gnunet-0.10.1/0000755000175000017500000000000012320755631010076 500000000000000gnunet-0.10.1/acinclude.m40000644000175000017500000000275711374167231012223 00000000000000# See: http://gcc.gnu.org/ml/gcc/2000-05/msg01141.html AC_DEFUN([CHECK_PTHREAD], [ AC_CHECK_LIB(pthread,pthread_create, [ PTHREAD_CPPFLAGS= PTHREAD_LDFLAGS= PTHREAD_LIBS=-lpthread ],[ AC_MSG_CHECKING(if compiler supports -pthread) save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -pthread" AC_TRY_LINK( [ #include ],[ pthread_create(0,0,0,0); ],[ AC_MSG_RESULT(yes) PTHREAD_CPPFLAGS=-pthread PTHREAD_LDFLAGS=-pthread PTHREAD_LIBS= ],[ AC_MSG_RESULT(no) AC_MSG_CHECKING(if compiler supports -pthreads) save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$save_CPPFLAGS -pthreads" AC_TRY_LINK( [ #include ],[ pthread_create(0,0,0,0); ],[ AC_MSG_RESULT(yes) PTHREAD_CPPFLAGS=-pthreads PTHREAD_LDFLAGS=-pthreads PTHREAD_LIBS= ],[ AC_MSG_RESULT(no) AC_MSG_CHECKING(if compiler supports -threads) save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$save_CPPFLAGS -threads" AC_TRY_LINK( [ #include ],[ pthread_create(0,0,0,0); ],[ AC_MSG_RESULT(yes) PTHREAD_CPPFLAGS=-threads PTHREAD_LDFLAGS=-threads PTHREAD_LIBS= ],[ AC_MSG_ERROR([Your system is not supporting pthreads!]) ]) ]) ]) CPPFLAGS="$save_CPPFLAGS" ]) ]) dnl Checks for all prerequisites of the intl subdirectory, dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. AC_DEFUN([AM_INTL_SUBDIR], [])gnunet-0.10.1/README0000644000175000017500000003103512307614644010703 00000000000000 Welcome to GNUnet What is GNUnet? =============== GNUnet is peer-to-peer framework focusing on security. The first and primary application for GNUnet is anonymous file-sharing. GNUnet is currently developed by a worldwide group of independent free software developers. GNUnet is a GNU package (http://www.gnu.org/). This is an ALPHA release. There are known and significant bugs as well as many missing features in this release. Additional documentation about GNUnet can be found at https://gnunet.org/. Dependencies: ============= Please note that for many of its dependencies GNUnet requires very recent versions of the libraries which are often NOT to be found in stable distributions in 2011. While using older packages may in some cases on some operating systems may seem to work in some limited fashion, we are in many cases aware of serious problems with older packages. Hence please make sure to use the versions listed below. These are the direct dependencies for running GNUnet: - libextractor >= 0.6.1 - libmicrohttpd >= 0.9.33 - libgcrypt >= 1.6 - libgnurl >= 7.35.0 (available from https://gnunet.org/gnurl) - libunistring >= 0.9.2 - gnutls >= 3.2.12 - libidn >= 1.0 - libglpk >= 4.45 - openssl >= 1.0 (binary, used to generate X.509 certificate) - libltdl >= 2.2 (part of GNU libtool) - sqlite >= 3.8 (default database, required) - mysql >= 5.1 (alternative to sqlite) - postgres >= 8.3 (alternative to sqlite) - libopus >= 1.0.1 (optional for experimental conversation tool) - libpulse >= 2.0 (optional for experimental conversation tool) - libogg >= 1.3.0 (optional for experimental conversation tool) - python-zbar >= 0.10 (optional for gnunet-qr) - TeX Live >= 2012 (optional for gnunet-bcd) Recommended autotools for compiling the SVN version are: - autoconf >= 2.59 - automake >= 1.11.1 - libtool >= 2.2 How to install? =============== The fastest way is to use a binary package if it is available for your system. For a more detailed description, read the installation instructions on the webpage at https://gnunet.org/installation. Note that some functions of GNUnet require "root" access. GNUnet will install (tiny) SUID binaries for those functions is you run "make install" as root. If you do not, GNUnet will still work, but some functionality will not be available (including certain forms of NAT traversal). GNUnet requires the GNU MP library (http://www.gnu.org/software/gmp/) and libgcrypt (http://www.gnupg.org/). You can specify the path to libgcrypt by passing "--with-gcrypt=PATH" to configure. You will also need either sqlite (http://www.sqlite.org/), MySQL (http://www.mysql.org/) or PostGres (http://www.postgres.org/). If you install from source, you need to install GNU libextractor first (download from http://www.gnu.org/software/libextractor/). We also recommend installing GNU libmicrohttpd (download from http://www.gnu.org/software/libmicrohttpd/). Then you can start the actual GNUnet compilation and installation process with: $ export GNUNET_PREFIX=/usr/local # or other directory of your choice # addgroup gnunetdns # adduser gnunet gnunet # ./configure --prefix=$GNUNET_PREFIX --with-extractor=$LE_PREFIX $ make # make install # sudo -u gnunet gnunet-arm -s Note that running the 'configure' and 'make install' steps as root (or with sudo) is required as some parts of the installation require the creation of SUID binaries. The installation will work if you do not run these steps as root, but some components may not be installed in the perfect place or with the right permissions and thus won't work. This will create the users and groups needed for running GNUnet securely and then compile and install GNUnet to $GNUNET_PREFIX/bin/, $GNUNET_PREFIX/lib/ and $GNUNET_PREFIX/share/ and start the system with the default configuration. It is strongly recommended that you add a user "gnunet" to run "gnunet-arm". You can then still run the end-user applications as another user. If you create a system user "gnunet", it is recommended that you edit the configuration file slightly so that data can be stored in the system user home directory at "/var/lib/gnunet". Depending on what the $HOME-directory of your "gnunet" user is, you might need to set the SERVICEHOME option in section "[PATHS]" to "/var/lib/gnunet" to do this. Depending on your personal preferences, you may also want to use "/etc/gnunet.conf" for the location of the configuration file in this case (instead of ~gnunet/.config/gnunet.conf"). In this case, you need to start GNUnet using "gnunet-arm -s -c /etc/gnunet.conf" or set "XDG_CONFIG_HOME=/etc/". You can avoid running 'make install' as root if you run configure with the "--with-sudo=yes" option and have extensive sudo rights (can run "chmod +s" and "chown" via 'sudo'). If you run 'make install' as a normal user without sudo rights (or the configure option), certain binaries that require additional priviledges will not be installed properly (and autonomous NAT traversal, WLAN, DNS/GNS and the VPN will then not work). If you run 'configure' and 'make install' as root or use the SUDO option, GNUnet's build system will install "libnss_gns*" libraries to "/lib/" regardless (!) of the $GNUNET_PREFIX you might have specified, as those libraries must be in "/lib/". If you are packaging GNUnet for binary distribution, this may cause your packaging script to miss those plugins, so you might need to do some additional manual work to include those libraries in your binary package(s). Similarly, if you want to use the GNUnet naming system and did NOT run GNUnet's 'make install' process with SUDO rights, the libraries will be installed to "$GNUNET_PREFIX/lib" and you will have to move them to "/lib/" manually. Finally, if you are compiling the code from subversion, you have to run ". bootstrap" before ./configure. If you receive an error during the running of ". bootstrap" that looks like "macro `AM_PATH_GTK' not found in library", you may need to run aclocal by hand with the -I option, pointing to your aclocal m4 macros, i.e. $ aclocal -I /usr/local/share/aclocal Configuration ============= Note that additional, per-user configuration files can be created by each user. However, this is usually not necessary as there are few per-user options that normal users would want to modify. The defaults that are shipped with the installation are usually just fine. The gnunet-setup tool is particularly useful to generate the master configuration for the peer. gnunet-setup can be used to configure and test (!) the network settings, choose which applications should be run and configure databases. Other options you might want to control include system limitations (such as disk space consumption, bandwidth, etc.). The resulting configuration files are human-readable and can theoretically be created or edited by hand. gnunet-setup is a separate download and requires somewhat recent versions of GTK+ and Glade. You can also create the configuration file by hand, but this is not recommended. For more general information about the GNU build process read the INSTALL file. GNUnet uses two types of configuration files, one that specifies the system-wide defaults (typically located in $GNUNET_PREFIX/share/gnunet/config.d/) and a second one that overrides default values with user-specific preferences. The user-specific configuration file should be located in "~/.config/gnunet.conf" or its location can be specified by giving the "-c" option to the respective GNUnet application. Usage ===== First, you must obtain an initial list of GNUnet hosts. Knowing a single peer is sufficient since after that GNUnet propagates information about other peers. Note that the default configuration contains URLs from where GNUnet downloads an initial hostlist whenever it is started. If you want to create an alternative URL for others to use, the file can be generated on any machine running GNUnet by periodically executing $ cat $SERVICEHOME/data/hosts/* > the_file and offering 'the_file' via your web server. Alternatively, you can run the build-in web server by adding '-p' to the OPTIONS value in the "hostlist" section of gnunet.conf and opening the respective HTTPPORT to the public. If the solution with the hostlist URL is not feasible for your situation, you can also add hosts manually. Simply copy the hostkeys to "$SERVICEHOME/data/hosts/" (where $SERVICEHOME is the directory specified in the gnunet.conf configuration file). You can also use "gnunet-peerinfo -g" to GET a URI for a peer and "gnunet-peerinfo -p URI" to add a URI from another peer. Finally, GNUnet peers that use UDP or WLAN will discover each other automatically (if they are in the vicinity of each other) using broadcasts (IPv4/WLAN) or multicasts (IPv6). The local node is started using "gnunet-arm -s". GNUnet should run 24/7 if you want to maximize your anonymity, as this makes partitioning attacks harder. Once your peer is running, you should then be able to access GNUnet using the shell: $ gnunet-search KEYWORD This will display a list of results to the console. You can abort the command using "CTRL-C". Then use $ gnunet-download -o FILENAME GNUNET_URI to retrieve a file. The GNUNET_URI is printed by gnunet-search together with a description. To publish files on GNUnet, use the "gnunet-publish" command. The GTK user interface is shipped separately. After downloading and installing gnunet-gtk, you can invoke the setup tool and the file-sharing GUI with: $ gnunet-setup $ gnunet-fs-gtk For further documentation, see our webpage. Hacking GNUnet ============== Contributions are welcome, please submit bugs to https://gnunet.org/bugs/. Please make sure to run contrib/report.sh and include the output with your bug reports. More about how to report bugs can be found in the GNUnet FAQ on the webpage. Submit patches via E-Mail to gnunet-developers@gnu.org. In order to run the unit tests with "make check", you need to set an environment variable ("GNUNET_PREFIX") to the directory where GNUnet is installed (usually, GNUnet will use OS specific tricks in order to try to figure out the PREFIX, but since the testcase binaries are not installed, that trick does not work for them). Also, before running any testcases, you must complete the installation first. Quick summary: $ ./configure --prefix=$SOMEWHERE $ make $ make install $ export GNUNET_PREFIX=$SOMEWHERE $ make check Some of the testcases require python >= 2.6 and pexpect to be installed. If any testcases fail to pass on your system, run "contrib/report.sh" and report the output together with information about the failing testcase to the Mantis bugtracking system at https://gnunet.org/bugs/. Running HTTP on port 80 and HTTPS on port 443 ============================================= In order to hide GNUnet's HTTP/HTTPS traffic perfectly, you might consider running GNUnet's HTTP/HTTPS transport on port 80/443. However, we do not recommend running GNUnet as root. Instead, forward port 80 to say 1080 with this command (as root, in your startup scripts): # iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 1080 or for HTTPS # iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 4433 Then set in the HTTP section of gnunet.conf the "ADVERTISED_PORT" to "80" and "PORT" to 1080 and similarly in the HTTPS section the "ADVERTISED_PORT" to "443" and "PORT" to 4433. You can do the same trick for the TCP and UDP transports if you want to map them to a priviledged port (from the point of view of the network). However, we are not aware of this providing any advantages at this point. If you are already running an HTTP or HTTPS server on port 80 (or 443), you may be able to configure it as a "ReverseProxy". Here, you tell GNUnet that the externally visible URI is some sub-page on your website, and GNUnet can then tunnel its traffic via your existing HTTP server. This is particularly powerful if your existing server uses HTTPS, as it makes it harder for an adversary to distinguish normal traffic to your server from GNUnet traffic. Finally, even if you just use HTTP, you might benefit (!) from ISP's traffic shaping as opposed to being throttled by ISPs that dislike P2P. Details for configuring the reverse proxy are documented on our website. Stay tuned ========== * https://gnunet.org/ * https://gnunet.org/bugs/ * https://gnunet.org/svn/ * http://www.gnu.org/software/gnunet/ * http://mail.gnu.org/mailman/listinfo/gnunet-developers * http://mail.gnu.org/mailman/listinfo/help-gnunet * http://mail.gnu.org/mailman/listinfo/info-gnunet * http://mail.gnu.org/mailman/listinfo/gnunet-svn gnunet-0.10.1/contrib/0000755000175000017500000000000012320755622011536 500000000000000gnunet-0.10.1/contrib/coverage.sh0000755000175000017500000000057212026026626013612 00000000000000#!/bin/sh # make sure configure was run with coverage enabled... lcov --directory . --zerocounters make check rm `find * -name "test_*.gc??"` `find * -name "perf_*.gc??"` for n in `find * -name "*.gc??" | grep libs` do cd `dirname $n` mv `basename $n` .. cd - done lcov --directory . --capture --output-file app.info mkdir -p doc/coverage genhtml -o doc/coverage app.info gnunet-0.10.1/contrib/gns-bcd.tex0000644000175000017500000221146312255042435013524 00000000000000\documentclass[14pt,a4paper,oneside,ngerman]{scrartcl} \usepackage{geometry} %\geometry{paperwidth=95mm, paperheight=65mm,left=0mm,right=0mm, top=0mm, bottom=0mm} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{graphicx} \usepackage{units} \usepackage{tikz} \usepackage{url} \usepackage[newdimens]{labels} \usepackage{pspicture} \usepackage{pst-barcode} \usepackage{auto-pst-pdf} \usetikzlibrary{positioning,shapes,shadows,arrows} \LabelCols=2% \LabelRows=5% \LeftPageMargin=17.0mm% \RightPageMargin=17.0mm% \TopPageMargin=10.0mm% \BottomPageMargin=10.0mm% \InterLabelColumn=3.5mm% \InterLabelRow=3.0mm% \LeftLabelBorder=2mm% \RightLabelBorder=2mm% \TopLabelBorder=2mm% \BottomLabelBorder=2mm% \numberoflabels=10% \LabelGridfalse% <-- or \LabelGridfalse \renewcommand{\rmdefault}{phv} \renewcommand{\seriesdefault}{m} \renewcommand{\shapedefault}{n} \definecolor{MyBlack}{cmyk}{0,0,0,1} \input{def.tex} \setlength\parindent{0pt} \newlength{\width} \newlength{\height} \setlength{\width}{85mm} \setlength{\height}{50mm} \newcommand{\logo}{ %LaTeX with PSTricks extensions %%Creator: inkscape 0.48.4 %%Please note this file requires PSTricks extensions \psset{xunit=.1pt,yunit=.1pt,runit=.1pt} \begin{pspicture}(744.09448242,1052.36218262) { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.57414055,linecolor=curcolor] { \newpath \moveto(-381.25674,1179.80841262) \lineto(-381.25674,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-282.64454,1133.40272062) \lineto(-381.25674,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-242.03964,1034.79060862) \lineto(-381.25674,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-281.67794,935.21172262) \lineto(-381.25674,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-382.22354,1034.79060862) \lineto(-521.44064,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-479.86894,936.17850262) \lineto(-381.25674,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-479.86894,1134.36951062) \lineto(-381.25674,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.25674,1034.79060862) \lineto(-381.25674,888.80601262) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.57414055,linecolor=curcolor] { \newpath \moveto(-381.35404,1179.66521262) \curveto(-352.25324,1156.60557262)(-317.44894,1142.47793062)(-282.64454,1133.40272062) \curveto(-273.72464,1095.34014862)(-259.44184,1067.08441862)(-242.03964,1034.79060862) \curveto(-265.24254,1003.07363862)(-276.84404,970.98276862)(-282.64454,936.17850262) \curveto(-323.24954,930.37778262)(-352.25324,912.97565262)(-381.25674,889.77279262) \curveto(-410.26034,918.77635262)(-433.46314,930.37778262)(-479.86894,936.17850262) \curveto(-482.44324,970.98276862)(-494.24764,1002.49677862)(-520.47384,1034.79060862) \curveto(-494.96354,1078.62190862)(-488.55394,1089.91334862)(-479.86894,1133.40272062) \curveto(-439.26394,1147.09291062)(-410.26034,1156.60557262)(-381.35404,1179.66521262) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.29664,1144.91591062) \curveto(-358.05394,1127.60200862)(-332.72784,1116.00057862)(-305.84754,1110.19985862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.00044,1112.41446862) \curveto(-363.85464,1098.59843862)(-346.45254,1090.27762862)(-329.05034,1086.99701862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-352.25324,1063.79416862) \lineto(-381.25674,1081.19630862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.25674,1144.91591062) \curveto(-404.45964,1127.60200862)(-430.40244,1118.91690862)(-456.70584,1110.19985862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.55294,1112.41446862) \curveto(-395.40834,1101.05761862)(-413.30194,1092.79772862)(-433.50304,1086.99701862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-410.42664,1063.77335862) \lineto(-381.29664,1081.19630862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.25674,924.57707262) \curveto(-358.05394,945.40846262)(-332.71464,956.43303862)(-305.84754,959.38134862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.25674,959.38134862) \curveto(-363.85464,973.46123862)(-352.25324,980.27668862)(-329.05034,982.58418862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-352.25324,1005.78704862) \lineto(-381.25674,988.38490862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.25674,924.57707262) \curveto(-410.26034,950.02348262)(-419.41524,953.58061862)(-456.66604,959.38134862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-381.25674,959.38134862) \curveto(-395.77454,976.78347862)(-413.75354,982.58418862)(-433.46314,982.58418862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-410.26034,1005.78704862) \lineto(-381.25674,988.38490862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-456.66604,959.38134862) \curveto(-462.46674,990.86337862)(-471.79264,1011.58774862)(-491.47034,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-433.46314,982.58418862) \curveto(-436.00564,1003.44757862)(-445.06464,1017.38846862)(-456.66604,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-427.66244,1034.79060862) \lineto(-410.26034,1005.78704862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-305.84754,959.38134862) \curveto(-300.04684,988.38490862)(-288.44534,1011.58774862)(-271.04324,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-329.05034,982.58418862) \curveto(-323.24954,1005.78704862)(-317.44894,1017.38846862)(-305.84754,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-334.85114,1034.79060862) \curveto(-342.95924,1026.27648862)(-348.76004,1017.38846862)(-352.25324,1005.78704862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-305.84754,1110.19985862) \curveto(-296.72764,1075.39557862)(-286.23964,1057.99345812)(-271.04324,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-329.05034,1086.99701862) \curveto(-325.35424,1067.28736862)(-317.44894,1052.19274815)(-305.84754,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-334.85114,1034.79060862) \lineto(-352.25324,1063.79416862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-456.66604,1110.19985862) \curveto(-462.46674,1083.90969862)(-474.06814,1057.99345812)(-491.47034,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-433.46314,1086.99701862) \curveto(-439.26394,1069.59487862)(-445.06464,1052.19274815)(-456.66604,1034.79060862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=6.66012001,linecolor=curcolor] { \newpath \moveto(-427.66244,1034.79060862) \lineto(-410.26034,1063.79416862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.86714172,linecolor=curcolor] { \newpath \moveto(-384.86194,1180.91840262) \lineto(-384.86194,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-286.24984,1134.51270062) \lineto(-384.86194,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-245.64484,1035.90058862) \lineto(-384.86194,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-285.28304,936.32170262) \lineto(-384.86194,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-385.82874,1035.90058862) \lineto(-525.04584,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-483.47404,937.28848262) \lineto(-384.86194,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-483.47404,1135.47950062) \lineto(-384.86194,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-384.86194,1035.90058862) \lineto(-384.86194,889.91599262) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.86714172,linecolor=curcolor] { \newpath \moveto(-384.95924,1180.77520262) \curveto(-355.85834,1157.71555262)(-321.05404,1143.58791062)(-286.24984,1134.51270062) \curveto(-277.32984,1096.45013862)(-263.04704,1068.19441862)(-245.64484,1035.90058862) \curveto(-268.84764,1004.18361862)(-280.44904,972.09274862)(-286.24984,937.28848262) \curveto(-326.85484,931.48776262)(-355.85834,914.08563262)(-384.86194,890.88278262) \curveto(-413.86544,919.88634262)(-437.06834,931.48776262)(-483.47404,937.28848262) \curveto(-486.04844,972.09274862)(-497.85284,1003.60676862)(-524.07904,1035.90058862) \curveto(-498.56864,1079.73189862)(-492.15914,1091.02332862)(-483.47404,1134.51270062) \curveto(-442.86904,1148.20291062)(-413.86544,1157.71555262)(-384.95924,1180.77520262) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-384.90174,1146.02590062) \curveto(-361.65904,1128.71199062)(-336.33294,1117.11056862)(-309.45264,1111.30984862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-384.60564,1113.52444862) \curveto(-367.45974,1099.70842862)(-350.05764,1091.38760862)(-332.65554,1088.10700862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-355.85834,1064.90414862) \lineto(-384.86194,1082.30629862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-384.86194,1146.02590062) \curveto(-408.06474,1128.71199062)(-434.00754,1120.02688862)(-460.31104,1111.30984862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-385.15804,1113.52444862) \curveto(-399.01354,1102.16759862)(-416.90704,1093.90770862)(-437.10814,1088.10700862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-414.03174,1064.88334862) \lineto(-384.90174,1082.30629862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-384.86194,925.68706262) \curveto(-361.65904,946.51845262)(-336.31974,957.54301862)(-309.45264,960.49133862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-384.86194,960.49133862) \curveto(-367.45974,974.57122862)(-355.85834,981.38668862)(-332.65554,983.69417862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-355.85834,1006.89702862) \lineto(-384.86194,989.49489862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-384.86194,925.68706262) \curveto(-413.86544,951.13347262)(-423.02044,954.69060862)(-460.27114,960.49133862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-384.86194,960.49133862) \curveto(-399.37974,977.89345862)(-417.35874,983.69417862)(-437.06834,983.69417862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-413.86544,1006.89702862) \lineto(-384.86194,989.49489862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-460.27114,960.49133862) \curveto(-466.07194,991.97335862)(-475.39784,1012.69773862)(-495.07544,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-437.06834,983.69417862) \curveto(-439.61074,1004.55755862)(-448.66974,1018.49844862)(-460.27114,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-431.26764,1035.90058862) \lineto(-413.86544,1006.89702862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-309.45264,960.49133862) \curveto(-303.65194,989.49489862)(-292.05064,1012.69773862)(-274.64834,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-332.65554,983.69417862) \curveto(-326.85484,1006.89702862)(-321.05404,1018.49844862)(-309.45264,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-338.45624,1035.90058862) \curveto(-346.56444,1027.38647862)(-352.36514,1018.49844862)(-355.85834,1006.89702862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-309.45264,1111.30984862) \curveto(-300.33274,1076.50557862)(-289.84464,1059.10344812)(-274.64834,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-332.65554,1088.10700862) \curveto(-328.95944,1068.39735862)(-321.05404,1053.30273815)(-309.45264,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-338.45624,1035.90058862) \lineto(-355.85834,1064.90414862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-460.27114,1111.30984862) \curveto(-466.07194,1085.01967862)(-477.67334,1059.10344812)(-495.07544,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-437.06834,1088.10700862) \curveto(-442.86904,1070.70485862)(-448.66974,1053.30273815)(-460.27114,1035.90058862) } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=3.91771698,linecolor=curcolor] { \newpath \moveto(-431.26764,1035.90058862) \lineto(-413.86544,1064.90414862) } } { \newrgbcolor{curcolor}{1 1 1} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-393.8088526,985.67869244) \curveto(-393.8088526,985.67869244)(-393.44546987,985.76087805)(-393.67396775,984.76553303) \curveto(-394.05309973,983.16620422)(-395.79555868,982.55700599)(-396.87725482,981.47163855) \curveto(-398.351462,980.48101881)(-398.6104145,978.72434872)(-397.21444931,977.75378495) \curveto(-398.7210224,978.22655517)(-400.8061979,979.66881501)(-399.57477539,981.47163855) \curveto(-398.22764147,983.19752119)(-395.09015533,983.91500755)(-395.42734981,986.59184681) \curveto(-396.37998575,989.53091147)(-400.50677037,988.15464924)(-401.53047213,991.51637193) \curveto(-402.56322605,991.80858295)(-404.01218802,991.93029551)(-404.1942803,993.24484667) \curveto(-404.2680542,994.15904494)(-403.90643652,994.92636108)(-403.48616886,995.69080272) \curveto(-398.64953801,998.87380689)(-404.01974746,1002.29292386)(-407.26268253,1003.58308712) \curveto(-407.6434434,1004.01109576)(-407.57924109,1004.56329308)(-407.56616462,1005.11588376) \curveto(-408.00450635,1007.01133693)(-404.29139316,1007.79143201)(-405.57675045,1009.38815359) \curveto(-406.80790064,1008.0810358)(-410.1193649,1006.25080865)(-409.48814897,1004.0396643) \curveto(-407.40162194,1002.49382145)(-405.04265242,1000.92449843)(-403.28385923,999.1477522) \lineto(-409.69046364,1003.71353414) \curveto(-410.77513515,1005.27372934)(-409.16701137,1006.53519295)(-408.13939121,1007.56183981) \lineto(-410.49971225,1006.84435849) \curveto(-407.00643307,1008.34976665)(-409.81008841,1010.72005768)(-412.38797917,1010.88834226) \curveto(-412.80366779,1011.24238537)(-412.67526822,1011.80423497)(-412.69143605,1012.29068683) \curveto(-409.99391548,1014.99232752)(-415.61149367,1012.6301204)(-416.43423228,1014.93232098) \curveto(-417.47225612,1016.45207141)(-415.71318557,1017.56090388)(-415.25407176,1018.81323463) \curveto(-417.95564689,1019.93198161)(-420.70037488,1022.59761535)(-417.68185288,1025.20533035) \curveto(-418.15605531,1027.3773411)(-420.21344898,1029.4084608)(-418.52481891,1031.69526513) \curveto(-421.06182111,1028.99623671)(-425.19981125,1029.49195254)(-427.89868334,1027.12948319) \lineto(-428.60678973,1025.9880377) \curveto(-430.35882532,1015.89113459)(-427.87009967,1005.36374167)(-421.99787569,997.02792631) \curveto(-420.19863268,993.38312546)(-414.14674714,991.72770347)(-414.61342039,987.40716718) \curveto(-414.92741712,987.05834356)(-415.26582697,986.71107823)(-415.79358091,986.85275094) \lineto(-414.81573507,987.7332923) \curveto(-414.61747496,988.13873357)(-414.65306838,988.74155242)(-414.95061992,989.1030289) \lineto(-415.79358091,990.37492645) \lineto(-416.56911713,990.92934268) \curveto(-418.00420584,992.20919807)(-414.66333087,988.06985641)(-416.87259923,988.4181606) \lineto(-416.46797492,989.07041588) \lineto(-416.73771942,990.11402232) \lineto(-417.91787994,991.71205003) \curveto(-427.39964418,1000.49661586)(-431.11951497,1013.52344574)(-429.31487092,1025.95542469) \curveto(-430.26656382,1025.78766458)(-430.67306411,1026.6697743)(-431.27056765,1027.12948319) \curveto(-433.23975943,1025.53406774)(-435.53400217,1022.53369545)(-438.28411104,1023.99865883) \curveto(-439.63960119,1023.1836007)(-442.18606908,1022.46716833)(-442.90361595,1024.422623) \curveto(-443.13707613,1028.72489863)(-436.22321249,1029.80764371)(-437.64345968,1034.33689928) \lineto(-437.20511794,1035.47834477) \curveto(-434.73956987,1036.86112254)(-433.95056887,1039.41013713)(-434.44014234,1042.00089256) \curveto(-445.86414358,1042.63579491)(-455.00871283,1052.19172136)(-458.69081416,1062.12947276) \curveto(-462.89758161,1077.75750209)(-454.49077809,1096.84247586)(-437.65018702,1101.26475952) \curveto(-434.47523651,1102.26179898)(-431.11143106,1103.2958893)(-427.66938867,1102.96063132) \curveto(-423.73641624,1102.81452582)(-419.63754961,1103.1857857)(-416.03637062,1101.94963286) \lineto(-407.87637911,1097.84042306) \curveto(-405.93417237,1096.63832049)(-403.38097209,1097.3364922)(-401.40234992,1097.84042306) \lineto(-401.36863249,1097.22078079) \curveto(-402.69700649,1094.04430225)(-406.3684545,1093.01634926)(-409.46116393,1092.39409976) \lineto(-415.395689,1092.52454679) \curveto(-417.50111211,1093.08431363)(-419.64698505,1092.9453843)(-421.86974845,1092.91590298) \curveto(-423.64200642,1092.95400277)(-425.35627001,1092.80106401)(-426.99501987,1092.39409976) \curveto(-440.79280693,1091.49633156)(-449.54624238,1070.12611679)(-436.84093842,1062.39037689) \curveto(-434.47655777,1062.09882147)(-432.65304285,1063.55960925)(-430.7378161,1064.57543385) \curveto(-428.61622517,1065.94647155)(-426.68075082,1067.60841412)(-424.87072589,1069.46734092) \lineto(-420.82444252,1074.03312286) \curveto(-419.87034916,1075.3793793)(-418.9038097,1076.75693758)(-417.58744306,1077.8162025) \curveto(-410.65617101,1087.7526528)(-394.60461121,1089.62853918)(-386.63344436,1080.29477157) \lineto(-383.59875453,1081.99063329) \curveto(-372.52814586,1090.46212021)(-359.1997351,1078.86111507)(-353.18426499,1069.59779298) \lineto(-349.94726048,1066.07561748) \curveto(-348.69964493,1065.25455819)(-347.29965039,1064.60673569)(-345.79980969,1064.47758976) \curveto(-344.71866828,1064.18381542)(-343.50962151,1064.38074418)(-342.46163776,1064.64065484) \curveto(-334.57411899,1069.13860353)(-335.48586637,1080.22954553)(-339.35949289,1087.01299746) \curveto(-342.82716881,1091.17438203)(-348.54183464,1092.71761766)(-353.76424414,1092.13319563) \lineto(-359.83365407,1092.52454679) \curveto(-361.76774664,1093.03826609)(-363.67221164,1094.10300266)(-364.79032825,1095.81843622) \curveto(-364.92923741,1096.64823501)(-365.47603369,1097.52734416)(-365.0600677,1098.36222628) \curveto(-361.7825932,1096.74594294)(-357.75521096,1096.52287132)(-354.47232533,1098.42745231) \curveto(-344.68304964,1105.30613606)(-328.58968849,1104.10729126)(-323.31604222,1092.36148675) \curveto(-320.72777803,1086.5590275)(-319.80792152,1079.96472804)(-320.58480926,1073.47218604) \curveto(-319.76206562,1060.58493604)(-330.83264907,1047.51244693)(-344.7005942,1048.25601564) \lineto(-341.46356448,1042.19004503) \curveto(-340.7944404,1040.95597999)(-338.70535153,1037.47815758)(-337.82191046,1040.29851025) \curveto(-337.68501345,1040.42604747)(-337.50132254,1040.71294821)(-337.34985634,1040.42895728) \curveto(-336.79768423,1039.02921993)(-337.72211977,1037.58904284)(-338.69861914,1036.58065665) \curveto(-346.41485779,1034.94349533)(-356.42129471,1036.39802477)(-361.02054698,1043.16843047) \lineto(-360.88566213,1034.49343873) \curveto(-358.52804413,1030.8368978)(-354.6948876,1035.98449454)(-352.32107657,1033.38460626) \curveto(-350.97231376,1030.58903989)(-349.90273088,1027.59389214)(-350.97231376,1024.44871543) \lineto(-357.37889296,1017.60004252) \curveto(-357.86647949,1015.4345574)(-353.69949215,1014.93884157)(-353.77097653,1012.6755174) \curveto(-355.36790488,1010.67179123)(-357.7133844,1009.19508776)(-359.94155388,1008.07712244) \curveto(-357.89953124,1006.06556955)(-358.11533591,1002.36075711)(-360.27872315,1000.44574218) \lineto(-361.59376852,1000.02177801) \curveto(-365.2259619,1001.37976948)(-371.67439287,997.479284)(-368.2364,993.59706422) \lineto(-367.79806331,992.32516667) \curveto(-367.81138688,991.52733035)(-367.68635099,990.7023577)(-368.10151514,990.00966268) \curveto(-368.75405788,988.07768313)(-370.44970275,986.86187875)(-372.14779851,985.83523189) \curveto(-377.09909183,983.99065744)(-379.81142365,978.3134358)(-377.07075526,973.70328059) \lineto(-375.78945254,973.6380596) \curveto(-379.00622961,972.50171258)(-374.37728926,971.86001227)(-373.09193197,972.00741887) \curveto(-374.83047252,971.19786769)(-377.84091061,971.34083645)(-377.94746395,973.76853184) \curveto(-381.85074829,976.7910832)(-379.88440076,974.72472309)(-378.99273961,974.05551832) \lineto(-378.75671255,973.30541894) \curveto(-379.26841466,973.46769731)(-379.89033132,973.73514725)(-380.5865766,974.08488365) \curveto(-381.28279163,974.43462005)(-383.24157972,977.3525344)(-384.05050053,977.84397378) \curveto(-384.85944656,978.33541315)(-385.09533746,979.02980262)(-384.74023532,980.94777275) \curveto(-385.08510019,977.15423899)(-385.08510019,976.80937412)(-385.24258268,976.11963934) \curveto(-385.47358692,975.10792981)(-387.49916941,978.87857344)(-387.67601699,979.91317309) \curveto(-387.83804826,980.86105854)(-388.84944512,983.10603126)(-389.39063863,983.70670685) \curveto(-389.93185736,984.30738747)(-392.32730283,988.87971017)(-393.85801671,988.034147) \curveto(-393.85014965,987.15537573)(-393.8326303,985.29793661)(-393.8088526,985.67869244) \closepath } } { \newrgbcolor{curcolor}{0.10980392 0.10980392 0.10980392} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-361.9777559,1018.19375575) \lineto(-361.84288013,1018.32420681) \curveto(-361.58863929,1018.30596975)(-361.86172227,1018.57010705)(-361.84288013,1018.32420681) \lineto(-361.9777559,1018.19375575) \lineto(-364.37180093,1016.40005372) \lineto(-364.50667671,1016.59573031) \curveto(-363.07429596,1017.97851151)(-361.21570777,1019.72003311)(-359.4488351,1020.24835989) \lineto(-360.25808976,1019.13952591) \curveto(-358.37387517,1020.54839732)(-356.31971709,1021.76420117)(-354.25611772,1022.85738103) \curveto(-352.45282859,1022.85238867)(-351.09597828,1024.85458671)(-351.05281804,1026.54262338) \curveto(-351.49075968,1028.70680641)(-351.71708123,1030.90360221)(-352.70504629,1032.9021124) \curveto(-354.65804753,1035.11586683)(-357.32454163,1031.36278993)(-359.65114877,1032.96733792) \lineto(-361.67428541,1034.53275061) \curveto(-364.13576832,1040.19693549)(-367.29995403,1045.71110166)(-371.25046551,1050.57823058) \lineto(-372.36319067,1052.76328578) \curveto(-372.79492803,1056.24371998)(-372.12850682,1060.24074035)(-369.49708042,1062.90585544) \curveto(-368.82067841,1063.28155449)(-368.09167484,1063.68595276)(-367.27163012,1063.55811073) \lineto(-368.72154471,1062.80801715) \lineto(-367.87857111,1061.2099917) \lineto(-371.25046551,1056.05717496) \curveto(-370.1709198,1057.71259887)(-366.82384254,1058.94014332)(-365.51824503,1057.16600895) \curveto(-365.42124237,1056.9139775)(-365.44600556,1056.33203534)(-365.85543447,1056.44852813) \lineto(-366.19262391,1057.29646) \curveto(-368.99534254,1058.28893164)(-372.2471975,1055.32534454)(-371.65509284,1052.66544749) \curveto(-369.80864347,1053.14955136)(-367.29590776,1054.4447999)(-365.1136177,1053.51337936) \lineto(-364.03461149,1053.05680066) \curveto(-363.62796103,1053.43054294)(-363.3936818,1055.35926181)(-364.23692515,1054.7526644) \lineto(-364.37180093,1054.94834098) \curveto(-362.76947671,1056.51505817)(-362.74519907,1059.00406434)(-363.62998416,1060.94908959) \lineto(-368.68782577,1066.81938714) \lineto(-365.6531208,1064.60171918) \curveto(-364.4621677,1063.36373865)(-363.35483758,1062.05531455)(-362.75329162,1060.49251089) \curveto(-362.21972305,1058.90361702)(-362.11735233,1056.77074224)(-363.19163789,1055.37230692) \curveto(-363.07140962,1054.55503105)(-363.09922101,1053.67513867)(-363.46138944,1052.89373684) \curveto(-361.87120404,1053.0868044)(-360.99855777,1050.03164065)(-363.02304317,1050.18687741) \lineto(-363.22535683,1050.90435822) \lineto(-363.83229783,1051.36093692) \lineto(-364.50667671,1051.42616245) \curveto(-363.38963553,1049.37677635)(-365.72352596,1047.03909341)(-367.91229005,1047.93659668) \lineto(-368.04716583,1047.54524351) \curveto(-367.03883453,1046.36661822)(-364.12228074,1046.09854129)(-363.4276705,1048.03443498) \curveto(-362.65833907,1047.95705141)(-363.62661227,1047.10170992)(-363.83229783,1046.79514994) \lineto(-361.7417233,1048.29533709) \lineto(-361.87659907,1047.31695416) \curveto(-364.30840932,1046.15306984)(-361.89304043,1043.43342621)(-361.60684752,1041.70755872) \lineto(-361.57312858,1043.50126075) \curveto(-361.66319862,1043.89391844)(-361.53649631,1045.28974474)(-361.06734441,1044.51225644) \curveto(-358.6314879,1039.07636091)(-351.65841027,1036.57430964)(-346.09613326,1037.98970361) \lineto(-347.95067518,1036.97870792) \lineto(-348.18670779,1036.88086963) \curveto(-346.52099196,1036.11133884)(-344.55045687,1036.90660762)(-342.82539569,1036.97870792) \curveto(-341.77269026,1036.00554304)(-339.20667862,1036.62609871)(-338.27333825,1038.05492914) \lineto(-339.82440967,1038.44628231) \lineto(-340.7685401,1039.3594397) \lineto(-352.97479785,1060.94908959) \curveto(-355.08290623,1063.31286274)(-357.69814753,1065.02698962)(-360.52784131,1066.42803397) \lineto(-361.67428541,1066.36280845) \lineto(-362.92188634,1067.24335308) \lineto(-364.8101472,1066.85199991) \lineto(-365.21477453,1067.7651573) \curveto(-365.69385329,1067.30205605)(-366.04331642,1066.51961062)(-366.83328385,1066.46064674) \lineto(-366.32749968,1067.8629956) \lineto(-367.40650589,1067.08028926) \curveto(-367.67989909,1067.40798231)(-367.85388884,1067.73971935)(-367.67625745,1068.12389771) \curveto(-370.19438819,1068.83629093)(-373.43140681,1068.00341311)(-375.22930091,1065.84100422) \lineto(-375.97111768,1065.51487658) \curveto(-375.09429026,1064.39612831)(-374.37823476,1062.55233308)(-375.49905246,1061.27521723) \curveto(-376.21537771,1060.08485134)(-377.60716084,1059.7893797)(-378.9721037,1059.9380939) \curveto(-379.23929261,1060.08172052)(-380.10762286,1060.09593968)(-379.61276364,1060.55773642) \curveto(-379.25035242,1060.53125486)(-379.10657485,1060.67362914)(-378.93838475,1060.94908959) \curveto(-376.62391644,1061.22708079)(-377.70413653,1064.54171169)(-378.33144376,1065.90622975) \curveto(-380.65939966,1066.86647998)(-382.41278475,1069.2209911)(-382.47887388,1071.67868901) \lineto(-383.1869717,1072.82013575) \curveto(-383.23262715,1070.83075714)(-382.65947254,1068.49959675)(-381.29871084,1066.81938714) \curveto(-380.26057199,1065.87100796)(-378.09541115,1064.33559902)(-379.14069842,1062.71017886) \lineto(-380.08482885,1064.99307235) \curveto(-383.62801549,1065.23205869)(-386.16368008,1068.33001038)(-386.42399033,1071.64607624) \curveto(-387.01137434,1070.22024619)(-386.35358518,1068.28565702)(-385.41242201,1067.01506373) \curveto(-384.12300959,1065.25788799)(-380.9709627,1065.41442926)(-379.68020152,1063.4928852) \lineto(-380.05110991,1063.32982138) \curveto(-381.59813506,1064.51588238)(-383.44863071,1065.22657974)(-385.27754623,1065.84100422) \curveto(-386.38393223,1067.24465759)(-387.12264685,1068.83616048)(-387.23324499,1070.60246779) \curveto(-387.74752632,1070.26316459)(-388.34246337,1070.19637365)(-388.91919219,1070.34156568) \curveto(-389.40609374,1069.94903845)(-390.43114964,1069.33683164)(-390.80745306,1070.08066356) \lineto(-394.38166112,1068.05867218) \lineto(-395.73041888,1067.01506373) \lineto(-395.86529466,1067.8629956) \curveto(-396.62235239,1067.78699481)(-397.08753894,1068.3259664)(-397.48380397,1068.77615299) \lineto(-398.12446391,1067.50425519) \lineto(-399.37206484,1068.38479982) \curveto(-400.15043295,1068.05084512)(-400.43124431,1068.39384921)(-400.1813195,1069.16750616) \lineto(-401.8672667,1068.3195743) \curveto(-401.31292726,1069.42697332)(-401.75666856,1070.23459581)(-402.4067698,1071.12427202) \lineto(-402.81139713,1069.62408486) \curveto(-402.33096962,1069.65020116)(-401.80050319,1069.57718771)(-402.06958036,1068.97182958) \lineto(-402.47420769,1068.58047641) \curveto(-403.15667912,1068.82546349)(-403.76807101,1068.71718912)(-404.09271701,1067.92822113) \curveto(-405.16349579,1067.68036412)(-405.27517294,1068.04826219)(-405.0031285,1068.80876576) \curveto(-405.34800585,1068.58321588)(-405.78958915,1067.96526923)(-406.0821347,1068.54786365) \curveto(-406.52102048,1068.24469539)(-407.25258669,1068.05697632)(-407.66692507,1068.38479982) \lineto(-409.48774805,1066.75416162) \curveto(-415.33326419,1065.76064637)(-422.31443436,1063.97685862)(-426.21234429,1058.6661961) \lineto(-427.49366417,1057.55736212) \curveto(-428.72966578,1055.03052515)(-429.44666541,1052.2597447)(-431.2701859,1049.99120083) \lineto(-433.22588465,1041.1857545) \curveto(-434.11296263,1041.11902878)(-432.92214441,1042.97945653)(-434.00142037,1042.32720124) \curveto(-433.87730768,1040.00647695)(-433.43305385,1036.9265275)(-436.12571384,1035.77203564) \lineto(-436.9349685,1034.85887825) \lineto(-437.10356322,1033.58698044) \curveto(-436.18006878,1030.04914779)(-440.44308744,1028.65853952)(-442.06024799,1026.11865745) \curveto(-442.46986572,1025.41409129)(-442.32028849,1024.68630484)(-442.06024799,1023.96621501) \curveto(-441.64887687,1023.40344915)(-441.06810178,1023.72409785)(-440.47545762,1023.67270013) \curveto(-438.38623185,1024.09797058)(-437.3787098,1026.56871359)(-434.97926974,1026.31433403) \curveto(-434.21519847,1027.47456573)(-432.94534304,1028.32849835)(-431.47249956,1028.14064883) \curveto(-429.87017534,1030.22003867)(-426.99867007,1029.66170815)(-424.72871076,1029.83651256) \lineto(-422.84044989,1031.72805289) \lineto(-423.51482877,1029.96696362) \lineto(-421.32309741,1030.7170572) \curveto(-421.06885657,1030.69882014)(-421.34193955,1030.96295744)(-421.32309741,1030.7170572) \lineto(-421.42425424,1031.33669972) \lineto(-419.67086915,1032.77166134) \curveto(-418.92514098,1032.98507927)(-418.38995391,1033.77026418)(-417.91748406,1034.33707402) \curveto(-416.71762916,1035.24892691)(-415.74463531,1036.49342999)(-414.95021699,1037.72880149) \lineto(-414.71418438,1037.50051215) \curveto(-414.86848227,1037.06258795)(-415.86912565,1036.37198005)(-415.15253065,1036.22861434) \lineto(-415.75947164,1035.18500589) \lineto(-414.61302755,1035.70681012) \lineto(-412.32013935,1038.31583125) \lineto(-411.03881948,1041.25098003) \lineto(-410.70163004,1041.57710767) \lineto(-409.04940178,1046.50163506) \lineto(-408.64477445,1049.63246042) \curveto(-408.26806641,1050.30402246)(-408.24675604,1051.07524911)(-408.24014712,1051.85012838) \lineto(-407.56576824,1054.06779635) \lineto(-407.43089247,1056.67681748) \lineto(-406.58791886,1058.86187268) \lineto(-402.74395924,1062.18837463) \lineto(-402.74395924,1062.38405122) \lineto(-403.24974341,1062.54711504) \curveto(-405.05303253,1061.98030519)(-406.58791886,1060.49251089)(-407.32973563,1058.79664716) \lineto(-410.83650581,1054.7526644) \lineto(-412.52245302,1053.70905594) \lineto(-412.52245302,1053.90473253) \lineto(-410.09468904,1055.99194944) \lineto(-409.7574996,1056.31807708) \lineto(-408.914526,1057.85087699) \lineto(-408.77965023,1057.98132805) \curveto(-408.52540939,1057.96310404)(-408.79849237,1058.22722829)(-408.77965023,1057.98132805) \lineto(-408.914526,1057.85087699) \lineto(-409.31915333,1057.58997488) \lineto(-409.42031016,1057.62258764) \lineto(-408.47617973,1058.99232374) \lineto(-408.24014712,1059.28583862) \lineto(-408.10527135,1059.41628967) \lineto(-407.97039557,1059.54674073) \curveto(-407.71615473,1059.52851672)(-407.98923772,1059.79264097)(-407.97039557,1059.54674073) \lineto(-408.10527135,1059.41628967) \lineto(-408.24014712,1059.28583862) \lineto(-410.63419215,1057.36168553) \lineto(-405.50891266,1063.29720861) \curveto(-402.68596266,1063.4497059)(-400.10039403,1063.11692525)(-398.56281018,1065.64532763) \curveto(-398.053789,1065.1475264)(-398.86075077,1064.66603155)(-399.0348754,1064.21036601) \lineto(-398.39421546,1063.59072349) \curveto(-399.25337416,1060.90864976)(-401.63797788,1058.78229754)(-403.5532139,1056.57897919) \curveto(-403.81001738,1056.32525189)(-404.14680219,1055.56550493)(-404.56478222,1055.92672391) \curveto(-402.39867726,1057.45169676)(-403.98535589,1059.19974092)(-403.5532139,1060.81863853) \lineto(-406.18329154,1058.34006846) \curveto(-408.31567756,1049.0376036)(-408.89294588,1038.08101935)(-417.91748406,1031.988955) \curveto(-418.3276413,1031.08336376)(-418.64473425,1030.17046727)(-418.62558189,1029.15164452) \lineto(-417.27682412,1026.15127021) \curveto(-417.2885219,1023.35439955)(-417.61428332,1020.15704415)(-414.47815177,1019.07430038) \lineto(-414.0398055,1018.06330469) \curveto(-415.11962096,1013.57839736)(-407.54688563,1013.30575466)(-406.31816731,1009.61659877) \curveto(-405.8416512,1009.85493285)(-405.10752235,1009.70149632)(-404.86825272,1009.19263284) \curveto(-405.03199191,1007.24238954)(-408.45594836,1006.08398416)(-406.99254619,1003.74630122) \lineto(-405.77866421,1002.96359488) \curveto(-401.62718782,1002.59950598)(-398.92157975,997.78990597)(-403.21602446,995.46265912) \lineto(-403.78924651,994.32121237) \curveto(-403.80667246,993.63895334)(-403.87226255,992.90842743)(-403.35090024,992.39705928) \lineto(-401.79982881,992.00570611) \curveto(-401.79898854,993.93507724)(-400.34856546,995.19132092)(-398.96743751,996.44104204) \curveto(-398.50643211,997.62932072)(-397.9619386,997.12447513)(-398.76512385,996.24536546) \curveto(-399.99991158,995.09322172)(-401.38845769,993.93116371)(-401.49635832,992.23399546) \curveto(-400.70126561,990.53943624)(-399.20751639,988.84487701)(-397.07917665,989.00533181) \curveto(-397.98972301,990.27357698)(-400.09230149,991.58304469)(-399.23718906,993.31021668) \curveto(-399.01963444,994.29864434)(-397.99808531,994.78953166)(-398.79884279,993.53850603) \curveto(-399.14533866,993.03066007)(-399.34225729,992.44636978)(-399.0348754,991.87525506) \lineto(-395.15719684,986.75505108) \curveto(-394.77455426,984.5230335)(-396.90114062,983.08807188)(-398.63024807,982.15665133) \lineto(-399.57437851,980.85214076) \curveto(-399.84143254,980.05051902)(-399.40376065,979.42891974)(-398.76512385,978.96060044) \curveto(-398.66361634,981.8931402)(-393.99861392,982.66541045)(-393.80843907,985.71144263) \lineto(-393.90959591,988.02694888) \curveto(-393.39733771,987.21176023)(-393.44508373,985.79362679)(-393.6735633,984.79828523) \curveto(-394.05269911,983.19895527)(-395.79515926,982.58974884)(-396.87686298,981.50439605) \curveto(-398.35105522,980.51375072)(-398.61001671,978.75709679)(-397.21405242,977.78654093) \curveto(-398.72061484,978.25929556)(-400.80579434,979.70156244)(-399.57437851,981.50439605) \curveto(-398.22723925,983.23026353)(-395.08975895,983.94774434)(-395.42694839,986.62460002) \curveto(-396.379576,989.56366233)(-400.50637012,988.18740368)(-401.53007726,991.54912742) \curveto(-402.56282108,991.84133778)(-404.01179154,991.96304862)(-404.19387384,993.27760392) \curveto(-404.26765089,994.19180492)(-403.90604893,994.95911804)(-403.48577601,995.72356123) \curveto(-398.64913068,998.90656701)(-404.01934458,1002.32568921)(-407.26229775,1003.61585016) \curveto(-407.64305206,1004.04386008)(-407.57885119,1004.5960594)(-407.56576824,1005.14865008) \curveto(-408.00411451,1007.04410393)(-404.2909844,1007.82420125)(-405.57635054,1009.42092219) \curveto(-406.80749663,1008.1138026)(-410.11896668,1006.28357427)(-409.48774805,1004.07242886) \curveto(-407.40121979,1002.52658384)(-405.04224247,1000.95725763)(-403.28346235,999.18051423) \lineto(-409.69006172,1003.74630122) \curveto(-410.77473271,1005.30649586)(-409.16660883,1006.56795758)(-408.13899029,1007.59460739) \lineto(-410.49931637,1006.87712658) \curveto(-407.00603377,1008.38253177)(-409.80969653,1010.75282748)(-412.38757724,1010.92110934) \curveto(-412.80326438,1011.27515351)(-412.67486264,1011.83700621)(-412.69104774,1012.3234582) \curveto(-409.99353221,1015.02509958)(-415.61110829,1012.66289185)(-416.43385052,1014.9650921) \curveto(-417.4718545,1016.48484691)(-415.71280462,1017.59368089)(-415.25368748,1018.84601103) \curveto(-417.95524928,1019.9647593)(-420.69997132,1022.63039619)(-417.68145145,1025.23811281) \curveto(-418.15567468,1027.41012291)(-420.21306977,1029.44124586)(-418.52442505,1031.72805289) \curveto(-421.0614384,1029.02902052)(-425.19942722,1029.52473454)(-427.8982915,1027.1622659) \lineto(-428.60638932,1026.02081915) \curveto(-430.35842565,1015.92390736)(-427.86969783,1005.39650709)(-421.99747629,997.06068456) \curveto(-420.19823344,993.41588204)(-414.14635736,991.76045813)(-414.61302755,987.43991913) \curveto(-414.92701835,987.091093)(-415.26542167,986.74383229)(-415.79319059,986.88550214) \lineto(-414.81534121,987.76604677) \curveto(-414.61707382,988.17148865)(-414.65268102,988.77430299)(-414.95021699,989.13578287) \lineto(-415.79319059,990.40768067) \lineto(-416.5687263,990.96209766) \curveto(-418.00380456,992.24195298)(-414.66293158,988.1026105)(-416.8721968,988.45091482) \lineto(-416.46756947,989.1031701) \lineto(-416.73732102,990.14677856) \lineto(-417.91748406,991.744804) \curveto(-427.39925112,1000.52937816)(-431.11912503,1013.55622068)(-429.31448715,1025.98820639) \curveto(-430.26617062,1025.82044633)(-430.67268621,1026.70255638)(-431.2701859,1027.1622659) \curveto(-433.23937223,1025.56684948)(-435.53360918,1022.56647517)(-438.28372626,1024.03144054) \curveto(-439.63922781,1023.21638234)(-442.18568246,1022.49994513)(-442.90322159,1024.45540647) \curveto(-443.13669156,1028.75768232)(-436.2228244,1029.84042609)(-437.64306632,1034.36968678) \lineto(-437.20472005,1035.51113353) \curveto(-434.73919086,1036.89391473)(-433.95016757,1039.44292838)(-434.43976664,1042.03368637) \curveto(-445.86374488,1042.66859166)(-455.0083225,1052.22452292)(-458.69043119,1062.16228442) \curveto(-462.89720665,1077.79032101)(-454.49039952,1096.87531061)(-437.64981011,1101.29760144) \curveto(-434.47483434,1102.29463886)(-431.11103248,1103.32872439)(-427.66900268,1102.99346517) \curveto(-423.73602504,1102.84735999)(-419.63715021,1103.2186237)(-416.03596698,1101.98246948) \lineto(-407.87598253,1097.8732612) \curveto(-405.93377135,1096.67115471)(-403.38057291,1097.36932876)(-401.40194527,1097.8732612) \lineto(-401.36822633,1097.25361868) \curveto(-402.69661785,1094.07713545)(-406.36807135,1093.04918112)(-409.4607729,1092.42692958) \lineto(-415.39530705,1092.55738063) \curveto(-417.50071791,1093.11714612)(-419.64659151,1092.97821574)(-421.8693443,1092.94873381) \curveto(-423.641612,1092.98683856)(-425.35588312,1092.83389774)(-426.9946238,1092.42692958) \curveto(-440.7924157,1091.52916541)(-449.54585357,1070.1589342)(-436.84055545,1062.42318653) \curveto(-434.4761831,1062.13162842)(-432.65266261,1063.59241935)(-430.73742658,1064.60824173) \curveto(-428.61583063,1065.97928234)(-426.68036324,1067.6412288)(-424.87033032,1069.50015636) \lineto(-420.82405704,1074.06594334) \curveto(-419.8699458,1075.41219825)(-418.90342598,1076.78976141)(-417.58703841,1077.84902399) \curveto(-410.65577227,1087.78548098)(-394.60420615,1089.66136718)(-386.63304778,1080.32759407) \lineto(-383.59834282,1082.0234578) \curveto(-372.52773911,1090.49494943)(-359.19931492,1078.89393695)(-353.1838553,1069.63060742) \lineto(-349.94683667,1066.10842888) \curveto(-348.69923574,1065.28736993)(-347.29922519,1064.63954999)(-345.79940655,1064.51040344) \curveto(-344.71824233,1064.21662766)(-343.50921588,1064.41355658)(-342.4612311,1064.67346726) \curveto(-334.57369571,1069.1714197)(-335.48545595,1080.26236854)(-339.35908824,1087.04582349) \curveto(-342.82674445,1091.2072122)(-348.54143108,1092.7504482)(-353.76382114,1092.16602746) \lineto(-359.83323106,1092.55738063) \curveto(-361.76734969,1093.0710969)(-363.67179565,1094.13583842)(-364.78991584,1095.85126982) \curveto(-364.92883789,1096.68106899)(-365.47562428,1097.56017866)(-365.05966739,1098.39506542) \curveto(-361.78218603,1096.77877683)(-357.75479535,1096.55570552)(-354.47191896,1098.46029095) \curveto(-344.68263513,1105.33897517)(-328.58925752,1104.14012996)(-323.31561467,1092.39431681) \curveto(-320.72734853,1086.59185381)(-319.80749573,1079.99755289)(-320.5843802,1073.5050038) \curveto(-319.76163797,1060.61774391)(-330.83224168,1047.54524351)(-344.70016898,1048.28881454) \lineto(-341.46315035,1042.2228404) \curveto(-340.79403163,1040.9887734)(-338.70494073,1037.51094823)(-337.8215044,1040.33130008) \curveto(-337.68460548,1040.45884207)(-337.50090468,1040.74574308)(-337.34943918,1040.46175113) \curveto(-336.79725775,1039.06201129)(-337.72169632,1037.62183163)(-338.69819694,1036.61344496) \curveto(-346.41444009,1034.9762842)(-356.42087393,1036.43081348)(-361.02013789,1043.20122332) \lineto(-360.88526212,1034.52622805) \curveto(-358.52763355,1030.86968493)(-354.69446399,1036.01728363)(-352.32065033,1033.41739407) \curveto(-350.97189257,1030.62182792)(-349.90232767,1027.62667166)(-350.97189257,1024.48149668) \lineto(-357.37849194,1017.63281621) \curveto(-357.86606787,1015.46732867)(-353.69908076,1014.97161465)(-353.77056493,1012.70828882) \curveto(-355.36749411,1010.70456058)(-357.71298386,1009.22785462)(-359.94113168,1008.10988907) \curveto(-357.89911243,1006.09833377)(-358.11491367,1002.39352376)(-360.27832112,1000.47850225) \lineto(-361.59335994,1000.05453631) \curveto(-365.22556459,1001.41253181)(-371.67397545,997.51204522)(-368.23599192,993.62982177) \lineto(-367.79764564,992.35792397) \curveto(-367.81098216,991.5600853)(-367.68595501,990.73511282)(-368.10111614,990.04241771) \curveto(-368.75364515,988.11043756)(-370.4493034,986.89463371)(-372.14738943,985.86798389) \curveto(-377.09867917,984.02340595)(-379.81103103,978.34617596)(-377.07035525,973.73603562) \lineto(-375.78903538,973.67081009) \curveto(-379.00582264,972.53445094)(-374.37688601,971.89276219)(-373.09151986,972.04017188) \curveto(-374.83006861,971.23059262)(-377.84049594,971.37356698)(-377.9470478,973.80126115) \curveto(-381.85035276,976.82381213)(-379.67210898,983.08024481)(-375.51928383,984.9548265) \lineto(-372.68689253,987.56384763) \curveto(-371.81505551,988.62454517)(-371.3340885,989.86500427)(-371.16954005,991.18386446) \lineto(-371.03466427,993.14063031) \curveto(-369.01422515,986.45631816)(-378.93973351,984.9300408)(-379.36324345,979.20845745) \lineto(-375.99134905,983.83946996) \curveto(-371.74411085,986.25151)(-364.99897329,990.87078192)(-370.596318,995.6452906) \lineto(-371.06838322,997.14547775) \lineto(-371.4392916,997.96079685) \curveto(-374.35260837,997.25570889)(-375.81735929,993.31413021)(-373.46242824,991.30779296) \lineto(-373.32755247,989.22057605) \curveto(-374.16337765,987.29772748)(-376.04799687,985.7818862)(-377.81217202,984.55695077) \curveto(-380.47461984,982.74368109)(-381.42819158,979.5724159)(-380.88059593,976.56682355) \curveto(-380.65993916,975.48968918)(-379.88399882,974.75746739)(-378.99233506,974.08825347) \lineto(-378.75630246,973.3381599) \curveto(-382.84978226,974.63640881)(-386.01261921,979.13149133)(-382.60026208,982.79586151) \curveto(-381.1274186,984.35214262)(-379.31603693,985.3748789)(-377.27266892,985.86146134) \curveto(-375.05531116,988.0778248)(-372.55201675,991.27387569)(-376.12622482,993.55807369) \lineto(-376.29481954,994.96042255) \lineto(-375.78903538,997.14547775) \curveto(-377.40349842,997.62605944)(-377.60716084,995.15870815)(-377.47498258,993.68852475) \lineto(-376.73316581,992.90581841) \curveto(-378.82643786,993.58703382)(-377.68889556,997.76512027)(-375.78903538,998.58043937) \lineto(-376.39597637,998.31953726) \lineto(-376.93547948,998.05863515) \lineto(-378.62142668,996.94980116) \curveto(-378.75016561,996.77069186)(-379.13449413,996.46374053)(-379.26208662,996.78673734) \lineto(-378.01448569,997.79773303) \lineto(-376.93547948,998.44998832) \lineto(-376.59829004,998.71089043) \lineto(-380.57712543,996.55844799) \lineto(-379.9364655,997.30854157) \lineto(-378.89117823,998.12386067) \curveto(-377.3212242,999.27026456)(-379.47330208,998.36506468)(-380.17249811,998.05863515) \lineto(-381.65613164,997.21070328) \lineto(-380.61084438,998.74350319) \curveto(-381.57722931,997.96379723)(-384.06501301,997.26418821)(-381.85844531,998.51521384) \curveto(-380.03627357,999.40606411)(-377.895795,1000.65200215)(-375.89019221,1000.04801376) \curveto(-371.15470371,1002.82531676)(-365.55196397,1000.85028776)(-360.27157734,1001.38513709) \curveto(-357.26924256,1004.94384192)(-360.50814945,1009.41439963)(-364.85735372,1009.01652391) \lineto(-369.8140385,1008.91868562) \lineto(-372.91618135,1008.00552822) \curveto(-382.58003071,1003.78021849)(-389.06081175,1015.41253922)(-392.91825895,1022.32905425) \curveto(-393.6089578,1023.22942744)(-394.6379251,1023.77575647)(-395.68321236,1023.76401587) \curveto(-393.41729932,1024.52350192)(-392.01459125,1021.57374263)(-391.02999809,1019.98093523) \lineto(-389.276613,1017.30668856) \curveto(-388.81398908,1019.64698052)(-388.08053461,1022.41645646)(-386.03959437,1023.89446693) \lineto(-386.27562698,1023.40527547) \curveto(-387.69317138,1021.55939301)(-388.61437294,1019.36911977)(-388.56851517,1017.01317369) \curveto(-386.81917635,1011.77686827)(-380.284445,1006.5340403)(-374.67631023,1009.83836557) \curveto(-374.15703849,1009.7791147)(-372.79883942,1010.21028153)(-373.05780091,1009.4470124) \curveto(-375.3925006,1008.92625178)(-377.75282668,1008.09684396)(-380.17249811,1008.04466354) \curveto(-379.0545128,1007.65422352)(-377.94030401,1007.31361582)(-376.69944687,1007.35979549) \curveto(-370.40074812,1009.74835434)(-363.87006304,1011.79513142)(-356.87270778,1010.62107191) \lineto(-354.47866275,1012.61045052) \curveto(-354.34866948,1014.77072002)(-358.25653324,1015.12815592)(-357.85055715,1017.37191409) \curveto(-358.96314743,1016.51993824)(-358.63607367,1017.76378907)(-358.12030871,1018.41552255) \lineto(-360.48063479,1016.39353117) \lineto(-359.60394224,1017.56759068) \curveto(-357.53899411,1020.11138628)(-361.98045342,1015.60169325)(-361.559641,1016.85010987) \lineto(-360.88526212,1017.63281621) \curveto(-360.70506808,1017.83358038)(-359.89163227,1018.42687179)(-360.61551056,1018.28507149) \lineto(-363.04327454,1016.13262905) \lineto(-361.99798727,1018.1872332) \lineto(-361.9777559,1018.19375575) \closepath } } { \newrgbcolor{curcolor}{0.10980392 0.10980392 0.10980392} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-361.9777559,1018.19375575) \lineto(-361.84288013,1018.32420681) \curveto(-361.58863929,1018.30596975)(-361.86172227,1018.57010705)(-361.84288013,1018.32420681) \lineto(-361.9777559,1018.19375575) \lineto(-364.37180093,1016.40005372) \lineto(-364.50667671,1016.59573031) \curveto(-363.07429596,1017.97851151)(-361.21570777,1019.72003311)(-359.4488351,1020.24835989) \lineto(-360.25808976,1019.13952591) \curveto(-358.37387517,1020.54839732)(-356.31971709,1021.76420117)(-354.25611772,1022.85738103) \curveto(-352.45282859,1022.85238867)(-351.09597828,1024.85458671)(-351.05281804,1026.54262338) \curveto(-351.49075968,1028.70680641)(-351.71708123,1030.90360221)(-352.70504629,1032.9021124) \curveto(-354.65804753,1035.11586683)(-357.32454163,1031.36278993)(-359.65114877,1032.96733792) \lineto(-361.67428541,1034.53275061) \curveto(-364.13576832,1040.19693549)(-367.29995403,1045.71110166)(-371.25046551,1050.57823058) \lineto(-372.36319067,1052.76328578) \curveto(-372.79492803,1056.24371998)(-372.12850682,1060.24074035)(-369.49708042,1062.90585544) \curveto(-368.82067841,1063.28155449)(-368.09167484,1063.68595276)(-367.27163012,1063.55811073) \lineto(-368.72154471,1062.80801715) \lineto(-367.87857111,1061.2099917) \lineto(-371.25046551,1056.05717496) \curveto(-370.1709198,1057.71259887)(-366.82384254,1058.94014332)(-365.51824503,1057.16600895) \curveto(-365.42124237,1056.9139775)(-365.44600556,1056.33203534)(-365.85543447,1056.44852813) \lineto(-366.19262391,1057.29646) \curveto(-368.99534254,1058.28893164)(-372.2471975,1055.32534454)(-371.65509284,1052.66544749) \curveto(-369.80864347,1053.14955136)(-367.29590776,1054.4447999)(-365.1136177,1053.51337936) \lineto(-364.03461149,1053.05680066) \curveto(-363.62796103,1053.43054294)(-363.3936818,1055.35926181)(-364.23692515,1054.7526644) \lineto(-364.37180093,1054.94834098) \curveto(-362.76947671,1056.51505817)(-362.74519907,1059.00406434)(-363.62998416,1060.94908959) \lineto(-368.68782577,1066.81938714) \lineto(-365.6531208,1064.60171918) \curveto(-364.4621677,1063.36373865)(-363.35483758,1062.05531455)(-362.75329162,1060.49251089) \curveto(-362.21972305,1058.90361702)(-362.11735233,1056.77074224)(-363.19163789,1055.37230692) \curveto(-363.07140962,1054.55503105)(-363.09922101,1053.67513867)(-363.46138944,1052.89373684) \curveto(-361.87120404,1053.0868044)(-360.99855777,1050.03164065)(-363.02304317,1050.18687741) \lineto(-363.22535683,1050.90435822) \lineto(-363.83229783,1051.36093692) \lineto(-364.50667671,1051.42616245) \curveto(-363.38963553,1049.37677635)(-365.72352596,1047.03909341)(-367.91229005,1047.93659668) \lineto(-368.04716583,1047.54524351) \curveto(-367.03883453,1046.36661822)(-364.12228074,1046.09854129)(-363.4276705,1048.03443498) \curveto(-362.65833907,1047.95705141)(-363.62661227,1047.10170992)(-363.83229783,1046.79514994) \lineto(-361.7417233,1048.29533709) \lineto(-361.87659907,1047.31695416) \curveto(-364.30840932,1046.15306984)(-361.89304043,1043.43342621)(-361.60684752,1041.70755872) \lineto(-361.57312858,1043.50126075) \curveto(-361.66319862,1043.89391844)(-361.53649631,1045.28974474)(-361.06734441,1044.51225644) \curveto(-358.6314879,1039.07636091)(-351.65841027,1036.57430964)(-346.09613326,1037.98970361) \lineto(-347.95067518,1036.97870792) \lineto(-348.18670779,1036.88086963) \curveto(-346.52099196,1036.11133884)(-344.55045687,1036.90660762)(-342.82539569,1036.97870792) \curveto(-341.77269026,1036.00554304)(-339.20667862,1036.62609871)(-338.27333825,1038.05492914) \lineto(-339.82440967,1038.44628231) \lineto(-340.7685401,1039.3594397) \lineto(-352.97479785,1060.94908959) \curveto(-355.08290623,1063.31286274)(-357.69814753,1065.02698962)(-360.52784131,1066.42803397) \lineto(-361.67428541,1066.36280845) \lineto(-362.92188634,1067.24335308) \lineto(-364.8101472,1066.85199991) \lineto(-365.21477453,1067.7651573) \curveto(-365.69385329,1067.30205605)(-366.04331642,1066.51961062)(-366.83328385,1066.46064674) \lineto(-366.32749968,1067.8629956) \lineto(-367.40650589,1067.08028926) \curveto(-367.67989909,1067.40798231)(-367.85388884,1067.73971935)(-367.67625745,1068.12389771) \curveto(-370.19438819,1068.83629093)(-373.43140681,1068.00341311)(-375.22930091,1065.84100422) \lineto(-375.97111768,1065.51487658) \curveto(-375.09429026,1064.39612831)(-374.37823476,1062.55233308)(-375.49905246,1061.27521723) \curveto(-376.21537771,1060.08485134)(-377.60716084,1059.7893797)(-378.9721037,1059.9380939) \curveto(-379.23929261,1060.08172052)(-380.10762286,1060.09593968)(-379.61276364,1060.55773642) \curveto(-379.25035242,1060.53125486)(-379.10657485,1060.67362914)(-378.93838475,1060.94908959) \curveto(-376.62391644,1061.22708079)(-377.70413653,1064.54171169)(-378.33144376,1065.90622975) \curveto(-380.65939966,1066.86647998)(-382.41278475,1069.2209911)(-382.47887388,1071.67868901) \lineto(-383.1869717,1072.82013575) \curveto(-383.23262715,1070.83075714)(-382.65947254,1068.49959675)(-381.29871084,1066.81938714) \curveto(-380.26057199,1065.87100796)(-378.09541115,1064.33559902)(-379.14069842,1062.71017886) \lineto(-380.08482885,1064.99307235) \curveto(-383.62801549,1065.23205869)(-386.16368008,1068.33001038)(-386.42399033,1071.64607624) \curveto(-387.01137434,1070.22024619)(-386.35358518,1068.28565702)(-385.41242201,1067.01506373) \curveto(-384.12300959,1065.25788799)(-380.9709627,1065.41442926)(-379.68020152,1063.4928852) \lineto(-380.05110991,1063.32982138) \curveto(-381.59813506,1064.51588238)(-383.44863071,1065.22657974)(-385.27754623,1065.84100422) \curveto(-386.38393223,1067.24465759)(-387.12264685,1068.83616048)(-387.23324499,1070.60246779) \curveto(-387.74752632,1070.26316459)(-388.34246337,1070.19637365)(-388.91919219,1070.34156568) \curveto(-389.40609374,1069.94903845)(-390.43114964,1069.33683164)(-390.80745306,1070.08066356) \lineto(-394.38166112,1068.05867218) \lineto(-395.73041888,1067.01506373) \lineto(-395.86529466,1067.8629956) \curveto(-396.62235239,1067.78699481)(-397.08753894,1068.3259664)(-397.48380397,1068.77615299) \lineto(-398.12446391,1067.50425519) \lineto(-399.37206484,1068.38479982) \curveto(-400.15043295,1068.05084512)(-400.43124431,1068.39384921)(-400.1813195,1069.16750616) \lineto(-401.8672667,1068.3195743) \curveto(-401.31292726,1069.42697332)(-401.75666856,1070.23459581)(-402.4067698,1071.12427202) \lineto(-402.81139713,1069.62408486) \curveto(-402.33096962,1069.65020116)(-401.80050319,1069.57718771)(-402.06958036,1068.97182958) \lineto(-402.47420769,1068.58047641) \curveto(-403.15667912,1068.82546349)(-403.76807101,1068.71718912)(-404.09271701,1067.92822113) \curveto(-405.16349579,1067.68036412)(-405.27517294,1068.04826219)(-405.0031285,1068.80876576) \curveto(-405.34800585,1068.58321588)(-405.78958915,1067.96526923)(-406.0821347,1068.54786365) \curveto(-406.52102048,1068.24469539)(-407.25258669,1068.05697632)(-407.66692507,1068.38479982) \lineto(-409.48774805,1066.75416162) \curveto(-415.33326419,1065.76064637)(-422.31443436,1063.97685862)(-426.21234429,1058.6661961) \lineto(-427.49366417,1057.55736212) \curveto(-428.72966578,1055.03052515)(-429.44666541,1052.2597447)(-431.2701859,1049.99120083) \lineto(-433.22588465,1041.1857545) \curveto(-434.11296263,1041.11902878)(-432.92214441,1042.97945653)(-434.00142037,1042.32720124) \curveto(-433.87730768,1040.00647695)(-433.43305385,1036.9265275)(-436.12571384,1035.77203564) \lineto(-436.9349685,1034.85887825) \lineto(-437.10356322,1033.58698044) \curveto(-436.18006878,1030.04914779)(-440.44308744,1028.65853952)(-442.06024799,1026.11865745) \curveto(-442.46986572,1025.41409129)(-442.32028849,1024.68630484)(-442.06024799,1023.96621501) \curveto(-441.64887687,1023.40344915)(-441.06810178,1023.72409785)(-440.47545762,1023.67270013) \curveto(-438.38623185,1024.09797058)(-437.3787098,1026.56871359)(-434.97926974,1026.31433403) \curveto(-434.21519847,1027.47456573)(-432.94534304,1028.32849835)(-431.47249956,1028.14064883) \curveto(-429.87017534,1030.22003867)(-426.99867007,1029.66170815)(-424.72871076,1029.83651256) \lineto(-422.84044989,1031.72805289) \lineto(-423.51482877,1029.96696362) \lineto(-421.32309741,1030.7170572) \curveto(-421.06885657,1030.69882014)(-421.34193955,1030.96295744)(-421.32309741,1030.7170572) \lineto(-421.42425424,1031.33669972) \lineto(-419.67086915,1032.77166134) \curveto(-418.92514098,1032.98507927)(-418.38995391,1033.77026418)(-417.91748406,1034.33707402) \curveto(-416.71762916,1035.24892691)(-415.74463531,1036.49342999)(-414.95021699,1037.72880149) \lineto(-414.71418438,1037.50051215) \curveto(-414.86848227,1037.06258795)(-415.86912565,1036.37198005)(-415.15253065,1036.22861434) \lineto(-415.75947164,1035.18500589) \lineto(-414.61302755,1035.70681012) \lineto(-412.32013935,1038.31583125) \lineto(-411.03881948,1041.25098003) \lineto(-410.70163004,1041.57710767) \lineto(-409.04940178,1046.50163506) \lineto(-408.64477445,1049.63246042) \curveto(-408.26806641,1050.30402246)(-408.24675604,1051.07524911)(-408.24014712,1051.85012838) \lineto(-407.56576824,1054.06779635) \lineto(-407.43089247,1056.67681748) \lineto(-406.58791886,1058.86187268) \lineto(-402.74395924,1062.18837463) \lineto(-402.74395924,1062.38405122) \lineto(-403.24974341,1062.54711504) \curveto(-405.05303253,1061.98030519)(-406.58791886,1060.49251089)(-407.32973563,1058.79664716) \lineto(-410.83650581,1054.7526644) \lineto(-412.52245302,1053.70905594) \lineto(-412.52245302,1053.90473253) \lineto(-410.09468904,1055.99194944) \lineto(-409.7574996,1056.31807708) \lineto(-408.914526,1057.85087699) \lineto(-408.77965023,1057.98132805) \curveto(-408.52540939,1057.96310404)(-408.79849237,1058.22722829)(-408.77965023,1057.98132805) \lineto(-408.914526,1057.85087699) \lineto(-409.31915333,1057.58997488) \lineto(-409.42031016,1057.62258764) \lineto(-408.47617973,1058.99232374) \lineto(-408.24014712,1059.28583862) \lineto(-408.10527135,1059.41628967) \lineto(-407.97039557,1059.54674073) \curveto(-407.71615473,1059.52851672)(-407.98923772,1059.79264097)(-407.97039557,1059.54674073) \lineto(-408.10527135,1059.41628967) \lineto(-408.24014712,1059.28583862) \lineto(-410.63419215,1057.36168553) \lineto(-405.50891266,1063.29720861) \curveto(-402.68596266,1063.4497059)(-400.10039403,1063.11692525)(-398.56281018,1065.64532763) \curveto(-398.053789,1065.1475264)(-398.86075077,1064.66603155)(-399.0348754,1064.21036601) \lineto(-398.39421546,1063.59072349) \curveto(-399.25337416,1060.90864976)(-401.63797788,1058.78229754)(-403.5532139,1056.57897919) \curveto(-403.81001738,1056.32525189)(-404.14680219,1055.56550493)(-404.56478222,1055.92672391) \curveto(-402.39867726,1057.45169676)(-403.98535589,1059.19974092)(-403.5532139,1060.81863853) \lineto(-406.18329154,1058.34006846) \curveto(-408.31567756,1049.0376036)(-408.89294588,1038.08101935)(-417.91748406,1031.988955) \curveto(-418.3276413,1031.08336376)(-418.64473425,1030.17046727)(-418.62558189,1029.15164452) \lineto(-417.27682412,1026.15127021) \curveto(-417.2885219,1023.35439955)(-417.61428332,1020.15704415)(-414.47815177,1019.07430038) \lineto(-414.0398055,1018.06330469) \curveto(-415.11962096,1013.57839736)(-407.54688563,1013.30575466)(-406.31816731,1009.61659877) \curveto(-405.8416512,1009.85493285)(-405.10752235,1009.70149632)(-404.86825272,1009.19263284) \curveto(-405.03199191,1007.24238954)(-408.45594836,1006.08398416)(-406.99254619,1003.74630122) \lineto(-405.77866421,1002.96359488) \curveto(-401.62718782,1002.59950598)(-398.92157975,997.78990597)(-403.21602446,995.46265912) \lineto(-403.78924651,994.32121237) \curveto(-403.80667246,993.63895334)(-403.87226255,992.90842743)(-403.35090024,992.39705928) \lineto(-401.79982881,992.00570611) \curveto(-401.79898854,993.93507724)(-400.34856546,995.19132092)(-398.96743751,996.44104204) \curveto(-398.50643211,997.62932072)(-397.9619386,997.12447513)(-398.76512385,996.24536546) \curveto(-399.99991158,995.09322172)(-401.38845769,993.93116371)(-401.49635832,992.23399546) \curveto(-400.70126561,990.53943624)(-399.20751639,988.84487701)(-397.07917665,989.00533181) \curveto(-397.98972301,990.27357698)(-400.09230149,991.58304469)(-399.23718906,993.31021668) \curveto(-399.01963444,994.29864434)(-397.99808531,994.78953166)(-398.79884279,993.53850603) \curveto(-399.14533866,993.03066007)(-399.34225729,992.44636978)(-399.0348754,991.87525506) \lineto(-395.15719684,986.75505108) \curveto(-394.77455426,984.5230335)(-396.90114062,983.08807188)(-398.63024807,982.15665133) \lineto(-399.57437851,980.85214076) \curveto(-399.84143254,980.05051902)(-399.40376065,979.42891974)(-398.76512385,978.96060044) \curveto(-398.66361634,981.8931402)(-393.99861392,982.66541045)(-393.80843907,985.71144263) \lineto(-393.90959591,988.02694888) \curveto(-393.39733771,987.21176023)(-393.44508373,985.79362679)(-393.6735633,984.79828523) \curveto(-394.05269911,983.19895527)(-395.79515926,982.58974884)(-396.87686298,981.50439605) \curveto(-398.35105522,980.51375072)(-398.61001671,978.75709679)(-397.21405242,977.78654093) \curveto(-398.72061484,978.25929556)(-400.80579434,979.70156244)(-399.57437851,981.50439605) \curveto(-398.22723925,983.23026353)(-395.08975895,983.94774434)(-395.42694839,986.62460002) \curveto(-396.379576,989.56366233)(-400.50637012,988.18740368)(-401.53007726,991.54912742) \curveto(-402.56282108,991.84133778)(-404.01179154,991.96304862)(-404.19387384,993.27760392) \curveto(-404.26765089,994.19180492)(-403.90604893,994.95911804)(-403.48577601,995.72356123) \curveto(-398.64913068,998.90656701)(-404.01934458,1002.32568921)(-407.26229775,1003.61585016) \curveto(-407.64305206,1004.04386008)(-407.57885119,1004.5960594)(-407.56576824,1005.14865008) \curveto(-408.00411451,1007.04410393)(-404.2909844,1007.82420125)(-405.57635054,1009.42092219) \curveto(-406.80749663,1008.1138026)(-410.11896668,1006.28357427)(-409.48774805,1004.07242886) \curveto(-407.40121979,1002.52658384)(-405.04224247,1000.95725763)(-403.28346235,999.18051423) \lineto(-409.69006172,1003.74630122) \curveto(-410.77473271,1005.30649586)(-409.16660883,1006.56795758)(-408.13899029,1007.59460739) \lineto(-410.49931637,1006.87712658) \curveto(-407.00603377,1008.38253177)(-409.80969653,1010.75282748)(-412.38757724,1010.92110934) \curveto(-412.80326438,1011.27515351)(-412.67486264,1011.83700621)(-412.69104774,1012.3234582) \curveto(-409.99353221,1015.02509958)(-415.61110829,1012.66289185)(-416.43385052,1014.9650921) \curveto(-417.4718545,1016.48484691)(-415.71280462,1017.59368089)(-415.25368748,1018.84601103) \curveto(-417.95524928,1019.9647593)(-420.69997132,1022.63039619)(-417.68145145,1025.23811281) \curveto(-418.15567468,1027.41012291)(-420.21306977,1029.44124586)(-418.52442505,1031.72805289) \curveto(-421.0614384,1029.02902052)(-425.19942722,1029.52473454)(-427.8982915,1027.1622659) \lineto(-428.60638932,1026.02081915) \curveto(-430.35842565,1015.92390736)(-427.86969783,1005.39650709)(-421.99747629,997.06068456) \curveto(-420.19823344,993.41588204)(-414.14635736,991.76045813)(-414.61302755,987.43991913) \curveto(-414.92701835,987.091093)(-415.26542167,986.74383229)(-415.79319059,986.88550214) \lineto(-414.81534121,987.76604677) \curveto(-414.61707382,988.17148865)(-414.65268102,988.77430299)(-414.95021699,989.13578287) \lineto(-415.79319059,990.40768067) \lineto(-416.5687263,990.96209766) \curveto(-418.00380456,992.24195298)(-414.66293158,988.1026105)(-416.8721968,988.45091482) \lineto(-416.46756947,989.1031701) \lineto(-416.73732102,990.14677856) \lineto(-417.91748406,991.744804) \curveto(-427.39925112,1000.52937816)(-431.11912503,1013.55622068)(-429.31448715,1025.98820639) \curveto(-430.26617062,1025.82044633)(-430.67268621,1026.70255638)(-431.2701859,1027.1622659) \curveto(-433.23937223,1025.56684948)(-435.53360918,1022.56647517)(-438.28372626,1024.03144054) \curveto(-439.63922781,1023.21638234)(-442.18568246,1022.49994513)(-442.90322159,1024.45540647) \curveto(-443.13669156,1028.75768232)(-436.2228244,1029.84042609)(-437.64306632,1034.36968678) \lineto(-437.20472005,1035.51113353) \curveto(-434.73919086,1036.89391473)(-433.95016757,1039.44292838)(-434.43976664,1042.03368637) \curveto(-445.86374488,1042.66859166)(-455.0083225,1052.22452292)(-458.69043119,1062.16228442) \curveto(-462.89720665,1077.79032101)(-454.49039952,1096.87531061)(-437.64981011,1101.29760144) \curveto(-434.47483434,1102.29463886)(-431.11103248,1103.32872439)(-427.66900268,1102.99346517) \curveto(-423.73602504,1102.84735999)(-419.63715021,1103.2186237)(-416.03596698,1101.98246948) \lineto(-407.87598253,1097.8732612) \curveto(-405.93377135,1096.67115471)(-403.38057291,1097.36932876)(-401.40194527,1097.8732612) \lineto(-401.36822633,1097.25361868) \curveto(-402.69661785,1094.07713545)(-406.36807135,1093.04918112)(-409.4607729,1092.42692958) \lineto(-415.39530705,1092.55738063) \curveto(-417.50071791,1093.11714612)(-419.64659151,1092.97821574)(-421.8693443,1092.94873381) \curveto(-423.641612,1092.98683856)(-425.35588312,1092.83389774)(-426.9946238,1092.42692958) \curveto(-440.7924157,1091.52916541)(-449.54585357,1070.1589342)(-436.84055545,1062.42318653) \curveto(-434.4761831,1062.13162842)(-432.65266261,1063.59241935)(-430.73742658,1064.60824173) \curveto(-428.61583063,1065.97928234)(-426.68036324,1067.6412288)(-424.87033032,1069.50015636) \lineto(-420.82405704,1074.06594334) \curveto(-419.8699458,1075.41219825)(-418.90342598,1076.78976141)(-417.58703841,1077.84902399) \curveto(-410.65577227,1087.78548098)(-394.60420615,1089.66136718)(-386.63304778,1080.32759407) \lineto(-383.59834282,1082.0234578) \curveto(-372.52773911,1090.49494943)(-359.19931492,1078.89393695)(-353.1838553,1069.63060742) \lineto(-349.94683667,1066.10842888) \curveto(-348.69923574,1065.28736993)(-347.29922519,1064.63954999)(-345.79940655,1064.51040344) \curveto(-344.71824233,1064.21662766)(-343.50921588,1064.41355658)(-342.4612311,1064.67346726) \curveto(-334.57369571,1069.1714197)(-335.48545595,1080.26236854)(-339.35908824,1087.04582349) \curveto(-342.82674445,1091.2072122)(-348.54143108,1092.7504482)(-353.76382114,1092.16602746) \lineto(-359.83323106,1092.55738063) \curveto(-361.76734969,1093.0710969)(-363.67179565,1094.13583842)(-364.78991584,1095.85126982) \curveto(-364.92883789,1096.68106899)(-365.47562428,1097.56017866)(-365.05966739,1098.39506542) \curveto(-361.78218603,1096.77877683)(-357.75479535,1096.55570552)(-354.47191896,1098.46029095) \curveto(-344.68263513,1105.33897517)(-328.58925752,1104.14012996)(-323.31561467,1092.39431681) \curveto(-320.72734853,1086.59185381)(-319.80749573,1079.99755289)(-320.5843802,1073.5050038) \curveto(-319.76163797,1060.61774391)(-330.83224168,1047.54524351)(-344.70016898,1048.28881454) \lineto(-341.46315035,1042.2228404) \curveto(-340.79403163,1040.9887734)(-338.70494073,1037.51094823)(-337.8215044,1040.33130008) \curveto(-337.68460548,1040.45884207)(-337.50090468,1040.74574308)(-337.34943918,1040.46175113) \curveto(-336.79725775,1039.06201129)(-337.72169632,1037.62183163)(-338.69819694,1036.61344496) \curveto(-346.41444009,1034.9762842)(-356.42087393,1036.43081348)(-361.02013789,1043.20122332) \lineto(-360.88526212,1034.52622805) \curveto(-358.52763355,1030.86968493)(-354.69446399,1036.01728363)(-352.32065033,1033.41739407) \curveto(-350.97189257,1030.62182792)(-349.90232767,1027.62667166)(-350.97189257,1024.48149668) \lineto(-357.37849194,1017.63281621) \curveto(-357.86606787,1015.46732867)(-353.69908076,1014.97161465)(-353.77056493,1012.70828882) \curveto(-355.36749411,1010.70456058)(-357.71298386,1009.22785462)(-359.94113168,1008.10988907) \curveto(-357.89911243,1006.09833377)(-358.11491367,1002.39352376)(-360.27832112,1000.47850225) \lineto(-361.59335994,1000.05453631) \curveto(-365.22556459,1001.41253181)(-371.67397545,997.51204522)(-368.23599192,993.62982177) \lineto(-367.79764564,992.35792397) \curveto(-367.81098216,991.5600853)(-367.68595501,990.73511282)(-368.10111614,990.04241771) \curveto(-368.75364515,988.11043756)(-370.4493034,986.89463371)(-372.14738943,985.86798389) \curveto(-377.09867917,984.02340595)(-379.81103103,978.34617596)(-377.07035525,973.73603562) \lineto(-375.78903538,973.67081009) \curveto(-379.00582264,972.53445094)(-374.37688601,971.89276219)(-373.09151986,972.04017188) \curveto(-374.83006861,971.23059262)(-377.84049594,971.37356698)(-377.9470478,973.80126115) \curveto(-381.85035276,976.82381213)(-379.67210898,983.08024481)(-375.51928383,984.9548265) \lineto(-372.68689253,987.56384763) \curveto(-371.81505551,988.62454517)(-371.3340885,989.86500427)(-371.16954005,991.18386446) \lineto(-371.03466427,993.14063031) \curveto(-369.01422515,986.45631816)(-378.93973351,984.9300408)(-379.36324345,979.20845745) \lineto(-375.99134905,983.83946996) \curveto(-371.74411085,986.25151)(-364.99897329,990.87078192)(-370.596318,995.6452906) \lineto(-371.06838322,997.14547775) \lineto(-371.4392916,997.96079685) \curveto(-374.35260837,997.25570889)(-375.81735929,993.31413021)(-373.46242824,991.30779296) \lineto(-373.32755247,989.22057605) \curveto(-374.16337765,987.29772748)(-376.04799687,985.7818862)(-377.81217202,984.55695077) \curveto(-380.47461984,982.74368109)(-381.42819158,979.5724159)(-380.88059593,976.56682355) \curveto(-380.65993916,975.48968918)(-379.88399882,974.75746739)(-378.99233506,974.08825347) \lineto(-378.75630246,973.3381599) \curveto(-382.84978226,974.63640881)(-386.01261921,979.13149133)(-382.60026208,982.79586151) \curveto(-381.1274186,984.35214262)(-379.31603693,985.3748789)(-377.27266892,985.86146134) \curveto(-375.05531116,988.0778248)(-372.55201675,991.27387569)(-376.12622482,993.55807369) \lineto(-376.29481954,994.96042255) \lineto(-375.78903538,997.14547775) \curveto(-377.40349842,997.62605944)(-377.60716084,995.15870815)(-377.47498258,993.68852475) \lineto(-376.73316581,992.90581841) \curveto(-378.82643786,993.58703382)(-377.68889556,997.76512027)(-375.78903538,998.58043937) \lineto(-376.39597637,998.31953726) \lineto(-376.93547948,998.05863515) \lineto(-378.62142668,996.94980116) \curveto(-378.75016561,996.77069186)(-379.13449413,996.46374053)(-379.26208662,996.78673734) \lineto(-378.01448569,997.79773303) \lineto(-376.93547948,998.44998832) \lineto(-376.59829004,998.71089043) \lineto(-380.57712543,996.55844799) \lineto(-379.9364655,997.30854157) \lineto(-378.89117823,998.12386067) \curveto(-377.3212242,999.27026456)(-379.47330208,998.36506468)(-380.17249811,998.05863515) \lineto(-381.65613164,997.21070328) \lineto(-380.61084438,998.74350319) \curveto(-381.57722931,997.96379723)(-384.06501301,997.26418821)(-381.85844531,998.51521384) \curveto(-380.03627357,999.40606411)(-377.895795,1000.65200215)(-375.89019221,1000.04801376) \curveto(-371.15470371,1002.82531676)(-365.55196397,1000.85028776)(-360.27157734,1001.38513709) \curveto(-357.26924256,1004.94384192)(-360.50814945,1009.41439963)(-364.85735372,1009.01652391) \lineto(-369.8140385,1008.91868562) \lineto(-372.91618135,1008.00552822) \curveto(-382.58003071,1003.78021849)(-389.06081175,1015.41253922)(-392.91825895,1022.32905425) \curveto(-393.6089578,1023.22942744)(-394.6379251,1023.77575647)(-395.68321236,1023.76401587) \curveto(-393.41729932,1024.52350192)(-392.01459125,1021.57374263)(-391.02999809,1019.98093523) \lineto(-389.276613,1017.30668856) \curveto(-388.81398908,1019.64698052)(-388.08053461,1022.41645646)(-386.03959437,1023.89446693) \lineto(-386.27562698,1023.40527547) \curveto(-387.69317138,1021.55939301)(-388.61437294,1019.36911977)(-388.56851517,1017.01317369) \curveto(-386.81917635,1011.77686827)(-380.284445,1006.5340403)(-374.67631023,1009.83836557) \curveto(-374.15703849,1009.7791147)(-372.79883942,1010.21028153)(-373.05780091,1009.4470124) \curveto(-375.3925006,1008.92625178)(-377.75282668,1008.09684396)(-380.17249811,1008.04466354) \curveto(-379.0545128,1007.65422352)(-377.94030401,1007.31361582)(-376.69944687,1007.35979549) \curveto(-370.40074812,1009.74835434)(-363.87006304,1011.79513142)(-356.87270778,1010.62107191) \lineto(-354.47866275,1012.61045052) \curveto(-354.34866948,1014.77072002)(-358.25653324,1015.12815592)(-357.85055715,1017.37191409) \curveto(-358.96314743,1016.51993824)(-358.63607367,1017.76378907)(-358.12030871,1018.41552255) \lineto(-360.48063479,1016.39353117) \lineto(-359.60394224,1017.56759068) \curveto(-357.53899411,1020.11138628)(-361.98045342,1015.60169325)(-361.559641,1016.85010987) \lineto(-360.88526212,1017.63281621) \curveto(-360.70506808,1017.83358038)(-359.89163227,1018.42687179)(-360.61551056,1018.28507149) \lineto(-363.04327454,1016.13262905) \lineto(-361.99798727,1018.1872332) \lineto(-361.9777559,1018.19375575) \closepath } } { \newrgbcolor{curcolor}{0.81176472 0.81176472 0.81176472} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.29825264,1077.54898656) \lineto(-454.09791101,1078.72304607) \lineto(-449.20866413,1077.19024615) \lineto(-444.69032563,1075.49438242) \lineto(-444.38685513,1075.85312282) \lineto(-443.88107097,1075.55960794) \curveto(-444.40924451,1071.32386213)(-443.4995074,1066.51152265)(-440.07083029,1063.59072349) \lineto(-442.36371849,1060.72080024) \lineto(-441.41958806,1062.54711504) \curveto(-441.54745029,1063.67434262)(-442.12336985,1062.87963478)(-442.5997511,1062.44927674) \curveto(-443.50233979,1062.7956243)(-442.20429532,1065.00220392)(-443.61131942,1063.75378731) \lineto(-443.94850886,1063.88423837) \lineto(-443.07181631,1065.90622975) \lineto(-445.16239084,1064.53649365) \curveto(-444.52807007,1065.49413486)(-443.67875731,1066.37976708)(-444.42057407,1067.47164243) \lineto(-446.24139705,1066.62371056) \lineto(-445.22982873,1068.51525088) \lineto(-445.46586134,1068.6783147) \curveto(-446.56482916,1067.84708057)(-446.05823575,1069.92138282)(-445.90420761,1070.47201673) \lineto(-447.85990637,1070.14588909) \lineto(-446.67974332,1071.15688478) \lineto(-447.08437065,1071.15688478) \lineto(-453.28865636,1069.5914721) \curveto(-454.42633353,1069.44667143)(-456.1196989,1069.7828438)(-456.79542654,1068.93921682) \curveto(-456.34831334,1068.67935831)(-455.57399151,1068.96944233)(-455.04204145,1069.06966787) \lineto(-453.05262375,1069.16750616) \lineto(-454.67113306,1068.58047641) \lineto(-456.12104766,1068.02605942) \lineto(-448.60172313,1069.55885933) \lineto(-449.78188618,1068.93921682) \lineto(-454.73857095,1066.9498382) \lineto(-454.60369517,1066.10190633) \lineto(-448.87147469,1067.8629956) \lineto(-455.311793,1065.15613617) \lineto(-450.89461133,1066.10190633) \lineto(-448.06222003,1067.21074031) \lineto(-448.19709581,1066.75416162) \curveto(-450.87033369,1065.46347886)(-453.94954766,1064.43213281)(-456.52567498,1063.59072349) \curveto(-455.7939739,1063.08731286)(-454.66304052,1063.76722377)(-453.82815946,1063.98207666) \lineto(-450.489984,1065.18874893) \lineto(-446.84833805,1066.81938714) \curveto(-449.71175077,1064.27559154)(-453.63798462,1063.45244537)(-457.03145914,1061.86224699) \lineto(-457.03145914,1061.40566829) \lineto(-453.45725108,1062.64495333) \lineto(-452.24336909,1062.64495333) \lineto(-455.8512961,1060.32944707) \curveto(-454.13432747,1059.90613339)(-452.15435108,1061.61530314)(-450.45626506,1062.28621292) \lineto(-448.87147469,1063.23198308) \lineto(-447.25296537,1064.07991495) \lineto(-452.44568276,1060.62296195) \curveto(-451.92438788,1060.27361402)(-451.27428664,1060.95000275)(-450.72601661,1061.11215341) \lineto(-447.52271693,1062.90585544) \lineto(-452.58055853,1059.77503008) \lineto(-455.27807405,1058.40529399) \lineto(-449.41097779,1060.68818748) \curveto(-449.53838145,1060.52003607)(-449.58038177,1060.13311823)(-449.27610202,1060.10115772) \lineto(-448.06222003,1060.42728536) \curveto(-448.37014143,1059.57165688)(-449.40949416,1059.26131382)(-450.15279456,1058.73142163) \lineto(-454.06419207,1056.44852813) \curveto(-451.77939642,1056.89741022)(-449.73602841,1058.41833909)(-447.75874953,1059.67719179) \lineto(-447.25296537,1059.90548114) \curveto(-448.88361351,1057.97219648)(-450.84335853,1056.42113341)(-453.25493741,1055.33969415) \lineto(-453.25493741,1055.01356651) \curveto(-452.89185182,1054.90154819)(-452.5016562,1055.02237717)(-452.24336909,1055.27446862) \lineto(-450.22023245,1056.44852813) \lineto(-448.60172313,1057.42691106) \curveto(-448.46347546,1056.57036942)(-447.51529876,1057.49894613)(-447.1180896,1057.68781317) \lineto(-452.71543431,1054.16563464) \lineto(-452.71543431,1053.70905594) \lineto(-451.13064394,1054.45914952) \lineto(-449.24238307,1055.50275797) \lineto(-446.54486755,1057.06817065) \curveto(-445.35607246,1057.92353823)(-445.70229858,1056.88149519)(-446.64602438,1056.51375366) \lineto(-451.77130387,1053.31770277) \curveto(-448.95644643,1054.34761387)(-445.87318618,1055.94107352)(-443.88107097,1058.2096174) \curveto(-444.16795175,1058.53965857)(-443.44609659,1058.83760879)(-443.20669209,1058.86187268) \curveto(-444.56623991,1055.50014895)(-448.72985512,1054.04561967)(-451.77130387,1052.27409432) \curveto(-453.11035058,1053.59947706)(-453.86592468,1055.22098369)(-454.80600884,1056.77465578) \curveto(-456.10675082,1058.3583316)(-456.89118834,1060.2707441)(-457.70583802,1062.05792357) \curveto(-461.72918243,1075.76832963)(-455.66651629,1092.64869637)(-441.58818278,1098.71467051) \curveto(-440.24603393,1099.60369446)(-438.73960638,1100.13006448)(-437.23843899,1100.6388236) \curveto(-433.04784863,1101.97072889)(-428.37170547,1102.85779607)(-423.88573716,1102.07378522) \curveto(-419.00728033,1102.1396891)(-413.93190488,1101.27764242)(-410.08794526,1098.06241523) \lineto(-407.15439712,1096.59484084) \curveto(-405.66132228,1096.28749815)(-404.21140769,1096.48488364)(-402.73721546,1096.82313019) \curveto(-404.19657135,1093.40400799)(-409.22878656,1093.281384)(-412.51570923,1093.36617719) \lineto(-411.90876823,1093.75753036) \curveto(-410.98257628,1094.38017325)(-411.41633678,1095.98172087)(-411.36926513,1097.0840323) \lineto(-412.1110819,1097.01880677) \curveto(-412.45933115,1098.43159172)(-413.75926388,1097.69219513)(-414.67372164,1097.9971897) \curveto(-414.65242476,1096.57396867)(-414.74790332,1094.87549591)(-415.41553841,1093.49662824) \lineto(-415.92132257,1093.46401548) \curveto(-416.30531391,1093.35925024)(-416.88406586,1093.54736066)(-416.35966885,1093.88798141) \curveto(-416.38799276,1094.82383729)(-415.92037844,1095.55905945)(-415.51669525,1096.33393873) \lineto(-415.55041419,1098.38854287) \lineto(-416.19107413,1099.33431303) \lineto(-416.89917195,1093.6270793) \lineto(-419.42809275,1093.72491759) \lineto(-419.56296853,1095.68168344) \lineto(-419.56296853,1096.59484084) \curveto(-419.41433542,1097.13216874)(-419.3927553,1097.69167333)(-418.78743282,1097.73628759) \lineto(-418.75371387,1096.20348767) \curveto(-418.99783903,1095.76269355)(-419.06878369,1094.14888353)(-418.48396232,1095.15987922) \lineto(-418.34908654,1095.68168344) \curveto(-418.03010533,1097.45973135)(-417.43597754,1095.28876486)(-418.21421077,1094.63807499) \lineto(-417.97817816,1094.27933458) \curveto(-416.45947692,1095.95041262)(-416.03192071,1098.55552022)(-417.57355083,1100.47575978) \lineto(-418.04561605,1100.34530872) \lineto(-417.97817816,1098.58421946) \lineto(-418.85487071,1100.47575978) \curveto(-419.69636067,1100.43589394)(-418.89978434,1098.11068212)(-419.52924959,1099.10602368) \curveto(-419.03128822,1100.46401918)(-420.64224449,1100.76536112)(-420.50709896,1099.33431303) \lineto(-420.87800735,1096.10564938) \lineto(-420.0013148,1097.34493442) \curveto(-420.06488176,1096.11725952)(-420.02356931,1094.72286818)(-420.94544524,1093.75753036) \lineto(-422.49651666,1093.75753036) \lineto(-420.64197474,1099.85611726) \curveto(-420.55886429,1100.33591625)(-420.92184197,1100.53707177)(-421.31635362,1100.6388236) \lineto(-422.96858188,1093.75753036) \lineto(-423.87899337,1093.72491759) \lineto(-425.59865951,1093.75753036) \lineto(-425.3626269,1097.89935141) \curveto(-425.6710878,1098.90369409)(-425.42418421,1100.4287974)(-426.40791417,1100.997564) \curveto(-426.0430752,1098.97165909)(-425.58517194,1096.31437107)(-426.07072473,1094.01843247) \lineto(-432.4773241,1091.99644109) \lineto(-438.58045297,1087.20236476) \lineto(-439.35598868,1088.27858597) \lineto(-438.9850803,1088.89822849) \lineto(-443.94176507,1093.10527507) \curveto(-444.2032892,1093.49597599)(-445.55083308,1094.1334903)(-445.02077128,1093.23572613) \lineto(-444.48126817,1092.84437296) \lineto(-445.42539861,1092.64869637) \lineto(-445.56027438,1092.19211768) \curveto(-444.13733494,1090.46494569)(-442.2612129,1088.77690901)(-440.50243278,1087.49587963) \curveto(-440.33208467,1087.82265953)(-440.73212622,1088.00176883)(-440.90706011,1088.21336045) \lineto(-442.59300731,1089.97444971) \curveto(-443.31432296,1090.65670874)(-444.45429302,1091.19912423)(-444.75101973,1092.12689215) \lineto(-441.98606631,1090.95283264) \lineto(-440.30011911,1088.47426256) \lineto(-440.16524334,1088.14813492) \curveto(-438.78951042,1087.43052365)(-438.78006912,1086.33486523)(-439.96292967,1085.40866273) \curveto(-441.44791197,1083.11272413)(-442.69955917,1080.70851115)(-443.33482408,1078.10340355) \lineto(-444.75101973,1078.88610989) \curveto(-445.9889096,1080.76982315)(-449.15876009,1080.68763898)(-451.22505698,1081.4299055) \lineto(-451.22505698,1081.10377785) \curveto(-448.56530668,1080.15370281)(-445.71807904,1079.47705318)(-443.57085668,1077.54898656) \lineto(-443.87432718,1076.1466377) \curveto(-446.79978277,1078.00426075)(-449.76974736,1079.94667698)(-453.01216101,1081.20161615) \lineto(-453.55166412,1080.94071403) \lineto(-450.44952127,1079.50575241) \curveto(-449.1258504,1079.01786546)(-448.72850636,1078.35452183)(-448.29150885,1077.54898656) \lineto(-448.29825264,1077.54898656) \closepath } } { \newrgbcolor{curcolor}{0.81176472 0.81176472 0.81176472} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.29825264,1077.54898656) \lineto(-454.09791101,1078.72304607) \lineto(-449.20866413,1077.19024615) \lineto(-444.69032563,1075.49438242) \lineto(-444.38685513,1075.85312282) \lineto(-443.88107097,1075.55960794) \curveto(-444.40924451,1071.32386213)(-443.4995074,1066.51152265)(-440.07083029,1063.59072349) \lineto(-442.36371849,1060.72080024) \lineto(-441.41958806,1062.54711504) \curveto(-441.54745029,1063.67434262)(-442.12336985,1062.87963478)(-442.5997511,1062.44927674) \curveto(-443.50233979,1062.7956243)(-442.20429532,1065.00220392)(-443.61131942,1063.75378731) \lineto(-443.94850886,1063.88423837) \lineto(-443.07181631,1065.90622975) \lineto(-445.16239084,1064.53649365) \curveto(-444.52807007,1065.49413486)(-443.67875731,1066.37976708)(-444.42057407,1067.47164243) \lineto(-446.24139705,1066.62371056) \lineto(-445.22982873,1068.51525088) \lineto(-445.46586134,1068.6783147) \curveto(-446.56482916,1067.84708057)(-446.05823575,1069.92138282)(-445.90420761,1070.47201673) \lineto(-447.85990637,1070.14588909) \lineto(-446.67974332,1071.15688478) \lineto(-447.08437065,1071.15688478) \lineto(-453.28865636,1069.5914721) \curveto(-454.42633353,1069.44667143)(-456.1196989,1069.7828438)(-456.79542654,1068.93921682) \curveto(-456.34831334,1068.67935831)(-455.57399151,1068.96944233)(-455.04204145,1069.06966787) \lineto(-453.05262375,1069.16750616) \lineto(-454.67113306,1068.58047641) \lineto(-456.12104766,1068.02605942) \lineto(-448.60172313,1069.55885933) \lineto(-449.78188618,1068.93921682) \lineto(-454.73857095,1066.9498382) \lineto(-454.60369517,1066.10190633) \lineto(-448.87147469,1067.8629956) \lineto(-455.311793,1065.15613617) \lineto(-450.89461133,1066.10190633) \lineto(-448.06222003,1067.21074031) \lineto(-448.19709581,1066.75416162) \curveto(-450.87033369,1065.46347886)(-453.94954766,1064.43213281)(-456.52567498,1063.59072349) \curveto(-455.7939739,1063.08731286)(-454.66304052,1063.76722377)(-453.82815946,1063.98207666) \lineto(-450.489984,1065.18874893) \lineto(-446.84833805,1066.81938714) \curveto(-449.71175077,1064.27559154)(-453.63798462,1063.45244537)(-457.03145914,1061.86224699) \lineto(-457.03145914,1061.40566829) \lineto(-453.45725108,1062.64495333) \lineto(-452.24336909,1062.64495333) \lineto(-455.8512961,1060.32944707) \curveto(-454.13432747,1059.90613339)(-452.15435108,1061.61530314)(-450.45626506,1062.28621292) \lineto(-448.87147469,1063.23198308) \lineto(-447.25296537,1064.07991495) \lineto(-452.44568276,1060.62296195) \curveto(-451.92438788,1060.27361402)(-451.27428664,1060.95000275)(-450.72601661,1061.11215341) \lineto(-447.52271693,1062.90585544) \lineto(-452.58055853,1059.77503008) \lineto(-455.27807405,1058.40529399) \lineto(-449.41097779,1060.68818748) \curveto(-449.53838145,1060.52003607)(-449.58038177,1060.13311823)(-449.27610202,1060.10115772) \lineto(-448.06222003,1060.42728536) \curveto(-448.37014143,1059.57165688)(-449.40949416,1059.26131382)(-450.15279456,1058.73142163) \lineto(-454.06419207,1056.44852813) \curveto(-451.77939642,1056.89741022)(-449.73602841,1058.41833909)(-447.75874953,1059.67719179) \lineto(-447.25296537,1059.90548114) \curveto(-448.88361351,1057.97219648)(-450.84335853,1056.42113341)(-453.25493741,1055.33969415) \lineto(-453.25493741,1055.01356651) \curveto(-452.89185182,1054.90154819)(-452.5016562,1055.02237717)(-452.24336909,1055.27446862) \lineto(-450.22023245,1056.44852813) \lineto(-448.60172313,1057.42691106) \curveto(-448.46347546,1056.57036942)(-447.51529876,1057.49894613)(-447.1180896,1057.68781317) \lineto(-452.71543431,1054.16563464) \lineto(-452.71543431,1053.70905594) \lineto(-451.13064394,1054.45914952) \lineto(-449.24238307,1055.50275797) \lineto(-446.54486755,1057.06817065) \curveto(-445.35607246,1057.92353823)(-445.70229858,1056.88149519)(-446.64602438,1056.51375366) \lineto(-451.77130387,1053.31770277) \curveto(-448.95644643,1054.34761387)(-445.87318618,1055.94107352)(-443.88107097,1058.2096174) \curveto(-444.16795175,1058.53965857)(-443.44609659,1058.83760879)(-443.20669209,1058.86187268) \curveto(-444.56623991,1055.50014895)(-448.72985512,1054.04561967)(-451.77130387,1052.27409432) \curveto(-453.11035058,1053.59947706)(-453.86592468,1055.22098369)(-454.80600884,1056.77465578) \curveto(-456.10675082,1058.3583316)(-456.89118834,1060.2707441)(-457.70583802,1062.05792357) \curveto(-461.72918243,1075.76832963)(-455.66651629,1092.64869637)(-441.58818278,1098.71467051) \curveto(-440.24603393,1099.60369446)(-438.73960638,1100.13006448)(-437.23843899,1100.6388236) \curveto(-433.04784863,1101.97072889)(-428.37170547,1102.85779607)(-423.88573716,1102.07378522) \curveto(-419.00728033,1102.1396891)(-413.93190488,1101.27764242)(-410.08794526,1098.06241523) \lineto(-407.15439712,1096.59484084) \curveto(-405.66132228,1096.28749815)(-404.21140769,1096.48488364)(-402.73721546,1096.82313019) \curveto(-404.19657135,1093.40400799)(-409.22878656,1093.281384)(-412.51570923,1093.36617719) \lineto(-411.90876823,1093.75753036) \curveto(-410.98257628,1094.38017325)(-411.41633678,1095.98172087)(-411.36926513,1097.0840323) \lineto(-412.1110819,1097.01880677) \curveto(-412.45933115,1098.43159172)(-413.75926388,1097.69219513)(-414.67372164,1097.9971897) \curveto(-414.65242476,1096.57396867)(-414.74790332,1094.87549591)(-415.41553841,1093.49662824) \lineto(-415.92132257,1093.46401548) \curveto(-416.30531391,1093.35925024)(-416.88406586,1093.54736066)(-416.35966885,1093.88798141) \curveto(-416.38799276,1094.82383729)(-415.92037844,1095.55905945)(-415.51669525,1096.33393873) \lineto(-415.55041419,1098.38854287) \lineto(-416.19107413,1099.33431303) \lineto(-416.89917195,1093.6270793) \lineto(-419.42809275,1093.72491759) \lineto(-419.56296853,1095.68168344) \lineto(-419.56296853,1096.59484084) \curveto(-419.41433542,1097.13216874)(-419.3927553,1097.69167333)(-418.78743282,1097.73628759) \lineto(-418.75371387,1096.20348767) \curveto(-418.99783903,1095.76269355)(-419.06878369,1094.14888353)(-418.48396232,1095.15987922) \lineto(-418.34908654,1095.68168344) \curveto(-418.03010533,1097.45973135)(-417.43597754,1095.28876486)(-418.21421077,1094.63807499) \lineto(-417.97817816,1094.27933458) \curveto(-416.45947692,1095.95041262)(-416.03192071,1098.55552022)(-417.57355083,1100.47575978) \lineto(-418.04561605,1100.34530872) \lineto(-417.97817816,1098.58421946) \lineto(-418.85487071,1100.47575978) \curveto(-419.69636067,1100.43589394)(-418.89978434,1098.11068212)(-419.52924959,1099.10602368) \curveto(-419.03128822,1100.46401918)(-420.64224449,1100.76536112)(-420.50709896,1099.33431303) \lineto(-420.87800735,1096.10564938) \lineto(-420.0013148,1097.34493442) \curveto(-420.06488176,1096.11725952)(-420.02356931,1094.72286818)(-420.94544524,1093.75753036) \lineto(-422.49651666,1093.75753036) \lineto(-420.64197474,1099.85611726) \curveto(-420.55886429,1100.33591625)(-420.92184197,1100.53707177)(-421.31635362,1100.6388236) \lineto(-422.96858188,1093.75753036) \lineto(-423.87899337,1093.72491759) \lineto(-425.59865951,1093.75753036) \lineto(-425.3626269,1097.89935141) \curveto(-425.6710878,1098.90369409)(-425.42418421,1100.4287974)(-426.40791417,1100.997564) \curveto(-426.0430752,1098.97165909)(-425.58517194,1096.31437107)(-426.07072473,1094.01843247) \lineto(-432.4773241,1091.99644109) \lineto(-438.58045297,1087.20236476) \lineto(-439.35598868,1088.27858597) \lineto(-438.9850803,1088.89822849) \lineto(-443.94176507,1093.10527507) \curveto(-444.2032892,1093.49597599)(-445.55083308,1094.1334903)(-445.02077128,1093.23572613) \lineto(-444.48126817,1092.84437296) \lineto(-445.42539861,1092.64869637) \lineto(-445.56027438,1092.19211768) \curveto(-444.13733494,1090.46494569)(-442.2612129,1088.77690901)(-440.50243278,1087.49587963) \curveto(-440.33208467,1087.82265953)(-440.73212622,1088.00176883)(-440.90706011,1088.21336045) \lineto(-442.59300731,1089.97444971) \curveto(-443.31432296,1090.65670874)(-444.45429302,1091.19912423)(-444.75101973,1092.12689215) \lineto(-441.98606631,1090.95283264) \lineto(-440.30011911,1088.47426256) \lineto(-440.16524334,1088.14813492) \curveto(-438.78951042,1087.43052365)(-438.78006912,1086.33486523)(-439.96292967,1085.40866273) \curveto(-441.44791197,1083.11272413)(-442.69955917,1080.70851115)(-443.33482408,1078.10340355) \lineto(-444.75101973,1078.88610989) \curveto(-445.9889096,1080.76982315)(-449.15876009,1080.68763898)(-451.22505698,1081.4299055) \lineto(-451.22505698,1081.10377785) \curveto(-448.56530668,1080.15370281)(-445.71807904,1079.47705318)(-443.57085668,1077.54898656) \lineto(-443.87432718,1076.1466377) \curveto(-446.79978277,1078.00426075)(-449.76974736,1079.94667698)(-453.01216101,1081.20161615) \lineto(-453.55166412,1080.94071403) \lineto(-450.44952127,1079.50575241) \curveto(-449.1258504,1079.01786546)(-448.72850636,1078.35452183)(-448.29150885,1077.54898656) \lineto(-448.29825264,1077.54898656) \closepath } } { \newrgbcolor{curcolor}{0.9137255 0.9137255 0.9137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-331.49583049,1078.72304607) \curveto(-328.89137926,1079.66920758)(-325.95783113,1080.73981941)(-322.9986566,1080.28845875) \lineto(-322.49287244,1080.45152257) \lineto(-324.3811333,1081.29945444) \lineto(-324.71832274,1081.4299055) \lineto(-322.49287244,1081.62558208) \lineto(-322.49287244,1081.95170972) \lineto(-324.9880743,1082.27783737) \lineto(-324.92063641,1082.40828842) \curveto(-325.23894324,1082.92109153)(-324.94866359,1082.95135617)(-324.34741436,1082.89747988) \lineto(-322.22312088,1083.06054371) \lineto(-328.09021715,1083.19099476) \lineto(-327.61815193,1083.32144582) \curveto(-327.4301351,1083.86320906)(-326.89265513,1083.86020868)(-326.370551,1083.81063728) \curveto(-325.24690091,1083.93069139)(-323.96706467,1084.17798746)(-322.86378082,1083.94108834) \lineto(-322.62774821,1084.10415216) \lineto(-324.71832274,1084.62595639) \curveto(-324.55323479,1084.74513647)(-323.57929681,1084.73767467)(-324.11138175,1085.21298614) \lineto(-325.5275774,1085.40866273) \curveto(-326.05399755,1085.97221129)(-324.99185082,1085.84254294)(-324.71832274,1085.99569248) \lineto(-323.8416302,1086.19136907) \lineto(-324.34741436,1086.55010947) \lineto(-329.06806652,1086.02830525) \lineto(-329.57385068,1086.06091801) \lineto(-326.10079945,1087.59371793) \lineto(-326.370551,1087.85462004) \lineto(-330.24822957,1086.45227118) \curveto(-328.92145656,1087.46731085)(-327.2040833,1088.09986803)(-325.59501529,1088.53948809) \lineto(-326.77517833,1089.02867955) \lineto(-325.86476684,1089.58309654) \lineto(-326.20195628,1090.56147947) \lineto(-325.59501529,1090.95283264) \lineto(-328.22509292,1090.88760711) \curveto(-327.84285497,1091.20316822)(-325.9618774,1091.32983619)(-327.04492988,1092.02905386) \curveto(-326.69034147,1092.22446954)(-326.50192001,1092.52489832)(-327.01121094,1092.7139219) \curveto(-326.82777988,1092.95343004)(-326.89640468,1093.29482046)(-327.28096249,1093.23572613) \lineto(-327.17980566,1094.24672182) \lineto(-327.34840038,1094.47501117) \lineto(-329.2029423,1094.11627076) \lineto(-331.19236,1094.40978564) \lineto(-328.69715814,1094.93158987) \lineto(-328.69715814,1095.25771751) \lineto(-329.57385068,1095.38816857) \curveto(-329.16099593,1095.58488876)(-328.13067988,1095.33579247)(-328.29253081,1096.04042385) \lineto(-330.68657584,1095.68168344) \lineto(-331.22607894,1095.68168344) \lineto(-331.32723577,1095.77952174) \lineto(-329.10178547,1096.49700255) \lineto(-329.06806652,1096.7252919) \lineto(-330.68657584,1096.59484084) \lineto(-332.54111776,1096.75790466) \lineto(-332.54111776,1096.95358125) \curveto(-331.56515664,1096.80760651)(-332.08092161,1097.52091289)(-332.54111776,1097.73628759) \lineto(-332.20392832,1097.93196417) \lineto(-332.3388041,1098.38854287) \curveto(-333.03071683,1098.1088558)(-333.98293981,1097.56644031)(-334.49681651,1098.38854287) \lineto(-334.83400595,1098.4537684) \curveto(-334.36113148,1098.51926787)(-333.63765782,1098.74663102)(-333.82243763,1099.43215132) \lineto(-338.34077613,1099.23647474) \lineto(-337.46408359,1099.69305344) \curveto(-337.96973287,1100.11767163)(-338.64006548,1099.64386034)(-339.18374973,1099.59521515) \lineto(-338.81284135,1100.08440661) \lineto(-341.61151371,1099.33431303) \lineto(-340.70110222,1099.88873002) \lineto(-340.02672334,1100.41053425) \lineto(-340.26275594,1100.6388236) \lineto(-343.87068296,1098.58421946) \lineto(-343.23002302,1099.46476409) \lineto(-342.58936308,1100.21485766) \curveto(-343.00329684,1100.34130387)(-343.4957283,1100.35287488)(-343.87068296,1100.08440661) \lineto(-344.34274817,1099.88873002) \lineto(-345.28687861,1099.23647474) \curveto(-345.98607463,1099.5335118)(-346.59382488,1099.64883053)(-347.2762963,1099.07341092) \lineto(-347.68092363,1099.46476409) \lineto(-351.15397487,1097.9971897) \curveto(-351.38784946,1098.06887256)(-351.74446102,1098.83638135)(-351.28885064,1099.17124921) \lineto(-347.2762963,1100.6388236) \curveto(-344.89573885,1101.54115356)(-342.34388917,1102.30859712)(-339.72325284,1101.68243205) \curveto(-337.26446744,1102.02590969)(-334.94595285,1100.67652395)(-332.81086931,1099.62782791) \curveto(-329.90294758,1098.6763179)(-327.68828733,1096.61701752)(-325.86476684,1094.21410906) \curveto(-321.36396219,1087.53762397)(-321.08476933,1079.68186134)(-321.24527151,1071.67216645) \lineto(-321.91965039,1067.6281837) \lineto(-323.8416302,1062.31230313) \lineto(-325.19038796,1064.46474557) \lineto(-326.26939417,1065.37790297) \curveto(-326.96805069,1065.58766827)(-327.00406252,1066.1664796)(-327.01121094,1066.68241353) \curveto(-325.84291696,1066.32797801)(-324.69809138,1065.6408923)(-323.67303548,1064.8887115) \lineto(-323.30212709,1065.05177533) \lineto(-324.17881964,1065.83448167) \lineto(-325.86476684,1066.81286459) \lineto(-327.95534137,1068.11737516) \lineto(-325.93220473,1067.72602199) \lineto(-325.59501529,1067.59557093) \lineto(-322.89749976,1066.09538378) \curveto(-322.81834117,1066.73681162)(-323.68787181,1066.98545134)(-324.07766281,1067.36728158) \curveto(-324.85265902,1067.89626062)(-326.53375069,1068.21338714)(-326.26939417,1069.29143467) \lineto(-326.74145939,1069.68278784) \lineto(-323.94278703,1068.54134109) \lineto(-322.86378082,1067.75863475) \lineto(-322.22312088,1067.5303454) \lineto(-322.22312088,1067.85647304) \curveto(-323.31871681,1068.65731208)(-324.65627989,1069.32143841)(-325.5275774,1070.46549418) \lineto(-324.65088485,1070.33504312) \curveto(-324.4457388,1070.15123758)(-324.08642973,1069.69452843)(-323.8416302,1070.00891548) \lineto(-325.29154479,1071.28081328) \lineto(-327.14608671,1072.29180897) \curveto(-325.39000411,1071.96424637)(-323.65550163,1070.88554658)(-322.86378082,1069.32404743) \curveto(-322.50595539,1069.52702928)(-322.8875864,1069.97852038)(-322.9986566,1070.23720483) \lineto(-323.36956498,1072.09613239) \lineto(-324.17881964,1072.68316214) \lineto(-321.548742,1071.57432816) \curveto(-321.39390461,1072.00612116)(-322.04022933,1072.12561433)(-322.32427772,1072.32442174) \lineto(-323.16725132,1072.8136132) \curveto(-323.85929892,1072.92377912)(-324.55782057,1073.41994971)(-325.25782585,1073.13974084) \lineto(-327.28096249,1074.24857482) \lineto(-324.34741436,1073.6289323) \curveto(-323.55340066,1073.93379642)(-322.72216126,1073.81756453)(-322.29055877,1072.87883873) \lineto(-321.81849356,1072.74838767) \curveto(-321.98614415,1073.87209307)(-323.44509542,1074.13247338)(-324.17881964,1074.63992799) \lineto(-322.62774821,1074.31380035) \curveto(-322.74472597,1074.75328996)(-322.84692135,1075.34814678)(-323.36956498,1075.55308539) \lineto(-322.35799666,1075.55308539) \curveto(-322.1601339,1075.4118069)(-321.63749026,1075.35780016)(-321.51502306,1075.58569816) \curveto(-323.26705939,1076.16920573)(-325.18769044,1076.76380165)(-327.17980566,1076.75975767) \lineto(-327.85418454,1077.15111084) \lineto(-333.88987552,1076.7271449) \lineto(-333.95731341,1076.14011515) \lineto(-335.64326061,1075.61831092) \lineto(-335.64326061,1076.85759596) \lineto(-331.52954944,1078.096881) \lineto(-326.50542678,1078.71652352) \curveto(-325.1662452,1078.68191485)(-323.74856591,1078.74130922)(-322.59402927,1079.10787669) \lineto(-323.40328393,1079.49922986) \lineto(-331.49583049,1078.71652352) \lineto(-331.49583049,1078.72304607) \closepath } } { \newrgbcolor{curcolor}{0.9137255 0.9137255 0.9137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-331.49583049,1078.72304607) \curveto(-328.89137926,1079.66920758)(-325.95783113,1080.73981941)(-322.9986566,1080.28845875) \lineto(-322.49287244,1080.45152257) \lineto(-324.3811333,1081.29945444) \lineto(-324.71832274,1081.4299055) \lineto(-322.49287244,1081.62558208) \lineto(-322.49287244,1081.95170972) \lineto(-324.9880743,1082.27783737) \lineto(-324.92063641,1082.40828842) \curveto(-325.23894324,1082.92109153)(-324.94866359,1082.95135617)(-324.34741436,1082.89747988) \lineto(-322.22312088,1083.06054371) \lineto(-328.09021715,1083.19099476) \lineto(-327.61815193,1083.32144582) \curveto(-327.4301351,1083.86320906)(-326.89265513,1083.86020868)(-326.370551,1083.81063728) \curveto(-325.24690091,1083.93069139)(-323.96706467,1084.17798746)(-322.86378082,1083.94108834) \lineto(-322.62774821,1084.10415216) \lineto(-324.71832274,1084.62595639) \curveto(-324.55323479,1084.74513647)(-323.57929681,1084.73767467)(-324.11138175,1085.21298614) \lineto(-325.5275774,1085.40866273) \curveto(-326.05399755,1085.97221129)(-324.99185082,1085.84254294)(-324.71832274,1085.99569248) \lineto(-323.8416302,1086.19136907) \lineto(-324.34741436,1086.55010947) \lineto(-329.06806652,1086.02830525) \lineto(-329.57385068,1086.06091801) \lineto(-326.10079945,1087.59371793) \lineto(-326.370551,1087.85462004) \lineto(-330.24822957,1086.45227118) \curveto(-328.92145656,1087.46731085)(-327.2040833,1088.09986803)(-325.59501529,1088.53948809) \lineto(-326.77517833,1089.02867955) \lineto(-325.86476684,1089.58309654) \lineto(-326.20195628,1090.56147947) \lineto(-325.59501529,1090.95283264) \lineto(-328.22509292,1090.88760711) \curveto(-327.84285497,1091.20316822)(-325.9618774,1091.32983619)(-327.04492988,1092.02905386) \curveto(-326.69034147,1092.22446954)(-326.50192001,1092.52489832)(-327.01121094,1092.7139219) \curveto(-326.82777988,1092.95343004)(-326.89640468,1093.29482046)(-327.28096249,1093.23572613) \lineto(-327.17980566,1094.24672182) \lineto(-327.34840038,1094.47501117) \lineto(-329.2029423,1094.11627076) \lineto(-331.19236,1094.40978564) \lineto(-328.69715814,1094.93158987) \lineto(-328.69715814,1095.25771751) \lineto(-329.57385068,1095.38816857) \curveto(-329.16099593,1095.58488876)(-328.13067988,1095.33579247)(-328.29253081,1096.04042385) \lineto(-330.68657584,1095.68168344) \lineto(-331.22607894,1095.68168344) \lineto(-331.32723577,1095.77952174) \lineto(-329.10178547,1096.49700255) \lineto(-329.06806652,1096.7252919) \lineto(-330.68657584,1096.59484084) \lineto(-332.54111776,1096.75790466) \lineto(-332.54111776,1096.95358125) \curveto(-331.56515664,1096.80760651)(-332.08092161,1097.52091289)(-332.54111776,1097.73628759) \lineto(-332.20392832,1097.93196417) \lineto(-332.3388041,1098.38854287) \curveto(-333.03071683,1098.1088558)(-333.98293981,1097.56644031)(-334.49681651,1098.38854287) \lineto(-334.83400595,1098.4537684) \curveto(-334.36113148,1098.51926787)(-333.63765782,1098.74663102)(-333.82243763,1099.43215132) \lineto(-338.34077613,1099.23647474) \lineto(-337.46408359,1099.69305344) \curveto(-337.96973287,1100.11767163)(-338.64006548,1099.64386034)(-339.18374973,1099.59521515) \lineto(-338.81284135,1100.08440661) \lineto(-341.61151371,1099.33431303) \lineto(-340.70110222,1099.88873002) \lineto(-340.02672334,1100.41053425) \lineto(-340.26275594,1100.6388236) \lineto(-343.87068296,1098.58421946) \lineto(-343.23002302,1099.46476409) \lineto(-342.58936308,1100.21485766) \curveto(-343.00329684,1100.34130387)(-343.4957283,1100.35287488)(-343.87068296,1100.08440661) \lineto(-344.34274817,1099.88873002) \lineto(-345.28687861,1099.23647474) \curveto(-345.98607463,1099.5335118)(-346.59382488,1099.64883053)(-347.2762963,1099.07341092) \lineto(-347.68092363,1099.46476409) \lineto(-351.15397487,1097.9971897) \curveto(-351.38784946,1098.06887256)(-351.74446102,1098.83638135)(-351.28885064,1099.17124921) \lineto(-347.2762963,1100.6388236) \curveto(-344.89573885,1101.54115356)(-342.34388917,1102.30859712)(-339.72325284,1101.68243205) \curveto(-337.26446744,1102.02590969)(-334.94595285,1100.67652395)(-332.81086931,1099.62782791) \curveto(-329.90294758,1098.6763179)(-327.68828733,1096.61701752)(-325.86476684,1094.21410906) \curveto(-321.36396219,1087.53762397)(-321.08476933,1079.68186134)(-321.24527151,1071.67216645) \lineto(-321.91965039,1067.6281837) \lineto(-323.8416302,1062.31230313) \lineto(-325.19038796,1064.46474557) \lineto(-326.26939417,1065.37790297) \curveto(-326.96805069,1065.58766827)(-327.00406252,1066.1664796)(-327.01121094,1066.68241353) \curveto(-325.84291696,1066.32797801)(-324.69809138,1065.6408923)(-323.67303548,1064.8887115) \lineto(-323.30212709,1065.05177533) \lineto(-324.17881964,1065.83448167) \lineto(-325.86476684,1066.81286459) \lineto(-327.95534137,1068.11737516) \lineto(-325.93220473,1067.72602199) \lineto(-325.59501529,1067.59557093) \lineto(-322.89749976,1066.09538378) \curveto(-322.81834117,1066.73681162)(-323.68787181,1066.98545134)(-324.07766281,1067.36728158) \curveto(-324.85265902,1067.89626062)(-326.53375069,1068.21338714)(-326.26939417,1069.29143467) \lineto(-326.74145939,1069.68278784) \lineto(-323.94278703,1068.54134109) \lineto(-322.86378082,1067.75863475) \lineto(-322.22312088,1067.5303454) \lineto(-322.22312088,1067.85647304) \curveto(-323.31871681,1068.65731208)(-324.65627989,1069.32143841)(-325.5275774,1070.46549418) \lineto(-324.65088485,1070.33504312) \curveto(-324.4457388,1070.15123758)(-324.08642973,1069.69452843)(-323.8416302,1070.00891548) \lineto(-325.29154479,1071.28081328) \lineto(-327.14608671,1072.29180897) \curveto(-325.39000411,1071.96424637)(-323.65550163,1070.88554658)(-322.86378082,1069.32404743) \curveto(-322.50595539,1069.52702928)(-322.8875864,1069.97852038)(-322.9986566,1070.23720483) \lineto(-323.36956498,1072.09613239) \lineto(-324.17881964,1072.68316214) \lineto(-321.548742,1071.57432816) \curveto(-321.39390461,1072.00612116)(-322.04022933,1072.12561433)(-322.32427772,1072.32442174) \lineto(-323.16725132,1072.8136132) \curveto(-323.85929892,1072.92377912)(-324.55782057,1073.41994971)(-325.25782585,1073.13974084) \lineto(-327.28096249,1074.24857482) \lineto(-324.34741436,1073.6289323) \curveto(-323.55340066,1073.93379642)(-322.72216126,1073.81756453)(-322.29055877,1072.87883873) \lineto(-321.81849356,1072.74838767) \curveto(-321.98614415,1073.87209307)(-323.44509542,1074.13247338)(-324.17881964,1074.63992799) \lineto(-322.62774821,1074.31380035) \curveto(-322.74472597,1074.75328996)(-322.84692135,1075.34814678)(-323.36956498,1075.55308539) \lineto(-322.35799666,1075.55308539) \curveto(-322.1601339,1075.4118069)(-321.63749026,1075.35780016)(-321.51502306,1075.58569816) \curveto(-323.26705939,1076.16920573)(-325.18769044,1076.76380165)(-327.17980566,1076.75975767) \lineto(-327.85418454,1077.15111084) \lineto(-333.88987552,1076.7271449) \lineto(-333.95731341,1076.14011515) \lineto(-335.64326061,1075.61831092) \lineto(-335.64326061,1076.85759596) \lineto(-331.52954944,1078.096881) \lineto(-326.50542678,1078.71652352) \curveto(-325.1662452,1078.68191485)(-323.74856591,1078.74130922)(-322.59402927,1079.10787669) \lineto(-323.40328393,1079.49922986) \lineto(-331.49583049,1078.71652352) \lineto(-331.49583049,1078.72304607) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-422.94160672,1100.89972571) \curveto(-423.19584756,1100.88148865)(-422.92276458,1101.14562595)(-422.94160672,1100.89972571) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-422.94160672,1100.89972571) \curveto(-423.19584756,1100.88148865)(-422.92276458,1101.14562595)(-422.94160672,1100.89972571) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-424.69499181,1100.89972571) \lineto(-424.4589592,1100.47575978) \lineto(-424.4589592,1100.41053425) \curveto(-424.78886535,1100.26547267)(-424.68096473,1100.73013934)(-424.69499181,1100.89972571) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-424.69499181,1100.89972571) \lineto(-424.4589592,1100.47575978) \lineto(-424.4589592,1100.41053425) \curveto(-424.78886535,1100.26547267)(-424.68096473,1100.73013934)(-424.69499181,1100.89972571) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-422.94160672,1100.89972571) \lineto(-422.84044989,1100.86711295) \lineto(-422.57069834,1099.75827897) \lineto(-422.773012,1099.75827897) \lineto(-422.94160672,1100.89972571) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-422.94160672,1100.89972571) \lineto(-422.84044989,1100.86711295) \lineto(-422.57069834,1099.75827897) \lineto(-422.773012,1099.75827897) \lineto(-422.94160672,1100.89972571) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-430.22489863,1100.6388236) \curveto(-430.47913947,1100.62058654)(-430.20605649,1100.88472384)(-430.22489863,1100.6388236) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-430.22489863,1100.6388236) \curveto(-430.47913947,1100.62058654)(-430.20605649,1100.88472384)(-430.22489863,1100.6388236) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-428.7412651,1100.76927466) \curveto(-428.49390292,1100.85606374)(-428.39611799,1100.58259919)(-428.50523249,1100.41053425) \lineto(-428.7412651,1100.76927466) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-428.7412651,1100.76927466) \curveto(-428.49390292,1100.85606374)(-428.39611799,1100.58259919)(-428.50523249,1100.41053425) \lineto(-428.7412651,1100.76927466) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-427.66225889,1100.76927466) \curveto(-427.38873081,1100.83478718)(-427.14743805,1100.51385149)(-427.2913505,1100.28008319) \lineto(-427.35878839,1100.28008319) \lineto(-427.66225889,1100.76927466) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-427.66225889,1100.76927466) \curveto(-427.38873081,1100.83478718)(-427.14743805,1100.51385149)(-427.2913505,1100.28008319) \lineto(-427.35878839,1100.28008319) \lineto(-427.66225889,1100.76927466) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.95514708,1100.24747043) \lineto(-430.22489863,1100.6388236) \lineto(-429.95514708,1100.24747043) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.95514708,1100.24747043) \lineto(-430.22489863,1100.6388236) \lineto(-429.95514708,1100.24747043) \closepath } } { \newrgbcolor{curcolor}{0.01960784 0.01960784 0.01960784} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-430.89927752,1100.37792149) \curveto(-431.15351835,1100.35968443)(-430.88043537,1100.62382173)(-430.89927752,1100.37792149) \closepath } } { \newrgbcolor{curcolor}{0.01960784 0.01960784 0.01960784} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-430.89927752,1100.37792149) \curveto(-431.15351835,1100.35968443)(-430.88043537,1100.62382173)(-430.89927752,1100.37792149) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-430.62952596,1099.98656832) \lineto(-430.89927752,1100.37792149) \lineto(-430.62952596,1099.98656832) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-430.62952596,1099.98656832) \lineto(-430.89927752,1100.37792149) \lineto(-430.62952596,1099.98656832) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-423.34623405,1100.37792149) \lineto(-423.24507722,1100.34530872) \lineto(-423.24507722,1098.97557263) \lineto(-423.31251511,1098.97557263) \lineto(-423.44739088,1100.21485766) \lineto(-423.34623405,1100.37792149) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-423.34623405,1100.37792149) \lineto(-423.24507722,1100.34530872) \lineto(-423.24507722,1098.97557263) \lineto(-423.31251511,1098.97557263) \lineto(-423.44739088,1100.21485766) \lineto(-423.34623405,1100.37792149) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.95514708,1100.24747043) \lineto(-429.71911447,1099.88873002) \lineto(-429.95514708,1100.24747043) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.95514708,1100.24747043) \lineto(-429.71911447,1099.88873002) \lineto(-429.95514708,1100.24747043) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-428.47151354,1100.24747043) \lineto(-428.23548094,1099.62782791) \lineto(-428.30291882,1099.62782791) \lineto(-428.47151354,1100.24747043) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-428.47151354,1100.24747043) \lineto(-428.23548094,1099.62782791) \lineto(-428.30291882,1099.62782791) \lineto(-428.47151354,1100.24747043) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.97828372,1100.11701937) \curveto(-431.73092155,1100.20380846)(-431.63313661,1099.93034391)(-431.74225112,1099.75827897) \lineto(-431.97828372,1100.11701937) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.97828372,1100.11701937) \curveto(-431.73092155,1100.20380846)(-431.63313661,1099.93034391)(-431.74225112,1099.75827897) \lineto(-431.97828372,1100.11701937) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-435.35017813,1099.7256662) \lineto(-435.45133496,1099.95395555) \lineto(-435.35017813,1099.7256662) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-435.35017813,1099.7256662) \lineto(-435.45133496,1099.95395555) \lineto(-435.35017813,1099.7256662) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-430.49465019,1099.7256662) \lineto(-430.62952596,1099.98656832) \lineto(-430.49465019,1099.7256662) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-430.49465019,1099.7256662) \lineto(-430.62952596,1099.98656832) \lineto(-430.49465019,1099.7256662) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-426.85300423,1099.07341092) \lineto(-427.25763156,1099.85611726) \lineto(-427.22391262,1099.95395555) \lineto(-426.98788001,1099.59521515) \lineto(-426.85300423,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-426.85300423,1099.07341092) \lineto(-427.25763156,1099.85611726) \lineto(-427.22391262,1099.95395555) \lineto(-426.98788001,1099.59521515) \lineto(-426.85300423,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-424.56011604,1099.98656832) \lineto(-424.4589592,1099.95395555) \lineto(-424.32408343,1098.84512157) \lineto(-424.52639709,1098.84512157) \lineto(-424.56011604,1099.98656832) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-424.56011604,1099.98656832) \lineto(-424.4589592,1099.95395555) \lineto(-424.32408343,1098.84512157) \lineto(-424.52639709,1098.84512157) \lineto(-424.56011604,1099.98656832) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-434.00142037,1099.07341092) \lineto(-434.4060477,1099.20386197) \lineto(-434.27117192,1098.55160669) \lineto(-434.23745298,1097.80151312) \lineto(-434.6420803,1099.56260238) \lineto(-434.27117192,1099.85611726) \lineto(-434.13629614,1099.7256662) \lineto(-434.00142037,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-434.00142037,1099.07341092) \lineto(-434.4060477,1099.20386197) \lineto(-434.27117192,1098.55160669) \lineto(-434.23745298,1097.80151312) \lineto(-434.6420803,1099.56260238) \lineto(-434.27117192,1099.85611726) \lineto(-434.13629614,1099.7256662) \lineto(-434.00142037,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-435.35017813,1099.7256662) \lineto(-435.11414552,1099.30170027) \lineto(-435.11414552,1099.23647474) \curveto(-435.44405167,1099.09141316)(-435.33615105,1099.55607983)(-435.35017813,1099.7256662) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-435.35017813,1099.7256662) \lineto(-435.11414552,1099.30170027) \lineto(-435.11414552,1099.23647474) \curveto(-435.44405167,1099.09141316)(-435.33615105,1099.55607983)(-435.35017813,1099.7256662) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-432.65266261,1097.89935141) \lineto(-432.88869521,1098.84512157) \lineto(-433.15844677,1099.69305344) \lineto(-432.9561331,1099.69305344) \lineto(-432.75381944,1099.10602368) \lineto(-432.55150577,1099.04079815) \lineto(-432.1131595,1097.37754718) \lineto(-431.97828372,1097.11664507) \lineto(-432.21431633,1094.86636434) \lineto(-432.14687844,1094.67068775) \lineto(-432.24803528,1094.63807499) \lineto(-432.38291105,1094.76852605) \lineto(-432.38291105,1096.46438978) \lineto(-432.55150577,1097.86673864) \lineto(-432.65266261,1097.89935141) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-432.65266261,1097.89935141) \lineto(-432.88869521,1098.84512157) \lineto(-433.15844677,1099.69305344) \lineto(-432.9561331,1099.69305344) \lineto(-432.75381944,1099.10602368) \lineto(-432.55150577,1099.04079815) \lineto(-432.1131595,1097.37754718) \lineto(-431.97828372,1097.11664507) \lineto(-432.21431633,1094.86636434) \lineto(-432.14687844,1094.67068775) \lineto(-432.24803528,1094.63807499) \lineto(-432.38291105,1094.76852605) \lineto(-432.38291105,1096.46438978) \lineto(-432.55150577,1097.86673864) \lineto(-432.65266261,1097.89935141) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-430.22489863,1099.20386197) \lineto(-430.49465019,1099.7256662) \lineto(-430.22489863,1099.20386197) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-430.22489863,1099.20386197) \lineto(-430.49465019,1099.7256662) \lineto(-430.22489863,1099.20386197) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.41564398,1099.20386197) \lineto(-429.65167659,1099.69305344) \lineto(-429.41564398,1099.20386197) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.41564398,1099.20386197) \lineto(-429.65167659,1099.69305344) \lineto(-429.41564398,1099.20386197) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.5736564,1098.94295986) \lineto(-431.67481323,1099.56260238) \lineto(-431.5736564,1098.94295986) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.5736564,1098.94295986) \lineto(-431.67481323,1099.56260238) \lineto(-431.5736564,1098.94295986) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-422.80673095,1099.59521515) \lineto(-422.57069834,1099.49737685) \lineto(-422.80673095,1099.59521515) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-422.80673095,1099.59521515) \lineto(-422.57069834,1099.49737685) \lineto(-422.80673095,1099.59521515) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-428.06688622,1099.07341092) \lineto(-428.16804305,1099.43215132) \lineto(-428.06688622,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-428.06688622,1099.07341092) \lineto(-428.16804305,1099.43215132) \lineto(-428.06688622,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.59607846 0.59607846 0.59607846} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-341.61151371,1099.33431303) \lineto(-341.98242209,1099.04079815) \lineto(-342.72423886,1098.4537684) \lineto(-342.92655252,1098.4537684) \lineto(-342.31961153,1098.97557263) \lineto(-341.61151371,1099.33431303) \closepath } } { \newrgbcolor{curcolor}{0.59607846 0.59607846 0.59607846} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-341.61151371,1099.33431303) \lineto(-341.98242209,1099.04079815) \lineto(-342.72423886,1098.4537684) \lineto(-342.92655252,1098.4537684) \lineto(-342.31961153,1098.97557263) \lineto(-341.61151371,1099.33431303) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.95514708,1098.55160669) \lineto(-430.22489863,1099.20386197) \lineto(-429.95514708,1098.55160669) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.95514708,1098.55160669) \lineto(-430.22489863,1099.20386197) \lineto(-429.95514708,1098.55160669) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.2807682,1098.94295986) \lineto(-429.41564398,1099.20386197) \lineto(-429.2807682,1098.94295986) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.2807682,1098.94295986) \lineto(-429.41564398,1099.20386197) \lineto(-429.2807682,1098.94295986) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-422.67185517,1099.20386197) \curveto(-422.41761433,1099.22209903)(-422.69069732,1098.95796173)(-422.67185517,1099.20386197) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-422.67185517,1099.20386197) \curveto(-422.41761433,1099.22209903)(-422.69069732,1098.95796173)(-422.67185517,1099.20386197) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-435.35017813,1099.07341092) \lineto(-434.97926974,1098.38854287) \lineto(-434.97926974,1098.32331734) \lineto(-435.31645918,1098.97557263) \lineto(-435.35017813,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-435.35017813,1099.07341092) \lineto(-434.97926974,1098.38854287) \lineto(-434.97926974,1098.32331734) \lineto(-435.31645918,1098.97557263) \lineto(-435.35017813,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-433.86654459,1098.8125088) \lineto(-434.00142037,1099.07341092) \lineto(-433.86654459,1098.8125088) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-433.86654459,1098.8125088) \lineto(-434.00142037,1099.07341092) \lineto(-433.86654459,1098.8125088) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-428.06688622,1099.07341092) \lineto(-427.96572938,1098.58421946) \lineto(-428.06688622,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-428.06688622,1099.07341092) \lineto(-427.96572938,1098.58421946) \lineto(-428.06688622,1099.07341092) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-426.71812845,1098.55160669) \lineto(-426.85300423,1099.07341092) \lineto(-426.71812845,1098.55160669) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-426.71812845,1098.55160669) \lineto(-426.85300423,1099.07341092) \lineto(-426.71812845,1098.55160669) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.43878062,1098.29070458) \lineto(-431.5736564,1098.94295986) \lineto(-431.43878062,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.43878062,1098.29070458) \lineto(-431.5736564,1098.94295986) \lineto(-431.43878062,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.2807682,1098.94295986) \lineto(-429.04473559,1098.32331734) \lineto(-429.11217348,1098.32331734) \lineto(-429.2807682,1098.94295986) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.2807682,1098.94295986) \lineto(-429.04473559,1098.32331734) \lineto(-429.11217348,1098.32331734) \lineto(-429.2807682,1098.94295986) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-422.67185517,1098.94295986) \lineto(-422.57069834,1098.19286629) \lineto(-422.63813623,1098.19286629) \lineto(-422.67185517,1098.94295986) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-422.67185517,1098.94295986) \lineto(-422.57069834,1098.19286629) \lineto(-422.63813623,1098.19286629) \lineto(-422.67185517,1098.94295986) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-433.59679304,1098.02980246) \lineto(-433.69794987,1098.06241523) \lineto(-433.86654459,1098.8125088) \lineto(-433.59679304,1098.02980246) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-433.59679304,1098.02980246) \lineto(-433.69794987,1098.06241523) \lineto(-433.86654459,1098.8125088) \lineto(-433.59679304,1098.02980246) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-423.34623405,1098.8125088) \lineto(-423.11020144,1098.77989604) \lineto(-423.11020144,1097.67106206) \lineto(-423.17763933,1097.67106206) \lineto(-423.34623405,1098.68205775) \lineto(-423.34623405,1098.8125088) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-423.34623405,1098.8125088) \lineto(-423.11020144,1098.77989604) \lineto(-423.11020144,1097.67106206) \lineto(-423.17763933,1097.67106206) \lineto(-423.34623405,1098.68205775) \lineto(-423.34623405,1098.8125088) \closepath } } { \newrgbcolor{curcolor}{0.87058824 0.87058824 0.87058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-339.45350129,1093.85536865) \lineto(-337.86871092,1094.083658) \curveto(-338.17218141,1093.4916711)(-338.68835101,1092.88194286)(-339.35234446,1092.45301979) \lineto(-340.16159911,1091.40941134) \curveto(-340.42851827,1091.109113)(-340.85216309,1090.7812895)(-340.7685401,1090.36580288) \lineto(-338.61052769,1092.38779426) \lineto(-336.78970471,1092.90959849) \lineto(-337.26176992,1092.2573432) \lineto(-338.20590036,1090.95283264) \curveto(-338.69887132,1090.35575815)(-339.6288398,1089.6274499)(-339.15003079,1088.93084126) \curveto(-337.35213669,1090.70758465)(-335.38969415,1092.81306471)(-332.74343142,1093.36617719) \lineto(-330.58541901,1093.82275589) \curveto(-333.69430565,1092.56272913)(-336.82746993,1090.51843062)(-338.77912241,1087.72416898) \curveto(-341.29050936,1090.54973887)(-345.07512364,1092.18820414)(-348.75992984,1092.94221125) \curveto(-353.3146848,1093.36043734)(-358.11761119,1092.22016465)(-362.21378851,1094.27933458) \curveto(-363.29778513,1095.052518)(-364.24097143,1096.09782231)(-364.50667671,1097.34493442) \lineto(-363.49510839,1097.0840323) \curveto(-361.2116615,1095.48861588)(-358.46693945,1096.35272368)(-356.0769407,1097.0840323) \lineto(-355.7734702,1096.59484084) \lineto(-356.6164438,1096.10564938) \curveto(-358.20528045,1095.72342778)(-359.65924131,1094.98416164)(-361.40453386,1095.12726645) \lineto(-361.70800435,1094.76852605) \curveto(-359.99238448,1094.33986387)(-358.2835084,1095.00946915)(-356.6164438,1095.38816857) \lineto(-357.29082268,1094.93158987) \lineto(-359.01048883,1094.11627076) \lineto(-356.81875747,1094.14888353) \lineto(-356.58272486,1094.11627076) \lineto(-353.31198729,1095.77952174) \lineto(-352.9410789,1095.55123239) \lineto(-350.34472021,1096.82313019) \lineto(-349.97381183,1096.59484084) \lineto(-352.43529474,1095.45339409) \lineto(-354.12124194,1094.5402367) \curveto(-352.47440872,1094.75730726)(-350.84510934,1095.43787042)(-349.40058978,1096.30132596) \lineto(-348.62505407,1096.07303661) \lineto(-344.7473755,1098.12764076) \lineto(-345.69150593,1094.80113881) \lineto(-346.09613326,1094.01843247) \curveto(-346.03071851,1093.54880867)(-345.33098298,1094.50892844)(-345.15200283,1094.80113881) \lineto(-344.41018606,1095.90997279) \curveto(-343.21680519,1097.14325708)(-341.80708358,1098.29853164)(-340.02672334,1098.38854287) \curveto(-341.31640551,1097.46586255)(-342.94543513,1096.65093479)(-343.80324507,1095.19249198) \curveto(-344.24873976,1094.51505964)(-344.73537156,1093.76013938)(-344.81481339,1092.97482402) \lineto(-344.57878078,1092.94221125) \curveto(-343.49599805,1096.16435235)(-339.89589383,1098.34158049)(-336.51995316,1098.77989604) \lineto(-339.15003079,1097.86673864) \lineto(-341.57779476,1096.30132596) \curveto(-342.60406454,1095.10913376)(-343.32983109,1093.36617719)(-342.96027147,1091.8986028) \lineto(-342.69051991,1092.42040703) \curveto(-342.87894137,1094.89375906)(-340.81439787,1096.64702126)(-338.64424663,1097.50799824) \lineto(-337.32920781,1097.73628759) \lineto(-339.21746868,1096.6274536) \lineto(-341.30804321,1094.73591328) \curveto(-342.1321342,1093.72204767)(-342.31947665,1092.26517027)(-341.98242209,1091.01805817) \lineto(-339.89184756,1093.10527507) \lineto(-339.45350129,1093.85536865) \closepath } } { \newrgbcolor{curcolor}{0.87058824 0.87058824 0.87058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-339.45350129,1093.85536865) \lineto(-337.86871092,1094.083658) \curveto(-338.17218141,1093.4916711)(-338.68835101,1092.88194286)(-339.35234446,1092.45301979) \lineto(-340.16159911,1091.40941134) \curveto(-340.42851827,1091.109113)(-340.85216309,1090.7812895)(-340.7685401,1090.36580288) \lineto(-338.61052769,1092.38779426) \lineto(-336.78970471,1092.90959849) \lineto(-337.26176992,1092.2573432) \lineto(-338.20590036,1090.95283264) \curveto(-338.69887132,1090.35575815)(-339.6288398,1089.6274499)(-339.15003079,1088.93084126) \curveto(-337.35213669,1090.70758465)(-335.38969415,1092.81306471)(-332.74343142,1093.36617719) \lineto(-330.58541901,1093.82275589) \curveto(-333.69430565,1092.56272913)(-336.82746993,1090.51843062)(-338.77912241,1087.72416898) \curveto(-341.29050936,1090.54973887)(-345.07512364,1092.18820414)(-348.75992984,1092.94221125) \curveto(-353.3146848,1093.36043734)(-358.11761119,1092.22016465)(-362.21378851,1094.27933458) \curveto(-363.29778513,1095.052518)(-364.24097143,1096.09782231)(-364.50667671,1097.34493442) \lineto(-363.49510839,1097.0840323) \curveto(-361.2116615,1095.48861588)(-358.46693945,1096.35272368)(-356.0769407,1097.0840323) \lineto(-355.7734702,1096.59484084) \lineto(-356.6164438,1096.10564938) \curveto(-358.20528045,1095.72342778)(-359.65924131,1094.98416164)(-361.40453386,1095.12726645) \lineto(-361.70800435,1094.76852605) \curveto(-359.99238448,1094.33986387)(-358.2835084,1095.00946915)(-356.6164438,1095.38816857) \lineto(-357.29082268,1094.93158987) \lineto(-359.01048883,1094.11627076) \lineto(-356.81875747,1094.14888353) \lineto(-356.58272486,1094.11627076) \lineto(-353.31198729,1095.77952174) \lineto(-352.9410789,1095.55123239) \lineto(-350.34472021,1096.82313019) \lineto(-349.97381183,1096.59484084) \lineto(-352.43529474,1095.45339409) \lineto(-354.12124194,1094.5402367) \curveto(-352.47440872,1094.75730726)(-350.84510934,1095.43787042)(-349.40058978,1096.30132596) \lineto(-348.62505407,1096.07303661) \lineto(-344.7473755,1098.12764076) \lineto(-345.69150593,1094.80113881) \lineto(-346.09613326,1094.01843247) \curveto(-346.03071851,1093.54880867)(-345.33098298,1094.50892844)(-345.15200283,1094.80113881) \lineto(-344.41018606,1095.90997279) \curveto(-343.21680519,1097.14325708)(-341.80708358,1098.29853164)(-340.02672334,1098.38854287) \curveto(-341.31640551,1097.46586255)(-342.94543513,1096.65093479)(-343.80324507,1095.19249198) \curveto(-344.24873976,1094.51505964)(-344.73537156,1093.76013938)(-344.81481339,1092.97482402) \lineto(-344.57878078,1092.94221125) \curveto(-343.49599805,1096.16435235)(-339.89589383,1098.34158049)(-336.51995316,1098.77989604) \lineto(-339.15003079,1097.86673864) \lineto(-341.57779476,1096.30132596) \curveto(-342.60406454,1095.10913376)(-343.32983109,1093.36617719)(-342.96027147,1091.8986028) \lineto(-342.69051991,1092.42040703) \curveto(-342.87894137,1094.89375906)(-340.81439787,1096.64702126)(-338.64424663,1097.50799824) \lineto(-337.32920781,1097.73628759) \lineto(-339.21746868,1096.6274536) \lineto(-341.30804321,1094.73591328) \curveto(-342.1321342,1093.72204767)(-342.31947665,1092.26517027)(-341.98242209,1091.01805817) \lineto(-339.89184756,1093.10527507) \lineto(-339.45350129,1093.85536865) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.72207253,1098.68205775) \curveto(-438.46783169,1098.70029481)(-438.74091468,1098.43615751)(-438.72207253,1098.68205775) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.72207253,1098.68205775) \curveto(-438.46783169,1098.70029481)(-438.74091468,1098.43615751)(-438.72207253,1098.68205775) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.96868744,1098.29070458) \lineto(-437.20472005,1098.64944498) \lineto(-436.96868744,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.96868744,1098.29070458) \lineto(-437.20472005,1098.64944498) \lineto(-436.96868744,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-424.42524026,1098.68205775) \lineto(-424.32408343,1098.64944498) \lineto(-424.32408343,1097.01880677) \lineto(-424.39152132,1097.01880677) \lineto(-424.42524026,1098.68205775) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-424.42524026,1098.68205775) \lineto(-424.32408343,1098.64944498) \lineto(-424.32408343,1097.01880677) \lineto(-424.39152132,1097.01880677) \lineto(-424.42524026,1098.68205775) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.95514708,1098.55160669) \lineto(-429.71911447,1098.19286629) \lineto(-429.95514708,1098.55160669) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.95514708,1098.55160669) \lineto(-429.71911447,1098.19286629) \lineto(-429.95514708,1098.55160669) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-426.71812845,1098.55160669) \lineto(-426.61697162,1098.51899393) \lineto(-426.4483769,1097.76890035) \lineto(-426.34722007,1096.88835572) \lineto(-426.4483769,1096.85574295) \lineto(-426.54953373,1096.88835572) \lineto(-426.58325268,1097.63844929) \lineto(-426.71812845,1098.55160669) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-426.71812845,1098.55160669) \lineto(-426.61697162,1098.51899393) \lineto(-426.4483769,1097.76890035) \lineto(-426.34722007,1096.88835572) \lineto(-426.4483769,1096.85574295) \lineto(-426.54953373,1096.88835572) \lineto(-426.58325268,1097.63844929) \lineto(-426.71812845,1098.55160669) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.72207253,1098.42115563) \curveto(-438.52663753,1098.47559286)(-438.23490123,1098.2629185)(-438.35116415,1098.06241523) \lineto(-438.72207253,1098.42115563) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.72207253,1098.42115563) \curveto(-438.52663753,1098.47559286)(-438.23490123,1098.2629185)(-438.35116415,1098.06241523) \lineto(-438.72207253,1098.42115563) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-427.93201044,1098.42115563) \lineto(-427.83085361,1098.38854287) \lineto(-427.66225889,1097.37754718) \curveto(-427.46088935,1097.08024922)(-427.46088935,1096.63123669)(-427.66225889,1096.33393873) \lineto(-427.79713466,1095.55123239) \lineto(-427.96572938,1094.67068775) \lineto(-428.03316727,1094.67068775) \lineto(-427.93201044,1095.29033027) \lineto(-427.79713466,1095.94258556) \lineto(-427.83085361,1096.56222808) \lineto(-427.93201044,1097.11664507) \curveto(-427.7379242,1097.37859079)(-427.7379242,1097.76785674)(-427.93201044,1098.02980246) \lineto(-427.93201044,1098.42115563) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-427.93201044,1098.42115563) \lineto(-427.83085361,1098.38854287) \lineto(-427.66225889,1097.37754718) \curveto(-427.46088935,1097.08024922)(-427.46088935,1096.63123669)(-427.66225889,1096.33393873) \lineto(-427.79713466,1095.55123239) \lineto(-427.96572938,1094.67068775) \lineto(-428.03316727,1094.67068775) \lineto(-427.93201044,1095.29033027) \lineto(-427.79713466,1095.94258556) \lineto(-427.83085361,1096.56222808) \lineto(-427.93201044,1097.11664507) \curveto(-427.7379242,1097.37859079)(-427.7379242,1097.76785674)(-427.93201044,1098.02980246) \lineto(-427.93201044,1098.42115563) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.96868744,1098.29070458) \lineto(-436.73265483,1097.80151312) \lineto(-436.96868744,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.96868744,1098.29070458) \lineto(-436.73265483,1097.80151312) \lineto(-436.96868744,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.43878062,1098.29070458) \lineto(-431.33762379,1097.67106206) \lineto(-431.43878062,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.43878062,1098.29070458) \lineto(-431.33762379,1097.67106206) \lineto(-431.43878062,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.84313726 0.84313726 0.84313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-343.9044019,1098.29070458) \lineto(-343.39861774,1098.12764076) \lineto(-343.80324507,1097.540611) \curveto(-344.04237982,1097.40872498)(-344.04237982,1097.21591832)(-343.80324507,1097.0840323) \lineto(-343.80324507,1096.88835572) \lineto(-345.42175438,1095.19249198) \lineto(-345.62406805,1095.19249198) \curveto(-345.29159926,1096.30158687)(-344.70124799,1097.38928778)(-343.9044019,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.84313726 0.84313726 0.84313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-343.9044019,1098.29070458) \lineto(-343.39861774,1098.12764076) \lineto(-343.80324507,1097.540611) \curveto(-344.04237982,1097.40872498)(-344.04237982,1097.21591832)(-343.80324507,1097.0840323) \lineto(-343.80324507,1096.88835572) \lineto(-345.42175438,1095.19249198) \lineto(-345.62406805,1095.19249198) \curveto(-345.29159926,1096.30158687)(-344.70124799,1097.38928778)(-343.9044019,1098.29070458) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.34058185,1098.16025352) \curveto(-440.08634101,1098.17849058)(-440.35943748,1097.91435328)(-440.34058185,1098.16025352) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.34058185,1098.16025352) \curveto(-440.08634101,1098.17849058)(-440.35943748,1097.91435328)(-440.34058185,1098.16025352) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-435.21530235,1098.16025352) \lineto(-434.97926974,1098.06241523) \lineto(-435.21530235,1098.16025352) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-435.21530235,1098.16025352) \lineto(-434.97926974,1098.06241523) \lineto(-435.21530235,1098.16025352) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.01101665,1098.16025352) \lineto(-428.64010827,1097.14925783) \lineto(-428.84242193,1097.14925783) \lineto(-429.01101665,1098.16025352) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.01101665,1098.16025352) \lineto(-428.64010827,1097.14925783) \lineto(-428.84242193,1097.14925783) \lineto(-429.01101665,1098.16025352) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-433.59679304,1098.02980246) \lineto(-433.49563621,1097.67106206) \lineto(-433.59679304,1098.02980246) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-433.59679304,1098.02980246) \lineto(-433.49563621,1097.67106206) \lineto(-433.59679304,1098.02980246) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-432.65266261,1097.89935141) \lineto(-432.78753838,1096.85574295) \lineto(-432.88869521,1096.36655149) \lineto(-432.92241416,1097.37754718) \curveto(-433.06255009,1097.56030911)(-433.14563357,1097.85278038)(-432.88869521,1097.9971897) \lineto(-432.65266261,1097.89935141) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-432.65266261,1097.89935141) \lineto(-432.78753838,1096.85574295) \lineto(-432.88869521,1096.36655149) \lineto(-432.92241416,1097.37754718) \curveto(-433.06255009,1097.56030911)(-433.14563357,1097.85278038)(-432.88869521,1097.9971897) \lineto(-432.65266261,1097.89935141) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.55051975,1097.76890035) \lineto(-429.65167659,1097.9971897) \lineto(-429.55051975,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.55051975,1097.76890035) \lineto(-429.65167659,1097.9971897) \lineto(-429.55051975,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.07083029,1097.76890035) \curveto(-440.32507113,1097.75066329)(-440.05197466,1098.01480059)(-440.07083029,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.07083029,1097.76890035) \curveto(-440.32507113,1097.75066329)(-440.05197466,1098.01480059)(-440.07083029,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.18256943,1097.76890035) \curveto(-438.43681027,1097.75066329)(-438.16372728,1098.01480059)(-438.18256943,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.18256943,1097.76890035) \curveto(-438.43681027,1097.75066329)(-438.16372728,1098.01480059)(-438.18256943,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.93595452,1097.63844929) \lineto(-440.07083029,1097.76890035) \lineto(-439.93595452,1097.63844929) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.93595452,1097.63844929) \lineto(-440.07083029,1097.76890035) \lineto(-439.93595452,1097.63844929) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-437.91281788,1097.24709612) \lineto(-438.18256943,1097.76890035) \lineto(-437.91281788,1097.24709612) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-437.91281788,1097.24709612) \lineto(-438.18256943,1097.76890035) \lineto(-437.91281788,1097.24709612) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-435.88968123,1097.24709612) \lineto(-435.99083807,1097.27970889) \lineto(-436.26058962,1097.73628759) \curveto(-435.97236008,1097.85639387)(-435.82291772,1097.46521029)(-435.88968123,1097.24709612) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-435.88968123,1097.24709612) \lineto(-435.99083807,1097.27970889) \lineto(-436.26058962,1097.73628759) \curveto(-435.97236008,1097.85639387)(-435.82291772,1097.46521029)(-435.88968123,1097.24709612) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-435.08042658,1097.76890035) \lineto(-434.97926974,1097.73628759) \lineto(-434.81067502,1096.46438978) \lineto(-434.9455508,1096.33393873) \lineto(-435.04670763,1096.36655149) \lineto(-435.08042658,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-435.08042658,1097.76890035) \lineto(-434.97926974,1097.73628759) \lineto(-434.81067502,1096.46438978) \lineto(-434.9455508,1096.33393873) \lineto(-435.04670763,1096.36655149) \lineto(-435.08042658,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.55051975,1097.76890035) \lineto(-429.31448715,1097.21448336) \lineto(-429.2807682,1097.11664507) \lineto(-429.31448715,1097.01880677) \curveto(-429.73138817,1096.9081321)(-429.48470038,1097.54543769)(-429.55051975,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.55051975,1097.76890035) \lineto(-429.31448715,1097.21448336) \lineto(-429.2807682,1097.11664507) \lineto(-429.31448715,1097.01880677) \curveto(-429.73138817,1096.9081321)(-429.48470038,1097.54543769)(-429.55051975,1097.76890035) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.80107874,1097.50799824) \lineto(-439.93595452,1097.63844929) \lineto(-439.80107874,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.80107874,1097.50799824) \lineto(-439.93595452,1097.63844929) \lineto(-439.80107874,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.42918434,1097.11664507) \curveto(-436.64673896,1097.15545426)(-436.77918698,1097.41511709)(-436.66521695,1097.60583653) \lineto(-436.59777906,1097.60583653) \lineto(-436.42918434,1097.11664507) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.42918434,1097.11664507) \curveto(-436.64673896,1097.15545426)(-436.77918698,1097.41511709)(-436.66521695,1097.60583653) \lineto(-436.59777906,1097.60583653) \lineto(-436.42918434,1097.11664507) \closepath } } { \newrgbcolor{curcolor}{0.68627453 0.68627453 0.68627453} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-334.73284912,1097.63844929) \lineto(-334.36194074,1097.60583653) \lineto(-334.36194074,1097.41015995) \lineto(-334.59797335,1097.37754718) \lineto(-335.64326061,1097.14925783) \curveto(-335.94834962,1097.28257881)(-335.63082506,1097.58078993)(-335.407228,1097.50799824) \lineto(-334.73284912,1097.63844929) \closepath } } { \newrgbcolor{curcolor}{0.68627453 0.68627453 0.68627453} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-334.73284912,1097.63844929) \lineto(-334.36194074,1097.60583653) \lineto(-334.36194074,1097.41015995) \lineto(-334.59797335,1097.37754718) \lineto(-335.64326061,1097.14925783) \curveto(-335.94834962,1097.28257881)(-335.63082506,1097.58078993)(-335.407228,1097.50799824) \lineto(-334.73284912,1097.63844929) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.34058185,1097.24709612) \lineto(-440.84636601,1097.41015995) \lineto(-440.84636601,1097.47538547) \curveto(-440.64917762,1097.58557748)(-440.38077483,1097.45747454)(-440.34058185,1097.24709612) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.34058185,1097.24709612) \lineto(-440.84636601,1097.41015995) \lineto(-440.84636601,1097.47538547) \curveto(-440.64917762,1097.58557748)(-440.38077483,1097.45747454)(-440.34058185,1097.24709612) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.12669986,1096.85574295) \lineto(-439.80107874,1097.50799824) \curveto(-439.4856043,1097.50451128)(-439.13034151,1097.16086798)(-439.12669986,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.12669986,1096.85574295) \lineto(-439.80107874,1097.50799824) \curveto(-439.4856043,1097.50451128)(-439.13034151,1097.16086798)(-439.12669986,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-434.13629614,1097.50799824) \lineto(-434.03513931,1096.88835572) \lineto(-434.13629614,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-434.13629614,1097.50799824) \lineto(-434.03513931,1096.88835572) \lineto(-434.13629614,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-433.46191726,1097.50799824) \lineto(-433.22588465,1096.95358125) \lineto(-433.22588465,1096.88835572) \curveto(-433.60596459,1096.7562088)(-433.41875701,1097.31388707)(-433.46191726,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-433.46191726,1097.50799824) \lineto(-433.22588465,1096.95358125) \lineto(-433.22588465,1096.88835572) \curveto(-433.60596459,1096.7562088)(-433.41875701,1097.31388707)(-433.46191726,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.30390484,1097.50799824) \lineto(-431.20274801,1096.88835572) \lineto(-431.30390484,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.30390484,1097.50799824) \lineto(-431.20274801,1096.88835572) \lineto(-431.30390484,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-423.21135828,1097.50799824) \curveto(-422.95711744,1097.5262353)(-423.23020042,1097.262098)(-423.21135828,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-423.21135828,1097.50799824) \curveto(-422.95711744,1097.5262353)(-423.23020042,1097.262098)(-423.21135828,1097.50799824) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.20570607,1097.11664507) \lineto(-440.34058185,1097.24709612) \lineto(-440.20570607,1097.11664507) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.20570607,1097.11664507) \lineto(-440.34058185,1097.24709612) \lineto(-440.20570607,1097.11664507) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-437.50819055,1096.33393873) \lineto(-437.60934738,1096.36655149) \lineto(-437.91281788,1097.24709612) \lineto(-437.81166104,1097.21448336) \lineto(-437.50819055,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-437.50819055,1096.33393873) \lineto(-437.60934738,1096.36655149) \lineto(-437.91281788,1097.24709612) \lineto(-437.81166104,1097.21448336) \lineto(-437.50819055,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-435.88968123,1097.24709612) \lineto(-435.7885244,1096.88835572) \lineto(-435.88968123,1097.24709612) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-435.88968123,1097.24709612) \lineto(-435.7885244,1096.88835572) \lineto(-435.88968123,1097.24709612) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.07083029,1096.98619401) \lineto(-440.20570607,1097.11664507) \lineto(-440.07083029,1096.98619401) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.07083029,1096.98619401) \lineto(-440.20570607,1097.11664507) \lineto(-440.07083029,1096.98619401) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.42918434,1097.11664507) \lineto(-436.15943279,1096.59484084) \lineto(-436.05827595,1096.10564938) \lineto(-436.42918434,1096.98619401) \lineto(-436.42918434,1097.11664507) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.42918434,1097.11664507) \lineto(-436.15943279,1096.59484084) \lineto(-436.05827595,1096.10564938) \lineto(-436.42918434,1096.98619401) \lineto(-436.42918434,1097.11664507) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-338.50937085,1096.46438978) \lineto(-338.47565191,1096.56222808) \lineto(-337.16061309,1097.11664507) \lineto(-336.92458048,1097.0840323) \lineto(-336.92458048,1097.01880677) \lineto(-338.50937085,1096.46438978) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-338.50937085,1096.46438978) \lineto(-338.47565191,1096.56222808) \lineto(-337.16061309,1097.11664507) \lineto(-336.92458048,1097.0840323) \lineto(-336.92458048,1097.01880677) \lineto(-338.50937085,1096.46438978) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.93595452,1096.85574295) \lineto(-440.07083029,1096.98619401) \lineto(-439.93595452,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.93595452,1096.85574295) \lineto(-440.07083029,1096.98619401) \lineto(-439.93595452,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.66620297,1096.59484084) \lineto(-439.93595452,1096.85574295) \lineto(-439.66620297,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.66620297,1096.59484084) \lineto(-439.93595452,1096.85574295) \lineto(-439.66620297,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.99182408,1096.7252919) \lineto(-439.12669986,1096.85574295) \lineto(-438.99182408,1096.7252919) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.99182408,1096.7252919) \lineto(-439.12669986,1096.85574295) \lineto(-438.99182408,1096.7252919) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.2807682,1095.94258556) \lineto(-429.38192503,1095.97519832) \lineto(-429.38192503,1096.82313019) \lineto(-429.31448715,1096.82313019) \lineto(-429.2807682,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.2807682,1095.94258556) \lineto(-429.38192503,1095.97519832) \lineto(-429.38192503,1096.82313019) \lineto(-429.31448715,1096.82313019) \lineto(-429.2807682,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-424.56011604,1096.85574295) \curveto(-424.3058752,1096.87398001)(-424.57895818,1096.60984271)(-424.56011604,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-424.56011604,1096.85574295) \curveto(-424.3058752,1096.87398001)(-424.57895818,1096.60984271)(-424.56011604,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-423.21135828,1096.85574295) \lineto(-422.97532567,1096.75790466) \lineto(-423.21135828,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-423.21135828,1096.85574295) \lineto(-422.97532567,1096.75790466) \lineto(-423.21135828,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.23137255 0.23137255 0.23137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-410.39815954,1096.85574295) \lineto(-410.16212693,1096.82313019) \lineto(-409.99353221,1096.46438978) \lineto(-410.12840799,1094.63807499) \lineto(-410.16212693,1094.27933458) \lineto(-410.63419215,1094.27933458) \lineto(-410.66791109,1094.63807499) \lineto(-410.39815954,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.23137255 0.23137255 0.23137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-410.39815954,1096.85574295) \lineto(-410.16212693,1096.82313019) \lineto(-409.99353221,1096.46438978) \lineto(-410.12840799,1094.63807499) \lineto(-410.16212693,1094.27933458) \lineto(-410.63419215,1094.27933458) \lineto(-410.66791109,1094.63807499) \lineto(-410.39815954,1096.85574295) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.85694831,1096.59484084) \lineto(-438.99182408,1096.7252919) \lineto(-438.85694831,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.85694831,1096.59484084) \lineto(-438.99182408,1096.7252919) \lineto(-438.85694831,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-434.13629614,1096.7252919) \lineto(-433.90026353,1096.69267913) \lineto(-433.90026353,1095.19249198) \lineto(-433.96770142,1095.19249198) \lineto(-434.13629614,1096.7252919) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-434.13629614,1096.7252919) \lineto(-433.90026353,1096.69267913) \lineto(-433.90026353,1095.19249198) \lineto(-433.96770142,1095.19249198) \lineto(-434.13629614,1096.7252919) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.39645141,1096.33393873) \lineto(-439.66620297,1096.59484084) \lineto(-439.39645141,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.39645141,1096.33393873) \lineto(-439.66620297,1096.59484084) \lineto(-439.39645141,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.72207253,1096.46438978) \lineto(-438.85694831,1096.59484084) \lineto(-438.72207253,1096.46438978) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.72207253,1096.46438978) \lineto(-438.85694831,1096.59484084) \lineto(-438.72207253,1096.46438978) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-435.88968123,1096.59484084) \lineto(-435.65364862,1096.56222808) \lineto(-435.4850539,1095.02942816) \lineto(-435.35017813,1093.59446654) \lineto(-435.21530235,1093.33356442) \lineto(-435.35017813,1093.07266231) \lineto(-435.2490213,1091.67031345) \lineto(-435.35017813,1092.68130914) \lineto(-435.61992968,1093.72491759) \lineto(-435.75480546,1093.98581971) \lineto(-436.02455701,1095.8121345) \lineto(-435.75480546,1096.07303661) \lineto(-435.88968123,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-435.88968123,1096.59484084) \lineto(-435.65364862,1096.56222808) \lineto(-435.4850539,1095.02942816) \lineto(-435.35017813,1093.59446654) \lineto(-435.21530235,1093.33356442) \lineto(-435.35017813,1093.07266231) \lineto(-435.2490213,1091.67031345) \lineto(-435.35017813,1092.68130914) \lineto(-435.61992968,1093.72491759) \lineto(-435.75480546,1093.98581971) \lineto(-436.02455701,1095.8121345) \lineto(-435.75480546,1096.07303661) \lineto(-435.88968123,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-433.32704149,1096.59484084) \lineto(-433.09100888,1095.64907068) \lineto(-433.09100888,1095.58384515) \lineto(-433.29332254,1095.58384515) \lineto(-433.32704149,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-433.32704149,1096.59484084) \lineto(-433.09100888,1095.64907068) \lineto(-433.09100888,1095.58384515) \lineto(-433.29332254,1095.58384515) \lineto(-433.32704149,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.30390484,1096.59484084) \lineto(-431.06787224,1096.49700255) \lineto(-431.30390484,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.30390484,1096.59484084) \lineto(-431.06787224,1096.49700255) \lineto(-431.30390484,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-423.21135828,1096.59484084) \lineto(-422.97532567,1096.49700255) \lineto(-423.21135828,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-423.21135828,1096.59484084) \lineto(-422.97532567,1096.49700255) \lineto(-423.21135828,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-346.33216587,1096.59484084) \curveto(-346.07792503,1096.6130779)(-346.35100802,1096.3489406)(-346.33216587,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-346.33216587,1096.59484084) \curveto(-346.07792503,1096.6130779)(-346.35100802,1096.3489406)(-346.33216587,1096.59484084) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.68933961,1096.20348767) \lineto(-442.06024799,1096.43177702) \lineto(-441.68933961,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.68933961,1096.20348767) \lineto(-442.06024799,1096.43177702) \lineto(-441.68933961,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-437.7779421,1095.29033027) \lineto(-438.01397471,1095.45339409) \lineto(-438.72207253,1096.46438978) \curveto(-438.32257048,1096.17791926)(-437.8263625,1095.79687173)(-437.7779421,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-437.7779421,1095.29033027) \lineto(-438.01397471,1095.45339409) \lineto(-438.72207253,1096.46438978) \curveto(-438.32257048,1096.17791926)(-437.8263625,1095.79687173)(-437.7779421,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.88235295 0.88235295 0.88235295} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-338.50937085,1096.46438978) \lineto(-338.5430898,1095.71429621) \lineto(-339.55465812,1094.73591328) \lineto(-339.62209601,1094.5402367) \lineto(-339.82440967,1094.47501117) \lineto(-341.71267054,1092.19211768) \lineto(-341.30804321,1094.21410906) \lineto(-338.50937085,1096.46438978) \closepath } } { \newrgbcolor{curcolor}{0.88235295 0.88235295 0.88235295} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-338.50937085,1096.46438978) \lineto(-338.5430898,1095.71429621) \lineto(-339.55465812,1094.73591328) \lineto(-339.62209601,1094.5402367) \lineto(-339.82440967,1094.47501117) \lineto(-341.71267054,1092.19211768) \lineto(-341.30804321,1094.21410906) \lineto(-338.50937085,1096.46438978) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.39645141,1096.33393873) \curveto(-439.14221057,1096.35217578)(-439.41530705,1096.08803849)(-439.39645141,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.39645141,1096.33393873) \curveto(-439.14221057,1096.35217578)(-439.41530705,1096.08803849)(-439.39645141,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-437.64306632,1093.98581971) \lineto(-437.00240639,1093.23572613) \lineto(-437.64306632,1095.02942816) \lineto(-437.33959583,1094.67068775) \lineto(-437.06984427,1094.14888353) \lineto(-437.00240639,1094.14888353) \lineto(-437.27215794,1095.38816857) \curveto(-437.53975148,1095.62285002)(-437.78792291,1096.02490017)(-437.50819055,1096.33393873) \lineto(-436.53034117,1094.40978564) \lineto(-436.46290328,1094.40978564) \lineto(-436.32802751,1094.9968154) \lineto(-436.15943279,1093.72491759) \curveto(-435.94430592,1093.27264378)(-435.94430592,1092.61177873)(-436.15943279,1092.15950491) \lineto(-436.29430856,1091.50724963) \lineto(-436.32802751,1091.14850922) \lineto(-436.39546539,1091.14850922) \lineto(-437.60934738,1093.75753036) \lineto(-437.64306632,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-437.64306632,1093.98581971) \lineto(-437.00240639,1093.23572613) \lineto(-437.64306632,1095.02942816) \lineto(-437.33959583,1094.67068775) \lineto(-437.06984427,1094.14888353) \lineto(-437.00240639,1094.14888353) \lineto(-437.27215794,1095.38816857) \curveto(-437.53975148,1095.62285002)(-437.78792291,1096.02490017)(-437.50819055,1096.33393873) \lineto(-436.53034117,1094.40978564) \lineto(-436.46290328,1094.40978564) \lineto(-436.32802751,1094.9968154) \lineto(-436.15943279,1093.72491759) \curveto(-435.94430592,1093.27264378)(-435.94430592,1092.61177873)(-436.15943279,1092.15950491) \lineto(-436.29430856,1091.50724963) \lineto(-436.32802751,1091.14850922) \lineto(-436.39546539,1091.14850922) \lineto(-437.60934738,1093.75753036) \lineto(-437.64306632,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.30390484,1096.33393873) \lineto(-431.06787224,1096.23610043) \lineto(-431.30390484,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.30390484,1096.33393873) \lineto(-431.06787224,1096.23610043) \lineto(-431.30390484,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-426.58325268,1096.33393873) \lineto(-426.34722007,1096.23610043) \lineto(-426.58325268,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-426.58325268,1096.33393873) \lineto(-426.34722007,1096.23610043) \lineto(-426.58325268,1096.33393873) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.914526,1096.20348767) \curveto(-409.16876684,1096.18525061)(-408.89568386,1096.44938791)(-408.914526,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.914526,1096.20348767) \curveto(-409.16876684,1096.18525061)(-408.89568386,1096.44938791)(-408.914526,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-346.87166898,1096.07303661) \lineto(-346.50076059,1096.30132596) \lineto(-346.87166898,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-346.87166898,1096.07303661) \lineto(-346.50076059,1096.30132596) \lineto(-346.87166898,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.81176472 0.81176472 0.81176472} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-339.45350129,1093.85536865) \lineto(-339.41978234,1094.083658) \curveto(-338.65571107,1094.9235019)(-337.8821985,1095.99215696)(-336.75598576,1096.33393873) \lineto(-336.38507738,1096.30132596) \lineto(-337.12689415,1095.77952174) \lineto(-337.80127303,1094.9968154) \lineto(-338.00358669,1094.67068775) \lineto(-339.45350129,1093.85536865) \closepath } } { \newrgbcolor{curcolor}{0.81176472 0.81176472 0.81176472} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-339.45350129,1093.85536865) \lineto(-339.41978234,1094.083658) \curveto(-338.65571107,1094.9235019)(-337.8821985,1095.99215696)(-336.75598576,1096.33393873) \lineto(-336.38507738,1096.30132596) \lineto(-337.12689415,1095.77952174) \lineto(-337.80127303,1094.9968154) \lineto(-338.00358669,1094.67068775) \lineto(-339.45350129,1093.85536865) \closepath } } { \newrgbcolor{curcolor}{0.20392157 0.20392157 0.20392157} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.65660668,1096.20348767) \lineto(-444.2856983,1096.04042385) \lineto(-441.92537222,1094.27933458) \lineto(-441.72305855,1094.21410906) \lineto(-440.91380389,1093.43140272) \lineto(-439.43017036,1091.99644109) \lineto(-438.99182408,1090.85499434) \lineto(-439.1604188,1090.626705) \lineto(-439.49760824,1090.75715605) \curveto(-440.35690181,1092.417798)(-441.98471756,1093.72883112)(-443.47644364,1094.86636434) \lineto(-443.94850886,1095.06204092) \lineto(-444.75776351,1095.71429621) \lineto(-444.65660668,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.20392157 0.20392157 0.20392157} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.65660668,1096.20348767) \lineto(-444.2856983,1096.04042385) \lineto(-441.92537222,1094.27933458) \lineto(-441.72305855,1094.21410906) \lineto(-440.91380389,1093.43140272) \lineto(-439.43017036,1091.99644109) \lineto(-438.99182408,1090.85499434) \lineto(-439.1604188,1090.626705) \lineto(-439.49760824,1090.75715605) \curveto(-440.35690181,1092.417798)(-441.98471756,1093.72883112)(-443.47644364,1094.86636434) \lineto(-443.94850886,1095.06204092) \lineto(-444.75776351,1095.71429621) \lineto(-444.65660668,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.41958806,1096.07303661) \lineto(-441.68933961,1096.20348767) \lineto(-441.41958806,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.41958806,1096.07303661) \lineto(-441.68933961,1096.20348767) \lineto(-441.41958806,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-432.92241416,1096.20348767) \lineto(-432.68638155,1096.17087491) \lineto(-432.68638155,1094.27933458) \lineto(-432.75381944,1094.27933458) \lineto(-432.92241416,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-432.92241416,1096.20348767) \lineto(-432.68638155,1096.17087491) \lineto(-432.68638155,1094.27933458) \lineto(-432.75381944,1094.27933458) \lineto(-432.92241416,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-423.21135828,1096.20348767) \lineto(-423.11020144,1095.58384515) \lineto(-423.21135828,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-423.21135828,1096.20348767) \lineto(-423.11020144,1095.58384515) \lineto(-423.21135828,1096.20348767) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.77965023,1095.8121345) \lineto(-408.914526,1096.20348767) \lineto(-408.77965023,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.77965023,1095.8121345) \lineto(-408.914526,1096.20348767) \lineto(-408.77965023,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.1498365,1095.8121345) \lineto(-441.41958806,1096.07303661) \lineto(-441.1498365,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.1498365,1095.8121345) \lineto(-441.41958806,1096.07303661) \lineto(-441.1498365,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.99182408,1093.72491759) \lineto(-438.48603992,1093.6270793) \lineto(-438.72207253,1094.11627076) \lineto(-439.49760824,1095.19249198) \lineto(-439.7673598,1096.04042385) \lineto(-439.43017036,1096.04042385) \lineto(-437.50819055,1092.68130914) \lineto(-437.54190949,1092.32256873) \lineto(-438.01397471,1092.45301979) \lineto(-438.6209157,1093.43140272) \lineto(-438.99182408,1093.72491759) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.99182408,1093.72491759) \lineto(-438.48603992,1093.6270793) \lineto(-438.72207253,1094.11627076) \lineto(-439.49760824,1095.19249198) \lineto(-439.7673598,1096.04042385) \lineto(-439.43017036,1096.04042385) \lineto(-437.50819055,1092.68130914) \lineto(-437.54190949,1092.32256873) \lineto(-438.01397471,1092.45301979) \lineto(-438.6209157,1093.43140272) \lineto(-438.99182408,1093.72491759) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.85694831,1095.68168344) \lineto(-439.22785669,1096.04042385) \curveto(-439.02055262,1096.15289875)(-438.80070511,1095.87070702)(-438.85694831,1095.68168344) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.85694831,1095.68168344) \lineto(-439.22785669,1096.04042385) \curveto(-439.02055262,1096.15289875)(-438.80070511,1095.87070702)(-438.85694831,1095.68168344) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.96868744,1096.07303661) \curveto(-436.7144466,1096.09127367)(-436.98752959,1095.82713637)(-436.96868744,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.96868744,1096.07303661) \curveto(-436.7144466,1096.09127367)(-436.98752959,1095.82713637)(-436.96868744,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-434.9455508,1096.07303661) \lineto(-434.81067502,1095.94258556) \lineto(-434.81067502,1092.02905386) \lineto(-434.91183186,1091.93121556) \lineto(-435.04670763,1092.19211768) \lineto(-434.9455508,1092.42040703) \lineto(-434.9455508,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-434.9455508,1096.07303661) \lineto(-434.81067502,1095.94258556) \lineto(-434.81067502,1092.02905386) \lineto(-434.91183186,1091.93121556) \lineto(-435.04670763,1092.19211768) \lineto(-434.9455508,1092.42040703) \lineto(-434.9455508,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-426.58325268,1096.07303661) \curveto(-426.31120824,1096.13206572)(-426.32280756,1095.96395344)(-426.4483769,1095.8121345) \curveto(-426.36128761,1095.52983841)(-426.67038243,1095.52983841)(-426.58325268,1095.8121345) \lineto(-426.58325268,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-426.58325268,1096.07303661) \curveto(-426.31120824,1096.13206572)(-426.32280756,1095.96395344)(-426.4483769,1095.8121345) \curveto(-426.36128761,1095.52983841)(-426.67038243,1095.52983841)(-426.58325268,1095.8121345) \lineto(-426.58325268,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.82745099 0.82745099 0.82745099} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-413.36542662,1096.07303661) \lineto(-413.09567506,1095.8121345) \curveto(-413.3582782,1095.48078882)(-413.23689,1095.04142966)(-412.96079929,1094.76852605) \lineto(-413.12939401,1093.23572613) \lineto(-414.95021699,1093.36617719) \lineto(-414.41071388,1094.9968154) \lineto(-414.07352444,1095.25771751) \lineto(-413.93864866,1094.14888353) \lineto(-413.50030239,1095.55123239) \lineto(-413.36542662,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.82745099 0.82745099 0.82745099} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-413.36542662,1096.07303661) \lineto(-413.09567506,1095.8121345) \curveto(-413.3582782,1095.48078882)(-413.23689,1095.04142966)(-412.96079929,1094.76852605) \lineto(-413.12939401,1093.23572613) \lineto(-414.95021699,1093.36617719) \lineto(-414.41071388,1094.9968154) \lineto(-414.07352444,1095.25771751) \lineto(-413.93864866,1094.14888353) \lineto(-413.50030239,1095.55123239) \lineto(-413.36542662,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-346.87166898,1096.07303661) \lineto(-347.2762963,1095.94258556) \lineto(-346.87166898,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-346.87166898,1096.07303661) \lineto(-347.2762963,1095.94258556) \lineto(-346.87166898,1096.07303661) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.2807682,1095.94258556) \lineto(-429.17961137,1095.45339409) \lineto(-429.2807682,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.2807682,1095.94258556) \lineto(-429.17961137,1095.45339409) \lineto(-429.2807682,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-407.16114091,1095.94258556) \lineto(-406.92510831,1095.71429621) \lineto(-407.16114091,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-407.16114091,1095.94258556) \lineto(-406.92510831,1095.71429621) \lineto(-407.16114091,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.60784316 0.60784316 0.60784316} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-355.63859442,1095.94258556) \lineto(-355.36884287,1095.94258556) \curveto(-354.630398,1095.93718488)(-356.11160377,1095.3798197)(-355.63859442,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.60784316 0.60784316 0.60784316} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-355.63859442,1095.94258556) \lineto(-355.36884287,1095.94258556) \curveto(-354.630398,1095.93718488)(-356.11160377,1095.3798197)(-355.63859442,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-347.2762963,1095.94258556) \curveto(-347.25744067,1095.69668532)(-347.53053714,1095.96082261)(-347.2762963,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-347.2762963,1095.94258556) \curveto(-347.25744067,1095.69668532)(-347.53053714,1095.96082261)(-347.2762963,1095.94258556) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.01496073,1095.68168344) \lineto(-441.1498365,1095.8121345) \lineto(-441.01496073,1095.68168344) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.01496073,1095.68168344) \lineto(-441.1498365,1095.8121345) \lineto(-441.01496073,1095.68168344) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.83381167,1095.8121345) \curveto(-436.60708549,1095.71674869)(-436.3146748,1095.46200386)(-436.46290328,1095.19249198) \lineto(-436.53034117,1095.19249198) \lineto(-436.83381167,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.83381167,1095.8121345) \curveto(-436.60708549,1095.71674869)(-436.3146748,1095.46200386)(-436.46290328,1095.19249198) \lineto(-436.53034117,1095.19249198) \lineto(-436.83381167,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.16902907,1095.8121345) \lineto(-431.06787224,1095.77952174) \lineto(-431.06787224,1094.67068775) \lineto(-431.2701859,1094.67068775) \lineto(-431.16902907,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.16902907,1095.8121345) \lineto(-431.06787224,1095.77952174) \lineto(-431.06787224,1094.67068775) \lineto(-431.2701859,1094.67068775) \lineto(-431.16902907,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.77965023,1095.8121345) \lineto(-408.54361762,1094.9968154) \lineto(-408.54361762,1094.93158987) \lineto(-408.77965023,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.77965023,1095.8121345) \lineto(-408.54361762,1094.9968154) \lineto(-408.54361762,1094.93158987) \lineto(-408.77965023,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-348.08555096,1095.55123239) \lineto(-347.71464258,1095.77952174) \curveto(-347.56506534,1095.5277512)(-347.92882531,1095.52983841)(-348.08555096,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-348.08555096,1095.55123239) \lineto(-347.71464258,1095.77952174) \curveto(-347.56506534,1095.5277512)(-347.92882531,1095.52983841)(-348.08555096,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.78823531 0.78823531 0.78823531} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.51896714,1095.8121345) \lineto(-332.8783072,1095.77952174) \curveto(-332.96248317,1095.25380398)(-333.58627015,1095.15087809)(-334.05847024,1095.15987922) \lineto(-335.37350906,1095.06204092) \lineto(-335.37350906,1095.12726645) \lineto(-335.00260067,1095.29033027) \lineto(-334.36194074,1095.45339409) \lineto(-333.51896714,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.78823531 0.78823531 0.78823531} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.51896714,1095.8121345) \lineto(-332.8783072,1095.77952174) \curveto(-332.96248317,1095.25380398)(-333.58627015,1095.15087809)(-334.05847024,1095.15987922) \lineto(-335.37350906,1095.06204092) \lineto(-335.37350906,1095.12726645) \lineto(-335.00260067,1095.29033027) \lineto(-334.36194074,1095.45339409) \lineto(-333.51896714,1095.8121345) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.74520917,1095.55123239) \lineto(-441.01496073,1095.68168344) \lineto(-440.74520917,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.74520917,1095.55123239) \lineto(-441.01496073,1095.68168344) \lineto(-440.74520917,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.58719676,1095.29033027) \lineto(-438.85694831,1095.68168344) \lineto(-438.58719676,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.58719676,1095.29033027) \lineto(-438.85694831,1095.68168344) \lineto(-438.58719676,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.74520917,1095.55123239) \curveto(-440.49096834,1095.56946944)(-440.76406481,1095.30533214)(-440.74520917,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.74520917,1095.55123239) \curveto(-440.49096834,1095.56946944)(-440.76406481,1095.30533214)(-440.74520917,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-407.16114091,1095.55123239) \curveto(-406.66452831,1095.60578702)(-407.08512493,1095.16274914)(-407.05998408,1094.93158987) \lineto(-407.16114091,1095.15987922) \lineto(-407.16114091,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-407.16114091,1095.55123239) \curveto(-406.66452831,1095.60578702)(-407.08512493,1095.16274914)(-407.05998408,1094.93158987) \lineto(-407.16114091,1095.15987922) \lineto(-407.16114091,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-348.08555096,1095.55123239) \curveto(-348.06669533,1095.30533214)(-348.3397918,1095.56946944)(-348.08555096,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-348.08555096,1095.55123239) \curveto(-348.06669533,1095.30533214)(-348.3397918,1095.56946944)(-348.08555096,1095.55123239) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-433.32704149,1095.42078133) \lineto(-433.09100888,1095.19249198) \lineto(-433.32704149,1095.42078133) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-433.32704149,1095.42078133) \lineto(-433.09100888,1095.19249198) \lineto(-433.32704149,1095.42078133) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-423.34623405,1095.02942816) \lineto(-423.24507722,1095.38816857) \lineto(-423.34623405,1095.02942816) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-423.34623405,1095.02942816) \lineto(-423.24507722,1095.38816857) \lineto(-423.34623405,1095.02942816) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-348.75992984,1095.29033027) \lineto(-348.52389723,1095.38816857) \lineto(-348.75992984,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-348.75992984,1095.29033027) \lineto(-348.52389723,1095.38816857) \lineto(-348.75992984,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.20570607,1095.02942816) \lineto(-440.44173868,1095.25771751) \lineto(-440.20570607,1095.02942816) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.20570607,1095.02942816) \lineto(-440.44173868,1095.25771751) \lineto(-440.20570607,1095.02942816) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.58719676,1095.29033027) \lineto(-438.35116415,1094.93158987) \lineto(-438.58719676,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.58719676,1095.29033027) \lineto(-438.35116415,1094.93158987) \lineto(-438.58719676,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-437.64306632,1095.02942816) \lineto(-437.7779421,1095.29033027) \lineto(-437.64306632,1095.02942816) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-437.64306632,1095.02942816) \lineto(-437.7779421,1095.29033027) \lineto(-437.64306632,1095.02942816) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.41564398,1095.29033027) \lineto(-429.31448715,1094.93158987) \lineto(-429.41564398,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.41564398,1095.29033027) \lineto(-429.31448715,1094.93158987) \lineto(-429.41564398,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-348.75992984,1095.29033027) \lineto(-348.99596245,1095.19249198) \lineto(-348.75992984,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-348.75992984,1095.29033027) \lineto(-348.99596245,1095.19249198) \lineto(-348.75992984,1095.29033027) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-349.97381183,1094.8989771) \lineto(-349.94009288,1094.9968154) \lineto(-349.33315189,1095.12726645) \lineto(-349.97381183,1094.8989771) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-349.97381183,1094.8989771) \lineto(-349.94009288,1094.9968154) \lineto(-349.33315189,1095.12726645) \lineto(-349.97381183,1094.8989771) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.07083029,1094.8989771) \lineto(-440.20570607,1095.02942816) \lineto(-440.07083029,1094.8989771) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.07083029,1094.8989771) \lineto(-440.20570607,1095.02942816) \lineto(-440.07083029,1094.8989771) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-423.34623405,1095.02942816) \lineto(-423.51482877,1094.27933458) \lineto(-423.58226666,1094.27933458) \lineto(-423.44739088,1094.9968154) \lineto(-423.34623405,1095.02942816) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-423.34623405,1095.02942816) \lineto(-423.51482877,1094.27933458) \lineto(-423.58226666,1094.27933458) \lineto(-423.44739088,1094.9968154) \lineto(-423.34623405,1095.02942816) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.93595452,1094.76852605) \lineto(-440.07083029,1094.8989771) \lineto(-439.93595452,1094.76852605) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.93595452,1094.76852605) \lineto(-440.07083029,1094.8989771) \lineto(-439.93595452,1094.76852605) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-433.32704149,1094.8989771) \lineto(-433.22588465,1094.67068775) \lineto(-433.32704149,1094.8989771) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-433.32704149,1094.8989771) \lineto(-433.22588465,1094.67068775) \lineto(-433.32704149,1094.8989771) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-349.97381183,1094.8989771) \lineto(-350.24356338,1094.76852605) \lineto(-349.97381183,1094.8989771) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-349.97381183,1094.8989771) \lineto(-350.24356338,1094.76852605) \lineto(-349.97381183,1094.8989771) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.66620297,1094.50762393) \lineto(-439.93595452,1094.76852605) \lineto(-439.66620297,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.66620297,1094.50762393) \lineto(-439.93595452,1094.76852605) \lineto(-439.66620297,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.3174452,1094.76852605) \lineto(-438.0814126,1094.5402367) \lineto(-438.3174452,1094.76852605) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.3174452,1094.76852605) \lineto(-438.0814126,1094.5402367) \lineto(-438.3174452,1094.76852605) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.77965023,1094.76852605) \lineto(-408.54361762,1094.67068775) \lineto(-408.77965023,1094.76852605) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.77965023,1094.76852605) \lineto(-408.54361762,1094.67068775) \lineto(-408.77965023,1094.76852605) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-350.24356338,1094.76852605) \lineto(-350.51331493,1094.63807499) \lineto(-350.24356338,1094.76852605) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-350.24356338,1094.76852605) \lineto(-350.51331493,1094.63807499) \lineto(-350.24356338,1094.76852605) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-350.51331493,1094.63807499) \lineto(-350.78306648,1094.50762393) \lineto(-350.51331493,1094.63807499) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-350.51331493,1094.63807499) \lineto(-350.78306648,1094.50762393) \lineto(-350.51331493,1094.63807499) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-347.54604786,1094.50762393) \lineto(-347.31001525,1094.60546223) \lineto(-347.54604786,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-347.54604786,1094.50762393) \lineto(-347.31001525,1094.60546223) \lineto(-347.54604786,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.11433981,1094.50762393) \lineto(-332.74343142,1094.60546223) \lineto(-333.11433981,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.11433981,1094.50762393) \lineto(-332.74343142,1094.60546223) \lineto(-333.11433981,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.53132719,1094.37717288) \lineto(-439.66620297,1094.50762393) \lineto(-439.53132719,1094.37717288) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.53132719,1094.37717288) \lineto(-439.66620297,1094.50762393) \lineto(-439.53132719,1094.37717288) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.30390484,1094.50762393) \lineto(-431.06787224,1094.40978564) \lineto(-431.30390484,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.30390484,1094.50762393) \lineto(-431.06787224,1094.40978564) \lineto(-431.30390484,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-350.78306648,1094.50762393) \lineto(-351.05281804,1094.37717288) \lineto(-350.78306648,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-350.78306648,1094.50762393) \lineto(-351.05281804,1094.37717288) \lineto(-350.78306648,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-347.54604786,1094.50762393) \lineto(-347.78208046,1094.40978564) \lineto(-347.54604786,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-347.54604786,1094.50762393) \lineto(-347.78208046,1094.40978564) \lineto(-347.54604786,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.11433981,1094.50762393) \lineto(-333.14805875,1094.40978564) \lineto(-334.32822179,1093.85536865) \lineto(-334.42937863,1093.88798141) \curveto(-334.15045552,1094.25794061)(-333.60906416,1094.49340477)(-333.11433981,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.11433981,1094.50762393) \lineto(-333.14805875,1094.40978564) \lineto(-334.32822179,1093.85536865) \lineto(-334.42937863,1093.88798141) \curveto(-334.15045552,1094.25794061)(-333.60906416,1094.49340477)(-333.11433981,1094.50762393) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.39645141,1094.24672182) \lineto(-439.53132719,1094.37717288) \lineto(-439.39645141,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.39645141,1094.24672182) \lineto(-439.53132719,1094.37717288) \lineto(-439.39645141,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-437.64306632,1093.98581971) \lineto(-437.87909893,1094.34456011) \lineto(-437.64306632,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-437.64306632,1093.98581971) \lineto(-437.87909893,1094.34456011) \lineto(-437.64306632,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.77965023,1093.98581971) \lineto(-408.6784934,1094.34456011) \lineto(-408.77965023,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.77965023,1093.98581971) \lineto(-408.6784934,1094.34456011) \lineto(-408.77965023,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-351.05281804,1094.37717288) \lineto(-351.32256959,1094.24672182) \lineto(-351.05281804,1094.37717288) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-351.05281804,1094.37717288) \lineto(-351.32256959,1094.24672182) \lineto(-351.05281804,1094.37717288) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-348.08555096,1094.37717288) \curveto(-347.83131012,1094.39540993)(-348.10439311,1094.13127263)(-348.08555096,1094.37717288) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-348.08555096,1094.37717288) \curveto(-347.83131012,1094.39540993)(-348.10439311,1094.13127263)(-348.08555096,1094.37717288) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.38685513,1094.11627076) \lineto(-444.62288774,1094.21410906) \lineto(-444.38685513,1094.11627076) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.38685513,1094.11627076) \lineto(-444.62288774,1094.21410906) \lineto(-444.38685513,1094.11627076) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.99182408,1093.72491759) \lineto(-439.39645141,1094.24672182) \lineto(-438.99182408,1093.72491759) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.99182408,1093.72491759) \lineto(-439.39645141,1094.24672182) \lineto(-438.99182408,1093.72491759) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-432.78753838,1093.20311337) \curveto(-432.84352532,1093.63047103)(-432.82005693,1094.16649442)(-432.28175422,1094.21410906) \curveto(-432.18475156,1093.91968102)(-432.20951476,1093.46336322)(-432.61894366,1093.43140272) \lineto(-432.78753838,1093.20311337) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-432.78753838,1093.20311337) \curveto(-432.84352532,1093.63047103)(-432.82005693,1094.16649442)(-432.28175422,1094.21410906) \curveto(-432.18475156,1093.91968102)(-432.20951476,1093.46336322)(-432.61894366,1093.43140272) \lineto(-432.78753838,1093.20311337) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-431.30390484,1094.24672182) \curveto(-430.98532826,1094.11209633)(-431.25391988,1093.71226384)(-431.33762379,1093.49662824) \lineto(-431.40506168,1093.49662824) \lineto(-431.30390484,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-431.30390484,1094.24672182) \curveto(-430.98532826,1094.11209633)(-431.25391988,1093.71226384)(-431.33762379,1093.49662824) \lineto(-431.40506168,1093.49662824) \lineto(-431.30390484,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-351.32256959,1094.24672182) \curveto(-351.30371395,1094.00082158)(-351.57681043,1094.26495888)(-351.32256959,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-351.32256959,1094.24672182) \curveto(-351.30371395,1094.00082158)(-351.57681043,1094.26495888)(-351.32256959,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-348.35530251,1094.24672182) \curveto(-348.10106167,1094.26495888)(-348.37414466,1094.00082158)(-348.35530251,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-348.35530251,1094.24672182) \curveto(-348.10106167,1094.26495888)(-348.37414466,1094.00082158)(-348.35530251,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-332.30508515,1094.24672182) \curveto(-331.64230559,1094.26237595)(-332.70593596,1093.71878639)(-332.30508515,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-332.30508515,1094.24672182) \curveto(-331.64230559,1094.26237595)(-332.70593596,1093.71878639)(-332.30508515,1094.24672182) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.84735203,1093.85536865) \lineto(-444.38685513,1094.11627076) \lineto(-443.84735203,1093.85536865) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.84735203,1093.85536865) \lineto(-444.38685513,1094.11627076) \lineto(-443.84735203,1093.85536865) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-348.89480562,1093.98581971) \lineto(-348.65877301,1094.083658) \lineto(-348.89480562,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-348.89480562,1093.98581971) \lineto(-348.65877301,1094.083658) \lineto(-348.89480562,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.77965023,1093.98581971) \curveto(-408.76080808,1093.73991946)(-409.03389107,1094.00405676)(-408.77965023,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.77965023,1093.98581971) \curveto(-408.76080808,1093.73991946)(-409.03389107,1094.00405676)(-408.77965023,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-351.99694847,1093.98581971) \curveto(-351.74270763,1094.00405676)(-352.01579061,1093.73991946)(-351.99694847,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-351.99694847,1093.98581971) \curveto(-351.74270763,1094.00405676)(-352.01579061,1093.73991946)(-351.99694847,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-348.89480562,1093.98581971) \lineto(-349.265714,1093.88798141) \lineto(-348.89480562,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-348.89480562,1093.98581971) \lineto(-349.265714,1093.88798141) \lineto(-348.89480562,1093.98581971) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.57760047,1093.72491759) \lineto(-443.84735203,1093.85536865) \lineto(-443.57760047,1093.72491759) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.57760047,1093.72491759) \lineto(-443.84735203,1093.85536865) \lineto(-443.57760047,1093.72491759) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.30784892,1093.59446654) \lineto(-443.57760047,1093.72491759) \lineto(-443.30784892,1093.59446654) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.30784892,1093.59446654) \lineto(-443.57760047,1093.72491759) \lineto(-443.30784892,1093.59446654) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-349.83893605,1093.72491759) \lineto(-349.60290344,1093.6270793) \lineto(-349.83893605,1093.72491759) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-349.83893605,1093.72491759) \lineto(-349.60290344,1093.6270793) \lineto(-349.83893605,1093.72491759) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.17297314,1093.46401548) \lineto(-443.30784892,1093.59446654) \lineto(-443.17297314,1093.46401548) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.17297314,1093.46401548) \lineto(-443.30784892,1093.59446654) \lineto(-443.17297314,1093.46401548) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.90322159,1093.20311337) \lineto(-443.17297314,1093.46401548) \lineto(-442.90322159,1093.20311337) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.90322159,1093.20311337) \lineto(-443.17297314,1093.46401548) \lineto(-442.90322159,1093.20311337) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.63347004,1092.94221125) \lineto(-442.90322159,1093.20311337) \lineto(-442.63347004,1092.94221125) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.63347004,1092.94221125) \lineto(-442.90322159,1093.20311337) \lineto(-442.63347004,1092.94221125) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-432.78753838,1093.20311337) \curveto(-432.76869624,1092.95721312)(-433.04177922,1093.22135042)(-432.78753838,1093.20311337) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-432.78753838,1093.20311337) \curveto(-432.76869624,1092.95721312)(-433.04177922,1093.22135042)(-432.78753838,1093.20311337) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.49859426,1092.8117602) \lineto(-442.63347004,1092.94221125) \lineto(-442.49859426,1092.8117602) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.49859426,1092.8117602) \lineto(-442.63347004,1092.94221125) \lineto(-442.49859426,1092.8117602) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.36371849,1092.68130914) \lineto(-442.49859426,1092.8117602) \lineto(-442.36371849,1092.68130914) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.36371849,1092.68130914) \lineto(-442.49859426,1092.8117602) \lineto(-442.36371849,1092.68130914) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.22884271,1092.55085808) \lineto(-442.36371849,1092.68130914) \lineto(-442.22884271,1092.55085808) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.22884271,1092.55085808) \lineto(-442.36371849,1092.68130914) \lineto(-442.22884271,1092.55085808) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.09396694,1092.42040703) \lineto(-442.22884271,1092.55085808) \lineto(-442.09396694,1092.42040703) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.09396694,1092.42040703) \lineto(-442.22884271,1092.55085808) \lineto(-442.09396694,1092.42040703) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.95909116,1092.28995597) \lineto(-442.09396694,1092.42040703) \lineto(-441.95909116,1092.28995597) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.95909116,1092.28995597) \lineto(-442.09396694,1092.42040703) \lineto(-441.95909116,1092.28995597) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.82421538,1092.15950491) \lineto(-441.95909116,1092.28995597) \lineto(-441.82421538,1092.15950491) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.82421538,1092.15950491) \lineto(-441.95909116,1092.28995597) \lineto(-441.82421538,1092.15950491) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.68933961,1092.02905386) \lineto(-441.82421538,1092.15950491) \lineto(-441.68933961,1092.02905386) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.68933961,1092.02905386) \lineto(-441.82421538,1092.15950491) \lineto(-441.68933961,1092.02905386) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-336.75598576,1092.15950491) \lineto(-336.2502016,1092.12689215) \lineto(-337.05945626,1091.40941134) \lineto(-337.26176992,1091.40941134) \lineto(-336.99201837,1091.73553898) \lineto(-336.75598576,1092.15950491) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-336.75598576,1092.15950491) \lineto(-336.2502016,1092.12689215) \lineto(-337.05945626,1091.40941134) \lineto(-337.26176992,1091.40941134) \lineto(-336.99201837,1091.73553898) \lineto(-336.75598576,1092.15950491) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.94949488,1092.02905386) \curveto(-446.69525404,1092.04729091)(-446.96835051,1091.78315361)(-446.94949488,1092.02905386) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.94949488,1092.02905386) \curveto(-446.69525404,1092.04729091)(-446.96835051,1091.78315361)(-446.94949488,1092.02905386) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.68933961,1092.02905386) \curveto(-441.43509877,1092.04729091)(-441.70819524,1091.78315361)(-441.68933961,1092.02905386) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.68933961,1092.02905386) \curveto(-441.43509877,1092.04729091)(-441.70819524,1091.78315361)(-441.68933961,1092.02905386) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.275116,1091.63770069) \lineto(-446.64602438,1091.86599003) \lineto(-446.275116,1091.63770069) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.275116,1091.63770069) \lineto(-446.64602438,1091.86599003) \lineto(-446.275116,1091.63770069) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.87048867,1091.37679857) \lineto(-446.275116,1091.63770069) \lineto(-445.87048867,1091.37679857) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.87048867,1091.37679857) \lineto(-446.275116,1091.63770069) \lineto(-445.87048867,1091.37679857) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.87048867,1091.37679857) \curveto(-445.67505367,1091.4312358)(-445.38331736,1091.21856144)(-445.49958028,1091.01805817) \lineto(-445.87048867,1091.37679857) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.87048867,1091.37679857) \curveto(-445.67505367,1091.4312358)(-445.38331736,1091.21856144)(-445.49958028,1091.01805817) \lineto(-445.87048867,1091.37679857) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.19610979,1090.85499434) \curveto(-445.45035063,1090.83675729)(-445.17725415,1091.10089459)(-445.19610979,1090.85499434) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.19610979,1090.85499434) \curveto(-445.45035063,1090.83675729)(-445.17725415,1091.10089459)(-445.19610979,1090.85499434) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.29430856,1090.9854454) \curveto(-436.04006772,1091.00368246)(-436.31315071,1090.73954516)(-436.29430856,1090.9854454) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.29430856,1090.9854454) \curveto(-436.04006772,1091.00368246)(-436.31315071,1090.73954516)(-436.29430856,1090.9854454) \closepath } } { \newrgbcolor{curcolor}{0.88627452 0.88627452 0.88627452} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-334.05847024,1090.9854454) \lineto(-333.62012397,1090.49625394) \lineto(-332.60855565,1090.82238158) \lineto(-335.57582272,1088.53948809) \curveto(-336.42162872,1088.11108682)(-337.07024632,1087.36099324)(-337.66639725,1086.64794777) \lineto(-337.66639725,1086.32182012) \lineto(-337.53152148,1086.19136907) \lineto(-336.72226682,1086.12614354) \lineto(-335.17119539,1087.36542858) \lineto(-332.60855565,1088.73516467) \lineto(-332.3388041,1088.53948809) \lineto(-332.8783072,1087.75678175) \curveto(-334.38891589,1087.03838778)(-335.39508918,1085.59259872)(-336.31763949,1084.29982874) \lineto(-336.45251527,1083.71279899) \lineto(-336.11532583,1083.45189688) \lineto(-336.21648266,1082.76702883) \lineto(-336.31763949,1082.79964159) \lineto(-337.19433204,1084.95208403) \lineto(-338.50937085,1087.0719137) \lineto(-337.59895937,1088.01768386) \lineto(-334.22706496,1090.75715605) \lineto(-334.05847024,1090.9854454) \closepath } } { \newrgbcolor{curcolor}{0.88627452 0.88627452 0.88627452} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-334.05847024,1090.9854454) \lineto(-333.62012397,1090.49625394) \lineto(-332.60855565,1090.82238158) \lineto(-335.57582272,1088.53948809) \curveto(-336.42162872,1088.11108682)(-337.07024632,1087.36099324)(-337.66639725,1086.64794777) \lineto(-337.66639725,1086.32182012) \lineto(-337.53152148,1086.19136907) \lineto(-336.72226682,1086.12614354) \lineto(-335.17119539,1087.36542858) \lineto(-332.60855565,1088.73516467) \lineto(-332.3388041,1088.53948809) \lineto(-332.8783072,1087.75678175) \curveto(-334.38891589,1087.03838778)(-335.39508918,1085.59259872)(-336.31763949,1084.29982874) \lineto(-336.45251527,1083.71279899) \lineto(-336.11532583,1083.45189688) \lineto(-336.21648266,1082.76702883) \lineto(-336.31763949,1082.79964159) \lineto(-337.19433204,1084.95208403) \lineto(-338.50937085,1087.0719137) \lineto(-337.59895937,1088.01768386) \lineto(-334.22706496,1090.75715605) \lineto(-334.05847024,1090.9854454) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.06123401,1090.72454329) \lineto(-445.19610979,1090.85499434) \lineto(-445.06123401,1090.72454329) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.06123401,1090.72454329) \lineto(-445.19610979,1090.85499434) \lineto(-445.06123401,1090.72454329) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.67974332,1090.59409223) \lineto(-447.18552749,1090.69193052) \lineto(-446.67974332,1090.59409223) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.67974332,1090.59409223) \lineto(-447.18552749,1090.69193052) \lineto(-446.67974332,1090.59409223) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.92635823,1090.59409223) \lineto(-445.06123401,1090.72454329) \lineto(-444.92635823,1090.59409223) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.92635823,1090.59409223) \lineto(-445.06123401,1090.72454329) \lineto(-444.92635823,1090.59409223) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.40999177,1090.46364117) \lineto(-446.67974332,1090.59409223) \lineto(-446.40999177,1090.46364117) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.40999177,1090.46364117) \lineto(-446.67974332,1090.59409223) \lineto(-446.40999177,1090.46364117) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.92635823,1090.59409223) \lineto(-444.69032563,1090.36580288) \lineto(-444.92635823,1090.59409223) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.92635823,1090.59409223) \lineto(-444.69032563,1090.36580288) \lineto(-444.92635823,1090.59409223) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.14024022,1090.33319012) \lineto(-446.40999177,1090.46364117) \lineto(-446.14024022,1090.33319012) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.14024022,1090.33319012) \lineto(-446.40999177,1090.46364117) \lineto(-446.14024022,1090.33319012) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.14024022,1090.33319012) \lineto(-445.90420761,1090.23535183) \lineto(-446.14024022,1090.33319012) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.14024022,1090.33319012) \lineto(-445.90420761,1090.23535183) \lineto(-446.14024022,1090.33319012) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-332.43996093,1090.33319012) \curveto(-332.03061295,1090.23128175)(-332.63971195,1089.87061067)(-332.67599354,1090.1701263) \lineto(-332.5748367,1090.20273906) \lineto(-332.43996093,1090.33319012) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-332.43996093,1090.33319012) \curveto(-332.03061295,1090.23128175)(-332.63971195,1089.87061067)(-332.67599354,1090.1701263) \lineto(-332.5748367,1090.20273906) \lineto(-332.43996093,1090.33319012) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.38685513,1090.072288) \curveto(-444.64109597,1090.05405095)(-444.3679995,1090.31818825)(-444.38685513,1090.072288) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.38685513,1090.072288) \curveto(-444.64109597,1090.05405095)(-444.3679995,1090.31818825)(-444.38685513,1090.072288) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.19610979,1089.81138589) \lineto(-445.56701817,1090.03967524) \lineto(-445.19610979,1089.81138589) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.19610979,1089.81138589) \lineto(-445.56701817,1090.03967524) \lineto(-445.19610979,1089.81138589) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.25197935,1089.94183695) \lineto(-444.38685513,1090.072288) \lineto(-444.25197935,1089.94183695) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.25197935,1089.94183695) \lineto(-444.38685513,1090.072288) \lineto(-444.25197935,1089.94183695) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.9822278,1089.68093483) \lineto(-444.25197935,1089.94183695) \lineto(-443.9822278,1089.68093483) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.9822278,1089.68093483) \lineto(-444.25197935,1089.94183695) \lineto(-443.9822278,1089.68093483) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.35412221,1089.81138589) \curveto(-447.09988137,1089.82962295)(-447.37297784,1089.56548565)(-447.35412221,1089.81138589) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.35412221,1089.81138589) \curveto(-447.09988137,1089.82962295)(-447.37297784,1089.56548565)(-447.35412221,1089.81138589) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.19610979,1089.81138589) \curveto(-444.94186895,1089.82962295)(-445.21496542,1089.56548565)(-445.19610979,1089.81138589) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.19610979,1089.81138589) \curveto(-444.94186895,1089.82962295)(-445.21496542,1089.56548565)(-445.19610979,1089.81138589) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.67974332,1089.55048378) \lineto(-447.05065171,1089.64832207) \lineto(-446.67974332,1089.55048378) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.67974332,1089.55048378) \lineto(-447.05065171,1089.64832207) \lineto(-446.67974332,1089.55048378) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.92635823,1089.68093483) \lineto(-444.69032563,1089.45264549) \lineto(-444.92635823,1089.68093483) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.92635823,1089.68093483) \lineto(-444.69032563,1089.45264549) \lineto(-444.92635823,1089.68093483) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.84735203,1089.55048378) \lineto(-443.9822278,1089.68093483) \lineto(-443.84735203,1089.55048378) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.84735203,1089.55048378) \lineto(-443.9822278,1089.68093483) \lineto(-443.84735203,1089.55048378) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.00536444,1089.28958166) \lineto(-446.67974332,1089.55048378) \lineto(-446.00536444,1089.28958166) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.00536444,1089.28958166) \lineto(-446.67974332,1089.55048378) \lineto(-446.00536444,1089.28958166) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.03809737,1088.76777744) \curveto(-443.5089487,1088.66916948)(-443.81174482,1089.17856781)(-443.84735203,1089.55048378) \curveto(-443.4610678,1089.43159068)(-443.1609692,1089.14138926)(-443.03809737,1088.76777744) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.03809737,1088.76777744) \curveto(-443.5089487,1088.66916948)(-443.81174482,1089.17856781)(-443.84735203,1089.55048378) \curveto(-443.4610678,1089.43159068)(-443.1609692,1089.14138926)(-443.03809737,1088.76777744) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.11710358,1089.02867955) \curveto(-444.31253858,1088.97424232)(-444.60427488,1089.18691668)(-444.48801196,1089.38741996) \lineto(-444.11710358,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.11710358,1089.02867955) \curveto(-444.31253858,1088.97424232)(-444.60427488,1089.18691668)(-444.48801196,1089.38741996) \lineto(-444.11710358,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.73561289,1089.15913061) \lineto(-446.00536444,1089.28958166) \lineto(-445.73561289,1089.15913061) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.73561289,1089.15913061) \lineto(-446.00536444,1089.28958166) \lineto(-445.73561289,1089.15913061) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.46586134,1089.02867955) \lineto(-445.73561289,1089.15913061) \lineto(-445.46586134,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.46586134,1089.02867955) \lineto(-445.73561289,1089.15913061) \lineto(-445.46586134,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.6901961 0.6901961 0.6901961} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-336.35135844,1087.20236476) \lineto(-335.44094695,1088.01768386) \curveto(-334.92086595,1088.59232077)(-334.22558133,1088.92014427)(-333.51896714,1089.15913061) \lineto(-333.28293453,1089.12651784) \lineto(-333.28293453,1089.06129231) \lineto(-336.11532583,1087.23497752) \lineto(-336.35135844,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.6901961 0.6901961 0.6901961} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-336.35135844,1087.20236476) \lineto(-335.44094695,1088.01768386) \curveto(-334.92086595,1088.59232077)(-334.22558133,1088.92014427)(-333.51896714,1089.15913061) \lineto(-333.28293453,1089.12651784) \lineto(-333.28293453,1089.06129231) \lineto(-336.11532583,1087.23497752) \lineto(-336.35135844,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.83775574,1089.02867955) \lineto(-447.6575927,1088.40903703) \lineto(-447.75874953,1088.37642427) \lineto(-448.83775574,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.83775574,1089.02867955) \lineto(-447.6575927,1088.40903703) \lineto(-447.75874953,1088.37642427) \lineto(-448.83775574,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.46586134,1089.02867955) \curveto(-445.2116205,1089.04691661)(-445.48471697,1088.78277931)(-445.46586134,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.46586134,1089.02867955) \curveto(-445.2116205,1089.04691661)(-445.48471697,1088.78277931)(-445.46586134,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.11710358,1089.02867955) \curveto(-443.86286274,1089.04691661)(-444.13595921,1088.78277931)(-444.11710358,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.11710358,1089.02867955) \curveto(-443.86286274,1089.04691661)(-444.13595921,1088.78277931)(-444.11710358,1089.02867955) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.65660668,1088.37642427) \lineto(-445.16239084,1088.73516467) \lineto(-444.65660668,1088.37642427) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.65660668,1088.37642427) \lineto(-445.16239084,1088.73516467) \lineto(-444.65660668,1088.37642427) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.90322159,1088.63732638) \lineto(-443.03809737,1088.76777744) \lineto(-442.90322159,1088.63732638) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.90322159,1088.63732638) \lineto(-443.03809737,1088.76777744) \lineto(-442.90322159,1088.63732638) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.49859426,1088.37642427) \lineto(-442.90322159,1088.63732638) \lineto(-442.49859426,1088.37642427) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.49859426,1088.37642427) \lineto(-442.90322159,1088.63732638) \lineto(-442.49859426,1088.37642427) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.35412221,1088.24597321) \curveto(-447.60836304,1088.22773615)(-447.33526657,1088.49187345)(-447.35412221,1088.24597321) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.35412221,1088.24597321) \curveto(-447.60836304,1088.22773615)(-447.33526657,1088.49187345)(-447.35412221,1088.24597321) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.65660668,1088.37642427) \lineto(-444.42057407,1088.14813492) \lineto(-444.65660668,1088.37642427) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.65660668,1088.37642427) \lineto(-444.42057407,1088.14813492) \lineto(-444.65660668,1088.37642427) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.36371849,1088.24597321) \lineto(-442.49859426,1088.37642427) \lineto(-442.36371849,1088.24597321) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.36371849,1088.24597321) \lineto(-442.49859426,1088.37642427) \lineto(-442.36371849,1088.24597321) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.08437065,1088.11552215) \lineto(-447.35412221,1088.24597321) \lineto(-447.08437065,1088.11552215) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.08437065,1088.11552215) \lineto(-447.35412221,1088.24597321) \lineto(-447.08437065,1088.11552215) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.09396694,1087.85462004) \lineto(-442.36371849,1088.24597321) \lineto(-442.09396694,1087.85462004) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.09396694,1087.85462004) \lineto(-442.36371849,1088.24597321) \lineto(-442.09396694,1087.85462004) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.08437065,1088.11552215) \curveto(-446.927645,1088.13698135)(-446.56388503,1088.13902943)(-446.71346227,1087.8872328) \lineto(-447.08437065,1088.11552215) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.08437065,1088.11552215) \curveto(-446.927645,1088.13698135)(-446.56388503,1088.13902943)(-446.71346227,1087.8872328) \lineto(-447.08437065,1088.11552215) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.11710358,1087.9850711) \curveto(-444.37134442,1087.96683404)(-444.09824794,1088.23097134)(-444.11710358,1087.9850711) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.11710358,1087.9850711) \curveto(-444.37134442,1087.96683404)(-444.09824794,1088.23097134)(-444.11710358,1087.9850711) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.71247625,1087.72416898) \lineto(-444.11710358,1087.9850711) \lineto(-443.71247625,1087.72416898) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.71247625,1087.72416898) \lineto(-444.11710358,1087.9850711) \lineto(-443.71247625,1087.72416898) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.14024022,1087.59371793) \lineto(-446.5111486,1087.82200728) \lineto(-446.14024022,1087.59371793) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.14024022,1087.59371793) \lineto(-446.5111486,1087.82200728) \lineto(-446.14024022,1087.59371793) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.95909116,1087.72416898) \lineto(-442.09396694,1087.85462004) \lineto(-441.95909116,1087.72416898) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.95909116,1087.72416898) \lineto(-442.09396694,1087.85462004) \lineto(-441.95909116,1087.72416898) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.71247625,1087.72416898) \lineto(-443.47644364,1087.49587963) \lineto(-443.71247625,1087.72416898) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.71247625,1087.72416898) \lineto(-443.47644364,1087.49587963) \lineto(-443.71247625,1087.72416898) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.82421538,1087.59371793) \lineto(-441.95909116,1087.72416898) \lineto(-441.82421538,1087.59371793) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.82421538,1087.59371793) \lineto(-441.95909116,1087.72416898) \lineto(-441.82421538,1087.59371793) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-449.24238307,1087.46326687) \lineto(-449.47841568,1087.56110516) \lineto(-449.24238307,1087.46326687) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-449.24238307,1087.46326687) \lineto(-449.47841568,1087.56110516) \lineto(-449.24238307,1087.46326687) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.87048867,1087.46326687) \lineto(-446.14024022,1087.59371793) \lineto(-445.87048867,1087.46326687) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.87048867,1087.46326687) \lineto(-446.14024022,1087.59371793) \lineto(-445.87048867,1087.46326687) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.55446383,1087.33281581) \lineto(-441.82421538,1087.59371793) \lineto(-441.55446383,1087.33281581) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.55446383,1087.33281581) \lineto(-441.82421538,1087.59371793) \lineto(-441.55446383,1087.33281581) \closepath } } { \newrgbcolor{curcolor}{0.63137257 0.63137257 0.63137257} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.11433981,1086.94146264) \lineto(-332.94574509,1087.16975199) \lineto(-331.66442521,1087.56110516) \lineto(-332.8783072,1086.97407541) \lineto(-333.11433981,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.63137257 0.63137257 0.63137257} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.11433981,1086.94146264) \lineto(-332.94574509,1087.16975199) \lineto(-331.66442521,1087.56110516) \lineto(-332.8783072,1086.97407541) \lineto(-333.11433981,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.79215688 0.79215688 0.79215688} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-329.87732118,1087.59371793) \lineto(-329.5064128,1087.49587963) \curveto(-330.24593668,1087.176405)(-330.9145159,1086.74578606)(-331.46211155,1086.12614354) \lineto(-331.39467366,1085.93046695) \lineto(-331.66442521,1085.66956484) \lineto(-332.47367987,1085.27821167) \lineto(-334.49681651,1084.23460322) \lineto(-334.69913018,1084.23460322) \lineto(-331.19236,1087.03930094) \lineto(-329.87732118,1087.59371793) \closepath } } { \newrgbcolor{curcolor}{0.79215688 0.79215688 0.79215688} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-329.87732118,1087.59371793) \lineto(-329.5064128,1087.49587963) \curveto(-330.24593668,1087.176405)(-330.9145159,1086.74578606)(-331.46211155,1086.12614354) \lineto(-331.39467366,1085.93046695) \lineto(-331.66442521,1085.66956484) \lineto(-332.47367987,1085.27821167) \lineto(-334.49681651,1084.23460322) \lineto(-334.69913018,1084.23460322) \lineto(-331.19236,1087.03930094) \lineto(-329.87732118,1087.59371793) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.70287997,1087.20236476) \lineto(-449.24238307,1087.46326687) \lineto(-448.70287997,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.70287997,1087.20236476) \lineto(-449.24238307,1087.46326687) \lineto(-448.70287997,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.73561289,1087.33281581) \lineto(-445.87048867,1087.46326687) \lineto(-445.73561289,1087.33281581) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.73561289,1087.33281581) \lineto(-445.87048867,1087.46326687) \lineto(-445.73561289,1087.33281581) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.17297314,1087.33281581) \curveto(-443.42721398,1087.31457876)(-443.15411751,1087.57871606)(-443.17297314,1087.33281581) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.17297314,1087.33281581) \curveto(-443.42721398,1087.31457876)(-443.15411751,1087.57871606)(-443.17297314,1087.33281581) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.33098556,1087.0719137) \lineto(-445.73561289,1087.33281581) \lineto(-445.33098556,1087.0719137) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.33098556,1087.0719137) \lineto(-445.73561289,1087.33281581) \lineto(-445.33098556,1087.0719137) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.03809737,1087.20236476) \lineto(-443.17297314,1087.33281581) \lineto(-443.03809737,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.03809737,1087.20236476) \lineto(-443.17297314,1087.33281581) \lineto(-443.03809737,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.41958806,1087.20236476) \lineto(-441.55446383,1087.33281581) \lineto(-441.41958806,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.41958806,1087.20236476) \lineto(-441.55446383,1087.33281581) \lineto(-441.41958806,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.70287997,1087.20236476) \curveto(-448.44863913,1087.22060181)(-448.7217356,1086.95646451)(-448.70287997,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.70287997,1087.20236476) \curveto(-448.44863913,1087.22060181)(-448.7217356,1086.95646451)(-448.70287997,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.90322159,1087.0719137) \lineto(-443.03809737,1087.20236476) \lineto(-442.90322159,1087.0719137) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.90322159,1087.0719137) \lineto(-443.03809737,1087.20236476) \lineto(-442.90322159,1087.0719137) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.41958806,1087.20236476) \curveto(-441.16534722,1087.22060181)(-441.43844369,1086.95646451)(-441.41958806,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.41958806,1087.20236476) \curveto(-441.16534722,1087.22060181)(-441.43844369,1086.95646451)(-441.41958806,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-336.35135844,1087.20236476) \curveto(-336.3325028,1086.95646451)(-336.60559927,1087.22060181)(-336.35135844,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-336.35135844,1087.20236476) \curveto(-336.3325028,1086.95646451)(-336.60559927,1087.22060181)(-336.35135844,1087.20236476) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.29825264,1086.94146264) \curveto(-448.55249348,1086.92322559)(-448.27939701,1087.18736289)(-448.29825264,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.29825264,1086.94146264) \curveto(-448.55249348,1086.92322559)(-448.27939701,1087.18736289)(-448.29825264,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.33098556,1087.0719137) \curveto(-445.07674473,1087.09015076)(-445.3498412,1086.82601346)(-445.33098556,1087.0719137) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.33098556,1087.0719137) \curveto(-445.07674473,1087.09015076)(-445.3498412,1086.82601346)(-445.33098556,1087.0719137) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.76834582,1086.94146264) \lineto(-442.90322159,1087.0719137) \lineto(-442.76834582,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.76834582,1086.94146264) \lineto(-442.90322159,1087.0719137) \lineto(-442.76834582,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.29825264,1086.94146264) \lineto(-448.06222003,1086.84362435) \lineto(-448.29825264,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.29825264,1086.94146264) \lineto(-448.06222003,1086.84362435) \lineto(-448.29825264,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.49859426,1086.68056053) \lineto(-442.76834582,1086.94146264) \lineto(-442.49859426,1086.68056053) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.49859426,1086.68056053) \lineto(-442.76834582,1086.94146264) \lineto(-442.49859426,1086.68056053) \closepath } } { \newrgbcolor{curcolor}{0.56862748 0.56862748 0.56862748} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-336.75598576,1086.94146264) \curveto(-336.50174493,1086.9596997)(-336.77482791,1086.6955624)(-336.75598576,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.56862748 0.56862748 0.56862748} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-336.75598576,1086.94146264) \curveto(-336.50174493,1086.9596997)(-336.77482791,1086.6955624)(-336.75598576,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.11433981,1086.94146264) \lineto(-333.51896714,1086.68056053) \lineto(-333.11433981,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.11433981,1086.94146264) \lineto(-333.51896714,1086.68056053) \lineto(-333.11433981,1086.94146264) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.62387376,1086.55010947) \lineto(-447.85990637,1086.77839882) \lineto(-447.62387376,1086.55010947) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.62387376,1086.55010947) \lineto(-447.85990637,1086.77839882) \lineto(-447.62387376,1086.55010947) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.52173091,1086.41965842) \lineto(-445.02751507,1086.77839882) \lineto(-444.52173091,1086.41965842) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.52173091,1086.41965842) \lineto(-445.02751507,1086.77839882) \lineto(-444.52173091,1086.41965842) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.49859426,1086.68056053) \lineto(-442.26256166,1086.32182012) \lineto(-442.49859426,1086.68056053) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.49859426,1086.68056053) \lineto(-442.26256166,1086.32182012) \lineto(-442.49859426,1086.68056053) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.51896714,1086.68056053) \curveto(-333.5001115,1086.43466029)(-333.77320797,1086.69879759)(-333.51896714,1086.68056053) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.51896714,1086.68056053) \curveto(-333.5001115,1086.43466029)(-333.77320797,1086.69879759)(-333.51896714,1086.68056053) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.35412221,1086.41965842) \lineto(-447.62387376,1086.55010947) \lineto(-447.35412221,1086.41965842) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.35412221,1086.41965842) \lineto(-447.62387376,1086.55010947) \lineto(-447.35412221,1086.41965842) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.53527127,1086.41965842) \lineto(-451.02948711,1086.2565946) \lineto(-451.02948711,1086.19136907) \curveto(-451.22667549,1086.08117706)(-451.49507828,1086.20928)(-451.53527127,1086.41965842) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.53527127,1086.41965842) \lineto(-451.02948711,1086.2565946) \lineto(-451.02948711,1086.19136907) \curveto(-451.22667549,1086.08117706)(-451.49507828,1086.20928)(-451.53527127,1086.41965842) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.21924643,1086.28920736) \lineto(-447.35412221,1086.41965842) \lineto(-447.21924643,1086.28920736) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.21924643,1086.28920736) \lineto(-447.35412221,1086.41965842) \lineto(-447.21924643,1086.28920736) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.25197935,1086.1587563) \lineto(-444.52173091,1086.41965842) \lineto(-444.25197935,1086.1587563) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.25197935,1086.1587563) \lineto(-444.52173091,1086.41965842) \lineto(-444.25197935,1086.1587563) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.8146191,1086.02830525) \lineto(-447.21924643,1086.28920736) \lineto(-446.8146191,1086.02830525) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.8146191,1086.02830525) \lineto(-447.21924643,1086.28920736) \lineto(-446.8146191,1086.02830525) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-450.72601661,1086.02830525) \curveto(-450.98025745,1086.01006819)(-450.70716098,1086.27420549)(-450.72601661,1086.02830525) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-450.72601661,1086.02830525) \curveto(-450.98025745,1086.01006819)(-450.70716098,1086.27420549)(-450.72601661,1086.02830525) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.11710358,1086.02830525) \lineto(-444.25197935,1086.1587563) \lineto(-444.11710358,1086.02830525) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.11710358,1086.02830525) \lineto(-444.25197935,1086.1587563) \lineto(-444.11710358,1086.02830525) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.09396694,1086.1587563) \lineto(-441.9928101,1085.93046695) \lineto(-442.09396694,1086.1587563) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.09396694,1086.1587563) \lineto(-441.9928101,1085.93046695) \lineto(-442.09396694,1086.1587563) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-450.32138928,1085.89785419) \lineto(-450.72601661,1086.02830525) \lineto(-450.32138928,1085.89785419) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-450.32138928,1085.89785419) \lineto(-450.72601661,1086.02830525) \lineto(-450.32138928,1085.89785419) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-450.32138928,1085.89785419) \lineto(-449.78188618,1086.02830525) \lineto(-448.8040368,1085.53911378) \curveto(-447.86813379,1085.40383604)(-446.91712469,1085.06414149)(-446.24139705,1084.36505427) \lineto(-444.8252014,1083.5171224) \lineto(-444.15082252,1082.86486712) \lineto(-443.20669209,1081.82125867) \lineto(-443.34156787,1081.36467997) \lineto(-443.94850886,1081.8864842) \lineto(-444.55544985,1082.86486712) \lineto(-446.44371072,1084.29982874) \lineto(-450.01791878,1085.66956484) \lineto(-450.32138928,1085.89785419) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-450.32138928,1085.89785419) \lineto(-449.78188618,1086.02830525) \lineto(-448.8040368,1085.53911378) \curveto(-447.86813379,1085.40383604)(-446.91712469,1085.06414149)(-446.24139705,1084.36505427) \lineto(-444.8252014,1083.5171224) \lineto(-444.15082252,1082.86486712) \lineto(-443.20669209,1081.82125867) \lineto(-443.34156787,1081.36467997) \lineto(-443.94850886,1081.8864842) \lineto(-444.55544985,1082.86486712) \lineto(-446.44371072,1084.29982874) \lineto(-450.01791878,1085.66956484) \lineto(-450.32138928,1085.89785419) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.54486755,1085.89785419) \lineto(-446.8146191,1086.02830525) \lineto(-446.54486755,1085.89785419) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.54486755,1085.89785419) \lineto(-446.8146191,1086.02830525) \lineto(-446.54486755,1085.89785419) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.9822278,1085.89785419) \lineto(-444.11710358,1086.02830525) \lineto(-443.9822278,1085.89785419) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.9822278,1085.89785419) \lineto(-444.11710358,1086.02830525) \lineto(-443.9822278,1085.89785419) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.275116,1085.76740313) \lineto(-446.54486755,1085.89785419) \lineto(-446.275116,1085.76740313) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.275116,1085.76740313) \lineto(-446.54486755,1085.89785419) \lineto(-446.275116,1085.76740313) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.84735203,1085.76740313) \lineto(-443.9822278,1085.89785419) \lineto(-443.84735203,1085.76740313) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.84735203,1085.76740313) \lineto(-443.9822278,1085.89785419) \lineto(-443.84735203,1085.76740313) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.87048867,1085.50650102) \lineto(-446.275116,1085.76740313) \lineto(-445.87048867,1085.50650102) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.87048867,1085.50650102) \lineto(-446.275116,1085.76740313) \lineto(-445.87048867,1085.50650102) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.03809737,1084.98469679) \lineto(-443.84735203,1085.76740313) \curveto(-443.48777321,1085.72738075)(-443.07950423,1085.33247931)(-443.03809737,1084.98469679) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.03809737,1084.98469679) \lineto(-443.84735203,1085.76740313) \curveto(-443.48777321,1085.72738075)(-443.07950423,1085.33247931)(-443.03809737,1084.98469679) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.60073712,1085.37604996) \lineto(-445.87048867,1085.50650102) \lineto(-445.60073712,1085.37604996) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.60073712,1085.37604996) \lineto(-445.87048867,1085.50650102) \lineto(-445.60073712,1085.37604996) \closepath } } { \newrgbcolor{curcolor}{0.90980393 0.90980393 0.90980393} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-409.31915333,1077.80988867) \lineto(-411.2074142,1079.50575241) \curveto(-411.76391165,1079.03143237)(-410.75342234,1078.22707115)(-410.53303532,1077.67943762) \lineto(-409.89237538,1075.88573559) \lineto(-410.43187849,1076.6032164) \lineto(-411.10625737,1077.77727591) \curveto(-411.33810882,1078.17971742)(-411.48013302,1078.81149189)(-411.98294991,1078.95133542) \lineto(-412.15154463,1078.59259501) \curveto(-411.42321544,1077.37692162)(-410.56810302,1076.13750613)(-410.56675426,1074.71167608) \lineto(-411.30857103,1076.01618664) \curveto(-411.86641724,1076.79289223)(-412.05955935,1078.27559895)(-413.1968319,1078.42953119) \lineto(-411.57832258,1075.10302925) \lineto(-411.37600892,1074.45077396) \lineto(-413.50030239,1077.94033973) \lineto(-413.736335,1077.77727591) \lineto(-413.50030239,1077.28808445) \curveto(-413.10187935,1076.76119263)(-412.61295466,1076.14872492)(-412.5898909,1075.49438242) \lineto(-412.72476668,1075.690059) \lineto(-413.39914556,1076.86411851) \curveto(-413.68710534,1077.08066727)(-413.78286714,1077.7016143)(-414.27583811,1077.51637379) \lineto(-414.41071388,1077.32069721) \curveto(-413.47926177,1075.99661898)(-412.32418562,1074.44033788)(-412.52245302,1072.88536128) \lineto(-412.82592351,1074.02680803) \lineto(-413.46658345,1075.36393136) \lineto(-414.47815177,1077.12502062) \curveto(-415.34742615,1077.27660475)(-414.59040888,1076.49324616)(-414.61302755,1076.1466377) \lineto(-414.95021699,1076.40753981) \lineto(-415.35484431,1076.86411851) \lineto(-415.52343903,1076.37492705) \curveto(-414.5782296,1074.94779249)(-413.79163407,1073.14887242)(-413.736335,1071.58085071) \curveto(-414.49636,1073.02103038)(-414.63150553,1075.05737138)(-416.16409897,1075.95096111) \lineto(-415.15253065,1073.40716551) \lineto(-415.82690953,1074.64645055) \curveto(-416.16477335,1074.99149359)(-416.78183003,1076.18055497)(-417.27682412,1075.46176965) \curveto(-416.02436767,1074.46734125)(-415.35754183,1072.81752673)(-415.15253065,1071.3199486) \lineto(-416.09666108,1072.82013575) \lineto(-417.64773251,1074.32032291) \curveto(-418.1589117,1074.70293585)(-418.16053021,1073.95584265)(-417.85004617,1073.73329315) \lineto(-416.33269369,1071.41778689) \curveto(-416.08195962,1070.9985172)(-416.45845187,1070.95481609)(-416.83847785,1071.05904649) \curveto(-417.27183372,1071.67020969)(-417.64786738,1073.27671445)(-418.45698717,1072.95058681) \lineto(-417.17566729,1070.4067912) \lineto(-418.86161449,1072.88536128) \curveto(-419.02400493,1073.00401956)(-419.22038406,1073.39633807)(-419.4011176,1073.08103787) \lineto(-417.54657568,1068.93921682) \lineto(-418.32211139,1070.27634015) \lineto(-419.13136605,1071.84175283) \curveto(-419.01117824,1072.33564053)(-419.85848136,1072.33564053)(-419.73830704,1071.84175283) \curveto(-419.97946493,1071.88302754)(-420.2791589,1072.24706426)(-420.48012381,1071.90697836) \lineto(-419.60343126,1070.01543803) \lineto(-419.97433965,1070.24372738) \lineto(-420.37896698,1070.11327633) \curveto(-419.96773073,1069.50393944)(-419.63283418,1068.80746125)(-419.60343126,1068.05867218) \curveto(-420.03570813,1069.05062202)(-420.68500011,1069.80410732)(-421.69400579,1070.08066356) \lineto(-421.35681635,1068.84137852) \lineto(-422.90788778,1069.55885933) \lineto(-422.16607101,1068.05867218) \lineto(-423.31251511,1068.64570194) \lineto(-422.16607101,1066.36280845) \lineto(-423.85201821,1068.12389771) \lineto(-423.64970455,1067.47164243) \lineto(-425.20077597,1067.60209348) \lineto(-424.4589592,1065.84100422) \lineto(-425.13333809,1066.42803397) \lineto(-425.77399802,1067.24335308) \lineto(-421.62656791,1071.84175283) \curveto(-417.4818353,1077.56724971)(-412.04229525,1083.17403612)(-404.99638471,1085.1216704) \curveto(-403.4223844,1085.33039209)(-401.86187167,1085.60616563)(-400.27573254,1085.25212146) \curveto(-396.00421671,1085.64738816)(-391.83655523,1083.69584035)(-388.71013474,1081.04507488) \lineto(-386.82187387,1079.4796622) \curveto(-386.32876803,1078.41178985)(-386.25755362,1076.98804702)(-386.48468443,1075.89225814) \curveto(-386.86328073,1076.8137644)(-386.66002294,1078.5169334)(-387.69856642,1078.82740691) \lineto(-387.83344219,1078.50127927) \curveto(-388.11762545,1079.1779289)(-388.44240632,1080.00668447)(-389.31707573,1079.74056431) \curveto(-389.16331734,1079.40400059)(-388.9864952,1078.10470806)(-389.48567045,1078.72956862) \lineto(-389.755422,1080.55588342) \lineto(-390.02517355,1078.46866651) \lineto(-390.19376827,1077.45767082) \lineto(-391.00302293,1082.21913439) \curveto(-391.19683942,1082.29157386)(-391.60699666,1082.30739757)(-391.50880709,1081.99084504) \lineto(-391.7448397,1080.19714301) \curveto(-391.601197,1079.72347522)(-391.17377566,1079.02621433)(-391.50880709,1078.59911757) \lineto(-392.21690492,1080.00146643) \lineto(-392.62153224,1082.08868333) \lineto(-394.03772789,1083.91499813) \lineto(-394.34119839,1080.81678553) \lineto(-394.07144684,1079.51227496) \lineto(-394.20632261,1079.12092179) \lineto(-395.85855087,1084.17590024) \lineto(-396.33061609,1084.04544918) \curveto(-396.11913087,1083.57321636)(-395.67822196,1083.12537788)(-395.85855087,1082.54526203) \curveto(-395.92509858,1082.76963785)(-396.24658848,1083.87586281)(-396.63408659,1083.16490455) \lineto(-396.2631782,1081.11030041) \lineto(-397.17358969,1082.64310032) \lineto(-397.44334124,1082.38219821) \curveto(-396.97518742,1081.07116509)(-395.90171112,1079.77317708)(-396.2631782,1078.37082822) \lineto(-397.98284435,1081.86039398) \lineto(-398.62350428,1083.19751732) \lineto(-399.06185056,1083.81715983) \curveto(-399.78937049,1083.50081602)(-398.14361627,1082.13695022)(-399.29788316,1082.21913439) \lineto(-399.43275894,1082.0234578) \curveto(-399.07587764,1081.40642431)(-398.4307668,1080.83074379)(-398.5560664,1080.06669195) \lineto(-399.19672633,1080.94723659) \lineto(-399.90482416,1082.21913439) \lineto(-400.51176515,1082.34958545) \lineto(-398.96069372,1078.76218139) \lineto(-401.79308502,1082.74093862) \lineto(-402.06283658,1082.54526203) \lineto(-401.35473875,1081.2081387) \lineto(-400.68035987,1079.77317708) \lineto(-400.71407881,1079.15353456) \lineto(-403.20928067,1082.87138967) \lineto(-403.24299962,1082.51264927) \curveto(-402.84309294,1082.1407333)(-402.84026055,1081.70241775)(-402.93952912,1081.24075146) \lineto(-402.56862074,1079.77317708) \lineto(-402.60233968,1079.0230835) \curveto(-403.66151915,1079.49570768)(-403.09976154,1081.62949561)(-404.42316266,1081.82778122) \lineto(-403.68134589,1079.15353456) \curveto(-405.61951079,1079.07555092)(-405.21623222,1082.41481097)(-406.71605085,1083.00184073) \lineto(-405.43473098,1079.67533878) \lineto(-407.18811607,1080.78417277) \lineto(-407.79505706,1081.37120252) \curveto(-407.95245709,1081.72472488)(-408.72381166,1081.683111)(-408.60431172,1081.24075146) \curveto(-407.89068399,1081.04285721)(-406.58791886,1079.6649027)(-407.25555396,1079.34921114) \curveto(-407.43925476,1079.07617708)(-407.55578743,1079.16162252)(-407.66018129,1079.41443667) \curveto(-407.84361234,1079.6779478)(-407.95434535,1080.48139586)(-408.40199805,1080.19714301) \curveto(-410.38197445,1081.89431126)(-407.77172355,1078.10601257)(-409.2786906,1078.17515163) \lineto(-409.31240954,1077.81641123) \lineto(-409.31915333,1077.80988867) \closepath } } { \newrgbcolor{curcolor}{0.90980393 0.90980393 0.90980393} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-409.31915333,1077.80988867) \lineto(-411.2074142,1079.50575241) \curveto(-411.76391165,1079.03143237)(-410.75342234,1078.22707115)(-410.53303532,1077.67943762) \lineto(-409.89237538,1075.88573559) \lineto(-410.43187849,1076.6032164) \lineto(-411.10625737,1077.77727591) \curveto(-411.33810882,1078.17971742)(-411.48013302,1078.81149189)(-411.98294991,1078.95133542) \lineto(-412.15154463,1078.59259501) \curveto(-411.42321544,1077.37692162)(-410.56810302,1076.13750613)(-410.56675426,1074.71167608) \lineto(-411.30857103,1076.01618664) \curveto(-411.86641724,1076.79289223)(-412.05955935,1078.27559895)(-413.1968319,1078.42953119) \lineto(-411.57832258,1075.10302925) \lineto(-411.37600892,1074.45077396) \lineto(-413.50030239,1077.94033973) \lineto(-413.736335,1077.77727591) \lineto(-413.50030239,1077.28808445) \curveto(-413.10187935,1076.76119263)(-412.61295466,1076.14872492)(-412.5898909,1075.49438242) \lineto(-412.72476668,1075.690059) \lineto(-413.39914556,1076.86411851) \curveto(-413.68710534,1077.08066727)(-413.78286714,1077.7016143)(-414.27583811,1077.51637379) \lineto(-414.41071388,1077.32069721) \curveto(-413.47926177,1075.99661898)(-412.32418562,1074.44033788)(-412.52245302,1072.88536128) \lineto(-412.82592351,1074.02680803) \lineto(-413.46658345,1075.36393136) \lineto(-414.47815177,1077.12502062) \curveto(-415.34742615,1077.27660475)(-414.59040888,1076.49324616)(-414.61302755,1076.1466377) \lineto(-414.95021699,1076.40753981) \lineto(-415.35484431,1076.86411851) \lineto(-415.52343903,1076.37492705) \curveto(-414.5782296,1074.94779249)(-413.79163407,1073.14887242)(-413.736335,1071.58085071) \curveto(-414.49636,1073.02103038)(-414.63150553,1075.05737138)(-416.16409897,1075.95096111) \lineto(-415.15253065,1073.40716551) \lineto(-415.82690953,1074.64645055) \curveto(-416.16477335,1074.99149359)(-416.78183003,1076.18055497)(-417.27682412,1075.46176965) \curveto(-416.02436767,1074.46734125)(-415.35754183,1072.81752673)(-415.15253065,1071.3199486) \lineto(-416.09666108,1072.82013575) \lineto(-417.64773251,1074.32032291) \curveto(-418.1589117,1074.70293585)(-418.16053021,1073.95584265)(-417.85004617,1073.73329315) \lineto(-416.33269369,1071.41778689) \curveto(-416.08195962,1070.9985172)(-416.45845187,1070.95481609)(-416.83847785,1071.05904649) \curveto(-417.27183372,1071.67020969)(-417.64786738,1073.27671445)(-418.45698717,1072.95058681) \lineto(-417.17566729,1070.4067912) \lineto(-418.86161449,1072.88536128) \curveto(-419.02400493,1073.00401956)(-419.22038406,1073.39633807)(-419.4011176,1073.08103787) \lineto(-417.54657568,1068.93921682) \lineto(-418.32211139,1070.27634015) \lineto(-419.13136605,1071.84175283) \curveto(-419.01117824,1072.33564053)(-419.85848136,1072.33564053)(-419.73830704,1071.84175283) \curveto(-419.97946493,1071.88302754)(-420.2791589,1072.24706426)(-420.48012381,1071.90697836) \lineto(-419.60343126,1070.01543803) \lineto(-419.97433965,1070.24372738) \lineto(-420.37896698,1070.11327633) \curveto(-419.96773073,1069.50393944)(-419.63283418,1068.80746125)(-419.60343126,1068.05867218) \curveto(-420.03570813,1069.05062202)(-420.68500011,1069.80410732)(-421.69400579,1070.08066356) \lineto(-421.35681635,1068.84137852) \lineto(-422.90788778,1069.55885933) \lineto(-422.16607101,1068.05867218) \lineto(-423.31251511,1068.64570194) \lineto(-422.16607101,1066.36280845) \lineto(-423.85201821,1068.12389771) \lineto(-423.64970455,1067.47164243) \lineto(-425.20077597,1067.60209348) \lineto(-424.4589592,1065.84100422) \lineto(-425.13333809,1066.42803397) \lineto(-425.77399802,1067.24335308) \lineto(-421.62656791,1071.84175283) \curveto(-417.4818353,1077.56724971)(-412.04229525,1083.17403612)(-404.99638471,1085.1216704) \curveto(-403.4223844,1085.33039209)(-401.86187167,1085.60616563)(-400.27573254,1085.25212146) \curveto(-396.00421671,1085.64738816)(-391.83655523,1083.69584035)(-388.71013474,1081.04507488) \lineto(-386.82187387,1079.4796622) \curveto(-386.32876803,1078.41178985)(-386.25755362,1076.98804702)(-386.48468443,1075.89225814) \curveto(-386.86328073,1076.8137644)(-386.66002294,1078.5169334)(-387.69856642,1078.82740691) \lineto(-387.83344219,1078.50127927) \curveto(-388.11762545,1079.1779289)(-388.44240632,1080.00668447)(-389.31707573,1079.74056431) \curveto(-389.16331734,1079.40400059)(-388.9864952,1078.10470806)(-389.48567045,1078.72956862) \lineto(-389.755422,1080.55588342) \lineto(-390.02517355,1078.46866651) \lineto(-390.19376827,1077.45767082) \lineto(-391.00302293,1082.21913439) \curveto(-391.19683942,1082.29157386)(-391.60699666,1082.30739757)(-391.50880709,1081.99084504) \lineto(-391.7448397,1080.19714301) \curveto(-391.601197,1079.72347522)(-391.17377566,1079.02621433)(-391.50880709,1078.59911757) \lineto(-392.21690492,1080.00146643) \lineto(-392.62153224,1082.08868333) \lineto(-394.03772789,1083.91499813) \lineto(-394.34119839,1080.81678553) \lineto(-394.07144684,1079.51227496) \lineto(-394.20632261,1079.12092179) \lineto(-395.85855087,1084.17590024) \lineto(-396.33061609,1084.04544918) \curveto(-396.11913087,1083.57321636)(-395.67822196,1083.12537788)(-395.85855087,1082.54526203) \curveto(-395.92509858,1082.76963785)(-396.24658848,1083.87586281)(-396.63408659,1083.16490455) \lineto(-396.2631782,1081.11030041) \lineto(-397.17358969,1082.64310032) \lineto(-397.44334124,1082.38219821) \curveto(-396.97518742,1081.07116509)(-395.90171112,1079.77317708)(-396.2631782,1078.37082822) \lineto(-397.98284435,1081.86039398) \lineto(-398.62350428,1083.19751732) \lineto(-399.06185056,1083.81715983) \curveto(-399.78937049,1083.50081602)(-398.14361627,1082.13695022)(-399.29788316,1082.21913439) \lineto(-399.43275894,1082.0234578) \curveto(-399.07587764,1081.40642431)(-398.4307668,1080.83074379)(-398.5560664,1080.06669195) \lineto(-399.19672633,1080.94723659) \lineto(-399.90482416,1082.21913439) \lineto(-400.51176515,1082.34958545) \lineto(-398.96069372,1078.76218139) \lineto(-401.79308502,1082.74093862) \lineto(-402.06283658,1082.54526203) \lineto(-401.35473875,1081.2081387) \lineto(-400.68035987,1079.77317708) \lineto(-400.71407881,1079.15353456) \lineto(-403.20928067,1082.87138967) \lineto(-403.24299962,1082.51264927) \curveto(-402.84309294,1082.1407333)(-402.84026055,1081.70241775)(-402.93952912,1081.24075146) \lineto(-402.56862074,1079.77317708) \lineto(-402.60233968,1079.0230835) \curveto(-403.66151915,1079.49570768)(-403.09976154,1081.62949561)(-404.42316266,1081.82778122) \lineto(-403.68134589,1079.15353456) \curveto(-405.61951079,1079.07555092)(-405.21623222,1082.41481097)(-406.71605085,1083.00184073) \lineto(-405.43473098,1079.67533878) \lineto(-407.18811607,1080.78417277) \lineto(-407.79505706,1081.37120252) \curveto(-407.95245709,1081.72472488)(-408.72381166,1081.683111)(-408.60431172,1081.24075146) \curveto(-407.89068399,1081.04285721)(-406.58791886,1079.6649027)(-407.25555396,1079.34921114) \curveto(-407.43925476,1079.07617708)(-407.55578743,1079.16162252)(-407.66018129,1079.41443667) \curveto(-407.84361234,1079.6779478)(-407.95434535,1080.48139586)(-408.40199805,1080.19714301) \curveto(-410.38197445,1081.89431126)(-407.77172355,1078.10601257)(-409.2786906,1078.17515163) \lineto(-409.31240954,1077.81641123) \lineto(-409.31915333,1077.80988867) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.19610979,1085.11514785) \lineto(-445.60073712,1085.37604996) \lineto(-445.19610979,1085.11514785) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.19610979,1085.11514785) \lineto(-445.60073712,1085.37604996) \lineto(-445.19610979,1085.11514785) \closepath } } { \newrgbcolor{curcolor}{0.82352942 0.82352942 0.82352942} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-331.49583049,1085.24559891) \lineto(-330.45054323,1085.21298614) \lineto(-331.22607894,1084.85424574) \lineto(-332.40624198,1084.4302798) \lineto(-332.74343142,1083.9737011) \curveto(-333.75931577,1083.53199382)(-334.76656807,1082.92487461)(-335.50838483,1082.14738631) \lineto(-335.23863328,1081.8864842) \lineto(-332.67599354,1083.5171224) \lineto(-330.82145161,1084.33244151) \lineto(-329.23666124,1084.69118191) \lineto(-330.51798112,1084.16937769) \lineto(-330.58541901,1083.58234793) \lineto(-335.37350906,1081.4299055) \lineto(-335.37350906,1081.10377785) \lineto(-333.35037242,1081.95170972) \lineto(-331.22607894,1082.76702883) \curveto(-330.78503515,1083.04306326)(-330.39443491,1082.98514299)(-329.91104012,1082.86486712) \curveto(-330.40347158,1082.67440858)(-331.15311115,1082.58191878)(-331.52954944,1082.01693525) \curveto(-332.45331363,1082.00289872)(-333.22224043,1081.48991298)(-333.88987552,1080.90810127) \lineto(-332.74343142,1080.90810127) \lineto(-335.37350906,1079.08178648) \lineto(-334.22706496,1079.21223753) \lineto(-334.22706496,1078.88610989) \lineto(-335.64326061,1078.10340355) \lineto(-335.91301216,1082.21261184) \curveto(-334.78005564,1083.60452461)(-333.09141093,1084.60117069)(-331.49583049,1085.24559891) \closepath } } { \newrgbcolor{curcolor}{0.82352942 0.82352942 0.82352942} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-331.49583049,1085.24559891) \lineto(-330.45054323,1085.21298614) \lineto(-331.22607894,1084.85424574) \lineto(-332.40624198,1084.4302798) \lineto(-332.74343142,1083.9737011) \curveto(-333.75931577,1083.53199382)(-334.76656807,1082.92487461)(-335.50838483,1082.14738631) \lineto(-335.23863328,1081.8864842) \lineto(-332.67599354,1083.5171224) \lineto(-330.82145161,1084.33244151) \lineto(-329.23666124,1084.69118191) \lineto(-330.51798112,1084.16937769) \lineto(-330.58541901,1083.58234793) \lineto(-335.37350906,1081.4299055) \lineto(-335.37350906,1081.10377785) \lineto(-333.35037242,1081.95170972) \lineto(-331.22607894,1082.76702883) \curveto(-330.78503515,1083.04306326)(-330.39443491,1082.98514299)(-329.91104012,1082.86486712) \curveto(-330.40347158,1082.67440858)(-331.15311115,1082.58191878)(-331.52954944,1082.01693525) \curveto(-332.45331363,1082.00289872)(-333.22224043,1081.48991298)(-333.88987552,1080.90810127) \lineto(-332.74343142,1080.90810127) \lineto(-335.37350906,1079.08178648) \lineto(-334.22706496,1079.21223753) \lineto(-334.22706496,1078.88610989) \lineto(-335.64326061,1078.10340355) \lineto(-335.91301216,1082.21261184) \curveto(-334.78005564,1083.60452461)(-333.09141093,1084.60117069)(-331.49583049,1085.24559891) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.92635823,1084.85424574) \lineto(-445.19610979,1085.11514785) \lineto(-444.92635823,1084.85424574) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.92635823,1084.85424574) \lineto(-445.19610979,1085.11514785) \lineto(-444.92635823,1084.85424574) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.63347004,1084.59334362) \curveto(-442.86154498,1084.5395717)(-443.09366619,1084.76410406)(-443.03809737,1084.98469679) \lineto(-442.63347004,1084.59334362) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.63347004,1084.59334362) \curveto(-442.86154498,1084.5395717)(-443.09366619,1084.76410406)(-443.03809737,1084.98469679) \lineto(-442.63347004,1084.59334362) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.65660668,1084.72379468) \lineto(-444.92635823,1084.85424574) \lineto(-444.65660668,1084.72379468) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.65660668,1084.72379468) \lineto(-444.92635823,1084.85424574) \lineto(-444.65660668,1084.72379468) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.52173091,1084.59334362) \lineto(-444.65660668,1084.72379468) \lineto(-444.52173091,1084.59334362) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.52173091,1084.59334362) \lineto(-444.65660668,1084.72379468) \lineto(-444.52173091,1084.59334362) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.52173091,1084.59334362) \curveto(-444.26749007,1084.61156763)(-444.54058654,1084.34744338)(-444.52173091,1084.59334362) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.52173091,1084.59334362) \curveto(-444.26749007,1084.61156763)(-444.54058654,1084.34744338)(-444.52173091,1084.59334362) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.22884271,1084.0715394) \lineto(-442.63347004,1084.59334362) \lineto(-442.22884271,1084.0715394) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.22884271,1084.0715394) \lineto(-442.63347004,1084.59334362) \lineto(-442.22884271,1084.0715394) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.9822278,1084.0715394) \lineto(-444.21826041,1084.4302798) \lineto(-443.9822278,1084.0715394) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.9822278,1084.0715394) \lineto(-444.21826041,1084.4302798) \lineto(-443.9822278,1084.0715394) \closepath } } { \newrgbcolor{curcolor}{0.74901962 0.74901962 0.74901962} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-376.27458818,1084.46289257) \lineto(-375.90367979,1084.29982874) \lineto(-375.86996085,1083.81063728) \lineto(-375.73508507,1081.98432249) \lineto(-375.90367979,1081.10377785) \lineto(-376.10599346,1080.9733268) \lineto(-376.1397124,1084.0715394) \lineto(-376.27458818,1084.46289257) \closepath } } { \newrgbcolor{curcolor}{0.74901962 0.74901962 0.74901962} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-376.27458818,1084.46289257) \lineto(-375.90367979,1084.29982874) \lineto(-375.86996085,1083.81063728) \lineto(-375.73508507,1081.98432249) \lineto(-375.90367979,1081.10377785) \lineto(-376.10599346,1080.9733268) \lineto(-376.1397124,1084.0715394) \lineto(-376.27458818,1084.46289257) \closepath } } { \newrgbcolor{curcolor}{0.80784315 0.80784315 0.80784315} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-375.33045774,1084.46289257) \lineto(-374.95954936,1084.4302798) \lineto(-374.65607886,1083.68018623) \lineto(-374.52120309,1082.89747988) \lineto(-374.65607886,1082.63657777) \curveto(-374.43933349,1082.14347278)(-374.43933349,1081.43381903)(-374.65607886,1080.94071403) \lineto(-374.68979781,1080.19062046) \lineto(-374.95954936,1079.66881623) \lineto(-375.02698725,1079.66881623) \lineto(-375.06070619,1082.2452246) \lineto(-375.19558197,1083.158382) \lineto(-375.33045774,1084.46289257) \closepath } } { \newrgbcolor{curcolor}{0.80784315 0.80784315 0.80784315} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-375.33045774,1084.46289257) \lineto(-374.95954936,1084.4302798) \lineto(-374.65607886,1083.68018623) \lineto(-374.52120309,1082.89747988) \lineto(-374.65607886,1082.63657777) \curveto(-374.43933349,1082.14347278)(-374.43933349,1081.43381903)(-374.65607886,1080.94071403) \lineto(-374.68979781,1080.19062046) \lineto(-374.95954936,1079.66881623) \lineto(-375.02698725,1079.66881623) \lineto(-375.06070619,1082.2452246) \lineto(-375.19558197,1083.158382) \lineto(-375.33045774,1084.46289257) \closepath } } { \newrgbcolor{curcolor}{0.627451 0.627451 0.627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-374.38632731,1084.46289257) \curveto(-374.13491886,1084.50621536)(-373.62198629,1084.46295257)(-373.74566737,1084.10415216) \lineto(-373.81310526,1084.10415216) \lineto(-374.38632731,1084.46289257) \closepath } } { \newrgbcolor{curcolor}{0.627451 0.627451 0.627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-374.38632731,1084.46289257) \curveto(-374.13491886,1084.50621536)(-373.62198629,1084.46295257)(-373.74566737,1084.10415216) \lineto(-373.81310526,1084.10415216) \lineto(-374.38632731,1084.46289257) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.13064394,1083.81063728) \lineto(-452.1759312,1084.10415216) \lineto(-452.1759312,1084.16937769) \lineto(-451.53527127,1084.0715394) \lineto(-451.13064394,1083.81063728) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.13064394,1083.81063728) \lineto(-452.1759312,1084.10415216) \lineto(-452.1759312,1084.16937769) \lineto(-451.53527127,1084.0715394) \lineto(-451.13064394,1083.81063728) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.71247625,1083.81063728) \lineto(-443.9822278,1084.0715394) \lineto(-443.71247625,1083.81063728) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.71247625,1083.81063728) \lineto(-443.9822278,1084.0715394) \lineto(-443.71247625,1083.81063728) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.09396694,1083.94108834) \lineto(-442.22884271,1084.0715394) \lineto(-442.09396694,1083.94108834) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.09396694,1083.94108834) \lineto(-442.22884271,1084.0715394) \lineto(-442.09396694,1083.94108834) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-378.02797327,1084.0715394) \curveto(-377.59637078,1084.14315703)(-377.77494631,1083.55677953)(-377.79194066,1083.32144582) \curveto(-378.30365935,1083.09928767)(-378.22731966,1083.84481546)(-378.02797327,1084.0715394) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-378.02797327,1084.0715394) \curveto(-377.59637078,1084.14315703)(-377.77494631,1083.55677953)(-377.79194066,1083.32144582) \curveto(-378.30365935,1083.09928767)(-378.22731966,1083.84481546)(-378.02797327,1084.0715394) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-329.33781808,1084.0715394) \lineto(-328.96690969,1083.9737011) \lineto(-329.33781808,1084.0715394) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-329.33781808,1084.0715394) \lineto(-328.96690969,1083.9737011) \lineto(-329.33781808,1084.0715394) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.95909116,1083.81063728) \lineto(-442.09396694,1083.94108834) \lineto(-441.95909116,1083.81063728) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.95909116,1083.81063728) \lineto(-442.09396694,1083.94108834) \lineto(-441.95909116,1083.81063728) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-450.72601661,1083.68018623) \lineto(-451.13064394,1083.81063728) \lineto(-450.72601661,1083.68018623) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-450.72601661,1083.68018623) \lineto(-451.13064394,1083.81063728) \lineto(-450.72601661,1083.68018623) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.57760047,1083.68018623) \lineto(-443.71247625,1083.81063728) \lineto(-443.57760047,1083.68018623) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.57760047,1083.68018623) \lineto(-443.71247625,1083.81063728) \lineto(-443.57760047,1083.68018623) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.82421538,1083.68018623) \lineto(-441.95909116,1083.81063728) \lineto(-441.82421538,1083.68018623) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.82421538,1083.68018623) \lineto(-441.95909116,1083.81063728) \lineto(-441.82421538,1083.68018623) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-450.59114083,1083.54973517) \lineto(-450.72601661,1083.68018623) \lineto(-450.59114083,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-450.59114083,1083.54973517) \lineto(-450.72601661,1083.68018623) \lineto(-450.59114083,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.29825264,1083.54973517) \lineto(-448.8040368,1083.64757346) \lineto(-448.29825264,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.29825264,1083.54973517) \lineto(-448.8040368,1083.64757346) \lineto(-448.29825264,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.17297314,1083.158382) \lineto(-443.57760047,1083.68018623) \lineto(-443.17297314,1083.158382) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.17297314,1083.158382) \lineto(-443.57760047,1083.68018623) \lineto(-443.17297314,1083.158382) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.68933961,1083.54973517) \lineto(-441.82421538,1083.68018623) \lineto(-441.68933961,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.68933961,1083.54973517) \lineto(-441.82421538,1083.68018623) \lineto(-441.68933961,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.81568629 0.81568629 0.81568629} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-372.90269377,1083.68018623) \lineto(-372.19459595,1083.32144582) \lineto(-371.11558974,1082.79964159) \lineto(-370.50864875,1082.86486712) \lineto(-370.07030247,1081.98432249) \lineto(-370.23889719,1080.71242468) \lineto(-370.4749298,1080.54936086) \lineto(-370.64352452,1081.03855233) \curveto(-370.95427831,1081.19091916)(-371.18397176,1081.51365508)(-371.04815185,1081.82125867) \lineto(-371.41906023,1082.37567566) \lineto(-371.68881179,1082.89747988) \curveto(-372.02357346,1082.83151079)(-372.00684887,1082.44285795)(-371.82368756,1082.2452246) \lineto(-371.95856334,1081.20161615) \lineto(-372.12715806,1082.34306289) \curveto(-372.53623629,1082.33308208)(-372.92791554,1082.38877294)(-372.767818,1082.89747988) \curveto(-372.95529532,1083.12890006)(-373.17554747,1083.40649991)(-372.90269377,1083.68018623) \closepath } } { \newrgbcolor{curcolor}{0.81568629 0.81568629 0.81568629} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-372.90269377,1083.68018623) \lineto(-372.19459595,1083.32144582) \lineto(-371.11558974,1082.79964159) \lineto(-370.50864875,1082.86486712) \lineto(-370.07030247,1081.98432249) \lineto(-370.23889719,1080.71242468) \lineto(-370.4749298,1080.54936086) \lineto(-370.64352452,1081.03855233) \curveto(-370.95427831,1081.19091916)(-371.18397176,1081.51365508)(-371.04815185,1081.82125867) \lineto(-371.41906023,1082.37567566) \lineto(-371.68881179,1082.89747988) \curveto(-372.02357346,1082.83151079)(-372.00684887,1082.44285795)(-371.82368756,1082.2452246) \lineto(-371.95856334,1081.20161615) \lineto(-372.12715806,1082.34306289) \curveto(-372.53623629,1082.33308208)(-372.92791554,1082.38877294)(-372.767818,1082.89747988) \curveto(-372.95529532,1083.12890006)(-373.17554747,1083.40649991)(-372.90269377,1083.68018623) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-450.05163773,1083.28883305) \lineto(-450.59114083,1083.54973517) \lineto(-450.05163773,1083.28883305) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-450.05163773,1083.28883305) \lineto(-450.59114083,1083.54973517) \lineto(-450.05163773,1083.28883305) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.02850109,1083.41928411) \lineto(-448.29825264,1083.54973517) \lineto(-448.02850109,1083.41928411) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.02850109,1083.41928411) \lineto(-448.29825264,1083.54973517) \lineto(-448.02850109,1083.41928411) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-441.68933961,1083.54973517) \curveto(-441.43509877,1083.56795918)(-441.70819524,1083.30383493)(-441.68933961,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-441.68933961,1083.54973517) \curveto(-441.43509877,1083.56795918)(-441.70819524,1083.30383493)(-441.68933961,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-371.01443291,1083.54973517) \lineto(-370.64352452,1083.32144582) \lineto(-371.01443291,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-371.01443291,1083.54973517) \lineto(-370.64352452,1083.32144582) \lineto(-371.01443291,1083.54973517) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.75874953,1083.28883305) \lineto(-448.02850109,1083.41928411) \lineto(-447.75874953,1083.28883305) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.75874953,1083.28883305) \lineto(-448.02850109,1083.41928411) \lineto(-447.75874953,1083.28883305) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-449.78188618,1083.158382) \lineto(-450.05163773,1083.28883305) \lineto(-449.78188618,1083.158382) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-449.78188618,1083.158382) \lineto(-450.05163773,1083.28883305) \lineto(-449.78188618,1083.158382) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.75874953,1083.28883305) \lineto(-447.52271693,1083.19099476) \lineto(-447.75874953,1083.28883305) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.75874953,1083.28883305) \lineto(-447.52271693,1083.19099476) \lineto(-447.75874953,1083.28883305) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-449.51213462,1083.02793094) \lineto(-449.78188618,1083.158382) \lineto(-449.51213462,1083.02793094) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-449.51213462,1083.02793094) \lineto(-449.78188618,1083.158382) \lineto(-449.51213462,1083.02793094) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.17297314,1083.158382) \lineto(-442.80206476,1082.66919054) \lineto(-443.17297314,1083.158382) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.17297314,1083.158382) \lineto(-442.80206476,1082.66919054) \lineto(-443.17297314,1083.158382) \closepath } } { \newrgbcolor{curcolor}{0.80784315 0.80784315 0.80784315} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-380.18598568,1083.158382) \curveto(-379.47019994,1083.09468275)(-379.86498134,1082.09181416)(-379.8150773,1081.62558208) \lineto(-380.28714252,1081.62558208) \curveto(-380.60976537,1082.10994686)(-380.42377168,1082.69710706)(-380.18598568,1083.158382) \closepath } } { \newrgbcolor{curcolor}{0.80784315 0.80784315 0.80784315} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-380.18598568,1083.158382) \curveto(-379.47019994,1083.09468275)(-379.86498134,1082.09181416)(-379.8150773,1081.62558208) \lineto(-380.28714252,1081.62558208) \curveto(-380.60976537,1082.10994686)(-380.42377168,1082.69710706)(-380.18598568,1083.158382) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-449.37725885,1082.89747988) \lineto(-449.51213462,1083.02793094) \lineto(-449.37725885,1082.89747988) \closepath } } { \newrgbcolor{curcolor}{0.02352941 0.02352941 0.02352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-449.37725885,1082.89747988) \lineto(-449.51213462,1083.02793094) \lineto(-449.37725885,1082.89747988) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.94949488,1082.89747988) \lineto(-447.18552749,1082.99531818) \lineto(-446.94949488,1082.89747988) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.94949488,1082.89747988) \lineto(-447.18552749,1082.99531818) \lineto(-446.94949488,1082.89747988) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.83775574,1082.63657777) \lineto(-449.37725885,1082.89747988) \lineto(-448.83775574,1082.63657777) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.83775574,1082.63657777) \lineto(-449.37725885,1082.89747988) \lineto(-448.83775574,1082.63657777) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.54486755,1082.63657777) \lineto(-446.94949488,1082.89747988) \lineto(-446.54486755,1082.63657777) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.54486755,1082.63657777) \lineto(-446.94949488,1082.89747988) \lineto(-446.54486755,1082.63657777) \closepath } } { \newrgbcolor{curcolor}{0.81568629 0.81568629 0.81568629} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-378.70235215,1082.89747988) \lineto(-378.43260059,1082.76702883) \lineto(-377.38731333,1082.73441606) \lineto(-377.48847016,1081.85387143) \curveto(-377.47437564,1081.5850118)(-377.41578561,1080.9922422)(-377.85937855,1081.10377785) \lineto(-377.92681643,1081.69080761) \lineto(-378.26400587,1081.69080761) \lineto(-378.60119531,1080.58197363) \lineto(-378.6686332,1080.58197363) \lineto(-378.70235215,1081.59296932) \curveto(-378.91262348,1081.96566799)(-378.91262348,1082.52478122)(-378.70235215,1082.89747988) \closepath } } { \newrgbcolor{curcolor}{0.81568629 0.81568629 0.81568629} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-378.70235215,1082.89747988) \lineto(-378.43260059,1082.76702883) \lineto(-377.38731333,1082.73441606) \lineto(-377.48847016,1081.85387143) \curveto(-377.47437564,1081.5850118)(-377.41578561,1080.9922422)(-377.85937855,1081.10377785) \lineto(-377.92681643,1081.69080761) \lineto(-378.26400587,1081.69080761) \lineto(-378.60119531,1080.58197363) \lineto(-378.6686332,1080.58197363) \lineto(-378.70235215,1081.59296932) \curveto(-378.91262348,1081.96566799)(-378.91262348,1082.52478122)(-378.70235215,1082.89747988) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.43312841,1082.37567566) \lineto(-448.83775574,1082.63657777) \lineto(-448.43312841,1082.37567566) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.43312841,1082.37567566) \lineto(-448.83775574,1082.63657777) \lineto(-448.43312841,1082.37567566) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.00536444,1082.37567566) \lineto(-446.54486755,1082.63657777) \lineto(-446.00536444,1082.37567566) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.00536444,1082.37567566) \lineto(-446.54486755,1082.63657777) \lineto(-446.00536444,1082.37567566) \closepath } } { \newrgbcolor{curcolor}{0.66274512 0.66274512 0.66274512} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-381.53474345,1082.63657777) \lineto(-381.39986767,1082.37567566) \lineto(-382.07424655,1080.41890981) \lineto(-382.24284127,1079.147012) \lineto(-382.31027916,1079.147012) \lineto(-382.3439981,1079.89710558) \lineto(-382.20912233,1080.15800769) \lineto(-382.07424655,1081.3320672) \curveto(-382.13298495,1081.85139286)(-381.86168233,1082.26544451)(-381.53474345,1082.63657777) \closepath } } { \newrgbcolor{curcolor}{0.66274512 0.66274512 0.66274512} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-381.53474345,1082.63657777) \lineto(-381.39986767,1082.37567566) \lineto(-382.07424655,1080.41890981) \lineto(-382.24284127,1079.147012) \lineto(-382.31027916,1079.147012) \lineto(-382.3439981,1079.89710558) \lineto(-382.20912233,1080.15800769) \lineto(-382.07424655,1081.3320672) \curveto(-382.13298495,1081.85139286)(-381.86168233,1082.26544451)(-381.53474345,1082.63657777) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.49859426,1082.37567566) \curveto(-442.7528351,1082.35745165)(-442.47973863,1082.6215759)(-442.49859426,1082.37567566) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.49859426,1082.37567566) \curveto(-442.7528351,1082.35745165)(-442.47973863,1082.6215759)(-442.49859426,1082.37567566) \closepath } } { \newrgbcolor{curcolor}{0.68235296 0.68235296 0.68235296} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-368.85642049,1082.50612671) \curveto(-367.90446726,1082.33262681)(-368.46797825,1081.08290569)(-368.31691738,1080.41890981) \lineto(-368.41807421,1080.32107151) \lineto(-368.4855121,1081.56035655) \curveto(-368.99035213,1081.61403716)(-368.83983077,1082.16617126)(-368.85642049,1082.50612671) \closepath } } { \newrgbcolor{curcolor}{0.68235296 0.68235296 0.68235296} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-368.85642049,1082.50612671) \curveto(-367.90446726,1082.33262681)(-368.46797825,1081.08290569)(-368.31691738,1080.41890981) \lineto(-368.41807421,1080.32107151) \lineto(-368.4855121,1081.56035655) \curveto(-368.99035213,1081.61403716)(-368.83983077,1082.16617126)(-368.85642049,1082.50612671) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.16337686,1082.2452246) \lineto(-448.43312841,1082.37567566) \lineto(-448.16337686,1082.2452246) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.16337686,1082.2452246) \lineto(-448.43312841,1082.37567566) \lineto(-448.16337686,1082.2452246) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.60073712,1082.11477354) \lineto(-446.00536444,1082.37567566) \lineto(-445.60073712,1082.11477354) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.60073712,1082.11477354) \lineto(-446.00536444,1082.37567566) \lineto(-445.60073712,1082.11477354) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.49859426,1082.37567566) \curveto(-442.24435343,1082.39389967)(-442.5174499,1082.12977542)(-442.49859426,1082.37567566) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.49859426,1082.37567566) \curveto(-442.24435343,1082.39389967)(-442.5174499,1082.12977542)(-442.49859426,1082.37567566) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.89362531,1082.11477354) \lineto(-448.16337686,1082.2452246) \lineto(-447.89362531,1082.11477354) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.89362531,1082.11477354) \lineto(-448.16337686,1082.2452246) \lineto(-447.89362531,1082.11477354) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.75874953,1081.98432249) \lineto(-447.89362531,1082.11477354) \lineto(-447.75874953,1081.98432249) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.75874953,1081.98432249) \lineto(-447.89362531,1082.11477354) \lineto(-447.75874953,1081.98432249) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.19610979,1081.85387143) \lineto(-445.60073712,1082.11477354) \lineto(-445.19610979,1081.85387143) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.19610979,1081.85387143) \lineto(-445.60073712,1082.11477354) \lineto(-445.19610979,1081.85387143) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.48899798,1081.85387143) \lineto(-447.75874953,1081.98432249) \lineto(-447.48899798,1081.85387143) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.48899798,1081.85387143) \lineto(-447.75874953,1081.98432249) \lineto(-447.48899798,1081.85387143) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-372.767818,1081.98432249) \lineto(-372.66666116,1081.95170972) \lineto(-372.93641272,1079.79926729) \lineto(-373.13872638,1079.53836517) \lineto(-373.17244532,1079.76665452) \lineto(-372.90269377,1081.07116509) \lineto(-372.767818,1081.98432249) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-372.767818,1081.98432249) \lineto(-372.66666116,1081.95170972) \lineto(-372.93641272,1079.79926729) \lineto(-373.13872638,1079.53836517) \lineto(-373.17244532,1079.76665452) \lineto(-372.90269377,1081.07116509) \lineto(-372.767818,1081.98432249) \closepath } } { \newrgbcolor{curcolor}{0.60392159 0.60392159 0.60392159} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-329.60756963,1081.98432249) \lineto(-329.10178547,1081.8864842) \lineto(-330.95632739,1081.20161615) \lineto(-331.19236,1081.23422891) \lineto(-330.99004633,1081.36467997) \lineto(-330.38310534,1081.69080761) \lineto(-329.60756963,1081.98432249) \closepath } } { \newrgbcolor{curcolor}{0.60392159 0.60392159 0.60392159} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-329.60756963,1081.98432249) \lineto(-329.10178547,1081.8864842) \lineto(-330.95632739,1081.20161615) \lineto(-331.19236,1081.23422891) \lineto(-330.99004633,1081.36467997) \lineto(-330.38310534,1081.69080761) \lineto(-329.60756963,1081.98432249) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.21924643,1081.72342037) \lineto(-447.48899798,1081.85387143) \lineto(-447.21924643,1081.72342037) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.21924643,1081.72342037) \lineto(-447.48899798,1081.85387143) \lineto(-447.21924643,1081.72342037) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.06123401,1081.72342037) \lineto(-445.19610979,1081.85387143) \lineto(-445.06123401,1081.72342037) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.06123401,1081.72342037) \lineto(-445.19610979,1081.85387143) \lineto(-445.06123401,1081.72342037) \closepath } } { \newrgbcolor{curcolor}{0.75686276 0.75686276 0.75686276} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-382.74862543,1081.85387143) \lineto(-382.6474686,1081.23422891) \lineto(-382.74862543,1081.20161615) \curveto(-383.10065121,1081.55866069)(-383.47776388,1081.00215648)(-383.1869717,1080.71242468) \lineto(-383.32184748,1080.58197363) \lineto(-384.06366425,1081.03855233) \lineto(-382.78234437,1081.75603314) \lineto(-382.74862543,1081.85387143) \closepath } } { \newrgbcolor{curcolor}{0.75686276 0.75686276 0.75686276} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-382.74862543,1081.85387143) \lineto(-382.6474686,1081.23422891) \lineto(-382.74862543,1081.20161615) \curveto(-383.10065121,1081.55866069)(-383.47776388,1081.00215648)(-383.1869717,1080.71242468) \lineto(-383.32184748,1080.58197363) \lineto(-384.06366425,1081.03855233) \lineto(-382.78234437,1081.75603314) \lineto(-382.74862543,1081.85387143) \closepath } } { \newrgbcolor{curcolor}{0.78431374 0.78431374 0.78431374} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-367.77741428,1081.85387143) \lineto(-367.27163012,1081.82125867) \curveto(-367.28178087,1081.27532099)(-366.95709981,1080.30933092)(-367.74369533,1080.19062046) \lineto(-367.77741428,1081.85387143) \closepath } } { \newrgbcolor{curcolor}{0.78431374 0.78431374 0.78431374} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-367.77741428,1081.85387143) \lineto(-367.27163012,1081.82125867) \curveto(-367.28178087,1081.27532099)(-366.95709981,1080.30933092)(-367.74369533,1080.19062046) \lineto(-367.77741428,1081.85387143) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.8146191,1081.46251826) \lineto(-447.21924643,1081.72342037) \lineto(-446.8146191,1081.46251826) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.8146191,1081.46251826) \lineto(-447.21924643,1081.72342037) \lineto(-446.8146191,1081.46251826) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.65660668,1081.46251826) \lineto(-445.06123401,1081.72342037) \lineto(-444.65660668,1081.46251826) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.65660668,1081.46251826) \lineto(-445.06123401,1081.72342037) \lineto(-444.65660668,1081.46251826) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.54486755,1081.3320672) \lineto(-446.8146191,1081.46251826) \lineto(-446.54486755,1081.3320672) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.54486755,1081.3320672) \lineto(-446.8146191,1081.46251826) \lineto(-446.54486755,1081.3320672) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.52173091,1081.3320672) \lineto(-444.65660668,1081.46251826) \lineto(-444.52173091,1081.3320672) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.52173091,1081.3320672) \lineto(-444.65660668,1081.46251826) \lineto(-444.52173091,1081.3320672) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.54486755,1081.3320672) \curveto(-446.29062671,1081.35029122)(-446.56372318,1081.08616696)(-446.54486755,1081.3320672) \closepath } } { \newrgbcolor{curcolor}{0.04313726 0.04313726 0.04313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.54486755,1081.3320672) \curveto(-446.29062671,1081.35029122)(-446.56372318,1081.08616696)(-446.54486755,1081.3320672) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.11710358,1081.07116509) \lineto(-444.52173091,1081.3320672) \lineto(-444.11710358,1081.07116509) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.11710358,1081.07116509) \lineto(-444.52173091,1081.3320672) \lineto(-444.11710358,1081.07116509) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-366.42865652,1081.3320672) \curveto(-366.16956015,1081.41208588)(-365.89117655,1081.24980477)(-366.05774813,1080.9733268) \curveto(-366.2650522,1080.8608519)(-366.48489972,1081.14304362)(-366.42865652,1081.3320672) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-366.42865652,1081.3320672) \curveto(-366.16956015,1081.41208588)(-365.89117655,1081.24980477)(-366.05774813,1080.9733268) \curveto(-366.2650522,1080.8608519)(-366.48489972,1081.14304362)(-366.42865652,1081.3320672) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.14024022,1081.07116509) \curveto(-446.39448106,1081.05294108)(-446.12138459,1081.31706533)(-446.14024022,1081.07116509) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.14024022,1081.07116509) \curveto(-446.39448106,1081.05294108)(-446.12138459,1081.31706533)(-446.14024022,1081.07116509) \closepath } } { \newrgbcolor{curcolor}{0.72549021 0.72549021 0.72549021} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-393.40381175,1081.20161615) \lineto(-393.30265491,1081.16900338) \lineto(-393.16777914,1079.40791412) \lineto(-393.3700928,1079.53836517) \lineto(-393.40381175,1081.20161615) \closepath } } { \newrgbcolor{curcolor}{0.72549021 0.72549021 0.72549021} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-393.40381175,1081.20161615) \lineto(-393.30265491,1081.16900338) \lineto(-393.16777914,1079.40791412) \lineto(-393.3700928,1079.53836517) \lineto(-393.40381175,1081.20161615) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.00536444,1080.94071403) \lineto(-446.14024022,1081.07116509) \lineto(-446.00536444,1080.94071403) \closepath } } { \newrgbcolor{curcolor}{0.03921569 0.03921569 0.03921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.00536444,1080.94071403) \lineto(-446.14024022,1081.07116509) \lineto(-446.00536444,1080.94071403) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.11710358,1081.07116509) \lineto(-443.88107097,1080.9733268) \lineto(-444.11710358,1081.07116509) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.11710358,1081.07116509) \lineto(-443.88107097,1080.9733268) \lineto(-444.11710358,1081.07116509) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.73561289,1080.81026298) \lineto(-446.00536444,1080.94071403) \lineto(-445.73561289,1080.81026298) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.73561289,1080.81026298) \lineto(-446.00536444,1080.94071403) \lineto(-445.73561289,1080.81026298) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.33098556,1080.54936086) \lineto(-445.73561289,1080.81026298) \lineto(-445.33098556,1080.54936086) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.33098556,1080.54936086) \lineto(-445.73561289,1080.81026298) \lineto(-445.33098556,1080.54936086) \closepath } } { \newrgbcolor{curcolor}{0.89411765 0.89411765 0.89411765} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-365.48452608,1080.67981192) \lineto(-364.84386615,1080.5167481) \lineto(-363.62998416,1079.73404176) \lineto(-363.86601677,1078.98394818) \lineto(-363.76485994,1077.71205038) \lineto(-364.23692515,1077.58159932) \curveto(-364.18594211,1078.08474905)(-364.62226525,1078.74783177)(-365.18105559,1078.36430566) \lineto(-365.34965031,1079.63620347) \lineto(-365.38336925,1080.25584599) \lineto(-365.48452608,1080.67981192) \closepath } } { \newrgbcolor{curcolor}{0.89411765 0.89411765 0.89411765} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-365.48452608,1080.67981192) \lineto(-364.84386615,1080.5167481) \lineto(-363.62998416,1079.73404176) \lineto(-363.86601677,1078.98394818) \lineto(-363.76485994,1077.71205038) \lineto(-364.23692515,1077.58159932) \curveto(-364.18594211,1078.08474905)(-364.62226525,1078.74783177)(-365.18105559,1078.36430566) \lineto(-365.34965031,1079.63620347) \lineto(-365.38336925,1080.25584599) \lineto(-365.48452608,1080.67981192) \closepath } } { \newrgbcolor{curcolor}{0.63137257 0.63137257 0.63137257} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-332.17020938,1080.67981192) \lineto(-331.79930099,1080.45152257) \lineto(-333.51896714,1079.63620347) \lineto(-333.62012397,1079.66881623) \lineto(-333.48524819,1079.86449282) \lineto(-332.97946403,1080.15800769) \lineto(-332.20392832,1080.58197363) \lineto(-332.17020938,1080.67981192) \closepath } } { \newrgbcolor{curcolor}{0.63137257 0.63137257 0.63137257} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-332.17020938,1080.67981192) \lineto(-331.79930099,1080.45152257) \lineto(-333.51896714,1079.63620347) \lineto(-333.62012397,1079.66881623) \lineto(-333.48524819,1079.86449282) \lineto(-332.97946403,1080.15800769) \lineto(-332.20392832,1080.58197363) \lineto(-332.17020938,1080.67981192) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.19610979,1080.41890981) \lineto(-445.33098556,1080.54936086) \lineto(-445.19610979,1080.41890981) \closepath } } { \newrgbcolor{curcolor}{0 0 0} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.19610979,1080.41890981) \lineto(-445.33098556,1080.54936086) \lineto(-445.19610979,1080.41890981) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.79148246,1080.15800769) \lineto(-445.19610979,1080.41890981) \lineto(-444.79148246,1080.15800769) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.79148246,1080.15800769) \lineto(-445.19610979,1080.41890981) \lineto(-444.79148246,1080.15800769) \closepath } } { \newrgbcolor{curcolor}{0.63529414 0.63529414 0.63529414} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-386.25539561,1080.41890981) \curveto(-386.06319763,1080.44657848)(-385.76026664,1080.433716)(-385.85076828,1080.15800769) \lineto(-385.74961145,1079.53836517) \lineto(-386.25539561,1080.41890981) \closepath } } { \newrgbcolor{curcolor}{0.63529414 0.63529414 0.63529414} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-386.25539561,1080.41890981) \curveto(-386.06319763,1080.44657848)(-385.76026664,1080.433716)(-385.85076828,1080.15800769) \lineto(-385.74961145,1079.53836517) \lineto(-386.25539561,1080.41890981) \closepath } } { \newrgbcolor{curcolor}{0.7764706 0.7764706 0.7764706} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-331.49583049,1078.72304607) \lineto(-331.52954944,1078.62520778) \lineto(-334.69913018,1077.64682485) \lineto(-335.37350906,1077.45114827) \lineto(-335.23863328,1077.77727591) \curveto(-333.47580689,1078.87906553)(-331.52280565,1079.56054185)(-329.60756963,1080.28845875) \lineto(-328.02277926,1080.38629704) \lineto(-328.02277926,1080.32107151) \lineto(-330.68657584,1079.50575241) \lineto(-331.09120317,1079.37530135) \curveto(-331.57176556,1079.54697494)(-332.30575953,1078.76479041)(-331.49583049,1078.72304607) \closepath } } { \newrgbcolor{curcolor}{0.7764706 0.7764706 0.7764706} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-331.49583049,1078.72304607) \lineto(-331.52954944,1078.62520778) \lineto(-334.69913018,1077.64682485) \lineto(-335.37350906,1077.45114827) \lineto(-335.23863328,1077.77727591) \curveto(-333.47580689,1078.87906553)(-331.52280565,1079.56054185)(-329.60756963,1080.28845875) \lineto(-328.02277926,1080.38629704) \lineto(-328.02277926,1080.32107151) \lineto(-330.68657584,1079.50575241) \lineto(-331.09120317,1079.37530135) \curveto(-331.57176556,1079.54697494)(-332.30575953,1078.76479041)(-331.49583049,1078.72304607) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.79148246,1080.15800769) \curveto(-444.53724162,1080.17623171)(-444.81033809,1079.91210745)(-444.79148246,1080.15800769) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.79148246,1080.15800769) \curveto(-444.53724162,1080.17623171)(-444.81033809,1079.91210745)(-444.79148246,1080.15800769) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-387.06465027,1080.15800769) \curveto(-386.81728809,1080.24479678)(-386.71950316,1079.97133223)(-386.82861766,1079.79926729) \lineto(-387.06465027,1080.15800769) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-387.06465027,1080.15800769) \curveto(-386.81728809,1080.24479678)(-386.71950316,1079.97133223)(-386.82861766,1079.79926729) \lineto(-387.06465027,1080.15800769) \closepath } } { \newrgbcolor{curcolor}{0.67058825 0.67058825 0.67058825} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-406.21701048,1079.63620347) \lineto(-405.98097787,1079.47313965) \lineto(-405.03684744,1077.84250144) \lineto(-405.17172322,1077.71205038) \lineto(-405.50891266,1077.97295249) \lineto(-406.21701048,1079.63620347) \closepath } } { \newrgbcolor{curcolor}{0.67058825 0.67058825 0.67058825} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-406.21701048,1079.63620347) \lineto(-405.98097787,1079.47313965) \lineto(-405.03684744,1077.84250144) \lineto(-405.17172322,1077.71205038) \lineto(-405.50891266,1077.97295249) \lineto(-406.21701048,1079.63620347) \closepath } } { \newrgbcolor{curcolor}{0.627451 0.627451 0.627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-367.77741428,1079.63620347) \lineto(-367.67625745,1079.27746306) \lineto(-367.77741428,1079.63620347) \closepath } } { \newrgbcolor{curcolor}{0.627451 0.627451 0.627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-367.77741428,1079.63620347) \lineto(-367.67625745,1079.27746306) \lineto(-367.77741428,1079.63620347) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.02850109,1079.50575241) \lineto(-447.75874953,1079.50575241) \lineto(-447.6575927,1079.47313965) \lineto(-446.44371072,1078.62520778) \lineto(-447.18552749,1078.62520778) \curveto(-447.14811295,1079.06965453)(-447.63156168,1079.22684805)(-447.99478214,1079.27746306) \lineto(-448.02850109,1079.50575241) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.02850109,1079.50575241) \lineto(-447.75874953,1079.50575241) \lineto(-447.6575927,1079.47313965) \lineto(-446.44371072,1078.62520778) \lineto(-447.18552749,1078.62520778) \curveto(-447.14811295,1079.06965453)(-447.63156168,1079.22684805)(-447.99478214,1079.27746306) \lineto(-448.02850109,1079.50575241) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-385.58101673,1079.2448503) \lineto(-385.4798599,1079.21223753) \curveto(-385.35441194,1078.88558809)(-384.88869937,1078.30260231)(-385.41242201,1078.10340355) \lineto(-385.58101673,1079.2448503) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-385.58101673,1079.2448503) \lineto(-385.4798599,1079.21223753) \curveto(-385.35441194,1078.88558809)(-384.88869937,1078.30260231)(-385.41242201,1078.10340355) \lineto(-385.58101673,1079.2448503) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-377.08384283,1079.2448503) \curveto(-376.92711718,1079.2663095)(-376.56335721,1079.26837062)(-376.71293445,1079.01656095) \curveto(-376.8908356,1078.91103909)(-377.17353522,1079.0056448)(-377.08384283,1079.2448503) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-377.08384283,1079.2448503) \curveto(-376.92711718,1079.2663095)(-376.56335721,1079.26837062)(-376.71293445,1079.01656095) \curveto(-376.8908356,1078.91103909)(-377.17353522,1079.0056448)(-377.08384283,1079.2448503) \closepath } } { \newrgbcolor{curcolor}{0.6901961 0.6901961 0.6901961} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-400.01272478,1079.11439924) \lineto(-399.91156795,1079.08178648) \lineto(-399.47322167,1077.80988867) \lineto(-399.37206484,1076.92934404) \lineto(-399.57437851,1077.0597951) \lineto(-399.877849,1078.46214396) \lineto(-400.01272478,1079.11439924) \closepath } } { \newrgbcolor{curcolor}{0.6901961 0.6901961 0.6901961} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-400.01272478,1079.11439924) \lineto(-399.91156795,1079.08178648) \lineto(-399.47322167,1077.80988867) \lineto(-399.37206484,1076.92934404) \lineto(-399.57437851,1077.0597951) \lineto(-399.877849,1078.46214396) \lineto(-400.01272478,1079.11439924) \closepath } } { \newrgbcolor{curcolor}{0.76078433 0.76078433 0.76078433} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-392.59455709,1079.11439924) \lineto(-392.35852448,1079.08178648) \curveto(-391.92759638,1078.32490944)(-392.0449383,1077.39635882)(-392.08877293,1076.53799087) \lineto(-392.15621082,1076.53799087) \lineto(-392.59455709,1077.80988867) \lineto(-392.59455709,1079.11439924) \closepath } } { \newrgbcolor{curcolor}{0.76078433 0.76078433 0.76078433} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-392.59455709,1079.11439924) \lineto(-392.35852448,1079.08178648) \curveto(-391.92759638,1078.32490944)(-392.0449383,1077.39635882)(-392.08877293,1076.53799087) \lineto(-392.15621082,1076.53799087) \lineto(-392.59455709,1077.80988867) \lineto(-392.59455709,1079.11439924) \closepath } } { \newrgbcolor{curcolor}{0.78431374 0.78431374 0.78431374} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-363.05676211,1078.85349713) \lineto(-362.14635062,1078.29908014) \lineto(-362.14635062,1078.23385461) \lineto(-362.41610218,1077.32069721) \lineto(-362.88816739,1077.58159932) \lineto(-363.05676211,1078.59259501) \lineto(-363.05676211,1078.85349713) \closepath } } { \newrgbcolor{curcolor}{0.78431374 0.78431374 0.78431374} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-363.05676211,1078.85349713) \lineto(-362.14635062,1078.29908014) \lineto(-362.14635062,1078.23385461) \lineto(-362.41610218,1077.32069721) \lineto(-362.88816739,1077.58159932) \lineto(-363.05676211,1078.59259501) \lineto(-363.05676211,1078.85349713) \closepath } } { \newrgbcolor{curcolor}{0.60392159 0.60392159 0.60392159} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-384.6368863,1078.72304607) \curveto(-384.45938978,1078.65106318)(-384.08551412,1078.38987407)(-384.40085369,1078.23385461) \lineto(-384.6368863,1078.72304607) \closepath } } { \newrgbcolor{curcolor}{0.60392159 0.60392159 0.60392159} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-384.6368863,1078.72304607) \curveto(-384.45938978,1078.65106318)(-384.08551412,1078.38987407)(-384.40085369,1078.23385461) \lineto(-384.6368863,1078.72304607) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.87048867,1078.3316929) \lineto(-446.24139705,1078.55998225) \lineto(-445.87048867,1078.3316929) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.87048867,1078.3316929) \lineto(-446.24139705,1078.55998225) \lineto(-445.87048867,1078.3316929) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-393.6735633,1078.46214396) \lineto(-393.43753069,1078.42953119) \lineto(-393.43753069,1077.19024615) \lineto(-393.50496858,1077.19024615) \lineto(-393.6735633,1078.46214396) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-393.6735633,1078.46214396) \lineto(-393.43753069,1078.42953119) \lineto(-393.43753069,1077.19024615) \lineto(-393.50496858,1077.19024615) \lineto(-393.6735633,1078.46214396) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.46586134,1078.07079079) \lineto(-445.87048867,1078.3316929) \lineto(-445.46586134,1078.07079079) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.46586134,1078.07079079) \lineto(-445.87048867,1078.3316929) \lineto(-445.46586134,1078.07079079) \closepath } } { \newrgbcolor{curcolor}{0.22352941 0.22352941 0.22352941} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-328.52856342,1078.20124184) \lineto(-325.56129634,1078.20124184) \curveto(-324.50886066,1078.17620828)(-323.4073302,1078.31673016)(-322.45915349,1077.94033973) \lineto(-321.95336933,1077.90772697) \lineto(-321.95336933,1077.58159932) \lineto(-322.32427772,1077.54898656) \lineto(-322.59402927,1077.67943762) \lineto(-328.6634392,1077.67943762) \lineto(-328.93319075,1077.54898656) \lineto(-330.28194851,1077.54898656) \lineto(-331.22607894,1077.28808445) \lineto(-331.59698733,1077.32069721) \lineto(-331.59698733,1077.77727591) \lineto(-328.6634392,1078.07079079) \lineto(-328.52856342,1078.20124184) \closepath } } { \newrgbcolor{curcolor}{0.22352941 0.22352941 0.22352941} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-328.52856342,1078.20124184) \lineto(-325.56129634,1078.20124184) \curveto(-324.50886066,1078.17620828)(-323.4073302,1078.31673016)(-322.45915349,1077.94033973) \lineto(-321.95336933,1077.90772697) \lineto(-321.95336933,1077.58159932) \lineto(-322.32427772,1077.54898656) \lineto(-322.59402927,1077.67943762) \lineto(-328.6634392,1077.67943762) \lineto(-328.93319075,1077.54898656) \lineto(-330.28194851,1077.54898656) \lineto(-331.22607894,1077.28808445) \lineto(-331.59698733,1077.32069721) \lineto(-331.59698733,1077.77727591) \lineto(-328.6634392,1078.07079079) \lineto(-328.52856342,1078.20124184) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.33098556,1077.94033973) \lineto(-445.46586134,1078.07079079) \lineto(-445.33098556,1077.94033973) \closepath } } { \newrgbcolor{curcolor}{0.06666667 0.06666667 0.06666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.33098556,1077.94033973) \lineto(-445.46586134,1078.07079079) \lineto(-445.33098556,1077.94033973) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.19610979,1077.80988867) \lineto(-445.33098556,1077.94033973) \lineto(-445.19610979,1077.80988867) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.19610979,1077.80988867) \lineto(-445.33098556,1077.94033973) \lineto(-445.19610979,1077.80988867) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-402.84511608,1077.94033973) \lineto(-402.44048875,1077.15763339) \curveto(-402.52779384,1076.80867681)(-402.34525296,1076.54412207)(-402.06958036,1076.34231428) \lineto(-402.20445614,1076.01618664) \lineto(-402.57536452,1076.76628022) \lineto(-402.84511608,1077.94033973) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-402.84511608,1077.94033973) \lineto(-402.44048875,1077.15763339) \curveto(-402.52779384,1076.80867681)(-402.34525296,1076.54412207)(-402.06958036,1076.34231428) \lineto(-402.20445614,1076.01618664) \lineto(-402.57536452,1076.76628022) \lineto(-402.84511608,1077.94033973) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-361.84288013,1077.94033973) \lineto(-361.7417233,1077.90772697) \lineto(-361.7417233,1076.92934404) \lineto(-361.80916118,1076.92934404) \lineto(-361.84288013,1077.94033973) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-361.84288013,1077.94033973) \lineto(-361.7417233,1077.90772697) \lineto(-361.7417233,1076.92934404) \lineto(-361.80916118,1076.92934404) \lineto(-361.84288013,1077.94033973) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.65660668,1077.4185355) \lineto(-445.19610979,1077.80988867) \lineto(-444.65660668,1077.4185355) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.65660668,1077.4185355) \lineto(-445.19610979,1077.80988867) \lineto(-444.65660668,1077.4185355) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-409.31915333,1077.80988867) \lineto(-409.2179965,1077.77727591) \lineto(-408.914526,1076.63582916) \lineto(-408.6784934,1075.10302925) \lineto(-409.01568284,1075.36393136) \lineto(-409.18427756,1076.89673128) \lineto(-409.31915333,1077.80988867) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-409.31915333,1077.80988867) \lineto(-409.2179965,1077.77727591) \lineto(-408.914526,1076.63582916) \lineto(-408.6784934,1075.10302925) \lineto(-409.01568284,1075.36393136) \lineto(-409.18427756,1076.89673128) \lineto(-409.31915333,1077.80988867) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.29825264,1077.54898656) \curveto(-447.89079292,1077.49978042)(-447.3318677,1077.41938343)(-447.1180896,1077.0597951) \lineto(-448.26453369,1077.45114827) \lineto(-448.29825264,1077.54898656) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.29825264,1077.54898656) \curveto(-447.89079292,1077.49978042)(-447.3318677,1077.41938343)(-447.1180896,1077.0597951) \lineto(-448.26453369,1077.45114827) \lineto(-448.29825264,1077.54898656) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-384.50201052,1077.54898656) \lineto(-384.26597791,1077.51637379) \lineto(-384.13110214,1076.27708876) \lineto(-384.19854002,1076.27708876) \lineto(-384.26597791,1077.12502062) \curveto(-384.50686605,1077.15160655)(-384.715384,1077.35487539)(-384.50201052,1077.54898656) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-384.50201052,1077.54898656) \lineto(-384.26597791,1077.51637379) \lineto(-384.13110214,1076.27708876) \lineto(-384.19854002,1076.27708876) \lineto(-384.26597791,1077.12502062) \curveto(-384.50686605,1077.15160655)(-384.715384,1077.35487539)(-384.50201052,1077.54898656) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.52173091,1077.28808445) \lineto(-444.65660668,1077.4185355) \lineto(-444.52173091,1077.28808445) \closepath } } { \newrgbcolor{curcolor}{0.02745098 0.02745098 0.02745098} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.52173091,1077.28808445) \lineto(-444.65660668,1077.4185355) \lineto(-444.52173091,1077.28808445) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-380.59061301,1077.4185355) \lineto(-380.48945618,1077.38592274) \lineto(-380.21970463,1076.53799087) \lineto(-380.48945618,1076.86411851) \curveto(-380.72279127,1077.00278798)(-380.77269531,1077.22468523)(-380.59061301,1077.4185355) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-380.59061301,1077.4185355) \lineto(-380.48945618,1077.38592274) \lineto(-380.21970463,1076.53799087) \lineto(-380.48945618,1076.86411851) \curveto(-380.72279127,1077.00278798)(-380.77269531,1077.22468523)(-380.59061301,1077.4185355) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.38685513,1077.15763339) \lineto(-444.52173091,1077.28808445) \lineto(-444.38685513,1077.15763339) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.38685513,1077.15763339) \lineto(-444.52173091,1077.28808445) \lineto(-444.38685513,1077.15763339) \closepath } } { \newrgbcolor{curcolor}{0.88627452 0.88627452 0.88627452} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-361.4382528,1074.15725908) \lineto(-360.89874969,1076.11402494) \curveto(-361.37445656,1076.38679809)(-361.33588209,1076.90977638)(-361.03362547,1077.28808445) \lineto(-360.25808976,1076.86411851) \curveto(-358.00161802,1074.78342416)(-356.20507268,1072.42878258)(-354.55958822,1069.98282527) \lineto(-355.26768604,1068.3195743) \lineto(-355.4699997,1068.51525088) \curveto(-355.12377359,1069.054666)(-354.63444427,1069.9371674)(-355.4699997,1070.27634015) \lineto(-355.7734702,1070.76553161) \lineto(-356.0769407,1069.75453592) \curveto(-356.55736821,1069.96964971)(-356.84600237,1069.73141999)(-357.22338479,1069.49363381) \lineto(-357.49313635,1071.18949754) \lineto(-357.89776368,1072.16788047) \curveto(-357.94772166,1071.92706782)(-357.93996631,1071.36638918)(-358.302391,1071.45039966) \lineto(-358.10007734,1073.99419526) \lineto(-358.97676988,1073.14626339) \lineto(-359.01048883,1073.5050038) \lineto(-359.04420777,1074.12464632) \lineto(-359.92090032,1072.75491022) \lineto(-359.98833821,1074.51599949) \curveto(-360.16623935,1074.62152135)(-360.44893898,1074.52691563)(-360.35924659,1074.28771014) \lineto(-360.39296553,1074.05942079) \lineto(-360.62899814,1075.33131859) \lineto(-361.4382528,1074.15725908) \closepath } } { \newrgbcolor{curcolor}{0.88627452 0.88627452 0.88627452} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-361.4382528,1074.15725908) \lineto(-360.89874969,1076.11402494) \curveto(-361.37445656,1076.38679809)(-361.33588209,1076.90977638)(-361.03362547,1077.28808445) \lineto(-360.25808976,1076.86411851) \curveto(-358.00161802,1074.78342416)(-356.20507268,1072.42878258)(-354.55958822,1069.98282527) \lineto(-355.26768604,1068.3195743) \lineto(-355.4699997,1068.51525088) \curveto(-355.12377359,1069.054666)(-354.63444427,1069.9371674)(-355.4699997,1070.27634015) \lineto(-355.7734702,1070.76553161) \lineto(-356.0769407,1069.75453592) \curveto(-356.55736821,1069.96964971)(-356.84600237,1069.73141999)(-357.22338479,1069.49363381) \lineto(-357.49313635,1071.18949754) \lineto(-357.89776368,1072.16788047) \curveto(-357.94772166,1071.92706782)(-357.93996631,1071.36638918)(-358.302391,1071.45039966) \lineto(-358.10007734,1073.99419526) \lineto(-358.97676988,1073.14626339) \lineto(-359.01048883,1073.5050038) \lineto(-359.04420777,1074.12464632) \lineto(-359.92090032,1072.75491022) \lineto(-359.98833821,1074.51599949) \curveto(-360.16623935,1074.62152135)(-360.44893898,1074.52691563)(-360.35924659,1074.28771014) \lineto(-360.39296553,1074.05942079) \lineto(-360.62899814,1075.33131859) \lineto(-361.4382528,1074.15725908) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.25197935,1077.02718233) \lineto(-444.38685513,1077.15763339) \lineto(-444.25197935,1077.02718233) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.25197935,1077.02718233) \lineto(-444.38685513,1077.15763339) \lineto(-444.25197935,1077.02718233) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.25197935,1077.02718233) \lineto(-444.01594675,1076.92934404) \lineto(-444.25197935,1077.02718233) \closepath } } { \newrgbcolor{curcolor}{0.07058824 0.07058824 0.07058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.25197935,1077.02718233) \lineto(-444.01594675,1076.92934404) \lineto(-444.25197935,1077.02718233) \closepath } } { \newrgbcolor{curcolor}{0.87843138 0.87843138 0.87843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-383.55788009,1077.02718233) \lineto(-383.32184748,1076.99456957) \lineto(-382.31027916,1074.05942079) \lineto(-381.26499189,1072.20049323) \curveto(-381.39253043,1071.2026731)(-381.11474028,1070.08979514)(-380.21970463,1069.55885933) \curveto(-379.70501867,1068.46267911)(-378.36516271,1068.29439724)(-377.25243755,1068.45002535) \curveto(-377.00035473,1068.59104295)(-376.5394842,1068.79780787)(-376.71293445,1069.16750616) \lineto(-376.94896706,1069.20011893) \curveto(-377.75323131,1068.7457579)(-379.10023569,1068.77276127)(-379.64648258,1069.5914721) \lineto(-379.54532575,1069.75453592) \lineto(-379.8150773,1072.42878258) \curveto(-379.54370724,1071.57458906)(-379.51066267,1070.33373861)(-378.29772482,1070.24372738) \lineto(-375.22930091,1069.29795722) \curveto(-375.74735877,1067.95561585)(-377.41563724,1067.43511613)(-378.80350898,1067.47164243) \lineto(-379.00582264,1067.01506373) \lineto(-379.34301208,1067.01506373) \curveto(-381.02761053,1068.22930216)(-381.95420711,1070.23198679)(-382.07424655,1072.20049323) \lineto(-383.28812854,1075.07041648) \lineto(-383.28812854,1076.11402494) \lineto(-383.55788009,1077.02718233) \closepath } } { \newrgbcolor{curcolor}{0.87843138 0.87843138 0.87843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-383.55788009,1077.02718233) \lineto(-383.32184748,1076.99456957) \lineto(-382.31027916,1074.05942079) \lineto(-381.26499189,1072.20049323) \curveto(-381.39253043,1071.2026731)(-381.11474028,1070.08979514)(-380.21970463,1069.55885933) \curveto(-379.70501867,1068.46267911)(-378.36516271,1068.29439724)(-377.25243755,1068.45002535) \curveto(-377.00035473,1068.59104295)(-376.5394842,1068.79780787)(-376.71293445,1069.16750616) \lineto(-376.94896706,1069.20011893) \curveto(-377.75323131,1068.7457579)(-379.10023569,1068.77276127)(-379.64648258,1069.5914721) \lineto(-379.54532575,1069.75453592) \lineto(-379.8150773,1072.42878258) \curveto(-379.54370724,1071.57458906)(-379.51066267,1070.33373861)(-378.29772482,1070.24372738) \lineto(-375.22930091,1069.29795722) \curveto(-375.74735877,1067.95561585)(-377.41563724,1067.43511613)(-378.80350898,1067.47164243) \lineto(-379.00582264,1067.01506373) \lineto(-379.34301208,1067.01506373) \curveto(-381.02761053,1068.22930216)(-381.95420711,1070.23198679)(-382.07424655,1072.20049323) \lineto(-383.28812854,1075.07041648) \lineto(-383.28812854,1076.11402494) \lineto(-383.55788009,1077.02718233) \closepath } } { \newrgbcolor{curcolor}{0.89411765 0.89411765 0.89411765} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-383.01837698,1077.02718233) \lineto(-382.10796549,1076.99456957) \lineto(-381.83821394,1076.73366745) \lineto(-380.69176984,1074.45077396) \lineto(-380.55689407,1074.32032291) \lineto(-380.21970463,1074.25509738) \lineto(-380.48945618,1072.88536128) \lineto(-380.9615214,1072.88536128) \lineto(-381.90565183,1074.45077396) \lineto(-383.01837698,1077.02718233) \closepath } } { \newrgbcolor{curcolor}{0.89411765 0.89411765 0.89411765} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-383.01837698,1077.02718233) \lineto(-382.10796549,1076.99456957) \lineto(-381.83821394,1076.73366745) \lineto(-380.69176984,1074.45077396) \lineto(-380.55689407,1074.32032291) \lineto(-380.21970463,1074.25509738) \lineto(-380.48945618,1072.88536128) \lineto(-380.9615214,1072.88536128) \lineto(-381.90565183,1074.45077396) \lineto(-383.01837698,1077.02718233) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-407.43089247,1076.89673128) \lineto(-407.32973563,1076.86411851) \lineto(-406.79023253,1075.49438242) \lineto(-407.12742197,1075.49438242) \lineto(-407.29601669,1076.11402494) \lineto(-407.43089247,1076.89673128) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-407.43089247,1076.89673128) \lineto(-407.32973563,1076.86411851) \lineto(-406.79023253,1075.49438242) \lineto(-407.12742197,1075.49438242) \lineto(-407.29601669,1076.11402494) \lineto(-407.43089247,1076.89673128) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-453.42353213,1076.24447599) \lineto(-451.83874176,1076.21186323) \lineto(-451.83874176,1076.1466377) \lineto(-453.38981319,1076.1466377) \lineto(-453.42353213,1076.24447599) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-453.42353213,1076.24447599) \lineto(-451.83874176,1076.21186323) \lineto(-451.83874176,1076.1466377) \lineto(-453.38981319,1076.1466377) \lineto(-453.42353213,1076.24447599) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.53527127,1076.24447599) \lineto(-451.43411443,1076.01618664) \lineto(-451.53527127,1076.24447599) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.53527127,1076.24447599) \lineto(-451.43411443,1076.01618664) \lineto(-451.53527127,1076.24447599) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-379.5116068,1076.24447599) \lineto(-379.24185525,1075.85312282) \lineto(-379.24185525,1073.89635697) \lineto(-379.74763941,1073.01581234) \lineto(-379.5116068,1074.4181612) \lineto(-379.5116068,1076.24447599) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-379.5116068,1076.24447599) \lineto(-379.24185525,1075.85312282) \lineto(-379.24185525,1073.89635697) \lineto(-379.74763941,1073.01581234) \lineto(-379.5116068,1074.4181612) \lineto(-379.5116068,1076.24447599) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-454.36766257,1076.11402494) \lineto(-453.72700263,1076.01618664) \lineto(-454.36766257,1076.11402494) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-454.36766257,1076.11402494) \lineto(-453.72700263,1076.01618664) \lineto(-454.36766257,1076.11402494) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.26551971,1076.11402494) \lineto(-450.22023245,1076.08141217) \lineto(-450.22023245,1076.01618664) \lineto(-451.23180077,1076.01618664) \lineto(-451.26551971,1076.11402494) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.26551971,1076.11402494) \lineto(-450.22023245,1076.08141217) \lineto(-450.22023245,1076.01618664) \lineto(-451.23180077,1076.01618664) \lineto(-451.26551971,1076.11402494) \closepath } } { \newrgbcolor{curcolor}{0.79215688 0.79215688 0.79215688} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-378.70235215,1076.11402494) \lineto(-378.33144376,1076.08141217) \curveto(-378.37785452,1075.29322689)(-377.74689215,1074.1963944)(-378.56747637,1073.63545486) \lineto(-378.6686332,1073.66806762) \lineto(-378.80350898,1075.95096111) \lineto(-378.70235215,1076.11402494) \closepath } } { \newrgbcolor{curcolor}{0.79215688 0.79215688 0.79215688} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-378.70235215,1076.11402494) \lineto(-378.33144376,1076.08141217) \curveto(-378.37785452,1075.29322689)(-377.74689215,1074.1963944)(-378.56747637,1073.63545486) \lineto(-378.6686332,1073.66806762) \lineto(-378.80350898,1075.95096111) \lineto(-378.70235215,1076.11402494) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-449.91676195,1075.98357388) \curveto(-449.66252111,1076.00179789)(-449.93561759,1075.73767364)(-449.91676195,1075.98357388) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-449.91676195,1075.98357388) \curveto(-449.66252111,1076.00179789)(-449.93561759,1075.73767364)(-449.91676195,1075.98357388) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.00536444,1075.20086754) \curveto(-445.62285674,1075.32216093)(-445.52722982,1074.92535491)(-445.36470451,1074.71167608) \lineto(-447.35412221,1074.80951437) \lineto(-447.62387376,1074.93996542) \curveto(-448.70719599,1074.9858842)(-449.76570108,1074.90743093)(-450.69229767,1074.45077396) \lineto(-450.72601661,1075.20086754) \lineto(-450.69229767,1075.29870583) \lineto(-449.1075073,1075.72267177) \lineto(-449.61329146,1075.95096111) \curveto(-448.71946969,1076.00779864)(-447.60499115,1076.10711103)(-446.98321382,1075.49438242) \lineto(-448.66916102,1075.42915689) \lineto(-448.56800419,1075.33131859) \lineto(-447.48899798,1075.20086754) \lineto(-446.275116,1074.93996542) \lineto(-445.90420761,1074.97257819) \lineto(-446.00536444,1075.20086754) \closepath } } { \newrgbcolor{curcolor}{0.03137255 0.03137255 0.03137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.00536444,1075.20086754) \curveto(-445.62285674,1075.32216093)(-445.52722982,1074.92535491)(-445.36470451,1074.71167608) \lineto(-447.35412221,1074.80951437) \lineto(-447.62387376,1074.93996542) \curveto(-448.70719599,1074.9858842)(-449.76570108,1074.90743093)(-450.69229767,1074.45077396) \lineto(-450.72601661,1075.20086754) \lineto(-450.69229767,1075.29870583) \lineto(-449.1075073,1075.72267177) \lineto(-449.61329146,1075.95096111) \curveto(-448.71946969,1076.00779864)(-447.60499115,1076.10711103)(-446.98321382,1075.49438242) \lineto(-448.66916102,1075.42915689) \lineto(-448.56800419,1075.33131859) \lineto(-447.48899798,1075.20086754) \lineto(-446.275116,1074.93996542) \lineto(-445.90420761,1074.97257819) \lineto(-446.00536444,1075.20086754) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-414.44443283,1075.85312282) \lineto(-414.20840022,1075.690059) \lineto(-413.50030239,1074.15725908) \lineto(-413.66889711,1073.92896974) \lineto(-413.736335,1073.92896974) \lineto(-414.20840022,1075.16825477) \lineto(-414.44443283,1075.85312282) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-414.44443283,1075.85312282) \lineto(-414.20840022,1075.690059) \lineto(-413.50030239,1074.15725908) \lineto(-413.66889711,1073.92896974) \lineto(-413.736335,1073.92896974) \lineto(-414.20840022,1075.16825477) \lineto(-414.44443283,1075.85312282) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.00536444,1075.20086754) \lineto(-446.64602438,1075.36393136) \lineto(-446.64602438,1075.42915689) \lineto(-446.00536444,1075.20086754) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.00536444,1075.20086754) \lineto(-446.64602438,1075.36393136) \lineto(-446.64602438,1075.42915689) \lineto(-446.00536444,1075.20086754) \closepath } } { \newrgbcolor{curcolor}{0.9254902 0.9254902 0.9254902} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-334.8677249,1075.46176965) \curveto(-334.40658462,1075.62248535)(-334.36032223,1075.23139309)(-334.05847024,1075.07041648) \curveto(-333.1294459,1075.11775717)(-332.00700969,1075.75254506)(-331.22607894,1075.07041648) \lineto(-330.45054323,1074.90735266) \lineto(-330.51798112,1074.58122502) \lineto(-330.11335379,1074.32032291) \curveto(-328.85334429,1073.98806406)(-327.4819274,1073.69076611)(-326.40426994,1073.01581234) \lineto(-330.01219696,1073.63545486) \lineto(-330.28194851,1073.76590591) \lineto(-330.78773267,1073.60284209) \lineto(-331.09120317,1073.24410169) \lineto(-332.40624198,1073.21148892) \lineto(-330.99004633,1072.42878258) \lineto(-331.09120317,1072.33094429) \lineto(-333.48524819,1072.55923364) \lineto(-333.55268608,1072.233106) \curveto(-334.51367599,1071.72369462)(-333.21509201,1071.56415298)(-332.8783072,1071.3199486) \lineto(-334.49681651,1070.79814437) \curveto(-334.78801331,1070.77538066)(-334.8938908,1070.51806595)(-334.90144384,1070.27634015) \lineto(-335.94673111,1069.98282527) \lineto(-335.57582272,1069.68931039) \curveto(-335.69008948,1068.64544104)(-334.02879757,1069.92934034)(-334.36194074,1068.84137852) \lineto(-335.54210378,1068.54786365) \lineto(-334.19334602,1068.41741259) \lineto(-334.09218919,1068.3195743) \curveto(-334.75159685,1068.44938614)(-334.65192366,1067.8014227)(-334.22706496,1067.66731901) \curveto(-334.73150036,1067.67524913)(-335.39009878,1067.9746617)(-335.81185533,1067.50425519) \curveto(-336.13825471,1067.50759474)(-336.57471272,1067.99214214)(-336.65482893,1067.4064169) \curveto(-337.22751148,1067.49487576)(-337.16951489,1067.1044227)(-337.05945626,1066.75416162) \curveto(-337.65790008,1066.75542308)(-337.76350781,1066.2648397)(-337.32920781,1065.97145528) \curveto(-338.12389589,1065.99175346)(-337.5096716,1065.44221534)(-337.59895937,1065.05829788) \lineto(-337.86871092,1065.25397446) \curveto(-338.32216328,1066.17626343)(-339.52228793,1064.75134654)(-338.40821402,1064.73217024) \lineto(-338.2396193,1064.37342983) \lineto(-338.37449508,1064.24297877) \curveto(-338.68403498,1064.22637235)(-339.02958672,1064.49044443)(-339.0825929,1064.01468942) \lineto(-339.58837706,1063.32982138) \lineto(-340.90341588,1064.40604259) \lineto(-340.90341588,1064.73217024) \lineto(-339.28490657,1066.29758292) \curveto(-336.82072614,1068.5178599)(-336.02765657,1071.69695215)(-335.77813639,1074.7769016) \lineto(-334.8677249,1075.46176965) \closepath } } { \newrgbcolor{curcolor}{0.9254902 0.9254902 0.9254902} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-334.8677249,1075.46176965) \curveto(-334.40658462,1075.62248535)(-334.36032223,1075.23139309)(-334.05847024,1075.07041648) \curveto(-333.1294459,1075.11775717)(-332.00700969,1075.75254506)(-331.22607894,1075.07041648) \lineto(-330.45054323,1074.90735266) \lineto(-330.51798112,1074.58122502) \lineto(-330.11335379,1074.32032291) \curveto(-328.85334429,1073.98806406)(-327.4819274,1073.69076611)(-326.40426994,1073.01581234) \lineto(-330.01219696,1073.63545486) \lineto(-330.28194851,1073.76590591) \lineto(-330.78773267,1073.60284209) \lineto(-331.09120317,1073.24410169) \lineto(-332.40624198,1073.21148892) \lineto(-330.99004633,1072.42878258) \lineto(-331.09120317,1072.33094429) \lineto(-333.48524819,1072.55923364) \lineto(-333.55268608,1072.233106) \curveto(-334.51367599,1071.72369462)(-333.21509201,1071.56415298)(-332.8783072,1071.3199486) \lineto(-334.49681651,1070.79814437) \curveto(-334.78801331,1070.77538066)(-334.8938908,1070.51806595)(-334.90144384,1070.27634015) \lineto(-335.94673111,1069.98282527) \lineto(-335.57582272,1069.68931039) \curveto(-335.69008948,1068.64544104)(-334.02879757,1069.92934034)(-334.36194074,1068.84137852) \lineto(-335.54210378,1068.54786365) \lineto(-334.19334602,1068.41741259) \lineto(-334.09218919,1068.3195743) \curveto(-334.75159685,1068.44938614)(-334.65192366,1067.8014227)(-334.22706496,1067.66731901) \curveto(-334.73150036,1067.67524913)(-335.39009878,1067.9746617)(-335.81185533,1067.50425519) \curveto(-336.13825471,1067.50759474)(-336.57471272,1067.99214214)(-336.65482893,1067.4064169) \curveto(-337.22751148,1067.49487576)(-337.16951489,1067.1044227)(-337.05945626,1066.75416162) \curveto(-337.65790008,1066.75542308)(-337.76350781,1066.2648397)(-337.32920781,1065.97145528) \curveto(-338.12389589,1065.99175346)(-337.5096716,1065.44221534)(-337.59895937,1065.05829788) \lineto(-337.86871092,1065.25397446) \curveto(-338.32216328,1066.17626343)(-339.52228793,1064.75134654)(-338.40821402,1064.73217024) \lineto(-338.2396193,1064.37342983) \lineto(-338.37449508,1064.24297877) \curveto(-338.68403498,1064.22637235)(-339.02958672,1064.49044443)(-339.0825929,1064.01468942) \lineto(-339.58837706,1063.32982138) \lineto(-340.90341588,1064.40604259) \lineto(-340.90341588,1064.73217024) \lineto(-339.28490657,1066.29758292) \curveto(-336.82072614,1068.5178599)(-336.02765657,1071.69695215)(-335.77813639,1074.7769016) \lineto(-334.8677249,1075.46176965) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.67014704,1075.33131859) \curveto(-451.26079906,1075.22941023)(-451.86989807,1074.86873915)(-451.90617965,1075.16825477) \lineto(-451.80502282,1075.20086754) \lineto(-451.67014704,1075.33131859) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.67014704,1075.33131859) \curveto(-451.26079906,1075.22941023)(-451.86989807,1074.86873915)(-451.90617965,1075.16825477) \lineto(-451.80502282,1075.20086754) \lineto(-451.67014704,1075.33131859) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.13064394,1075.33131859) \lineto(-450.89461133,1075.10302925) \lineto(-451.13064394,1075.33131859) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.13064394,1075.33131859) \lineto(-450.89461133,1075.10302925) \lineto(-451.13064394,1075.33131859) \closepath } } { \newrgbcolor{curcolor}{0.90196079 0.90196079 0.90196079} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-377.62334594,1075.33131859) \lineto(-376.57805867,1075.03780372) \lineto(-376.37574501,1074.58122502) \lineto(-376.03855557,1074.51599949) \lineto(-375.49905246,1073.79851868) \lineto(-375.8362419,1073.86374421) \curveto(-376.35902041,1073.19205172)(-377.10960411,1072.76560721)(-377.99425432,1073.01581234) \lineto(-378.02797327,1073.37455274) \lineto(-377.75822171,1074.02680803) \lineto(-377.62334594,1075.33131859) \closepath } } { \newrgbcolor{curcolor}{0.90196079 0.90196079 0.90196079} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-377.62334594,1075.33131859) \lineto(-376.57805867,1075.03780372) \lineto(-376.37574501,1074.58122502) \lineto(-376.03855557,1074.51599949) \lineto(-375.49905246,1073.79851868) \lineto(-375.8362419,1073.86374421) \curveto(-376.35902041,1073.19205172)(-377.10960411,1072.76560721)(-377.99425432,1073.01581234) \lineto(-378.02797327,1073.37455274) \lineto(-377.75822171,1074.02680803) \lineto(-377.62334594,1075.33131859) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-371.14930868,1074.93996542) \curveto(-370.95387368,1074.99440265)(-370.66213738,1074.78172829)(-370.7784003,1074.58122502) \lineto(-371.14930868,1074.93996542) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-371.14930868,1074.93996542) \curveto(-370.95387368,1074.99440265)(-370.66213738,1074.78172829)(-370.7784003,1074.58122502) \lineto(-371.14930868,1074.93996542) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-448.83775574,1074.54861225) \lineto(-447.08437065,1074.54861225) \lineto(-445.76933184,1074.38554843) \lineto(-445.90420761,1073.92896974) \lineto(-446.44371072,1073.99419526) \lineto(-448.33197158,1073.79851868) \lineto(-449.24238307,1073.89635697) \lineto(-452.07477437,1073.76590591) \lineto(-452.31080698,1073.66806762) \lineto(-452.34452592,1073.76590591) \lineto(-452.31080698,1073.86374421) \lineto(-450.72601661,1073.89635697) \lineto(-449.37725885,1074.02680803) \lineto(-448.19709581,1074.18987185) \lineto(-448.83775574,1074.54861225) \closepath } } { \newrgbcolor{curcolor}{0.03529412 0.03529412 0.03529412} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-448.83775574,1074.54861225) \lineto(-447.08437065,1074.54861225) \lineto(-445.76933184,1074.38554843) \lineto(-445.90420761,1073.92896974) \lineto(-446.44371072,1073.99419526) \lineto(-448.33197158,1073.79851868) \lineto(-449.24238307,1073.89635697) \lineto(-452.07477437,1073.76590591) \lineto(-452.31080698,1073.66806762) \lineto(-452.34452592,1073.76590591) \lineto(-452.31080698,1073.86374421) \lineto(-450.72601661,1073.89635697) \lineto(-449.37725885,1074.02680803) \lineto(-448.19709581,1074.18987185) \lineto(-448.83775574,1074.54861225) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-449.24238307,1074.4181612) \curveto(-448.98814223,1074.43638521)(-449.26123871,1074.17226096)(-449.24238307,1074.4181612) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-449.24238307,1074.4181612) \curveto(-448.98814223,1074.43638521)(-449.26123871,1074.17226096)(-449.24238307,1074.4181612) \closepath } } { \newrgbcolor{curcolor}{0.9137255 0.9137255 0.9137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-374.52120309,1074.4181612) \lineto(-374.35260837,1074.18987185) \curveto(-373.7505229,1074.11662358)(-374.14665306,1073.5980154)(-374.08285681,1073.27671445) \curveto(-373.89983038,1072.94719508)(-373.66555116,1073.25967754)(-373.47591582,1073.34193998) \lineto(-373.40847793,1072.49400811) \lineto(-372.80153694,1072.29833153) \lineto(-372.90269377,1071.67868901) \curveto(-372.81270465,1071.0550025)(-373.58867197,1070.85332517)(-374.08285681,1070.8633699) \curveto(-374.77598343,1070.47684342)(-375.80926675,1070.07035793)(-376.51062078,1070.66769332) \lineto(-376.51062078,1070.73291885) \curveto(-375.50768451,1070.97294879)(-375.02428973,1071.88884566)(-374.65607886,1072.72229746) \lineto(-374.65607886,1073.37455274) \lineto(-374.52120309,1074.4181612) \closepath } } { \newrgbcolor{curcolor}{0.9137255 0.9137255 0.9137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-374.52120309,1074.4181612) \lineto(-374.35260837,1074.18987185) \curveto(-373.7505229,1074.11662358)(-374.14665306,1073.5980154)(-374.08285681,1073.27671445) \curveto(-373.89983038,1072.94719508)(-373.66555116,1073.25967754)(-373.47591582,1073.34193998) \lineto(-373.40847793,1072.49400811) \lineto(-372.80153694,1072.29833153) \lineto(-372.90269377,1071.67868901) \curveto(-372.81270465,1071.0550025)(-373.58867197,1070.85332517)(-374.08285681,1070.8633699) \curveto(-374.77598343,1070.47684342)(-375.80926675,1070.07035793)(-376.51062078,1070.66769332) \lineto(-376.51062078,1070.73291885) \curveto(-375.50768451,1070.97294879)(-375.02428973,1071.88884566)(-374.65607886,1072.72229746) \lineto(-374.65607886,1073.37455274) \lineto(-374.52120309,1074.4181612) \closepath } } { \newrgbcolor{curcolor}{0.68627453 0.68627453 0.68627453} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-361.4382528,1074.15725908) \lineto(-361.87659907,1072.49400811) \lineto(-361.94403696,1072.49400811) \lineto(-361.53940963,1074.12464632) \lineto(-361.4382528,1074.15725908) \closepath } } { \newrgbcolor{curcolor}{0.68627453 0.68627453 0.68627453} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-361.4382528,1074.15725908) \lineto(-361.87659907,1072.49400811) \lineto(-361.94403696,1072.49400811) \lineto(-361.53940963,1074.12464632) \lineto(-361.4382528,1074.15725908) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-453.0189048,1073.76590591) \lineto(-452.51312064,1073.66806762) \lineto(-453.0189048,1073.76590591) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-453.0189048,1073.76590591) \lineto(-452.51312064,1073.66806762) \lineto(-453.0189048,1073.76590591) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.21924643,1073.37455274) \lineto(-446.44371072,1073.34193998) \lineto(-446.44371072,1073.27671445) \lineto(-446.8146191,1073.24410169) \lineto(-448.8040368,1073.08103787) \lineto(-448.93891258,1072.88536128) \lineto(-448.56800419,1072.85274852) \lineto(-447.08437065,1072.98319957) \lineto(-446.94949488,1072.85274852) \lineto(-447.08437065,1072.72229746) \lineto(-451.23180077,1072.75491022) \lineto(-451.23180077,1072.82013575) \lineto(-449.51213462,1072.85274852) \lineto(-449.41097779,1072.88536128) \lineto(-449.47841568,1073.08103787) \lineto(-449.3435399,1073.21148892) \lineto(-449.14122624,1073.14626339) \lineto(-447.25296537,1073.27671445) \lineto(-447.21924643,1073.37455274) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.21924643,1073.37455274) \lineto(-446.44371072,1073.34193998) \lineto(-446.44371072,1073.27671445) \lineto(-446.8146191,1073.24410169) \lineto(-448.8040368,1073.08103787) \lineto(-448.93891258,1072.88536128) \lineto(-448.56800419,1072.85274852) \lineto(-447.08437065,1072.98319957) \lineto(-446.94949488,1072.85274852) \lineto(-447.08437065,1072.72229746) \lineto(-451.23180077,1072.75491022) \lineto(-451.23180077,1072.82013575) \lineto(-449.51213462,1072.85274852) \lineto(-449.41097779,1072.88536128) \lineto(-449.47841568,1073.08103787) \lineto(-449.3435399,1073.21148892) \lineto(-449.14122624,1073.14626339) \lineto(-447.25296537,1073.27671445) \lineto(-447.21924643,1073.37455274) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-365.88915341,1073.11365063) \lineto(-365.78799658,1072.88536128) \curveto(-366.04129329,1072.76893371)(-365.99772841,1072.99089619)(-365.88915341,1073.11365063) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-365.88915341,1073.11365063) \lineto(-365.78799658,1072.88536128) \curveto(-366.04129329,1072.76893371)(-365.99772841,1072.99089619)(-365.88915341,1073.11365063) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.67974332,1072.98319957) \lineto(-446.03908339,1072.88536128) \lineto(-446.67974332,1072.98319957) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.67974332,1072.98319957) \lineto(-446.03908339,1072.88536128) \lineto(-446.67974332,1072.98319957) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.93989859,1072.85274852) \lineto(-451.83874176,1072.62445917) \lineto(-454.90716567,1072.5918464) \lineto(-455.0083225,1072.6896847) \lineto(-452.07477437,1072.72229746) \lineto(-451.93989859,1072.85274852) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.93989859,1072.85274852) \lineto(-451.83874176,1072.62445917) \lineto(-454.90716567,1072.5918464) \lineto(-455.0083225,1072.6896847) \lineto(-452.07477437,1072.72229746) \lineto(-451.93989859,1072.85274852) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.67014704,1072.85274852) \lineto(-451.56899021,1072.62445917) \lineto(-451.67014704,1072.85274852) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.67014704,1072.85274852) \lineto(-451.56899021,1072.62445917) \lineto(-451.67014704,1072.85274852) \closepath } } { \newrgbcolor{curcolor}{0.85882354 0.85882354 0.85882354} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-383.96250742,1072.85274852) \lineto(-383.82763164,1072.72229746) \lineto(-383.69275586,1072.07004218) \lineto(-383.11953382,1068.97182958) \lineto(-382.91722015,1068.77615299) \curveto(-382.78987044,1067.92704707)(-382.2309722,1067.20291325)(-381.77077605,1066.4932595) \lineto(-380.89408351,1065.84100422) \lineto(-382.31027916,1066.10190633) \lineto(-382.6474686,1066.55848503) \lineto(-383.11953382,1067.01506373) \lineto(-383.32184748,1067.60209348) \lineto(-384.36713474,1070.76553161) \lineto(-384.36713474,1072.20049323) \lineto(-383.96250742,1072.85274852) \closepath } } { \newrgbcolor{curcolor}{0.85882354 0.85882354 0.85882354} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-383.96250742,1072.85274852) \lineto(-383.82763164,1072.72229746) \lineto(-383.69275586,1072.07004218) \lineto(-383.11953382,1068.97182958) \lineto(-382.91722015,1068.77615299) \curveto(-382.78987044,1067.92704707)(-382.2309722,1067.20291325)(-381.77077605,1066.4932595) \lineto(-380.89408351,1065.84100422) \lineto(-382.31027916,1066.10190633) \lineto(-382.6474686,1066.55848503) \lineto(-383.11953382,1067.01506373) \lineto(-383.32184748,1067.60209348) \lineto(-384.36713474,1070.76553161) \lineto(-384.36713474,1072.20049323) \lineto(-383.96250742,1072.85274852) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-455.8512961,1072.72229746) \lineto(-455.61526349,1072.49400811) \lineto(-455.8512961,1072.72229746) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-455.8512961,1072.72229746) \lineto(-455.61526349,1072.49400811) \lineto(-455.8512961,1072.72229746) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-455.44666877,1072.72229746) \lineto(-455.34551194,1072.49400811) \lineto(-455.44666877,1072.72229746) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-455.44666877,1072.72229746) \lineto(-455.34551194,1072.49400811) \lineto(-455.44666877,1072.72229746) \closepath } } { \newrgbcolor{curcolor}{0.78039217 0.78039217 0.78039217} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-390.03191734,1072.72229746) \lineto(-389.25638163,1072.16788047) \lineto(-389.52613318,1071.71130177) \curveto(-389.77376511,1071.8160931)(-390.12673501,1071.78328466)(-390.06563629,1072.16788047) \lineto(-390.5377015,1072.29833153) \lineto(-390.03191734,1072.72229746) \closepath } } { \newrgbcolor{curcolor}{0.78039217 0.78039217 0.78039217} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-390.03191734,1072.72229746) \lineto(-389.25638163,1072.16788047) \lineto(-389.52613318,1071.71130177) \curveto(-389.77376511,1071.8160931)(-390.12673501,1071.78328466)(-390.06563629,1072.16788047) \lineto(-390.5377015,1072.29833153) \lineto(-390.03191734,1072.72229746) \closepath } } { \newrgbcolor{curcolor}{0.84313726 0.84313726 0.84313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-385.31126518,1072.72229746) \lineto(-385.04151363,1072.5918464) \lineto(-385.1763894,1071.41778689) \lineto(-383.86135058,1067.47164243) \lineto(-383.86135058,1067.27596584) \curveto(-384.90555884,1068.18951459)(-385.49739375,1069.57190444)(-385.71589251,1070.89598267) \lineto(-385.85076828,1071.15688478) \lineto(-385.85076828,1072.07004218) \lineto(-385.81704934,1072.16788047) \curveto(-385.47837626,1072.13157594)(-385.32219012,1072.43791416)(-385.31126518,1072.72229746) \closepath } } { \newrgbcolor{curcolor}{0.84313726 0.84313726 0.84313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-385.31126518,1072.72229746) \lineto(-385.04151363,1072.5918464) \lineto(-385.1763894,1071.41778689) \lineto(-383.86135058,1067.47164243) \lineto(-383.86135058,1067.27596584) \curveto(-384.90555884,1068.18951459)(-385.49739375,1069.57190444)(-385.71589251,1070.89598267) \lineto(-385.85076828,1071.15688478) \lineto(-385.85076828,1072.07004218) \lineto(-385.81704934,1072.16788047) \curveto(-385.47837626,1072.13157594)(-385.32219012,1072.43791416)(-385.31126518,1072.72229746) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-456.66055076,1072.5918464) \lineto(-456.01989082,1072.49400811) \lineto(-456.66055076,1072.5918464) \closepath } } { \newrgbcolor{curcolor}{0.05490196 0.05490196 0.05490196} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-456.66055076,1072.5918464) \lineto(-456.01989082,1072.49400811) \lineto(-456.66055076,1072.5918464) \closepath } } { \newrgbcolor{curcolor}{0.8392157 0.8392157 0.8392157} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-378.56747637,1072.5918464) \lineto(-377.79194066,1072.29833153) \curveto(-377.60486796,1071.66681796)(-376.5779238,1071.89210694)(-376.24086923,1072.29833153) \lineto(-375.86996085,1072.46139535) \lineto(-375.63392824,1072.42878258) \lineto(-376.03855557,1071.71130177) \curveto(-376.15770483,1071.46566243)(-376.32813386,1071.18245319)(-376.6792155,1071.28733584) \curveto(-377.29182128,1070.93707475)(-378.37730153,1071.31615247)(-378.46631954,1072.03742941) \lineto(-378.56747637,1072.5918464) \closepath } } { \newrgbcolor{curcolor}{0.8392157 0.8392157 0.8392157} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-378.56747637,1072.5918464) \lineto(-377.79194066,1072.29833153) \curveto(-377.60486796,1071.66681796)(-376.5779238,1071.89210694)(-376.24086923,1072.29833153) \lineto(-375.86996085,1072.46139535) \lineto(-375.63392824,1072.42878258) \lineto(-376.03855557,1071.71130177) \curveto(-376.15770483,1071.46566243)(-376.32813386,1071.18245319)(-376.6792155,1071.28733584) \curveto(-377.29182128,1070.93707475)(-378.37730153,1071.31615247)(-378.46631954,1072.03742941) \lineto(-378.56747637,1072.5918464) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.48899798,1072.20049323) \lineto(-446.94949488,1072.20049323) \lineto(-446.71346227,1072.10265494) \lineto(-447.48899798,1071.93959112) \lineto(-448.12965792,1071.84175283) \lineto(-447.48899798,1072.20049323) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.48899798,1072.20049323) \lineto(-446.94949488,1072.20049323) \lineto(-446.71346227,1072.10265494) \lineto(-447.48899798,1071.93959112) \lineto(-448.12965792,1071.84175283) \lineto(-447.48899798,1072.20049323) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-414.71418438,1072.20049323) \lineto(-414.34327599,1071.45039966) \lineto(-414.5793086,1071.67868901) \lineto(-414.71418438,1072.20049323) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-414.71418438,1072.20049323) \lineto(-414.34327599,1071.45039966) \lineto(-414.5793086,1071.67868901) \lineto(-414.71418438,1072.20049323) \closepath } } { \newrgbcolor{curcolor}{0.65882355 0.65882355 0.65882355} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-371.14930868,1072.07004218) \lineto(-370.74468135,1071.93959112) \lineto(-370.91327607,1071.58085071) \curveto(-371.24318222,1071.43578914)(-371.1352816,1071.9004558)(-371.14930868,1072.07004218) \closepath } } { \newrgbcolor{curcolor}{0.65882355 0.65882355 0.65882355} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-371.14930868,1072.07004218) \lineto(-370.74468135,1071.93959112) \lineto(-370.91327607,1071.58085071) \curveto(-371.24318222,1071.43578914)(-371.1352816,1071.9004558)(-371.14930868,1072.07004218) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-449.37725885,1071.93959112) \lineto(-448.33197158,1071.90697836) \lineto(-448.33197158,1071.84175283) \lineto(-449.3435399,1071.84175283) \lineto(-449.37725885,1071.93959112) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-449.37725885,1071.93959112) \lineto(-448.33197158,1071.90697836) \lineto(-448.33197158,1071.84175283) \lineto(-449.3435399,1071.84175283) \lineto(-449.37725885,1071.93959112) \closepath } } { \newrgbcolor{curcolor}{0.66666669 0.66666669 0.66666669} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-332.5748367,1071.93959112) \lineto(-331.90045782,1071.80914006) \lineto(-330.85517056,1071.51562519) \lineto(-330.85517056,1071.45039966) \curveto(-331.0626095,1071.12988141)(-331.43999192,1071.36559343)(-331.66442521,1071.51562519) \lineto(-332.54111776,1071.84175283) \lineto(-332.5748367,1071.93959112) \closepath } } { \newrgbcolor{curcolor}{0.66666669 0.66666669 0.66666669} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-332.5748367,1071.93959112) \lineto(-331.90045782,1071.80914006) \lineto(-330.85517056,1071.51562519) \lineto(-330.85517056,1071.45039966) \curveto(-331.0626095,1071.12988141)(-331.43999192,1071.36559343)(-331.66442521,1071.51562519) \lineto(-332.54111776,1071.84175283) \lineto(-332.5748367,1071.93959112) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.80502282,1071.54823795) \lineto(-451.67014704,1071.67868901) \lineto(-450.59114083,1071.80914006) \lineto(-449.54585357,1071.7765273) \lineto(-449.6470104,1071.67868901) \lineto(-450.72601661,1071.54823795) \lineto(-451.80502282,1071.54823795) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.80502282,1071.54823795) \lineto(-451.67014704,1071.67868901) \lineto(-450.59114083,1071.80914006) \lineto(-449.54585357,1071.7765273) \lineto(-449.6470104,1071.67868901) \lineto(-450.72601661,1071.54823795) \lineto(-451.80502282,1071.54823795) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.00536444,1071.80914006) \lineto(-445.49958028,1071.71130177) \lineto(-446.00536444,1071.80914006) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.00536444,1071.80914006) \lineto(-445.49958028,1071.71130177) \lineto(-446.00536444,1071.80914006) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-447.48899798,1071.67868901) \lineto(-447.38784115,1071.45039966) \lineto(-448.43312841,1071.41778689) \lineto(-449.07378835,1071.3199486) \lineto(-449.07378835,1071.38517413) \lineto(-448.83775574,1071.41778689) \lineto(-447.52271693,1071.58085071) \lineto(-447.48899798,1071.67868901) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-447.48899798,1071.67868901) \lineto(-447.38784115,1071.45039966) \lineto(-448.43312841,1071.41778689) \lineto(-449.07378835,1071.3199486) \lineto(-449.07378835,1071.38517413) \lineto(-448.83775574,1071.41778689) \lineto(-447.52271693,1071.58085071) \lineto(-447.48899798,1071.67868901) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.8146191,1071.67868901) \lineto(-446.30883494,1071.58085071) \lineto(-446.8146191,1071.67868901) \closepath } } { \newrgbcolor{curcolor}{0.04705882 0.04705882 0.04705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.8146191,1071.67868901) \lineto(-446.30883494,1071.58085071) \lineto(-446.8146191,1071.67868901) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-418.89533344,1070.11327633) \lineto(-418.99649027,1070.14588909) \lineto(-419.46855549,1070.99382096) \lineto(-419.67086915,1071.64607624) \lineto(-419.60343126,1071.64607624) \lineto(-418.89533344,1070.11327633) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-418.89533344,1070.11327633) \lineto(-418.99649027,1070.14588909) \lineto(-419.46855549,1070.99382096) \lineto(-419.67086915,1071.64607624) \lineto(-419.60343126,1071.64607624) \lineto(-418.89533344,1070.11327633) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-398.52909124,1071.67868901) \curveto(-398.2748504,1071.69691302)(-398.54793339,1071.43278876)(-398.52909124,1071.67868901) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-398.52909124,1071.67868901) \curveto(-398.2748504,1071.69691302)(-398.54793339,1071.43278876)(-398.52909124,1071.67868901) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.80502282,1071.54823795) \lineto(-452.04105543,1071.45039966) \lineto(-451.80502282,1071.54823795) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.80502282,1071.54823795) \lineto(-452.04105543,1071.45039966) \lineto(-451.80502282,1071.54823795) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-449.37725885,1071.41778689) \lineto(-449.27610202,1071.38517413) \lineto(-450.22023245,1071.05904649) \lineto(-450.28767034,1071.05904649) \curveto(-450.43724757,1071.31081703)(-450.0734876,1071.30872981)(-449.91676195,1071.28733584) \lineto(-449.37725885,1071.41778689) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-449.37725885,1071.41778689) \lineto(-449.27610202,1071.38517413) \lineto(-450.22023245,1071.05904649) \lineto(-450.28767034,1071.05904649) \curveto(-450.43724757,1071.31081703)(-450.0734876,1071.30872981)(-449.91676195,1071.28733584) \lineto(-449.37725885,1071.41778689) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-455.98617188,1071.15688478) \lineto(-453.45725108,1071.12427202) \lineto(-453.55840791,1071.02643372) \lineto(-455.8512961,1071.02643372) \lineto(-455.98617188,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-455.98617188,1071.15688478) \lineto(-453.45725108,1071.12427202) \lineto(-453.55840791,1071.02643372) \lineto(-455.8512961,1071.02643372) \lineto(-455.98617188,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-452.88402903,1071.15688478) \lineto(-452.7828722,1070.92859543) \lineto(-452.88402903,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-452.88402903,1071.15688478) \lineto(-452.7828722,1070.92859543) \lineto(-452.88402903,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-452.61427748,1071.15688478) \lineto(-452.51312064,1070.92859543) \lineto(-452.61427748,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-452.61427748,1071.15688478) \lineto(-452.51312064,1070.92859543) \lineto(-452.61427748,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-452.20965015,1071.15688478) \curveto(-451.95540931,1071.17510879)(-452.22850578,1070.91098454)(-452.20965015,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.07843138 0.07843138 0.07843138} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-452.20965015,1071.15688478) \curveto(-451.95540931,1071.17510879)(-452.22850578,1070.91098454)(-452.20965015,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-451.93989859,1071.15688478) \lineto(-450.75973555,1071.12427202) \lineto(-450.75973555,1071.05904649) \lineto(-451.90617965,1070.92859543) \lineto(-451.93989859,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.05098039 0.05098039 0.05098039} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-451.93989859,1071.15688478) \lineto(-450.75973555,1071.12427202) \lineto(-450.75973555,1071.05904649) \lineto(-451.90617965,1070.92859543) \lineto(-451.93989859,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.80392158 0.80392158 0.80392158} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-366.69840807,1071.15688478) \lineto(-366.32749968,1071.12427202) \lineto(-366.29378074,1071.02643372) \curveto(-366.60817617,1070.26068602)(-367.29793089,1069.73783818)(-367.946009,1069.23273169) \lineto(-368.28319844,1069.16750616) \lineto(-368.55294999,1068.97182958) \lineto(-368.68782577,1069.42840828) \curveto(-367.91215518,1069.68187468)(-367.4426526,1070.42870698)(-366.93444068,1070.99382096) \lineto(-366.73212701,1071.05904649) \lineto(-366.69840807,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.80392158 0.80392158 0.80392158} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-366.69840807,1071.15688478) \lineto(-366.32749968,1071.12427202) \lineto(-366.29378074,1071.02643372) \curveto(-366.60817617,1070.26068602)(-367.29793089,1069.73783818)(-367.946009,1069.23273169) \lineto(-368.28319844,1069.16750616) \lineto(-368.55294999,1068.97182958) \lineto(-368.68782577,1069.42840828) \curveto(-367.91215518,1069.68187468)(-367.4426526,1070.42870698)(-366.93444068,1070.99382096) \lineto(-366.73212701,1071.05904649) \lineto(-366.69840807,1071.15688478) \closepath } } { \newrgbcolor{curcolor}{0.56862748 0.56862748 0.56862748} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-370.34005403,1070.63508055) \lineto(-370.23889719,1070.27634015) \curveto(-370.46589312,1070.28448551)(-370.46980452,1070.50710807)(-370.34005403,1070.63508055) \closepath } } { \newrgbcolor{curcolor}{0.56862748 0.56862748 0.56862748} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-370.34005403,1070.63508055) \lineto(-370.23889719,1070.27634015) \curveto(-370.46589312,1070.28448551)(-370.46980452,1070.50710807)(-370.34005403,1070.63508055) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-406.89138936,1070.37417844) \lineto(-406.79023253,1070.01543803) \lineto(-406.89138936,1070.37417844) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-406.89138936,1070.37417844) \lineto(-406.79023253,1070.01543803) \lineto(-406.89138936,1070.37417844) \closepath } } { \newrgbcolor{curcolor}{0.80392158 0.80392158 0.80392158} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-372.90269377,1070.37417844) \lineto(-372.53178539,1070.34156568) \lineto(-372.93641272,1069.23273169) \lineto(-373.40847793,1068.97182958) \lineto(-373.57707265,1069.20011893) \lineto(-374.08285681,1069.23273169) \curveto(-374.17330451,1069.48228456)(-373.82942523,1069.69831151)(-373.6107916,1069.75453592) \lineto(-372.90269377,1070.37417844) \closepath } } { \newrgbcolor{curcolor}{0.80392158 0.80392158 0.80392158} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-372.90269377,1070.37417844) \lineto(-372.53178539,1070.34156568) \lineto(-372.93641272,1069.23273169) \lineto(-373.40847793,1068.97182958) \lineto(-373.57707265,1069.20011893) \lineto(-374.08285681,1069.23273169) \curveto(-374.17330451,1069.48228456)(-373.82942523,1069.69831151)(-373.6107916,1069.75453592) \lineto(-372.90269377,1070.37417844) \closepath } } { \newrgbcolor{curcolor}{0.67058825 0.67058825 0.67058825} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-357.79660684,1070.37417844) \lineto(-357.69545001,1070.14588909) \lineto(-357.79660684,1070.37417844) \closepath } } { \newrgbcolor{curcolor}{0.67058825 0.67058825 0.67058825} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-357.79660684,1070.37417844) \lineto(-357.69545001,1070.14588909) \lineto(-357.79660684,1070.37417844) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.914526,1070.24372738) \curveto(-408.56843476,1070.16878325)(-408.6138879,1069.7463175)(-408.6784934,1069.49363381) \lineto(-408.74593128,1069.49363381) \lineto(-408.914526,1070.24372738) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.914526,1070.24372738) \curveto(-408.56843476,1070.16878325)(-408.6138879,1069.7463175)(-408.6784934,1069.49363381) \lineto(-408.74593128,1069.49363381) \lineto(-408.914526,1070.24372738) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-418.76045766,1069.85237421) \lineto(-418.89533344,1070.11327633) \lineto(-418.76045766,1069.85237421) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-418.76045766,1069.85237421) \lineto(-418.89533344,1070.11327633) \lineto(-418.76045766,1069.85237421) \closepath } } { \newrgbcolor{curcolor}{0.60784316 0.60784316 0.60784316} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-413.77005394,1070.11327633) \lineto(-413.66889711,1070.08066356) \lineto(-413.39914556,1069.23273169) \lineto(-413.63517817,1069.5914721) \lineto(-413.77005394,1070.11327633) \closepath } } { \newrgbcolor{curcolor}{0.60784316 0.60784316 0.60784316} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-413.77005394,1070.11327633) \lineto(-413.66889711,1070.08066356) \lineto(-413.39914556,1069.23273169) \lineto(-413.63517817,1069.5914721) \lineto(-413.77005394,1070.11327633) \closepath } } { \newrgbcolor{curcolor}{0.74117649 0.74117649 0.74117649} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-412.55617196,1070.11327633) \curveto(-412.17096674,1070.17277505)(-411.65709004,1070.11637715)(-411.71319836,1069.62408486) \lineto(-411.10625737,1068.45002535) \curveto(-411.28415851,1068.34450349)(-411.56685814,1068.43910921)(-411.47716575,1068.6783147) \lineto(-411.64576047,1069.29795722) \lineto(-412.38757724,1069.36318275) \lineto(-412.55617196,1070.11327633) \closepath } } { \newrgbcolor{curcolor}{0.74117649 0.74117649 0.74117649} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-412.55617196,1070.11327633) \curveto(-412.17096674,1070.17277505)(-411.65709004,1070.11637715)(-411.71319836,1069.62408486) \lineto(-411.10625737,1068.45002535) \curveto(-411.28415851,1068.34450349)(-411.56685814,1068.43910921)(-411.47716575,1068.6783147) \lineto(-411.64576047,1069.29795722) \lineto(-412.38757724,1069.36318275) \lineto(-412.55617196,1070.11327633) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-418.76045766,1069.85237421) \lineto(-418.65930083,1069.62408486) \lineto(-418.76045766,1069.85237421) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-418.76045766,1069.85237421) \lineto(-418.65930083,1069.62408486) \lineto(-418.76045766,1069.85237421) \closepath } } { \newrgbcolor{curcolor}{0.78431374 0.78431374 0.78431374} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-354.42471244,1069.72192316) \lineto(-353.91892828,1069.29795722) \curveto(-352.98113701,1067.68819118)(-351.31852331,1066.51021814)(-350.00753077,1065.12352341) \curveto(-350.19905437,1063.55028366)(-350.43238947,1061.8518109)(-351.62604008,1060.62296195) \lineto(-351.82835375,1060.62296195) \lineto(-351.99694847,1060.8512513) \lineto(-351.76091586,1061.14476618) \lineto(-351.69347797,1061.60134487) \curveto(-350.93250884,1062.50837107)(-350.28267735,1063.58028741)(-350.24356338,1064.764783) \lineto(-350.37843916,1064.89523406) \lineto(-351.05281804,1064.37342983) \curveto(-350.9076917,1064.7703924)(-350.69849937,1065.61532389)(-351.42372642,1065.5801021) \lineto(-351.62604008,1066.16713186) \lineto(-352.67132735,1066.85199991) \lineto(-355.06537238,1064.66694471) \lineto(-352.97479785,1067.01506373) \lineto(-353.04223573,1067.14551479) \lineto(-353.98636617,1066.62371056) \lineto(-353.98636617,1066.9498382) \curveto(-353.54316437,1067.15803809)(-353.48422365,1068.13876913)(-354.12124194,1067.79777007) \curveto(-354.09890651,1068.07393496)(-353.80549775,1068.64335382)(-354.3909935,1068.58047641) \lineto(-354.42471244,1069.72192316) \closepath } } { \newrgbcolor{curcolor}{0.78431374 0.78431374 0.78431374} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-354.42471244,1069.72192316) \lineto(-353.91892828,1069.29795722) \curveto(-352.98113701,1067.68819118)(-351.31852331,1066.51021814)(-350.00753077,1065.12352341) \curveto(-350.19905437,1063.55028366)(-350.43238947,1061.8518109)(-351.62604008,1060.62296195) \lineto(-351.82835375,1060.62296195) \lineto(-351.99694847,1060.8512513) \lineto(-351.76091586,1061.14476618) \lineto(-351.69347797,1061.60134487) \curveto(-350.93250884,1062.50837107)(-350.28267735,1063.58028741)(-350.24356338,1064.764783) \lineto(-350.37843916,1064.89523406) \lineto(-351.05281804,1064.37342983) \curveto(-350.9076917,1064.7703924)(-350.69849937,1065.61532389)(-351.42372642,1065.5801021) \lineto(-351.62604008,1066.16713186) \lineto(-352.67132735,1066.85199991) \lineto(-355.06537238,1064.66694471) \lineto(-352.97479785,1067.01506373) \lineto(-353.04223573,1067.14551479) \lineto(-353.98636617,1066.62371056) \lineto(-353.98636617,1066.9498382) \curveto(-353.54316437,1067.15803809)(-353.48422365,1068.13876913)(-354.12124194,1067.79777007) \curveto(-354.09890651,1068.07393496)(-353.80549775,1068.64335382)(-354.3909935,1068.58047641) \lineto(-354.42471244,1069.72192316) \closepath } } { \newrgbcolor{curcolor}{0.59607846 0.59607846 0.59607846} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-374.79095464,1069.5914721) \curveto(-374.48033573,1069.51524955)(-374.19601759,1069.03809872)(-374.65607886,1068.93921682) \lineto(-374.79095464,1069.5914721) \closepath } } { \newrgbcolor{curcolor}{0.59607846 0.59607846 0.59607846} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-374.79095464,1069.5914721) \curveto(-374.48033573,1069.51524955)(-374.19601759,1069.03809872)(-374.65607886,1068.93921682) \lineto(-374.79095464,1069.5914721) \closepath } } { \newrgbcolor{curcolor}{0.63921571 0.63921571 0.63921571} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-450.86089239,1067.7651573) \curveto(-450.66464813,1068.07184774)(-450.18570425,1068.30548558)(-449.81560512,1068.25434877) \lineto(-450.86089239,1067.7651573) \closepath } } { \newrgbcolor{curcolor}{0.63921571 0.63921571 0.63921571} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-450.86089239,1067.7651573) \curveto(-450.66464813,1068.07184774)(-450.18570425,1068.30548558)(-449.81560512,1068.25434877) \lineto(-450.86089239,1067.7651573) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-409.18427756,1068.15651048) \curveto(-408.72327215,1068.2209533)(-409.00556715,1067.78185504)(-409.2179965,1067.66731901) \lineto(-409.18427756,1068.15651048) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-409.18427756,1068.15651048) \curveto(-408.72327215,1068.2209533)(-409.00556715,1067.78185504)(-409.2179965,1067.66731901) \lineto(-409.18427756,1068.15651048) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-450.86089239,1067.7651573) \lineto(-450.89461133,1067.66731901) \lineto(-452.1759312,1067.27596584) \lineto(-452.1759312,1067.34119137) \lineto(-450.86089239,1067.7651573) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-450.86089239,1067.7651573) \lineto(-450.89461133,1067.66731901) \lineto(-452.1759312,1067.27596584) \lineto(-452.1759312,1067.34119137) \lineto(-450.86089239,1067.7651573) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-421.72772474,1067.37380413) \lineto(-421.0870648,1066.55848503) \lineto(-421.0870648,1066.36280845) \curveto(-421.3782616,1066.24121502)(-421.48413909,1066.61770981)(-421.49169213,1066.81938714) \lineto(-421.72772474,1067.37380413) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-421.72772474,1067.37380413) \lineto(-421.0870648,1066.55848503) \lineto(-421.0870648,1066.36280845) \curveto(-421.3782616,1066.24121502)(-421.48413909,1066.61770981)(-421.49169213,1066.81938714) \lineto(-421.72772474,1067.37380413) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-411.47716575,1067.37380413) \curveto(-411.26797342,1067.42916756)(-410.92754696,1067.32945078)(-411.24113314,1067.14551479) \curveto(-411.34504144,1067.05580359)(-411.74125252,1067.11823747)(-411.51088469,1067.27596584) \lineto(-411.47716575,1067.37380413) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-411.47716575,1067.37380413) \curveto(-411.26797342,1067.42916756)(-410.92754696,1067.32945078)(-411.24113314,1067.14551479) \curveto(-411.34504144,1067.05580359)(-411.74125252,1067.11823747)(-411.51088469,1067.27596584) \lineto(-411.47716575,1067.37380413) \closepath } } { \newrgbcolor{curcolor}{0.72156864 0.72156864 0.72156864} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-374.92583041,1067.37380413) \lineto(-374.68979781,1067.34119137) \lineto(-375.8362419,1066.29758292) \curveto(-376.07200476,1066.05324809)(-376.42686293,1065.84935309)(-376.78037234,1065.97145528) \lineto(-376.78037234,1066.16713186) \lineto(-375.09442513,1067.14551479) \lineto(-374.92583041,1067.37380413) \closepath } } { \newrgbcolor{curcolor}{0.72156864 0.72156864 0.72156864} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-374.92583041,1067.37380413) \lineto(-374.68979781,1067.34119137) \lineto(-375.8362419,1066.29758292) \curveto(-376.07200476,1066.05324809)(-376.42686293,1065.84935309)(-376.78037234,1065.97145528) \lineto(-376.78037234,1066.16713186) \lineto(-375.09442513,1067.14551479) \lineto(-374.92583041,1067.37380413) \closepath } } { \newrgbcolor{curcolor}{0.64313728 0.64313728 0.64313728} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-412.42129618,1067.24335308) \lineto(-412.0503878,1067.01506373) \lineto(-412.52245302,1066.88461267) \lineto(-412.42129618,1067.24335308) \closepath } } { \newrgbcolor{curcolor}{0.64313728 0.64313728 0.64313728} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-412.42129618,1067.24335308) \lineto(-412.0503878,1067.01506373) \lineto(-412.52245302,1066.88461267) \lineto(-412.42129618,1067.24335308) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-424.42524026,1067.11290202) \lineto(-424.18920765,1066.75416162) \lineto(-424.42524026,1067.11290202) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-424.42524026,1067.11290202) \lineto(-424.18920765,1066.75416162) \lineto(-424.42524026,1067.11290202) \closepath } } { \newrgbcolor{curcolor}{0.66666669 0.66666669 0.66666669} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-377.62334594,1067.11290202) \lineto(-377.25243755,1067.08028926) \lineto(-377.75822171,1066.72154885) \lineto(-378.39888165,1066.62371056) \lineto(-377.99425432,1066.9498382) \lineto(-377.62334594,1067.11290202) \closepath } } { \newrgbcolor{curcolor}{0.66666669 0.66666669 0.66666669} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-377.62334594,1067.11290202) \lineto(-377.25243755,1067.08028926) \lineto(-377.75822171,1066.72154885) \lineto(-378.39888165,1066.62371056) \lineto(-377.99425432,1066.9498382) \lineto(-377.62334594,1067.11290202) \closepath } } { \newrgbcolor{curcolor}{0.72941178 0.72941178 0.72941178} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-426.04374957,1066.98245096) \lineto(-425.94259274,1066.9498382) \lineto(-425.26821386,1065.31919999) \lineto(-425.94259274,1066.29758292) \lineto(-426.27978218,1066.29758292) \curveto(-426.31996168,1066.12551797)(-426.29579194,1065.85209256)(-426.58325268,1065.93884251) \curveto(-426.77639479,1065.72346782)(-427.04857411,1065.95099664)(-426.98788001,1066.19974462) \lineto(-426.04374957,1066.98245096) \closepath } } { \newrgbcolor{curcolor}{0.72941178 0.72941178 0.72941178} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-426.04374957,1066.98245096) \lineto(-425.94259274,1066.9498382) \lineto(-425.26821386,1065.31919999) \lineto(-425.94259274,1066.29758292) \lineto(-426.27978218,1066.29758292) \curveto(-426.31996168,1066.12551797)(-426.29579194,1065.85209256)(-426.58325268,1065.93884251) \curveto(-426.77639479,1065.72346782)(-427.04857411,1065.95099664)(-426.98788001,1066.19974462) \lineto(-426.04374957,1066.98245096) \closepath } } { \newrgbcolor{curcolor}{0.60784316 0.60784316 0.60784316} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-416.60244524,1066.98245096) \curveto(-416.33134493,1066.87343302)(-416.14373273,1066.50473919)(-416.23153686,1066.23235739) \curveto(-416.76335204,1066.01554773)(-416.57344695,1066.70054623)(-416.60244524,1066.98245096) \closepath } } { \newrgbcolor{curcolor}{0.60784316 0.60784316 0.60784316} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-416.60244524,1066.98245096) \curveto(-416.33134493,1066.87343302)(-416.14373273,1066.50473919)(-416.23153686,1066.23235739) \curveto(-416.76335204,1066.01554773)(-416.57344695,1066.70054623)(-416.60244524,1066.98245096) \closepath } } { \newrgbcolor{curcolor}{0.63921571 0.63921571 0.63921571} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-414.17468127,1066.98245096) \lineto(-413.80377289,1066.75416162) \curveto(-413.9180936,1066.69114071)(-414.44928835,1066.67276016)(-414.20840022,1066.88461267) \lineto(-414.17468127,1066.98245096) \closepath } } { \newrgbcolor{curcolor}{0.63921571 0.63921571 0.63921571} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-414.17468127,1066.98245096) \lineto(-413.80377289,1066.75416162) \curveto(-413.9180936,1066.69114071)(-414.44928835,1066.67276016)(-414.20840022,1066.88461267) \lineto(-414.17468127,1066.98245096) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-419.7045881,1066.33019568) \curveto(-419.43524117,1066.16987133)(-419.37279369,1065.75047118)(-419.46855549,1065.44965105) \lineto(-419.53599338,1065.44965105) \lineto(-419.7045881,1066.33019568) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-419.7045881,1066.33019568) \curveto(-419.43524117,1066.16987133)(-419.37279369,1065.75047118)(-419.46855549,1065.44965105) \lineto(-419.53599338,1065.44965105) \lineto(-419.7045881,1066.33019568) \closepath } } { \newrgbcolor{curcolor}{0.22745098 0.22745098 0.22745098} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-379.64648258,1066.19974462) \lineto(-379.14069842,1066.16713186) \curveto(-378.27614469,1065.46126119)(-377.73799035,1064.46083204)(-377.92681643,1063.36243414) \lineto(-378.16284904,1063.19937032) \lineto(-378.39888165,1063.36243414) \lineto(-378.73607109,1064.99307235) \lineto(-379.74763941,1065.84100422) \lineto(-379.64648258,1066.19974462) \closepath } } { \newrgbcolor{curcolor}{0.22745098 0.22745098 0.22745098} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-379.64648258,1066.19974462) \lineto(-379.14069842,1066.16713186) \curveto(-378.27614469,1065.46126119)(-377.73799035,1064.46083204)(-377.92681643,1063.36243414) \lineto(-378.16284904,1063.19937032) \lineto(-378.39888165,1063.36243414) \lineto(-378.73607109,1064.99307235) \lineto(-379.74763941,1065.84100422) \lineto(-379.64648258,1066.19974462) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.00536444,1065.93884251) \curveto(-445.75112361,1065.95706652)(-446.02422008,1065.69294227)(-446.00536444,1065.93884251) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.00536444,1065.93884251) \curveto(-445.75112361,1065.95706652)(-446.02422008,1065.69294227)(-446.00536444,1065.93884251) \closepath } } { \newrgbcolor{curcolor}{0.78823531 0.78823531 0.78823531} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-377.48847016,1065.93884251) \lineto(-377.18499966,1065.31919999) \curveto(-375.69327358,1065.17426887)(-375.28459998,1063.41331005)(-375.49905246,1062.18837463) \lineto(-375.97111768,1061.60134487) \lineto(-376.37574501,1061.14476618) \lineto(-376.37574501,1061.34044276) \lineto(-375.86996085,1062.80801715) \lineto(-376.03855557,1063.81901284) \lineto(-376.30830712,1064.60171918) \lineto(-376.64549656,1064.47126812) \lineto(-376.6792155,1064.24297877) \lineto(-376.54433973,1063.46027243) \curveto(-376.33784491,1063.12592637)(-376.33784491,1062.62055898)(-376.54433973,1062.28621292) \curveto(-376.5540292,1061.90464358)(-376.74233737,1061.44271639)(-377.08384283,1061.24260447) \lineto(-377.21871861,1061.50350658) \lineto(-377.08384283,1062.54711504) \lineto(-377.18499966,1063.75378731) \lineto(-377.62334594,1065.6779404) \lineto(-377.48847016,1065.93884251) \closepath } } { \newrgbcolor{curcolor}{0.78823531 0.78823531 0.78823531} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-377.48847016,1065.93884251) \lineto(-377.18499966,1065.31919999) \curveto(-375.69327358,1065.17426887)(-375.28459998,1063.41331005)(-375.49905246,1062.18837463) \lineto(-375.97111768,1061.60134487) \lineto(-376.37574501,1061.14476618) \lineto(-376.37574501,1061.34044276) \lineto(-375.86996085,1062.80801715) \lineto(-376.03855557,1063.81901284) \lineto(-376.30830712,1064.60171918) \lineto(-376.64549656,1064.47126812) \lineto(-376.6792155,1064.24297877) \lineto(-376.54433973,1063.46027243) \curveto(-376.33784491,1063.12592637)(-376.33784491,1062.62055898)(-376.54433973,1062.28621292) \curveto(-376.5540292,1061.90464358)(-376.74233737,1061.44271639)(-377.08384283,1061.24260447) \lineto(-377.21871861,1061.50350658) \lineto(-377.08384283,1062.54711504) \lineto(-377.18499966,1063.75378731) \lineto(-377.62334594,1065.6779404) \lineto(-377.48847016,1065.93884251) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-355.90834598,1065.93884251) \curveto(-355.56427787,1065.83766467)(-356.06264387,1065.32859247)(-356.27925436,1065.44965105) \lineto(-355.90834598,1065.93884251) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-355.90834598,1065.93884251) \curveto(-355.56427787,1065.83766467)(-356.06264387,1065.32859247)(-356.27925436,1065.44965105) \lineto(-355.90834598,1065.93884251) \closepath } } { \newrgbcolor{curcolor}{0.63529414 0.63529414 0.63529414} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-328.79831497,1065.54748934) \lineto(-329.43897491,1065.90622975) \curveto(-329.16032155,1066.04959546)(-328.89690916,1065.76677757)(-328.79831497,1065.54748934) \closepath } } { \newrgbcolor{curcolor}{0.63529414 0.63529414 0.63529414} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-328.79831497,1065.54748934) \lineto(-329.43897491,1065.90622975) \curveto(-329.16032155,1066.04959546)(-328.89690916,1065.76677757)(-328.79831497,1065.54748934) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-427.52738311,1065.80839145) \curveto(-427.2562828,1065.69937351)(-427.0686706,1065.33067968)(-427.15647473,1065.05829788) \lineto(-427.52738311,1065.80839145) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-427.52738311,1065.80839145) \curveto(-427.2562828,1065.69937351)(-427.0686706,1065.33067968)(-427.15647473,1065.05829788) \lineto(-427.52738311,1065.80839145) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-420.51384275,1065.80839145) \lineto(-420.10921542,1064.63433194) \lineto(-420.14293437,1064.53649365) \lineto(-420.48012381,1064.40604259) \lineto(-420.61499958,1064.53649365) \lineto(-420.64871853,1065.54748934) \lineto(-420.51384275,1065.80839145) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-420.51384275,1065.80839145) \lineto(-420.10921542,1064.63433194) \lineto(-420.14293437,1064.53649365) \lineto(-420.48012381,1064.40604259) \lineto(-420.61499958,1064.53649365) \lineto(-420.64871853,1065.54748934) \lineto(-420.51384275,1065.80839145) \closepath } } { \newrgbcolor{curcolor}{0.64313728 0.64313728 0.64313728} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-421.72772474,1065.54748934) \lineto(-421.32309741,1064.764783) \curveto(-421.44244898,1064.43330687)(-421.73959381,1064.05265068)(-421.45797319,1063.72117455) \lineto(-421.49169213,1063.62333625) \lineto(-421.82888157,1063.4928852) \lineto(-421.72772474,1065.54748934) \closepath } } { \newrgbcolor{curcolor}{0.64313728 0.64313728 0.64313728} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-421.72772474,1065.54748934) \lineto(-421.32309741,1064.764783) \curveto(-421.44244898,1064.43330687)(-421.73959381,1064.05265068)(-421.45797319,1063.72117455) \lineto(-421.49169213,1063.62333625) \lineto(-421.82888157,1063.4928852) \lineto(-421.72772474,1065.54748934) \closepath } } { \newrgbcolor{curcolor}{0.81176472 0.81176472 0.81176472} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-328.79831497,1065.54748934) \curveto(-327.64634097,1065.30263271)(-326.82103609,1064.33546857)(-325.86476684,1063.68856178) \lineto(-324.85319852,1062.31882569) \lineto(-324.24625753,1062.25360016) \lineto(-324.07766281,1061.89485975) \lineto(-325.02179324,1060.19899602) \lineto(-325.25782585,1060.36205984) \lineto(-327.85418454,1063.59072349) \lineto(-327.68558982,1063.81901284) \lineto(-327.48327615,1063.81901284) \lineto(-325.5275774,1061.40566829) \lineto(-325.05551218,1061.53611935) \lineto(-325.19038796,1061.86224699) \lineto(-325.72989106,1062.64495333) \lineto(-327.2135246,1064.34081707) \lineto(-327.41583827,1064.40604259) \curveto(-327.60412485,1064.90136526)(-328.18247218,1065.09860725)(-328.62972025,1065.31919999) \lineto(-328.79831497,1065.54748934) \closepath } } { \newrgbcolor{curcolor}{0.81176472 0.81176472 0.81176472} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-328.79831497,1065.54748934) \curveto(-327.64634097,1065.30263271)(-326.82103609,1064.33546857)(-325.86476684,1063.68856178) \lineto(-324.85319852,1062.31882569) \lineto(-324.24625753,1062.25360016) \lineto(-324.07766281,1061.89485975) \lineto(-325.02179324,1060.19899602) \lineto(-325.25782585,1060.36205984) \lineto(-327.85418454,1063.59072349) \lineto(-327.68558982,1063.81901284) \lineto(-327.48327615,1063.81901284) \lineto(-325.5275774,1061.40566829) \lineto(-325.05551218,1061.53611935) \lineto(-325.19038796,1061.86224699) \lineto(-325.72989106,1062.64495333) \lineto(-327.2135246,1064.34081707) \lineto(-327.41583827,1064.40604259) \curveto(-327.60412485,1064.90136526)(-328.18247218,1065.09860725)(-328.62972025,1065.31919999) \lineto(-328.79831497,1065.54748934) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-428.20176199,1065.41703828) \lineto(-427.22391262,1064.01468942) \lineto(-426.58325268,1062.93846821) \lineto(-426.61697162,1062.71017886) \lineto(-426.81928529,1062.84062991) \lineto(-428.30291882,1065.18874893) \lineto(-428.20176199,1065.41703828) \closepath } } { \newrgbcolor{curcolor}{0.67843139 0.67843139 0.67843139} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-428.20176199,1065.41703828) \lineto(-427.22391262,1064.01468942) \lineto(-426.58325268,1062.93846821) \lineto(-426.61697162,1062.71017886) \lineto(-426.81928529,1062.84062991) \lineto(-428.30291882,1065.18874893) \lineto(-428.20176199,1065.41703828) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-337.29548887,1064.89523406) \lineto(-337.05945626,1064.66694471) \lineto(-337.29548887,1064.89523406) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-337.29548887,1064.89523406) \lineto(-337.05945626,1064.66694471) \lineto(-337.29548887,1064.89523406) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.54486755,1064.63433194) \curveto(-445.88208798,1064.64998607)(-446.94571836,1064.10639652)(-446.54486755,1064.63433194) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.54486755,1064.63433194) \curveto(-445.88208798,1064.64998607)(-446.94571836,1064.10639652)(-446.54486755,1064.63433194) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-422.80673095,1064.63433194) \curveto(-422.58917632,1064.59552275)(-422.45672831,1064.33585993)(-422.57069834,1064.14514048) \curveto(-422.77139349,1064.2023824)(-423.03183862,1064.4438734)(-422.80673095,1064.63433194) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-422.80673095,1064.63433194) \curveto(-422.58917632,1064.59552275)(-422.45672831,1064.33585993)(-422.57069834,1064.14514048) \curveto(-422.77139349,1064.2023824)(-423.03183862,1064.4438734)(-422.80673095,1064.63433194) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-328.52856342,1064.63433194) \lineto(-328.02277926,1064.27559154) \lineto(-328.52856342,1064.63433194) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-328.52856342,1064.63433194) \lineto(-328.02277926,1064.27559154) \lineto(-328.52856342,1064.63433194) \closepath } } { \newrgbcolor{curcolor}{0.85882354 0.85882354 0.85882354} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-349.29943295,1064.50388089) \lineto(-346.06241432,1063.8516256) \lineto(-345.28687861,1063.68856178) \lineto(-345.25315966,1063.19937032) \lineto(-344.57878078,1058.24223016) \lineto(-344.61249972,1057.7530387) \lineto(-344.98340811,1058.37268122) \lineto(-345.25315966,1058.11177911) \curveto(-345.13843433,1057.25393296)(-345.3221756,1056.29459589)(-345.79266277,1055.50275797) \lineto(-345.65778699,1054.98095375) \lineto(-346.97282581,1052.66544749) \lineto(-347.64720469,1053.90473253) \lineto(-346.90538792,1054.88311545) \curveto(-346.71858497,1055.52193428)(-346.39717599,1056.21371623)(-345.82638171,1056.57897919) \curveto(-345.39154221,1058.33485041)(-345.51562792,1060.26683056)(-345.55663016,1062.1231491) \lineto(-345.69150593,1062.25360016) \lineto(-346.50076059,1063.29720861) \lineto(-346.7367932,1063.32982138) \lineto(-348.05183202,1063.36243414) \lineto(-348.45645935,1063.9494639) \lineto(-348.62505407,1063.72117455) \curveto(-348.78204947,1061.91964545)(-349.29039627,1060.06202241)(-350.47959599,1058.6661961) \lineto(-350.91794226,1059.15538756) \lineto(-350.74934754,1059.77503008) \curveto(-349.71795248,1060.84172837)(-349.09846804,1062.18185208)(-348.89480562,1063.59072349) \lineto(-349.265714,1064.01468942) \lineto(-349.29943295,1064.50388089) \closepath } } { \newrgbcolor{curcolor}{0.85882354 0.85882354 0.85882354} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-349.29943295,1064.50388089) \lineto(-346.06241432,1063.8516256) \lineto(-345.28687861,1063.68856178) \lineto(-345.25315966,1063.19937032) \lineto(-344.57878078,1058.24223016) \lineto(-344.61249972,1057.7530387) \lineto(-344.98340811,1058.37268122) \lineto(-345.25315966,1058.11177911) \curveto(-345.13843433,1057.25393296)(-345.3221756,1056.29459589)(-345.79266277,1055.50275797) \lineto(-345.65778699,1054.98095375) \lineto(-346.97282581,1052.66544749) \lineto(-347.64720469,1053.90473253) \lineto(-346.90538792,1054.88311545) \curveto(-346.71858497,1055.52193428)(-346.39717599,1056.21371623)(-345.82638171,1056.57897919) \curveto(-345.39154221,1058.33485041)(-345.51562792,1060.26683056)(-345.55663016,1062.1231491) \lineto(-345.69150593,1062.25360016) \lineto(-346.50076059,1063.29720861) \lineto(-346.7367932,1063.32982138) \lineto(-348.05183202,1063.36243414) \lineto(-348.45645935,1063.9494639) \lineto(-348.62505407,1063.72117455) \curveto(-348.78204947,1061.91964545)(-349.29039627,1060.06202241)(-350.47959599,1058.6661961) \lineto(-350.91794226,1059.15538756) \lineto(-350.74934754,1059.77503008) \curveto(-349.71795248,1060.84172837)(-349.09846804,1062.18185208)(-348.89480562,1063.59072349) \lineto(-349.265714,1064.01468942) \lineto(-349.29943295,1064.50388089) \closepath } } { \newrgbcolor{curcolor}{0.90980393 0.90980393 0.90980393} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-429.82027131,1064.24297877) \curveto(-429.56886286,1064.28630157)(-429.05593028,1064.24303878)(-429.17961137,1063.88423837) \lineto(-429.65167659,1063.55811073) \curveto(-429.42063438,1062.94773023)(-428.88531243,1062.36865799)(-429.04473559,1061.6665704) \lineto(-429.68539553,1062.67756609) \lineto(-429.95514708,1062.15576187) \lineto(-429.5842387,1060.49251089) \curveto(-429.81541578,1060.85255581)(-430.35694202,1062.68930669)(-430.52836913,1061.40566829) \lineto(-430.79812068,1061.47089382) \curveto(-431.13719838,1061.44066831)(-431.20301776,1061.18103157)(-431.20274801,1060.88386406) \lineto(-431.53993745,1061.07954065) \lineto(-431.20274801,1057.88348976) \lineto(-431.70853217,1059.80764284) \curveto(-431.94038363,1060.17199265)(-431.76058073,1061.11737145)(-432.48406789,1060.94908959) \curveto(-432.19894049,1059.66218992)(-432.00148236,1058.24744821)(-432.14687844,1056.8398813) \lineto(-432.38291105,1057.19862171) \curveto(-432.57214177,1058.4004673)(-432.54813388,1059.81286089)(-433.46191726,1060.72080024) \lineto(-433.83282565,1060.55773642) \lineto(-433.19216571,1059.0249365) \lineto(-432.65266261,1055.1114048) \lineto(-432.61894366,1054.36131123) \curveto(-432.51593903,1054.18559365)(-432.41878801,1053.94595506)(-432.14687844,1054.10040911) \lineto(-432.21431633,1055.99194944) \curveto(-431.54627661,1056.26863613)(-431.71635497,1055.49427865)(-431.70853217,1055.1114048) \curveto(-431.68781525,1054.71457269)(-431.81819967,1054.17006998)(-431.43878062,1053.93734529) \lineto(-431.00043435,1056.51375366) \lineto(-430.39349335,1053.57860489) \curveto(-430.9360986,1052.56095619)(-430.87553938,1051.11307991)(-432.07944056,1050.51300505) \lineto(-433.49563621,1043.40342246) \curveto(-436.87966943,1043.55618065)(-440.21784489,1043.7719467)(-443.1392542,1045.36018831) \lineto(-440.17198713,1050.64345611) \curveto(-439.90048219,1050.99619577)(-439.70059629,1051.4012463)(-440.20570607,1051.58922627) \curveto(-440.31336391,1052.14703499)(-440.03832523,1052.71814972)(-439.56504613,1052.99157513) \lineto(-439.66620297,1051.98057944) \lineto(-438.48603992,1053.44815383) \lineto(-437.67678527,1054.68743887) \curveto(-438.086403,1051.41833539)(-439.64327408,1048.41274304)(-441.38586911,1045.5558649) \lineto(-441.38586911,1045.0992862) \lineto(-440.07083029,1046.89298823) \lineto(-438.72207253,1049.37155831) \lineto(-437.91281788,1051.32832416) \lineto(-437.4744716,1052.73067302) \curveto(-437.38108362,1050.48300131)(-438.50748517,1048.15444995)(-439.26157564,1045.97983083) \lineto(-439.09298092,1045.62109043) \lineto(-438.3174452,1046.50163506) \lineto(-438.35116415,1046.14289465) \lineto(-438.68835359,1044.44703092) \lineto(-438.21628837,1044.57748197) \lineto(-437.37331477,1048.58885197) \curveto(-437.24129836,1049.47239697)(-437.15292775,1050.40212166)(-436.66521695,1051.16526034) \lineto(-436.32802751,1051.10003481) \lineto(-436.05827595,1051.36093692) \lineto(-435.75480546,1053.80689424) \lineto(-435.38389707,1056.64420472) \lineto(-434.9455508,1051.1978731) \lineto(-434.43976664,1051.16526034) \lineto(-434.00142037,1049.50200936) \curveto(-434.0432993,1049.23314974)(-434.34225145,1048.73365264)(-433.90026353,1048.62146473) \lineto(-433.63051198,1048.88236684) \curveto(-432.78214335,1052.18799662)(-433.07563304,1055.77018264)(-433.46191726,1059.15538756) \lineto(-434.23745298,1060.75341301) \curveto(-435.23040844,1061.0985865)(-434.15408626,1059.26887998)(-435.04670763,1059.1227748) \lineto(-435.11414552,1058.79664716) \lineto(-435.58621074,1058.92709821) \curveto(-435.33345353,1060.00997243)(-437.16695483,1059.84390824)(-436.69893589,1058.76403439) \lineto(-436.73265483,1056.8398813) \lineto(-436.96868744,1059.80764284) \lineto(-437.4744716,1060.10115772) \curveto(-437.33946095,1060.82163891)(-438.06104635,1061.18768457)(-438.3174452,1061.63395764) \lineto(-438.82322936,1061.40566829) \lineto(-438.75579148,1061.79702146) \lineto(-438.82322936,1062.25360016) \curveto(-435.85461353,1060.5186011)(-432.30872938,1062.34006312)(-429.82027131,1064.24297877) \closepath } } { \newrgbcolor{curcolor}{0.90980393 0.90980393 0.90980393} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-429.82027131,1064.24297877) \curveto(-429.56886286,1064.28630157)(-429.05593028,1064.24303878)(-429.17961137,1063.88423837) \lineto(-429.65167659,1063.55811073) \curveto(-429.42063438,1062.94773023)(-428.88531243,1062.36865799)(-429.04473559,1061.6665704) \lineto(-429.68539553,1062.67756609) \lineto(-429.95514708,1062.15576187) \lineto(-429.5842387,1060.49251089) \curveto(-429.81541578,1060.85255581)(-430.35694202,1062.68930669)(-430.52836913,1061.40566829) \lineto(-430.79812068,1061.47089382) \curveto(-431.13719838,1061.44066831)(-431.20301776,1061.18103157)(-431.20274801,1060.88386406) \lineto(-431.53993745,1061.07954065) \lineto(-431.20274801,1057.88348976) \lineto(-431.70853217,1059.80764284) \curveto(-431.94038363,1060.17199265)(-431.76058073,1061.11737145)(-432.48406789,1060.94908959) \curveto(-432.19894049,1059.66218992)(-432.00148236,1058.24744821)(-432.14687844,1056.8398813) \lineto(-432.38291105,1057.19862171) \curveto(-432.57214177,1058.4004673)(-432.54813388,1059.81286089)(-433.46191726,1060.72080024) \lineto(-433.83282565,1060.55773642) \lineto(-433.19216571,1059.0249365) \lineto(-432.65266261,1055.1114048) \lineto(-432.61894366,1054.36131123) \curveto(-432.51593903,1054.18559365)(-432.41878801,1053.94595506)(-432.14687844,1054.10040911) \lineto(-432.21431633,1055.99194944) \curveto(-431.54627661,1056.26863613)(-431.71635497,1055.49427865)(-431.70853217,1055.1114048) \curveto(-431.68781525,1054.71457269)(-431.81819967,1054.17006998)(-431.43878062,1053.93734529) \lineto(-431.00043435,1056.51375366) \lineto(-430.39349335,1053.57860489) \curveto(-430.9360986,1052.56095619)(-430.87553938,1051.11307991)(-432.07944056,1050.51300505) \lineto(-433.49563621,1043.40342246) \curveto(-436.87966943,1043.55618065)(-440.21784489,1043.7719467)(-443.1392542,1045.36018831) \lineto(-440.17198713,1050.64345611) \curveto(-439.90048219,1050.99619577)(-439.70059629,1051.4012463)(-440.20570607,1051.58922627) \curveto(-440.31336391,1052.14703499)(-440.03832523,1052.71814972)(-439.56504613,1052.99157513) \lineto(-439.66620297,1051.98057944) \lineto(-438.48603992,1053.44815383) \lineto(-437.67678527,1054.68743887) \curveto(-438.086403,1051.41833539)(-439.64327408,1048.41274304)(-441.38586911,1045.5558649) \lineto(-441.38586911,1045.0992862) \lineto(-440.07083029,1046.89298823) \lineto(-438.72207253,1049.37155831) \lineto(-437.91281788,1051.32832416) \lineto(-437.4744716,1052.73067302) \curveto(-437.38108362,1050.48300131)(-438.50748517,1048.15444995)(-439.26157564,1045.97983083) \lineto(-439.09298092,1045.62109043) \lineto(-438.3174452,1046.50163506) \lineto(-438.35116415,1046.14289465) \lineto(-438.68835359,1044.44703092) \lineto(-438.21628837,1044.57748197) \lineto(-437.37331477,1048.58885197) \curveto(-437.24129836,1049.47239697)(-437.15292775,1050.40212166)(-436.66521695,1051.16526034) \lineto(-436.32802751,1051.10003481) \lineto(-436.05827595,1051.36093692) \lineto(-435.75480546,1053.80689424) \lineto(-435.38389707,1056.64420472) \lineto(-434.9455508,1051.1978731) \lineto(-434.43976664,1051.16526034) \lineto(-434.00142037,1049.50200936) \curveto(-434.0432993,1049.23314974)(-434.34225145,1048.73365264)(-433.90026353,1048.62146473) \lineto(-433.63051198,1048.88236684) \curveto(-432.78214335,1052.18799662)(-433.07563304,1055.77018264)(-433.46191726,1059.15538756) \lineto(-434.23745298,1060.75341301) \curveto(-435.23040844,1061.0985865)(-434.15408626,1059.26887998)(-435.04670763,1059.1227748) \lineto(-435.11414552,1058.79664716) \lineto(-435.58621074,1058.92709821) \curveto(-435.33345353,1060.00997243)(-437.16695483,1059.84390824)(-436.69893589,1058.76403439) \lineto(-436.73265483,1056.8398813) \lineto(-436.96868744,1059.80764284) \lineto(-437.4744716,1060.10115772) \curveto(-437.33946095,1060.82163891)(-438.06104635,1061.18768457)(-438.3174452,1061.63395764) \lineto(-438.82322936,1061.40566829) \lineto(-438.75579148,1061.79702146) \lineto(-438.82322936,1062.25360016) \curveto(-435.85461353,1060.5186011)(-432.30872938,1062.34006312)(-429.82027131,1064.24297877) \closepath } } { \newrgbcolor{curcolor}{0.86274511 0.86274511 0.86274511} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.51896714,1061.37305553) \lineto(-330.72029478,1057.81826423) \lineto(-329.97847801,1054.88311545) \lineto(-329.7424454,1055.1114048) \lineto(-330.41682429,1057.98132805) \lineto(-330.45054323,1058.60097057) \lineto(-329.97847801,1057.49213659) \lineto(-329.70872646,1056.57897919) \lineto(-329.37153702,1056.44852813) \lineto(-330.24822957,1059.25322585) \curveto(-329.93545264,1059.33482299)(-329.70508481,1058.92853317)(-329.70872646,1058.6661961) \lineto(-329.23666124,1057.94871529) \lineto(-328.62972025,1056.70943025) \curveto(-328.13310764,1056.50775291)(-328.28174075,1057.0366015)(-328.49484448,1057.23123447) \lineto(-330.24822957,1060.55773642) \curveto(-329.1417087,1059.7336771)(-328.28848454,1058.59966606)(-327.82046559,1057.36168553) \lineto(-327.48327615,1057.23123447) \lineto(-327.34840038,1057.42691106) \curveto(-327.75788323,1058.97406059)(-328.93049323,1060.17551482)(-330.11335379,1061.14476618) \lineto(-332.54111776,1064.21036601) \lineto(-330.58541901,1063.16675756) \lineto(-330.68657584,1062.80801715) \lineto(-328.3599687,1060.49251089) \lineto(-326.80889727,1057.49213659) \lineto(-328.49484448,1055.86149838) \lineto(-331.66442521,1053.05680066) \lineto(-332.00161465,1053.05680066) \lineto(-331.90045782,1055.24185586) \lineto(-332.13649043,1055.66582179) \lineto(-332.97946403,1057.45952382) \lineto(-333.35037242,1058.34006846) \lineto(-330.92260845,1054.49176228) \lineto(-330.58541901,1054.49176228) \curveto(-330.80850354,1055.82366757)(-331.88993751,1056.94293764)(-332.54111776,1058.14439187) \lineto(-332.54111776,1058.34006846) \lineto(-332.3388041,1058.40529399) \lineto(-333.62012397,1060.62296195) \curveto(-333.2741676,1060.75308688)(-333.44127869,1061.08162786)(-333.51896714,1061.37305553) \closepath } } { \newrgbcolor{curcolor}{0.86274511 0.86274511 0.86274511} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.51896714,1061.37305553) \lineto(-330.72029478,1057.81826423) \lineto(-329.97847801,1054.88311545) \lineto(-329.7424454,1055.1114048) \lineto(-330.41682429,1057.98132805) \lineto(-330.45054323,1058.60097057) \lineto(-329.97847801,1057.49213659) \lineto(-329.70872646,1056.57897919) \lineto(-329.37153702,1056.44852813) \lineto(-330.24822957,1059.25322585) \curveto(-329.93545264,1059.33482299)(-329.70508481,1058.92853317)(-329.70872646,1058.6661961) \lineto(-329.23666124,1057.94871529) \lineto(-328.62972025,1056.70943025) \curveto(-328.13310764,1056.50775291)(-328.28174075,1057.0366015)(-328.49484448,1057.23123447) \lineto(-330.24822957,1060.55773642) \curveto(-329.1417087,1059.7336771)(-328.28848454,1058.59966606)(-327.82046559,1057.36168553) \lineto(-327.48327615,1057.23123447) \lineto(-327.34840038,1057.42691106) \curveto(-327.75788323,1058.97406059)(-328.93049323,1060.17551482)(-330.11335379,1061.14476618) \lineto(-332.54111776,1064.21036601) \lineto(-330.58541901,1063.16675756) \lineto(-330.68657584,1062.80801715) \lineto(-328.3599687,1060.49251089) \lineto(-326.80889727,1057.49213659) \lineto(-328.49484448,1055.86149838) \lineto(-331.66442521,1053.05680066) \lineto(-332.00161465,1053.05680066) \lineto(-331.90045782,1055.24185586) \lineto(-332.13649043,1055.66582179) \lineto(-332.97946403,1057.45952382) \lineto(-333.35037242,1058.34006846) \lineto(-330.92260845,1054.49176228) \lineto(-330.58541901,1054.49176228) \curveto(-330.80850354,1055.82366757)(-331.88993751,1056.94293764)(-332.54111776,1058.14439187) \lineto(-332.54111776,1058.34006846) \lineto(-332.3388041,1058.40529399) \lineto(-333.62012397,1060.62296195) \curveto(-333.2741676,1060.75308688)(-333.44127869,1061.08162786)(-333.51896714,1061.37305553) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-446.00536444,1064.11252772) \lineto(-446.03908339,1063.62333625) \curveto(-446.2244027,1063.5209974)(-446.73976305,1063.59579804)(-446.37627283,1063.81901284) \lineto(-446.00536444,1064.11252772) \closepath } } { \newrgbcolor{curcolor}{0.67450982 0.67450982 0.67450982} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-446.00536444,1064.11252772) \lineto(-446.03908339,1063.62333625) \curveto(-446.2244027,1063.5209974)(-446.73976305,1063.59579804)(-446.37627283,1063.81901284) \lineto(-446.00536444,1064.11252772) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-341.61151371,1064.11252772) \curveto(-341.35727287,1064.13075173)(-341.63035585,1063.86662747)(-341.61151371,1064.11252772) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-341.61151371,1064.11252772) \curveto(-341.35727287,1064.13075173)(-341.63035585,1063.86662747)(-341.61151371,1064.11252772) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-342.15101681,1063.98207666) \lineto(-341.9149842,1063.62333625) \lineto(-342.15101681,1063.98207666) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-342.15101681,1063.98207666) \lineto(-341.9149842,1063.62333625) \lineto(-342.15101681,1063.98207666) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-330.82145161,1063.98207666) \curveto(-330.56721078,1064.00030067)(-330.84030725,1063.73617642)(-330.82145161,1063.98207666) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-330.82145161,1063.98207666) \curveto(-330.56721078,1064.00030067)(-330.84030725,1063.73617642)(-330.82145161,1063.98207666) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-330.55170006,1063.8516256) \curveto(-330.29745922,1063.86984962)(-330.57055569,1063.60572536)(-330.55170006,1063.8516256) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-330.55170006,1063.8516256) \curveto(-330.29745922,1063.86984962)(-330.57055569,1063.60572536)(-330.55170006,1063.8516256) \closepath } } { \newrgbcolor{curcolor}{0.1254902 0.1254902 0.1254902} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-388.0087807,1063.72117455) \lineto(-387.4692776,1063.46027243) \lineto(-387.63787232,1063.23198308) \lineto(-389.45869529,1062.97108097) \lineto(-389.32381952,1063.29720861) \lineto(-388.68315958,1063.46027243) \lineto(-388.0087807,1063.72117455) \closepath } } { \newrgbcolor{curcolor}{0.1254902 0.1254902 0.1254902} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-388.0087807,1063.72117455) \lineto(-387.4692776,1063.46027243) \lineto(-387.63787232,1063.23198308) \lineto(-389.45869529,1062.97108097) \lineto(-389.32381952,1063.29720861) \lineto(-388.68315958,1063.46027243) \lineto(-388.0087807,1063.72117455) \closepath } } { \newrgbcolor{curcolor}{0.16470589 0.16470589 0.16470589} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-385.71589251,1063.72117455) \lineto(-385.34498412,1063.68856178) \lineto(-385.34498412,1063.36243414) \lineto(-387.60415337,1062.41666398) \lineto(-387.97506176,1062.44927674) \curveto(-388.0715384,1062.85680584)(-387.46118505,1062.84402164)(-387.19952604,1062.93846821) \lineto(-385.71589251,1063.72117455) \closepath } } { \newrgbcolor{curcolor}{0.16470589 0.16470589 0.16470589} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-385.71589251,1063.72117455) \lineto(-385.34498412,1063.68856178) \lineto(-385.34498412,1063.36243414) \lineto(-387.60415337,1062.41666398) \lineto(-387.97506176,1062.44927674) \curveto(-388.0715384,1062.85680584)(-387.46118505,1062.84402164)(-387.19952604,1062.93846821) \lineto(-385.71589251,1063.72117455) \closepath } } { \newrgbcolor{curcolor}{0.66274512 0.66274512 0.66274512} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-344.84853233,1063.72117455) \lineto(-344.61249972,1062.97108097) \lineto(-344.84853233,1063.32982138) \lineto(-344.84853233,1063.72117455) \closepath } } { \newrgbcolor{curcolor}{0.66274512 0.66274512 0.66274512} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-344.84853233,1063.72117455) \lineto(-344.61249972,1062.97108097) \lineto(-344.84853233,1063.32982138) \lineto(-344.84853233,1063.72117455) \closepath } } { \newrgbcolor{curcolor}{0.83529413 0.83529413 0.83529413} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-343.63465035,1063.72117455) \lineto(-342.45448731,1063.68856178) \lineto(-342.31961153,1063.36243414) \lineto(-342.52192519,1063.29720861) \lineto(-342.92655252,1062.97108097) \lineto(-343.39861774,1062.84062991) \lineto(-343.6009314,1062.84062991) \lineto(-343.63465035,1063.72117455) \closepath } } { \newrgbcolor{curcolor}{0.83529413 0.83529413 0.83529413} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-343.63465035,1063.72117455) \lineto(-342.45448731,1063.68856178) \lineto(-342.31961153,1063.36243414) \lineto(-342.52192519,1063.29720861) \lineto(-342.92655252,1062.97108097) \lineto(-343.39861774,1062.84062991) \lineto(-343.6009314,1062.84062991) \lineto(-343.63465035,1063.72117455) \closepath } } { \newrgbcolor{curcolor}{0.61176473 0.61176473 0.61176473} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-422.53697939,1063.32982138) \lineto(-422.30094679,1063.10153203) \lineto(-422.53697939,1063.32982138) \closepath } } { \newrgbcolor{curcolor}{0.61176473 0.61176473 0.61176473} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-422.53697939,1063.32982138) \lineto(-422.30094679,1063.10153203) \lineto(-422.53697939,1063.32982138) \closepath } } { \newrgbcolor{curcolor}{0.83529413 0.83529413 0.83529413} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.80107874,1063.19937032) \curveto(-439.50111502,1063.27543633)(-439.23109371,1063.05926588)(-439.12669986,1062.80801715) \lineto(-439.56504613,1062.18837463) \lineto(-440.64405234,1061.01431512) \lineto(-442.5997511,1058.92709821) \lineto(-442.5997511,1059.64457902) \lineto(-442.46487532,1059.90548114) \curveto(-441.59290343,1060.68388259)(-440.8531098,1061.54133739)(-440.3068629,1062.51450227) \lineto(-439.83479769,1062.97108097) \lineto(-439.80107874,1063.19937032) \closepath } } { \newrgbcolor{curcolor}{0.83529413 0.83529413 0.83529413} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.80107874,1063.19937032) \curveto(-439.50111502,1063.27543633)(-439.23109371,1063.05926588)(-439.12669986,1062.80801715) \lineto(-439.56504613,1062.18837463) \lineto(-440.64405234,1061.01431512) \lineto(-442.5997511,1058.92709821) \lineto(-442.5997511,1059.64457902) \lineto(-442.46487532,1059.90548114) \curveto(-441.59290343,1060.68388259)(-440.8531098,1061.54133739)(-440.3068629,1062.51450227) \lineto(-439.83479769,1062.97108097) \lineto(-439.80107874,1063.19937032) \closepath } } { \newrgbcolor{curcolor}{0.74117649 0.74117649 0.74117649} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-329.47269385,1063.19937032) \lineto(-328.12393609,1062.41666398) \lineto(-327.85418454,1062.54711504) \lineto(-327.61815193,1062.51450227) \lineto(-325.5275774,1059.84025561) \lineto(-325.32526374,1059.64457902) \lineto(-325.46013951,1059.44890244) \curveto(-326.59107289,1060.58774016)(-327.64917336,1062.09444987)(-329.16922336,1062.84062991) \lineto(-329.47269385,1063.19937032) \closepath } } { \newrgbcolor{curcolor}{0.74117649 0.74117649 0.74117649} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-329.47269385,1063.19937032) \lineto(-328.12393609,1062.41666398) \lineto(-327.85418454,1062.54711504) \lineto(-327.61815193,1062.51450227) \lineto(-325.5275774,1059.84025561) \lineto(-325.32526374,1059.64457902) \lineto(-325.46013951,1059.44890244) \curveto(-326.59107289,1060.58774016)(-327.64917336,1062.09444987)(-329.16922336,1062.84062991) \lineto(-329.47269385,1063.19937032) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.33098556,1063.06891926) \curveto(-444.90342935,1062.98117788)(-445.07000094,1062.41653353)(-445.33098556,1062.28621292) \lineto(-445.33098556,1063.06891926) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.33098556,1063.06891926) \curveto(-444.90342935,1062.98117788)(-445.07000094,1062.41653353)(-445.33098556,1062.28621292) \lineto(-445.33098556,1063.06891926) \closepath } } { \newrgbcolor{curcolor}{0.73725492 0.73725492 0.73725492} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-346.87166898,1062.67756609) \lineto(-346.77051214,1062.64495333) \curveto(-346.23006491,1061.62691328)(-346.32596159,1060.44946204)(-346.33216587,1059.28583862) \lineto(-346.7367932,1057.98132805) \lineto(-346.60191742,1057.45952382) \lineto(-347.84951835,1054.88311545) \lineto(-348.05183202,1054.7526644) \lineto(-348.18670779,1055.2092431) \lineto(-347.84951835,1055.53537074) \curveto(-346.93775811,1057.26384724)(-346.62525093,1059.14234246)(-346.60191742,1061.11215341) \lineto(-346.87166898,1061.63395764) \lineto(-346.87166898,1062.67756609) \closepath } } { \newrgbcolor{curcolor}{0.73725492 0.73725492 0.73725492} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-346.87166898,1062.67756609) \lineto(-346.77051214,1062.64495333) \curveto(-346.23006491,1061.62691328)(-346.32596159,1060.44946204)(-346.33216587,1059.28583862) \lineto(-346.7367932,1057.98132805) \lineto(-346.60191742,1057.45952382) \lineto(-347.84951835,1054.88311545) \lineto(-348.05183202,1054.7526644) \lineto(-348.18670779,1055.2092431) \lineto(-347.84951835,1055.53537074) \curveto(-346.93775811,1057.26384724)(-346.62525093,1059.14234246)(-346.60191742,1061.11215341) \lineto(-346.87166898,1061.63395764) \lineto(-346.87166898,1062.67756609) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-334.46309757,1062.54711504) \curveto(-334.71733841,1062.52889102)(-334.44424194,1062.79301528)(-334.46309757,1062.54711504) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-334.46309757,1062.54711504) \curveto(-334.71733841,1062.52889102)(-334.44424194,1062.79301528)(-334.46309757,1062.54711504) \closepath } } { \newrgbcolor{curcolor}{0.87058824 0.87058824 0.87058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-329.87732118,1062.67756609) \curveto(-328.25746311,1061.96425971)(-327.16631808,1060.52903719)(-325.99964262,1059.25322585) \lineto(-325.8310479,1058.76403439) \lineto(-326.74145939,1057.7530387) \curveto(-326.8593543,1058.82586819)(-327.50175414,1059.75415791)(-328.02277926,1060.68818748) \lineto(-329.84360224,1062.44927674) \lineto(-329.87732118,1062.67756609) \closepath } } { \newrgbcolor{curcolor}{0.87058824 0.87058824 0.87058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-329.87732118,1062.67756609) \curveto(-328.25746311,1061.96425971)(-327.16631808,1060.52903719)(-325.99964262,1059.25322585) \lineto(-325.8310479,1058.76403439) \lineto(-326.74145939,1057.7530387) \curveto(-326.8593543,1058.82586819)(-327.50175414,1059.75415791)(-328.02277926,1060.68818748) \lineto(-329.84360224,1062.44927674) \lineto(-329.87732118,1062.67756609) \closepath } } { \newrgbcolor{curcolor}{0.56862748 0.56862748 0.56862748} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-334.46309757,1062.54711504) \lineto(-334.09218919,1062.05792357) \lineto(-334.46309757,1062.54711504) \closepath } } { \newrgbcolor{curcolor}{0.56862748 0.56862748 0.56862748} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-334.46309757,1062.54711504) \lineto(-334.09218919,1062.05792357) \lineto(-334.46309757,1062.54711504) \closepath } } { \newrgbcolor{curcolor}{0.16862746 0.16862746 0.16862746} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-386.12051983,1062.41666398) \curveto(-385.86911139,1062.45998678)(-385.35617881,1062.41672399)(-385.4798599,1062.05792357) \lineto(-386.08680089,1061.79702146) \lineto(-385.34498412,1061.60134487) \lineto(-386.12051983,1061.37305553) \curveto(-386.28452878,1061.16668195)(-386.6095794,1061.36834233)(-386.49142822,1061.60134487) \lineto(-386.28911455,1061.6665704) \lineto(-386.39027139,1061.7644087) \lineto(-387.30068288,1061.6665704) \lineto(-387.03093132,1062.25360016) \lineto(-386.25539561,1062.28621292) \lineto(-386.12051983,1062.41666398) \closepath } } { \newrgbcolor{curcolor}{0.16862746 0.16862746 0.16862746} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-386.12051983,1062.41666398) \curveto(-385.86911139,1062.45998678)(-385.35617881,1062.41672399)(-385.4798599,1062.05792357) \lineto(-386.08680089,1061.79702146) \lineto(-385.34498412,1061.60134487) \lineto(-386.12051983,1061.37305553) \curveto(-386.28452878,1061.16668195)(-386.6095794,1061.36834233)(-386.49142822,1061.60134487) \lineto(-386.28911455,1061.6665704) \lineto(-386.39027139,1061.7644087) \lineto(-387.30068288,1061.6665704) \lineto(-387.03093132,1062.25360016) \lineto(-386.25539561,1062.28621292) \lineto(-386.12051983,1062.41666398) \closepath } } { \newrgbcolor{curcolor}{0.64705884 0.64705884 0.64705884} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-350.1086876,1062.15576187) \lineto(-349.83893605,1062.02531081) \lineto(-351.22141276,1059.97070667) \lineto(-351.42372642,1059.97070667) \lineto(-351.42372642,1060.16638325) \curveto(-350.90067816,1060.77324157)(-350.31005714,1061.3877965)(-350.1086876,1062.15576187) \closepath } } { \newrgbcolor{curcolor}{0.64705884 0.64705884 0.64705884} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-350.1086876,1062.15576187) \lineto(-349.83893605,1062.02531081) \lineto(-351.22141276,1059.97070667) \lineto(-351.42372642,1059.97070667) \lineto(-351.42372642,1060.16638325) \curveto(-350.90067816,1060.77324157)(-350.31005714,1061.3877965)(-350.1086876,1062.15576187) \closepath } } { \newrgbcolor{curcolor}{0.62352943 0.62352943 0.62352943} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-336.89086154,1061.50350658) \curveto(-337.14510238,1061.48528257)(-336.87201939,1061.74940682)(-336.89086154,1061.50350658) \closepath } } { \newrgbcolor{curcolor}{0.62352943 0.62352943 0.62352943} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-336.89086154,1061.50350658) \curveto(-337.14510238,1061.48528257)(-336.87201939,1061.74940682)(-336.89086154,1061.50350658) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-425.36937069,1061.50350658) \lineto(-425.26821386,1061.47089382) \lineto(-424.99846231,1060.88386406) \curveto(-425.46580687,1060.67031568)(-425.37557498,1061.23751688)(-425.36937069,1061.50350658) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-425.36937069,1061.50350658) \lineto(-425.26821386,1061.47089382) \lineto(-424.99846231,1060.88386406) \curveto(-425.46580687,1060.67031568)(-425.37557498,1061.23751688)(-425.36937069,1061.50350658) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-336.62110999,1061.11215341) \lineto(-336.89086154,1061.50350658) \lineto(-336.62110999,1061.11215341) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-336.62110999,1061.11215341) \lineto(-336.89086154,1061.50350658) \lineto(-336.62110999,1061.11215341) \closepath } } { \newrgbcolor{curcolor}{0.63137257 0.63137257 0.63137257} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.51896714,1061.37305553) \curveto(-333.77320797,1061.35483151)(-333.5001115,1061.61895577)(-333.51896714,1061.37305553) \closepath } } { \newrgbcolor{curcolor}{0.63137257 0.63137257 0.63137257} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.51896714,1061.37305553) \curveto(-333.77320797,1061.35483151)(-333.5001115,1061.61895577)(-333.51896714,1061.37305553) \closepath } } { \newrgbcolor{curcolor}{0.27058825 0.27058825 0.27058825} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-384.50201052,1061.11215341) \curveto(-384.30185487,1061.0860632)(-384.16387695,1060.85307761)(-384.40085369,1060.75341301) \curveto(-384.62784962,1060.76155837)(-384.63176102,1060.98418093)(-384.50201052,1061.11215341) \closepath } } { \newrgbcolor{curcolor}{0.27058825 0.27058825 0.27058825} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-384.50201052,1061.11215341) \curveto(-384.30185487,1061.0860632)(-384.16387695,1060.85307761)(-384.40085369,1060.75341301) \curveto(-384.62784962,1060.76155837)(-384.63176102,1060.98418093)(-384.50201052,1061.11215341) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-336.62110999,1061.11215341) \curveto(-336.36686915,1061.13037742)(-336.63995213,1060.86625317)(-336.62110999,1061.11215341) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-336.62110999,1061.11215341) \curveto(-336.36686915,1061.13037742)(-336.63995213,1060.86625317)(-336.62110999,1061.11215341) \closepath } } { \newrgbcolor{curcolor}{0.74509805 0.74509805 0.74509805} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.53132719,1060.98170236) \lineto(-439.29529458,1060.94908959) \curveto(-439.13506216,1060.51273081)(-439.32519654,1060.00371078)(-439.7673598,1059.84025561) \lineto(-439.53132719,1060.98170236) \closepath } } { \newrgbcolor{curcolor}{0.74509805 0.74509805 0.74509805} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.53132719,1060.98170236) \lineto(-439.29529458,1060.94908959) \curveto(-439.13506216,1060.51273081)(-439.32519654,1060.00371078)(-439.7673598,1059.84025561) \lineto(-439.53132719,1060.98170236) \closepath } } { \newrgbcolor{curcolor}{0.21176471 0.21176471 0.21176471} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-383.42300431,1060.19899602) \lineto(-383.01837698,1060.19899602) \lineto(-382.91722015,1059.97070667) \lineto(-383.92878847,1059.84025561) \lineto(-383.92878847,1060.03593219) \lineto(-383.69275586,1060.06854496) \lineto(-383.42300431,1060.19899602) \closepath } } { \newrgbcolor{curcolor}{0.21176471 0.21176471 0.21176471} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-383.42300431,1060.19899602) \lineto(-383.01837698,1060.19899602) \lineto(-382.91722015,1059.97070667) \lineto(-383.92878847,1059.84025561) \lineto(-383.92878847,1060.03593219) \lineto(-383.69275586,1060.06854496) \lineto(-383.42300431,1060.19899602) \closepath } } { \newrgbcolor{curcolor}{0.83529413 0.83529413 0.83529413} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-349.02968139,1060.06854496) \lineto(-348.52389723,1060.03593219) \lineto(-348.99596245,1058.01394082) \lineto(-348.79364879,1057.94871529) \lineto(-348.75992984,1057.72042594) \curveto(-348.96979655,1057.47517795)(-349.13866102,1057.1791845)(-348.99596245,1056.8398813) \lineto(-348.7262109,1056.44852813) \lineto(-347.71464258,1058.07916634) \lineto(-348.38902146,1055.79627285) \lineto(-348.52389723,1055.66582179) \lineto(-349.67034133,1057.10078342) \lineto(-350.1086876,1057.98132805) \lineto(-349.02968139,1060.06854496) \closepath } } { \newrgbcolor{curcolor}{0.83529413 0.83529413 0.83529413} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-349.02968139,1060.06854496) \lineto(-348.52389723,1060.03593219) \lineto(-348.99596245,1058.01394082) \lineto(-348.79364879,1057.94871529) \lineto(-348.75992984,1057.72042594) \curveto(-348.96979655,1057.47517795)(-349.13866102,1057.1791845)(-348.99596245,1056.8398813) \lineto(-348.7262109,1056.44852813) \lineto(-347.71464258,1058.07916634) \lineto(-348.38902146,1055.79627285) \lineto(-348.52389723,1055.66582179) \lineto(-349.67034133,1057.10078342) \lineto(-350.1086876,1057.98132805) \lineto(-349.02968139,1060.06854496) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-438.18256943,1059.9380939) \lineto(-438.0814126,1059.90548114) \lineto(-438.48603992,1058.92709821) \lineto(-438.55347781,1058.92709821) \lineto(-438.18256943,1059.9380939) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-438.18256943,1059.9380939) \lineto(-438.0814126,1059.90548114) \lineto(-438.48603992,1058.92709821) \lineto(-438.55347781,1058.92709821) \lineto(-438.18256943,1059.9380939) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-334.46309757,1059.9380939) \curveto(-334.20885673,1059.95631791)(-334.4819532,1059.69219366)(-334.46309757,1059.9380939) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-334.46309757,1059.9380939) \curveto(-334.20885673,1059.95631791)(-334.4819532,1059.69219366)(-334.46309757,1059.9380939) \closepath } } { \newrgbcolor{curcolor}{0.66274512 0.66274512 0.66274512} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.60073712,1059.67719179) \curveto(-445.61959275,1059.92309203)(-445.34649628,1059.65896778)(-445.60073712,1059.67719179) \closepath } } { \newrgbcolor{curcolor}{0.66274512 0.66274512 0.66274512} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.60073712,1059.67719179) \curveto(-445.61959275,1059.92309203)(-445.34649628,1059.65896778)(-445.60073712,1059.67719179) \closepath } } { \newrgbcolor{curcolor}{0.64705884 0.64705884 0.64705884} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-440.47545762,1059.80764284) \curveto(-440.16699672,1059.63740422)(-440.39103887,1059.17404206)(-440.50917657,1058.92709821) \lineto(-440.57661445,1058.92709821) \lineto(-440.47545762,1059.80764284) \closepath } } { \newrgbcolor{curcolor}{0.64705884 0.64705884 0.64705884} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-440.47545762,1059.80764284) \curveto(-440.16699672,1059.63740422)(-440.39103887,1059.17404206)(-440.50917657,1058.92709821) \lineto(-440.57661445,1058.92709821) \lineto(-440.47545762,1059.80764284) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-445.60073712,1059.67719179) \lineto(-445.83676972,1059.44890244) \lineto(-445.60073712,1059.67719179) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-445.60073712,1059.67719179) \lineto(-445.83676972,1059.44890244) \lineto(-445.60073712,1059.67719179) \closepath } } { \newrgbcolor{curcolor}{0.60392159 0.60392159 0.60392159} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-407.97039557,1059.54674073) \curveto(-407.98923772,1059.79264097)(-407.71615473,1059.52851672)(-407.97039557,1059.54674073) \closepath } } { \newrgbcolor{curcolor}{0.60392159 0.60392159 0.60392159} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-407.97039557,1059.54674073) \curveto(-407.98923772,1059.79264097)(-407.71615473,1059.52851672)(-407.97039557,1059.54674073) \closepath } } { \newrgbcolor{curcolor}{0.6156863 0.6156863 0.6156863} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-407.97039557,1059.54674073) \lineto(-408.10527135,1059.41628967) \lineto(-407.97039557,1059.54674073) \closepath } } { \newrgbcolor{curcolor}{0.6156863 0.6156863 0.6156863} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-407.97039557,1059.54674073) \lineto(-408.10527135,1059.41628967) \lineto(-407.97039557,1059.54674073) \closepath } } { \newrgbcolor{curcolor}{0.66666669 0.66666669 0.66666669} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.10527135,1059.41628967) \lineto(-408.24014712,1059.28583862) \lineto(-408.10527135,1059.41628967) \closepath } } { \newrgbcolor{curcolor}{0.66666669 0.66666669 0.66666669} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.10527135,1059.41628967) \lineto(-408.24014712,1059.28583862) \lineto(-408.10527135,1059.41628967) \closepath } } { \newrgbcolor{curcolor}{0.66274512 0.66274512 0.66274512} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-342.01614103,1059.41628967) \curveto(-341.72831613,1059.36249166)(-341.68825802,1059.01789215)(-341.78010843,1058.79664716) \lineto(-341.84754631,1058.79664716) \lineto(-342.01614103,1059.41628967) \closepath } } { \newrgbcolor{curcolor}{0.66274512 0.66274512 0.66274512} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-342.01614103,1059.41628967) \curveto(-341.72831613,1059.36249166)(-341.68825802,1059.01789215)(-341.78010843,1058.79664716) \lineto(-341.84754631,1058.79664716) \lineto(-342.01614103,1059.41628967) \closepath } } { \newrgbcolor{curcolor}{0.83529413 0.83529413 0.83529413} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.78871869,1057.72042594) \lineto(-332.5748367,1055.50275797) \lineto(-332.70971248,1055.24185586) \lineto(-332.3388041,1052.66544749) \lineto(-332.81086931,1052.40454538) \lineto(-332.97946403,1053.15463895) \lineto(-333.11433981,1054.06779635) \curveto(-333.00162412,1054.94560151)(-333.53137571,1055.6540812)(-334.0247513,1056.31807708) \lineto(-335.64326061,1059.38367691) \curveto(-334.97589527,1059.64053504)(-334.91789869,1058.81634526)(-334.63169229,1058.47051951) \lineto(-333.88987552,1056.97033236) \lineto(-333.68756186,1056.97033236) \lineto(-333.78871869,1057.72042594) \closepath } } { \newrgbcolor{curcolor}{0.83529413 0.83529413 0.83529413} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.78871869,1057.72042594) \lineto(-332.5748367,1055.50275797) \lineto(-332.70971248,1055.24185586) \lineto(-332.3388041,1052.66544749) \lineto(-332.81086931,1052.40454538) \lineto(-332.97946403,1053.15463895) \lineto(-333.11433981,1054.06779635) \curveto(-333.00162412,1054.94560151)(-333.53137571,1055.6540812)(-334.0247513,1056.31807708) \lineto(-335.64326061,1059.38367691) \curveto(-334.97589527,1059.64053504)(-334.91789869,1058.81634526)(-334.63169229,1058.47051951) \lineto(-333.88987552,1056.97033236) \lineto(-333.68756186,1056.97033236) \lineto(-333.78871869,1057.72042594) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-343.23002302,1059.28583862) \lineto(-342.99399041,1059.25322585) \lineto(-342.82539569,1058.63358333) \lineto(-342.82539569,1058.37268122) \lineto(-342.96027147,1056.41591537) \lineto(-343.09514724,1056.28546431) \lineto(-343.19630408,1056.31807708) \lineto(-343.09514724,1057.32907277) \lineto(-343.23002302,1058.89448545) \lineto(-343.23002302,1059.28583862) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-343.23002302,1059.28583862) \lineto(-342.99399041,1059.25322585) \lineto(-342.82539569,1058.63358333) \lineto(-342.82539569,1058.37268122) \lineto(-342.96027147,1056.41591537) \lineto(-343.09514724,1056.28546431) \lineto(-343.19630408,1056.31807708) \lineto(-343.09514724,1057.32907277) \lineto(-343.23002302,1058.89448545) \lineto(-343.23002302,1059.28583862) \closepath } } { \newrgbcolor{curcolor}{0.70980394 0.70980394 0.70980394} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-344.03927768,1059.15538756) \lineto(-343.87068296,1058.53574504) \lineto(-343.53349352,1058.47051951) \lineto(-343.53349352,1056.97033236) \lineto(-343.6009314,1056.97033236) \lineto(-343.66836929,1058.07916634) \lineto(-343.80324507,1058.2096174) \curveto(-344.30053205,1057.98028444)(-344.25899032,1058.90818281)(-344.03927768,1059.15538756) \closepath } } { \newrgbcolor{curcolor}{0.70980394 0.70980394 0.70980394} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-344.03927768,1059.15538756) \lineto(-343.87068296,1058.53574504) \lineto(-343.53349352,1058.47051951) \lineto(-343.53349352,1056.97033236) \lineto(-343.6009314,1056.97033236) \lineto(-343.66836929,1058.07916634) \lineto(-343.80324507,1058.2096174) \curveto(-344.30053205,1057.98028444)(-344.25899032,1058.90818281)(-344.03927768,1059.15538756) \closepath } } { \newrgbcolor{curcolor}{0.87058824 0.87058824 0.87058824} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-336.35135844,1059.15538756) \lineto(-333.95731341,1054.94834098) \lineto(-333.01318298,1052.14364326) \lineto(-333.95731341,1051.49138798) \curveto(-336.21108763,1050.61853996)(-338.46216433,1049.67029123)(-340.90341588,1049.53462213) \curveto(-340.59266209,1050.76868912)(-340.1471674,1052.21800036)(-340.5325075,1053.54599212) \lineto(-340.39763172,1056.28546431) \lineto(-340.63366433,1057.81826423) \lineto(-340.39763172,1057.19862171) \lineto(-340.229037,1056.8398813) \lineto(-339.89184756,1057.68781317) \lineto(-339.0825929,1055.86149838) \lineto(-339.18374973,1054.45914952) \lineto(-339.31862551,1052.63283473) \lineto(-339.82440967,1051.10003481) \lineto(-339.62209601,1050.96958375) \curveto(-338.71694467,1052.16229776)(-338.73677141,1053.73775518)(-338.77912241,1055.24185586) \lineto(-338.50937085,1055.50275797) \lineto(-338.61052769,1056.77465578) \lineto(-337.73383514,1056.77465578) \lineto(-337.56524042,1056.0245622) \lineto(-337.32920781,1055.92672391) \lineto(-337.3966457,1057.81826423) \lineto(-337.19433204,1057.94871529) \lineto(-337.05945626,1057.29646) \lineto(-336.89086154,1056.54636643) \lineto(-336.62110999,1056.80726854) \curveto(-337.16587325,1057.23932244)(-336.24156955,1058.36615867)(-336.18276372,1057.36168553) \lineto(-335.13747645,1053.15463895) \lineto(-335.27235223,1052.1110305) \lineto(-335.00260067,1051.32832416) \lineto(-334.73284912,1051.85012838) \curveto(-334.73640984,1054.43436382)(-335.61965735,1056.77335127)(-336.35135844,1059.15538756) \closepath } } { \newrgbcolor{curcolor}{0.87058824 0.87058824 0.87058824} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-336.35135844,1059.15538756) \lineto(-333.95731341,1054.94834098) \lineto(-333.01318298,1052.14364326) \lineto(-333.95731341,1051.49138798) \curveto(-336.21108763,1050.61853996)(-338.46216433,1049.67029123)(-340.90341588,1049.53462213) \curveto(-340.59266209,1050.76868912)(-340.1471674,1052.21800036)(-340.5325075,1053.54599212) \lineto(-340.39763172,1056.28546431) \lineto(-340.63366433,1057.81826423) \lineto(-340.39763172,1057.19862171) \lineto(-340.229037,1056.8398813) \lineto(-339.89184756,1057.68781317) \lineto(-339.0825929,1055.86149838) \lineto(-339.18374973,1054.45914952) \lineto(-339.31862551,1052.63283473) \lineto(-339.82440967,1051.10003481) \lineto(-339.62209601,1050.96958375) \curveto(-338.71694467,1052.16229776)(-338.73677141,1053.73775518)(-338.77912241,1055.24185586) \lineto(-338.50937085,1055.50275797) \lineto(-338.61052769,1056.77465578) \lineto(-337.73383514,1056.77465578) \lineto(-337.56524042,1056.0245622) \lineto(-337.32920781,1055.92672391) \lineto(-337.3966457,1057.81826423) \lineto(-337.19433204,1057.94871529) \lineto(-337.05945626,1057.29646) \lineto(-336.89086154,1056.54636643) \lineto(-336.62110999,1056.80726854) \curveto(-337.16587325,1057.23932244)(-336.24156955,1058.36615867)(-336.18276372,1057.36168553) \lineto(-335.13747645,1053.15463895) \lineto(-335.27235223,1052.1110305) \lineto(-335.00260067,1051.32832416) \lineto(-334.73284912,1051.85012838) \curveto(-334.73640984,1054.43436382)(-335.61965735,1056.77335127)(-336.35135844,1059.15538756) \closepath } } { \newrgbcolor{curcolor}{0.81960785 0.81960785 0.81960785} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.71247625,1056.41591537) \lineto(-442.63347004,1057.45952382) \lineto(-442.66718898,1057.55736212) \curveto(-443.1782333,1057.83991911)(-442.31732122,1058.75372876)(-441.92537222,1058.40529399) \lineto(-441.72305855,1058.40529399) \lineto(-441.18355545,1058.73142163) \curveto(-441.2739357,1058.24236062)(-441.45613939,1057.74834246)(-441.92537222,1057.42691106) \lineto(-442.76834582,1056.54636643) \lineto(-443.17297314,1056.67681748) \lineto(-443.71247625,1056.41591537) \closepath } } { \newrgbcolor{curcolor}{0.81960785 0.81960785 0.81960785} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.71247625,1056.41591537) \lineto(-442.63347004,1057.45952382) \lineto(-442.66718898,1057.55736212) \curveto(-443.1782333,1057.83991911)(-442.31732122,1058.75372876)(-441.92537222,1058.40529399) \lineto(-441.72305855,1058.40529399) \lineto(-441.18355545,1058.73142163) \curveto(-441.2739357,1058.24236062)(-441.45613939,1057.74834246)(-441.92537222,1057.42691106) \lineto(-442.76834582,1056.54636643) \lineto(-443.17297314,1056.67681748) \lineto(-443.71247625,1056.41591537) \closepath } } { \newrgbcolor{curcolor}{0.21176471 0.21176471 0.21176471} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-383.01837698,1058.76403439) \lineto(-382.37771705,1058.73142163) \lineto(-382.51259282,1058.53574504) \lineto(-384.06366425,1058.27484293) \lineto(-383.92878847,1058.47051951) \lineto(-383.55788009,1058.50313228) \lineto(-383.01837698,1058.76403439) \closepath } } { \newrgbcolor{curcolor}{0.21176471 0.21176471 0.21176471} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-383.01837698,1058.76403439) \lineto(-382.37771705,1058.73142163) \lineto(-382.51259282,1058.53574504) \lineto(-384.06366425,1058.27484293) \lineto(-383.92878847,1058.47051951) \lineto(-383.55788009,1058.50313228) \lineto(-383.01837698,1058.76403439) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.39645141,1058.50313228) \lineto(-439.29529458,1058.47051951) \lineto(-439.26157564,1058.24223016) \curveto(-439.46807045,1057.94427995)(-439.56626001,1057.3148536)(-440.03711135,1057.36168553) \lineto(-439.96967346,1057.49213659) \lineto(-439.39645141,1058.50313228) \closepath } } { \newrgbcolor{curcolor}{0.69803923 0.69803923 0.69803923} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.39645141,1058.50313228) \lineto(-439.29529458,1058.47051951) \lineto(-439.26157564,1058.24223016) \curveto(-439.46807045,1057.94427995)(-439.56626001,1057.3148536)(-440.03711135,1057.36168553) \lineto(-439.96967346,1057.49213659) \lineto(-439.39645141,1058.50313228) \closepath } } { \newrgbcolor{curcolor}{0.14117648 0.14117648 0.14117648} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-390.30166889,1058.37268122) \curveto(-389.60719352,1058.41385157)(-389.40150796,1057.58501774)(-389.89704157,1057.19862171) \lineto(-388.95291113,1056.54636643) \lineto(-388.54828381,1056.0245622) \lineto(-388.41340803,1055.37230692) \curveto(-388.34347494,1055.02100222)(-389.05137045,1054.67008888)(-389.22266269,1054.98095375) \lineto(-389.12150585,1055.60059627) \lineto(-390.67257728,1056.31807708) \lineto(-390.94232883,1057.16600895) \lineto(-390.47026362,1057.68781317) \lineto(-390.70629622,1057.85087699) \curveto(-393.67086578,1057.77186279)(-396.59497261,1057.17827135)(-398.96743751,1055.40491968) \lineto(-399.16975118,1055.53537074) \lineto(-398.4953723,1056.12240049) \lineto(-395.42694839,1057.45952382) \lineto(-394.2130664,1057.72042594) \curveto(-393.07984013,1058.31528276)(-391.754281,1058.26740722)(-390.43654467,1058.24223016) \lineto(-390.30166889,1058.37268122) \closepath } } { \newrgbcolor{curcolor}{0.14117648 0.14117648 0.14117648} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-390.30166889,1058.37268122) \curveto(-389.60719352,1058.41385157)(-389.40150796,1057.58501774)(-389.89704157,1057.19862171) \lineto(-388.95291113,1056.54636643) \lineto(-388.54828381,1056.0245622) \lineto(-388.41340803,1055.37230692) \curveto(-388.34347494,1055.02100222)(-389.05137045,1054.67008888)(-389.22266269,1054.98095375) \lineto(-389.12150585,1055.60059627) \lineto(-390.67257728,1056.31807708) \lineto(-390.94232883,1057.16600895) \lineto(-390.47026362,1057.68781317) \lineto(-390.70629622,1057.85087699) \curveto(-393.67086578,1057.77186279)(-396.59497261,1057.17827135)(-398.96743751,1055.40491968) \lineto(-399.16975118,1055.53537074) \lineto(-398.4953723,1056.12240049) \lineto(-395.42694839,1057.45952382) \lineto(-394.2130664,1057.72042594) \curveto(-393.07984013,1058.31528276)(-391.754281,1058.26740722)(-390.43654467,1058.24223016) \lineto(-390.30166889,1058.37268122) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-333.78871869,1057.72042594) \lineto(-334.0247513,1058.2096174) \lineto(-333.78871869,1057.72042594) \closepath } } { \newrgbcolor{curcolor}{0.57647061 0.57647061 0.57647061} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-333.78871869,1057.72042594) \lineto(-334.0247513,1058.2096174) \lineto(-333.78871869,1057.72042594) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-444.92635823,1058.11177911) \curveto(-444.35488957,1058.23412915)(-445.07971199,1057.48509223)(-445.16239084,1057.81826423) \lineto(-445.09495296,1057.88348976) \lineto(-444.92635823,1058.11177911) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-444.92635823,1058.11177911) \curveto(-444.35488957,1058.23412915)(-445.07971199,1057.48509223)(-445.16239084,1057.81826423) \lineto(-445.09495296,1057.88348976) \lineto(-444.92635823,1058.11177911) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.77965023,1057.98132805) \curveto(-408.79849237,1058.22722829)(-408.52540939,1057.96310404)(-408.77965023,1057.98132805) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.77965023,1057.98132805) \curveto(-408.79849237,1058.22722829)(-408.52540939,1057.96310404)(-408.77965023,1057.98132805) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.77965023,1057.98132805) \lineto(-408.914526,1057.85087699) \lineto(-408.77965023,1057.98132805) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.77965023,1057.98132805) \lineto(-408.914526,1057.85087699) \lineto(-408.77965023,1057.98132805) \closepath } } { \newrgbcolor{curcolor}{0.24313726 0.24313726 0.24313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-382.20912233,1057.72042594) \curveto(-381.86478447,1057.59271435)(-382.37488465,1057.12869994)(-382.61374965,1057.19862171) \lineto(-382.98465804,1057.23123447) \lineto(-382.20912233,1057.72042594) \closepath } } { \newrgbcolor{curcolor}{0.24313726 0.24313726 0.24313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-382.20912233,1057.72042594) \curveto(-381.86478447,1057.59271435)(-382.37488465,1057.12869994)(-382.61374965,1057.19862171) \lineto(-382.98465804,1057.23123447) \lineto(-382.20912233,1057.72042594) \closepath } } { \newrgbcolor{curcolor}{0.23529412 0.23529412 0.23529412} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-381.804495,1057.32907277) \lineto(-381.43358661,1057.29646) \lineto(-381.43358661,1057.10078342) \lineto(-381.56846239,1056.97033236) \lineto(-383.11953382,1056.44852813) \lineto(-382.88350121,1056.67681748) \lineto(-382.44515493,1056.90510683) \lineto(-381.804495,1057.32907277) \closepath } } { \newrgbcolor{curcolor}{0.23529412 0.23529412 0.23529412} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-381.804495,1057.32907277) \lineto(-381.43358661,1057.29646) \lineto(-381.43358661,1057.10078342) \lineto(-381.56846239,1056.97033236) \lineto(-383.11953382,1056.44852813) \lineto(-382.88350121,1056.67681748) \lineto(-382.44515493,1056.90510683) \lineto(-381.804495,1057.32907277) \closepath } } { \newrgbcolor{curcolor}{0.86666667 0.86666667 0.86666667} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-443.71247625,1056.41591537) \lineto(-447.21924643,1053.67644318) \lineto(-449.41097779,1052.40454538) \lineto(-450.59114083,1051.85012838) \curveto(-450.68648452,1051.50025865)(-450.26083006,1051.59770559)(-450.05163773,1051.58922627) \curveto(-447.66433649,1052.64770615)(-445.40786476,1054.11736775)(-443.54388153,1055.86149838) \lineto(-443.07181631,1055.99194944) \lineto(-444.42057407,1054.7526644) \lineto(-448.66916102,1051.42616245) \lineto(-448.66916102,1051.23048587) \curveto(-447.54780382,1051.31727495)(-446.66220947,1052.27579018)(-445.76933184,1052.9263496) \lineto(-445.09495296,1053.3829283) \lineto(-447.89362531,1050.54561782) \lineto(-447.72503059,1050.18687741) \lineto(-447.1180896,1050.57823058) \lineto(-446.30883494,1051.23048587) \lineto(-445.4321424,1052.07841773) \lineto(-443.07181631,1054.62221334) \curveto(-442.57776634,1055.0988815)(-441.87182653,1055.5743756)(-442.22884271,1056.28546431) \lineto(-441.9928101,1056.51375366) \curveto(-441.96491779,1056.01073439)(-441.40111007,1055.88054423)(-441.1498365,1056.28546431) \lineto(-440.64405234,1056.90510683) \lineto(-440.77892812,1056.31807708) \curveto(-442.50533805,1053.839507)(-444.70516196,1051.43920756)(-447.18552749,1049.59984766) \lineto(-447.18552749,1049.40417107) \lineto(-446.8146191,1049.24110725) \lineto(-444.55544985,1051.23048587) \lineto(-443.61131942,1052.14364326) \lineto(-443.07181631,1052.66544749) \lineto(-440.91380389,1054.81788993) \curveto(-441.01229019,1053.74219051)(-442.02018989,1052.96418041)(-442.5997511,1052.07841773) \lineto(-444.2856983,1050.18687741) \lineto(-445.9716455,1048.0996605) \lineto(-445.63445606,1048.0996605) \curveto(-443.87028091,1049.84379113)(-442.30302439,1051.57096312)(-440.84636601,1053.51337936) \lineto(-440.37430079,1053.12202619) \lineto(-441.85793433,1051.36093692) \lineto(-444.08338463,1048.68669026) \lineto(-444.89263929,1047.18650311) \curveto(-444.57810898,1047.03922386)(-444.28583317,1047.37852706)(-444.21826041,1047.64308181) \lineto(-441.25099333,1051.29571139) \lineto(-441.04867967,1051.29571139) \curveto(-441.69311613,1049.36503575)(-443.00437842,1047.5804653)(-444.42057407,1046.0124436) \curveto(-446.30209115,1047.17893695)(-448.14044798,1048.47666406)(-449.81560512,1049.99120083) \lineto(-451.40039549,1051.85012838) \curveto(-448.84584829,1053.29422158)(-446.07145357,1054.64830355)(-443.71247625,1056.41591537) \closepath } } { \newrgbcolor{curcolor}{0.86666667 0.86666667 0.86666667} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-443.71247625,1056.41591537) \lineto(-447.21924643,1053.67644318) \lineto(-449.41097779,1052.40454538) \lineto(-450.59114083,1051.85012838) \curveto(-450.68648452,1051.50025865)(-450.26083006,1051.59770559)(-450.05163773,1051.58922627) \curveto(-447.66433649,1052.64770615)(-445.40786476,1054.11736775)(-443.54388153,1055.86149838) \lineto(-443.07181631,1055.99194944) \lineto(-444.42057407,1054.7526644) \lineto(-448.66916102,1051.42616245) \lineto(-448.66916102,1051.23048587) \curveto(-447.54780382,1051.31727495)(-446.66220947,1052.27579018)(-445.76933184,1052.9263496) \lineto(-445.09495296,1053.3829283) \lineto(-447.89362531,1050.54561782) \lineto(-447.72503059,1050.18687741) \lineto(-447.1180896,1050.57823058) \lineto(-446.30883494,1051.23048587) \lineto(-445.4321424,1052.07841773) \lineto(-443.07181631,1054.62221334) \curveto(-442.57776634,1055.0988815)(-441.87182653,1055.5743756)(-442.22884271,1056.28546431) \lineto(-441.9928101,1056.51375366) \curveto(-441.96491779,1056.01073439)(-441.40111007,1055.88054423)(-441.1498365,1056.28546431) \lineto(-440.64405234,1056.90510683) \lineto(-440.77892812,1056.31807708) \curveto(-442.50533805,1053.839507)(-444.70516196,1051.43920756)(-447.18552749,1049.59984766) \lineto(-447.18552749,1049.40417107) \lineto(-446.8146191,1049.24110725) \lineto(-444.55544985,1051.23048587) \lineto(-443.61131942,1052.14364326) \lineto(-443.07181631,1052.66544749) \lineto(-440.91380389,1054.81788993) \curveto(-441.01229019,1053.74219051)(-442.02018989,1052.96418041)(-442.5997511,1052.07841773) \lineto(-444.2856983,1050.18687741) \lineto(-445.9716455,1048.0996605) \lineto(-445.63445606,1048.0996605) \curveto(-443.87028091,1049.84379113)(-442.30302439,1051.57096312)(-440.84636601,1053.51337936) \lineto(-440.37430079,1053.12202619) \lineto(-441.85793433,1051.36093692) \lineto(-444.08338463,1048.68669026) \lineto(-444.89263929,1047.18650311) \curveto(-444.57810898,1047.03922386)(-444.28583317,1047.37852706)(-444.21826041,1047.64308181) \lineto(-441.25099333,1051.29571139) \lineto(-441.04867967,1051.29571139) \curveto(-441.69311613,1049.36503575)(-443.00437842,1047.5804653)(-444.42057407,1046.0124436) \curveto(-446.30209115,1047.17893695)(-448.14044798,1048.47666406)(-449.81560512,1049.99120083) \lineto(-451.40039549,1051.85012838) \curveto(-448.84584829,1053.29422158)(-446.07145357,1054.64830355)(-443.71247625,1056.41591537) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-339.18374973,1056.67681748) \curveto(-338.96619511,1056.63800829)(-338.8337471,1056.37834547)(-338.94771713,1056.18762602) \lineto(-339.18374973,1056.67681748) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-339.18374973,1056.67681748) \curveto(-338.96619511,1056.63800829)(-338.8337471,1056.37834547)(-338.94771713,1056.18762602) \lineto(-339.18374973,1056.67681748) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-430.35977441,1056.28546431) \curveto(-430.04632311,1056.09474487)(-430.0452441,1055.61338047)(-430.1237418,1055.27446862) \curveto(-430.54347522,1055.39570984)(-430.29152727,1055.96703328)(-430.35977441,1056.28546431) \closepath } } { \newrgbcolor{curcolor}{0.58431375 0.58431375 0.58431375} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-430.35977441,1056.28546431) \curveto(-430.04632311,1056.09474487)(-430.0452441,1055.61338047)(-430.1237418,1055.27446862) \curveto(-430.54347522,1055.39570984)(-430.29152727,1055.96703328)(-430.35977441,1056.28546431) \closepath } } { \newrgbcolor{curcolor}{0.1254902 0.1254902 0.1254902} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-381.804495,1056.28546431) \curveto(-381.50223838,1056.37954562)(-381.34740099,1056.1626316)(-381.29871084,1055.92672391) \lineto(-382.71490649,1055.40491968) \lineto(-382.84978226,1055.60059627) \lineto(-382.6474686,1055.79627285) \lineto(-381.804495,1056.28546431) \closepath } } { \newrgbcolor{curcolor}{0.1254902 0.1254902 0.1254902} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-381.804495,1056.28546431) \curveto(-381.50223838,1056.37954562)(-381.34740099,1056.1626316)(-381.29871084,1055.92672391) \lineto(-382.71490649,1055.40491968) \lineto(-382.84978226,1055.60059627) \lineto(-382.6474686,1055.79627285) \lineto(-381.804495,1056.28546431) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-437.50819055,1056.0245622) \lineto(-437.40703371,1055.66582179) \lineto(-437.50819055,1056.0245622) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-437.50819055,1056.0245622) \lineto(-437.40703371,1055.66582179) \lineto(-437.50819055,1056.0245622) \closepath } } { \newrgbcolor{curcolor}{0.11372549 0.11372549 0.11372549} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-337.16061309,1055.76366009) \curveto(-336.59062806,1055.18732732)(-336.13919884,1054.3704428)(-336.08160688,1053.54599212) \lineto(-335.84557428,1051.75229009) \lineto(-335.94673111,1051.85012838) \lineto(-335.94673111,1052.37193261) \lineto(-336.8571426,1054.94834098) \lineto(-336.89086154,1053.28509001) \lineto(-337.19433204,1051.62183904) \lineto(-337.3966457,1051.49138798) \lineto(-337.29548887,1052.50238367) \lineto(-337.16061309,1052.76328578) \lineto(-337.16061309,1055.76366009) \closepath } } { \newrgbcolor{curcolor}{0.11372549 0.11372549 0.11372549} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-337.16061309,1055.76366009) \curveto(-336.59062806,1055.18732732)(-336.13919884,1054.3704428)(-336.08160688,1053.54599212) \lineto(-335.84557428,1051.75229009) \lineto(-335.94673111,1051.85012838) \lineto(-335.94673111,1052.37193261) \lineto(-336.8571426,1054.94834098) \lineto(-336.89086154,1053.28509001) \lineto(-337.19433204,1051.62183904) \lineto(-337.3966457,1051.49138798) \lineto(-337.29548887,1052.50238367) \lineto(-337.16061309,1052.76328578) \lineto(-337.16061309,1055.76366009) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-437.37331477,1055.50275797) \curveto(-437.10653049,1055.48718212)(-437.30077858,1055.11766645)(-437.4744716,1055.14401757) \lineto(-437.37331477,1055.50275797) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-437.37331477,1055.50275797) \curveto(-437.10653049,1055.48718212)(-437.30077858,1055.11766645)(-437.4744716,1055.14401757) \lineto(-437.37331477,1055.50275797) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-434.67579925,1055.50275797) \lineto(-434.43976664,1055.47014521) \lineto(-434.43976664,1054.10040911) \lineto(-434.50720453,1054.10040911) \lineto(-434.67579925,1055.50275797) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-434.67579925,1055.50275797) \lineto(-434.43976664,1055.47014521) \lineto(-434.43976664,1054.10040911) \lineto(-434.50720453,1054.10040911) \lineto(-434.67579925,1055.50275797) \closepath } } { \newrgbcolor{curcolor}{0.91764706 0.91764706 0.91764706} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-345.38803544,1051.98057944) \lineto(-345.75894382,1051.23048587) \lineto(-345.42175438,1051.23048587) \curveto(-344.40007038,1052.39906643)(-343.79515252,1053.78732658)(-343.33117985,1055.2092431) \lineto(-343.12886619,1054.94834098) \lineto(-342.82539569,1055.1114048) \lineto(-342.58936308,1055.47014521) \lineto(-343.9044019,1051.85012838) \lineto(-343.49977457,1051.58922627) \lineto(-343.73580718,1050.8391327) \lineto(-343.3648988,1051.06742204) \lineto(-341.98242209,1054.42653676) \lineto(-341.71267054,1054.10040911) \lineto(-341.24060532,1054.16563464) \lineto(-341.51035687,1052.14364326) \curveto(-341.98377085,1051.57852928)(-341.02385995,1051.42107486)(-341.20688638,1052.1110305) \lineto(-341.0720106,1052.37193261) \lineto(-340.83597799,1053.12202619) \curveto(-340.69489793,1051.82038554)(-340.92285148,1050.57170803)(-341.3754811,1049.40417107) \lineto(-345.21944072,1049.40417107) \lineto(-346.4333227,1051.23048587) \curveto(-346.55975526,1051.48721355)(-346.75729432,1051.86526071)(-346.4333227,1052.07841773) \lineto(-346.16357115,1052.33931985) \lineto(-345.82638171,1052.4697709) \lineto(-346.33216587,1051.85012838) \curveto(-346.39225303,1051.44090342)(-345.97528457,1051.43320681)(-345.82638171,1051.75229009) \lineto(-345.38803544,1051.98057944) \closepath } } { \newrgbcolor{curcolor}{0.91764706 0.91764706 0.91764706} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-345.38803544,1051.98057944) \lineto(-345.75894382,1051.23048587) \lineto(-345.42175438,1051.23048587) \curveto(-344.40007038,1052.39906643)(-343.79515252,1053.78732658)(-343.33117985,1055.2092431) \lineto(-343.12886619,1054.94834098) \lineto(-342.82539569,1055.1114048) \lineto(-342.58936308,1055.47014521) \lineto(-343.9044019,1051.85012838) \lineto(-343.49977457,1051.58922627) \lineto(-343.73580718,1050.8391327) \lineto(-343.3648988,1051.06742204) \lineto(-341.98242209,1054.42653676) \lineto(-341.71267054,1054.10040911) \lineto(-341.24060532,1054.16563464) \lineto(-341.51035687,1052.14364326) \curveto(-341.98377085,1051.57852928)(-341.02385995,1051.42107486)(-341.20688638,1052.1110305) \lineto(-341.0720106,1052.37193261) \lineto(-340.83597799,1053.12202619) \curveto(-340.69489793,1051.82038554)(-340.92285148,1050.57170803)(-341.3754811,1049.40417107) \lineto(-345.21944072,1049.40417107) \lineto(-346.4333227,1051.23048587) \curveto(-346.55975526,1051.48721355)(-346.75729432,1051.86526071)(-346.4333227,1052.07841773) \lineto(-346.16357115,1052.33931985) \lineto(-345.82638171,1052.4697709) \lineto(-346.33216587,1051.85012838) \curveto(-346.39225303,1051.44090342)(-345.97528457,1051.43320681)(-345.82638171,1051.75229009) \lineto(-345.38803544,1051.98057944) \closepath } } { \newrgbcolor{curcolor}{0.18431373 0.18431373 0.18431373} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-381.39986767,1055.1114048) \lineto(-381.02895928,1055.07879204) \lineto(-381.16383506,1054.7526644) \lineto(-382.31027916,1054.49176228) \lineto(-381.83821394,1054.88311545) \lineto(-381.39986767,1055.1114048) \closepath } } { \newrgbcolor{curcolor}{0.18431373 0.18431373 0.18431373} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-381.39986767,1055.1114048) \lineto(-381.02895928,1055.07879204) \lineto(-381.16383506,1054.7526644) \lineto(-382.31027916,1054.49176228) \lineto(-381.83821394,1054.88311545) \lineto(-381.39986767,1055.1114048) \closepath } } { \newrgbcolor{curcolor}{0.10196079 0.10196079 0.10196079} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-338.2396193,1055.1114048) \lineto(-338.10474353,1054.98095375) \lineto(-338.00358669,1054.16563464) \lineto(-338.10474353,1053.93734529) \lineto(-338.00358669,1053.51337936) \lineto(-338.10474353,1053.28509001) \lineto(-338.5430898,1050.70868164) \lineto(-338.61052769,1050.70868164) \lineto(-338.64424663,1051.1978731) \lineto(-338.37449508,1052.63283473) \lineto(-338.2396193,1052.89373684) \lineto(-338.2396193,1055.1114048) \closepath } } { \newrgbcolor{curcolor}{0.10196079 0.10196079 0.10196079} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-338.2396193,1055.1114048) \lineto(-338.10474353,1054.98095375) \lineto(-338.00358669,1054.16563464) \lineto(-338.10474353,1053.93734529) \lineto(-338.00358669,1053.51337936) \lineto(-338.10474353,1053.28509001) \lineto(-338.5430898,1050.70868164) \lineto(-338.61052769,1050.70868164) \lineto(-338.64424663,1051.1978731) \lineto(-338.37449508,1052.63283473) \lineto(-338.2396193,1052.89373684) \lineto(-338.2396193,1055.1114048) \closepath } } { \newrgbcolor{curcolor}{0.64705884 0.64705884 0.64705884} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-439.93595452,1054.98095375) \curveto(-439.59296542,1054.86073005)(-439.94037575,1054.39640256)(-440.17198713,1054.36131123) \lineto(-439.93595452,1054.98095375) \closepath } } { \newrgbcolor{curcolor}{0.64705884 0.64705884 0.64705884} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-439.93595452,1054.98095375) \curveto(-439.59296542,1054.86073005)(-439.94037575,1054.39640256)(-440.17198713,1054.36131123) \lineto(-439.93595452,1054.98095375) \closepath } } { \newrgbcolor{curcolor}{0.6901961 0.6901961 0.6901961} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-433.86654459,1054.98095375) \lineto(-433.76538776,1054.94834098) \curveto(-433.41835239,1054.36065897)(-433.64695334,1053.6606586)(-433.76538776,1053.05680066) \lineto(-433.83282565,1053.05680066) \lineto(-434.00142037,1054.19824741) \lineto(-433.86654459,1054.98095375) \closepath } } { \newrgbcolor{curcolor}{0.6901961 0.6901961 0.6901961} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-433.86654459,1054.98095375) \lineto(-433.76538776,1054.94834098) \curveto(-433.41835239,1054.36065897)(-433.64695334,1053.6606586)(-433.76538776,1053.05680066) \lineto(-433.83282565,1053.05680066) \lineto(-434.00142037,1054.19824741) \lineto(-433.86654459,1054.98095375) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-344.98340811,1054.98095375) \lineto(-344.88225128,1054.7526644) \lineto(-344.98340811,1054.98095375) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-344.98340811,1054.98095375) \lineto(-344.88225128,1054.7526644) \lineto(-344.98340811,1054.98095375) \closepath } } { \newrgbcolor{curcolor}{0.25490198 0.25490198 0.25490198} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-380.86036456,1054.58960058) \curveto(-380.70363891,1054.61105977)(-380.33987894,1054.6131209)(-380.48945618,1054.36131123) \lineto(-381.63590028,1054.10040911) \lineto(-381.5010245,1054.2960857) \lineto(-380.86036456,1054.58960058) \closepath } } { \newrgbcolor{curcolor}{0.25490198 0.25490198 0.25490198} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-380.86036456,1054.58960058) \curveto(-380.70363891,1054.61105977)(-380.33987894,1054.6131209)(-380.48945618,1054.36131123) \lineto(-381.63590028,1054.10040911) \lineto(-381.5010245,1054.2960857) \lineto(-380.86036456,1054.58960058) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-398.79884279,1054.19824741) \lineto(-397.95586919,1052.79589855) \curveto(-397.64970118,1052.84399585)(-397.34353317,1052.98113905)(-397.18033348,1052.63283473) \lineto(-394.88744528,1053.28509001) \curveto(-393.88005811,1053.70683828)(-392.65929746,1053.96434866)(-391.65042666,1053.67644318) \lineto(-391.24579933,1053.80689424) \lineto(-390.97604778,1053.67644318) \lineto(-388.58200275,1054.03518358) \lineto(-387.06465027,1051.32832416) \lineto(-387.43555865,1051.23048587) \lineto(-387.7053102,1051.49138798) \curveto(-388.05463846,1052.39437019)(-389.34135337,1052.0675903)(-389.9981984,1052.20886879) \lineto(-390.13307417,1052.01319221) \curveto(-387.82400089,1050.10077971)(-390.82714492,1046.8890747)(-393.26893597,1047.41479246) \curveto(-394.09046432,1047.71130771)(-394.98050957,1048.1108793)(-395.29207261,1048.98020514) \curveto(-395.38671494,1049.93484597)(-394.92035497,1050.78303874)(-394.24678535,1051.42616245) \lineto(-394.88744528,1051.32832416) \curveto(-396.35759124,1050.99776118)(-397.54449807,1050.05342598)(-398.76512385,1049.20849449) \lineto(-398.66396702,1048.58885197) \curveto(-398.05109149,1047.7531825)(-397.24507385,1046.97256337)(-396.26992199,1046.59947335) \lineto(-396.00017044,1046.27334571) \lineto(-396.23620305,1046.11028189) \curveto(-397.67667633,1046.49954784)(-398.74219497,1047.61438257)(-399.50694062,1048.81714132) \lineto(-399.97900583,1048.88236684) \curveto(-400.02556495,1049.28154708)(-400.25374779,1049.59084653)(-399.877849,1049.89336253) \lineto(-398.93371857,1051.71967733) \lineto(-399.97900583,1051.62183904) \lineto(-398.79884279,1054.19824741) \closepath } } { \newrgbcolor{curcolor}{0.05882353 0.05882353 0.05882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-398.79884279,1054.19824741) \lineto(-397.95586919,1052.79589855) \curveto(-397.64970118,1052.84399585)(-397.34353317,1052.98113905)(-397.18033348,1052.63283473) \lineto(-394.88744528,1053.28509001) \curveto(-393.88005811,1053.70683828)(-392.65929746,1053.96434866)(-391.65042666,1053.67644318) \lineto(-391.24579933,1053.80689424) \lineto(-390.97604778,1053.67644318) \lineto(-388.58200275,1054.03518358) \lineto(-387.06465027,1051.32832416) \lineto(-387.43555865,1051.23048587) \lineto(-387.7053102,1051.49138798) \curveto(-388.05463846,1052.39437019)(-389.34135337,1052.0675903)(-389.9981984,1052.20886879) \lineto(-390.13307417,1052.01319221) \curveto(-387.82400089,1050.10077971)(-390.82714492,1046.8890747)(-393.26893597,1047.41479246) \curveto(-394.09046432,1047.71130771)(-394.98050957,1048.1108793)(-395.29207261,1048.98020514) \curveto(-395.38671494,1049.93484597)(-394.92035497,1050.78303874)(-394.24678535,1051.42616245) \lineto(-394.88744528,1051.32832416) \curveto(-396.35759124,1050.99776118)(-397.54449807,1050.05342598)(-398.76512385,1049.20849449) \lineto(-398.66396702,1048.58885197) \curveto(-398.05109149,1047.7531825)(-397.24507385,1046.97256337)(-396.26992199,1046.59947335) \lineto(-396.00017044,1046.27334571) \lineto(-396.23620305,1046.11028189) \curveto(-397.67667633,1046.49954784)(-398.74219497,1047.61438257)(-399.50694062,1048.81714132) \lineto(-399.97900583,1048.88236684) \curveto(-400.02556495,1049.28154708)(-400.25374779,1049.59084653)(-399.877849,1049.89336253) \lineto(-398.93371857,1051.71967733) \lineto(-399.97900583,1051.62183904) \lineto(-398.79884279,1054.19824741) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-342.69051991,1054.06779635) \lineto(-342.58936308,1053.839507) \lineto(-342.69051991,1054.06779635) \closepath } } { \newrgbcolor{curcolor}{0.59215689 0.59215689 0.59215689} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-342.69051991,1054.06779635) \lineto(-342.58936308,1053.839507) \lineto(-342.69051991,1054.06779635) \closepath } } { \newrgbcolor{curcolor}{0.21568628 0.21568628 0.21568628} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-380.32086146,1053.54599212) \curveto(-380.16413581,1053.56745132)(-379.80037584,1053.56951245)(-379.94995308,1053.31770277) \curveto(-380.18207429,1053.2098067)(-380.7571846,1053.08902207)(-380.45573724,1052.76328578) \lineto(-380.48945618,1052.66544749) \lineto(-380.62433196,1052.40454538) \curveto(-380.99105919,1052.52671279)(-381.19323798,1053.27321896)(-380.62433196,1053.31770277) \lineto(-380.3545804,1053.44815383) \lineto(-380.32086146,1053.54599212) \closepath } } { \newrgbcolor{curcolor}{0.21568628 0.21568628 0.21568628} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-380.32086146,1053.54599212) \curveto(-380.16413581,1053.56745132)(-379.80037584,1053.56951245)(-379.94995308,1053.31770277) \curveto(-380.18207429,1053.2098067)(-380.7571846,1053.08902207)(-380.45573724,1052.76328578) \lineto(-380.48945618,1052.66544749) \lineto(-380.62433196,1052.40454538) \curveto(-380.99105919,1052.52671279)(-381.19323798,1053.27321896)(-380.62433196,1053.31770277) \lineto(-380.3545804,1053.44815383) \lineto(-380.32086146,1053.54599212) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-342.96027147,1053.28509001) \lineto(-342.85911463,1053.05680066) \lineto(-342.96027147,1053.28509001) \closepath } } { \newrgbcolor{curcolor}{0.61960787 0.61960787 0.61960787} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-342.96027147,1053.28509001) \lineto(-342.85911463,1053.05680066) \lineto(-342.96027147,1053.28509001) \closepath } } { \newrgbcolor{curcolor}{0.93725491 0.93725491 0.93725491} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-369.9354267,1052.63283473) \lineto(-368.04716583,1052.37193261) \lineto(-368.08088477,1052.27409432) \curveto(-368.47121527,1052.14406071)(-368.89378108,1051.89904753)(-369.02501521,1051.49138798) \lineto(-369.69939409,1050.44777953) \curveto(-370.24011107,1050.82843571)(-370.78096294,1051.35937151)(-371.01443291,1051.98057944) \lineto(-369.96914564,1052.53499643) \lineto(-369.9354267,1052.63283473) \closepath } } { \newrgbcolor{curcolor}{0.93725491 0.93725491 0.93725491} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-369.9354267,1052.63283473) \lineto(-368.04716583,1052.37193261) \lineto(-368.08088477,1052.27409432) \curveto(-368.47121527,1052.14406071)(-368.89378108,1051.89904753)(-369.02501521,1051.49138798) \lineto(-369.69939409,1050.44777953) \curveto(-370.24011107,1050.82843571)(-370.78096294,1051.35937151)(-371.01443291,1051.98057944) \lineto(-369.96914564,1052.53499643) \lineto(-369.9354267,1052.63283473) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-343.23002302,1052.63283473) \lineto(-343.12886619,1052.40454538) \lineto(-343.23002302,1052.63283473) \closepath } } { \newrgbcolor{curcolor}{0.57254905 0.57254905 0.57254905} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-343.23002302,1052.63283473) \lineto(-343.12886619,1052.40454538) \lineto(-343.23002302,1052.63283473) \closepath } } { \newrgbcolor{curcolor}{0.60392159 0.60392159 0.60392159} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-345.38803544,1051.98057944) \curveto(-345.40689107,1052.22647968)(-345.1337946,1051.96235543)(-345.38803544,1051.98057944) \closepath } } { \newrgbcolor{curcolor}{0.60392159 0.60392159 0.60392159} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-345.38803544,1051.98057944) \curveto(-345.40689107,1052.22647968)(-345.1337946,1051.96235543)(-345.38803544,1051.98057944) \closepath } } { \newrgbcolor{curcolor}{0.20392157 0.20392157 0.20392157} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-380.32086146,1051.58922627) \curveto(-379.96856593,1051.64466797)(-379.62247469,1051.0742055)(-380.01739096,1050.90435822) \curveto(-380.02166383,1050.4819577)(-380.45937888,1050.16900562)(-380.82664562,1050.05642635) \lineto(-380.82664562,1050.382554) \lineto(-380.45573724,1050.80651993) \lineto(-380.32086146,1051.58922627) \closepath } } { \newrgbcolor{curcolor}{0.20392157 0.20392157 0.20392157} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-380.32086146,1051.58922627) \curveto(-379.96856593,1051.64466797)(-379.62247469,1051.0742055)(-380.01739096,1050.90435822) \curveto(-380.02166383,1050.4819577)(-380.45937888,1050.16900562)(-380.82664562,1050.05642635) \lineto(-380.82664562,1050.382554) \lineto(-380.45573724,1050.80651993) \lineto(-380.32086146,1051.58922627) \closepath } } { \newrgbcolor{curcolor}{0.89411765 0.89411765 0.89411765} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-366.96815962,1051.1978731) \lineto(-366.46237546,1051.16526034) \lineto(-366.46237546,1050.44777953) \lineto(-367.06931645,1050.44777953) \lineto(-366.96815962,1051.1978731) \closepath } } { \newrgbcolor{curcolor}{0.89411765 0.89411765 0.89411765} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-366.96815962,1051.1978731) \lineto(-366.46237546,1051.16526034) \lineto(-366.46237546,1050.44777953) \lineto(-367.06931645,1050.44777953) \lineto(-366.96815962,1051.1978731) \closepath } } { \newrgbcolor{curcolor}{0.98431373 0.98431373 0.98431373} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-392.32480554,1051.06742204) \lineto(-391.54926982,1051.03480928) \curveto(-391.44981243,1050.68350458)(-391.23446976,1050.29293412)(-391.6841456,1050.05642635) \lineto(-392.42596237,1050.18687741) \lineto(-392.32480554,1051.06742204) \closepath } } { \newrgbcolor{curcolor}{0.98431373 0.98431373 0.98431373} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-392.32480554,1051.06742204) \lineto(-391.54926982,1051.03480928) \curveto(-391.44981243,1050.68350458)(-391.23446976,1050.29293412)(-391.6841456,1050.05642635) \lineto(-392.42596237,1050.18687741) \lineto(-392.32480554,1051.06742204) \closepath } } { \newrgbcolor{curcolor}{0.23921569 0.23921569 0.23921569} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-388.0087807,1049.76291148) \lineto(-387.63787232,1049.73029871) \lineto(-387.60415337,1048.98020514) \lineto(-387.4692776,1048.71930302) \curveto(-387.37062945,1047.70191523)(-387.60995303,1046.5185937)(-388.68315958,1046.11028189) \lineto(-388.78431641,1046.14289465) \lineto(-388.78431641,1046.4690223) \curveto(-388.38859089,1046.69678984)(-387.94080331,1047.03348402)(-388.0087807,1047.54524351) \curveto(-387.79203533,1048.03834851)(-387.79203533,1048.74800226)(-388.0087807,1049.24110725) \lineto(-388.0087807,1049.76291148) \closepath } } { \newrgbcolor{curcolor}{0.23921569 0.23921569 0.23921569} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-388.0087807,1049.76291148) \lineto(-387.63787232,1049.73029871) \lineto(-387.60415337,1048.98020514) \lineto(-387.4692776,1048.71930302) \curveto(-387.37062945,1047.70191523)(-387.60995303,1046.5185937)(-388.68315958,1046.11028189) \lineto(-388.78431641,1046.14289465) \lineto(-388.78431641,1046.4690223) \curveto(-388.38859089,1046.69678984)(-387.94080331,1047.03348402)(-388.0087807,1047.54524351) \curveto(-387.79203533,1048.03834851)(-387.79203533,1048.74800226)(-388.0087807,1049.24110725) \lineto(-388.0087807,1049.76291148) \closepath } } { \newrgbcolor{curcolor}{0.14509805 0.14509805 0.14509805} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.29430856,1049.11065619) \lineto(-435.92340018,1048.94759237) \lineto(-435.88968123,1045.84937978) \lineto(-436.15943279,1045.45802661) \lineto(-436.42918434,1045.84937978) \lineto(-436.29430856,1046.11028189) \lineto(-436.29430856,1049.11065619) \closepath } } { \newrgbcolor{curcolor}{0.14509805 0.14509805 0.14509805} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.29430856,1049.11065619) \lineto(-435.92340018,1048.94759237) \lineto(-435.88968123,1045.84937978) \lineto(-436.15943279,1045.45802661) \lineto(-436.42918434,1045.84937978) \lineto(-436.29430856,1046.11028189) \lineto(-436.29430856,1049.11065619) \closepath } } { \newrgbcolor{curcolor}{0.18431373 0.18431373 0.18431373} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-397.31520925,1048.71930302) \lineto(-397.07917665,1048.5562392) \lineto(-397.01173876,1048.23011156) \curveto(-396.16363988,1047.21376738)(-394.94813938,1046.72601088)(-393.6735633,1046.63208612) \lineto(-393.40381175,1046.50163506) \lineto(-390.30166889,1046.371184) \lineto(-389.89704157,1046.50163506) \lineto(-389.66100896,1046.33857124) \lineto(-390.06563629,1045.88199254) \lineto(-390.841172,1045.84937978) \lineto(-395.12347789,1046.27334571) \lineto(-395.32579156,1046.59947335) \curveto(-396.15500783,1046.91946979)(-396.95374217,1047.46514656)(-397.41636609,1048.23011156) \lineto(-397.31520925,1048.71930302) \closepath } } { \newrgbcolor{curcolor}{0.18431373 0.18431373 0.18431373} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-397.31520925,1048.71930302) \lineto(-397.07917665,1048.5562392) \lineto(-397.01173876,1048.23011156) \curveto(-396.16363988,1047.21376738)(-394.94813938,1046.72601088)(-393.6735633,1046.63208612) \lineto(-393.40381175,1046.50163506) \lineto(-390.30166889,1046.371184) \lineto(-389.89704157,1046.50163506) \lineto(-389.66100896,1046.33857124) \lineto(-390.06563629,1045.88199254) \lineto(-390.841172,1045.84937978) \lineto(-395.12347789,1046.27334571) \lineto(-395.32579156,1046.59947335) \curveto(-396.15500783,1046.91946979)(-396.95374217,1047.46514656)(-397.41636609,1048.23011156) \lineto(-397.31520925,1048.71930302) \closepath } } { \newrgbcolor{curcolor}{0.63137257 0.63137257 0.63137257} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-442.90322159,1047.02343929) \lineto(-442.76834582,1046.89298823) \lineto(-443.61131942,1045.62109043) \lineto(-443.67875731,1045.62109043) \lineto(-443.84735203,1045.84937978) \lineto(-442.90322159,1047.02343929) \closepath } } { \newrgbcolor{curcolor}{0.63137257 0.63137257 0.63137257} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-442.90322159,1047.02343929) \lineto(-442.76834582,1046.89298823) \lineto(-443.61131942,1045.62109043) \lineto(-443.67875731,1045.62109043) \lineto(-443.84735203,1045.84937978) \lineto(-442.90322159,1047.02343929) \closepath } } { \newrgbcolor{curcolor}{0.24705882 0.24705882 0.24705882} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-385.71589251,1046.63208612) \lineto(-385.34498412,1046.59947335) \lineto(-385.34498412,1046.40379677) \curveto(-385.93479589,1045.5313401)(-386.41967431,1044.52921508)(-387.33440182,1043.89261392) \lineto(-387.57043443,1044.05567775) \lineto(-385.74961145,1046.40379677) \lineto(-385.71589251,1046.63208612) \closepath } } { \newrgbcolor{curcolor}{0.24705882 0.24705882 0.24705882} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-385.71589251,1046.63208612) \lineto(-385.34498412,1046.59947335) \lineto(-385.34498412,1046.40379677) \curveto(-385.93479589,1045.5313401)(-386.41967431,1044.52921508)(-387.33440182,1043.89261392) \lineto(-387.57043443,1044.05567775) \lineto(-385.74961145,1046.40379677) \lineto(-385.71589251,1046.63208612) \closepath } } { \newrgbcolor{curcolor}{0.96470588 0.96470588 0.96470588} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-367.1030354,1046.371184) \lineto(-365.61940186,1045.58847766) \lineto(-363.49510839,1045.81676701) \lineto(-361.84288013,1039.84863117) \lineto(-361.4382528,1039.19637588) \lineto(-361.33709597,1035.31545695) \lineto(-361.53940963,1035.445908) \lineto(-362.61841584,1037.79402702) \lineto(-365.78799658,1044.25135433) \lineto(-366.52981335,1045.0992862) \lineto(-367.1030354,1046.371184) \closepath } } { \newrgbcolor{curcolor}{0.96470588 0.96470588 0.96470588} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-367.1030354,1046.371184) \lineto(-365.61940186,1045.58847766) \lineto(-363.49510839,1045.81676701) \lineto(-361.84288013,1039.84863117) \lineto(-361.4382528,1039.19637588) \lineto(-361.33709597,1035.31545695) \lineto(-361.53940963,1035.445908) \lineto(-362.61841584,1037.79402702) \lineto(-365.78799658,1044.25135433) \lineto(-366.52981335,1045.0992862) \lineto(-367.1030354,1046.371184) \closepath } } { \newrgbcolor{curcolor}{0.12941177 0.12941177 0.12941177} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-408.3750229,1044.02306498) \lineto(-408.10527135,1043.76216287) \lineto(-408.64477445,1042.58810336) \lineto(-408.10527135,1041.5444949) \curveto(-408.16855506,1041.04617187)(-408.7742552,1040.53336876)(-408.24014712,1040.10953328) \lineto(-408.24014712,1039.84863117) \lineto(-408.00411451,1036.88086963) \lineto(-408.10527135,1036.84825686) \lineto(-408.20642818,1036.88086963) \curveto(-408.30161001,1037.5752606)(-408.39201725,1038.284523)(-408.914526,1038.80502271) \lineto(-409.15055861,1039.62034182) \lineto(-409.45402911,1040.63133751) \lineto(-409.35287228,1040.85962686) \lineto(-409.85865644,1040.76178856) \lineto(-408.3750229,1044.02306498) \closepath } } { \newrgbcolor{curcolor}{0.12941177 0.12941177 0.12941177} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-408.3750229,1044.02306498) \lineto(-408.10527135,1043.76216287) \lineto(-408.64477445,1042.58810336) \lineto(-408.10527135,1041.5444949) \curveto(-408.16855506,1041.04617187)(-408.7742552,1040.53336876)(-408.24014712,1040.10953328) \lineto(-408.24014712,1039.84863117) \lineto(-408.00411451,1036.88086963) \lineto(-408.10527135,1036.84825686) \lineto(-408.20642818,1036.88086963) \curveto(-408.30161001,1037.5752606)(-408.39201725,1038.284523)(-408.914526,1038.80502271) \lineto(-409.15055861,1039.62034182) \lineto(-409.45402911,1040.63133751) \lineto(-409.35287228,1040.85962686) \lineto(-409.85865644,1040.76178856) \lineto(-408.3750229,1044.02306498) \closepath } } { \newrgbcolor{curcolor}{0.17647059 0.17647059 0.17647059} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-407.29601669,1037.50051215) \lineto(-407.19485986,1037.46789938) \lineto(-407.16114091,1037.10915898) \lineto(-407.16114091,1036.45690369) \curveto(-407.18892532,1036.05198361)(-407.57237715,1035.49704482)(-408.0715524,1035.70681012) \lineto(-407.29601669,1037.50051215) \closepath } } { \newrgbcolor{curcolor}{0.17647059 0.17647059 0.17647059} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-407.29601669,1037.50051215) \lineto(-407.19485986,1037.46789938) \lineto(-407.16114091,1037.10915898) \lineto(-407.16114091,1036.45690369) \curveto(-407.18892532,1036.05198361)(-407.57237715,1035.49704482)(-408.0715524,1035.70681012) \lineto(-407.29601669,1037.50051215) \closepath } } { \newrgbcolor{curcolor}{0.10588235 0.10588235 0.10588235} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-381.26499189,1036.84825686) \lineto(-379.24185525,1036.84825686) \lineto(-378.70235215,1036.58735475) \curveto(-376.41620774,1036.18256512)(-374.31214563,1034.92019024)(-372.4643475,1033.48914215) \curveto(-371.29578377,1032.86141167)(-369.92193912,1032.75744217)(-369.0924531,1031.5323763) \lineto(-368.62038788,1031.59760183) \lineto(-367.40650589,1030.81489549) \lineto(-365.45080714,1029.05380622) \curveto(-364.91508056,1028.93856576)(-364.31636699,1028.3470224)(-364.16948727,1027.87974671) \lineto(-365.72055869,1028.27109988) \lineto(-367.40650589,1029.90173809) \lineto(-368.21576055,1029.70606151) \lineto(-368.89013943,1030.1626402) \lineto(-369.12617204,1030.06480191) \lineto(-370.1714593,1030.88012102) \curveto(-370.3958926,1031.25803773)(-370.6319252,1031.14050133)(-370.98071396,1031.14102313) \curveto(-372.72465775,1033.35477756)(-375.23739346,1034.88888199)(-377.89309749,1035.80464841) \curveto(-379.7287568,1035.9645814)(-381.80314624,1036.16273656)(-383.52416114,1035.51113353) \curveto(-386.25000058,1034.14791999)(-388.23132573,1030.35831679)(-386.15423878,1027.81452118) \lineto(-385.68217356,1026.83613826) \curveto(-385.49874251,1026.73543004)(-385.28671779,1026.36351408)(-385.58101673,1026.28172127) \curveto(-386.25512586,1026.87162095)(-386.66568772,1027.77147234)(-386.96349344,1028.59722752) \lineto(-387.73902915,1030.06480191) \curveto(-387.85260804,1032.9516838)(-385.51627636,1035.71855071)(-382.6474686,1036.3590654) \lineto(-381.26499189,1036.84825686) \closepath } } { \newrgbcolor{curcolor}{0.10588235 0.10588235 0.10588235} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-381.26499189,1036.84825686) \lineto(-379.24185525,1036.84825686) \lineto(-378.70235215,1036.58735475) \curveto(-376.41620774,1036.18256512)(-374.31214563,1034.92019024)(-372.4643475,1033.48914215) \curveto(-371.29578377,1032.86141167)(-369.92193912,1032.75744217)(-369.0924531,1031.5323763) \lineto(-368.62038788,1031.59760183) \lineto(-367.40650589,1030.81489549) \lineto(-365.45080714,1029.05380622) \curveto(-364.91508056,1028.93856576)(-364.31636699,1028.3470224)(-364.16948727,1027.87974671) \lineto(-365.72055869,1028.27109988) \lineto(-367.40650589,1029.90173809) \lineto(-368.21576055,1029.70606151) \lineto(-368.89013943,1030.1626402) \lineto(-369.12617204,1030.06480191) \lineto(-370.1714593,1030.88012102) \curveto(-370.3958926,1031.25803773)(-370.6319252,1031.14050133)(-370.98071396,1031.14102313) \curveto(-372.72465775,1033.35477756)(-375.23739346,1034.88888199)(-377.89309749,1035.80464841) \curveto(-379.7287568,1035.9645814)(-381.80314624,1036.16273656)(-383.52416114,1035.51113353) \curveto(-386.25000058,1034.14791999)(-388.23132573,1030.35831679)(-386.15423878,1027.81452118) \lineto(-385.68217356,1026.83613826) \curveto(-385.49874251,1026.73543004)(-385.28671779,1026.36351408)(-385.58101673,1026.28172127) \curveto(-386.25512586,1026.87162095)(-386.66568772,1027.77147234)(-386.96349344,1028.59722752) \lineto(-387.73902915,1030.06480191) \curveto(-387.85260804,1032.9516838)(-385.51627636,1035.71855071)(-382.6474686,1036.3590654) \lineto(-381.26499189,1036.84825686) \closepath } } { \newrgbcolor{curcolor}{0.23137255 0.23137255 0.23137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-406.0821347,1035.93509946) \lineto(-405.8461021,1035.77203564) \lineto(-406.11585365,1035.05455483) \lineto(-406.79023253,1034.14139743) \lineto(-406.99254619,1034.14139743) \lineto(-407.02626514,1034.23923573) \lineto(-406.3856052,1035.18500589) \lineto(-406.0821347,1035.93509946) \closepath } } { \newrgbcolor{curcolor}{0.23137255 0.23137255 0.23137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-406.0821347,1035.93509946) \lineto(-405.8461021,1035.77203564) \lineto(-406.11585365,1035.05455483) \lineto(-406.79023253,1034.14139743) \lineto(-406.99254619,1034.14139743) \lineto(-407.02626514,1034.23923573) \lineto(-406.3856052,1035.18500589) \lineto(-406.0821347,1035.93509946) \closepath } } { \newrgbcolor{curcolor}{0.84313726 0.84313726 0.84313726} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-416.73732102,1034.36968678) \lineto(-416.63616419,1034.01094638) \lineto(-417.17566729,1033.61959321) \curveto(-417.42559211,1033.61222794)(-417.69156714,1033.50989691)(-417.7151704,1033.22824004) \lineto(-418.72673872,1032.51075923) \lineto(-418.89533344,1032.41292093) \lineto(-419.13136605,1032.57598475) \lineto(-417.78260829,1033.81526979) \curveto(-417.35518695,1033.50636169)(-416.95838242,1034.05947417)(-416.73732102,1034.36968678) \closepath } } { \newrgbcolor{curcolor}{0.84313726 0.84313726 0.84313726} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-416.73732102,1034.36968678) \lineto(-416.63616419,1034.01094638) \lineto(-417.17566729,1033.61959321) \curveto(-417.42559211,1033.61222794)(-417.69156714,1033.50989691)(-417.7151704,1033.22824004) \lineto(-418.72673872,1032.51075923) \lineto(-418.89533344,1032.41292093) \lineto(-419.13136605,1032.57598475) \lineto(-417.78260829,1033.81526979) \curveto(-417.35518695,1033.50636169)(-416.95838242,1034.05947417)(-416.73732102,1034.36968678) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-382.88350121,1033.06517622) \curveto(-381.78170099,1033.16418857)(-380.74572015,1032.81392748)(-379.94995308,1032.11940606) \lineto(-379.88251519,1031.79327841) \lineto(-379.64648258,1031.49976354) \lineto(-379.8150773,1031.27147419) \lineto(-380.28714252,1031.40192524) \curveto(-380.68071003,1032.51636862)(-382.20642481,1032.40809424)(-383.11953382,1031.988955) \lineto(-384.46829158,1029.24948281) \lineto(-384.77176207,1028.36893817) \lineto(-385.14267046,1028.40155094) \lineto(-385.58101673,1029.67344874) \lineto(-385.58101673,1030.58660614) \curveto(-385.4590081,1031.82732614)(-384.28904167,1032.83166883)(-383.01837698,1032.93472516) \lineto(-382.88350121,1033.06517622) \closepath } } { \newrgbcolor{curcolor}{0.0627451 0.0627451 0.0627451} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-382.88350121,1033.06517622) \curveto(-381.78170099,1033.16418857)(-380.74572015,1032.81392748)(-379.94995308,1032.11940606) \lineto(-379.88251519,1031.79327841) \lineto(-379.64648258,1031.49976354) \lineto(-379.8150773,1031.27147419) \lineto(-380.28714252,1031.40192524) \curveto(-380.68071003,1032.51636862)(-382.20642481,1032.40809424)(-383.11953382,1031.988955) \lineto(-384.46829158,1029.24948281) \lineto(-384.77176207,1028.36893817) \lineto(-385.14267046,1028.40155094) \lineto(-385.58101673,1029.67344874) \lineto(-385.58101673,1030.58660614) \curveto(-385.4590081,1031.82732614)(-384.28904167,1032.83166883)(-383.01837698,1032.93472516) \lineto(-382.88350121,1033.06517622) \closepath } } { \newrgbcolor{curcolor}{0.18431373 0.18431373 0.18431373} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-421.18822163,1032.41292093) \curveto(-421.01288312,1032.39938011)(-420.53245561,1032.50376705)(-420.68243747,1032.18463158) \lineto(-421.32309741,1031.76066565) \curveto(-421.68645275,1031.90364001)(-421.28020691,1032.23028945)(-421.18822163,1032.41292093) \closepath } } { \newrgbcolor{curcolor}{0.18431373 0.18431373 0.18431373} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-421.18822163,1032.41292093) \curveto(-421.01288312,1032.39938011)(-420.53245561,1032.50376705)(-420.68243747,1032.18463158) \lineto(-421.32309741,1031.76066565) \curveto(-421.68645275,1031.90364001)(-421.28020691,1032.23028945)(-421.18822163,1032.41292093) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-420.10921542,1031.76066565) \curveto(-420.12805757,1032.00656589)(-419.85497459,1031.74244164)(-420.10921542,1031.76066565) \closepath } } { \newrgbcolor{curcolor}{0.58823532 0.58823532 0.58823532} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-420.10921542,1031.76066565) \curveto(-420.12805757,1032.00656589)(-419.85497459,1031.74244164)(-420.10921542,1031.76066565) \closepath } } { \newrgbcolor{curcolor}{0.6156863 0.6156863 0.6156863} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-420.10921542,1031.76066565) \lineto(-420.2440912,1031.63021459) \lineto(-420.10921542,1031.76066565) \closepath } } { \newrgbcolor{curcolor}{0.6156863 0.6156863 0.6156863} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-420.10921542,1031.76066565) \lineto(-420.2440912,1031.63021459) \lineto(-420.10921542,1031.76066565) \closepath } } { \newrgbcolor{curcolor}{0.65098041 0.65098041 0.65098041} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-420.2440912,1031.63021459) \lineto(-420.37896698,1031.49976354) \lineto(-420.2440912,1031.63021459) \closepath } } { \newrgbcolor{curcolor}{0.65098041 0.65098041 0.65098041} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-420.2440912,1031.63021459) \lineto(-420.37896698,1031.49976354) \lineto(-420.2440912,1031.63021459) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-420.37896698,1031.49976354) \curveto(-420.36012483,1031.25386329)(-420.63320781,1031.51798755)(-420.37896698,1031.49976354) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-420.37896698,1031.49976354) \curveto(-420.36012483,1031.25386329)(-420.63320781,1031.51798755)(-420.37896698,1031.49976354) \closepath } } { \newrgbcolor{curcolor}{0.61176473 0.61176473 0.61176473} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-421.32309741,1030.7170572) \curveto(-421.34193955,1030.96295744)(-421.06885657,1030.69882014)(-421.32309741,1030.7170572) \closepath } } { \newrgbcolor{curcolor}{0.61176473 0.61176473 0.61176473} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-421.32309741,1030.7170572) \curveto(-421.34193955,1030.96295744)(-421.06885657,1030.69882014)(-421.32309741,1030.7170572) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-378.70235215,1029.8038998) \curveto(-376.48364563,1029.9704858)(-375.67843724,1027.61232205)(-375.06070619,1026.02081915) \lineto(-374.92583041,1023.80315119) \lineto(-375.56649035,1022.13990022) \lineto(-375.46533352,1022.88999379) \lineto(-375.19558197,1023.54224908) \lineto(-375.33045774,1025.36856387) \lineto(-376.78037234,1028.27109988) \lineto(-376.84781022,1028.59722752) \lineto(-377.5221891,1029.11903175) \lineto(-378.6686332,1029.11903175) \curveto(-378.72197657,1028.81090636)(-378.79413511,1028.39959417)(-378.46631954,1028.20587435) \lineto(-376.81409128,1026.80352549) \curveto(-376.98012336,1025.86493014)(-378.33144376,1026.11526572)(-379.00582264,1026.2491085) \curveto(-379.99810373,1026.46852718)(-381.23801674,1027.11034638)(-381.26499189,1028.23848712) \curveto(-381.00683966,1029.25587491)(-379.86767885,1029.78302763)(-378.83722792,1029.67344874) \lineto(-378.70235215,1029.8038998) \closepath } } { \newrgbcolor{curcolor}{0.07450981 0.07450981 0.07450981} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-378.70235215,1029.8038998) \curveto(-376.48364563,1029.9704858)(-375.67843724,1027.61232205)(-375.06070619,1026.02081915) \lineto(-374.92583041,1023.80315119) \lineto(-375.56649035,1022.13990022) \lineto(-375.46533352,1022.88999379) \lineto(-375.19558197,1023.54224908) \lineto(-375.33045774,1025.36856387) \lineto(-376.78037234,1028.27109988) \lineto(-376.84781022,1028.59722752) \lineto(-377.5221891,1029.11903175) \lineto(-378.6686332,1029.11903175) \curveto(-378.72197657,1028.81090636)(-378.79413511,1028.39959417)(-378.46631954,1028.20587435) \lineto(-376.81409128,1026.80352549) \curveto(-376.98012336,1025.86493014)(-378.33144376,1026.11526572)(-379.00582264,1026.2491085) \curveto(-379.99810373,1026.46852718)(-381.23801674,1027.11034638)(-381.26499189,1028.23848712) \curveto(-381.00683966,1029.25587491)(-379.86767885,1029.78302763)(-378.83722792,1029.67344874) \lineto(-378.70235215,1029.8038998) \closepath } } { \newrgbcolor{curcolor}{0.93725491 0.93725491 0.93725491} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-427.39250734,1029.41254663) \lineto(-426.7518474,1029.24948281) \lineto(-426.88672318,1029.05380622) \lineto(-427.8982915,1028.33632541) \lineto(-429.31448715,1026.7056872) \lineto(-429.82027131,1026.67307444) \lineto(-430.39349335,1027.1622659) \lineto(-430.7306828,1027.94497224) \lineto(-429.31448715,1028.79290411) \curveto(-428.80573572,1029.18164826)(-428.20432463,1029.36271433)(-427.52738311,1029.28209557) \lineto(-427.39250734,1029.41254663) \closepath } } { \newrgbcolor{curcolor}{0.93725491 0.93725491 0.93725491} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-427.39250734,1029.41254663) \lineto(-426.7518474,1029.24948281) \lineto(-426.88672318,1029.05380622) \lineto(-427.8982915,1028.33632541) \lineto(-429.31448715,1026.7056872) \lineto(-429.82027131,1026.67307444) \lineto(-430.39349335,1027.1622659) \lineto(-430.7306828,1027.94497224) \lineto(-429.31448715,1028.79290411) \curveto(-428.80573572,1029.18164826)(-428.20432463,1029.36271433)(-427.52738311,1029.28209557) \lineto(-427.39250734,1029.41254663) \closepath } } { \newrgbcolor{curcolor}{0.16862746 0.16862746 0.16862746} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-375.19558197,1028.23848712) \curveto(-374.42989219,1028.00667559)(-374.00786588,1027.14074148)(-373.81310526,1026.44478509) \lineto(-373.34104004,1026.51001062) \lineto(-373.17244532,1026.15127021) \lineto(-373.17244532,1025.75991704) \lineto(-371.82368756,1022.49864062) \lineto(-371.82368756,1022.10728745) \lineto(-371.55393601,1020.93322794) \lineto(-371.72253073,1020.70493859) \lineto(-371.92484439,1020.83538965) \lineto(-372.09343911,1021.45503217) \lineto(-372.93641272,1024.42279371) \lineto(-373.03756955,1024.45540647) \lineto(-373.67822948,1023.83576395) \lineto(-374.75723569,1027.22749143) \lineto(-375.16186302,1027.87974671) \lineto(-375.19558197,1028.23848712) \closepath } } { \newrgbcolor{curcolor}{0.16862746 0.16862746 0.16862746} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-375.19558197,1028.23848712) \curveto(-374.42989219,1028.00667559)(-374.00786588,1027.14074148)(-373.81310526,1026.44478509) \lineto(-373.34104004,1026.51001062) \lineto(-373.17244532,1026.15127021) \lineto(-373.17244532,1025.75991704) \lineto(-371.82368756,1022.49864062) \lineto(-371.82368756,1022.10728745) \lineto(-371.55393601,1020.93322794) \lineto(-371.72253073,1020.70493859) \lineto(-371.92484439,1020.83538965) \lineto(-372.09343911,1021.45503217) \lineto(-372.93641272,1024.42279371) \lineto(-373.03756955,1024.45540647) \lineto(-373.67822948,1023.83576395) \lineto(-374.75723569,1027.22749143) \lineto(-375.16186302,1027.87974671) \lineto(-375.19558197,1028.23848712) \closepath } } { \newrgbcolor{curcolor}{0.8509804 0.8509804 0.8509804} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-432.51778683,1027.45578078) \lineto(-432.14687844,1027.42316801) \curveto(-432.12095532,1026.69525112)(-433.07212627,1026.61189289)(-433.59679304,1026.41217232) \lineto(-433.83282565,1026.44478509) \lineto(-433.29332254,1027.03181484) \lineto(-432.55150577,1027.35794249) \lineto(-432.51778683,1027.45578078) \closepath } } { \newrgbcolor{curcolor}{0.8509804 0.8509804 0.8509804} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-432.51778683,1027.45578078) \lineto(-432.14687844,1027.42316801) \curveto(-432.12095532,1026.69525112)(-433.07212627,1026.61189289)(-433.59679304,1026.41217232) \lineto(-433.83282565,1026.44478509) \lineto(-433.29332254,1027.03181484) \lineto(-432.55150577,1027.35794249) \lineto(-432.51778683,1027.45578078) \closepath } } { \newrgbcolor{curcolor}{0.1254902 0.1254902 0.1254902} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-397.45008503,1026.93397655) \lineto(-396.00017044,1026.90136379) \lineto(-396.00017044,1026.7056872) \curveto(-397.17817547,1026.81461383)(-397.96261298,1025.88958539)(-398.79884279,1025.23811281) \lineto(-399.06859434,1025.75991704) \lineto(-398.69768596,1026.18388297) \lineto(-397.45008503,1026.93397655) \closepath } } { \newrgbcolor{curcolor}{0.1254902 0.1254902 0.1254902} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-397.45008503,1026.93397655) \lineto(-396.00017044,1026.90136379) \lineto(-396.00017044,1026.7056872) \curveto(-397.17817547,1026.81461383)(-397.96261298,1025.88958539)(-398.79884279,1025.23811281) \lineto(-399.06859434,1025.75991704) \lineto(-398.69768596,1026.18388297) \lineto(-397.45008503,1026.93397655) \closepath } } { \newrgbcolor{curcolor}{0.91764706 0.91764706 0.91764706} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-436.15943279,1025.75991704) \lineto(-434.67579925,1025.75991704) \lineto(-433.90026353,1025.59685322) \lineto(-435.61992968,1024.45540647) \lineto(-436.02455701,1024.45540647) \lineto(-436.19315173,1024.35756818) \lineto(-436.39546539,1024.42279371) \lineto(-436.56406011,1024.32495542) \lineto(-436.83381167,1024.45540647) \lineto(-437.33959583,1024.48801924) \lineto(-437.33959583,1024.68369582) \lineto(-436.19315173,1025.66207875) \lineto(-436.15943279,1025.75991704) \closepath } } { \newrgbcolor{curcolor}{0.91764706 0.91764706 0.91764706} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-436.15943279,1025.75991704) \lineto(-434.67579925,1025.75991704) \lineto(-433.90026353,1025.59685322) \lineto(-435.61992968,1024.45540647) \lineto(-436.02455701,1024.45540647) \lineto(-436.19315173,1024.35756818) \lineto(-436.39546539,1024.42279371) \lineto(-436.56406011,1024.32495542) \lineto(-436.83381167,1024.45540647) \lineto(-437.33959583,1024.48801924) \lineto(-437.33959583,1024.68369582) \lineto(-436.19315173,1025.66207875) \lineto(-436.15943279,1025.75991704) \closepath } } { \newrgbcolor{curcolor}{0.93333334 0.93333334 0.93333334} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-417.68145145,1024.19450436) \lineto(-417.58029462,1024.1618916) \lineto(-417.68145145,1023.15089591) \curveto(-417.60350674,1022.53908045)(-417.89455518,1021.79811845)(-417.4116999,1021.32458111) \lineto(-417.31054307,1020.83538965) \curveto(-417.87648183,1020.89208368)(-418.36230437,1021.359542)(-418.62558189,1021.84638534) \curveto(-418.71689279,1022.61422026)(-418.35421182,1023.28526049)(-417.85004617,1023.83576395) \lineto(-417.68145145,1024.19450436) \closepath } } { \newrgbcolor{curcolor}{0.93333334 0.93333334 0.93333334} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-417.68145145,1024.19450436) \lineto(-417.58029462,1024.1618916) \lineto(-417.68145145,1023.15089591) \curveto(-417.60350674,1022.53908045)(-417.89455518,1021.79811845)(-417.4116999,1021.32458111) \lineto(-417.31054307,1020.83538965) \curveto(-417.87648183,1020.89208368)(-418.36230437,1021.359542)(-418.62558189,1021.84638534) \curveto(-418.71689279,1022.61422026)(-418.35421182,1023.28526049)(-417.85004617,1023.83576395) \lineto(-417.68145145,1024.19450436) \closepath } } { \newrgbcolor{curcolor}{0.71764708 0.71764708 0.71764708} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-354.28983666,1022.36818957) \curveto(-354.3086923,1022.61408981)(-354.03559583,1022.34996555)(-354.28983666,1022.36818957) \closepath } } { \newrgbcolor{curcolor}{0.71764708 0.71764708 0.71764708} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-354.28983666,1022.36818957) \curveto(-354.3086923,1022.61408981)(-354.03559583,1022.34996555)(-354.28983666,1022.36818957) \closepath } } { \newrgbcolor{curcolor}{0.71764708 0.71764708 0.71764708} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-354.28983666,1022.36818957) \lineto(-354.55958822,1022.23773851) \lineto(-354.28983666,1022.36818957) \closepath } } { \newrgbcolor{curcolor}{0.71764708 0.71764708 0.71764708} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-354.28983666,1022.36818957) \lineto(-354.55958822,1022.23773851) \lineto(-354.28983666,1022.36818957) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-354.55958822,1022.23773851) \curveto(-354.54073258,1021.99183827)(-354.81382905,1022.25596252)(-354.55958822,1022.23773851) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-354.55958822,1022.23773851) \curveto(-354.54073258,1021.99183827)(-354.81382905,1022.25596252)(-354.55958822,1022.23773851) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-355.63859442,1021.58548323) \curveto(-355.38435359,1021.60372028)(-355.65743657,1021.33958298)(-355.63859442,1021.58548323) \closepath } } { \newrgbcolor{curcolor}{0.60000002 0.60000002 0.60000002} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-355.63859442,1021.58548323) \curveto(-355.38435359,1021.60372028)(-355.65743657,1021.33958298)(-355.63859442,1021.58548323) \closepath } } { \newrgbcolor{curcolor}{0.80392158 0.80392158 0.80392158} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-356.17809753,1021.19413006) \lineto(-356.0769407,1020.83538965) \lineto(-357.08850902,1020.44403648) \lineto(-356.17809753,1021.19413006) \closepath } } { \newrgbcolor{curcolor}{0.80392158 0.80392158 0.80392158} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-356.17809753,1021.19413006) \lineto(-356.0769407,1020.83538965) \lineto(-357.08850902,1020.44403648) \lineto(-356.17809753,1021.19413006) \closepath } } { \newrgbcolor{curcolor}{0.94509804 0.94509804 0.94509804} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-414.84906015,1018.45465786) \lineto(-414.5793086,1018.19375575) \lineto(-414.84906015,1017.1501473) \lineto(-414.20840022,1015.81302397) \curveto(-413.9412113,1015.30778702)(-413.55209469,1014.75910988)(-412.99451823,1014.5085134) \lineto(-412.99451823,1014.31283681) \lineto(-413.77005394,1014.28022405) \lineto(-414.0398055,1014.14977299) \lineto(-414.44443283,1014.28022405) \curveto(-415.32328338,1014.33410034)(-415.97257537,1015.23538669)(-416.19781792,1015.97608779) \lineto(-415.28740643,1017.70456429) \lineto(-415.01765487,1017.9654664) \lineto(-414.84906015,1018.45465786) \closepath } } { \newrgbcolor{curcolor}{0.94509804 0.94509804 0.94509804} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-414.84906015,1018.45465786) \lineto(-414.5793086,1018.19375575) \lineto(-414.84906015,1017.1501473) \lineto(-414.20840022,1015.81302397) \curveto(-413.9412113,1015.30778702)(-413.55209469,1014.75910988)(-412.99451823,1014.5085134) \lineto(-412.99451823,1014.31283681) \lineto(-413.77005394,1014.28022405) \lineto(-414.0398055,1014.14977299) \lineto(-414.44443283,1014.28022405) \curveto(-415.32328338,1014.33410034)(-415.97257537,1015.23538669)(-416.19781792,1015.97608779) \lineto(-415.28740643,1017.70456429) \lineto(-415.01765487,1017.9654664) \lineto(-414.84906015,1018.45465786) \closepath } } { \newrgbcolor{curcolor}{0.56862748 0.56862748 0.56862748} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-361.84288013,1018.32420681) \curveto(-361.86172227,1018.57010705)(-361.58863929,1018.30596975)(-361.84288013,1018.32420681) \closepath } } { \newrgbcolor{curcolor}{0.56862748 0.56862748 0.56862748} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-361.84288013,1018.32420681) \curveto(-361.86172227,1018.57010705)(-361.58863929,1018.30596975)(-361.84288013,1018.32420681) \closepath } } { \newrgbcolor{curcolor}{0.62352943 0.62352943 0.62352943} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-361.84288013,1018.32420681) \lineto(-361.9777559,1018.19375575) \lineto(-361.84288013,1018.32420681) \closepath } } { \newrgbcolor{curcolor}{0.62352943 0.62352943 0.62352943} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-361.84288013,1018.32420681) \lineto(-361.9777559,1018.19375575) \lineto(-361.84288013,1018.32420681) \closepath } } { \newrgbcolor{curcolor}{0.95686275 0.95686275 0.95686275} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-411.34228997,1013.2366156) \lineto(-410.56675426,1013.07355177) \lineto(-410.49931637,1012.87787519) \lineto(-409.42031016,1011.83426674) \lineto(-409.2179965,1011.76904121) \lineto(-408.61105551,1011.0515604) \lineto(-407.80180085,1010.66020722) \curveto(-407.32353135,1010.63805664)(-407.00927079,1010.16762403)(-406.79023253,1009.81227536) \curveto(-406.6066666,1008.7926699)(-407.75257119,1008.44906181)(-408.3750229,1007.88812227) \lineto(-408.47617973,1007.98596056) \curveto(-407.59962206,1009.40918159)(-409.43555113,1010.78804926)(-410.80278687,1010.75804552) \lineto(-411.7469173,1010.88849657) \lineto(-412.11782569,1011.0515604) \curveto(-412.83023954,1011.78039045)(-411.95030997,1012.77612336)(-411.34228997,1013.2366156) \closepath } } { \newrgbcolor{curcolor}{0.95686275 0.95686275 0.95686275} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-411.34228997,1013.2366156) \lineto(-410.56675426,1013.07355177) \lineto(-410.49931637,1012.87787519) \lineto(-409.42031016,1011.83426674) \lineto(-409.2179965,1011.76904121) \lineto(-408.61105551,1011.0515604) \lineto(-407.80180085,1010.66020722) \curveto(-407.32353135,1010.63805664)(-407.00927079,1010.16762403)(-406.79023253,1009.81227536) \curveto(-406.6066666,1008.7926699)(-407.75257119,1008.44906181)(-408.3750229,1007.88812227) \lineto(-408.47617973,1007.98596056) \curveto(-407.59962206,1009.40918159)(-409.43555113,1010.78804926)(-410.80278687,1010.75804552) \lineto(-411.7469173,1010.88849657) \lineto(-412.11782569,1011.0515604) \curveto(-412.83023954,1011.78039045)(-411.95030997,1012.77612336)(-411.34228997,1013.2366156) \closepath } } { \newrgbcolor{curcolor}{0.19215687 0.19215687 0.19215687} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-387.06465027,1002.53962894) \lineto(-387.23324499,1001.78953537) \lineto(-387.33440182,1001.7569226) \curveto(-387.7531911,1001.98208113)(-387.15434266,1002.29881629)(-387.06465027,1002.53962894) \closepath } } { \newrgbcolor{curcolor}{0.19215687 0.19215687 0.19215687} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-387.06465027,1002.53962894) \lineto(-387.23324499,1001.78953537) \lineto(-387.33440182,1001.7569226) \curveto(-387.7531911,1001.98208113)(-387.15434266,1002.29881629)(-387.06465027,1002.53962894) \closepath } } { \newrgbcolor{curcolor}{0.21568628 0.21568628 0.21568628} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-374.11657576,1002.27872683) \lineto(-373.6107916,1002.24611407) \lineto(-373.88054315,1001.91998642) \lineto(-374.21773259,1001.8547609) \lineto(-374.65607886,1001.62647155) \lineto(-377.48847016,1001.62647155) \lineto(-377.72450277,1001.8547609) \curveto(-377.57519528,1002.10327016)(-377.27280379,1002.02291231)(-377.08384283,1001.88737366) \lineto(-376.00483662,1001.88737366) \curveto(-375.35244249,1001.89132241)(-374.55357327,1001.77496398)(-374.11657576,1002.27872683) \closepath } } { \newrgbcolor{curcolor}{0.21568628 0.21568628 0.21568628} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-374.11657576,1002.27872683) \lineto(-373.6107916,1002.24611407) \lineto(-373.88054315,1001.91998642) \lineto(-374.21773259,1001.8547609) \lineto(-374.65607886,1001.62647155) \lineto(-377.48847016,1001.62647155) \lineto(-377.72450277,1001.8547609) \curveto(-377.57519528,1002.10327016)(-377.27280379,1002.02291231)(-377.08384283,1001.88737366) \lineto(-376.00483662,1001.88737366) \curveto(-375.35244249,1001.89132241)(-374.55357327,1001.77496398)(-374.11657576,1002.27872683) \closepath } } { \newrgbcolor{curcolor}{0.1882353 0.1882353 0.1882353} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-384.6368863,1001.36556943) \lineto(-384.40085369,1001.33295667) \curveto(-383.98044589,1000.91590464)(-383.50892018,1000.52089884)(-382.91722015,1000.41979927) \lineto(-382.88350121,1000.32196098) \lineto(-383.15325276,1000.06105887) \lineto(-384.46829158,999.89799505) \lineto(-385.27754623,999.18051423) \lineto(-385.31126518,999.40880358) \curveto(-384.97340136,999.87347025)(-384.4937831,1000.37596772)(-383.86135058,1000.35457374) \lineto(-383.86135058,1000.55025033) \curveto(-384.19044748,1000.69009386)(-384.60478586,1001.00017602)(-384.6368863,1001.36556943) \closepath } } { \newrgbcolor{curcolor}{0.1882353 0.1882353 0.1882353} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-384.6368863,1001.36556943) \lineto(-384.40085369,1001.33295667) \curveto(-383.98044589,1000.91590464)(-383.50892018,1000.52089884)(-382.91722015,1000.41979927) \lineto(-382.88350121,1000.32196098) \lineto(-383.15325276,1000.06105887) \lineto(-384.46829158,999.89799505) \lineto(-385.27754623,999.18051423) \lineto(-385.31126518,999.40880358) \curveto(-384.97340136,999.87347025)(-384.4937831,1000.37596772)(-383.86135058,1000.35457374) \lineto(-383.86135058,1000.55025033) \curveto(-384.19044748,1000.69009386)(-384.60478586,1001.00017602)(-384.6368863,1001.36556943) \closepath } } { \newrgbcolor{curcolor}{0.70980394 0.70980394 0.70980394} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-374.25145153,998.7565483) \lineto(-374.01541893,998.52825895) \lineto(-374.42004625,998.52825895) \lineto(-374.25145153,998.7565483) \closepath } } { \newrgbcolor{curcolor}{0.70980394 0.70980394 0.70980394} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-374.25145153,998.7565483) \lineto(-374.01541893,998.52825895) \lineto(-374.42004625,998.52825895) \lineto(-374.25145153,998.7565483) \closepath } } { \newrgbcolor{curcolor}{0.85882354 0.85882354 0.85882354} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-369.39592359,997.8433909) \lineto(-369.26104782,997.71293985) \curveto(-369.65704309,997.08416575)(-369.82186129,996.40060221)(-369.83426986,995.6583357) \lineto(-370.03658353,995.78878676) \curveto(-370.32427356,996.33759435)(-370.63354371,996.89814254)(-370.44121086,997.54987602) \lineto(-369.96914564,997.22374838) \lineto(-369.39592359,997.8433909) \closepath } } { \newrgbcolor{curcolor}{0.85882354 0.85882354 0.85882354} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-369.39592359,997.8433909) \lineto(-369.26104782,997.71293985) \curveto(-369.65704309,997.08416575)(-369.82186129,996.40060221)(-369.83426986,995.6583357) \lineto(-370.03658353,995.78878676) \curveto(-370.32427356,996.33759435)(-370.63354371,996.89814254)(-370.44121086,997.54987602) \lineto(-369.96914564,997.22374838) \lineto(-369.39592359,997.8433909) \closepath } } { \newrgbcolor{curcolor}{0.16470589 0.16470589 0.16470589} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-393.80843907,997.58248879) \lineto(-393.57240647,997.35419944) \curveto(-395.43504094,995.43656891)(-395.91250118,992.15311581)(-393.97703379,990.17939132) \curveto(-393.74504746,991.7200183)(-393.95954041,993.65069394)(-392.45968131,994.71256554) \lineto(-392.35852448,994.48427619) \curveto(-393.6295938,993.32013096)(-393.52088392,991.57652214)(-393.6735633,990.0163275) \lineto(-389.12150585,983.78728954) \curveto(-389.07451513,984.94791259)(-389.65453492,986.04670184)(-390.33538784,986.98334043) \lineto(-391.07720461,988.15739994) \lineto(-390.87489094,988.15739994) \lineto(-389.39125741,986.07018303) \curveto(-388.97084961,985.02605277)(-388.54760943,983.84860154)(-388.78431641,982.74368109) \lineto(-388.44712697,982.61323003) \lineto(-390.26794995,980.98259182) \lineto(-391.07720461,980.26511101) \lineto(-390.40282573,981.24349393) \lineto(-389.25638163,982.35232792) \lineto(-389.39125741,983.59161296) \curveto(-391.34290989,986.36500242)(-393.6384956,989.0040273)(-396.06760833,991.35345083) \lineto(-396.47223565,992.13615717) \curveto(-396.94443575,993.60242705)(-396.4133354,995.11565931)(-396.06760833,996.50626757) \lineto(-395.86529466,996.63671863) \lineto(-395.83157572,996.01707611) \curveto(-396.33061609,994.97581577)(-396.04171218,993.67678415)(-396.06760833,992.52751034) \lineto(-395.59554311,991.744804) \curveto(-396.02957336,993.76549087)(-395.53345979,996.11360989)(-393.80843907,997.58248879) \closepath } } { \newrgbcolor{curcolor}{0.16470589 0.16470589 0.16470589} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-393.80843907,997.58248879) \lineto(-393.57240647,997.35419944) \curveto(-395.43504094,995.43656891)(-395.91250118,992.15311581)(-393.97703379,990.17939132) \curveto(-393.74504746,991.7200183)(-393.95954041,993.65069394)(-392.45968131,994.71256554) \lineto(-392.35852448,994.48427619) \curveto(-393.6295938,993.32013096)(-393.52088392,991.57652214)(-393.6735633,990.0163275) \lineto(-389.12150585,983.78728954) \curveto(-389.07451513,984.94791259)(-389.65453492,986.04670184)(-390.33538784,986.98334043) \lineto(-391.07720461,988.15739994) \lineto(-390.87489094,988.15739994) \lineto(-389.39125741,986.07018303) \curveto(-388.97084961,985.02605277)(-388.54760943,983.84860154)(-388.78431641,982.74368109) \lineto(-388.44712697,982.61323003) \lineto(-390.26794995,980.98259182) \lineto(-391.07720461,980.26511101) \lineto(-390.40282573,981.24349393) \lineto(-389.25638163,982.35232792) \lineto(-389.39125741,983.59161296) \curveto(-391.34290989,986.36500242)(-393.6384956,989.0040273)(-396.06760833,991.35345083) \lineto(-396.47223565,992.13615717) \curveto(-396.94443575,993.60242705)(-396.4133354,995.11565931)(-396.06760833,996.50626757) \lineto(-395.86529466,996.63671863) \lineto(-395.83157572,996.01707611) \curveto(-396.33061609,994.97581577)(-396.04171218,993.67678415)(-396.06760833,992.52751034) \lineto(-395.59554311,991.744804) \curveto(-396.02957336,993.76549087)(-395.53345979,996.11360989)(-393.80843907,997.58248879) \closepath } } { \newrgbcolor{curcolor}{0.90588236 0.90588236 0.90588236} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-375.19558197,996.9302335) \curveto(-374.85839253,996.70390092)(-374.44890967,996.56431829)(-374.1502947,996.89762074) \lineto(-374.1502947,996.70194416) \lineto(-374.42004625,996.18013993) \curveto(-375.0879511,995.41817531)(-375.19679585,994.42035517)(-375.22930091,993.44066774) \curveto(-375.65173184,993.69256873)(-376.06944212,994.37861084)(-375.73508507,994.8430166) \lineto(-375.73508507,994.97346765) \curveto(-375.79931292,995.69407929)(-375.49743395,996.3118955)(-375.19558197,996.9302335) \closepath } } { \newrgbcolor{curcolor}{0.90588236 0.90588236 0.90588236} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-375.19558197,996.9302335) \curveto(-374.85839253,996.70390092)(-374.44890967,996.56431829)(-374.1502947,996.89762074) \lineto(-374.1502947,996.70194416) \lineto(-374.42004625,996.18013993) \curveto(-375.0879511,995.41817531)(-375.19679585,994.42035517)(-375.22930091,993.44066774) \curveto(-375.65173184,993.69256873)(-376.06944212,994.37861084)(-375.73508507,994.8430166) \lineto(-375.73508507,994.97346765) \curveto(-375.79931292,995.69407929)(-375.49743395,996.3118955)(-375.19558197,996.9302335) \closepath } } { \newrgbcolor{curcolor}{0.20784314 0.20784314 0.20784314} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-389.76216579,994.71256554) \curveto(-389.46557396,994.80745564)(-388.98528132,994.62765495)(-389.39125741,994.35382513) \curveto(-391.9012956,992.84450641)(-391.38607014,989.30276022)(-389.12150585,987.76604677) \curveto(-388.61005691,986.8128409)(-387.62033847,986.2136792)(-386.69374188,985.67882986) \lineto(-386.15423878,985.15702564) \lineto(-385.34498412,983.33071084) \lineto(-385.4798599,982.87413214) \curveto(-386.67013862,981.72329292)(-387.1563658,980.11900583)(-387.19952604,978.53663451) \curveto(-386.84426325,977.56516549)(-386.06090474,976.65683478)(-385.07523257,976.22112825) \curveto(-385.26459816,977.78523642)(-385.23924151,979.55806628)(-384.60316735,980.98259182) \lineto(-384.6368863,979.84114507) \lineto(-384.8729189,978.89537491) \curveto(-385.56024586,975.47886174)(-382.45999127,973.03942698)(-379.68020152,971.72056679) \lineto(-379.68020152,971.39443915) \curveto(-381.68580431,972.30655294)(-383.64150307,973.71255443)(-384.80548102,975.6340985) \curveto(-387.09971797,976.02740843)(-389.65291641,978.00308969)(-388.98663008,980.52601312) \lineto(-389.79588473,979.87375784) \curveto(-390.65302029,978.85310877)(-390.85317594,977.53868392)(-390.67257728,976.22112825) \curveto(-390.04513517,975.20347956)(-388.77487511,973.94997535)(-387.4692776,974.36220069) \lineto(-387.23324499,974.13391134) \curveto(-388.73441238,973.53253197)(-390.31245896,974.94675188)(-390.97604778,976.18851549) \curveto(-391.18497035,977.94960475)(-390.75336787,979.60372415)(-389.39125741,980.78691524) \lineto(-388.64944064,981.89574922) \curveto(-388.34974666,981.64789221)(-388.12261586,982.03233147)(-387.90762387,982.22187686) \curveto(-387.95990172,982.98292832)(-387.74536831,983.65162044)(-387.33440182,984.276481) \lineto(-387.77274809,985.54837881) \curveto(-389.42362759,987.01073515)(-391.08529715,988.6961628)(-391.78530243,990.79903384) \lineto(-391.65042666,991.32083807) \curveto(-391.77356824,992.7205779)(-390.59070768,993.70678789)(-389.76216579,994.71256554) \closepath } } { \newrgbcolor{curcolor}{0.20784314 0.20784314 0.20784314} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-389.76216579,994.71256554) \curveto(-389.46557396,994.80745564)(-388.98528132,994.62765495)(-389.39125741,994.35382513) \curveto(-391.9012956,992.84450641)(-391.38607014,989.30276022)(-389.12150585,987.76604677) \curveto(-388.61005691,986.8128409)(-387.62033847,986.2136792)(-386.69374188,985.67882986) \lineto(-386.15423878,985.15702564) \lineto(-385.34498412,983.33071084) \lineto(-385.4798599,982.87413214) \curveto(-386.67013862,981.72329292)(-387.1563658,980.11900583)(-387.19952604,978.53663451) \curveto(-386.84426325,977.56516549)(-386.06090474,976.65683478)(-385.07523257,976.22112825) \curveto(-385.26459816,977.78523642)(-385.23924151,979.55806628)(-384.60316735,980.98259182) \lineto(-384.6368863,979.84114507) \lineto(-384.8729189,978.89537491) \curveto(-385.56024586,975.47886174)(-382.45999127,973.03942698)(-379.68020152,971.72056679) \lineto(-379.68020152,971.39443915) \curveto(-381.68580431,972.30655294)(-383.64150307,973.71255443)(-384.80548102,975.6340985) \curveto(-387.09971797,976.02740843)(-389.65291641,978.00308969)(-388.98663008,980.52601312) \lineto(-389.79588473,979.87375784) \curveto(-390.65302029,978.85310877)(-390.85317594,977.53868392)(-390.67257728,976.22112825) \curveto(-390.04513517,975.20347956)(-388.77487511,973.94997535)(-387.4692776,974.36220069) \lineto(-387.23324499,974.13391134) \curveto(-388.73441238,973.53253197)(-390.31245896,974.94675188)(-390.97604778,976.18851549) \curveto(-391.18497035,977.94960475)(-390.75336787,979.60372415)(-389.39125741,980.78691524) \lineto(-388.64944064,981.89574922) \curveto(-388.34974666,981.64789221)(-388.12261586,982.03233147)(-387.90762387,982.22187686) \curveto(-387.95990172,982.98292832)(-387.74536831,983.65162044)(-387.33440182,984.276481) \lineto(-387.77274809,985.54837881) \curveto(-389.42362759,987.01073515)(-391.08529715,988.6961628)(-391.78530243,990.79903384) \lineto(-391.65042666,991.32083807) \curveto(-391.77356824,992.7205779)(-390.59070768,993.70678789)(-389.76216579,994.71256554) \closepath } } { \newrgbcolor{curcolor}{0.20784314 0.20784314 0.20784314} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-413.63517817,991.19038701) \lineto(-412.52245302,990.57074449) \curveto(-411.5593051,990.0968158)(-410.85808594,989.06273027)(-411.10625737,987.96172336) \lineto(-411.37600892,987.70082124) \lineto(-411.98294991,987.70082124) \lineto(-411.84807413,987.89649783) \lineto(-411.51088469,987.96172336) \curveto(-410.89922305,989.2449704)(-412.42021718,990.32680101)(-413.46658345,990.8316466) \lineto(-413.63517817,991.19038701) \closepath } } { \newrgbcolor{curcolor}{0.20784314 0.20784314 0.20784314} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-413.63517817,991.19038701) \lineto(-412.52245302,990.57074449) \curveto(-411.5593051,990.0968158)(-410.85808594,989.06273027)(-411.10625737,987.96172336) \lineto(-411.37600892,987.70082124) \lineto(-411.98294991,987.70082124) \lineto(-411.84807413,987.89649783) \lineto(-411.51088469,987.96172336) \curveto(-410.89922305,989.2449704)(-412.42021718,990.32680101)(-413.46658345,990.8316466) \lineto(-413.63517817,991.19038701) \closepath } } { \newrgbcolor{curcolor}{0.8509804 0.8509804 0.8509804} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-375.73508507,986.88550214) \lineto(-375.70136613,987.11379149) \lineto(-374.35260837,988.94010628) \lineto(-373.81310526,989.72281262) \lineto(-373.6107916,989.72281262) \curveto(-373.54187008,988.68533537)(-374.45012355,987.80518209)(-375.2967388,987.24424254) \lineto(-375.36417669,987.04856596) \lineto(-375.73508507,986.88550214) \closepath } } { \newrgbcolor{curcolor}{0.8509804 0.8509804 0.8509804} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-375.73508507,986.88550214) \lineto(-375.70136613,987.11379149) \lineto(-374.35260837,988.94010628) \lineto(-373.81310526,989.72281262) \lineto(-373.6107916,989.72281262) \curveto(-373.54187008,988.68533537)(-374.45012355,987.80518209)(-375.2967388,987.24424254) \lineto(-375.36417669,987.04856596) \lineto(-375.73508507,986.88550214) \closepath } } { \newrgbcolor{curcolor}{0.74509805 0.74509805 0.74509805} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-375.73508507,986.88550214) \lineto(-375.86996085,986.75505108) \lineto(-375.73508507,986.88550214) \closepath } } { \newrgbcolor{curcolor}{0.74509805 0.74509805 0.74509805} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-375.73508507,986.88550214) \lineto(-375.86996085,986.75505108) \lineto(-375.73508507,986.88550214) \closepath } } { \newrgbcolor{curcolor}{0.60784316 0.60784316 0.60784316} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-375.86996085,986.75505108) \curveto(-375.85110521,986.50915084)(-376.12420169,986.77327509)(-375.86996085,986.75505108) \closepath } } { \newrgbcolor{curcolor}{0.60784316 0.60784316 0.60784316} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-375.86996085,986.75505108) \curveto(-375.85110521,986.50915084)(-376.12420169,986.77327509)(-375.86996085,986.75505108) \closepath } } { \newrgbcolor{curcolor}{0.23137255 0.23137255 0.23137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-415.92806636,985.97234474) \lineto(-415.69203375,985.93973198) \curveto(-415.44642497,985.52881115)(-415.18624959,984.92847538)(-414.61302755,984.89612352) \lineto(-414.30955705,984.79828523) \lineto(-414.20840022,984.70044694) \lineto(-414.44443283,984.53738312) \curveto(-415.1433591,984.61385353)(-415.91592754,985.24442784)(-415.92806636,985.97234474) \closepath } } { \newrgbcolor{curcolor}{0.23137255 0.23137255 0.23137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-415.92806636,985.97234474) \lineto(-415.69203375,985.93973198) \curveto(-415.44642497,985.52881115)(-415.18624959,984.92847538)(-414.61302755,984.89612352) \lineto(-414.30955705,984.79828523) \lineto(-414.20840022,984.70044694) \lineto(-414.44443283,984.53738312) \curveto(-415.1433591,984.61385353)(-415.91592754,985.24442784)(-415.92806636,985.97234474) \closepath } } { \newrgbcolor{curcolor}{0.84705883 0.84705883 0.84705883} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-387.33440182,985.58099157) \curveto(-387.58864266,985.56275451)(-387.31555967,985.82689181)(-387.33440182,985.58099157) \closepath } } { \newrgbcolor{curcolor}{0.84705883 0.84705883 0.84705883} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-387.33440182,985.58099157) \curveto(-387.58864266,985.56275451)(-387.31555967,985.82689181)(-387.33440182,985.58099157) \closepath } } { \newrgbcolor{curcolor}{0.95294118 0.95294118 0.95294118} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-387.33440182,985.58099157) \lineto(-386.55886611,985.15702564) \lineto(-386.25539561,984.53738312) \lineto(-386.39027139,984.01557889) \lineto(-386.62630399,983.4611619) \lineto(-387.43555865,982.74368109) \lineto(-387.4692776,983.23287255) \lineto(-387.06465027,984.40693206) \lineto(-386.96349344,984.63522141) \lineto(-387.30068288,985.35270222) \lineto(-387.33440182,985.58099157) \closepath } } { \newrgbcolor{curcolor}{0.95294118 0.95294118 0.95294118} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-387.33440182,985.58099157) \lineto(-386.55886611,985.15702564) \lineto(-386.25539561,984.53738312) \lineto(-386.39027139,984.01557889) \lineto(-386.62630399,983.4611619) \lineto(-387.43555865,982.74368109) \lineto(-387.4692776,983.23287255) \lineto(-387.06465027,984.40693206) \lineto(-386.96349344,984.63522141) \lineto(-387.30068288,985.35270222) \lineto(-387.33440182,985.58099157) \closepath } } { \newrgbcolor{curcolor}{0.9137255 0.9137255 0.9137255} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-378.29772482,985.32008946) \curveto(-377.78101572,985.35631572)(-378.337702,984.97778588)(-378.46631954,984.83089799) \lineto(-379.20813631,984.63522141) \curveto(-380.33906969,983.60309265)(-381.9353245,982.74237658)(-382.24284127,981.17826841) \lineto(-382.47887388,980.23249824) \curveto(-382.92490807,979.69060455)(-382.80648714,978.76753288)(-382.61374965,978.14528134) \lineto(-382.6474686,976.61248142) \lineto(-383.65903692,977.78654093) \curveto(-383.88306558,979.57763394)(-383.1257381,981.17044134)(-382.31027916,982.67845556) \curveto(-381.17772727,983.64835916)(-380.09427016,984.77610855)(-378.60119531,985.09180011) \lineto(-378.29772482,985.32008946) \closepath } } { \newrgbcolor{curcolor}{0.9137255 0.9137255 0.9137255} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-378.29772482,985.32008946) \curveto(-377.78101572,985.35631572)(-378.337702,984.97778588)(-378.46631954,984.83089799) \lineto(-379.20813631,984.63522141) \curveto(-380.33906969,983.60309265)(-381.9353245,982.74237658)(-382.24284127,981.17826841) \lineto(-382.47887388,980.23249824) \curveto(-382.92490807,979.69060455)(-382.80648714,978.76753288)(-382.61374965,978.14528134) \lineto(-382.6474686,976.61248142) \lineto(-383.65903692,977.78654093) \curveto(-383.88306558,979.57763394)(-383.1257381,981.17044134)(-382.31027916,982.67845556) \curveto(-381.17772727,983.64835916)(-380.09427016,984.77610855)(-378.60119531,985.09180011) \lineto(-378.29772482,985.32008946) \closepath } } { \newrgbcolor{curcolor}{0.65490198 0.65490198 0.65490198} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-379.10697947,984.14602995) \curveto(-379.12583511,984.39193019)(-378.85273864,984.12779289)(-379.10697947,984.14602995) \closepath } } { \newrgbcolor{curcolor}{0.65490198 0.65490198 0.65490198} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-379.10697947,984.14602995) \curveto(-379.12583511,984.39193019)(-378.85273864,984.12779289)(-379.10697947,984.14602995) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-379.10697947,984.14602995) \lineto(-379.24185525,984.01557889) \lineto(-379.10697947,984.14602995) \closepath } } { \newrgbcolor{curcolor}{0.58039218 0.58039218 0.58039218} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-379.10697947,984.14602995) \lineto(-379.24185525,984.01557889) \lineto(-379.10697947,984.14602995) \closepath } } { \newrgbcolor{curcolor}{0.93333334 0.93333334 0.93333334} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-379.24185525,984.01557889) \lineto(-379.68020152,983.26548531) \lineto(-380.82664562,981.50439605) \lineto(-380.86036456,981.01520458) \lineto(-381.13011612,980.49340036) \lineto(-381.39986767,978.01483028) \lineto(-380.75920773,975.37319638) \lineto(-380.75920773,975.1775198) \lineto(-381.5010245,975.69932402) \lineto(-382.31027916,976.74293248) \lineto(-382.44515493,979.5476302) \curveto(-382.11632779,981.04781735)(-381.43749801,982.65627888)(-379.94995308,983.52638743) \lineto(-379.47788786,983.98296613) \lineto(-379.24185525,984.01557889) \closepath } } { \newrgbcolor{curcolor}{0.93333334 0.93333334 0.93333334} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-379.24185525,984.01557889) \lineto(-379.68020152,983.26548531) \lineto(-380.82664562,981.50439605) \lineto(-380.86036456,981.01520458) \lineto(-381.13011612,980.49340036) \lineto(-381.39986767,978.01483028) \lineto(-380.75920773,975.37319638) \lineto(-380.75920773,975.1775198) \lineto(-381.5010245,975.69932402) \lineto(-382.31027916,976.74293248) \lineto(-382.44515493,979.5476302) \curveto(-382.11632779,981.04781735)(-381.43749801,982.65627888)(-379.94995308,983.52638743) \lineto(-379.47788786,983.98296613) \lineto(-379.24185525,984.01557889) \closepath } } { \newrgbcolor{curcolor}{0.96470588 0.96470588 0.96470588} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-386.12051983,983.49377466) \lineto(-385.98564406,983.23287255) \lineto(-386.15423878,982.74368109) \curveto(-386.80676778,981.93879807)(-387.07611471,980.94997906)(-387.36812076,980.0042089) \lineto(-387.43555865,980.0042089) \lineto(-387.43555865,982.15665133) \lineto(-386.55886611,982.74368109) \lineto(-386.12051983,983.49377466) \closepath } } { \newrgbcolor{curcolor}{0.96470588 0.96470588 0.96470588} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-386.12051983,983.49377466) \lineto(-385.98564406,983.23287255) \lineto(-386.15423878,982.74368109) \curveto(-386.80676778,981.93879807)(-387.07611471,980.94997906)(-387.36812076,980.0042089) \lineto(-387.43555865,980.0042089) \lineto(-387.43555865,982.15665133) \lineto(-386.55886611,982.74368109) \lineto(-386.12051983,983.49377466) \closepath } } { \newrgbcolor{curcolor}{0.97254902 0.97254902 0.97254902} \pscustom[linestyle=none,fillstyle=solid,fillcolor=curcolor] { \newpath \moveto(-388.0087807,981.66745987) \lineto(-387.87390492,981.53700881) \lineto(-387.87390492,979.18888979) \lineto(-386.82861766,977.06906012) \lineto(-386.82861766,976.87338353) \curveto(-387.86500312,977.14341722)(-388.29336859,978.22616099)(-388.68315958,979.05843873) \lineto(-388.51456486,981.24349393) \lineto(-388.0087807,981.66745987) \closepath } } { \newrgbcolor{curcolor}{0.97254902 0.97254902 0.97254902} \pscustom[linewidth=0.13264497,linecolor=curcolor] { \newpath \moveto(-388.0087807,981.66745987) \lineto(-387.87390492,981.53700881) \lineto(-387.87390492,979.18888979) \lineto(-386.82861766,977.06906012) \lineto(-386.82861766,976.87338353) \curveto(-387.86500312,977.14341722)(-388.29336859,978.22616099)(-388.68315958,979.05843873) \lineto(-388.51456486,981.24349393) \lineto(-388.0087807,981.66745987) \closepath } } \end{pspicture} } \newcommand{\card}[1]{ \begin{tikzpicture}[font=\tiny] % \draw[-,line width=1pt,MyBlack] (-5mm,0mm) to (-2mm,0mm); % \draw[-,line width=1pt,MyBlack] (0mm,5mm) to (0mm,2mm); % \draw[-,line width=1pt,MyBlack] [xshift=2mm](\width,0mm) to [xshift=3mm](\width,0mm); % \draw[-,line width=1pt,MyBlack] (\width,5mm) to (\width,2mm); % \draw[-,line width=1pt,MyBlack] (-5mm,-\height) to (-2mm,-\height); % \draw[-,line width=1pt,MyBlack] [yshift=-2mm](0mm,-\height) to [yshift=-3mm](0mm,-\height); % \draw[-,line width=1pt,MyBlack] [xshift=2mm](\width,-\height) to [xshift=3mm](\width,-\height); % \draw[-,line width=1pt,MyBlack] [yshift=-2mm](\width,-\height) to [yshift=-3mm](\width,-\height); \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-16mm) {\orga}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-18.5mm) {\ifthenelse{\equal{#1}{english}}{\departmenten}{\departmentde}}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-21.0mm) {\ifthenelse{\equal{#1}{english}}{\subdepartmenten}{\subdepartmentde}}; \ifthenelse{\equal{\gpglineone}{}\or\equal{#1}{german}}{ \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-33.0mm) {Tel}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-35.5mm) {Fax}; \node[rectangle,draw=white,minimum height=7pt,text width=30mm,inner sep=0pt] at (65mm,-33.0mm) {\phone}; \node[rectangle,draw=white,minimum height=7pt,text width=30mm,inner sep=0pt] at (65mm,-35.5mm) {\fax}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-38.5mm) {\email}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-41.0mm) {\homepage}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-44.0mm) {GPG Fingerprint:}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-46.5mm) {\gpglineone}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-49.0mm) {\gpglinetwo}; } { \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-35.0mm) {\email}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-37.5mm) {\homepage}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-44.0mm) {GPG Fingerprint:}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-46.5mm) {\gpglineone}; \node[rectangle,draw=white,minimum height=7pt,text width=37.5mm,inner sep=0pt] at (64.25mm,-49.0mm) {\gpglinetwo}; } \ifthenelse{\equal{\gns}{}\or\equal{#1}{english}}{ \node[rectangle,draw=white,minimum height=7pt,text width=120mm,inner sep=0pt] at (62mm,-2mm) {\gns}; \node[rectangle,draw=white,minimum height=7pt,text width=41mm,inner sep=0pt] at (24.25mm,-21.0mm) {\ifthenelse{\equal{\prefix}{}}{}{\tiny \prefix}}; \node[rectangle,draw=white,minimum height=7pt,text width=41mm,inner sep=0pt] at (24.25mm,-24.0mm) {\fontsize{8pt}{8pt}\selectfont \textbf{\name}\ifthenelse{\equal{\suffix}{}}{}{, \tiny \suffix}}; \node[rectangle,draw=white,minimum height=7pt,text width=41mm,inner sep=0pt] at (24.25mm,-29.0mm) {\ifthenelse{\equal{#1}{english}}{\textit{\jobtitleenglish}}{\textit{\jobtitlegerman}}}; } { \node at (78mm,-7mm) {\logo}; %\includegraphics[height=7mm]{gnunet-logo.pdf}}; \node[rectangle,draw=white,line width=1pt,inner sep=0pt] at (17mm,-17mm) {\begin{pspicture}(15mm,15mm) \psbarcode{gnunet://gns/\gns}{eclevel=Q}{qrcode}\end{pspicture}}; \node[rectangle,draw=white,minimum height=7pt,text width=41mm,inner sep=0pt] at (24.25mm,-35.0mm) {\ifthenelse{\equal{\prefix}{}}{}{\tiny \prefix}}; \node[rectangle,draw=white,minimum height=7pt,text width=41mm,inner sep=0pt] at (24.25mm,-41.5mm) {\fontsize{8pt}{8pt}\selectfont \textbf{\name}\ifthenelse{\equal{\suffix}{}}{}{, \tiny \suffix}}; \node[rectangle,draw=white,minimum height=7pt,text width=41mm,inner sep=0pt] at (24.25mm,-47.0mm) {\ifthenelse{\equal{#1}{english}}{\textit{\jobtitleenglish}}{\textit{\jobtitlegerman}}}; } \end{tikzpicture} } \begin{document} \addresslabel{\card{german}} %\addresslabel{\card{english}} \end{document} \begin{figure} \begin{center} \card{german} \end{center} \end{figure} %\clearpage %\begin{figure} % \begin{center} % \card{english} % \end{center} %\end{figure} gnunet-0.10.1/contrib/gnunet-logo.pdf0000644000175000017500000026200212247442021014403 00000000000000%PDF-1.4 %µí®û 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xœÄ½ËŽ4=’%¶÷§ˆP6ï—­  ´Pk)h!¤  2!ôÌbôøâ9ÇHwü¢:êïNV~|Iº‡;4Úõ˜ñ_}üÓÏÿüßÿôÿ•Çÿòÿ>þ7öTõ´³§«Ç»³Ë{ë —¾h}éÒgÏ÷—x{ƒ¿¼ÂÛ;ÂåÁÞ.ïöŽpyG°w„Ë;‚½#\ÞìñòŽhwD{G¼¼#Ú;âåÑÞ/ïˆöŽtyG²w¤Ë;’½#]Þ‘ìéòŽdïH—w${G¾¼#Û;òåÙÞ‘/ïÈöŽ|yG¶wäË;²½£\ÞQìåòŽbï(—w”IS—w{G¹¼£Ø;ª½Ã=ðÿùçÇ?ý_n\9â‡ë±ªú‡ü§ñß=þÿóá>Üãÿ>Òã}üëÃóÿþ ±}ŒÿÜ –ÏïÃûøQ]}øÚüãû±Ú¾~Ô_ÿ}¼0~ø˜|MãëY=|䞣³»òòaã !äWÛúÁ_x„ïñ#ŽIô½~¤±`å>|ôAÓ—Q|ä±Îo? ¦6ö±ï壴ôW†`O}>þµixúÁùˆ0ž[X+»HçßxZ\Á´žñ¬X>º÷Ǿô%}Ôüˆþ£ŒùDŸ££Ôø(ý#æ|<‚÷~ìªî?úØ(ÏKþ9žZ>2¦/ ²Û+°¥}ŒÙ´çkzÇŠûð®_ú8ÞžÏaðˆóËãG·}>ºûÈ.ÜGqcLuŒ%ùõû§õû|Ä0>°Í„Aaƒc|˜”ðS´ñø€q÷`u ÿÜàðy왂 zƒºÆç<>>#-„àö‹Ç7§ñ•~܆§ÖÂwüÛ×êõD2: ·9~ÑÛ¤¿>½ç?Ó>}|jÄØÝGêá‘ÇZ‘ñ÷|8n<¿Üåoƒºhkƒ˜ANx¨Ê¿ýÙcñÇFÄg—A£úl|ïßýÙ.uYrß:‰Œk>Ä®OLçšû:˜Lxg]&K±œËîǺ70H­œ/þ¶ð>wòÏwWÞ'÷ÑûM€ä4.´¿2 ¶§|Ëœ×6¶ÏøvìÍ¢Õ¯ýß5cý]' |îѪW_l|åí ˜ƒýëðôEßÔÈŒ°ø}ü;¶f¨•+5¸ñc0ß<4¶“ùþú opup2ŸÙ\ C™ñCÔ¡ÐÎÁ¼ýôBÉtʬ§ùø·—ÿ‰¦¿ù¶Ïœ@ßÄj× –ßêß1ÏDý½¤Ï¥‰Ã9 kLï¿Á}´xŸ’msÀ£‡Duñ|Å}ßüÛo¸³ûñ‚Á7DV–d£CcîaFüå)2Î7ŸÛG ùµ×5AnˆãêÿC&è&2ÞÝ$ëóm RºSm´OÿkÛc}¸‰÷1 9ÛöÙÿQ›ãöÑcÇÿÿÛo)”vƒ× ƒ{šC•-*/£U†NV;¿÷“q˜Hǘ“ÍÇí3¦¥Ž—ƒøGÓ—Ž1uxÿ`/žÜ £ ¶5V–tŠOC£AÅî/^ÂÜ ÊÖZÍœ|?( øåñCO„‰Ñ ){øÁÞóXŸÑn3½Ì¯ýc|î Ò]Ïóƒ>×§>è$jÛø¦X¡±ÕÎÃÐäï¯èmˆôŠfªsmL†2šƒ .ↆ3  Ñ*e|Þh¶±=‡k_Y Vªé±cÁ‡}’ÇŒ¥¤¶¬ÕÃc3drLj†ÙAwÿıQУÿ@wä½øš¡cí0 ‚ÖgüƒÔ›Ǹw,ŒQW¾]uÔx—ù€6ùT0ÊqK8”‡€ºvJú1~ßÇ‡Ž ìo šøc¨A_¸¯OÏýî€iµCÁÇçÒ©ÔÇýøÆ:DæÕ8Æä4€¹HcïŒWBG3E¾Ú‹2ÑÑe k\Ô„„rÐA“ÞV\ áö±=X(˜8Þxiê/—ñóO.¦¯$¡Ö îw!’ÄÆðÑ„j‡ý&oçåÊŸƒh8†ëƒ<®ŽÇMëù0ÞN« š}‰/z*$†gb‡‹35(”sáÇ"%\:Ñ.›æn¥,‡NÊ]5¶Cõ`¤CÑÿ~a»Fǯû!Vü‚s:øÓcw`»à“¸¨(= ¥n-žŽ=š¦œ?0„’8MC»Î·R§Ò;˜©<ÂNã/ð™óWÀnÐöðbdìbÝÕ æv Ïc#ësÀŽ8‚X8!°™0&š7ÙÞ»¸×B¢tÀ³é)üTö<«;ù5zäÉø…ƒBÁè Êfìñ²èIõŸœõظx á@›Ùzoª'8©òØPãw@Ë‚£Ü(ªýZ!rÏñƒ±mHòcŸHO*1+;­ƒÆ)èÕ·I\c"éOõ…Š·Q 4× Þx2¡PÏÿH|k– ¦G%epßAo—'MC¾B±+\÷XíŽ2O Úåp$±DÕ8Ú;+>ȱÁ"T*¤ $ÜO]àÏ55пýÜ1ƒ@@ÖÝ|ªX7°hh?q¨$ÐÁÙŠã7ޏ ç“?ž‰<žË*)b4à Çí1cÐW¨yb‘@ Pvš¤1Õ)IlP¬vXx\„±€´Ðþ9dGÝB´Š ÀeÆF+l4S¨ˆ@ûâzbob7‡@¢sp×¾Þ‡- 7¿v¨0BèÐ@?!¡É÷VÕx:håS´á#MDÒô^$;tz€¼Œƒª-üÉÈ~Ç`Fçù¼Ôç¯!ÓœiÄcê‚´ªìu™ŽÚ@-+ÓA­Á'.J%{2ï]Æ"W(j¶<^*ÒÐFR³›áR‡×Û.[6%Õ>|õ°Ãî{„ê¾å±ÝžÞÂð2kWOýd&¯óÔ#¡}NƒÂÑÈ‚·K˽pŒk(GÒ*+™W3Ú„3ÀQ3özºb.Ôïi° h0ÝEü?Å6çÏ?þÛþCçúã_þ™×>¶Áÿ8Üã?ÿþëéúÀW?û§{8ˆ‘ƒiÅjnÉBªû²M©]f¸ÃÉEæ!_õ‹cýDûøúØ/²vjYƒƒtßmoƒƒ¢‘ /úÞ<™ëøY¡n,­É0_¥NP^ƒ]J’ƒƒ€—‚¹åh¬±üK+t<‹.zhÎA‚ Žg;–y¤yFá©Ãˆ;m0ÊZ†Е¨›cÃËK‚øEçLA_»ªÁø&|¹Øá‰t?ÆKÉwçT¬…?¡G‚‘h=D!Ú‚ka_b£óíyµìÇoF¨Ÿä òAžDÓРáÓûT¢xZ—q_r—À… •›Æ>yb¤çÒó£*郎Üà“…r;v9¾Äƒƒ)ù-KMœëjŠãtSÁU‰B˜¶Êëmò½œfÁ£éDÃñ>z:Ý%×äDí%:Ù2En€¨m|c¨b¶d£ðJ'FzÆÌaú?9DºXMmæìCkrEÞoãsƒ$®X)=¶€’ÀUªôhÓqÌøH¬0X+ôã|žÛÆÁÿm“Ðɉ£>çí;`´øù’ƒ+êê\A„‘‡wÔÖÃ¥±hŽ–_¢äxéKÊûÌýèÍE#VöÉh»Î´àѤ±:‡6õU|Y+öím¸AÏð^s㸘´qUã!]|6W±ɹ1ª!ºñtbï5Û+¨Ù:xN¼}‡3zœ W¦ãšIßl^Û19^ß ò-Ò¤ZŒ¦eH BÕ6 ‚];Ñ“—8ehCôñÐãÇ3ª¤Ã,cxª¯¶lò} ò:α{蓩¹B±'g†Ï˜þ‘4IÌ'¹D¢—szá`4E´f‡´îm2ê͸ÃôÂ`_ ¶[uèØÃÔ¦b¨ ¡C>p[’6Ü`+àˆU¾Ž(›÷)į.à  |´š"qQ–5üL‰q¼z³©b$·%á%‚Uœtt†í²™žmH¹ûíð”; `VX€È²õŠOœÌøÔ1¬Ñ¤> _þèž!<´Å'äã+¡8>š4´¨0£Ô«P-žI•>`›öÁø(é| ‰&ß9”a: €ªà›*!Êñ¢f˜S Þ˜Î!±à)ŒŠº ÃÛƒBQ……‘§(—„±âêòF1†Ô.Ôø ÷ê芶*öÙ»'îÚxž¥Ï $`ðºœøo’)ZHþ`´l`¿4q3YlC|¤KGïŒhQbçQ=b8¿ýI·«¯çýUƒsPÉ} À‘‰1ysä"€ÊÎŽÂ]Ìi‚}âäha»¶¾dg%ÑÄØ‰I=f±ç`K6:LSÌ’Z1ħ»?{àýy>I®5MKâh ê¢îšºsËq°'¥ªž‰–‰´‘Àͽ: h0ë ‡„d¢A³Ç0âÓýŸ|¢h`½3*. ç‚îöakR\¢É/¨’]f(ž.– –Ê?d’.D C¥« [ŒÈ— ûþ˜6å¾7cÝ;¡>è6Â%R|2œå !‰’Á3z’¾(GH¡ þDµ¯+„Pš‡ÐTŒÔ÷óñžj/E§6,>Û_æo…³¬+¸Io9 Bd7dWÒâZQXî—JDGiæ”b£Ë­éêh†ˆ¡0ÉI±_2 ‹!è‰Å#jœðpù)ÇÉd¸˘c3 !hÚ³²‡˜¶ˆ÷íæZ :اBcdh2f)ºMÇrÈBÔíÍTÆ13ì nh±IÜk€šjö\Ɖa¦Ã”1:ÕFWŒ¢_²y`à¼HÁ]È«j‹Œy̓)—¢#ÃO4zªô(úùÌM]½Äf•ÉT6DyÆÙ×·¹œ O ­hƒ BŠZÜ ÄÎ(2\úID4lèè$"ú+2\„4ìœí²¹J€EÈ·Êh$;ͰïªýBa]`sÚa›™ÑJSœIQ£™ç†#þT$x!–IûSÁáÁ<½,zlB˜tcÁt5’z¡¶y߸ÞäÇCª’¸‰|æ˜_[?úX2ÌXmlCÅ–@ÿ‚L† ÂW1t×!æ\½¾“ªLã"þH°¿Æs Þ¬w¡G53¨+ÃÃù2ýHËhsä x—"LüwøF¾ƒ$¹G¡]d–ŽîA¾¢Öb‹ñ²¢a K<À°’„ Ø’,‰·$°¤"ËÍ:œa:ª2V /‰+ÆŸ$Dì<§%FÐn¹Îu$„§ï"V £ÍS£L—Ù;_-ð #-“Ã)²U&n_Ši9“Ä4{ù¼AúC6úY‚Þj¹`'I r/0Æ‘•ºdèIÒc²­ ÄØêP2ŸãBP¢íäÈ6%bݱO %I.q‚(€ï&ÿ° à[K~á( ªh HIJH…¤Wƒ!H(¥"üÎû ¦dž}v¦¤ƒPæa& ä—$ÃÃ4ú1 OYÄó`~UciNîsó0†_ §Håä£ SIÜGÏT‰÷¹Uy`°¦‚Á*ÑQ¥ÃUÂ_âW˜á*¹T!L`%‘;¤CVIrB+¹e4bØJl²&PéDÒˆ8 ]Iæš'"­ínÚãçX‘c",µkŸ6„%EJ]¦OŒÍ?Ğʼn±ÄðFÿ±P–&µâDY’gŽ}d0K4]¼à,)³&βRÍxs^HK¾!2ÈcHK X\Ê jIÇ|ZPË ­ë8±–ˆ ™Ue*àxK§›á\@Ó‚ãêÀ –À¶@HN°%Œt 創„3¼ù…µÄýõÄZFñÄ…µ$Bnõ ¶4ÓÙÀ–0IémZ`˱º‚éN°¥Ð [ʯßÊB[úAÆô…N°¥—ÞÀ–p±ŒÉ!ØRŒÚ1Ú!°%tCàÖjÂ?ÀÉV4ì…øC:WMg d¡¯fy@\k‹ g QëëDY-æ'Ʋhÿ-ˆeuT='Â’ÞŒÊDXVh†¯´»'¼²‚4‰¯„ï£Ëœéö¡:Ox%—û ®b#Ô[‰ .aB+ñ[€…‰¬ä£Šü ²ÊgÀJ\íBœ/1Xe…¾Ó'ª~X4Uviø'¦ËÓ¦Òì!ÃT2Ò™ R …ÚOD%EZ€J¸$iÚOÙÈYB8á”äÊ M‰Ü'¸š|éM.¾‰¥D2E5×áË{Ø”`À)=<®DéK†£Ä¦5¼qHEʲ¡(é[¥D7%h€PcƒPÒäH-.%¦!,%Ýè ¨l ìa(©g¸Ÿ4 ”±KƒOš¯x¢'‰ñ>Á“ náf :‰ž„-mÐId²EÀ[ä–|œ¸ÉEa‚M’hœøójàu²ôø´`2{b&«¼H2 ØÒôò!eAä-‰]+äIžy¦Åkl ­êæR + ~s\HIhƒÔ”EŒ (YÁÞÃÄI2',-”dw3H>a’°£Rš0ÉÃÍ &‰p “T,¨„+JÁIÆh>¸ãIúµöÙàI^´1!’^ÎÙ‘ôš‰‘”Åîë#ipa$-ª'´¢ùzì¢ò8!’T, \…¥·X¾a$‰~©Wˆ$ð)ÏDRº”A$å¦l¶V €Û¶‰‘$¦ó:„ŽR´&D*”óÇ# p¤‚ßF,<Dy‚ ê#Å[P®!YaösàѰû‰ß¼P’2ý“Á¸Oó, “¤(o}Æ”c°Å[c¯˜wô*Ù¸932‚JÒÚAXI™ ÍM‚64EJzL¸$´ Ÿ„·\m}¬á%¥¶<¤º^ÖbÐî‹ô+NÌd“½´“0À¢a;W©þqb&Ù! 7Ð$“\\±d´+u¡&Ñ.Þ+nKÜ$ðÌù~N¢MãÄ“ž@I²èCÕÌÑb“lN†IàW(ÝBH+NUA´9ȉ*ÖPÙc†ÉP¶‹Ü)U4’\Uc= VR–’ §"Ò‚äwÛ²ÞeY륛.$Iaz›¢ŠAiÔxHË⇙î’No%–Œ@؇Mî $‰±c+é!"„hþaiZʨ٭äÍK"ØS ð}Å`Haù]’›!Ð^èÕ„ˆVd¢¯b¡þ=ëNo¡ CÌ3¤LÚpÄÛAx?8z]؃™0±”…‚E¸ÄƒUfLµ0<½Z5PÇ!"\š¦jØÜ€Q ~á‹9bäøâJÙÊå&˜Œ<9‘‘¨ÜqØJ¦ÛʇEyDdtð)ù¹ÖtFæ…}œ›E GþETz0‡[;qpÑ5µï_û&¸åïŠt¡rFb6W¡ýh’CŒùò^øŠæ¶eÂQ–~¯±1N˜£˜˜ž«ú}¾©+_Ägƒ:6Ý‘œÍc³ëiòßHgð?ÕÛ›dÙªG~É@³ý‹t@GÄxP4,v…–¯Uïm4I,Ô …ãûÊü'hÍ„"¿2 Â0°“QûòaþÍÚ×›æ*‡…jˆZ"OH˜¥¦gÃBzfú ,!Ý‹Œ»^µ 2± r£µeÚÓ¤ƒDVn€Ê,ï }´äé,ƒNb 8¨¿uaT¡óF¦aƒ…$sÊAÊuAw3#H>–D HÛI¤&$ªw"øˆ”qF˜Ì”qªÎÒÓL`RÆ$PˆrºqÅÙîö‹F8k”BgK&}m;ÆŒ¡ kÛ;¡Êc¥FøÅú¶ ž‘B ½‹Y-jžÒ'úQâACHÛÚš¯Í‘T¥hRÄ¢#éµ–ÀeÏÜB5% eJ;pXDÞ³Ò™b’3¨* zº2`¢Ýሗ æñšÐ¼­’ÉC¦í@%iý¤c,Z˜LQެ,ªñÃGðÂ8@°LžØEùЪl¤d'ù²*‚^±ÈÁ[@©Tµƒ¼]†ä¦ßïÎ…dˆñ¦pH4ÆŒ%  ï žS+*Æ…×Õ4í‚¡‚¬dn0Ù"Ö…³f%*yæÉÐш ‘<[™nr¬e.BoÀé]"š‚NA'úD3« ¯c¶éIœµl•d4{)zŽé@øÂ €¤,¼—^¥X|‘ÁíÑ@ÛT²ç»¿þÞàNÁ ŸªOr‡2Â:u q&ÁÁ¸˜ÂáëþCã… hº!sµ]Té›ÊE4LÓDv ˆ3’졉é¢P€°0ÒBïTLÓ&JW±ÙO|L6’ÖË ï<³àΊyþ<Ä`Yø0Æ“(I.…åLÆýG†ÕûÂBÀZ8ÛE!4D@[Ô/¨Yõl^ox™í´:åÊœæÎä9ÎQrТ¼Þ¦üBh¸šE—åí(q<|ÛuƒÔ/·^—S0r÷Xb G=Lr,kõ&xBµnTÈ-0C£Úq8š†S'XFL¸ÏcÒçƒ(Q–l|<ŸË€CN†ÄQ$Ì2yj™(üfj *aœnjŒÞ]ËfbtØvpµbþÑrš"ŵ£Jì†')2>…H±×f»Ï5°r/…±cL¢eâ€_Að÷ZSó휠­È z+6"enÀ¸LM1qpð˜Y+„OÌÝð7rD )Ñ“·ÐIeæÉLAW,óÑV±È´²˜˜£œT(«]fÍ1 ð½*„ rf>¹ ÂC XÆ»bÙ,<§Eûn‹H&&~Â__ôMD$*˜íú`äÂȲÒ\òÐdD `Í;åBØHM^ñF§4#(ZàNë3¤6H¼ê³u&wa Ä" C˜¶¥ÀR4œo ®Ó$aªË NɉlRHǤ€ `ˆžwf…BFÁÑ€pžÈarZap¤d'¨¬Ó†òp"ØÂÚây˜óZ ïŽÞGvŸ„Bc˜bðÐCQ0ør[² ïWž1t8kÅ\Q¡@‹Š3–h{ÉU݈Uw@¤¸˜ ûÑF®‚#3P ÑQ©ºZÅ]‰Ê (Å57õÚÀ8bÀó…X Jµ¢`•RÉtE§ b4ÖqU AÇÎôV&5wY…%l!EÈH´™ßš*BÂ7’vŠl1:Ñhå#  I Ì ãzl =¦֚ڨ°šu.iJžc²W¬£&SñZaå&L^±@ ºp±¤³ã\Eü ÐCïcÉ̳µ9*´lÑ¢‹»•&­³ÒÒöªð4h%av‰[uü*–š„Ù9Š ÖËÐdCHÚû ,ªÞ‚çð2ÎÐ:É%Ù¤o†aÁØcq•iÚ|ýDn!òÝwPLÛ ÌzÎ^§”Âù0o7qû%VbxŽ•&® 5Ø{Û;c;ášð °¶:´ebü Ê/&N3—©SdVíĽÜ uAºÂ™/߬¸˜âáQ™Ôsœ¯nÍž³4‚_ú"G©„$ÃÂYÜ¢EB,χdNúQjàyÝSuBðrÐôÁŠ¢7²ósÒOŸT˧«¨’£Ž{Y.‰9ët0üWö¬týUeäTÅ€¾”JO$B®j2°ÕL›Æ>ÆÖG0B‹äb¡R? bÛÂELR+´8߃1ý›!an÷"ïXˆÜYMÌ0ñçö覨~ûD«q{• ªÌO;Œ•ãƒiŽîØb•£&;F°"Gž ¶Á÷t¡"¹EeøÊËtóª3jË2Õ/+OŒGGº{‹ÂÝxU¥s+Z‚êIó™ùð®Úz±ÔqWXÜYÿ—²$©bUE!Œ1áÖ½.Æ…hi4«‡5ädšúJWÉÔ4< ÖG† ÎŽ4>ÖÙÂæâ;6à—ƒ‰Û´Œe"¢öWRÚ{æ¸:t;O—/bcŲ˜nK¶Y³P³ßÿ’nøªÀª8¶> 9÷Ð!¼ð¯@Oôš#™~>l°ƒÿùú^^}Ë/_0±9¬"eS鮨G #©NŽo ©À7[.Â:Œ²Ó÷[Xö¥9èt¡©c+ö~ P½·‹@îë0ŒžT¸EIÑÚXÕfùtEQs4«À?`;j™É›T"õ$&eÐu™US0EA >£™å1ÌVÁRâÀ€Kª)èNc$÷Sn~R# ²)‹ ‘<Á”¼›Ï4VcóV´v΀0ÅÚÈŽ³l ÷TµºÓœSî¶âiˆhƒ} ȤÒ&5/Ü“•5¶W9nçOa¡~6Çü§¯5wsÓÒ$ Iµ0½…IŽÍ‚ „a¾O0¯‰hæüT©¦ú}Ÿég ¯Ìwø¨b±ð×0;JH: Y]S_è¨)Uĉ«½¦NÅ:'¶©Ûò3ÈÁ[Q ÄÖqbDå ,°[œÔp+QõrÆõ s( m€gmÈv¿ð028fŒ9}$^qChKbpTåN Þ¡º+q.B0õHbøUµfvéìD¿Jºw-­­\Uu {j¡*”‚bÁpšT9‘ á6³Â>Lu©a„÷0=¨tÂÆ ÄF±ØÆ"9õlP|èÔ( —J™äD¨öOöBå@š‡b=P«X( …¡ç9e¾Ì #ŸÜ(ÂC}"£ñR<©X4e”P¥iÅ`ðW˜f÷Å…ÆÔ­]©Õ0/X,¼Ò¬Â.: ¬P]îÂõª&CK(õgƒüd“‘Î!™tÍK’°Ç‡2ËJd³ÀA™B­NN¤~ jÃËF³šN·VÂŒ¿ n?I‡Á„\Ÿ¯8ç50¨³J\©ló‡ìDL¡yª£ª<pÓˆˆtxÅ~ÄãV õ²Dq2E¥t:ªœt“â +™=Tc¥KÑu”íoBÐXANO×R RY D¡mYejx Q}ëH¸'j|œ·ô"úVíÔ4™W4¢(]uBè£B€VêÅæ½žìU>¨Þe‚wâ^¨˜ „òh¬@³ÇS¿Ô7ƒÉDÚbÿKë9f[3ˆeÉðn’,»µ“•ðË0“äŽÒË›Š•_z8òSY¨ò)ucX¶6ct•œN îZ,:8'nÈ"›,×VžLŠ™3kmØ Ì|â§Íærk0[ÿôͶ¿uÃ[–Ü/‰¾`¸5·ÐN¬NÜ ¢¡…/÷~î%\¼—Aª†íé5[m©"Í ßX¢œf”QÙ­H·Š(ðe´¡– ) ÖêFF†kùÌÞG^g!r›¸<½m"Ž,Y%^ ¤q'l:4BŸ¬zóqhè§|‚ŒØ¡ ÖªZm_L< E õBümì¨Àzózh0Só¼CÐeel£,ˆ×/’Èù•¦œTMh)Š”ÌxuLðR‡K:ÄË ‰`gijÙ:êDþƒªÃÇÅÐÏ?©qÂoyí­dØwÏð…*ý‘œxø‡~N$ˆ#B¢ÈD ¥!b'sõ*ZˆÙéB¥Ùø,µ¢?ÃŒq•›õᘡ¦‹ w† âIàÊ`/^R=ÒÖ%ãû&3p³~,˜æ¬És雿¨Ç™ ¢J†õ!?‡Ø_¬+1Í›NúîV¥uf7¤b¸+NN “i¶ŠÁÝtXî7ûIõwA4a.™[$pج'rÇÒe€ÕuHÍÈ„oŒ:’»‰·o¡éØLe¦ 1†ôs¹uS\.΋¨"qe–ÙÞ¤A8y·4C§—Uc°öJjAÉ0³½?Hs±”••³[ üƒ!q`8IºÐ“«¨ÒŠ:·¯ªfÖº~ ƒÓ€Ë×(œa16j¸3¶D-Ú/U¬Ê‰Aq_ãû)ÍåT‰5ߢ<¿îˆã9&绸ç2¾M\þYejP{¨—VÆáhófå ~*—&ŸB×ÌÕÓw«³¯í`9ZÌ>ïƒ]7Ö^fÑKKžc=}Ég‹Ô­ïŒ}/´å™-…{cã@~Ê–~Yn^èFŸåãç²V^]}Ó¿Xfƒßu¶›Õpò"V¥ëÏÈJåxܵ•ùè%Óu¾wÒg‚¹%%±9j¤†ÉL_¿=öê6ijUÚ¡L ®§}³q‡&±ÖH²Ò¥gÒíÙÖȨöú™¦[U'4ƒB|÷‡m¥ƒÓÂÔg%†ÿ˜Ð13°ÿô—)8¯ox7:ëÎý̈£,rxª[œP8 r¿uM_€Áðÿïnåta³·í¸•šP{~ŠvjV,b´,«âõ¥Õi§¸Ýh¼ýP¼zÉÿˆí7Õ_Ï8â÷ã¶[­ìŸ’ºèX…ÎàX¹”":oå:cÃöE*ÚÏ?$›_]};,^ž¡I~3ÓÄœänÎÛ34ÿ¢Ä‘Ä Q«ª©\$«ð,®Ë½ŸùÓQk”Qg±Ì*s$a²áç?8Œ—WßCÓhЬîZ3Ë_f³™àãvÿ±JÁÙq¯·v¹ü`cÒ›Rñ¾}6m—4݃¶e“ Øy]òµÚÓÕ^Uøtµ·Î=“S½¸³±@Ø|I¢û:^çäד9–&c¤c«V8M';Ù]_3ë„ 9vÊ“4pÜnÈnþ UJ¸]oÁ¼9Îê óQõ.dPMSqù„X× '`f+:qòTMUf)øÌ-nÍ,MÉê ©½1ÏhE»l …%ìV1¥­PscÿÉÉþŸGòÛsÂ;ãeRš:E$¯Kd½åûí[½oM°4–;ýVKE_BÚÅÒ=k_(ê.;Œb'ìíξ¾%û² ÂðŽWWPöò°s&¹ó ËŸÿPLùÕÕ¿®ê‚0ªz^êr¯ž˜«Î*&'”/¡À“P˜ª¦–¬Ú°Uà¼À¶P[iÓÒ<É0º¤üDrj%æè e²îÝš"ÈÓ9‡Ëì ³pÝ×Ã./¡¢©Ȯ]f à°¶27ͰêÑaÚÒJ3/„æ9y–?á0ŸpåïÌ åÖεª Ì´b/Ò‰Uqqf¤¢ê³¶°nUp”¯BX¢Îƒƒç£ Ï*Ó«ÛqiûY°Y5oÿâÂHj‰‹'”Üïû¾ —5Gr»žGòÛsÒÓ´È„íœèª’Põ¡@†®=nw~ntðÐ%AV  I¢Åž'beÏé0È5pÚzg®Ô < ‘U íi×t’–ïB–7+”¨zñë3è•éWä6қŚt¢º8È5Ö` `õŸÿ]ùêê{‚z•¦— .B®©îå—*ýäÓJd¿|J V¿êØÍbÈŒ#_ŠO'•~ˆÑ¤,½Ÿ…çû~ ɶN˜ôGi)­bÌ‘™E‡ÆÕy¢–gSUfÕ¥«VEòq£[«­âú$ã›þ³I¨¢ÅV€©\=Z>9Ûs%m…V{c ‡¥Os 3ûh¿‰ÑÓG^FÙ÷ îtij\J9r'¦ËH–÷êé ãÕÕ¿Ëg)%AÀ—ÏÓ¦¶<3Qæ¾Ë\8瘌`µ¥Å,“ÙôÙ›_K;W¶ÖX¨ˆ-β×D6?F°³Âˆd¾~‰c®èDQÖlX^é®çooáÔ_×; ;9¨)H‡töOR§>eݺ)‰!΂Ì6<Ä,´µÛ@¦$q­tȘÝ2ŸgÙ,[KåP½›õN5œyúû¬í][íkâ`Ä‘XGÒMø.N]:Ÿ«›—Þ3Gùü‡ôžWWßc€Nuuç·t+>ÝT¸® 6U5bµU/3’Ùp‡Nqý´ŽšNɲt$>ÊÒµ¤í° h9 tó|,û…F•$ˆýýƒ2ª*È‹J7æ±üŒßXæcÜåÇ©EJ‡ÔPXœî®]zÓ?ÿP¸óÕÕ÷–$V…)æ æÁäkIxH¦¨ÔG/Ï]â å–×c&hN¯ÈÊ}Ø"ÕÊG¹(nÓé0m¼Ù^>¡²N'ªmëÌþTug*²¸qº§&ïèÞ‡•Kõmí^&‘ûDëžLQYû›öûc>àÜ8uŽçùüåÕ7iîM(’ñ-›vš÷Y®0YÕä1Õ8°; °\­¾@Tö´e¯nB,yò•|Ð&…Âä7 ØÏ»ó­H+7'Õ\ü7Í}át›‰®Š§I;ª€Ca5Ο$ºaß/®vùˆ¶cÝþn<´ò(^«-& S õÛªƒ®öŠÎ\•4™¨8ÐÅ$xn÷ýö­˜K‹§âð¤[8õ ðëN+ÒbñVÓ]Á…};r ™[’G£_[¡fš²*eÈâØ˜áò“MÙ‘ŽOÒö÷!Ÿ×˜Õ÷STs0Í¢{6>û11¤üé/Ó{_ßð×i5®üÙ­æÞªÒ"`ȷʶ¤kx -åXúÀFÿ¤a4çØnkk «“»•ZZ›òœ¸k³Å‹·áTH ?ýeºÀëþ.|«ªøVÍÝæ¤“LZµ™ÄðÃøØ þ@ܱ_ŠÙn XÁ•/¨ß#Ùáfîªõ$Ja>X?¡ûNfÎLc𧕺ƒ ^èB„âuâó*õ×™ÞÓ«¿U«ôI:;‰–&pî'ÕÒ[”ŠŠk_DzHñùÕÐ}uõM£7ËÞ\£˜èžGñû$‹ðS™'›Ÿ ØKóû XÃÌ99]>ãì´™nô)‚e 'iïÞù½Þ0K'½ÂUùøù‡Ñë‹«^üo=(1N܇:ìø&ïòèU…ë2.Lr/G ûôŠ­§X¸ù-™G3ÝvÄVëæLŽŽ0H¹SÍXbLÁñ€:Wöy ¿Ï®¯O‘aÁyÄí?À‘²†gEÉäš'ž«UXõz÷N¬%NdW6 àß@òŽõ•úë·Ÿ@ˆË>ÛiŸÎ6Ä%+iCü©SE‰œ;uAx?YáV[²éœ‰vØù!8$bB*vÂüN))f…C§T=å1pµóczM«|ªú²‚©b{·ò¶qm'ëC*ýŽnV)Í>>ï󽱯ðÑýu kckdAèÃ9îëÝç8±mõŸB·ë¿·åm½NV.‚uc ’•)®r ·›·–+ÂãN¬çõìU“ÂMt²Ž®ÚBîÛ ?egÖœðÐW+Ìâá9»ç­;«&¡,11gç|ék¯ËbèŸnß‹jþ¹°fK¶°—ÆŠUÅžâìNý;™éx3–Ųî8’ËÈöÆœW®†&ôÈO´ãÆõ©³†=ë”Þgik>|UÁé©nÜG¶ÕGW…WélŽä2²­¶ÍT°Ê9ɽ¨”5/Öö¸ßzá6¿ïr®Ru,§ë2}›‰¹º8A¾Éed;“pp𳧲ܣ% ^F¶Óž@ê£4og»ê2°­&Ø= ]vËÉ\Û w÷‚îþúý¸lóHÖÖý~ÜG¶« KPÚÏœtÐBÑÑ`‰A]UHíà’ó ‘Ù˜1SÜf/,lÑ|™¿„‹l# W9¹¹ôÇýÖÊØ™‰06Hܺy»u0¾$Lã‹Ía­²Ô·aJò¸àÜʤq\Ƶ•Q=$ w 8L¼FÊügÊ1ÏØ¨-eaû•ׯAâ´qèbVe¨‚Ú‡÷[7§„Ð _E$ž–‘½2Zˆ«,I¸‚Ë½× w« ùü‡e¸¿¸ú6Œ’ÅÏæy`Qïª\7a”Y§„Ä2ëJÒe<¼:úB!|2]Ä-cSMþÄ&“©p‚q²“LÐ#Œ HBGfþ….èàqtò3TW=ë°1>ò:¨!¸Z·ç å šŽáAdÖý#uo/ùÖÁwÈò‡Àhƒ¯ç2ÓG95”ðsPÐ`¾¶Ûw—àU?/Yí£Æ×UŸ·Z2˜B„– *‰Çê°Ó¦îÚÚïËᬚÂj¾ŸvÌf.8*!åH…r/Š$+v1Çq›ŸÕ† r"µs7é4çg«IøcBXÖ›‡³mub$ÕÝ/.Móq™ŸÍ”ú<&r—13בüv„•è™9ttÍGL._ ²²¬›‹]Gªež0Ç­î=èsº}ÇXͪ!Uxòà•¶hûýÞ­utŒÖàŒ3]?Ün`›6ÞܯnsÍÉV^Å3yÌ.Ûê1‹*¼'Ê‹Xéì­¢q¥!·ï÷þ#4Õ ÍG™•mc£¼Ý»•Ð%Xp®µI^6‹wŒš2f– ™1¦¾Ù®6'ýš+Åo¥ð¤„Å:TÍ‹ø×¸¶ê!Ug­<>ƒÀãA èGuhááqŸ=V AÔ¥ò¸Äƒ~íÂËÀhܼÕ/açƒÖAeÕøXâä"uŸ†­8ç½(õz|Aºå†þ¾–‘UEg7’.±Yd=ƒ5]·‘]}uÎwF­Ÿþ0_Ý‹«oûêHZõi¿eÆÁctQ<ˆ† mQ3©ê0IÕT‘ ú“=Ô—FG™ˆ4ëh~šyô\£šùÞR‘%ˆ±fl~ìçxX’‹Õc)v0÷¶jŸc/ñl¯i‰Þ÷ÚV׌â‹¢o{m3ÔŠZèI!ÈíBOÓF¤p¿uëƒY)ŠÃž~ d+ÎÂì¬EB·9ٌò½äÆ$·š_?· ŒöØá¸êIC€JÜïÝ™û7­ÓEC·•üGÔ=¾¬\±‘$¿ V6_·{ÏùÊs¥žÿ°å‹«ÕctҼƄf”N‚?ݾÕ ,q½dr Ê!ìÈÑF«kÅc!å]îÝZ+ð'÷bÆÓhg4¢&Y,÷[7o¢´×TÞ¶Ëf ø¾¨Q>þÎHÓft–T†ÿžsr™£ \€?~þ¡Íøêêßu=õΠbÿçfD®Imîvû…aÔ‚J€?ÿÐ_]ý«º±•úÓÌm…(à 7NGSFFT9Ì1·9û¡VŒbÒÚö5ýa$¿/p~Ò1 Ð ÍwÒHÚôãçF#/®¾ [¼„ÑHç>ï]EXç³³¤ëÓí[#òAžëv£¨­´ì˜CxŽÄqn€º$¤íÒ¦² Þ<ÛÁã×v›¯õxܶ5×|‡§×²uG õ‚ù A;ò²C·Z]‰2õË-LxNÑVÝݳÀÕ9GÚ)>p5r©Páà~ï¿ëÔi¹aÏ·Þf³ˆ‡óó$‰‹£c#9àüh•¾§‚x›èMQâC¨õÂÚ™ FÄ!…*›p^#@jq•ƒ~BÇfeÅ0#X¶¦±ÜJPv§ç&t$&»1õÙœcLGK[}ÍkÆ užX?Óù€Dˆ¯Á¿0öÜNÿÔ±ês¿LãmŸoÕ¢ :rÛq[ýʉá‘Ùçmž’¬me#¹NÑæXP“d® ~™¢ÍQO8AšNÑZ™îk$ð:ÒoìwGêH2ºýöذòRtZ¹¸OmBÏ ì“?ÿÁa¼¼únõhamÌB€¡Ñá]-O÷…6ØW¢mã®2ŽMØèybØømˆ‘Ä´–Ä´ãàꌦ§ƒ}ü˜ÓxU¶GdÔ€Ñóhaƒ«öÁ}{ k¯%ìºû†ƒÀ‘ŽÑô[¤å4ä;G?Rb¶†¥Ý‡¹—u¾H À{ü¶žmB6Ì|œdÙ(Äö@GFƒï…Çã½ tÂØ×Y%­ÚyMÝ1óüÆu=ë,³2æ /Ù=áA8Vá„t–"àG'Ï«­ÙÁ(œ„ñ[gg´œÒ€)CK3|Eætƒ©'qksцEý¨±öÓxDÛ¯òFåÄ(³®ë<ÔîX|_?æœød£@h¯U+®ŒÉò…£Ê †N98^ð-˜¸2?øsžƒ«¬|ɇóñ–ЇµÑïÕÒ¦­™‹o2‡Õ€5ùc_Ň#~ƒEm\³†ŽŸ:}{Iú'êæ¤Y¬,À2.Ø‹*­”y?Ü]¤ñAú~…¨Z9:¼° xà•ü&¥ó—×{?@·ú~è2_TyÞ¸M+Û\»Î£`­…3t0•n7œ Óí½9ÔC›)kÔzYÕ “=Ím‰–Ã*ó*'Oœ`n‘äŠö¨H‚Á´qGpƒsÌ‚¹ɰ¥¢íÈ.?†7±›{­êapñ ¶ #‹o<Ô§j(˜Ð̲|g«‰œ–5Ó˜D{h -³!~|Î1šÈ†ì:n–7Åߣa™š"‚I³6"¡=š×ù`ïéà»»UÉñëa™§ƒñá¹UÔ!ƒÅ‘b]ubš²§;Ë%eµ¤ƒ—ó4¿xð4ïVhZæø<{ö—”ÈÌò­Ì×õ5ÿ3ì ÎíÀð`—ÑÆA/£]ÈO‡øCÒaW24¯c¾zå?‡nê#HÌ-¤g­:(€S“45s‘À]@Åap–8ÞÚ@òäŒg¢¾Úà0ädÙ;G?4ßqÙ;ObÂÕ‚‰ô.‰©‚ý…c´EÊȘÐ{'–à˜·ûÀp.Ñ£lÁåQÈMŽ´¹ÁiÐLbQ‚ùð÷Ú™L>ðKüàÒÞ{©õ R&™ŽŽˆ²k¸ü=܃ p4·wÌτǜ «1ñ<û|<èX“0,ìÀ¦ûM0FžFí\Kãk›ÞæºÔ08Ó­#IÄ'ìÂ/N'0’Ó¨ƒl˜ÅÿÐÃB‹ËѸݚJS}j¾{'½ûí÷dÛ™ —‹”†v>›Sä*%H&C†«««‘µ§ðÀÂ<|aÍÖÓÆg–4oà$V‡=Ú!ršÙ5ˆ¤Óšje¶¹èž5ÈÔ|ãñŠ˜1H¤š{«&~ÌŸã¼w#9R¨2nù0°{CªéÀÝŽi¬£)ó^‡ÂºHä@‹Âi<4—˜4_XÉÎòzŸ„~ ¼3ŒI•p)GBéÖcˆYwxf€Ã€àÈJÆœsÍt£ÑÄ';8!³8Ÿ9@TçC³¡ø–$4¶5`6xZÓ¼k8G÷Bu(³L‹8ÖpØ+ên3û—¬€ƒrä{½“ÏiYtl ó,<Æx¤C©À¦ lKÇt¼a<€rü’M>+êoÔXätx5  Ž q¢$šÖùmæ[ë-hyŠ9/ÙT…LÙ À ŽüSñ»®Sué&Hb}%µË+ˆ”‘ -¤h5՘Š.$ò@4ù'.Ü‚aHATÚV„»¤g©,É&>ïn”·e,PjQ;_Ÿ˜YÁO\t¼ÓuвœLŒo•jƒÎò² s¥£•$ïj·çÆ0‡ÌáÝSzÉ®bæ·•ddW&c„°[jbBMÝ\°cöz·•7YÖÌ{1êΑ4úš?ÿP1…WWߌJ”é$‡PZŠKƒý*aXC8M¬S¥w«¬ªã ÇüJG! ¬jèl¾¦j’¬Å ½›©Ä±P‚ Ó½u|­”ßå1ú¦ªFShâb¡2Å´'Æ‹'|‘I?Γ±@ÑÑß;’›eœ¡vmõ~ýr²îcŽ£]×Þ4Wöe©²‰¶ùå>u½FVìõ<°«¦"ùœû*>i@³Lp:ÙÌ“¯»¦ˆò¢ÁÉÊYJÝz.ß$=ù,ÏbÿŽ9/ƒü–š ä!¨ˆà¶mÞRÉùVÉXg 8Ìú¦ ýŒAm… NÂ\ål7ý*ÏqB, $Bëó¬¬ /‘¦ û¿ikTOÙØ1Ϊ!¬ÙÛÌõsZ³u×VßßóHŠ±Ô D¡Ý{ïq¿sk¾•*¿A÷Lå,Óg#Ù;TŒÁRTîfŠí5Xêý_ázÿxé=1œL“ñº€ÝŽ#Å<ØaеÚ^æÎà¥ÄªØ/Ž Ã=¦¸d?o)*€ÓoG9µy íó’À¯®¾ùi^žÂóÓ¼¬Ð%aƒ×·Â|ìÖÑÅ‘»ͺC’…*éP'¥˜JéjéÃu>1ˆõ©Ž”¤AÑj_£€º5_Ê%¸u$™~¢ƒ,Ž¡+M¬íùü‡`鯮¾9}A>ºsú‚t?Á*›4ÖtMs ìù©ŽÕX=[‡#R]$ûýÈ]†ÞÈÙ–N3 ÏÔ¹eï¹I|9ãF?Ʊ|Ì`u %´êbþɯ–^ô]öÃä„è mƒÑ¢Ï ' «%o<ÚpÒ4Ö¨ÀɯÓnçPߟ½ íjN°õA£ƒ¶ãTè7Šä6왃xYïM9†=³% äܤ›ëylÀrÝ„›…^Ð5ë"mU½TéÀÚÉ'LdÊÅíÝs$ 4¿6ãwa2wHÿ9'¿ŸÌ¨:¨çœÜÈæ¢LyÀ?ÿ2õêê›Ú@œØÑ*:Zšü:JREDšË!Ë14è€wî¸hYÎ œÄ­ƒ4ܺÍ:è …»+Ù+Z”k1À]’uB q¹M¸Ï';X[2²¬¥`39Õ;rRéÌè5¨-J€G%$Í´1=‘;#ðöø^è/-Rï"cJM*Î[¦ï#ŽïG“3àS×%µpâÏhÑÉHäñxšõ­@ÙIV±‹Ø\׋¢‡8XÐ…El?7"jÐô§Úذö¸ßyQ7¦?æù©¯®¾¹E“À×sxkÍ=º+ÏðÒ¢žÛn(Þ\lÆÅod½u ?§F}7C„=fsÕŸ€ÌgÛr‹{ï.a+ó éÔ½*¥¿ê$ðuîa v„ 2#ûöÕ¤Ÿl&QAÅѦåˆ6ýØ£ƒi,.[AÉùô®­@ù¡è÷4Å×ü$Íðtž?¢š¾ Ÿm/‡@d—;*‡pNÑ&“È«k ·ÙÙ¤Ùù¦ØÈ\tpMV)kß彃rg‡¨œ˜mÆ-Çø¬mF[U´Õ]ŸþÁOv˜RÔYЉÆ{[‡zªiƒò»a˜å©­NïÍ:P1 &ÜSjÒs ZÝ?s«*æ|Æ4mš“ò6W)®ŠÞÆYàB7úøù‡Ü<¯®¾IoeòL=:€>8ÕtŸ”Dñ½jÍ)|-µÛ8$Î¥ÇÓ«côOpU+× —Oíù}ø««onΪàßüð Ôˆ•Ú©NܨM‰Ÿãã /IÅü=lC>!㟙ñÒòfHŽáü*qóæâ€…~&²jd[}>Z#¹ÍÑæLÖç9AFÒË,ÌJ}:=î÷n-3l™¾”egƒiO-ÙÆýøù‡dÛ««oò&ëœ)tÈ-€Ì7´pl Ӟ͚' é“í,ˤ8X|xšSNÎýº?|óyEÔd'7*®•+ñg“x‚ÚíÎsˆ³pÊý_qÞ?^zoº]™[âä›9]S“ÐüUj4,tÁý‹àbS)Ú[M3íØ«ïûTm®>{Û(EЉ†Û %TqÒt±5CÛÎq‰ Ú¶ÜÎ ‹6¦‹sØ›_øü‡|œ¯®¾É6ºPíˆËcÑå.JÄ ²†FAœ:Zó€ËÐÒì ž»2S=|jUÒ”:’R3b][¡ÐØE3)­úÃñÉäŠZBä;‚Ò8n0¿_®>Û$OljrQÖÁnÈv¦¬QÚ±'`qt4'»'…U Öû‹÷ ¯12¸º¡Ä‹éÝò'}?î¶y{Uñ>|äiL¿å¹~³yþÃÖïÅÕ7M¥JÎÙ@»&-’ÖF³‹ùôœÕôiY™”HÈ>~ðë:ëµ=ÿ!¡òêêß—S(x¿ÏŒÂ-r)ë;6[¹e• ýj¦d$§ý¨Ä~’¡’¾°YÏM µÓ,ì§*'¤+ÌLÏ:ÔÓz–_rü„ÖѬ¼€G¢=¤]œ–3ð²ÍZ®ÜÓWnÎIx¦L¤© ]xK•^–û½òcþ'2]ÿ½I—^ysÌÙUZ- RæìšÃ‹ÅŒàh¾•Ë æÆ|þÔÉWß«³Qtd«øÚ72êè…Æ"2u¯ ÉS?¬eå-Äý{Ä 'ú«ü» ìºhÚO×;uVd¶ß ¿ïö5L‡6Çé´››Å(ZÓ9‹)Í-n¡ßãÖaµPd.JkÊT8ñ2‰œ~SÍËœÄÛ¿Fºô&ñ*'¯Sˆ*NqfÙ^>ʧ¦l/4‹J²E†»•ŽÞÚ­~Í¿wK¡ÐÆ9¨àíÀVT¢µp†3ó_Éíps³º†&gb·ÇíÑ—ñþæé]Î+™éádHF.é’c‡tg_f!ëèm–ºP.qMåVÒL©¦W˜¤pg¨ÇÏ?$Î^]}óS*êç—TÖ¿¸|‰¥úàUf@[¬XÜÀWÖÆa.~õÖcFVçB¥Ó¨ZC)X‡8Ë~)Û6c°<î&ësý‡uTí°¬ìY‹úë,ÃÙsU¹ÛäÙ}3xЬ>MÚ÷ãF ÿˆê¬ÖvØžMku2æ\ŒfQá…Rf1ŒJZècÕº¹> ]ËwDÖ¡jø¡:4Ôge¶N_QÓQ/׊οXõ;Íç¡穜;âì0M?IÕ`k5î¦}¶uzž¥õoæÎý(˜d\­šwIظ¡†0…Fò,¢§vl‘忬‚\’'«RÆ_>bèwކÖÓúˆWWÿ®Ü1¤1Ú²TÕ-â$;Õ ¬LçÃO[2çÀÕûÕü>Uzqªƒ×0$½!›«‡ÙÓ½Ã|¶Jõñ¡­ióv6[Råâãé•WñŸOüGðµ@äÂ'Áýº-V'3Ðþ"ªZ{?©pÕ¾]ôåó•,D‡3I†B{÷Ù':Ÿ^quÔlÈE$„D¬ú ªM¼¼ã8׬éùyÇ_]}›Ý—Ž•²_b%ŽÒ…ݸ+‹¡ Yd§¶4Ù)hŽ16è¡ÀDs¬ùYe¸»êRÅB,nW⻕5ôPjohoŸ{ÀêZâXÉÐPÈ, •'cé¾Ì&tü®ÊXvû1 ~ò•]µ»4—¨|>Tû£`CÜôx„gË«Î`síààij˜©œ£8«}!*\¢Œ¡öqÔ!n(³×Õö`‘TŒ7Ñ­b¦m>n±® û_¼á^ÖÑÌÖÁ‹kxÁTiDaQ½“Ç]£8¨@Ѱ2°õ­MDÓÐø¬³Åò› Eæ¢N´@™ËdËTÃ3ÌÇ"7é]Æn8”ôÇ<áöÜ6[Õ½Ÿ#¥þÐ;ÚÔãžÿІ}uõM–˜>êe ´SY=iá£Ï•ó…oP§jõsÝX”ÙHh"Í;ÐõÅP­¶¥ò\ vÅX×wlvÃ÷¢?x™µVéNÒË7U¢ªpö圂ŽQÃtNÅ,¥£ þ?4Õí,(î益ªŽ¦SÉ.ºa–*‡s+[šÎa F=ð¹ ”*K6J{ðÞj¬¢¢ªÚ‘TÐŒ–Iáa—·•à€ªkN¹ÈR¶Ò*FÀá—•1Ñ(aŽKO¡ÙØQãP+Cà‚¬n f¸¬Â­Ì Ü±:&ÞGš¬] /3¦rÒ]QŃFÇ ÞÏâ̵¤¨3\ÕâÄÏÀ¨}|­’·hlÌòNNÅ}þBG ,¬â( ž–©Ú/"9Ž)š&”›†æJïvrú:ëaž(ÇÀÂբޤ"»eØ$8Á¦š¨Ò¿ Yg›óB¿’žƒ4Æ¢“­k¥ª_`uÛªÛ¹‘lÚVeÙ$ã«ÏÚ³1ï†Üã´¿ˆÂQ¨°WeZÔ€öÅ^ÐTYJ$Ë`•ŸQG'Ûɨcj_pà¢SB£L!k†*m˜Áëì Â⯛š™ïÂq hÒÕS¦é—µŽè(º}˜Ó<%¡ÔÌ6h®Ì¢‚ÙS\ ‰æY‚ŽÊIMÏ&jjèöè¼N7P%ÊìdXál™ñ¾ÔåB ¾òj+jZ¡a»L( gΡ@;=1U{"ä*: [\ÜF‡<›­&3^ˆ³ÌPƒ\€éÔÈÚñ ¹¶fGÅ“²ã¡>]ê/Î9êÑv°Yu¤òm³'æ1.·øõ-žå.$Õ¨Ægò2´ƒÑ0AÏÓ§Yp‘Ì–ˆâ&Œ7† ø{4a 34ržøäáAøù‡øôâêÛÈSd4zLtÊQÒa ÁÍ;Œ}£ÆªTŠ6+•zÔŒ÷µš[ŽÀÈá>«°ò'ÎæuðN¹éª¯óÚøû±j&RÚËÏÞ§R§m ² ÈW]:Þ÷Y¬3!EŽì,ž¨"`FýµßŽ ÿ}<\˜GEµ‰‡#®Gmê¢ÿž/ÝÒš 'ð!QJ––³„»ù™uêÒ¶¹O—ŸÌÜí£Ÿ7ˆL^´(ku‘ å]†çjS¶€ÅueB3¿ž:U;J æC‚Ž}»÷\êsAç?´S_]}»¨p—ƨ¢Ì­9„ƒO•óè› e MEc§8©NnRäXV·ðç­56›t²&p:JÕÁdaVœ‹™';•6ӃɃ^¬Ø@žö¦R½U*Q«×! —"÷' @—â#ž Y¬I¡§÷–ˆÁÊYªCDð:M²úÆ<ï)®É]Õ™?ÏŽÉgÎÌzþÃjX¼¸ú×c^$Í«b^¤ÿk½Ø3ܲOF˜ÞæNf=ã©yç{Êä/nLf®Ú}_¸UóýƽÁ€–ÕiоUñÔñbÆÛ8ûÓ£kö0D‘N…ïäÑ|Mc€à~ý˜D´I+ôu¶uš¼:(5l‡:|˜' ±ý¼L“f,Lḧ ¬Þ˜é¤ë–ýHkyÆ‘ñXÂ’éhÊEéýÊŽ<ì÷›Cžë©D´sú7Q°“&XÞpžèH©CFÐæqU°oEQå"nIp7 õ÷½zR«¯×HÒíHï† &þü‡?¯®¾qLÚ:p†ÔÚ€è@ ž :KÐTK<ÆNþ<ÅS;êļ€l9y’¥¨@-ž¤ð8B@ˆùÕyάeI_«~o8Cn “®õˆ¾Q ¿gv5{f t#/:›Pú ò³‘Hüì£7zŽÚm$ñ©®ð¸‰§? }þâê›(d@Ï!ðL¾î/ð שçÓËÓ¬ÃËä™>8a¯*5tÛãÚýx€éCÀniMk1qÿñóm£WWßFŒcr~WÔi©“é # ¢ÓB¹Ñ\;…´ŽƒF%h"û¤ÒåâP~ É+=+zïÙ4X“ÉríXaFÛä½¹w{N·%ÀàŽ gÒäUæ’_µ¤ñçžØfa’ÍÜ Ò¢õ&Ó†rE|úCëùêêÛ±$Ó[4ˆy,Á©‹{DÇ3\û²ëA¥¦Z„°íþÏuÚ >cšõÒcÌjfÿI÷xD¡²+k81æ h°Yç:0ƒú ÎH—9CÙäÇ0¬¾õ4Å?Œí~_ô=±a¨ò·t‰—`¨ÍrÍÜ<Žvü“†}:Çl AºìXäÓ[ ┿ÏHA|uõïr–ØFf ès’è9)qƬðEæ«'ÚHœÙ꫟OÛª..c¬ë¿`sé\=]#ó`Û©«ÏöYÆÒ2 žÿ°2–/®¾7Ÿc>‡ˆH…33·­³õDñÞl3»BÌØ©IéÊ4¡ !HþìçŠþdµï¹asÊ9‹‘¸"ý“úè¤l+ ¿>¶V®’¼vºÛqý=OzàÖŒ}Åm¨ªx'èïÒ·q<͉ʚ)j%ò°Â’K(u«^mJã´±ÃEq°úâk³odÚþëÓkMýÉoÃGn_›§‚3÷¯«M§>ëÆÒA¥ãÍU#äYóœp¶oòdÑyþò^^\}Sç=Ã8œ7tfÙÏÃ|ÛbÖ÷»·bÖŸøLãrál7‘‰ Ñ<Å 8œ{Bh#¬³³v”\mÄ0¹‰zçáQÊ’‹‘™šÓF,càS='– ~´Y¨4³¨¾g@O»q¶·z%ƒ˜© ´ÄGÝrïÁpˆºt ¤ÿ‘ÌÅ vÈ•3m|X¸*cåCî÷nU¯Ìveo;Û¶O0 ?§³Ítìç?ì`†WßöuÒ 1ÇÈâm6•v*bc(yQ>:˜¿€BÙM%!s;”ÑT¥:Ò!‚Õ¡Æ™ÃCÿb‘$Ëc )‘ô‘ 8ã3J¸C¯ Ó‹‡ø°ì¤ÄŠêÍÑjžó¸ÄCŸHŒ¼ºúæÄe ŽøLQ„J'-dåK'-…¨Ž`/qÚ<Ð#úý1ðU½¢«¬¦Š!nL#ªTÓ6¢²ÈØOkð_` +ñ+ù:£m'I€ÚÒ1s¾føìöªÇƒh|R8PÀ~À„ø{·r.µË³Ò ²‹˜)´¾;*Iu)D;*,[ªeY|+;„wO3¥*s ª+Ý è(9“Gûná›{ñùð‹«ï*‘#‘KF-òT*¯Å+ìà™ç?¬xÅ‹«ïB1©ÅOEÖ –›2ëÀ ée´Çܰ63c®g{èE?ÿ«öÕÕ÷FèÛ[#4ÀOQ臡”©×ÆšÁp´7Ôq¢—ºj•AŸ$Y´jv[<íÓl‰• cþ3´½ßæúIôÄéûv•iQe¼”'{¢9~kj|ìB™"ŸOâC˜dpBŸ<¢\ sYIG ÷6Hȳ‰˜¿ŒM?&ŠÒùâÆÑ(†u ø•ú…+œˆ{epE5ë¢=VX"9™»m¼v¨’†¹dÛ¿Îcó0.¸€pÔ@±PvKk°'”$_Ð¥ˆÌÐÈË(ç…fòö%|b™ç^Ç®; #J9åÆxd/kjó%Â;¡›y"÷¢ ÌvT¢«÷Ñ):èE¾WaÓ‚`pÝ¡‰¢wDr>-8ùÊæØ|‡˜gg›B61Áózî˜Îãçfj¿¸ú6$†Ÿ ®#H céâJä™Þ ˆ1¸G"Hÿ¢^LüóV%ñÅÕw^BÝ õŠ2#œf˜‰Rózc¢ÅpÃ÷Rt¿‚µW¡ŒÄ5 Åâ«Ò•Þܵw•ýLEmyw0¹3'x¤a¥½‚Qg»¶¸I±h à\3LV³¿D‚Ïv¦ïŒçRâi{ѱTÚ£-¯Sì; ¥]—ÿSºÍ€ l$ÁJë (hÈUI—}6„²üç  31¤NË&˜¥µ¹‹ö€ÿüÃêE¿¸ú67@ý¨õ-Üï)±p© ÎŒ˜–0ÙͲ…SŸA2âPüì0V „Y8ÙîZ²£}þCKöêê»j}fSôÇ+¡ŠF욬œÛ>øÅº9vœ7æÑ›ÂÛoŠ‹”y ²Ã93*‡5aÄ…%K¸«ù"%E>$&¯šиÄ<ýa„ûâê{“ç$Åd¦ŽÉƒF²FÐ<‡aP°¹uU$Ü܇T…Ñ<¬-%‹éGNŽ ÐsF‹öb±£è›“ÓRµ{jWð¤ntà"ósF¿hs4s΄9^ÆT¨*¡rPÁ §ïÄ—4&ñuÖ½d*CV3ìöÔ=bß°ÌëKˆ˜ô熢²°M‰“†¨ê½–´¦ |ܤí/J2UÉ!±ðKJVq:˜”ìzŸ1 ¤¾`îUšTÍ X;L×îóVúîÅÕ·s¦© ˆ:-iºù gFnm¥ž­Ì(em“«Iç@2¡SáˆËìë>ã }–ÒD¶­ã‡"çô’†MhØ.Ûoµ‰ãb¶-ÑJ*BI²û­)< äù3 _\}› s–æøXï5µ“XÉ”†ˆa“Îû1Ï1Ù$0Ñ\šR&æÅh³œ”‹awé±z¬Â³³ŽÜÁÒÖ±ZNñAxOg­ûÆ”»¯baÊÕaôg êêÃègçξ4KkçíEÒ ²ÄšÕËE®œƒ´ ³.š-T#Ì&‹ÕŠà묩ÖÑ”¦zÇKÖ€,¿é_*‹ìÚµ²±*Ü*h$륢…V#™¹ñ¦ÌþfEz¤‘fYÚVܽ)Ü€Lå™Ò‰Žs £*Sj» (?~Øï÷0Þª‰‹ŒÕ®M‹¹•PNÌÈCñ¹Ñ²ü¼rƒÅüfõ–Q¿ŒÏN˜Ãža‘AÕMÇŽqÀ¦Ïgæâç¼~¨Ãé{C¹Õ÷ûE•yši“.ìsêÈ,KJÔq7°dP‹$ÛQ*ØZ gLmȆ¢2ã¶Ñê¹›<+VC{úC¡„WWÿ*•÷IÆPØ‘.ÍÍñ#kv²ŠkÁÍ p’í!zÝÅ¥äp"ÆCLGeØŠŒ ¹Ö‹i[ˆ aX¯7Yþp—{c1ܙؽ:€à©ÆÝºÜxEn]r{=¦äH_ U¡õòótú=õ`Bâ°¿ë|SIÇ%¹5Ž»À&º+ŽÆr²ÝO)µgkÕ>ƒ‘E°½}™)»_K_ïDÀ«= |µ·6R}Q„5V›LApK“üMð¥s›Ñï3Óz:+wLìl2ãJV™;tBP'¯Bé¾ßûelŠi®ðÈ`²—u hèsO⚇¶UÓ P3Ï gÒ5lÙwyîÕ±ú{¦YYz}Ì< #¼ÕþÕÔx&Bø”¤a4;uhÒÅÛ¬£û‹Ÿ²ÌYïTqͺP;ÍEô®¦HŽžàÂå9èI³# 1xx7X>´Ü¿ùh£|Æ,Òr³:O‚¤cr§<‘”ˆ>TÝ}ËN‘¬[g—Õy“ýjþ®W>ÏmýB>c¾W˜¬X ^ÌZsŽUÙ†'óÆ™h'…EühŠÆþ{)óD©6ƒQ¸z­ÅZÖÑX¬fõºµ ³Â›N)E û)•-á1&`ŽVA¦gÅ¢"ˆæ¡µ=Và ³sòÒ½JdŒ‡F3XÚn´¥›49„—6 …|«ß'˜åùK±qõ=._åcTÙ†Áå«TºFz,Û¶7®Ž–ÌÂÚ=µÊmÈ>ÄàÌ  ËF •töÅ'u~<Í&üX-wV+«Oqr*sŽªÎÀô©,[UõBÍ'Zµ(¿}´®’z<¿Ð_t°‡)$£§Îè¸cÓ^8F¹ZÞ©…8Úp…Ç ­[€P-z dÕ×,ìƒCÙŠ‚&j“ jÆU¤!;l)ÝM£ [¼jD™Œ?@_4æxÆÚ%*x] Ò0:2Ç ÝˆY;‹KÕ ­YÑO—™ŸúÿwmÉãJö_«ð *€xp³ÿÚûÿžG‚\º¡î;ÖtDG‘ M ÈÇÉ“x"»RGpÊ ­JmèP“p8ÿXݽ©ê 6ÐÂT'cL«Þ5¸8~ú1¨Rs8ñÛŸo©ljÇhRÍÊS(oªÄXôÁ:MSHá¤é9Ã*$B1÷&tªŽlüæÈò@ÆÍ0üJêÔDÏá‚ÿérÔôÎV©„ºöÑ ÷ˆ‘Ô—­Ó—F"jÒÃ4…I™`%dòÁ¬4íð×—zŽû Ï+ùœçÈMGC95Áó0wÕ@áÝLb:O[¥kzÀÎês}“ì:o¾¸'¦Pq@i‰÷¤hê&Å OàLÒh›0©¶9"³äÜE¯T]¤ªiFmŒÒ!-­Éü?#7½5EóyÎ;\ËE Ü˸¥ñ˜èˆ:cä7çQê@íä¹Ü }[Ò¹|ž”í%e}ÂL9lNî3™f*T®÷žX£ïQ1·šeÏ÷<ç6•+ÇÉ'0§;L²^zó¹–6L}NÅBŒ(·EåÍöÂ*!|&ížsþIš•tm{ìÔîs,§ÇQÁiÂûá- º·b¼½;}×HŸ ŠÅtU¬æ;‡ê<f ¨s‚N’Í_ݵÍR¢ÐguöÙ–Ïq®+\¦ð8÷5ô§Ð»Ï?ǶöÉ–MúvÅ0Û-v6À¦à¾{Êüž<§#æw)bhหG»øß°Bó*‘c¶¸!«¡gËyÌõ®š$ÜÎÅ“ Ö„ÀF[ü²Ñ m¬tO¿ 6·iâSËðD^ÿÈK -ì~¯½”åAtñÇÏ©©Ï®¾¨,«J%]Y 9]ƒTèÒûbœw—VW»¦¿·r¦i‹ëâkÒ¨¡%XÒâ)À;ÌÇä1u?y¸6x=)¥•AYûÄí›¶ÚÝM¸ŠdY³$/…2&n­áiP‚kÒ3~§ö0î·ÃÛCå º8‡óF,n¯ü:WÏb¿äï ©[‡T‚˜á8&0èT²Ê.…xªú½žÃä„§ÃÚ< uV¤‘‘/Bºð'/IOçLR)dEgN´\¢’é^F_·©NQ†+†}}±1?|îÁ<—½ï蹡¤Ä9³»nü“.÷ Jšmäf\rÕSþ0Ê笤”¦àçÁ:K{*Ë;­-¶;%TÒoS‚¦ÎQ¡uäÛ2PËïT €Â2/ê Ü=ªÅ¾õKÌ‘Yoñ‡‘ó°¤~ ’A…â"‰°—¯3ÈNצ±ÆfD=ZwÁºß,S³ò“ΣÁ^Yh4ûP~ÄÞýÝïqkŸk1lLuqk—ëô-ã„é¬ýÀÀŒ—ñUù7lTÄ»¿ýMUU*ÇN õ‘¬Jøz»º,w.Ôð‡Û¯>&ûîîÿeÿ~éåbªdT¢ÿ-­1§%þUv°š“4V(K"/VCùÎåM ò:®‡Ìw8?íŸÛã^ãÙÕ—¶\–7)$—˜®#Ÿ_áÞ$ñáêÎTó’¿iÒ—A´m÷Ðp‡PÁœ$zNyoJÆã10O®¾¸ê*÷¾ù’öu]#nGÎEVà€ÛãÉ ž\}±WMèðÙ+¹"·õ¶Ë›ÔbºP}ìãMZÄçåüFƒ_M ~ÎQ–Çãçž\}Õë[…ÀpÒëK0ðAHï{†÷´ã7SÖ]CTçúÌ€ µÑÚË ×b:Ôñm³5¾t²HÿÖ ¸¼Lˆ¥A5¾ZçÄWMT’& ÒÄr?7Ç6¬Š@2&ÙÝB\ÓQŠþ¯ã¹Ô“S»MÚëX–{D³gwC^ÏЕÞr³JY-áÀŠÈ•Œk¨B=ÏÐ]±™½C9<šÄïºp >@rn:Y]€–cÍn+40×½4Ì&C‚Eô±ž]}Q~ìñmàÊT %ü·ï66ÊlœË¨L¤qÒy’]»ËöØ÷Ë¢‘Á§wÊ«½û“§3^^oêÐæ=Û ÍhÌ"¤»þªRɰO—ç,Á—ß>dÇ×cmþôF0¾º·cÚÉïÉ]'+xl W…È÷ÀÝ"=}ÓTlæáîÅÚŽL±ÇW zrõeu©)Âã¹³ËN`ÚËõ˜.=+þM/£ÍßOEÄËåäЪg†„`¹mò­Œ,ÃÜš4Lážp@Œ"nØí,oêÁ[R.~°ý÷鎡1Åã¬Z=¹ú¢j•iàYD|Ó]9,L³\‰Ž$¨ˆS±±ªNŠªBwy}¬Ž-˜/ÿHØ„j©MážÁÒEª› ;ÀÀž2ÑñOÿ‰Z”C‰[³(.ñ“¸.·$82Ÿ2A]+„¥cnü<0„åÉÕe`¢…çð …`xÚÄ÷ªY8ãÆl‘Ü-·»¦>3 º„%#Hyrx°+#jýáeKŠ¢ÅzÝgW_œØÙžÁÞ+P´fc(wXBî˜MñžHù ÍûÒMõ¯ ØH̸²¤å”ìƒùdšúÈÍxâ› àÒ?úÜ€¾ ç2Ë»"²ûáÀ¾'Wÿµ/u7òhcÕDÞážR }ê*ʱ½<üìê?*ÀºŒB6Õ-¨¡‚«-²?¢¶{¸¼>ôÐÕJ"äØÞoYãó-@š¿Ïùç•hƒ¶¯8ÿ×Û…0ˆü¬½?¹úªÅ#×2F ‰bi¬e?ÂÌÖÿNC³ G)¨0\÷;Üûìr˜€š2Ï®¾Ld:ªújØ¥;L]rŒK~ƒý´–ÅÆPƒfÍÈÑDÛ–\öý=6}vh+Eõù=Ó4Zz¶cPq]7‚@êqÅnj†ãÕ‘ o "ŽHžý5Ï%vä屎Ûk’Ê]ÐÀš,eÞ.rT†ƒo%ZÔáéFß™B®eåÌí/ì„·€‚Á‰üì'B . {†žg\o³Ö ïÙ6¤~Î~²â‹ãP˜mS$‰d¨÷ð§XS[öAàÀjÍ!Ñû “6ü*¶Üýùí®);ªôáì-Ù•@(D„ÅÎÜÃ^r!?WÎ"ö{S&ÊqÝ' oÇ•3fÊ”ÇçŒ=¹újuLáãº.*)[.Ë]-’ÈÅõöÕÁÃëãç,O®þë>†uY~3AòáGÙ‹Íhý¾¸Û¯º¨Q¬ré£U†þhœ8ß5Xˆ~Fž Ôð©–Ôo³éM[TQ‡:Už.¨8ô©èçžåü¹‚µ2Óºê|©2X1L*•ø3|«Q¡,mŠÍºrre$½QEî—ÞpGÕ½´MªÐ ë \i &Cä¢ä¹†zºC-dÖüäSe £ÞyŠpî^—–·TIÝ;a1YEHÇ1; „öb¶Ù{S$! Ñ¢ò8|P2¤vF¶rÌ¡¼¿i‚~PôèŽ]²Jôñ@šï³«/‡R„šdè›a$D-0HŸ_pi˜P’ÛCSkwÚRsø¶ã¹ØŠ¤:]¨Ò‰yßµwùóŒFx@ê.œ–I „ ¬~]· j)_4cýï›’+Xlõ¿åŠÒh„†¥ìzj`ñ½óTž|§àI¸28€# i>ˆ\ç™!3(´Ü¢úœ7>8}LΛôÑÞ¢ œ ]¤dû°Ž=jÏŠìMB¨Æ/Ñž@³"Eú«–^ÃjÀ¹ñŽ›¤Å&H·dÝ'ˆ-\äáFŽ"„ŒIͦÔ]ª¹êzºú_)Gƒß: U°}¬€$¦hV«¦æåÃØY~èk1WÛñœfß|‘[©¼•·¦wKsd±*‘x ëb¯Ï ØZä/6*óµqÏU¯qXÄSÙƒ¸¶]CñÃÔ^TDyœ^öäêkZ]s0ojb]˜ÔAC“hÝ ›epë(rïΠµQT‚ˆrÍéj`¼0ðhªi~6Ô®¯[ª\l¸çõ‹t´îáïÌüyæþ] ¿]® µ£¡w¦÷Ô¹­â:íF!¯ª™2þ)¬µ¿'€ûÅ·oëG/'Kôª»VdÖà/²—dÐ23fð â«Û²Ž×ÎÆ¬å5©(ED÷ñ@±ŠgW_®ïQtéPÞ’ÄXI=餳Sò6lÚ3ïõrêÿ­’Ô2¶ÄO^7êø}L• Ç¼¢èd«^^%«ôp×÷®;©×–»ß¢ùK縕ÕK‘#µüñ@{ó«/ï ‚TÏ)†BS—Ì™áf¡7¥½Ë x6ú… ^ºöìãºþìê‹]oŽlìQ<<5ã§§¦µ´Øoz¶”Õl¼EU¬ÅI‹ë6ÍAm÷žñ9<Fð?¹ú/Už¢´Âu%T³ï²×]xâÒå¾óÓLB÷2d ŒSóbN»ò€œ{T< ;sð[eR$lýÓèh0ùómjôTpÀˆD¯Ö¼´«Ž¡{xìëù¼¤-’En¿-ÂSr¶¨D,ºÓUÙ²¤«„H+ö?r3ôãö$ýV¥ÀQqó~¹»r"Q"êêçBíª”Ø… ÅKb\€,+ΊHÄiˆòï¼:’æ¡Ê®6O&Ú8¸9 dTÆ0!Î…ŠémÜ8·˜iM„AÞZoîŽÆø¨t +IbHüƲ““¾hœ7ªG.Fq“r°k®Ÿ#Òl…a:¿³}Eè”Ôäæ©SƒÕÙe„%ü…?\;•Š ÍÓr icýL¨ÜÝ”ÃÔÕ§ iœÒ™TgŠ|•Ý ÙEŸ~+gᩞȪ¬»yíX‘–ÕšlSagõ{èOR­ ä ˜YÑá$C­5éD ù ‡l‡iWU6©^KC¦ù/ïÖ¥b$¸©Ç\9Hwcò}óŽ•”TÕì3KIè·dcF(æV Cßk?ÇZعŒBù\Ë«l¹½Ñ7=¬ß´Ã¥Ôí,ÎNÓ=¼`D™odߥ>w¯xýbÁƱ(™-!…Y9ÖSÜç©8ž*U[¦8h×ÀãŒÇYçNGùxxúïCå¯}Òš±zKÇ’=O«û»q‡oÞäåÐ~¥[èÞÞMhÀå&¯@æ;h>zúã/¡ªÅÈûkš/ûõeŠâÖßgW_æ•(ƒŠS G¸oha¬wžw9ßí„«ÈÚ©›×òÌÏÌÕ’ì8Ï–l—W‘Î%I?{Ùì’dØ_œV—›1YX‰$ÜOÎÖÝË»´öHǵŸŽŸó0yÅ`V¨ÿ9¨ç¨ÍO$ ¿+/¦Ã%fD[é…\Òw•ÏÜV!A£aÒ;$Xƒ?DïðìêË)B'(-\èdõ#öyÞSï[šÝ Cé±ô·;¹I1h8ô¶.¿Žpñ¯3p7œDФ‰í¨s1îCE¸/Ńžô¢?kYADMŸƒl¹8çÞaõL¬'D™¨%hOö;Àì=–p7ð\çÕÀrýE(\„¢·]ò%)EJ-Zõ# æRt¯Ï‚0ÛT.q:Rèóév÷ŒÖW°uŠ÷ñ@òöÙÕ—·´Øjoh=Ø+ò°™×Ú¾"®ü±$•bcTpÅ8úÙ÷-!ÝóçúþìêË{…¢Ûîûy>%¸“°“Os¾.÷¸­î¹M­w½iÊ}øF¥ß5ê±¶XOE¹Áˆ06k„4ÔãÎÐÌ{€ÅðšæC¥Ýá·ÍZÅçÿËõý¸87ÄX²h³¾ÍÇÏ{¢Ÿ\}m+Øÿ¬Ä©IR$A£`C ê»M=±ÕÎÛOé¶’´(¿:80 êŠïúUý|2NÅK±Å›×}eú5ŠäÛyvõ宜õ6ëBw{‹EžŒs)XM)*ç¹à51ðŒ<êÅKóµ(¾í¡ÆÒïWæS´ìú pð«HT,%amÁºu.4ûú{ÒŠnÙªù —~jOuÌO‹žëÁN¢¦§ïÍ¢Ã;B¶æ¹./ú0<8Jb¾ê~¿PJºÂŽñØiš¼%›lïæíl.T}i¨r©­qYÃê—}rõe²ð¢¥ëò¦©Oï+“¸R8º®óf7\’q]œ\æ]¶¼t|$*[,ZƸÖ}ÈÉpåQ²Vù‹Ø¤S3È©r­5»¿Ï_!RüÉÚ‘b‰q_Óöw·«ÀLQúéCë@w†V¤w>ÈÐzvõåò‚’{Êß,‚(HÒ´ Ðbë!›¼MMšáÖŒRj}ˆRã\‘> ÏO–!”ñ¼j• ©Î#ŸmfyråÐÍ©zå}±õÀÎle-ñ«\¬’6‡h¿›tïÁäþÍ&v„Ì$bÏŒí¦n¢¤Ìw8Cüþãó«ÿL0h–`ˆ¯FB”0&Š[·*y° ”–£6“«qÙgiþ¤çLÍ»&¶#kK‡qW#…\Èb!Û[^=@ã4ýñ;Šy=»úr•SOiÀžTåTÈÕ`C[[b!tÓDËm®ü°/´òŸ]}Q¥ëVMI¿±š·#J¨bæøžj–¾æPÄ3Ðu[¾™ýôzŠ\ÑTWüxPöMt ¡º¤¤sÉy9›7•—j»¾œÉc¨#»‰ ”“ëõ OºˆØã#”O®¾ †¢Ó_‡,‘D(fº¥S‡c2oP•°/ˆ$‰-ÐM˜.)Gª¾Ff¤Xþ\4¤x Xã\ûñ( ´ù®tßò¥Â¼EU~6¢Ê$»¡Cu#ºnªïíñ0Qêù£âó8BvtS~°`¯,¬F2_Ó¥-xWÌ)¤ðñ@ŸãÙÕWS²Ì2æù9 ÆYÍ(k$(]Qºˆr}6$:ìÔ@îD”?l¬ÀÈõ—••‡±-ºÿXw‰NµŸv½?¹ú²W‘z²?¨ËsÁžŸ˜Õ´ŠZrŽêŒÄ•gVÑìø¬çAct")r ?NÞµçø!Ú\ØÑpXL»lë­zêL¨4/U+wíú¹Z/€˜ L …[iF´i@&¨ðuhÖÎ^F 3cV5™ –¤ówTPM-,åFIõeÛtç¿Uµ„sSPV]6Û¢´[g©ß Ó ;;mN½Ý¦P¨ Ã1–óO!Á[Y£1âLÉÀ@ç¡…”£bn;lèÐS‰’»öTÐc–Ã=¥Êcüh)ÕÊÁ‰ ÷«TG§´¸c_× íª˜€- ¨`|{?‹rÞΖÒí™…ó_Y0–î8Ebü¬!m‚õçoԤ͛ ·M"hß[^GZU’•Ÿ³c¨2Ù± ˜Iï1F-ÝèË¡R<Øpxrõ5QÑèfÉc Õ$åâ¼ÅõM{Ð.IÑTaÃOWÈÑâä&¹A¸[.ö °âв+cõXŒ¼>È }võÕŠdáÊ…€–|¤# ¯ÐÑ¥¸cùÓi>l¶¡áü„ƒNFM3Øì8Ïúz³ QŸÒBExC­Ya"ž…Š›Ý“,ªÝ΂ñü U¢dų,”úÃK\óakQÜðç‘¢ÿᆗqÅÑùTjàŠ›Þo«Ü—%©Äر –*ÚrÿiöGh’Æ|® “º[4B•–ª½›5Ý<Îéc"ž³ £!œ\Øn—ŒìæJ”bÖ%Ve\¤7äv0CF¬÷Ƶxß’B)rÁàZR>VòŽÈÓÁúÞï Ò_´â†“f=ëT*z¸á”.¨“æ¯VQb³Zîà"ÿøŒ’eô‚æäÚÒL• ´g1éª/;2Ë–­?÷¶¢ô@¸‹¬ÇY¨pT¯"àÝŽ‡Ûß“Šÿ·>ÏË’ïjÛípÿ¯ºð×K¯þþúsü}íð±ÚÞÿzøQ‚uhecj;êßß½~¨_dV5…cPª»h_V/PH`g‹ëçŸ?ܾÈàÉ0ôóH2ø?Üð¢ U¶:Ѷ´SšõÍ*µ·Jal»jžŸAd$]–U½o´ûµÅ©e–I¤n]™¨•È$Ønqˆ`PG¢§©ß«¢›RÙ¥}QÛ#ÅVyе¢†[´øZ•e%ݻ۸L™À¯ˆÒ/o¶e±ŠêwOýïFuy#_ß Ä-4‰i2Òþzæùð–b¤Z¦-~û¸ •“{ÈØU†w¼CÛÃò4CËÜ@>ߺêRV®b…oiµ±õ¡ØöÐ€ËæèÎÇVÈlŠ>Â:¢¶P÷P™œYއ£ÃŒ†îh= ñ}Äv¸ Óüñ¥Ï‰Ù*˜*umRö³ÝY¿É&s:Ϻo9ÏåÇ5UTÏÕ Îò8Â(ñq¶Rcê¸ìpðÓ­îk Ì9e«S‹ê\NC."µÜ´ µ8 FÀô);Ë’«…Y eò)PùªlÉ^©Å=:ÔKôˆ;xINý•2¾«Å¶g–£ bA®%X¦|J!϶ý¹–ç“<»ÿ×µùþvéµé\窃#í{ÒÊAè/Ü}«ª{#q·Ÿó uŸêtá{í $Ëß ,ÖÈ‹í}ÍÊ[ø…ºFœ Ë¿¹VPVåªï ïA÷@¶:Z\½$r†Ñ²9§›´¦EÜ™›T6§„ÕÀ ¾¦ @"þåqÇ7ö› æˆ}¸ß¾žýŠZG%j°v“Ì©Úɦv»o!š¡I¤ˆÊXæ{ÏÊ}Ç L"îYʼáJRdÏAKI÷ Ê Ÿ¿"'Ì FÀ?,ÑŸ\}M;邨œ½¾ú"½pü2x2ïŠ'Üi Ùrî<ƒÒZò`?§4ÌZ.}å‘}Òæ¤t2´[°á´ô‡¡{ø„†u <¡94À™]ðaï×Y>eLÜÔ¦\Yxcþ<ˆ½æÙÕKˆË·ÌpjˆUÈA'!SÎs–ЧîþÿëcWÞ^ùA¿ð±ýWÕïŸë_jRù2¿¥ oÜÁÕwÿÿWµkñ\êbÏ¡[ ð↮¹F‡çÝý 1IÀ0´å<»úrýym……Á€oUœ§ôœ»l©¢ +°†ï¤g¨öÏ®¾& \pª(YñÛó|W!縡“Û÷ëãØä¢(HØÕ /VQZÄa:Ç=°}I8ÈrÏþsmP¶í±I‡Gƒª{ž- J±²)ºEÝbÈ goÆR ]€Gb8`Œw…E…Û›^kˆÚø€“WlѯRžGŒ®(µô[Q»MãŸøñ†;öýãñ/ÞÄ`ý×~RŸóbNN · ‡MÎgW_ó+;u߬ûFœ‹V%¸Â›_4FvñO+VVÅÞÏÄ)²'/@ë°©Šo‘o¹ )°çxjÕÒDà í"á’;Ùm:§w¹ó?Ñ@Ë'>OS„-‘SàC8‚¥!݇’ÄñÄ®!Ë2€]ö\?ÙÉE Û¢ëT³ˆÞ°¢˜ót½’,i¾ôŽ?ØŠFéH|à2ª‹a@ÙÇi¤Ï®¾ îÁjl‚1´SÏ¥½Pˆy´”ÑX¿×.¼ÄèIeu¨³>v¥CþEP.l¸MÝ‚ÃSVž&Õaq¢XFžÔdj¡äl9ªøì³K‡’ãÌî z Ö†»âäñ(zåîà¾t×]¨<4þ%90{µØÓ’òlQ„µhä“Öë®~f;Wìg~rõe˜k‚®îf&gª!ZìðÙI)W7“Êß1ÿˆ¾êb”U$ߦñ-9Eš—ž*Ší¯éÏ™[øá‰¬­,õþ|¦Ó«­GÕ-ú•ªò‹“ž˜R¤«–)Xœ ê×6¹¯‰N«Z–äL×›µjJõe0 ò79=ªùÛª§6†žÙÈvÂE‘h¹Löàç­ö'W_ìYéE-ØÒ¿5&°«Ž&k9æþ2jL¢w€,äËW©ŽŠ ÐŒu&®e[¦©Y€X)í‘ûs•ï}ùhUuÂ¥+B@w)‚¿YéI,d#B¿o¥*Gë“Ö b ­Õ„ MuøŽµ3æf!ÒnÝ–¼‰¾…5d”Eà)+XTB,E¥èC½Í]y²€çq*ɧŽÁ@éÒš/ôŠ2ˆ5ÉÂÀð¡¼SJ |ÊMŒQÄêáÛ‚ã"Õãùo½WqŠ·m®RrðzŒt×½Jœžƒ1;_³·È÷ÜYã§…LæÐ6•5) ?²€›JñšG†.70ç}yˆÃŠŸAr¢·xˆIÑû&½õ¢=b&im.aO…sÀIVUÞ{L.•*ÂMš;-H4›¬5—)¾ø»Ùóx óÙÕæÂ%Ý;SnàµÜDZL¢ãl}ª:&k0EÄg4Üæ_¬2sgí'íÁôæcqöý ‡Tsk¢ÁÓc;n޳hÛ ¸ÄæþEшž®,+ýy× ‚.D¥Õ€»€ ’÷øšk/ôök2CGvÐÏ'3<¹ú2±awÞ!n VâÔèÀÄUºI”y\ ïÎÝ‘Ù*¬5\»3^†I([ç4 ™ÄT6-d~ØŸ¼È<Ãhc‚ˆôDØO+,ª~ÁN›>¢#ø˜$ "*%¦±švË¡ÅR4F¿Ó3ј©¡Ÿ¡ùRÊ]Èr㣡†RDm½=ú]º!B íƒÐ˜¢r±‡€ºùO¨`€øhj=tÃ5fîBJO—«g˜ò]@6â-ˆœï²e>£élÝŠ†¤iêÆ¶%Áð,¬u×»´¢‰­í‰•Kö8å¹@Ž«ì PÉìAŠFI[ÍRc™£ÏÜœój6Êk7…[ÐB þ®nnÅÙÜèáµU¦TØ0ä÷éLÝèV ±1ÀŽg-úù:7ý®l3ƒ,kI:Yõð§3ì_{àÚ±ÉÞš Íú]}ßF$%k‡æµV¤Btž¦è9½8 Kk6´†¶´PRÛb¬¹x!§ÅÍ06à¬7Ó_læcgfÛøPuÊX¢”#˜qOW÷jÒÎüj B‚á¶èïGǦ|ö:™ú†=MU=HŒõZÆ€r `£'mÊ(0™…iIŽ1šìL€è29K2¯ Üñ7ÂÄeÑè!jCÑd ‰qî*·Ú±1†±^¿D› §QI{bðµxÇ#J¹mD|]¡Îªü²¯Ûe7G“Z F4‚ñ®Í¶%a„Ù“ð;Ÿj“+Ç%3ð»aý½2N‚MÖ¹…®éŠžƒNW|rõÅ~Üÿªú!Q©jà\R=K•ø‹÷@@á ­Ö»‡ýÌÜÛΆ$LØ1w[Æ”å.4yÌá–>eþçÉ›¶¦¶›¹ú²_LR‘¯H©£^ØDòÇ;võËYtë,J1hQÓÇÏ;bŸ\ý×Ý´\T!¡—çhÏú” d¤@ªÌÔßiQª\»ŸÌ«%_µjÜC/_Û™»êQ?ÄÇ>‚óa|ÍûT k{\|‡CSª†‰%õ³‘‰äþ/ÞTÓðïýÜʲ¬ÞxüÕïKÑÇ:ÍAÃÜNäŽPý«êðÕ} ÷FÕŽ•×}§]›%±ƒ ¢«æáÚ’»Mž°;Ž —äÔëW•]û&ZÄ*ÑÂPIý&¹Ÿ«]9N²"„…²—çæiÐïØ~50*£.Ò™Uqc‹a^¢3{O„×®Jp’îfŸ \=uÕås¿jY2¬¶ìåÑk~ÙL‚gWÿY¶9LUM"鬘n¦îh¨CFG©`EY–¦–"ÒD¾MBb@fÓ/FeÈ/JN”pßi þçö¿u²Çù endstream endobj 4 0 obj 38253 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> /s5 5 0 R /s7 7 0 R /s9 9 0 R /s11 11 0 R /s13 13 0 R /s15 15 0 R /s17 17 0 R /s19 19 0 R /s21 21 0 R /s23 23 0 R /s25 25 0 R /s27 27 0 R /s29 29 0 R /s31 31 0 R /s33 33 0 R /s35 35 0 R /s37 37 0 R /s39 39 0 R /s41 41 0 R /s43 43 0 R /s45 45 0 R /s47 47 0 R /s49 49 0 R /s51 51 0 R /s53 53 0 R /s55 55 0 R /s57 57 0 R /s59 59 0 R /s61 61 0 R /s63 63 0 R /s65 65 0 R /s67 67 0 R /s69 69 0 R >> /XObject << /x6 6 0 R /x8 8 0 R /x10 10 0 R /x12 12 0 R /x14 14 0 R /x16 16 0 R /x18 18 0 R /x20 20 0 R /x22 22 0 R /x24 24 0 R /x26 26 0 R /x28 28 0 R /x30 30 0 R /x32 32 0 R /x34 34 0 R /x36 36 0 R /x38 38 0 R /x40 40 0 R /x42 42 0 R /x44 44 0 R /x46 46 0 R /x48 48 0 R /x50 50 0 R /x52 52 0 R /x54 54 0 R /x56 56 0 R /x58 58 0 R /x60 60 0 R /x62 62 0 R /x64 64 0 R /x66 66 0 R /x68 68 0 R /x70 70 0 R >> >> endobj 71 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 230.732712 238.238022 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 2 0 R >> endobj 72 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 116.238022 120 238.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCcCC3=#c ##sC Y”ªÆÀí endstream endobj 6 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 113 116.238022 120 238.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x73 73 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _an¬à’ÏȵËü endstream endobj 74 0 obj << /Type /Mask /S /Alpha /G 72 0 R >> endobj 5 0 obj << /Type /ExtGState /SMask 74 0 R /ca 1 /CA 1 /AIS false >> endobj 75 0 obj << /Type /XObject /Length 49 /Filter /FlateDecode /Subtype /Form /BBox [ 113 116.238022 199 201.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCcCC3=#c ## 3 S…¢T…4.À“ü endstream endobj 8 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 113 116.238022 199 201.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x76 76 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _an¦à’Ïȵàÿ endstream endobj 77 0 obj << /Type /Mask /S /Alpha /G 75 0 R >> endobj 7 0 obj << /Type /ExtGState /SMask 77 0 R /ca 1 /CA 1 /AIS false >> endobj 78 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 116.238022 231 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCcCC3=#c ## ÓBÁL¡(U! À3ñ endstream endobj 10 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 113 116.238022 231 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x79 79 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _an©à’Ïȵõ  endstream endobj 80 0 obj << /Type /Mask /S /Alpha /G 78 0 R >> endobj 9 0 obj << /Type /ExtGState /SMask 80 0 R /ca 1 /CA 1 /AIS false >> endobj 81 0 obj << /Type /XObject /Length 46 /Filter /FlateDecode /Subtype /Form /BBox [ 113 36.238022 199 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCcc3=#c ## 3*JUHã¸+Î endstream endobj 12 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 113 36.238022 199 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x82 82 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _aa¤à’ÏȵÌü endstream endobj 83 0 obj << /Type /Mask /S /Alpha /G 81 0 R >> endobj 11 0 obj << /Type /ExtGState /SMask 83 0 R /ca 1 /CA 1 /AIS false >> endobj 84 0 obj << /Type /XObject /Length 46 /Filter /FlateDecode /Subtype /Form /BBox [ 1 116.238022 119 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCC3=#c ## ÓBÁL¡(U! ®ä endstream endobj 14 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 1 116.238022 119 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x85 85 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _aaªà’Ïȵáÿ endstream endobj 86 0 obj << /Type /Mask /S /Alpha /G 84 0 R >> endobj 13 0 obj << /Type /ExtGState /SMask 86 0 R /ca 1 /CA 1 /AIS false >> endobj 87 0 obj << /Type /XObject /Length 45 /Filter /FlateDecode /Subtype /Form /BBox [ 35 37.238022 120 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.cScs=#c ## S*JUHã°  endstream endobj 16 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 35 37.238022 120 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x88 88 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _aa¡à’Ïȵö  endstream endobj 89 0 obj << /Type /Mask /S /Alpha /G 87 0 R >> endobj 15 0 obj << /Type /ExtGState /SMask 89 0 R /ca 1 /CA 1 /AIS false >> endobj 90 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 35 116.238022 120 202.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.cSCC3=#c ## S 3…¢T…4.¸JÏ endstream endobj 18 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 35 116.238022 120 202.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x91 91 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ai¨à’ÏȵÍü endstream endobj 92 0 obj << /Type /Mask /S /Alpha /G 90 0 R >> endobj 17 0 obj << /Type /ExtGState /SMask 92 0 R /ca 1 /CA 1 /AIS false >> endobj 93 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 -0.761978 120 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCc]=s3CKs sC#c…¢T…4.·ÚÈ endstream endobj 20 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 113 -0.761978 120 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x94 94 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ai¢à’Ïȵâÿ endstream endobj 95 0 obj << /Type /Mask /S /Alpha /G 93 0 R >> endobj 19 0 obj << /Type /ExtGState /SMask 95 0 R /ca 1 /CA 1 /AIS false >> endobj 96 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 2 1.238022 231 238.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.#C=#c ####K#cs…¢T…4.®¶ endstream endobj 22 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 2 1.238022 231 238.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x97 97 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ai®à’Ïȵ÷  endstream endobj 98 0 obj << /Type /Mask /S /Alpha /G 96 0 R >> endobj 21 0 obj << /Type /ExtGState /SMask 98 0 R /ca 1 /CA 1 /AIS false >> endobj 99 0 obj << /Type /XObject /Length 49 /Filter /FlateDecode /Subtype /Form /BBox [ 113 177.238022 180 211.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCcCss=#c ##3sc…¢T…4.Àêü endstream endobj 24 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 177.238022 180 211.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x100 100 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ah` à’ÏȾ‘ # endstream endobj 101 0 obj << /Type /Mask /S /Alpha /G 99 0 R >> endobj 23 0 obj << /Type /ExtGState /SMask 101 0 R /ca 1 /CA 1 /AIS false >> endobj 102 0 obj << /Type /XObject /Length 49 /Filter /FlateDecode /Subtype /Form /BBox [ 114 158.238022 162 185.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCCS =#c ## #s…¢T…4.Àíý endstream endobj 26 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 114 158.238022 162 185.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x103 103 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ah`¬à’ÏȾ¦ & endstream endobj 104 0 obj << /Type /Mask /S /Alpha /G 102 0 R >> endobj 25 0 obj << /Type /ExtGState /SMask 104 0 R /ca 1 /CA 1 /AIS false >> endobj 105 0 obj << /Type /XObject /Length 49 /Filter /FlateDecode /Subtype /Form /BBox [ 113 139.238022 143 160.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCcCcK=#c ##c#C…¢T…4.À:ì endstream endobj 28 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 139.238022 143 160.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x106 106 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ah`¦à’ÏȾ» ) endstream endobj 107 0 obj << /Type /Mask /S /Alpha /G 105 0 R >> endobj 27 0 obj << /Type /ExtGState /SMask 107 0 R /ca 1 /CA 1 /AIS false >> endobj 108 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 53 176.238022 120 211.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.ScCs3=#c ##3scS…¢T…4.¸™Ï endstream endobj 30 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 53 176.238022 120 211.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x109 109 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ah`©à’ÏȾР, endstream endobj 110 0 obj << /Type /Mask /S /Alpha /G 108 0 R >> endobj 29 0 obj << /Type /ExtGState /SMask 110 0 R /ca 1 /CA 1 /AIS false >> endobj 111 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 72 158.238022 120 185.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.s#CS =#c ## #s…¢T…4.¸«Ð endstream endobj 32 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 72 158.238022 120 185.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x112 112 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahh¤à’ÏȾ§ & endstream endobj 113 0 obj << /Type /Mask /S /Alpha /G 111 0 R >> endobj 31 0 obj << /Type /ExtGState /SMask 113 0 R /ca 1 /CA 1 /AIS false >> endobj 114 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 90 139.238022 120 160.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.KCcK=#c ##c#C…¢T…4.¸À endstream endobj 34 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 90 139.238022 120 160.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x115 115 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahhªà’ÏȾ¼ ) endstream endobj 116 0 obj << /Type /Mask /S /Alpha /G 114 0 R >> endobj 33 0 obj << /Type /ExtGState /SMask 116 0 R /ca 1 /CA 1 /AIS false >> endobj 117 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 28.238022 180 62.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCc# =#c ##3sc…¢T…4.·üÇ endstream endobj 36 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 28.238022 180 62.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x118 118 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahh¡à’ÏÈ¾Ñ , endstream endobj 119 0 obj << /Type /Mask /S /Alpha /G 117 0 R >> endobj 35 0 obj << /Type /ExtGState /SMask 119 0 R /ca 1 /CA 1 /AIS false >> endobj 120 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 56.238022 162 81.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCcS3=#c ##K#S…¢T…4.¸È endstream endobj 38 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 56.238022 162 81.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x121 121 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahd¨à’ÏȾ¨ & endstream endobj 122 0 obj << /Type /Mask /S /Alpha /G 120 0 R >> endobj 37 0 obj << /Type /ExtGState /SMask 122 0 R /ca 1 /CA 1 /AIS false >> endobj 123 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 113 79.238022 143 99.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CCcsK=#c ##c# lªB·î¾ endstream endobj 40 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 113 79.238022 143 99.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x124 124 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahd¢à’ÏȾ½ ) endstream endobj 125 0 obj << /Type /Mask /S /Alpha /G 123 0 R >> endobj 39 0 obj << /Type /ExtGState /SMask 125 0 R /ca 1 /CA 1 /AIS false >> endobj 126 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 53 28.238022 120 62.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.Sc# =#c ##3sc…¢T…4.¯åš endstream endobj 42 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 53 28.238022 120 62.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x127 127 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahd®à’ÏÈ¾Ò , endstream endobj 128 0 obj << /Type /Mask /S /Alpha /G 126 0 R >> endobj 41 0 obj << /Type /ExtGState /SMask 128 0 R /ca 1 /CA 1 /AIS false >> endobj 129 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 72 56.238022 120 81.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.s#S3=#c ## #S…¢T…4.°› endstream endobj 44 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 72 56.238022 120 81.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x130 130 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahl à’ÏȾ© & endstream endobj 131 0 obj << /Type /Mask /S /Alpha /G 129 0 R >> endobj 43 0 obj << /Type /ExtGState /SMask 131 0 R /ca 1 /CA 1 /AIS false >> endobj 132 0 obj << /Type /XObject /Length 46 /Filter /FlateDecode /Subtype /Form /BBox [ 90 79.238022 120 99.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.KsK=#c ##c# dªB¯ò’ endstream endobj 46 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 90 79.238022 120 99.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x133 133 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahl¬à’ÏȾ¾ ) endstream endobj 134 0 obj << /Type /Mask /S /Alpha /G 132 0 R >> endobj 45 0 obj << /Type /ExtGState /SMask 134 0 R /ca 1 /CA 1 /AIS false >> endobj 135 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 25 56.238022 59 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.#SS3=#c ##c33…¢T…4.¯É™ endstream endobj 48 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 25 56.238022 59 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x136 136 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahl¦à’ÏÈ¾Ó , endstream endobj 137 0 obj << /Type /Mask /S /Alpha /G 135 0 R >> endobj 47 0 obj << /Type /ExtGState /SMask 137 0 R /ca 1 /CA 1 /AIS false >> endobj 138 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 53 74.238022 78 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.Scs=#c ###S …¢T…4.¯âš endstream endobj 50 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 53 74.238022 78 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x139 139 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahl©à’ÏȾè / endstream endobj 140 0 obj << /Type /Mask /S /Alpha /G 138 0 R >> endobj 49 0 obj << /Type /ExtGState /SMask 140 0 R /ca 1 /CA 1 /AIS false >> endobj 141 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 76 93.238022 97 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.s3Kc=#c ###C#K…¢T…4.°<› endstream endobj 52 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 76 93.238022 97 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x142 142 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahb¤à’ÏȾ¿ ) endstream endobj 143 0 obj << /Type /Mask /S /Alpha /G 141 0 R >> endobj 51 0 obj << /Type /ExtGState /SMask 143 0 R /ca 1 /CA 1 /AIS false >> endobj 144 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 174 56.238022 208 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CsS3=#c ##c33…¢T…4.¸¡Î endstream endobj 54 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 174 56.238022 208 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x145 145 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahbªà’ÏÈ¾Ô , endstream endobj 146 0 obj << /Type /Mask /S /Alpha /G 144 0 R >> endobj 53 0 obj << /Type /ExtGState /SMask 146 0 R /ca 1 /CA 1 /AIS false >> endobj 147 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 155 74.238022 180 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CSSs=#c ###S …¢T…4.¸‡Í endstream endobj 56 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 155 74.238022 180 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x148 148 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahb¡à’ÏȾé / endstream endobj 149 0 obj << /Type /Mask /S /Alpha /G 147 0 R >> endobj 55 0 obj << /Type /ExtGState /SMask 149 0 R /ca 1 /CA 1 /AIS false >> endobj 150 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 137 93.238022 157 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CcsKc=#c ####K…¢T…4.¸`È endstream endobj 58 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 137 93.238022 157 122.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x151 151 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahj¨à’ÏȾÀ ) endstream endobj 152 0 obj << /Type /Mask /S /Alpha /G 150 0 R >> endobj 57 0 obj << /Type /ExtGState /SMask 152 0 R /ca 1 /CA 1 /AIS false >> endobj 153 0 obj << /Type /XObject /Length 49 /Filter /FlateDecode /Subtype /Form /BBox [ 174 116.238022 208 183.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CsCC3=#c ##c3s…¢T…4.Àôü endstream endobj 60 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 174 116.238022 208 183.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x154 154 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahj¢à’ÏÈ¾Õ , endstream endobj 155 0 obj << /Type /Mask /S /Alpha /G 153 0 R >> endobj 59 0 obj << /Type /ExtGState /SMask 155 0 R /ca 1 /CA 1 /AIS false >> endobj 156 0 obj << /Type /XObject /Length 49 /Filter /FlateDecode /Subtype /Form /BBox [ 155 116.238022 180 164.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CSSCC3=#c ###S …¢T…4.ÀÐú endstream endobj 62 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 155 116.238022 180 164.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x157 157 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahj®à’ÏȾê / endstream endobj 158 0 obj << /Type /Mask /S /Alpha /G 156 0 R >> endobj 61 0 obj << /Type /ExtGState /SMask 158 0 R /ca 1 /CA 1 /AIS false >> endobj 159 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 137 116.238022 157 146.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.CcsCC3=#c ###c tªBÀ\ì endstream endobj 64 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 137 116.238022 157 146.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x160 160 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahf à’ÏȾÁ ) endstream endobj 161 0 obj << /Type /Mask /S /Alpha /G 159 0 R >> endobj 63 0 obj << /Type /ExtGState /SMask 161 0 R /ca 1 /CA 1 /AIS false >> endobj 162 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 25 116.238022 59 183.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.#SCC3=#c ##c3s…¢T…4.·çÇ endstream endobj 66 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 25 116.238022 59 183.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x163 163 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahf¬à’ÏÈ¾Ö , endstream endobj 164 0 obj << /Type /Mask /S /Alpha /G 162 0 R >> endobj 65 0 obj << /Type /ExtGState /SMask 164 0 R /ca 1 /CA 1 /AIS false >> endobj 165 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 53 116.238022 78 164.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.ScCC3=#c ###S …¢T…4.·øÇ endstream endobj 68 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 53 116.238022 78 164.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x166 166 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahf¦à’ÏȾë / endstream endobj 167 0 obj << /Type /Mask /S /Alpha /G 165 0 R >> endobj 67 0 obj << /Type /ExtGState /SMask 167 0 R /ca 1 /CA 1 /AIS false >> endobj 168 0 obj << /Type /XObject /Length 47 /Filter /FlateDecode /Subtype /Form /BBox [ 76 116.238022 97 146.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 0.199095 /ca 0.199095 >> >> >> >> stream xœ3P0¢týD…ôb.s3CC3=#c ###Cc lªB¸ ¿ endstream endobj 70 0 obj << /Type /XObject /Length 48 /Filter /FlateDecode /Subtype /Form /BBox [ 76 116.238022 97 146.238022 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources << /ExtGState << /a0 << /CA 1 /ca 1 >> >> /XObject << /x169 169 0 R >> >> >> stream xœ+ä2T0B©k gnfhin¡œË¥Ÿh ^¬ _ahf©à’ÏÈ¿ 2 endstream endobj 170 0 obj << /Type /Mask /S /Alpha /G 168 0 R >> endobj 69 0 obj << /Type /ExtGState /SMask 170 0 R /ca 1 /CA 1 /AIS false >> endobj 73 0 obj << /Length 172 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 117 120 239 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 171 0 R >> stream xœ+ä2PÁ wýD…ôb.S=#SKcC#…r.C/ Î⊎U0Ð3PHá2QðU(T0ëÐQFÆ– ɹ\††fz¦– Fzff ¹ P®¡¡…ž™…‰BŽB°B W ­® endstream endobj 172 0 obj 101 endobj 171 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 76 0 obj << /Length 174 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 117 199 202 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 173 0 R >> stream xœ‹; ÂPû=Å\ÀÍnÞÇ·'‹˜2Xˆ‚ ¦¹¾‰ ÃT³ˆ±s=ÑÝ×WЦ¾YTVqΛo™n˜OÉ\XðÿqØÓ§à1‹GÑÜH¡ÇH̸W-±¥im™#ƒ òÇ endstream endobj 174 0 obj 102 endobj 173 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 79 0 obj << /Length 176 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 117 231 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 175 0 R >> stream xœ+ä2PÁ wýD…ôb.S=c# K3…r.C/ Î⊎U0Ð3PHá2QðU(T0ëÐQFÆ– ɹ\FFæz–f¦ ††zf& ¹@–™ž©%\ G!X!+ òÚg endstream endobj 176 0 obj 101 endobj 175 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 82 0 obj << /Length 178 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 37 199 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 177 0 R >> stream xœ‹; „` ûœâ»ÀÆä‘œ`A°PK±ÑB,¼þª ÃTsà¡û¢šËI™c0ñ‚‹õíJÃaÁÐ÷ø< Ñ1ï¤^8äu㘠;T g¿c\,aC–Zúòýh endstream endobj 178 0 obj 102 endobj 177 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 85 0 obj << /Length 180 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 1 117 119 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 179 0 R >> stream xœ=‹1 €@ û¼b?`L4wœ/ µ QÄ+ÄÂïëYÈ2 SìI‚´¾F> ¶‹—EÊã&Eó²Ó8AX°’¡Å ýYRQVX"©:ê¡ØC„±™þ}`@G=ÚÂ% endstream endobj 180 0 obj 99 endobj 179 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 88 0 obj << /Length 182 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 35 38 120 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 181 0 R >> stream xœ‹= Â`û=Å\Àu7ßïž XDK±AL,¼¾‰<†·ˆ±í4²¿ÏMC·¨|Å9¬¼ärÅÔxHæÈ‚ÿ»MC ¦5¦¥efÜ«–5x×Ú3oÎL2ÉÞ? endstream endobj 182 0 obj 103 endobj 181 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 91 0 obj << /Length 184 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 35 117 120 203 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 183 0 R >> stream xœ‹A Â0ïûŠù€ë&ibö‚ÐCëQ<” bŃß7•a˜ÓìbŒWΓ±~$kŠÕ¼ð•À­ù’ÇSc‘Žžð?NGbræMÒE‹;ÉÕ"!ÍÞRµÔŽ7wä°yÌ endstream endobj 184 0 obj 102 endobj 183 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 94 0 obj << /Length 186 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 0 120 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 185 0 R >> stream xœ-‹K Â@÷}Šº€îù1s!à"ÉR\AÌ"¸ÈõcDEAÁ[Å86žéfãù‘¬1Tk…MœþËK®7L‡$.¬øïq:b㾈{ÑÜp¯ZjbáBÌšJãÍÄ ƒìÛŸ/ endstream endobj 186 0 obj 102 endobj 185 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 97 0 obj << /Length 188 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 2 2 231 239 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 187 0 R >> stream xœ]PKJC1gg^s¿É] 8¨ÅTP„Š·ïÍ«mEÂ#„wþÇÖ±Îãn_;Þ¿š“x* ¾ã¾¾Ïöü‚NoÍð€#xcܬK4±?4æ /ŠÐ˜ŒX“F*„IƒBTÈ•Áéd¿=¤ ŒNbÒŠdÔM‘B³p"ƒ2Ì“bÚFH².`+ {½;±”p”¤žõç ‹À!”›“°ÿ‰ÄZŒ?«ŒQ¤!•tŽúÏdY‘†Ñ»ðµúdâj Na—Rª%³â¹ÀO–§ômÅ/°8¦n­µÓðeà3Ηij®Ê2k‰k¨µé¿É÷øhOص]û_YÄ endstream endobj 188 0 obj 258 endobj 187 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 100 0 obj << /Length 190 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 178 180 212 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 189 0 R >> stream xœ‹1 Â@Eû9Å¿€ãÌÎüÍî !Eb)AR ¯¯‘ÇãUoÃÎ|Âñnx¾…¥Y¯øˆãüó%×L IŒØàÿã°§DDzŠ{U²#LÙ VxP™š‘pRÓ œð¡j÷6  .˜d’/ÅnÍ endstream endobj 190 0 obj 118 endobj 189 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 103 0 obj << /Length 192 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 114 159 162 186 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 191 0 R >> stream xœ‹K Â@÷}ŠwÛîéÏÌœ d‘¸A².¼¾‰<ŠÚÔÛHplp~^ ¶Ò¤'¾¤¸ì¼év‡°àIŽôÿ8*Ö±¬¤š\»!’£¬P-ÈÊiêÎnŽê\öL£±E &wmXpÅDýÈUÞ endstream endobj 192 0 obj 121 endobj 191 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 106 0 obj << /Length 194 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 140 143 161 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 193 0 R >> stream xœ‹1 Â@û}Å|Àu÷.o_ R$–b! ‚˜â°ðû&a¦š&ÆÆ|æx7^_)šSµèù‰3¬¾åzÃÔxJÇHÃ÷ã°%åైçÐSd¢hWYpïµÕµ¬ùpa’Iþ±PÖ endstream endobj 194 0 obj 101 endobj 193 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 109 0 obj << /Length 196 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 53 177 120 212 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 195 0 R >> stream xœ‹; Qó9E_Àq¾ïs‚Á`5YA6X ¼¾o¥©ª¨7ì»L8>¯%»5é_RœoºÝ!,xRàŒ úö˜w,+©ÎÎfXÑ‹UDpx V¶êHeo#…m¸±gbÁ3Íô=³Ö endstream endobj 196 0 obj 115 endobj 195 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 112 0 obj << /Length 198 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 72 159 120 186 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 197 0 R >> stream xœ‹A ÂP D÷9Å\À˜ä7ù?'(]´.Å…T„.Š ¯ï¯ ÃcÌN‚#ˈóCðús±&ø’âÒû¦Û‚' ˜°CÿÓ+‰u#ÕàâöfØ âláÑÂéÕº«¨×ì+8µaÅ3Íôu¯S endstream endobj 198 0 obj 119 endobj 197 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 115 0 obj << /Length 200 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 90 140 120 161 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 199 0 R >> stream xœ‹; €@ ûœâ]À˜ìnÄœ@,ÔR,DA-ÄÂëûa¦š“]…|¬ÇPЏIQ¿n4Œ,”Ðà„þGö%DÇ|G–àÆé¨læ(õÏŽ-µôÇ endstream endobj 200 0 obj 99 endobj 199 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 118 0 obj << /Length 202 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 29 180 63 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 201 0 R >> stream xœ‹A ÂPC÷sŠ\Àq2¿óûçÁEu).¤‚ tQ\x}%„¼²‰a×eÂñax}$´x³¬ø qê~ËíSÃSœ±ÿÇa/‰e²j$ܪ¶p¬` e'¦)[#tðÞµÔ«&û>¦ ®˜e–Ãc endstream endobj 202 0 obj 121 endobj 201 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 121 0 obj << /Length 204 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 57 162 82 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 203 0 R >> stream xœŒ± A Dû|Åü€1Ùlv/_ wWŠ…(‡…¿oV†aæ3; †–ŽwÁëCÎV&‰†/)Îé7]o<©â‚ú_F <6RmìíÁ¢Ô„=›¶Î½¶äà–\¸Œô‰Í=Y¸ÖüÀŠ™fú÷h endstream endobj 204 0 obj 121 endobj 203 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 124 0 obj << /Length 206 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 113 80 143 100 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 205 0 R >> stream xœŒ1 ƒPû=Å\ ›]¿_ÿž@R¨e° B,$…×WÃc˜jÞ*ƹ±ãú0Þ?ÉšªbѰ‰Ó|ä>cj¼¤æÆŠÿ‹Ë©*ÏE<…¶‘ðÚµ”–÷Fsà9ëqÆ—‰AÙói endstream endobj 206 0 obj 105 endobj 205 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 127 0 obj << /Length 208 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 53 29 120 63 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 207 0 R >> stream xœŒÍ Â@ƒïóyÇùéNwŸ  ôÐzRAz(|}g%„ð’ƒ]ë„óCðúPa·*-ð%Å%ý¦Û‚' ˜q@ÿ‹Só†m'ÕàÒ`\‹aGsö:BkðW–èÙ—`ë865l¸b¡…~Ê#Þ endstream endobj 208 0 obj 119 endobj 207 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 130 0 obj << /Length 210 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 72 57 120 82 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 209 0 R >> stream xœE‹± Â@DûýŠù×ÙËÞ]ö Á"Z‹€ ¤þ~.62<†Ç0›Gîœ'âõ‘¬]ê_1\oŸ ‹8nØ`¿Çé¨ÔæUÌŠæ€ÕPZ £kÔ +Y¶Ù›QÝÕµOñÀ ƒìÇ¡Ø endstream endobj 210 0 obj 117 endobj 209 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 133 0 obj << /Length 212 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 90 80 120 100 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 211 0 R >> stream xœŒ± Â@ûýŠù¬»¹»x÷!ÅÅR,DA¤þ~.2<¦z³‰q0œÆû+ICŸ­ üĹ´}ävÇÔxIdbÃÿîP ÏUJÐÏxtÍÍ+‚§¤­Å•*UvÜê7 endstream endobj 212 0 obj 104 endobj 211 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 136 0 obj << /Length 214 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 25 57 59 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 213 0 R >> stream xœ‹1 Q ûœâ]À˜—ŸŸÍž@,VK±a‹ÅÂëëÊ0L5«6Îìï†ç[º6/!Ž?_r½ÁÔðÀ +ø?v[¼˜驞£ :5`oZˆP&ØõHxi°@–ff\0É$_¨.‘ endstream endobj 214 0 obj 117 endobj 213 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 139 0 obj << /Length 216 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 53 75 78 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 215 0 R >> stream xœ‹1 Q ûœâ]À˜ä'ùù'‹ÕR,dAØb±ðúº2 SÍJ‚óû»àù¦àf%#ñ!Åñç‹®7 ä8a…þÝkóBݹ̡)ì>° ÷PoÜ£Áá ÚŒS‘liP-Îr̸`¢‰¾Ê'à endstream endobj 216 0 obj 118 endobj 215 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 142 0 obj << /Length 218 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 76 94 97 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 217 0 R >> stream xœ‹1 Â@û}Å|ÀÍnîrÙ{A@°ˆ–’"(bŠ`‘ï›È0L5«×f6^_é4µaµ°‰sÞ}Ë}ÂÔxJæÂŠÿÓ‘6U‹ôUsép-‘Y¨ISôxv½nŒ2ÊÝ»@ endstream endobj 218 0 obj 103 endobj 217 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 145 0 obj << /Length 220 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 174 57 208 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 219 0 R >> stream xœŒ= Â`Dû=Å\Àug¿ß=A@°ˆ–b!!E°ðú~‘ax0ðfÞ˄ãÃðúHÑäÝ¢â+Äiô-·;L OÉ8cÿÆa‡§À² [Õ`[¨Ñ±‚ZJ€¥èxôg05õ\á–µUÙµŽ}Á³Ìò¥t endstream endobj 220 0 obj 121 endobj 219 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 148 0 obj << /Length 222 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 155 75 180 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 221 0 R >> stream xœLA A »÷ù€µÎt:/X<¬Ѭ {X<ø}»BH²‘`ÇeÂñ!x}¨±•áø’â”|ÓíaÁ“*ÎØ ÿÅa—bËJÚ‚­5¨ ×:°¦+<òD«rDÏÜÙ-Õ »d³; ¨{T,¸b¦™~<е endstream endobj 222 0 obj 121 endobj 221 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 151 0 obj << /Length 224 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 137 94 157 123 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 223 0 R >> stream xœ‹K AC÷uŠ\À²>]ÝÕ'\Œ.Å…Œ ³\x}{$„ðB²‘`×eÂñ!x}(Ø-¥W|Iq~ÓíaÁ“ ÎØ ÿÇaóŽe% ç¦Õäš+´46kP .ÝGV¨WKïܺ^9³aÁ3Íô8É¡ endstream endobj 224 0 obj 123 endobj 223 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 154 0 obj << /Length 226 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 174 117 208 184 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 225 0 R >> stream xœ‹A Â@ïóŠþ€ãôìîdöÁCô($‚ ä<ø}iŠ¢½ŠaßeÄñax}¤iñ´ø qÚxËíSÃS*ÎXÁÿã°ËKǼ‡ÐÎDK-­a³ª³!CÙ;Ø]Ã4S:áVuˆ­™Y1ãŠI&ù:3 endstream endobj 226 0 obj 121 endobj 225 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 157 0 obj << /Length 228 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 155 117 180 165 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 227 0 R >> stream xœ-‹Á Â@CïóùÇÉÎîìîÕ£x ‚ÐCñàïÛ !<’,bØtp|^)ê©Y|…8­~ËíSÃS2ÎXÀýqØ"yÇ4 KS/5´³aƒêLèI£å«†WвÖHàH¶½ŸpÅ(£üîL endstream endobj 228 0 obj 120 endobj 227 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 160 0 obj << /Length 230 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 137 117 157 147 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 229 0 R >> stream xœ‹1 Â@û}Å|Àu7{—ܾ@R$–b! ‚˜"Xø} ÃT³Š±1Ø_Ç[ªF×,{>â>å|ÁÔ¸KadÅÿÇnKÉm¯¡ƒWÜ›ö­°à‘:dUKãʼnI&ùÜ 6 endstream endobj 230 0 obj 103 endobj 229 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 163 0 obj << /Length 232 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 25 117 59 184 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 231 0 R >> stream xœ‹K ÂP÷sо€ã|_æ ¸ˆ.Å…D„,‚ ¯o"MQPÐ+ ö]F‚ׇ’ÝJz×§7Ýî<)pÆ ý?»Ì;æ…²±5C{&¤r3ÅÐÙk@{@EX·hÅ¡ÕâVWL4Ñrº. endstream endobj 232 0 obj 117 endobj 231 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 166 0 obj << /Length 234 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 53 117 78 165 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 233 0 R >> stream xœ‹± A Dû|Åü€1Éf³Ù/8,NK±áŠÃÂßwO†7¯f#ÁžË„ãCðúPåb)=ð%Åið¦Û‚'9ÎØ ÿÇa—•Že¥æœæhÁ]+𰦣 ŽÊÕ Tœ[j° ©&ÇX\1ÓL?vŒF endstream endobj 234 0 obj 118 endobj 233 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 169 0 obj << /Length 236 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /BBox [ 76 117 97 147 ] /Group << /Type /Group /S /Transparency /I true /CS /DeviceRGB >> /Resources 235 0 R >> stream xœ‹; ÂPû=Å\À;¼OvO 1e°AL,r} ÃT³Š±s9ÒÝŒçGªæÞ-›$N?_2_15R8³’þÇaOŸƒû"Chi•”\›"kö¨Zœ7£Œò±ÐÝ endstream endobj 236 0 obj 102 endobj 235 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 1 0 obj << /Type /Pages /Kids [ 71 0 R ] /Count 1 >> endobj 237 0 obj << /Creator (cairo 1.12.2 (http://cairographics.org)) /Producer (cairo 1.12.2 (http://cairographics.org)) >> endobj 238 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 239 0000000000 65535 f 0000086018 00000 n 0000038369 00000 n 0000000015 00000 n 0000038345 00000 n 0000040506 00000 n 0000040050 00000 n 0000041432 00000 n 0000040976 00000 n 0000042358 00000 n 0000041901 00000 n 0000043280 00000 n 0000042824 00000 n 0000044201 00000 n 0000043746 00000 n 0000045121 00000 n 0000044666 00000 n 0000046046 00000 n 0000045590 00000 n 0000046971 00000 n 0000046515 00000 n 0000047889 00000 n 0000047436 00000 n 0000048821 00000 n 0000048360 00000 n 0000049756 00000 n 0000049294 00000 n 0000050691 00000 n 0000050229 00000 n 0000051623 00000 n 0000051162 00000 n 0000052555 00000 n 0000052094 00000 n 0000053487 00000 n 0000053026 00000 n 0000054417 00000 n 0000053957 00000 n 0000055347 00000 n 0000054887 00000 n 0000056276 00000 n 0000055816 00000 n 0000057203 00000 n 0000056744 00000 n 0000058130 00000 n 0000057671 00000 n 0000059056 00000 n 0000058597 00000 n 0000059983 00000 n 0000059524 00000 n 0000060910 00000 n 0000060451 00000 n 0000061837 00000 n 0000061378 00000 n 0000062769 00000 n 0000062308 00000 n 0000063701 00000 n 0000063240 00000 n 0000064633 00000 n 0000064172 00000 n 0000065568 00000 n 0000065106 00000 n 0000066503 00000 n 0000066041 00000 n 0000067437 00000 n 0000066975 00000 n 0000068367 00000 n 0000067907 00000 n 0000069297 00000 n 0000068837 00000 n 0000070226 00000 n 0000069766 00000 n 0000039439 00000 n 0000039668 00000 n 0000070315 00000 n 0000040446 00000 n 0000040593 00000 n 0000070777 00000 n 0000041372 00000 n 0000041519 00000 n 0000071240 00000 n 0000042298 00000 n 0000042445 00000 n 0000071702 00000 n 0000043220 00000 n 0000043368 00000 n 0000072164 00000 n 0000044141 00000 n 0000044289 00000 n 0000072621 00000 n 0000045061 00000 n 0000045209 00000 n 0000073083 00000 n 0000045986 00000 n 0000046134 00000 n 0000073545 00000 n 0000046911 00000 n 0000047059 00000 n 0000074006 00000 n 0000047829 00000 n 0000047977 00000 n 0000074621 00000 n 0000048760 00000 n 0000048910 00000 n 0000075101 00000 n 0000049694 00000 n 0000049845 00000 n 0000075584 00000 n 0000050629 00000 n 0000050780 00000 n 0000076047 00000 n 0000051561 00000 n 0000051712 00000 n 0000076523 00000 n 0000052493 00000 n 0000052644 00000 n 0000077003 00000 n 0000053425 00000 n 0000053576 00000 n 0000077462 00000 n 0000054355 00000 n 0000054506 00000 n 0000077943 00000 n 0000055285 00000 n 0000055436 00000 n 0000078424 00000 n 0000056214 00000 n 0000056365 00000 n 0000078890 00000 n 0000057141 00000 n 0000057292 00000 n 0000079368 00000 n 0000058068 00000 n 0000058219 00000 n 0000079844 00000 n 0000058994 00000 n 0000059145 00000 n 0000080308 00000 n 0000059921 00000 n 0000060072 00000 n 0000080784 00000 n 0000060848 00000 n 0000060999 00000 n 0000081261 00000 n 0000061775 00000 n 0000061926 00000 n 0000081723 00000 n 0000062707 00000 n 0000062858 00000 n 0000082205 00000 n 0000063639 00000 n 0000063790 00000 n 0000082687 00000 n 0000064571 00000 n 0000064722 00000 n 0000083171 00000 n 0000065506 00000 n 0000065657 00000 n 0000083654 00000 n 0000066441 00000 n 0000066592 00000 n 0000084136 00000 n 0000067375 00000 n 0000067526 00000 n 0000084601 00000 n 0000068305 00000 n 0000068456 00000 n 0000085078 00000 n 0000069235 00000 n 0000069386 00000 n 0000085556 00000 n 0000070164 00000 n 0000070703 00000 n 0000070679 00000 n 0000071166 00000 n 0000071142 00000 n 0000071628 00000 n 0000071604 00000 n 0000072090 00000 n 0000072066 00000 n 0000072547 00000 n 0000072524 00000 n 0000073009 00000 n 0000072985 00000 n 0000073471 00000 n 0000073447 00000 n 0000073932 00000 n 0000073908 00000 n 0000074547 00000 n 0000074523 00000 n 0000075027 00000 n 0000075003 00000 n 0000075510 00000 n 0000075486 00000 n 0000075973 00000 n 0000075949 00000 n 0000076449 00000 n 0000076425 00000 n 0000076929 00000 n 0000076905 00000 n 0000077388 00000 n 0000077365 00000 n 0000077869 00000 n 0000077845 00000 n 0000078350 00000 n 0000078326 00000 n 0000078816 00000 n 0000078792 00000 n 0000079294 00000 n 0000079270 00000 n 0000079770 00000 n 0000079746 00000 n 0000080234 00000 n 0000080210 00000 n 0000080710 00000 n 0000080686 00000 n 0000081187 00000 n 0000081163 00000 n 0000081649 00000 n 0000081625 00000 n 0000082131 00000 n 0000082107 00000 n 0000082613 00000 n 0000082589 00000 n 0000083097 00000 n 0000083073 00000 n 0000083580 00000 n 0000083556 00000 n 0000084062 00000 n 0000084038 00000 n 0000084527 00000 n 0000084503 00000 n 0000085004 00000 n 0000084980 00000 n 0000085482 00000 n 0000085458 00000 n 0000085944 00000 n 0000085920 00000 n 0000086084 00000 n 0000086213 00000 n trailer << /Size 239 /Root 238 0 R /Info 237 0 R >> startxref 86267 %%EOF gnunet-0.10.1/contrib/gnunet_janitor.py.in0000644000175000017500000000511112221077151015453 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2011 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Finds any gnunet processes still running in the system and kills them # # gnunet janitor can be used by invoking `make' like this: # TESTS_ENVIRONMENT='${top_srcdir}/contrib/gnunet_janitor.py &&' make check from __future__ import print_function import os import re import subprocess import sys import shutil import time import signal import terminate if os.name == 'nt': from win32com.client import GetObject WMI = GetObject('winmgmts:') def get_process_list (): result = [] if os.name == 'nt': processes = WMI.InstancesOf('Win32_Process') for p in processes: result.append ((p.Properties_('ProcessId').Value, re.sub (r'(.+)\.exe', r'\1', p.Properties_('Name').Value))) else: pids = [pid for pid in os.listdir('/proc') if pid.isdigit ()] for pid in pids: with open (os.path.join ('/proc', pid, 'cmdline'), 'rb') as p: cmdline = p.read ().split ('\x00') if len (cmdline) > 0: result.append ((pid, cmdline[0])) return result def main (): procs = get_process_list () gnunet_procs = [] for p in procs: if re.match (r'gnunet-.+', p[1]): gnunet_procs.append (p) for p in gnunet_procs: if re.match (r'gnunet-service-arm', p[1]): print ("killing arm process {0:5} {1}".format (p[0], p[1])) try: terminate.safe_terminate_process_by_pid (int (p[0]), 1) except OSError as e: print ("failed: {0}".format (e)) pass for p in gnunet_procs: if not re.match (r'gnunet-service-arm', p[1]): print ("killing non-arm process {0:5} {1}".format (p[0], p[1])) try: terminate.safe_terminate_process_by_pid (int (p[0]), 1) except OSError as e: print ("failed: {0}".format (e)) pass if __name__ == '__main__': sys.exit (main ()) gnunet-0.10.1/contrib/pydiffer.py.in0000644000175000017500000000165612221077151014247 00000000000000#!@PYTHON@ import os import sys import difflib import filecmp def getdiff (old, new): diff = [] with open (old) as a: with open (new) as b: for l in difflib.unified_diff (a.read ().splitlines (), b.read ().splitlines ()): diff.append (l) return diff def dc_getdiff (dc, old, new): diff = [] for f in dc.left_only: diff.append ("Only in {}: {}".format (old, f)) for f in dc.right_only: diff.append ("Only in {}: {}".format (new, f)) for f in dc.diff_files: r = getdiff (os.path.join (old, f), os.path.join (new, f)) diff.extend (r) for dn, dc in dc.subdirs.items (): r = dc_getdiff (dc, os.path.join (old, dn), os.path.join (new, dn)) diff.extend (r) return diff def dcdiff (old, new): dc = filecmp.dircmp (old, new) diff = dc_getdiff (dc, old, new) return diff def main (): for l in dcdiff (sys.argv[1], sys.argv[2]): print (l) if __name__ == '__main__': main () gnunet-0.10.1/contrib/Makefile.in0000644000175000017500000012714112320752057013530 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ noinst_PROGRAMS = timeout_watchdog$(EXEEXT) check_PROGRAMS = test_gnunet_prefix$(EXEEXT) subdir = contrib DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgdata_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) am_test_gnunet_prefix_OBJECTS = \ test_gnunet_prefix-test_gnunet_prefix.$(OBJEXT) test_gnunet_prefix_OBJECTS = $(am_test_gnunet_prefix_OBJECTS) am__DEPENDENCIES_1 = test_gnunet_prefix_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__timeout_watchdog_SOURCES_DIST = timeout_watchdog.c \ timeout_watchdog_w32.c @MINGW_FALSE@am_timeout_watchdog_OBJECTS = timeout_watchdog.$(OBJEXT) @MINGW_TRUE@am_timeout_watchdog_OBJECTS = \ @MINGW_TRUE@ timeout_watchdog_w32.$(OBJEXT) timeout_watchdog_OBJECTS = $(am_timeout_watchdog_OBJECTS) timeout_watchdog_LDADD = $(LDADD) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgdatadir)" \ "$(DESTDIR)$(tap32dir)" "$(DESTDIR)$(tap64dir)" SCRIPTS = $(bin_SCRIPTS) $(noinst_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(test_gnunet_prefix_SOURCES) $(timeout_watchdog_SOURCES) DIST_SOURCES = $(test_gnunet_prefix_SOURCES) \ $(am__timeout_watchdog_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_pkgdata_DATA) $(tap32_DATA) $(tap64_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include tap32dir = $(pkgdatadir)/openvpn-tap32/tapw32/ tap64dir = $(pkgdatadir)/openvpn-tap32/tapw64/ @MINGW_FALSE@timeout_watchdog_SOURCES = \ @MINGW_FALSE@ timeout_watchdog.c @MINGW_TRUE@timeout_watchdog_SOURCES = \ @MINGW_TRUE@ timeout_watchdog_w32.c noinst_SCRIPTS = \ terminate.py \ pydiffer.py \ gnunet_pyexpect.py \ gnunet_janitor.py bin_SCRIPTS = \ gnunet-gns-import.sh dist_pkgdata_DATA = \ gns-bcd.html \ gns-bcd.tex \ gnunet-logo.pdf \ gnunet-logo-color.png \ testing_hostkeys.ecc @MINGW_TRUE@tap32_DATA = \ @MINGW_TRUE@ openvpn-tap32/tapw32/tap0901.sys \ @MINGW_TRUE@ openvpn-tap32/tapw32/tap0901.cat \ @MINGW_TRUE@ openvpn-tap32/tapw32/OemWin2k.inf @MINGW_TRUE@tap64_DATA = \ @MINGW_TRUE@ openvpn-tap32/tapw64/tap0901.sys \ @MINGW_TRUE@ openvpn-tap32/tapw64/tap0901.cat \ @MINGW_TRUE@ openvpn-tap32/tapw64/OemWin2k.inf EXTRA_DIST = \ coverage.sh \ report.sh \ terminate.py.in \ gnunet_pyexpect.py.in \ gnunet_janitor.py.in \ pydiffer.py.in \ gnunet-gns-import.sh \ openvpn-tap32/tapw32/tap0901.sys \ openvpn-tap32/tapw32/tap0901.cat \ openvpn-tap32/tapw32/OemWin2k.inf \ openvpn-tap32/tapw64/tap0901.sys \ openvpn-tap32/tapw64/tap0901.cat \ openvpn-tap32/tapw64/OemWin2k.inf \ openvpn-tap32/INSTALL \ openvpn-tap32/tap32-signed-i386-2.1.zip \ openvpn-tap32/tap32-source-2.1.zip CLEANFILES = \ $(noinst_SCRIPTS) do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_gnunet_prefix_SOURCES = \ test_gnunet_prefix.c test_gnunet_prefix_CPPFLAGS = \ $(LTDLINCL) $(AM_CPPFLAGS) test_gnunet_prefix_LDADD = \ $(GCLIBADD) $(WINLIB) \ $(LTLIBICONV) \ $(GN_LIBINTL) \ $(LIBLTDL) -lunistring $(XLIB) pkghellodir = $(pkgdatadir)/hellos all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu contrib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list test_gnunet_prefix$(EXEEXT): $(test_gnunet_prefix_OBJECTS) $(test_gnunet_prefix_DEPENDENCIES) $(EXTRA_test_gnunet_prefix_DEPENDENCIES) @rm -f test_gnunet_prefix$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_prefix_OBJECTS) $(test_gnunet_prefix_LDADD) $(LIBS) timeout_watchdog$(EXEEXT): $(timeout_watchdog_OBJECTS) $(timeout_watchdog_DEPENDENCIES) $(EXTRA_timeout_watchdog_DEPENDENCIES) @rm -f timeout_watchdog$(EXEEXT) $(AM_V_CCLD)$(LINK) $(timeout_watchdog_OBJECTS) $(timeout_watchdog_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_prefix-test_gnunet_prefix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeout_watchdog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeout_watchdog_w32.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< test_gnunet_prefix-test_gnunet_prefix.o: test_gnunet_prefix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_prefix_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_prefix-test_gnunet_prefix.o -MD -MP -MF $(DEPDIR)/test_gnunet_prefix-test_gnunet_prefix.Tpo -c -o test_gnunet_prefix-test_gnunet_prefix.o `test -f 'test_gnunet_prefix.c' || echo '$(srcdir)/'`test_gnunet_prefix.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_prefix-test_gnunet_prefix.Tpo $(DEPDIR)/test_gnunet_prefix-test_gnunet_prefix.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_prefix.c' object='test_gnunet_prefix-test_gnunet_prefix.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_prefix_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_prefix-test_gnunet_prefix.o `test -f 'test_gnunet_prefix.c' || echo '$(srcdir)/'`test_gnunet_prefix.c test_gnunet_prefix-test_gnunet_prefix.obj: test_gnunet_prefix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_prefix_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_prefix-test_gnunet_prefix.obj -MD -MP -MF $(DEPDIR)/test_gnunet_prefix-test_gnunet_prefix.Tpo -c -o test_gnunet_prefix-test_gnunet_prefix.obj `if test -f 'test_gnunet_prefix.c'; then $(CYGPATH_W) 'test_gnunet_prefix.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_prefix.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_prefix-test_gnunet_prefix.Tpo $(DEPDIR)/test_gnunet_prefix-test_gnunet_prefix.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_prefix.c' object='test_gnunet_prefix-test_gnunet_prefix.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_prefix_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_prefix-test_gnunet_prefix.obj `if test -f 'test_gnunet_prefix.c'; then $(CYGPATH_W) 'test_gnunet_prefix.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_prefix.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgdataDATA: $(dist_pkgdata_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ done uninstall-dist_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) install-tap32DATA: $(tap32_DATA) @$(NORMAL_INSTALL) @list='$(tap32_DATA)'; test -n "$(tap32dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(tap32dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(tap32dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(tap32dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(tap32dir)" || exit $$?; \ done uninstall-tap32DATA: @$(NORMAL_UNINSTALL) @list='$(tap32_DATA)'; test -n "$(tap32dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(tap32dir)'; $(am__uninstall_files_from_dir) install-tap64DATA: $(tap64_DATA) @$(NORMAL_INSTALL) @list='$(tap64_DATA)'; test -n "$(tap64dir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(tap64dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(tap64dir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(tap64dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(tap64dir)" || exit $$?; \ done uninstall-tap64DATA: @$(NORMAL_UNINSTALL) @list='$(tap64_DATA)'; test -n "$(tap64dir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(tap64dir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_gnunet_prefix.log: test_gnunet_prefix$(EXEEXT) @p='test_gnunet_prefix$(EXEEXT)'; \ b='test_gnunet_prefix'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(tap32dir)" "$(DESTDIR)$(tap64dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dist_pkgdataDATA \ install-tap32DATA install-tap64DATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binSCRIPTS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binSCRIPTS uninstall-dist_pkgdataDATA \ uninstall-tap32DATA uninstall-tap64DATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am dist-hook \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binSCRIPTS \ install-data install-data-am install-data-local \ install-dist_pkgdataDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ install-tap32DATA install-tap64DATA installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binSCRIPTS uninstall-dist_pkgdataDATA \ uninstall-tap32DATA uninstall-tap64DATA %.py: %.py.in Makefile $(do_subst) < $< > $@ chmod +x $@ install-data-local: $(mkinstalldirs) $(DESTDIR)$(pkghellodir) @$(NORMAL_INSTALL) for hello in $(srcdir)/hellos/*; do \ if test -f $$hello; then \ $(INSTALL_DATA) $$hello $(DESTDIR)$(pkghellodir)/ ; \ fi \ done dist-hook: if test -d $(srcdir)/hellos; then \ mkdir -p $(distdir)/hellos; \ for hello in $(srcdir)/hellos/*; do \ if test -f $$hello; then \ cp -p $$hello $(distdir)/hellos; \ fi \ done \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/contrib/test_gnunet_prefix.c0000644000175000017500000000372012320751570015536 00000000000000/* This file is part of GNUnet (C) 2011, 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** * @file contrib/test_gnunet_prefix.c * @brief test if environment variable GNUNET_PREFIX is set so that * we have a chance to run tests * @author Christian Grothoff */ #include "platform.h" int main (int argc, char **argv) { const char *basename; const char *dirname; basename = getenv ("GNUNET_PREFIX"); if (NULL == basename) { fprintf (stderr, _("Environment variable GNUNET_PREFIX not set\n")); fprintf (stderr, _("Testcases will not work!\n")); return 1; } dirname = DIR_SEPARATOR_STR ".." DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR "config.d"; { char tmp[strlen (basename) + strlen (dirname) + 1]; sprintf (tmp, "%s%s", basename, dirname); if (0 != access (tmp, R_OK)) { fprintf (stderr, _("Failed to access `%s': %s\n"), tmp, STRERROR (errno)); fprintf (stderr, _("Check that you did run `make install' and that GNUNET_PREFIX='%s' is the correct prefix.\n"), basename); fprintf (stderr, _("Testcases will not work!\n")); return 2; } } return 0; } gnunet-0.10.1/contrib/gnunet-gns-import.sh0000755000175000017500000000501212272443212015403 00000000000000#!/bin/sh # This shell-script will import some GNS authorities into your GNS # namestore. LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools not found, check environmental variables PATH and GNUNET_PREFIX" exit 1 fi gnunet-arm -I 1> /dev/null 2>/dev/null if [ ! $? -eq 0 ] then echo "GNUnet is not running, please start GNUnet before running import" exit 1 fi options='' while getopts "c:" opt; do case $opt in c) options+="-c $OPTARG" ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done # By default, we create three GNS zones: gnunet-identity -C master-zone $options gnunet-identity -C short-zone $options gnunet-identity -C private-zone $options # Additionally, we create the FS SKS zone gnunet-identity -C sks-zone $options # Integrate those with the respective subsystems. gnunet-identity -e short-zone -s gns-short $options gnunet-identity -e master-zone -s gns-master $options gnunet-identity -e master-zone -s namestore $options gnunet-identity -e master-zone -s gns-proxy $options gnunet-identity -e master-zone -s phone-ego $options gnunet-identity -e private-zone -s gns-private $options gnunet-identity -e sks-zone -s fs-sks $options # Get the public keys as strings (so we can create PKEY records) MASTER=`gnunet-identity -d $options | grep master-zone | awk '{print $3}'` SHORT=`gnunet-identity -d $options | grep short-zone | awk '{print $3}'` PRIVATE=`gnunet-identity -d $options | grep private-zone | awk '{print $3}'` PIN=72QC35CO20UJN1E91KPJFNT9TG4CLKAPB4VK9S3Q758S9MLBRKOG # Link short and private zones into master zone if (gnunet-namestore -z master-zone -D -n private -t PKEY | grep "PKEY: $PRIVATE" 1>/dev/null) then echo "Private zone link exists, skipping" else gnunet-namestore -z master-zone -a -e never -n private -p -t PKEY -V $PRIVATE $options fi if (gnunet-namestore -z master-zone -D -n short -t PKEY | grep "PKEY: $SHORT" 1>/dev/null) then echo "Shorten zone link exists, skipping" else gnunet-namestore -z master-zone -a -e never -n short -p -t PKEY -V $SHORT $options fi # Link GNUnet's FCFS zone into master zone under label "pin" if (gnunet-namestore -z master-zone -D -n pin -t PKEY | grep "PKEY: $PIN" 1>/dev/null) then echo "Pin zone link exists, skipping" else gnunet-namestore -z master-zone -a -e never -n pin -p -t PKEY -V $PIN $options fi gnunet-0.10.1/contrib/report.sh0000755000175000017500000001321512017074155013330 00000000000000#!/bin/sh TEST=`type type|grep not` if test -n "$TEST"; then WHICH=which else WHICH=type fi echo "Please submit the following information with your bug report: " echo "--------------------------------------------------------------" OS=`uname -s 2>/dev/null` echo "OS : $OS" REL=`uname -r 2>/dev/null` echo "OS RELEASE : $REL" HW=`uname -m 2>/dev/null` echo "HARDWARE : $HW" TEST=`$WHICH gcc 2>/dev/null` if test -n "$TEST"; then VERS=`gcc --version 2>/dev/null | head -n 1` echo "gcc : $VERS" else echo "gcc : Not Found"; fi TEST=`$WHICH gmake 2>/dev/null` if test -n "$TEST" ; then gmake --version 2>/dev/null |\ awk -F, '{print $1}' |\ awk '/GNU Make/{print "GNU gmake :",$NF}' else TEST=`make --version 2>/dev/null` if test -n "$TEST"; then make --version 2>/dev/null |\ awk -F, '{print $1}' |\ awk '/GNU Make/{print "make :",$NF}' else echo "make : Not Found" fi fi TEST=`$WHICH autoconf 2>/dev/null` if test -n "$TEST"; then autoconf --version |\ head -n 1 |\ awk '{\ if (length($4) == 0) {\ print "autoconf : "$3\ } else {\ print "autoconf : "$4\ }}' else echo "autoconf : Not Found" fi TEST=`$WHICH automake 2>/dev/null` if test -n "$TEST"; then automake --version 2>/dev/null |\ head -n 1 |\ awk '{print "automake : "$4}' else echo "automake : Not Found" fi TEST=`$WHICH libtool 2>/dev/null` if test -n "$TEST"; then libtool --version 2>/dev/null |\ head -n 1 |\ awk '{print "libtool : "$4}' else echo "libtool : Not Found" fi TEST=`$WHICH extract 2>/dev/null` if test -n "$TEST"; then extract -v 2>/dev/null |\ head -n 1 |\ awk '{print "libextractor : "$2}' else echo "libextractor : Not Found" fi if test -x gnunetd; then gnunetd -v | sed -e "s/v//" 2>/dev/null |\ awk '{print "GNUnet 0.8 : "$2 (may conflict!)}' else echo "GNUnet 0.8 : Not Found (good)" fi TEST=`$WHICH gnunet-arm 2>/dev/null` if test -n "$TEST"; then gnunet-arm -v | sed -e "s/v//" 2>/dev/null |\ awk '{print "GNUnet 0.9 : "$2}' else echo "GNUnet 0.9 : Not Found" fi TEST=`$WHICH libgcrypt-config 2> /dev/null` if test -n "$TEST"; then libgcrypt-config --version 2> /dev/null | \ awk '{print "libgcrypt : "$1}' else echo "libgcrypt : Not Found" fi TEST=`$WHICH mysql_config 2> /dev/null` if test -n "$TEST"; then mysql_config --version 2> /dev/null | \ awk '{print "mysql : "$1}' else echo "mysql : Not Found" fi TEST=`$WHICH pkg-config 2> /dev/null` if test -n "$TEST"; then pkg-config --version 2> /dev/null | \ awk '{print "pkg-config : "$1}' else echo "pkg-config : Not Found" fi TEST=`$WHICH pkg-config 2> /dev/null` if test -n "$TEST"; then pkg-config --modversion glib-2.0 2> /dev/null | \ awk '{print "glib2 : "$1}' else echo "glib2 : Not Found" fi TEST=`$WHICH pkg-config 2> /dev/null` if test -n "$TEST"; then pkg-config --modversion gtk+-2.0 2> /dev/null | \ awk '{print "gtk2+ : "$1}' else echo "gtk2+ : Not Found" fi TEST=`$WHICH dpkg 2> /dev/null` if test -n "$TEST"; then LINES=`dpkg -s libgmp3-dev | grep Version | wc -l` if test "$LINES" = "1" then VERSION=`dpkg -s libgmp3-dev | grep Version | awk '{print $2}'` echo "GMP : libgmp3-dev-$VERSION.deb" else echo "GMP : dpkg: libgmp3-dev not installed" fi else TEST=`$WHICH rpm 2> /dev/null` if test -n "$TEST"; then rpm -q gmp | sed -e "s/gmp-//" 2> /dev/null | \ awk '{print "GMP : "$1.rpm}' else echo "GMP : Test not available" fi fi TEST=`$WHICH dpkg 2> /dev/null` if test -n "$TEST"; then LINES=`dpkg -s libunistring-dev | grep Version | wc -l` if test "$LINES" = "1" then VERSION=`dpkg -s libunistring-dev | grep Version | awk '{print $2}'` echo "libunistring : libunistring3-dev-$VERSION.deb" else echo "libunistring : dpkg: libunistring3-dev not installed" fi else TEST=`$WHICH rpm 2> /dev/null` if test -n "$TEST"; then rpm -q unistring | sed -e "s/unistring-//" 2> /dev/null | \ awk '{print "libunistring : "$1.rpm}' else echo "libunistring : Test not available" fi fi TEST=`$WHICH gettext 2> /dev/null` if test -n "$TEST"; then gettext --version | head -n1 2> /dev/null | \ awk '{print "GNU gettext : "$4}' else echo "GNU gettext : Not found" fi TEST=`$WHICH curl-config 2> /dev/null` if test -n "$TEST"; then curl-config --version | head -n1 2> /dev/null | \ awk '{print "libcurl : "$2}' else echo "libcurl : Not found" fi echo -n "libmicrohttpd : " TMPFILE=`mktemp /tmp/mhd-version-testXXXXXX` cat - >$TMPFILE.c < #include int main() { fprintf (stdout, "%X\n", MHD_VERSION); return 0; } EOF gcc -o $TMPFILE $TMPFILE.c 2> /dev/null && $TMPFILE || echo "Not found" rm -f $TMPFILE $TMPFILE.bin echo -n "GNU GLPK : " TMPFILE=`mktemp /tmp/glpk-version-testXXXXXX` cat - >$TMPFILE.c < #include int main() { fprintf (stdout, "%u.%u\n", GLP_MAJOR_VERSION, GLP_MINOR_VERSION); return 0; } EOF gcc -o $TMPFILE $TMPFILE.c 2> /dev/null && $TMPFILE || echo "Not found" rm -f $TMPFILE $TMPFILE.bin echo -n "GNUtls : " TMPFILE=`mktemp /tmp/gnutls-version-testXXXXXX` cat - >$TMPFILE.c < #include int main() { fprintf (stdout, "%s\n", GNUTLS_VERSION); return 0; } EOF gcc -o $TMPFILE $TMPFILE.c 2> /dev/null && $TMPFILE || echo "Not found" rm -f $TMPFILE $TMPFILE.bin echo "--------------------------------------------------------------" gnunet-0.10.1/contrib/terminate.py.in0000644000175000017500000000433012221077151014417 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2011 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Utility module that implements safe process termination for W32. # For other platforms it's equivalent to Popen.kill () # Requires pywin32 on W32. import sys import os import subprocess if os.name == 'nt': import win32api import win32process class dummyobj (object): pass def safe_terminate_process_by_pid (pid, code): if os.name == 'nt': p = dummyobj () p._handle = win32api.OpenProcess (2 | 1024 | 8 | 32 | 16, 0, pid) result = safe_terminate_process (p, code) win32api.CloseHandle (p._handle) return result else: return os.kill (int (pid), SIGKILL) def safe_terminate_process (proc, code): if os.name == 'nt': cp = win32api.GetCurrentProcess () result = False dupproc = win32api.DuplicateHandle (cp, proc._handle, cp, 2 | 1024 | 8 | 32 | 16, 0, 0) try: exitcode = win32process.GetExitCodeProcess (dupproc) if exitcode == 0x103: kernel32 = win32api.GetModuleHandle ("kernel32") exitprocess = win32api.GetProcAddress (kernel32, "ExitProcess") th, tid = win32process.CreateRemoteThread (dupproc, None, 0, exitprocess, code, 0) win32api.CloseHandle (th) result = True else: result = True # except failed to get exit code? failed to get module handle? finally: win32api.CloseHandle (dupproc) return result else: return proc.kill () gnunet-0.10.1/contrib/timeout_watchdog.c0000644000175000017500000000526712225777501015206 00000000000000/* This file is part of GNUnet (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file contrib/timeout_watchdog.c * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period * @author Matthias Wachs */ #include #include #include #include #include #include static pid_t child; static void sigchld_handler (int val) { int status = 0; int ret = 0; waitpid (child, &status, 0); if (WIFEXITED (status) != 0) { ret = WEXITSTATUS (status); printf ("Test process exited with result %u\n", ret); } if (WIFSIGNALED (status) != 0) { ret = WTERMSIG (status); printf ("Test process was signaled %u\n", ret); } exit (ret); } static void sigint_handler (int val) { kill (0, val); exit (val); } int main (int argc, char *argv[]) { int timeout = 0; pid_t gpid = 0; if (argc < 3) { printf ("arg 1: timeout in sec., arg 2: executable, arg arguments\n"); exit (1); } timeout = atoi (argv[1]); if (timeout == 0) timeout = 600; /* with getpgid() it does not compile, but getpgrp is the BSD version and working */ gpid = getpgrp (); signal (SIGCHLD, sigchld_handler); signal (SIGABRT, sigint_handler); signal (SIGFPE, sigint_handler); signal (SIGILL, sigint_handler); signal (SIGINT, sigint_handler); signal (SIGSEGV, sigint_handler); signal (SIGTERM, sigint_handler); child = fork (); if (child == 0) { /* int setpgrp(pid_t pid, pid_t pgid); is not working on this machine */ //setpgrp (0, pid_t gpid); if (-1 != gpid) setpgid (0, gpid); execvp (argv[2], &argv[2]); exit (1); } if (child > 0) { sleep (timeout); printf ("Child processes were killed after timeout of %u seconds\n", timeout); kill (0, SIGTERM); exit (1); } exit (1); } /* end of timeout_watchdog.c */ gnunet-0.10.1/contrib/testing_hostkeys.ecc0000644000175000017500000040000012236654562015541 00000000000000,E.‚Pݳ&‹0vvxRL¥ßµ´W&¹4渋?$˜Ÿ¸ò…9zdcÆH_¡Ñ¯l#BVé@½D§ëcaÅÊ{X{¦-IpÂ.©ÇÍsö»Å"#§æå±`h¦—Ïxûæ;Óšx£+G„ÿr…´½m¤0;ªGNÒ‰Ö“°µ G .]æßuœ6âãž„~ákmTjºAA›jÍBËß w€¤J0KAm+ÏžWõç=·ÛÝ éjY×3¦•*Ãj o²';wý¦Ê<ÑoŸ¿i€ìÓ¸¦”‡îcS/{h,ºx‰óL§ÀõÛj<1£³‘¹»%ëb²]d¨×Ý«A9¬½uÅCÒ!‚bKtM¾›Ž–Ïtjm Û꾌°ø³yÒýý6yšŸ#t´_ ‹BvlO‰5+]”5FwOöù ,+ÎS,æ/}¥HÔ¨Žý³Ž|äjQ…MÉŒƒ Þ?é¸h’=Ša|‚¸C“˪3á3–ÿ'Ëï/š¼~q8¬*ÇG`-´H©46ã|½N¯§àçmO\jútÒ/wwødVFÁèα‚‹*M£¦æoð¸æÃÒÈ_ ”®*ÁH†ß¼iö[žÇÿäÓÑIt‚À¼ðú™v Ê[º"ÕäæÕû$h¢¬ÔbˆŒõîR~sfk¡gW-!þ÷ s ¥©ŸÊ–äò.5¢•*yjy3îŒøÒÙŒ¹'_>&Íd)X(D'D[›Ü›±…t»¯fcƒ&F7÷§.O3¥Lf8µ2`é™èf”˜yAg(õÀ)ª?'ƒE’M3½|iÜïÎfŒS2ãl\4ÈÐ0.|(J¤DyAgpRb[T9G[¦Ê5¦0#9Ì‘À¡ˆïµëó~.®Ç»ÀÚ’Ήiu‚ ñÂé“É:z_ŽzÃ^g}ÆÆŒÔŠrU²i—A†±àÕ[ãÜø³Ö°Î\ŽŽ“cnËðXŽåkæ3Ëp¿JE $eõUM*[e²™A'êhöøY9³a˜«€ÏÎÞü4ê4gXÒÊnÌsšHzÖþ´ÑcÍ:Æ$æ‘^äãØÃÆŽ«$;I¾ê¥?-”Ü*&Ÿ$P/dµ†êa\HÖE °ÿÛ5¿ÓÂ…33øRRCæI¿Ën÷tÍÕ}œÀ¸Ö„Û_aD]ÎBU·—y¡§i®¹Ù9Üb>;già°¿T£¼tp½¤Ê7Û–õUÊG1ÖïînðwŸFÛç©8¤˜_®–™ÇŽäÿ@O>È–.N·ƒ™B¯•wwæsùñ?"û‰Y®¤Û”H(Ô‡‹ì»wƒBôÆ‘×ÒË_e{1ðÇ+ϼÀ£çÂ|ôæSgã5QmÉÁ_ÊAÏõ ,ù"ºÄöm+iŸ*™ÅEc2aì–,‚ñ­,f ҪܬIøµ2g_¡½¹qè5çœZ¡Ò‹û¾ƒ³ÓZ–ä;nPd“X$¾—QCå3Å 2dᛚgÈll^Ôdé׃œàZrµI³¸Ms¯h„&{b¢ ½9ë--®ûŽ þ®²9ûS$±‹ð´¾÷u}ÃH@ Çóûtcod­âñµ°½`Iù¯mZ|žgì¾á  ‚üÇÄïIþ7C—}ä™Ô§dšÆì ày™¢9jr¯ô1ÆNk,ÉêÃ;Œ„äï›>Ú,[G¤¤4ã9¸ŠìûP¹<.±ûãr»#õÏû¼Í½…hÖó:ßd7+^¡ý ðwꛄÀ‹—·PÔÜORQÒº¹U&ãåͪºÉkxû[úYá:]/ÛLÁÃìä|·âIIç!/\Ûyž¡•I4±ÆÖDÀ¡7j‘q~¾Z’ýC(Úh€ëÃÍ×jxÕJAAxÜ_á´­ qНÁ4tfÆKŒ_{š¦»Xþû.*Ï,N¥A‰l5´Ý§/# 6;1kXôHÊL¿Oø$¾#à­3çåÆu0Ûjèë¶R(­5ôÃ4û´þ‚<¶\îP¾°è«¡qL grßSm e¨#ß§ž­¤g ?hš[4*-Ö«W>ïb»Kiñ޾/½èâ²M!•|Š4štÎ=Ê›]ë E¹«–ùV=2 Æ#…üίÅe§¸o¢Õëvìh…wËÂl,»³\Õ¶ Ùýjhº§ÅÓ—‰Î7`O~DzÔýµgÇlÎí1pZê1t=æàX¬ ÝäÁç9Ê®7ïÕÆ ÀÄòÈ®šÞ@Ëþ3Zˆrü¾=ë笔@! h¸¢²-X‚šå«þ`‰nÛMäF[î’ÁÜÞí¸CváiÁÔIs^ #œ/zî:(<l1–la¾Ä…EÇÉôþ@¯µ0iㆠV/uæ†.62™yø×a¬hã ²%¯­Y½9T^ã™ñAÝGZQ*?ÍÌYÀ¨R¥Hy‰£Brµë>„tRf4¢ï‰3Î*(Û{ôòé¥öÐ&˜­ÃÑ~ë`}TaäØK} ÆèNèVz!ŽZ´ˆÛÈ |çÍxcÀë<´²pfä&r#äq&\ðC¤ +K¸Ò)z8þdà¿§…š ÎV%áiUym]qh–Ãù 2·ª®@Á|Ö}Ò‹’!ÕK<Ûx¸ï6§-¦!dv9‘ƒyÇ j(Ò臢M㌡<‚M0©¼*.qüDìqÜ¥¹8“rÒT¸o[u/þ;Ïìn ËhaÀ¥hÝ™ÂTÙªÒ‡®ROM£FÜ )ìLá±ÆF5¢ž/L¸«q÷é=tÓ7)òÞ©¬ª0__Êwx„$bÔ®ÉG¼Üw¡í¤ ëðv’¾-PK@Ñ !ÜÑGˆª˜[ƒÓ)dpŒê´KEXì6·¯ ¥ Ø ¾·7wXã[”¦©&¢A­ ¯æ¿8Ê8n´&Êä¬Ïl䇼¸@2¸BÚœ³œ’§5bÀ{›HÏšYyQÍEžhþôŠCÁD‡qÚt›ôç9Zh§§ÔÁ› Äz…A¸PŸÓÃ¥{Yoð+(ÔÚ±e–â<¤‡áBbcoêµ;Ö–øA¨Æd9>dvmöý\sù ÜW‚'^0Qz^näp(ùÇ£n>”V5®y,Ú'öô{†Ê‰I³‡´Ò‰K‰¯:G••\y¿E÷Dzˆ+M6á•ÚÇý«v€× sð¥’ô.&ÛTàÄ´“0ç W b_¹ðY &2i:W¶3Éõ±Tâí¾×IN ‹R™°¢A!q .]lbkþT”‹Hë¼æÇõ|±WZñS'ï—c—»¸=]g všŠ1ÄêÈðÎ.• …€í5HCŠ=íhda§È´°j=Y`óG:^°+Æ7š½)±Y ݦ]XˆüóEDzÏ÷Æ0çörÜÁ\<@ÉñhÉc Œ$ÿÕ/«Ê‘Ò/§íÛj;¯Ö%C¾fB‘}u“Òc'ãUöª®xÆñU½Çå‹é(Ö‹É.%•ÚliÑ©íÞä›r$ƉÜjµMí#ãï¨IÞtRçŽË·ó2Õ–ž M—CˆG® êtŽÚk%†»F„¶¼ ©sÎÅ–HªŒ"Vñc}°mjÑWõ{JÅÙs?éng¹yâè #ÍÙ WÈÑ5I*a\ú~¾®ˆ…é[ ù”Ùö}âR”‡)êÔÒ^q!Í1¨eòcŠˆ:²•a§eð7€ZkÿnòÌi±ÃÄÇ‘=7Wy[úŽ„@ðœÅw4à Ð=ZpèÚ¹½´³s׊`Aº!Ž a]w Ûü!ÖõòË RØHÔ"ÍZéÁ# 0ÙNzÍ?>cèƒù6ï‡."D9HÐnf±ØÀK†ðÞŒt9 §Ã˜DI?`ÞJW(eGG'ØÛö<܆/á'Óë"(Õ8À'_¤‹†øv‹ÐаømV©)ÇA!œˆÞVîõÄg},i^˜¹L®› ž? þáêµ!y¨W‘[  Zõß3›Ñ¦©_ÁN R•2þ°»x’ö„ùkÝÖZ#ýk‰äA×Í%ß)æÍ>Ë3ɃÓC˜cŠ2GüÆbŠ"q:•©Š …a¦á¥Ó úâ¿nL$ðMŸÜaõûÆ.c¬ùÑ­H<àx‘>ùÒè« ×v¶Y2 ÔêùÉ+é9¨-tN¼ˆ- P»Øÿ%S#´mùÈóÒÏÕ˜=Î#¡àîcOü¿·¹Ûk’ íÊ ,zÖ£×goı˜©ïKCªíÉM#Òëpàïkï•Ò”‡Ü-2—°*ÓýKæz_öÁ‘$$ï!þJúË8^ ²ó±cçÞEÞT›*èß“%sº4üIÃæÌ-b\P"ÎM¹@òŠGxÅ“j«q¤÷ûelÔ#n‰Í\ÈŽ–ùÙ‹ÿùÛ{N­K9T¥ºËÑHþÕ0¢EÇþ,Jø¥ˆÊ‹ÞÝöeÒLŒEä`"°Ÿó¦¾e•+…R¡Ví×÷Ò@§UÐ#!õM…L °ÏKÃ5…kçppÊ÷gþcûn6x(;K_"•Z àyÏwá[ïL@]ôJ}¢#²âdðVœ(îûªé3>ˆ*ÀPõS1G,–(YLÿ%åâ™\˜õé‰ÑŠÈ„…½dbÖ ¡+jm¦ à¦â&í†èÍD¼Š?ÃüàRˆò÷§Âl ¸¹?¥:éI2Ñ´hFqtžLöX ¤7¼ªŽ‘Ú^i,›q¹²ëbÍÓ¤A¤}€P1jQWR;ä7ŒÅ¸>)—d³cDcœXÌ{-Ch+1%¡TSønÒü ±³š›ðfÚp ´76‡è=`!Žk\3"­v^Êq_Ûæ˜  ýRëÿî4²ä<E‰¨>žî~ÁKŒ¯òs£>U4X‹óþHwd­øÆøÇĵ'>£¢e$O&À†rͤÀ˜þUx7Ñð+hÍY ¨.+æïŽ,A'´\¥þ÷IºO•t<ïñ2Jð»³e °@ñ Z¯`X û ç²^FŽÉ`i „)\i„Ö8K6öÔDÑwE‚ ¸Hl46Tµf6¦âÓºq’Ñyh‹Í×a½Ž]…2ëž5v1 Ý(Åò¼ãÐçbœdvx»€ó¨AÞ¡ƒË§;±c5»\e¶šß‚qþñhÎ'.'4ÒÓŒ+oWg nÈuD &Ð’”÷d˜/$«"C-݆RØÁ7 }ð¯Â9+§SãP·)ˆéÜÞoפcÉõ§ÆOå?A¸'QÝ`œ 5ùeÐk4B`ì}»‡¼„hCü" æ®W éº$ô½³Åìy¦i—Õ÷ùÐTк)[p?»î/b©Öœœõe}rÑJè·WÈHÕ\ & 4sñÁŠUµçä2W" [½4ÚjôÒî £ÿ¥³žÉ ô°¡Žü´ Ð67*|0Ä·ý2‘'éê?‡Y©O• Î?&Ûæ²iW;&!Ú¸Á4í¡,åS¼7 ÎW¯*ä¿çNi戎áë;ÅÞôïõB\ìª*ÖQee5ãz¦÷ËP ¨,k¢ï(+èyñl¸*.[ D5•é¯Bwö9¿¥±!Ce\ëxn–o_0R쮹õH}åm­×Ò™Ô¥ iZ¥(;‰ùØÃc22¿!þëÿ·Wó)ÊkÚ‡ºGæK%ŽCcð;}TêY²f­Éiõ5òô*U¶eˆ]ú«`íÔÈKSZOû•"1{î*üÚßKs×…s.8Ž"* þ³å@ÛÖ…Dd¯Ú¤x¦á¢šDL°lÃ(àpJ^,kgÇ8ö̤³J´¹VÏGR¡JgñŠ\>ÝêØ`<*¢m[¶|Hì”S¾£’ù{Ô!G:%»w’üEOñˆ…dÐ뀠>]6vÅ7ʺÖåj½E¯<{ÖÃbYt€vžÜì~n¸ºÆŠ3½0W´°4 0™fû(þÍp½¿d8¦âñ¯ê ï™œ""ªFÔOÝy·,“<Í«&ò¬g³ì§’Íâ¡/׈±fÍ+êˆþ–/=ŽoúÝNMŽ'Lê2"Ÿ¸ÇÂ8œÂ¿ë|Fé;à÷+ífÀþj⎶l°ý欨áƒN¾Sy Ĕ ä!Éy}ûùœúŒþ wh˲ÛF$äè‡}…ïpR¯c”],sIi²Ÿ% )UÈíï‡=I@ˆŸGP‘¯Ï®°ƒºeÞ… 7Øž3@‚謴ü¶à_@h®Â °­,µ™A_Hê£AƒpkÐLE€ˆ>¾oß‘-”å·õ£Y}‰‡› —6h¤r'dëK—&S&U2÷ªnÇ5Uª1jçú‡¿Þ”NèÝì½ie,ÝÚŒÈ*õäƒ3ÚO9 ’ŠÎ Q6g©é˜Kce²F¼ ùO¡Á€”}÷™ rmOS‡—ÞçÄÙ5´5þj£W…÷«ñÓ}D†údhŽ êŽD‰“î°Z<ú¹äØvêÄ’ÙëPµU? ¯OøsŠK¿Ï‘é­2ìíïš()·ßv_þô­æÞÑòáNª­*V\fíjFAà‰°1vš<¢ f{‡{Rs\mùkÕ3ÃtooÔÖÁÍüOÁì//F¯¿ÓšîO7îû–kÐÍ ©†¸DzžëWÑÁØ¢.²ë’múò2R}#äúùVéWAÎF—,ñÕ~5<Æ!GÊ;‹>”÷gŽ ]cyÊÄea”8uìù÷|N˜€ÞÊ•ÆP™¾õ>NrÊâX à¡P@Bz^ûÅ1AþHÔoï Éw n!îàÎ%ÀÆÝcªêp…¼ÚXµëJv„ÛB¼  ›À‰ÙŠ‚Ÿ´4ª€®Ý9ª™x-mô"0N›Ü·6åügâÆÖü$Cò“mÌÒ¤Ú@t…œ‡‹=PvëÇä1«Ô;¿šû¸Ó=©âI&ØyêMãÙæ€`êU§†µ=ÃÓFFIÖ`[†d7,)11¨­¸ ºº†À‹,ú| 7^Úœà›òµOq¶ƒ]­h^­`X ¯Üߤƒ¹À$¡jW[À-ŸHñÁ7H? 0^mìfŽ¢X;»X¯Ö¹&«·´åôv|J¦3 ÷%ÅØüf¯Ãïïæ–.Æf, ò3Êhš ^vzßÄT.ç^½øVƒ6ù·Û®ÑLÍjFÊ`\~&[Œ/ç¾7f ÏÜún‰B®U 5¤b@K¶Æ¤‚{bv5ÈN]I£ú‚iãu´ÉÎ:ÛÄ÷0 ÇT÷W•À1#©vŽQC€”ÃiX´d³Üâ¨AÿÇ­L fSnâò™¹TÎj¦Òm°ÞãÉj1Í.ÆíX $YÝìz|.ØL·çJ»ùJ¶ùýun1–ëÎ8?û<3€‘PïóØ}@§œªjÒžý{u«Õ¸q\fqd»:|[XÛ1`)•É}GXÙ¦ *ûµû jï®Ð¥·4} 8oñ—6Kpµô½‘aÙóÑÔµÑF~MÕÚ}t\9ì¥DRõ[“(“,ô°W_Y©’gA´›‘s0,ñŒ ”Ë[¶8!0?ˆbìÅÞ‡! õô¼ªù&wÚz øÞ˜Ñ™"kèáËÙ½ÒEå­ÀBíOãÿÿVÉlõs‹Ã¥¸ƒÚá:]t7[Ϙ†‚ ²O^3¹-î‰êÛíá˜'àå·6쫽`&Üóà>ikGnûÊÝ¥ËÍâAgbq5˜Å[9^† D`M8˜LKܸ‡åa>Þ-œžvÐ'¬Y²{/þô/®4y–M] p@s ÑX„þõT5^Dsøv–ùU9~ öÛ~²taLg'ùhÅÊ5aÞ"Å#LLÑmŠü92p×ÎçÍÆ±ü¨mÖ®Ò½¾*v`B–v½8ÀU-Œ ±ÕG6 Zs|g‡Â;¥&L†dúÀÓPó(hÚ>(¢<¥Ý¾óiÈ¥úÍ6KI͆:µn7ÄOÆ ’}lÅøÍ Ûƒ¬ë6k„çÛ×vˆhã1Báâ¿I³ÖŸx‘˜LX1÷P¿‘z¢!ëÒ™#ââPT±í^ïå2ï-“z 4gk °Ë.X¿µŽ=`l×î9 øÖ\Ï­f³Ró‚­.oâ‹•÷”Ùm¸ÃÕ[±¥½ñ¢G(UºX0‘r:J×< MáÏe¦Ñ+›LLú{BìnðúT !2@ Dà r{¥Ç—dXl Wý[.¥ÔŸmgsB&K²}²¡ ±‡]T¬Ìà‰(j\±–ºßï•2R»h³†;-)Ÿ#ÇÐØb[©‹U¬ÓY-䩊—CxfZ_VÚìÐê¸9ú\Ý;^Û¢u—§Ñ ^ßY̵JÔŽb÷Ì`3Y'ÙZDÝäðœÊœn•3 ¦rÝ}/¢¨ÑÝ;ÆÅò"€V)S«,à.º-Kiîʧ$¿´‘™$”L®$åL|6⵩Ð"4eɆïLAÑN‘+b˽Nr•÷t‰h?öÀc],ä“KOÎ’{¢"¿jl5[<&ö’lЇ¬ OŸ+{÷&©Ê½ïr•U-9ÞB‘½Mºvè~LÑê2äYµm!¯Zµ`Ÿ™ÂGÉó{œ(£ÕÈìÞÒòm¯1¬åsÚ <‡ÏŽ|¹SÆ›×ìqG!'4HšÒ £ìçá Àìf_ù‹>à×:÷ì™ Œž“Óž)"ñv”ÂÏ–#5 ž½/ЦBåç1¿ª2W–ÏB^±WîMÑÖ…Rã½Ô¤ °oË瀜‡*£%!ž+eÑ3 jb‘ÕŸ‡P Ñ?#7¦åd’-Иãè|NÓ»¥¶«ÝŸDÓ—‡#m¡!©Qi€Š×!†ƒ[@îOÊëXÞ #þ{ƒcŒú}±©O>< ýl9a=Õäåä'Š¿Û…ð‘·'KBâßÏ¢¦%ñÁñË>Žp¡ÙÅq2²®3ÔÄ#¶åÜ>›Hs±5ùÅx–ñw޾æûÔÄ‚h&äúô»Æ‘HÉ? zTB6¢Y¤{m]çßòMê;F’õÝk¨Ÿøo"ÐѪvÛŒªÓúäíDlÌ|ÇD¯[ø­ŽöVö-vuHµ®›^2¶2tà1 ÄÅN~RÓ‚¹6“x@UꀘMJRô5úb?˜ú$£W•ÑŸiÐæÄ_P)íÁ€›`à÷v‰ˆ5¶jKÅOPæè»yžáx4*V£gõÆ0—hK NðÂn£†¯›ã4¾„P ô‰º‹B7ô].”å?Î8Ð…t_±ñghÊ/…9ת:½KUšŠ S^c~8”Dâ06‹ p†–ÌÑ]%JSíyã»ðº2ïÞVoa¢ù¤N<Œ¨ÄôÑ­$ëÁv¤gÔ»sín`Dé˜äS’XD<7‘R&zëÕ”*Ƴ·HîDcÿŽ ,­ï[C`‡í–>õé×°ÂÿûNŽÐÀ¨øRÀI}‹1DKѲ@v7_aäúÛ ªª¾–„Ñ!n6PþR±([£ºŽ7;c(àç8váÚò«[‰S®°„ƒ>n;#ŠpXˆ¸ËòÛ¹"Lw‰t³ää(?1¶û캪7Îyªøh¬7‘ÿn£mMóRþæöç_Ÿp$­kñ(Ðee© Î lè^µfDPÞ& :vF¯Q[˼œ+–²„üvÆ*r‡‰u~J4èíñƒ¶Ûuœù¬Þ-ž÷Ìk<Ô1ô;BØ4úù±)öœ~tèÁ¨ñĉiR`!å““ U»mìætPÐÂ?"1ìÉDšÆïÑŒ?JŸHûœ)$‡¿z(1züýýù¾þÒ‚úœ¹âIû[Åoû±¯<­ùŽ—ç­e`óôÐëíeâTOªü? éW³‘’‚úÝÌWÌò¬ýÃ1 ¥¥Žçá{Îvz-Ç>ªBôÆ4À¿Wnv‘šiñºOÒÃÐ ª‚pql|d`ÏGºËò»Dt_•–g?²Y”Ù3oQÌ×ÂmÂ_—R} ‚­×NÉIXeöòq|ùþ}öï°õ29p£.¶æï:–‹ ØïïëÃaÕš€ž4‚^1ôƒ¾|Ž×s˜Èg©´€=È?Î \ú¯vÚ@Ýò|Â`Žÿ¥Õka&òË!Çi?e›¯î@%i%·nê·5¦âR®­]~òo¹… C±‰‰„ɱóâê:„ÅL‹ØÄ#Z”ÅLn.aŽæÓY:v&&™'˜?¬oÊ¥ ͪ*J¥ˆçH¨L)§`*Û:EŒ0RÅ9,Hªlþ:€¯øð”ºÒiï9Ý Ùø9 ÆÞý$CãÑ–k|üÂÆÔð© ~sLI·œ p)ñ§‰¥…)øDÌp,níN0{‹±iý^ò‰©»B o˜äæyÇuŽm “=nz–)8bÃð´Ü²X¸ de²ª0:—ÚgL·û&Åv O¤9oBk}“ë/_•ZÔï¤ìNt‰} ›U"bYæ$k6×?¤¢7Œ&T²|x4ЀÄìÞÃþ‰m®â»¿ôa‡ðHt’ÙéH¬õ( ïÜXk*%ì ãí2àôÁY?ýY7"3\Ì.f‡ùWl%.ó3›Ù]Ž™µ™Ž[G^mt ºoL:a•Z ¾ž ¯ð 5Ñ®ÂhˆÆ×¼råZÀÝ–¨‹¯\e˜|-ÒDµlµV¨ÙckAÕ4³4Pׂï ³¢Gc©ª䊅¯ÆùÂæz—T?ÙÄ ³ JQ\ôbMÏ9•aó\Yw{Ö!ütÔØáèèŠb’9²˜7µF6 ªÕ.Í¡0,×P3uÐkö§Ñ6ôÅnƒ-–,°·9"6îÞ»–àÒ§È‹ÆPG\šJ=&ïÜ}ZL¡ÆÄ¯ù:߇rQéši3°î(@-|Ü#ú·‰¾2×~ë¯e©V-óÀâ*±ë†Ï@8f×­õ©Âß(RN?tdfŠ›,kO†öÌùeŽÉ¡Ï¼M³Ì%œÕ £WJ×ä—·dá#œKÕ³º1ùDÎøý€D™Üƒ•¤á¬—òY€‡FÃÔnu׉#¸sÐ)ûE~¬7NW¯’·?aH÷i¨WB]Z ×è@#ý/Ì Ï ‘'^ÝQr«vÓW@¾ HÅgZëËùa¨<2±:ÊŽŠ³ÞOõ,¨çךC½by|TDÕ9St)OÊ ë.ÀNÐEÛüé‘Tú}xppCɧH+`VÀ1"„ÜǬ™½ŒÃ~¹y‚·È!$¬¢xø¯È¸ÇÆg_;Ý¡%Úf‘"’†ÄêìreN9‘:Ù“¸Ðy0€&çôŠi’„Wã\`ÑËÎn;ûà7“á¤z³ÁRlÙJ²ú‰6Hö¼×ø‘ß[uò2]¤ŸÎô‘_Är3Í•Œa躾HÜtOBç³0'\"È ,8õ;:õ˵ßóëyöÿ{Ï5›ZßðFtm¯¤š ?X78ÝvK.ÙW¸ôH‚:ˆ£ î QE¿^f‡@¼i¶^úVÿÐËçTý‹¯D¾Í¡ýeª@_+×û"CE³ ‡0ï_˨ÍHcÓRЊã·´w^õ©Ã­N ï5-,¯Ê!ó‹÷^¦Ü4>gSëÔAq¹Lü8äzâÝ5®ÚU¤ ©·lÿ Th|¤‚³!ÿè|L—ù`Xômm-„#%‹N¦}U›í?ä„xžmT—njKÕ2]DU7°µÛâ¡™€Çj’’œzoü²ÕYy‰› %úþ°@³ö²IX!èºU¬—®¹Œ¤ÿí$YFëe¸™þ’€šíß§e ´\¦þ4 ºfÁö?'dý8ö©¦H gÓJÝ?7ÞA”pv;E,Ç$õ5§‹ÁÁ\:i;ÜþnmêI6;~CgeæW† M„æÂPBË` vCák=ПðšÇ(®¬&"C`‘eÖcQf} †A«|}¶2ѹQõrØò”‹Ä…-z$dHAœ™>óÐê_]ÿ€¶< Ç<çókÚb‚FÆæ%Úg`8N;éeÐé»kÛ yÄ\ÌO:MšàñJin’Ëðªø\¹¶e dþøô¯),î…*ï~s†Æ*ãóÓ‘Ä.˜Åibýf*†|÷øoT©DprVCÀÝa§& 'ºê•qdHÇIÚß¼›Ü –gÿ ®*daPêgãûëNí¼„—²ÜùYlÇÔú°êd^Eè5•½5ßÑ9+Xê^–S§À&'Ö=pÅJ‘ MxS‰A’úwÒÑzaHÒÐcypÓ­Üd7ÆEψëµv=<ºˆ¦ÿêVTÚ [÷Š)>sã='Œh ×ÞØ¹ (´öV:kÑ"c#×ãðŒ´øC¤=KÎb)qõå%<°ê~´ö†}A7ñ$Ü3´äQ]ï¶ hv6]ÿ¿QèLàÞn7XMÊ.§Œ+õámóˆN*¾@,¯EeI#çéþ¶ŽÛ –ѳ²ì“p;I}H³ç}ï¾Ñ ˆ¯¤£ÓºŒ×šÕôóV±;Ëæ§‘ÃâÓ]ÖCXŠC®,F©ÌŸõšnpß<¿pæHçpZ¬eÛjo–€&9óõˆî¾žÐè^ÜóLå…{ù.Q¾åòûФ¶DžÌ\­O|=píI>š'ùêËn*¸,}rñyˆÝÕ:9>iWvº:sú™Ü' XùY‘DëÊõ5n8_'À°.è iå”Ëz c\?–$± 8ìÞP9j×¼ÍÖX$éN(›{®I¢¡ƒ/ºîŸFŸRSßkPùˆÿ ¤Â}C:ç1.6U—¹‹¯‘rzæ"$uƒ¾ÿ{nýÞȽ9$ô{z›>Ô ‹èäá}Ì&­6¤ ɧqu:p'¯Ìj=ǧ0k(qø0‘éHý­aî¯RÕEdQó|òU¤W||ÝWò@ ú3(ËgWÉ¢˜ê%Â.´(–p*Qí­‚!ú‹Ñ%ò4>ɯØÜ(Oòzév‘AM”¬Íòó–¡›fí‘æç*HÖ‡ÿîj ýgF ¯L ‘¦b²s‹È:–܇X[Ù¯ú?SBD?…×§rñ(—éÍÞïLøAòw4ªÏt8T“Ö‘cÐ:dË-†À/Ë>ÙbâßX‹3\u"ÝAñ¿«Ã—0{ÿb±ŒàðoM»óõ¨ì´"˜VGP2— 蘺ž šOI¦˜7„\¾5„¿DF)Ì~–tEúŸÅ1ÁÍK*ïÕÉÏcÑç`!xˆ ƒ“2—­5l&‰þPÐUTœW!êå¡ÚŠ#»‡„p¸ÑźÎ5@°v+$ð¿FÆø#ÆÓÇ‘Àõ2÷؆cŸƒÂ«ÌÃHAä.o}ç-£UfÛ™»X<¯Ýë¥AÍië7røÍ^m¨'NiþÜ—7­1u[v¥[)ŠÔM~Iûýv‰‘JdïM ‰Þa§$Æø¸Yy·§=ÒØ Çuä-˜|SË8‘E‹m²–Š×„™4ÇFé›bŒ•–"$n ¹Ç_‹n¦#ÇW¨¥ëÌüë÷Ï"ÔÜ ã(J¢Á3e¡âÛ È¡éþ‚¿û’[‹¹ßÌwТHOKLúÿôµ;Î âOºðá–Œµ8<ÈmÓjä† qg[í‚ofFaª¾a#ò.ú½ê!Jwíw4Š„þˆ1”½e¦³ô¢vÎÿv"ø ¥&5•¢NDÒr›]æZù+>ˆPßuU -ÌÑ«;ÿ‚ªh&_ÏB×Ogÿ. ,7¤P‰=k^ö®î|§Wéë÷Y5iHÙða,^°ï°Á&´W†¢ßh‹ÛX:¿¦ÄŽIVYõ1©¡áh¯á359áTlP6ß|=°rþ ŠÖ:ñçtì¾ÆtÉi¼²g¡+¶VghTˆLÀ:)æ…|ÝNtõ˜Œe_.Àmƒuc^fŸá뼃_VŒåU£ôÆìÔ˨æó¦IŸÕ~§åhsÄõSëX½‚]!+ªVÁÆ©B«ÈS®¦@ šÌï7 {ò,‚ª˜GÓ?›™ãæ¼*d0N¤c&°¸hf›–Pð\–z{»^_t&fTµÔ¢øVnSHÿÃàÐ{©â'zˆ¯eŒïbw ƒàÁ=ÿÜØ¦_å ¬p€y—ÎF\P‘Œ5!·ÄŸö^ ðØŒüeÿF,Ü[ʬ¨¤Ïµ¢Läôª;Pÿ ýׂÝD>ˆü)ôÛORˇ‘¨®ëý騷nº›×FÊxpTHI¤ _‘´æ­#¹q23›Obä`ž¤‚l&TEdzù MBx™†HC¢ï‘»%ªAŽE8#*ËÑfv\&¬kñ’ÔáxÜ𪜿¦¸8 ·¯%5Ÿèô^U5Q1‹$(S1‰ š=®±om ÷ûp‡9ð7Líߢïd8 ð©´UZšõ¢VXúºN‚3(°‘iLP&¯øŽ]¾XSÎT[ ¹™³$# ABôõ½ŒNª`wè–¨ê3šoÄ`~UúnÉ]à`gŽå9‘?¹áZx”ÑõŸÚ¿d~ĵ==,&™Ñ@zŒqwê“0.2âñ!ž·sHßÙ(Çl/‰(ï;j'zÙªcaÆü’!ÁzôKmæç:õÌ'Ké2ƒ¯>SSpÈþma¬ìAÈqà“úîáÿW✅Ú?ö ­¨ nöVÔXŒŽ\Ôùʇbí¦'Ç9Eju(^_HA{ªÏÄøµƒeÇQú&»wÿâ~<ªA’ãHðSõ†é#Õö6©«´Ç¥ç¯ZœeU¿ßCN„n€ò…hÍUj´ÿG½Ù8ïÐ# 2µÕ—¶]#º.|§?ªJ7¬•¬>$ˆqvqê\H:½ ¡LUÖpR¤‹ð#aÈ¥¤5{:Ì«=¦ñNcá»Ó$æÆÍZ£¯f7Í|HøÍUήvÌ|¹$2Ö¾ü}· Î5—OÑ?Œî |øJu£$Ø,ãÒmn(&àý„¢–M4•2t°³Á4‹cTÎ’ @Qæ î&Hz´z]s±¿¹º…ÝÛ Ýo[…'ìèÐx³s?í¦˜;jËV¦Ý;LöÔyùÑ!c„gzÎÂo¿¶_¡»‘tXP¹ñ18žh 2÷ì1vÙ"äc/¾™‰=›ìo«Ç² §®*àËÜI.£Dn7™>;­äȰ­ŠÕÑ~á*©™+Bi˜}Þ1Û¸åC>anæ?BZq¨d8Zø…qìœQŠ%¹ Qö·ˆ‰4» Êæµ×7ï™é]æÄ<š¼V+Ž83WrÔ™ûbOÀÀjrþàÕ ÌHÔþE£=ü­à@™îí¤> ¶ÿ˜ ñ³ŸüÕfîÛý©Ÿ”‘n[54ÛC¨7÷ÅÏ…9ÿO ] ›C|}+±Þö;~§ŒN3Ôpdb* #ó·ò¬^@õç­G¶¢Ù®°Êø8d4ùF/?vÚÇu»0.“¯‹Bæªå§äo‚ž:Y?Cc.éª&a™‰v–í®É—ù=”a÷R²,o'Ô´úºüÜ„´Á¿е‰-5PÒŠ\WßàUl!·Ô…(+\“’Å4’›%ŒÐV{Uù›2œàÙž×å$%ß×A‡La„1‚ÖâªÌ>Ç€8›«|†‹féXg…j5Éh¿ƒ‘Ó3n,5ìñ?%+G@×_¡Iã±ã †âß"÷ª.»3ŽÊó´õæ6OVtæ¨ Y’£‚ ‹š3àR Yàƒwñ?—‡Å7¼ÝŠÁ§ÈÌÉ(ýTª¢«ÑIRÞFDÉ£/’ò‡š>ݼŠËËŠ&±¥î}Dià0*ecÕô¬Z8Ž8FEÉ¢ï·Ù$Ñ‘@ÔýR¬È[:ÞVÖæ­2Ù·{3 Î5ýº;jçÿ´<üð‹C«ç°lKQç_þi®ÛJh $XÛC5ˆ„éùŗψ¥/!å‘è'êùC©°ù¯²q~½à/öñ2PÉFo[Ü"•_]éõ43Ó÷‡Í‡'¢’®e¥½¥-¨TÃí ŠÒ/cQ9ÐÙäs8%ÖÕõíýÕÍfý~ex­ r„õÁg´‰1vñ‹NÈY§¿¼ž£l)êAããVb:gLt°?op»«2 IžÁKu;ƒM¹*ZïH¥É¼b<<á§úÐ!L¾[z—ð)];Ä×§f£EIcÏ¥èü—Ä®cg ÿ‡Ý‰ù ¸Br°o¨tŠKóÀ)^±{Ê|…NJéŠue"ë¶*5ÎÔã¡¿G™$â¹Ðã¾qëÅȵpÛÐï NS¶ÌÕÁfÕ·¬l¥!‘¨t5«vfl­ÔXŸ’]ÐdmqñØ ñÌÀï¶5ÔJçâ x°Êi8R'†h&Ũö´¹ªñ¼@6,õóÃtq:²é½×“ÒV¯«³âómFŒâ²±Ä.v+à5­ÝÌ‹1µ«n¯Í©Ÿ¥îVεÝ|Êï÷Y¸s‚H}°Š"ôˆ‘ûx€õ"Ì`>'G³;-S€Ù WÓ¿±ë,-tÎï‚XÉÈÑXyT5ÛŒ+|è\ÄÆ%î…ˆbnx‰ãÚKÜ0æ˜:‘R¿rœøÊ¬ÑÔ‚ %{Ž­fûžRåe­D‘bªrʈ¬›¦à@‰wá =;<¸&EŽNŽ1)f°õ•ºÒ¥ÛHê¤×ÌfÌ»%•`%„Ø ~_‹Ô’A??g!rërJ˜·›9©ÌÕ¶Rv¬ X>X¦­Û<`F<áwS]Œòêâ™Á2f>–u;á^ÍA·=ø¼ÄŒö„õÏÆ+Aš{ÄjË{[Ô­&4;ñ×5ÃiÙ¢»}"ý†Ä”°H›- è·=·èÀœÕÓ±ZÓhPPÌ›‘$RÜZRûo)*Cî„E&· »Œ#Zœ’³-i£’PO”îG4^]ÙÎÏÁ/¥ Ì)Mçèœà£ ÿÇ;‘PÇÁ¤WÅ~$Wº>¾qªyǹ sõq^à¼v’ùZ„K`¢j]1Õ‰ ^°ˆDh¬ºF„£™Ö6š£„:Â~o›Å@9Ø »6µŸl÷WB[#"ÝÔÿN³heNiSŸZ…gÞQ–žySŒè¸¤ áùO„•2b<·¾ÙºØ1 É¢·±¨¸é%¤€]¦®b» ˜¡¹Õû†WTAãM¬7ÍažDˆÓ%Ô5z˜y˜®Ï›à.tr–…€W)_3´¹»æ½Ÿóy¼ˆ£°´ü±Î¡oìª÷sXb3!Å#âÖ˜8Ã7ä©lãKÙ]®V{ÛK¨ƒëÿ¼ 7ÿÚ4‰¹§q‡LgvMñün¾8º÷µ/R­Ü=6ZÚ®ÇøÎ©}u3E•>Ý<ÜãNnÕFk¶ÑÃŽ/ÕÝŒ‚§QñàèÛ&ö‡V O×ãÝ|euO—(c^ 'ä¢#Øo#²º³ eŠˆäÝ+}µ‘ a΂liáóSæ_,d3ó9iéd"ØæÁ:# dÎ’êŽ$Bùaln’@— ½÷.b;µ™Í(%ÿ¥¯ÖÊ6*µ–nC¦•Ÿ×yŽø`?»ÉÊÁJ^‹‚óÂѺٷnH‚'Ù’ÁµQrè¶™³ÝÐÖ=4;â%é ÒtEV2Ô¡S£Pü‹1ÜK´–gú>:Ç 8lï·úu³Kô°Èd{¶×ßPXÝvôN„(¡I’(ê$bs"qÜ âmßÎ㌔¢qð Òˆg% Ïh `9\É;{kÀæßü²nâ­*¨È®£ÈDÈ'{°8ùOSB{¢+àš|¿[ 5ñUoGf)/öÒ£`c›Be1á#ï„ä³?ƒÊ!ÍIÞ¡ŸG²wÄn«Gzó5g|  i›\UGziŠ)¨}h9ºQxØòhQ°y½ˆÐ¹CÆõF)ò,êÕöb¬Ü%ã,_mBÍ ’>±¿ºqÐÓ“ñ’öå…Žúáæï‡òiÇL âÒtBf†û‡£¼<¬ÿÍ$ª@x£Ùéajö—‰à»©Óÿ;zùI{Jb¯A¹cë¯Õas§}¨f+f¹ÞNµÏ«?Ï$¡“ C)Gæ|Ι'í.ÙŠ/»ÊzB¡Î3åw£©Æý&iȺ£÷z!¬Á…òÿÒví7¡° ]'xáÔƒš§ÙbèWÞ”ád9–ñ«æs˜ÄÅÕã Ø_݇gÂäæÞrÉ”öuV]˜ã¹24¬‘4ˆA™±ãm_\:°ä9)Zñ»oµ õu¤éVVEQËÓ–Úwñ§á ð²f‘ÐÜÖïÅ3ÖÆh0ø4ÔšúÄ þ¯å^’±‰ËW>©‹®ÿ³¼•] tcÈ<3Çù’^¨D™Æ¥“fd8×.Ûãö-ºD© k8L鍊ˆƒ/W<©IÆ_ŽBª;gÔÚ°Á–‚GК‹$ ÃzãR ¨#È/q¼(TB«AW˜û…ã.„Ý6͘6ß_þIfÁ»õ~ðL#Îçî3® g-ÆmH2:Ãk₼ÐJØÈy™N®±y2Ù1ê¯?Å’QsI£+©ÙÕÈݬ.eY€°ÄݦåŸ5\Aðø[‚šûøïèÂ!I©1©Í'(öxðv8Ú ÿyä…ûíHW¬Ö‹¼‚,:c8t¢ ….?nèôv`‰î*:—ÜÓ±8ØÒ<éÇTø>£³îtF.ïa[{lqM8ÈV·ªØ¥_Íé°,UQRlÑmjYÒæíFÜˬ! ±º«<¢xu¾ï#¿ áó¢lä^|=±W2vGƒ*µÁ<|Îsu/Ê•µ>P¯ó ÓèZ á ýoüP=$Éçh*azŽ˜ÞügJJpëßòÁH.Ó‰°·žtP]ß¹Æ÷Œ ^^üpEŠ=t-©Ç’͈Í–.áqš—‰G纄)æwûT–àm–’ìyQå&VK);’³ø®HUAµp¹Ÿ-‚ºÑóxE;ÛN§¡» Ó;(U”4‡¿eÞ¨íMt];<5@·ÛßG—b„Q \Ž|]Jx)÷ÂL¡!숮y4äopœ?Û8"j·Ù3Ê¥7=}^\Å_è;Ée)Hì ŠÞEìxÔ»”N”¿©Ôà‹\§:7Þz–=Ã%ìáÓ>`±>ĉå8½3ñÆNŽU­?¤*–›Ç—šº?,–ª–0lвÈ7¡Ê é55KªfŸ‹[áWmr\»ú§ÛDï´IÕ%êdC8K¸"lí¯@“2Vƨ˜ýŠ„%ãÊF‰JÍç¥R¼9[ˆC¦Ýœ5´hP‰óÔlÇ”¾ à€°Döqk2ýµßó"êh¼Öí¶€œÒóEUÛ‹†æËj5ëŸë[Ù_È]wú( ž€³ô{uj¤lŸ®Îuƒ+@gcˆÞ}ÍŠKø†ÔÚo“ùc„¤™¾k5[HX†ÞF¥ #† Ü_|¹C°R 1„¨ñ¿Í9õê+~66ª¡º®Þ¼êO‚feŽ¢Elµ7çñP±1Ff8CêçMº$úx|Ýî/#’]%,•+ØL¾Ò Rcö¸3T/{UN³:ò†¾Ý‡iŒQ-’ßÓEdE³æœ ]wí­Gií˜iOÉ2*UšöØt>  <©ŠØö³7½_ãþþ‘Aƒt˜Y#Ïj%ŒÓ¦§Ð<.Ü‘Œ¹X$ºd1²‚?^ÊüEÝ}x朗y®˜Ù%AÕââX«s½ÖýMÚþ@á±€<PMº¾¥P=K=é•CÝœ-+_ ´Eª•íÞ`.ÆŽ^†µÊzl*…”ñ1Ŧ_@þòÃ@ÿF›[‘Òt$4ašmË9¥”í«¦Þ[/ Þ$Z]X6?­Ü.Où2l@½JÚC$_¥ãép±­K"eÞ’‡G=ÃÆ.„½;Ý!Ò­XR_£$k7ÈÄWYÃc®ŽQ–]ÿã'ÔnÓÄ œJ-ÎÅÚ/A©˜wºj({JW•›Y‰NÛæì3­ª»{ºj[¾ï>4PøP‘|H :v\g«üxñÍrDõ€¯$]ÌDz¡D‡RþÞp›Ð4Y ½å»‡BéBÿ:‘]°,ÌûÊʇF/§òl¹“ggœ_"Þ,3½ì5´é¼âÊ ÖѼ§ÍÅöÒŒaKt.VÅÇØÓr[ ¶vÁÚx¹Ã/á«™ÓÍ:S:ú@ztjy‘Ê- t%l°c*þ(å%MLH©¾X¶ôŒ”$îŽ÷¿z…èô@Ù‚Öx,q§I¨UûÛèê¬ï2 }à]°ÚÉa¯.ïµû2ùÍ?ß Ê OèMì9Ó~Æ¨Ñ q…íYâlbBW<7dè7Á9ß…ßÚú0ß‘-:鶇ðð–zèE Ã^Ûí›ëK|¹]_;bY±ºÃ”=#§®­©(I6<…Yƒ[ã¿\ioËê„Á³¬]Áã³þj1=ëŸ;n¢j ËzããâŠcÈŸyÚÈ_ {Ý+Ç!þ×°¦ET 6G¤ú÷rÆ'7`ú…[ªÜÝ{'Œ'ã.€Ü­„HÁ@'ÈŠ²~‘ïTÇü»vìË©ÍÛÄî«åwó‡’/_ÆXᛌM}mì…ž}2xî„¶âÖà §‚Qzã\ :×PÅ.þÖþÇÈ åõ`ÖId®ßÚòêñ»,Õ»à Âd…ñsÛJ* Ùº†Þ Æ'‡èã†ÅgÕTŽ™å ÙpÎâ¶¿ëx°—Ù‹5®(¯”â]ê©?“_Ya•·YàÚ®åFaõl‰FÛ€Û#ÆñægT :LC*y\ºDãÄq%x.“ E 4Õ¿Ë3GãmŒ‘´ˆ²dûM?|vS>o—Ì»Mà^3¤Þ ‡$óÝ&™X%DìV.´©ÇšgL§1Ô¼áÎsAÑRzgˆ¦÷Wº†±ù÷;Õã¦g—Á–p¡xÌej:ž‚Ëÿ%‘_ÝÆ©¥0U¦Qsl•öŸ-½³"œûûK:–!Ÿ»%t`3PV.ëõ¶’r2¡ãŸÏAü‰¸À¿tn z˜`dž¡ç±䪣g:ì$Ùt×ÓoºSÿÔäwÿ|—I£ €U\×8•éaÒ(ÙÇ¿Rg"‰>=Ãÿx: 'æë ™ ¼‡ýÙ|Ú"â¼Þ|ÁÜJ޶@ZÀUzu˜©¹Ñx-Iª•"@W‡qYÈhmæ÷‘ÏíæßQ]󭢊MWˆ\ÏÍ?y„ÔLaü4ƒŠËë ñR™o["Ðíl(³Óîn® ™=_Çäͯ±m¨!cCMÝë7Þ1ñ¯¥†kòŸ?ŽLHvÄç~ˆ”˜ú§¬QŸjÇ7Æýz]Ù`*Ùôétá¨ÝW÷#Oâ?çùÓn†ƒAIb­TC?8[U´æîPï8"YÑJ²ù& ÞÔZIö¼ÇTaäç½Y¢Üë €{rã—k0‚^ü¥´JÞ;€¹ÎÊ ?KJMZè`Vñ?7êx¨éÑAx›ˆSóZÓZà”HVñ} AFèdTÓÞˆ'-y"²–ï—V1u_ô$ãî7¦û:cÿ±­ú/y_ËoŽ¥WþhÄ}eCzÏËj¾,§bƒî¼_x‡4ú?ƒq½ÿPnÉü¹VËt|Ä_Ì•:7‹IÞƒ>6{2AÒ<äf—ûpнBõÁ3HìŸkj:|ß^gô®/îøˆr#ôE if¢‡vxIH|b-~X}“ü§•è?PîN!¯÷4:?ôÎ^ÂÛb<ÄNJÿ ®Õ#â­;ÍX_æ“«üD¶­{ÿ2ªqr-Ó…fRÆñbøÝNEßvÖà7¯¼æ'®r˜âdë O™’'š¶)jÁpëÕ ò>×Û'ã'NÿC±_⚟Y Ô.¦^¾¾¯ô¨n1÷9AÂÊc³ÛàÃ=Æe’€ýý?ŽÅz êc,Å$Yƒ¡Õ ¼Íù.æàad¼˜à *¯» b@óGß…ÊÀrK­Ä $6E“úáË{„-´éøÓ+>CÙùP¬èç½náüÕeÁOl¬4#{±A‡úÅ yuÛ,ýªíq v¯A-áÙ¹zØ}_jÉ»²¼kpdfÍ~à*—á‰ÇÇ„wâ èP,ܨÙ8'ü¤ÌÉxßu {6&±¥©Æmð›E†#‰‘’uÎD*×JP3“ÈÂ䧯è½ÖZ"£t´çü¢Á¸á <› .ÑÁ8./î:L³,cË˳§\+·´Â¥/L#ã„ À»æÖIã5 §{ 4fIêÔ¡+‚7ç¥V½Jšû†\צ©mÂ;ߟè8Ug—ø«¿É¸ŠooëÍ– Ï$2føßajf~ꎈuîi†½½¯5®ûqÚ"”ßkÅGe߉衒÷ÜõãWŽ«âµ– .Ô–§9ç047«®=GΑI Ÿ …Œ*HÆ7€O=ôêRGÞÁlˆ‹¯?ǪŸgËLXê­°/Äí )(òº›XâC%äÄú=ƒ=t"ò*Md”Öúr F×ƼÉ_¶ún3î 'fä|޲–〭Ãàiî%je +#}wp¢­ŒÙ]|ñ3w‘(M8 dײ?â)ûâ¼mqïR{wgäóØo¸„…gQ–(Y ÷Ts)ºIÇâ×kÐÔ‹9]E«…‰÷¿OxK¶M²X¾Åïcü%­Ÿ¡ÍU¡ˆÙ3~,`iÄׂözˆ@/ËÜœi8òDø“ê3¡Ø+Ò ¹dŒ!»Ó¾ýÚ¹¹)›¥OW’TŠ„"vßšHÄ8é{¯8§UHo³îÆ¿R´…OŒb~œÚeå€;fÀZ Ê «ÞvvA4ú …x¡éŠH·íáÖÆúËþΜ€Ä\Nd.Öæý<=©ôši‹ sˆ©Åü3kz™¨jm“Ó9p •žæeýo,0fº5lùßBËVŒÀ~[¢~¤ tåm ŒD×ÿ@Ù…f.E2úÔGJ!3•O)ðÒ).Õ)ƒåeÂjÁ¾,Ž–£E²t2×ÐøKB|©âíp°&SGnoÚî@†Ì³öm·vœ<í&lÉ©ÝÇÒ!tQOOÃñ$P’¿]Ž! ëøšÜ¹]Œ=)ô&¡åkBŽ$Í»÷ZsìÅðH›æà µÒo‰ËÍäCƒcçp1NJeøþ(±ñÐì¶y @&õ‰ˆÓ²©¯¾À¹ø j|A<1æYË—Œ>R–Б^ãéÍÿ\&à÷'™Å«T棹jz¥_Z×G-Éfƒ‹T#°Š}ve§I /ÊO9UbZNÍ»õJ¸¦áÁû¦TE˜8 cÁúìB:ȃ²¦>ÇÇ{Ûƒ LÆOfÊ5€}Móköµá›W•£HÈYáútM̽­F¢sÜþÁ<4›â\×`m£GJo®¨^|ÃO6(vía–ÑoPÓ¹OœÛSš¯I–îêÏ¡¹oiθðàeÃÔÜ~'ËntûÀ•ãö/¬žl:Çìz€™Ÿ…5J§Ë@7ðoñ±dùG´£³ÖjÇÿr= °aìí®ñù¸žÊk·é_ ¨ÜŽH²íÒô•E•/4YšÇ7ðºBFâej—·®Ïþ2/€;(Ã}âEo@¸á‹•#Èw'òr‹qT@1ŒIð®*˜î®—–c®à|}Ë.ÏGÊ:º1ÂM$»Ãm4ž³êR ÍbNþ?™—|®0(=ZÜáÔúHº­ˆÆéŒ$àXüÈ¡9´>æÏfŠJïb^¾YÆTÅõ%Žëts}¯.%\ím¤…¡æ5ÕÌÀ‹cejÏ:Ëcèˆ'•t>{0¸ïÌ˲ÃÀ²\'ÜqÞìxÏèI*ÇsˆÇp’ÏôZkm¦¼‚°ç]£FæÜYY’-ÅuI¬È—¢¼ÕÛƒeY¢m?ê‰=\†gŽ ¼ÉÓ¦œââ×€ö«›±*ÿ<±gq(… EåN?ùZ~ÿ3¼i B/ {v<Â&œwØ uΆƒGDx¿–õæoëK®JMoñ²N¦…>¸€ã‹Ï­²ŠÎ'Ué°–ƒÝChfFGæêRãvõóa˜›W†.‚`ÚÛ$&†¨Ò»š2‡,ü3†a‚d->/’0MÐeµÓ´”ÌRœÀôG&.žeˆ[ÖÀÞ•3å^"ÚÃʶCjˆ+6¶;;ÔŸðÄ” ¼õh~Fº=3$Ù<-}IÊ<´BÅgwà5Ô̰B>dük/<éÜAŒ\afsĹd*ž#,JàѧAÓ‚[¡2Ÿ§ø5öŠYT^“,Ð伯®H³èP¹*…¡Ì‚nºÿÑ…Q4¢ŽÝ_·$íóêd›íàL§«›#„¨º»qæý¨Æõææ+(×Ôxl'2>²€KL¿5™Úò£Ù"UªÞ!=ÞG›öÈ ¯»mƒZTñX\óÈ­2Ô¯°~J—/;ö+–%»‚å^Ló-n²£Î ãï±Ãoú…‚‘Q÷mÜØqBý¬’™`V3~¡ØäðP…¬û'WÐ-@LÙ}$÷ÞýHk 8fWæ0¾a——ý!ƒNÁº)«t’"8°ÑUÑj;´î\ùâ>ù‹ÏwS½¹æþ´¦Ž‡•X ÎVùÁ¿î…¾ ©òéÓü]ý,{ôÉe€Tsµ¨ À’E‡$ÆÉîè©äy'×%4ëÀDÈ $“þȾ”Ç·ÀÆ«1n›Çú7íäñÕ^„Fœuvríp¨¼¤<Úç+<ŽÞ†2Ž.á.0ÕõÒSŠ’k«‹¿ªÖ8X‚u)aâ·Qe)]ìN„椦’»sôo'™ì•+Å/.%Õ[… ÞMÊLp×Ñ®-Íñù(„R=“¡·uq‡¶ˆž¢ãøÏ›–èi©üd´Iƒ¼W-LD¹2R¬@ëNJæ ÜESx¦hRcTèÞp}Nu1œ`=Ùçç`ñ Ùmäê<Œ›€0e†h&Kâá·œx?LUyzAÙs,}÷D¨©ºÙdÍ ÌGGK'&h÷™ÑXJ=pja‘Á ÍÁßNÓXµç¥fµØ/¶ðît…23K¨^i'€3ÖíEx¶8Éc ¬Æ.mÛ5’*&47„M1]\@ëSüFµ@BÍ`kTÉÛXŸó‚M:‘¸‚Øôa’|ê¨8…_dKöÂ2OµªHçfD!ª9N E q£i±÷)A¹ŽT [É"Ía.nVLû¢$%cü¢‰ ƒ=Ñ´ùy÷ý&òÔN»óx()¡îH•Íz¾Ü2²½ :VÜ·çcÑhþ@Ž‚ëx˜B݉ͤF… 4¯C¾„g4žd!þŽ·g‹ú‚X°^cd…ó¦ õó3CQ± JϺ¾É˜AõŸT¥ÁnÈ/"Éö¼"#Dš}ûWÏÞagŒüyŸÛ:¯Y~ZZ²è"Dª ÃFÐ!Ohz@¾èûÜX"‰OÏb>í ­|C>,²‘º ЩK_sÍY>~Bò Õâ»à|â¼òêÿ¨ŒF+γbϷ̨þšõþ©§µZSÔH­É]¾¾_ÿW¤)KÉܵöKÏç®÷&RÂìLÝ&2ÒJïÐBª¶©0•æF¯|Mìö6°-”ýÁ9l,ÒÑ´_¾ŠøsjÑ týÀùù¾H¤ZÆ åübJ[lŒÁ/½óÇÛ+V“Cr8½Ö[HU¼w͆H_T’Såõ9nïЦðaw­¶ë”K–uù'p”³W?ï-/g÷AÍÂYœ€†Š-¸ü•Ï‚Ð'³£‚b•DsDâ³ÃôÔ2áûЉÒa mi!9ŒTZÔ \E†Ç­dEÞÕ(Â9,ƒì_׌;l¸OM1mÕ7D*r`œæFÔ76Ëá^Dïe5³ÞÓM–!HôòÎêãNÔ;ù‹&€à²ÒÊ—‘õ¶MÛ%wõnê%×2e}\‘¤yA*׉ ”‘#>Vˆ9ÿ½ ðÚ¿©ËS|¸ç&§âÕœ“çðß|ub}ËE}Ѥ¹¡èø}vµ+¥„Ú¢‚ÒÄ,ç©c°¼Iàm¼ ÐFŸ¥÷,0ªOkðTê–Ž^u¨.Z<á5DùÄ€?!Üm¥¦²=¶­±5øJt+ÞnR¢¿©uô»áŒè¿å™©Ñ&é]½Óþl^¡†yÆ_®%ÿM^%þ:´š…#Îâq¤jFL— ×bˆ7;ÈÝŒÆ×K“…|·4ð€`gËX†^÷¢ßã,öÕ‘D ‘bôE0:KsõMmtÔ3ö‚êC·_;n;¿!çGŸSHåJõXÞ^i”ƒ¬F¸Ú{ê´d#1^EK‹jG3ý½` $¶a< y«unÆ(nó– Þ[—´µÖ`‚“Ý€ˆ‚«Sâ2å…#sç=•´*‘h}ZLûÅÌV€¢Œ6'qöª¶)ŒÔm²þ²•ï~³OÇá$î‡çãø|¯É—cN«„Y¯pŸ-ŒãX ÀõìyY»HLV3°>¸ÕMzÿ{4v¥¦®!¯åaG¡¿%7Fÿ!Qýµ$œXß3 ݇Æ‹¤¥WE·ë]eíxã ÷»œÓ8ËDœxg±#áBŽ-Œ‚Iõ%Ä÷htý~ƒ-§8t<8ƒŠäЊSoç„Ô=ý†|“Ú͹Ô&}Ë‘†ºbWµý»Å:ÛKgú ®µµÒìHL¦«ˆó¶VÓkð<˜‚qÑghk„Ò¥0}°Ï¾6fÍ®\¨œÇ©'¾AØîÿVÎٸٱwWÞµ™ÿk'e¤âÑ•†™<»_LƒV©E¨ßðF2^ÛÝuk, zkãüøŽ%Ú-g4è8‚Ûª“FÉÒùZö"Œ4 <ê審9›‹7õÛ£rÉAȟDzrŒ=Wç1SDí¢DD=gÍ•'—O‘B«K ñæN+W§_)‡ß¥$°?J·n&aÙéWéä¹6vNëIq=è½üÍ2¨a߀W}œkôÅYl>ñÀ„"ö¶f}Y…JÞä…Ôæ ïCëæØ[Ô,5޶$©Ó…äLRÔ˜J”K<³— 2dD´5\>ÞâËÛô¼—{ãs‚Ýlò´ÊÖîà™Ö«6Õ†^ŒÇ|Ô´ô ¬T¯òIåià„±Õú­Dø@&²ñxnFœá&·É¯üæ(³S!j{ó“ÊÀšÇq£‚Kç²4þUH¿Ä`Ø·Ô5®à­—‹Xç eRE7tCmÆŽË qT ˆ~´ê©DFŠáoÚ…3‚ýFö+Ã7);¥¥äü¡oœÂh“mˆ½–¯²c¸ä5ò´pdÓù—Í3RYlšðÆ(³ä ×@£>Z•`Žlé 7¼#êÄÈÊ)Pª0‰Ôf¸Òi~C¬v¼`"B1 zœ«.2Adû+9 ï´Ä$eaZ Ô­oòœ >R–.ŽDÒÒJ¢SÌE°8ÆÁrÄäàK/ 0y¢¢RT]´ÁùJ2l™èB<ã~làPe 1®üNÇSáê-d¹0_ ¹ÂI€è<0ŸdùA7}Ÿ†q°'–UIÈ·Rk‘È¿‚[Ku¤ƒoð¿ø¥R¶yA\È\(ºÁ•¹[B…_Â&Ó§€ýÈl9™ €ðOð Jt 8:Iñ…V#‡Œtº ˆZòþHËÖ‚W x†Íü:ÎýÙÂøŸ»± hŽEG6àÜQ—«úÛÆÇOˆOxoÓõ”'…ê\‹òðäÎÚ“¯‰~¡#‚1a‘:üˆq‡ û«¢Ý#ÞïFÝÒgšÐG7æH~ª}¥L{h¦†zß!öiV÷o`ˆ6Ð4ĸzV†~ŒÌ©P/~P'”ßÌ)Iø@ÅPÔacôèØ³XщÜ_Új&Œ_FôÆž š¸Ï§³#•Péo ÉòU'–*fŒ-Dapï@ù)ÏU*ï/)Ý©ûù 4!Æ]RVdøç€µeuˆÖ‹=g´„Ÿ#k>2˯çyd«2ÊßÐ;@Ï]žumŸ¤ž°ÒV¶©z”o‚FC^Ô¸NNÌÙ7BUì¸yþ³ÌÄu¿ðÚÔwök.á_wq©hóRíU4úã`âwµRÈë'/Y.Ûç%h/~+Ï•ë(ÊÓò’ÒE ·îß9嵐̈¤“†25x*>%KZD±^ Dú§–ö=¦[ßVù=&h¬Àeڞ渘ÖÝ—ªªAÏò5Ü,³—3g4«AL»¬®€²ÇŒc‚»O‰ÈU‹ELCž–nȰŠÁÌ\~"!±ÂƒK%DuÖäìÞD—ÜôWÅ«à’JX‚½²`¸ÑÄèƒHŸ×òÏÆSÁSRÔ¾ÎØ `ž¬Õõý;Knè"¬sã{·F©tÔ+Ve~žÇX´¶×dA—EX$Ô§£Vôo‹@ørz3€UevfVyæÑ耀ƒ…Äç§s9€"/‹;4Z?_ÿö0^©óv ÄÄŠ?r£¼éž†u5ÜŸø*åÑm÷ßxò ˆX¡56Éš3ºB.ÎÅŬ‡¢ÿf Ü/åÖIFNbhWÆôŸ¤½|ä÷R›˜àg‘â¶[“pÊäöž Õí¼‚œ¬kCÀŸ2ýÓrÑÄu,)5éÄàIqT†K=aØR™ïpž¸1d…äá»2{ ú@`2Ø-x¤w]LëŪ8,3|Ëž "Ý;g9oLøÞXôååv¯xX ~YvÜèÑ67Êc.ZT‘aÆâ %ER®œŠWZ÷ôE#بEâ.¼xŒggÆŠéML’w@‘+¢k¨ªñÿd ¹Ç‹L´,£•ÏdèÊ`œÚfÀAø4íH¥M‘1Žì­c›¡(gûÓ²é³w´øìbË|Sß­QãY‘çÏÂJò¡Ý•´k|¾p|é|ò~G÷°5J¹‡¾ú3K+DfñJü/ œ4§´ŽlÙ(îNÃ6¢u$ƒeü×ÛºŒì—̑϶‰F½¸þu±C;…ô8ÇK¶ÉÈè¿3;`­™b}*;i##=1ä¿n¡–™N3ÝVØèZE\5áBž–Ššg`H"Ül¶M¬ó0qUÔg¢Ô srËÝDðál¥´+ÿËg“¢Ií„åK„Ÿl⨤Æ+¸¾Âª ½O½‡Þß^££Ãë¢ Wëƒ=àçX¸• tE1ÁgB‰X(G¸€§~ Ò¾¸˜‰æ,ÏŸêC‹‹¬8Æ¥­·«’øºñ7ê"ȸk¹%ó]²áÛ¾Íe ,Ø ûN†Iý¶ÿ_ÝE(Ìþo¦¿F8øi¢è±¢ÝRãžz`Yà !ÉN‡o®PÎYè‘óop¾ê›Ú›Ñ íøj!BU]S5šè¾3ïzbÿ¡¾#—…–ŒÑ´72Ó8;E(ú^¦Š‹©iââ-d´Œž°qC¡d@šO†€ÁQç] ¢f!éµAÌ:.¶Û“6'o¬øõrs(„º«DðÜyãKy³ß/mÀ‚üàÒrerzTR þ¸c…X”š¥—‰Ý¨&QPÉÍÆ/¢^Aïs(h%KÊiônáÈ$¾7 ¢ÁŽ[áå¿oDØÈµ½’CY,?M{’­!r7ßøDH aÓìµ°¥ÒÃQi$ÍD{ wB£ÆŒ]{^iÉȹ2ý Ør—Ay‘¥K-«œeŸ¤¸©Ûh„yš—´\Âc­ŽlDÓ½|Î(yÂ~®Ó ?¾=. è€ØS©òÃ,VcñàïU„3ªØ;ºí;›0™Œµ®ýÂu/ö ±w‹Tƒ¼üoGb¾ÿñ©µ´6—]2îr£UNMW‰›ÿÎÒ.aÉ6A  PQL`:~q%bLà“øBèc cÚq øðœ=,»ð¿'\âé»ÁÙRíš¡? áåZ~.íVäs×ä “ñM¶:âE}›CÓd”CZ¾ú~ÓüZõö6-†`÷1`‹#GZ¼ àOÅ6Å€Ñ/n”VƒAø.-Rk‰s €”³(^8Ÿì9·7©&>[²åf=ül"*w;ň1ðÛzÃUj^!{Óé¹*IXnéOžq™éBsZÿáÖYs¼’¦L!sWÙ¬„;_ É`ü-%ù™ï’TŽI× ¾`ÓmГBã¨GÐßŸÔØ\ªJЈj0xYi~YjZ¶eyöœï*êèAaŸºÎn¦üº™èÅI8Úbžá¬Û¿³NÅÕ‰\QORóiA)E›ØÈÍID¬sám™”~ÔÂ]eù¥ž³ )©$ëa@†T$ª« I¦Ñ®”ú ôè0TtÎYW¼Èü¿ŸUIkĤÞ1À=ç¶Wvá.mñ; ¶Ä›Žhé¦Ó–7µ"2h¾L°†æ“P³Žd×kàl<ÍÜ»ãó™rcówÀÑK<¿¿ü'Š_)òiøО¨A1áõÜü#×Üzº*>Óoj :HçîjÅÂK¯p¯I- s2# ˆÅZ†`w¼¤4ò¯ÃL„,'è´EX&%¢+žµ Rbl¶%L"9—(ã‡IEö™;Ûư§CoI·¹êγÙAíÒÙ‰2Iƒõ·EBÁT5t» ˆø°@¨—;íW>U®ÐÒƒzߘÑE—šÿç®>_ÁmY!_'òsTe&»%2Ì_€OÆüÙ?ÇZJ;är²'–Ããq”2 Ì èM“OôþYúVäÒ Å²‹ê†¨­.3$µ"\É# À­½}ž¸ÈÄãövø\ã‹GœÕ,BNP>Iô¼˜Ò0óüÆ5݈C%©7l¿˜þehÿˤҲíhî*eu Ì c¦Õ˜”b ý =0PÃ6¶øaßiFÒÅA¸³›öx …ÄÒÈ‹µúG7îþ™–Yx½L¼˜û¶³ëD±æu.™v(ûòlEªd±¾4KÇÈfž©¦«(.Œ—”)”–ºa…&2[=ñÄ3„åÜJ0ŒÀïÈÇÙ\3™ CЩ f†ÉÔSÏHÎÌâ¢Ç‡$‹1s›Òó„C5 ИÃY½£wc§ ÙWC>y¥aûÉWT¬¢Lþ 9ÿ2}e#@׎ŸamÏÑ¢š Sú‰%ç‚­Æ62ƒÿ|ß÷ynŸDú7õ­Çu)M¡ÅÙI«è­6ŸYÔu£ƒ±º:1.?n¯ç¢:’Q¾[èE5µÝÞÌùà¸Ò¯à·¤þ¶[ø€!é† —žØdr„à9xÖKÚCÇÜ|ü­!éŽÌ /u©¢Ã܄ݔ£ ÑdU>(Û”0¥=ãèÑî_á8›a÷p€²mø‰ÐP#'é Û¾³à þ6ÏçxJˆ p·/$°».]N2¨kF„À YWoåW$;o0À%êÈÏ­´£–¢ÙPÛ&M†[#íÄ"Ä«Gh—/Mò“<v>9¾kG‡¸PU/ µTz ÈwóŒÞº”OR¶ÍÜ l»+T0Ùò&kuHþÀÔ§9ñ@/Õ:.|¾xé=çêöoP’ ÿg¼è0&9WªÚ …5Ïþþž·bRUrHu_]ïý²yCÆ5(eK¹ëÚRâôÔxîiZ|úއ±LìR k¬¨²U“ Û# )섪 «,ê‚>ÊÅWÄoË»ú°l(bß*[8äK˜*ó~‰LÆ|€ì¨ ©}¦Ì"éh©²XY «^Í0¬žóÆ®¹-0õ³·À¥ܶF<€©À üÅqÖÉsïZÒQã6‚b}šžÐ’ßcË%V½ç„zƌژXäÊÙèlî÷Öˆù¯>ÙÖ;™ýrrÄYGÏ<¿lñØãhÐå| `@Hˆh‰¹÷ƒÁž§ÌZÌæ¶¡Ô%(M÷B¾kBm¬vOªt³ ”ÍæúHï1œ³&ì9™Þwcëé¼Y¹Çn—l§…"ÇŠÆ}Ú•Yò¤mǪ׈V|­ÔÚ¼{UÄ¿–] ¼þHÇ;ûWyˆ?ÀáÈsÇaÊgaD*·Ÿ02ï‹qõÅ«Hm'Ë3.ÖÏd-Bâ­_&äˆÆRLË þcj#\YQ雇$Õ9 6b'hY„ebÖ±_«÷äÂSý„Ì®º÷!­½³˜Œõç2ßèÃ+£O×Q&OD}Ñ¿"¹7?(kóÐh[ö…ˆá”ï;²¢6%1 *ÔfÄœñËú%…O¥bp˜wpüùüËšH0ða¾€´íXÜ/‡FEOú:O–íi ÿPk\­«¨3m"ƒÈß,:ˆZèíä8²ð„ÊÒ0ÄíåŽ3s2•¶.îÕÁÛ9Êëì»O˜W¨ñ9" ºrÈ­ÌYúï>tc-:6ŒÔ~½ß*ÍU¬w•[vQÊâÖu7娬ڱëñ¬¼h-?aßX_6ét¨'Gÿô¼DÎXއbàmI–$À®‰´_w0<ÆÒÚ ¯–ÄÃ"(΃nYƯò>íè&Ë®î6,‰V›E]¶ xÉ"\ŠþC’q0›âoœüþI¾¥$Ó‰³­´äk·1ûZrŒBåX2 ºôŸM3–äVõDÃ?.âùx! F6€Sù¬÷Pó‡y"ž;ñ:‹´äýÑ!5ülÒõž… ˆcÚª$~V †û õšu5HLhÎÉ“›Îçl¯§^(²Ú- ý¾SÍ}öZqPÁ0ýžÔ­ôVKdÚ®ˆÉ"ÏNÝp 1°Ý]„ö»ÒVû†©÷N+Ò«éÿvŸU˜æI8i¬·àê_ —Ôªó› < ÙÏÈ`ÙË×¥×äúî±åªû€´M§GÒÓt@Ç‹òʇæ>Ìô‰Ñ–05Kr? •«pœ¬ËþGï^R"‘ ! uÐ])Þîãü-ˆf\*ÁQDªü"´û'¸)Ú¿b½¹EuHP_œ*FK‹5ØoaøÑvP 8¡Õ«W[.Y‹YJ¸¶ Ù-µdŠIwÂl|ð[b®ŠôÏ(„sÀç²5B KòdgmÒ˜e:`öÆÎ–Ò(NSÜ’·ž\®·õ?nÆ VöƒŸà@b6dâ–0*‚Ý×gŸÅ K{¸§äÇ}%eØ„ÒÐí‹m:çJjB݃3Ë螯³›mKõtDI'B“àÏ"ÅA4ZßIÄ †q›ƒä_QÉzùüŒê4zxÎðŒÂ¦ ÏR!WiÿnÔ™›þ”Q2ñ·Šyü·¥áê_>á^yÒÍöØ1SÔcY}ÿ4€n–‰Øôðæ{kb{·%ðó`ÃçÊë^oÂDòãœÂq÷š¦g¶í,žmiÿ¾Æ’¸ÁójûNÁ°êÆàKEóSZ¨iJá8ã&7-CÚÐ\ß'K‚´Íƒû Õ—þÖ¡êÀ‘ ʧ m-¬ƒþR»E?‹Š2Û Û}ž›$>Çh†ÈcT¼mЫšØ¦\(A¦ŸûûÏ9)Ò B_×äjab72Vž’ ¸„b0œ'Oÿ¯ùÝ•†EÄ1WJ¹þøþ™6ŽÒ›ŒàGî÷põïšV'ÒÊ몓 O ë)ð5ŠÂ¢«óð[W³Þ/ÖTß Ñ&,T‚}ëwrê­«PkæªKà…÷_Ösá`ÿvWò»³ZÄæ?h.¿ ²¼pW\¬ðho6ð_ŒŽ*J}‚£\MbM¡½k›Ô½~Y€1•§6¼2µ¦%NU‚¡—#Ú÷Ú:ÔœùTÛQ—ÓS%*ÖOÖj5ÙõÜßGþy-Eœ…?vœ¹bÉ{o1›摃g±† LÛÕ^/}Ò`—kÏ8{Ÿ‹:wˆèCyëmº§æø^î@‚DL’$s^>ò¯<þ-ÌÀ[¥‡•"»”ùV °Fõ 0_ı.ÑÃØìÜ£“ˆ-£°Ç6yÕØa(?S’&kE¦Ò”°~©?¯,¼T錛i\ö´¿ ª¹MâéñùÏ͘ä–.¤¾®_wˆ´µE/*“´Ø;wŒôh,R,I®ß…•/¤èšr&ÃT?"¡ ªñµ°3©†øötZ7]’Ýâr¡•.¿-ð²M¼G)‡5 –lò¨ãz~2Ù¸zVaÜ”VÔ¹z†›cç¶bžàçc=Kâ\°TWt=]ýïLlBj)¾ŸxfT0,™\jlýÁpâckïÏÈwÐ/]¶ZD`œS رs˜[0—õ`ÐŹÊòrpµÉ'wð(:o†‹qæ´a2þ!Mþ|ŒVƒBŠ‹Ýà.¼'›2\½2Hš¯çß,¦ î9C{W+°$¼ 4}ì‚Sœ'Ú'¬ø:ÙÉXòÖÕW%X¾O©“=ä¤\@ÿò"üýy&1:ÂÎÒˆšóÁ҄ǧ'Å€ÔçÌ_!!êé[gîÉH$úZPµ­h¨?òxâÏ@oòǽ¥í‘¸üºÓÑαFüh´Â>?n„epös†â×óé £µ‰õ-O#â¹¹p¯ eÛòi‚¿É o¿ÕLDÂ?AGÇñ}níMl›ŒþbIÛÿ.;ÝS)—d±w8fê'2>˜Â‰`VõÛXÐê­¯d®ÏÿÕr³¡K2QYÁF3g(PµÑŠ©¼‰¾5ć‡[#á,ˆH• î"Ϥî22‡gê(~Ö]ÿs''ÜöÒÏý.XÓ+%_Ǹ/š›ë|gÇ5¥d;¶»=$½b.Þ"‘òRs'jЯȕµjùŽÞ±×bºf)ñúÓÇ:X3Åû î‰÷{Fc0:³Yb1A©˜«-*Ï®àdë×]dðZ­»˜@bv{ëù8•ƒ[Ëöô Hjä¸õ¦êõ½T)´£o‡iwd®Eœ{^wGBÍŽÝéÑÆÅ·UÍwÉ- Cðâ–‡ìå>ÈÀY°Z'ÊK‰ƒ3XÍ­¨ñgcÖL²ekÅ,»l\eøÓi}M,èΊ·(ý3‚娰f0j¹&ä/-†Ü6‘Ü#ìÿà,.ùÕ‘®ï×_ÅUŒÞiæ§DüßHóÝÀa@\ SÀEBá¼X~Ïûš:ôk§†Érëvž&ÑdCÐ.Ú¹PÞébMœ†§­½q ©ü½rRtZfH@¾(W¤’(: ‚ ÏASºŽ1å)­Ï è±É‰ýøŸÿ-b7l¸; Yo)Ò’OƒÞVÔl5FKÇyá&§Ëõ`Ý…|ƒ)I†SužÊ¯ÜæÂ!Ôz#ÈorÔæi9jHè¤J¸”W %8aqçïÙ7ÁªErâýBv!³aΓëÃGÀGôtu«yC«Ð„éKƒéÈÞTÍ9À“96dt»Õ4<(øç×BNÌ&Á¶+5ÑÏg/¦$3äWOôGþÕЕ°Z6!ˆÍ¶Œ9O½»Å_;zÝ- ¯>ôè–Íì}¬Þ©#2¶;x&<Ì–j®Œâ’òÇŒªÚŒõeª!‡Ë¿; üßÄO{ÈdW.Ç"rB"r áí²éžŸ½Mººæ{É|¬Dé3‹’?åîR«÷óƒúæ†úfܪÏÁ(êÁ-(“늨•¡\›óÁöΣ§Ë6.3UŽªv›±òÔ#BÞp‡-Ò fg.S;ÔSi3œRÕ'òùðÈOm°¶ñIs}ìü„ØîDÄÕÄQæ×Yù™.<¼ÁxG ­¹I.Ôxk)j%±cè™Ã¿êX÷IÒ„Öòܤ¬¼°~ g9æcûGÆyß5ÿœO¯J–dz¶$m²‰WZµ Â7§"Ý™«9j0Î,2(dTáñξÕΫs„ Â…AóuÌ_T– 1§Àv|Äbl¿×FÝ4ß­ qîCyõ@µÄÕñÞ ßg]5yZ]Ø/®…c¢˜[«Ñ©•]´/>[/!"q‡µÈ@ÀÚ¾T![uqÔv†òpj˜Îö ‹¢VÛI ,qLëØ•¦‰à31EeI8`˜ËÚÉ\êU…[Œ”‰d †Üü‹`•†€Ï°°í>˜‘lCùj„HÒ8¶t@ÉEqŸ1BƒhãWи²‰[L* onNêÆ!Œðâ{=Z—J\^/A("k¬ÆBÌÿAò¨£‰œC/«…`û,·¥Ú6q‹AáØßžÎ÷Q ‚¦{œqwE¤ž^"´«‚»Ö“‘)2SëÈÀÒ(f7DÀRXÊ變H†ôŽL©)tïYgY~˜m®x@Š'kž‚¸Ñ5eÍ~ª´fÏ6ˆ´Q¤Û–Ó%ILZ˜Úóáih£õeM2ˆ…aþݹ~œ!<èQyØP,™..áÑ 9ìË€ê!åZ 8Êó®W'Ü7À W’;EEv]“˜¿Ô)!Õö P.Œ.³ælh×­ú??œù ±.y3!§æ¡þ&U[ÍoƒP›­ãfúFg5yöo °æ>8X]'ÛƒDY2‚’ÃS“:©»œ‡™­p>¼%´½k¦ßÞ¬UÜ]®C'„µžR1ŸÏ¨º7 4ÞRׇ|mC[”F ‰D«C”oô—œ@~*ÝÝÕå÷U¬@qAïJ gA—ó‡Zº·º;ý^ðaJ¯K|LüÓßáéÄ{ü÷ɽbàN­(Àók –wtFY%ɇm¹0âxF ʹÀ󑙢¬VÀëQÕéMŒ»…²¶ Ð%Èéù¼Œ‘ßú®Ã3«Z5uv1nŒ®ØÁ\Îì¾îJ1ï•v7£O³Øæ®ÂkbKÂÒ±Åxƒ‚Ÿ9vóÒû]‘ò)3œÜ3ÚÏŸ”³T>†4Jû;\ÊÈ3—ÆâUÞõØù[- ~güÒ0×CÚˆÕ:§ŒR®+„/z6/”ǺÏ´ŸË«Ó}ÙP ãZzëUÛQŠaT-$ý $=#”¡§Ù=UßÍùÄ ä?«º!ttìE4<iÚƒ<šÕ‰òÉøoGìã2W+”É Z­0¡_ ~)kƒËŽ3ü£ßÌ2}t~ä{1ÏhKåq²‡X³?¡ì©½T‘²É”ë‚Ñi^}±u×âëÍÃ[Kí¼ÈúÎ)^F6YÃòýì˜Ô€g@çdÜnÆvf¢ÄæÙäüGiýlP))cš²^!÷¢.Ók8ãyæ<­©I}ltD"ÖõÖY˜…ʃ¡U Ãæ¢ÐJ[F ºê¾Ò5j™oIòVÙüÎBuÆ< -ÝÄ[PÛl²ñh›s”–Ùø"”•D”…QrTša¼#ŒÍ‘»0©³›¤“¦u.k 9 Ÿ*›­DyO(´³-ßólõPl˧¯ Ámª¿£bZTŒuµÆËN>µEpëV`ÌÉñÐ6³äÝQ­ËâÏþU5–å`IZ6}]é±K^ÌÓ²S%Ed­|„S[,SŸG%tœO§× ¬yÚH⎩¼ì y¥wÜ IJ˜,QþåŠÙùëBwÓÞzGòŸ«»7P2,1$¡“#:¼@zîòªiFju•’„j9EÇ/´¬dJÕ~åëiÑß-”*QeŒK§°Y`¿s³†)ažÚ»wðÔþ,pº»7èpZ'»Œmö#zîµ,úʪ±sšªeqkî·ÞZËÿ¥g”Ê ¯þî)ÜVŠ&B¬Ftµ×uÊm°H$ÃêNSÊY«±Æ…ãL° í²³(—~C³‹S“­LÒ[Ž2)C†ØX HÃ~|³Étd7–aÙ­2Bç†cOŒÌ|µ§œ ’ÀìÍ ÕÃÈ¥ƒ m„Ao:e¾ŒâéT˜ Õ)¹D@gîtGeŠs*`xâƒâM&~xŸ—64ë}؉”„·‚©ÊÍð¾¨;St}7o–'ž¢wÊ¥ R°xÆÇŸÚ"~ˆ×;çoÉÇP†%÷šN½=›ä¾ë³eÌKÈ$‚÷ \:ðkGVÝ&÷êë¸ 4"º† á„•û0.„u^æU’GXyOÈÈ»i2@/â_Q¦£1 xð€«8¡HWI‚YK¾b|^\eä;“«ÅævBø±&YEý¾zêÐH ç K=žE’ÓL©ïucC@‹ŠÆÐÿ‘Ö©œ’Û7Z˜D-û„Uon¥†yp}Çw!™WULäÕ²é5âÅüî/I\rH÷ùžª«nž%¼¯“Âk Ëï!™¸'ahécÇΑ ŽwCÜ£'|Ž`âoë”Hx#ÅíHœOh¸iQvÁ°üZjÖ…ý÷‰wÓ=á‡õÖ֯"ÓUDÂ+kD4D ÏòÛ¢Be)ôõ«¢R½š³ÑÇõî øÖxS1¾€3ì»ù¯†ñ ¡ùé| ¦é|°<²@<¤ülq|¼cÒqÝé@1ôÐá3d—Ú±¡¬!mQù-)©¥„1Ó oî€nm±[ݞ츿ÚqœƒÜ%±ÀA~ŒûŽðô`(V8D™ˆ’v¢E}Ãù>8P&#¯]åôV´Œyöü3º0±Û¸\—°>è'ï(EÁnbÂ…ÀÛÄ׆öØÞÊ~q³=ªŽÐL‡Å œÍqT7b1é!¯ºQ¸bÀµ-ð²ß§‚šVÖѰ›8,ü4v©Q3µm ÓvµÃïvPØuú-èmÛé_®ƒŸ=Z¥ú°õ,àܯ\§¢dŽï3ÁåÎ{rJˆ ÝK¥ÂjQxó-5õÁ¨¦h7‡”›Äׯa~WH£ñÐì1:uUß”ýÿ7CŸ@t.2ÖÁ„iCÁg%–ÂÍCƒÐßö=ãzÇGÇÑ0ªÌ·ÚsÓ-G˜9Ýsr&šÞí'gF0ЊÎp>ɲ¥0K£€ãqñ ¬gŒ¢Ö’èÁ€‡æ¥adÄà‡Èdˆ=ÃJ¥<Åšz°tëúÌúË^C¤Îú·¯àŒD¨á JùOCÀë(SvÈB$!Ñ—Î/aaæFyt…°Ï rg@Z<ˆ`8ŽGoÄ)º|Æ2x7cdeoÁ¡u„{ÆŠq+D;–?‚º45Ì&¸+fP?DZ­z3øYqšø'#YtE1áÀ®tSÖ¹»Ù9ò¢Çö_ã<¼ÉÀ­×«Nú¬æ]4ñGH ÚÔí½œàÐHh`·M A?j[­sÞT{ZžKmQ(Ëfµ›B(Juc×gíaIùn ®Ë`eáY7FfCBä²ÏñÝû¤À€3Ë[ܲƒöÄ×;ƒDƒÛdƒ†ám¢¹ƒ¶çz# Û#eÖÍ4MEÀ¬x¶é:k áâgâaI "ÆŒ?]¢ø@( ‚YÝ5Õ©’žØÅ¥€xŽ—ÖÏŒ>‚ïÁ+oŠBD·áê«Ù BT‡ùJ4SÃÖ4ƺÝé'/¡ÂC/}- @Ks¬¥¶Ø¨jéE~L€÷¨T¹Ïúé õ·Äw§9ˆèâfXÆirÛ8Pê{·ëg A€z ã i-Öqˆ*”¼€q°Œõú¦.'oT‹ø+å ůq’©(ùºÒšøN0zØ×;ÃéÒ–.Hø…F¯Cñ¹¨·î“5äÅ—az,¸î×;QË›ûºM9¤üOæÛì4 '‡ÝÎkõ@2jzúˆµ;hÈ×hé.ÈÀm[‹2˜P‚ƒ§Ð/¿ÀYwÇ•DÔW) â‹>›ƒÇ¦Bv³þÙÏr@2öÜÄ…/ø9ÄÖ;yÅ|åX~h%¬ÉÊ- É;ÛDÅmÈùP‰ £Îv>ɘ(ØÊ²((K$u­£2ª̆v`ï­*roJ¾|í¿O·¯X2ºè¦lK|òé+'ÔýyUkúð:ˆAéQíÚÐçèb;( ~"½{oÔ"4mÂâmf§ëµø»¿%¡aáo¼ƒ’xЯÂI·ñnú¦"IUÅrÞFxSÚÀ*+©~×!è ]á@^8ž…¸cËJÖÃ6&ä36Ó'>øG®Cþ<‹GâR)ø°´zNx$Ø&û?7§7!ªX20Ô‰“⯇N˜uæÓ¤Ñ´¦VUáf ]å;+Ì1¸…o/—ª}GR1¿ÇbA‰ÐmÓf@•.®Zj€Ð-ý_‘_3Å‹^+\ÔN~…&PcâÜÀ¹É"’¿IAÀCB0|ìÂògÒZš%ó@+Ø7¾6;øSr» ö@ ’ZWÅTÑ\¨Åò+Æ®Bï_ý\òañ1Ë-nå§‘L²:(F§û…‹=‡ƒ,¡/ñ¨áŠâk ‘¨Ùép­ˆ)¬[CÍ¡·” }á‡Rá[ѯ1cûéU6Þy9ÊÞþIRãôNÙQK§r¡¶Fþ­öó¥=†mðñ&Ī ¿$Ûg'bpj·H¿Œ¬ºØä„ìÆ§ÔÏéxòÓ)9< ª"9ŸŽÜÁ=]W«£Þ­¼Qü4‰XÑÛÚ\õò#+W' à€É{ÓL¤l2ëY¸0)Z7fbüQ×*¨†GG¹ã.¤–ò$â/@<ú)Q&eöEÃßdA<´••yF›K®èOè¦Õ UfÅzñTÐA©±u|‚i?˜)b}6ŠM6?Ã*.gA%b2³ÜnJº£›YòCeˆL☀;ˆcýLb5Û>xÏ—ÿ£¥õìç«ÛÓ$¡a{mX“÷, Ø:qOM±èóÏZf¹Xœ×Ч²¤„Äqü*b¡\20Us 8ìˆ@µÆB±Ï2 ¶CZ‡”ìeͦº!/ˆïs«NVø˜0/ç*“Ù†°€I~!© \!F™êL‰Ë:;„3½±(’ß¶@’ „!¶cë·l|]ÔÊ!joÞµ–¿v©»æ–O/kPÍß–{êíèΔäbîÞÛ ¤A à›gžºV¬8'?ÐþJé”5èvóÃ,tÜ©æLO4YÞB$qe56'*’aáŸ.ù…«’…{Í´z“ÛÏCpƒ]š:j<”*L%ÐI÷ÜÔ%I‹¼Ríãj-,§¼hÂb•™²Æ¼ÿ¹çÚ|¼…;8;grÌÑÍIÓ#V™Ò•ŒkÏ@µV] ä>–±‚%XrFIt‹Y¡õ–ó¿Z´µ¤nre9ÎÁÔ܉åº ¬8ª¢h£Së>ºqÐA,1!(ÿ”ÐóÎ|"üÛ(XÑtH¢K 1dtÁ®(ÈâTqÿ¸z,²{ ÿªFÎ_ŒöÍCü¥c³ÅЫ®R/¢8tæfyAf>ðàW³GâU¯])¯¿£ÚZfp ö¡\¢'P´v¶5'Zò)'Ïò«-Á¦w݆Z1¨õR,³8ðÀP\°âˆ¤&“¤ybŠkZíu¤þ ÇqÊtwt'À¯i…h^?úÐKQsùçì©ñlAê[ï–µñÝü,ß¿ãpOÅ7z –žÓ¶?÷q¾Ìß&hjÓö¬ðÅvžBˆçÙC.Ü•«z¢eAµâþÆÅ%>±qç¦mjLþ·xKåÜêò’ÇWÜ[ÿ6ü¡ÈTó Ióð½Dt{g>Áäç%\¬ñ9ú(DÐŦ#›®€d-ØPlú>{¤Ù(%¶’Ù£°mÚG=ghàK3‚„u›;ƾͳ(0µVœ!*+6ûØYBAûYØ)‚ŒmÝ« |ÿ鉩¤³¨ß{×g_gÍù]:D3sƒa9{ަ’å—»ißöqñ2ò¥D«:îìÀcpIá~^Òø?`–—ùu`ã×%ѵ–_‡]C1(eL¼TÃI% u®ã)Ç–ÒÛ\ɤΠ­SLŒòÁ(ÞªêØ®0ñF+«Çè¨[áíz€ÛaFið–¸jêäKñoÚ¶nè‹átY3¸hú¶'OiÑÇÜ\;œÒEûÀî™·¥YÇ~’ªQ=™¿”Êh¼Ràèðˆ\R!PfZä:Ùè½¥L,pgs7¯$)ˆ¤ñ~¹­6ñ±Ú“N :Á1ÅŽ eAÌÆÞD{õ7ù¶ç)Ô)¼Ãô#qð¯&êàm<ˆµ…|øtèûÊqÌõ«ŠETÜ.[Ò¨ˆ ˜óUcà 5»þ’‘VÐúTöX ן_=ÝV2Ž‹·áó@V¸íˆ{`O0Uðmêõ “×ðŸt–§ü_c„bæ¡Ôf*ñÁ¼êî¶<¼l‘\J½æPåTŒùRç‡É“V)îqKqxÓr±kUÌši^ ·JPUNªýãçÞv,ªydRÈvµ ðZlø¥WÇ0û-×eT‰È]¯Úžk<É¢nkäÈL |ͪ½úß–Ÿ¥ Í:Ÿr5üv¦oжáulÇ ºýÎØðÊ…ìMõ"[iiFI¿-ȧÕÊt«Üáû˜ùZq—Š#þŒý”Ž™3lp­”ì¹]ddÇ‘UÍÄËÏeÂCY×±[Ù캲Öሶäî8Qö|¢a—p.0n¿hhÄg@‹L!¦’½‰áÚ×YŸZaò1.U¡‹H„¤Ç¡ò$ÙUî…"P/Š÷#9·i £Ã=<4L{ Y}$–zXf°ai™[H'?‚´ek~wñÆÝï &ÙýÔl&RÜË›#o4]çJåïeÃä 0Þý¼ÚLjH‡ŽÙ’v‰EcÒ͇¼§å›p€Ž±”Ððíà̯šUã…º)à>UKødÁªæ³éTÐð¬Ë^£ND„(>r¡¶œÅû8£Œ¾ï¨œå7Ùo5¥05[€T#!lÿõ…ÅÂì~o³p31†Yqt³œÚÖ =¤ }Æ[Å{ͨ·¸ôÛF7‡G¼×àz#‘ˆ§£ þŒ;™%K‡G6|áæ0”å}fxVQƒùb ›£á¯Ñ‘êóÌs›¶’x&m}¢ìDÌ`×;£±É)ìˆÊ§-éۯT„ƒ€ 4î– 'Úê¬ÄþcßsÕÈ+‹Gt]f€ãïï¶p5‚3‚Ú˜VÓ¥È54Ega•­`‡cƒ^8r$/ ˆáÉÿbçÊjUsö½ö6•PCl矖«æ¤s=M¢˜q³†+2#WÎÑiL±v+X¨j¬´AK‘XÖº€qËg†g¸~˜:–š¤5Šs_:Óø ñ˜˜ $z™ ìßù=Á¸7}\ØsŒïÛœu´¸D¦ñÖÁÆfÕêú¼ÖŠ*ïF¤"tŸƒÃ|º:êHr‚•ùÞ=Pâm“ƒ¹ky­Þ¬}ØÕ?T(2@V _¥Œ]˜J•Ìä`ãÜ[×£â$“sª'#ú9LsEé„/׊*Û­÷¿l6ÏV#e¡….!qå'èÁy¨ñÁ˜øíúÒ04mQ¥^ü¨å`lèÿˆ«Dæ2&÷ü¢CQј( ‘3¶â¶}] Lw…9]­rî~¾ÉxÇÍ1ÏЃňšÌG£DÏ 2]NÄ>mŸÒÌuâãÔ¹›áÙ½’´êV=Mc3ÎÇ&Xb¹ÐC¼ñξ7÷L¶é¹D¬Jb¸3à_ÃwIÑ:ž‚ˆ³TÉÜŠº(Ã(½‚ÿýºFê4%¯ß6ÞºËx踡à'•òxóQSEM‚À¦Ñ¾ÝWªö@²_g2…³2Ú{¨î'ûNÖ¨›ÌS E£:Žº¢ëFöõÄ3ÖxÂGZ“ºÙ(5Ϩ,É#bCÐÍ S d¹Ät‰©ºÙ¡;îßü½…yC{¥¯/oá}·ÇŽ2Q4½˜¨‡¼³Ó —žÝ‹^;ƒ4#ÈGÛ.ò¡: ŒQ¯"pžÄ­V«÷Wv¥†M&ÑDô.Ѻû*?Ú•v¹ṉ̃M‡ô÷Bªeõ |²€H½åÿŒt>8=çéùÿhÛu¾7Å“ZF!M…t'!Ç£ïO|Ø—‚K–,hf°ÔvAhH<,}&£7Œ…F¹$¯¥ažðPF·`…ªßY å>!ÞU£Ö¿† ‹ÄƒÓêGY¸¸ÓÎákHWk_ž:°½èZkR#IŒ“­ª¡à(#kiNexÏ#x=>Xâ#¢Ë~Ú6ã-ì_—­ÌÇíri·èr*˜$³—þÙûÇ=«Âu·D<Ôžªn'J¶Ç³cÖðà/ßv°%"koäw£X™×)ãxy2{Ho×ëwåHm¦ð¡ûÂKFIß÷DÂì—&NÓêÊÃg&:'-¾¢ ‘2mg²ŽS¨™Ø°ã¤# UÒxI´ÁáFL#ñP¸"á<˜ÁæÞÉYD Sy00‘ñÛ„À(Z[@nƒy”Ü8d*sk¸°S/TS½2)²ãê©ÈYƒRäÙª¤ï†’(ãËâàÅôm²qcq€æô­µékÞS*ÀÈÚË‹Ñe1ÏîOäåè ôEÞ§p; ªn¼õ Í–½dÊwÓÉ{ýࣥzdöê³ÆÒ,±ã À™Ó]µW'ŸËÐc®É ¼s½Ä\Ê{ÉFÜë:´6$°ïQ`߬#«×]GÂ^|½8ûQfäù“®F&I;/á¼7;³®ØÌÈçì˜ù 4³ƒrÈ:iÒ¹iƒszд§n'\,þ¤`F™Ï–f™| —^L?bA˜¾ss­~.£‚‹ã>ŒqóBôó…v_—–jòU i¯ŸD±nöÅN8§ÊN¬p!–Z¶½†¨!{Ê kZó¦ú©ÖDû]ÜïÞ•ibj7Y "9ÿØVKÝ:óŠhéf»ÄÛ\²—‹(ÇO±ÄÔæš¹£4[üpÜërXÛŒd#¦ŒóIqë8¦ïgý¿OΜ³9Nk4GrÇ2¾QjÊJëè(Tæu{f:ÕhÀ–-)z Ü…i‡äÖ#—\ŽÓ!‡d‹Ìs@P!˜üÒ G¦" UâE°¶êæ"¶èpj#fú|$ Óã5çöãp[ÈaL+.úÆ*…jLdý²|\ðƒ˜òrˆ=Õ2W‚{=™qÙ lâ`l tÍùTÔT …NËRï ð¡ó^U%t½ þ_ ÈX¬ Ñ–†µáàË¡$Î^r„ŒVtʾÿø$Ãp6z ÕP {‡"krŒóôDÉ– Ëð¥ÂC~^ö¸ŒF‹-žÑQɶl".îh ·›ÉÕRù’Ãuè‚àuìŽg‘ƒDC;o‰ðk”²÷k*Ѩ`ƺ­Ž‰ñ 4£«C¬GãŰÌAŸ°£¦,ù¦›Må\½—,nF0 ù<Ž7t£#A­°¢*¸°0ç]bs²ñšrúÞ"õ[Ë î«ôU´dµ±ðwì+jÒx´íò—'[Šóaƒ³ð5 wÄo(TàeÖC+©Hƒý][ƒwÁÚa…€!35ó;)ç²ç8Nr¹Kú&1Ù¦ÉÞÞ©ýÆó†%öYÜ ÕÙW2ØE+J,ç»ùÏÃVŒ#£š†<Ðãá6¥Ž‹E%¤É’-ï¿j ©üƇIB²¶-³ØQcúÛ²õ–Òu~Þ^j5ØšÔ­Ìí§­Åä \†Óèæø„^c-¹­ (ùœÂeÜ!ä¯ãtˆž¾s…#æ^RbUÞk[Ç(aùÏT• i6IUãÇØÞ $ûq§˜bÂPõ+’ó€J.#, ëê ämôb6†iÍ÷HN–"’X¡ut öH ÓûÕ3N:áËÇåÄr#ôÑ$ð¾——î$õªç"i»©]4ËñcU~1”äiÖNÑ-TÛnZÈŠ·æù1Ê™ƒ©·Z]¦)±í™«ØNïv¡£!EA¤u©æÚ³Í½IÍæS` ¸ÎÿCh°³ Öè°6ç+Ç15¡"¯_¢3‡OžYቿ‰Îsb·Ôs~‘ŠÞêx,ß~&ÒtY©»ö=ýìá¶²£Šs+& s-/9òT¶-}×'ÙdIçý]¸¢–ƒ›þUÕªœ»æXt˜®<·®:±ÑüòèÕŽpdéVn¢ìKRovq.ø¸LÍ"5媸s°CûAI üƒ†•S©­î3fÇÖÈ‚eõ2 Qs![øbqŠ“ü@e¿é8£`T-]¬³n=ìà+c˜UmÀë•‘{ü{;ÌÌ83¬Ø„ü™7N× «Â«;gÏqšþ&æBjvÖHqNª°ìŒP[`ø×Þ–HE¶Nø±cYÀÏB ˆP—%믣+Œ]Á…3€lÿ죶09•-meô¡‡wsœ‰½M˜!„zFa^]QDŠ=q™º÷!¶¡2ï“/îßÌxå%ø—³¡µ$L(ßUÙuYy¿´Ç€û‡ž…Ü|ÌÎc,M™Ø¥R7mòG©Ðï!’á0ÌÍÕdيذ xèb¨}¡*Ç[³S@•~1ÌÔùUœ„žÕ/´# IQ4³W² ØTõ6—8LÎ#ü~‘,V>ã$^ß`‹sQƒr“`Üÿ±¸ÇÙÔš±kù¿ë½m8÷ÉÝád'0ô_þÞ¥[¤7ýNxÁÙ;a{;I8rä#ðÛãQW]»X»˜ŽË É y¨ùûÚ™³ü¶°z,å׬BÉm¯}¨qX>*±T2ARH,œg4©³¨¶?în“xl^`ï×w<ô$—ª¹ßÂR¡3ý¥ ³ÚÖ^Øäñ€WZNYˆe¢µíA©pký—t“]ŽƒKs §†$ÑHÛ¸%Rrà ç±Û]«2¡¡h™:RŽ?EŽþJ}—ŠçbüµÉBp,°&ÿjè9þ et1ÅH¼{nuîïR‹5{µùÝé5 c;ìXéß…‹V6˜9æ}õ…BFêú¿˜H^E¹¼µØé-}ó,igäçž³ó üág5 v-<Ô½0Õß …Ì„JÔiøþ¸ÌBºŽc#•#Xü ÕÜ3,MÆÓ#á $W« «‡Ë~YÈlÒïܳTˆÔh»¶Çm TPùc±µøþHû€ÌM—.C‡u9_h¼£ÃC óõÁ8Ø ìÉn1YU-¹âÄ ‡¡ú± .ˆ*Ç@õ§»ÆPf¶a#Ø.ÛZ•¸g²eÕ1 lGhìSj˜0¦øÎ&_{A$úd™™H™ZøL3„Ìèbªõ©SRÊ­ q`òì©øv¤Ï㇭1Û^¸@³²^ÁÒâä°ž#—Ž*ú™ƒpô?ƒ[‹Â£°æ„‹Ô«½^*„›0ìRÒ¿^J{ìÏÙZG{›­ÿ‡-ÌKE ÑðŒ:·ÚÊxM mq)Æðàûji+é­|aQ²ÒÐG57·éäµ ³á ùY˜|gCt£ÃõNÄ-Xõ?K.ë×ñGˆfó âz¾DéĈͫ±êÀýWöÌJð‚ ß “Ëz)A-o¯§J¹E@Ît£_ªÏjŽv÷Q`À¨ÚîÏòË8嬧í :VÍ‘/nÔi§†ÞäµbUݺÛv?-‚wdr<%×O ’†tƒ·· ƒÒÐM±K„÷ͨ –Ô,Õ\X(š]ãaYTªè<€sôáQNþcøÁ5þù÷¶0)Š«˜¤Ãþ®z¨`|c¦.Kü΃âN\]2¢Tö¾ÝˆäoÏÎ,®diÁƒ«æ« Õ9Ò£ c^¼h‡eOZs|þò/ì0Ýtš5¯&‘ZÛ[™Ø1þ2ã=ÑY`ßw'ÉïYR‹ùѺx¨‘\ìk)ëŽÖµ¶òƒónÍCÙJ¾F8!Ä“yßJ\zOb*Ag!ìùÃëÙyÿa™ÅÔMÑŠd á'eÎ[÷6Ú f2"ƒ|‘ 1‡ŒôVˆkŸ•(ï÷)3yÔ©¼É/„£‡è×Eî°5Éél—0Ú}¤G!†ûé»Ý6´d›È¼ÅñÀ1X­Ñs1^ÊZ_¢Ð™7B¬Íç܉S›dAÐ!ZLð÷EÏ—"§˜µÂ—€_ùüÌ¢›&2×UžŸþŸ(Žº½¼*©„v»®L³Ÿí1c©™g@ý[’{CNÊ ìªõä+P1¢éÙQ' ïü®lüÝìÄæ»Dó%žº3À•ó¤œïH]vÈÈÉO­ß%5>0 :& ðØ?Ø\«ÎXü«Ñl‹87`ø-¥Æåjåêê/¯9æ@3½œ˜n/'w[£PÑZ½c'ì.%Dû9Ž“¹ T‹{¯†5ÏG ^ '`êM¸J\ÓdìH5@´ä½­}òÿNÂ<›ow£Rõº,d«¿¨ ², †? `9¼lBúr7Õà鉗Ð~Éaø…‰fq>& úp|a³e&Ü'@Žð)eqÉÊÑ—T@ ˆ’}¢cG…->!‹"Qò5#"Œð¯@¸Dµ»ç!4ç¼þLšê3‹sªË— õí@a’ZMe-"0 !üQ=€r†B•rÐP›†òW%µàBe•w%ѯñ–rwámëÔ[-ІœéPÂO3ŒŸ™.Õ{¡×ïÆò" ø¼ÜVw5±@‹9ê´‘«©~ÃYÿæÂÏÓÇÄßÑä‰N”½m†JÀv®ŒÈÚÍK:Q”‹&h·æÿºØi4—þvC|œêZ›¼Â |L5ì«'.u<âÛ›g+v![«EÁ‚W™"- CJê@´Ë¥¤~?T;F3 ÁÚëÖÚ[9_Ñ"ŸîËòLe Ê‹:Õ¡€ôŠNÝ_äŠn$†åÀÜÉ,-Ø ¾m:!dÿ¤Ž§…KÁÖ¿Þ0òy»‘‘?¼aêßËvÝ««¸5&jM…›•3 È3Ëð­—hžçäLþb‰\)ãaç-é÷°ðÀ›ê>9ÓW%E¶>„É¡Ô+Œè(¼hÍÆ­o·ˆw"°‰øƒŒ»FLñwî hxl‹´§²lÔ ‹†‘JÐæëíÑ­&ßr×6ýÍ@œ<î  »ü(øT[&.o–·ñØÑGTú€ç'«ú‹#äÝ05å‹&²W± ·’¢@,ñ4Ì -YýG*½+bb*°!¼Ýóβ4®YD@ŠCðÃéã"‚<=Ta¢¨vFýŸϾ@œÞnN&ÐòxÞo’5ð…¼a…dÆ>`:ól§D—ù•ŽÖ=9¾(©t4í3Î_PLÖ#ÄNÇicrj? ]hø]UM#"ý#·À–ú({r>’O9þ_ðzö™ñã,gÓ²]ɱ:¹×½¥pTž|\$SM^2bâ Ðìs2·…„·È*k»bƒôþ¨j»º¥Á˜ˆ;'8›nÝ*½LÍÄ çY«ä›¬â™µOr¶Ý<ÄgO/ͬq³Ü" ¬°i9ªn ô;¹—þŠETÌç½çsíß2r+ŠøD°>l{®@ß;iH…:#)XÈ–Û‡h¸ë™hs†«'ý™Sê(‚Rz÷®[‡à¢xJØN‡¤ÅQˆSD' ‡½°ÈÓ‹qv ZñB€”çÆd1VÛÉ5 yÎRº—¥E½\!` f ±ôãý¤E<=òÙðAú“ºO€&}ç\WmÒÜŒpWÝ`ýìݧx]!湿½:ì…Êm¡z’>™\¯àit.NþîèZ¥Ý˜ë]ýûܳ¦‡ tò23Bæˆ&AøP‰mmð?QèV^—0!G¬©}ß§š8ÊÛ†–ÕÆ³Â•™Ç^›É*æx6›èâõ‚ ·ÜÌŠe$x1 ®YŒØñÖÈýšsnS±ôt±?  øÍi¼Aï–ë¿>[×ù×2s·b7UÄÖæ>%»ÛÌ·ýX¤cÁo¦ÏÌ&¸?×Ygþ²€€9Þ¬ð[jI9*|£ñvsÎu[ÌÂO!ÀŽ9'âC³–Ø(¥Cä=› «RkL1š‚ÈõcÅXYÙq&íÓ%SñœÇ‡[𥋺5xî~"M$Óo £Ä,¯Œµ¢2-ìn̈½Cù/±ùÅÕ+±'éC·GèŽÌ‰H¦äXûJz§·ôÂAu £OäsÐ3qšâ#jf:VC£ýÔðG&mÄ‘!vÀÜŽÀïªýè†[mí[ý¾ß¥ç¯OÏ k3n„TóN±§U,B[#ïÝI"-Ž »­r;Y2áç!±qå¶VÓ¢Gó8†‰½^2ÅM—² Ó<¨éu,‚ t¿ý…np4˜ÊØ8+£À-­mFctþ: $jí/ûÔ2•x¤õ*üÞ<Ÿ«þ(½$ôÃG™M T”aw˜‚ŠOì»ry°ïìŶì§M¨†DùÉ z”¦íUG³TòËjx‡O~¦­Lø§U ÙP[„öÇ:î˜ÃB®Ä=Ʀ‹¼;]Ï”à¤wö[˜câØ›Èdh>çÖ:›ñ"»ô-I7wô¨>ZÁ€ðYà^&K£«»òKß{K/§ôB™"´¸tjÐåXwzÍÅ3œJ=½Jƒš Á]QÏckLÔÚFìˆÍ«Çê'ò0’½€oçtOE§H)¹è=É(eª]½ÍPBnˆøÛJJ1愃§jH ÙàÂY󺧽@qóMQ@ÔÓœê4ÿñF©Yü¹jû:à"î ®q×mj1êQ„È'àÙ WétÈBZ–†oÔÀ€"××°ÅÂý"nÍÑFe%`èŸã§¥ ØP z6}4T¡\íÛ9iÖ~FFpžD„ü·ÌuKV€'ÍèüW¡qè°;cqˆÇ’3usÀü„ˆcˆ™¦Ç»&ƒß‘Ej·5"„Õn’ª‚Ľk»Ôm> ©‹Ua(Yñ/U­T*.= êjXxœ¯«û”W‘˜Ñg ³¼×ÞÇÀ0±’7³%8ÑNûZŒ‚½ïä8\öC}>YÏ8·½i{±ÜàÓÀY©)mnUpB‚“΢¤¸Uê9×y_Xð¯@_Ъlòà"Az˜ž`…<GÜ„¬ÎCªüÿ,-.0QÓAXd&êç¶±kº%Hâ^ü\ - ã€U1øÒ‚ì dCÝÚ5êúÅ~ÅbäüvÐ𡺉{<4\…x[ù·` œáÞñTU¢¶4¡æ58éìåÁ§Z‘fÉD«7â§|ƒÈ=2W_“ßV3.mˆ¹Ì^ò¹åQµz^ÖF¨–Ÿ±‹rìª&mxX±3z5K¼ÇÒù¸ûWrkSd…oÝ‚^ÿïÿ–õ¡Pì¸@‚/1’jjkŽ=‹†ícPcæÀ“¡$ÕTäär›õD˜%fPÃÑií9…¶n¥ ~ùj ŠÃ®'ÛÃ%X„ßëÄ‹Ùý&p~¦âŒÖèÎXÚë:Ù˜,›Ö¾ô3¥™³n*ŸX™%AúðLL HC–ÈIêÝ@¾¾?öïéîÙ3¾æˆ€áŽk"@þÖD´/RWŸXžfHAÇMŠoŒ›\ìÅXv–Ò ­ÒiÚþ4*ÒS­6šì`¬êçZ€o–6…+ ÊÇú(%W€¥êÃ.Š?ÖÚZó%užÚ ;1‰õeŸ†¨ÐVù¶Ã/\G4}'àÖ€Ê ¼ç}5ÍÝ(®aµÇg¥D=ú›r”wÊPû|éö¾ƒ ä iӇ慟·$CÇ”+Ð ŸÄ¤1›qS^MŸ“_uäME49ÉgCRÒ5jš­q¼µ^U—rí|Èu-úuœÈd.NW‹µ)¦J¬»4¿»@ŒÿAó”¸k–BÝc§ŽKo—h5‘U ‰ƒ“³†Æç¡DÛŒœà ;¶”mŸW¾Åó§w:`ùÐóŒä``üïÄ˹>vz²ÈÕ6bo §Ê1:Ùûœ]I„,N1›Ú]ê^ridBñm{!²¸Ù<„ojb¼¯rô5/Ö0}œ¸ñNÜÑ]Ý?ö´L¢½›'=s¸Ñ“£‰4q/‰RµÁÎI3G¶¸¿ÂP8Óí#N5p$_²/ªHRA3ª¢u1gÉN°‰“ü$R±W-Yo˜Û ‡PN¬8¶ÔÚûcèäô¢Ú•jôg$„X+æÁ|• f¥¦(Í÷B ñslé­œp˜èÞ·$´O–‡Ð¶oa`î‚ý ˆ.í(0¬›nÏÎ.<Ï“{aKElôWå×CØH4Š|{œ|eÈÓ“Î¥§“Òc=À°Kþ‘´€˜fŸŸ}EÒ«ÙÇæ[Fò"S;]NLªIÖº%.ëÕ%Öèv–ZPf¾Ïà„ì©·!pè‚3Ù…Cš33@ÉñΡð(EÓ±Yî=}—"Ã!³Úñ2¸P#…«ÆlCcq8¤ç Ÿ“®:ìAµ¬'íÈ4Bgó„Þ~#Ÿ)_Ø%Š ˜ü°}D½`! ]Σf¥—mXîóìO쯖W>‘Š}­uÍ®M4rÐc9–)HÉ RQì˜ï©ñ¢¶r0 J›l²ú°JºBãF¢>Az¸. ä÷n ³î‘žµUö ;ë«G‰dE€·têaׂ¼°LÏ,%fþ¡ÙMÉpÖ(“)—*-Ähñ"pEì>#o6|aëé‘ÝV‡âè²o| ÁÔ`‘Ôÿ ¯Aô±â^œ³¢Žpßc!M ¹Açg¯6%ý÷ƒMêtËFª†Æ€¾¾ÕºäÉø‘¡uôÖÏRS¬®0ºþónÚþŒ×f²E»y…j£nMh-‡[ YGü»jÃ϶Ñá]i…”!–ZcàI•+ñ!ëx ÌYPå úÑæ¥ÒðIÏìàPÁ"ë§Á¨sŸº'̸ëTR„üû ó”Ç&\Ñ÷·×ýJëT–‰Ìâî0\•\Šu¶[éÕÅìû™4 ®ý„NkôX)L¥Häíg1¢Î=”4{™ÏÆ"Ä+À)â oóS…¾Õ²ao­qï;zj3¡:ˆ#}4ï‡IÄŒÝW™Åx¨µ¢µ+sn{|ËvºîóR©^Å~ç½,!ØëúVî8\,54ißí_ †°Fwù<ŽîP}lPo Uð5 9âß5§ÍÐóF^…8†Ç·@× T¬g À–“¨+74t‚‰?º„÷´n¡¤ÿIŠ–ÁtKú~Ò¶P¥#dùﺣ}•óåÖî'˜¼[6§<‰/nŠÐ¾®=Q¡ßºÇDEÔ†ÀöØ}¬3V 3¹YlÙ !>Ü\"¯8o“šÒŒœÂ¡P8F«~·/忸£Â‰´¢ÒJîšRoÎ'Ìî_Öžgl‘•ì†vô½em§Òò×ê]b¶Ž°µ³ür⾦äf€·íÈÙ!Ž0iΙµ ×N\•8¥¥|CâMžà~ž­—ßc ÂÞu÷8Ê*xæ Þ`2Ö| _~èŠl‹²Ÿ¯eo’/0sÿLÎ4Û2­v$§òlK®cžcž'­M_2ù_¦-weÙÈZÅÏÞj¤üõ߻ȗËZ¼’2ÈÜ`ïö–ò c#R;Dos\‚Å;ç½üAmåP'éÄ.dq¹”Œ—5â‘ÿë77ü>!uÌ9@è*¢Î¾GYŸÉ§¿G®õm±üìîm„S’ë¾þîÓ^‡a‡;¹Süø“dzdކµH€1`xö"·Ã?›¼~':À#‚¸Ó“#ÛäH3Çr\B¶˜ªTç9¾—Èù¥$*²­ýäÒ@z¾"î9¶¥îü楩8Ø7• â’sô#{5©ßŠŽTt*µ¡2͇¡·¨*§ã±hö‚–¯¨ìÓ ¶˜bp.­l[ˆÐšÁ¬×šõŸÑVgáÝEAÿ•PÄ6rCÞøÈkãRÙp•a¤7¾'í/Éc'#Ûʼn×/'œƒhfÆ|=1- ̃”[xÌ]«°t6j3ßó¶ª÷peÑï¤põUîÑÊVmÊ •TÀhwôÝ}y½È\zÊ¥*þ›¾«æC¶C^ EqÖS0Ž&é¼@äp{ÍÔþf¶´s¨‘"À§Ø¡–ìû†™'‰±ô>Þ3a‚“éç`¢ã ,4×îÃlô¿ÇQ.±”€³Ufø»¶ãMÊ|šGc™^1—)öqf22»Iúâ=’˜çùŠ=¢À.P} ü«ööR[ÎYʺÆi‘÷¢ËÍ™%¤Î‰yÏ”‰Ç¶l’]hïØàë›ó!ÆÃ˜æêºÊŽî1BË §¥ÜŒ&ˆ Ñ>Rm¥M(dÒ¦ÓéÄ ÏâÒ4ƒÈùm2 [£7Ÿí°ã‘F*<%¬Ál‡l{Ï •vÌý$¦zF¬\þZW¤ˆ("6üÄ7¿GšCÆ›zÖíc8b)¢®"²HÌ¿Sçø¬šçºN ºÂV/2Š(}&ÍÑñ³OkY81Ÿ„ š£º áhœúøÐÆŸ¬Ï°Äûó2 Ý’y¦Äçɱ]j€£Šû.mˆ}°)1ÞÀö; ”jÙHÈOÄjù+yácGÍûÜiaÔsƒ^M)ÌDàJîSýhjyOÚáeµjÞæI\&䀫µ­G¯)²z¤Y‘®«wV¥]|Ó{ÿ[Vbï˜ë ÷î5OZn§~{†ŸŠ”åÜSr›¼ëûPk¢Ãôu'Ò±@¹-[5yX{Ê`·z¼«Üê4c‘iz¨àVºä2”DøˆÅ éûu`R¯¦hšjŽŒ0§õ]:lgg'áê‡Ó„Ÿ´Lä X«áÊ­ëæýWG‘â¨ZmAìÙíq·[×éEN­"µD`dË‘ E=’•ü§]O våâ1ú+y8³—å_,‹rR2?)E3Ž|@•DÔ3â‘ðBfÅ`Rî"'øDÊ×Ç£Du-Ææ‘Ì X³H0i\Ên±œ£\-OKkf ,5ðD%5¼~ýй+IÌš ûèn$óõûi€/, ÁCÄʾ9pÊÊÆA½ÞÆ ±n~ÿ£½û^„hß${jê}‡@(‚µ“}Åq)Ô»8|æâWcîó´È»ÞèÎOo¶©E=j42>‰Òº)æþ(<Ä`¼4XÄ«²,•y±ƒÙ"\ŒÕŒ5³ú€­]?€¤~jÇÇ7à[rˆ  ’êžaì"a™LnY-ߨæJ“£È÷Áž0ï„#P’H2K¤´ðèz—¿öµÎ3Jú§Bêlѧ—ÂU¸ìØùy.WYo›úUÒb¹}´úÅÎ]U¯iWWYŒ_3G0¹€K;‘mJ àǘEbêûx޳û=¡^“ÿCEìŸÔQˆiÿÓÝÓB­T®Œ =žiI9• Å Š>OCÅËißûzCvz)ƒ_í×-O›a}Z ~h¹ú4»Ô¦xÑì)€¸ª­žl°¿ì½¨¥w–½ •‡@Øž1 z8僘JÖ>tän*Zõ8ȼw6ˆ¡YЧ½Šq°ž6ŒÞ¿ïpÅ’ÉËlMQ5@â%ŸÀ—s´.\iÁIBR½°XxF)«’{<òßAbp¥åÛ]ô$ÄŸûFâGØ W¬ù”z"íœÁ¾—N†| jC$7Âç©T ¨¦"À0t3Œ‹³3\ßÙž‚ L­˜ÛÌûaá>BÜËöÿn0kí+ãcb3:ĄÜ!lLþ¶JŸã®œÏâûÊŽÓ"ü†ŸûB*0ù¶‰Îmò¼õ‘M7|Àg@Âaµ.xSAá!˜Šl4’{WEƒ¶ca ‘õÛéPÆMý0|ð¢òZˆ;€rˆ›VP `WXLëùŒñ™²·øSr·§ #C™{ªËù匮HŽœÑÚ=uw·’Ʋ‘fæ¬8rEɦôòøž€@´¸»t ªbبD(Ó߆§nUO??ç#Y™“ÔB„‹™Öàå\!¾‡ôvI^ãÃËø$,ŸZó²JØŠD‚=¿ˬ§!œ~dâNÕ18žv5Š:UKÓÂ)Šªõ-˜ÔØX¥<¹¢.,(OÔ‹{ªºÔigôZ¢Ny¯]$ÌMûmþÛ·»2¸q ¸Œ˜ö)o‚Å(ôÜùÖ‚€1ýÚÀ†Q°âTŠñ(fè,É ÊZ+øåˤN·¡­,‰…jûWÈ%t’³^5€ÖÙ›³å΂ËëŸÇ&n`¹[©‡1æ,Èòç:_Âc3Ù,Ñ7äâ”ÀYÉ¡ÎkHóÒ¼µ¬ái°ƒ$4Nÿ˜õEF»[#„F“Y‹ur+þd’nÔI/•¼~g·ŠD`0¢_BG.E׉ƒf×],€'&CpzÛ½"±QÂzð dYBt\î×G}Kýˆ‚LÍmv/raGq y‡9FeÔB’ù€ÛÝämß|µ»—¸@ÍË3ê &qÍ@º'~Þ~År «l@[þ—RWÄ3OÿÀ’ÄÆÕçØ¨ç¶¨¶Õ 3„ïz?¸okì_¾ãȧƒU ÕL d¨Ø§Á“mxèþ[q©™w…ˆPTÚÁ[Öc}RCc7_€M÷ÂN]ØV¾¨Œúª½ÇkKUQÆMNLNQUG ª,&º¢«]-`Þ'Å ¡öQɸoÙƒ¹(9•ŸMñn ­°±qœ×ÞÕ:­=—οYÄ|½Éè2À`Fÿê‘¥Ÿ¾þ\žª‚í×à&¬(l¦åîƒ{š,¢t,”’`2ä“ÛëfBöI–‰[Kô@ÄÀ+çyCQ Vú…Á­Ô ›î×ïswV]¾ž¯2Ùù`m ¸û³F2Ñv†ìMóŠQñkžN} ¯¯hz ý£to5S(á%HǪäLq½¹%\ÿ¥€8k‰–ѵÁö̸ß}—-iܤ“æ7`]˾2 Âù†^'o.+0áxtöÖ#a>aâÃÕÛñýÿ}§FÃâü Æ?—«g ¨½íŸ+¼`y½Âj ¢gê™’K|Ì1-›P€”\þ×ÉGO cSZ´ƒDš*³¬ÏºŠS¿Qó(;p'šJW%ÛTÔ½øL>v[wÌH§geliáç…m¿ÁÈóÏ!Mïv™Îî‚{1´$—ÒS“Rôî&Ù¨›òA¢SÒ‹ÝŽy…ȯ†£l,IðÌEÖúmÂnŽÑÅçg Lÿ&VZ‘£`.³j•ôexwùïïÝÅŽ~õ1LöÆnlLñeÏ—Jjξ+,nU”"bÏPkïNÐ?õ¼hgz|ßyHçGس[[ëþ,ú½G­]8 b¸ Øó¾SÉ~OEcæ¶ç¬(Å‹ˆrŽQ âí=š!â1¼^#:¤ëÉ‘µ{?ªV²«ôà —*;W™übð¤ë*,æCì¾4Êë¶õ<›ñ›ïU f¦¾ŒS>½eß9&9 §…..gFJç—é7>\+KqÄfh‡ìÙ“nPƒFêjç¾|²Ðˆ[pëÝ9QŽ %À—hÅË7Úñ±Éq¬ØÕTª¿Â~ç¨.2îÙ¥åj…f~mýÆgl_rž8WÔÍ—;À½ëÿäŽk lâ\$¬îùr/ÒŠnx{Nh¸Ã…\†ÊÐG£^Ôx¿6AŠŠã•l¯mÐ3>7•„GHƒ/êué´ÍÒàRNmûqë_âãïi ò~Èà P<%qÿ5-¯×<•í«Üp}ÍR×z6îlî +4ÝTÛ`ÀÆößI_Ø5k"If‹òQqÑ$é<»¾ÝŒÑ«’ ÜZÒ[Žsò£7ǬÙJ€Ì}Fª€k©,ÂŒx-’ÕßQq7Î^ƒ1&j •ÈÙ–> $çN6Îÿ<Ö èð›sçm˜Rƒ•ƒDj\))RG-Ò¯îx±àB:±"ßÀxv;šÍ²ýwPŒ›åQ !I/!\#iª/ÞV@ßk„¾X”ËÒ•/ŠmD?ýçG„3ÁÌ®êZI8¦}À½í̿قzéèîMZ‹@w›|«XN‡¶r<.3³iE­Ô{ÝT fÝ/ FòkŠ®Œf¯Jî°žôN²|ʃ‡\÷ÉQÇ8Öƒ}"Õ~e<ÛÅØŽÍ‚m¦¶éSjÁÆkÕåÔê°‡ M¶ìÂDï{×*“êxÛ»,÷zñþ@Mà$u[¯“·{õÖ¥œ“)éíà4Ç‘‘ŽF›´}:c™ýáúTÓï@ûWd¼)^|<Ý‚„¥lH^¾afå5„IÓ„–£v`¾ µK¬š{,£ù‹ˆw3Êÿp9¢ÓS+šÇi¢ÚOh#ìû£‘f¥W¦ærü9Åõß·P‹Öÿ²€~]Äjœ9¹28·®¨fÜ*·Ÿ :Mç‚°¤ @¬Äð‹i“ÛÑ¢EßñÚÖ’´¯ÈéÄ»ªPd¶œçt”˜lE€ƒ€ ÇÉS(Ðpdž¿üƒB¯ö²z²çj”莚 ÓÁ_u A‰,lÞ·Áh…2ÆSAâZ@­²¯ëé.N&”Ü•ÄÉþSv1°à4Î4r”ÚŒPçC˜ˆ‡%>á(ˆ+‰¤ÝÝwÛ¥ Yòî–;›í3f«Û3ÐYÒk¿¼¥=g”‘Q~Ò±²¿kìàùŠsOØÈûµ'·ï)ð)Lf™X´òÂÆ <¡]tJÂÈléìć½7Ô¨Œµ?Ñì{)Bx5„ÑVüø,#~Ý99-wC̪\mw„´‘v‚ S¾ò8×ò&Qø“Ts…BÞoioÔY E‹wà 0í¨ôPâÂuZI%SÈIn¹U(ÎÔ9•*go·/0†3àú§·d&3/ÿ'~geœŸ“ñ8 Á±…[õªP½+m)í9üC–­ßîÇ<…²`L@ZcK‚èÈ:QxÔ¦ï*׫Ri‹.xæ.¶F‡1ž¸äDy!.~E†Ê,Ð/ø,“¨ËP`À1êüšTFOÎ1¶n9“¸jMÃJc þú‡©€øÇ.ffÇ““Ÿ¨Åƒ21Ê‚Ú`KšGØ\&j¶D¯[ÕÛËJv Z¼Ÿgx”ðxçæ”lVÂVÕ7ó4# $ÿ´ÆZÈ)xݤÃ&b'0°ø}¤Y:DIÆàDUôD\g€lêÿ{‰¼a‹Œt¾í ÿmžöe‹üi0 ˆ¯udm'Åh9Úæl¾ ‚áïFËÿQJCֻ܀ø E%7;`,*È`£‚ÒªÍÕ¤…_åµìñê=®â"ýÑ©ª<Ö–Cè¿ú‚ #Þ}2pðzš …‰› •ÖF9¿÷\BNiyëYê6XªpØØÏød£äÄÛ{_˜|ޭБNxaõ')ò ±"·Ž¬é½ º é-|³—žXÚ‹ýg¤l¸!c¼rÒàßW0âÚjzÐL ÝíN®ª<‚ž†qÛ ¬²EQ úÛ"µÿ¯³ÿK="ÂÌéŠÒVŒ@ì%༎G皀¨àj)—éßszÎ OÆ8ûÀØîÝ ñ ïómrŽçµY踆•^1À,Ê2že€Üý9/´œQ„lF|ЄÄêC?æ¶{à"íæ’Fx0ß1¥è–Û.ñî›n±!ý%IQÄ#lõ¼Ö½#î+Ô?o%Y?©|ÊpY‡4/¼ûÂXÚú¶V–"p§…HÚær«YBâNw76¬ßP&§*G>Íb [¨¬ºGP‰¢6#þæ8(iÐ?äûÚS U†+•¸²Û©!«Ô{¬‹†ùKŸˆ³¿h™cHd E ˆ—†k‡Oíñ¸ÔÂ*4 ¸ßæž [nî?ËA–qÜ”F#£õ#éÞ7ݾß™ú3á„ÖMÎyÞH"j«åÌ÷l_zÈ€ßW´5YÐØu/>–û tèR;½}”^Î\‡ÛÅÜ$¶¹>V9¤_°W9Å”(Å"…`°?ØÞ÷Y/XRãÓq‘ iWß>i+|å!57¦ョ¥µt[Y&d•EÁ¶"ßï šíùÊw{n&H…‘Dm³^Ý„ò¡j…´`XØŽÌe™A^#PðÈ+ÁoíÏ•aþ‚"â׺Ð:ÛœžE˱Œ/ ôõ”/TÎîÍ&ç¼ÿ^û@Pd7DD&¦zÑ%n½+_ý’MïKU¿ µøŒ›$“N#®-ëùÕ>QFd–Üô½¬n¯0°Ü£WSarûÀ}¬Áõ½]²b„MÌ(´º€]¤ÏLÿmîhjJô@ '(öû¨m‡ÏŒÇ8ß–ˆ·zð ¥þüœ¢’ÓÙŒ÷È%ú¢ Ò|®ûpŠ òðp×—ÒÐ5z¶"h{:ȘU-ž|_o’©2äÕØ¢pÌ[<(¦eËüs7Ó S Nÿ wèjolºø_:ôYr¥Lµcr X…sàÿöiWÖ?˜jzŸ9×tvŒ<…ÁÏ š‰H°K5¢=n1„/ˆžh£½–ÀÔj¹»zIU@Ž¥‚æÄžo´í¥¢‹”TEøq´v‰½w- Ķ, óÌéAð ûÐ~O¤â‘«a¡ÊNT]¬Õ¦ƒà>Ú |…„X™du.tÕÐÍü_˜êö’áÍ¥…é×ðº±ÛŒ­ôHu8ÙéäŽÏNÂç‰]/µ\½4{X²2ÕÌ”Ò æÞ@„ø½D5pK_Ô½I#~|žõRŸ´pÖûaMÜãLO×ùs±áæLx—Ðä%¹ÚÛØð«}¸åS,Ôô£yæxh Wà IÀ…€©Q•4{¨Ùªðd5?ò'Ù[2”÷+-‡˜(Z¤5ƒoW*€ o.$2$£4bß^(Šj-‚©:"ª¶ à«Ì“| Û#ŠÔÙö q?\2Í\Ñî‚À2ÃÖsEê/«K™ò¹Vé å~VR0 W<Ô°ýwƒ5ÃHzÛT“ò@Qo³¿ÇB䃄DJæÕSÉ„•êŠ! ƒçˆúÀfCÝnÛVî‰|P>#g Äùü÷_(ÚbX–A£…¨°&eC·~Ÿ¬;<+t°†ÂB²iŸÁz4ïÆ=J6ke[x&4[òZ '«h=Æwш*¿Öž›?›ü6-ÅT•qor9Z¶¢)âAÇ÷S0éçiÇÙ +sävÆBl]UœQ$jfˆÆ›XÀ ŸFW[ézpH:B<+D•ÞaætN[¼Í³Ìå›ý¤¯îyòd8eMo¶(.£æ>Y*|^ÿ+Ÿ5åS`âlsVû—kˆU&ŠÛ‚àM"Öø¡S·Þ¬@CÓAŒ²!Üaìü™Ëþ»X”H$T¹ÝŽ-ˆ»ßÕŸ'µz±86c^vVû íæÆÏ°û0)H&J$·Ò$ñ|uõQj("¢D“ÊáÎάÓ}N<0Éú4Çy®Ç›zŸû¦†FÁ\tœDþ)þ‰Rìtƒ”cX'àíB,¼qQ_Õ?ë kVlN˜ßóŒR r×kxÌLàœx‘™lû34ô~š/¤•`Šñw`² \ÙÍ ¿ÀKõ¥¬ÆA_pµ4 ZÌ p¯UEáIкªÓ¨eŠ÷p/ýø¤¹ä]LBq,Âî®\yI¡‡Æ»„Ú_ÈT'}Ødë Vªu ΈëŸÖëZ \côýf„|3f@– Ç0þìwV2äeøþ½ Ða#­çÖõJN»?¶©ÎñÌÚw˜ðÝ(]áG…~/«‡:Tb×ÖC¥¶©~PÕ€‘~¸½Ø-çTùŸiUâîÂ&_¬ÿ®&úJJý»Ç;Õlóãl‚U÷¨˜÷ÿþQ0¡ŽY ·2±²êÓ y tñ”BÎ<­ ä;ß(W_9 …Uu*sË#×O¹µm6>.wæÔë:Ye†[ UÑ0«ÈÖ$w¬¼õF5qÑ=þ ôðl8}ÙÀyˆ–ÃÛBêr”œü±Ÿ÷&[JXUG*¿î2ö¼-7^‰ÍéË?Z/§Y–ù}ÙÉ~å/d&[úÌõÆJyVë:¢TŽðK¡cŒëޱï²Ëͳ ר¾™Né‹÷P‰m‰¿§®éϳf{¯Ú1S®q.‹º$ýhx×vÂ…Xn×­³˜×~"H òïÑú…Å y d-Ö²fxFí3í†`òdH]&i¥fT‰‘óI@-¸OôH7:©X9KôLO`T•ñ±«½ÐçC8OPÒÛÍŽÀUcägNä™ÄuþsÜþ ¶=3Íg§}ëCÎQ8-ü»„´-»Ô~Jãæo‚ÿËó=pRŽ“ÚêÚê2¢ÃòJxè؃O«¥¼oà6DNÜTq™ã7V"ƒ6ÖÈ‚€ÿÑ>Ï1ì~Ð}F\ º¹k|ÃûS¡ ³¹>Çâ_^Le£ÕXéW!`® °<ÍJi·qîf¿35b¹Q~à55}« Äæûá‡Bv7"àž.pàc*ÖtBZ}0B£A‹¼HÙIXÆŸ+2j±|ïÂ(Z‚þ%’(ÚÀú §í}}÷:ô | 6½îQ{‹Áܰ‰PÕ˜8yóB•¡„&˜„ÑJ—ùõ:¯@óqÚO½Ë € ‘$Uò$N{U°š·&þ‰“l¸I¯ðÔþ¨¶&4œ¼—Ñ·¾½¼”\¶\×: ºÅ|“: c¯±Jj—vG†s3®Èlìö£µ1ä7ˆ‘  ÜÑ0yâ̵¡þîÛ㬨Ä!0LA×0Hé.ëYЬØÊñ÷ícøü춬—ì´~ÅMËTìÓ_q—2ÎÜØ&‚Iê5°(;•ˆÐÖg„•²íÏím*q8; –áWÖºPåî^Á"RºîdüÆüœ’€{Ê>(œy]‡`=Ò£°[­Ùå<òÚNò¡|RTò¦WA”ÉÉöœ»_ÿm –6÷êÿÏ Í_o‰É0†z–J/µ£³V=mùIàuâx‰)¦˜Š“e¥ó›É~ÚUö"¯_yGg#â½}ؾVи>•ÊÔ¢ÒI²Í´kM½µ¡ï¢¤£”ù¼¢Ótղớ-\ t ™ ù´iÝÓ—¬â¢«|æ!çûOë5ˆ©sý¢±Tú‘H `¾¡%EÙ3ežë甃$1ïÖ´ý›´Þn#pÓ“¾…³zƒ–Û·³Y1”师ªú@«àØîÑ$רGâçïB¢”œÏƒ."•Ùη&s›·Ø+›”eŸØe]eœ\e\æP›h¦ˆ,iÕHáÆª’Ð`ƒÌ ׸ܵ‰åX‘ëLýVúLáÐòÆÀž`êáR¶N!‡SòH„¹ª–ò/­(¼Í Xýé'aAÎg¬€ORšx` L—Lsc7añæÛY?hÕÄ qÒTbZ~Bý&«‰æ7@5ŽgÄð¹³!LJB¢ìF‚çܧ*×Guþä¤d µF!ÇË]ÿMÌéoª\X½ž¨÷ô=–Š¿¯;‰ÐZH[8•wìcki"Ñå{u¹#+þšGÖú>bM%Ýò°k8¸ »Ø³¿ºrSàxFYb®8(çU\¹W‰lTª©±‰‘ì‰êóünÎ2K?g ˆñÎõÀ%ÚvLH ‡iÒ4êBÛuÙá¡¡b*OðCˆ1Ôš]wÏZù¬ S-ÖqKFËäc2 uÄÝš5„ßÜ4p;XÛ½í‡áý0K÷íâ—å@…rºãGTƒ™æýß+¸Že,ÍÛSBàuBªI—*véÐ劔ç@ÖãG:°N'ò§_ÝAMœ']Y’ÏÝÀMnX(9?锂řÝ+ —ó!h;ǯÚXh$;{/‰žïb. ]™ò9²-0(䡤É;žåKœ}ÞÃÈÙ•øçààßN^àfèpqÒgÈ÷܉É;OgÛ‚r||™ïkà‚æDQÄÌŠ¿Ð™Û0ê]ê!sSÂTã8Ò­š–}pï·(ÄÑ=/aëÎ(­}mÍ#„2Ž™Û‚¹¿ØF0ïm¦NE DÀ+4òæË¸Dåé'0ɃÁ¸†%³$„!]uà;ÍVÇeŸ(Ml’¯½êÕi+ŒY%Ü-zsÀ\mFîàŽrÊÂÜ3¨µóç÷ª »Ø$ÁL âÏO±Ü¼o¼v‘2X}}€¦ê¢Æsa¾%U_|ÍÜ Q¸´ÒÑ¡#A[¼Xlíh%Íþ“±°ôÙÕb‹¡¨.Çëè 2×Ù3h?3èÂÓí·Ù¡>†ShcÄ+ZÇñÄfÒŒuxm¡Åû 6ôÃø!!…v2Œ:µ+Çþ·`Gé~SÀΛ2õ¶¤Ê³çJ%ñh4Zp/þŸ!!AþfˆüùÃC:óP,½ËÇcâc~>~ø›H°íÄšb–GÝ_éæÜáÖsK±4¸z6ÿò‡ˆ†>£ÿŒŽzP%ÅÛà©4[Ù þ'ŽDMß]¼†ÜÞ6·RSJTHƒ p5Ñ å¸¦F•öÒŠ-”ŒI ý~#C]×—Ü÷Ö^ñ܉ʦð>¥$î¯÷»ñb'5¡˜÷ ÜÀ8%ú6Õ ØK>Ã;·(! ¡YBoZç.[FW˜m3Lí±¯Âl[w(jUóTY33Å%,CU·—e–f¤ œ‹­ 7ár=…ý~ ÅíreûYÓÅq«Å)_œµ¶î3{\ ÀCýÕšÅí?×s£xd€ Å®"ƒ3НµàëÜÿ6IïšQÚ•<7LÕ²õóá$Ïóº"ù™CZÅ•o#ÄYxš8X: Ùž|¨þ ŽÚ‘%NŒ®€£~wã·®*:²t%8ØéF 'B8dVÚi¹Öf]„ÛÍ 2wÿf÷©¼¸¢µé­‚ÿç¿£ZaÙ!rÏI©Ã¢üÒhl™È¹ë¿SnÚ¤¢Ð"m¢+¤Ì‘4HHütÍ7É48ƒÙ6F[¢('õtuàT­Öj6Ê·¼,Ÿä˜ r*Átˆ^ã#"²ôl"u²6þ!½–`Ìl^uƒ´»w¶Xð lú¿'èu7ûó+·ò1X6.RvPŒ)—hŠfz±P'ª|%•sî;uvf† JÉ@ÎÒ°ŽAfŽe@OJ%%‘'ˆ@;ÁG¡us®|ºÁBÅÅZÄz–rFö½«1²-Ï<Þ2Ë‹–5‹f))`ˆùϲž ÊB‘8›à‹‘À×Y"Ͳ±{yM~Óï g9ZV¤Iæ'”ß'¯ð_Û†Äj,£{¶CþDËAN%ŒŸYýÔ „ [Fù·Z®Äše‘{Éð6?ÿ×{~ù³À6îgãnæ~BýùÑowŒÂk5@Œi†ò%ßç!Z~»p{cëžP±9“Âb݉§ ‰›AçT~½™•p´¥i/§BgÑ•Ò ÃB‚6äz%È¥{D:ÞsˆW˶Ci3eÊŸ 019|Ø}‚'¬ä½;jDÏhØhqØ{§a3HNSh1*c¥fõí1Ä\êý>ÂÓ5RwyIØ–yóy¨ˆ¤ûöê×Í,`~Jó†l+]Í\’-ïÕ‚÷uTÆñÇkœÍÅFp% ‘V mú^ÉotÅ;qc¡‡uÙÖÊ7Îå!@"4|—IZˆ)­vªæÚ=~µB¤™7ÐZ?¥k†ç{P¿“íŽdŽÇ¢‰×½ âk#ÚG¬÷bB'®¬E8î'BY-/„è•÷³ÇêNÈÿùÞ ]ó ${ËIÚé0RÁÓF <‚³…ÁQPØß´œþ§d;™RÈ‚ïoáL¸ŒùtD’PŸÆYžJØu5¸4"gÄ}n•ý‚K`Y –‰NåeÔD³ºgŸG…œZ,OrZøÃ3˜½—‰i6rU­%›1Mð’J”ûšËhûñn~“BÖ} -Ì" UMå,–mgUÁSÝXé4â}À7?­ÛÁ”È*/*çQ8 ôéú¼X²©í”§Ð%‡ÚÞøáp¯Zä_÷€ëì[øžÿ©VÛElHUo'U]åÍ]¼ÛÉ\îB6Ë|_ª+þ™5NxåCÙ*W´¯Œ€ý™EÀÅ{œ3̪i9r"lãXôa6ÓF‹B*»¨7wØìDw©-R,£¦è›×•O. ÏóœT–‰aÿ7"ÂmÆQ”¢ñÍ ÿÍ6úó†QÍŒý³O–? šÞì­>$ ÎÎ –îì GÙ-Á&‘3Æ×Œ l©w [hÒCŠa´¡jb¾›,.|-ãO²gS !Ϩ¬xK¨·f)¾Woýš>éW ic9æ 0±wT]0=Söø0OoA-Pö…cjR­cØÍÑÙoа4×!¼³;µ“ã4œ$—ÌjWèb‘6[ט/‘òtr²Î­¿v4–¨Dü %«xM´&žGS‘~ÖP·ÌìñšIǼ;Uù ïËM•ÄGH¾ª½"‰»œTñä&Xk5I [G²*€>æõn7^ÕôˆÂÝTîÁ` Ùy•1ÀK¶Ûî0¼Ê°F¶é±ÜQܽ'+aÔ(ÂQ;ÛƒÙbó~‘FN©;eÕ.¬ µ™,~JhØ@_ÔEÿuE+/læ'/* /AåAåÌ4!䪫 Ò>Ù®€0©x´½7{£J³3@£D÷°_™>’³“Ö<ÓF¶ÝæÚ4Ì à“€—‚1Úüt+éX†x!’êǼ_ BoÓÿeÁfM¦ $.Å¿`•bWPÃ÷›U²ð òØm«¿Ü$¥%¹¶=H蒞NjiBœú‹’-!xßé&n1öýÐQᦂ5+ʸ¯æ¤¦o¼×tD œã²ã½kË éKìcÈô¡nž0þíì«ó=…5\rpLç*íuÌ£¼ÂÃ8$n@iÕ'¦Ûñ¹³13Þ_aq ô¾6c儲í8»99™4ý™¢±&ì¤v>˜Zç^l–¨/…øƒÊ/z9¼¿[kw±Y’ª€×ÏÜe§ â-VíqáËM7k«šÝ(n<=Ö '²jµU5$³Á—ýèzKiòxíK¥3+ÿ×rVúW«ÁAi‡<ƒZ̺s7목ì0ÎŒ'ú¥QfÛÑ©n–%5ôVî3l~»ú @Ç-FJ3’‰¾qî¤B¦ÈÀ0Õ%  üÙÚé¾8¡ÐÑQÓÆXœ|ƒ ‰q ¹Éë õ¢ÄÀ±äã+0Á‰r=8I_®Ýêp—–M6ðzfÊ”¤=Øõ‡@oê#®ÐH ƒ1°¯ùõQñ?"÷1ëÿ•·†ÜSŒhòžGµh£YU<±€‹Ñv˜Y±Wà ÒWÕ*ìHÎûò¾½"äbŸ*&Ë ô¾IÌŽ’>8UŒÚf^nóX쮥`º3JÎs¹L´Ô&W€ˆãÃ@M,ûžFÿ‡îNt¢ÚõTå¯SãPp¹Š¸¼gtÿRf°Ú%fœ“Ütn¨?â]ÕeÞpÜHŽ$Œµýnÿ1ñÏžšoñ3ªaUÊt N‚¸>ºx¨ŽQím9ÔJ‘–4ÏFšLRز^9o~úB|H÷Ìæ-Þ c·Ýo°Ø÷~ˆëÄ7C°Ÿqã020ôãÚ#Ñ0vï`„6¥£_Ü)YÑŒ…ç"Z¿,‚u‰=Ì{Û¾Hºöpð”èS!Ú6ѹ‹y.ÇSöí&™™bÃ38íÑ0hÌ\‹èvàÎx²·›LËÈ&ÑÊ…\¸j--¶Î]5~‚MÅ®“•ŽKa¾7#§nƒ¥´mþbu~ޤœh?§¥ ãH$ëªÜ“ÓÉÕ7è»ñ·‘šŠ]YuY]žo¬‰<Í•g­ >>S‰ǧ–Ž|•q|ÿ\Ë+ÑQ4kÿ»Q.¦²›¢Ö+£B1¦è¿-¡Âxç}÷ ‡«çr³„”ÂÈû«³ ea¬ }2XkLØ0/[¿ØðßÜJ[àÿû‹ï8¬Fy*ºùSnÈ‚[­; ` ìá£=Ûá’B߯K>^­ãCë¢+!bgÂò—äôäL´ˆy Cß;m˜†äœÅÐ1€¢¾aJ®Ð»Éã„Ôhä@sûZÏg_㉼&ÐmN*pªéaTð•'ûx´]Ý’ÆÎë/¾0“L5×±í-I…óB½îfe}œÃ\éÝq‰–)T~¾Øàº#j±v„SJ>G§YVDÕºŸRÃß–k&­Æ‹ÄO0ŠÙëçQ—뫚^rµ£¨ÍFA3"©cùšŠ÷îf¾)|€~ÐÑÆmï—[#£|5=vg* mNˆ+>ÝÈCn§ y8¹Eìbî¶È$™ $$Ÿ¸é‰C NNw þüZ·™¬nç¦ò€’>nà"lp -©"¾î!fm€‚\åÏ%Ú;Я¬ªÊ {°Ž¸Ig¢–« ú—‚®Î€ŠrV`†Í¨ÃZÏ«× ÞÖ¨Ãñ"®deš4DžÍjY‰oØX³;÷›»iÅôxkó?cëGÏÓìì¿i©¯^ë€zJ&žšª®Î¨¨#dàlžÖól'ôXÓFäÏp¸ŒvÄcQ7æ U¨˜¨ §VŸ;V±éϤ·Ûÿý8ä”'!à~÷›˜r&§eENwkc„u”ªãD¿\içÞÃ.T|:‰ò¾ZÎ9›Z]ÖÊç|¯¬¥ˆ0jîÁ5jb«RÆ5`ÆO¯è•@·7QHáþrÐB "L}?½gAÐ:d—¿3¼Ò,¶ GÐèñ¥^?‡%\یӹ‘ÕÜï»±êk~¯gÏ?dŸ‹NL@qÜD]£aAœ©”ô݇®õ¦I©›o¦Ö Ûür°«„™ Ös…nu¶ûÆC¥ÌÆ»¯3æ0Éô›Üƒ‹÷ £@Í„·ŒR¤,EÒ-¯ûC­•É͸12¡ö¹i^…©w®E•"#„´¨.R¯hE¬ýnöW¥—ôð^’ó@²IƒaWŸ—­‡×wº(˜ðëSÕĵג3œú|"nèØ W> i¬MÓ+1ìc‡¦€%-¥%Ξþò¤î3q7}å`ó½Þß½R @úïz“1i¨’ü·wUb™=©¬Ù–ÉxjN«…:¬¾:²£H}³ÂÝÐì7¸Ð˜M5Y¦žPh‚2y ^•d>ý‹¥8 àçäS7³‘²Ê6#ó¸›Þ­îˆl/ÆS0••Æ—ñ9ÜlýðiîÌS]ÜÍ®M¬”À¦«íÂJÑaôñ¥…ß ‘™¯„ì¢HBêp$;ZI11þ¼gKzO·ÖJ-R¡Á_„ñ´þ>t«˜Å[sW›3Än‡‰´ªáüÒJïr±ϳú’ÄSŽD³ §>õ׿jÚÔ8ïl­Ü¥ýðà„—è6zÓ ´âãXDkËPø¶×.Tî ?õhW©¾P‘ßÅ©îF=ÒMNx¦ß¬J“ >d—¥ØzQÖçÃöcíq¸›h¬µë .à?{W–^2û;¹pGÌ{³<3­T k6V×ýAšƒ–­Vª8$‹þ…¼©›=ïwV'ÌŠËÃmK-òaZ"¿*tSúX:Ás"Ìõñk#²~¨+@ðÇú"þA0Äv/3ŸUÚNØúr8¿ÚŽŸ=’q³ñßI·&xPô#v%œÅ>3ÚéúŒåVŒsrn_eÓ›û<]®‘è›~GÒă~Zó|BQ 0ï"!÷Ó ÔÇ£>£I,RZúîã~G ^ù~ômÆŸ¤ÿâwià¦ìŠwc#—ØÑø½åû2t /êÎì} ⫞j ‰|õ†yþs—§ ³ˆyƒl›3÷Oç2všV”ªzÚí wD0¸Æ>b ±tìòîЬ½¨k÷< ¿Â}±.ïÒº¤nɑи"`I£p^Ô°7Ž e)*{™YÄ¡¡íK*–GGõÿì/‹$ýü¯/+ B@5;ù~Aš½nxy´_{qm-ÛQ—L aÿÂÚ­WSž¢U3øÎ¸ üå>¾B×Å®Ðë­Œpô›é›4¾Ù6êè™”öÆî:aøŠ%·z©¾Ìi^Š(d÷ oTÓ‘q F…j;ç.Ë׳½—Ê áî¸çùÂx½ì½R·ó”_šêIioÚÞ!·û|CH0AX€‰p²TK\F \šK[ºJ'r ™È3èc#4 ,¨"æ\Bt…›^l”“Í{±([—üRhz|9Ò¿¦¼¯—¥ ‰£MO¤•6QÜîꦼ§÷Š£°êI‰’ÚF6¶²§èÌ´™X'[hü„5<÷»qµ); a:¦»S¦ Û6^ï6¨³+×fŒ=#<øÎ&$9%»EF©W9@ZÏ«|E±ætzO µd?Ú®¿wù¡³8lXœ‚Êš”#öçbáøx9°·pÆã{ã EdÛì¹Â欄g¡”<Ò³)Á°•§AÂÆšê„)¶ïµFJèr ùÀ^b4¹äÐõ†ö;ãÅÀ•dYaÌÕ´O¢‡0ý†(#ˆ!¤#G„9=xêX†¶èë»7f_ëA#…¢E+6WíàùP XÝ(Èö„á ‡Ý(0K¸¹ÈI­ªÓŠh3Ž¡H#þ²õþŽ7›HÎßá³ÒRŸ¦¦á+V”R÷Õ”ŽÂ‡ž ž üY=3·îB@Çuõùw霵ÜìY7@bÑ4‰ªÒMP,ÕÀxz^ü«ï¯Í&Æ…þ·Ðý Õ¼KsÅþÌ.hi£{TÇ𠜣°/y6 h¡æß(s¹Õˆ[@ê÷ õÑ}o‡eir|… qeì¦júgИô¿ú$i¹oòKE”‰[óÌ‚Œ t9cÌÏacÑwÎpÅ4I›TLíàLjƒÀeïãATð»EnRås_7¾ ûèhê[Lå½aÅp–¢Ý4¡FJ¸æVo¦$¥zšÀ7àùôñõþñ$5vr ¤îÄ-Þà~Ö4/>‘ܯQtSÏ ^c6„Y¬_4RîÁ¬~C[?|eUì†U~£Tcjî® ¼g;‹]sL¬€é#Â_Ò¯±'A{Ûü™ì‡|Ól}û¶ˆ}Õ ÝÿTy^PâÝ „4RÛÁÒÕæÐþ?à£qgÜY2á‰ÊþñG” n X/‰F™l¾j6ªî3vB&Ñî‹~„ÅÜO÷\f‹Î§d™üSÿ—ú-¬îè‹êŸ´ŸÙÞL¿©Lþ Þ{DUÖUi‹ù)3Çxצ£åöC¶txNãFåNaº˜}œ+J˜òÇ&r}+QQ:K³ªåŵìöâÕ¦ºó>›Ë‹¡^YCÁ0õ‹‚»¹B¾øN# u}r\F}SÁ½¢Öãî:š˜@à¶l‹³ñÈÒ£Õº<¬Ò\'pÿaĘòé´®_…Ðõï^ÀZegCOÛîH«(ɤÊ?frwÙUlïú×#ÏêA;Žú­TF¡räªL,f¼øvfw6hšÿF¨|ó,5(q™KG'‡ÜÁv KvñM/§i˜"³ôÌ–ûÏìÆ¶7aß:uíç@d‡•–8ÛmØC¨Xþ# Y"ûy#*ë&kFç™ýª2/=‹ é»_}<2©S]Üç{BÂ*¦L[¡öˆé¡ZafüöcÆA7éQE|x#I‘Ý?)ÓœÞ:%jrþ,{Œv÷ÈQ`ý `–H„“3Èã/<>?>3ÔŸtgÜ™õ”|R…(¯:Ý¡a·×-‡‚‘"V,4oyïw'\ßm (:‚éƒÝzxPÃH`se<²ô&‡ ƒx5Öæ•q­ Ü^î‘Ò(õˆl<ÔnqËÓkæ9ôÓÒmp©EK¯ÿî½iЊæ³Ò–l#Ý'oxÕÈ9îÉkzœôbÓkûý[§]­ d½ÀÌ}I©bcãíÇFç@7“ÑAÑææXØ1 :ñòEßiÁ âtùS»³ú²O¥dÿÒðnõƒ?pÿÿkÆë2t¼G‚Ž|¬…6Ð%VFDÖ1œÎa!ÎÎÑ‚¼aøÑMäÇëhŽì‚“âñ{8ÙGô)ÔÊ7™ðÆ5È­·ÒÿÓ³­é¿0 m¦íbXL 7ÑHœÃª“6m'’:žG”¯8…ÝÐŽ‘[Œ0ªf#ðX@êP€Êß‘µYŠÞ±ýv~Ä}R •1Zñyp=­ºŒþìˆ3<©m'Å×3lع~Žv àÀ.ä-•ÓÀ–Ή7æõØ#8±€Ò)ãñß(âáSÎ ð^åÙLÎcÔ2¡;íKs#€-¬›AÆY˜ðÃ;a©…N t>¸ Œ2«ïBùúl–‡žã¶@~Ë’J×™qÓÒhiôEF{KÓ8í¿‡@ÓcHS8¤hTGÆ”['*® $]w¾ƒ]Á¹q3=Ä·_Æ’û$Ê;a$Z hvCøŽG‡ó/\»dWD‹•þ½[½¬ë®? Ǧ]Çù¿á”ë˜ÂFý^Ëý? ›nTÈ8om “ý#QtÂ|ñ»ï_‹åØQ³Ø¢JOŸB®Ãadëõû×ì6Ѽw\ô1?yÂk6Çx#ú®ÏÒŸC¦&&³à&,’:dg»ð¬³+*ŠG¸jY€ÂÇP2öÔþªTé×ÂÙW@ ã£%wì–_@É£ŽºéWFAæ1YÁ" ™óýÄCyS¦Oj<ênÀ#î‡ûÔ-TÔ¾&¾ßÌá†Ûƒô€naüAÉÌHØqzA hŽdéì²: È·WN^Þd¹íy§›EùQ©iüÞžŒiµÍ­¡.JÕ™Hûô!:ý+H§#plu Þé©Ç7Ï%&ȪajõÔZ;ƒ<͈@‰Ëˆš)JêÀ¦¹«­s²±wÚ0Sܶ8}Š‘CËD@q;„¬a(¥¡“CY«wÁž%6MS¶ñWŠñ~ÞÁ¥cúòjA›V¦î¾šå;þOÀHúlý¡¡Þ?¨^Aû° ?—œ%’£dñ÷_¡Â8_qƧC§…âÛ€°ªý–‡#6eU£¨ãmWÏ‚‹óiÿJ™ŽJ/ wc'¢¤I%Ó{Ï·4ãOƵÿ™ÜB}yÐBzUÒ ƒÉžµævåĦÑG¼¦º·:ôÞêrô†èüý‡d®¦¤Òùbu‹Wve3lÔÑYíŒz¼‡˜Pšì5ÝJ±Ú¶E!‘<ž…†ÜŠ‚C—WMêqžë99Ã;ûd&4}.!C¿Ó-ÒÎ=ïXjM[öEÌZF,ÏÄaвLO–RB[½òÅUë²÷Õl;Ñ¡64>l!ªVm½Ÿ³õ,”~* E÷£ m]{[>`W‘ÏâÕ$v‰^†{¶XÔ³nMçñæà4²Ñ{ƒ}1BÒÚ kí?G«m•{ß}nn@(úH§)‰íRÞÃîî™ZÒØ`;ç׿ ŠÆ¬¿ÞѺ è:öêss·ÎxÆ: É< ´¡ëz$vqm`<Íià!Ô$Ò×ZÖ Ìﮫ¦sà~%-˜{ø9KçÞtß‹µpš¸µÁ¾‰Vch¬}ÁÀç¹j’.üœç ²_XMB&~Ì¢†î5¤ ‹ìfîðf§Ý[§ß^“þ°Æ¨ÎËduâ–Ù}Ãá$lÄs4 :T&ÃøÉrRì©ö%&:XM:t[2š]`4 ÔE¸Zá';D99ƒ@„…ç÷þK‘UþÚ«XfÆ@[…4ÑW¿B[DmluÐÃç† CRíaI#ªMìß7pÉ6ý-'h5‘[ëA‹h‡æ3ªÃ ®ê¿VÌFLÆ~Õ“‘zzЖ½&¤7ÇãÕf€ð9û\U—ûgóU¶pHâýÆ‚øÊ…X!•Þøm>“Ï‘æª÷xÇÒ“sO8ƒÜZ¢òº‡*óãÀ(ñ•þ+îãs(nÎ÷Ÿ™ŸvX[òr„ÊŒ‚$EšÓ¥¤šØC}ï³Ë½ƒs7üߣw:Ô¥5É¿<9ã=ì•8Ž´SR{´ œ÷!n°‚au ]¢ÒDõ³é´Û·ë¼ó÷ jìÅZàß^3Àô‰Íñ?óØå@ÁÙ]“H"\$ûT– ³d[CŸFà%Zäòëºéå]õœ3f¬£Øðžþw{¯ÍJ!‹î:+Š”°oD:­»˜ÓIÞ@v§’T_'3¥QŠª¿z`)yûŒú¦\8 šòÏâˆÈζnh"Îä•Wò{'¦º“¥ÝJ$N_ŸÞ¸æa¸ µsÂ=¥\ØÏ¦€¼æžýõZ4?¨YþcÊi¸fæÝ7´º½ƒÑ>þ»Éך‹wUâ6Tf•0á„nâÛöÕgo? ©PÄïé& |A 3ÀF>¿\ŒªT*þÐrÅ,.)Iü{*‹áªDåëÂ%îíoã/ýDMÐ:¥.67ò2v(pƒmgæ µÐŸjkÀ-®]›]LðýFgU —Ÿƒ™'©+ש2ž5Dÿ7ýÈÓø‘úXªf㊯Çšv‹0üÁb¢;hMíEä.àÓÕT»×Ñ¢~-Ç8¹¶ï ég*ÔËÔ­âêY,A)’zOÏ…d›Žð³Â0Z´<°´˜ ›Ì\øš„#åáUý -’ÿcs ŽÂ4³P§5¼¸Ø4‰º¼Æ¤åæÎÊ¿»HÒý÷¤ÅbS B?÷´ÀIº ÏãM\?$ž¨Ô2ê–f,Hþ©)Ðcth!×ߺLi¬NÔÖW³‡hW(ŠÖXX¦xúeIÜlÚC?þ15@³‡Ú–`ÏâI‘ &;»–Ô…ó°‘Çz1´$œÅ[|Cj79ßÏ#l„å:çê˜_XJiìcŠÏ?ÞèÑüd`E=é ¤hy,œê7C÷ühÉß Ôa•²u•±[†ôMGðz`0cm!ÿ¬¬0ä†Î–Ÿ¾ýÇÁH V& íu1"Ò[8‘Õ™4G2³Rm÷T*]°oÑ„“žánýbÒi•³Zõ‰çj\üX2tÛK½vżþì\ñp–œë€ñ-3=9!@Ýr[óx¨ÎkRûd—ná$`Ä ÙÕ¤H„J¡¸_\GªÉÞÍçâîd)…:­ïìmõiªÞ}ök£ê¼ á:ùjôBâÓ>›—vù¶¹§/’²îä³aþ_û­‘8õ›…ncx á‰ÔA¶µ¢\¡¿x¾d­[«“äû¶0ôÄ[#N‚оœ ·Ã÷?3NμÏi Aåáþ–Ù4#ì¿èÈÿNTòa˜vJðLùí¦ÞXY@lQÝ+ò© ßÒjÔiÝnúç>‰2ÜL#ÛßÞ奈5™‹t`t¦ùÆØš –GH¨«&•’XîJÖu ‘»iq«§È«Ïõx]J«<¼ÁD0¤Ø$ñvÇ’äy¹>!@ØüʇYuÅaò#á6SÙÉ×OUר(ÝOAÓ‘`¦¨€öw¢ˆÖ© b_hÒjy1í»??‡œVx*|—áœÓ[5Ê5K"³¤Ç“å\}!fšÈ¬[‹ìÞˆ1ð®Jr €i‘©b¶â;ŸøáRãät÷£¦w’°tàdð'¯t- "j­Ÿé|rï«t{¿yŠAU³j¯3ß\¼†K‘! á2…[¦ÝóÑuÕ7×K+“¶ŠØ ™M0Øä¶¹îNUI`¤iš;u‰žñøÜ“œÒ—Hâÿ˜†p•÷dϵ4—bÌnÓûœ«j™4_PúÒÅfGX1ðð>iåi•¡ª8Є"ÝÙ`îëá`Põ$ïÀÑgtŠÔ´&›‚ĦRGš»‡Å?V{e”j*F÷ƒ'ß~Ÿ‚t/Bpe±{ •Ýb° Ì,m4óÕþD² ¬|Tm Æ&0r*1 F0@’[èö6­\®ç4WѤPËB’U»l¥@sÎõAXs‘>Ãèݹz‚1ý³ûÑæIvY]$Þ=12ød\dœf¬€fàw% uVêcŒ¿ò:àP @-šKÐûׯ€=Œ3ÒÐFÏz¢fpœ§ ͉þTjœ„Á}pª°ÖÒ. Âá1BZa'3ŽW:ìØ©ÿeÓ1£d°sµW\¡Ðj¼a<*º©6»3™rˆ@Ðvn§tǸ>ç2.s÷rÛ0ƒ»·¶UOåÔm¶‡®·wg"Ì %n¼)»¦Ðõ¯N›¾I€…Rª^™ÌÆd¤nâ|›âáC•ÎÕœæCÃë>U™•½‰“ËJ‹~HtÐ{~q,»ÖѰÏÅ"pIúïω÷…èÁÀiEàÆKÀíA1äÊY 06´¦Ÿ5{ów5ÕથF¨I÷’_ _`†Z"{[v㣠=ÁSƒsq¢9Œâ’Iû‘dx#3–›–AF‰Ü»¤6.8R>·‡á/‘_‚/w™?{)0ýÌL;éBíú ú‰ø½“û¡¼Ù ¯oGÆ1×Fµ›Ú6‰h—üà$BtHßï2ÙcóQ”À~y´úñL R˜<úßòSó‰Ú˜³®ã!ÊŽôLã¢HðŸl>Õ–¥øð¨.ù‹Še¤ÀBÄ „' ›œôqTÁ±ÒMˆO ç¾áÖg(ݳ^õV&Áö\xs²ðZRYž:V¶]åÃÃUÁƦî=cò?äìnnNÓHÉ5S™ÀÔýk‘ÍíÿÉÕÎ9TZ­üøh㘺7¼ÐWÏAÖp~ç+ʭ隈Ô¡­A¾[´ w·ä( ØC’|²úa©OSÈfãÝnºd=l je%éÍœ¢©{~ ÄhQsçÓ¸Ìau,Ã_£¯"ÕvñÚbS#­“á~¼ñ,Ýlßà!–”Ù[|~ñîšSѬXgÿL_î÷Z:ÐàLÿÛºÎëS ?È®†wÃÛMRã»d±I2œ›\UÔéGP¹×b&ìü¡‰»r"Žïb Su†:6+O—ÂîF@Rãc… "ÿ›ð_>ÉøV[iZ«î¨•yë|]Ä@8'Ç3º ‡‘Ä–åEý7k؈M†È"zœÎ¡†ó—³„¤í0l`WpúHø>÷ ¦ÅÀ‘ŒLÛ­ø8¶™Ró²>8)m~æå§<ÍÈs`îÚLTŽ˜²Ã‡öJÍeÂǸ·ÚãMª!-Š:T@YõÞÛîÃ3ýsìÐFe•j=Ã/Ïtìv]´}%s§[ ›Ïl\pÑE…FòW®«A­,n³>èõ®qa(Z´°X1º¬‰Óì‘¢˜_ŠFVs.Ī¥‘xL QùBÈ|kÊ÷¬è>Ñ‹-0¿J`55™tÏzÒgî°2¢ìèªÞóꯈø›Óay8L§ÇÔ‚›clR±üy³BLà¶¼%ôA$ž=ãlV$—í÷F&?úAeJH°R“KTVµM%„c¸6±»ë²ƒòÎÜS¡$*aâyÊw]Uˆ³¡ªâÈ °~Ýæ-Ö²âDЈ%ÑH„†˜¶sמzS]´ÿ]ÑïÖèNþ%öœ‘»z˜ÄIç4Á\Ñœv¯Øü_Ä€’ýÊÃãôéÄ¿ú¥vT *$lÓÔÙ?e¼ý$OòX©ên²ô$—Ú÷†…r³íþ/ÔP0©ÕJþt}Rg( B¥Ðôì&‡Œ:‘\ÈŸŽŒþ+Zà¤á¿°A¿©cÁi8©ìÏjc0•r~,véÖØù¹HŒôÈí*|(Èg+Út•ÎÔlý{Ûà ŽÓ‹ó =u#Þ%Sn-‚`ý“rz\Ôe$OŽìc™Ð^cñ4µÝâµfôçô-2À± ôd8§ªbînªô4‡~\ßQ©¢²{¤Wª{|Or„¸6X@2ùÀºG1IŽQi”–c½tQ<ùS©›SWT¨êÃ[%µ. ÊÇXº˜×:гãsÑš;™˜¸É+8¥O @Ô ã¸ãÙ° .þSä! ÖÌíW'bló¬íµ¢âèÒ‚ï§&CÝ êD*ÜÆjä.ýµÐ—sþ露âE éT9û!Å¢.Â]Í]qÚÞËá•ò™.Ô¶‡ôx'²¹£5Ä!m‘þ™"bù€ ''!lqŠUâ—Ô ™>7ìþe3C{®Þ¾åÿG¤ƒBK<®ßè7¥é¤Ÿ=NÌÖzÌ—1‘­¬rûÊU¬™Oë®S˜˜ÕCÔ„QfÐ/GHeï 'Ñô˜QÝœÝ\ÒÔŽ¸Éý..ŸùO»WüĹ¿ZÚF©ÁLiÏ¡˜f4f¯Å—Ñ% 'O7'Á…ôÛ[MY%“}yåT3T‘dy.JÝtØT|È^DØèŽ™z3*¾ø3Ÿ¾ÿ¹¹õ.—špû }„ƒÿ4ÙíiÀ¼\9‚Óoÿ´5ò2Íà2X#‚*·]4/½ö÷i=®Dwlçýõ³õù»:8~èšHF#`rÅþ´ZôØrw;3ÂeuVi2AcåÃ…¼ä Qší¯ üçyý‡]‰ò÷ÑÐ…˜Ÿ#üiƒN»W0° ¹^2†ÞDí3¼D(q»ŒÝoË›¨uŠ–4ZSSÄŠ†Á©ç"÷‘AÖÏpø®y=îm 8nö/7r&†Éž–¶ žÈ*üý“DÃîJ9NäÑ,´~Wԓ+¸;Ïx3Åoãܯ.»U DŒâe3õWJ&/  .TÝT"&êºßIÚò+Np°ËÍ¡agGx-øµyá%ëÏÕÃ쌎ÛuD4sM•qͱéƒmiä@lFÓ…NË O„ìu»Ô~hF8À…Âÿã5ÜÊÝ,Ê­m̺Åä©p’#¡‘Kj©4ÆÆM ‡#8O|GÞ~Ý*Ï:´½¸°3Ž@òîúx\$Ø)qÚ)µû‹Ž^z˜ÜñûRk†œ¨Å‘M%“,Zú.^׆?atËìÙ#0"ßS!'zâßb0˜5:>Cm‰ éz¥îm#‚5$"Í ¡"ÒT²†ÛìÓ ¶ZØn÷¦)šgÝÚx“\Y‚×›-ïÜX)áE½|w£»cX’”E°‰.k“¥PV®ÚÂÕ Ìbr«<æ o„!?1ú1PáÑ» šU{~7©ßò¤· ]ï,pó+b˜wUÅ<‡ %º·“אּþgůtzr]åZoxDZ'ñ†C¢ˆgï 3ª‰UÇ*‚æÿ(×o+\Þ6'sžpþÛ˜çñøð×ó¼à< M(<ŽOP/@^; «»Ê\1 ذëI<0-ÃhÞ<û|jtÝ*ÿžÖâZlnq^‘vb•1r1ÀO6P Í„.š\r¢wÐÓë—"+¨›X‹ÊiÑÝ÷ß}’ wĤ&µE#jÞé Û ×Šo6—Ü‘BŠáwhóþÏ«-êÞÚ[ ¦íä ¶»Þ]Ô ®¡xQM‹ü룗$6q4ù¨_ÞÖka#v§M´QÓ+¨ÐÔúýŒUšdlÌîÂTõh8=ÿ¸  swêÚÖ©ÉohXx ª+³ŠŸ¹Ü}“-3ÛNºU¢åÃQnB%Hãn™· ßÁ|t”7ÿ®6Tÿ*†N·Ô<ý»ŠÞú¯?\a¿´ëÑ‘Ï^ôÊÆzšs>¤‚3xºÁéVòÿwôW¬•²#®›(×0à Õo@(…˜$L÷~¶kŒ²%„ŸÃsÛønóEºZß+Éþ.˜âÎoÚïëúIœ–B#¥ ‡ÌÉU*°UúHðz­b#gm_#a]mº÷]ÅãÙZ:nVKkÇ2ãÏ´?£ ([¬žò$ù+ ²ft _-ò#˜Ï O^Þbð ¶sTÿr‹ÝSø[ÁÍÝ&ZûÅÉñµ˜äTßâpÒ\µèÖ%{|»Ò†;b5\ô4ö-|+÷Dížà·Ý´f$æ‰À…'µOÜ6é¬ðçµ`)„÷?þÖWÐò* ÈÔe‡÷(¡cao6Äq£ÿÈ¡&'ã;-O8ÀQûÕsI4Çž ÉŽ Vî%a÷ôA÷QKkävË,ÌòÕú›1 ž™o=°¡¸—báfÔ:ð1G[Ä“±>æCÝ/,;ЀSe­´NÌÔϪ+i?´á>ù(²1ÙOe¯8õ—ò!ýÊh*rP{É.*I“‚Ž91Èm‡µoF˜µ ð7ŽŠ^×0Q®  Áô×$žàÝœ…aÀlqîM¿:bï”<›ïr­£åBƳ³^b{cß½e¨Ât!t§åû a”„KZ[uŸ]¨¢è­¬öC #»Vû, iA±v›·àõg(s–:Bm±nIWJ‹UºG ®‚í)&Vðã«gj¤Ò/ñøp ´µDÁÈS‚ÐkQM%µ-äëÈé’nAêóà›r‘!땯@±“µßj¬äåzÎ\2¦œÿS¡|ÿØ1}%>¥9…µ78r»°LJiGUmK~HÒÎÐ~YX$%ÇçGÑü»8ÀÁÅ÷ŠÅpõºr 3‰“fDò“®TÚóµèúyœ&E+7"BõyÖWÓ'„¼I‘Û‹À‚ìÎß3Lù‰w’ÕÏì›l‘€%"ížÄ{ßΣ©œhvUK¥Âõ×þÁÙ_úÚsíªP$ÉîÇ‘ÑT÷ŸëT7Sʨ}Ú9NÊXÞœ›Ãj2·NãI¼Ã×È:\¥áF*üÝÂÓéÌ pµ¿Xgž˜z¯B¹àVM¸äìšÍñÈÆRyÏÿíëžD%Z FœÙÛ\U¢7AåÛ¦Ò†Ðz}h4ÉIÄš)ŸM„êâô*1,õÍ^ÉÀ-ÔS±É¥àï†ìvÚôd¤üK«MRó1cˆ-”ϲºŠƒÂ“Ü׌f ÿò€;+µˆ°š¼Ñ¥8¨®EÐ@;p’IÖˆ!TaÍ.2ª" \0¹äÜ*D‚qb^ŠÅ\îæÕëÝ3i©p„Ãilþ5f 5Ë,ën4Ù-³dcùÐNÉ<ÜÍu¹s‡ì#NųޗU»Û¬—e½IöG]îÏÛèán&Ó=²×†Y¶îPÌü\=v2ªI #fþôô±“3öýz+»à/< ZÁæ>žÆ[ u}§ÎdÓ{mn¶ñ ¯äJ‘6¸bŽªÇ1}:Ë~ä†ABj3-sRÈS]t†&O³ów R©è÷Os6n¤òJÁÀ¾ãjB§i}2Ájùó[3>µæÝÁŽá.¾»?zÏ v¿êoTyWZû¢ftm7tÕò¿ÕbÂ,\)µGéÚÝ7·V'oÐή¸:¥YíÕ‹ò÷yíŸYWƒX»¹ì¶gŸ•(§òÁs¾ö^$Ä¢á·ÏðÄ{˜R¬ÜìóÞ•yþ=-Jºù*‡Ž„×KN扛@.=úÕO^û;”ïÁo3ÐVj?WÝ‘œ`í<“2&L7Æé„^$_D¾äâjTHGdíy@¿RAÑ7·s7»g4ˆ?…‰·åk+ÿë¶Wá·€N˜é·’e¶ز±¬ ÐÛÅvÌÙn‹£+…Îl}5<ˆóܺöYIèCTQÉFöW¥º4JÀeʶ‡u¥c;rÔK6ÿø„Ÿ%y«êFW€'—|dhYf–ãÚ0†jô\Œ†»]5S–lŽ8®³÷ô‡‘ ý¿è kd1ý3†üòϳ l×ÏÖ3-Õ\gvì®í=TT²QÂäæ°%rÝÁ¥ÔC ˜_È€2#ã·øèEß`$ ·Ša@]¨kLU:8Ý%ßδqUSºe>4f > ç0µŒ$TÐgj !‰ŽOl¹,eÕ¼^SëÔé8šöìß;9ÙOðéS-z´à³ ¿‚ÁgKoÅxwa«, 5| ’üÝf=gc]ì7eúe¢“ú0(zÔƒUâã1>Tዺîýt7DZL…uýïui{8bnÚ6VÝ=†UÏ·»n6F?² µ©Xv P]'3¤·“¹~µA”j¥0É&T_´^hßk©`\4²–žÁõ^s#ˆµ­_Zá(jFŒFzaÝùp´˜i~pWoÃLMî5õ›tm~è;%õhbcìÖ*íš6Ý‘béS³¨¯ß7ÊÉûþš ¹/W‚ 2ˆáËš‚óýžýü[‰>ŒÔP-ƒˆãŒÎWMÒ$x$8Zôºþ3Î@`ÄûsG“_X‚9EX…ù(œ©,Ž´ù$½^'=Ìë‹4^yЗlÖpÆÖÿÅcËÈ”ÿžzÐWø+$òç-Å–#ÿÖ-Z.Ç®S+ä¼k*Àl±¶+dBìmàW6ußüìêÎ>¹[ñ‹ê¨v›fÙ†e³Äi<`ÅÅvþÌl2Ìq"M_éæ40^ 7d;÷Ñ'ÔÝWÚR?ª)aa;¸%> 2´ÖfPÌ[¢;*ŲÁ¹Ðö:ˆˆ·³¿ù_^VÓ(6E]{˜Š5y÷ôçÐè@x$ó'0¸ìúWtÛjÎìšP¼}’ožqÑèê¹1š\íR¥Eÿ•(QnƒÙIÜS!3oGq¦¥{ J@?AàhÞ±Šý®ï_V€Kt¹wðˆ‡ˆîPèl¬ëRÒU2ÔÑ[õ9ÚæÚø0§,SÆß˜UéLb$AæÎ,ðjŠM‰-ÎÍ‹ù†b郹íj„X†î¤#ÜRöø‘àÔjn•CÿS}SkzÍ$U4ÔgÞf¦Ï+E¿•.ð…±£a†WŸÐžp.rQý èï#iòî“~¶:&ß(Âu ߦ–#2ÁY·Á¿ã G’8V¼åA/įÏ@ð¦R²í5am%ÿn‰mÐ/Å ŽÁëhIü³[0¿.I #;zP´B‰ª6¶æ¶ì°¬—³ŽØ~sX$¦«á(¨)š¤Xf…?¥ `8{»3õVqB£“ýÿ‘a¤¯ê–ÁΉâDH Ó‡+æ¹ñV{*%“MŸeÏ21µbŸ8/Qù'·£Lgzi‡ªŠË-ÇcèX; LÚM‡Åø‘K«ÏÏ‰Ž îó+Aºq÷.FXwùÉÁ¸¨UÃnç)#¼Ž»Éñãû§vûX41N)Í0䘰=ÍïD,«V5\‰`â¿ •*SyŠY¶~Ç1k_dÊløíÊ^VÚà1éès%ŽöËA¡â¹Øû{ óW¿JƒYÏ'Àt‡Š2ý÷E>ƒeðE„4tÐ9súo ݰ'aF(}?Aå×Ï¥ôå q¹“te jö®[«\Dm×ò%óà8#þo(d„’Êœäc5>(Goã Ue}æ ivW<Ø%'M=U D05+½®F1ò”RÃÛ–“¿^§dœÀ ‘šãdò›(`Q¡à{¸Dnµ ž ä \7ƒ­½…Ê“_Ë£¤þ#§ ^n3G;)ÂC{dTÉnI¸K1ÀÛ¸LOU®u@#ënœøI]gœI¨ï¢l¢NTc ó#ÞêcÆü¿¡Å©U§g§;­QŒÌ(Uô”…“\fHK¡¦T3‹ oŠúðžÊH¡‹¯!0o‰¶yLÙ€˜8¡æùY¯¾ 3ºHCŠxAâ#V Ëcšu—F ¿=‹03àrT9qü“ ºŽ¥¥“W -¤A[ûX¹„5§KΈ5\@Ï „Û-½Ô±Sm¦"¨CêõôýãEokºà‰Ðe…tEîð…5ô”ª"SaS¨"ÞïqíT*wñÖ˱Õšª²"åa%_ÏâÇÞÔÔÔ¾yä4%U¾l¼®»ÔùAê‚‚ÈuxÓ ˆú‡[ÝX’…-7Ã7•ë˜óikö,:¢¾`(­‹ãXk…yh ×jo&Ê1B“±Ëkûè ´`+ÐÂØ‘8þ܃Ó˜'o§È²þY[ÒÒ¬!X@Ê<¿Ùí'HîË&DìïE;±å‘©4hüøàøÉ±A˜ŒˆÞ…•^ýÔ/õ^,OÊbR7vä »e5´¥ªVNöG¸hßî ¨mñ A$!I½k!„ξ6ù‡Ñ!ñA“‰mÝ‘æÈS%EÔçã0“ ]x£^¿eR²kÁ/À-§HP^+˜  Y: „Ö´†Çmì@nLÕ_fûvqïhðŽÌ wªÝÌ m@²™4Ê(½VgfÜ„_)X427û€…åÕO‘@ÿ§CÈ<Àn¬.uÁ*Waóê#X TsJ„}̸ÙyçêR z­mÝÆÂÜ~k&´Ø%ã0;ù·â²bº˜7…qYµb9£eܰÓZ×ÈC-#ÐÑv‹ž‚äÜÙú°7†ú)±meÐ ¬c¼«KŽÖ¼%µ±çtOi¿ç+Æ!ÂXà(#ÃòEƒÆ)#¡ ~:&ÎZÿãú£Y'ßèüÒÐ/¹P9rËmÐbà´”dV.;4R@¯¦©r>ð99•2³âuóéV¦¼)–_îúJ¶>§ l÷Áîd£q”­-‚^NPÖ%säþ ¤‰a i)­(Í‘ik^J÷dë„ Fv;¿§6•”/.:'‰± žß§DÞ­S§K]¿E/¥ßñ(=_Ÿå¤°«œÂ2ÜvdGÂmûå—´àOolòuÕp®M°C}ꎭ‡ÀÿinÚ·‰óA†Û15ûÂAsô„–Ööè6Ÿ·P*ˆí­Ó¼£ŒèÄø#õ €»V6³h;±ŠÓ+‰QêéqàìÖš9Iã‰FñÿtßþÃN»‘gÑåblŒaÿ(š ) ‡}¨ÜÞ45¤弉Íþ¹¶W ®z`æc` D¥Uù๷O”WuµÜÝs…¤N0[™4zˆLa{Di»føç8}“Iž¡ˆ\…£E~´ËÜ`>Ë%eÁæ…Ä̉c8FÝÎ䳩׿¥¤¿Z/÷ 8Ny™°‘] ½ôE©y’®S‹KC¼¿çgnBẇ'«è¾0/J2ŠØ!'TMT†aì†"pFaÒ/¯±&2í^ÉÁDýÚ  1¯–}!z†Óo²48x!`ª2tþ¸fÏq[ë$…Žö€±^ÅÜ<(øë»CfŠ÷²³è¬åy{VïÞÉ¥Â@žú…Ás$NYŸ ²“€|¤F 3óïÜÞK¡oy ¡G°<&yƒDêSh÷x/é¥Ñ“s¥s›”åô{«Ö=È1u Í3 !Ãrè@?…šDQYš}ð†wF…7’e}*åËŠŠXÒL˜CqÅ[/µz°%À3<«W !àK0W†Ä1ì²sÒ²;nšðáú£™=±ª÷ݶ•Ì#Åž§#ì´k|CaÈõœùl±6[³‰IácðÕ­™p¬ #›=yßCÕèÜ/6ýzò•áƒÝ s1€ß¨•ÝM^zLªƒ³lèi¶¡+,FgÜzeuH ýl‚Kû°òËú" {^w#±ù!…@7È«‚£cž'– Oy¤¹™ùI³DÚ‘úý‚äME•P¤ÓvPyŽ0ᯔëaúŒ];¿1=…Ù4†Ÿ|hK8©CDßtã;Èk’ ”s;¹‡)U#æc×ïGÔðgëȪˆÛb:Ì„¼#«—”™óˆh' Zôg ÂR›4\·ú-ðýž’ñá_ÃÃ÷uøÏñbÿ¬]Þ0@Ck°ßV£gdêÛsëocãàYñÇ¡}!esÈä;Ó$ªQ#eS}]QÄ]wìç+·’Ï6G\.F€:./c»ÔBýî·€oh…PÜñ®7c?3O3’Äø¬7ºHIÂEàÀY¤´4ÂûJx³|€YИÍ&»ŠLnà–_ŒÌ$ rįÃ÷Ð/ì»×†îâ(ä)'dÖ¿]ÅŠæò9ïÞ/¶d"X|PœJ¨Fõì˲0ôj÷†±)'ó~ª7oKÛÅw­·Ë és#/Z†\µ1¡jEÝÏpEÿ\}rCÆÎå\ ž.”~¡g.3~«oÝ•|) ¬oÇ ’€ÓÓ\*7¥[½¨Šä¶õFI´Ë['þï/Û bÐ˃ºÎg|ìGd—@Ó©Œ1ÝÊÛå À–k.…»6ª²c[¸Í‰±PWy![8Ô²¶iÑØxé&ݰ}áOdkWÚÛ/ÚÅ^îNØ ïYfÚÇK” .:'F»`¡’Õ\ÙHËÛOV| Ó‡X`’4‘çú\Íw™C‘T<¯r†t“•¥ø\‹wG ›,¯5;˜œEÇÉ…?é¨ßäãƒ@(á2q×sÆIfL`<…/Kcݹ2p-³=ÿhà]Øfž}Mn–([°|˜™¢E[si*@î…ÚgêÜ$"†®<=ÜùèËA°¹¨øz›Ýóv¾]—Z´ò½-H«§Œ¬ä/õ# |‰7ÔŒ¾+Š¿¾œš?ˆ<¡M)’C¥]$è°Ö4¨cÅ{©©™zbÞî÷x6kα19*³’¦täƒJq]0ÞNÊ[›3éW÷_]†¯ô&¬{ºÊ­?Öd¦%ìëØCNjg°ÏÂÝ"Õ¿Îj5Õw±v'L`ˆ û…¢ln? Á?zèÈH0Kåó|äùáÓrlK¿­êZlš”;&„—‹ìÄc«K²X’r*Ïq”]ôô þZÔ³*†`6ã7¶Ó üû/†#ÒžÎçÝÛ*B"Y”#+.€–H'ãí]¤ãG¢BZ-4yüc+ò(Þå©Î068yà@³ÿÖä4ôÓ7ÜC@Â^Ê>eN’‰•â%šÚõÈc‡õcR÷òæyÃgàA«ôŠˆ¼ë9ì¿…ŽÞÙY˜æ ,%4äï‚QbÓr×òþ”mÝÄ[{ñ¸˜uû•[/9OIûóÔ)18¹0”læô¤"ÿpsàQ}´2+ïâìƒz¯AC÷SÄ•D°qÞ¿QãTúBÀf4ŸAÙô̦\kÒÆœ±¸Äû£‘à·Ò‡M?êwXNãË)SMKË_1Êw(þrÔ×úŽÿ–ãTRf|ã¸À9Ö´n‰í´ñëÛ@×ÿêG©]DÚJ£sì±ÙÀ¯ªýý)‹Ø®‘½M£-@n-´*‡KY»LÍÛ”+Ú7D ´Ô ÃÐøê$Ø­JQfÒUBöÞ4v–ù±T3F(è‡CÅtf]áó%ÿ ï‡õýãÙ´EM{+ÖéÄÊW’ K´Ø¨iúP‰QÔðÙ.Ï·©¼×p£ì¯~ƒì!x̘úßþÙj)X$\Ž™òÛ§‚†+¡ßÕy0QgêXµ\‘£*é‚:O£~Qу#ŠŽ–,MÇ'í§ˆ.aç ¥ú5ñgö¬ˆØà (ÍFÓS\­[GO5Î¥×´c€'~¬º~§ ò¬¦8bS˜\Fz!ï†ýN¬¬¸]ਢvhŒL¡»eéj&“‰—§Lïâ7rŠc‡³uº ŸXƒ) õ#²!QNoä:å_gr$Óˆkߨ ø‹Í—"Ú½Ðù–Œ?ñ<ÈV[*[¯ÙdÈ›£0y )§?Ú¦N5ün±¤L)USi½PÆ®Ï1õÞ€{QF*{äD¨¶ãNO†¡—vøÔÓî-vò=ìc6ñ£E°õªÉ„ÞYÒïôð$xøTY@]z¨z ¾.¤ã´bÆÉ)Cy•FUÉ 5fÀ‘Î[.Nï»Wn‹ÃU9TO ]Sé!…TW‘†3^:K Ÿj½Ôük˜q…Yš'%ž$þ2æ?¬™¾¿@JY hHgÒ¦m_îÚyO^,é_ÙØ?\j²T‘•¸¢‚sÐI»îLgvl;÷¦µØŒÀ@Ë|™Ð¸Aöº[KÙuóšÇ †É0=Üñì‡.„„JžãׯCg^†!¥qB¹ *W{ÀWçsíçRÚ‰ÐIÉ‘¹çlé ø²NÙGYÊǮݲ8ò‡ø-ˆXî?óS¥­Í‘ßc„r“Ïh³}µ]ÒŽ“8‰w©üøbãÈwŠ÷”÷¹&z“Ëscþ zëf¡,.8¸¼õ`ÜM~ ÛöÊš‹Œêt1öbŒ²Uá”$XÞM‚ #|IBïî¼¼Ÿ¼\¤Ê)Qq÷¤<…z޹ϯ1?wÕa·Tý‚¬@º±vä&[P!½„Î÷óHÒóTรñ«É(´6([úS_žk†d·-ÿR§¼•z©«UîG…hÔÊ(^Ùå≊“ÈF+"x%bãVPõŒ”¾Â%ñ!4DÿG3¿BÚþÛÑ%¤±x"²mø†ßžƒÚ)ÞÉÓxFd*¥}K¦Ÿ¿5_rçv]>Ù¨NÜñF(•û3`r„Å8únsHK•Ù1å*:r’6Ñ´¿)M ½î|*U¯Cub‹Ï:Õ"~ Íâ?EªVމ]µ¹Pã"`Mžwl¦té® ÖË!‰ãvNíñâu‡+ú~K ×é|‘ÃN$z}Z”O?ÔžC2É ÂèÇ +™rWO¥¤½¨yxqn<ÌÌHH¡«,ºœÿcžƒ£H#ÆÕëá MÙxñS5IÀ°‘nH 18ðþ.¿{³•® ŠBXƒ²9R6dj5ÓóІ5÷Øá9¬«-“ê¶%Ÿ‡|—s2ëeü2 ž³ ºwzFÌ’NPTl±ÑI qnþXó¯¤ÖÇÚçu²Æîø$7M7¦±7Q8¯ÊžæÖõØ ‚zÓ}‰Ãò-’ÇxpоxaøL¤MŽ8Öä8ŒÓ´ ‹7©õ¾í`&ly÷d»•z¶k‚ï]ð(‡P–ˆ®T{ÿ95ró% îÑ  œiÓæÀŽñ!ý#Á%§r¢&AYÙQçíZµî¡ÖJ#¯6¬[wG¨d2X~Uæ÷üÑvW•-8LâkCéè_°%™ö<=Œ¿¡÷©QÎÆsމé°7!¬~{ ¦ÿ‰·Ï!wþ²ËÎó¬[%¿¸n ýî;+²U %—ØC9Dúv¬¿ ÀÅövöÓ> îœKw2 öÚLùxà´*Bÿ€ÄCUïNýþ”AßÍ"®"ðÉÌX3u|mŽ.&õueT=8n©DË}–š}Õ <¤çoæZÌ”R@Â5<‘yj,•ý"×Ùn³·²·;‡J’èu—yÝ’©½ýŸãêwôó²_k{*¸½“¡W¶‹+„‰—õ?öÎ-š£À;|د٩óT4Cr{`³(i” ,¦°JgÅðß/1£Ú4üÛg©/ì“Êœ¤²qñ4Ï_•Âûz"6`êσ·ãüËD•$t“%È9Äé.IÌ^”ŠL[t~)ÈRûgV=ºïõ¿Qk¢zKÈy³&Gðÿç—õ/ùYÛ÷m–fÖ[3а†B8`,*ï-É7pæùMÚÇãÑdLÐZúi‹¦å:4¶”ÚG0E+NìB_”HÁ1^iÝm›þYæïa{“³äßÿš‰2Ezžá[ø[¹˜šr½â|¨Óš]ÏQTµ”ä$¦Šhzßшó{—´F´œò‚BeÕò"À&Êp%¢íåŽÃ-éù›?â½å$4¼õFŸ¾>uÜXÚÑØWü")9)vhî]$aKShÑ`eÊvSñO¨}‚r†U-$¸[e·T ¦…v¸Z*¡½-7POlö³öoåû,¡å ù›mxõic|![…Kò§ô »¥ÔÔå-l­M5 þ3¹Ç¼{–|1ù) ˜æÕMRJÏÈu4½ÒÞ8Ç󂼎;¯b+giƒjû†(•u¾Œ&&@?<è$%·Æý’ï t§ 3r¿¦ŸÛ¤^¾f«feŒ€ú¡h—€ÏßuÀ¨´.–Ómo“…^é·Â@+5Рà/ì!iÐu‡æ›6yõÉ%î÷á'®ùŽB Œ‡–ûYùX–Waw@œä¢ï ë¿ŠÓ'ä\¥°€È§£Ò Ôàö R%Óª‡;¼£VQjØÑXkcãR˨>$çO§zþÙYÀúÅg‚ηÉ,BÀÒç4T¦Jv"(ŒÑ àÔx^ VWvT>ã2œ{šõ3Ò^ÚÓÆÉ3v¹©¥S?:sß9J¬ìºJYö÷¬¡ÞdD®QÐâASB¾»Íúɼ»¸\`fl7is?ÐgÏö,¾ÂÃwòÃ!ŒYXfÓ/MˆQ ›.: '¹(KNø.*¤’ü^¿›åÜOQ±·†¿Õò§síÏžì¹"i òèÜ<œÒäÃÑÆ–ûä¯$OóJKÛúå'À´êÛ(¼ã}ΪºïªdHcØ…Xx¢ P#wŠ9U–aHvê×CµÄݧCõý™`†·šdÀ•ÐþÙPØn“Ùê uCš7œJ® òåØ ÊbÚÄ8% –|QÕ[ ?¡_íø3Bl©?÷^à=A€$”AŸ3/Ž¢cBÖñ×J7ÇóVÔƒò»…œn,Yw€@¬:à§=/uüP2§¹ÑÒðô°èX=Zdª¥¤whœ?¢Y0ñÅÒmÞäÝT|,¹©­¯ÿ|uÇÇ×BÚç-™aÀ‰ÊbAÑêäÆx^$¹ î‘D} 瀸GÆóý*¯“–NØiaÉí© ?Ú~³ßM\zi9[hÊù¦‹\›gL×9~#\s^VrF‰½…ù2æ©1¹]ѤÙIžœa % aM'Å9«ü'GÈ©Êþž`}‚ìqÇøC^ÖK9‹(A;!Yã¶Ð!wZú}Kç¼^²Ê‘Ó“·‹¤ˆs´_£EÒú¢ ˜ úŸÅ´†dBÔ@K˜´—U ”è¢ÝJÿ¬í«_+2ªM½<Àןp¯G\׸n¢±ÒY‹¾\v©oyï+¤íù}kŽi¡Y%'Cƒu¤°äi±û6U_MaNR°| 'kÆ\dÒRt÷=£¥žÍŒÃOñÞô5×´•} ©vLâÐÊF]Äê‚êG$ú\ЙoæTÉ&ÿ”¥aÏËlÇIû ¿7~àYHZvoteÚÙd/³ú.Hë—x•=9Ÿ:ž°Ã@’’~5œçGÁÞ5k´oWªâ…°ò5°œ¤ßï¹Ñìá0ùË!«I&s’µpO¯´w #¾A˜ªSC8G°¾Û‚JëuDÇ8 µ—»>vÚ´“‚âé=CŠ?”fY½dùŠãÚž¸xTÒïF¿ò bË›†™÷,ã~;GÀRo¤HK‚‹ªØ˜…eŒ½ûÃkƒéð£¨%õç´ :±Ø.‰43ór­,ÿÕ䜚ˆ2®û)U0ýaéiFAQU̱7 7º|ÁÝç -ÜuÁècFž¥Ÿ{ßwR[NR\¦ß·=œÖ)†fáZS’½Â½ÝäW­¹Û«‡rëq‹^ò(¿i³Ì_¤½Æ´.±¡˜™²—‘ȶœÜëxlן8¾4hpÉðÑ»xªì5jH¯-&\Š_¾úÒÄÜ%$&ËuþÒÏŒY&Q ÷…ñù”÷®1nRQ8”LÑmä…Ã’ôÀ†Ø.©Ï\O_4Õu»5ú… ÎÇ3¬xöÛÙ–­¬½.¤­4F9c3µ—‡F ¸E0@¶§bi©G¾áîÂ ç™¤Š†Ëa¡ymrs ™ £[H ”ÿô/ìWm©dÈÑ•l”¾eîh“‘o!N.ä\U ¯bÀ¦®“™ê9&Õ}¬|Q\–¡¶¡m®Ë`º(òˆ¼&­à¥&LUGq¨òˆy=\ó6Yg)! ÍúW!c’¸ÄÄ¢}ð?4©I÷ c4üm°mžâÍ!a¼ÏÕ ïoŸPé©j° ,fKì}Çyר¿9ïV¤3íÍÞo1®?ùÅ ¿Ícy[ÔO:•>ÓHjK˜g™|±ôÉãtæÌzåm|¯¹Q罦ƒyÊKWÚÁÎÍ9ß­lpé^Ny—Ô¢ œ~¢¼žóMLÖ@lSR®bTù{ 3$¾kÏ ·yXÆ9—U¦ôÐ Ð÷›×?ĆzÜŒ=àÌ™7; ˜‡< Þ-ûÆû+³"ph[Wȹ°õ.c(v9E›Q–®k¢§]‘Ü^b>hË¿åì¾ÃIDå>Xi ÊÂÉØû&‡5Àü7õ(Ù‹°q.ßÎb¯>ãHQb¤:mÊD/êÞ—!¡P"ÊkgOwKdgŒFÌn¹½fÖ-,½nb×èw®‹Ÿš¯¶sRv¹MŽº"ŸSZý¢Ͱú.^2ñŠèCÊ-ç*gmβ¢BÌ”(‘¡ ü¥.°Rš¬¦Ï%µa‡)Ê ÛiyçAïÎŒ¸Ò[¹·£"9°2ôàëPø"›fÊ{çó¬[‹høN­Çü§ èÖñHLfCRýL9 ø ˆ`zÈ8/¦,Hmßÿï¨×Áš™›iT:´ü@z'#ÉTB$5©vvvÑ?ã(®,¹¤²¸ÕÓÇÂí˜["TƒÇ­4´Tª+³3³‹”#õ¨>™…Á°ô5 á_¶Ä@o{c.]W7Ž2oBå ¼7%ß_À [xîN Ši~¤K¾6ê­ëM…TŒÿÌ´€Û¿1„Öi³|¦F³^®ùj éL·8×QM KŸ(‚—øhJ6+ç¦Î]5µ6€_ D^;‚ÜðÞüÒ¼:-eÈ P'WÑaŽŽ`£.½¼)šZtÎ ^2Ü æ)¥3CP«‘ð‰±b^[:_ÏŒ i°]ÎîmúÿéS•[ºå#Ý,)E\K‹ ccq¯mRrœÛ$.å7‡x[(¡ò)†OÖÃ\D=ì{ìIVç ¢W»å+6È\W³9L+)ÃlŠªvf/?ÛûJ ×ÓÛ/¤¼hŒ–ÒédŒFezCµ,·Ã¹Š™^9½$ÐT+»[Í”s{ÕÛñÁP—[ƒCöŸÊ»¿¦»ß½ÏñÅ:nåžç6âjù½‹IÒ1Í-Dª±ÚÅó ƒ 5ýbbS ‚úÔ°q Ça9ç¿­µ­Røšç¼MvæY_‰€Ù8Ôœšl¾ f„?ëQ¡øËô­dA?êX­ô²ZTpêa;;VÔààx¥p«‰@"#íêFP.å²t4†ÉµP(A/. Â&hòw±¬šŸKmd‘Zl5Ð(ÂP f¸'6AØÛ Qäb\¥Ÿ(ÓõXÁ&½’?$úÕ¼SÃ^n™”>×ü—¨ ç?¼V 9dq9ŸU…“•ÚW<šhˆ±µ(GòQZbKuU­6E­'ni»‰ÏÁaz‘79ô§À˘•v·!ÿ~ùAÊóçæÝžÓ1m´æFW*`Š œ¶áþNè0ÄÁyUEÀI¹Ü–çbø:†ì»ÀÜ-ÒcÕP„‘*Ñ”Åa?ÔO üÌ®x4‡ã¾aKÞ%¯•^q»­?OˆF¢Žá‚Ab$‰Eˆ€vMâbœÓâJmQG(~²äSóëj¦ -oAF|9ÿ:ôž€ê*+®‰þwlñÿ•UÈ£&;n«ƒ?i¦|{¡\a0ýqO0*µ•‹AuoÏvP®ÓãqN}_$Àw“&Ú)˜†­„¹ú4íWìéB–šË)é0MfoIG$ð“q°2N½G†[DŽðòä›-)Q7!9—p™ól¸ƒþrfDÁ ü`v<16DÇ=¿›™æüøH=lØŒÚìj•]øø#"‹¬ g`Ñz0oú6¸ñÊ•²e~êQùáyÃl¨‘ÄbÊ16û‚ùÂm>znL縘 5ÿû¨¹Ñv‹N†Ž ŽÕ·ÐKcé8¿r,V†r ï‡54 i<Èô™úKTœ¥ÄOIž"".v6ÐÝnjJᨿí@=ÿ÷"gP‚‡¥“¹È÷‰V¢ š ¾ÓEïá_1W&ê *Ø;•Æì` MmÔ+v}—›ŒG̯òÅ(ò·˜?]Yù Ö›ÓTP`¶«(]G‚û˜¥æ48–¦¿Ï©Ö >%&¿ç]Ø_0¤Îü‹p¼>}ZÉ{ÄB–8'çùt/¦QbA§’i`m´$šM¯4Ëbred99¿màñÉiÇ tJ©p~i;þ©Ìÿ  ¶d{”4Úv Xêwå|⚆ú‹–oÞ™³´A¿ÇÊ5S¥æÚ7y¿6ñ¯ ·7S r0§ö1CÊt_“)úë±[-:Ï$f•— ¨ ·"Qc–Õš=bµ*>wŒp¸vühùœ:4¬®CêáÀ¯Ò¬±¶®?1(fNˆw…,2î™åòñhœ]2ÆMZ}&[ö|ÿèëÈ^+¶QKÄZ)Üq%V¦“c IòG³¹q°»o)Œa²†ò¨ ¨õ„?ÖÛŒ‚®èˆKÛQ¹q+ÐãvfP@ÉÑ*” BY ÓI45‹ryñVVüANðyyÙ4¹Ò2JËÏ\Õ£•­ÁÅ"!¤;Ü´œ—vè T˜í·&¶(«ÏpJ‘Û¯«õÛ)³¹ù'¹©ÌpÃ4&Í:¼‡+v?š>)ÿëÁN4B_øB‘c¤Ît@Æ«Fô›ë< g¯ùöá×錉×Ìù[†>}ƒÎHšmK¨H@¢å˜,sHF3žsëÙUasĬãkãhj•˜òù2<ÀC”‹6X¥òQ…0°ÄŸpF^p}IÑo£Ö PúG¼‘ž'æÙ F-ʧõ¿þd:ñ$‘Pµ€hté5е‹öñŠÐù>zKQòôjÏ&Bû8Óí®L&¨uJ÷rGÚ…ÔùGAL,0p‹»ÝËJ¿í?všÓ\¶ÂỬÝpz^Å÷C­1ÝŸß±[ŠQh^½‚\ozhûæû f6î«uÛ×ã ·­2”W}QáÈœüääŽþïéžü“’B‹>úèpó‡Åö³íÒµÏåW{˜}£ÍY½5g/’ºÅyÔžv”dÆ!%b‰¾;æÎœìæƒWˆc®¿SFH­‰™ÙÚ’MtÌcÉÓû½Ž 8pÜ<ˆhð q°JºÞK̘Ù.äDVíÿ$oÛ „@ò2q 3låS Ðh¸Â.Ñ¡“!ÞFIhBîŸ'-”¦cMîžÍ€e'"ÎOY0&[aÓ7ê)B›Äº±GDÀ½J/ˆ ×î²ÁÝoÒ&q……cîÉ›ÌÍ Ž°làW¸!ZpàN ñõY›ª,îUiÝ?6ålv‘‡Þ4m`sN’læ!Ö¡™z*çÇb­¯ª??aËP¬»L€˜Ôˆ^°+äǰlä±ÔF°4Áf ïºex·»ÀÁ0ß?IŸ>úZ዇L<1+|_Ô!?¿nÅ]у» #û£êȸ+SC§ÞÏß^£ïîN‹3})6)¬ŒrÖÝö¬CDaßæV$åͲ٦›e5n+{°ÓÊï 3e•Ñsû¿cÆ'véà,Ì  ²ŸŒj̈́’Zò‰Ä_àï,DíºCǦéj#®“‡½Aðy™ùSżgYÇç5üNŒøâùS»i=øUNWé^›ÊäG9doSÛâÄÊ:áú-ô¶$Þôó ûÓªƒA¾˜[n-“x1})n^þrç{–hû­¯6<¦¥HÞ×i¿à"Qw;Á"›úm/š²ü§ù¢aú¶œÏKƒá¨+¶^ßí×·ÐaIU*”Ó®°jŽm6äEĽ’Ê2b„“…»P¼{MÎ)ê^ÛN',ê åíµa¸ê³ÄéèÈ€Ÿ'tkµ\^öâ6 n¥¡N>®*ÿ¥VÅÏb*zœ¶ú;™¿m‘%z?Nƒ€yï ëÒÝA°R8ðs%ÍÖf¥“vP”<Ë%w-ýŒ¶ÄÅk*¨'°gýgX›H„ÕËíð¢]—ñb·¤RC‘áœTƒ³ ¼/ Ôaê üâ¡37qX„×hã³ 3¼¡ýB¼}¹PÀ8ëR¿~Eîl) ióŸ‰{Z£ëQŸ4Ó;桽vÎMR¹ÿ­à„L˾PÿýÐi" ÝbñBB¸K0¼õØ"ãqR?{bnaLÈ››S ZêÖ.ýÛsòÐé6ªHGœpy®„­”û|ËŸ Ç kPh;»ÇgƒWHñBôyQDÞª#i#Drs´gÝõ›ïY-- T¡hÁËeHÅfäjªtsu^÷‡&æ”Ó Sö/—ýrÿݸíÇ[¹ )üì6¸ªè>>M”é ü¹­çx©¡luѨ =ƒ ÚX¤tmÖõ«{ÕjhXضîÞY.`B¼je,f˜?{ O—C.p§[Òm˜‘o‚Ÿÿ¦¼LugPŽàµ ' ï•™ã`ÜI4ˆæ´R M…#.ÉâájZ YI;ˆHèîµhÊ Åfðç‹ó™íÊ­ÿ¼3ø(€ê[zš1Ý ðâCïŠ@òÍ¿=øÅ ÝÚ×zóF|Õ‚m²ž§ýˆÐTÅq¢Èr=ßgùÁ§€©Ù=uÊÃHtšÍ†Cºn”GÌ BzãÇ=v€=:̆¹ì¢£ Êsì?tÝ6ÕîÐí (!Ñ|è¢@g²1–õµ¡ËÒŒüX{‹3~êùÝ©+6~‹YA“™'SÔù';9úîU„Ç9á„fùpÓ†~,€ÐBBöèlÃ0¦“"ê4¹'&ì”Æè<ÖÃbX€]TÑM* aÐ0ˆ‚˜ òmÂï«Þâ‚ÕèÖ-Û²§ÿ²“Éò²‹ ý‡0§PIt]Á35a÷¬#q’õgÞÏ:@Çè[E)'ˆºî£ÛN?’·ì î\¾#¡rõÊÐB?óD¢ÍoEÊ¢ïµg¨õJtœtm"÷9ð$µ›hɘÀwпJ9²'{4H#©+3Y­êÚ9…"#sÑüJx1D©PÇTv¡ml’˜•I‘­$u ˜lˆUÆ=åê—úºÏÐ]MKÕªžŽø “µÖçaÈׯ,rmêHKˆMy+Qþ©þo'£m¤‘ŠÙÀ´Dô ôZb¢¯6LÜ%ÀgZëÂlgy² ó·SåΩ{_ š¯j¥ÓºcÄ-d9–œp÷ûh òØdÅôô”ÔqÚ÷tµëÔPYÀËxÏûÁê ÕùÐȃÎf®Í+±ži-•O–‚TEíæ½VÚ#(Ô‚%Ä×ýÅEªMÍóë.y[<¯´·ê¸%ÅV§b^ů¼ÙÁ""‰LSl—“ç 3&nAÙ«IÁ©¶SÉ7dKŸIÔ]-m_SXTŽlœ›cõØפ=BÚ.íJŸGû¸ò®gnÇÄV3ª¤†;  §L­cÛ-z?˜ª«ê¡³Ê't£ìøâSÂqZH’¥Q#¹’Ã}rWN KBnš˜Óö§ä/þô1Å )×Ò8/ÞœQî7Ò­¿C¯éæTÄ×KM}ÿŸ/p=¦Ø ß4„ï¸ N–{°'’chcµ”Ž÷iç#ì`[ Žry@ÂzÂd~jì|~‘4Å0–8VÜIÅÙ; ²„“‡B„ÜÁ"?àr"f`ÚwùI¦éúf´Š;ü$KØÎ¶_nÌíuc<¯/38"ˆ^Z/úÚÐÖjƒUœ~z@:Ê5ÿ›fIyëgõ?ë–crè‘3ÜÙP ˆÈÁUó b)Þøz=*B'ˆˆ4ÀÿÌüsÕwféËqÌ›.©†ô9Ø?ìöŸ>Šiì*üѽLÅh mØSDø,ºŸ€”`6¶²¤ Ã*×çqørÝ’ÂŒî¬ñ .,ÌŽ¶\ÌI:Œ={Ö\Gš×z7õ2EÚ¸¨¶HÖà~—ÒÊ}É”>Óì÷EêRòEJÎø~ÐZ¯¬œ"½D»•&ûýkàÐÌKϽ]Uc°—ï¸6Àƒ×ƒèÁ95üåÁ0mÁ×y@õ RHÍ•6ÈoÒñ‹Gz'Ñ”€ ¥\ŽÞÉ,7‘΅¹‘ÈŒßYñœTSުأ:ÕÁ µ÷2C"ë,=f° ‚‹•„úUzË’©Ð…ûÆþ¬h¡{æ.¼åÎ;½”è¿k\M­]曡Ã\Þ$®{œÏÉjó9IÅÞf7ò&½Ãœ@«Ök0¿ó£y!ª)v®Ë\r×I ¾‰%ô¡§ƒkfqiC„œww‡z½µÙ»Ä/œn:t@Ì‚F.&„Œ3KºAÈ'ÿî0À{Á#àÁü¢DJc`Ã{ÓÛV-¦àÀhS R‰Hóídž8½¶„'Ï€â»a/ /Ür$\¨ëú+™!Ë¥’Ĉ Ú›da1uê'ŒgÜ”]*dÚyà Á>BvÈiÍõ1ÿÿIfjCʼ" #ŸöÔ^¸¶ÿ›Ï¿†Ö°AÈÅç>-öDaê%é9éÞö6-lnAŸ 2=†Äb¢íÀ²Ò–ça[ÀܦnX,–i§ü(• úiµŽBæU•@æÄlÞ=gjšµç_™ˆA…Z†¾jEåIŒ¨~RG©(2<2à—í‘óúÏÏ1˜yŠ­'ŠÀ+Á õXÇ:¨0}ò‰ƒ¡â‡Æ8dŽè 1âÎO‚ bFtÁ1sÖµýÖ±8GÕÍ©ùÜ/ ñÄQ‹/¹sô‹aÌjNõZ´[šfp«_¹å )µDb…Ð K°ûå±Õî§¹h60î°ÉÈ…J²:t& »²—ð ‰~–’ã{µS<t¹R´|1Æý€á¬O¥Ys$ïC•þÂQCZWM3ê–nÓ|ž ‹úú׿±óÁ„)Õ#ù™†b*dQ²õGÝD …’¬8÷IºÊvc UD{åþ,A†ê+b«ù…mãPòá9©h0Åt©•¤I°1‚s8änß«2²~œ B÷Ö|ÈDtv:Ù§Ô™@¡aÕl”P·‡XlU±„-ŽÀñ‹ HZDUŽËç6ðWhÏ ø)Ê<â¸gMæ .úž¬ôEš“×rؕԢöñÚšáÅ_I¿ÅÔOq<¤E·ÝÄîOî ¯Ý | Æ:ê¸EØ´1ÒW©Ô³,ÚF¾µ§±ÙšäsªÇÆ×Ýë©~ÓeGÆ­l©6‹I/rýÝBÑvo…&à10+ýsNÛÍà›‡u~¹ÒÏÚ’_GÔþ‹TCÈ5ä8¾D(=A·Išnz1!åJÂ]7Øf¢K[Qè‹p&V¡Ó¯ØšîÍ/V¿g( SFŽV-{@Ó{ûoÞ€BÇÄÒ·h¥;1\ ßv½êï³xmLc¾›ßªÕ(oy"n²âv§pb¬xày§c/ Æån¡"»eäi¯TÕ¤xµíðËë¥Të(—ݘ†!am8ËçÝ{Ù‹n«‘™Ñ!!/r ¢ãJKÕ:<åÉgN -:G&ÏÙܽ¿Wq“ÔÛ“¤2µ¡‰\¨‹E‹5G†Â uË£© ¬ù@‡ÑÚ¾#A€È)‚ßÿ`É×wÙ»(€tˆ±à#7îÙ4çä¿úZ[l0d›nªù»™ªd‹}Gá|˜èÛÂí6¦zÚež¬«Ã§2½çñG-ûÞ,%‘Û]‘÷\ Õº‰#è·îÿ–ŠHaP!ʧ³æ¯ ñ,J)£{B¶¿ò†Zºç!}eÍØ‡,3¥:÷õ>z]›¾‰Aaæoõ›Üi "CßëReÌŽ¹Äm«ˆEÁ`™3ž‘Ñç½-“õ¿5€Ð¯ˆ(7Û†ûNm* -zŸÑÜ–ÔQ¢Œw¼ à¶Zæ]Íh±Ãš:W%'*Wþ̵…ucª$S(®ÇwDЯ„-wØEçÔ¾Pú4½~÷[{h‹™þ‹ý[‹§gÅóÑœØ6rÙÌÂHÊÜœµvp24µÊhÎNm+çꤟý™¢®íOq}OÒØo™³uZ*ú+ ûÿÜ•„ ·•£h³·×‡U90 ›…4¼® b-÷DØçÄçë'ý Š^…‘áÓ!¾æ†cã•´¶*¦Onò0éÀG©¹º/Ýâñ(˜ÐH “½ âg~Z‚µÈo–h7ÖÞ22y‚µ+1~@jµ@¨òÂt†-Žhrö¬LGa|"ðÛTJYÊ"êž\¢yùÜ€møµáR_S‹×¡æ²(9ND쩪¾ûÍÒ·¤]šoAªˆè’äë ·gg­îàX^êÄPñÙ§fa°.yÌÂð僺w©qµBÍTóºj0üqkœƒp¨¯ÒìÚ¸DsïôpëÃ_?9xÑ/xºKóÕÆdM±Ððc¤•x9MæÛ7$Á/¹ÅõÁÊP3ºE¤¨%ª;,æÅš— xb™y¸Û¦ÿÞ0ȱ:Sè_hª»Ã@È4ã¢õ9X\“ÛTüçüï0Vç^µ^©Bï×¶îŠ÷šºË¸éþ¬û~åB›xFÁ»^€»¢á;>„äUÔôÛ¹fúŸ¸eÍ9èyê²Ç~VuŽ;æð^øì¡) ZYÍ”Ql n&9&Hls+’Žc{”ÆZ£2cùn¹aŽ‘„ å0n59pœ°Ø{Eêê/X«Ãm¡è«Óµ™ÆS™v¦>+F¢¦¸¯ø²ÂïvÔ&µ•ëzí‚b”nÉ9q¸èòœ~äSOøª }5xì¯>¯‚14 Oç³ @ƒ;çõª‡ÞÖíÁ™ ~úk„ÿ°»‹¾ÄÞãF³³³Ù+s‘"{‡Ýz‘t…¦ÝJÍw´}úŒæªßÄ5±Xp3#oœ:åZt®ºEŽkÈGaoœ¿uîN6o ­°‰E¼WŸî®ÐŒ(4,{º;põ4Ú ”ý¨ª¿€§~½6oŸÒ™­½×t”MBU bœ+^d$/Þhdh”—¨R' VÕb©¨jüSÒs†ûJºÝ 7»´ø¥;a;½ÄJÔ}„Ÿ¯A%³ÁÛú ŸÜ‹#ß 22&i«ü¨ùªOÒ«oåÖ¥k‡õ`%R¨Æ ±j÷°8L×õÌÎñ¸ð”Ë*>ÎSAa—d~d•F‹[¸ÌÿT9¢²þ]¿'-§È}ŸKªÑy-¾ñN‘¸‰zàü·äz鯯Y°,ÔßN-6¯©Åg3›ÔŒþ‚À.Ì tkxDx¿;fZ#GUéNÑx(P›6?c (¸H§s†³Š4ãŒÞè¥d²Bk±ÆŸê«û#Ø®/•rì¢àƒF’(µ—áxóY•‰ð×ô+ˆRùÁ8ô™ë.µÒžB²î.åY®…êõÕ¢ÄçÍN_:a9J«…Õ¸*p{±;w§.;×R˜˜@Ñ2Uh„ÎìÇ=£È¦âøõ5–óòíµ–0HÊýêŽp²Å„l rÒT·¯™Tûe?E:âX‹/¹?—ÆúdV3ìg—@ržærVí æà]ÿ:æñ(¢qæÃ ^eÿÓ,ʬÈSÂ.?îu6l§•=¤ƒ™ëàÅìZ΢îDΆ™7°' a&öUê” '×c¢"&]CCÐERæ {û=öuǤ¦0Ý m ÷Êà¶§ºüq?ÉêIã>=!6€ÑXl\žÒšW µ81'úngÅðP¡ºÑYËç-"àõÀŽÁš©ª¨+úî>ŠgU[ùéï‹ì°/­)wSª¨k70pMuž]ÅT þØ ú˜!õ1Ë®ŸG̈ò —}µµšÇ6Ž®ôâcÐnÕx "V/â?g®çqIbò¹a€Š×Mš˜‚ë@„ÿ@›ÁË•¢BÙ¿ѽ1Qb­ù BÇÊ÷° ÚÇ»™ I®_L9º=.õÆ<•Ô}kAP¯žsïcñZ\¦ ‰"ƒ¡0çYfE2S°~pA`£T5ZL$*¸AÊŽƒŽ¨|НŸ. YdS¯¾ðËúk>ét'È&dî™ý€|”’»=u/XïÏfÐùI@ ûKH•üȽËü :³\”eqFÓ`HnâšœxEŽØ¹¹?ûøÕþ2p6‡{ú×ÌãÎÌCែÔá…þ­1!Õ±nù€¯†ódè9ÛäêxÕ¤@; ×5êíìZìýnní}r8Ç¢šâhÚÂiЀž ¼¨ºst¤Ù¤”‡ð#ã‹Ñ3¿!¤HïÄøEõÅ´Ó· ¹ ÊQéÊÓò€U…ý‰]çœÖ¡xâ“'öÑ ÏsBî° Ö 1Ëû©ml7H –È  aÉçÝq†¼ Ÿ¿å>‰ëÎô=§üNOîÒòàŸ‹ÓÃoëóò;,”×»MØÎ¸ÆÊP‰öá–Xžj†<ot·ç{ÙO&øØ&(«A<™C¥8'¤žBí ƒ/ï(Fë21 Ž ìð…ÜØåw¦„Æ›'ñŒ‰ÏoÁêÍÙOÕ…_ ‡X»6€å §´Í–5þGþr\:&רÏOXÂl Ï-¡—M µÕÔ9(Síïn½ü ¦Û(—SÇ¿NE¦‚Éèñ–zHc¤©“À̲z#Qñ]±/ÒZ¶@ú^'ÇòÌ‹¤5ÃzûµüѤ+]GC~…F]ã¡ÖþÇJ~§SvÎ[Íüåb~e¿ñƒ6$Ó,žƒkù ø-ï÷íTŒ/„Øu¯¼ß[§8M,ýÞ·…¸’þÝý¿-aTƒ¢µ¯¯ùd¬±|]V¼û·ç´—8ȺĺÎ}Váf;š¬"Ãðcè'þ”—‘cxª ôÔEÕ EŠP.رy]çTd¡™ÿ‘ï=BŽÎFZc°÷NH|\ùµ¸ôv¢tim¸>¹¡Éì|A…J„Ã1Ž ÛÔõ5¹a=úöiFáƒ4Üãqº;*ìMÍÚåTùÜ7 §ñA”©;Û0 ‘Í- 7À¡º sàŠ™¤æ¹Š{o Š}¹Ÿ´øÙ®=ð"‚¸vôÒ Ñ>|›P[ñ!ý1kI¦¾H\[x³%§Jlœå)…9YÁÓ–²k£;]øÉ”‚gìŽâÂï)å+þ+Pøª7?‚­:?‹o¬$ ±hþyü¶ÍéyC…êÙÞöls‰}p>¯ ʳ†nþPJ‹)¯ä@vau ¹ò4+³¾ÞkÊøÞÞ”˜»Ú«Nå”ü6¤¾J€¨Ô2^»pÈ™vcÃ#Iô-à‡¦þ Š|F´š6“p‡ kuÎÐý_žÓ¿<ɱjàye®¤¶—†Ó»|Ù[yñi¢xèݽ4θ¡]8%,Fß%U­ ©pðïÀ›ˆ )Qx¶þwø¨ lsYˆ^N7Ú¹ 6ˆ}âžQ;9bíïªÄ6«LIó4–K!Ùr£UòÄQD l,½ÂŒÿ¹–0"³©øË-Y7ùMBt:çZLsr½S‚LüÓºd&îÚiJ|­Re”8AyÓrŸõ2-©úxõPd`:’ A ä ˜F&"ÁÀÝ<´¥;EØç1³ŸµWÏÿùÓ¨ ÌbåyÒ;·®à Á{î ²v³Ï我ºX «˜ÏQ'‰[çuHŒa¸¾³¥€¦ýAº|5ìÓ¾/•åUŽ$—Y[ño`˜ÜþΓL 'Å¥¬oüawû‚GHÖD‘¦T ®3ƒÜÌù=Ðñs^sÖ•а^Ф›ucõ9ó#A 9 %#úÇÑí맘Úâè‰0Hjy‚iÉâùÚ¿åÕÆuw`'³Š4hA^1“=ìÒ zõe².ORK°[îÏô_tÞhcn: «D}÷( °× $Xt‘ »´¡óÿñºÀò|Aœ"t- ¹Nè­¶T¶„ýEãSi#ù]ª¥€o°*cåíOÄî­WÌs^8Ñçî—e«©t"±DFÕïfT¼í?8¦Šÿ¬;¬®À£âa£Å&ØfÆÁ%&ç9™hå@ Òl”¾ãaÛµ<Ý ORq*ꬦMÖV%G$ÀÞ…9.›\2ÞYŸ“Ù'sJ²»wŒÁ³b¯Tg#Ÿh=¥výA€s-Õ[ŠO’‘ª¨/§ýáÈOC¤y"\¬7ôãÓgˆçüds§=£†¸§7º`•™ànßÞLêFFD€"WÙø Và…Îñ2/–¥„|šÀ…ÕJ*×xmJíó‡ET>$8°äY$¿ªÓ"Yavè“zýØðÂ/A¯ÚųÒ:ålÕ Yù—#Àõ§¬ÔYÝúZž­FýÚ=†høzè–ÿì‡õýæ¤Yì_×õÀN5Ifðà³LiƒîgR\Æ–°EÒ³ÊIýƈyYÁp =ö :=5 Ø$ ýG 4Cêƒw4 æªI?{ÎC1 ˧æÀz…âRë´/ˆ%îÉëj>¥­ãJN0|ð"µ¿#ª‡×q fl¯1O Ÿôý±|:n—ØcJITµpe_|âûÙ#掎HwXÍ·õ@{G· ¯ÕanÀ6ñÜ$}HTZ"K€Qð“,§[Á­Ùs·Žï>ŠÅÎ)‰cÎöpñ§ñŶד·*м£´®Y²ûÞ:qÇ éŠFØÌ­ȈU2›I€€FÏŸx07x™Ëzàþº¨‹Ãa"ëà·ïnÁµy[uY£%¶Çm¶Èübß(ÛÒ¸$Ä37¶„G„åH,›òøé|ìþ*¡'=ö Hõ¬ÖÅ­‹þk¥½(i†î…‚`"íÑúyè^ Ãíƒyf¢_'ÆhßÒÆ7 d?‡&…ïqÔ›¥L…2\Mx-pZX¹aJ¾×Uµ“=·/:²Ð{êÐk› ×)!‰IñýÂ"bŒË²ärv4þY×¢2 F20N$ùY‹âÊ9Öþ×VªXò º:Ö‘tø«Ç°HCR,/}níêí9Ø6T ¦ÌÅJN6ÑNÔ‡&é½9DT8´ëõæbx½> DZOqäÛUrz@þŒ>X*¶¨c›0Ð3‚¦QP§¦Ó1÷õžeds?©vXf€#oà%`Å+x/}èwyÆšç¢^ØÉ"×¥ ½ÍÇÔ@¢"«2>oa½»€Y©`› Èt3“Çrϳk,­¢#ý/@i›KÕó¿ÙVPl<˜(.Ø0´aÍYÃU·„öÁp5oÑK®ó: mEC#çT™ ôIVü9 üI…Àñûq]çynƼªá²|y“îRiÝ·•ÏfÉ7U²ñÞNÇcYbŽ,:sóPÚY]ÒÄDï²d±…|¸X伇ÆÑÍߘ©â®üenÕ+¯ž3ŧü_Ù…ý—Ôþ^BÑ`s˜åÙ¾ôñ*â‘Ø6˜¶ØòÖrþ¸-ÅrŒ"€»}­µùVåPèv&©¯Ížq¤à[áÍn‘€ÂÔ¬õžGÄLf§adÙô7{×­¦o« ¬úü v‚ÇKŒZ]pHAÔ*Ž®ÂE˜¬\—·ÛèdfY—’`û0‘$ö¤ª½bvoI#┈4JÎ9ÖÃÇœJisg?Áöcc<ÌH­SèKðÃçÁó$ïU޶jSð4»‰/è9‹,Û¬›TYE—÷àte”©Éå2 LøÐR…Qê–Àœ2­  î<Œvyö¡†ñ~˜ÿ]…²v+RFð… 9D6½@„¶ò×þºÖy8µ?%Ô7¨}§ôômCTg錜àMÔ^Mý›“)N'^5dDß‹7¢åÙãuð­Ü êãÁµ?¨NQ«hiXD?¶°«·E«ê_p¢ “Û‚%*— •u”¥=Ïœ2 Ùߞ̱e˜n'ò0ºÑk/xÜpzR¼yRÑu§ÒcêáõhM㶸jò¡8òÛ¨fÜôné’uû!óË‘(óPD,ˆ ˜˜ËÁû[‡¾T龸ӵì6t¾•¯Êd†Èò7ÑŽÌD·¯ãñ&hlÁKãÍ´&ñv8,çÏÌþ®/¸EzÕ¨X ZùÔØEÅÓ®ªóð|EK7«Ý+§ÁtT‚k'Á(Êh•9‰Ð¨Œ  "³óDž=~íʹÒ]¿]Œ5ëT@b,9w}æFíWŠ,Œ×?ÜÁ…{úF\¨ÜË}SG€î“¼rz¯¿ÿ¤ûýfž±¶ +Aþþu\2´ãÜiøie±‹†…•Le4 a̘\ ÷_¯t,ÕÊe7‡6·í]¡X>GA¥øžÅë”’‰"¡3ë õf†|ÕÔ;!M¸qn¨vZâ%yÆÜbPè]¿R=Ð|mB ÎuNÓ&1æè¡^ Ø,]ÇÛÔ„D•Ò.XùéøNTT†œ¿¥ß_Sº1ïÎËÇ@@] ®M °DúÝæ˜ýŠ@€ãö„¬¶Ÿ»lø°©ÝÁhn7g¥¿e!–ØÜiY+vžÂŸÔ6w]ɼƒùrav ¥š³D°yt*2ø)WCà>eR-‹BkÄUc¦<ÇØ­xÏ ,u£Å´Øâ ¬¤´ÔÙUÌn!?•"Q+„HOyÀ!³¼‡@µ>0>*C4HÜÒTo•ü¼Ów^'—™Xµ4WÀÒÈ|ʨ'8ÊËÅ5Ó1u?Õƒ<ÛÓë¯TC2ž‚&YHÂ;Ô}^×Ý…©$gïᱺÍæ3–3Ñ ÅBè“é•Üán.X,Û°Ç–£V﫟Bñ^¿µVLÚG¸ƒîh9ùÎÚì)ÿü*ÆÀRMÛ2u9~"Ô…Yê±-¨Íµ½•§R•ZÄô@¿›œdŽ´|†ª¼ï¯ 3J;TÏXešʹ °ÛMš’^aâ·ü6Dõ²,6ª÷Îæå–ÞI (!8®ƒr9ýˆS¿²i ofM^âÞ¦Hà½lÏ(dôvŸ¥Ü“õlÂ×Éá†ìI’rQºÛù𗜠…Vß“Þt®fúݲ}¡4 ÈÈ“ñ(û“r…“Õ¨|<•IQöæ’{ÿÏlwóRä}'-P¥|ô…wfã)ÍË,3?òц¾¼R¶Å™€;¬eTY¦È!ä&PòäðÕ¸|¡KxÚÚ]£ïÈ.Äjƒ £Í#ùóËß•\’&´Ë£ðNµÔ„ ÖÃ/wŸ (V䃎iP6ýÏÒcÕ-ÀÝË3¥õ C6/+#t£ '’…“xú ù•;ý,PwKuˆôZU‚<(‡n$ăC!7áöZAŽé,ráxngõû‚Ð"Aƒ¼Áà°/ÎÃzºàVFf•b«| ²Ë|ì`¥ ð¯~Ñ%PäX ‰QpØ o2FS×ýkü~Â]­A¸·VâŠá°ó§‘nšß`Ô#ý"b¼éÁû½.n,Ý£Ò59æíîX\Ï\è rHŠ›:<ðnz±™6ÿ¢í¼2+8‹“9¤kÛŽëΝwÌ3÷G¤êœ³»¾„_Ù³¢²¿‰6¯{²‡÷$>zˆ¯ÕY «<«B^ ÙÄY:=¡~—DÒY«T@N‘ãˆ1Bœª(~vÕÍ$ 9,HšÃ¸Ö˜o¿nÆå¡9žn„A³Ôgî%lž?QªÎœe¾¿Ôè]K‘s¥ZÍ—aáé‡/&çûTGŒè6÷¡jq…˜A‚†Ys(%|<òóxúØ“cÂÖî.®q|†Ôƒz2z³7!Œ½¡÷‹Èºÿú‘î™wyÜ„þdg%ºµÐ\pÛ?Ÿô¡þ·y´H/vhw`ôçm:)¡®–]-\î‚S¡~±%‚ß— zço(‰§}Þ·šƒ«–žžÛîÅkÀ£J,MË3â~&Œ3[ވ◶rä.€˜„Ï–EgO˜GsP›Ao'(î(cغV±¹yV¶š»!óyšAÛÊšJ'9Íü^U܇ª=íþ‡Ðx–/¾Š<ÇèËÎîçµ°ƒ$åºOŸçw2ÝA»Çß=íŠO+‘—V èÖP}üL±Tì'Z2ÇÑÁ „+ÿsOÝÌʳ¯2nXÙX Ío‘×ðгs’òXµ&!„?\NzÖ0aß’zožÙ2šZ•-;&~ÉK› !%›&/É&þöÞ(2~Nµ"#iQwL‡©õÉÃc ¤®ðÌ5aÔúM¾? rÁôÅÃ>>U¨„*yR,bpÀï ²jÝ‹d–ÁÍ{Æb?ubfqg±4ö•[i…p€¢Z9núB3Q>4²µ]G«BÈåLW$ —SÏ»w»)è=!éx·#«ùÊ A^GÒ 6ãßl`¬JòDÓ] ¸˜öUŠR–Xõ•4^N¥[‡ÔÆ)ƒèàµgi§×w,«^gþçÑì%1Â]î(n×"er6«{fÍIó\¤’¥Ýz[¼¨æÞÐÐôyå÷ EZšÚÙÐé¢Yƒ¥;¨ÄºËÖ„µ«Oíidƒî¤Ùz4k®ÅZêÌ™3K!Êl•¥ÖNdoEÓSÙY›ÑßvüÆ”ö_—?<ð!þ™•ú:O é{ìåÆš}5hnÌ6ÄO£ÇWg~äŽáEÊ?ö÷ò(‚”×bs?t³Ô]QYÆi~e“këy#µGÞÄ7:¤/íÉ$¿2«Žk[¦ª…{ùu œCvȦ&MC–sÄA(‚U]gXVx8–N¨Ø‰[-âb85>ø×ëúß#Ë 6Òƒg¼Ûnøelf¤Å¡sׇyXòש.°´03h?·jB޳GÍ\úó¹¿6ìYfäü§¡9eˆ)âë2‡‘ PR†ÀÇçIÅð1º–«¡˜ÌCkïwÍmˆÔÚòq­sj‚ɤ|¥VûBÂÿ–gö–,íØ= q%ø›ŒåÃ$‡ö*à»Û’~GÕnÁÍO®öxÖ×W.Pg¯–é h‰J—½¦6HèÕ­*q”Xë­)ƒ¯î¡3Krõ<±}êVúwxØ)€sÖ©MÓíð]'GÛ%s[—&4úïÉsÃÿ8÷õÎ1ÚÆc' ¨òŠDF@ö “y$2cÏ~ˆhÄØÄªIÜz1¦7°Œ—$‚³`»#~e*e1P¢f‚QúZ¼ƒèµ;Ûé$iÊ CÐöA)ãP§Ò:?Ýwö¿kæ®ìä“|òö€¥ ˆtz(s_¹/ÅÇgØ'蔯8®É…7ÎûgÈ;¶Y‚«IlgÄÄ0> û HæýŽ5aø£'& v˜Ð<=©˜G˜õ²$ÙÂA&lž£g‚ƒ“‚j ³•Å–Ê&ˆ&ôŽïâ0‚FרîÀ¨¤ ä1Y@1“zÇ=ü"‹,¥RRëC%EÒ̳M•¶˜:V÷YcŠös¢?îÈ‚÷MôZй2rrÑ“cä/nÏ’ ÖI;ÒîÕ­ajêSg09mëth†St»6õ ÄQ\öÞ9£cªz¡ÏIþ ²>GbÁ”ûMU‰Â¥îŽÎFĺ®.Lî«™Ð"=ÉÔ÷ ãƒÛ±æg)ÆvO¼·š0¢‹g ]ðÙoÕ̳ÐdZ(’¹°=s>:ðLVsOE±÷Ý~…}Úªf±!H«ÃCu v¬Î؉Eš[Öƒ"ƒ¼ð憸ZÉdë!<òÙçðèÝŒghŽÅ°{´tNñ4'²^B7ø/¨þ‚âH[ãø‡D|hjÙÉOš*T–¡&z …=Ë4PåýÜ4 a˧O¤"|ZýÝ^=ÿ¥‹”ÜíÓ¾zöwß cä…€³^ÌÒÊ+P÷Ókúk¢3à=~ƒ©Øù ù_¢Dq–5-[Í@£WùŽæRØB·3ä¡7KíýԞσ4+jPý)´]¿KlKj¾É^Bæð„‘çaËwt>Éýä(ª®UûÞëü&#ÆßÁ@#œ7—‰ ø{|AÏV®¦Xô(^J¸|ÿ­Ð¶Pßýàìí#‘³aHº"ZgX^)§%' ÚRžʽ÷h:ºmžÏ•®¤ëÌ…]ÈlA’-òòÐ#&œùjëšôX÷B2öÀë}À{XÝ~ViÉ9-– /ô,‰‹í?¶yv`¹ÿÉŸÎÏĤŽ:;®3{Óü_ãpWqå A 䊭¥ògpP=ã÷ø7±%…ûóåeÕ™Y&Y½ñ~?Šæ•ŸEt2à?È rÇATå:…ö{«QÓÙ®á£ÖX’+Å[?:]¶(°XÿD]·€ÁÖ5ôit Éq°ÎŸ¿ŽPÊ?‰N 5€’ÝJ¢¨ ܃X÷çç%““×ûç'š jŽÔ\ÜôaíQ•-Á<Í'È†ä ŸœòãRj¼}*ná~ÒF`M8[UP ¯L´Ãí{oÞb5áyCÌI GɤB±Q³ wÌž¬W¾X¤êßõ_Jû 6ãΈë¸Ò¦4ÆdšE×tC¥Ë8:Ñ£ÊQ`ó‚ÂY¤ÿ–ü‡éâß)úkJœö…æ‰À½9Î~Ò¼üW¹uöŇ^Ã9î€"7>êØ@µêÑÍç_ð6ÔD—ÙƒÔà…VãúˆcH•€#þ¿oµŽé§l´rVÂÁ-çi£Â&éýµ/á°Ž¢÷·­o쫹֛¾$©øÖ8tÐ+7”hy•Àfa›iZ㔹¥…"Í/°½^lj×äÕ3,ð çŠ}]C EØÁ¤ÇƒRÊ´¹W\·_d‘xиËóTVÖÔ/Ô‰"¤ç-« ¸5—¸])û‰ ‰cÅS90ù¹@/0ªEÏô›\rD5L.2iŠÅ½–bPÆõ áà17èú6~PUm-ãè®0™ÿè}/Ÿ$é§´uÎÔ]œøP}Yu.8OP®ã½0dG⾚Z*äá‘Ú]ï9ãH#1Îo¿DØ^戇XˆòË«6Pâï¼C¸»fr/©4ÐÆ¿ñGzI–Þ« ž¬Ì˜¼âúº3å|BEÿTÖ¼ÈÀ‰H?8ꥧ¸ª5édšµ¡(Xú1Y€¦DB[j@þô Ì&tWOcvÙܨf‘-±g@Hh07êk2,×å*”øo9kbáìª@iPF¼­UÜUÿ¯C^oäú¼ì´Bo¼0PºÂº¶t’˜AØsr9ö¤þ>$2S¢‡Ü=&©XwŒ[ÿlòÝ[Ó}Ÿ‡¦o‹ôÓa°}Lö> ŸÌÍHRJÄe•ÚC;H'E¼/ H ù˜­¤ŠDÇ}ÍKë Ùþne§hç˜s†{ôÇ}˜êªÏ7)3åƒüÎF¹` ¥Ÿ“±Æ%z¨j_jÂB$Ç¢‰îL_ëÀ9 Õ„ÕT°’ô&¹N¬Ïi)µº¦m[eÃÖ^ùS‰¬{Ãý5ŠÅx\’²Ø‘Â.ÜÅÒáð‹ÀY¦Ç¨R!llÙ Ÿ¦)hØ÷R¤(_ÖAnñ«–y¸áòEBü6O›Žñƒ5nF¨Â¥¬mÅ7 Y·:¿‹]¹&@"#žÊ̳åt™Á—ùêZ™ãzÅê.unqD±zî_:Ì©9¿ ¦í¶Ñ0>iLIHÖZ9öÆ‘FXˆïˆSqn%À'ÙâÀªÌbÅíÊ"ò~6×o+:è£_ò­ópgý/·Fü UënÁ·¬‚…¹àˆÊ"•ùð™É\ŠÛ9d .ýßû² OoYà¾AcICWè:ïþºbkÓÞ€èñàÚéT{þá·I3e|Æÿ F4¡¿l2‚¼©«À9ñ0ÑCm;Ë‹g_èPö¥†¬Æ·’Lh’Jÿ.†õkŽ›¬Â–Še´4Øe¥í‡%/õiœTLÞì7—· TÂ)¦Lª‡·±Œ¼Í¼PÂñ/2°xnYC›q¤½7Í…˜Ö©ÿÙ°¹;ß9‹á%•Òß«¢óD%§ivIþlÛ–ÊH—®`ð£RˆMžfèæ$Óìi¼Ž* M›Q¼}ì5X4“6¨]uIëú·Šeì²Òž[ˆNPFœ®§bªÒò‡1ニªÍÜÝÀðÊÅÇÝžOÖŒ¡&VÌ o„ ètßÚÿ3®iãz/稆rŸ9çr:H† 3u°äOÑR¦Ïed©;ugݼij¥Þü1ÁÑã^œ«zƒ¬a­fj‚âï©—a k‡fsF/Áðɧÿ$çõ˜Èß –ĆXœGžÿyìyÙ'eèÆœk^K¬úçKè6p´9Ç›â7]x j„Kzö9w™?2@“ÉR âòó &ú õ\¡§"ž5©‘nÉ &…GÄ×%³hÔbPÐÅ9·œD:ލèH25l”òªyR2‚gМU†öfåЩDipÿ¼Óhoò€ZyÆš08™l9ÚiÞwN&Ûùî’¿±Rw&(½Ž8 †Ú÷±“?4ÊS÷½º„¹6Wšëicâ²…¢«oÅõ/ø îtÍ!£pbæ ^¬VÕ{Æxám‰ç¡Ó£4itº—x݆”NZݨ?SІ‡÷gùDýóñïD€ Ï­b¥ýâ­ºÔîõÒ[ónjÃ'QÊý¦Ì@Ù2Ðjï`ÉQdUÁyTE¤ï§¦Â`^ÖD/Dûsçæ¨io"ÀŒÊD»´bö ‘*Ë„bu‘:9·žµ6>nq«Ë–ø7!ýIsRL&ü°²R×-ÉnëiûªfXßq¼º¬¼Wd ÉWÕåŽèZ+¤™ö5ïe#eb¨üBSòŒû‚r¼Ô–ªÆ…¯RÝMÔÂ3”?‡fZì(RªäâUÈçèG $ÝÞÐN¹ÞгGן±Šþ¥¬9ÏWîlQŽ5öÒ{{S_½ÍDºªÁÖXi¾Æ§ÿ¦lÍ9è7åÕåÏVÀ U¬!ë–¾zé’hV°ºs’ãmÜà‹ÈªÌM,ö0›ï B5ƒ¹0QzXœ&ï´Yƒ øÇKU­>bU(]ÆßœpË‹,ˆÃÉ9û߇pšêm€…c=ÍÖ›”‡äÿä+Jl‰“ؘeSIYçRŸ-âÙxûåª=%)°|//šZKÕ¹­WÏâÇyú¨ÓÛ³m˜™Akú3߉;ÞR?ŒBÖÆCVƒ/†#'3RaLH¯¦LÑñYÂ’a«þ¡‹tú¤÷tÖOj Ò?Z8iýœzް¿ygïßAáž«ÿ ]6Á #m'£ÐŒ|ÜÓiS|«½!ymPkÇ©KÙ¡öEƒ—º“=„o'„»”u&Ïeü¼øvóÍÈ*»¤•—Ž}exb[¥¸á‰ým’pÒ^_ˉðkH¦³-à?]ûàÇ•Z‰ºâyæaÇÈJeUáþÃ’Þ¨›0>‡Æ‚¼i·9]œu\Y ÒþËi{PQvf߸^Zð¸P…á‚ô24ë˜È«ûÃo‹.H»cŠOòŒÝˆ¢éø5­‘¥/‰0”ldEn©¼h.Õ16çû yOÕíGAÀrð";DÂÛ ‹û<°¥uÑ;寍þ|„`[¢ÔLd»ü3CA´É¹¯úÔ éž”Þ“.1ÅÎP<¼…{õñå7œ="©WîWXŸ?æ©ßáXi0#<µ/µìª :l¹ÜPçxÁ-ÅãÎcH­··Øb¿ÊW‚Ô ²ÌJ3Ý–ŸHšoIxðžôx¯0÷ ë+­%ÇÀ‚¢“'ðLiºÛωœFˆÐ¯X0U5î Š%­•èƒU&%ô¬ÊþÏMþ:<¼¥½z–8Æ5Q.“–ê‹#¥Jˆ[Ía ßVY©…!³ÜE´6ÓÓ}8î–Š"Ùô"·9˜LÏ/_YTl¶~f^x=yèÑÌQ%݆—‘û{iûåcŽ7ÃÕ/[•Ì1ŒÌ<^ñéC‹2ãzXÕÂýºX6†ï÷åß›ž=¿½vQ>éIÑ :p\TÏœ·ˆÑõʳRfæ®tY7²"áoŠÖýœˆé¶¶Ëæðu÷®ãÏÌ «\ ƒ¿}¯Ü «RÂhC 2bŽõHÜNǥѻQÞ¡±€­iN¨¸_ÎX*%ƒìŽá2”³-]*¾ò¬o­ñçÐÌÙ"CC—x5i4{Uq¾ Tšu§’•±èZ®öÉó½Ã˜aÙñpÒ÷,’ï¿‚˜¤Ê+[@韫‰¡ÿÔ¤îD 6ãéqÛ¢\"g7V;LGþLZk1“(+ÚXË,RÌß,­/²ÐÒí6äê`ï7à…˜˜ß|¨Ô•\ ¤}›ssOûq}!Ej½°çïöõŸ'b”°¦Aµžú,æò"õ1 šl sÏlxÎÄ$-¦I‚á’‡®gu²Lu®6ŠWH$/yî3¼Mÿé…öÁ)‘Ÿ0öòYõƒÂ­W¡þt[‚ g=ùI—úèvžq­ƒÚ"Z¬óZ1ÃàHNY_9i¨ìÔ×l™^jg/ [¨‘#õSÐèGÍÏC•3g†dl–ýËHÀj‡âúŽá¢¢ŠÈÛé™Òù!56i§õ "änrD%ÎäFö×Òى̱ñ‚£\‹¨-¼= L‚®/.¹¾×$ÊŸ¹É’%à ºNA`Ýï)“Š.T$3µ9ãNx¿¬5"ñ¤KŸ{³…æ-R×$1عè¼òÔ+ª¶°p¹R÷èP-TÓŒ,„:+ÇKâˆB¡4Ãå;Â"šù²ƒx9ݸ··`¥9ÙÚ²7.½ëpö ûòËacG«÷É£ÞÛ~’~~Ö–J”¶kºË=cΉÅÇÜ2)i!Wg^á“É*û«ödz|•bZïw2ÎIÑUÕUe6ß°Z_à‘Ü„ØùÖ›LJI†zŽÍÄË:}^¸¾‰¹KiñëƒÖàZ³ÿtµLÉ@ˆ™Á€ù[v—ÊíPãïÀôýµÔJÉÑA$˜Âê%Ê7Æ´¼ž½Ye!%¦¤G×$‘ÙЭ¤Õx)¦×äLN¶Œ­u2U\ÇzaÔÚ¾t\Ò3胗ôéK|¸ÛH.,:9ÊoÞº+¨å>Ô©™Iø Uç,ûß JåwÉ\®p®Â.×ç„(aÚÇúÂj²[V¿L*a³-î9•‹ %­½™ºñ`ˆ²A×9]œ#ö]@¹â2ÊÌ’+‘ ö°>[ã#F^¼ò_t iIòåŠü°+:¿Ø`±;@É–½ &.‰/ÝŽxÄp~C£µ‘톻|q,±ã*ïTk4øÿ­8H[)^½—6£ÅJYÊ+ížµ˜RúKG^ê NìÂò÷Œ,ðè]X¬¨hÃ~ 7Ûû·y×Ñ2LÐçÔæ©¦±,à‘ÏZ¦R ¬É$ ÀOÏxô9•ͧ¡³² u(ˆÛiØ•¹PûkœYP§giMßL(¡`LøL³&ßü£R°Íî^ndŽKÞÛ%T®ø\"l`—¦N61 ÆZÇ^µî¬­“YžÅšEê¤2Ïçß1cyÁæò;'TÄ«ÿÖo8fÒú‹ŒžŽ 2«„ph9ÊÕÐh¤n‹âÝBß,¨‰ðJܼUX¥ª‡êÔÒ7– ^nZ Xš4o0æõÂj߇Oº¾«nÚíÕV9”Ž#ô¡Ð•Š¢ÙºÝ(¾âÝŽ­Aía䈚ͷx$ô%HäTFhBhø¥¶œê¡™~[€èyßßOð~Àf¼JVÆ+b›†™”Ôsàl¤[†¥ü,&d8šùG«>R;)àîÑ©z"«aÒ/<'Ðî´Ô[¸®ÛÜ¥¬)ÁÕÙƒ7ôÓŽBîÇЩݖLGm‰§þâÿh«Lg,JHH‰9Ÿõ¥o1Úû±£%˜Ø$B cÄ¿Ócor±=²¹¬03*ÿ€—Ȱe0{aƒËæ×‰îí×È̪¬Z–áu9 zåà„d'ô¼$LQc$ü,Œû×2ˆ¦µ…lcç9°€Âk ˜sƒ‘¥1ùG‰†“On+ 'Ø]¨AñU%Ö;#<¤‰ü.§üEªkÅ%1`¢ýˆÆbæ åjFÄÌsÎæ½D¯hý´ÀÒ^­8I›ätíåèJb3Äw:G˜2ƒà1ܵ@JÑ”a4ª¢¯jw‹<èLL9¨&ÄÕqŒ© öÔirÊÝLÍŽ‰{™ûU 9DªtL%þ­œWñ„¬—<k½TR7>ßÕj¶cÌ7³ÍµøÐú‰¹B1J`iGÕÃ’¦*¹Z#~±EôêYÜÐJLqé<¨&ƒëI.íÔ!&9&R!dyàÀà,¬tëËïwzP+^÷ÙÃHLiÜ>ŸD“‡€Ørµ\…¶Óbûq×Ls†„Z4mBjž4þ¬ž+mÑq´š"7‡r6’ßÍdý}ûžBä[kîtê<`?ÔÚûò€uëù¢ŸõÁ.BþäóÒ¹Ùsq¾Xü¾AIMEðúC7¯[Äxü,QCuí\!ø0ËQ^sÌ5Á›Ã:±xJÅZ2–ûÁþ«Ö›ñeãiMàpo<>Žq6«ikò¯/E—KÏzâyRd³sHàÄì =?œË·- ÿ'¾º¤V+€*‡]z…‡ñ®ÏDR£‘ ­T[àbfÖÄüÛýŽ6ºIhi¯'\V}qxd +õü Ùo€þbôø ¾SA€è]tyóè‰ÓïÚƒZZê£8Â=Jõۦ錛„@¦ÜÉ«?†&ºÕ²¢jIÂuµþú{°íî)8uÞaþÝ—ªo¡ùÇs¼^¦'å#Mš…ËŒ@h9ÎÄd$ û`($†¸Ôæå ÐÛ7õltî ó ,ìÁN¤zz¤Ìò÷m‹)_†ò»ü ‡RMEÃâŽnŒÁ~?=bG¶h"^Ï PÿI£hL޵wyAÁÈ|Nr݈ü"Îe˜HŽe#CÁŽ1ÈÇÔÖøƒ”ËQ;°æè0<üÖüo{L(ªzt»rd‹¿ñÈœâf‡·J*yqmMéùf¹§·WPNóóÁ'¬‡‘©î¬Žb·M¢ê¶~¢ÂÓœ\…áÒªr0̸ n24LSÎþ9fc¥pžìX—ui 6»gF†éT¥ ¾‘i­/N0<†bÚX¾ÙJ“Ót Åeì…‡å½yèuÕJò`# §Û,nq‰Ž¢­‚ dÓƒÁ7¤ï*H5Âè¡]Y¶°ä‰‡áwü¬.Ï}KƬ¹H8Ýx€[ç+72ùD,4ç»Xë_£ 0”¤n:#ŒÄY;ªgÄ-ê)ÖUBP¦™¶%Ãïê̳ ÞT¬A;»}ð‚ŒÚêÑŒ"Bà"¨œtOŽ/ÈÇ®$”¡„ç€âÚž ‚õ«F)ŽÒ~,–˜YÖ œ®ÀI,Ôô(§Év÷°æ<á‡4ƒ†÷h<ß«‹ž¹R#E|dÂãáXOƒ+ó[ÿµÍSèJ„·<·ƒŽ´¶)`¾_³¥BLÞî´üæ6‡nwÇθ‰WÈ+eêðm×”GåLôÎÏ̺½ Ÿ£.µ,œ¯ÕA`yË÷‰Ž‘c Øô*+µ`ûxÛ÷ƇÝ×¶í;u¹¥¿‹å–Blòpû9áL¯¨…UmÚ›ÝyŒ÷©þ湫€Ycý!Ѭþ<t¨B~¾{½!‹™Uª/„Ú6ÿIÄeÎý^B{)â’GæõlÉc-gsØ¿HZÅσ)ÿKA¿zÈEá$B^±.Õyr±>VðaF²¾Ä;-æíN ¹þöˆ92Ý}r§@ãÔ1ÃØ!›È0&Xî!m®I\¢ªÚ^n+o®¡!… ý8¡Ž\Ò ¨[†7zýF:ˆ(röÔ–¦˜, "Ñù˱:É"¸êdåŠ*U,g{„ôëÆ»Éõ™½¼æ|Ã붃ÁŽÃ ['=øýÜÉ{s<^‹˜õU+­PFÆ-x¹ðd蛨 !^÷epÙÿør{qˆqµª¬)$¤äjGkŠìýîÏæ@BM#¢•EË€ÿmQ±Ïµ;áA¾­@V•šCÚë½¾&ŽŽT:æÇ¼GÉà%´8¾÷&]?ê²}7Ÿöë¢Ë:馮GÞ®iæÕ£É Só…¸Ýº8J®–¾8ÖÎ*+P%ªäã#ø·N!–û\[û{ =Þ^Òì«ëÐøZÓ}‹y~R Õæûä]N(u¤¦fã°ÙÁV¶ðÐ[´{:²d/ÒéÓŸ£‡SD—˱y¨PÞw•’§ßPâ“iRXm¼û]œdž¥næMs)ÞrcŒ|êF¹ÔÜaÈ'žRp š˜à<²m>ñÚÍTQåúÈôÂc¸¶‚©R«¹ü9 "ͦ~ô‰•ŽUå|å[;Ñ ±åI<Û¼–Ø b„ æ,8È-'¤x/Ø®F^âYfœGj|ªžÖyK†—Oɳ!"Fôg€…ú P%ÞhíhxêôX['ÒÕí‘']€rÐÅ@ä/§‚rÐ\õ¹•ÀcÞ£:Älóncéu.°<‡`Yݳ¿²ÂÒ$~?C,+¥†8Äzݼʢø!»çöŠ bŠø/~¨–zŠ_wnú…°¦5¸¹o!•âZ¾Ûé{Û‡Á|¥¯8V $Èþ[a‚{Èû™fþ·vî‚À—î#”Õ:_¿×ãdE 7h¤Ã|§ýÞÎ.eþ*áå9;ýüŠÒÇ¿…À¼õ4´çQ²Vö¤‰2qåÝÏãÙ½yía â)tB"fØy~ÒÁšr‰ÎUùf«ÿ§;"Õábž÷æðBº†£DÑVˆ;Ï”ý]áZ1hÕ†¶99ƒÜ#ù0`í>Á¤ƒŽ±Æ %Çìùj¼/É­·W0˜gÞA­¼t—iÄc댊x§„*2ŠªæH!Ö-|u{Z'€¸)­P ;ÖCš%â65°Ã/ö$¥µÊê§eÇ}òÜÃTç¦ T—»W½+ú¾?ŠÁó{º8žA8Òž]¼~Ã’sç qN¶KžÛYñãæ ¯$üó"> .öi+‡5=o×øŒrƒÂ;Yq3åe–&€ußòtŠË6=Ìàç"•oW‘x‚à1s²nˆÇl&#K‘L=.‚_ í‹RA´†tNMcb›‘5”Y³šWCâ–nÅöNž &c2¶~@EkñÛÐF÷Éÿ}%ö”gwâI“x P0ØäЋPSþìÔŽ ø.òo+þ’W–zA<ðž`·lÎp´(éݽŞJ¯'´:ô.-G·¡:!¯áa4ybŽèèlÒF©P—q®6…»’Vý€4Ð.¨Ü Æ·ó< „7ê•¢'œ £~K M©oDIû#g–Ö£¦zº{X! 5æ#ǘ&)A¤‰”<ÕEnÛ@8x@_ªy!gŽ_ÆX®˜èǶ4§w[Øïœª0ƒÊ&½c\QÓ÷­´N%ÿÔÔÔž"aŸA¯œ8‡wÚ}$­·úÚÖÁM}!:™£ífu eá›o4Þ¦ŸT¦á!CKC²Nê˜PKΩò’Œ Zdæ&f‚ÑÎ=¹cÞh§‚‹0â’håi3}Âï΢Ð3¥ûOÆ£«¼8"šr3®—ºã0»_Ãç…·: é¼Ò²6‘qò·~ÑMí¾G‰)él)7a×(Sw¶¾ûŒÖÆÚ4 ' ʰ%§rÉ_Äe­ˆi#ÌñVº÷¸z…Ì$9ËùÎ’ÎÒÀÜmøõæ"^µ§Š^óEù碟Ã60÷HÝdgté Esthý¯€Þ˜fŒ,qaNh”¦uðè·åfiu§zוÔÐ;ŸQ7õb/çéÂî¢c€)sWãr5IßvɶΤÅÊ¿¶  &7·4ÊñŒü²4z*”È,ª_ã;x¬åÄñ*\Êßóp”…CƒOkˆuâ®Ú—ó»i×Ar“€  ÔÇédij²Â‰WHØ'˜ó";ÑÆêÊ¢Î)ÚÞTõ5-3ÅÎNŸó‹“Q7ŸŠf ¼Àª§ûFÈ*|ÑËN•‰ƒ²r1«ü"b¾ø«þ&ÁÇ€‚»¾EâFé †ŸN›jÌ#<[bȳĿ/Ü3õLÖÑ(Ø××ýIæ-†ÙpoﱟÔ}v§¸3 °Yª>µPà=Þh —ætª¹Ht‚‹pÖùÃ3¹#§Ö2ØÝ̤ԾäimÏ õ¨á¾.¬!3ËJ6ölhmäïŸk9‰˜€‚ØÝ ýBõ ã~%еž]ÍúOCCkí–hõ–GþFî{$ —+»nO‚(*ÞF€ Ö˜D ÛfF³[ákæHü±O–œ—ùQãL.|x`bvsV¨Èðê°°Og­A0Þ MÉçÄû ìì_ï7_¤ƒØF1®8çƒ U5ÿ³Æq5 Ƥ×µñÑ–H†,åS~TyC“Týåab'‹/¢9>MVeQêþÀ· \•6ß¡è™ÕózÂâêlëÆ]N:Ýû-ºGòA»ÒÆüçëGS?ú%MW•Žb%Xg¢›æ$ÔJ…|նʳš’ågC¾UrÀv’)•aÛ)w[ûîU4¾M{ýýÃüÕÈ¿-É{ÞŠSS÷Šá¥½Ø0ò.¾#<| &•²êü1 ¯¤ûç4übTø,ö[°0{‚:5ִɱUÇ M[x¨ŠdŸ<`Áá±™Ïù„£ÙêÝ0lj úP§í°KÂÛ²ÚMË›TϘl¸Ö¾Í5†s[sý˜ “¡U°|7cn5 *þYMÿ€ãÔ»üjL3ÂFÖî…B×­±âkïÅù£`u±ÛM¹ö>rÝ?ÃQë¦É—,Ži©f÷æ5"Lu1 7LCAÚo£ôé^SW_ÔDÀùöƒGÅÌîfõ ª/ƒÒV&ÿû÷y OCÑ–TsÌɹ¯EDü[Ï-ÿ5f‰Ô›;NePLø$ÄÙ‰¿ú¼kMU7nÿ挃˜GCHj 0 Ñän •#:ÁhôÀ¶åŒ©Æ±Ÿ+“yKŸÓ8$dŸ Å”Ä5$¾häqŽh;2çd˜`u¦(¤øÓÄÕJwÓÖú¨[K‡ç|h ie":ž$2†ö¤&TPŒ .&”þÈà—Ø| ø@iX?„Ç-Ia0³ï'B%Ɖ" ¯ývûuÕ’U ›ÃÂuDœ×”úâM1ÁjÎô¾â-× ”âyI( Gö øñËál!vaÍT Ø]’ªâó@-$6'q½½Áqø·aÉÀiO˜¬ä6ϰ?"'¿zŠz1‹55ç­®šš$޵ y¡·Zš‘©·Û©&‰Q§\dÅÙ%<=ð™mm®×fÙ}”‡”,ê'¹R˜“¤ùKÒívÏÁê5YŸ×v§‹ˆê³GõÝ¢Ìæhˆ*ðœn}„6žå!ù­we¼™B´µTë2лÔí›/cµ¼Yƒ÷ˤ\àBÅÁDà™™£Tüªq@çŸÒŒÀ·ˆ‰Ñðp¿ºV‰&dwû˜?¼ÃW½H·ë–B…VÊ.Ì,ÞÑVô¦J?³…„Gx‡d鮇¯iìá2_iÕ P×.h8â•úª(ƒ÷«ž©á„Œî«O¥9i`žÙÖp–Κ!C^f#äÏ5¡ŽsðIŸ~HµÞhQQ:®ÎÞöÑûY¯?1V·„åËLBI4KÔ'©¤C;9Ýø½oðë˜=[gê´@YºJÅtFmV(>Í€å³ae0Zbèf:\YÌ"Ë‹!9÷u´‹ÝÊC¹R’•¸Fñ|?­”ºQva(燜R|)|ÊÆíݰp¯>‰»çŒáøº`÷Lå£ý5=RS° Àm®ÆŒo_`§‘î>‡ƒæÏBñÉ—þ/Es/ÂÈÀ9ëšðQÊËH}\ÄU¨ ¿Í_*öEpæl¸¦ùÛŒ@fæSiÿEûìÏ@lˆÐ8‘‹‘kºl2‡accQSTê–yMʬ1”TëÀuåÖÇ™)þhÊ­ÈnETÝ,M|W¢Ø‰à*¬ã°¾znnô%Ñïæñ…ÎîâºÄx€ãz±B­?vªªPâ¾-z#_ØW²·*0ž'9–##é»íßÔÕE¤°Çfò"›2Ü%‡À>RAìîÙÚÙ‘Þ]ÖÝ;éžÐ¶ÆTîäÄmksú ÓÃU|~Ðt¶BͪG/Å€Ô.t£ÉIwõÛ¥ÐYP*ÄI‹MDŒó›P¯ 'jÈýôm oëÇWÀ|¼‡ñéFöä?ÀDED³âùYTª+±<À1’>KÆVyƒ24"¦t ûAÊø_|fm¼ó’WÇÀ.ÓÁ˜3ˆ™ ’&½~ì¸Hëê40¥®‰ O™3tŸ·õôöç³Ü(Í90ýÇÏ1„)!ô—â¥f5¸$éV­Óü^¸*{y8µhè^U=6bŸëx ýÈÂQ,íæ!:4íöÖ8Æ[ÈÞå|}âÿ¹…éïÀhLØ•18£è,ŒeL‘«@‘’öjFk\OhcL»Îõ'ýyÒ6û9Éã`1TÇá«Üû‡Î½Sú3¥PV‡p›þ„œ²oU4tëß^÷íõc¯Áø=ÝD¸zºˆ@“ ‰ ‰¾Pôsȶ?'(ù«õíM¬ ®ˆÁ'Þ60€¢mD6äÎá¡‘˜ë¬àìtžÈ5[WSÙÝ,¬Œ¸'¶¥=3¯ýÿBü/¹(Ž ÿ{úfäŠ?UVÈvY76¨¡Ë+騇½)À[ƒIñ{Ñ\òAô=6¸Ó@öœÑr¯`ýrÐJõR´0qÿ b%Ü%v:|®ÝeŠÍÎ,NHÓb"B‰Ç€ ¶ª"bÃ*›\½v\uÝÀVž­ÕŽš¨¹òPÍ^^eYé uáîä¼Ý›Â¯Ú+Ò}¹%ñÏÌŸv¡G95}j4+ }3osÞÆ;÷"ÄfëH>Év`†ÎΕð‰ÿ*v?Ì €NBBjYns‚”†Ò×qµŒíµóâC9ä­Ê»¶2y›6ÕXU‹åß ?åÄÂPB-=û\Þb>I”Ì14YâN«*ÛÆzÇOó ’¿Ûª`§©h¥œ ‚j›-˜¡¼3(¶ŸwüEކ6¥â3øþª´ÈۧßÐd0F–“.e½ íy. Ó’*9gbTg*FÛ60AÆ¡²F-Å ›^-.>Q”(Ï#Dý]¡ d2……LV?4ð©±jî€ÉáS°ÚµÐä.Ádzœ‡|ÅcGÔ Á|q×¼øN½F5ž*‰J!¨¯`Pó{l%tT¼•aQ!÷7!Åðr§iÊMǘlH8À) 1Eë§9mÒÃ+\DÌFۗתÎ`GçuÔ¶¸r©:¥xVž )€h‚8s˜D·N7æ¾ÿ0€õŠâ!”Ö„Ͱƒ±JùN³\¿A'‰OGª…îºí¿@Ð@¨2¦T=Ì{VL#“á.¶Êž ôQ|­ 1r½û7ò¿kóZ³–¦o@ ÈŸp :™ æ*šŸý ÆÊñçv}« “®èÛǸ(7¿¡@HlÍñ4E®XˆMÕùØüç à¿9@¸ŸM É*í·™ê2êú¿aµŒE9«Ø{„RÏ@ÐÝbŸPr'F ßüM7¡º\îx§ÅFØŽÍùÝž*žocÀÂ@aåÃ!ø×Dîù%è€4»gÓ™³ .—Õ‚f³ÇÉAHRPÀ€Găæ€&`ªÄÌ‹áýæ^xø@]}ø¶ÞqTÌ«šxl…ž[ Î÷ß)ä)§9cÖ-B½ú@Bg£yÂh:¸ýŽ˜ œ›8ÿrŒ2T™¯ˆB\Rø3–hIý[C Ãqã(…sVW,-U¹g(~°À?ho&1fšÇyɰó²ºUIâÆÑO”! Bó0&‘2Q¿óÿbî A‹Ë~ü¾3T”/Ö}² ŠhuZrCýª{pX¿ 6ƒ†ÛÍœÅÙº‡Æ Á·Œ2K¶Ž¹².H`…ú[\Ÿ3rŠ ú‚£ANMQÞ‘¡á`ê¼ Tç˜+fì»oîR å§ ‡ ø…B ò¤ÇÜÄð@cˆ '8‚|\P )ÈGÊePpªå}Ũén€ÏddæÅt†Wzn†Å‹.0B$a`° ŽÂÉ‚üî”,®P¨Är}±º¨á[¿šÞ @±yÙRõ˜“T§Zßý,ëÍ (!uoÔcCünëS·ñ1=/’ wñv1í“Ìßy—l6ÙÄ.s–:R$š[Î 9•gÃì:Š­)?Q{Ë“äHùˆ4·tÒ3ŒasFJ¹Nx22\"9úìÒüE&›pç¾½œbmmæúŸ¦ÐDzûÇ©áàá>üËÑ»dÏåÛýêÉÒ¡ £b6(¹™ uMÿsXÖ~‘ZÌ4ˆÈ8òûBßóŸk6=ÊKV¿!ªrîŒ9 Þsw™5Ð#Í0öú3ÈïÀv-k>›?`P$Q…™œžÒ忟†EÑ-ó*e+ÂPᧅ݉ ‰;m 2–HmüKˆ¼u(º±ðÂAˆ YÜ å€ek˜„‚ cÞ´óð†€–ÁE¾±H¯Õe·w3c><Å-¢sÕa¦µLH¬ ÑC“ÅRðÛKL3f®öN )Ÿ”¢xnæé>ç(¤SfCØÇ®xœ±sdb'¢Ë}òDá16ÔÄ£›ì@ôë®™)Ì[Úl6f–´M4Õâµhåš$‹š+j¿¦Ç ‰¦#Tf?´[Ìñ½—Æ<^«Œ}[oaBS%AçÔûwVÞK¶$ú(e½+Ž[M¹ÂÁ}fOðh†H0ÅÇ{àÚ¾3°ÏµÄžìtÆéØŽäíØKçÑaüµ9ĺVÂ!¤é¼ã¨­š@v@ë••ô}j蜬#UI¨Á;GYBÂÈ{tv”–í÷y8`K†ÉÅàs#N UÕ+çîPº©ÑS}Z?D!‡€×r#SÖ:GÞ<šó~ÊZ^å›hxŽt½·ëj÷¬ÍÑý1@03Á»xÌÞÖò„‚ô{“Ê­i¯²„Öé”(Lõ+GŠÈ^òi1|°{‚uºqèXÆ¢ú£0«äÖÝÓ¿+ïïyšçER)«w²üRáÛ,â~¾>«ê¨ë,UÇ;Ϊmø»¢E›Ö`"ýç¡÷Y,¤0N‚g6"oŸ‹ÁÉ=Æ«ÓaV;úñ' Å‰Œ&E7C¤—5 Sȱ ô¦=ý¡ª1Gåª0!4ÕÍ£(˜ZõxvÆŸî'¾l(*·Ž^±nÎL¬º¶á 8‡@yÚÄPè‰[ªŸþ‚‚Õå280ã×¢„%î"–HƒlÉ«®hUêk[½VðOw<”ä2ˆ:•»ObI膆`K %?$B‘ówþŠä7“ÚêS+Âðˆõ§Mq]oB|Ó~†tÛ -7Ì2d·d¯1m$ qJÁ óÀç3½ÆP;Ö@Ã<`ÁMPÍM>‰JÿßqŒ—à·{áä‰ÕËöôI€ù_&ü–Æ_*aÊ·54·7¥O–CŠÏä­©×,´! è,–Rîeô¶„õÓJRĤÀÜAuOï1MßïæF±$E 1èæ—_çfHÕYœ5•±·PQ¤^䔕‡Fš@^MÙ¤ÆÝ^å–bmö̾ÄÒ©:bâ¯Í¡û@¢òNyбŸ«s=Ò4ÐÆ»oŽ6¨öVB_{ùÓš!ÐÛnfí®R«|5m;:¹[Q„Dïf©¾Î:‹­("à+Å*JíOGÖµj)¶›šeé>sx ÇW;©K¤Ý:ŒwÛ­D2 û<PàÚ顨»ÈLCÖYvâ¢ÎÆ„x)"’`MIëîËÁ´šWî=`Ç<¸ZhåT¥èX˜D5S«BÌÐú£ƒ2™LœÂ‰x]¬·l «L˜Gé†BsÙ•ÎõŒÞv­Èám»™á‚´Ê›“'= bʵëúK#Ä Lpk @˜ðýœ–ÇMÀÇ?GmþSFWu\ÒŽcæ`€ƒF©Çºë¹êŸ¥`õ£w=r‘ïX‘‹6 “ ¦¼@>‹±o4ñ)®aÁ³ð{v€XJæ<7&q)IÖP4„‹“wÿ{4±#€4£ñý=ܤ¨ ÅGäºn]jsÒ\§Äþ­¸0Š¢eMM Å(S¥œåü»?$üð …9]È5¶žþ`&Y®{!µßâØ/]‡cše¨Šã#V¦O Ãf¨6ÐòœÎá9XÔPgZHbÉĶ•k/‡t&(ð8 ˆx ?ÅH¸•¿€MªÙš<Â*Ï­«váÔÚJbèF¤€–Ð+“æÛ?Þ¬g$pÒå¯P'4YoD.ôPú½Œ~†:Âî6«‚íºÿÝ?LD=ï8ºû-O¿ÿÈÔª…Õür⧆O~øwmüöaC`P°íÛDÉuïY[íß 3Xþ¹ /£w̃pޝ›âõ‚ìL +kÓ uö#ŒÂ </ªÑ£oX~b)Úž=bÆÒ:wKM¸Sµç˜”ÌÛ/£3€Û‘Æhf1ëi²Z¹ý’Øe„8–¯¤¿+!]Ê“ TLŠ´ýDöØxé‚g±ñÏr}™ `ìŽ9Ä/ûžI¾B!g­"!ÓÓËÛÆ¶§9ßÜN‘ÇTkg^jŠÓÎúx H´ÅË}$º²íÛØj¾*š4“ô¾`a(ßÂM·ßÑÎkïã wàAÑIYħ¿ØÉkÈ'5JÓ§Ä´ÌCy¬ÕTÁ}Ÿðj ½DØÜ&®ºÚdÏPRgÁÕáá à/Ë~^èpʨí9äh6N(ËæÊ¾M¡¶Gùþôè2–L/˜7!œî¨•Ypö‚PF7ÊI¶¾z!Ù%Ѿ!¸rcîà}gùNEU®iu½´Xµ„UÍAþ÷{Q¥‘¿’ÝT€#—±ÉýÅ=ì&`¶\:}Œø©42IżØ%É-“{»à¾µ^õzAœ5¤¬õ&ÂóôX§¾¶Ð–«$,ú\€3EpÃP(¨ñu•q?©[¸Udzò¿öÇ Ü9Ü—Ò$L#m7hÚe[ƒF¾2¬·¦úU"åzC$$þ~2›å=×™µq"?ßqïAËbí‚Ðã%‰\¸UÞœf,ªƒ McÙibÍ^%þC2?¤€NüÏQñl1¿ª3ݾ/uÉÂÇre¬T4¼¶š‹+l±Êf¸hé,Ý5q¿ùê±Eõ%ë’°»7»¤V¼Õ %S.tUE(‘W¹Î‰Nùk‚ÙáY×¹¤ûM$ÖW»q~R¥°0²^°„–?¥Ï³³¸Áày6Ʀ¿UáζòÓ|ì« GH5I?ÈÖ¹½#*$Hฬå4zÊû¹„Ê£b)ü…dõ>#Ë‘Êß{ò‰šùÍ•4òkÞ=?êÝ—mTèµÈ𧆋xˆŒü8i£±Ñƒ¿k;üuòBB^Ñ(cò°UÒÐÈG—N!#ŧ¤¸´¨ðéPÆ!8&„s î웸e–ƒ¡Ý. ÎØw 슋VÙ»ÕǦ ÇJK1¾SàÆ>‚8Úf•íb¢¶ù>üe(ˆ–¨¶éã£û§Ø&%ê.Öi8¸»Ò+,ìªyj¨º=ÀN¿òÈêPS1Ä[ ˜SW&õbÅûPÙ †Ì!ý(æ’ÿàÔTõùFCûGœ!9ÑÂ󷼨j’c‰»^ ¦¿ÂE¸ªKKÏÔâ°ìféFÚ/#ï, Ïa ëÅ×ã?"¿Á}iwÓsŸ{Ãá½á¯SChž¦³ ub=¤„~Ìÿf}¼Q¸`üðìZ•âÖÿdÎÉÑÒËú¦: “g(…ÃÆJT ᢹƒsSÙ•¾Mdñpöô™ké‚^4…° ΊE\=EÍcö÷žx=縕î›å©|ò?œ³xÓKR Û‡»8ØWôéGTÍ*âPr/äÁs!ƒ\KŽXŸ«Ô¹¬D·5½'»ð£›4LûÖ”‰¿RiP¦!ƒ°  Ç×ïýéèî×ÿ\ã ÛhƒÖ±âÅ0ŠˆôмêíýæãäRòcõωGc£pÙ£³ÆþÕBAªJí”厑‹´…‹ÙŠÃQä„ì56Ëß³¿92½Žvö7²éµIÝ‘ÉSWg¼Ï÷G9fn±Ñ‹¹r²fèùƒ ëäJ¼uoK„é+ÒûA2áI¬â]É,ÂHÊëžR"g«Å½HßoýVð…’UA|Kv¦€R\ JUܘÞüç\UH£| µT¡ &Ëlº?JXÉ{MÊXa¬µw}ÿp,ÄFËê_’5ȸŒÐÔwš—¤ÇWçù)~ÉTIK'¦(»¤|Õ}ÜÉ1m Sñ¢¤·Ún.Á˜Î—añÚM—e›1”|'Ž“ù6-)¯ ÿ.ýëŽ x8SŒ˜œï»?&±x%B´Wâ×2HÃ\¿ „¦Jÿ~ba¨Lå ‰56%ÚIü¸®¶Ð˜¹=^‹1˜‘[ùÌY“¤JBébvuküËH;ß_¨BV ?â VîÊ“[FÌOä+îÈç|×!€«?AÝ•,¡ñQÞw0.‰3Ã.œ[Æ×bOѶHQ¨È·4 ¡3¸—÷T-Ò,'Öó*’¾-×u¶_7ÌÖŸ Ž;ÛPTžFÊšù¼s{‘laÙ•ê†cTœÏ?®`AMAÉ—Š«TŸG+J„Ë)4Ûÿ>“Å€h°>ì¿RüҜ̤Þ2H†Wë“ôs·.ÙÈÙ.ÉgÛaÆq:éÔ¹ŸÖªK±°Á9‰j¬Râþ¯oðB¢tyªȶ$ŽÃ¶ÒÇ qç˜`)è†n<_L>~ÊÏ/wÔ4ÕÒKÏ iÎ1Œ·CàZÍæ°£ëŽ£‡‹za_Úù¼º(zìYÖ¬Pô¥B°u7°Pï‹-[ÿßꂺPqäÑѬ®0ÀŒå(¯¯Ê¹3»f‡|Õ BèTuâªilÎkCD )ýÅ·Æá°ÅÉIݶ4= ~³¢b8Œ±ÑeߪnÂýé²àS&}nÉ·ez”[oQ úx O²ÝlÔŠ7õ¶z Ê1ùÂ*Âç57l–|ò¨SUbO!%öA:¼/¨Ï(–7ô™s¥bÌXÉyñò`'ÓªEº²#&ÁsU¥¨«õ9jû1ʦ5Ât)ÅÔ_Ë“µoe•}wÄ&yí®ÖpSÜìþ¡ÝŸ¥ÅÀ$ð¾)f@ÍС‰Ÿ>f¥øèò$U=ïˆrð¿ f1/ Çh}ý (¡Z¤[&ƒlmɪeÆË*<0æÏjλÏEºŒAœ#uæt”oyK€…¨Íÿb̶ϯý‹2v¯Í_ÆÊ¬æ¥.(=ÉM8A§È+5‹xø·ã^¢¢ÔñLZÔU¼èSÉ%3a»^Ù}˜–cñ„Ã’z¥Ù‚#ÖÝŸ[ ”ibäwE»§r Ã"Š?{´?È Åç€ÔK_\éS•C`©‰ÜjIU*^ˆéÛ‰›¾é5b>>Î6¼ˆ €a ©ºlø]ã4êéÛê0B•FŸDï}¢,tGƒpòö¹V™b{­F·UÇñiZdr­M›!²ÏSdb*%‹ÊƒR1wUûQÌnß$diA7g|[nÑoŠÒ ¾üCŠé{à—qÈ þÀ/ð6©Ðõ¥Äh¤ËbÙŒU>íÀìþ @iºÅÁˆ|IBQ€^Ó3®à ŠäÍ7!Ö'¿êß'ÌõãÐßÃZ?奩Í9Ë‘¾ÜÁÄpRìrZ­ÉÃ:¡H1å]L/?(Z[øÏlØ-N>÷mÁ ùŒ†`Ô?¢ÍeHcŒ‡¹=qߺ«”/z™m¿r|㛎Yßf~Ga¡Ï·“r×^hœ*÷,ùxLêÙàÑr9Éqõ3¿OÙ—Á8A™FLd%j*5oø ýÑ^ì%nülFXiÆŒè5^|°gägªØà{U;ÕsW~¾: áž~¯Í$ËÃT¡¿"Œ¹’B&и•Í#>ÈLù5Cž·å™ýØ¥Nà0ƒ\s-œAPÝ_Ç›$n­=u€SS"ƒaúêÅõ*)ཧL¼ùàa$új-–ÓÅÒŸ]¾$ƒt´“øn%¡¿Š »Õí×6jÛ…g½H` ‡‹µþKÕpÛ+D¶Z‹ÛÈ·Qbfq)Õsï0°H<ÛEe—?_%Ùæ†GæÓM ¬°ë.#Nè%±áíé™CW{©ýï°5éL)â9c™í.†~ÚKvÌüòêV­:†“ž°Xz üûƼš‡êéõ°¹Yú ®ÅHáäòðt–&ýR ¡u[µÆC×N§+ýðصԉÀQbDîŽÝïW2ÏÑ'ƒÑ¿ZZ6MJê³Î0zg“ôÅ-ÎÕëdMIw@ºÈ—[ÄΨ:#¶þzd?ez„ò>‹£›°³( ¦bSQX޳g¡> .*Ø­É ËHgyØäÀ©¸Ç|Þ‘}T7">Ë ýîÌîƒ1Ž_ðñÉZàî”*½ šXº²ÅÞµÛPáÄržÚÿa]öè‘\ëQ†£ß{OE›ÜÃIöu‰1Ù(Kΰ7“ë ‘®z®‡ÒWÆ>úP¶¿È+ƒ˜$v¤¡ ¦X Aꆈ$Þñ‡YðghcÌ¢`9ûJ¤Wî‡-Žª¥Ü@=—Ô„µñ«¢Œê$ÑcŒ:=«ƒ/³´Š‰ô^¶ý~Vj¾ò7#Rÿ Äʚ-æ Žq W‹8.‘cv+$Ø;ówj&£åÉÕ—Òvâ+Ïy7ûðlŸú– 庌'bÅU°\—Òo\Ñ¢¼Âáš§l‘³š>èhû)’ÍR©GwcD4íMMÿ³©;¤wÉý•®ÞQFtå¼O(Òx§Ò.ìlfNÂÓ$þ€š¦ãf›#°›Wòò/‚f3þŠ=¤Ýš1ª–âÄuÄ`—øå›Âæ;·ñ÷ÄQ§¶â‘í®;ÔׄßNkŒióÞôùévcRk›¼¼jIãG…;£•Â;‘M$gó²wðHÐ.‹ÓiÝâõÚC ²aÿ© \.ºHA'¢Å#a 3Ö&ö,üŠ€ÐÙ¹/CnçÆJnp"elpWþñ#¯oÅ-¡ÎŠ“Ž!ŸÔ´~MªUºžÛ|‚{ôhàoÍ]Z Q*C»7'¾·$»tÍz XL‚•÷Ìp- jvp‡wCˆëC¹üõòÖUå¥.\yÛ?3Ÿ’É¨ÎæË‹•\GŠT2oè„9áÙ$ZâÒÏF¡Ò›­ÍÿV“_èn*"Ç“JsÊš¯eJæf€8„’Lg湯ù 7¿2o4‚B›цžÏàù“ægð¿«( hñe[çʱŰˆË‘˜=ÂRk^µ2þNƒ¹ê3QtA8ÀÕ€¸³w]LMËËÎ=3LÒÀˆ#˜°€q™Ôñ—Èå8((¢úßÓ€¡þ%kíÏôD¥‚P ªQåGÞÜȥYMg· ˜.’Æ^dsækt ¦h”ŠÐÀ ÜqÕ†mùÞwp×d¾¼¸—•;Â)íbIšìÓˆ(Cçf˜ç £Ÿrž>ÙI+µ“ѱ®XE cý²·f}É@N¯Zó`‘¿YÀƒ¹-‡«Qû)]žÅà'¢Ï$Ù}Îëp¦ëY»Vý?=,Gµ„ï—Ô9¢J…8çŸ(ã«æ~!p=^š mJ1æ´Ö§<'é—Þ|DË5¼ìÎv¥+†ê7*ø9nµ‚{ñë({œÙ1å+™˜#µ[æ&¥i»Í>€‹$Þ¨*UA)´>¸°Y™:fHSœ¼¤Å“WþÔ­nyv–H=…€à¥·[S]®‰è›*cOÜÏhŠô5Ç‚0;³”-ƒß@Ëeòfy½3È$áÙÜSlש:M?4ç§¹Ði‡uŠ—.*;­Ë¼d¼3%yÌ•5øyKKrjHÕ´Û 5ò“íšZ@íTÝ—mîqÁ¡nÒï‘è íupS˯çC<Í—¶ú¨œJO>ÇFÉU—+NnÉY|¡´q¦³wz;¾‡ƒôøYbK˜É'¡ªE‚’­Ë𠕝£· ?5²ZF¾Dܯš„€ü}^{•eÜf~#\Åû$‘üÃ@s™€Î‘†ÖÀU''w·{w÷jGì}拆 Dª:„ˆ»)!“?@9}¦•xÊó?GŠo@Ÿ«‡·7jc߬ Õ Cü0ꢶí¯=é…‡ù˜ê}s¡Ýþ"——Vµê˜ÔÍ`JÏV¨Ÿ½¡býà¦ÄMŽD¹RÖžW_‘׳¡Z䬌e«ilŸJ×z¬æš´|òuÀ`㘟½á£P²,µõ¾ C÷aÜÙÝ) 8l!ò³çÎ|¥"`³Q.K{%þ›ÇkgûÓ÷ž¼VE³øš_aO¸t]NY£¦ªÿOžCÒqË8ÜàìÓ¶a#øü.òL> t³Ä€ÊZó_Ɖðc†­‘u%l’š” ˆüüæ.ÀÕ¢­Iúè(¤?ô2NœGñäª0bQbEœf-­!·puÍü“e¾t‰õ“ØQ^eÞþ}Ŭ—ó=дܜd°ÌævGD——ö/Éʳfá5,*ÿõ”oÚ‹ø¢¼Ët¬&~x \÷£›³¯‘zÖ_û¶Ce ž†ÒžvèK 2Úu¼œŽVÀ¬‹ÌÙÏý;.2çUGx.#~­]kÂcŒuQYv¨_s^ìz¢P¦‰Î ¸÷‘¤9Ý, ʩԠ~D ·Â­l²3ÕÕÂ?¾¦2ŸÙ‡Ì¥ëŒp(¦)osø„ÞWp=c¬ê’.vcëdãÅ V”—í Ï 3Ó Ê&9ÊCÇþõkÜ\^~oCà¿3ª Ïjß>•§ïÊÆN²¸ÝFgöˆi‘rû¨†*ßf Rlsl.gíÐÜè€Ëÿ*Z“ÝÏØd÷ot_²IK½]y&£ÛÊBE††"¾ˆ¯sÎÉBa€‰•×>Œäç‘CŽ:Œ¦ÜÒž©ŽGµ]Äô)èËð†)„É›$Éš½lP¥êÊ×D^¬âBX®™(÷wÁ5•%Òä1¨$VËr½vn51"(é—ðckßÇ^~«Ã¡4tȵödUµƒ×VÇ„Êê'ص˜Ç»\Ѿ]¬¡`€•„±îÎêt¸š9p6 ©¨ì´·µ ‹ÅàÆ6.3uÜSûÝ7¨ÿ÷ÏvT lÿPŠ‘³‹îÚ-7Q\sÙç0ÛÂv³chˆÌ09x«ï û£ƒ´»zžºÎJh5Ò!ƒú¯'“¢°b§%¤iû.C~štµ>£Dò„í~`^:“ÀÒŽ€ú%|ߪ`qw'â$uFpJiÚÉPH¸Õ¡Ñ‹X¤áêá2KM`LJgÝ4úX° úTcoûŸµõ;´U¼RIGdÊÉWÍ€xƒ°jMɇ^Ö9ù€dº©h^P ¦–€®¡AsF¼ÏͶ›Ì6ÍrÛlj#†O#2Ù˺§è‹žµ¥2 àooOݹëuU.ýP¼¡ºGl|[&¼(«gc­Ù6Òž¥Ìh¥'o=·JáÇ£pJ•7ýTßXÆ<¤k§yÖïÛPí­Ì âŠ×çAœžÆEž÷*ÍÙ¬oÉ΋-ác;[¨Þ޽D†­ƒþSšÐµ?Ü’"}EÀ18,Ë–È}€j¿îˆ$liB¯HZëËkéƒàï`ƒݹÌî×wíÈJSó.ãu/XÉaT½ ·§Yû9Y¾|~ ÎQ ÐÌ´D¬5t`H'GÆ×Ý»Á-LÔã5ôTIª,*†>Pª=“hîߊPíHÿ{­>Ö?Á%%§xï6/ÇÕ=r6¼ØoF‹4çr*ã&¤…’wß’˜¿éЬ,uïÖð vO[•ô7uB‚=U N®m›Õ ‰ú‹]© nm>n Åç©›9JPa„’Ô¨eщt4T‚þ¬£Ë á‰4ŸàP¡ôšMp'± –‘±x°bR6!ǽ¬dÖ8GÓ¥õ˜½ O³>ÿ—OîÝÔR<&éݶϴ†W IÞÅ;ЛÞcô÷âqaf;Q¯»$ëÇu}m¨é¿DU“jíùŽÂ³ûÜ \vï†l,À§¦](„‚ qÁò¸KÃ*oÆ›+E ³?†yµÙà|ìãŸO5wŠv þ&žA{¢Óòcæâ[Ïð HÌ•¬˜éЕ„µÁ¥Œ¦‹o‚©¾ßö0úà«]º)ˆ¥ W0Æœ’ †â¸GùóÓ~I—%ߦœü,ÉN\ÁXu¤CèÄG»©öÄ€²¥°Q7"KuñØÉŽ€pœYªÔ¤مš>žÛÁÛRAQ]B’ß=æS„’–®fc]^ÓäÀü®  ma"RSam5•ÕÖo‡(5Œ¹¥×3ÂΦ(ƒ,˜©Ù)†ôMíXQ±Ø*B62}±qgï´­ðfAXè]UPt*4ˆ?œž„d“Š‹ÁgèÜ2´T,Ï!@ôác À1Ho„˜[nŸ~çýe“.õ¼/`ÇU¦)—¢½ÈÇëà䓽Õz@–ú;®C×Ë̈́ڌÜ#vf „Ó±%ó“ÅÌĨó}US<¿ê)ñÙÐÿk½Y2§q~ X´fªµ¿;IéXóŸpmq-P¢]p]á_¢µè6ó{ hðàëè=ÂÚN•=oJÉã⺄´RCöÓé]ÿÜÎ×s”hôÛÎ~…õÁte³*žök•<+Ò,þž;ê™hbQj9ý8=î¼žŽ‰÷0îç%e¸=x½’¬Ü”åáTy ¹2ŠÉµm)^£o¨U(‰Ñµdõ4ÙO% vF9O]™Ýø9†oge׸ 3p´¸épf@˜ò:Õ­Âà¤ïzðŠ×Ãë¼ O+b2kPO»†Tƒ{N鑸C`hWU‚lß?:ã1$ I„øKµTÐÜîelŠ[É£üõïÂ!Ïv±v®7ëaÔ¯#¢wr¦×Oc#Ž V¨Gx•YŸoyP?ŽþOƒü1‡£”÷%¼ÒTùÂ…ñŸué¾°T#¶OËh…¼Óx!6pž½iVº¿:1«HHákàp附«b§ ¾FNœI˜‡48 …cô踄ŒL~S¬ÀÓaãÊèXä9sX ©CeÐŽi(‹e\¿à?àê\­{óà?Ø:ÒŇë«|?ÑÙ²U-(OöC²À[½s~Ÿža;áÑáaùߺ±Vkzñô6µ¶ª¤ùð•˜×|úáŠYPó³“ëK!þ¬€ŒÃ'B‚ùÊbÿÂ×e7ËÉ„[6Rª—Sø#q¾ÙÒ˜âZÏ—9ñô²¿[/ 8Ò©WR\4¦´ ¦¨L£„ÇýÿW Ÿ«E°–F=)L©¦-hkËßïXpJƒ—ÈB›à)š9K8’Ï&LŠRyÓÞ¼Ü)£PnWÅ©¿î­;I˜Ê¸zDxåÖþR ×B9æˆÜC?¡=…ÉêºCúv“)½ý f‘­ðpkµùž¬ ªÿÁË¡@Á!w‰92#þÔœ :ï¯æìklæ>—äÒë!D4çÒýÄ‚{wÛ<þRqøl5Ô÷SÒ½1…Ló³Ý² ÷ŒÀÒe…~ê­7yŒ£É1÷þý"†ò'ÙÓLvÉh«áÛu”&ósM9Öıà/¬fjÑV^ »ñJÛXµìnƒ³V›¢)jÍ}ã¯ãõÐè@üÑr<~˜“fKk¥™»\…á &1ÉfœM³¿åPæ ?h\¼¹&lå¶kµê¸,¾UZ˜ƒéѺþË´’B$ûz&mŸ¸ù䩸 ¼ãEx š[P ×±íŸŸ‚Ï}IMð"bþî§yC Ý糎÷׬ å+ñ}t0¦ª@7Æ5ãÚå³ì›y¼|¹2¿œ¨ÒJ‹‹ºªXROi"³%õó·ª°àq/ä0{I2N(ø[—=¼ïíyþ‘Á`œ:ó{¾ˆçÈPŸëâotMÁ}¸*#ÝmAµ#›®É ‘R[p´ š")ñj(Õh÷ §ŽÅxø¢ˆ¢N‡ClÙ2²a,˜ÍÁD„€]]EͳA¤K$º#&½ƒZÂñµ ž€a‰lf*cà8´‰šÎò¼‚Áô Pš ºÞG–k Šì”€Øß¾E¡“ç‘iµ‚°ž}O1Šñ;g=óiÕAͤ6à]ç|¤»Ð_qs<œÖª@B]<¡cÌšà÷v墨üNÃ0ãÕ•^Ρ׺™æšCÈ]„Äk:ô Ök!œ”»¥Ý¯S»”âÛŽA5½(÷NÂ#r}Èweø EZÜÎÑða l©êÞÑ‹§Za}ÒCƇ‡×Jœÿ ÙÍÌjAûxa¬_ÒÒd¤:½ûãаÊÊ>UþÍR£Ð1â·Úôôâzïøúƒ—ƒ0QKIþ®§»[ÒeÕÒY>_rùœÜ«¥TÖ³“æ ÖòÁ0‰Ù ÐtšåÁÈ1â\M÷Xe©È§ÐΔ;ê±|¤kÈöZ(-‘ɨÙG®¼i«ECøˆ%½YyÛoàAì(&yúLAÌ{C?âõa‹O)çÒ$l°x›;rkÁÛÛ®†ŽÆ8]HªäJÁÞhââ˜ì ^­@M 0@0Ç"·¥Òï-·ÐÐìÖ]I•€ ‹ïfî¼B_ºÇ_ÈÂ8NåÑÿ¹]ÄÈElj°»$~M,›A*©s©M$Gÿ¿ìBÒ—¤”+›ë[u´ÅèÐR3î L€Ÿƒ½¬ïIÞbÓ8Õ­rïcÀ%Þ fÌR8åü‡€q_•›šrÂXŸŒ‘3ç¾ÌP_#ÇGÝù–<ÿõãV•´Ñ 0'VÈ¥ô$3zc»~¢dˆÅÚŒXѪN"úîA.X‡àn› ››¬àam î€HǧÐ7Yl¢")œ¹ÑÄ[„>öºØ«õù'ÁÔò9J(ÀeárS‘ƦñòâïÝ–ŒÛiÀþ•¢ŽÔ±K4ÿC‡â³èÔñËPW4^iB& %¶d„ÝK{2lWÓ®òÃã8;”ïN´üTQ.šb,Û÷ÚÜÕ_¾tå3>ÛªzÊè5{§Ì íIâ"vjߪ¼O‰4¾Î`ñoù]ÿÓ¢g‘pëäL°.^³R¸3‡ìl„zgk­TöœÅ4µS“YŽÁÆ#èu^t.Ì­nÀP÷RPÌ…!«ƒü̸e²Ss8b& eÑ´Èr‡D¾•jV`aB¸Žß5€•¾åxŒçŽÖÂMûwmS¥ a×ø‰²¸U¥€"êü°õÿíƒ>÷Žr¾¥ ™®­œjWX"R˜2%]Ð\íÖÙ'*XÄ1ï1mDRÒ¡Ê)`?ãßÃÞ(0L† øÕPóÌÑ&ÉMx FµøM#wSÍÓeCˆänä8sùªV2Œ_¸ìç¼#ÓžYª„Ba>y'«ëê¦ûì‡yX¤ñê¯ÑZMŸ¯œ±z¦T,zÊ弤òĆ.-š;’Ú ôÒYµb÷ðËö ¶0¹¤xJ¶» î:\\P"@ß mv\¡ E®êä‹÷jSù‘T ˆò€b@ÎGFçw>åòª nôs ,.¤;÷rt}"§¨IyÂZw«þUà€R2¢l Q%Ù“äüÙœ%Iásö(˜Þ% ´Û²Ág]¿‰ÞÿšÁÑÑ49ÛBqÛ”šqBúJ“Ì-²þ€ÊöÏà&±«½Ü[K‘š¬©×[7­<ˆ`NÈÁl“Í6¾}**– n…pö øª8“ÁÑk—Z-`•ƒH{WY6ÀBƒ¸"=•Ýzml>"55†² Sº†·Ô,¡£â:¨XBkY×ïZÚÓC‹½Xô?¤OÛÞÑø†6?Ápu‹$CFó«õ.²ªÒŠ]ëLƒ3Z „< X±wÉ'Éàµò„Š`Ry×þõ‹Øˆø>ì,ëwÅÞ-·¦\à?Œªi1wå®4)‰Ùô!RÐÝ`® èÇðë³½ÿvÂŽÇyú˜55ÈU‚p´~=[¯¿Êe¶v¬rivWº+b«9Ñ@ûXYɪ¢¬l`ânfQv8 jx^b5€†—&Æ+y%ïÚ-X0éÃvÓ÷Î{e‚Âó-N@¹Ü\S¯Wb!¬e„Ùæ$q3ȼBµ½=À@(Öë¶ÂQm!T™åµEò¬v@œMî*vÞøE ¬ÈêúòYe”,Jt]±Œ.Ã{]ÿåEdª{&»À5—1½-¶B-¾e0Jâ'£Xº£_ 鈉ɌM,i…pv;®0b³w¤±b¸H$!£d‚ßZ6šD<Ùu7¤˜s¾§|+€ëJ©Çüš« J¤WÈDfL+á´¸’Ä&6qþ¹é€söS9HàØyl NqÖÇû-tìPøîG“VîÞ÷P,ï”yÈv î…ü7"ýÄ%Á¿aù+]«0žQ& Žkò^nŽ)‰pé ØCñcWx˜€iÈ–—Ôý'[²¡ÓÖï/ƒ¿¹©#é´`˜öGèÂû¿Úu»S¿cæ´A ¬ó7 |á9“]je(Ù.þ†˜œù sî¹Ô²@hG[î ¼öö;úé´ë΢KÓz¸Uº­uûšGøK찆ܖ+ç€Ñ"ÀŽ:´ÑKÍæ°]·#œ§ÄI£Xbâ˜Ø|i-µF\‡3¾n â•˦°ç]| (Çn>²ŠáB×;oùøË5'ïÂjlø÷É-åé „Õž NÒ…˜ÑeõR}Ô–ÚëÕ&|In'H¼±ÚcîêÜ\Dù°òXóG}ÒH´ó^b^wÃ+úeöÈ¢‹D`SÎ’?(iDmó’›”â/vY¬£7—ÓËÑbç‹Ƥ±Ž`ÑC çš¶ÝÓ6žØãZÓU(»?è DGé)gV\O¡zø¥ò‹ùË\TC eh½Ã€ä8Ûw¢ÊY×AVÆìÔ$°C¼£þåFÏ&‰º± Q&CýX&¥ömj¨¦?÷[³Õ‹ó³ÁÅìøÉÕ`ûø“ öü8¬z’€Š·v2›§˜vÂúÆö%g6Îè4fÓËa§dÊŸ#¦0~ð³÷v9ÈlçŸâ¹·¡œ¼L]‹ µaÐdÁàÛ!Ýyâ?Bæ¡î•4ähºØ[z!8 m­HîkFw_pÿ‹Ó†Óò¡¶—£2lÀqö)¯GßÊŠ}•­–.H\̦ÜWê ¤eteÄkòø÷kí?o±òIðt.ÁÔE,¿€|žwbÔl¿ÜkÎFþ¸ÁEò‡ŘR<Õ–¥.ËCŒûMÖh¥ ZÝR[ÚìÊû‘}˜dõ¼t^å¦h>SÅ,ðj1·^jäüLÊðßÄ7qgû–'r& H¬7‡®CDÄògO&ˆc<ÅUBx?o\š]G³FEš8/ιù2íPæi³t >‘®a…p,Ô¨Þþ™]‹Š*¬rìv ÇZçHëuªèÙDVš`9ÉJz= 8جa¦]‚l½ºóÌj‰(ž±Î:Ñ]l˜€Ô°¿ÖéçL¨£H4EÈz9Ø;9dúO§œ*†œI.Ú‘‚‘`†½aod Ù€ÌvQfö=Û‡çîUÿB´ØZ4ª_J° %"tü0Tæa ŸO¶KoV…^õP$([ÎíŸh8š±JÙá³+?QW¦?Iç˜|lO”aÐ00„®#ëyLË H0à+6öc×k-ŒàöžVw<#Ø6’»jˆq¥$@(,å(NØ]]ä~ðóû°y,**/¿ÚÜãÖ™é`9Lµ¡Ïë'"æ½¾lÉ5m®ØWר‰…’¢ËàD±œðÈ/àEýëˆ$ošQ¯ÖãØÎ ÂiôBN0…Þv&N`a™y+D¢RžájtLèámÈsûYZµ¤Ê0æ áCNÛ};é ”O#æP÷øÕji–Hl'ÂÚk%]ï‡m•ãÒP\°ù)éªÓ¢cù:»Ø1w´‚¢¯¼ká ሄ?ØØ¦Æ2NCÍΘ£6ô½M„þrÀ‘u£3« uÆ7‰mUÞ•Ý6s7UQÚú>TÍ·ÂüeêB¯‘ãrUFéû’ïÔ”öL ÿéYÍ\µŠÏ‰ÃgÝÉÛ  ) 0÷Y0ñѽì-A¶À­ìæ0ƒ_ú/¸Lñr³JËÄïÞŒ¿ðœkɳ,Ú™{†D¶Q•üLËßüúÏz˜˜rèHx§„a,Dá!['Åu«==‹–*¼ÑÌOÄ•lûÎ(t?,¨—b›Û>4Ú¾XƤ©©<ÈBe¡hƒ´~ ç™sWaY‹*É#}ó³ô ßž^sËþÑŒAØÐ÷7^Í¿Iò;¢æF’I1uSt”ÐIí/»¹&D+I0ݺ{9מŒï—ø¡"q@ìÜi¶t?ÐsZªìå{ÆpÆ’±û,Ŝ̰7k/­C»ÍïÏj~#•üú¬„6´ƒ²ýâ$‚ynÿÁT²•Žøcâ|Ž3.Þ5'$YþLºåï©e©¡ ‡wº[mÇØˆo ²†O! W©KL(0‡"»Ÿ<Ð`~#'"«ç@HøºŸîèQ@Z QƒÂѤ$òíÌ/JÑ0kº ‘HñkäÌW’"$‰,ƒ=gáÒûN¬ë§ìsai3ý °ù_ÊÊ  xÞ–\)Ë]gfÖÜc{Xª0™ŠÛ%ÊKØÎ¬! •ß–.ËêÕNnÞ:ÐÛ§NB\Ф#ucýœèvÉ OÏV‡ ?B™îÁkÅÉŠÎ꫎ ºˆhí0õ¢¢˜ íeº(Q=Œº–§ª·}¨W“ýx1§ù<íO“bÂÔ£€€·]öÕé™g$äZ©”t}Zð•?T-ˆì \úª±nDëï¾…¶Ü¾9½û~$[7#_:u‡7j÷¦‡—G¦Ñ—°dX·§¡œÕˆsÞèé´PeHÝ£(ÅæÏÓØÃÞ4‘³Ýæ‹ïäîé*MÊh"Ìb 7ÿìG «ž*¶ çø{Ò½âq[dH{?àè…¤3©55BXÀÙ3›ŽRxׯ›"q|3õ¡0‰˜¬Ô‚5zÐÊæRÊð >èÖÚúSÞ–JØHëFø!÷š(ö@¶zÌ=„W¼35ƒº5 k8ZH§tO³›‚q§q¢1t‹äªÏî âö–˜¼EÙdÒÑÍÖ?t¥‡a?ìýúòƒMf-W´³FN'1Ô®1Ù Awtù†tµ¬ŠÏß¿lŸÏÝÿ,××ó'ŸÀÃ'É(ÿÀòDM kìG`|ʯ–€?ý BÆVã_IKËÅÁàV¶µÓŒ¤»§Êò-ýóG}™¿?ÎH¼¶>¬„;õS¸^é+†#ÿ&ê;qÿ¦UöóùlÄÉ=œ´îZ87%ô„ÙåÉ„¦ Ò }5­Rþ%eÈ›£/òâzv‚Î?­ÚÔ—/¬ø€mp¢¤LFßR1zãi³˜¿bŠÇؽI ‡‰xÔDab/'±KbnæíšÞNmPš]üÔYÊ(†°'[½ýÍ”qÃ"†ˆ’{x vZûêšo²¢+Hª+/,# :Y—¤QwNìqèÃP(ss’SÙ@1ê:F¡acx*ÜÐ-Gc9Àsés¡‡ô*5]–DU\aœø mJÂ?þ²Ékn„’Åù®âY:PŠç«Ð\Êï¾òKû‘†œA²šâº„_”J~i¸a:û);ª<èf5ïdöónúþûú“Íç5lÛ•$}ÅËí¬ÖÎQŠ·~’Cõ,YÆ’mÔ ¹â (sVÈh.ãyOÝéu»„@ÝmùÏuUz”ÂÿC­8âÙÚñåäÝ õqÎð¸kˆJs²˜Ϩ2ýÉZ_²/_a$ëvS‰…*®XTéäú̾›tmìEyKÄÕ¸¡ú§#ÓÃÈ? }RqÎû£Ø1€T3àsï 8S“ ¾ÂâOPÛCè2~ü2Ž×£!èñæC¸MªÎ מRíš'Ë’†m¼Ni8 tú *)|–†Ážõú8™À¹[þ~”Š: k>8Ÿ½J¬I,klÌ 6ÜWNb {ÚÿÙ3ˆ¸0‡Hjô“ƒ¾ðÐÃsƒ]ï{埠W·Œ“DîZ4§R7«Ÿ†¸Á \v[£›šãáb/¦oCô>ÕkþXˆ9z»KûlíȶOÍÔ±'zc¦ÉÓÖJÓä‰L:^`r‰õä©,¡µ2%ƒ¦ŒøEezO( pÚ'Ê“x£3´HªâD¸ !Åf¿ ]$=â¹ÕÌ‹üê:B{nRb™m—Œ®Vyî\jõ¶ëD°©ÆYÈrZÓ?:E&¸´ùáCЂßÚ³¼²9=‘0Q*á߯ÊnÑ µ¥¥/¾‚Eº€[:¤(Ôî” 'ÙÎ]V!¹ÝÂo•Þ1g…¹'’]ÂFòà8ú#u£žiìT4ô‹;¢3µçÏHIá”…g’ÖŠh$ß±l+Bb.øçAy€‡eœyp-m£Õ£âQãöYvYPàmØ%ùÃxd7ÎZ¤Ó‰¯íFÎ{¬Q‡á+‰ ¸¸ˆ!qÓ 2ÁŒÃªgó¬a㟰Ä}r†‚Al%jëm)¼DÌ €G!\9eÄ{#âGÿ ´®C†Ïÿ-×1ª®$F…C3"Ñ\Ì”ù±²‡Pf¿eèLýZB9ÐQöØS˜•žmxkxKldR±øN0Ikf°qü’Jùõ^šžBþí‘89˜$H͹¬-ÝoG¯c¬b#åO« wšè¶lŽ7‘Èï'D–`WÈÂãÁ¼ eÝÒ…Æ2”ÜGsª•jýGÚ·Sµ«Æ‹á‡L‰XJçbðtœš°ýÁ+ B lØV€P¥š ñ*¶?<Á±/pãÚOªêúð·± ÷¡%î@ŸüpÖÜÀk#ª.ÖØŒ¼z¼|àA<Þi1½c1æw‹c(•Që•¿·ê»;ýÝ"À¢»>}T~í¨H~B'ã‚ J®‡Ÿ­íåÕÊü_(â“=:Æ!MkØdY™ìBæWëq ŽV'Ìë §¤ W 4ìß$s–^åg&` )=hTñÅÕ ÿäÀ$*ê…’ÂóŽ[áZšÇÌ_p=aØ€T\|0óÙvy6UêYùØÄ¯f¯ô½F¶Ä“æL Oænm¾\â|0#5Âà†À‘ϽTñ'ΫÝÞ<]Ȇe‰¯ÔuÍ ¯¨µ}—jð#㈛ àâ;çÅF&ãM6Ÿ¥È S-Ú›g¸óJ«G[·U •çç¿Õ·øU:N¥6!ø'åhÁk‚Ñ$P«(r§òÙÞì~#ˆö ×–%øgð€›òÅí¯o¯¦…°e†M:8ݹíVcéÁxíüÞ}Çpã“–ò‘ú𻟗3ªœò¢ë.Û—žtù‰ºªeÇ•ð?¢ Ú@ŒËÇàxRž áñÑi Ž-i…QÄJí÷ì)¢Mnêö¥¼’5Åæ ¢Ôhz¡f è‘bf{§-«Cº_Mb¿™y?¡æ²Ã¯.OúÑÉM•ÍÚÈý&*²XŒ(€ðNGÂ÷©,ùµg¿ýéeÁl†H ~#€ZíM¦ë[¶zC•A6;ÌŸØæ  $@ chmod +x $@ # init_gnunet_redhat \ # init_gnunet_ubuntu \ # visualize_stats.sh \ # gnmessage.sh \ # junkinsert.sh \ # junklookup.sh \ # namespacehelper.sh check_PROGRAMS = \ test_gnunet_prefix if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_gnunet_prefix_SOURCES = \ test_gnunet_prefix.c test_gnunet_prefix_CPPFLAGS = \ $(LTDLINCL) $(AM_CPPFLAGS) test_gnunet_prefix_LDADD = \ $(GCLIBADD) $(WINLIB) \ $(LTLIBICONV) \ $(GN_LIBINTL) \ $(LIBLTDL) -lunistring $(XLIB) pkghellodir= $(pkgdatadir)/hellos install-data-local: $(mkinstalldirs) $(DESTDIR)$(pkghellodir) @$(NORMAL_INSTALL) for hello in $(srcdir)/hellos/*; do \ if test -f $$hello; then \ $(INSTALL_DATA) $$hello $(DESTDIR)$(pkghellodir)/ ; \ fi \ done dist-hook: if test -d $(srcdir)/hellos; then \ mkdir -p $(distdir)/hellos; \ for hello in $(srcdir)/hellos/*; do \ if test -f $$hello; then \ cp -p $$hello $(distdir)/hellos; \ fi \ done \ fi gnunet-0.10.1/contrib/openvpn-tap32/0000755000175000017500000000000012320755622014152 500000000000000gnunet-0.10.1/contrib/openvpn-tap32/tap32-signed-i386-2.1.zip0000644000175000017500000010173212062314071017777 00000000000000PK/\ŒAsigned driver/PKltAsigned driver/include/PKtâ@@_YšI #signed driver/include/tap-windows.h•–ÝnÚ@…ï+õFéMRÅПDQ/³+`»¶ EB² ^ªÆKw×PTõÝ;k“@@!Ä7˜õÌ7ÇgÇcúøþ|M¯:`YÂWªU0áM!lI( Á—,¡°dBåq *^©ûGB—lBašgÅx§L­g°¡×0鱿ŒI˜pd®b ,“ &hã5¨Ëöˆ–ÔllDè ­xÎuWC\*y¶O“<X¼€â_‹/Ö‚=Ìœ[Ш×ÕFݨƒ» Ù½ç@H'³Œ§üQY;›Ô*%,Î/hJc‰šò,¡¢Õñº€b¤–Ñ€sI)ŒiÊW{R´_"žkÌT`”äSµŠ½†5ÏagHO˜T‚s…j•.ú‰ ˜ó„M×I¯nK+*æø´Ôáô¡C3*p+¼|œ² tÑ÷LÒ­¼Í½  g[sÛZQP*‹Äz·ŽÜÄVk‚{UPf|Añ$VZ犥)Z¹¤Ó<Ýøˆá0°Ã[·‚é a`ú¾é„Ãk W3ŽWé’–06_¤ Ù¨HÄ™î™iÉèߺÅ$óÆîÚáТ¶:$ íúتžé‡¶Õïš>x}ßsR(ÕØq̬iá8šP³t·?‡¸OE¦ Ìâ%ÅýšP¶D‰1L°±^߉ÿ)ÏŠûÅð­§Eï€)K±Ý]oh;´v’æ yJ((Oöë]º¸6…Œ« ¬SHáGwõYk¹Â¶Ÿ/°¤—ÆZ ׈f³^.•ï™õ†aU£YÿÐLüéý»lŠý8…(‰ l'ºÅE\a}¾øþÝf¶|ß=ŠŒ۵®< ØÔÙB‘–넾ÛÅß9ôwN¥ªÌ)vQr#LWá¼mwIÔ"÷¶E¢¾s縧9P&U ˆÂ®ŒLËÂnº(5ƒ'¨¤™ÒM~Y3^PSÈ:$Œz¦ÏŽ=Åš ´•à“Њnúí6ñIëâöžøí:¯boÃöÂþIj›oÃÚNÛ=ûùt,&¶íNä¹¶F¡[ž¼€ýr:6Ð&–mFAh†ýà˜Ú¯§c7j[·–‡ü8†ýv:V{Ûu;Q×vÈkÞ^žŽÝQ[âzá‹Ø«ìãƒb&8§ÊǤÉf•%O©¢ò¤ýÄ´ãþóz[õC‘{èp ùôAÏÔ5~ꬷƒèø02[¦?º#C8 †AHz£‘• Ãâ™< ¨Â¥òOÒXÊÑèïçVó+¹úÖ¨’fãKÕ0,R½i[Fµ~‰%7Ĩ7Ëg»¥\ÿNß©C¬gApzY‡ª¿ÞTx߬CÇÚø¢’k©è_b¨òÝñíuóúñ{¸_å`nÙ>œð¨F”c”}¶ Æ»ÜÆéC·ŠoËMÜúøÇe*w؇`¯Ø?‹œ~ΖöÓ,aøåñPKfô@Ëß<®Nsigned driver/license.txt¥\[sã4~†ÿ é íŒ ìr§ 3¡Mi ´%I¾á$Jbpì`Ù-ù÷|ç"ÉvÒå¶³°mlûMG™ ïßÿ9+>zýþôéÇæ²Êžleòla g¿|÷Ý·ßÿû?x ™m2g–ö ‹ÍR=§Îd…Ûe•]šùÞÔk.Æ÷#ÙXßÂ^™n³²0ßÌÏYîÊbc•+› pÓbiÊùovQ›E¹´¦\1Ì#´(p¼.ÊݾÊÖ›Úœ^œ™×~øúý×¾úÐÜílñÓý­™ÙŦ(órY—˜q±$´-­lnSšb)yÏoïo 6p„ókÅõv:žš›¸§äGåÃÌweéjó“­æMµn3įêç´²„Í®*Ÿ²%°y/uïgî½Äà·ÅïEùœÛåz ðœ +ÿ¢Y–‹†3ÿÌsÙäKÂ>Ýu°—$¶ApŒoeÿhÈŒ›×3Ÿñ»·Ǥ€(+ò½Ù¦ÕïxžÑf±It{Ë‹Üâ×ñ!¤ð&^|D²¼`kØh¯À€å¶|R!Á5•õ)hB|Ë··æ¾™C‰¼ÕšSØõý­·ó.'Âe.IñŸÁcz s꬈ãâîþq2þöz6 mƒÝŒ ^øËò ª¤Þw%^¸´‰8,±%yB§ì[oû‰äoG·£ÉðÆÜ?|s3¾0øot;É+òç'jb¾k`¨¯¾øâ•@éº/<øü‹„›+Ø•™z¼*A<«–¸SZzüÏ'_Àûnwp8÷yº°‰™6lá£>LÌ7p‰ᇡ1¾~õêÕû¯>úð3c¦C8KáHÄ1’¯©Õ¿,€$kZ4bÿméaÆîÌ›±X0‰„5±I‹5©b¬ %a—ž£Â¯ûʦ[8ÌV¼ò{³-¨ˆÖJÿ-­ËÖ…àZ§¿ãÃçtOÖMñ…Ô²ÜÒ3·ÁÛDˆ cÊÀ˜oö ¡¨«ÔÕ,|ª-l•æªÏ£M¨g0­b)Û­›”ý°åíÌ6ãgä1ÿ}¼´%l]S±³jG&~›È%&OGŽªr‰a£ö Nœ¸u@€ù¤!½«MXõé½èùÔç³y—XU‘sC˜ÙšçMéB`㘑‘§ †â—ðñtZn­,|Q{[$œ'ò)’±(ãAȼ"óUkV’Øe+N³•„¿ÌmÎ’löäÓ>Íõ*fÞÚ‰2¿4-胸˜Þ îè(àØ <Œ©‚AFdŸë …sR¬‚i€¼ätAbp±v1K-iyMK”}¤#~äk'»à-ˆ-󌵘-mÁî@¶RX €•Ýý.J’Qe5Æè[ŒÐ «ú;Áè]ލÎîÑV5‚4½±ÃÃlžåY‰·"Ø*@:&áW`¥¯Ã~—ÙŠ;0å íŸ)y÷Ä¿u $§&õ×6»ºà÷:#ÚÅ·˜•¨J­3ÕJÊY¬¨ùŸÈ᱘™!ÀuuOÑiÑž 0 •N£lÔH‚4,–·)Ÿé­­WD$òU —•ˆ~ʈ(A-Ú¹=¦;œÙ›úr®íÎ}iN_qdãÇ])ÂÔéë3pseYŠÝØö¼Éæ—ㇹ]ÃìB†îÃfÒ‘:Áý ¬T´=öCTk KǦØBœî{ΓØlN ŒÍ-Ö›ƒWEbXè’:¹ ]Ne%‡z†6e*û¡j@Ùr?B ™”¢®Ÿö±¹“0²K¥l”m<(õ+®¥Y@šÅ(={•aµÒ ¡“¶&ØÅÛ&† MØr<šF.Ç嘦ګ|*h€¤ñì=JñšZ Ÿhkô Úªã΀UÆO©ñµÎ÷̇bwô´’ô‘=2{›§2[2Kò¨ÓÞ®«ÊŠ 8õ"ÐM…$°ÊÕ†CáÎNG¶ RB剅Î.Ø%õo¿b¶FŒ¨›åú•OÂbþcíB Âʦ•ñ<diy“sÒ nï±i5[‘â{)§}nWHÁÂ9• ”åApÙ@IÒÉÙÕFY µlÕª“€¿óÏRt<Ÿ&?LÍðöåÃíåx6¾»š«» WãÛos9žÎ&ãoè¿øÃÝåøj|1¤YaŒÉÎÓç/½íg„q[óÛžàÈl³++_áe5‘$Høú…Þ’ÈÐV$§Ž:Æù%승Pj Ía¿ 9”ø^×Â]¬Àì$,‘6¶Z°Þ7–ò ɳ >+دŠãÍjŽªæ@ùÀï~šA™vÿ+Gòo„àÜÚ‚ÝQ{kîü,‰“ ŠW5Ö4‡|ÔŠ¤.KcÈ«$GéþŸ”ÐÀ­ ê=×ÍHä1™' ¯gëÙ"~4Û$t3Û…±i—-š²q¹`î$@«ñÉŽ\Û€Î7<¢í·%X¢ú'O ÷ÝlÔCqn~·vGæ’.Ø×«8d¡¦ìW`Æm5c ò~œ£ƒµ f(Qs^¿äÄ+Ö©1©è3ѤL|w"(yY¬Ù(Ûï«èTjZiIš,Ù…«ÍÞÁtrÕy1x-u?Ÿ@îŽHlÚ©/Âë¦VfÇÁûO©¶b‚ôéuÐ'Í ªRXE5:âa½<—¯á躴_tßLKÐßN:K¡ï8K mGBÐT‰|EìŸÃ¶h,Æ•Ph˪£´82‚ØCÆŸô,‹T:¹6楫,—¼§™Í •œ€ª¢Bqä‹uDAøÏþI`o…&†WI}k±™÷±¡×˜täåm/Q÷R( gy~Îé]U‡?s,}/öPÔ…Vjš_®¨ ëdk)hÒ}Râ‡j:^S‹Íªe„Cq¥/ОIµ±8“r!Š"$ ô³WäÏKé$·ÒR«R bðI ¶ Ç,õid+i/?$ÉUˆ&Þ{“6³J*€”SQmÜk_¬ZJBæÎæK“ˆv9Ù¬Š?e_D­ÌxrÒ󑿍‡L„~ô†ÊëSí”Hf•Ñ[ˆÇ%,9 Mé ’WèÐÐFïñ°Í”c›ç áò»4O™}îyQ…³ÇÓÑŸ Ë®íK“u¼…l›ÃátDLý`Âñ’Ø4C¡Œ¢Ã|V„ªë©L{ËþKnÜàŒêßßÑ÷ù‰“ž"Vv´˜wަ#e1e*”Yà >æsâäÔ>ÒšùëEÓM$®QwD^RÙ·¦)á"BÚy ^ÆV°MèoáB6¹ÇŸ¨ÄÏEÇFYÒ$1áÜ'¬ÚÔ–=lf}ÇE[€ ½í©‘ÞÔa€t—@±·‘;´«)~znj1”¹N0œ^8¢_ú‡7ô™@ …)>oû*ÀépB[Ú±aƒXèk³r;ãÚ†¤0HЕn哨†b 'OôÁB\…¦PµD! h‘LÆ–Þ ‹üÚnwdœßz[ó£-8ÙŠÝKI…YR«Í…µ¶¬èü¦0‚²´'ðÞ¹©R"2‰›iIEäýIgÁGžô±¨Á’c|»pãvô8aü¤jq4¥PêÇ4™œjmÉ+¦ë5ñLûjKèÁÏGP?‹cwJ¾)¯9ÃïxþTæ8¤ IQÊ*]-J5ÃŽÞj^y_1 NŸHmôbŒüè…AŸ”>ZÈòv!©z}av¦9¸YlMíÇ4 ôíbêmòãñÚpnöRj¶,QÖ=æïfeÃ"û.-øX&H‡>Ë-ÇÊJzåH·°äeïSJ@¨*˜V铈o`Ûî5;Þgjœê’ÅB÷â\^‰ƒõ ÖÑh«=ˆ’僙I'Ó;¤0U‹Óô>1Oiž Hð†^jîzúöh¬ñU(f$íb×±Od¡ÏË :ΓÆ:»WËrÆj’|O.M³zaa×fá´‚Æÿ[±¾'ª¶L$¥TÿT"/ËBàüg‰,Žë-!fˆG‰Õ3gÀêÕE\§s ÷2ñœóP·OÆ" ñ>1’cmß¶Xq´ˆs6ýfŒ¼§Ç9!`ÙÎáþyÕí8U]”FÁä,åi3÷qe.²œùˆÔ=&\E÷Ã=<ÁHŽHE<[U~I%¥óÜ« ëRΉ¯¸Li!/}D¯–~€! d[©Jq£Ïi›†ª´,VJ¨,óÆi5„£ˆRFpDƒV)…]eÇ®ñü ñÝU¶“÷¥ÄE€Œb–§^r| Òvé­×P„'€³FÂÑ3ë€õ sÒ§ªmJ|ÔIñÆwåT“J}K*$Îí…ÔóÒn«‡]V:ø$µ³h#Ûô7<%ÚÊ‚³ßS¡“ðþêmóDòMrýgJ'%fp5R:»=ÎÔ¶x*ŽºÇÔg$‘¦ LˆñŽ›Œ–©Ú/jÍÞzŸ.¬úÙG|‡èëXGæ|oOLXö þlN‡™ô°žôCÚî’9‡u† 8s`{¢/=Ò]Ç®)È?ô(è¯Ox˜òðf½iÅbJlÓ£,ò¬å14º­6Sü¹ˆ1‡üƒ JËJ¬U&ùrÍ’;yíe]¢Ã ËÏIæ{MbˆÉœïR+ š²#*8szæl³|…—1Kçi¬rB–6>j …2lûøjä-Õ³›Òu> ÎXûk`JG`qpÚ+2Â$ÑÓêpP‘cÃb¡¥Î{oêQ:äÃßU“‹ÿÁ8i±ˆ©ä',JRŽƒª7]€z Ë¨­ªÇ÷^¡tX%«[. ØÑp_B¦M¹Ý=äV‘Iò\PxF5g,bÅ(•wêkÂJ*7¡¨ù‚~44†bõ*„ „)‘q"A èw¿&×ÅþMÇgÜuà£×…×$År8Hñ9ƒ(!QßÖñ­u¸)X¥ËÎ^iÕùt §F8V`\;-¡ÿ@{g¤k^Þ0@•×j¶…áÚõv f1Štvp‹ÃÄBû ‡ÃÓqcbŠv]WM¥çtí±%0„³ÿPò–«XõÆéê í{[V&}ü\·-ðÿÉ-Z(ô°ëÀ…š£õàgt’$Ià†ŒXO?øc~ktüX’žX%Ë€Ì^­(^Y}0‹g$ÚS2§E©gâ$ô<ÝXwF)uä/Ñ+\Å»š@Ÿê,ÈSÌUr†ƒÒÝoÝöîgñuÄF$]ޏIß‚XçöjífǺÌÚõæÕÒ“óÓeÐ;¯(5ïw4¥sÙ¶ÉaÈ–Çô±G¸ÛŽÔ:¦Š|%wX˱B\¨Í·jŠïö¸eú‰Ãy¯4ÊZ NÍ ˜¸e¨f¹GQ²Ÿ0¢ñ«²´÷G‰¤íGÏ›´†: ˆ0Ú"‡þ7*c)?!j„P±R)dtô €Y`ôÌÒky…Iy±øð*ÍbÓJDþ"BnØ>ä:hžáGºŠ¸(çÙÅBŒÖRöÂ7€ˆ¹.š<…oÎ*Œ0Ó|f…p”ytû¡ŸÙ›  n©*µñµØ;î­ðC¬@]ýV{kç©l7 ýŽ#B’U#ÚF¿y¿Ðžàábœò%%Þ‹ï“6£ŽGú£43²š²iC™Š¾{ÞE`“jEtF,ý9gœI"¬+Ju‡];b×Ãw‚ØéNyMvœ4†P´£ÃüLQâ–«-ñ~o¢iHš‡é™a«Ðx¦AÄ5cˆw§ÕØÉù:ˆgA5 ”…´ð1½}ÇÆ†,;×Fp³#âM¢–e!ÂX"n-yÊ©1‚2u“4¡Ó¾ˆ{£Ó’Å“…vwt™âóÕqoÊ,ä›Üô8Tú8 „y¯|¯£cÏZ¦ÎÁûäÍcn"SLѺïÒcÙò9…Ƀ6´ÎêèÝ©^‰Ð:‘ä¢ ¨ÇŸùx,ƒ~ 'z¾KzéÍÁlÙ·~®ƒËaÙ!‘€zàÒ!Õ€ ¬--ØAÏ{Í¢8:Doë9$€°ûŽÑœ$‹®»8^ê5'Û’¡øõÞÁ4N7Á ¾C#ŸJ„ŽTPo¢„ÓQ“@ÐF”î,®|kÔÁÎËåþÅæø|7ìå+Û4N­T¸ ‰äDU€FÏà *Àm8˜zëäªÙ–Bÿ 2§ ± EŒKÖ(¢î`fá®›^·òkøº c‰¼veyÁÒBérÑ}â¢mü «?Îr†TJ㤻Ä`' ro@>þ oÍvn+’TÇ|ÏiÅ„ÞÛ}¨s£‹>bŸˆË§A¸ÊÃ8áÂ(”¶q¶% àóã‰{ÃóNÐå $±¼³™x‰¼’Nú9àA<¶Vìqì€pf€J­*Â"ª;ýÍ›8öá@ÓS?ܶÊ<&˜xîP¼vo&ØÉf×ʻɻj ³ Únd‘ˆ‘:nÛ¶êzI=Cü17úº"‡ö–o°çsÌóü8™ iÅ‘Ø ua*]®Ýp$$Ù2)q„),><à¿.Ó\ì_l³â¿˜`À55ÌgJ~c[‚?ò·¸:·¢<¬r[úô…ïwág½+Á'.âÌ‚ªäîå¶Û;óóp2Þ΃N`Jð›ÑÅða:2³ë‘¹ŸÜ};þ`ÆS?§|i®&£‘¹»2×ÃÉ·£„Þ›ŒðF¦–Û ðÞÿ>úe6º™{L:g3ÀûæÑ ïï~øÍÍÈÜ ¼t1ºŸ™Ÿ¯G4Ó|G[ü<NÓÙ–ŒoÍÏ“ñ Ñ2^µ4×w7—£ OP€ýy¡¹NfãÑ€€ËOãË.i'Ã)?1?g×w³@H˜Góýøö21£1^÷“Ñ\0Àÿ¼Gx<¾½¸y¸ämŒfƒ3ðë‡1pÙÌ"ÿ®Â'„°Àü0š\\ãƒá7ã›1¶¥™î«ñìÛðä÷Pð¿x¸‚”‡ÉýÝt40ÂJ€ë'ãé÷fHô)‹|zPÄg@ùax{ABë •‰6wm@ýÍ%½@þbØÈ\Ž®F³ñO£„ÞÅVÓ‡FÊùéŒuscnGÀy8y4ÓÑä§ñq &£ûáxbx†}2!8w·Ñ½€w¤9£ŸH+noˆîÉèLJñä˜nœá·“3¶¥4;¾¹!‰¨C‚Eü ªÃ#TëWOe|þQ†Ñ ö=Õ-~sGÜø8 5 C¬a]~;šíA-h{?ø[°÷£‹1ý€çPGÈþFøs;áø=3„x…@h§!Ù'éß­j íß·ÙÓ°{_'ESn‚Øh60þÑû“Ñ-øÆ†6¼¸x˜ g´¯FÓ˜áø–ÅPD7Ûúxrém9n®†ã›‡ÉÞaï»ûeý‹¢‰Š7=KX#Ìø Û]\«$¶#ÄëáãµáåOcX¥îDp€êXys'0ê/óÝ¢8§‰tãÉrà•bsgœhb`Åm¨ÝÃIc˜ŠÐšá$$'å,sƒïopíEû£ó(¥ù0D(•»Ò”L´P¿w†Ÿ®h³â=¤‚éÖƒŸ£âY$)ÐÖbµ–)þ¯ZïŠþW4·ñ5ö X£©Ô×qwª‘Û—Å::pNúw yìÙ½( èãÃi Gý…º&~1‚Ÿp/檇¹ó‹d´Û¾ŒÛÐŒS-<ÓtŒMâñ_P÷}˜'§Bý¹¿ã<­ÿŠ• ; UôãuYý“p=µ6~QǦ_*PY­Ò¢©ÉñBÔÙx¨±/ Ó=”|=GmLzü†TY!|Dò?¾éAþÒESj>tfdðWe”B®Ð’ÖXë«Ê"[èýÎ×À®ÐmYoà7ñ.Ñß÷I‰«U˜•Î3<Õ.;MâMqEN®¸´a‘…ØÖ¸Ù·²ò'. ‚êúEÒ3[²ZÓ5Ù#ë(Cô¢ðð›éÝ ’›Çv’}NÊâõÄÔ{èÿ¯|Qùù½AËnÌ>†Ž6ÇN$î¾jô¾Ukºóö–‹÷ÚÈ âüÎf¿£z‘éˆ}À“0 T¹ÃeëÞµŸvAúòåÁ»ŸéÑMØÑ½UÑÒAYÐÁÕ’‹=9ZŽwÕŽ£'Ïä(AÅÜòá.À¾¿¿sç=àÌCåý÷É…ãMº@Ç®í¯ƒPE›æ‰Fº.¯‘1•{,=•ç8ï­h„ë ú ”Ž"‡zPņ²kíÙù‚- ˆPÝ€Q i$éqÈUeª akzá‹RçøW¥ë³þPK0xtAJ6ï  gsigned driver/OemWin2k.infµY{oÚ0ÿÒ¾ƒWmÒ)Øû%1’mh% ºJÖ‚Ù¡{|÷ÝÙ h»ÒuѦûîw¿{øb{/Èýk|nÞ<ÒéB²É4#w[÷Hݶëûu»f“nJùaÏ#¦\$b¨²H›GrÁ“ƒ’`ÊI¥˜ÈpFàçXRJ”g§¡¤/ÈBÌIr"iÌT&Ùñ<£„e$äqUH21/Jx87ç1•$›R’Q9SDŒõË;o@ÞQNe˜Þü8a9`劒*œÔ·ù…À…Õ”Æäx¡‘Þ"Gßp„7à ô+õ÷Ÿ›7ÑÿìÍO¤õÞm}pû8Ådø±í9·aãÉ3{˜ ‘¨a4ýÆøçÍ/=* $ï$åÃ,L÷OoÔ‡¬ñôñPмտUr¥î è ²ÿšŒYBŸW«ÕèyÕX©¢•ª¶R5ØÕi6«Fwê`áAnáÁÒ´ð`4êÒÙGmÄ3mÏšÕ¾ÛéºÄé·O„€6ã* “„ÿ.õÑ Ù³ŸÙµ-áy ©¡—“•t&Nèjî_õApO€åL‡žÐ ÕsÖŽŽuacõCñ$ŒO °´é}à‹SEbÉN ŒOY6EaIÂ4µ@Ykª©˜'1Éä qÎô²`œ¨y4%!9 ±Và F#IP“‹ŒD"IXL ®£Ò”GWÊ::fœÆ¨z¼Ðš…‚:ïÌ“Œ¥Éré î¦  —{aFÓ"sf!ÁÂS`žiH W9£ßa™£¢àN¡c3Pf4aƒ â§aéNæàM³ª¢cÞ ÜçfJ›“ó(ÓôB¥æU„ÚI–GÕ&º/d4^«]ì†Íp,D(¾&µ92ðQw3 ⩌§Põ‘àc6Ul\d®¨B§¤0!f†âXŠQ4Cb `+yµÜ­Ý#}“bˆVì'xJic+0¬iduà¾3 ãàå*ÖwÁ6ªHh¨2òºA(Ã(ƒ$Zc! ¼uO¨ß#­iÈ'TÇaï–f­s½Wòy䫽ÂËøšAhN¡MC×Xqá HT´™Fn‘ûïÜÀkv\õ»ƒ~Ëõ·‘rç>,öF­n§×õ\/µ„ÄlM{ºŽ›c^HôÑ×ÿâ¸=×s\¯Õv}½þ¨<ÏÊU`/aŠU‘d)ÆV×MOІß6¨k¬£õd©ÕëwA+¡³ÐœGŽ{Øn¹ðßê·{A»ë·uádJSÜŒ%à¶ùœâ¿uÄ›7¾šnqtóXòÙ„‡ÙVã+²w»h:^p{OO·Bhbò‹úÆ »r% 33›ÀŠ~7h;0÷óaÜxLŸ=©ïÓFýÑ~­ÑýãqTÛ·ŸÂ.å˜ÖìFíéoT[†´î¿ï¬aØ£™nýzg²Üðùì´Lß5iŵP̃|!2†ÇKU[ÑèŽîƒàþ+ûIÕ®WaçT·žUlÿ<Ó±ñMRul¶3€1*÷æf¦˜;|¶·æØ†\>nµ_ûÿø «g>ÏÇa kÐp Í—ø4Òüï:‚Ó{×BàkÙ”‰×*™«ZÑQÍçR[a-‰Wx̬âå:B…‘:÷YÖĵèlê¤UtzøÀ²H‘3˜z­·£ÞûÏ~»Õ<€¸Øß퇥™Ãv?µÒ„ß}|löÝ‘ë :n¿¸Žª—„Þ·h’füiiÜëŽ|·}JÏÕì²NÓ Úzü©}§0ý«ÜêЧl)*OÂ*ýùVeù>F)­ÓŒã>À-I'‘HàL‚›„oµMªß|DÔQž¬€­ÂT}Å8ÿô´CòþCß"–xéÉaó1Û"{¹ÞޚΰÍ2¬8<Ù RØÊöñƒcå:ÀX=º@ã@œnhPÜKr𕔬 Ú‰¥•Vkü|µ¢íx°y±Œ­3ýžÑvŠŽÖ}0ÃN0XYYÂI5ä@hoí`‘–£Îx¶‹¶CÇ!lÀ‹hÖÙö.ê]…0É´“n‡q=Z˜ÞÍr'ü®G¯HÜÏhj•ÔÏÑ…Í}èg°µPÖ¹ùÒBÄHí³‘8 _ý]Ô72gï¢{É´­t‡ÈN t9ðÍ4…û}i‘gRà±l'ÀÚ:`N…X>gçB5[—XIÍv< ç§]P6ƒ¼]Ô—Á½°´šxòôoƳbl;óûZ€4#<îuéòZWß*¯+xq¹òZÓ5õ°]^œ˜µ wBY¯©á?o[׿„ÅnìZ,®tŠÉYÜò}Ð.ò<÷`d®¿p"ßr­‹á ¯Qu?z#8÷ÁAÃÏ7P—·º!™…2#£ÜEüÞt»Áȇ#zPPÛð?ûÛ1"Z`“zst×êŽÛizN ¡±)Ðö›o\gž‡—w¦øô¯vLù™‹©4 ¸uÈ3¶ (Uâ‰R53Öò‘†q¥2ï¬K±Æ] ˜wRÌSm·Í=]xM ᜉފ“·I89ó0Òêö>¿=xÿC»—(¶æ`…øp¯¡ï¿ó#Ën¶ô%º¾ØƒôS˜|sq o,ÈxU_-•3ÁƒÁ——s>‡;¾×\ºÇL¡f à¸ýMŠ"èmvKÇô;&Ô²tnZ6…X;»ü,Rªˆ-æ9ÃèéË‘à#se‰^€HÛArªðS±ÔP.Ãbµ,¢/`—ÿåÂðE;±d½²ªYçÌ B.Üá*SW‘äñmýtEPV¯SŽ×5Èšü‘ɦ½Ó¤¥‰eYaèÅf½ü:§H BÄR%Od…~§`7ˆœ×ŠoîÛ*WCý×¥v‰n—Ç×aíPKfô@fdfFÈ—signed driver/tap0901.catÝY <”Yÿæa0äÍ"iB’çÁ“B¥ÄD^•2Æk3cfäQÄ$eÛ¥-e*Ñ–’jQè­´ [±¥‡Dz¨mK/{¿ñhTûþíî﷾߽ß9çžsï¹ïÎ@¤“E7M›•örF+é¤BQ2ƒ!+y‚Œ™«+ƒþ+‚¼ƒÇˆìˆ±¿ Šb"8(TÄ`ð*rn¶~îÓö;µréŽÊ/F‘)ÀŽÈdš5mP’RÇ¢½ââ€óÞÓ±ƒ3,Ók„ ‹b‹ÄqB( ¾§#6ˆ-¤Ér‚ՄŶ9CŠ {ø >BaX€þa<,†lLõå‰DB°x ‚Ák &ƒVö°KD€Ä Àg„í,0C_ñ@¼GDþ =  tè%´5G†hÊ M…4¢Éh¿ARýbÉó§¾² q‚ 4è„#|¦CÊB2i;”’LÍvePÏJ-  7C²Döp`ø$b±X°‡ÇÀbðä…ÀØHI”1+#“vé'ë!èg§ÍEWÂ2}À8©#€×ÈI\Fµcô˜8ñù3"YQkèNÁ¡ œtÝÿʧ)G@’ô"áy€£Gipqý⻤ÂEð‚3à#K%5EÒ¹õp›\vœ#ó7´iÃmvº˜6#Æ7FúDd⋸ÂÙ½PñB+±Hí8ÉL‚øa(Æa1X,‘Iš{Aÿ&€QÃx†‘³Bd8o0²¢3;ŒíÂ’\9,ø­}ŠÔUbcc-ƒa 6Y²¸Qd30qÀƒa‹Yì°p’£@ÃgrX!$Ôè¡#ü^ ¤W#ƒàDeʉXƒœ¹Ø!¸ÿ¦é» JÁ­Ž”©ç/w=mZלm¶‹¨wh »`ZÉ©ŠÒ ßoÉÿÖÑŸ~µ-»Å¡UHËŸ}qîxÑËÙ{¼ÔhŸ»FEg$±Žì/XR—ŸúÊ#h^õ«Ó=­´Ì»„¹ ÅS&ŽÞoê¤k&E?°=1—/?¹šNc,Œ%^WvÖÈekaQ¢±_q\ýá<âGG÷æêGFAü¢ô›:³}›-ïèy™'m¹¤KÐÊ|oƒW_´3úê‚åÞ­‹ƒoÛ­>øÕÓÕzãí×ìª.ŸZ±¦"îÙâ^Ú~bpí‰Ð€M©5;Çë¯Ðe(Ô.:~ÇQ˜G;:§‹ƒGnwJ=H9'9)cHx"’P@EÊx<‡è1”œBtË-¡ÎG_N„Å ¤¯küqs#,jfO‰ãâæÈЫJî¾~(s-ÁT}ª—Öû/¿b‰3Š‘xôØÌÄ͵?×Wí Í#Ü.jŒ—WzçÐV„Uäœ:º'.©éá™@ãëfƸG‡ÂYí9jû¹bµG×óoLp(»çÓw¥)E9ºjúò‚ô¶KÍU›víïÍRM|PDž¸7 ”ç¸ýmÌùæ2]{ÓïWÉ0Öe\8•U½g{~6×Oñ5‡tJŽ\¾j{RJ_ãä µWEÓz äGïÚx¬0©Ü4{ÿ˜#[ÈçÇ.MzR¸> õgm£ú+Qu;skUb’û·SÞÝ¿ìD½lØp›oº-¨bÉ£Mºö‹¬²£fU`–X[}×f!°IÇO'ê­ïÛýú‹'¯wêªÜj/­Ùôp‘¢LÎ$Û)Úkæ¶Fž0J_w®êZÞ2{º‘¸ùÖ•ç³us~.à&Œ=´ñÛ²"Œ}ÆUfEpï_î`CBcùÆÅmöß4qÈyTP¯u61ÂÔmcö}·ùïô/‘zÂsWûu1«*oÖIÌ늫R*#»á[Nû×_šFäÞí ©¬´pˆj÷…¹P)ñ)•{ÓmÓéEMë×çYÕP„UUª!8ÙKO*c}o¤5éšØ\ãZzyÏ"nø>;þóß÷w?~ÒÉ3L¹;ÞðdÞEe×RÛ}~uôºëZÙ*@D8 !4w>Up“ì2·í¶WWÇû+°4••?QÁßÅ( 5ñW0j=½ØaˆÉ¨,È(pB;*ÙHþ@ÖÐ(d(DY’òkÐîÄŒd‡rù6sH(«NdD†0LŠ÷†`Ü€ÿº¼ŽÃ4?„ÎáFrÃØ!st2–CJ¸ßRú]8ýa±ÚNçìæ Uba·öM[bæÔ9¿¯~yxÔ&²k³ðÒÒðK:øÈeN„ œ˜î£vA°o‘û‘¶0Û Ê@µ1íÍÝ‚=;Ì{蘯”Þr'Í ¡Œj µÄ6@«çÆØoj­&y9Î:ŠnÜóÂ’Ó)«ßÞ6kz‡´ÿM¶—s™€²'ýLª ‰O ºšØ-s&Q³)µxo£íº„&³NúmËÑkNœ»5±~CTÏô¸I·ý'×·!ž¾Ê§³4›ÕãvdÖNºhQãñú§O)ã¢{_nþòÀî„ H¿D/ݽ¡Ö§}¼¬:»¬5Ÿwxï¢HeÍIWæ¬ m9ôH6«0¦«bNE8k«­F`Î,ÜCM¹ˆc¥~†³-{Ï„4¯—Ѓ¾;Úã¶*ò¯Ok™&\ÕœPp(IÐ"- À²É’S8f<^ rfxReq8ÀÑ ,ÅæbÓ4“ j=âTZ…3-X ô~ÂDòS}›ßÖaN „x‰L,eùÀ´Y˜´w‘8 dó}È5,FËr°ç?+ Ò‚ÅXðCx\[ÈåÇCÕ(h‹Çœòz ·¿º¢¼ Xr‹¹üž½Bzé‹·§ÜãÊÙÌ1ËLäÏy?ÀåoýªÅë’AAë5Ótù²¹6Ô̯ŸþÄt«’mx>ý~róüÕ×;¦$bèK[ïêž6‡qëŒ[…ƒqKNÏ÷qïá6q‰§"?w´üGKö/çÖ™>Ìî"šéS¥Øÿ&Šþ^„:Ýgx?{©düdÊ’i»×qy';¨ÑÑô˜ü}º™Ùé‹‹ £ëÝçî»;§bYõöš½´ l+ºQW¬¿ÚÙP¼Sí(cQú4gæÝnËetö¯‘÷0¶{BÏm¹æüìÑÌgÅ*‹¹•Wâ·ùkv<žXŽ3Íoè]©ãÁ–˜È¿1PÉ2oÔÑu#?»jv-Õé «K+©QÞl~M÷»/WvªìV‹~ÑòÃmµ„ævŸ ݘ…á! k¦úyZkËt7¨O¹@Ý­VOh¹ŒPŒ‘Cø|„aê†`ÿ8dŽÀRJ‚ýÿ5ê»À«>é‚úŸ\ßVHEˆþƒQÀU* LþÓQÀÅE'G ü§lÈ]RVƒ”T0M›¯I'tŸ½ò~.„‰dºV,t;q°ariw`IøÍ°ÚÆzãö:«måJ^Wý¼­ÝÛÿš½rßa!EÃÁRÅÍdñ€œ|ßóTÕ¬ õÓ|ºb­Ø¥+¿ñÞ?ÓhsýŠ9‡Tçœ8µçÂûõ= ýž9õ3Ù\KßÕϘXK Â?¾¹™Î×®R澕»GYv5µ˜(?Ã8÷ÁÓþþ´ëçäé¡u…Ô ÚJ6gZºW+Zo,®äxô&­;©ß$Å\ "õƒ¦"ME´‡÷QGVúWГÒU +E)^~°Ã“á)òx½{Ž\ß™ÜS7«©ËÙŠ &éÏý(1±àî»´z §üõeê´3‡Ü¹% ù›› Lyã¹zý÷k¢?0÷íK°l/ÄN÷®XSÞI©ÆÇbgˤÏÜ*>¹£X9wï*½åž¯tý’õ‹ PKfô@4\]ÖoF€zsigned driver/tap0901.sysì\ XTǾwY–EWÄ`%¦6>‚¬R`Å ¸ Æ€Ë.,Æh[‚îUÓˆ,«\n6µmš¦ï¦ïwÓ6ULšò0Æ IÓÔ¶6½dÓÖ&ÑP·ÿ™»^é»ýúõë…¹ó:sæÌÌ™3gÎÌÝÂM¹ŽãôpÁ ÇurÚ“Ëýõ§FÇq óOà‹æ†Nþögn(©©mJmhÜygãö»Rwl¯¯ß)¦¾·*µQªO­­O]»Á•z×Îʪ¥Ó¦M™Ïýÿùox>1ôÂ]¯|ìȪ°{á÷‹WýŒù9ð)­sÕ%øs¾°êE濺êç,?{Õ)æ/ Å2ßY»£†ðŒ¯Çaã¸Ûy÷ -ÞN;Ïéø©|<×R‚ˆIKûyǵèáœã¹¼É& Çž* îHJAÄL¾™ýk¡èsxYÅ[9®+†%Eñ$ÁßÎqË‘žæâ¸”¿Ð_Ž’ÑsC£óÑ¿¿T¬Ú#Âÿd¡F/WÄü1O*¦ÒÒÆÊí"h(ˆÑp¶hþ˜'ÙK50n/%¸Ãü p}ëŠÖ•°ú €!8æO¨÷—K›wp¡>Ù['à[³´±ªnç ¸í!¸íá¸òQ‚¥ÊëÞ×M.e«É­HÉeJ³Ñ] ïu•©[­çëî€Z¢‡óÛRróˆ¼uX})å/ú†„û[pÙ–ÌÅ„£ÓÐ<ß9ñ=q\@ò“®W S2¯«•Ë—_¹~¨õÕá`ðÉÖ‚ ¸[Š¿4Õéð^*v•õÚ.Qê|+aVl—”§õù3åÒ¹pØ7´÷&ªbP¼Î{…ß•¨Ø’ÅN5à8Tƒ*}CÍ‹‘þ5b+qgùp±¿tÄéáÐ¨Û cëµX ‘”¬ØÌ¾.1V)‘Š-‘…K‡e³ÒSQ¾YùõÖã'G?¬¿<×j†Kx®¦a5ÏU>ÂØ”ºÐ]öHª›ç–Ù†-?vøm+¿@Yr•j9gé’mÉh}S¼GÞ:RS²Ú±Úí·]p“N:yt²´,s«I¼ÅíR /«5Yç}ÊÔk¹†^WP´ðb¥<ÐÝ¡QuÌÈÉ[/üe€Nš¨ÇÔßœ êä¤íK.ß>ãÛ·O)4úúÅ›› ½w#ê¢tç(&õ¡uø%•V¿=åáýú˜©jµE,ýÖn)ÎÒU¾õ˜ž“Œr^ÆËÄâãé=Êj£[y¿Þz‘"üÊô˜ŸZu‹@§¼öCæàj½R¬·›vÅÈÅ@í‹ ølÆ2eÞ$dT£âú4/­'õ‹NÈFÿ† ˆ²èRÖ>j.¯7‘>—r‡Þ­,³t•)×À£ÙJÉóú¬R“dÈ ®Óä’ïš•b£Ýú(~¡|ëU„®b:=Nž‚6 çˆæŠrK Dñ»,]Ô…²¡Z¶ë)å,gÒÏ•ùoã1Ûü¤{ØLÞál±Þ;¼D¬õ/+½Ãi{c½ÃYûfx‡WSȾÏè/ø¬÷Jìîzÿž'-ýÞ`ìîXA`¶ÏgC‘¯¦x»¼Ãñ»uJŸ÷ª¡)¯íœ×nJÿ>˜Õ¡Oï:¯×u·ëÓפŸ³ôâcN§Ÿ;B¼ b|M`‡˜Þ+†Šë»ÊsC-JµèmÆ£X)4Yº\Ñ6ʶÙfj7ôØù`o9S¦¼ø¤Õ´¡µ„Ÿ'o5zƒÁ{"+ï‘âÁ‡DF feZ£~eÖ.óÊÕðí»Œ+·7–¬¬Þíð6pâm¡.ÿFjú[‘¦oü,"›ÞlâÄÝ¿ÔO=Ýžøžü^[^ñÊiYƒ·;bÚÐÞ÷£½“νqüß²OÏIïQ Èf¿)³õ -»»oðÅ”RS™Óß–6§ÙQ°‚É ~UXØÄõØõ¼Šâë°™:JÍí6¹ežë±M㥥ŠÑíLë5†øújE2UËñ„´ýAþx^.FC™«ç)ð¶ãáÐä…¨b8RŽ\xUJSŒþbCëUVÉ<¬²*ª•Ò‘j„odõ”_‡+ÒBãÆ›­N–þõe– eÈú¢\ˆõÇ´¯ÆŸÇ|ѱÓÃÞaªÝ›í_Ç ‡¡-F¾ºû—FáðËs‹‰¹**1ê"‰|éPz»õ~×5뉽ýÖ§›gV£,/Zˇʾa¹ˆE!æÙ˜?(=Ý*-f%(йŠKoT(=å—ƒnŒšÉÒoéò÷åa0H,°è0 Šªý‰i1/YÞ'Óø€Î2„êgü£®¾ó\uÌOA§·KsÂÚ»÷$Ö¨Ülj¡ª!(J®î~ÕZ,oÆœ”÷5^ú5/ è/À‡{ýkùéJ_E÷ ¹|3¤v‚p¸+¦[éCÜ×/½qy`ë13kÊxyœè·Ït¨uŪß}£Óï~WÇI¿}ž£Z.š«$´v£j,ÆWDÇI$/ Kç‰øÐ;¤jø†ö¥u<˜u‘fHϢ«Aq^ÛqVËÕâ<ï0¿×$jËúòý·óüj멽Þ¾ “Öö½o´üˆåò’J€o XÁ2G××É9®C¥jAWV‘Ið£KÍ-ˆŸ.øN!âò» D‘rB¹ÎZaôçß·Þ±QïíÒƒS²¯|Ÿ¢„\>{5/ø†ë?ß#ÍÔÀ²Ëõ’‘ì±â Ö¶Ùè-Uu0€"½´Iœ°#y„ñJÇϪ³6ê¤Ü#k#Ñd)ZLËAz7hšîíJ±š¥wt8ÂäL—¦k¤Hñ›¥ šÈUlNïb÷vóµy¾§a…4™b-òøíhCˆÄÛBmX+êÓûºïòÖ®2å(5DÞc¨VŽúˆËä=SÚúÅ©ŠÛ#›«w=¤Ý rfµâœ¢4§VËýã¬ß¯öä&ØzrLïYæžÜÙÓ;^ñÌæޫ¯XÎx\"\2RÍŠ{¯ì˜c9“}BŒïÍ}G&N‘(¼#Ôc­½`7`¼Yד»ˆow,éøë<”~'ë@åY¥9±ù³ôWË Ð^°©7)÷êå=K-A´"ny…ìÈØœU8_Š•Ù¡º²•¢½rÁ*È5Ù±F)6x» ²Ã^­¬Ó?¾ÃußáÞ&œ…¦ ·S¹““<¾†:A}êÐaÎ|aô'ë11‹á”@ äÕ#”"—ðRcëÝûú£üñô®ãcÖ;›Qi1·…CÏ ‡ú°Ü ‡l×,'„C¥A—¥!q[N”ùWöùwëÓÏ)§'‰sQèž¾Æ{•oQz¼ýADÁ¤vhd+uM«jÌï‚ô¢ÊO;Càº\Ì9é´‡óÕé B/A)$mK™-›å¸ïóÞ>Âc¨(ï8Îäžž›t= ¬U£x@¶ ‡ž² €æ«ìý–e€‘ìò§ ¸Ëü÷è{lANya âreE;Ñö¬÷Õ8=øSP]5šêÞ#¡ÆÕØ H?¡:-¹Câ{²ŠôБz” ßôf`!šaPfÉæ€^1È1J‘¾æÎÅ’c$ÕÐu øxD§ ªáq¸€§@†ø0ˆ@ÑßD¢r*¢gYº27-ì’YÎà1¤’PqÌ×*ün¤ÔçöóÜàç#Qžp~$ ¾0~_$ÿµXä7…ó‡òß‹„=ÏóŸrÔ+Ýxçð¼ŽÛýnqVŽŽúË7ƒzøÓ >=Œ 9„àB`ÒÞ•ÃüG!öÚµ?¡_c+ëבY¼V.1Tn !J %œ '¤„z%DÚ}¢ ŽQ¹? f¬VrMhµìã‚uÁA.ÜâTжRQ³ŽÙ½Z|WN `÷uBÛR€/áÚnDЫòƒIð‰?F¤›*Ê;gs|×fh•–gÔ¼w£Æ_o{æp<ÿ'q^ŽŽ¼Ec¡æF ¼WÌñr…^®0ʦ£4¬Ø•ª0Ƭ—•w&F‹½º0\LaÜ¢|”Ùí(“ÓÕÙ@ (ð-¶ŽÏ`ó¨vF æ%òœ9 š¨¹§á^‚ûTÈz”/À½5“çªá?÷J•/ƒ/Á}n9ÜÒ\p•pR’sòäÛî·MîœëxšSG3Ť% ˆˆ5èOqŽW|/ðÔ†¥4–^Ö•³jNÔ7ÍD2ë‰^žLf”AŠž¢Ë!NÝ=Ç×µk ””W/„aDêLB©¢±h„ûö²y”<ºc£? 2Ù¼ÿ>qD 1“/‹`¥¥ T½âÙØù¯ýë—ÑýšN.Mñ':cÎ(Ý‹Ž‰SPK¨ÚÖ+]€Üeî5ßN‡´u•ù~а>LjÌ«!ÿg¾‰$µÚ÷5ý]Ô)‰hm±Ó¥¦QÌ–ÒñåyŸJVž•÷•§u¦ *6[BÈ ÍJ¼5ͪ݋0£r¯c3ª'7=-ðN-°,pH˜µ€%§ne}Ž–&+¥)½lÑ öŒî$,zÈ>s¬Ý‘ K¨Gµ1c=ö§Æ©9zêÉýï“jÃÂ5›áâ"üR2Ï}î0\WòúwᅩËþËø·ì¿²ÿÎýìq™¥‡½±×víè²t¡­þ¢Ì’ˆdÉ] %oY†E­Ç÷VfÙSöVÈöåòdè.I–Þ©ØMõ—óG[$î¨E/V XßbÚ:…#†íµ'3ÎÉå)¡B "ðD‘E–×ñ‹P0d–q)Bë/ˆ*ìsŠË4#b¸æ¤ñ¶DË9Ñæ Ê)ë[R,ì]ú™`R²‹4ĉ†F7¹>CÍñ.—¿f Ï̉S…Cù  Ó$º4`qJúåY´±Æ6•œþŠD%!%?YÉ×+½ïŒ¤· *FVÐBãjX OÁy ÈÛF[ IÈ‰íæŽ²dà`£y7XÎøí™Ì äT¯]£ØÎ(ÖÈ |pt…qÑúæ+ɨϿžÛêć©.":Z]¢’H·úÙA àgü5ÑJê”ü†¿»–:B­eº2ËÃyéî½ùsëQJáÄþí`‡ÆÌòe⊖}iœt‹r´ív³vsÍTŽÏu`7[d®1!-ô1ÒBÝfg0©“¨._Vþí“ÌfáÄÅ-{8ñ&¥`ï+­™8 qäV+k僭l¯Úîƒ×Ó•"OÊŸf:2Xç·ëq˜a.Ÿ¾¯hv ¶C—Ó!ÌÝêk5ý6 ýŸy^Ç&n¨Ç ¶}ÿY2÷¿Lï£\jÂXOc‚ø™1W­W`i¾BÛÞÛ;ÍÁ\½2ªÿ›MQñH÷+6{8q¦»µç1$cÌ`#ÆÜšŠ™†Å¡ Ë(âDù¶íï9o`' ¬}.Ðéí~£˜lÂþâ§'¡¸Ø­´“ÚW¬¬¤ˬ짇ò@¥œÌ}[öØT.,lþªôˆŽ·¥¿½À",— 2å‚•rA®ŒQ.(€…àv¹ H.pÊnD6É[ä‚mrA%"5í íí-Ô¦öûy¼ `tØ#ì•ÛI±oo?ÈSÖƒìe˜(§D÷Û™!s8äíV˜ÂÏã´I¶©²íuÙvQ¶Á`pR¶aþ¼l;+Û^–m—°'Ï,_.¥”kVÑèhG„¶‹8‚±Çàq.¶E Ã^œ Öå¢<iŸ³†Î*ý¶oÏbG¯­/™š·õd¯íyN‡4 o=+o}9˜¤‹5Î4 V‰ý…ç‹=zÌ<ãXxaRxÛè5i‰àì1€ámýXy@¶à·tbLûb¼÷-ƒà{‘ŽCá4Øÿï ¤b<ÒZúƒÌà¿Q1ø|È\>µý~fãz2ë3ˆ Úu’"å€n ¦OtbJãÔ_‹Ã͹X¨Üjþk¨Å;‡ªAbç[Á kˆ[{>.5†ÍJºŽ?€…R:~">ሠtÖ8¯€LCÇ:~r$8ßiÁ·™iÉè8vbìr:@–£Lõ£æ¶.)®b3Ó×Ü.u*RZ¬¼rQðÍ%EôöF½bßTB“g¢3Wk¾(Íjy,O¶ ï“Äõ1Â}ŸB4< -¿=  CÊo¶ao1AÃo¢¹é¯vd¦b`jk¢ÇâÍ$?œŽb­úu#7ܳZQ?:‘Úpñ­É¡®<jV(}¤A—š\¥§àòÙ뻊½çcœÐ÷ПýS0ˆKæžÔ.>d§M¦ÆK3”Í&Vk…(‚¨½‘|Í{Ûõ…‡ø›nêäÜd1*{ÜLêm³­ä­™Ò4ïkÌL|Ußô»À;;Í;Â`.*‰«YðÝCC1È`®è›^k¹'1[ðU#±åžŒ‚o ½{t'B¬¼ßµJC1 ,×YÓ_æXÞãV_9!ê30Fçϰ±˜”2£<«ZÉ7±cÉ ¹rlÉek«e÷”޼„v{Bµ²^ ÐášÞ™ÊQÁv÷ô{bv=)H‡ ³;CI"zp@?->™&“’)à0*ÓRXŠIqÍ’Ý7)®9²ûfÅõÑMr±Qq½ç¼–s=öŒöû{ MË3{ìÙÛà[ÛËsüî 씹 yù*en" ¬Qæ&³€]™KØ‹åòÛzìEºû^©ÈuÈåŽj¥b­'Õ <%êÞ7éôÃãv—±6gªVÜv@TýÂyšyòñ„3ºž8Ô˜ù5 |éácëÈ^éP a¨¤r,ÑÒ…k(eŒ}²ÓÀ<ˆO!Jwµl»V•‡“O°­3zÃà¿Ûèo2(½ÄmH -ôè³gá\ ì ûÙ;F—ú›fiÀeãí£€³ö¯ö(S­8AYÌvéß;Bpy±šõ‡™F;~Ññc—òß[HA(Aðý#&œaü„´³„_vôt c€ÌÞ„0 ³Ö§¾Ç)œw“2pci²µ¿F–’n¡í&J<7«™¯„¹ÔKRúp!ö`¶kÂa:‘´›0j :Æ}àLs},3õž›Ý'±ŸFv" ­nƒp¸@ÈÆg ‡7PXOˆä"bŸSlQªp¸LÊ€i>UjtÒ«è&õÆ¡`8Uå•_0 ãŒPpÜ~Àìÿ,érÕùSüŒ÷ß«@ŒŠ†ÐEÕèw(‡¿.õNÐ6^§>À– 37¹<šK¶k¶k¯NmF%=ù œÿ0±pMê#q8¢^ËõÚI˜ 8Ÿ>çVc1mXE„ؼgÈ&©)Æa x–6\O~q2 ç›±Ìw!©LU ô'¨ûõË– úeòÛë—¤XB+^c”¡È …“ÞKzÕyì‹­ÇŵJA"_x›õ8ƾ؊V ’c ÌØêèÑ«­¿!ßy݃¦î×L1'€0æÅ í³ÙÿH~¶+Çyù6½<§gM ¯|@/7Ÿ÷—½ÑzõApåáæ—å\Ögöêk» 1lW„¶Jh/°ÂŸO{Sd/ Åa ¶—®ëü6Þ“©®Ê ­¿¤Í˜l†’èÿâ|N³yBÈTYÞ´c(×+ÆÂúˆ÷pèßÚ.ôÉ…È.š›è_™lm>¿ëºñ\k€9tˆt0¼ä:½S},QÛtüœŠÒ.Ui>xÐúsqBé&*ý<É—­¦–} !;š=ægÈ¥FÞMPe½Á›¥¬Ç aµÚ$ÝÜr”íšÄüµÂwzp¼°×¡¸E'Tª¡«¤†ˆ5ƒæÖ -FåÚ)ðŎ竳ŠMÒÚ¤eÚ¤|e€¥[;ó8-cSåÐIKü®¥þ¯^#1, ªïe!Ü÷œ¦ ÎÖP>¥Ýi5’€ T£ù‚ïQêw.¬1+ÑÊLøË‰ Z:ø ÃóNá>…eAÚsýŸ¤þ Ð8]É‚NÐÒ ºõ×:Ì8>Þ:>¾£u*ÕãÿLËhñ²¿ 1KPn~¹e_'¾£åè£$ÙzT¬ðÅ0`:j%L¬Í&Ñ´§†¶Q4æ<ªvPQMœX&eР=™j<+7›ÆÒÁHÈ “¦UŸõ½¸@Ùß@Á=zqŽCÝ"笲Ÿê*$àbÐXêp…æzíªZ¢‡´´¿EîÀx³ÒäÔ¤ãåÍç&È›´¨°KCøŒ96Ì“ÜÜåP?þ+ZždéeìžØ­Ø#w~²œŸb½(´=I°ÿ Žè»ñxŠñ'nÙ–ÉÓÁHB„ArŸ,®éy5ô9€Š %óaj­}ËßS[0âÊzŠÁ#h”÷£I¸ïE¶dZp"Š¥ée.\DºÖÕn{%!h‹–“_ ‡âI\£l_©¼xãYë‹â;´J¦6¶ƒÜÀ¯¡4î6ØI9¿MÀž ¥e­l/·Q.*s¸¡Ë4!­Ò¾IqÉî-ÂáӈܮءßlSŠÜrQåhÝ¿TóØ`ªÁBJSmìN‹ àÒIüu€±ñý@ÃH-|™H…ÍüZw{á+ÄSÐxòo£Æ÷ÚWñS»Ñ¨>Pp›Rø²\” "×ÊE%ð6Ên´© !çΨ©¡ÑöT+ƒ‹€B#ªt¢R5¢ô3P­pHç€}3aœ)uç$¥^‹e¥ÌÕ=ö®g?[Äz÷ßO]¢ÍeºìÃø‡š´ø—rŠMòC0,°áßÏ BJÆäÉïý^¼uÀÊkXùÁû¯…)ùà$”l%­÷Ùy-½â-£èp3ú`F õW&¶ #Y~ˆ`3"¸¿6 n}lx8¿7Iî«zp±­òI© ³6”—ãƒgµ‚‹úà£(UQ¦{Ìš6>ž‡ÓÁÅÀéábá ñÚg|ûûß)ìô׳=b™Ÿ©_6°£ÓÁŒ.JŸ§AÞ—*7C9¿ÎPµ\ø;õÑ“˜8 0Z.ÑÉ2“'ǘáÐÔy~ ¦A^¦œg’óÌrŒœgìˆ[yh¶îùŽ|>·ø/A>9T°Ð)]‹¢!'Ë^ϲ‡GçU Öžß)¶‹5 Å0"ÔlûÆQÕÆèjÚ/N6û„HÉ(‰R°,ws!Ø®Àx4‘6Ç¢c¸íîÁh´÷uõÁ ÈB7“†£È”œ‹NåPོ-ñBqð…Ñ…h¿€¼ÒK0ø/vQŒ¹³èùíX¯÷ËŠ]þÒ =öåü#u¤o‚‰Õ n%Î[bÆ åÊûå}PÊRxègØ¡™eƒÚªìzu7õ™½!k•xcÖ>½øk¯8 \ˆÕ§¨;¸KlRØyrø@\ˆ4Têd÷÷è[´+|eïëOc}á—ú„•æìÀ nõ»/ Ò;Ù÷?Þ×q°A—ý»zl×8ºj}vW:f­¼OŒÍµv7á{ Sçu¸RºèTh¢›ó$’xµäm¢¬—¥iå´N…Ø…g‡Çìv“>EiÐ*·«×¾43yßü{ú­r¹Yf×mzöo>˜ô9vtšâôÛL”Äâžý§Œ^ûâ—cI%OcB"˜ôEÀe5'Šé=û™íŠº/Î2_ ™¯4ÓE(m‰›ËC¤•)9_EÒ‘9€¡éñø,’"ÉxÑÉZµ\z &$â%š? $„$÷Ú.rìvÄðy°^ðll=:éëNvNì/Mt_ÀNÚ3o¦NðùÑvt½Î8C¬ïµ%R/¡PöMÒYpDjÃ$ °‡ío›Çô®·9™“Þ #i+T#\e”f¡¢ãfW¤"éc²-1``}„ªýmJÜŽV¿ŽQdwhÐÞß|3šè@#XëXÁ…¬%œ”Š]XN.†»9®“¼€)‡¾MÝÛIžl_ ԳơNžõ£QÔ³B¨˜ngĸòWˆæŒC”2 ¢ƒQD3Bˆ¦0Dzº[ìÑýM m‰"y6dÒ-ÚpD:òz§ßŽs‚)àtÊê8«R ¦cëµè@â{¬i ](2«GI õan{°Ó©WÜz§ÿ(-ˆeêò«$‹1OÓÿÆ‘WŽG8×­ºO³c?WÙx% Îíú ¿þ¬BÛ¡?¡ò"sñd<ÕÒÄÜJàEC™*à.ÉærK8ë$=ÖidV‘bŽAyˆ¶Q§ øLÈÃWÌwóx§Ò[©¹Ìîº\pF®Ž¤@f…Ã/SFúÑÒeð•D¡¹1Ž)˔˶DÚ7‰3!v³x¬,ü”œNÖ1#yûT ÷¼bQ~W,+ÏìEQKW]2€³lFIoí“|’V_BP2%SP2ª_…î8®ZzMeA)Ö÷ ”h9Wä.SGص|¤´wªµgwœ$´§¬ ñú!ݽÂÍøB\7¹<»þV$zÿÚÓ®ä:]dz¹Í˜ëP®Ñ*†ý¾Œ¤jäUp×Ü˶ú\ÔŽFýúY§¼°è´<5”©G¦r‚á.s¸a£SE 7}I'ÅC0Êi²50 èÞµÀ¿vUPæ{cˆ_€©3 ‘x2ÛcÐ>… sÆØõDû¾¹ÉhaŒP¦0%Ij²­Á=fïð5q¾ ˆyÖbÊT¿ÊøÑ„m¶˜â6ãÎuß/µ³&ÈXÙ5‚3\ºdQxÑûÖ5±ú©_¿Y¹}?èÝoÆ*®p2ìëýèˆTÚU’ÀäÞ›Oö¾³¨U:E .ÎW cIX"ÁÍHÈV“ áO’A8û¾° £–阵8k£IœQ£µî9¥Oݤ%³¯7LãÑ÷ŒŒEˆâ ·ÀJ‹Nyœ6)Y.“ØBù´„ƒ%Hݱ©.œQl5K3\ô¨g§Û%BÆ$Zé“ç§ÅYÖ7Ç£®Nva»`íÛƒcba\8 ÷Ú^§ÛÁõ²¤:dé¼Ú¤±³2Œ¨ç /쉃I¹=9`¢*.µßqS&úGÉ*;ëPêŽ|ÑMÇj%óÍÊÚù‰Êíó“Kqü_\“²6Û ¾©  ð”¼v¾±R^@)MS6½ØrÒ`ò^»&Zc¹÷ê5Qo}c×Rÿò]þ-ß7+SÑéØƒrÒÉž]r0ª§¦°O-r‘À£•Äld·sAùq Õ_^­7„7¶Ø·¡jŒ‰¥OMz+ˆÕ$LÁs°!Q]ÅZcÚJ0Ô Y×C›ÑRåv$¼;øþ”àû“ƒï_¨&i€tBVê.s)¯YºpíóŒeÈ žÞŒ‹ˆÇ•×”?(Ý^]ªXn¿å r_ÕÎÙæè8ú¥Xý†NÛPKÝ|£³8(ÎOTÓfnX‰‹ÊS*:ÔßC«M¹¢Á{·ÜŽOœ÷LU¦·ë‚<>± à[`:Ê~ „Þq‡w8(ÅÄŽ ÇG߀»˜‰Y×a3ÁòR“VA‹$iqïoЄ(èP¾)×xåEq™÷^#'-Â\ã ›;b‚8ˆzV¥/ŽóPZšáÍÙƒ¾Y”g½UÝLH›Ü½?¥ŽþZÄ¡ûµˆ‘®¾àHÐ×õ'ú&ä<½?ÝÇÞÙ{€½Uö~ž½Ÿbï“xãˆ.I› ß0†çÂàû$1n}3œù@4³ÁC™^fh.àMŸ6/A†=KK”LÂýs °¯e0µåÊÆÝ‚p´O8*Ð5¿pù_8zÿ³õÄu_ÑWÈþN¢æYá@gGgÒ¢£ôŒjÁÅH  †Ì«¦Š·yÕ1ëÅbb‚¯†ìÕ~‚7n‰„õƒŽH˜\‹p+ ·QnE$K7øn„WÞ,-Æé³Ö·ŠsÄúœüQ"FðO"¼Ìè¼bÀ”òSð}ýS@.XÈ>–õ ²´q|ÎÀ°Þ4«Ê°ÂÂnûà×>u>†äB²Nܰ²F¼ue8{ånÁ÷C¸%´ ¾Ñ–UuÒL»–H !gÐeÓmÌ„S­w$´\Éæ´ìã—K‰öpÁ­àBxŲÓYö—(;x/ôÁ·b)»Rh{ƒj…¶AØ)´gIh{öm§X`£ÐöãXê˜Nê?1±ÿ/G†WuŽ ©_ˆÕÆx¸Vø`?)'·xÕ<¡íV½ªYhëá(+´ebr`èo¢ï2Ú2xDߟb Ìíõ·N¡A®¢Iœ¥×( zHôíÂacuVN¸oj½ì w¦p¸[\néW.ŸYÝvZh[„\å§—ÏPx§Uù¯ݬÙϘ³uk Ñ27Ò·^ éìÊGñè~{ѱÁ•|¸¾4Ô'M‰¤÷ Æ G¨§EƒÆ ]6 ÂEòG ­ÐöÝ3yNšúÈâH] {÷úNþ)ô!U÷¶õMÄ-¦ ‡×Œ8j8º­á»„‡ŸµÔ¡:bCê8¯×÷T{`fÇš‘vˆ^g‰á‚9l¼j½Ð6— Š7OÜI³¶m*ZZ€´õælg²oÍH¬½‹ß±%‹†Ü\ëÓÒ¥E ßéa­ç§éBM_8®é¸u-™œK…þ¸HKzº—M&ÚüÈOú!Öîf3-|«:X½úâßYê«vß‹¬QÏ“€ bæŽ)c¤2á¾$&c¡ËÝ4…$#|RFÍÄzÆÈ¨¢òe¨;Uœ>ÔÕIxrÍH·ð6*kF(-æãg(t½õ¹{gïÕ[7M¿|Ö{†»üR¨F>³Q÷Kʰ¤³œÓø‡k6¡µáñ™ãý#¬“ˆÌbéû šhQz§— 7°ú¥7JDˆÞ¾®{ ”-.QXk?î¤KM4źӼW²äO?F†•—öbüÔoí E'ü¶7õØ5¨> UdNˆàœ8åTKVšXô³ñbï>-wð]×Mtº¥éwCèk#­ßSESµâ#‘Q-F-(¢¬è}‚Bœv“PakÇÐñ\1çòq¶Ñ‰×ÆuIà–®Ü¶³¢ ÅɬýYCÇuât--Uu¦7ý`€€~p½Ÿg8MÒìà˜c4¸=©êÓ—™:dÊÑL¿Ÿª?EþCÇâì¡ãziF™Û“¦å«ÒJzŸ8IÄk½-Vûºö½Wù´&g¨§…Ã1A?ƒßv sòGˆä9òÔÇùЬ”f±D15øƒEë/¼¤ÞAU¢žÐ®ÏoS¯|;|}þë”´­Ç۽ߑ¦ZÉKXHÞâm3ÉËl`^ZûɛßÂbËSgCmH¢ªÜ8§8èDl¸5‹Ó¼{SÅ™­A:æ(Óg¨ÙfAgÀ„ÓÄG´Î"t"°Í­æ}šr0\¦æ >/ÀyÂÃìwb´_„ÿS'Ó¿3ê§N"PQåàõ8iœóˆJ˜8f=þ½pݺ›.|a>¼Q:„ú鿜|xc´¯÷l_:ñ»£ÒŽmÒ~wÔ1*mßÈ^çÿ†üþZì]Uw5Uá'Y¿B¡ wƒWõN±ÎÞXUµº¾©Ö%6ÖÖßÉݦ[_嬺k箪b©JªZÛ°ˆa¸ÒúÚøã(÷+~ÝÎê¼w5ÔU‰(ô~©ª øAª³ª®j{SUÞöúUu®†ÚúÛwîxwp¯«‡£¸§ÆnÚW·³©Š«BÈU%ºªvHµâÝÞë©Ú!r· uCCU½½¶® «w (Ék¬‚î†[[Õ´£±¶AÜÙÈ}GWxWáöª«ªÒ±ýΪ&È i®†ªµÕwçmßQŒ³MµbíöºÚ0’¾FuD{¤dç¸V?D½J ƒDÁ1’ÀXR»ã}y;¥z‘â×W­‘îÌ«©Úñ>ÛŽ«w6½¯±¾niÕž*úåØõUùUbžÔØXU/®k|ÇmàÖW‡ú/Òs·#mõŽ÷KµÑ´‚Õ·/­¬«ã¸¢ÊÚ¦Õuø™ZtK!Æ®ñî²Z±¦dû\)ËÃÐ…Ò9î–R誫ªj/h±µUUwÖ6A' ©¦®IÄÒR_°½¾²®ª‘ûêx8M»ã¾§¥¯«¯¬¥ÊI)•šÂÁ}w²\î -Õ9Ó|–Ê8!og}uíRãv±v'T¶A–ã¬Ú^96ãE–N¼16ýG!ü¹E}nµˆ{¯$V5Ñø[º´¾nçöÊp!h,”[RÕxWm=ZTÖ¸½¡Ò»Ç–*¬­¯mØÙ(r2KðW¤@ÑÚu®¥®;ð›ËŸÓ¸‰–rîS£8«dg¡T'Ö®¹[¬*âþíÏ~3:"p\:[ÏÒ&I×k:϶­p1ãñQÚr¼ÝÐÖ+ð¶qN„Ö·‹_‡·azžÐÿþš¶jÆã‹ø·Âáôø#ô†Q¸»èÎÛ42-þNοÚû:ι€ùÁ€òåpYÌ_ƒ7ÑLG¼y€¹ ºÿvÀß=F÷/ájJu ðëA»ù©x7¢Œi;P/‡œ'\ïZ¸&ä4²…¨í6BøV£ì®ŒQZÉv8MÀçF¼‘íb¶C*ê¨Bl7Û¼ñµ ×.¶{Ñ~êúúh}v5Ú¸”¹e\*ü[àR¹÷;Á‹F;³ákt¬ÅßzV.“Ãm;Öo"ÃYOôD{„íµ´>ón¶ïÚÄè¹0wR Ö£ ÈÕH©¡>šÐ‡%¬÷j²“öz€«eý¶yDÁà§'—Ñ´!„«V£)Òöú¿J[5MhÄ*Ñ;¢û»é˜drSÆ×3ad&Ž Öh6ƒÜ¨¥qçÒ3ŸÓ3*6!ûžŠ×ãö¿àIë[ñÌŠŸ¯˜‘ñÕŒoe<™q1#x«öò?‚7=Ív_Ú‡Òâ—-Y–¿ìü²ié)éJÿrzª%ͲÁr¿å²…_¾nù†ŸËø"Ê3ãÑŒÇ2:3~”Ñ•ñTF_ÆÉŒŒç3Îf¼œq>ãB†šñ:°_ÊÎÉàÞ£ñ=y™m™dæf­Í*Ⱥ=+3;'{CösÙ/dÿ,Ûd5[gYWXk­_³öZ/Yõ+—¯Ü³ò“+¿´ò7+§äælË9”Ó•S°j望«~¹êòªä[çÞzË­Þú𭟹•~Üýs ý#iŸN{$í±´'ÓúÓžI›²,iÙ¼e7.Ë^f[¶a™kYå²úe{–í]V´\Zþƒå¶…+Ü+*V|~Å7V<¶â‰¶Ì3Ë<›ù«Ìßdþ633k}Öž¬æ¬f•d#û©ì¾ìSÙ:«Áj²~qå/VÆä,ι7GÍùmÎHÎöU5«ZVXõíUîî: šJ¢h¤DD¥*Ÿ^‰ˆ®¨ˆQ¦(1´(@@‰H±‚b'*‚‹¨4EPÚZPvEpQAE¤Xе¢²óƒ"ºn;{Îî9ø?óÞ¼™ÿþÌË}%ÉI§Žó#G…«Ë5ãZpgqçs—pø﹃`:þJ=4Zm„’! âX¢5"+‰µÄ‡ÄWÄ~bIJZOª'Ý"µ“zIý¤Òòx²Ùƒ, ‘CÉ[Èyä§dmŠe1%‚²RL©¦Ü¢xP¦¶S;¨´q4c‡æF“ÒÒëÿ€†£¢Ï¤ûгéùôZúOôúmú[º:c<ÙáÂà1Ü^Œ 1#’ÍXň{“ÈØÄH+aÁLangîf62[˜w˜ãX¡¬(ÖV-«µÉ>Õ¾ÄþŽý+{<{,ÛíÃNfg±O±ëد٠‡4‡V#Ž#g!'”SÈ©å´s:8=`MÆsݸî nØ19·^“IŠ„ŒèG*"í'%—R’©§©á´XÚnZ4ó>ók;ggç'›“Ë9æ;Ïù‰ó‚ƒà.äJ¹p ‡ÝP0´‰’BQ£jR­©Õ…Ê£zQP#©ÑÔtê°·§¨ç¨5Tsš5í°÷[À.{hÏho€E*ÓGÐ t;:‹îLŸCЃé"ú*z*=‡^J?V¬žÞDGüŠß~@¡Œ Æâ,ãã_@*£ä2°|AI†¨ á°JVêh”¾ Æâ­° "#££¹ä‘‡q4 3ð‘ ¹áq±¶âo6p9èaþƒŒ†Í‰™±z%Îë5ï™jTæQTòˆ8J”Ë´OC2%{H†6‘£A9…çÎ*V(=1¤+R hµV¡$z«ƒšçFÔ´`BEïÉ—ƒh=4yUvR땦òmŽô¥i­~˜G´8ì(vÜû.êbS‘>Óò§õJ¼y©—jÒêÂíÍJy©½ 3¬Q!žX¿wôMƒÃ¥ùzëCðñ½Æ¸1‡")³×š—m›qdìÉù¾¸¬åËÖ<ÉÙâ÷RÏ´îjhvõþ=UšQ±{IïüèÄ’½ªOn°Ü½¸dÑ£múÌvé¡Î%ÈEd»3­6Jf2Þ`ãŠ7ߎzòv¿¾æ¶ÂÊm= Ô”2쩽ÄY7CΚ&m¾PÞœ¹’É2•7ݹú|†~ÆËlQÌøü”ï‹òÌÔküÿ>Ž'}¼>¦áDÊ‹c­ÌM'Ù²ëtϯ^jé’’þÀÅýý¸+†½õÁ{¼ºø~=ê›F¯ÎìŠ.WÏ3ŠRNþ>¬mÓË¥{îu”•Ù°C[1­ASi¤ãiÙaDße[í‚Æ-[2í*I‘ååZhå+OJ¢<[âõÍ)ǧþxè–ÌCœ;ò®·û‡îÇOº·Šý¤÷ÌLÎe^Ö˜^HÍõªfUßÐMׄdØb¡{áSmOߺû SGã­* hh| ¢’ŠQ$Ä(‹ßÃ(zº ƒÂ& ²!ÂÀ ÆÑˆLHñð$bˆ€ “Tú{Ðî2é@QD˜3¡σë%ü0ïM £AýõáÚ€ÏÕÐ=@&  $ÖðÍØ~Bÿ‘ПÂéÏ µ¯†uÎh*Ñ¿ÁÔ;ºmG”{vÕâ)*^ØFœÞyeYð•ј•NØT´œå¡}I’»Àõdk59FÒjˆï¿—}¨sŸu/ ¹AÑw‰01W¤P}u{[Æï¬äÝ4Ï̘2ZÍEt1² Všð®ÝdìrË»†GúÓݦIH‡’~ˆ“4F0_[Ý­ôÃjBcܱà ÔÍ1VSYí¶cÏ^¸3‘·%9´wr´}»·C]+b®§Fm¡Iç4z_jN•ýe›ÊÙoÙ÷”dÞ÷joø’£c.!‚" ’\ë«<ÚÌ”u„E7³ÄŇ„hì¯Î\x=ÿ‘rZNTWÉ œÊÐdà«í¾À gtAeii¡—ÉåtÛ¾ü· ÐãžûÚ¢w©E4›ÅÈu-c®&f߃Ôè `åX`…€6èAx¬ŠXª2 At1äÙÊ­å–ñæŸA”ü…UÚómD$òa ü­<ååÁ.× ºò JÀQ„ÅùÅ;#ã߇ ‘€Ì‚XŸTC!um?ÎüõËÃN" ±ˆ%6b‘D Êp@4Œ÷”Ç8r.ÂQQ‘0T¼»žEˆ@pŽDÃïf‚–“"¿ŒT 8pfËœJàpDÁ\…<ô@[ gËpŽýÕ¬05e0Ïš¾ a§8» ç?L~.8‡-µ@ó€§ÐÛp"@€"ÛS̶ÖÎüA;´BaÛ`äbp-xüçkÁ3Âׂ¯ß Äðyð~a XX–øXß0TЃü÷j Iã?-3xG1ІL?Ñ2^ï㦉ñ»ñ†¤PŸ=5î–|¹½Ÿ0†¼!ăï#ÞÁp *RŠ(Pâ7~àIžjªØ úvàÔú‹}~Ý%ÐõWê[l¶yï¨ X¤•ÒKXIn=5ÐpÂëü‡–Îß‘ËÜÚhºØv+Wù ŸG/<× V¶Ý8'ëÌØHèD›ÒÖ%ßµu2ß|ÂùöÏÏ­›£U‚~™ãˬ߹©òC–ê²y[ÅÁN/Në˜lìºXMÌ칋wÝEì;w£é,~à2%fRIšlׇ+,Bº"¨ª¾¯Ó¦îHôÝ“k³¯Ô)³×dïë«>1ø‚;üU÷™ªI…/ní•Þ‡ŒNùcWšã.Ì{ˆÎÚµáºÛãì›Í–I¸£Ê{(´­›žþÂw)W®>ùAl“{ÂÎj$kÙÍ{úµÖÀo~+ç£ßR1ð|ì+îÙ-/˜«±g î«%û—cëÁHD÷ƒ ŽôiÃÈÿÆ‹þ™‡ª}cò }bMìȬXÒ¢I7‹Äç:háᬨ¬\ý­éI óLÂë\ƒV;rsïÍ,YY±·ò0#YhÇ2íZî­}>ãT5b‚,iÒègÖÝ.«”ôO $âfO ?ae½5I¼8c ÿÙ1Í…¢²«+v{ëùu<¶8¶Ìªï[7z¶PIbŽë7ÖL3–§ŒÖw!>»fÕçtœ-ØqÓ°gå^Ùý~ɺN̓Úá/®ÿÜ®ÓÔæáSßœ0¿’ë5—ü=•ïj\'½D;¨]‡½þã˜YzkJ·–jÿ8iBó.Úú"Bî´´¸¥ÊgÊšŠn›!´’Á•ìnŽÍcÞ‘Ÿ l4û¦IPê'å<ïKƒÄ~ÓÀ¥«þû§q…X•O°ÿ¿Fý© &iø?Aýߤok‡y þ½Àôa^Àáo{©0z89*à_š<»H i4IΑ³ãYâ—¿7_Èog ü݆²oÆkúo¦¼ßra2¥®õÇs\ίw(ìö+¾TÕP7¡­Ún÷‰¥ên)ë_în£¢Þ ×åG’F²m5]ÌwãªàÞ<ÓJK®ó›äѵÜNX¸nç¼#ÓL·×­™¯Yœq¶æÐNì‡-½#yãzfÔM+¥ÜxÇ:0À³¨Â/Æ<¾½%’W­×½S¹OZy-î˜Ð÷Ý„=Ág*ão\À±«shÉz³lßjëZ¡šCN9V6»oÍæâïÔýßxcü3ïÆ¨ ;Ë’RöMžZœÈËhyW| õ•°ŠØ“!ÀÄ9‰ß3Þ®ªÈžÕ ¡Lâì®rU{‹nAË̪Ã3Öuh[¬m[Úœä±Ý~…vé=‘KÇŒÌUêózëÚOwuΧ9™ªÚˆŸn}ÜM·4e¿vÚ8^cUó8Š=ÖÚH–âåé#\§Ùï[3æ±ÔÝ•0MßqýÓ-§›v¼ŒäîRòµ ö‘¥37/Ü0{µÞ†|òd¹ÊL\ Ÿ`ƒ{4¢ÊÛëtîûþ(I ëpM°­?‡øàmÓ„£Ï¯ ‰Â/Åv‡æy§­SÊXX?‡¦ÑhHh¹O蹿EI©ÙsãÌÇ—HâêQåÅÍϺºÊö‘îõ†"ô+JÛN ÀãWPK?/\ŒA$signed driver/ ð„¿TØÍð„¿TØÍ€iîSØÍPK?ltA$,signed driver/include/ ð ǧÇÍð ǧÇÍð ǧÇÍPK?tâ@@_YšI #$ `signed driver/include/tap-windows.h ´V0WXÍð ǧÇÍð ǧÇÍPK?fô@Ëß<®N$ êsigned driver/license.txt /·™mfÍHǧÇÍHǧÇÍPK?0xtAJ6ï  g$ ]!signed driver/OemWin2k.inf àýjŠ'ÇÍÐf|?!ÇÍÐf|?!ÇÍPK?fô@fdfFÈ—$ 5*signed driver/tap0901.cat ñ¢¥mfÍà|?!ÇÍà|?!ÇÍPK?fô@4\]ÖoF€z$ 4:signed driver/tap0901.sys —@£mfÍð´|?!ÇÍð´|?!ÇÍPKêÚ€gnunet-0.10.1/contrib/openvpn-tap32/tapw32/0000755000175000017500000000000012320755622015272 500000000000000gnunet-0.10.1/contrib/openvpn-tap32/tapw32/OemWin2k.inf0000644000175000017500000001614712123076772017357 00000000000000; **************************************************************************** ; * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. * ; * This program is free software; you can redistribute it and/or modify * ; * it under the terms of the GNU General Public License version 2 * ; * as published by the Free Software Foundation. * ; **************************************************************************** ; SYNTAX CHECKER ; cd \WINDDK\3790\tools\chkinf ; chkinf c:\src\openvpn\tap-win32\i386\oemwin2k.inf ; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm ; INSTALL/REMOVE DRIVER ; tapinstall install OemWin2k.inf TAP0901 ; tapinstall update OemWin2k.inf TAP0901 ; tapinstall remove TAP0901 ;********************************************************* ; Note to Developers: ; ; If you are bundling the TAP-Windows driver with your app, ; you should try to rename it in such a way that it will ; not collide with other instances of TAP-Windows defined ; by other apps. Multiple versions of the TAP-Windows ; driver, each installed by different apps, can coexist ; on the same machine if you follow these guidelines. ; NOTE: these instructions assume you are editing the ; generated OemWin2k.inf file, not the source ; OemWin2k.inf.in file which is preprocessed by winconfig ; and uses macro definitions from settings.in. ; ; (1) Rename all tapXXXX instances in this file to ; something different (use at least 5 characters ; for this name!) ; (2) Change the "!define TAP" definition in openvpn.nsi ; to match what you changed tapXXXX to. ; (3) Change TARGETNAME in SOURCES to match what you ; changed tapXXXX to. ; (4) Change TAP_COMPONENT_ID in common.h to match what ; you changed tapXXXX to. ; (5) Change SZDEPENDENCIES in service.h to match what ; you changed tapXXXX to. ; (6) Change DeviceDescription and Provider strings. ; (7) Change PRODUCT_TAP_WIN_DEVICE_DESCRIPTION in constants.h to what you ; set DeviceDescription to. ; ;********************************************************* [Version] Signature = "$Windows NT$" CatalogFile = tap0901.cat ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} Provider = %Provider% Class = Net ; This version number should match the version ; number given in SOURCES. DriverVer=07/02/2012,9.00.00.9 [Strings] DeviceDescription = "TAP-Windows Adapter V9" Provider = "TAP-Windows Provider V9" ;---------------------------------------------------------------- ; Manufacturer + Product Section (Done) ;---------------------------------------------------------------- [Manufacturer] %Provider% = tap0901 [tap0901] %DeviceDescription% = tap0901.ndi, tap0901 ;--------------------------------------------------------------- ; Driver Section (Done) ;--------------------------------------------------------------- ;----------------- Characteristics ------------ ; NCF_PHYSICAL = 0x04 ; NCF_VIRTUAL = 0x01 ; NCF_SOFTWARE_ENUMERATED = 0x02 ; NCF_HIDDEN = 0x08 ; NCF_NO_SERVICE = 0x10 ; NCF_HAS_UI = 0x80 ;----------------- Characteristics ------------ [tap0901.ndi] CopyFiles = tap0901.driver, tap0901.files AddReg = tap0901.reg AddReg = tap0901.params.reg Characteristics = 0x81 [tap0901.ndi.Services] AddService = tap0901, 2, tap0901.service [tap0901.reg] HKR, Ndi, Service, 0, "tap0901" HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" HKR, , Manufacturer, 0, "%Provider%" HKR, , ProductName, 0, "%DeviceDescription%" [tap0901.params.reg] HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" HKR, Ndi\params\MTU, Type, 0, "int" HKR, Ndi\params\MTU, Default, 0, "1500" HKR, Ndi\params\MTU, Optional, 0, "0" HKR, Ndi\params\MTU, Min, 0, "100" HKR, Ndi\params\MTU, Max, 0, "1500" HKR, Ndi\params\MTU, Step, 0, "1" HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" HKR, Ndi\params\MediaStatus, Type, 0, "enum" HKR, Ndi\params\MediaStatus, Default, 0, "0" HKR, Ndi\params\MediaStatus, Optional, 0, "0" HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" HKR, Ndi\params\MAC, Type, 0, "edit" HKR, Ndi\params\MAC, Optional, 0, "1" HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" HKR, Ndi\params\AllowNonAdmin, Default, 0, "1" HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" ;---------------------------------------------------------------- ; Service Section ;---------------------------------------------------------------- ;---------- Service Type ------------- ; SERVICE_KERNEL_DRIVER = 0x01 ; SERVICE_WIN32_OWN_PROCESS = 0x10 ;---------- Service Type ------------- ;---------- Start Mode --------------- ; SERVICE_BOOT_START = 0x0 ; SERVICE_SYSTEM_START = 0x1 ; SERVICE_AUTO_START = 0x2 ; SERVICE_DEMAND_START = 0x3 ; SERVICE_DISABLED = 0x4 ;---------- Start Mode --------------- [tap0901.service] DisplayName = %DeviceDescription% ServiceType = 1 StartType = 3 ErrorControl = 1 LoadOrderGroup = NDIS ServiceBinary = %12%\tap0901.sys ;----------------------------------------------------------------- ; File Installation ;----------------------------------------------------------------- ;----------------- Copy Flags ------------ ; COPYFLG_NOSKIP = 0x02 ; COPYFLG_NOVERSIONCHECK = 0x04 ;----------------- Copy Flags ------------ ; SourceDisksNames ; diskid = description[, [tagfile] [, , subdir]] ; 1 = "Intel Driver Disk 1",e100bex.sys,, [SourceDisksNames] 1 = %DeviceDescription%, tap0901.sys ; SourceDisksFiles ; filename_on_source = diskID[, [subdir][, size]] ; e100bex.sys = 1,, ; on distribution disk 1 [SourceDisksFiles] tap0901.sys = 1 [DestinationDirs] tap0901.files = 11 tap0901.driver = 12 [tap0901.files] ; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK ; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK [tap0901.driver] tap0901.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK ;--------------------------------------------------------------- ; End ;--------------------------------------------------------------- gnunet-0.10.1/contrib/openvpn-tap32/tapw32/tap0901.sys0000644000175000017500000007520012123076772017057 00000000000000MZÿÿ¸@hº´ Í!¸LÍ!This program cannot be run in DOS mode. $šö×mÞ—¹>Þ—¹>Þ—¹>×ï,>Ý—¹>×ï=>Ý—¹>Þ—¸>ô—¹>˜ä>Ù—¹>˜æ>ß—¹>×ï:>Η¹>×ï->ß—¹>×ï(>ß—¹>RichÞ—¹>PEL”E Pà  €T ßW€€R€€e€¹„ðWP]Àe€a40SPT@€R°.text›M€N€ h.rdataH€R€€R@H.data|V€V@ÈINIT.€V€€V â.rsrcÀ]]@B.relocâaa@B‹ÿU‹ìƒì S‹] V‹uW‹}VhÿÿÿSWè];…ÀŒóVhÿÿÿjEP‰}ü‰]øèÚ:‹ð…öŒ÷Eàÿÿt¾ À…ÛtzÆëu…Ûu‹M8tf‹÷÷Þöæøÿÿ¿Æ ÀëV‹EU RPMôQSWÇEôè$;‹ð‹Eô‹Ë+È8‰Uü‰Mø…ö|&÷Etƒùv‹EPQRèG;ë…ÛtÆ…ö},‹E©t…ÛtPMøQUüRjSWèJ;…ö}þ€u‹E…Àt‹Mü‰‹E…Àt‹Uø‰‹Æ_^[‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìjþhøThpAd¡Pƒì SVW¡ V1Eø3ÅPEðd£‰eè3Û3À‰Eä‹u;ót{‰]ühTAPAVEäPÿÌR…Àu18] t/VS‹MäQèh9ƒÄ ÇEüþÿÿÿ‹Eä‹Mðd‰ Y_^[‹å]‰]äÇEüþÿÿÿ‹Eä‹Mðd‰ Y_^[‹å]¸Ëeè3ÀÇEüþÿÿÿ‹Mðd‰ Y_^[‹å]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìjþhUhpAd¡PƒìSVW¡ V1Eø3ÅPEðd£‰eè‹M…Ét*‹E …Àt#ÇEüjPQÿÈRë ¸ËeèÇEüþÿÿÿ‹Mðd‰ Y_^[‹å]ÂÌÌÌÌÌÌ‹ÿU‹ìV‹ujµPèˆþÿÿ3É;Áu3À^]‰p‰H‰‰H ^]ÂÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹M‹AV‹q;ðu3À^]‹Ö;Ðr+ЋE ‰D‘ÿA‹Q;Q v‰Q ^]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹EW‹x…ÿu3À_]‹PV‹0N‰;Êr+ʉOÿ‰H;H v‰H ‹D°^_]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹MS‹YV‹13ÀW‹þ…Ût:‹T¹K9U u@ÿIë‰T±‹QF;òr+ò‹QG;úr+ú…ÛuÔ…Àt ‹E _^[]Â_^3À[]ÂÌÌÌÌÌ‹ÿU‹ìS3ÀV‹u‰f‰F‹E ¾3Ò2ÛWJ…À„ÿE ƒø:tnƒø-tiƒø.tdƒø0|ƒø9~ƒøA|ƒøF~HŸƒùwnx¿3ɃÿwHÉëxŸƒÿwH©ë ƒÀЃø w‹ÈƒúsC„Ûuˆ 2³ëŠ2ÀàÁˆ2B2Û3Éë Ñ2Û¹‹E ¾…À…sÿÿÿʃù_À^@[]Â_^2À[]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìQ‹M 3ÀSV‹u‰f‰F‰Eü‰E ˆÆFÿŠ3ÒW‹Ù¿„À„C‰]ƒÿƒ‚<{u ÇEüëh<0r<9v_^] ÆF_^] ÌÌÌÌÌ‹ÿU‹ìŠE ŠUˆE ‹E€xÆE u.‹Vqþwf‹u f‰´ˆ”!ƒ^] Æ@^] ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìƒìŠE ‹MˆEø‹E€xÆEù‰Múu0‹Qúw‹Uø‰”f‹Uüf‰”#ƒ‹å] Æ@‹å] ÌÌÌÌÌÌÌÌÌ‹ÿU‹ìQS‹] V3ÉKW3ÿ3ö;Ù‰Mü‰] ~hC™+ÂÑøƒø‹E|:I¶¶\fÁâ·Ò3Ó¶\ú¶TfÁâ·Ò3ÓUü‹] ƒÁSþ;Ê|É;Ë}f¶¶DfÁâ·ò3ð‹MüÏñ‹ÆÁè…Àt‹ÿ·öð‹ÆÁè…Àuò_‹Æ^÷Ð[‹å]ÂÌÌÌÌÌ‹ÿU‹ìSVW‹} 3É3À…ÿ~C‹u»+Þ‰] ë‹u‹] 0Ú;ß}¶t0ë3öf¶»f¯ÓfÖ·ÒƒÀÊ;Ç|Ì‹E@ºf¶pÿ¶fÁæ·ö3ó΃Àƒêuå‹E@ºf¶pÿ¶fÁæ·ö3ó΃Àƒêuå·ÇD‹È_Áé^[…Ét·ÀÁ‹ÈÁé…Éuò÷Ð]ÂÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìV‹ujFPèlþÿÿŠèV#RV'ŠÌFPf‰N‹ÁøQRèúþÿÿŠèŠÌf‰N-^]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìV‹u 3ÉW‹}…ö~0Š”9ð‹Æ+ÁH€úÿt„Òt€ú5tƒø| ¶„9ñLA;Î|Ð_ƒÈÿ^]ƒø|ò€¼9ñuè¶„9ò_^]ÂÌÌÌÌÌÌÌ‹ÿU‹ì¸ŠèV‹u ŠÌf9N …Û‹U€z …ÎSVW‹}‹Ê‹;_G…­ŠXƒÀƒÁ:…œŠ@:A…‹;OjGjuŠXƒÀ:^uŠ@:Ft!;‡ueŠHƒÀ:NuZŠ@:FuR‹E¹CŠùŠÝf9Xu@¹DŠùŠÝf9u2‹E€xu)‹Ê‹ƒÀ;uŠPƒÀƒÁ:uŠ@:Au _[°^]Â_[2À^]Â2À^]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìƒ}$‹UV‹ut!‹ ;NjFjuŠHƒÀ:JuŠ@:Bt2É뱋E SW‹¾‰xf‹¾…f‰x „Ét ‹Vj‰f‹Vnë ‹z‰8f‹R ‹} f‰PºŠúÆ@EÆ@Æ@Æ@ŠÞ— f‰X ŠúŠÞ3Òf‰Pf‰Pf‰Pf‰X‹V|‰P3Ò:Êt Ç@ÿÿÿÿë‹Nt‰H¹CŠùÇøÆ@*Æ@+ˆP-ŠÝ¹Df‰X"ŠùŠÝf‹Ï‹}f‰X$ŠùŠÝ3Éf‰H(¹ˆH,f‰X&‹‰x.3ÿf‰x2f‰x4_‰P6[9M$u‰P:ë‹Nt‰H:‹N|‰H>‹M‰PB‹QƒÁ‰PFf‹IºcS‚cÊf‰HJ‰^] ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌjhèÄõÿÿ3Ò£`V;Ât 3Éë ëI¡`V‰TƒÁù|ì°Ã2ÀÃÌÌÌÌÌÌ‹ÿU‹ìQ‹E‹€t¶Ô¶È‰Eü¶Eþ3ʶUÿS3È¡`VV3ÊW<Èw2ۋκðÁBƒút/‹ÆƒÉÿðÁÿˆR<s>h'ÿÄR‹Ö¸ðÁ@ƒøuÑjjèõÿÿ…Àt‹M‰H‹‰‰³ƒÈÿðÁ_^ŠÃ[‹å]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìƒì‹M‹t¶Ð‰Eø¶Ä3жEú3жEû3С`VSÐVW{ÆEÿ‹×¸ðÁ@ƒøt4‹5ˆR‹ÏƒÊÿðÁÿÖ<seh'ÿÄR‹Ç¹ðÁAƒùuÕ‹M‹33À…öt79Nt ‹Æ‹6…öuóë(…Àt‹‰ë‹‰‹NhàQèõÿÿjVèõÿÿÆEÿƒÊÿðÁŠEÿ_^[‹å]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìQ‹U¶Î¶Â3Á¶M 3Á¶M S3Á‹ `VVW<Á3Ûw‰]ü‹Æ¹ðÁAƒùt2‹ÖƒÈÿðÁÿˆR<s]h'ÿÄR‹ÎºðÁBƒúuÑ‹U‹3É…Àt/d$‹X;“tt ‹È‹…Àuí‹]üë…Ét ‹‰‹‰‰‹‹ZƒÈÿðÁ_^‹Ã[‹å]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ¡`V…ÀthPèüóÿÿÇ`VÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìV‹u‹ÆFE…Àt‹HRPè¼óÿÿ‹F…Àt‹HRPè¤óÿÿ‹Fp…Àt‹HRPèŒóÿÿ€~4t F,Pÿ Sƒ~t ‹N Qÿ¼R‹F(…ÀtjPPè]óÿÿ€~Ft ƒÆHVÿàR^]ÂÌÌÌÌÌÌÌÌ3ÀÂÌÌÌÌÌÌÌÌÌÌÌ3ÀÂÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìì¡ V3ʼnEü‹E‹MSVW‹}•üþÿÿ3Ûh‰…ðþÿÿ‹ÂSP‰ôþÿÿ‰•øþÿÿsèÆ+‹E ‹MƒÄ =‡ „ÿþþÿƒø‡.ÿ$… Ç…øþÿÿpP¾é>Ç…üþÿÿÿÿÿé/ºf‰•üþÿÿ¾éÇ…üþÿÿ é Ç…øþÿÿPS¾ˆéöÇ…üþÿÿéçÇ…üþÿÿ‰ 騋U3À8Z1”À‰…üþÿÿé‹E‹P$‰•üþÿÿé±Ç…üþÿÿ †é¢Ç…üþÿÿé“‹E‹P(‰•üþÿÿé‚Ç…üþÿÿêés‹E‹P,‰•üþÿÿéb=‡Ö„Á=w)t=…‰üþÿÿé2‹E‹P‰•üþÿÿé!= wS=ƒ¾þþýÿƒø‡Öÿ$…ü‹E‹P‰•üþÿÿéé‹E‹P ‰•üþÿÿ騋E‹P‰•üþÿÿéÇ=‚‘=‡†‹E‹Pf‹@ ‰•üþÿÿf‰…ÿÿÿ¾éÇ…üþÿÿ é=üwAt'=w„.ÿÿÿ-„#ÿÿÿƒèéÿÿÿ=üu&_^¸À[‹Mü3ÍèC)‹å]Â=ýt=ýt+_^¸À[‹Mü3Íè)‹å]ƒùr ‰_‰_‰_ ¾;ñv ‹ôþÿÿ_‰1^¸À[‹Mü3Íèæ(‹å]‹…øþÿÿ‹•ðþÿÿVPW‰2è)‹MüƒÄ _^3Í3À[è¸(‹å]ÂC‹‹ËÚœÚËÚËûfºËWu«4üSduÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹E V=‡™t-thƒètƒè …׋M‹U3À‰‰^]ƒ}s‹M¸ÀÇ^]‹U‹=êw…Àv‹M‹U‰A(3ÀÇ^]¸À^]ƒ}‹M¸ÀÇ‚|‹U3ÀÇ^]Â=ý‡8„³=…9‹u‹M‹Elj¸«ªªª÷áÁê‰URÒ‹Á+Ât ¸À^]ÂùÀvÇÀ¸ À^]‹uSW¾œ‹Ïÿ€RhÀž¬jSˆ† è2'‹M‹UQRSè0'‹EŠ– ƒÄ‹Ï‰†¨ÿ„R_[3À^]‹M‹ Aÿƒøw+ÿ$…@‹EÆ@20ë"‹EÆ@21ë‹EÆ@22ë‹EÆ@23ë‹EÆ@2?ƒ}s‹M‹UǸÀÇ^]ƒù‹MžÂˆP‹U3Àlj^]Â=ýr =ý†)þÿÿ‹M‹UǸÀÇ^]‹ÿ¥®·ÀÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìSVW‹} 3É3À…ÿ~C‹u»+Þ‰] ë‹u‹] 0Ú;ß}¶t0ë3öf¶»f¯ÓfÖ·ÒƒÀÊ;Ç|Ì‹E@ºf¶pÿ¶fÁæ·ö3ó΃Àƒêuå‹E@ºf¶pÿ¶fÁæ·ö3ó΃Àƒêuå·ÇD:‹È_Áé^[…Ét·ÀÁ‹ÈÁé…Éuò÷Ð]ÂÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìjþh8UhpAd¡Pƒì SVW¡ V1Eø3ÅPEðd£‰eèÇEäÀ3À‹uN8‡‹} ‹…Ày¹%ÿÿÿ+Á3Ûë 3Û3É%ÿÿÿ;Ã|d9F|_‰F‰]ä‰^‰]üPT9R‹F Pèâ$ƒÄ ÇEüþÿÿÿëV¸ËeèÇtVPÇpV] ‹uÇFÀ3Û‰^ÇEüþÿÿÿ‹} ë‰^ÇF€ÇtVPÇpVN ÇEüS‹áÿÿÿƒÁQWÿÈRÇEüþÿÿÿë¸ËeèÇEüþÿÿÿ3Û‹u‹}ä‹Î;ûuŠUë2ÒÿS‹Ç‹Mðd‰ Y_^[‹å] ÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìV‹uW‹} …ötmS^‹Ëÿ€RˆF‹FWPèFìÿÿŠV;Nj˔E ÿ„R€} [t3ÉW8‡ ÇG ÀÇG€}t ¶G%PÿS€} t 2Ò‹ÏÿS_^] ÆE ë¾ÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìSVW‹}_‹ÿ‹Ëÿ€RˆG‹G‹P…Òu3öë(‹‹p‰MA‰;Îr+ΉJÿ‰H;H v‰H ‹M‹tˆŠW‹Ëÿ„R…öt!3ÒF8‡2Ò‹ÎÇF ÀÇFÿSë‹Ëÿ€RˆG‹‹P…Òu3öë$‹‹pK‰;Îr+ΉJÿ‰H;H v‰H ‹t˜ŠW_‹Ëÿ„R…öt‹áÿÿÿƒÁQVèŸéÿÿëž_h‹Ëÿ€RˆGl‹Gp‹P…Òu3öë$‹‹pK‰;Îr+ΉJÿ‰H;H v‰H ‹t˜ŠWl_h‹Ëÿ„R…öt‹jƒÂRVÿÈRë _^[]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìSŠ] V‹u8^1t5€~0u/jj„Ût ‹Fh @Pë ‹Nh @Qÿ´R‹VRÿ¸Rˆ^1^[]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹E€x3t,€xpt&‹H|#H<;H8u‹P@f‹HD‰f‰ˆ…Æ€€]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìV‹uhTAPIFPMQÿÌR…À…§‹U‹E SW‰2‹MVPƒÁQè2!‹užÔƒÄ ‹Ëÿ€R‹Uˆ†Ø‹†Ü‹H‰U ‹P;Ñu3ÿë"‹8ú;ùr+ù‹M‰L¸ÿ@‹H;H v‰H ‹} Š–Ø‹Ëÿ„R…ÿ_[jtVÆ´VÿS^] ‹E‹ƒÂRPÿÈR^] ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìjþh`UhpAd¡PƒìSVW¡ V1Eø3ÅPEðd£‰eèÇEü‹u‹F‹MƒÁòQQ‹M QRjQQV‹ˆØQ‹dÿÒ‹v‹†ØP‹ŽpÿÑë¸ËeèÇtVPÇpV´ ÇEüþÿÿÿ‹Mðd‰ Y_^[‹å] ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹E3ɈH3‰H4‰H8‰H<‰H@‰HD‰HHf‰HL‰HN‰HR‰HVf‰HZ‰H\‰H`‰Hdf‰HhˆHpˆˆ€‰ˆŒ‰Ht‰Hx‰H|‰ˆˆˆˆ‰ˆ”‰ˆf‰ˆ…]ÂÌÌÌÌÌÌÌÌ‹ÿU‹ìƒì83ÀSV‹u3Û‰]ü‰Eà‰Eä‰Eè‰Eì‰Eð‰EȉẺEЉEÔ‰E؉E܉Eô‰Eø8^4u^ÇpVè ÇtVP[‹å]ÂjEàPÿS…Àt^ÇpVð ÇtVP[‹å]ÂSSMôQUÈRhEüƒÆ,PÇEȉ]ÌÇEÔ‰uЉ]؉]ÜÿS…Àt^ÇpV ÇtVP[‹å]‹UüMàQjRÿS…Àt^ÇpV ÇtVP[‹å]‹EüPÿ S…ÀtÇpV ÇtVP^[‹å]ÂÌÌÌÌÌÌÌÌ‹ÿU‹ìS‹] ƒûtƒût ƒû…ÙVjhèäÿÿ‹ð…ö„ÁWSj5Vè£èÿÿ‹}‹G|Pj6Vèôèÿÿƒûtƒûu1‹ˆÉQj3VèÙèÿÿ‹WxRjVèÍèÿÿ‹‡ŒPŒQVè èÿÿ€Éÿ€~uX‹Púw ˆŒ0ÿëÆF€~u6‹E ‹‹UP‹EQ‹MR‹UPQR^SWèìÿÿVèGêÿÿ‹PSWè¸ûÿÿhVèäÿÿ_^[]ÂÌÌÌÌÌÌ‹ÿU‹ì‹Ef‹HŠñV‹uŠÕ·Ê– ;Ê…qf‹HŠñŠÕ¹ÿf…Ñ…[‹US‹]W‹}SRP‹E PWèêÿÿ„Àu_[^]ÂVSè êÿÿ€;‹ð…ƒþ„ǃþ… ‹C …Àt;Gtu€¿t ƒ¿”‚œjhè€âÿÿ‹ð…ö„Ájj5Vèçÿÿ‹O|Qj6Vèpçÿÿ€Éÿ€~uZ‹Púw ˆŒ0ÿëÆF€~u8‹‹M‹UjP‹EQ‹M RPQ^SWèÖêÿÿVèéÿÿ‹ÂRSWèpúÿÿ‹]hVèÒâÿÿë;‹E‹M‹U SP‹ÆH÷ØÀQƒàRƒÀPWèŸýÿÿƒþuƇ_[°^]ƒþu‹[ …Ût ;_ttÿ‡”_[°^]°^]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìS‹] Vs&¸V‹ÎWº+Èd$‹<;8u ƒêƒÀƒúsîë"¸V¹+ð‹;…{ƒéƒÀƒùsê€{:…f€{6‡…\€{7…R¸VS>¹+Ћ4;0…8ƒéƒÀƒùsêjjVèÞàÿÿ‹ð…ö„‹}¸Ý†ŠèŠÌf‰N ‹W‰f‹G f‰F‹O@‰Nf‹WDf‰V ŠCˆFf‹Kf‰NŠS¸ ŠèˆVÆF:ÆFÿŠÌFf‰N‹V‰‹ V‰H‹V‰P‹ V‰H ‹S‰V&‹S‰V*‹SN&‰Q‹S"‰Q 3ÛÆF6ˆÆF7f‰^8ÆF:`f‰^;ˆ^=V6‰] ‹V‰^>‹V‰^B‹V‰^F‹VQ‰^JÆFNÆFO‹_@P‰^Pf‹_Dj Rf‰^Tè|óÿÿŠèjVVWŠÌf‰N8è;øÿÿjVVè£àÿÿ_^°[]Â_^2À[]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹EPè’ëÿÿ…Àt‹M jlQPèMõÿÿ]‹M j3ÀQPè;õÿÿ]ÂÌÌÌÌÌÌÌ‹ÿU‹ìQ¸ŠèS‹] VWŠÌf‹Áf‰Eþf9C …š‹M‹Sys‹Ç;…„ŠPƒÀƒÆ:…sŠ@:F…g‹Ss‹Ç;…WŠPƒÀƒÆ:…FŠ@:F…:Aj‹ ;…-ŠPƒÀ:S…Š@:C…¹ŠáŠÅf‰Ef9C…ûf9C…ñ€{…çºŠâŠÆf‰Eüf9C…Ѐ{…Æ‹M9K…º‹C&‹Ð#U;U…©;Á„¡jj*è8Þÿÿ‹ð…ö„ƒ·M·Eþ·Uüf‰F f‰N¸Šèf‰VÆFÆFj*VŠÌ‹Ef‰N‹‰V·Hf‰N ‹‰·Of‰N‹‰V·@f‰F‹‰N ·W‹Mf‰V$‹C&‹UR‰F‰N&è#öÿÿj*Vè‹Þÿÿ_^°[‹å]Â_^2À[‹å]ÂÌÌÌÌÌ‹ÿU‹ìSVW‹}ŸÔ‹Ëÿ€Rˆ‡Ø‹‡Ü‹P…Òu3öë$‹‹pK‰;Îr+ΉJÿ‰H;H v‰H ‹t˜Š—ØŸÔ‹Ëÿ„R…öt‹PNQWègöÿÿ‹jƒÂRVÿÈRë‡_^[]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìS‹ÄRVW‹}ÇtVPÇpV[ÆG·lh ¡ÆFDÇFÆF$ÿÓVèóÿÿh ¡ÿÓVè˜éÿÿƒƇ˜tWÿØR€¿™t ‹GPÿÀRWè‹çÿÿ_^[]ÂÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìjþh€UhpAd¡PƒìSVW¡ V1Eø3ÅPEðd£‰eè‹u‹U ‹B‰E€zub3Û‰]à‰]ä;ÃtD‹HMà…Éu¹ë(‹Ñ‹HHáÿ‹úçÿŒ9ÿÁé Áê Ê‹U ÙÿEä‹…Àu¼‹Eä‰B‹Mà‰J‰ÆB‹z‰}àWòúñÿ‡‘3Û9ž|„m8^1„dhTAP5GPM QÿÌR…Àu‹E ;Ãu¸šÀ‹Mðd‰ Y_^[‹å] ‹×âÿÿÿ‰‰]ü¤$‹E…Àte;ßscö@t‹@ ë jPÿüR‹È‰Mä‹E‹@<;}àvÇtVPÇpViéPQ‹M TRè´ƒÄ ‹ß‹E‹‰M‹}àë”;ßtÇtVPÇpVséÔ‹] €~p„³KS‰UC&‰Eäƒÿ*u9ºŠâŠÆf9A u*€¾€t!–Rjÿ‹F|P‹VtRQVèöúÿÿ„Àthézÿr^¸ŠðŠÔf9Q uO‹E€8EuG‹Ð€z u?¸CŠðŠÔ‹Eäf9Pu-S.‡æþÿÿ…ÀŽ0PR‹UäR‹EPQVèÂöÿÿ„À…‹] €~3„·ƒÿ‚Kf‹Q ŠâŠÆ·À-tXƒèt.-×~…܃ÿ6‚ÓQVèøÿÿ„À…Ä‹E €ëfƒÿ*…°V@R‹FÚÿÿ‰E Š–„‹Ëÿ„R…ÿt‹E …ÀtjPWè™ìÿÿ뇸ËeèÇEüþÿÿÿ3À‹Mðd‰ Y_^[‹å] ¸À‹Mðd‰ Y_^[‹å] ÌÌÌÌÌÌÌÌ‹ÿU‹ìjþh UhpAd¡Pƒì0¡ V1Eø3ʼnEäSVWPEðd£‰eè‹E‹} ‰}ÀPè™ãÿÿ‹ð‰uÜÇEÈ‹_`3À‰G‰G;ð„½ 8†…± ¶ƒø‡‹ ¶€`8ÿ$…H8‹C üÿÝÿƒø$‡m¶ˆ˜8ÿ$p8¹9Kr%‹G ‹V‰f‹V f‰P‰O2Ò‹ÏÿS‹EÈén ÇpV‰¸#ÀÇtVPé ¸ 9Cr2‹O Ç ‹W ÇB ‹O ÇA‰G2Ò‹ÏÿS‹EÈé ÇpV¢¸#ÀÇtVP鼸9Cr‹W ‹N,‰ ‰G2Ò‹ÏÿS‹EÈéÏÇpV´¸#ÀÇtVPéw¶VöÚÒ€âà€ÂaˆUÌŠ†°öØÀ$àtˆEÍŠN2ˆMζV0öÚÒ€âà€ÂcˆUÏÆEЋ†Ü‹Žlj‹P R‹@Pj@‹Q R‹APj‹†p‹H Q‹PR‹FP‹NQ‹V R‹FP‹Ž¬Q‹pVR¡tVPMÌQhÀPhjj‹SR‹G PèiÔÿÿƒÄ\‰G‹K‰O鹃{ ‚ÙÆF3‹F‰EÜf‹V ÁèþÀˆEÞ‹G ‹‰N4‹G ‹H‰N8‹G ‹@‰F<‹Ù#Ø;ÙtÇpV¸ ÀÇtVPéV‹N‰NFf‹F f‰FJ‹E܉F@f‰VD‰FTf‰VX‰NN·V f‰VR¸ŠèŠÌf‹Áf‰FZ‹VN‰V\·Ñf‰FL‹FR‰F`‹NV‰Nd¸Ý†ŠèŠÌf‰NhÆF3VèÞìÿÿÇG2Ò‹ÏÿS‹EÈé ÇpV.¸ ÀÇtVP鵃{rqÆF3‹N‰MÜf‹F ÁéþÁˆMÞ‹W ‹ ‰N4‹W ‹J‰N8ÇF<ÿÿÿÿ‹V‰VFf‹Èf‰NJ‹M܉N@f‰FD‰NTf‰FX‰VN·Àf‰FR¹ŠáŠÅf‰FZ‹VN‰V\f‹Ðé+ÿÿÿÇpVU¸ ÀÇtVPé ƒ{r‹W ¶PVèŸëÿÿéÿÿÿÇpVg¸ ÀÇtVPéêƒ{rfÆFpƆ€Ç†Œ‹O ‹‰Vt‹G ‹H‰Nx‹W ‹B‰F|‹O ‹Q ‰–ˆ‹F‰†f‹N f‰Ž…€†ƒÆFpƆ€éŒþÿÿÇpV¸ ÀÇtVPé`{w5€~pt/džŒ‹SR‹G PŽŒQèã ƒÄ ‹S‰–Œé6þÿÿÇpV©¸ ÀÇtVPéÇpV²¸ ÀÇtVP鿯EÇ‹C‰G‹G…Àu%ÇtVPÇpVϸ ÀÇGé°ö@t‹@ ëjjjjjPÿøR‰G …Àu%ÇtVPÇpVÛ¸šÀÇGéh€~uÇpVåé=ÇEÀž€‹Ëÿ€Rˆ†„€~t*€¾°t!‹†lƒxt‹Žpƒyu PèÍÓÿÿ‰EÀŠ–„‹Ëÿ„Rƒ}Àtj‹UÀRWè*æÿÿ‰EÈé‹Ëÿ€Rˆ†„€~t6€¾°t-W‹†pPè(Óÿÿ;Çu¹ &W8‡ ÇEÈ‹G`€HÆEÇŠ–„‹Ëÿ„R€}Ç…ŽÇpV éY‹G3Ò;ÂuÇpV/ ¸ Àé€ö@t‹@ ëjjjjjPÿøR3Ò‰G ;ÂuÇpV9 ¸šÀéG€~uÇpVA ¸Àé-ŠN3„Éurƒ{rd‰Uü‹K‰O‹N‹[SòRRPRjPPV‹ØP‹‰dÿÑ‹F‹ØR‹€pÿÐ3À‰EȉGÇEüþÿÿÿéá¸ÃÇpVl ë„É„¥ƒ{‚›ÇEüVNŠ€áð€ù`uV\‹K‰O‹N‹[SSPjRRV‹‘ØR‹dÿЋF‹ˆØQ‹pÿÒ3À‰EȉGÇEüþÿÿÿë`¸ÃÇpV¡ ÇtVP‹eè¸À‰EÈ‹}À‰GÇGÇEüþÿÿÿ‹uÜë"ÇpV« ¸#ÀÇtVP‰G‰EȉWƒ}ÈuÿF2Ò‹ÏÿS‹EÈéÞÿF2Ò‹ÏÿS‹EÈéÉžŒ‹Ã¹ðÁAƒùt3‹ÓƒÈÿðÁÿˆR<ƒˆh'ÿÄR‹ËºðÁBƒúuÍ3Ò8–°t'9–|uVèéÿÿ¸‰†|†¬‰UȉWëÇtVPÇpVÚ ¸À‰EȉG‰WƒÈÿðÁ2Ò‹ÏÿS‹EÈéÇpVå é´žŒ‹ËºðÁBƒút4ëI‹ÃƒÉÿðÁÿˆR<s{h'ÿÄR‹Ó¸ðÁ@ƒøuÑdž|VèQèÿÿŽlQè•äÿÿ€~1t'€~0u!jjh @‹VRÿ´R‹FPÿ¸RÆF1ƒÉÿðÁ 2Ò‹ÏÿS‹EÈëZÇpV ÇtVPÇG¸À‰G‰EÈ2Ò‹ÏÿS‹EÈë%2Ò‹Ï€;u ÿS3ÀëÇGÀÿS¸À‹Mðd‰ Y_^[‹Mä3Íè‹å]‹ÿ_6$734l.é7‹.Ø.2/w/91Î12Ž280ê2        ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìƒìSV‹uW3ÿjtWV‰}üè¦ƒÄ ¸Pj‹Èjp‰~ ‰}ø‰}ðf‰Eöf‰Mîè°Ìÿÿ‹Ø‰];ßu ÇEüšÀé‹} ¸à-‰C8‰C ‰C‰‰CŠ<{t „ÀtÔŠGG<{uôjjPèjÌÿÿ‰Eð‰F(…Àu ÇEüšÀé{jjPèKÌÿÿ‰Eø…Àu ÇEüšÀé_·Uî‹EðhpQWh`QhPQhjjRPèáÊÿÿƒÄ$…Àt ÇEüšÀé%‹EðPŠ@„Éuù·MöhpQWh0QhPQhj+‹UøjQRf‰Eìè”ÊÿÿƒÄ$…Àt ÇEüšÀ騋EøPŠ@„Éuù‹=ðR+Âf‰EôjEìPMäQÿ×…Àt ÇEüšÀé£jUôR^,Sÿ×…À…{‹MF P~WQSUäÆF4¡lVRPÿ°R…ÀuV‹ƒH3ÿj@‰~‰~hÆFèŠÌÿÿj‰èÌÿÿj‰FèwÌÿÿ‰Fp9>t#9~t;ÇtWh0(NHQÿôRÆFFÆFDëÇEüšÀUäRÿ S‹]‹Eø…ÀtjPPèªËÿÿ…ÛtjpSèžËÿÿ‹}ü…ÿtVè±×ÿÿ‹Ç_^[‹å]ÂÌÌÌÌÌÌ‹ÿU‹ìƒì‹MW3ÿ3ÀÆEþÆEÿ;Ïv‹U9<‚t@;Árö;Áu ¸À_‹å]‹M Vjhà‰èTÊÿÿ‹ð;÷u ^¸šÀ_‹å]ÂS‹]WjcjVSÿœRhÐ(VSÇF(ê‰~$ÆF2?‰^‰¾œƆ¤ÿ R‹URE PMQƆ™ÇF,ÜÆF0ÆF1ÿ¤R9}t2Ɔ˜9~tVÿØR€¾™t ‹VRÿÀR‹E[^_‹å]ÂW‹=¨R¹f‰MMôQf‰Uô‹U f‰Eìf‰EöREPMQÇEðRÇEøàQÿ׋E jUìRPMQURÿ׃}uc‹Eƒ8……jƒÀPVÿìR…ÀtnÇEšÀ‹U Rÿ¬Rƒ~Ɔ˜tVÿØR€¾™t ‹FPÿÀR[^¸šÀ_‹å]ƒ}u"‹ExujƒÃSVÿìR…Àu—‰Eëƒ}u“ƒ~tj¹EìPf‰Mì‹M ºf‰UîQUREPÇEðÐQÿ׃}u(‹Eƒ8u ‹@=@}¸@ë =~¸‰F,j¹EìPf‰Mì‹M ºf‰UîQUREPÇEð°Qÿ׃}u‹Eƒ8uƒxtÆF0ÆF1j¹EìPf‰Mì‹M ºf‰UîQUREPÇEðQÿ׃}u‹Eƒ8u ƒxtÆEÿj¹EìPf‰Mì‹M ºf‰UîQUREPÇEð€Qÿ׃}u7‹Eƒ8u/jƒÀPMôQÿìR…Àu‹UøRFPè ÊÿÿMôQŠØÿØRëŠ]þ‹U Rÿ¬R„Ûu ‹FPNQè¾ÊÿÿƒÈÿ‰Fjf‰Fn‹VR¾lWè4úÿÿ‹Ø…Ût2ƒ~Ɔ˜tVÿØR€¾™t ‹FPÿÀR‹Ã[^_‹å]ÂVèVÑÿÿ„ÀuSWÇtVPÇpVCèÈÓÿÿƒ~Ɔ˜tVÿØR€¾™„¶ýÿÿ‹NQÿÀR[^¸šÀ_‹å]€}ÿÆFtWèáÿÿ[^3À_‹å]ÂÌÌÌÌÌ; VuÂéÌÌÌÌÌ‹ÿU‹ìQ‰Müjÿ5$Vÿ5 Vÿuüh÷ÿäRÌÌÌÌÌÌÌÿ%SÌÌÌÌÌÌÿ%ÜRÌÌÌÌÌÌ‹ÿU‹ì‹U 3À;Ðt‹ ;Mr¸ Àë÷Et‹M9u ÇR;Ðt‰]ÂÌÌÌÌÌÌ‹ÿU‹ì‹M 3À…Ét;Mv¸ À] ÌÌÌÌÌÌ‹ÿU‹ì3À÷Et‹M 9Eu;Èu;Mv¸ Àëÿuÿu ÿuè¨ÿÿÿ]ÂÌÌÌÌÌÌ‹ÿU‹ìSV‹u Wÿu‹}ÿu3ÛNVWèüƒÄ…À| ;Æwuˆ>ëˆ>»€‹Æ‹M…Ét‰_^‹Ã[]ÂÌÌÌÌÌÌ‹ÿU‹ì‹E ƒøvHP‹E%ÿP‹E@PèÐþÿÿƒÄ 3À] ÌÌÌÌÌ‹ÿU‹ìS‹]V‹uW‹} …ÿv÷Et‹M‹U‰‹×+щÆ÷Et;‹E%ÿWPV‰E ètþÿÿƒÄ ƒ} u ‹E‰0‰;ë…ÿv)‹MD>ÿ‰ÇÆ…ÿv÷Et ‹E‰0‰;Æ_^3À[]ÂÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìƒìS‹] V‹s35 VW‹ÆEÿÇEø{ƒøþt ‹NÏ3 8è¨ýÿÿ‹N ‹FÏ3 8è˜ýÿÿ‹Eö@f…â‹MUì‰Sü‹[ ‰Eì‰Mðƒûþt_I[‹L†D†‰Eô‹‰E…Ét‹×è€ÆEÿ…À|@G‹E‹Øƒøþu΀}ÿt$‹ƒøþt ‹NÏ3 8è%ýÿÿ‹N ‹VÏ3 :èýÿÿ‹Eø_^[‹å]ÃÇEøëÉ‹M èW‹E 9X th VW‹Ó‹ÈèZ‹E ‹M‰H ‹ƒøþt ‹NÏ3 8èÆüÿÿ‹N ‹VÏ3 :è¶üÿÿ‹Eô‹H‹×èíºþÿÿÿ9S tŠh VW‹Ëè éTÿÿÿÌÌÌÌÌ‹ÿU‹ìƒì S3Û9]uSSSSSèØ ƒÄƒÈÿëu‹M V‹u;Ët;óuSSSSSè· ƒÄƒÈÿëS¸ÿÿÿ‰Eä;Èw‰MäWÿuEàÿuÇEìBÿu‰uèP‰uàèsƒÄ‹ø;ótÿMäx‹Eàˆë EàPSèŠYY‹Ç_^[ÉÃÌÌÌÌÌ‹ÿU‹ìÿujÿuÿu ÿuèIÿÿÿƒÄ]ÃÌÌÌÌÌÌÌSVW‹T$‹D$‹L$URPQQhDdÿ5¡ V3ĉD$d‰%‹D$0‹X‹L$,3‹p ƒþþt;‹T$4ƒúþt;òv.4v\³‹ ‰H ƒ{uÌh‹CèÎ ¹‹Cèà ë°dƒÄ_^[ËL$÷A¸t3‹D$‹H3ÈèûÿÿU‹hÿp ÿpÿpè>ÿÿÿƒÄ ]‹D$‹T$‰¸ÃU‹L$‹)ÿqÿqÿq(èÿÿÿƒÄ ]ÂUVWS‹ê3À3Û3Ò3ö3ÿÿÑ[_^]Ëê‹ñ‹Ájè+ 3À3Û3É3Ò3ÿÿæU‹ìSVWjjhÃDQè— _^[]ÃU‹l$RQÿt$è´þÿÿƒÄ ]ÂÌÌÌÌÌ‹ÿU‹ì‹E ƒH ƒÈÿ]ÃÌÌÌÌÌöA @tƒyt$ÿIx ‹ˆÿ¶Àë ¾ÀQPèÄÿÿÿYYƒøÿu ÃÿÃÌÌÌÌÌ‹ÿU‹ìV‹ðë‹MŠEÿM è°ÿÿÿƒ>ÿtƒ} ç^]ÃÌÌÌÌÌ‹ÿU‹ìöG @SV‹ð‹Ùt1ƒu+‹Eë*ŠÿM‹ÏèsÿÿÿCƒ>ÿuƒ=xV*u‹Ï°?è[ÿÿÿƒ}Ö^[]ÃÌÌÌÌÌ‹ÿU‹ììP¡ V3ʼnEü‹E‹US3Û‰…Àýÿÿ‰•àýÿÿ‰Èýÿÿ‰ðýÿÿ‰Ðýÿÿ‰èýÿÿ‰Ôýÿÿ‰Äýÿÿ‰Ìýÿÿ;ÃuSSSSS諃ăÈÿékV‹u ;óuSSSSS莃ăÈÿéMŠW3ÿ‰Üýÿÿ‰äýÿÿ„À„-F9Üýÿÿ‰u ŒŠÈ€é €ùXw¾È¾‰ÐSƒáë3ɾŒÏðSjÁù_‰¸ýÿÿ;χ¸ÿ$–Nƒèýÿÿÿ‰Äýÿÿ‰Ðýÿÿ‰Ôýÿÿ‰ðýÿÿ‰Ìýÿÿ釾Àƒè tJƒèt6ƒèt%HHtƒè…hƒðýÿÿé\ƒðýÿÿéPƒðýÿÿéDðýÿÿ€é5ƒðýÿÿé)<*u,ƒÂ‰•àýÿÿ‹Rü;Ó‰•Ðýÿÿ ƒðýÿÿ÷Ðýÿÿéù‹ÐýÿÿkÉ ¾ÀDЉ…ÐýÿÿéÞ‰èýÿÿéÓ<*u&ƒÂ‰•àýÿÿ‹Rü;Ó‰•èýÿÿµƒèýÿÿÿé©‹èýÿÿkÉ ¾ÀDЉ…èýÿÿéŽluFðýÿÿ‰u éSƒðýÿÿéGƒðýÿÿ é;Š€ù6u€~4uFFðýÿÿ€‰u é€ù3u€~2uFF¥ðýÿÿÿÿÿ‰u éû€ùd„ò€ùi„é€ùo„à€ùu„×€ùx„΀ùX„ʼn¸ýÿÿ‹ÀýÿÿµÜýÿÿ‰ÌýÿÿèRüÿÿ飾ÀƒøiÉt/ƒèC„?ƒè„ƃè„8HHt&ƒè „6H…ýƒðýÿÿ@Ç…äýÿÿ ée‹ƒÂ‰•àýÿÿ;Ãth‹p;óta·f9H‚I÷…ðýÿÿ·Át43É‹Ð÷ÒA„Ñ„+‹Ö÷Ò„Ñ„Ñ艵ìýÿÿ‰…äýÿÿ‰Ìýÿÿé‰Ìýÿÿ‰µìýÿÿéX¡(V‰…ìýÿÿPŠ@„Éuù+Âé<÷…ðýÿÿ0u ðýÿÿƒ½èýÿÿÿ¹ÿÿÿt‹èýÿÿƒÂ÷…ðýÿÿ‰•àýÿÿ‹Rü‰•ìýÿÿ„û;Óu ¡,V‰…ìýÿÿ‹…ìýÿÿÇ…ÌýÿÿéÀ÷…ðýÿÿ0u ðýÿÿƒÂ÷…ðýÿÿ‰•àýÿÿt0·BüPh…ôýÿÿP…äýÿÿPèPƒÄ…ÀtÇ…ÄýÿÿëŠBüˆ…ôýÿÿÇ…äýÿÿ…ôýÿÿ‰…ìýÿÿéeƒèn„H„¶Htoƒè„ ÿÿÿHH„Kþÿÿƒè…8Ç…Èýÿÿ'ëYIf9t@@;Ëuô+…ìýÿÿÑø‰…äýÿÿé ;Óu ¡(V‰…ìýÿÿ‹…ìýÿÿëI€8t@;Ëuõ+…ìýÿÿëËÇ…èýÿÿ‰½Èýÿÿö…ðýÿÿ€Ç…äýÿÿt>Š…ÈýÿÿQÆ…Øýÿÿ0ˆ…ÙýÿÿÇ…Ôýÿÿëö…ðýÿÿ€Ç…äýÿÿt ðýÿÿ‹ðýÿÿ÷Á€u÷Át‹ƒÂ‰•àýÿÿ‹Rüë,ƒÂ‰•àýÿÿöÁ töÁ@t¿Büë·Büë‹BüöÁ@t™ë3ÒöÁ@t;Ó|;Ãs÷؃Ò÷Úðýÿÿ÷…ðýÿÿ‹Ú‹øu3Ûƒ½èýÿÿ} Ç…èýÿÿ냥ðýÿÿ÷¸9…èýÿÿ~‰…èýÿÿ‹Ç Ãu!…Ôýÿÿuó‹…èýÿÿÿèýÿÿ…À‹Ç Ãt-‹…äýÿÿ™RPSWèsƒÁ0ƒù9‰´ýÿÿ‹ø‹Ú~ÈýÿÿˆNë½Eó+ÆF÷…ðýÿÿ‰…äýÿÿ‰µìýÿÿt_…Àt‹Î€90tTÿìýÿÿ‹ìýÿÿÆ0@é'þÿÿ‹2ƒÂ‰•àýÿÿè<…À„¬ö…ðýÿÿ t f‹…Üýÿÿf‰ë‹…Üýÿÿ‰Ç…Äýÿÿƒ½Äýÿÿ…\‹ðýÿÿöÃ@t=÷Ãt Æ…Øýÿÿ-ë"3À@„ØtÆ…Øýÿÿ+‰…ÔýÿÿëöÃtÆ…Øýÿÿ Ç…Ôýÿÿ‹µÐýÿÿ+µäýÿÿ+µÔýÿÿöà uÿµÀýÿÿ…ÜýÿÿVj èË÷ÿÿƒÄ ÿµÔýÿÿ‹½Àýÿÿ…ÜýÿÿØýÿÿèÖ÷ÿÿYöÃtöÃuWVj0…Üýÿÿè‘÷ÿÿƒÄ ƒ½Ìýÿÿ‹…äýÿÿtf…À~b‹ìýÿÿ‰…´ýÿÿ·ÿ´ýÿÿPjEôP…¼ýÿÿCPC躃ąÀu(9…¼ýÿÿt ÿµ¼ýÿÿ…ÜýÿÿMôèY÷ÿÿƒ½´ýÿÿYuµëƒÜýÿÿÿë‹ìýÿÿP…Üýÿÿè2÷ÿÿYƒ½Üýÿÿ|ö…ðýÿÿtWVj …ÜýÿÿèåöÿÿƒÄ ‹u Š„Àt%‹½¸ýÿÿ‹•àýÿÿ3Ûéå÷ÿÿSSSSSèEƒÄƒÈÿë‹…Üýÿÿ_^‹Mü3Í[èÀðÿÿÉÃI‘HŸFÉF'GrG}GÂG­HÌÌÌÌÌÃÌÌÌÌÌÌÌÌSQ»0Vë SQ»0V‹L$ ‰K‰C‰k UQPXY]Y[ÂÿÐÃÌÌÌÌÌ¡ VƒÈ3É9hV”Á‹ÁÃÌÌÌÌÌ‹ÿU‹ìW3ÿ9} u9}v ‹E;Çt‰83ÀëeV‹u;÷tƒÿ}ÿÿÿvWWWWWèoÿÿÿƒÄjXë>9} u ;÷t3¡PVë*jEPE Pÿuÿu èí…À} j*X£xVë ;÷t‹E ‰3À^_]ÃÌÌÌÌÌ‹ÿU‹ìjÿuÿuÿu ÿuè\ÿÿÿƒÄ]ÃÌÌÌÌÌÌÌÌV‹D$ Àu(‹L$‹D$ 3Ò÷ñ‹Ø‹D$÷ñ‹ð‹Ã÷d$‹È‹Æ÷d$ÑëG‹È‹\$‹T$ ‹D$ÑéÑÛÑêÑØ Éuô÷ó‹ð÷d$‹È‹D$÷æÑr;T$ wr;D$v N+D$T$3Û+D$T$ ÷Ú÷؃ڋʋӋًȋÆ^ÂÌÌÌÌÌÿ%$SÌÌÌÌÌÌÿ%(SÌÌÌÌTAP-Windows Adapter V9ÌÌÌÌÌÌÌÌÌc:\users\samuli\tap-windows\src\tapdrvr.cÌÌÌÌÌÌState=%s Err=[%s/%d] #O=%d Tx=[%d,%d] Rx=[%d,%d] IrpQ=[%d,%d,%d] PktQ=[%d,%d,%d] InjQ=[%d,%d,%d]ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ\DosDevices\Global\ÌÌÌÌÌÌÌÌÌÌÌÌ%s%s%sÌÌÌÌÌÌÌÌÌ\Device\ÌÌÌÌÌÌÌ.tapÌÌÌÌÌÌÌÌÌÌÌMACÌÌÌÌÌÌÌÌAllowNonAdminÌÌÌÌMediaStatusÌÌÌÌÌÌÌÌMTUÌÌÌÌÌÌÌÌNdisVersionÌÌÌÌÌÌÌÌMiniportName®ZšZ†ZN\6\\\Ú[Â[ª[[z[d[F[.[[øZæZÊZf\YúXYhZZZ:ZZZèYÔY¶Y¨Y’YˆYtYZYDYðX,Yˆ\”\”E PI˜T˜T     (null)(null)EEE50P( 8PP700WP `h````xpxxppH VðTRSDSÊÁ?¿´D´hœ¿¸øŠc:\Users\Samuli\tap-windows\src\i386\tap0901.pdbpADþÿÿÿÔÿÿÿþÿÿÿlrþÿÿÿØÿÿÿþÿÿÿöüþÿÿÿÔÿÿÿþÿÿÿÈÎþÿÿÿBHþÿÿÿØÿÿÿþÿÿÿ‰þÿÿÿÈÿÿÿþÿÿÿ™-Ÿ-äÿÿÿ°ÿÿÿþÿÿÿN5T5þÿÿÿÏ5Õ5ÿÿþ€Næ@»±¿DèSØS “u˜s˜.‹ÿU‹ì‹E ‹MVWjPQhlV¿ÀÿÐRè:¹ÿÿ„À„½jj`èù®ÿÿ‹ð…ö„ªj`ÆÆFÇF ;ÇFÐ(ÇF,`ÇF8pÇF0p)ÇF$€ÇF4 ‹lVVRÿR‹øÿÀ tÿšÀu‹ lVjQë‹lVjRë …ÿt¡lVjPÿ”Rj`VèC¯ÿÿ…ÿu‹ lVhQÿ˜R‹Ç_^]¡`V…ÀthPè¯ÿÿÇ`V‹Ç_^]ÂÌÌÌÌÌ¡ V¹Næ@»…Àt;Áu¡èR‹5 V£ Vu‹Á£ V÷У$VÃÌÌÌÌÌ‹ÿU‹ìè½ÿÿÿ]é¡þÿÿ̘XxZØR@XÂZ€RPX~\R®ZšZ†ZN\6\\\Ú[Â[ª[[z[d[F[.[[øZæZÊZf\YúXYhZZZ:ZZZèYÔY¶Y¨Y’YˆYtYZYDYðX,Yˆ\”\©memset§memcpyRtlFreeAnsiStringJKeRemoveQueueDpcRtlFreeUnicodeStringãIofCompleteRequest¡IoReleaseCancelSpinLock&KeInsertQueueDpc ZwCloseeZwSetSecurityObject/ZwOpenFileÌRtlCreateSecurityDescriptor¯MmMapLockedPages°MmMapLockedPagesSpecifyCacheKeInitializeDpc©RtlAnsiStringToUnicodeString–RtlUnicodeStringToAnsiStringfKeTickCountöKeBugCheckExntoskrnl.exe@KeGetCurrentIrqlOKfReleaseSpinLockLKfAcquireSpinLockHAL.dllNdisAllocateMemoryWithTagUNdisFreeMemoryÍNdisMSleep§NdisMDeregisterAdapterShutdownHandler¨NdisMDeregisterDevice²NdisMIndicateStatusComplete±NdisMIndicateStatus½NdisMRegisterDevice$NdisCloseConfigurationéNdisReadConfigurationÙNdisOpenConfiguration¼NdisMRegisterAdapterShutdownHandlerÈNdisMSetAttributesExÂNdisMRegisterUnloadHandlerNdisTerminateWrapperÁNdisMRegisterMiniport‰NdisInitializeWrapperNDIS.SYS RtlUnwindœRtlUnicodeToMultiByteN€0€ H`]``4VS_VERSION_INFO½ïþ ?ÀStringFileInfoœ040904B0HCompanyNameThe OpenVPN Projectn#FileDescriptionTAP-Windows Virtual Network DriverVFileVersion9.9.1 9/9 built by: WinDDK8 InternalNametap0901.sysZLegalCopyrightOpenVPN Technologies, Inc.@ OriginalFilenametap0901.sysf#ProductNameTAP-Windows Virtual Network Driver8 ProductVersion9.9.1 9/9DVarFileInfo$Translation °È5Í5ß56¨6­6¿6ð6ÿ?¼0V0‚0‘0 1-1G1à1 22‘2¦2 303O3Œ3÷34I4O5 6¤6¨6¬6°6´6¸6¼6À6Ä6È6Ì6Ð6Ô6Ø6Ü6à6ä6è6ì6ð6ô6ø6ü6777C8„8¡8@9D9H9L98:=:O:Ó:×:Ý: ;;;5;i;©;Ç;ô;<4|>Ì>â>÷>??/?”?˜?ž?  “00¡0´0¿0É0Í0 111#1:1E1O1S1d1n1x1|1N4u4µ4E5M5V5_5¢5«5´5½5E8”8´8Ø8ã8ç8í889K9x9}99T:«:Ä:È:Î:;; ;¤<á<=,==è=í=ü=a>h>€>‡>®>¼>Ë>Ï>??%?)?M?[?j?n?ý?00 0|0‹0011,101²1Á1Å1è1÷1û1r22…2Î2Ý2á2ì2û2ÿ233%3V3c3g3m3Ž3¬3ð34=4b4r4Š4´4Ã4Ý4V5×5á5å566"6>6S66”6Ü6à6æ6 77K7Z7¦7°7Å7Ð7Ú7Þ7ú788H8L8P8T8X8\8p8t8x8|8€8„8ˆ8Œ88”8)99–9›9Ô9Ú9ß9:m:u:»:Å:à:Œ;‘;·;ß;÷; <A>^>m>²>Å>á>å>ë>??S?s?y?‡?”? ?Ø?@@‚1`2³2¡3­3¹45º5q6€6›6x9ä9ß:–>š>ž>¢>¦>ª>®>²>Ç>Ð>õ>?^??Ph\0h0Œ44 55,505L5P5X5\5t5x5”5˜5´5¸5À5Ä5(6,6¢6­6Ý6ä6ë6ò6ù677 77/7:7H7Q7c7h7o7|7‘7§7¹7À7Å7Î7Õ7€0‚p *†H†÷  ‚a0‚]1 0 +0h +‚7 Z0X03 +‚70%  ¢€<<<Obsolete>>>0!0 +—}{67Pì(ëE!¼V³·í10ˆ ‚º0‚;0‚#  a M´'0  *†H†÷ 01 0 UUS10U Washington10URedmond10U Microsoft Corporation1)0'U Microsoft Code Verification Root0 110415194533Z 210415195533Z0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0‚"0  *†H†÷ ‚0‚ ‚ÆÌåsæûÔ»å--2¦ßå?ÉÍ%I¶q*ÃÕ”4g¢ °_i¦@±Ä·²Ð˜¤©AY:ÓÜ”Ö<Ût8¤JÌM%‚÷J¥S8îóImq‘~c¶«¦_䄸ObQ¾øÅìÛ8’ãå‘ Ä(AUûËZ‰~qè5¿Mr =¾:8P[w1³Ç$Eš§¬mZ·ºëQ ˜AA"Nea‡AP¦y\‰ÞJWÕ.æ]S,~˜Í¤hsÐ4\¡qÓZ|UÛ^dá7‡0Vå´)€ñy9ˆ¢|'f·ˆ·xòÊ ¨8« d¿f]•„Á¡%‡]P ÌA»n Q8¸KË£Ë0È0U  00U 0 U†0Uÿ0ÿ0U±>Ãiø¿GÔ˜&ïcd+Ã0U#0€bû ![CnÚ TPkõÒ–qñž0UUN0L0J H F†Dhttp://crl.microsoft.com/pki/crl/products/MicrosoftCodeVerifRoot.crl0  *†H†÷ ‚ ŒÁYíoœk-ÁJ>uELAP½€êÙ°’‹*?SžV9jŠc¶x$yõ}¸¹G¡ –Âö˽¢fŸá¬Òy ý<ܬ p¯?ìx~ÔëK`&Ùsa‘!í°hcà—«o íÙŸÒÚ'<³äVùÑÔq½B|¦‰ÜÍÕ½•¢«ñ“}è¬1)¨]fpAüuÉÕ³9*Ð…P‹¬‘ÊÄ“Ëq¥¤”oX ún Ä1µ…~ùÒ=Ê[…l †ì" ¥t4O(¼•J«¶˜°] ¤wv~ï§Ž]„ö$ËÑm¦Ã¡œÂu€ÿ2ýæÏC:‚÷Îár*›b·_í•9\/”mH·_3/»Ü-s4‰B ‹yù£úïú¡ßà²Á•ë\ —;5>ˆMÛl¿$‰È½ØŸ{9:$ ÕßÑóJ—ö¦oz°©³¬9‘Óa·dñ>W8¯ÎzÒµõ®Ü9™Õ¶<—í¦ËÇ}k*L”æLTýÍ ìÎhœ‡Xéa`¾ëÉÕ}Ÿéx½¬!u©nàŒj*kœãçe¼¼-}:vÛãÅ,0‚¿0‚§ Wî]pë› ±R rœ 0  *†H†÷ 0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0 110210120000Z 260210120000Z0s1 0 UUS10U  DigiCert Inc10U www.digicert.com1200U)DigiCert High Assurance Code Signing CA-10‚"0  *†H†÷ ‚0‚ ‚Åù#æ”'Ä€¤€2_@£opÀå6qq:u¤ª’”‰^¬#qËNg}A?ªãK·{¾Á¨8i/:$éwYÇfC &‚‰@ò,êçLç|¸ÿˆ O&7ï:¤ú"lˆÉJaò®^o¼Ñy›Y`åî)µ*¤ÎñƒOis( û"“" L1òÓ+Ø„C¯-îP«×0x<¥#g‘£‚T0‚P0Uÿ0U% 0 +0‚ÃU ‚º0‚¶0‚²`†H†ýl0‚¤0:+.http://www.digicert.com/ssl-cps-repository.htm0‚d+0‚V‚RAny use of this Certificate constitutes acceptance of the DigiCert EV CPS and the Relying Party Agreement which limit liability and are incorporated herein by reference.0Uÿ0ÿ0+s0q0$+0†http://ocsp.digicert.com0I+0†=http://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt0U‡0„0@ > <†:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl0@ > <†:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl0U—Hëk¹²X#Ì”.ñÆeÒdŽ0U#0€±>Ãiø¿GÔ˜&ïcd+Ã0  *†H†÷ ‚‚é…¯§L¿¯Î=²ê`±hÞgÂÒË&àÃ/›µkS…ö›à5ÿúiƒª´t2<.L(› ­ ùó„“Ë`@Véw/i²ƒ™U«G$–ËK°´—¿Ä¥™þŽìP^W—ËG¹4Ùü:¢ÿP) bîÞ–:o Â…oüä2{Ó„®i` F&œèðÿÿ†ÙÈ :fç6Oè±–’.N¾ §3®¼nOñ~´FdùY"!dKâz缉žBOÀ¶uêF²¥T/Œ“Í64j(WÌ”?é|È~CÚù—¡YGÚªàm8]5+Å"†ËʼzM=&F1‚!0‚0‡0s1 0 UUS10U  DigiCert Inc10U www.digicert.com1200U)DigiCert High Assurance Code Signing CA-1;7’›£9Y c0 + p0 +‚7 100 *†H†÷  1  +‚70 +‚7 10  +‚70# *†H†÷  1Ò<,¿¨æÉH­´ˆP—Úü´¸0  *†H†÷ ‚œ—c„Cpý8ý¾¦MÜ0#†n+Ñ? ì³Sgv%ÂÔq—ƒå)àvm؉V–;y¹ãoLåJŸ™ÂUìÎè;INH°6C$ -±pð’îê7*$<øC‹|Ø4;,!‚XWZiƒû]ÄîTH‡GA…ðŽºÕ˜öt>±²š]+hZ‚”9^ŠO}а=3B K Äa- í Â/å€CÀ©ûuc/a4nåN‡.ÎÀþY-Õ 7Qp{lu \s!€êm¬Y“ƒ—^ÎQnÔ ÚäëäŽØW‹KîÊ2pý´fØòéé¼ÿž2ãìm¾¹àµgnunet-0.10.1/contrib/openvpn-tap32/tapw32/tap0901.cat0000644000175000017500000001462712123076772017016 000000000000000‚“ *†H†÷  ‚„0‚€1 0 +0‚Š +‚7  ‚{0‚w0  +‚7 ‘L5XNÒ@«<º ƒvž¼ 120720114838Z0 +‚7 0‚x0‚»R977D7B363750EC28EB4521BC56B3B7ED311930881‚c0: +‚7 1,0*Filetap0901.sys0V +‚7 1H0F OSAttr02:5.1,2:5.2,2:6.0,2:6.10b +‚7 1T0RL{C689AAB8-8E78-11D0-8C47-00C04FC295EE}0i +‚71[0Y04 +‚70&   ¢€<<<Obsolete>>>0!0 +—}{67Pì(ëE!¼V³·í10ˆ0‚µRD65994DD38DE0E1971F8C99A048C46ACC284E8BF1‚]0< +‚7 1.0,Fileoemwin2k.inf0V +‚7 1H0F OSAttr02:5.1,2:5.2,2:6.0,2:6.10a +‚71S0Q0, +‚7¢€<<<Obsolete>>>0!0 +ÖY”Ý8ÞqøÉšŒF¬Â„è¿0b +‚7 1T0RL{DE351A42-8E59-11D0-8C47-00C04FC295EE} ¹0¶0~ +‚7 p0nOS`XPX86,Server2003X86,VistaX86,Server2008X86,7X8604 +‚7 &0$ HWID1tap0901 ‚º0‚;0‚#  a M´'0  *†H†÷ 01 0 UUS10U Washington10URedmond10U Microsoft Corporation1)0'U Microsoft Code Verification Root0 110415194533Z 210415195533Z0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0‚"0  *†H†÷ ‚0‚ ‚ÆÌåsæûÔ»å--2¦ßå?ÉÍ%I¶q*ÃÕ”4g¢ °_i¦@±Ä·²Ð˜¤©AY:ÓÜ”Ö<Ût8¤JÌM%‚÷J¥S8îóImq‘~c¶«¦_䄸ObQ¾øÅìÛ8’ãå‘ Ä(AUûËZ‰~qè5¿Mr =¾:8P[w1³Ç$Eš§¬mZ·ºëQ ˜AA"Nea‡AP¦y\‰ÞJWÕ.æ]S,~˜Í¤hsÐ4\¡qÓZ|UÛ^dá7‡0Vå´)€ñy9ˆ¢|'f·ˆ·xòÊ ¨8« d¿f]•„Á¡%‡]P ÌA»n Q8¸KË£Ë0È0U  00U 0 U†0Uÿ0ÿ0U±>Ãiø¿GÔ˜&ïcd+Ã0U#0€bû ![CnÚ TPkõÒ–qñž0UUN0L0J H F†Dhttp://crl.microsoft.com/pki/crl/products/MicrosoftCodeVerifRoot.crl0  *†H†÷ ‚ ŒÁYíoœk-ÁJ>uELAP½€êÙ°’‹*?SžV9jŠc¶x$yõ}¸¹G¡ –Âö˽¢fŸá¬Òy ý<ܬ p¯?ìx~ÔëK`&Ùsa‘!í°hcà—«o íÙŸÒÚ'<³äVùÑÔq½B|¦‰ÜÍÕ½•¢«ñ“}è¬1)¨]fpAüuÉÕ³9*Ð…P‹¬‘ÊÄ“Ëq¥¤”oX ún Ä1µ…~ùÒ=Ê[…l †ì" ¥t4O(¼•J«¶˜°] ¤wv~ï§Ž]„ö$ËÑm¦Ã¡œÂu€ÿ2ýæÏC:‚÷Îár*›b·_í•9\/”mH·_3/»Ü-s4‰B ‹yù£úïú¡ßà²Á•ë\ —;5>ˆMÛl¿$‰È½ØŸ{9:$ ÕßÑóJ—ö¦oz°©³¬9‘Óa·dñ>W8¯ÎzÒµõ®Ü9™Õ¶<—í¦ËÇ}k*L”æLTýÍ ìÎhœ‡Xéa`¾ëÉÕ}Ÿéx½¬!u©nàŒj*kœãçe¼¼-}:vÛãÅ,0‚¿0‚§ Wî]pë› ±R rœ 0  *†H†÷ 0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0 110210120000Z 260210120000Z0s1 0 UUS10U  DigiCert Inc10U www.digicert.com1200U)DigiCert High Assurance Code Signing CA-10‚"0  *†H†÷ ‚0‚ ‚Åù#æ”'Ä€¤€2_@£opÀå6qq:u¤ª’”‰^¬#qËNg}A?ªãK·{¾Á¨8i/:$éwYÇfC &‚‰@ò,êçLç|¸ÿˆ O&7ï:¤ú"lˆÉJaò®^o¼Ñy›Y`åî)µ*¤ÎñƒOis( û"“" L1òÓ+Ø„C¯-îP«×0x<¥#g‘£‚T0‚P0Uÿ0U% 0 +0‚ÃU ‚º0‚¶0‚²`†H†ýl0‚¤0:+.http://www.digicert.com/ssl-cps-repository.htm0‚d+0‚V‚RAny use of this Certificate constitutes acceptance of the DigiCert EV CPS and the Relying Party Agreement which limit liability and are incorporated herein by reference.0Uÿ0ÿ0+s0q0$+0†http://ocsp.digicert.com0I+0†=http://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt0U‡0„0@ > <†:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl0@ > <†:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl0U—Hëk¹²X#Ì”.ñÆeÒdŽ0U#0€±>Ãiø¿GÔ˜&ïcd+Ã0  *†H†÷ ‚‚é…¯§L¿¯Î=²ê`±hÞgÂÒË&àÃ/›µkS…ö›à5ÿúiƒª´t2<.L(› ­ ùó„“Ë`@Véw/i²ƒ™U«G$–ËK°´—¿Ä¥™þŽìP^W—ËG¹4Ùü:¢ÿP) bîÞ–:o Â…oüä2{Ó„®i` F&œèðÿÿ†ÙÈ :fç6Oè±–’.N¾ §3®¼nOñ~´FdùY"!dKâz缉žBOÀ¶uêF²¥T/Œ“Í64j(WÌ”?é|È~CÚù—¡YGÚªàm8]5+Å"†ËʼzM=&F1‚ 0‚0‡0s1 0 UUS10U  DigiCert Inc10U www.digicert.com1200U)DigiCert High Assurance Code Signing CA-1;7’›£9Y c0 + o0 +‚7 100 *†H†÷  1  +‚7 0 +‚7 10  +‚70# *†H†÷  1Oú£KùÆœÄÞ¾6|i Z'$M0  *†H†÷ ‚DÓŸûãüqð ý¬ûP}¦c?9÷Èr¡,¼¸.U rEx®ùÂ5±íâ$0ð 1ƒý‘ê\c ·D&­+ò8›³1><âÈ©ß} Ö Òéµ6OIÏÛé®ÞU^;ŸQË×dM áQ¸Öç(k=Nq IQþ}Xx†Åµ±I 8/®¨2ì’°®ÇÑ K+ràdž]’äzÝØ%ày‹éåýsD¦3‚N)}¦ãý†k:ÖnµúÏ6@ưNo±Î¤–Ô#­>ûR‡Žâþ‹ô:è,Wùz-s§BU·ˆµç2¾w J‰Gš Àž®œ¨…|RøX€®§gnunet-0.10.1/contrib/openvpn-tap32/tapw64/0000755000175000017500000000000012320755622015277 500000000000000gnunet-0.10.1/contrib/openvpn-tap32/tapw64/OemWin2k.inf0000644000175000017500000001617012123076772017360 00000000000000; **************************************************************************** ; * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. * ; * This program is free software; you can redistribute it and/or modify * ; * it under the terms of the GNU General Public License version 2 * ; * as published by the Free Software Foundation. * ; **************************************************************************** ; SYNTAX CHECKER ; cd \WINDDK\3790\tools\chkinf ; chkinf c:\src\openvpn\tap-win32\i386\oemwin2k.inf ; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm ; INSTALL/REMOVE DRIVER ; tapinstall install OemWin2k.inf TAP0901 ; tapinstall update OemWin2k.inf TAP0901 ; tapinstall remove TAP0901 ;********************************************************* ; Note to Developers: ; ; If you are bundling the TAP-Windows driver with your app, ; you should try to rename it in such a way that it will ; not collide with other instances of TAP-Windows defined ; by other apps. Multiple versions of the TAP-Windows ; driver, each installed by different apps, can coexist ; on the same machine if you follow these guidelines. ; NOTE: these instructions assume you are editing the ; generated OemWin2k.inf file, not the source ; OemWin2k.inf.in file which is preprocessed by winconfig ; and uses macro definitions from settings.in. ; ; (1) Rename all tapXXXX instances in this file to ; something different (use at least 5 characters ; for this name!) ; (2) Change the "!define TAP" definition in openvpn.nsi ; to match what you changed tapXXXX to. ; (3) Change TARGETNAME in SOURCES to match what you ; changed tapXXXX to. ; (4) Change TAP_COMPONENT_ID in common.h to match what ; you changed tapXXXX to. ; (5) Change SZDEPENDENCIES in service.h to match what ; you changed tapXXXX to. ; (6) Change DeviceDescription and Provider strings. ; (7) Change PRODUCT_TAP_WIN_DEVICE_DESCRIPTION in constants.h to what you ; set DeviceDescription to. ; ;********************************************************* [Version] Signature = "$Windows NT$" CatalogFile = tap0901.cat ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} Provider = %Provider% Class = Net ; This version number should match the version ; number given in SOURCES. DriverVer=07/02/2012,9.00.00.9 [Strings] DeviceDescription = "TAP-Windows Adapter V9" Provider = "TAP-Windows Provider V9" ;---------------------------------------------------------------- ; Manufacturer + Product Section (Done) ;---------------------------------------------------------------- [Manufacturer] %Provider% = tap0901, NTamd64 [tap0901.NTamd64] %DeviceDescription% = tap0901.ndi, tap0901 ;--------------------------------------------------------------- ; Driver Section (Done) ;--------------------------------------------------------------- ;----------------- Characteristics ------------ ; NCF_PHYSICAL = 0x04 ; NCF_VIRTUAL = 0x01 ; NCF_SOFTWARE_ENUMERATED = 0x02 ; NCF_HIDDEN = 0x08 ; NCF_NO_SERVICE = 0x10 ; NCF_HAS_UI = 0x80 ;----------------- Characteristics ------------ [tap0901.ndi] CopyFiles = tap0901.driver, tap0901.files AddReg = tap0901.reg AddReg = tap0901.params.reg Characteristics = 0x81 [tap0901.ndi.Services] AddService = tap0901, 2, tap0901.service [tap0901.reg] HKR, Ndi, Service, 0, "tap0901" HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" HKR, , Manufacturer, 0, "%Provider%" HKR, , ProductName, 0, "%DeviceDescription%" [tap0901.params.reg] HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" HKR, Ndi\params\MTU, Type, 0, "int" HKR, Ndi\params\MTU, Default, 0, "1500" HKR, Ndi\params\MTU, Optional, 0, "0" HKR, Ndi\params\MTU, Min, 0, "100" HKR, Ndi\params\MTU, Max, 0, "1500" HKR, Ndi\params\MTU, Step, 0, "1" HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" HKR, Ndi\params\MediaStatus, Type, 0, "enum" HKR, Ndi\params\MediaStatus, Default, 0, "0" HKR, Ndi\params\MediaStatus, Optional, 0, "0" HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" HKR, Ndi\params\MAC, Type, 0, "edit" HKR, Ndi\params\MAC, Optional, 0, "1" HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" HKR, Ndi\params\AllowNonAdmin, Default, 0, "1" HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" ;---------------------------------------------------------------- ; Service Section ;---------------------------------------------------------------- ;---------- Service Type ------------- ; SERVICE_KERNEL_DRIVER = 0x01 ; SERVICE_WIN32_OWN_PROCESS = 0x10 ;---------- Service Type ------------- ;---------- Start Mode --------------- ; SERVICE_BOOT_START = 0x0 ; SERVICE_SYSTEM_START = 0x1 ; SERVICE_AUTO_START = 0x2 ; SERVICE_DEMAND_START = 0x3 ; SERVICE_DISABLED = 0x4 ;---------- Start Mode --------------- [tap0901.service] DisplayName = %DeviceDescription% ServiceType = 1 StartType = 3 ErrorControl = 1 LoadOrderGroup = NDIS ServiceBinary = %12%\tap0901.sys ;----------------------------------------------------------------- ; File Installation ;----------------------------------------------------------------- ;----------------- Copy Flags ------------ ; COPYFLG_NOSKIP = 0x02 ; COPYFLG_NOVERSIONCHECK = 0x04 ;----------------- Copy Flags ------------ ; SourceDisksNames ; diskid = description[, [tagfile] [, , subdir]] ; 1 = "Intel Driver Disk 1",e100bex.sys,, [SourceDisksNames] 1 = %DeviceDescription%, tap0901.sys ; SourceDisksFiles ; filename_on_source = diskID[, [subdir][, size]] ; e100bex.sys = 1,, ; on distribution disk 1 [SourceDisksFiles] tap0901.sys = 1 [DestinationDirs] tap0901.files = 11 tap0901.driver = 12 [tap0901.files] ; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK ; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK [tap0901.driver] tap0901.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK ;--------------------------------------------------------------- ; End ;--------------------------------------------------------------- gnunet-0.10.1/contrib/openvpn-tap32/tapw64/tap0901.sys0000644000175000017500000010760012123076772017064 00000000000000MZÿÿ¸@𺴠Í!¸LÍ!This program cannot be run in DOS mode. $—Q7Zö?dZö?dZö?dSޏd[ö?dSŽ»dYö?dZö>d|ö?dSެd_ö?dSŽªdYö?dS޼dUö?dS޶d[ö?dSŽ«d[ö?dSŽ®d[ö?dRichZö?dPEd†–E Pð"  ^0¢Ð†AP¢<°Àøz€À @qp8.textáUV h.rdatat p Z@H.data˜€d@È.pdataøf@HINIT^ l â.rsrcÀ°t@B.reloc<Àx@B@UVWATAUHƒì`‹´$°M‹áM‹èA¸ÿÿÿD‹ÎH‹úH‹éè?C…ÀˆGHŒ$¸D‹Î3ÒA¸ÿÿÿH‰\$XH‰l$0H‰|$8èØB‹Ø…Àˆ¬÷Æàÿÿt» ÀH…ÿ„£ÆEéšH…ÿu%H‹„$¸@88„€» À¸€H…íDËØëpL‹Œ$¸H„$ÀLD$@H‹×H‹ÍH‰D$ HÇD$@èÛAH‹×‹ØH‹D$@H+ÐH (H‰L$0H‰T$8…Ûx#ºæ sHƒúvD‹Æè|Aë H…ÿtÆE…Ûy:÷Æt&H…ÿt!HD$8LL$0E3ÀH‹×H‹Í‰t$(H‰D$ è{@…Ûyû€uM…ít H‹D$0I‰EM…ät H‹D$8I‰$‹ÃH‹\$XHƒÄ`A]A\_^]ÃÌÌÌÌÌÌÌÌH‰\$H‰t$WHƒì ¶ò‹ù3ÛH‰\$@…ÉtBA¸TAPA‹×HL$@ÿ6^…Àu"@„ötL‹Ç3ÒH‹L$@è–BH‹\$@ë H‹\$@ëH‰\$@ë3ÛH‹ÃH‹\$0H‹t$8HƒÄ _ÃÌÌÌÌÌÌÌÌÌÌÌÌHƒì(H…Ét…Òt E3Àÿ ^ëHƒÄ(ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌD‹IL‹Â‹QA;Ñu3ÀÃA;ÑrA+ÑL‰DÑÿA‹A;A v‰A I‹ÀÃÌÌÌÌÌÌÌÌÌÌÌÌÌ‹A…Àu3ÀÃD‹D‹IAP‰A;ÑrA+щÿȉA;A v‰A J‹DÁÃÌÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰|$E3À3ÛH‹ùD‰fD‰GD¾C2ÉD‹ÓL‹ÛL‹ÈE…À„Ëfff„HÿÂAƒø:„–Aƒø-„ŒAƒø.„‚Aƒø0|Aƒø9~AƒøA|AƒøF~ A@Ÿƒø‡A@¿ƒøwAƒÀÉëA@ŸƒøwAƒÀ©ëA@ÐD‹Ãƒø DFÀAƒús]„ÉuEˆ;±ë'A¶;IÿÃAÿÂÀàL‹ËAÀ2ÉAˆD;ÿ‹ÃëDÐMÙ2ɸL‹ÈD¾E…À…@ÿÿÿB ƒù“ÀH‹\$H‹|$ÃH‹\$H‹|$2ÀÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌHƒì3ÀE3ÀE3Ò‰f‰AˆÆAÿ¶E3ÉA»„À„”H‰$HYHÿÂAƒûs<{uAºëi<0r<9vA‹@‰BFA·@ f‰BJ¸cS‚cȉ‚ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌH‰\$ UATAUHƒìPM‹áM‹è‹ÚH‹éƒútƒút ƒú…Y²¹H‰t$pèSøÿÿH‹ðH…À„7€xÆD$x5ÆD$yˆ\$zu4‹Hùw#H‹ÈHT$x·f‰„1¶Bˆ„1!ƒëÆF€~‹…ˆÆD$@6‰D$BÆD$Au/‹A=wHT$@‹‰„1·Bf‰„1#ƒëÆFH‰¼$€ƒût ƒû…Ï€~‹…”ÆD$@3ÈÆD$A‰D$Bu/‹A=wHT$@‹‰„1·Bf‰„1#ƒëÆF€~‹…„ÆD$@‰D$BÆD$Au/‹A=wHT$@‹‰„1·Bf‰„1#ƒëÆF€~‹½˜u/‹9=w…ÿtH•˜HŒ1L‹Çè™E>ëÆF€~u‹A=w Æ„1ÿÿëÆF€~…€‹‰\$8HV‰D$0H‹„$˜M‹ÌH‰D$(H‹„$M‹ÅH‹ÍH‰D$ èOüÿÿHNºè‘ùÿÿ‹LN#fÁÈLFHN'“øf‰FèúÿÿDƒHVfÁÈH‹Íf‰F-èå1ºH‹Îè˜öÿÿH‹¼$€H‹t$pH‹œ$ˆHƒÄPA]A\]ÃÌÌÌÌÌÌÌÌÌH‰\$H‰l$VATAUHƒì0A·@Hc\$xM‹áfÁÈI‹èL‹êD·ÐHƒ H‹ñL;Ð…tA·@¹ÿfÁÈf…Á…]H‰|$PH‹|$pH‹ÎH‰|$ èQúÿÿ„ÀuH‹|$PH‹\$XH‹l$`HƒÄ0A]A\^Ã3É…Û~Hffffff„LcÁ‹ÓA¶„8ð+ÑÿÊ<ÿ„›„Àt<5trƒú| A¶„8ñLÿÁ;Ë|ƃËÿ€?…ȃûtoƒû…º‹G …Àt;†€u€¾œt ƒ¾ rEL‹ÍM‹ÅºH‹ÎH‰|$(L‰d$ è.üÿÿëeƒú|HcÁ€¼8ñu ¶œ8òëƒËÿ눃Ëÿ냺¸ƒûL‹ÍM‹ÅH‹ÎDÐH‰|$(L‰d$ èÞûÿÿƒûu ˆžœŠÃéßþÿÿƒûu‹G …Àt;†€tÿ† °é¾þÿÿ°é¼þÿÿÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌL‹ÜI‰[I‰sWHƒì H‹@2ÿH‹ñ¶ØI‰CA¶C H3ØA¶C H3ØA¶C H3ØA¶C H3ØA¶C H3ØA¶CH3ØA¶CH3ظHÁãH„cðÁCÿÀƒøt1„ðƒCÿD À<s@¹'ÿ`R¸ðÁCÿÀƒøu×3ÒJèmóÿÿH…ÀtH‰pH‹ @·H‰H‰ðƒCÿH‹\$8H‹t$@@ŠÇHƒÄ _ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌL‹ÜI‰kI‰s WHƒì H‹@2íH‹ñ¶øI‰CA¶C H3øA¶C H3øA¶C H3øA¶C H3øA¶C H3øA¶CH3øA¶CH3ø¸HÁçH=”bðÁGÿÀƒøt1„ðƒGÿD À<sy¹'ÿpQ¸ðÁGÿÀƒøu×H‰\$8H‹3ÉH…ÛtDH9st H‹ËH‹H…Ûuïë1H…ÉtH‹H‰ëH‹H‰H‹KºXèÄòÿÿºH‹Ëè·òÿÿ@µðƒGÿH‹\$8H‹t$H@ŠÅH‹l$@HƒÄ _ÃÌÌÌÌÌÌÌL‹ÜI‰[I‰sI‰KWHƒì A¶C ¶Ù3ÿH3ØA¶C H‹ñH3ØA¶C H3ØA¶C H3ØA¶C H3ØA¶CH3ØA¶CH3ظHÁãH|aðÁCÿÀƒøt)ðƒCÿD À<sm¹'ÿ`P¸ðÁCÿÀƒøu×H‹ H‹×H…ÉtAffff„H‹AH;°t H‹ÑH‹ H…ÉuèëH…ÒtH‹H‰H‹H‰H‰ H‹H‹xðƒCÿH‹\$8H‹t$@H‹ÇHƒÄ _ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌHƒì(H‹ Å`H…ÉtºèfñÿÿHÇ«`HƒÄ(ÃÌÌÌÌÌÌ@UVATHì€E3ä@2ö@2íA‹ÄE…ÉtE9 t ÿÀIƒÀA;ÁrðA;Áu¸ÀHÄ€A\^]ɹX²H‰œ$ ètðÿÿH‹ØH…Àu ¸šÀéäA¹cH‰¼$¨H‹¼$ÀEA­H‹ÐH‹ÏD‰d$ ÿÇNLÐH‹ÓH‹ÏÇC4êD‰c0ÆC>?H‰{L‰£¨ƃ¸ÿcNL‹„$ÈHT$@HŒ$¸Æƒ¥ÇC8ÜDˆcH‹ùÆøÇ ÆÀ¹ ¡H‰[Ç[[ÿìIH€è˜"¹ ¡ÿÕIH€èQHƒƇ¤t H‹ÏÿúI€¿¥t H‹OÿOIH‹ÏH‹\$0HƒÄ _é…÷ÿÿÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ@SHƒì H‹ÙÆAyH‹ H…Ét‹QÕèüêÿÿH‹KH…Ét‹QÕèäêÿÿH‹‹ÐH…Ét‹QÕèÉêÿÿ€{`t HKPÿ‰IHƒ{t H‹Kÿ¨HH‹KHH…Ét ºPè•êÿÿ€{zt H‹€ÿIHƒÄ [ÃÌÌÌÌÌÌÌÌÌÌÌÌH‹ÄSVHì˜H‰hH‹êL‰`3ÒA¸ØL‰hèH‹ñ3Ûè£,A½P²¹à‰^ûýtV¸ÀH‹Œ$ H3Ìè¬#Lœ$0I‹[0I‹k8I‹sHI‹ãA_A^A]A\_ÃAƒýrÇEÇEÇE ¿A;ýv A‰>¸Àë D‹ÇI‹ÔH‹ÍA‰?è+23Àë‹;,-w,w,©,¶,ƒ,¶,©,¶,©, ,ü+Y,,,©,-L,f,,.,¿-ÌÌÌÌÌÌÌÌ@VATHƒì(M‹àH‹ñú‡Êútꄃƒêt%ƒú …ÐH‹D$h3ɉH‹D$`‹Ñ‰‹ÁHƒÄ(A\^ÃAƒùsH‹D$hºÀÇ‹ÂHƒÄ(A\^ÃA‹=êw …Àt‰A4H‹D$`3ÉÇ‹Á‹ÑHƒÄ(A\^úÀ‹ÂHƒÄ(A\^ÃH‹D$hºÀÇAƒù‚ÂH‹D$`3ÉÇ‹Á‹ÑHƒÄ(A\^Ãú„Âúýt3úýv úý†0ÿÿÿH‹D$h3ɺÀ‰H‹D$`‰‹ÂHƒÄ(A\^ÃA‹‹Êƒét'ƒétƒétƒùtÆF>?ëÆF>3ëÆF>2ë ÆF>1ëÆF>0Aƒùs#H‹D$`3ɺÀ‰H‹D$hÇ‹ÂHƒÄ(A\^ÃúžÀ3ɈFH‹D$`‹ÑÇH‹D$h‰‹ÁHƒÄ(A\^ÃH‹D$`L‹D$hH‰l$PAÇD‰L‰l$ H¸«ªªªªªªªE‹éI÷åA‹ÁH‹êHÁíHLmHÉH+Át ºÀé‚AùÀvº ÀAÇÀëkHލH‰\$HH‰|$XÿÉ?HŽÀ3ÒA¸Àˆ†°è—#HŽÀM‹ÅI‹Ôèe/¶–°Hލ‰®¼ÿã?H‹|$XH‹\$H3É‹ÑH‹l$PL‹l$ ‹ÂHƒÄ(A\^ÃÌÌÌÌÌÌÌÌÌH‰\$H‰|$I‹Ù3ÒE3ÒM‹ÈE3Û¿ABƒø }E¶D ëE3ÀA¶ AƒÂIƒÃf¯ÇfAÀ·ÀÐAƒú |ÌMAA¹M‹Ñfffffff„A¶@ÿIƒÀfÁà·ÈA¶@þ3ÈÑIƒêuáLCfffff„A¶@ÿIƒÀfÁà·ÈA¶@þ3ÈÑIƒéuáƒÂZ‹ÂÁè…ÀtD·ÒЋÂÁè…ÀuòH‹\$H‹|$÷Òf‹ÂÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰l$H‰t$ ATHƒì L‹J&HB&L%œÍÿÿ3íH‹ÚH‹ñM;Œ$8uL‹HM;Œ$@u‹ÍëɃÙÿ…Ét/H‹I;”$HuH‹PI;”$Pu‹ÅëÀƒØÿ…Àt2ÀéX€{:uó€{6‡uí@8k7uçH‹S>I;”$HuH‹SFI;”$Pu‹ÅëÀƒØÿ…Àu¾HV²H‰|$0è–ÞÿÿH‹øH…À„ý¸Ý†LGLO&fÁÈHO6º f‰G ‹F‰·Ff‰G‹FL‰G·FPf‰G ¶CˆG·Cf‰G¶CÆG:ˆGÆGÿ¸ fÁÈf‰GI‹„$HI‰I‹„$PI‰@H‹CI‰H‹CƈI‰A3À@ˆo7f‰o8ÆG:`f‰G;ˆG=I‹„$HH‰G>I‹„$PÆGNH‰GFÆGO‹FL‰GP·FPf‰GTèUýÿÿA¸VfÁÈH‹×H‹Îf‰G8è\ºVH‹ÏèÞÿÿ°H‹|$0H‹\$8H‹l$@H‹t$HHƒÄ A\ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$WATAUHƒìPL‹ÊH‹ÙH‹z€z(ucL‹Ç3öE3ÒE3ÛH…ÿtCA‹@(ð…Àu¸ë$‹ÐA‹H,AH áÿ%ÿ„ÿÁè Áê ÂDÐAÿÃM‹M…Àu½E‰Y A‰qE‰AÆA(A‹qFò=ñÿ‡°ƒ» „Ÿ€{=„•VA¸TAP5HL$pÿ;…À…rH‹L$pH…É„d‹Æºð‰E3äH…ÿtrD;æsmöG tH‹Wë3ÒH‹ÏÿË;H‹ÐH‰”$ˆ‹G(F, D;îvH}/H‰&LÇLiéFL‹ÀA‹ÌH‹D$pHLèÒ*E‹åH‹?H‰|$@ë‰D;ætH9/H‰âKÇÐKsé€{|„ÇH‹D$pHPL@LH&ƒþ*uK¸fÁÈf9B u<€»Œt3HƒH‰D$(ÇD$ ÿÿÿÿD‹‹ˆD‹ƒ€H‹ËèQ„Àtké—þr^¸fÁÈf9B uOA€8EuIA€x uB¸CfÁÈfA9Au2H‹L$pHƒÁ.†æþÿÿ…À~‰D$(H‰L$ H‹Ëè0åÿÿ„Àt é6é1€{?„ǃþ‚H‹L$p·AfÁÈ·Ðêtiƒêt2ú×~uWƒþ6‚ðHQH‹Ëèeûÿÿ„À…ÜH‹D$p€ëoƒþ*…ÆHCLH‰D$(‹CH‰D$ D‹KDD‹C@HQH‹ËèSéƒþ"‚”H‹QH;SLu‹Q ;STuf‹Qf;SXu3ÀëÀƒØÿ…ÀukH‹D$p€H‹¨ÿ,9ˆƒ°3ÿH‰|$0@8{t"@8»øtH‹T$pH‹‹€è·ÚÿÿH‹øH‰D$0¶“°H‹¨ÿC9H;|$ptÿC,VE3ÀH‹L$pÿp8é¯ÿC$„3ÿH‰|$8H‰|$pH‹¨ÿŸ8ˆƒ°@8{t?@8»øt6H‹ƒ€9xt*H‹‹ˆ9ytèeÚÿÿH‹øH‰D$8H‹‹€èQÚÿÿH‰D$p¶“°H‹¨ÿ 8H…ÿtH‹T$pH…ÒtA°H‹Ïè.éiÿÿÿë3À븚Àë 3Àë¸ÀH‹\$xH‹´$€HƒÄPA]A\_ÃÌÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$ WATAUAVAWHìðH‹/HH3ÄH‰„$èH‹úH‰”$Ðè¤æÿÿH‹ØH‰„$ÈE3äA‹ôD‰¤$ÀL‹¯¸D‰g0L‰g8H…À„Ñ @8°À…Ä A¶M…É„¹ ƒé„Ô ƒé„£ƒé„ ƒù t¾À‰w03ÒH‹Ïÿf7é{ A‹EüÿÝÿƒø$‡ÁHxÆÿÿ¶„pF‹Œ‚HFHÊÿáAƒ}rH‹O‹C‰·Cf‰AHÇG8é¡H+H‰ÁGǯG‰¾#À‰w0é|Aƒ} r*H‹GÇ H‹GÇ@ H‹GD‰`HÇG8 éKHÂ*H‰kGÇYG¢¾#À‰w0é&Aƒ}rH‹O‹C8‰HÇG8é H€*H‰)GÇG´¾#À‰w0éä¸a¹A@8sEÁˆ„$ظt¹T@8³øEÁˆ„$Ù¶C>ˆ„$Ú¸c¹C@8s<EÁˆ„$Û@ˆ´$ÜH‹‹PL‹ƒ€L‹‹ˆA‹UÇ„$°‹A ‰„$¨‹A‰„$ Ç„$˜@A‹@ ‰„$A‹@‰„$ˆÇ„$€A‹A ‰D$xA‹A‰D$p‹C(‰D$h‹C ‰D$`‹C,‰D$X‹C$‰D$P‹ƒô‰D$H‹ F‰D$@H‹ FH‰D$8H„$ØH‰D$0Hà)H‰D$(ÇD$ E3ÉE3ÀH‹OèTÔÿÿ‹ð‰G0A‹MH‰O8é”Aƒ} ‚õ@ˆs?HŒ$È‹C‰·Cf‰Aþ„$ÊH‹G‹‰K@H‹G‹P‰SDH‹G‹H‰KH‹Â#Á;Ât%H»(H‰dEÇRE¾ À‰w0é‹C‰CR·Cf‰CVHŒ$È‹‰CL·Af‰CPHŒ$È‹‰C`·Af‰Cd‹C‰CZ·Cf‰C^¸fÁÈf‰Cff‰CXH‹CZH‰Ch‹Cb‰Cp¸Ý†fÁÈf‰CtÆC?H‹ËèoHÇG8é”H (H‰´DÇ¢D.¾ À‰w0éoAƒ}‚Å@ˆs?HŒ$ЋC‰·Cf‰Aþ„$ÒH‹G‹‰K@H‹G‹H‰KDÇCHÿÿÿÿ‹C‰CR·Cf‰CVHŒ$Ћ‰CL·Af‰CPHŒ$Ћ‰C`·Af‰Cd‹C‰CZ·Cf‰C^¸fÁÈf‰Cff‰CXH‹CZH‰Ch‹Cb‰Cp¸Ý†fÁÈf‰CtÆC?H‹Ëèz HÇG8éŸH'H‰¿CÇ­CU¾ À‰w0ézAƒ}rH‹G¶H‹ËèÒ HÇG8éWHÎ&H‰wCÇeCg¾ À‰w0é2Aƒ}‚€@ˆs|@ˆ³ŒD‰£˜H‹G‹‰‹€H‹G‹H‰‹„H‹G‹H‰‹ˆH‹G‹H ‰‹”‹C‰ƒ·Cf‰ƒ‘€ƒÆC|ƃŒH‹Ëè‚ HÇG8é§H&H‰ÇBǵB¾ À‰w0é‚A}w6@8s|t0D‰£˜E‹EH‹˜H‹WèU!E‹]D‰›˜HÇG8ëBH¹%H‰bBÇPB©¾ À‰w0ë H—%H‰@BÇ.B²¾ À‰w03ÒH‹Ïÿc1éxH‹OH…Éu)H^%H‰BÇõA/ ¾ À‰w0L‰g8é,öA tH‹QëÇD$(D‰d$ E3É3ÒEAÿ1H‹ÐH‰WH…Òu)H%H‰ªAǘA9 ¾šÀ‰w0L‰g8éÏ@8su)HÒ$H‰{AÇiAA ¾À‰w0L‰g8é ¶C?„À…²A‹Mƒù‚¥H‰O8L‹SA‹EƒÀòHJ‰D$8‰D$0H‰L$(ÇD$ L‹ÊL‹ÂH‹ÓI‹ŠAÿ’€L‹[I‹‹Aÿ“˜A‹ôD‰¤$ÀD‰g0ë>H.$H‰×@ÇÅ@l ¾À‰´$ÀH‹¼$Љw0E3äL‰g8H‹œ$Èéâ„À„¶A‹Mƒù‚©LCZ¶$ð<`uLChH‰O8L‹SA‹E‰D$8‰D$0H‰T$(ÇD$ M‹ÈH‹ÓI‹ŠAÿ’€L‹[I‹‹Aÿ“˜A‹ôD‰¤$ÀD‰g0ë>Hm#H‰@Ç@¡ ¾À‰´$ÀH‹¼$Љw0E3äL‰g8H‹œ$Èë$H-#H‰Ö?ÇÄ?« L‰g8¾#À‰w0…öuÿC ëÿC(3ÒH‹Ïÿé.éþE2ÿA‹EH‰G8H‹OH…Éu4HÙ"H‰‚?Çp?Ͼ À‰w0L‰g83ÒH‹Ïÿ¡.é¶öA tH‹AëÇD$(D‰d$ E3É3ÒEAÿŒ.H‰GH…Àu4Ht"H‰?Ç ?Û¾šÀ‰w0L‰g83ÒH‹Ïÿ<.éQ@8su4H:"H‰ã>ÇÑ>å¾À‰w0L‰g83ÒH‹Ïÿ.éM‹ôH‹¨ÿµ-ˆƒ°@8st)@8³øt H‹‹€9qtH‹ƒˆ9puè{ÏÿÿL‹ð¶“°H‹¨ÿÌ-M…ötE3ÀI‹ÖH‹Ïèa‹ðé¤H‹¨ÿE-ˆƒ°@8std@8³øt[H‹‹ˆ‹QD‹AA;ÐuI‹Äë A;ÐrA+ÐH‰|ÑÿA‹A;A v‰A H‹ÇH;ÇuH$H‡Gh¾H‹‡¸€HA·¶“°H‹¨ÿ!-E„ÿ… Hù H‰¢=Ç= ¾À‰w0L‰g83ÒH‹ÏÿÁ,éÖ¸ðÁƒ¼ÿÀƒøt_„ðƒƒ¼ÿD À<s!¹'ÿ-,¸ðÁƒ¼ÿÀƒøuÑë&Hx H‰!=Ç= ¾À‰w0L‰g8ëYD‰£ H‹Ëè H‹€èŽ@8s=t)@8sà>Î;B?        ÌÌÌÌÌÌÌÌÌÌÌDˆD$H‰T$H‰L$SVWHƒì H‹òH‹Ù¿À‰|$XE3ÀI‹ÀH‡Ah‹ ºás ¸ºñ+ÈëA‹Àºñ…Éxc9K8|^LcÉL‰K8A‹øD‰D$XD‰C0H˜HTM‹ÁH‹KèFëYH½H‰f:ÇT:] ¿ÀH‹\$@‰{0E3ÀL‰C8H‹t$HA‹øë#L‰C8ÇC0€H|H‰%:Ç:N ‹ºòƒÂE3ÀH‹Îÿ¶(ë H‹\$@‹|$X…ÿu¶T$PH‹Ëÿ))ë 3ÒH‹Ëÿ)‹ÇHƒÄ _^[ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ@SHƒì H‹Úè²×ÿÿH…ÀtHˆ€A°H‹ÓHƒÄ [é&3ÉA°H‹ÓHƒÄ [éÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ@SHƒì H‰l$0H‰t$8H‹ÚH‰|$@H‹ñA¶èH…É„’HƒÁ(L‰d$HÿA(H‹VE3ÒˆF0D‹ZD‹ A‹ÉE…ÛtG‹ÁAÿËL‹DÂI;ØuAÿÂÿJëA‹ÁAÿÁL‰D‹BD;ÈrD+È‹BÿÁ;Èr+ÈE…ÛuÃE…ÒtH‹Ãë3À¶V0H;ÃHN(@”Çÿ*(L‹d$H@„ÿtë@·3ÀH‡ChÇC0 ÀHÇC8H‹t$8@„íH‹l$0t ¶KEÿ¥'@„ÿH‹|$@t 3ÒH‹Ëÿ°'HƒÄ [ÃÌÌÌÌÌÌÌÌÌÌH‰\$H‰l$H‰t$WHƒì H‹ù3í€HO(ÿ>'H‹_ˆG0‹S…ÒuH‹Ýë'D‹‹KA@‰;Ár+Á‰Bÿ‰C;C v‰C J‹\öW0HO(ÿV'H…ÛtH‹Å3ÒH‹ËH‡ChÇC0 ÀH‰k8ÿ 'ëŠHO(ÿÈ&H‹ˆG0‹Q…ÒuH‹Ýë*D‹ D‹AAA‰A;ÀrA+À‰Bÿ‰A;A v‰A J‹\ɶW0HO(ÿÞ&H…Ût‹H‹ËºòƒÂèðÇÿÿë”HÀÿY&H‹Ðˆ‡È‹Q…ÒuH‹Ýë*D‹ D‹AAA‰A;ÀrA+À‰Bÿ‰A;A v‰A J‹\ɶ—ÈHÀÿb&H…Ût‹E3ÀH‹ËƒÂÿ”%ë„H‹\$0H‹l$8H‹t$@HƒÄ _ÃÌÌÌÌÌÌÌÌÌÌÌÌÌH‰\$WHƒì ¶úH‹Ù8Q=t2€y<u,H‹IE3ÉE3À„Òº @uº @ÿ_%H‹Kÿ]%@ˆ{=H‹\$0HƒÄ _ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌ€y?t/€y|t)‹ˆ#AH;ADu‹ALÆŒ‰·APf‰‘óÃÌÌÌÌÌÌÌÌÌH‰\$H‰l$VWAUAVAWHƒì ½E‹èH‹ÚfÁÍL‹ùf9j …›D‹Z3ÀD;YufD‹Z fD;Yu‹ÈëɃÙÿ…É…rD‹BE;GufD‹BfE;Gu‹ÈëɃÙÿ…É…KD‹E;Gvu fD‹BfE;GztÀƒØÿ…À…)¿fÁÏf9z…f9z… €z…¾fÁÎf9r…ï€z…åD9j…Û‹J&‹Á#D$pA;Á…ÉA;Í„À²¹*L‰d$PèÅÿÿL‹àH…À„šf‰h f‰xf‰pÆ@Æ@¹fÁÉA¸*I‹Ôf‰HH‹L$x‹A‰D$·AfA‰D$ A‹GA‰$A·GfA‰D$‹A‰D$·AI‹ÏfA‰D$A‹GA‰D$ A·GfA‰D$$‹C&E‰l$&A‰D$è9º*I‹ÌèìÄÿÿL‹d$P°ë2ÀH‹\$XH‹l$`HƒÄ A_A^A]_^ÃÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$WHƒì A‹øH‹òH‹ÙHL$HWA¸TAPIÿ|"…À…¶H‹D$HL‹ÇH‹Ö‰8H‹L$HHƒÁè±H‹@ÿÜ"H‹‹PH‹|$HˆƒH‹QD‹AA;Ðu3ÿëA;ÐrA+ÐH‰|ÑÿA‹A;A v‰A ¶“HH‹@ÿé"H…ÿt#H‹E3ÀH‹Óÿ¹"H‹\$0H‹t$8HƒÄ _ÃH‹L$HE3À‹ƒÂÿö!H‹\$0H‹t$8HƒÄ _ÃÌÌÌÌÌÌH‰\$H‰t$WHƒì I‹øH@ÿ"H‹Pˆ‡H‹Q…Òu3Ûë*D‹ D‹AAA‰A;ÀrA+À‰Bÿ‰A;A v‰A J‹\ɶ—HH@ÿ#"H…Ût%D‹HSH‹Ïè7‹E3ÀƒÂH‹ËÿF!ésÿÿÿH‹\$0H‹t$8HƒÄ _ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ@SHƒì@H‹ÙL‹QA@òLB‰D$8‰D$0L‰D$(ÇD$ L‹ÊL‹ÂH‹ÑI‹ŠAÿ’€L‹[I‹‹Aÿ“˜ëHdH‰ 2Çû1´ HƒÄ@[ÃÌÌÌÌÌÌÌÌÌÌÌÌÌ3ÀÆA?3Ò‰Q@‰QD‰QHH‰AL‰ATf‰AXH‰AZ‰Abf‰AfH‰Ah‰Apf‰AtˆA|ˆŒ‰‘˜‰‘€‰‘„‰‘ˆ‰‘”ˆœ‰‘ ‰f‰‘ÃÌÌÌÌÌÌÌÌÌÌÌÌÌL‹ÜI‰[WHì 3À3ÿH‹ÙI‰{I‰C˜I‰C I‰C¨I‰C°I‰C¸I‰CÀI‰CÈI‰CÐI‰CØI‰CàI‰CèI‰CˆI‰C8A`uÇ 1è éÍHL$@ºÿ …ÀtÇè0ð éªHCPLL$0LD$hHŒ$°º‰|$(H‰D$xÇD$h0H‰|$pÇ„$€H‰¼$ˆH‰¼$‰|$ ÿ½…Àt Ç0 ëDH‹Œ$°LD$@ºÿ¥…Àt ÇW0 ëH‹Œ$°ÿ—…ÀtÇ90 HŠH‰30H‹œ$¸HÄ _ÃÌÌÌÌÌÌÌÌff„H; y/uHÁÁf÷ÁÿÿuÂHÁÉéÌÌÌÌÌÌÌÌHƒì8L‹ U/L‹F/Hƒd$ H‹Ñ¹÷ÿÂÌÌÌÌÌÌÌÌÌÌH‹ÄH‰XH‰hH‰pH‰x ATHƒì L‹d$PI‹éH‹úH‹ñH…Òtºd$X sN H‹ÂL‰MI+ÀI‰$Aƺd$X s6¶\$XL‹Â‹ÓèG…Ûu H‰uI‰<$ëH…ÿt,HD>ÿH‰EIÇ$ÆH…ÿtºd$X s H‰uI‰<$ÆH‹\$0H‹l$8H‹t$@H‹|$H3ÀHƒÄ A\ÃÌÌÌÌÌÌÌHƒì(A‹ÀHƒúvLBÿHÿÁ¶ÐèÈ3ÀHƒÄ(ÃÌÌÌÌÌÌÌÌÌH‰\$H‰l$H‰t$WHƒì I‹ÁL‹L$PHZÿI‹øH‹ÓL‹ÀH‹é3öèY…ÀxH˜H;Ãw u@ˆ4+ëH‹Øë @ˆ4+¾€H…ÿtH‰H‹\$0H‹l$8‹ÆH‹t$@HƒÄ _ÃÌÌÌÌÌÌÌÌÌ3ÀH;Ðt L9r¸ ÀÃAºásH9uLÇL‰H;ÐtH‰ÃÌÌÌÌÌÌÌ3ÀAºás H;Èu H;Ðu ëH;ÐtI;Ðv¸ ÀÃÌÌÌÌÌÌÌH‰\$WHƒì`M‹ÑI‹ÀH‹ùM…ÀuHƒd$ E3ÉE3À3Ò3Éè× ƒÈÿëiH…ÒtH…ÉtÜL‹Œ$¹ÿÿÿM‹ÂH;ÑÇD$HBH‰|$@GÑHL$0H‰|$0‰T$8H‹Ðè‹ØH…ÿtƒl$8x H‹D$0Æë HT$03Éè/‹ÃH‹\$pHƒÄ`_ÃÌÌÌÌÌÌHƒì8L‰L$ E3ÉèCÿÿÿHƒÄ8ÃÌÌÌÌÌÌÌÌÌÌÌÌff„H‹ÁIƒørS¶ÒI¹I¯ÑIƒø@rH÷ÙƒátL+ÁH‰HÈM‹ÈIƒà?IÁéu9M‹ÈIƒàIÁétfffH‰HƒÁIÿÉuôM…Àt ˆHÿÁIÿÈuöÂffffffIùs0H‰H‰QH‰QHƒÁ@H‰QØH‰QàIÿÉH‰QèH‰QðH‰QøuØë”fDHÃHÃQHÃQHƒÁ@HÃQØHÃQàIÿÉHÃQèHÃQðHÃQøuÐð€ $éTÿÿÿÌÌÌÌÌ̃J ƒÈÿÃÌÌÌÌÌÌÌÌ@SHƒì öB@I‹Øt HƒzuAÿë&ƒBÿx H‹ˆHÿ¶Áë¾Éèºÿÿÿƒøÿu ëÿHƒÄ [ÃÌÌÌÌÌÌÌÌÌ…Ò~LH‰\$H‰l$H‰t$WHƒì I‹ùI‹ð‹Ú@ŠéL‹ÇH‹Ö@ŠÍÿËè}ÿÿÿƒ?ÿt…ÛçH‹\$0H‹l$8H‹t$@HƒÄ _ÃÌÌÌÌÌÌÌH‰\$H‰l$H‰t$WHƒì Aö@@I‹ùI‹ð‹ÚH‹ét IƒxuAë6…Ò~2ŠML‹ÇH‹ÖÿËèÿÿÿHÿŃ?ÿuƒ=û**uL‹ÇH‹Ö±?èôþÿÿ…ÛÎH‹\$0H‹l$8H‹t$@HƒÄ _ÃÌÌÌÌÌÌÌ@SUVWATAUAWHì€H‹;*H3ÄH‰„$xE3ÀM‹éL‹úL‹ÙH‰L$XD‰D$`A‹ðE‹àD‰D$HE‹ÈD‰D$@E‹ÐD‰D$0D‰D$PD‰D$DI;ÈuL‰D$ 3Ò3É莃ÈÿéWI;ÐtåAŠ?A‹èD‰D$8D‰D$4A‹ÐA:ø„4H‹\$XIÿÇA;èH 'ŒGà@€ÿht3@€ÿlt@€ÿw…¥ºî éœA€?lu IÿǺî 銃Î邃Πë}AŠºî<6uA€4u IƒÇºîëa<3uA€2u IƒÇºöëL`)OuOuO  4 2p 2p`0>`GGGuGŒGŒG! .\0t!\0¿0ìs!  t 4 \0¿0ìs!ÔT  .\0tBÀ`1 d/T-4,&ðàÐÀp$_   t4!`d°t!dkœt!k„ˆt!dk„ˆt!tdkœt!4`d°t4 B>`-88 d42 p>`¿ÿÿ!X,u!4 X,u  ²ÐÀp`Pd42 p!pK„Lpu!Ä pK„Lpu T 4 2ðàÐ p `! H&Hœv!t H&Hœv!&HLHÐu!Ä &HLHÐu!t dT H&Hœv!@23v!t@23vd T42Àd42p!pXv!4pXvd T2 pd42 p!,°t!4,°t20, d'4&ðàÐ À pœcI@«@«@AlAlAé!C4w!Cê w!tCê w!dC4w4’ ÐÀP!°'¼'èw!İ'¼'èw!Ôİ'¼'èw!¼'£(Ìw!£( )´w!t£( )´w!ôä¼'£(Ìw!Ô ÄT°'¼'èw  `0!6#S#x!Ô6#S#x!ôät4Ð !˜x!!D!„x!D!"px!((ôäD!"px!t!D!„x!4Ð !˜x  òÀ`P!°Üx!t °Üx!t °ÜxT 4 RÐ À ` d4’Ð À p>`!5¿7y8Õ7y8y8! P œv!td P œv!td P œv2¢ß-™+Í] ÒfÔÿÿpq`qu˜s˜.ÿÿþ€X,uXŒuŒ˜u àt =ÀtÐò8t,°t,ÀˆvÀÅxvÐV¸t`d°tdkœtk„ˆt„ÆttÆdtDTtD\Dtpv8t€ÿ8tC4wCê wê w•üv•§ìv°Üx(Èx(<¤x<e´xel¤x€`hvpXvvDvv‰4v $v  Ê ÐrÐ !˜x!D!„xD!"px"#Xx#"#Hx"#6#8x6#S#xS#Ò$xÒ$8&ôw@&ë&ts'¤'œv°'¼'èw¼'£(Ìw£( )´w )Ö* wÖ*æ*wæ*ø*€wø*+hw+)+Tw)+=+Dw`+˜.t .\0t\0¿0ìs¿0#1Ôs#1-1Äs-171´s@1.28t@23v34üu4.4ìu@4¤8ðx°8•F¤v F¾G€sÐG Hœv H&Hœv&HLHÐuLHØH¼uØHI¬uII˜uI&Iˆu0IÃJsÐJ"KtspK„Lpu„L=M\u=MVMLu`MZN>>0!0 +»ÂxÒñº­ZJ°7„ºbSø… ‚º0‚;0‚#  a M´'0  *†H†÷ 01 0 UUS10U Washington10URedmond10U Microsoft Corporation1)0'U Microsoft Code Verification Root0 110415194533Z 210415195533Z0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0‚"0  *†H†÷ ‚0‚ ‚ÆÌåsæûÔ»å--2¦ßå?ÉÍ%I¶q*ÃÕ”4g¢ °_i¦@±Ä·²Ð˜¤©AY:ÓÜ”Ö<Ût8¤JÌM%‚÷J¥S8îóImq‘~c¶«¦_䄸ObQ¾øÅìÛ8’ãå‘ Ä(AUûËZ‰~qè5¿Mr =¾:8P[w1³Ç$Eš§¬mZ·ºëQ ˜AA"Nea‡AP¦y\‰ÞJWÕ.æ]S,~˜Í¤hsÐ4\¡qÓZ|UÛ^dá7‡0Vå´)€ñy9ˆ¢|'f·ˆ·xòÊ ¨8« d¿f]•„Á¡%‡]P ÌA»n Q8¸KË£Ë0È0U  00U 0 U†0Uÿ0ÿ0U±>Ãiø¿GÔ˜&ïcd+Ã0U#0€bû ![CnÚ TPkõÒ–qñž0UUN0L0J H F†Dhttp://crl.microsoft.com/pki/crl/products/MicrosoftCodeVerifRoot.crl0  *†H†÷ ‚ ŒÁYíoœk-ÁJ>uELAP½€êÙ°’‹*?SžV9jŠc¶x$yõ}¸¹G¡ –Âö˽¢fŸá¬Òy ý<ܬ p¯?ìx~ÔëK`&Ùsa‘!í°hcà—«o íÙŸÒÚ'<³äVùÑÔq½B|¦‰ÜÍÕ½•¢«ñ“}è¬1)¨]fpAüuÉÕ³9*Ð…P‹¬‘ÊÄ“Ëq¥¤”oX ún Ä1µ…~ùÒ=Ê[…l †ì" ¥t4O(¼•J«¶˜°] ¤wv~ï§Ž]„ö$ËÑm¦Ã¡œÂu€ÿ2ýæÏC:‚÷Îár*›b·_í•9\/”mH·_3/»Ü-s4‰B ‹yù£úïú¡ßà²Á•ë\ —;5>ˆMÛl¿$‰È½ØŸ{9:$ ÕßÑóJ—ö¦oz°©³¬9‘Óa·dñ>W8¯ÎzÒµõ®Ü9™Õ¶<—í¦ËÇ}k*L”æLTýÍ ìÎhœ‡Xéa`¾ëÉÕ}Ÿéx½¬!u©nàŒj*kœãçe¼¼-}:vÛãÅ,0‚¿0‚§ Wî]pë› ±R rœ 0  *†H†÷ 0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0 110210120000Z 260210120000Z0s1 0 UUS10U  DigiCert Inc10U www.digicert.com1200U)DigiCert High Assurance Code Signing CA-10‚"0  *†H†÷ ‚0‚ ‚Åù#æ”'Ä€¤€2_@£opÀå6qq:u¤ª’”‰^¬#qËNg}A?ªãK·{¾Á¨8i/:$éwYÇfC &‚‰@ò,êçLç|¸ÿˆ O&7ï:¤ú"lˆÉJaò®^o¼Ñy›Y`åî)µ*¤ÎñƒOis( û"“" L1òÓ+Ø„C¯-îP«×0x<¥#g‘£‚T0‚P0Uÿ0U% 0 +0‚ÃU ‚º0‚¶0‚²`†H†ýl0‚¤0:+.http://www.digicert.com/ssl-cps-repository.htm0‚d+0‚V‚RAny use of this Certificate constitutes acceptance of the DigiCert EV CPS and the Relying Party Agreement which limit liability and are incorporated herein by reference.0Uÿ0ÿ0+s0q0$+0†http://ocsp.digicert.com0I+0†=http://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt0U‡0„0@ > <†:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl0@ > <†:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl0U—Hëk¹²X#Ì”.ñÆeÒdŽ0U#0€±>Ãiø¿GÔ˜&ïcd+Ã0  *†H†÷ ‚‚é…¯§L¿¯Î=²ê`±hÞgÂÒË&àÃ/›µkS…ö›à5ÿúiƒª´t2<.L(› ­ ùó„“Ë`@Véw/i²ƒ™U«G$–ËK°´—¿Ä¥™þŽìP^W—ËG¹4Ùü:¢ÿP) bîÞ–:o Â…oüä2{Ó„®i` F&œèðÿÿ†ÙÈ :fç6Oè±–’.N¾ §3®¼nOñ~´FdùY"!dKâz缉žBOÀ¶uêF²¥T/Œ“Í64j(WÌ”?é|È~CÚù—¡YGÚªàm8]5+Å"†ËʼzM=&F1‚!0‚0‡0s1 0 UUS10U  DigiCert Inc10U www.digicert.com1200U)DigiCert High Assurance Code Signing CA-1;7’›£9Y c0 + p0 +‚7 100 *†H†÷  1  +‚70 +‚7 10  +‚70# *†H†÷  1™î.—­` ÙJxT³¸æb·œ×}0  *†H†÷ ‚©á»¯ …°8Û©]>>0!0 +‚0%ð+5[7ß}vW°ò´ÓXH‘¥0b +‚7 1T0RL{DE351A42-8E59-11D0-8C47-00C04FC295EE}0‚»RBBC2789018D2F1BAAD5A4AB0371784BA6253F8851‚c0: +‚7 1,0*Filetap0901.sys0V +‚7 1H0F OSAttr02:5.1,2:5.2,2:6.0,2:6.10b +‚7 1T0RL{C689AAB8-8E78-11D0-8C47-00C04FC295EE}0i +‚71[0Y04 +‚70&   ¢€<<<Obsolete>>>0!0 +»ÂxÒñº­ZJ°7„ºbSø… Ý0Ú0¡ +‚7 ’0OS€XPX64,Server2003X64,VistaX64,Server2008X64,7X64,Server2008R2X6404 +‚7 &0$ HWID1tap0901 ‚º0‚;0‚#  a M´'0  *†H†÷ 01 0 UUS10U Washington10URedmond10U Microsoft Corporation1)0'U Microsoft Code Verification Root0 110415194533Z 210415195533Z0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0‚"0  *†H†÷ ‚0‚ ‚ÆÌåsæûÔ»å--2¦ßå?ÉÍ%I¶q*ÃÕ”4g¢ °_i¦@±Ä·²Ð˜¤©AY:ÓÜ”Ö<Ût8¤JÌM%‚÷J¥S8îóImq‘~c¶«¦_䄸ObQ¾øÅìÛ8’ãå‘ Ä(AUûËZ‰~qè5¿Mr =¾:8P[w1³Ç$Eš§¬mZ·ºëQ ˜AA"Nea‡AP¦y\‰ÞJWÕ.æ]S,~˜Í¤hsÐ4\¡qÓZ|UÛ^dá7‡0Vå´)€ñy9ˆ¢|'f·ˆ·xòÊ ¨8« d¿f]•„Á¡%‡]P ÌA»n Q8¸KË£Ë0È0U  00U 0 U†0Uÿ0ÿ0U±>Ãiø¿GÔ˜&ïcd+Ã0U#0€bû ![CnÚ TPkõÒ–qñž0UUN0L0J H F†Dhttp://crl.microsoft.com/pki/crl/products/MicrosoftCodeVerifRoot.crl0  *†H†÷ ‚ ŒÁYíoœk-ÁJ>uELAP½€êÙ°’‹*?SžV9jŠc¶x$yõ}¸¹G¡ –Âö˽¢fŸá¬Òy ý<ܬ p¯?ìx~ÔëK`&Ùsa‘!í°hcà—«o íÙŸÒÚ'<³äVùÑÔq½B|¦‰ÜÍÕ½•¢«ñ“}è¬1)¨]fpAüuÉÕ³9*Ð…P‹¬‘ÊÄ“Ëq¥¤”oX ún Ä1µ…~ùÒ=Ê[…l †ì" ¥t4O(¼•J«¶˜°] ¤wv~ï§Ž]„ö$ËÑm¦Ã¡œÂu€ÿ2ýæÏC:‚÷Îár*›b·_í•9\/”mH·_3/»Ü-s4‰B ‹yù£úïú¡ßà²Á•ë\ —;5>ˆMÛl¿$‰È½ØŸ{9:$ ÕßÑóJ—ö¦oz°©³¬9‘Óa·dñ>W8¯ÎzÒµõ®Ü9™Õ¶<—í¦ËÇ}k*L”æLTýÍ ìÎhœ‡Xéa`¾ëÉÕ}Ÿéx½¬!u©nàŒj*kœãçe¼¼-}:vÛãÅ,0‚¿0‚§ Wî]pë› ±R rœ 0  *†H†÷ 0l1 0 UUS10U  DigiCert Inc10U www.digicert.com1+0)U"DigiCert High Assurance EV Root CA0 110210120000Z 260210120000Z0s1 0 UUS10U  DigiCert Inc10U www.digicert.com1200U)DigiCert High Assurance Code Signing CA-10‚"0  *†H†÷ ‚0‚ ‚Åù#æ”'Ä€¤€2_@£opÀå6qq:u¤ª’”‰^¬#qËNg}A?ªãK·{¾Á¨8i/:$éwYÇfC &‚‰@ò,êçLç|¸ÿˆ O&7ï:¤ú"lˆÉJaò®^o¼Ñy›Y`åî)µ*¤ÎñƒOis( û"“" L1òÓ+Ø„C¯-îP«×0x<¥#g‘£‚T0‚P0Uÿ0U% 0 +0‚ÃU ‚º0‚¶0‚²`†H†ýl0‚¤0:+.http://www.digicert.com/ssl-cps-repository.htm0‚d+0‚V‚RAny use of this Certificate constitutes acceptance of the DigiCert EV CPS and the Relying Party Agreement which limit liability and are incorporated herein by reference.0Uÿ0ÿ0+s0q0$+0†http://ocsp.digicert.com0I+0†=http://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt0U‡0„0@ > <†:http://crl3.digicert.com/DigiCertHighAssuranceEVRootCA.crl0@ > <†:http://crl4.digicert.com/DigiCertHighAssuranceEVRootCA.crl0U—Hëk¹²X#Ì”.ñÆeÒdŽ0U#0€±>Ãiø¿GÔ˜&ïcd+Ã0  *†H†÷ ‚‚é…¯§L¿¯Î=²ê`±hÞgÂÒË&àÃ/›µkS…ö›à5ÿúiƒª´t2<.L(› ­ ùó„“Ë`@Véw/i²ƒ™U«G$–ËK°´—¿Ä¥™þŽìP^W—ËG¹4Ùü:¢ÿP) bîÞ–:o Â…oüä2{Ó„®i` F&œèðÿÿ†ÙÈ :fç6Oè±–’.N¾ §3®¼nOñ~´FdùY"!dKâz缉žBOÀ¶uêF²¥T/Œ“Í64j(WÌ”?é|È~CÚù—¡YGÚªàm8]5+Å"†ËʼzM=&F1‚ 0‚0‡0s1 0 UUS10U  DigiCert Inc10U www.digicert.com1200U)DigiCert High Assurance Code Signing CA-1;7’›£9Y c0 + o0 +‚7 100 *†H†÷  1  +‚7 0 +‚7 10  +‚70# *†H†÷  1ÈuÁÌ1ó•T$®qž§uÜsÿ0  *†H†÷ ‚ô. ›? T¹¿‘Yr’‚¤nèêŸTKVõ.eAf(òM)-ð5ò ZJVwÔ¦sлcãâ¡X  û+®„¢î3÷™âJ„WzÂG.«5`|@[jxWV/x¸CèF¦ÄϦ)Aug’蕱 m q»šQX0ÂÄ:[G‚8pM0W9Ê‚¯.b¥ynhš¢I2ÏÒRG4‡;'úä #0ÜÜA`¸Ñèš«ǯdM 0º\¥±‘‘ˆ™®™y1°ón2nœ¾%ê:‘k‡!t½KÖ7‚È1‡}#ø^h×BB4lqL¬y®8ŠÓôÏúaž$’LXÄk‚ùšºFŠ1̰°žÏD©ÊÙ}/š4Ík'˜ÓËÝóGŽÛCigi– “ý†e/¿ÎÒå s`\Ua#¨B~4«JûÍ{,ûå ]úi<#U3 Ñé4«pÃ¥Òæ ÙnµZµV§ù`zsãüìü¬ÑøøÞ’WS(þîcœrŒqºÝõ£îm­ƒ)O¨Cûë¨;Ã,1‰ÙšSFupRïÀË%g(DŽYÍó³W%3¨Ä™âèCÖ•G‚Ö/4Ap<3êç þÅÊ)æqLLϯ¿–}!È÷ŒHU]ì€äÆ(- Lþ.ºNßžXöÇ´'C÷ÖõîÜ*ìö@±© ¹vÔÄ0Mì„Ë‚$ø‚H”nÐëzëo9ÛIÏŽ&Ä‡ÏæŽH«Š­‡­kMn†Ý®ØÖåSp_ì t<÷(\ût¸A4|–]çt8ÇízÏÁ½> 7uÞÄ÷7šD^±xîÍip¡Ö¶cFF4 Ÿb÷ö4¸’õÉô1Ãáç§àÞ§µë{½IßqícÚ]Ÿ÷»÷R>‘kå`Œ¡ìô£­|N-í {ý—…©|ˆ}(¥ Âùº/žJGäÊ‹®Ê‡ê”e8ð=ׯJv,œÐ‹‹T8Säîº,/ÊâÝ®ˆ6ÇQrNt>õ ¹âL¯K–ó§ÄÁ~7ÌiÈ7KºÌR3Â3™n_r™>š´âÑ/ðçüì7PKý[ŒA6ÀIcùæ tap-win32-source-2.1/constants.h­V]“Ò0}ß™ýwÆ—EaùXÁq©¥ëV¡Ô~¬®/LhSMLR½7uÕí -½çÜsϽIÚ}x~'ì¼câjÐÝßC§|¢JP¹bkªÀHX)¹f9…5S¦& Y5¿»rºf…¢™aRÎ̤̑˾Dðw %ÓIäÞ LèS4‡ÅLIÁõCo'q/ƾ“Š!×›K¤ãZŠŸÙ´¬&oHñÑ•«­bËÒÀ…Û‚A¯7è zýÌVT܆$4+…ärɨnƒ/²ËöŽŒˆÜâå”hÔT‹œªFÖ«p(F[¸Ð”‚r¹iý$Åú¶T¤²4…Â(- ³!Š>ƒ­¬!#Ùs¦b‹Ú Zc“v¥‚Jæ¬Ø6LößcjCU¥A;A ¯¨  [Ö Î2˜ ïBÓ£¼}-¨ÅèòhîµUïá“Ä$ÄvëEµæØ«†¥”+Š7ÄXÆ9Zµ¦EÍ÷>b8¼ó“›Yš€ÜÁ;'Šœ ¹{†á¦”ø–®éŽŒU+Î)"ìÌ;Ž©¹7r^ú?¹´èÚO/ŽázáȆN”øn:q"Ó(œÅÞ%@L©¥m(þdVÑ8Ž&äÔÆOçóû¤Q$Ï¡$kŠýÊ([£DÖß;±÷ŸK±lêÅð£§Íì4ã8î³ðÎ^¡µ¯sLr4,ûm—ZÏ€ ¤iÃF1ƒ,ò]ýa´‡Oq쫦 9ÉhâÚR\]õÚðRjcç@oÐï÷;ý«Þ€4v,¸{~v~Öí>ÿ—åß\¡’y™fÞîgyµ3VSc˜Xêÿ'ãüìAN &ÐŽh6NÝd'6âðˆûã|ìÝú®‡?±ùaâÏ‚S Æ~<Ÿ:¯gÑüÖ‹bŒ€á}~pÑûg?Ç»í1“B\9ÿjÎii^rãE—Ìou‘~œž8€¶NÉàT,MiWzUsÃ2¢q,ó\Q­ãŠíêm˜ÒØƒÄ aÊ«ê 0âÃäØh8¼`~ùrD1ûbÞ¦^ê}7mô1öt†Î » +½Âå ŸkZS°Ý:Âý(<Áî3B¸Í¢®Ta͈²UAeçsWî÷ªÙQì™&«CšSîàµçžJ;poܰëD!êkd2ñ‘6Ÿ;?¯(Ü듉7÷pÝ8ÁÁRÒ Œ,ñÈ.q»âm &»<|qàüPKý[ŒA;¬©¾d<tap-win32-source-2.1/dhcp.c½iSã6ô3;³ÿA»¶1°=)»H€L!qs´³mw<ÆVˆ‹c»>`éõÛûžK¶âv;Í´%‘Þ­§wHêþöógd›i×Þý!ˆŽ÷Å·Ï_‘Ý]Ò%w4hHü4¸§)Éc’¤ñ}àSr¤yá†$wF¢éãÓûÀ£d^D^Ä‘ù#‰#<üø!Ûd)Ã"Ȉí7#A”%AJ}róHò%g»ÏEÂàDÏ]@ëÛ= fqT§–ÅE ÌQøy'ip»ÈIëÌ"‡Îáîaç CF ¾·‡dJ½E‡ñm@³6DÞ^›s#ñSR7™ŠÈ§)ë¾" L†b’VF)¹¡aü`ÕDA»Ý¦îÉÌS€Êâyþà¦ô˜<ÆñܨûA–§ÁM‘ƒ´92ÝS²Œý`þÈ(á¨bÓt™‘xÎåÎÈh Kb7aà‘+°{”Q%žÐdA€l¡Œ{ŽM¸Dð+&.®Ö%”¬>¬£²ˆ _Üå|ÂLAŠŒÎ‹PØÀɃéåh6%Ýá[òCw<î§o<_Ä0Kï)',“0Ú QêFè3sNãº?>»¤îéàj0}KÀDçƒé°?™óÑ\Öƒ³ÙUwLìÙØMú{„L(E²ŒÄ:cÍ™ÅÁ>ÍÝ Ôýó-¬SB†>Y¸÷ÖË£Á=ˆèëé•öãè–é àʦÌwy‚»ì·ƒá˜Ö ˜”ŒJi~\%ë˜sÅy›<¤AT⵫ZqíϾ·_&ÀÒ]¶É¤@GG69³Á¯»„tvŽ:_2›tyÿù³çÏö÷Oš>8 {Îge4'½Ë3›Ä Ê­ÅDÂß½çÏ&4G¬Q{¿\g·d{Ù&÷qà“mÐÇmÖȂۈùaNBYÏŸýò¡QZ/–»¯cØsÜ“0Ÿßù>Ó  ‘‚ÿýæ„IéŒìé`4œ8§³óóþØ™ ~ìúÖïð/Gä|¶AüË>CX–k`wMÁ‡õev»'T%»6á²#™ã_“æ§äÌŸð÷O)6 3ZŠ¢©GNÈt<ë+Xøóç*Sv4[‚|mf¸ü1¡Òr8 èàbÃþÝCàÑšÁö[ žÍéKĨ}Ðm’¿Ñ ?,ë¸A’/›$i“ÙÕhxÁ¬T“êˤÂ94ä‰.È#Çæå/ ~°FG‡ÿB¥£ÃÿZ§¥Ëþþª ¼ Þ]V,Y5ao6¹§ÏŸ‰ãIè–Ÿ¦Ù¾)æmÂFä&uxA]HfÒœ yˆSÿàs”]Ø ¨BaÈ~ƒþä[ºw”|Nn‚œáfóèFa_@z{ˆ‰ëÿ¡ P¿TP2i%®wGsN S.û8±$6,!´& È7UÑÉ.9€aÜ­‡–,B\¿¨ýSðŽ|ó ùÒ"ŸÎûóóNÇ‚8ÀgvÞ‰Q‹ëÄtÝL¦¹¥lÁö²2G…ã(|ZK…™:G‡8„t¤2 ›ñ ‘B]ƒD˜bZôú5P±ó6Ì¥‚“UÁK!€?ý«5ÌK0-c‘Ҭіð-/Ò,ÀÕ"ágÊ_ ­ÃȰXsÀRS¤,õÐ8m˜öi–ãü¿ò¸­t7\ AÂsC¯Ýœ¥{d†ènVÈ®ð=©}éqÿÄáZü÷@±ÈÓ ÉפSuÅ•.(÷™õl’d´ðcÂ7º–·@³ç.Tð h`‹:œÙ!ˆX‚dÀe2ºRÙWMj¶ZrTUÓJµ5ZýCæ¨Àîl~Cöd«bVÒ8½8$Q±¼¡)Ú ÇqÙnóxŠ4|¹JªåfØöx49µS—îSò»£4a‘„sp³\†”j8Qëë‘å¿ +[rMa!a# H€òtt)3ÔÚÂ#Šé¢¬Id8Ê6££å™'Eò׫oJ®%Eb’Ò½ Ùc3`¯EŽc«’R["ÇUT:Ø—½±Å2ºbÈô;[ͱ𠖅ÿ4OŒÁV ??¥À E ;b„ÛÁªÔ¾Ä’AU§½ ÷Ðf > êë‡y²„ãÞ‚“ÁFmZf$D°¹.xùtÍq¦P‰‰DÅimû /Ñ+®!_ðZúIÀÄÊš-ÄÄlUÒÌŠ`$h“ ÚÂTˆª1¸„ê™3c؆‚Ô-«]ôVˆã‹þ§?ìYD}Àv~àGŸæÐ†yÀ&ÿÂ?)Ä8¾ ¢[VKìÍ]¤­ú“Ý’vïÂÙAʲÐxõzráLßÚ} PKQ\CÕ«1Ý_C4¯wl|:a‘ÉXJaá'2òÊÖÿ²?`K=÷ðݱ†Æ'Jl”\vqì¯2P½©#«>Šp/!*BhL%ñ•J˜J*/àÝWø‰ÞÒ¼¦¨2 Ë)0ȽTÅõïÝÈc}}Dß—Ìnÿ(å=®úÝáógÚÖi&·ÖÔMº¾›À—ƒÔ pâð„Býé¥sÙïöú°¡h¾Ð§0Âh胳-|1\ßÈZœ¾.`æ†%ÚûWeR.OZÀo÷5&'eäDlg`C¬ü„ <€Ñ“²Å¶qi˜óîÕ¤¯El^,]wÏÈRH#Äå(E€y§ÿݬ{E¸0Põ´• >:±žS"`… ˜{ݤ±ë{XÄ)ò–‡½ÜTMï59ZuA°2%qN%QôÏ?þ  áš8œ³t=k½6vœæ¢jÊJ¼8…sº\I ‹Ïyiëþ8µ'Ž µ ‹Ç xÕZ‡;cpOÈré¦>žº‰·”µfc,;úJ,P8.ØþTí=@w{½ñ¿b¶tso±¹çp¼Òhd'‡ØAßÍ›U\ÍeØi„>ë~â9úWY‰Ñ÷MrŒå•sÃ=†ÕÍ 8á‡Í˜XnÆÛýFÓ˜b4*Ó‚Ô©¿÷rÊ2 ‹ÒØ@¶1X¹ªÿ”°Ûªem^jZ0…g15UdjƨLÌuò'ãOt´ü7†|—d õ‚yà1wÞa¥ë½QUò‘“jv¿Å(ÌÅi ®?xÅTúã%U.ZPæ§ìüÑH ¼ ö˜“»+¢ R“[£”•o“J“LH„'ñµˆb»•<Å$Ï#FPJÓ-t,±¡ø×;Oí­WØ“¾²È¤Um °×:’%bgXcVFr$#%1(ìlPås7Óù~ͯsÏC9ø\*óg%}JÕ-):²q€1c±ƒ¤q©%®/pÿê” Z™6Hã@}™f=c°ÍédeÖ9ÖàXrªåª²NÿxYô¶¯S—qð,/Ú´TÕ…› @@‘Æ}ûêí±>µýÇAuå4Z&N¤'ªÁ÷è6"+Á÷Ê\F=aº·æ¨ˆ%ë”koD!æ åQ¢(¨¬q%d°Öà­âW\€'åjôPèK÷6ð„+„¤ÕyÿùÑ—‡Ÿ}~Äúá'“žJÂeT¯´ÉO„è§ ‘/N=6ÉŽÕ „ÃäÇéq}vl¬òËó™ä.לãEÅ=Fxý‡ÙIìž}«†”Õ›ó^ÿtvaÃÊËŸàUÅ;¢™çkrêòƨ|M>öŽ^¶Ù‘ßT&~þ)üëŽeÒRz‹Àmc7 cOÆrÒj³BMÏp€]swõGH©Ôa`kø×¢ÅÄ9¬Ý2¹ÚÕî^ã¸BgÂvôL"G‡:•Iü=ÜÛzíUûOQeVÙhÅåõ/“ã Þ€6Á{Þf) šôéàºß–ûSIÃÞ’89Ð`+.Ii¾t³»µt‡ýéuwò­®[ÄÑtJ#ÖÌ õ®OçÜËÅ«g¤yKÌ>Š*";Y‘°·ŽÀvàÚ`NÓŒàÈËî?+kÚ|s5;\¦ò0ª¾b/p]eË|~5ú»ve‘¦øŒ$ òÀ ¡©HåYõ°ï&Ä+ <:[x0=¸=Ö•)_æjùïòÃÉO€oyɇäaÄVð¿…/¾€Ä7)ÿUˆ ¸ø|Jú=ãiž,3Ðr¾7»¶ôÏ>Ðx)@^jkC'|ÊÀQ«“JŒóÙÕƒ¨øã˜Å jQ]€xÆ Ñ/ÐجoëQXixÊTÚgk%ø4±nxë°>žrù¸Ÿù"BªUs8 –ø.F¸W=`Z2Ön|—°Á‡¥ØK¸h)ôN¼ì“].T¸~á©—XÆÁ[³Ç,§K°2¢¢Õãð»Ý²ÅßÛ»tÉŸwǃ¹l}ƒŸö9ƒÑÙôÊ9 ϲÝÉwø´Œ¶|>"žx7$·¼š«nwÝ»žòðÊΗçøq%˜4æm9¼îƒ¼›RxÚ”åXH°GnðP'F¹òߎW?•óD›KÇ|¡µæñ«5ä„q7ÀG j8¸ÛµÃ?Ö#¿RýžªM¢<^°k¡Ý×¢[³0GýëFwédew‡˜ €éS ãÒ)†J¿ÐOcš1g¾À_BF·èVEö¦ÔÁ8ôUËBÐú/´Ð¨¬úo>‹bÖMǪkfitMÌš˜(Žvyóݬ?™–Å®’÷øâ„hp¦ú5ºnôXÒ’'X(Xo09ÃLEÄi– §ÖUér¢!ðB¤2§×-†:ÄáÛ›=TåM[5mHÖ¯å 5ð“ýEˆwW8RùýâÄ<Ç•/¶ØYÏ s^>§tà ‡\š 7®à¿x‡W§Ýž£ ê€2Îôr܇Û᫞4S¥9©Þ'H ð¦ªÓ§I5¯ä­¼üº¬*yªµÃý7žj‹¬ÞVè¯^=5/̰áÉIÍ™|_C°¼îO¹Ì?ò ”nggýj7ŸBbôN/ð+ÂÐ5§øtWlG¨EïªZ<Ë0œÁÎðø®ÚyPœë[ÿk>\ò~©Í½Îàü¥,T!€oj ‚æV|²‘Äìt`ó¢‹Y×9|ýqöp(—º,Ó´ÛIÖµë© ½:­wd÷5yiðõÿ9_<ž^Á•Ol‘¥Lz&h>+#^p"°àÃ…­áJOª~|Šðc3áÇu„³§gÍ„³•„Ÿ¸î]gœ…ƪ´¿¼¼­ñª9,£ŸtÞÜùò=¬..i(1a†¯¨”¯2ËN˜-ÌÝÚá2BV¨/]E|ºá쾉˜´ØÜÉÇ>Ò€ xq`"㨎‹¿KÔÒ—ùÞ$X& $Lè&Rxÿ°Šg¦yÅMcâhµÔ…†2p„sâ{U»èãkñê3“Û}ÈX"«’|eùâºHSŽ<ö39•rTãŠâx‚gªîÙR’nƒÊtjµÉ`³˜è¯Ö¸ [YÝf›¤äÔJ‚rR’…+ZHÃ#,ü0ÓVà ºä'þ÷]•;z°äÁÅŠ÷§ÛÖŠ§&Ÿ¢Îgÿcÿ¾:¯¦‡§åéé&¯L¹sHxíõj™fWÌ•©PÊ"Èè;s$ÎY`6þç@X÷¾S½ð4–NeHßäí'اóæÿË‚ò§Ÿ[ŠøúÊ,ô§ì› —×Ü߯î‰ý?}PKý[ŒAí'Jrtap-win32-source-2.1/dhcp.hXmÒ@þ¬‰ÿa…9^O‰šíI#”J‹æ4†”v¡Ûní¶‡hüïÎn[ xøÖ:yæugfïüìÞ]8°óñ{u;çůþxüøL’ˆà%ô†$2ˆvC=74I3'€Ô‰%Ä©Ç#7Ô%°Ê"7¥,ršnE€:<¶áM.mð)—!öÆá@#Ó„x°ÜBêꦖ›X#>¨NHëMá΢c4β•KP|²x›ÐµŸBmX‡N«ÕyÜiµ[0IôÎ4À&®±€­)á Ð#·ÙÈÁœÈò ˆÃѦ,òH"ÍzmŽáÂŒÔ8!°$ÛÔLq['N(`V rq¶J7NB°e¸N„èåiB—YŠÖ¦Bé9K d]m%’ îU§$ 9°Un‡1‡×$" ¦ÄÌ–uaŒq8Ù›Wø‚¶îïƒ{%,²r‹ð¡Gdë7Nìmõ0WÅg1ÁN*ìÜÐ ÀP@ÆÉ* Š8";¼×íÑtnƒb\Ã{e6S ûz€ì©Ïð+¹!9 ã€"6Z”8‘¨™UŽ1Ñfà )—úX·¯Ct¥Û†fYp5aÉšÊÌÖ‡ó±2s>3§–Ö°°âwÁZɈc<’:48¬ÏkÌG#|ç†`¾\BoÐD\,¬?g¢ˆÀ¢µôÙ÷1•µ#V4ÀrŸš×ºñC뙇Jve~‘¥úè "–6`“ÐQØo³Z)íÞ3,û0F•fฤV& ºÝV.OûDhuÚíöãv·õ`n)BøüÞÝ{wïlj³ˆ÷s­]¤óóÿþ1± „N´…¥ã:š3íí\³l,7›2ä∭0GHRHM³$Â4Ê›W‚"©Ê1ˆ¬Z²¢ñ0Bˆm1|’ˆ¸—P_2‚N'¨ðèa Ÿ#´‰¦tÏKçÍÿvÕ[—Šº8°m¦/ìÑL³FÓ± Ýÿ £t`â|¥aB”…K’ˆšZ€Å"ñÏ{J°-f±<\ÿ£cç‚^Ì-m¶°æ¦9Ö5u15m}jX‹ËùÕ• ë4èôúU™[¹*ùëH·çª 1KÒÂo¾s<Ä|9kò×9«äh:µMkaNg6ôŸчýâ†ŠÏØ>IÅ À㛹X·äÒ÷î¦Û˜ îB¾£)p`KYßí_èæøZDóÞ]<³Ø4gXƒ}”ÏÏJk.óž|¡t°côÄm¤< >C4×MxØ~/ Ýš,AK}±0¤u · H„X'Áðó:õK¸þCцÈb~èb5G)p’rq´[ ì"Û|úÈ!'&7œ5rñi<Åþ _©78HŠÃ†;rU]m€ë3N"„(t”ÂÖ³ Ý3Ä+‹<<_صIÙKDƒwÑI4gíD aä)¸Uà¬ùàÀ8—Š ŽÜÜw¢FÅsº’Ý*ª:¸­b<ÜâNôð÷<OpKx(6cŸ#¤€®‚ñ X!wVå^W¸“p$²O¬ë òÇvÿÓ`ïñ®`n—á‘’ý'(‚2E¯s‚Ò:ŸaKEJŽÙíÎE!µd,•´ëÞÐYSw°?4bqµ¾ö»^·ß…–è†%ŸqÁõ,/ÖòÀn;À[³G‹‘¦¨Ú HêˬëæHóPå[æÉ×¼yx¾‹o²™Sàåwˆ‘gçs9>žêŸvØWYœÏ"NבÜûR)7ÒEÏkŠ £¾ÂXwhòõ~‚¿ó¾yz޹ ã¢äÖkAþ‹‰„œ‹±f,.K«Åu\«è7‚Ó V„¤^¿•_„C°C ÿ>~™{u‚õj>KèÛô=úõ•"ê‚¡R¦ç¬¤rŒÔ-ÓwÚìj<}/5K¾2Îÿ¸t Þ<Ÿy·ôY RéQ¼×᮲0üî¯å²¯=ñe— KkðWüå+fãà ÷Xçìâ?ÁÄñþ¬Ûü²Øž ± æ›ÊˆIU2l.Õ…H«}mÊí§×=ÈÅxÍ.D+9’ÂûÍd3_Jõ„Ú˜`Ó ánèx?xn[b4 Ùlþ 4ÄͰºŠ@ýve¨ϥ…4ý- ¶òÝÓk ˜Ò â•}å»[|14{¢XoráÜž-±™bÏåŸOI5%8Ó í})xQ˜‘ü…è¥n¨¹lïY!ºÄcóGIÜñèæaî=©ÌMõùŸd*(V>­£š¡î7æ^Y¢¿+ÒI±”é_ôTU·†¢ý@»JŸŠÉ!µïè• tp4,9cÿ¤JW†oŠò©Ò ¥ ÷ñE ÎÓ*]7ð?ä¿P¼\¾?ßMuõÞ]5 c…š‹­-=œÀg8‚ñB|@~*&ñˆåD>˼ YBžáh®P÷³±ž·‚ÿ…ñPKü[ŒA³Õ ˆ¬ƒtap-win32-source-2.1/endian.h”MoÚ@†ï‘òFê"¾é‡ªœBˆUb,Û4â-ö¯ºìZ»k(ÿ¾³†„–ZNÞ™gÞ}gD÷æú n/l?s9t_Ÿ?B» ü@-Q@¦ù5X¥Vž!l¸¶`YY#Þûe¸á)B^ÉÔr%™àvJõÈÔÖt¨øUCÁ ¤ŠØ[f€KSr,w` „‘Ž÷b\àž­9±¾u'Œ’§4£*MÍk(GªÜi¾*,4FMôzƒö ×ïÁ¬Dù= Á´J¨GÓ_¦ÖÆdæê5 d†4U2C]Ëš„S 1ÆÉ@à Â…Ú6O¤8ßVš­&×”eTn·Lã-ìT)“Dϸ±š/+Kj­kÚUÖ*ãù®&¹Ûck‹zm@å{Á&(QÓHÂj)x Sò]<Ê;¼…´¸SÍ}pŠâ½":)jÂÜ´.<â¨5£YÕ”B•HÌ:[.Y•Á¼)žýäq6OÀ ðìE‘$‹[J·…¢(npãëRpb“"ͤۙ|ÏxG£G*òîü©Ÿ,€,zð“`Çð0‹heC/JüÑ|êEΣp;1¢ÃÖˆKfåµãdB†–qñû~.hN†DŠ ¶AšWŠ|C¤´XÿžÄÁ¡äª~/¥=­w§ä\кÏÂ…LÈÚTT5y+¨)oö»)5oç •mÁVsKuqª¬ö§¯´öë’Z†‚¥Ø‚¸rˆá°×‚;e¬Kòzƒ~¿ßî{_æ±çŠ»×W×Wxžaîþ@^hÉtü2î}/ Ýs‰ ­*Lãg"+æd ¶w;‹ñ–•tyL+¨Õ¤9šxMsV¾ »…ÂàÆ<~œEI“'°¿â§’ñé,˜œ)?F™qÚé_PKý[ŒAǑǩ9 Õ"tap-win32-source-2.1/error.c½kSÛFðs˜á?léZ`ƒ!i;­K:Âà‰±U[N“¦ŒGHg¬‰,y$™GSþ{wïN:½àK5©eïíûywôpo{ ö,ÝlýéoŽå·ŸÞB«:|aQÀ|p#ï–E„°ŠÂ[ÏepëEÉÚö!±WœÅ¦Çe·žÃ`¾œÄ Û÷’@nx qªÃ‹Á ‘÷ƒÄ+/b.\?@²`Ð훆PQ*C ={é!¯÷ÈÎàÌ-× çLñg7\=DÞÍ"FWƒãvû¸uÜ>jÃhÅ‚æ,æ,‚Ðo<7¡8MÁÌ\¢˜ÏìuZ.‹¸ZçæP™˜Ô8†FÌ\3?¼ÓJªßn"{IlæbÅá<¹³#Ö‡p Ž w׋“È»^'¨mBBÖ¡ëÍ8'‚*Ñ ‹–1„s¡Çp ç,`†Ä\_ûžô{3¥ž´u!„x¡œ{FM„Fø+D!6EëF(]]Œç²W ¿Ø éyçù>ºÖ1›¯}éGD‡?ûÖÅhj>üêã±>´>u=Y„¸Ên™`æ-W¾‡¼Q£È(gæ‚Ç¥1î^ ‘~Úô­O€.:ë[Cc2³ÑSÖÔÇV¿;èc0§cs41&Œ[Îâ[Κs£\–ØžŸÏÏO§•ô]XØ· ãå0ïU´ÁÁÄz:Òÿ~Üp{]ù”çg0÷|L÷‘ù©?ÜÞÚÞ:Œú½í­Ëng?Àšk¬ƒØ» xE&XlóØû'µeˆó‹ÂK†éý×ÒAM@$¢ i\°üu°ûmk/i€ôºï‡4ÿ¦PŠˆ„ÉyBé°äØ+Û¡þ"•«5…§mƒôÞÌ’Ô ¼âZ³"Ië¼ÜöªFf„þLÓ%õ1û5Œ¥’6© ¯_W£t"xWÎþ4fæ¸?´Êé%ÓÂ;—eŒÞýcڳ˩e|œé=Ý´ú eÔçKSi…dä J¯¯ø_š½dYÄ–¶xÁ ZEÛVŽšÖ+Á8£—EòŠ›AoþÜÚ378Т›¸“A‡ÖÄÒ­éâÄNÖjAÖ# Èä<Ä‹0 Ä¥)Ý®eT’ 0NüI¡2]gñGnnÜ륈ìCΔ&2ÁG2RÞ(Á_£J%Ðp:”@k<ÑÏŒÙp4ÃBvu«?¿¼>aôˆrR$•6•€d.™©ü€j/hÂA*À©N@¸v6™v»85b™3NŠ­Bƒ1mŠž UM*Ï‚QF&ÔÉR¬G| L Ø€ÌWÇ&öDæp)u¹\ä–½I²üXhòç,áÈ4'Ò¾…í¦©^õx‘78¢ó£ ‰p³jãÆí|ã d0ÞÕßÁ-RoFÄ´5×õ’ÎeâúKÄÿÜÈ3šÒÎ×vÑóÿþ …º±¬¼ YiiQ8Z¹Yd3×ƒßøàEš#ü£ˆp%Ç”çöWú¨Ìã¼jŸýþþU‡ãW'4×A _ñ #÷ÙCäæpÐc®à„–¨$'娈ȇ¸ª åÉï¼²µ®4CU6™–C*àÈp½ª‹Vf‘ä¡¶,…}Bâ3bŠ›úÒȲŸbNOŽ÷[uÄò~õ•ŠÔ¿ o™HýòxÎx7¹Ôý#”ÁéŠ&ñE±ò¨t(Ø–U\ºÎ74#ªÑ· !µ² £Wy— Ç1‹êw°Gûy±µ¤º‘}‡±G6¡Ñعü¤O&ÆØ‚9:r7>Üu±Ñ4S JU¼ïÙéú¦»`ÎãíûöY»}ªŸêÍÔé`4<Ÿ™ÖXã´µ í—@K;#3º´ÔàK½«÷zcXÚNjž2m÷þ×⿦ ¡n_5ùûH¾¯ò«o$ô­|ÿx¥Uô裔¾Éå{«™íºQªCm4¼M¿Ú%ì3’Ê(á¤ÿRõQiO¯#ñ:¯7RÉòáF(kFaò>+úšÍ!<à9 hp`±ñ;6žr<²F³iÏüU€³„ÜAØN§×êVqV‹Ûï^V‘¸û¼û\a»ln¯ý¤‚óûï¿§(…@öÖË•>6‹‡²UÄæÞ}:¹qyfêÝ÷†{v´ªIµ˜p Žœ¬A,«Fæ+’µÞ-g˜°³ ¿«Š*'';©z¸ìü]!™'íûÝöÛ,ß ’p§<ȼnŠ­ÂãR²hìºZ-¥ŠŽ‰ÊâØzX1­€YÅ™à1§*Ë|ž,ñ'¥q¬Š¼’Dôæ$rÊîU®)¦JKÎßL\‰OU~ß,Šï›}3^!$Æß¢ü¶dlåª)Ä8¼êJ+ûÁmWºa]Ì. ½gŒi‰Ë™v/ðKb}îgút`ɘ F£÷:\ãN±”LÛùÂ’ãÚrJw|)/våÊÕ Ý/ì#[+o©+ö!cÞu+ Å y¯¢iM>ºÕ[;¤€¢ ¸kÞä%Ú§ðÎF u)ƒqEéˆJ‘àêކФ†Màžá^ÈðU ‘v²Fyæ 0u ¡b¡Á¾bV¸ð üÍžÒj›«ÒdSB<+âõßHðê‚ÆÕQT}ó¢7NÇr„§RÂ…ý:÷äR|_Z‡TL’â¤P:3e` Oä¦+rFIŦL_ùÈÎý=¯Ñ»“L%5¸è(Cáj½ãsž6ü‹j›ÔK*Z§“QåPy¦n}RÕ¾yûVuºªêãÞ×6x]òо™GD†³s¬³ÿ†‡5#ÿ 1#ïíÛ²Åê ¾à›±ÀUYtªdׂŒ>[uvtÊ'j×s gøj¾ßíÆŸwÝ«\†ä·t+é'ô5•;ùõ]ƒOV›„Iê¡ðë×ÂÞßÄo-=™&ÑÇÅ(y•F¹p_"Þ<ظÓKc­t(ª‰¢ó›EbJZ\ Ç-Ê©(”ZùQÀñâÄÁ*&´g0Bíe.¯\ðçC?ì›Y8Ÿk@å1]ê“÷<Ú$$«MÁBA)Þ7#†xµpØ[»1B{qÄøýçB¥Á„­ÈW¸-×°Ö,³;3GcK£‹¤8ŽÃu~®9I!­r±”N«8Ô"SéWfuvï* Í~×»£²¬´É]¦_x[ Wò®Eromâ+ åßʼS 2¶r ,Åü&îâ_‰Ÿê^OMn~ƒ6}˜hM ~kšRÓÌŽRÖW¯¶p¹ìñÚ¢ÆgCaã³±×n¥¸ñ)ø&î dˆBÊlUôÊúÚ^í­xíâ®PP¾–ŸÛãžl\™*¥ÓÆÛTµ2àðh^{tÎŽZ|â#†WO͵´TCÁ=! TrëÅ ÍΖ"8‚¸É²ùªöºßã1<ü¿þPKü[ŒAŠñ~|.y tap-win32-source-2.1/error.h•UÛnÚ@}n¤üÃT}ˆ¡7U´8Ä*˘¶H•¬Å`U³ë®×PÔöß;»\’´µZÏΜ9{æ,Ô.ÎÏà tüËÏ\¼lÔ¶«7¯àòø†J` ‰âKT %dJ.y‚°äJ,Í2 ñØ“à’ÇÓBÄšKÁR®× PD®ò*ï8Ìy±$ìË‹<ã ˜¬AÏZžïn(nɘ6[pÂúX%¸4—â>Z. EÍ-(½¶d¶V|6×Pj•¡Q¯7.õ«: 2Ÿü>„Ï…LåŒc^OÄÕÊŒ‰ÄÔ+L‘åÄ© *K«ãwÈä†FJ9"L0•«ò=*F·™b 3U”•Ë©^1…MXËb&=á¹V|Rhb«MÓšT° Ÿ®-’‰ZkT‹ätã?‚ T4¿˜¤<†.é.r<ÐÛž…¸˜„|~÷Æ0nÑ›¤&ÌLë‰C¸&4+‹2—Ò‚iÃsÅÓ”¤€"Çi‘nu¤tøì…·ƒQN Ÿ púá¸Iéz.i—¸ã‹,å„MŒÆ3Ó FÏ Z·Tä\{]/Itã…}w8„›A@–õ ôZ£®€? üÁЭ  ¬…xJ¬©UœDHP3žûsLsʉdšÀœ-‘æ#_E1ëï“ØêŸJ1³ç¥ôƒ¦Ö;`ÊS²ûÀ{ýI§EBMöe/¿™R¹ | Bê ¬ׄ"Ÿœêk¿~G¶_dÔÒOYŒâåËz®e®MzϨ7®®®.¯^Öߌ†Ž)®ŸŸÕj—÷„¶{=êtÌhØþ(|0Ó¼HpÊBº‘ƒ T†¯çg?ÍÀ,ê²\»JIuC¶@øQtãuÝ(jž$u «_,&¨lZ×ëïÒ~Ûn¤Tûºc–z!õ²ˆ5ü4@…ÈùLXKkú4ObäÑÓ`Ì2ÓïšÝ‰çLÁ…Æ›ÄëÁ ë:}@CÎFz£Ðý©Œ¿Ñëoh㤘 ²¡õiൡ·¶a_øR,E®÷-m‡ ãÔ£‘W«Õòq¡“ç¨Nж´Œ·*–sJ:Õµ‹Eæ³øî*·™¢éü ¯<{"’¥˜Ý¾+ MêAôÆãð[|7¼n]§ípz¾Ùû[ÕrúÑg7ò¯BÉZÓœ0j{Cß [·ðë|ÄêV¡ í©ï) ßÃ.#꺟Ünyg!§;Dä#‹xè³A.Mº ?ï‘böš–Ž¹”¡=9ÞÿMP˜æøïˆ¶BÐ?Äñq{cg8tƒ°„?²£»dÛ?·Á² гÙ1ÏÞ:¥ÝåªìïO¹¹Kû½»I†£žùN룖¶ã;;[wÇ]§9 5ö©dƒ§0p?ó€¼ìêTÓG4û×Óýïó³Ã°þPKý[ŒA{£ ,õltap-win32-source-2.1/hexdump.c…ToÚ0ý{“öNL“ £èÖicÓ”m£Qˆ´B[…LâkÁŽl‡ÛúÝwNB€ví"!ÙÜ»wïÞ]rrôê%Œ,çø–ñÓæI~:{ÇÇ`ÁO*9À—lI%h±KæSX2©&qJñÔãÓ%ó( ÷4œDLo@pÀ¾X©&o5„L'{E0®b&©³ èBÛvº™Ä\Œ tÈ‚!×·ÒEJð‡lJ$‹§¤xm‹x#Ù<ÔPnW Y¯7›õF1å7NFÔ ¹ˆÄœQU›{µjFF¸oò%(Q¨)á>•©¬K§(FM(+JaF#±ªæ¦ïc9O…/âì/õl#ŸóúðçOñßhœµàíÛün¤eÏïâdÞ›ò>¾ -"_tºçãKÊåÒ›úû5bKUØR¥¾¥Ï!®¹FÔVäŽ7“[~$ö+lÝ,Ðwð ìxŠÎ³-†öq<ËßõXÔ~ ÊÓ"úúÁ·=2¶;rØ/·ˆû§>÷»Åú PKý[ŒA0•zŽitap-win32-source-2.1/hexdump.hµUkÒ@ýnâ¸ÑDÁð^Q|„¥°Û¸@Ó‚Ê'2´·tb;ÓÌLA4þwï´ÝE××§mB2½3gÎ=SºOî߃'Ë‘×þÈÅÙ [¯ž?…vFð•À"Å÷¨ÀHÈ•ÜóaÏ•)X †å%Äßž÷%#–Ò‡õz=~X×Rê(¥®¤Ô5v}RLëñµVûH¸UJ¸5—p %Ü»túVÉrmŒë¡y|\÷N÷Clß}£m"¸—E”¦¤ú;çGsB³×xÐhnÏ2 =mN§â ],ÁÍ¿î \bÓ/47äò!L+CG*±1{N yRÆÇXJôá[ôIrö’ø++&Hš“(Ë `U|r"fiBŠüàAmMUQ0Nä,žˆ|0S£f#M‘“‹‚Ä"MYB5®‘¹v')ÖɲtÄ8MñäT‘*$äxg–,Kçeƒœ«êWiAhOª˜é‚’QкP€Ö7(F¿A#£à L¢QS`fŒÓúâ+.CÑŽg`I «²¦¼Ý ‡zI‰Ëgq¡”‹¤œTåph$Eéod«ŽPÐd%GTšè2­ D Fò"ø¯èÈ× U£ÐÊÀ—R[ ù >bc`Å–Ef’J4*ÚÁL«8ÊÅ”HZ b`kež\oÞ ¾/xsõŒ¥1ôVjy`€¾S ó`åÂ××A6ŒHi$ rú@”Gq!¬¸F"×h(ðÊ ¥@ë±&S凃+Jkéƒ% P²Îk\²[ pÍWHEÝÊVRY5%¦]ŠAdÿ…zfÇAРÛ÷-'ØD*Eì¼½ØZÝN¯ë9^8tm„Åt íz²Š[bž©è9nðÁvzŽg;žå:ª=šÊßÀÞÃÚ1l*ãœeè[•7½\|aøUƒ¼ÆÑ\÷æ\=¿k÷­p„¾ë½Ð&ª$)¤RgÝo˜l›¢Juþ­ï]¾ôñî Ÿ._Ió¨˜Aå=!W¡xñU/¼z –­ƒ?g)U–`Ø\ûè¨G…&L¡_ô]È~ÜNÚwéƒ{­CÚnÝ9l6czx2Š›‡û°-9¡ÍF»yÿ²Í=\תçk @˜öh¡z½ÚŠÌ·|6=.Ýju4±ªu ¯HÆÐçøR²Öº­ÚxâɪM¾sl›¡std¬ÎwÌW]ß;0¹ÑÀkë®W­+:”7#‰¾^å·7®åÀŸÀòÝ^èv½££ƒmòÀó×F‘ÊC‡ÿ8Ði[G'â³QC–€·P£º7 h¬Œ¹n No\ˆ—Eó®°´1bvì»·•7I²5 ÈÜhš ñšJz$åЈ/_Z—÷qK¾—øŸJ[‰>UZüFø·ëQcËüEÄC»sÌËáÂ#º]ubUß6ØR°X’-šzÖóaïåûÀµÌcðVã[ãöÒÊ×ûÕBsi!è>ßš¾3t¼~Çñ¡’mMÔZ"zéÚðYÐó÷—æ½î0p|¬CµÖl,ó˜Á°ïªùû¿0ªÌ“͈«¡oØc¥Çöü(·lÛ–FÈ«Ì$ñéÎBÊéøüÄØ5•Ϻ<ÖKÓ7­ÐñÝ t­àèè ãkþ&ËO•:åÄŽâ.Gk«Êïû\ܦÍZÊË×>´ ¬µ¥QÊ-ç9Ø„8Xa¸œ½ Óý Î>~ë’¬“wÎà8_×8(nâ9-–˜Œ3±¡˜½m7[Õ°=Ø7ZÖ–žt wfü?­š£°¿¸‰‹ˆ¯õ¢ƒ=¸ÃÓl9ŒûpÛtÁ!¨rlóN£±{W9$JK_íÅÛa\ÍV¢÷“܉¾©Ù¿T<(hf,±ïà…#V°é“ÆÎx)"¢©öY …MØ>ìk‘kìÃ{ΰ-x¨@êeÇ›Y÷OêÒZ3/r‡ã½›«€)ù%bqøÄî„2­sT’ia£Ìá»ÊZ`ð˜½ûܹg¦–‰çOp3™Vu°i¬*bÆxßêÜéµÊ¾‘^aÅùÒk…WçÃfzypo¡i²ÊjN•ÿyï¿ú}¬vˆ"q¤’ BL¶éVî͆p‘ê9ÇC}ýˆ å6p ®?Û­a÷­‡ç$8÷å¦îüR×(‹(/HG$Hw–~Ϻ]<é›~X©¶F¼B§£IÁºêf?ì® ´Öl§czöB{À ÌgÇŽ=wÏíó»€Ý»«ò@Ëd–F§¸¡ô-› ¤ª| ®Eª&ÎiÁåL[Í8y.ò²ÉÎÉŽE”tsØÖ¼ÈÅ,Ã[°hôãQ~ŠÂ›­kƒmúžÊ )Œ?V u;âê;Ôè‚ÊcÇÙIÈó4o=6YÝÞûçÇ/à(¼v{åÑgc ê&€õ«Dy¸ÚO–úiC]ºB&|–˜R]*ÃK2YäÂGƒ|,¢1žP>xy<ã3¸}jÀeøIÂòOŸ³‰×¸?N«³("èxöP'ôÔ0Tv®KÖ9ÙÜž‰ÙžF@µ ©ºÓ >Ô7Ëh¸6ÚRj ’}§Zû%1… ƒ¨{òùob _”=sR•›Jj°’,‚Ëg•[6˵Å;ÏÙTí>E"IKAïBù¤Ó&Œ²^ÄiZ‹³Ô0Œ»0õh=Í~îÈ-³Læ_òýF5À~ 7­XøaÓw'ë_ëöÝB‡'!í7PKü[ŒA-‹mL‹4tap-win32-source-2.1/instance.cåXmoÓ0þ̤ý‡jF˺ò®ÒIYX kK›Œ*MÜÕ,«Äéhÿ³ÔIÛB0irbŸŸ{{îìt{ks¶³[yCÃ{µíôéá}¨TÀ„S…$?¢sg0‹Øœúæ4â‰wgâ²?ŸÌ©G`œ„§,tÊÏ…€:|vßÅÍ™ ƒÇû̆ñŒFćÑ9ð ¦Ýµ”‰©1baßRÄzy႘…Ëh1K"T.AñµÉfç=™p(5 ¨U«µJ­ºS…ÎŒ„¯»mpˆ7 YÀN(‰Ë`‡ÞݲsC_ìH@ÜmJBŸDÒ¬çÝ 1±0£¥˜‘€K¦ˆ¸DîTÀŒ#”ŠÙ˜Ÿ¹©Ã9KÀsCD÷iÌ#:J8ZË…ÒmÁ”ùt|.‘ĬVÍI4•í<'!‰0%ÝdPZ÷0&Ú¼Ô´EÄÜg¢¾²ß*qE¶®pBÛêc®$Ê„Í>¸\ØyFƒCILÆIÆÅáít˜í#xcözfÛ9ª£8Ÿ0\%s¢ÀètPÄF‹"7œ+ŒC«×<ÀMæžÝ²#À=³¶ÕïóN)Û5{ŽÝ´Ìt½n§oÝè"`%ÄUÁˈc|Â]äùy„yŠÑÈÀ‡‰;'˜/Ð9šè‚‡Äúv&Òø,<‘þ¢¸Ž©äŽÓéÞéÙíçZ/H|T²Ø QáY2ê@Ç2^†³ˆrDaWfµ@íOöÓªì®GÊÐOĽ{Õ2챘 ñC ZÛÙÙ©ìÜ«>ôM±y{scsã¦OÆ4$`·ûŽÙnZ×ÖQÉ5 Tê¾îØûF _*»Ó¡õ‰c §¦CÇí˶`yˆöp²7h¾´œ>Ô<ü|FPÐçÄã°ƒ/hÇêìVH>ñºXBM¦ïΰTºŒ†8Àt˜NàúÅÂêúª…­1±bæáÀ±ÞBÀ¼S ¡mþ&R*‡µà¿[õú¸ˆ{`ö$ja¶N†vs7ôÈO íA«%··ašÄÊ“(D~N„Ànª²“=]éÍ ªÈ!¾vƒ„€J#¸¾a²¤'ƒæÖÖÖ U–Ògn ©K1ýLŽr#4pßK5{W=†8쨡¦†{Ç2Æ$ˆÉz˜Çß #‡ûjx †‡jx¤U((á”ü;<2û}«ç@©jÔÕä¦B8µ×é´,³-"Dy¥Å —D|²Ðh„åì¨ô(ؕ̒© £´¿…\epzKm¦ãepcÉ Ì$Ðzú&;Z‰¢’*¶‰µ¹¯Ã;A®ÙmÛ*z—nuTv3¾Ò㻂ûÊ iá"h:¾Zà™Ùê \MÙÖÎ4Äù(¦”!Fã†ïóúüü‚ÿiJá„ñaZÍ×VËt‹ŽóŠh¨mfóÕÀîY*zCsßì:ök ÃHG•]^–z²ÈáåÓbg¤;é˜ï<^E$äR‘v5Eã„ Ù ›»®Ø¦'ÙSeWôF¡íÚ;¡†ìY‹~jÎl#¹À1Kêµ\V+;Bâb‘x|È–ÂB²³øºŸödðúHõ¿'ïB·JêPÔ Àûß§\2xeW>6»Ê "Q¹ù?Ä&Á˜Í q¹Y߇¿6ºSë.T’'LuÑÚD_z–±Ê°¾MëkÏæËŽÓ÷Ó;‰ÃŠ.­^_fÙõ%ót•ÍzR„ugðžŠð’êeÖÊy_*ÜãÚ¤k?\ BÉqZÈûÖÞày¯…7Þá'æ1\ê´ØÔ¸å¿o”峡Êã'*ªXPšËåD¯<² `–\…ªû‰fR.\iOÁ‹o6…:Ëéª,½|½ÊùìM.È•FyÀ¦Õñí*[©1Ô—™×#S6'©UÏ"6ý½ôûAú|?97EÒfYÆ[oDæ´šaóý²8Ò¥u¹ÀÞîÇâ[¦.÷&KÇ„ÂFÊ-¤’e¥‹ÃcÑ…¯¥†_.©Û᪺%jÒÆå[W[¨–Î^Ï"âžÏá¶ö×ÔÆ ç77ZŒ&Ù¬k¤»o½¶‘‘½VÓÁ<©/ÛÎè#ñø•U²¢Iº­¸òkÊ%ý/ÚôOKÑ5Q(ù±Ž¨Æ7 —±+ŠŸàÄ)âúâ§aåú;qþŠR“Å9í{¶¼R~já"_zWÞ¥?\#_PKý[ŒAOÎ £¼- tap-win32-source-2.1/lock.hÝTmÒ@þì%ü‡1& /çK jR¹ÞÙÈK¥E%1!¥—]ÜÝBˆñ¿;[êq’çqgbœЗyžyæ™ÙÖŸ”Žà @èøµOLœ´êÅÕó§P«_Q ä(¶DFÂBÉ%K–L™,â`¢ENq]$¸d1Bš‰Ø0)"Î̤ª‘È•>&ð/ 3¦!–ĽŠ40¡LaÓ5˜BÇóÝÄBŒ}qÍq½?&:®¥ØeÓ2ST<'¥ÛŽ\¬»˜(w*Ðj4ZµV£Ù€ÁÅG¿!Æ3!¹¼`¨«à‰ø¸º!‹Dbñ 9Fš4e"A•Ë:÷»@b´•Ñ‚²F„)r¹ªìH±¾]¨hniREYZ¦f)lÃZfG‚ئbÓÌZc‹Ö¥‚¹LXºÎ™ìÓmiƒj®A¦ýœ£@E#ñ³)g1tÉw¡q+¯è…´Ø=Ûš{fEt'©Hd§µ§‰­Ö„f•³Ìäé"2VçŠqNV@¦1Íxá#¥Ã'/|7…àôÇðÉ~8nSº™Iz‹Kܱù‚3â&E*vgÒ GÏvÞÈyëu½p dÑ™öÝ €³ÁVÖw†¡×u!ø£¡?Üc€ÑÒæûÌJsÇÉ„MÄøÕýÓœ4‰ä Ì¢%Ò¼bdK’AL‹uó$ ÿ¹y¿”¾õ4ßœ eœÖ}à½þ9Yó,¡"—€œåÒ~;¥JX Bš*¬3Ä"÷Nõ·Õ~ö’Ö~¾ ’>b¬BYŠ““FÞJmlzÏh´šÍf­yÒx0  ®—ŽJGf½ÀS 9YlJGßé ,%§JÄ™÷SeÓ.ý€Þ(t?·-ìa˜ÀÍ“IÐu]z= Ù €zæ,VRc,E¢¯B¼¾Nr\y^ï@¿µ7y x 6ü¸šìt>Œ¼¡»ÉŸ¼í:ïÉV ¼.¾PphØþ­f¶ùrŸ¦ä :§\Æ_1!×Αt–—·ª+xøš•_àê[p;eO±(»Sµ}-¸pÄEyw6„ØSùþm^C·ë:»ïqó:ص=»Öô·ëV¥¯…θ©Ü¿v–ÞzÑþ]Ë=±§öÌénnŽ»îšýCNßù[Ç] {pÙl8ýQ¯wnvÏr:§ŽzÝ+›ùWÖí›þ?¾¢öP¾Çs4L)yê‡r^Á©øNØy7éºÝne|Øg¸¶Ýø0Óìfßþ(ÿBMF_Ûð‡Q=ìLÜÃaú PKý[ŒAÖ¸_Haztap-win32-source-2.1/macinfo.c•WûoAþÙ&ýFM„âAµ±&'%¶…ðPcšånM]²{WÀêÿîìî=8 >š>޹Ùo¾™ÝoúòÅþ¼¸Ýƒ/ŒÖ^ÆOG¯àà\¸¥’Ó|ÉPÀ\Š;æS¸c2ŒH!™ˆ‡¾|zÇ< ãˆ{!œ,\à€1|±P\œp˜2ž@ìQÀ¸š3I}­ œRh´»ç–bLF¿h’C¬O„ ”à›hJDƒPüØó•d“i…FjŽS;¨9U:sÊ?w¯`@½)˜0ªÊÐæ^¥lÁ÷õzIJrЏO¥¡õ¡{HFi5((JaD±(nPÑy›H2Ó0c‰^JŒÃ‘´+G8¢ûL…’¢Ù†:èK!a&|6^$mÍB‡TΈ±åq5„”S‰%éF£€ypyçŠfôâ½ í ¦Yr[šQß2ÂOƒ]­?l"ãêc­ ÊTÌ)>Pó\° ÀT@¤è8 â<¢;|i>v†p¯®á‹Ûë¹Wƒë:º‡Soéµ`l6b##I¸î™±Å¸<ï5>â"÷}û¢=¸LQ«=¸:ï÷¡ÕéaËvÝÞ Ý^¸=è{ÝNÿ¼ЧTÈ?%kl2ŽIðiHX°ÞŸ×X'…$¦äŽb½<Êî"ëó>1ûE÷,§¦w À˜Øîîuûê¦Ö "ƒ¤ Jš~]¥bظ˰,DñǪæZûõ)¶ýlŽ!»ñhú‘†8Òä“hRÍHÐæxø<Á6 >ÎoS"‰‡½\Üß»GTcn>“ ¢pN]ƒÞ`aÍÞÁs÷9<{ëÖ·hm=/êäWè…E(A±Ñ‘Šî„';áLJ'ÿïì„?݆ϡëuqJ$ #ÉG4þÒö÷ÎŹ{µ¿×%RÑK·üå6›=li…-b“ï!$¼PÒ[O»WOž°–7 oš¥.±Æ¸0ÅûóÆgâ«–{Ñ?O!~Àf7ÄÜóø²ó¼¼vûýóÞ :\=oÒœŠ±cônmÞ¼˜êQðR.•â ÝÛ?¶7Úê’xMM€ažÐ»ˆ^îñÖ6S:Ë‘¬›×Û;2ö]ÛyôËÆ´ec“7õê|ЬÇè‡CÑ„3`Ó· Ø*Æiõ t¼íGÙ¾g쵃 ޝuþ¾¥hßu“êŠ ÆÓDÜÜù 74`çzë²½ÿS¬/ z„#G¡TJ¬e»°rr¬ô_ËÌ<$§ÃlU?o¼1²sµ^ŒR.vïVu’ãgªXBŠÚ€(‚Xv«Ãv3ÑK⓹nVNf4Ó™¾ÁШ±¶‡d„'ßײí8oZ­7ËeúGƒJ#+ï«}чä5t,Å,–‰ˆcÓˆ…é¸Ñ0ËóTb±Ço…Ç) 2” Æ£%Ô*¯ôÔ§7fÖNì^…,]ztŽ×·öÓʯt\”o_ÌLx-¯1ÕlÃmCe|g¦¶Àèš¹ˆÂ©q$Ò¬BKx>Ge5r¦â°ÚA;+@ÊœÃ$ó'Ô׳-p.„¼UFôlÚ4-¾#2bv(c|I•N|€’ÁQǪÂÈi¦qVC¡Ã£M•>ÅÙN†i™4n¹Xpx2ÂIyê“Ìñ÷ÅòIYÏ¿ÂqPµ}›0ÜÁ*c 3}Œì §‚ÕêQí´V}}ˆUëXÔr‚›`–7AõòÝÀНk''§§'GµêÑñÉñÑQ%•ûÏv3íîž©,^¼é9ЛHLÄ›pêÇZ·Øn±XtR—œ(ys<ÝëÞúxn y9›¹f®ªm›G«&"f (¥y‹ ‰õÙÖ!ÜN"CøøÍù®Ý–zÆ–ªµ´Z[b¥7²[«˜½@¶¯÷vûm=s588Ü?×oâÕÔc[ôHaüR!Ú(Æÿ*’ÉÍ–ôج¾ÅåU=oûyfѳÍ+•Œ.äŠX4+2Ǭ [wúîøq¨m„ê:þÄ¿¶˜øÛpJJl8vĦdÐ IÜÃfR·ÍbWÆCN¬‹µïzè( ñ_–^Ñ.´RñPKý[ŒAÍlÑj+Ýtap-win32-source-2.1/macinfo.hµ”[¯Ò@ÇßMü“˜H1\ ÇK¼&8ÚÈ¥Ðà‹YÚ)lÜî6»[ã‡w¶ÅçD>hŸ¶™ßü÷?ÝwïÀ€Eµ?ryÑïOB» |A-Q@ªù5X…V;ž"츶%`YQ!~÷¤¸ã BVÊÄr%™àöJõHÕÞt¨ø§†-7(bï™.MÁ5¦°>€Ý" ÂhTK<Šq!Ë9±Þu'Œ’7iF•ššWPz¨â ùfkÁ4¡ïûývßïù0+P~ˆ¦°Àd+•Pަ¡L:­Ædêê5 d†4•2E]ÉzÄ'£žA„5 µoÞâ|Ûh–;L¦)˨Ìî™ÆçpP%$L=åÆj¾.-©µ®iWiÈUʳCEr_O­-êÜ€ÊjÓ%¼A‰šF•kÁ“ïÒàIÞñ.¤Å%˜íÉÜK§h^+¢7EM˜›Ö-—8iMiVe« ¤³Nçž AV@i0+ÅÑGJ‡áâíl¹€`º‚AÓÅê9¥Û­¢(î°†ñ¼œØ¤H3év&«“Q‡ËYL+ñ",ÇA Ñ2ŽfóQ`Žè°â6³²Êq2!E˸8ßÏÍÉH‘Â–íæ• ß‘D -ÖŸ'qô_(¹©îKé'O«Ý©´î³hNßµ‰(SjrUPQ®ìwSj>žT¶{Í-QÔ­S½¶ÚžÒÚ経K°óÒ!..ü¼VƺôIà÷{½^»wá?XÎWܽ{çî{<£Ì`Â’Pfjˆ—˜Ò÷´:Ýøî*ºÝ—ÿþqXø«‡ieþ›ŒŸ÷ 5¢à9Ù©=ÖÁË—ÐxÖ€ïß¡>·ÏÎFó¼ú-~ò ·^B•^¯(ÅoÀýûÀ :?m4]í1œE.¯EØY$k4©ÇÏ.õ’}ž/ECËc4õšÒfMÔ'H?ƒµv±f <¥þ iÑ=ª †Ã˜x'ÚxÄW¸¦óº¢}B­®ÑnÇЧϣ÷Ë`ì±Öº¦€—cžäÕ3'eý+‚3ѯ¯‡2åôoñPKý[ŒAÅP€X¶÷tap-win32-source-2.1/MAKEFILE=Œ±ÊÂ0E÷Bßáÿáw©àˆXÔt0:¹Äæ+ÓD’ˆôíM(¸Þ{ÎY”ÅMÞ °¦ûöŒ]{dUULéˆúÜÛ÷jè“{ã#mDtJAÂÒ3‘cƒ6”¿øÐ½_Î’5 Ò0¿#y2´UÚSÃŒ)c9–V‘´ðžî¤1™ý•“ípî¼Z'¥,ª–o—†áïŸ‹ÓæÀ¿.o9›«µ¢¡,¾PKý[ŒA4kBÒtap-win32-source-2.1/mem.c¥WÛn›@}n¤üÃT•Zhqâ¤7U©+QLSTǦš¸YÖ1*fíìºQÿ½³»\Œ¤‘ŠvfΜ93»8‡O÷÷à)€«Û­ó(y~|Xܽz­è𓰄IJhIdæŒ.£À2bYîÇùsqÛ’e˜äIE4ñã([Ms„t•`pÉa¥PÄ^ù)DI: ár Ù”€aÙ¦¤Xᆮ?‹ëÓÂÅ)M¶ÑRš3L.@ñÑ ó5‹®¦(† Çíöqë¸}Ô†Áœ$_ì>¸$˜&4¦WI5°’à@“`~òxFbâ§È)OB­S»H&å4ŽAI KÓ•ºE…ëvÅü‡™0ôJé$[ùŒœÀšæø ¢‡Qš±è2ÏmÆ“R3F“µ@â«uꌰY t"yô=8% aØ;¿Œ£z¨{’’š^Q ráé´÷gäHFøD1‰Ï»uG5×{%P¦tNðÆÏ8ÏUÇ(ä)™äq¡#ºÃ¹å~x.èýœëáÞwG'èžM)ZÉ’H°h6#ÄFFÌOøÌL$Æ™94>bþÞêYîP¢–Û7> †8²¶>t-ÃëéC°½¡=ṗ+ îk"GB’ùQ¼9Ÿ#ìSŠ$ã¦þ’`¿-‘¢Ö¿;QèÓäJԋbvÀ$ŠqÜöÈ꟢´Aœ‡˜¤ (•ü¼Kê DHh¦ÁŠE¢Ð;»Úí—opìgsLiÇ~@4prñüy[ƒ÷4͸û™Ð>>::j=o¿ðîïíï¶v.¾ gu\ÙŸøWdF’ìf_ŽaXÝý=ŒÐ㘠x½Ö>;Ño‚4ƒž©÷á7aTÝß»ÆÜ B I–³:Ð÷z½\ Eƪøˆ×xœ±5(Vp×>j)òú‘¤ÏQk׿åq™@«È<ÑmÝ}¢b,Çè`â®åŒWw=üò QZ¯Å§¤#¨ógqñŒ_q¥HÙ΢ž×?øI┈‡ÝR%ÖŸº6ò+ s<ÛÌ Ã´]kЛ¦á¹æ÷K·gÕÍÒï,¾ø “>¥3z CÕ01cŠè’×Ãi°Ù=Þ¯²'ÒÃýºóƒºïO‘ë¶`e¦Z®G$Ác²p多®uÿÚêK×Ô©P¤x“ òØg°ÈIN`VM?0Š›5!éAµu…d‚+ðÙ3=sü~„Ùô^o`蜀’òÊà;Ï"î)*øAqñ™\ÁtÒP4@UÕ]X½Û[ý®y¡,}¦ñóD€^Kd\ƒg¾z‚ EŸøâ»,ZïîøÂ.xHÿVÃTÄtÇ1‡®Œ~Û.v©9zð±ñÑ4>)ê6ÎÊÉÄáp—øæm!ÅÛ&ßÍdB4O¿LY¨ˆ+#.žÝÕQý3ýbìX_MIæºV¤ÌòŽ'™ù¿ÆÍÍ5蔌ê¢E~xZÜXI”•\I·Ü$…ç'´©EUñ»r~˜I)üU¨OÎg©P5p‡ž‰Eeb²«^£…æuIü®Í=èTU ©Ö¢v¯ ÍÃC—ÇGY÷æa±Ø>vg”z/WGÑBƒ[4ØœXï^{ƒ“§Óš“V¼jð¥8+ùÉî…$Íæ6fÛ³ÓÙžÐ]ÕA`B§”ž/mocP¸VöD-UÇW»ÿ›~`<'+ Ïž~üiwÌ7ÚSÆìÊAçµMhrš÷áaAãæ²K U^58’È­Ö½«+*2ý¸©RóWÆü »OïSh àÉ‚_É?THÊíÀcñ~·ÓI®ÕE­¦ü× "L­VsOHi99®ªB„ÿÁj\ãNìAS«Õ›ÿ¼(|·§¨‰È£n™EÑ4Ö¸78 ÁŽ6¶$ŸˆŠ¶gPòÚ•ò-ÂÿšÜ¼ÍKë6ƒj}·C¥i{€ö÷þPKý[ŒAF¹;otap-win32-source-2.1/proto.h¥XÿoÒ@ÿÙ%û^bbÀ°Q؜Ԥ– j[T4¦éÚ+4–^mpÿwß] ·Ò1MìKû¾|Þ÷wÇÚOOOà)€£šg£ä¢Û.ß®.áì TøF²„ÄdцdÀ(¤ÝDM”±µóRqì È&ò „ëÄgM¼8b·@@Ýæç¨¼óaåàSÄÞz9DIžF àæØ’€f˜zábé gô½U„XïÎ.Îirˆ–Óu†Æ(~j4½Í¢Å’ACkBWQºg]¥£À4%Ésñ— é""y ŒÄ?o`^pýŒÄÄËѧuL¸54Ç€ÎäÜ.4rBà†ÄtÛª–¥NœyÅÙ’"—lH­Ò8Blô(óÞ3aq­[Ú•Ô·ÆØpæ€)ÎD·mL-lYSµC›U Ì™eNmýÀ&„à ˆ‡’ŠŒc¼(¾ÛŸs¬SŽNÆ,½ Ázù$Ú ‹øØX¯D™ÿ˜& /ŠËœŠÞac»O͹1bjýx ‘½‚@Ù§ŸW©Ùƒ(„„²l³ˆ! }°ª•Ö~öÛ~•¢I3ö|Ò{Í!..”¼¥9ãâ×*€Òít:g å9ÀÌV¹rûôäô¤Ý~ý×Gx ¼ ÈHŽS§³%_9 –ÄÃNo‰ÙS-óÿ-žë¸8“ݦù8sy´H°þÒ˸»j¿oÁ—«¯½{dxyŽ‹ôŠ>œ¸túIi ¾öüÂÔï|ºhå7èÎÈ&hì ÆÎù214÷Zýä^kªí¸cÃv¾ ˜kM|qœÓ Äi÷úô¤âv@rÖƒêÓ~*ÈQ"z[Šè=mßÕÌ3¯(5w‹žpßvj¢¼PÔW„oº†‰âÊå…¢”І¹¹ä#ȨOcléš ¶^©rUª ¥ªÁb4µœ‚ZKô&Œ§Œ>8‰t°¬[Ùx-xjʯ*À(!ÿ5ùè†È¿Ìcù¬\$¸}™÷½÷hÇ"üèK‰ÿÝÒ lQ€R[B0Šó›oI&œÎÈ÷5šÊ9Î>iÇ”é;À) PTvâv¹'®37u.¢(#ÐB´˜3ss'ʽÞ1§¬©3­éJ§”ROáys¿E;úyhñª®%­èI­ËjxN]K?ÓmgFmŽçHì Þ²]Ô²ƒÇb¥‚­ï=ñŽrØ ÿn“©rExa˜;¡ãP‡-û0^]ò÷é g™ªöNwøÔɯÚÔñ/D†Ñ~×=¼›åú@­‘;Ô÷ƒn56Mh4øß7oಠOxúÍ{„Çúd'¼ƒW¯ ‹Â²]vW:7&<¦ ‹Ñ¼'W’ 0.W%F~Wì»ÓÁàZµß¡ÍN†éM—†aÍ‹aŠžõqivž‹å‡ï•uY—v4¾–¯„4¾ÿEÚЮ9¸Æ÷¿Š¹x·ŠË`öô"H¼¿$þ·"{ãédÈEs~ÂTIAI*‚ÀËMyÇåØ^ÆÏÊŒœ ‹¿y­ï»ðO‘,y®þÃE`çfyVª,ÎÓ*¥l„zt¿Ñô½~Ýwñ*íïg).wk Áó—çÕ¾Ìì‘aTõ”f¬zÒâS†wßåa§ +T‚“ï½;w¾Ë„OÖ« ¢.g¬Ëu„<ÿJè6&Á‚¬H¤Ze­å>T#³³ i¥Æ™LMÁérøÝÙÖ±MºòçàúÞ±.k?80Æ?PKý[ŒA7ÿtl†!tap-win32-source-2.1/prototypes.hÍXmoÓ0þŽÄ8‰/€Œwñ"¤,É ¬MC’ „*/qZCjÛY)ˆÿÎÙI›®/ƒBìC׿ÎÏŸ;ßùrçæÕ+p u¢[o¿ïNûíѸu øD%§%ä’Q Z@%ÅË)œ1©kR‚&•…Øõ—Ó3–Q(jži&8)™žƒà€6r1S·qñ‡ S ÄžŒ«ŠIšÃéô„‚D~ãbëŒxdÊëè6•Jðu4%j‰Æ-(þtE5—l<Ñpݽ÷ö÷ïݺ·wåÇQ)Í&\”b̨ڃ€g·÷0Âs³^Ò’…>Õ<§Òºõ2ê:£Œ÷ຢNi)f7Ö\1¼%™˜B¢–…žIŸÁ\ÔŽè9SZ²ÓZ£·Ú½#$LEΊ¹E2O;ӚʩQ4~„CxI9•’¨>-Y=ä+Ú¹×î}1 jÒ‘{hˆN‚ð%R›•uŽF– ,Ê’~¥Ï€À…Þƒ™dQÄ…Q=—ÚŸ`ÚO+4•$£{Ôâþýý=8Jõ¾°ïîÝ»·îÞß 0L³øÎÕ+W¯\cfda*È(Šé =‰üdäù‡Aè{(G!ãt‡Ü „i’:é0ÏžkŸkiÒàºý„ „È‹ƒc? ^ûn Õ¨Qœ~¤™ÞëÔ†aà<”¤1’‡z1¢æÑ«vã™1y<Q½q$K2V?IÖ¦•¬¥ëüÍja7dá â×òx—VëdžVkgPçŽÊ¼X8°ÜeWÕm™µwÀWB|Ú(²þqàú]‘m47êzG(ÄÏ46wii­€ø_0ýͨ+!ËG­‘Lp¥!› 7«QH¦åΣØGÄüwl¬C-1ÎU½Ë®óì ÓÅ5]°t} }KJ…&:øæ÷úqtÝWæ"%™À22?BmÔp—ðŒ–ï’²<%Ùߌòy—àho÷öM kÝ]7wXÖj‚ż¾|PVPl[Y¶/Ûêéå;ÛÂ×H ÌåÄÑ/bœKì×-ꈒÙ9Y9ži–XµMʪ§z&ä§ÝÒ)Qç¥}ǵâ)ÉÖÉI¨¶7{úÕ†¿>…k7ŽiÀMR5©ìѦ&^~hþfe!Îí§Æ8¹w4””_d;³`öÎ;°ámÚcßÅØð^mVÃ-ËÚ[5SÉ F¥Yt­*àù,ŸÞž¼0Ï60ÎSYeË}® Vö‰žD.ÜćÍÚ&¿D×W:Y2WšN9®§”ë»ÈÌüºV&4ûÞ$«ž§5ÇkÊoœ1‹eº“ÇTEt69l_V¨ëÂ5¯üÐ9èù£p:^?=ïÈL }ç5ΞÏáá£ýý«WÚ·*T“J”vL³¡ªqÆÄ¯Ç ³×,Þ³3q%ð&zZÎ͇QŸ¢ø“Ú¡ÏBQ"K žY¡ž.GR¿dSƉnæF;h1cÉŒ¢‰ïcœqÒJÜ8ˆRôï:¦E3a¿›á LhV›¢ÞâÍ@hTˆn^0ˆ ‘Ìž\žÝÎL{äcÚ™ïÒˆã8Šy´þTcËT¤ ÛDyþ©}lE©Ø«YapËN§z^Q3›¢ Î4Œ¶qò u—G¬¹ˆŠ|®éûG>`ô¿ocrÑyO' ºl¾Ù[è5)iÛQ{Ù‚vkžvF‚ßbô4„ ˆ€cîLí0¶Xmq«[€·•L²J Ùf0EÒŠnê*ñU(¸“cþÀõŸt¶uˆ–ηAxïhÔ ¥ADƒ8ôîÑÕ+[H]°z÷чgFº6ª÷1u+!µ¹z=ƒæ«ÛDÌ`Š¢[FÒÔe^o˜žñ}y6›Î6JãaèZæFî+ß=ê Vtö )W ûJ±v³LWgß‘´cu;Š”ÝÒ5]o½:¢‡l1²ÛÅ73œÅ»rÓ¹úíPKý[ŒAÞsd+# tap-win32-source-2.1/resource.rc•TaoÚ0ý ÿá”~hA2úmš&âfÁއ6Ò¤ˆS²SÅ¡Õþýœ¤¥ÒÜ»{ç÷.'_%r¹Ùž½%2NßÔ`ý½Ó®Q™¿Šì¥;íažEsìù„Qè O*eºÝ¦r°6ªÊ¢*º'æ¡‹ûÇÈÆç€…ý‰G\®F>÷:mèÁBÆežPŽ=ŠŠf¸HÂv§rx‹U"E¬ÿ®ÒL@¥!‘Ï0a³£M.ñµ•g:£ NåuRhÚ®™×}Pš(`/\û„õBA¾Ûfî´¿ê¨Ö©›ÖüžG–7/m¾¤J%O¯‹ÍN¨¯­2Ð)e´Ónµ*¹nXŽS‡FupÏ(¯£ù£u ´ÄÉ$rȸÓî keɵ£¢iD1`Þô#•­²êLeÍs½rî tŠÃ1CžÕ€DíÙ¸[Äw6Ð üªòÊê‡>dzH¨žã ±ƒ›å, Meztƒ³·X,U»ˆ†Ç:Ì#6Ñ{]ô;Õ¡Û”òÅ”GÄc þªÙÁ6r&Ì u“< 1òüRÄÈ4ïnGæóSBíÙ8˜åb¹–é&}N„ê‘ËîЛë1+˜ðæØ.ÍåCòþâh¼Z)²3ô“yÑ>Ù7Íâ{š&´NŸÊzÔçܨ.T?5¾‡¯Ô™jƒ‹&S½¯‡~`èOÙè’ .Ã}É%QÝò d¥klæý8»ƒ }ü…ÇÝ-^›Ø(ñ_ô‚#ãdubõ㫳z.®Ÿæ¿¿Ë«ÍýPKü[ŒAë%>{tap-win32-source-2.1/SOURCES.inUë®Ò@þOÂ;ŒhT¢oñ‡ †K˱ …@9¨1!Ûv ëiwÉn âÓ;ÓR*^¢ !»;3ßÌ|sé}æ"‰ÀÌ;k!_¾€H‹×V³Q‰F*M™ŒÞ@P\;!›fc:x?[ŒfÓyOfÊàÝõª{$ iøƒÅã{ƒ©Óë÷ç‹™½ùt´qí~¿ûŸæNÏ^¸·Î¢zšüw=«ºMÜá²÷à±mØàqCÂöra%"€ß™É´a1'i³áz£ÉÊv*€óµÔ }PšþŽSþ€i¡$È< ð;®9¤¹É àð¶GªýÚõ^¾Ø`º›op`IÎ D<’G $)…JÆbÛ9Ö®ÙmlgìzÅå\Dt9·¡crIæ`vƒ§¥;ó®©«eýþ‚¹ÞßÀHVƒQäs­¢<ä!#†¥øwJ•ˆ3‹•NYFüà •í ÖœÃCw<¼ãQÙÆ*)Ž"I€%‰:Bn S°çšP ÎQ`T®CÞIø'H`o·Bnñ AJ<‚Év*Ï€Å13Ô¡ð ߥÆ#S3rtÏC«(øpåNlÇ»m·à^Záî®Õlx¾í W7Eã•®VKl {Ø{޶ÎdéüSdzÝqÉØ’gXït/®Aí3‘ŠïKæ ‰»³oÐ1æ{%.Yð¨T1¨³²jöyTŽGñÃqÇeeˆ‰—êªÛ±{íµT¨â.*i]9!3-¤!–A†µÑ8D£.¹f¶½ø†‘0cxŠ(º[V SzL–lÈl|î…Kà¦ø©6æ)¤ìû(×ÔU,Cù©ê(€¡Î™ËZc¹““¾‚H¡µ@4./P”'`§ž .Z]µ&ÅòksÒ°£=Ú0|Úž'övôä ¼¶žÁc„M83zÐ*ßî`9Õ†#=ÃIåT¥PÄ'JÿD(¾‘¦.ø*Z÷÷šmSV«·0€ H”2رC1|”Úæ)H.PAcø!ŸÌ3E&稢4½Ôžð”à~º,8_Y H9«ùÊ÷—àUðY-r°Š‰.S2ÁÔ÷ûDpê‚ézZŸRRð—&ÉZ#12À!üu'”!$ k@ÍTfx.!fVo“ôt9ÚÌæ¾;u?|Úr8uÄ õôy¢ÿ¨UJW#]ÏdíŽk |_4}™—H½¡¤@ã*9]ï°fcâzp÷Ž'ƒÚÍ?_ÛÐůЙ:ž?˜¼ñfÐæÅŸëgoœóÙÂ_þJ ÕÑpýó".cÂ+®WNa¹¶íSµO¹¤Þ.fë%º&èÞóúaìN ¬þB·­árYúJW{­t…¿#Ó³Ã.ÀúG-âîúcÉìz°ð\ïf3qnI¯»~I8ËÙj1ÂSÆö‘>h+ÍË=biäüPKý[ŒAñ1äƒEcZtap-win32-source-2.1/tapdrvr.cìisÛºñ³ßÌûH:I¤<ùJšQìŽ,É1]Õ‘¼4Íhh‰¶ØH¤*R±Ý6ýíÝ]\$AR”­ôšª¯ŽD.Àb±Xì.‡Ïü=glXëíp½—/Å·_ý’íï³ûâ¬à¾±æzÁÒ]9SvyÇ™ÃêV¯É›(ƒ/öÂ\ïÝ<ð½$¶À_¯ rB ?ëþònå^ÏBVª—Ù‹££û/ŽŽXwéxï{6t&3ÏŸû×®T˜åM*™íM±üÊ™;vmZ{SgEÍzÛk1hL€ÍxÁJã°Kgîß”MAº]¯ì¢¹ZTà_…7öÊ©²;Í&¶اn®ÜËu­ ±ÒCÅþÔ½º#LøTW:«EÀü+ގΈ½u²µ~¿Ö~¬x8óá­óÕáÈÜÅrînhÑÊög®8Žv³_¿€Bµ3«e ?2 ѹ5ì4vÞíËöjý¡Uµj}Öõ{ÝAó€±ã ZB‘G¬+¢8aê„¶;òçG§9Ÿ²™ýÕñš8îWh¢Í&ÀX›GBÐî{×Ô_×4%Þ!WîؽÛûhuÞi'óõ*Q‹"?ŽR¹ÊÜ+æùa…ݬܰø¹£cíW¿¶_,¡ÊÞÜž86X#Š—/*ìÌBo×;zq||¼üòè׌5,|øã?þpxxr¯–$¦’Ó¿9{í9SìÀ¿ú"äÎÔ#çÌ]g…%%S#ÿ+Q‚/è¥"¶A»·ØWÍÞü™;ë4¬{Å–þ T¹°=ûÚY8^¨ËžÝA3®ìõXØaþÆ1Œòcu•àsÂÊÆJýæèÅÁK,˜“WDÅË5–§yí,ÖsÀAÖÞc„׬´ôáÇ~èïÓfõ¾þ² ÷ò××3F„Gù<¶ºõak\ïvέ·ã^×ê ÇÃ.ÿÄIŽ:Ìõ'áüà!#õã¿|ÈOüÅÃì1>¼ò€V¬Ñx÷¾Ù·k¿ïöᩳZù«ØC¶X! €vq|í{ôÿ3@zëÅ¥³Ó˱÷|p—ÂÀ‹ÒøÛVÇêuûÃq£oA%úí™Õ©õ?BçÛ½ÚÐ:k5ÙQ¼è«#U˜'°~h´MðÔp0ìjçÍqË:ã¼ÏÎåú†óÊg ¾–ëPƒ×Zƒî¸qö¶×ÇRŸ(ÆFólô¶7® ÇP4¹~ÁAŽ2³ÄܪϜÉ’gá _àÀ)1[Ú“/N ,tŒ+@ùq…òálÕª~õjõwM`Ïþ¨S‡èvÆõ‹fýÝNúÕü¹×ì[í&¬-ÔQê¾wå^¯Wr¿T7üË?;“åÈ%Ÿ@ödâ{9w`ùõ -½}{ºp=”£vA€H˜K\ä± þ›~µ½ Ðo¹Bº H' ]ïZ ŽÆ,$3ò¶¡ð\I%ãY€ÐÐp{jÂ>´ƒšÖlÇŽ† Ù©ÿ;ÝN­,\G36>1ß°W¿::ŠÌï70ႃÙiìQ4BIj<ŸN¿ðgÎeòmó6ºÅxh/L9†ºSï7q^ÃÚ°”ÙO?Áߘô­µ›ã³Ñù90ÐÀúc“ýf3:çóvî_ÚóàaUüøÉwP°"\;ÀˆVö¦ò©U„!¶b#Õ2X/—þ Df×j´@D|úÌNØßâð`ü¶Ùlý¨¯M"ÖhP‰¾k7Vm<õpi6RÞYñhÐŒ¿¨ýlµGíq«Û}W»hÖ‰·õq·‡¢4^UËê¼zÍD-CP«mk8>kuëïh¬bïûÍz–ά×ï›F·?n4õ¾EµF_‹ew ÿ$_ýŒ•vßÅ+«¿‡G&X³ßïö“‰§ X_ŽAâ·kdÍZ£ÑU?ñ¾>ê÷Í·g§+¸6^N×7®µ¬·dþ8„èO§ :E«eñîšín?‘l]{Ô‚ Im0ÃûDrØéUæ@X±Ñ•ÝU¬’þV,ÂçVkØŒ“¹×ï»ÐÜ4ŽR va•-29K‰¨&•·’f ç}'Y}6™ÌD0HÑÍ” ˆ:p§Y¦ÌP=7‰î?þð­ú09¶Q–5ø&§é…«»‡Wô‹åʾ^Ø\o}F4-KVâ5QEe’}CÞÿˆ¼a%P z‚Äݳß™Ør̺¤;¹ö¨å8êXõne]6¥Ùw®QqºëÙá jAÉÈÃëbóñ ´ÃuÀN¢Çç5«5ê7«\kòu§µ:0* ‡U°çóqO*[„eÔjA1,xâñÒ¬ãƒvrG àæ ›yÎ Ce…~dC OB4¸¿¢¦÷к±<.=mKbuÄ*ÄJOSV%½=–ñ41"Py…ø;±¨êΑQ ¯œRÏÞ"XûŽv=Ø V:>‚O¹ŠxksÐÖp§;Å×רƒ„ÎmÈ‚%è%QõŽá~£ôXBÍE•Ëø’ÑJ‹±A5çñ'Ðî?Ë*МueƒdJ{j/C1ŒÍÛŸ¼ÇårU"ºöa/0ó·^Ї߶d'A½’Ea…ä‡Z5ß84³hl‰ÁßvÔ[0 §ø@°ÜS®0Øn5ËUMà8B>‡îGàÔ.%p´û§mÜó#¯‹M>;!«öö$JâWSʺ^vY«“[VO:>»VP¸Æù¦¾r€kSÊ\ØóЀƇ)°}'pL`zZeñÏás&·ûãVó}³¦4áÌžÁ•³jØ¡mâå¶Çê60ÿ DTË «÷háÖÎêÎò€AÄ1r¨GS+]›,áÕœ"Ê,¥“+é%$¦¼$2“äçRšÜµŠËÛ=Vl&Ø ±p0ª×AA}¯Ü^b *{ý§'Óƒ'ÓÏìIÿ)qãLõl ÖdÕûúüf#5•f_Øãó)ù;‘|;7jÃæx, ­6ü‚Yk¦\x®<¯Ù³'ÏϰþÄ¢´Úr¼ëpvøÂ|s¶¾Þæ˜/aþ}¡)%¤FñÎjÁó ©Fy2³Wöˆ p'»2‚‘g:¿“I)Ëö†Î Hl‡ryNå¾ânÝ~Aî”v#—ª¶såDŠ9š¼B¯Á•Ï]?×0÷½d·þ%}€íUwÔ¯7ó)«:Œ¯;qa½Îån¸ïÒ@a«­››¦pæ6vä}ñü\ïB{.æÙŠ$·Žî¶Ùªõr±|¶\s1‚::qâï*Ee‘R¢Âð$MQu 9òæ¾ÍŒÌn‚- uS ̵´¾äkVŠ«²²+'\¯<µg€§ßþ5»1Þ¬‡×ô¶•ìÇÝݼǒ;§b+Àš°:ÓŠÒsƒ“'økq‰_ÄÀXö `¾¶:É×j à?ù" v,Yw©,É'mûöl®…°g©¬ø98¡æÜÉqD¾§(†Ãܹ Bl…Ü“ì€á62kb‹bÅ6]­32•ãÊì?”ÐÇÞ‹,ÇMg|’¡5„ Ðà ¯ÚÅ-pçÝâ«Ã‹’!eÔ–ïÅ«h‘:ºLÄóˆ•^S{¤¨H…ž›ˆ¶'gL%Q¾{ $Ü\"Œ¢­D!é€V:¶m½PZü™ÛhŸÚž[,Öí¶šµ”mÛ“sð I5ÊžƒlÔc!úT“¶Ž@J-bµ¤ã%Z‰ãÙà€ƒÏgLNU‡fÄqYXãæs®°F±ÉÔ¶¿@ð ¸ËԮݨbÒæ½ N€%­¤$¨]:B ñ|ø&Æ.à™¿? ˆÏìщ9~ÑO? @½¨Eª<‰¡ß´Åyª§q|º±=xøšÌ•Ò”>fËÔÆW®^±UuÔQöEnŠŒoˆŸ‹ÖŠÖK*m5šrHcvpAù«;=pózm,$.“ƒ«ç]ªIBW“jïŠê\ã=ûŠè‘Ñ3”\Âkíôž&MS¾Ee›*‹ÒåÊÚÚ—¥„a*.è·À/þʱ‘ÄÚ®ŠÃéֆÈ©vĵPÄYÍ[Þ«RŠp¥çñZÖ'_ÿJ~#¸ÚŒ¹g£aÝ< 4ÖZ`ˆO‚€s\ÂÖN,€ûÍ?ŒšƒÐ.4¹…NÐFÁ“Õ!o†TG•_“¾€7};¡'‡S[`ì(ÚI²æöP ¾mc²KL t±¶|ÿ‹=s@í;¾>¯ZÒ£Ý4U£”\§L cÂ6(´—o <ûÝ3Dîx£ìÀ †Ù‚„IA™ †ŠÀ’‰æ@>­ áT˜Æ],`W$aOWðŒ²…ç‚œ²âÔÛÂzKOã=®ãS.R^Èâ0*$ž¶èy&-ä ÜÁlNqï8Û¤›™;™‰ØG¹T‹b ÏwPnâÐ^…‡²4’kVÅ ŽT"›+h3•Š)L4¥é‹>Qóg ¹ûÊ<•^ÏCè/ÝN™­<Œg%´5IxhFæð<.U-"©a°ÙUQ¯ó+Wp´UB)fÒŸ`Ϥ`”T(ä•€ƒËqMßÐ7Ñ_üWX¢¥µ–*%¯Z\ ]Àþ •¡áTð˜üÜCA…!ˆUeL9ÎC¡úä‹Û+2©À°qn`Ñ£ÛWGðIòµø´¬K›«¤±vЙ ªUYT_ÁD²†«žOáç0àí{[aÏ¢vuB÷Œ%M@Ï»v¦ ƒ[ðÎ&ž)•„Èÿ`u^¼§ÔΞ—“:<ÄuFGjgœUúðâ]ùaüÅ™j» É•éLÉúÈL%š˜½Ù­Ò]Îäy½N?gux€ö1®·vä)$Zsùˆá]ùÀ°&=+ðÔDØßÿÎåõ ¦ª p¬ÏýÀIHǨ„/¬œ$ˆ-†÷×N(}Ǽ‹j| ˜RâtCQÎ@…”aðqm\Ñéoi D¦þø@oxÈ*H“€J?-¸æïx9u˜r ö,Â5t|ƒ´«Æ yÃ@P¼#ˆæ1!Š>5 2’4 ɧºPÆ> «ÆÔ1Y€4Æ] »åDÌñþïò ØÀ Zlo±O£vn”)!³}zìißrÓñ½º2v:ø1Ìÿ~JÃy´y ¥O)>lþ’KQPß騾ÈXA”¸%p¤ }¿¡ü7îu h€š¶iÀ¸ w’£Â¥º+aàà –b³žT"# õ!  Ý¨Md4¶¼Q‡*ªºt|Wø$øŒ „\ “EQM¦b,J¤©låÒ‘»¡¿âÆ•õrŠÂ("Òtr³8>ºlПësüà7ÔчêüÀ˜ƒaö•ÓÇ Î(€ Æ>¹}ÿOy' \âq²ÒOGŸ+æÃã´‡/>gáx™þË´‡¯>GœÓ¹‘Ô—+ˆi!7”ˆ§é&õ(—Aø]ò83—½QaQ€ •«à6vÅÀ˜ÝŸÉª?¹ŸÉíùù¶fú—ô)Ôbá)¹Æd8o>ŽYÌôh0À #ª-±ÏÔgþÒN .DYܨzŸ H¢bC’Ø{˜}¥À?zÖÕ¦Ò»0ô£E±¾%—®î°ÉÏx±’^Tkb=É$¡.X€é°¬¶ rÜ×µ­jN?*•„ …NR6©[p"Æ5¼\âhUC6>cGÍæñr?þ J0€YáCuút+"åt$â”ÍÁB%ãuÙ@Oˆ’¼R”ÀÊáaŠp77 @‘{ÏI_éİSi–ÿnó”Æ"‘à8bk¶¨ Š]³[Qˆ½LÊ @º3 *å/²¦e5%°)¿´à#ØÑ¡ƒWUSs‹‡NjVhqè¾sÀd¹l°»IZ“95oJžo¬ @cpå†:y—ÓÐrjŽŠ¡ o¶[¥©©ÅxSæm\ÆÑ ä†³*êÆÎŒƒ(G»˜*©úX4g§›Õ %²‘Ýù$¦|£ùÞª7Ñ>ìw[àEŠë>ÕôR}8 TöCß6‹×óЭîÀÞ‚{¤B.Iïºe€Œ*öÈjlƒ,*N؉Cl½ÐÔJ1ƒþªg{–d÷* wp:z&þÙu…=‘G½QƒB‰qrGíb§=ƒ—tÔíO?E[¸ýiÅ䱬¥ïÏɪg0¶¼° ROÚ =‹¤ 0ÙŸÈìNŠ£‡OoŠÆ¼¤¿ÛÜ.B¤-† ¸[\ú˜ú}r;ÚûÖ¥†‡/ÿŽaÈìSì¬ôÈèkÛ}gFÎxè¤*hàCRŸÌzðoxÕ¼­‰Óºæ¼©Ð›œ%_Ð@¥}yÈ1·gk|Ö¼° &¾g¯ä!\z:Å? 𚾂5¬>—Áâ’nœdýœ–RÆŒ5/ÊZ”é˘ïËMq¢+ª4\@´=ºWsÇK4Ó㈠ú‘†i°žË,ºµwfÓ ü—s±;&óWÿF>iô?‹‘c²òûs4Ò¿K#XžÆœÒI¦æ…wÇÕ¼&ïÿê`&;BLfÇ5íTïÍÙrT—µwzè' µ‘3ž‹í¶åA÷{2…Z8eR–̽ïÁ ñ¿6題À¾Ñ’M$Ã1š‰ÒE'@PÍÌü!‰&8§X|RE׊ï0§ ùîåN›=f!ÖB„ŸFRæÔu~þ.ü‰ ¥LºÜîm‘N®:w€¶!yÒ3Á rF§•z˜ÏJ LoP³ ª}êFÞ*µ[Y^jÎ ßo/ò<©°^Ííë@„ågõyÿôœ þùGºcX1õ¹Õ}sfE¸rÇr!úL¥sŸÃñ¿èuúþɵÈ]$$ ›B¬;OÛ üÄ¢ðãPÄY‘‹+Ê¢y1* ò êÏå%ü&Ôœ/¥üS<=dÉY¯xTÍÜÆE½wXë÷ä|s‰8®¿UlàÆ òÎQÍÙà­0þ•F›о’¹€Ï·¨æ¦MÜTn‹;°ìæ`HÕˆ$SÅr{K#ª P„¿Ä37<ÔL9œØ,$‚[òöLr¦n+ã®ûTÓo¯1jMÐ@¤uĤ‹6ªåÉ–w¢¥p|WäHƒÄË£¾~±ÆÛ“íx˜ÇËæ'­ó–‡UsŸG¯*`§y[änP&î—|ÒÈ™Xâg^‡·Ep5‹£ìB©ï-ˆvx Á Ý qωV`ª‰ØÖ§¬‡WOü¹Ðµv9çŒYg^•¹åeÞ¤»Q EŠIâȹ¯#ÄâAƒöh0DkÞ Ó?zô(kÔyuJßeª¤7( ÍßY°Þí}Ô‰¾ñDp-²ÓE¸Þì+R!Ä«ç ßv8ÆŒèH4H½ù5w5ª%øðc¯ ²°Í«×ÀËŽñþ¬ß­5ð.Ûô÷ÂïÐlÀò•†[G×Zû½«ö~²o7ScãÌÒ+š.¹WÜg: áïHm×t"±×‰7`z™È—Ef¤¼!;»qöjz>‰˜Ó1örDÝm”ÈjÉúŠIøMݯ5Hê…ÝFtÿ´¼þÅÚÍo¯)ÔÜÞÅÇ“S”IiNovGž Ø8ñ‡pÿÉÒ™ÀÎÜ™k ¬5½¥ê—noÊíäÙ¬y|„:¤¹Bwö!>a—Ë zdÜ Âì ÂUkHlóœYzD퉰z™™6o"Dò¡ïª—F¬å‚Gq§ Btr¯ãÎïÍ[ÎŒ{Ñ31¢#ÁÇmuÇzµÀ\2.Q/(=åE…d q©„=sn\@å]«ž §¯öÏèXÎE%ÛtMßân¶F_Ï›S,Ò»‚¹á6µ·×éëµ^íÌjYC+ryåÔ—‡¸¹×€dKxR·—ö¥;wñƈj¸=þP{׌2mžÑ€U†Á¸1‘j‘‘ZqÙÈ3h4Ö^za]],Ïùáaä+ˆäë%?¾ðÒñ­Ò Dàá © OÎA4D+¬Uzá”5UÐ<™ìËþ鸘l´Œ‘Ú,JI¯Ûöµ;áæx^H,s‘ r"k\¸‡oztjÕ)#øH¾Á¿ùë­9š‘£#ê( ãK®2ۓ˽ÿqÜë~;s–ˆKmþ²vÁ…啬dŠ)ÒåÅpŸ·;ÄÃ>ƒL*Ú!jXÁ»q÷ü¼Õ5…äùyOV$ûeǶ:ïk-(Ū9ÝíŠ$¨tP9 N§uOmgÆg‡Í™$^瀑0Ìkƒ°µp•B|…àòòíX„Wa¼Ãh))Ò_+ÒÝ`]‘ÎnÓèvÃ6'ÿÑÜðJÁ8ýuÇoL6³Žz3^5Ò“=™ßf¤gå.›rõ„M¤ òPª+†©L\Žž&)Í™œÛøÏ¸iüttûäèÅü66·M•BŠüýS¾Ïž)HÛÄüNöd[òkcM½ÞÄ+Ù6ûÒ¶¬¶·’¶8%˜¢¨SŸ,htcR»Ùǽô ¹q¿¼ó¶ ÍêÓÎÆkç§u95¥É:ÎMÄr"kâ)jrÏK½ e–0ziE,Ž&jZ“OšnG¯ÅÛük˜žq†Ò$ÉCz\ éñVH_Cúb+¤/‹!}™ŠTo3‹aù]–oùëëyÍjúM>ÚÂØÈTÎq! ë}…x}HëBb[ƒmêY,eí–åŒî©¦$8ýÔdÈdÝÛ$§ßKUÇ{þ ^®o{öµ³€ŒOêø:5$ˆÖyê¸6kò%â„S÷ncg›&\2m­ü¹2W»^(.R7rX†fpd¬ÅY¥`(Zñ·Ò½ßlwß7•çN=€¢×ymB⊘ûW­GùV.qï#xé°vPRäÛ»w>Äðµ}g$ߚƟ]ÅóŸËì¨CüEô ØITÞ‰QÓæÛAøü ´#â­>5AǤw•/m@ ºÅ‘UVT¯|(µ¹6€'8漬_ªôä=Ç}]ð”ýêÕ«—˜x^ž¥|õcìAÜ\þ(ý:™}ù„͈3*g«,ò7Ð vºÿÆ_SzõĉxÝëÈga ú -†6ž8Œ3¼¸ã±ˆ9NI®,áž½‚EçY9ߟ {ãùcuNä0a¼ 2}Z‘ÒÑ’œ–h‘âYNŒá~ʆ=êϸ ®ÐBs‰ൎp~q9W|:AÑT$q'¯d<†\Ÿú²¨ƒfD¡Øü‡»»ä›OÆ. #áˆÉM`Π’¡¤ Ç#Ñ&\%xç5V{8†õo#f'ª1?%ä+áH ÀS³­{¼¡i÷…í©a†¦cݪöœ.œÀ<ò&ðoð7éü1ÇŸ®3ÿI6´’è]JßÔH$È÷Ö ;°ö¤0)§Ëñ Õ8WKÄNòFÎ †I˜ÝŠÆMÑQ[NUVzœXÖAÍJ§>7וx/°°¼Æê}ý¥˜&·‰x‘Ýúá¯p/eÊ31åO8x`;ð6݇Pè¿hÖßfjï;ÊŠ÷Yý 8©*|·Wa‡?qŸ&G ±ú²¶]Ñ´†ëµ¾ÏÆõ(YèÖ«¯´o þSÝžÂÍ7plüw²XtHF‚ò÷^ºÅu.Ê2ƒ‰ ÄÉrâîÎ#Ô}ž°Á,¥D›òС“3'FÕél²óÛ󦱙CY²qk7{îð¬lÑGåŒ PU¬ÞEÝ%?ÊÙ’Eíñt-岯6jp ë)á5î…P=-* k ŠÎñ;!s“Z°Þ†¬ ®ë iÿt‰f: ¡Ù¼îÞà#€æ(ðQÛ«¥èrÌ d @?uŸ0¼×É mV̧Þg7Í]j (ñ ƒ“¹ñUGžó¹¦¼Rø’šâI¡<5’O°*º-bÃxYÊ]sµcZªñÀè/_Á\$yWa/ àû.Ä:6¬&ÑbKle–ƒŒ¡Md=˜)ŠHõpFy؃] Œ³ÍN«ç@gšø+g @Iü¤ÏñÒ Ÿ~®É¨fJ¬-°¯Ã ¹‘(É…Xû~FÕú­®Ûx¡+7ßðÎS›ôT­9OŒº±lfuð®2tŠB“=‡È(.W˜évêÈ„˜ØŒC~©À¸V`ààŽAEô¿LTKårm_ä[™ 3B¸÷ú¦—&ÑÎ{èïÓZ„Ö@ɳG*²Þ)’0ôW\á(Q<~¹]ÒãÑÆ±|ß5)c5 ×^lŠ-?|˜ ï3QÊh lÙbpéñB“ÓS:23…ÑPIù×TN³ ‘µ€ºâèiê"5Ôʽž…ÈÕÜ’HÄË”þ>J[ƒrä¬x‘³†_?bÃ…{Þ¹ÕKy³‚Dètø=FyïA½2ßÓn~ècbµ”b†'|2fG“caй½ºŽ †ãaÖ:GNÜŸ=Øò 3ÇOP4ú`ãø`T¯7¿£ìpËPäs¦2^EAÙȽãA´u`(š,–À¥B{6 ZImífîj…mmîk ™û…§"s†¼!ùfƒ¿Ÿ •`8êì^ÚõàZ=•Nf«h|Á´…8¯(Ë!å?”…tÄûK2,X( I›«bIòaÐÔwªÈ1…}ð¨gÜ+Aبÿ¥Œcyå’ûVÙ†BC¹½9þ“†ß²l꣓DÕ1qx¨n^\ñlBd¦€¼´:upÜ4;ü¬¨î¨>9Ÿ²Á°—\|U…›q–«gÏt^­ßA&3™“_$j{zªÃ~ý.šÜÒ±'3™ÒSâÀR"u.çtYü¾œûĬfèÞŒ ™ø5§îÅÇT¿€W›{©@Ž×þãüm‹Ê4‹ =\ö¿ÔƒËbúùË"ˆ¤Fh̘4J$Áíctkõ° ½§¯í,ñ>?âc û©ä†C½Â/ÇzøxA¤x>NѺ¿XâõŽ*JˆíeÂ‚ÎøS««b—ÔÖýÞJvÜ I¯ÄŸñع¥U¶Ôü¹ÞäY š?7ëp]–ðÑõuÔ³(º1=HÁz‡ºó.ÜʽzÅ|ŒÉ[cŽ‹×Û„m‡¿Êb–0QL@¼”™òsgÉÙbîÜ T4pÝæÆµø(þž»¬œ¸CéÁ_ZB׬ˆ8èžA*WtÃò÷ÝKHÎÉÓ ¢0€çð·˜sã×Àò,ØOcÎgŒüe¥8þ²p¯v‘òõw”Ⴎ蛣d,Ó¯ÃcÉáÑh" ± –?>ꔲ|°Ï×ù ãø,ŽlI×c‰wQ¢û§–Ï«<ȮلŸþÕ‚° W @%ü|èÏËWüFõìܶñ1œÐµÁtét”Ü@\î\ýÁŸýÕ9ؘ±AâêO%ƒù ‚Dû§1Ør2´&ŒÌFÑ«Ët„åKù×çfcAä ºnBÆÉ©˜ qV|Íæ1‚Ç…ˆ©©î I ŒºeߢçK²µÓ'™'M°“pNŒ!nÅ]í&×@$’(õž½×Q]Ê EOÅpöµ|‘3õ@}«ƒ'i€ ¥ÄêÖ‡-ˆ§b²‡×F(›{U¬¢î:\®Ã¨7/C§Fžnöúþ‰f£,W“—(Ú’JNfêV2œïh}YÝõFÇ­Têñš \¹üé賌W<ÉLX½æã ÌV硘_|æÎËÆÙ[]Å1:%«àƒ#å],ʃÿ¾Û’ó ÁÄý¸îø?•ë’ù3 ‹Œÿ†á²:ç]c¼èÂb3üéøWŸã³!B™ˆÎ‹}ÆpõÚ³jŒÉ÷ö³8þ¼¨«´ZŽ Ë0QKò}yÏŸ¿€ç™qö9MÒ!^µù}¨`‘6½¤:ë‰6%ßOŒ6ý’žÿé_ˆWŘ"õ2:VR8p´z ³÷‹MZ1ï7©(nÎã_¶¿½.'ü>¦18y00Ç@ ò!Þ˜ý‹.(Ólx ¦øŸõc¿Ð:ýÝûFã] Ñß+Bl®“WøÚpMPÌBÔ»·Àü•‚âŠÑ”öÂxÞ‚«Ø;ëÅ¥Pwh ‘9—P1f@o3_@u›‡G4ƒjTÓ¡úYõöï[o¿P½i´ýSãÈ© ,ìÛq¼Pü*—ȸIf»ð2™màôÚ®tÈ–Í 2ÙÍ0n¦Á7—z°'ì~2©š³.*U-k‰lußbn¾fúŒ çr}ÓO Ù"–ˆr_Ë÷AEÖs×®—£-qŒ: œ¤ÿ7™œÇ)#†ÛÞsë-zýî¿#µ¼Dc@£j¤ŽÁ í–b»R±E‹eïå“qò¨™xëxö‡æ92 íjƒ™S±ænU,ÍA¸ù§$Úø¼ØŠÚ˜PB³ëìdk¬Çk¦Kþ>X_|4àç l¸hèNDš€öíñÖz? _aNמæ´Ü Ùeqü9§É/)ÚýÊ\âPT¯†™™à<˜F£g„œI›HF„C°š¤åé,Xš³$þÝP¡‡>Ä ·,‘Î÷šé3Ú&âêX:VñÚŒºË›£èŠ”ïù!YëªQX5o:\{m0‹E:˜Šl «”MÐE{'„ðúxÉ?W÷=w‹&/Åk˵¹"¶×…ÓY°å_^SLÉ%‹»Seò¿F$¿ø¿H~°HþÇQõÿRåÿRå_'U †È~ɱWõM[c¢‚ãÁHH¾½ÉÓ»(Ñ:ˆEô–„?´Lus>W3bÆn5rB¼cü2ÇûÃw9-åºÌ“&J²\îYˆ ë1Ãë’ÔŽy—þƒ¹ áÒRøÄP¦×„!s}‘æ8:ÛdÛ.¤»KvC¯øïHòCözŸIÚãus3—[˲-˲,Ë’zÄà±{¡Wîš*;V}õ¨;ÔÍѧàP¹¥àÒŒDfÓ¿C¹˜ß’»~”eèÛúßRõQÖRQŒ¯±lŠ`j—jzwqòUá ¡ÑX-÷Ñb€Ê;‚ Æ=Ä'¹_UW`Ê)›üºËÕýP½’ïP¢ QâK 3ÁŒ÷7?%¦ É5¾µØ"ÝmG¥‰Ž©Y³9†ËŽR µƒº{lÇåüAøwÙãPÌ’ôG"%7«]cíÙBw …æd¾P™pLØ všòƒ*YàQFàZ·I£cuÕGêòWò¶Öq³%€uwÞsÄßöûÛf%Lën'wpí" ¿M–@Ñ‹à:”þ¬ Ä)vqÜ„pEž,ÁfÜï·š+ðÜ_ÌiáÜ ô´Åïd¶.@— ìýΦìƒÞ •d5à¸æÉ}ünHj_l=1!áß62•À0 ¾0›ÓÑhvwÎq•๠w¥oZcûO¼¢¡‡óŠÿþQï`€uÏW˜ƒÝ—,)¿d)-l7U b,OhSvT§68ž†ãðÁb ®È•Ìc\Ñw@,„ù¾ŸXL’¨z¡Y÷ò+ü<Oï+ ¿¦®/x(Y)f"7XO‚åoГs©Û(œQ—C€n™áò¾ó’ÉÈs©a¢> 'Iõ Š]‰Noð1é7•F”ûQ¬ëüýNAñ’‚¾(ä7ð\Øi!Ü» öÇ9¨TœUø‚PBt+œTh®á»zi°g¡™91Š›0÷ÎL/î‚ÆAÁþDd|ò$˜øAó¨9 õ$Û\¯‹þvŽ¥'‰7“ñtÄG‰GTÌ©¥'RL6ÓÌÿªõÓÒ{cÝúi”ã§$ÊÚÚq%)è"7æ^©Á•¤š:d÷áþ§:†ÓŽb2:uÖ8Ü›†Ù$è†ä³©½’ô—öV°mÝÄá\úÎÒok4ÅÊÝù¯õÛÙ)é·6uwD+ú:ÀdPr¾<›üøÌùàêV?Z “ñ}”ߎUÜ …™ÐBÔ½R™@Õ'™ÏN¯îž͹/Üh:pž¥+k´ây5Æ“ v£º4¹×̇VôÚL "ëè6«¤g18WÛ°–H+*Ûã!õ,œWm;{EAÃî8Jg—h¿û9üÍbƒ½b|þnw‰Ï‹ÛÄùççšî,9|O"²…­¤±Óÿï%k’·%}`èÖ?z+©cW!Ì#Îr¨þ{I[©ß)úÿ& z úÿŒ­ îpô2˜«ÛÆ«TïCš­:î:;•{Î;ÞP×½ÐÛìd‡\À5ÝÕf•PÀµNTBÆÿEËßT´ðb®•˜Øí&ªæZÚ÷×z¼Í‹ô þèùí#Cî¯tS¹xP’VE5ŽM0èݯ9N7Öׯɵ-Èd'í¨1þôLK¶>…üf4”ðLoIÎÒ­»éTSëÄDV&—‰E¦¡ô¥ÁʨÄ/‰ù èWo# ¿cŠ$ÄÍâC›å`,jvÄç\ölóø¦nXSÇ9É Yj"]ÂWÏç7õÜ–4è¥gÔÌ/“$ËuðSÝj3Ó"4%¹¾1| þ‹U¨Ã÷›âG?šy­G]ÐF©¬3K ‰:n岂xƒ!³ S”Õ.ˆâL˜|0Š\0€±Ï+bb(‘He˜A ‘Rn<ÙM9·‡¿E‚¹îƒÙJ­eÄGæa5nHb`ô½5F«Cµ¦5Ñþ?RÁþ =ÕD‹ò{d#Žè‰Œ»Ú¢Î<(vëðþ©JVõißí@§¦uLÄñ•ØÇ0¶4’Ú]ì+l’‰ÕÌÅêms”We¨:õìÛã³7TÏÛª‹DêÔè|soꪲ2ß A»Þ‹©ïõÕKZ‘L͵#š›µ,ÀØ»"ùZÅÛ-ˆ¿ÆWNû~]¢39~¼q_j“ØöbŽwâpƒÆÄ$ß ¤º<½5ZIM¥ZÿîÂ.äsrgïð-jAX7tòê“› ª:äÆˆ˜bÄ[¢v‘%qæ¨(v¸êùf]…t†£÷DÕˆâ[³`–ƒj£]IwÑz‹× âQøçrSÔŽ‹F‹µ«‚Í(Ô"¡£ým™@sA.2{„©Àñ¶©Od¥çP"¥ÄDëÄrÿ=L´ jMÁ÷MÄvÉÇO·ÝtOôÏ7¢âœ'¾TÙªcRö ÉwÞxÉ[ÞÔ4ê#Sºš¯êqø™¢™<߀2mü®ÖÄôæV½-¬Ü™Üªp] ©w¡G…¾ f@d§f¹§¸¥(º‰mºôÀÜškäò»;èúgãV©áÑáéÑèøx4Húr@?:¯‚óCó aºUŠK••£“¤ô0êAU`¤² Œ~À\úÜ_o‹s¶ºizñ›(†§™ñÙËÝ@v«NXƒ‚øGsPöçâÙL=†~~Ï€_ùK×½±¸G¯2|95—F$«'î˜FC,ÙŽ‘< –®öÓ¶Ým±@èu{Ò¡L{_é.§Ndì±é$¹¢h°ææ} ts:ûò*|¤FáCY»ºå’&µ>Ö¦iBÕĨyaÙ×fqs –ñ©ôÃ9øâ†Ø]ÚþóUL dÒ4LNKžßȸø?tå2J¢ÈVWq˜Ëj”M7ŒéŒŒp^@,zÕ´Þ™³¸4Jƒ:Õ®wIø~Õiu"ŸéCuT/ÆåÇ“”§¤ÚºÐ›Ô§6šVZJRÛÅZÆyÓ¦®ª †·C‡d•Œâw0ñÁÌ´œ¥á,ºŽfâ7»VB@_Ä\’…õªÂдáÛÜ*QX–7«»0Î?«,ù¼ãÒ©¿möw¿Ð‘ƒµLæ‹.ÌP4ž· ÅÖÁŒÞ©/Õu—â§É½ír]±¨+$D‹y͸ÃÄ—øqrï3'õ½…T÷zƒ,ç{AøXÇåÀw1ÚÊã†]ÆRõF–.vÞ3å­’&À0yDZÃU¨ˆA ŠÑ=;ǯI~K´Ôű…ÂIÿ©ýbu¡ Áº†ÃWbžÌ2q§´52¢àTÉoÁCyÍSè&Ár× »·-íwC>›Él¶ZªX^Võ®&Œ\£Y&ÅžÃòÚœº·Ýùª~êÞÂÊŒ|é>r/X½˜}KÙÑ‚© fB¾š»ë³`Ñÿ6¾GoôfžqBtQî ¾ ã—©õ¤¼Âùs v×r;l"È++Oô ºÒ¢rž'·;MvéìI=‘%¨…@½h/ÜÓ®i}©úŸ€I¡·¢›³U¿ì=P;›>tÙ ~L+[Q¡ŸJ;ñÔØç=ÏÂo@ˆ}~—‰Öo?*7Õó±¼¼ßoÍDš`låå„M’Œç’Ô"kLë»\'w“ÖÏSS_w7ãÃøyQj€–$ ÿtÏ 8}Ì/u ù*ƨ¿àñ,f8&Yëèôðåñœ¾N‡'ãÓíʸ~æ;pBS…òç òtw˜¬rÌïðyžãáÍú×8Âϳ÷§I|ˆÍ´vÓÏaèJ•¨[(?]GG“ñù„p6§"é²zy8NÆ/aŸ¸I€èW§ÝùÏŽ^‰(»¢ïr!ÊpàèÒÕšÍy&³yÕšN†J‚*(hÁà?fMS|Á‚S… ñ0G3ØÇQüºŠTï|ä®âûKQ¨M O6†©ÝÝØ¤å8ÌÐ¤Èœí²›ál…¾ä`œ-£4O–’te“v9?czñz ÇNè>(º²wkMghç_´Æè¯Ü”ó|]­rô€”€ÈêWa 3@Pİ—¯P·:V*üNœhý”¿úѾÇÇ£ûôŽ|¬ª‘.~9<<x=ŽS?÷õ¿òŸ-OwPÑ}@]_e/öß~¸ÿÅ[Ô¶DÏ>tõ±|­©14™§ç]N’èUâøÒ°áøôÛ³É EÙàЭÝëdž¼gH™iPÛï4áÞ°£ P×FÃÑPãÇj!¬>š>ó—‡C£C¼>ÝÏÉJAYUšö°]r Z]<€ ì:z;ý *c£›²ÀwC@¥ö;KñBá¶ä7 ÷NèÚRaè ìZýƒ1B$1‹¯õÝÑ©#X_Ûnt÷L´B­´Ý(V!ì´ûµLúùw Hèy‚e=o½9= +íÙäñ±¬ÿ¥öŸ› !˜ ªý¾KcM†ˆÞmærjâ<¹…AEpoß.•ù¹j1”òÔ‡™Š¿…X9—P ƒ…UDc.ÌV•"AŸ?ïÞÒ£tøkÚŸV[üIy ¸ÍæÿPKý[ŒAS’Hýxtap-win32-source-2.1/types.h­XYÓ0~Gâ?Xð±Àrƒ*!…4Kmš”S(rwkH탥 øí|ã$MÚ.Ç+´{Æs|3žsëÚÅ ìc¡åßx-ÕÝ;·š¯÷ØÌbŸD®DÊ’\~9+5ËrýE&‚}‘yYñ”•<3"~÷“ˆ/2lY©¸”ZñT–¦ƒŽDŸ7q¸µa% kÈ>㓪Èd.¶Ø°r%˜íúNmbc †|-!ëÅMˆK ­ö¥ºÊ¡ÜÅÒÖÙ&—§«’]±¯²;ÇÇwnÜ9¾}̦™P¯|…"^)êS)Š#æªøæQ-Œ«„Îç"¼€M•JDnÌzæŒ)ÈŒ;ìJ![ˆTŸ]Ý3…p;ÍùšÄ,spzYžñ\ ØFW,æ ÒY”¹\T%¬-Ié-³µNärc$Ñn§ºùº`zYÛáÍÙ3¡DŽøÕ"•1wUˆÎ¼ÆØB Ū÷„, j‹°ÒPÂ)Zp¢³5A¬Œ”•Î>xIvžÉ4¬*IJJÁÎ^»áh:™å½e¯­ÙÌò·°—+ ªø"jar¥²aQÎå̲–1qfö‡¬§îØ ß2@t↞ìd:CÊúÖ,tíùØš1>ó§s“±@kDü ¬¥A $¢ä2íçç[Ä©€‘iÂVü‹@¼b!¿ÀDÎb$Öß#ÑàŸjujü{‡©É#`)S¤ûÔëzÏmœV ”l)[ø)JWL.™Òå;Ëe )úQÝIíû‘öë *ý”Ç∉¸{÷øˆ=ÕEI싱ã;·oß¾qûîñCÆæE‡o]¼pñÂe¹DF.©‚Dá[ß ¢¡sâzÎ$ìK%It®Üd‚ÎÁ*.Yô²ú~ñä§p}«6è–…üÖ_Æ<ã1jIokÍ¿F[.ÿÕÔ28ÌßÀÆf ÎSòÌJx†û48—èóø“(wŽV 8öOBz¾iÌ÷†n¬ÙéíDAh…󀭣ϊDPò²*[Ή3tç0LPªuGðGo׶Ƈ¿Ú2æisnC汕$¹( öþÁ‡ÒÓj¹DÍxç>:¸¢12±ÞFÓYˆ`¥ór÷ð¦„ßÅ {αk{;¾– ß¿ÃØùZ E•¨éÖ-ÊŒ¶AèÅGFª´™Á›}¦€Qº×¡c×à¿¡˜å­Ý<£Eñ¡óʵhúô¹cÃÒ94½¨xñӧ 1í%VM£Ž@!j윣èÓ­Juüi×¼­äÀw½h<µ_@€±i ^#öét:v,ûV 3Ȥ"Yç¨Xäµx nÅ©.DÃP mÐÊV\ S–Ød:o –Œµ‰s‚jüµæ@M.[„W¼@AFyÍÐ8¸ªL7ØLaÏ®™#ìAÊaŒ_k*„ñT‰„¬ÉÙ5ƒ˜Z¢çÚÓ!åýÌ5pΕ¤<–êÓ–©Sfç‚ÙcÚÅ…ªrkCan“:.SÌ)uFÔ_U”[kƼ(<×ù *©jU"7YMÂ«Ö ‘jzìFÿ$å§Å®Õ`r‹Y¥”T§ûñ4É6¿¨ÏD=ˆôd}»Î Æ7\Ð\´©[? 3.íŠvÍö0‹]%KÉSÔºÄhq}úà0-·ä:/»[ÕîÓr{Ó»Ëj®y·ü˯/(Ig¸ã—ñ§×|Ë~á„Qà¾s®Pa6Åú*»BÐ<¯lÏ_e×Yãê®$4“¹ÇŽ¿>:®ö¨F~4±‚Ìü\ùYŸ¸JVu—<€dXƒEWï†PËÐ2¤vµ®\‹º9§ÈŸÖáµ ô1ÇÚÖz ¶ýþ\ ì¿EÌõ¨Œý´ZÊ?à¶+ïdæ8Wäâ*Ò£%éD`îÙ°+´{tŽöšrãI XŽÏAôY{µÅ³^þÒ®!™s¹õݳ&ÎÔð‹< c!ŸoÖ­Ñ8byÛ­ŽÃ84±lk8$‡ð5Ø¿“жÄäÔÕƒÃn3‘Jfè¬q½žÓ`7ûzDU¿éÊ,éc`F,Ö"œÍ=Û Ý©Ù#Ç~±#õ^Åæ`ýIG…Âëá£F7 èO|%x²³; ç]Ñ‚v‡ ¯Ýh§ažžñ õ–†íʱB¼Dr©žçÏVøÕö´|²ÀªîtôáôVÈ‹ XÒPŒrYÜìaÝXÍꃖQi·zLl´AEßšßIëŽ[g™>#ÿˆŠé,8QWô½#®ZjSÄ3JÌ¥¾a>èÝ&v–•2غ~“M4 ¤®¿»™ã–Âå™Î?ý†´æEMrÂQ4r¬¡3«›R¨çÀðD»¡Ãa>GOsÍ“Wñœ¦;Ù>ÃYzoC):VÎ÷ÝJVq¡Ï.Ðözö¶Ž©´K©vW5Nò×Ú"™õ/Ú‘ç#‡G×<>Th^îQ)×¢o[å]TT™yqF:£Î[D SÞÑ{$ astap-win32-source-2.1/SOURCES.in `öƒèSØÍPσèSØÍPσèSØÍPK?ý[ŒAñ1äƒEcZ$ Üwtap-win32-source-2.1/tapdrvr.c ¨+éSØÍ+éSØÍ+éSØÍPK?ý[ŒAS’Hýx$ ›½tap-win32-source-2.1/types.h 0…)éSØÍ0…)éSØÍ0…)éSØÍPKo ÒÅgnunet-0.10.1/contrib/gnunet_pyexpect.py.in0000644000175000017500000000543112221077151015653 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Testcase for gnunet-peerinfo from __future__ import print_function import os import re import subprocess import sys import shutil import time class pexpect (object): def __init__ (self): super (pexpect, self).__init__ () def spawn (self, stdin, arglist, *pargs, **kwargs): env = kwargs.pop ('env', None) if env is None: env = os.environ.copy () # This messes up some testcases, disable log redirection env.pop ('GNUNET_FORCE_LOGFILE', None) self.proc = subprocess.Popen (arglist, *pargs, env=env, **kwargs) if self.proc is None: print ("Failed to spawn a process {0}".format (arglist)) sys.exit (1) if stdin is not None: self.stdo, self.stde = self.proc.communicate (stdin) else: self.stdo, self.stde = self.proc.communicate () return self.proc def expect (self, s, r, flags=0): stream = self.stdo if s == 'stdout' else self.stde if isinstance (r, str): if r == "EOF": if len (stream) == 0: return True else: print ("Failed to find `{1}' in {0}, which is `{2}' ({3})".format (s, r, stream, len (stream))) sys.exit (2) raise ValueError ("Argument `r' should be an instance of re.RegexObject or a special string, but is `{0}'".format (r)) m = r.search (stream, flags) if not m: print ("Failed to find `{1}' in {0}, which is is `{2}'".format (s, r.pattern, stream)) sys.exit (2) stream = stream[m.end ():] if s == 'stdout': self.stdo = stream else: self.stde = stream return m def read (self, s, size=-1): stream = self.stdo if s == 'stdout' else self.stde result = "" if size < 0: result = stream new_stream = "" else: result = stream[0:size] new_stream = stream[size:] if s == 'stdout': self.stdo = new_stream else: self.stde = new_stream return result gnunet-0.10.1/contrib/hellos/0000755000175000017500000000000012320755622013024 500000000000000gnunet-0.10.1/contrib/hellos/DPQIBOOJV8QBS3FGJ6B0K5NTSQ9SULV45H5KCR4HU7PQ64N8Q9F00000644000175000017500000000057412236654562022031 00000000000000|nu%ãú4¾ ð™– ýæ“ÏWä,KFl‘ñó£èÒ^https_client;ÿÿÿÿÿÿÿÿ3https://[2001:4ca0:2001:42:225:90ff:fe6b:d60]:4433https_client#ÿÿÿÿÿÿÿÿhttps://131.159.74.67:4433http_client:ÿÿÿÿÿÿÿÿ2http://[2001:4ca0:2001:42:225:90ff:fe6b:d60]:1080http_client"ÿÿÿÿÿÿÿÿhttp://131.159.74.67:1080tcpÿÿÿÿÿÿÿÿ L  B%ÿþk `&tcp ÿÿÿÿÿÿÿÿƒŸJC&gnunet-0.10.1/contrib/hellos/R8TTJ9GAL5VIFOFNM8KNT3D83BVQPBNRHJSSD0IME63V821906EG0000644000175000017500000000057612236654562021766 00000000000000~Ú;Ù¦ ©'á÷²)~¨ÿ¬®ûŒùÆ‚Vq‡ô)https_client<ÿÿÿÿÿÿÿÿ4https://[2001:4ca0:2001:11:226:b9ff:fe7d:84ed]:4433https_client#ÿÿÿÿÿÿÿÿhttps://131.159.20.52:4433http_client;ÿÿÿÿÿÿÿÿ3http://[2001:4ca0:2001:11:226:b9ff:fe7d:84ed]:1080http_client"ÿÿÿÿÿÿÿÿhttp://131.159.20.52:1080tcpÿÿÿÿÿÿÿÿ L  &¹ÿþ}„í&tcp ÿÿÿÿÿÿÿÿƒŸ4&gnunet-0.10.1/contrib/gns-bcd.html0000644000175000017500000031533612255773025013700 00000000000000 Create your GNU Name System Business Card

GNU Name System Business Card

Please fill in the information below to generate your business card.

gnunet-0.10.1/contrib/timeout_watchdog_w32.c0000644000175000017500000001210512225777501015666 00000000000000/* This file is part of GNUnet (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file contrib/timeout_watchdog_w32.c * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period * @author LRN */ #include #include #include int main (int argc, char *argv[]) { int i; DWORD wait_result; wchar_t *commandline; wchar_t **wargv; wchar_t *arg; unsigned int cmdlen; STARTUPINFOW start; PROCESS_INFORMATION proc; wchar_t wpath[MAX_PATH + 1]; wchar_t *pathbuf; DWORD pathbuf_len, alloc_len; wchar_t *ptr; wchar_t *non_const_filename; wchar_t *wcmd; int wargc; int timeout = 0; ssize_t wrote; HANDLE job; if (argc < 3) { printf ("arg 1: timeout in sec., arg 2: executable, arg arguments\n"); exit (1); } timeout = atoi (argv[1]); if (timeout == 0) timeout = 600; commandline = GetCommandLineW (); if (commandline == NULL) { printf ("Failed to get commandline: %lu\n", GetLastError ()); exit (2); } wargv = CommandLineToArgvW (commandline, &wargc); if (wargv == NULL || wargc <= 1) { printf ("Failed to get parse commandline: %lu\n", GetLastError ()); exit (3); } job = CreateJobObject (NULL, NULL); if (job == NULL) { printf ("Failed to create a job: %lu\n", GetLastError ()); exit (4); } pathbuf_len = GetEnvironmentVariableW (L"PATH", (wchar_t *) &pathbuf, 0); alloc_len = pathbuf_len + 1; pathbuf = malloc (alloc_len * sizeof (wchar_t)); ptr = pathbuf; alloc_len = GetEnvironmentVariableW (L"PATH", ptr, pathbuf_len); cmdlen = wcslen (wargv[2]); if (cmdlen < 5 || wcscmp (&wargv[2][cmdlen - 4], L".exe") != 0) { non_const_filename = malloc (sizeof (wchar_t) * (cmdlen + 5)); swprintf (non_const_filename, cmdlen + 5, L"%S.exe", wargv[2]); } else { non_const_filename = wcsdup (wargv[2]); } /* Check that this is the full path. If it isn't, search. */ if (non_const_filename[1] == L':') swprintf (wpath, sizeof (wpath) / sizeof (wchar_t), L"%S", non_const_filename); else if (!SearchPathW (pathbuf, non_const_filename, NULL, sizeof (wpath) / sizeof (wchar_t), wpath, NULL)) { printf ("Failed to get find executable: %lu\n", GetLastError ()); exit (5); } free (pathbuf); free (non_const_filename); cmdlen = wcslen (wpath) + 4; i = 3; while (NULL != (arg = wargv[i++])) cmdlen += wcslen (arg) + 4; wcmd = malloc (sizeof (wchar_t) * (cmdlen + 1)); wrote = 0; i = 2; while (NULL != (arg = wargv[i++])) { /* This is to escape trailing slash */ wchar_t arg_lastchar = arg[wcslen (arg) - 1]; if (wrote == 0) { wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\" ", wpath, arg_lastchar == L'\\' ? L"\\" : L""); } else { if (wcschr (arg, L' ') != NULL) wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\"%S", arg, arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" "); else wrote += swprintf (&wcmd[wrote], cmdlen + 1 - wrote, L"%S%S%S", arg, arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" "); } } LocalFree (wargv); memset (&start, 0, sizeof (start)); start.cb = sizeof (start); if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &start, &proc)) { wprintf (L"Failed to get spawn process `%S' with arguments `%S': %lu\n", wpath, wcmd, GetLastError ()); exit (6); } AssignProcessToJobObject (job, proc.hProcess); ResumeThread (proc.hThread); CloseHandle (proc.hThread); free (wcmd); wait_result = WaitForSingleObject (proc.hProcess, timeout * 1000); if (wait_result == WAIT_OBJECT_0) { DWORD status; wait_result = GetExitCodeProcess (proc.hProcess, &status); CloseHandle (proc.hProcess); if (wait_result != 0) { printf ("Test process exited with result %lu\n", status); TerminateJobObject (job, status); exit (status); } printf ("Test process exited (failed to obtain exit status)\n"); TerminateJobObject (job, 0); exit (0); } printf ("Child processes were killed after timeout of %u seconds\n", timeout); TerminateJobObject (job, 1); CloseHandle (proc.hProcess); exit (1); } /* end of timeout_watchdog_w32.c */ gnunet-0.10.1/contrib/gnunet-logo-color.png0000644000175000017500000001530311374167231015541 00000000000000‰PNG  IHDRIK<»ª×sBIT|dˆtEXtSoftwarewww.inkscape.org›î<UIDATxœÍœy\UåÖÇ¿ ˆIÀ&IQ Ò4Q1§½VZjjJÞR¯¦™Ú½·2›l0¯ šo£co™•e·;˜–³”©ék9¦¦¦Љà„Ê( ÀzÿX<6zðZÞõùðùè~Î~γ×^ÃoýÖóQUþDD"y@0ø^UO]ÜU™ø]ìˆHO`+„_ƒE䲋º0GäbZ’ˆÔ¦7c€Ö€›€ÑÀZçzŠª–\œU^DK‘ÛmÎúK, X $'%@_G¡GTõwýZ8¾4B±1ÀDà:Ï'™À| =ü{¯ùw³$I‘ÅÀ\`ÐXìTÕUݧª³1Eîæ3E¤µˆýË~w‘"²³„@à=`‹ªPÕ²sÍ¡ªÙªú Ð8,>‘f"rÉo¸|à7R’ˆD‰È3"²˜ lºïbÊÉ<Ÿ@¬ªUõ1 P | |$"·‹H øgÈS’ˆ„ŠÈY†äDà  30 ß”#UŠª¦«ê ì?V‹Èó"R_D.À#ñ…ÿIö:ÿŽßÍ:@H5æê…ÀXà²jÜô’lÌz{á80ç?ù;/œ$"M?b™g!ð5òÔljEä* +݈ÊK†À2à`—¯®)"Ä;kë ÔÀàÄLGÎÇÍ«c5 ±˜²H¦]ë€+ÿó°ÂÁÀaà H¾…¹f+àL\zV´t½ÈV/aÙòŸçªÆ—NÃÀ݇@[ <Å_0dýG æ2cðÀIFÊ–cîXã<ÃBP«¶¾Þ_ÀݘônŠUõ¤¯7‹È%"2HÞþ,SÕU-ô¾G #5À\æSàß"Ò^DBª±n+Ŭòï@] LDü}ÀWÓÍÆ\¢w‡à 4ÞÁðÍ àLá—ãTqAÜcW`îx øè„û¸þºÀÌõš‡0ËôÉ}UÒÍX±™\Üî(j°›¢€«çí@:szbñ«Ê…MIŸ‰Æaq1ÅùwCªˆ1@Œ‡‚€``ð*s!•4ÒyÐ<®Ýá(êAà2,Ý>¬rÞö˜y7ÂÇøå‹’<>Œ¹þ,(/ÃbÎ8Шç(óeÇ¢ƒë÷bõ >=¿JZ<Ô÷ºÞÈÁuùBŸt,®NáêãwÜ€Á‰,àQ| Ò𬠾{5v,­BAÎ=5ãX=gÁìë"Ž®tß…•“sŽ Åùa,‹mÄâß ð«Æ\~Žîò…qS„cñC€Zçš×—ìvWr/® jÏbœP¢óP¾É.Xu߸Ø‚¥ç$çÚ×Àý"áË|jÅòåÀx,YaîæV¦|…•L—žk^_jœ>Îb‹TµÈkìJþ³¨ODdÁرc'†„„Üœ——PR|àÀ¦NúÔ¡C‡^ÁÊ—±˜böa|Ñe@ºªv‘ÁÎÃv‘W€]Æ kÜ Aƒ#""b‚ƒƒ/IOOߟššúÂôéÓ¿‘XÌ?Æh•fXFÞ× Æ Å(àJÙ§.¤\ÎZ–88"KÛ[Tõ ×øD  ˜¦ª;D¤s§Næ$%%ªªßªU«hÑ¢ÙÙÙÔ®]›ãÇIvv6ÇŽË+((Ø>iÒ¤^À!U-‘1Ž’¦ªê.€:ÇßYXX˜““sªV­Z¡aaa\}õÕœ:uŠÝ»wÓ¤I6mÚ´áwÞ¹ »_b`µ7†ÅžPÕí.Ï÷%ððªî¯Jçr·Û±ôyËXÞÒ™ÓŸqãÆMûìãå –¥¤¤LÈÍÍH«V­ÈÈÈ ,,ì ¸ ª'DäSç¥î‰ŸãûEd–Å÷aîw†T¸‡c°=yÞògŒØÏQÕS¡¡¡™™™üãÿàСC;v,CßÇTu>ð`ûöíß¿í¶Û¦¤¤ðöÛo³wï^6mÚDZZ{öìáÛo¿eþüùÜzë­ <˜~ýúHnn.‹-ò«[·îcÏ=÷Ü#"r3÷»%%%sâããµ^½zlß¾   ÂÂÂÜ‚IXAYE—åeG‰uÝÆ+Y’Üþ‚q>•¬HDî°¬v @‹ŠŠ¤nݺԮ]›ÌÌÌ —dŒ1âò:„lذ™3gHDD”””PPP@=(-- &&†½{÷N:uؼy3'N”N¬S§ÎÑýû÷¿ ,xâ‰'Z…„„øýío#,,ŒÐÐPrssS½ŸIUÓDd-Vùïwþ<Ç÷‰È\ ¯3¶÷ŒgöN2"ò"V”þ°ÍSINšÜŒUÑ Ë3дiÓNFGG_’’’Bjj*-[¶ÔÏ>ûìîåË—/6lØÛAAAó²²$%%…f͚ѪU+ Àºuë¨[·.111lÛ¶Y³fQTTDpp0ùË_˜>}:×\s ‹-âàÁƒ´mÛ¶ìàÁƒÿ,((XÛµk×wæÌ™ã·víZz÷îM¯^½èÞ½{ˬ¬¬ ./?ãà“€õÞ±GDb°XÖÓ{ÜÏëƒQX!;÷XÔ#¯¾Ã\€’’’¥¥¥œ:uŠÕ«W“-ݺu›÷ù矗´k×îñ+VHXX ,`úôé :”W^y…;ôôtbbbÈËËã‡~à‰'ž 44”¶mÛ²iÓ&âãã cÆŒtïÞüü|¿èèè¾¥¥¥_{í5¿Í›7Ó¯_?bccùþûïËŽ=ªnÝUý +EÆŠoïñ}X¶î‹•Z§õâiI"ò1p +.·«j©Ç˜?ïßÀØÄÝåcÏ<óÌðŽ;NÈÍÍeÙ²e’––Æ]wÝÅìÙ³éܹ3#FŒ ¯}ùå—,]º”˜˜xà’““)--eàÀ¬ZµŠ›o¾™€€ú÷ïϽ÷ÞKXX·ß~;S¦L! € 6PTTD‹-ˆÇßß_‡ ¶1###xÏ A;°f'ððµªæx—[S/ÌšŠÀÃ’D¤p'VðT#cŒÞF<¬àõ×_Ÿ¸qãÆcáááôêÕ‹›nº !<<œÞ½{óøãW(¨´´”èèh:vìÈÓO?Í‚  bß¾}lß¾ððpŽ9@\\;vì¨ø®¤¤$²²²HHH k×®ròäɲµk׎ÊÈÈ âܶGOu¼Q¶—5E•_÷t·‰Xä†i<5‡¸·€,·bpôèÑ;322JjÔ¨A`` ={ö$>>žÈÈHüüN¿¿?×\s QQQøùù±bÅ >ÿüs>̉'hÚ´)þþF=GEEñÆoœqíÚµ‰‹‹£AƒZPPp²¨¨(mݺu _~ùåqªº#û†áâRŽ|€±]=á!å™.¦BÑŽ»Ý‡u.ZàÅc|ÒwÀë1V©uÜì¸òÊ+ÛM™2å—?þX—,Y¢ ,Ðýû÷«·üøãZVV¦ªª?ýô“N›6M—,Y¢?üðßËÊÊÒ1cÆèرcõÔ©S× µGÇõœÁ7aeÍaÌejVÁ;µÁ ÷6¸0¦Àt¬®‹-G!€ĹÜð¶ ¤á2^¾éêqÚõ¡‡jóä“O~8räÈœJRÕ÷Þ{O÷ìÙSézqqq¥k³fÍÒ¹sçê£>šVPPPqý³Ï>+¨ã²¦G0ú¥1U€Xrš^Å3Ç`ÞÔp4–‡fW‹ˆg,ŠÆ||–:³]ŠåÖŽÙÆ÷‰HyêL}ã7Š0¦²B/^LBB 66öŒ‰9xð 9994hа4gÎæÍ›—|âĉ›"##c/½ôRÿ† J\\ÜÝ»wû‹È^¬'X.~ÀµX l½ˆd{/#ãžÂDd'à½ýg3>2#Ë/ǰ‘·_…ÎÆ-êÖ"¾£`›bàRºvíš0|øð«Ê?TZZÊŒ3§sçÎìÞ½»ÒDÉÉɤ§§ÏÊ•+iÙ²%Íš5ãúë¯'!!áÎŒŒŒ¢Å‹¯ËÌÌ<\‰±¦Í±—äMúcì¦?îz 3–€¹hž×ø•W ÖuHÁXº8¬îù7+[bïñàg¬…Ô¨Y³æe}ôÑ&UÕmÛ¶é§Ÿ~Z6tèÐÝãÆûÙÍýÊeܸqúî»ïêôéÓ577WgÍš¥“'O>#½ð ïÉÄŠðD—uýKõ·bÞà½æ8°¸t™×X'¬Ž»¨UîƒåVp^,æ|1~±Uøw[gÑmÀI“&MüñÇõÍ7ßÌ7n\zƒ Þzê©/¼³bÅ ÍÍÍUUÕ´´4-..Ö)S¦è¨Q£´¨¨H‹‹‹5??¿âó~øábŒÄŸä¬;Èk-ë0¸¶Šõöq £ p¹×X0Vÿ™òv»ÇàÓXeß„ÊãrG³‘U|ñ cÅ9òÎ>}úÜÓ»w襤¤×±ši÷„ väååU² ­[·jZZšnݺµâZJJŠ._¾¼âÿÙÙÙ:~üømÚ´™‰¸-pÉ^X0sÃJ[Ë:ì(Ê-hã4?ä­$ÁHôI@=—›[c`òï·ç¡ÈCƨX|Ÿ>}>¨_¿~00?88xÚäÉ“‹*iIU—.]ªÉÉÉnCúÅ_hÏž=uРAÏa›ÞU¬1Êñˆ»ºU¼Ì¹XE‘x5u<â@Tùõ ”¦ö©¾Wt‹Ã)á1¾ãŒaml¼Æ/`í¥:5ŠŸŸß‘5j„-..îš¿bÅŠJœöm·ÝÆÎ;½/н{wfÏžM``à,ëìv^ˆ·ŒÇ¬ Û{p†ˆÈ­Ž"fûõÌâÝã½Þq殘ß臥¾  cµ° ÝX©ªÞ}8ÁÊ–À?UõpRRR¢ŸŸ_ÝY³fÍ‘ÑþþþÝ>ùä“ÁÁÁ$%%'öîÝKrr2×]wùùù„„„°mÛ6rss)((Е+W_³fÍ«À|UMõúîËåÝ ü¢ª•x0‡.™ ÌSÕ^c÷cáä1¼w»˜£`þŒKüÁÊ“Å@Ã*̹?¶{¤qùµ¤¤¤™zé–$&&æŒ5ª2WÕÒÒR]ºt©®_¿^9¢ªŸî½÷Þãñíò½b­íf¸W½0Лˆ{U± ö•’S%fÒ±œÑˆŒ*wùÌdo¬âìÇ,,øÇˆH8@``àá믿¾'FU<‘––¶lÍš5‘;wî<ƒÓ9yò$ÙÙÙ´iÓ€_ý•… ’ššJDDÄà9ŒRîàrBà>çåä©Wqî0ã±X”«ªÞ˜¨֪߈W³ \)UYÓ6Œ¡¼ÊeüYÌl]wÿ‹ÌõU•ààà›5j”Yg#à’5j$téÒ%SU+,¦°°P·nݪƒÖN:éwÞ©]ºtÉéÚµëû‘‘‘M±Â´œûá$,iÇ Èå.ë¹ø?ÌŠÜ2Þ:ÌÍâ]ŸÇí¢‡ynÆD;‹jƒ{¦ë‰±€M0z0::z\‡^Â#£Ìœ9sçÊ•+uÊ”)g·[¶lÑ &èܹsõŽ;îx¯T?a•@¹«5ÇÝÕ–Ïà‚›°-D;0H榋³up¿Ä`{; ¢{Z_¦cš°hÞ²ÎQP3gñc233? ?Ú®]»¾‰‰‰õÖ¬YóÜæÍ›¦¦¦’‘‘QqsBBEEEQ§Npõ"ÇÔi.`ñ©»£¬˜+y»Z}Ì‚¾Ã‹rä ßå©W"òü³YÓ}Ø~Å&.c}0ä[iÌ?†µoÆb«‚¿[o½õæ–-[V`˜\÷ä“On6lØï¾ûNU \¾øâ‹:dÈùçX_7¬Ùp# Ý\m,¶"Êۯũ‚V9—%µš5]Ž%|…YK­ò]."Ò£`J0Fs5†[–¬^½ú–õëׇ•·n®½öÚyyy_þòË/oeeeirr2ß|󦧧Ϛ6mZ7¯yCD¤¯ˆÌ‘Ÿ±$¡X~—÷â¤3ØyŽ£NRò”Þ:/ö¶VO9«’Ô°Â*¬Ú®é5Vü€Å :DDÚb |ÌYx¬’î,-++ë|,‘Ž;vìàý÷ßU\\¼1333÷äÉ“úÍ7ßœúøãÿè1gùSô_±ºë5 ý'bÛ`[t›ÀxÖ Èw^ž[@ß‚eE×Bø|”4Û>ç¶ }§£¨ñX÷ù̆×W¥’°Žk LûcnU b §Ï Á¬=×±¦ wÇù¢yµ{Ã">)Èež+08Ž‚‰ò«¤$¬œX¹ü_±®m¥låÃ÷Þæ(ê5NóJ>%™êœw;Šçy˜ë¤c}©j‰ªUÕ¡X@í¼'"×{Ÿ=“ç±à¿ «#g?«QÅÕ•ÕØI¥'°x¬>þ`LuN=OÆx›æXå€Ä«· ¼¹êÛYÿõ"Ò;Fú/ÌËÕ[µ0×Jöi5ÎÏŠH4;oÁ(ëœy–añÌg©öAeg§EÖ hŽ™CgWboþßÎb|:°,"¯bu5V¶ÜèÜ?SŽÛ¾M·y®pæyK[°Š` Æçô‰ñ"_^&pa~«³ªpLiobñ#xkÏœóHV‘a=ý·1áëq®ö#pãÁþ„½¸Ú˜UV;vžW஦Òå|€Uî뱬xöBÒúR,‹ž«N ÁâË/Xæ‡Äz¾¼”‹®$¯‡ Åh“CX¿«QU à8ÉËêöaûÄËá@äj1Uýýæ?袪'Tu»çt¥ØÏ“UKDäùëæ¼ˆ!úyªú³ªÑÊ[/ˆün? ä<Ä q÷ŠÈ-Ul>?CDäR™ŠÑ&+0ëY ìг0ŠJ~÷_âRÕ•[†ýÆÉ].Ôp…8›ëwbø^lwË6U=¬ŽïýÖraÆGqÜâYÙ=ôÓν ‘@l;tìðóFì¤Ó9… -EIå¢F¤cn$V<ƒe¨c™±?F³fü^–ã-õ×+!Ò ãÑÅ‚ûõ§ôf=¿yÜ9›üW( *vãoÀ(á±®kšþü ç’ ¢¬hйÙ΋å^ÞòÿBƒµäÉk-IEND®B`‚gnunet-0.10.1/po/0000755000175000017500000000000012320755631010514 500000000000000gnunet-0.10.1/po/Rules-quot0000644000175000017500000000337611374167231012451 00000000000000# Special Makefile rules for English message catalogs with quotation marks. DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot .SUFFIXES: .insert-header .po-update-en en@quot.po-create: $(MAKE) en@quot.po-update en@boldquot.po-create: $(MAKE) en@boldquot.po-update en@quot.po-update: en@quot.po-update-en en@boldquot.po-update: en@boldquot.po-update-en .insert-header.po-update-en: @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ ll=`echo $$lang | sed -e 's/@.*//'`; \ LC_ALL=C; export LC_ALL; \ cd $(srcdir); \ if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "creation of $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi en@quot.insert-header: insert-header.sin sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header en@boldquot.insert-header: insert-header.sin sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header mostlyclean: mostlyclean-quot mostlyclean-quot: rm -f *.insert-header gnunet-0.10.1/po/insert-header.sin0000644000175000017500000000124011374167231013677 00000000000000# Sed script that inserts the file called HEADER before the header entry. # # At each occurrence of a line starting with "msgid ", we execute the following # commands. At the first occurrence, insert the file. At the following # occurrences, do nothing. The distinction between the first and the following # occurrences is achieved by looking at the hold space. /^msgid /{ x # Test if the hold space is empty. s/m/m/ ta # Yes it was empty. First occurrence. Read the file. r HEADER # Output the file's contents by reading the next line. But don't lose the # current line while doing this. g N bb :a # The hold space was nonempty. Following occurrences. Do nothing. x :b } gnunet-0.10.1/po/Makevars0000644000175000017500000000346312203416111012121 00000000000000# Makefile variables for PO directory in any package using GNU gettext. # Usually the message domain is the same as the package name. DOMAIN = $(PACKAGE) # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ --from-code=UTF-8 # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Christian Grothoff # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = gnunet-developers@mail.gnu.org # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = gnunet-0.10.1/po/LINGUAS0000644000175000017500000000005711610004035011445 00000000000000# set of available languages vi de sv es zh_CN gnunet-0.10.1/po/en@quot.header0000644000175000017500000000226311374167231013225 00000000000000# All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # gnunet-0.10.1/po/es.gmo0000644000175000017500000041265012320736475011564 00000000000000Þ•©d%=¬J c3¡c*Õcdd7d(Md&vd(dÆdád"ûd1e!PereŠe)¥eÏe!æef"f)9f"cf †f§fÂf)ßf g3$g.Xg1‡g-¹g*çg(h;h1Yh-‹h&¹h àh$i7&i^i/}i1­ißi#ûi#j)Cj&mj&”j&»jâj$új!kAk*Yk$„k©k,¿k!ìkl,lGl"al„l)¤l$Îl!ólm)1m.[m&Šm+±m.Ým& n+3n/_n/n¿n/Ûn$ o20o'co+‹o-·o7åo6p/Tp„p!¡p/Ãp"ópq5qQqmq(„q+­qÙq.ïq*rIr"br…rr·r/Ðr"s,#s&Ps&wsžs$¶sÛsñs% t3t0Kt|t–t"±t/Ôt#u(uCu(^u#‡u«u)Çuñuv'*vRv+ev(‘v1ºvìv% w 2wSw(nw1—wÉw(ßw x)x(Dx(mx–x±x3Ìx(y)y1:yly‹yªyÈy,åyz$,zQzfz‚z ¢zÃz#Þz#{+&{&R{ y{š{%¬{"Ò{(õ{!|@|!]|"|¢|´|(Ä|'í|}62}i}‚} }º}"Ó}ö}~&~5~L~+h~ ”~¡~º~4Õ~& #1)U.®Íí+ €$8€$]€'‚€ª€¿€Ý€÷€(<Wv–µ2Ô1‚9‚X‚g‚‚“‚­‚Å‚4Ý‚+ƒ4>ƒ%sƒ™ƒ-¯ƒ%݃"„&„)E„o„‰„%§„#Í„ñ„* …7…K… ]…$k……¥…¼…Ô…ë…ý…†%†@†3R†&††­†$̆"ñ†$‡(9‡&b‡)‰‡#³‡$ׇ,ü‡7)ˆ/aˆ#‘ˆ"µˆ؈êˆþˆ ‰‰.‰"F‰&i‰!‰ ²‰-Ó‰Š+Š#HŠ-lŠ3šŠΊ/8‹1M‹+‹-«‹2Ù‹ Œ/%Œ,UŒ‚Œ,œŒAÉŒ %-?m%‹-±.ß Ž&/ŽVŽvŽ%–Ž"¼Ž(ߎ(-=<+z5¦&Ü*#.R(iU’,è%‘;‘4U‘!Š‘Z¬‘2’K:’†’"¢’"Å’<è’B%“6h“Ÿ“»“דí“# ”&0”(W”:€”%»”*á”T •Ta•$¶•0Û•. –!;–"]–&€–)§–Ñ–@ð–/1—<a—hž—J˜QR˜1¤˜ Ö˜ã˜8õ˜A.™p™-Ž™=¼™)ú™$š$Dš;iš>¥š+äš›!0›R›#m›‘›n±›- œNNœ.œQÌœ1#P$t#™E½%žC)žOmž½ž;Óž;ŸKŸ<hŸ<¥Ÿ1⟠'  D  e >† *Å %ð '¡0>¡o¡Œ¡#¨¡?Ì¡7 ¢4D¢y¢?¢:¿¢4ú¢6/£"f£<‰£/Æ£ö£(¤/:¤,j¤#—¤»¤Õ¤-ð¤9¥JX¥_£¥¦/¦&E¦!l¦!ަ-°¦NÞ¦7-§%e§,‹§N¸§¨E&¨ l¨¨ “¨Ÿ¨/¾¨î¨©1©'O©w©”©«©©#ß©-ª1ªGª%^ª„ª)™ªê!Þª/«.0«_«2z«!­«Ï«+ï«"¬/>¬n¬ˆ¬#£¬)Ǭ)ñ¬<­X­x­&˜­$¿­'ä­( ®25®9h®A¢®:䮯>9¯7x¯°¯,Я!ý¯$°LD°=‘°#ϰ%ó°7±7Q±'‰±(±±"Ú±)ý±&'²#N²,r²%Ÿ²)Ų)ï²³)3³']³0…³¶³Ô³$ð³´$.´#S´'w´-Ÿ´(Í´7ö´).µ7Xµ8µɵ3âµ1¶#H¶!l¶޶­¶/Á¶0ñ¶a"·?„·3Ä·*ø·0#¸ET¸-š¸'ȸ*ð¸¹(7¹1`¹/’¹'¹=ê¹%(º/Nº~º ’º.³º!âº4»,9»Df»(«»Ô»è»¼#¼P=¼޼¬¼-Ƽô¼A½8P½6‰½-À½î½,¾35¾5i¾1Ÿ¾5Ѿ"¿G*¿]r¿Gп#À%<À,bÀ*À+ºÀ#æÀ4 Á&?ÁfÁ'wÁ!ŸÁBÁÁÂ"Â-BÂ*pÂ9›Â1ÕÂ.Ã<6ÃBsÃE¶ÃüÃÄ7+ÄcÄ/ıÄ(ÎÄ"÷Ä#Å>Å\ÅwÅÅ=¡ÅßÅäÅ.ìÅ(Æ@DÆ;…ÆÁÆ5ÕÆ@ Ç@LÇ$Ç@²Ç;óÇ/È'CÈkÈ2‡È"ºÈUÝÈ)3É/]É,ÉUºÉ%Ê%6ÊT\ÊD±ÊgöÊ^Ë#}ˡ˱ËÐË ìËøË& Ì(1Ì4ZÌÌ#¦Ì8ÊÌ5Í9Í;VÍ7’Í$ÊÍ#ïÍÎ6-Î<dΡÎ-»ÎéÎÏ$$Ï!IÏ%kÏ#‘Ï+µÏáÏÐÐ">Ð/aÐ!‘Ð"³Ð1ÖÐÑ2ÑMÑ%_Ñ'…Ñ$­Ñ3ÒÑ0Ò#7Ò[Ò#yÒ1ÒÏÒçÒ'Ó-ÓLBÓTÓ'äÓ Ô-+ÔKYÔ¥Ô'½Ô*åÔ*Õ;Õ6@Õ,wÕ8¤Õ9ÝÕ!Ö-9Ö6gÖ%žÖHÄÖ: ×H×$`×*…×(°×Ù×Hñ×:ØOLØPœØ8íØ3&Ù'ZÙ‚Ù žÙ=«ÙéÙ%üÙ*"ÚVMÚV¤Ú-ûÚ&)Û9PÛ"ŠÛ ­Û0ÎÛ-ÿÛ0-Ü8^Ü!—Ü2¹ÜìÜÝ4"Ý<WÝ ”ÝSŸÝóÝ'Þ@-Þ9nÞ&¨ÞÏÞ7æÞ'ßFßaß}ß•ß!®ß(Ðßùß)à+BàZnàÉàÜà$÷àá%6á\á,mášá±á/Çá÷á,â)Câmâ‚â2â0ÐâOã6Qã1ˆãºã'Ùã5ä57ä,mä>šä"Ùä0üä)-åXWå#°åÔå)ðå5æ>Pæ+æ=»æ8ùæ>2çqç‹ç*¥çÐçãç.õç,$è3Qè/…è*µè+àè é$é>é5Sé‰é4¡éIÖé8 êYêvê"ê5²ê%èê(ë7ë"Në"që-”ëÂëKÝë)ìOBì’ì=²ì=ðì6.í/eí4•í(Êíóí î&îFî_î#vî šî»î)ÚîïP$ï,uï<¢ï6ßï%ð6<ð#sð—ð²ð'Îð.öðM%ñ5sñ9©ñAãño%òo•òBóHó=fó.¤ó+Óó)ÿó!)ô KôlôŠô/¦ôÖô,öô#õ5@õBvõ¹õBÙõ'ö1Dö<vöd³ö;÷/T÷ „÷o’÷øEø-dø ’ø,³ø!àø!ù"$ù"Gùjù!Šù ¬ù(Íù'öù;ú$Zúú1–ú?Èú'û0ûBû]û8sûW¬ûüü/5ü(eüŽüB«üîü!ý6'ý!^ý€ý”ý²ýRÁý(þ.=þlþ+tþK þ!ìþÿ"ÿAÿ'`ÿcˆÿ,ìÿ+0E(vLŸ:ì;'$c"ˆ$«#Ð,ô!5@1v2¨-Û 3) ]%~-¤&Òù 6*Q|k€#ì %A.Z*‰<´ñ'óTp+‚®Å×î!"3?s!²¶»¿(Ô6ý 4BE`¦#¶^Ú(9 b 3{ 3¯ 4ã  4 'M 7u  ­ ¹ H¾  3% Y *p › ­ +µ  á , ?/ +o :› Ö Ø  á ë ( %0 'V 5~ '´ 0Ü 4 /B!r”°¹!ÖøA(-j#˜>¼û(0Y#[ ‰D© îûBþ'A-i;—Ó(ð+7c"ƒ¦ Á$Íò,SI7®æÿ2VK ¢Ãà è1ö(>W+l˜!©ËNç06$gŒ-¦KÔ@ 8aFš-á-1=#o“;•Ñì !&MH+–)Â!ì<FK7’ÊÑ>ï^.#7±é!&@*Y7„ ¼ Ýë'#>K.Š4¹(î /=\'m!• ·/Äô1 ?ŸZ6ú .1!/`!!ª!1½!&ï!?"V"p""‰"C¬"'ð" #"9#C\# #%¼#â#$.$(K$%t$š$#¹$,Ý$* %J5%B€%OÃ%G&A[&?&.Ý&K 'LX'C¥'1é'3(EO("•(=¸(@ö( 7)+X)*„)/¯).ß)-*.<*k*+‹*4·*ì*/ +*;+ f+G‡+?Ï+&,6,V,$u,%š,6À,,÷,!$-!F-1h-3š-)Î-.ø-3'.)[..….1´.1æ.5/LN/D›/Mà/E.05t06ª0<á0;1ZZ1!µ1+×112)52._2"Ž2"±2$Ô27ù2213d39|3/¶3æ3"4#4;4W4=q4(¯47Ø4+5.<5k5*‹5 ¶5×5'ó569;6u6•6=µ63ó6+'7"S7!v7K˜7(ä7# 8118.c8 ’86³8ê869:89Bs9$¶9-Û9 : *:2K:>~:½:5Ô: ; +;2L;0;"°;!Ó;Nõ;FD<‹<>Ÿ<#Þ<=%!=G=/f=–=(¯=Ø=&í=)>#>>'b>)Š>&´>;Û>2?%J?p?*„?$¯?8Ô?" @0@%N@%t@š@«@/½@)í@"AA:A |A!A¿AÛA)öA% BFBaBuBB<«BèB ÿB" CICC>C-ÌC5úC90D'jD'’D!ºD1ÜD$E)3E)]E‡E žE¿EÛEõE F!F/>I%}I0£I/ÔI5J:JTJ,sJ. J-ÏJ3ýJ1KKK^K.pK!ŸK ÁKâK.L/LLLTL6pL§LA½L8ÿL"8M*[M%†M'¬M-ÔM.N41N2fN2™N9ÌNBO4IO-~O-¬OÚOîOP P*P CP*dP1P)ÁP.ëP4QOQ;nQ,ªQF×Q2R&QR?xR(¸RáR6üR03S<dS<¡S%ÞSET+JTvT8“TNÌTU5U1SU!…U-§U1ÕU2V$:V,_V#ŒV#°V/ÔV3W=8W%vWœW¡WH¶W;ÿWC;X0X,°X%ÝXY0YlNY5»Y3ñY#%ZIIZ6“ZgÊZH2[a{[Ý[,ú[''\BO\H’\=Û\"]"<]_](|]+¥]3Ñ];^CA^0…^2¶^ié^kS_-¿_?í_>-`,l`*™`;Ä`:a;aJPaI›aKåaˆ1b`ºblc>ˆc ÇcÓcIëc_5d.•dOÄdQe7fe)že;ÈeQfRVf-©f*×f&g )g$Jg-ogygCh`[h?¼hxühPui*Æi;ñi,-jbZj-½jWëjnCk²k[Ìk`(l&‰lI°lIúlJDmm%¤m$ÊmFïmX6n:n2Ên3ýnL1o~ožo1¼oRîoOAp@‘p ÒpDÞpH#q@lqD­q0òqX#rH|rÅr/âr@s?Ss)“s"½s!àsLtAOtq‘tzu~u-Žu.¼u-ëu-v8GvR€v;Óv2w9BwY|w#ÖwGúw#Bxfxlx'|x=¤xâxûxRy/fy"–y¹yÐyéy,z?3zszˆz2¡zÔz?ïz/{.O{5~{6´{*ë{G|2^|4‘|?Æ|7}K>}(Š}+³}8ß}W~:p~b«~9;H7„>¼>ûA:€R|€SÏ€b#P†*×]‚S`‚4´‚Dé‚9.ƒ=hƒb¦ƒV „.`„=„@Í„@…CO…J“…4Þ…K†?_†?Ÿ†7߆6‡JN‡P™‡,ê‡Dˆ8\ˆL•ˆ2âˆ1‰7G‰(‰2¨‰9Û‰@ŠIVŠ> ŠWߊB7‹Uz‹UЋ+&ŒRRŒP¥Œ<öŒ431hšMµJŽtNŽMÃŽHAZJœVça>> Bß+"‘AN‘H‘HÙ‘:"’Z]’;¸’Gô’'<“:d“NŸ“4î“S#”Fw”f¾”A%•#g•0‹•/¼•+ì•q–2Š–,½–Sê–+>—fj—WÑ—X)˜K‚˜ΘBî˜Q1™Fƒ™OÊ™Rš+mšX™šoòšYb›<¼›>ù›:8œ0sœ,¤œ-ÑœBÿœ+Bn:0ºXë.Dž&sž7šž5Òž>ŸMGŸ0•ŸLÆŸN _b * 3í e!¡8‡¡=À¡.þ¡?-¢3m¢3¡¢+Õ¢*£-,£Z£Dq£ ¶£ ã2Σ0¤H2¤F{¤¤EÙ¤T¥Ut¥)Ê¥Hô¥F=¦„¦)›¦Ŧ;á¦9§tW§A̧;¨.J¨gy¨&á¨1©k:©Y¦©†ª!‡ª%©ªϪ&Þª#«)«8«'P«3x«F¬«ó«6¬KH¬L”¬&á¬A­;J­.†­)µ­$ß­J®WO®!§®>É®!¯+*¯3V¯,Н/·¯0ç¯/°0H°1y°)«°=Õ°F±(Z±&ƒ±Eª±ð±;²@².T²5ƒ²'¹²0á²3³+F³&r³8™³;Ò³´ *´2K´~´R™´nì´@[µ1œµ?εg¶"v¶)™¶/ö*ó¶·G&·En·@´·Zõ·BP¸I“¸WݸA5¹Yw¹Xѹ(*º7SºD‹º@к&»`8»!™»k»»k'¼W“¼Jë¼E6½-|½ª½HÀ½ ¾. ¾>O¾r޾f¿=h¿,¦¿>Ó¿(À(;ÀBdÀ:§À:âÀJÁ*hÁ:“Á#ÎÁ#òÁ9ÂBP “Â_ŸÂÿÂ8ÃZKÃ=¦Ã*äÃÄG-Ä4uÄ%ªÄ'ÐÄøÄÅ..Å0]Å&ŽÅ:µÅ0ðÅn!Æ&ÆE·Æ%ýÆ"#Ç-FÇtÇ.‡Ç ¶Ç×Ç9ðÇ*È=JÈ*ˆÈ³ÈÈÈ4âÈ2É`JÉ?«ÉMëÉ!9Ê)[Ê7…Ê7½Ê0õÊF&Ë3mË1¡Ë*ÓËcþË(bÌ‹Ì?¨Ì>èÌA'Í+iÍY•ÍGïÍC7Î{ΛÎ-¸ÎæÎÏ5Ï3JÏ>~Ï=½Ï;ûÏB7ÐzДгÐ;ÏÐ ÑE'Ñ[mÑHÉÑ)Ò$<Ò*aÒKŒÒ/ØÒ/Ó8Ó+VÓ*‚Ó,­ÓÚÓeùÓ)_Ôe‰Ô3ïÔX#ÕX|ÕAÕÕJÖCbÖ)¦Ö#ÐÖ%ôÖ+×F×b×$€×,¥×-Ò×3Ø&4Ø^[Ø<ºØC÷Ø6;Ù,rÙEŸÙ7åÙ)Ú+GÚ8sÚ1¬ÚVÞÚ=5ÛVsÛPÊÛsÜsÜJÝ3NÝg‚ÝMêÝB8ÞG{ÞÃÞ/áÞ+ß.=ß;lß-¨ß-ÖßàD!àIfà"°àXÓà0,áC]áC¡ápåáOVâI¦âðâyã}ã^›ã:úã&5ä8\ä#•ä"¹ä.Üä+ å*7å,bå+å6»å5òåC(æ,læ™æ9°æAêæ%,çRç&kç’çH®ç÷çyè“è7³è4ëè# éDDé‰é+£éEÏé5êKê)hê’êr¤ê8ë@Pë‘ë2™ënÌë3;ì#oì,“ì Àì.áì‚í8“í7Ìí:î-?îTmîCÂî;ï/Bï/rï)¢ï'Ìï6ôï&+ðDRð=—ð:Õð2ñ"CñBfñ(©ñ-Òñ8ò'9òaò&€ò §ò6ÈòÿòŠó2’óÅó0Öó%ô<-ô9jô?¤ôäô.æôoõ…õ@¤õåõöö,ö*>öiö>‰ö"Èö(ëö÷÷÷&÷<;÷@x÷¹÷É÷Kæ÷2ø#Døqhø0Úø ù<,ùHiù?²ùòùú/0úI`ú ªú¸ú`¿ú! û]Bû' ûKÈû!ü 6ü;Cü2ü<²üSïü5CýFyýÀýÂýÒý+áý: þ<Hþ>…þBÄþ;ÿCCÿ<‡ÿ.Äÿ"óÿ .":&]„%šFÀ<5DCz!¾,à9 GI d+pHœåýM2N@RÂ%,;&h0(À/é" <%H'n'–¾xÛTMgµ Õ<öX3,Œ,¹æþ7;H„£P¼ 2" %U h{ 5ä * *E 6p W§ Kÿ AK O 5Ý 5 YI *£ Î 1Ð    # D !c +… `± :8M0†=·HõB>ˆe§… &“Oº 4(]%|>¢Bá"$G]w;“AÏ\?n*® Ùåü)85Q#‡«?¾ þG@g*Žðqzµ‹ B3EcD²sþbh ¡ŽVÉKÇ£P±ƒE[š}Pî—Øa}†ª(%JòÞÍÌÃî­Sžx”uª, aÏËø£LÓ™˜ïDr@­M#Жa$Ä`FíÍ-cÿv”+„4¤½tž |?y†…%ã°@f™_>FËþ Ë*H=Ñ´c$À‹‚¾a´êðS(Ð ›Äå¼D}˜¶PJ•åGbôdðöã)t OÅÿA£L µÑ³P&»7œmä¾xÕ„•m;¢Ãu^9®Ô›» Àx'-Œ/Œ‹¿­¢¯ ’ˆI£zbo·1T‹NÁHé…89º4B"ú‰«Ž`IæXäG–sÆßMûãó×ý\¨É_;œ{\Cx‘‚§èë%<»ÙT I»¦&‘Õ½Z¥T‘&=÷ï(ò=ZƒÙ«É¬Ë“Ð —2¦ö“f˜*bŽ¡)5®n É4j/éX Õ)߀A§„©[úÖkJûH ëq w¯=rÒÜl7ƒNàáZ?Î+]>nj¡Á ß2†º,îpþUå—Ôþ  NÀc©‰.a‚VœÓû LÞŠ/‘WowGåæÁLBµ\‡qn‡QM|m¨B9×0‡™1µS"¹YY©€Ê}|5óüòQoCvõX~–?Çõ”<¾"¤ÖEvSdqh—™–<*š]C8K¼ý`6à[ ¯¬ˆ0Kš'†šU¨gŸ[rÿ~Nç#ÅÊ.ü>3Pâ8çF\úy?ç.Û€pÇ_Æ&ѱ6%~ŸS¿Qi[ wí„z…~Ø¡ñ+g1 IïÚ…¸Ž°E6¸erè¤'¨VMdƒê5ŠW§ºiÝ+ fŒé²`f¬<ÆÊ%{¬_ù:¥hé,ð÷½WÒÜ(±j#à”¥Aô'áûY@Ú7³=Ïh©RÎÈH¶ýÖ°)ìkÌÈ"Àw³Œh°Û@1t“±‚<-ÒT—rúž]VzÝà}Aʦoˆ5ãlЉO|Œíy÷œ­,nä^“¦_Ö2Å{Šˆ*":JE½ˆƒÚFe 4¤’Ýkõ:só¡Ú-YW)ÔÍlíD¹Õ!¸èïOgÆ™vó ¸Ý ³ WŸZ ^¢“u3¥c®×øÅŸ&¿¨Bîøßê…tØ{·'²òX`è˜çõö7ª~æ΄Š¯;Âvát‡Ç”¶Äø’ ÏñRye5-Û^–$!¼Uñüù¢•ÒsO6m²i¼39‚.ÐpÌ\Èl‹GGæ¶>u7’|z>˜º§·/Qg2ìqC HZÏRª9Ó/N+g›ëì‰âdÿÌpoÜΩyXp:D:xm›ÙR0Þ¹Û·ž C1V@×QìùÞ0{ÃuFKOifR;Ù£‰¢Ÿ.Óôd¹Âœ•(j’¿Âw†ë#?lMe!] ÔLÍê•6´I0iJk÷jÀYUù,¾ônÈ€Ñ#âsâUk!K«á§Â¥öØ;ž‘®]š¤bÜÄ!8eýü^4ñA‡ «¦2$$›83´äTÁ Corrupt or unsupported record of type %u Failed to write to `%s': %s # ACKs received via WLAN# Active destinations# Bytes dropped in mesh queue (overflow)# Bytes given to mesh for transmission# Bytes of bandwidth requested from core# Bytes received from MESH# Bytes received from TUN# Bytes transmitted to other peers# Client response discarded (no matching request)# DATA messages received via WLAN# DHT requests combined# DISCONNECT messages sent# DNS exit failed (failed to open socket)# DNS records modified# DNS replies dropped (too late?)# DNS replies intercepted# DNS replies received# DNS requests answered via TUN interface# DNS requests dropped (malformed)# DNS requests dropped (timeout)# DNS requests intercepted# DNS requests mapped to VPN# DNS requests received via TUN interface# Datastore `PUT' failures# Datastore lookups aborted (more than MAX_RESULTS)# Datastore lookups concluded (error queueing)# Datastore lookups concluded (found last result)# Datastore lookups concluded (load too high)# Datastore lookups concluded (no results)# Datastore lookups concluded (seen all)# Datastore lookups initiated# Duplicate REPLIES matched against routing table# Duplicate REPLIES to CLIENT request dropped# Duplicate RESULTS found in datacache# Entries added to routing table# Entries removed from routing table# External DNS response discarded (no matching request)# FIND PEER messages initiated# FIND PEER requests ignored due to Bloomfilter# FIND PEER requests ignored due to lack of HELLO# GAP PUT messages received# GET REPLICATION requests executed# GET REPLICATION requests received# GET STOP requests received from clients# GET ZERO ANONYMITY requests executed# GET ZERO ANONYMITY requests received# GET messages queued for transmission# GET requests executed# GET requests from clients injected# GET requests given to datacache# GET requests received# GET requests received (from other peers)# GET requests received from clients# GET requests routed# Good REPLIES matched against routing table# Good RESULTS found in datacache# HELLO beacons sent via WLAN# HELLO messages gossipped# HELLO messages received# HELLO messages received via WLAN# HELLOs obtained from peerinfo# ICMP IP-exit requests received via mesh# ICMP packets dropped (not allowed)# ICMP packets received from mesh# ICMP packets sent via TUN# ICMP service requests received via mesh# ICMPv4 packets dropped (impossible PT to v6)# ICMPv4 packets dropped (not allowed)# ICMPv4 packets dropped (type not allowed)# ICMPv6 packets dropped (impossible PT to v4)# ICMPv6 packets dropped (not allowed)# ICMPv6 packets dropped (type not allowed)# IPv4 broadcast HELLO beacons received via udp# IPv6 multicast HELLO beacons received via udp# ITEMS stored in datacache# Invalid REPLIES matched against routing table# Invalid RESULTS found in datacache# Irrelevant REPLIES matched against routing table# Irrelevant RESULTS found in datacache# KEEPALIVE messages discarded (no session)# KEEPALIVE messages discarded (peer unknown)# KEEPALIVE_RESPONSE messages discarded (not connected)# KEEPALIVE_RESPONSE messages discarded (not expected)# Key match, type mismatches in REPLY to CLIENT# Loopback routes suppressed# Network size estimates received# Non-DNS UDP packet received via TUN interface# P2P FIND PEER requests processed# P2P GET requests ONLY routed# P2P GET requests received# P2P PUT requests received# P2P RESULTS received# P2P messages dropped due to full queue# P2P query messages received and processed# P2P searches active# P2P searches destroyed due to ultimate reply# PING message for different peer received# PING messages received# PING without HELLO messages sent# PONG messages created# PONG messages decrypted# PONG messages received# PONGs dropped, no matching pending validation# PONGs dropped, signature expired# PONGs multicast to all available addresses# PONGs unicast via reliable transport# PUT messages queued for transmission# PUT requests executed# PUT requests received from clients# PUT requests routed# Packets received from TUN# Packets received from TUN interface# Peer selection failed# Peers excluded from routing due to Bloomfilter# Pending requests active# Pending requests created# Preference updates given to core# Queued messages discarded (peer disconnected)# RELEASE RESERVE requests executed# REMOVE requests executed# REMOVE requests received# REPLIES ignored for CLIENTS (no match)# REQUEST CONNECT messages received# RESERVE requests executed# RESULT messages queued for transmission# RESULTS queued for clients# Replies received from DHT# Requests dropped from datastore queue# Results received# SET QUOTA messages ignored (no such peer)# TCP DATA requests dropped (no session)# TCP IP-exit creation requests received via mesh# TCP WELCOME messages received# TCP data requests received via mesh# TCP packets received from mesh# TCP packets sent via TUN# TCP requests dropped (no such service)# TCP service creation requests received via mesh# TCP sessions active# UDP IP-exit requests received via mesh# UDP packets received from mesh# UDP packets sent via TUN# UDP requests dropped (no such service)# UDP service requests received via mesh# UPDATE requests executed# UPDATE requests received# Unsupported REPLIES matched against routing table# Unsupported RESULTS found in datacache# WLAN ACKs sent# WLAN DATA messages discarded due to CRC32 error# WLAN DATA messages processed# WLAN MAC endpoints allocated# WLAN message fragments sent# WLAN messages defragmented# WLAN messages pending (with fragmentation)# WLAN sessions allocated# acknowledgements sent for fragment# active connections# address records discarded# address revalidations started# advertised URI `%s' downloaded# advertised hostlist URIs# artificial delays introduced (ms)# average retransmission delay (ms)# bandwidth quota violations by other peers# bits removed from fragmentation ACKs# bytes currently in TCP buffers# bytes decrypted# bytes discarded by TCP (disconnect)# bytes discarded by TCP (timeout)# bytes downloaded from hostlist servers# bytes dropped (ancient message)# bytes dropped (duplicates)# bytes dropped (out of sequence)# bytes dropped by SMTP (outgoing)# bytes encrypted# bytes expired# bytes in message queue for other peers# bytes of messages of type %u received# bytes of payload decrypted# bytes payload dropped (other peer was not connected)# bytes payload received# bytes purged (low-priority)# bytes received via SMTP# bytes received via TCP# bytes removed (explicit request)# bytes sent to datastore# bytes sent via SMTP# bytes stored# bytes total received# bytes transmitted via TCP# bytes used in file-sharing datastore `%s'# cache size# client searches active# client searches received# client searches updated (merged content seen list)# connect requests issued to transport# datastore connections (re)created# disconnect messages ignored (timestamp)# disconnected from peer upon explicit request# disconnects due to blacklist# disconnects due to quota of 0# duplicate fragments received# duplicate replies discarded (bloomfilter)# encrypted bytes given to transport# fragment acknowledgements received# fragmentation transmissions completed# fragments received# fragments received via WLAN# fragments retransmitted# fragments transmitted# fragments wrap arounds# friends connected# friends in configuration# hostlist URIs read from file# hostlist URIs written to file# hostlist advertisements send# hostlist downloads initiated# index blocks removed: original file inaccessible# invalid HELLOs downloaded from hostlist servers# irrelevant replies discarded# items stored# keepalive messages sent# keepalives sent# key exchanges initiated# key exchanges stopped# messages defragmented# messages discarded (expired prior to transmission)# messages discarded (session disconnected)# messages discarded due to lack of neighbour record# messages dropped due to slow client# messages fragmented# messages timed out while in transport queue# messages transmitted to other peers# migration stop messages received# migration stop messages sent# milliseconds between hostlist downloads# ms throttling suggested# neighbour entries allocated# network-level TCP disconnect events# on-demand blocks matched requests# on-demand lookups failed# on-demand lookups performed successfully# peers blacklisted# peers connected# peers known# query messages sent to other peers# query plan entries# query plans executed# queue entries created# queue entry timeouts# queue overflows# quota# refreshed my HELLO# rekey operations confirmed via PONG# replies dropped# replies dropped due to insufficient cover traffic# replies dropped due to type mismatch# replies received and matched# replies received for local clients# replies received for other peers# replies transmitted to other peers# request dropped, priority insufficient# requested DBLOCK or IBLOCK not found# requests done for a price (normal load)# requests done for free (low load)# requests dropped due TTL underflow# requests dropped due to higher-TTL request# requests dropped due to initiator not being connected# requests dropped due to missing reverse route# requests filtered by bloom filter# requests filtered by bloomfilter# requests merged# requests received# requests refreshed# reserved# results found# results found locally# running average P2P latency (ms)# send requests dropped (disconnected)# session keys confirmed via PONG# sessions terminated by timeout# sessions terminated by transport disconnect# status messages received# storage requests dropped due to high load# total size of fragmented messages# transmission failed (core has no bandwidth)# transmission failures for messages to other peers# transmission request failures# transport-service disconnect requests for TCP# type map refreshes sent# type maps received# unexpected CONNECT_ACK messages (disconnecting)# unexpected CONNECT_ACK messages (no peer)# unexpected CONNECT_ACK messages (not ready)# unexpected CONNECT_ACK messages (waiting on ATS)# updates to my type map# valid HELLOs downloaded from hostlist servers%24s: %-17s %4s (%u connections in total) %s failed at %s:%d: `%s' %s request received, but have no datacache! %s service is lacking key configuration settings (%s). Exiting. %s: illegal option -- %c %s: invalid option -- %c %s: option `%c%s' does not allow an argument %s: option `%s' is ambiguous %s: option `%s' requires an argument %s: option `--%s' does not allow an argument %s: option `-W %s' does not allow an argument %s: option `-W %s' is ambiguous %s: option requires an argument -- %c %s: unrecognized option `%c%s' %s: unrecognized option `--%s' %u address resolutions had a timeout %u hostlist URIs loaded from file --option argument required to set value --section argument is required 0 msA port has to be between 1 and 65535 to connect to host `%s' A port is required to connect to host `%s' ARM now monitors connections to service `%s' at `%s' ATS returned results for %u addresses Accepting connection (%u of %u) from `%s' Accepting connection from `%s': %p Access denied to `%s' Access from `%s' denied to service `%s' Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data size %u Adding `%s' without addresses for peer `%s' Adding host %u failed with error: %s Adding record failed: %s Adding successfully tested hostlist `%s' datastore. Address to obtain hostlist: `%s' Advertised hostlist with URI `%s' could not be downloaded. Advertised URI gets dismissed. Advertisement message could not be queued by core Arguments mandatory for long options are also mandatory for short options. Assertion failed at %s:%d. Attempt to cancel dead task %llu! Attempt to connect to `%s' failed Authoritative DNS suffix to use (optional); default: zkey.euAuthoritative FCFS suffix to use (optional); default: fcfs.zkey.euAutomatically publish files from a directory on GNUnetBinding to IPv4 address %s Binding to IPv6 address %s Block not of type %u Block of type %u is malformed Bloomfilter construction complete. Bootstrapping using hostlist at `%s'. Call with name of HELLO file to modify. Can not index file `%s': %s. Will try to insert instead. Cannot change user/group to `%s': %s Cannot connect to ATS service, exiting... Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES Cannot extract metadata from a URI! Cannot issue request to ATS service, exiting... Cannot obtain information about user `%s': %s Cannot parse DNS request from %s Cannot start the master controllerChange DNS replies to point elsewhere.Character sets requested were `%s'->`%s' Cleanup after abort complete. Client was disconnected from core service, trying to reconnect. Command line tool to access the testing libraryConfiguration fails to specify option `%s' in section `%s'! Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled. Configuration specifies invalid value for option `%s' in section `%s': %s Configuration value '%s' for '%s' in section '%s' is not in set of legal choices Configured DNS exit `%s' is not working / valid. Connected toContent not foundControl services and the Automated Restart Manager (ARM)Core service is lacking HOSTKEY configuration setting. Exiting. Core service of `%4s' ready. Could not access PEERINFO service. Exiting. Could not access a pre-bound socket, will try to bind myself Could not access configuration file `%s' Could not access file `%s': %s Could not access hostkey file `%s'. Could not access indexed file `%s' (%s) at offset %llu: %s Could not access pre-bound socket %u, will try to bind myself Could not acquire lock on file `%s': %s... Could not bind to any port: %s Could not connect to %s service! Could not connect to DHT! Could not connect to `%s' service. Could not connect to datastore.Could not create a new TLS certificate, program `gnunet-transport-certificate-creation' could not be started! Could not create keyword URI from arguments. Could not determine installation path for %s. Set `%s' environment variable. Could not determine plugin installation path. Could not determine valid hostname and port for service `%s' from configuration. Could not extract hostkey %u (offset too large?) Could not find IP of host `%s': %s Could not find binary `%s' in PATH! Could not find matching reservationCould not handle hostlist request since I do not have a response yet Could not initialize `%s' subsystem. Could not initialize curl multi handle, failed to start %s plugin! Could not load quota for network `%s': `%s', assigning default bandwidth %llu Could not open `%s'. Could not open file `%s' for reading to load hostlists: %s Could not open file `%s' for writing to save hostlists: %s Could not open file `%s': %sCould not parse IPv4 network specification `%s' for `%s:%s' Could not parse IPv6 network specification `%s' for `%s:%s' Could not pass reply to client, message too big! Could not publish Could not read file `%s': %sCould not resolve `%s' (%s): %s Could not resolve our FQDN : %s Could not resume running search, will resume as paused search Could not save some persistent statistics Could not send list result to client Could not send status result to client Could not start hostlist HTTP server on port %u Could not start publishing. Could not start searching. Could not start unindex operation. Could not submit request, not expecting to receive a response. Could not use specified filename `%s' for bloomfilter. Creating a new private key. This may take a while. DEBUGDaemon to announce regular expressions for the peer using mesh.Daemon to run to perform IP protocol translation to GNUnetDaemon to run to provide an IP exit node for the VPNDaemon to use file-sharing to measure its performance.Datastore lookup already took %s! Datastore payload inaccurate (%lld < %lld). Trying to fix. Default service `%s' not configured correctly! Detected external IP `%s' Detected internal network address `%s'. Did not find mime type `%s' in extension list. Did not find well-formed HELLO in file `%s' Direct access to transport service.Directory `%s' contents: Directory `%s' meta data: Directory too large for system address space Disabling IPv6 since it is not supported on this system! Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s Disconnected fromDisconnected from peer `%s' while benchmarking Display contents of a GNUnet directoryDomain name must not contain `+' Domain name must not contain `.' Download failed: could not open file `%s': %sDownload files from GNUnet using a GNUnet CHK or LOC URI (gnunet://fs/chk/...)Download limit of %u bytes exceeded, stopping download Download of hostlist `%s' completed. Download of hostlist from `%s' failed: `%s' Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to download Downloading `%s' done (%s/s). Dropping message of type %u and size %u, have %u/%u messages pending ECC signing failed at %s:%d: %s ERROREnd of fileError accessing file `%s': %s Error communicating with ARM. ARM not running? Error creating tunnel Error downloading: %s. Error in communication with PEERINFO service: %s Error loading search strings. Exiting. Error opening file `%s': %s Error publishing: %s. Error reading `%s': %sError reading from `%s': %s Error reading length of string `%s'Error reading response from datastore serviceError searching: %s. Error unindexing: %s. Error writing HELLO to file `%s': %s Error writing `%s'. Error writing hostlist URIs to file `%s' Error writing to `%s': %s Expected `%s' to be a directory! External protocol violation detected at %s:%d. Extracting meta data from file `%s' complete. Failed to access `%s': %s Failed to allocate IP address for new destination Failed to close statement %p: %d Failed to compute hash of file.Failed to connect to %s service. Exiting. Failed to connect to DHT service! Failed to connect to FS service for unindexing.Failed to connect to GNS Failed to connect to `%s' Failed to connect to `%s' service. Failed to connect to `datastore' service.Failed to connect to `gnunet-nat-server' Failed to connect to core service, can not manage topology! Failed to connect to datastore.Failed to connect to namestore Failed to connect to the DHT service! Failed to connect to the namestore! Failed to connect to transport service Failed to connect to transport service! Failed to convert DNS IDNA name `%s' to UTF-8: %s Failed to convert UTF-8 name `%s' to DNS IDNA format: %s Failed to create configuration for peer (not enough free ports?) Failed to create directory for recursive download of `%s' Failed to create indices Failed to create listen socket bound to `%s' for NAT test: %s Failed to create or access directory for log file `%s' Failed to create page for `%s' Failed to create record for domain `%s': %s Failed to delete bogus block: %s Failed to drop table from database. Failed to establish TCP connection to `%s:%u', no further addresses to try. Failed to expand `$HOME': environment variable `HOME' not setFailed to find %saddress for `%s'. Failed to find given position in fileFailed to find unallocated IPv4 address in VPN's range Failed to find unallocated IPv6 address in VPN's range Failed to get KSKs from directory scan.Failed to get file identifiers for `%s' Failed to initialize bloomfilter. Failed to initialize hostkey for peer %u Failed to initialize testing library! Failed to initialize watch routine Failed to list connections, timeout occured Failed to load configuration from %s Failed to load datacache plugin for `%s' Failed to load datastore plugin for `%s' Failed to load state: %s Failed to load transport plugin for `%s' Failed to not connect to `%s' service. Failed to obtain statistics from host `%s:%llu' Failed to obtain statistics. Failed to open UDP sockets Failed to open `%s' for writing: %s Failed to open `%s': %s Failed to open file `%s' for writingFailed to open file for unindexing.Failed to pack DNS request. Dropping. Failed to pack DNS response into UDP packet! Failed to parse DNS request. Dropping. Failed to parse HELLO message: invalid expiration time Failed to parse HELLO message: malformed Failed to parse HELLO message: missing expiration time Failed to parse HELLO message: missing transport plugin Failed to parse URI: %s Failed to parse `%s' as an address for plugin `%s' Failed to parse inbound message from helper `%s' Failed to parse peer identity `%s' Failed to prepare statement `%s' Failed to read directory `%s' Failed to read fileFailed to read peer index from toology file: %sFailed to read peer index from topology file: %sFailed to receive acknowledgement from statistics service, some statistics might have been lost! Failed to receive response for `%s' request from `%s' service. Failed to receive response from `PEERINFO' service.Failed to receive response from database. Failed to receive status response from database.Failed to receive valid response for `%s' request from `%s' service. Failed to remove bogus bloomfilter file `%s' Failed to remove configuration file %s Failed to remove servicehome directory %s Failed to resolve `%s': %s Failed to resolve address for peer `%s' Failed to resume publishing information `%s': %s Failed to resume publishing operation `%s': %s Failed to resume sub-download `%s': %s Failed to resume sub-download `%s': could not open file `%s' Failed to resume sub-search `%s': %s Failed to resume unindexing operation `%s': %s Failed to run `%s' Failed to save state to file %s Failed to seek to offset %llu in file `%s': %sFailed to send DNS request to %s Failed to send connect request to transport service Failed to send request to transport service Failed to set IPv4 broadcast option for broadcast socket on port %d Failed to setup post processor for `%s' Failed to start %s Failed to start HTTP server Failed to start `%s' at `%s' Failed to start `%s': %s Failed to start meta directory scanner. Is gnunet-helper-publish-fs installed? Failed to start service `%s' Failed to start service. Failed to transmit request to drop database. Failed to write `%s': %s Failed to write block of %u bytes at offset %llu in file `%s': %sFailed to write configuration file `%s' for peer %u: %s Failed to write directory with search results to `%s' Failed to write hostkey file for peer %u: %s Failure adding HELLO: %s Failure to transmit request to service `%s' Failure while resuming download operation `%s': %s Failure while resuming publishing operation `%s': %s Failure while resuming search operation `%s': %s Failure while resuming unindexing operation `%s': %s Fatal error initializing ARM API. Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)! Fewer friends specified than required by minimum friend count. Will only connect to friends. File `%s' in directory `%s' does not match naming convention. Removed. File `%s' is too big to be a HELLO File `%s' is too small to be a HELLO Found %u addresses to report to NAT service Found %u existing records for domain `%s' Found existing name `%s' for the given key Found friend `%s' in configuration Found myself `%s' in friend list (useless, ignored) GNUnet DNS-to-GNS proxy (a DNS server)GNUnet GNS proxyGNUnet NAT traversal test helper daemonGNUnet hostlist server and clientGNUnet topology control (maintaining P2P mesh and F2F constraints)GNUnet zone manipulation toolGenerating %u keys, please waitGiven `%s' option is out of range: %llu > %u Got duplicate service records for `%s:%u' Got non-IP packet with %u bytes and protocol %u from TUN Got result with unknown block type `%d', ignoringHELLOs without addresses encountered (ignored)Hash mismatch trying to index file `%s' which has hash `%s' Have %u/%u connections. Will consider downloading hostlist in %s Have neither PORT nor UNIXPATH for service `%s', but one is required Heap database running Heap datacache running Helper binary `%s' not SUID, cannot run WLAN transport Host %s cannot start testbed Host registration failed for a host. Error: %s Hostkeys file not found: %s Hostlist file `%s' could not be removed Hostlist file `%s' does not exist Hostlist service starts on %s:%llu Hosts file %s cannot be read Hosts file %s has no data Hosts file %s not found I am peer `%s'. ICMP Packet dropped, have no matching connection information INFOINVALIDIP of recursive DNS resolver to use (required)IPv4 packet options received. Ignored. IPv4 packet with unsupported next header %u received. Ignored. IPv4 support disabled as this system does not support IPv4 IPv4 support is %s IPv6 address did contain ':' to separate port number IPv6 address did contain ']' before ':' to separate port number IPv6 address did contain a valid port number after the last ':' IPv6 address did not start with `[' IPv6 packet with unsupported next header %d received. Ignored. IPv6 support disabled as this system does not support IPv6 IPv6 support is %s Ignoring to connect peer %u to peer %u Importing HELLOs from `%s' Inbound quota configured for network `%s' is %llu Incorrect hostkey file format: %s Index request received for file `%s' is already indexed as `%s'. Permitting anyway. Indexed file `%s' changed at offset %llu Initialization of plugin mechanism failed: %s! Initiating shutdown as requested by client. Insufficient space (%llu bytes are available) to satisfy `%s' request for %llu bytes Insufficient space for publishing: %sInsufficient space to satisfy requestInsufficient space to satisfy request and requested amount is larger than cache sizeInternal IP address not known, cannot use ICMP NAT traversal method Internal error or bogus download URI (expected %u bytes at depth %u and offset %llu/%llu, got %u bytes)Internal error scanning `%s'. Internal error scanning directory. Internal error.Invalid IPv6 address `%s': %s Invalid IPv6 address: `%s' Invalid URIInvalid URI `%s' Invalid URI: does not start with `%s' Invalid URI: fails to specify subsystem Invalid `%s' message received from hostlist at `%s' Invalid argument `%s' Invalid command line argument `%s' Invalid data in database. Trying to fix (by deletion). Invalid error message received from datastore serviceInvalid format for IP: `%s' Invalid network notation ('/%d' is not legal in IPv4 CIDR).Invalid network notation (does not end with ';': `%s') Invalid port number %llu. Exiting. Invalid response from `fs' service.Invalid time format `%s' Issue a GET request to the GNUnet DHT, prints results.Issue a PUT request to the GNUnet DHT insert DATA under KEY.Issueing DHT GET with keyIssuing put request for `%s' with data `%s'! Key number %u does not exist Keywords for file `%s' (%s) Lacking key configuration settings. Learning is enabled on this peer Learning is not enabled on this peer Linking controllers failed. ExitingLoading %llu bytes of statistics from `%s' Loading `%s' datacache plugin Loading `%s' datastore plugin Loading `%s' transport plugin Loading hostkey from `%s' failed. Loading saved hostlist entries from file `%s' Looks like we're busy waiting... Lookup a record for the given nameMAGIC mismatch. This is not a GNUnet directory. Malformed CHK URIMalformed KSK URI (must not begin or end with `+')Malformed SKS URIManipulate GNUnet configuration filesManipulate GNUnet private ECC key filesMaximum number of connections is %u Measure quality and performance of the NSE service.Message `%.*s' repeated %u times in the last %s Meta data extraction has finished. Meta data for file `%s' (%s) Metadata `%s' failed to deserializeMigration of content to peer `%s' blocked for %s Missing argument: name Missing argument: subsystem Missing option `%s' for operation `%s' Monitor DNS queries.More friendly connections required than target total number of connections. Multiple operations given. Please choose only one operation: %s, %s, %s, %s, %s, %s Must provide KEY and DATA for DHT put! Must provide key for DHT GET! Must specify `%s' for `%s' in configuration! Must specify `%s' or numeric IP address for `%s' of `%s' in configuration! Mysql database running NAT traversal with ICMP Server failed. NAT traversal with ICMP Server succeeded. NAT traversal with ICMP Server timed out. NONENeed %llu bytes more space (%llu allowed, using %llu) Need a non-empty hostname for service `%s'. Neither IPv4 nor IPv6 are enabled! Fix in configuration No IP addresses found for hostname `%s' of service `%s'! No URI specified on command line No `%s' specified for `%s' in configuration! No addresses found for hostname `%s' of service `%s'! No configuration file given. Exiting No default services configured, GNUnet will not really start right now. No email-address specified, can not start SMTP transport. No files found in `%s' No handler known for subsystem `%s' No hostkey file specified on command line No hosts loaded. Need at least one host No keywords specified! No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s No options given No outbound quota configure for network `%s', assigning default bandwidth %llu No outbound quota configured for network `%s', assigning default bandwidth %llu No policy directory specified on command line. Exiting. No port configured for plugin `%s', cannot test it No search strings file given. Exiting. No subsystem or name given No such userNo transport plugins configured, peer will never communicate No unneeded outputNo useful service enabled. Exiting. No working gnunet-helper-nat-server found None of the functions for the hostlist daemon were enabled. I have no reason to run! Not transmitting `%s' with `%s', message too big (%u bytes!). This should not happen. Notifying transport only about hostname `%s' Number of double-quotes not balanced! Number of peers to run in each round, separated by commasOn-demand lookup already took %s! Only CHK or LOC URIs supported. Option `%s' is required when using option `%s'. Option `%s' makes no sense with option `%s'. Option `%s' makes no sense without option `%s'. Option `%s' or `%s' is required when using option `%s'. Option `%s' or `%s' is required. Outbound quota configure for network `%s' is %llu PUT request not confirmed! PUT request sent with keyPacket from unknown protocol %u received. Ignored. Packet received for unmapped destination `%s' (dropping it) Peer `%s' Peer `%s' plugin `%s', address `%s', `%s' bw out: %u Bytes/s, bw in %u Bytes/s, %s Peer `%s': %s %s Perform default-actions for GNUnet URIsPlease pass valid port number as the first argument! (got `%s') Please select one operation : %s or %s or %s or %s or %s Plugin `%s' does not support URIs yet Plugin `%s' not found Plugin does not support get_keys function. Please fix! Port is required! Fix in configuration Postgres database running Postgres datacache running Preparing to stop `%s' Preprocessing complete. Print information about ATS statePrint information about connected peers.Print information about peers.Print statistics about GNUnet operations.Prints all packets that go through the DHT.Processing code for message of type %u did not call `GNUNET_SERVER_receive_done' after %s Profiler for regexProfiler for regex libraryProtocol %u not supported, dropping Publication of `%s' done Publish a file or directory on GNUnetPublishing `%s' Publishing `%s' at %llu/%llu (%s remaining) Publishing `%s' done. Publishing failed: %sQuota for network `%11s' (in/out): %10s / %10s Quotes not balanced in KSK URIRebuilding bloomfilter. Please be patient. Received %llu bytes/s (%llu bytes in %s) Received %s message Received %u bytes from %s Received DNS response that is too small (%u bytes)Received IPv4 packet with options (dropping it) Received PING from `%s' for different identity: I am `%s', PONG identity: `%s' Received a PING message with validation bug from `%s' Received invalid message from `PEERINFO' service.Received last message for %s Received malformed DNS request from %s Received malformed IPv4-UDP packet on TUN interface. Received malformed IPv6-UDP packet on TUN interface. Received malformed message via %s. Ignored. Received packet of unknown protocol %d from TUN (dropping it) Received request for our hostlist Received unexpected message of type %u in %s:%u Received unsupported DNS request from %s Recursive downloads of directories larger than 4 GB are not supported on 32-bit systems Recursive upload failed at `%s': %sRecursive upload failed: %sRefusing `%s' request to hostlist server Refusing `%s' request with %llu bytes of upload data Rejecting control connection from peer `%s', which is not me! Removing expired address of transport `%s' Require valid port number for service `%s' in configuration! Require valid port number for service in configuration! Reserving space for %u entries and %llu bytes for publication Restarting service `%s'. Result %d, type %d: %.*s Running gnunet-helper-nat-client %s %s %u Running services: SKS URI malformedSKS URI malformed (could not decode signature)SKS URI malformed (could not find signature)SKS URI malformed (could not parse expiration time)SKS URI malformed (signature failed validation)SMTP filter string to invalid, lacks ': ' SMTP filter string to long, capped to `%s' SMTP: `%s' failed: %s. Scanning directory `%s'. Scanning file `%s'. Search GNUnet for files that were published on GNUnetSent DNS request to %s Serialized metadata `%s' larger than allowed (%u>%u)Server reached maximum number connections (%u), rejecting new connection Service `%s' configured for IPv4, but IPv4 is disabled! Service `%s' is not running Service `%s' runs at %s Service `%s' took %s to terminate Service process could not initialize server function Service process failed to initialize Service process failed to report status Setup tunnels via VPN.Short read reading from file `%s'!Shutdown for plugin `%s' complete Shutdown in progress, aborting transmission. Shutting down plugin `%s' Since learning is not enabled on this peer, hostlist file `%s' was removed Size mismatch for block Size of file on disk is incorrect for this Bloom filter (want %llu, have %llu) Special file-sharing operationsSpecific IPv4 address `%s' in configuration file is invalid! Specific IPv6 address `%s' in configuration file is invalid! Specified policies directory does not exist. Exiting. Specified topology must be supported by testbedSpecified value for `%s' of service `%s' is invalid Specify the type of the record to lookupSqlite database running Sqlite datacache running Starting default services `%s' Starting download `%s'. Starting service `%s' Starting to receive benchmark data Starting transport plugins `%s' Still no peers found in `%s'! String `%s' longer than allowed (%u > %u)Successfully connected to `%s' Successfully connected to `%s', starting to send benchmark data in %u Kb blocks Syntax error while deserializing in line %u TCP Packet dropped, have no matching connection information TCP transport advertises itself as being on port %llu TCP transport listening on port %llu TCP transport not listening on any port (client only) Target filename must be specified. Template database running Template datacache running Testbed cannot be started on localhost Testing connection reversal with ICMP server. The requested amount (%llu bytes) is larger than the cache size (%llu bytes) There was trouble processing file `%s', skipping it. This may be ok if someone is currently generating a key. This may be ok if someone is currently generating a private key. This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration This system has a global IPv6 address, setting IPv6 to supported. Timeout sending PUT request! Timeout transmitting iteration request to `PEERINFO' service.Timeout trying to download hostlist from `%s' Timeout trying to resolve IP address `%s'. Timeout trying to resolve hostname `%s'. Timeout waiting for `fs' service.Topology file %s cannot be read Topology file %s has no data Topology file %s not found Topology file needs more peers than given ones Transmission to client failed! Transmitted %llu bytes/s (%llu bytes in %s) Transmitting %u bytes to %s Transport service is lacking NEIGHBOUR_LIMIT option. Tried to close sqlite without finalizing all prepared statements. Trying to connect to `%s' (%p) Trying to connect to remote host, but service `%s' is not running Trying to send with invalid session %p Trying to use file `%s' for MySQL configuration. UDP Packet dropped, have no matching connection information UDP could not transmit message to `%s': Network seems down, please check your network configuration UDP port to listen on for inbound DNS requests; default: 53UNIXPATH `%s' too long, maximum length is %llu URI is `%s'. URI to be published (can be used instead of passing a file to add keywords to the file with the respective URI)URI to import into our zoneUnable to bind listening socket for service `%s' to address `%s': %s Unable to create socket for service `%s': %s Unable to import certificate %s Unable to import private key from file `%s' Unable to initialize Postgres: %sUnable to initialize SQLite: %s. Unable to parse IPv4 address `%s' Unable to parse IPv6 address `%s' Unable to parse MX record `%s' Unable to parse PKEY record `%s' Unable to parse SOA record `%s' Unable to parse TLSA record string `%s' Unable to parse VPN record string `%s' Unable to shorten unix path `%s' while keeping name unique Unexpected address length: %u bytes Unexpected status: %d Unexpected time for a response from `fs' service.Unindex a file that was previously indexed with gnunet-publish.Unindexing at %llu/%llu (%s remaining) Unindexing done. Unknown address family %d Unknown command `%s' Unknown command, use 'q' to quit or 'r' to restart peer Unknown metadata type in metadata option `%s'. Using metadata type `unknown' instead. Unrecognized URI typeUnsupported block type %u Unsupported block type (%u) in local response! Unsupported block type (%u) in request! Unsupported form value `%s' Unsupported message of type %u (%u bytes) received from peer `%s' Unsupported type `%s' Use %s to get a list of options. Use `/help command' to get help for a specific commandUse build-in GNUnet stub resolverUsing `%s' instead Using external hostname `%s' Using port %u Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes) Value `%s' invalid for record type `%s' Value in given topology file: %s out of range WARNINGWLAN address with invalid size encountered When trying to read key file `%s' I found %u bytes but I need at least %u. Writing %u hostlist URIs to `%s' Wrong CORE service Wrong format `%s' for netmask Wrong format `%s' for network Wrote %llu bytes of statistics to `%s' You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first. You must NOT specify an URI and a filename. You must pass a number to the `%s' option. You must pass relative time to the `%s' option. You must specify a filename to inspect. You must specify one and only one directory name for automatic publication. You must specify one and only one filename for insertion. You must specify one and only one filename for unindexing. You need to specify a URI argument. `%' must be followed by HEX number`%s' failed at %s:%d with error: %s `%s' failed at %s:%u with error: %s`%s' failed for library `%s' with error: %s `%s' failed for port %d (%s). `%s' failed for port %d (%s): address already in use `%s' failed on file `%s' at %s:%d with error: %s `%s' failed to resolve method '%s' with error: %s `%s' for `%s' failed at %s:%d with error: %s `%s' is not a GNUnet directory `%s' is not a valid IP address! Ignoring BINDTOIP. `%s' is not a valid IP address. `%s' is not a valid peer identifier. `%s' must be installed SUID, refusing to run `%s:%s' failed at %s:%d with error: %s`++' not allowed in KSK URI`external-ip' command not found `upnpc' command not found aborted due to explicit disconnect requestaddadd an additional keyword for the top-level file or directory (this option can be specified multiple times)add given HELLO uri to the databaseadd recordadvertise our hostlist to other peersalso output HELLO uri(s)automatically terminate experiment after DELAYautomatically terminate search after DELAYautomatically terminate search after VALUE results are foundbbe verbose (print progress information)bootstrap using hostlists (it is highly recommended that you always use this option)bytes in hostlistbytes not included in hostlist (size limit)configuration templateconnect to a peerconnect to remote hostconsensus timeoutcould not connect to `fs' servicecreate COUNT number of peerscreate COUNT public-private key pairs (for testing)create or list public recordcreate unique configuration filesdaydaysdeldelay between roundsdelete config file and directory on exitdelete incomplete downloads (when aborted with CTRL-C)delete recorddestination IP for the tunneldisable adding the creation time to the metadata of the uploaded filedisplay recordsdo daemonize (detach from terminal)do not index, perform full insertion (stores entire file in encrypted form in GNUnet database)do not resolve IP addresses to hostnamesdo not resolve hostnamesdo not use libextractor to add keywords or metadatadon't let gnunet-service-arm inherit standard errordon't let gnunet-service-arm inherit standard outputdon't print status messagesdon't resolve host namesdownload a GNUnet directory recursivelyenable learning about hostlist servers from other peersend of timeexitexpiration time for record to use (for adding only), "never" is possibleexpired addresses encounteredextract hostkey file from pre-computed hostkey listfailed to compute hashfailed to transmit request (service down?)filename too longforeverget list of active addresses currently usedget list of all active addressesgnunet-helper-nat-client found, enabling it gnunet-helper-nat-client not found or behind NAT, disabling it gnunet-helper-nat-server found, testing it gnunet-helper-nat-server generated malformed address `%s' hhash numhelp texthostlist requests processedhostlist requests refused (not HTTP GET)hostlist requests refused (not ready)hostlist requests refused (upload data)how long should the mapping be valid for new tunnels?how long should the monitor command runhow long to execute this query before giving up?how long to store this entry in the dht (in seconds)how many parallel requests (replicas) to createhow many peers receive one value?how many replicas to createibf sizeinternal error decoding treeinternal error decrypting contentinvalid addressjust print the statistics valuelibgcrypt has not the expected version (version %s is required). limit output to statistics for the given NAMElimit output to the given SUBSYSTEMlimit to the number of connections to NSE services, 0 for nonelist all known peerslist currently running serviceslisten on specified port (default: 7777)mmake the value being set persistentmalformedmaximum path compression lengthmeasure how fast we are receiving data from all peers (until CTRL-C)monitor modemsname of the file for writing connection information and statisticsname of the file for writing statisticsname of the file for writing the main resultsname of the file with the login information for the testbedname of the option to accessname of the record to add/delete/displayname of the section to accessname of the service we would like to accessname of the table to write DFAsneed a valid IPv4 or IPv6 address needs to be an actual filenot indexednumber of common elements in A and Bnumber of element in set A-Bnumber of element in set B-Anumber of peers in consensusnumber of unique configuration files to create, or number of the hostkey to extractnumber of valuesobtain option of value as a filename (with $-expansion)only monitor DNS queriesonly monitor DNS repliesonly search the local peer (no P2P network search)only simulate the process but do not do any actual publishing (useful to compute URIs)output only the identity stringsoutput our own identity onlypeer idpeer identitypeer offering the service we would like to accesspem file to use as CAperform a reverse lookupport for remote hostpreference type to set: latency | bandwidthpreference valueprint a list of all indexed filesprint all configured quotasprint list of extracted keywords that would be used, but do not perform uploadprint the hash of the public key in ASCII formatprint the public key in ASCII formatprovide a hostlist serverprovide information about a particular tunnelprovide information about all connects and disconnect events (continuously)provide information about all current connections (continuously)provide information about all current connections (once)publish the files under the pseudonym NAME (place file into namespace)request that result should be an IPv4 addressrequest that result should be an IPv6 addressrun a testbed to measure file-sharing performancerun the experiment with COUNT peersssend data for benchmarking to the other peer (until CTRL-C)service is offered via TCPservice is offered via UDPset A recordsset AAAA recordsset preference for the given peerset the ID of this version of the publication (for namespace insertions only)set the desired LEVEL of receiver-anonymityset the desired LEVEL of sender-anonymityset the desired replication LEVELset the maximum number of parallel downloads that is allowedset the maximum number of parallel requests for blocks that is allowedset the meta-data for the given TYPE to the given VALUEsignalsignal (%d, %p) returned %d. specifies name of a file with the HOSTS the testbed should usespecify ID of an updated version to be published in the future (for namespace insertions only)specify the priority of the contentsqlite version to old to determine size, assuming zero start a particular servicestart all GNUnet default servicesstop a particular servicestop all GNUnet servicesstop and start all GNUnet default servicestest transport configuration (involves external server)the data to insert under the keythe query keythe type of data to look forthe type to insert data astime required, content pushing disabledtimeout in MSECS milliseconds for completing current operationtimeout on index-start request to `fs' servicetolerate COUNT number of continious timeout failurestype of the record to add/delete/displayunknownunknown addressunknown errorupnpc found, enabling its use upnpc not found use DHT's demultiplex everywhere optionvalue of the record to add/deletevalue to setverbose output (include ATS address properties)watch value continuouslywrite search results to file starting with PREFIXwrite the file to FILENAMEProject-Id-Version: gnunet 0.9.5a Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org POT-Creation-Date: 2014-04-08 11:11+0200 PO-Revision-Date: 2013-02-23 17:50+0100 Last-Translator: Miguel Ãngel Arruga Vivas Language-Team: Spanish Language: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); Registro corrupto o no soportado del tipo %u Se produjo un fallo al escribir en «%s»: %s # ACK recibidos vía WLAN# Destinos activos# Bytes omitidos en la cola mesh (desbordamiento)# Bytes dados para transmisión a mesh# Bytes de ancho de banda solicitados por el servicio principal# Bytes recibidos de MESH# Bytes recibidos de TUN# Bytes transmitidos a otros pares# Respuestas de cliente descartadas (ninguna petición coincidente)# mensajes «DATA» recibidos vía WLAN# Peticiones a la DHT combinadas# Mensajes «DISCONNECT» enviados# Salidas DNS fallidas (se produjo un fallo al abrir el «socket»)# Registros DNS modificados# Respuestas DNS (¿demasiado tarde?)# Respuestas DNS interceptadas# Respuestas DNS recibidas# Peticiones DNS contestadas vía interfaz TUN# Peticiones DNS omitidas (mal formadas)# Peticiones DNS omitidas (expiradas)# Peticiones DNS interceptadas# Peticiones DNS asociadas a la VPN# Peticiones DNS recibidas vía interfaz TUN# «PUT» en el almacén de datos fallidos# Búsquedas en el almacén de datos finalizadas (más de «MAX_RESULTS»)# Búsquedas en el almacén de datos finalizadas (error encolando)# Búsquedas en el almacén de datos finalizadas (encontrado último resultado)# Búsquedas en el almacén de datos finalizadas (carga demasiado alta)# Búsquedas en el almacén de datos finalizadas (sin resultados)# Búsquedas en el almacén de datos finalizadas (vistos todos)# Búsquedas en el almacén de datos iniciadas# Respuestas (REPLIES) duplicadas encontradas en la tabla de encaminamiento# Peticiones duplicadas de respuestas (REPLIES) a clientes (CLIENT) omitidas# Resultados (RESULTS) duplicados encontrados en la caché de datos# Entradas añadidas a la tabla de encaminamiento# Entradas eliminadas de la tabla de encaminamiento# Respuestas DNS externas descartadas (ninguna petición coincidente)# mensajes «FIND PEER» iniciados# Peticiones «FIND PEER» ignoradas debido a «Bloomfilter»# Peticiones «FIND PEER» ignoradas debido a falta de «HELLO»# Mensajes «GAP PUT» recibidos# peticiones «GET REPLICATION» ejecutadas# peticiones «GET REPLICATION» recibidas# peticiones «GET STOP» recibidas de clientes# peticiones «GET ZERO ANONYMITY» ejecutadas# peticiones «GET ZERO ANONYMITY» recibidas# Mensajes «GET» encolados para transmisión# peticiones «GET» ejecutadas# peticiones «GET» inyectadas de clientes# Peticiones «GET» realizadas a la caché de datos# peticiones «GET» recibidas# peticiones «GET» recibidas (de otros pares)# peticiones «GET» recibidas de clientes# Peticiones «GET» encaminadas# Buenas respuestas (REPLIES) encontradas en la tabla de encaminamiento# Buenos resultados (RESULTS) encontrados en la caché de datos# «beacons HELLO» enviados vía WLAN# Mensajes «HELLO» rumoreados# mensajes «HELLO» recibidos# mensajes HELLO recibidos vía WLAN# «HELLO» obtenidos de «peerinfo»# Peticiones de salida IP por ICMP recibidas vía mesh# Paquetes ICMP omitidos (tipo no permitido)# Paquetes ICMP recibidos de mesh# Paquetes ICMP enviados vía TUN# Peticiones de servicio ICMP recibidas vía mesh# Paquetes ICMPv4 omitidos (imposible atravesar v6)# Paquetes ICMPv4 omitidos (no permitido)# Paquetes ICMPv4 omitidos (tipo no permitido)# Paquetes ICMPv6 omitidos (imposible atravesar v4)# Paquetes ICMPv6 omitidos (no permitido)# Paquetes ICMPv6 omitidos (tipo no permitido)# beacons HELLO broadcast IPv4 recibidos vía UDP# beacons HELLO multicast IPv6 recibidos vía UDP# Elementos (ITEMS) almacenados en la caché de datos# Respuestas (REPLIES) no válidas encontradas en la tabla de encaminamiento# Resultados (RESULTS) no válidos encontrados en la caché de datos# Respuestas (REPLIES) irrelevantes encontradas en la tabla de encaminamiento# Resultados (RESULTS) irrelevantes encontrados en la caché de datos# mensajes «KEEPALIVE» descartados (no hay sesión)# Mensajes «KEEPALIVE» descartados (par desconocido)# mensajes «KEEPALIVE_RESPONSE» descartados (no conectado)# Mensajes «KEEPALIVE_RESPONSE» descartados (no esperado)# Coincidencias de clave, diferencias de tipo en la respuesta (REPLY) del cliente (CLIENT)# Rutas en bucle local eliminadas# Estimaciones del tamaño de red recibidas# Paquetes UDP no-DNS recibidos vía interfaz TUN# Peticiones «FIND PEER» P2P procesadas# Peticiones «GET» P2P SOLAMENTE encaminadas# Peticiones «GET» P2P recibidas# Peticiones «PUT» P2P recibidas# Resultados (RESULTS) P2P recibidos# Mensajes P2P omitidos debido a saturación de la cola# mensajes de búsqueda P2P recibidos y procesados# busquedas P2P activas# búsquedas P2P destruidas debido a respuesta definitiva# Mensajes PING recibidos para un par diferente# mensajes PING recibidos# Mensajes PING sin HELLO mandados# mensajes PONG creados# mensajes PONG descifrados# mensajes PONG recibidos# PONG omitidos, no hay una validación pendiente coincidente# Mensajes PONG omitidos, firma expirada# multicast de PONG a todas las direcciones disponibles# unicast de PONG vía transporte confiable# mensajes «PUT» encolados para transmisión# peticiones «PUT» ejecutadas# peticiones «PUT» recibidas de clientes# Peticiones «PUT» encaminadas# Paquetes recibidos de TUN# Paquetes recibidos de la interfaz TUN# Selecciones de pares fallidas# Pares excluidos del encaminado debido a «Bloomfilter»# Peticiones pendientes activas# Peticiones pendientes creadas# Actualizaciones de preferencias dadas al servicio principal# Mensajes encolados descartados (par desconectado)# Peticiones «RELEASE RESERVE» ejecutadas# peticiones «REMOVE» ejecutadas# peticiones «REMOVE» recibidas# Respuestas (REPLIES) ignoradas para clientes (CLIENTS) (sin coincidencia)# mensajes «REQUEST CONNECT» recibidos# peticiones «RESERVE» ejecutadas# Mensajes «RESULT» encolados para transmisión# Resultados (RESULTS) encolados para clientes# Respuestas recibidas de la DHT# Peticiones omitidas de la cola del almacén de datos# Resultados recibidos# Mensajes «SET QUOTA» ignorados (no existe tal par)# Peticiones de datos (DATA) TCP omitidas (no hay sesión)# Peticiones de creación de salida IP por TCP recibidas vía mesh# Mensajes «WELCOME» TCP recibidos# Peticiones de datos TCP recibidas vía mesh# Paquetes TCP recibidos de mesh# Paquetes TCP enviados vía TUN# Peticiones TCP omitidas (no existe tal servicio)# Peticiones de creaciones de servicio TCP recibidas vía mesh# Sesiones TCP activas# Peticiones de salida IP por UDP recibidas vía mesh# Paquetes UDP recibidos de mesh# Paquetes UDP enviados vía TUN# Peticiones UDP omitidas (no existe tal servicio)# Peticiones de servicio UDP recibidas vía mesh# peticiones «UPDATE» ejecutadas# peticiones «UPDATE» recibidas# Respuestas (REPLIES) no soportadas encontradas en la tabla de encaminamiento# Resultados (RESULTS) no soportados encontrados en la caché de datos# ACK WLAN enviados# mensajes DATA WLAN descartados debido a un error en el CRC32# mensajes «DATA» WLAN procesados# MAC de destino WLAN alojadas# fragmentos de mensaje WLAN enviados# mensajes WLAN defragmentados# mensajes WLAN pendientes (con fragmentación)# sesiones WLAN alojadas# reconocimientos enviados por framentos# conexiones activas# registros de direcciones descartados# revalidaciones de direcciones iniciadas# URI anunciadas «%s» descargadas# URI de listas de máquinas anunciadas# retardos artificiales introducidos (ms)# retardo de retransmisión medio (ms)# violaciones de la cuota de ancho de banda por otros pares# bits eliminados de reconocimientos de fragmentos# bytes actualmente en los buffer TCP# bytes descifrados# bytes descartados por TCP (desconectado)# bytes omitidos por TCP (expirados)# bytes descargados de servidores de listas de máquinas# bytes omitidos (mensaje antiguo)# bytes omitidos (duplicados)# bytes omitidos (fuera de secuencia)# bytes omitidos por SMTP (salientes)# bytes cifrados# bytes expirados# bytes en la cola de mensajes para otros pares# bytes de mensajes del tipo %u recibidos# bytes de «payload» descifrados# bytes de «payload» omitidos (el otro par no estaba conectado)# bytes de «payload» recibidos# bytes purgados (baja prioridad)# bytes recibidos vía SMTP# bytes recibidos vía TCP# bytes eliminados (petición explícita)# bytes mandados al almacén de datos# bytes enviados vía SMTP# bytes almacenados# total de bytes recibidos# bytes recibidos vía TCP# bytes usados en el almacén de ficheros compartidos «%s»# tamaño de la caché# búsquedas de clientes activas# búsquedas de clientes recibidas# búsquedas de clientes actualizadas (contenido unido visto en la lista)# peticiones de conexión requeridas al servicio de transporte# conexiones a almacenes de datos (re)creadas# mensajes de desconexión ignorados (marca temporal)# desconexiones del par debido a una petición explícita# desconexiones debido a la lista negra# desconexiones debido a una cuota de 0# fragmentos duplicados recibidos# respuestas duplicadas descartadas (bloomfilter)# bytes cifrados dados al transporte# reconocimientos de fragmentos recibidos# transmisiones de fragmentos completadas# fragmentos recibidos# fragmentos recibidos vía WLAN# fragmentos retransmitidos# fragmentos transmitidos# encajes de fragmentos# amigos conectados# amigos en configuración# URI de listas de máquinas leídas de fichero# URI de listas de máquinas escritas a fichero# anuncios de listas de máquinas enviados# descargas de listas de máquinas iniciadas# bloques de índice eliminados: fichero original inaccesible# «HELLO» no válidos descargados de servidores de listas de máquinas# respuestas irrelevantes descartadas# elementos almacenados# mensajes «keepalive» enviados# «keepalives» enviados# intercambio de claves iniciados# intercambio de claves parados# mensajes defragmentados# mensajes descartados (expirados antes de su transmisión)# mensajes descartados (sesión desconectada)# mensajes descartados debido a la falta de registro vecinal# mensajes omitidos debido a un cliente lento# mensajes fragmentados# mensajes expirados mientras estaban en la cola de transporte# mensajes transmitidos a otros pares# mensajes de detención de migración recibidos# mensajes de detención de migración enviados# milisegundos entre descargas de listas de máquinas# ms de impulso sugeridos# entradas de vecinos alojadas# eventos de desconexión TCP a nivel de red# peticiones asociadas de bloques bajo demanda# búsquedas fallidas de bloques bajo demanda# búsquedas satisfactorias de bloques bajo demanda# pares en la lista negra# pares conectados# pares conocidos# mensajes de búsqueda enviados a otros pares# entradas de planes de búsqueda# planes de búsqueda ejecutados# entradas creadas en la cola# expiraciones de plazo en la cola de entradas# desbordamientos de la cola# cuota# refrescos de mi «HELLO»# operaciones de cambio de clave confirmadas vía PONG# respuestas omitidas# respuestas omitidas debido a insuficiente tráfico de cobertura# respuestas omitidas debido a incompatibilidad de tipos# respuestas recibidas y asociadas# respuestas recibidas de clientes locales# respuestas recibidas de otros pares# respuestas transmitidas a otros pares# peticiones omitidas, prioridad insuficiente# «DBLOCK» o «IBLOCK» pedido no encontrado# peticiones realizadas por un precio (carga normal)# peticiones realizadas gratuitamente (baja carga)# peticiones omitidas debido a expiración del TTL# peticiones omitidas debido a una petición de mayor TTL# peticiones omitidas debido a que el iniciador no está conectado# peticiones omitidas debido a falta de ruta inversa# peticiones filtradas por el «bloomfilter»# peticiones filtradas por el «bloomfilter»# peticiones unidas# peticiones recibidas# peticiones refrescadas# reservado# resultados encontrados# resultados hallados localmente# latencia media de P2P en ejecución (ms)# peticiones de envío descartadas (desconectado)# claves de sesión confirmadas vía PONG# sesiones terminadas por plazo de expiración# sesiones terminadas por desconexión de transporte# mensajes de estado recibidos# peticiones de almacenamiento omitidas debido a alta carga# tamaño total de los mensajes fragmentados# transmisión fallida (el servicio principal no tiene ancho de banda)# fallos de transmisión en mensajes a otros pares# fallos en peticiones de transmisión# peticiones de desconexión del servicio de transporte por TCP# envíos de refrescos del mapa de tipos# mapas de tipos recibidos# Mensajes «CONNECT_ACK» inesperados (desconectando)# Mensajes «CONNECT_ACK» inesperados (sin par)# Mensajes «CONNECT_ACK» inesperados (no estaba preparado)# Mensajes «CONNECT_ACK» inesperados (esperando en el ATS)# actualizaciones de mi mapa de tipos# «HELLO» válidos descargados de servidores de listas de máquinas%24s: %-17s %4s (%u conexiones en total) %s falló en %s:%d: «%s». ¡Petición %s recibida, pero no tiene caché de datos! El servicio %s carece de opciones de configuración de clave (%s). Saliendo. %s: opción ilegal -- %c %s: opción no válida -- %c %s: la opción «%c%s» no permite un parámetro %s: la opción «%s» es ambigua %s: la opción «%s» requiere un parámetro %s: la opción «--%s» no permite un parámetro %s: la opción «-W %s» no permite un parámetro %s: la opción «-W %s» es ambigua %s: la opción requiere un parámetro -- %c %s: opción no reconocida «%c%s» %s: opción no reconocida «--%s» %u resoluciones de dirección pasaron de plazo %u URI de listas de máquinas cargadas del fichero el parámetro --option es necesario para establecer un valor el parámetro --section es necesario 0 msUn puerto debe estar entre 1 y 65534 para conectar a la máquina «%s» Se necesita un puerto para conectar con la máquina «%s» El ARM ahora gestiona las conexiones del servicio «%s» en «%s» El ATS devolvió resultados para %u direcciones Aceptando conexión (%u de %u) desde «%s» Aceptando conexión desde «%s»: %p Acceso denegado a «%s» Acceso denegado desde «%s» al servicio «%s» Acceso desde la conexión %p (%u de %u) para «%s» «%s» URL «%s» con tamaño de los datos de subida %u Añadiendo «%s» sin direcciones para el par «%s» No se pudo añadir la máquina %u por el error: %s No se pudo añadir el registro: %s Añadiendo el almacén de datos de la lista de máquinas probada «%s». Dirección para obtener la lista de máquinas: «%s» Lista de máquinas anunciada con la URI «%s» no pudo ser descargada. La URI anunciada es descartada. Los mensajes de anuncio no pudieron encolarse por el servicio principal Los parámetros obligatorios para las opciones largas también lo son para sus versiones cortas. Aserción fallida en %s:%d. ¡Intento de cancelar la tarea muerta %llu! El intento de conectar a «%s» falló Sufijo DNS autoritativo a usar (opcional); predeterminado: zkey.euSufijo FCFS autoritativo a usar (opcional); predeterminado: fcfs.zkey.euPublicar automáticamente ficheros de un directorio en GNUnetAsociando a la dirección IPv4 %s Asociando a la dirección IPv6 %s El bloque no es del tipo %u El bloque del tipo %u está mal formado Construcción de «bloomfilter» completa. Inicializando usando lista de máquinas en «%s». Llamar con el nombre del fichero «HELLO» para modificar. No se pudo indexar el fichero «%s»: %s. Se intentará insertar. Imposible cambiar el usuario/grupo a «%s»: %s No se puede conectar al servicio ATS, saliendo... No se puede habilitar salida IPv4 pero se deshabilita IPv4 sobre interfaz TUN, se usará ENABLE_IPv4=YES No se pudo habilitar la salida IPv6 pero se deshabilita IPv6 sobre interfaz TUN, se usará ENABLE_IPv6=YES ¡No se pueden extraer metadatos de una URI! No se puede iniciar una petición al servicio ATS, saliendo... No se pudo obtener información acerca del usuario «%s»: %s No se puede procesar la petición DNS de %s No se puede iniciar el controlador maestroCambiar las respuestas DNS apuntando a cualquier otro lado.Los conjuntos de caracteres pedidos fueron «%s»->«%s» Limpieza completada El cliente se desconectó del servicio principal, tratando de reconectar. Herramienta de línea de comandos para acceder a la biblioteca de pruebas¡La configuración no especifica la opción «%s» en la sección «%s»! La configuración requiere «%s», pero el binario no está instalado de forma correcta (SUID bit no activado). Opción deshabilitada. La configuración especifica un valor no válido en la opción «%s» de la sección «%s»: %s El valor de configuración «%s» para «%s» de la sección «%s» no está dentro de las opciones legales La salida DNS configurada «%s» no funciona o no es válida. Conectado aContenido no encontradoServicios de control y el Gestor de Reinicio Automático (ARM en inglés)Al servicio principal le falta la configuración de la clave de máquina (HOSTKEY). Saliendo. El servicio principal de «%4s» está listo. No se pudo acceder al servicio de información de pares (PEERINFO). Saliendo. No se pudo acceder a un «socket» pre-ascociado, lo intentaré asociar yo mismo No se pudo acceder al fichero de configuración «%s» No se pudo acceder al fichero «%s»: %s No se pudo acceder al fichero de clave de máquina «%s». No se pudo acceder al fichero indexado «%s» (%s) en el desplazamiento %llu: %s No se pudo acceder al «socket» pre-ascociado %u, lo intentaré asociar yo mismo No se pudo bloquear el fichero «%s»: %s... No se pudo asociar con ningún puerto: %s ¡No se pudo conectar al servicio %s! ¡No se pudo conectar a la DHT! No se pudo conectar al servicio %s. No se pudo conectar con el almacén de datos.¡No se pudo crear un certificado TLS nuevo, el programa «gnunet-transport-certificate-creation» no pudo ser iniciado! No se pudo crear URI de palabra clave a partir de los parámetros. No se pudo determinar la ruta de instalación de %s. Establezca la variable de entorno «%s». No se pudo determinar la ruta de instalación de los módulos. No se pudo determinar un nombre de máquina y un puerto válidos para el servicio «%s» a partir de la configuración. No se pudo extraer la clave de máquina %u (¿desplazamiento demasiado grande?) No se encontró la IP del host «%s»: %s ¡No se pudo encontrar el programa llamado «%s» en PATH! No se pudo encontrar una reserva coincidenteNo se pudo manejar una petición de lista de máquinas debido a que no hay una respuesta todavía No se pudo inicializar el subsistema «%s». ¡No se pudo inicializar el multi-manejador de curl, no se pudo iniciar el módulo %s! No se pudieron cargar las cuotas para la red «%s»: «%s», asignando el ancho de banda predeterminado %llu No se pudo abrir «%s». No se pudo abrir el fichero «%s» en modo lectura para cargar las listas de máquinas: %s No se pudo abrir el fichero «%s» en modo escritura para almacenar las listas de máquinas: %s No se pudo abrir el fichero «%s»: %sNo se pudo procesar la especificación de red IPv4 «%s» para «%s:%s» No se pudo procesar la especificación de red IPv6 «%s» para «%s:%s» ¡No se pudo enviar respuesta al cliente, el mensaje es demasiado grande! No se pudo publicar No se pudo leer el fichero «%s»: %sNo se pudo resolver «%s» (%s): %s No se pudo resolver nuestro nombre de dominio cualificado (FQDN) : %s No se pudo retomar la búsqueda en ejecución, se retomará como una búsqueda en pausa No se pudieron guardar algunas estadísticas persistentes No se pudo mandar el resultado (lista) al cliente No se pudo mandar el resultado (estado) al cliente No se pudo arrancar un servidor de listas de máquinas HTTP en el puerto %u No se pudo empezar a publicar. No se pudo empezar a buscar. No se pudo empezar la operación de desindexado. No se pudo enviar correctamente la petición, no se espera recibir una respuesta. No se pudo usar el nombre de fichero especificado «%s» para «bloomfilter». Generando una clave privada nueva. Esto puede tomar un tiempo. DEPURACIÓNDemonio para anunciar expresiones regulares para el par usando mesh.Demonio a ejecutar para realizar la traducción de protocolo IP a GNUnetDemonio a ejecutar para obtener un nodo de salida IP para la VPNDemonio para medir el rendimiento de usar compartición de archivos.¡La búsqueda en el almacén de datos toma %s! El «payload» del almacén de datos es impreciso (%lld < %lld). Intentando repararlo. ¡El servicio predeterminado «%s» no está configurado correctamente! Detectada IP externa «%s» Detectada dirección de la red interna «%s». No se encontró el tipo MIME «%s» en la lista de extensiones. No se encontró un «HELLO» bien formado en el fichero «%s» Acceso directo al servicio de transporte.Contenidos del directorio «%s»: Metadatos del directorio «%s»: Directorio demasiado grande para el espacio de direccionamiento del sistema ¡Deshabilitando IPv6 ya que no está soportado en este sistema! Deshabilitando el soporte para IPv6 para el servicio «%s», se produjo un fallo al crear un «socket» IPv6: %s Deshabilitando el soporte de dominio de «sockets» UNIX para el servicio «%s», no se pudo crear un «socket» UNIX: %s Desconectado deDesconectado del par «%s» mientras probaba Muestra los contenidos de un directorio GNUnetEl nombre de dominio no puede contener «+» El nombre de dominio no puede contener «.» Descarga fallida: no se pudo abrir el fichero «%s»: %sDescargar ficheros de GNUnet usando una URI GNUnet CHK o LOC (gnunet://fs/chk/...)Límite de descarga de %u bytes superado, parando descarga Descarga de lista de máquinas «%s» completada. Descarga de lista de máquinas de «%s» fallida: «%s» Descargando «%s» en %llu/%llu (%s restantes, %s/s). El bloque tardó %s en descargarse Finalizada descarga «%s» (%s/s). Mensaje omitido de tipo %u y tamaño %u, hay %u/%u mensajes pendientes El firmado ECC falló en %s:%d: %s ERRORFin del ficheroError accediendo al fichero «%s»: %s Error al comunicar con el ARM. ¿Está el ARM ejecutándose? Error creando el túnel Error descargando: %s. Error en la comunicación con el servicio de información de pares (PEERINFO): %s Error cargando cadenas de búsqueda. Saliendo. Error abriendo fichero «%s»: %s Error publicando: %s. Error leyendo «%s»: %sError leyendo de «%s»: %s Se produjo un error leyendo la cadena «%s»Error leyendo respuesta del servicio de almacenamiento de datosError buscando: %s. Error desindexando: %s. Error escribiendo «HELLO» al fichero «%s»: %s Error escribiendo «%s». Error escribiendo URI de listas de máquinas al fichero «%s» Error escribiendo a «%s»: %s ¡Se esperaba que «%s» fuera un directorio! Violación externa del protocolo detectada en %s:%d. Extracción de metadatos del fichero «%s» completa. Se produjo un fallo al acceder «%s»: %s Se produjo un fallo al alojar las direcciones IP para el nuevo destino Se produjo un fallo al cerrar la sentencia %p: %d Se produjo un fallo al calcular el hash del fichero.Se produjo un fallo al conectar con el servicio %s. Saliendo. ¡Se produjo un fallo al conectar con el servicio DHT! Se produjo un fallo al conectar con el servicio «FS» para el desindexado.Se produjo un fallo al conectar con GNS Se produjo un fallo al conectar con «%s» Se produjo un fallo al conectar con el servicio «%s». Se produjo un fallo al conectar con el servicio de almacenamiento de datos (datastore).Se produjo un fallo al conectar con «gnunet-nat-server» ¡Se produjo un fallo al conectar con el servicio principal, no se puede gestionar la topología! Se produjo un fallo al conectar con el almacén de datos.Se produjo un fallo al conectar con el almacén de nombres ¡Se produjo un fallo al conectar con el servicio DHT! ¡Se produjo un fallo al conectar con el almacén de nombres! Se produjo un fallo al conectar con el servicio de transporte ¡Se produjo un fallo al conectar con el servicio de transporte! Se produjo un fallo al convertir el nombre en formato DNS IDNA «%s» a UTF-8: %s Se produjo un fallo al convertir el nombre en UTF-8 «%s» al formato DNS IDNA: %s Se produjo un fallo al crear la configuración para el par (¿no hay suficientes puertos libres?) Se produjo un fallo al crear el directorio para la descarga recursiva de «%s» Se produjo un fallo al crear los índices Se produjo un fallo al crear el «socket» de escucha asociado a «%s» para pruebas NAT: %s Se produjo un fallo al crear o acceder al directorio para el fichero de log «%s» Se produjo un fallo al crear la página para «%s» Se produjo un fallo al crear un registro para el dominio «%s»: %s Se produjo un fallo al eliminar el bloque defectuoso: %s Se produjo un fallo al borrar una tabla de la base de datos. Se produjo un fallo al establecer la conexión TCP a «%s:%u», no quedan direcciones por probar. Se produjo un fallo al expandir «$HOME»: variable de entorno «HOME» no establecidaNo se encontró la dirección %s para «%s». Se produjo un fallo al buscar la posición dada en el ficheroNo se encontraron direcciones IPv4 libres en el rango de la VPN No se encontraron direcciones IPv6 libres en el rango de la VPN Se produjo un fallo al obtener KSKs de la búsqueda de directorios.Se produjo un fallo al obtener los identificadores de fichero para «%s» Se produjo un fallo al inicializar «bloomfilter». Se produjo un fallo al inicializar la clave de la máquina desde el par %u ¡Se produjo un fallo al inicializar la biblioteca de pruebas! Se produjo un fallo al inicializar la rutina de visualización No se pudieron listar las conexiones, expiró el plazo Se produjo un fallo al cargar la configuración de %s Se produjo un fallo al cargar el módulo de la cache de datos para «%s» Se produjo un fallo al inicializar el módulo del almacén de datos para «%s» Se produjo un fallo al cargar el estado: %s Se produjo un fallo al cargar el módulo del transporte para «%s» Se produjo un fallo al conectar con el servicio «%s». Se produjo un fallo al obtener las estadísticas de la máquina «%s:%llu» Se produjo un fallo al obtener las estadísticas. Se produjo un fallo al abrir los «sockets» UDP Se produjo un fallo al abrir «%s» para escritura: %s Se produjo un fallo al abrir «%s»: %s Se produjo un fallo al abrir «%s» para escrituraSe produjo un fallo al abrir el fichero para desindexado.Se produjo un fallo al empaquetar la petición DNS. Omitiendo. ¡Se produjo un fallo al empaquetar una respuesta DNS en un paquete UDP! Se produjo un fallo al procesar la petición DNS. Omitiendo. Se produjo un fallo al procesar un mensaje «HELLO»: tiempo de expiración no válido Se produjo un fallo al procesar un mensaje «HELLO»: mal formado Se produjo un fallo al procesar un mensaje «HELLO»: falta el tiempo de expiración Se produjo un fallo al procesar un mensaje «HELLO»: falta el módulo de transporte Se produjo un fallo al procesar la URI: %s Se produjo un fallo al procesar «%s» como una dirección para el módulo «%s» Se produjo un fallo al procesar el mensaje interno del programa auxiliar «%s» Se produjo un fallo al procesar la identidad del par «%s» Se produjo un fallo al preparar la sentencia «%s» Se produjo un fallo al leer el directorio «%s» No se pudo leer el ficheroSe produjo un fallo al leer el índice de pares del archivo de topología: %sSe produjo un fallo al leer índice de pares del fichero de topología: %s¡No se ha recibido el reconocimiento del servicio de estadísticas, algunas estadísticas se pueden haber perdido! No se ha recibido la respuesta para la petición «%s» del servicio «%s». No se obtuvo respuesta del servicio de información de pares (PEERINFO).Se produjo un fallo al recibir la respuesta de la base de datos. Se produjo un fallo al recibir el estado de respuesta de la base de datos.No se ha recibido una respuesta válida para la petición «%s» del servicio «%s». Se produjo un fallo al borrar el fichero de configuración defectuoso de «bloomfilter» «%s»: Se produjo un fallo al borrar el fichero de configuración %s Se produjo un fallo al eliminar el directorio «servicehome» %s. Se produjo un fallo al resolver «%s»: %s Se produjo un fallo al resolver la dirección para el par «%s» Se produjo un fallo al retomar la operación de publicación «%s»: %s Se produjo un fallo al retomar la operación de publicación «%s»: %s Se produjo un fallo al retomar la sub-descarga «%s»: %s Se produjo un fallo al retomar la sub-descarga «%s»: no se pudo abrir el fichero «%s» Se produjo un fallo al retomar la sub-búsqueda «%s»: %s Se produjo un fallo al retomar la operación de desindexado «%s»: %s Se produjo un fallo al ejecutar «%s» Se produjo un fallo al guardar el estado en el fichero %s Se produjo un fallo al buscar en el desplazamiento %llu del fichero «%s»: %sSe produjo un fallo al mandar la petición DNS a %s Se produjo un fallo al enviar una petición de conexión al servicio de transporte Se produjo un fallo al enviar una petición al servicio de transporte Se produjo un fallo al establecer la opción de «broadcast» IPv4 para el «socket» en el puerto %d Se produjo un fallo al configurar el post-procesador para «%s» Se produjo un fallo al arrancar %s Se produjo un fallo al iniciar el servidor HTTP Se produjo un fallo al inciar «%s» en «%s» Se produjo un fallo al arrancar «%s»: %s Se produjo un fallo al iniciar el meta-escáner de directorios. ¿Está «gnunet-helper-publish-fs» instalado? Se produjo un fallo al iniciar el servicio «%s» Se produjo un fallo al iniciar el servicio. Se produjo un fallo al transmitir la petición de eliminación a la base de datos. Se produjo un fallo al escribir «%s»: %s Se produjo un fallo al escribir el bloque de %u bytes en el desplazamiento %llu del fichero «%s»: %sSe produjo un fallo al escribir el fichero de configuración «%s» para el par %u: %s Se produjo un fallo al escribir el directorio con los resultados de búsqueda de «%s» Se produjo un fallo al escribir la clave de la máquina para el par %u: %s Fallo añadiendo «HELLO»: %s Se produjo un fallo al transmitir la petición al servicio «%s» Se produjo un fallo mientras se retomaba de la operación de descarga «%s»: %s Fallo mientras se reiniciaba la operación de publicación «%s»: %s Se produjo un fallo mientras se retomaba la operación de búsqueda «%s»: %s Se produjo un fallo mientras se retomaba la operación de publicación «%s»: %s Error fatal al inicializar la API del ARM. ¡Error lógico interno fatal, el proceso está colgado en «%s» (abortar con CTRL-C)! Menos amigos especificados que los requeridos por el contador mínimo de amigos. Sólo me conectaré a amigos. El fichero «%s» en el directorio «%s» no sigue la convención de nombres. Eliminado. El fichero «%s» es demasiado grande para ser un «HELLO» El fichero «%s» es demasiado pequeño para ser un «HELLO» Encontradas %u direcciones para comunicar al servicio NAT Encontrados %u registros para el dominio «%s» Encontrado nombre «%s» para la clave dada Encontrado amigo «%s» en la configuración Me he encontrado «%s» en mi lista de amigos (inútil, ignorado) Pasarela GNUnet DNS-a-GNS (un servidor DNS)Proxy GNUnet GNSDemonio de ayuda en las pruebas de recorrido NAT de GNUnetServidor y cliente GNUnet de listas de máquinasControl de topología de GNUnet (manteniendo las restricciones del mesh de P2P y de F2F)Herramienta de manipulación de zona de GNUnetGenerando %u claves, por favor, espereLa opción «%s» dada está fuera de rango: %llu > %u Hay registros de servicios duplicados para «%s:%u» Se obtuvo un paquete no-IP con %u bytes y protocolo %u de TUN Se obtuvo un resultado con un tipo desconocido de bloque «%d», ignorándolo«HELLO» sin dirección encontrados (ignorados)Hash no asociado intentando indexar el fichero «%s» que tiene hash «%s» Hay %u/%u conexiones. Se considerará descargar una lista de máquinas en %s No hay ni puerto (PORT) ni ruta unix (UNIXPATH) para el servicio «%s», pero uno es necesario Base de datos de montículo ejecutándose Caché de datos de montículo (heap) ejecutándose El ejecutable auxiliar «%s» no tiene activado el bit SUID, no se puede ejecutar el transporte WLAN La máquina %s no puede comenzar la batería de pruebas El registro de máquinas falló para una máquina. Error: %s El fichero de máquinas no fue encontrado: %s El fichero de listas de máquinas «%s» no pudo ser eliminado El fichero de listas de máquinas «%s» no existe Servicio de listas de máquinas arranca en %s:%llu El archivo de máquinas %s no puede leerse El archivo de máquinas %s no tiene datos El fichero de máquinas %s no fue encontrado Yo soy el par «%s». Paquete ICMP omitido, no hay información de conexiones coincidente INFORMACIÓNNO VÃLIDOIP del resolvedor recursivo DNS a usar (requerido)Opciones de paquete IPv4 recibidas. Ignoradas. Recibido paquete IPv4 con cabecera «next» no soportada %u. Ignorado. El soporte de IPv4 se deshabilita porque este sistema no soporta IPv4 El soporte IPv4 es %s La dirección IPv6 contenía «:» para separar el número de puerto La dirección IPv6 contenía «]» antes de «:» para separar el número de puerto La dirección IPv6 contenía un número de puerto válido después del último «:» La dirección IPv6 no empezaba con «[» Recibido paquete IPv6 con cabecera «next» no soportada %d. Ignorado. El soporte de IPv6 se deshabilita porque este sistema no soporta IPv6 El soporte IPv6 es %s Ignorando conexión del par %u al par %u Importando HELLO de «%s» La cuota de entrada configurada para la red «%s» es %llu El fichero de máquinas no tiene el formato correcto: %s La petición de indexado recibida para el fichero «%s» ya está indexada como «%s». Se permite de todos modos. El fichero indexado «%s» ha cambiado en el desplazamiento %llu ¡La inicialización del mecanismo de módulos falló: %s! Iniciando apagado bajo petición del cliente. Espacio insuficiente (%llu bytes están disponibles) para satisfacer la petición «%s» de %llu bytes Espacio insuficiente para publicar: %sEspacio insuficiente para satisfacer la peticiónEspacio insuficiente para satisfacer la petición y la cantidad pedida es mayor que el tamaño de la cachéDirecciones internas IP no conocidas, no se puede usar el método del recorrido NAT ICMP Error interno o URI de descarga defectuosa (se esperaban %u bytes a profundidad %u y desplazamiento %llu/%llu, se obtuvieron %u bytes)Error interno escaneando «%s». Error interno escaneando directorio. Error interno.Dirección IPv6 «%s» no válida: %s Dirección IPv6 no válida: «%s» URI no válidaURI no válida: «%s» URI no válida: no comienza con «%s» URI no válida: falla al especificar el subsistema Mensaje «%s» no válido recibido de la lista de máquinas en «%s» Parámetro no válido «%s» Parámetro no válido «%s» en la línea de comandos Datos no válidos en la base de datos. Intentando arreglar (por borrado). Mensaje de error no válido recibido del servicio de almacenamiento de datosFormato no válido para la IP: «%s» Notación de red no válida («/%d» no es válido en IPv4 CIDR).Notación de red no válida (no termina con «;»: «%s») Número de puerto %llu no válido. Saliendo. Respuesta no válida del servicio «fs».Formato de tiempo no válido «%s» Iniciando una peticion «GET» a la DHT de GNUnet, imprimiendo resultados.Inicianco una petición «PUT» a la DHT de GNUnet para insertar «DATA» bajo «KEY».Enviando un «GET» DHT con clave¡Iniciando petición de subida para «%s» con datos «%s»! El número de clave %u no existe Palabras clave para el fichero «%s» (%s) Falta configuración sobre las opciones de claves. El aprendizaje está habilitado en este par El aprendizaje no está habilitado en este par Los controladores de enlazado fallaron. SaliendoCargando %llu bytes de estadísticas de «%s» Cargando el módulo de la cache de datos «%s» Cargando el módulo del almacén de datos «%s» Cargando el módulo de transporte «%s» La carga de la clave de la máquina desde «%s» ha fallado. Cargando entradas guardadas de listas de máquinas del fichero «%s» Parece que estamos en espera ocupada... Buscar el registro para el nombre dadoNo hay coincidencia con «MAGIC». Esto no es un directorio GNUnet. URI CHK mal formadaURI KSK mal formada (no debe empezar ni terminar con «+»)URI SKS mal formadaManipular ficheros de configuración de GNUnetManipular los ficheros de clave privada ECC de GNUnetEl número máximo de conexiones es %u Medir la calidad y rendimiento del servicio NSE.Mensaje `%.*s» repetido %u veces en el último %s La extracción de metadatos ha finalizado. Metadatos para el fichero «%s» (%s) Se produjo un fallo al deserializar los metadatos «%s»Migración de contenido al par «%s» bloqueada durante %s Falta el argumento: nombre Falta el parámetro: subsistema Falta la opción «%s» para la operación «%s» Monitorizar consultas DNS.Más conexiones amistosas requeridas que el número objetivo total de conexiones. Múltiples operaciones introducidas. Por favor, seleccione únicamente una operación: %s, %s, %s, %s, %s, %s ¡Se deben proveer «KEY» y «DATA» para una subida a la DHT! ¡Se debe proveer una clave para el «GET» DHT! ¡Se debe especificar «%s» para «%s» en la configuración! ¡Se debe especificar «%s» o una dirección numérica IP para «%s» de «%s» en la configuración! Base de datos Mysql ejecutándose Recorrido NAT con servidor ICMP fallido. Recorrido NAT con servidor ICMP satisfactorio. Recorrido NAT con servidor ICMP expirado. NINGUNOSe necesitan %llu bytes más de espacio (%llu permitidos, usando %llu) Se necesita un nombre de máquina no vacío para el servicio «%s». ¡Ni IPv4 ni IPv6 están habilitadas! Corrija la configuración ¡No se encontraron direcciones IP para el nombre de máquina «%s» del servicio «%s»! No se ha especificado una URI en la línea de comandos. Saliendo. ¡No se ha especificado ningún «%s» para «%s» en la configuración! ¡No se encontraron direcciones para el nombre de máquina «%s» del servicio «%s»! No se ha introducido ningún fichero de configuración. Saliendo No hay servicios predeterminados configurados, GNUnet no va a iniciarse realmente ahora. No se ha especificado una dirección de correo, no se puede iniciar el transporte SMTP. No se han encontrado ficheros en «%s» No hay un manejador conocido para el subsistema «%s» No se ha especificado la clave de máquina en la línea de comandos No se han cargado máquinas. Se necesita al menos una máquina. ¡Ninguna palabra clave especificada! Ninguna operación introducida. Por favor, seleccione alguna operación: %s, %s, %s, %s, %s, %s No se han proporcionado opciones No hay configurada una cuota de salida para la red «%s», asignando el ancho de banda predeterminado %llu No hay configurada una cuota de salida para la red «%s», asignando el ancho de banda predeterminado %llu No se ha especificado una política de directorios en la línea de comandos. Saliendo. Ningún puerto fue configurado para el módulo «%s», no se puede probar No se ha proporcionado un fichero de cadenas de búsqueda. Saliendo. No se proporcionó un subsistema o un nombre No existe tal usuarioNo hay módulos de transporte configurados, el par nunca se comunicará Sin salida innecesariaNingún servicio útil habilitado. Saliendo. No se ha encontrado un «gnunet-helper-nat-server» funcional Ninguna de las funciones para el demonio de listas de máquinas fue activada. ¡No tengo razón para ejecutarme! No transmitiendo «%s» con «%s», mensaje demasiado grande (¡%u bytes!). Esto no debería suceder. Notificando al transporte sólo el nombre de máquina «%s» ¡Número de comillas dobles no balanceado! Número de pares a ejecutar en cada ronda, separados por comas¡La búsqueda en bajo demanda toma %s! Sólo URI «CHK» o «LOC» soportadas. La opción «%s» es obligatoria cuando se usa la opción «%s». La opción «%s» no tiene sentido con la opción «%s». La opción «%s» no tiene sentido sin la opción «%s». Las opción «%s» o «%s» es necesaria cuando se usa la opción «%s». Las opción «%s» o «%s» es necesaria. La cuota de salida configurada para la red «%s» es %llu ¡Petición «PUT» no confirmada! Petición «PUT» enviada con claveRecibido paquete de protocolo desconocido %u. Ignorado. Paquete recibido para el destino «%s» no mapeado (omitiéndolo) Par «%s» Par «%s» módulo «%s», dirección «%s», «%s» subida: %u Bytes/s, bajada %u Bytes/s, %s Par «%s»: %s %s Realizar las acciones predeterminadas para URI de GNUnet¡Por favor, pase un número de puerto válido como primer parámetro! (se obtuvo «%s») Por favor, seleccione una operación: %s o %s o %s o %s o %s El módulo «%s» no soporta URI todavía Módulo «%s» no encontrado El módulo no soporta la función «get_keys». Por favor, corríjalo. ¡El puerto es necesario! Corrija la configuración Base de datos Postgres ejecutándose Caché de datos Postgres ejecutándose Preparando para parar «%s» Preprocesado completo. Imprime información acerca del estado del ATSImprime información sobre los pares conectados.Imprimir información sobre los pares.Imprime estadísticas acerca de las operaciones de GNUnet.Imprime todos los paquetes que pasan por la DHT.El código de procesado para el mensaje del tipo %u no llamó a «GNUNET_SERVER_receive_done» después de %s Perfilador para expresiones regulares.Analizador de rendimiento para la biblioteca de expresiones regularesProtocolo %u no soportado, omitiendo Publicación de «%s» finalizada Publicar un fichero o un directorio en GNUnetPublicando «%s» Publicando «%s» en %llu/%llu (%s restantes) Publicación «%s» finalizada. Publicación fallida: %sCuota para la red «%11s» (entrada/salida): %10s / %10s Comillas no cerradas en URI KSKReconstruyendo «bloomfilter». Por favor, tenga paciencia. Recibidos %llu bytes/s (%llu bytes en %s) Recibido mensaje %s Recibidos %u bytes de %s Recibida respuesta DNS demasiado pequeña (%u bytes)Recibido paquete IPv4 con opciones (omitiéndolo) Recibido PING de «%s» para una identidad diferente: Yo soy «%s», identidad del PONG: «%s» Recibido un mensaje PING con un error de validación de «%s» Recibido mensaje no válido del servicio de información de pares (PEERINFO).Recibido último mensaje para %s Recibida petición DNS mal formada de %s Recibido paquete UDP IPv4 mal formado en interfaz TUN. Recibido paquete UDP IPv6 mal formado en interfaz TUN. Mensaje mal formado recibido vía %s. Ignorado. Recibido paquete de protocolo %d desconocido desde TUN (omitiéndolo) Peticiones recibidas de nuestra lista de máquinas Recibido mensaje inesperado del tipo %u en %s:%u Recibida petición DNS no soportada de %s Las descargas recursivas de directorios mayores de 4GB no están soportadas en sistemas de 32 bits La subida recursiva falló en «%s»: %sSubida recursiva fallida: %sRechazando petición «%s» al servidor de listas de máquinas Rechazando petición «%s» con %llu bytes de datos de subida ¡Rechazando conexión de control del par «%s», que no soy yo! Eliminando dirección de transporte «%s» ¡Se requiere un número de puerto válido para el servicio «%s» en la configuración! ¡Se necesita un puerto válido para el servicio en la configuración! Reservando espacio para %u entradas y %llu bytes para publicación Reiniciando el servicio «%s» Resultado %d, tipo %d: %.*s Ejecutando gnunet-helper-nat-client %s %s %u Servicios en ejecución: URI SKS mal formadaURI SKS mal formada (no se pudo decodificar la firma)URI SKS mal formada (no se pudo encontrar la firma)URI SKS mal formada (no se encuentra el tiempo de expiración)URI SKS mal formada (se produjo un fallo al validar la firma)La cadena de filtrado SMTP no es válida, carece de «: » La cadena de filtrado SMTP es demasiado larga, recortada a «%s» SMTP: «%s» falló: %s. Escaneando directorio «%s». Escaneando fichero «%s». Buscar en GNUnet ficheros que han sido publicados en GNUnetPetición DNS enviada a %s Los metadatos serializados «%s» son mayores de lo permitido (%u>%u)El servidor ha alcanzado el número máximo de conexiones (%u), rechazando nueva conexión ¡Servicio «%s» configurado para IPv4, pero IPv4 está deshabilitado! El servicio «%s» no está ejecutandose El servicio «%s» se ejecuta en %s El servicio «%s» tardó %s en finalizar No se pudo inicializar la función del servidor en el proceso del servicio No se pudo inicializar el proceso del servicio El proceso del servicio no devolvió un estado Configurar túneles vía VPN.¡Lectura corta leyendo del fichero «%s»!Finalización del módulo «%s» completa Apagado en proceso, abortando transmisión. Finalizando el módulo «%s» La lista de máquinas «%s» fue eliminada puesto que el aprendizaje no está habilitado en este par Discrepancias de tamaños para el bloque El tamaño del fichero en disco es incorrecto para este «Bloom filter» (esperado %llu, tiene %llu) Operaciones especiales de compartición de ficheros¡La dirección IPv4 «%s» especificada en el fichero de configuración no es válida! ¡La dirección IPv6 «%s» especificada en el fichero de configuración no es válida! Las políticas de directorio especificadas no existen. Saliendo. La topología especificada debe estar soportada por la batería de pruebasEl valor especificado «%s» para el servicio «%s» no es válido Especificar el tipo del registro a buscarBase de datos sqlite ejecutándose Caché de datos Sqlite ejecutándose Iniciando servicios predeterminados «%s» Iniciando descarga «%s». Iniciando el servicio «%s» Empezando a recibir datos de prueba Iniciando los módulos de transporte «%s» ¡Aún no se han encontrado pares en «%s»! La cadena «%s» es mayor de lo permitido (%u > %u)Conectado satisfactoriamente a «%s» Conectado satisfactoriamente a «%s», empezando a mandar datos de prueba en bloques de %u Kb Error de sintaxis en la línea %u mientras se deserializaba Paquete TCP omitido, no hay información de conexiones coincidente El transporte TCP anuncia que está en el puerto %llu Transporte TCP escuchando en el puerto %llu Transporte TCP no escuchando en ningún puerto (únicamente cliente) El nombre de fichero de destino debe ser especificado. Base de datos de plantilla ejecutándose Caché de datos de plantilla en ejecución La batería de pruebas no se puede iniciar en localhost Probando conexión inversa con el servidor ICMP. La cantidad solicitada (%llu bytes) es mayor que el tamaño de la caché (%llu bytes) Hubo un problema procesando el fichero «%s», omitiéndolo. Esto puede ser correcto si alguien está actualmente generando una clave de máquina. Esto puede estar bien si alguien está actualmente generando una clave privada. Este sistema no soporta IPv4, se deshabilitarán las funciones IPv4 aunque estén habilitadas en la configuración Este sistema no soporta IPv6, se deshabilitarán las funciones IPv6 aunque estén habilitadas en la configuración Este sistema tiene una dirección IPv6 global, fijando IPv6 a habilitado. ¡Expiró el plazo enviando una petición «PUT»! Petición de transmisión de iteración de expiración al servicio de información de pares (PEERINFO).Finalizado el plazo mientras se intentaba bajar lista de máquinas de «%s» Expiración de plazo intentando resolver la dirección IP «%s». Expiración de plazo intentando resolver el nombre de máquina «%s». Esperando al servicio «fs».El fichero de topología %s no puede ser leido El fichero de topología %s no tiene datos El fichero de topología %s no fue encontrado El fichero de topología necesita más pares que los dados ¡La transmisión con el cliente ha fallado! Transmitidos %llu bytes/s (%llu bytes en %s) Transmitiendo %u bytes a %s El servicio de transporte carece de la opción «NEIGHBOUR_LIMIT». Se intentó cerrar sqlite sin finalizar todas las sentencias preparadas. Intentando conectar a «%s» (%p) Intentando conectar con máquina remota, pero el servicio «%s» no se está ejecutando Intentando enviar con una sesión no válida %p Intentando usar el fichero «%s» para la configuración de MySQL. Paquete UDP omitido, no hay información de conexiones coincidente UDP no pudo transmitir el mensaje a «%s»: La red parece caída, por favor, compruebe su configuración de red Puerto UDP en el que escuchar para peticiones DNS entrantes; predeterminado: 53La ruta tipo UNIX «%s» es demasiado larga, la longitud máxima es %llu La URI es «%s». URI a ser publicada (puede ser usado en vez de pasar un fichero para añadir claves con el fichero con la URI respectiva)URI a importar a nuestra zonaImposible asociar el «socket» de escucha para el servicio «%s» a la dirección «%s»: %s Imposible crear un «socket» para el servicio «%s»: %s No se pudo importar el certificado %s No se pudo importar la clave privada del fichero «%s» No se pudo inicializar Postgres: %sImposible inicializar SQLite: %s. No se pudo procesar la dirección IPv4 «%s» No se pudo procesar dirección IPv4 «%s» No se pudo procesar el registro MX «%s» No se pudo procesar el registro PKEY «%s» No se pudo procesar el registro SOA «%s» No se pudo procesar la cadena de registro TLSA «%s» No se pudo procesar la cadena de registro VPN «%s» Imposible acortar la ruta unix «%s» manteniendo el nombre único Longitud de dirección inesperada: %u bytes Estado inesperado: %d Tiempo inesperado para una respuesta del servicio «fs».Desindexa un fichero previamente indexado con «gnunet-publish».Desindexado en %llu/%llu (quedan %s) Desindexado finalizado. Familia de direcciones %d desconocida Comando desconocido «%s» Comando desconocido, use «q» para salir o «r» para reiniciar el par Tipo de metadatos desconocido en la opción de metadatos «%s». Usando el tipo de metadatos desconocido (unknown) en su lugar. Tipo de URI no reconocidoTipo de bloque %u no soportado ¡Tipo de bloque no soportado (%u) en respuesta local! ¡Tipo de bloque no soportado (%u) en la petición! Forma de valor no soportada «%s» Mensaje no soportado del tipo %u (%u bytes) recibido del par «%s» Tipo no soportado «%s» Use %s para obtener una lista de opciones. Use «/help comando» para obtener ayuda sobre un comando específicoUtilizar el resolvedor interno para pruebas de GNUnetUsando «%s» en su defecto Usando nombre de máquina externo «%s» Usando puerto %u Usando la utilización de páginas de sqlite para estimar el «payload» (%llu páginas de %llu bytes de tamaño) Valor «%s» no válido para el tipo de registro «%s» Valor en el fichero de topología dato: %s está fuera de rango PELIGRODirección WLAN con tamaño no válido encontrada Cuando se intentaba leer el fichero de claves «%s» se encontraron %u bytes pero al menos %u son necesarios. Escribiendo %u URI de listas de máquinas a «%s» Servicio principal (CORE) erróneo Formato «%s» erroneo para máscara de red Formato «%s» erroneo para red Escritos %llu bytes de estadísticas a «%s» Se ha intentado crear una batería de pruebas con más de %u máquinas. Por favor, pre-compute más claves de máquinas primero. No se puede especificar una URI y un nombre de fichero. Tienes que introducir un número en la opción «%s». Debes introducir un tiempo relativo en la opción «%s». Debes especificar un fichero a inspeccionar. Debes especificar uno y solo un nombre de directorio para publicación automática. Se debe especificar uno y solo un nombre de fichero para insertar. Se debe especificar uno y solo un fichero para desindexar. Tiene que especificar una URI como parámetro. '%' debe ser seguido por un número hexadecimal«%s» falló en %s: %d con el error: %s «%s» falló en %s:%u con el error: %sFalló «%s» para la biblioteca «%s» con error: %s «%s» falló para el puerto %d (%s). «%s» falló para el puerto %d (%s): dirección en uso actualmente «%s» falló en el fichero «%s» en %s:%d con el error: %s «%s» falló al resolver el método «%s» con error: %s «%s» para «%s» falló en %s: %d con error: %s «%s» no es un directorio GNUnet ¡«%s» no es una dirección IP válida! Ignorando «BINDTOIP». «%s» no es una dirección IP válida. «%s» no es un identificador de par válido «%s» debe ser instalado con SUID, se niega a arrancar «%s:%s» falló en %s:%d con error: %s«++» no permitido en URI KSKcomando «external-ip» no encontrado comando «upnpc» no encontrado abortado debido a petición de desconexión explícitaañadirañadir una palabra clave adicional para el fichero del nivel más alto o el directorio (esta opción puede ser especificada varias veces)añade la URI de «HELLO» dada a la base de datosañadir registroanuncia nuestra lista de máquinas a otros parestambién mostrar las URI de «HELLO»termina el experimento automáticamente despues de «DELAY»terminar búsqueda automáticamente después de «DELAY»terminar búsqueda después de «VALUE» resultados encontradosbser prolijo (imprime información de progreso)realizar inicialización usando listas de máquinas (es altamente recomendable que siempre se use esta opción)bytes en la lista de máquinasbytes no incluidos en la lista de máquinas (límite de tamaño)plantilla de configuraciónconectar a un parconectar a equipo remotoplazo de consensono se pudo conectar con el servicio «fs»crea «COUNT» número de parescrea «COUNT» pares de claves pública-privada (para pruebas)crear o listar registros públicoscrear ficheros de configuración únicosdíadíasborrarretraso entre rondasborrar el directorio y el fichero de configuración al salirborra descargas incompletas (cuando fueron abortadas con CTRL-C=borrar registroIP de destino para el túneldeshabilitar añadir tiempo de creación a los metadatos del fichero subidomostrar registrosdemonizar (desasociar del terminal)no indexar, hacer inserciones totales (almacena el fichero entero de forma cifrada en la base de datos de GNUnet)no resuelve direcciones IP a nombres de máquinano resolver nombres de máquinasno usar libextractor para añadir palabras clave o metadatosno permite heredar la salida de error estándar a «gnunet-service-arm»no permite heredar la salida estándar a «gnunet-service-arm»no imprime mensajes de estadono resolver nombres de máquinadescarga un directorio de GNUnet recursivamentehabilitar aprendizaje de servidores de listas de máquinas de otros paresfin del plazosalidatiempo de expiración del registro a usar (únicamente para añadir), nunca ("never") es posibledirecciones expiradas encontradasextraer los ficheros de claves de máquinas de una lista pre-computada de claves de máquinasse produjo un fallo al calcular el hashse produjo un fallo al transmitir la petición (¿está caido el servicio?)nombre de fichero demasiado largopara siempreobtiene una lista de direcciones activas usadas actualmenteobtiene una lista de todas las direcciones activas«gnunet-helper-nat-client» encontrado, habilitando su uso «gnunet-helper-nat-client» no encontrado o detrás de NAT, deshabilitando su uso «gnunet-helper-nat-server» encontrado, probándolo «gnunet-helper-nat-server» generó la dirección mal formada «%s» hnúmero de hashtexto de ayudaPeticiones de lista de máquinas procesadasPeticiones de listas de máquinas rechazadas (no HTTP GET)Peticiones de listas de máquinas rechazadas (no preparados)Peticiones de listas de máquinas rechazadas (datos de subida)¿cuánto tiempo debe ser válido el mapeado para túneles nuevos?cuanto tiempo debe ejecutarse el comando de monitorización¿cuánto tiempo se debe ejecutar esta consulta antes de abandonar?cuanto tiempo almacenar esta entrada en la DHT (en segundos)cuantas peticiones paralelas (réplicas) crear¿cuántos pares reciben un valor?cuantas réplicas creartamaño ibferror interno decodificando árbolerror interno descifrando el contenidodirección no válidaimprime el valor de las estadísticaslibgcrypt no tiene la versión esperada (se necesita la versión %s). limita la salida de estadísticas para el nombre (NAME) dadolímite de salida para el subsistema (SUBSYSTEM) dadolímite al número de conexiones a servicios NSE, 0 para ilimitadasmostrar todos los pares conocidoslista de servicios actualmente en ejecuciónescuchar en el puerto especificado (predeterminado: 7777)mhacer el valor persistentemal formadolongitud de la máxima compresión de rutasmedir cómo de rápido recibimos datos de todos los pares (hasta CTRL-C)modo de monitorizaciónmsnombre del fichero para escribir información y estadísticas de la conexiónnombre del fichero para escribir las estadísticasnombre del fichero en el que escribir los resultados principalesnombre del fichero con la información de acceso usada para la batería de pruebasnombre de la opción a la que accedernombre del registro a añadir/borrar/mostrarnombre de la sección a la que accedernombre del servicio al que nos gustaría accedernombre de la tabla para escribir los DFAse necesita una dirección IPv4 o IPv6 válida tiene que ser un fichero de verdadno indexadonúmero de elementos comunes en A y Bnúmero de elementos en el conjunto A-Bnúmero de elementos en el conjunto B-Anúmero de pares en consensonúmero de ficheros de configuración únicos o claves de máquina a crear, o el número de claves de máquina a extraernúmero de valoresobtener la opción del valor como un nombre de fichero (con expansión del $)sólo monitorizar consultas DNSsólo monitorizar respuestas DNSúnicamente buscar en el par local (no buscar en la red P2P)únicamente simular el proceso pero no publicar nada realmente (útil para calcular URI)mostrar únicamente las cadenas de identidadmuestra únicamente nuestra propia identidadidentificación del paridentidad del parpar que ofrece el servicio al que nos gustaría accederfichero pem para usar como autoridad de certificación (CA)realizar una búsqueda inversapuerto del equipo remototipo de preferencia a modificar: latency (latencia) | bandwidth (ancho de banda)valor de preferenciaimprimir una lista de todos los ficheros indexadosimprime todas las cuotas configuradasimprimir una lista de las palabras clave extraídas que podrían ser usadas, pero sin realizar la subidaimprime el hash de la clave pública en formato ASCIIimprime la clave pública en formato ASCIIproveer un servidor de listas de máquinasproveer información acerca de un túnel en particularprovee información sobre todas los eventos de conexión y desconexión (continuamente)provee información sobre todas las conexiones actuales (de forma continua)provee información sobre todas las conexiones actuales (una vez)publicar los ficheros bajo el seudónimo NAME (coloca el fichero en el espacio)petición cuyo resultado debe ser una dirección IPv4petición cuyo resultado debe ser una dirección IPv6ejecuta una batería de pruebas para medir el rendimiento de la compartición de ficherosejecuta el experimento con «COUNT» paressenviar data para prueba a otro par (hasta CTRL-C)el servicio es ofrecido vía TCPel servicio es ofrecido vía UDPestablece registros de clase Aestablece registros de clase AAAAestablece las preferencias para el par dadoestablece la ID de esta versión de la publicación (para inserciones en el espacio únicamente)establece el nivel LEVEL deseado de anonimato del receptorestablece el nivel LEVEL deseado de anonimato del emisorestablece el nivel LEVEL deseado de replicaciónestablece el número máximo de descargas paralelas permitidoestablece el número máximo de peticiones de bloque paralelas permitidoestablece los metadatos para el tipo TYPE dado al valor VALUE dadoseñalseñal (%d, %p) devolvió %d. especifica el nombre de un fichero con las máquinas (HOSTS) que la batería de pruebas debería usarespecificar la ID de una versión actualizada para ser publicada en el futuro (para inserciones en el espacio de nombres únicamente)especificar la prioridad del contenidola versión de sqlite es muy antigua para determinar el tamaño, se asume cero inicia un servicio particularinicia todos los servicios predeterminados de GNUnetdetiene un servicio particulardetiene todos los servicios de GNUnetdetiene e inicia todos los servicios predeterminados de GNUnetprobar configuración de transporte (requiere un servidor externo)los datos a insertar bajo la clavela clave de búsquedael tipo de datos a buscarel tipo de datos a insertarse requiere tiempo, publicación de contenido deshabilitadaplazo en milisegundos (MSECS) para completar la operación actualexpiración del plazo en la petición de inicio de indexado (index-start) al servicio «fs»tolerar un número «COUNT» de continuas expiraciones de plazotipo del registro a añadir/borrar/mostrardesconocidodirección desconocidaerror desconocido«upnpc» encontrado, habilitando su uso «upnpc» no encontrado opción para usar el demultiplexado de la DHT siemprevalor del registro a añadir/borrarvalor a establecersalida prolija (incluye las propiedades de direcciones del ATS)visualiza el valor continuamenteescribir resultados de búsqueda al fichero que empiecen por «PREFIX»escribe los datos al nombre del fichero proporcionado (FILENAME)gnunet-0.10.1/po/es.po0000644000175000017500000153500412320736475011420 00000000000000# Spanish translations for GNUnet package. # Copyright (C) 2012 Christian Grothoff # This file is distributed under the same license as the GNUnet package. # Miguel Ãngel Arruga Vivas , 2006, 2013. # msgid "" msgstr "" "Project-Id-Version: gnunet 0.9.5a\n" "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n" "POT-Creation-Date: 2014-04-08 11:11+0200\n" "PO-Revision-Date: 2013-02-23 17:50+0100\n" "Last-Translator: Miguel Ãngel Arruga Vivas \n" "Language-Team: Spanish \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/arm/arm_api.c:337 #, fuzzy msgid "Client was disconnected from arm service, trying to reconnect.\n" msgstr "" "El cliente se desconectó del servicio principal, tratando de reconectar.\n" #: src/arm/arm_monitor_api.c:321 #, fuzzy msgid "" "Monitoring client was disconnected from arm service, trying to reconnect.\n" msgstr "" "El cliente se desconectó del servicio principal, tratando de reconectar.\n" #: src/arm/gnunet-arm.c:164 #, c-format msgid "Failed to remove configuration file %s\n" msgstr "Se produjo un fallo al borrar el fichero de configuración %s\n" #: src/arm/gnunet-arm.c:170 #, c-format msgid "Failed to remove servicehome directory %s\n" msgstr "Se produjo un fallo al eliminar el directorio «servicehome» %s.\n" #: src/arm/gnunet-arm.c:216 src/testbed/gnunet-service-testbed_peers.c:1013 #, fuzzy msgid "Message was sent successfully" msgstr "El almacén de nombres añadió el registro satisfactoriamente" #: src/arm/gnunet-arm.c:218 #, fuzzy msgid "Misconfiguration (can not connect to the ARM service)" msgstr "¡Se produjo un fallo al conectar con el servicio dv!\n" #: src/arm/gnunet-arm.c:220 src/testbed/gnunet-service-testbed_peers.c:1017 #, fuzzy msgid "We disconnected from ARM before we could send a request" msgstr "# desconexiones del par debido a una petición explícita" #: src/arm/gnunet-arm.c:222 src/testbed/gnunet-service-testbed_peers.c:1019 msgid "ARM API is busy" msgstr "" #: src/arm/gnunet-arm.c:224 #, fuzzy msgid "Request does not fit into a message" msgstr "no imprime mensajes de estado" # Miguel: "timeout" lo he traducido como plazo, pero no se # si hay alguna palabra que lo describa mejor. #: src/arm/gnunet-arm.c:226 src/testbed/gnunet-service-testbed_peers.c:1023 #, fuzzy msgid "Request timed out" msgstr "plazo de consenso" #: src/arm/gnunet-arm.c:228 src/testbed/gnunet-service-testbed_peers.c:1025 #, fuzzy msgid "Unknown request status" msgstr "Usuario desconocido «%s»\n" #: src/arm/gnunet-arm.c:244 src/testbed/gnunet-service-testbed_peers.c:1041 #, fuzzy, c-format msgid "%s is stopped" msgstr "# elementos almacenados" #: src/arm/gnunet-arm.c:246 src/testbed/gnunet-service-testbed_peers.c:1043 #, fuzzy, c-format msgid "%s is starting" msgstr "'%s' comenzando\n" #: src/arm/gnunet-arm.c:248 src/testbed/gnunet-service-testbed_peers.c:1045 #, c-format msgid "%s is stopping" msgstr "" #: src/arm/gnunet-arm.c:250 src/testbed/gnunet-service-testbed_peers.c:1047 #, fuzzy, c-format msgid "%s is starting already" msgstr "'%s' comenzando\n" #: src/arm/gnunet-arm.c:252 src/testbed/gnunet-service-testbed_peers.c:1049 #, c-format msgid "%s is stopping already" msgstr "" #: src/arm/gnunet-arm.c:254 src/testbed/gnunet-service-testbed_peers.c:1051 #, c-format msgid "%s is started already" msgstr "" #: src/arm/gnunet-arm.c:256 src/testbed/gnunet-service-testbed_peers.c:1053 #, c-format msgid "%s is stopped already" msgstr "" # Miguel: ¿Debería cambiar las siglas de ARM? # De momento las he mantenido con una traducción en # otro mensaje. #: src/arm/gnunet-arm.c:258 src/testbed/gnunet-service-testbed_peers.c:1055 #, fuzzy, c-format msgid "%s service is not known to ARM" msgstr "El servicio «%s» es desconocido para el ARM.\n" #: src/arm/gnunet-arm.c:260 src/testbed/gnunet-service-testbed_peers.c:1057 #, fuzzy, c-format msgid "%s service failed to start" msgstr "El proceso del servicio no devolvió un estado\n" # Miguel: ¿Es mejor «ya que» que «porque» o «debido al apagado»? #: src/arm/gnunet-arm.c:262 #, fuzzy, c-format msgid "%s service cannot be started because ARM is shutting down" msgstr "Petición ignorada porque el ARM se está apagando.\n" #: src/arm/gnunet-arm.c:264 src/testbed/gnunet-service-testbed_peers.c:1061 #, fuzzy, c-format msgid "%.s Unknown result code." msgstr "Código de respuesta del ARM desconocido.\n" #: src/arm/gnunet-arm.c:297 msgid "Fatal error initializing ARM API.\n" msgstr "Error fatal al inicializar la API del ARM.\n" #: src/arm/gnunet-arm.c:326 src/arm/gnunet-arm.c:335 #, fuzzy, c-format msgid "Failed to start the ARM service: %s\n" msgstr "Se produjo un fallo al iniciar el servicio «%s»\n" #: src/arm/gnunet-arm.c:369 #, fuzzy, c-format msgid "Failed to send a stop request to the ARM service: %s\n" msgstr "Se produjo un fallo al enviar una petición al servicio de transporte\n" #: src/arm/gnunet-arm.c:379 #, fuzzy, c-format msgid "Failed to stop the ARM service: %s\n" msgstr "Fichero almacenado en '%s'.\n" #: src/arm/gnunet-arm.c:421 #, fuzzy, c-format msgid "Failed to send a request to start the `%s' service: %%s\n" msgstr "Se produjo un fallo al enviar una petición al servicio de transporte\n" #: src/arm/gnunet-arm.c:431 #, fuzzy, c-format msgid "Failed to start the `%s' service: %s\n" msgstr "Se produjo un fallo al iniciar el servicio «%s»\n" #: src/arm/gnunet-arm.c:468 #, fuzzy, c-format msgid "Failed to send a request to kill the `%s' service: %%s\n" msgstr "Se produjo un fallo al enviar una petición al servicio de transporte\n" #: src/arm/gnunet-arm.c:479 #, fuzzy, c-format msgid "Failed to kill the `%s' service: %s\n" msgstr "Se produjo un fallo al escribir «%s»: %s\n" #: src/arm/gnunet-arm.c:517 #, fuzzy, c-format msgid "Failed to request a list of services: %s\n" msgstr "Se produjo un fallo al iniciar el servicio «%s»\n" #: src/arm/gnunet-arm.c:525 msgid "Error communicating with ARM. ARM not running?\n" msgstr "Error al comunicar con el ARM. ¿Está el ARM ejecutándose?\n" #: src/arm/gnunet-arm.c:530 msgid "Running services:\n" msgstr "Servicios en ejecución:\n" #: src/arm/gnunet-arm.c:612 #, c-format msgid "Now only monitoring, press CTRL-C to stop.\n" msgstr "" #: src/arm/gnunet-arm.c:643 #, c-format msgid "Stopped %s.\n" msgstr "" #: src/arm/gnunet-arm.c:646 #, fuzzy, c-format msgid "Starting %s...\n" msgstr "Iniciando descarga «%s».\n" #: src/arm/gnunet-arm.c:649 #, c-format msgid "Stopping %s...\n" msgstr "" #: src/arm/gnunet-arm.c:660 #, fuzzy, c-format msgid "Unknown status %u for service %s.\n" msgstr "Solicitando incio del servicio «%s».\n" #: src/arm/gnunet-arm.c:724 msgid "stop all GNUnet services" msgstr "detiene todos los servicios de GNUnet" #: src/arm/gnunet-arm.c:726 msgid "start a particular service" msgstr "inicia un servicio particular" #: src/arm/gnunet-arm.c:728 msgid "stop a particular service" msgstr "detiene un servicio particular" #: src/arm/gnunet-arm.c:730 msgid "start all GNUnet default services" msgstr "inicia todos los servicios predeterminados de GNUnet" #: src/arm/gnunet-arm.c:733 msgid "stop and start all GNUnet default services" msgstr "detiene e inicia todos los servicios predeterminados de GNUnet" #: src/arm/gnunet-arm.c:736 msgid "delete config file and directory on exit" msgstr "borrar el directorio y el fichero de configuración al salir" #: src/arm/gnunet-arm.c:739 msgid "monitor ARM activities" msgstr "" #: src/arm/gnunet-arm.c:741 msgid "don't print status messages" msgstr "no imprime mensajes de estado" #: src/arm/gnunet-arm.c:744 msgid "timeout in MSECS milliseconds for completing current operation" msgstr "plazo en milisegundos (MSECS) para completar la operación actual" #: src/arm/gnunet-arm.c:746 msgid "list currently running services" msgstr "lista de servicios actualmente en ejecución" #: src/arm/gnunet-arm.c:748 msgid "don't let gnunet-service-arm inherit standard output" msgstr "no permite heredar la salida estándar a «gnunet-service-arm»" #: src/arm/gnunet-arm.c:750 msgid "don't let gnunet-service-arm inherit standard error" msgstr "no permite heredar la salida de error estándar a «gnunet-service-arm»" # Miguel: ARM se mantiene en todo el texto, aquí está la traducción. #: src/arm/gnunet-arm.c:761 msgid "Control services and the Automated Restart Manager (ARM)" msgstr "" "Servicios de control y el Gestor de Reinicio Automático (ARM en inglés)" # Miguel: Si no me equivoco, "status result" es un # resultado de tipo estado. #: src/arm/gnunet-service-arm.c:266 msgid "Could not send status result to client\n" msgstr "No se pudo mandar el resultado (estado) al cliente\n" # Miguel: Si no me equivoco, "list result" es un resultado # de tipo lista. #: src/arm/gnunet-service-arm.c:302 msgid "Could not send list result to client\n" msgstr "No se pudo mandar el resultado (lista) al cliente\n" #: src/arm/gnunet-service-arm.c:529 #, c-format msgid "Failed to start service `%s'\n" msgstr "Se produjo un fallo al iniciar el servicio «%s»\n" #: src/arm/gnunet-service-arm.c:540 #, c-format msgid "Starting service `%s'\n" msgstr "Iniciando el servicio «%s»\n" # Miguel: ¿Alguna idea para "socket"? #: src/arm/gnunet-service-arm.c:639 #, c-format msgid "Unable to create socket for service `%s': %s\n" msgstr "Imposible crear un «socket» para el servicio «%s»: %s\n" #: src/arm/gnunet-service-arm.c:661 #, c-format msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n" msgstr "" "Imposible asociar el «socket» de escucha para el servicio «%s» a la " "dirección «%s»: %s\n" # Miguel: He traducido "monitor" por gestionar, # no es exactamente lo mismo que el texto en inglés, pero # es fiel a la realidad puesto que el ARM reinicia # las conexiones cuando se caen. #: src/arm/gnunet-service-arm.c:695 #, c-format msgid "ARM now monitors connections to service `%s' at `%s'\n" msgstr "El ARM ahora gestiona las conexiones del servicio «%s» en «%s»\n" #: src/arm/gnunet-service-arm.c:831 #, c-format msgid "Preparing to stop `%s'\n" msgstr "Preparando para parar «%s»\n" #: src/arm/gnunet-service-arm.c:1100 #, c-format msgid "Restarting service `%s'.\n" msgstr "Reiniciando el servicio «%s»\n" #: src/arm/gnunet-service-arm.c:1193 msgid "exit" msgstr "salida" #: src/arm/gnunet-service-arm.c:1198 msgid "signal" msgstr "señal" #: src/arm/gnunet-service-arm.c:1203 msgid "unknown" msgstr "desconocido" #: src/arm/gnunet-service-arm.c:1209 #, c-format msgid "Service `%s' took %s to terminate\n" msgstr "El servicio «%s» tardó %s en finalizar\n" #: src/arm/gnunet-service-arm.c:1231 #, fuzzy, c-format msgid "Service `%s' terminated normally, will restart at any time\n" msgstr "El servicio «%s» finalizó con estado %s/%d, se reiniciará en %llu ms\n" #: src/arm/gnunet-service-arm.c:1246 #, fuzzy, c-format msgid "Service `%s' terminated with status %s/%d, will restart in %s\n" msgstr "El servicio «%s» finalizó con estado %s/%d, se reiniciará en %llu ms\n" #: src/arm/gnunet-service-arm.c:1500 #, c-format msgid "Starting default services `%s'\n" msgstr "Iniciando servicios predeterminados «%s»\n" # Miguel: He traducido "default" por "predeterminado", la locución # "por defecto" no tiene sentido en sitios como este y he tratado # de ser consistente. #: src/arm/gnunet-service-arm.c:1511 #, c-format msgid "Default service `%s' not configured correctly!\n" msgstr "¡El servicio predeterminado «%s» no está configurado correctamente!\n" # Miguel: ¿No hay servicios -> no hay ningún servicio? #: src/arm/gnunet-service-arm.c:1524 msgid "" "No default services configured, GNUnet will not really start right now.\n" msgstr "" "No hay servicios predeterminados configurados, GNUnet no va a iniciarse " "realmente ahora.\n" #: src/arm/mockup-service.c:41 msgid "Initiating shutdown as requested by client.\n" msgstr "Iniciando apagado bajo petición del cliente.\n" #: src/ats/ats_api_performance.c:468 #, c-format msgid "Received %s message\n" msgstr "Recibido mensaje %s\n" #: src/ats/ats_api_performance.c:511 #, c-format msgid "Received last message for %s \n" msgstr "Recibido último mensaje para %s\n" #: src/ats/gnunet-ats-solver-eval.c:2199 src/ats/gnunet-ats-solver-eval.c:2233 #: src/ats/gnunet-service-ats_addresses.c:1980 #: src/ats/gnunet-service-ats_addresses.c:2024 #, c-format msgid "" "Could not load quota for network `%s': `%s', assigning default bandwidth " "%llu\n" msgstr "" "No se pudieron cargar las cuotas para la red «%s»: «%s», asignando el ancho " "de banda predeterminado %llu\n" # Miguel: "Outbound" lo he traducido como salida en todo el texto. #: src/ats/gnunet-ats-solver-eval.c:2205 #: src/ats/gnunet-service-ats_addresses.c:1987 #, c-format msgid "Outbound quota configure for network `%s' is %llu\n" msgstr "La cuota de salida configurada para la red «%s» es %llu\n" #: src/ats/gnunet-ats-solver-eval.c:2212 #: src/ats/gnunet-service-ats_addresses.c:1995 #, c-format msgid "" "No outbound quota configured for network `%s', assigning default bandwidth " "%llu\n" msgstr "" "No hay configurada una cuota de salida para la red «%s», asignando el ancho " "de banda predeterminado %llu\n" # Miguel: "Inbound" lo he traducido como entrada en todo el texto. #: src/ats/gnunet-ats-solver-eval.c:2239 #: src/ats/gnunet-service-ats_addresses.c:2031 #, c-format msgid "Inbound quota configured for network `%s' is %llu\n" msgstr "La cuota de entrada configurada para la red «%s» es %llu\n" #: src/ats/gnunet-ats-solver-eval.c:2246 #: src/ats/gnunet-service-ats_addresses.c:2039 #, c-format msgid "" "No outbound quota configure for network `%s', assigning default bandwidth " "%llu\n" msgstr "" "No hay configurada una cuota de salida para la red «%s», asignando el ancho " "de banda predeterminado %llu\n" #: src/ats/gnunet-ats-solver-eval.c:2671 #: src/ats-tests/gnunet-solver-eval.c:919 #, fuzzy msgid "solver to use" msgstr "valor a establecer" #: src/ats/gnunet-ats-solver-eval.c:2674 src/ats/gnunet-ats-solver-eval.c:2677 #: src/ats-tests/gnunet-solver-eval.c:922 #: src/ats-tests/gnunet-solver-eval.c:925 msgid "experiment to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2680 #, fuzzy msgid "print logging" msgstr "Iniciando descarga «%s».\n" #: src/ats/gnunet-service-ats_addresses.c:2217 #, c-format msgid "Initializing solver `%s '`%s'\n" msgstr "" #: src/ats/gnunet-service-ats_addresses.c:2220 #, fuzzy, c-format msgid "Failed to initialize solver `%s'!\n" msgstr "¡No se puede inicializar el resolvedor!\n" #: src/ats/gnunet-service-ats_addresses.c:2243 #, fuzzy msgid "Failed to initialize solver!\n" msgstr "¡No se puede inicializar el resolvedor!\n" #: src/ats/plugin_ats_mlp.c:892 msgid "Problem size too large, cannot allocate memory!\n" msgstr "" #: src/ats/plugin_ats_mlp.c:1329 #, fuzzy, c-format msgid "Adding address for peer `%s' multiple times\n" msgstr "Añadiendo «%s» sin direcciones para el par «%s»\n" #: src/ats/plugin_ats_mlp.c:1376 #, c-format msgid "Updating address property `%s' for peer `%s' %p not added before\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2122 #, fuzzy, c-format msgid "" "Adjusting inconsistent outbound quota configuration for network `%s', is " "%llu must be at least %llu\n" msgstr "" "No hay configurada una cuota de salida para la red «%s», asignando el ancho " "de banda predeterminado %llu\n" #: src/ats/plugin_ats_mlp.c:2131 #, fuzzy, c-format msgid "" "Adjusting inconsistent inbound quota configuration for network `%s', is %llu " "must be at least %llu\n" msgstr "" "No hay configuración de cuota de entrada para la red '%s', asignando el " "ancho de banda predeterminado (%llu)\n" # Miguel: "Outbound" lo he traducido como salida en todo el texto. #: src/ats/plugin_ats_mlp.c:2142 #, fuzzy, c-format msgid "" "Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n" msgstr "La cuota de salida configurada para la red «%s» es %llu\n" # Miguel: "Outbound" lo he traducido como salida en todo el texto. #: src/ats/plugin_ats_mlp.c:2150 #, fuzzy, c-format msgid "" "Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n" msgstr "La cuota de salida configurada para la red «%s» es %llu\n" # Miguel: "Outbound" lo he traducido como salida en todo el texto. #: src/ats/plugin_ats_mlp.c:2161 #, fuzzy, c-format msgid "Using default quota configuration for network `%s' (in/out) %llu/%llu\n" msgstr "La cuota de salida configurada para la red «%s» es %llu\n" #: src/ats/plugin_ats_proportional.c:1511 #, fuzzy, c-format msgid "Invalid network type `%u' `%s': Disconnect!\n" msgstr "No se encontró la IP del host «%s»: %s\n" #: src/ats-tests/ats-testing.c:72 msgid "Benchmarking done\n" msgstr "" #: src/ats-tests/ats-testing.c:105 #, fuzzy, c-format msgid "Failed to connect peer 0 and %u\n" msgstr "Se produjo un fallo al conectar con «%s»\n" #: src/ats-tests/ats-testing.c:413 #, c-format msgid "Connected master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:419 #, fuzzy, c-format msgid "Failed to connect master peer [%u] with slave [%u]\n" msgstr "Fallo al conectar a gnunetd.\n" #: src/ats-tests/ats-testing.c:450 msgid "Connecting peers on CORE level\n" msgstr "" #: src/ats-tests/ats-testing.c:461 #, c-format msgid "Connecting master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:470 #, fuzzy, c-format msgid "Could not connect master [%u] and slave [%u]\n" msgstr "¡No se pudo conectar al servicio %s!\n" #: src/ats-tests/ats-testing.c:490 src/ats-tests/ats-testing.c:671 #, fuzzy msgid "Initialization failed, shutdown\n" msgstr "¡La inicialización del mecanismo de módulos falló: %s!\n" #: src/ats-tests/ats-testing-log.c:842 msgid "Stop logging\n" msgstr "" #: src/ats-tests/ats-testing-log.c:893 #, fuzzy, c-format msgid "Start logging `%s'\n" msgstr "Iniciando descarga «%s».\n" #: src/ats-tests/gnunet-ats-sim.c:86 #, c-format msgid "" "Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. " "= %u KiB/s\n" msgstr "" # Miguel: ¿Como podría traducir "resolutions" y "resolve"? # Son difíciles de no calcar, puesto que no conozco como expresar # el concepto de obtener una dirección a partir de un nombre # en castellano sin la palabra resolver. :-) #: src/ats-tool/gnunet-ats.c:169 #, c-format msgid "%u address resolutions had a timeout\n" msgstr "%u resoluciones de dirección pasaron de plazo\n" #: src/ats-tool/gnunet-ats.c:171 #, c-format msgid "ATS returned results for %u addresses\n" msgstr "El ATS devolvió resultados para %u direcciones\n" # Miguel: "Plugin" está traducido como módulo en todo el texto # puesto que no hay módulos fijos en contraposición a cargables. #: src/ats-tool/gnunet-ats.c:232 #, c-format msgid "" "Peer `%s' plugin `%s', address `%s', `%s' bw out: %u Bytes/s, bw in %u Bytes/" "s, %s\n" msgstr "" "Par «%s» módulo «%s», dirección «%s», «%s» subida: %u Bytes/s, bajada %u " "Bytes/s, %s\n" #: src/ats-tool/gnunet-ats.c:413 #, c-format msgid "Quota for network `%11s' (in/out): %10s / %10s\n" msgstr "Cuota para la red «%11s» (entrada/salida): %10s / %10s\n" #: src/ats-tool/gnunet-ats.c:433 src/core/gnunet-core.c:163 #: src/namestore/gnunet-namestore.c:550 src/transport/gnunet-transport.c:1246 #, c-format msgid "Service `%s' is not running\n" msgstr "El servicio «%s» no está ejecutandose\n" #: src/ats-tool/gnunet-ats.c:445 src/transport/gnunet-transport.c:1255 #, c-format msgid "Failed to parse peer identity `%s'\n" msgstr "Se produjo un fallo al procesar la identidad del par «%s»\n" #: src/ats-tool/gnunet-ats.c:454 #, c-format msgid "Please select one operation : %s or %s or %s or %s or %s\n" msgstr "Por favor, seleccione una operación: %s o %s o %s o %s o %s\n" #: src/ats-tool/gnunet-ats.c:470 src/ats-tool/gnunet-ats.c:489 #: src/ats-tool/gnunet-ats.c:506 src/ats-tool/gnunet-ats.c:543 #, c-format msgid "Cannot connect to ATS service, exiting...\n" msgstr "No se puede conectar al servicio ATS, saliendo...\n" #: src/ats-tool/gnunet-ats.c:478 src/ats-tool/gnunet-ats.c:495 #, c-format msgid "Cannot issue request to ATS service, exiting...\n" msgstr "No se puede iniciar una petición al servicio ATS, saliendo...\n" #: src/ats-tool/gnunet-ats.c:515 #, fuzzy, c-format msgid "No preference type given!\n" msgstr "establece las preferencias para el par dado" #: src/ats-tool/gnunet-ats.c:520 #, fuzzy, c-format msgid "No peer given!\n" msgstr "No se han proporcionado opciones\n" #: src/ats-tool/gnunet-ats.c:536 #, fuzzy msgid "Valid type required\n" msgstr "Tipo requerido\n" #: src/ats-tool/gnunet-ats.c:594 msgid "get list of active addresses currently used" msgstr "obtiene una lista de direcciones activas usadas actualmente" #: src/ats-tool/gnunet-ats.c:596 msgid "get list of all active addresses" msgstr "obtiene una lista de todas las direcciones activas" #: src/ats-tool/gnunet-ats.c:599 msgid "do not resolve IP addresses to hostnames" msgstr "no resuelve direcciones IP a nombres de máquina" # Miguel: Aquí he dejado monitorización porque esto es # del servicio de traducción de direcciones. #: src/ats-tool/gnunet-ats.c:601 msgid "monitor mode" msgstr "modo de monitorización" #: src/ats-tool/gnunet-ats.c:603 msgid "set preference for the given peer" msgstr "establece las preferencias para el par dado" #: src/ats-tool/gnunet-ats.c:605 msgid "print all configured quotas" msgstr "imprime todas las cuotas configuradas" # Miguel: He preferido extender id a identificación por claridad. #: src/ats-tool/gnunet-ats.c:607 msgid "peer id" msgstr "identificación del par" # Miguel: No me he encontrado esta opción todavía, # pero creo que son palabras clave. #: src/ats-tool/gnunet-ats.c:610 msgid "preference type to set: latency | bandwidth" msgstr "" "tipo de preferencia a modificar: latency (latencia) | bandwidth (ancho de " "banda)" #: src/ats-tool/gnunet-ats.c:612 msgid "preference value" msgstr "valor de preferencia" # Miguel: ¿Algo menos forzado que "salida prolija"? #: src/ats-tool/gnunet-ats.c:615 msgid "verbose output (include ATS address properties)" msgstr "salida prolija (incluye las propiedades de direcciones del ATS)" #: src/ats-tool/gnunet-ats.c:622 msgid "Print information about ATS state" msgstr "Imprime información acerca del estado del ATS" #: src/consensus/gnunet-consensus-profiler.c:437 #: src/secretsharing/gnunet-secretsharing-profiler.c:535 msgid "number of peers in consensus" msgstr "número de pares en consenso" #: src/consensus/gnunet-consensus-profiler.c:440 msgid "how many peers receive one value?" msgstr "¿cuántos pares reciben un valor?" #: src/consensus/gnunet-consensus-profiler.c:443 #: src/set/gnunet-set-profiler.c:286 src/set/gnunet-set-profiler.c:289 #: src/set/gnunet-set-profiler.c:292 msgid "number of values" msgstr "número de valores" # Miguel: "timeout" lo he traducido como plazo, pero no se # si hay alguna palabra que lo describa mejor. #: src/consensus/gnunet-consensus-profiler.c:446 msgid "consensus timeout" msgstr "plazo de consenso" #: src/consensus/gnunet-consensus-profiler.c:449 msgid "delay until consensus starts" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:452 #: src/secretsharing/gnunet-secretsharing-profiler.c:550 msgid "be more verbose (print received values)" msgstr "" #: src/conversation/conversation_api.c:557 #: src/conversation/conversation_api_call.c:470 #, fuzzy msgid "Connection to conversation service lost, trying to reconnect\n" msgstr "" "El cliente se desconectó del servicio principal, tratando de reconectar.\n" #: src/conversation/gnunet-conversation.c:264 #, c-format msgid "Incoming call from `%s'. Please /accept #%u or /cancel %u the call.\n" msgstr "" #: src/conversation/gnunet-conversation.c:286 #, c-format msgid "Call from `%s' terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:319 #, c-format msgid "Call from `%s' suspended by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:324 #, c-format msgid "Call from `%s' resumed by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:342 #, c-format msgid "Ego `%s' no longer available, phone is now down.\n" msgstr "" #: src/conversation/gnunet-conversation.c:356 #, fuzzy msgid "Failed to setup phone (internal error)\n" msgstr "¡Se produjo un fallo al configurar el túnel mesh!\n" #: src/conversation/gnunet-conversation.c:368 #, c-format msgid "" "Phone active on line %u. Type `/help' for a list of available commands\n" msgstr "" #: src/conversation/gnunet-conversation.c:390 #, c-format msgid "Resolved address of `%s'. Now ringing other party.\n" msgstr "" #: src/conversation/gnunet-conversation.c:397 #, fuzzy, c-format msgid "Connection established to `%s'\n" msgstr "'%s' falló en %s: %d con error: '%s'.\n" #: src/conversation/gnunet-conversation.c:404 #, fuzzy, c-format msgid "Failed to resolve `%s'\n" msgstr "Se produjo un fallo al resolver «%s»: %s\n" #: src/conversation/gnunet-conversation.c:411 msgid "Call terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:417 #, c-format msgid "Connection to `%s' suspended (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:423 #, c-format msgid "Connection to `%s' resumed (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:428 msgid "Error with the call, restarting it\n" msgstr "" #: src/conversation/gnunet-conversation.c:495 #, c-format msgid "Unknown command `%s'\n" msgstr "Comando desconocido «%s»\n" #: src/conversation/gnunet-conversation.c:511 #: src/conversation/gnunet-conversation.c:525 #, c-format msgid "Ego `%s' not available\n" msgstr "" #: src/conversation/gnunet-conversation.c:518 #: src/conversation/gnunet-conversation.c:575 msgid "You are calling someone else already, hang up first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:533 #: src/conversation/gnunet-conversation.c:588 #, c-format msgid "You are answering call from `%s', hang up or suspend that call first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:544 msgid "Call recipient missing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:599 msgid "There is no incoming call to accept here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:616 #, c-format msgid "There is no incoming call `%s' to accept right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:647 msgid "We currently do not have an address.\n" msgstr "" #: src/conversation/gnunet-conversation.c:670 #, c-format msgid "We are currently trying to locate the private key for the ego `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:675 #, c-format msgid "We are listening for incoming calls for ego `%s' on line %u.\n" msgstr "" #: src/conversation/gnunet-conversation.c:681 #: src/conversation/gnunet-conversation.c:705 #, c-format msgid "You are having a conversation with `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:686 msgid "" "We had an internal error setting up our phone line. You can still make " "calls.\n" msgstr "" #: src/conversation/gnunet-conversation.c:695 #, fuzzy, c-format msgid "We are trying to find the network address to call `%s'.\n" msgstr "Detectada dirección de la red interna «%s».\n" #: src/conversation/gnunet-conversation.c:700 #, c-format msgid "We are calling `%s', his phone should be ringing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:719 msgid "Calls waiting:\n" msgstr "" #: src/conversation/gnunet-conversation.c:725 #, fuzzy, c-format msgid "#%u: `%s'\n" msgstr "Par «%s»\n" #: src/conversation/gnunet-conversation.c:753 #: src/conversation/gnunet-conversation.c:768 msgid "There is no call that could be suspended right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:801 #: src/conversation/gnunet-conversation.c:817 msgid "There is no call that could be resumed right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:824 #, c-format msgid "Already talking with `%s', cannot resume a call right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:833 msgid "There is no incoming call to resume here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:850 #, c-format msgid "There is no incoming call `%s' to resume right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:885 msgid "There is no call that could be cancelled right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:893 msgid "There is no incoming call to refuse here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:910 #, c-format msgid "There is no incoming call `%s' to refuse right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:937 msgid "Use `/address' to find out which address this phone should have in GNS" msgstr "" #: src/conversation/gnunet-conversation.c:939 msgid "Use `/call USER.gnu' to call USER" msgstr "" #: src/conversation/gnunet-conversation.c:941 msgid "Use `/accept #NUM' to accept incoming call #NUM" msgstr "" #: src/conversation/gnunet-conversation.c:943 msgid "Use `/suspend' to suspend the active call" msgstr "" #: src/conversation/gnunet-conversation.c:945 msgid "" "Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming " "calls, no argument is needed to resume the current outgoing call." msgstr "" #: src/conversation/gnunet-conversation.c:947 msgid "Use `/cancel' to reject or terminate a call" msgstr "" #: src/conversation/gnunet-conversation.c:949 #, fuzzy msgid "Use `/status' to print status information" msgstr "ser prolijo (imprime información de progreso)" #: src/conversation/gnunet-conversation.c:951 #, fuzzy msgid "Use `/quit' to terminate gnunet-conversation" msgstr "Use «/quit» para finalizar «gnunet-chat»" #: src/conversation/gnunet-conversation.c:953 msgid "Use `/help command' to get help for a specific command" msgstr "Use «/help comando» para obtener ayuda sobre un comando específico" #: src/conversation/gnunet-conversation.c:1151 #, fuzzy, c-format msgid "Name of our ego changed to `%s'\n" msgstr "Se produjo un fallo al crear la página para «%s»\n" #: src/conversation/gnunet-conversation.c:1164 #, fuzzy, c-format msgid "Our ego `%s' was deleted!\n" msgstr "El pseudónimo '%s' fue borrado.\n" #: src/conversation/gnunet-conversation.c:1199 #, fuzzy msgid "You must specify the NAME of an ego to use\n" msgstr "Debes especificar un fichero a inspeccionar.\n" #: src/conversation/gnunet-conversation.c:1223 #, fuzzy msgid "Failed to start gnunet-helper-w32-console\n" msgstr "Se produjo un fallo al iniciar el proceso «gnunet-peerinfo».\n" #: src/conversation/gnunet-conversation.c:1249 msgid "sets the NAME of the ego to use for the phone (and name resolution)" msgstr "" #: src/conversation/gnunet-conversation.c:1252 msgid "sets the LINE to use for the phone" msgstr "" #: src/conversation/gnunet-conversation.c:1276 msgid "Enables having a conversation with other GNUnet users." msgstr "" #: src/conversation/gnunet-conversation-test.c:121 #, c-format msgid "" "\n" "End of transmission. Have a GNU day.\n" msgstr "" #: src/conversation/gnunet-conversation-test.c:149 #, c-format msgid "" "\n" "We are now playing your recording back. If you can hear it, your audio " "settings are working..." msgstr "" #: src/conversation/gnunet-conversation-test.c:215 #, c-format msgid "" "We will now be recording you for %s. After that time, the recording will be " "played back to you..." msgstr "" #: src/conversation/gnunet-conversation-test.c:248 #: src/multicast/gnunet-multicast.c:70 src/revocation/gnunet-revocation.c:522 #: src/template/gnunet-template.c:70 msgid "help text" msgstr "texto de ayuda" #: src/conversation/gnunet-helper-audio-playback.c:305 #, fuzzy, c-format msgid "pa_stream_write() failed: %s\n" msgstr "stadísticas (%s) falló: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:587 msgid "gnunet-helper-audio-playback - Got signal, exiting\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:612 #: src/conversation/gnunet-helper-audio-record.c:545 #, fuzzy msgid "Connection established.\n" msgstr "Colección detenida.\n" #: src/conversation/gnunet-helper-audio-playback.c:617 #: src/conversation/gnunet-helper-audio-record.c:550 #, fuzzy, c-format msgid "pa_stream_new() failed: %s\n" msgstr "stadísticas (%s) falló: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:631 #, c-format msgid "pa_stream_connect_playback() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:644 #: src/conversation/gnunet-helper-audio-record.c:576 #, fuzzy, c-format msgid "Connection failure: %s\n" msgstr "'%s' falló en %s: %d con error: '%s'.\n" #: src/conversation/gnunet-helper-audio-playback.c:665 #: src/conversation/gnunet-helper-audio-record.c:599 #, fuzzy msgid "Wrong Spec\n" msgstr "Servicio principal (CORE) erróneo\n" #: src/conversation/gnunet-helper-audio-playback.c:671 #: src/conversation/gnunet-helper-audio-record.c:605 #, fuzzy msgid "pa_mainloop_new() failed.\n" msgstr "La operación ha fallado.\n" #: src/conversation/gnunet-helper-audio-playback.c:685 #: src/conversation/gnunet-helper-audio-record.c:620 #, fuzzy msgid "pa_context_new() failed.\n" msgstr "La operación ha fallado.\n" #: src/conversation/gnunet-helper-audio-playback.c:692 #: src/conversation/gnunet-helper-audio-record.c:626 #, fuzzy, c-format msgid "pa_context_connect() failed: %s\n" msgstr "# reconexiones rápidas fallidas" #: src/conversation/gnunet-helper-audio-playback.c:698 #: src/conversation/gnunet-helper-audio-record.c:632 #, fuzzy msgid "pa_mainloop_run() failed.\n" msgstr "La operación ha fallado.\n" #: src/conversation/gnunet-helper-audio-playback.c:768 #, c-format msgid "Read error from STDIN: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback-gst.c:325 #, c-format msgid "Read error from STDIN: %d %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:344 #, fuzzy, c-format msgid "opus_encode_float() failed: %s. Aborting\n" msgstr "# reconexiones rápidas fallidas" #: src/conversation/gnunet-helper-audio-record.c:420 #, fuzzy, c-format msgid "pa_stream_peek() failed: %s\n" msgstr "stadísticas (%s) falló: %s\n" #: src/conversation/gnunet-helper-audio-record.c:458 msgid "Got signal, exiting.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:483 #, fuzzy msgid "Stream successfully created.\n" msgstr "Conectado satisfactoriamente a «%s»\n" #: src/conversation/gnunet-helper-audio-record.c:488 #, fuzzy, c-format msgid "pa_stream_get_buffer_attr() failed: %s\n" msgstr "stadísticas (%s) falló: %s\n" #: src/conversation/gnunet-helper-audio-record.c:496 #, c-format msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:500 #, c-format msgid "Using sample spec '%s', channel map '%s'.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:507 #, fuzzy, c-format msgid "Connected to device %s (%u, %ssuspended).\n" msgstr "Conectado a %s.\n" #: src/conversation/gnunet-helper-audio-record.c:516 #, c-format msgid "Stream error: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:563 #, fuzzy, c-format msgid "pa_stream_connect_record() failed: %s\n" msgstr "No se pudo borrar el registro: %s\n" #: src/conversation/gnunet-helper-audio-record.c:676 #, fuzzy msgid "ogg_stream_init() failed.\n" msgstr "stadísticas (%s) falló: %s\n" #: src/conversation/gnunet-helper-audio-record.c:721 #, fuzzy, c-format msgid "Failed to allocate %d bytes for second packet\n" msgstr "" "Se produjo un fallo al alojar las direcciones IP para el nuevo destino\n" #: src/conversation/gnunet-service-conversation.c:841 msgid "Mesh audio channel not ready; audio data dropped\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:932 #, c-format msgid "" "No available phone for incoming call on line %u, sending HANG_UP signal\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:1338 #, fuzzy, c-format msgid "Received incoming channel on port %u\n" msgstr "Desconectado de %s\n" #: src/conversation/microphone.c:121 #, fuzzy msgid "Could not start record audio helper\n" msgstr "No se pudo empezar la operación de desindexado.\n" #: src/conversation/plugin_gnsrecord_conversation.c:116 #, fuzzy, c-format msgid "Unable to parse PHONE record `%s'\n" msgstr "No se pudo procesar el registro PKEY «%s»\n" #: src/conversation/speaker.c:75 #, fuzzy msgid "Could not start playback audio helper.\n" msgstr "No se pudo empezar a publicar.\n" #: src/core/core_api.c:767 msgid "Client was disconnected from core service, trying to reconnect.\n" msgstr "" "El cliente se desconectó del servicio principal, tratando de reconectar.\n" #: src/core/gnunet-core.c:80 #, c-format msgid "Peer `%s'\n" msgstr "Par «%s»\n" #: src/core/gnunet-core.c:110 src/core/gnunet-core.c:138 #: src/transport/gnunet-transport.c:910 src/transport/gnunet-transport.c:930 #, c-format msgid "%24s: %-17s %4s (%u connections in total)\n" msgstr "%24s: %-17s %4s (%u conexiones en total)\n" #: src/core/gnunet-core.c:112 src/transport/gnunet-transport.c:911 msgid "Connected to" msgstr "Conectado a" #: src/core/gnunet-core.c:140 src/transport/gnunet-transport.c:931 msgid "Disconnected from" msgstr "Desconectado de" #: src/core/gnunet-core.c:211 src/peerinfo-tool/gnunet-peerinfo.c:694 #, c-format msgid "Invalid command line argument `%s'\n" msgstr "Parámetro no válido «%s» en la línea de comandos\n" # Miguel: ¿Quizá continuamente fuese mejor? #: src/core/gnunet-core.c:233 src/transport/gnunet-transport.c:1486 msgid "provide information about all current connections (continuously)" msgstr "" "provee información sobre todas las conexiones actuales (de forma continua)" #: src/core/gnunet-core.c:244 msgid "Print information about connected peers." msgstr "Imprime información sobre los pares conectados." #: src/core/gnunet-service-core.c:105 msgid "Core service is lacking HOSTKEY configuration setting. Exiting.\n" msgstr "" "Al servicio principal le falta la configuración de la clave de máquina " "(HOSTKEY). Saliendo.\n" #: src/core/gnunet-service-core.c:126 #, c-format msgid "Core service of `%4s' ready.\n" msgstr "El servicio principal de «%4s» está listo.\n" #: src/core/gnunet-service-core_clients.c:370 msgid "# send requests dropped (disconnected)" msgstr "# peticiones de envío descartadas (desconectado)" #: src/core/gnunet-service-core_clients.c:480 msgid "# messages discarded (session disconnected)" msgstr "# mensajes descartados (sesión desconectada)" #: src/core/gnunet-service-core_clients.c:526 #, c-format msgid "# bytes of messages of type %u received" msgstr "# bytes de mensajes del tipo %u recibidos" #: src/core/gnunet-service-core_kx.c:535 msgid "# bytes encrypted" msgstr "# bytes cifrados" #: src/core/gnunet-service-core_kx.c:586 msgid "# bytes decrypted" msgstr "# bytes descifrados" #: src/core/gnunet-service-core_kx.c:673 msgid "# key exchanges initiated" msgstr "# intercambio de claves iniciados" #: src/core/gnunet-service-core_kx.c:713 msgid "# key exchanges stopped" msgstr "# intercambio de claves parados" #: src/core/gnunet-service-core_kx.c:810 msgid "# old ephemeral keys ignored" msgstr "" #: src/core/gnunet-service-core_kx.c:816 #, fuzzy msgid "# ephemeral keys received" msgstr "# mapas de tipos recibidos" #: src/core/gnunet-service-core_kx.c:850 #, c-format msgid "" "Ephemeral key message from peer `%s' rejected as its validity range does not " "match our system time (%llu not in [%llu,%llu]).\n" msgstr "" #: src/core/gnunet-service-core_kx.c:861 #, fuzzy msgid "# EPHEMERAL_KEY messages received" msgstr "# mensajes «SET_KEY» descifrados" #: src/core/gnunet-service-core_kx.c:951 #: src/transport/gnunet-service-transport_validation.c:1016 msgid "# PING messages received" msgstr "# mensajes PING recibidos" #: src/core/gnunet-service-core_kx.c:959 #, fuzzy msgid "# PING messages dropped (out of order)" msgstr "# Mensajes P2P omitidos debido a saturación de la cola" #: src/core/gnunet-service-core_kx.c:986 #, c-format msgid "" "Received PING from `%s' for different identity: I am `%s', PONG identity: `" "%s'\n" msgstr "" "Recibido PING de «%s» para una identidad diferente: Yo soy «%s», identidad " "del PONG: «%s»\n" #: src/core/gnunet-service-core_kx.c:1003 msgid "# PONG messages created" msgstr "# mensajes PONG creados" #: src/core/gnunet-service-core_kx.c:1029 msgid "# sessions terminated by timeout" msgstr "# sesiones terminadas por plazo de expiración" #: src/core/gnunet-service-core_kx.c:1039 msgid "# keepalive messages sent" msgstr "# mensajes «keepalive» enviados" #: src/core/gnunet-service-core_kx.c:1096 #: src/transport/gnunet-service-transport_validation.c:1328 msgid "# PONG messages received" msgstr "# mensajes PONG recibidos" #: src/core/gnunet-service-core_kx.c:1102 #, fuzzy msgid "# PONG messages dropped (connection down)" msgstr "# mensajes PONG recibidos" #: src/core/gnunet-service-core_kx.c:1107 #, fuzzy msgid "# PONG messages dropped (out of order)" msgstr "# Mensajes P2P omitidos debido a saturación de la cola" #: src/core/gnunet-service-core_kx.c:1137 msgid "# PONG messages decrypted" msgstr "# mensajes PONG descifrados" #: src/core/gnunet-service-core_kx.c:1171 msgid "# session keys confirmed via PONG" msgstr "# claves de sesión confirmadas vía PONG" #: src/core/gnunet-service-core_kx.c:1181 #, fuzzy msgid "# timeouts prevented via PONG" msgstr "# bytes recibidos vía TCP" #: src/core/gnunet-service-core_kx.c:1188 msgid "# rekey operations confirmed via PONG" msgstr "# operaciones de cambio de clave confirmadas vía PONG" #: src/core/gnunet-service-core_kx.c:1328 #, fuzzy msgid "# DATA message dropped (out of order)" msgstr "# bytes omitidos (fuera de secuencia)" #: src/core/gnunet-service-core_kx.c:1335 #, c-format msgid "" "Session to peer `%s' went down due to key expiration (should not happen)\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1338 #, fuzzy msgid "# sessions terminated by key expiration" msgstr "# sesiones terminadas por plazo de expiración" #: src/core/gnunet-service-core_kx.c:1383 #: src/core/gnunet-service-core_kx.c:1408 msgid "# bytes dropped (duplicates)" msgstr "# bytes omitidos (duplicados)" #: src/core/gnunet-service-core_kx.c:1395 msgid "# bytes dropped (out of sequence)" msgstr "# bytes omitidos (fuera de secuencia)" #: src/core/gnunet-service-core_kx.c:1437 msgid "# bytes dropped (ancient message)" msgstr "# bytes omitidos (mensaje antiguo)" #: src/core/gnunet-service-core_kx.c:1445 msgid "# bytes of payload decrypted" msgstr "# bytes de «payload» descifrados" #: src/core/gnunet-service-core_kx.c:1480 #, fuzzy msgid "# PAYLOAD dropped (out of order)" msgstr "# bytes omitidos (fuera de secuencia)" #: src/core/gnunet-service-core_neighbours.c:168 msgid "# sessions terminated by transport disconnect" msgstr "# sesiones terminadas por desconexión de transporte" #: src/core/gnunet-service-core_neighbours.c:184 #: src/core/gnunet-service-core_neighbours.c:335 msgid "# neighbour entries allocated" msgstr "# entradas de vecinos alojadas" #: src/core/gnunet-service-core_neighbours.c:252 msgid "# encrypted bytes given to transport" msgstr "# bytes cifrados dados al transporte" #: src/core/gnunet-service-core_neighbours.c:418 #, c-format msgid "Unsupported message of type %u (%u bytes) received from peer `%s'\n" msgstr "Mensaje no soportado del tipo %u (%u bytes) recibido del par «%s»\n" #: src/core/gnunet-service-core_sessions.c:216 #: src/core/gnunet-service-core_sessions.c:288 #: src/dht/gnunet-service-dht_neighbours.c:662 #: src/dht/gnunet-service-dht_neighbours.c:727 #: src/dht/gnunet-service-xdht_neighbours.c:1304 #: src/fs/gnunet-service-fs_cp.c:606 src/fs/gnunet-service-fs_cp.c:1501 #: src/topology/gnunet-daemon-topology.c:707 #: src/topology/gnunet-daemon-topology.c:808 #: src/transport/gnunet-service-transport_neighbours.c:917 #: src/transport/gnunet-service-transport_neighbours.c:1141 #: src/transport/gnunet-service-transport_neighbours.c:3142 #: src/transport/gnunet-service-transport_neighbours.c:3438 msgid "# peers connected" msgstr "# pares conectados" #: src/core/gnunet-service-core_sessions.c:255 msgid "# type map refreshes sent" msgstr "# envíos de refrescos del mapa de tipos" #: src/core/gnunet-service-core_sessions.c:426 msgid "# messages discarded (expired prior to transmission)" msgstr "# mensajes descartados (expirados antes de su transmisión)" #: src/core/gnunet-service-core_typemap.c:110 #: src/core/gnunet-service-core_typemap.c:121 msgid "# type maps received" msgstr "# mapas de tipos recibidos" #: src/core/gnunet-service-core_typemap.c:151 msgid "# updates to my type map" msgstr "# actualizaciones de mi mapa de tipos" #: src/datacache/datacache.c:115 src/datacache/datacache.c:266 #: src/datastore/gnunet-service-datastore.c:838 msgid "# bytes stored" msgstr "# bytes almacenados" #: src/datacache/datacache.c:117 src/datacache/datacache.c:268 msgid "# items stored" msgstr "# elementos almacenados" #: src/datacache/datacache.c:143 src/datacache/datacache.c:150 #: src/datastore/gnunet-service-datastore.c:1487 #: src/datastore/gnunet-service-datastore.c:1498 #, c-format msgid "No `%s' specified for `%s' in configuration!\n" msgstr "¡No se ha especificado ningún «%s» para «%s» en la configuración!\n" #: src/datacache/datacache.c:184 #, c-format msgid "Loading `%s' datacache plugin\n" msgstr "Cargando el módulo de la cache de datos «%s»\n" #: src/datacache/datacache.c:192 #, c-format msgid "Failed to load datacache plugin for `%s'\n" msgstr "" "Se produjo un fallo al cargar el módulo de la cache de datos para «%s»\n" #: src/datacache/datacache.c:295 msgid "# requests received" msgstr "# peticiones recibidas" #: src/datacache/datacache.c:304 msgid "# requests filtered by bloom filter" msgstr "# peticiones filtradas por el «bloomfilter»" #: src/datacache/plugin_datacache_heap.c:406 msgid "Heap datacache running\n" msgstr "Caché de datos de montículo (heap) ejecutándose\n" #: src/datacache/plugin_datacache_postgres.c:392 msgid "Postgres datacache running\n" msgstr "Caché de datos Postgres ejecutándose\n" #: src/datacache/plugin_datacache_sqlite.c:69 #: src/datacache/plugin_datacache_sqlite.c:72 #: src/datastore/plugin_datastore_mysql.c:806 #: src/datastore/plugin_datastore_mysql.c:820 #: src/datastore/plugin_datastore_sqlite.c:57 src/mysql/mysql.c:41 #: src/mysql/mysql.c:48 src/mysql/mysql.c:522 src/mysql/mysql.c:531 #: src/mysql/mysql.c:591 src/mysql/mysql.c:607 #: src/namecache/plugin_namecache_postgres.c:52 #: src/namecache/plugin_namecache_sqlite.c:52 #: src/namestore/plugin_namestore_postgres.c:52 #: src/namestore/plugin_namestore_sqlite.c:52 #: src/testbed/generate-underlay-topology.c:47 #: src/testbed/gnunet-daemon-latency-logger.c:52 #: src/testbed/gnunet-daemon-testbed-underlay.c:55 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:51 #: src/util/crypto_mpi.c:39 src/include/gnunet_common.h:602 #: src/include/gnunet_common.h:611 src/scalarproduct/scalarproduct.h:50 #, c-format msgid "`%s' failed at %s:%d with error: %s\n" msgstr "«%s» falló en %s: %d con el error: %s\n" #: src/datacache/plugin_datacache_sqlite.c:450 msgid "Sqlite datacache running\n" msgstr "Caché de datos Sqlite ejecutándose\n" #: src/datacache/plugin_datacache_sqlite.c:484 #: src/datastore/plugin_datastore_sqlite.c:404 #: src/namecache/plugin_namecache_sqlite.c:295 #: src/namestore/plugin_namestore_sqlite.c:327 msgid "Tried to close sqlite without finalizing all prepared statements.\n" msgstr "" "Se intentó cerrar sqlite sin finalizar todas las sentencias preparadas.\n" #: src/datacache/plugin_datacache_sqlite.c:491 #, c-format msgid "Failed to close statement %p: %d\n" msgstr "Se produjo un fallo al cerrar la sentencia %p: %d\n" #: src/datacache/plugin_datacache_template.c:125 msgid "Template datacache running\n" msgstr "Caché de datos de plantilla en ejecución\n" # Miguel: "Drop" en bases de datos es eliminar una tabla # del modelo. #: src/datastore/datastore_api.c:310 msgid "Failed to transmit request to drop database.\n" msgstr "" "Se produjo un fallo al transmitir la petición de eliminación a la base de " "datos.\n" #: src/datastore/datastore_api.c:394 msgid "# queue entry timeouts" msgstr "# expiraciones de plazo en la cola de entradas" #: src/datastore/datastore_api.c:443 msgid "# queue overflows" msgstr "# desbordamientos de la cola" #: src/datastore/datastore_api.c:471 msgid "# queue entries created" msgstr "# entradas creadas en la cola" #: src/datastore/datastore_api.c:491 msgid "# Requests dropped from datastore queue" msgstr "# Peticiones omitidas de la cola del almacén de datos" #: src/datastore/datastore_api.c:533 msgid "# datastore connections (re)created" msgstr "# conexiones a almacenes de datos (re)creadas" #: src/datastore/datastore_api.c:616 src/scalarproduct/scalarproduct_api.c:279 msgid "# transmission request failures" msgstr "# fallos en peticiones de transmisión" #: src/datastore/datastore_api.c:638 msgid "# bytes sent to datastore" msgstr "# bytes mandados al almacén de datos" #: src/datastore/datastore_api.c:770 msgid "Failed to receive status response from database." msgstr "" "Se produjo un fallo al recibir el estado de respuesta de la base de datos." #: src/datastore/datastore_api.c:784 msgid "Error reading response from datastore service" msgstr "Error leyendo respuesta del servicio de almacenamiento de datos" #: src/datastore/datastore_api.c:796 src/datastore/datastore_api.c:802 msgid "Invalid error message received from datastore service" msgstr "" "Mensaje de error no válido recibido del servicio de almacenamiento de datos" #: src/datastore/datastore_api.c:806 msgid "# status messages received" msgstr "# mensajes de estado recibidos" #: src/datastore/datastore_api.c:876 msgid "# PUT requests executed" msgstr "# peticiones «PUT» ejecutadas" #: src/datastore/datastore_api.c:944 msgid "# RESERVE requests executed" msgstr "# peticiones «RESERVE» ejecutadas" #: src/datastore/datastore_api.c:1005 msgid "# RELEASE RESERVE requests executed" msgstr "# Peticiones «RELEASE RESERVE» ejecutadas" #: src/datastore/datastore_api.c:1065 msgid "# UPDATE requests executed" msgstr "# peticiones «UPDATE» ejecutadas" #: src/datastore/datastore_api.c:1129 msgid "# REMOVE requests executed" msgstr "# peticiones «REMOVE» ejecutadas" #: src/datastore/datastore_api.c:1174 msgid "Failed to receive response from database.\n" msgstr "Se produjo un fallo al recibir la respuesta de la base de datos.\n" #: src/datastore/datastore_api.c:1233 msgid "# Results received" msgstr "# Resultados recibidos" #: src/datastore/datastore_api.c:1300 msgid "# GET REPLICATION requests executed" msgstr "# peticiones «GET REPLICATION» ejecutadas" #: src/datastore/datastore_api.c:1363 msgid "# GET ZERO ANONYMITY requests executed" msgstr "# peticiones «GET ZERO ANONYMITY» ejecutadas" #: src/datastore/datastore_api.c:1424 msgid "# GET requests executed" msgstr "# peticiones «GET» ejecutadas" #: src/datastore/gnunet-datastore.c:114 #, fuzzy, c-format msgid "Failed to store item: %s, aborting\n" msgstr "Se produjo un fallo al abrir «%s» para escritura" #: src/datastore/gnunet-datastore.c:200 #, c-format msgid "Cannot use the same configuration for source and destination\n" msgstr "" #: src/datastore/gnunet-datastore.c:246 msgid "" "specifies the configuration to use to access an alternative datastore; will " "merge that datastore into our current datastore" msgstr "" #: src/datastore/gnunet-datastore.c:255 #, fuzzy msgid "Manipulate GNUnet datastore" msgstr "Manipular ficheros de configuración de GNUnet" #: src/datastore/gnunet-service-datastore.c:351 msgid "# bytes expired" msgstr "# bytes expirados" #: src/datastore/gnunet-service-datastore.c:425 msgid "# bytes purged (low-priority)" msgstr "# bytes purgados (baja prioridad)" #: src/datastore/gnunet-service-datastore.c:483 #: src/gns/gnunet-gns-helper-service-w32.c:223 msgid "Transmission to client failed!\n" msgstr "¡La transmisión con el cliente ha fallado!\n" #: src/datastore/gnunet-service-datastore.c:514 #: src/gns/gnunet-gns-helper-service-w32.c:262 msgid "Shutdown in progress, aborting transmission.\n" msgstr "Apagado en proceso, abortando transmisión.\n" #: src/datastore/gnunet-service-datastore.c:630 msgid "# results found" msgstr "# resultados encontrados" #: src/datastore/gnunet-service-datastore.c:673 #, c-format msgid "" "Insufficient space (%llu bytes are available) to satisfy `%s' request for " "%llu bytes\n" msgstr "" "Espacio insuficiente (%llu bytes están disponibles) para satisfacer la " "petición «%s» de %llu bytes\n" #: src/datastore/gnunet-service-datastore.c:684 #, c-format msgid "" "The requested amount (%llu bytes) is larger than the cache size (%llu " "bytes)\n" msgstr "" "La cantidad solicitada (%llu bytes) es mayor que el tamaño de la caché (%llu " "bytes)\n" #: src/datastore/gnunet-service-datastore.c:688 msgid "" "Insufficient space to satisfy request and requested amount is larger than " "cache size" msgstr "" "Espacio insuficiente para satisfacer la petición y la cantidad pedida es " "mayor que el tamaño de la caché" #: src/datastore/gnunet-service-datastore.c:694 msgid "Insufficient space to satisfy request" msgstr "Espacio insuficiente para satisfacer la petición" #: src/datastore/gnunet-service-datastore.c:699 #: src/datastore/gnunet-service-datastore.c:751 #: src/datastore/gnunet-service-datastore.c:964 #: src/datastore/gnunet-service-datastore.c:1421 msgid "# reserved" msgstr "# reservado" #: src/datastore/gnunet-service-datastore.c:764 msgid "Could not find matching reservation" msgstr "No se pudo encontrar una reserva coincidente" #: src/datastore/gnunet-service-datastore.c:850 #, c-format msgid "Need %llu bytes more space (%llu allowed, using %llu)\n" msgstr "" "Se necesitan %llu bytes más de espacio (%llu permitidos, usando %llu)\n" #: src/datastore/gnunet-service-datastore.c:1010 msgid "# GET requests received" msgstr "# peticiones «GET» recibidas" #: src/datastore/gnunet-service-datastore.c:1022 msgid "# requests filtered by bloomfilter" msgstr "# peticiones filtradas por el «bloomfilter»" #: src/datastore/gnunet-service-datastore.c:1050 msgid "# UPDATE requests received" msgstr "# peticiones «UPDATE» recibidas" #: src/datastore/gnunet-service-datastore.c:1080 msgid "# GET REPLICATION requests received" msgstr "# peticiones «GET REPLICATION» recibidas" #: src/datastore/gnunet-service-datastore.c:1113 msgid "# GET ZERO ANONYMITY requests received" msgstr "# peticiones «GET ZERO ANONYMITY» recibidas" #: src/datastore/gnunet-service-datastore.c:1138 msgid "Content not found" msgstr "Contenido no encontrado" #: src/datastore/gnunet-service-datastore.c:1146 msgid "# bytes removed (explicit request)" msgstr "# bytes eliminados (petición explícita)" #: src/datastore/gnunet-service-datastore.c:1178 msgid "# REMOVE requests received" msgstr "# peticiones «REMOVE» recibidas" # Miguel: ¿Cómo traducir «payload»? ¿Código cargado? #: src/datastore/gnunet-service-datastore.c:1220 #, c-format msgid "Datastore payload inaccurate (%lld < %lld). Trying to fix.\n" msgstr "" "El «payload» del almacén de datos es impreciso (%lld < %lld). Intentando " "repararlo.\n" #: src/datastore/gnunet-service-datastore.c:1281 #, c-format msgid "Loading `%s' datastore plugin\n" msgstr "Cargando el módulo del almacén de datos «%s»\n" #: src/datastore/gnunet-service-datastore.c:1290 #, c-format msgid "Failed to load datastore plugin for `%s'\n" msgstr "" "Se produjo un fallo al inicializar el módulo del almacén de datos para «%s»\n" #: src/datastore/gnunet-service-datastore.c:1492 #, c-format msgid "# bytes used in file-sharing datastore `%s'" msgstr "# bytes usados en el almacén de ficheros compartidos «%s»" #: src/datastore/gnunet-service-datastore.c:1503 msgid "# quota" msgstr "# cuota" #: src/datastore/gnunet-service-datastore.c:1505 msgid "# cache size" msgstr "# tamaño de la caché" #: src/datastore/gnunet-service-datastore.c:1518 #, c-format msgid "Could not use specified filename `%s' for bloomfilter.\n" msgstr "" "No se pudo usar el nombre de fichero especificado «%s» para «bloomfilter».\n" #: src/datastore/gnunet-service-datastore.c:1536 #: src/datastore/gnunet-service-datastore.c:1552 #, c-format msgid "Failed to remove bogus bloomfilter file `%s'\n" msgstr "" "Se produjo un fallo al borrar el fichero de configuración defectuoso de " "«bloomfilter» «%s»:\n" #: src/datastore/gnunet-service-datastore.c:1582 msgid "Failed to initialize bloomfilter.\n" msgstr "Se produjo un fallo al inicializar «bloomfilter».\n" #: src/datastore/gnunet-service-datastore.c:1611 msgid "Rebuilding bloomfilter. Please be patient.\n" msgstr "Reconstruyendo «bloomfilter». Por favor, tenga paciencia.\n" #: src/datastore/gnunet-service-datastore.c:1616 msgid "Plugin does not support get_keys function. Please fix!\n" msgstr "El módulo no soporta la función «get_keys». Por favor, corríjalo.\n" #: src/datastore/gnunet-service-datastore.c:1619 msgid "Bloomfilter construction complete.\n" msgstr "Construcción de «bloomfilter» completa.\n" #: src/datastore/plugin_datastore_heap.c:820 msgid "Heap database running\n" msgstr "Base de datos de montículo ejecutándose\n" #: src/datastore/plugin_datastore_mysql.c:783 #, c-format msgid "Failed to prepare statement `%s'\n" msgstr "Se produjo un fallo al preparar la sentencia «%s»\n" #: src/datastore/plugin_datastore_mysql.c:791 #, c-format msgid "`%s' for `%s' failed at %s:%d with error: %s\n" msgstr "«%s» para «%s» falló en %s: %d con error: %s\n" #: src/datastore/plugin_datastore_mysql.c:1022 msgid "Mysql database running\n" msgstr "Base de datos Mysql ejecutándose\n" #: src/datastore/plugin_datastore_postgres.c:824 msgid "Failed to drop table from database.\n" msgstr "Se produjo un fallo al borrar una tabla de la base de datos.\n" #: src/datastore/plugin_datastore_postgres.c:860 #: src/namecache/plugin_namecache_postgres.c:414 #: src/namestore/plugin_namestore_postgres.c:569 msgid "Postgres database running\n" msgstr "Base de datos Postgres ejecutándose\n" #: src/datastore/plugin_datastore_sqlite.c:57 #: src/testbed/generate-underlay-topology.c:50 #: src/testbed/gnunet-daemon-latency-logger.c:55 #: src/testbed/gnunet-daemon-testbed-underlay.c:58 #, c-format msgid "`%s' failed at %s:%u with error: %s" msgstr "«%s» falló en %s:%u con el error: %s" #: src/datastore/plugin_datastore_sqlite.c:255 #: src/namecache/plugin_namecache_sqlite.c:193 #: src/namestore/plugin_namestore_sqlite.c:204 #: src/psycstore/plugin_psycstore_sqlite.c:319 #, c-format msgid "Unable to initialize SQLite: %s.\n" msgstr "Imposible inicializar SQLite: %s.\n" #: src/datastore/plugin_datastore_sqlite.c:663 msgid "Invalid data in database. Trying to fix (by deletion).\n" msgstr "" "Datos no válidos en la base de datos. Intentando arreglar (por borrado).\n" # to should be too, i think #: src/datastore/plugin_datastore_sqlite.c:1156 msgid "sqlite version to old to determine size, assuming zero\n" msgstr "" "la versión de sqlite es muy antigua para determinar el tamaño, se asume " "cero\n" #: src/datastore/plugin_datastore_sqlite.c:1175 #, c-format msgid "" "Using sqlite page utilization to estimate payload (%llu pages of size %llu " "bytes)\n" msgstr "" "Usando la utilización de páginas de sqlite para estimar el «payload» (%llu " "páginas de %llu bytes de tamaño)\n" #: src/datastore/plugin_datastore_sqlite.c:1215 #: src/namecache/plugin_namecache_sqlite.c:583 #: src/namestore/plugin_namestore_sqlite.c:719 msgid "Sqlite database running\n" msgstr "Base de datos sqlite ejecutándose\n" #: src/datastore/plugin_datastore_template.c:257 msgid "Template database running\n" msgstr "Base de datos de plantilla ejecutándose\n" #: src/dht/dht_api.c:376 msgid "Failed to connect to the DHT service!\n" msgstr "¡Se produjo un fallo al conectar con el servicio DHT!\n" #: src/dht/gnunet-dht-get.c:133 #, c-format msgid "" "Result %d, type %d:\n" "%.*s\n" msgstr "" "Resultado %d, tipo %d:\n" "%.*s\n" #: src/dht/gnunet-dht-get.c:159 msgid "Must provide key for DHT GET!\n" msgstr "¡Se debe proveer una clave para el «GET» DHT!\n" #: src/dht/gnunet-dht-get.c:165 src/dht/gnunet-dht-monitor.c:225 msgid "Failed to connect to DHT service!\n" msgstr "¡Se produjo un fallo al conectar con el servicio DHT!\n" #: src/dht/gnunet-dht-get.c:173 msgid "Issueing DHT GET with key" msgstr "Enviando un «GET» DHT con clave" #: src/dht/gnunet-dht-get.c:189 src/dht/gnunet-dht-monitor.c:262 #: src/dht/gnunet-dht-put.c:198 msgid "the query key" msgstr "la clave de búsqueda" #: src/dht/gnunet-dht-get.c:192 msgid "how many parallel requests (replicas) to create" msgstr "cuantas peticiones paralelas (réplicas) crear" #: src/dht/gnunet-dht-get.c:195 src/dht/gnunet-dht-monitor.c:265 msgid "the type of data to look for" msgstr "el tipo de datos a buscar" #: src/dht/gnunet-dht-get.c:198 src/dht/gnunet-dht-put.c:210 msgid "how long to execute this query before giving up?" msgstr "¿cuánto tiempo se debe ejecutar esta consulta antes de abandonar?" #: src/dht/gnunet-dht-get.c:201 src/dht/gnunet-dht-put.c:201 msgid "use DHT's demultiplex everywhere option" msgstr "opción para usar el demultiplexado de la DHT siempre" #: src/dht/gnunet-dht-get.c:204 src/dht/gnunet-dht-monitor.c:271 #: src/dht/gnunet-dht-put.c:213 src/fs/gnunet-auto-share.c:753 #: src/fs/gnunet-download.c:328 src/fs/gnunet-publish.c:877 #: src/fs/gnunet-search.c:301 src/fs/gnunet-unindex.c:168 #: src/nse/gnunet-nse-profiler.c:873 msgid "be verbose (print progress information)" msgstr "ser prolijo (imprime información de progreso)" #: src/dht/gnunet-dht-get.c:225 msgid "Issue a GET request to the GNUnet DHT, prints results." msgstr "" "Iniciando una peticion «GET» a la DHT de GNUnet, imprimiendo resultados." #: src/dht/gnunet-dht-monitor.c:268 msgid "how long should the monitor command run" msgstr "cuanto tiempo debe ejecutarse el comando de monitorización" #: src/dht/gnunet-dht-monitor.c:293 msgid "Prints all packets that go through the DHT." msgstr "Imprime todos los paquetes que pasan por la DHT." #: src/dht/gnunet-dht-put.c:118 msgid "PUT request sent with key" msgstr "Petición «PUT» enviada con clave" #: src/dht/gnunet-dht-put.c:121 msgid "Timeout sending PUT request!\n" msgstr "¡Expiró el plazo enviando una petición «PUT»!\n" #: src/dht/gnunet-dht-put.c:124 msgid "PUT request not confirmed!\n" msgstr "¡Petición «PUT» no confirmada!\n" #: src/dht/gnunet-dht-put.c:153 msgid "Must provide KEY and DATA for DHT put!\n" msgstr "¡Se deben proveer «KEY» y «DATA» para una subida a la DHT!\n" #: src/dht/gnunet-dht-put.c:160 #, c-format msgid "Could not connect to %s service!\n" msgstr "¡No se pudo conectar al servicio %s!\n" #: src/dht/gnunet-dht-put.c:176 #, c-format msgid "Issuing put request for `%s' with data `%s'!\n" msgstr "¡Iniciando petición de subida para «%s» con datos «%s»!\n" #: src/dht/gnunet-dht-put.c:192 msgid "the data to insert under the key" msgstr "los datos a insertar bajo la clave" #: src/dht/gnunet-dht-put.c:195 msgid "how long to store this entry in the dht (in seconds)" msgstr "cuanto tiempo almacenar esta entrada en la DHT (en segundos)" #: src/dht/gnunet-dht-put.c:204 msgid "how many replicas to create" msgstr "cuantas réplicas crear" #: src/dht/gnunet-dht-put.c:207 msgid "the type to insert data as" msgstr "el tipo de datos a insertar" #: src/dht/gnunet-dht-put.c:236 msgid "Issue a PUT request to the GNUnet DHT insert DATA under KEY." msgstr "" "Inicianco una petición «PUT» a la DHT de GNUnet para insertar «DATA» bajo " "«KEY»." #: src/dht/gnunet-service-dht.c:172 src/dht/gnunet-service-xdht.c:176 msgid "Failed to connect to transport service!\n" msgstr "¡Se produjo un fallo al conectar con el servicio de transporte!\n" #: src/dht/gnunet-service-dht_clients.c:417 #: src/dht/gnunet-service-xdht_clients.c:838 msgid "# GET requests from clients injected" msgstr "# peticiones «GET» inyectadas de clientes" #: src/dht/gnunet-service-dht_clients.c:513 #: src/dht/gnunet-service-xdht_clients.c:927 msgid "# PUT requests received from clients" msgstr "# peticiones «PUT» recibidas de clientes" #: src/dht/gnunet-service-dht_clients.c:597 #: src/dht/gnunet-service-xdht_clients.c:1013 msgid "# GET requests received from clients" msgstr "# peticiones «GET» recibidas de clientes" #: src/dht/gnunet-service-dht_clients.c:798 #: src/dht/gnunet-service-xdht_clients.c:1214 msgid "# GET STOP requests received from clients" msgstr "# peticiones «GET STOP» recibidas de clientes" #: src/dht/gnunet-service-dht_clients.c:1039 #: src/dht/gnunet-service-xdht_clients.c:498 msgid "# Key match, type mismatches in REPLY to CLIENT" msgstr "" "# Coincidencias de clave, diferencias de tipo en la respuesta (REPLY) del " "cliente (CLIENT)" #: src/dht/gnunet-service-dht_clients.c:1052 #: src/dht/gnunet-service-xdht_clients.c:511 msgid "# Duplicate REPLIES to CLIENT request dropped" msgstr "" "# Peticiones duplicadas de respuestas (REPLIES) a clientes (CLIENT) omitidas" #: src/dht/gnunet-service-dht_clients.c:1089 #: src/dht/gnunet-service-xdht_clients.c:548 #, c-format msgid "Unsupported block type (%u) in request!\n" msgstr "¡Tipo de bloque no soportado (%u) en la petición!\n" #: src/dht/gnunet-service-dht_clients.c:1112 #: src/dht/gnunet-service-xdht_clients.c:571 msgid "# RESULTS queued for clients" msgstr "# Resultados (RESULTS) encolados para clientes" #: src/dht/gnunet-service-dht_clients.c:1166 #: src/dht/gnunet-service-dht_clients.c:1209 #: src/dht/gnunet-service-xdht_clients.c:625 #: src/dht/gnunet-service-xdht_clients.c:668 msgid "# REPLIES ignored for CLIENTS (no match)" msgstr "" "# Respuestas (REPLIES) ignoradas para clientes (CLIENTS) (sin coincidencia)" #: src/dht/gnunet-service-dht_clients.c:1176 #: src/dht/gnunet-service-xdht_clients.c:635 msgid "Could not pass reply to client, message too big!\n" msgstr "" "¡No se pudo enviar respuesta al cliente, el mensaje es demasiado grande!\n" #: src/dht/gnunet-service-dht_datacache.c:68 #: src/dht/gnunet-service-xdht_datacache.c:68 #, c-format msgid "%s request received, but have no datacache!\n" msgstr "¡Petición %s recibida, pero no tiene caché de datos!\n" #: src/dht/gnunet-service-dht_datacache.c:78 #: src/dht/gnunet-service-xdht_datacache.c:78 msgid "# ITEMS stored in datacache" msgstr "# Elementos (ITEMS) almacenados en la caché de datos" #: src/dht/gnunet-service-dht_datacache.c:165 #: src/dht/gnunet-service-xdht_datacache.c:165 msgid "# Good RESULTS found in datacache" msgstr "# Buenos resultados (RESULTS) encontrados en la caché de datos" #: src/dht/gnunet-service-dht_datacache.c:176 #: src/dht/gnunet-service-xdht_datacache.c:176 msgid "# Duplicate RESULTS found in datacache" msgstr "# Resultados (RESULTS) duplicados encontrados en la caché de datos" #: src/dht/gnunet-service-dht_datacache.c:182 #: src/dht/gnunet-service-xdht_datacache.c:182 msgid "# Invalid RESULTS found in datacache" msgstr "# Resultados (RESULTS) no válidos encontrados en la caché de datos" #: src/dht/gnunet-service-dht_datacache.c:188 #: src/dht/gnunet-service-xdht_datacache.c:188 msgid "# Irrelevant RESULTS found in datacache" msgstr "# Resultados (RESULTS) irrelevantes encontrados en la caché de datos" #: src/dht/gnunet-service-dht_datacache.c:200 #: src/dht/gnunet-service-xdht_datacache.c:200 msgid "# Unsupported RESULTS found in datacache" msgstr "# Resultados (RESULTS) no soportados encontrados en la caché de datos" #: src/dht/gnunet-service-dht_datacache.c:203 #: src/dht/gnunet-service-xdht_datacache.c:203 #, c-format msgid "Unsupported block type (%u) in local response!\n" msgstr "¡Tipo de bloque no soportado (%u) en respuesta local!\n" #: src/dht/gnunet-service-dht_datacache.c:234 #: src/dht/gnunet-service-xdht_datacache.c:234 msgid "# GET requests given to datacache" msgstr "# Peticiones «GET» realizadas a la caché de datos" #: src/dht/gnunet-service-dht_hello.c:84 #: src/dht/gnunet-service-xdht_hello.c:82 msgid "# HELLOs obtained from peerinfo" msgstr "# «HELLO» obtenidos de «peerinfo»" #: src/dht/gnunet-service-dht_neighbours.c:516 msgid "# Preference updates given to core" msgstr "# Actualizaciones de preferencias dadas al servicio principal" #: src/dht/gnunet-service-dht_neighbours.c:610 msgid "# FIND PEER messages initiated" msgstr "# mensajes «FIND PEER» iniciados" #: src/dht/gnunet-service-dht_neighbours.c:764 msgid "# Queued messages discarded (peer disconnected)" msgstr "# Mensajes encolados descartados (par desconectado)" #: src/dht/gnunet-service-dht_neighbours.c:819 #: src/dht/gnunet-service-xdht_neighbours.c:703 msgid "# Bytes transmitted to other peers" msgstr "# Bytes transmitidos a otros pares" #: src/dht/gnunet-service-dht_neighbours.c:857 #: src/dht/gnunet-service-xdht_neighbours.c:742 msgid "# Bytes of bandwidth requested from core" msgstr "# Bytes de ancho de banda solicitados por el servicio principal" #: src/dht/gnunet-service-dht_neighbours.c:889 #, fuzzy msgid "# requests TTL-dropped" msgstr "# peticiones unidas" #: src/dht/gnunet-service-dht_neighbours.c:1093 #: src/dht/gnunet-service-dht_neighbours.c:1130 msgid "# Peers excluded from routing due to Bloomfilter" msgstr "# Pares excluidos del encaminado debido a «Bloomfilter»" #: src/dht/gnunet-service-dht_neighbours.c:1108 #: src/dht/gnunet-service-dht_neighbours.c:1145 msgid "# Peer selection failed" msgstr "# Selecciones de pares fallidas" #: src/dht/gnunet-service-dht_neighbours.c:1287 msgid "# PUT requests routed" msgstr "# Peticiones «PUT» encaminadas" #: src/dht/gnunet-service-dht_neighbours.c:1316 msgid "# PUT messages queued for transmission" msgstr "# mensajes «PUT» encolados para transmisión" #: src/dht/gnunet-service-dht_neighbours.c:1323 #: src/dht/gnunet-service-dht_neighbours.c:1440 #: src/dht/gnunet-service-dht_neighbours.c:1543 #: src/dht/gnunet-service-xdht_neighbours.c:794 #: src/dht/gnunet-service-xdht_neighbours.c:860 #: src/dht/gnunet-service-xdht_neighbours.c:919 #: src/dht/gnunet-service-xdht_neighbours.c:981 #: src/dht/gnunet-service-xdht_neighbours.c:1041 msgid "# P2P messages dropped due to full queue" msgstr "# Mensajes P2P omitidos debido a saturación de la cola" #: src/dht/gnunet-service-dht_neighbours.c:1405 msgid "# GET requests routed" msgstr "# Peticiones «GET» encaminadas" #: src/dht/gnunet-service-dht_neighbours.c:1432 msgid "# GET messages queued for transmission" msgstr "# Mensajes «GET» encolados para transmisión" #: src/dht/gnunet-service-dht_neighbours.c:1550 msgid "# RESULT messages queued for transmission" msgstr "# Mensajes «RESULT» encolados para transmisión" #: src/dht/gnunet-service-dht_neighbours.c:1636 msgid "# P2P PUT requests received" msgstr "# Peticiones «PUT» P2P recibidas" #: src/dht/gnunet-service-dht_neighbours.c:1639 #, fuzzy msgid "# P2P PUT bytes received" msgstr "# Peticiones «PUT» P2P recibidas" #: src/dht/gnunet-service-dht_neighbours.c:1803 msgid "# FIND PEER requests ignored due to Bloomfilter" msgstr "# Peticiones «FIND PEER» ignoradas debido a «Bloomfilter»" #: src/dht/gnunet-service-dht_neighbours.c:1811 msgid "# FIND PEER requests ignored due to lack of HELLO" msgstr "# Peticiones «FIND PEER» ignoradas debido a falta de «HELLO»" #: src/dht/gnunet-service-dht_neighbours.c:1904 msgid "# P2P GET requests received" msgstr "# Peticiones «GET» P2P recibidas" #: src/dht/gnunet-service-dht_neighbours.c:1907 #, fuzzy msgid "# P2P GET bytes received" msgstr "# Peticiones «GET» P2P recibidas" #: src/dht/gnunet-service-dht_neighbours.c:1961 msgid "# P2P FIND PEER requests processed" msgstr "# Peticiones «FIND PEER» P2P procesadas" #: src/dht/gnunet-service-dht_neighbours.c:1975 msgid "# P2P GET requests ONLY routed" msgstr "# Peticiones «GET» P2P SOLAMENTE encaminadas" #: src/dht/gnunet-service-dht_neighbours.c:2052 msgid "# P2P RESULTS received" msgstr "# Resultados (RESULTS) P2P recibidos" #: src/dht/gnunet-service-dht_neighbours.c:2055 #, fuzzy msgid "# P2P RESULT bytes received" msgstr "# Resultados (RESULTS) P2P recibidos" #: src/dht/gnunet-service-dht_nse.c:59 src/dht/gnunet-service-xdht_nse.c:59 msgid "# Network size estimates received" msgstr "# Estimaciones del tamaño de red recibidas" #: src/dht/gnunet-service-dht_routing.c:211 msgid "# Good REPLIES matched against routing table" msgstr "" "# Buenas respuestas (REPLIES) encontradas en la tabla de encaminamiento" #: src/dht/gnunet-service-dht_routing.c:220 msgid "# Duplicate REPLIES matched against routing table" msgstr "" "# Respuestas (REPLIES) duplicadas encontradas en la tabla de encaminamiento" #: src/dht/gnunet-service-dht_routing.c:226 msgid "# Invalid REPLIES matched against routing table" msgstr "" "# Respuestas (REPLIES) no válidas encontradas en la tabla de encaminamiento" #: src/dht/gnunet-service-dht_routing.c:232 msgid "# Irrelevant REPLIES matched against routing table" msgstr "" "# Respuestas (REPLIES) irrelevantes encontradas en la tabla de encaminamiento" #: src/dht/gnunet-service-dht_routing.c:244 msgid "# Unsupported REPLIES matched against routing table" msgstr "" "# Respuestas (REPLIES) no soportadas encontradas en la tabla de " "encaminamiento" #: src/dht/gnunet-service-dht_routing.c:317 msgid "# Entries removed from routing table" msgstr "# Entradas eliminadas de la tabla de encaminamiento" #: src/dht/gnunet-service-dht_routing.c:399 msgid "# Entries added to routing table" msgstr "# Entradas añadidas a la tabla de encaminamiento" #: src/dht/gnunet-service-dht_routing.c:417 msgid "# DHT requests combined" msgstr "# Peticiones a la DHT combinadas" #: src/dht/gnunet-service-xdht_neighbours.c:1398 #, c-format msgid "" "\n" "SUPU %s, %s, %d,my_identity = %s" msgstr "" #: src/dht/gnunet-service-xdht_neighbours.c:1514 #: src/dht/gnunet-service-xdht_neighbours.c:1524 #: src/dht/gnunet-service-xdht_neighbours.c:1530 #: src/dht/gnunet-service-xdht_neighbours.c:1536 #: src/dht/gnunet-service-xdht_neighbours.c:1545 #, c-format msgid "" "\n" "SUPU %s, %s, %d" msgstr "" #: src/dht/plugin_block_dht.c:138 #, c-format msgid "Block not of type %u\n" msgstr "El bloque no es del tipo %u\n" #: src/dht/plugin_block_dht.c:145 msgid "Size mismatch for block\n" msgstr "Discrepancias de tamaños para el bloque\n" #: src/dht/plugin_block_dht.c:155 #, c-format msgid "Block of type %u is malformed\n" msgstr "El bloque del tipo %u está mal formado\n" #: src/dns/dnsparser.c:257 #, c-format msgid "Failed to convert DNS IDNA name `%s' to UTF-8: %s\n" msgstr "" "Se produjo un fallo al convertir el nombre en formato DNS IDNA «%s» a UTF-8: " "%s\n" #: src/dns/dnsparser.c:856 #, c-format msgid "Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n" msgstr "" "Se produjo un fallo al convertir el nombre en UTF-8 «%s» al formato DNS " "IDNA: %s\n" #: src/dns/dnsstub.c:175 #, c-format msgid "Could not bind to any port: %s\n" msgstr "No se pudo asociar con ningún puerto: %s\n" #: src/dns/dnsstub.c:295 src/dns/dnsstub.c:383 #, c-format msgid "Failed to send DNS request to %s\n" msgstr "Se produjo un fallo al mandar la petición DNS a %s\n" #: src/dns/dnsstub.c:299 #, c-format msgid "Sent DNS request to %s\n" msgstr "Petición DNS enviada a %s\n" #: src/dns/dnsstub.c:368 #, c-format msgid "Configured DNS exit `%s' is not working / valid.\n" msgstr "La salida DNS configurada «%s» no funciona o no es válida.\n" #: src/dns/dnsstub.c:440 #, c-format msgid "Received DNS response that is too small (%u bytes)" msgstr "Recibida respuesta DNS demasiado pequeña (%u bytes)" #: src/dns/gnunet-dns-monitor.c:355 msgid "only monitor DNS queries" msgstr "sólo monitorizar consultas DNS" #: src/dns/gnunet-dns-monitor.c:358 msgid "only monitor DNS replies" msgstr "sólo monitorizar respuestas DNS" #: src/dns/gnunet-dns-monitor.c:369 msgid "Monitor DNS queries." msgstr "Monitorizar consultas DNS." #: src/dns/gnunet-dns-redirector.c:236 msgid "set A records" msgstr "establece registros de clase A" #: src/dns/gnunet-dns-redirector.c:239 msgid "set AAAA records" msgstr "establece registros de clase AAAA" #: src/dns/gnunet-dns-redirector.c:251 msgid "Change DNS replies to point elsewhere." msgstr "Cambiar las respuestas DNS apuntando a cualquier otro lado." #: src/dns/gnunet-service-dns.c:456 msgid "# DNS requests answered via TUN interface" msgstr "# Peticiones DNS contestadas vía interfaz TUN" #: src/dns/gnunet-service-dns.c:603 msgid "# DNS exit failed (failed to open socket)" msgstr "# Salidas DNS fallidas (se produjo un fallo al abrir el «socket»)" #: src/dns/gnunet-service-dns.c:714 msgid "# External DNS response discarded (no matching request)" msgstr "# Respuestas DNS externas descartadas (ninguna petición coincidente)" #: src/dns/gnunet-service-dns.c:792 msgid "# Client response discarded (no matching request)" msgstr "# Respuestas de cliente descartadas (ninguna petición coincidente)" #: src/dns/gnunet-service-dns.c:907 msgid "Received malformed IPv4-UDP packet on TUN interface.\n" msgstr "Recibido paquete UDP IPv4 mal formado en interfaz TUN.\n" #: src/dns/gnunet-service-dns.c:923 msgid "Received malformed IPv6-UDP packet on TUN interface.\n" msgstr "Recibido paquete UDP IPv6 mal formado en interfaz TUN.\n" #: src/dns/gnunet-service-dns.c:932 #, c-format msgid "Got non-IP packet with %u bytes and protocol %u from TUN\n" msgstr "Se obtuvo un paquete no-IP con %u bytes y protocolo %u de TUN\n" #: src/dns/gnunet-service-dns.c:942 msgid "# Non-DNS UDP packet received via TUN interface" msgstr "# Paquetes UDP no-DNS recibidos vía interfaz TUN" #: src/dns/gnunet-service-dns.c:1009 msgid "# DNS requests received via TUN interface" msgstr "# Peticiones DNS recibidas vía interfaz TUN" #: src/dns/gnunet-service-dns.c:1049 src/exit/gnunet-daemon-exit.c:3514 #, c-format msgid "`%s' must be installed SUID, refusing to run\n" msgstr "«%s» debe ser instalado con SUID, se niega a arrancar\n" #: src/dns/gnunet-service-dns.c:1069 src/exit/gnunet-daemon-exit.c:3571 msgid "need a valid IPv4 or IPv6 address\n" msgstr "se necesita una dirección IPv4 o IPv6 válida\n" #: src/dv/gnunet-dv.c:169 msgid "verbose output" msgstr "" #: src/dv/gnunet-dv.c:178 #, fuzzy msgid "Print information about DV state" msgstr "Imprime información acerca del estado del ATS" #: src/exit/gnunet-daemon-exit.c:802 #, c-format msgid "Got duplicate service records for `%s:%u'\n" msgstr "Hay registros de servicios duplicados para «%s:%u»\n" #: src/exit/gnunet-daemon-exit.c:853 #, fuzzy msgid "# Bytes transmitted via mesh channels" msgstr "# Bytes transmitidos vía túneles MESH" #: src/exit/gnunet-daemon-exit.c:970 src/exit/gnunet-daemon-exit.c:2397 #: src/exit/gnunet-daemon-exit.c:2654 src/vpn/gnunet-service-vpn.c:1407 #: src/vpn/gnunet-service-vpn.c:1797 src/vpn/gnunet-service-vpn.c:1960 msgid "# ICMPv4 packets dropped (type not allowed)" msgstr "# Paquetes ICMPv4 omitidos (tipo no permitido)" #: src/exit/gnunet-daemon-exit.c:1007 src/exit/gnunet-daemon-exit.c:2456 #: src/exit/gnunet-daemon-exit.c:2713 src/vpn/gnunet-service-vpn.c:1463 #: src/vpn/gnunet-service-vpn.c:1856 src/vpn/gnunet-service-vpn.c:1993 msgid "# ICMPv6 packets dropped (type not allowed)" msgstr "# Paquetes ICMPv6 omitidos (tipo no permitido)" #: src/exit/gnunet-daemon-exit.c:1047 msgid "# ICMP packets dropped (not allowed)" msgstr "# Paquetes ICMP omitidos (tipo no permitido)" #: src/exit/gnunet-daemon-exit.c:1054 msgid "ICMP Packet dropped, have no matching connection information\n" msgstr "Paquete ICMP omitido, no hay información de conexiones coincidente\n" #: src/exit/gnunet-daemon-exit.c:1130 msgid "UDP Packet dropped, have no matching connection information\n" msgstr "Paquete UDP omitido, no hay información de conexiones coincidente\n" #: src/exit/gnunet-daemon-exit.c:1204 msgid "TCP Packet dropped, have no matching connection information\n" msgstr "Paquete TCP omitido, no hay información de conexiones coincidente\n" #: src/exit/gnunet-daemon-exit.c:1256 msgid "# Packets received from TUN" msgstr "# Paquetes recibidos de TUN" #: src/exit/gnunet-daemon-exit.c:1270 msgid "# Bytes received from TUN" msgstr "# Bytes recibidos de TUN" #: src/exit/gnunet-daemon-exit.c:1296 msgid "IPv4 packet options received. Ignored.\n" msgstr "Opciones de paquete IPv4 recibidas. Ignoradas.\n" #: src/exit/gnunet-daemon-exit.c:1323 #, c-format msgid "IPv4 packet with unsupported next header %u received. Ignored.\n" msgstr "" "Recibido paquete IPv4 con cabecera «next» no soportada %u. Ignorado.\n" #: src/exit/gnunet-daemon-exit.c:1369 #, c-format msgid "IPv6 packet with unsupported next header %d received. Ignored.\n" msgstr "" "Recibido paquete IPv6 con cabecera «next» no soportada %d. Ignorado.\n" #: src/exit/gnunet-daemon-exit.c:1377 #, c-format msgid "Packet from unknown protocol %u received. Ignored.\n" msgstr "Recibido paquete de protocolo desconocido %u. Ignorado.\n" #: src/exit/gnunet-daemon-exit.c:1759 msgid "# TCP packets sent via TUN" msgstr "# Paquetes TCP enviados vía TUN" #: src/exit/gnunet-daemon-exit.c:1872 msgid "# TCP service creation requests received via mesh" msgstr "# Peticiones de creaciones de servicio TCP recibidas vía mesh" #: src/exit/gnunet-daemon-exit.c:1875 src/exit/gnunet-daemon-exit.c:1968 #: src/exit/gnunet-daemon-exit.c:2073 src/exit/gnunet-daemon-exit.c:2321 #: src/exit/gnunet-daemon-exit.c:2570 src/exit/gnunet-daemon-exit.c:2859 #: src/exit/gnunet-daemon-exit.c:2966 msgid "# Bytes received from MESH" msgstr "# Bytes recibidos de MESH" #: src/exit/gnunet-daemon-exit.c:1909 src/exit/gnunet-daemon-exit.c:2990 #, fuzzy, c-format msgid "No service %s found for %s on port %d!\n" msgstr "¡Ningún servicio encontrado para %s en el puerto %d!\n" #: src/exit/gnunet-daemon-exit.c:1914 msgid "# TCP requests dropped (no such service)" msgstr "# Peticiones TCP omitidas (no existe tal servicio)" #: src/exit/gnunet-daemon-exit.c:1971 msgid "# TCP IP-exit creation requests received via mesh" msgstr "# Peticiones de creación de salida IP por TCP recibidas vía mesh" #: src/exit/gnunet-daemon-exit.c:2076 msgid "# TCP data requests received via mesh" msgstr "# Peticiones de datos TCP recibidas vía mesh" #: src/exit/gnunet-daemon-exit.c:2090 msgid "# TCP DATA requests dropped (no session)" msgstr "# Peticiones de datos (DATA) TCP omitidas (no hay sesión)" #: src/exit/gnunet-daemon-exit.c:2150 msgid "# ICMP packets sent via TUN" msgstr "# Paquetes ICMP enviados vía TUN" #: src/exit/gnunet-daemon-exit.c:2324 msgid "# ICMP IP-exit requests received via mesh" msgstr "# Peticiones de salida IP por ICMP recibidas vía mesh" #: src/exit/gnunet-daemon-exit.c:2573 msgid "# ICMP service requests received via mesh" msgstr "# Peticiones de servicio ICMP recibidas vía mesh" #: src/exit/gnunet-daemon-exit.c:2639 src/vpn/gnunet-service-vpn.c:1397 #: src/vpn/gnunet-service-vpn.c:1954 msgid "# ICMPv4 packets dropped (impossible PT to v6)" msgstr "# Paquetes ICMPv4 omitidos (imposible atravesar v6)" #: src/exit/gnunet-daemon-exit.c:2698 src/vpn/gnunet-service-vpn.c:1433 #: src/vpn/gnunet-service-vpn.c:1445 src/vpn/gnunet-service-vpn.c:1844 msgid "# ICMPv6 packets dropped (impossible PT to v4)" msgstr "# Paquetes ICMPv6 omitidos (imposible atravesar v4)" #: src/exit/gnunet-daemon-exit.c:2748 msgid "# UDP packets sent via TUN" msgstr "# Paquetes UDP enviados vía TUN" #: src/exit/gnunet-daemon-exit.c:2862 msgid "# UDP IP-exit requests received via mesh" msgstr "# Peticiones de salida IP por UDP recibidas vía mesh" #: src/exit/gnunet-daemon-exit.c:2969 msgid "# UDP service requests received via mesh" msgstr "# Peticiones de servicio UDP recibidas vía mesh" #: src/exit/gnunet-daemon-exit.c:2995 msgid "# UDP requests dropped (no such service)" msgstr "# Peticiones UDP omitidas (no existe tal servicio)" #: src/exit/gnunet-daemon-exit.c:3031 #, fuzzy msgid "# Inbound MESH channels created" msgstr "# Túneles interiores MESH creados" #: src/exit/gnunet-daemon-exit.c:3235 src/exit/gnunet-daemon-exit.c:3245 #, fuzzy, c-format msgid "Option `%s' for domain `%s' is not formatted correctly!\n" msgstr "Las opción «%s» o «%s» es necesaria.\n" #: src/exit/gnunet-daemon-exit.c:3259 src/exit/gnunet-daemon-exit.c:3267 #, c-format msgid "`%s' is not a valid port number (for domain `%s')!" msgstr "" #: src/exit/gnunet-daemon-exit.c:3300 #, c-format msgid "No addresses found for hostname `%s' of service `%s'!\n" msgstr "" "¡No se encontraron direcciones para el nombre de máquina «%s» del servicio " "«%s»!\n" #: src/exit/gnunet-daemon-exit.c:3314 src/exit/gnunet-daemon-exit.c:3326 #, c-format msgid "Service `%s' configured for IPv4, but IPv4 is disabled!\n" msgstr "¡Servicio «%s» configurado para IPv4, pero IPv4 está deshabilitado!\n" #: src/exit/gnunet-daemon-exit.c:3337 #, c-format msgid "No IP addresses found for hostname `%s' of service `%s'!\n" msgstr "" "¡No se encontraron direcciones IP para el nombre de máquina «%s» del " "servicio «%s»!\n" #: src/exit/gnunet-daemon-exit.c:3527 msgid "" "This system does not support IPv4, will disable IPv4 functions despite them " "being enabled in the configuration\n" msgstr "" "Este sistema no soporta IPv4, se deshabilitarán las funciones IPv4 aunque " "estén habilitadas en la configuración\n" #: src/exit/gnunet-daemon-exit.c:3535 msgid "" "This system does not support IPv6, will disable IPv6 functions despite them " "being enabled in the configuration\n" msgstr "" "Este sistema no soporta IPv6, se deshabilitarán las funciones IPv6 aunque " "estén habilitadas en la configuración\n" #: src/exit/gnunet-daemon-exit.c:3542 msgid "" "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use " "ENABLE_IPv4=YES\n" msgstr "" "No se puede habilitar salida IPv4 pero se deshabilita IPv4 sobre interfaz " "TUN, se usará ENABLE_IPv4=YES\n" #: src/exit/gnunet-daemon-exit.c:3548 msgid "" "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use " "ENABLE_IPv6=YES\n" msgstr "" "No se pudo habilitar la salida IPv6 pero se deshabilita IPv6 sobre interfaz " "TUN, se usará ENABLE_IPv6=YES\n" #: src/exit/gnunet-daemon-exit.c:3554 src/exit/gnunet-daemon-exit.c:3717 #: src/pt/gnunet-daemon-pt.c:1247 msgid "No useful service enabled. Exiting.\n" msgstr "Ningún servicio útil habilitado. Saliendo.\n" #: src/exit/gnunet-daemon-exit.c:3664 msgid "Must be a number" msgstr "" #: src/exit/gnunet-daemon-exit.c:3813 msgid "Daemon to run to provide an IP exit node for the VPN" msgstr "Demonio a ejecutar para obtener un nodo de salida IP para la VPN" #: src/experimentation/gnunet-daemon-experimentation.c:55 msgid "Experimentation daemon shutting down ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:77 msgid "Experimentation daemon starting ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:83 #, fuzzy msgid "Failed to create statistics!\n" msgstr "Se produjo un fallo al crear los índices\n" #: src/experimentation/gnunet-daemon-experimentation.c:120 msgid "GNUnet experimentation daemon" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:241 #, c-format msgid "Experiment `%s': Experiment signature is invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:250 #, c-format msgid "" "Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu " "sec. \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:303 #, c-format msgid "Experiment `%s': Issuer missing\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:312 #, c-format msgid "Experiment `%s': Issuer invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:320 #, c-format msgid "Experiment `%s': Issuer not accepted!\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:330 #, c-format msgid "Experiment `%s': Version missing or invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:339 #, c-format msgid "Experiment `%s': Required capabilities missing \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:345 #, c-format msgid "Experiment `%s': Required capabilities invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:390 #, fuzzy, c-format msgid "Failed to parse file `%s'\n" msgstr "Se produjo un fallo al procesar «HELLO» en el fichero «%s»\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:420 #: src/experimentation/gnunet-daemon-experimentation_experiments.c:452 msgid "" "No valid experiment issuers configured! Set value to public keys of issuers! " "Exiting.\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:435 #, fuzzy msgid "Invalid value for public key\n" msgstr "Parámetro no válido «%s»\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:473 #, fuzzy, c-format msgid "Cannot read experiments file `%s'\n" msgstr "No se pudo leer la lista de amigos «%s»\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:221 #, c-format msgid "Cannot send message to peer `%s' for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:309 #, c-format msgid "Sending experimentation request to peer %s\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:453 #, c-format msgid "Added peer `%s' as active node\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:891 #, fuzzy, c-format msgid "Connected to peer %s\n" msgstr "Conectado a %s.\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:921 #, fuzzy, c-format msgid "Disconnected from peer %s\n" msgstr "Desconectado de %s\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:1104 #, fuzzy msgid "Failed to connect to CORE service!\n" msgstr "¡Se produjo un fallo al conectar con el servicio DHT!\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:108 #, c-format msgid "Peer `%s' did not respond to request for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:143 #, fuzzy, c-format msgid "Starting inbound experiment `%s' with peer `%s'\n" msgstr "Iniciando el servicio %s para el par «%4s»\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:276 #, fuzzy, c-format msgid "Starting outbound experiment `%s' with peer `%s'\n" msgstr "Iniciando el servicio %s para el par «%4s»\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:294 #, fuzzy, c-format msgid "Received %s message from peer %s for experiment `%s'\n" msgstr "Recibido último mensaje para %s\n" #: src/fragmentation/defragmentation.c:270 msgid "# acknowledgements sent for fragment" msgstr "# reconocimientos enviados por framentos" #: src/fragmentation/defragmentation.c:456 msgid "# fragments received" msgstr "# fragmentos recibidos" #: src/fragmentation/defragmentation.c:521 msgid "# duplicate fragments received" msgstr "# fragmentos duplicados recibidos" #: src/fragmentation/defragmentation.c:534 msgid "# messages defragmented" msgstr "# mensajes defragmentados" #: src/fragmentation/fragmentation.c:208 msgid "# fragments transmitted" msgstr "# fragmentos transmitidos" #: src/fragmentation/fragmentation.c:211 msgid "# fragments retransmitted" msgstr "# fragmentos retransmitidos" #: src/fragmentation/fragmentation.c:237 msgid "# fragments wrap arounds" msgstr "# encajes de fragmentos" #: src/fragmentation/fragmentation.c:281 msgid "# messages fragmented" msgstr "# mensajes fragmentados" #: src/fragmentation/fragmentation.c:284 msgid "# total size of fragmented messages" msgstr "# tamaño total de los mensajes fragmentados" #: src/fragmentation/fragmentation.c:405 msgid "# fragment acknowledgements received" msgstr "# reconocimientos de fragmentos recibidos" #: src/fragmentation/fragmentation.c:411 msgid "# bits removed from fragmentation ACKs" msgstr "# bits eliminados de reconocimientos de fragmentos" #: src/fragmentation/fragmentation.c:435 msgid "# fragmentation transmissions completed" msgstr "# transmisiones de fragmentos completadas" #: src/fs/fs_api.c:465 #, c-format msgid "Could not open file `%s': %s" msgstr "No se pudo abrir el fichero «%s»: %s" #: src/fs/fs_api.c:474 #, c-format msgid "Could not read file `%s': %s" msgstr "No se pudo leer el fichero «%s»: %s" # Short read?? #: src/fs/fs_api.c:480 #, c-format msgid "Short read reading from file `%s'!" msgstr "¡Lectura corta leyendo del fichero «%s»!" #: src/fs/fs_api.c:1066 #, c-format msgid "Failed to resume publishing information `%s': %s\n" msgstr "Se produjo un fallo al retomar la operación de publicación «%s»: %s\n" #: src/fs/fs_api.c:1571 #, c-format msgid "Failure while resuming publishing operation `%s': %s\n" msgstr "Fallo mientras se reiniciaba la operación de publicación «%s»: %s\n" #: src/fs/fs_api.c:1585 #, c-format msgid "Failed to resume publishing operation `%s': %s\n" msgstr "Se produjo un fallo al retomar la operación de publicación «%s»: %s\n" #: src/fs/fs_api.c:2242 #, c-format msgid "Failure while resuming unindexing operation `%s': %s\n" msgstr "" "Se produjo un fallo mientras se retomaba la operación de publicación «%s»: " "%s\n" #: src/fs/fs_api.c:2252 #, c-format msgid "Failed to resume unindexing operation `%s': %s\n" msgstr "Se produjo un fallo al retomar la operación de desindexado «%s»: %s\n" #: src/fs/fs_api.c:2378 src/fs/fs_api.c:2619 #, c-format msgid "Failed to resume sub-download `%s': %s\n" msgstr "Se produjo un fallo al retomar la sub-descarga «%s»: %s\n" #: src/fs/fs_api.c:2395 #, c-format msgid "Failed to resume sub-search `%s': %s\n" msgstr "Se produjo un fallo al retomar la sub-búsqueda «%s»: %s\n" #: src/fs/fs_api.c:2409 src/fs/fs_api.c:2428 src/fs/fs_api.c:2911 #, c-format msgid "Failure while resuming search operation `%s': %s\n" msgstr "" "Se produjo un fallo mientras se retomaba la operación de búsqueda «%s»: %s\n" #: src/fs/fs_api.c:2610 #, c-format msgid "Failed to resume sub-download `%s': could not open file `%s'\n" msgstr "" "Se produjo un fallo al retomar la sub-descarga «%s»: no se pudo abrir el " "fichero «%s»\n" #: src/fs/fs_api.c:2855 msgid "Could not resume running search, will resume as paused search\n" msgstr "" "No se pudo retomar la búsqueda en ejecución, se retomará como una búsqueda " "en pausa\n" #: src/fs/fs_api.c:2949 #, c-format msgid "Failure while resuming download operation `%s': %s\n" msgstr "" "Se produjo un fallo mientras se retomaba de la operación de descarga «%s»: " "%s\n" #: src/fs/fs_directory.c:208 msgid "MAGIC mismatch. This is not a GNUnet directory.\n" msgstr "No hay coincidencia con «MAGIC». Esto no es un directorio GNUnet.\n" #: src/fs/fs_download.c:322 msgid "" "Recursive downloads of directories larger than 4 GB are not supported on 32-" "bit systems\n" msgstr "" "Las descargas recursivas de directorios mayores de 4GB no están soportadas " "en sistemas de 32 bits\n" #: src/fs/fs_download.c:342 msgid "Directory too large for system address space\n" msgstr "" "Directorio demasiado grande para el espacio de direccionamiento del sistema\n" #: src/fs/fs_download.c:523 src/fs/fs_download.c:535 #, c-format msgid "Failed to open file `%s' for writing" msgstr "Se produjo un fallo al abrir «%s» para escritura" #: src/fs/fs_download.c:905 #, c-format msgid "Failed to create directory for recursive download of `%s'\n" msgstr "" "Se produjo un fallo al crear el directorio para la descarga recursiva de " "«%s»\n" #: src/fs/fs_download.c:987 #, c-format msgid "" "Internal error or bogus download URI (expected %u bytes at depth %u and " "offset %llu/%llu, got %u bytes)" msgstr "" "Error interno o URI de descarga defectuosa (se esperaban %u bytes a " "profundidad %u y desplazamiento %llu/%llu, se obtuvieron %u bytes)" #: src/fs/fs_download.c:1013 msgid "internal error decrypting content" msgstr "error interno descifrando el contenido" #: src/fs/fs_download.c:1036 #, c-format msgid "Download failed: could not open file `%s': %s" msgstr "Descarga fallida: no se pudo abrir el fichero «%s»: %s" #: src/fs/fs_download.c:1046 #, c-format msgid "Failed to seek to offset %llu in file `%s': %s" msgstr "" "Se produjo un fallo al buscar en el desplazamiento %llu del fichero «%s»: %s" #: src/fs/fs_download.c:1055 #, c-format msgid "Failed to write block of %u bytes at offset %llu in file `%s': %s" msgstr "" "Se produjo un fallo al escribir el bloque de %u bytes en el desplazamiento " "%llu del fichero «%s»: %s" #: src/fs/fs_download.c:1153 msgid "internal error decoding tree" msgstr "error interno decodificando árbol" #: src/fs/fs_download.c:1944 msgid "Invalid URI" msgstr "URI no válida" #: src/fs/fs_getopt.c:192 #, c-format msgid "" "Unknown metadata type in metadata option `%s'. Using metadata type " "`unknown' instead.\n" msgstr "" "Tipo de metadatos desconocido en la opción de metadatos «%s». Usando el " "tipo de metadatos desconocido (unknown) en su lugar.\n" # Miguel: "Failed to receive (valid) response" no lo he traducido # "por se produjo un fallo al recibir una respuesta", sino # como "no se ha recibido una respuesta" puesto que es # más claro. #: src/fs/fs_list_indexed.c:90 #, c-format msgid "Failed to receive response for `%s' request from `%s' service.\n" msgstr "" "No se ha recibido la respuesta para la petición «%s» del servicio «%s».\n" #: src/fs/fs_list_indexed.c:113 #, c-format msgid "Failed to receive valid response for `%s' request from `%s' service.\n" msgstr "" "No se ha recibido una respuesta válida para la petición «%s» del servicio " "«%s».\n" #: src/fs/fs_list_indexed.c:151 #, c-format msgid "Failed to not connect to `%s' service.\n" msgstr "Se produjo un fallo al conectar con el servicio «%s».\n" #: src/fs/fs_misc.c:126 #, c-format msgid "Did not find mime type `%s' in extension list.\n" msgstr "No se encontró el tipo MIME «%s» en la lista de extensiones.\n" #: src/fs/fs_namespace.c:207 #, c-format msgid "Failed to open `%s' for writing: %s\n" msgstr "Se produjo un fallo al abrir «%s» para escritura: %s\n" #: src/fs/fs_namespace.c:229 #, c-format msgid "Failed to write `%s': %s\n" msgstr "Se produjo un fallo al escribir «%s»: %s\n" #: src/fs/fs_namespace.c:320 #, fuzzy, c-format msgid "Failed to read `%s': %s\n" msgstr "Se produjo un fallo al escribir «%s»: %s\n" #: src/fs/fs_namespace.c:466 msgid "Failed to connect to datastore." msgstr "Se produjo un fallo al conectar con el almacén de datos." #: src/fs/fs_publish.c:125 src/fs/fs_publish.c:415 #, c-format msgid "Publishing failed: %s" msgstr "Publicación fallida: %s" #: src/fs/fs_publish.c:667 src/fs/fs_publish.c:684 src/fs/fs_publish.c:723 #: src/fs/fs_publish.c:744 src/fs/fs_publish.c:768 src/fs/fs_publish.c:914 #, c-format msgid "Can not index file `%s': %s. Will try to insert instead.\n" msgstr "No se pudo indexar el fichero «%s»: %s. Se intentará insertar.\n" #: src/fs/fs_publish.c:669 msgid "timeout on index-start request to `fs' service" msgstr "" "expiración del plazo en la petición de inicio de indexado (index-start) al " "servicio «fs»" #: src/fs/fs_publish.c:681 msgid "unknown error" msgstr "error desconocido" #: src/fs/fs_publish.c:725 msgid "failed to compute hash" msgstr "se produjo un fallo al calcular el hash" #: src/fs/fs_publish.c:745 msgid "filename too long" msgstr "nombre de fichero demasiado largo" #: src/fs/fs_publish.c:770 msgid "could not connect to `fs' service" msgstr "no se pudo conectar con el servicio «fs»" #: src/fs/fs_publish.c:793 #, c-format msgid "Failed to get file identifiers for `%s'\n" msgstr "" "Se produjo un fallo al obtener los identificadores de fichero para «%s»\n" #: src/fs/fs_publish.c:862 #, c-format msgid "Recursive upload failed at `%s': %s" msgstr "La subida recursiva falló en «%s»: %s" #: src/fs/fs_publish.c:868 #, c-format msgid "Recursive upload failed: %s" msgstr "Subida recursiva fallida: %s" #: src/fs/fs_publish.c:915 msgid "needs to be an actual file" msgstr "tiene que ser un fichero de verdad" #: src/fs/fs_publish.c:1151 #, c-format msgid "Insufficient space for publishing: %s" msgstr "Espacio insuficiente para publicar: %s" #: src/fs/fs_publish.c:1243 #, c-format msgid "Reserving space for %u entries and %llu bytes for publication\n" msgstr "Reservando espacio para %u entradas y %llu bytes para publicación\n" #: src/fs/fs_publish_ksk.c:219 msgid "Could not connect to datastore." msgstr "No se pudo conectar con el almacén de datos." #: src/fs/fs_publish_ublock.c:219 msgid "Internal error." msgstr "Error interno." #: src/fs/fs_search.c:813 #, fuzzy, c-format msgid "Failed to parse URI `%s': %s\n" msgstr "Se produjo un fallo al procesar la URI: %s\n" #: src/fs/fs_search.c:872 #, c-format msgid "Got result with unknown block type `%d', ignoring" msgstr "" "Se obtuvo un resultado con un tipo desconocido de bloque «%d», ignorándolo" #: src/fs/fs_unindex.c:59 msgid "Failed to find given position in file" msgstr "Se produjo un fallo al buscar la posición dada en el fichero" #: src/fs/fs_unindex.c:64 msgid "Failed to read file" msgstr "No se pudo leer el fichero" #: src/fs/fs_unindex.c:234 msgid "Unexpected time for a response from `fs' service." msgstr "Tiempo inesperado para una respuesta del servicio «fs»." #: src/fs/fs_unindex.c:242 msgid "Timeout waiting for `fs' service." msgstr "Esperando al servicio «fs»." #: src/fs/fs_unindex.c:250 msgid "Invalid response from `fs' service." msgstr "Respuesta no válida del servicio «fs»." #: src/fs/fs_unindex.c:291 msgid "Failed to connect to FS service for unindexing." msgstr "" "Se produjo un fallo al conectar con el servicio «FS» para el desindexado." #: src/fs/fs_unindex.c:347 src/fs/fs_unindex.c:359 msgid "Failed to get KSKs from directory scan." msgstr "Se produjo un fallo al obtener KSKs de la búsqueda de directorios." #: src/fs/fs_unindex.c:355 #, c-format msgid "Internal error scanning `%s'.\n" msgstr "Error interno escaneando «%s».\n" #: src/fs/fs_unindex.c:414 #, fuzzy, c-format msgid "Failed to remove UBlock: %s\n" msgstr "Se produjo un fallo al eliminar el KBlock: %s\n" #: src/fs/fs_unindex.c:562 src/fs/fs_unindex.c:626 msgid "Failed to connect to `datastore' service." msgstr "" "Se produjo un fallo al conectar con el servicio de almacenamiento de datos " "(datastore)." #: src/fs/fs_unindex.c:639 msgid "Failed to open file for unindexing." msgstr "Se produjo un fallo al abrir el fichero para desindexado." #: src/fs/fs_unindex.c:673 msgid "Failed to compute hash of file." msgstr "Se produjo un fallo al calcular el hash del fichero." # Cadena erronea, corregida en SVN. #: src/fs/fs_uri.c:222 #, no-c-format msgid "`%' must be followed by HEX number" msgstr "'%' debe ser seguido por un número hexadecimal" #: src/fs/fs_uri.c:281 msgid "Malformed KSK URI (must not begin or end with `+')" msgstr "URI KSK mal formada (no debe empezar ni terminar con «+»)" #: src/fs/fs_uri.c:299 msgid "`++' not allowed in KSK URI" msgstr "«++» no permitido en URI KSK" #: src/fs/fs_uri.c:306 msgid "Quotes not balanced in KSK URI" msgstr "Comillas no cerradas en URI KSK" #: src/fs/fs_uri.c:376 msgid "Malformed SKS URI" msgstr "URI SKS mal formada" #: src/fs/fs_uri.c:419 src/fs/fs_uri.c:434 msgid "Malformed CHK URI" msgstr "URI CHK mal formada" #: src/fs/fs_uri.c:512 src/fs/fs_uri.c:580 msgid "SKS URI malformed" msgstr "URI SKS mal formada" #: src/fs/fs_uri.c:527 src/fs/fs_uri.c:537 #, fuzzy msgid "LOC URI malformed" msgstr "URI SKS mal formada" #: src/fs/fs_uri.c:545 src/fs/fs_uri.c:553 #, fuzzy msgid "LOC URI malformed (could not decode public key)" msgstr "URI SKS mal formada (no se pudo decodificar la clave pública)" #: src/fs/fs_uri.c:559 msgid "SKS URI malformed (could not find signature)" msgstr "URI SKS mal formada (no se pudo encontrar la firma)" #: src/fs/fs_uri.c:565 src/fs/fs_uri.c:574 msgid "SKS URI malformed (could not decode signature)" msgstr "URI SKS mal formada (no se pudo decodificar la firma)" #: src/fs/fs_uri.c:586 msgid "SKS URI malformed (could not parse expiration time)" msgstr "URI SKS mal formada (no se encuentra el tiempo de expiración)" #: src/fs/fs_uri.c:598 msgid "SKS URI malformed (signature failed validation)" msgstr "URI SKS mal formada (se produjo un fallo al validar la firma)" #: src/fs/fs_uri.c:636 msgid "Unrecognized URI type" msgstr "Tipo de URI no reconocido" #: src/fs/fs_uri.c:860 msgid "Lacking key configuration settings.\n" msgstr "Falta configuración sobre las opciones de claves.\n" #: src/fs/fs_uri.c:866 #, c-format msgid "Could not access hostkey file `%s'.\n" msgstr "No se pudo acceder al fichero de clave de máquina «%s».\n" #: src/fs/fs_uri.c:1050 src/fs/fs_uri.c:1077 msgid "No keywords specified!\n" msgstr "¡Ninguna palabra clave especificada!\n" #: src/fs/fs_uri.c:1083 msgid "Number of double-quotes not balanced!\n" msgstr "¡Número de comillas dobles no balanceado!\n" #: src/fs/gnunet-auto-share.c:236 #, c-format msgid "Failed to load state: %s\n" msgstr "Se produjo un fallo al cargar el estado: %s\n" #: src/fs/gnunet-auto-share.c:289 src/fs/gnunet-auto-share.c:299 #: src/fs/gnunet-auto-share.c:309 #, c-format msgid "Failed to save state to file %s\n" msgstr "Se produjo un fallo al guardar el estado en el fichero %s\n" #: src/fs/gnunet-auto-share.c:401 #, c-format msgid "Publication of `%s' done\n" msgstr "Publicación de «%s» finalizada\n" #: src/fs/gnunet-auto-share.c:488 #, c-format msgid "Publishing `%s'\n" msgstr "Publicando «%s»\n" #: src/fs/gnunet-auto-share.c:497 #, c-format msgid "Failed to run `%s'\n" msgstr "Se produjo un fallo al ejecutar «%s»\n" #: src/fs/gnunet-auto-share.c:686 #, c-format msgid "" "You must specify one and only one directory name for automatic publication.\n" msgstr "" "Debes especificar uno y solo un nombre de directorio para publicación " "automática.\n" #: src/fs/gnunet-auto-share.c:737 src/fs/gnunet-publish.c:824 msgid "set the desired LEVEL of sender-anonymity" msgstr "establece el nivel LEVEL deseado de anonimato del emisor" #: src/fs/gnunet-auto-share.c:741 src/fs/gnunet-publish.c:828 msgid "disable adding the creation time to the metadata of the uploaded file" msgstr "" "deshabilitar añadir tiempo de creación a los metadatos del fichero subido" #: src/fs/gnunet-auto-share.c:744 src/fs/gnunet-publish.c:831 msgid "do not use libextractor to add keywords or metadata" msgstr "no usar libextractor para añadir palabras clave o metadatos" #: src/fs/gnunet-auto-share.c:747 src/fs/gnunet-publish.c:855 msgid "specify the priority of the content" msgstr "especificar la prioridad del contenido" #: src/fs/gnunet-auto-share.c:750 src/fs/gnunet-publish.c:862 msgid "set the desired replication LEVEL" msgstr "establece el nivel LEVEL deseado de replicación" #: src/fs/gnunet-auto-share.c:770 msgid "Automatically publish files from a directory on GNUnet" msgstr "Publicar automáticamente ficheros de un directorio en GNUnet" #: src/fs/gnunet-daemon-fsprofiler.c:660 msgid "Daemon to use file-sharing to measure its performance." msgstr "Demonio para medir el rendimiento de usar compartición de archivos." #: src/fs/gnunet-directory.c:49 #, c-format msgid "\t\n" msgstr "\t\n" #: src/fs/gnunet-directory.c:94 #, c-format msgid "Directory `%s' meta data:\n" msgstr "Metadatos del directorio «%s»:\n" #: src/fs/gnunet-directory.c:97 #, c-format msgid "Directory `%s' contents:\n" msgstr "Contenidos del directorio «%s»:\n" #: src/fs/gnunet-directory.c:132 msgid "You must specify a filename to inspect.\n" msgstr "Debes especificar un fichero a inspeccionar.\n" #: src/fs/gnunet-directory.c:145 #, c-format msgid "Failed to read directory `%s'\n" msgstr "Se produjo un fallo al leer el directorio «%s»\n" #: src/fs/gnunet-directory.c:154 #, c-format msgid "`%s' is not a GNUnet directory\n" msgstr "«%s» no es un directorio GNUnet\n" #: src/fs/gnunet-directory.c:183 msgid "Display contents of a GNUnet directory" msgstr "Muestra los contenidos de un directorio GNUnet" #: src/fs/gnunet-download.c:137 #, c-format msgid "Starting download `%s'.\n" msgstr "Iniciando descarga «%s».\n" #: src/fs/gnunet-download.c:147 msgid "" msgstr "" #: src/fs/gnunet-download.c:157 #, c-format msgid "" "Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to " "download\n" msgstr "" "Descargando «%s» en %llu/%llu (%s restantes, %s/s). El bloque tardó %s en " "descargarse\n" #: src/fs/gnunet-download.c:179 #, c-format msgid "Error downloading: %s.\n" msgstr "Error descargando: %s.\n" #: src/fs/gnunet-download.c:194 #, c-format msgid "Downloading `%s' done (%s/s).\n" msgstr "Finalizada descarga «%s» (%s/s).\n" #: src/fs/gnunet-download.c:209 src/fs/gnunet-publish.c:286 #: src/fs/gnunet-search.c:200 src/fs/gnunet-unindex.c:108 #, c-format msgid "Unexpected status: %d\n" msgstr "Estado inesperado: %d\n" #: src/fs/gnunet-download.c:234 msgid "You need to specify a URI argument.\n" msgstr "Tiene que especificar una URI como parámetro.\n" #: src/fs/gnunet-download.c:240 src/fs/gnunet-publish.c:665 #, c-format msgid "Failed to parse URI: %s\n" msgstr "Se produjo un fallo al procesar la URI: %s\n" #: src/fs/gnunet-download.c:247 msgid "Only CHK or LOC URIs supported.\n" msgstr "Sólo URI «CHK» o «LOC» soportadas.\n" #: src/fs/gnunet-download.c:254 msgid "Target filename must be specified.\n" msgstr "El nombre de fichero de destino debe ser especificado.\n" #: src/fs/gnunet-download.c:268 src/fs/gnunet-publish.c:797 #: src/fs/gnunet-search.c:250 src/fs/gnunet-unindex.c:140 #, c-format msgid "Could not initialize `%s' subsystem.\n" msgstr "No se pudo inicializar el subsistema «%s».\n" #: src/fs/gnunet-download.c:305 src/fs/gnunet-search.c:289 msgid "set the desired LEVEL of receiver-anonymity" msgstr "establece el nivel LEVEL deseado de anonimato del receptor" #: src/fs/gnunet-download.c:308 msgid "delete incomplete downloads (when aborted with CTRL-C)" msgstr "borra descargas incompletas (cuando fueron abortadas con CTRL-C=" #: src/fs/gnunet-download.c:311 src/fs/gnunet-search.c:292 msgid "only search the local peer (no P2P network search)" msgstr "únicamente buscar en el par local (no buscar en la red P2P)" #: src/fs/gnunet-download.c:314 msgid "write the file to FILENAME" msgstr "escribe los datos al nombre del fichero proporcionado (FILENAME)" #: src/fs/gnunet-download.c:318 msgid "set the maximum number of parallel downloads that is allowed" msgstr "establece el número máximo de descargas paralelas permitido" #: src/fs/gnunet-download.c:322 msgid "set the maximum number of parallel requests for blocks that is allowed" msgstr "establece el número máximo de peticiones de bloque paralelas permitido" #: src/fs/gnunet-download.c:325 msgid "download a GNUnet directory recursively" msgstr "descarga un directorio de GNUnet recursivamente" #: src/fs/gnunet-download.c:339 msgid "" "Download files from GNUnet using a GNUnet CHK or LOC URI (gnunet://fs/" "chk/...)" msgstr "" "Descargar ficheros de GNUnet usando una URI GNUnet CHK o LOC (gnunet://fs/" "chk/...)" #: src/fs/gnunet-fs.c:117 msgid "print a list of all indexed files" msgstr "imprimir una lista de todos los ficheros indexados" #: src/fs/gnunet-fs.c:127 msgid "Special file-sharing operations" msgstr "Operaciones especiales de compartición de ficheros" #: src/fs/gnunet-fs-profiler.c:193 msgid "run the experiment with COUNT peers" msgstr "ejecuta el experimento con «COUNT» pares" #: src/fs/gnunet-fs-profiler.c:196 msgid "specifies name of a file with the HOSTS the testbed should use" msgstr "" "especifica el nombre de un fichero con las máquinas (HOSTS) que la batería " "de pruebas debería usar" #: src/fs/gnunet-fs-profiler.c:199 msgid "automatically terminate experiment after DELAY" msgstr "termina el experimento automáticamente despues de «DELAY»" #: src/fs/gnunet-fs-profiler.c:208 msgid "run a testbed to measure file-sharing performance" msgstr "" "ejecuta una batería de pruebas para medir el rendimiento de la compartición " "de ficheros" #: src/fs/gnunet-publish.c:231 src/fs/gnunet-publish.c:243 #, c-format msgid "Publishing `%s' at %llu/%llu (%s remaining)\n" msgstr "Publicando «%s» en %llu/%llu (%s restantes)\n" #: src/fs/gnunet-publish.c:250 #, c-format msgid "Error publishing: %s.\n" msgstr "Error publicando: %s.\n" #: src/fs/gnunet-publish.c:260 #, c-format msgid "Publishing `%s' done.\n" msgstr "Publicación «%s» finalizada.\n" #: src/fs/gnunet-publish.c:264 #, c-format msgid "URI is `%s'.\n" msgstr "La URI es «%s».\n" #: src/fs/gnunet-publish.c:283 msgid "Cleanup after abort complete.\n" msgstr "Limpieza completada\n" #: src/fs/gnunet-publish.c:401 #, c-format msgid "Meta data for file `%s' (%s)\n" msgstr "Metadatos para el fichero «%s» (%s)\n" #: src/fs/gnunet-publish.c:403 #, c-format msgid "Keywords for file `%s' (%s)\n" msgstr "Palabras clave para el fichero «%s» (%s)\n" #: src/fs/gnunet-publish.c:542 msgid "Could not publish\n" msgstr "No se pudo publicar\n" #: src/fs/gnunet-publish.c:565 msgid "Could not start publishing.\n" msgstr "No se pudo empezar a publicar.\n" #: src/fs/gnunet-publish.c:598 #, c-format msgid "Scanning directory `%s'.\n" msgstr "Escaneando directorio «%s».\n" #: src/fs/gnunet-publish.c:600 #, c-format msgid "Scanning file `%s'.\n" msgstr "Escaneando fichero «%s».\n" #: src/fs/gnunet-publish.c:605 #, c-format msgid "There was trouble processing file `%s', skipping it.\n" msgstr "Hubo un problema procesando el fichero «%s», omitiéndolo.\n" #: src/fs/gnunet-publish.c:610 msgid "Preprocessing complete.\n" msgstr "Preprocesado completo.\n" #: src/fs/gnunet-publish.c:614 #, c-format msgid "Extracting meta data from file `%s' complete.\n" msgstr "Extracción de metadatos del fichero «%s» completa.\n" #: src/fs/gnunet-publish.c:618 msgid "Meta data extraction has finished.\n" msgstr "La extracción de metadatos ha finalizado.\n" #: src/fs/gnunet-publish.c:625 msgid "Internal error scanning directory.\n" msgstr "Error interno escaneando directorio.\n" #: src/fs/gnunet-publish.c:656 #, fuzzy, c-format msgid "Selected pseudonym `%s' unknown\n" msgstr "Espacio de nombres «%s» desconocido.\n" #: src/fs/gnunet-publish.c:682 #, c-format msgid "Failed to access `%s': %s\n" msgstr "Se produjo un fallo al acceder «%s»: %s\n" #: src/fs/gnunet-publish.c:695 msgid "" "Failed to start meta directory scanner. Is gnunet-helper-publish-fs " "installed?\n" msgstr "" "Se produjo un fallo al iniciar el meta-escáner de directorios. ¿Está " "«gnunet-helper-publish-fs» instalado?\n" #: src/fs/gnunet-publish.c:747 #, c-format msgid "Cannot extract metadata from a URI!\n" msgstr "¡No se pueden extraer metadatos de una URI!\n" #: src/fs/gnunet-publish.c:754 #, c-format msgid "You must specify one and only one filename for insertion.\n" msgstr "Se debe especificar uno y solo un nombre de fichero para insertar.\n" #: src/fs/gnunet-publish.c:760 #, c-format msgid "You must NOT specify an URI and a filename.\n" msgstr "No se puede especificar una URI y un nombre de fichero.\n" #: src/fs/gnunet-publish.c:768 src/vpn/gnunet-vpn.c:209 #, c-format msgid "Option `%s' is required when using option `%s'.\n" msgstr "La opción «%s» es obligatoria cuando se usa la opción «%s».\n" #: src/fs/gnunet-publish.c:778 src/fs/gnunet-publish.c:785 #: src/transport/gnunet-transport.c:1284 src/transport/gnunet-transport.c:1314 #: src/transport/gnunet-transport.c:1344 #, c-format msgid "Option `%s' makes no sense without option `%s'.\n" msgstr "La opción «%s» no tiene sentido sin la opción «%s».\n" #: src/fs/gnunet-publish.c:835 msgid "" "print list of extracted keywords that would be used, but do not perform " "upload" msgstr "" "imprimir una lista de las palabras clave extraídas que podrían ser usadas, " "pero sin realizar la subida" #: src/fs/gnunet-publish.c:839 msgid "" "add an additional keyword for the top-level file or directory (this option " "can be specified multiple times)" msgstr "" "añadir una palabra clave adicional para el fichero del nivel más alto o el " "directorio (esta opción puede ser especificada varias veces)" #: src/fs/gnunet-publish.c:843 msgid "set the meta-data for the given TYPE to the given VALUE" msgstr "establece los metadatos para el tipo TYPE dado al valor VALUE dado" #: src/fs/gnunet-publish.c:846 msgid "" "do not index, perform full insertion (stores entire file in encrypted form " "in GNUnet database)" msgstr "" "no indexar, hacer inserciones totales (almacena el fichero entero de forma " "cifrada en la base de datos de GNUnet)" #: src/fs/gnunet-publish.c:851 msgid "" "specify ID of an updated version to be published in the future (for " "namespace insertions only)" msgstr "" "especificar la ID de una versión actualizada para ser publicada en el futuro " "(para inserciones en el espacio de nombres únicamente)" #: src/fs/gnunet-publish.c:859 msgid "publish the files under the pseudonym NAME (place file into namespace)" msgstr "" "publicar los ficheros bajo el seudónimo NAME (coloca el fichero en el " "espacio)" #: src/fs/gnunet-publish.c:865 msgid "" "only simulate the process but do not do any actual publishing (useful to " "compute URIs)" msgstr "" "únicamente simular el proceso pero no publicar nada realmente (útil para " "calcular URI)" #: src/fs/gnunet-publish.c:869 msgid "" "set the ID of this version of the publication (for namespace insertions only)" msgstr "" "establece la ID de esta versión de la publicación (para inserciones en el " "espacio únicamente)" #: src/fs/gnunet-publish.c:873 msgid "" "URI to be published (can be used instead of passing a file to add keywords " "to the file with the respective URI)" msgstr "" "URI a ser publicada (puede ser usado en vez de pasar un fichero para añadir " "claves con el fichero con la URI respectiva)" #: src/fs/gnunet-publish.c:889 msgid "Publish a file or directory on GNUnet" msgstr "Publicar un fichero o un directorio en GNUnet" #: src/fs/gnunet-search.c:114 #, c-format msgid "Failed to write directory with search results to `%s'\n" msgstr "" "Se produjo un fallo al escribir el directorio con los resultados de búsqueda " "de «%s»\n" #: src/fs/gnunet-search.c:191 #, c-format msgid "Error searching: %s.\n" msgstr "Error buscando: %s.\n" #: src/fs/gnunet-search.c:240 msgid "Could not create keyword URI from arguments.\n" msgstr "No se pudo crear URI de palabra clave a partir de los parámetros.\n" #: src/fs/gnunet-search.c:264 msgid "Could not start searching.\n" msgstr "No se pudo empezar a buscar.\n" #: src/fs/gnunet-search.c:295 msgid "write search results to file starting with PREFIX" msgstr "escribir resultados de búsqueda al fichero que empiecen por «PREFIX»" #: src/fs/gnunet-search.c:298 msgid "automatically terminate search after DELAY" msgstr "terminar búsqueda automáticamente después de «DELAY»" #: src/fs/gnunet-search.c:305 msgid "automatically terminate search after VALUE results are found" msgstr "terminar búsqueda después de «VALUE» resultados encontrados" #: src/fs/gnunet-search.c:316 msgid "Search GNUnet for files that were published on GNUnet" msgstr "Buscar en GNUnet ficheros que han sido publicados en GNUnet" #: src/fs/gnunet-service-fs.c:271 msgid "# running average P2P latency (ms)" msgstr "# latencia media de P2P en ejecución (ms)" #: src/fs/gnunet-service-fs.c:326 src/fs/gnunet-service-fs.c:539 msgid "# Loopback routes suppressed" msgstr "# Rutas en bucle local eliminadas" #: src/fs/gnunet-service-fs.c:639 src/hostlist/gnunet-daemon-hostlist.c:288 #: src/topology/gnunet-daemon-topology.c:1254 #: src/topology/gnunet-daemon-topology.c:1261 #, c-format msgid "Failed to connect to `%s' service.\n" msgstr "Se produjo un fallo al conectar con el servicio «%s».\n" #: src/fs/gnunet-service-fs_cp.c:682 msgid "# migration stop messages received" msgstr "# mensajes de detención de migración recibidos" #: src/fs/gnunet-service-fs_cp.c:686 #, c-format msgid "Migration of content to peer `%s' blocked for %s\n" msgstr "Migración de contenido al par «%s» bloqueada durante %s\n" #: src/fs/gnunet-service-fs_cp.c:721 msgid "# replies transmitted to other peers" msgstr "# respuestas transmitidas a otros pares" #: src/fs/gnunet-service-fs_cp.c:727 msgid "# replies dropped" msgstr "# respuestas omitidas" #: src/fs/gnunet-service-fs_cp.c:752 src/fs/gnunet-service-fs_cp.c:1301 msgid "# P2P searches active" msgstr "# busquedas P2P activas" #: src/fs/gnunet-service-fs_cp.c:845 msgid "# artificial delays introduced (ms)" msgstr "# retardos artificiales introducidos (ms)" #: src/fs/gnunet-service-fs_cp.c:898 msgid "# replies dropped due to type mismatch" msgstr "# respuestas omitidas debido a incompatibilidad de tipos" #: src/fs/gnunet-service-fs_cp.c:906 msgid "# replies received for other peers" msgstr "# respuestas recibidas de otros pares" #: src/fs/gnunet-service-fs_cp.c:920 msgid "# replies dropped due to insufficient cover traffic" msgstr "# respuestas omitidas debido a insuficiente tráfico de cobertura" #: src/fs/gnunet-service-fs_cp.c:958 msgid "# P2P searches destroyed due to ultimate reply" msgstr "# búsquedas P2P destruidas debido a respuesta definitiva" #: src/fs/gnunet-service-fs_cp.c:1026 msgid "# requests done for free (low load)" msgstr "# peticiones realizadas gratuitamente (baja carga)" #: src/fs/gnunet-service-fs_cp.c:1051 msgid "# request dropped, priority insufficient" msgstr "# peticiones omitidas, prioridad insuficiente" #: src/fs/gnunet-service-fs_cp.c:1061 msgid "# requests done for a price (normal load)" msgstr "# peticiones realizadas por un precio (carga normal)" #: src/fs/gnunet-service-fs_cp.c:1139 msgid "# GET requests received (from other peers)" msgstr "# peticiones «GET» recibidas (de otros pares)" #: src/fs/gnunet-service-fs_cp.c:1173 msgid "# requests dropped due to initiator not being connected" msgstr "# peticiones omitidas debido a que el iniciador no está conectado" #: src/fs/gnunet-service-fs_cp.c:1195 msgid "# requests dropped due to missing reverse route" msgstr "# peticiones omitidas debido a falta de ruta inversa" #: src/fs/gnunet-service-fs_cp.c:1246 msgid "# requests dropped due TTL underflow" msgstr "# peticiones omitidas debido a expiración del TTL" #: src/fs/gnunet-service-fs_cp.c:1270 msgid "# requests dropped due to higher-TTL request" msgstr "# peticiones omitidas debido a una petición de mayor TTL" #: src/fs/gnunet-service-fs_cp.c:1299 msgid "# P2P query messages received and processed" msgstr "# mensajes de búsqueda P2P recibidos y procesados" #: src/fs/gnunet-service-fs_cp.c:1670 msgid "# migration stop messages sent" msgstr "# mensajes de detención de migración enviados" #: src/fs/gnunet-service-fs_indexing.c:130 #: src/fs/gnunet-service-fs_indexing.c:181 #, c-format msgid "Could not open `%s'.\n" msgstr "No se pudo abrir «%s».\n" #: src/fs/gnunet-service-fs_indexing.c:142 #, c-format msgid "Error writing `%s'.\n" msgstr "Error escribiendo «%s».\n" #: src/fs/gnunet-service-fs_indexing.c:237 #, c-format msgid "" "Index request received for file `%s' is already indexed as `%s'. Permitting " "anyway.\n" msgstr "" "La petición de indexado recibida para el fichero «%s» ya está indexada como " "«%s». Se permite de todos modos.\n" #: src/fs/gnunet-service-fs_indexing.c:275 #, c-format msgid "Hash mismatch trying to index file `%s' which has hash `%s'\n" msgstr "" "Hash no asociado intentando indexar el fichero «%s» que tiene hash «%s»\n" #: src/fs/gnunet-service-fs_indexing.c:477 #, c-format msgid "Failed to delete bogus block: %s\n" msgstr "Se produjo un fallo al eliminar el bloque defectuoso: %s\n" #: src/fs/gnunet-service-fs_indexing.c:542 msgid "# index blocks removed: original file inaccessible" msgstr "# bloques de índice eliminados: fichero original inaccesible" #: src/fs/gnunet-service-fs_indexing.c:557 #, c-format msgid "Could not access indexed file `%s' (%s) at offset %llu: %s\n" msgstr "" "No se pudo acceder al fichero indexado «%s» (%s) en el desplazamiento %llu: " "%s\n" #: src/fs/gnunet-service-fs_indexing.c:559 msgid "not indexed" msgstr "no indexado" #: src/fs/gnunet-service-fs_indexing.c:574 #, c-format msgid "Indexed file `%s' changed at offset %llu\n" msgstr "El fichero indexado «%s» ha cambiado en el desplazamiento %llu\n" #: src/fs/gnunet-service-fs_lc.c:202 src/fs/gnunet-service-fs_lc.c:368 msgid "# client searches active" msgstr "# búsquedas de clientes activas" #: src/fs/gnunet-service-fs_lc.c:256 msgid "# replies received for local clients" msgstr "# respuestas recibidas de clientes locales" #: src/fs/gnunet-service-fs_lc.c:327 msgid "# client searches received" msgstr "# búsquedas de clientes recibidas" #: src/fs/gnunet-service-fs_lc.c:362 msgid "# client searches updated (merged content seen list)" msgstr "" "# búsquedas de clientes actualizadas (contenido unido visto en la lista)" #: src/fs/gnunet-service-fs_mesh_client.c:484 #, fuzzy msgid "# replies received via mesh" msgstr "# respuestas recibidas vía «stream»" #: src/fs/gnunet-service-fs_mesh_client.c:498 #, fuzzy msgid "# replies received via mesh dropped" msgstr "# respuestas recibidas omitidas vía «stream»" #: src/fs/gnunet-service-fs_mesh_server.c:260 #, fuzzy msgid "# Blocks transferred via mesh" msgstr "# Bloques transferidos vía «stream»" #: src/fs/gnunet-service-fs_mesh_server.c:352 #, fuzzy msgid "# queries received via mesh not answered" msgstr "# consultas recibidas vía «stream»" #: src/fs/gnunet-service-fs_mesh_server.c:432 #, fuzzy msgid "# queries received via mesh" msgstr "# consultas recibidas vía «stream»" #: src/fs/gnunet-service-fs_mesh_server.c:476 #, fuzzy msgid "# mesh client connections rejected" msgstr "# conexiones de clientes «stream» rechazadas" #: src/fs/gnunet-service-fs_mesh_server.c:482 #: src/fs/gnunet-service-fs_mesh_server.c:522 #, fuzzy msgid "# mesh connections active" msgstr "# conexiones «stream» activas" #: src/fs/gnunet-service-fs_pe.c:269 msgid "# average retransmission delay (ms)" msgstr "# retardo de retransmisión medio (ms)" #: src/fs/gnunet-service-fs_pe.c:400 msgid "# transmission failed (core has no bandwidth)" msgstr "# transmisión fallida (el servicio principal no tiene ancho de banda)" #: src/fs/gnunet-service-fs_pe.c:433 msgid "# query messages sent to other peers" msgstr "# mensajes de búsqueda enviados a otros pares" # ??? #: src/fs/gnunet-service-fs_pe.c:484 #, fuzzy msgid "# delay heap timeout (ms)" msgstr "# plazo del retraso del montículo" #: src/fs/gnunet-service-fs_pe.c:492 msgid "# query plans executed" msgstr "# planes de búsqueda ejecutados" #: src/fs/gnunet-service-fs_pe.c:552 msgid "# requests merged" msgstr "# peticiones unidas" #: src/fs/gnunet-service-fs_pe.c:560 msgid "# requests refreshed" msgstr "# peticiones refrescadas" #: src/fs/gnunet-service-fs_pe.c:616 src/fs/gnunet-service-fs_pe.c:700 #: src/fs/gnunet-service-fs_pe.c:771 msgid "# query plan entries" msgstr "# entradas de planes de búsqueda" #: src/fs/gnunet-service-fs_pr.c:311 msgid "# Pending requests created" msgstr "# Peticiones pendientes creadas" #: src/fs/gnunet-service-fs_pr.c:394 src/fs/gnunet-service-fs_pr.c:645 msgid "# Pending requests active" msgstr "# Peticiones pendientes activas" #: src/fs/gnunet-service-fs_pr.c:814 msgid "# replies received and matched" msgstr "# respuestas recibidas y asociadas" #: src/fs/gnunet-service-fs_pr.c:844 msgid "# duplicate replies discarded (bloomfilter)" msgstr "# respuestas duplicadas descartadas (bloomfilter)" #: src/fs/gnunet-service-fs_pr.c:853 msgid "# irrelevant replies discarded" msgstr "# respuestas irrelevantes descartadas" #: src/fs/gnunet-service-fs_pr.c:867 #, c-format msgid "Unsupported block type %u\n" msgstr "Tipo de bloque %u no soportado\n" #: src/fs/gnunet-service-fs_pr.c:880 msgid "# results found locally" msgstr "# resultados hallados localmente" #: src/fs/gnunet-service-fs_pr.c:1001 msgid "# Datastore `PUT' failures" msgstr "# «PUT» en el almacén de datos fallidos" #: src/fs/gnunet-service-fs_pr.c:1029 msgid "# storage requests dropped due to high load" msgstr "# peticiones de almacenamiento omitidas debido a alta carga" #: src/fs/gnunet-service-fs_pr.c:1064 msgid "# Replies received from DHT" msgstr "# Respuestas recibidas de la DHT" #: src/fs/gnunet-service-fs_pr.c:1192 #, fuzzy msgid "# Replies received from MESH" msgstr "# Respuestas recibidas de la DHT" #: src/fs/gnunet-service-fs_pr.c:1244 #, c-format msgid "Datastore lookup already took %s!\n" msgstr "¡La búsqueda en el almacén de datos toma %s!\n" #: src/fs/gnunet-service-fs_pr.c:1264 #, c-format msgid "On-demand lookup already took %s!\n" msgstr "¡La búsqueda en bajo demanda toma %s!\n" #: src/fs/gnunet-service-fs_pr.c:1311 msgid "# Datastore lookups concluded (no results)" msgstr "# Búsquedas en el almacén de datos finalizadas (sin resultados)" #: src/fs/gnunet-service-fs_pr.c:1326 msgid "# Datastore lookups concluded (seen all)" msgstr "# Búsquedas en el almacén de datos finalizadas (vistos todos)" #: src/fs/gnunet-service-fs_pr.c:1335 msgid "# Datastore lookups aborted (more than MAX_RESULTS)" msgstr "# Búsquedas en el almacén de datos finalizadas (más de «MAX_RESULTS»)" #: src/fs/gnunet-service-fs_pr.c:1350 msgid "# requested DBLOCK or IBLOCK not found" msgstr "# «DBLOCK» o «IBLOCK» pedido no encontrado" #: src/fs/gnunet-service-fs_pr.c:1364 msgid "# on-demand blocks matched requests" msgstr "# peticiones asociadas de bloques bajo demanda" #: src/fs/gnunet-service-fs_pr.c:1377 msgid "# on-demand lookups performed successfully" msgstr "# búsquedas satisfactorias de bloques bajo demanda" #: src/fs/gnunet-service-fs_pr.c:1382 msgid "# on-demand lookups failed" msgstr "# búsquedas fallidas de bloques bajo demanda" #: src/fs/gnunet-service-fs_pr.c:1409 src/fs/gnunet-service-fs_pr.c:1449 #: src/fs/gnunet-service-fs_pr.c:1590 msgid "# Datastore lookups concluded (error queueing)" msgstr "# Búsquedas en el almacén de datos finalizadas (error encolando)" #: src/fs/gnunet-service-fs_pr.c:1467 msgid "# Datastore lookups concluded (found last result)" msgstr "" "# Búsquedas en el almacén de datos finalizadas (encontrado último resultado)" #: src/fs/gnunet-service-fs_pr.c:1478 msgid "# Datastore lookups concluded (load too high)" msgstr "# Búsquedas en el almacén de datos finalizadas (carga demasiado alta)" #: src/fs/gnunet-service-fs_pr.c:1566 msgid "# Datastore lookups initiated" msgstr "# Búsquedas en el almacén de datos iniciadas" #: src/fs/gnunet-service-fs_pr.c:1651 msgid "# GAP PUT messages received" msgstr "# Mensajes «GAP PUT» recibidos" #: src/fs/gnunet-service-fs_push.c:631 msgid "time required, content pushing disabled" msgstr "se requiere tiempo, publicación de contenido deshabilitada" #: src/fs/gnunet-unindex.c:89 #, c-format msgid "Unindexing at %llu/%llu (%s remaining)\n" msgstr "Desindexado en %llu/%llu (quedan %s)\n" #: src/fs/gnunet-unindex.c:95 #, c-format msgid "Error unindexing: %s.\n" msgstr "Error desindexando: %s.\n" #: src/fs/gnunet-unindex.c:100 msgid "Unindexing done.\n" msgstr "Desindexado finalizado.\n" #: src/fs/gnunet-unindex.c:130 #, c-format msgid "You must specify one and only one filename for unindexing.\n" msgstr "Se debe especificar uno y solo un fichero para desindexar.\n" #: src/fs/gnunet-unindex.c:147 msgid "Could not start unindex operation.\n" msgstr "No se pudo empezar la operación de desindexado.\n" #: src/fs/gnunet-unindex.c:179 msgid "Unindex a file that was previously indexed with gnunet-publish." msgstr "Desindexa un fichero previamente indexado con «gnunet-publish»." #: src/gns/gns_api.c:393 #, fuzzy msgid "Failed to deserialize lookup reply from GNS service!\n" msgstr "" "¡Se produjo un fallo al serializar la respuesta de la búsqueda desde el " "servicio GNS!\n" #: src/gns/gnunet-bcd.c:123 #, fuzzy, c-format msgid "Refusing `%s' request to HTTP server\n" msgstr "Rechazando petición «%s» al servidor de listas de máquinas\n" #: src/gns/gnunet-bcd.c:355 src/hostlist/hostlist-server.c:567 #, c-format msgid "Invalid port number %llu. Exiting.\n" msgstr "Número de puerto %llu no válido. Saliendo.\n" #: src/gns/gnunet-bcd.c:360 #, fuzzy, c-format msgid "Businesscard HTTP server starts on %llu\n" msgstr "Servicio de listas de máquinas arranca en %s:%llu\n" #: src/gns/gnunet-bcd.c:374 #, fuzzy, c-format msgid "Could not start businesscard HTTP server on port %u\n" msgstr "" "No se pudo arrancar un servidor de listas de máquinas HTTP en el puerto %u\n" #: src/gns/gnunet-bcd.c:519 msgid "Run HTTP serve on port PORT (default is 8888)" msgstr "" #: src/gns/gnunet-bcd.c:531 msgid "GNUnet HTTP server to create business cards" msgstr "" #: src/gns/gnunet-dns2gns.c:228 msgid "Failed to pack DNS response into UDP packet!\n" msgstr "" "¡Se produjo un fallo al empaquetar una respuesta DNS en un paquete UDP!\n" #: src/gns/gnunet-dns2gns.c:400 #, c-format msgid "Cannot parse DNS request from %s\n" msgstr "No se puede procesar la petición DNS de %s\n" #: src/gns/gnunet-dns2gns.c:416 #, c-format msgid "Received malformed DNS request from %s\n" msgstr "Recibida petición DNS mal formada de %s\n" #: src/gns/gnunet-dns2gns.c:424 #, c-format msgid "Received unsupported DNS request from %s\n" msgstr "Recibida petición DNS no soportada de %s\n" #: src/gns/gnunet-dns2gns.c:701 msgid "No ego configured for `dns2gns` subsystem\n" msgstr "" #: src/gns/gnunet-dns2gns.c:727 #, fuzzy msgid "No DNS server specified!\n" msgstr "¡Ninguna palabra clave especificada!\n" #: src/gns/gnunet-dns2gns.c:749 #, fuzzy msgid "No valid GNS zone specified!\n" msgstr "¡Ninguna palabra clave especificada!\n" #: src/gns/gnunet-dns2gns.c:770 msgid "IP of recursive DNS resolver to use (required)" msgstr "IP del resolvedor recursivo DNS a usar (requerido)" #: src/gns/gnunet-dns2gns.c:773 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu" msgstr "" "Sufijo FCFS autoritativo a usar (opcional); predeterminado: fcfs.zkey.eu" #: src/gns/gnunet-dns2gns.c:776 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu" msgstr "Sufijo DNS autoritativo a usar (opcional); predeterminado: zkey.eu" #: src/gns/gnunet-dns2gns.c:779 msgid "UDP port to listen on for inbound DNS requests; default: 53" msgstr "" "Puerto UDP en el que escuchar para peticiones DNS entrantes; predeterminado: " "53" #: src/gns/gnunet-dns2gns.c:782 msgid "Public key of the GNS zone to use (overrides default)" msgstr "" #: src/gns/gnunet-dns2gns.c:795 msgid "GNUnet DNS-to-GNS proxy (a DNS server)" msgstr "Pasarela GNUnet DNS-a-GNS (un servidor DNS)" #: src/gns/gnunet-gns.c:227 #, c-format msgid "Please specify name to lookup!\n" msgstr "" #: src/gns/gnunet-gns.c:308 #, c-format msgid "Ego for `%s' not found, cannot perform lookup.\n" msgstr "" #: src/gns/gnunet-gns.c:347 src/gns/gnunet-gns-helper-service-w32.c:798 #, c-format msgid "" "Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-" "gns-import.sh?\n" msgstr "" #: src/gns/gnunet-gns.c:386 src/gns/gnunet-gns-helper-service-w32.c:828 #, c-format msgid "Failed to connect to GNS\n" msgstr "Se produjo un fallo al conectar con GNS\n" #: src/gns/gnunet-gns.c:399 #, c-format msgid "Public key `%s' is not well-formed\n" msgstr "" #: src/gns/gnunet-gns.c:449 msgid "Lookup a record for the given name" msgstr "Buscar el registro para el nombre dado" #: src/gns/gnunet-gns.c:452 msgid "Specify the type of the record to lookup" msgstr "Especificar el tipo del registro a buscar" #: src/gns/gnunet-gns.c:455 #, fuzzy msgid "Specify timeout for the lookup" msgstr "Especificar el tipo del registro a buscar" #: src/gns/gnunet-gns.c:458 msgid "No unneeded output" msgstr "Sin salida innecesaria" #: src/gns/gnunet-gns.c:461 #, fuzzy msgid "Specify the public key of the zone to lookup the record in" msgstr "Especificar el tipo del registro a buscar" #: src/gns/gnunet-gns.c:464 #, fuzzy msgid "Specify the name of the ego of the zone to lookup the record in" msgstr "Especificar el tipo del registro a buscar" #: src/gns/gnunet-gns.c:478 #, fuzzy msgid "GNUnet GNS resolver tool" msgstr "Herramienta de acceso GNUnet GNS" #: src/gns/gnunet-gns-helper-service-w32.c:768 #, c-format msgid "" "Ego for `gns-short' not found. This is not really fatal, but i'll pretend " "that it is and refuse to perform a lookup. Did you run gnunet-gns-import." "sh?\n" msgstr "" #: src/gns/gnunet-gns-helper-service-w32.c:838 #, fuzzy, c-format msgid "Failed to connect to identity service\n" msgstr "Fallo al conectar a gnunetd.\n" #: src/gns/gnunet-gns-import.c:479 msgid "This program will import some GNS authorities into your GNS namestore." msgstr "" #: src/gns/gnunet-gns-proxy.c:105 src/hostlist/hostlist-client.c:469 #: src/hostlist/hostlist-client.c:683 src/hostlist/hostlist-client.c:689 #: src/hostlist/hostlist-client.c:741 src/hostlist/hostlist-client.c:750 #: src/hostlist/hostlist-client.c:871 src/hostlist/hostlist-client.c:963 #: src/hostlist/hostlist-client.c:968 #: src/transport/plugin_transport_http_client.c:1062 #: src/transport/plugin_transport_http_client.c:1077 #, c-format msgid "%s failed at %s:%d: `%s'\n" msgstr "%s falló en %s:%d: «%s».\n" #: src/gns/gnunet-gns-proxy.c:833 #, fuzzy, c-format msgid "Unsupported CURL SSL backend %d\n" msgstr "Tipo de bloque %u no soportado\n" #: src/gns/gnunet-gns-proxy.c:856 #, fuzzy, c-format msgid "Failed to fetch CN from cert: %s\n" msgstr "Se produjo un fallo al mandar la petición DNS a %s\n" #: src/gns/gnunet-gns-proxy.c:879 #, fuzzy, c-format msgid "Failed to initialize DANE: %s\n" msgstr "¡No se puede inicializar el resolvedor!\n" #: src/gns/gnunet-gns-proxy.c:892 #, fuzzy, c-format msgid "Failed to parse DANE record: %s\n" msgstr "Se produjo un fallo al procesar la petición DNS. Omitiendo.\n" #: src/gns/gnunet-gns-proxy.c:907 #, fuzzy, c-format msgid "Failed to verify TLS connection using DANE: %s\n" msgstr "Se produjo un fallo al borrar el fichero de configuración %s\n" #: src/gns/gnunet-gns-proxy.c:917 #, c-format msgid "Failed DANE verification failed with GnuTLS verify status code: %u\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:941 #, c-format msgid "SSL certificate subject name (%s) does not match `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1086 #, c-format msgid "Cookie domain `%s' supplied by server is invalid\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1602 #, fuzzy, c-format msgid "Unsupported HTTP method `%s'\n" msgstr "Tipo no soportado «%s»\n" #: src/gns/gnunet-gns-proxy.c:1973 #, c-format msgid "Unable to import private key from file `%s'\n" msgstr "No se pudo importar la clave privada del fichero «%s»\n" #: src/gns/gnunet-gns-proxy.c:2003 #, c-format msgid "Unable to import certificate %s\n" msgstr "No se pudo importar el certificado %s\n" #: src/gns/gnunet-gns-proxy.c:2177 #, fuzzy, c-format msgid "Failed to start HTTPS server for `%s'\n" msgstr "Se produjo un fallo al iniciar el servidor HTTP\n" #: src/gns/gnunet-gns-proxy.c:2196 #, fuzzy msgid "Failed to pass client to MHD\n" msgstr "Se produjo un fallo al conectar con GNS\n" #: src/gns/gnunet-gns-proxy.c:2504 #, fuzzy, c-format msgid "Unsupported socks version %d\n" msgstr "Tipo de bloque %u no soportado\n" #: src/gns/gnunet-gns-proxy.c:2533 #, fuzzy, c-format msgid "Unsupported socks command %d\n" msgstr "Tipo de bloque %u no soportado\n" #: src/gns/gnunet-gns-proxy.c:2551 src/gns/gnunet-gns-proxy.c:2580 msgid "SSL connection to plain IPv4 address requested\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2631 #, fuzzy, c-format msgid "Unsupported socks address type %d\n" msgstr "Tipo de bloque %u no soportado\n" #: src/gns/gnunet-gns-proxy.c:2970 msgid "No ego configured for `shorten-zone`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3010 #, fuzzy, c-format msgid "No ego configured for `%s`\n" msgstr "" "Ningún puerto fue configurado para el módulo «%s», no se puede probar\n" #: src/gns/gnunet-gns-proxy.c:3072 #, fuzzy, c-format msgid "Failed to load SSL/TLS key and certificate from `%s'\n" msgstr "Se produjo un fallo al leer la lista de amigos de «%s»\n" #: src/gns/gnunet-gns-proxy.c:3113 msgid "listen on specified port (default: 7777)" msgstr "escuchar en el puerto especificado (predeterminado: 7777)" #: src/gns/gnunet-gns-proxy.c:3116 msgid "pem file to use as CA" msgstr "fichero pem para usar como autoridad de certificación (CA)" #: src/gns/gnunet-gns-proxy.c:3135 msgid "GNUnet GNS proxy" msgstr "Proxy GNUnet GNS" #: src/gns/gnunet-service-gns.c:862 msgid "Failed to connect to the namestore!\n" msgstr "¡Se produjo un fallo al conectar con el almacén de nombres!\n" #: src/gns/gnunet-service-gns.c:870 #, fuzzy msgid "Failed to connect to the namecache!\n" msgstr "¡Se produjo un fallo al conectar con el almacén de nombres!\n" #: src/gns/gnunet-service-gns.c:903 msgid "Could not connect to DHT!\n" msgstr "¡No se pudo conectar a la DHT!\n" #: src/gns/gnunet-service-gns.c:919 #, fuzzy msgid "valid public key required" msgstr "Tipo requerido\n" #: src/gns/gnunet-service-gns_interceptor.c:263 #, fuzzy msgid "Error converting GNS response to DNS response!\n" msgstr "¡Se produjo un error al convertir los argumentos a una URI!\n" #: src/gns/gnunet-service-gns_interceptor.c:369 #, fuzzy msgid "Failed to connect to the DNS service!\n" msgstr "¡Se produjo un fallo al conectar con el servicio GNS!\n" #: src/gns/gnunet-service-gns_resolver.c:816 #, fuzzy msgid "Failed to parse DNS response\n" msgstr "Se produjo un fallo al procesar la petición DNS. Omitiendo.\n" #: src/gns/gnunet-service-gns_resolver.c:958 #, c-format msgid "Skipping record of unsupported type %d\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1317 #, c-format msgid "GNS lookup resulted in DNS name that is too long (`%s')\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1817 msgid "GNS lookup recursion failed (no delegation record found)\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1841 #, fuzzy, c-format msgid "Failed to cache GNS resolution: %s\n" msgstr "Se produjo un fallo al mandar la petición DNS a %s\n" #: src/gns/gnunet-service-gns_resolver.c:2123 #, c-format msgid "Zone %s was revoked, resolution fails\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:2272 #, c-format msgid "Hostname `%s' is not well-formed, resolution fails\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:151 #, c-format msgid "Unable to parse PKEY record `%s'\n" msgstr "No se pudo procesar el registro PKEY «%s»\n" #: src/gns/plugin_gnsrecord_gns.c:180 #, fuzzy, c-format msgid "Unable to parse GNS2DNS record `%s'\n" msgstr "No se pudo procesar el registro SOA «%s»\n" #: src/gns/plugin_gnsrecord_gns.c:201 #, fuzzy, c-format msgid "Failed to serialize GNS2DNS record with value `%s'\n" msgstr "" "Se produjo un fallo al escribir el directorio con los resultados de búsqueda " "de «%s»\n" #: src/gns/plugin_gnsrecord_gns.c:217 #, c-format msgid "Unable to parse VPN record string `%s'\n" msgstr "No se pudo procesar la cadena de registro VPN «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:293 #, c-format msgid "Unable to parse IPv4 address `%s'\n" msgstr "No se pudo procesar la dirección IPv4 «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:314 #, fuzzy, c-format msgid "Failed to serialize NS record with value `%s'\n" msgstr "" "Se produjo un fallo al escribir el directorio con los resultados de búsqueda " "de «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:336 #, fuzzy, c-format msgid "Failed to serialize CNAME record with value `%s'\n" msgstr "" "Se produjo un fallo al escribir el directorio con los resultados de búsqueda " "de «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:420 #, fuzzy, c-format msgid "Failed to serialize CERT record with %u bytes\n" msgstr "" "Se produjo un fallo al escribir el directorio con los resultados de búsqueda " "de «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:452 #, c-format msgid "Unable to parse SOA record `%s'\n" msgstr "No se pudo procesar el registro SOA «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:471 #, fuzzy, c-format msgid "Failed to serialize SOA record with mname `%s' and rname `%s'\n" msgstr "Se produjo un fallo al crear un registro para el dominio «%s»: %s\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:494 #, fuzzy, c-format msgid "Failed to serialize PTR record with value `%s'\n" msgstr "" "Se produjo un fallo al escribir el directorio con los resultados de búsqueda " "de «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:514 #, c-format msgid "Unable to parse MX record `%s'\n" msgstr "No se pudo procesar el registro MX «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:529 #, fuzzy, c-format msgid "Failed to serialize MX record with hostname `%s'\n" msgstr "" "Se produjo un fallo al escribir el directorio con los resultados de búsqueda " "de «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:549 #, c-format msgid "Unable to parse IPv6 address `%s'\n" msgstr "No se pudo procesar dirección IPv4 «%s»\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:567 #, c-format msgid "Unable to parse TLSA record string `%s'\n" msgstr "No se pudo procesar la cadena de registro TLSA «%s»\n" #: src/hello/gnunet-hello.c:123 msgid "Call with name of HELLO file to modify.\n" msgstr "Llamar con el nombre del fichero «HELLO» para modificar.\n" #: src/hello/gnunet-hello.c:129 #, c-format msgid "Error accessing file `%s': %s\n" msgstr "Error accediendo al fichero «%s»: %s\n" #: src/hello/gnunet-hello.c:137 #, c-format msgid "File `%s' is too big to be a HELLO\n" msgstr "El fichero «%s» es demasiado grande para ser un «HELLO»\n" #: src/hello/gnunet-hello.c:144 #, c-format msgid "File `%s' is too small to be a HELLO\n" msgstr "El fichero «%s» es demasiado pequeño para ser un «HELLO»\n" #: src/hello/gnunet-hello.c:154 src/hello/gnunet-hello.c:183 #, c-format msgid "Error opening file `%s': %s\n" msgstr "Error abriendo fichero «%s»: %s\n" #: src/hello/gnunet-hello.c:170 #, c-format msgid "Did not find well-formed HELLO in file `%s'\n" msgstr "No se encontró un «HELLO» bien formado en el fichero «%s»\n" #: src/hello/gnunet-hello.c:195 #, c-format msgid "Error writing HELLO to file `%s': %s\n" msgstr "Error escribiendo «HELLO» al fichero «%s»: %s\n" #: src/hello/gnunet-hello.c:203 #, c-format msgid "Modified %u addresses \n" msgstr "" #: src/hello/hello.c:944 msgid "Failed to parse HELLO message: missing expiration time\n" msgstr "" "Se produjo un fallo al procesar un mensaje «HELLO»: falta el tiempo de " "expiración\n" #: src/hello/hello.c:953 msgid "Failed to parse HELLO message: invalid expiration time\n" msgstr "" "Se produjo un fallo al procesar un mensaje «HELLO»: tiempo de expiración no " "válido\n" #: src/hello/hello.c:963 msgid "Failed to parse HELLO message: malformed\n" msgstr "Se produjo un fallo al procesar un mensaje «HELLO»: mal formado\n" #: src/hello/hello.c:973 msgid "Failed to parse HELLO message: missing transport plugin\n" msgstr "" "Se produjo un fallo al procesar un mensaje «HELLO»: falta el módulo de " "transporte\n" #: src/hello/hello.c:990 #, c-format msgid "Plugin `%s' not found\n" msgstr "Módulo «%s» no encontrado\n" #: src/hello/hello.c:999 #, c-format msgid "Plugin `%s' does not support URIs yet\n" msgstr "El módulo «%s» no soporta URI todavía\n" #: src/hello/hello.c:1018 #, c-format msgid "Failed to parse `%s' as an address for plugin `%s'\n" msgstr "" "Se produjo un fallo al procesar «%s» como una dirección para el módulo «%s»\n" #: src/hostlist/gnunet-daemon-hostlist.c:259 msgid "" "None of the functions for the hostlist daemon were enabled. I have no " "reason to run!\n" msgstr "" "Ninguna de las funciones para el demonio de listas de máquinas fue " "activada. ¡No tengo razón para ejecutarme!\n" #: src/hostlist/gnunet-daemon-hostlist.c:308 msgid "advertise our hostlist to other peers" msgstr "anuncia nuestra lista de máquinas a otros pares" #: src/hostlist/gnunet-daemon-hostlist.c:313 msgid "" "bootstrap using hostlists (it is highly recommended that you always use this " "option)" msgstr "" "realizar inicialización usando listas de máquinas (es altamente recomendable " "que siempre se use esta opción)" #: src/hostlist/gnunet-daemon-hostlist.c:316 msgid "enable learning about hostlist servers from other peers" msgstr "" "habilitar aprendizaje de servidores de listas de máquinas de otros pares" #: src/hostlist/gnunet-daemon-hostlist.c:320 msgid "provide a hostlist server" msgstr "proveer un servidor de listas de máquinas" #: src/hostlist/gnunet-daemon-hostlist.c:335 msgid "GNUnet hostlist server and client" msgstr "Servidor y cliente GNUnet de listas de máquinas" #: src/hostlist/hostlist-client.c:288 msgid "# bytes downloaded from hostlist servers" msgstr "# bytes descargados de servidores de listas de máquinas" #: src/hostlist/hostlist-client.c:309 src/hostlist/hostlist-client.c:339 msgid "# invalid HELLOs downloaded from hostlist servers" msgstr "# «HELLO» no válidos descargados de servidores de listas de máquinas" #: src/hostlist/hostlist-client.c:312 src/hostlist/hostlist-client.c:342 #, c-format msgid "Invalid `%s' message received from hostlist at `%s'\n" msgstr "Mensaje «%s» no válido recibido de la lista de máquinas en «%s»\n" #: src/hostlist/hostlist-client.c:330 msgid "# valid HELLOs downloaded from hostlist servers" msgstr "# «HELLO» válidos descargados de servidores de listas de máquinas" #: src/hostlist/hostlist-client.c:592 src/hostlist/hostlist-client.c:1333 msgid "# advertised hostlist URIs" msgstr "# URI de listas de máquinas anunciadas" #: src/hostlist/hostlist-client.c:622 #, c-format msgid "# advertised URI `%s' downloaded" msgstr "# URI anunciadas «%s» descargadas" #: src/hostlist/hostlist-client.c:664 #, c-format msgid "" "Advertised hostlist with URI `%s' could not be downloaded. Advertised URI " "gets dismissed.\n" msgstr "" "Lista de máquinas anunciada con la URI «%s» no pudo ser descargada. La URI " "anunciada es descartada.\n" #: src/hostlist/hostlist-client.c:802 #, c-format msgid "Timeout trying to download hostlist from `%s'\n" msgstr "" "Finalizado el plazo mientras se intentaba bajar lista de máquinas de «%s»\n" #: src/hostlist/hostlist-client.c:816 #, c-format msgid "Download limit of %u bytes exceeded, stopping download\n" msgstr "Límite de descarga de %u bytes superado, parando descarga\n" #: src/hostlist/hostlist-client.c:836 #, c-format msgid "Download of hostlist from `%s' failed: `%s'\n" msgstr "Descarga de lista de máquinas de «%s» fallida: «%s»\n" #: src/hostlist/hostlist-client.c:842 #, c-format msgid "Download of hostlist `%s' completed.\n" msgstr "Descarga de lista de máquinas «%s» completada.\n" #: src/hostlist/hostlist-client.c:850 #, c-format msgid "Adding successfully tested hostlist `%s' datastore.\n" msgstr "Añadiendo el almacén de datos de la lista de máquinas probada «%s».\n" #: src/hostlist/hostlist-client.c:903 #, c-format msgid "Bootstrapping using hostlist at `%s'.\n" msgstr "Inicializando usando lista de máquinas en «%s».\n" #: src/hostlist/hostlist-client.c:911 msgid "# hostlist downloads initiated" msgstr "# descargas de listas de máquinas iniciadas" #: src/hostlist/hostlist-client.c:1040 src/hostlist/hostlist-client.c:1506 msgid "# milliseconds between hostlist downloads" msgstr "# milisegundos entre descargas de listas de máquinas" #: src/hostlist/hostlist-client.c:1049 #, c-format msgid "Have %u/%u connections. Will consider downloading hostlist in %s\n" msgstr "" "Hay %u/%u conexiones. Se considerará descargar una lista de máquinas en %s\n" #: src/hostlist/hostlist-client.c:1109 src/hostlist/hostlist-client.c:1125 msgid "# active connections" msgstr "# conexiones activas" #: src/hostlist/hostlist-client.c:1280 #, c-format msgid "Loading saved hostlist entries from file `%s' \n" msgstr "Cargando entradas guardadas de listas de máquinas del fichero «%s»\n" #: src/hostlist/hostlist-client.c:1285 #, c-format msgid "Hostlist file `%s' does not exist\n" msgstr "El fichero de listas de máquinas «%s» no existe\n" #: src/hostlist/hostlist-client.c:1296 #, c-format msgid "Could not open file `%s' for reading to load hostlists: %s\n" msgstr "" "No se pudo abrir el fichero «%s» en modo lectura para cargar las listas de " "máquinas: %s\n" #: src/hostlist/hostlist-client.c:1329 #, c-format msgid "%u hostlist URIs loaded from file\n" msgstr "%u URI de listas de máquinas cargadas del fichero\n" #: src/hostlist/hostlist-client.c:1331 msgid "# hostlist URIs read from file" msgstr "# URI de listas de máquinas leídas de fichero" #: src/hostlist/hostlist-client.c:1376 #, c-format msgid "Could not open file `%s' for writing to save hostlists: %s\n" msgstr "" "No se pudo abrir el fichero «%s» en modo escritura para almacenar las listas " "de máquinas: %s\n" #: src/hostlist/hostlist-client.c:1381 #, c-format msgid "Writing %u hostlist URIs to `%s'\n" msgstr "Escribiendo %u URI de listas de máquinas a «%s»\n" #: src/hostlist/hostlist-client.c:1405 src/hostlist/hostlist-client.c:1422 #, c-format msgid "Error writing hostlist URIs to file `%s'\n" msgstr "Error escribiendo URI de listas de máquinas al fichero «%s»\n" #: src/hostlist/hostlist-client.c:1417 msgid "# hostlist URIs written to file" msgstr "# URI de listas de máquinas escritas a fichero" #: src/hostlist/hostlist-client.c:1471 msgid "Learning is enabled on this peer\n" msgstr "El aprendizaje está habilitado en este par\n" #: src/hostlist/hostlist-client.c:1483 msgid "Learning is not enabled on this peer\n" msgstr "El aprendizaje no está habilitado en este par\n" #: src/hostlist/hostlist-client.c:1495 #, c-format msgid "" "Since learning is not enabled on this peer, hostlist file `%s' was removed\n" msgstr "" "La lista de máquinas «%s» fue eliminada puesto que el aprendizaje no está " "habilitado en este par\n" #: src/hostlist/hostlist-client.c:1499 #, c-format msgid "Hostlist file `%s' could not be removed\n" msgstr "El fichero de listas de máquinas «%s» no pudo ser eliminado\n" #: src/hostlist/hostlist-server.c:137 msgid "bytes in hostlist" msgstr "bytes en la lista de máquinas" #: src/hostlist/hostlist-server.c:161 msgid "expired addresses encountered" msgstr "direcciones expiradas encontradas" #: src/hostlist/hostlist-server.c:189 src/hostlist/hostlist-server.c:425 #: src/peerinfo-tool/gnunet-peerinfo.c:350 #: src/peerinfo-tool/gnunet-peerinfo.c:419 #: src/peerinfo-tool/gnunet-peerinfo.c:490 #: src/topology/gnunet-daemon-topology.c:925 #, c-format msgid "Error in communication with PEERINFO service: %s\n" msgstr "" "Error en la comunicación con el servicio de información de pares (PEERINFO): " "%s\n" #: src/hostlist/hostlist-server.c:210 msgid "HELLOs without addresses encountered (ignored)" msgstr "«HELLO» sin dirección encontrados (ignorados)" #: src/hostlist/hostlist-server.c:224 msgid "bytes not included in hostlist (size limit)" msgstr "bytes no incluidos en la lista de máquinas (límite de tamaño)" #: src/hostlist/hostlist-server.c:268 #, c-format msgid "Refusing `%s' request to hostlist server\n" msgstr "Rechazando petición «%s» al servidor de listas de máquinas\n" #: src/hostlist/hostlist-server.c:271 msgid "hostlist requests refused (not HTTP GET)" msgstr "Peticiones de listas de máquinas rechazadas (no HTTP GET)" #: src/hostlist/hostlist-server.c:284 #, c-format msgid "Refusing `%s' request with %llu bytes of upload data\n" msgstr "Rechazando petición «%s» con %llu bytes de datos de subida\n" #: src/hostlist/hostlist-server.c:288 msgid "hostlist requests refused (upload data)" msgstr "Peticiones de listas de máquinas rechazadas (datos de subida)" #: src/hostlist/hostlist-server.c:296 msgid "Could not handle hostlist request since I do not have a response yet\n" msgstr "" "No se pudo manejar una petición de lista de máquinas debido a que no hay una " "respuesta todavía\n" #: src/hostlist/hostlist-server.c:299 msgid "hostlist requests refused (not ready)" msgstr "Peticiones de listas de máquinas rechazadas (no preparados)" #: src/hostlist/hostlist-server.c:303 msgid "Received request for our hostlist\n" msgstr "Peticiones recibidas de nuestra lista de máquinas\n" #: src/hostlist/hostlist-server.c:304 msgid "hostlist requests processed" msgstr "Peticiones de lista de máquinas procesadas" #: src/hostlist/hostlist-server.c:346 msgid "# hostlist advertisements send" msgstr "# anuncios de listas de máquinas enviados" #: src/hostlist/hostlist-server.c:390 msgid "Advertisement message could not be queued by core\n" msgstr "" "Los mensajes de anuncio no pudieron encolarse por el servicio principal\n" #: src/hostlist/hostlist-server.c:557 src/peerinfo-tool/gnunet-peerinfo.c:639 #: src/transport/gnunet-service-transport.c:1114 msgid "Could not access PEERINFO service. Exiting.\n" msgstr "" "No se pudo acceder al servicio de información de pares (PEERINFO). " "Saliendo.\n" #: src/hostlist/hostlist-server.c:576 #, c-format msgid "Hostlist service starts on %s:%llu\n" msgstr "Servicio de listas de máquinas arranca en %s:%llu\n" #: src/hostlist/hostlist-server.c:590 #, c-format msgid "Address to obtain hostlist: `%s'\n" msgstr "Dirección para obtener la lista de máquinas: «%s»\n" #: src/hostlist/hostlist-server.c:630 #, c-format msgid "`%s' is not a valid IP address! Ignoring BINDTOIP.\n" msgstr "¡«%s» no es una dirección IP válida! Ignorando «BINDTOIP».\n" #: src/hostlist/hostlist-server.c:673 #, c-format msgid "Could not start hostlist HTTP server on port %u\n" msgstr "" "No se pudo arrancar un servidor de listas de máquinas HTTP en el puerto %u\n" #: src/identity/gnunet-identity.c:165 #, fuzzy, c-format msgid "Failed to create ego: %s\n" msgstr "Se produjo un fallo al crear la página para «%s»\n" #: src/identity/gnunet-identity.c:184 #, fuzzy, c-format msgid "Failed to set default ego: %s\n" msgstr "Se produjo un fallo al crear la página para «%s»\n" #: src/identity/gnunet-identity.c:327 msgid "create ego NAME" msgstr "" #: src/identity/gnunet-identity.c:330 #, fuzzy msgid "delete ego NAME " msgstr "borrar un nombre de espacio de nombres (NAME)" #: src/identity/gnunet-identity.c:333 #, fuzzy msgid "display all egos" msgstr "mostrar registros" #: src/identity/gnunet-identity.c:336 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)" msgstr "" # Miguel: Aquí he dejado monitorización porque esto es # del servicio de traducción de direcciones. #: src/identity/gnunet-identity.c:339 #, fuzzy msgid "run in monitor mode egos" msgstr "modo de monitorización" #: src/identity/gnunet-identity.c:342 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)" msgstr "" #: src/identity/gnunet-identity.c:351 msgid "Maintain egos" msgstr "" #: src/identity/gnunet-service-identity.c:338 msgid "no default known" msgstr "" #: src/identity/gnunet-service-identity.c:362 msgid "default configured, but ego unknown (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:439 #: src/identity/gnunet-service-identity.c:670 #: src/identity/gnunet-service-identity.c:778 #, fuzzy, c-format msgid "Failed to write subsystem default identifier map to `%s'.\n" msgstr "" "Se produjo un fallo al obtener los identificadores de fichero para «%s»\n" #: src/identity/gnunet-service-identity.c:446 msgid "Unknown ego specified for service (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:516 msgid "identifier already in use for another ego" msgstr "" #: src/identity/gnunet-service-identity.c:647 #, fuzzy msgid "target name already exists" msgstr "El registro ya existía en el almacén de nombres" #: src/identity/gnunet-service-identity.c:686 #: src/identity/gnunet-service-identity.c:795 msgid "no matching ego found" msgstr "" #: src/identity/gnunet-service-identity.c:829 #, fuzzy, c-format msgid "Failed to parse ego information in `%s'\n" msgstr "Se produjo un fallo al procesar la identidad del par «%s»\n" #: src/identity/gnunet-service-identity.c:902 #, fuzzy, c-format msgid "Failed to parse subsystem identity configuration file `%s'\n" msgstr "Se produjo un fallo al borrar el fichero de configuración %s\n" #: src/identity/gnunet-service-identity.c:914 #, fuzzy, c-format msgid "Failed to create directory `%s' for storing egos\n" msgstr "Se produjo un fallo al leer el directorio «%s»\n" #: src/mesh/gnunet-mesh.c:357 #, fuzzy, c-format msgid "Invalid target `%s'\n" msgstr "Parámetro no válido «%s»\n" #: src/mesh/gnunet-mesh.c:607 #, fuzzy, c-format msgid "Invalid peer ID `%s'\n" msgstr "URI no válida: «%s»\n" #: src/mesh/gnunet-mesh.c:650 #, fuzzy, c-format msgid "Invalid tunnel owner `%s'\n" msgstr "Formato de tiempo no válido «%s»\n" #: src/mesh/gnunet-mesh.c:716 msgid "You must NOT give a TARGETwhen using 'request all' options\n" msgstr "" #: src/mesh/gnunet-mesh.c:807 #, fuzzy msgid "provide information about a particular connection" msgstr "proveer información acerca de un túnel en particular" #: src/mesh/gnunet-mesh.c:810 msgid "activate echo mode" msgstr "" #: src/mesh/gnunet-mesh.c:816 msgid "port to listen to (default; 0)" msgstr "" #: src/mesh/gnunet-mesh.c:819 src/mesh/gnunet-mesh.c:822 #, fuzzy msgid "provide information about all peers" msgstr "proveer información acerca de un túnel en particular" #: src/mesh/gnunet-mesh.c:825 msgid "provide information about a particular tunnel" msgstr "proveer información acerca de un túnel en particular" #: src/mesh/gnunet-mesh.c:828 #, fuzzy msgid "provide information about all tunnels" msgstr "proveer información acerca de un túnel en particular" #: src/mesh/gnunet-service-mesh_peer.c:390 msgid "Wrong CORE service\n" msgstr "Servicio principal (CORE) erróneo\n" #: src/mysql/mysql.c:174 #, c-format msgid "Trying to use file `%s' for MySQL configuration.\n" msgstr "Intentando usar el fichero «%s» para la configuración de MySQL.\n" #: src/mysql/mysql.c:181 #, c-format msgid "Could not access file `%s': %s\n" msgstr "No se pudo acceder al fichero «%s»: %s\n" #: src/namecache/gnunet-namecache.c:109 #, fuzzy, c-format msgid "No records found for `%s'" msgstr "No se han encontrado ficheros en «%s»\n" #: src/namecache/gnunet-namecache.c:124 src/namestore/gnunet-namestore.c:397 #, c-format msgid "\tCorrupt or unsupported record of type %u\n" msgstr "\tRegistro corrupto o no soportado del tipo %u\n" #: src/namecache/gnunet-namecache.c:185 #, fuzzy, c-format msgid "You must specify which zone should be accessed\n" msgstr "Se debe especificar un apodo\n" #: src/namecache/gnunet-namecache.c:195 src/namestore/gnunet-namestore.c:695 #, fuzzy, c-format msgid "Invalid public key for reverse lookup `%s'\n" msgstr "Parámetro no válido «%s»\n" #: src/namecache/gnunet-namecache.c:203 #, fuzzy, c-format msgid "You must specify a name\n" msgstr "¡Debes especificar un receptor!\n" #: src/namecache/gnunet-namecache.c:234 src/namestore/gnunet-namestore.c:931 msgid "name of the record to add/delete/display" msgstr "nombre del registro a añadir/borrar/mostrar" #: src/namecache/gnunet-namecache.c:237 #, fuzzy msgid "spezifies the public key of the zone to look in" msgstr "Especificar el tipo del registro a buscar" #: src/namecache/gnunet-namecache.c:248 src/namestore/gnunet-namestore.c:963 msgid "GNUnet zone manipulation tool" msgstr "Herramienta de manipulación de zona de GNUnet" #: src/namecache/namecache_api.c:276 #, fuzzy msgid "Namecache failed to cache block" msgstr "El almacén de nombres no pudo añadir el registro" #: src/namecache/plugin_namecache_postgres.c:89 #: src/namestore/plugin_namestore_postgres.c:96 msgid "Failed to create indices\n" msgstr "Se produjo un fallo al crear los índices\n" #: src/namestore/gnunet-namestore.c:303 #, c-format msgid "Adding record failed: %s\n" msgstr "No se pudo añadir el registro: %s\n" #: src/namestore/gnunet-namestore.c:332 #, fuzzy, c-format msgid "Deleting record failed, record does not exist%s%s\n" msgstr "No se pudo borrar el registro: %s\n" #: src/namestore/gnunet-namestore.c:339 #, fuzzy, c-format msgid "Deleting record failed%s%s\n" msgstr "No se pudo borrar el registro: %s\n" #: src/namestore/gnunet-namestore.c:558 #, c-format msgid "No options given\n" msgstr "No se han proporcionado opciones\n" #: src/namestore/gnunet-namestore.c:569 #: src/namestore/gnunet-namestore-fcfsd.c:970 msgid "Failed to connect to namestore\n" msgstr "Se produjo un fallo al conectar con el almacén de nombres\n" #: src/namestore/gnunet-namestore.c:577 src/namestore/gnunet-namestore.c:586 #: src/namestore/gnunet-namestore.c:603 src/namestore/gnunet-namestore.c:625 #: src/namestore/gnunet-namestore.c:665 #, c-format msgid "Missing option `%s' for operation `%s'\n" msgstr "Falta la opción «%s» para la operación «%s»\n" #: src/namestore/gnunet-namestore.c:578 src/namestore/gnunet-namestore.c:587 #: src/namestore/gnunet-namestore.c:604 src/namestore/gnunet-namestore.c:626 msgid "add" msgstr "añadir" #: src/namestore/gnunet-namestore.c:595 #, c-format msgid "Unsupported type `%s'\n" msgstr "Tipo no soportado «%s»\n" #: src/namestore/gnunet-namestore.c:615 #, c-format msgid "Value `%s' invalid for record type `%s'\n" msgstr "Valor «%s» no válido para el tipo de registro «%s»\n" #: src/namestore/gnunet-namestore.c:651 #, c-format msgid "Invalid time format `%s'\n" msgstr "Formato de tiempo no válido «%s»\n" #: src/namestore/gnunet-namestore.c:666 msgid "del" msgstr "borrar" #: src/namestore/gnunet-namestore.c:715 #: src/peerinfo-tool/gnunet-peerinfo.c:723 #, c-format msgid "Invalid URI `%s'\n" msgstr "URI no válida: «%s»\n" #: src/namestore/gnunet-namestore.c:750 #, fuzzy, c-format msgid "Invalid nick `%s'\n" msgstr "URI no válida: «%s»\n" #: src/namestore/gnunet-namestore.c:790 #, fuzzy, c-format msgid "Ego `%s' not known to identity service\n" msgstr "'%s': servicio desconocido: %s\n" #: src/namestore/gnunet-namestore.c:817 #, fuzzy, c-format msgid "No default ego configured in identity service\n" msgstr "'%s': servicio desconocido: %s\n" #: src/namestore/gnunet-namestore.c:853 #, fuzzy, c-format msgid "Identity service is not running\n" msgstr "El servicio «%s» no está ejecutandose\n" #: src/namestore/gnunet-namestore.c:865 #, fuzzy, c-format msgid "Cannot connect to identity service\n" msgstr "¡No se pudo conectar al servicio %s!\n" #: src/namestore/gnunet-namestore.c:913 msgid "add record" msgstr "añadir registro" #: src/namestore/gnunet-namestore.c:916 msgid "delete record" msgstr "borrar registro" #: src/namestore/gnunet-namestore.c:919 msgid "display records" msgstr "mostrar registros" #: src/namestore/gnunet-namestore.c:922 msgid "" "expiration time for record to use (for adding only), \"never\" is possible" msgstr "" "tiempo de expiración del registro a usar (únicamente para añadir), nunca " "(\"never\") es posible" #: src/namestore/gnunet-namestore.c:925 #, fuzzy msgid "set the desired nick name for the zone" msgstr "establece el nivel LEVEL deseado de replicación" #: src/namestore/gnunet-namestore.c:928 #, fuzzy msgid "monitor changes in the namestore" msgstr "¡Se produjo un fallo al conectar con el almacén de nombres!\n" #: src/namestore/gnunet-namestore.c:934 #, fuzzy msgid "determine our name for the given PKEY" msgstr "establece las preferencias para el par dado" #: src/namestore/gnunet-namestore.c:937 msgid "type of the record to add/delete/display" msgstr "tipo del registro a añadir/borrar/mostrar" #: src/namestore/gnunet-namestore.c:940 msgid "URI to import into our zone" msgstr "URI a importar a nuestra zona" #: src/namestore/gnunet-namestore.c:943 msgid "value of the record to add/delete" msgstr "valor del registro a añadir/borrar" #: src/namestore/gnunet-namestore.c:946 msgid "create or list public record" msgstr "crear o listar registros públicos" #: src/namestore/gnunet-namestore.c:949 msgid "" "create shadow record (only valid if all other records of the same type have " "expired" msgstr "" #: src/namestore/gnunet-namestore.c:952 #, fuzzy msgid "name of the ego controlling the zone" msgstr "nombre de la sección a la que acceder" # form?? #: src/namestore/gnunet-namestore-fcfsd.c:464 #, c-format msgid "Unsupported form value `%s'\n" msgstr "Forma de valor no soportada «%s»\n" #: src/namestore/gnunet-namestore-fcfsd.c:491 #, c-format msgid "Failed to create record for domain `%s': %s\n" msgstr "Se produjo un fallo al crear un registro para el dominio «%s»: %s\n" #: src/namestore/gnunet-namestore-fcfsd.c:525 #, c-format msgid "Found existing name `%s' for the given key\n" msgstr "Encontrado nombre «%s» para la clave dada\n" #: src/namestore/gnunet-namestore-fcfsd.c:534 msgid "Error when mapping zone to name\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:596 #, c-format msgid "Found %u existing records for domain `%s'\n" msgstr "Encontrados %u registros para el dominio «%s»\n" #: src/namestore/gnunet-namestore-fcfsd.c:652 #, c-format msgid "Failed to create page for `%s'\n" msgstr "Se produjo un fallo al crear la página para «%s»\n" #: src/namestore/gnunet-namestore-fcfsd.c:668 #, c-format msgid "Failed to setup post processor for `%s'\n" msgstr "Se produjo un fallo al configurar el post-procesador para «%s»\n" #: src/namestore/gnunet-namestore-fcfsd.c:704 msgid "Domain name must not contain `.'\n" msgstr "El nombre de dominio no puede contener «.»\n" #: src/namestore/gnunet-namestore-fcfsd.c:712 msgid "Domain name must not contain `+'\n" msgstr "El nombre de dominio no puede contener «+»\n" #: src/namestore/gnunet-namestore-fcfsd.c:910 msgid "No ego configured for `fcfsd` subsystem\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:936 msgid "Failed to start HTTP server\n" msgstr "Se produjo un fallo al iniciar el servidor HTTP\n" #: src/namestore/gnunet-namestore-fcfsd.c:978 #, fuzzy msgid "Failed to connect to identity\n" msgstr "Se produjo un fallo al conectar con GNS\n" #: src/namestore/gnunet-namestore-fcfsd.c:1011 #, fuzzy msgid "GNU Name System First Come First Serve name registration service" msgstr "Servicio de registro GNUnet GNS primero en llegar, primero en servirse" #: src/namestore/gnunet-service-namestore.c:655 #, fuzzy, c-format msgid "Failed to replicate block in namecache: %s\n" msgstr "Se produjo un fallo al crear el espacio de nombres «%s»\n" #: src/namestore/namestore_api.c:275 #, fuzzy msgid "Namestore failed to store record\n" msgstr "El almacén de nombres no pudo añadir el registro\n" #: src/nat/gnunet-nat-server.c:279 #, c-format msgid "Please pass valid port number as the first argument! (got `%s')\n" msgstr "" "¡Por favor, pase un número de puerto válido como primer parámetro! (se " "obtuvo «%s»)\n" #: src/nat/gnunet-nat-server.c:321 msgid "GNUnet NAT traversal test helper daemon" msgstr "Demonio de ayuda en las pruebas de recorrido NAT de GNUnet" #: src/nat/nat_auto.c:170 msgid "NAT traversal with ICMP Server timed out.\n" msgstr "Recorrido NAT con servidor ICMP expirado.\n" #: src/nat/nat_auto.c:203 msgid "NAT traversal with ICMP Server succeeded.\n" msgstr "Recorrido NAT con servidor ICMP satisfactorio.\n" #: src/nat/nat_auto.c:204 msgid "NAT traversal with ICMP Server failed.\n" msgstr "Recorrido NAT con servidor ICMP fallido.\n" #: src/nat/nat_auto.c:225 msgid "Testing connection reversal with ICMP server.\n" msgstr "Probando conexión inversa con el servidor ICMP.\n" #: src/nat/nat_auto.c:274 #, c-format msgid "Detected external IP `%s'\n" msgstr "Detectada IP externa «%s»\n" #: src/nat/nat_auto.c:344 msgid "This system has a global IPv6 address, setting IPv6 to supported.\n" msgstr "" "Este sistema tiene una dirección IPv6 global, fijando IPv6 a habilitado.\n" #: src/nat/nat_auto.c:360 #, c-format msgid "Detected internal network address `%s'.\n" msgstr "Detectada dirección de la red interna «%s».\n" #: src/nat/nat_auto.c:413 msgid "upnpc found, enabling its use\n" msgstr "«upnpc» encontrado, habilitando su uso\n" #: src/nat/nat_auto.c:414 msgid "upnpc not found\n" msgstr "«upnpc» no encontrado\n" #: src/nat/nat_auto.c:447 msgid "gnunet-helper-nat-server found, testing it\n" msgstr "«gnunet-helper-nat-server» encontrado, probándolo\n" #: src/nat/nat_auto.c:448 msgid "No working gnunet-helper-nat-server found\n" msgstr "No se ha encontrado un «gnunet-helper-nat-server» funcional\n" #: src/nat/nat_auto.c:482 msgid "gnunet-helper-nat-client found, enabling it\n" msgstr "«gnunet-helper-nat-client» encontrado, habilitando su uso\n" #: src/nat/nat_auto.c:483 msgid "gnunet-helper-nat-client not found or behind NAT, disabling it\n" msgstr "" "«gnunet-helper-nat-client» no encontrado o detrás de NAT, deshabilitando su " "uso\n" #: src/nat/nat.c:867 #, c-format msgid "gnunet-helper-nat-server generated malformed address `%s'\n" msgstr "«gnunet-helper-nat-server» generó la dirección mal formada «%s»\n" #: src/nat/nat.c:917 #, c-format msgid "Failed to start %s\n" msgstr "Se produjo un fallo al arrancar %s\n" #: src/nat/nat.c:1205 msgid "malformed" msgstr "mal formado" #: src/nat/nat.c:1276 src/nat/nat.c:1288 #, c-format msgid "" "Configuration requires `%s', but binary is not installed properly (SUID bit " "not set). Option disabled.\n" msgstr "" "La configuración requiere «%s», pero el binario no está instalado de forma " "correcta (SUID bit no activado). Opción deshabilitada.\n" #: src/nat/nat.c:1426 msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n" msgstr "" "Direcciones internas IP no conocidas, no se puede usar el método del " "recorrido NAT ICMP\n" #: src/nat/nat.c:1442 #, c-format msgid "Running gnunet-helper-nat-client %s %s %u\n" msgstr "Ejecutando gnunet-helper-nat-client %s %s %u\n" #: src/nat/nat_mini.c:155 msgid "no valid address was returned by `external-ip'" msgstr "" #: src/nat/nat_mini.c:175 #, fuzzy msgid "`external-ip' command not found" msgstr "comando «external-ip» no encontrado\n" #: src/nat/nat_mini.c:201 msgid "`external-ip' command not found\n" msgstr "comando «external-ip» no encontrado\n" #: src/nat/nat_mini.c:366 #, fuzzy msgid "Failed to run `upnpc` command" msgstr "Se produjo un fallo al ejecutar «%s»\n" #: src/nat/nat_mini.c:512 #, fuzzy msgid "`upnpc' command took too long, process killed" msgstr "comando «upnpc» no encontrado\n" #: src/nat/nat_mini.c:540 msgid "`upnpc' command failed to establish port mapping" msgstr "" #: src/nat/nat_mini.c:604 msgid "`upnpc' command not found\n" msgstr "comando «upnpc» no encontrado\n" #: src/nat/nat_mini.c:608 #, fuzzy msgid "`upnpc` command not found" msgstr "comando «upnpc» no encontrado\n" #: src/nat/nat_test.c:351 msgid "Failed to connect to `gnunet-nat-server'\n" msgstr "Se produjo un fallo al conectar con «gnunet-nat-server»\n" #: src/nat/nat_test.c:423 #, c-format msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n" msgstr "" "Se produjo un fallo al crear el «socket» de escucha asociado a «%s» para " "pruebas NAT: %s\n" #: src/nse/gnunet-nse.c:117 #, fuzzy msgid "NSE service is not running\n" msgstr "El servicio «%s» no está ejecutandose\n" #: src/nse/gnunet-nse.c:122 msgid "Error while checking if NSE service is running or not\n" msgstr "" #: src/nse/gnunet-nse.c:168 #, fuzzy msgid "Show network size estimates from NSE service." msgstr "# Estimaciones del tamaño de red recibidas" #: src/nse/gnunet-nse-profiler.c:858 msgid "limit to the number of connections to NSE services, 0 for none" msgstr "límite al número de conexiones a servicios NSE, 0 para ilimitadas" #: src/nse/gnunet-nse-profiler.c:861 msgid "name of the file for writing connection information and statistics" msgstr "" "nombre del fichero para escribir información y estadísticas de la conexión" #: src/nse/gnunet-nse-profiler.c:864 src/testbed/gnunet-testbed-profiler.c:306 msgid "name of the file with the login information for the testbed" msgstr "" "nombre del fichero con la información de acceso usada para la batería de " "pruebas" #: src/nse/gnunet-nse-profiler.c:867 msgid "name of the file for writing the main results" msgstr "nombre del fichero en el que escribir los resultados principales" #: src/nse/gnunet-nse-profiler.c:870 msgid "Number of peers to run in each round, separated by commas" msgstr "Número de pares a ejecutar en cada ronda, separados por comas" #: src/nse/gnunet-nse-profiler.c:876 msgid "delay between rounds" msgstr "retraso entre rondas" #: src/nse/gnunet-nse-profiler.c:885 msgid "Measure quality and performance of the NSE service." msgstr "Medir la calidad y rendimiento del servicio NSE." #: src/nse/gnunet-service-nse.c:1517 #: src/revocation/gnunet-service-revocation.c:789 src/util/gnunet-scrypt.c:248 msgid "Value is too large.\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:215 #, c-format msgid "Removing expired address of transport `%s'\n" msgstr "Eliminando dirección de transporte «%s»\n" #: src/peerinfo/gnunet-service-peerinfo.c:352 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s': %s\n" msgstr "Se produjo un fallo al procesar «HELLO» en el fichero «%s»\n" #: src/peerinfo/gnunet-service-peerinfo.c:371 #: src/peerinfo/gnunet-service-peerinfo.c:388 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s'\n" msgstr "Se produjo un fallo al procesar «HELLO» en el fichero «%s»\n" #: src/peerinfo/gnunet-service-peerinfo.c:466 msgid "# peers known" msgstr "# pares conocidos" #: src/peerinfo/gnunet-service-peerinfo.c:503 #, c-format msgid "" "File `%s' in directory `%s' does not match naming convention. Removed.\n" msgstr "" "El fichero «%s» en el directorio «%s» no sigue la convención de nombres. " "Eliminado.\n" #: src/peerinfo/gnunet-service-peerinfo.c:653 #, fuzzy, c-format msgid "Scanning directory `%s'\n" msgstr "Escaneando directorio «%s».\n" #: src/peerinfo/gnunet-service-peerinfo.c:658 #, c-format msgid "Still no peers found in `%s'!\n" msgstr "¡Aún no se han encontrado pares en «%s»!\n" #: src/peerinfo/gnunet-service-peerinfo.c:994 #, fuzzy, c-format msgid "Cleaning up directory `%s'\n" msgstr "Escaneando directorio «%s».\n" #: src/peerinfo/gnunet-service-peerinfo.c:1287 #, c-format msgid "Importing HELLOs from `%s'\n" msgstr "Importando HELLO de «%s»\n" #: src/peerinfo/gnunet-service-peerinfo.c:1298 msgid "Skipping import of included HELLOs\n" msgstr "" #: src/peerinfo/peerinfo_api.c:236 msgid "aborted due to explicit disconnect request" msgstr "abortado debido a petición de desconexión explícita" #: src/peerinfo/peerinfo_api.c:356 msgid "failed to transmit request (service down?)" msgstr "" "se produjo un fallo al transmitir la petición (¿está caido el servicio?)" # Miguel: "Failed to receive" también aquí está traducido como # "no se obtuvo respuesta" por claridad. #: src/peerinfo/peerinfo_api.c:506 msgid "Failed to receive response from `PEERINFO' service." msgstr "" "No se obtuvo respuesta del servicio de información de pares (PEERINFO)." #: src/peerinfo/peerinfo_api.c:547 src/peerinfo/peerinfo_api.c:566 #: src/peerinfo/peerinfo_api.c:581 src/peerinfo/peerinfo_api.c:592 #: src/peerinfo/peerinfo_api.c:603 msgid "Received invalid message from `PEERINFO' service." msgstr "" "Recibido mensaje no válido del servicio de información de pares (PEERINFO)." #: src/peerinfo/peerinfo_api.c:678 msgid "Timeout transmitting iteration request to `PEERINFO' service." msgstr "" "Petición de transmisión de iteración de expiración al servicio de " "información de pares (PEERINFO)." #: src/peerinfo/peerinfo_api_notify.c:268 #, c-format msgid "Could not connect to `%s' service.\n" msgstr "No se pudo conectar al servicio %s.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:232 #, fuzzy, c-format msgid "%sPeer `%s'\n" msgstr "Par «%s»\n" #: src/peerinfo-tool/gnunet-peerinfo.c:239 #, c-format msgid "\tExpires: %s \t %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:428 #, fuzzy, c-format msgid "Failure: Did not receive %s\n" msgstr "Se produjo un fallo al resolver «%s»: %s\n" #: src/peerinfo-tool/gnunet-peerinfo.c:436 #, fuzzy, c-format msgid "Failure: Received invalid %s\n" msgstr "recibido mensaje '%s' no válido: %s.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:445 #, fuzzy, c-format msgid "Failed to write HELLO with %u bytes to file `%s'\n" msgstr "Se produjo un fallo al procesar «HELLO» en el fichero «%s»\n" #: src/peerinfo-tool/gnunet-peerinfo.c:458 #, c-format msgid "Wrote %s HELLO containing %u addresses with %u bytes to file `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:522 #, c-format msgid "Failure adding HELLO: %s\n" msgstr "Fallo añadiendo «HELLO»: %s\n" #: src/peerinfo-tool/gnunet-peerinfo.c:633 #, fuzzy, c-format msgid "Service `%s' is not running, please start GNUnet\n" msgstr "El servicio «%s» no está ejecutandose\n" #: src/peerinfo-tool/gnunet-peerinfo.c:654 src/util/gnunet-scrypt.c:224 #, c-format msgid "Loading hostkey from `%s' failed.\n" msgstr "La carga de la clave de la máquina desde «%s» ha fallado.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:745 #, c-format msgid "I am peer `%s'.\n" msgstr "Yo soy el par «%s».\n" #: src/peerinfo-tool/gnunet-peerinfo.c:789 msgid "don't resolve host names" msgstr "no resolver nombres de máquina" #: src/peerinfo-tool/gnunet-peerinfo.c:792 msgid "output only the identity strings" msgstr "mostrar únicamente las cadenas de identidad" #: src/peerinfo-tool/gnunet-peerinfo.c:795 msgid "include friend-only information" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:798 msgid "output our own identity only" msgstr "muestra únicamente nuestra propia identidad" #: src/peerinfo-tool/gnunet-peerinfo.c:801 msgid "list all known peers" msgstr "mostrar todos los pares conocidos" #: src/peerinfo-tool/gnunet-peerinfo.c:804 msgid "dump hello to file" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:807 msgid "also output HELLO uri(s)" msgstr "también mostrar las URI de «HELLO»" #: src/peerinfo-tool/gnunet-peerinfo.c:810 msgid "add given HELLO uri to the database" msgstr "añade la URI de «HELLO» dada a la base de datos" #: src/peerinfo-tool/gnunet-peerinfo.c:821 msgid "Print information about peers." msgstr "Imprimir información sobre los pares." #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:105 #: src/transport/gnunet-service-transport_plugins.c:128 #, c-format msgid "Starting transport plugins `%s'\n" msgstr "Iniciando los módulos de transporte «%s»\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:109 #: src/transport/gnunet-service-transport_plugins.c:133 #, c-format msgid "Loading `%s' transport plugin\n" msgstr "Cargando el módulo de transporte «%s»\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:129 #: src/transport/gnunet-service-transport_plugins.c:165 #, c-format msgid "Failed to load transport plugin for `%s'\n" msgstr "Se produjo un fallo al cargar el módulo del transporte para «%s»\n" #: src/postgres/postgres.c:59 #, c-format msgid "`%s:%s' failed at %s:%d with error: %s" msgstr "«%s:%s» falló en %s:%d con error: %s" #: src/postgres/postgres.c:148 #, c-format msgid "Unable to initialize Postgres: %s" msgstr "No se pudo inicializar Postgres: %s" #: src/psycstore/gnunet-service-psycstore.c:200 #, fuzzy msgid "Failed to store membership information!\n" msgstr "Se produjo un fallo al retomar la operación de publicación «%s»: %s\n" #: src/psycstore/gnunet-service-psycstore.c:224 #, fuzzy msgid "Failed to test membership!\n" msgstr "¡Se produjo un fallo al configurar el túnel mesh!\n" #: src/psycstore/gnunet-service-psycstore.c:246 #, fuzzy msgid "Failed to store fragment!\n" msgstr "Se produjo un fallo al iniciar el demonio: %s\n" #: src/psycstore/gnunet-service-psycstore.c:272 #, fuzzy msgid "Failed to get fragment!\n" msgstr "¡Se produjo un fallo al obtener la clave de máquina!\n" #: src/psycstore/gnunet-service-psycstore.c:299 #, fuzzy msgid "Failed to get message!\n" msgstr "¡Se produjo un fallo al obtener la clave de máquina!\n" #: src/psycstore/gnunet-service-psycstore.c:328 #, fuzzy msgid "Failed to get message fragment!\n" msgstr "Se produjo un fallo al procesar un mensaje «HELLO»: mal formado\n" #: src/psycstore/gnunet-service-psycstore.c:356 #, fuzzy msgid "Failed to get master counters!\n" msgstr "¡Se produjo un fallo al obtener la clave de máquina!\n" #: src/psycstore/gnunet-service-psycstore.c:392 #: src/psycstore/gnunet-service-psycstore.c:465 msgid "Tried to set invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:408 #, fuzzy msgid "Failed to begin modifying state!\n" msgstr "Se produjo un fallo al cargar el estado: %s\n" #: src/psycstore/gnunet-service-psycstore.c:431 #, fuzzy, c-format msgid "Unknown operator: %c\n" msgstr "Operación desconocida '%s'\n" #: src/psycstore/gnunet-service-psycstore.c:441 #, fuzzy msgid "Failed to end modifying state!\n" msgstr "Se produjo un fallo al cargar el estado: %s\n" #: src/psycstore/gnunet-service-psycstore.c:479 #, fuzzy msgid "Failed to begin synchronizing state!\n" msgstr "¡Se produjo un fallo al obtener la clave de máquina!\n" #: src/psycstore/gnunet-service-psycstore.c:495 #, fuzzy msgid "Failed to end synchronizing state!\n" msgstr "¡Se produjo un fallo al obtener la clave de máquina!\n" #: src/psycstore/gnunet-service-psycstore.c:515 #: src/psycstore/gnunet-service-psycstore.c:534 #, fuzzy msgid "Failed to reset state!\n" msgstr "¡Se produjo un fallo al obtener la clave de máquina!\n" #: src/psycstore/gnunet-service-psycstore.c:557 #: src/psycstore/gnunet-service-psycstore.c:608 msgid "Tried to get invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:584 #: src/psycstore/gnunet-service-psycstore.c:623 #, fuzzy msgid "Failed to get state variable!\n" msgstr "¡Se produjo un fallo al obtener la clave de máquina!\n" #: src/psycstore/plugin_psycstore_sqlite.c:60 #, fuzzy, c-format msgid "`%s' failed at %s:%d with error: %s (%d)\n" msgstr "«%s» falló en %s: %d con el error: %s\n" #: src/psycstore/plugin_psycstore_sqlite.c:253 #, fuzzy, c-format msgid "" "Error preparing SQL query: %s\n" " %s\n" msgstr "Error leyendo de «%s»: %s\n" #: src/psycstore/plugin_psycstore_sqlite.c:276 #, fuzzy, c-format msgid "" "Error executing SQL query: %s\n" " %s\n" msgstr "Error abriendo fichero «%s»: %s\n" #: src/psycstore/plugin_psycstore_sqlite.c:1796 #, fuzzy msgid "SQLite database running\n" msgstr "Base de datos sqlite ejecutándose\n" #: src/pt/gnunet-daemon-pt.c:482 msgid "Failed to pack DNS request. Dropping.\n" msgstr "Se produjo un fallo al empaquetar la petición DNS. Omitiendo.\n" #: src/pt/gnunet-daemon-pt.c:488 msgid "# DNS requests mapped to VPN" msgstr "# Peticiones DNS asociadas a la VPN" #: src/pt/gnunet-daemon-pt.c:541 msgid "# DNS records modified" msgstr "# Registros DNS modificados" #: src/pt/gnunet-daemon-pt.c:717 msgid "# DNS replies intercepted" msgstr "# Respuestas DNS interceptadas" #: src/pt/gnunet-daemon-pt.c:723 msgid "Failed to parse DNS request. Dropping.\n" msgstr "Se produjo un fallo al procesar la petición DNS. Omitiendo.\n" #: src/pt/gnunet-daemon-pt.c:826 msgid "# DNS requests dropped (timeout)" msgstr "# Peticiones DNS omitidas (expiradas)" #: src/pt/gnunet-daemon-pt.c:883 msgid "# DNS requests intercepted" msgstr "# Peticiones DNS interceptadas" #: src/pt/gnunet-daemon-pt.c:888 #, fuzzy msgid "# DNS requests dropped (DNS mesh channel down)" msgstr "# Peticiones DNS omitidas (túnel mesh DNS caído)" #: src/pt/gnunet-daemon-pt.c:896 msgid "# DNS requests dropped (malformed)" msgstr "# Peticiones DNS omitidas (mal formadas)" #: src/pt/gnunet-daemon-pt.c:969 msgid "# DNS replies received" msgstr "# Respuestas DNS recibidas" #: src/pt/gnunet-daemon-pt.c:985 msgid "# DNS replies dropped (too late?)" msgstr "# Respuestas DNS (¿demasiado tarde?)" #: src/pt/gnunet-daemon-pt.c:1261 src/pt/gnunet-daemon-pt.c:1270 #: src/pt/gnunet-daemon-pt.c:1290 src/pt/gnunet-daemon-pt.c:1301 #: src/pt/gnunet-daemon-pt.c:1310 #, c-format msgid "Failed to connect to %s service. Exiting.\n" msgstr "Se produjo un fallo al conectar con el servicio %s. Saliendo.\n" #: src/pt/gnunet-daemon-pt.c:1347 msgid "Daemon to run to perform IP protocol translation to GNUnet" msgstr "" "Demonio a ejecutar para realizar la traducción de protocolo IP a GNUnet" #: src/regex/gnunet-daemon-regexprofiler.c:270 #: src/regex/gnunet-regex-simulation-profiler.c:659 #, c-format msgid "%s service is lacking key configuration settings (%s). Exiting.\n" msgstr "" "El servicio %s carece de opciones de configuración de clave (%s). " "Saliendo.\n" #: src/regex/gnunet-daemon-regexprofiler.c:380 msgid "Daemon to announce regular expressions for the peer using mesh." msgstr "Demonio para anunciar expresiones regulares para el par usando mesh." #: src/regex/gnunet-regex-profiler.c:1288 msgid "No configuration file given. Exiting\n" msgstr "No se ha introducido ningún fichero de configuración. Saliendo\n" #: src/regex/gnunet-regex-profiler.c:1299 #, fuzzy msgid "Configuration option \"regex_prefix\" missing. Exiting\n" msgstr "Falta una opción de configuración (regex_prefix). Saliendo\n" #: src/regex/gnunet-regex-profiler.c:1328 #: src/regex/gnunet-regex-simulation-profiler.c:622 #, c-format msgid "No policy directory specified on command line. Exiting.\n" msgstr "" "No se ha especificado una política de directorios en la línea de comandos. " "Saliendo.\n" #: src/regex/gnunet-regex-profiler.c:1334 #: src/regex/gnunet-regex-simulation-profiler.c:629 #, c-format msgid "Specified policies directory does not exist. Exiting.\n" msgstr "Las políticas de directorio especificadas no existen. Saliendo.\n" #: src/regex/gnunet-regex-profiler.c:1341 #, c-format msgid "No files found in `%s'\n" msgstr "No se han encontrado ficheros en «%s»\n" #: src/regex/gnunet-regex-profiler.c:1350 msgid "No search strings file given. Exiting.\n" msgstr "No se ha proporcionado un fichero de cadenas de búsqueda. Saliendo.\n" #: src/regex/gnunet-regex-profiler.c:1370 msgid "Error loading search strings. Exiting.\n" msgstr "Error cargando cadenas de búsqueda. Saliendo.\n" #: src/regex/gnunet-regex-profiler.c:1455 msgid "name of the file for writing statistics" msgstr "nombre del fichero para escribir las estadísticas" #: src/regex/gnunet-regex-profiler.c:1458 #, fuzzy msgid "wait TIMEOUT before ending the experiment" msgstr "" "esperar «TIMEOUT» antes de considerar que una coincidencia de cadenas como " "fallida" #: src/regex/gnunet-regex-profiler.c:1461 msgid "directory with policy files" msgstr "" #: src/regex/gnunet-regex-profiler.c:1464 #, fuzzy msgid "name of file with input strings" msgstr "nombre del fichero para escribir las estadísticas" #: src/regex/gnunet-regex-profiler.c:1467 #, fuzzy msgid "name of file with hosts' names" msgstr "nombre del fichero para escribir las estadísticas" #: src/regex/gnunet-regex-profiler.c:1479 msgid "Profiler for regex" msgstr "Perfilador para expresiones regulares." #: src/regex/gnunet-regex-simulation-profiler.c:689 msgid "name of the table to write DFAs" msgstr "nombre de la tabla para escribir los DFA" # WTF??? #: src/regex/gnunet-regex-simulation-profiler.c:692 msgid "maximum path compression length" msgstr "longitud de la máxima compresión de rutas" #: src/regex/gnunet-regex-simulation-profiler.c:705 msgid "Profiler for regex library" msgstr "Analizador de rendimiento para la biblioteca de expresiones regulares" #: src/regex/regex_api.c:131 #, fuzzy, c-format msgid "Regex `%s' is too long!\n" msgstr "El servicio «%s» no está ejecutandose\n" #: src/revocation/gnunet-revocation.c:126 #, fuzzy, c-format msgid "Key `%s' is valid\n" msgstr "Formato del pseudónimo '%s' no es válido.\n" # Miguel: ¿Quizá fuese mejor «Se ha parado el servicio x»? # Esto también es aplicable a las siguientes traducciones. #: src/revocation/gnunet-revocation.c:131 #, fuzzy, c-format msgid "Key `%s' has been revoked\n" msgstr "El servicio «%s» se ha parado.\n" #: src/revocation/gnunet-revocation.c:137 #, fuzzy msgid "Internal error\n" msgstr "Error interno." #: src/revocation/gnunet-revocation.c:163 #, c-format msgid "Key for ego `%s' is still valid, revocation failed (!)\n" msgstr "" #: src/revocation/gnunet-revocation.c:168 #, fuzzy msgid "Revocation failed (!)\n" msgstr "La operación ha fallado.\n" #: src/revocation/gnunet-revocation.c:173 #, c-format msgid "Key for ego `%s' has been successfully revoked\n" msgstr "" #: src/revocation/gnunet-revocation.c:178 msgid "Revocation successful.\n" msgstr "" #: src/revocation/gnunet-revocation.c:183 msgid "Internal error, key revocation might have failed\n" msgstr "" #: src/revocation/gnunet-revocation.c:294 #, c-format msgid "Revocation certificate for `%s' stored in `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:324 #, fuzzy, c-format msgid "Ego `%s' not found.\n" msgstr "Módulo «%s» no encontrado\n" #: src/revocation/gnunet-revocation.c:345 #, c-format msgid "Error: revocation certificate in `%s' is not for `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:365 msgid "Revocation certificate ready\n" msgstr "" #: src/revocation/gnunet-revocation.c:375 msgid "Revocation certificate not ready, calculating proof of work\n" msgstr "" #: src/revocation/gnunet-revocation.c:407 #, fuzzy, c-format msgid "Public key `%s' malformed\n" msgstr "El bloque del tipo %u está mal formado\n" #: src/revocation/gnunet-revocation.c:421 msgid "" "Testing and revoking at the same time is not allowed, only executing test.\n" msgstr "" #: src/revocation/gnunet-revocation.c:441 #, fuzzy msgid "No filename to store revocation certificate given.\n" msgstr "Se produjo un fallo al leer la lista de amigos de «%s»\n" #: src/revocation/gnunet-revocation.c:463 #, fuzzy, c-format msgid "Failed to read revocation certificate from `%s'\n" msgstr "Se produjo un fallo al leer la lista de amigos de «%s»\n" #: src/revocation/gnunet-revocation.c:488 #, fuzzy msgid "No action specified. Nothing to do.\n" msgstr "Ninguna interfaz especificada, usando la marcada por defecto\n" #: src/revocation/gnunet-revocation.c:504 msgid "use NAME for the name of the revocation file" msgstr "" #: src/revocation/gnunet-revocation.c:507 msgid "" "revoke the private key associated for the the private key associated with " "the ego NAME " msgstr "" #: src/revocation/gnunet-revocation.c:510 msgid "actually perform revocation, otherwise we just do the precomputation" msgstr "" #: src/revocation/gnunet-revocation.c:513 msgid "test if the public key KEY has been revoked" msgstr "" #: src/revocation/gnunet-service-revocation.c:272 #, fuzzy msgid "Duplicate revocation received from peer. Ignored.\n" msgstr "Opciones de paquete IPv4 recibidas. Ignoradas.\n" #: src/revocation/gnunet-service-revocation.c:434 #, c-format msgid "Error computing revocation set union with %s\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:486 msgid "SET service crashed, terminating revocation service\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:812 #, fuzzy msgid "Could not open revocation database file!" msgstr "No se pudo conectar con el almacén de datos." #: src/scalarproduct/gnunet-scalarproduct.c:225 #, fuzzy msgid "You must specify at least one message ID to check!\n" msgstr "Debes especificar un fichero a inspeccionar.\n" #: src/scalarproduct/gnunet-scalarproduct.c:232 msgid "This program needs a session identifier for comparing vectors.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:239 msgid "Please give a session key for --input_key!\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:251 #, c-format msgid "" "Tried to set initiator mode, as peer ID was given. However, `%s' is not a " "valid peer identifier.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:278 #: src/scalarproduct/gnunet-scalarproduct.c:314 #, fuzzy, c-format msgid "Could not convert `%s' to int32_t.\n" msgstr "No se pudo conectar al servicio %s.\n" #: src/scalarproduct/gnunet-scalarproduct.c:286 msgid "Need elements to compute the vectorproduct, got none.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:346 #, fuzzy, c-format msgid "Could not convert `%s' to integer.\n" msgstr "No se pudo conectar al servicio %s.\n" #: src/scalarproduct/gnunet-scalarproduct.c:407 msgid "" "A comma separated list of elements to compare as vector with our remote peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:410 msgid "" "A comma separated mask to select which elements should actually be compared." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:413 msgid "" "[Optional] peer to calculate our scalarproduct with. If this parameter is " "not given, the service will wait for a remote peer to compute the request." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:416 msgid "Transaction ID shared with peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:425 msgid "Calculate the Vectorproduct with a GNUnet peer." msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:541 #, fuzzy, c-format msgid "Client (%p) disconnected from us.\n" msgstr "Desconectado de %s\n" # Miguel: Si no me equivoco, "status result" es un # resultado de tipo estado. #: src/scalarproduct/gnunet-service-scalarproduct.c:613 #: src/scalarproduct/gnunet-service-scalarproduct.c:702 #, fuzzy, c-format msgid "Could not send message to client (%p)!\n" msgstr "No se pudo mandar el resultado (estado) al cliente\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:619 #, c-format msgid "Sending session-end notification to client (%p) for session %s\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:712 #, c-format msgid "Sent result to client (%p), this session (%s) has ended!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:766 #: src/scalarproduct/gnunet-service-scalarproduct.c:855 msgid "Could not send service-response message via mesh!)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1028 #, c-format msgid "Failed to communicate with `%s', scalar product calculation aborted.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1099 #: src/scalarproduct/gnunet-service-scalarproduct.c:1208 #, fuzzy msgid "Transmitting service request.\n" msgstr "Reiniciando el servicio «%s»\n" # Miguel: Si no me equivoco, "list result" es un resultado # de tipo lista. #: src/scalarproduct/gnunet-service-scalarproduct.c:1108 #, fuzzy msgid "Could not send service-request multipart message to channel!\n" msgstr "No se pudo mandar el resultado (lista) al cliente\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1147 #, fuzzy, c-format msgid "Successfully created new channel to peer (%s)!\n" msgstr "Conectado satisfactoriamente a «%s»\n" # Miguel: Si no me equivoco, "list result" es un resultado # de tipo lista. #: src/scalarproduct/gnunet-service-scalarproduct.c:1217 #, fuzzy msgid "Could not send message to channel!\n" msgstr "No se pudo mandar el resultado (lista) al cliente\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1274 #, fuzzy msgid "Too short message received from client!\n" msgstr "# peticiones «PUT» recibidas de clientes" #: src/scalarproduct/gnunet-service-scalarproduct.c:1287 #, fuzzy msgid "Invalid message received from client, session information incorrect!\n" msgstr "Mensaje «%s» no válido recibido de la lista de máquinas en «%s»\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1298 #, c-format msgid "" "Duplicate session information received, cannot create new session with key `" "%s'\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1318 #, c-format msgid "" "Got client-request-session with key %s, preparing channel to remote " "service.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1354 #, c-format msgid "Creating new channel for session with key %s.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1399 #, c-format msgid "" "Got client-responder-session with key %s and a matching service-request-" "session set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1409 #, c-format msgid "" "Got client-responder-session with key %s but NO matching service-request-" "session set, queuing element for later use.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1439 #, fuzzy, c-format msgid "New incoming channel from peer %s.\n" msgstr "Desconectado de %s\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1471 #, c-format msgid "Peer disconnected, terminating session %s with peer (%s)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1672 #: src/scalarproduct/gnunet-service-scalarproduct.c:1814 #, c-format msgid "Got session with key %s and a matching element set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1681 #: src/scalarproduct/gnunet-service-scalarproduct.c:1821 #, c-format msgid "Got session with key %s without a matching element set, queueing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1771 #, c-format msgid "" "Got message with duplicate session key (`%s'), ignoring service request.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2014 msgid "Shutting down, initiating cleanup.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2100 #, fuzzy msgid "Connect to MESH failed\n" msgstr "Conexión fallida (¿bug?)\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:2104 #, fuzzy msgid "Mesh initialized\n" msgstr "Conexión fallida\n" #: src/scalarproduct/scalarproduct_api.c:246 #, fuzzy msgid "# SUC responder result messages received" msgstr "# mensajes de detención de migración recibidos" #: src/scalarproduct/scalarproduct_api.c:300 #, fuzzy msgid "# bytes sent to scalarproduct" msgstr "# bytes mandados al almacén de datos" #: src/scalarproduct/scalarproduct_api.c:345 #: src/scalarproduct/scalarproduct_api.c:440 #, fuzzy msgid "Failed to connect to the scalarproduct service\n" msgstr "Se produjo un fallo al conectar con el servicio de chat\n" #: src/scalarproduct/scalarproduct_api.c:353 #: src/scalarproduct/scalarproduct_api.c:448 #, fuzzy msgid "Failed to send a message to the statistics service\n" msgstr "¡Se produjo un fallo al conectar al servicio de estadísticas!\n" #: src/scalarproduct/scalarproduct_api.c:387 #: src/scalarproduct/scalarproduct_api.c:485 #, fuzzy msgid "Failed to send a message to the scalarproduct service\n" msgstr "Se produjo un fallo al enviar una petición al servicio de transporte\n" #: src/secretsharing/gnunet-secretsharing-profiler.c:538 msgid "dkg start delay" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:541 msgid "dkg timeout" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:544 msgid "threshold" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:547 msgid "also profile decryption" msgstr "" #: src/set/gnunet-service-set.c:1431 #, fuzzy msgid "Could not connect to mesh service\n" msgstr "¡No se pudo conectar al servicio %s!\n" # Miguel: Conjunto resta. #: src/set/gnunet-set-ibf-profiler.c:221 msgid "number of element in set A-B" msgstr "número de elementos en el conjunto A-B" #: src/set/gnunet-set-ibf-profiler.c:224 msgid "number of element in set B-A" msgstr "número de elementos en el conjunto B-A" # Miguel: Conjunto unión. #: src/set/gnunet-set-ibf-profiler.c:227 msgid "number of common elements in A and B" msgstr "número de elementos comunes en A y B" # Miguel: "hash" me tiene un poco frito. ¿Existe alguna traducción buena? #: src/set/gnunet-set-ibf-profiler.c:230 msgid "hash num" msgstr "número de hash" #: src/set/gnunet-set-ibf-profiler.c:233 msgid "ibf size" msgstr "tamaño ibf" #: src/set/gnunet-set-profiler.c:295 msgid "oeration to execute" msgstr "" #: src/statistics/gnunet-service-statistics.c:280 #, c-format msgid "Loading %llu bytes of statistics from `%s'\n" msgstr "Cargando %llu bytes de estadísticas de «%s»\n" #: src/statistics/gnunet-service-statistics.c:346 #, c-format msgid "Wrote %llu bytes of statistics to `%s'\n" msgstr "Escritos %llu bytes de estadísticas a «%s»\n" #: src/statistics/gnunet-statistics.c:140 msgid "Failed to obtain statistics.\n" msgstr "Se produjo un fallo al obtener las estadísticas.\n" #: src/statistics/gnunet-statistics.c:142 #, c-format msgid "Failed to obtain statistics from host `%s:%llu'\n" msgstr "" "Se produjo un fallo al obtener las estadísticas de la máquina «%s:%llu»\n" #: src/statistics/gnunet-statistics.c:189 msgid "Missing argument: subsystem \n" msgstr "Falta el parámetro: subsistema\n" #: src/statistics/gnunet-statistics.c:195 msgid "Missing argument: name\n" msgstr "Falta el argumento: nombre\n" #: src/statistics/gnunet-statistics.c:226 #, c-format msgid "No subsystem or name given\n" msgstr "No se proporcionó un subsistema o un nombre\n" #: src/statistics/gnunet-statistics.c:234 #, c-format msgid "Failed to initialize watch routine\n" msgstr "Se produjo un fallo al inicializar la rutina de visualización\n" #: src/statistics/gnunet-statistics.c:261 #, c-format msgid "Trying to connect to remote host, but service `%s' is not running\n" msgstr "" "Intentando conectar con máquina remota, pero el servicio «%s» no se está " "ejecutando\n" #: src/statistics/gnunet-statistics.c:269 #, c-format msgid "A port is required to connect to host `%s'\n" msgstr "Se necesita un puerto para conectar con la máquina «%s»\n" #: src/statistics/gnunet-statistics.c:276 #, c-format msgid "A port has to be between 1 and 65535 to connect to host `%s'\n" msgstr "Un puerto debe estar entre 1 y 65534 para conectar a la máquina «%s»\n" #: src/statistics/gnunet-statistics.c:308 #, c-format msgid "Invalid argument `%s'\n" msgstr "Parámetro no válido «%s»\n" #: src/statistics/gnunet-statistics.c:334 msgid "limit output to statistics for the given NAME" msgstr "limita la salida de estadísticas para el nombre (NAME) dado" #: src/statistics/gnunet-statistics.c:337 msgid "make the value being set persistent" msgstr "hacer el valor persistente" #: src/statistics/gnunet-statistics.c:340 msgid "limit output to the given SUBSYSTEM" msgstr "límite de salida para el subsistema (SUBSYSTEM) dado" #: src/statistics/gnunet-statistics.c:343 msgid "just print the statistics value" msgstr "imprime el valor de las estadísticas" #: src/statistics/gnunet-statistics.c:346 msgid "watch value continuously" msgstr "visualiza el valor continuamente" #: src/statistics/gnunet-statistics.c:349 msgid "connect to remote host" msgstr "conectar a equipo remoto" #: src/statistics/gnunet-statistics.c:352 msgid "port for remote host" msgstr "puerto del equipo remoto" #: src/statistics/gnunet-statistics.c:364 msgid "Print statistics about GNUnet operations." msgstr "Imprime estadísticas acerca de las operaciones de GNUnet." #: src/statistics/statistics_api.c:519 msgid "Could not save some persistent statistics\n" msgstr "No se pudieron guardar algunas estadísticas persistentes\n" #: src/statistics/statistics_api.c:1090 msgid "" "Failed to receive acknowledgement from statistics service, some statistics " "might have been lost!\n" msgstr "" "¡No se ha recibido el reconocimiento del servicio de estadísticas, algunas " "estadísticas se pueden haber perdido!\n" #: src/testbed/generate-underlay-topology.c:223 msgid "Need atleast 2 arguments\n" msgstr "" #: src/testbed/generate-underlay-topology.c:228 msgid "Database filename missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:235 #, fuzzy msgid "Topology string missing\n" msgstr "falta una opción" #: src/testbed/generate-underlay-topology.c:240 #, fuzzy, c-format msgid "Invalid topology: %s\n" msgstr "Parámetro no válido «%s»\n" #: src/testbed/generate-underlay-topology.c:252 #, c-format msgid "An argument is missing for given topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:258 #, fuzzy, c-format msgid "Invalid argument `%s' given as topology argument\n" msgstr "Parámetro no válido «%s»\n" #: src/testbed/generate-underlay-topology.c:266 #, fuzzy, c-format msgid "Filename argument missing for topology `%s'\n" msgstr "¡Falló mientras se esperaba la configuración topológica!\n" #: src/testbed/generate-underlay-topology.c:280 #, c-format msgid "Second argument for topology `%s' is missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:286 #, fuzzy, c-format msgid "Invalid argument `%s'; expecting unsigned int\n" msgstr "Argumento no válido para '%s' en %s:%d.\n" #: src/testbed/generate-underlay-topology.c:335 #: src/testbed/gnunet-testbed-profiler.c:293 msgid "create COUNT number of peers" msgstr "crea «COUNT» número de pares" #: src/testbed/generate-underlay-topology.c:344 msgid "" "Generates SQLite3 database representing a given underlay topology.\n" "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" "The following options are available for TOPO followed by TOPOOPTS if " "applicable:\n" "\t LINE\n" "\t RING\n" "\t RANDOM \n" "\t SMALL_WORLD \n" "\t SMALL_WORLD_RING \n" "\t CLIQUE\n" "\t 2D_TORUS\n" "\t SCALE_FREE \n" "\t FROM_FILE \n" "TOPOOPTS:\n" "\t num_rnd_links: The number of random links\n" "\t cap: the maximum number of links a node can have\n" "\t m: the number of links a node should have while joining the network\n" "\t filename: the path of the file which contains topology information\n" "NOTE: the format of the above file is descibed here: https://www.gnunet.org/" "content/topology-file-format\n" msgstr "" #: src/testbed/gnunet-daemon-latency-logger.c:325 msgid "Daemon to log latency values of connections to neighbours" msgstr "" #: src/testbed/gnunet-daemon-testbed-blacklist.c:264 msgid "" "Daemon to restrict incoming transport layer connections during testbed " "deployments" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:235 src/testing/list-keys.c:50 #: src/testing/testing.c:293 src/util/gnunet-ecc.c:217 #, c-format msgid "Incorrect hostkey file format: %s\n" msgstr "El fichero de máquinas no tiene el formato correcto: %s\n" #: src/testbed/gnunet-daemon-testbed-underlay.c:474 msgid "Daemon to restrict underlay network in testbed deployments" msgstr "" #: src/testbed/gnunet-service-testbed_cpustatus.c:730 #, c-format msgid "" "Cannot open %s for writing load statistics. Not logging load statistics\n" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1015 #, fuzzy msgid "Misconfiguration (can't connect to the ARM service)" msgstr "¡Se produjo un fallo al conectar con el servicio dv!\n" #: src/testbed/gnunet-service-testbed_peers.c:1021 #, fuzzy msgid "Request doesn't fit into a message" msgstr "no imprime mensajes de estado" # Miguel: ¿Es mejor «ya que» que «porque» o «debido al apagado»? #: src/testbed/gnunet-service-testbed_peers.c:1059 #, fuzzy, c-format msgid "%s service can't be started because ARM is shutting down" msgstr "Petición ignorada porque el ARM se está apagando.\n" #: src/testbed/gnunet_testbed_mpi_spawn.c:125 #, fuzzy msgid "Waiting for child to exit.\n" msgstr "Esperando a los pares para conectar (%u ciclos restantes)...\n" #: src/testbed/gnunet_testbed_mpi_spawn.c:247 #, fuzzy, c-format msgid "Spawning process `%s'\n" msgstr "Iniciando el proceso auxiliar (HELPER) «%s»\n" #: src/testbed/gnunet-testbed-profiler.c:267 #, fuzzy, c-format msgid "Exiting as the number of peers is %u\n" msgstr "El número máximo de conexiones es %u\n" #: src/testbed/gnunet-testbed-profiler.c:296 msgid "tolerate COUNT number of continious timeout failures" msgstr "tolerar un número «COUNT» de continuas expiraciones de plazo" #: src/testbed/gnunet-testbed-profiler.c:299 msgid "" "run profiler in non-interactive mode where upon testbed setup the profiler " "does not wait for a keystroke but continues to run until a termination " "signal is received" msgstr "" #: src/testbed/testbed_api_hosts.c:415 #, c-format msgid "Hosts file %s not found\n" msgstr "El fichero de máquinas %s no fue encontrado\n" #: src/testbed/testbed_api_hosts.c:423 #, c-format msgid "Hosts file %s has no data\n" msgstr "El archivo de máquinas %s no tiene datos\n" #: src/testbed/testbed_api_hosts.c:430 #, c-format msgid "Hosts file %s cannot be read\n" msgstr "El archivo de máquinas %s no puede leerse\n" #: src/testbed/testbed_api_hosts.c:570 #, c-format msgid "The function %s is only available when compiled with (--with-ll)\n" msgstr "" #: src/testbed/testbed_api_hosts.c:1586 #, c-format msgid "Adding host %u failed with error: %s\n" msgstr "No se pudo añadir la máquina %u por el error: %s\n" #: src/testbed/testbed_api_testbed.c:819 msgid "Linking controllers failed. Exiting" msgstr "Los controladores de enlazado fallaron. Saliendo" #: src/testbed/testbed_api_testbed.c:988 #, c-format msgid "Host registration failed for a host. Error: %s\n" msgstr "El registro de máquinas falló para una máquina. Error: %s\n" #: src/testbed/testbed_api_testbed.c:1054 msgid "Controller crash detected. Shutting down.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1143 #, c-format msgid "Host %s cannot start testbed\n" msgstr "La máquina %s no puede comenzar la batería de pruebas\n" #: src/testbed/testbed_api_testbed.c:1147 msgid "Testbed cannot be started on localhost\n" msgstr "La batería de pruebas no se puede iniciar en localhost\n" #: src/testbed/testbed_api_testbed.c:1185 msgid "Cannot start the master controller" msgstr "No se puede iniciar el controlador maestro" #: src/testbed/testbed_api_testbed.c:1203 msgid "Shutting down testbed due to timeout while setup.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1263 #, fuzzy msgid "No hosts loaded from LoadLeveler. Need at least one host\n" msgstr "No se han cargado máquinas. Se necesita al menos una máquina.\n" #: src/testbed/testbed_api_testbed.c:1275 msgid "No hosts loaded. Need at least one host\n" msgstr "No se han cargado máquinas. Se necesita al menos una máquina.\n" #: src/testbed/testbed_api_testbed.c:1299 msgid "Specified topology must be supported by testbed" msgstr "" "La topología especificada debe estar soportada por la batería de pruebas" #: src/testbed/testbed_api_testbed.c:1349 #, c-format msgid "" "Maximum number of edges a peer can have in a scale free topology cannot be " "more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_testbed.c:1365 #, c-format msgid "" "The number of edges that can established when adding a new node to scale " "free topology cannot be more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_topology.c:960 #, c-format msgid "Topology file %s not found\n" msgstr "El fichero de topología %s no fue encontrado\n" #: src/testbed/testbed_api_topology.c:966 #, c-format msgid "Topology file %s has no data\n" msgstr "El fichero de topología %s no tiene datos\n" #: src/testbed/testbed_api_topology.c:973 #, c-format msgid "Topology file %s cannot be read\n" msgstr "El fichero de topología %s no puede ser leido\n" #: src/testbed/testbed_api_topology.c:995 #, c-format msgid "Failed to read peer index from toology file: %s" msgstr "" "Se produjo un fallo al leer el índice de pares del archivo de topología: %s" #: src/testbed/testbed_api_topology.c:1004 #: src/testbed/testbed_api_topology.c:1028 #, c-format msgid "Value in given topology file: %s out of range\n" msgstr "Valor en el fichero de topología dato: %s está fuera de rango\n" #: src/testbed/testbed_api_topology.c:1010 #: src/testbed/testbed_api_topology.c:1034 #, c-format msgid "Failed to read peer index from topology file: %s" msgstr "" "Se produjo un fallo al leer índice de pares del fichero de topología: %s" #: src/testbed/testbed_api_topology.c:1016 #: src/testbed/testbed_api_topology.c:1040 msgid "Topology file needs more peers than given ones\n" msgstr "El fichero de topología necesita más pares que los dados\n" #: src/testbed/testbed_api_topology.c:1074 #, c-format msgid "Ignoring to connect peer %u to peer %u\n" msgstr "Ignorando conexión del par %u al par %u\n" #: src/testing/gnunet-testing.c:173 #, c-format msgid "Could not extract hostkey %u (offset too large?)\n" msgstr "" "No se pudo extraer la clave de máquina %u (¿desplazamiento demasiado " "grande?)\n" #: src/testing/gnunet-testing.c:258 #, c-format msgid "Unknown command, use 'q' to quit or 'r' to restart peer\n" msgstr "Comando desconocido, use «q» para salir o «r» para reiniciar el par\n" #: src/testing/gnunet-testing.c:355 msgid "create unique configuration files" msgstr "crear ficheros de configuración únicos" #: src/testing/gnunet-testing.c:357 msgid "extract hostkey file from pre-computed hostkey list" msgstr "" "extraer los ficheros de claves de máquinas de una lista pre-computada de " "claves de máquinas" #: src/testing/gnunet-testing.c:359 msgid "" "number of unique configuration files to create, or number of the hostkey to " "extract" msgstr "" "número de ficheros de configuración únicos o claves de máquina a crear, o el " "número de claves de máquina a extraer" #: src/testing/gnunet-testing.c:361 msgid "configuration template" msgstr "plantilla de configuración" #: src/testing/gnunet-testing.c:363 msgid "run the given service, wait on stdin for 'r' (restart) or 'q' (quit)" msgstr "" #: src/testing/gnunet-testing.c:376 msgid "Command line tool to access the testing library" msgstr "" "Herramienta de línea de comandos para acceder a la biblioteca de pruebas" #: src/testing/list-keys.c:90 #, fuzzy msgid "list COUNT number of keys" msgstr "crea «COUNT» número de pares" #: src/testing/list-keys.c:93 msgid "skip COUNT number of keys in the beginning" msgstr "" #: src/testing/testing.c:277 #, c-format msgid "Hostkeys file not found: %s\n" msgstr "El fichero de máquinas no fue encontrado: %s\n" #: src/testing/testing.c:718 #, c-format msgid "Key number %u does not exist\n" msgstr "El número de clave %u no existe\n" # Miguel: "testbed" lo he traducido como batería de pruebas, pero # no es una traducción muy literal. #: src/testing/testing.c:1157 #, c-format msgid "" "You attempted to create a testbed with more than %u hosts. Please " "precompute more hostkeys first.\n" msgstr "" "Se ha intentado crear una batería de pruebas con más de %u máquinas. Por " "favor, pre-compute más claves de máquinas primero.\n" #: src/testing/testing.c:1166 #, c-format msgid "Failed to initialize hostkey for peer %u\n" msgstr "" "Se produjo un fallo al inicializar la clave de la máquina desde el par %u\n" #: src/testing/testing.c:1176 #, fuzzy msgid "PRIVATE_KEY option in PEER section missing in configuration\n" msgstr "¡Falta la opción «%s» en la sección «%s» de la configuración!\n" #: src/testing/testing.c:1189 msgid "Failed to create configuration for peer (not enough free ports?)\n" msgstr "" "Se produjo un fallo al crear la configuración para el par (¿no hay " "suficientes puertos libres?)\n" #: src/testing/testing.c:1203 #, fuzzy, c-format msgid "Cannot open hostkey file `%s': %s\n" msgstr "No se pudo abrir el fichero de claves de máquina: %s\n" #: src/testing/testing.c:1215 #, c-format msgid "Failed to write hostkey file for peer %u: %s\n" msgstr "" "Se produjo un fallo al escribir la clave de la máquina para el par %u: %s\n" #: src/testing/testing.c:1240 #, c-format msgid "Failed to write configuration file `%s' for peer %u: %s\n" msgstr "" "Se produjo un fallo al escribir el fichero de configuración «%s» para el par " "%u: %s\n" #: src/testing/testing.c:1342 #, c-format msgid "Failed to start `%s': %s\n" msgstr "Se produjo un fallo al arrancar «%s»: %s\n" #: src/testing/testing.c:1706 #, c-format msgid "Failed to load configuration from %s\n" msgstr "Se produjo un fallo al cargar la configuración de %s\n" #: src/topology/friends.c:100 #, fuzzy, c-format msgid "Syntax error in FRIENDS file at offset %llu, skipping bytes `%.*s'.\n" msgstr "" "Error de sintaxis en el fichero de la lista negra en el desplazamiento %llu, " "omitiendo bytes «%s».\n" #: src/topology/friends.c:154 #, fuzzy, c-format msgid "Directory for file `%s' does not seem to be writable.\n" msgstr "«gnunet-arm» o «ssh» no parecen terminar.\n" #: src/topology/gnunet-daemon-topology.c:255 msgid "# peers blacklisted" msgstr "# pares en la lista negra" #: src/topology/gnunet-daemon-topology.c:388 msgid "# connect requests issued to transport" msgstr "# peticiones de conexión requeridas al servicio de transporte" #: src/topology/gnunet-daemon-topology.c:728 #: src/topology/gnunet-daemon-topology.c:813 msgid "# friends connected" msgstr "# amigos conectados" #: src/topology/gnunet-daemon-topology.c:993 msgid "Failed to connect to core service, can not manage topology!\n" msgstr "" "¡Se produjo un fallo al conectar con el servicio principal, no se puede " "gestionar la topología!\n" #: src/topology/gnunet-daemon-topology.c:1022 #, c-format msgid "Found myself `%s' in friend list (useless, ignored)\n" msgstr "Me he encontrado «%s» en mi lista de amigos (inútil, ignorado)\n" #: src/topology/gnunet-daemon-topology.c:1029 #, c-format msgid "Found friend `%s' in configuration\n" msgstr "Encontrado amigo «%s» en la configuración\n" #: src/topology/gnunet-daemon-topology.c:1050 msgid "Encountered errors parsing friends list!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1052 msgid "# friends in configuration" msgstr "# amigos en configuración" #: src/topology/gnunet-daemon-topology.c:1057 msgid "" "Fewer friends specified than required by minimum friend count. Will only " "connect to friends.\n" msgstr "" "Menos amigos especificados que los requeridos por el contador mínimo de " "amigos. Sólo me conectaré a amigos.\n" #: src/topology/gnunet-daemon-topology.c:1063 msgid "" "More friendly connections required than target total number of connections.\n" msgstr "" "Más conexiones amistosas requeridas que el número objetivo total de " "conexiones.\n" #: src/topology/gnunet-daemon-topology.c:1094 msgid "# HELLO messages received" msgstr "# mensajes «HELLO» recibidos" # gossiped?? #: src/topology/gnunet-daemon-topology.c:1151 msgid "# HELLO messages gossipped" msgstr "# Mensajes «HELLO» rumoreados" #: src/topology/gnunet-daemon-topology.c:1290 msgid "GNUnet topology control (maintaining P2P mesh and F2F constraints)" msgstr "" "Control de topología de GNUnet (manteniendo las restricciones del mesh de " "P2P y de F2F)" #: src/transport/gnunet-service-transport_blacklist.c:271 #, fuzzy, c-format msgid "Adding blacklisting entry for peer `%s'\n" msgstr "Añadiendo «%s» sin direcciones para el par «%s»\n" #: src/transport/gnunet-service-transport_blacklist.c:279 #, c-format msgid "Adding blacklisting entry for peer `%s':`%s'\n" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:464 #: src/transport/gnunet-service-transport_blacklist.c:745 msgid "# disconnects due to blacklist" msgstr "# desconexiones debido a la lista negra" #: src/transport/gnunet-service-transport.c:220 #, fuzzy msgid "# bytes payload discarded due to not connected peer" msgstr "# bytes de «payload» descartados debido a par no conectado" #: src/transport/gnunet-service-transport.c:424 msgid "# bytes total received" msgstr "# total de bytes recibidos" #: src/transport/gnunet-service-transport.c:515 msgid "# bytes payload received" msgstr "# bytes de «payload» recibidos" #: src/transport/gnunet-service-transport.c:686 #, fuzzy, c-format msgid "Could not obtain a valid network for `%s' %s (%s)\n" msgstr "Imposible obtener IP para la interfaz '%s' usando '%s'.\n" #: src/transport/gnunet-service-transport.c:733 #, c-format msgid "" "Address or session unknown: failed to update properties for peer `%s' plugin " "`%s' address `%s' session %p\n" msgstr "" #: src/transport/gnunet-service-transport.c:1084 #, fuzzy msgid "Transport service is lacking key configuration settings. Exiting.\n" msgstr "" "El servicio de transporte carece de opciones de configuración de clave. " "Saliendo.\n" #: src/transport/gnunet-service-transport_clients.c:432 #, c-format msgid "Dropping message of type %u and size %u, have %u/%u messages pending\n" msgstr "" "Mensaje omitido de tipo %u y tamaño %u, hay %u/%u mensajes pendientes\n" #: src/transport/gnunet-service-transport_clients.c:439 msgid "# messages dropped due to slow client" msgstr "# mensajes omitidos debido a un cliente lento" #: src/transport/gnunet-service-transport_clients.c:596 #, c-format msgid "Rejecting control connection from peer `%s', which is not me!\n" msgstr "¡Rechazando conexión de control del par «%s», que no soy yo!\n" #: src/transport/gnunet-service-transport_clients.c:737 msgid "# bytes payload dropped (other peer was not connected)" msgstr "# bytes de «payload» omitidos (el otro par no estaba conectado)" #: src/transport/gnunet-service-transport_clients.c:770 #, fuzzy, c-format msgid "Blacklist refuses connection attempt to peer `%s'\n" msgstr "Se produjo un fallo al conectar con «%s»\n" #: src/transport/gnunet-service-transport_clients.c:776 #, fuzzy, c-format msgid "Blacklist allows connection attempt to peer `%s'\n" msgstr "Se produjo un fallo al conectar con «%s»\n" #: src/transport/gnunet-service-transport_clients.c:801 msgid "# REQUEST CONNECT messages received" msgstr "# mensajes «REQUEST CONNECT» recibidos" #: src/transport/gnunet-service-transport_clients.c:815 #, fuzzy, c-format msgid "Received a request connect message for peer `%s'\n" msgstr "Recibido último mensaje para %s\n" #: src/transport/gnunet-service-transport_clients.c:826 #, fuzzy msgid "# REQUEST DISCONNECT messages received" msgstr "# mensajes «REQUEST CONNECT» recibidos" #: src/transport/gnunet-service-transport_clients.c:840 #, fuzzy, c-format msgid "Received a request disconnect message for peer `%s'\n" msgstr "Recibido último mensaje para %s\n" #: src/transport/gnunet-service-transport_hello.c:181 msgid "# refreshed my HELLO" msgstr "# refrescos de mi «HELLO»" #: src/transport/gnunet-service-transport_neighbours.c:1095 msgid "# DISCONNECT messages sent" msgstr "# Mensajes «DISCONNECT» enviados" #: src/transport/gnunet-service-transport_neighbours.c:1220 #: src/transport/gnunet-service-transport_neighbours.c:1629 msgid "# bytes in message queue for other peers" msgstr "# bytes en la cola de mensajes para otros pares" #: src/transport/gnunet-service-transport_neighbours.c:1225 msgid "# messages transmitted to other peers" msgstr "# mensajes transmitidos a otros pares" #: src/transport/gnunet-service-transport_neighbours.c:1230 msgid "# transmission failures for messages to other peers" msgstr "# fallos de transmisión en mensajes a otros pares" #: src/transport/gnunet-service-transport_neighbours.c:1287 msgid "# messages timed out while in transport queue" msgstr "# mensajes expirados mientras estaban en la cola de transporte" #: src/transport/gnunet-service-transport_neighbours.c:1343 msgid "# keepalives sent" msgstr "# «keepalives» enviados" #: src/transport/gnunet-service-transport_neighbours.c:1376 msgid "# KEEPALIVE messages discarded (peer unknown)" msgstr "# Mensajes «KEEPALIVE» descartados (par desconocido)" #: src/transport/gnunet-service-transport_neighbours.c:1384 msgid "# KEEPALIVE messages discarded (no session)" msgstr "# mensajes «KEEPALIVE» descartados (no hay sesión)" #: src/transport/gnunet-service-transport_neighbours.c:1431 msgid "# KEEPALIVE_RESPONSE messages discarded (not connected)" msgstr "# mensajes «KEEPALIVE_RESPONSE» descartados (no conectado)" #: src/transport/gnunet-service-transport_neighbours.c:1440 msgid "# KEEPALIVE_RESPONSE messages discarded (not expected)" msgstr "# Mensajes «KEEPALIVE_RESPONSE» descartados (no esperado)" #: src/transport/gnunet-service-transport_neighbours.c:1448 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (address changed)" msgstr "# mensajes «KEEPALIVE_RESPONSE» descartados (no conectado)" #: src/transport/gnunet-service-transport_neighbours.c:1456 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (wrong nonce)" msgstr "# mensajes «KEEPALIVE_RESPONSE» descartados (no conectado)" #: src/transport/gnunet-service-transport_neighbours.c:1534 msgid "# messages discarded due to lack of neighbour record" msgstr "# mensajes descartados debido a la falta de registro vecinal" #: src/transport/gnunet-service-transport_neighbours.c:1568 msgid "# bandwidth quota violations by other peers" msgstr "# violaciones de la cuota de ancho de banda por otros pares" # throttling? #: src/transport/gnunet-service-transport_neighbours.c:1584 msgid "# ms throttling suggested" msgstr "# ms de impulso sugeridos" #: src/transport/gnunet-service-transport_neighbours.c:1678 #, fuzzy, c-format msgid "" "Failed to send CONNECT message to peer `%s' using address `%s' session %p\n" msgstr "¡Se produjo un fallo al conectar al servicio de estadísticas!\n" #: src/transport/gnunet-service-transport_neighbours.c:1705 msgid "# Failed attempts to switch addresses (failed to send CONNECT CONT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1751 #, fuzzy msgid "# SESSION_CONNECT messages sent" msgstr "# Mensajes «DISCONNECT» enviados" #: src/transport/gnunet-service-transport_neighbours.c:1767 #, fuzzy, c-format msgid "Failed to transmit CONNECT message via plugin to %s\n" msgstr "Se produjo un fallo al transmitir un mensaje al servicio «%s».\n" #: src/transport/gnunet-service-transport_neighbours.c:1794 msgid "# Failed attempts to switch addresses (failed to send CONNECT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1844 #, c-format msgid "" "Failed to send CONNECT_ACK message to peer `%s' using address `%s' session " "%p\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1899 #, fuzzy msgid "# CONNECT_ACK messages sent" msgstr "# Mensajes «DISCONNECT» enviados" #: src/transport/gnunet-service-transport_neighbours.c:1914 #, fuzzy, c-format msgid "Failed to transmit CONNECT_ACK message via plugin to %s\n" msgstr "Se produjo un fallo al transmitir un mensaje al servicio «%s».\n" #: src/transport/gnunet-service-transport_neighbours.c:2192 #, fuzzy, c-format msgid "Blacklisting disapproved to connect to peer `%s'\n" msgstr "Se produjo un fallo al conectar con «%s»\n" #: src/transport/gnunet-service-transport_neighbours.c:2312 #, fuzzy msgid "# CONNECT messages received" msgstr "# mensajes «REQUEST CONNECT» recibidos" #: src/transport/gnunet-service-transport_neighbours.c:2317 #, c-format msgid "CONNECT request from peer `%s' ignored due impending shutdown\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2590 msgid "# Attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3012 #, fuzzy msgid "# Failed attempts to switch addresses (no response)" msgstr "Se produjo un fallo al procesar la petición DNS. Omitiendo.\n" #: src/transport/gnunet-service-transport_neighbours.c:3107 #, fuzzy msgid "# CONNECT_ACK messages received" msgstr "# mensajes «REQUEST CONNECT» recibidos" #: src/transport/gnunet-service-transport_neighbours.c:3115 msgid "# unexpected CONNECT_ACK messages (no peer)" msgstr "# Mensajes «CONNECT_ACK» inesperados (sin par)" #: src/transport/gnunet-service-transport_neighbours.c:3129 #: src/transport/gnunet-service-transport_neighbours.c:3164 msgid "# unexpected CONNECT_ACK messages (not ready)" msgstr "# Mensajes «CONNECT_ACK» inesperados (no estaba preparado)" #: src/transport/gnunet-service-transport_neighbours.c:3176 msgid "# unexpected CONNECT_ACK messages (waiting on ATS)" msgstr "# Mensajes «CONNECT_ACK» inesperados (esperando en el ATS)" #: src/transport/gnunet-service-transport_neighbours.c:3200 msgid "# Successful attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3208 msgid "# unexpected CONNECT_ACK messages (disconnecting)" msgstr "# Mensajes «CONNECT_ACK» inesperados (desconectando)" #: src/transport/gnunet-service-transport_neighbours.c:3396 #, fuzzy msgid "# SESSION_ACK messages received" msgstr "# mensajes SET QUOTA recibidos" #: src/transport/gnunet-service-transport_neighbours.c:3424 #, fuzzy msgid "# unexpected SESSION_ACK messages" msgstr "# Mensajes «SESSION ACK» inesperados" #: src/transport/gnunet-service-transport_neighbours.c:3490 msgid "# SET QUOTA messages ignored (no such peer)" msgstr "# Mensajes «SET QUOTA» ignorados (no existe tal par)" #: src/transport/gnunet-service-transport_neighbours.c:3505 msgid "# disconnects due to quota of 0" msgstr "# desconexiones debido a una cuota de 0" #: src/transport/gnunet-service-transport_neighbours.c:3545 #, fuzzy msgid "# disconnect messages ignored (malformed)" msgstr "# mensajes de desconexión ignorados (formato antiguo)" #: src/transport/gnunet-service-transport_neighbours.c:3551 #, fuzzy msgid "# DISCONNECT messages received" msgstr "# mensajes «REQUEST CONNECT» recibidos" #: src/transport/gnunet-service-transport_neighbours.c:3560 msgid "# disconnect messages ignored (timestamp)" msgstr "# mensajes de desconexión ignorados (marca temporal)" #: src/transport/gnunet-service-transport_neighbours.c:3687 msgid "# disconnected from peer upon explicit request" msgstr "# desconexiones del par debido a una petición explícita" #: src/transport/gnunet-service-transport_plugins.c:120 msgid "Transport service is lacking NEIGHBOUR_LIMIT option.\n" msgstr "El servicio de transporte carece de la opción «NEIGHBOUR_LIMIT».\n" #: src/transport/gnunet-service-transport_plugins.c:178 #: src/transport/gnunet-service-transport_plugins.c:186 #: src/transport/gnunet-service-transport_plugins.c:194 #: src/transport/gnunet-service-transport_plugins.c:202 #: src/transport/gnunet-service-transport_plugins.c:210 #: src/transport/gnunet-service-transport_plugins.c:218 #: src/transport/gnunet-service-transport_plugins.c:226 #: src/transport/gnunet-service-transport_plugins.c:234 #: src/transport/gnunet-service-transport_plugins.c:242 #: src/transport/gnunet-service-transport_plugins.c:250 #: src/transport/gnunet-service-transport_plugins.c:258 #, fuzzy, c-format msgid "Missing function `%s' in transport plugin for `%s'\n" msgstr "Se produjo un fallo al cargar el módulo del transporte para «%s»\n" #: src/transport/gnunet-service-transport_plugins.c:265 #, fuzzy, c-format msgid "Did not load plugin `%s' due to missing functions\n" msgstr "Falló al cargar el plugin '%s' en %s:%d. Descargando plugin.\n" #: src/transport/gnunet-service-transport_validation.c:488 msgid "# address records discarded" msgstr "# registros de direcciones descartados" #: src/transport/gnunet-service-transport_validation.c:558 #, c-format msgid "" "Not transmitting `%s' with `%s', message too big (%u bytes!). This should " "not happen.\n" msgstr "" "No transmitiendo «%s» con «%s», mensaje demasiado grande (¡%u bytes!). Esto " "no debería suceder.\n" #: src/transport/gnunet-service-transport_validation.c:616 msgid "# PING without HELLO messages sent" msgstr "# Mensajes PING sin HELLO mandados" #: src/transport/gnunet-service-transport_validation.c:722 msgid "# address revalidations started" msgstr "# revalidaciones de direcciones iniciadas" #: src/transport/gnunet-service-transport_validation.c:1011 msgid "# PING message for different peer received" msgstr "# Mensajes PING recibidos para un par diferente" #: src/transport/gnunet-service-transport_validation.c:1062 #, fuzzy, c-format msgid "Plugin `%s' not available, cannot confirm having this address\n" msgstr "" "No confirmando el PING con dirección «%s» ya que no puedo confirmar tener " "esa dirección.\n" #: src/transport/gnunet-service-transport_validation.c:1072 msgid "# failed address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1075 #, c-format msgid "Address `%s' is not one of my addresses, not confirming PING\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1083 msgid "# successful address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1095 #, fuzzy, c-format msgid "" "Not confirming PING from peer `%s' with address `%s' since I cannot confirm " "having this address.\n" msgstr "" "No confirmando el PING con dirección «%s» ya que no puedo confirmar tener " "esa dirección.\n" #: src/transport/gnunet-service-transport_validation.c:1103 #, c-format msgid "Received a PING message with validation bug from `%s'\n" msgstr "Recibido un mensaje PING con un error de validación de «%s»\n" #: src/transport/gnunet-service-transport_validation.c:1157 #, fuzzy, c-format msgid "Failed to create PONG signature for peer `%s'\n" msgstr "Se produjo un fallo al crear la página para «%s»\n" #: src/transport/gnunet-service-transport_validation.c:1206 msgid "# PONGs unicast via reliable transport" msgstr "# unicast de PONG vía transporte confiable" #: src/transport/gnunet-service-transport_validation.c:1215 msgid "# PONGs multicast to all available addresses" msgstr "# multicast de PONG a todas las direcciones disponibles" #: src/transport/gnunet-service-transport_validation.c:1356 msgid "# PONGs dropped, no matching pending validation" msgstr "# PONG omitidos, no hay una validación pendiente coincidente" #: src/transport/gnunet-service-transport_validation.c:1371 msgid "# PONGs dropped, signature expired" msgstr "# Mensajes PONG omitidos, firma expirada" #: src/transport/gnunet-service-transport_validation.c:1493 #, fuzzy, c-format msgid "Validation received new %s message for peer `%s' with size %u\n" msgstr "Recibido último mensaje para %s\n" #: src/transport/gnunet-service-transport_validation.c:1500 #, c-format msgid "Adding `%s' without addresses for peer `%s'\n" msgstr "Añadiendo «%s» sin direcciones para el par «%s»\n" #: src/transport/gnunet-transport.c:367 #, c-format msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n" msgstr "Transmitidos %llu bytes/s (%llu bytes en %s)\n" #: src/transport/gnunet-transport.c:375 #, c-format msgid "Received %llu bytes/s (%llu bytes in %s)\n" msgstr "Recibidos %llu bytes/s (%llu bytes en %s)\n" #: src/transport/gnunet-transport.c:415 #, c-format msgid "Failed to connect to `%s'\n" msgstr "Se produjo un fallo al conectar con «%s»\n" #: src/transport/gnunet-transport.c:428 #, c-format msgid "Failed to resolve address for peer `%s'\n" msgstr "Se produjo un fallo al resolver la dirección para el par «%s»\n" # Miguel: La traducción no es literal, pero me parece más correcta # en castellano. #: src/transport/gnunet-transport.c:438 msgid "Failed to list connections, timeout occured\n" msgstr "No se pudieron listar las conexiones, expiró el plazo\n" #: src/transport/gnunet-transport.c:559 #, fuzzy, c-format msgid "" "Peer `%s' %s %s\n" "\t%s%s\n" "\t%s%s\n" "\t%s%s\n" msgstr "Par «%s»: %s %s\n" #: src/transport/gnunet-transport.c:586 #, fuzzy, c-format msgid "Peer `%s' %s `%s' \n" msgstr "Par «%s»: %s %s\n" #: src/transport/gnunet-transport.c:712 msgid "No transport plugins configured, peer will never communicate\n" msgstr "" "No hay módulos de transporte configurados, el par nunca se comunicará\n" #: src/transport/gnunet-transport.c:726 #, c-format msgid "No port configured for plugin `%s', cannot test it\n" msgstr "" "Ningún puerto fue configurado para el módulo «%s», no se puede probar\n" #: src/transport/gnunet-transport.c:789 #, c-format msgid "Transmitting %u bytes to %s\n" msgstr "Transmitiendo %u bytes a %s\n" #: src/transport/gnunet-transport.c:810 #, c-format msgid "Successfully connected to `%s'\n" msgstr "Conectado satisfactoriamente a «%s»\n" #: src/transport/gnunet-transport.c:834 #, c-format msgid "" "Successfully connected to `%s', starting to send benchmark data in %u Kb " "blocks\n" msgstr "" "Conectado satisfactoriamente a «%s», empezando a mandar datos de prueba en " "bloques de %u Kb\n" #: src/transport/gnunet-transport.c:865 #, fuzzy, c-format msgid "Successfully disconnected from `%s'\n" msgstr "Conectado satisfactoriamente a «%s»\n" #: src/transport/gnunet-transport.c:888 #, c-format msgid "Disconnected from peer `%s' while benchmarking\n" msgstr "Desconectado del par «%s» mientras probaba\n" #: src/transport/gnunet-transport.c:950 #, c-format msgid "Received %u bytes from %s\n" msgstr "Recibidos %u bytes de %s\n" #: src/transport/gnunet-transport.c:975 #, c-format msgid "Peer `%s': %s %s in state `%s' until %s\n" msgstr "" #: src/transport/gnunet-transport.c:986 #, c-format msgid "Peer `%s': %s %s\n" msgstr "Par «%s»: %s %s\n" #: src/transport/gnunet-transport.c:1197 src/transport/gnunet-transport.c:1222 msgid "Failed to send connect request to transport service\n" msgstr "" "Se produjo un fallo al enviar una petición de conexión al servicio de " "transporte\n" #: src/transport/gnunet-transport.c:1266 #, c-format msgid "" "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, " "%s, %s\n" msgstr "" "Múltiples operaciones introducidas. Por favor, seleccione únicamente una " "operación: %s, %s, %s, %s, %s, %s\n" #: src/transport/gnunet-transport.c:1274 #, c-format msgid "" "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s\n" msgstr "" "Ninguna operación introducida. Por favor, seleccione alguna operación: %s, " "%s, %s, %s, %s, %s\n" #: src/transport/gnunet-transport.c:1293 src/transport/gnunet-transport.c:1323 #: src/transport/gnunet-transport.c:1353 src/transport/gnunet-transport.c:1376 #: src/transport/gnunet-transport.c:1419 msgid "Failed to connect to transport service\n" msgstr "Se produjo un fallo al conectar con el servicio de transporte\n" #: src/transport/gnunet-transport.c:1302 src/transport/gnunet-transport.c:1332 #: src/transport/gnunet-transport.c:1362 msgid "Failed to send request to transport service\n" msgstr "Se produjo un fallo al enviar una petición al servicio de transporte\n" #: src/transport/gnunet-transport.c:1381 msgid "Starting to receive benchmark data\n" msgstr "Empezando a recibir datos de prueba\n" #: src/transport/gnunet-transport.c:1465 #, fuzzy msgid "print information for all peers (instead of only connected peers )" msgstr "Imprime información sobre los pares conectados." #: src/transport/gnunet-transport.c:1468 msgid "measure how fast we are receiving data from all peers (until CTRL-C)" msgstr "medir cómo de rápido recibimos datos de todos los pares (hasta CTRL-C)" #: src/transport/gnunet-transport.c:1471 msgid "connect to a peer" msgstr "conectar a un par" #: src/transport/gnunet-transport.c:1474 #, fuzzy msgid "disconnect to a peer" msgstr "conectar a un par" #: src/transport/gnunet-transport.c:1477 #, fuzzy msgid "print information for all pending validations " msgstr "Imprime información de los pares de GNUnet." # Miguel: ¿Quizá continuamente fuese mejor? #: src/transport/gnunet-transport.c:1480 #, fuzzy msgid "print information for all pending validations continously" msgstr "" "provee información sobre todas las conexiones actuales (de forma continua)" #: src/transport/gnunet-transport.c:1483 msgid "provide information about all current connections (once)" msgstr "provee información sobre todas las conexiones actuales (una vez)" #: src/transport/gnunet-transport.c:1489 msgid "" "provide information about all connects and disconnect events (continuously)" msgstr "" "provee información sobre todas los eventos de conexión y desconexión " "(continuamente)" #: src/transport/gnunet-transport.c:1491 msgid "do not resolve hostnames" msgstr "no resolver nombres de máquinas" #: src/transport/gnunet-transport.c:1493 msgid "peer identity" msgstr "identidad del par" #: src/transport/gnunet-transport.c:1495 msgid "send data for benchmarking to the other peer (until CTRL-C)" msgstr "enviar data para prueba a otro par (hasta CTRL-C)" #: src/transport/gnunet-transport.c:1498 msgid "test transport configuration (involves external server)" msgstr "probar configuración de transporte (requiere un servidor externo)" #: src/transport/gnunet-transport.c:1507 msgid "Direct access to transport service." msgstr "Acceso directo al servicio de transporte." #: src/transport/plugin_transport_bluetooth.c:621 #, fuzzy msgid "# Bluetooth ACKs sent" msgstr "# ACK WLAN enviados" #: src/transport/plugin_transport_bluetooth.c:640 #, fuzzy msgid "# Bluetooth messages defragmented" msgstr "# mensajes defragmentados" #: src/transport/plugin_transport_bluetooth.c:686 #: src/transport/plugin_transport_bluetooth.c:737 #: src/transport/plugin_transport_bluetooth.c:1942 #, fuzzy msgid "# Bluetooth sessions allocated" msgstr "# sesiones WLAN alojadas" #: src/transport/plugin_transport_bluetooth.c:837 #, fuzzy msgid "# Bluetooth message fragments sent" msgstr "# fragmentos de mensaje WLAN enviados" #: src/transport/plugin_transport_bluetooth.c:861 #, fuzzy msgid "# Bluetooth messages pending (with fragmentation)" msgstr "# mensajes WLAN pendientes (con fragmentación)" #: src/transport/plugin_transport_bluetooth.c:969 #: src/transport/plugin_transport_bluetooth.c:1054 #: src/transport/plugin_transport_bluetooth.c:1944 #, fuzzy msgid "# Bluetooth MAC endpoints allocated" msgstr "# MAC de destino WLAN alojadas" #: src/transport/plugin_transport_bluetooth.c:1307 #, fuzzy msgid "# HELLO messages received via Bluetooth" msgstr "# mensajes HELLO recibidos vía WLAN" #: src/transport/plugin_transport_bluetooth.c:1331 #, fuzzy msgid "# fragments received via Bluetooth" msgstr "# fragmentos recibidos vía WLAN" #: src/transport/plugin_transport_bluetooth.c:1341 #, fuzzy msgid "# ACKs received via Bluetooth" msgstr "# ACK recibidos vía WLAN" #: src/transport/plugin_transport_bluetooth.c:1401 #, fuzzy msgid "# Bluetooth DATA messages discarded due to CRC32 error" msgstr "# mensajes DATA WLAN descartados debido a un error en el CRC32" #: src/transport/plugin_transport_bluetooth.c:1512 #, fuzzy msgid "# DATA messages received via Bluetooth" msgstr "# mensajes «DATA» recibidos vía WLAN" #: src/transport/plugin_transport_bluetooth.c:1547 #, fuzzy msgid "# Bluetooth DATA messages processed" msgstr "# mensajes «DATA» WLAN procesados" #: src/transport/plugin_transport_bluetooth.c:1610 #, fuzzy msgid "# HELLO beacons sent via Bluetooth" msgstr "# «beacons HELLO» enviados vía WLAN" #: src/transport/plugin_transport_bluetooth.c:1723 #, fuzzy msgid "Bluetooth address with invalid size encountered\n" msgstr "Dirección WLAN con tamaño no válido encontrada\n" #: src/transport/plugin_transport_bluetooth.c:1923 #, fuzzy, c-format msgid "Helper binary `%s' not SUID, cannot run bluetooth transport\n" msgstr "" "El ejecutable auxiliar «%s» no tiene activado el bit SUID, no se puede " "ejecutar el transporte WLAN\n" #: src/transport/plugin_transport_http_client.c:1622 #, c-format msgid "Could not initialize curl multi handle, failed to start %s plugin!\n" msgstr "" "¡No se pudo inicializar el multi-manejador de curl, no se pudo iniciar el " "módulo %s!\n" #: src/transport/plugin_transport_http_client.c:1697 #: src/transport/plugin_transport_http_server.c:3007 #, c-format msgid "Shutting down plugin `%s'\n" msgstr "Finalizando el módulo «%s»\n" #: src/transport/plugin_transport_http_client.c:1722 #: src/transport/plugin_transport_http_server.c:3063 #, c-format msgid "Shutdown for plugin `%s' complete\n" msgstr "Finalización del módulo «%s» completa\n" #: src/transport/plugin_transport_http_client.c:1750 #: src/transport/plugin_transport_http_server.c:2907 #, c-format msgid "Maximum number of connections is %u\n" msgstr "El número máximo de conexiones es %u\n" #: src/transport/plugin_transport_http_server.c:1402 #, c-format msgid "" "Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data " "size %u\n" msgstr "" "Acceso desde la conexión %p (%u de %u) para «%s» «%s» URL «%s» con tamaño de " "los datos de subida %u\n" #: src/transport/plugin_transport_http_server.c:1663 #, c-format msgid "Accepting connection (%u of %u) from `%s'\n" msgstr "Aceptando conexión (%u de %u) desde «%s»\n" #: src/transport/plugin_transport_http_server.c:1671 #, c-format msgid "" "Server reached maximum number connections (%u), rejecting new connection\n" msgstr "" "El servidor ha alcanzado el número máximo de conexiones (%u), rechazando " "nueva conexión\n" #: src/transport/plugin_transport_http_server.c:1958 msgid "" "Could not create a new TLS certificate, program `gnunet-transport-" "certificate-creation' could not be started!\n" msgstr "" "¡No se pudo crear un certificado TLS nuevo, el programa «gnunet-transport-" "certificate-creation» no pudo ser iniciado!\n" #: src/transport/plugin_transport_http_server.c:1982 #, fuzzy, c-format msgid "No usable TLS certificate found and creating one at `%s/%s' failed!\n" msgstr "" "¡No se encontró ningún certificado TLS útil y se produjo un fallo al crear " "uno!\n" #: src/transport/plugin_transport_http_server.c:2405 msgid "Require valid port number for service in configuration!\n" msgstr "¡Se necesita un puerto válido para el servicio en la configuración!\n" #: src/transport/plugin_transport_http_server.c:2437 src/util/service.c:698 #, c-format msgid "Failed to resolve `%s': %s\n" msgstr "Se produjo un fallo al resolver «%s»: %s\n" #: src/transport/plugin_transport_http_server.c:2454 src/util/service.c:715 #, c-format msgid "Failed to find %saddress for `%s'.\n" msgstr "No se encontró la dirección %s para «%s».\n" #: src/transport/plugin_transport_http_server.c:2565 #, c-format msgid "Found %u addresses to report to NAT service\n" msgstr "Encontradas %u direcciones para comunicar al servicio NAT\n" #: src/transport/plugin_transport_http_server.c:2637 msgid "Disabling IPv6 since it is not supported on this system!\n" msgstr "¡Deshabilitando IPv6 ya que no está soportado en este sistema!\n" #: src/transport/plugin_transport_http_server.c:2730 #, c-format msgid "IPv4 support is %s\n" msgstr "El soporte IPv4 es %s\n" #: src/transport/plugin_transport_http_server.c:2744 #, c-format msgid "IPv6 support is %s\n" msgstr "El soporte IPv6 es %s\n" #: src/transport/plugin_transport_http_server.c:2751 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n" msgstr "¡Ni IPv4 ni IPv6 están habilitadas! Corrija la configuración\n" #: src/transport/plugin_transport_http_server.c:2762 msgid "Port is required! Fix in configuration\n" msgstr "¡El puerto es necesario! Corrija la configuración\n" #: src/transport/plugin_transport_http_server.c:2769 #, c-format msgid "Using port %u\n" msgstr "Usando puerto %u\n" #: src/transport/plugin_transport_http_server.c:2784 #, c-format msgid "Specific IPv4 address `%s' in configuration file is invalid!\n" msgstr "" "¡La dirección IPv4 «%s» especificada en el fichero de configuración no es " "válida!\n" #: src/transport/plugin_transport_http_server.c:2794 #, c-format msgid "Binding to IPv4 address %s\n" msgstr "Asociando a la dirección IPv4 %s\n" #: src/transport/plugin_transport_http_server.c:2815 #, c-format msgid "Specific IPv6 address `%s' in configuration file is invalid!\n" msgstr "" "¡La dirección IPv6 «%s» especificada en el fichero de configuración no es " "válida!\n" #: src/transport/plugin_transport_http_server.c:2825 #, c-format msgid "Binding to IPv6 address %s\n" msgstr "Asociando a la dirección IPv6 %s\n" #: src/transport/plugin_transport_http_server.c:2877 #, c-format msgid "Using external hostname `%s'\n" msgstr "Usando nombre de máquina externo «%s»\n" #: src/transport/plugin_transport_http_server.c:2893 #, c-format msgid "Notifying transport only about hostname `%s'\n" msgstr "Notificando al transporte sólo el nombre de máquina «%s»\n" #: src/transport/plugin_transport_smtp.c:223 #, c-format msgid "Received malformed message via %s. Ignored.\n" msgstr "Mensaje mal formado recibido vía %s. Ignorado.\n" #: src/transport/plugin_transport_smtp.c:310 msgid "SMTP filter string to invalid, lacks ': '\n" msgstr "La cadena de filtrado SMTP no es válida, carece de «: »\n" # to should be too #: src/transport/plugin_transport_smtp.c:319 #, c-format msgid "SMTP filter string to long, capped to `%s'\n" msgstr "La cadena de filtrado SMTP es demasiado larga, recortada a «%s»\n" #: src/transport/plugin_transport_smtp.c:414 #: src/transport/plugin_transport_smtp.c:424 #: src/transport/plugin_transport_smtp.c:437 #: src/transport/plugin_transport_smtp.c:456 #: src/transport/plugin_transport_smtp.c:479 #: src/transport/plugin_transport_smtp.c:487 #: src/transport/plugin_transport_smtp.c:500 #: src/transport/plugin_transport_smtp.c:511 #, c-format msgid "SMTP: `%s' failed: %s.\n" msgstr "SMTP: «%s» falló: %s.\n" #: src/transport/plugin_transport_smtp.c:652 msgid "No email-address specified, can not start SMTP transport.\n" msgstr "" "No se ha especificado una dirección de correo, no se puede iniciar el " "transporte SMTP.\n" #: src/transport/plugin_transport_smtp.c:664 msgid "# bytes received via SMTP" msgstr "# bytes recibidos vía SMTP" #: src/transport/plugin_transport_smtp.c:665 msgid "# bytes sent via SMTP" msgstr "# bytes enviados vía SMTP" #: src/transport/plugin_transport_smtp.c:667 msgid "# bytes dropped by SMTP (outgoing)" msgstr "# bytes omitidos por SMTP (salientes)" #: src/transport/plugin_transport_tcp.c:555 #, c-format msgid "Unexpected address length: %u bytes\n" msgstr "Longitud de dirección inesperada: %u bytes\n" #: src/transport/plugin_transport_tcp.c:762 #: src/transport/plugin_transport_tcp.c:928 #: src/transport/plugin_transport_tcp.c:2005 #: src/transport/plugin_transport_tcp.c:2558 msgid "# TCP sessions active" msgstr "# Sesiones TCP activas" #: src/transport/plugin_transport_tcp.c:795 #: src/transport/plugin_transport_tcp.c:921 #: src/transport/plugin_transport_tcp.c:1009 #: src/transport/plugin_transport_tcp.c:1056 #: src/transport/plugin_transport_tcp.c:1219 #: src/transport/plugin_transport_tcp.c:1237 msgid "# bytes currently in TCP buffers" msgstr "# bytes actualmente en los buffer TCP" #: src/transport/plugin_transport_tcp.c:798 msgid "# bytes discarded by TCP (disconnect)" msgstr "# bytes descartados por TCP (desconectado)" #: src/transport/plugin_transport_tcp.c:1012 msgid "# bytes discarded by TCP (timeout)" msgstr "# bytes omitidos por TCP (expirados)" #: src/transport/plugin_transport_tcp.c:1059 msgid "# bytes transmitted via TCP" msgstr "# bytes recibidos vía TCP" #: src/transport/plugin_transport_tcp.c:1193 #, c-format msgid "Trying to send with invalid session %p\n" msgstr "Intentando enviar con una sesión no válida %p\n" #: src/transport/plugin_transport_tcp.c:1462 msgid "# requests to create session with invalid address" msgstr "" #: src/transport/plugin_transport_tcp.c:1567 msgid "# transport-service disconnect requests for TCP" msgstr "# peticiones de desconexión del servicio de transporte por TCP" #: src/transport/plugin_transport_tcp.c:2055 msgid "# TCP WELCOME messages received" msgstr "# Mensajes «WELCOME» TCP recibidos" #: src/transport/plugin_transport_tcp.c:2215 msgid "# bytes received via TCP" msgstr "# bytes recibidos vía TCP" #: src/transport/plugin_transport_tcp.c:2279 msgid "# network-level TCP disconnect events" msgstr "# eventos de desconexión TCP a nivel de red" #: src/transport/plugin_transport_tcp.c:2437 src/util/service.c:582 #: src/util/service.c:588 #, c-format msgid "Require valid port number for service `%s' in configuration!\n" msgstr "" "¡Se requiere un número de puerto válido para el servicio «%s» en la " "configuración!\n" #: src/transport/plugin_transport_tcp.c:2451 msgid "Failed to start service.\n" msgstr "Se produjo un fallo al iniciar el servicio.\n" #: src/transport/plugin_transport_tcp.c:2547 #, c-format msgid "TCP transport listening on port %llu\n" msgstr "Transporte TCP escuchando en el puerto %llu\n" #: src/transport/plugin_transport_tcp.c:2551 msgid "TCP transport not listening on any port (client only)\n" msgstr "Transporte TCP no escuchando en ningún puerto (únicamente cliente)\n" #: src/transport/plugin_transport_tcp.c:2554 #, c-format msgid "TCP transport advertises itself as being on port %llu\n" msgstr "El transporte TCP anuncia que está en el puerto %llu\n" #: src/transport/plugin_transport_udp_broadcasting.c:167 msgid "# IPv6 multicast HELLO beacons received via udp" msgstr "# beacons HELLO multicast IPv6 recibidos vía UDP" #: src/transport/plugin_transport_udp_broadcasting.c:210 msgid "# IPv4 broadcast HELLO beacons received via udp" msgstr "# beacons HELLO broadcast IPv4 recibidos vía UDP" #: src/transport/plugin_transport_udp_broadcasting.c:603 msgid "" "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:626 #, c-format msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n" msgstr "" "Se produjo un fallo al establecer la opción de «broadcast» IPv4 para el " "«socket» en el puerto %d\n" #: src/transport/plugin_transport_udp.c:1513 #, c-format msgid "" "Trying to create session for address of unexpected length %u (should be %u " "or %u)\n" msgstr "" #: src/transport/plugin_transport_udp.c:2602 #, c-format msgid "" "UDP could not transmit message to `%s': Network seems down, please check " "your network configuration\n" msgstr "" "UDP no pudo transmitir el mensaje a «%s»: La red parece caída, por favor, " "compruebe su configuración de red\n" #: src/transport/plugin_transport_udp.c:2616 #, fuzzy msgid "" "UDP could not transmit IPv6 message! Please check your network configuration " "and disable IPv6 if your connection does not have a global IPv6 address\n" msgstr "" "UDP no pudo transmitir el mensaje a «%s». Por favor, compruebe su " "configuración de red y deshabilite IPv6 si su conexión carece de una " "dirección IPv6 global\n" #: src/transport/plugin_transport_udp.c:2961 msgid "Failed to open UDP sockets\n" msgstr "Se produjo un fallo al abrir los «sockets» UDP\n" #: src/transport/plugin_transport_udp.c:3056 #, c-format msgid "Given `%s' option is out of range: %llu > %u\n" msgstr "La opción «%s» dada está fuera de rango: %llu > %u\n" #: src/transport/plugin_transport_udp.c:3097 #, c-format msgid "Invalid IPv6 address: `%s'\n" msgstr "Dirección IPv6 no válida: «%s»\n" #: src/transport/plugin_transport_udp.c:3168 #, fuzzy msgid "Failed to create network sockets, plugin failed\n" msgstr "Se produjo un fallo al crear una nueva firma" #: src/transport/plugin_transport_unix.c:1321 #, fuzzy, c-format msgid "Cannot create path to `%s'\n" msgstr "Se produjo un fallo al crear la página para «%s»\n" #: src/transport/plugin_transport_unix.c:1652 #, fuzzy msgid "No UNIXPATH given in configuration!\n" msgstr "¡%s mal formada «%s» dada en la configuración!\n" #: src/transport/plugin_transport_unix.c:1688 #, fuzzy msgid "Failed to open UNIX listen socket\n" msgstr "Se produjo un fallo al abrir los «sockets» UNIX\n" #: src/transport/plugin_transport_wlan.c:620 msgid "# WLAN ACKs sent" msgstr "# ACK WLAN enviados" #: src/transport/plugin_transport_wlan.c:639 msgid "# WLAN messages defragmented" msgstr "# mensajes WLAN defragmentados" #: src/transport/plugin_transport_wlan.c:688 #: src/transport/plugin_transport_wlan.c:772 #: src/transport/plugin_transport_wlan.c:1948 msgid "# WLAN sessions allocated" msgstr "# sesiones WLAN alojadas" #: src/transport/plugin_transport_wlan.c:876 msgid "# WLAN message fragments sent" msgstr "# fragmentos de mensaje WLAN enviados" #: src/transport/plugin_transport_wlan.c:900 msgid "# WLAN messages pending (with fragmentation)" msgstr "# mensajes WLAN pendientes (con fragmentación)" #: src/transport/plugin_transport_wlan.c:1008 #: src/transport/plugin_transport_wlan.c:1098 #: src/transport/plugin_transport_wlan.c:1950 msgid "# WLAN MAC endpoints allocated" msgstr "# MAC de destino WLAN alojadas" #: src/transport/plugin_transport_wlan.c:1302 msgid "# HELLO messages received via WLAN" msgstr "# mensajes HELLO recibidos vía WLAN" #: src/transport/plugin_transport_wlan.c:1326 msgid "# fragments received via WLAN" msgstr "# fragmentos recibidos vía WLAN" #: src/transport/plugin_transport_wlan.c:1336 msgid "# ACKs received via WLAN" msgstr "# ACK recibidos vía WLAN" #: src/transport/plugin_transport_wlan.c:1396 msgid "# WLAN DATA messages discarded due to CRC32 error" msgstr "# mensajes DATA WLAN descartados debido a un error en el CRC32" #: src/transport/plugin_transport_wlan.c:1518 msgid "# DATA messages received via WLAN" msgstr "# mensajes «DATA» recibidos vía WLAN" #: src/transport/plugin_transport_wlan.c:1553 msgid "# WLAN DATA messages processed" msgstr "# mensajes «DATA» WLAN procesados" #: src/transport/plugin_transport_wlan.c:1616 msgid "# HELLO beacons sent via WLAN" msgstr "# «beacons HELLO» enviados vía WLAN" #: src/transport/plugin_transport_wlan.c:1729 msgid "WLAN address with invalid size encountered\n" msgstr "Dirección WLAN con tamaño no válido encontrada\n" #: src/transport/plugin_transport_wlan.c:1929 #, c-format msgid "Helper binary `%s' not SUID, cannot run WLAN transport\n" msgstr "" "El ejecutable auxiliar «%s» no tiene activado el bit SUID, no se puede " "ejecutar el transporte WLAN\n" #: src/transport/transport_api.c:739 #, c-format msgid "Received unexpected message of type %u in %s:%u\n" msgstr "Recibido mensaje inesperado del tipo %u en %s:%u\n" #: src/transport/transport-testing.c:584 msgid "Failed to initialize testing library!\n" msgstr "¡Se produjo un fallo al inicializar la biblioteca de pruebas!\n" #: src/tun/regex.c:129 #, c-format msgid "Bad mask: %d\n" msgstr "" #: src/util/bio.c:170 src/util/bio.c:178 #, c-format msgid "Error reading `%s': %s" msgstr "Error leyendo «%s»: %s" #: src/util/bio.c:180 msgid "End of file" msgstr "Fin del fichero" #: src/util/bio.c:237 #, c-format msgid "Error reading length of string `%s'" msgstr "Se produjo un error leyendo la cadena «%s»" #: src/util/bio.c:247 #, c-format msgid "String `%s' longer than allowed (%u > %u)" msgstr "La cadena «%s» es mayor de lo permitido (%u > %u)" #: src/util/bio.c:293 #, c-format msgid "Serialized metadata `%s' larger than allowed (%u>%u)" msgstr "Los metadatos serializados «%s» son mayores de lo permitido (%u>%u)" #: src/util/bio.c:307 #, c-format msgid "Metadata `%s' failed to deserialize" msgstr "Se produjo un fallo al deserializar los metadatos «%s»" #: src/util/client.c:261 src/util/client.c:858 src/util/service.c:619 #, c-format msgid "UNIXPATH `%s' too long, maximum length is %llu\n" msgstr "" "La ruta tipo UNIX «%s» es demasiado larga, la longitud máxima es %llu\n" #: src/util/client.c:265 src/util/client.c:863 src/util/service.c:623 #, c-format msgid "Using `%s' instead\n" msgstr "Usando «%s» en su defecto\n" #: src/util/client.c:360 #, c-format msgid "" "Could not determine valid hostname and port for service `%s' from " "configuration.\n" msgstr "" "No se pudo determinar un nombre de máquina y un puerto válidos para el " "servicio «%s» a partir de la configuración.\n" #: src/util/client.c:368 #, c-format msgid "Need a non-empty hostname for service `%s'.\n" msgstr "Se necesita un nombre de máquina no vacío para el servicio «%s».\n" #: src/util/client.c:1008 #, fuzzy, c-format msgid "Could not connect to service `%s', configuration broken.\n" msgstr "No se pudo conectar con el servicio «%s», no debe estar corriendo.\n" #: src/util/client.c:1020 #, c-format msgid "Failure to transmit request to service `%s'\n" msgstr "Se produjo un fallo al transmitir la petición al servicio «%s»\n" #: src/util/client.c:1303 msgid "Could not submit request, not expecting to receive a response.\n" msgstr "" "No se pudo enviar correctamente la petición, no se espera recibir una " "respuesta.\n" #: src/util/common_logging.c:254 src/util/common_logging.c:1039 msgid "DEBUG" msgstr "DEPURACIÓN" #: src/util/common_logging.c:256 src/util/common_logging.c:1037 msgid "INFO" msgstr "INFORMACIÓN" #: src/util/common_logging.c:258 src/util/common_logging.c:1035 msgid "WARNING" msgstr "PELIGRO" #: src/util/common_logging.c:260 src/util/common_logging.c:1033 msgid "ERROR" msgstr "ERROR" #: src/util/common_logging.c:262 src/util/common_logging.c:1041 msgid "NONE" msgstr "NINGUNO" #: src/util/common_logging.c:391 #, c-format msgid "Failed to create or access directory for log file `%s'\n" msgstr "" "Se produjo un fallo al crear o acceder al directorio para el fichero de log " "«%s»\n" #: src/util/common_logging.c:817 #, c-format msgid "Message `%.*s' repeated %u times in the last %s\n" msgstr "Mensaje `%.*s» repetido %u veces en el último %s\n" #: src/util/common_logging.c:1042 msgid "INVALID" msgstr "NO VÃLIDO" #: src/util/common_logging.c:1157 msgid "unknown address" msgstr "dirección desconocida" #: src/util/common_logging.c:1196 msgid "invalid address" msgstr "dirección no válida" #: src/util/common_logging.c:1214 #, c-format msgid "Configuration fails to specify option `%s' in section `%s'!\n" msgstr "¡La configuración no especifica la opción «%s» en la sección «%s»!\n" #: src/util/common_logging.c:1235 #, c-format msgid "" "Configuration specifies invalid value for option `%s' in section `%s': %s\n" msgstr "" "La configuración especifica un valor no válido en la opción «%s» de la " "sección «%s»: %s\n" #: src/util/configuration.c:288 #, c-format msgid "Syntax error while deserializing in line %u\n" msgstr "Error de sintaxis en la línea %u mientras se deserializaba\n" #: src/util/configuration.c:996 #, c-format msgid "" "Configuration value '%s' for '%s' in section '%s' is not in set of legal " "choices\n" msgstr "" "El valor de configuración «%s» para «%s» de la sección «%s» no está dentro " "de las opciones legales\n" #: src/util/configuration.c:1066 #, c-format msgid "Recursive expansion suspected, aborting $-expansion for term `%s'\n" msgstr "" #: src/util/configuration.c:1098 #, fuzzy, c-format msgid "Missing closing `%s' in option `%s'\n" msgstr "Falta la opción «%s» para la operación «%s»\n" #: src/util/configuration.c:1172 #, c-format msgid "" "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined " "as an environmental variable\n" msgstr "" #: src/util/connection.c:423 #, c-format msgid "Access denied to `%s'\n" msgstr "Acceso denegado a «%s»\n" #: src/util/connection.c:438 #, c-format msgid "Accepting connection from `%s': %p\n" msgstr "Aceptando conexión desde «%s»: %p\n" #: src/util/connection.c:553 #, c-format msgid "" "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n" msgstr "" "Se produjo un fallo al establecer la conexión TCP a «%s:%u», no quedan " "direcciones por probar.\n" #: src/util/connection.c:751 src/util/connection.c:919 #, c-format msgid "Trying to connect to `%s' (%p)\n" msgstr "Intentando conectar a «%s» (%p)\n" #: src/util/connection.c:910 #, c-format msgid "Attempt to connect to `%s' failed\n" msgstr "El intento de conectar a «%s» falló\n" #: src/util/container_bloomfilter.c:531 #, c-format msgid "" "Size of file on disk is incorrect for this Bloom filter (want %llu, have " "%llu)\n" msgstr "" "El tamaño del fichero en disco es incorrecto para este «Bloom " "filter» (esperado %llu, tiene %llu)\n" #: src/util/crypto_ecc.c:702 src/util/crypto_ecc.c:740 #: src/util/crypto_ecc.c:858 src/util/crypto_ecc.c:896 #, c-format msgid "Could not acquire lock on file `%s': %s...\n" msgstr "No se pudo bloquear el fichero «%s»: %s...\n" #: src/util/crypto_ecc.c:707 src/util/crypto_ecc.c:863 msgid "Creating a new private key. This may take a while.\n" msgstr "Generando una clave privada nueva. Esto puede tomar un tiempo.\n" #: src/util/crypto_ecc.c:744 src/util/crypto_ecc.c:900 msgid "This may be ok if someone is currently generating a private key.\n" msgstr "" "Esto puede estar bien si alguien está actualmente generando una clave " "privada.\n" #: src/util/crypto_ecc.c:774 src/util/crypto_ecc.c:930 #, c-format msgid "" "When trying to read key file `%s' I found %u bytes but I need at least %u.\n" msgstr "" "Cuando se intentaba leer el fichero de claves «%s» se encontraron %u bytes " "pero al menos %u son necesarios.\n" #: src/util/crypto_ecc.c:778 src/util/crypto_ecc.c:934 msgid "This may be ok if someone is currently generating a key.\n" msgstr "" "Esto puede ser correcto si alguien está actualmente generando una clave de " "máquina.\n" #: src/util/crypto_ecc.c:1016 #, fuzzy msgid "Could not load peer's private key\n" msgstr "No se pudo acceder a la clave de máquina.\n" #: src/util/crypto_ecc.c:1120 #, c-format msgid "ECC signing failed at %s:%d: %s\n" msgstr "El firmado ECC falló en %s:%d: %s\n" #: src/util/crypto_ecc.c:1170 #, fuzzy, c-format msgid "EdDSA signing failed at %s:%d: %s\n" msgstr "El firmado ECC falló en %s:%d: %s\n" #: src/util/crypto_ecc.c:1244 #, fuzzy, c-format msgid "ECDSA signature verification failed at %s:%d: %s\n" msgstr "La verificación de la firma RSA fallo en %s:%d: %s\n" #: src/util/crypto_ecc.c:1301 #, fuzzy, c-format msgid "EdDSA signature verification failed at %s:%d: %s\n" msgstr "La verificación de la firma RSA fallo en %s:%d: %s\n" #: src/util/crypto_random.c:284 #, c-format msgid "libgcrypt has not the expected version (version %s is required).\n" msgstr "libgcrypt no tiene la versión esperada (se necesita la versión %s).\n" #: src/util/disk.c:1184 #, c-format msgid "Expected `%s' to be a directory!\n" msgstr "¡Se esperaba que «%s» fuera un directorio!\n" #: src/util/disk.c:1546 src/util/service.c:1318 #, c-format msgid "Cannot obtain information about user `%s': %s\n" msgstr "No se pudo obtener información acerca del usuario «%s»: %s\n" #: src/util/getopt.c:568 #, c-format msgid "%s: option `%s' is ambiguous\n" msgstr "%s: la opción «%s» es ambigua\n" #: src/util/getopt.c:592 #, c-format msgid "%s: option `--%s' does not allow an argument\n" msgstr "%s: la opción «--%s» no permite un parámetro\n" #: src/util/getopt.c:597 #, c-format msgid "%s: option `%c%s' does not allow an argument\n" msgstr "%s: la opción «%c%s» no permite un parámetro\n" #: src/util/getopt.c:614 src/util/getopt.c:781 #, c-format msgid "%s: option `%s' requires an argument\n" msgstr "%s: la opción «%s» requiere un parámetro\n" #: src/util/getopt.c:643 #, c-format msgid "%s: unrecognized option `--%s'\n" msgstr "%s: opción no reconocida «--%s»\n" #: src/util/getopt.c:647 #, c-format msgid "%s: unrecognized option `%c%s'\n" msgstr "%s: opción no reconocida «%c%s»\n" #: src/util/getopt.c:672 #, c-format msgid "%s: illegal option -- %c\n" msgstr "%s: opción ilegal -- %c\n" #: src/util/getopt.c:674 #, c-format msgid "%s: invalid option -- %c\n" msgstr "%s: opción no válida -- %c\n" #: src/util/getopt.c:702 src/util/getopt.c:829 #, c-format msgid "%s: option requires an argument -- %c\n" msgstr "%s: la opción requiere un parámetro -- %c\n" #: src/util/getopt.c:750 #, c-format msgid "%s: option `-W %s' is ambiguous\n" msgstr "%s: la opción «-W %s» es ambigua\n" #: src/util/getopt.c:768 #, c-format msgid "%s: option `-W %s' does not allow an argument\n" msgstr "%s: la opción «-W %s» no permite un parámetro\n" #: src/util/getopt.c:933 #, c-format msgid "Use %s to get a list of options.\n" msgstr "Use %s para obtener una lista de opciones.\n" #: src/util/getopt_helpers.c:84 #, c-format msgid "" "Arguments mandatory for long options are also mandatory for short options.\n" msgstr "" "Los parámetros obligatorios para las opciones largas también lo son para sus " "versiones cortas.\n" #: src/util/getopt_helpers.c:268 src/util/getopt_helpers.c:326 #, c-format msgid "You must pass a number to the `%s' option.\n" msgstr "Tienes que introducir un número en la opción «%s».\n" #: src/util/getopt_helpers.c:298 #, c-format msgid "You must pass relative time to the `%s' option.\n" msgstr "Debes introducir un tiempo relativo en la opción «%s».\n" #: src/util/gnunet-config.c:90 #, c-format msgid "--section argument is required\n" msgstr "el parámetro --section es necesario\n" #: src/util/gnunet-config.c:133 #, c-format msgid "--option argument required to set value\n" msgstr "el parámetro --option es necesario para establecer un valor\n" #: src/util/gnunet-config.c:160 msgid "obtain option of value as a filename (with $-expansion)" msgstr "" "obtener la opción del valor como un nombre de fichero (con expansión del $)" #: src/util/gnunet-config.c:163 msgid "name of the section to access" msgstr "nombre de la sección a la que acceder" #: src/util/gnunet-config.c:166 msgid "name of the option to access" msgstr "nombre de la opción a la que acceder" #: src/util/gnunet-config.c:169 msgid "value to set" msgstr "valor a establecer" #: src/util/gnunet-config.c:178 msgid "Manipulate GNUnet configuration files" msgstr "Manipular ficheros de configuración de GNUnet" #: src/util/gnunet-ecc.c:75 #, c-format msgid "Failed to open `%s': %s\n" msgstr "Se produjo un fallo al abrir «%s»: %s\n" #: src/util/gnunet-ecc.c:81 #, c-format msgid "Generating %u keys, please wait" msgstr "Generando %u claves, por favor, espere" #: src/util/gnunet-ecc.c:97 #, c-format msgid "" "\n" "Failed to write to `%s': %s\n" msgstr "" "\n" "Se produjo un fallo al escribir en «%s»: %s\n" #: src/util/gnunet-ecc.c:107 #, fuzzy, c-format msgid "" "\n" "Finished!\n" msgstr "¡Finalizado!\n" #: src/util/gnunet-ecc.c:110 #, c-format msgid "" "\n" "Error, %u keys not generated\n" msgstr "" #: src/util/gnunet-ecc.c:199 #, fuzzy, c-format msgid "Hostkeys file `%s' not found\n" msgstr "El fichero de máquinas %s no fue encontrado\n" #: src/util/gnunet-ecc.c:210 #, fuzzy, c-format msgid "Hostkeys file `%s' is empty\n" msgstr "El archivo de amigos «%s» está vacío.\n" #: src/util/gnunet-ecc.c:232 #, fuzzy, c-format msgid "Could not read hostkey file: %s\n" msgstr "¡No se puede leer el fichero de claves de máquina!\n" #: src/util/gnunet-ecc.c:283 msgid "No hostkey file specified on command line\n" msgstr "No se ha especificado la clave de máquina en la línea de comandos\n" #: src/util/gnunet-ecc.c:349 msgid "list keys included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:352 msgid "number of keys to list included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:355 msgid "create COUNT public-private key pairs (for testing)" msgstr "crea «COUNT» pares de claves pública-privada (para pruebas)" #: src/util/gnunet-ecc.c:358 msgid "print the public key in ASCII format" msgstr "imprime la clave pública en formato ASCII" #: src/util/gnunet-ecc.c:361 msgid "print the hash of the public key in ASCII format" msgstr "imprime el hash de la clave pública en formato ASCII" #: src/util/gnunet-ecc.c:364 msgid "print examples of ECC operations (used for compatibility testing)" msgstr "" #: src/util/gnunet-ecc.c:375 msgid "Manipulate GNUnet private ECC key files" msgstr "Manipular los ficheros de clave privada ECC de GNUnet" #: src/util/gnunet-resolver.c:149 msgid "perform a reverse lookup" msgstr "realizar una búsqueda inversa" #: src/util/gnunet-resolver.c:160 msgid "Use build-in GNUnet stub resolver" msgstr "Utilizar el resolvedor interno para pruebas de GNUnet" #: src/util/gnunet-scrypt.c:279 msgid "number of bits to require for the proof of work" msgstr "" #: src/util/gnunet-scrypt.c:282 msgid "file with private key, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:285 msgid "file with proof of work, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:288 msgid "time to wait between calculations" msgstr "" #: src/util/gnunet-scrypt.c:299 #, fuzzy msgid "Manipulate GNUnet proof of work files" msgstr "Manipular los ficheros de clave privada ECC de GNUnet" #: src/util/gnunet-service-resolver.c:299 #, c-format msgid "Could not resolve `%s' (%s): %s\n" msgstr "No se pudo resolver «%s» (%s): %s\n" #: src/util/gnunet-service-resolver.c:371 #: src/util/gnunet-service-resolver.c:412 #, c-format msgid "Could not find IP of host `%s': %s\n" msgstr "No se encontró la IP del host «%s»: %s\n" #: src/util/gnunet-uri.c:84 #, c-format msgid "No URI specified on command line\n" msgstr "No se ha especificado una URI en la línea de comandos. Saliendo.\n" #: src/util/gnunet-uri.c:89 #, c-format msgid "Invalid URI: does not start with `%s'\n" msgstr "URI no válida: no comienza con «%s»\n" #: src/util/gnunet-uri.c:96 #, c-format msgid "Invalid URI: fails to specify subsystem\n" msgstr "URI no válida: falla al especificar el subsistema\n" #: src/util/gnunet-uri.c:106 #, c-format msgid "No handler known for subsystem `%s'\n" msgstr "No hay un manejador conocido para el subsistema «%s»\n" #: src/util/gnunet-uri.c:168 msgid "Perform default-actions for GNUnet URIs" msgstr "Realizar las acciones predeterminadas para URI de GNUnet" #: src/util/helper.c:338 #, c-format msgid "Error reading from `%s': %s\n" msgstr "Error leyendo de «%s»: %s\n" #: src/util/helper.c:383 #, c-format msgid "Failed to parse inbound message from helper `%s'\n" msgstr "" "Se produjo un fallo al procesar el mensaje interno del programa auxiliar " "«%s»\n" #: src/util/helper.c:609 #, c-format msgid "Error writing to `%s': %s\n" msgstr "Error escribiendo a «%s»: %s\n" #: src/util/network.c:134 #, c-format msgid "Unable to shorten unix path `%s' while keeping name unique\n" msgstr "Imposible acortar la ruta unix «%s» manteniendo el nombre único\n" #: src/util/network.c:1355 src/util/network.c:1480 #, c-format msgid "" "Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n" msgstr "" "¡Error lógico interno fatal, el proceso está colgado en «%s» (abortar con " "CTRL-C)!\n" #: src/util/os_installation.c:421 #, c-format msgid "" "Could not determine installation path for %s. Set `%s' environment " "variable.\n" msgstr "" "No se pudo determinar la ruta de instalación de %s. Establezca la variable " "de entorno «%s».\n" #: src/util/os_installation.c:766 #, c-format msgid "Could not find binary `%s' in PATH!\n" msgstr "¡No se pudo encontrar el programa llamado «%s» en PATH!\n" #: src/util/os_installation.c:826 #, fuzzy, c-format msgid "CreateProcess failed for binary %s (%d).\n" msgstr "«%s» falló para el puerto %d (%s).\n" #: src/util/os_installation.c:836 #, c-format msgid "GetExitCodeProcess failed for binary %s (%d).\n" msgstr "" #: src/util/plugin.c:87 #, c-format msgid "Initialization of plugin mechanism failed: %s!\n" msgstr "¡La inicialización del mecanismo de módulos falló: %s!\n" #: src/util/plugin.c:148 #, c-format msgid "`%s' failed to resolve method '%s' with error: %s\n" msgstr "«%s» falló al resolver el método «%s» con error: %s\n" #: src/util/plugin.c:223 #, c-format msgid "`%s' failed for library `%s' with error: %s\n" msgstr "Falló «%s» para la biblioteca «%s» con error: %s\n" #: src/util/plugin.c:382 msgid "Could not determine plugin installation path.\n" msgstr "No se pudo determinar la ruta de instalación de los módulos.\n" #: src/util/program.c:246 src/util/service.c:1452 #, fuzzy, c-format msgid "Malformed configuration file `%s', exit ...\n" msgstr "Se produjo un fallo al borrar el fichero de configuración %s\n" #: src/util/program.c:258 src/util/service.c:1467 #, c-format msgid "Could not access configuration file `%s'\n" msgstr "No se pudo acceder al fichero de configuración «%s»\n" #: src/util/program.c:263 src/util/service.c:1462 #, fuzzy msgid "Malformed configuration, exit ...\n" msgstr "Se produjo un fallo al borrar el fichero de configuración %s\n" #: src/util/resolver_api.c:198 #, c-format msgid "Must specify `%s' for `%s' in configuration!\n" msgstr "¡Se debe especificar «%s» para «%s» en la configuración!\n" #: src/util/resolver_api.c:216 #, c-format msgid "" "Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n" msgstr "" "¡Se debe especificar «%s» o una dirección numérica IP para «%s» de «%s» en " "la configuración!\n" #: src/util/resolver_api.c:348 #, c-format msgid "Timeout trying to resolve IP address `%s'.\n" msgstr "Expiración de plazo intentando resolver la dirección IP «%s».\n" #: src/util/resolver_api.c:352 #, c-format msgid "Timeout trying to resolve hostname `%s'.\n" msgstr "Expiración de plazo intentando resolver el nombre de máquina «%s».\n" #: src/util/resolver_api.c:908 #, c-format msgid "Could not resolve our FQDN : %s\n" msgstr "" "No se pudo resolver nuestro nombre de dominio cualificado (FQDN) : %s\n" #: src/util/scheduler.c:813 msgid "Looks like we're busy waiting...\n" msgstr "Parece que estamos en espera ocupada...\n" #: src/util/scheduler.c:948 #, c-format msgid "Attempt to cancel dead task %llu!\n" msgstr "¡Intento de cancelar la tarea muerta %llu!\n" #: src/util/server.c:484 #, c-format msgid "`%s' failed for port %d (%s).\n" msgstr "«%s» falló para el puerto %d (%s).\n" #: src/util/server.c:493 #, c-format msgid "`%s' failed for port %d (%s): address already in use\n" msgstr "«%s» falló para el puerto %d (%s): dirección en uso actualmente\n" #: src/util/server.c:499 #, fuzzy, c-format msgid "`%s' failed for `%s': address already in use\n" msgstr "«%s» falló para «%.*s»: dirección en uso actualmente\n" #: src/util/server.c:892 #, c-format msgid "" "Processing code for message of type %u did not call " "`GNUNET_SERVER_receive_done' after %s\n" msgstr "" "El código de procesado para el mensaje del tipo %u no llamó a " "«GNUNET_SERVER_receive_done» después de %s\n" #: src/util/service.c:347 #, c-format msgid "Unknown address family %d\n" msgstr "Familia de direcciones %d desconocida\n" #: src/util/service.c:354 #, c-format msgid "Access from `%s' denied to service `%s'\n" msgstr "Acceso denegado desde «%s» al servicio «%s»\n" #: src/util/service.c:409 #, c-format msgid "Could not parse IPv4 network specification `%s' for `%s:%s'\n" msgstr "No se pudo procesar la especificación de red IPv4 «%s» para «%s:%s»\n" #: src/util/service.c:446 #, c-format msgid "Could not parse IPv6 network specification `%s' for `%s:%s'\n" msgstr "No se pudo procesar la especificación de red IPv6 «%s» para «%s:%s»\n" #: src/util/service.c:563 #, c-format msgid "" "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n" msgstr "" "Deshabilitando el soporte para IPv6 para el servicio «%s», se produjo un " "fallo al crear un «socket» IPv6: %s\n" #: src/util/service.c:653 #, c-format msgid "" "Disabling UNIX domain socket support for service `%s', failed to create UNIX " "domain socket: %s\n" msgstr "" "Deshabilitando el soporte de dominio de «sockets» UNIX para el servicio " "«%s», no se pudo crear un «socket» UNIX: %s\n" #: src/util/service.c:669 #, c-format msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n" msgstr "" "No hay ni puerto (PORT) ni ruta unix (UNIXPATH) para el servicio «%s», pero " "uno es necesario\n" #: src/util/service.c:903 msgid "Could not access a pre-bound socket, will try to bind myself\n" msgstr "" "No se pudo acceder a un «socket» pre-ascociado, lo intentaré asociar yo " "mismo\n" #: src/util/service.c:952 src/util/service.c:970 #, c-format msgid "Specified value for `%s' of service `%s' is invalid\n" msgstr "El valor especificado «%s» para el servicio «%s» no es válido\n" #: src/util/service.c:995 #, c-format msgid "Could not access pre-bound socket %u, will try to bind myself\n" msgstr "" "No se pudo acceder al «socket» pre-ascociado %u, lo intentaré asociar yo " "mismo\n" #: src/util/service.c:1165 #, c-format msgid "Failed to start `%s' at `%s'\n" msgstr "Se produjo un fallo al inciar «%s» en «%s»\n" #: src/util/service.c:1207 #, c-format msgid "Service `%s' runs at %s\n" msgstr "El servicio «%s» se ejecuta en %s\n" #: src/util/service.c:1256 msgid "Service process failed to initialize\n" msgstr "No se pudo inicializar el proceso del servicio\n" #: src/util/service.c:1260 msgid "Service process could not initialize server function\n" msgstr "" "No se pudo inicializar la función del servidor en el proceso del servicio\n" #: src/util/service.c:1264 msgid "Service process failed to report status\n" msgstr "El proceso del servicio no devolvió un estado\n" #: src/util/service.c:1319 msgid "No such user" msgstr "No existe tal usuario" #: src/util/service.c:1332 #, c-format msgid "Cannot change user/group to `%s': %s\n" msgstr "Imposible cambiar el usuario/grupo a «%s»: %s\n" #: src/util/service.c:1402 msgid "do daemonize (detach from terminal)" msgstr "demonizar (desasociar del terminal)" #: src/util/signal.c:89 #, c-format msgid "signal (%d, %p) returned %d.\n" msgstr "señal (%d, %p) devolvió %d.\n" #: src/util/strings.c:145 msgid "b" msgstr "b" #: src/util/strings.c:433 #, c-format msgid "Character sets requested were `%s'->`%s'\n" msgstr "Los conjuntos de caracteres pedidos fueron «%s»->«%s»\n" #: src/util/strings.c:561 msgid "Failed to expand `$HOME': environment variable `HOME' not set" msgstr "" "Se produjo un fallo al expandir «$HOME»: variable de entorno «HOME» no " "establecida" #: src/util/strings.c:658 msgid "µs" msgstr "" #: src/util/strings.c:662 msgid "forever" msgstr "para siempre" #: src/util/strings.c:664 msgid "0 ms" msgstr "0 ms" #: src/util/strings.c:670 msgid "ms" msgstr "ms" #: src/util/strings.c:676 msgid "s" msgstr "s" #: src/util/strings.c:682 msgid "m" msgstr "m" #: src/util/strings.c:688 msgid "h" msgstr "h" #: src/util/strings.c:695 msgid "day" msgstr "día" #: src/util/strings.c:697 msgid "days" msgstr "días" #: src/util/strings.c:726 msgid "end of time" msgstr "fin del plazo" #: src/util/strings.c:1159 msgid "IPv6 address did not start with `['\n" msgstr "La dirección IPv6 no empezaba con «[»\n" #: src/util/strings.c:1167 msgid "IPv6 address did contain ':' to separate port number\n" msgstr "La dirección IPv6 contenía «:» para separar el número de puerto\n" #: src/util/strings.c:1173 msgid "IPv6 address did contain ']' before ':' to separate port number\n" msgstr "" "La dirección IPv6 contenía «]» antes de «:» para separar el número de " "puerto\n" #: src/util/strings.c:1180 msgid "IPv6 address did contain a valid port number after the last ':'\n" msgstr "" "La dirección IPv6 contenía un número de puerto válido después del último " "«:»\n" #: src/util/strings.c:1189 #, c-format msgid "Invalid IPv6 address `%s': %s\n" msgstr "Dirección IPv6 «%s» no válida: %s\n" #: src/util/strings.c:1395 src/util/strings.c:1411 msgid "Port not in range\n" msgstr "" #: src/util/strings.c:1420 #, fuzzy, c-format msgid "Malformed port policy `%s'\n" msgstr "Se produjo un fallo al iniciar el servicio «%s»\n" #: src/util/strings.c:1503 src/util/strings.c:1534 src/util/strings.c:1582 #: src/util/strings.c:1603 #, c-format msgid "Invalid format for IP: `%s'\n" msgstr "Formato no válido para la IP: «%s»\n" #: src/util/strings.c:1560 #, c-format msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)." msgstr "Notación de red no válida («/%d» no es válido en IPv4 CIDR)." #: src/util/strings.c:1612 #, fuzzy, c-format msgid "Invalid format: `%s'\n" msgstr "Formato de tiempo no válido «%s»\n" #: src/util/strings.c:1664 #, c-format msgid "Invalid network notation (does not end with ';': `%s')\n" msgstr "Notación de red no válida (no termina con «;»: «%s»)\n" #: src/util/strings.c:1714 #, c-format msgid "Wrong format `%s' for netmask\n" msgstr "Formato «%s» erroneo para máscara de red\n" #: src/util/strings.c:1745 #, c-format msgid "Wrong format `%s' for network\n" msgstr "Formato «%s» erroneo para red\n" #: src/vpn/gnunet-service-vpn.c:550 src/vpn/gnunet-service-vpn.c:1086 #, fuzzy msgid "# Active channels" msgstr "# Túneles activos" #: src/vpn/gnunet-service-vpn.c:642 msgid "# Bytes given to mesh for transmission" msgstr "# Bytes dados para transmisión a mesh" #: src/vpn/gnunet-service-vpn.c:680 msgid "# Bytes dropped in mesh queue (overflow)" msgstr "# Bytes omitidos en la cola mesh (desbordamiento)" #: src/vpn/gnunet-service-vpn.c:753 #, fuzzy msgid "# Mesh channels created" msgstr "# Túneles mesh creados" #: src/vpn/gnunet-service-vpn.c:784 #, fuzzy msgid "Failed to setup mesh channel!\n" msgstr "¡Se produjo un fallo al configurar el túnel mesh!\n" #: src/vpn/gnunet-service-vpn.c:978 #, c-format msgid "Protocol %u not supported, dropping\n" msgstr "Protocolo %u no soportado, omitiendo\n" #: src/vpn/gnunet-service-vpn.c:1305 msgid "# ICMPv4 packets dropped (not allowed)" msgstr "# Paquetes ICMPv4 omitidos (no permitido)" #: src/vpn/gnunet-service-vpn.c:1326 msgid "# ICMPv6 packets dropped (not allowed)" msgstr "# Paquetes ICMPv6 omitidos (no permitido)" #: src/vpn/gnunet-service-vpn.c:1531 msgid "# Packets received from TUN interface" msgstr "# Paquetes recibidos de la interfaz TUN" #: src/vpn/gnunet-service-vpn.c:1564 src/vpn/gnunet-service-vpn.c:1600 #, c-format msgid "Packet received for unmapped destination `%s' (dropping it)\n" msgstr "Paquete recibido para el destino «%s» no mapeado (omitiéndolo)\n" #: src/vpn/gnunet-service-vpn.c:1610 msgid "Received IPv4 packet with options (dropping it)\n" msgstr "Recibido paquete IPv4 con opciones (omitiéndolo)\n" #: src/vpn/gnunet-service-vpn.c:1624 #, c-format msgid "Received packet of unknown protocol %d from TUN (dropping it)\n" msgstr "Recibido paquete de protocolo %d desconocido desde TUN (omitiéndolo)\n" #: src/vpn/gnunet-service-vpn.c:1706 msgid "# ICMP packets received from mesh" msgstr "# Paquetes ICMP recibidos de mesh" #: src/vpn/gnunet-service-vpn.c:2045 msgid "# UDP packets received from mesh" msgstr "# Paquetes UDP recibidos de mesh" #: src/vpn/gnunet-service-vpn.c:2200 msgid "# TCP packets received from mesh" msgstr "# Paquetes TCP recibidos de mesh" #: src/vpn/gnunet-service-vpn.c:2351 msgid "Failed to find unallocated IPv4 address in VPN's range\n" msgstr "No se encontraron direcciones IPv4 libres en el rango de la VPN\n" #: src/vpn/gnunet-service-vpn.c:2406 msgid "Failed to find unallocated IPv6 address in VPN's range\n" msgstr "No se encontraron direcciones IPv6 libres en el rango de la VPN\n" #: src/vpn/gnunet-service-vpn.c:2447 src/vpn/gnunet-service-vpn.c:2663 msgid "# Active destinations" msgstr "# Destinos activos" #: src/vpn/gnunet-service-vpn.c:2715 msgid "Failed to allocate IP address for new destination\n" msgstr "" "Se produjo un fallo al alojar las direcciones IP para el nuevo destino\n" #: src/vpn/gnunet-service-vpn.c:2982 #, fuzzy msgid "Must specify valid IPv6 address" msgstr "«%s» no es una dirección IP válida.\n" #: src/vpn/gnunet-service-vpn.c:3006 msgid "Must specify valid IPv6 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3014 msgid "IPv6 support disabled as this system does not support IPv6\n" msgstr "" "El soporte de IPv6 se deshabilita porque este sistema no soporta IPv6\n" #: src/vpn/gnunet-service-vpn.c:3027 #, fuzzy msgid "Must specify valid IPv4 address" msgstr "«%s» no es una dirección IP válida.\n" #: src/vpn/gnunet-service-vpn.c:3040 msgid "Must specify valid IPv4 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3050 msgid "IPv4 support disabled as this system does not support IPv4\n" msgstr "" "El soporte de IPv4 se deshabilita porque este sistema no soporta IPv4\n" #: src/vpn/gnunet-vpn.c:147 msgid "Error creating tunnel\n" msgstr "Error creando el túnel\n" #: src/vpn/gnunet-vpn.c:190 src/vpn/gnunet-vpn.c:221 #, c-format msgid "Option `%s' makes no sense with option `%s'.\n" msgstr "La opción «%s» no tiene sentido con la opción «%s».\n" #: src/vpn/gnunet-vpn.c:203 #, c-format msgid "Option `%s' or `%s' is required.\n" msgstr "Las opción «%s» o «%s» es necesaria.\n" #: src/vpn/gnunet-vpn.c:215 #, c-format msgid "Option `%s' or `%s' is required when using option `%s'.\n" msgstr "Las opción «%s» o «%s» es necesaria cuando se usa la opción «%s».\n" #: src/vpn/gnunet-vpn.c:235 #, c-format msgid "`%s' is not a valid peer identifier.\n" msgstr "«%s» no es un identificador de par válido\n" #: src/vpn/gnunet-vpn.c:255 #, c-format msgid "`%s' is not a valid IP address.\n" msgstr "«%s» no es una dirección IP válida.\n" #: src/vpn/gnunet-vpn.c:290 msgid "request that result should be an IPv4 address" msgstr "petición cuyo resultado debe ser una dirección IPv4" #: src/vpn/gnunet-vpn.c:293 msgid "request that result should be an IPv6 address" msgstr "petición cuyo resultado debe ser una dirección IPv6" #: src/vpn/gnunet-vpn.c:296 msgid "how long should the mapping be valid for new tunnels?" msgstr "¿cuánto tiempo debe ser válido el mapeado para túneles nuevos?" #: src/vpn/gnunet-vpn.c:299 msgid "destination IP for the tunnel" msgstr "IP de destino para el túnel" #: src/vpn/gnunet-vpn.c:302 msgid "peer offering the service we would like to access" msgstr "par que ofrece el servicio al que nos gustaría acceder" #: src/vpn/gnunet-vpn.c:305 msgid "name of the service we would like to access" msgstr "nombre del servicio al que nos gustaría acceder" #: src/vpn/gnunet-vpn.c:308 msgid "service is offered via TCP" msgstr "el servicio es ofrecido vía TCP" #: src/vpn/gnunet-vpn.c:311 msgid "service is offered via UDP" msgstr "el servicio es ofrecido vía UDP" #: src/vpn/gnunet-vpn.c:323 msgid "Setup tunnels via VPN." msgstr "Configurar túneles vía VPN." #: src/include/gnunet_common.h:566 src/include/gnunet_common.h:573 #: src/include/gnunet_common.h:581 #, c-format msgid "Assertion failed at %s:%d.\n" msgstr "Aserción fallida en %s:%d.\n" #: src/include/gnunet_common.h:593 #, c-format msgid "External protocol violation detected at %s:%d.\n" msgstr "Violación externa del protocolo detectada en %s:%d.\n" #: src/include/gnunet_common.h:620 src/include/gnunet_common.h:629 #, c-format msgid "`%s' failed on file `%s' at %s:%d with error: %s\n" msgstr "«%s» falló en el fichero «%s» en %s:%d con el error: %s\n" #, fuzzy #~ msgid "# TRAIL SETUP requests received" #~ msgstr "# peticiones «GET» recibidas" #, fuzzy #~ msgid "# TRAIL SETUP bytes received" #~ msgstr "# Peticiones «GET» P2P recibidas" #~ msgid "# other peer asked to disconnect from us" #~ msgstr "# peticiones de otro par para desconectarse de nosotros" #, fuzzy #~ msgid "provide information about a particular channel" #~ msgstr "proveer información acerca de un túnel en particular" #~ msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED" #~ msgstr "" #~ "proveer información acerca de todos los túneles (de forma continua) SIN " #~ "IMPLEMENTAR" #~ msgid "NSE service is lacking key configuration settings. Exiting.\n" #~ msgstr "" #~ "El servicio NSE carece de opciones de configuración de clave. Saliendo.\n" #~ msgid "Could not find option `%s:%s' in configuration.\n" #~ msgstr "No se pudo encontrar la opción «%s:%s» en la configuración.\n" #~ msgid "Peer `%s': %s \n" #~ msgstr "Par «%s»: %s \n" #~ msgid "Peer `%s' disconnected\n" #~ msgstr "Par «%s» desconectado\n" #~ msgid "Transport plugin: `%s' port %llu\n" #~ msgstr "Módulo de transporte: «%s» puerto %llu\n" #~ msgid "Found %u transport plugins: `%s'\n" #~ msgstr "Encontrados %u módulos de transporte: «%s»\n" #~ msgid "Send ping messages to test connectivity (default == NO)" #~ msgstr "" #~ "Enviar mensajes «ping» para probar la conectividad (predeterminado: NO)" #, fuzzy #~ msgid "Failed to parse HELLO in file `%s': %s %u \n" #~ msgstr "Se produjo un fallo al procesar «HELLO» en el fichero «%s»\n" #, fuzzy #~ msgid "Internal error %d\n" #~ msgstr "Error interno." #, fuzzy #~ msgid "Aborting call to `%s'\n" #~ msgstr "Error escribiendo a «%s»: %s\n" #, fuzzy #~ msgid "You are already in a conversation with `%s'.\n" #~ msgstr "No se pudo acceder al fichero de configuración «%s»\n" #~ msgid "Print information about mesh tunnels and peers." #~ msgstr "Imprimir información acerca de tuneles mesh y pares." #~ msgid "" #~ "%s service is lacking key configuration settings (%s). Using default " #~ "(%u).\n" #~ msgstr "" #~ "El servicio %s carece de opciones de configuración de clave (%s). Usando " #~ "predeterminada (%u).\n" #~ msgid "Port 0, client only mode\n" #~ msgstr "Puerto 0, modo únicamente cliente\n" #~ msgid "" #~ "Specific IPv4 address `%s' for plugin %s in configuration file is " #~ "invalid! Binding to all addresses!\n" #~ msgstr "" #~ "¡La dirección IPV4 «%s» especificada para el módulo %s en el fichero de " #~ "configuración no es válida! ¡Asociándose a todas las direcciones!\n" #~ msgid "" #~ "Specific IPv6 address `%s' for plugin %s in configuration file is " #~ "invalid! Binding to all addresses!\n" #~ msgstr "" #~ "¡La dirección IPv6 «%s» especificada para el módulo %s en el fichero de " #~ "configuración no es válida! ¡Asociándose a todas las direcciones!\n" #~ msgid "No external hostname configured\n" #~ msgstr "No hay nombre de máquina externo configurado\n" #~ msgid "Starting `%s' process to generate entropy\n" #~ msgstr "Iniciando el proceso «%s» para generar entropía\n" #~ msgid "Loading block plugin `%s'\n" #~ msgstr "Cargando el módulo de bloques «%s»\n" #, fuzzy #~ msgid "Invalid value `%s'\n" #~ msgstr "Parámetro no válido «%s»\n" #, fuzzy #~ msgid "Found issuer for public key `%s'\n" #~ msgstr "Encontrados %u módulos de transporte: «%s»\n" #, fuzzy #~ msgid "No issuer for public key `%s'\n" #~ msgstr "No se han encontrado ficheros en «%s»\n" #~ msgid "Unsupported record type %d\n" #~ msgstr "Tipo de registro %d no soportado\n" #~ msgid "Invalid work requirement for NSE service. Exiting.\n" #~ msgstr "Requisitos de trabajo no válidos para el servicio NSE. Saliendo.\n" #, fuzzy #~ msgid "Failed to get slave counters!\n" #~ msgstr "¡Se produjo un fallo al obtener la clave de máquina!\n" #~ msgid "# DNS requests aborted (tunnel down)" #~ msgstr "# Peticiones DNS abortadas (túnel caído)" #, fuzzy #~ msgid "" #~ "Could not translate E[a%d] to MPI!\n" #~ "%s/%s\n" #~ msgstr "Imposible obtener IP para la interfaz '%s' usando '%s'.\n" #~ msgid "Job command file not given. Exiting\n" #~ msgstr "Fichero de configuración de trabajos no proporcionado. Saliendo\n" #~ msgid "Error while decoding key %u\n" #~ msgstr "Error decodificando clave %u\n" #~ msgid "Could not read friends list `%s'\n" #~ msgstr "No se pudo leer la lista de amigos «%s»\n" #~ msgid "Failed to read friends list from `%s': out of memory\n" #~ msgstr "" #~ "Se produjo un fallo al leer la lista de amigos de «%s»: no hay memoria " #~ "disponible\n" #~ msgid "Failed to read friends list from `%s'\n" #~ msgstr "Se produjo un fallo al leer la lista de amigos de «%s»\n" #~ msgid "" #~ "Syntax error in topology specification at offset %llu, skipping bytes.\n" #~ msgstr "" #~ "Error de sintaxis en la especificación de topología en el desplazamiento " #~ "%llu, omitiendo bytes.\n" #~ msgid "" #~ "Syntax error in topology specification at offset %llu, skipping bytes `" #~ "%s'.\n" #~ msgstr "" #~ "Error de sintaxis en la especificación de topología en el desplazamiento " #~ "%llu, omitiendo bytes «%s».\n" #~ msgid "ECC signature verification failed at %s:%d: %s\n" #~ msgstr "La verificación de firma ECC falló en %s:%d: %s\n" #~ msgid "No `%s' specified for service `%s' in configuration.\n" #~ msgstr "" #~ "Ningún «%s» especificado para el servicio «%s» en la configuración.\n" #~ msgid "Access denied to UID %d / GID %d\n" #~ msgstr "Acceso denegado al UID %d / GID %d\n" #~ msgid "# peers connected to mesh tunnels" #~ msgstr "# pares conectados a túneles mesh" #~ msgid "print IP address only after mesh tunnel has been created" #~ msgstr "" #~ "imprimir direcciones IP solamente después de haber creado el túnel mesh" #~ msgid "Failed to parse metadata about pseudonym from file `%s': %s\n" #~ msgstr "" #~ "Se produjo un fallo al procesar los metadatos del fichero «%s» acerca del " #~ "seudónimo: %s\n" #~ msgid "no-name" #~ msgstr "sin nombre" #~ msgid "Option `%s' ignored\n" #~ msgstr "Opción «%s» ignorada\n" #, fuzzy #~ msgid "advertise namespace NAME" #~ msgstr "crear o anunciar un nombre de espacio de nombres (NAME)" #~ msgid "" #~ "add an additional keyword for the advertisment (this option can be " #~ "specified multiple times)" #~ msgstr "" #~ "añade una palabra clave adicional para el anuncio (esta opción puede ser " #~ "especificada varias veces)" #~ msgid "use the given PRIORITY for the advertisments" #~ msgstr "usa la prioridad (PRIORITY) dada para los anuncios" #~ msgid "do not print names of remote namespaces" #~ msgstr "no imprime los nombres de los espacios de nombres remotos" #~ msgid "specify ID of the root of the namespace" #~ msgstr "especifica la identificación (ID) del espacio de nombres raíz" #~ msgid "change rating of namespace ID by VALUE" #~ msgstr "cambia la valoración del espacio de nombres «ID» al valor «VALUE»" #~ msgid "Manage GNUnet pseudonyms." #~ msgstr "Gestionar seudónimos de GNUnet." #~ msgid "Please specify lookup, shorten or authority operation!\n" #~ msgstr "" #~ "¡Por favor, especifique la operación: búsqueda (lookup), acortado " #~ "(shorten) o autoridad (authority)!\n" #~ msgid "try to shorten a given name" #~ msgstr "intentar acortar un nombre dado" #~ msgid "Get the authority of a particular name" #~ msgstr "Obtener la autoridad de un nombre particular" #~ msgid "Failed to read or create private zone key\n" #~ msgstr "Se produjo un fallo al leer o crear una clave de zona privada\n" #~ msgid "Records for name `%s' in zone %s too large to fit into DHT" #~ msgstr "" #~ "Los registros para el nombre «%s» en la zona %s son demasiado grandes " #~ "para entrar en la DHT" #~ msgid "Unable to initialize resolver!\n" #~ msgstr "¡No se puede inicializar el resolvedor!\n" #~ msgid "Not a GADS TLD: `%s'\n" #~ msgstr "No es un TLD GADS: «%s»\n" #~ msgid "for at least" #~ msgstr "al menos por" #~ msgid "until" #~ msgstr "hasta" #~ msgid "Using default zone file `%s'\n" #~ msgstr "Usando el fichero de zonas predeterminado «%s»\n" #~ msgid "create or list non-authority record" #~ msgstr "crear o listar registros sin-autoridad" #~ msgid "filename with the zone key" #~ msgstr "nombre del fichero con la clave de zona" #~ msgid "Failed to write zone key to file `%s': %s\n" #~ msgstr "" #~ "Se produjo un fallo al escribir la clave de zona al fichero «%s»: %s\n" #~ msgid "file exists but reading key failed" #~ msgstr "el fichero existe, pero no se pudo leer la clave" #~ msgid "file exists with different key" #~ msgstr "el fichero existe con diferente clave" #~ msgid "No directory to load zonefiles specified in configuration\n" #~ msgstr "" #~ "Ningún directorio del que cargar ficheros de zona especificado en la " #~ "configuración\n" #~ msgid "Creating directory `%s' for zone files failed!\n" #~ msgstr "" #~ "¡Se produjo un fallo creando el directorio «%s» para ficheros de zonas!\n" #~ msgid "" #~ "Could not parse execution interval for `%s', set to default 60 sec.\n" #~ msgstr "" #~ "No se pudo determinar el intervalo de ejecución para «%s», " #~ "estableciéndolo a los 60 segundos predeterminados.\n" #~ msgid "name of the template configuration file to use (optional)" #~ msgstr "nombre del fichero plantilla de configuración a usar (opcional)" #~ msgid "name of the service to run" #~ msgstr "nombre del servicio a ejecutar" #~ msgid "print the short hash of the public key in ASCII format" #~ msgstr "imprime el hash corto de la clave pública en formato ASCII" #~ msgid "start peers with the given template configuration" #~ msgstr "inicia los pares con la plantilla de configuración dada" #~ msgid "number of peers to start" #~ msgstr "número de pares para empezar" #, fuzzy #~ msgid "Failed to read or generate private key: %s\n" #~ msgstr "Se produjo un fallo al leer o crear una clave de zona privada\n" #~ msgid "Transport service is unable to access hostkey. Exiting.\n" #~ msgstr "" #~ "El servicio de transporte no es capaz de acceder a la clave de la " #~ "máquina. Saliendo.\n" #~ msgid "" #~ "Failed to recover namespace `%s', cannot resume publishing operation.\n" #~ msgstr "" #~ "Se produjo un fallo al recuperar el espacio de nombres «%s», no se pudo " #~ "retomar la operación de publicación.\n" #~ msgid "Failed to create or read private key for namespace `%s'\n" #~ msgstr "" #~ "Se produjo un fallo al crear o leer la clave privada para el espacio de " #~ "nombres «%s»\n" #, fuzzy #~ msgid "Failed to read private key for namespace `%s'\n" #~ msgstr "" #~ "Se produjo un fallo al crear o leer la clave privada para el espacio de " #~ "nombres «%s»\n" #~ msgid "Failed to read namespace private key file `%s', deleting it!\n" #~ msgstr "" #~ "Se produjo un fallo al leer el fichero de la clave privada del espacio de " #~ "nombres «%s», ¡borrándolo!\n" #, fuzzy #~ msgid "Identifiers or URI too long to create UBlock" #~ msgstr "" #~ "Identificadores o URI demasiado largos para crear un bloque S (SBlock)" #~ msgid "print names of local namespaces" #~ msgstr "imprime los nombres de los espacios de nombres locales" #~ msgid "Failed to create namespace `%s' (illegal filename?)\n" #~ msgstr "" #~ "Se produjo un fallo al crear el espacio de nombres «%s» (¿nombre de " #~ "fichero ilegal?).\n" #~ msgid "# Replies received from STREAM" #~ msgstr "# Respuestas recibidas de «STREAM»" #~ msgid "Mesh service could not access hostkey: %s. Exiting.\n" #~ msgstr "" #~ "El servicio mesh no puede acceder a la clave de la máquina: %s. " #~ "Saliendo.\n" #~ msgid "add/del" #~ msgstr "añadir/borrar" #~ msgid "" #~ "Deletion requires either absolute time, or no time at all. Got relative " #~ "time `%s' instead.\n" #~ msgstr "" #~ "El borrado requiere o tiempo absoluto, o ningún tiempo. Tomado tiempo " #~ "relativo «%s» en su defecto.\n" #~ msgid "No valid expiration time for operation `%s'\n" #~ msgstr "Tiempo de expiración no válido para la operación «%s»\n" # Miguel: "Failed to find" lo he traducido por "No se pudo encontrar" # puesto que es mas claro que "fallar en la búsqueda". #~ msgid "Failed to find record to remove\n" #~ msgstr "No se pudo encontrar el registro a borrar\n" #~ msgid "Could not parse zone key file `%s'\n" #~ msgstr "No se pudo procesar el fichero de clave de zona «%s»\n" #~ msgid "Failed to create new signature" #~ msgstr "Se produjo un fallo al crear una nueva firma" #~ msgid "Failed to put new set of records in database" #~ msgstr "" #~ "Se produjo un fallo al insertar un nuevo conjunto de registros en la base " #~ "de datos" #~ msgid "Failed to remove records from database" #~ msgstr "Se produjo un fallo al borrar registros de la base de datos" #~ msgid "Failed to access database" #~ msgstr "Se produjo un fallo al acceder a la base de datos" #~ msgid "unknown internal error in namestore" #~ msgstr "error interno desconocido en el almacén de nombres" #~ msgid "Protocol error" #~ msgstr "Error de protocolo" #~ msgid "NSE service could not access hostkey: %s\n" #~ msgstr "El servicio NSE no puede acceder a la clave de máquina: %s\n" #, fuzzy #~ msgid "" #~ "Error loading search strings.Given file does not contain enough strings. " #~ "Exiting.\n" #~ msgstr "" #~ "Error cargando cadenas de búsqueda. El fichero proporcionado no contiene " #~ "cadenas suficientes. Saliendo.\n" #~ msgid "Transport service could not access hostkey: %s. Exiting.\n" #~ msgstr "" #~ "El servicio de transporte no puede acceder a la clave de la máquina: %s. " #~ "Saliendo.\n" #~ msgid "Address of unexpected length: %u\n" #~ msgstr "Dirección de tamaño inesperado: %u\n" #~ msgid "Failure to transmit TEST request.\n" #~ msgstr "Se produjo un fallo al transmitir la peticion «TEST».\n" #~ msgid "" #~ "File `%s' does not contain a valid private key (too long, %llu bytes). " #~ "Deleting it.\n" #~ msgstr "" #~ "El fichero «%s» no contiene una clave privada válida (demasiado grande, " #~ "%llu bytes). Borrándolo.\n" #~ msgid "" #~ "File `%s' does not contain a valid private key (failed decode, %llu " #~ "bytes). Deleting it.\n" #~ msgstr "" #~ "El fichero «%s» no contiene una clave privada válida (falló al " #~ "decodificar, %llu bytes). Borrándolo.\n" #~ msgid "File `%s' does not contain a valid private key. Deleting it.\n" #~ msgstr "" #~ "El fichero «%s» no contiene una clave privada válida. Borrándolo.\n" #~ msgid "interrupted by shutdown" #~ msgstr "interrumpido por apagado" #~ msgid "gnunet-ecc failed" #~ msgstr "«gnunet-ecc» falló" #~ msgid "" #~ "File `%s' does not contain a valid private key (too long, %llu bytes). " #~ "Renaming it.\n" #~ msgstr "" #~ "El fichero «%s» no contiene una clave privada válida (demasiado grande, " #~ "%llu bytes). Renombrándolo.\n" #~ msgid "gnunet-rsa failed" #~ msgstr "«gnunet-rsa» falló" #~ msgid "RSA signature verification failed at %s:%d: %s\n" #~ msgstr "La verificación de la firma RSA fallo en %s:%d: %s\n" #~ msgid "`%s' failed for drive `%S': %u\n" #~ msgstr "«%s» falló para la unidad «%S»: %u\n" #~ msgid "Manipulate GNUnet private RSA key files" #~ msgstr "Manipular los ficheros de clave privada RSA de GNUnet" #~ msgid "No hosts-file specified on command line. Exiting.\n" #~ msgstr "" #~ "No se ha especificado el fichero de máquinas en la línea de comandos. " #~ "Saliendo.\n" #~ msgid "number of search strings to read from search strings file" #~ msgstr "" #~ "número de cadenas de búsqueda a leer del fichero de cadenas de búsqueda" # Miguel: "shutdown request" se refiere a finalizar el # que hace de cliente. #~ msgid "Failed to transmit shutdown request to client.\n" #~ msgstr "" #~ "Se produjo un fallo al transmitir una petición de apagado al cliente.\n" #~ msgid "Service `%s' was already running.\n" #~ msgstr "El servicio «%s» aún estaba ejecutándose.\n" #~ msgid "Service `%s' has been started.\n" #~ msgstr "El servicio «%s» se ha iniciado.\n" #~ msgid "Service `%s' was already being stopped.\n" #~ msgstr "El servicio «%s» estaba siendo parado con anterioridad.\n" #~ msgid "Service `%s' was already not running.\n" #~ msgstr "El servicio «%s» no se estaba ejecutando.\n" # Miguel: ¿Conectar y conexión? #~ msgid "Error communicating with ARM service.\n" #~ msgstr "Error al comunicar con el servicio ARM.\n" #~ msgid "Timeout communicating with ARM service.\n" #~ msgstr "Fin del tiempo de espera en la comunicación con el servicio ARM.\n" #~ msgid "Error in communication with PEERINFO service\n" #~ msgstr "" #~ "Error en la comunicación con el servicio de información de pares " #~ "(PEERINFO)\n" #~ msgid "%s Received message from %s of type %d, distance %u!\n" #~ msgstr "%s Recibido mensaje de %s del tipo %d, distancia %u!\n" #~ msgid "IP address of this system as seen by the rest of the testbed" #~ msgstr "" #~ "Dirección IP de este sistema como visto desde el resto de equipos de " #~ "prueba" #~ msgid "delay between queries to statistics during a round" #~ msgstr "retardo entre consultas a las estadísticas durante una ronda" #~ msgid "" #~ "prefix of the filenames we use for writing the topology for each round" #~ msgstr "" #~ "prefijo de los nombres de fichero usados para escribir la topología de " #~ "cada ronda" #, fuzzy #~ msgid "An operation has failed while starting peers: %s\n" #~ msgstr "Una operación ha fallado mientras se iniciaban los pares\n" #~ msgid "Creating a peer failed. Error: %s\n" #~ msgstr "No se pudo crear un par. Error: %s\n" #~ msgid "An operation has failed while starting slaves\n" #~ msgstr "Una operación ha fallado mientras se arrancaban los esclavos\n" #~ msgid "An operation has failed while linking\n" #~ msgstr "Una operación ha fallado mientras se enlazaba\n" #~ msgid "Unable to connect to master controller -- Check config\n" #~ msgstr "" #~ "No se puede conectar al controlador principal -- Compruebe la " #~ "configuración\n" #~ msgid "Checking whether given hosts can start testbed. Please wait\n" #~ msgstr "" #~ "Comprobando si las máquinas dadas pueden iniciar la batería de pruebas. " #~ "Por favor, espere\n" #~ msgid "Exiting\n" #~ msgstr "Saliendo\n" #~ msgid "create COUNT number of random links between peers" #~ msgstr "crear un número «COUNT» de enlaces aleatorios entre pares" #~ msgid "wait DELAY before starting string search" #~ msgstr "esperar «DELAY» antes de empezar la búsqueda de cadenas" #~ msgid "No hosts-file specified on command line\n" #~ msgstr "" #~ "No se ha especificado el fichero de máquinas en la línea de comandos.\n" #~ msgid "Profiler for testbed" #~ msgstr "Analizador de rendimiento para la batería de pruebas" #~ msgid "Could not read blacklist file `%s'\n" #~ msgstr "No se pudo leer el fichero de la lista negra «%s»\n" #~ msgid "Failed to read blacklist from `%s'\n" #~ msgstr "Se produjo un fallo al leer la lista negra de «%s»\n" #~ msgid "Syntax error in blacklist file at offset %llu, giving up!\n" #~ msgstr "" #~ "¡Error de sintaxis en el fichero de la lista negra en el desplazamiento " #~ "%llu, rindiendose!\n" #~ msgid "Syntax error in blacklist file at offset %llu, skipping bytes.\n" #~ msgstr "" #~ "Error de sintaxis en el fichero de la lista negra en el desplazamiento " #~ "%llu, omitiendo bytes.\n" #~ msgid "Found myself `%s' in blacklist (useless, ignored)\n" #~ msgstr "Me he encontrado «%s» en mi lista negra (inútil, ignorado)\n" #~ msgid "Failed to read hostkey: %s\n" #~ msgstr "Se produjo un fallo al leer la clave de máquina: %s\n" #~ msgid "# Delayed connecting due to lack of public key" #~ msgstr "# Retrasada la conexión debido a la falta de clave pública" #~ msgid "# session keys received" #~ msgstr "# claves de sesión recibidas" #~ msgid "`%s' is for `%s', not for me. Ignoring.\n" #~ msgstr "«%s» es para «%s», no para mí. Ignorándolo.\n" #~ msgid "# SET_KEY and PING messages created" #~ msgstr "# mensajes «SET_KEY» y «PING» creados" #~ msgid "# REKEY operations performed" #~ msgstr "# operaciones de cambio de clave (REKEY) realizadas" #~ msgid "# failed to decrypt message (no session key)" #~ msgstr "# fallos al descifrar el mensaje (no hay clave de sesión)" #~ msgid "Message received far too old (%s). Content ignored.\n" #~ msgstr "El mensaje recibido es muy antiguo (%s). Se ignora el contenido.\n" #~ msgid "Unknown error" #~ msgstr "Error desconocido" #~ msgid "Failed to serialize meta data" #~ msgstr "Se produjo un fallo al serializar metadatos" #~ msgid "Failed to connect to datastore service" #~ msgstr "Se produjo un fallo al conectar con el servicio de almacenamiento" #~ msgid "Failed to parse URI `%s' from KBlock!\n" #~ msgstr "¡Se produjo un fallo al procesar la URI «%s» del KBlock!\n" #~ msgid "Regexprofiler could not access hostkey: %s. Exiting.\n" #~ msgstr "" #~ "El perfilador de expresiones regulares no puede acceder a la clave de " #~ "máquina: %s. Saliendo.\n" #~ msgid "" #~ "if this option is set, only one peer is responsible for searching all " #~ "strings" #~ msgstr "" #~ "si esta opción está activada, únicamente un par es responsable de buscar " #~ "todas las cadenas" #~ msgid "Could not access STATISTICS service. Exiting.\n" #~ msgstr "" #~ "No se pudo acceder al servicio de estadísticas (STATISTICS). Saliendo.\n" #~ msgid "" #~ "use insecure, weak random number generator for key generation (for " #~ "testing only)" #~ msgstr "" #~ "usar un generador de números aleatorios inseguro y débil para la " #~ "generación de claves (únicamente para pruebas)" #~ msgid "Failed to open named pipe `%s' for reading: %s\n" #~ msgstr "" #~ "Se produjo un fallo al abrir el fichero (tubería) «%s» para lectura: %s\n" #~ msgid "Failed to open named pipe `%s' for writing: %s\n" #~ msgstr "" #~ "Se produjo un fallo al abrir el fichero (tubería) «%s» para escritura: " #~ "%s\n" #~ msgid "session identifier" #~ msgstr "identificador de sesión" #~ msgid "Mesh service could not access hostkey. Exiting.\n" #~ msgstr "" #~ "El servicio 'MESH' no puede acceder a la clave de la máquina. Saliendo.\n" #~ msgid "\rChecked %u hosts" #~ msgstr "\rComprobadas %u máquinas" #~ msgid "" #~ "\n" #~ "All hosts can start testbed. Creating peers\n" #~ msgstr "" #~ "\n" #~ "Todas las máquinas pueden iniciar la batería de pruebas. Creando pares\n" #~ msgid "Only `CLIQUE' and `RANDOM' are permitted.\n" #~ msgstr "Únicamente se permiten «CLIQUE» y «RANDOM».\n" #~ msgid "create COUNT number of random links" #~ msgstr "crea «COUNT» número de enlaces aleatorios" #~ msgid "" #~ "Try to acheive TOPOLOGY. This options takes either CLIQUE or RANDOM. For " #~ "CLIQUE the parameter -n is ignored. The default is to acheive a random " #~ "graph topology." #~ msgstr "" #~ "Intentar adquirir topología (TOPOLOGY) dada. Estas opciones toman " #~ "«CLIQUE» o «RANDOM» como argumentos. «CLIQUE» ignora el parámetro -n. Lo " #~ "predeterminado es adquirir una topología aleatoria (RANDOM) en el grafo." #~ msgid "Some operations are still pending. Cancelling them\n" #~ msgstr "Algunas operaciones están todavía pendientes. Cancelándolas\n" #~ msgid "MySQL datacache running\n" #~ msgstr "Caché de datos MySQL ejecutándose\n" #~ msgid "Reply mismatched in terms of namespace. Discarded.\n" #~ msgstr "" #~ "Respuesta no asociada en terminos de espacio de nombres. Descartada.\n" #~ msgid "Proof of work invalid: %llu!\n" #~ msgstr "¡Prueba de trabajo no válida: %llu!\n" #, fuzzy #~ msgid "No hosts loaded. Need atleast one host\n" #~ msgstr "No se han cargado máquinas. Se necesita al menos una máquina.\n" #~ msgid "Blacklist file `%s' is empty.\n" #~ msgstr "El fichero de lista negra «%s» está vacío.\n" #~ msgid "try to connect to the given peer" #~ msgstr "intentar conectar al par dado" #~ msgid "Configuration failes to specify option `%s' in section `%s'!\n" #~ msgstr "" #~ "¡La configuración no especifica la opción «%s» en la sección «%s»!\n" #~ msgid "Error receiving response to `%s' request from ARM for service `%s'\n" #~ msgstr "" #~ "Error recibiendo respuesta a la petición «%s» del ARM para el servicio " #~ "«%s»\n" #~ msgid "Requesting termination of service `%s'.\n" #~ msgstr "Solicitando finalización del servicio «%s».\n" #~ msgid "Error while trying to transmit request to start `%s' to ARM\n" #~ msgstr "" #~ "Se produjo un fallo al transmitir la petición de inicio de «%s» al ARM\n" #~ msgid "Error while trying to transmit request to stop `%s' to ARM\n" #~ msgstr "" #~ "Se produjo un fallo al transmitir la petición de finalización de «%s» al " #~ "ARM\n" #~ msgid "Asked to start service `%s' within %llu ms\n" #~ msgstr "Se solicitó iniciar el servicio «%s» en %llu ms\n" #~ msgid "Stopping service `%s' within %llu ms\n" #~ msgstr "Parando el servicio «%s» en %llu ms\n" #~ msgid "Fatal configuration error: `%s' option in section `%s' missing.\n" #~ msgstr "" #~ "Error fatal de configuración: falta la opción «%s» en la sección «%s».\n" #~ msgid "Failed to transmit shutdown ACK.\n" #~ msgstr "" #~ "Se produjo un fallo al transmitir el reconocimiento de finalización.\n" #~ msgid "Configuration file `%s' for service `%s' not valid: %s\n" #~ msgstr "" #~ "El fichero de configuración «%s» para el servicio «%s» no es válido: %s\n" #~ msgid "Transmitting shutdown ACK.\n" #~ msgstr "Transmitiendo el reconocimiento de finalización.\n" #~ msgid "Could not transmit confirmation receipt\n" #~ msgstr "No se pudo transmitir la confirmación de la recepción\n" #~ msgid "The current user must be the the first one joined\n" #~ msgstr "El usuario actual debe ser el primero en unirse\n" #~ msgid "Unknown message type: '%u'\n" #~ msgstr "Tipo de mensaje «%u» desconocido\n" #~ msgid "Configuration option `%s' in section `%s' missing\n" #~ msgstr "Falta la opción de configuración «%s» en la sección «%s»\n" #~ msgid "Failed to access chat home directory `%s'\n" #~ msgstr "Se produjo un fallo al acceder al directorio para el chat «%s»\n" #~ msgid "Failed to create/open key in file `%s'\n" #~ msgstr "Se produjo un fallo al crear/abrir la clave en el fichero «%s».\n" #~ msgid "Could not serialize metadata\n" #~ msgstr "No se pudieron serializar los metadatos\n" #~ msgid "Undefined mandatory parameter: joinCallback\n" #~ msgstr "Parámetro obligatorio indefinido: joinCallback\n" #~ msgid "Undefined mandatory parameter: messageCallback\n" #~ msgstr "Parámetro obligatorio indefinido: messageCallback\n" #~ msgid "Undefined mandatory parameter: memberCallback\n" #~ msgstr "Parámetro obligatorio indefinido: memberCallback\n" #~ msgid "Joined\n" #~ msgstr "Unido\n" #~ msgid "anonymous" #~ msgstr "anónimo" #~ msgid "(%s) `%s' said: %s\n" #~ msgstr "(%s) «%s» dijo: %s\n" #~ msgid "(%s) `%s' said to you: %s\n" #~ msgstr "(%s) «%s» te dijo: %s\n" #~ msgid "(%s) `%s' said for sure: %s\n" #~ msgstr "(%s) «%s» dijo para asegurarse: %s\n" #~ msgid "(%s) `%s' said to you for sure: %s\n" #~ msgstr "(%s) «%s» te dijo para asegurarse: %s\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you received: %s\n" #~ msgstr "(%s) «%s» confirmó que usted recibió: %s\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you and only you received: %s\n" #~ msgstr "(%s) «%s» confirmó que usted y sólo usted recibió: %s\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you received from him or her: %s\n" #~ msgstr "(%s) «%s» confirmó que usted recibió de él o ella: %s\n" #, fuzzy #~ msgid "" #~ "(%s) `%s' was confirmed that you and only you received from him or her: " #~ "%s\n" #~ msgstr "" #~ "(%s) «%s» confirmó que usted y sólo usted recibió de él o ella: %s\n" #, fuzzy #~ msgid "(%s) `%s' said off the record: %s\n" #~ msgstr "(%s) «%s» dijo en privado: %s\n" #~ msgid "(%s) <%s> said using an unknown message type: %s\n" #~ msgstr "(%s) <%s> dijo usando un tipo de mensaje desconocido: %s\n" #~ msgid "'%s' acknowledged message #%d\n" #~ msgstr "«%s» reconoció el mensaje #%d\n" #~ msgid "`%s' entered the room\n" #~ msgstr "«%s» entró en la sala\n" #~ msgid "`%s' left the room\n" #~ msgstr "«%s» dejó la sala\n" #~ msgid "Could not change username\n" #~ msgstr "No se pudo cambiar el nombre de usuario\n" #~ msgid "Joining room `%s' as user `%s'...\n" #~ msgstr "Uniéndose a la sala «%s» como usuario «%s»...\n" #~ msgid "Changed username to `%s'\n" #~ msgstr "Nombre de usuario cambiado a «%s»\n" #~ msgid "Users in room `%s': " #~ msgstr "Usuarios en sala «%s»" #~ msgid "Syntax: /msg USERNAME MESSAGE" #~ msgstr "Sintáxis: /msg USUARIO MENSAJE" #~ msgid "User `%s' is currently not in the room!\n" #~ msgstr "¡El usuario «%s» no está actualmente en la sala!\n" #~ msgid "" #~ "Use `/join #roomname' to join a chat room. Joining a room will cause you " #~ "to leave the current room" #~ msgstr "" #~ "Use «/join #nombre_de_sala» para unirse a una sala de chat. Unirse a una " #~ "sala provocará que deje su sala actual" #~ msgid "" #~ "Use `/nick nickname' to change your nickname. This will cause you to " #~ "leave the current room and immediately rejoin it with the new name." #~ msgstr "" #~ "Use «/nick apodo» para cambiar su apodo. Esto provocará que deje la sala " #~ "actual y se reconecte inmediatamente con el nuevo nombre." #~ msgid "" #~ "Use `/msg nickname message' to send a private message to the specified " #~ "user" #~ msgstr "" #~ "Use «/msg apodo mensaje» para mandar un mensaje privado al usuario " #~ "especificado" #~ msgid "The `/notice' command is an alias for `/msg'" #~ msgstr "El comando «/notice» es un alias para «/msg»" #~ msgid "The `/query' command is an alias for `/msg'" #~ msgstr "El comando «/query» es un alias para «/msg»" #~ msgid "Use `/sig message' to send a signed public message" #~ msgstr "Use «/sig mensaje» para mandar mensajes firmados públicamente" #~ msgid "Use `/ack message' to require signed acknowledgment of the message" #~ msgstr "" #~ "Use «/ack mensaje» para requerir una notificación firmada de la recepción " #~ "del mensaje" #~ msgid "Use `/anonymous message' to send a public anonymous message" #~ msgstr "Use «/anonymous mensaje» para mandar un mensaje anónimo público" #~ msgid "The `/anon' command is an alias for `/anonymous'" #~ msgstr "El comando «/anon» es un alias para «/anonymous»" #~ msgid "The `/leave' command is an alias for `/quit'" #~ msgstr "El comando «/leave» es un alias para «/quit»" #~ msgid "Use `/names' to list all of the current members in the chat room" #~ msgstr "" #~ "Use «/names» para mostrar una lista de los miembros actuales de la sala " #~ "de chat" #~ msgid "Failed to join room `%s'\n" #~ msgstr "Se produjo un fallo al unirse a la sala «%s»\n" #~ msgid "set the nickname to use (required)" #~ msgstr "fijar el apodo a usar (requerido)" #~ msgid "set the chat room to join" #~ msgstr "fija la sala de chat a la que unirse" #~ msgid "Join a chat on GNUnet." #~ msgstr "Unirse a un chat en GNUnet" #~ msgid "Failed to queue a message notification\n" #~ msgstr "Se produjo un fallo al encolar una notificación de mensaje\n" #~ msgid "Failed to queue a join notification\n" #~ msgstr "Se produjo un fallo al encolar una notificación de unión\n" #~ msgid "Failed to queue a confirmation receipt\n" #~ msgstr "Se produjo un fallo al encolar una confirmación de recepción\n" #~ msgid "Failed to queue a leave notification\n" #~ msgstr "Se produjo un fallo al encolar una notificación de abandono\n" #~ msgid "Core service could not access hostkey. Exiting.\n" #~ msgstr "" #~ "El servicio principal no puede acceder a la clave de la máquina. " #~ "Saliendo.\n" #~ msgid "# entries in session map" #~ msgstr "# entradas en el mapa de sesiones" #~ msgid "# reconnected to DATASTORE" #~ msgstr "# reconexiones al almacén de datos (DATASTORE)" #~ msgid "Unable to initialize Postgres with configuration `%s': %s" #~ msgstr "No se pudo inicializar Postgres con la configuración «%s»: %s" #~ msgid "Connected to %s service!\n" #~ msgstr "¡Conectado al servicio «%s»!\n" #~ msgid "# Peers connected" #~ msgstr "# Pares conectados" #~ msgid "Changing DNS reply according to client specifications\n" #~ msgstr "" #~ "Cambiando la respuesta DNS de acuerdo con las especificaciones del " #~ "cliente\n" #~ msgid "" #~ "Configured to provide DNS exit, but no valid DNS server configured!\n" #~ msgstr "" #~ "¡Configurado para proveer salida DNS, pero no hay ningún servidor DNS " #~ "válido configurado!\n" #~ msgid "Configuration fails to specify `%s' in section `%s'\n" #~ msgstr "" #~ "El fichero de configuración debe especificar «%s» en la sección «%s»\n" #~ msgid "Could not create namespace `%s'\n" #~ msgstr "No se pudo crear el espacio de nombres «%s»\n" #~ msgid "Configuration option `%s' in section `%s' missing.\n" #~ msgstr "Falta la opción «%s» en la sección «%s» de la configuración\n" #~ msgid "Configuration fails to specify `%s', assuming default value." #~ msgstr "" #~ "La configuración no especifica «%s», asumiendo el valor predeterminado." #~ msgid "" #~ "Invalid value specified for option `%s' in section `%s', content pushing " #~ "disabled\n" #~ msgstr "" #~ "Especificado valor no válido para la opción «%s» en la sección «%s», " #~ "publicación de contenido deshabilitada\n" #~ msgid "Issue a request to the GNUnet Naming System, prints results." #~ msgstr "" #~ "Iniciar una peticion al servicio de nombrado de GNUnet (GNS), imprimiendo " #~ "resultados." #~ msgid "No `%s' specified in `%s' configuration, will not bootstrap.\n" #~ msgstr "" #~ "No se ha especificado ningún «%s» en la configuración de «%s», no se " #~ "inicializará\n" #~ msgid "%s failed for `%s' at %s:%d: `%s'\n" #~ msgstr "%s falló para «%s» en %s:%d: «%s».\n" #~ msgid "Scheduled saving of hostlists\n" #~ msgstr "Guardados de listas de máquinas programados\n" #~ msgid "Hostlists will be saved to file again in %llums\n" #~ msgstr "" #~ "Las listas de máquinas serán guardadas a fichero de nuevo en %llums\n" #~ msgid "Initial time between hostlist downloads is %llums\n" #~ msgstr "El tiempo inicial entre descargas de listas de máquinas es %llums\n" #~ msgid "" #~ "No `%s' specified in `%s' configuration, cannot load hostlists from " #~ "file.\n" #~ msgstr "" #~ "No se ha especificado ningún «%s» en la configuración de «%s», no se pudo " #~ "cargar la lista de máquinas del fichero\n" #~ msgid "" #~ "No `%s' specified in `%s' configuration, cannot save hostlists to file.\n" #~ msgstr "" #~ "No se ha especificado ningún «%s» en la configuración de «%s», no se " #~ "puede almacenar la lista de máquinas en un fichero.\n" #~ msgid "Hostlists will be saved to file again in %llums\n" #~ msgstr "" #~ "Las listas de máquinas serán guardadas a fichero de nuevo en %llums\n" #~ msgid "Sending 100 CONTINUE reply\n" #~ msgstr "Enviando respuesta «100 CONTINUE»\n" #~ msgid "Mesh service is lacking key configuration settings. Exiting.\n" #~ msgstr "" #~ "El servicio mesh carece de opciones de configuración de clave. " #~ "Saliendo.\n" #~ msgid "NSE service could not access hostkey. Exiting.\n" #~ msgstr "" #~ "El servicio NSE no puede acceder a la clave de la máquina. Saliendo.\n" #~ msgid "Failed to transmit iteration request to `PEERINFO' service\n" #~ msgstr "" #~ "Petición de transmisión de iteración de expiración al servicio de " #~ "información de pares (PEERINFO).\n" #~ msgid "Could not read hostkeys file, specify hostkey file with -H!\n" #~ msgstr "" #~ "¡No se pudo leer el fichero de claves de máquina, especifique el fichero " #~ "de claves de máquina con -H!\n" #~ msgid "Specified hostkey file `%s' not found!\n" #~ msgstr "" #~ "¡El fichero de claves de máquina especificado %s no fue encontrado!\n" #~ msgid "host key file" #~ msgstr "fichero de clave de máquina" #~ msgid "Peer is lacking HOSTKEY configuration setting.\n" #~ msgstr "El par carece de configuración de claves de máquina (HOSTKEY).\n" #~ msgid "`scp' does not seem to terminate (timeout copying config).\n" #~ msgstr "" #~ "Parece que «scp» no termina (expiración de plazo copiando la " #~ "configuración).\n" #~ msgid "`scp' did not complete cleanly.\n" #~ msgstr "«scp» no se completó limpiamente.\n" #~ msgid "Failed to create pipe for `gnunet-peerinfo' process.\n" #~ msgstr "" #~ "Se produjo un fallo al crear la tubería para el proceso «gnunet-" #~ "peerinfo».\n" #~ msgid "Failed to create pipe for `ssh' process.\n" #~ msgstr "Se produjo un fallo al crear la tubería para el proceso «ssh».\n" #~ msgid "Could not start `%s' process to create hostkey.\n" #~ msgstr "" #~ "No se pudo iniciar el proceso «%s» para crear la clave de máquina.\n" #~ msgid "Failed to start `ssh' process.\n" #~ msgstr "Se produjo un fallo al iniciar el proceso «ssh».\n" #~ msgid "Error reading from gnunet-peerinfo: %s\n" #~ msgstr "Error leyendo de «gnunet-peerinfo»: %s\n" #~ msgid "Malformed output from gnunet-peerinfo!\n" #~ msgstr "¡Salida mal formada de «gnunet-peerinfo»!\n" #~ msgid "Could not start `%s' process to start GNUnet.\n" #~ msgstr "No se pudo iniciar el proceso «%s» para iniciar GNUnet.\n" #~ msgid "Failed to start `gnunet-arm' process.\n" #~ msgstr "Se produjo un fallo al iniciar el proceso «gnunet-arm».\n" #~ msgid "`gnunet-arm' does not seem to terminate.\n" #~ msgstr "Parece que «gnunet-arm» no termina.\n" #~ msgid "`ssh' does not seem to terminate.\n" #~ msgstr "«ssh» no parece terminar.\n" #~ msgid "Unable to get HELLO for peer!\n" #~ msgstr "¡Imposible obtener «HELLO» del par!\n" #~ msgid "`gnunet-arm' terminated with non-zero exit status (or timed out)!\n" #~ msgstr "" #~ "¡«gnunet-arm» terminó con un estado de salida no cero (o expiró el " #~ "plazo)!\n" #~ msgid "shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n" #~ msgstr "" #~ "el apagado (o bien «gnunet-arm» o bien «ssh») no se completó " #~ "limpiamente.\n" #~ msgid "`scp' does not seem to terminate.\n" #~ msgstr "«scp» no parece terminar.\n" #~ msgid "Could not start `%s' process to copy configuration directory.\n" #~ msgstr "" #~ "No se pudo iniciar el proceso «%s» para copiar el directorio de " #~ "configuración.\n" #~ msgid "Terminating peer `%4s'\n" #~ msgstr "Terminando par «%4s»\n" #~ msgid "Setting d->dead on peer `%4s'\n" #~ msgstr "Fijando d->dead en el par «%4s»\n" #~ msgid "Peer not yet running, can not change configuration at this point." #~ msgstr "" #~ "Par todavía no ejecutandose, no se puede cambiar la configuración en este " #~ "punto." #~ msgid "Failed to write new configuration to disk." #~ msgstr "Se produjo un fallo al guardar la nueva configuración al disco" #~ msgid "Could not start `%s' process to copy configuration file.\n" #~ msgstr "" #~ "No se pudo iniciar el proceso «%s» para copiar el fichero de " #~ "configuración.\n" #~ msgid "Failed to copy new configuration to remote machine." #~ msgstr "" #~ "Se produjo un fallo al copiar la nueva configuración a la máquina remota." #~ msgid "Peers failed to connect" #~ msgstr "Los pares fallaron al conectar" #~ msgid "Failed to connect to core service of first peer!\n" #~ msgstr "" #~ "¡Se produjo un fallo al conectar con el servicio principal del primer " #~ "par!\n" #~ msgid "Peers are not fully running yet, can not connect!\n" #~ msgstr "" #~ "¡Los pares no están ejecutandose completamente todavía, no puedo " #~ "conectarme!\n" #~ msgid "Invalid value `%s' for option `%s' in section `%s': expected float\n" #~ msgstr "" #~ "Valor «%s» no válido para la opción «%s» en la sección «%s»: se esperaba " #~ "un float\n" #~ msgid "Target is %d connections per peer." #~ msgstr "El objetivo son %d conexiones por par" #~ msgid "" #~ "Invalid value `%s' for option `%s' in section `%s': got %f, needed value " #~ "greater than 0\n" #~ msgstr "" #~ "Valor «%s» no válido para la opción «%s» en la sección «%s»: se obtuvo " #~ "%f, se necesitaba un valor mayor que 0\n" #~ msgid "Connecting nodes in 2d torus topology: %u rows %u columns\n" #~ msgstr "" #~ "Conectando nodos en topología tórica bidimensional: %u filas %u columnas\n" #~ msgid "natural log of %d is %d, will run %d iterations\n" #~ msgstr "el logaritmo natural de %d es %d, se ejecutará %d iteraciones\n" #~ msgid "Total connections added thus far: %u!\n" #~ msgstr "¡Conexiones totales añadidas hasta ahora: %u!\n" #~ msgid "Total connections added for small world: %d!\n" #~ msgstr "¡Conexiones totales añadidas para el mundo pequeño: %d!\n" #~ msgid "rand is %f probability is %f\n" #~ msgstr "aleatorio es %f probabilidad es %f\n" #~ msgid "" #~ "No `%s' specified in peer configuration in section `%s', cannot copy " #~ "friends file!\n" #~ msgstr "" #~ "¡No se especifica «%s» en la configuración del par en la sección «%s», no " #~ "se puede copiar el archivo de amigos!\n" #~ msgid "Finished copying all friend files!\n" #~ msgstr "¡Se terminó de copiar todos los ficheros de amigos!\n" #~ msgid "Copying file with command cp %s %s\n" #~ msgstr "Copiando fichero con el comando «cp %s %s»\n" #~ msgid "Copying file with command scp %s %s\n" #~ msgstr "Copiando fichero con el comando «scp %s %s»\n" #~ msgid "Checking copy status of file %d\n" #~ msgstr "Comprobando el estado de la copia del fichero %d\n" #~ msgid "File %d copied\n" #~ msgstr "Fichero %d copiado\n" #~ msgid "Finished copying all blacklist files!\n" #~ msgstr "¡Se terminaron de copiar todos los ficheros de listas negras!\n" #~ msgid "Delaying connect, we have too many outstanding connections!\n" #~ msgstr "" #~ "¡Retrasando la conexión, tenemos demasiadas conexiones pendientes!\n" #~ msgid "Creating connection, outstanding_connections is %d\n" #~ msgstr "" #~ "Creando conexion, %d conexiones pendientes (outstanding_connections)\n" #~ msgid "Creating connection, outstanding_connections is %d (max %d)\n" #~ msgstr "" #~ "Creando conexion, %d conexiones pendientes (outstanding_connections), " #~ "máximo %d\n" #~ msgid "Creating clique topology\n" #~ msgstr "Creando topología de clique\n" #~ msgid "Creating small world (ring) topology\n" #~ msgstr "Creando topología de mundo pequeño (anillo)\n" #~ msgid "Creating small world (2d-torus) topology\n" #~ msgstr "Creando topología de mundo pequeño (tórica bidimensional)\n" #~ msgid "Creating ring topology\n" #~ msgstr "Creando topología de anillo\n" #~ msgid "Creating 2d torus topology\n" #~ msgstr "Creando topología tórica bidimensional\n" #~ msgid "Creating Erdos-Renyi topology\n" #~ msgstr "Creando topología Erdos-Renyi\n" #~ msgid "Creating InterNAT topology\n" #~ msgstr "Creando topología InterNAT\n" #~ msgid "Creating Scale Free topology\n" #~ msgstr "Creando topología Scale Free\n" #~ msgid "Creating straight line topology\n" #~ msgstr "Creando topología de línea recta\n" #~ msgid "Creating no allowed topology (all peers can connect at core level)\n" #~ msgstr "" #~ "Creando topología no permitida (todos los pares se pueden conectar al " #~ "nivel del servicio principal)\n" #~ msgid "Failed during friend file copying!\n" #~ msgstr "¡Se produjo un fallo durante la copia del fichero de amigos!\n" #~ msgid "Friend files created/copied successfully!\n" #~ msgstr "¡Ficheros de amigos creados/copiados satisfactoriamente!\n" #~ msgid "Blacklisting all but clique topology\n" #~ msgstr "Añadiendo a la lista negra todas las topologías excepto clique\n" #~ msgid "Blacklisting all but small world (ring) topology\n" #~ msgstr "" #~ "Añadiendo a la lista negra todas las topologías excepto mundo pequeño " #~ "(anillo)\n" #~ msgid "Blacklisting all but small world (2d-torus) topology\n" #~ msgstr "" #~ "Añadiendo a la lista negra todas las topologías excepto mundo pequeño " #~ "(tórica bidimensional)\n" #~ msgid "Blacklisting all but ring topology\n" #~ msgstr "Añadiendo a la lista negra todas las topologías excepto anillo\n" #~ msgid "Blacklisting all but 2d torus topology\n" #~ msgstr "" #~ "Añadiendo a la lista negra todas las topologías excepto tórica " #~ "bidimensional\n" #~ msgid "Blacklisting all but Erdos-Renyi topology\n" #~ msgstr "" #~ "Añadiendo a la lista negra todas las topologías excepto Erdos-Renyi\n" #~ msgid "Blacklisting all but InterNAT topology\n" #~ msgstr "Añadiendo a la lista negra todas las topologías excepto InterNAT\n" #~ msgid "Blacklisting all but Scale Free topology\n" #~ msgstr "" #~ "Añadiendo a la lista negra todas las topologías excepto Scale Free\n" #~ msgid "Blacklisting all but straight line topology\n" #~ msgstr "" #~ "Añadiendo a la lista negra todas las topologías excepto línea recta\n" #~ msgid "Failed during blacklist file copying!\n" #~ msgstr "" #~ "¡Se produjo un fallo durante la copia del fichero de listas negras!\n" #~ msgid "Blacklist files created/copied successfully!\n" #~ msgstr "¡Ficheros de listas negras creados/copiados satisfactoriamente!\n" #, fuzzy #~ msgid "Creating clique CONNECT topology\n" #~ msgstr "Creando topología de anillo «CONNECT»\n" #, fuzzy #~ msgid "Creating small world (ring) CONNECT topology\n" #~ msgstr "Creando topología de mundo pequeño (anillo) «CONNECT»\n" #, fuzzy #~ msgid "Creating small world (2d-torus) CONNECT topology\n" #~ msgstr "" #~ "Añadiendo a la lista negra todas las topologías excepto mundo pequeño " #~ "(tórica bidimensional) «CONNECT»\n" #, fuzzy #~ msgid "Creating ring CONNECT topology\n" #~ msgstr "Creando topología de anillo «CONNECT»\n" #, fuzzy #~ msgid "Creating 2d torus CONNECT topology\n" #~ msgstr "Creando topología tórica bidimensional «CONNECT»\n" #, fuzzy #~ msgid "Creating Erdos-Renyi CONNECT topology\n" #~ msgstr "Creando topología Erdos-Renyi «CONNECT»\n" #, fuzzy #~ msgid "Creating InterNAT CONNECT topology\n" #~ msgstr "Creando topología InterNAT «CONNECT»\n" #, fuzzy #~ msgid "Creating Scale Free CONNECT topology\n" #~ msgstr "Creando topología Scale Free «CONNECT»\n" #, fuzzy #~ msgid "Creating straight line CONNECT topology\n" #~ msgstr "Creando topología de línea recta «CONNECT»\n" #, fuzzy #~ msgid "Creating no CONNECT topology\n" #~ msgstr "No se crea ninguna topología «CONNECT»\n" #~ msgid "Unknown topology specification, can't connect peers!\n" #~ msgstr "" #~ "¡Especificación de topología desconocida, no se puede conectar con los " #~ "pares!\n" #~ msgid "Connecting random subset (%'.2f percent) of possible peers\n" #~ msgstr "" #~ "Conectando a un subconjunto aleatorio (%'.2f por ciento) de posibles " #~ "pares\n" #~ msgid "Connecting a minimum of %u peers each (if possible)\n" #~ msgstr "Conectando a un mínimo de %u pares cada uno (si es posible)\n" #~ msgid "Using DFS to connect a minimum of %u peers each (if possible)\n" #~ msgstr "" #~ "Usando DFS para conectar a un mínimo de %u pares cada uno (si es " #~ "posible)\n" #~ msgid "Finding additional %u closest peers each (if possible)\n" #~ msgstr "" #~ "Encontrando %u pares adicionales mas cercanos cada uno (si es posible)\n" #~ msgid "Could not create configuration for peer number %u on `%s'!\n" #~ msgstr "" #~ "¡No se puede crear la configuración para el par número %u en «%s»!\n" #~ msgid "Option `%s' in section `%s' not specified!\n" #~ msgstr "¡No se ha especificado la opción «%s» en la sección «%s»!\n" #~ msgid "# bytes payload received for other peers" #~ msgstr "# bytes de «payload» recibidos de otros pares" #~ msgid "# failed connection attempts due to timeout" #~ msgstr "# conexiones fallidas debido a expiración de plazo" #~ msgid "# peers disconnected due to external request" #~ msgstr "# pares desconectados debido a petición externa" #~ msgid "# peers disconnected due to timeout" #~ msgstr "# pares desconectados debido a expiración de plazo" #~ msgid "# peers disconnected due to global disconnect" #~ msgstr "# pares desconectados debido a desconexión global" #~ msgid "# messages not sent (no such peer or not connected)" #~ msgstr "# mensajes no enviados (no existe tal par o no está conectado)" #~ msgid "# KEEPALIVE messages discarded (not connected)" #~ msgstr "# mensajes «KEEPALIVE» descartados (no conectado)" #~ msgid "# unexpected CONNECT_ACK messages" #~ msgstr "# mensajes «CONNECT_ACK» inesperados" #~ msgid "FREEING %s\n" #~ msgstr "LIBERANDO %s\n" #~ msgid "Found valid IPv4 NAT address (creating session)!\n" #~ msgstr "¡Encontrada una dirección NAT IPv4 válida (creando sesión)!\n" #~ msgid "Failed to find option %s in section %s!\n" #~ msgstr "¡Se produjo un fallo al buscar la opción %s en la sección %s!\n" #~ msgid "# wlan session timeouts" #~ msgstr "# expiraciones de plazo en sesiones wlan" #~ msgid "# wlan session created" #~ msgstr "# sesiones wlan creadas" #~ msgid "# wlan pending sessions" #~ msgstr "# sesiones wlan pendientes" #~ msgid "# wlan pending fragments" #~ msgstr "# fragmentos wlan pendientes" #~ msgid "" #~ "Finished reading from gnunet-helper-transport-wlan stdout with code: %d\n" #~ msgstr "" #~ "Se terminó de leer la salida estándar de «gnunet-helper-transport-wlan» " #~ "con código: %d\n" #~ msgid "# wlan hello beacons send" #~ msgstr "# beacons hello de wlan enviados" #~ msgid "Error writing to wlan helper. errno == %d, ERROR: %s\n" #~ msgstr "" #~ "Error escribiendo al programa auxiliar para wlan. errno == %d, ERROR: %s" #~ msgid "# wlan acks send" #~ msgstr "# acks de wlan enviados" #~ msgid "# wlan fragments send" #~ msgstr "# fragmentos wlan enviados" #~ msgid "Wlan Address len %d is wrong\n" #~ msgstr "La longitud %d de la dirección Wlan es incorrecta\n" #~ msgid "# wlan mac endpoints" #~ msgstr "# destinos mac de wlan" #~ msgid "# wlan whole messages received" #~ msgstr "# mensajes completos de wlan recibidos" #~ msgid "# wlan hello messages received" #~ msgstr "# mensajes hello de wlan recibidos" #~ msgid "# wlan fragments received" #~ msgstr "# fragmentos wlan recibidos" #~ msgid "# wlan acks received" #~ msgstr "# acks de wlan recibidos" #~ msgid "# wlan mac endpoints timeouts" #~ msgstr "# expiraciones de plazo en destinos mac de wlan" #~ msgid "# wlan mac endpoints created" #~ msgstr "# destinos mac de wlan creados" #~ msgid "# wlan WLAN_HELPER_DATA received" #~ msgstr "# WLAN_HELPER_DATA de wlan recibidos" #~ msgid "# wlan messages for this client received" #~ msgstr "# mensajes de wlan para este cliente recibidos" #~ msgid "# wlan messages inside WLAN_HELPER_DATA received" #~ msgstr "# mensajes de wlan dentro de WLAN_HELPER_DATA recibidos" #~ msgid "Syntax error in configuration file `%s' at line %u.\n" #~ msgstr "" #~ "Error de sintáxis en el fichero de configuración «%s» en la línea %u.\n" #~ msgid "" #~ "Could not satisfy pending transmission request, socket closed or connect " #~ "failed (%p).\n" #~ msgstr "" #~ "No se pudo satisfacer la petición de transmisión pendiente, «socket» " #~ "cerrado o conexión fallida (%p).\n" #~ msgid "I am host `%s'. Stored new private key in `%s'.\n" #~ msgstr "Yo soy la máquina «%s». Almacenada nueva clave privada en «%s».\n" #~ msgid "I am host `%s'. Read private key from `%s'.\n" #~ msgstr "Soy el host «%s». Leida clave privada de «%s».\n" #~ msgid "Resolver asked to look up `%s'.\n" #~ msgstr "El resolvedor solicitó buscar «%s».\n" #, fuzzy #~ msgid "Resolver asked to look up IP address `%s'.\n" #~ msgstr "El resolvedor solicitó buscar la dirección IP «%s»\n" #~ msgid "Got 0 bytes from helper `%s' (EOF)\n" #~ msgstr "Se obtuvieron 0 bytes del programa auxiliar «%s» (EOF)\n" #~ msgid "Got %u bytes from helper `%s'\n" #~ msgstr "Se obtuvieron %u bytes del programa auxiliar «%s»\n" #~ msgid "access (%s, X_OK) failed: %s\n" #~ msgstr "acceso (%s, X_OK) falló: %s\n" #~ msgid "Resolver returns `%s' for IP `%s'.\n" #~ msgstr "El resolvedor devuelve «%s» para la IP «%s».\n" #, fuzzy #~ msgid "Resolver returns `%s'.\n" #~ msgstr "El resolvedor devuelve «%s».\n" #, fuzzy #~ msgid "Resolving our FQDN `%s'\n" #~ msgstr "Resolviendo nuestro nombre de dominio cualificado (FQDN) «%s»\n" #~ msgid "eternity" #~ msgstr "eternidad" #~ msgid "" #~ "Unknown user `%s'. Make sure you specify its numeric suffix, if any.\n" #~ msgstr "" #~ "Usuario desconocido «%s». Asegurese de especificar su sufíjo numérico, en " #~ "el caso de que lo haya.\n" #~ msgid "how long to execute? 0 = forever" #~ msgstr "¿cuánto tiempo se debe ejecutar? 0 = para siempre" #~ msgid "Lookup a record using GNS (NOT IMPLEMENTED)" #~ msgstr "Busca un registro usando GNS (NO IMPLEMENTADO)" #~ msgid "Option `%s' not specified in configuration section `%s'\n" #~ msgstr "" #~ "No se ha especificado la opción «%s» en la sección de configuración «%s»\n" #~ msgid "Option `%s' not given, but I need a zone key file!\n" #~ msgstr "" #~ "¡No se proporciona la opción «%s», pero se necesita un fichero de claves " #~ "de zona!\n" #~ msgid "" #~ "File zone `%s' but corrupt content already exists, failed to write! \n" #~ msgstr "" #~ "¡Ya existe el fichero de zonas «%s» pero con contenido corrupto, falló al " #~ "escribir!\n" #~ msgid "File zone `%s' containing this key already exists\n" #~ msgstr "Ya existe un fichero de zonas «%s» que contiene esta clave\n" #~ msgid "" #~ "File zone `%s' but different zone key already exists, failed to write! \n" #~ msgstr "" #~ "¡Ya existe el fichero de zonas «%s» pero con diferentes claves de zona, " #~ "falló al escribir!\n" #~ msgid "Stored zonekey for zone `%s' in file `%s'\n" #~ msgstr "Almacenada clave de zona para la zona «%s» en el fichero «%s»\n" #~ msgid "No records for entry" #~ msgstr "No hay registros para la entrada" #~ msgid "tmppath cannot be NULL\n" #~ msgstr "tmppath no puede ser NULL\n" #~ msgid "Invalid configuration option `%s' in section `%s'\n" #~ msgstr "Opción de configuración «%s» en la sección «%s» no válida\n" #~ msgid "Missing configuration option `%s' in section `%s'\n" #~ msgstr "Falta la opción de configuración «%s» en la sección «%s»\n" #, fuzzy #~ msgid "" #~ "provide inthe 'struct GNUNET_TRANSPORT_PeerIterateContextformation about " #~ "all tunnels (continuously)" #~ msgstr "Imprime información de los pares de GNUnet." #, fuzzy #~ msgid "Key file `%s' for private zone does not exist!\n" #~ msgstr "número de mensajes a usar por iteración" #, fuzzy #~ msgid "internal error" #~ msgstr "Error desconocido.\n" #, fuzzy #~ msgid "Copying file with RENAME (%s,%s)\n" #~ msgstr "'%s' falló con el código de error %s: %s" #, fuzzy #~ msgid "Failed to send to `%s': %s\n" #~ msgstr "Fichero almacenado en '%s'.\n" #, fuzzy #~ msgid "Could not access file: %s\n" #~ msgstr "Imposible ejecutar '%s': %s\n" #, fuzzy #~ msgid "`%s' failed on file `%s': %s" #~ msgstr "'%s' falló para la unidad %s: %u\n" #, fuzzy #~ msgid "# bytes TCP was asked to transmit" #~ msgstr "# bytes descifrados" #, fuzzy #~ msgid "# bytes discarded by TCP (failed to connect)" #~ msgstr "# bytes omitidos por TCP (salientes)" #, fuzzy #~ msgid "# wlan messages queued" #~ msgstr "# mensajes WLAN encolados" #~ msgid "print this help" #~ msgstr "imprime esta ayuda" #~ msgid "print the version number" #~ msgstr "imprime el número de versión" #, fuzzy #~ msgid "Failed to start service `%s'!\n" #~ msgstr "Falló al comenzar la recolección.\n" #, fuzzy #~ msgid "Binary implementing service `%s' not known!\n" #~ msgstr "La verificación de la firma falló: el par '%s' no es conocido.\n" #, fuzzy #~ msgid "Service `%s' stopped\n" #~ msgstr "Servicio eliminado.\n" #, fuzzy #~ msgid "Unable to accept connection for service `%s': %s\n" #~ msgstr "Imposible guardar el fichero de configuración '%s':" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "MiB" #~ msgstr "MiB" #~ msgid "GiB" #~ msgstr "GiB" #~ msgid "TiB" #~ msgstr "TiB" #, fuzzy #~ msgid "Failed to create IPv4 broadcast socket on port %d\n" #~ msgstr "Falló al actualizar los datos del módulo '%s'\n" #, fuzzy #~ msgid "Failed to load block plugin `%s'\n" #~ msgstr "Imposible inicializar la aplicación '%s'\n" #, fuzzy #~ msgid "Could not resolve our FQDN : %s %u\n" #~ msgstr "Imposible resolver '%s': %s\n" #, fuzzy #~ msgid "Failed to load dhtlog plugin for `%s'\n" #~ msgstr "Imposible inicializar la aplicación '%s'\n" #, fuzzy #~ msgid "Found peer `%s'\n" #~ msgstr "Yo soy el par '%s'.\n" #, fuzzy #~ msgid "Failed to initialize MySQL database connection for dhtlog.\n" #~ msgstr "Imposible inicializar SQLite.\n" #, fuzzy #~ msgid "Loading udp transport plugin\n" #~ msgstr "Probando transporte(s) %s\n" #, fuzzy #~ msgid "curl failed for `%s' at %s:%d: `%s'\n" #~ msgstr "'%s' falló en %s: %d con error: '%s'.\n" #, fuzzy #~ msgid "Phase 3: sending messages\n" #~ msgstr "Falló al entregar el mensaje '%s'.\n" #, fuzzy #~ msgid "Loading HTTPS transport plugin `%s'\n" #~ msgstr "Probando transporte(s) %s\n" #, fuzzy #~ msgid "Failed to load transport plugin for https\n" #~ msgstr "Imposible inicializar la aplicación '%s'\n" #, fuzzy #~ msgid "Fail! Could not connect peers\n" #~ msgstr "'%s': Imposible conectar.\n" #, fuzzy #~ msgid "Loading tcp transport plugin\n" #~ msgstr "Probando transporte(s) %s\n" #, fuzzy #~ msgid "Failed to load transport plugin for tcp\n" #~ msgstr "Imposible inicializar la aplicación '%s'\n" #, fuzzy #~ msgid "# HTTP peers active" #~ msgstr "# bytes recibidos por TCP" #, fuzzy #~ msgid "Misconfigured address to bind to in configuration!\n" #~ msgstr "¡Ninguna aplicación definida en la configuración!\n" #, fuzzy #~ msgid "Failed to load transport plugin for http\n" #~ msgstr "Imposible inicializar la aplicación '%s'\n" #, fuzzy #~ msgid "# PING messages decrypted" #~ msgstr "# mensajes defragmentados" #, fuzzy #~ msgid "# bytes successfully transmitted by plugins" #~ msgstr "# bytes transmitidos satisfactoriamente por los módulos" #, fuzzy #~ msgid "# transport failed to selected peer address" #~ msgstr "Anunciando mi transporte %d a los pares seleccionados.\n" #, fuzzy #~ msgid "# peer addresses considered valid" #~ msgstr "# Anuncios de los pares recibidos" #, fuzzy #~ msgid "# PING with HELLO messages sent" #~ msgstr "# mensajes de texto mandados por PING" #, fuzzy #~ msgid "# HELLOs received for validation" #~ msgstr "# blocks migrados" #, fuzzy #~ msgid "Received `%s' message from `%s' destined for `%s' which is not me!\n" #~ msgstr "¡Recibido PING no destinado a nosotros!\n" #, fuzzy #~ msgid "Could not send PONG to `%s': no address available\n" #~ msgstr "¡Imposible encontrar el par '%s' en la tabla de enrutado!\n" #, fuzzy #~ msgid "# HELLO messages received from other peers" #~ msgstr "Mensaje '%s' inválido recibido del par '%s'.\n" #~ msgid "Error" #~ msgstr "Error" #~ msgid "Help" #~ msgstr "Ayuda" #~ msgid "Error!" #~ msgstr "¡Error!" #~ msgid "No" #~ msgstr "No" #~ msgid "Yes" #~ msgstr "Sí" #, fuzzy #~ msgid "Abort" #~ msgstr "_Acerca de" #, fuzzy #~ msgid "Ok" #~ msgstr "k" #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://gnunet.org/\n" #~ "and join our community at\n" #~ "\thttp://gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "the GNUnet team" #~ msgstr "" #~ "¡Bienvenido a GNUnet!\n" #~ "\n" #~ "Este asistente te preguntará unas cuestiones básicas para configurar " #~ "GNUnet.\n" #~ "\n" #~ "Por favor, visita nuestra página en\n" #~ "\thttp://gnunet.org/\n" #~ "y únete a nuestra comunidad en \n" #~ "\thttp://gnunet.org/drupal/\n" #~ "\n" #~ "Diviertete,\n" #~ "\n" #~ "el equipo de GNUnet" #~ msgid "" #~ "Choose the network interface that connects your computer to the internet " #~ "from the list below." #~ msgstr "" #~ "Escoge la interfaz de red que conecta tu ordenador a Internet de la lista " #~ "de abajo." #~ msgid "" #~ "The \"Network interface\" is the device that connects your computer to " #~ "the internet. This is usually a modem, an ISDN card or a network card in " #~ "case you are using DSL." #~ msgstr "" #~ "La \"Interfaz de red\" es el dispositivo que conecta tu ordenador a " #~ "Internet. Normalmente es un módem, una tarjeta de RDSI o una tarjeta de " #~ "red en el caso de los xDSL como el ADSL." #, fuzzy #~ msgid "Network configuration: interface" #~ msgstr "Interfaz de red:" #~ msgid "" #~ "What is the name of the network interface that connects your computer to " #~ "the Internet?" #~ msgstr "" #~ "¿Cuál es el nombre de la interfaz de red que conecta tu ordenador a " #~ "Internet?" #, fuzzy #~ msgid "Network configuration: IP" #~ msgstr "Configuración de GNUnet" #, fuzzy #~ msgid "What is this computer's public IP address or hostname?" #~ msgstr "" #~ "¿Cuál es es la dirección pública IP o el nombre del dominio de éste " #~ "ordenador?\n" #~ "\n" #~ "En caso de duda, dejar este campo en blanco." #, fuzzy #~ msgid "" #~ "If your provider always assigns the same IP-Address to you (a \"static\" " #~ "IP-Address), enter it into the \"IP-Address\" field. If your IP-Address " #~ "changes every now and then (\"dynamic\" IP-Address) but there's a " #~ "hostname that always points to your actual IP-Address (\"Dynamic DNS\"), " #~ "you can also enter it here.\n" #~ "If left empty, GNUnet will try to automatically detect the IP.\n" #~ "You can specify a hostname, GNUnet will then use DNS to resolve it.\n" #~ "If in doubt, leave this empty." #~ msgstr "" #~ "Si tu proveedor siempre te asigna la misma dirección IP (una IP \"estática" #~ "\") introducela en el campo \"Dirección IP\". Si tu dirección IP cambia " #~ "pero hay un nombre de dominio que siempre apunta a tu dirección IP actual " #~ "(\"DNS dinámica\"), puedes introducirlo allí también.\n" #~ "En caso de duda deja el campo en blanco. GNUnet intentará determinar tu " #~ "dirección IP" #, fuzzy #~ msgid "Bandwidth configuration: upload" #~ msgstr "Configuración de GNUnet" #, fuzzy #~ msgid "How much upstream bandwidth (in bytes/s) may be used?" #~ msgstr "¿Cuánta subida (Bytes/s) será usada por GNUnet?" #, fuzzy #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "The \"upstream\" is the data channel through which data is *sent* to the " #~ "internet. The limit is the maximum amount which GNUnet is allowed to use. " #~ "If you have a flatrate, you can set it to the maximum speed of your " #~ "internet connection. You should not use a value that is higher than what " #~ "your actual connection allows." #~ msgstr "" #~ "Puedes limitar el uso de recursos de GNUnet aquí.\n" #~ "\n" #~ "La \"subida\" es el canal de datos a través del cual los datos son " #~ "*mandados* a Internet. El límite, o bien es el total máximo para este " #~ "ordenador, o bien el que se le permita usar a GNUnet. Puedes especificar " #~ "este valor más tarde. Si tienes una tarifa plana puedes configurarlo a la " #~ "máxima velocidad de tu conexión a Internet." #, fuzzy #~ msgid "Bandwidth configuration: download" #~ msgstr "Configuración de GNUnet" #, fuzzy #~ msgid "How much downstream bandwidth (in bytes/s) may be used?" #~ msgstr "¿Cuánta bajada (Bytes/s) será usada por GNUnet?" #, fuzzy #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "The \"downstream\" is the data channel through which data is *received* " #~ "from the internet. The limit is the maximum amount which GNUnet is " #~ "allowed to use. If you have a flatrate, you can set it to the maximum " #~ "speed of your internet connection. You should not use a value that is " #~ "higher than what your actual connection allows." #~ msgstr "" #~ "Puedes limitar el uso de recursos de GNUnet aquí.\n" #~ "\n" #~ "La \"bajada\" es el canal de datos a través del cuál los datos son " #~ "*recibidos* de Internet. El límite, o bien es el total máximo de este " #~ "ordenador, o bien el que se le permita usar a GNUnet. Puedes especificar " #~ "este valor más tarde. Si tienes una tarifa plana puedes configurarlo a la " #~ "máxima velocidad de tu conexión a Internet." #, fuzzy #~ msgid "Quota configuration" #~ msgstr "Configuración de GNUnet" #, fuzzy #~ msgid "" #~ "The GNUnet datastore contains all content that GNUnet needs to store " #~ "(indexed, inserted and migrated content)." #~ msgstr "" #~ "¿Cuál es el tamaño máximo de almacenamiento en MB?\n" #~ "\n" #~ "El almacenamiento de GNUnet contiene todos los datos que GNUnet genera " #~ "(datos del índice, contenido insertado y migrado)." #, fuzzy #~ msgid "Daemon configuration: user account" #~ msgstr "Imposible crear la cuenta de usuario:" #, fuzzy #~ msgid "" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "user account under which the GNUnet service is started at system " #~ "startup.\n" #~ "\n" #~ "However, GNUnet may not be able to access files other than its own. This " #~ "includes files you want to publish in GNUnet. You'll have to grant read " #~ "permissions to the user specified below.\n" #~ "\n" #~ "Leave the field empty to run GNUnet with system privileges.\n" #~ msgstr "" #~ "Define el usuario bajo el que correrán los servicios de GNUnet.\n" #~ "\n" #~ "Por razones de seguridad, es una buena idea dejar que la configuración " #~ "cree una nueva cuenta de usuario bajo el cual el servicio de GNUnet es " #~ "arrancado al iniciar el sistema.\n" #~ "\n" #~ "Por consiguiente, GNUnet no tiene la posibilidad de acceder a otros " #~ "ficheros que no sean los que posee. Ésto incluye los ficheros que quieras " #~ "publicar en GNUnet. Tendrás que garantizar que el usuario especificado " #~ "aquí posea permisos de lectura.\n" #~ "\n" #~ "Deja los campos vacíos para arrancar GNUnet con privilegios de sistema.\n" #~ "Usuario de GNUnet:" #, fuzzy #~ msgid "" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "group for the chosen user account.\n" #~ "\n" #~ "You can also specify a already existent group here.\n" #~ "\n" #~ "Only members of this group will be allowed to start and stop the the " #~ "GNUnet server and have access to GNUnet server data.\n" #~ msgstr "" #~ "Define el grupo bajo el que correrán los servicios de GNUnet aquí.\n" #~ "\n" #~ "Por razones de seguridad, es una buena idea dejar que la configuración " #~ "cree un nuevo grupo para la cuenta de usuario creada.\n" #~ "\n" #~ "Puedes especificar un grupo ya existente aquí.\n" #~ "\n" #~ "Sólo los miembros de este grupo esta autorizados a arrancar y parar el " #~ "servidor de GNUnet y tener acceso a los datos del servidor de GNUnet.\n" #~ "\n" #~ "Grupo de GNUnet:" #, fuzzy #~ msgid "" #~ "If you say \"yes\" here, the GNUnet background process will be " #~ "automatically started when you turn on your computer. If you say \"no\" " #~ "here, you have to launch GNUnet yourself each time you want to use it." #~ msgstr "" #~ "¿Quieres arrancar GNUnet como un servicio de sistema?\n" #~ "n\n" #~ "Si dices \"sí\" aquí, el proceso en segundo plano de GNUnet sera " #~ "automáticamente arrancado cuando enciendas tu ordenador. Si dices \"no\" " #~ "aquí, tendrás que ejecutar GNUnet tu mismo cada vez que quieras usarlo." #, fuzzy #~ msgid "Unable to create user account for daemon." #~ msgstr "Imposible crear la cuenta de usuario:" #, fuzzy #~ msgid "Save configuration?" #~ msgstr "Configuración de GNUnet" #, fuzzy #~ msgid "GNUnet Configuration" #~ msgstr "Configuración de GNUnet" #~ msgid "Back" #~ msgstr "Atrás" #~ msgid "Up" #~ msgstr "Arriba" #~ msgid "Cancel" #~ msgstr "Cancelar" #, fuzzy #~ msgid "Configuration unchanged, no need to save.\n" #~ msgstr "" #~ "La configuración o la versión de GNUnet cambiaron. ¡Debes ejecutar " #~ "'%s'!\n" #, fuzzy #~ msgid "Do you wish to save your new configuration?" #~ msgstr "¿Quieres guardar tu configuración?" #, fuzzy #~ msgid "" #~ "\n" #~ "Your configuration changes were NOT saved.\n" #~ msgstr "Fichero de configuración '%s' creado.\n" #~ msgid "This version of Windows doesn't support services.\n" #~ msgstr "Esta versión de Windows no soporta servicios.\n" #, fuzzy #~ msgid "Error: can't open Service Control Manager: %s\n" #~ msgstr "Error: imposible abrir el Service Control Manager: &s\n" #~ msgid "Error: can't create service: %s\n" #~ msgstr "Error: imposible crear el servicio: %s\n" #~ msgid "Error: can't access service: %s\n" #~ msgstr "Error: imposible acceder al servicio: %s\n" #~ msgid "Error: can't delete service: %s\n" #~ msgstr "Error: imposible borrar el servicio: %s\n" #, fuzzy #~ msgid "Configuration changed. Save?" #~ msgstr "" #~ "La configuración o la versión de GNUnet cambiaron. ¡Debes ejecutar " #~ "'%s'!\n" #, fuzzy #~ msgid "Error saving configuration." #~ msgstr "Imposible guardar la configuración" #, fuzzy #~ msgid "(unknown connection)" #~ msgstr "Conexión de red" #, fuzzy #~ msgid "Do you want to save the new configuration?" #~ msgstr "¿Quieres guardar tu configuración?" #~ msgid "Unable to change startup process:" #~ msgstr "Imposible cambiar el proceso de arranque:" #~ msgid "generate configuration for gnunetd, the GNUnet daemon" #~ msgstr "genera configuración para gnunetd, el demonio de GNUnet" #~ msgid "Tool to setup GNUnet." #~ msgstr "Herramienta de configuración de GNUnet." #, fuzzy #~ msgid "Too many arguments.\n" #~ msgstr "Argumentos en la linea de comandos inválidos.\n" #, fuzzy #~ msgid "Configuration file `%s' must be a filename (but is a directory).\n" #~ msgstr "" #~ "El fichero de configuración '%s' no ha sido encontrado. ¡Ejecute gnunet-" #~ "setup!\n" #, fuzzy #~ msgid "Undefined option.\n" #~ msgstr "Otras configuraciones" #, fuzzy #~ msgid "yes" #~ msgstr "Bytes" #~ msgid "Yes\n" #~ msgstr "Sí\n" #~ msgid "No\n" #~ msgstr "No\n" #~ msgid "Help\n" #~ msgstr "Ayuda\n" #, fuzzy #~ msgid "Abort\n" #~ msgstr "_Acerca de" #, fuzzy #~ msgid "Configuration was unchanged, no need to save.\n" #~ msgstr "" #~ "La configuración o la versión de GNUnet cambiaron. ¡Debes ejecutar " #~ "'%s'!\n" #~ msgid "Can't open Service Control Manager" #~ msgstr "Imposible abrir el Service Control Manager" #~ msgid "Can't create service" #~ msgstr "Imposible crear el servicio" #~ msgid "Error changing the permissions of the GNUnet directory" #~ msgstr "Error cambiando los permisos del directorio de GNUnet" #, fuzzy #~ msgid "Cannot write to the registry" #~ msgstr "Imposible escribir en el registro" #~ msgid "Can't delete the service" #~ msgstr "Imposible borrar el servicio" #~ msgid "This version of Windows does not support multiple users." #~ msgstr "Esta versión de Windows no permite usuarios múltiples" #~ msgid "Error accessing local security policy" #~ msgstr "Error accediendo a la política de seguridad local" #~ msgid "Error granting service right to user" #~ msgstr "Error garantizando el servicio correcto al usuario" #~ msgid "Unknown error while creating a new user" #~ msgstr "Error desconocido mientras se creaba un nuevo usuario" #, fuzzy #~ msgid "" #~ "Configuration does not satisfy constraints of configuration specification " #~ "file `%s'!\n" #~ msgstr "" #~ "La configuración debe especificar un directorio para los datos FS en la " #~ "sección '%s' bajo'%s'.\n" #~ msgid "FATAL" #~ msgstr "FATAL" #~ msgid "NOTHING" #~ msgstr "NADA" #, fuzzy #~ msgid "Syntax error in configuration entry HOST in section NETWORK: `%s'\n" #~ msgstr "" #~ "Error de sintaxis en el fichero de configuración '%s' en la linea %d.\n" #, fuzzy #~ msgid "Error connecting to %s:%u. Is the daemon running?\n" #~ msgstr "Imposible conectar a %u.%u.%u.%u:%u: %s\n" #, fuzzy #~ msgid "Cannot connect to %s:%u: %s\n" #~ msgstr "Imposible conectar a %u.%u.%u.%u:%u: %s\n" #, fuzzy #~ msgid "Reading result from gnunetd failed, reply invalid!\n" #~ msgstr "¡'%s' falló, respuesta no válida!\n" #, fuzzy #~ msgid "No interface specified in section `%s' under `%s'!\n" #~ msgstr "Ninguna interfaz especificada, usando la marcada por defecto\n" #, fuzzy #~ msgid "" #~ "Could not find interface `%s' using `%s', trying to find another " #~ "interface.\n" #~ msgstr "Imposible obtener IP para la interfaz '%s' usando '%s'.\n" #~ msgid "Could not find an IP address for interface `%s'.\n" #~ msgstr "Imposible obtener la dirección IP para la interfaz '%s'.\n" #, fuzzy #~ msgid "" #~ "There is more than one IP address specified for interface `%s'.\n" #~ "GNUnet will use %s.\n" #~ msgstr "" #~ "Hay más de una dirección IP especificada para la interfaz '%s'.\n" #~ "GNUnet usará %u.%u.%u.%u.\n" #~ msgid "Could not resolve `%s' to determine our IP address: %s\n" #~ msgstr "Imposible resolver '%s' para determinar nuestra dirección IP: %s\n" #, fuzzy #~ msgid "Received malformed message (too small) from connection. Closing.\n" #~ msgstr "Recibida respuesta anómala a'%s' del par '%s'.\n" #~ msgid "Can't create semaphore: %i" #~ msgstr "Imposible crear un semáforo: %i" #, fuzzy #~ msgid "Command `%s' failed with error code %u\n" #~ msgstr "'%s' falló con el código de error %s: %s" #~ msgid "Availability test failed for `%s' at %s:%d.\n" #~ msgstr "Test de disponibilidad fallido para '%s' en %s:%d.\n" #, fuzzy #~ msgid "Starting datastore conversion (this may take a while).\n" #~ msgstr "Creando nueva clave local (esto puede llevar un tiempo).\n" #, fuzzy #~ msgid "Failed to load sqstore service. Check your configuration!\n" #~ msgstr "Imposible guardar la configuración" #, fuzzy #~ msgid "" #~ "%s:%d - RPC %s:%p could not be registered: another callback is already " #~ "using this name (%p)\n" #~ msgstr "" #~ "%s::%s - RPC %s:%p no pudo ser registrada: otro evento está actualmente " #~ "usando este nombre (%p)\n" #, fuzzy #~ msgid "%s:%d - async RPC %s:%p could not be unregistered: not found\n" #~ msgstr "" #~ "%s::%s RPC asíncrona %s:%p no pudo ser desregistrada: no encontrada\n" #~ msgid "`%s' registering handlers %d %d %d\n" #~ msgstr "'%s' registrando manejadores %d %d %d\n" #~ msgid "Using %u messages of size %u for %u times.\n" #~ msgstr "Usando %u mensajes de un tamaño de %u durante %u veces.\n" #~ msgid "output in gnuplot format" #~ msgstr "salida en formato de gnuplot" #~ msgid "number of messages to use per iteration" #~ msgstr "número de mensajes a usar por iteración" #~ msgid "message size" #~ msgstr "tamaño del mensaje" #~ msgid "sleep for SPACE ms after each a message block" #~ msgstr "duerme durante SPACE ms después de cada bloque de mensajes" #~ msgid "number of messages in a message block" #~ msgstr "número de mensajes en un bloque de mensajes" #~ msgid "Error establishing connection with gnunetd.\n" #~ msgstr "Se produjo un error estableciendo conexión con gnunetd.\n" #~ msgid "Invalid receiver peer ID specified (`%s' is not valid name).\n" #~ msgstr "" #~ "ID del par receptor especificada no válida ('%s' no es un nombre " #~ "válido).\n" #~ msgid "Time:\n" #~ msgstr "Tiempo:\n" #~ msgid "\tmax %llums\n" #~ msgstr "\tmax %llums\n" #~ msgid "\tmin %llums\n" #~ msgstr "\tmin %llums\n" #~ msgid "\tmean %8.4fms\n" #~ msgstr "\tmean %8.4fms\n" #~ msgid "\tvariance %8.4fms\n" #~ msgstr "\tvariance %8.4fms\n" #~ msgid "Loss:\n" #~ msgstr "Perdido:\n" #~ msgid "\tmax %u\n" #~ msgstr "\tmax %u\n" #~ msgid "\tmin %u\n" #~ msgstr "\tmin %u\n" #~ msgid "\tmean %8.4f\n" #~ msgstr "\tmean %8.4f\n" #~ msgid "\tvariance %8.4f\n" #~ msgstr "\tvariance %8.4f\n" #~ msgid "Output format not known, this should not happen.\n" #~ msgstr "El formato de salida es desconocido, ésto no debería pasar.\n" #~ msgid "" #~ "\n" #~ "Did not receive the message from gnunetd. Is gnunetd running?\n" #~ msgstr "" #~ "\n" #~ "No se recibió el mensaje de gnunetd. ¿Está gnunetd ejecutandose?\n" #, fuzzy #~ msgid "# bytes received in plaintext of type %d" #~ msgstr "# bytes recibidos por TCP" #, fuzzy #~ msgid "# bytes allocated by SQLite" #~ msgstr "# bytes en la base de datos" #~ msgid "" #~ "Failed to load MySQL database module. Check that MySQL is running and " #~ "configured properly!\n" #~ msgstr "" #~ "Falló al cargar el modulo de la base de datos MySQL. ¡Comprueba que " #~ "MySQL esta ejecutandose y esta configurada correctamente!\n" #, fuzzy #~ msgid "use PRIORITY for the priority of the trace request" #~ msgstr "especifica la prioridad del contenido" #, fuzzy #~ msgid "HELLO message from `%s' has an invalid signature. Dropping.\n" #~ msgstr "mensaje de saludo de '%s' inválido (firma inválida). Omitiendo.\n" #, fuzzy #~ msgid "HELLO message has expiration too far in the future. Dropping.\n" #~ msgstr "" #~ "mensaje de saludo recibido inválido (tiempo superior al límite). " #~ "Omitiendo.\n" #, fuzzy #~ msgid "Could not send HELLO+PING, ping buffer full.\n" #~ msgstr "Imposible mandar ahora saludos+PING, buffer del ping lleno.\n" #~ msgid "" #~ "Announcing ourselves pointless: no other peers are known to us so far.\n" #~ msgstr "" #~ "Es inútil anunciarnos: no hay más pares que nos conozcan más allá.\n" #, fuzzy #~ msgid "# Peer advertisements of type NAT received" #~ msgstr "# Anuncios de los pares recibidos" #, fuzzy #~ msgid "# Peer advertisements updating earlier HELLOs" #~ msgstr "# Anuncios de los pares recibidos" #, fuzzy #~ msgid "# Peer advertisements for unsupported transport" #~ msgstr "# Anuncios de los pares recibidos" #, fuzzy #~ msgid "# Peer advertisements not confirmed due to ping busy" #~ msgstr "# Anuncios de los pares recibidos" #, fuzzy #~ msgid "# Peer advertisements not confirmed due to lack of self ad" #~ msgstr "# Anuncios de los pares recibidos" #, fuzzy #~ msgid "# Peer advertisements not confirmed due to send error" #~ msgstr "# Anuncios de los pares recibidos" #~ msgid "`%s' registering handler %d (plaintext and ciphertext)\n" #~ msgstr "'%s' registrando manejador %d (texto plano e hipertexto)\n" #~ msgid "" #~ "ensures that this peer is known by other peers and discovers other peers" #~ msgstr "" #~ "Asegura que este par es conocido por otros pares y descubre otros pares" #~ msgid "`%s' registering handler %d\n" #~ msgstr "'%s' registrando manejador %d\n" #, fuzzy #~ msgid "`%s' registering CS handlers %d and %d\n" #~ msgstr "'%s' registrando manejadores %d y %d\n" #~ msgid "enables P2P-chat (incomplete)" #~ msgstr "Activa el chat P2P (incompleto)" #, fuzzy #~ msgid "Existing key in file `%s' failed format check, creating new key.\n" #~ msgstr "" #~ "Se produjo un fallo al comprobar la clave local existente en el fichero " #~ "'%s', creando nueva clave local.\n" #, fuzzy #~ msgid "Creating new key for this nickname (this may take a while).\n" #~ msgstr "Creando nueva clave local (esto puede llevar un tiempo).\n" #, fuzzy #~ msgid "# max bytes allowed in dstore" #~ msgstr "# bytes en la base de datos" #~ msgid "Transport library `%s' did not provide required function '%s%s'.\n" #~ msgstr "" #~ "La biblioteca de transporte '%s' no provee la función '%s%s' requerida.\n" #, fuzzy #~ msgid "Query (get KEY, put KEY VALUE) DHT table." #~ msgstr "" #~ "Pregunta (coje KEY, pone KEY VALUE, borra KEY VALUE) a una tabla DHT." #, fuzzy #~ msgid "allow TIME ms to process a GET command" #~ msgstr "Reserva TIME ms para procesar cada comando" #, fuzzy #~ msgid "Issuing `%s(%s,%s)' command.\n" #~ msgstr "'%s(%s, %s)' falló.\n" #~ msgid "Command `%s' requires an argument (`%s').\n" #~ msgstr "El comando '%s' requiere un argumento ('%s').\n" #~ msgid "Command `%s' requires two arguments (`%s' and `%s').\n" #~ msgstr "El comando '%s' requiere dos argumentos ('%s' y '%s').\n" #, fuzzy #~ msgid "# dht put requests received" #~ msgstr "# bytes recibidos por TCP" #, fuzzy #~ msgid "`%s' registering p2p handlers: %d %d %d\n" #~ msgstr "'%s' registrando manejadores %d %d %d\n" #~ msgid "`%s' failed. Terminating connection to client.\n" #~ msgstr "'%s' falló. Finalizando conexión con el cleinte.\n" #, fuzzy #~ msgid "`%s' registering client handlers: %d %d\n" #~ msgstr "'%s' registrando un manejador de clientes %d\n" #~ msgid "" #~ "Existing hostkey in file `%s' failed format check, creating new hostkey.\n" #~ msgstr "" #~ "Se produjo un fallo al comprobar la clave local existente en el fichero " #~ "'%s', creando nueva clave local.\n" #~ msgid "Done creating hostkey.\n" #~ msgstr "Correcto al crear la clave local.\n" #, fuzzy #~ msgid "Removed file `%s' containing invalid HELLO data.\n" #~ msgstr "Borrando el fichero '%s' que contiene datos de saludo no válidos.\n" #~ msgid "Signature failed verification: signature invalid.\n" #~ msgstr "Falló la verificación de la firma: firma no válida.\n" #~ msgid "Received malformed `%s' message. Dropping.\n" #~ msgstr "Recibido el mensaje '%s' con un mal formato. Omitiendo.\n" #~ msgid "Received ping for another peer. Dropping.\n" #~ msgstr "Recibido ping de otro par. Omitiendo.\n" #~ msgid "`%s' registering handlers %d %d (plaintext and ciphertext)\n" #~ msgstr "'%s' registrando manejadores %d %d (texto plano e hipertexto)\n" #, fuzzy #~ msgid "Cannot encrypt sessionkey, peer `%s' not known!\n" #~ msgstr "¡Imposible cifrar la clave de sesión, otro par desconocido!\n" #, fuzzy #~ msgid "Could not create any HELLO for myself (have transports `%s')!\n" #~ msgstr "¡Imposible crear la clave local!\n" #, fuzzy #~ msgid "" #~ "Session key received from peer `%s' has invalid format (discarded).\n" #~ msgstr "El mensaje recibido del par es inválido.\n" #, fuzzy #~ msgid "Session key received from peer `%s' is for `%s' and not for me!\n" #~ msgstr "El mensaje recibido del par es inválido.\n" #~ msgid "setkey `%s' from `%s' fails CRC check (have: %u, want %u).\n" #~ msgstr "" #~ "el cambio de clave '%s' de '%s' falló al comprobar el CRC (dio: %u, " #~ "esperado %u).\n" #, fuzzy #~ msgid "" #~ "Error parsing encrypted session key from `%s', given message part size is " #~ "invalid.\n" #~ msgstr "" #~ "Error analizando la clave de sesión cifrada, el mensaje dado del tamaño " #~ "de las partes es inválido.\n" #, fuzzy #~ msgid "Unknown type in embedded message from `%s': %u (size: %u)\n" #~ msgstr "Tipo desconocido en el mensaje embebido: %u (tamaño: %u)\n" #~ msgid "automate creation of a namespace by starting a collection" #~ msgstr "creación automática de un espacio al empezar una colección" #~ msgid "create a new pseudonym under the given NICKNAME" #~ msgstr "crea un nuevo pseudónimo bajo el APODO dado" #~ msgid "delete the pseudonym with the given NICKNAME" #~ msgstr "borra el pseudónimo con el APODO dado" #~ msgid "end automated building of a namespace (ends collection)" #~ msgstr "" #~ "finaliza la construcción automática de un espacio (finaliza la " #~ "recolección)" #~ msgid "" #~ "Create new pseudonyms, delete pseudonyms or list existing pseudonyms." #~ msgstr "" #~ "Crea nuevos pseudónimos, borra pseudónimos o lista los pseudónimos " #~ "existentes." #~ msgid "" #~ "use the given keyword to advertise the namespace (use when creating a new " #~ "pseudonym)" #~ msgstr "" #~ "usa la clave dada para anunciar el espacio (úsalo cuando crees un nuevo " #~ "pseudónimo)" #, fuzzy #~ msgid "specify metadata describing the namespace or collection" #~ msgstr "" #~ "finaliza la construcción automática de un espacio (finaliza la " #~ "recolección)" #~ msgid "" #~ "do not generate an advertisement for this namespace (use when creating a " #~ "new pseudonym)" #~ msgstr "" #~ "no genera un anuncio para este espacio (úsalo cuando crees un nuevo " #~ "pseudónimo)" #~ msgid "do not list the pseudonyms from the pseudonym database" #~ msgstr "no listar los pseudónimos de la base de datos de pseudónimos" #~ msgid "" #~ "specify IDENTIFIER to be the address of the entrypoint to content in the " #~ "namespace (use when creating a new pseudonym)" #~ msgstr "" #~ "especifica el IDENTIFIER para ser la dirección del punto de entrada al " #~ "contenido en el espacio (úsalo cuando crees un nuevo pseudónimo)" #~ msgid "Namespace `%s' (%s) has rating %d.\n" #~ msgstr "El espacio '%s' (%s) ha sido valorado con un %d.\n" #~ msgid "\tRating (after update): %d\n" #~ msgstr "\tValoración (después de la actualización): %d\n" #~ msgid "Failed to stop collection (not active?).\n" #~ msgstr "Falló al parar la recolección (¿no está activa?).\n" #~ msgid "Error deleting pseudonym `%s' (does not exist?).\n" #~ msgstr "Error borrando el pseudónimo '%s' (¿no existe?).\n" #, fuzzy #~ msgid "Started collection.\n" #~ msgstr "Iniciada colección '%s'.\n" #~ msgid "Namespace `%s' created (root: %s).\n" #~ msgstr "El espacio '%s' fue creado (root: %s).\n" #, fuzzy #~ msgid "You must specify a name for the collection (`%s' option).\n" #~ msgstr "Debes especificar un apodo (use la opción '%s').\n" #~ msgid "%d files found in directory.\n" #~ msgstr "%d ficheros encontrados en el directorio.\n" #~ msgid "Perform directory related operations." #~ msgstr "Realiza operaciones respecto al directorio." #~ msgid "" #~ "remove all entries from the directory database and stop tracking URIs" #~ msgstr "" #~ "borra todas las entradas de la base de datos del directorio y detiene el " #~ "seguimiento de URIs" #~ msgid "list entries from the directory database" #~ msgstr "lista las entradas de la base de datos del directorio" #~ msgid "start tracking entries for the directory database" #~ msgstr "comienza a seguir las entradas de la base de datos del directorio" #~ msgid "Listed %d matching entries.\n" #~ msgstr "%d entradas encontradas.\n" #, fuzzy #~ msgid "Upload of `%s' at %llu out of %llu bytes.\n" #~ msgstr "Descargado del fichero '%s' el %16llu de %16llu bytes(%8.3f kbps)\n" #, fuzzy #~ msgid "Upload aborted.\n" #~ msgstr "Descarga abortada" #, fuzzy #~ msgid "Uploading suspended.\n" #~ msgstr "¡Subida rechazada!" #, fuzzy #~ msgid "" #~ "run in debug mode; gnunet-auto-share will not daemonize and error " #~ "messages will be written to stderr instead of a logfile" #~ msgstr "" #~ "se ejecuta en modo de depuración; gnunetd no sera un demonio y los " #~ "mensajes de error serán escritos a través de stderr en vez de en un " #~ "fichero de log" #, fuzzy #~ msgid "" #~ "do not use libextractor to add additional references to directory entries " #~ "and/or the published file" #~ msgstr "" #~ "usa libextractor para añadir referencias directas adicionales a las " #~ "entradas del directorio" #~ msgid "Created entry `%s' in namespace `%s'\n" #~ msgstr "Creada la entrada '%s' en el espacio '%s'\n" #, fuzzy #~ msgid "" #~ "%16llu of %16llu bytes inserted (estimating %6s to completion) - %s\n" #~ msgstr "%16llu de %16llu bytes insertados (%s estimado para completar)\n" #, fuzzy #~ msgid "" #~ "Upload of `%s' complete, %llu bytes took %llu seconds (%8.3f KiB/s).\n" #~ msgstr "" #~ "Subida de '%s' completada, %llu bytes tomaron %llu segundos (%8.3f " #~ "kbps).\n" #, fuzzy #~ msgid "" #~ "\n" #~ "Upload aborted.\n" #~ msgstr "Descarga abortada" #, fuzzy #~ msgid "" #~ "\n" #~ "Error uploading file: %s" #~ msgstr "" #~ "\n" #~ "Error subiendo el fichero %s\n" #~ msgid "" #~ "even if gnunetd is running on the local machine, force the creation of a " #~ "copy instead of making a link to the GNUnet share directory" #~ msgstr "" #~ "aunque gnunetd este corriendo en el ordenador local, fuerza la creación " #~ "de una copia en vez de hacer un enlace al directorio para compartir de " #~ "GNUnet" #~ msgid "Make files available to GNUnet for sharing." #~ msgstr "Permite a GNUnet disponer de los ficheros para compartirlos." #~ msgid "Could not access namespace `%s' (does not exist?).\n" #~ msgstr "Imposible acceder al espacio '%s' (¿no existe?).\n" #~ msgid "Search GNUnet for files." #~ msgstr "Buscar GNUnet en busca de ficheros." #~ msgid "write encountered (decrypted) search results to FILENAME" #~ msgstr "escribe los resultados encontrados (descifrados) a FILENAME" #~ msgid "" #~ "%16llu of %16llu bytes unindexed (estimating %llu seconds to " #~ "completion) " #~ msgstr "" #~ "%16llu de %16llu bytes desindexados (estimados %llu segundos para " #~ "completar) " #, fuzzy #~ msgid "" #~ "\n" #~ "Unindexing of `%s' complete, %llu bytes took %llu seconds (%8.3f KiB/s).\n" #~ msgstr "" #~ "\n" #~ "El desindexado de '%s' se completó, %llu bytes tomaron %llu segundos " #~ "(%8.3f kbps).\n" #, fuzzy #~ msgid "Not enough arguments. You must specify a filename.\n" #~ msgstr "" #~ "Argumentos insuficientes. Debes especificar una URI de un fichero de " #~ "GNUnet\n" #~ msgid "`%s' failed. Is `%s' a file?\n" #~ msgstr "'%s' falló. ¿Es '%s' un fichero?\n" #~ msgid "Download files from GNUnet." #~ msgstr "Descarga los ficheros de GNUnet" #, fuzzy #~ msgid "Download of file `%s' at %16llu out of %16llu bytes (%8.3f KiB/s)\n" #~ msgstr "Descargado del fichero '%s' el %16llu de %16llu bytes(%8.3f kbps)\n" #, fuzzy #~ msgid "Download aborted.\n" #~ msgstr "Descarga abortada" #, fuzzy #~ msgid "Download of file `%s' complete. Speed was %8.3f KiB per second.\n" #~ msgstr "" #~ "Descarga del fichero '%s' completada. La velocidad media fue " #~ "%8.3fkilobytes por segundo.\n" #~ msgid "Not enough arguments. You must specify a GNUnet file URI\n" #~ msgstr "" #~ "Argumentos insuficientes. Debes especificar una URI de un fichero de " #~ "GNUnet\n" #~ msgid "URI `%s' invalid for gnunet-download.\n" #~ msgstr "La URI '%s' no es válida para una descarga-de-gnunet.\n" #, fuzzy #~ msgid "No filename specified, using `%s' instead (for now).\n" #~ msgstr "Ningún nombre especificado para la tabla, usando '%s'.\n" #, fuzzy #~ msgid "Downloading %d files from directory `%s'.\n" #~ msgstr "Descarga los ficheros de GNUnet" #~ msgid "File stored as `%s'.\n" #~ msgstr "Fichero almacenado en '%s'.\n" #~ msgid "Collecting file identifiers disabled.\n" #~ msgstr "Recolección de identificadores de fichero desactivada.\n" #~ msgid "Deleted corrupt URI database in `%s'." #~ msgstr "Borrada base de datos de URIs corrupta en '%s'." #~ msgid "Cannot get size of file `%s'" #~ msgstr "Imposible determinar el tamaño del fichero '%s'" #~ msgid "Cannot hash `%s'.\n" #~ msgstr "Imposible hallar el hash de '%s'.\n" #~ msgid "Initialization for indexing file `%s' failed.\n" #~ msgstr "" #~ "Durante la inicialización de la indexación del fichero '%s' se produjo un " #~ "fallo.\n" #, fuzzy #~ msgid "Cannot open file `%s': `%s'" #~ msgstr "Imposible abrir el fichero de configuración '%s'.\n" #~ msgid "Renaming of file `%s' to `%s' failed: %s\n" #~ msgstr "Al renombrar el fichero '%s' a '%s' se produjo un fallo: %s\n" #~ msgid "Could not rename file `%s' to `%s': file exists\n" #~ msgstr "Imposible renombrar el fichero '%s' a '%s': el fichero ya existe\n" #~ msgid "CHK URI not allowed for search.\n" #~ msgstr "CHK URI no autorizado para buscar.\n" #~ msgid "LOC URI not allowed for search.\n" #~ msgstr "LOC URI no autorizado para buscar.\n" #~ msgid "File `%s' does not contain a pseudonym.\n" #~ msgstr "El fichero '%s' no contiene un pseudónimo.\n" #, fuzzy #~ msgid "Format of file `%s' is invalid, trying to remove.\n" #~ msgstr "El formato del fichero '%s' no es válido.\n" #~ msgid "" #~ "Decrypted content does not match key. This is either a bug or a " #~ "maliciously inserted file. Download aborted.\n" #~ msgstr "" #~ "El contenido descifrado no encuentra una clave. Esto puede ser un bug o " #~ "un fichero introducido maliciosamente. Descarga abortada.\n" #, fuzzy #~ msgid "Application aborted." #~ msgstr "_Opciones" #~ msgid "FSUI state file `%s' had syntax error at offset %u.\n" #~ msgstr "" #~ "Fichero del estado de FSUI '%s' tiene un error de sintáxis en la " #~ "asignación %u.\n" #, fuzzy #~ msgid "" #~ "`%s' registering client handlers %d %d %d %d %d %d %d %d and P2P handlers " #~ "%d %d\n" #~ msgstr "" #~ "'%s' registrando manejadores de clientes %d %d %d %d %d %d %d %d %d\n" #~ msgid "enables (anonymous) file-sharing" #~ msgstr "activa la compartición de ficheros anónima" #~ msgid "" #~ "Because the file `%s' has been unavailable for 3 days it got removed from " #~ "your share. Please unindex files before deleting them as the index now " #~ "contains invalid references!\n" #~ msgstr "" #~ "El fichero '%s' se ha eliminado de tus compartidos porque no ha estado " #~ "disponible durante tres días. Por favor, desindexa los ficheros antes de " #~ "borrarlos porque eso causa que el índice tenga referencias no válidas.\n" #, fuzzy #~ msgid "" #~ "Unindexed ODB block `%s' from offset %llu already missing from " #~ "datastore.\n" #~ msgstr "" #~ "Bloque ODB '%s' desindexado del offset %llu perdido de la base de datos.\n" #~ msgid "# blocks migrated" #~ msgstr "# blocks migrados" #, fuzzy #~ msgid "# blocks injected for migration" #~ msgstr "# blocks migrados" #, fuzzy #~ msgid "# on-demand fetches for migration" #~ msgstr "# blocks migrados" #, fuzzy #~ msgid "Friend list of %s:%d\n" #~ msgstr "Fallo al conectar a gnunetd.\n" #, fuzzy #~ msgid "Bootstrap data obtained from `%s' is invalid.\n" #~ msgstr "Formato del pseudónimo '%s' no es válido.\n" #~ msgid "`%s' registering client handler %d\n" #~ msgstr "'%s' registrando un manejador de clientes %d\n" #~ msgid "allows clients to determine gnunetd's configuration" #~ msgstr "permite a los clientes determinar la configuración de gnunetd" #~ msgid "`%s' registering client handler %d and %d\n" #~ msgstr "'%s' registrando manejador de clientes %d y %d\n" #, fuzzy #~ msgid "% of allowed network load (up)" #~ msgstr "% de red permitida para la subida" #, fuzzy #~ msgid "% of allowed network load (down)" #~ msgstr "% de red permitida para bajada" #, fuzzy #~ msgid "% of allowed cpu load" #~ msgstr "% de CPU permitida para el uso" #, fuzzy #~ msgid "% of allowed io load" #~ msgstr "% de CPU permitida para el uso" #, fuzzy #~ msgid "`%s' registering client handlers %d %d %d and p2p handler %d\n" #~ msgstr "" #~ "'%s' registrando manejadores de clientes %d %d %d %d %d %d %d %d %d\n" #~ msgid "Supported peer-to-peer messages:\n" #~ msgstr "Mensajes P2P soportados:\n" #~ msgid "Supported client-server messages:\n" #~ msgstr "Mensajes cliente-servidor soportados:\n" #~ msgid "prints supported protocol messages" #~ msgstr "imprime los mensajes del protocolo" #, fuzzy #~ msgid "VPN Received unknown IP version %d...\n" #~ msgstr "Recibida petición de tipo desconocido %d en %s: %d\n" #, fuzzy #~ msgid "Cannot open tunnel device: %s" #~ msgstr "Imposible abrir el fichero de configuración '%s'.\n" #, fuzzy #~ msgid "Cannot set interface IPv6 address for gnu%d because %s\n" #~ msgstr "Imposible obtener la dirección IP para la interfaz '%s'.\n" #, fuzzy #~ msgid "Cannot add route IPv6 address for gnu%s because %s\n" #~ msgstr "Imposible obtener la dirección IP para la interfaz '%s'.\n" #, fuzzy #~ msgid "`%s' initialising RFC4913 module %d and %d\n" #~ msgstr "'%s' registrando manejadores %d y %d\n" #, fuzzy #~ msgid "enables IPv6 over GNUnet (incomplete)" #~ msgstr "Activa el chat P2P (incompleto)" #~ msgid "Application module `%s' already initialized!\n" #~ msgstr "¡El módulo de la aplicación '%s' ya esta inicializado!\n" #~ msgid "Could not shutdown `%s': application not loaded\n" #~ msgstr "Imposible apagar '%s': aplicación no cargada\n" #~ msgid "Could not shutdown application `%s': not initialized\n" #~ msgstr "Imposible apagar la aplicación '%s': no inicializada\n" #~ msgid "Could not find '%s%s' method in library `%s'.\n" #~ msgstr "Imposible encontrar el método '%s%s' en la biblioteca '%s'.\n" #~ msgid "Could not properly shutdown application `%s'.\n" #~ msgstr "Imposible apagar la aplicación '%s' adecuadamente.\n" #~ msgid "Could not properly unload service `%s'!\n" #~ msgstr "¡Imposible descargar adecuadamente el servicio '%s'!\n" #~ msgid "run as user LOGIN" #~ msgstr "ejecuta como el usuario LOGIN" #~ msgid "" #~ "run in debug mode; gnunetd will not daemonize and error messages will be " #~ "written to stderr instead of a logfile" #~ msgstr "" #~ "se ejecuta en modo de depuración; gnunetd no sera un demonio y los " #~ "mensajes de error serán escritos a través de stderr en vez de en un " #~ "fichero de log" #~ msgid "Starts the gnunetd daemon." #~ msgstr "Arranca el demonio de gnunetd." #, fuzzy #~ msgid "specify username as which gnunetd should run" #~ msgstr "especifica el host en el que gnunetd esta ejecutandose" #~ msgid "Configuration or GNUnet version changed. You need to run `%s'!\n" #~ msgstr "" #~ "La configuración o la versión de GNUnet cambiaron. ¡Debes ejecutar " #~ "'%s'!\n" #~ msgid "The `%s' request received from client is malformed.\n" #~ msgstr "La petición '%s' recibida del cliente esta mal formada.\n" #, fuzzy #~ msgid "Registering failed, message type %d already in use.\n" #~ msgstr "%s falló, el mensaje del tipo %d ya está en uso.\n" #, fuzzy #~ msgid "Unable to obtain filesystem information for `%s': %u\n" #~ msgstr "Imposible guardar el fichero de configuración '%s': %s.\n" #, fuzzy #~ msgid "`%s' message invalid (signature invalid).\n" #~ msgstr "mensaje de saludo inválido (firma no válida).\n" #~ msgid "Message details: %u: length %d, priority: %d\n" #~ msgstr "Detalles del mensaje: %u: longitud %d, prioridad: %d\n" #~ msgid "Message from `%s' discarded: invalid format.\n" #~ msgstr "Mensaje de '%s' descartado: formato inválido.\n" #~ msgid "Invalid sequence number %u <= %u, dropping message.\n" #~ msgstr "Secuencia de números no válida %u <= %u, omitiendo mensaje.\n" #~ msgid "Message received more than one day old. Dropped.\n" #~ msgstr "Mensajes recibidos de mas de un día de antigüedad. Omitidos.\n" #~ msgid "# bytes noise sent" #~ msgstr "# \"bytes-ruido\" mandados" #, fuzzy #~ msgid "# total bytes per second receive limit" #~ msgstr "# bytes de ruido recibidos" #, fuzzy #~ msgid "# total number of messages in send buffers" #~ msgstr "número de mensajes en un bloque de mensajes" #, fuzzy #~ msgid "# total number of bytes we were allowed to send but did not" #~ msgstr "número de mensajes en un bloque de mensajes" #, fuzzy #~ msgid "# total number of bytes we were allowed to sent" #~ msgstr "número de mensajes en un bloque de mensajes" #~ msgid "`%s': Could not create hello.\n" #~ msgstr "'%s': Imposible crear saludo.\n" #~ msgid "`%s': Could not send.\n" #~ msgstr "'%s': Imposible mandar.\n" #~ msgid "`%s': Could not disconnect.\n" #~ msgstr "'%s': Imposible desconectar.\n" #, fuzzy #~ msgid "" #~ "`%s' transport OK. It took %ums to transmit %llu messages of %llu bytes " #~ "each.\n" #~ msgstr "" #~ "Transporte '%s' OK. Tomó %ums transmitir %d mensajes de %d bytes cada " #~ "uno.\n" #~ msgid " Transport %d is not being tested\n" #~ msgstr " El transporte %d no esta siendo probado\n" #~ msgid "" #~ "\n" #~ "Contacting `%s'." #~ msgstr "" #~ "\n" #~ "Contactando '%s'." #, fuzzy #~ msgid "OK!\n" #~ msgstr "OK" #~ msgid "send messages with SIZE bytes payload" #~ msgstr "manda mensajes con SIZE bytes payload" #~ msgid "Available transport(s): %s\n" #~ msgstr "Transporte(s) disponible(s): %s\n" #, fuzzy #~ msgid "%s failed for url `%s' and post-data `%s' at %s:%d: `%s'\n" #~ msgstr "'%s' falló en %s: %d con error: '%s'.\n" #~ msgid "# bytes sent via HTTP" #~ msgstr "# bytes mandados vía HTTP" #~ msgid "# bytes dropped by HTTP (outgoing)" #~ msgstr "#bytes omitidos vía HTTP (salientes)" #, fuzzy #~ msgid "# HTTP curl receive callbacks" #~ msgstr "# bytes recibidos por TCP" #, fuzzy #~ msgid "# HTTP connect calls" #~ msgstr "# de pares conectados" #, fuzzy #~ msgid "Failed to obtain my (external) %s address!\n" #~ msgstr "¡Falló al obtener mi dirección IP (externa)!\n" #, fuzzy #~ msgid "specify host on which gnunetd is running" #~ msgstr "especifica el host en el que gnunetd esta ejecutandose" #, fuzzy #~ msgid "No help available." #~ msgstr "'%s' no esta disponible." #, fuzzy #~ msgid "Show rarely used options" #~ msgstr "Mostrar todas las opciones" #, fuzzy #~ msgid "Meta-configuration" #~ msgstr "Configuración de GNUnet" #, fuzzy #~ msgid "Full pathname of GNUnet HOME directory" #~ msgstr "Error en el formato del fichero (¿no es un directorio de GNUnet?)\n" #, fuzzy #~ msgid "Full pathname of GNUnet directory for file-sharing data" #~ msgstr "Error en el formato del fichero (¿no es un directorio de GNUnet?)\n" #, fuzzy #~ msgid "Full pathname to the directory with the key-value database" #~ msgstr "Error en el formato del fichero (¿no es un directorio de GNUnet?)\n" #, fuzzy #~ msgid "Full pathname of GNUnet directory for indexed files symbolic links" #~ msgstr "Error en el formato del fichero (¿no es un directorio de GNUnet?)\n" #, fuzzy #~ msgid "Disable automatic establishment of connections" #~ msgstr "Se produjo un error estableciendo conexión con gnunetd.\n" #, fuzzy #~ msgid "Run gnunetd as this group." #~ msgstr "Ejecutar gnunet-update" #, fuzzy #~ msgid "General settings" #~ msgstr "Otras configuraciones" #, fuzzy #~ msgid "Settings for restricting connections to friends" #~ msgstr "'%s' falló. Finalizando conexión con el cleinte.\n" #, fuzzy #~ msgid "Name of the MySQL database GNUnet should use" #~ msgstr "Imposible inicializar SQLite.\n" #, fuzzy #~ msgid "Configuration file that specifies the MySQL username and password" #~ msgstr "" #~ "La configuración o la versión de GNUnet cambiaron. ¡Debes ejecutar " #~ "'%s'!\n" #, fuzzy #~ msgid "Configuration of the MySQL database" #~ msgstr "" #~ "La configuración o la versión de GNUnet cambiaron. ¡Debes ejecutar " #~ "'%s'!\n" #, fuzzy #~ msgid "MB of diskspace GNUnet can use for anonymous file sharing" #~ msgstr "activa la compartición de ficheros anónima" #, fuzzy #~ msgid "Number of entries in the migration buffer" #~ msgstr "número de mensajes en un bloque de mensajes" #, fuzzy #~ msgid "" #~ "MB of diskspace GNUnet can use for caching DHT index data (the data will " #~ "be stored in /tmp)" #~ msgstr "activa la compartición de ficheros anónima" #, fuzzy #~ msgid "Options for anonymous file sharing" #~ msgstr "activa la compartición de ficheros anónima" #, fuzzy #~ msgid "Applications" #~ msgstr "_Opciones" #, fuzzy #~ msgid "Network interface" #~ msgstr "Interfaz de red:" #, fuzzy #~ msgid "Network interface to monitor" #~ msgstr "Interfaz de red:" #, fuzzy #~ msgid "Load management" #~ msgstr "Argumentos en la linea de comandos inválidos.\n" #, fuzzy #~ msgid "This is equivalent to the -H option. The format is IP:PORT." #~ msgstr "Muestra el valor de la opción" #, fuzzy #~ msgid "General options" #~ msgstr "Otras configuraciones" #, fuzzy #~ msgid "Full pathname of GNUnet client HOME directory" #~ msgstr "Error en el formato del fichero (¿no es un directorio de GNUnet?)\n" #, fuzzy #~ msgid "`%s' failed at %s:%d in %s with error: %s\n" #~ msgstr "'%s' falló en %s: %d con el error: %s\n" #, fuzzy #~ msgid "`%s' failed at %s:%d with error `%s' after %llums\n" #~ msgstr "'%s' falló en %s: %d con el error: %s\n" #~ msgid "'%s(%s,%s)' succeeded\n" #~ msgstr "'%s (%s, %s)' logrado satisfactoriamente\n" #~ msgid "'%s(%s,%s)' failed.\n" #~ msgstr "'%s(%s, %s)' falló.\n" #, fuzzy #~ msgid "" #~ "Directory `%s' in directory `%s' does not match naming convention. " #~ "Removed.\n" #~ msgstr "" #~ "El fichero '%s' en el directorio '%s' no sigue la convención de nombres. " #~ "Eliminando.\n" #~ msgid "" #~ "set interval for availability of updates to SECONDS (for namespace " #~ "insertions only)" #~ msgstr "" #~ "cambia el intervalo de disponibilidad de las actualizaciones a SEGUNDOS " #~ "(para inserciones en el espacio solamente)" #~ msgid "" #~ "specifies this as an aperiodic but updated publication (for namespace " #~ "insertions only)" #~ msgstr "" #~ "especifica esto como una aperiódica pero actualizada publicación (para " #~ "inserciones en el espacio únicamente)" #~ msgid "specify creation time for SBlock (see man-page for format)" #~ msgstr "" #~ "especifica el tiempo para la creación de un Superbloque (vea la página " #~ "del manual para el formato)" #~ msgid "" #~ "ID of the previous version of the content (for namespace update only)" #~ msgstr "" #~ "ID de la versión previa del contenido (para actualizaciones del espacio " #~ "únicamente)" #~ msgid "Parsing time failed. Use `%s' format.\n" #~ msgstr "Se produjo un fallo al analizar el tiempo. Use el formato '%s'.\n" #~ msgid "Publication interval for periodic publication changed." #~ msgstr "Intervalo de publicación periódica cambiado." #~ msgid "" #~ "Publishing update for periodically updated content more than a week ahead " #~ "of schedule.\n" #~ msgstr "" #~ "publicaciones actualizadas para contenido actualizado periódicamente más " #~ "de una semana antes de la tarea planificada.\n" #, fuzzy #~ msgid "Received malformed message via TCP. Closing.\n" #~ msgstr "Recibido el mensaje '%s' con un mal formato. Omitiendo.\n" #~ msgid "Cannot create pseudonym `%s', file `%s' exists.\n" #~ msgstr "Imposible crear el pseudónimo '%s', el fichero '%s' ya existe.\n" #~ msgid "GNUnet configuration assistant" #~ msgstr "Asistente de configuración de GNUnet" #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://gnunet.org\n" #~ "and join our community at\n" #~ "\thttps://gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "The GNUnet team" #~ msgstr "" #~ "¡Bienvenido a GNUnet!\n" #~ "\n" #~ "Este asistente le preguntará unos datos básicos para configurar GNUnet.\n" #~ "\n" #~ "Por favor, visite nuestra página en\n" #~ "\thttps://gnunet.org/drupal/\n" #~ "\n" #~ "Diviertase,\n" #~ "\n" #~ "El equipo de GNUnet" #~ msgid "Next" #~ msgstr "Siguiente" #~ msgid "" #~ "Enter information about your network connection here.\n" #~ "\n" #~ "The \"Network interface\" is the device that connects your computer to " #~ "the internet. This is usually a modem, an ISDN card or a network card in " #~ "case you are using DSL.\n" #~ "\n" #~ "If your provider always assigns the same IP-Address to you (a \"static\" " #~ "IP-Address), enter it into the \"IP-Address\" field. If your IP-Address " #~ "changes every now and then (\"dynamic\" IP-Address) but there's a " #~ "hostname that always points to your actual IP-Address (\"Dynamic DNS\"), " #~ "you can also enter it here.\n" #~ "If in doubt, leave the field empty. GNUnet will then try to determine " #~ "your IP-Address.\n" #~ "\n" #~ "If you are connected to the internet through another computer doing SNAT, " #~ "a router or a \"hardware firewall\" and other computers on the internet " #~ "cannot connect to this computer, check the last option on this page. " #~ "Leave it unchecked on direct connections through modems, ISDN cards and " #~ "DNAT (also known as \"port forwarding\")." #~ msgstr "" #~ "Introduce información acerca de tu conexión aquí.\n" #~ "\n" #~ "La \"Interfaz de red\" es el dispositivo que conecta tu ordenador a " #~ "Internet. Normalmente es un módem, una tarjeta de RDSI, un módem ADSL o " #~ "una tarjeta de red en el caso de un router.\n" #~ "\n" #~ "Si tu proveedor siempre te da la misma dirección IP (una dirección IP " #~ "\"estática\") introducelo en el campo \"Dirección IP\". Si tu dirección " #~ "IP cambia (una dirección IP \"dinámica\") pero hay un nombre de dominio " #~ "que siempre apunta a tu dirección IP actual (\"DNS dinámica\") también " #~ "puedes introducirla aquí.\n" #~ "En caso de duda deja el campo vacío. GNUnet intentara determinar tu " #~ "dirección IP automaticamente.\n" #~ "\n" #~ "Si tu estas conectado a Internet a través de otro ordenador haciendo " #~ "SNAT, a un router o a un \"cortafuegos de hardware\" y otros ordenadores " #~ "no pueden conectar con tu ordenador marca la última opción en ésta " #~ "página. Déjala sin marcar en conexiones directas a través de modems, " #~ "tarjetas de RDSI y DNAT (también conocido como \"seguimiento de puertos" #~ "\")." #~ msgid "Computer cannot receive inbound connections (SNAT/Firewall)" #~ msgstr "" #~ "El ordenador no puede recibir conexiones entrantes (SNAT/Cortafuegos)" #~ msgid "IP-Address/Hostname:" #~ msgstr "Dirección IP/Nombre del dominio" #, fuzzy #~ msgid "Network interface:" #~ msgstr "Interfaz de red:" #~ msgid "" #~ "You can limit GNUnet's ressource usage here.\n" #~ "\n" #~ "\"Bandwidth limitation\" is how much data may be sent per second. If you " #~ "have a flatrate you can set it to the maximum speed of your internet " #~ "connection.\n" #~ "\n" #~ "The \"Max. CPU usage\" is the percentage of processor time GNUnet is " #~ "allowed to use." #~ msgstr "" #~ "Puedes limitar el uso de recursos de GNUnet aquí.\n" #~ "\n" #~ "\"Limitación de ancho de banda\" es cuantos datos pueden ser mandados por " #~ "segundo. Si tienes una tarifa plana puedes seleccionar la velocidad " #~ "máxima de tu conexión a Internet.\n" #~ "\n" #~ "El \"Uso máximo de CPU\" es el porcentaje del tiempo de procesado que " #~ "GNUnet puede usar." #~ msgid "Downstream (Bytes/s):" #~ msgstr "Bajada (Bytes/s):" #~ msgid "Upstream (Bytes/s):" #~ msgstr "Subida (Bytes/s):" #~ msgid "Bandwidth limitation" #~ msgstr "Limitación del ancho de banda" #~ msgid "Use denoted bandwidth for GNUnet" #~ msgstr "Usa el ancho de banda marcado para GNUnet" #~ msgid "Share denoted bandwidth with other applications" #~ msgstr "Comparte el ancho de banda marcado con otras aplicaciones" #~ msgid "Bandwidth sharing" #~ msgstr "Ancho de banda compartido" #~ msgid "Max. CPU usage (%):" #~ msgstr "Uso máximo de la CPU (%):" #~ msgid "CPU usage" #~ msgstr "Uso de CPU" #~ msgid "Load limitation" #~ msgstr "Limitación de carga" #~ msgid "" #~ "GNUnet is able to store data from other peers in your datastore. This is " #~ "useful if an adversary has access to your inserted content and you need " #~ "to deny that the content is yours. With \"content migration\" on, the " #~ "content could have \"migrated\" over the internet to your node without " #~ "your knowledge.\n" #~ "It also helps to spread popular content over different peers to enhance " #~ "availability.\n" #~ "\n" #~ "The GNUnet datastore contains all data that GNUnet generates (index data, " #~ "inserted and migrated content). Its maximum size can be specified below.\n" #~ "\n" #~ "If you are an experienced user, you may want to tweak your GNUnet " #~ "installation using the enhanced configurator.\n" #~ "\n" #~ "After changing the configuration and/or updating GNUnet, it is sometimes " #~ "required to run gnunet-update to update internal data structures. " #~ "Depending on the changes made, this may take some time." #~ msgstr "" #~ "GNUnet es capaz de almacenar datos de otros pares en tu base de datos. " #~ "Ésto es útil si un adversario tiene acceso a tu contenido y tu necesitas " #~ "negar que ese contenido sea tuyo. Con la \"migración de contenido\" " #~ "activada, tu contenido puede haber \"migrado\" por Internet hasta tu nodo " #~ "sin tu conocimiento.\n" #~ "Ésto también ayuda a difundir contenidos populares por diferentes pares " #~ "para facilitar su disponibilidad.\n" #~ "\n" #~ "La base de datos de GNUnet contiene todos los datos que GNUnet genera " #~ "(índices, contenido insertado y descargado). Su máximo tamaño puede ser " #~ "especificado debajo.\n" #~ "\n" #~ "Si eres un usuario experimentado, puedes desear exprimir tu instalación " #~ "de GNUnet usando la herramienta de configuración avanzada.\n" #~ "\n" #~ "Después de cambiar la configuración y/o actualizar GNUnet, a veces " #~ "esnecesario ejecutar gnunet-update para actualizar las estructuras de " #~ "datos internas. Dependiendo de los cambios que se hayan hecho, ésto podrá " #~ "tomar algún tiempo." #~ msgid "Store migrated content" #~ msgstr "Almacena contenido migrado" #~ msgid "Maximum datastore size (MB):" #~ msgstr "Máximo tamaño de almacenamiento (MB):" #~ msgid "Start the GNUnet background process on computer startup" #~ msgstr "Arranca el demonio de GNUnet al encender el ordenador" #~ msgid "Open the enhanced configurator" #~ msgstr "Abre el editor de configuración avanzado" #, fuzzy #~ msgid "Run gnunet-update" #~ msgstr "¡gnunet-update falló!" #, fuzzy #~ msgid "Other settings" #~ msgstr "Otras configuraciones" #~ msgid "" #~ "Define the user and the group owning the GNUnet service here.\n" #~ "\n" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "user account and a new group under which the GNUnet service is started at " #~ "system startup.\n" #~ "\n" #~ "However, GNUnet may not be able to access files other than its own. This " #~ "includes files you want to publish in GNUnet. You'll have to grant read " #~ "permissions to the user specified below.\n" #~ "\n" #~ "Leave the fields empty to run GNUnet with system privileges." #~ msgstr "" #~ "Define el usuario y el grupo bajo el que correrán los servicios de GNUnet " #~ "aquí.\n" #~ "\n" #~ "Por razones de seguridad, es una buena idea dejar que la configuración " #~ "cree una nueva cuenta de usuario y un nuevo grupo bajo el cual el " #~ "servicio de GNUnet es arrancado al iniciar el sistema.\n" #~ "\n" #~ "Por consiguiente, GNUnet no tiene la posibilidad de acceder a otros " #~ "ficheros que no sean los que posee. Ésto incluye los ficheros que quieras " #~ "publicar en GNUnet. Tendrás que garantizar que el usuario especificado " #~ "aquí posea permisos de lectura.\n" #~ "\n" #~ "Deja los campos vacíos para arrancar GNUnet con privilegios de sistema." #~ msgid "User account:" #~ msgstr "Cuenta de usuario:" #~ msgid "Group:" #~ msgstr "Grupo:" #, fuzzy #~ msgid "Save configuration" #~ msgstr "Configuración de GNUnet" #, fuzzy #~ msgid "Show copyright information for gnunet-setup." #~ msgstr "Se produjo un error leyendo información de gnunetd.\n" #, fuzzy #~ msgid "About gnunet-setup" #~ msgstr "gnunet-setup" #, fuzzy #~ msgid "(C) 2001-2007 Christian Grothoff (and other contributing authors)" #~ msgstr "" #~ "C) 2001-2006 Christian Grothoff (y otros autores que han contribuido)" #~ msgid "This is the configuration tool for GNUnet." #~ msgstr "Esta es la herramienta de configuración de GNUnet." #~ msgid "Could not unlink temporary file `%s': %s\n" #~ msgstr "Imposible desenlazar temporalmente el fichero '%s': %s\n" #~ msgid "Write(%d, %p, %d) failed: %s\n" #~ msgstr "Escribiendo(%d, %p, %d) se produjo un fallo: %s\n" #~ msgid "AND" #~ msgstr "Y" #, fuzzy #~ msgid "Could not find IPv6 address of host `%s': %s\n" #~ msgstr "Imposible encontrar la IP del host '%s': %s\n" #, fuzzy #~ msgid "Error running search (no reason given)." #~ msgstr "Se produjo un fallo al comenzar la búsqueda. Consulte los logs.\n" #, fuzzy #~ msgid "Download failed (no reason given)" #~ msgstr "La descarga del ERCS falló (vea los logs)." #~ msgid "Now %d of %d chat clients at this node.\n" #~ msgstr "Ahora hay %d de %d clientes de chat en este nodo.\n" #, fuzzy #~ msgid "Invalid data in %s (NCS). Trying to fix (by deletion).\n" #~ msgstr "Datos no válidos en %s. Intentando fijar (por borrado).\n" #~ msgid "HTTP: Could not determine my public IP address.\n" #~ msgstr "HTTP: Imposible determinar mi dirección IP pública.\n" #~ msgid "" #~ "%s::%s - RPC %s:%p could not be unregistered: another callback registered " #~ "under that name: %p\n" #~ msgstr "" #~ "%s::%s - RPC %s:%p no pudo ser desregistrada: otro evento está " #~ "actualmente registrado con este nombre (%p)\n" #~ msgid "%s::%s - RPC %s:%p could not be unregistered: not found\n" #~ msgstr "%s::%s - RPC %s:%p no pudo ser desregistrada: no encontrada\n" #~ msgid "Dropping RPC request %u: message malformed.\n" #~ msgstr "Omitiendo la petición RPC %u: mensaje mal formado.\n" #~ msgid "`%s' called with timeout above 1 hour (bug?)\n" #~ msgstr "'%s' fue llamada con un retraso de una hora(¿bug?)\n" #~ msgid "RPC not unregistered: %s:%p\n" #~ msgstr "No fue desregistrada RPC: %s:%p\n" #~ msgid "RPC async reply invalid.\n" #~ msgstr "RPC respuesta asíncrona no válida.\n" #~ msgid "async RPC reply not received.\n" #~ msgstr "respuesta RPC asíncrona no recibida.\n" #, fuzzy #~ msgid "# bytes received via TCP6" #~ msgstr "# bytes recibidos por TCP" #, fuzzy #~ msgid "# bytes sent via TCP6" #~ msgstr "# bytes enviados por TCP" #, fuzzy #~ msgid "# bytes dropped by TCP6 (outgoing)" #~ msgstr "# bytes omitidos por TCP (salientes)" #~ msgid "UDP6: Could not determine my public IPv6 address.\n" #~ msgstr "UDP6: Imposible determinar mi dirección IPv6 pública.\n" #, fuzzy #~ msgid "# bytes received via UDP6" #~ msgstr "# bytes recibidos vía UDP" #, fuzzy #~ msgid "# bytes sent via UDP6" #~ msgstr "# bytes enviados vía UDP" #, fuzzy #~ msgid "# bytes dropped by UDP6 (outgoing)" #~ msgstr "# bytes omitidos por UDP (salientes)" #, fuzzy #~ msgid "Received malformed message instead of welcome message. Closing.\n" #~ msgstr "Recibido el mensaje '%s' con un mal formato. Omitiendo.\n" #, fuzzy #~ msgid "Received malformed message from tcp-peer connection. Closing.\n" #~ msgstr "Recibido el mensaje '%s' con un mal formato. Omitiendo.\n" #, fuzzy #~ msgid "TCP: Could not determine my public IP address.\n" #~ msgstr "HTTP: Imposible determinar mi dirección IP pública.\n" #~ msgid "Cannot connect to %u.%u.%u.%u:%u: %s\n" #~ msgstr "Imposible conectar a %u.%u.%u.%u:%u: %s\n" #~ msgid "UDP: Could not determine my public IP address.\n" #~ msgstr "UDP: Imposible determinar mi dirección IP pública.\n" #~ msgid "Failed to send message of size %d via UDP to %u.%u.%u.%u:%u: %s\n" #~ msgstr "" #~ "Falló al mandar el mensaje de tamaño %d a través de UDP a %u.%u.%u.%u:%u: " #~ "%s\n" #, fuzzy #~ msgid "Received malformed message from udp-peer connection. Closing.\n" #~ msgstr "Recibido el mensaje '%s' con un mal formato. Omitiendo.\n" #~ msgid "exit after receiving LIMIT results" #~ msgstr "sale después de recibir LIMIT resultados" #, fuzzy #~ msgid "wait DELAY seconds for search results before aborting" #~ msgstr "espera TIMEOUT segundos para buscar resultados después de abortar" #~ msgid "Message received from peer is invalid.\n" #~ msgstr "El mensaje recibido del par es inválido.\n" #~ msgid "myself" #~ msgstr "yo" #~ msgid "" #~ "Cover traffic requested but traffic service not loaded. Rejecting " #~ "request.\n" #~ msgstr "" #~ "Solicitada la cobertura de tráfico pero el servicio de tráfico no ha sido " #~ "cargado. Rechazando la petición.\n" #~ msgid "Cannot satisfy desired level of anonymity, ignoring request.\n" #~ msgstr "" #~ "Imposible satisfacer el nivel deseado de anonimato, ignorando la " #~ "petición.\n" #~ msgid "`%s' registering handlers %d %d\n" #~ msgstr "'%s' registrando manejadores %d %d\n" #, fuzzy #~ msgid "Indexed file disappeared, deleting block for query `%s'\n" #~ msgstr "" #~ "Fichero indexado desaparecido, borrando el bloque para preguntas '%s'\n" #~ msgid "" #~ "Configuration file must specify directory for storage of FS data in " #~ "section `%s' under `%s'.\n" #~ msgstr "" #~ "El fichero de configuración debe especificar un directorio para el " #~ "almacenamiento de los datos de FS en la sección '%s' bajo '%s'.\n" #~ msgid "" #~ "Content `%s' seems to be not available on the network (tried %u times).\n" #~ msgstr "" #~ "El contenido '%s' parece no estar disponible en la red (intentado %u " #~ "veces).\n" #, fuzzy #~ msgid "Start GNUnet-testbed helper." #~ msgstr "Arranca el cliente de chat de GNUnet" #~ msgid "Cannot connect to LOOPBACK port %d: %s\n" #~ msgstr "Imposible conectar al puerto de LOOPBACK %d: %s\n" #~ msgid "No client service started. Trying again in 30 seconds.\n" #~ msgstr "" #~ "No hay ningún servicio de cliente ejecutandose. Se volverá a intentar en " #~ "30 segundos.\n" #, fuzzy #~ msgid "" #~ "Error (%s) binding the TCP listener to port %d. No proxy service " #~ "started.\n" #~ "Trying again in %d seconds...\n" #~ msgstr "" #~ "No hay ningún servicio de cliente ejecutandose. Se volverá a intentar en " #~ "30 segundos.\n" #~ msgid "Rejected unauthorized connection from %u.%u.%u.%u.\n" #~ msgstr "Rechazada conexión no autorizada de %u.%u.%u.%u.\n" #~ msgid "Protocol violation on socket. Expected command.\n" #~ msgstr "Violación del protocolo en el socket. Esperando comando.\n" #~ msgid "Malformed entry in the configuration in section %s under %s: %s\n" #~ msgstr "" #~ "Entrada mal formada en la configuración en la sección %s bajo %s: %s\n" #~ msgid "size of `%s' message is wrong. Ignoring.\n" #~ msgstr "el tamaño del mensaje '%s' es erroneo. Se ignora.\n" #~ msgid "TESTBED could not generate hello message for protocol %u\n" #~ msgstr "" #~ "TESTBED no puede generar el mensaje de saludo para el protocolo %u\n" #~ msgid "received invalid `%s' message (empty module name)\n" #~ msgstr "recibido mensaje '%s' no válido (nombre del módulo vacío)\n" #~ msgid "loading module `%s' failed. Notifying client.\n" #~ msgstr "" #~ "se produjo un fallo al cargar el módulo '%s'. Notificando al cliente.\n" #~ msgid "unloading module failed. Notifying client.\n" #~ msgstr "" #~ "se produjo un fallo al descargar el módulo. Notificando al cliente.\n" #~ msgid "'..' is not allowed in file name (%s).\n" #~ msgstr "'..' no esta permitido en el nombre del fichero(%s).\n" #~ msgid "Empty filename for UPLOAD_FILE message is invalid!\n" #~ msgstr "" #~ "¡Nombre del fichero vacío para el mensaje UPLOAD_FILE es inválido!\n" #~ msgid "Filename for UPLOAD_FILE message is not null-terminated (invalid!)\n" #~ msgstr "" #~ "Nombre del fichero para el mensaje UPLOAD_FILE no esta terminado en null " #~ "(¡inválido!)\n" #~ msgid "Invalid message received at %s:%d." #~ msgstr "Mensaje inválido recibido en %s:%d." #, fuzzy #~ msgid "received invalid testbed message of size %u\n" #~ msgstr "recibido mensaje '%s' no válido: %s.\n" #~ msgid "Could not resolve name of HTTP proxy `%s'.\n" #~ msgstr "Imposible resolver el nombre del proxy HTTP '%s'.\n" #, fuzzy #~ msgid "Could not register testbed, host `%s' unknown\n" #~ msgstr "" #~ "Imposible descargar lista de contactos, servidor '%s' desconocido.\n" #~ msgid "Failed so send HTTP request `%s' to host `%s': %s\n" #~ msgstr "Falló al mandar la petición HTTP '%s' al host '%s': %s\n" #~ msgid "Exit register (error: no http response read).\n" #~ msgstr "Saliendo del registro (error: no se leyó una respuesta de http).\n" #, fuzzy #~ msgid "Description" #~ msgstr "Pregunta" #, fuzzy #~ msgid "Section" #~ msgstr "Pregunta" #, fuzzy #~ msgid "Option" #~ msgstr "_Opciones" #~ msgid "Sending E-mail to `%s' failed.\n" #~ msgstr "Enviando un correo electrónico a '%s' se produjo un fallo.\n" #, fuzzy #~ msgid "Network configuration: NAT" #~ msgstr "Configuración de GNUnet" #~ msgid "" #~ "Is this machine behind NAT?\n" #~ "\n" #~ "If you are connected to the internet through another computer doing SNAT, " #~ "a router or a \"hardware firewall\" and other computers on the internet " #~ "cannot connect to this computer, say \"yes\" here. Answer \"no\" on " #~ "direct connections through modems, ISDN cards and DNAT (also known as " #~ "\"port forwarding\")." #~ msgstr "" #~ "¿Tu máquina esta detrás de un NAT?\n" #~ "\n" #~ "Si tu estás conectado a Internet a través de otro ordenador haciendo " #~ "SNAT, un router o un \"cortafuegos de hardware\" y otros ordenadores no " #~ "pueden conectarse al tuyo a través de Internet directamente, responde \"si" #~ "\" aquí. Responde \"no\" en conexiones directas a través de módems, " #~ "tarjetas de RDSI y DNAT (también conocido como \"seguimiento de puertos" #~ "\")." #, fuzzy #~ msgid "Configuration of the logging system" #~ msgstr "" #~ "La configuración o la versión de GNUnet cambiaron. ¡Debes ejecutar " #~ "'%s'!\n" #, fuzzy #~ msgid "Run gnunetd as this user." #~ msgstr "Ejecutar gnunet-update" #, fuzzy #~ msgid "Run gnunetd during system startup?" #~ msgstr "Ejecutar gnunet-update" #, fuzzy #~ msgid "Path settings" #~ msgstr "Otras configuraciones" #~ msgid "specify nickname" #~ msgstr "especifica el apodo" #~ msgid "You must specify a nickname (use option `%s').\n" #~ msgstr "Debes especificar un apodo (use la opción '%s').\n" #~ msgid "mysql datastore" #~ msgstr "base de datos mysql" #, fuzzy #~ msgid "" #~ "`%s' failed at %s:%d with error: I/%s S/%s SC/%s SS/%s SSC/%s U/%s D/%s " #~ "DG/%s\n" #~ msgstr "'%s' falló en %s: %d con el error: %s\n" #~ msgid "Database failed to delete `%s'.\n" #~ msgstr "Falló al borrar de la base de datos %s.\n" #, fuzzy #~ msgid "Error log:\n" #~ msgstr "Error" #, fuzzy #~ msgid "# bytes received via TCP-OLD" #~ msgstr "# bytes recibidos por TCP" #, fuzzy #~ msgid "# bytes sent via TCP-OLD" #~ msgstr "# bytes enviados por TCP" #, fuzzy #~ msgid "# bytes dropped by TCP-OLD (outgoing)" #~ msgstr "# bytes omitidos por TCP (salientes)" #~ msgid "hello advertisement for protocol %d received.\n" #~ msgstr "Inicio de comunicación del protocolo %d recibido.\n" #~ msgid "`%s' failed (%d, %u). Will not send PING.\n" #~ msgstr "'%s' falló (%d, %u). No se mandará el PING.\n" #~ msgid "Removing hello from peer `%s' (expired %ds ago).\n" #~ msgstr "Eliminando saludo del par '%s' (expiró hace %ds).\n" #~ msgid "Waiting for gnunetd to start (%u iterations left)...\n" #~ msgstr "Esperando a gnunetd para empezar (%u ciclos restantes)...\n" #, fuzzy #~ msgid "Deleting expired content. This may take a while.\n" #~ msgstr "Creando nueva clave local (esto puede llevar un tiempo).\n" #~ msgid "User `%s' not known, cannot change UID to it.\n" #~ msgstr "Usuario '%s' desconocido, imposible cambiar la UID a él.\n" #~ msgid "" #~ "Expected welcome on http connection, got garbage. Closing connection.\n" #~ msgstr "" #~ "Esperada bienvenida en la conexión http, encontrada basura. Cerrando la " #~ "conexión.\n" #~ msgid "%s: Rejected connection from blacklisted address %u.%u.%u.%u.\n" #~ msgstr "" #~ "%s: Conexión rechazada de una dirección de la \"lista negra\" %u.%u.%u." #~ "%u.\n" #~ msgid "Unexpected reply to `%s' operation.\n" #~ msgstr "Respuesta inesperada a la operación '%s'.\n" #~ msgid "join table called NAME" #~ msgstr "únete a la tabla llamada NAME" #~ msgid "Malformed optional field `%s' received from peer `%s'.\n" #~ msgstr "Campo opcional anómalo '%s' recibido del par '%s'.\n" #~ msgid "Malformed response to `%s' on master table.\n" #~ msgstr "Respuesta anómala a '%s' en la tabla maestra.\n" #~ msgid "Invalid response to `%s' from `%s'\n" #~ msgstr "Respuesta inválida a '%s' de '%s'\n" #~ msgid "RPC for `%s' received for table that we do not participate in!\n" #~ msgstr "¡RPC para '%s' recibida de la tabla en la cual no participamos!\n" #~ msgid "`%s' failed. Terminating connection to client.\n" #~ msgstr "'%s' falló. Finalizando conexión con el cliente.\n" #~ msgid "" #~ "Share denoted bandwidth with other applications?\n" #~ "\n" #~ "Say \"yes\" here, if you don't want other network traffic to interfere " #~ "with GNUnet's operation, but still wish to constrain GNUnet's bandwidth " #~ "usage to values entered in the previous steps, or if you can't reliably " #~ "measure the maximum capabilities of your connection. \"No\" can be very " #~ "useful if other applications are causing a lot of traffic on your LAN. " #~ "In this case, you do not want to limit the traffic that GNUnet can " #~ "inflict on your internet connection whenever your high-speed LAN gets " #~ "used (e.g. by NFS)." #~ msgstr "" #~ "¿Compartir el ancho de banda marcado con otras aplicaciones?\n" #~ "\n" #~ "Di \"sí\" aquí si no quieres que el resto del tráfico de la red no " #~ "interfiera con las operaciones de GNUnet, pero aun quieres mantener el " #~ "ancho de banda usado por GNUnet introducido en los pasos previos, o no " #~ "puedes asegurar las máximas capacidades de tu conexión. \"No\" puede ser " #~ "muy útil si otras aplicaciones crean mucho tráfico en tu LAN. En ese " #~ "caso no quieres limitar el tráfico que GNUnet puede crear en tu conexión " #~ "a Internet cuando una LAN de alta velocidad es usada (por ejemplo bajo " #~ "NFS)." #~ msgid "How much CPU (in %) may be used?" #~ msgstr "¿Cuánta CPU (en %) podrá ser usada?" #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "This is the percentage of processor time GNUnet is allowed to use." #~ msgstr "" #~ "Tu puedes limitar el uso de recursos de GNUnet aquí.\n" #~ "\n" #~ "Este es el porcentaje del tiempo del procesador que GNUnet puede usar." #~ msgid "" #~ "Store migrated content?\n" #~ "\n" #~ "GNUnet is able to store data from other peers in your datastore. This is " #~ "useful if an adversary has access to your inserted content and you need " #~ "to deny that the content is yours. With \"content migration\" on, the " #~ "content could have \"migrated\" over the internet to your node without " #~ "your knowledge.\n" #~ "It also helps to spread popular content over different peers to enhance " #~ "availability." #~ msgstr "" #~ "¿Almacena el contenido migrado?\n" #~ "\n" #~ "GNUnet puede almacenar datos de otros pares en tu ordenador. Esto es muy " #~ "útil si un adversario accede a tu contenido insertado y necesitas negar " #~ "que dicho contenido sea tuyo. Con la \"migración de contenidos\" " #~ "activada, el contenido puede haber \"migrado\" a través de internet a tu " #~ "nodo sin tu conocimiento.\n" #~ "Ésto también ayuda a repartir contenido popular a través de diferentes " #~ "pares para aumentar la disponibilidad." #~ msgid "" #~ "If you are an experienced user, you may want to tweak your GNUnet " #~ "installation using the enhanced configurator.\n" #~ "\n" #~ "Do you want to start it after saving your configuration?" #~ msgstr "" #~ "Si eres un usuario experimentado, puedes desear exprimir tu instalación " #~ "de GNUnet usando la herramienta de configuración avanzada.\n" #~ "\n" #~ "¿Quieres arrancarla después de guardar tu configuración?" #~ msgid "" #~ "Unable to save configuration file %s: %s.\n" #~ "\n" #~ "Try again?" #~ msgstr "" #~ "Imposible guardar el fichero de configuración %s: %s.\n" #~ "\n" #~ "¿Intentar de nuevo?" #~ msgid "Failed to send `%s'. Closing connection.\n" #~ msgstr "Fallo al mandar '%s'. Cerrando la conexión.\n" #~ msgid "Received invalid `%s' request (size %d)\n" #~ msgstr "Recibida petición '%s' no válida (tamaño %d)\n" #~ msgid "Received invalid `%s' request (wrong table)\n" #~ msgstr "Recibida petición '%s' no válida (tabla errónea)\n" #~ msgid "This client already participates in the given DHT!\n" #~ msgstr "Este cliente ya participa en el DHT dado\n" #~ msgid "Cannot leave DHT: table not known!\n" #~ msgstr "Imposible dejar DHT: ¡tabla no conocida!\n" #~ msgid "gnunetd signaled error in response to `%s' message\n" #~ msgstr "gnunetd lanzó una señal de error en respuesta al mensaje '%s'\n" #~ msgid "Failed to send `%s' message to gnunetd\n" #~ msgstr "Falló al mandar el mensaje '%s' a gnunetd\n" #~ msgid "Join a DHT." #~ msgstr "Únete a DHT" #~ msgid "allow SIZE bytes of memory for the local table" #~ msgstr "Reserva SIZE bytes de memoria para la tabla local" #~ msgid "Call to `%s' with value '%.*s' (%d bytes).\n" #~ msgstr "Llama a '%s' con el valor '%.*s' (%d bytes).\n" #~ msgid "Error joining DHT.\n" #~ msgstr "Error uniéndose a DHT.\n" #~ msgid "Joined DHT. Press CTRL-C to leave.\n" #~ msgstr "Unido a DHT. Pulsa CTRL-C para abandonarlo.\n" #~ msgid "sendAck failed. Terminating connection to client.\n" #~ msgstr "sendAck falló. Finalizando conexión con el cliente.\n" #, fuzzy #~ msgid "Upload failed (consult logs)." #~ msgstr "La descarga del ERCS falló (vea los logs)." #~ msgid "Could not resolve name of SMTP server `%s': %s" #~ msgstr "Imposible resolver el nombre del servidor de SMTP '%s': %s" #~ msgid "query table called NAME" #~ msgstr "pregunta a la tabla llamada NAME" #~ msgid "No commands specified.\n" #~ msgstr "Ningún comando fue especificado.\n" #~ msgid "Superflous arguments (ignored).\n" #~ msgstr "Argumentos superfluos (ignorados).\n" #~ msgid "Query `%s' had no results.\n" #~ msgstr "La pregunta '%s' no tuvo resultados.\n" #~ msgid "FSUI persistence: error restoring download\n" #~ msgstr "FSUI persistente: error restableciendo la descarga\n" #~ msgid "ECRS download suspending." #~ msgstr "La descarga del ERCS fue suspendida." #~ msgid "Upload failed." #~ msgstr "Subida fallida" #~ msgid "Cannot upload directory without using recursion." #~ msgstr "Imposible compartir un directorio sin hacerlo recursivamente." #, fuzzy #~ msgid "expected `%s' to be a directory!\n" #~ msgstr "¡'%s' se esperaba que '%s' fuera un directorio!\n" #~ msgid "Sorry, no help is available for this option.\n" #~ msgstr "Lo siento, no hay ayuda disponible para esta opción.\n" #~ msgid "%s: Rejected connection from blacklisted address %s.\n" #~ msgstr "%s: Conexión rechazada de una dirección de la \"lista negra\" %s.\n" #~ msgid "Received invalid UDP message from %u.%u.%u.%u:%u, dropping.\n" #~ msgstr "Recibido mensaje UDP no válido del %u.%u.%u.%u:%u, omitiendo.\n" #~ msgid "" #~ "Configuration file must specify directory for storing FS data in section `" #~ "%s' under `%s'.\n" #~ msgstr "" #~ "El fichero de configuración debe especificar el directorio para almacenar " #~ "los datos FS en la sección '%s' bajo '%s'.\n" #~ msgid "" #~ "Configuration file must specify a directory for GNUnet to store per-peer " #~ "data under %s%s\n" #~ msgstr "" #~ "El fichero de configuración debe especificar un directorio para que " #~ "GNUnet almacene la información por-par bajo%s%s\n" #~ msgid "%s `%s' returned no known hosts!\n" #~ msgstr "¡%s '%s' devolvió hosts desconocidos!\n" #~ msgid "" #~ "specify that the contents of the namespace are of the given MIMETYPE (use " #~ "when creating a new pseudonym)" #~ msgstr "" #~ "especifica que los contenidos del espacio son del MIMETYPE dado (úsalo " #~ "cuando crees un nuevo pseudónimo)" #~ msgid "" #~ "specify NAME to be the realname of the user controlling the namespace " #~ "(use when creating a new pseudonym)" #~ msgstr "" #~ "especifica el NAME para ser el nombre real del usuario que controla el " #~ "espacio (úsalo cuando crees un nuevo pseudónimo)" #~ msgid "" #~ "use DESCRIPTION to describe the content of the namespace (use when " #~ "creating a new pseudonym)" #~ msgstr "" #~ "usa la DESCRIPTION para describir el contenido del espacio (úsalo cuando " #~ "crees un nuevo pseudónimo)" #~ msgid "" #~ "specify the given URI as an address that contains more information about " #~ "the namespace (use when creating a new pseudonym)" #~ msgstr "" #~ "especifica la URI dada como dirección que contiene mas información del " #~ "espacio (úsalo cuando crees un nuevo pseudónimo)" #~ msgid "%8u of %8u bytes deleted." #~ msgstr "%8u de %8u bytes borrados." #~ msgid "specify the file to delete from GNUnet (obligatory, file must exist)" #~ msgstr "" #~ "especifica el fichero a borrar de GNUnet (el fichero debe existir " #~ "obligatoriamente)" #~ msgid "" #~ "Remove file from GNUnet. The specified file is not removed\n" #~ "from the filesystem but just from the local GNUnet datastore." #~ msgstr "" #~ "Borra el fichero de GNUnet. El fichero especificado no es borrado\n" #~ "del sistema de ficheros, solamente de la base de datos local de GNUnet." #~ msgid "You must specify a filename (option -f)\n" #~ msgstr "Debes especificar un fichero (opción -f)\n" #~ msgid "" #~ "Error deleting file %s.\n" #~ "Probably a few blocks were already missing from the database.\n" #~ msgstr "" #~ "Error borrando el fichero %s.\n" #~ "Probablemente algunos bloques se hayan perdido de la base de datos.\n" #~ msgid "gnunet-directory [OPTIONS] [FILENAMES]" #~ msgstr "directorio-de-gnunet [OPCIONES] [FICHEROS]" #~ msgid "process directories recursively" #~ msgstr "procesa los directorios recursivamente" #~ msgid "Only one file or directory can be specified at a time.\n" #~ msgstr "Solo un fichero o un directorio puede ser especificado cada vez.\n" #~ msgid "You must specify a file or directory to upload.\n" #~ msgstr "Debes especificar un fichero o directorio para subir.\n" #~ msgid "Not enough arguments. You must specify a keyword or identifier.\n" #~ msgstr "" #~ "No hay suficientes argumentos. Debes especificar una clave o un " #~ "identificador.\n" #~ msgid "LEVEL" #~ msgstr "NIVEL" #~ msgid "FILENAME" #~ msgstr "FICHERO" #~ msgid "" #~ "Configuration file must specify a directory for GNUnet to store per-peer " #~ "data under %s%s.\n" #~ msgstr "" #~ "El fichero de configuración debe especificar un directorio para que " #~ "GNUnet almacene la información por-par bajo %s%s.\n" #~ msgid "Template for gnunet-clients." #~ msgstr "Plantilla para clientes-de-gnunet." #~ msgid "Invalid port \"%s\" in hostlist specification, trying port %d.\n" #~ msgstr "" #~ "Puerto inválido \"%s\" en la especificación de la lista local, probando " #~ "el puerto %d.\n" #~ msgid "Parsing HTTP response for URL `%s' failed.\n" #~ msgstr "Analizando HTTP de la URL '%s' se produjo un fallo.\n" #~ msgid "Could not resolve name of HTTP proxy `%s'. Trying without a proxy.\n" #~ msgstr "" #~ "Imposible resolver el nombre del proxy HTTP '%s'. Intentándolo sin un " #~ "proxy.\n" #~ msgid "Option `%s' makes no sense without option `%s'." #~ msgstr "La opción '%s' no tiene ningún sentido sin la opción '%s'." #~ msgid "Updated data for %d applications.\n" #~ msgstr "Actualizados los datos para %d aplicaciones.\n" #~ msgid "Argument %d: `%s'\n" #~ msgstr "Argumento %d: '%s'\n" #~ msgid "FATAL: Identity plugin not found!\n" #~ msgstr "FATAL: ¡Plugin de identidad no encontrado!\n" #~ msgid "Available MODEs:\n" #~ msgstr "MODOs disponibles:\n" #~ msgid " config\t\ttext-based configuration\n" #~ msgstr " configuración\t\tconfiguración basada en texto\n" #~ msgid " menuconfig\ttext-based menu\n" #~ msgstr " menuconfig\tmenú basado en texto\n" #~ msgid " wizard-curses\tBasic text-based graphical configuration\n" #~ msgstr "" #~ " wizard-curses\t Configuración básica en modo gráfico pero basado en " #~ "texto\n" #~ msgid "" #~ " wizard-gtk\tBasic GTK configuration\n" #~ "\n" #~ msgstr "" #~ " wizard-gtk\tConfiguración GTK básica\n" #~ "\n" #~ msgid "gnunet-setup must have write-access to the configuration file `%s'\n" #~ msgstr "" #~ "gnunet-setup debe tener acceso de escritura al fichero de configuración " #~ "'%s'\n" #, fuzzy #~ msgid "" #~ "Can only run wizard to configure gnunetd.\n" #~ "Did you forget the `%s' option?\n" #~ msgstr "" #~ "Solo se puede arrancar wizard para configurar gnunetd.\n" #~ "¿Te olvidaste de la opción %s'?\n" #~ msgid "Gtk GNUnet Configurator" #~ msgstr "Configurador Gtk de GNUnet" #~ msgid "_File" #~ msgstr "_Fichero" #~ msgid "_Load" #~ msgstr "_Cargar" #~ msgid "Save the config in .config" #~ msgstr "Guardar la configuración en .config" #~ msgid "_Save" #~ msgstr "_Guardar" #~ msgid "_Quit" #~ msgstr "_Salir" #~ msgid "Show _name" #~ msgstr "Mostrar el _nombre" #~ msgid "Show range (Y/M/N)" #~ msgstr "Muestra el rango (Y/M/N)" #~ msgid "Show _range" #~ msgstr "Muestra el _rango" #~ msgid "Show _data" #~ msgstr "Mostrar los _datos" #~ msgid "Show all _options" #~ msgstr "Mostrar todas las _opciones" #~ msgid "_Help" #~ msgstr "_Ayuda" #~ msgid "_Introduction" #~ msgstr "_Introducción" #~ msgid "Goes up of one level (single view)" #~ msgstr "Sube un nivel (vista única)" #~ msgid "Load" #~ msgstr "Cargar" #~ msgid "Save a config file" #~ msgstr "Guardar un fichero de configuración" #~ msgid "Save" #~ msgstr "Guardar" #~ msgid "Single view" #~ msgstr "Vista única" #~ msgid "Single" #~ msgstr "Única" #~ msgid "Split view" #~ msgstr "Vista doble" #~ msgid "Split" #~ msgstr "Doble" #~ msgid "Full view" #~ msgstr "Vista completa" #~ msgid "Full" #~ msgstr "Completa" #~ msgid "Collapse the whole tree in the right frame" #~ msgstr "Contraer el árbol completo en el lateral izquierdo" #~ msgid "Collapse" #~ msgstr "Contraer" #~ msgid "Expand the whole tree in the right frame" #~ msgstr "Expandir el árbol entero en el lateral izquierdo" #~ msgid "Expand" #~ msgstr "Expandir" #~ msgid "" #~ "This is GNUnet's configuration interface.\n" #~ "\n" #~ "GNUnet's options are separated into categories. You can browse them in " #~ "the left tree. If you click on one of the categories, its options are " #~ "shown above. \n" #~ "\n" #~ "To change the value of an option, simply click on its value and enter a " #~ "new value. To get additional information about a specific option, click " #~ "on its description." #~ msgstr "" #~ "Ésta es la interfaz de configuración de GNUnet.\n" #~ "\n" #~ "Las opciones de GNUnet están separadas en categorías. Tu puedes " #~ "explorarlas en el árbol de la izquierda. Si pulsas en una de las " #~ "categorías las opciones son mostradas encima.\n" #~ "\n" #~ "Para cambiar el valor de una opción, simplemente pulsa en su valor e " #~ "introduce uno nuevo. Para obtener información adicional acerca de una " #~ "opción específica, pulsa en su descripción." #~ msgid "Introduction" #~ msgstr "Introducción" #, fuzzy #~ msgid "" #~ "Welcome to GNUnet Setup.\n" #~ "\n" #~ "For each option, a blank box indicates the feature is disabled, and " #~ "checked one indicates it is enabled.\n" #~ "If you do not see an option that you believe should be present, try " #~ "turning on Show All Options under the Options menu.\n" #~ "\n" #~ "Although there is no cross reference yet to help you figure out what " #~ "other options must be enabled to support the option you are interested " #~ "in, you can still view the help of a grayed-out option.\n" #~ "\n" #~ "Toggling Show Debug Info under the Options menu will show the " #~ "dependencies, which you can then match by examining other options." #~ msgstr "" #~ "Bienvenido a la configuración de GNUnet.\n" #~ "\n" #~ "Para cada opción una caja en blanco indica que la opción está desactivada " #~ "y una marcada indica que está activada.\n" #~ "Si no ves una opción que crees que debería estar presente, prueba " #~ "activando la opción \"Mostrar todas las opciones\" en el menú de " #~ "\"Opciones\".\n" #~ "\n" #~ "Although·there·is·no·cross·reference·yet·to·help·you·figure·out·what·other·options·must·be·enabled·to·support·the·option·you·are·interested·in," #~ "·you·can·still·view·the·help·of·a·grayed-out·option.\n" #~ "\n" #~ "Toggling·Show·Debug·Info·under·the·Options·menu·will·show·the·dependencies," #~ "·which·you·can·then·match·by·examining·other·options." #~ msgid "" #~ "Configuration file not found. Please run GNUnet Setup (Client " #~ "Configuration) first." #~ msgstr "" #~ "Fichero de configuración no encontrado. Por favor, ejecuta GNUnet Setup " #~ "(Configuración del cliente) primero." #~ msgid "Configuration file `%s' not found. Run `gnunet-setup -d'!\n" #~ msgstr "" #~ "El·fichero·de·configuración·'%s'·no·ha·sido·encontrado.··¡Ejecute·'gnunet-" #~ "setup -d'!\n" #~ msgid "Cron stopped\n" #~ msgstr "Cron detenido\n" #~ msgid "Caught signal %d.\n" #~ msgstr "Cogida señal %d.\n" #~ msgid "Invalid network notation (additional characters: `%s')." #~ msgstr "Notación de red no válida (caracteres adicionales: '%s')." #~ msgid "FAILURE" #~ msgstr "FALLO" #~ msgid "MESSAGE" #~ msgstr "MENSAJE" #~ msgid "CRON" #~ msgstr "CRON" #~ msgid "EVERYTHING" #~ msgstr "TODO" #~ msgid "Invalid LOGLEVEL `%s' specified.\n" #~ msgstr "LOGLEVEL inválido '%s' especificado.\n" #~ msgid "" #~ "Cannot determine port of gnunetd server. Define in configuration file in " #~ "section `%s' under `%s'.\n" #~ msgstr "" #~ "Imposible determinar el puerto del servidor de gnunetd. Defínelo en el " #~ "fichero de configuración en la sección '%s' bajo '%s'.\n" #~ msgid "" #~ "Usage: %s\n" #~ "%s\n" #~ "\n" #~ msgstr "" #~ "Uso: %s\n" #~ "%s\n" #~ "\n" #~ msgid "g" #~ msgstr "g" #~ msgid "t" #~ msgstr "t" #~ msgid "`%s' failed, other side closed connection.\n" #~ msgstr "'%s' falló, conexión cerrada en el otro lado.\n" #~ msgid "Attempted path to `%s' was `%s'.\n" #~ msgstr "La ruta esperada a '%s' fue '%s'.\n" gnunet-0.10.1/po/quot.sed0000644000175000017500000000023111374167231012116 00000000000000s/"\([^"]*\)"/“\1â€/g s/`\([^`']*\)'/‘\1’/g s/ '\([^`']*\)' / ‘\1’ /g s/ '\([^`']*\)'$/ ‘\1’/g s/^'\([^`']*\)' /‘\1’ /g s/“â€/""/g gnunet-0.10.1/po/vi.po0000644000175000017500000151577512320736474011443 00000000000000# Vietnamese translation for GNUnet. # Copyright © 2008 Christian Grothoff (msgids). # This file is distributed under the same license as the gnunet package. # Phan Vinh Thinh , 2005. # Clytie Siddall , 2008. # msgid "" msgstr "" "Project-Id-Version: gnunet 0.8.0a\n" "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n" "POT-Creation-Date: 2014-04-08 11:11+0200\n" "PO-Revision-Date: 2008-09-10 22:05+0930\n" "Last-Translator: Clytie Siddall \n" "Language-Team: Vietnamese \n" "Language: vi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: LocFactoryEditor 1.7b3\n" #: src/arm/arm_api.c:337 msgid "Client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/arm_monitor_api.c:321 msgid "" "Monitoring client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/gnunet-arm.c:164 #, fuzzy, c-format msgid "Failed to remove configuration file %s\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/arm/gnunet-arm.c:170 #, fuzzy, c-format msgid "Failed to remove servicehome directory %s\n" msgstr "Lá»—i truy cập đến thư mục nhà GNUnet « %s »\n" #: src/arm/gnunet-arm.c:216 src/testbed/gnunet-service-testbed_peers.c:1013 msgid "Message was sent successfully" msgstr "" #: src/arm/gnunet-arm.c:218 #, fuzzy msgid "Misconfiguration (can not connect to the ARM service)" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/arm/gnunet-arm.c:220 src/testbed/gnunet-service-testbed_peers.c:1017 #, fuzzy msgid "We disconnected from ARM before we could send a request" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/arm/gnunet-arm.c:222 src/testbed/gnunet-service-testbed_peers.c:1019 msgid "ARM API is busy" msgstr "" #: src/arm/gnunet-arm.c:224 msgid "Request does not fit into a message" msgstr "" #: src/arm/gnunet-arm.c:226 src/testbed/gnunet-service-testbed_peers.c:1023 #, fuzzy msgid "Request timed out" msgstr "# các khoá phiên chạy được chấp nhận" #: src/arm/gnunet-arm.c:228 src/testbed/gnunet-service-testbed_peers.c:1025 #, fuzzy msgid "Unknown request status" msgstr "Không rõ ngưá»i dùng « %s »\n" #: src/arm/gnunet-arm.c:244 src/testbed/gnunet-service-testbed_peers.c:1041 #, fuzzy, c-format msgid "%s is stopped" msgstr "# các byte trong kho dữ liệu" #: src/arm/gnunet-arm.c:246 src/testbed/gnunet-service-testbed_peers.c:1043 #, c-format msgid "%s is starting" msgstr "" #: src/arm/gnunet-arm.c:248 src/testbed/gnunet-service-testbed_peers.c:1045 #, c-format msgid "%s is stopping" msgstr "" #: src/arm/gnunet-arm.c:250 src/testbed/gnunet-service-testbed_peers.c:1047 #, fuzzy, c-format msgid "%s is starting already" msgstr "« %s » Ä‘ang đăng ký trình Ä‘iá»u khiển %d\n" #: src/arm/gnunet-arm.c:252 src/testbed/gnunet-service-testbed_peers.c:1049 #, c-format msgid "%s is stopping already" msgstr "" #: src/arm/gnunet-arm.c:254 src/testbed/gnunet-service-testbed_peers.c:1051 #, c-format msgid "%s is started already" msgstr "" #: src/arm/gnunet-arm.c:256 src/testbed/gnunet-service-testbed_peers.c:1053 #, c-format msgid "%s is stopped already" msgstr "" #: src/arm/gnunet-arm.c:258 src/testbed/gnunet-service-testbed_peers.c:1055 #, fuzzy, c-format msgid "%s service is not known to ARM" msgstr "Không gian tên « %s » có đánh giá %d.\n" #: src/arm/gnunet-arm.c:260 src/testbed/gnunet-service-testbed_peers.c:1057 #, fuzzy, c-format msgid "%s service failed to start" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/arm/gnunet-arm.c:262 #, fuzzy, c-format msgid "%s service cannot be started because ARM is shutting down" msgstr "« %s » Ä‘ang tắt.\n" #: src/arm/gnunet-arm.c:264 src/testbed/gnunet-service-testbed_peers.c:1061 #, c-format msgid "%.s Unknown result code." msgstr "" #: src/arm/gnunet-arm.c:297 msgid "Fatal error initializing ARM API.\n" msgstr "" #: src/arm/gnunet-arm.c:326 src/arm/gnunet-arm.c:335 #, fuzzy, c-format msgid "Failed to start the ARM service: %s\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/arm/gnunet-arm.c:369 #, fuzzy, c-format msgid "Failed to send a stop request to the ARM service: %s\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/arm/gnunet-arm.c:379 #, fuzzy, c-format msgid "Failed to stop the ARM service: %s\n" msgstr "Lá»—i vào phòng « %s »\n" #: src/arm/gnunet-arm.c:421 #, fuzzy, c-format msgid "Failed to send a request to start the `%s' service: %%s\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/arm/gnunet-arm.c:431 #, fuzzy, c-format msgid "Failed to start the `%s' service: %s\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/arm/gnunet-arm.c:468 #, fuzzy, c-format msgid "Failed to send a request to kill the `%s' service: %%s\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/arm/gnunet-arm.c:479 #, fuzzy, c-format msgid "Failed to kill the `%s' service: %s\n" msgstr "Lá»—i chạy %s: %s %d\n" #: src/arm/gnunet-arm.c:517 #, fuzzy, c-format msgid "Failed to request a list of services: %s\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/arm/gnunet-arm.c:525 #, fuzzy msgid "Error communicating with ARM. ARM not running?\n" msgstr "Cổng để liên lạc vá»›i giao diện ngưá»i dùng GNUnet" #: src/arm/gnunet-arm.c:530 #, fuzzy msgid "Running services:\n" msgstr "Äang nạp và khởi động dùng « %s ».\n" #: src/arm/gnunet-arm.c:612 #, c-format msgid "Now only monitoring, press CTRL-C to stop.\n" msgstr "" #: src/arm/gnunet-arm.c:643 #, c-format msgid "Stopped %s.\n" msgstr "" #: src/arm/gnunet-arm.c:646 #, fuzzy, c-format msgid "Starting %s...\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/arm/gnunet-arm.c:649 #, c-format msgid "Stopping %s...\n" msgstr "" #: src/arm/gnunet-arm.c:660 #, fuzzy, c-format msgid "Unknown status %u for service %s.\n" msgstr "Không rõ ngưá»i dùng « %s »\n" #: src/arm/gnunet-arm.c:724 #, fuzzy msgid "stop all GNUnet services" msgstr "há»§y cài đặt dịch vụ GNUnet" #: src/arm/gnunet-arm.c:726 msgid "start a particular service" msgstr "" #: src/arm/gnunet-arm.c:728 msgid "stop a particular service" msgstr "" #: src/arm/gnunet-arm.c:730 #, fuzzy msgid "start all GNUnet default services" msgstr "há»§y cài đặt dịch vụ GNUnet" #: src/arm/gnunet-arm.c:733 #, fuzzy msgid "stop and start all GNUnet default services" msgstr "há»§y cài đặt dịch vụ GNUnet" #: src/arm/gnunet-arm.c:736 msgid "delete config file and directory on exit" msgstr "" #: src/arm/gnunet-arm.c:739 msgid "monitor ARM activities" msgstr "" #: src/arm/gnunet-arm.c:741 msgid "don't print status messages" msgstr "" #: src/arm/gnunet-arm.c:744 #, fuzzy msgid "timeout in MSECS milliseconds for completing current operation" msgstr "thá»i gian chá» sá»± hoàn thành cá»§a má»™t lần lặp (theo miligiây)" #: src/arm/gnunet-arm.c:746 #, fuzzy msgid "list currently running services" msgstr "Äang nạp và khởi động dùng « %s ».\n" #: src/arm/gnunet-arm.c:748 msgid "don't let gnunet-service-arm inherit standard output" msgstr "" #: src/arm/gnunet-arm.c:750 msgid "don't let gnunet-service-arm inherit standard error" msgstr "" #: src/arm/gnunet-arm.c:761 msgid "Control services and the Automated Restart Manager (ARM)" msgstr "" #: src/arm/gnunet-service-arm.c:266 msgid "Could not send status result to client\n" msgstr "" #: src/arm/gnunet-service-arm.c:302 #, fuzzy msgid "Could not send list result to client\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/arm/gnunet-service-arm.c:529 #, fuzzy, c-format msgid "Failed to start service `%s'\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/arm/gnunet-service-arm.c:540 #, fuzzy, c-format msgid "Starting service `%s'\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/arm/gnunet-service-arm.c:639 #, fuzzy, c-format msgid "Unable to create socket for service `%s': %s\n" msgstr "Không thể tạo tài khoản ngưá»i dùng:" #: src/arm/gnunet-service-arm.c:661 #, c-format msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:695 #, c-format msgid "ARM now monitors connections to service `%s' at `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:831 #, fuzzy, c-format msgid "Preparing to stop `%s'\n" msgstr "Äang bắt đầu tài lên « %s ».\n" #: src/arm/gnunet-service-arm.c:1100 #, fuzzy, c-format msgid "Restarting service `%s'.\n" msgstr "Äang nạp và khởi động dùng « %s ».\n" #: src/arm/gnunet-service-arm.c:1193 msgid "exit" msgstr "" #: src/arm/gnunet-service-arm.c:1198 msgid "signal" msgstr "" #: src/arm/gnunet-service-arm.c:1203 #, fuzzy msgid "unknown" msgstr "Lá»—i không rõ" #: src/arm/gnunet-service-arm.c:1209 #, fuzzy, c-format msgid "Service `%s' took %s to terminate\n" msgstr "Dịch vụ đã bị xoá.\n" #: src/arm/gnunet-service-arm.c:1231 #, c-format msgid "Service `%s' terminated normally, will restart at any time\n" msgstr "" #: src/arm/gnunet-service-arm.c:1246 #, c-format msgid "Service `%s' terminated with status %s/%d, will restart in %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:1500 #, fuzzy, c-format msgid "Starting default services `%s'\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/arm/gnunet-service-arm.c:1511 #, c-format msgid "Default service `%s' not configured correctly!\n" msgstr "" #: src/arm/gnunet-service-arm.c:1524 msgid "" "No default services configured, GNUnet will not really start right now.\n" msgstr "" #: src/arm/mockup-service.c:41 msgid "Initiating shutdown as requested by client.\n" msgstr "" #: src/ats/ats_api_performance.c:468 #, fuzzy, c-format msgid "Received %s message\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/ats/ats_api_performance.c:511 #, fuzzy, c-format msgid "Received last message for %s \n" msgstr "Nhận yêu cầu định tuyến\n" #: src/ats/gnunet-ats-solver-eval.c:2199 src/ats/gnunet-ats-solver-eval.c:2233 #: src/ats/gnunet-service-ats_addresses.c:1980 #: src/ats/gnunet-service-ats_addresses.c:2024 #, c-format msgid "" "Could not load quota for network `%s': `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2205 #: src/ats/gnunet-service-ats_addresses.c:1987 #, c-format msgid "Outbound quota configure for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2212 #: src/ats/gnunet-service-ats_addresses.c:1995 #, c-format msgid "" "No outbound quota configured for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2239 #: src/ats/gnunet-service-ats_addresses.c:2031 #, c-format msgid "Inbound quota configured for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2246 #: src/ats/gnunet-service-ats_addresses.c:2039 #, c-format msgid "" "No outbound quota configure for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2671 #: src/ats-tests/gnunet-solver-eval.c:919 msgid "solver to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2674 src/ats/gnunet-ats-solver-eval.c:2677 #: src/ats-tests/gnunet-solver-eval.c:922 #: src/ats-tests/gnunet-solver-eval.c:925 msgid "experiment to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2680 #, fuzzy msgid "print logging" msgstr "Theo dõi" #: src/ats/gnunet-service-ats_addresses.c:2217 #, c-format msgid "Initializing solver `%s '`%s'\n" msgstr "" #: src/ats/gnunet-service-ats_addresses.c:2220 #, fuzzy, c-format msgid "Failed to initialize solver `%s'!\n" msgstr "Không thể sÆ¡ khởi SQLite: %s.\n" #: src/ats/gnunet-service-ats_addresses.c:2243 #, fuzzy msgid "Failed to initialize solver!\n" msgstr "Không thể sÆ¡ khởi SQLite: %s.\n" #: src/ats/plugin_ats_mlp.c:892 msgid "Problem size too large, cannot allocate memory!\n" msgstr "" #: src/ats/plugin_ats_mlp.c:1329 #, fuzzy, c-format msgid "Adding address for peer `%s' multiple times\n" msgstr "Không thể lấy địa chỉ cá»§a đồng đẳng « %s ».\n" #: src/ats/plugin_ats_mlp.c:1376 #, c-format msgid "Updating address property `%s' for peer `%s' %p not added before\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2122 #, c-format msgid "" "Adjusting inconsistent outbound quota configuration for network `%s', is " "%llu must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2131 #, c-format msgid "" "Adjusting inconsistent inbound quota configuration for network `%s', is %llu " "must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2142 #, c-format msgid "" "Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2150 #, c-format msgid "" "Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2161 #, c-format msgid "Using default quota configuration for network `%s' (in/out) %llu/%llu\n" msgstr "" #: src/ats/plugin_ats_proportional.c:1511 #, fuzzy, c-format msgid "Invalid network type `%u' `%s': Disconnect!\n" msgstr "Không tìm thấy địa chỉ IP cá»§a máy « %s »: %s\n" #: src/ats-tests/ats-testing.c:72 msgid "Benchmarking done\n" msgstr "" #: src/ats-tests/ats-testing.c:105 #, fuzzy, c-format msgid "Failed to connect peer 0 and %u\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/ats-tests/ats-testing.c:413 #, c-format msgid "Connected master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:419 #, fuzzy, c-format msgid "Failed to connect master peer [%u] with slave [%u]\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/ats-tests/ats-testing.c:450 msgid "Connecting peers on CORE level\n" msgstr "" #: src/ats-tests/ats-testing.c:461 #, c-format msgid "Connecting master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:470 #, fuzzy, c-format msgid "Could not connect master [%u] and slave [%u]\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/ats-tests/ats-testing.c:490 src/ats-tests/ats-testing.c:671 #, fuzzy msgid "Initialization failed, shutdown\n" msgstr "Lá»—i sÆ¡ khởi cÆ¡ chế phần bổ sung: %s\n" #: src/ats-tests/ats-testing-log.c:842 #, fuzzy msgid "Stop logging\n" msgstr "Theo dõi" #: src/ats-tests/ats-testing-log.c:893 #, fuzzy, c-format msgid "Start logging `%s'\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/ats-tests/gnunet-ats-sim.c:86 #, c-format msgid "" "Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. " "= %u KiB/s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:169 #, c-format msgid "%u address resolutions had a timeout\n" msgstr "" #: src/ats-tool/gnunet-ats.c:171 #, c-format msgid "ATS returned results for %u addresses\n" msgstr "" #: src/ats-tool/gnunet-ats.c:232 #, fuzzy, c-format msgid "" "Peer `%s' plugin `%s', address `%s', `%s' bw out: %u Bytes/s, bw in %u Bytes/" "s, %s\n" msgstr "Äồng đẳng « %s » có mức tin cậy %8u và địa chỉ « %s »\n" #: src/ats-tool/gnunet-ats.c:413 #, c-format msgid "Quota for network `%11s' (in/out): %10s / %10s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:433 src/core/gnunet-core.c:163 #: src/namestore/gnunet-namestore.c:550 src/transport/gnunet-transport.c:1246 #, fuzzy, c-format msgid "Service `%s' is not running\n" msgstr "« %s » không phải là má»™t tập tin.\n" #: src/ats-tool/gnunet-ats.c:445 src/transport/gnunet-transport.c:1255 #, fuzzy, c-format msgid "Failed to parse peer identity `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/ats-tool/gnunet-ats.c:454 #, c-format msgid "Please select one operation : %s or %s or %s or %s or %s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:470 src/ats-tool/gnunet-ats.c:489 #: src/ats-tool/gnunet-ats.c:506 src/ats-tool/gnunet-ats.c:543 #, fuzzy, c-format msgid "Cannot connect to ATS service, exiting...\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/ats-tool/gnunet-ats.c:478 src/ats-tool/gnunet-ats.c:495 #, fuzzy, c-format msgid "Cannot issue request to ATS service, exiting...\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/ats-tool/gnunet-ats.c:515 #, fuzzy, c-format msgid "No preference type given!\n" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/ats-tool/gnunet-ats.c:520 #, fuzzy, c-format msgid "No peer given!\n" msgstr "chưa đưa ra tên" #: src/ats-tool/gnunet-ats.c:536 msgid "Valid type required\n" msgstr "" #: src/ats-tool/gnunet-ats.c:594 msgid "get list of active addresses currently used" msgstr "" #: src/ats-tool/gnunet-ats.c:596 msgid "get list of all active addresses" msgstr "" #: src/ats-tool/gnunet-ats.c:599 #, fuzzy msgid "do not resolve IP addresses to hostnames" msgstr "không quyết định các tên máy" #: src/ats-tool/gnunet-ats.c:601 msgid "monitor mode" msgstr "" #: src/ats-tool/gnunet-ats.c:603 #, fuzzy msgid "set preference for the given peer" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/ats-tool/gnunet-ats.c:605 msgid "print all configured quotas" msgstr "" #: src/ats-tool/gnunet-ats.c:607 msgid "peer id" msgstr "" #: src/ats-tool/gnunet-ats.c:610 msgid "preference type to set: latency | bandwidth" msgstr "" #: src/ats-tool/gnunet-ats.c:612 msgid "preference value" msgstr "" #: src/ats-tool/gnunet-ats.c:615 msgid "verbose output (include ATS address properties)" msgstr "" #: src/ats-tool/gnunet-ats.c:622 #, fuzzy msgid "Print information about ATS state" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/consensus/gnunet-consensus-profiler.c:437 #: src/secretsharing/gnunet-secretsharing-profiler.c:535 #, fuzzy msgid "number of peers in consensus" msgstr "số lần lặp lại" #: src/consensus/gnunet-consensus-profiler.c:440 msgid "how many peers receive one value?" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:443 #: src/set/gnunet-set-profiler.c:286 src/set/gnunet-set-profiler.c:289 #: src/set/gnunet-set-profiler.c:292 #, fuzzy msgid "number of values" msgstr "số lần lặp lại" #: src/consensus/gnunet-consensus-profiler.c:446 #, fuzzy msgid "consensus timeout" msgstr "# các khoá phiên chạy được chấp nhận" #: src/consensus/gnunet-consensus-profiler.c:449 msgid "delay until consensus starts" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:452 #: src/secretsharing/gnunet-secretsharing-profiler.c:550 msgid "be more verbose (print received values)" msgstr "" #: src/conversation/conversation_api.c:557 #: src/conversation/conversation_api_call.c:470 msgid "Connection to conversation service lost, trying to reconnect\n" msgstr "" #: src/conversation/gnunet-conversation.c:264 #, c-format msgid "Incoming call from `%s'. Please /accept #%u or /cancel %u the call.\n" msgstr "" #: src/conversation/gnunet-conversation.c:286 #, c-format msgid "Call from `%s' terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:319 #, c-format msgid "Call from `%s' suspended by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:324 #, c-format msgid "Call from `%s' resumed by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:342 #, c-format msgid "Ego `%s' no longer available, phone is now down.\n" msgstr "" #: src/conversation/gnunet-conversation.c:356 #, fuzzy msgid "Failed to setup phone (internal error)\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/conversation/gnunet-conversation.c:368 #, c-format msgid "" "Phone active on line %u. Type `/help' for a list of available commands\n" msgstr "" #: src/conversation/gnunet-conversation.c:390 #, c-format msgid "Resolved address of `%s'. Now ringing other party.\n" msgstr "" #: src/conversation/gnunet-conversation.c:397 #, fuzzy, c-format msgid "Connection established to `%s'\n" msgstr "%s bị lá»—i tại %s:%d: « %s »\n" #: src/conversation/gnunet-conversation.c:404 #, fuzzy, c-format msgid "Failed to resolve `%s'\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/conversation/gnunet-conversation.c:411 msgid "Call terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:417 #, c-format msgid "Connection to `%s' suspended (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:423 #, c-format msgid "Connection to `%s' resumed (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:428 msgid "Error with the call, restarting it\n" msgstr "" #: src/conversation/gnunet-conversation.c:495 #, fuzzy, c-format msgid "Unknown command `%s'\n" msgstr "Không rõ câu lệnh « %s ».\n" #: src/conversation/gnunet-conversation.c:511 #: src/conversation/gnunet-conversation.c:525 #, c-format msgid "Ego `%s' not available\n" msgstr "" #: src/conversation/gnunet-conversation.c:518 #: src/conversation/gnunet-conversation.c:575 msgid "You are calling someone else already, hang up first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:533 #: src/conversation/gnunet-conversation.c:588 #, c-format msgid "You are answering call from `%s', hang up or suspend that call first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:544 msgid "Call recipient missing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:599 msgid "There is no incoming call to accept here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:616 #, c-format msgid "There is no incoming call `%s' to accept right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:647 msgid "We currently do not have an address.\n" msgstr "" #: src/conversation/gnunet-conversation.c:670 #, c-format msgid "We are currently trying to locate the private key for the ego `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:675 #, c-format msgid "We are listening for incoming calls for ego `%s' on line %u.\n" msgstr "" #: src/conversation/gnunet-conversation.c:681 #: src/conversation/gnunet-conversation.c:705 #, c-format msgid "You are having a conversation with `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:686 msgid "" "We had an internal error setting up our phone line. You can still make " "calls.\n" msgstr "" #: src/conversation/gnunet-conversation.c:695 #, fuzzy, c-format msgid "We are trying to find the network address to call `%s'.\n" msgstr "GNUnet bây giá» sá»­ dụng địa chỉ IP %s.\n" #: src/conversation/gnunet-conversation.c:700 #, c-format msgid "We are calling `%s', his phone should be ringing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:719 msgid "Calls waiting:\n" msgstr "" #: src/conversation/gnunet-conversation.c:725 #, fuzzy, c-format msgid "#%u: `%s'\n" msgstr "Tôi là đồng đẳng « %s ».\n" #: src/conversation/gnunet-conversation.c:753 #: src/conversation/gnunet-conversation.c:768 msgid "There is no call that could be suspended right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:801 #: src/conversation/gnunet-conversation.c:817 msgid "There is no call that could be resumed right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:824 #, c-format msgid "Already talking with `%s', cannot resume a call right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:833 msgid "There is no incoming call to resume here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:850 #, c-format msgid "There is no incoming call `%s' to resume right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:885 msgid "There is no call that could be cancelled right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:893 msgid "There is no incoming call to refuse here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:910 #, c-format msgid "There is no incoming call `%s' to refuse right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:937 msgid "Use `/address' to find out which address this phone should have in GNS" msgstr "" #: src/conversation/gnunet-conversation.c:939 msgid "Use `/call USER.gnu' to call USER" msgstr "" #: src/conversation/gnunet-conversation.c:941 msgid "Use `/accept #NUM' to accept incoming call #NUM" msgstr "" #: src/conversation/gnunet-conversation.c:943 msgid "Use `/suspend' to suspend the active call" msgstr "" #: src/conversation/gnunet-conversation.c:945 msgid "" "Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming " "calls, no argument is needed to resume the current outgoing call." msgstr "" #: src/conversation/gnunet-conversation.c:947 msgid "Use `/cancel' to reject or terminate a call" msgstr "" #: src/conversation/gnunet-conversation.c:949 msgid "Use `/status' to print status information" msgstr "" #: src/conversation/gnunet-conversation.c:951 #, fuzzy msgid "Use `/quit' to terminate gnunet-conversation" msgstr "Gõ chuá»—i « /quit » để thoát khá»i trình gnunet-chat" #: src/conversation/gnunet-conversation.c:953 msgid "Use `/help command' to get help for a specific command" msgstr "Gõ chuá»—i « /help LỆNH » để xem trợ giúp vá» lệnh đó" #: src/conversation/gnunet-conversation.c:1151 #, fuzzy, c-format msgid "Name of our ego changed to `%s'\n" msgstr "Không thể tạo miá»n tên.\n" #: src/conversation/gnunet-conversation.c:1164 #, fuzzy, c-format msgid "Our ego `%s' was deleted!\n" msgstr "Biệt hiệu « %s » bị xoá.\n" #: src/conversation/gnunet-conversation.c:1199 #, fuzzy msgid "You must specify the NAME of an ego to use\n" msgstr "Phải ghi rõ chỉ má»™t tên tập tin để chèn.\n" #: src/conversation/gnunet-conversation.c:1223 #, fuzzy msgid "Failed to start gnunet-helper-w32-console\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/conversation/gnunet-conversation.c:1249 msgid "sets the NAME of the ego to use for the phone (and name resolution)" msgstr "" #: src/conversation/gnunet-conversation.c:1252 msgid "sets the LINE to use for the phone" msgstr "" #: src/conversation/gnunet-conversation.c:1276 msgid "Enables having a conversation with other GNUnet users." msgstr "" #: src/conversation/gnunet-conversation-test.c:121 #, c-format msgid "" "\n" "End of transmission. Have a GNU day.\n" msgstr "" #: src/conversation/gnunet-conversation-test.c:149 #, c-format msgid "" "\n" "We are now playing your recording back. If you can hear it, your audio " "settings are working..." msgstr "" #: src/conversation/gnunet-conversation-test.c:215 #, c-format msgid "" "We will now be recording you for %s. After that time, the recording will be " "played back to you..." msgstr "" #: src/conversation/gnunet-conversation-test.c:248 #: src/multicast/gnunet-multicast.c:70 src/revocation/gnunet-revocation.c:522 #: src/template/gnunet-template.c:70 msgid "help text" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:305 #, fuzzy, c-format msgid "pa_stream_write() failed: %s\n" msgstr "SMTP: « %s » bị lá»—i: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:587 msgid "gnunet-helper-audio-playback - Got signal, exiting\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:612 #: src/conversation/gnunet-helper-audio-record.c:545 #, fuzzy msgid "Connection established.\n" msgstr "Thu thập bị dừng.\n" #: src/conversation/gnunet-helper-audio-playback.c:617 #: src/conversation/gnunet-helper-audio-record.c:550 #, fuzzy, c-format msgid "pa_stream_new() failed: %s\n" msgstr "SMTP: « %s » bị lá»—i: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:631 #, c-format msgid "pa_stream_connect_playback() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:644 #: src/conversation/gnunet-helper-audio-record.c:576 #, fuzzy, c-format msgid "Connection failure: %s\n" msgstr "%s bị lá»—i tại %s:%d: « %s »\n" #: src/conversation/gnunet-helper-audio-playback.c:665 #: src/conversation/gnunet-helper-audio-record.c:599 msgid "Wrong Spec\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:671 #: src/conversation/gnunet-helper-audio-record.c:605 #, fuzzy msgid "pa_mainloop_new() failed.\n" msgstr "Lá»—i ná»™i bá»™ : khẳng định không thành công tại %s:%d.\n" #: src/conversation/gnunet-helper-audio-playback.c:685 #: src/conversation/gnunet-helper-audio-record.c:620 #, fuzzy msgid "pa_context_new() failed.\n" msgstr "Lá»—i ná»™i bá»™ : khẳng định không thành công tại %s:%d.\n" #: src/conversation/gnunet-helper-audio-playback.c:692 #: src/conversation/gnunet-helper-audio-record.c:626 #, fuzzy, c-format msgid "pa_context_connect() failed: %s\n" msgstr "# cá»§a các đồng đẳng đã kết nối" #: src/conversation/gnunet-helper-audio-playback.c:698 #: src/conversation/gnunet-helper-audio-record.c:632 #, fuzzy msgid "pa_mainloop_run() failed.\n" msgstr "Lá»—i ná»™i bá»™ : khẳng định không thành công tại %s:%d.\n" #: src/conversation/gnunet-helper-audio-playback.c:768 #, c-format msgid "Read error from STDIN: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback-gst.c:325 #, c-format msgid "Read error from STDIN: %d %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:344 #, fuzzy, c-format msgid "opus_encode_float() failed: %s. Aborting\n" msgstr "# cá»§a các đồng đẳng đã kết nối" #: src/conversation/gnunet-helper-audio-record.c:420 #, fuzzy, c-format msgid "pa_stream_peek() failed: %s\n" msgstr "SMTP: « %s » bị lá»—i: %s\n" #: src/conversation/gnunet-helper-audio-record.c:458 msgid "Got signal, exiting.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:483 #, fuzzy msgid "Stream successfully created.\n" msgstr "Không đủ quyá»n cho « %s ».\n" #: src/conversation/gnunet-helper-audio-record.c:488 #, fuzzy, c-format msgid "pa_stream_get_buffer_attr() failed: %s\n" msgstr "SMTP: « %s » bị lá»—i: %s\n" #: src/conversation/gnunet-helper-audio-record.c:496 #, c-format msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:500 #, c-format msgid "Using sample spec '%s', channel map '%s'.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:507 #, fuzzy, c-format msgid "Connected to device %s (%u, %ssuspended).\n" msgstr "« %s » được kết nối tá»›i « %s ».\n" #: src/conversation/gnunet-helper-audio-record.c:516 #, c-format msgid "Stream error: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:563 #, fuzzy, c-format msgid "pa_stream_connect_record() failed: %s\n" msgstr "Gặp lá»—i khi tải lên tập tin: %s\n" #: src/conversation/gnunet-helper-audio-record.c:676 #, fuzzy msgid "ogg_stream_init() failed.\n" msgstr "SMTP: « %s » bị lá»—i: %s\n" #: src/conversation/gnunet-helper-audio-record.c:721 #, fuzzy, c-format msgid "Failed to allocate %d bytes for second packet\n" msgstr "Lá»—i tạo thư mục tạm thá»i." #: src/conversation/gnunet-service-conversation.c:841 msgid "Mesh audio channel not ready; audio data dropped\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:932 #, c-format msgid "" "No available phone for incoming call on line %u, sending HANG_UP signal\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:1338 #, fuzzy, c-format msgid "Received incoming channel on port %u\n" msgstr "« %.*s » được kết nối tá»›i « %.*s ».\n" #: src/conversation/microphone.c:121 #, fuzzy msgid "Could not start record audio helper\n" msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #: src/conversation/plugin_gnsrecord_conversation.c:116 #, fuzzy, c-format msgid "Unable to parse PHONE record `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/conversation/speaker.c:75 #, fuzzy msgid "Could not start playback audio helper.\n" msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #: src/core/core_api.c:767 msgid "Client was disconnected from core service, trying to reconnect.\n" msgstr "" #: src/core/gnunet-core.c:80 #, fuzzy, c-format msgid "Peer `%s'\n" msgstr "Tôi là đồng đẳng « %s ».\n" #: src/core/gnunet-core.c:110 src/core/gnunet-core.c:138 #: src/transport/gnunet-transport.c:910 src/transport/gnunet-transport.c:930 #, c-format msgid "%24s: %-17s %4s (%u connections in total)\n" msgstr "" #: src/core/gnunet-core.c:112 src/transport/gnunet-transport.c:911 #, fuzzy msgid "Connected to" msgstr "« %s » được kết nối tá»›i « %s ».\n" #: src/core/gnunet-core.c:140 src/transport/gnunet-transport.c:931 #, fuzzy msgid "Disconnected from" msgstr "« %.*s » được kết nối tá»›i « %.*s ».\n" #: src/core/gnunet-core.c:211 src/peerinfo-tool/gnunet-peerinfo.c:694 #, fuzzy, c-format msgid "Invalid command line argument `%s'\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/core/gnunet-core.c:233 src/transport/gnunet-transport.c:1486 #, fuzzy msgid "provide information about all current connections (continuously)" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/core/gnunet-core.c:244 #, fuzzy msgid "Print information about connected peers." msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/core/gnunet-service-core.c:105 #, fuzzy msgid "Core service is lacking HOSTKEY configuration setting. Exiting.\n" msgstr "Lưu cấu hình ngay bây giá» không?" #: src/core/gnunet-service-core.c:126 #, c-format msgid "Core service of `%4s' ready.\n" msgstr "" #: src/core/gnunet-service-core_clients.c:370 #, fuzzy msgid "# send requests dropped (disconnected)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/core/gnunet-service-core_clients.c:480 #, fuzzy msgid "# messages discarded (session disconnected)" msgstr "# các thông báo được chắp liá»n" #: src/core/gnunet-service-core_clients.c:526 #, fuzzy, c-format msgid "# bytes of messages of type %u received" msgstr "# các byte nhiá»…u được nhận" #: src/core/gnunet-service-core_kx.c:535 msgid "# bytes encrypted" msgstr "# các byte đã mã hoá" #: src/core/gnunet-service-core_kx.c:586 msgid "# bytes decrypted" msgstr "# các byte đã giải mã" #: src/core/gnunet-service-core_kx.c:673 msgid "# key exchanges initiated" msgstr "" #: src/core/gnunet-service-core_kx.c:713 msgid "# key exchanges stopped" msgstr "" #: src/core/gnunet-service-core_kx.c:810 msgid "# old ephemeral keys ignored" msgstr "" #: src/core/gnunet-service-core_kx.c:816 #, fuzzy msgid "# ephemeral keys received" msgstr "# các thông báo phát hiện dht được nhận" #: src/core/gnunet-service-core_kx.c:850 #, c-format msgid "" "Ephemeral key message from peer `%s' rejected as its validity range does not " "match our system time (%llu not in [%llu,%llu]).\n" msgstr "" #: src/core/gnunet-service-core_kx.c:861 #, fuzzy msgid "# EPHEMERAL_KEY messages received" msgstr "# các thông báo được chắp liá»n" #: src/core/gnunet-service-core_kx.c:951 #: src/transport/gnunet-service-transport_validation.c:1016 #, fuzzy msgid "# PING messages received" msgstr "# các thông báo PING được tạo" #: src/core/gnunet-service-core_kx.c:959 #, fuzzy msgid "# PING messages dropped (out of order)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/core/gnunet-service-core_kx.c:986 #, c-format msgid "" "Received PING from `%s' for different identity: I am `%s', PONG identity: `" "%s'\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1003 #, fuzzy msgid "# PONG messages created" msgstr "# các thông báo PING được tạo" #: src/core/gnunet-service-core_kx.c:1029 #, fuzzy msgid "# sessions terminated by timeout" msgstr "# các byte loại Ä‘i bởi TCP (Ä‘i ra)" #: src/core/gnunet-service-core_kx.c:1039 #, fuzzy msgid "# keepalive messages sent" msgstr "# các thông báo PING nhập thô được gá»­i" #: src/core/gnunet-service-core_kx.c:1096 #: src/transport/gnunet-service-transport_validation.c:1328 #, fuzzy msgid "# PONG messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/core/gnunet-service-core_kx.c:1102 #, fuzzy msgid "# PONG messages dropped (connection down)" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/core/gnunet-service-core_kx.c:1107 #, fuzzy msgid "# PONG messages dropped (out of order)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/core/gnunet-service-core_kx.c:1137 #, fuzzy msgid "# PONG messages decrypted" msgstr "# các thông báo PING được tạo" #: src/core/gnunet-service-core_kx.c:1171 #, fuzzy msgid "# session keys confirmed via PONG" msgstr "# Các quảng cáo đồng đẳng được xác nhận qua PONG" #: src/core/gnunet-service-core_kx.c:1181 #, fuzzy msgid "# timeouts prevented via PONG" msgstr "# các byte đã nhận qua TCP" #: src/core/gnunet-service-core_kx.c:1188 #, fuzzy msgid "# rekey operations confirmed via PONG" msgstr "# Các quảng cáo đồng đẳng được xác nhận qua PONG" #: src/core/gnunet-service-core_kx.c:1328 #, fuzzy msgid "# DATA message dropped (out of order)" msgstr "# các byte loại bá» bởi UDP (Ä‘i ra)" #: src/core/gnunet-service-core_kx.c:1335 #, c-format msgid "" "Session to peer `%s' went down due to key expiration (should not happen)\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1338 #, fuzzy msgid "# sessions terminated by key expiration" msgstr "# các byte loại Ä‘i bởi TCP (Ä‘i ra)" #: src/core/gnunet-service-core_kx.c:1383 #: src/core/gnunet-service-core_kx.c:1408 #, fuzzy msgid "# bytes dropped (duplicates)" msgstr "# các byte loại bá» bởi UDP (Ä‘i ra)" #: src/core/gnunet-service-core_kx.c:1395 #, fuzzy msgid "# bytes dropped (out of sequence)" msgstr "# các byte loại bá» bởi UDP (Ä‘i ra)" #: src/core/gnunet-service-core_kx.c:1437 #, fuzzy msgid "# bytes dropped (ancient message)" msgstr "# các byte loại bá» bởi UDP (Ä‘i ra)" #: src/core/gnunet-service-core_kx.c:1445 #, fuzzy msgid "# bytes of payload decrypted" msgstr "# các byte đã giải mã" #: src/core/gnunet-service-core_kx.c:1480 #, fuzzy msgid "# PAYLOAD dropped (out of order)" msgstr "# các byte loại bá» bởi UDP (Ä‘i ra)" #: src/core/gnunet-service-core_neighbours.c:168 #, fuzzy msgid "# sessions terminated by transport disconnect" msgstr "# Các quảng cáo đồng đẳng bị há»§y do trá»ng tải" #: src/core/gnunet-service-core_neighbours.c:184 #: src/core/gnunet-service-core_neighbours.c:335 msgid "# neighbour entries allocated" msgstr "" #: src/core/gnunet-service-core_neighbours.c:252 msgid "# encrypted bytes given to transport" msgstr "" #: src/core/gnunet-service-core_neighbours.c:418 #, c-format msgid "Unsupported message of type %u (%u bytes) received from peer `%s'\n" msgstr "" #: src/core/gnunet-service-core_sessions.c:216 #: src/core/gnunet-service-core_sessions.c:288 #: src/dht/gnunet-service-dht_neighbours.c:662 #: src/dht/gnunet-service-dht_neighbours.c:727 #: src/dht/gnunet-service-xdht_neighbours.c:1304 #: src/fs/gnunet-service-fs_cp.c:606 src/fs/gnunet-service-fs_cp.c:1501 #: src/topology/gnunet-daemon-topology.c:707 #: src/topology/gnunet-daemon-topology.c:808 #: src/transport/gnunet-service-transport_neighbours.c:917 #: src/transport/gnunet-service-transport_neighbours.c:1141 #: src/transport/gnunet-service-transport_neighbours.c:3142 #: src/transport/gnunet-service-transport_neighbours.c:3438 #, fuzzy msgid "# peers connected" msgstr "# cá»§a các đồng đẳng đã kết nối" #: src/core/gnunet-service-core_sessions.c:255 #, fuzzy msgid "# type map refreshes sent" msgstr "# tổng số yêu cầu lá»— hổng được gá»­i" #: src/core/gnunet-service-core_sessions.c:426 msgid "# messages discarded (expired prior to transmission)" msgstr "" #: src/core/gnunet-service-core_typemap.c:110 #: src/core/gnunet-service-core_typemap.c:121 #, fuzzy msgid "# type maps received" msgstr "# các thông báo phát hiện dht được nhận" #: src/core/gnunet-service-core_typemap.c:151 msgid "# updates to my type map" msgstr "" #: src/datacache/datacache.c:115 src/datacache/datacache.c:266 #: src/datastore/gnunet-service-datastore.c:838 #, fuzzy msgid "# bytes stored" msgstr "# các byte trong kho dữ liệu" #: src/datacache/datacache.c:117 src/datacache/datacache.c:268 #, fuzzy msgid "# items stored" msgstr "# các byte trong kho dữ liệu" #: src/datacache/datacache.c:143 src/datacache/datacache.c:150 #: src/datastore/gnunet-service-datastore.c:1487 #: src/datastore/gnunet-service-datastore.c:1498 #, c-format msgid "No `%s' specified for `%s' in configuration!\n" msgstr "" #: src/datacache/datacache.c:184 #, c-format msgid "Loading `%s' datacache plugin\n" msgstr "" #: src/datacache/datacache.c:192 #, fuzzy, c-format msgid "Failed to load datacache plugin for `%s'\n" msgstr "Lá»—i cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #: src/datacache/datacache.c:295 #, fuzzy msgid "# requests received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/datacache/datacache.c:304 msgid "# requests filtered by bloom filter" msgstr "# các yêu cầu được lá»c theo bá»™ lá»c bloom" #: src/datacache/plugin_datacache_heap.c:406 #, fuzzy msgid "Heap datacache running\n" msgstr "kho dữ liệu sqlite" #: src/datacache/plugin_datacache_postgres.c:392 msgid "Postgres datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:69 #: src/datacache/plugin_datacache_sqlite.c:72 #: src/datastore/plugin_datastore_mysql.c:806 #: src/datastore/plugin_datastore_mysql.c:820 #: src/datastore/plugin_datastore_sqlite.c:57 src/mysql/mysql.c:41 #: src/mysql/mysql.c:48 src/mysql/mysql.c:522 src/mysql/mysql.c:531 #: src/mysql/mysql.c:591 src/mysql/mysql.c:607 #: src/namecache/plugin_namecache_postgres.c:52 #: src/namecache/plugin_namecache_sqlite.c:52 #: src/namestore/plugin_namestore_postgres.c:52 #: src/namestore/plugin_namestore_sqlite.c:52 #: src/testbed/generate-underlay-topology.c:47 #: src/testbed/gnunet-daemon-latency-logger.c:52 #: src/testbed/gnunet-daemon-testbed-underlay.c:55 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:51 #: src/util/crypto_mpi.c:39 src/include/gnunet_common.h:602 #: src/include/gnunet_common.h:611 src/scalarproduct/scalarproduct.h:50 #, c-format msgid "`%s' failed at %s:%d with error: %s\n" msgstr "« %s » bị lá»—i tại %s:%d vá»›i lá»—i: %s\n" #: src/datacache/plugin_datacache_sqlite.c:450 msgid "Sqlite datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:484 #: src/datastore/plugin_datastore_sqlite.c:404 #: src/namecache/plugin_namecache_sqlite.c:295 #: src/namestore/plugin_namestore_sqlite.c:327 msgid "Tried to close sqlite without finalizing all prepared statements.\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:491 #, fuzzy, c-format msgid "Failed to close statement %p: %d\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/datacache/plugin_datacache_template.c:125 msgid "Template datacache running\n" msgstr "" #: src/datastore/datastore_api.c:310 msgid "Failed to transmit request to drop database.\n" msgstr "" #: src/datastore/datastore_api.c:394 msgid "# queue entry timeouts" msgstr "" #: src/datastore/datastore_api.c:443 msgid "# queue overflows" msgstr "" #: src/datastore/datastore_api.c:471 #, fuzzy msgid "# queue entries created" msgstr "# các truy vấn lá»— hổng được định tuyến" #: src/datastore/datastore_api.c:491 #, fuzzy msgid "# Requests dropped from datastore queue" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/datastore/datastore_api.c:533 #, fuzzy msgid "# datastore connections (re)created" msgstr "# các kết nối dht" #: src/datastore/datastore_api.c:616 src/scalarproduct/scalarproduct_api.c:279 #, fuzzy msgid "# transmission request failures" msgstr "# các sá»± truyá»n PONG bị lá»—i" #: src/datastore/datastore_api.c:638 #, fuzzy msgid "# bytes sent to datastore" msgstr "# các byte trong kho dữ liệu" #: src/datastore/datastore_api.c:770 #, fuzzy msgid "Failed to receive status response from database." msgstr "" "\n" "Không nhận được đáp ứng từ gnunetd.\n" #: src/datastore/datastore_api.c:784 msgid "Error reading response from datastore service" msgstr "" #: src/datastore/datastore_api.c:796 src/datastore/datastore_api.c:802 #, fuzzy msgid "Invalid error message received from datastore service" msgstr "Nhận được thông báo « %s » sai từ đồng đẳng « %s ».\n" #: src/datastore/datastore_api.c:806 #, fuzzy msgid "# status messages received" msgstr "# các thông báo phát hiện dht được nhận" #: src/datastore/datastore_api.c:876 #, fuzzy msgid "# PUT requests executed" msgstr "# các yêu cầu dht được định tuyến" #: src/datastore/datastore_api.c:944 #, fuzzy msgid "# RESERVE requests executed" msgstr "# các yêu cầu dht được định tuyến" #: src/datastore/datastore_api.c:1005 msgid "# RELEASE RESERVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1065 #, fuzzy msgid "# UPDATE requests executed" msgstr "# các yêu cầu dht được định tuyến" #: src/datastore/datastore_api.c:1129 #, fuzzy msgid "# REMOVE requests executed" msgstr "# các yêu cầu dht được định tuyến" #: src/datastore/datastore_api.c:1174 #, fuzzy msgid "Failed to receive response from database.\n" msgstr "" "\n" "Không nhận được đáp ứng từ gnunetd.\n" #: src/datastore/datastore_api.c:1233 #, fuzzy msgid "# Results received" msgstr "# các kết quả dht được nhận" #: src/datastore/datastore_api.c:1300 msgid "# GET REPLICATION requests executed" msgstr "" #: src/datastore/datastore_api.c:1363 msgid "# GET ZERO ANONYMITY requests executed" msgstr "" #: src/datastore/datastore_api.c:1424 #, fuzzy msgid "# GET requests executed" msgstr "# các yêu cầu dht được định tuyến" #: src/datastore/gnunet-datastore.c:114 #, fuzzy, c-format msgid "Failed to store item: %s, aborting\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/datastore/gnunet-datastore.c:200 #, c-format msgid "Cannot use the same configuration for source and destination\n" msgstr "" #: src/datastore/gnunet-datastore.c:246 msgid "" "specifies the configuration to use to access an alternative datastore; will " "merge that datastore into our current datastore" msgstr "" #: src/datastore/gnunet-datastore.c:255 #, fuzzy msgid "Manipulate GNUnet datastore" msgstr "cập nhật má»™t giá trị trong tập tin cấu hình" #: src/datastore/gnunet-service-datastore.c:351 #, fuzzy msgid "# bytes expired" msgstr "# các byte được nhận" #: src/datastore/gnunet-service-datastore.c:425 msgid "# bytes purged (low-priority)" msgstr "" #: src/datastore/gnunet-service-datastore.c:483 #: src/gns/gnunet-gns-helper-service-w32.c:223 msgid "Transmission to client failed!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:514 #: src/gns/gnunet-gns-helper-service-w32.c:262 msgid "Shutdown in progress, aborting transmission.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:630 msgid "# results found" msgstr "" #: src/datastore/gnunet-service-datastore.c:673 #, c-format msgid "" "Insufficient space (%llu bytes are available) to satisfy `%s' request for " "%llu bytes\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:684 #, c-format msgid "" "The requested amount (%llu bytes) is larger than the cache size (%llu " "bytes)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:688 msgid "" "Insufficient space to satisfy request and requested amount is larger than " "cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:694 msgid "Insufficient space to satisfy request" msgstr "" #: src/datastore/gnunet-service-datastore.c:699 #: src/datastore/gnunet-service-datastore.c:751 #: src/datastore/gnunet-service-datastore.c:964 #: src/datastore/gnunet-service-datastore.c:1421 msgid "# reserved" msgstr "" #: src/datastore/gnunet-service-datastore.c:764 msgid "Could not find matching reservation" msgstr "" #: src/datastore/gnunet-service-datastore.c:850 #, c-format msgid "Need %llu bytes more space (%llu allowed, using %llu)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1010 #, fuzzy msgid "# GET requests received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/datastore/gnunet-service-datastore.c:1022 #, fuzzy msgid "# requests filtered by bloomfilter" msgstr "# các yêu cầu được lá»c theo bá»™ lá»c bloom" #: src/datastore/gnunet-service-datastore.c:1050 #, fuzzy msgid "# UPDATE requests received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/datastore/gnunet-service-datastore.c:1080 #, fuzzy msgid "# GET REPLICATION requests received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/datastore/gnunet-service-datastore.c:1113 #, fuzzy msgid "# GET ZERO ANONYMITY requests received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/datastore/gnunet-service-datastore.c:1138 msgid "Content not found" msgstr "" #: src/datastore/gnunet-service-datastore.c:1146 msgid "# bytes removed (explicit request)" msgstr "" #: src/datastore/gnunet-service-datastore.c:1178 #, fuzzy msgid "# REMOVE requests received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/datastore/gnunet-service-datastore.c:1220 #, c-format msgid "Datastore payload inaccurate (%lld < %lld). Trying to fix.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1281 #, c-format msgid "Loading `%s' datastore plugin\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1290 #, fuzzy, c-format msgid "Failed to load datastore plugin for `%s'\n" msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #: src/datastore/gnunet-service-datastore.c:1492 #, fuzzy, c-format msgid "# bytes used in file-sharing datastore `%s'" msgstr "# các byte được phép trong kho dữ liệu" #: src/datastore/gnunet-service-datastore.c:1503 msgid "# quota" msgstr "" #: src/datastore/gnunet-service-datastore.c:1505 msgid "# cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:1518 #, c-format msgid "Could not use specified filename `%s' for bloomfilter.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1536 #: src/datastore/gnunet-service-datastore.c:1552 #, fuzzy, c-format msgid "Failed to remove bogus bloomfilter file `%s'\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/datastore/gnunet-service-datastore.c:1582 #, fuzzy msgid "Failed to initialize bloomfilter.\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/datastore/gnunet-service-datastore.c:1611 msgid "Rebuilding bloomfilter. Please be patient.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1616 msgid "Plugin does not support get_keys function. Please fix!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1619 msgid "Bloomfilter construction complete.\n" msgstr "" #: src/datastore/plugin_datastore_heap.c:820 #, fuzzy msgid "Heap database running\n" msgstr "kho dữ liệu sqlite" #: src/datastore/plugin_datastore_mysql.c:783 #, fuzzy, c-format msgid "Failed to prepare statement `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/datastore/plugin_datastore_mysql.c:791 #, fuzzy, c-format msgid "`%s' for `%s' failed at %s:%d with error: %s\n" msgstr "« %s » bị lá»—i tại %s:%d vá»›i lá»—i: %s\n" #: src/datastore/plugin_datastore_mysql.c:1022 msgid "Mysql database running\n" msgstr "" #: src/datastore/plugin_datastore_postgres.c:824 #, fuzzy msgid "Failed to drop table from database.\n" msgstr "" "\n" "Không nhận được đáp ứng từ gnunetd.\n" #: src/datastore/plugin_datastore_postgres.c:860 #: src/namecache/plugin_namecache_postgres.c:414 #: src/namestore/plugin_namestore_postgres.c:569 msgid "Postgres database running\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:57 #: src/testbed/generate-underlay-topology.c:50 #: src/testbed/gnunet-daemon-latency-logger.c:55 #: src/testbed/gnunet-daemon-testbed-underlay.c:58 #, fuzzy, c-format msgid "`%s' failed at %s:%u with error: %s" msgstr "« %s » bị lá»—i tại %s:%d vá»›i lá»—i: %s" #: src/datastore/plugin_datastore_sqlite.c:255 #: src/namecache/plugin_namecache_sqlite.c:193 #: src/namestore/plugin_namestore_sqlite.c:204 #: src/psycstore/plugin_psycstore_sqlite.c:319 #, c-format msgid "Unable to initialize SQLite: %s.\n" msgstr "Không thể sÆ¡ khởi SQLite: %s.\n" #: src/datastore/plugin_datastore_sqlite.c:663 #, fuzzy msgid "Invalid data in database. Trying to fix (by deletion).\n" msgstr "Dữ liệu sai trong %s. Äang thá»­ sá»­a chữa (bằng cách xoá).\n" #: src/datastore/plugin_datastore_sqlite.c:1156 msgid "sqlite version to old to determine size, assuming zero\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1175 #, c-format msgid "" "Using sqlite page utilization to estimate payload (%llu pages of size %llu " "bytes)\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1215 #: src/namecache/plugin_namecache_sqlite.c:583 #: src/namestore/plugin_namestore_sqlite.c:719 #, fuzzy msgid "Sqlite database running\n" msgstr "kho dữ liệu sqlite" #: src/datastore/plugin_datastore_template.c:257 msgid "Template database running\n" msgstr "" #: src/dht/dht_api.c:376 #, fuzzy msgid "Failed to connect to the DHT service!\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/dht/gnunet-dht-get.c:133 #, c-format msgid "" "Result %d, type %d:\n" "%.*s\n" msgstr "" #: src/dht/gnunet-dht-get.c:159 msgid "Must provide key for DHT GET!\n" msgstr "" #: src/dht/gnunet-dht-get.c:165 src/dht/gnunet-dht-monitor.c:225 #, fuzzy msgid "Failed to connect to DHT service!\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/dht/gnunet-dht-get.c:173 msgid "Issueing DHT GET with key" msgstr "" #: src/dht/gnunet-dht-get.c:189 src/dht/gnunet-dht-monitor.c:262 #: src/dht/gnunet-dht-put.c:198 msgid "the query key" msgstr "" #: src/dht/gnunet-dht-get.c:192 msgid "how many parallel requests (replicas) to create" msgstr "" #: src/dht/gnunet-dht-get.c:195 src/dht/gnunet-dht-monitor.c:265 msgid "the type of data to look for" msgstr "" #: src/dht/gnunet-dht-get.c:198 src/dht/gnunet-dht-put.c:210 msgid "how long to execute this query before giving up?" msgstr "" #: src/dht/gnunet-dht-get.c:201 src/dht/gnunet-dht-put.c:201 msgid "use DHT's demultiplex everywhere option" msgstr "" #: src/dht/gnunet-dht-get.c:204 src/dht/gnunet-dht-monitor.c:271 #: src/dht/gnunet-dht-put.c:213 src/fs/gnunet-auto-share.c:753 #: src/fs/gnunet-download.c:328 src/fs/gnunet-publish.c:877 #: src/fs/gnunet-search.c:301 src/fs/gnunet-unindex.c:168 #: src/nse/gnunet-nse-profiler.c:873 msgid "be verbose (print progress information)" msgstr "" #: src/dht/gnunet-dht-get.c:225 msgid "Issue a GET request to the GNUnet DHT, prints results." msgstr "" #: src/dht/gnunet-dht-monitor.c:268 msgid "how long should the monitor command run" msgstr "" #: src/dht/gnunet-dht-monitor.c:293 msgid "Prints all packets that go through the DHT." msgstr "" #: src/dht/gnunet-dht-put.c:118 #, fuzzy msgid "PUT request sent with key" msgstr "# độ tin cậy được tiêu phí" #: src/dht/gnunet-dht-put.c:121 msgid "Timeout sending PUT request!\n" msgstr "" #: src/dht/gnunet-dht-put.c:124 #, fuzzy msgid "PUT request not confirmed!\n" msgstr "# độ tin cậy được tiêu phí" #: src/dht/gnunet-dht-put.c:153 msgid "Must provide KEY and DATA for DHT put!\n" msgstr "" #: src/dht/gnunet-dht-put.c:160 #, fuzzy, c-format msgid "Could not connect to %s service!\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/dht/gnunet-dht-put.c:176 #, c-format msgid "Issuing put request for `%s' with data `%s'!\n" msgstr "" #: src/dht/gnunet-dht-put.c:192 msgid "the data to insert under the key" msgstr "" #: src/dht/gnunet-dht-put.c:195 msgid "how long to store this entry in the dht (in seconds)" msgstr "" #: src/dht/gnunet-dht-put.c:204 msgid "how many replicas to create" msgstr "" #: src/dht/gnunet-dht-put.c:207 msgid "the type to insert data as" msgstr "" #: src/dht/gnunet-dht-put.c:236 msgid "Issue a PUT request to the GNUnet DHT insert DATA under KEY." msgstr "" #: src/dht/gnunet-service-dht.c:172 src/dht/gnunet-service-xdht.c:176 #, fuzzy msgid "Failed to connect to transport service!\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/dht/gnunet-service-dht_clients.c:417 #: src/dht/gnunet-service-xdht_clients.c:838 #, fuzzy msgid "# GET requests from clients injected" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_clients.c:513 #: src/dht/gnunet-service-xdht_clients.c:927 #, fuzzy msgid "# PUT requests received from clients" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/dht/gnunet-service-dht_clients.c:597 #: src/dht/gnunet-service-xdht_clients.c:1013 #, fuzzy msgid "# GET requests received from clients" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_clients.c:798 #: src/dht/gnunet-service-xdht_clients.c:1214 #, fuzzy msgid "# GET STOP requests received from clients" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_clients.c:1039 #: src/dht/gnunet-service-xdht_clients.c:498 msgid "# Key match, type mismatches in REPLY to CLIENT" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1052 #: src/dht/gnunet-service-xdht_clients.c:511 msgid "# Duplicate REPLIES to CLIENT request dropped" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1089 #: src/dht/gnunet-service-xdht_clients.c:548 #, c-format msgid "Unsupported block type (%u) in request!\n" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1112 #: src/dht/gnunet-service-xdht_clients.c:571 msgid "# RESULTS queued for clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1166 #: src/dht/gnunet-service-dht_clients.c:1209 #: src/dht/gnunet-service-xdht_clients.c:625 #: src/dht/gnunet-service-xdht_clients.c:668 msgid "# REPLIES ignored for CLIENTS (no match)" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1176 #: src/dht/gnunet-service-xdht_clients.c:635 msgid "Could not pass reply to client, message too big!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:68 #: src/dht/gnunet-service-xdht_datacache.c:68 #, fuzzy, c-format msgid "%s request received, but have no datacache!\n" msgstr "# các byte kiểu %d được nhận" #: src/dht/gnunet-service-dht_datacache.c:78 #: src/dht/gnunet-service-xdht_datacache.c:78 msgid "# ITEMS stored in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:165 #: src/dht/gnunet-service-xdht_datacache.c:165 msgid "# Good RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:176 #: src/dht/gnunet-service-xdht_datacache.c:176 msgid "# Duplicate RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:182 #: src/dht/gnunet-service-xdht_datacache.c:182 msgid "# Invalid RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:188 #: src/dht/gnunet-service-xdht_datacache.c:188 msgid "# Irrelevant RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:200 #: src/dht/gnunet-service-xdht_datacache.c:200 msgid "# Unsupported RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:203 #: src/dht/gnunet-service-xdht_datacache.c:203 #, c-format msgid "Unsupported block type (%u) in local response!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:234 #: src/dht/gnunet-service-xdht_datacache.c:234 #, fuzzy msgid "# GET requests given to datacache" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_hello.c:84 #: src/dht/gnunet-service-xdht_hello.c:82 #, fuzzy msgid "# HELLOs obtained from peerinfo" msgstr "Nhận được thông báo « %s » sai từ đồng đẳng « %s ».\n" #: src/dht/gnunet-service-dht_neighbours.c:516 msgid "# Preference updates given to core" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:610 #, fuzzy msgid "# FIND PEER messages initiated" msgstr "# các thông báo PING được tạo" #: src/dht/gnunet-service-dht_neighbours.c:764 #, fuzzy msgid "# Queued messages discarded (peer disconnected)" msgstr "# các thông báo được chắp liá»n" #: src/dht/gnunet-service-dht_neighbours.c:819 #: src/dht/gnunet-service-xdht_neighbours.c:703 #, fuzzy msgid "# Bytes transmitted to other peers" msgstr "# các byte kiểu %d được gá»­i " #: src/dht/gnunet-service-dht_neighbours.c:857 #: src/dht/gnunet-service-xdht_neighbours.c:742 #, fuzzy msgid "# Bytes of bandwidth requested from core" msgstr "# các yêu cầu máy/trình khách lá»— hổng được phun vào" #: src/dht/gnunet-service-dht_neighbours.c:889 #, fuzzy msgid "# requests TTL-dropped" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_neighbours.c:1093 #: src/dht/gnunet-service-dht_neighbours.c:1130 msgid "# Peers excluded from routing due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1108 #: src/dht/gnunet-service-dht_neighbours.c:1145 #, fuzzy msgid "# Peer selection failed" msgstr "# các cuá»™c gá»i HTTP select (lá»±a chá»n)" #: src/dht/gnunet-service-dht_neighbours.c:1287 #, fuzzy msgid "# PUT requests routed" msgstr "# các yêu cầu dht được định tuyến" #: src/dht/gnunet-service-dht_neighbours.c:1316 #, fuzzy msgid "# PUT messages queued for transmission" msgstr "# các thông báo PING được tạo" #: src/dht/gnunet-service-dht_neighbours.c:1323 #: src/dht/gnunet-service-dht_neighbours.c:1440 #: src/dht/gnunet-service-dht_neighbours.c:1543 #: src/dht/gnunet-service-xdht_neighbours.c:794 #: src/dht/gnunet-service-xdht_neighbours.c:860 #: src/dht/gnunet-service-xdht_neighbours.c:919 #: src/dht/gnunet-service-xdht_neighbours.c:981 #: src/dht/gnunet-service-xdht_neighbours.c:1041 #, fuzzy msgid "# P2P messages dropped due to full queue" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/dht/gnunet-service-dht_neighbours.c:1405 #, fuzzy msgid "# GET requests routed" msgstr "# các yêu cầu dht được định tuyến" #: src/dht/gnunet-service-dht_neighbours.c:1432 #, fuzzy msgid "# GET messages queued for transmission" msgstr "# các thông báo PING được tạo" #: src/dht/gnunet-service-dht_neighbours.c:1550 #, fuzzy msgid "# RESULT messages queued for transmission" msgstr "# các thông báo PING được tạo" #: src/dht/gnunet-service-dht_neighbours.c:1636 #, fuzzy msgid "# P2P PUT requests received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_neighbours.c:1639 #, fuzzy msgid "# P2P PUT bytes received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_neighbours.c:1803 #, fuzzy msgid "# FIND PEER requests ignored due to Bloomfilter" msgstr "# các yêu cầu được lá»c theo bá»™ lá»c bloom" #: src/dht/gnunet-service-dht_neighbours.c:1811 msgid "# FIND PEER requests ignored due to lack of HELLO" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1904 #, fuzzy msgid "# P2P GET requests received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_neighbours.c:1907 #, fuzzy msgid "# P2P GET bytes received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_neighbours.c:1961 #, fuzzy msgid "# P2P FIND PEER requests processed" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_neighbours.c:1975 #, fuzzy msgid "# P2P GET requests ONLY routed" msgstr "# các yêu cầu dht được định tuyến" #: src/dht/gnunet-service-dht_neighbours.c:2052 #, fuzzy msgid "# P2P RESULTS received" msgstr "# Tín hiệu HTTP PUT được nhận" #: src/dht/gnunet-service-dht_neighbours.c:2055 #, fuzzy msgid "# P2P RESULT bytes received" msgstr "# Tín hiệu HTTP PUT được nhận" #: src/dht/gnunet-service-dht_nse.c:59 src/dht/gnunet-service-xdht_nse.c:59 #, fuzzy msgid "# Network size estimates received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-dht_routing.c:211 msgid "# Good REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:220 msgid "# Duplicate REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:226 msgid "# Invalid REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:232 msgid "# Irrelevant REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:244 msgid "# Unsupported REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:317 msgid "# Entries removed from routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:399 msgid "# Entries added to routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:417 #, fuzzy msgid "# DHT requests combined" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/dht/gnunet-service-xdht_neighbours.c:1398 #, c-format msgid "" "\n" "SUPU %s, %s, %d,my_identity = %s" msgstr "" #: src/dht/gnunet-service-xdht_neighbours.c:1514 #: src/dht/gnunet-service-xdht_neighbours.c:1524 #: src/dht/gnunet-service-xdht_neighbours.c:1530 #: src/dht/gnunet-service-xdht_neighbours.c:1536 #: src/dht/gnunet-service-xdht_neighbours.c:1545 #, c-format msgid "" "\n" "SUPU %s, %s, %d" msgstr "" #: src/dht/plugin_block_dht.c:138 #, fuzzy, c-format msgid "Block not of type %u\n" msgstr "Không biết truyá»n tải nào kiểu %d.\n" #: src/dht/plugin_block_dht.c:145 msgid "Size mismatch for block\n" msgstr "" #: src/dht/plugin_block_dht.c:155 #, c-format msgid "Block of type %u is malformed\n" msgstr "" #: src/dns/dnsparser.c:257 #, fuzzy, c-format msgid "Failed to convert DNS IDNA name `%s' to UTF-8: %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/dns/dnsparser.c:856 #, fuzzy, c-format msgid "Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/dns/dnsstub.c:175 #, fuzzy, c-format msgid "Could not bind to any port: %s\n" msgstr "Không tìm thấy địa chỉ IP cá»§a máy « %s »: %s\n" #: src/dns/dnsstub.c:295 src/dns/dnsstub.c:383 #, fuzzy, c-format msgid "Failed to send DNS request to %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/dns/dnsstub.c:299 #, fuzzy, c-format msgid "Sent DNS request to %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/dns/dnsstub.c:368 #, c-format msgid "Configured DNS exit `%s' is not working / valid.\n" msgstr "" #: src/dns/dnsstub.c:440 #, c-format msgid "Received DNS response that is too small (%u bytes)" msgstr "" #: src/dns/gnunet-dns-monitor.c:355 msgid "only monitor DNS queries" msgstr "" #: src/dns/gnunet-dns-monitor.c:358 msgid "only monitor DNS replies" msgstr "" #: src/dns/gnunet-dns-monitor.c:369 msgid "Monitor DNS queries." msgstr "" #: src/dns/gnunet-dns-redirector.c:236 msgid "set A records" msgstr "" #: src/dns/gnunet-dns-redirector.c:239 msgid "set AAAA records" msgstr "" #: src/dns/gnunet-dns-redirector.c:251 msgid "Change DNS replies to point elsewhere." msgstr "" #: src/dns/gnunet-service-dns.c:456 msgid "# DNS requests answered via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:603 msgid "# DNS exit failed (failed to open socket)" msgstr "" #: src/dns/gnunet-service-dns.c:714 msgid "# External DNS response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:792 msgid "# Client response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:907 msgid "Received malformed IPv4-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:923 msgid "Received malformed IPv6-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:932 #, c-format msgid "Got non-IP packet with %u bytes and protocol %u from TUN\n" msgstr "" #: src/dns/gnunet-service-dns.c:942 msgid "# Non-DNS UDP packet received via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:1009 #, fuzzy msgid "# DNS requests received via TUN interface" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/dns/gnunet-service-dns.c:1049 src/exit/gnunet-daemon-exit.c:3514 #, c-format msgid "`%s' must be installed SUID, refusing to run\n" msgstr "" #: src/dns/gnunet-service-dns.c:1069 src/exit/gnunet-daemon-exit.c:3571 #, fuzzy msgid "need a valid IPv4 or IPv6 address\n" msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n" #: src/dv/gnunet-dv.c:169 msgid "verbose output" msgstr "" #: src/dv/gnunet-dv.c:178 #, fuzzy msgid "Print information about DV state" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/exit/gnunet-daemon-exit.c:802 #, c-format msgid "Got duplicate service records for `%s:%u'\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:853 #, fuzzy msgid "# Bytes transmitted via mesh channels" msgstr "# các byte được gá»­i" #: src/exit/gnunet-daemon-exit.c:970 src/exit/gnunet-daemon-exit.c:2397 #: src/exit/gnunet-daemon-exit.c:2654 src/vpn/gnunet-service-vpn.c:1407 #: src/vpn/gnunet-service-vpn.c:1797 src/vpn/gnunet-service-vpn.c:1960 msgid "# ICMPv4 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1007 src/exit/gnunet-daemon-exit.c:2456 #: src/exit/gnunet-daemon-exit.c:2713 src/vpn/gnunet-service-vpn.c:1463 #: src/vpn/gnunet-service-vpn.c:1856 src/vpn/gnunet-service-vpn.c:1993 msgid "# ICMPv6 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1047 msgid "# ICMP packets dropped (not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1054 msgid "ICMP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1130 msgid "UDP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1204 msgid "TCP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1256 #, fuzzy msgid "# Packets received from TUN" msgstr "# các byte đã nhận qua HTTP" #: src/exit/gnunet-daemon-exit.c:1270 #, fuzzy msgid "# Bytes received from TUN" msgstr "# các byte đã nhận qua HTTP" #: src/exit/gnunet-daemon-exit.c:1296 msgid "IPv4 packet options received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1323 #, c-format msgid "IPv4 packet with unsupported next header %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1369 #, c-format msgid "IPv6 packet with unsupported next header %d received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1377 #, c-format msgid "Packet from unknown protocol %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1759 #, fuzzy msgid "# TCP packets sent via TUN" msgstr "# các byte đã gá»­i qua UDP" #: src/exit/gnunet-daemon-exit.c:1872 #, fuzzy msgid "# TCP service creation requests received via mesh" msgstr "# các yêu cầu danh sách máy được nhận" #: src/exit/gnunet-daemon-exit.c:1875 src/exit/gnunet-daemon-exit.c:1968 #: src/exit/gnunet-daemon-exit.c:2073 src/exit/gnunet-daemon-exit.c:2321 #: src/exit/gnunet-daemon-exit.c:2570 src/exit/gnunet-daemon-exit.c:2859 #: src/exit/gnunet-daemon-exit.c:2966 #, fuzzy msgid "# Bytes received from MESH" msgstr "# các byte đã nhận qua HTTP" #: src/exit/gnunet-daemon-exit.c:1909 src/exit/gnunet-daemon-exit.c:2990 #, c-format msgid "No service %s found for %s on port %d!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1914 #, fuzzy msgid "# TCP requests dropped (no such service)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/exit/gnunet-daemon-exit.c:1971 #, fuzzy msgid "# TCP IP-exit creation requests received via mesh" msgstr "# các yêu cầu danh sách máy được nhận" #: src/exit/gnunet-daemon-exit.c:2076 #, fuzzy msgid "# TCP data requests received via mesh" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/exit/gnunet-daemon-exit.c:2090 #, fuzzy msgid "# TCP DATA requests dropped (no session)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/exit/gnunet-daemon-exit.c:2150 #, fuzzy msgid "# ICMP packets sent via TUN" msgstr "# các byte đã gá»­i qua UDP" #: src/exit/gnunet-daemon-exit.c:2324 #, fuzzy msgid "# ICMP IP-exit requests received via mesh" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/exit/gnunet-daemon-exit.c:2573 #, fuzzy msgid "# ICMP service requests received via mesh" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/exit/gnunet-daemon-exit.c:2639 src/vpn/gnunet-service-vpn.c:1397 #: src/vpn/gnunet-service-vpn.c:1954 msgid "# ICMPv4 packets dropped (impossible PT to v6)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2698 src/vpn/gnunet-service-vpn.c:1433 #: src/vpn/gnunet-service-vpn.c:1445 src/vpn/gnunet-service-vpn.c:1844 msgid "# ICMPv6 packets dropped (impossible PT to v4)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2748 #, fuzzy msgid "# UDP packets sent via TUN" msgstr "# các byte đã gá»­i qua UDP" #: src/exit/gnunet-daemon-exit.c:2862 #, fuzzy msgid "# UDP IP-exit requests received via mesh" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/exit/gnunet-daemon-exit.c:2969 #, fuzzy msgid "# UDP service requests received via mesh" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/exit/gnunet-daemon-exit.c:2995 #, fuzzy msgid "# UDP requests dropped (no such service)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/exit/gnunet-daemon-exit.c:3031 #, fuzzy msgid "# Inbound MESH channels created" msgstr "# các truy vấn lá»— hổng được định tuyến" #: src/exit/gnunet-daemon-exit.c:3235 src/exit/gnunet-daemon-exit.c:3245 #, fuzzy, c-format msgid "Option `%s' for domain `%s' is not formatted correctly!\n" msgstr "Bị từ chối đặt tùy chá»n « %s » trong phần « %s » thành « %s ».\n" #: src/exit/gnunet-daemon-exit.c:3259 src/exit/gnunet-daemon-exit.c:3267 #, c-format msgid "`%s' is not a valid port number (for domain `%s')!" msgstr "" #: src/exit/gnunet-daemon-exit.c:3300 #, c-format msgid "No addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3314 src/exit/gnunet-daemon-exit.c:3326 #, c-format msgid "Service `%s' configured for IPv4, but IPv4 is disabled!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3337 #, c-format msgid "No IP addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3527 msgid "" "This system does not support IPv4, will disable IPv4 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3535 msgid "" "This system does not support IPv6, will disable IPv6 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3542 msgid "" "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use " "ENABLE_IPv4=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3548 msgid "" "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use " "ENABLE_IPv6=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3554 src/exit/gnunet-daemon-exit.c:3717 #: src/pt/gnunet-daemon-pt.c:1247 msgid "No useful service enabled. Exiting.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3664 msgid "Must be a number" msgstr "" #: src/exit/gnunet-daemon-exit.c:3813 msgid "Daemon to run to provide an IP exit node for the VPN" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:55 msgid "Experimentation daemon shutting down ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:77 msgid "Experimentation daemon starting ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:83 #, fuzzy msgid "Failed to create statistics!\n" msgstr "Không thể tạo miá»n tên.\n" #: src/experimentation/gnunet-daemon-experimentation.c:120 msgid "GNUnet experimentation daemon" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:241 #, c-format msgid "Experiment `%s': Experiment signature is invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:250 #, c-format msgid "" "Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu " "sec. \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:303 #, c-format msgid "Experiment `%s': Issuer missing\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:312 #, c-format msgid "Experiment `%s': Issuer invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:320 #, c-format msgid "Experiment `%s': Issuer not accepted!\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:330 #, c-format msgid "Experiment `%s': Version missing or invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:339 #, c-format msgid "Experiment `%s': Required capabilities missing \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:345 #, c-format msgid "Experiment `%s': Required capabilities invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:390 #, fuzzy, c-format msgid "Failed to parse file `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:420 #: src/experimentation/gnunet-daemon-experimentation_experiments.c:452 msgid "" "No valid experiment issuers configured! Set value to public keys of issuers! " "Exiting.\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:435 #, fuzzy msgid "Invalid value for public key\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:473 #, fuzzy, c-format msgid "Cannot read experiments file `%s'\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:221 #, c-format msgid "Cannot send message to peer `%s' for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:309 #, c-format msgid "Sending experimentation request to peer %s\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:453 #, c-format msgid "Added peer `%s' as active node\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:891 #, fuzzy, c-format msgid "Connected to peer %s\n" msgstr "« %s » được kết nối tá»›i « %s ».\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:921 #, fuzzy, c-format msgid "Disconnected from peer %s\n" msgstr "« %.*s » được kết nối tá»›i « %.*s ».\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:1104 #, fuzzy msgid "Failed to connect to CORE service!\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:108 #, c-format msgid "Peer `%s' did not respond to request for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:143 #, fuzzy, c-format msgid "Starting inbound experiment `%s' with peer `%s'\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:276 #, fuzzy, c-format msgid "Starting outbound experiment `%s' with peer `%s'\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:294 #, fuzzy, c-format msgid "Received %s message from peer %s for experiment `%s'\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/fragmentation/defragmentation.c:270 msgid "# acknowledgements sent for fragment" msgstr "" #: src/fragmentation/defragmentation.c:456 #, fuzzy msgid "# fragments received" msgstr "# các mảnh bị loại bá»" #: src/fragmentation/defragmentation.c:521 #, fuzzy msgid "# duplicate fragments received" msgstr "# các kết quả dht được nhận" #: src/fragmentation/defragmentation.c:534 msgid "# messages defragmented" msgstr "# các thông báo được chắp liá»n" #: src/fragmentation/fragmentation.c:208 #, fuzzy msgid "# fragments transmitted" msgstr "# Các tá»± quảng cáo được truyá»n" #: src/fragmentation/fragmentation.c:211 #, fuzzy msgid "# fragments retransmitted" msgstr "# Các tá»± quảng cáo được truyá»n" #: src/fragmentation/fragmentation.c:237 #, fuzzy msgid "# fragments wrap arounds" msgstr "# Các tá»± quảng cáo được truyá»n" #: src/fragmentation/fragmentation.c:281 msgid "# messages fragmented" msgstr "# các thông báo bị tế phân" #: src/fragmentation/fragmentation.c:284 msgid "# total size of fragmented messages" msgstr "" #: src/fragmentation/fragmentation.c:405 #, fuzzy msgid "# fragment acknowledgements received" msgstr "# Các quảng cáo đồng đẳng được nhận" #: src/fragmentation/fragmentation.c:411 msgid "# bits removed from fragmentation ACKs" msgstr "" #: src/fragmentation/fragmentation.c:435 #, fuzzy msgid "# fragmentation transmissions completed" msgstr "# các sá»± truyá»n PONG bị lá»—i" #: src/fs/fs_api.c:465 #, fuzzy, c-format msgid "Could not open file `%s': %s" msgstr "Lá»—i mở tập tin theo dõi « %s »: %s\n" #: src/fs/fs_api.c:474 #, fuzzy, c-format msgid "Could not read file `%s': %s" msgstr "Lá»—i mở tập tin theo dõi « %s »: %s\n" #: src/fs/fs_api.c:480 #, c-format msgid "Short read reading from file `%s'!" msgstr "" #: src/fs/fs_api.c:1066 #, fuzzy, c-format msgid "Failed to resume publishing information `%s': %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_api.c:1571 #, c-format msgid "Failure while resuming publishing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:1585 #, fuzzy, c-format msgid "Failed to resume publishing operation `%s': %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_api.c:2242 #, c-format msgid "Failure while resuming unindexing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2252 #, fuzzy, c-format msgid "Failed to resume unindexing operation `%s': %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_api.c:2378 src/fs/fs_api.c:2619 #, fuzzy, c-format msgid "Failed to resume sub-download `%s': %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_api.c:2395 #, fuzzy, c-format msgid "Failed to resume sub-search `%s': %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_api.c:2409 src/fs/fs_api.c:2428 src/fs/fs_api.c:2911 #, c-format msgid "Failure while resuming search operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2610 #, c-format msgid "Failed to resume sub-download `%s': could not open file `%s'\n" msgstr "" #: src/fs/fs_api.c:2855 msgid "Could not resume running search, will resume as paused search\n" msgstr "" #: src/fs/fs_api.c:2949 #, c-format msgid "Failure while resuming download operation `%s': %s\n" msgstr "" #: src/fs/fs_directory.c:208 #, fuzzy msgid "MAGIC mismatch. This is not a GNUnet directory.\n" msgstr "Lá»—i định dạng tập tin (không phải là thư mục GNUnet ?)\n" #: src/fs/fs_download.c:322 msgid "" "Recursive downloads of directories larger than 4 GB are not supported on 32-" "bit systems\n" msgstr "" #: src/fs/fs_download.c:342 msgid "Directory too large for system address space\n" msgstr "" #: src/fs/fs_download.c:523 src/fs/fs_download.c:535 #, fuzzy, c-format msgid "Failed to open file `%s' for writing" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_download.c:905 #, fuzzy, c-format msgid "Failed to create directory for recursive download of `%s'\n" msgstr "Lá»—i cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #: src/fs/fs_download.c:987 #, c-format msgid "" "Internal error or bogus download URI (expected %u bytes at depth %u and " "offset %llu/%llu, got %u bytes)" msgstr "" #: src/fs/fs_download.c:1013 msgid "internal error decrypting content" msgstr "" #: src/fs/fs_download.c:1036 #, fuzzy, c-format msgid "Download failed: could not open file `%s': %s" msgstr "Lá»—i mở tập tin theo dõi « %s »: %s\n" #: src/fs/fs_download.c:1046 #, fuzzy, c-format msgid "Failed to seek to offset %llu in file `%s': %s" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_download.c:1055 #, fuzzy, c-format msgid "Failed to write block of %u bytes at offset %llu in file `%s': %s" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_download.c:1153 #, fuzzy msgid "internal error decoding tree" msgstr "=\tLá»—i Ä‘á»c thư mục.\n" #: src/fs/fs_download.c:1944 #, fuzzy msgid "Invalid URI" msgstr "Dữ liệu nhập không hợp lệ.\n" #: src/fs/fs_getopt.c:192 #, c-format msgid "" "Unknown metadata type in metadata option `%s'. Using metadata type " "`unknown' instead.\n" msgstr "" "Không rõ kiểu siêu dữ liệu trong tùy chá»n siêu dữ liệu « %s ». Äang ùng kiểu " "siêu dữ liệu « không rõ » (unknown) để thay thế.\n" #: src/fs/fs_list_indexed.c:90 #, fuzzy, c-format msgid "Failed to receive response for `%s' request from `%s' service.\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/fs/fs_list_indexed.c:113 #, fuzzy, c-format msgid "Failed to receive valid response for `%s' request from `%s' service.\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/fs/fs_list_indexed.c:151 #, fuzzy, c-format msgid "Failed to not connect to `%s' service.\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/fs/fs_misc.c:126 #, c-format msgid "Did not find mime type `%s' in extension list.\n" msgstr "" #: src/fs/fs_namespace.c:207 #, fuzzy, c-format msgid "Failed to open `%s' for writing: %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_namespace.c:229 #, fuzzy, c-format msgid "Failed to write `%s': %s\n" msgstr "Lá»—i chạy %s: %s %d\n" #: src/fs/fs_namespace.c:320 #, fuzzy, c-format msgid "Failed to read `%s': %s\n" msgstr "Lá»—i chạy %s: %s %d\n" #: src/fs/fs_namespace.c:466 #, fuzzy msgid "Failed to connect to datastore." msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/fs/fs_publish.c:125 src/fs/fs_publish.c:415 #, fuzzy, c-format msgid "Publishing failed: %s" msgstr "Gặp lá»—i khi tải lên tập tin: %s\n" #: src/fs/fs_publish.c:667 src/fs/fs_publish.c:684 src/fs/fs_publish.c:723 #: src/fs/fs_publish.c:744 src/fs/fs_publish.c:768 src/fs/fs_publish.c:914 #, fuzzy, c-format msgid "Can not index file `%s': %s. Will try to insert instead.\n" msgstr "Lá»—i đánh chỉ mục tập tin « %s ». Äá» nghị: thá»­ chèn tập tin.\n" #: src/fs/fs_publish.c:669 msgid "timeout on index-start request to `fs' service" msgstr "" #: src/fs/fs_publish.c:681 #, fuzzy msgid "unknown error" msgstr "Lá»—i không rõ" #: src/fs/fs_publish.c:725 msgid "failed to compute hash" msgstr "" #: src/fs/fs_publish.c:745 #, fuzzy msgid "filename too long" msgstr "tên tập tin" #: src/fs/fs_publish.c:770 msgid "could not connect to `fs' service" msgstr "" #: src/fs/fs_publish.c:793 #, fuzzy, c-format msgid "Failed to get file identifiers for `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/fs/fs_publish.c:862 #, fuzzy, c-format msgid "Recursive upload failed at `%s': %s" msgstr "%s bị lá»—i tại %s:%d: « %s »\n" #: src/fs/fs_publish.c:868 #, fuzzy, c-format msgid "Recursive upload failed: %s" msgstr "Gặp lá»—i khi tải lên tập tin: %s\n" #: src/fs/fs_publish.c:915 msgid "needs to be an actual file" msgstr "" #: src/fs/fs_publish.c:1151 #, fuzzy, c-format msgid "Insufficient space for publishing: %s" msgstr "Không đủ quyá»n truy cập cho « %s »: %s\n" #: src/fs/fs_publish.c:1243 #, c-format msgid "Reserving space for %u entries and %llu bytes for publication\n" msgstr "" #: src/fs/fs_publish_ksk.c:219 #, fuzzy msgid "Could not connect to datastore." msgstr "« %s »: Không thể kết nối.\n" #: src/fs/fs_publish_ublock.c:219 #, fuzzy msgid "Internal error." msgstr "Lá»—i VR." #: src/fs/fs_search.c:813 #, fuzzy, c-format msgid "Failed to parse URI `%s': %s\n" msgstr "Tập tin « %s » có URI: %s\n" #: src/fs/fs_search.c:872 #, c-format msgid "Got result with unknown block type `%d', ignoring" msgstr "" #: src/fs/fs_unindex.c:59 msgid "Failed to find given position in file" msgstr "" #: src/fs/fs_unindex.c:64 #, fuzzy msgid "Failed to read file" msgstr "Lá»—i gá»­i tin nhẳn.\n" #: src/fs/fs_unindex.c:234 msgid "Unexpected time for a response from `fs' service." msgstr "" #: src/fs/fs_unindex.c:242 msgid "Timeout waiting for `fs' service." msgstr "" #: src/fs/fs_unindex.c:250 #, fuzzy msgid "Invalid response from `fs' service." msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/fs/fs_unindex.c:291 #, fuzzy msgid "Failed to connect to FS service for unindexing." msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/fs/fs_unindex.c:347 src/fs/fs_unindex.c:359 #, fuzzy msgid "Failed to get KSKs from directory scan." msgstr "Lá»—i truy cập đến thư mục nhà GNUnet « %s »\n" #: src/fs/fs_unindex.c:355 #, fuzzy, c-format msgid "Internal error scanning `%s'.\n" msgstr "=\tLá»—i Ä‘á»c thư mục.\n" #: src/fs/fs_unindex.c:414 #, fuzzy, c-format msgid "Failed to remove UBlock: %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/fs_unindex.c:562 src/fs/fs_unindex.c:626 #, fuzzy msgid "Failed to connect to `datastore' service." msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/fs/fs_unindex.c:639 #, fuzzy msgid "Failed to open file for unindexing." msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/fs/fs_unindex.c:673 #, fuzzy msgid "Failed to compute hash of file." msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/fs/fs_uri.c:222 #, no-c-format msgid "`%' must be followed by HEX number" msgstr "" #: src/fs/fs_uri.c:281 msgid "Malformed KSK URI (must not begin or end with `+')" msgstr "" #: src/fs/fs_uri.c:299 msgid "`++' not allowed in KSK URI" msgstr "" #: src/fs/fs_uri.c:306 msgid "Quotes not balanced in KSK URI" msgstr "" #: src/fs/fs_uri.c:376 msgid "Malformed SKS URI" msgstr "" #: src/fs/fs_uri.c:419 src/fs/fs_uri.c:434 msgid "Malformed CHK URI" msgstr "" #: src/fs/fs_uri.c:512 src/fs/fs_uri.c:580 msgid "SKS URI malformed" msgstr "" #: src/fs/fs_uri.c:527 src/fs/fs_uri.c:537 msgid "LOC URI malformed" msgstr "" #: src/fs/fs_uri.c:545 src/fs/fs_uri.c:553 msgid "LOC URI malformed (could not decode public key)" msgstr "" #: src/fs/fs_uri.c:559 msgid "SKS URI malformed (could not find signature)" msgstr "" #: src/fs/fs_uri.c:565 src/fs/fs_uri.c:574 msgid "SKS URI malformed (could not decode signature)" msgstr "" #: src/fs/fs_uri.c:586 msgid "SKS URI malformed (could not parse expiration time)" msgstr "" #: src/fs/fs_uri.c:598 msgid "SKS URI malformed (signature failed validation)" msgstr "" #: src/fs/fs_uri.c:636 msgid "Unrecognized URI type" msgstr "" #: src/fs/fs_uri.c:860 #, fuzzy msgid "Lacking key configuration settings.\n" msgstr "Lưu cấu hình ngay bây giá» không?" #: src/fs/fs_uri.c:866 #, fuzzy, c-format msgid "Could not access hostkey file `%s'.\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/fs/fs_uri.c:1050 src/fs/fs_uri.c:1077 msgid "No keywords specified!\n" msgstr "Chưa ghi rõ từ khoá.\n" #: src/fs/fs_uri.c:1083 msgid "Number of double-quotes not balanced!\n" msgstr "Có dấu nháy kép thừa hay thiếu.\n" #: src/fs/gnunet-auto-share.c:236 #, fuzzy, c-format msgid "Failed to load state: %s\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/fs/gnunet-auto-share.c:289 src/fs/gnunet-auto-share.c:299 #: src/fs/gnunet-auto-share.c:309 #, fuzzy, c-format msgid "Failed to save state to file %s\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/fs/gnunet-auto-share.c:401 #, c-format msgid "Publication of `%s' done\n" msgstr "" #: src/fs/gnunet-auto-share.c:488 #, fuzzy, c-format msgid "Publishing `%s'\n" msgstr "Gặp lá»—i khi tải lên tập tin: %s\n" #: src/fs/gnunet-auto-share.c:497 #, fuzzy, c-format msgid "Failed to run `%s'\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/fs/gnunet-auto-share.c:686 #, fuzzy, c-format msgid "" "You must specify one and only one directory name for automatic publication.\n" msgstr "Phải ghi rõ chỉ má»™t tên tập tin để chèn.\n" #: src/fs/gnunet-auto-share.c:737 src/fs/gnunet-publish.c:824 msgid "set the desired LEVEL of sender-anonymity" msgstr "đặt CẤP mong muốn cá»§a tình trạng nặc danh cá»§a ngưá»i gá»­i" #: src/fs/gnunet-auto-share.c:741 src/fs/gnunet-publish.c:828 msgid "disable adding the creation time to the metadata of the uploaded file" msgstr "tắt thêm giá» tạo vào siêu dữ liệu cá»§a tập tin đã tải lên" #: src/fs/gnunet-auto-share.c:744 src/fs/gnunet-publish.c:831 msgid "do not use libextractor to add keywords or metadata" msgstr "" #: src/fs/gnunet-auto-share.c:747 src/fs/gnunet-publish.c:855 msgid "specify the priority of the content" msgstr "xác định mức ưu tiên cá»§a ná»™i dung" #: src/fs/gnunet-auto-share.c:750 src/fs/gnunet-publish.c:862 msgid "set the desired replication LEVEL" msgstr "" #: src/fs/gnunet-auto-share.c:770 #, fuzzy msgid "Automatically publish files from a directory on GNUnet" msgstr "Tá»± động chia sẻ má»™t thư mục." #: src/fs/gnunet-daemon-fsprofiler.c:660 msgid "Daemon to use file-sharing to measure its performance." msgstr "" #: src/fs/gnunet-directory.c:49 #, c-format msgid "\t\n" msgstr "" #: src/fs/gnunet-directory.c:94 #, fuzzy, c-format msgid "Directory `%s' meta data:\n" msgstr "==> Thư mục « %s »:\n" #: src/fs/gnunet-directory.c:97 #, fuzzy, c-format msgid "Directory `%s' contents:\n" msgstr "==> Thư mục « %s »:\n" #: src/fs/gnunet-directory.c:132 #, fuzzy msgid "You must specify a filename to inspect.\n" msgstr "Phải ghi rõ chỉ má»™t tên tập tin để chèn.\n" #: src/fs/gnunet-directory.c:145 #, fuzzy, c-format msgid "Failed to read directory `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/fs/gnunet-directory.c:154 #, fuzzy, c-format msgid "`%s' is not a GNUnet directory\n" msgstr "Lá»—i định dạng tập tin (không phải là thư mục GNUnet ?)\n" #: src/fs/gnunet-directory.c:183 #, fuzzy msgid "Display contents of a GNUnet directory" msgstr "Lá»—i định dạng tập tin (không phải là thư mục GNUnet ?)\n" #: src/fs/gnunet-download.c:137 #, fuzzy, c-format msgid "Starting download `%s'.\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/fs/gnunet-download.c:147 #, fuzzy msgid "" msgstr "Lá»—i không rõ" #: src/fs/gnunet-download.c:157 #, c-format msgid "" "Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to " "download\n" msgstr "" #: src/fs/gnunet-download.c:179 #, fuzzy, c-format msgid "Error downloading: %s.\n" msgstr "Gặp lá»—i khi tải xuống: %s\n" #: src/fs/gnunet-download.c:194 #, fuzzy, c-format msgid "Downloading `%s' done (%s/s).\n" msgstr "Tiến trình tải lên « %s » đã tiếp tục lại.\n" #: src/fs/gnunet-download.c:209 src/fs/gnunet-publish.c:286 #: src/fs/gnunet-search.c:200 src/fs/gnunet-unindex.c:108 #, fuzzy, c-format msgid "Unexpected status: %d\n" msgstr "Gặp sá»± kiện bất thưá»ng: %d\n" #: src/fs/gnunet-download.c:234 #, fuzzy msgid "You need to specify a URI argument.\n" msgstr "KHÔNG cho phép ghi rõ cả hai địa chỉ URI và tên tập tin.\n" #: src/fs/gnunet-download.c:240 src/fs/gnunet-publish.c:665 #, fuzzy, c-format msgid "Failed to parse URI: %s\n" msgstr "Tập tin « %s » có URI: %s\n" #: src/fs/gnunet-download.c:247 msgid "Only CHK or LOC URIs supported.\n" msgstr "" #: src/fs/gnunet-download.c:254 msgid "Target filename must be specified.\n" msgstr "" #: src/fs/gnunet-download.c:268 src/fs/gnunet-publish.c:797 #: src/fs/gnunet-search.c:250 src/fs/gnunet-unindex.c:140 #, fuzzy, c-format msgid "Could not initialize `%s' subsystem.\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/fs/gnunet-download.c:305 src/fs/gnunet-search.c:289 #, fuzzy msgid "set the desired LEVEL of receiver-anonymity" msgstr "đặt CẤP mong muốn cá»§a tình trạng nặc danh cá»§a ngưá»i gá»­i" #: src/fs/gnunet-download.c:308 msgid "delete incomplete downloads (when aborted with CTRL-C)" msgstr "xoá việc tải vá» không hoàn thành (khi há»§y bở dùng CTRL-C)" #: src/fs/gnunet-download.c:311 src/fs/gnunet-search.c:292 msgid "only search the local peer (no P2P network search)" msgstr "" #: src/fs/gnunet-download.c:314 msgid "write the file to FILENAME" msgstr "ghi tập tin vào TÊN_TẬP_TIN" #: src/fs/gnunet-download.c:318 #, fuzzy msgid "set the maximum number of parallel downloads that is allowed" msgstr "đặt số tối Ä‘a các việc tải xuống đồng thá»i được phép" #: src/fs/gnunet-download.c:322 #, fuzzy msgid "set the maximum number of parallel requests for blocks that is allowed" msgstr "đặt số tối Ä‘a các việc tải xuống đồng thá»i được phép" #: src/fs/gnunet-download.c:325 msgid "download a GNUnet directory recursively" msgstr "tải xuống đệ quy má»™t thư mục GNUnet" #: src/fs/gnunet-download.c:339 msgid "" "Download files from GNUnet using a GNUnet CHK or LOC URI (gnunet://fs/" "chk/...)" msgstr "" #: src/fs/gnunet-fs.c:117 msgid "print a list of all indexed files" msgstr "" #: src/fs/gnunet-fs.c:127 #, fuzzy msgid "Special file-sharing operations" msgstr "Tùy chá»n chia sẻ tập tin" #: src/fs/gnunet-fs-profiler.c:193 msgid "run the experiment with COUNT peers" msgstr "" #: src/fs/gnunet-fs-profiler.c:196 msgid "specifies name of a file with the HOSTS the testbed should use" msgstr "" #: src/fs/gnunet-fs-profiler.c:199 msgid "automatically terminate experiment after DELAY" msgstr "" #: src/fs/gnunet-fs-profiler.c:208 msgid "run a testbed to measure file-sharing performance" msgstr "" #: src/fs/gnunet-publish.c:231 src/fs/gnunet-publish.c:243 #, c-format msgid "Publishing `%s' at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-publish.c:250 #, fuzzy, c-format msgid "Error publishing: %s.\n" msgstr "Gặp lá»—i khi tải xuống: %s\n" #: src/fs/gnunet-publish.c:260 #, c-format msgid "Publishing `%s' done.\n" msgstr "" #: src/fs/gnunet-publish.c:264 #, fuzzy, c-format msgid "URI is `%s'.\n" msgstr "Tôi là đồng đẳng « %s ».\n" #: src/fs/gnunet-publish.c:283 #, fuzzy msgid "Cleanup after abort complete.\n" msgstr "Hoàn thành khởi chạy « %s ».\n" #: src/fs/gnunet-publish.c:401 #, fuzzy, c-format msgid "Meta data for file `%s' (%s)\n" msgstr "Äang cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #: src/fs/gnunet-publish.c:403 #, fuzzy, c-format msgid "Keywords for file `%s' (%s)\n" msgstr "Từ khoá cho tập tin « %s »:\n" #: src/fs/gnunet-publish.c:542 #, fuzzy msgid "Could not publish\n" msgstr "Không thể truy cập đến « %s »: %s\n" #: src/fs/gnunet-publish.c:565 #, fuzzy msgid "Could not start publishing.\n" msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #: src/fs/gnunet-publish.c:598 #, fuzzy, c-format msgid "Scanning directory `%s'.\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/fs/gnunet-publish.c:600 #, fuzzy, c-format msgid "Scanning file `%s'.\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/fs/gnunet-publish.c:605 #, c-format msgid "There was trouble processing file `%s', skipping it.\n" msgstr "" #: src/fs/gnunet-publish.c:610 msgid "Preprocessing complete.\n" msgstr "" #: src/fs/gnunet-publish.c:614 #, fuzzy, c-format msgid "Extracting meta data from file `%s' complete.\n" msgstr "Äang cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #: src/fs/gnunet-publish.c:618 msgid "Meta data extraction has finished.\n" msgstr "" #: src/fs/gnunet-publish.c:625 #, fuzzy msgid "Internal error scanning directory.\n" msgstr "=\tLá»—i Ä‘á»c thư mục.\n" #: src/fs/gnunet-publish.c:656 #, fuzzy, c-format msgid "Selected pseudonym `%s' unknown\n" msgstr "Không gian tên « %s » có đánh giá %d.\n" #: src/fs/gnunet-publish.c:682 #, fuzzy, c-format msgid "Failed to access `%s': %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/gnunet-publish.c:695 msgid "" "Failed to start meta directory scanner. Is gnunet-helper-publish-fs " "installed?\n" msgstr "" #: src/fs/gnunet-publish.c:747 #, c-format msgid "Cannot extract metadata from a URI!\n" msgstr "Không thể trích siêu dữ liệu ra má»™t địa chỉ URI.\n" #: src/fs/gnunet-publish.c:754 #, c-format msgid "You must specify one and only one filename for insertion.\n" msgstr "Phải ghi rõ chỉ má»™t tên tập tin để chèn.\n" #: src/fs/gnunet-publish.c:760 #, c-format msgid "You must NOT specify an URI and a filename.\n" msgstr "KHÔNG cho phép ghi rõ cả hai địa chỉ URI và tên tập tin.\n" #: src/fs/gnunet-publish.c:768 src/vpn/gnunet-vpn.c:209 #, c-format msgid "Option `%s' is required when using option `%s'.\n" msgstr "Tùy chá»n « %s » cần thiết khi dùng tùy chá»n « %s ».\n" #: src/fs/gnunet-publish.c:778 src/fs/gnunet-publish.c:785 #: src/transport/gnunet-transport.c:1284 src/transport/gnunet-transport.c:1314 #: src/transport/gnunet-transport.c:1344 #, c-format msgid "Option `%s' makes no sense without option `%s'.\n" msgstr "Tùy chá»n « %s » không có nghÄ©a khi không có tùy chá»n « %s ».\n" #: src/fs/gnunet-publish.c:835 msgid "" "print list of extracted keywords that would be used, but do not perform " "upload" msgstr "" "in ra danh sách các từ khóa đã giải phóng cần sá»­ dụng, nhưng không thá»±c hiện " "tải lên" #: src/fs/gnunet-publish.c:839 msgid "" "add an additional keyword for the top-level file or directory (this option " "can be specified multiple times)" msgstr "" "thêm má»™t từ khoá bổ sung cho tập tin hoặc thư mục ở cấp đầu (có thể chỉ ra " "tùy chá»n này nhiá»u lần)" #: src/fs/gnunet-publish.c:843 msgid "set the meta-data for the given TYPE to the given VALUE" msgstr "đặt siêu dữ liệu cho KIỂU đưa ra thành GIÃ_TRỊ chỉ ra" #: src/fs/gnunet-publish.c:846 msgid "" "do not index, perform full insertion (stores entire file in encrypted form " "in GNUnet database)" msgstr "" "không đánh chỉ mục, thá»±c hiện việc chèn đầy đủ (chứa toàn bá»™ tập tin ở dạng " "mã hóa trong cÆ¡ sở dữ liệu GNUnet)" #: src/fs/gnunet-publish.c:851 msgid "" "specify ID of an updated version to be published in the future (for " "namespace insertions only)" msgstr "" "chỉ ra mã số cá»§a má»™t phiên bản đã cập nhật để công bố trong tương lai (chỉ " "cho sá»± chèn không gian tên)" #: src/fs/gnunet-publish.c:859 msgid "publish the files under the pseudonym NAME (place file into namespace)" msgstr "" "công bố các tập tin dưới biệt hiệu TÊN (đặt tập tin vào không gian tên)" #: src/fs/gnunet-publish.c:865 #, fuzzy msgid "" "only simulate the process but do not do any actual publishing (useful to " "compute URIs)" msgstr "" "chỉ mô phá»ng tiến trình, không thật công bố (có ích để tính địa chỉ URI)" #: src/fs/gnunet-publish.c:869 msgid "" "set the ID of this version of the publication (for namespace insertions only)" msgstr "" "đặt mã số cá»§a phiên bản này cá»§a sá»± công bố (chỉ cho chèn không gian tên)" #: src/fs/gnunet-publish.c:873 msgid "" "URI to be published (can be used instead of passing a file to add keywords " "to the file with the respective URI)" msgstr "" "Äịa chỉ URI cần công bố (có thể được dùng thay vào gá»­i má»™t tập tin để thêm " "từ khoá vào tập tin có địa chỉ URI tương ứng)" #: src/fs/gnunet-publish.c:889 msgid "Publish a file or directory on GNUnet" msgstr "" #: src/fs/gnunet-search.c:114 #, c-format msgid "Failed to write directory with search results to `%s'\n" msgstr "" #: src/fs/gnunet-search.c:191 #, fuzzy, c-format msgid "Error searching: %s.\n" msgstr "Gặp lá»—i khi tải xuống: %s\n" #: src/fs/gnunet-search.c:240 #, fuzzy msgid "Could not create keyword URI from arguments.\n" msgstr "Không thể tạo miá»n tên.\n" #: src/fs/gnunet-search.c:264 #, fuzzy msgid "Could not start searching.\n" msgstr "Không thể tạo miá»n tên.\n" #: src/fs/gnunet-search.c:295 msgid "write search results to file starting with PREFIX" msgstr "" #: src/fs/gnunet-search.c:298 msgid "automatically terminate search after DELAY" msgstr "" #: src/fs/gnunet-search.c:305 msgid "automatically terminate search after VALUE results are found" msgstr "" #: src/fs/gnunet-search.c:316 #, fuzzy msgid "Search GNUnet for files that were published on GNUnet" msgstr "Không hiển thị kết quả tìm kiếm cho tập tin được chúng ta tải lên" #: src/fs/gnunet-service-fs.c:271 msgid "# running average P2P latency (ms)" msgstr "" #: src/fs/gnunet-service-fs.c:326 src/fs/gnunet-service-fs.c:539 #, fuzzy msgid "# Loopback routes suppressed" msgstr "# tổng số định tuyến lá»— hổng thành công" #: src/fs/gnunet-service-fs.c:639 src/hostlist/gnunet-daemon-hostlist.c:288 #: src/topology/gnunet-daemon-topology.c:1254 #: src/topology/gnunet-daemon-topology.c:1261 #, fuzzy, c-format msgid "Failed to connect to `%s' service.\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/fs/gnunet-service-fs_cp.c:682 #, fuzzy msgid "# migration stop messages received" msgstr "# các thông báo phát hiện dht được nhận" #: src/fs/gnunet-service-fs_cp.c:686 #, c-format msgid "Migration of content to peer `%s' blocked for %s\n" msgstr "" #: src/fs/gnunet-service-fs_cp.c:721 #, fuzzy msgid "# replies transmitted to other peers" msgstr "# các byte kiểu %d được gá»­i " #: src/fs/gnunet-service-fs_cp.c:727 #, fuzzy msgid "# replies dropped" msgstr "# các đáp ứng dht được định tuyến" #: src/fs/gnunet-service-fs_cp.c:752 src/fs/gnunet-service-fs_cp.c:1301 msgid "# P2P searches active" msgstr "" #: src/fs/gnunet-service-fs_cp.c:845 msgid "# artificial delays introduced (ms)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:898 #, fuzzy msgid "# replies dropped due to type mismatch" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/fs/gnunet-service-fs_cp.c:906 #, fuzzy msgid "# replies received for other peers" msgstr "# các byte kiểu %d được nhận" #: src/fs/gnunet-service-fs_cp.c:920 msgid "# replies dropped due to insufficient cover traffic" msgstr "" #: src/fs/gnunet-service-fs_cp.c:958 msgid "# P2P searches destroyed due to ultimate reply" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1026 #, fuzzy msgid "# requests done for free (low load)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/fs/gnunet-service-fs_cp.c:1051 msgid "# request dropped, priority insufficient" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1061 #, fuzzy msgid "# requests done for a price (normal load)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/fs/gnunet-service-fs_cp.c:1139 msgid "# GET requests received (from other peers)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1173 #, fuzzy msgid "# requests dropped due to initiator not being connected" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/fs/gnunet-service-fs_cp.c:1195 #, fuzzy msgid "# requests dropped due to missing reverse route" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/fs/gnunet-service-fs_cp.c:1246 #, fuzzy msgid "# requests dropped due TTL underflow" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/fs/gnunet-service-fs_cp.c:1270 #, fuzzy msgid "# requests dropped due to higher-TTL request" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/fs/gnunet-service-fs_cp.c:1299 #, fuzzy msgid "# P2P query messages received and processed" msgstr "# các thông báo phát hiện dht được nhận" #: src/fs/gnunet-service-fs_cp.c:1670 #, fuzzy msgid "# migration stop messages sent" msgstr "# các thông báo phát hiện dht được nhận" #: src/fs/gnunet-service-fs_indexing.c:130 #: src/fs/gnunet-service-fs_indexing.c:181 #, fuzzy, c-format msgid "Could not open `%s'.\n" msgstr "Lá»—i mở tập tin theo dõi « %s »: %s\n" #: src/fs/gnunet-service-fs_indexing.c:142 #, fuzzy, c-format msgid "Error writing `%s'.\n" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/fs/gnunet-service-fs_indexing.c:237 #, c-format msgid "" "Index request received for file `%s' is already indexed as `%s'. Permitting " "anyway.\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:275 #, c-format msgid "Hash mismatch trying to index file `%s' which has hash `%s'\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:477 #, fuzzy, c-format msgid "Failed to delete bogus block: %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/fs/gnunet-service-fs_indexing.c:542 msgid "# index blocks removed: original file inaccessible" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:557 #, fuzzy, c-format msgid "Could not access indexed file `%s' (%s) at offset %llu: %s\n" msgstr "Không thể giải quyết « %s » (%s): %s\n" #: src/fs/gnunet-service-fs_indexing.c:559 msgid "not indexed" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:574 #, fuzzy, c-format msgid "Indexed file `%s' changed at offset %llu\n" msgstr "Äánh chỉ mục dữ liệu cá»§a tập tin « %s » bị lá»—i tại vị tri %llu.\n" #: src/fs/gnunet-service-fs_lc.c:202 src/fs/gnunet-service-fs_lc.c:368 #, fuzzy msgid "# client searches active" msgstr "# các yêu cầu khách lá»— hổng được nhận" #: src/fs/gnunet-service-fs_lc.c:256 #, fuzzy msgid "# replies received for local clients" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/fs/gnunet-service-fs_lc.c:327 #, fuzzy msgid "# client searches received" msgstr "# các yêu cầu khách lá»— hổng được nhận" #: src/fs/gnunet-service-fs_lc.c:362 msgid "# client searches updated (merged content seen list)" msgstr "" #: src/fs/gnunet-service-fs_mesh_client.c:484 #, fuzzy msgid "# replies received via mesh" msgstr "# các byte kiểu %d được nhận" #: src/fs/gnunet-service-fs_mesh_client.c:498 #, fuzzy msgid "# replies received via mesh dropped" msgstr "# các byte kiểu %d được nhận" #: src/fs/gnunet-service-fs_mesh_server.c:260 #, fuzzy msgid "# Blocks transferred via mesh" msgstr "# các byte được gá»­i" #: src/fs/gnunet-service-fs_mesh_server.c:352 #, fuzzy msgid "# queries received via mesh not answered" msgstr "# các byte đã nhận qua TCP" #: src/fs/gnunet-service-fs_mesh_server.c:432 #, fuzzy msgid "# queries received via mesh" msgstr "# các byte đã nhận qua TCP" #: src/fs/gnunet-service-fs_mesh_server.c:476 #, fuzzy msgid "# mesh client connections rejected" msgstr "# các kết nối dht" #: src/fs/gnunet-service-fs_mesh_server.c:482 #: src/fs/gnunet-service-fs_mesh_server.c:522 #, fuzzy msgid "# mesh connections active" msgstr "# các kết nối dht" #: src/fs/gnunet-service-fs_pe.c:269 #, fuzzy msgid "# average retransmission delay (ms)" msgstr "# thá»i gian trung bình còn kết nối (theo miligiây)" #: src/fs/gnunet-service-fs_pe.c:400 #, fuzzy msgid "# transmission failed (core has no bandwidth)" msgstr "Lá»—i thá»­ gá»­i, kiểu truyá»n tải %d không được há»— trợ\n" #: src/fs/gnunet-service-fs_pe.c:433 #, fuzzy msgid "# query messages sent to other peers" msgstr "# các byte thông báo gá»­i Ä‘i bị loại bá»" #: src/fs/gnunet-service-fs_pe.c:484 msgid "# delay heap timeout (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:492 #, fuzzy msgid "# query plans executed" msgstr "# các yêu cầu dht được định tuyến" #: src/fs/gnunet-service-fs_pe.c:552 #, fuzzy msgid "# requests merged" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/fs/gnunet-service-fs_pe.c:560 #, fuzzy msgid "# requests refreshed" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/fs/gnunet-service-fs_pe.c:616 src/fs/gnunet-service-fs_pe.c:700 #: src/fs/gnunet-service-fs_pe.c:771 msgid "# query plan entries" msgstr "" #: src/fs/gnunet-service-fs_pr.c:311 #, fuzzy msgid "# Pending requests created" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/fs/gnunet-service-fs_pr.c:394 src/fs/gnunet-service-fs_pr.c:645 #, fuzzy msgid "# Pending requests active" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/fs/gnunet-service-fs_pr.c:814 #, fuzzy msgid "# replies received and matched" msgstr "# các byte kiểu %d được nhận" #: src/fs/gnunet-service-fs_pr.c:844 msgid "# duplicate replies discarded (bloomfilter)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:853 msgid "# irrelevant replies discarded" msgstr "" #: src/fs/gnunet-service-fs_pr.c:867 #, c-format msgid "Unsupported block type %u\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:880 #, fuzzy msgid "# results found locally" msgstr "# ná»™i dung lá»— hổng được tìm cục bá»™" #: src/fs/gnunet-service-fs_pr.c:1001 msgid "# Datastore `PUT' failures" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1029 #, fuzzy msgid "# storage requests dropped due to high load" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/fs/gnunet-service-fs_pr.c:1064 #, fuzzy msgid "# Replies received from DHT" msgstr "# các byte đã nhận qua HTTP" #: src/fs/gnunet-service-fs_pr.c:1192 #, fuzzy msgid "# Replies received from MESH" msgstr "# các byte đã nhận qua HTTP" #: src/fs/gnunet-service-fs_pr.c:1244 #, c-format msgid "Datastore lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1264 #, c-format msgid "On-demand lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1311 msgid "# Datastore lookups concluded (no results)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1326 msgid "# Datastore lookups concluded (seen all)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1335 msgid "# Datastore lookups aborted (more than MAX_RESULTS)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1350 msgid "# requested DBLOCK or IBLOCK not found" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1364 msgid "# on-demand blocks matched requests" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1377 msgid "# on-demand lookups performed successfully" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1382 msgid "# on-demand lookups failed" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1409 src/fs/gnunet-service-fs_pr.c:1449 #: src/fs/gnunet-service-fs_pr.c:1590 msgid "# Datastore lookups concluded (error queueing)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1467 msgid "# Datastore lookups concluded (found last result)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1478 msgid "# Datastore lookups concluded (load too high)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1566 msgid "# Datastore lookups initiated" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1651 #, fuzzy msgid "# GAP PUT messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/fs/gnunet-service-fs_push.c:631 msgid "time required, content pushing disabled" msgstr "" #: src/fs/gnunet-unindex.c:89 #, fuzzy, c-format msgid "Unindexing at %llu/%llu (%s remaining)\n" msgstr "Lá»—i bá» chỉ mục (không đưa ra lý do)." #: src/fs/gnunet-unindex.c:95 #, fuzzy, c-format msgid "Error unindexing: %s.\n" msgstr "" "\n" "Gặp lá»—i khi bá» chỉ mục tập tin: %s\n" #: src/fs/gnunet-unindex.c:100 #, fuzzy msgid "Unindexing done.\n" msgstr "Bá» chỉ mục tập tin." #: src/fs/gnunet-unindex.c:130 #, fuzzy, c-format msgid "You must specify one and only one filename for unindexing.\n" msgstr "Phải ghi rõ chỉ má»™t tên tập tin để chèn.\n" #: src/fs/gnunet-unindex.c:147 #, fuzzy msgid "Could not start unindex operation.\n" msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #: src/fs/gnunet-unindex.c:179 msgid "Unindex a file that was previously indexed with gnunet-publish." msgstr "" #: src/gns/gns_api.c:393 #, fuzzy msgid "Failed to deserialize lookup reply from GNS service!\n" msgstr "" "\n" "Không nhận được đáp ứng từ gnunetd.\n" #: src/gns/gnunet-bcd.c:123 #, fuzzy, c-format msgid "Refusing `%s' request to HTTP server\n" msgstr "trình phục vụ danh sách máy HTTP hợp nhất" #: src/gns/gnunet-bcd.c:355 src/hostlist/hostlist-server.c:567 #, c-format msgid "Invalid port number %llu. Exiting.\n" msgstr "" #: src/gns/gnunet-bcd.c:360 #, c-format msgid "Businesscard HTTP server starts on %llu\n" msgstr "" #: src/gns/gnunet-bcd.c:374 #, fuzzy, c-format msgid "Could not start businesscard HTTP server on port %u\n" msgstr "Cổng cho trình phục vụ HTTP danh sách máy chá»§ thống nhất" #: src/gns/gnunet-bcd.c:519 msgid "Run HTTP serve on port PORT (default is 8888)" msgstr "" #: src/gns/gnunet-bcd.c:531 msgid "GNUnet HTTP server to create business cards" msgstr "" #: src/gns/gnunet-dns2gns.c:228 #, fuzzy msgid "Failed to pack DNS response into UDP packet!\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/gns/gnunet-dns2gns.c:400 #, c-format msgid "Cannot parse DNS request from %s\n" msgstr "" #: src/gns/gnunet-dns2gns.c:416 #, fuzzy, c-format msgid "Received malformed DNS request from %s\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/gns/gnunet-dns2gns.c:424 #, fuzzy, c-format msgid "Received unsupported DNS request from %s\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/gns/gnunet-dns2gns.c:701 msgid "No ego configured for `dns2gns` subsystem\n" msgstr "" #: src/gns/gnunet-dns2gns.c:727 #, fuzzy msgid "No DNS server specified!\n" msgstr "Chưa ghi rõ từ khoá.\n" #: src/gns/gnunet-dns2gns.c:749 #, fuzzy msgid "No valid GNS zone specified!\n" msgstr "Chưa ghi rõ từ khoá.\n" #: src/gns/gnunet-dns2gns.c:770 msgid "IP of recursive DNS resolver to use (required)" msgstr "" #: src/gns/gnunet-dns2gns.c:773 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:776 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:779 msgid "UDP port to listen on for inbound DNS requests; default: 53" msgstr "" #: src/gns/gnunet-dns2gns.c:782 msgid "Public key of the GNS zone to use (overrides default)" msgstr "" #: src/gns/gnunet-dns2gns.c:795 msgid "GNUnet DNS-to-GNS proxy (a DNS server)" msgstr "" #: src/gns/gnunet-gns.c:227 #, c-format msgid "Please specify name to lookup!\n" msgstr "" #: src/gns/gnunet-gns.c:308 #, c-format msgid "Ego for `%s' not found, cannot perform lookup.\n" msgstr "" #: src/gns/gnunet-gns.c:347 src/gns/gnunet-gns-helper-service-w32.c:798 #, c-format msgid "" "Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-" "gns-import.sh?\n" msgstr "" #: src/gns/gnunet-gns.c:386 src/gns/gnunet-gns-helper-service-w32.c:828 #, fuzzy, c-format msgid "Failed to connect to GNS\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/gns/gnunet-gns.c:399 #, c-format msgid "Public key `%s' is not well-formed\n" msgstr "" #: src/gns/gnunet-gns.c:449 msgid "Lookup a record for the given name" msgstr "" #: src/gns/gnunet-gns.c:452 #, fuzzy msgid "Specify the type of the record to lookup" msgstr "xác định mức ưu tiên cá»§a ná»™i dung" #: src/gns/gnunet-gns.c:455 #, fuzzy msgid "Specify timeout for the lookup" msgstr "xác định mức ưu tiên cá»§a ná»™i dung" #: src/gns/gnunet-gns.c:458 msgid "No unneeded output" msgstr "" #: src/gns/gnunet-gns.c:461 #, fuzzy msgid "Specify the public key of the zone to lookup the record in" msgstr "xác định mức ưu tiên cá»§a ná»™i dung" #: src/gns/gnunet-gns.c:464 #, fuzzy msgid "Specify the name of the ego of the zone to lookup the record in" msgstr "xác định mức ưu tiên cá»§a ná»™i dung" #: src/gns/gnunet-gns.c:478 #, fuzzy msgid "GNUnet GNS resolver tool" msgstr "Bản ghi lá»—i GNUnet" #: src/gns/gnunet-gns-helper-service-w32.c:768 #, c-format msgid "" "Ego for `gns-short' not found. This is not really fatal, but i'll pretend " "that it is and refuse to perform a lookup. Did you run gnunet-gns-import." "sh?\n" msgstr "" #: src/gns/gnunet-gns-helper-service-w32.c:838 #, fuzzy, c-format msgid "Failed to connect to identity service\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/gns/gnunet-gns-import.c:479 msgid "This program will import some GNS authorities into your GNS namestore." msgstr "" #: src/gns/gnunet-gns-proxy.c:105 src/hostlist/hostlist-client.c:469 #: src/hostlist/hostlist-client.c:683 src/hostlist/hostlist-client.c:689 #: src/hostlist/hostlist-client.c:741 src/hostlist/hostlist-client.c:750 #: src/hostlist/hostlist-client.c:871 src/hostlist/hostlist-client.c:963 #: src/hostlist/hostlist-client.c:968 #: src/transport/plugin_transport_http_client.c:1062 #: src/transport/plugin_transport_http_client.c:1077 #, c-format msgid "%s failed at %s:%d: `%s'\n" msgstr "%s bị lá»—i tại %s:%d: « %s »\n" #: src/gns/gnunet-gns-proxy.c:833 #, fuzzy, c-format msgid "Unsupported CURL SSL backend %d\n" msgstr "Lệnh không được há»— trợ « %s ». Äang há»§y bá».\n" #: src/gns/gnunet-gns-proxy.c:856 #, fuzzy, c-format msgid "Failed to fetch CN from cert: %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/gns/gnunet-gns-proxy.c:879 #, fuzzy, c-format msgid "Failed to initialize DANE: %s\n" msgstr "Không thể sÆ¡ khởi SQLite: %s.\n" #: src/gns/gnunet-gns-proxy.c:892 #, fuzzy, c-format msgid "Failed to parse DANE record: %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/gns/gnunet-gns-proxy.c:907 #, fuzzy, c-format msgid "Failed to verify TLS connection using DANE: %s\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/gns/gnunet-gns-proxy.c:917 #, c-format msgid "Failed DANE verification failed with GnuTLS verify status code: %u\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:941 #, c-format msgid "SSL certificate subject name (%s) does not match `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1086 #, c-format msgid "Cookie domain `%s' supplied by server is invalid\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1602 #, fuzzy, c-format msgid "Unsupported HTTP method `%s'\n" msgstr "Lệnh không được há»— trợ « %s ». Äang há»§y bá».\n" #: src/gns/gnunet-gns-proxy.c:1973 #, fuzzy, c-format msgid "Unable to import private key from file `%s'\n" msgstr "Không thể tạo tài khoản ngưá»i dùng:" #: src/gns/gnunet-gns-proxy.c:2003 #, fuzzy, c-format msgid "Unable to import certificate %s\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/gns/gnunet-gns-proxy.c:2177 #, fuzzy, c-format msgid "Failed to start HTTPS server for `%s'\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/gns/gnunet-gns-proxy.c:2196 #, fuzzy msgid "Failed to pass client to MHD\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/gns/gnunet-gns-proxy.c:2504 #, fuzzy, c-format msgid "Unsupported socks version %d\n" msgstr "Lệnh không được há»— trợ « %s ». Äang há»§y bá».\n" #: src/gns/gnunet-gns-proxy.c:2533 #, fuzzy, c-format msgid "Unsupported socks command %d\n" msgstr "Lệnh không được há»— trợ « %s ». Äang há»§y bá».\n" #: src/gns/gnunet-gns-proxy.c:2551 src/gns/gnunet-gns-proxy.c:2580 msgid "SSL connection to plain IPv4 address requested\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2631 #, fuzzy, c-format msgid "Unsupported socks address type %d\n" msgstr "Lệnh không được há»— trợ « %s ». Äang há»§y bá».\n" #: src/gns/gnunet-gns-proxy.c:2970 msgid "No ego configured for `shorten-zone`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3010 #, c-format msgid "No ego configured for `%s`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3072 #, fuzzy, c-format msgid "Failed to load SSL/TLS key and certificate from `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/gns/gnunet-gns-proxy.c:3113 msgid "listen on specified port (default: 7777)" msgstr "" #: src/gns/gnunet-gns-proxy.c:3116 msgid "pem file to use as CA" msgstr "" #: src/gns/gnunet-gns-proxy.c:3135 msgid "GNUnet GNS proxy" msgstr "" #: src/gns/gnunet-service-gns.c:862 #, fuzzy msgid "Failed to connect to the namestore!\n" msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/gns/gnunet-service-gns.c:870 #, fuzzy msgid "Failed to connect to the namecache!\n" msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/gns/gnunet-service-gns.c:903 #, fuzzy msgid "Could not connect to DHT!\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/gns/gnunet-service-gns.c:919 #, fuzzy msgid "valid public key required" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/gns/gnunet-service-gns_interceptor.c:263 #, fuzzy msgid "Error converting GNS response to DNS response!\n" msgstr "Gặp lá»—i khi chuyển đổi các đối số sang URI.\n" #: src/gns/gnunet-service-gns_interceptor.c:369 #, fuzzy msgid "Failed to connect to the DNS service!\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/gns/gnunet-service-gns_resolver.c:816 #, fuzzy msgid "Failed to parse DNS response\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/gns/gnunet-service-gns_resolver.c:958 #, c-format msgid "Skipping record of unsupported type %d\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1317 #, c-format msgid "GNS lookup resulted in DNS name that is too long (`%s')\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1817 msgid "GNS lookup recursion failed (no delegation record found)\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1841 #, fuzzy, c-format msgid "Failed to cache GNS resolution: %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/gns/gnunet-service-gns_resolver.c:2123 #, c-format msgid "Zone %s was revoked, resolution fails\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:2272 #, c-format msgid "Hostname `%s' is not well-formed, resolution fails\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:151 #, fuzzy, c-format msgid "Unable to parse PKEY record `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/gns/plugin_gnsrecord_gns.c:180 #, fuzzy, c-format msgid "Unable to parse GNS2DNS record `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/gns/plugin_gnsrecord_gns.c:201 #, fuzzy, c-format msgid "Failed to serialize GNS2DNS record with value `%s'\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/gns/plugin_gnsrecord_gns.c:217 #, fuzzy, c-format msgid "Unable to parse VPN record string `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:293 #, fuzzy, c-format msgid "Unable to parse IPv4 address `%s'\n" msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:314 #, fuzzy, c-format msgid "Failed to serialize NS record with value `%s'\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:336 #, fuzzy, c-format msgid "Failed to serialize CNAME record with value `%s'\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:420 #, fuzzy, c-format msgid "Failed to serialize CERT record with %u bytes\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:452 #, fuzzy, c-format msgid "Unable to parse SOA record `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:471 #, fuzzy, c-format msgid "Failed to serialize SOA record with mname `%s' and rname `%s'\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:494 #, fuzzy, c-format msgid "Failed to serialize PTR record with value `%s'\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:514 #, fuzzy, c-format msgid "Unable to parse MX record `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:529 #, fuzzy, c-format msgid "Failed to serialize MX record with hostname `%s'\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:549 #, fuzzy, c-format msgid "Unable to parse IPv6 address `%s'\n" msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:567 #, fuzzy, c-format msgid "Unable to parse TLSA record string `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/hello/gnunet-hello.c:123 msgid "Call with name of HELLO file to modify.\n" msgstr "" #: src/hello/gnunet-hello.c:129 #, fuzzy, c-format msgid "Error accessing file `%s': %s\n" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/hello/gnunet-hello.c:137 #, c-format msgid "File `%s' is too big to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:144 #, c-format msgid "File `%s' is too small to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:154 src/hello/gnunet-hello.c:183 #, fuzzy, c-format msgid "Error opening file `%s': %s\n" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/hello/gnunet-hello.c:170 #, fuzzy, c-format msgid "Did not find well-formed HELLO in file `%s'\n" msgstr "Không tìm thấy tập tin nào trong thư mục « %s »\n" #: src/hello/gnunet-hello.c:195 #, fuzzy, c-format msgid "Error writing HELLO to file `%s': %s\n" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/hello/gnunet-hello.c:203 #, c-format msgid "Modified %u addresses \n" msgstr "" #: src/hello/hello.c:944 #, fuzzy msgid "Failed to parse HELLO message: missing expiration time\n" msgstr "Lá»—i lưu cấu hình." #: src/hello/hello.c:953 #, fuzzy msgid "Failed to parse HELLO message: invalid expiration time\n" msgstr "Lá»—i lưu cấu hình." #: src/hello/hello.c:963 #, fuzzy msgid "Failed to parse HELLO message: malformed\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/hello/hello.c:973 #, fuzzy msgid "Failed to parse HELLO message: missing transport plugin\n" msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #: src/hello/hello.c:990 #, c-format msgid "Plugin `%s' not found\n" msgstr "" #: src/hello/hello.c:999 #, c-format msgid "Plugin `%s' does not support URIs yet\n" msgstr "" #: src/hello/hello.c:1018 #, fuzzy, c-format msgid "Failed to parse `%s' as an address for plugin `%s'\n" msgstr "Lá»—i đóng kết đến cổng %s %d.\n" #: src/hostlist/gnunet-daemon-hostlist.c:259 msgid "" "None of the functions for the hostlist daemon were enabled. I have no " "reason to run!\n" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:308 #, fuzzy msgid "advertise our hostlist to other peers" msgstr "Tắt quảng cáo máy này cho đồng đẳng khác" #: src/hostlist/gnunet-daemon-hostlist.c:313 msgid "" "bootstrap using hostlists (it is highly recommended that you always use this " "option)" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:316 #, fuzzy msgid "enable learning about hostlist servers from other peers" msgstr "Tắt quảng cáo máy này cho đồng đẳng khác" #: src/hostlist/gnunet-daemon-hostlist.c:320 #, fuzzy msgid "provide a hostlist server" msgstr "trình phục vụ danh sách máy HTTP hợp nhất" #: src/hostlist/gnunet-daemon-hostlist.c:335 msgid "GNUnet hostlist server and client" msgstr "" #: src/hostlist/hostlist-client.c:288 #, fuzzy msgid "# bytes downloaded from hostlist servers" msgstr "trình phục vụ danh sách máy HTTP hợp nhất" #: src/hostlist/hostlist-client.c:309 src/hostlist/hostlist-client.c:339 #, fuzzy msgid "# invalid HELLOs downloaded from hostlist servers" msgstr "# các HELLO tải xuống qua HTTP" #: src/hostlist/hostlist-client.c:312 src/hostlist/hostlist-client.c:342 #, fuzzy, c-format msgid "Invalid `%s' message received from hostlist at `%s'\n" msgstr "Nhận được thông báo « %s » sai từ đồng đẳng « %s ».\n" #: src/hostlist/hostlist-client.c:330 #, fuzzy msgid "# valid HELLOs downloaded from hostlist servers" msgstr "# các HELLO tải xuống qua HTTP" #: src/hostlist/hostlist-client.c:592 src/hostlist/hostlist-client.c:1333 msgid "# advertised hostlist URIs" msgstr "" #: src/hostlist/hostlist-client.c:622 #, c-format msgid "# advertised URI `%s' downloaded" msgstr "" #: src/hostlist/hostlist-client.c:664 #, c-format msgid "" "Advertised hostlist with URI `%s' could not be downloaded. Advertised URI " "gets dismissed.\n" msgstr "" #: src/hostlist/hostlist-client.c:802 #, fuzzy, c-format msgid "Timeout trying to download hostlist from `%s'\n" msgstr "Äang thá»­ tải danh sách các máy xuống « %s »\n" #: src/hostlist/hostlist-client.c:816 #, c-format msgid "Download limit of %u bytes exceeded, stopping download\n" msgstr "" #: src/hostlist/hostlist-client.c:836 #, fuzzy, c-format msgid "Download of hostlist from `%s' failed: `%s'\n" msgstr "Tải lên « %s » hoàn thành, địa chỉ URI là « %s ».\n" #: src/hostlist/hostlist-client.c:842 #, fuzzy, c-format msgid "Download of hostlist `%s' completed.\n" msgstr "Tải lên « %s » hoàn thành, địa chỉ URI là « %s ».\n" #: src/hostlist/hostlist-client.c:850 #, c-format msgid "Adding successfully tested hostlist `%s' datastore.\n" msgstr "" #: src/hostlist/hostlist-client.c:903 #, fuzzy, c-format msgid "Bootstrapping using hostlist at `%s'.\n" msgstr "Äang nạp và khởi động dùng « %s ».\n" #: src/hostlist/hostlist-client.c:911 msgid "# hostlist downloads initiated" msgstr "" #: src/hostlist/hostlist-client.c:1040 src/hostlist/hostlist-client.c:1506 msgid "# milliseconds between hostlist downloads" msgstr "" #: src/hostlist/hostlist-client.c:1049 #, c-format msgid "Have %u/%u connections. Will consider downloading hostlist in %s\n" msgstr "" #: src/hostlist/hostlist-client.c:1109 src/hostlist/hostlist-client.c:1125 #, fuzzy msgid "# active connections" msgstr "# các kết nối dht" #: src/hostlist/hostlist-client.c:1280 #, fuzzy, c-format msgid "Loading saved hostlist entries from file `%s' \n" msgstr "Äang thá»­ tải danh sách các máy xuống « %s »\n" #: src/hostlist/hostlist-client.c:1285 #, fuzzy, c-format msgid "Hostlist file `%s' does not exist\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/hostlist/hostlist-client.c:1296 #, fuzzy, c-format msgid "Could not open file `%s' for reading to load hostlists: %s\n" msgstr "Lá»—i mở tập tin theo dõi « %s »: %s\n" #: src/hostlist/hostlist-client.c:1329 #, c-format msgid "%u hostlist URIs loaded from file\n" msgstr "" #: src/hostlist/hostlist-client.c:1331 #, fuzzy msgid "# hostlist URIs read from file" msgstr "# các byte danh sách máy được trả vá»" #: src/hostlist/hostlist-client.c:1376 #, fuzzy, c-format msgid "Could not open file `%s' for writing to save hostlists: %s\n" msgstr "Lá»—i mở tập tin theo dõi « %s »: %s\n" #: src/hostlist/hostlist-client.c:1381 #, fuzzy, c-format msgid "Writing %u hostlist URIs to `%s'\n" msgstr "Äang thá»­ tải danh sách các máy xuống « %s »\n" #: src/hostlist/hostlist-client.c:1405 src/hostlist/hostlist-client.c:1422 #, c-format msgid "Error writing hostlist URIs to file `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:1417 #, fuzzy msgid "# hostlist URIs written to file" msgstr "# các byte danh sách máy được trả vá»" #: src/hostlist/hostlist-client.c:1471 msgid "Learning is enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1483 msgid "Learning is not enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1495 #, c-format msgid "" "Since learning is not enabled on this peer, hostlist file `%s' was removed\n" msgstr "" #: src/hostlist/hostlist-client.c:1499 #, fuzzy, c-format msgid "Hostlist file `%s' could not be removed\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/hostlist/hostlist-server.c:137 #, fuzzy msgid "bytes in hostlist" msgstr "# các byte trong kho dữ liệu" #: src/hostlist/hostlist-server.c:161 msgid "expired addresses encountered" msgstr "" #: src/hostlist/hostlist-server.c:189 src/hostlist/hostlist-server.c:425 #: src/peerinfo-tool/gnunet-peerinfo.c:350 #: src/peerinfo-tool/gnunet-peerinfo.c:419 #: src/peerinfo-tool/gnunet-peerinfo.c:490 #: src/topology/gnunet-daemon-topology.c:925 #, fuzzy, c-format msgid "Error in communication with PEERINFO service: %s\n" msgstr "Cổng để liên lạc vá»›i giao diện ngưá»i dùng GNUnet" #: src/hostlist/hostlist-server.c:210 msgid "HELLOs without addresses encountered (ignored)" msgstr "" #: src/hostlist/hostlist-server.c:224 msgid "bytes not included in hostlist (size limit)" msgstr "" #: src/hostlist/hostlist-server.c:268 #, fuzzy, c-format msgid "Refusing `%s' request to hostlist server\n" msgstr "trình phục vụ danh sách máy HTTP hợp nhất" #: src/hostlist/hostlist-server.c:271 #, fuzzy msgid "hostlist requests refused (not HTTP GET)" msgstr "# các yêu cầu danh sách máy được nhận" #: src/hostlist/hostlist-server.c:284 #, c-format msgid "Refusing `%s' request with %llu bytes of upload data\n" msgstr "" #: src/hostlist/hostlist-server.c:288 #, fuzzy msgid "hostlist requests refused (upload data)" msgstr "# các yêu cầu danh sách máy được nhận" #: src/hostlist/hostlist-server.c:296 msgid "Could not handle hostlist request since I do not have a response yet\n" msgstr "" #: src/hostlist/hostlist-server.c:299 #, fuzzy msgid "hostlist requests refused (not ready)" msgstr "# các yêu cầu danh sách máy được nhận" #: src/hostlist/hostlist-server.c:303 #, fuzzy msgid "Received request for our hostlist\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/hostlist/hostlist-server.c:304 #, fuzzy msgid "hostlist requests processed" msgstr "# các yêu cầu danh sách máy được nhận" #: src/hostlist/hostlist-server.c:346 #, fuzzy msgid "# hostlist advertisements send" msgstr "# Các quảng cáo ngoại được chuyển tiếp" #: src/hostlist/hostlist-server.c:390 msgid "Advertisement message could not be queued by core\n" msgstr "" #: src/hostlist/hostlist-server.c:557 src/peerinfo-tool/gnunet-peerinfo.c:639 #: src/transport/gnunet-service-transport.c:1114 #, fuzzy msgid "Could not access PEERINFO service. Exiting.\n" msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #: src/hostlist/hostlist-server.c:576 #, c-format msgid "Hostlist service starts on %s:%llu\n" msgstr "" #: src/hostlist/hostlist-server.c:590 #, fuzzy, c-format msgid "Address to obtain hostlist: `%s'\n" msgstr "Äang thá»­ tải danh sách các máy xuống « %s »\n" #: src/hostlist/hostlist-server.c:630 #, fuzzy, c-format msgid "`%s' is not a valid IP address! Ignoring BINDTOIP.\n" msgstr "« %s » không sẵn sàng.\n" #: src/hostlist/hostlist-server.c:673 #, fuzzy, c-format msgid "Could not start hostlist HTTP server on port %u\n" msgstr "Cổng cho trình phục vụ HTTP danh sách máy chá»§ thống nhất" #: src/identity/gnunet-identity.c:165 #, fuzzy, c-format msgid "Failed to create ego: %s\n" msgstr "Không thể tạo miá»n tên.\n" #: src/identity/gnunet-identity.c:184 #, fuzzy, c-format msgid "Failed to set default ego: %s\n" msgstr "Không thể tạo miá»n tên.\n" #: src/identity/gnunet-identity.c:327 msgid "create ego NAME" msgstr "" #: src/identity/gnunet-identity.c:330 msgid "delete ego NAME " msgstr "" #: src/identity/gnunet-identity.c:333 msgid "display all egos" msgstr "" #: src/identity/gnunet-identity.c:336 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)" msgstr "" #: src/identity/gnunet-identity.c:339 msgid "run in monitor mode egos" msgstr "" #: src/identity/gnunet-identity.c:342 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)" msgstr "" #: src/identity/gnunet-identity.c:351 msgid "Maintain egos" msgstr "" #: src/identity/gnunet-service-identity.c:338 msgid "no default known" msgstr "" #: src/identity/gnunet-service-identity.c:362 msgid "default configured, but ego unknown (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:439 #: src/identity/gnunet-service-identity.c:670 #: src/identity/gnunet-service-identity.c:778 #, fuzzy, c-format msgid "Failed to write subsystem default identifier map to `%s'.\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/identity/gnunet-service-identity.c:446 msgid "Unknown ego specified for service (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:516 msgid "identifier already in use for another ego" msgstr "" #: src/identity/gnunet-service-identity.c:647 msgid "target name already exists" msgstr "" #: src/identity/gnunet-service-identity.c:686 #: src/identity/gnunet-service-identity.c:795 msgid "no matching ego found" msgstr "" #: src/identity/gnunet-service-identity.c:829 #, fuzzy, c-format msgid "Failed to parse ego information in `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/identity/gnunet-service-identity.c:902 #, fuzzy, c-format msgid "Failed to parse subsystem identity configuration file `%s'\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/identity/gnunet-service-identity.c:914 #, fuzzy, c-format msgid "Failed to create directory `%s' for storing egos\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/mesh/gnunet-mesh.c:357 #, fuzzy, c-format msgid "Invalid target `%s'\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/mesh/gnunet-mesh.c:607 #, fuzzy, c-format msgid "Invalid peer ID `%s'\n" msgstr "Dữ liệu nhập không hợp lệ.\n" #: src/mesh/gnunet-mesh.c:650 #, fuzzy, c-format msgid "Invalid tunnel owner `%s'\n" msgstr "Äịa chỉ IP định dạng sai: %s\n" #: src/mesh/gnunet-mesh.c:716 msgid "You must NOT give a TARGETwhen using 'request all' options\n" msgstr "" #: src/mesh/gnunet-mesh.c:807 #, fuzzy msgid "provide information about a particular connection" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/mesh/gnunet-mesh.c:810 msgid "activate echo mode" msgstr "" #: src/mesh/gnunet-mesh.c:816 msgid "port to listen to (default; 0)" msgstr "" #: src/mesh/gnunet-mesh.c:819 src/mesh/gnunet-mesh.c:822 #, fuzzy msgid "provide information about all peers" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/mesh/gnunet-mesh.c:825 #, fuzzy msgid "provide information about a particular tunnel" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/mesh/gnunet-mesh.c:828 #, fuzzy msgid "provide information about all tunnels" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/mesh/gnunet-service-mesh_peer.c:390 msgid "Wrong CORE service\n" msgstr "" #: src/mysql/mysql.c:174 #, c-format msgid "Trying to use file `%s' for MySQL configuration.\n" msgstr "Äang thá»­ dùng tập tin « %s » cho cấu hình MySQL.\n" #: src/mysql/mysql.c:181 #, fuzzy, c-format msgid "Could not access file `%s': %s\n" msgstr "Không thể truy cập đến « %s »: %s\n" #: src/namecache/gnunet-namecache.c:109 #, fuzzy, c-format msgid "No records found for `%s'" msgstr "Vẫn còn không tìm thấy đồng đẳng trong « %s ».\n" #: src/namecache/gnunet-namecache.c:124 src/namestore/gnunet-namestore.c:397 #, c-format msgid "\tCorrupt or unsupported record of type %u\n" msgstr "" #: src/namecache/gnunet-namecache.c:185 #, fuzzy, c-format msgid "You must specify which zone should be accessed\n" msgstr "chỉ ra TRUYỀN_TẢI nào cần được thá»­ nghiệm" #: src/namecache/gnunet-namecache.c:195 src/namestore/gnunet-namestore.c:695 #, fuzzy, c-format msgid "Invalid public key for reverse lookup `%s'\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/namecache/gnunet-namecache.c:203 #, fuzzy, c-format msgid "You must specify a name\n" msgstr "Phải ghi rõ tên hiệu\n" #: src/namecache/gnunet-namecache.c:234 src/namestore/gnunet-namestore.c:931 msgid "name of the record to add/delete/display" msgstr "" #: src/namecache/gnunet-namecache.c:237 #, fuzzy msgid "spezifies the public key of the zone to look in" msgstr "xác định mức ưu tiên cá»§a ná»™i dung" #: src/namecache/gnunet-namecache.c:248 src/namestore/gnunet-namestore.c:963 #, fuzzy msgid "GNUnet zone manipulation tool" msgstr "Cấu hình GNUnet" #: src/namecache/namecache_api.c:276 msgid "Namecache failed to cache block" msgstr "" #: src/namecache/plugin_namecache_postgres.c:89 #: src/namestore/plugin_namestore_postgres.c:96 #, fuzzy msgid "Failed to create indices\n" msgstr "Không thể tạo miá»n tên.\n" #: src/namestore/gnunet-namestore.c:303 #, fuzzy, c-format msgid "Adding record failed: %s\n" msgstr "Gặp lá»—i khi tải lên tập tin: %s\n" #: src/namestore/gnunet-namestore.c:332 #, fuzzy, c-format msgid "Deleting record failed, record does not exist%s%s\n" msgstr "Gặp lá»—i khi tải lên tập tin: %s\n" #: src/namestore/gnunet-namestore.c:339 #, fuzzy, c-format msgid "Deleting record failed%s%s\n" msgstr "Gặp lá»—i khi tải lên tập tin: %s\n" #: src/namestore/gnunet-namestore.c:558 #, fuzzy, c-format msgid "No options given\n" msgstr "chưa đưa ra tên" #: src/namestore/gnunet-namestore.c:569 #: src/namestore/gnunet-namestore-fcfsd.c:970 #, fuzzy msgid "Failed to connect to namestore\n" msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/namestore/gnunet-namestore.c:577 src/namestore/gnunet-namestore.c:586 #: src/namestore/gnunet-namestore.c:603 src/namestore/gnunet-namestore.c:625 #: src/namestore/gnunet-namestore.c:665 #, fuzzy, c-format msgid "Missing option `%s' for operation `%s'\n" msgstr "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #: src/namestore/gnunet-namestore.c:578 src/namestore/gnunet-namestore.c:587 #: src/namestore/gnunet-namestore.c:604 src/namestore/gnunet-namestore.c:626 msgid "add" msgstr "" #: src/namestore/gnunet-namestore.c:595 #, fuzzy, c-format msgid "Unsupported type `%s'\n" msgstr "Lệnh không được há»— trợ « %s ». Äang há»§y bá».\n" #: src/namestore/gnunet-namestore.c:615 #, c-format msgid "Value `%s' invalid for record type `%s'\n" msgstr "" #: src/namestore/gnunet-namestore.c:651 #, fuzzy, c-format msgid "Invalid time format `%s'\n" msgstr "Äịa chỉ IP định dạng sai: %s\n" #: src/namestore/gnunet-namestore.c:666 msgid "del" msgstr "" #: src/namestore/gnunet-namestore.c:715 #: src/peerinfo-tool/gnunet-peerinfo.c:723 #, fuzzy, c-format msgid "Invalid URI `%s'\n" msgstr "Dữ liệu nhập không hợp lệ.\n" #: src/namestore/gnunet-namestore.c:750 #, fuzzy, c-format msgid "Invalid nick `%s'\n" msgstr "Dữ liệu nhập không hợp lệ.\n" #: src/namestore/gnunet-namestore.c:790 #, c-format msgid "Ego `%s' not known to identity service\n" msgstr "" #: src/namestore/gnunet-namestore.c:817 #, c-format msgid "No default ego configured in identity service\n" msgstr "" #: src/namestore/gnunet-namestore.c:853 #, fuzzy, c-format msgid "Identity service is not running\n" msgstr "« %s » không phải là má»™t tập tin.\n" #: src/namestore/gnunet-namestore.c:865 #, fuzzy, c-format msgid "Cannot connect to identity service\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/namestore/gnunet-namestore.c:913 msgid "add record" msgstr "" #: src/namestore/gnunet-namestore.c:916 msgid "delete record" msgstr "" #: src/namestore/gnunet-namestore.c:919 msgid "display records" msgstr "" #: src/namestore/gnunet-namestore.c:922 msgid "" "expiration time for record to use (for adding only), \"never\" is possible" msgstr "" #: src/namestore/gnunet-namestore.c:925 #, fuzzy msgid "set the desired nick name for the zone" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/namestore/gnunet-namestore.c:928 #, fuzzy msgid "monitor changes in the namestore" msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/namestore/gnunet-namestore.c:934 #, fuzzy msgid "determine our name for the given PKEY" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/namestore/gnunet-namestore.c:937 msgid "type of the record to add/delete/display" msgstr "" #: src/namestore/gnunet-namestore.c:940 msgid "URI to import into our zone" msgstr "" #: src/namestore/gnunet-namestore.c:943 msgid "value of the record to add/delete" msgstr "" #: src/namestore/gnunet-namestore.c:946 msgid "create or list public record" msgstr "" #: src/namestore/gnunet-namestore.c:949 msgid "" "create shadow record (only valid if all other records of the same type have " "expired" msgstr "" #: src/namestore/gnunet-namestore.c:952 msgid "name of the ego controlling the zone" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:464 #, fuzzy, c-format msgid "Unsupported form value `%s'\n" msgstr "Lệnh không được há»— trợ « %s ». Äang há»§y bá».\n" #: src/namestore/gnunet-namestore-fcfsd.c:491 #, fuzzy, c-format msgid "Failed to create record for domain `%s': %s\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/namestore/gnunet-namestore-fcfsd.c:525 #, c-format msgid "Found existing name `%s' for the given key\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:534 msgid "Error when mapping zone to name\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:596 #, c-format msgid "Found %u existing records for domain `%s'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:652 #, fuzzy, c-format msgid "Failed to create page for `%s'\n" msgstr "Không thể tạo miá»n tên.\n" #: src/namestore/gnunet-namestore-fcfsd.c:668 #, fuzzy, c-format msgid "Failed to setup post processor for `%s'\n" msgstr "Lá»—i cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #: src/namestore/gnunet-namestore-fcfsd.c:704 msgid "Domain name must not contain `.'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:712 msgid "Domain name must not contain `+'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:910 msgid "No ego configured for `fcfsd` subsystem\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:936 #, fuzzy msgid "Failed to start HTTP server\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/namestore/gnunet-namestore-fcfsd.c:978 #, fuzzy msgid "Failed to connect to identity\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/namestore/gnunet-namestore-fcfsd.c:1011 msgid "GNU Name System First Come First Serve name registration service" msgstr "" #: src/namestore/gnunet-service-namestore.c:655 #, fuzzy, c-format msgid "Failed to replicate block in namecache: %s\n" msgstr "Lá»—i cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #: src/namestore/namestore_api.c:275 msgid "Namestore failed to store record\n" msgstr "" #: src/nat/gnunet-nat-server.c:279 #, c-format msgid "Please pass valid port number as the first argument! (got `%s')\n" msgstr "" #: src/nat/gnunet-nat-server.c:321 msgid "GNUnet NAT traversal test helper daemon" msgstr "" #: src/nat/nat_auto.c:170 msgid "NAT traversal with ICMP Server timed out.\n" msgstr "" #: src/nat/nat_auto.c:203 msgid "NAT traversal with ICMP Server succeeded.\n" msgstr "" #: src/nat/nat_auto.c:204 msgid "NAT traversal with ICMP Server failed.\n" msgstr "" #: src/nat/nat_auto.c:225 #, fuzzy msgid "Testing connection reversal with ICMP server.\n" msgstr "Cổng để liên lạc vá»›i giao diện ngưá»i dùng GNUnet" #: src/nat/nat_auto.c:274 #, c-format msgid "Detected external IP `%s'\n" msgstr "" #: src/nat/nat_auto.c:344 msgid "This system has a global IPv6 address, setting IPv6 to supported.\n" msgstr "" #: src/nat/nat_auto.c:360 #, fuzzy, c-format msgid "Detected internal network address `%s'.\n" msgstr "GNUnet bây giá» sá»­ dụng địa chỉ IP %s.\n" #: src/nat/nat_auto.c:413 msgid "upnpc found, enabling its use\n" msgstr "" #: src/nat/nat_auto.c:414 msgid "upnpc not found\n" msgstr "" #: src/nat/nat_auto.c:447 msgid "gnunet-helper-nat-server found, testing it\n" msgstr "" #: src/nat/nat_auto.c:448 msgid "No working gnunet-helper-nat-server found\n" msgstr "" #: src/nat/nat_auto.c:482 msgid "gnunet-helper-nat-client found, enabling it\n" msgstr "" #: src/nat/nat_auto.c:483 msgid "gnunet-helper-nat-client not found or behind NAT, disabling it\n" msgstr "" #: src/nat/nat.c:867 #, c-format msgid "gnunet-helper-nat-server generated malformed address `%s'\n" msgstr "" #: src/nat/nat.c:917 #, fuzzy, c-format msgid "Failed to start %s\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/nat/nat.c:1205 msgid "malformed" msgstr "" #: src/nat/nat.c:1276 src/nat/nat.c:1288 #, c-format msgid "" "Configuration requires `%s', but binary is not installed properly (SUID bit " "not set). Option disabled.\n" msgstr "" #: src/nat/nat.c:1426 msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n" msgstr "" #: src/nat/nat.c:1442 #, c-format msgid "Running gnunet-helper-nat-client %s %s %u\n" msgstr "" #: src/nat/nat_mini.c:155 msgid "no valid address was returned by `external-ip'" msgstr "" #: src/nat/nat_mini.c:175 msgid "`external-ip' command not found" msgstr "" #: src/nat/nat_mini.c:201 msgid "`external-ip' command not found\n" msgstr "" #: src/nat/nat_mini.c:366 #, fuzzy msgid "Failed to run `upnpc` command" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/nat/nat_mini.c:512 msgid "`upnpc' command took too long, process killed" msgstr "" #: src/nat/nat_mini.c:540 msgid "`upnpc' command failed to establish port mapping" msgstr "" #: src/nat/nat_mini.c:604 msgid "`upnpc' command not found\n" msgstr "" #: src/nat/nat_mini.c:608 msgid "`upnpc` command not found" msgstr "" #: src/nat/nat_test.c:351 #, fuzzy msgid "Failed to connect to `gnunet-nat-server'\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/nat/nat_test.c:423 #, c-format msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n" msgstr "" #: src/nse/gnunet-nse.c:117 #, fuzzy msgid "NSE service is not running\n" msgstr "« %s » không phải là má»™t tập tin.\n" #: src/nse/gnunet-nse.c:122 msgid "Error while checking if NSE service is running or not\n" msgstr "" #: src/nse/gnunet-nse.c:168 #, fuzzy msgid "Show network size estimates from NSE service." msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/nse/gnunet-nse-profiler.c:858 #, fuzzy msgid "limit to the number of connections to NSE services, 0 for none" msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/nse/gnunet-nse-profiler.c:861 msgid "name of the file for writing connection information and statistics" msgstr "" #: src/nse/gnunet-nse-profiler.c:864 src/testbed/gnunet-testbed-profiler.c:306 msgid "name of the file with the login information for the testbed" msgstr "" #: src/nse/gnunet-nse-profiler.c:867 msgid "name of the file for writing the main results" msgstr "" #: src/nse/gnunet-nse-profiler.c:870 msgid "Number of peers to run in each round, separated by commas" msgstr "" #: src/nse/gnunet-nse-profiler.c:876 msgid "delay between rounds" msgstr "" #: src/nse/gnunet-nse-profiler.c:885 #, fuzzy msgid "Measure quality and performance of the NSE service." msgstr "Không thể truy cập đến dịch vụ" #: src/nse/gnunet-service-nse.c:1517 #: src/revocation/gnunet-service-revocation.c:789 src/util/gnunet-scrypt.c:248 #, fuzzy msgid "Value is too large.\n" msgstr "Giá trị không nằm trong phạm vi được phép." #: src/peerinfo/gnunet-service-peerinfo.c:215 #, fuzzy, c-format msgid "Removing expired address of transport `%s'\n" msgstr "Äã nạp truyá»n tải « %s »\n" #: src/peerinfo/gnunet-service-peerinfo.c:352 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s': %s\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/peerinfo/gnunet-service-peerinfo.c:371 #: src/peerinfo/gnunet-service-peerinfo.c:388 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/peerinfo/gnunet-service-peerinfo.c:466 msgid "# peers known" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:503 #, c-format msgid "" "File `%s' in directory `%s' does not match naming convention. Removed.\n" msgstr "" "Tập tin « %s » trong thư mục « %s » không tùy theo quy ước đặt tên. Bị gỡ " "bá».\n" #: src/peerinfo/gnunet-service-peerinfo.c:653 #, fuzzy, c-format msgid "Scanning directory `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/peerinfo/gnunet-service-peerinfo.c:658 #, c-format msgid "Still no peers found in `%s'!\n" msgstr "Vẫn còn không tìm thấy đồng đẳng trong « %s ».\n" #: src/peerinfo/gnunet-service-peerinfo.c:994 #, fuzzy, c-format msgid "Cleaning up directory `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/peerinfo/gnunet-service-peerinfo.c:1287 #, c-format msgid "Importing HELLOs from `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:1298 msgid "Skipping import of included HELLOs\n" msgstr "" #: src/peerinfo/peerinfo_api.c:236 msgid "aborted due to explicit disconnect request" msgstr "" #: src/peerinfo/peerinfo_api.c:356 #, fuzzy msgid "failed to transmit request (service down?)" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/peerinfo/peerinfo_api.c:506 #, fuzzy msgid "Failed to receive response from `PEERINFO' service." msgstr "" "\n" "Không nhận được đáp ứng từ gnunetd.\n" #: src/peerinfo/peerinfo_api.c:547 src/peerinfo/peerinfo_api.c:566 #: src/peerinfo/peerinfo_api.c:581 src/peerinfo/peerinfo_api.c:592 #: src/peerinfo/peerinfo_api.c:603 #, fuzzy msgid "Received invalid message from `PEERINFO' service." msgstr "" "\n" "Không nhận được đáp ứng từ gnunetd.\n" #: src/peerinfo/peerinfo_api.c:678 #, fuzzy msgid "Timeout transmitting iteration request to `PEERINFO' service." msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/peerinfo/peerinfo_api_notify.c:268 #, fuzzy, c-format msgid "Could not connect to `%s' service.\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/peerinfo-tool/gnunet-peerinfo.c:232 #, fuzzy, c-format msgid "%sPeer `%s'\n" msgstr "Tôi là đồng đẳng « %s ».\n" #: src/peerinfo-tool/gnunet-peerinfo.c:239 #, c-format msgid "\tExpires: %s \t %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:428 #, fuzzy, c-format msgid "Failure: Did not receive %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/peerinfo-tool/gnunet-peerinfo.c:436 #, c-format msgid "Failure: Received invalid %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:445 #, fuzzy, c-format msgid "Failed to write HELLO with %u bytes to file `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/peerinfo-tool/gnunet-peerinfo.c:458 #, c-format msgid "Wrote %s HELLO containing %u addresses with %u bytes to file `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:522 #, c-format msgid "Failure adding HELLO: %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:633 #, fuzzy, c-format msgid "Service `%s' is not running, please start GNUnet\n" msgstr "« %s » không phải là má»™t tập tin.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:654 src/util/gnunet-scrypt.c:224 #, c-format msgid "Loading hostkey from `%s' failed.\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:745 #, c-format msgid "I am peer `%s'.\n" msgstr "Tôi là đồng đẳng « %s ».\n" #: src/peerinfo-tool/gnunet-peerinfo.c:789 msgid "don't resolve host names" msgstr "không quyết định các tên máy" #: src/peerinfo-tool/gnunet-peerinfo.c:792 msgid "output only the identity strings" msgstr "chỉ xuất những chuá»—i nhận diện" #: src/peerinfo-tool/gnunet-peerinfo.c:795 msgid "include friend-only information" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:798 msgid "output our own identity only" msgstr "chỉ xuất nhận diện mình" #: src/peerinfo-tool/gnunet-peerinfo.c:801 #, fuzzy msgid "list all known peers" msgstr "liệt kê má»i bá»™ tiếp hợp mạng" #: src/peerinfo-tool/gnunet-peerinfo.c:804 msgid "dump hello to file" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:807 msgid "also output HELLO uri(s)" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:810 msgid "add given HELLO uri to the database" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:821 #, fuzzy msgid "Print information about peers." msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:105 #: src/transport/gnunet-service-transport_plugins.c:128 #, fuzzy, c-format msgid "Starting transport plugins `%s'\n" msgstr "Äang nạp các truyá»n tải « %s »\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:109 #: src/transport/gnunet-service-transport_plugins.c:133 #, fuzzy, c-format msgid "Loading `%s' transport plugin\n" msgstr "Äang nạp các truyá»n tải « %s »\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:129 #: src/transport/gnunet-service-transport_plugins.c:165 #, fuzzy, c-format msgid "Failed to load transport plugin for `%s'\n" msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #: src/postgres/postgres.c:59 #, fuzzy, c-format msgid "`%s:%s' failed at %s:%d with error: %s" msgstr "« %s » bị lá»—i tại %s:%d vá»›i lá»—i: %s" #: src/postgres/postgres.c:148 #, fuzzy, c-format msgid "Unable to initialize Postgres: %s" msgstr "Không thể sÆ¡ khởi SQLite: %s.\n" #: src/psycstore/gnunet-service-psycstore.c:200 #, fuzzy msgid "Failed to store membership information!\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/psycstore/gnunet-service-psycstore.c:224 #, fuzzy msgid "Failed to test membership!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/psycstore/gnunet-service-psycstore.c:246 #, fuzzy msgid "Failed to store fragment!\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/psycstore/gnunet-service-psycstore.c:272 #, fuzzy msgid "Failed to get fragment!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/psycstore/gnunet-service-psycstore.c:299 #, fuzzy msgid "Failed to get message!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/psycstore/gnunet-service-psycstore.c:328 #, fuzzy msgid "Failed to get message fragment!\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/psycstore/gnunet-service-psycstore.c:356 #, fuzzy msgid "Failed to get master counters!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/psycstore/gnunet-service-psycstore.c:392 #: src/psycstore/gnunet-service-psycstore.c:465 msgid "Tried to set invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:408 #, fuzzy msgid "Failed to begin modifying state!\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/psycstore/gnunet-service-psycstore.c:431 #, fuzzy, c-format msgid "Unknown operator: %c\n" msgstr "Không rõ thao tác « %s ».\n" #: src/psycstore/gnunet-service-psycstore.c:441 #, fuzzy msgid "Failed to end modifying state!\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/psycstore/gnunet-service-psycstore.c:479 #, fuzzy msgid "Failed to begin synchronizing state!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/psycstore/gnunet-service-psycstore.c:495 #, fuzzy msgid "Failed to end synchronizing state!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/psycstore/gnunet-service-psycstore.c:515 #: src/psycstore/gnunet-service-psycstore.c:534 #, fuzzy msgid "Failed to reset state!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/psycstore/gnunet-service-psycstore.c:557 #: src/psycstore/gnunet-service-psycstore.c:608 msgid "Tried to get invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:584 #: src/psycstore/gnunet-service-psycstore.c:623 #, fuzzy msgid "Failed to get state variable!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/psycstore/plugin_psycstore_sqlite.c:60 #, fuzzy, c-format msgid "`%s' failed at %s:%d with error: %s (%d)\n" msgstr "« %s » bị lá»—i tại %s:%d vá»›i lá»—i: %s\n" #: src/psycstore/plugin_psycstore_sqlite.c:253 #, fuzzy, c-format msgid "" "Error preparing SQL query: %s\n" " %s\n" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/psycstore/plugin_psycstore_sqlite.c:276 #, fuzzy, c-format msgid "" "Error executing SQL query: %s\n" " %s\n" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/psycstore/plugin_psycstore_sqlite.c:1796 #, fuzzy msgid "SQLite database running\n" msgstr "kho dữ liệu sqlite" #: src/pt/gnunet-daemon-pt.c:482 msgid "Failed to pack DNS request. Dropping.\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:488 #, fuzzy msgid "# DNS requests mapped to VPN" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/pt/gnunet-daemon-pt.c:541 msgid "# DNS records modified" msgstr "" #: src/pt/gnunet-daemon-pt.c:717 #, fuzzy msgid "# DNS replies intercepted" msgstr "# các đáp ứng dht được định tuyến" #: src/pt/gnunet-daemon-pt.c:723 msgid "Failed to parse DNS request. Dropping.\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:826 #, fuzzy msgid "# DNS requests dropped (timeout)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/pt/gnunet-daemon-pt.c:883 #, fuzzy msgid "# DNS requests intercepted" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/pt/gnunet-daemon-pt.c:888 #, fuzzy msgid "# DNS requests dropped (DNS mesh channel down)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/pt/gnunet-daemon-pt.c:896 #, fuzzy msgid "# DNS requests dropped (malformed)" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/pt/gnunet-daemon-pt.c:969 #, fuzzy msgid "# DNS replies received" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/pt/gnunet-daemon-pt.c:985 #, fuzzy msgid "# DNS replies dropped (too late?)" msgstr "# các đáp ứng dht được định tuyến" #: src/pt/gnunet-daemon-pt.c:1261 src/pt/gnunet-daemon-pt.c:1270 #: src/pt/gnunet-daemon-pt.c:1290 src/pt/gnunet-daemon-pt.c:1301 #: src/pt/gnunet-daemon-pt.c:1310 #, fuzzy, c-format msgid "Failed to connect to %s service. Exiting.\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/pt/gnunet-daemon-pt.c:1347 msgid "Daemon to run to perform IP protocol translation to GNUnet" msgstr "" #: src/regex/gnunet-daemon-regexprofiler.c:270 #: src/regex/gnunet-regex-simulation-profiler.c:659 #, fuzzy, c-format msgid "%s service is lacking key configuration settings (%s). Exiting.\n" msgstr "Lưu cấu hình ngay bây giá» không?" #: src/regex/gnunet-daemon-regexprofiler.c:380 msgid "Daemon to announce regular expressions for the peer using mesh." msgstr "" #: src/regex/gnunet-regex-profiler.c:1288 #, fuzzy msgid "No configuration file given. Exiting\n" msgstr "dùng tập tin cấu hình TÊN_TẬP_TIN" #: src/regex/gnunet-regex-profiler.c:1299 #, fuzzy msgid "Configuration option \"regex_prefix\" missing. Exiting\n" msgstr "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #: src/regex/gnunet-regex-profiler.c:1328 #: src/regex/gnunet-regex-simulation-profiler.c:622 #, c-format msgid "No policy directory specified on command line. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1334 #: src/regex/gnunet-regex-simulation-profiler.c:629 #, c-format msgid "Specified policies directory does not exist. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1341 #, fuzzy, c-format msgid "No files found in `%s'\n" msgstr "Vẫn còn không tìm thấy đồng đẳng trong « %s ».\n" #: src/regex/gnunet-regex-profiler.c:1350 msgid "No search strings file given. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1370 #, fuzzy msgid "Error loading search strings. Exiting.\n" msgstr "Gặp lá»—i khi tải xuống: %s\n" #: src/regex/gnunet-regex-profiler.c:1455 #, fuzzy msgid "name of the file for writing statistics" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/regex/gnunet-regex-profiler.c:1458 msgid "wait TIMEOUT before ending the experiment" msgstr "" #: src/regex/gnunet-regex-profiler.c:1461 msgid "directory with policy files" msgstr "" #: src/regex/gnunet-regex-profiler.c:1464 #, fuzzy msgid "name of file with input strings" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/regex/gnunet-regex-profiler.c:1467 #, fuzzy msgid "name of file with hosts' names" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/regex/gnunet-regex-profiler.c:1479 msgid "Profiler for regex" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:689 msgid "name of the table to write DFAs" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:692 msgid "maximum path compression length" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:705 msgid "Profiler for regex library" msgstr "" #: src/regex/regex_api.c:131 #, fuzzy, c-format msgid "Regex `%s' is too long!\n" msgstr "« %s » không phải là má»™t tập tin.\n" #: src/revocation/gnunet-revocation.c:126 #, fuzzy, c-format msgid "Key `%s' is valid\n" msgstr "Äịnh dạng cá»§a biệt hiệu « %s » là không hợp lệ.\n" #: src/revocation/gnunet-revocation.c:131 #, fuzzy, c-format msgid "Key `%s' has been revoked\n" msgstr "Dịch vụ đã bị xoá.\n" #: src/revocation/gnunet-revocation.c:137 #, fuzzy msgid "Internal error\n" msgstr "Lá»—i VR." #: src/revocation/gnunet-revocation.c:163 #, c-format msgid "Key for ego `%s' is still valid, revocation failed (!)\n" msgstr "" #: src/revocation/gnunet-revocation.c:168 #, fuzzy msgid "Revocation failed (!)\n" msgstr "Lá»—i ná»™i bá»™ : khẳng định không thành công tại %s:%d.\n" #: src/revocation/gnunet-revocation.c:173 #, c-format msgid "Key for ego `%s' has been successfully revoked\n" msgstr "" #: src/revocation/gnunet-revocation.c:178 msgid "Revocation successful.\n" msgstr "" #: src/revocation/gnunet-revocation.c:183 msgid "Internal error, key revocation might have failed\n" msgstr "" #: src/revocation/gnunet-revocation.c:294 #, c-format msgid "Revocation certificate for `%s' stored in `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:324 #, fuzzy, c-format msgid "Ego `%s' not found.\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/revocation/gnunet-revocation.c:345 #, c-format msgid "Error: revocation certificate in `%s' is not for `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:365 msgid "Revocation certificate ready\n" msgstr "" #: src/revocation/gnunet-revocation.c:375 msgid "Revocation certificate not ready, calculating proof of work\n" msgstr "" #: src/revocation/gnunet-revocation.c:407 #, fuzzy, c-format msgid "Public key `%s' malformed\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/revocation/gnunet-revocation.c:421 msgid "" "Testing and revoking at the same time is not allowed, only executing test.\n" msgstr "" #: src/revocation/gnunet-revocation.c:441 #, fuzzy msgid "No filename to store revocation certificate given.\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/revocation/gnunet-revocation.c:463 #, fuzzy, c-format msgid "Failed to read revocation certificate from `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/revocation/gnunet-revocation.c:488 #, fuzzy msgid "No action specified. Nothing to do.\n" msgstr "Chưa xác định giao diện nên dùng mặc định.\n" #: src/revocation/gnunet-revocation.c:504 msgid "use NAME for the name of the revocation file" msgstr "" #: src/revocation/gnunet-revocation.c:507 msgid "" "revoke the private key associated for the the private key associated with " "the ego NAME " msgstr "" #: src/revocation/gnunet-revocation.c:510 msgid "actually perform revocation, otherwise we just do the precomputation" msgstr "" #: src/revocation/gnunet-revocation.c:513 msgid "test if the public key KEY has been revoked" msgstr "" #: src/revocation/gnunet-service-revocation.c:272 msgid "Duplicate revocation received from peer. Ignored.\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:434 #, c-format msgid "Error computing revocation set union with %s\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:486 msgid "SET service crashed, terminating revocation service\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:812 #, fuzzy msgid "Could not open revocation database file!" msgstr "« %s »: Không thể kết nối.\n" #: src/scalarproduct/gnunet-scalarproduct.c:225 #, fuzzy msgid "You must specify at least one message ID to check!\n" msgstr "Phải ghi rõ chỉ má»™t tên tập tin để chèn.\n" #: src/scalarproduct/gnunet-scalarproduct.c:232 msgid "This program needs a session identifier for comparing vectors.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:239 msgid "Please give a session key for --input_key!\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:251 #, c-format msgid "" "Tried to set initiator mode, as peer ID was given. However, `%s' is not a " "valid peer identifier.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:278 #: src/scalarproduct/gnunet-scalarproduct.c:314 #, fuzzy, c-format msgid "Could not convert `%s' to int32_t.\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/scalarproduct/gnunet-scalarproduct.c:286 msgid "Need elements to compute the vectorproduct, got none.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:346 #, fuzzy, c-format msgid "Could not convert `%s' to integer.\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/scalarproduct/gnunet-scalarproduct.c:407 msgid "" "A comma separated list of elements to compare as vector with our remote peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:410 msgid "" "A comma separated mask to select which elements should actually be compared." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:413 msgid "" "[Optional] peer to calculate our scalarproduct with. If this parameter is " "not given, the service will wait for a remote peer to compute the request." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:416 msgid "Transaction ID shared with peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:425 msgid "Calculate the Vectorproduct with a GNUnet peer." msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:541 #, fuzzy, c-format msgid "Client (%p) disconnected from us.\n" msgstr "« %.*s » được kết nối tá»›i « %.*s ».\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:613 #: src/scalarproduct/gnunet-service-scalarproduct.c:702 #, fuzzy, c-format msgid "Could not send message to client (%p)!\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:619 #, c-format msgid "Sending session-end notification to client (%p) for session %s\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:712 #, c-format msgid "Sent result to client (%p), this session (%s) has ended!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:766 #: src/scalarproduct/gnunet-service-scalarproduct.c:855 msgid "Could not send service-response message via mesh!)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1028 #, c-format msgid "Failed to communicate with `%s', scalar product calculation aborted.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1099 #: src/scalarproduct/gnunet-service-scalarproduct.c:1208 #, fuzzy msgid "Transmitting service request.\n" msgstr "Äang nạp và khởi động dùng « %s ».\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1108 #, fuzzy msgid "Could not send service-request multipart message to channel!\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1147 #, fuzzy, c-format msgid "Successfully created new channel to peer (%s)!\n" msgstr "Không đủ quyá»n cho « %s ».\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1217 #, fuzzy msgid "Could not send message to channel!\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1274 #, fuzzy msgid "Too short message received from client!\n" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/scalarproduct/gnunet-service-scalarproduct.c:1287 #, fuzzy msgid "Invalid message received from client, session information incorrect!\n" msgstr "Nhận được thông báo « %s » sai từ đồng đẳng « %s ».\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1298 #, c-format msgid "" "Duplicate session information received, cannot create new session with key `" "%s'\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1318 #, c-format msgid "" "Got client-request-session with key %s, preparing channel to remote " "service.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1354 #, c-format msgid "Creating new channel for session with key %s.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1399 #, c-format msgid "" "Got client-responder-session with key %s and a matching service-request-" "session set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1409 #, c-format msgid "" "Got client-responder-session with key %s but NO matching service-request-" "session set, queuing element for later use.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1439 #, fuzzy, c-format msgid "New incoming channel from peer %s.\n" msgstr "« %.*s » được kết nối tá»›i « %.*s ».\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1471 #, c-format msgid "Peer disconnected, terminating session %s with peer (%s)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1672 #: src/scalarproduct/gnunet-service-scalarproduct.c:1814 #, c-format msgid "Got session with key %s and a matching element set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1681 #: src/scalarproduct/gnunet-service-scalarproduct.c:1821 #, c-format msgid "Got session with key %s without a matching element set, queueing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1771 #, c-format msgid "" "Got message with duplicate session key (`%s'), ignoring service request.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2014 msgid "Shutting down, initiating cleanup.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2100 #, fuzzy msgid "Connect to MESH failed\n" msgstr " Không kết nối được (lá»—i ?)\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:2104 #, fuzzy msgid "Mesh initialized\n" msgstr "Lá»—i sÆ¡ khởi lõi.\n" #: src/scalarproduct/scalarproduct_api.c:246 #, fuzzy msgid "# SUC responder result messages received" msgstr "# các thông báo phát hiện dht được nhận" #: src/scalarproduct/scalarproduct_api.c:300 #, fuzzy msgid "# bytes sent to scalarproduct" msgstr "# các byte trong kho dữ liệu" #: src/scalarproduct/scalarproduct_api.c:345 #: src/scalarproduct/scalarproduct_api.c:440 #, fuzzy msgid "Failed to connect to the scalarproduct service\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/scalarproduct/scalarproduct_api.c:353 #: src/scalarproduct/scalarproduct_api.c:448 #, fuzzy msgid "Failed to send a message to the statistics service\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/scalarproduct/scalarproduct_api.c:387 #: src/scalarproduct/scalarproduct_api.c:485 #, fuzzy msgid "Failed to send a message to the scalarproduct service\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/secretsharing/gnunet-secretsharing-profiler.c:538 msgid "dkg start delay" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:541 msgid "dkg timeout" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:544 msgid "threshold" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:547 msgid "also profile decryption" msgstr "" #: src/set/gnunet-service-set.c:1431 #, fuzzy msgid "Could not connect to mesh service\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/set/gnunet-set-ibf-profiler.c:221 #, fuzzy msgid "number of element in set A-B" msgstr "số lần lặp lại" #: src/set/gnunet-set-ibf-profiler.c:224 #, fuzzy msgid "number of element in set B-A" msgstr "số lần lặp lại" #: src/set/gnunet-set-ibf-profiler.c:227 msgid "number of common elements in A and B" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:230 msgid "hash num" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:233 msgid "ibf size" msgstr "" #: src/set/gnunet-set-profiler.c:295 msgid "oeration to execute" msgstr "" #: src/statistics/gnunet-service-statistics.c:280 #, fuzzy, c-format msgid "Loading %llu bytes of statistics from `%s'\n" msgstr "Äã tải %llu byte xuống « %s ».\n" #: src/statistics/gnunet-service-statistics.c:346 #, fuzzy, c-format msgid "Wrote %llu bytes of statistics to `%s'\n" msgstr "Äã tải %llu byte xuống « %s ».\n" #: src/statistics/gnunet-statistics.c:140 #, fuzzy msgid "Failed to obtain statistics.\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/statistics/gnunet-statistics.c:142 #, fuzzy, c-format msgid "Failed to obtain statistics from host `%s:%llu'\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/statistics/gnunet-statistics.c:189 msgid "Missing argument: subsystem \n" msgstr "" #: src/statistics/gnunet-statistics.c:195 msgid "Missing argument: name\n" msgstr "" #: src/statistics/gnunet-statistics.c:226 #, fuzzy, c-format msgid "No subsystem or name given\n" msgstr "chưa đưa ra tên" #: src/statistics/gnunet-statistics.c:234 #, fuzzy, c-format msgid "Failed to initialize watch routine\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/statistics/gnunet-statistics.c:261 #, fuzzy, c-format msgid "Trying to connect to remote host, but service `%s' is not running\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/statistics/gnunet-statistics.c:269 #, fuzzy, c-format msgid "A port is required to connect to host `%s'\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/statistics/gnunet-statistics.c:276 #, c-format msgid "A port has to be between 1 and 65535 to connect to host `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:308 #, fuzzy, c-format msgid "Invalid argument `%s'\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/statistics/gnunet-statistics.c:334 msgid "limit output to statistics for the given NAME" msgstr "" #: src/statistics/gnunet-statistics.c:337 msgid "make the value being set persistent" msgstr "" #: src/statistics/gnunet-statistics.c:340 msgid "limit output to the given SUBSYSTEM" msgstr "" #: src/statistics/gnunet-statistics.c:343 msgid "just print the statistics value" msgstr "" #: src/statistics/gnunet-statistics.c:346 msgid "watch value continuously" msgstr "" #: src/statistics/gnunet-statistics.c:349 msgid "connect to remote host" msgstr "" #: src/statistics/gnunet-statistics.c:352 msgid "port for remote host" msgstr "" #: src/statistics/gnunet-statistics.c:364 msgid "Print statistics about GNUnet operations." msgstr "In ra thống kê vá» các thao tác GNUnet." #: src/statistics/statistics_api.c:519 #, fuzzy msgid "Could not save some persistent statistics\n" msgstr "Không thể tạo miá»n tên.\n" #: src/statistics/statistics_api.c:1090 msgid "" "Failed to receive acknowledgement from statistics service, some statistics " "might have been lost!\n" msgstr "" #: src/testbed/generate-underlay-topology.c:223 msgid "Need atleast 2 arguments\n" msgstr "" #: src/testbed/generate-underlay-topology.c:228 msgid "Database filename missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:235 msgid "Topology string missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:240 #, fuzzy, c-format msgid "Invalid topology: %s\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/testbed/generate-underlay-topology.c:252 #, c-format msgid "An argument is missing for given topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:258 #, fuzzy, c-format msgid "Invalid argument `%s' given as topology argument\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/testbed/generate-underlay-topology.c:266 #, c-format msgid "Filename argument missing for topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:280 #, c-format msgid "Second argument for topology `%s' is missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:286 #, fuzzy, c-format msgid "Invalid argument `%s'; expecting unsigned int\n" msgstr "Äối số không hợp lệ cho « %s ».\n" #: src/testbed/generate-underlay-topology.c:335 #: src/testbed/gnunet-testbed-profiler.c:293 msgid "create COUNT number of peers" msgstr "" #: src/testbed/generate-underlay-topology.c:344 msgid "" "Generates SQLite3 database representing a given underlay topology.\n" "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" "The following options are available for TOPO followed by TOPOOPTS if " "applicable:\n" "\t LINE\n" "\t RING\n" "\t RANDOM \n" "\t SMALL_WORLD \n" "\t SMALL_WORLD_RING \n" "\t CLIQUE\n" "\t 2D_TORUS\n" "\t SCALE_FREE \n" "\t FROM_FILE \n" "TOPOOPTS:\n" "\t num_rnd_links: The number of random links\n" "\t cap: the maximum number of links a node can have\n" "\t m: the number of links a node should have while joining the network\n" "\t filename: the path of the file which contains topology information\n" "NOTE: the format of the above file is descibed here: https://www.gnunet.org/" "content/topology-file-format\n" msgstr "" #: src/testbed/gnunet-daemon-latency-logger.c:325 msgid "Daemon to log latency values of connections to neighbours" msgstr "" #: src/testbed/gnunet-daemon-testbed-blacklist.c:264 msgid "" "Daemon to restrict incoming transport layer connections during testbed " "deployments" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:235 src/testing/list-keys.c:50 #: src/testing/testing.c:293 src/util/gnunet-ecc.c:217 #, c-format msgid "Incorrect hostkey file format: %s\n" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:474 msgid "Daemon to restrict underlay network in testbed deployments" msgstr "" #: src/testbed/gnunet-service-testbed_cpustatus.c:730 #, c-format msgid "" "Cannot open %s for writing load statistics. Not logging load statistics\n" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1015 #, fuzzy msgid "Misconfiguration (can't connect to the ARM service)" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/testbed/gnunet-service-testbed_peers.c:1021 msgid "Request doesn't fit into a message" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1059 #, fuzzy, c-format msgid "%s service can't be started because ARM is shutting down" msgstr "« %s » Ä‘ang tắt.\n" #: src/testbed/gnunet_testbed_mpi_spawn.c:125 #, fuzzy msgid "Waiting for child to exit.\n" msgstr "Äang đợi các đồng đẳng kết nối" #: src/testbed/gnunet_testbed_mpi_spawn.c:247 #, fuzzy, c-format msgid "Spawning process `%s'\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/testbed/gnunet-testbed-profiler.c:267 #, fuzzy, c-format msgid "Exiting as the number of peers is %u\n" msgstr "tăng sổ tối Ä‘a các kết nối TCP/IP" #: src/testbed/gnunet-testbed-profiler.c:296 msgid "tolerate COUNT number of continious timeout failures" msgstr "" #: src/testbed/gnunet-testbed-profiler.c:299 msgid "" "run profiler in non-interactive mode where upon testbed setup the profiler " "does not wait for a keystroke but continues to run until a termination " "signal is received" msgstr "" #: src/testbed/testbed_api_hosts.c:415 #, fuzzy, c-format msgid "Hosts file %s not found\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/testbed/testbed_api_hosts.c:423 #, fuzzy, c-format msgid "Hosts file %s has no data\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/testbed/testbed_api_hosts.c:430 #, fuzzy, c-format msgid "Hosts file %s cannot be read\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/testbed/testbed_api_hosts.c:570 #, c-format msgid "The function %s is only available when compiled with (--with-ll)\n" msgstr "" #: src/testbed/testbed_api_hosts.c:1586 #, fuzzy, c-format msgid "Adding host %u failed with error: %s\n" msgstr "« %s » thất bại vá»›i mã lá»—i %d: %s\n" #: src/testbed/testbed_api_testbed.c:819 msgid "Linking controllers failed. Exiting" msgstr "" #: src/testbed/testbed_api_testbed.c:988 #, c-format msgid "Host registration failed for a host. Error: %s\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1054 msgid "Controller crash detected. Shutting down.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1143 #, c-format msgid "Host %s cannot start testbed\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1147 msgid "Testbed cannot be started on localhost\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1185 msgid "Cannot start the master controller" msgstr "" #: src/testbed/testbed_api_testbed.c:1203 msgid "Shutting down testbed due to timeout while setup.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1263 msgid "No hosts loaded from LoadLeveler. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1275 msgid "No hosts loaded. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1299 msgid "Specified topology must be supported by testbed" msgstr "" #: src/testbed/testbed_api_testbed.c:1349 #, c-format msgid "" "Maximum number of edges a peer can have in a scale free topology cannot be " "more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_testbed.c:1365 #, c-format msgid "" "The number of edges that can established when adding a new node to scale " "free topology cannot be more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_topology.c:960 #, fuzzy, c-format msgid "Topology file %s not found\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/testbed/testbed_api_topology.c:966 #, fuzzy, c-format msgid "Topology file %s has no data\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/testbed/testbed_api_topology.c:973 #, fuzzy, c-format msgid "Topology file %s cannot be read\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/testbed/testbed_api_topology.c:995 #, fuzzy, c-format msgid "Failed to read peer index from toology file: %s" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/testbed/testbed_api_topology.c:1004 #: src/testbed/testbed_api_topology.c:1028 #, c-format msgid "Value in given topology file: %s out of range\n" msgstr "" #: src/testbed/testbed_api_topology.c:1010 #: src/testbed/testbed_api_topology.c:1034 #, fuzzy, c-format msgid "Failed to read peer index from topology file: %s" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/testbed/testbed_api_topology.c:1016 #: src/testbed/testbed_api_topology.c:1040 msgid "Topology file needs more peers than given ones\n" msgstr "" #: src/testbed/testbed_api_topology.c:1074 #, fuzzy, c-format msgid "Ignoring to connect peer %u to peer %u\n" msgstr "Ä‘ang kết nối đồng đẳng %s:%d tá»›i đồng đẳng %s:%d\n" #: src/testing/gnunet-testing.c:173 #, fuzzy, c-format msgid "Could not extract hostkey %u (offset too large?)\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/testing/gnunet-testing.c:258 #, c-format msgid "Unknown command, use 'q' to quit or 'r' to restart peer\n" msgstr "" #: src/testing/gnunet-testing.c:355 #, fuzzy msgid "create unique configuration files" msgstr "cập nhật má»™t giá trị trong tập tin cấu hình" #: src/testing/gnunet-testing.c:357 msgid "extract hostkey file from pre-computed hostkey list" msgstr "" #: src/testing/gnunet-testing.c:359 #, fuzzy msgid "" "number of unique configuration files to create, or number of the hostkey to " "extract" msgstr "in ra đầu ra tiêu chuẩn má»™t giá trị từ tập tin cấu hình" #: src/testing/gnunet-testing.c:361 #, fuzzy msgid "configuration template" msgstr "Cấu hình đã được lưu." #: src/testing/gnunet-testing.c:363 msgid "run the given service, wait on stdin for 'r' (restart) or 'q' (quit)" msgstr "" #: src/testing/gnunet-testing.c:376 msgid "Command line tool to access the testing library" msgstr "" #: src/testing/list-keys.c:90 msgid "list COUNT number of keys" msgstr "" #: src/testing/list-keys.c:93 msgid "skip COUNT number of keys in the beginning" msgstr "" #: src/testing/testing.c:277 #, c-format msgid "Hostkeys file not found: %s\n" msgstr "" #: src/testing/testing.c:718 #, fuzzy, c-format msgid "Key number %u does not exist\n" msgstr "đặt số trình ná»n cần khởi chạy" #: src/testing/testing.c:1157 #, c-format msgid "" "You attempted to create a testbed with more than %u hosts. Please " "precompute more hostkeys first.\n" msgstr "" #: src/testing/testing.c:1166 #, fuzzy, c-format msgid "Failed to initialize hostkey for peer %u\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/testing/testing.c:1176 msgid "PRIVATE_KEY option in PEER section missing in configuration\n" msgstr "" #: src/testing/testing.c:1189 #, fuzzy msgid "Failed to create configuration for peer (not enough free ports?)\n" msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #: src/testing/testing.c:1203 #, fuzzy, c-format msgid "Cannot open hostkey file `%s': %s\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/testing/testing.c:1215 #, fuzzy, c-format msgid "Failed to write hostkey file for peer %u: %s\n" msgstr "Lá»—i tạo thư mục tạm thá»i." #: src/testing/testing.c:1240 #, fuzzy, c-format msgid "Failed to write configuration file `%s' for peer %u: %s\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/testing/testing.c:1342 #, fuzzy, c-format msgid "Failed to start `%s': %s\n" msgstr "Lá»—i chạy %s: %s %d\n" #: src/testing/testing.c:1706 #, fuzzy, c-format msgid "Failed to load configuration from %s\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/topology/friends.c:100 #, fuzzy, c-format msgid "Syntax error in FRIENDS file at offset %llu, skipping bytes `%.*s'.\n" msgstr "" "Lá»—i cú pháp trong sá»± xác định địa hình há»c, Ä‘ang bá» qua các byte « %s ».\n" #: src/topology/friends.c:154 #, c-format msgid "Directory for file `%s' does not seem to be writable.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:255 msgid "# peers blacklisted" msgstr "" #: src/topology/gnunet-daemon-topology.c:388 #, fuzzy msgid "# connect requests issued to transport" msgstr "# các yêu cầu máy/trình khách lá»— hổng được phun vào" #: src/topology/gnunet-daemon-topology.c:728 #: src/topology/gnunet-daemon-topology.c:813 #, fuzzy msgid "# friends connected" msgstr "# cá»§a các đồng đẳng đã kết nối" #: src/topology/gnunet-daemon-topology.c:993 msgid "Failed to connect to core service, can not manage topology!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1022 #, c-format msgid "Found myself `%s' in friend list (useless, ignored)\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1029 #, fuzzy, c-format msgid "Found friend `%s' in configuration\n" msgstr "" "\n" "Kết thúc cấu hình.\n" #: src/topology/gnunet-daemon-topology.c:1050 msgid "Encountered errors parsing friends list!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1052 #, fuzzy msgid "# friends in configuration" msgstr "" "\n" "Kết thúc cấu hình.\n" #: src/topology/gnunet-daemon-topology.c:1057 msgid "" "Fewer friends specified than required by minimum friend count. Will only " "connect to friends.\n" msgstr "" "Xác định quá ít bạn bè (dưới số tối thiểu). Sẽ chỉ kết nối tá»›i bạn bè.\n" #: src/topology/gnunet-daemon-topology.c:1063 msgid "" "More friendly connections required than target total number of connections.\n" msgstr "Cần thiết nhiá»u kết nối bạn bè hÆ¡n tổng số kết nối đích.\n" #: src/topology/gnunet-daemon-topology.c:1094 #, fuzzy msgid "# HELLO messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/topology/gnunet-daemon-topology.c:1151 #, fuzzy msgid "# HELLO messages gossipped" msgstr "# các thông báo gá»­i Ä‘i bị loại bá»" #: src/topology/gnunet-daemon-topology.c:1290 msgid "GNUnet topology control (maintaining P2P mesh and F2F constraints)" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:271 #, fuzzy, c-format msgid "Adding blacklisting entry for peer `%s'\n" msgstr "Không thể lấy địa chỉ cá»§a đồng đẳng « %s ».\n" #: src/transport/gnunet-service-transport_blacklist.c:279 #, c-format msgid "Adding blacklisting entry for peer `%s':`%s'\n" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:464 #: src/transport/gnunet-service-transport_blacklist.c:745 msgid "# disconnects due to blacklist" msgstr "" #: src/transport/gnunet-service-transport.c:220 #, fuzzy msgid "# bytes payload discarded due to not connected peer" msgstr "# Các quảng cáo đồng đẳng bị há»§y do trá»ng tải" #: src/transport/gnunet-service-transport.c:424 #, fuzzy msgid "# bytes total received" msgstr "# tổng số ná»™i dung lá»— hổng được nhận" #: src/transport/gnunet-service-transport.c:515 #, fuzzy msgid "# bytes payload received" msgstr "# các byte đã giải mã" #: src/transport/gnunet-service-transport.c:686 #, fuzzy, c-format msgid "Could not obtain a valid network for `%s' %s (%s)\n" msgstr "Không thể lấy địa chỉ IP cho giao diện « %s », dùng « %s ».\n" #: src/transport/gnunet-service-transport.c:733 #, c-format msgid "" "Address or session unknown: failed to update properties for peer `%s' plugin " "`%s' address `%s' session %p\n" msgstr "" #: src/transport/gnunet-service-transport.c:1084 #, fuzzy msgid "Transport service is lacking key configuration settings. Exiting.\n" msgstr "Lưu cấu hình ngay bây giá» không?" #: src/transport/gnunet-service-transport_clients.c:432 #, c-format msgid "Dropping message of type %u and size %u, have %u/%u messages pending\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:439 #, fuzzy msgid "# messages dropped due to slow client" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/transport/gnunet-service-transport_clients.c:596 #, c-format msgid "Rejecting control connection from peer `%s', which is not me!\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:737 msgid "# bytes payload dropped (other peer was not connected)" msgstr "" #: src/transport/gnunet-service-transport_clients.c:770 #, fuzzy, c-format msgid "Blacklist refuses connection attempt to peer `%s'\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-service-transport_clients.c:776 #, fuzzy, c-format msgid "Blacklist allows connection attempt to peer `%s'\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-service-transport_clients.c:801 #, fuzzy msgid "# REQUEST CONNECT messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_clients.c:815 #, fuzzy, c-format msgid "Received a request connect message for peer `%s'\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/transport/gnunet-service-transport_clients.c:826 #, fuzzy msgid "# REQUEST DISCONNECT messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_clients.c:840 #, fuzzy, c-format msgid "Received a request disconnect message for peer `%s'\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/transport/gnunet-service-transport_hello.c:181 msgid "# refreshed my HELLO" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1095 #, fuzzy msgid "# DISCONNECT messages sent" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_neighbours.c:1220 #: src/transport/gnunet-service-transport_neighbours.c:1629 #, fuzzy msgid "# bytes in message queue for other peers" msgstr "# các byte thông báo gá»­i Ä‘i bị loại bá»" #: src/transport/gnunet-service-transport_neighbours.c:1225 #, fuzzy msgid "# messages transmitted to other peers" msgstr "# các byte kiểu %d được gá»­i " #: src/transport/gnunet-service-transport_neighbours.c:1230 #, fuzzy msgid "# transmission failures for messages to other peers" msgstr "# các byte thông báo gá»­i Ä‘i bị loại bá»" #: src/transport/gnunet-service-transport_neighbours.c:1287 msgid "# messages timed out while in transport queue" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1343 #, fuzzy msgid "# keepalives sent" msgstr "# các khoá phiên chạy được gá»­i" #: src/transport/gnunet-service-transport_neighbours.c:1376 #, fuzzy msgid "# KEEPALIVE messages discarded (peer unknown)" msgstr "# các thông báo được chắp liá»n" #: src/transport/gnunet-service-transport_neighbours.c:1384 #, fuzzy msgid "# KEEPALIVE messages discarded (no session)" msgstr "# các thông báo được chắp liá»n" #: src/transport/gnunet-service-transport_neighbours.c:1431 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (not connected)" msgstr "# các thông báo được chắp liá»n" #: src/transport/gnunet-service-transport_neighbours.c:1440 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (not expected)" msgstr "# các thông báo được chắp liá»n" #: src/transport/gnunet-service-transport_neighbours.c:1448 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (address changed)" msgstr "# các thông báo được chắp liá»n" #: src/transport/gnunet-service-transport_neighbours.c:1456 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (wrong nonce)" msgstr "# các thông báo được chắp liá»n" #: src/transport/gnunet-service-transport_neighbours.c:1534 #, fuzzy msgid "# messages discarded due to lack of neighbour record" msgstr "# các thông báo được chắp liá»n" #: src/transport/gnunet-service-transport_neighbours.c:1568 #, fuzzy msgid "# bandwidth quota violations by other peers" msgstr "theo dõi gnunetd sá»­ dụng dải thông" #: src/transport/gnunet-service-transport_neighbours.c:1584 msgid "# ms throttling suggested" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1678 #, fuzzy, c-format msgid "" "Failed to send CONNECT message to peer `%s' using address `%s' session %p\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-service-transport_neighbours.c:1705 msgid "# Failed attempts to switch addresses (failed to send CONNECT CONT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1751 #, fuzzy msgid "# SESSION_CONNECT messages sent" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_neighbours.c:1767 #, fuzzy, c-format msgid "Failed to transmit CONNECT message via plugin to %s\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/transport/gnunet-service-transport_neighbours.c:1794 msgid "# Failed attempts to switch addresses (failed to send CONNECT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1844 #, c-format msgid "" "Failed to send CONNECT_ACK message to peer `%s' using address `%s' session " "%p\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1899 #, fuzzy msgid "# CONNECT_ACK messages sent" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_neighbours.c:1914 #, fuzzy, c-format msgid "Failed to transmit CONNECT_ACK message via plugin to %s\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/transport/gnunet-service-transport_neighbours.c:2192 #, fuzzy, c-format msgid "Blacklisting disapproved to connect to peer `%s'\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-service-transport_neighbours.c:2312 #, fuzzy msgid "# CONNECT messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_neighbours.c:2317 #, c-format msgid "CONNECT request from peer `%s' ignored due impending shutdown\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2590 msgid "# Attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3012 #, fuzzy msgid "# Failed attempts to switch addresses (no response)" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/transport/gnunet-service-transport_neighbours.c:3107 #, fuzzy msgid "# CONNECT_ACK messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_neighbours.c:3115 #, fuzzy msgid "# unexpected CONNECT_ACK messages (no peer)" msgstr "gá»­i ÄẾM thông báo" #: src/transport/gnunet-service-transport_neighbours.c:3129 #: src/transport/gnunet-service-transport_neighbours.c:3164 #, fuzzy msgid "# unexpected CONNECT_ACK messages (not ready)" msgstr "gá»­i ÄẾM thông báo" #: src/transport/gnunet-service-transport_neighbours.c:3176 #, fuzzy msgid "# unexpected CONNECT_ACK messages (waiting on ATS)" msgstr "gá»­i ÄẾM thông báo" #: src/transport/gnunet-service-transport_neighbours.c:3200 msgid "# Successful attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3208 #, fuzzy msgid "# unexpected CONNECT_ACK messages (disconnecting)" msgstr "gá»­i ÄẾM thông báo" #: src/transport/gnunet-service-transport_neighbours.c:3396 #, fuzzy msgid "# SESSION_ACK messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_neighbours.c:3424 #, fuzzy msgid "# unexpected SESSION_ACK messages" msgstr "# các thông báo PONG đã mật mã được gá»­i" #: src/transport/gnunet-service-transport_neighbours.c:3490 msgid "# SET QUOTA messages ignored (no such peer)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3505 msgid "# disconnects due to quota of 0" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3545 msgid "# disconnect messages ignored (malformed)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3551 #, fuzzy msgid "# DISCONNECT messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/gnunet-service-transport_neighbours.c:3560 msgid "# disconnect messages ignored (timestamp)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3687 #, fuzzy msgid "# disconnected from peer upon explicit request" msgstr "# các yêu cầu lá»— hổng bị bá» do trá»ng tải" #: src/transport/gnunet-service-transport_plugins.c:120 msgid "Transport service is lacking NEIGHBOUR_LIMIT option.\n" msgstr "" #: src/transport/gnunet-service-transport_plugins.c:178 #: src/transport/gnunet-service-transport_plugins.c:186 #: src/transport/gnunet-service-transport_plugins.c:194 #: src/transport/gnunet-service-transport_plugins.c:202 #: src/transport/gnunet-service-transport_plugins.c:210 #: src/transport/gnunet-service-transport_plugins.c:218 #: src/transport/gnunet-service-transport_plugins.c:226 #: src/transport/gnunet-service-transport_plugins.c:234 #: src/transport/gnunet-service-transport_plugins.c:242 #: src/transport/gnunet-service-transport_plugins.c:250 #: src/transport/gnunet-service-transport_plugins.c:258 #, fuzzy, c-format msgid "Missing function `%s' in transport plugin for `%s'\n" msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #: src/transport/gnunet-service-transport_plugins.c:265 #, fuzzy, c-format msgid "Did not load plugin `%s' due to missing functions\n" msgstr "Lá»—i nạp phần bổ sung « %s » tại %s:%d. Äang há»§y nạp phần bổ sung.\n" #: src/transport/gnunet-service-transport_validation.c:488 msgid "# address records discarded" msgstr "" #: src/transport/gnunet-service-transport_validation.c:558 #, c-format msgid "" "Not transmitting `%s' with `%s', message too big (%u bytes!). This should " "not happen.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:616 #, fuzzy msgid "# PING without HELLO messages sent" msgstr "# các thông báo PONG nhập thô được gá»­i" #: src/transport/gnunet-service-transport_validation.c:722 msgid "# address revalidations started" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1011 #, fuzzy msgid "# PING message for different peer received" msgstr "# các thông báo PING được tạo" #: src/transport/gnunet-service-transport_validation.c:1062 #, c-format msgid "Plugin `%s' not available, cannot confirm having this address\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1072 msgid "# failed address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1075 #, c-format msgid "Address `%s' is not one of my addresses, not confirming PING\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1083 msgid "# successful address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1095 #, c-format msgid "" "Not confirming PING from peer `%s' with address `%s' since I cannot confirm " "having this address.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1103 #, c-format msgid "Received a PING message with validation bug from `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1157 #, fuzzy, c-format msgid "Failed to create PONG signature for peer `%s'\n" msgstr "Không thể tạo miá»n tên.\n" #: src/transport/gnunet-service-transport_validation.c:1206 msgid "# PONGs unicast via reliable transport" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1215 msgid "# PONGs multicast to all available addresses" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1356 msgid "# PONGs dropped, no matching pending validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1371 msgid "# PONGs dropped, signature expired" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1493 #, fuzzy, c-format msgid "Validation received new %s message for peer `%s' with size %u\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/transport/gnunet-service-transport_validation.c:1500 #, fuzzy, c-format msgid "Adding `%s' without addresses for peer `%s'\n" msgstr "Không thể lấy địa chỉ cá»§a đồng đẳng « %s ».\n" #: src/transport/gnunet-transport.c:367 #, fuzzy, c-format msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n" msgstr "Äang thá»­ tải danh sách các máy xuống « %s »\n" #: src/transport/gnunet-transport.c:375 #, fuzzy, c-format msgid "Received %llu bytes/s (%llu bytes in %s)\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/transport/gnunet-transport.c:415 #, fuzzy, c-format msgid "Failed to connect to `%s'\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-transport.c:428 #, fuzzy, c-format msgid "Failed to resolve address for peer `%s'\n" msgstr "Lá»—i đóng kết đến cổng %s %d.\n" #: src/transport/gnunet-transport.c:438 #, fuzzy msgid "Failed to list connections, timeout occured\n" msgstr "Không kết nối được đến trình ná»n gnunetd." #: src/transport/gnunet-transport.c:559 #, fuzzy, c-format msgid "" "Peer `%s' %s %s\n" "\t%s%s\n" "\t%s%s\n" "\t%s%s\n" msgstr "Tôi là đồng đẳng « %s ».\n" #: src/transport/gnunet-transport.c:586 #, fuzzy, c-format msgid "Peer `%s' %s `%s' \n" msgstr "Tôi là đồng đẳng « %s ».\n" #: src/transport/gnunet-transport.c:712 msgid "No transport plugins configured, peer will never communicate\n" msgstr "" #: src/transport/gnunet-transport.c:726 #, c-format msgid "No port configured for plugin `%s', cannot test it\n" msgstr "" #: src/transport/gnunet-transport.c:789 #, fuzzy, c-format msgid "Transmitting %u bytes to %s\n" msgstr "Äang thá»­ tải danh sách các máy xuống « %s »\n" #: src/transport/gnunet-transport.c:810 #, fuzzy, c-format msgid "Successfully connected to `%s'\n" msgstr "Không đủ quyá»n cho « %s ».\n" #: src/transport/gnunet-transport.c:834 #, c-format msgid "" "Successfully connected to `%s', starting to send benchmark data in %u Kb " "blocks\n" msgstr "" #: src/transport/gnunet-transport.c:865 #, fuzzy, c-format msgid "Successfully disconnected from `%s'\n" msgstr "Không đủ quyá»n cho « %s ».\n" #: src/transport/gnunet-transport.c:888 #, fuzzy, c-format msgid "Disconnected from peer `%s' while benchmarking\n" msgstr "« %.*s » được kết nối tá»›i « %.*s ».\n" #: src/transport/gnunet-transport.c:950 #, fuzzy, c-format msgid "Received %u bytes from %s\n" msgstr "Nhận yêu cầu định tuyến\n" #: src/transport/gnunet-transport.c:975 #, c-format msgid "Peer `%s': %s %s in state `%s' until %s\n" msgstr "" #: src/transport/gnunet-transport.c:986 #, fuzzy, c-format msgid "Peer `%s': %s %s\n" msgstr "Tôi là đồng đẳng « %s ».\n" #: src/transport/gnunet-transport.c:1197 src/transport/gnunet-transport.c:1222 #, fuzzy msgid "Failed to send connect request to transport service\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-transport.c:1266 #, c-format msgid "" "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, " "%s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1274 #, c-format msgid "" "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1293 src/transport/gnunet-transport.c:1323 #: src/transport/gnunet-transport.c:1353 src/transport/gnunet-transport.c:1376 #: src/transport/gnunet-transport.c:1419 #, fuzzy msgid "Failed to connect to transport service\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-transport.c:1302 src/transport/gnunet-transport.c:1332 #: src/transport/gnunet-transport.c:1362 #, fuzzy msgid "Failed to send request to transport service\n" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-transport.c:1381 msgid "Starting to receive benchmark data\n" msgstr "" #: src/transport/gnunet-transport.c:1465 #, fuzzy msgid "print information for all peers (instead of only connected peers )" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/transport/gnunet-transport.c:1468 msgid "measure how fast we are receiving data from all peers (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1471 #, fuzzy msgid "connect to a peer" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-transport.c:1474 #, fuzzy msgid "disconnect to a peer" msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/gnunet-transport.c:1477 #, fuzzy msgid "print information for all pending validations " msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/transport/gnunet-transport.c:1480 #, fuzzy msgid "print information for all pending validations continously" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/transport/gnunet-transport.c:1483 #, fuzzy msgid "provide information about all current connections (once)" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/transport/gnunet-transport.c:1489 #, fuzzy msgid "" "provide information about all connects and disconnect events (continuously)" msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #: src/transport/gnunet-transport.c:1491 #, fuzzy msgid "do not resolve hostnames" msgstr "không quyết định các tên máy" #: src/transport/gnunet-transport.c:1493 msgid "peer identity" msgstr "" #: src/transport/gnunet-transport.c:1495 msgid "send data for benchmarking to the other peer (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1498 msgid "test transport configuration (involves external server)" msgstr "" #: src/transport/gnunet-transport.c:1507 #, fuzzy msgid "Direct access to transport service." msgstr "Lá»—i kết nối đến gnunetd.\n" #: src/transport/plugin_transport_bluetooth.c:621 msgid "# Bluetooth ACKs sent" msgstr "" #: src/transport/plugin_transport_bluetooth.c:640 #, fuzzy msgid "# Bluetooth messages defragmented" msgstr "# các thông báo được chắp liá»n" #: src/transport/plugin_transport_bluetooth.c:686 #: src/transport/plugin_transport_bluetooth.c:737 #: src/transport/plugin_transport_bluetooth.c:1942 #, fuzzy msgid "# Bluetooth sessions allocated" msgstr "# các khoá phiên chạy được chấp nhận" #: src/transport/plugin_transport_bluetooth.c:837 #, fuzzy msgid "# Bluetooth message fragments sent" msgstr "# các thông báo bị tế phân" #: src/transport/plugin_transport_bluetooth.c:861 msgid "# Bluetooth messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_bluetooth.c:969 #: src/transport/plugin_transport_bluetooth.c:1054 #: src/transport/plugin_transport_bluetooth.c:1944 #, fuzzy msgid "# Bluetooth MAC endpoints allocated" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/transport/plugin_transport_bluetooth.c:1307 #, fuzzy msgid "# HELLO messages received via Bluetooth" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_bluetooth.c:1331 #, fuzzy msgid "# fragments received via Bluetooth" msgstr "# các mảnh bị loại bá»" #: src/transport/plugin_transport_bluetooth.c:1341 #, fuzzy msgid "# ACKs received via Bluetooth" msgstr "# các byte đã nhận qua TCP" #: src/transport/plugin_transport_bluetooth.c:1401 #, fuzzy msgid "# Bluetooth DATA messages discarded due to CRC32 error" msgstr "# các thông báo được chắp liá»n" #: src/transport/plugin_transport_bluetooth.c:1512 #, fuzzy msgid "# DATA messages received via Bluetooth" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_bluetooth.c:1547 #, fuzzy msgid "# Bluetooth DATA messages processed" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_bluetooth.c:1610 #, fuzzy msgid "# HELLO beacons sent via Bluetooth" msgstr "# các byte đã gá»­i qua UDP" #: src/transport/plugin_transport_bluetooth.c:1723 msgid "Bluetooth address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1923 #, c-format msgid "Helper binary `%s' not SUID, cannot run bluetooth transport\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1622 #, c-format msgid "Could not initialize curl multi handle, failed to start %s plugin!\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1697 #: src/transport/plugin_transport_http_server.c:3007 #, fuzzy, c-format msgid "Shutting down plugin `%s'\n" msgstr "Äang nạp các truyá»n tải « %s »\n" #: src/transport/plugin_transport_http_client.c:1722 #: src/transport/plugin_transport_http_server.c:3063 #, fuzzy, c-format msgid "Shutdown for plugin `%s' complete\n" msgstr "Tải lên « %s » hoàn thành, địa chỉ URI là « %s ».\n" #: src/transport/plugin_transport_http_client.c:1750 #: src/transport/plugin_transport_http_server.c:2907 #, fuzzy, c-format msgid "Maximum number of connections is %u\n" msgstr "tăng sổ tối Ä‘a các kết nối TCP/IP" #: src/transport/plugin_transport_http_server.c:1402 #, c-format msgid "" "Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data " "size %u\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1663 #, c-format msgid "Accepting connection (%u of %u) from `%s'\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1671 #, c-format msgid "" "Server reached maximum number connections (%u), rejecting new connection\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1958 msgid "" "Could not create a new TLS certificate, program `gnunet-transport-" "certificate-creation' could not be started!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1982 #, c-format msgid "No usable TLS certificate found and creating one at `%s/%s' failed!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2405 #, fuzzy msgid "Require valid port number for service in configuration!\n" msgstr "Lá»—i lưu cấu hình." #: src/transport/plugin_transport_http_server.c:2437 src/util/service.c:698 #, fuzzy, c-format msgid "Failed to resolve `%s': %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/transport/plugin_transport_http_server.c:2454 src/util/service.c:715 #, fuzzy, c-format msgid "Failed to find %saddress for `%s'.\n" msgstr "Lá»—i đóng kết đến cổng %s %d.\n" #: src/transport/plugin_transport_http_server.c:2565 #, c-format msgid "Found %u addresses to report to NAT service\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2637 msgid "Disabling IPv6 since it is not supported on this system!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2730 #, c-format msgid "IPv4 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2744 #, c-format msgid "IPv6 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2751 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2762 #, fuzzy msgid "Port is required! Fix in configuration\n" msgstr "" "\n" "Kết thúc cấu hình.\n" #: src/transport/plugin_transport_http_server.c:2769 #, fuzzy, c-format msgid "Using port %u\n" msgstr "Äang thá»­ nghiệm (các) truyá»n tải %s\n" #: src/transport/plugin_transport_http_server.c:2784 #, fuzzy, c-format msgid "Specific IPv4 address `%s' in configuration file is invalid!\n" msgstr "Äang thá»­ dùng tập tin « %s » cho cấu hình MySQL.\n" #: src/transport/plugin_transport_http_server.c:2794 #, fuzzy, c-format msgid "Binding to IPv4 address %s\n" msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n" #: src/transport/plugin_transport_http_server.c:2815 #, fuzzy, c-format msgid "Specific IPv6 address `%s' in configuration file is invalid!\n" msgstr "Äang thá»­ dùng tập tin « %s » cho cấu hình MySQL.\n" #: src/transport/plugin_transport_http_server.c:2825 #, fuzzy, c-format msgid "Binding to IPv6 address %s\n" msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n" #: src/transport/plugin_transport_http_server.c:2877 #, fuzzy, c-format msgid "Using external hostname `%s'\n" msgstr "Äang bắt đầu tài vỠ« %s »\n" #: src/transport/plugin_transport_http_server.c:2893 #, fuzzy, c-format msgid "Notifying transport only about hostname `%s'\n" msgstr "không quyết định các tên máy" #: src/transport/plugin_transport_smtp.c:223 #, c-format msgid "Received malformed message via %s. Ignored.\n" msgstr "Nhận được thông báo dạng sai qua %s. Bị bá» qua.\n" #: src/transport/plugin_transport_smtp.c:310 msgid "SMTP filter string to invalid, lacks ': '\n" msgstr "Chuá»—i lá»c vào SMTP không hợp lệ, còn thiếu « : »\n" #: src/transport/plugin_transport_smtp.c:319 #, c-format msgid "SMTP filter string to long, capped to `%s'\n" msgstr "Chuá»—i lá»c vào SMTP quá dài, tối Ä‘a « %s »\n" #: src/transport/plugin_transport_smtp.c:414 #: src/transport/plugin_transport_smtp.c:424 #: src/transport/plugin_transport_smtp.c:437 #: src/transport/plugin_transport_smtp.c:456 #: src/transport/plugin_transport_smtp.c:479 #: src/transport/plugin_transport_smtp.c:487 #: src/transport/plugin_transport_smtp.c:500 #: src/transport/plugin_transport_smtp.c:511 #, c-format msgid "SMTP: `%s' failed: %s.\n" msgstr "SMTP: « %s » bị lá»—i: %s\n" #: src/transport/plugin_transport_smtp.c:652 msgid "No email-address specified, can not start SMTP transport.\n" msgstr "Chưa ghi rõ địa chỉ thư Ä‘iện tá»­ nên không tạo được truyá»n tải SMTP.\n" #: src/transport/plugin_transport_smtp.c:664 msgid "# bytes received via SMTP" msgstr "# các byte đã nhận qua SMTP" #: src/transport/plugin_transport_smtp.c:665 msgid "# bytes sent via SMTP" msgstr "# các byte đã gá»­i qua SMTP" #: src/transport/plugin_transport_smtp.c:667 msgid "# bytes dropped by SMTP (outgoing)" msgstr "# các byte loại Ä‘i bởi SMTP (Ä‘i ra)" #: src/transport/plugin_transport_tcp.c:555 #, fuzzy, c-format msgid "Unexpected address length: %u bytes\n" msgstr "Gặp sá»± kiện bất thưá»ng: %d\n" #: src/transport/plugin_transport_tcp.c:762 #: src/transport/plugin_transport_tcp.c:928 #: src/transport/plugin_transport_tcp.c:2005 #: src/transport/plugin_transport_tcp.c:2558 #, fuzzy msgid "# TCP sessions active" msgstr "# các khoá phiên chạy được chấp nhận" #: src/transport/plugin_transport_tcp.c:795 #: src/transport/plugin_transport_tcp.c:921 #: src/transport/plugin_transport_tcp.c:1009 #: src/transport/plugin_transport_tcp.c:1056 #: src/transport/plugin_transport_tcp.c:1219 #: src/transport/plugin_transport_tcp.c:1237 #, fuzzy msgid "# bytes currently in TCP buffers" msgstr "# các byte đã gừi qua TCP" #: src/transport/plugin_transport_tcp.c:798 #, fuzzy msgid "# bytes discarded by TCP (disconnect)" msgstr "# các byte loại Ä‘i bởi TCP (Ä‘i ra)" #: src/transport/plugin_transport_tcp.c:1012 #, fuzzy msgid "# bytes discarded by TCP (timeout)" msgstr "# các byte loại Ä‘i bởi TCP (Ä‘i ra)" #: src/transport/plugin_transport_tcp.c:1059 #, fuzzy msgid "# bytes transmitted via TCP" msgstr "# các byte được gá»­i" #: src/transport/plugin_transport_tcp.c:1193 #, c-format msgid "Trying to send with invalid session %p\n" msgstr "" #: src/transport/plugin_transport_tcp.c:1462 msgid "# requests to create session with invalid address" msgstr "" #: src/transport/plugin_transport_tcp.c:1567 msgid "# transport-service disconnect requests for TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:2055 #, fuzzy msgid "# TCP WELCOME messages received" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_tcp.c:2215 msgid "# bytes received via TCP" msgstr "# các byte đã nhận qua TCP" #: src/transport/plugin_transport_tcp.c:2279 msgid "# network-level TCP disconnect events" msgstr "" #: src/transport/plugin_transport_tcp.c:2437 src/util/service.c:582 #: src/util/service.c:588 #, c-format msgid "Require valid port number for service `%s' in configuration!\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2451 #, fuzzy msgid "Failed to start service.\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/transport/plugin_transport_tcp.c:2547 #, c-format msgid "TCP transport listening on port %llu\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2551 msgid "TCP transport not listening on any port (client only)\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2554 #, c-format msgid "TCP transport advertises itself as being on port %llu\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:167 #, fuzzy msgid "# IPv6 multicast HELLO beacons received via udp" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_udp_broadcasting.c:210 #, fuzzy msgid "# IPv4 broadcast HELLO beacons received via udp" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_udp_broadcasting.c:603 msgid "" "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:626 #, c-format msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n" msgstr "" #: src/transport/plugin_transport_udp.c:1513 #, c-format msgid "" "Trying to create session for address of unexpected length %u (should be %u " "or %u)\n" msgstr "" #: src/transport/plugin_transport_udp.c:2602 #, c-format msgid "" "UDP could not transmit message to `%s': Network seems down, please check " "your network configuration\n" msgstr "" #: src/transport/plugin_transport_udp.c:2616 msgid "" "UDP could not transmit IPv6 message! Please check your network configuration " "and disable IPv6 if your connection does not have a global IPv6 address\n" msgstr "" #: src/transport/plugin_transport_udp.c:2961 #, fuzzy msgid "Failed to open UDP sockets\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/transport/plugin_transport_udp.c:3056 #, c-format msgid "Given `%s' option is out of range: %llu > %u\n" msgstr "" #: src/transport/plugin_transport_udp.c:3097 #, fuzzy, c-format msgid "Invalid IPv6 address: `%s'\n" msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n" #: src/transport/plugin_transport_udp.c:3168 #, fuzzy msgid "Failed to create network sockets, plugin failed\n" msgstr "Không thể tạo miá»n tên.\n" #: src/transport/plugin_transport_unix.c:1321 #, fuzzy, c-format msgid "Cannot create path to `%s'\n" msgstr "Không thể tạo miá»n tên.\n" #: src/transport/plugin_transport_unix.c:1652 #, fuzzy msgid "No UNIXPATH given in configuration!\n" msgstr "Lá»—i lưu cấu hình." #: src/transport/plugin_transport_unix.c:1688 #, fuzzy msgid "Failed to open UNIX listen socket\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/transport/plugin_transport_wlan.c:620 msgid "# WLAN ACKs sent" msgstr "" #: src/transport/plugin_transport_wlan.c:639 #, fuzzy msgid "# WLAN messages defragmented" msgstr "# các thông báo được chắp liá»n" #: src/transport/plugin_transport_wlan.c:688 #: src/transport/plugin_transport_wlan.c:772 #: src/transport/plugin_transport_wlan.c:1948 #, fuzzy msgid "# WLAN sessions allocated" msgstr "# các khoá phiên chạy được chấp nhận" #: src/transport/plugin_transport_wlan.c:876 #, fuzzy msgid "# WLAN message fragments sent" msgstr "# các thông báo bị tế phân" #: src/transport/plugin_transport_wlan.c:900 msgid "# WLAN messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_wlan.c:1008 #: src/transport/plugin_transport_wlan.c:1098 #: src/transport/plugin_transport_wlan.c:1950 #, fuzzy msgid "# WLAN MAC endpoints allocated" msgstr "# các yêu cầu get (lấy) dht được nhận" #: src/transport/plugin_transport_wlan.c:1302 #, fuzzy msgid "# HELLO messages received via WLAN" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_wlan.c:1326 #, fuzzy msgid "# fragments received via WLAN" msgstr "# các mảnh bị loại bá»" #: src/transport/plugin_transport_wlan.c:1336 #, fuzzy msgid "# ACKs received via WLAN" msgstr "# các byte đã nhận qua TCP" #: src/transport/plugin_transport_wlan.c:1396 #, fuzzy msgid "# WLAN DATA messages discarded due to CRC32 error" msgstr "# các thông báo được chắp liá»n" #: src/transport/plugin_transport_wlan.c:1518 #, fuzzy msgid "# DATA messages received via WLAN" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_wlan.c:1553 #, fuzzy msgid "# WLAN DATA messages processed" msgstr "# các thông báo PONG đã mật mã được nhận" #: src/transport/plugin_transport_wlan.c:1616 #, fuzzy msgid "# HELLO beacons sent via WLAN" msgstr "# các byte đã gá»­i qua UDP" #: src/transport/plugin_transport_wlan.c:1729 msgid "WLAN address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_wlan.c:1929 #, c-format msgid "Helper binary `%s' not SUID, cannot run WLAN transport\n" msgstr "" #: src/transport/transport_api.c:739 #, fuzzy, c-format msgid "Received unexpected message of type %u in %s:%u\n" msgstr "Nhận được thông báo bị há»ng từ đồng đẳng « %s » trong %s:%d.\n" #: src/transport/transport-testing.c:584 #, fuzzy msgid "Failed to initialize testing library!\n" msgstr "Lá»—i sÆ¡ khởi dịch vụ « %s ».\n" #: src/tun/regex.c:129 #, c-format msgid "Bad mask: %d\n" msgstr "" #: src/util/bio.c:170 src/util/bio.c:178 #, fuzzy, c-format msgid "Error reading `%s': %s" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/util/bio.c:180 msgid "End of file" msgstr "" #: src/util/bio.c:237 #, c-format msgid "Error reading length of string `%s'" msgstr "" #: src/util/bio.c:247 #, c-format msgid "String `%s' longer than allowed (%u > %u)" msgstr "" #: src/util/bio.c:293 #, c-format msgid "Serialized metadata `%s' larger than allowed (%u>%u)" msgstr "" #: src/util/bio.c:307 #, c-format msgid "Metadata `%s' failed to deserialize" msgstr "" #: src/util/client.c:261 src/util/client.c:858 src/util/service.c:619 #, c-format msgid "UNIXPATH `%s' too long, maximum length is %llu\n" msgstr "" #: src/util/client.c:265 src/util/client.c:863 src/util/service.c:623 #, fuzzy, c-format msgid "Using `%s' instead\n" msgstr "%s: tùy chá»n « %s » là mÆ¡ hồ\n" #: src/util/client.c:360 #, c-format msgid "" "Could not determine valid hostname and port for service `%s' from " "configuration.\n" msgstr "" #: src/util/client.c:368 #, c-format msgid "Need a non-empty hostname for service `%s'.\n" msgstr "" #: src/util/client.c:1008 #, fuzzy, c-format msgid "Could not connect to service `%s', configuration broken.\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/util/client.c:1020 #, fuzzy, c-format msgid "Failure to transmit request to service `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/util/client.c:1303 msgid "Could not submit request, not expecting to receive a response.\n" msgstr "" #: src/util/common_logging.c:254 src/util/common_logging.c:1039 msgid "DEBUG" msgstr "Gá»  Lá»–I" #: src/util/common_logging.c:256 src/util/common_logging.c:1037 msgid "INFO" msgstr "TIN" #: src/util/common_logging.c:258 src/util/common_logging.c:1035 msgid "WARNING" msgstr "CẢNH BÃO" #: src/util/common_logging.c:260 src/util/common_logging.c:1033 msgid "ERROR" msgstr "Lá»–I" #: src/util/common_logging.c:262 src/util/common_logging.c:1041 msgid "NONE" msgstr "" #: src/util/common_logging.c:391 #, fuzzy, c-format msgid "Failed to create or access directory for log file `%s'\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/util/common_logging.c:817 #, fuzzy, c-format msgid "Message `%.*s' repeated %u times in the last %s\n" msgstr "Thông Ä‘iệp « %.*s » đã lặp lại %u lần trong %llu giây trước\n" #: src/util/common_logging.c:1042 msgid "INVALID" msgstr "" #: src/util/common_logging.c:1157 msgid "unknown address" msgstr "" #: src/util/common_logging.c:1196 msgid "invalid address" msgstr "" #: src/util/common_logging.c:1214 #, fuzzy, c-format msgid "Configuration fails to specify option `%s' in section `%s'!\n" msgstr "" "Cấu hình không thá»a mãn các ràng buá»™c cá»§a tập tin đặc tả cấu hình « %s ».\n" #: src/util/common_logging.c:1235 #, fuzzy, c-format msgid "" "Configuration specifies invalid value for option `%s' in section `%s': %s\n" msgstr "" "Cấu hình không thá»a mãn các ràng buá»™c cá»§a tập tin đặc tả cấu hình « %s ».\n" #: src/util/configuration.c:288 #, fuzzy, c-format msgid "Syntax error while deserializing in line %u\n" msgstr "Gặp lá»—i cú pháp trong tập tin cấu hình « %s » tại dòng %d.\n" #: src/util/configuration.c:996 #, c-format msgid "" "Configuration value '%s' for '%s' in section '%s' is not in set of legal " "choices\n" msgstr "" "Giá trị cấu hình « %s » cho « %s » trong phần « %s » không phải nằm trong " "tập hợp các sá»± chá»n được phép\n" #: src/util/configuration.c:1066 #, c-format msgid "Recursive expansion suspected, aborting $-expansion for term `%s'\n" msgstr "" #: src/util/configuration.c:1098 #, fuzzy, c-format msgid "Missing closing `%s' in option `%s'\n" msgstr "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #: src/util/configuration.c:1172 #, c-format msgid "" "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined " "as an environmental variable\n" msgstr "" #: src/util/connection.c:423 #, fuzzy, c-format msgid "Access denied to `%s'\n" msgstr "Không đủ quyá»n cho « %s ».\n" #: src/util/connection.c:438 #, c-format msgid "Accepting connection from `%s': %p\n" msgstr "" #: src/util/connection.c:553 #, fuzzy, c-format msgid "" "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n" msgstr "Lá»—i thiết lập kết nối vá»›i đồng đẳng.\n" #: src/util/connection.c:751 src/util/connection.c:919 #, fuzzy, c-format msgid "Trying to connect to `%s' (%p)\n" msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #: src/util/connection.c:910 #, fuzzy, c-format msgid "Attempt to connect to `%s' failed\n" msgstr " Lá»—i kết nối\n" #: src/util/container_bloomfilter.c:531 #, c-format msgid "" "Size of file on disk is incorrect for this Bloom filter (want %llu, have " "%llu)\n" msgstr "" #: src/util/crypto_ecc.c:702 src/util/crypto_ecc.c:740 #: src/util/crypto_ecc.c:858 src/util/crypto_ecc.c:896 #, fuzzy, c-format msgid "Could not acquire lock on file `%s': %s...\n" msgstr "Lá»—i mở tập tin theo dõi « %s »: %s\n" #: src/util/crypto_ecc.c:707 src/util/crypto_ecc.c:863 #, fuzzy msgid "Creating a new private key. This may take a while.\n" msgstr "Äang tạo khoá máy má»›i (có thể hÆ¡i lâu).\n" #: src/util/crypto_ecc.c:744 src/util/crypto_ecc.c:900 msgid "This may be ok if someone is currently generating a private key.\n" msgstr "" #: src/util/crypto_ecc.c:774 src/util/crypto_ecc.c:930 #, c-format msgid "" "When trying to read key file `%s' I found %u bytes but I need at least %u.\n" msgstr "" #: src/util/crypto_ecc.c:778 src/util/crypto_ecc.c:934 msgid "This may be ok if someone is currently generating a key.\n" msgstr "" #: src/util/crypto_ecc.c:1016 #, fuzzy msgid "Could not load peer's private key\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/util/crypto_ecc.c:1120 #, fuzzy, c-format msgid "ECC signing failed at %s:%d: %s\n" msgstr "%s bị lá»—i tại %s:%d: « %s »\n" #: src/util/crypto_ecc.c:1170 #, fuzzy, c-format msgid "EdDSA signing failed at %s:%d: %s\n" msgstr "%s bị lá»—i tại %s:%d: « %s »\n" #: src/util/crypto_ecc.c:1244 #, fuzzy, c-format msgid "ECDSA signature verification failed at %s:%d: %s\n" msgstr "Lá»—i thẩm tra chữ ký RSA tại %s:%d: %s\n" #: src/util/crypto_ecc.c:1301 #, fuzzy, c-format msgid "EdDSA signature verification failed at %s:%d: %s\n" msgstr "Lá»—i thẩm tra chữ ký RSA tại %s:%d: %s\n" #: src/util/crypto_random.c:284 #, c-format msgid "libgcrypt has not the expected version (version %s is required).\n" msgstr "libgcrypt không có phiên bản mong đợi (yêu cầu phiên bản %s).\n" #: src/util/disk.c:1184 #, c-format msgid "Expected `%s' to be a directory!\n" msgstr "Mong đợi « %s » là má»™t thư mục.\n" #: src/util/disk.c:1546 src/util/service.c:1318 #, c-format msgid "Cannot obtain information about user `%s': %s\n" msgstr "Không thể lấy thông tin vá» ngưá»i dùng « %s »: %s\n" #: src/util/getopt.c:568 #, c-format msgid "%s: option `%s' is ambiguous\n" msgstr "%s: tùy chá»n « %s » là mÆ¡ hồ\n" #: src/util/getopt.c:592 #, c-format msgid "%s: option `--%s' does not allow an argument\n" msgstr "%s: tùy chá»n « --%s » không cho phép đối số\n" #: src/util/getopt.c:597 #, c-format msgid "%s: option `%c%s' does not allow an argument\n" msgstr "%s: tùy chá»n « %c%s » không cho phép đối số\n" #: src/util/getopt.c:614 src/util/getopt.c:781 #, c-format msgid "%s: option `%s' requires an argument\n" msgstr "%s: tùy chá»n « %s » cần thiết đối số\n" #: src/util/getopt.c:643 #, c-format msgid "%s: unrecognized option `--%s'\n" msgstr "%s: không nhận ra tùy chá»n « --%s »\n" #: src/util/getopt.c:647 #, c-format msgid "%s: unrecognized option `%c%s'\n" msgstr "%s: không nhận ra tùy chá»n « %c%s »\n" #: src/util/getopt.c:672 #, c-format msgid "%s: illegal option -- %c\n" msgstr "%s: tùy chá»n không được phép -- %c\n" #: src/util/getopt.c:674 #, c-format msgid "%s: invalid option -- %c\n" msgstr "%s: tùy chá»n không hợp lệ -- %c\n" #: src/util/getopt.c:702 src/util/getopt.c:829 #, c-format msgid "%s: option requires an argument -- %c\n" msgstr "%s: tùy chá»n cần thiết đối số -- %c\n" #: src/util/getopt.c:750 #, c-format msgid "%s: option `-W %s' is ambiguous\n" msgstr "%s: tùy chá»n « -W %s » là mÆ¡ hồ\n" #: src/util/getopt.c:768 #, c-format msgid "%s: option `-W %s' does not allow an argument\n" msgstr "%s: tùy chá»n « -W %s » không cho phép đối số\n" #: src/util/getopt.c:933 #, fuzzy, c-format msgid "Use %s to get a list of options.\n" msgstr "" "Hãy sá»­ dụng câu lệnh trợ giúp « --help » để xem danh sách các tùy chá»n.\n" #: src/util/getopt_helpers.c:84 #, c-format msgid "" "Arguments mandatory for long options are also mandatory for short options.\n" msgstr "" "Má»i đối số bắt buá»™c phải sá»­ dụng vá»›i tùy chá»n dài cÅ©ng bắt buá»™c vá»›i tùy chá»n " "ngắn.\n" #: src/util/getopt_helpers.c:268 src/util/getopt_helpers.c:326 #, c-format msgid "You must pass a number to the `%s' option.\n" msgstr "Phải gá»­i má»™t con số cho tùy chá»n « %s ».\n" #: src/util/getopt_helpers.c:298 #, fuzzy, c-format msgid "You must pass relative time to the `%s' option.\n" msgstr "Phải gá»­i má»™t con số cho tùy chá»n « %s ».\n" #: src/util/gnunet-config.c:90 #, fuzzy, c-format msgid "--section argument is required\n" msgstr "đặt tên hiệu cần dùng (cần thiết)" #: src/util/gnunet-config.c:133 #, c-format msgid "--option argument required to set value\n" msgstr "" #: src/util/gnunet-config.c:160 msgid "obtain option of value as a filename (with $-expansion)" msgstr "" #: src/util/gnunet-config.c:163 msgid "name of the section to access" msgstr "" #: src/util/gnunet-config.c:166 msgid "name of the option to access" msgstr "" #: src/util/gnunet-config.c:169 msgid "value to set" msgstr "" #: src/util/gnunet-config.c:178 #, fuzzy msgid "Manipulate GNUnet configuration files" msgstr "cập nhật má»™t giá trị trong tập tin cấu hình" #: src/util/gnunet-ecc.c:75 #, fuzzy, c-format msgid "Failed to open `%s': %s\n" msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #: src/util/gnunet-ecc.c:81 #, c-format msgid "Generating %u keys, please wait" msgstr "" #: src/util/gnunet-ecc.c:97 #, fuzzy, c-format msgid "" "\n" "Failed to write to `%s': %s\n" msgstr "Lá»—i chạy %s: %s %d\n" #: src/util/gnunet-ecc.c:107 #, c-format msgid "" "\n" "Finished!\n" msgstr "" #: src/util/gnunet-ecc.c:110 #, c-format msgid "" "\n" "Error, %u keys not generated\n" msgstr "" #: src/util/gnunet-ecc.c:199 #, fuzzy, c-format msgid "Hostkeys file `%s' not found\n" msgstr "Khoá phiên chạy từ đồng đẳng « %s » không thể được thẩm tra.\n" #: src/util/gnunet-ecc.c:210 #, fuzzy, c-format msgid "Hostkeys file `%s' is empty\n" msgstr "Äịnh dạng cá»§a tập tin « %s » là không hợp lệ.\n" #: src/util/gnunet-ecc.c:232 #, fuzzy, c-format msgid "Could not read hostkey file: %s\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/util/gnunet-ecc.c:283 msgid "No hostkey file specified on command line\n" msgstr "" #: src/util/gnunet-ecc.c:349 msgid "list keys included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:352 msgid "number of keys to list included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:355 msgid "create COUNT public-private key pairs (for testing)" msgstr "" #: src/util/gnunet-ecc.c:358 msgid "print the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:361 msgid "print the hash of the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:364 msgid "print examples of ECC operations (used for compatibility testing)" msgstr "" #: src/util/gnunet-ecc.c:375 #, fuzzy msgid "Manipulate GNUnet private ECC key files" msgstr "cập nhật má»™t giá trị trong tập tin cấu hình" #: src/util/gnunet-resolver.c:149 msgid "perform a reverse lookup" msgstr "" #: src/util/gnunet-resolver.c:160 msgid "Use build-in GNUnet stub resolver" msgstr "" #: src/util/gnunet-scrypt.c:279 msgid "number of bits to require for the proof of work" msgstr "" #: src/util/gnunet-scrypt.c:282 msgid "file with private key, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:285 msgid "file with proof of work, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:288 msgid "time to wait between calculations" msgstr "" #: src/util/gnunet-scrypt.c:299 #, fuzzy msgid "Manipulate GNUnet proof of work files" msgstr "cập nhật má»™t giá trị trong tập tin cấu hình" #: src/util/gnunet-service-resolver.c:299 #, c-format msgid "Could not resolve `%s' (%s): %s\n" msgstr "Không thể giải quyết « %s » (%s): %s\n" #: src/util/gnunet-service-resolver.c:371 #: src/util/gnunet-service-resolver.c:412 #, c-format msgid "Could not find IP of host `%s': %s\n" msgstr "Không tìm thấy địa chỉ IP cá»§a máy « %s »: %s\n" #: src/util/gnunet-uri.c:84 #, c-format msgid "No URI specified on command line\n" msgstr "" #: src/util/gnunet-uri.c:89 #, fuzzy, c-format msgid "Invalid URI: does not start with `%s'\n" msgstr "Ký hiệu mạng sai (không kết thúc vá»›i « ; »: « %s »)\n" #: src/util/gnunet-uri.c:96 #, c-format msgid "Invalid URI: fails to specify subsystem\n" msgstr "" #: src/util/gnunet-uri.c:106 #, c-format msgid "No handler known for subsystem `%s'\n" msgstr "" #: src/util/gnunet-uri.c:168 msgid "Perform default-actions for GNUnet URIs" msgstr "" #: src/util/helper.c:338 #, fuzzy, c-format msgid "Error reading from `%s': %s\n" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/util/helper.c:383 #, fuzzy, c-format msgid "Failed to parse inbound message from helper `%s'\n" msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #: src/util/helper.c:609 #, fuzzy, c-format msgid "Error writing to `%s': %s\n" msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #: src/util/network.c:134 #, c-format msgid "Unable to shorten unix path `%s' while keeping name unique\n" msgstr "" #: src/util/network.c:1355 src/util/network.c:1480 #, c-format msgid "" "Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n" msgstr "" #: src/util/os_installation.c:421 #, c-format msgid "" "Could not determine installation path for %s. Set `%s' environment " "variable.\n" msgstr "" #: src/util/os_installation.c:766 #, fuzzy, c-format msgid "Could not find binary `%s' in PATH!\n" msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #: src/util/os_installation.c:826 #, fuzzy, c-format msgid "CreateProcess failed for binary %s (%d).\n" msgstr "« %s » thất bại cho ổ đĩa « %s »: %u\n" #: src/util/os_installation.c:836 #, c-format msgid "GetExitCodeProcess failed for binary %s (%d).\n" msgstr "" #: src/util/plugin.c:87 #, c-format msgid "Initialization of plugin mechanism failed: %s!\n" msgstr "Lá»—i sÆ¡ khởi cÆ¡ chế phần bổ sung: %s\n" #: src/util/plugin.c:148 #, c-format msgid "`%s' failed to resolve method '%s' with error: %s\n" msgstr "« %s » không giải quyết được phương pháp « %s », vá»›i lá»—i: %s\n" #: src/util/plugin.c:223 #, c-format msgid "`%s' failed for library `%s' with error: %s\n" msgstr "« %s » thất bại cho thư viện « %s » vá»›i lá»—i: %s\n" #: src/util/plugin.c:382 #, fuzzy msgid "Could not determine plugin installation path.\n" msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #: src/util/program.c:246 src/util/service.c:1452 #, fuzzy, c-format msgid "Malformed configuration file `%s', exit ...\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/util/program.c:258 src/util/service.c:1467 #, fuzzy, c-format msgid "Could not access configuration file `%s'\n" msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #: src/util/program.c:263 src/util/service.c:1462 #, fuzzy msgid "Malformed configuration, exit ...\n" msgstr "Không thể lưu tập tin cấu hình « %s »:" #: src/util/resolver_api.c:198 #, fuzzy, c-format msgid "Must specify `%s' for `%s' in configuration!\n" msgstr "Äang thá»­ dùng tập tin « %s » cho cấu hình MySQL.\n" #: src/util/resolver_api.c:216 #, c-format msgid "" "Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n" msgstr "" #: src/util/resolver_api.c:348 #, fuzzy, c-format msgid "Timeout trying to resolve IP address `%s'.\n" msgstr "GNUnet bây giá» sá»­ dụng địa chỉ IP %s.\n" #: src/util/resolver_api.c:352 #, fuzzy, c-format msgid "Timeout trying to resolve hostname `%s'.\n" msgstr "không quyết định các tên máy" #: src/util/resolver_api.c:908 #, fuzzy, c-format msgid "Could not resolve our FQDN : %s\n" msgstr "Không thể giải quyết « %s » (%s): %s\n" #: src/util/scheduler.c:813 msgid "Looks like we're busy waiting...\n" msgstr "" #: src/util/scheduler.c:948 #, c-format msgid "Attempt to cancel dead task %llu!\n" msgstr "" #: src/util/server.c:484 #, fuzzy, c-format msgid "`%s' failed for port %d (%s).\n" msgstr "« %s » thất bại cho ổ đĩa « %s »: %u\n" #: src/util/server.c:493 #, fuzzy, c-format msgid "`%s' failed for port %d (%s): address already in use\n" msgstr "« %s » bị lá»—i cho cổng %d. Trình gnunetd có chạy chưa?\n" #: src/util/server.c:499 #, fuzzy, c-format msgid "`%s' failed for `%s': address already in use\n" msgstr "« %s » bị lá»—i cho cổng %d. Trình gnunetd có chạy chưa?\n" #: src/util/server.c:892 #, c-format msgid "" "Processing code for message of type %u did not call " "`GNUNET_SERVER_receive_done' after %s\n" msgstr "" #: src/util/service.c:347 #, fuzzy, c-format msgid "Unknown address family %d\n" msgstr "\tKhông rõ miá»n tên « %s »\n" #: src/util/service.c:354 #, c-format msgid "Access from `%s' denied to service `%s'\n" msgstr "" #: src/util/service.c:409 #, c-format msgid "Could not parse IPv4 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:446 #, c-format msgid "Could not parse IPv6 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:563 #, c-format msgid "" "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n" msgstr "" #: src/util/service.c:653 #, c-format msgid "" "Disabling UNIX domain socket support for service `%s', failed to create UNIX " "domain socket: %s\n" msgstr "" #: src/util/service.c:669 #, c-format msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n" msgstr "" #: src/util/service.c:903 msgid "Could not access a pre-bound socket, will try to bind myself\n" msgstr "" #: src/util/service.c:952 src/util/service.c:970 #, c-format msgid "Specified value for `%s' of service `%s' is invalid\n" msgstr "" #: src/util/service.c:995 #, c-format msgid "Could not access pre-bound socket %u, will try to bind myself\n" msgstr "" #: src/util/service.c:1165 #, fuzzy, c-format msgid "Failed to start `%s' at `%s'\n" msgstr "Lá»—i chạy %s: %s %d\n" #: src/util/service.c:1207 #, fuzzy, c-format msgid "Service `%s' runs at %s\n" msgstr "Äồng đẳng « %s » có mức tin cậy %8u\n" #: src/util/service.c:1256 msgid "Service process failed to initialize\n" msgstr "" #: src/util/service.c:1260 msgid "Service process could not initialize server function\n" msgstr "" #: src/util/service.c:1264 msgid "Service process failed to report status\n" msgstr "" #: src/util/service.c:1319 msgid "No such user" msgstr "Không có ngưá»i dùng như vậy" #: src/util/service.c:1332 #, c-format msgid "Cannot change user/group to `%s': %s\n" msgstr "Không thể thay đổi ngưá»i dùng/nhóm thành « %s »: %s\n" #: src/util/service.c:1402 msgid "do daemonize (detach from terminal)" msgstr "" #: src/util/signal.c:89 #, c-format msgid "signal (%d, %p) returned %d.\n" msgstr "" #: src/util/strings.c:145 msgid "b" msgstr "b" #: src/util/strings.c:433 #, c-format msgid "Character sets requested were `%s'->`%s'\n" msgstr "" #: src/util/strings.c:561 msgid "Failed to expand `$HOME': environment variable `HOME' not set" msgstr "" "Lá»—i mở rá»™ng biến môi trưá»ng « $HOME »: chưa đặt biến môi trưá»ng « HOME »" #: src/util/strings.c:658 msgid "µs" msgstr "" #: src/util/strings.c:662 msgid "forever" msgstr "" #: src/util/strings.c:664 msgid "0 ms" msgstr "" #: src/util/strings.c:670 msgid "ms" msgstr "mg" #: src/util/strings.c:676 msgid "s" msgstr "g" #: src/util/strings.c:682 msgid "m" msgstr "p" #: src/util/strings.c:688 msgid "h" msgstr "g" #: src/util/strings.c:695 #, fuzzy msgid "day" msgstr " ngày" #: src/util/strings.c:697 #, fuzzy msgid "days" msgstr " ngày" #: src/util/strings.c:726 msgid "end of time" msgstr "" #: src/util/strings.c:1159 msgid "IPv6 address did not start with `['\n" msgstr "" #: src/util/strings.c:1167 msgid "IPv6 address did contain ':' to separate port number\n" msgstr "" #: src/util/strings.c:1173 msgid "IPv6 address did contain ']' before ':' to separate port number\n" msgstr "" #: src/util/strings.c:1180 msgid "IPv6 address did contain a valid port number after the last ':'\n" msgstr "" #: src/util/strings.c:1189 #, fuzzy, c-format msgid "Invalid IPv6 address `%s': %s\n" msgstr "Mức ưu tiên tiến trình không hợp lê « %s ».\n" #: src/util/strings.c:1395 src/util/strings.c:1411 msgid "Port not in range\n" msgstr "" #: src/util/strings.c:1420 #, fuzzy, c-format msgid "Malformed port policy `%s'\n" msgstr "Lá»—i bắt đầu thu thập.\n" #: src/util/strings.c:1503 src/util/strings.c:1534 src/util/strings.c:1582 #: src/util/strings.c:1603 #, c-format msgid "Invalid format for IP: `%s'\n" msgstr "Äịa chỉ IP định dạng sai: %s\n" #: src/util/strings.c:1560 #, c-format msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)." msgstr "Ký hiệu mạng sai (« /%d » không hợp lệ trong CIDR IPv4)." #: src/util/strings.c:1612 #, fuzzy, c-format msgid "Invalid format: `%s'\n" msgstr "Äịa chỉ IP định dạng sai: %s\n" #: src/util/strings.c:1664 #, c-format msgid "Invalid network notation (does not end with ';': `%s')\n" msgstr "Ký hiệu mạng sai (không kết thúc vá»›i « ; »: « %s »)\n" #: src/util/strings.c:1714 #, fuzzy, c-format msgid "Wrong format `%s' for netmask\n" msgstr "Mặt nạ mạng có định dạng sai « %s »: %s\n" #: src/util/strings.c:1745 #, fuzzy, c-format msgid "Wrong format `%s' for network\n" msgstr "Mạng có định dạng sai « %s »: %s\n" #: src/vpn/gnunet-service-vpn.c:550 src/vpn/gnunet-service-vpn.c:1086 #, fuzzy msgid "# Active channels" msgstr "# các kết nối dht" #: src/vpn/gnunet-service-vpn.c:642 #, fuzzy msgid "# Bytes given to mesh for transmission" msgstr "# các thông báo PING được tạo" #: src/vpn/gnunet-service-vpn.c:680 #, fuzzy msgid "# Bytes dropped in mesh queue (overflow)" msgstr "# các byte loại bá» bởi UDP (Ä‘i ra)" #: src/vpn/gnunet-service-vpn.c:753 #, fuzzy msgid "# Mesh channels created" msgstr "# các truy vấn lá»— hổng được định tuyến" #: src/vpn/gnunet-service-vpn.c:784 #, fuzzy msgid "Failed to setup mesh channel!\n" msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #: src/vpn/gnunet-service-vpn.c:978 #, c-format msgid "Protocol %u not supported, dropping\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1305 msgid "# ICMPv4 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1326 msgid "# ICMPv6 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1531 #, fuzzy msgid "# Packets received from TUN interface" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/vpn/gnunet-service-vpn.c:1564 src/vpn/gnunet-service-vpn.c:1600 #, c-format msgid "Packet received for unmapped destination `%s' (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1610 msgid "Received IPv4 packet with options (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1624 #, c-format msgid "Received packet of unknown protocol %d from TUN (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1706 #, fuzzy msgid "# ICMP packets received from mesh" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/vpn/gnunet-service-vpn.c:2045 #, fuzzy msgid "# UDP packets received from mesh" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/vpn/gnunet-service-vpn.c:2200 #, fuzzy msgid "# TCP packets received from mesh" msgstr "# các đáp ứng lá»— hổng được gá»­i cho trình/máy khách" #: src/vpn/gnunet-service-vpn.c:2351 msgid "Failed to find unallocated IPv4 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2406 msgid "Failed to find unallocated IPv6 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2447 src/vpn/gnunet-service-vpn.c:2663 #, fuzzy msgid "# Active destinations" msgstr "# các kết nối dht" #: src/vpn/gnunet-service-vpn.c:2715 msgid "Failed to allocate IP address for new destination\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2982 #, fuzzy msgid "Must specify valid IPv6 address" msgstr "« %s » không sẵn sàng.\n" #: src/vpn/gnunet-service-vpn.c:3006 msgid "Must specify valid IPv6 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3014 msgid "IPv6 support disabled as this system does not support IPv6\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:3027 #, fuzzy msgid "Must specify valid IPv4 address" msgstr "« %s » không sẵn sàng.\n" #: src/vpn/gnunet-service-vpn.c:3040 msgid "Must specify valid IPv4 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3050 msgid "IPv4 support disabled as this system does not support IPv4\n" msgstr "" #: src/vpn/gnunet-vpn.c:147 #, fuzzy msgid "Error creating tunnel\n" msgstr "Hoàn thành tạo khoá.\n" #: src/vpn/gnunet-vpn.c:190 src/vpn/gnunet-vpn.c:221 #, fuzzy, c-format msgid "Option `%s' makes no sense with option `%s'.\n" msgstr "Tùy chá»n « %s » không có nghÄ©a khi không có tùy chá»n « %s ».\n" #: src/vpn/gnunet-vpn.c:203 #, fuzzy, c-format msgid "Option `%s' or `%s' is required.\n" msgstr "Bị từ chối đặt tùy chá»n « %s » trong phần « %s » thành « %s ».\n" #: src/vpn/gnunet-vpn.c:215 #, fuzzy, c-format msgid "Option `%s' or `%s' is required when using option `%s'.\n" msgstr "Tùy chá»n « %s » cần thiết khi dùng tùy chá»n « %s ».\n" #: src/vpn/gnunet-vpn.c:235 #, fuzzy, c-format msgid "`%s' is not a valid peer identifier.\n" msgstr "« %s » không sẵn sàng.\n" #: src/vpn/gnunet-vpn.c:255 #, fuzzy, c-format msgid "`%s' is not a valid IP address.\n" msgstr "« %s » không sẵn sàng.\n" #: src/vpn/gnunet-vpn.c:290 msgid "request that result should be an IPv4 address" msgstr "" #: src/vpn/gnunet-vpn.c:293 msgid "request that result should be an IPv6 address" msgstr "" #: src/vpn/gnunet-vpn.c:296 msgid "how long should the mapping be valid for new tunnels?" msgstr "" #: src/vpn/gnunet-vpn.c:299 msgid "destination IP for the tunnel" msgstr "" #: src/vpn/gnunet-vpn.c:302 msgid "peer offering the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:305 msgid "name of the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:308 #, fuzzy msgid "service is offered via TCP" msgstr "# các byte đã nhận qua TCP" #: src/vpn/gnunet-vpn.c:311 #, fuzzy msgid "service is offered via UDP" msgstr "# các byte đã nhận qua UDP" #: src/vpn/gnunet-vpn.c:323 msgid "Setup tunnels via VPN." msgstr "" #: src/include/gnunet_common.h:566 src/include/gnunet_common.h:573 #: src/include/gnunet_common.h:581 #, fuzzy, c-format msgid "Assertion failed at %s:%d.\n" msgstr "Lá»—i ná»™i bá»™ : khẳng định không thành công tại %s:%d.\n" #: src/include/gnunet_common.h:593 #, fuzzy, c-format msgid "External protocol violation detected at %s:%d.\n" msgstr "Lá»—i ná»™i bá»™ : khẳng định không thành công tại %s:%d.\n" #: src/include/gnunet_common.h:620 src/include/gnunet_common.h:629 #, c-format msgid "`%s' failed on file `%s' at %s:%d with error: %s\n" msgstr "« %s » thất bại ở tập tin « %s » tại %s:%d vá»›i lá»—i: %s\n" #, fuzzy #~ msgid "# TRAIL SETUP requests received" #~ msgstr "# các yêu cầu get (lấy) dht được nhận" #, fuzzy #~ msgid "# TRAIL SETUP bytes received" #~ msgstr "# các yêu cầu get (lấy) dht được nhận" #, fuzzy #~ msgid "provide information about a particular channel" #~ msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #, fuzzy #~ msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED" #~ msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #, fuzzy #~ msgid "Could not find option `%s:%s' in configuration.\n" #~ msgstr "Không tìm thấy phương pháp « %s%s » trong thư viện « %s ».\n" #, fuzzy #~ msgid "Peer `%s' disconnected\n" #~ msgstr "# cá»§a các đồng đẳng đã kết nối" #, fuzzy #~ msgid "Transport plugin: `%s' port %llu\n" #~ msgstr "Äang nạp các truyá»n tải « %s »\n" #, fuzzy #~ msgid "Found %u transport plugins: `%s'\n" #~ msgstr "Äang nạp các truyá»n tải « %s »\n" #, fuzzy #~ msgid "Failed to parse HELLO in file `%s': %s %u \n" #~ msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #, fuzzy #~ msgid "Internal error %d\n" #~ msgstr "Lá»—i VR." #, fuzzy #~ msgid "Aborting call to `%s'\n" #~ msgstr "Gặp lá»—i khi tạo ngưá»i dùng" #, fuzzy #~ msgid "You are already in a conversation with `%s'.\n" #~ msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #, fuzzy #~ msgid "Print information about mesh tunnels and peers." #~ msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #, fuzzy #~ msgid "" #~ "%s service is lacking key configuration settings (%s). Using default " #~ "(%u).\n" #~ msgstr "Lưu cấu hình ngay bây giá» không?" #, fuzzy #~ msgid "Loading block plugin `%s'\n" #~ msgstr "Äang nạp các truyá»n tải « %s »\n" #, fuzzy #~ msgid "Invalid value `%s'\n" #~ msgstr "Äối số không hợp lệ cho « %s ».\n" #, fuzzy #~ msgid "Found issuer for public key `%s'\n" #~ msgstr "Äang nạp các truyá»n tải « %s »\n" #, fuzzy #~ msgid "No issuer for public key `%s'\n" #~ msgstr "Vẫn còn không tìm thấy đồng đẳng trong « %s ».\n" #, fuzzy #~ msgid "Failed to get slave counters!\n" #~ msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #, fuzzy #~ msgid "" #~ "Could not translate E[a%d] to MPI!\n" #~ "%s/%s\n" #~ msgstr "Không thể lấy địa chỉ IP cho giao diện « %s », dùng « %s ».\n" #, fuzzy #~ msgid "Job command file not given. Exiting\n" #~ msgstr "dùng tập tin cấu hình TÊN_TẬP_TIN" #, fuzzy #~ msgid "Error while decoding key %u\n" #~ msgstr "Gặp lá»—i khi tải xuống: %s\n" #~ msgid "Could not read friends list `%s'\n" #~ msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #, fuzzy #~ msgid "Failed to read friends list from `%s': out of memory\n" #~ msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #~ msgid "Failed to read friends list from `%s'\n" #~ msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #, fuzzy #~ msgid "" #~ "Syntax error in topology specification at offset %llu, skipping bytes.\n" #~ msgstr "Lá»—i cú pháp trong sá»± xác định địa hình há»c, Ä‘ang bá» qua các byte.\n" #, fuzzy #~ msgid "" #~ "Syntax error in topology specification at offset %llu, skipping bytes `" #~ "%s'.\n" #~ msgstr "" #~ "Lá»—i cú pháp trong sá»± xác định địa hình há»c, Ä‘ang bá» qua các byte « %s ».\n" #, fuzzy #~ msgid "ECC signature verification failed at %s:%d: %s\n" #~ msgstr "Lá»—i thẩm tra chữ ký RSA tại %s:%d: %s\n" #, fuzzy #~ msgid "# peers connected to mesh tunnels" #~ msgstr "# cá»§a các đồng đẳng đã kết nối" #, fuzzy #~ msgid "Failed to parse metadata about pseudonym from file `%s': %s\n" #~ msgstr "Lá»—i phân tích dữ liệu giao diện từ « %s ».\n" #~ msgid "no-name" #~ msgstr "không-tên" #, fuzzy #~ msgid "Option `%s' ignored\n" #~ msgstr "%s: tùy chá»n « %s » là mÆ¡ hồ\n" #, fuzzy #~ msgid "" #~ "add an additional keyword for the advertisment (this option can be " #~ "specified multiple times)" #~ msgstr "" #~ "thêm má»™t từ khóa bổ sung cho tất cả tập tin và thư mục (có thể chỉ ra tùy " #~ "chá»n này nhiá»u lần)" #, fuzzy #~ msgid "specify ID of the root of the namespace" #~ msgstr "đặt đánh giá cá»§a má»™t không gian tên" #, fuzzy #~ msgid "change rating of namespace ID by VALUE" #~ msgstr "đặt đánh giá cá»§a má»™t không gian tên" #, fuzzy #~ msgid "try to shorten a given name" #~ msgstr "Lá»—i kết nối đến gnunetd.\n" #, fuzzy #~ msgid "Failed to read or create private zone key\n" #~ msgstr "Lá»—i cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #, fuzzy #~ msgid "Unable to initialize resolver!\n" #~ msgstr "Không thể sÆ¡ khởi SQLite: %s.\n" #, fuzzy #~ msgid "Using default zone file `%s'\n" #~ msgstr "Äang bắt đầu tài vỠ« %s »\n" #, fuzzy #~ msgid "filename with the zone key" #~ msgstr "tên tập tin" #, fuzzy #~ msgid "Failed to write zone key to file `%s': %s\n" #~ msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #, fuzzy #~ msgid "file exists with different key" #~ msgstr "tên tập tin" #, fuzzy #~ msgid "name of the template configuration file to use (optional)" #~ msgstr "Tập tin cấu hình gnunetd có đưá»ng dẫn nào?" #, fuzzy #~ msgid "number of peers to start" #~ msgstr "số lần lặp lại" #, fuzzy #~ msgid "Failed to read or generate private key: %s\n" #~ msgstr "Lá»—i cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #, fuzzy #~ msgid "Transport service is unable to access hostkey. Exiting.\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "Failed to create or read private key for namespace `%s'\n" #~ msgstr "Lá»—i cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #, fuzzy #~ msgid "Failed to read namespace private key file `%s', deleting it!\n" #~ msgstr "Lá»—i thêm mục nhập vào không gian tên « %s » (có chưa ?)\n" #, fuzzy #~ msgid "print names of local namespaces" #~ msgstr "đặt đánh giá cá»§a má»™t không gian tên" #, fuzzy #~ msgid "Failed to create namespace `%s' (illegal filename?)\n" #~ msgstr "Không thể tạo miá»n tên.\n" #, fuzzy #~ msgid "# Replies received from STREAM" #~ msgstr "# các byte đã nhận qua HTTP" #, fuzzy #~ msgid "Mesh service could not access hostkey: %s. Exiting.\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "No valid expiration time for operation `%s'\n" #~ msgstr "" #~ "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #, fuzzy #~ msgid "Failed to find record to remove\n" #~ msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #, fuzzy #~ msgid "Could not parse zone key file `%s'\n" #~ msgstr "Không thể truy cập đến tập tin gnunet-directory « %s »\n" #, fuzzy #~ msgid "Failed to create new signature" #~ msgstr "Không thể tạo miá»n tên.\n" #, fuzzy #~ msgid "Failed to put new set of records in database" #~ msgstr "" #~ "\n" #~ "Không nhận được đáp ứng từ gnunetd.\n" #, fuzzy #~ msgid "Failed to remove records from database" #~ msgstr "" #~ "\n" #~ "Không nhận được đáp ứng từ gnunetd.\n" #, fuzzy #~ msgid "Failed to access database" #~ msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #, fuzzy #~ msgid "unknown internal error in namestore" #~ msgstr "=\tLá»—i Ä‘á»c thư mục.\n" #, fuzzy #~ msgid "NSE service could not access hostkey: %s\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "" #~ "Error loading search strings.Given file does not contain enough strings. " #~ "Exiting.\n" #~ msgstr "Gặp lá»—i khi tải xuống: %s\n" #, fuzzy #~ msgid "Transport service could not access hostkey: %s. Exiting.\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "Address of unexpected length: %u\n" #~ msgstr "Gặp sá»± kiện bất thưá»ng: %d\n" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (too long, %llu bytes). " #~ "Deleting it.\n" #~ msgstr "Tập tin « %s » không chứa biệt hiệu nên thá»­ gỡ bá».\n" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (failed decode, %llu " #~ "bytes). Deleting it.\n" #~ msgstr "Tập tin « %s » không chứa biệt hiệu nên thá»­ gỡ bá».\n" #, fuzzy #~ msgid "File `%s' does not contain a valid private key. Deleting it.\n" #~ msgstr "Tập tin « %s » không chứa biệt hiệu nên thá»­ gỡ bá».\n" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (too long, %llu bytes). " #~ "Renaming it.\n" #~ msgstr "Tập tin « %s » không chứa biệt hiệu nên thá»­ gỡ bá».\n" #~ msgid "RSA signature verification failed at %s:%d: %s\n" #~ msgstr "Lá»—i thẩm tra chữ ký RSA tại %s:%d: %s\n" #, fuzzy #~ msgid "`%s' failed for drive `%S': %u\n" #~ msgstr "« %s » thất bại cho ổ đĩa « %s »: %u\n" #, fuzzy #~ msgid "Service `%s' was already running.\n" #~ msgstr "Không gian tên « %s » có đánh giá %d.\n" #, fuzzy #~ msgid "Service `%s' has been started.\n" #~ msgstr "Dịch vụ đã bị xoá.\n" #, fuzzy #~ msgid "Service `%s' was already being stopped.\n" #~ msgstr "Dịch vụ đã bị xoá.\n" #, fuzzy #~ msgid "Service `%s' was already not running.\n" #~ msgstr "« %s » không phải là má»™t tập tin.\n" #, fuzzy #~ msgid "Error communicating with ARM service.\n" #~ msgstr "Cổng để liên lạc vá»›i giao diện ngưá»i dùng GNUnet" #, fuzzy #~ msgid "Timeout communicating with ARM service.\n" #~ msgstr "Cổng để liên lạc vá»›i giao diện ngưá»i dùng GNUnet" #, fuzzy #~ msgid "Error in communication with PEERINFO service\n" #~ msgstr "Cổng để liên lạc vá»›i giao diện ngưá»i dùng GNUnet" #, fuzzy #~ msgid "%s Received message from %s of type %d, distance %u!\n" #~ msgstr "Nhận được thông báo bị há»ng từ đồng đẳng « %s » trong %s:%d.\n" #, fuzzy #~ msgid "Creating a peer failed. Error: %s\n" #~ msgstr "Gặp lá»—i khi tải lên tập tin: %s\n" #, fuzzy #~ msgid "Exiting\n" #~ msgstr "Thoát" #, fuzzy #~ msgid "Could not read blacklist file `%s'\n" #~ msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #, fuzzy #~ msgid "Failed to read blacklist from `%s'\n" #~ msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #, fuzzy #~ msgid "Syntax error in blacklist file at offset %llu, giving up!\n" #~ msgstr "Gặp lá»—i cú pháp trong tập tin cấu hình « %s » tại dòng %d.\n" #, fuzzy #~ msgid "Syntax error in blacklist file at offset %llu, skipping bytes.\n" #~ msgstr "Lá»—i cú pháp trong sá»± xác định địa hình há»c, Ä‘ang bá» qua các byte.\n" #, fuzzy #~ msgid "Failed to read hostkey: %s\n" #~ msgstr "Lá»—i bắt đầu thu thập.\n" #, fuzzy #~ msgid "# session keys received" #~ msgstr "# các khoá phiên chạy bị từ chối" #, fuzzy #~ msgid "# SET_KEY and PING messages created" #~ msgstr "# các thông báo PING được tạo" #, fuzzy #~ msgid "Message received far too old (%s). Content ignored.\n" #~ msgstr "Thông báo nhận được cÅ© hÆ¡n má»™t ngày. Äã loại bá».\n" #, fuzzy #~ msgid "Unknown error" #~ msgstr "Lá»—i không rõ.\n" #, fuzzy #~ msgid "Failed to serialize meta data" #~ msgstr "Lá»—i lấy thông kê vá» truyá»n tải.\n" #, fuzzy #~ msgid "Failed to connect to datastore service" #~ msgstr "Không kết nối được đến trình ná»n gnunetd." #, fuzzy #~ msgid "Failed to parse URI `%s' from KBlock!\n" #~ msgstr "Tập tin « %s » có URI: %s\n" #, fuzzy #~ msgid "Regexprofiler could not access hostkey: %s. Exiting.\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "Could not access STATISTICS service. Exiting.\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "Failed to open named pipe `%s' for reading: %s\n" #~ msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #, fuzzy #~ msgid "Failed to open named pipe `%s' for writing: %s\n" #~ msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #, fuzzy #~ msgid "session identifier" #~ msgstr "# các phiên chạy được thiết lập" #, fuzzy #~ msgid "Mesh service could not access hostkey. Exiting.\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "" #~ "provide inthe 'struct GNUNET_TRANSPORT_PeerIterateContextformation about " #~ "all tunnels (continuously)" #~ msgstr "In ra thông tin vá» các đồng đẳng GNUnet." #, fuzzy #~ msgid "No `%s' specified in `%s' configuration, will not bootstrap.\n" #~ msgstr "" #~ "Chưa ghi rõ địa chỉ URL cá»§a danh sách các máy nên không nạp và khởi " #~ "động.\n" #, fuzzy #~ msgid "" #~ "No `%s' specified in `%s' configuration, cannot load hostlists from " #~ "file.\n" #~ msgstr "" #~ "Chưa ghi rõ địa chỉ URL cá»§a danh sách các máy nên không nạp và khởi " #~ "động.\n" #, fuzzy #~ msgid "" #~ "No `%s' specified in `%s' configuration, cannot save hostlists to file.\n" #~ msgstr "" #~ "Chưa ghi rõ địa chỉ URL cá»§a danh sách các máy nên không nạp và khởi " #~ "động.\n" #, fuzzy #~ msgid "Got %u bytes from helper `%s'\n" #~ msgstr "Nhận yêu cầu định tuyến\n" #, fuzzy #~ msgid "Asked to start service `%s' within %llu ms\n" #~ msgstr "« %s »: Chưa nhận thông báo sau %llu miligiây.\n" #, fuzzy #~ msgid "Configuration file `%s' for service `%s' not valid: %s\n" #~ msgstr "Tập tin cấu hình « %s » đã được ghi.\n" #, fuzzy #~ msgid "Could not transmit confirmation receipt\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "Unknown message type: '%u'\n" #~ msgstr "\tKhông rõ miá»n tên « %s »\n" #, fuzzy #~ msgid "Configuration option `%s' in section `%s' missing\n" #~ msgstr "" #~ "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #, fuzzy #~ msgid "Failed to access chat home directory `%s'\n" #~ msgstr "Lá»—i truy cập đến thư mục nhà GNUnet « %s »\n" #, fuzzy #~ msgid "Failed to create/open key in file `%s'\n" #~ msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #, fuzzy #~ msgid "Could not serialize metadata\n" #~ msgstr "Không thể tạo miá»n tên.\n" #~ msgid "anonymous" #~ msgstr "nặc danh" #, fuzzy #~ msgid "(%s) `%s' said: %s\n" #~ msgstr "« %s » nói: %s\n" #, fuzzy #~ msgid "(%s) `%s' said to you: %s\n" #~ msgstr "« %s » nói cho bạn: %s\n" #, fuzzy #~ msgid "(%s) `%s' said for sure: %s\n" #~ msgstr "« %s » nói thật: %s\n" #, fuzzy #~ msgid "(%s) `%s' said to you for sure: %s\n" #~ msgstr "« %s » nói thật cho bạn: %s\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you received: %s\n" #~ msgstr "« %s » xác nhận bạn đã nhận được: %s\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you and only you received: %s\n" #~ msgstr "« %s » xác nhận mà chỉ bạn đã nhận được: %s\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you received from him or her: %s\n" #~ msgstr "« %s » xác nhận mà bạn đã nhận được từ há» : %s\n" #, fuzzy #~ msgid "" #~ "(%s) `%s' was confirmed that you and only you received from him or her: " #~ "%s\n" #~ msgstr "« %s » xác nhận mà chỉ bạn Ä‘a nhận được từ há» : %s\n" #, fuzzy #~ msgid "(%s) `%s' said off the record: %s\n" #~ msgstr "« %s » nói không chính thức: %s\n" #, fuzzy #~ msgid "(%s) <%s> said using an unknown message type: %s\n" #~ msgstr "<%s> đã nói bằng má»™t kiểu tin nhẳn không rõ : %s\n" #~ msgid "`%s' entered the room\n" #~ msgstr "« %s » vào phòng\n" #~ msgid "`%s' left the room\n" #~ msgstr "« %s » rá»i phòng\n" #, fuzzy #~ msgid "Could not change username\n" #~ msgstr "Không thể tạo miá»n tên.\n" #, fuzzy #~ msgid "Joining room `%s' as user `%s'...\n" #~ msgstr "Äã vào phòng « %s » là ngưá»i dùng « %s ».\n" #, fuzzy #~ msgid "Changed username to `%s'\n" #~ msgstr "Äã thay đổi tên ngưá»i dùng thành « %s ».\n" #~ msgid "Users in room `%s': " #~ msgstr "Ngưá»i dùng trong phòng « %s »:" #~ msgid "Syntax: /msg USERNAME MESSAGE" #~ msgstr "Cú pháp: /msg TÊN_NGƯỜI_DÙNG TIN_NHẲN" #~ msgid "User `%s' is currently not in the room!\n" #~ msgstr "Ngưá»i dùng « %s » hiện thá»i không có trong phòng này.\n" #~ msgid "" #~ "Use `/join #roomname' to join a chat room. Joining a room will cause you " #~ "to leave the current room" #~ msgstr "" #~ "Gõ chuá»—i « /join #tên_phòng » để vào má»™t phòng trò chuyện nào đó (việc " #~ "này cÅ©ng gây ra bạn ra khá»i phòng hiện tại)" #~ msgid "" #~ "Use `/nick nickname' to change your nickname. This will cause you to " #~ "leave the current room and immediately rejoin it with the new name." #~ msgstr "" #~ "Gõ chuá»—i « /nick tên_hiệu » để thay đổi tên hiệu cá»§a mình (việc này cÅ©ng " #~ "gây ra bạn ra khá»i phòng hiện tại, sau đó vào lại ngay vá»›i tên má»›i)" #~ msgid "" #~ "Use `/msg nickname message' to send a private message to the specified " #~ "user" #~ msgstr "" #~ "Gõ chuá»—i « /msg tên_hiệu tin_nhẳn » để gá»­i má»™t tin nhẳn riêng cho ngưá»i " #~ "dùng có tên đó" #~ msgid "The `/notice' command is an alias for `/msg'" #~ msgstr "Lệnh « /notice » là má»™t biệt hiệu cho « /msg »" #~ msgid "The `/query' command is an alias for `/msg'" #~ msgstr "Lệnh « /query » là má»™t biệt hiệu cho « /msg »" #, fuzzy #~ msgid "Use `/sig message' to send a signed public message" #~ msgstr "" #~ "Gõ chuá»—i « /msg tên_hiệu tin_nhẳn » để gá»­i má»™t tin nhẳn riêng cho ngưá»i " #~ "dùng có tên đó" #, fuzzy #~ msgid "The `/anon' command is an alias for `/anonymous'" #~ msgstr "Lệnh « /notice » là má»™t biệt hiệu cho « /msg »" #~ msgid "The `/leave' command is an alias for `/quit'" #~ msgstr "Lệnh « /leave » là má»™t biệt hiệu cho « /quit »" #~ msgid "Use `/names' to list all of the current members in the chat room" #~ msgstr "" #~ "Gõ chuá»—i « /names » để liệt kê tất cả các thành viên hiện thá»i trong " #~ "phòng trò chuyện đó" #~ msgid "Failed to join room `%s'\n" #~ msgstr "Lá»—i vào phòng « %s »\n" #~ msgid "set the chat room to join" #~ msgstr "đặt phòng trò chuyện cần vào" #~ msgid "Join a chat on GNUnet." #~ msgstr "Vào phòng trò chuyện trên GNUnet." #, fuzzy #~ msgid "Failed to queue a message notification\n" #~ msgstr "Lá»—i lưu cấu hình." #, fuzzy #~ msgid "Failed to queue a join notification\n" #~ msgstr "Lá»—i lưu cấu hình." #, fuzzy #~ msgid "Failed to queue a confirmation receipt\n" #~ msgstr "Lá»—i lưu cấu hình." #, fuzzy #~ msgid "Failed to queue a leave notification\n" #~ msgstr "Lá»—i lưu cấu hình." #, fuzzy #~ msgid "Connected to %s service!\n" #~ msgstr "« %s » được kết nối tá»›i « %s ».\n" #, fuzzy #~ msgid "Configuration fails to specify `%s' in section `%s'\n" #~ msgstr "Tập tin cấu hình « %s » đã được ghi.\n" #, fuzzy #~ msgid "Configuration fails to specify `%s', assuming default value." #~ msgstr "Tập tin cấu hình « %s » đã được ghi.\n" #, fuzzy #~ msgid "Key file `%s' for private zone does not exist!\n" #~ msgstr "đặt số trình ná»n cần khởi chạy" #, fuzzy #~ msgid "Option `%s' not specified in configuration section `%s'\n" #~ msgstr "" #~ "Äặc tả mạng dạng sai trong cấu hình phần « %s » cho mục nhập « %s »: %s\n" #, fuzzy #~ msgid "Peer is lacking HOSTKEY configuration setting.\n" #~ msgstr "Lưu cấu hình ngay bây giá» không?" #, fuzzy #~ msgid "`scp' did not complete cleanly.\n" #~ msgstr "« %s » không phải được kết nối tá»›i đồng đẳng nào.\n" #, fuzzy #~ msgid "Failed to create pipe for `gnunet-peerinfo' process.\n" #~ msgstr "Lá»—i bắt đầu thu thập.\n" #, fuzzy #~ msgid "Could not start `%s' process to create hostkey.\n" #~ msgstr "Lá»—i bắt đầu thu thập.\n" #, fuzzy #~ msgid "Failed to start `ssh' process.\n" #~ msgstr "Lá»—i bắt đầu thu thập.\n" #, fuzzy #~ msgid "Error reading from gnunet-peerinfo: %s\n" #~ msgstr "Gặp lá»—i khi Ä‘á»c thông tin từ gnunetd.\n" #, fuzzy #~ msgid "Malformed output from gnunet-peerinfo!\n" #~ msgstr "Gặp lá»—i khi Ä‘á»c thông tin từ gnunetd.\n" #, fuzzy #~ msgid "Could not start `%s' process to start GNUnet.\n" #~ msgstr "Không thể tạo miá»n tên.\n" #, fuzzy #~ msgid "Failed to start `gnunet-arm' process.\n" #~ msgstr "Lá»—i dừng chạy gnunet-auto-share.\n" #, fuzzy #~ msgid "shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n" #~ msgstr "« %s » không phải được kết nối tá»›i đồng đẳng nào.\n" #, fuzzy #~ msgid "Could not start `%s' process to copy configuration directory.\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "Terminating peer `%4s'\n" #~ msgstr "Không đủ quyá»n cho « %s ».\n" #, fuzzy #~ msgid "Setting d->dead on peer `%4s'\n" #~ msgstr "Äang bắt đầu tài lên « %s ».\n" #, fuzzy #~ msgid "Failed to write new configuration to disk." #~ msgstr "Lá»—i lưu cấu hình." #, fuzzy #~ msgid "Could not start `%s' process to copy configuration file.\n" #~ msgstr "Không tìm thấy phương pháp « %s%s » trong thư viện « %s ».\n" #, fuzzy #~ msgid "Failed to copy new configuration to remote machine." #~ msgstr "Lá»—i lưu cấu hình." #, fuzzy #~ msgid "Peers failed to connect" #~ msgstr "Không kết nối được đến trình ná»n gnunetd." #, fuzzy #~ msgid "Failed to connect to core service of first peer!\n" #~ msgstr "Lá»—i nạp dịch vụ sqstore. Hãy kiểm tra lại cấu hình.\n" #, fuzzy #~ msgid "Invalid value `%s' for option `%s' in section `%s': expected float\n" #~ msgstr "" #~ "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #, fuzzy #~ msgid "" #~ "Invalid value `%s' for option `%s' in section `%s': got %f, needed value " #~ "greater than 0\n" #~ msgstr "" #~ "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #, fuzzy #~ msgid "" #~ "No `%s' specified in peer configuration in section `%s', cannot copy " #~ "friends file!\n" #~ msgstr "" #~ "Äặc tả mạng dạng sai trong cấu hình phần « %s » cho mục nhập « %s »: %s\n" #, fuzzy #~ msgid "Unknown topology specification, can't connect peers!\n" #~ msgstr "Lá»—i cú pháp trong sá»± xác định địa hình há»c, Ä‘ang bá» qua các byte.\n" #, fuzzy #~ msgid "Could not create configuration for peer number %u on `%s'!\n" #~ msgstr "Không thể truy cập đến thông tin vá» không gian tên.\n" #, fuzzy #~ msgid "Option `%s' in section `%s' not specified!\n" #~ msgstr "Bị từ chối đặt tùy chá»n « %s » trong phần « %s » thành « %s ».\n" #, fuzzy #~ msgid "Failed to find option %s in section %s!\n" #~ msgstr "Lá»—i đóng kết đến cổng %s %d.\n" #, fuzzy #~ msgid "Invalid configuration option `%s' in section `%s'\n" #~ msgstr "" #~ "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #, fuzzy #~ msgid "Missing configuration option `%s' in section `%s'\n" #~ msgstr "" #~ "Giá trị cấu hình « %s » cho « %s » trong phần « %s » nên là con số\n" #, fuzzy #~ msgid "internal error" #~ msgstr "Lá»—i VR." #, fuzzy #~ msgid "Could not create namespace `%s'\n" #~ msgstr "Không thể tạo miá»n tên.\n" #, fuzzy #~ msgid "Stored zonekey for zone `%s' in file `%s'\n" #~ msgstr "Lá»—i mở tập tin ghi sá»± kiện « %s »: %s\n" #, fuzzy #~ msgid "Namestore removed record successfully" #~ msgstr "Dịch vụ GNUnet đã được cài đặt.\n" #, fuzzy #~ msgid "Could not read hostkeys file, specify hostkey file with -H!\n" #~ msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #, fuzzy #~ msgid "access (%s, X_OK) failed: %s\n" #~ msgstr "SMTP: « %s » bị lá»—i: %s\n" #, fuzzy #~ msgid "# Peers connected" #~ msgstr "# cá»§a các đồng đẳng đã kết nối" #, fuzzy #~ msgid "%s failed for `%s' at %s:%d: `%s'\n" #~ msgstr "%s bị lá»—i tại %s:%d: « %s »\n" #, fuzzy #~ msgid "Failed to transmit shutdown ACK.\n" #~ msgstr "Lá»—i bắt đầu thu thập.\n" #, fuzzy #~ msgid "Unable to initialize Postgres with configuration `%s': %s" #~ msgstr "Không thể lưu tập tin cấu hình « %s »:" #, fuzzy #~ msgid "Target is %d connections per peer." #~ msgstr "Lá»—i thiết lập kết nối vá»›i đồng đẳng.\n" #~ msgid "Connecting nodes in 2d torus topology: %u rows %u columns\n" #~ msgstr "" #~ "Äang kết nối các Ä‘iểm nút theo địa hình há»c hình xuyến hai chiá»u: %u " #~ "hàng, %u cá»™t\n" #, fuzzy #~ msgid "Copying file with RENAME (%s,%s)\n" #~ msgstr "« %s » thất bại vá»›i mã lá»—i %s: %s\n" #, fuzzy #~ msgid "Copying file with command scp %s %s\n" #~ msgstr "« %s » thất bại vá»›i mã lá»—i %s: %s\n" #, fuzzy #~ msgid "Finished copying all blacklist files!\n" #~ msgstr "Không thể Ä‘á»c danh sách bạn bè « %s »\n" #, fuzzy #~ msgid "Failed during blacklist file copying!\n" #~ msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #, fuzzy #~ msgid "# bytes payload received for other peers" #~ msgstr "# các byte kiểu %d được nhận" #, fuzzy #~ msgid "# peers disconnected due to timeout" #~ msgstr "# các kết nối bị đóng (vấn đỠtruyá»n tải)" #, fuzzy #~ msgid "# peers disconnected due to global disconnect" #~ msgstr "# Các quảng cáo đồng đẳng bị há»§y do trá»ng tải" #, fuzzy #~ msgid "# messages not sent (no such peer or not connected)" #~ msgstr "# các thông báo được chắp liá»n" #, fuzzy #~ msgid "# unexpected CONNECT_ACK messages" #~ msgstr "gá»­i ÄẾM thông báo" #, fuzzy #~ msgid "# wlan session created" #~ msgstr "# các khoá phiên chạy được chấp nhận" #, fuzzy #~ msgid "# wlan pending fragments" #~ msgstr "# các mảnh bị loại bá»" #, fuzzy #~ msgid "# wlan fragments send" #~ msgstr "# các mảnh bị loại bá»" #, fuzzy #~ msgid "# wlan whole messages received" #~ msgstr "# các thông báo phát hiện dht được nhận" #, fuzzy #~ msgid "# wlan hello messages received" #~ msgstr "# các thông báo phát hiện dht được nhận" #, fuzzy #~ msgid "# wlan fragments received" #~ msgstr "# các mảnh bị loại bá»" #, fuzzy #~ msgid "# wlan acks received" #~ msgstr "# các yêu cầu khách lá»— hổng được nhận" #, fuzzy #~ msgid "# wlan messages for this client received" #~ msgstr "# các thông báo phát hiện dht được nhận" #, fuzzy #~ msgid "# wlan messages inside WLAN_HELPER_DATA received" #~ msgstr "# các thông báo phát hiện dht được nhận" #, fuzzy #~ msgid "Could not access file: %s\n" #~ msgstr "Không thể truy cập đến « %s »: %s\n" #, fuzzy #~ msgid "`%s' failed on file `%s': %s" #~ msgstr "« %s » thất bại cho ổ đĩa « %s »: %u\n" #, fuzzy #~ msgid "# bytes TCP was asked to transmit" #~ msgstr "# các byte được gá»­i" #, fuzzy #~ msgid "# bytes discarded by TCP (failed to connect)" #~ msgstr "# các byte loại Ä‘i bởi TCP (Ä‘i ra)" #, fuzzy #~ msgid "# wlan messages queued" #~ msgstr "# các thông báo phát hiện dht được nhận" #~ msgid "print this help" #~ msgstr "hiển thị trợ giúp này" #~ msgid "print the version number" #~ msgstr "hiển thị số thứ tá»± phiên bản" #, fuzzy #~ msgid "configure logging to write logs to LOGFILE" #~ msgstr "cấu hình chức năng ghi sá»± kiện để dùng CẤP_GHI_LƯU" #~ msgid "configure logging to use LOGLEVEL" #~ msgstr "cấu hình chức năng ghi sá»± kiện để dùng CẤP_GHI_LƯU" #~ msgid "be verbose" #~ msgstr "xuất chi tiết" #, fuzzy #~ msgid "Failed to start service `%s'!\n" #~ msgstr "Lá»—i bắt đầu thu thập.\n" #, fuzzy #~ msgid "Binary implementing service `%s' not known!\n" #~ msgstr "Không thẩm tra được chữ ký: không rõ đồng đẳng « %s ».\n" #, fuzzy #~ msgid "Service `%s' stopped\n" #~ msgstr "Dịch vụ đã bị xoá.\n" #, fuzzy #~ msgid "Unable to accept connection for service `%s': %s\n" #~ msgstr "Không thể lưu tập tin cấu hình « %s »:" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "MiB" #~ msgstr "MiB" #~ msgid "GiB" #~ msgstr "GiB" #~ msgid "TiB" #~ msgstr "TiB" #, fuzzy #~ msgid "Failed to create IPv4 broadcast socket on port %d\n" #~ msgstr "Lá»—i cập nhật dữ liệu cho mô-Ä‘un « %s »\n" #, fuzzy #~ msgid "Failed to load block plugin `%s'\n" #~ msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #, fuzzy #~ msgid "Could not resolve our FQDN : %s %u\n" #~ msgstr "Không thể giải quyết « %s » (%s): %s\n" #, fuzzy #~ msgid "Failed to load dhtlog plugin for `%s'\n" #~ msgstr "Lá»—i Ä‘á»c danh sách bạn bè từ « %s »\n" #, fuzzy #~ msgid "Found peer `%s'\n" #~ msgstr "Tôi là đồng đẳng « %s ».\n" #, fuzzy #~ msgid "Failed to initialize MySQL database connection for dhtlog.\n" #~ msgstr "Lá»—i sÆ¡ khởi kết nối cÆ¡ sở dữ liệu MySQL cho kho dữ liệu.\n" #, fuzzy #~ msgid "Loading udp transport plugin\n" #~ msgstr "Äang nạp các truyá»n tải « %s »\n" #, fuzzy #~ msgid "curl failed for `%s' at %s:%d: `%s'\n" #~ msgstr "%s bị lá»—i tại %s:%d: « %s »\n" #, fuzzy #~ msgid "Phase 3: sending messages\n" #~ msgstr "Lá»—i gá»­i tin nhẳn.\n" #, fuzzy #~ msgid "Loading HTTPS transport plugin `%s'\n" #~ msgstr "Äang nạp các truyá»n tải « %s »\n" #, fuzzy #~ msgid "Failed to load transport plugin for https\n" #~ msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #, fuzzy #~ msgid "Fail! Could not connect peers\n" #~ msgstr "Không thể kết nối tá»›i %s:%u: %s\n" #, fuzzy #~ msgid "Loading tcp transport plugin\n" #~ msgstr "Äang nạp các truyá»n tải « %s »\n" #, fuzzy #~ msgid "Failed to load transport plugin for tcp\n" #~ msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #, fuzzy #~ msgid "# HTTP peers active" #~ msgstr "# Tín hiệu HTTP GET được nhận" #, fuzzy #~ msgid "Failed to load transport plugin for http\n" #~ msgstr "Không thể nạp phần bổ sung truyá»n tải « %s »\n" #, fuzzy #~ msgid "# PING messages decrypted" #~ msgstr "# các thông báo PING được tạo" #, fuzzy #~ msgid "# bytes successfully transmitted by plugins" #~ msgstr "# các byte được gá»­i" #, fuzzy #~ msgid "# connected addresses" #~ msgstr "# cá»§a các đồng đẳng đã kết nối" #, fuzzy #~ msgid "# transport failed to selected peer address" #~ msgstr "Äang quảng cáo truyá»n tải %d cá»§a mình tá»›i các đồng đẳng đã chá»n.\n" #, fuzzy #~ msgid "# peer addresses considered valid" #~ msgstr "# Các quảng cáo đồng đẳng được xác nhận qua PONG" #, fuzzy #~ msgid "# PING with HELLO messages sent" #~ msgstr "# các thông báo PING được tạo" #, fuzzy #~ msgid "# HELLOs received for validation" #~ msgstr "# các khối được lấy để nâng cấp" #, fuzzy #~ msgid "Received `%s' message from `%s' destined for `%s' which is not me!\n" #~ msgstr "Nhận được PING « %s » không dành cho chúng ta.\n" #~ msgid "Error" #~ msgstr "Lá»—i" #~ msgid "Help" #~ msgstr "Trợ giúp" #~ msgid "Error!" #~ msgstr "Lá»—i !" #~ msgid "No" #~ msgstr "Không" #~ msgid "Yes" #~ msgstr "Có" #~ msgid "Internal error! (Choice invalid?)" #~ msgstr "Lá»—i ná»™i bá»™ (sai chá»n ?)" #~ msgid "Abort" #~ msgstr "Há»§y" #~ msgid "Ok" #~ msgstr "OK" #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://gnunet.org/\n" #~ "and join our community at\n" #~ "\thttp://gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "the GNUnet team" #~ msgstr "" #~ "Xin chào mừng tá»›i GNUnet !\n" #~ "\n" #~ "Trình giúp đỡ này sẽ há»i bạn vài câu cÆ¡ bản để cấu hình GNUnet.\n" #~ "\n" #~ "Xin hãy thăm trang chá»§ cá»§a chúng tôi tại\n" #~ "\thttp://gnunet.org\n" #~ "và tham gia cá»™ng đồng tại\n" #~ "\thttp://www.gnunet.org/drupal/\n" #~ "\n" #~ "Chúc có nhiá»u niá»m vui,\n" #~ "\n" #~ "đội GNUnet" #~ msgid "" #~ "Choose the network interface that connects your computer to the internet " #~ "from the list below." #~ msgstr "" #~ "Chá»n giao diện mạng kết nối máy tính tá»›i Internet từ danh sách dưới đây." #~ msgid "" #~ "The \"Network interface\" is the device that connects your computer to " #~ "the internet. This is usually a modem, an ISDN card or a network card in " #~ "case you are using DSL." #~ msgstr "" #~ "« Giao diện mạng » là thiết bị kết nối máy tính vá»›i Internet. Äây thưá»ng " #~ "là má»™t bá»™ Ä‘iá»u giải, má»™t bo mạch ISDN hay má»™t bo mạch mạng nếu dùng DSL." #~ msgid "Network configuration: interface" #~ msgstr "Cấu hình mạng: giao diện" #~ msgid "" #~ "What is the name of the network interface that connects your computer to " #~ "the Internet?" #~ msgstr "Máy tính này kết nối tá»›i Internet qua giao diện mạng tên nào?" #~ msgid "Network configuration: IP" #~ msgstr "Cấu hình mạng: IP" #~ msgid "What is this computer's public IP address or hostname?" #~ msgstr "Äịa chỉ IP công cá»™ng hoặc tên cá»§a máy tính này là gì?" #~ msgid "" #~ "If your provider always assigns the same IP-Address to you (a \"static\" " #~ "IP-Address), enter it into the \"IP-Address\" field. If your IP-Address " #~ "changes every now and then (\"dynamic\" IP-Address) but there's a " #~ "hostname that always points to your actual IP-Address (\"Dynamic DNS\"), " #~ "you can also enter it here.\n" #~ "If left empty, GNUnet will try to automatically detect the IP.\n" #~ "You can specify a hostname, GNUnet will then use DNS to resolve it.\n" #~ "If in doubt, leave this empty." #~ msgstr "" #~ "Nếu nhà cung cấp luôn luôn gán cùng má»™t địa chỉ IP (má»™t địa chỉ IP « tÄ©nh " #~ "»), thì hãy nhập địa chỉ đó vào vùng « Äịa chỉ IP ». Nếu địa chỉ IP thay " #~ "đổi sau má»—i lần kết nối (địa chỉ IP « động ») nhưng có má»™t tên máy luôn " #~ "luôn chỉ tá»›i địa chỉ IP thá»±c cá»§a bạn (« DNS động »), thì cÅ©ng có thể nhập " #~ "nó ở đây.\n" #~ "Nếu không biết phải làm gì, thì hãy để trống. GNUnet sẽ thá»­ tá»± động phát " #~ "hiện địa chỉ IP.\n" #~ "Bạn cÅ©ng có thể ghi rõ tên máy. Vì thế GNUnet sẽ dùng dịch vụ DNS để giải " #~ "quyết nó." #~ msgid "Bandwidth configuration: upload" #~ msgstr "Cấu hình dải thông: tải lên" #~ msgid "How much upstream bandwidth (in bytes/s) may be used?" #~ msgstr "Dòng ra có thể dùng bao nhiêu byte?" #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "The \"upstream\" is the data channel through which data is *sent* to the " #~ "internet. The limit is the maximum amount which GNUnet is allowed to use. " #~ "If you have a flatrate, you can set it to the maximum speed of your " #~ "internet connection. You should not use a value that is higher than what " #~ "your actual connection allows." #~ msgstr "" #~ "Có thể giá»›i hạn sá»­ dụng tài nguyên cá»§a GNUnet ở đây.\n" #~ "\n" #~ "« Dòng ra » (upstream) là kênh dữ liệu qua đó _gá»­i_ dữ liệu tá»›i Internet. " #~ "Giá»›i hạn là số tối Ä‘a được gán cho GNUnet. Nếu có tốc độ Ä‘á»u, thì có thể " #~ "đặt thành tốc độ kết nối Internet lá»›n nhất. Không nên đặt giá trị lá»›n hÆ¡n " #~ "số được gán cho kết nối Internet cá»§a bạn." #~ msgid "Bandwidth configuration: download" #~ msgstr "Cấu hình dải thông: tải xuống" #~ msgid "How much downstream bandwidth (in bytes/s) may be used?" #~ msgstr "Dòng vào có thể dùng bao nhiêu byte?" #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "The \"downstream\" is the data channel through which data is *received* " #~ "from the internet. The limit is the maximum amount which GNUnet is " #~ "allowed to use. If you have a flatrate, you can set it to the maximum " #~ "speed of your internet connection. You should not use a value that is " #~ "higher than what your actual connection allows." #~ msgstr "" #~ "Có thể giá»›i hạn sá»­ dụng tài nguyên cá»§a GNUnet ở đây.\n" #~ "\n" #~ "« Dòng vào » (downstream) là kênh dữ liệu qua đó _nhận_ dữ liệu từ " #~ "Internet. Giá»›i hạn là số tối Ä‘a được gán cho GNUnet. Nếu có tốc độ Ä‘á»u, " #~ "thì có thể đặt thành tốc độ kết nối Internet lá»›n nhất. Không nên đặt giá " #~ "trị lá»›n hÆ¡n số được gán cho kết nối Internet cá»§a bạn." #~ msgid "Quota configuration" #~ msgstr "Cấu hình hạn ngạch" #~ msgid "What is the maximum size of the datastore in MB?" #~ msgstr "Kho dữ liệu có kích cỡ tối Ä‘a (theo MB)?" #~ msgid "" #~ "The GNUnet datastore contains all content that GNUnet needs to store " #~ "(indexed, inserted and migrated content)." #~ msgstr "" #~ "Kho dữ liệu GNUnet chứa tất cả các dữ liệu GNUnet cần cất giữ (dữ liệu " #~ "chỉ mục, ná»™i dung chèn và nhập vào)." #~ msgid "Daemon configuration: user account" #~ msgstr "Cấu hình trình ná»n: tài khoản ngưá»i dùng" #~ msgid "As which user should gnunetd be run?" #~ msgstr "Trình ná»n gnunetd nên chạy vá»›i tư cách ngưá»i dùng nào?" #~ msgid "" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "user account under which the GNUnet service is started at system " #~ "startup.\n" #~ "\n" #~ "However, GNUnet may not be able to access files other than its own. This " #~ "includes files you want to publish in GNUnet. You'll have to grant read " #~ "permissions to the user specified below.\n" #~ "\n" #~ "Leave the field empty to run GNUnet with system privileges.\n" #~ msgstr "" #~ "Vì lý do bảo mật, nên cho phép thiết lập này tạo má»™t tài khoản ngưá»i dùng " #~ "má»›i sở hữu dịch vụ GNUnet chạy má»—i khi khởi động máy tính.\n" #~ "\n" #~ "Tuy nhiên, GNUnet có thể không truy cập được tá»›i các tập tin mà nó không " #~ "sở hữu, bao gồm các tập tin ngưá»i dùng muốn đưa ra chia sẻ trong GNUnet. " #~ "Sẽ cần cho phép ngưá»i dùng chỉ ra dưới đây quyá»n Ä‘á»c chúng.\n" #~ "\n" #~ "Äể trống để chạy GNUnet vá»›i quyá»n hệ thống.\n" #~ msgid "Daemon configuration: group account" #~ msgstr "Cấu hình trình ná»n: tài khoản nhóm" #~ msgid "As which group should gnunetd be run?" #~ msgstr "gnunetd nên chạy như nhóm nào?" #~ msgid "" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "group for the chosen user account.\n" #~ "\n" #~ "You can also specify a already existent group here.\n" #~ "\n" #~ "Only members of this group will be allowed to start and stop the the " #~ "GNUnet server and have access to GNUnet server data.\n" #~ msgstr "" #~ "Vì lý do bảo mật, nên để thiết lập này tạo má»™t nhóm má»›i cho tài khoản " #~ "ngưá»i dùng đã chá»n\n" #~ "\n" #~ "CÅ©ng có thể chỉ ra má»™t nhóm đã có.\n" #~ "\n" #~ "Chỉ thành viên cá»§a nhóm này má»›i có quyá»n chạy và dừng trình phục vụ " #~ "GNUnet và có truy cập tá»›i dữ liệu cá»§a trình phục vụ GNUnet.\n" #~ msgid "Do you want to automatically launch GNUnet as a system service?" #~ msgstr "Bạn có muốn tá»± động khởi chạy GNUnet như là dịch vụ hệ thống không?" #~ msgid "" #~ "If you say \"yes\" here, the GNUnet background process will be " #~ "automatically started when you turn on your computer. If you say \"no\" " #~ "here, you have to launch GNUnet yourself each time you want to use it." #~ msgstr "" #~ "Bật tùy chá»n này thì tiến trình GNUnet ná»n được tá»± động khởi chạy má»—i lần " #~ "mở máy tính. Không thì bạn cần phải tá»± khởi chạy GNUnet má»—i lần để sá»­ " #~ "dụng nó." #~ msgid "Unable to create user account for daemon." #~ msgstr "Không thể tạo tài khoản ngưá»i dùng cho trình ná»n." #~ msgid "Unable to setup autostart for daemon." #~ msgstr "Không thể thiết lập chức năng tá»± động khởi chạy cho trình ná»n." #~ msgid "Save configuration?" #~ msgstr "Lưu cấu hình không?" #~ msgid "GNUnet Configuration" #~ msgstr "Cấu hình GNUnet" #~ msgid "Back" #~ msgstr "Lùi" #~ msgid "Up" #~ msgstr "Lên" #~ msgid "Cancel" #~ msgstr "Thôi" #~ msgid "Internal error! (Value invalid?)" #~ msgstr "Lá»—i ná»™i bá»™ (giá trị sai ?)" #~ msgid "Invalid input, expecting floating point value." #~ msgstr "Dữ liệu nhập sai, mong đợi giá trị chấm động." #~ msgid "Invalid input, expecting integer." #~ msgstr "Dữ liệu nhập sai, mong đợi số nguyên." #~ msgid "Configuration unchanged, no need to save.\n" #~ msgstr "Cấu hình chưa thay đổi thì không cần lưu lại.\n" #~ msgid "Do you wish to save your new configuration?" #~ msgstr "Bạn có muốn lưu cấu hình má»›i không?" #~ msgid "" #~ "\n" #~ "Your configuration changes were NOT saved.\n" #~ msgstr "" #~ "\n" #~ "CHƯA lưu các thay đổi trong cấu hình.\n" #~ msgid "install GNUnet as Windows service" #~ msgstr "cài đặt GNUnet như là má»™t dịch vụ Windows" #~ msgid "display a file's hash value" #~ msgstr "hiển thị giá trị tổng kiểm cá»§a tập tin" #~ msgid "This version of Windows doesn't support services.\n" #~ msgstr "Phiên bản Windows này không há»— trợ dịch vụ.\n" #~ msgid "Error: can't open Service Control Manager: %s\n" #~ msgstr "Lá»—i: không thể mở Bá»™ Quản lý Äiá»u khiển Dịch vụ : %s\n" #~ msgid "Error: can't create service: %s\n" #~ msgstr "Lá»—i: không thể tạo dịch vụ : %s\n" #~ msgid "Error: can't access service: %s\n" #~ msgstr "Lá»—i: không thể truy cập đến dịch vụ : %s\n" #~ msgid "Error: can't delete service: %s\n" #~ msgstr "Lá»—i: không thể xoá dịch vụ : %s\n" #~ msgid "Configuration changed. Save?" #~ msgstr "Cấu hình bị thay đổi. Lưu ?" #~ msgid "Error saving configuration." #~ msgstr "Gặp lá»—i khi lưu cấu hình." #~ msgid "(unknown connection)" #~ msgstr "(không rõ kết nối)" #~ msgid "Do you want to save the new configuration?" #~ msgstr "Bạn có muốn lưu cấu hình má»›i này không?" #~ msgid "Unable to change startup process:" #~ msgstr "Không thể thay đổi tiến trình khởi chạy:" #~ msgid "" #~ "Running gnunet-update failed.\n" #~ "This maybe due to insufficient permissions, please check your " #~ "configuration.\n" #~ "Finally, run gnunet-update manually." #~ msgstr "" #~ "Lá»—i chạy tiến trình cập nhật gnunet-update.\n" #~ "Äây có thể do không đủ quyá»n, hãy kiểm tra cấu hình.\n" #~ "Cuối cùng, chạy gnunet-update thá»§ công." #~ msgid "Can only set one option per invocation.\n" #~ msgstr "Chỉ có thể đặt má»™t tùy chá»n trong má»—i cuá»™c gá»i.\n" #~ msgid "" #~ "Invalid syntax, argument to 'set' must have the format SECTION:" #~ "OPTION=VALUE.\n" #~ msgstr "" #~ "Cú pháp sai, đối số tá»›i « set » phải theo định dạng:\n" #~ "PHẦN:TÙY_CHỌN­=GIÃ_TRỊ\n" #~ msgid "Can only display one option per invocation.\n" #~ msgstr "Chỉ có thể hiển thị má»™t tùy chá»n trong má»—i cuá»™c gá»i.\n" #~ msgid "" #~ "Invalid syntax, argument to 'get' must have the format SECTION:OPTION.\n" #~ msgstr "" #~ "Cú pháp sai, đối số tá»›i « get » phải theo định dạng:\n" #~ "PHẦN:TÙY_CHỌN\n" #~ msgid "generate configuration for gnunetd, the GNUnet daemon" #~ msgstr "tạo ra cấu hình cho gnunetd, trình ná»n GNUnet" #~ msgid "Tool to setup GNUnet." #~ msgstr "Công cụ để thiết lập GNUnet." #~ msgid "Too many arguments.\n" #~ msgstr "Quá nhiá»u đối số.\n" #~ msgid "Undefined option.\n" #~ msgstr "Tùy chá»n không xác định.\n" #~ msgid "yes" #~ msgstr "có" #~ msgid "no" #~ msgstr "không" #~ msgid "\tEnter yes (%s), no (%s) or help (%s): " #~ msgstr "\tNhập có (%s), không (%s) hoặc trợ giúp (%s): " #~ msgid "\tPossible choices:\n" #~ msgstr "\tLá»±a chá»n có thể:\n" #~ msgid "\tUse single space prefix to avoid conflicts with hotkeys!\n" #~ msgstr "\tHãy dùng tiá»n tố má»™t dấu cách để tránh xung đột vá»›i phím nóng.\n" #~ msgid "\tEnter string (type '%s' for default value `%s'): " #~ msgstr "\tNhập chuá»—i (gõ « %s » cho giá trị mặc định « %s »): " #~ msgid "\t Enter choice (default is %c): " #~ msgstr "\t Nhập sá»± chá»n (mặc định là %c):" #~ msgid "\tEnter floating point (type '%s' for default value %f): " #~ msgstr "\tNhập chấm động (gõ « %s » cho giá trị mặc định %f): " #~ msgid "" #~ "\tEnter unsigned integer in interval [%llu,%llu] (type '%s' for default " #~ "value %llu): " #~ msgstr "" #~ "\tNhập số nguyên không có dấu trong khoảng [%llu,%llu] (gõ « %s » cho giá " #~ "trị mặc định %llu): " #~ msgid "Yes\n" #~ msgstr "Có\n" #~ msgid "No\n" #~ msgstr "Không\n" #~ msgid "Help\n" #~ msgstr "Trợ giúp\n" #~ msgid "Abort\n" #~ msgstr "Há»§y bá»\n" #~ msgid "" #~ "\n" #~ "Invalid entry, try again (use '?' for help): " #~ msgstr "" #~ "\n" #~ "Dữ liệu nhập sai. Hãy thá»­ lại (dùng « ? » để xem trợ giúp): " #~ msgid "Unknown kind %x (internal error). Skipping option.\n" #~ msgstr "Kiểu không rõ %x (lá»—i ná»™i bá»™). Äang bá» qua tùy chá»n.\n" #~ msgid "\tDescend? (y/n/?) " #~ msgstr "\tGiảm dần ? (c/k?)" #~ msgid "Aborted.\n" #~ msgstr "Bị há»§y bá».\n" #~ msgid "Unknown kind %x (internal error). Aborting.\n" #~ msgstr "Kiểu không rõ %x (lá»—i ná»™i bá»™). Äang há»§y bá».\n" #~ msgid "You can always press ENTER to keep the current value.\n" #~ msgstr "" #~ "Lúc nào bạn cÅ©ng có thể bấm phím Enter để giữ lại giá trị hiện có.\n" #~ msgid "Use the '%s' key to abort.\n" #~ msgstr "Dùng phím « %s » để há»§y bá».\n" #~ msgid "" #~ "Save configuration? Answer 'y' for yes, 'n' for no, 'r' to repeat " #~ "configuration. " #~ msgstr "" #~ "Lưu lại cấu hình không?\n" #~ " • y\t\tcó\n" #~ " • n\t\tkhông\n" #~ " • r\t\tlặp lại cấu hình." #~ msgid "Configuration was unchanged, no need to save.\n" #~ msgstr "Cấu hình chưa thay đổi thì không cần lưu lại.\n" #~ msgid "" #~ "Internal error: entry `%s' in section `%s' not found for visibility " #~ "change!\n" #~ msgstr "" #~ "Lá»—i ná»™i bá»™ : mục nhập « %s » trong phần « %s » không tìm thấy để thay đổi " #~ "tình trạng hiển rõ.\n" #~ msgid "Can't open Service Control Manager" #~ msgstr "Không thể mở Bá»™ Quản lý Äiá»u khiển Dịch vụ" #~ msgid "Can't create service" #~ msgstr "Không thể tạo dịch vụ" #~ msgid "Error changing the permissions of the GNUnet directory" #~ msgstr "Gặp lá»—i khi thay đổi quyá»n hạn cá»§a thư mục GNUnet" #~ msgid "Cannot write to the registry" #~ msgstr "Không thể ghi vào sổ đăng ký" #~ msgid "Can't delete the service" #~ msgstr "Không thể xoá dịch vụ" #~ msgid "This version of Windows does not support multiple users." #~ msgstr "Phiên bản Windows này không có há»— trợ Ä‘a ngưá»i dùng." #~ msgid "Error accessing local security policy" #~ msgstr "Gặp lá»—i khi truy cập đến chính sách bảo mật cục bá»™" #~ msgid "Error granting service right to user" #~ msgstr "Gặp lá»—i khi cấp quyá»n dịch vụ cho ngưá»i dùng" #~ msgid "Unknown error while creating a new user" #~ msgstr "Gặp lá»—i không rõ trong khi tạo má»™t ngưá»i dùng má»›i" #~ msgid "" #~ "\n" #~ "Press any key to continue\n" #~ msgstr "" #~ "\n" #~ "Hãy bấm bất cứ phím nào để tiếp tục.\n" #~ msgid "STATUS" #~ msgstr "TRẠNG THÃI" #~ msgid "FATAL" #~ msgstr "NGHIÊM TRỌNG" #~ msgid "USER" #~ msgstr "NGƯỜI DÙNG" #~ msgid "ADMIN" #~ msgstr "QUẢN TRỊ" #~ msgid "DEVELOPER" #~ msgstr "NHÀ PHÃT TRIỂN" #~ msgid "REQUEST" #~ msgstr "YÊU CẦU" #~ msgid "BULK" #~ msgstr "HÀNG LOẠT" #~ msgid "IMMEDIATE" #~ msgstr "NGAY" #~ msgid "ALL" #~ msgstr "TẤT CẢ" #~ msgid "NOTHING" #~ msgstr "KHÔNG GÃŒ" #, fuzzy #~ msgid "Could not find valid value for HOST in section NETWORK.\n" #~ msgstr "Không tìm thấy giá trị đúng cho MÃY trong phần MẠNG." #, fuzzy #~ msgid "Syntax error in configuration entry HOST in section NETWORK: `%s'\n" #~ msgstr "Gặp lá»—i cú pháp trong mục nhập cấu hình MÃY trong phần MẠNG: « %s »" #~ msgid "Error connecting to %s:%u. Is the daemon running?\n" #~ msgstr "Gặp lá»—i khi kết nối tá»›i %s:%u. Trình ná»n Ä‘ang chạy không?\n" #~ msgid "Reading result from gnunetd failed, reply invalid!\n" #~ msgstr "Lá»—i Ä‘á»c kết quả từ gnunetd, đáp ứng không hợp lệ.\n" #~ msgid "" #~ "Setting option `%s' in section `%s' to `%s' when processing command line " #~ "option `%s' was denied.\n" #~ msgstr "" #~ "Bị từ chối đặt tùy chá»n « %s » trong phần « %s » thành « %s » khi xá»­ lý " #~ "tùy chá»n dòng lệnh « %s ».\n" #~ msgid "No interface specified in section `%s' under `%s'!\n" #~ msgstr "" #~ "Không có giao diện mạng được xác định trong cấu hình phần « %s » dưới « " #~ "%s ».\n" #~ msgid "" #~ "Could not find interface `%s' using `%s', trying to find another " #~ "interface.\n" #~ msgstr "" #~ "Không tìm thấy giao diện « %s » trong « %s », Ä‘ang thá»­ tìm giao diện " #~ "khác.\n" #~ msgid "Could not find an IP address for interface `%s'.\n" #~ msgstr "Không tìm thấy má»™t địa chỉ IP cho giao diện « %s ».\n" #~ msgid "" #~ "There is more than one IP address specified for interface `%s'.\n" #~ "GNUnet will use %s.\n" #~ msgstr "" #~ "Có vài địa chỉ IP chỉ ra cho giao diện « %s ».\n" #~ "GNUnet sẽ dùng %s.\n" #~ msgid "Could not resolve `%s' to determine our IP address: %s\n" #~ msgstr "" #~ "Không thể giải quyết « %s » để quyết định địa chỉ IP cá»§a chúng ta: %s\n" #~ msgid "Received malformed message (too small) from connection. Closing.\n" #~ msgstr "Nhận được thông báo bị há»ng (quá nhá») từ kết nối. Äang đóng.\n" #~ msgid "select listen socket for `%s' not valid!\n" #~ msgstr "sai chá»n ổ cắm lắng nghe cho « %s »\n" #~ msgid "" #~ "Configuration value '%llu' for '%s' in section '%s' is out of legal " #~ "bounds [%llu,%llu]\n" #~ msgstr "" #~ "Giá tri cấu hình « %llu » cho « %s » trong phần « %s » ở ngoại phạm vi " #~ "được phép [%llu,%llu]\n" #~ msgid "`%s' returned with error code %u" #~ msgstr "« %s » trả lại vá»›i mã lá»—i %u" #~ msgid "Can't create semaphore: %i" #~ msgstr "Không thể tạo cá» hiệu : %i" #~ msgid "Cannot query the CPU usage (Windows NT).\n" #~ msgstr "Không há»i được sá»± sá»­ dụng CPU (Windows NT).\n" #~ msgid "Cannot query the CPU usage (Win 9x)\n" #~ msgstr "Không há»i được sá»± sá»­ dụng CPU (Windows 9x).\n" #~ msgid "" #~ "No network interfaces defined in configuration section `%s' under `%s'!\n" #~ msgstr "" #~ "Không có giao diện mạng được xác định trong cấu hình phần « %s » dưới « " #~ "%s ».\n" #~ msgid "Setting open descriptor limit not supported.\n" #~ msgstr "Không há»— trợ chức năng đặt giá»›i hạn bá»™ mô tả còn mở.\n" #~ msgid "Command `%s' failed with error code %u\n" #~ msgstr "Câu lệnh « %s » đã thất bại vá»›i mã lá»—i %u\n" #~ msgid "Real-time delay violation (%llu ms) at %s:%u\n" #~ msgstr "Xâm phạm khoảng đợi thá»i gian thá»±c (%llu miligiây) tại %s:%u\n" #~ msgid "Deadlock due to `%s'.\n" #~ msgstr "Bế tắc do « %s ».\n" #~ msgid "Lock acquired for too long (%llu ms) at %s:%u\n" #~ msgstr "Khoá đặt được quá lâu (%llu miligiây) tại %s:%u\n" #~ msgid "Out of memory (for logging)\n" #~ msgstr "Tràn bá»™ nhá»› (để ghi sá»± kiện)\n" #~ msgid "Availability test failed for `%s' at %s:%d.\n" #~ msgstr "Lá»—i kiểm tra tình trạng sẵn sàng cho « %s » tại %s:%d.\n" #~ msgid "# bloom filter false positives" #~ msgstr "# các dương giả cá»§a bá»™ lá»c bloom" #~ msgid "Failed to load state service. Trying to do without.\n" #~ msgstr "Lá»—i nạp dịch vụ tình trạng. Không có nhưng vẫn Ä‘ang thá»­ tiếp tục.\n" #~ msgid "Datastore conversion at approximately %u%%\n" #~ msgstr "Chuyển đổi kho dữ liệu theo xấp xỉ %u%%\n" #~ msgid "Starting datastore conversion (this may take a while).\n" #~ msgstr "Äang bắt đầu chuyển đổi kho dữ liệu (có thể hÆ¡i lâu).\n" #~ msgid "Completed datastore conversion.\n" #~ msgstr "Hoàn tất chuyển đổi kho dữ liệu.\n" #~ msgid "" #~ "%s:%d - RPC %s:%p could not be registered: another callback is already " #~ "using this name (%p)\n" #~ msgstr "" #~ "%s:%d - RPC %s:%p không đăng ký được: má»™t cuá»™c gá»i ngược lại khác Ä‘ang " #~ "dùng tên này (%p)\n" #~ msgid "%s:%d - async RPC %s:%p could not be unregistered: not found\n" #~ msgstr "" #~ "%s:%d - RPC không đồng bá»™ %s:%p không há»§y đăng ký được: không tìm thấy\n" #~ msgid "`%s' registering handlers %d %d %d\n" #~ msgstr "« %s » Ä‘ang đăng ký các trình Ä‘iá»u khiển %d %d %d\n" #~ msgid "Using %u messages of size %u for %u times.\n" #~ msgstr "Sá»­ dụng %u thông báo vá»›i kích cỡ %u trong %u lần.\n" #~ msgid "Times: max %16llu min %16llu mean %12.3f variance %12.3f\n" #~ msgstr "Thá»i gian: đại %16llu tiểu %16llu t.bình %12.3f ph.sai %12.3f\n" #~ msgid "Loss: max %16u min %16u mean %12.3f variance %12.3f\n" #~ msgstr "Mất: đại %16u tiểu %16u t.bình %12.3f ph.sai %12.3f\n" #~ msgid "Running benchmark...\n" #~ msgstr "Äang chạy tiến trình kiểm chuẩn...\n" #~ msgid "allows profiling of direct peer-to-peer connections" #~ msgstr "cho phép Ä‘o hiệu năng sá»­ dụng cá»§a kết nối đồng đẳng trá»±c tiếp" #~ msgid "Start GNUnet transport benchmarking tool." #~ msgstr "Khởi chạy công cụ kiểm chuẩn truyá»n tải cá»§a GNUnet." #~ msgid "output in gnuplot format" #~ msgstr "kết xuất theo định dạng gnuplot" #~ msgid "number of messages to use per iteration" #~ msgstr "số tin nhắn cần dùng má»—i lần lặp" #~ msgid "receiver host identifier (ENC file name)" #~ msgstr "đồ nhận diện máy nhận (tên tập tin mã hoá)" #~ msgid "message size" #~ msgstr "kích cỡ tin nhắn" #~ msgid "sleep for SPACE ms after each a message block" #~ msgstr "ngá»§ KHOẢNG miligiây sau má»—i khối tin nhắn" #~ msgid "number of messages in a message block" #~ msgstr "số tin nhắn trong má»™t khối tin nhắn" #~ msgid "Error establishing connection with gnunetd.\n" #~ msgstr "Lá»—i thiết lập kết nối đến gnunetd.\n" #~ msgid "You must specify a receiver!\n" #~ msgstr "Phải ghi rõ má»™t máy nhận.\n" #~ msgid "Invalid receiver peer ID specified (`%s' is not valid name).\n" #~ msgstr "" #~ "Chỉ ra mã số đồng đẳng nhận sai (« %s » không phải là má»™t tên đúng).\n" #~ msgid "Time:\n" #~ msgstr "Thá»i gian:\n" #~ msgid "\tmax %llums\n" #~ msgstr "\tđại %llu mg\n" #~ msgid "\tmin %llums\n" #~ msgstr "\ttiểu %llu mg\n" #~ msgid "\tmean %8.4fms\n" #~ msgstr "\ttrung bình %8.4f mg\n" #~ msgid "\tvariance %8.4fms\n" #~ msgstr "\tphương sai %8.4f mg\n" #~ msgid "Loss:\n" #~ msgstr "Mất:\n" #~ msgid "\tmax %u\n" #~ msgstr "\tđại %u\n" #~ msgid "\tmin %u\n" #~ msgstr "\ttiểu %u\n" #~ msgid "\tmean %8.4f\n" #~ msgstr "\tt.bình %8.4f\n" #~ msgid "\tvariance %8.4f\n" #~ msgstr "\tph.sai %8.4f\n" #~ msgid "Output format not known, this should not happen.\n" #~ msgstr "Äịnh dạng kết xuất không rõ, Ä‘iá»u này không nên xảy ra.\n" #~ msgid "" #~ "\n" #~ "Did not receive the message from gnunetd. Is gnunetd running?\n" #~ msgstr "" #~ "\n" #~ "Không nhận được thông báo từ gnunetd. Trình ná»n gnunetd Ä‘ang chạy không?\n" #~ msgid "# bytes received in plaintext of type %d" #~ msgstr "# các byte nhập thô kiểu %d được nhận" #, fuzzy #~ msgid "# bytes allocated by SQLite" #~ msgstr "# các byte được phép trong kho dữ liệu" #~ msgid "" #~ "Failed to load MySQL database module. Check that MySQL is running and " #~ "configured properly!\n" #~ msgstr "" #~ "Lá»—i nạp mô-Ä‘un cÆ¡ sở dữ liệu MySQL. Hãy kiểm tra lại MySQL Ä‘ang chạy và " #~ "có cấu hình đúng.\n" #~ msgid "probe network to the given DEPTH" #~ msgstr "dò mạng tá»›i độ sâu SÂU đưa ra" #~ msgid "" #~ "specify output format; 0 for human readable output, 1 for dot, 2 for vcg" #~ msgstr "" #~ "chỉ ra định dạng kết quả;\n" #~ " • 0\t\tkết xuất cho ngưá»i Ä‘á»c được\n" #~ " • 1\t\tdấu chấm\n" #~ " • 2\t\tvcg" #~ msgid "use PRIORITY for the priority of the trace request" #~ msgstr "dùng ƯU_TIÊN làm ưu tiên cá»§a yêu cầu tìm đưá»ng" #~ msgid "wait DELAY seconds for replies" #~ msgstr "đợi đáp ứng TRỄ giây" #~ msgid "" #~ "Format specification invalid. Use 0 for user-readable, 1 for dot, 2 for " #~ "vcg.\n" #~ msgstr "" #~ "Äặt tả định dạng sai. Dùng:\n" #~ " • 0\t\tkết xuất cho ngưá»i Ä‘á»c được\n" #~ " • 1\t\tdấu chấm\n" #~ " • 2\t\tvcg\n" #~ msgid "allows mapping of the network topology" #~ msgstr "cho phép ánh xạ địa hình cá»§a mạng" #~ msgid "HELLO message from `%s' has an invalid signature. Dropping.\n" #~ msgstr "Thông báo HELLO từ « %s » có chữ ký sai. Äang bá» Ä‘i.\n" #~ msgid "HELLO message has expiration too far in the future. Dropping.\n" #~ msgstr "Thông báo HELLO hết hạn trong tương lai quá nhiá»u. Äang bá» Ä‘i.\n" #~ msgid "Could not send HELLO+PING, ping buffer full.\n" #~ msgstr "Không gá»­i được tín hiệu HELLO+PING, đầy bá»™ đệm ping.\n" #~ msgid "" #~ "Failed to create an advertisement for this peer. Will not send PING.\n" #~ msgstr "" #~ "Không tạo được quảng cáo cho đồng đẳng này. Sẽ không gá»­i tín hiệu PING.\n" #~ msgid "" #~ "Announcing ourselves pointless: no other peers are known to us so far.\n" #~ msgstr "Không có nghÄ©a khi tá»± thông báo : chưa biết đồng đẳng khác.\n" #~ msgid "# Peer advertisements of type NAT received" #~ msgstr "# Các quảng cáo đồng đẳng kiểu NAT được nhận" #~ msgid "# Peer advertisements updating earlier HELLOs" #~ msgstr "# Các quảng cáo đồng đẳng cập nhật tin hiệu HELLO trước" #~ msgid "# Peer advertisements for unsupported transport" #~ msgstr "# Các quảng cáo đồng đẳng cho truyá»n tải không được há»— trợ" #~ msgid "# Peer advertisements not confirmed due to ping busy" #~ msgstr "# Các quảng cáo đồng đẳng không được xác nhận do ping Ä‘ang bận" #~ msgid "# Peer advertisements not confirmed due to lack of self ad" #~ msgstr "# Các quảng cáo đồng đẳng không được xác nhận do không tá»± quảng cáo" #~ msgid "# Peer advertisements not confirmed due to send error" #~ msgstr "# Các quảng cáo đồng đẳng không được xác nhận do lá»—i gá»­i" #~ msgid "`%s' registering handler %d (plaintext and ciphertext)\n" #~ msgstr "" #~ "« %s » Ä‘ang đăng ký trình Ä‘iá»u khiển %d (nhập thô và văn bản mã hóa)\n" #~ msgid "" #~ "ensures that this peer is known by other peers and discovers other peers" #~ msgstr "" #~ "đảm bảo là đồng đẳng này được biết bởi và phát hiện các đồng đẳng khác" #~ msgid "maintains GNUnet default mesh topology" #~ msgstr "bảo quản định hình mắc lưới mặc định cá»§a GNUnet" #~ msgid "`%s' registering CS handlers %d and %d\n" #~ msgstr "« %s » Ä‘ang đăng ký các trình Ä‘iá»u khiển CS %d và %d\n" #~ msgid "enables P2P-chat (incomplete)" #~ msgstr "hiệu lá»±c trò chuyện giữa các đồng đẳng (chưa hoàn tất)" #~ msgid "Existing key in file `%s' failed format check, creating new key.\n" #~ msgstr "" #~ "Kiểm tra định dạng cá»§a chìa khóa đã có trong tập tin « %s » không thành " #~ "công, Ä‘ang tạo chìa khóa máy má»›i.\n" #~ msgid "Creating new key for this nickname (this may take a while).\n" #~ msgstr "Äang tạo khoá má»›i cho tên hiệu này (có thể hÆ¡i lâu).\n" #~ msgid "# max bytes allowed in dstore" #~ msgstr "# các byte được phép trong kho dữ liệu dstore" #~ msgid "" #~ "Converting peer address to string failed, transport type %d not " #~ "supported\n" #~ msgstr "" #~ "Lá»—i chuyển đổi địa chỉ đồng đẳng sang chuá»—i, kiểu truyá»n tải %d không " #~ "được há»— trợ\n" #~ msgid "" #~ "Transport connection attempt failed, transport type %d not supported\n" #~ msgstr "" #~ "Lá»—i thá»­ kết nối truyá»n tải, kiểu cÆ¡ chế truyá»n %d không được há»— trợ\n" #~ msgid "" #~ "Transport failed to connect to peer `%s' (%u HELLOs known, none worked)\n" #~ msgstr "" #~ "Truyá»n tải không kết nối được tá»›i đồng đẳng « %s » (đã biết %u tín hiệu " #~ "HELLO, mà không có tín hiệu nào hoạt động được)\n" #~ msgid "No transport succeeded in creating a hello!\n" #~ msgstr "Không có truyá»n tải nào đã tạo được má»™t tín hiệu HELLO.\n" #~ msgid "Transport library `%s' did not provide required function '%s%s'.\n" #~ msgstr "" #~ "Thư viện truyá»n tải « %s » không cung cấp chức năng yêu cầu « %s%s ».\n" #~ msgid "Query (get KEY, put KEY VALUE) DHT table." #~ msgstr "Há»i (nhận KHOÃ, gá»­i GIÃ_TRỊ_KHOÃ) bảng DHT." #~ msgid "allow TIME ms to process a GET command" #~ msgstr "cho phép THỜI_GIAN mili giây để xá»­ lý má»—i câu lệnh GET (lấy)" #~ msgid "Issuing `%s(%s,%s)' command.\n" #~ msgstr "Äang cấp câu lệnh « %s(%s,%s) ».\n" #~ msgid "Command `%s' requires an argument (`%s').\n" #~ msgstr "Câu lệnh « %s » cần đến má»™t đối số (« %s »).\n" #~ msgid "Command `%s' requires two arguments (`%s' and `%s').\n" #~ msgstr "Câu lệnh « %s » cần đến hai đối số (« %s » và « %s »).\n" #~ msgid "# dht route host lookups performed" #~ msgstr "# các việc tra tìm đưá»ng tá»›i máy dht được làm" #~ msgid "# dht discovery messages sent" #~ msgstr "# các thông báo phát hiện dht được gá»­i" #~ msgid "# dht put requests received" #~ msgstr "# các yêu cầu put (gá»­i) dht được nhận" #~ msgid "`%s' registering p2p handlers: %d %d %d\n" #~ msgstr "« %s » Ä‘ang đăng ký các trình Ä‘iá»u khiển p2p: %d %d %d\n" #~ msgid "`%s' failed. Terminating connection to client.\n" #~ msgstr "« %s » bị lá»—i. Äang chấm dứt kết nối tá»›i máy khách.\n" #~ msgid "`%s' registering client handlers: %d %d\n" #~ msgstr "« %s » Ä‘ang đăng ký các trình Ä‘iá»u khiển máy khách: %d %d\n" #~ msgid "Enables efficient non-anonymous routing" #~ msgstr "Hiệu lá»±c định tuyến khác nặc danh hiệu dụng" #~ msgid "" #~ "Existing hostkey in file `%s' failed format check, creating new hostkey.\n" #~ msgstr "" #~ "Kiểm tra định dạng cá»§a chìa khóa máy trong tập tin « %s » không thành " #~ "công, Ä‘ang tạo chìa khóa máy má»›i.\n" #~ msgid "Done creating hostkey.\n" #~ msgstr "Hoàn thành tạo khoá máy.\n" #~ msgid "Removed file `%s' containing invalid HELLO data.\n" #~ msgstr "Äã gỡ bá» tập tin « %s » chứa dữ liệu HELLO sai.\n" #~ msgid "Signature failed verification: signature invalid.\n" #~ msgstr "Không thẩm tra được chữ ký: chữ ký sai.\n" #~ msgid "Peer `%s' is currently strictly blacklisted (for another %llums).\n" #~ msgstr "" #~ "Äồng đẳng « %s » hiện thá»i bị cấm hoàn toàn (trong %llu miligiây sau).\n" #~ msgid "Peer `%s' is currently blacklisted (for another %llums).\n" #~ msgstr "Äồng đẳng « %s » hiện thá»i bị cấm (trong %llu miligiây sau).\n" #~ msgid "Received malformed `%s' message. Dropping.\n" #~ msgstr "Nhận được thông báo « %s » bị há»ng. Äang bá» Ä‘i.\n" #~ msgid "Received ping for another peer. Dropping.\n" #~ msgstr "Nhận được tin hiệu ping cho đồng đẳng khác. Äang bá» Ä‘i.\n" #~ msgid "" #~ "Could not match PONG against any PING. Try increasing MAX_PING_PONG " #~ "constant.\n" #~ msgstr "" #~ "Không tương ứng được PONG đối vá»›i bất kỳ PING. Hãy thá»­ tăng hằng số " #~ "MAX_PING_PONG.\n" #~ msgid "Cannot create PING, table full. Try increasing MAX_PING_PONG.\n" #~ msgstr "Không tạo được PING, bảng đầy. Hãy thá»­ tăng MAX_PING_PONG.\n" #~ msgid "# plaintext PONG messages received" #~ msgstr "# các thông báo PONG nhập thô được nhận" #~ msgid "# encrypted PING messages received" #~ msgstr "# các thông báo PING đã mật mã được nhận" #~ msgid "# encrypted PING messages sent" #~ msgstr "# các thông báo PING đã mật mã được gá»­i" #~ msgid "`%s' registering handlers %d %d (plaintext and ciphertext)\n" #~ msgstr "" #~ "« %s » Ä‘ang đăng ký các trình Ä‘iá»u khiển %d %d (nhập thô và văn bản mã " #~ "hóa)\n" #~ msgid "# hostlist HELLOs returned" #~ msgstr "# các lá»i chào mừng HELLO danh sách máy được trả vá»" #~ msgid "Cannot encrypt sessionkey, peer `%s' not known!\n" #~ msgstr "Không thể mã hoá khoá phiên chạy, không rõ đồng đẳng « %s ».\n" #~ msgid "Could not create any HELLO for myself (have transports `%s')!\n" #~ msgstr "Không thể tạo tín hiệu HELLO nào cho mình (có truyá»n tải « %s »).\n" #~ msgid "" #~ "Session key received from peer `%s' has invalid format (discarded).\n" #~ msgstr "" #~ "Khoá phiên chạy được nhận từ đồng đẳng « %s » có định dạng sai (bị há»§y).\n" #~ msgid "Session key received from peer `%s' is for `%s' and not for me!\n" #~ msgstr "" #~ "Khoá phiên chạy được nhận từ đồng đẳng « %s » dành cho « %s », không phải " #~ "cho tôi.\n" #~ msgid "setkey `%s' from `%s' fails CRC check (have: %u, want %u).\n" #~ msgstr "" #~ "Kiểm tra CRC setkey « %s » từ « %s » không thành công (có %u, còn muốn " #~ "%u).\n" #~ msgid "" #~ "Error parsing encrypted session key from `%s', given message part size is " #~ "invalid.\n" #~ msgstr "" #~ "Lá»—i phân tích chìa khóa phiên chạy đã mã hóa từ « %s », kích cỡ cá»§a phần " #~ "thông báo đưa ra là sai.\n" #~ msgid "Unknown type in embedded message from `%s': %u (size: %u)\n" #~ msgstr "" #~ "Gặp kiểu không rõ trong thông báo nhúng từ « %s »: %u (kích cỡ : %u)\n" #~ msgid "automate creation of a namespace by starting a collection" #~ msgstr "tá»± động tạo má»™t không gian tên bằng cách bắt đầu má»™t thu thập" #~ msgid "create a new pseudonym under the given NICKNAME" #~ msgstr "tạo má»™t biệt hiệu má»›i dưới TÊN_HIỆU đưa ra" #~ msgid "delete the pseudonym with the given NICKNAME" #~ msgstr "xoá biệt hiệu có TÊN_HIỆU đã cho" #~ msgid "end automated building of a namespace (ends collection)" #~ msgstr "" #~ "kết thúc việc tá»± động xây dá»±ng má»™t không gian tên (kết thúc thu thập)" #~ msgid "" #~ "Create new pseudonyms, delete pseudonyms or list existing pseudonyms." #~ msgstr "Tạo biệt hiệu má»›i, xóa biệt hiệu hoặc liệt kê các biệt hiệu có." #~ msgid "" #~ "use the given keyword to advertise the namespace (use when creating a new " #~ "pseudonym)" #~ msgstr "" #~ "sá»­ dụng từ khóa đưa ra để quảng cáo không gian tên (dùng khi tạo má»™t biệt " #~ "hiệu má»›i)" #~ msgid "specify metadata describing the namespace or collection" #~ msgstr "ghi rõ siêu dữ liệu mô tả không gian tên (hoặc thu thập)" #~ msgid "" #~ "do not generate an advertisement for this namespace (use when creating a " #~ "new pseudonym)" #~ msgstr "" #~ "đừng tạo ra má»™t quảng cáo cho không gian tên này (dùng khi tạo má»™t biệt " #~ "hiệu má»›i)" #~ msgid "do not list the pseudonyms from the pseudonym database" #~ msgstr "không liệt kê các biệt hiệu từ cÆ¡ sở dữ liệu biệt hiệu" #~ msgid "" #~ "specify IDENTIFIER to be the address of the entrypoint to content in the " #~ "namespace (use when creating a new pseudonym)" #~ msgstr "" #~ "ghi rõ BỘ_NHẬN_DIỆN là địa chỉ cá»§a Ä‘iểm vào ná»™i dung trong không gian tên " #~ "(dùng khi tạo má»™t biệt hiệu má»›i)" #~ msgid "Namespace `%s' (%s) has rating %d.\n" #~ msgstr "Không gian tên « %s » (%s) có đánh giá %d.\n" #~ msgid "\tRating (after update): %d\n" #~ msgstr "\tÄánh giá (sau khi cập nhật): %d\n" #~ msgid "Failed to stop collection (not active?).\n" #~ msgstr "Lá»—i dừng thu thập (không hoạt động ?).\n" #~ msgid "Error deleting pseudonym `%s' (does not exist?).\n" #~ msgstr "Lá»— xoá biệt hiệu « %s » (không tồn tại ?).\n" #~ msgid "Started collection.\n" #~ msgstr "Äã bắt đầu thu thập.\n" #~ msgid "Namespace `%s' created (root: %s).\n" #~ msgstr "Äã tạo không gian tên « %s » (gốc: %s).\n" #~ msgid "You must specify a name for the collection (`%s' option).\n" #~ msgstr "Bạn phải ghi rõ má»™t tên cho thu thập (tùy chá»n « %s »).\n" #~ msgid "%d files found in directory.\n" #~ msgstr "Tìm thấy %d tập tin trong thư mục.\n" #~ msgid "Perform directory related operations." #~ msgstr "Thá»±c hiện các thao tác liên quan đến thư mục." #~ msgid "" #~ "remove all entries from the directory database and stop tracking URIs" #~ msgstr "" #~ "gỡ bá» má»i mục nhập khá»i cÆ¡ sở dữ liệu thư mục, và dừng theo dõi các địa " #~ "chỉ URI" #~ msgid "list entries from the directory database" #~ msgstr "liệt kê các mục nhập từ cÆ¡ sở dữ liệu thư mục" #~ msgid "start tracking entries for the directory database" #~ msgstr "bắt đầu theo dõi các mục nhập cho cÆ¡ sở dữ liệu thư mục" #~ msgid "Listed %d matching entries.\n" #~ msgstr "Äã liệt kê %d mục nhập tương ứng.\n" #~ msgid "Upload of `%s' at %llu out of %llu bytes.\n" #~ msgstr "Tải lên tập tin « %s » tại %llu trên %llu byte.\n" #~ msgid "Upload aborted.\n" #~ msgstr "Tải lên bị há»§y bá».\n" #~ msgid "Uploading suspended.\n" #~ msgstr "Tiến trình tải lên bị ngưng.\n" #~ msgid "" #~ "run in debug mode; gnunet-auto-share will not daemonize and error " #~ "messages will be written to stderr instead of a logfile" #~ msgstr "" #~ "chạy trong chế độ tìm sá»­a lá»—i; gnunet-auto-share sẽ không trở thành trình " #~ "ná»n và sẽ ghi thông báo lá»—i ra đầu lá»—i tiêu chuẩn thay vì vào má»™t tập tin " #~ "ghi sá»± kiện." #~ msgid "" #~ "do not use libextractor to add additional references to directory entries " #~ "and/or the published file" #~ msgstr "" #~ "đừng dùng libextractor để thêm các tham chiếu bổ sung vào mục nhập thư " #~ "mục và/hay tập tin công bố" #~ msgid "Unknown keyword type `%s' in metadata configuration\n" #~ msgstr "Không rõ kiểu từ khoá « %s » trong cấu hình siêu dữ liệu\n" #~ msgid "Directory `%s' is already on the list of shared directories.\n" #~ msgstr "Thư mục « %s » đã có trong danh sách các thư mục dùng chung.\n" #~ msgid "" #~ "The specified directories were added to the list of shared directories.\n" #~ msgstr "" #~ "Những thư mục đưa ra đã được thêm vào danh sách các thư mục dùng chung.\n" #~ msgid "Created entry `%s' in namespace `%s'\n" #~ msgstr "Äã tạo mục nhập « %s » trong không gian tên « %s »\n" #~ msgid "mimetype" #~ msgstr "kiểu MIME" #~ msgid "" #~ "%16llu of %16llu bytes inserted (estimating %6s to completion) - %s\n" #~ msgstr "" #~ "đã chèn %16llu trên %16llu byte (sẽ hoàn thành trong khoảng %6s giây) - " #~ "%s\n" #~ msgid "" #~ "Upload of `%s' complete, %llu bytes took %llu seconds (%8.3f KiB/s).\n" #~ msgstr "" #~ "Hoàn thành tải lên « %s », %llu byte trong %llu giây (%8.3f KiB/giây).\n" #~ msgid "" #~ "\n" #~ "Upload aborted.\n" #~ msgstr "" #~ "\n" #~ "Tải lên bị há»§y bá».\n" #~ msgid "" #~ "\n" #~ "Error uploading file: %s" #~ msgstr "" #~ "\n" #~ "Gặp lá»—i khi tải lên tập tin: %s" #~ msgid "" #~ "\n" #~ "Unexpected event: %d\n" #~ msgstr "" #~ "\n" #~ "Gặp sá»± kiện bất thưá»ng: %d\n" #~ msgid "" #~ "even if gnunetd is running on the local machine, force the creation of a " #~ "copy instead of making a link to the GNUnet share directory" #~ msgstr "" #~ "thậm chí nếu gnunetd Ä‘ang chạy trên máy cục bá»™, bắt buá»™c tạo má»™t bản sao " #~ "thay vì tạo má»™t liên kết đến thư mục chia sẻ cá»§a GNUnet" #~ msgid "Make files available to GNUnet for sharing." #~ msgstr "Làm cho các tập tin sẵn sàng qua GNUnet để chia sẻ." #~ msgid "Could not access namespace `%s' (does not exist?).\n" #~ msgstr "Không thể truy cập đến không gian tên « %s » (không tồn tại ?).\n" #~ msgid "Search GNUnet for files." #~ msgstr "Tìm tập tin trong GNUnet." #~ msgid "write encountered (decrypted) search results to FILENAME" #~ msgstr "ghi kết quả tìm kiếm tìm thấy (đã giải mã) vào tập tin TÊN_TẬP_TIN" #~ msgid "" #~ "%16llu of %16llu bytes unindexed (estimating %llu seconds to " #~ "completion) " #~ msgstr "" #~ "Äã bá» chỉ mục %16llu trên %16llu byte (sẽ hoàn thành sau khoảng %llu " #~ "giây) " #~ msgid "" #~ "\n" #~ "Unindexing of `%s' complete, %llu bytes took %llu seconds (%8.3f KiB/s).\n" #~ msgstr "" #~ "\n" #~ "Hoàn thành bá» chỉ mục cá»§a « %s », %llu byte sau %llu giây (%8.3f KiB/" #~ "giây).\n" #~ msgid "Not enough arguments. You must specify a filename.\n" #~ msgstr "Không đủ đối số. Phải xác định má»™t tên tập tin.\n" #~ msgid "`%s' failed. Is `%s' a file?\n" #~ msgstr "« %s » bị lá»—i. « %s » là má»™t tập tin phải không?\n" #~ msgid "" #~ "download a GNUnet directory that has already been downloaded. Requires " #~ "that a filename of an existing file is specified instead of the URI. The " #~ "download will only download the top-level files in the directory unless " #~ "the `-R' option is also specified." #~ msgstr "" #~ "tải xuống má»™t thư mục GNUnet đã được tải vá» trước. Cần thiết ghi rõ tên " #~ "tập tin cá»§a má»™t tập tin đã có, thay cho địa chỉ URI. Việc tải vá» sẽ chỉ " #~ "tải vá» các tập tin cấp đầu cá»§a thư mục, nếu không cÅ©ng đưa ra tùy chá»n « -" #~ "R »." #~ msgid "Download files from GNUnet." #~ msgstr "Tải tập tin xuống GNUnet." #~ msgid "Download of file `%s' at %16llu out of %16llu bytes (%8.3f KiB/s)\n" #~ msgstr "" #~ "Tải xuống tập tin « %s » tại %16llu trên %16llu byte (%8.3f KiB/giây)\n" #~ msgid "Download aborted.\n" #~ msgstr "Tiến trình tải xuống bị há»§y bá».\n" #~ msgid "Download of file `%s' complete. Speed was %8.3f KiB per second.\n" #~ msgstr "" #~ "Hoàn thành tải xuống tập tin « %s ». Tốc độ là %8.3f KiB má»™t giây.\n" #~ msgid "Not enough arguments. You must specify a GNUnet file URI\n" #~ msgstr "Không đủ đối số. Phải ghi rõ má»™t địa chỉ URI tập tin GNUnet\n" #~ msgid "URI `%s' invalid for gnunet-download.\n" #~ msgstr "Sai URI « %s » cho gnunet-download.\n" #~ msgid "No filename specified, using `%s' instead (for now).\n" #~ msgstr "Chưa ghi rõ tên tập tin, Ä‘ang dùng « %s » để thay thế (lúc này).\n" #~ msgid "Downloading %d files from directory `%s'.\n" #~ msgstr "Äang tải %d tập tin xuống thư mục « %s ».\n" #~ msgid "File stored as `%s'.\n" #~ msgstr "Tập tin được lưu dạng « %s ».\n" #~ msgid "Collecting file identifiers disabled.\n" #~ msgstr "Chức năng thu thập các đồ nhận diện tập tin đã bị tắt.\n" #~ msgid "Deleted corrupt URI database in `%s'." #~ msgstr "Äã xoá cÆ¡ sở dữ liệu địa chỉ URI bị há»ng trong « %s »." #~ msgid "Cannot get size of file `%s'" #~ msgstr "Không thể lấy kích cỡ cá»§a tập tin « %s »" #~ msgid "Cannot hash `%s'.\n" #~ msgstr "Không thể tạo mẫu duy nhất đại diện cho « %s ».\n" #~ msgid "Initialization for indexing file `%s' failed.\n" #~ msgstr "Lá»—i sÆ¡ khởi tập tin đánh chỉ mục « %s ».\n" #~ msgid "Cannot open file `%s': `%s'" #~ msgstr "Không thể mở tập tin « %s »: « %s »" #~ msgid "Renaming of file `%s' to `%s' failed: %s\n" #~ msgstr "Lá»—i thay đổi tên cá»§a tập tin « %s » thành « %s »: %s\n" #~ msgid "Could not rename file `%s' to `%s': file exists\n" #~ msgstr "Không thể thay đổi tên tập tin « %s » thành « %s »: tập tin đã có\n" #~ msgid "CHK URI not allowed for search.\n" #~ msgstr "Không cho phép địa chỉ URI CHK khi tìm kiếm.\n" #~ msgid "LOC URI not allowed for search.\n" #~ msgstr "Không cho phép địa chỉ URI LOC khi tìm kiếm.\n" #~ msgid "File `%s' does not contain a pseudonym.\n" #~ msgstr "Tập tin « %s » không chứa biệt hiệu.\n" #~ msgid "Format of file `%s' is invalid, trying to remove.\n" #~ msgstr "Äịnh dạng cá»§a tập tin « %s » là không hợp lệ nên thá»­ gỡ bá».\n" #~ msgid "" #~ "Decrypted content does not match key. This is either a bug or a " #~ "maliciously inserted file. Download aborted.\n" #~ msgstr "" #~ "Ná»™i dung đã giải mã không tương ứng chìa khóa. Äây là má»™t lá»—i hoặc má»™t " #~ "tập tin chèn vào vá»›i ý xấu. Tiến trình tải xuống bị há»§y bá».\n" #~ msgid "Revision %u" #~ msgstr "Bản sá»­a đổi %u" #~ msgid "Application aborted." #~ msgstr "Ứng dụng bị há»§y bá»." #~ msgid "FSUI state file `%s' had syntax error at offset %u.\n" #~ msgstr "Tập tin tình trạng FSUI « %s » có lá»—i cú pháp tại khoảng bù %u.\n" #~ msgid "# gap content total planned" #~ msgstr "# tổng số ná»™i dung lá»— hổng dá»± định" #~ msgid "Datastore full.\n" #~ msgstr "Kho dữ liệu đầy.\n" #~ msgid "# gap requests total received" #~ msgstr "# tổng số yêu cầu lá»— hổng được nhận" #~ msgid "# gap total trust awarded" #~ msgstr "# tổng số tin cậy lá»— hổng được cấp" #~ msgid "" #~ "`%s' registering client handlers %d %d %d %d %d %d %d %d and P2P handlers " #~ "%d %d\n" #~ msgstr "" #~ "« %s » Ä‘ang đăng ký các trình Ä‘iá»u khiển kiểu ứng dụng khách %d %d %d %d " #~ "%d %d %d %d và kiểu P2P %d %d\n" #~ msgid "enables (anonymous) file-sharing" #~ msgstr "hiệu lá»±c chia sẻ tập tin (nặc danh)" #~ msgid "" #~ "Because the file `%s' has been unavailable for 3 days it got removed from " #~ "your share. Please unindex files before deleting them as the index now " #~ "contains invalid references!\n" #~ msgstr "" #~ "Vì không có tập tin « %s » trong 3 ngày nên đã xóa nó khá»i chia sẻ cá»§a " #~ "bạn. Xin hãy bá» chỉ mục các tập tin trước khi xoá chúng vì chỉ mục hiện " #~ "thá»i chứa các tham chiếu sai.\n" #~ msgid "Indexed content changed (does not match its hash).\n" #~ msgstr "" #~ "Ná»™i dung đánh chỉ mục bị thay đổi (không tương ứng vá»›i tổng kiểm).\n" #~ msgid "" #~ "Unindexed ODB block `%s' from offset %llu already missing from " #~ "datastore.\n" #~ msgstr "" #~ "Khối ODB đã bá» chỉ mục « %s » từ khoảng bù %llu đã không có trong kho dữ " #~ "liệu.\n" #~ msgid "# distinct interned peer IDs in pid table" #~ msgstr "# các mã số đồng đẳng bị giam giữ riêng biệt trong bảng PID" #~ msgid "# total RC of interned peer IDs in pid table" #~ msgstr "# tổng số RC cá»§a mã số đồng đẳng bị giam giữ trong bảng PID" #~ msgid "# gap client requests tracked" #~ msgstr "# các yêu cầu máy/trình khách lá»— hổng được theo dõi" #~ msgid "# gap query bloomfilter resizing updates" #~ msgstr "" #~ "# các bản cập nhật thay đổi kích cỡ bá»™ lá»c bloomfilter truy vấn lá»— hổng" #~ msgid "# blocks migrated" #~ msgstr "# các khối được nâng cấp" #~ msgid "# blocks injected for migration" #~ msgstr "# các khối được phun vào để nâng cấp" #~ msgid "# on-demand fetches for migration" #~ msgstr "# các lần lấy theo yêu cầu để nâng cấp" #~ msgid "# gap queries dropped (table full)" #~ msgstr "# các truy vấn lá»— hổng bị bá» (bảng đầy)" #~ msgid "# gap queries dropped (redundant)" #~ msgstr "# các truy vấn lá»— hổng bị bá» (thừa)" #~ msgid "# gap queries refreshed existing record" #~ msgstr "# các truy vấn lá»— hổng đã cập nhật mục ghi đã có" #~ msgid "# trust earned" #~ msgstr "# độ tin cậy giành được" #~ msgid "# blocks pushed into DHT" #~ msgstr "# các khối được đẩy vào DHT" #~ msgid "scp command is : %s \n" #~ msgstr "Câu lệnh scp là: %s\n" #~ msgid "Friend list of %s:%d\n" #~ msgstr "Danh sách bạn bè cá»§a %s:%d\n" #~ msgid "scp command for friend file copy is : %s \n" #~ msgstr "Câu lệnh scp cho bản sao tập tin bạn bè là: %s\n" #~ msgid "Set up multiple gnunetd daemons across multiple hosts." #~ msgstr "Thiết lập nhiá»u trình ná»n gnunetd qua nhiá»u máy khác nhau." #~ msgid "Bootstrap data obtained from `%s' is invalid.\n" #~ msgstr "Sai dữ liệu nạp và khởi động được lấy từ « %s ».\n" #~ msgid "`%s' registering client handler %d\n" #~ msgstr "« %s » Ä‘ang đăng ký trình Ä‘iá»u khiển máy khách %d\n" #~ msgid "allows clients to determine gnunetd's configuration" #~ msgstr "cho phép máy khách quyết định cấu hình cá»§a trình ná»n gnunetd." #~ msgid "`%s' registering client handler %d and %d\n" #~ msgstr "« %s » Ä‘ang đăng ký trình Ä‘iá»u khiển máy khách %d và %d\n" #~ msgid "Template description." #~ msgstr "Mô tả mẫu." #~ msgid "Uptime (seconds)" #~ msgstr "Thá»i gian chạy (giây)" #~ msgid "# Any-Blocks" #~ msgstr "# Khối bất kỳ" #~ msgid "# DBlocks" #~ msgstr "# Khối D" #~ msgid "# SBlocks" #~ msgstr "# Khối S" #~ msgid "# KBlocks" #~ msgstr "# Khối K" #~ msgid "# NBlocks" #~ msgstr "# Khối N" #~ msgid "# KNBlocks" #~ msgstr "# Khối KN" #~ msgid "# OnDemand-Blocks" #~ msgstr "# Khối theo yêu cầu" #~ msgid "# Unknown-Blocks" #~ msgstr "# Khối không rõ" #~ msgid "# expired" #~ msgstr "# đã hết hạn" #~ msgid "# expire in 1h" #~ msgstr "# hết hạn trong 1 giá»" #~ msgid "# expire in 24h" #~ msgstr "# hết hạn trong 24 giá»" #~ msgid "# expire in 1 week" #~ msgstr "# hết hạn trong 1 tuần" #~ msgid "# expire in 1 month" #~ msgstr "# hết hạn trong 1 tháng" #~ msgid "# zero priority" #~ msgstr "# ưu tiên 0" #~ msgid "# priority one" #~ msgstr "# ưu tiên 1" #~ msgid "# priority larger than one" #~ msgstr "# ưu tiên >1" #~ msgid "# no anonymity" #~ msgstr "# nặc danh 0" #~ msgid "# anonymity one" #~ msgstr "# nặc danh 1" #~ msgid "# anonymity larger than one" #~ msgstr "# nặc danh >1" #~ msgid "% of allowed network load (up)" #~ msgstr "% trá»ng tải mạng được phép (chạy)" #~ msgid "% of allowed network load (down)" #~ msgstr "% trá»ng tải mạng được phép (không chạy)" #~ msgid "% of allowed cpu load" #~ msgstr "% trá»ng tải CPU được phép" #~ msgid "% of allowed io load" #~ msgstr "% trá»ng tải V/R được phép" #~ msgid "# plibc handles" #~ msgstr "# các bá»™ xá»­ lý plibc" #~ msgid "`%s' registering client handlers %d %d %d and p2p handler %d\n" #~ msgstr "" #~ "« %s » Ä‘ang đăng ký các trình Ä‘iá»u khiển máy khách %d %d %d và trình Ä‘iá»u " #~ "khiển đồng đẳng %d\n" #~ msgid "keeps statistics about gnunetd's operation" #~ msgstr "tính thống kê vá» thao tác gnunetd" #~ msgid "Supported peer-to-peer messages:\n" #~ msgstr "Thông báo đồng đẳng được há»— trợ :\n" #~ msgid "Supported client-server messages:\n" #~ msgstr "Thông báo máy khách-chá»§ được há»— trợ :\n" #~ msgid "prints supported protocol messages" #~ msgstr "in ra các thông báo giao thức được há»— trợ" #~ msgid "Suppress display of asynchronous log messages" #~ msgstr "Thu hồi hiển thị các thông Ä‘iệp ghi sá»± kiện không đồng bá»™" #~ msgid "VPN IP src not anonymous. drop..\n" #~ msgstr "VPN Nguồn địa chỉ IP không phải nặc danh, bá» Ä‘i.\n" #~ msgid "VPN IP not anonymous, drop.\n" #~ msgstr "VPN Äịa chỉ IP không phải nặc danh, bá» Ä‘i.\n" #~ msgid "VPN Received, not anonymous, drop.\n" #~ msgstr "VPN Nhận được, không phải nặc danh, bá» Ä‘i.\n" #~ msgid "VPN Received unknown IP version %d...\n" #~ msgstr "VPN Nhận được phiên bản IP không rõ %d...\n" #~ msgid "<- GNUnet(%d) : %s\n" #~ msgstr "<- GNUnet(%d) : %s\n" #~ msgid "" #~ "Could not write the tunnelled IP to the OS... Did to setup a tunnel?\n" #~ msgstr "" #~ "Không thể ghi vào HÄH địa chỉ IP theo đưá»ng hầm... Äã làm để thiết lập " #~ "má»™t đưá»ng hầm ?\n" #~ msgid "Prepare route announcement level %d\n" #~ msgstr "Chuẩn bị thông cáo định tuyến cấp %d\n" #~ msgid "Send route announcement %d with route announce\n" #~ msgstr "Gá»­i thông cáo định tuyến %d vá»›i đưá»ng đã báo\n" #~ msgid "Send outside table info %d\n" #~ msgstr "Gá»­i thông tin bảng bên ngoài %d\n" #~ msgid "Receive route announce.\n" #~ msgstr "Nhận thông cáo định tuyến.\n" #~ msgid "Going to try insert route into local table.\n" #~ msgstr "Sẽ thá»­ chèn đưá»ng vào bảng cục bá»™.\n" #~ msgid "Inserting with hops %d\n" #~ msgstr "Äang chèn vá»›i số bước nhảy %d\n" #~ msgid "Request level %d from peer %d\n" #~ msgstr "Yêu cầu cấp %d từ đồng đẳng %d\n" #~ msgid "Receive table limit on peer reached %d\n" #~ msgstr "Giá»›i hạn bảng nhận trên đồng đẳng đã tá»›i %d\n" #~ msgid "Not storing route to myself from peer %d\n" #~ msgstr "Không phải lưu lại đưá»ng đến máy này từ đồng đẳng %d\n" #~ msgid "Duplicate route to node from peer %d, choosing minimum hops" #~ msgstr "" #~ "ÄÆ°á»ng trùng đến nút từ đồng đẳng %d, Ä‘ang chá»n đưá»ng có ít bước nhảy hÆ¡n" #~ msgid "Inserting route from peer %d in route table at location %d\n" #~ msgstr "Äang chèn đưá»ng từ đồng đẳng %d vào bảng định tuyến tại vị trí %d\n" #~ msgid "RFC4193 Frame length %d is too big for GNUnet!\n" #~ msgstr "RFC4193 Chiá»u dài khung %d quá lá»›n cho GNUnet!\n" #~ msgid "RFC4193 Frame length %d too small\n" #~ msgstr "RFC4193 Chiá»u dài khung %d quá nhá»\n" #~ msgid "RFC4193 Ethertype %x and IP version %x do not match!\n" #~ msgstr "RFC4193 Ethertype %x và phiên bản IP %x không tương ứng.\n" #~ msgid "RFC4193 Going to try and make a tunnel in slot %d\n" #~ msgstr "RFC4193 Sẽ thá»­ tạo má»™t đưá»ng hầm trong khoảng %d\n" #, fuzzy #~ msgid "Cannot open tunnel device: %s" #~ msgstr "Không thể mở thiết bị đưá»ng hầm do %s" #~ msgid "RFC4193 Create skips gnu%d as we are already using it\n" #~ msgstr "RFC4193 Chức năng tạo sẽ ná» qua gnu%d vì chúng ta Ä‘ang dùng nó\n" #~ msgid "Cannot set tunnel name to %s because of %s\n" #~ msgstr "không thể đặt tên đưá»ng hầm thành %s do %s\n" #~ msgid "Configured tunnel name to %s\n" #~ msgstr "Tên đưá»ng hầm đã được cấu hình thành %s\n" #~ msgid "Cannot get socket flags for gnu%d because %s\n" #~ msgstr "Không thể lấy các cỠổ cắm cho gnu%d do %s\n" #~ msgid "Cannot set socket flags for gnu%d because %s\n" #~ msgstr "Không thể đặt các cỠổ cắm cho gnu%d do %s\n" #~ msgid "Cannot set MTU for gnu%d because %s\n" #~ msgstr "Không thể đặt MTU cho gnu%d do %s\n" #~ msgid "Cannot get interface index for gnu%d because %s\n" #~ msgstr "Không thể lấy chá»§ mục giao diện cho gnu%d do %s\n" #~ msgid "IPv6 ifaddr gnu%d - %x:%x:%x:%x:%x:%x:%x:%x/%d\n" #~ msgstr "IPv6 ifaddr gnu%d - %x:%x:%x:%x:%x:%x:%x:%x/%d\n" #~ msgid "Cannot set interface IPv6 address for gnu%d because %s\n" #~ msgstr "Không thể đặt địa chỉ IPv6 cá»§a giao diện cho gnu%d do %s\n" #~ msgid "IPv6 route gnu%d - destination %x:%x:%x:%x:%x:%x:%x:%x/%d\n" #~ msgstr "ÄÆ°á»ng IPv6 gnu%d - đích đến %x:%x:%x:%x:%x:%x:%x:%x/%d\n" #~ msgid "Cannot add route IPv6 address for gnu%s because %s\n" #~ msgstr "Không thể thêm địa chỉ IPv6 cá»§a đưá»ng cho gnu%s do %s\n" #~ msgid "" #~ "RFC4193 We have run out of memory and so I can't store a tunnel for this " #~ "peer.\n" #~ msgstr "" #~ "RFC4193 Tràn bá»™ nhá»› thì không thể cất giữ má»™t đưá»ng hầm cho đồng đẳng " #~ "này.\n" #~ msgid "RFC4193 Thread running (frame %d tunnel %d f2f %d) ...\n" #~ msgstr "RFC4193 Mạch Ä‘ang chạy (khung %d đưá»ng hầm %d f2f %d) ...\n" #~ msgid "VPN dropping connection %x\n" #~ msgstr "VPN Ä‘ang bá» Ä‘i kết nối %x\n" #~ msgid "VPN cannot drop connection %x\n" #~ msgstr "VPN không thể bá» Ä‘i kết nối %x\n" #~ msgid "RFC4193 Thread exiting\n" #~ msgstr "RFC4193 Mạch Ä‘ang thoát\n" #~ msgid "realise alloc ram\n" #~ msgstr "realise cấp phát bá»™ nhá»› RAM\n" #~ msgid "realise add routes\n" #~ msgstr "realise thêm đưá»ng\n" #~ msgid "realise copy table\n" #~ msgstr "realise chép bảng\n" #~ msgid "`%s' initialising RFC4913 module %d and %d\n" #~ msgstr "« %s » Ä‘ang sÆ¡ khởi mô-Ä‘un RFC4913 %d và %d\n" #~ msgid "RFC4193 my First 4 hex digits of host id are %x\n" #~ msgstr "RFC4193 my 4 chữ số thập lúc đầu tiên cá»§a mã số máy là %x\n" #~ msgid "enables IPv6 over GNUnet (incomplete)" #~ msgstr "hiệu lá»±c IPv6 qua GNUnet (chưa hoàn tất)" #~ msgid "RFC4193 Waiting for tun thread to end\n" #~ msgstr "RFC4193 Äang đợi kết thúc mạch tun\n" #~ msgid "RFC4193 The tun thread has ended\n" #~ msgstr "RFC4193 Mạch tun đã kết thúc\n" #~ msgid "RFC4193 Closing tunnel %d fd %d\n" #~ msgstr "RFC4193 Äang đóng đưá»ng hầm %d fd %d\n" #~ msgid "Configuration value `%s' under [MODULES] for `%s' is invalid!\n" #~ msgstr "Sai giá trị cấu hình « %s » dưới [MÔ-ÄUN] cho « %s ».\n" #~ msgid "Application module `%s' already initialized!\n" #~ msgstr "Mô-Ä‘un ứng dụng « %s » đã được sở khởi.\n" #~ msgid "Could not shutdown `%s': application not loaded\n" #~ msgstr "Không thể tắt « %s »: chưa nạp ứng dụng\n" #~ msgid "Could not shutdown application `%s': not initialized\n" #~ msgstr "Không thể tắt ứng dụng « %s »: chưa được sÆ¡ khởi\n" #~ msgid "Could not release %p: service not loaded\n" #~ msgstr "Không thể giải phóng %p: chưa nạp dịch vụ\n" #~ msgid "Could not properly shutdown application `%s'.\n" #~ msgstr "Không thể tắt đúng ứng dụng « %s ».\n" #~ msgid "Could not properly unload service `%s'!\n" #~ msgstr "Không thể há»§y nạp đúng dịch vụ « %s ».\n" #~ msgid "Updates GNUnet datastructures after version change." #~ msgstr "Cập nhật cấu trúc dữ liệu GNUnet sau khi thay đổi phiên bản." #~ msgid "run as user LOGIN" #~ msgstr "chạy dưới ngưá»i dùng ÄÄ‚NG_NHẬP" #~ msgid "run in client mode (for getting client configuration values)" #~ msgstr "chạy trong chế độ khách (để lấy các giá trị cấu hình cá»§a máy khách)" #~ msgid "" #~ "Failed to determine filename used to store GNUnet version information!\n" #~ msgstr "" #~ "Lá»—i quyết định tên tập tin được dùng để chứa thông tin vá» phiên bản " #~ "GNUnet.\n" #~ msgid "" #~ "run in debug mode; gnunetd will not daemonize and error messages will be " #~ "written to stderr instead of a logfile" #~ msgstr "" #~ "chạy trong chế độ tìm sá»­a lá»—i; gnunetd sẽ không trở thành trình ná»n và sẽ " #~ "ghi thông báo lá»—i ra đầu lá»—i tiêu chuẩn thay vì vào má»™t tập tin ghi sá»± " #~ "kiện." #~ msgid "Starts the gnunetd daemon." #~ msgstr "Khởi chạy trình ná»n gnunetd." #~ msgid "disable padding with random data (experimental)" #~ msgstr "tắt đệm lót vá»›i dữ liệu ngẫu nhiên (vẫn thá»±c nghiệm !)" #~ msgid "print all log messages to the console (only works together with -d)" #~ msgstr "" #~ "in má»i thông Ä‘iệp ghi sá»± kiện ra bàn giao tiếp (chỉ hoạt động tổ hợp vá»›i " #~ "« -d »)" #~ msgid "specify username as which gnunetd should run" #~ msgstr "chỉ ra tên ngưá»i dùng dưới đó cần chạy gnunetd" #~ msgid "Configuration or GNUnet version changed. You need to run `%s'!\n" #~ msgstr "" #~ "Cấu hình hoặc phiên bản GNUnet bị thay đổi. Ngưá»i dùng cần chạy « %s ».\n" #~ msgid "The `%s' request received from client is malformed.\n" #~ msgstr "Nhận được yêu cầu « %s » dạng sai từ máy khách.\n" #~ msgid "Registering failed, message type %d already in use.\n" #~ msgstr "Lá»—i đăng ký, thông Ä‘iệp kiểu %d Ä‘ang được dùng.\n" #~ msgid "Unable to obtain filesystem information for `%s': %u\n" #~ msgstr "Không thể đại được thông tin vá» hệ thống tập tin cho « %s »: %u\n" #~ msgid "" #~ "Filesystem `%s' of partition `%s' is unknown. Please contact gnunet-" #~ "developers@gnu.org!" #~ msgstr "" #~ "Hệ thống tập tin « %s » cá»§a phân vùng « %s » không rõ. Hãy liên lạc vá»›i " #~ "các nhà phát triển gnunet ở địa chỉ « gnunet-developers@gnu.org »." #~ msgid "" #~ "Limiting datastore size to %llu GB, because the `%s' filesystem does not " #~ "support larger files. Please consider storing the database on a NTFS " #~ "partition!\n" #~ msgstr "" #~ "Äang hạn chế kích cỡ kho dữ liệu thành %llu GB, vì hệ thống tập tin « %s " #~ "» không há»— trợ tập tin lá»›n hÆ¡n đó. Khuyên bạn cất giữ cÆ¡ sở dữ liệu trong " #~ "má»™t phiên bản kiểu NTFS.\n" #~ msgid "`%s' message invalid (signature invalid).\n" #~ msgstr "Thông báo « %s » không hợp lệ (chữ ký sai).\n" #~ msgid "`%s' selected %d out of %d messages (MTU: %d).\n" #~ msgstr "« %s » đã chá»n %d trên %d thông báo (MTU: %d).\n" #~ msgid "Message details: %u: length %d, priority: %d\n" #~ msgstr "Chi tiết vá» thông báo: %u: dài %d, ưu tiên: %d\n" #~ msgid "Message from `%s' discarded: invalid format.\n" #~ msgstr "Thông báo từ « %s » bị há»§y: định dạng sai.\n" #~ msgid "Invalid sequence number %u <= %u, dropping message.\n" #~ msgstr "" #~ "Sai số thứ tá»± dãy trong thông báo %u ≤ %u, Ä‘ang loại bá» thông báo.\n" #~ msgid "# connections closed (HANGUP sent)" #~ msgstr "# các kết nối bị đóng (gá»­i tín hiệu ngừng nói HANGUP)" #~ msgid "# bytes noise sent" #~ msgstr "# các byte nhiá»…u được gá»­i" #~ msgid "# total bytes per second send limit" #~ msgstr "# giá»›i hạn tổng số byte má»—i giây" #~ msgid "# total bytes per second receive limit" #~ msgstr "# giá»›i hạn nhận tổng số byte má»—i giây" #~ msgid "# total number of messages in send buffers" #~ msgstr "# tổng số thông báo trong bá»™ đệm gá»­i" #~ msgid "# total number of bytes we were allowed to send but did not" #~ msgstr "# tổng số byte được phép gá»­i mà chưa" #~ msgid "# total number of bytes we were allowed to sent" #~ msgstr "# tổng số byte được phép gá»­i" #~ msgid "# total number of bytes we are currently allowed to send" #~ msgstr "# tổng số byte hiện thá»i được phép gá»­i" #~ msgid "# transports switched to stream transport" #~ msgstr "# các truyá»n tải được chuyển sang truyá»n tải luồng" #~ msgid "# conn. shutdown: other peer sent too much" #~ msgstr "# kết nối bị ngắt: đồng đẳng khác đã gá»­i quá nhiá»u" #~ msgid "# conn. shutdown: we lacked bandwidth" #~ msgstr "# kết nối bị ngắt: không đủ băng thông." #~ msgid "# conn. shutdown: other peer timed out" #~ msgstr "# kết nối bị ngắt: đồng đẳng khác quá hạn" #~ msgid "# conn. shutdown: timed out during connect" #~ msgstr "# kết nối bị ngắt: quá hạn trong khi thiết lập kết nối" #~ msgid "# conn. shutdown: other peer requested it" #~ msgstr "# kết nối bị ngắt: theo yêu cầu cá»§a đồng đẳng khác" #~ msgid "`%s': Could not create hello.\n" #~ msgstr "« %s »: Không tạo được tín hiệu xin chào (hello).\n" #~ msgid "`%s': Could not send.\n" #~ msgstr "« %s »: Không thể gá»­i.\n" #~ msgid "`%s': Could not disconnect.\n" #~ msgstr "« %s »: Không thể ngắt kết nối.\n" #~ msgid "" #~ "`%s' transport OK. It took %ums to transmit %llu messages of %llu bytes " #~ "each.\n" #~ msgstr "" #~ "« %s » truyá»n tải OK. Cần %u miligiây để truyá»n Ä‘i %llu thông báo vá»›i " #~ "%llu byte má»—i cái.\n" #~ msgid " Transport %d is not being tested\n" #~ msgstr " Truyá»n tải %d không Ä‘ang thá»­\n" #~ msgid "" #~ "\n" #~ "Contacting `%s'." #~ msgstr "" #~ "\n" #~ "Äang liên lạc vá»›i « %s »." #~ msgid "Timeout after %llums.\n" #~ msgstr "Quá hạn sau %llu miligiây.\n" #~ msgid "OK!\n" #~ msgstr "OK!\n" #~ msgid "Tool to test if GNUnet transport services are operational." #~ msgstr "" #~ "Công cụ để thá»­ nghiệm xem dịch vụ truyá»n tải GNUnet có hoạt động không." #~ msgid "ping peers from HOSTLISTURL that match transports" #~ msgstr "" #~ "gá»­i tín hiệu ping cho các đồng đẳng từ HOSTLISTURL (danh sách máy theo " #~ "URL) tương ứng vá»›i truyá»n tải" #~ msgid "send messages with SIZE bytes payload" #~ msgstr "gá»­i thông báo có KÃCH_Cá»  byte tải trá»ng" #~ msgid "specifies after how many MS to time-out" #~ msgstr "chỉ ra hết thá»i gian chá» sau bao nhiêu miligiay" #~ msgid "repeat each test X times" #~ msgstr "lặp lại má»—i hàm thá»­ X lần" #~ msgid "Available transport(s): %s\n" #~ msgstr "Các truyá»n tải sẵn sàng: %s\n" #~ msgid "" #~ "\n" #~ "%d out of %d peers contacted successfully (%d times transport " #~ "unavailable).\n" #~ msgstr "" #~ "\n" #~ "Äã liên lạc thành công vá»›i %d trên %d đồng đẳng (truyá»n tải không sẵn " #~ "sàng %d lần).\n" #~ msgid "Port is 0, will only send using %s.\n" #~ msgstr "Cổng là 0, chỉ sẽ gá»­i dùng %s.\n" #~ msgid "%s failed for url `%s' and post-data `%s' at %s:%d: `%s'\n" #~ msgstr "" #~ "%s bị lá»—i đối vá»›i địa chỉ URL « %s » và dữ liệu cuối « %s » tại %s:%d: « " #~ "%s »\n" #~ msgid "upnp: NAT Returned IP: %s\n" #~ msgstr "upnp: địa chỉ IP được NAT trả vá»: %s\n" #~ msgid "" #~ "The UPnP service could not be loaded. To disable UPnP, set the " #~ "configuration option \"UPNP\" in section \"%s\" to \"NO\"\n" #~ msgstr "" #~ "Dịch vụ UPnP không thể nạp được. Äể tắt UPnP, đặt tùy chá»n cấu hình « " #~ "UPNP » trong phần « %s » thành « NO » (không).\n" #~ msgid "# bytes sent via HTTP" #~ msgstr "# các byte đã gá»­i qua HTTP" #~ msgid "# bytes dropped by HTTP (outgoing)" #~ msgstr "# các byte loại bá» bởi HTTP (Ä‘i ra)" #~ msgid "# HTTP GET issued" #~ msgstr "# Tín hiệu HTTP GET được gá»­i" #~ msgid "# HTTP PUT issued" #~ msgstr "# Tín hiệu HTTP PUT được gá»­i" #~ msgid "# HTTP send calls" #~ msgstr "# các cuá»™c gá»i HTTP send (gá»­i)" #~ msgid "# HTTP curl send callbacks" #~ msgstr "# các cuá»™c gá»i ngược HTTP curl send (hàm curl gá»­i)" #~ msgid "# HTTP curl receive callbacks" #~ msgstr "# các cuá»™c gá»i ngược HTTP curl receive (hàm curl nhận)" #~ msgid "# HTTP mhd access callbacks" #~ msgstr "# các cuá»™c gá»i ngược HTTP mhd access (hàm mhd truy cập)" #~ msgid "# HTTP mhd read callbacks" #~ msgstr "# các cuá»™c gá»i ngược HTTP mhd read (hàm mhd Ä‘á»c)" #~ msgid "# HTTP mhd close callbacks" #~ msgstr "# các cuá»™c gá»i ngược HTTP mhd close (hàm mhd đóng)" #~ msgid "# HTTP connect calls" #~ msgstr "# các cuá»™c gá»i HTTP connect (kết nối)" #~ msgid "Failed to obtain my (external) %s address!\n" #~ msgstr "Lá»—i lấy địa chỉ %s (bên ngoài) cá»§a mình.\n" #~ msgid "MTU %llu for `%s' is probably too low!\n" #~ msgstr "MTU %llu cho « %s » rất có thể quá thấp.\n" #~ msgid "# UDP connections (right now)" #~ msgstr "# các kết nối UDP (lúc này)" #~ msgid "specify host on which gnunetd is running" #~ msgstr "ghi rõ máy trên đó chạy trình ná»n gnunetd" #~ msgid "" #~ "External protocol violation: assertion failed at %s:%d (no need to panic, " #~ "we can handle this).\n" #~ msgstr "" #~ "Xâm phạm giao thức bên ngoài: khẳng định không thành công tại %s:%d (đừng " #~ "lo, vẫn còn có thể sá»­a chữa).\n" #~ msgid "No help available." #~ msgstr "Không có trợ giúp sẵn sàng." #~ msgid "" #~ "You can use 'make check' in src/transports/upnp/ to find out if your NAT " #~ "supports UPnP. You should disable this option if you are sure that you " #~ "are not behind a NAT. If your NAT box does not support UPnP, having this " #~ "on will not do much harm (only cost a small amount of resources)." #~ msgstr "" #~ "Bạn có thể dùng câu lệnh « make check » trong « src/transports/upnp » để " #~ "tìm biết nếu NAT đó há»— trợ UPnP không. Chưa chắc nếu máy này nằm sau má»™t " #~ "NAT thì bạn nên tắt tùy chá»n này. Nếu máy NAT đó không há»— trợ UPnP, việc " #~ "bật tùy chá»n này sẽ không rất vấn đỠgì (chỉ chiếm má»™t ít tài nguyên)." #~ msgid "Prompt for development and/or incomplete code" #~ msgstr "Nhắc vá»›i mã vẫn phát triển và/hay mã chưa hoàn toàn" #~ msgid "" #~ "If EXPERIMENTAL is set to NO, options for experimental code are not " #~ "shown. If in doubt, use NO.\n" #~ "\n" #~ "Some options apply to experimental code that maybe in a state of " #~ "development where the functionality, stability, or the level of testing " #~ "is not yet high enough for general use. These features are said to be of " #~ "\"alpha\" quality. If a feature is currently in alpha, uninformed use is " #~ "discouraged (since the developers then do not fancy \"Why doesn't this " #~ "work?\" type messages).\n" #~ "\n" #~ "However, active testing and qualified feedback of these features is " #~ "always welcome. Users should just be aware that alpha features may not " #~ "meet the normal level of reliability or it may fail to work in some " #~ "special cases. Bug reports are usually welcomed by the developers, but " #~ "please read the documents and and use for how to report problems." #~ msgstr "" #~ "Nếu EXPERIMENTAL (thá»±c nghiệm) được đặt thành NO (không) thì không hiển " #~ "thị tùy chá»n vá» mã vẫn thá»±c nghiệm. Chưa chắc thì đặt NO.\n" #~ "\n" #~ "Má»™t số tùy chá»n nào đó có áp dụng cho mã thá»±c nghiệm, mà có thể vẫn còn " #~ "được phát triển thì chưa đầy đủ chức năng, ổn định hay đủ thá»­ để sá»­ dụng " #~ "má»™t cách chung. Các tính năng này được nhãn là « alpha » (a). Nếu má»™t " #~ "tính năng vẫn là alpha, khuyên ngưá»i dùng bình thưá»ng không dùng nó.\n" #~ "\n" #~ "Tùy nhiên, nếu bạn quen vá»›i tiến trình thá»­ và phản hồi, má»i bạn tham gia " #~ "(miá»…n là bạn hiểu được rằng phần má»m này có thể chưa sẵn sàng sá»­ dụng vá»›i " #~ "dữ liệu quan trá»ng). Nhà phát triển má»i bạn gá»­i báo cáo lá»—i: xin hãy Ä‘á»c " #~ "tài liệu và , sau đó dùng địa " #~ "chỉ để thông báo vấn Ä‘á»." #~ msgid "Show options for advanced users" #~ msgstr "Hiện tùy chá»n cấp cao" #~ msgid "" #~ "These are options that maybe difficult to understand for the beginner. " #~ "These options typically refer to features that allow tweaking of the " #~ "installation. If in a hurry, say NO." #~ msgstr "" #~ "Tùy chá»n cấp này có thể khó hiểu cho ngưá»i dùng bắt đầu sá»­ dụng máy tính. " #~ "Tùy chá»n kiểu này thưá»ng tham chiếu đến tính năng cho phép Ä‘iá»u chỉnh bản " #~ "cài đặt. Vá»™i thì đặt NO (không)." #~ msgid "Show rarely used options" #~ msgstr "Hiện tùy chá»n ít dùng" #~ msgid "" #~ "These are options that hardly anyone actually needs. If you plan on " #~ "doing development on GNUnet, you may want to look into these. If in " #~ "doubt or in a hurry, say NO." #~ msgstr "" #~ "Tùy chá»n này cần bởi rất ít ngưá»i. Nếu bạn định phát triển qua GNUnet, có " #~ "lẽ tùy chá»n này có ích. Nếu không hay vá»™i, hãy đặt NO (không)." #~ msgid "Meta-configuration" #~ msgstr "Siêu cấu hình" #~ msgid "Which level of configuration should be available" #~ msgstr "Cấp cấu hình nên sẵn sàng" #~ msgid "Full pathname of GNUnet HOME directory" #~ msgstr "Tên đưá»ng dẫn đầy đủ đến thư mục HOME GNUnet" #~ msgid "" #~ "This gives the root-directory of the GNUnet installation. Make sure there " #~ "is some space left in that directory. :-) Users inserting or indexing " #~ "files will be able to store data in this directory up to the (global) " #~ "quota specified below. Having a few gigabytes of free space is " #~ "recommended." #~ msgstr "" #~ "Äây đưa ra thư mục gốc cá»§a bản cài đặt GNUnet. Hãy kiểm tra xem vẫn còn " #~ "có sức chứa còn lại trong thư mục đó. :-)\n" #~ "Ngưá»i dùng cần chèn hay phụ lục tập tin thì có thể lưu dữ liệu vào thư " #~ "mục này đến hạn ngạch (toàn cục) được ghi rõ dưới đây. Khuyên có vài GB " #~ "sức chứa còn rảnh." #~ msgid "Full pathname of GNUnet directory for file-sharing data" #~ msgstr "" #~ "Tên đưá»ng dẫn đầy đủ đến thư mục GNUnet sẽ chứa dữ liệu chia sẻ tập tin" #~ msgid "Full pathname to the directory with the key-value database" #~ msgstr "Tên đưá»ng dẫn đầy đủ đến thư mục có cÆ¡ sở dữ liệu khoá-giá_trị " #~ msgid "Note that the kvstore is currently not used." #~ msgstr "Ghi chú rằng hiện thá»i không dùng kvstore. " #~ msgid "Full pathname of GNUnet directory for indexed files symbolic links" #~ msgstr "" #~ "Tên đưá»ng dẫn đầy đủ đến thư mục GNUnet sẽ chứa các liên kết tương trưng " #~ "đến tập tin phụ lục" #~ msgid "How many minutes should peer advertisements last?" #~ msgstr "Có nên quảng cáo đồng đẳnh trong mấy phút?" #~ msgid "" #~ "How many minutes is the current IP valid? (GNUnet will sign HELLO " #~ "messages with this expiration timeline. If you are on dialup, 60 (for 1 " #~ "hour) is suggested. If you have a static IP address, you may want to set " #~ "this to a large value (say 14400). The default is 1440 (1 day). If your " #~ "IP changes periodically, you will want to choose an expiry period smaller " #~ "than the frequency with which your IP changes." #~ msgstr "" #~ "Äịa chỉ IP hiện thá»i vẫn hợp lệ trong bao nhiêu phút? (GNUnet sẽ ký má»—i " #~ "thông Ä‘iệp HELLO dùng thá»i hạn này. Nếu bạn quay số để kết nối, khuyên " #~ "dùng 60 (1 giá»). Nếu máy này có má»™t địa chỉ IP tÄ©nh, má»™t giá trị lá»›n hÆ¡n " #~ "(v.d. 14400) có ích. Mặc định là 1440 (1 ngày). Nếu máy này có má»™t địa " #~ "chỉ IP thay đổi theo định kỳ, khuyên bạn chá»n má»™t thá»i hạn ngắn hÆ¡n " #~ "khoảng thá»i gian giữa hai lần thay đổi địa chỉ IP." #~ msgid "Where can GNUnet find an initial list of peers?" #~ msgstr "GNUnet có thể tìm má»™t danh sách các đồng đẳng đầu tiên ở đâu?" #~ msgid "" #~ "GNUnet can automatically update the hostlist from the web. While GNUnet " #~ "internally communicates which hosts are online, it is typically a good " #~ "idea to get a fresh hostlist whenever gnunetd starts from the WEB. By " #~ "setting this option, you can specify from which server gnunetd should try " #~ "to download the hostlist. The default should be fine for now.\n" #~ "\t\t\n" #~ "The general format is a list of space-separated URLs. Each URL must have " #~ "the format http://HOSTNAME/FILENAME\n" #~ "\t\t\n" #~ "If you want to setup an alternate hostlist server, you must run a " #~ "permanent node and \"cat data/hosts/* > hostlist\" every few minutes to " #~ "keep the list up-to-date.\n" #~ "\t\t\n" #~ "If you do not specify a HOSTLISTURL, you must copy valid hostkeys to data/" #~ "hosts manually." #~ msgstr "" #~ "GNUnet có khả năng tá»± động cập nhật danh sách các máy chá»§ từ Web. Dù " #~ "GNUnet liên lạc ná»™i bá»™ những máy này hiện thá»i trá»±c tuyến, thưá»ng có ích " #~ "để lấy má»™t danh sách máy má»›i từ Web khi nào trình ná»n gnunetd khởi chạy. " #~ "Bằng cách đặt tùy chá»n này, bạn có thể ghi rõ gnunetd nên thá»­ tải danh " #~ "sách máy xuống máy phục vụ nào. Bây giá» giá trị mặc định vẫn ổn.\n" #~ "\n" #~ "Äịnh dạng chung là má»™t danh sách các địa chỉ URL định giá»›i bằng dấu cách. " #~ "Má»—i địa chỉ URL nên có dạng « http://tên_máy/tên_tập_tin ».\n" #~ "\n" #~ "Muốn thiết lập má»™t máy phục vụ danh sách máy xen kẽ thì bạn cần phải chạy " #~ "má»™t nút thông tin (node) bá»n bỉ, và chạy câu lệnh « cat data/hosts/* > " #~ "hostlist » sau má»—i vài phút để cập nhật danh sách.\n" #~ "\n" #~ "Nếu bạn không ghi rõ má»™t HOSTLISTURL (địa chỉ URL cá»§a danh sách máy), bạn " #~ "cÅ©ng cần phải tá»± sao chép má»—i khoá máy hợp lệ vào « data/hosts »." #~ msgid "HTTP Proxy Server" #~ msgstr "Máy phục vụ á»§y nhiệm HTTP" #~ msgid "" #~ "If you have to use a proxy for outbound HTTP connections, specify the " #~ "proxy configuration here. Default is no proxy." #~ msgstr "" #~ "Nếu bạn cần dùng má»™t máy phục vụ á»§y nhiệm cho kết nối HTTP Ä‘i ra, hãy ghi " #~ "rõ cấu hình á»§y nhiệm ở đây. Mặc định là không dùng á»§y nhiệm." #~ msgid "" #~ "Name of the directory where gnunetd should store contact information " #~ "about peers" #~ msgstr "" #~ "Tên cá»§a thư mục vào đó gnunetd nên lưu thông tin liên lạc vỠđồng đẳng" #~ msgid "" #~ "Unless you want to share the directory directly using a webserver, the " #~ "default is most likely just fine." #~ msgstr "" #~ "Nếu bạn không muốn chia sẻ thư mục má»™t cách trá»±c tiếp dùng má»™t máy phục " #~ "vụ Web, giá trị mặc định rất có thể ổn." #~ msgid "How long should logs be kept?" #~ msgstr "Bao lâu nên giữ bản theo dõi?" #~ msgid "" #~ "How long should logs be kept? If you specify a value greater than zero, a " #~ "log is created each day with the date appended to its filename. These " #~ "logs are deleted after $KEEPLOG days.\tTo keep logs forever, set this " #~ "value to 0." #~ msgstr "" #~ "Bao lâu nên giữ sổ theo dõi (log)? Nếu bạn ghi rõ má»™t giá trị hÆ¡n số " #~ "không, má»™t sổ theo dõi được tạo hàng ngày vá»›i ngày tháng được phụ thêm " #~ "vào tên tập tin. Sổ theo dõi này bị xoá sau $KEEPLOG ngày.\tÄể không bao " #~ "giá» xoá sổ theo dõi, hãy đặt giá trị này thành 0." #~ msgid "" #~ "What maximum number of open file descriptors should be requested from the " #~ "OS?" #~ msgstr "" #~ "Có nên yêu cầu từ hệ Ä‘iá»u hành bao nhiêu bá»™ mô tả tập tin còn mở (tối Ä‘a)?" #~ msgid "" #~ "The default of 1024 should be fine for most systems. If your system can " #~ "support more, increasing the number might help support additional clients " #~ "on machines with plenty of bandwidth. For embedded systems, a smaller " #~ "number might be acceptable. A value of 0 will leave the descriptor limit " #~ "untouched. This option is mostly for OS X systems where the default is " #~ "too low. Note that if gnunetd cannot obtain the desired number of file " #~ "descriptors from the operating system, it will print a warning and try to " #~ "run with what it is given." #~ msgstr "" #~ "Giá trị mặc định 1024 nên ổn cho phần lá»›n hệ thống. Nếu hệ thống này có " #~ "khả năng há»— trợ nhiá»u bá»™ mô tả tập tin hÆ¡n, má»™t số lá»›n hÆ¡n có thể giúp há»— " #~ "trợ các ứng dụng khách bổ sung trên máy có rất nhiá»u bảng thông. Äối vá»›i " #~ "hệ thống nhúng, má»™t số nhá» hÆ¡n có thể ổn. Giá trị 0 sẽ không thay đổi " #~ "giá»›i hạn. Tùy chá»n này thưá»ng có ích trên hệ thống OSX (có giá trị mặc " #~ "định quá thấp). Ghi chú rằng nếu gnunetd không thể lấy số các bá»™ mô tả " #~ "tập tin yêu cầu từ hệ Ä‘iá»u hành, thì nó sẽ in ra má»™t cảnh báo và thá»­ chạy " #~ "vá»›i số đưa ra." #~ msgid "Where should gnunetd write the logs?" #~ msgstr "gnunetd nên ghi sổ theo dõi vào đâu?" #~ msgid "Enable for extra-verbose logging." #~ msgstr "Bật để theo dõi rất chi tiết hÆ¡n." #~ msgid "Specify which system messages should be logged how" #~ msgstr "Ghi rõ những thông Ä‘iệp hệ thống nào nên được theo dõi như thế nào" #~ msgid "Logging of events for users" #~ msgstr "Theo dõi sá»± kiện cho ngưá»i dùng" #~ msgid "Logging of events for the system administrator" #~ msgstr "Theo dõi sá»± kiện cho quản trị hệ thống" #~ msgid "Where should gnunetd write the PID?" #~ msgstr "gnunetd nên ghi PID vào đâu?" #~ msgid "" #~ "The default is no longer /var/run/gnunetd.pid since we could not delete " #~ "the file on shutdown at that location." #~ msgstr "" #~ "Giá trị mặc định không còn là « /var/run/gnunetd.pid » lại, vì không thể " #~ "xoá tập tin ở vị trí đó khi tắt máy." #~ msgid "As which user should gnunetd run?" #~ msgstr "gnunetd nên chạy dưới ngưá»i dùng nào?" #~ msgid "" #~ "Empty means \"current user\". On computer startup, it is root/SYSTEM. " #~ "Under Windows, this setting affects the creation of a new system service " #~ "only." #~ msgstr "" #~ "Trống có nghÄ©a là « ngưá»i dùng hiện thá»i ». Khi máy khởi động, nó là « " #~ "root/SYSTEM ». Dưới Windows, thiết lập này chỉ ảnh hưởng đến việc tạo má»™t " #~ "dịch vụ hệ thống." #~ msgid "Should gnunetd be automatically started when the system boots?" #~ msgstr "Khi hệ thống khởi động, có nên tá»± động khởi chạy gnunetd không?" #~ msgid "" #~ "Set to YES if gnunetd should be automatically started on boot. If this " #~ "option is set, gnunet-setup will install a script to start the daemon " #~ "upon completion. This option may not work on all systems." #~ msgstr "" #~ "Äặt thành YES (có) nếu trình ná»n gnunetd nên tá»± động được khởi chạy khi " #~ "hệ thống khởi động. Nếu đặt tùy chá»n này thì tiến trình thiết lập gnunet-" #~ "setup sẽ cài đặt má»™t văn lệnh để khởi chạy trình ná»n này má»™t khi hoàn " #~ "tất. Tùy chá»n này có thể không hoạt động đúng trên má»i hệ thống." #~ msgid "Which transport mechanisms should GNUnet use?" #~ msgstr "GNUnet nên dùng những cÆ¡ chế truyá»n nào?" #~ msgid "" #~ "Use a space-separated list of modules, e.g. \"udp smtp tcp\". The " #~ "available transports are udp, tcp, http, smtp and nat.\n" #~ "\t\t\n" #~ "Loading the 'nat' and 'tcp' modules is required for peers behind NAT " #~ "boxes that cannot directly be reached from the outside. Peers that are " #~ "NOT behind a NAT box and that want to *allow* peers that ARE behind a NAT " #~ "box to connect must ALSO load the 'nat' module. Note that the actual " #~ "transfer will always be via tcp initiated by the peer behind the NAT " #~ "box. The nat transport requires the use of tcp, http and/or smtp in " #~ "addition to nat itself." #~ msgstr "" #~ "Dùng má»™t danh sách các mô-Ä‘un định giá»›i bằng dấu cách, v.d. « udp smtp " #~ "tcp ». Những cÆ¡ chế truyá»n sẵn sàng: udp, tcp, http, smtp, nat.\n" #~ "\n" #~ "Nạp hai mô-Ä‘un « nat » và « tcp » cần thiết cho đồng đẳng nằm sau máy NAT " #~ "mà không tá»›i được từ bên ngoài. Äồng đẳng KHÔNG phải nằm sau máy NAT và " #~ "muốn _cho phép_ kết nối từ đồng đẳng mà CÓ phải nằm sau NAT thì CŨNG cần " #~ "phải nạp mô-Ä‘un « nat ». Ghi chú rằng việc truyá»n thật lúc nào cÅ©ng chạy " #~ "qua tcp, được sÆ¡ khởi bởi đồng đẳng nằm sau máy NAT. CÆ¡ chế truyá»n nat " #~ "cÅ©ng cần thiết tcp, http và/hay smtp thêm vào nat chính nó." #~ msgid "Which applications should gnunetd support?" #~ msgstr "gnunetd nên há»— trợ những ứng dụng nào?" #~ msgid "" #~ "Whenever this option is changed, you MUST run gnunet-update. Currently, " #~ "the available applications are:\n" #~ "\n" #~ "advertising: advertises your peer to other peers. Without it, your peer " #~ "will not participate in informing peers about other peers. You should " #~ "always load this module.\n" #~ "\n" #~ "getoption: allows clients to query gnunetd about the values of various " #~ "configuration options. Many tools need this. You should always load " #~ "this module.\n" #~ "\n" #~ "stats: allows tools like gnunet-stats and gnunet-gtk to query gnunetd " #~ "about various statistics. This information is usually quite useful to " #~ "diagnose errors, hence it is recommended that you load this module.\n" #~ "\n" #~ "traffic: keeps track of how many messages were recently received and " #~ "transmitted. This information can then be used to establish how much " #~ "cover traffic is currently available. The amount of cover traffic " #~ "becomes important if you want to make anonymous requests with an " #~ "anonymity level that is greater than one. It is recommended that you " #~ "load this module.\n" #~ "\n" #~ "fs: needed for anonymous file sharing. You should always load this " #~ "module.\n" #~ "\n" #~ "hostlist: integrated hostlist HTTP server. Useful if you want to offer a " #~ "hostlist and running Apache would be overkill.\n" #~ "\n" #~ "chat: broadcast chat (demo-application, ALPHA quality).\tRequired for " #~ "gnunet-chat. Note that the current implementation of chat is not " #~ "considered to be secure.\n" #~ "\n" #~ "tbench: benchmark transport performance. Required for gnunet-tbench. " #~ "Note that tbench allows other users to abuse your resources.\n" #~ "\n" #~ "tracekit: topology visualization toolkit. Required for gnunet-tracekit. " #~ "Note that loading tracekit will make it slightly easier for an adversary " #~ "to compromise your anonymity." #~ msgstr "" #~ "Khi nào tùy chá»n này bị thay đổi, bạn CẦN PHẢI chạy tiến trình cập nhật " #~ "gnunet-update. Hiện thá»i có những ứng dụng sẵn sàng này:\n" #~ "\n" #~ " • advertising\tquảng cáo đồng đẳng này cho các đồng đẳng khác. Không có " #~ "ứng dụng này thì đồng đẳng này sẽ không tham gia hoạt động cho đồng đẳng " #~ "biết vỠđồng đẳng khác. Lúc nào cÅ©ng nên nạp mô-Ä‘un này.\n" #~ "\n" #~ " • getoption\tcho phép ứng dụng khách há»i gnunetd vá» giá trị cá»§a má»™t số " #~ "tùy chá»n cấu hình nào đó. Rất nhiá»u công cụ cần chức năng này. Lúc nào " #~ "cÅ©ng nên nạp mô-Ä‘un này.\n" #~ "\n" #~ " • stats\tcho phép công cụ như gnunet-stats và gnunet-gtk há»i gnunetd vá» " #~ "má»™t số thống kê nào đó. Thông tin này thưá»ng hÆ¡i hữu ích để chẩn Ä‘oán " #~ "lá»—i, do đó khuyên bạn nạp mô-Ä‘un này.\n" #~ "\n" #~ " • traffic\ttheo dõi bao nhiêu tin nhẳn vừa nhận và gá»­i. Thông tin này " #~ "thì có thể được dùng để tính bao nhiêu giao thông trải ra hiện thá»i sẵn " #~ "sàng. Lượng giao thông trải ra trở thành quan trá»ng nếu bạn muốn gá»­i yêu " #~ "cầu nặc danh vá»›i má»™t cấp nặc danh hÆ¡n má»™t. Khuyên bạn nạp mô-Ä‘un này.\n" #~ "\n" #~ " • fs\tcần để chia sẻ tập tin má»™t cách nặc danh. Lúc nào cÅ©ng nên nạp mô-" #~ "Ä‘un này.\n" #~ "\n" #~ " • hostlist\ttrình phục vụ HTTP danh sách máy thống nhất. Có ích nếu bạn " #~ "muốn cung cấp má»™t danh sách máy, nhưng không muốn chạy Apache cho má»™t " #~ "công việc rất nhá» như vậy.\n" #~ "\n" #~ " • chat\ttrò chuyện quảng bá (ứng dụng minh hoạ, vẫn ALPHA). Cần thiết " #~ "cho ứng dụng trò chuyện gnunet-chat. Ghi chú rằng bản thá»±c hiện chat hiện " #~ "thá»i chưa được xem là bảo mật.\n" #~ "\n" #~ " • tbench\tkiểm chuẩn hiệu suất truyá»n. Cần thiết cho gnunet-tbench. Ghi " #~ "chú rằng tbench cho phép ngưá»i dùng khác lạm dụng các tài nguyên cá»§a " #~ "bạn.\n" #~ "\n" #~ " • tracekit\tbá»™ công cụ mưá»ng tượng địa hình. Cần thiết cho gnunet-" #~ "tracekit. Ghi chú rằng việc nạp tracekit sẽ làm cho má»™t ít dá»… hÆ¡n khi " #~ "ngưá»i dùng muốn xâm nhập tình trạng nặc danh cá»§a bạn." #~ msgid "Disable client-server connections" #~ msgstr "Tắt má»i kết nối kiểu khách-máy_phục_vụ" #~ msgid "" #~ "This option can be used to tell gnunetd not to open the client port. " #~ "When run like this, gnunetd will participate as a peer in the network but " #~ "not support any user interfaces. This may be useful for headless systems " #~ "that are never expected to have end-user interactions. Note that this " #~ "will also prevent you from running diagnostic tools like gnunet-stats!" #~ msgstr "" #~ "Tùy chá»n này có thể được dùng để báo trình ná»n gnunetd không mở cổng cho " #~ "ứng dụng khách. Khi chạy bằng cách này, gnunetd sẽ tham gia là má»™t đồng " #~ "đẳng trên mạng, còn không há»— trợ giao diện ngưá»i dùng nào. Có thể hữu ích " #~ "cho hệ thống không cần màn hình mà không bao giá» nên tương tác vá»›i ngưá»i " #~ "dùng cuối cùng. Ghi chú rằng tùy chá»n này cÅ©ng ngăn cản bạn chạy công cụ " #~ "chẩn Ä‘oán như tiến trình thống kê gnunet-stats !" #~ msgid "YES disables IPv6 support, NO enables IPv6 support" #~ msgstr "YES hay NO thì tắt hay bật há»— trợ IPv6" #~ msgid "" #~ "This option may be useful on peers where the kernel does not support " #~ "IPv6. You might also want to set this option if you do not have an IPv6 " #~ "network connection." #~ msgstr "" #~ "Tùy chá»n này có thể hữu ích trên đồng đẳng không có hạt nhân há»— trợ IPv6. " #~ "CÅ©ng có thể đặt tùy chá»n này nếu không có kết nối mạng kiểu IPv6." #~ msgid "Disable peer discovery" #~ msgstr "Tắt khám phá đồng đẳng" #~ msgid "" #~ "The option 'PRIVATE-NETWORK' can be used to limit the connections of this " #~ "peer to peers of which the hostkey has been copied by hand to data/" #~ "hosts; if this option is given, GNUnet will not accept advertisements of " #~ "peers that the local node does not already know about. Note that in " #~ "order for this option to work, HOSTLISTURL should either not be set at " #~ "all or be set to a trusted peer that only advertises the private network. " #~ "Also, the option does NOT work at the moment if the NAT transport is " #~ "loaded; for that, a couple of lines above would need some minor " #~ "editing :-)." #~ msgstr "" #~ "Tùy chá»n « PRIVATE-NETWORK » có thể được dùng để hạn chế kết nối cá»§a đồng " #~ "đẳng này thành những đồng đẳng có khoá máy đã được sao chép bằng tay vào " #~ "« data/hosts »; nếu bật tùy chá»n này thì GNUnet sẽ không chấp nhận quảng " #~ "cáo vỠđồng đẳng không được nút cục bá»™ nhận ra. Ghi chú rằng tùy chá»n này " #~ "cÅ©ng cần HOSTLISTURL không đặt bằng cách nào cả hay có đặt thành má»™t đồng " #~ "đẳng tin cậy mà chỉ quảng cáo mạng riêng. HÆ¡n nữa, tùy chá»n này KHÔNG " #~ "hoạt động khi nào cÆ¡ chế trung NAT được nạp: để tránh trưá»ng hợp đó, cÅ©ng " #~ "cần phải chỉnh sá»­a vài dòng bên trên. :-)" #~ msgid "Disable automatic establishment of connections" #~ msgstr "Tắt tá»± động thiết lập kết nối" #~ msgid "" #~ "If this option is enabled, GNUnet will not automatically establish " #~ "connections to other peers, but instead wait for applications to " #~ "specifically request connections to other peers (or for other peers to " #~ "connect to us)." #~ msgstr "" #~ "Bật tùy chá»n này thì GNUnet sẽ không tá»± động thiết lập kết nối tá»›i đồng " #~ "đẳng khác, thay vào đó nó đợi ứng đụng yêu cầu dứt khoát kết nối tá»›i đồng " #~ "đẳng khác (hoặc đợi đồng đẳng khác kết nối đến máy này)." #~ msgid "Enable advertising of other peers by this peer" #~ msgstr "Bật máy này quảng cáo đồng đẳng khác" #~ msgid "" #~ "This option may be useful during testing, but turning it off is " #~ "dangerous! If in any doubt, set it to YES (which is the default)." #~ msgstr "" #~ "Tùy chá»n này có thể hữu ích trong khi thá»­: trong má»i trưá»ng hợp Ä‘á»u không " #~ "nên tắt nó ! Chưa chắc thì đặt nó thành YES (có) mà mặc định." #~ msgid "" #~ "Which is the client-server port that is used between gnunetd and the " #~ "clients (TCP only). You may firewall this port for non-local machines " #~ "(but you do not have to since GNUnet will perform access control and only " #~ "allow connections from machines that are listed under TRUSTED)." #~ msgstr "" #~ "Trình ná»n gnunetd và các ứng dụng khách liên lạc (chỉ TCP) qua cổng khách-" #~ "phục_vụ nào? Bạn cÅ©ng có thể đặt bức tưá»ng lá»­a giữa cổng này và các máy " #~ "khác cục bá»™, nhưng không cần phải vì GNUnet sẽ Ä‘iá»u khiển truy cập và chỉ " #~ "cho phép kết nối từ máy được liệt kê dưới TRUSTED (tin cậy). " #~ msgid "IPv4 networks allowed to use gnunetd server" #~ msgstr "Các mạng IPV4 được phép dùng trình phục vụ gnunetd" #~ msgid "" #~ "This option specifies which hosts are trusted enough to connect as " #~ "clients (to the TCP port). This is useful if you run gnunetd on one host " #~ "of your network and want to allow all other hosts to use this node as " #~ "their server. By default, this is set to 'loopback only'. The format is " #~ "IP/NETMASK where the IP is specified in dotted-decimal and the netmask " #~ "either in CIDR notation (/16) or in dotted decimal (255.255.0.0). Several " #~ "entries must be separated by a semicolon, spaces are not allowed." #~ msgstr "" #~ "Tùy chá»n này ghi rõ những máy nào đủ tin cậy để kết nối là ứng dụng khách " #~ "(đến cổng TCP). Có ích nếu bạn chạy trình nên gnunetd trên má»™t máy cá»§a " #~ "mạng cục bá»™, cÅ©ng muốn các máy khác cùng mạng dùng nút này làm máy phục " #~ "vụ. Mặc định là tùy chá»n này được đặt thành « loopback only » (chỉ mạch " #~ "ná»™i bá»™). Äịnh dạng là IP/MẶT_NẠ_MẠNG mà địa chỉ IP được ghi rõ theo thập " #~ "phân đánh chấm (v.d. 255.255.0.0), và mặt nạ mạng (netmask) theo hoặc " #~ "cách ghi CIDR (v.d. 1/16) hoặc thập phân đánh chấm. Vài mục nhập nên định " #~ "giá»›i bằng dấu hai chấm, cÅ©ng không cho phép khoảng cách." #~ msgid "IPv6 networks allowed to use gnunetd server" #~ msgstr "Các mạng IPv6 được phép dùng trình phục vụ gnunetd" #~ msgid "Limit connections to the specfied set of peers." #~ msgstr "Hạn chế kết nối thành tập hợp đồng đẳng được ghi rõ." #~ msgid "" #~ "If this option is not set, any peer is allowed to connect. If it is set, " #~ "only the specified peers are allowed. Specify the list of peer IDs (not " #~ "IPs!)" #~ msgstr "" #~ "Không bật tùy chá»n này thì má»i đồng đẳng được phép kết nối. Nếu bật nó " #~ "thì chỉ cho phép những đồng đẳng đưa ra. Hãy ghi rõ danh sách các mã số " #~ "đồng đẳng, không phải địa chỉ IP !" #~ msgid "Run gnunetd as this group." #~ msgstr "Chạy gnunetd dưới nhóm này." #~ msgid "" #~ "When started as root, gnunetd will change permissions to the given group." #~ msgstr "" #~ "Khi khởi chạy bởi ngưá»i chá»§, trình ná»n gnunetd sẽ chuyển đổi quyá»n truy " #~ "cập sang nhóm đưa ra." #~ msgid "Prevent the specfied set of peers from connecting." #~ msgstr "Chặn kết nối từ tập hợp đồng đẳng được ghi rõ." #~ msgid "" #~ "If this option is not set, any peer is allowed to connect. If the ID of " #~ "a peer is listed here, connections from that peer will be refused. " #~ "Specify the list of peer IDs (not IPs!)" #~ msgstr "" #~ "Không bật tùy chá»n này thì má»i đồng đẳng Ä‘á»u được phép kết nối. Nếu mã số " #~ "cá»§a má»™t đồng đẳng nào đó được liệt kê ở đây, thì kết nối từ máy đó bị từ " #~ "chối. Hãy ghi rõ danh sách các mã số đồng đẳng, không phải địa chỉ IP !" #~ msgid "Topology Maintenance" #~ msgstr "Duy trì địa hình" #~ msgid "Rarely used settings for peer advertisements and connections" #~ msgstr "Thiết lập ít dùng vá» quảng cáo và kết nối cá»§a đồng đẳng" #~ msgid "General settings" #~ msgstr "Thiết lập chung" #~ msgid "Settings that change the behavior of GNUnet in general" #~ msgstr "Thiết lập mà sá»­a đổi ứng xá»­ chung cá»§a GNUnet" #~ msgid "Modules" #~ msgstr "Mô-Ä‘un" #~ msgid "Settings that select specific implementations for GNUnet modules" #~ msgstr "Thiết lập mà chá»n bản thá»±c hiện riêng cho mô-Ä‘un GNUnet" #~ msgid "Fundamentals" #~ msgstr "CÆ¡ bản" #~ msgid "Which database should be used?" #~ msgstr "Có nên dùng cÆ¡ sở dữ liệu nào?" #, fuzzy #~ msgid "" #~ "Which database should be used? The options are \"sqstore_sqlite\", " #~ "\"sqstore_postgres\" and \"sqstore_mysql\". You must run gnunet-update " #~ "after changing this value!\n" #~ "\t\t\t\n" #~ "In order to use MySQL or Postgres, you must configure the respective " #~ "database, which is relatively simple. Read the file doc/README.mysql or " #~ "doc/README.postgres for how to setup the respective database." #~ msgstr "" #~ "Có nên dùng cÆ¡ sở dữ liệu nào? Hai tùy chá»n là « sqstore_sqlite » và « " #~ "sqstore_mysql ». Sau khi thay đổi giá trị này thì cÅ©ng cần phải chạy tiến " #~ "trình cập nhật gnunet-update !\n" #~ "\n" #~ "Äể sá»­ dụng sqstore_mysql, bạn cÅ©ng cần phải cấu hình cÆ¡ sở dữ liệu MySQL: " #~ "má»™t công việc hÆ¡i đơn giản. Hãy Ä‘á»c tài liệu Äá»c Äi « doc/README.mysql » " #~ "để tìm biết thiết lập MySQL như thế nào." #~ msgid "Which topology should be used?" #~ msgstr "Có nên địa hình nào?" #~ msgid "" #~ "Which database should be used for the temporary datastore of the DHT?" #~ msgstr "Có nên dùng cÆ¡ sở dữ liệu nào làm kho dữ liệu tạm thá»i cá»§a DHT?" #~ msgid "" #~ "Which topology should be used? The only option at the moment is " #~ "\"topology_default\"" #~ msgstr "" #~ "Có nên địa hình nào? Tùy chá»n duy nhất hiện thá»i là « topology_default »." #~ msgid "" #~ "The minimum number of connected friends before this peer is allowed to " #~ "connect to peers that are not listed as friends" #~ msgstr "" #~ "Số tối thiểu các bạn bè có kết nối trước khi đồng đẳng nay được phép kết " #~ "nối tá»›i đồng đẳng lạ (không phải được liệt kê là bạn bè)" #~ msgid "" #~ "Note that this option does not guarantee that the peer will be able to " #~ "connect to the specified number of friends. Also, if the peer had " #~ "connected to a sufficient number of friends and then established non-" #~ "friend connections, some of the friends may drop out of the network, " #~ "temporarily resulting in having fewer than the specified number of " #~ "friends connected while being connected to non-friends. However, it is " #~ "guaranteed that the peer itself will never choose to drop a friend's " #~ "connection if this would result in dropping below the specified number of " #~ "friends (unless that number is higher than the overall connection target)." #~ msgstr "" #~ "Ghi chú rằng tùy chá»n này không đảm bảo rằng đồng đẳng sẽ kết nối được " #~ "tá»›i số các bạn bè đưa ra. HÆ¡n nữa, nếu đồng đẳng có kết nối tá»›i đủ bạn " #~ "bè, sau đó thiết lập kết nối khác bạn bè, thì má»™t số bạn bè có thể dứt " #~ "khá»i mạng, tạm thá»i có kết quả là quá ít bạn bè có kết nối trong khi kết " #~ "nối tá»›i khác bạn bè. Tuy nhiên đảm bảo rằng đồng đẳng chính nó không bao " #~ "giá» chá»n ngắt kết nối tá»›i bạn bè nếu việc đó có kết quả là quá ít bán bè " #~ "có kết nối (nếu số đã đặt không phải lá»›n hÆ¡n đích kết nối toàn bá»™)." #~ msgid "" #~ "If set to YES, the peer is only allowed to connect to other peers that " #~ "are explicitly specified as friends" #~ msgstr "" #~ "Bật tùy chá»n này (đặt YES) thì đồng đẳng chỉ được phép tá»›i đồng đẳng được " #~ "ghi rõ dứt khoát là bạn bè" #~ msgid "" #~ "Use YES only if you have (trustworthy) friends that use GNUnet and are " #~ "afraid of establishing (direct) connections to unknown peers" #~ msgstr "" #~ "Hãy đặt YES chỉ nếu bạn có bạn bè tin cậy có sá»­ dụng GNUnet và không muốn " #~ "thiết lập kết nối trá»±c tiếp tá»›i đồng đẳng lạ" #~ msgid "List of friends for friend-to-friend topology" #~ msgstr "Danh sách bạn bè cho địa hình bạn-đến-bạn" #~ msgid "" #~ "Specifies the name of a file which contains a list of GNUnet peer IDs " #~ "that are friends. If used with the friend-to-friend topology, this will " #~ "ensure that GNUnet only connects to these peers (via any available " #~ "transport)." #~ msgstr "" #~ "Ghi rõ tên cá»§a má»™t tập tin chứa danh sách các mã số đồng đẳng GNUnet cÅ©ng " #~ "là bạn bè. Nếu dùng vá»›i địa hình bạn-đến-bạn, thì tùy chá»n này sẽ đảm bảo " #~ "rằng GNUnet chỉ kết nối tá»›i những đồng đẳng đó (qua bất cứ cÆ¡ chế truyá»n " #~ "hoạt động nào)." #~ msgid "Friend-to-Friend Topology Specification" #~ msgstr "Äặc tả địa hình bạn-đến-bạn" #~ msgid "Settings for restricting connections to friends" #~ msgstr "Thiết lập để hạn chế kết nối thành bạn bè" #~ msgid "Name of the MySQL database GNUnet should use" #~ msgstr "Tên cá»§a cÆ¡ sở dữ liệu MySQL mà GNUnet nên dùng" #~ msgid "Configuration file that specifies the MySQL username and password" #~ msgstr "Tập tin cấu hình mà ghi rõ tên ngưá»i dùng và mật khẩu MySQL" #~ msgid "Configuration of the MySQL database" #~ msgstr "Cấu hình cá»§a cÆ¡ sở dữ liệu MySQL" #~ msgid "MB of diskspace GNUnet can use for anonymous file sharing" #~ msgstr "MB sức chứa trên đĩa cho GNUnet dùng để chia sẻ tập tin nặc danh" #~ msgid "" #~ "How much disk space (MB) is GNUnet allowed to use for anonymous file " #~ "sharing? This does not take indexed files into account, only the space " #~ "directly used by GNUnet is accounted for. GNUnet will gather content " #~ "from the network if the current space-consumption is below the number " #~ "given here (and if content migration is allowed below).\n" #~ "\n" #~ "Note that if you change the quota, you need to run gnunet-update " #~ "afterwards." #~ msgstr "" #~ "Bao nhiêu sức chứa trên đĩa (theo MB) cho phép GNUnet dùng để chia sẻ tập " #~ "tin má»™t cách nặc danh? Giá trị này không tính tập tin phụ lục, chỉ tính " #~ "sức chứa được GNUnet dùng trá»±c tiếp. GNUnet sẽ tập hợp ná»™i dung từ mạng " #~ "nếu tiêu thụ sức chứa hiện thá»i nhá» hÆ¡n số đưa ra ở đây (và nếu chức năng " #~ "nâng cấp ná»™i dung được phép bên dưới).\n" #~ "\n" #~ "Ghi chú rằng nếu bạn sá»­a đổi hạn ngạch này, sau đó cÅ©ng cần phải chạy " #~ "tiến trình cập nhật gnunet-update." #~ msgid "Number of entries in the migration buffer" #~ msgstr "Số các mục nhập trong vùng đệm nâng cấp" #~ msgid "" #~ "Each entry uses about 32k of memory. More entries can reduce disk IO and " #~ "CPU usage at the expense of having gnunetd use more memory. Very large " #~ "values may again increase CPU usage. A value of 0 will prevent your peer " #~ "from sending unsolicited responses." #~ msgstr "" #~ "Má»—i mục nhập chiếm khoảng 32k trong vùng nhá»›. Nhiá»u mục nhập hÆ¡n thì có " #~ "thể giảm VR cá»§a đĩa và sá»­ dụng CPU, còn gnunetd chiếm vùng nhá»› lá»›n hÆ¡n. " #~ "Giá trị rất lá»›n cÅ©ng có thể tăng sá»­ dụng CPU. Giá trị 0 sẽ ngăn cản máy " #~ "này đáp ứng mà không yêu cầu." #~ msgid "Size of the routing table for anonymous routing." #~ msgstr "Kích cỡ cá»§a bảng định tuyến đối vá»›i định tuyến nặc danh." #~ msgid "Size of the routing table for DHT routing." #~ msgstr "Kích cỡ cá»§a bảng định tuyến đối vá»›i định tuyến DHT." #~ msgid "Allow migrating content to this peer." #~ msgstr "Cho phép nâng cấp ná»™i dung lên máy này." #~ msgid "" #~ "If you say yes here, GNUnet will migrate content to your server, and you " #~ "will not be able to control what data is stored on your machine. \n" #~ "\t\t\t\n" #~ "If you activate it, you can claim for *all* the non-indexed (-n to gnunet-" #~ "insert) content that you did not know what it was even if an adversary " #~ "takes control of your machine. If you do not activate it, it is obvious " #~ "that you have knowledge of all the content that is hosted on your machine " #~ "and thus can be considered liable for it." #~ msgstr "" #~ "Bật tùy chá»n này thì GNUnet sẽ nâng cấp ná»™i dung đến máy phục vụ này, và " #~ "bạn không thể Ä‘iá»u khiển dữ liệu nào được giữ trên máy này.\n" #~ "\n" #~ "Tùy chá»n này cho phép ngưá»i dùng từ chối trách nhiệm vá» ná»™i dung không " #~ "phụ lục (-n tá»›i gnunet-insert) nằm trong máy cá»§a mình, thậm chí nếu ngưá»i " #~ "khác xâm nhập hệ thống. Không bật tùy chá»n này thì ngưá»i dùng chịu trách " #~ "nhiệm vá» tất cả các ná»™i dung trên máy cá»§a mình." #~ msgid "" #~ "MB of diskspace GNUnet can use for caching DHT index data (the data will " #~ "be stored in /tmp)" #~ msgstr "" #~ "MB sức chứa trên đĩa cho GNUnet dùng để lưu tạm dữ liệu phụ lục DHT (dữ " #~ "liệu được giữ trong /tmp)" #~ msgid "" #~ "DHT index data is inherently small and expires comparatively quickly. It " #~ "is deleted whenever gnunetd is shut down.\n" #~ "\n" #~ "The size of the DSTORE QUOTA is specified in MB." #~ msgstr "" #~ "Dữ liệu phụ lục DHT vốn đã nhá» và hết hạn hÆ¡i nhanh. Nó bị xoá khi nào " #~ "gnunetd bị thoát.\n" #~ "\n" #~ "Kích cỡ cá»§a hạn ngạch kho dữ liệu (DSTORE QUOTA) được ghi rõ theo MB." #~ msgid "Options for anonymous file sharing" #~ msgstr "Tùy chá»n vá» chia sẻ tập tin nặc danh" #~ msgid "Applications" #~ msgstr "Ứng dụng" #~ msgid "Is this machine unreachable behind a NAT?" #~ msgstr "Máy này không tá»›i được ở sau NAT không?" #~ msgid "" #~ "Set to YES if this machine is behind a NAT that limits connections from " #~ "the outside to the GNUnet port and that cannot be traversed using UPnP. " #~ "Note that if you have configured your NAT box to allow direct connections " #~ "from other machines to the GNUnet ports or if GNUnet can open ports using " #~ "UPnP, you should set the option to NO. Set this only to YES if other " #~ "peers cannot contact you directly. You can use 'make check' in src/" #~ "transports/upnp/ to find out if your NAT supports UPnP. You can also use " #~ "gnunet-transport-check with the '-p' option in order to determine which " #~ "setting results in more connections. Use YES only if you get no " #~ "connections otherwise. Set to AUTO to use YES if the local IP is belongs " #~ "to a private IP network and NO otherwise." #~ msgstr "" #~ "Äặt thành YES (có) nếu máy này nằm sau má»™t máy NAT mà hạn chế kết nối từ " #~ "bên ngoài đến cổng GNUnet và không thể Ä‘i qua được dùng UPnP. Ghi chú " #~ "rằng nếu bạn đã cấu hình máy NAT để cho phép kết nối trá»±c tiếp từ máy " #~ "khác đến cổng GNUnet, hoặc nếu GNUnet có quyá»n mở cổng dùng UPnP, thì bạn " #~ "nên đặt tùy chá»n này thành NO (không). Chỉ đặt thành YES nếu đồng đẳng " #~ "khác không thể liên lạc vá»›i máy này má»™t cách trá»±c tiếp. Bạn cÅ©ng có thể " #~ "sá»­ dụng câu lệnh « make check » (trong /src/transports/upnp) để tìm biết " #~ "nếu NAT đó há»— trợ UPnP không. Bạn cÅ©ng có thể sá»­ dụng công cụ gnunet-" #~ "transport-check vá»›i tùy chá»n « -p » để quyết định thiết lập nào gây ra " #~ "nhiá»u kết nối hÆ¡n. Äặt YES chỉ nếu bạn không nhận kết nối bằng cách khác. " #~ "Äặt thành AUTO (tá»± động) để sá»­ dụng YES nếu địa chỉ IP cục bá»™ thuá»™c vá» " #~ "má»™t mạng IP riêng, không thì NO." #~ msgid "Which port should be used by the TCP IPv4 transport?" #~ msgstr "CÆ¡ chế truyá»n IPv4 TCP nên dùng cổng nào?" #~ msgid "Should we try to determine our external IP using UPnP?" #~ msgstr "" #~ "Có nên thá»­ quyết định địa chỉ IP bên ngoài cá»§a mình dùng UPnP không?" #~ msgid "Which IP(v4)s are not allowed to connect?" #~ msgstr "Những địa chỉ IP(v4) nào không có quyá»n kết nối?" #~ msgid "" #~ "Which IP(v4)s are allowed to connect? Leave empty to use the IP of your " #~ "primary network interface." #~ msgstr "" #~ "Những địa chỉ IP(v4) nào có quyá»n kết nối? Bá» trống để sá»­ dụng địa chỉ IP " #~ "cá»§a giao diện mạng chính." #~ msgid "Which IPv6s are not allowed to connect?" #~ msgstr "Những địa chỉ IPv6 nào không có quyá»n kết nối?" #~ msgid "" #~ "Which IPv6s are allowed to connect? Leave empty to allow any IP to " #~ "connect." #~ msgstr "" #~ "Những địa chỉ IPv6 nào có quyá»n kết nối? Bá» trống để cho phép má»i địa chỉ " #~ "IP kết nối." #~ msgid "TCP transport" #~ msgstr "CÆ¡ chế truyá»n TCP" #~ msgid "Which port should be used by the HTTP transport?" #~ msgstr "CÆ¡ chế truyá»n HTTP nên dùng cổng nào?" #~ msgid "Which is the external port of the HTTP transport?" #~ msgstr "CÆ¡ chế truyá»n HTTP dùng cổng bên ngoài nào?" #~ msgid "" #~ "Use this option if your firewall maps, say, port 80 to your real HTTP " #~ "port. This can be useful in making the HTTP messages appear even more " #~ "legit (without needing to run gnunetd as root due to the use of a " #~ "privileged port)." #~ msgstr "" #~ "Hãy bật tùy chá»n này nếu bức tưá»ng lá»­a ánh xạ, v.d. cổng 80 vá»›i cổng HTTP " #~ "thật. Có thể hữu ích để làm cho các thông Ä‘iệp HTTP hình như ngay cả " #~ "chính đáng hÆ¡n (mà không cần chạy gnunetd dưới ngưá»i chá»§ do dùng má»™t cổng " #~ "có quyá»n đặc biệt)." #~ msgid "HTTP transport" #~ msgstr "CÆ¡ chế truyá»n HTTP" #~ msgid "What is the maximum transfer unit for SMTP?" #~ msgstr "Äối vá»›i SMTP, đơn vị truyá»n tối Ä‘a là gì?" #~ msgid "" #~ "What is the maximum number of e-mails that gnunetd would be allowed to " #~ "send per hour?" #~ msgstr "gnunetd có quyá»n gá»­i má»—i giá» bao nhiêu thư Ä‘iện tá»­ (tối Ä‘a)?" #~ msgid "Use 0 for unlimited" #~ msgstr "0 = vô hạn" #~ msgid "Which e-mail address should be used to send e-mail to this peer?" #~ msgstr "Äể gá»­i thư cho đồng đẳng này, có nên dùng địa chỉ thư Ä‘iện tá»­ nào?" #~ msgid "" #~ "You must make sure that e-mail received at this address is forwarded to " #~ "the PIPE which is read by gnunetd. Use the FILTER option to filter e-" #~ "mail with procmail and the PIPE option to set the name of the pipe." #~ msgstr "" #~ "Bạn cần phải đảm bảo rằng thư Ä‘iện tá»­ được nhận ở địa chỉ này thật được " #~ "chuyển tiếp tá»›i PIPE (ống dẫn) được gnunetd Ä‘á»c. Hãy dùng tùy chá»n FILTER " #~ "(lá»c) để lá»c thư bằng procmail, và tùy chá»n PIPE để đặt tên cá»§a ống dẫn." #~ msgid "" #~ "Which header line should other peers include in e-mails to enable " #~ "filtering?" #~ msgstr "Äể hiệu lá»±c lá»c thư, đồng đẳng khác nên ghi dòng đầu nào?" #~ msgid "" #~ "You can specify a header line here which can then be used by procmail to " #~ "filter GNUnet e-mail from your inbox and forward it to gnunetd." #~ msgstr "" #~ "Ở đây thì bạn có dịp ghi rõ má»™t dòng đầu cho procmail dùng để lá»c thư " #~ "GNUnet từ há»™p Thư Äến cá»§a bạn và chuyển tiếp nó tá»›i gnunetd." #~ msgid "What is the filename of the pipe where gnunetd can read its e-mail?" #~ msgstr "gnunetd có thể Ä‘á»c thư qua ống dẫn có tên tập tin nào?" #~ msgid "" #~ "Have a look at contrib/dot-procmailrc for an example .procmailrc file." #~ msgstr "" #~ "Xem « contrib/dot-procmailrc » để tìm má»™t tập tin .procmailrc ví dụ." #~ msgid "What is the name and port of the server for outgoing e-mail?" #~ msgstr "Máy phục vụ thư gá»­i ra có tên và cổng nào?" #~ msgid "The basic format is HOSTNAME:PORT." #~ msgstr "Äịnh dạng cÆ¡ bản là « TÊN_MÃY:Cá»”NG »." #~ msgid "SMTP transport" #~ msgstr "CÆ¡ chế SMTP" #~ msgid "Which port should be used by the UDP IPv4 transport?" #~ msgstr "CÆ¡ chế truyá»n IPv4 UDP nên dùng cổng nào?" #~ msgid "What is the maximum transfer unit for UDP?" #~ msgstr "Äối vá»›i UDP, đơn vị truyá»n tối Ä‘a là gì?" #~ msgid "Which IPs are not allowed to connect?" #~ msgstr "Những địa chỉ IP nào không có quyá»n kết nối?" #~ msgid "" #~ "Which IPs are allowed to connect? Leave empty to allow connections from " #~ "any IP." #~ msgstr "" #~ "Những địa chỉ IP nào có quyá»n kết nối? Bá» trống để cho phép kết nối từ " #~ "má»i địa chỉ IP." #~ msgid "UDP transport" #~ msgstr "CÆ¡ chế truyá»n UDP" #~ msgid "Network interface" #~ msgstr "Giao diện mạng" #~ msgid "External IP address (leave empty to try auto-detection)" #~ msgstr "Äịa chỉ IP bên ngoài (bá» trống để thá»­ tá»± động phát hiện)" #~ msgid "External IPv6 address (leave empty to try auto-detection)" #~ msgstr "Äịa chỉ IPv6 bên ngoài (bá» trống để thá»­ tá»± động phát hiện)" #~ msgid "Transports" #~ msgstr "CÆ¡ chế truyá»n" #~ msgid "What is the maximum number of bytes per second that we may receive?" #~ msgstr "Có thể nhận bao nhiêu byte má»—i giây (tối Ä‘a)?" #~ msgid "What is the maximum number of bytes per second that we may send?" #~ msgstr "Có thể gá»­i bao nhiêu byte má»—i giây (tối Ä‘a)?" #~ msgid "What is the maximum CPU load (percentage)?" #~ msgstr "Tải trá»ng CPU tối Ä‘a là gì (theo phần trăm)?" #~ msgid "" #~ "The highest tolerable CPU load. Load here always refers to the total " #~ "system load, that is it includes CPU utilization by other processes. A " #~ "value of 50 means that once your 1 minute-load average goes over 50% non-" #~ "idle, GNUnet will try to reduce CPU consumption until the load goes under " #~ "the threshold. Reasonable values are typically between 50 and 100. " #~ "Multiprocessors may use values above 100." #~ msgstr "" #~ "Tải trá»ng CPU cao nhất có thể. Ở đây thì tải trá»ng tham chiếu đến tổng số " #~ "tải trá»ng hệ thống, tức là nó cÅ©ng tính sá»­ dụng CPU cá»§a các tiến trình " #~ "khác. Giá trị 50 có nghÄ©a là má»™t khi tải trá»ng trung bình má»—i phút vượt " #~ "quá 50% không nghỉ, thì GNUnet thá»­ giảm sá»­ dụng CPU đến khi tải trá»ng nhá» " #~ "hÆ¡n ngưỡng. Giá trị hợp lý thưá»ng nằm giữa 50 và 100. Máy Ä‘a bá»™ xá»­ lý có " #~ "khả năng sá»­ dụng giá trị hÆ¡n 100." #~ msgid "What is the maximum IO load (permille)?" #~ msgstr "Tải trá»ng VR tối Ä‘a là gì (theo phần nghìn)?" #~ msgid "" #~ "The highest tolerable IO load. Load here refers to the percentage of CPU " #~ "cycles wasted waiting for IO for the entire system, that is it includes " #~ "disk utilization by other processes. A value of 10 means that once the " #~ "average number of cycles wasted waiting for IO is more than 10% non-idle, " #~ "GNUnet will try to reduce IO until the load goes under the threshold. " #~ "Reasonable values are typically between 10 and 75." #~ msgstr "" #~ "Tải trá»ng VR cao nhất có thể tha thứ được. Ở đây thì tải trá»ng tham chiếu " #~ "đến tá»· lệ phần trăm chu kỳ CPU bị phí khi đợi VR đối vá»›i toàn hệ thống, " #~ "tức là nó cÅ©ng tính sá»­ dụng đĩa cá»§a các tiến trình khác. Giá trị 10 có " #~ "nghÄ©a là má»™t khi số các chu kỳ trung bình bị phí khi đợi VR hÆ¡n 10% không " #~ "nghỉ, GNUnet sẽ thá»­ giảm VR đến khi tải trá»ng nhá» hÆ¡n ngưỡng. Giá trị hợp " #~ "lý thưá»ng nằm giữa 10 và 75." #~ msgid "What is the maximum CPU load (hard limit)?" #~ msgstr "Tải trá»ng CPU tối Ä‘a là gì (giá»›i hạn cứng)?" #~ msgid "" #~ "The highest tolerable CPU load. This is the hard limit, so once it is " #~ "reached, gnunetd will start to massively drop data to reduce the load. " #~ "Use with caution." #~ msgstr "" #~ "Tải trá»ng CPU cao nhất có thể tha thứ được. Äây là giá»›i hạn cứng, do đó " #~ "má»™t khi tá»›i được, gnunetd sẽ bắt đầu bá» rất nhiá»u dữ liệu để giảm tải " #~ "trá»ng. Hãy sá»­ dụng cẩn thận." #~ msgid "What is the maximum upstream bandwidth (hard limit)?" #~ msgstr "Băng thông dòng ra tối Ä‘a là gì (giá»›i hạn cứng)?" #~ msgid "" #~ "The limit is given as a percentage of the MAXNETUPBPS limit. Use 100 to " #~ "have MAXNETUPBPS be the hard limit. Use zero for no limit." #~ msgstr "" #~ "Giá»›i hạn được ghi rõ theo phần trăm cá»§a giá»›i hạn MAXNETUPBPS. Dùng 100 để " #~ "đặt MAXNETUPBPS là giá»›i hạn cứng. 0 = vô hạn." #, fuzzy #~ msgid "What priority should gnunetd use to run?" #~ msgstr "gnunetd nên chạy như nhóm nào?" #~ msgid "Should we disable random padding (experimental option)?" #~ msgstr "Có nên tắt đệm ngẫu nhiên (tùy chá»n vẫn thá»±c nghiệm) không?" #~ msgid "Use basic bandwidth limitation? (YES/NO). If in doubt, say YES." #~ msgstr "" #~ "Äặt giá»›i hạn băng thông cÆ¡ bản không? (YES/NO) Chưa chắc thì đặt YES (có)." #~ msgid "" #~ "Basic bandwidth limitation (YES) means simply that the bandwidth limits " #~ "specified apply to GNUnet and only to GNUnet. If set to YES, you simply " #~ "specify the maximum bandwidth (upstream and downstream) that GNUnet is " #~ "allowed to use and GNUnet will stick to those limitations. This is " #~ "useful if your overall bandwidth is so large that the limit is mostly " #~ "used to ensure that enough capacity is left for other applications. Even " #~ "if you want to dedicate your entire connection to GNUnet you should not " #~ "set the limits to values higher than what you have since GNUnet uses " #~ "those limits to determine for example the number of connections to " #~ "establish (and it would be inefficient if that computation yields a " #~ "number that is far too high). \n" #~ "\n" #~ "While basic bandwidth limitation is simple and always works, there are " #~ "some situations where it is not perfect. Suppose you are running another " #~ "application which performs a larger download. During that particular " #~ "time, it would be nice if GNUnet would throttle its bandwidth consumption " #~ "(automatically) and resume using more bandwidth after the download is " #~ "complete. This is obviously advanced magic since GNUnet will have to " #~ "monitor the behavior of other applications. Another scenario is a monthly " #~ "cap on bandwidth imposed by your ISP, which you would want to ensure is " #~ "obeyed. Here, you may want GNUnet to monitor the traffic from other " #~ "applications to ensure that the combined long-term traffic is within the " #~ "pre-set bounds. Note that you should probably not set the bounds tightly " #~ "since GNUnet may observe that the bounds are about to be broken but would " #~ "be unable to stop other applications from continuing to use bandwidth.\n" #~ "\n" #~ "If either of these two scenarios applies, set BASICLIMITING to NO. Then " #~ "set the bandwidth limits to the COMBINED amount of traffic that is " #~ "acceptable for both GNUnet and other applications. GNUnet will then " #~ "immediately throttle bandwidth consumption if the short-term average is " #~ "above the limit, and it will also try to ensure that the long-term " #~ "average is below the limit. Note however that using NO can have the " #~ "effect of GNUnet (almost) ceasing operations after other applications " #~ "perform high-volume downloads that are beyond the defined limits. GNUnet " #~ "would reduce consumption until the long-term limits are again within " #~ "bounds.\n" #~ "\n" #~ "NO only works on platforms where GNUnet can monitor the amount of traffic " #~ "that the local host puts out on the network. This is only implemented " #~ "for Linux and Win32. In order for the code to work, GNUnet needs to know " #~ "the specific network interface that is used for the external connection " #~ "(after all, the amount of traffic on loopback or on the LAN should never " #~ "be counted since it is irrelevant)." #~ msgstr "" #~ "Giá»›i hạn băng thông cÆ¡ bản (YES) có nghÄ©a đơn giản là má»—i giá»›i hạn băng " #~ "thông đưa ra chỉ áp dụng cho GNUnet. Nếu đặt thành YES (có) thì bạn đơn " #~ "giản chỉ ghi rõ băng thông tối Ä‘a (dòng ra và dòng vào) cho phép GNUnet " #~ "dùng, và GNUnet sẽ tuân theo những giá»›i hạn đó. Có ích nếu băng thông " #~ "toàn bá»™ lá»›n quá đến mức là giá»›i hạn thưá»ng dùng để đảm bảo đủ khả năng " #~ "còn lại cho các ứng dụng khác. Thậm chí nếu bạn muốn dành kết nối hoàn " #~ "toàn cho GNUnet, không nên đặt giá»›i hạn thành giá trị cao hÆ¡n khả năng, " #~ "vì GNUnet dùng giá»›i hạn đó để quyết định, ví dụ, số các kết nối nên thiết " #~ "lập (không có hiệu quả nếu phép tính có kết quả là quá lá»›n).\n" #~ "\n" #~ "Dù chức năng hạn chế băng thông cÆ¡ bản vẫn đơn giản và lúc nào cÅ©ng hoạt " #~ "động được, trong má»™t số trưá»ng hợp nào đó nó không phải hoàn toàn. Giả sá»­ " #~ "bạn Ä‘ang chạy má»™t ứng dụng khác mà thá»±c hiện má»™t công việc tải xuống lá»›n " #~ "hÆ¡n. Trong khi làm công việc đó, có ích nếu GNUnet giảm tiêu thụ băng " #~ "thông (má»™t cách tá»± động), cÅ©ng tăng lại má»™t khi công việc tải xuống đó đã " #~ "chạy xong. Chức năng này thá»±c sá»± phức tạp, vì GNUnet phải theo dõi ứng xá»­ " #~ "cá»§a các ứng dụng khác. Má»™t trưá»ng hợp khác là má»™t ngưỡng băng thông hàng " #~ "tháng được nhà cung cấp dịch vụ Internet (ISP) Ä‘iá»u khiển: bạn muốn đảm " #~ "bảo tuân theo nó. Trong trưá»ng hợp đó, bạn có thể muốn theo dõi tải cho " #~ "mạng từ các ứng dụng khác để đảm bảo rằng tổng số tải trá»ng lâu dài nằm " #~ "dưới ngưỡng định sẵn. Ghi chú rằng không nên đặt ngưỡng quá chặt chẽ vì " #~ "GNUnet có thể phát hiện ngưỡng sắp bị vượt quá nhưng không thể ngăn cản " #~ "ứng dụng khác tiếp tục chiếm băng thông.\n" #~ "\n" #~ "Nếu có má»™t cá»§a hai trưá»ng hợp này, hãy đặt BASICLIMITING thành NO " #~ "(không). Sau đó thì đặt giá»›i hạn băng thông thành Tá»”NG Sá» tải trá»ng thoả " #~ "đáng cho cả hai GNUnet và ứng dụng khác. GNUnet thì giảm ngay tiêu thụ " #~ "băng thông nếu trung bình ngắn kỳ hÆ¡n giá»›i hạn, nó cÅ©ng thá»­ đảm bảo rằng " #~ "trung bình lâu dài dưới giá»›i hạn. Tuy nhiên, ghi chú rằng việc đặt NO " #~ "(không) có kết quả có thể là GNUnet gần dừng hoạt động sau khi ứng dụng " #~ "khác chạy công việc lá»›n mà vượt quá giá»›i hạn đã xác định. Lúc đó, GNUnet " #~ "sẽ giảm tiêu thụ đến khi giá»›i hạn lâu dài lại nằm trong phạm vi đưa ra.\n" #~ "\n" #~ "Giá trị NO chỉ hoạt động được trên ná»n tảng thích hợp vá»›i GNUnet theo dõi " #~ "tải cho mạng được máy cục bá»™ gá»­i. Chức năng này chỉ được thá»±c hiện cho " #~ "Linux và Win32. Äể mà mã hoạt động được, GNUnet cần biết giao diện mạng " #~ "dứt khoát dùng cho kết nối bên ngoài (thôi, lượng tải trá»ng trên mạch ná»™i " #~ "bá»™ hay LAN không bao giá» nên được đếm vì nó không thích đáng). " #~ msgid "Network interface to monitor" #~ msgstr "Giao diện mạng cần theo dõi" #~ msgid "" #~ "For which interfaces should we do accounting? GNUnet will evaluate the " #~ "total traffic (not only the GNUnet related traffic) and adjust its " #~ "bandwidth usage accordingly. You can currently only specify a single " #~ "interface. GNUnet will also use this interface to determine the IP to " #~ "use. Typical values are eth0, ppp0, eth1, wlan0, etc. 'ifconfig' will " #~ "tell you what you have. Never use 'lo', that just won't work. Under " #~ "Windows, specify the index number reported by 'gnunet-win-tool -n'." #~ msgstr "" #~ "Có nên tính đến những giao diện nào? GNUnet sẽ định giá tổng số tải trá»ng " #~ "(không phải chỉ tải trá»ng liên quan đến GNUnet) và Ä‘iá»u chỉnh sá»­ dụng " #~ "băng thông má»™t cách thích hợp. Hiện thá»i ngưá»i dùng chỉ có thể ghi rõ má»™t " #~ "giao diện riêng lẻ. GNUnet sẽ cÅ©ng sá»­ dụng giao doện này để quyết định " #~ "địa chỉ IP cần dùng. Giá trị thưá»ng dùng: eth0, ppp0, eth1, wlan0, v.v. " #~ "Lệnh « ifconfig » sẽ hiển thị những giao diện sẵn sàng. Không bao giá» nên " #~ "dùng « lo » vì nó không hoạt động được. Dưới Windows, hãy ghi rõ số chỉ " #~ "mục trả lại bởi câu lệnh « gnunet-win-tool -n »." #~ msgid "Load management" #~ msgstr "Quản lý tải trá»ng" #~ msgid "Root node" #~ msgstr "Nút gốc" #~ msgid "Where should gnunet-clients write their logs?" #~ msgstr "Ứng dụng khách gnunet-clients nên ghi sổ theo dõi vào đâu?" #~ msgid "On which machine and port is gnunetd running (for clients)?" #~ msgstr "gnunetd Ä‘ang chạy trên máy và cổng nào (cho ứng dụng khách)?" #~ msgid "This is equivalent to the -H option. The format is IP:PORT." #~ msgstr "Äây tương đương vá»›i tùy chá»n « -H ». Äịnh dạng là « IP:Cá»”NG »." #~ msgid "This option is used when clients need to start gnunetd." #~ msgstr "Tùy chá»n này dùng khi ứng dụng khách cần khởi chạy gnunetd." #~ msgid "General options" #~ msgstr "Tùy chá»n chung" #~ msgid "Do not add metadata listing the creation time for inserted content" #~ msgstr "" #~ "Không nên thêm siêu dữ liệu mà ghi nhá»› giá» tạo cá»§a ná»™i dung được chèn vào" #~ msgid "" #~ "Which non-default extractors should GNUnet use for keyword extractors" #~ msgstr "" #~ "Äối vá»›i bá»™ trích khác từ khoá, GNUnet nên dùng những bá»™ trích khác mặc " #~ "định nào?" #~ msgid "" #~ "Specify which additional extractor libraries should be used. gnunet-" #~ "insert uses libextractor to extract keywords from files. libextractor can " #~ "be dynamically extended to handle additional file formats. If you want to " #~ "use more than the default set of extractors, specify additional extractor " #~ "libraries here. The format is [[-]LIBRARYNAME[:[-]LIBRARYNAME]*].\n" #~ "\n" #~ "The default is to use filenames and to break larger words at spaces (and " #~ "underscores, etc.). This should be just fine for most people. The '-' " #~ "before a library name indicates that this should be executed last and " #~ "makes only sense for the split-library." #~ msgstr "" #~ "Ghi rõ những thư viện trích bổ sung nào nên dùng. Tiến trình chèn gnunet-" #~ "insert sá»­ dụng libextractor để trích các từ khoá khá»i tập tin. " #~ "libextractor cÅ©ng có thể mở rá»™ng động để quản lý định dạng tập tin bổ " #~ "sung. Muốn sá»­ dụng bá»™ trích bên ngoài tập hợp mặc định thì ghi rõ ở đây " #~ "những thư viện trích bổ sung. Äịnh dạng là « [[-]tên_thư_viện[:" #~ "[-]tên_thư_viện]*] ».\n" #~ "\n" #~ "Mặc định là dùng tên tập tin, và ngắt từ lá»›n ở dấu cách, dấu gạch dưới v." #~ "v. Äây nên ổn cho phần lá»›n ngưá»i dùng. Dấu gạch nối « - » đằng trước má»™t " #~ "tên thư viện có ngụ ý nó nên được thá»±c hiện cuối cùng, thích hợp chỉ cho " #~ "split-library." #~ msgid "How many entries should the URI DB table have?" #~ msgstr "Bảng DB URI nên chứa bao nhiêu mục nhập?" #~ msgid "" #~ "GNUnet uses two bytes per entry on the disk. This database is used to " #~ "keep track of how a particular URI has been used in the past. For " #~ "example, GNUnet may remember that a particular URI has been found in a " #~ "search previously or corresponds to a file uploaded by the user. This " #~ "information can then be used by user-interfaces to filter URI lists, such " #~ "as search results. If the database is full, older entries will be " #~ "discarded. The default value should be sufficient without causing undue " #~ "disk utilization." #~ msgstr "" #~ "GNUnet dùng hai byte cho má»—i mục nhập trên đĩa. CÆ¡ sở dữ liệu này dùng để " #~ "theo dõi má»™t URI nào đó đã được sá»­ dụng như thế nào. Ví dụ, GNUnet có thể " #~ "nhá»› rằng má»™t URI nào đó đã được phát hiện bằng má»™t công việc tìm kiếm " #~ "trước, hay tương ứng vá»›i má»™t tập tin được ngưá»i dùng tải lên. Thông tin " #~ "này thì có thể được dùng bởi giao diện ngưá»i dùng để lá»c danh sách các " #~ "URI, như kết quả tìm kiếm. Nếu cÆ¡ sở dữ liệu bị đầy thì há»§y các mục nhập " #~ "cÅ©. Giá trị mặc định nên ổn mà không gây ra sá»­ dụng đĩa má»™t cách quá " #~ "chừng." #~ msgid "" #~ "Location of the file specifying metadata for the auto-share directory" #~ msgstr "Vị trí cá»§a tập tin ghi rõ siêu dữ liệu cho thư mục tá»± động chia sẻ" #~ msgid "" #~ "Location of the file with the PID of any running gnunet-auto-share daemon " #~ "process" #~ msgstr "" #~ "Vị trí cá»§a tập tin chứa PID cá»§a bất kỳ tiến trình ná»n gnunet-auto-share" #~ msgid "Location of the log file for gnunet-auto-share" #~ msgstr "Vị trí cá»§a tập tin theo dõi cho gnunet-auto-share" #~ msgid "Which plugins should be loaded by gnunet-gtk?" #~ msgstr "gnunet-gtk nên nạp những phần bổ sung nào?" #~ msgid "" #~ "Load the about plugin for the about dialog. The daemon plugin allows " #~ "starting and stopping of gnunetd and displays information about gnunetd. " #~ "The fs plugin provides the file-sharing functionality. The stats plugin " #~ "displays various statistics about gnunetd." #~ msgstr "" #~ "Nạp phần bổ sung about cho há»™p thoại giá»›i thiệu. Phần bổ sung daemon cho " #~ "phép khởi chạy và dừng chạy trình ná»n gnunetd, và hiển thị thông tin vá» " #~ "gnunetd. Phần bổ sung fs cung cấp chức năng chia sẻ tập tin. Phần bổ sung " #~ "stats hiển thị thống kê khác nhau vá» gnunetd." #~ msgid "How frequently (in milli-seconds) should the statistics update?" #~ msgstr "Thống kê có nên cập nhật thưá»ng xuyên cỡ nào (theo mili-giây)?" #~ msgid "" #~ "Each pixel in the stats dialog corresponds to the time interval specified " #~ "here." #~ msgstr "" #~ "Má»—i Ä‘iểm ảnh trong há»™p thoại thống kê thì tương ứng vá»›i khoảng thá»i gian " #~ "đưa ra ở đây." #~ msgid "Do not show thumbnail previews from meta-data in search results" #~ msgstr "" #~ "Không hiển thị ô xem thá»­ ảnh mẫu từ siêu dữ liệu trong kết quả tìm kiếm" #~ msgid "" #~ "This option is useful for people who maybe offended by some previews or " #~ "use gnunet-gtk at work and would like to avoid bad surprises." #~ msgstr "" #~ "Tùy chá»n này có ích cho ngưá»i dùng không thích má»™t số ô xem thá»­, hoặc sá»­ " #~ "dụng gnunet-gtk ở chá»— làm và muốn tránh sá»± ngạc nhiên xấu." #~ msgid "" #~ "This option is useful to eliminate files that the user already has from " #~ "the search. Naturally, enabling this option maybe confusing because some " #~ "obviously expected search results would no longer show up. This option " #~ "only works if the URI_DB_SIZE option under FS is not zero (since the URI " #~ "DB is used to determine which files the user is sharing)" #~ msgstr "" #~ "Tùy chá»n này có ích để loại ra việc tìm kiếm những tập tin đã có trên máy " #~ "đó. Tất nhiên, bật tùy chá»n có thể gây ra bối rối vì má»™t số kết quả tìm " #~ "kiếm mong đợi sẽ không được hiển thị. Tùy chá»n này chỉ hoạt động được nếu " #~ "tùy chá»n URI_DB_SIZE (kích cỡ cÆ¡ sở dữ liệu URI) dưới FS khác số không " #~ "(vì cÆ¡ sở dữ liệu URI được dùng để quyết định những tập tin được ngưá»i " #~ "dùng chia sẻ)" #~ msgid "To which directory should gnunet-gtk save downloads to?" #~ msgstr "gnunet-gtk nên lưu tập tin tải vá» vào thư mục nào?" #~ msgid "Options related to gnunet-gtk" #~ msgstr "Tùy chá»n liên quan đến gnunet-gtk" #~ msgid "Full pathname of GNUnet client HOME directory" #~ msgstr "Tên đưá»ng dẫn đầy đủ đến thư mục HOME khách GNUnet" #~ msgid "The directory for GNUnet files that belong to the user." #~ msgstr "Thư mục chứa những tập tin GNUnet mà thuá»™c vá» ngưá»i dùng." #~ msgid "`%s' failed at %s:%d with error `%s' after %llums\n" #~ msgstr "« %s » bị lá»—i tại %s:%d vá»›i lá»—i:« %s » đẳng sau %llu miligiây\n" #~ msgid "" #~ "Directory `%s' in directory `%s' does not match naming convention. " #~ "Removed.\n" #~ msgstr "" #~ "Thư mục « %s » trong thư mục « %s » không tùy theo quy ước đặt tên. Bị gỡ " #~ "bá».\n" gnunet-0.10.1/po/zh_CN.gmo0000644000175000017500000000675012320736475012156 00000000000000Þ•&L5|PQk-…³%Ñ-÷.% T&uœ¼KÜ%(.N#} ¡ÂÈ!Î=ð./3c;€7¼ ô!#+J+i•—A™ÛÝà…âh  (š à )á ( *4 _ '€ %¨ %Î 7ô ', /T #„ ¨ Ç Î Õ <î + $2 W As <µ ò ÿ  $& K 0j ›  7¡ Ù Ý ä  $"& #   ! %%s: illegal option -- %c %s: invalid option -- %c %s: option `%c%s' does not allow an argument %s: option `%s' is ambiguous %s: option `%s' requires an argument %s: option `--%s' does not allow an argument %s: option `-W %s' does not allow an argument %s: option `-W %s' is ambiguous %s: option requires an argument -- %c %s: unrecognized option `%c%s' %s: unrecognized option `--%s' Arguments mandatory for long options are also mandatory for short options. Cannot change user/group to `%s': %s Cannot obtain information about user `%s': %s Could not find IP of host `%s': %s Could not resolve `%s' (%s): %s DEBUGERRORExpected `%s' to be a directory! Failed to expand `$HOME': environment variable `HOME' not setINFOInitialization of plugin mechanism failed: %s! Invalid format for IP: `%s' Invalid network notation ('/%d' is not legal in IPv4 CIDR).Invalid network notation (does not end with ';': `%s') No such userUnable to initialize SQLite: %s. WARNINGWrong format `%s' for netmask Wrong format `%s' for network You must pass a number to the `%s' option. bhlibgcrypt has not the expected version (version %s is required). mmssProject-Id-Version: gnunet-0.8.1 Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org POT-Creation-Date: 2014-04-08 11:11+0200 PO-Revision-Date: 2011-07-09 12:12+0800 Last-Translator: Wylmer Wang Language-Team: Chinese (simplified) Language: zh_CN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit %sï¼šéžæ³•选项 -- %c %s:无效选项 -- %c %s:选项“%c%sâ€ä¸å…è®¸æœ‰å‚æ•° %s:选项“%sâ€æœ‰æ­§ä¹‰ %s:选项“%sâ€è¦æ±‚æœ‰ä¸€ä¸ªå‚æ•° %s:选项“--%sâ€ä¸å…è®¸æœ‰å‚æ•° %s:选项“-W %s†ä¸å…è®¸æœ‰å‚æ•° %s:选项“-W %sâ€æœ‰æ­§ä¹‰ %sï¼šé€‰é¡¹è¦æ±‚æœ‰ä¸€ä¸ªå‚æ•° -- %c %s:无法识别的选项“%c%s†%s:无法识别的选项“--%sâ€ é•¿é€‰é¡¹çš„å¿…é€‰å‚æ•°å¯¹çŸ­é€‰é¡¹ä¹Ÿæ˜¯å¿…选的。 无法更改用户/组为“%sâ€ï¼š%s æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s 找ä¸åˆ°ä¸»æœºâ€œ%sâ€çš„ IP:%s 无法解æžâ€œ%sâ€(%s):%s 调试错误“%sâ€åº”ä¸ºç›®å½•ï¼ æ‰©å±•â€œ$HOMEâ€å¤±è´¥ï¼šæ²¡æœ‰è®¾ç½®çŽ¯å¢ƒå˜é‡â€œHOMEâ€ä¿¡æ¯æ’件机构åˆå§‹åŒ–失败:%sï¼ IP æ ¼å¼æ— æ•ˆï¼šâ€œ%s†网络表示法无效(“/%d†在 IPv4 CIDR ä¸­æ˜¯éžæ³•çš„)。无效的网络表示法(没有以“;â€ç»“尾:“%sâ€) 无此用户无法åˆå§‹åŒ– SQLite:%s。 警告网络掩ç çš„æ ¼å¼â€œ%sâ€é”™è¯¯ 网络的格å¼â€œ%sâ€é”™è¯¯ 您必须å‘“%sâ€é€‰é¡¹ä¼ é€’一个数字。 bæ—¶libgcrypt 的版本ä¸ç¬¦åˆé¢„期(è¦æ±‚版本 %s)。 分毫秒秒gnunet-0.10.1/po/en@boldquot.header0000644000175000017500000000247111374167231014067 00000000000000# All this catalog "translates" are quotation characters. # The msgids must be ASCII and therefore cannot contain real quotation # characters, only substitutes like grave accent (0x60), apostrophe (0x27) # and double quote (0x22). These substitutes look strange; see # http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html # # This catalog translates grave accent (0x60) and apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019). # It also translates pairs of apostrophe (0x27) to # left single quotation mark (U+2018) and right single quotation mark (U+2019) # and pairs of quotation mark (0x22) to # left double quotation mark (U+201C) and right double quotation mark (U+201D). # # When output to an UTF-8 terminal, the quotation characters appear perfectly. # When output to an ISO-8859-1 terminal, the single quotation marks are # transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to # grave/acute accent (by libiconv), and the double quotation marks are # transliterated to 0x22. # When output to an ASCII terminal, the single quotation marks are # transliterated to apostrophes, and the double quotation marks are # transliterated to 0x22. # # This catalog furthermore displays the text between the quotation marks in # bold face, assuming the VT100/XTerm escape sequences. # gnunet-0.10.1/po/Makefile.in.in0000644000175000017500000003322112221077151013101 00000000000000# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2006 by Ulrich Drepper # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public # License but which still want to provide support for the GNU gettext # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. # # Origin: gettext-0.16 PACKAGE = @PACKAGE@ VERSION = @VERSION@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ SHELL = /bin/sh @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ localedir = @localedir@ gettextsrcdir = $(datadir)/gettext/po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ # We use $(mkdir_p). # In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as # "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions, # @install_sh@ does not start with $(SHELL), so we add it. # In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined # either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake # versions, $(mkinstalldirs) and $(install_sh) are unused. mkinstalldirs = $(SHELL) @install_sh@ -d install_sh = $(SHELL) @install_sh@ MKDIR_P = @MKDIR_P@ mkdir_p = @mkdir_p@ GMSGFMT_ = @GMSGFMT@ GMSGFMT_no = @GMSGFMT@ GMSGFMT_yes = @GMSGFMT_015@ GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT)) MSGFMT_ = @MSGFMT@ MSGFMT_no = @MSGFMT@ MSGFMT_yes = @MSGFMT_015@ MSGFMT = $(MSGFMT_$(USE_MSGCTXT)) XGETTEXT_ = @XGETTEXT@ XGETTEXT_no = @XGETTEXT@ XGETTEXT_yes = @XGETTEXT_015@ XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT)) MSGMERGE = msgmerge MSGMERGE_UPDATE = @MSGMERGE@ --update MSGINIT = msginit MSGCONV = msgconv MSGFILTER = msgfilter POFILES = @POFILES@ GMOFILES = @GMOFILES@ UPDATEPOFILES = @UPDATEPOFILES@ DUMMYPOFILES = @DUMMYPOFILES@ DISTFILES.common = Makefile.in.in remove-potcdate.sin \ $(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3) DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \ $(POFILES) $(GMOFILES) \ $(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3) POTFILES = \ CATALOGS = @CATALOGS@ # Makevars gets inserted here. (Don't remove this line!) .SUFFIXES: .SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update .po.mo: @echo "$(MSGFMT) -c -o $@ $<"; \ $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ .po.gmo: @lang=`echo $* | sed -e 's,.*/,,'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo .sin.sed: sed -e '/^#/d' $< > t-$@ mv t-$@ $@ all: all-@USE_NLS@ all-yes: stamp-po all-no: # $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no # internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because # we don't want to bother translators with empty POT files). We assume that # LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty. # In this case, stamp-po is a nop (i.e. a phony target). # stamp-po is a timestamp denoting the last time at which the CATALOGS have # been loosely updated. Its purpose is that when a developer or translator # checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS, # "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent # invocations of "make" will do nothing. This timestamp would not be necessary # if updating the $(CATALOGS) would always touch them; however, the rule for # $(POFILES) has been designed to not touch files that don't need to be # changed. stamp-po: $(srcdir)/$(DOMAIN).pot test ! -f $(srcdir)/$(DOMAIN).pot || \ test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES) @test ! -f $(srcdir)/$(DOMAIN).pot || { \ echo "touch stamp-po" && \ echo timestamp > stamp-poT && \ mv stamp-poT stamp-po; \ } # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. # This target rebuilds $(DOMAIN).pot; it is an expensive operation. # Note that $(DOMAIN).pot is not touched if it doesn't need to be changed. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \ msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \ else \ msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \ fi; \ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' \ --msgid-bugs-address="$$msgid_bugs_address" test ! -f $(DOMAIN).po || { \ if test -f $(srcdir)/$(DOMAIN).pot; then \ sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ else \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ else \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ } # This rule has no dependencies: we don't need to update $(DOMAIN).pot at # every "make" invocation, only create it when it is missing. # Only "make $(DOMAIN).pot-update" or "make dist" will force an update. $(srcdir)/$(DOMAIN).pot: $(MAKE) $(DOMAIN).pot-update # This target rebuilds a PO file if $(DOMAIN).pot has changed. # Note that a PO file is not touched if it doesn't need to be changed. $(POFILES): $(srcdir)/$(DOMAIN).pot @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ if test -f "$(srcdir)/$${lang}.po"; then \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot; \ else \ $(MAKE) $${lang}.po-create; \ fi install: install-exec install-data install-exec: install-data: install-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ for file in $(DISTFILES.common) Makevars.template; do \ $(INSTALL_DATA) $(srcdir)/$$file \ $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ for file in Makevars; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi install-data-no: all install-data-yes: all $(mkdir_p) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $(DESTDIR)$$dir; \ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ fi; \ done; \ done install-strip: install installdirs: installdirs-exec installdirs-data installdirs-exec: installdirs-data: installdirs-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \ else \ : ; \ fi installdirs-data-no: installdirs-data-yes: $(mkdir_p) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $(DESTDIR)$$dir; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ fi; \ done; \ done # Define this as empty until I found a useful application. installcheck: uninstall: uninstall-exec uninstall-data uninstall-exec: uninstall-data: uninstall-data-@USE_NLS@ if test "$(PACKAGE)" = "gettext-tools"; then \ for file in $(DISTFILES.common) Makevars.template; do \ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ done; \ else \ : ; \ fi uninstall-data-no: uninstall-data-yes: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ done; \ done check: all info dvi ps pdf html tags TAGS ctags CTAGS ID: mostlyclean: rm -f remove-potcdate.sed rm -f stamp-poT rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po rm -fr *.o clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES *.mo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f stamp-po $(GMOFILES) distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(MAKE) update-po @$(MAKE) dist2 # This is a separate target because 'update-po' must be executed before. dist2: stamp-po $(DISTFILES) dists="$(DISTFILES)"; \ if test "$(PACKAGE)" = "gettext-tools"; then \ dists="$$dists Makevars.template"; \ fi; \ if test -f $(srcdir)/$(DOMAIN).pot; then \ dists="$$dists $(DOMAIN).pot stamp-po"; \ fi; \ if test -f $(srcdir)/ChangeLog; then \ dists="$$dists ChangeLog"; \ fi; \ for i in 0 1 2 3 4 5 6 7 8 9; do \ if test -f $(srcdir)/ChangeLog.$$i; then \ dists="$$dists ChangeLog.$$i"; \ fi; \ done; \ if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \ for file in $$dists; do \ if test -f $$file; then \ cp -p $$file $(distdir) || exit 1; \ else \ cp -p $(srcdir)/$$file $(distdir) || exit 1; \ fi; \ done update-po: Makefile $(MAKE) $(DOMAIN).pot-update test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for creating PO files. .nop.po-create: @lang=`echo $@ | sed -e 's/\.po-create$$//'`; \ echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \ exit 1 # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: Makefile $(GMOFILES) @: Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@ cd $(top_builddir) \ && $(SHELL) ./config.status $(subdir)/$@.in po-directories force: # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/po/POTFILES.in0000644000175000017500000003174012320752065012214 00000000000000src/arm/arm_api.c src/arm/arm_monitor_api.c src/arm/gnunet-arm.c src/arm/gnunet-service-arm.c src/arm/mockup-service.c src/ats/ats_api_performance.c src/ats/ats_api_scheduling.c src/ats/gnunet-ats-solver-eval.c src/ats/gnunet-service-ats_addresses.c src/ats/gnunet-service-ats.c src/ats/gnunet-service-ats_normalization.c src/ats/gnunet-service-ats_performance.c src/ats/gnunet-service-ats_reservations.c src/ats/gnunet-service-ats_scheduling.c src/ats/plugin_ats_mlp.c src/ats/plugin_ats_proportional.c src/ats/plugin_ats_ril.c src/ats-tests/ats-testing.c src/ats-tests/ats-testing-experiment.c src/ats-tests/ats-testing-log.c src/ats-tests/ats-testing-preferences.c src/ats-tests/ats-testing-traffic.c src/ats-tests/gnunet-ats-sim.c src/ats-tests/gnunet-solver-eval.c src/ats-tool/gnunet-ats.c src/block/block.c src/block/plugin_block_template.c src/block/plugin_block_test.c src/consensus/consensus_api.c src/consensus/gnunet-consensus-profiler.c src/consensus/gnunet-service-consensus.c src/conversation/conversation_api.c src/conversation/conversation_api_call.c src/conversation/gnunet-conversation.c src/conversation/gnunet-conversation-test.c src/conversation/gnunet-helper-audio-playback.c src/conversation/gnunet-helper-audio-playback-gst.c src/conversation/gnunet-helper-audio-record.c src/conversation/gnunet-helper-audio-record-gst.c src/conversation/gnunet-service-conversation.c src/conversation/microphone.c src/conversation/plugin_gnsrecord_conversation.c src/conversation/speaker.c src/core/core_api.c src/core/core_api_iterate_peers.c src/core/gnunet-core.c src/core/gnunet-service-core.c src/core/gnunet-service-core_clients.c src/core/gnunet-service-core_kx.c src/core/gnunet-service-core_neighbours.c src/core/gnunet-service-core_sessions.c src/core/gnunet-service-core_typemap.c src/datacache/datacache.c src/datacache/plugin_datacache_heap.c src/datacache/plugin_datacache_postgres.c src/datacache/plugin_datacache_sqlite.c src/datacache/plugin_datacache_template.c src/datastore/datastore_api.c src/datastore/gnunet-datastore.c src/datastore/gnunet-service-datastore.c src/datastore/plugin_datastore_heap.c src/datastore/plugin_datastore_mysql.c src/datastore/plugin_datastore_postgres.c src/datastore/plugin_datastore_sqlite.c src/datastore/plugin_datastore_template.c src/dht/dht_api.c src/dht/dht_test_lib.c src/dht/gnunet-dht-get.c src/dht/gnunet-dht-monitor.c src/dht/gnunet-dht-put.c src/dht/gnunet-service-dht.c src/dht/gnunet-service-dht_clients.c src/dht/gnunet-service-dht_datacache.c src/dht/gnunet-service-dht_hello.c src/dht/gnunet-service-dht_neighbours.c src/dht/gnunet-service-dht_nse.c src/dht/gnunet-service-dht_routing.c src/dht/gnunet-service-xdht.c src/dht/gnunet-service-xdht_clients.c src/dht/gnunet-service-xdht_datacache.c src/dht/gnunet-service-xdht_hello.c src/dht/gnunet-service-xdht_neighbours.c src/dht/gnunet-service-xdht_nse.c src/dht/gnunet-service-xdht_routing.c src/dht/plugin_block_dht.c src/dns/dns_api.c src/dns/dnsparser.c src/dns/dnsstub.c src/dns/gnunet-dns-monitor.c src/dns/gnunet-dns-redirector.c src/dns/gnunet-helper-dns.c src/dns/gnunet-service-dns.c src/dns/plugin_block_dns.c src/dv/dv_api.c src/dv/gnunet-dv.c src/dv/gnunet-service-dv.c src/dv/plugin_transport_dv.c src/env/env.c src/exit/gnunet-daemon-exit.c src/exit/gnunet-helper-exit.c src/exit/gnunet-helper-exit-windows.c src/experimentation/gnunet-daemon-experimentation.c src/experimentation/gnunet-daemon-experimentation_capabilities.c src/experimentation/gnunet-daemon-experimentation_experiments.c src/experimentation/gnunet-daemon-experimentation_nodes.c src/experimentation/gnunet-daemon-experimentation_scheduler.c src/experimentation/gnunet-daemon-experimentation_storage.c src/fragmentation/defragmentation.c src/fragmentation/fragmentation.c src/fs/fs_api.c src/fs/fs_directory.c src/fs/fs_dirmetascan.c src/fs/fs_download.c src/fs/fs_file_information.c src/fs/fs_getopt.c src/fs/fs_list_indexed.c src/fs/fs_misc.c src/fs/fs_namespace.c src/fs/fs_publish.c src/fs/fs_publish_ksk.c src/fs/fs_publish_ublock.c src/fs/fs_search.c src/fs/fs_sharetree.c src/fs/fs_test_lib.c src/fs/fs_tree.c src/fs/fs_unindex.c src/fs/fs_uri.c src/fs/gnunet-auto-share.c src/fs/gnunet-daemon-fsprofiler.c src/fs/gnunet-directory.c src/fs/gnunet-download.c src/fs/gnunet-fs.c src/fs/gnunet-fs-profiler.c src/fs/gnunet-helper-fs-publish.c src/fs/gnunet-publish.c src/fs/gnunet-search.c src/fs/gnunet-service-fs.c src/fs/gnunet-service-fs_cp.c src/fs/gnunet-service-fs_indexing.c src/fs/gnunet-service-fs_lc.c src/fs/gnunet-service-fs_mesh_client.c src/fs/gnunet-service-fs_mesh_server.c src/fs/gnunet-service-fs_pe.c src/fs/gnunet-service-fs_pr.c src/fs/gnunet-service-fs_push.c src/fs/gnunet-service-fs_put.c src/fs/gnunet-unindex.c src/fs/plugin_block_fs.c src/gns/gns_api.c src/gns/gnunet-bcd.c src/gns/gnunet-dns2gns.c src/gns/gnunet-gns.c src/gns/gnunet-gns-helper-service-w32.c src/gns/gnunet-gns-import.c src/gns/gnunet-gns-proxy.c src/gns/gnunet-service-gns.c src/gns/gnunet-service-gns_interceptor.c src/gns/gnunet-service-gns_resolver.c src/gns/gnunet-service-gns_shorten.c src/gns/nss/nss_gns.c src/gns/nss/nss_gns_query.c src/gns/plugin_block_gns.c src/gns/plugin_gnsrecord_gns.c src/gnsrecord/gnsrecord.c src/gnsrecord/gnsrecord_crypto.c src/gnsrecord/gnsrecord_misc.c src/gnsrecord/gnsrecord_serialization.c src/gnsrecord/plugin_gnsrecord_dns.c src/gns/w32nsp.c src/gns/w32nsp-install.c src/gns/w32nsp-resolve.c src/gns/w32nsp-uninstall.c src/hello/address.c src/hello/gnunet-hello.c src/hello/hello.c src/hostlist/gnunet-daemon-hostlist.c src/hostlist/hostlist-client.c src/hostlist/hostlist-server.c src/identity/gnunet-identity.c src/identity/gnunet-service-identity.c src/identity/identity_api.c src/identity/identity_api_lookup.c src/mesh/gnunet-mesh.c src/mesh/gnunet-mesh-profiler.c src/mesh/gnunet-service-mesh.c src/mesh/gnunet-service-mesh_channel.c src/mesh/gnunet-service-mesh_connection.c src/mesh/gnunet-service-mesh_dht.c src/mesh/gnunet-service-mesh_hello.c src/mesh/gnunet-service-mesh_local.c src/mesh/gnunet-service-mesh_peer.c src/mesh/gnunet-service-mesh_tunnel.c src/mesh/mesh_api.c src/mesh/mesh_common.c src/mesh/mesh_path.c src/mesh/mesh_test_lib.c src/mesh/mesh_tunnel_tree.c src/multicast/gnunet-multicast.c src/multicast/gnunet-service-multicast.c src/multicast/multicast_api.c src/mysql/mysql.c src/namecache/gnunet-namecache.c src/namecache/gnunet-service-namecache.c src/namecache/namecache_api.c src/namecache/plugin_namecache_postgres.c src/namecache/plugin_namecache_sqlite.c src/namestore/gnunet-namestore.c src/namestore/gnunet-namestore-fcfsd.c src/namestore/gnunet-service-namestore.c src/namestore/namestore_api.c src/namestore/namestore_api_monitor.c src/namestore/plugin_namestore_postgres.c src/namestore/plugin_namestore_sqlite.c src/nat/gnunet-helper-nat-client.c src/nat/gnunet-helper-nat-client-windows.c src/nat/gnunet-helper-nat-server.c src/nat/gnunet-helper-nat-server-windows.c src/nat/gnunet-nat-server.c src/nat/nat_auto.c src/nat/nat.c src/nat/nat_mini.c src/nat/nat_test.c src/nse/gnunet-nse.c src/nse/gnunet-nse-profiler.c src/nse/gnunet-service-nse.c src/nse/nse_api.c src/peerinfo/gnunet-service-peerinfo.c src/peerinfo/peerinfo_api.c src/peerinfo/peerinfo_api_notify.c src/peerinfo-tool/gnunet-peerinfo.c src/peerinfo-tool/gnunet-peerinfo_plugins.c src/postgres/postgres.c src/psyc/gnunet-service-psyc.c src/psyc/psyc_api.c src/psyc/psyc_common.c src/psycstore/gnunet-service-psycstore.c src/psycstore/plugin_psycstore_sqlite.c src/psycstore/psycstore_api.c src/pt/gnunet-daemon-pt.c src/regex/gnunet-daemon-regexprofiler.c src/regex/gnunet-regex-profiler.c src/regex/gnunet-regex-simulation-profiler.c src/regex/gnunet-service-regex.c src/regex/perf-regex.c src/regex/plugin_block_regex.c src/regex/regex_api.c src/regex/regex_block_lib.c src/regex/regex_internal.c src/regex/regex_internal_dht.c src/regex/regex_test_graph.c src/regex/regex_test_lib.c src/regex/regex_test_random.c src/revocation/gnunet-revocation.c src/revocation/gnunet-service-revocation.c src/revocation/revocation_api.c src/scalarproduct/gnunet-scalarproduct.c src/scalarproduct/gnunet-service-scalarproduct.c src/scalarproduct/scalarproduct_api.c src/secretsharing/gnunet-secretsharing-profiler.c src/secretsharing/gnunet-service-secretsharing.c src/secretsharing/secretsharing_api.c src/secretsharing/secretsharing_common.c src/set/gnunet-service-set.c src/set/gnunet-service-set_intersection.c src/set/gnunet-service-set_union.c src/set/gnunet-set-ibf-profiler.c src/set/gnunet-set-profiler.c src/set/ibf.c src/set/set_api.c src/set/strata_estimator.c src/statistics/gnunet-service-statistics.c src/statistics/gnunet-statistics.c src/statistics/statistics_api.c src/template/gnunet-service-template.c src/template/gnunet-template.c src/testbed/generate-underlay-topology.c src/testbed/gnunet-daemon-latency-logger.c src/testbed/gnunet-daemon-testbed-blacklist.c src/testbed/gnunet-daemon-testbed-underlay.c src/testbed/gnunet-helper-testbed.c src/testbed/gnunet_mpi_test.c src/testbed/gnunet-service-test-barriers.c src/testbed/gnunet-service-testbed_barriers.c src/testbed/gnunet-service-testbed.c src/testbed/gnunet-service-testbed_cache.c src/testbed/gnunet-service-testbed_connectionpool.c src/testbed/gnunet-service-testbed_cpustatus.c src/testbed/gnunet-service-testbed_links.c src/testbed/gnunet-service-testbed-logger.c src/testbed/gnunet-service-testbed_meminfo.c src/testbed/gnunet-service-testbed_oc.c src/testbed/gnunet-service-testbed_peers.c src/testbed/gnunet_testbed_mpi_spawn.c src/testbed/gnunet-testbed-profiler.c src/testbed/testbed_api_barriers.c src/testbed/testbed_api.c src/testbed/testbed_api_hosts.c src/testbed/testbed_api_operations.c src/testbed/testbed_api_peers.c src/testbed/testbed_api_sd.c src/testbed/testbed_api_services.c src/testbed/testbed_api_statistics.c src/testbed/testbed_api_testbed.c src/testbed/testbed_api_test.c src/testbed/testbed_api_topology.c src/testbed/testbed_api_underlay.c src/testbed/testbed_logger_api.c src/testing/gnunet-testing.c src/testing/list-keys.c src/testing/testing.c src/topology/friends.c src/topology/gnunet-daemon-topology.c src/transport/gnunet-helper-transport-bluetooth.c src/transport/gnunet-helper-transport-wlan.c src/transport/gnunet-helper-transport-wlan-dummy.c src/transport/gnunet-service-transport_blacklist.c src/transport/gnunet-service-transport.c src/transport/gnunet-service-transport_clients.c src/transport/gnunet-service-transport_hello.c src/transport/gnunet-service-transport_manipulation.c src/transport/gnunet-service-transport_neighbours.c src/transport/gnunet-service-transport_plugins.c src/transport/gnunet-service-transport_validation.c src/transport/gnunet-transport.c src/transport/gnunet-transport-certificate-creation.c src/transport/gnunet-transport-wlan-receiver.c src/transport/gnunet-transport-wlan-sender.c src/transport/plugin_transport_bluetooth.c src/transport/plugin_transport_http_client.c src/transport/plugin_transport_http_common.c src/transport/plugin_transport_http_server.c src/transport/plugin_transport_smtp.c src/transport/plugin_transport_tcp.c src/transport/plugin_transport_template.c src/transport/plugin_transport_udp_broadcasting.c src/transport/plugin_transport_udp.c src/transport/plugin_transport_unix.c src/transport/plugin_transport_wlan.c src/transport/transport_api_address_to_string.c src/transport/transport_api_blacklist.c src/transport/transport_api.c src/transport/transport_api_monitoring.c src/transport/transport-testing.c src/tun/regex.c src/tun/tun.c src/util/bandwidth.c src/util/bio.c src/util/client.c src/util/common_allocation.c src/util/common_endian.c src/util/common_logging.c src/util/configuration.c src/util/connection.c src/util/container_bloomfilter.c src/util/container_heap.c src/util/container_meta_data.c src/util/container_multihashmap32.c src/util/container_multihashmap.c src/util/container_multipeermap.c src/util/container_slist.c src/util/crypto_crc.c src/util/crypto_ecc.c src/util/crypto_hash.c src/util/crypto_hkdf.c src/util/crypto_kdf.c src/util/crypto_mpi.c src/util/crypto_paillier.c src/util/crypto_random.c src/util/crypto_symmetric.c src/util/disk.c src/util/getopt.c src/util/getopt_helpers.c src/util/gnunet-config.c src/util/gnunet-config-diff.c src/util/gnunet-ecc.c src/util/gnunet-helper-w32-console.c src/util/gnunet-resolver.c src/util/gnunet-scrypt.c src/util/gnunet-service-resolver.c src/util/gnunet-uri.c src/util/helper.c src/util/load.c src/util/mq.c src/util/network.c src/util/os_installation.c src/util/os_network.c src/util/os_priority.c src/util/peer.c src/util/plugin.c src/util/program.c src/util/resolver_api.c src/util/scheduler.c src/util/server.c src/util/server_mst.c src/util/server_nc.c src/util/server_tc.c src/util/service.c src/util/signal.c src/util/speedup.c src/util/strings.c src/util/time.c src/util/w32cat.c src/util/win.c src/util/winproc.c src/vpn/gnunet-helper-vpn.c src/vpn/gnunet-helper-vpn-windows.c src/vpn/gnunet-service-vpn.c src/vpn/gnunet-vpn.c src/vpn/vpn_api.c src/include/gnunet_common.h src/include/gnunet_mq_lib.h src/include/gnunet_postgres_lib.h src/include/gnunet_time_lib.h src/scalarproduct/scalarproduct.h src/testbed/testbed_api.h src/testbed/testbed_api_operations.h gnunet-0.10.1/po/zh_CN.po0000644000175000017500000077736512320736475012033 00000000000000# Chinese simplified translation for GNUnet. # Copyright (C) 2011 Christian Grothoff # This file is distributed under the same license as the GNUnet package. # Wylmer Wang , 2011. # msgid "" msgstr "" "Project-Id-Version: gnunet-0.8.1\n" "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n" "POT-Creation-Date: 2014-04-08 11:11+0200\n" "PO-Revision-Date: 2011-07-09 12:12+0800\n" "Last-Translator: Wylmer Wang \n" "Language-Team: Chinese (simplified) \n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/arm/arm_api.c:337 msgid "Client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/arm_monitor_api.c:321 msgid "" "Monitoring client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/gnunet-arm.c:164 #, fuzzy, c-format msgid "Failed to remove configuration file %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/arm/gnunet-arm.c:170 #, c-format msgid "Failed to remove servicehome directory %s\n" msgstr "" #: src/arm/gnunet-arm.c:216 src/testbed/gnunet-service-testbed_peers.c:1013 msgid "Message was sent successfully" msgstr "" #: src/arm/gnunet-arm.c:218 #, fuzzy msgid "Misconfiguration (can not connect to the ARM service)" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/arm/gnunet-arm.c:220 src/testbed/gnunet-service-testbed_peers.c:1017 msgid "We disconnected from ARM before we could send a request" msgstr "" #: src/arm/gnunet-arm.c:222 src/testbed/gnunet-service-testbed_peers.c:1019 msgid "ARM API is busy" msgstr "" #: src/arm/gnunet-arm.c:224 msgid "Request does not fit into a message" msgstr "" #: src/arm/gnunet-arm.c:226 src/testbed/gnunet-service-testbed_peers.c:1023 msgid "Request timed out" msgstr "" #: src/arm/gnunet-arm.c:228 src/testbed/gnunet-service-testbed_peers.c:1025 #, fuzzy msgid "Unknown request status" msgstr "未知的用户“%sâ€\n" #: src/arm/gnunet-arm.c:244 src/testbed/gnunet-service-testbed_peers.c:1041 #, c-format msgid "%s is stopped" msgstr "" #: src/arm/gnunet-arm.c:246 src/testbed/gnunet-service-testbed_peers.c:1043 #, c-format msgid "%s is starting" msgstr "" #: src/arm/gnunet-arm.c:248 src/testbed/gnunet-service-testbed_peers.c:1045 #, c-format msgid "%s is stopping" msgstr "" #: src/arm/gnunet-arm.c:250 src/testbed/gnunet-service-testbed_peers.c:1047 #, c-format msgid "%s is starting already" msgstr "" #: src/arm/gnunet-arm.c:252 src/testbed/gnunet-service-testbed_peers.c:1049 #, c-format msgid "%s is stopping already" msgstr "" #: src/arm/gnunet-arm.c:254 src/testbed/gnunet-service-testbed_peers.c:1051 #, c-format msgid "%s is started already" msgstr "" #: src/arm/gnunet-arm.c:256 src/testbed/gnunet-service-testbed_peers.c:1053 #, c-format msgid "%s is stopped already" msgstr "" #: src/arm/gnunet-arm.c:258 src/testbed/gnunet-service-testbed_peers.c:1055 #, fuzzy, c-format msgid "%s service is not known to ARM" msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #: src/arm/gnunet-arm.c:260 src/testbed/gnunet-service-testbed_peers.c:1057 #, fuzzy, c-format msgid "%s service failed to start" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/arm/gnunet-arm.c:262 #, c-format msgid "%s service cannot be started because ARM is shutting down" msgstr "" #: src/arm/gnunet-arm.c:264 src/testbed/gnunet-service-testbed_peers.c:1061 #, c-format msgid "%.s Unknown result code." msgstr "" #: src/arm/gnunet-arm.c:297 msgid "Fatal error initializing ARM API.\n" msgstr "" #: src/arm/gnunet-arm.c:326 src/arm/gnunet-arm.c:335 #, fuzzy, c-format msgid "Failed to start the ARM service: %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/arm/gnunet-arm.c:369 #, fuzzy, c-format msgid "Failed to send a stop request to the ARM service: %s\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/arm/gnunet-arm.c:379 #, fuzzy, c-format msgid "Failed to stop the ARM service: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/arm/gnunet-arm.c:421 #, fuzzy, c-format msgid "Failed to send a request to start the `%s' service: %%s\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/arm/gnunet-arm.c:431 #, fuzzy, c-format msgid "Failed to start the `%s' service: %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/arm/gnunet-arm.c:468 #, fuzzy, c-format msgid "Failed to send a request to kill the `%s' service: %%s\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/arm/gnunet-arm.c:479 #, fuzzy, c-format msgid "Failed to kill the `%s' service: %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/arm/gnunet-arm.c:517 #, fuzzy, c-format msgid "Failed to request a list of services: %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/arm/gnunet-arm.c:525 #, fuzzy msgid "Error communicating with ARM. ARM not running?\n" msgstr "连接 %s:%u 出错。守护程åºåœ¨è¿è¡Œå—?\n" #: src/arm/gnunet-arm.c:530 msgid "Running services:\n" msgstr "" #: src/arm/gnunet-arm.c:612 #, c-format msgid "Now only monitoring, press CTRL-C to stop.\n" msgstr "" #: src/arm/gnunet-arm.c:643 #, c-format msgid "Stopped %s.\n" msgstr "" #: src/arm/gnunet-arm.c:646 #, fuzzy, c-format msgid "Starting %s...\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/arm/gnunet-arm.c:649 #, c-format msgid "Stopping %s...\n" msgstr "" #: src/arm/gnunet-arm.c:660 #, fuzzy, c-format msgid "Unknown status %u for service %s.\n" msgstr "未知的用户“%sâ€\n" #: src/arm/gnunet-arm.c:724 #, fuzzy msgid "stop all GNUnet services" msgstr "å¸è½½ GNUnet æœåŠ¡" #: src/arm/gnunet-arm.c:726 msgid "start a particular service" msgstr "" #: src/arm/gnunet-arm.c:728 msgid "stop a particular service" msgstr "" #: src/arm/gnunet-arm.c:730 #, fuzzy msgid "start all GNUnet default services" msgstr "å¸è½½ GNUnet æœåŠ¡" #: src/arm/gnunet-arm.c:733 #, fuzzy msgid "stop and start all GNUnet default services" msgstr "å¸è½½ GNUnet æœåŠ¡" #: src/arm/gnunet-arm.c:736 msgid "delete config file and directory on exit" msgstr "" #: src/arm/gnunet-arm.c:739 msgid "monitor ARM activities" msgstr "" #: src/arm/gnunet-arm.c:741 msgid "don't print status messages" msgstr "" #: src/arm/gnunet-arm.c:744 #, fuzzy msgid "timeout in MSECS milliseconds for completing current operation" msgstr "等待一次迭代完æˆçš„æ—¶é—´(毫秒)" #: src/arm/gnunet-arm.c:746 msgid "list currently running services" msgstr "" #: src/arm/gnunet-arm.c:748 msgid "don't let gnunet-service-arm inherit standard output" msgstr "" #: src/arm/gnunet-arm.c:750 msgid "don't let gnunet-service-arm inherit standard error" msgstr "" #: src/arm/gnunet-arm.c:761 msgid "Control services and the Automated Restart Manager (ARM)" msgstr "" #: src/arm/gnunet-service-arm.c:266 msgid "Could not send status result to client\n" msgstr "" #: src/arm/gnunet-service-arm.c:302 #, fuzzy msgid "Could not send list result to client\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/arm/gnunet-service-arm.c:529 #, fuzzy, c-format msgid "Failed to start service `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/arm/gnunet-service-arm.c:540 #, c-format msgid "Starting service `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:639 #, fuzzy, c-format msgid "Unable to create socket for service `%s': %s\n" msgstr "无法创建用户账户:" #: src/arm/gnunet-service-arm.c:661 #, c-format msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:695 #, c-format msgid "ARM now monitors connections to service `%s' at `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:831 #, c-format msgid "Preparing to stop `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:1100 #, c-format msgid "Restarting service `%s'.\n" msgstr "" #: src/arm/gnunet-service-arm.c:1193 msgid "exit" msgstr "" #: src/arm/gnunet-service-arm.c:1198 msgid "signal" msgstr "" #: src/arm/gnunet-service-arm.c:1203 #, fuzzy msgid "unknown" msgstr "未知错误" #: src/arm/gnunet-service-arm.c:1209 #, fuzzy, c-format msgid "Service `%s' took %s to terminate\n" msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #: src/arm/gnunet-service-arm.c:1231 #, c-format msgid "Service `%s' terminated normally, will restart at any time\n" msgstr "" #: src/arm/gnunet-service-arm.c:1246 #, c-format msgid "Service `%s' terminated with status %s/%d, will restart in %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:1500 #, fuzzy, c-format msgid "Starting default services `%s'\n" msgstr "å¸è½½ GNUnet æœåŠ¡" #: src/arm/gnunet-service-arm.c:1511 #, c-format msgid "Default service `%s' not configured correctly!\n" msgstr "" #: src/arm/gnunet-service-arm.c:1524 msgid "" "No default services configured, GNUnet will not really start right now.\n" msgstr "" #: src/arm/mockup-service.c:41 msgid "Initiating shutdown as requested by client.\n" msgstr "" #: src/ats/ats_api_performance.c:468 #, c-format msgid "Received %s message\n" msgstr "" #: src/ats/ats_api_performance.c:511 #, c-format msgid "Received last message for %s \n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2199 src/ats/gnunet-ats-solver-eval.c:2233 #: src/ats/gnunet-service-ats_addresses.c:1980 #: src/ats/gnunet-service-ats_addresses.c:2024 #, c-format msgid "" "Could not load quota for network `%s': `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2205 #: src/ats/gnunet-service-ats_addresses.c:1987 #, c-format msgid "Outbound quota configure for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2212 #: src/ats/gnunet-service-ats_addresses.c:1995 #, c-format msgid "" "No outbound quota configured for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2239 #: src/ats/gnunet-service-ats_addresses.c:2031 #, c-format msgid "Inbound quota configured for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2246 #: src/ats/gnunet-service-ats_addresses.c:2039 #, c-format msgid "" "No outbound quota configure for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2671 #: src/ats-tests/gnunet-solver-eval.c:919 msgid "solver to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2674 src/ats/gnunet-ats-solver-eval.c:2677 #: src/ats-tests/gnunet-solver-eval.c:922 #: src/ats-tests/gnunet-solver-eval.c:925 msgid "experiment to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2680 #, fuzzy msgid "print logging" msgstr "未知的命令“%sâ€ã€‚\n" #: src/ats/gnunet-service-ats_addresses.c:2217 #, c-format msgid "Initializing solver `%s '`%s'\n" msgstr "" #: src/ats/gnunet-service-ats_addresses.c:2220 #, fuzzy, c-format msgid "Failed to initialize solver `%s'!\n" msgstr "无法åˆå§‹åŒ– SQLite:%s。\n" #: src/ats/gnunet-service-ats_addresses.c:2243 #, fuzzy msgid "Failed to initialize solver!\n" msgstr "无法åˆå§‹åŒ– SQLite:%s。\n" #: src/ats/plugin_ats_mlp.c:892 msgid "Problem size too large, cannot allocate memory!\n" msgstr "" #: src/ats/plugin_ats_mlp.c:1329 #, c-format msgid "Adding address for peer `%s' multiple times\n" msgstr "" #: src/ats/plugin_ats_mlp.c:1376 #, c-format msgid "Updating address property `%s' for peer `%s' %p not added before\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2122 #, c-format msgid "" "Adjusting inconsistent outbound quota configuration for network `%s', is " "%llu must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2131 #, c-format msgid "" "Adjusting inconsistent inbound quota configuration for network `%s', is %llu " "must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2142 #, c-format msgid "" "Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2150 #, c-format msgid "" "Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2161 #, c-format msgid "Using default quota configuration for network `%s' (in/out) %llu/%llu\n" msgstr "" #: src/ats/plugin_ats_proportional.c:1511 #, fuzzy, c-format msgid "Invalid network type `%u' `%s': Disconnect!\n" msgstr "找ä¸åˆ°ä¸»æœºâ€œ%sâ€çš„ IP:%s\n" #: src/ats-tests/ats-testing.c:72 msgid "Benchmarking done\n" msgstr "" #: src/ats-tests/ats-testing.c:105 #, fuzzy, c-format msgid "Failed to connect peer 0 and %u\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/ats-tests/ats-testing.c:413 #, c-format msgid "Connected master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:419 #, fuzzy, c-format msgid "Failed to connect master peer [%u] with slave [%u]\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/ats-tests/ats-testing.c:450 msgid "Connecting peers on CORE level\n" msgstr "" #: src/ats-tests/ats-testing.c:461 #, c-format msgid "Connecting master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:470 #, fuzzy, c-format msgid "Could not connect master [%u] and slave [%u]\n" msgstr "无法连接到 %s:%u:%s\n" #: src/ats-tests/ats-testing.c:490 src/ats-tests/ats-testing.c:671 #, fuzzy msgid "Initialization failed, shutdown\n" msgstr "æ’件机构åˆå§‹åŒ–失败:%sï¼\n" #: src/ats-tests/ats-testing-log.c:842 msgid "Stop logging\n" msgstr "" #: src/ats-tests/ats-testing-log.c:893 #, fuzzy, c-format msgid "Start logging `%s'\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/ats-tests/gnunet-ats-sim.c:86 #, c-format msgid "" "Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. " "= %u KiB/s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:169 #, c-format msgid "%u address resolutions had a timeout\n" msgstr "" #: src/ats-tool/gnunet-ats.c:171 #, c-format msgid "ATS returned results for %u addresses\n" msgstr "" #: src/ats-tool/gnunet-ats.c:232 #, c-format msgid "" "Peer `%s' plugin `%s', address `%s', `%s' bw out: %u Bytes/s, bw in %u Bytes/" "s, %s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:413 #, c-format msgid "Quota for network `%11s' (in/out): %10s / %10s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:433 src/core/gnunet-core.c:163 #: src/namestore/gnunet-namestore.c:550 src/transport/gnunet-transport.c:1246 #, fuzzy, c-format msgid "Service `%s' is not running\n" msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #: src/ats-tool/gnunet-ats.c:445 src/transport/gnunet-transport.c:1255 #, fuzzy, c-format msgid "Failed to parse peer identity `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/ats-tool/gnunet-ats.c:454 #, c-format msgid "Please select one operation : %s or %s or %s or %s or %s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:470 src/ats-tool/gnunet-ats.c:489 #: src/ats-tool/gnunet-ats.c:506 src/ats-tool/gnunet-ats.c:543 #, fuzzy, c-format msgid "Cannot connect to ATS service, exiting...\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/ats-tool/gnunet-ats.c:478 src/ats-tool/gnunet-ats.c:495 #, fuzzy, c-format msgid "Cannot issue request to ATS service, exiting...\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/ats-tool/gnunet-ats.c:515 #, fuzzy, c-format msgid "No preference type given!\n" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/ats-tool/gnunet-ats.c:520 #, c-format msgid "No peer given!\n" msgstr "" #: src/ats-tool/gnunet-ats.c:536 msgid "Valid type required\n" msgstr "" #: src/ats-tool/gnunet-ats.c:594 msgid "get list of active addresses currently used" msgstr "" #: src/ats-tool/gnunet-ats.c:596 msgid "get list of all active addresses" msgstr "" #: src/ats-tool/gnunet-ats.c:599 #, fuzzy msgid "do not resolve IP addresses to hostnames" msgstr "GNUnet 现在使用 IP åœ°å€ %s。\n" #: src/ats-tool/gnunet-ats.c:601 msgid "monitor mode" msgstr "" #: src/ats-tool/gnunet-ats.c:603 #, fuzzy msgid "set preference for the given peer" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/ats-tool/gnunet-ats.c:605 msgid "print all configured quotas" msgstr "" #: src/ats-tool/gnunet-ats.c:607 msgid "peer id" msgstr "" #: src/ats-tool/gnunet-ats.c:610 msgid "preference type to set: latency | bandwidth" msgstr "" #: src/ats-tool/gnunet-ats.c:612 msgid "preference value" msgstr "" #: src/ats-tool/gnunet-ats.c:615 msgid "verbose output (include ATS address properties)" msgstr "" #: src/ats-tool/gnunet-ats.c:622 #, fuzzy msgid "Print information about ATS state" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/consensus/gnunet-consensus-profiler.c:437 #: src/secretsharing/gnunet-secretsharing-profiler.c:535 #, fuzzy msgid "number of peers in consensus" msgstr "迭代次数" #: src/consensus/gnunet-consensus-profiler.c:440 msgid "how many peers receive one value?" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:443 #: src/set/gnunet-set-profiler.c:286 src/set/gnunet-set-profiler.c:289 #: src/set/gnunet-set-profiler.c:292 #, fuzzy msgid "number of values" msgstr "迭代次数" #: src/consensus/gnunet-consensus-profiler.c:446 msgid "consensus timeout" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:449 msgid "delay until consensus starts" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:452 #: src/secretsharing/gnunet-secretsharing-profiler.c:550 msgid "be more verbose (print received values)" msgstr "" #: src/conversation/conversation_api.c:557 #: src/conversation/conversation_api_call.c:470 msgid "Connection to conversation service lost, trying to reconnect\n" msgstr "" #: src/conversation/gnunet-conversation.c:264 #, c-format msgid "Incoming call from `%s'. Please /accept #%u or /cancel %u the call.\n" msgstr "" #: src/conversation/gnunet-conversation.c:286 #, c-format msgid "Call from `%s' terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:319 #, c-format msgid "Call from `%s' suspended by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:324 #, c-format msgid "Call from `%s' resumed by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:342 #, c-format msgid "Ego `%s' no longer available, phone is now down.\n" msgstr "" #: src/conversation/gnunet-conversation.c:356 #, fuzzy msgid "Failed to setup phone (internal error)\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/conversation/gnunet-conversation.c:368 #, c-format msgid "" "Phone active on line %u. Type `/help' for a list of available commands\n" msgstr "" #: src/conversation/gnunet-conversation.c:390 #, c-format msgid "Resolved address of `%s'. Now ringing other party.\n" msgstr "" #: src/conversation/gnunet-conversation.c:397 #, fuzzy, c-format msgid "Connection established to `%s'\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/conversation/gnunet-conversation.c:404 #, fuzzy, c-format msgid "Failed to resolve `%s'\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/conversation/gnunet-conversation.c:411 msgid "Call terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:417 #, c-format msgid "Connection to `%s' suspended (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:423 #, c-format msgid "Connection to `%s' resumed (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:428 msgid "Error with the call, restarting it\n" msgstr "" #: src/conversation/gnunet-conversation.c:495 #, fuzzy, c-format msgid "Unknown command `%s'\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/conversation/gnunet-conversation.c:511 #: src/conversation/gnunet-conversation.c:525 #, c-format msgid "Ego `%s' not available\n" msgstr "" #: src/conversation/gnunet-conversation.c:518 #: src/conversation/gnunet-conversation.c:575 msgid "You are calling someone else already, hang up first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:533 #: src/conversation/gnunet-conversation.c:588 #, c-format msgid "You are answering call from `%s', hang up or suspend that call first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:544 msgid "Call recipient missing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:599 msgid "There is no incoming call to accept here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:616 #, c-format msgid "There is no incoming call `%s' to accept right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:647 msgid "We currently do not have an address.\n" msgstr "" #: src/conversation/gnunet-conversation.c:670 #, c-format msgid "We are currently trying to locate the private key for the ego `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:675 #, c-format msgid "We are listening for incoming calls for ego `%s' on line %u.\n" msgstr "" #: src/conversation/gnunet-conversation.c:681 #: src/conversation/gnunet-conversation.c:705 #, c-format msgid "You are having a conversation with `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:686 msgid "" "We had an internal error setting up our phone line. You can still make " "calls.\n" msgstr "" #: src/conversation/gnunet-conversation.c:695 #, fuzzy, c-format msgid "We are trying to find the network address to call `%s'.\n" msgstr "GNUnet 现在使用 IP åœ°å€ %s。\n" #: src/conversation/gnunet-conversation.c:700 #, c-format msgid "We are calling `%s', his phone should be ringing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:719 msgid "Calls waiting:\n" msgstr "" #: src/conversation/gnunet-conversation.c:725 #, fuzzy, c-format msgid "#%u: `%s'\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/conversation/gnunet-conversation.c:753 #: src/conversation/gnunet-conversation.c:768 msgid "There is no call that could be suspended right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:801 #: src/conversation/gnunet-conversation.c:817 msgid "There is no call that could be resumed right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:824 #, c-format msgid "Already talking with `%s', cannot resume a call right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:833 msgid "There is no incoming call to resume here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:850 #, c-format msgid "There is no incoming call `%s' to resume right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:885 msgid "There is no call that could be cancelled right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:893 msgid "There is no incoming call to refuse here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:910 #, c-format msgid "There is no incoming call `%s' to refuse right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:937 msgid "Use `/address' to find out which address this phone should have in GNS" msgstr "" #: src/conversation/gnunet-conversation.c:939 msgid "Use `/call USER.gnu' to call USER" msgstr "" #: src/conversation/gnunet-conversation.c:941 msgid "Use `/accept #NUM' to accept incoming call #NUM" msgstr "" #: src/conversation/gnunet-conversation.c:943 msgid "Use `/suspend' to suspend the active call" msgstr "" #: src/conversation/gnunet-conversation.c:945 msgid "" "Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming " "calls, no argument is needed to resume the current outgoing call." msgstr "" #: src/conversation/gnunet-conversation.c:947 msgid "Use `/cancel' to reject or terminate a call" msgstr "" #: src/conversation/gnunet-conversation.c:949 msgid "Use `/status' to print status information" msgstr "" #: src/conversation/gnunet-conversation.c:951 msgid "Use `/quit' to terminate gnunet-conversation" msgstr "" #: src/conversation/gnunet-conversation.c:953 msgid "Use `/help command' to get help for a specific command" msgstr "" #: src/conversation/gnunet-conversation.c:1151 #, fuzzy, c-format msgid "Name of our ego changed to `%s'\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/conversation/gnunet-conversation.c:1164 #, c-format msgid "Our ego `%s' was deleted!\n" msgstr "" #: src/conversation/gnunet-conversation.c:1199 #, fuzzy msgid "You must specify the NAME of an ego to use\n" msgstr "您必须指定一个昵称\n" #: src/conversation/gnunet-conversation.c:1223 #, fuzzy msgid "Failed to start gnunet-helper-w32-console\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/conversation/gnunet-conversation.c:1249 msgid "sets the NAME of the ego to use for the phone (and name resolution)" msgstr "" #: src/conversation/gnunet-conversation.c:1252 msgid "sets the LINE to use for the phone" msgstr "" #: src/conversation/gnunet-conversation.c:1276 msgid "Enables having a conversation with other GNUnet users." msgstr "" #: src/conversation/gnunet-conversation-test.c:121 #, c-format msgid "" "\n" "End of transmission. Have a GNU day.\n" msgstr "" #: src/conversation/gnunet-conversation-test.c:149 #, c-format msgid "" "\n" "We are now playing your recording back. If you can hear it, your audio " "settings are working..." msgstr "" #: src/conversation/gnunet-conversation-test.c:215 #, c-format msgid "" "We will now be recording you for %s. After that time, the recording will be " "played back to you..." msgstr "" #: src/conversation/gnunet-conversation-test.c:248 #: src/multicast/gnunet-multicast.c:70 src/revocation/gnunet-revocation.c:522 #: src/template/gnunet-template.c:70 msgid "help text" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:305 #, fuzzy, c-format msgid "pa_stream_write() failed: %s\n" msgstr "“%sâ€è¯´ï¼š%s\n" #: src/conversation/gnunet-helper-audio-playback.c:587 msgid "gnunet-helper-audio-playback - Got signal, exiting\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:612 #: src/conversation/gnunet-helper-audio-record.c:545 msgid "Connection established.\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:617 #: src/conversation/gnunet-helper-audio-record.c:550 #, fuzzy, c-format msgid "pa_stream_new() failed: %s\n" msgstr "“%sâ€è¯´ï¼š%s\n" #: src/conversation/gnunet-helper-audio-playback.c:631 #, c-format msgid "pa_stream_connect_playback() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:644 #: src/conversation/gnunet-helper-audio-record.c:576 #, fuzzy, c-format msgid "Connection failure: %s\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/conversation/gnunet-helper-audio-playback.c:665 #: src/conversation/gnunet-helper-audio-record.c:599 msgid "Wrong Spec\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:671 #: src/conversation/gnunet-helper-audio-record.c:605 msgid "pa_mainloop_new() failed.\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:685 #: src/conversation/gnunet-helper-audio-record.c:620 msgid "pa_context_new() failed.\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:692 #: src/conversation/gnunet-helper-audio-record.c:626 #, fuzzy, c-format msgid "pa_context_connect() failed: %s\n" msgstr "“%sâ€è¯´ï¼š%s\n" #: src/conversation/gnunet-helper-audio-playback.c:698 #: src/conversation/gnunet-helper-audio-record.c:632 msgid "pa_mainloop_run() failed.\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:768 #, c-format msgid "Read error from STDIN: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback-gst.c:325 #, c-format msgid "Read error from STDIN: %d %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:344 #, fuzzy, c-format msgid "opus_encode_float() failed: %s. Aborting\n" msgstr "“%sâ€è¯´ï¼š%s\n" #: src/conversation/gnunet-helper-audio-record.c:420 #, fuzzy, c-format msgid "pa_stream_peek() failed: %s\n" msgstr "“%sâ€è¯´ï¼š%s\n" #: src/conversation/gnunet-helper-audio-record.c:458 msgid "Got signal, exiting.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:483 #, fuzzy msgid "Stream successfully created.\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/conversation/gnunet-helper-audio-record.c:488 #, fuzzy, c-format msgid "pa_stream_get_buffer_attr() failed: %s\n" msgstr "“%sâ€è¯´ï¼š%s\n" #: src/conversation/gnunet-helper-audio-record.c:496 #, c-format msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:500 #, c-format msgid "Using sample spec '%s', channel map '%s'.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:507 #, fuzzy, c-format msgid "Connected to device %s (%u, %ssuspended).\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/conversation/gnunet-helper-audio-record.c:516 #, c-format msgid "Stream error: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:563 #, fuzzy, c-format msgid "pa_stream_connect_record() failed: %s\n" msgstr "“%sâ€è¯´ï¼š%s\n" #: src/conversation/gnunet-helper-audio-record.c:676 #, fuzzy msgid "ogg_stream_init() failed.\n" msgstr "“%sâ€è¯´ï¼š%s\n" #: src/conversation/gnunet-helper-audio-record.c:721 #, fuzzy, c-format msgid "Failed to allocate %d bytes for second packet\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/conversation/gnunet-service-conversation.c:841 msgid "Mesh audio channel not ready; audio data dropped\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:932 #, c-format msgid "" "No available phone for incoming call on line %u, sending HANG_UP signal\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:1338 #, fuzzy, c-format msgid "Received incoming channel on port %u\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/conversation/microphone.c:121 #, fuzzy msgid "Could not start record audio helper\n" msgstr "找ä¸åˆ°ä¸»æœºâ€œ%sâ€çš„ IP:%s\n" #: src/conversation/plugin_gnsrecord_conversation.c:116 #, fuzzy, c-format msgid "Unable to parse PHONE record `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/conversation/speaker.c:75 msgid "Could not start playback audio helper.\n" msgstr "" #: src/core/core_api.c:767 msgid "Client was disconnected from core service, trying to reconnect.\n" msgstr "" #: src/core/gnunet-core.c:80 #, c-format msgid "Peer `%s'\n" msgstr "" #: src/core/gnunet-core.c:110 src/core/gnunet-core.c:138 #: src/transport/gnunet-transport.c:910 src/transport/gnunet-transport.c:930 #, c-format msgid "%24s: %-17s %4s (%u connections in total)\n" msgstr "" #: src/core/gnunet-core.c:112 src/transport/gnunet-transport.c:911 #, fuzzy msgid "Connected to" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/core/gnunet-core.c:140 src/transport/gnunet-transport.c:931 #, fuzzy msgid "Disconnected from" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/core/gnunet-core.c:211 src/peerinfo-tool/gnunet-peerinfo.c:694 #, fuzzy, c-format msgid "Invalid command line argument `%s'\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/core/gnunet-core.c:233 src/transport/gnunet-transport.c:1486 msgid "provide information about all current connections (continuously)" msgstr "" #: src/core/gnunet-core.c:244 msgid "Print information about connected peers." msgstr "" #: src/core/gnunet-service-core.c:105 #, fuzzy msgid "Core service is lacking HOSTKEY configuration setting. Exiting.\n" msgstr "ç«‹å³ä¿å­˜é…置?" #: src/core/gnunet-service-core.c:126 #, c-format msgid "Core service of `%4s' ready.\n" msgstr "" #: src/core/gnunet-service-core_clients.c:370 msgid "# send requests dropped (disconnected)" msgstr "" #: src/core/gnunet-service-core_clients.c:480 msgid "# messages discarded (session disconnected)" msgstr "" #: src/core/gnunet-service-core_clients.c:526 #, c-format msgid "# bytes of messages of type %u received" msgstr "" #: src/core/gnunet-service-core_kx.c:535 msgid "# bytes encrypted" msgstr "" #: src/core/gnunet-service-core_kx.c:586 msgid "# bytes decrypted" msgstr "" #: src/core/gnunet-service-core_kx.c:673 msgid "# key exchanges initiated" msgstr "" #: src/core/gnunet-service-core_kx.c:713 msgid "# key exchanges stopped" msgstr "" #: src/core/gnunet-service-core_kx.c:810 msgid "# old ephemeral keys ignored" msgstr "" #: src/core/gnunet-service-core_kx.c:816 msgid "# ephemeral keys received" msgstr "" #: src/core/gnunet-service-core_kx.c:850 #, c-format msgid "" "Ephemeral key message from peer `%s' rejected as its validity range does not " "match our system time (%llu not in [%llu,%llu]).\n" msgstr "" #: src/core/gnunet-service-core_kx.c:861 msgid "# EPHEMERAL_KEY messages received" msgstr "" #: src/core/gnunet-service-core_kx.c:951 #: src/transport/gnunet-service-transport_validation.c:1016 msgid "# PING messages received" msgstr "" #: src/core/gnunet-service-core_kx.c:959 msgid "# PING messages dropped (out of order)" msgstr "" #: src/core/gnunet-service-core_kx.c:986 #, c-format msgid "" "Received PING from `%s' for different identity: I am `%s', PONG identity: `" "%s'\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1003 msgid "# PONG messages created" msgstr "" #: src/core/gnunet-service-core_kx.c:1029 msgid "# sessions terminated by timeout" msgstr "" #: src/core/gnunet-service-core_kx.c:1039 msgid "# keepalive messages sent" msgstr "" #: src/core/gnunet-service-core_kx.c:1096 #: src/transport/gnunet-service-transport_validation.c:1328 msgid "# PONG messages received" msgstr "" #: src/core/gnunet-service-core_kx.c:1102 msgid "# PONG messages dropped (connection down)" msgstr "" #: src/core/gnunet-service-core_kx.c:1107 msgid "# PONG messages dropped (out of order)" msgstr "" #: src/core/gnunet-service-core_kx.c:1137 msgid "# PONG messages decrypted" msgstr "" #: src/core/gnunet-service-core_kx.c:1171 msgid "# session keys confirmed via PONG" msgstr "" #: src/core/gnunet-service-core_kx.c:1181 msgid "# timeouts prevented via PONG" msgstr "" #: src/core/gnunet-service-core_kx.c:1188 msgid "# rekey operations confirmed via PONG" msgstr "" #: src/core/gnunet-service-core_kx.c:1328 msgid "# DATA message dropped (out of order)" msgstr "" #: src/core/gnunet-service-core_kx.c:1335 #, c-format msgid "" "Session to peer `%s' went down due to key expiration (should not happen)\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1338 msgid "# sessions terminated by key expiration" msgstr "" #: src/core/gnunet-service-core_kx.c:1383 #: src/core/gnunet-service-core_kx.c:1408 msgid "# bytes dropped (duplicates)" msgstr "" #: src/core/gnunet-service-core_kx.c:1395 msgid "# bytes dropped (out of sequence)" msgstr "" #: src/core/gnunet-service-core_kx.c:1437 msgid "# bytes dropped (ancient message)" msgstr "" #: src/core/gnunet-service-core_kx.c:1445 msgid "# bytes of payload decrypted" msgstr "" #: src/core/gnunet-service-core_kx.c:1480 msgid "# PAYLOAD dropped (out of order)" msgstr "" #: src/core/gnunet-service-core_neighbours.c:168 msgid "# sessions terminated by transport disconnect" msgstr "" #: src/core/gnunet-service-core_neighbours.c:184 #: src/core/gnunet-service-core_neighbours.c:335 msgid "# neighbour entries allocated" msgstr "" #: src/core/gnunet-service-core_neighbours.c:252 msgid "# encrypted bytes given to transport" msgstr "" #: src/core/gnunet-service-core_neighbours.c:418 #, c-format msgid "Unsupported message of type %u (%u bytes) received from peer `%s'\n" msgstr "" #: src/core/gnunet-service-core_sessions.c:216 #: src/core/gnunet-service-core_sessions.c:288 #: src/dht/gnunet-service-dht_neighbours.c:662 #: src/dht/gnunet-service-dht_neighbours.c:727 #: src/dht/gnunet-service-xdht_neighbours.c:1304 #: src/fs/gnunet-service-fs_cp.c:606 src/fs/gnunet-service-fs_cp.c:1501 #: src/topology/gnunet-daemon-topology.c:707 #: src/topology/gnunet-daemon-topology.c:808 #: src/transport/gnunet-service-transport_neighbours.c:917 #: src/transport/gnunet-service-transport_neighbours.c:1141 #: src/transport/gnunet-service-transport_neighbours.c:3142 #: src/transport/gnunet-service-transport_neighbours.c:3438 msgid "# peers connected" msgstr "" #: src/core/gnunet-service-core_sessions.c:255 msgid "# type map refreshes sent" msgstr "" #: src/core/gnunet-service-core_sessions.c:426 msgid "# messages discarded (expired prior to transmission)" msgstr "" #: src/core/gnunet-service-core_typemap.c:110 #: src/core/gnunet-service-core_typemap.c:121 msgid "# type maps received" msgstr "" #: src/core/gnunet-service-core_typemap.c:151 msgid "# updates to my type map" msgstr "" #: src/datacache/datacache.c:115 src/datacache/datacache.c:266 #: src/datastore/gnunet-service-datastore.c:838 msgid "# bytes stored" msgstr "" #: src/datacache/datacache.c:117 src/datacache/datacache.c:268 msgid "# items stored" msgstr "" #: src/datacache/datacache.c:143 src/datacache/datacache.c:150 #: src/datastore/gnunet-service-datastore.c:1487 #: src/datastore/gnunet-service-datastore.c:1498 #, c-format msgid "No `%s' specified for `%s' in configuration!\n" msgstr "" #: src/datacache/datacache.c:184 #, c-format msgid "Loading `%s' datacache plugin\n" msgstr "" #: src/datacache/datacache.c:192 #, c-format msgid "Failed to load datacache plugin for `%s'\n" msgstr "" #: src/datacache/datacache.c:295 msgid "# requests received" msgstr "" #: src/datacache/datacache.c:304 msgid "# requests filtered by bloom filter" msgstr "" #: src/datacache/plugin_datacache_heap.c:406 #, fuzzy msgid "Heap datacache running\n" msgstr "sqlite æ•°æ®ä»“库" #: src/datacache/plugin_datacache_postgres.c:392 msgid "Postgres datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:69 #: src/datacache/plugin_datacache_sqlite.c:72 #: src/datastore/plugin_datastore_mysql.c:806 #: src/datastore/plugin_datastore_mysql.c:820 #: src/datastore/plugin_datastore_sqlite.c:57 src/mysql/mysql.c:41 #: src/mysql/mysql.c:48 src/mysql/mysql.c:522 src/mysql/mysql.c:531 #: src/mysql/mysql.c:591 src/mysql/mysql.c:607 #: src/namecache/plugin_namecache_postgres.c:52 #: src/namecache/plugin_namecache_sqlite.c:52 #: src/namestore/plugin_namestore_postgres.c:52 #: src/namestore/plugin_namestore_sqlite.c:52 #: src/testbed/generate-underlay-topology.c:47 #: src/testbed/gnunet-daemon-latency-logger.c:52 #: src/testbed/gnunet-daemon-testbed-underlay.c:55 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:51 #: src/util/crypto_mpi.c:39 src/include/gnunet_common.h:602 #: src/include/gnunet_common.h:611 src/scalarproduct/scalarproduct.h:50 #, fuzzy, c-format msgid "`%s' failed at %s:%d with error: %s\n" msgstr "“%sâ€äºŽ %s:%d 处失败,错误为:%s\n" #: src/datacache/plugin_datacache_sqlite.c:450 msgid "Sqlite datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:484 #: src/datastore/plugin_datastore_sqlite.c:404 #: src/namecache/plugin_namecache_sqlite.c:295 #: src/namestore/plugin_namestore_sqlite.c:327 msgid "Tried to close sqlite without finalizing all prepared statements.\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:491 #, fuzzy, c-format msgid "Failed to close statement %p: %d\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/datacache/plugin_datacache_template.c:125 msgid "Template datacache running\n" msgstr "" #: src/datastore/datastore_api.c:310 msgid "Failed to transmit request to drop database.\n" msgstr "" #: src/datastore/datastore_api.c:394 msgid "# queue entry timeouts" msgstr "" #: src/datastore/datastore_api.c:443 msgid "# queue overflows" msgstr "" #: src/datastore/datastore_api.c:471 msgid "# queue entries created" msgstr "" #: src/datastore/datastore_api.c:491 msgid "# Requests dropped from datastore queue" msgstr "" #: src/datastore/datastore_api.c:533 msgid "# datastore connections (re)created" msgstr "" #: src/datastore/datastore_api.c:616 src/scalarproduct/scalarproduct_api.c:279 msgid "# transmission request failures" msgstr "" #: src/datastore/datastore_api.c:638 msgid "# bytes sent to datastore" msgstr "" #: src/datastore/datastore_api.c:770 msgid "Failed to receive status response from database." msgstr "" #: src/datastore/datastore_api.c:784 msgid "Error reading response from datastore service" msgstr "" #: src/datastore/datastore_api.c:796 src/datastore/datastore_api.c:802 msgid "Invalid error message received from datastore service" msgstr "" #: src/datastore/datastore_api.c:806 msgid "# status messages received" msgstr "" #: src/datastore/datastore_api.c:876 msgid "# PUT requests executed" msgstr "" #: src/datastore/datastore_api.c:944 msgid "# RESERVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1005 msgid "# RELEASE RESERVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1065 msgid "# UPDATE requests executed" msgstr "" #: src/datastore/datastore_api.c:1129 msgid "# REMOVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1174 msgid "Failed to receive response from database.\n" msgstr "" #: src/datastore/datastore_api.c:1233 msgid "# Results received" msgstr "" #: src/datastore/datastore_api.c:1300 msgid "# GET REPLICATION requests executed" msgstr "" #: src/datastore/datastore_api.c:1363 msgid "# GET ZERO ANONYMITY requests executed" msgstr "" #: src/datastore/datastore_api.c:1424 msgid "# GET requests executed" msgstr "" #: src/datastore/gnunet-datastore.c:114 #, fuzzy, c-format msgid "Failed to store item: %s, aborting\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/datastore/gnunet-datastore.c:200 #, c-format msgid "Cannot use the same configuration for source and destination\n" msgstr "" #: src/datastore/gnunet-datastore.c:246 msgid "" "specifies the configuration to use to access an alternative datastore; will " "merge that datastore into our current datastore" msgstr "" #: src/datastore/gnunet-datastore.c:255 #, fuzzy msgid "Manipulate GNUnet datastore" msgstr "更改é…置文件中的一个值" #: src/datastore/gnunet-service-datastore.c:351 msgid "# bytes expired" msgstr "" #: src/datastore/gnunet-service-datastore.c:425 msgid "# bytes purged (low-priority)" msgstr "" #: src/datastore/gnunet-service-datastore.c:483 #: src/gns/gnunet-gns-helper-service-w32.c:223 msgid "Transmission to client failed!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:514 #: src/gns/gnunet-gns-helper-service-w32.c:262 msgid "Shutdown in progress, aborting transmission.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:630 msgid "# results found" msgstr "" #: src/datastore/gnunet-service-datastore.c:673 #, c-format msgid "" "Insufficient space (%llu bytes are available) to satisfy `%s' request for " "%llu bytes\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:684 #, c-format msgid "" "The requested amount (%llu bytes) is larger than the cache size (%llu " "bytes)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:688 msgid "" "Insufficient space to satisfy request and requested amount is larger than " "cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:694 msgid "Insufficient space to satisfy request" msgstr "" #: src/datastore/gnunet-service-datastore.c:699 #: src/datastore/gnunet-service-datastore.c:751 #: src/datastore/gnunet-service-datastore.c:964 #: src/datastore/gnunet-service-datastore.c:1421 msgid "# reserved" msgstr "" #: src/datastore/gnunet-service-datastore.c:764 msgid "Could not find matching reservation" msgstr "" #: src/datastore/gnunet-service-datastore.c:850 #, c-format msgid "Need %llu bytes more space (%llu allowed, using %llu)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1010 msgid "# GET requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1022 msgid "# requests filtered by bloomfilter" msgstr "" #: src/datastore/gnunet-service-datastore.c:1050 msgid "# UPDATE requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1080 msgid "# GET REPLICATION requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1113 msgid "# GET ZERO ANONYMITY requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1138 msgid "Content not found" msgstr "" #: src/datastore/gnunet-service-datastore.c:1146 msgid "# bytes removed (explicit request)" msgstr "" #: src/datastore/gnunet-service-datastore.c:1178 msgid "# REMOVE requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1220 #, c-format msgid "Datastore payload inaccurate (%lld < %lld). Trying to fix.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1281 #, c-format msgid "Loading `%s' datastore plugin\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1290 #, fuzzy, c-format msgid "Failed to load datastore plugin for `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/datastore/gnunet-service-datastore.c:1492 #, c-format msgid "# bytes used in file-sharing datastore `%s'" msgstr "" #: src/datastore/gnunet-service-datastore.c:1503 msgid "# quota" msgstr "" #: src/datastore/gnunet-service-datastore.c:1505 msgid "# cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:1518 #, c-format msgid "Could not use specified filename `%s' for bloomfilter.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1536 #: src/datastore/gnunet-service-datastore.c:1552 #, fuzzy, c-format msgid "Failed to remove bogus bloomfilter file `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/datastore/gnunet-service-datastore.c:1582 #, fuzzy msgid "Failed to initialize bloomfilter.\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/datastore/gnunet-service-datastore.c:1611 msgid "Rebuilding bloomfilter. Please be patient.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1616 msgid "Plugin does not support get_keys function. Please fix!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1619 msgid "Bloomfilter construction complete.\n" msgstr "" #: src/datastore/plugin_datastore_heap.c:820 #, fuzzy msgid "Heap database running\n" msgstr "sqlite æ•°æ®ä»“库" #: src/datastore/plugin_datastore_mysql.c:783 #, fuzzy, c-format msgid "Failed to prepare statement `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/datastore/plugin_datastore_mysql.c:791 #, fuzzy, c-format msgid "`%s' for `%s' failed at %s:%d with error: %s\n" msgstr "“%sâ€äºŽ %s:%d 处失败,错误为:%s\n" #: src/datastore/plugin_datastore_mysql.c:1022 msgid "Mysql database running\n" msgstr "" #: src/datastore/plugin_datastore_postgres.c:824 #, fuzzy msgid "Failed to drop table from database.\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/datastore/plugin_datastore_postgres.c:860 #: src/namecache/plugin_namecache_postgres.c:414 #: src/namestore/plugin_namestore_postgres.c:569 msgid "Postgres database running\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:57 #: src/testbed/generate-underlay-topology.c:50 #: src/testbed/gnunet-daemon-latency-logger.c:55 #: src/testbed/gnunet-daemon-testbed-underlay.c:58 #, fuzzy, c-format msgid "`%s' failed at %s:%u with error: %s" msgstr "“%sâ€äºŽ %s:%d 处失败,错误为:%s\n" #: src/datastore/plugin_datastore_sqlite.c:255 #: src/namecache/plugin_namecache_sqlite.c:193 #: src/namestore/plugin_namestore_sqlite.c:204 #: src/psycstore/plugin_psycstore_sqlite.c:319 #, c-format msgid "Unable to initialize SQLite: %s.\n" msgstr "无法åˆå§‹åŒ– SQLite:%s。\n" #: src/datastore/plugin_datastore_sqlite.c:663 #, fuzzy msgid "Invalid data in database. Trying to fix (by deletion).\n" msgstr "%s 中有无效数æ®ã€‚请å°è¯•ä¿®å¤(删除之)。\n" #: src/datastore/plugin_datastore_sqlite.c:1156 msgid "sqlite version to old to determine size, assuming zero\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1175 #, c-format msgid "" "Using sqlite page utilization to estimate payload (%llu pages of size %llu " "bytes)\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1215 #: src/namecache/plugin_namecache_sqlite.c:583 #: src/namestore/plugin_namestore_sqlite.c:719 #, fuzzy msgid "Sqlite database running\n" msgstr "sqlite æ•°æ®ä»“库" #: src/datastore/plugin_datastore_template.c:257 msgid "Template database running\n" msgstr "" #: src/dht/dht_api.c:376 #, fuzzy msgid "Failed to connect to the DHT service!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/dht/gnunet-dht-get.c:133 #, c-format msgid "" "Result %d, type %d:\n" "%.*s\n" msgstr "" #: src/dht/gnunet-dht-get.c:159 msgid "Must provide key for DHT GET!\n" msgstr "" #: src/dht/gnunet-dht-get.c:165 src/dht/gnunet-dht-monitor.c:225 #, fuzzy msgid "Failed to connect to DHT service!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/dht/gnunet-dht-get.c:173 msgid "Issueing DHT GET with key" msgstr "" #: src/dht/gnunet-dht-get.c:189 src/dht/gnunet-dht-monitor.c:262 #: src/dht/gnunet-dht-put.c:198 msgid "the query key" msgstr "" #: src/dht/gnunet-dht-get.c:192 msgid "how many parallel requests (replicas) to create" msgstr "" #: src/dht/gnunet-dht-get.c:195 src/dht/gnunet-dht-monitor.c:265 msgid "the type of data to look for" msgstr "" #: src/dht/gnunet-dht-get.c:198 src/dht/gnunet-dht-put.c:210 msgid "how long to execute this query before giving up?" msgstr "" #: src/dht/gnunet-dht-get.c:201 src/dht/gnunet-dht-put.c:201 msgid "use DHT's demultiplex everywhere option" msgstr "" #: src/dht/gnunet-dht-get.c:204 src/dht/gnunet-dht-monitor.c:271 #: src/dht/gnunet-dht-put.c:213 src/fs/gnunet-auto-share.c:753 #: src/fs/gnunet-download.c:328 src/fs/gnunet-publish.c:877 #: src/fs/gnunet-search.c:301 src/fs/gnunet-unindex.c:168 #: src/nse/gnunet-nse-profiler.c:873 msgid "be verbose (print progress information)" msgstr "" #: src/dht/gnunet-dht-get.c:225 msgid "Issue a GET request to the GNUnet DHT, prints results." msgstr "" #: src/dht/gnunet-dht-monitor.c:268 msgid "how long should the monitor command run" msgstr "" #: src/dht/gnunet-dht-monitor.c:293 msgid "Prints all packets that go through the DHT." msgstr "" #: src/dht/gnunet-dht-put.c:118 msgid "PUT request sent with key" msgstr "" #: src/dht/gnunet-dht-put.c:121 msgid "Timeout sending PUT request!\n" msgstr "" #: src/dht/gnunet-dht-put.c:124 msgid "PUT request not confirmed!\n" msgstr "" #: src/dht/gnunet-dht-put.c:153 msgid "Must provide KEY and DATA for DHT put!\n" msgstr "" #: src/dht/gnunet-dht-put.c:160 #, fuzzy, c-format msgid "Could not connect to %s service!\n" msgstr "无法连接到 %s:%u:%s\n" #: src/dht/gnunet-dht-put.c:176 #, c-format msgid "Issuing put request for `%s' with data `%s'!\n" msgstr "" #: src/dht/gnunet-dht-put.c:192 msgid "the data to insert under the key" msgstr "" #: src/dht/gnunet-dht-put.c:195 msgid "how long to store this entry in the dht (in seconds)" msgstr "" #: src/dht/gnunet-dht-put.c:204 msgid "how many replicas to create" msgstr "" #: src/dht/gnunet-dht-put.c:207 msgid "the type to insert data as" msgstr "" #: src/dht/gnunet-dht-put.c:236 msgid "Issue a PUT request to the GNUnet DHT insert DATA under KEY." msgstr "" #: src/dht/gnunet-service-dht.c:172 src/dht/gnunet-service-xdht.c:176 #, fuzzy msgid "Failed to connect to transport service!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/dht/gnunet-service-dht_clients.c:417 #: src/dht/gnunet-service-xdht_clients.c:838 msgid "# GET requests from clients injected" msgstr "" #: src/dht/gnunet-service-dht_clients.c:513 #: src/dht/gnunet-service-xdht_clients.c:927 msgid "# PUT requests received from clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:597 #: src/dht/gnunet-service-xdht_clients.c:1013 msgid "# GET requests received from clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:798 #: src/dht/gnunet-service-xdht_clients.c:1214 msgid "# GET STOP requests received from clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1039 #: src/dht/gnunet-service-xdht_clients.c:498 msgid "# Key match, type mismatches in REPLY to CLIENT" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1052 #: src/dht/gnunet-service-xdht_clients.c:511 msgid "# Duplicate REPLIES to CLIENT request dropped" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1089 #: src/dht/gnunet-service-xdht_clients.c:548 #, c-format msgid "Unsupported block type (%u) in request!\n" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1112 #: src/dht/gnunet-service-xdht_clients.c:571 msgid "# RESULTS queued for clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1166 #: src/dht/gnunet-service-dht_clients.c:1209 #: src/dht/gnunet-service-xdht_clients.c:625 #: src/dht/gnunet-service-xdht_clients.c:668 msgid "# REPLIES ignored for CLIENTS (no match)" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1176 #: src/dht/gnunet-service-xdht_clients.c:635 msgid "Could not pass reply to client, message too big!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:68 #: src/dht/gnunet-service-xdht_datacache.c:68 #, c-format msgid "%s request received, but have no datacache!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:78 #: src/dht/gnunet-service-xdht_datacache.c:78 msgid "# ITEMS stored in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:165 #: src/dht/gnunet-service-xdht_datacache.c:165 msgid "# Good RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:176 #: src/dht/gnunet-service-xdht_datacache.c:176 msgid "# Duplicate RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:182 #: src/dht/gnunet-service-xdht_datacache.c:182 msgid "# Invalid RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:188 #: src/dht/gnunet-service-xdht_datacache.c:188 msgid "# Irrelevant RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:200 #: src/dht/gnunet-service-xdht_datacache.c:200 msgid "# Unsupported RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:203 #: src/dht/gnunet-service-xdht_datacache.c:203 #, c-format msgid "Unsupported block type (%u) in local response!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:234 #: src/dht/gnunet-service-xdht_datacache.c:234 msgid "# GET requests given to datacache" msgstr "" #: src/dht/gnunet-service-dht_hello.c:84 #: src/dht/gnunet-service-xdht_hello.c:82 msgid "# HELLOs obtained from peerinfo" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:516 msgid "# Preference updates given to core" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:610 msgid "# FIND PEER messages initiated" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:764 msgid "# Queued messages discarded (peer disconnected)" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:819 #: src/dht/gnunet-service-xdht_neighbours.c:703 msgid "# Bytes transmitted to other peers" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:857 #: src/dht/gnunet-service-xdht_neighbours.c:742 msgid "# Bytes of bandwidth requested from core" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:889 msgid "# requests TTL-dropped" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1093 #: src/dht/gnunet-service-dht_neighbours.c:1130 msgid "# Peers excluded from routing due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1108 #: src/dht/gnunet-service-dht_neighbours.c:1145 msgid "# Peer selection failed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1287 msgid "# PUT requests routed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1316 msgid "# PUT messages queued for transmission" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1323 #: src/dht/gnunet-service-dht_neighbours.c:1440 #: src/dht/gnunet-service-dht_neighbours.c:1543 #: src/dht/gnunet-service-xdht_neighbours.c:794 #: src/dht/gnunet-service-xdht_neighbours.c:860 #: src/dht/gnunet-service-xdht_neighbours.c:919 #: src/dht/gnunet-service-xdht_neighbours.c:981 #: src/dht/gnunet-service-xdht_neighbours.c:1041 msgid "# P2P messages dropped due to full queue" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1405 msgid "# GET requests routed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1432 msgid "# GET messages queued for transmission" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1550 msgid "# RESULT messages queued for transmission" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1636 msgid "# P2P PUT requests received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1639 msgid "# P2P PUT bytes received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1803 msgid "# FIND PEER requests ignored due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1811 msgid "# FIND PEER requests ignored due to lack of HELLO" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1904 msgid "# P2P GET requests received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1907 msgid "# P2P GET bytes received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1961 msgid "# P2P FIND PEER requests processed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1975 msgid "# P2P GET requests ONLY routed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:2052 msgid "# P2P RESULTS received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:2055 msgid "# P2P RESULT bytes received" msgstr "" #: src/dht/gnunet-service-dht_nse.c:59 src/dht/gnunet-service-xdht_nse.c:59 msgid "# Network size estimates received" msgstr "" #: src/dht/gnunet-service-dht_routing.c:211 msgid "# Good REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:220 msgid "# Duplicate REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:226 msgid "# Invalid REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:232 msgid "# Irrelevant REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:244 msgid "# Unsupported REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:317 msgid "# Entries removed from routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:399 msgid "# Entries added to routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:417 msgid "# DHT requests combined" msgstr "" #: src/dht/gnunet-service-xdht_neighbours.c:1398 #, c-format msgid "" "\n" "SUPU %s, %s, %d,my_identity = %s" msgstr "" #: src/dht/gnunet-service-xdht_neighbours.c:1514 #: src/dht/gnunet-service-xdht_neighbours.c:1524 #: src/dht/gnunet-service-xdht_neighbours.c:1530 #: src/dht/gnunet-service-xdht_neighbours.c:1536 #: src/dht/gnunet-service-xdht_neighbours.c:1545 #, c-format msgid "" "\n" "SUPU %s, %s, %d" msgstr "" #: src/dht/plugin_block_dht.c:138 #, c-format msgid "Block not of type %u\n" msgstr "" #: src/dht/plugin_block_dht.c:145 msgid "Size mismatch for block\n" msgstr "" #: src/dht/plugin_block_dht.c:155 #, c-format msgid "Block of type %u is malformed\n" msgstr "" #: src/dns/dnsparser.c:257 #, fuzzy, c-format msgid "Failed to convert DNS IDNA name `%s' to UTF-8: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/dns/dnsparser.c:856 #, fuzzy, c-format msgid "Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/dns/dnsstub.c:175 #, fuzzy, c-format msgid "Could not bind to any port: %s\n" msgstr "找ä¸åˆ°ä¸»æœºâ€œ%sâ€çš„ IP:%s\n" #: src/dns/dnsstub.c:295 src/dns/dnsstub.c:383 #, fuzzy, c-format msgid "Failed to send DNS request to %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/dns/dnsstub.c:299 #, fuzzy, c-format msgid "Sent DNS request to %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/dns/dnsstub.c:368 #, c-format msgid "Configured DNS exit `%s' is not working / valid.\n" msgstr "" #: src/dns/dnsstub.c:440 #, c-format msgid "Received DNS response that is too small (%u bytes)" msgstr "" #: src/dns/gnunet-dns-monitor.c:355 msgid "only monitor DNS queries" msgstr "" #: src/dns/gnunet-dns-monitor.c:358 msgid "only monitor DNS replies" msgstr "" #: src/dns/gnunet-dns-monitor.c:369 msgid "Monitor DNS queries." msgstr "" #: src/dns/gnunet-dns-redirector.c:236 msgid "set A records" msgstr "" #: src/dns/gnunet-dns-redirector.c:239 msgid "set AAAA records" msgstr "" #: src/dns/gnunet-dns-redirector.c:251 msgid "Change DNS replies to point elsewhere." msgstr "" #: src/dns/gnunet-service-dns.c:456 msgid "# DNS requests answered via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:603 msgid "# DNS exit failed (failed to open socket)" msgstr "" #: src/dns/gnunet-service-dns.c:714 msgid "# External DNS response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:792 msgid "# Client response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:907 msgid "Received malformed IPv4-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:923 msgid "Received malformed IPv6-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:932 #, c-format msgid "Got non-IP packet with %u bytes and protocol %u from TUN\n" msgstr "" #: src/dns/gnunet-service-dns.c:942 msgid "# Non-DNS UDP packet received via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:1009 msgid "# DNS requests received via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:1049 src/exit/gnunet-daemon-exit.c:3514 #, c-format msgid "`%s' must be installed SUID, refusing to run\n" msgstr "" #: src/dns/gnunet-service-dns.c:1069 src/exit/gnunet-daemon-exit.c:3571 #, fuzzy msgid "need a valid IPv4 or IPv6 address\n" msgstr "无效的进程优先级“%sâ€\n" #: src/dv/gnunet-dv.c:169 msgid "verbose output" msgstr "" #: src/dv/gnunet-dv.c:178 #, fuzzy msgid "Print information about DV state" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/exit/gnunet-daemon-exit.c:802 #, c-format msgid "Got duplicate service records for `%s:%u'\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:853 #, fuzzy msgid "# Bytes transmitted via mesh channels" msgstr "" "\n" "按任æ„键继续\n" #: src/exit/gnunet-daemon-exit.c:970 src/exit/gnunet-daemon-exit.c:2397 #: src/exit/gnunet-daemon-exit.c:2654 src/vpn/gnunet-service-vpn.c:1407 #: src/vpn/gnunet-service-vpn.c:1797 src/vpn/gnunet-service-vpn.c:1960 msgid "# ICMPv4 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1007 src/exit/gnunet-daemon-exit.c:2456 #: src/exit/gnunet-daemon-exit.c:2713 src/vpn/gnunet-service-vpn.c:1463 #: src/vpn/gnunet-service-vpn.c:1856 src/vpn/gnunet-service-vpn.c:1993 msgid "# ICMPv6 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1047 msgid "# ICMP packets dropped (not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1054 msgid "ICMP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1130 msgid "UDP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1204 msgid "TCP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1256 msgid "# Packets received from TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:1270 msgid "# Bytes received from TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:1296 msgid "IPv4 packet options received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1323 #, c-format msgid "IPv4 packet with unsupported next header %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1369 #, c-format msgid "IPv6 packet with unsupported next header %d received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1377 #, c-format msgid "Packet from unknown protocol %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1759 msgid "# TCP packets sent via TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:1872 msgid "# TCP service creation requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:1875 src/exit/gnunet-daemon-exit.c:1968 #: src/exit/gnunet-daemon-exit.c:2073 src/exit/gnunet-daemon-exit.c:2321 #: src/exit/gnunet-daemon-exit.c:2570 src/exit/gnunet-daemon-exit.c:2859 #: src/exit/gnunet-daemon-exit.c:2966 msgid "# Bytes received from MESH" msgstr "" #: src/exit/gnunet-daemon-exit.c:1909 src/exit/gnunet-daemon-exit.c:2990 #, c-format msgid "No service %s found for %s on port %d!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1914 msgid "# TCP requests dropped (no such service)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1971 msgid "# TCP IP-exit creation requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2076 msgid "# TCP data requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2090 msgid "# TCP DATA requests dropped (no session)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2150 msgid "# ICMP packets sent via TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:2324 msgid "# ICMP IP-exit requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2573 msgid "# ICMP service requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2639 src/vpn/gnunet-service-vpn.c:1397 #: src/vpn/gnunet-service-vpn.c:1954 msgid "# ICMPv4 packets dropped (impossible PT to v6)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2698 src/vpn/gnunet-service-vpn.c:1433 #: src/vpn/gnunet-service-vpn.c:1445 src/vpn/gnunet-service-vpn.c:1844 msgid "# ICMPv6 packets dropped (impossible PT to v4)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2748 msgid "# UDP packets sent via TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:2862 msgid "# UDP IP-exit requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2969 msgid "# UDP service requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2995 msgid "# UDP requests dropped (no such service)" msgstr "" #: src/exit/gnunet-daemon-exit.c:3031 msgid "# Inbound MESH channels created" msgstr "" #: src/exit/gnunet-daemon-exit.c:3235 src/exit/gnunet-daemon-exit.c:3245 #, fuzzy, c-format msgid "Option `%s' for domain `%s' is not formatted correctly!\n" msgstr "%s:选项“%sâ€æœ‰æ­§ä¹‰\n" #: src/exit/gnunet-daemon-exit.c:3259 src/exit/gnunet-daemon-exit.c:3267 #, c-format msgid "`%s' is not a valid port number (for domain `%s')!" msgstr "" #: src/exit/gnunet-daemon-exit.c:3300 #, c-format msgid "No addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3314 src/exit/gnunet-daemon-exit.c:3326 #, c-format msgid "Service `%s' configured for IPv4, but IPv4 is disabled!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3337 #, c-format msgid "No IP addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3527 msgid "" "This system does not support IPv4, will disable IPv4 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3535 msgid "" "This system does not support IPv6, will disable IPv6 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3542 msgid "" "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use " "ENABLE_IPv4=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3548 msgid "" "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use " "ENABLE_IPv6=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3554 src/exit/gnunet-daemon-exit.c:3717 #: src/pt/gnunet-daemon-pt.c:1247 msgid "No useful service enabled. Exiting.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3664 msgid "Must be a number" msgstr "" #: src/exit/gnunet-daemon-exit.c:3813 msgid "Daemon to run to provide an IP exit node for the VPN" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:55 msgid "Experimentation daemon shutting down ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:77 msgid "Experimentation daemon starting ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:83 #, fuzzy msgid "Failed to create statistics!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/experimentation/gnunet-daemon-experimentation.c:120 msgid "GNUnet experimentation daemon" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:241 #, c-format msgid "Experiment `%s': Experiment signature is invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:250 #, c-format msgid "" "Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu " "sec. \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:303 #, c-format msgid "Experiment `%s': Issuer missing\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:312 #, c-format msgid "Experiment `%s': Issuer invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:320 #, c-format msgid "Experiment `%s': Issuer not accepted!\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:330 #, c-format msgid "Experiment `%s': Version missing or invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:339 #, c-format msgid "Experiment `%s': Required capabilities missing \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:345 #, c-format msgid "Experiment `%s': Required capabilities invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:390 #, fuzzy, c-format msgid "Failed to parse file `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:420 #: src/experimentation/gnunet-daemon-experimentation_experiments.c:452 msgid "" "No valid experiment issuers configured! Set value to public keys of issuers! " "Exiting.\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:435 #, fuzzy msgid "Invalid value for public key\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:473 #, fuzzy, c-format msgid "Cannot read experiments file `%s'\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:221 #, c-format msgid "Cannot send message to peer `%s' for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:309 #, c-format msgid "Sending experimentation request to peer %s\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:453 #, c-format msgid "Added peer `%s' as active node\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:891 #, fuzzy, c-format msgid "Connected to peer %s\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:921 #, fuzzy, c-format msgid "Disconnected from peer %s\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:1104 #, fuzzy msgid "Failed to connect to CORE service!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:108 #, c-format msgid "Peer `%s' did not respond to request for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:143 #, c-format msgid "Starting inbound experiment `%s' with peer `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:276 #, c-format msgid "Starting outbound experiment `%s' with peer `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:294 #, c-format msgid "Received %s message from peer %s for experiment `%s'\n" msgstr "" #: src/fragmentation/defragmentation.c:270 msgid "# acknowledgements sent for fragment" msgstr "" #: src/fragmentation/defragmentation.c:456 msgid "# fragments received" msgstr "" #: src/fragmentation/defragmentation.c:521 msgid "# duplicate fragments received" msgstr "" #: src/fragmentation/defragmentation.c:534 msgid "# messages defragmented" msgstr "" #: src/fragmentation/fragmentation.c:208 msgid "# fragments transmitted" msgstr "" #: src/fragmentation/fragmentation.c:211 msgid "# fragments retransmitted" msgstr "" #: src/fragmentation/fragmentation.c:237 msgid "# fragments wrap arounds" msgstr "" #: src/fragmentation/fragmentation.c:281 msgid "# messages fragmented" msgstr "" #: src/fragmentation/fragmentation.c:284 msgid "# total size of fragmented messages" msgstr "" #: src/fragmentation/fragmentation.c:405 msgid "# fragment acknowledgements received" msgstr "" #: src/fragmentation/fragmentation.c:411 msgid "# bits removed from fragmentation ACKs" msgstr "" #: src/fragmentation/fragmentation.c:435 msgid "# fragmentation transmissions completed" msgstr "" #: src/fs/fs_api.c:465 #, fuzzy, c-format msgid "Could not open file `%s': %s" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_api.c:474 #, fuzzy, c-format msgid "Could not read file `%s': %s" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/fs/fs_api.c:480 #, c-format msgid "Short read reading from file `%s'!" msgstr "" #: src/fs/fs_api.c:1066 #, fuzzy, c-format msgid "Failed to resume publishing information `%s': %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_api.c:1571 #, c-format msgid "Failure while resuming publishing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:1585 #, fuzzy, c-format msgid "Failed to resume publishing operation `%s': %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/fs_api.c:2242 #, c-format msgid "Failure while resuming unindexing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2252 #, fuzzy, c-format msgid "Failed to resume unindexing operation `%s': %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/fs_api.c:2378 src/fs/fs_api.c:2619 #, fuzzy, c-format msgid "Failed to resume sub-download `%s': %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_api.c:2395 #, fuzzy, c-format msgid "Failed to resume sub-search `%s': %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_api.c:2409 src/fs/fs_api.c:2428 src/fs/fs_api.c:2911 #, c-format msgid "Failure while resuming search operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2610 #, fuzzy, c-format msgid "Failed to resume sub-download `%s': could not open file `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/fs_api.c:2855 msgid "Could not resume running search, will resume as paused search\n" msgstr "" #: src/fs/fs_api.c:2949 #, c-format msgid "Failure while resuming download operation `%s': %s\n" msgstr "" #: src/fs/fs_directory.c:208 msgid "MAGIC mismatch. This is not a GNUnet directory.\n" msgstr "" #: src/fs/fs_download.c:322 msgid "" "Recursive downloads of directories larger than 4 GB are not supported on 32-" "bit systems\n" msgstr "" #: src/fs/fs_download.c:342 msgid "Directory too large for system address space\n" msgstr "" #: src/fs/fs_download.c:523 src/fs/fs_download.c:535 #, fuzzy, c-format msgid "Failed to open file `%s' for writing" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_download.c:905 #, c-format msgid "Failed to create directory for recursive download of `%s'\n" msgstr "" #: src/fs/fs_download.c:987 #, c-format msgid "" "Internal error or bogus download URI (expected %u bytes at depth %u and " "offset %llu/%llu, got %u bytes)" msgstr "" #: src/fs/fs_download.c:1013 msgid "internal error decrypting content" msgstr "" #: src/fs/fs_download.c:1036 #, fuzzy, c-format msgid "Download failed: could not open file `%s': %s" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_download.c:1046 #, fuzzy, c-format msgid "Failed to seek to offset %llu in file `%s': %s" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_download.c:1055 #, fuzzy, c-format msgid "Failed to write block of %u bytes at offset %llu in file `%s': %s" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/fs_download.c:1153 #, fuzzy msgid "internal error decoding tree" msgstr "未知错误。\n" #: src/fs/fs_download.c:1944 #, fuzzy msgid "Invalid URI" msgstr "无效æ¡ç›®ã€‚\n" #: src/fs/fs_getopt.c:192 #, c-format msgid "" "Unknown metadata type in metadata option `%s'. Using metadata type " "`unknown' instead.\n" msgstr "" #: src/fs/fs_list_indexed.c:90 #, c-format msgid "Failed to receive response for `%s' request from `%s' service.\n" msgstr "" #: src/fs/fs_list_indexed.c:113 #, c-format msgid "Failed to receive valid response for `%s' request from `%s' service.\n" msgstr "" #: src/fs/fs_list_indexed.c:151 #, fuzzy, c-format msgid "Failed to not connect to `%s' service.\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/fs/fs_misc.c:126 #, c-format msgid "Did not find mime type `%s' in extension list.\n" msgstr "" #: src/fs/fs_namespace.c:207 #, fuzzy, c-format msgid "Failed to open `%s' for writing: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_namespace.c:229 #, fuzzy, c-format msgid "Failed to write `%s': %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/fs/fs_namespace.c:320 #, fuzzy, c-format msgid "Failed to read `%s': %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/fs/fs_namespace.c:466 msgid "Failed to connect to datastore." msgstr "" #: src/fs/fs_publish.c:125 src/fs/fs_publish.c:415 #, c-format msgid "Publishing failed: %s" msgstr "" #: src/fs/fs_publish.c:667 src/fs/fs_publish.c:684 src/fs/fs_publish.c:723 #: src/fs/fs_publish.c:744 src/fs/fs_publish.c:768 src/fs/fs_publish.c:914 #, c-format msgid "Can not index file `%s': %s. Will try to insert instead.\n" msgstr "" #: src/fs/fs_publish.c:669 msgid "timeout on index-start request to `fs' service" msgstr "" #: src/fs/fs_publish.c:681 #, fuzzy msgid "unknown error" msgstr "未知错误" #: src/fs/fs_publish.c:725 msgid "failed to compute hash" msgstr "" #: src/fs/fs_publish.c:745 msgid "filename too long" msgstr "" #: src/fs/fs_publish.c:770 msgid "could not connect to `fs' service" msgstr "" #: src/fs/fs_publish.c:793 #, fuzzy, c-format msgid "Failed to get file identifiers for `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/fs_publish.c:862 #, c-format msgid "Recursive upload failed at `%s': %s" msgstr "" #: src/fs/fs_publish.c:868 #, c-format msgid "Recursive upload failed: %s" msgstr "" #: src/fs/fs_publish.c:915 msgid "needs to be an actual file" msgstr "" #: src/fs/fs_publish.c:1151 #, c-format msgid "Insufficient space for publishing: %s" msgstr "" #: src/fs/fs_publish.c:1243 #, c-format msgid "Reserving space for %u entries and %llu bytes for publication\n" msgstr "" #: src/fs/fs_publish_ksk.c:219 msgid "Could not connect to datastore." msgstr "" #: src/fs/fs_publish_ublock.c:219 #, fuzzy msgid "Internal error." msgstr "未知错误。\n" #: src/fs/fs_search.c:813 #, fuzzy, c-format msgid "Failed to parse URI `%s': %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/fs/fs_search.c:872 #, c-format msgid "Got result with unknown block type `%d', ignoring" msgstr "" #: src/fs/fs_unindex.c:59 msgid "Failed to find given position in file" msgstr "" #: src/fs/fs_unindex.c:64 #, fuzzy msgid "Failed to read file" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/fs/fs_unindex.c:234 msgid "Unexpected time for a response from `fs' service." msgstr "" #: src/fs/fs_unindex.c:242 msgid "Timeout waiting for `fs' service." msgstr "" #: src/fs/fs_unindex.c:250 #, fuzzy msgid "Invalid response from `fs' service." msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/fs/fs_unindex.c:291 msgid "Failed to connect to FS service for unindexing." msgstr "" #: src/fs/fs_unindex.c:347 src/fs/fs_unindex.c:359 #, fuzzy msgid "Failed to get KSKs from directory scan." msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/fs_unindex.c:355 #, fuzzy, c-format msgid "Internal error scanning `%s'.\n" msgstr "未知错误。\n" #: src/fs/fs_unindex.c:414 #, fuzzy, c-format msgid "Failed to remove UBlock: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_unindex.c:562 src/fs/fs_unindex.c:626 #, fuzzy msgid "Failed to connect to `datastore' service." msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/fs/fs_unindex.c:639 #, fuzzy msgid "Failed to open file for unindexing." msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/fs_unindex.c:673 msgid "Failed to compute hash of file." msgstr "" #: src/fs/fs_uri.c:222 #, no-c-format msgid "`%' must be followed by HEX number" msgstr "" #: src/fs/fs_uri.c:281 msgid "Malformed KSK URI (must not begin or end with `+')" msgstr "" #: src/fs/fs_uri.c:299 msgid "`++' not allowed in KSK URI" msgstr "" #: src/fs/fs_uri.c:306 msgid "Quotes not balanced in KSK URI" msgstr "" #: src/fs/fs_uri.c:376 msgid "Malformed SKS URI" msgstr "" #: src/fs/fs_uri.c:419 src/fs/fs_uri.c:434 msgid "Malformed CHK URI" msgstr "" #: src/fs/fs_uri.c:512 src/fs/fs_uri.c:580 msgid "SKS URI malformed" msgstr "" #: src/fs/fs_uri.c:527 src/fs/fs_uri.c:537 msgid "LOC URI malformed" msgstr "" #: src/fs/fs_uri.c:545 src/fs/fs_uri.c:553 msgid "LOC URI malformed (could not decode public key)" msgstr "" #: src/fs/fs_uri.c:559 msgid "SKS URI malformed (could not find signature)" msgstr "" #: src/fs/fs_uri.c:565 src/fs/fs_uri.c:574 msgid "SKS URI malformed (could not decode signature)" msgstr "" #: src/fs/fs_uri.c:586 msgid "SKS URI malformed (could not parse expiration time)" msgstr "" #: src/fs/fs_uri.c:598 msgid "SKS URI malformed (signature failed validation)" msgstr "" #: src/fs/fs_uri.c:636 msgid "Unrecognized URI type" msgstr "" #: src/fs/fs_uri.c:860 #, fuzzy msgid "Lacking key configuration settings.\n" msgstr "ç«‹å³ä¿å­˜é…置?" #: src/fs/fs_uri.c:866 #, fuzzy, c-format msgid "Could not access hostkey file `%s'.\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/fs/fs_uri.c:1050 src/fs/fs_uri.c:1077 msgid "No keywords specified!\n" msgstr "" #: src/fs/fs_uri.c:1083 msgid "Number of double-quotes not balanced!\n" msgstr "" #: src/fs/gnunet-auto-share.c:236 #, fuzzy, c-format msgid "Failed to load state: %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/fs/gnunet-auto-share.c:289 src/fs/gnunet-auto-share.c:299 #: src/fs/gnunet-auto-share.c:309 #, fuzzy, c-format msgid "Failed to save state to file %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/gnunet-auto-share.c:401 #, c-format msgid "Publication of `%s' done\n" msgstr "" #: src/fs/gnunet-auto-share.c:488 #, c-format msgid "Publishing `%s'\n" msgstr "" #: src/fs/gnunet-auto-share.c:497 #, fuzzy, c-format msgid "Failed to run `%s'\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/fs/gnunet-auto-share.c:686 #, c-format msgid "" "You must specify one and only one directory name for automatic publication.\n" msgstr "" #: src/fs/gnunet-auto-share.c:737 src/fs/gnunet-publish.c:824 msgid "set the desired LEVEL of sender-anonymity" msgstr "" #: src/fs/gnunet-auto-share.c:741 src/fs/gnunet-publish.c:828 msgid "disable adding the creation time to the metadata of the uploaded file" msgstr "" #: src/fs/gnunet-auto-share.c:744 src/fs/gnunet-publish.c:831 msgid "do not use libextractor to add keywords or metadata" msgstr "" #: src/fs/gnunet-auto-share.c:747 src/fs/gnunet-publish.c:855 msgid "specify the priority of the content" msgstr "" #: src/fs/gnunet-auto-share.c:750 src/fs/gnunet-publish.c:862 msgid "set the desired replication LEVEL" msgstr "" #: src/fs/gnunet-auto-share.c:770 msgid "Automatically publish files from a directory on GNUnet" msgstr "" #: src/fs/gnunet-daemon-fsprofiler.c:660 msgid "Daemon to use file-sharing to measure its performance." msgstr "" #: src/fs/gnunet-directory.c:49 #, c-format msgid "\t\n" msgstr "" #: src/fs/gnunet-directory.c:94 #, c-format msgid "Directory `%s' meta data:\n" msgstr "" #: src/fs/gnunet-directory.c:97 #, c-format msgid "Directory `%s' contents:\n" msgstr "" #: src/fs/gnunet-directory.c:132 #, fuzzy msgid "You must specify a filename to inspect.\n" msgstr "您必须指定一个昵称\n" #: src/fs/gnunet-directory.c:145 #, fuzzy, c-format msgid "Failed to read directory `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/gnunet-directory.c:154 #, fuzzy, c-format msgid "`%s' is not a GNUnet directory\n" msgstr "更改 GNUnet 目录的æƒé™å‡ºé”™" #: src/fs/gnunet-directory.c:183 #, fuzzy msgid "Display contents of a GNUnet directory" msgstr "更改 GNUnet 目录的æƒé™å‡ºé”™" #: src/fs/gnunet-download.c:137 #, fuzzy, c-format msgid "Starting download `%s'.\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/fs/gnunet-download.c:147 #, fuzzy msgid "" msgstr "未知错误" #: src/fs/gnunet-download.c:157 #, c-format msgid "" "Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to " "download\n" msgstr "" #: src/fs/gnunet-download.c:179 #, c-format msgid "Error downloading: %s.\n" msgstr "" #: src/fs/gnunet-download.c:194 #, c-format msgid "Downloading `%s' done (%s/s).\n" msgstr "" #: src/fs/gnunet-download.c:209 src/fs/gnunet-publish.c:286 #: src/fs/gnunet-search.c:200 src/fs/gnunet-unindex.c:108 #, c-format msgid "Unexpected status: %d\n" msgstr "" #: src/fs/gnunet-download.c:234 #, fuzzy msgid "You need to specify a URI argument.\n" msgstr "您必须指定一个昵称\n" #: src/fs/gnunet-download.c:240 src/fs/gnunet-publish.c:665 #, fuzzy, c-format msgid "Failed to parse URI: %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/fs/gnunet-download.c:247 msgid "Only CHK or LOC URIs supported.\n" msgstr "" #: src/fs/gnunet-download.c:254 msgid "Target filename must be specified.\n" msgstr "" #: src/fs/gnunet-download.c:268 src/fs/gnunet-publish.c:797 #: src/fs/gnunet-search.c:250 src/fs/gnunet-unindex.c:140 #, fuzzy, c-format msgid "Could not initialize `%s' subsystem.\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/fs/gnunet-download.c:305 src/fs/gnunet-search.c:289 msgid "set the desired LEVEL of receiver-anonymity" msgstr "" #: src/fs/gnunet-download.c:308 msgid "delete incomplete downloads (when aborted with CTRL-C)" msgstr "" #: src/fs/gnunet-download.c:311 src/fs/gnunet-search.c:292 msgid "only search the local peer (no P2P network search)" msgstr "" #: src/fs/gnunet-download.c:314 msgid "write the file to FILENAME" msgstr "" #: src/fs/gnunet-download.c:318 msgid "set the maximum number of parallel downloads that is allowed" msgstr "" #: src/fs/gnunet-download.c:322 msgid "set the maximum number of parallel requests for blocks that is allowed" msgstr "" #: src/fs/gnunet-download.c:325 msgid "download a GNUnet directory recursively" msgstr "" #: src/fs/gnunet-download.c:339 msgid "" "Download files from GNUnet using a GNUnet CHK or LOC URI (gnunet://fs/" "chk/...)" msgstr "" #: src/fs/gnunet-fs.c:117 msgid "print a list of all indexed files" msgstr "" #: src/fs/gnunet-fs.c:127 msgid "Special file-sharing operations" msgstr "" #: src/fs/gnunet-fs-profiler.c:193 msgid "run the experiment with COUNT peers" msgstr "" #: src/fs/gnunet-fs-profiler.c:196 msgid "specifies name of a file with the HOSTS the testbed should use" msgstr "" #: src/fs/gnunet-fs-profiler.c:199 msgid "automatically terminate experiment after DELAY" msgstr "" #: src/fs/gnunet-fs-profiler.c:208 msgid "run a testbed to measure file-sharing performance" msgstr "" #: src/fs/gnunet-publish.c:231 src/fs/gnunet-publish.c:243 #, c-format msgid "Publishing `%s' at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-publish.c:250 #, c-format msgid "Error publishing: %s.\n" msgstr "" #: src/fs/gnunet-publish.c:260 #, c-format msgid "Publishing `%s' done.\n" msgstr "" #: src/fs/gnunet-publish.c:264 #, c-format msgid "URI is `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:283 msgid "Cleanup after abort complete.\n" msgstr "" #: src/fs/gnunet-publish.c:401 #, fuzzy, c-format msgid "Meta data for file `%s' (%s)\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/gnunet-publish.c:403 #, fuzzy, c-format msgid "Keywords for file `%s' (%s)\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/fs/gnunet-publish.c:542 #, fuzzy msgid "Could not publish\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/fs/gnunet-publish.c:565 msgid "Could not start publishing.\n" msgstr "" #: src/fs/gnunet-publish.c:598 #, fuzzy, c-format msgid "Scanning directory `%s'.\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/fs/gnunet-publish.c:600 #, fuzzy, c-format msgid "Scanning file `%s'.\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/fs/gnunet-publish.c:605 #, c-format msgid "There was trouble processing file `%s', skipping it.\n" msgstr "" #: src/fs/gnunet-publish.c:610 msgid "Preprocessing complete.\n" msgstr "" #: src/fs/gnunet-publish.c:614 #, fuzzy, c-format msgid "Extracting meta data from file `%s' complete.\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/gnunet-publish.c:618 msgid "Meta data extraction has finished.\n" msgstr "" #: src/fs/gnunet-publish.c:625 #, fuzzy msgid "Internal error scanning directory.\n" msgstr "未知错误。\n" #: src/fs/gnunet-publish.c:656 #, c-format msgid "Selected pseudonym `%s' unknown\n" msgstr "" #: src/fs/gnunet-publish.c:682 #, fuzzy, c-format msgid "Failed to access `%s': %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/gnunet-publish.c:695 msgid "" "Failed to start meta directory scanner. Is gnunet-helper-publish-fs " "installed?\n" msgstr "" #: src/fs/gnunet-publish.c:747 #, c-format msgid "Cannot extract metadata from a URI!\n" msgstr "" #: src/fs/gnunet-publish.c:754 #, c-format msgid "You must specify one and only one filename for insertion.\n" msgstr "" #: src/fs/gnunet-publish.c:760 #, c-format msgid "You must NOT specify an URI and a filename.\n" msgstr "" #: src/fs/gnunet-publish.c:768 src/vpn/gnunet-vpn.c:209 #, c-format msgid "Option `%s' is required when using option `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:778 src/fs/gnunet-publish.c:785 #: src/transport/gnunet-transport.c:1284 src/transport/gnunet-transport.c:1314 #: src/transport/gnunet-transport.c:1344 #, c-format msgid "Option `%s' makes no sense without option `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:835 msgid "" "print list of extracted keywords that would be used, but do not perform " "upload" msgstr "" #: src/fs/gnunet-publish.c:839 msgid "" "add an additional keyword for the top-level file or directory (this option " "can be specified multiple times)" msgstr "" #: src/fs/gnunet-publish.c:843 msgid "set the meta-data for the given TYPE to the given VALUE" msgstr "" #: src/fs/gnunet-publish.c:846 msgid "" "do not index, perform full insertion (stores entire file in encrypted form " "in GNUnet database)" msgstr "" #: src/fs/gnunet-publish.c:851 msgid "" "specify ID of an updated version to be published in the future (for " "namespace insertions only)" msgstr "" #: src/fs/gnunet-publish.c:859 msgid "publish the files under the pseudonym NAME (place file into namespace)" msgstr "" #: src/fs/gnunet-publish.c:865 msgid "" "only simulate the process but do not do any actual publishing (useful to " "compute URIs)" msgstr "" #: src/fs/gnunet-publish.c:869 msgid "" "set the ID of this version of the publication (for namespace insertions only)" msgstr "" #: src/fs/gnunet-publish.c:873 msgid "" "URI to be published (can be used instead of passing a file to add keywords " "to the file with the respective URI)" msgstr "" #: src/fs/gnunet-publish.c:889 msgid "Publish a file or directory on GNUnet" msgstr "" #: src/fs/gnunet-search.c:114 #, c-format msgid "Failed to write directory with search results to `%s'\n" msgstr "" #: src/fs/gnunet-search.c:191 #, fuzzy, c-format msgid "Error searching: %s.\n" msgstr "创建用户出错" #: src/fs/gnunet-search.c:240 msgid "Could not create keyword URI from arguments.\n" msgstr "" #: src/fs/gnunet-search.c:264 msgid "Could not start searching.\n" msgstr "" #: src/fs/gnunet-search.c:295 msgid "write search results to file starting with PREFIX" msgstr "" #: src/fs/gnunet-search.c:298 msgid "automatically terminate search after DELAY" msgstr "" #: src/fs/gnunet-search.c:305 msgid "automatically terminate search after VALUE results are found" msgstr "" #: src/fs/gnunet-search.c:316 msgid "Search GNUnet for files that were published on GNUnet" msgstr "" #: src/fs/gnunet-service-fs.c:271 msgid "# running average P2P latency (ms)" msgstr "" #: src/fs/gnunet-service-fs.c:326 src/fs/gnunet-service-fs.c:539 msgid "# Loopback routes suppressed" msgstr "" #: src/fs/gnunet-service-fs.c:639 src/hostlist/gnunet-daemon-hostlist.c:288 #: src/topology/gnunet-daemon-topology.c:1254 #: src/topology/gnunet-daemon-topology.c:1261 #, fuzzy, c-format msgid "Failed to connect to `%s' service.\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/fs/gnunet-service-fs_cp.c:682 msgid "# migration stop messages received" msgstr "" #: src/fs/gnunet-service-fs_cp.c:686 #, c-format msgid "Migration of content to peer `%s' blocked for %s\n" msgstr "" #: src/fs/gnunet-service-fs_cp.c:721 msgid "# replies transmitted to other peers" msgstr "" #: src/fs/gnunet-service-fs_cp.c:727 msgid "# replies dropped" msgstr "" #: src/fs/gnunet-service-fs_cp.c:752 src/fs/gnunet-service-fs_cp.c:1301 msgid "# P2P searches active" msgstr "" #: src/fs/gnunet-service-fs_cp.c:845 msgid "# artificial delays introduced (ms)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:898 msgid "# replies dropped due to type mismatch" msgstr "" #: src/fs/gnunet-service-fs_cp.c:906 msgid "# replies received for other peers" msgstr "" #: src/fs/gnunet-service-fs_cp.c:920 msgid "# replies dropped due to insufficient cover traffic" msgstr "" #: src/fs/gnunet-service-fs_cp.c:958 msgid "# P2P searches destroyed due to ultimate reply" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1026 msgid "# requests done for free (low load)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1051 msgid "# request dropped, priority insufficient" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1061 msgid "# requests done for a price (normal load)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1139 msgid "# GET requests received (from other peers)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1173 msgid "# requests dropped due to initiator not being connected" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1195 msgid "# requests dropped due to missing reverse route" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1246 msgid "# requests dropped due TTL underflow" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1270 msgid "# requests dropped due to higher-TTL request" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1299 msgid "# P2P query messages received and processed" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1670 msgid "# migration stop messages sent" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:130 #: src/fs/gnunet-service-fs_indexing.c:181 #, fuzzy, c-format msgid "Could not open `%s'.\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/fs/gnunet-service-fs_indexing.c:142 #, fuzzy, c-format msgid "Error writing `%s'.\n" msgstr "创建用户出错" #: src/fs/gnunet-service-fs_indexing.c:237 #, c-format msgid "" "Index request received for file `%s' is already indexed as `%s'. Permitting " "anyway.\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:275 #, c-format msgid "Hash mismatch trying to index file `%s' which has hash `%s'\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:477 #, fuzzy, c-format msgid "Failed to delete bogus block: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/fs/gnunet-service-fs_indexing.c:542 msgid "# index blocks removed: original file inaccessible" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:557 #, fuzzy, c-format msgid "Could not access indexed file `%s' (%s) at offset %llu: %s\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/fs/gnunet-service-fs_indexing.c:559 msgid "not indexed" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:574 #, c-format msgid "Indexed file `%s' changed at offset %llu\n" msgstr "" #: src/fs/gnunet-service-fs_lc.c:202 src/fs/gnunet-service-fs_lc.c:368 msgid "# client searches active" msgstr "" #: src/fs/gnunet-service-fs_lc.c:256 msgid "# replies received for local clients" msgstr "" #: src/fs/gnunet-service-fs_lc.c:327 msgid "# client searches received" msgstr "" #: src/fs/gnunet-service-fs_lc.c:362 msgid "# client searches updated (merged content seen list)" msgstr "" #: src/fs/gnunet-service-fs_mesh_client.c:484 msgid "# replies received via mesh" msgstr "" #: src/fs/gnunet-service-fs_mesh_client.c:498 msgid "# replies received via mesh dropped" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:260 msgid "# Blocks transferred via mesh" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:352 msgid "# queries received via mesh not answered" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:432 msgid "# queries received via mesh" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:476 #, fuzzy msgid "# mesh client connections rejected" msgstr "" "\n" "按任æ„键继续\n" #: src/fs/gnunet-service-fs_mesh_server.c:482 #: src/fs/gnunet-service-fs_mesh_server.c:522 #, fuzzy msgid "# mesh connections active" msgstr "" "\n" "按任æ„键继续\n" #: src/fs/gnunet-service-fs_pe.c:269 msgid "# average retransmission delay (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:400 msgid "# transmission failed (core has no bandwidth)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:433 msgid "# query messages sent to other peers" msgstr "" #: src/fs/gnunet-service-fs_pe.c:484 msgid "# delay heap timeout (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:492 msgid "# query plans executed" msgstr "" #: src/fs/gnunet-service-fs_pe.c:552 msgid "# requests merged" msgstr "" #: src/fs/gnunet-service-fs_pe.c:560 msgid "# requests refreshed" msgstr "" #: src/fs/gnunet-service-fs_pe.c:616 src/fs/gnunet-service-fs_pe.c:700 #: src/fs/gnunet-service-fs_pe.c:771 msgid "# query plan entries" msgstr "" #: src/fs/gnunet-service-fs_pr.c:311 msgid "# Pending requests created" msgstr "" #: src/fs/gnunet-service-fs_pr.c:394 src/fs/gnunet-service-fs_pr.c:645 msgid "# Pending requests active" msgstr "" #: src/fs/gnunet-service-fs_pr.c:814 msgid "# replies received and matched" msgstr "" #: src/fs/gnunet-service-fs_pr.c:844 msgid "# duplicate replies discarded (bloomfilter)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:853 msgid "# irrelevant replies discarded" msgstr "" #: src/fs/gnunet-service-fs_pr.c:867 #, c-format msgid "Unsupported block type %u\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:880 msgid "# results found locally" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1001 msgid "# Datastore `PUT' failures" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1029 msgid "# storage requests dropped due to high load" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1064 msgid "# Replies received from DHT" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1192 msgid "# Replies received from MESH" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1244 #, c-format msgid "Datastore lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1264 #, c-format msgid "On-demand lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1311 msgid "# Datastore lookups concluded (no results)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1326 msgid "# Datastore lookups concluded (seen all)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1335 msgid "# Datastore lookups aborted (more than MAX_RESULTS)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1350 msgid "# requested DBLOCK or IBLOCK not found" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1364 msgid "# on-demand blocks matched requests" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1377 msgid "# on-demand lookups performed successfully" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1382 msgid "# on-demand lookups failed" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1409 src/fs/gnunet-service-fs_pr.c:1449 #: src/fs/gnunet-service-fs_pr.c:1590 msgid "# Datastore lookups concluded (error queueing)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1467 msgid "# Datastore lookups concluded (found last result)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1478 msgid "# Datastore lookups concluded (load too high)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1566 msgid "# Datastore lookups initiated" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1651 msgid "# GAP PUT messages received" msgstr "" #: src/fs/gnunet-service-fs_push.c:631 msgid "time required, content pushing disabled" msgstr "" #: src/fs/gnunet-unindex.c:89 #, c-format msgid "Unindexing at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-unindex.c:95 #, c-format msgid "Error unindexing: %s.\n" msgstr "" #: src/fs/gnunet-unindex.c:100 msgid "Unindexing done.\n" msgstr "" #: src/fs/gnunet-unindex.c:130 #, c-format msgid "You must specify one and only one filename for unindexing.\n" msgstr "" #: src/fs/gnunet-unindex.c:147 msgid "Could not start unindex operation.\n" msgstr "" #: src/fs/gnunet-unindex.c:179 msgid "Unindex a file that was previously indexed with gnunet-publish." msgstr "" #: src/gns/gns_api.c:393 #, fuzzy msgid "Failed to deserialize lookup reply from GNS service!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-bcd.c:123 #, c-format msgid "Refusing `%s' request to HTTP server\n" msgstr "" #: src/gns/gnunet-bcd.c:355 src/hostlist/hostlist-server.c:567 #, c-format msgid "Invalid port number %llu. Exiting.\n" msgstr "" #: src/gns/gnunet-bcd.c:360 #, c-format msgid "Businesscard HTTP server starts on %llu\n" msgstr "" #: src/gns/gnunet-bcd.c:374 #, fuzzy, c-format msgid "Could not start businesscard HTTP server on port %u\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-bcd.c:519 msgid "Run HTTP serve on port PORT (default is 8888)" msgstr "" #: src/gns/gnunet-bcd.c:531 msgid "GNUnet HTTP server to create business cards" msgstr "" #: src/gns/gnunet-dns2gns.c:228 #, fuzzy msgid "Failed to pack DNS response into UDP packet!\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/gns/gnunet-dns2gns.c:400 #, c-format msgid "Cannot parse DNS request from %s\n" msgstr "" #: src/gns/gnunet-dns2gns.c:416 #, c-format msgid "Received malformed DNS request from %s\n" msgstr "" #: src/gns/gnunet-dns2gns.c:424 #, c-format msgid "Received unsupported DNS request from %s\n" msgstr "" #: src/gns/gnunet-dns2gns.c:701 msgid "No ego configured for `dns2gns` subsystem\n" msgstr "" #: src/gns/gnunet-dns2gns.c:727 msgid "No DNS server specified!\n" msgstr "" #: src/gns/gnunet-dns2gns.c:749 msgid "No valid GNS zone specified!\n" msgstr "" #: src/gns/gnunet-dns2gns.c:770 msgid "IP of recursive DNS resolver to use (required)" msgstr "" #: src/gns/gnunet-dns2gns.c:773 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:776 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:779 msgid "UDP port to listen on for inbound DNS requests; default: 53" msgstr "" #: src/gns/gnunet-dns2gns.c:782 msgid "Public key of the GNS zone to use (overrides default)" msgstr "" #: src/gns/gnunet-dns2gns.c:795 msgid "GNUnet DNS-to-GNS proxy (a DNS server)" msgstr "" #: src/gns/gnunet-gns.c:227 #, c-format msgid "Please specify name to lookup!\n" msgstr "" #: src/gns/gnunet-gns.c:308 #, c-format msgid "Ego for `%s' not found, cannot perform lookup.\n" msgstr "" #: src/gns/gnunet-gns.c:347 src/gns/gnunet-gns-helper-service-w32.c:798 #, c-format msgid "" "Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-" "gns-import.sh?\n" msgstr "" #: src/gns/gnunet-gns.c:386 src/gns/gnunet-gns-helper-service-w32.c:828 #, fuzzy, c-format msgid "Failed to connect to GNS\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-gns.c:399 #, c-format msgid "Public key `%s' is not well-formed\n" msgstr "" #: src/gns/gnunet-gns.c:449 msgid "Lookup a record for the given name" msgstr "" #: src/gns/gnunet-gns.c:452 msgid "Specify the type of the record to lookup" msgstr "" #: src/gns/gnunet-gns.c:455 msgid "Specify timeout for the lookup" msgstr "" #: src/gns/gnunet-gns.c:458 msgid "No unneeded output" msgstr "" #: src/gns/gnunet-gns.c:461 msgid "Specify the public key of the zone to lookup the record in" msgstr "" #: src/gns/gnunet-gns.c:464 msgid "Specify the name of the ego of the zone to lookup the record in" msgstr "" #: src/gns/gnunet-gns.c:478 #, fuzzy msgid "GNUnet GNS resolver tool" msgstr "GNUnet 错误日志" #: src/gns/gnunet-gns-helper-service-w32.c:768 #, c-format msgid "" "Ego for `gns-short' not found. This is not really fatal, but i'll pretend " "that it is and refuse to perform a lookup. Did you run gnunet-gns-import." "sh?\n" msgstr "" #: src/gns/gnunet-gns-helper-service-w32.c:838 #, fuzzy, c-format msgid "Failed to connect to identity service\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-gns-import.c:479 msgid "This program will import some GNS authorities into your GNS namestore." msgstr "" #: src/gns/gnunet-gns-proxy.c:105 src/hostlist/hostlist-client.c:469 #: src/hostlist/hostlist-client.c:683 src/hostlist/hostlist-client.c:689 #: src/hostlist/hostlist-client.c:741 src/hostlist/hostlist-client.c:750 #: src/hostlist/hostlist-client.c:871 src/hostlist/hostlist-client.c:963 #: src/hostlist/hostlist-client.c:968 #: src/transport/plugin_transport_http_client.c:1062 #: src/transport/plugin_transport_http_client.c:1077 #, c-format msgid "%s failed at %s:%d: `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:833 #, fuzzy, c-format msgid "Unsupported CURL SSL backend %d\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/gns/gnunet-gns-proxy.c:856 #, fuzzy, c-format msgid "Failed to fetch CN from cert: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/gns/gnunet-gns-proxy.c:879 #, fuzzy, c-format msgid "Failed to initialize DANE: %s\n" msgstr "无法åˆå§‹åŒ– SQLite:%s。\n" #: src/gns/gnunet-gns-proxy.c:892 #, fuzzy, c-format msgid "Failed to parse DANE record: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/gns/gnunet-gns-proxy.c:907 #, fuzzy, c-format msgid "Failed to verify TLS connection using DANE: %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gns/gnunet-gns-proxy.c:917 #, c-format msgid "Failed DANE verification failed with GnuTLS verify status code: %u\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:941 #, c-format msgid "SSL certificate subject name (%s) does not match `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1086 #, c-format msgid "Cookie domain `%s' supplied by server is invalid\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1602 #, fuzzy, c-format msgid "Unsupported HTTP method `%s'\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/gns/gnunet-gns-proxy.c:1973 #, fuzzy, c-format msgid "Unable to import private key from file `%s'\n" msgstr "无法创建用户账户:" #: src/gns/gnunet-gns-proxy.c:2003 #, fuzzy, c-format msgid "Unable to import certificate %s\n" msgstr "无法ä¿å­˜é…置文件“%sâ€ï¼š" #: src/gns/gnunet-gns-proxy.c:2177 #, fuzzy, c-format msgid "Failed to start HTTPS server for `%s'\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-gns-proxy.c:2196 #, fuzzy msgid "Failed to pass client to MHD\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-gns-proxy.c:2504 #, fuzzy, c-format msgid "Unsupported socks version %d\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/gns/gnunet-gns-proxy.c:2533 #, fuzzy, c-format msgid "Unsupported socks command %d\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/gns/gnunet-gns-proxy.c:2551 src/gns/gnunet-gns-proxy.c:2580 msgid "SSL connection to plain IPv4 address requested\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2631 #, fuzzy, c-format msgid "Unsupported socks address type %d\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/gns/gnunet-gns-proxy.c:2970 msgid "No ego configured for `shorten-zone`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3010 #, c-format msgid "No ego configured for `%s`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3072 #, fuzzy, c-format msgid "Failed to load SSL/TLS key and certificate from `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gns/gnunet-gns-proxy.c:3113 msgid "listen on specified port (default: 7777)" msgstr "" #: src/gns/gnunet-gns-proxy.c:3116 msgid "pem file to use as CA" msgstr "" #: src/gns/gnunet-gns-proxy.c:3135 msgid "GNUnet GNS proxy" msgstr "" #: src/gns/gnunet-service-gns.c:862 #, fuzzy msgid "Failed to connect to the namestore!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-service-gns.c:870 #, fuzzy msgid "Failed to connect to the namecache!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-service-gns.c:903 #, fuzzy msgid "Could not connect to DHT!\n" msgstr "无法连接到 %s:%u:%s\n" #: src/gns/gnunet-service-gns.c:919 #, fuzzy msgid "valid public key required" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/gns/gnunet-service-gns_interceptor.c:263 msgid "Error converting GNS response to DNS response!\n" msgstr "" #: src/gns/gnunet-service-gns_interceptor.c:369 #, fuzzy msgid "Failed to connect to the DNS service!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/gns/gnunet-service-gns_resolver.c:816 #, fuzzy msgid "Failed to parse DNS response\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/gns/gnunet-service-gns_resolver.c:958 #, c-format msgid "Skipping record of unsupported type %d\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1317 #, c-format msgid "GNS lookup resulted in DNS name that is too long (`%s')\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1817 msgid "GNS lookup recursion failed (no delegation record found)\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1841 #, fuzzy, c-format msgid "Failed to cache GNS resolution: %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/gns/gnunet-service-gns_resolver.c:2123 #, c-format msgid "Zone %s was revoked, resolution fails\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:2272 #, c-format msgid "Hostname `%s' is not well-formed, resolution fails\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:151 #, fuzzy, c-format msgid "Unable to parse PKEY record `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gns/plugin_gnsrecord_gns.c:180 #, fuzzy, c-format msgid "Unable to parse GNS2DNS record `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gns/plugin_gnsrecord_gns.c:201 #, fuzzy, c-format msgid "Failed to serialize GNS2DNS record with value `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gns/plugin_gnsrecord_gns.c:217 #, fuzzy, c-format msgid "Unable to parse VPN record string `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:293 #, fuzzy, c-format msgid "Unable to parse IPv4 address `%s'\n" msgstr "无效的进程优先级“%sâ€\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:314 #, fuzzy, c-format msgid "Failed to serialize NS record with value `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:336 #, fuzzy, c-format msgid "Failed to serialize CNAME record with value `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:420 #, fuzzy, c-format msgid "Failed to serialize CERT record with %u bytes\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:452 #, fuzzy, c-format msgid "Unable to parse SOA record `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:471 #, fuzzy, c-format msgid "Failed to serialize SOA record with mname `%s' and rname `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:494 #, fuzzy, c-format msgid "Failed to serialize PTR record with value `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:514 #, fuzzy, c-format msgid "Unable to parse MX record `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:529 #, fuzzy, c-format msgid "Failed to serialize MX record with hostname `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:549 #, fuzzy, c-format msgid "Unable to parse IPv6 address `%s'\n" msgstr "无效的进程优先级“%sâ€\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:567 #, fuzzy, c-format msgid "Unable to parse TLSA record string `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/hello/gnunet-hello.c:123 msgid "Call with name of HELLO file to modify.\n" msgstr "" #: src/hello/gnunet-hello.c:129 #, fuzzy, c-format msgid "Error accessing file `%s': %s\n" msgstr "创建用户出错" #: src/hello/gnunet-hello.c:137 #, c-format msgid "File `%s' is too big to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:144 #, c-format msgid "File `%s' is too small to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:154 src/hello/gnunet-hello.c:183 #, fuzzy, c-format msgid "Error opening file `%s': %s\n" msgstr "创建用户出错" #: src/hello/gnunet-hello.c:170 #, c-format msgid "Did not find well-formed HELLO in file `%s'\n" msgstr "" #: src/hello/gnunet-hello.c:195 #, fuzzy, c-format msgid "Error writing HELLO to file `%s': %s\n" msgstr "创建用户出错" #: src/hello/gnunet-hello.c:203 #, c-format msgid "Modified %u addresses \n" msgstr "" #: src/hello/hello.c:944 #, fuzzy msgid "Failed to parse HELLO message: missing expiration time\n" msgstr "ä¿å­˜é…置失败。" #: src/hello/hello.c:953 #, fuzzy msgid "Failed to parse HELLO message: invalid expiration time\n" msgstr "ä¿å­˜é…置失败。" #: src/hello/hello.c:963 #, fuzzy msgid "Failed to parse HELLO message: malformed\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/hello/hello.c:973 msgid "Failed to parse HELLO message: missing transport plugin\n" msgstr "" #: src/hello/hello.c:990 #, c-format msgid "Plugin `%s' not found\n" msgstr "" #: src/hello/hello.c:999 #, c-format msgid "Plugin `%s' does not support URIs yet\n" msgstr "" #: src/hello/hello.c:1018 #, fuzzy, c-format msgid "Failed to parse `%s' as an address for plugin `%s'\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/hostlist/gnunet-daemon-hostlist.c:259 msgid "" "None of the functions for the hostlist daemon were enabled. I have no " "reason to run!\n" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:308 msgid "advertise our hostlist to other peers" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:313 msgid "" "bootstrap using hostlists (it is highly recommended that you always use this " "option)" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:316 msgid "enable learning about hostlist servers from other peers" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:320 msgid "provide a hostlist server" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:335 msgid "GNUnet hostlist server and client" msgstr "" #: src/hostlist/hostlist-client.c:288 msgid "# bytes downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:309 src/hostlist/hostlist-client.c:339 msgid "# invalid HELLOs downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:312 src/hostlist/hostlist-client.c:342 #, c-format msgid "Invalid `%s' message received from hostlist at `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:330 msgid "# valid HELLOs downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:592 src/hostlist/hostlist-client.c:1333 msgid "# advertised hostlist URIs" msgstr "" #: src/hostlist/hostlist-client.c:622 #, c-format msgid "# advertised URI `%s' downloaded" msgstr "" #: src/hostlist/hostlist-client.c:664 #, c-format msgid "" "Advertised hostlist with URI `%s' could not be downloaded. Advertised URI " "gets dismissed.\n" msgstr "" #: src/hostlist/hostlist-client.c:802 #, c-format msgid "Timeout trying to download hostlist from `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:816 #, c-format msgid "Download limit of %u bytes exceeded, stopping download\n" msgstr "" #: src/hostlist/hostlist-client.c:836 #, fuzzy, c-format msgid "Download of hostlist from `%s' failed: `%s'\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/hostlist/hostlist-client.c:842 #, c-format msgid "Download of hostlist `%s' completed.\n" msgstr "" #: src/hostlist/hostlist-client.c:850 #, c-format msgid "Adding successfully tested hostlist `%s' datastore.\n" msgstr "" #: src/hostlist/hostlist-client.c:903 #, c-format msgid "Bootstrapping using hostlist at `%s'.\n" msgstr "" #: src/hostlist/hostlist-client.c:911 msgid "# hostlist downloads initiated" msgstr "" #: src/hostlist/hostlist-client.c:1040 src/hostlist/hostlist-client.c:1506 msgid "# milliseconds between hostlist downloads" msgstr "" #: src/hostlist/hostlist-client.c:1049 #, c-format msgid "Have %u/%u connections. Will consider downloading hostlist in %s\n" msgstr "" #: src/hostlist/hostlist-client.c:1109 src/hostlist/hostlist-client.c:1125 msgid "# active connections" msgstr "" #: src/hostlist/hostlist-client.c:1280 #, c-format msgid "Loading saved hostlist entries from file `%s' \n" msgstr "" #: src/hostlist/hostlist-client.c:1285 #, c-format msgid "Hostlist file `%s' does not exist\n" msgstr "" #: src/hostlist/hostlist-client.c:1296 #, fuzzy, c-format msgid "Could not open file `%s' for reading to load hostlists: %s\n" msgstr "无法解æžâ€œ%sâ€æ¥ç¡®å®šå·²æ–¹çš„ IP 地å€ï¼š%s\n" #: src/hostlist/hostlist-client.c:1329 #, c-format msgid "%u hostlist URIs loaded from file\n" msgstr "" #: src/hostlist/hostlist-client.c:1331 msgid "# hostlist URIs read from file" msgstr "" #: src/hostlist/hostlist-client.c:1376 #, fuzzy, c-format msgid "Could not open file `%s' for writing to save hostlists: %s\n" msgstr "无法解æžâ€œ%sâ€æ¥ç¡®å®šå·²æ–¹çš„ IP 地å€ï¼š%s\n" #: src/hostlist/hostlist-client.c:1381 #, c-format msgid "Writing %u hostlist URIs to `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:1405 src/hostlist/hostlist-client.c:1422 #, c-format msgid "Error writing hostlist URIs to file `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:1417 msgid "# hostlist URIs written to file" msgstr "" #: src/hostlist/hostlist-client.c:1471 msgid "Learning is enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1483 msgid "Learning is not enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1495 #, c-format msgid "" "Since learning is not enabled on this peer, hostlist file `%s' was removed\n" msgstr "" #: src/hostlist/hostlist-client.c:1499 #, c-format msgid "Hostlist file `%s' could not be removed\n" msgstr "" #: src/hostlist/hostlist-server.c:137 msgid "bytes in hostlist" msgstr "" #: src/hostlist/hostlist-server.c:161 msgid "expired addresses encountered" msgstr "" #: src/hostlist/hostlist-server.c:189 src/hostlist/hostlist-server.c:425 #: src/peerinfo-tool/gnunet-peerinfo.c:350 #: src/peerinfo-tool/gnunet-peerinfo.c:419 #: src/peerinfo-tool/gnunet-peerinfo.c:490 #: src/topology/gnunet-daemon-topology.c:925 #, c-format msgid "Error in communication with PEERINFO service: %s\n" msgstr "" #: src/hostlist/hostlist-server.c:210 msgid "HELLOs without addresses encountered (ignored)" msgstr "" #: src/hostlist/hostlist-server.c:224 msgid "bytes not included in hostlist (size limit)" msgstr "" #: src/hostlist/hostlist-server.c:268 #, c-format msgid "Refusing `%s' request to hostlist server\n" msgstr "" #: src/hostlist/hostlist-server.c:271 msgid "hostlist requests refused (not HTTP GET)" msgstr "" #: src/hostlist/hostlist-server.c:284 #, c-format msgid "Refusing `%s' request with %llu bytes of upload data\n" msgstr "" #: src/hostlist/hostlist-server.c:288 msgid "hostlist requests refused (upload data)" msgstr "" #: src/hostlist/hostlist-server.c:296 msgid "Could not handle hostlist request since I do not have a response yet\n" msgstr "" #: src/hostlist/hostlist-server.c:299 msgid "hostlist requests refused (not ready)" msgstr "" #: src/hostlist/hostlist-server.c:303 msgid "Received request for our hostlist\n" msgstr "" #: src/hostlist/hostlist-server.c:304 msgid "hostlist requests processed" msgstr "" #: src/hostlist/hostlist-server.c:346 msgid "# hostlist advertisements send" msgstr "" #: src/hostlist/hostlist-server.c:390 msgid "Advertisement message could not be queued by core\n" msgstr "" #: src/hostlist/hostlist-server.c:557 src/peerinfo-tool/gnunet-peerinfo.c:639 #: src/transport/gnunet-service-transport.c:1114 msgid "Could not access PEERINFO service. Exiting.\n" msgstr "" #: src/hostlist/hostlist-server.c:576 #, c-format msgid "Hostlist service starts on %s:%llu\n" msgstr "" #: src/hostlist/hostlist-server.c:590 #, c-format msgid "Address to obtain hostlist: `%s'\n" msgstr "" #: src/hostlist/hostlist-server.c:630 #, fuzzy, c-format msgid "`%s' is not a valid IP address! Ignoring BINDTOIP.\n" msgstr "“%sâ€ä¸å¯ç”¨ã€‚\n" #: src/hostlist/hostlist-server.c:673 #, c-format msgid "Could not start hostlist HTTP server on port %u\n" msgstr "" #: src/identity/gnunet-identity.c:165 #, fuzzy, c-format msgid "Failed to create ego: %s\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/identity/gnunet-identity.c:184 #, fuzzy, c-format msgid "Failed to set default ego: %s\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/identity/gnunet-identity.c:327 msgid "create ego NAME" msgstr "" #: src/identity/gnunet-identity.c:330 msgid "delete ego NAME " msgstr "" #: src/identity/gnunet-identity.c:333 msgid "display all egos" msgstr "" #: src/identity/gnunet-identity.c:336 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)" msgstr "" #: src/identity/gnunet-identity.c:339 msgid "run in monitor mode egos" msgstr "" #: src/identity/gnunet-identity.c:342 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)" msgstr "" #: src/identity/gnunet-identity.c:351 msgid "Maintain egos" msgstr "" #: src/identity/gnunet-service-identity.c:338 msgid "no default known" msgstr "" #: src/identity/gnunet-service-identity.c:362 msgid "default configured, but ego unknown (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:439 #: src/identity/gnunet-service-identity.c:670 #: src/identity/gnunet-service-identity.c:778 #, fuzzy, c-format msgid "Failed to write subsystem default identifier map to `%s'.\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/identity/gnunet-service-identity.c:446 msgid "Unknown ego specified for service (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:516 msgid "identifier already in use for another ego" msgstr "" #: src/identity/gnunet-service-identity.c:647 msgid "target name already exists" msgstr "" #: src/identity/gnunet-service-identity.c:686 #: src/identity/gnunet-service-identity.c:795 msgid "no matching ego found" msgstr "" #: src/identity/gnunet-service-identity.c:829 #, fuzzy, c-format msgid "Failed to parse ego information in `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/identity/gnunet-service-identity.c:902 #, fuzzy, c-format msgid "Failed to parse subsystem identity configuration file `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/identity/gnunet-service-identity.c:914 #, fuzzy, c-format msgid "Failed to create directory `%s' for storing egos\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/mesh/gnunet-mesh.c:357 #, fuzzy, c-format msgid "Invalid target `%s'\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/mesh/gnunet-mesh.c:607 #, fuzzy, c-format msgid "Invalid peer ID `%s'\n" msgstr "无效æ¡ç›®ã€‚\n" #: src/mesh/gnunet-mesh.c:650 #, fuzzy, c-format msgid "Invalid tunnel owner `%s'\n" msgstr "IP æ ¼å¼æ— æ•ˆï¼šâ€œ%sâ€\n" #: src/mesh/gnunet-mesh.c:716 msgid "You must NOT give a TARGETwhen using 'request all' options\n" msgstr "" #: src/mesh/gnunet-mesh.c:807 #, fuzzy msgid "provide information about a particular connection" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/mesh/gnunet-mesh.c:810 msgid "activate echo mode" msgstr "" #: src/mesh/gnunet-mesh.c:816 msgid "port to listen to (default; 0)" msgstr "" #: src/mesh/gnunet-mesh.c:819 src/mesh/gnunet-mesh.c:822 #, fuzzy msgid "provide information about all peers" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/mesh/gnunet-mesh.c:825 #, fuzzy msgid "provide information about a particular tunnel" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/mesh/gnunet-mesh.c:828 #, fuzzy msgid "provide information about all tunnels" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/mesh/gnunet-service-mesh_peer.c:390 msgid "Wrong CORE service\n" msgstr "" #: src/mysql/mysql.c:174 #, c-format msgid "Trying to use file `%s' for MySQL configuration.\n" msgstr "" #: src/mysql/mysql.c:181 #, fuzzy, c-format msgid "Could not access file `%s': %s\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/namecache/gnunet-namecache.c:109 #, fuzzy, c-format msgid "No records found for `%s'" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/namecache/gnunet-namecache.c:124 src/namestore/gnunet-namestore.c:397 #, c-format msgid "\tCorrupt or unsupported record of type %u\n" msgstr "" #: src/namecache/gnunet-namecache.c:185 #, fuzzy, c-format msgid "You must specify which zone should be accessed\n" msgstr "您必须指定一个昵称\n" #: src/namecache/gnunet-namecache.c:195 src/namestore/gnunet-namestore.c:695 #, fuzzy, c-format msgid "Invalid public key for reverse lookup `%s'\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/namecache/gnunet-namecache.c:203 #, fuzzy, c-format msgid "You must specify a name\n" msgstr "您必须指定一个接收方ï¼\n" #: src/namecache/gnunet-namecache.c:234 src/namestore/gnunet-namestore.c:931 msgid "name of the record to add/delete/display" msgstr "" #: src/namecache/gnunet-namecache.c:237 msgid "spezifies the public key of the zone to look in" msgstr "" #: src/namecache/gnunet-namecache.c:248 src/namestore/gnunet-namestore.c:963 #, fuzzy msgid "GNUnet zone manipulation tool" msgstr "GNUnet é…ç½®" #: src/namecache/namecache_api.c:276 msgid "Namecache failed to cache block" msgstr "" #: src/namecache/plugin_namecache_postgres.c:89 #: src/namestore/plugin_namestore_postgres.c:96 #, fuzzy msgid "Failed to create indices\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/namestore/gnunet-namestore.c:303 #, c-format msgid "Adding record failed: %s\n" msgstr "" #: src/namestore/gnunet-namestore.c:332 #, c-format msgid "Deleting record failed, record does not exist%s%s\n" msgstr "" #: src/namestore/gnunet-namestore.c:339 #, c-format msgid "Deleting record failed%s%s\n" msgstr "" #: src/namestore/gnunet-namestore.c:558 #, c-format msgid "No options given\n" msgstr "" #: src/namestore/gnunet-namestore.c:569 #: src/namestore/gnunet-namestore-fcfsd.c:970 #, fuzzy msgid "Failed to connect to namestore\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/namestore/gnunet-namestore.c:577 src/namestore/gnunet-namestore.c:586 #: src/namestore/gnunet-namestore.c:603 src/namestore/gnunet-namestore.c:625 #: src/namestore/gnunet-namestore.c:665 #, fuzzy, c-format msgid "Missing option `%s' for operation `%s'\n" msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #: src/namestore/gnunet-namestore.c:578 src/namestore/gnunet-namestore.c:587 #: src/namestore/gnunet-namestore.c:604 src/namestore/gnunet-namestore.c:626 msgid "add" msgstr "" #: src/namestore/gnunet-namestore.c:595 #, fuzzy, c-format msgid "Unsupported type `%s'\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/namestore/gnunet-namestore.c:615 #, c-format msgid "Value `%s' invalid for record type `%s'\n" msgstr "" #: src/namestore/gnunet-namestore.c:651 #, fuzzy, c-format msgid "Invalid time format `%s'\n" msgstr "IP æ ¼å¼æ— æ•ˆï¼šâ€œ%sâ€\n" #: src/namestore/gnunet-namestore.c:666 msgid "del" msgstr "" #: src/namestore/gnunet-namestore.c:715 #: src/peerinfo-tool/gnunet-peerinfo.c:723 #, fuzzy, c-format msgid "Invalid URI `%s'\n" msgstr "无效æ¡ç›®ã€‚\n" #: src/namestore/gnunet-namestore.c:750 #, fuzzy, c-format msgid "Invalid nick `%s'\n" msgstr "无效æ¡ç›®ã€‚\n" #: src/namestore/gnunet-namestore.c:790 #, c-format msgid "Ego `%s' not known to identity service\n" msgstr "" #: src/namestore/gnunet-namestore.c:817 #, c-format msgid "No default ego configured in identity service\n" msgstr "" #: src/namestore/gnunet-namestore.c:853 #, fuzzy, c-format msgid "Identity service is not running\n" msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #: src/namestore/gnunet-namestore.c:865 #, fuzzy, c-format msgid "Cannot connect to identity service\n" msgstr "无法连接到 %s:%u:%s\n" #: src/namestore/gnunet-namestore.c:913 msgid "add record" msgstr "" #: src/namestore/gnunet-namestore.c:916 msgid "delete record" msgstr "" #: src/namestore/gnunet-namestore.c:919 msgid "display records" msgstr "" #: src/namestore/gnunet-namestore.c:922 msgid "" "expiration time for record to use (for adding only), \"never\" is possible" msgstr "" #: src/namestore/gnunet-namestore.c:925 #, fuzzy msgid "set the desired nick name for the zone" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/namestore/gnunet-namestore.c:928 #, fuzzy msgid "monitor changes in the namestore" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/namestore/gnunet-namestore.c:934 #, fuzzy msgid "determine our name for the given PKEY" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/namestore/gnunet-namestore.c:937 msgid "type of the record to add/delete/display" msgstr "" #: src/namestore/gnunet-namestore.c:940 msgid "URI to import into our zone" msgstr "" #: src/namestore/gnunet-namestore.c:943 msgid "value of the record to add/delete" msgstr "" #: src/namestore/gnunet-namestore.c:946 msgid "create or list public record" msgstr "" #: src/namestore/gnunet-namestore.c:949 msgid "" "create shadow record (only valid if all other records of the same type have " "expired" msgstr "" #: src/namestore/gnunet-namestore.c:952 msgid "name of the ego controlling the zone" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:464 #, fuzzy, c-format msgid "Unsupported form value `%s'\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/namestore/gnunet-namestore-fcfsd.c:491 #, fuzzy, c-format msgid "Failed to create record for domain `%s': %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/namestore/gnunet-namestore-fcfsd.c:525 #, c-format msgid "Found existing name `%s' for the given key\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:534 msgid "Error when mapping zone to name\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:596 #, c-format msgid "Found %u existing records for domain `%s'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:652 #, fuzzy, c-format msgid "Failed to create page for `%s'\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/namestore/gnunet-namestore-fcfsd.c:668 #, fuzzy, c-format msgid "Failed to setup post processor for `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/namestore/gnunet-namestore-fcfsd.c:704 msgid "Domain name must not contain `.'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:712 msgid "Domain name must not contain `+'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:910 msgid "No ego configured for `fcfsd` subsystem\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:936 #, fuzzy msgid "Failed to start HTTP server\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/namestore/gnunet-namestore-fcfsd.c:978 #, fuzzy msgid "Failed to connect to identity\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/namestore/gnunet-namestore-fcfsd.c:1011 msgid "GNU Name System First Come First Serve name registration service" msgstr "" #: src/namestore/gnunet-service-namestore.c:655 #, fuzzy, c-format msgid "Failed to replicate block in namecache: %s\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/namestore/namestore_api.c:275 msgid "Namestore failed to store record\n" msgstr "" #: src/nat/gnunet-nat-server.c:279 #, c-format msgid "Please pass valid port number as the first argument! (got `%s')\n" msgstr "" #: src/nat/gnunet-nat-server.c:321 msgid "GNUnet NAT traversal test helper daemon" msgstr "" #: src/nat/nat_auto.c:170 msgid "NAT traversal with ICMP Server timed out.\n" msgstr "" #: src/nat/nat_auto.c:203 msgid "NAT traversal with ICMP Server succeeded.\n" msgstr "" #: src/nat/nat_auto.c:204 msgid "NAT traversal with ICMP Server failed.\n" msgstr "" #: src/nat/nat_auto.c:225 msgid "Testing connection reversal with ICMP server.\n" msgstr "" #: src/nat/nat_auto.c:274 #, c-format msgid "Detected external IP `%s'\n" msgstr "" #: src/nat/nat_auto.c:344 msgid "This system has a global IPv6 address, setting IPv6 to supported.\n" msgstr "" #: src/nat/nat_auto.c:360 #, fuzzy, c-format msgid "Detected internal network address `%s'.\n" msgstr "GNUnet 现在使用 IP åœ°å€ %s。\n" #: src/nat/nat_auto.c:413 msgid "upnpc found, enabling its use\n" msgstr "" #: src/nat/nat_auto.c:414 msgid "upnpc not found\n" msgstr "" #: src/nat/nat_auto.c:447 msgid "gnunet-helper-nat-server found, testing it\n" msgstr "" #: src/nat/nat_auto.c:448 msgid "No working gnunet-helper-nat-server found\n" msgstr "" #: src/nat/nat_auto.c:482 msgid "gnunet-helper-nat-client found, enabling it\n" msgstr "" #: src/nat/nat_auto.c:483 msgid "gnunet-helper-nat-client not found or behind NAT, disabling it\n" msgstr "" #: src/nat/nat.c:867 #, c-format msgid "gnunet-helper-nat-server generated malformed address `%s'\n" msgstr "" #: src/nat/nat.c:917 #, fuzzy, c-format msgid "Failed to start %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/nat/nat.c:1205 msgid "malformed" msgstr "" #: src/nat/nat.c:1276 src/nat/nat.c:1288 #, c-format msgid "" "Configuration requires `%s', but binary is not installed properly (SUID bit " "not set). Option disabled.\n" msgstr "" #: src/nat/nat.c:1426 msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n" msgstr "" #: src/nat/nat.c:1442 #, c-format msgid "Running gnunet-helper-nat-client %s %s %u\n" msgstr "" #: src/nat/nat_mini.c:155 msgid "no valid address was returned by `external-ip'" msgstr "" #: src/nat/nat_mini.c:175 msgid "`external-ip' command not found" msgstr "" #: src/nat/nat_mini.c:201 msgid "`external-ip' command not found\n" msgstr "" #: src/nat/nat_mini.c:366 #, fuzzy msgid "Failed to run `upnpc` command" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/nat/nat_mini.c:512 msgid "`upnpc' command took too long, process killed" msgstr "" #: src/nat/nat_mini.c:540 msgid "`upnpc' command failed to establish port mapping" msgstr "" #: src/nat/nat_mini.c:604 msgid "`upnpc' command not found\n" msgstr "" #: src/nat/nat_mini.c:608 msgid "`upnpc` command not found" msgstr "" #: src/nat/nat_test.c:351 msgid "Failed to connect to `gnunet-nat-server'\n" msgstr "" #: src/nat/nat_test.c:423 #, c-format msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n" msgstr "" #: src/nse/gnunet-nse.c:117 #, fuzzy msgid "NSE service is not running\n" msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #: src/nse/gnunet-nse.c:122 msgid "Error while checking if NSE service is running or not\n" msgstr "" #: src/nse/gnunet-nse.c:168 msgid "Show network size estimates from NSE service." msgstr "" #: src/nse/gnunet-nse-profiler.c:858 msgid "limit to the number of connections to NSE services, 0 for none" msgstr "" #: src/nse/gnunet-nse-profiler.c:861 msgid "name of the file for writing connection information and statistics" msgstr "" #: src/nse/gnunet-nse-profiler.c:864 src/testbed/gnunet-testbed-profiler.c:306 msgid "name of the file with the login information for the testbed" msgstr "" #: src/nse/gnunet-nse-profiler.c:867 msgid "name of the file for writing the main results" msgstr "" #: src/nse/gnunet-nse-profiler.c:870 msgid "Number of peers to run in each round, separated by commas" msgstr "" #: src/nse/gnunet-nse-profiler.c:876 msgid "delay between rounds" msgstr "" #: src/nse/gnunet-nse-profiler.c:885 #, fuzzy msgid "Measure quality and performance of the NSE service." msgstr "无法访问该æœåŠ¡" #: src/nse/gnunet-service-nse.c:1517 #: src/revocation/gnunet-service-revocation.c:789 src/util/gnunet-scrypt.c:248 #, fuzzy msgid "Value is too large.\n" msgstr "值ä¸åœ¨åˆæ³•范围内。" #: src/peerinfo/gnunet-service-peerinfo.c:215 #, c-format msgid "Removing expired address of transport `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:352 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s': %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/peerinfo/gnunet-service-peerinfo.c:371 #: src/peerinfo/gnunet-service-peerinfo.c:388 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/peerinfo/gnunet-service-peerinfo.c:466 msgid "# peers known" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:503 #, c-format msgid "" "File `%s' in directory `%s' does not match naming convention. Removed.\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:653 #, fuzzy, c-format msgid "Scanning directory `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/peerinfo/gnunet-service-peerinfo.c:658 #, c-format msgid "Still no peers found in `%s'!\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:994 #, fuzzy, c-format msgid "Cleaning up directory `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/peerinfo/gnunet-service-peerinfo.c:1287 #, c-format msgid "Importing HELLOs from `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:1298 msgid "Skipping import of included HELLOs\n" msgstr "" #: src/peerinfo/peerinfo_api.c:236 msgid "aborted due to explicit disconnect request" msgstr "" #: src/peerinfo/peerinfo_api.c:356 #, fuzzy msgid "failed to transmit request (service down?)" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/peerinfo/peerinfo_api.c:506 msgid "Failed to receive response from `PEERINFO' service." msgstr "" #: src/peerinfo/peerinfo_api.c:547 src/peerinfo/peerinfo_api.c:566 #: src/peerinfo/peerinfo_api.c:581 src/peerinfo/peerinfo_api.c:592 #: src/peerinfo/peerinfo_api.c:603 #, fuzzy msgid "Received invalid message from `PEERINFO' service." msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/peerinfo/peerinfo_api.c:678 #, fuzzy msgid "Timeout transmitting iteration request to `PEERINFO' service." msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/peerinfo/peerinfo_api_notify.c:268 #, fuzzy, c-format msgid "Could not connect to `%s' service.\n" msgstr "无法连接到 %s:%u:%s\n" #: src/peerinfo-tool/gnunet-peerinfo.c:232 #, fuzzy, c-format msgid "%sPeer `%s'\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/peerinfo-tool/gnunet-peerinfo.c:239 #, c-format msgid "\tExpires: %s \t %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:428 #, fuzzy, c-format msgid "Failure: Did not receive %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/peerinfo-tool/gnunet-peerinfo.c:436 #, c-format msgid "Failure: Received invalid %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:445 #, fuzzy, c-format msgid "Failed to write HELLO with %u bytes to file `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/peerinfo-tool/gnunet-peerinfo.c:458 #, c-format msgid "Wrote %s HELLO containing %u addresses with %u bytes to file `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:522 #, c-format msgid "Failure adding HELLO: %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:633 #, fuzzy, c-format msgid "Service `%s' is not running, please start GNUnet\n" msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #: src/peerinfo-tool/gnunet-peerinfo.c:654 src/util/gnunet-scrypt.c:224 #, c-format msgid "Loading hostkey from `%s' failed.\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:745 #, c-format msgid "I am peer `%s'.\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:789 msgid "don't resolve host names" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:792 msgid "output only the identity strings" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:795 msgid "include friend-only information" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:798 msgid "output our own identity only" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:801 #, fuzzy msgid "list all known peers" msgstr "列出所有网络适é…器" #: src/peerinfo-tool/gnunet-peerinfo.c:804 msgid "dump hello to file" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:807 msgid "also output HELLO uri(s)" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:810 msgid "add given HELLO uri to the database" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:821 #, fuzzy msgid "Print information about peers." msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:105 #: src/transport/gnunet-service-transport_plugins.c:128 #, c-format msgid "Starting transport plugins `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:109 #: src/transport/gnunet-service-transport_plugins.c:133 #, c-format msgid "Loading `%s' transport plugin\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:129 #: src/transport/gnunet-service-transport_plugins.c:165 #, fuzzy, c-format msgid "Failed to load transport plugin for `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/postgres/postgres.c:59 #, fuzzy, c-format msgid "`%s:%s' failed at %s:%d with error: %s" msgstr "“%sâ€äºŽ %s:%d 处失败,错误为:%s\n" #: src/postgres/postgres.c:148 #, fuzzy, c-format msgid "Unable to initialize Postgres: %s" msgstr "无法åˆå§‹åŒ– SQLite:%s。\n" #: src/psycstore/gnunet-service-psycstore.c:200 #, fuzzy msgid "Failed to store membership information!\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/psycstore/gnunet-service-psycstore.c:224 #, fuzzy msgid "Failed to test membership!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/psycstore/gnunet-service-psycstore.c:246 #, fuzzy msgid "Failed to store fragment!\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/psycstore/gnunet-service-psycstore.c:272 #, fuzzy msgid "Failed to get fragment!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/psycstore/gnunet-service-psycstore.c:299 #, fuzzy msgid "Failed to get message!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/psycstore/gnunet-service-psycstore.c:328 #, fuzzy msgid "Failed to get message fragment!\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/psycstore/gnunet-service-psycstore.c:356 #, fuzzy msgid "Failed to get master counters!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/psycstore/gnunet-service-psycstore.c:392 #: src/psycstore/gnunet-service-psycstore.c:465 msgid "Tried to set invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:408 #, fuzzy msgid "Failed to begin modifying state!\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/psycstore/gnunet-service-psycstore.c:431 #, fuzzy, c-format msgid "Unknown operator: %c\n" msgstr "未知错误" #: src/psycstore/gnunet-service-psycstore.c:441 #, fuzzy msgid "Failed to end modifying state!\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/psycstore/gnunet-service-psycstore.c:479 #, fuzzy msgid "Failed to begin synchronizing state!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/psycstore/gnunet-service-psycstore.c:495 #, fuzzy msgid "Failed to end synchronizing state!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/psycstore/gnunet-service-psycstore.c:515 #: src/psycstore/gnunet-service-psycstore.c:534 #, fuzzy msgid "Failed to reset state!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/psycstore/gnunet-service-psycstore.c:557 #: src/psycstore/gnunet-service-psycstore.c:608 msgid "Tried to get invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:584 #: src/psycstore/gnunet-service-psycstore.c:623 #, fuzzy msgid "Failed to get state variable!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/psycstore/plugin_psycstore_sqlite.c:60 #, fuzzy, c-format msgid "`%s' failed at %s:%d with error: %s (%d)\n" msgstr "“%sâ€äºŽ %s:%d 处失败,错误为:%s\n" #: src/psycstore/plugin_psycstore_sqlite.c:253 #, fuzzy, c-format msgid "" "Error preparing SQL query: %s\n" " %s\n" msgstr "创建用户出错" #: src/psycstore/plugin_psycstore_sqlite.c:276 #, fuzzy, c-format msgid "" "Error executing SQL query: %s\n" " %s\n" msgstr "创建用户出错" #: src/psycstore/plugin_psycstore_sqlite.c:1796 #, fuzzy msgid "SQLite database running\n" msgstr "sqlite æ•°æ®ä»“库" #: src/pt/gnunet-daemon-pt.c:482 msgid "Failed to pack DNS request. Dropping.\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:488 msgid "# DNS requests mapped to VPN" msgstr "" #: src/pt/gnunet-daemon-pt.c:541 msgid "# DNS records modified" msgstr "" #: src/pt/gnunet-daemon-pt.c:717 msgid "# DNS replies intercepted" msgstr "" #: src/pt/gnunet-daemon-pt.c:723 msgid "Failed to parse DNS request. Dropping.\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:826 msgid "# DNS requests dropped (timeout)" msgstr "" #: src/pt/gnunet-daemon-pt.c:883 msgid "# DNS requests intercepted" msgstr "" #: src/pt/gnunet-daemon-pt.c:888 msgid "# DNS requests dropped (DNS mesh channel down)" msgstr "" #: src/pt/gnunet-daemon-pt.c:896 msgid "# DNS requests dropped (malformed)" msgstr "" #: src/pt/gnunet-daemon-pt.c:969 msgid "# DNS replies received" msgstr "" #: src/pt/gnunet-daemon-pt.c:985 msgid "# DNS replies dropped (too late?)" msgstr "" #: src/pt/gnunet-daemon-pt.c:1261 src/pt/gnunet-daemon-pt.c:1270 #: src/pt/gnunet-daemon-pt.c:1290 src/pt/gnunet-daemon-pt.c:1301 #: src/pt/gnunet-daemon-pt.c:1310 #, fuzzy, c-format msgid "Failed to connect to %s service. Exiting.\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/pt/gnunet-daemon-pt.c:1347 msgid "Daemon to run to perform IP protocol translation to GNUnet" msgstr "" #: src/regex/gnunet-daemon-regexprofiler.c:270 #: src/regex/gnunet-regex-simulation-profiler.c:659 #, fuzzy, c-format msgid "%s service is lacking key configuration settings (%s). Exiting.\n" msgstr "ç«‹å³ä¿å­˜é…置?" #: src/regex/gnunet-daemon-regexprofiler.c:380 msgid "Daemon to announce regular expressions for the peer using mesh." msgstr "" #: src/regex/gnunet-regex-profiler.c:1288 msgid "No configuration file given. Exiting\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1299 #, fuzzy msgid "Configuration option \"regex_prefix\" missing. Exiting\n" msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #: src/regex/gnunet-regex-profiler.c:1328 #: src/regex/gnunet-regex-simulation-profiler.c:622 #, c-format msgid "No policy directory specified on command line. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1334 #: src/regex/gnunet-regex-simulation-profiler.c:629 #, c-format msgid "Specified policies directory does not exist. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1341 #, fuzzy, c-format msgid "No files found in `%s'\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/regex/gnunet-regex-profiler.c:1350 msgid "No search strings file given. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1370 #, fuzzy msgid "Error loading search strings. Exiting.\n" msgstr "创建用户出错" #: src/regex/gnunet-regex-profiler.c:1455 #, fuzzy msgid "name of the file for writing statistics" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/regex/gnunet-regex-profiler.c:1458 msgid "wait TIMEOUT before ending the experiment" msgstr "" #: src/regex/gnunet-regex-profiler.c:1461 msgid "directory with policy files" msgstr "" #: src/regex/gnunet-regex-profiler.c:1464 #, fuzzy msgid "name of file with input strings" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/regex/gnunet-regex-profiler.c:1467 #, fuzzy msgid "name of file with hosts' names" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/regex/gnunet-regex-profiler.c:1479 msgid "Profiler for regex" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:689 msgid "name of the table to write DFAs" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:692 msgid "maximum path compression length" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:705 msgid "Profiler for regex library" msgstr "" #: src/regex/regex_api.c:131 #, fuzzy, c-format msgid "Regex `%s' is too long!\n" msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #: src/revocation/gnunet-revocation.c:126 #, c-format msgid "Key `%s' is valid\n" msgstr "" #: src/revocation/gnunet-revocation.c:131 #, fuzzy, c-format msgid "Key `%s' has been revoked\n" msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #: src/revocation/gnunet-revocation.c:137 #, fuzzy msgid "Internal error\n" msgstr "未知错误。\n" #: src/revocation/gnunet-revocation.c:163 #, c-format msgid "Key for ego `%s' is still valid, revocation failed (!)\n" msgstr "" #: src/revocation/gnunet-revocation.c:168 msgid "Revocation failed (!)\n" msgstr "" #: src/revocation/gnunet-revocation.c:173 #, c-format msgid "Key for ego `%s' has been successfully revoked\n" msgstr "" #: src/revocation/gnunet-revocation.c:178 msgid "Revocation successful.\n" msgstr "" #: src/revocation/gnunet-revocation.c:183 msgid "Internal error, key revocation might have failed\n" msgstr "" #: src/revocation/gnunet-revocation.c:294 #, c-format msgid "Revocation certificate for `%s' stored in `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:324 #, c-format msgid "Ego `%s' not found.\n" msgstr "" #: src/revocation/gnunet-revocation.c:345 #, c-format msgid "Error: revocation certificate in `%s' is not for `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:365 msgid "Revocation certificate ready\n" msgstr "" #: src/revocation/gnunet-revocation.c:375 msgid "Revocation certificate not ready, calculating proof of work\n" msgstr "" #: src/revocation/gnunet-revocation.c:407 #, fuzzy, c-format msgid "Public key `%s' malformed\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/revocation/gnunet-revocation.c:421 msgid "" "Testing and revoking at the same time is not allowed, only executing test.\n" msgstr "" #: src/revocation/gnunet-revocation.c:441 #, fuzzy msgid "No filename to store revocation certificate given.\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/revocation/gnunet-revocation.c:463 #, fuzzy, c-format msgid "Failed to read revocation certificate from `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/revocation/gnunet-revocation.c:488 #, fuzzy msgid "No action specified. Nothing to do.\n" msgstr "没有指定接å£ï¼Œå°†ä½¿ç”¨é»˜è®¤ã€‚\n" #: src/revocation/gnunet-revocation.c:504 msgid "use NAME for the name of the revocation file" msgstr "" #: src/revocation/gnunet-revocation.c:507 msgid "" "revoke the private key associated for the the private key associated with " "the ego NAME " msgstr "" #: src/revocation/gnunet-revocation.c:510 msgid "actually perform revocation, otherwise we just do the precomputation" msgstr "" #: src/revocation/gnunet-revocation.c:513 msgid "test if the public key KEY has been revoked" msgstr "" #: src/revocation/gnunet-service-revocation.c:272 msgid "Duplicate revocation received from peer. Ignored.\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:434 #, c-format msgid "Error computing revocation set union with %s\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:486 msgid "SET service crashed, terminating revocation service\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:812 #, fuzzy msgid "Could not open revocation database file!" msgstr "无法连接到 %s:%u:%s\n" #: src/scalarproduct/gnunet-scalarproduct.c:225 #, fuzzy msgid "You must specify at least one message ID to check!\n" msgstr "您必须指定一个昵称\n" #: src/scalarproduct/gnunet-scalarproduct.c:232 msgid "This program needs a session identifier for comparing vectors.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:239 msgid "Please give a session key for --input_key!\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:251 #, c-format msgid "" "Tried to set initiator mode, as peer ID was given. However, `%s' is not a " "valid peer identifier.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:278 #: src/scalarproduct/gnunet-scalarproduct.c:314 #, fuzzy, c-format msgid "Could not convert `%s' to int32_t.\n" msgstr "无法连接到 %s:%u:%s\n" #: src/scalarproduct/gnunet-scalarproduct.c:286 msgid "Need elements to compute the vectorproduct, got none.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:346 #, fuzzy, c-format msgid "Could not convert `%s' to integer.\n" msgstr "无法连接到 %s:%u:%s\n" #: src/scalarproduct/gnunet-scalarproduct.c:407 msgid "" "A comma separated list of elements to compare as vector with our remote peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:410 msgid "" "A comma separated mask to select which elements should actually be compared." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:413 msgid "" "[Optional] peer to calculate our scalarproduct with. If this parameter is " "not given, the service will wait for a remote peer to compute the request." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:416 msgid "Transaction ID shared with peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:425 msgid "Calculate the Vectorproduct with a GNUnet peer." msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:541 #, fuzzy, c-format msgid "Client (%p) disconnected from us.\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:613 #: src/scalarproduct/gnunet-service-scalarproduct.c:702 #, fuzzy, c-format msgid "Could not send message to client (%p)!\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:619 #, c-format msgid "Sending session-end notification to client (%p) for session %s\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:712 #, c-format msgid "Sent result to client (%p), this session (%s) has ended!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:766 #: src/scalarproduct/gnunet-service-scalarproduct.c:855 msgid "Could not send service-response message via mesh!)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1028 #, c-format msgid "Failed to communicate with `%s', scalar product calculation aborted.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1099 #: src/scalarproduct/gnunet-service-scalarproduct.c:1208 msgid "Transmitting service request.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1108 #, fuzzy msgid "Could not send service-request multipart message to channel!\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1147 #, fuzzy, c-format msgid "Successfully created new channel to peer (%s)!\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1217 #, fuzzy msgid "Could not send message to channel!\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1274 msgid "Too short message received from client!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1287 msgid "Invalid message received from client, session information incorrect!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1298 #, c-format msgid "" "Duplicate session information received, cannot create new session with key `" "%s'\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1318 #, c-format msgid "" "Got client-request-session with key %s, preparing channel to remote " "service.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1354 #, c-format msgid "Creating new channel for session with key %s.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1399 #, c-format msgid "" "Got client-responder-session with key %s and a matching service-request-" "session set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1409 #, c-format msgid "" "Got client-responder-session with key %s but NO matching service-request-" "session set, queuing element for later use.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1439 #, fuzzy, c-format msgid "New incoming channel from peer %s.\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1471 #, c-format msgid "Peer disconnected, terminating session %s with peer (%s)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1672 #: src/scalarproduct/gnunet-service-scalarproduct.c:1814 #, c-format msgid "Got session with key %s and a matching element set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1681 #: src/scalarproduct/gnunet-service-scalarproduct.c:1821 #, c-format msgid "Got session with key %s without a matching element set, queueing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1771 #, c-format msgid "" "Got message with duplicate session key (`%s'), ignoring service request.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2014 msgid "Shutting down, initiating cleanup.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2100 #, fuzzy msgid "Connect to MESH failed\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:2104 msgid "Mesh initialized\n" msgstr "" #: src/scalarproduct/scalarproduct_api.c:246 msgid "# SUC responder result messages received" msgstr "" #: src/scalarproduct/scalarproduct_api.c:300 msgid "# bytes sent to scalarproduct" msgstr "" #: src/scalarproduct/scalarproduct_api.c:345 #: src/scalarproduct/scalarproduct_api.c:440 #, fuzzy msgid "Failed to connect to the scalarproduct service\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/scalarproduct/scalarproduct_api.c:353 #: src/scalarproduct/scalarproduct_api.c:448 #, fuzzy msgid "Failed to send a message to the statistics service\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/scalarproduct/scalarproduct_api.c:387 #: src/scalarproduct/scalarproduct_api.c:485 #, fuzzy msgid "Failed to send a message to the scalarproduct service\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/secretsharing/gnunet-secretsharing-profiler.c:538 msgid "dkg start delay" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:541 msgid "dkg timeout" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:544 msgid "threshold" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:547 msgid "also profile decryption" msgstr "" #: src/set/gnunet-service-set.c:1431 #, fuzzy msgid "Could not connect to mesh service\n" msgstr "无法连接到 %s:%u:%s\n" #: src/set/gnunet-set-ibf-profiler.c:221 #, fuzzy msgid "number of element in set A-B" msgstr "迭代次数" #: src/set/gnunet-set-ibf-profiler.c:224 #, fuzzy msgid "number of element in set B-A" msgstr "迭代次数" #: src/set/gnunet-set-ibf-profiler.c:227 msgid "number of common elements in A and B" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:230 msgid "hash num" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:233 msgid "ibf size" msgstr "" #: src/set/gnunet-set-profiler.c:295 msgid "oeration to execute" msgstr "" #: src/statistics/gnunet-service-statistics.c:280 #, c-format msgid "Loading %llu bytes of statistics from `%s'\n" msgstr "" #: src/statistics/gnunet-service-statistics.c:346 #, c-format msgid "Wrote %llu bytes of statistics to `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:140 #, fuzzy msgid "Failed to obtain statistics.\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/statistics/gnunet-statistics.c:142 #, fuzzy, c-format msgid "Failed to obtain statistics from host `%s:%llu'\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/statistics/gnunet-statistics.c:189 msgid "Missing argument: subsystem \n" msgstr "" #: src/statistics/gnunet-statistics.c:195 msgid "Missing argument: name\n" msgstr "" #: src/statistics/gnunet-statistics.c:226 #, c-format msgid "No subsystem or name given\n" msgstr "" #: src/statistics/gnunet-statistics.c:234 #, fuzzy, c-format msgid "Failed to initialize watch routine\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/statistics/gnunet-statistics.c:261 #, fuzzy, c-format msgid "Trying to connect to remote host, but service `%s' is not running\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/statistics/gnunet-statistics.c:269 #, fuzzy, c-format msgid "A port is required to connect to host `%s'\n" msgstr "无法连接到 %s:%u:%s\n" #: src/statistics/gnunet-statistics.c:276 #, c-format msgid "A port has to be between 1 and 65535 to connect to host `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:308 #, fuzzy, c-format msgid "Invalid argument `%s'\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/statistics/gnunet-statistics.c:334 msgid "limit output to statistics for the given NAME" msgstr "" #: src/statistics/gnunet-statistics.c:337 msgid "make the value being set persistent" msgstr "" #: src/statistics/gnunet-statistics.c:340 msgid "limit output to the given SUBSYSTEM" msgstr "" #: src/statistics/gnunet-statistics.c:343 msgid "just print the statistics value" msgstr "" #: src/statistics/gnunet-statistics.c:346 msgid "watch value continuously" msgstr "" #: src/statistics/gnunet-statistics.c:349 msgid "connect to remote host" msgstr "" #: src/statistics/gnunet-statistics.c:352 msgid "port for remote host" msgstr "" #: src/statistics/gnunet-statistics.c:364 msgid "Print statistics about GNUnet operations." msgstr "" #: src/statistics/statistics_api.c:519 #, fuzzy msgid "Could not save some persistent statistics\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/statistics/statistics_api.c:1090 msgid "" "Failed to receive acknowledgement from statistics service, some statistics " "might have been lost!\n" msgstr "" #: src/testbed/generate-underlay-topology.c:223 msgid "Need atleast 2 arguments\n" msgstr "" #: src/testbed/generate-underlay-topology.c:228 msgid "Database filename missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:235 msgid "Topology string missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:240 #, fuzzy, c-format msgid "Invalid topology: %s\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/testbed/generate-underlay-topology.c:252 #, c-format msgid "An argument is missing for given topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:258 #, fuzzy, c-format msgid "Invalid argument `%s' given as topology argument\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/testbed/generate-underlay-topology.c:266 #, c-format msgid "Filename argument missing for topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:280 #, c-format msgid "Second argument for topology `%s' is missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:286 #, fuzzy, c-format msgid "Invalid argument `%s'; expecting unsigned int\n" msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #: src/testbed/generate-underlay-topology.c:335 #: src/testbed/gnunet-testbed-profiler.c:293 msgid "create COUNT number of peers" msgstr "" #: src/testbed/generate-underlay-topology.c:344 msgid "" "Generates SQLite3 database representing a given underlay topology.\n" "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" "The following options are available for TOPO followed by TOPOOPTS if " "applicable:\n" "\t LINE\n" "\t RING\n" "\t RANDOM \n" "\t SMALL_WORLD \n" "\t SMALL_WORLD_RING \n" "\t CLIQUE\n" "\t 2D_TORUS\n" "\t SCALE_FREE \n" "\t FROM_FILE \n" "TOPOOPTS:\n" "\t num_rnd_links: The number of random links\n" "\t cap: the maximum number of links a node can have\n" "\t m: the number of links a node should have while joining the network\n" "\t filename: the path of the file which contains topology information\n" "NOTE: the format of the above file is descibed here: https://www.gnunet.org/" "content/topology-file-format\n" msgstr "" #: src/testbed/gnunet-daemon-latency-logger.c:325 msgid "Daemon to log latency values of connections to neighbours" msgstr "" #: src/testbed/gnunet-daemon-testbed-blacklist.c:264 msgid "" "Daemon to restrict incoming transport layer connections during testbed " "deployments" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:235 src/testing/list-keys.c:50 #: src/testing/testing.c:293 src/util/gnunet-ecc.c:217 #, c-format msgid "Incorrect hostkey file format: %s\n" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:474 msgid "Daemon to restrict underlay network in testbed deployments" msgstr "" #: src/testbed/gnunet-service-testbed_cpustatus.c:730 #, c-format msgid "" "Cannot open %s for writing load statistics. Not logging load statistics\n" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1015 #, fuzzy msgid "Misconfiguration (can't connect to the ARM service)" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/testbed/gnunet-service-testbed_peers.c:1021 msgid "Request doesn't fit into a message" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1059 #, c-format msgid "%s service can't be started because ARM is shutting down" msgstr "" #: src/testbed/gnunet_testbed_mpi_spawn.c:125 msgid "Waiting for child to exit.\n" msgstr "" #: src/testbed/gnunet_testbed_mpi_spawn.c:247 #, fuzzy, c-format msgid "Spawning process `%s'\n" msgstr "å¸è½½ GNUnet æœåŠ¡" #: src/testbed/gnunet-testbed-profiler.c:267 #, fuzzy, c-format msgid "Exiting as the number of peers is %u\n" msgstr "增加 TCP/IP 的最大连接数" #: src/testbed/gnunet-testbed-profiler.c:296 msgid "tolerate COUNT number of continious timeout failures" msgstr "" #: src/testbed/gnunet-testbed-profiler.c:299 msgid "" "run profiler in non-interactive mode where upon testbed setup the profiler " "does not wait for a keystroke but continues to run until a termination " "signal is received" msgstr "" #: src/testbed/testbed_api_hosts.c:415 #, c-format msgid "Hosts file %s not found\n" msgstr "" #: src/testbed/testbed_api_hosts.c:423 #, c-format msgid "Hosts file %s has no data\n" msgstr "" #: src/testbed/testbed_api_hosts.c:430 #, c-format msgid "Hosts file %s cannot be read\n" msgstr "" #: src/testbed/testbed_api_hosts.c:570 #, c-format msgid "The function %s is only available when compiled with (--with-ll)\n" msgstr "" #: src/testbed/testbed_api_hosts.c:1586 #, fuzzy, c-format msgid "Adding host %u failed with error: %s\n" msgstr "“%sâ€ä»¥é”™è¯¯ç  %d 失败:%s\n" #: src/testbed/testbed_api_testbed.c:819 msgid "Linking controllers failed. Exiting" msgstr "" #: src/testbed/testbed_api_testbed.c:988 #, c-format msgid "Host registration failed for a host. Error: %s\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1054 msgid "Controller crash detected. Shutting down.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1143 #, c-format msgid "Host %s cannot start testbed\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1147 msgid "Testbed cannot be started on localhost\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1185 msgid "Cannot start the master controller" msgstr "" #: src/testbed/testbed_api_testbed.c:1203 msgid "Shutting down testbed due to timeout while setup.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1263 msgid "No hosts loaded from LoadLeveler. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1275 msgid "No hosts loaded. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1299 msgid "Specified topology must be supported by testbed" msgstr "" #: src/testbed/testbed_api_testbed.c:1349 #, c-format msgid "" "Maximum number of edges a peer can have in a scale free topology cannot be " "more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_testbed.c:1365 #, c-format msgid "" "The number of edges that can established when adding a new node to scale " "free topology cannot be more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_topology.c:960 #, c-format msgid "Topology file %s not found\n" msgstr "" #: src/testbed/testbed_api_topology.c:966 #, c-format msgid "Topology file %s has no data\n" msgstr "" #: src/testbed/testbed_api_topology.c:973 #, c-format msgid "Topology file %s cannot be read\n" msgstr "" #: src/testbed/testbed_api_topology.c:995 #, fuzzy, c-format msgid "Failed to read peer index from toology file: %s" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/testbed/testbed_api_topology.c:1004 #: src/testbed/testbed_api_topology.c:1028 #, c-format msgid "Value in given topology file: %s out of range\n" msgstr "" #: src/testbed/testbed_api_topology.c:1010 #: src/testbed/testbed_api_topology.c:1034 #, fuzzy, c-format msgid "Failed to read peer index from topology file: %s" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/testbed/testbed_api_topology.c:1016 #: src/testbed/testbed_api_topology.c:1040 msgid "Topology file needs more peers than given ones\n" msgstr "" #: src/testbed/testbed_api_topology.c:1074 #, fuzzy, c-format msgid "Ignoring to connect peer %u to peer %u\n" msgstr "无法连接到 %s:%u:%s\n" #: src/testing/gnunet-testing.c:173 #, fuzzy, c-format msgid "Could not extract hostkey %u (offset too large?)\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/testing/gnunet-testing.c:258 #, c-format msgid "Unknown command, use 'q' to quit or 'r' to restart peer\n" msgstr "" #: src/testing/gnunet-testing.c:355 #, fuzzy msgid "create unique configuration files" msgstr "更改é…置文件中的一个值" #: src/testing/gnunet-testing.c:357 msgid "extract hostkey file from pre-computed hostkey list" msgstr "" #: src/testing/gnunet-testing.c:359 #, fuzzy msgid "" "number of unique configuration files to create, or number of the hostkey to " "extract" msgstr "打å°é…置文件中的一个值到标准输出" #: src/testing/gnunet-testing.c:361 #, fuzzy msgid "configuration template" msgstr "é…置已ä¿å­˜" #: src/testing/gnunet-testing.c:363 msgid "run the given service, wait on stdin for 'r' (restart) or 'q' (quit)" msgstr "" #: src/testing/gnunet-testing.c:376 msgid "Command line tool to access the testing library" msgstr "" #: src/testing/list-keys.c:90 msgid "list COUNT number of keys" msgstr "" #: src/testing/list-keys.c:93 msgid "skip COUNT number of keys in the beginning" msgstr "" #: src/testing/testing.c:277 #, c-format msgid "Hostkeys file not found: %s\n" msgstr "" #: src/testing/testing.c:718 #, c-format msgid "Key number %u does not exist\n" msgstr "" #: src/testing/testing.c:1157 #, c-format msgid "" "You attempted to create a testbed with more than %u hosts. Please " "precompute more hostkeys first.\n" msgstr "" #: src/testing/testing.c:1166 #, fuzzy, c-format msgid "Failed to initialize hostkey for peer %u\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/testing/testing.c:1176 msgid "PRIVATE_KEY option in PEER section missing in configuration\n" msgstr "" #: src/testing/testing.c:1189 #, fuzzy msgid "Failed to create configuration for peer (not enough free ports?)\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/testing/testing.c:1203 #, fuzzy, c-format msgid "Cannot open hostkey file `%s': %s\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/testing/testing.c:1215 #, fuzzy, c-format msgid "Failed to write hostkey file for peer %u: %s\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/testing/testing.c:1240 #, fuzzy, c-format msgid "Failed to write configuration file `%s' for peer %u: %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/testing/testing.c:1342 #, fuzzy, c-format msgid "Failed to start `%s': %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/testing/testing.c:1706 #, fuzzy, c-format msgid "Failed to load configuration from %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/topology/friends.c:100 #, fuzzy, c-format msgid "Syntax error in FRIENDS file at offset %llu, skipping bytes `%.*s'.\n" msgstr "é…置文件“%sâ€ç¬¬ %d 行有语法错误。\n" #: src/topology/friends.c:154 #, c-format msgid "Directory for file `%s' does not seem to be writable.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:255 msgid "# peers blacklisted" msgstr "" #: src/topology/gnunet-daemon-topology.c:388 msgid "# connect requests issued to transport" msgstr "" #: src/topology/gnunet-daemon-topology.c:728 #: src/topology/gnunet-daemon-topology.c:813 msgid "# friends connected" msgstr "" #: src/topology/gnunet-daemon-topology.c:993 msgid "Failed to connect to core service, can not manage topology!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1022 #, c-format msgid "Found myself `%s' in friend list (useless, ignored)\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1029 #, fuzzy, c-format msgid "Found friend `%s' in configuration\n" msgstr "" "\n" "结æŸé…置。\n" #: src/topology/gnunet-daemon-topology.c:1050 msgid "Encountered errors parsing friends list!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1052 #, fuzzy msgid "# friends in configuration" msgstr "" "\n" "结æŸé…置。\n" #: src/topology/gnunet-daemon-topology.c:1057 msgid "" "Fewer friends specified than required by minimum friend count. Will only " "connect to friends.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1063 msgid "" "More friendly connections required than target total number of connections.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1094 msgid "# HELLO messages received" msgstr "" #: src/topology/gnunet-daemon-topology.c:1151 msgid "# HELLO messages gossipped" msgstr "" #: src/topology/gnunet-daemon-topology.c:1290 msgid "GNUnet topology control (maintaining P2P mesh and F2F constraints)" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:271 #, fuzzy, c-format msgid "Adding blacklisting entry for peer `%s'\n" msgstr "å¸è½½ GNUnet æœåŠ¡" #: src/transport/gnunet-service-transport_blacklist.c:279 #, c-format msgid "Adding blacklisting entry for peer `%s':`%s'\n" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:464 #: src/transport/gnunet-service-transport_blacklist.c:745 msgid "# disconnects due to blacklist" msgstr "" #: src/transport/gnunet-service-transport.c:220 msgid "# bytes payload discarded due to not connected peer" msgstr "" #: src/transport/gnunet-service-transport.c:424 msgid "# bytes total received" msgstr "" #: src/transport/gnunet-service-transport.c:515 msgid "# bytes payload received" msgstr "" #: src/transport/gnunet-service-transport.c:686 #, fuzzy, c-format msgid "Could not obtain a valid network for `%s' %s (%s)\n" msgstr "无法利用“%2$sâ€è޷喿ޥå£â€œ%1$sâ€çš„ IP。\n" #: src/transport/gnunet-service-transport.c:733 #, c-format msgid "" "Address or session unknown: failed to update properties for peer `%s' plugin " "`%s' address `%s' session %p\n" msgstr "" #: src/transport/gnunet-service-transport.c:1084 #, fuzzy msgid "Transport service is lacking key configuration settings. Exiting.\n" msgstr "ç«‹å³ä¿å­˜é…置?" #: src/transport/gnunet-service-transport_clients.c:432 #, c-format msgid "Dropping message of type %u and size %u, have %u/%u messages pending\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:439 msgid "# messages dropped due to slow client" msgstr "" #: src/transport/gnunet-service-transport_clients.c:596 #, c-format msgid "Rejecting control connection from peer `%s', which is not me!\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:737 msgid "# bytes payload dropped (other peer was not connected)" msgstr "" #: src/transport/gnunet-service-transport_clients.c:770 #, fuzzy, c-format msgid "Blacklist refuses connection attempt to peer `%s'\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-service-transport_clients.c:776 #, fuzzy, c-format msgid "Blacklist allows connection attempt to peer `%s'\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-service-transport_clients.c:801 msgid "# REQUEST CONNECT messages received" msgstr "" #: src/transport/gnunet-service-transport_clients.c:815 #, fuzzy, c-format msgid "Received a request connect message for peer `%s'\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/transport/gnunet-service-transport_clients.c:826 msgid "# REQUEST DISCONNECT messages received" msgstr "" #: src/transport/gnunet-service-transport_clients.c:840 #, fuzzy, c-format msgid "Received a request disconnect message for peer `%s'\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/transport/gnunet-service-transport_hello.c:181 msgid "# refreshed my HELLO" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1095 msgid "# DISCONNECT messages sent" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1220 #: src/transport/gnunet-service-transport_neighbours.c:1629 msgid "# bytes in message queue for other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1225 msgid "# messages transmitted to other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1230 msgid "# transmission failures for messages to other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1287 msgid "# messages timed out while in transport queue" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1343 msgid "# keepalives sent" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1376 msgid "# KEEPALIVE messages discarded (peer unknown)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1384 msgid "# KEEPALIVE messages discarded (no session)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1431 msgid "# KEEPALIVE_RESPONSE messages discarded (not connected)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1440 msgid "# KEEPALIVE_RESPONSE messages discarded (not expected)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1448 msgid "# KEEPALIVE_RESPONSE messages discarded (address changed)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1456 msgid "# KEEPALIVE_RESPONSE messages discarded (wrong nonce)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1534 msgid "# messages discarded due to lack of neighbour record" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1568 msgid "# bandwidth quota violations by other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1584 msgid "# ms throttling suggested" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1678 #, fuzzy, c-format msgid "" "Failed to send CONNECT message to peer `%s' using address `%s' session %p\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-service-transport_neighbours.c:1705 msgid "# Failed attempts to switch addresses (failed to send CONNECT CONT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1751 msgid "# SESSION_CONNECT messages sent" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1767 #, fuzzy, c-format msgid "Failed to transmit CONNECT message via plugin to %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/transport/gnunet-service-transport_neighbours.c:1794 msgid "# Failed attempts to switch addresses (failed to send CONNECT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1844 #, c-format msgid "" "Failed to send CONNECT_ACK message to peer `%s' using address `%s' session " "%p\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1899 msgid "# CONNECT_ACK messages sent" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1914 #, fuzzy, c-format msgid "Failed to transmit CONNECT_ACK message via plugin to %s\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/transport/gnunet-service-transport_neighbours.c:2192 #, fuzzy, c-format msgid "Blacklisting disapproved to connect to peer `%s'\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-service-transport_neighbours.c:2312 msgid "# CONNECT messages received" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2317 #, c-format msgid "CONNECT request from peer `%s' ignored due impending shutdown\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2590 msgid "# Attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3012 #, fuzzy msgid "# Failed attempts to switch addresses (no response)" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/transport/gnunet-service-transport_neighbours.c:3107 msgid "# CONNECT_ACK messages received" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3115 msgid "# unexpected CONNECT_ACK messages (no peer)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3129 #: src/transport/gnunet-service-transport_neighbours.c:3164 msgid "# unexpected CONNECT_ACK messages (not ready)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3176 msgid "# unexpected CONNECT_ACK messages (waiting on ATS)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3200 msgid "# Successful attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3208 msgid "# unexpected CONNECT_ACK messages (disconnecting)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3396 msgid "# SESSION_ACK messages received" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3424 msgid "# unexpected SESSION_ACK messages" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3490 msgid "# SET QUOTA messages ignored (no such peer)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3505 msgid "# disconnects due to quota of 0" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3545 msgid "# disconnect messages ignored (malformed)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3551 msgid "# DISCONNECT messages received" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3560 msgid "# disconnect messages ignored (timestamp)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3687 msgid "# disconnected from peer upon explicit request" msgstr "" #: src/transport/gnunet-service-transport_plugins.c:120 msgid "Transport service is lacking NEIGHBOUR_LIMIT option.\n" msgstr "" #: src/transport/gnunet-service-transport_plugins.c:178 #: src/transport/gnunet-service-transport_plugins.c:186 #: src/transport/gnunet-service-transport_plugins.c:194 #: src/transport/gnunet-service-transport_plugins.c:202 #: src/transport/gnunet-service-transport_plugins.c:210 #: src/transport/gnunet-service-transport_plugins.c:218 #: src/transport/gnunet-service-transport_plugins.c:226 #: src/transport/gnunet-service-transport_plugins.c:234 #: src/transport/gnunet-service-transport_plugins.c:242 #: src/transport/gnunet-service-transport_plugins.c:250 #: src/transport/gnunet-service-transport_plugins.c:258 #, fuzzy, c-format msgid "Missing function `%s' in transport plugin for `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/transport/gnunet-service-transport_plugins.c:265 #, c-format msgid "Did not load plugin `%s' due to missing functions\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:488 msgid "# address records discarded" msgstr "" #: src/transport/gnunet-service-transport_validation.c:558 #, c-format msgid "" "Not transmitting `%s' with `%s', message too big (%u bytes!). This should " "not happen.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:616 msgid "# PING without HELLO messages sent" msgstr "" #: src/transport/gnunet-service-transport_validation.c:722 msgid "# address revalidations started" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1011 msgid "# PING message for different peer received" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1062 #, c-format msgid "Plugin `%s' not available, cannot confirm having this address\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1072 msgid "# failed address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1075 #, c-format msgid "Address `%s' is not one of my addresses, not confirming PING\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1083 msgid "# successful address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1095 #, c-format msgid "" "Not confirming PING from peer `%s' with address `%s' since I cannot confirm " "having this address.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1103 #, c-format msgid "Received a PING message with validation bug from `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1157 #, fuzzy, c-format msgid "Failed to create PONG signature for peer `%s'\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/transport/gnunet-service-transport_validation.c:1206 msgid "# PONGs unicast via reliable transport" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1215 msgid "# PONGs multicast to all available addresses" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1356 msgid "# PONGs dropped, no matching pending validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1371 msgid "# PONGs dropped, signature expired" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1493 #, c-format msgid "Validation received new %s message for peer `%s' with size %u\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1500 #, c-format msgid "Adding `%s' without addresses for peer `%s'\n" msgstr "" #: src/transport/gnunet-transport.c:367 #, c-format msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n" msgstr "" #: src/transport/gnunet-transport.c:375 #, c-format msgid "Received %llu bytes/s (%llu bytes in %s)\n" msgstr "" #: src/transport/gnunet-transport.c:415 #, fuzzy, c-format msgid "Failed to connect to `%s'\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-transport.c:428 #, fuzzy, c-format msgid "Failed to resolve address for peer `%s'\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/transport/gnunet-transport.c:438 #, fuzzy msgid "Failed to list connections, timeout occured\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-transport.c:559 #, fuzzy, c-format msgid "" "Peer `%s' %s %s\n" "\t%s%s\n" "\t%s%s\n" "\t%s%s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/transport/gnunet-transport.c:586 #, fuzzy, c-format msgid "Peer `%s' %s `%s' \n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/transport/gnunet-transport.c:712 msgid "No transport plugins configured, peer will never communicate\n" msgstr "" #: src/transport/gnunet-transport.c:726 #, c-format msgid "No port configured for plugin `%s', cannot test it\n" msgstr "" #: src/transport/gnunet-transport.c:789 #, c-format msgid "Transmitting %u bytes to %s\n" msgstr "" #: src/transport/gnunet-transport.c:810 #, fuzzy, c-format msgid "Successfully connected to `%s'\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/transport/gnunet-transport.c:834 #, c-format msgid "" "Successfully connected to `%s', starting to send benchmark data in %u Kb " "blocks\n" msgstr "" #: src/transport/gnunet-transport.c:865 #, fuzzy, c-format msgid "Successfully disconnected from `%s'\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/transport/gnunet-transport.c:888 #, fuzzy, c-format msgid "Disconnected from peer `%s' while benchmarking\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/transport/gnunet-transport.c:950 #, c-format msgid "Received %u bytes from %s\n" msgstr "" #: src/transport/gnunet-transport.c:975 #, c-format msgid "Peer `%s': %s %s in state `%s' until %s\n" msgstr "" #: src/transport/gnunet-transport.c:986 #, fuzzy, c-format msgid "Peer `%s': %s %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/transport/gnunet-transport.c:1197 src/transport/gnunet-transport.c:1222 #, fuzzy msgid "Failed to send connect request to transport service\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-transport.c:1266 #, c-format msgid "" "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, " "%s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1274 #, c-format msgid "" "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1293 src/transport/gnunet-transport.c:1323 #: src/transport/gnunet-transport.c:1353 src/transport/gnunet-transport.c:1376 #: src/transport/gnunet-transport.c:1419 #, fuzzy msgid "Failed to connect to transport service\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-transport.c:1302 src/transport/gnunet-transport.c:1332 #: src/transport/gnunet-transport.c:1362 #, fuzzy msgid "Failed to send request to transport service\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-transport.c:1381 msgid "Starting to receive benchmark data\n" msgstr "" #: src/transport/gnunet-transport.c:1465 #, fuzzy msgid "print information for all peers (instead of only connected peers )" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/transport/gnunet-transport.c:1468 msgid "measure how fast we are receiving data from all peers (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1471 #, fuzzy msgid "connect to a peer" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-transport.c:1474 #, fuzzy msgid "disconnect to a peer" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/gnunet-transport.c:1477 #, fuzzy msgid "print information for all pending validations " msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/transport/gnunet-transport.c:1480 #, fuzzy msgid "print information for all pending validations continously" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/transport/gnunet-transport.c:1483 msgid "provide information about all current connections (once)" msgstr "" #: src/transport/gnunet-transport.c:1489 msgid "" "provide information about all connects and disconnect events (continuously)" msgstr "" #: src/transport/gnunet-transport.c:1491 msgid "do not resolve hostnames" msgstr "" #: src/transport/gnunet-transport.c:1493 msgid "peer identity" msgstr "" #: src/transport/gnunet-transport.c:1495 msgid "send data for benchmarking to the other peer (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1498 msgid "test transport configuration (involves external server)" msgstr "" #: src/transport/gnunet-transport.c:1507 #, fuzzy msgid "Direct access to transport service." msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/plugin_transport_bluetooth.c:621 msgid "# Bluetooth ACKs sent" msgstr "" #: src/transport/plugin_transport_bluetooth.c:640 msgid "# Bluetooth messages defragmented" msgstr "" #: src/transport/plugin_transport_bluetooth.c:686 #: src/transport/plugin_transport_bluetooth.c:737 #: src/transport/plugin_transport_bluetooth.c:1942 msgid "# Bluetooth sessions allocated" msgstr "" #: src/transport/plugin_transport_bluetooth.c:837 msgid "# Bluetooth message fragments sent" msgstr "" #: src/transport/plugin_transport_bluetooth.c:861 msgid "# Bluetooth messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_bluetooth.c:969 #: src/transport/plugin_transport_bluetooth.c:1054 #: src/transport/plugin_transport_bluetooth.c:1944 msgid "# Bluetooth MAC endpoints allocated" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1307 msgid "# HELLO messages received via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1331 msgid "# fragments received via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1341 msgid "# ACKs received via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1401 msgid "# Bluetooth DATA messages discarded due to CRC32 error" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1512 msgid "# DATA messages received via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1547 msgid "# Bluetooth DATA messages processed" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1610 msgid "# HELLO beacons sent via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1723 msgid "Bluetooth address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1923 #, c-format msgid "Helper binary `%s' not SUID, cannot run bluetooth transport\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1622 #, c-format msgid "Could not initialize curl multi handle, failed to start %s plugin!\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1697 #: src/transport/plugin_transport_http_server.c:3007 #, fuzzy, c-format msgid "Shutting down plugin `%s'\n" msgstr "未知的命令“%sâ€ã€‚\n" #: src/transport/plugin_transport_http_client.c:1722 #: src/transport/plugin_transport_http_server.c:3063 #, c-format msgid "Shutdown for plugin `%s' complete\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1750 #: src/transport/plugin_transport_http_server.c:2907 #, fuzzy, c-format msgid "Maximum number of connections is %u\n" msgstr "增加 TCP/IP 的最大连接数" #: src/transport/plugin_transport_http_server.c:1402 #, c-format msgid "" "Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data " "size %u\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1663 #, c-format msgid "Accepting connection (%u of %u) from `%s'\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1671 #, c-format msgid "" "Server reached maximum number connections (%u), rejecting new connection\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1958 msgid "" "Could not create a new TLS certificate, program `gnunet-transport-" "certificate-creation' could not be started!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1982 #, c-format msgid "No usable TLS certificate found and creating one at `%s/%s' failed!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2405 #, fuzzy msgid "Require valid port number for service in configuration!\n" msgstr "ä¿å­˜é…置失败。" #: src/transport/plugin_transport_http_server.c:2437 src/util/service.c:698 #, fuzzy, c-format msgid "Failed to resolve `%s': %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/transport/plugin_transport_http_server.c:2454 src/util/service.c:715 #, fuzzy, c-format msgid "Failed to find %saddress for `%s'.\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/transport/plugin_transport_http_server.c:2565 #, c-format msgid "Found %u addresses to report to NAT service\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2637 msgid "Disabling IPv6 since it is not supported on this system!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2730 #, c-format msgid "IPv4 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2744 #, c-format msgid "IPv6 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2751 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2762 #, fuzzy msgid "Port is required! Fix in configuration\n" msgstr "" "\n" "结æŸé…置。\n" #: src/transport/plugin_transport_http_server.c:2769 #, c-format msgid "Using port %u\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2784 #, c-format msgid "Specific IPv4 address `%s' in configuration file is invalid!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2794 #, fuzzy, c-format msgid "Binding to IPv4 address %s\n" msgstr "无效的进程优先级“%sâ€\n" #: src/transport/plugin_transport_http_server.c:2815 #, c-format msgid "Specific IPv6 address `%s' in configuration file is invalid!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2825 #, fuzzy, c-format msgid "Binding to IPv6 address %s\n" msgstr "无效的进程优先级“%sâ€\n" #: src/transport/plugin_transport_http_server.c:2877 #, fuzzy, c-format msgid "Using external hostname `%s'\n" msgstr "å¸è½½ GNUnet æœåŠ¡" #: src/transport/plugin_transport_http_server.c:2893 #, c-format msgid "Notifying transport only about hostname `%s'\n" msgstr "" #: src/transport/plugin_transport_smtp.c:223 #, c-format msgid "Received malformed message via %s. Ignored.\n" msgstr "" #: src/transport/plugin_transport_smtp.c:310 msgid "SMTP filter string to invalid, lacks ': '\n" msgstr "" #: src/transport/plugin_transport_smtp.c:319 #, c-format msgid "SMTP filter string to long, capped to `%s'\n" msgstr "" #: src/transport/plugin_transport_smtp.c:414 #: src/transport/plugin_transport_smtp.c:424 #: src/transport/plugin_transport_smtp.c:437 #: src/transport/plugin_transport_smtp.c:456 #: src/transport/plugin_transport_smtp.c:479 #: src/transport/plugin_transport_smtp.c:487 #: src/transport/plugin_transport_smtp.c:500 #: src/transport/plugin_transport_smtp.c:511 #, c-format msgid "SMTP: `%s' failed: %s.\n" msgstr "" #: src/transport/plugin_transport_smtp.c:652 msgid "No email-address specified, can not start SMTP transport.\n" msgstr "" #: src/transport/plugin_transport_smtp.c:664 msgid "# bytes received via SMTP" msgstr "" #: src/transport/plugin_transport_smtp.c:665 msgid "# bytes sent via SMTP" msgstr "" #: src/transport/plugin_transport_smtp.c:667 msgid "# bytes dropped by SMTP (outgoing)" msgstr "" #: src/transport/plugin_transport_tcp.c:555 #, c-format msgid "Unexpected address length: %u bytes\n" msgstr "" #: src/transport/plugin_transport_tcp.c:762 #: src/transport/plugin_transport_tcp.c:928 #: src/transport/plugin_transport_tcp.c:2005 #: src/transport/plugin_transport_tcp.c:2558 msgid "# TCP sessions active" msgstr "" #: src/transport/plugin_transport_tcp.c:795 #: src/transport/plugin_transport_tcp.c:921 #: src/transport/plugin_transport_tcp.c:1009 #: src/transport/plugin_transport_tcp.c:1056 #: src/transport/plugin_transport_tcp.c:1219 #: src/transport/plugin_transport_tcp.c:1237 msgid "# bytes currently in TCP buffers" msgstr "" #: src/transport/plugin_transport_tcp.c:798 msgid "# bytes discarded by TCP (disconnect)" msgstr "" #: src/transport/plugin_transport_tcp.c:1012 msgid "# bytes discarded by TCP (timeout)" msgstr "" #: src/transport/plugin_transport_tcp.c:1059 msgid "# bytes transmitted via TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:1193 #, c-format msgid "Trying to send with invalid session %p\n" msgstr "" #: src/transport/plugin_transport_tcp.c:1462 msgid "# requests to create session with invalid address" msgstr "" #: src/transport/plugin_transport_tcp.c:1567 msgid "# transport-service disconnect requests for TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:2055 msgid "# TCP WELCOME messages received" msgstr "" #: src/transport/plugin_transport_tcp.c:2215 msgid "# bytes received via TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:2279 msgid "# network-level TCP disconnect events" msgstr "" #: src/transport/plugin_transport_tcp.c:2437 src/util/service.c:582 #: src/util/service.c:588 #, c-format msgid "Require valid port number for service `%s' in configuration!\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2451 #, fuzzy msgid "Failed to start service.\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/transport/plugin_transport_tcp.c:2547 #, c-format msgid "TCP transport listening on port %llu\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2551 msgid "TCP transport not listening on any port (client only)\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2554 #, c-format msgid "TCP transport advertises itself as being on port %llu\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:167 msgid "# IPv6 multicast HELLO beacons received via udp" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:210 msgid "# IPv4 broadcast HELLO beacons received via udp" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:603 msgid "" "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:626 #, c-format msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n" msgstr "" #: src/transport/plugin_transport_udp.c:1513 #, c-format msgid "" "Trying to create session for address of unexpected length %u (should be %u " "or %u)\n" msgstr "" #: src/transport/plugin_transport_udp.c:2602 #, c-format msgid "" "UDP could not transmit message to `%s': Network seems down, please check " "your network configuration\n" msgstr "" #: src/transport/plugin_transport_udp.c:2616 msgid "" "UDP could not transmit IPv6 message! Please check your network configuration " "and disable IPv6 if your connection does not have a global IPv6 address\n" msgstr "" #: src/transport/plugin_transport_udp.c:2961 #, fuzzy msgid "Failed to open UDP sockets\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/transport/plugin_transport_udp.c:3056 #, c-format msgid "Given `%s' option is out of range: %llu > %u\n" msgstr "" #: src/transport/plugin_transport_udp.c:3097 #, fuzzy, c-format msgid "Invalid IPv6 address: `%s'\n" msgstr "无效的进程优先级“%sâ€\n" #: src/transport/plugin_transport_udp.c:3168 #, fuzzy msgid "Failed to create network sockets, plugin failed\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/transport/plugin_transport_unix.c:1321 #, fuzzy, c-format msgid "Cannot create path to `%s'\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/transport/plugin_transport_unix.c:1652 #, fuzzy msgid "No UNIXPATH given in configuration!\n" msgstr "ä¿å­˜é…置失败。" #: src/transport/plugin_transport_unix.c:1688 #, fuzzy msgid "Failed to open UNIX listen socket\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/transport/plugin_transport_wlan.c:620 msgid "# WLAN ACKs sent" msgstr "" #: src/transport/plugin_transport_wlan.c:639 msgid "# WLAN messages defragmented" msgstr "" #: src/transport/plugin_transport_wlan.c:688 #: src/transport/plugin_transport_wlan.c:772 #: src/transport/plugin_transport_wlan.c:1948 msgid "# WLAN sessions allocated" msgstr "" #: src/transport/plugin_transport_wlan.c:876 msgid "# WLAN message fragments sent" msgstr "" #: src/transport/plugin_transport_wlan.c:900 msgid "# WLAN messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_wlan.c:1008 #: src/transport/plugin_transport_wlan.c:1098 #: src/transport/plugin_transport_wlan.c:1950 msgid "# WLAN MAC endpoints allocated" msgstr "" #: src/transport/plugin_transport_wlan.c:1302 msgid "# HELLO messages received via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1326 msgid "# fragments received via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1336 msgid "# ACKs received via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1396 msgid "# WLAN DATA messages discarded due to CRC32 error" msgstr "" #: src/transport/plugin_transport_wlan.c:1518 msgid "# DATA messages received via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1553 msgid "# WLAN DATA messages processed" msgstr "" #: src/transport/plugin_transport_wlan.c:1616 msgid "# HELLO beacons sent via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1729 msgid "WLAN address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_wlan.c:1929 #, c-format msgid "Helper binary `%s' not SUID, cannot run WLAN transport\n" msgstr "" #: src/transport/transport_api.c:739 #, c-format msgid "Received unexpected message of type %u in %s:%u\n" msgstr "" #: src/transport/transport-testing.c:584 #, fuzzy msgid "Failed to initialize testing library!\n" msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #: src/tun/regex.c:129 #, c-format msgid "Bad mask: %d\n" msgstr "" #: src/util/bio.c:170 src/util/bio.c:178 #, fuzzy, c-format msgid "Error reading `%s': %s" msgstr "创建用户出错" #: src/util/bio.c:180 msgid "End of file" msgstr "" #: src/util/bio.c:237 #, c-format msgid "Error reading length of string `%s'" msgstr "" #: src/util/bio.c:247 #, c-format msgid "String `%s' longer than allowed (%u > %u)" msgstr "" #: src/util/bio.c:293 #, c-format msgid "Serialized metadata `%s' larger than allowed (%u>%u)" msgstr "" #: src/util/bio.c:307 #, c-format msgid "Metadata `%s' failed to deserialize" msgstr "" #: src/util/client.c:261 src/util/client.c:858 src/util/service.c:619 #, c-format msgid "UNIXPATH `%s' too long, maximum length is %llu\n" msgstr "" #: src/util/client.c:265 src/util/client.c:863 src/util/service.c:623 #, fuzzy, c-format msgid "Using `%s' instead\n" msgstr "%s:选项“%sâ€æœ‰æ­§ä¹‰\n" #: src/util/client.c:360 #, c-format msgid "" "Could not determine valid hostname and port for service `%s' from " "configuration.\n" msgstr "" #: src/util/client.c:368 #, c-format msgid "Need a non-empty hostname for service `%s'.\n" msgstr "" #: src/util/client.c:1008 #, fuzzy, c-format msgid "Could not connect to service `%s', configuration broken.\n" msgstr "无法连接到 %s:%u:%s\n" #: src/util/client.c:1020 #, c-format msgid "Failure to transmit request to service `%s'\n" msgstr "" #: src/util/client.c:1303 msgid "Could not submit request, not expecting to receive a response.\n" msgstr "" #: src/util/common_logging.c:254 src/util/common_logging.c:1039 msgid "DEBUG" msgstr "调试" #: src/util/common_logging.c:256 src/util/common_logging.c:1037 msgid "INFO" msgstr "ä¿¡æ¯" #: src/util/common_logging.c:258 src/util/common_logging.c:1035 msgid "WARNING" msgstr "警告" #: src/util/common_logging.c:260 src/util/common_logging.c:1033 msgid "ERROR" msgstr "错误" #: src/util/common_logging.c:262 src/util/common_logging.c:1041 msgid "NONE" msgstr "" #: src/util/common_logging.c:391 #, fuzzy, c-format msgid "Failed to create or access directory for log file `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/util/common_logging.c:817 #, fuzzy, c-format msgid "Message `%.*s' repeated %u times in the last %s\n" msgstr "消æ¯â€œ%.*sâ€é‡å¤äº† %u 次,在最近 %llu 秒内\n" #: src/util/common_logging.c:1042 msgid "INVALID" msgstr "" #: src/util/common_logging.c:1157 msgid "unknown address" msgstr "" #: src/util/common_logging.c:1196 msgid "invalid address" msgstr "" #: src/util/common_logging.c:1214 #, fuzzy, c-format msgid "Configuration fails to specify option `%s' in section `%s'!\n" msgstr "é…ç½®ä¸æ»¡è¶³é…置规范文件“%sâ€çš„约æŸï¼\n" #: src/util/common_logging.c:1235 #, fuzzy, c-format msgid "" "Configuration specifies invalid value for option `%s' in section `%s': %s\n" msgstr "é…ç½®ä¸æ»¡è¶³é…置规范文件“%sâ€çš„约æŸï¼\n" #: src/util/configuration.c:288 #, fuzzy, c-format msgid "Syntax error while deserializing in line %u\n" msgstr "é…置文件“%sâ€ç¬¬ %d 行有语法错误。\n" #: src/util/configuration.c:996 #, c-format msgid "" "Configuration value '%s' for '%s' in section '%s' is not in set of legal " "choices\n" msgstr "" #: src/util/configuration.c:1066 #, c-format msgid "Recursive expansion suspected, aborting $-expansion for term `%s'\n" msgstr "" #: src/util/configuration.c:1098 #, fuzzy, c-format msgid "Missing closing `%s' in option `%s'\n" msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #: src/util/configuration.c:1172 #, c-format msgid "" "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined " "as an environmental variable\n" msgstr "" #: src/util/connection.c:423 #, fuzzy, c-format msgid "Access denied to `%s'\n" msgstr "“%sâ€å·²è¿žæŽ¥åˆ°â€œ%sâ€ã€‚\n" #: src/util/connection.c:438 #, c-format msgid "Accepting connection from `%s': %p\n" msgstr "" #: src/util/connection.c:553 #, c-format msgid "" "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n" msgstr "" #: src/util/connection.c:751 src/util/connection.c:919 #, fuzzy, c-format msgid "Trying to connect to `%s' (%p)\n" msgstr "无法连接到 %s:%u:%s\n" #: src/util/connection.c:910 #, c-format msgid "Attempt to connect to `%s' failed\n" msgstr "" #: src/util/container_bloomfilter.c:531 #, c-format msgid "" "Size of file on disk is incorrect for this Bloom filter (want %llu, have " "%llu)\n" msgstr "" #: src/util/crypto_ecc.c:702 src/util/crypto_ecc.c:740 #: src/util/crypto_ecc.c:858 src/util/crypto_ecc.c:896 #, fuzzy, c-format msgid "Could not acquire lock on file `%s': %s...\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/util/crypto_ecc.c:707 src/util/crypto_ecc.c:863 #, fuzzy msgid "Creating a new private key. This may take a while.\n" msgstr "正在å¯åŠ¨æ•°æ®ä»“库转æ¢(å¯èƒ½éœ€è¦ä¸€æ®µæ—¶é—´)。\n" #: src/util/crypto_ecc.c:744 src/util/crypto_ecc.c:900 msgid "This may be ok if someone is currently generating a private key.\n" msgstr "" #: src/util/crypto_ecc.c:774 src/util/crypto_ecc.c:930 #, c-format msgid "" "When trying to read key file `%s' I found %u bytes but I need at least %u.\n" msgstr "" #: src/util/crypto_ecc.c:778 src/util/crypto_ecc.c:934 msgid "This may be ok if someone is currently generating a key.\n" msgstr "" #: src/util/crypto_ecc.c:1016 #, fuzzy msgid "Could not load peer's private key\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/util/crypto_ecc.c:1120 #, fuzzy, c-format msgid "ECC signing failed at %s:%d: %s\n" msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #: src/util/crypto_ecc.c:1170 #, fuzzy, c-format msgid "EdDSA signing failed at %s:%d: %s\n" msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #: src/util/crypto_ecc.c:1244 #, fuzzy, c-format msgid "ECDSA signature verification failed at %s:%d: %s\n" msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #: src/util/crypto_ecc.c:1301 #, fuzzy, c-format msgid "EdDSA signature verification failed at %s:%d: %s\n" msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #: src/util/crypto_random.c:284 #, c-format msgid "libgcrypt has not the expected version (version %s is required).\n" msgstr "libgcrypt 的版本ä¸ç¬¦åˆé¢„期(è¦æ±‚版本 %s)。\n" #: src/util/disk.c:1184 #, c-format msgid "Expected `%s' to be a directory!\n" msgstr "“%sâ€åº”为目录ï¼\n" #: src/util/disk.c:1546 src/util/service.c:1318 #, c-format msgid "Cannot obtain information about user `%s': %s\n" msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #: src/util/getopt.c:568 #, c-format msgid "%s: option `%s' is ambiguous\n" msgstr "%s:选项“%sâ€æœ‰æ­§ä¹‰\n" #: src/util/getopt.c:592 #, c-format msgid "%s: option `--%s' does not allow an argument\n" msgstr "%s:选项“--%sâ€ä¸å…è®¸æœ‰å‚æ•°\n" #: src/util/getopt.c:597 #, c-format msgid "%s: option `%c%s' does not allow an argument\n" msgstr "%s:选项“%c%sâ€ä¸å…è®¸æœ‰å‚æ•°\n" #: src/util/getopt.c:614 src/util/getopt.c:781 #, c-format msgid "%s: option `%s' requires an argument\n" msgstr "%s:选项“%sâ€è¦æ±‚æœ‰ä¸€ä¸ªå‚æ•°\n" #: src/util/getopt.c:643 #, c-format msgid "%s: unrecognized option `--%s'\n" msgstr "%s:无法识别的选项“--%sâ€\n" #: src/util/getopt.c:647 #, c-format msgid "%s: unrecognized option `%c%s'\n" msgstr "%s:无法识别的选项“%c%sâ€\n" #: src/util/getopt.c:672 #, c-format msgid "%s: illegal option -- %c\n" msgstr "%sï¼šéžæ³•选项 -- %c\n" #: src/util/getopt.c:674 #, c-format msgid "%s: invalid option -- %c\n" msgstr "%s:无效选项 -- %c\n" #: src/util/getopt.c:702 src/util/getopt.c:829 #, c-format msgid "%s: option requires an argument -- %c\n" msgstr "%sï¼šé€‰é¡¹è¦æ±‚æœ‰ä¸€ä¸ªå‚æ•° -- %c\n" #: src/util/getopt.c:750 #, c-format msgid "%s: option `-W %s' is ambiguous\n" msgstr "%s:选项“-W %sâ€æœ‰æ­§ä¹‰\n" #: src/util/getopt.c:768 #, c-format msgid "%s: option `-W %s' does not allow an argument\n" msgstr "%s:选项“-W %s†ä¸å…è®¸æœ‰å‚æ•°\n" #: src/util/getopt.c:933 #, fuzzy, c-format msgid "Use %s to get a list of options.\n" msgstr "请使用 --help 获å–选项列表。\n" #: src/util/getopt_helpers.c:84 #, c-format msgid "" "Arguments mandatory for long options are also mandatory for short options.\n" msgstr "é•¿é€‰é¡¹çš„å¿…é€‰å‚æ•°å¯¹çŸ­é€‰é¡¹ä¹Ÿæ˜¯å¿…选的。\n" #: src/util/getopt_helpers.c:268 src/util/getopt_helpers.c:326 #, c-format msgid "You must pass a number to the `%s' option.\n" msgstr "您必须å‘“%sâ€é€‰é¡¹ä¼ é€’一个数字。\n" #: src/util/getopt_helpers.c:298 #, fuzzy, c-format msgid "You must pass relative time to the `%s' option.\n" msgstr "您必须å‘“%sâ€é€‰é¡¹ä¼ é€’一个数字。\n" #: src/util/gnunet-config.c:90 #, fuzzy, c-format msgid "--section argument is required\n" msgstr "设置è¦ä½¿ç”¨çš„æ˜µç§°(å¿…é¡»)" #: src/util/gnunet-config.c:133 #, c-format msgid "--option argument required to set value\n" msgstr "" #: src/util/gnunet-config.c:160 msgid "obtain option of value as a filename (with $-expansion)" msgstr "" #: src/util/gnunet-config.c:163 msgid "name of the section to access" msgstr "" #: src/util/gnunet-config.c:166 msgid "name of the option to access" msgstr "" #: src/util/gnunet-config.c:169 msgid "value to set" msgstr "" #: src/util/gnunet-config.c:178 #, fuzzy msgid "Manipulate GNUnet configuration files" msgstr "更改é…置文件中的一个值" #: src/util/gnunet-ecc.c:75 #, fuzzy, c-format msgid "Failed to open `%s': %s\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/util/gnunet-ecc.c:81 #, c-format msgid "Generating %u keys, please wait" msgstr "" #: src/util/gnunet-ecc.c:97 #, fuzzy, c-format msgid "" "\n" "Failed to write to `%s': %s\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/util/gnunet-ecc.c:107 #, c-format msgid "" "\n" "Finished!\n" msgstr "" #: src/util/gnunet-ecc.c:110 #, c-format msgid "" "\n" "Error, %u keys not generated\n" msgstr "" #: src/util/gnunet-ecc.c:199 #, c-format msgid "Hostkeys file `%s' not found\n" msgstr "" #: src/util/gnunet-ecc.c:210 #, fuzzy, c-format msgid "Hostkeys file `%s' is empty\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/util/gnunet-ecc.c:232 #, fuzzy, c-format msgid "Could not read hostkey file: %s\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/util/gnunet-ecc.c:283 msgid "No hostkey file specified on command line\n" msgstr "" #: src/util/gnunet-ecc.c:349 msgid "list keys included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:352 msgid "number of keys to list included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:355 msgid "create COUNT public-private key pairs (for testing)" msgstr "" #: src/util/gnunet-ecc.c:358 msgid "print the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:361 msgid "print the hash of the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:364 msgid "print examples of ECC operations (used for compatibility testing)" msgstr "" #: src/util/gnunet-ecc.c:375 #, fuzzy msgid "Manipulate GNUnet private ECC key files" msgstr "更改é…置文件中的一个值" #: src/util/gnunet-resolver.c:149 msgid "perform a reverse lookup" msgstr "" #: src/util/gnunet-resolver.c:160 msgid "Use build-in GNUnet stub resolver" msgstr "" #: src/util/gnunet-scrypt.c:279 msgid "number of bits to require for the proof of work" msgstr "" #: src/util/gnunet-scrypt.c:282 msgid "file with private key, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:285 msgid "file with proof of work, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:288 msgid "time to wait between calculations" msgstr "" #: src/util/gnunet-scrypt.c:299 #, fuzzy msgid "Manipulate GNUnet proof of work files" msgstr "更改é…置文件中的一个值" #: src/util/gnunet-service-resolver.c:299 #, c-format msgid "Could not resolve `%s' (%s): %s\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/util/gnunet-service-resolver.c:371 #: src/util/gnunet-service-resolver.c:412 #, c-format msgid "Could not find IP of host `%s': %s\n" msgstr "找ä¸åˆ°ä¸»æœºâ€œ%sâ€çš„ IP:%s\n" #: src/util/gnunet-uri.c:84 #, c-format msgid "No URI specified on command line\n" msgstr "" #: src/util/gnunet-uri.c:89 #, fuzzy, c-format msgid "Invalid URI: does not start with `%s'\n" msgstr "无效的网络表示法(没有以“;â€ç»“尾:“%sâ€)\n" #: src/util/gnunet-uri.c:96 #, c-format msgid "Invalid URI: fails to specify subsystem\n" msgstr "" #: src/util/gnunet-uri.c:106 #, c-format msgid "No handler known for subsystem `%s'\n" msgstr "" #: src/util/gnunet-uri.c:168 msgid "Perform default-actions for GNUnet URIs" msgstr "" #: src/util/helper.c:338 #, fuzzy, c-format msgid "Error reading from `%s': %s\n" msgstr "创建用户出错" #: src/util/helper.c:383 #, fuzzy, c-format msgid "Failed to parse inbound message from helper `%s'\n" msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #: src/util/helper.c:609 #, fuzzy, c-format msgid "Error writing to `%s': %s\n" msgstr "创建用户出错" #: src/util/network.c:134 #, c-format msgid "Unable to shorten unix path `%s' while keeping name unique\n" msgstr "" #: src/util/network.c:1355 src/util/network.c:1480 #, c-format msgid "" "Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n" msgstr "" #: src/util/os_installation.c:421 #, fuzzy, c-format msgid "" "Could not determine installation path for %s. Set `%s' environment " "variable.\n" msgstr "无法确定安装路径。请å°è¯•设置“%sâ€\n" #: src/util/os_installation.c:766 #, fuzzy, c-format msgid "Could not find binary `%s' in PATH!\n" msgstr "找ä¸åˆ°ä¸»æœºâ€œ%sâ€çš„ IP:%s\n" #: src/util/os_installation.c:826 #, fuzzy, c-format msgid "CreateProcess failed for binary %s (%d).\n" msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #: src/util/os_installation.c:836 #, c-format msgid "GetExitCodeProcess failed for binary %s (%d).\n" msgstr "" #: src/util/plugin.c:87 #, c-format msgid "Initialization of plugin mechanism failed: %s!\n" msgstr "æ’件机构åˆå§‹åŒ–失败:%sï¼\n" #: src/util/plugin.c:148 #, c-format msgid "`%s' failed to resolve method '%s' with error: %s\n" msgstr "" #: src/util/plugin.c:223 #, c-format msgid "`%s' failed for library `%s' with error: %s\n" msgstr "" #: src/util/plugin.c:382 #, fuzzy msgid "Could not determine plugin installation path.\n" msgstr "无法确定用户界é¢å®šä¹‰æ–‡ä»¶ã€‚" #: src/util/program.c:246 src/util/service.c:1452 #, fuzzy, c-format msgid "Malformed configuration file `%s', exit ...\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/util/program.c:258 src/util/service.c:1467 #, fuzzy, c-format msgid "Could not access configuration file `%s'\n" msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #: src/util/program.c:263 src/util/service.c:1462 #, fuzzy msgid "Malformed configuration, exit ...\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/util/resolver_api.c:198 #, c-format msgid "Must specify `%s' for `%s' in configuration!\n" msgstr "" #: src/util/resolver_api.c:216 #, c-format msgid "" "Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n" msgstr "" #: src/util/resolver_api.c:348 #, fuzzy, c-format msgid "Timeout trying to resolve IP address `%s'.\n" msgstr "GNUnet 现在使用 IP åœ°å€ %s。\n" #: src/util/resolver_api.c:352 #, c-format msgid "Timeout trying to resolve hostname `%s'.\n" msgstr "" #: src/util/resolver_api.c:908 #, fuzzy, c-format msgid "Could not resolve our FQDN : %s\n" msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #: src/util/scheduler.c:813 msgid "Looks like we're busy waiting...\n" msgstr "" #: src/util/scheduler.c:948 #, c-format msgid "Attempt to cancel dead task %llu!\n" msgstr "" #: src/util/server.c:484 #, fuzzy, c-format msgid "`%s' failed for port %d (%s).\n" msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #: src/util/server.c:493 #, c-format msgid "`%s' failed for port %d (%s): address already in use\n" msgstr "" #: src/util/server.c:499 #, fuzzy, c-format msgid "`%s' failed for `%s': address already in use\n" msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #: src/util/server.c:892 #, c-format msgid "" "Processing code for message of type %u did not call " "`GNUNET_SERVER_receive_done' after %s\n" msgstr "" #: src/util/service.c:347 #, c-format msgid "Unknown address family %d\n" msgstr "" #: src/util/service.c:354 #, c-format msgid "Access from `%s' denied to service `%s'\n" msgstr "" #: src/util/service.c:409 #, c-format msgid "Could not parse IPv4 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:446 #, c-format msgid "Could not parse IPv6 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:563 #, c-format msgid "" "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n" msgstr "" #: src/util/service.c:653 #, c-format msgid "" "Disabling UNIX domain socket support for service `%s', failed to create UNIX " "domain socket: %s\n" msgstr "" #: src/util/service.c:669 #, c-format msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n" msgstr "" #: src/util/service.c:903 msgid "Could not access a pre-bound socket, will try to bind myself\n" msgstr "" #: src/util/service.c:952 src/util/service.c:970 #, c-format msgid "Specified value for `%s' of service `%s' is invalid\n" msgstr "" #: src/util/service.c:995 #, c-format msgid "Could not access pre-bound socket %u, will try to bind myself\n" msgstr "" #: src/util/service.c:1165 #, fuzzy, c-format msgid "Failed to start `%s' at `%s'\n" msgstr "è¿è¡Œ %s失败:%s %d\n" #: src/util/service.c:1207 #, c-format msgid "Service `%s' runs at %s\n" msgstr "" #: src/util/service.c:1256 msgid "Service process failed to initialize\n" msgstr "" #: src/util/service.c:1260 msgid "Service process could not initialize server function\n" msgstr "" #: src/util/service.c:1264 msgid "Service process failed to report status\n" msgstr "" #: src/util/service.c:1319 msgid "No such user" msgstr "无此用户" #: src/util/service.c:1332 #, c-format msgid "Cannot change user/group to `%s': %s\n" msgstr "无法更改用户/组为“%sâ€ï¼š%s\n" #: src/util/service.c:1402 msgid "do daemonize (detach from terminal)" msgstr "" #: src/util/signal.c:89 #, c-format msgid "signal (%d, %p) returned %d.\n" msgstr "" #: src/util/strings.c:145 msgid "b" msgstr "b" #: src/util/strings.c:433 #, c-format msgid "Character sets requested were `%s'->`%s'\n" msgstr "" #: src/util/strings.c:561 msgid "Failed to expand `$HOME': environment variable `HOME' not set" msgstr "扩展“$HOMEâ€å¤±è´¥ï¼šæ²¡æœ‰è®¾ç½®çŽ¯å¢ƒå˜é‡â€œHOMEâ€" #: src/util/strings.c:658 msgid "µs" msgstr "" #: src/util/strings.c:662 msgid "forever" msgstr "" #: src/util/strings.c:664 msgid "0 ms" msgstr "" #: src/util/strings.c:670 msgid "ms" msgstr "毫秒" #: src/util/strings.c:676 msgid "s" msgstr "ç§’" #: src/util/strings.c:682 msgid "m" msgstr "分" #: src/util/strings.c:688 msgid "h" msgstr "æ—¶" #: src/util/strings.c:695 #, fuzzy msgid "day" msgstr " 天" #: src/util/strings.c:697 #, fuzzy msgid "days" msgstr " 天" #: src/util/strings.c:726 msgid "end of time" msgstr "" #: src/util/strings.c:1159 msgid "IPv6 address did not start with `['\n" msgstr "" #: src/util/strings.c:1167 msgid "IPv6 address did contain ':' to separate port number\n" msgstr "" #: src/util/strings.c:1173 msgid "IPv6 address did contain ']' before ':' to separate port number\n" msgstr "" #: src/util/strings.c:1180 msgid "IPv6 address did contain a valid port number after the last ':'\n" msgstr "" #: src/util/strings.c:1189 #, fuzzy, c-format msgid "Invalid IPv6 address `%s': %s\n" msgstr "无效的进程优先级“%sâ€\n" #: src/util/strings.c:1395 src/util/strings.c:1411 msgid "Port not in range\n" msgstr "" #: src/util/strings.c:1420 #, fuzzy, c-format msgid "Malformed port policy `%s'\n" msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #: src/util/strings.c:1503 src/util/strings.c:1534 src/util/strings.c:1582 #: src/util/strings.c:1603 #, c-format msgid "Invalid format for IP: `%s'\n" msgstr "IP æ ¼å¼æ— æ•ˆï¼šâ€œ%sâ€\n" #: src/util/strings.c:1560 #, c-format msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)." msgstr "网络表示法无效(“/%d†在 IPv4 CIDR ä¸­æ˜¯éžæ³•çš„)。" #: src/util/strings.c:1612 #, fuzzy, c-format msgid "Invalid format: `%s'\n" msgstr "IP æ ¼å¼æ— æ•ˆï¼šâ€œ%sâ€\n" #: src/util/strings.c:1664 #, c-format msgid "Invalid network notation (does not end with ';': `%s')\n" msgstr "无效的网络表示法(没有以“;â€ç»“尾:“%sâ€)\n" #: src/util/strings.c:1714 #, c-format msgid "Wrong format `%s' for netmask\n" msgstr "网络掩ç çš„æ ¼å¼â€œ%sâ€é”™è¯¯\n" #: src/util/strings.c:1745 #, c-format msgid "Wrong format `%s' for network\n" msgstr "网络的格å¼â€œ%sâ€é”™è¯¯\n" #: src/vpn/gnunet-service-vpn.c:550 src/vpn/gnunet-service-vpn.c:1086 msgid "# Active channels" msgstr "" #: src/vpn/gnunet-service-vpn.c:642 msgid "# Bytes given to mesh for transmission" msgstr "" #: src/vpn/gnunet-service-vpn.c:680 msgid "# Bytes dropped in mesh queue (overflow)" msgstr "" #: src/vpn/gnunet-service-vpn.c:753 #, fuzzy msgid "# Mesh channels created" msgstr "" "\n" "按任æ„键继续\n" #: src/vpn/gnunet-service-vpn.c:784 #, fuzzy msgid "Failed to setup mesh channel!\n" msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #: src/vpn/gnunet-service-vpn.c:978 #, c-format msgid "Protocol %u not supported, dropping\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1305 msgid "# ICMPv4 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1326 msgid "# ICMPv6 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1531 msgid "# Packets received from TUN interface" msgstr "" #: src/vpn/gnunet-service-vpn.c:1564 src/vpn/gnunet-service-vpn.c:1600 #, c-format msgid "Packet received for unmapped destination `%s' (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1610 msgid "Received IPv4 packet with options (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1624 #, c-format msgid "Received packet of unknown protocol %d from TUN (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1706 msgid "# ICMP packets received from mesh" msgstr "" #: src/vpn/gnunet-service-vpn.c:2045 msgid "# UDP packets received from mesh" msgstr "" #: src/vpn/gnunet-service-vpn.c:2200 msgid "# TCP packets received from mesh" msgstr "" #: src/vpn/gnunet-service-vpn.c:2351 msgid "Failed to find unallocated IPv4 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2406 msgid "Failed to find unallocated IPv6 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2447 src/vpn/gnunet-service-vpn.c:2663 msgid "# Active destinations" msgstr "" #: src/vpn/gnunet-service-vpn.c:2715 msgid "Failed to allocate IP address for new destination\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2982 #, fuzzy msgid "Must specify valid IPv6 address" msgstr "“%sâ€ä¸å¯ç”¨ã€‚\n" #: src/vpn/gnunet-service-vpn.c:3006 msgid "Must specify valid IPv6 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3014 msgid "IPv6 support disabled as this system does not support IPv6\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:3027 #, fuzzy msgid "Must specify valid IPv4 address" msgstr "“%sâ€ä¸å¯ç”¨ã€‚\n" #: src/vpn/gnunet-service-vpn.c:3040 msgid "Must specify valid IPv4 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3050 msgid "IPv4 support disabled as this system does not support IPv4\n" msgstr "" #: src/vpn/gnunet-vpn.c:147 #, fuzzy msgid "Error creating tunnel\n" msgstr "创建用户出错" #: src/vpn/gnunet-vpn.c:190 src/vpn/gnunet-vpn.c:221 #, c-format msgid "Option `%s' makes no sense with option `%s'.\n" msgstr "" #: src/vpn/gnunet-vpn.c:203 #, fuzzy, c-format msgid "Option `%s' or `%s' is required.\n" msgstr "%s:选项“%sâ€æœ‰æ­§ä¹‰\n" #: src/vpn/gnunet-vpn.c:215 #, c-format msgid "Option `%s' or `%s' is required when using option `%s'.\n" msgstr "" #: src/vpn/gnunet-vpn.c:235 #, fuzzy, c-format msgid "`%s' is not a valid peer identifier.\n" msgstr "“%sâ€ä¸å¯ç”¨ã€‚\n" #: src/vpn/gnunet-vpn.c:255 #, fuzzy, c-format msgid "`%s' is not a valid IP address.\n" msgstr "“%sâ€ä¸å¯ç”¨ã€‚\n" #: src/vpn/gnunet-vpn.c:290 msgid "request that result should be an IPv4 address" msgstr "" #: src/vpn/gnunet-vpn.c:293 msgid "request that result should be an IPv6 address" msgstr "" #: src/vpn/gnunet-vpn.c:296 msgid "how long should the mapping be valid for new tunnels?" msgstr "" #: src/vpn/gnunet-vpn.c:299 msgid "destination IP for the tunnel" msgstr "" #: src/vpn/gnunet-vpn.c:302 msgid "peer offering the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:305 msgid "name of the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:308 msgid "service is offered via TCP" msgstr "" #: src/vpn/gnunet-vpn.c:311 msgid "service is offered via UDP" msgstr "" #: src/vpn/gnunet-vpn.c:323 msgid "Setup tunnels via VPN." msgstr "" #: src/include/gnunet_common.h:566 src/include/gnunet_common.h:573 #: src/include/gnunet_common.h:581 #, c-format msgid "Assertion failed at %s:%d.\n" msgstr "" #: src/include/gnunet_common.h:593 #, c-format msgid "External protocol violation detected at %s:%d.\n" msgstr "" #: src/include/gnunet_common.h:620 src/include/gnunet_common.h:629 #, c-format msgid "`%s' failed on file `%s' at %s:%d with error: %s\n" msgstr "" #, fuzzy #~ msgid "provide information about a particular channel" #~ msgstr "æ— æ³•èŽ·å–æœ‰å…³ç”¨æˆ·â€œ%sâ€çš„ä¿¡æ¯ï¼š%s\n" #, fuzzy #~ msgid "Could not find option `%s:%s' in configuration.\n" #~ msgstr "找ä¸åˆ°ä¸»æœºâ€œ%sâ€çš„ IP:%s\n" #, fuzzy #~ msgid "Peer `%s' disconnected\n" #~ msgstr "" #~ "\n" #~ "按任æ„键继续\n" #, fuzzy #~ msgid "Found %u transport plugins: `%s'\n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "Failed to parse HELLO in file `%s': %s %u \n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "Internal error %d\n" #~ msgstr "未知错误。\n" #, fuzzy #~ msgid "Aborting call to `%s'\n" #~ msgstr "创建用户出错" #, fuzzy #~ msgid "You are already in a conversation with `%s'.\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "" #~ "%s service is lacking key configuration settings (%s). Using default " #~ "(%u).\n" #~ msgstr "ç«‹å³ä¿å­˜é…置?" #, fuzzy #~ msgid "Loading block plugin `%s'\n" #~ msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #, fuzzy #~ msgid "Invalid value `%s'\n" #~ msgstr "“%sâ€çš„傿•°æ— æ•ˆã€‚\n" #, fuzzy #~ msgid "Found issuer for public key `%s'\n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "No issuer for public key `%s'\n" #~ msgstr "è¿è¡Œ %s失败:%s %d\n" #, fuzzy #~ msgid "Failed to get slave counters!\n" #~ msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "" #~ "Could not translate E[a%d] to MPI!\n" #~ "%s/%s\n" #~ msgstr "无法利用“%2$sâ€è޷喿ޥå£â€œ%1$sâ€çš„ IP。\n" #, fuzzy #~ msgid "Error while decoding key %u\n" #~ msgstr "è§£æž dscl 输出时出错。\n" #, fuzzy #~ msgid "Failed to parse metadata about pseudonym from file `%s': %s\n" #~ msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #~ msgid "no-name" #~ msgstr "æ— åç§°" #, fuzzy #~ msgid "Option `%s' ignored\n" #~ msgstr "%s:选项“%sâ€æœ‰æ­§ä¹‰\n" #, fuzzy #~ msgid "try to shorten a given name" #~ msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Failed to read or create private zone key\n" #~ msgstr "无法为守护程åºåˆ›å»ºç”¨æˆ·è´¦æˆ·ã€‚" #, fuzzy #~ msgid "Unable to initialize resolver!\n" #~ msgstr "无法åˆå§‹åŒ– SQLite:%s。\n" #, fuzzy #~ msgid "Using default zone file `%s'\n" #~ msgstr "å¸è½½ GNUnet æœåŠ¡" #, fuzzy #~ msgid "Failed to write zone key to file `%s': %s\n" #~ msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #, fuzzy #~ msgid "name of the template configuration file to use (optional)" #~ msgstr "打å°é…置文件中的一个值到标准输出" #, fuzzy #~ msgid "number of peers to start" #~ msgstr "迭代次数" #, fuzzy #~ msgid "Failed to read or generate private key: %s\n" #~ msgstr "无法为守护程åºåˆ›å»ºç”¨æˆ·è´¦æˆ·ã€‚" #, fuzzy #~ msgid "Transport service is unable to access hostkey. Exiting.\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "Failed to create namespace `%s' (illegal filename?)\n" #~ msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Mesh service could not access hostkey: %s. Exiting.\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "No valid expiration time for operation `%s'\n" #~ msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #, fuzzy #~ msgid "Failed to find record to remove\n" #~ msgstr "无法连接到 %s:%u:%s\n" #, fuzzy #~ msgid "Could not parse zone key file `%s'\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "Failed to create new signature" #~ msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Failed to remove records from database" #~ msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Failed to access database" #~ msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #, fuzzy #~ msgid "unknown internal error in namestore" #~ msgstr "未知错误。\n" #, fuzzy #~ msgid "NSE service could not access hostkey: %s\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "" #~ "Error loading search strings.Given file does not contain enough strings. " #~ "Exiting.\n" #~ msgstr "创建用户出错" #, fuzzy #~ msgid "Transport service could not access hostkey: %s. Exiting.\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "`%s' failed for drive `%S': %u\n" #~ msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #, fuzzy #~ msgid "Service `%s' was already running.\n" #~ msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #, fuzzy #~ msgid "Service `%s' has been started.\n" #~ msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #, fuzzy #~ msgid "Service `%s' was already being stopped.\n" #~ msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #, fuzzy #~ msgid "Service `%s' was already not running.\n" #~ msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #, fuzzy #~ msgid "Creating a peer failed. Error: %s\n" #~ msgstr "“%sâ€ä»¥é”™è¯¯ç  %d 失败:%s\n" #, fuzzy #~ msgid "Exiting\n" #~ msgstr "退出" #, fuzzy #~ msgid "Failed to read blacklist from `%s'\n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "Syntax error in blacklist file at offset %llu, giving up!\n" #~ msgstr "é…置文件“%sâ€ç¬¬ %d 行有语法错误。\n" #, fuzzy #~ msgid "Failed to read hostkey: %s\n" #~ msgstr "è¿è¡Œ %s失败:%s %d\n" #, fuzzy #~ msgid "Failed to serialize meta data" #~ msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Failed to parse URI `%s' from KBlock!\n" #~ msgstr "è¿è¡Œ %s失败:%s %d\n" #, fuzzy #~ msgid "Regexprofiler could not access hostkey: %s. Exiting.\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "Could not access STATISTICS service. Exiting.\n" #~ msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Failed to open named pipe `%s' for reading: %s\n" #~ msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #, fuzzy #~ msgid "Failed to open named pipe `%s' for writing: %s\n" #~ msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #, fuzzy #~ msgid "Mesh service could not access hostkey. Exiting.\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "Configuration file `%s' for service `%s' not valid: %s\n" #~ msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #, fuzzy #~ msgid "Unknown message type: '%u'\n" #~ msgstr "未知æ“作“%sâ€ã€‚\n" #, fuzzy #~ msgid "Configuration option `%s' in section `%s' missing\n" #~ msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #, fuzzy #~ msgid "Failed to access chat home directory `%s'\n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "Failed to create/open key in file `%s'\n" #~ msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #~ msgid "anonymous" #~ msgstr "匿å" #, fuzzy #~ msgid "(%s) `%s' said: %s\n" #~ msgstr "“%sâ€è¯´ï¼š%s\n" #, fuzzy #~ msgid "(%s) `%s' said to you: %s\n" #~ msgstr "“%sâ€å¯¹æ‚¨è¯´ï¼š%s\n" #, fuzzy #~ msgid "(%s) `%s' said for sure: %s\n" #~ msgstr "“%sâ€å¯¹æ‚¨è¯´ï¼š%s\n" #, fuzzy #~ msgid "(%s) `%s' said to you for sure: %s\n" #~ msgstr "“%sâ€å¯¹æ‚¨è¯´ï¼š%s\n" #, fuzzy #~ msgid "(%s) `%s' said off the record: %s\n" #~ msgstr "“%sâ€å¯¹æ‚¨è¯´ï¼š%s\n" #~ msgid "`%s' entered the room\n" #~ msgstr "“%sâ€è¿›å…¥äº†æˆ¿é—´\n" #~ msgid "`%s' left the room\n" #~ msgstr "“%sâ€ç¦»å¼€äº†æˆ¿é—´\n" #, fuzzy #~ msgid "Could not change username\n" #~ msgstr "å·²å°†ç”¨æˆ·åæ”¹ä¸ºâ€œ%sâ€ã€‚\n" #, fuzzy #~ msgid "Changed username to `%s'\n" #~ msgstr "å·²å°†ç”¨æˆ·åæ”¹ä¸ºâ€œ%sâ€ã€‚\n" #~ msgid "Users in room `%s': " #~ msgstr "房间“%sâ€ä¸­çš„用户:" #~ msgid "Syntax: /msg USERNAME MESSAGE" #~ msgstr "语法:/msg ç”¨æˆ·å æ¶ˆæ¯" #~ msgid "User `%s' is currently not in the room!\n" #~ msgstr "用户“%sâ€å½“å‰ä¸åœ¨æˆ¿é—´é‡Œï¼\n" #~ msgid "set the chat room to join" #~ msgstr "设置è¦åŠ å…¥çš„èŠå¤©å®¤" #, fuzzy #~ msgid "Failed to queue a message notification\n" #~ msgstr "ä¿å­˜é…置失败。" #, fuzzy #~ msgid "Failed to queue a join notification\n" #~ msgstr "ä¿å­˜é…置失败。" #, fuzzy #~ msgid "Failed to queue a confirmation receipt\n" #~ msgstr "ä¿å­˜é…置失败。" #, fuzzy #~ msgid "Failed to queue a leave notification\n" #~ msgstr "ä¿å­˜é…置失败。" #, fuzzy #~ msgid "Configuration fails to specify `%s' in section `%s'\n" #~ msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #, fuzzy #~ msgid "Configuration fails to specify `%s', assuming default value." #~ msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #, fuzzy #~ msgid "Option `%s' not specified in configuration section `%s'\n" #~ msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #, fuzzy #~ msgid "Peer is lacking HOSTKEY configuration setting.\n" #~ msgstr "ç«‹å³ä¿å­˜é…置?" #, fuzzy #~ msgid "Failed to create pipe for `gnunet-peerinfo' process.\n" #~ msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Could not start `%s' process to create hostkey.\n" #~ msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Failed to start `ssh' process.\n" #~ msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Could not start `%s' process to start GNUnet.\n" #~ msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Failed to start `gnunet-arm' process.\n" #~ msgstr "åˆå§‹åŒ–“%sâ€æœåŠ¡å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Could not start `%s' process to copy configuration directory.\n" #~ msgstr "找ä¸åˆ°ä¸»æœºâ€œ%sâ€çš„ IP:%s\n" #, fuzzy #~ msgid "Terminating peer `%4s'\n" #~ msgstr "未知的用户“%sâ€\n" #, fuzzy #~ msgid "Setting d->dead on peer `%4s'\n" #~ msgstr "å¸è½½ GNUnet æœåŠ¡" #, fuzzy #~ msgid "Failed to write new configuration to disk." #~ msgstr "ä¿å­˜é…置失败。" #, fuzzy #~ msgid "Failed to copy new configuration to remote machine." #~ msgstr "ä¿å­˜é…置失败。" #, fuzzy #~ msgid "Peers failed to connect" #~ msgstr "" #~ "\n" #~ "按任æ„键继续\n" #, fuzzy #~ msgid "Failed to connect to core service of first peer!\n" #~ msgstr "加载 sqstore æœåŠ¡å¤±è´¥ã€‚æ£€æŸ¥æ‚¨çš„é…ç½®ï¼\n" #, fuzzy #~ msgid "Invalid value `%s' for option `%s' in section `%s': expected float\n" #~ msgstr "é…ç½®ä¸æ»¡è¶³é…置规范文件“%sâ€çš„约æŸï¼\n" #, fuzzy #~ msgid "Could not create configuration for peer number %u on `%s'!\n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "Invalid configuration option `%s' in section `%s'\n" #~ msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #, fuzzy #~ msgid "Missing configuration option `%s' in section `%s'\n" #~ msgstr "é…置文件“%sâ€å·²å†™å…¥ã€‚\n" #, fuzzy #~ msgid "internal error" #~ msgstr "未知错误。\n" #, fuzzy #~ msgid "Could not create namespace `%s'\n" #~ msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #, fuzzy #~ msgid "Stored zonekey for zone `%s' in file `%s'\n" #~ msgstr "打开日志文件“%sâ€å¤±è´¥ï¼š%s\n" #, fuzzy #~ msgid "Namestore removed record successfully" #~ msgstr "GNUnet æœåŠ¡å®‰è£…æˆåŠŸã€‚\n" #, fuzzy #~ msgid "Could not read hostkeys file, specify hostkey file with -H!\n" #~ msgstr "找ä¸åˆ°æŽ¥å£â€œ%sâ€çš„一个 IP 地å€ã€‚\n" #, fuzzy #~ msgid "access (%s, X_OK) failed: %s\n" #~ msgstr "“%sâ€è¯´ï¼š%s\n" #, fuzzy #~ msgid "# Peers connected" #~ msgstr "" #~ "\n" #~ "按任æ„键继续\n" #, fuzzy #~ msgid "Unable to initialize Postgres with configuration `%s': %s" #~ msgstr "无法ä¿å­˜é…置文件“%sâ€ï¼š" #, fuzzy #~ msgid "Copying file with RENAME (%s,%s)\n" #~ msgstr "“%sâ€ä»¥é”™è¯¯ç  %s 失败:%s\n" #, fuzzy #~ msgid "Copying file with command scp %s %s\n" #~ msgstr "“%sâ€ä»¥é”™è¯¯ç  %s 失败:%s\n" #, fuzzy #~ msgid "Finished copying all blacklist files!\n" #~ msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #, fuzzy #~ msgid "Failed during blacklist file copying!\n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "Could not access file: %s\n" #~ msgstr "错误:无法访问æœåŠ¡ï¼š%s\n" #, fuzzy #~ msgid "`%s' failed on file `%s': %s" #~ msgstr "对驱动器“%2$sâ€çš„“%1$sâ€æ“作失败:%3$u\n" #, fuzzy #~ msgid "Failed to start service `%s'!\n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "Service `%s' stopped\n" #~ msgstr "æœåŠ¡å·²åˆ é™¤ã€‚\n" #, fuzzy #~ msgid "Unable to accept connection for service `%s': %s\n" #~ msgstr "无法ä¿å­˜é…置文件“%sâ€ï¼š" #~ msgid "KiB" #~ msgstr "KiB" #~ msgid "MiB" #~ msgstr "MiB" #~ msgid "GiB" #~ msgstr "GiB" #~ msgid "TiB" #~ msgstr "TiB" #, fuzzy #~ msgid "Could not resolve our FQDN : %s %u\n" #~ msgstr "无法解æžâ€œ%sâ€(%s):%s\n" #, fuzzy #~ msgid "Failed to load dhtlog plugin for `%s'\n" #~ msgstr "è§£æžé…置文件“%sâ€å¤±è´¥\n" #, fuzzy #~ msgid "Phase 3: sending messages\n" #~ msgstr "å‘逿¶ˆæ¯å¤±è´¥ã€‚\n" #, fuzzy #~ msgid "Fail! Could not connect peers\n" #~ msgstr "无法连接到 %s:%u:%s\n" #~ msgid "Error" #~ msgstr "错误" #~ msgid "Help" #~ msgstr "帮助" #~ msgid "Error!" #~ msgstr "错误ï¼" #~ msgid "No" #~ msgstr "å¦" #~ msgid "Yes" #~ msgstr "是" #~ msgid "Internal error! (Choice invalid?)" #~ msgstr "内部错误ï¼(选择无效?)" #~ msgid "Abort" #~ msgstr "中止" #~ msgid "Ok" #~ msgstr "确定" #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://gnunet.org/\n" #~ "and join our community at\n" #~ "\thttp://gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "the GNUnet team" #~ msgstr "" #~ "欢迎使用 GNUnetï¼\n" #~ "\n" #~ "此助手将询问您几个基本问题,以é…ç½® GNUnet。\n" #~ "\n" #~ "请访问我们的主页\n" #~ "\thttp://gnunet.org/\n" #~ "并欢迎加入我们的社区\n" #~ "\thttp://gnunet.org/drupal/\n" #~ "\n" #~ "ç¥æ‚¨ä½¿ç”¨æ„‰å¿«ï¼Œ\n" #~ "\n" #~ "GNUnet 团队" #~ msgid "" #~ "Choose the network interface that connects your computer to the internet " #~ "from the list below." #~ msgstr "请从下é¢çš„列表中选择计算机è”网的网络接å£ã€‚" #~ msgid "" #~ "The \"Network interface\" is the device that connects your computer to " #~ "the internet. This is usually a modem, an ISDN card or a network card in " #~ "case you are using DSL." #~ msgstr "" #~ "“网络接å£â€æ˜¯å°†æ‚¨çš„计算机连接到互è”网的设备。该设备通常为一å°è°ƒåˆ¶è§£è°ƒå™¨ã€ä¸€" #~ "å¼  ISDN 塿ˆ–一张网å¡(若您使用 DSL 网络)。" #~ msgid "Network configuration: interface" #~ msgstr "网络é…置:接å£" #~ msgid "" #~ "What is the name of the network interface that connects your computer to " #~ "the Internet?" #~ msgstr "您的计算机è”网所使用的网络接å£çš„å称是什么?" #~ msgid "Network configuration: IP" #~ msgstr "网络é…置:IP" #~ msgid "What is this computer's public IP address or hostname?" #~ msgstr "è¿™å°è®¡ç®—机的公网 IP åœ°å€æˆ–ä¸»æœºåæ˜¯ä»€ä¹ˆï¼Ÿ" #~ msgid "" #~ "If your provider always assigns the same IP-Address to you (a \"static\" " #~ "IP-Address), enter it into the \"IP-Address\" field. If your IP-Address " #~ "changes every now and then (\"dynamic\" IP-Address) but there's a " #~ "hostname that always points to your actual IP-Address (\"Dynamic DNS\"), " #~ "you can also enter it here.\n" #~ "If left empty, GNUnet will try to automatically detect the IP.\n" #~ "You can specify a hostname, GNUnet will then use DNS to resolve it.\n" #~ "If in doubt, leave this empty." #~ msgstr "" #~ "如果您的网络è¿è¥å•†æ€»æ˜¯åˆ†é…固定的 IP 地å€ç»™æ‚¨(â€œé™æ€â€ IP 地å€),请将它输" #~ "入“IP 地å€â€å­—段。如果您的 IP æ˜¯ä¸æ—¶å˜åŒ–çš„(“动æ€â€ IP 地å€)但有一个总是指å‘" #~ "您的实际 IP 地å€çš„主机å(â€œåŠ¨æ€ DNSâ€),也å¯ä»¥å°†è¿™ä¸ªä¸»æœºå填到这里。\n" #~ "如果ä¸å¡«ï¼ŒGNUnet å°†å°è¯•自动检测此 IP。\n" #~ "您å¯ä»¥æŒ‡å®šä¸€ä¸ªä¸»æœºå,GNUnet 将使用 DNS æ¥è§£æžå®ƒã€‚\n" #~ "å¦‚æžœä¸æ˜Žç™½ï¼Œè¯·ä¸å¡«ã€‚" #~ msgid "Bandwidth configuration: upload" #~ msgstr "带宽é…置:上传" #~ msgid "How much upstream bandwidth (in bytes/s) may be used?" #~ msgstr "å¯ä»¥ä½¿ç”¨å¤šå°‘上行带宽(å•ä½ä¸ºå­—节/ç§’)?" #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "The \"upstream\" is the data channel through which data is *sent* to the " #~ "internet. The limit is the maximum amount which GNUnet is allowed to use. " #~ "If you have a flatrate, you can set it to the maximum speed of your " #~ "internet connection. You should not use a value that is higher than what " #~ "your actual connection allows." #~ msgstr "" #~ "您å¯ä»¥åœ¨æ­¤é™åˆ¶ GNUnet 的资æºå ç”¨ã€‚\n" #~ "\n" #~ "â€œä¸Šè¡Œâ€æ˜¯å‘互è”网“å‘é€â€æ•°æ®çš„æ•°æ®é€šé“。é™åˆ¶æ˜¯ GNUnet å¯ä½¿ç”¨çš„æœ€å¤§æ•°æ®æµé‡ã€‚" #~ "如果您的网速很平稳,您å¯ä»¥å°†è¯¥é™åˆ¶è®¾ç½®ä¸ºç½‘速的最大值。您ä¸åº”该使用超过实际" #~ "连接速度æžé™çš„值。" #~ msgid "Bandwidth configuration: download" #~ msgstr "带宽é…置:下载" #~ msgid "How much downstream bandwidth (in bytes/s) may be used?" #~ msgstr "å¯ä»¥ä½¿ç”¨å¤šå°‘下行带宽(å•ä½ä¸ºå­—节/ç§’)?" #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "The \"downstream\" is the data channel through which data is *received* " #~ "from the internet. The limit is the maximum amount which GNUnet is " #~ "allowed to use. If you have a flatrate, you can set it to the maximum " #~ "speed of your internet connection. You should not use a value that is " #~ "higher than what your actual connection allows." #~ msgstr "" #~ "您å¯ä»¥åœ¨æ­¤é™åˆ¶ GNUnet 的资æºå ç”¨ã€‚\n" #~ "\n" #~ "â€œä¸‹è¡Œâ€æ˜¯æ•°æ®ä»Žäº’è”ç½‘â€œæŽ¥æ”¶â€æ•°æ®çš„æ•°æ®é€šé“。é™åˆ¶æ˜¯ GNUnet å¯ä½¿ç”¨çš„æœ€å¤§æ•°æ®æµ" #~ "é‡ã€‚如果您的网速很平稳,您å¯ä»¥å°†è¯¥é™åˆ¶è®¾ç½®ä¸ºç½‘速的最大值。您ä¸åº”该使用超过" #~ "实际连接速度æžé™çš„值。" #~ msgid "Quota configuration" #~ msgstr "é…é¢é…ç½®" #~ msgid "What is the maximum size of the datastore in MB?" #~ msgstr "æ•°æ®ä»“库的最大尺寸是多少(MB)?" #~ msgid "" #~ "The GNUnet datastore contains all content that GNUnet needs to store " #~ "(indexed, inserted and migrated content)." #~ msgstr "" #~ "GNUnet æ•°æ®ä»“库包å«äº† GNUnet 需è¦ä¿å­˜çš„æ‰€æœ‰å†…容(ç´¢å¼•çš„ã€æ’入的和åˆå¹¶çš„内" #~ "容)。" #~ msgid "Daemon configuration: user account" #~ msgstr "守护程åºé…置:用户账户" #~ msgid "As which user should gnunetd be run?" #~ msgstr "以什么用户身份è¿è¡Œ gnunetd?" #, fuzzy #~ msgid "" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "user account under which the GNUnet service is started at system " #~ "startup.\n" #~ "\n" #~ "However, GNUnet may not be able to access files other than its own. This " #~ "includes files you want to publish in GNUnet. You'll have to grant read " #~ "permissions to the user specified below.\n" #~ "\n" #~ "Leave the field empty to run GNUnet with system privileges.\n" #~ msgstr "" #~ "出于安全考虑,让设置助手创建一个专门用于在系统å¯åŠ¨æ—¶å¯åЍ GNUnet æœåŠ¡çš„è´¦æˆ·" #~ "是个ä¸é”™çš„主æ„。\n" #~ "\n" #~ "但是,GNUnet å¯èƒ½æ— æ³•访问ä¸å±žäºŽè‡ªå·±è´¦æˆ·çš„æ–‡ä»¶ã€‚这包括您想通过 GNUnet å‘布" #~ "的文件。您必须对以下用户赋予读æƒé™ã€‚\n" #~ "\n" #~ "ä¸å¡«æ­¤å­—段则以系统æƒé™è¿è¡Œ GNUnet。\n" #~ msgid "Daemon configuration: group account" #~ msgstr "守护程åºé…置:组账户" #~ msgid "As which group should gnunetd be run?" #~ msgstr "以什么用户组身份è¿è¡Œ gnunetd?" #~ msgid "" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "group for the chosen user account.\n" #~ "\n" #~ "You can also specify a already existent group here.\n" #~ "\n" #~ "Only members of this group will be allowed to start and stop the the " #~ "GNUnet server and have access to GNUnet server data.\n" #~ msgstr "" #~ "出于安全考虑,让设置助手为选择的用户创建一个新组是个ä¸é”™çš„主æ„。\n" #~ "\n" #~ "您也å¯ä»¥åœ¨æ­¤æŒ‡å®šä¸€ä¸ªçŽ°æœ‰çš„ç»„ã€‚\n" #~ "\n" #~ "åªæœ‰è¯¥ç»„çš„æˆå‘˜å¯ä»¥å¯åŠ¨å’Œåœæ­¢ GNUnet æœåŠ¡å™¨å’Œè®¿é—® GNUnet æœåŠ¡å™¨æ•°æ®ã€‚\n" #~ msgid "Do you want to automatically launch GNUnet as a system service?" #~ msgstr "您想将 GNUnet 作为系统æœåŠ¡è‡ªåŠ¨å¯åЍå—?" #~ msgid "" #~ "If you say \"yes\" here, the GNUnet background process will be " #~ "automatically started when you turn on your computer. If you say \"no\" " #~ "here, you have to launch GNUnet yourself each time you want to use it." #~ msgstr "" #~ "如果您回答“是â€ï¼ŒGNUnet åŽå°è¿›ç¨‹å°†åœ¨å¼€æœºæ—¶è‡ªåЍå¯åŠ¨ã€‚å¦‚æžœæ‚¨å›žç­”â€œå¦â€ï¼Œåˆ™éœ€è¦" #~ "åœ¨æ¯æ¬¡ä½¿ç”¨ GNUnet 时自己å¯åŠ¨å®ƒã€‚" #~ msgid "Unable to setup autostart for daemon." #~ msgstr "无法将守护进程设置为自动å¯åŠ¨ã€‚" #~ msgid "Save configuration?" #~ msgstr "ä¿å­˜é…置?" #~ msgid "GNUnet Configuration" #~ msgstr "GNUnet é…ç½®" #~ msgid "Back" #~ msgstr "åŽé€€" #~ msgid "Up" #~ msgstr "å‘上" #~ msgid "Cancel" #~ msgstr "å–æ¶ˆ" #~ msgid "Internal error! (Value invalid?)" #~ msgstr "内部错误ï¼(值无效?)" #~ msgid "Invalid input, expecting floating point value." #~ msgstr "无效输入,应为浮点值。" #~ msgid "Invalid input, expecting integer." #~ msgstr "无效输入,应为整数。" #~ msgid "Configuration unchanged, no need to save.\n" #~ msgstr "é…置未更改,无须ä¿å­˜ã€‚\n" #~ msgid "Do you wish to save your new configuration?" #~ msgstr "您想ä¿å­˜æ–°é…ç½®å—?" #~ msgid "" #~ "\n" #~ "Your configuration changes were NOT saved.\n" #~ msgstr "" #~ "\n" #~ "您的é…置更改没有ä¿å­˜ã€‚\n" #~ msgid "install GNUnet as Windows service" #~ msgstr "以 Windows æœåŠ¡æ–¹å¼å®‰è£… GNUnet" #~ msgid "display a file's hash value" #~ msgstr "显示一个文件的散列值" #~ msgid "This version of Windows doesn't support services.\n" #~ msgstr "此版本的 Windows 䏿”¯æŒæœåŠ¡ã€‚\n" #~ msgid "Error: can't open Service Control Manager: %s\n" #~ msgstr "错误:无法打开æœåŠ¡æŽ§åˆ¶ç®¡ç†å™¨ï¼š%s\n" #~ msgid "Error: can't create service: %s\n" #~ msgstr "错误:无法创建æœåŠ¡ï¼š%s\n" #~ msgid "Error: can't delete service: %s\n" #~ msgstr "错误:无法删除æœåŠ¡ï¼š%s\n" #~ msgid "Configuration changed. Save?" #~ msgstr "é…置已更改。ä¿å­˜å—?" #~ msgid "Error saving configuration." #~ msgstr "ä¿å­˜é…置出错。" #~ msgid "(unknown connection)" #~ msgstr "(未知连接)" #~ msgid "Do you want to save the new configuration?" #~ msgstr "您想ä¿å­˜æ–°é…ç½®å—?" #~ msgid "Unable to change startup process:" #~ msgstr "无法更改å¯åŠ¨è¿›ç¨‹ï¼š" #~ msgid "" #~ "Running gnunet-update failed.\n" #~ "This maybe due to insufficient permissions, please check your " #~ "configuration.\n" #~ "Finally, run gnunet-update manually." #~ msgstr "" #~ "è¿è¡Œ gnunet-update 失败。\n" #~ "è¿™å¯èƒ½æ˜¯æƒé™ä¸è¶³é€ æˆçš„,请检查您的é…置。\n" #~ "最åŽï¼Œæ‰‹åЍè¿è¡Œ gnunet-update。" #~ msgid "Can only set one option per invocation.\n" #~ msgstr "æ¯æ¬¡è°ƒç”¨åªèƒ½è®¾ç½®ä¸€ä¸ªé€‰é¡¹ã€‚\n" #~ msgid "" #~ "Invalid syntax, argument to 'set' must have the format SECTION:" #~ "OPTION=VALUE.\n" #~ msgstr "语法无效,“setâ€çš„傿•°å¿…须为 SECTION:OPTION=VALUE 的格å¼ã€‚\n" #~ msgid "Can only display one option per invocation.\n" #~ msgstr "æ¯æ¬¡è°ƒç”¨åªèƒ½æ˜¾ç¤ºä¸€ä¸ªé€‰é¡¹ã€‚\n" #~ msgid "" #~ "Invalid syntax, argument to 'get' must have the format SECTION:OPTION.\n" #~ msgstr "语法无效,“getâ€çš„傿•°å¿…须为 SECTION:OPTION 的格å¼ã€‚\n" #~ msgid "generate configuration for gnunetd, the GNUnet daemon" #~ msgstr "为 GNUnet å®ˆæŠ¤ç¨‹åº gnunetd 生æˆé…ç½®" #~ msgid "Tool to setup GNUnet." #~ msgstr "设置 GNUnet 的工具。" #~ msgid "Too many arguments.\n" #~ msgstr "傿•°è¿‡å¤šã€‚\n" #~ msgid "Configuration file `%s' must be a filename (but is a directory).\n" #~ msgstr "é…置文件“%sâ€å¿…须是一个文件å(但是一个目录)。\n" #~ msgid "Undefined option.\n" #~ msgstr "未定义的选项。\n" #~ msgid "yes" #~ msgstr "是" #~ msgid "no" #~ msgstr "å¦" #~ msgid "\tEnter yes (%s), no (%s) or help (%s): " #~ msgstr "\t输入 yes (%s)ã€no (%s) 或 help (%s):" #~ msgid "\tPossible choices:\n" #~ msgstr "\tå¯ç”¨é€‰é¡¹ï¼š\n" #~ msgid "\tUse single space prefix to avoid conflicts with hotkeys!\n" #~ msgstr "\t使用一个空格å‰ç¼€æ¥é¿å…与快æ·é”®å†²çªï¼\n" #~ msgid "\tEnter string (type '%s' for default value `%s'): " #~ msgstr "\t输入字符串(输入“%sâ€ä»¥ä½¿ç”¨é»˜è®¤å€¼â€œ%sâ€):" #~ msgid "\t Enter choice (default is %c): " #~ msgstr "\t 输入选择(默认为 %c):" #~ msgid "\tEnter floating point (type '%s' for default value %f): " #~ msgstr "\t输入浮点数(输入“%sâ€ä»¥ä½¿ç”¨é»˜è®¤å€¼ %f):" #~ msgid "" #~ "\tEnter unsigned integer in interval [%llu,%llu] (type '%s' for default " #~ "value %llu): " #~ msgstr "\t输入区间 [%llu,%llu] å†…çš„æ— ç¬¦å·æ•´æ•°(输入“%sâ€ä»¥ä½¿ç”¨é»˜è®¤å€¼ %llu):" #~ msgid "Yes\n" #~ msgstr "是\n" #~ msgid "No\n" #~ msgstr "å¦\n" #~ msgid "Help\n" #~ msgstr "帮助\n" #~ msgid "Abort\n" #~ msgstr "中止\n" #~ msgid "" #~ "\n" #~ "Invalid entry, try again (use '?' for help): " #~ msgstr "" #~ "\n" #~ "无效æ¡ç›®ï¼Œè¯·é‡è¯•(使用“?â€èŽ·å–帮助):" #~ msgid "Unknown kind %x (internal error). Skipping option.\n" #~ msgstr "未知的类型 %x (内部错误)。将跳过选项。\n" #, fuzzy #~ msgid "\tDescend? (y/n/?) " #~ msgstr "\t下é™(y/n/?) " #~ msgid "Aborted.\n" #~ msgstr "已中止。\n" #~ msgid "Unknown kind %x (internal error). Aborting.\n" #~ msgstr "未知的类型 %x (内部错误)。将中止。\n" #~ msgid "You can always press ENTER to keep the current value.\n" #~ msgstr "您å¯ä»¥éšä¾¿æŒ‰ ENTER é”®æ¥ä¿æŒå½“å‰å€¼ã€‚\n" #~ msgid "Use the '%s' key to abort.\n" #~ msgstr "使用“%sâ€é”®æ¥ä¸­æ­¢ã€‚\n" #~ msgid "" #~ "Save configuration? Answer 'y' for yes, 'n' for no, 'r' to repeat " #~ "configuration. " #~ msgstr "ä¿å­˜é…置?回答“yâ€è¡¨ç¤ºæ˜¯ï¼Œâ€œnâ€è¡¨ç¤ºå¦ï¼Œâ€œrâ€è¡¨ç¤ºé‡å¤é…置。" #~ msgid "Configuration was unchanged, no need to save.\n" #~ msgstr "é…置未更改,无须ä¿å­˜ã€‚\n" #~ msgid "" #~ "Internal error: entry `%s' in section `%s' not found for visibility " #~ "change!\n" #~ msgstr "内部错误:找ä¸åˆ°â€œ%2$sâ€èŠ‚çš„æ¡ç›®â€œ%1$sâ€ä»¥è¿›è¡Œå¯è§†åŒ–更改ï¼\n" #~ msgid "Can't open Service Control Manager" #~ msgstr "无法打开æœåŠ¡æŽ§åˆ¶ç®¡ç†å™¨" #~ msgid "Can't create service" #~ msgstr "无法创建æœåŠ¡" #~ msgid "Cannot write to the registry" #~ msgstr "无法写入该注册表" #~ msgid "Can't delete the service" #~ msgstr "无法删除该æœåŠ¡" #~ msgid "This version of Windows does not support multiple users." #~ msgstr "此版本的 Windows 䏿”¯æŒå¤šç”¨æˆ·ã€‚" #~ msgid "Error accessing local security policy" #~ msgstr "访问本地安全策略出错" #~ msgid "Error granting service right to user" #~ msgstr "å‘用户授予æœåŠ¡æƒé™å‡ºé”™" #~ msgid "Unknown error while creating a new user" #~ msgstr "在创建新用户时å‘生未知错误" #~ msgid "STATUS" #~ msgstr "状æ€" #~ msgid "FATAL" #~ msgstr "致命" #~ msgid "USER" #~ msgstr "用户" #~ msgid "ADMIN" #~ msgstr "管ç†å‘˜" #~ msgid "DEVELOPER" #~ msgstr "å¼€å‘者" #~ msgid "REQUEST" #~ msgstr "请求" #~ msgid "BULK" #~ msgstr "批é‡" #~ msgid "IMMEDIATE" #~ msgstr "ç«‹å³" #~ msgid "ALL" #~ msgstr "所有" #~ msgid "NOTHING" #~ msgstr "æ— " #~ msgid "Could not find valid value for HOST in section NETWORK.\n" #~ msgstr "在 NETWORK(网络) 节中找ä¸åˆ° HOST(主机) 的有效值。\n" #~ msgid "Syntax error in configuration entry HOST in section NETWORK: `%s'\n" #~ msgstr "在 NETWORK 节的é…ç½®æ¡ç›® HOST 中有语法错误:“%sâ€\n" #~ msgid "Reading result from gnunetd failed, reply invalid!\n" #~ msgstr "从 gnunetd 读å–结果失败,应答无效ï¼\n" #~ msgid "" #~ "Setting option `%s' in section `%s' to `%s' when processing command line " #~ "option `%s' was denied.\n" #~ msgstr "" #~ "在处ç†å‘½ä»¤è¡Œé€‰é¡¹â€œ%4$sâ€æ—¶ï¼Œå°†â€œ%2$sâ€èŠ‚çš„é€‰é¡¹â€œ%1$sâ€è®¾ç½®ä¸ºâ€œ%3$sâ€è¢«æ‹’ç»ã€‚\n" #~ msgid "No interface specified in section `%s' under `%s'!\n" #~ msgstr "“%2$sâ€ä¸‹çš„“%1$sâ€èŠ‚ä¸­æ²¡æœ‰æŒ‡å®šæŽ¥å£ï¼\n" #~ msgid "" #~ "Could not find interface `%s' using `%s', trying to find another " #~ "interface.\n" #~ msgstr "无法利用“%2$sâ€æ‰¾åˆ°æŽ¥å£â€œ%1$sâ€ï¼Œå°è¯•查找å¦ä¸€ä¸ªæŽ¥å£ã€‚\n" #~ msgid "" #~ "There is more than one IP address specified for interface `%s'.\n" #~ "GNUnet will use %s.\n" #~ msgstr "" #~ "为“%sâ€æŽ¥å£æŒ‡å®šäº†è¶…过一个 IP 地å€ã€‚\n" #~ "GNUnet 将使用 %s。\n" #~ msgid "Received malformed message (too small) from connection. Closing.\n" #~ msgstr "从连接收到æŸå的消æ¯(过å°)。关闭。\n" #, fuzzy #~ msgid "select listen socket for `%s' not valid!\n" #~ msgstr "选择“%sâ€çš„监å¬å¥—接字无效ï¼\n" #~ msgid "`%s' returned with error code %u" #~ msgstr "“%sâ€è¿”å›žäº†é”™è¯¯ç  %u" #~ msgid "Can't create semaphore: %i" #~ msgstr "无法创建信å·é‡ï¼š%i" #~ msgid "Cannot query the CPU usage (Windows NT).\n" #~ msgstr "无法查询 CPU 使用率(Windows NT)。\n" #~ msgid "Cannot query the CPU usage (Win 9x)\n" #~ msgstr "无法查询 CPU 使用率(Windows 9x)。\n" #~ msgid "Setting open descriptor limit not supported.\n" #~ msgstr "䏿”¯æŒè®¾ç½®æ‰“å¼€æè¿°ç¬¦é™åˆ¶ã€‚\n" #~ msgid "Command `%s' failed with error code %u\n" #~ msgstr "命令“%sâ€å¤±è´¥ï¼Œé”™è¯¯ç  %u\n" #~ msgid "Real-time delay violation (%llu ms) at %s:%u\n" #~ msgstr "实时延迟冲çª(%llu 毫秒),于 %s:%u\n" #~ msgid "Deadlock due to `%s'.\n" #~ msgstr "“%sâ€é€ æˆäº†æ­»é”。\n" #, fuzzy #~ msgid "Out of memory (for logging)\n" #~ msgstr "(用于日志的)内存耗尽\n" #~ msgid "Completed datastore conversion.\n" #~ msgstr "å·²å®Œæˆæ•°æ®ä»“库轮æ¢ã€‚\n" #~ msgid "" #~ "%s:%d - RPC %s:%p could not be registered: another callback is already " #~ "using this name (%p)\n" #~ msgstr "%s:%d - 无法注册 RPC %s:%p:å¦ä¸€è°ƒç”¨æ­£åœ¨ä½¿ç”¨æ­¤åç§°(%p)\n" #~ msgid "%s:%d - async RPC %s:%p could not be unregistered: not found\n" #~ msgstr "%s:%d - 异步 RPC %s:%p 无法解除注册:找ä¸åˆ°\n" #~ msgid "output in gnuplot format" #~ msgstr "以 gnuplot æ ¼å¼è¾“出" #~ msgid "number of messages to use per iteration" #~ msgstr "æ¯æ¬¡è¿­ä»£æ‰€ä½¿ç”¨çš„æ¶ˆæ¯æ•°é‡" #~ msgid "receiver host identifier (ENC file name)" #~ msgstr "接收方主机标识(ENC 文件å)" #~ msgid "message size" #~ msgstr "消æ¯å°ºå¯¸" #~ msgid "number of messages in a message block" #~ msgstr "一个消æ¯å—ä¸­çš„æ¶ˆæ¯æ•°é‡" #~ msgid "Error establishing connection with gnunetd.\n" #~ msgstr "通过 gnunetd 建立连接失败。\n" #~ msgid "Time:\n" #~ msgstr "时间:\n" #~ msgid "\tmax %llums\n" #~ msgstr "\t最长 %llu毫秒\n" #~ msgid "\tmin %llums\n" #~ msgstr "\t最短 %llu毫秒\n" #~ msgid "\tmean %8.4fms\n" #~ msgstr "\tå¹³å‡ %8.4f毫秒\n" #, fuzzy #~ msgid "\tvariance %8.4fms\n" #~ msgstr "\t波动 %8.4f毫秒\n" #~ msgid "Loss:\n" #~ msgstr "丢失:\n" #~ msgid "\tmax %u\n" #~ msgstr "\t最多 %u\n" #~ msgid "\tmin %u\n" #~ msgstr "\t最少 %u\n" #~ msgid "\tmean %8.4f\n" #~ msgstr "\tå¹³å‡ %8.4f\n" #, fuzzy #~ msgid "\tvariance %8.4f\n" #~ msgstr "\t波动 %8.4f\n" #~ msgid "Output format not known, this should not happen.\n" #~ msgstr "è¾“å‡ºæ ¼å¼æœªçŸ¥ï¼Œä¸åº”å‡ºçŽ°è¿™ç§æƒ…况。\n" #~ msgid "" #~ "\n" #~ "Did not receive the message from gnunetd. Is gnunetd running?\n" #~ msgstr "" #~ "\n" #~ "没有从 gnunetd 接收到消æ¯ã€‚gnunetd 在è¿è¡Œå—?\n" #~ msgid "" #~ "Failed to load MySQL database module. Check that MySQL is running and " #~ "configured properly!\n" #~ msgstr "加载 MySQL æ•°æ®åº“模å—失败。请检查 MySQL 是å¦è¿è¡Œå’Œæ˜¯å¦é…置正确ï¼\n" #, fuzzy #~ msgid "Command `%s' requires an argument (`%s').\n" #~ msgstr "%s:选项“%sâ€è¦æ±‚æœ‰ä¸€ä¸ªå‚æ•°\n" #, fuzzy #~ msgid "Command `%s' requires two arguments (`%s' and `%s').\n" #~ msgstr "%s:选项“%sâ€è¦æ±‚æœ‰ä¸€ä¸ªå‚æ•°\n" #~ msgid "" #~ "OS tells us about very large message (%u bytes) pending on UDP socket, " #~ "truncating at 64k\n" #~ msgstr "" #~ "æ“作系统通知,在 UPnP å¥—æŽ¥å­—ä¸Šæœ‰å¤§é‡æ¶ˆæ¯å¾…处ç†(%u 字节),将截短为64k\n" #~ msgid "" #~ "Couldn't find a group (`%s') for the new user and none was specified.\n" #~ msgstr "找ä¸åˆ°æ–°ç”¨æˆ·çš„组(“%sâ€)且没有指定用户组。\n" #~ msgid "Failed to find a free system id for the new group.\n" #~ msgstr "无法为新组找到一个空闲的系统标识。\n" #~ msgid "Failed to find a free system id for the new user.\n" #~ msgstr "无法为新用户找到一个个空闲的系统标识。\n" gnunet-0.10.1/po/de.po0000644000175000017500000137635012320736474011407 00000000000000# German translations for GNUnet package # German messages for GNUnet. # Copyright (C) 2004, 2005 Christian Grothoff # This file is distributed under the same license as the GNUnet package. # Christian Grothoff , 2004, 2005. msgid "" msgstr "" "Project-Id-Version: GNUnet 0.7.0b\n" "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n" "POT-Creation-Date: 2014-04-08 11:11+0200\n" "PO-Revision-Date: 2006-03-17 21:37+0100\n" "Last-Translator: Nils Durner \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: src/arm/arm_api.c:337 msgid "Client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/arm_monitor_api.c:321 msgid "" "Monitoring client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/gnunet-arm.c:164 #, fuzzy, c-format msgid "Failed to remove configuration file %s\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/arm/gnunet-arm.c:170 #, fuzzy, c-format msgid "Failed to remove servicehome directory %s\n" msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #: src/arm/gnunet-arm.c:216 src/testbed/gnunet-service-testbed_peers.c:1013 msgid "Message was sent successfully" msgstr "" #: src/arm/gnunet-arm.c:218 #, fuzzy msgid "Misconfiguration (can not connect to the ARM service)" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/arm/gnunet-arm.c:220 src/testbed/gnunet-service-testbed_peers.c:1017 #, fuzzy msgid "We disconnected from ARM before we could send a request" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/arm/gnunet-arm.c:222 src/testbed/gnunet-service-testbed_peers.c:1019 msgid "ARM API is busy" msgstr "" #: src/arm/gnunet-arm.c:224 msgid "Request does not fit into a message" msgstr "" #: src/arm/gnunet-arm.c:226 src/testbed/gnunet-service-testbed_peers.c:1023 #, fuzzy msgid "Request timed out" msgstr "# Sitzungsschlüssel akzeptiert" #: src/arm/gnunet-arm.c:228 src/testbed/gnunet-service-testbed_peers.c:1025 #, fuzzy msgid "Unknown request status" msgstr "Unbekannte Operation `%s'\n" #: src/arm/gnunet-arm.c:244 src/testbed/gnunet-service-testbed_peers.c:1041 #, fuzzy, c-format msgid "%s is stopped" msgstr "# bytes in der Datenbank" #: src/arm/gnunet-arm.c:246 src/testbed/gnunet-service-testbed_peers.c:1043 #, fuzzy, c-format msgid "%s is starting" msgstr "`%s' startet\n" #: src/arm/gnunet-arm.c:248 src/testbed/gnunet-service-testbed_peers.c:1045 #, c-format msgid "%s is stopping" msgstr "" #: src/arm/gnunet-arm.c:250 src/testbed/gnunet-service-testbed_peers.c:1047 #, fuzzy, c-format msgid "%s is starting already" msgstr "`%s' startet\n" #: src/arm/gnunet-arm.c:252 src/testbed/gnunet-service-testbed_peers.c:1049 #, c-format msgid "%s is stopping already" msgstr "" #: src/arm/gnunet-arm.c:254 src/testbed/gnunet-service-testbed_peers.c:1051 #, c-format msgid "%s is started already" msgstr "" #: src/arm/gnunet-arm.c:256 src/testbed/gnunet-service-testbed_peers.c:1053 #, c-format msgid "%s is stopped already" msgstr "" #: src/arm/gnunet-arm.c:258 src/testbed/gnunet-service-testbed_peers.c:1055 #, fuzzy, c-format msgid "%s service is not known to ARM" msgstr "Namespace `%s' hat das Rating %d.\n" #: src/arm/gnunet-arm.c:260 src/testbed/gnunet-service-testbed_peers.c:1057 #, fuzzy, c-format msgid "%s service failed to start" msgstr "Fehler beim Starten der Collection.\n" #: src/arm/gnunet-arm.c:262 #, fuzzy, c-format msgid "%s service cannot be started because ARM is shutting down" msgstr "`%s' fährt herunter.\n" #: src/arm/gnunet-arm.c:264 src/testbed/gnunet-service-testbed_peers.c:1061 #, c-format msgid "%.s Unknown result code." msgstr "" #: src/arm/gnunet-arm.c:297 msgid "Fatal error initializing ARM API.\n" msgstr "" #: src/arm/gnunet-arm.c:326 src/arm/gnunet-arm.c:335 #, fuzzy, c-format msgid "Failed to start the ARM service: %s\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/arm/gnunet-arm.c:369 #, fuzzy, c-format msgid "Failed to send a stop request to the ARM service: %s\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/arm/gnunet-arm.c:379 #, fuzzy, c-format msgid "Failed to stop the ARM service: %s\n" msgstr "Fehler beim Binden an UDP Port %d.\n" #: src/arm/gnunet-arm.c:421 #, fuzzy, c-format msgid "Failed to send a request to start the `%s' service: %%s\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/arm/gnunet-arm.c:431 #, fuzzy, c-format msgid "Failed to start the `%s' service: %s\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/arm/gnunet-arm.c:468 #, fuzzy, c-format msgid "Failed to send a request to kill the `%s' service: %%s\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/arm/gnunet-arm.c:479 #, fuzzy, c-format msgid "Failed to kill the `%s' service: %s\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/arm/gnunet-arm.c:517 #, fuzzy, c-format msgid "Failed to request a list of services: %s\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/arm/gnunet-arm.c:525 #, fuzzy msgid "Error communicating with ARM. ARM not running?\n" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/arm/gnunet-arm.c:530 #, fuzzy msgid "Running services:\n" msgstr "Collection `%s' begonnen.\n" #: src/arm/gnunet-arm.c:612 #, c-format msgid "Now only monitoring, press CTRL-C to stop.\n" msgstr "" #: src/arm/gnunet-arm.c:643 #, c-format msgid "Stopped %s.\n" msgstr "" #: src/arm/gnunet-arm.c:646 #, fuzzy, c-format msgid "Starting %s...\n" msgstr "Collection `%s' begonnen.\n" #: src/arm/gnunet-arm.c:649 #, c-format msgid "Stopping %s...\n" msgstr "" #: src/arm/gnunet-arm.c:660 #, fuzzy, c-format msgid "Unknown status %u for service %s.\n" msgstr "Unbekannte Operation `%s'\n" #: src/arm/gnunet-arm.c:724 msgid "stop all GNUnet services" msgstr "" #: src/arm/gnunet-arm.c:726 msgid "start a particular service" msgstr "" #: src/arm/gnunet-arm.c:728 msgid "stop a particular service" msgstr "" #: src/arm/gnunet-arm.c:730 msgid "start all GNUnet default services" msgstr "" #: src/arm/gnunet-arm.c:733 msgid "stop and start all GNUnet default services" msgstr "" #: src/arm/gnunet-arm.c:736 msgid "delete config file and directory on exit" msgstr "" #: src/arm/gnunet-arm.c:739 msgid "monitor ARM activities" msgstr "" #: src/arm/gnunet-arm.c:741 msgid "don't print status messages" msgstr "" #: src/arm/gnunet-arm.c:744 #, fuzzy msgid "timeout in MSECS milliseconds for completing current operation" msgstr "Zeit, die gewartet wird, bis der Durchlauf fertiggestellt wird (in ms)" #: src/arm/gnunet-arm.c:746 #, fuzzy msgid "list currently running services" msgstr "Collection `%s' begonnen.\n" #: src/arm/gnunet-arm.c:748 msgid "don't let gnunet-service-arm inherit standard output" msgstr "" #: src/arm/gnunet-arm.c:750 msgid "don't let gnunet-service-arm inherit standard error" msgstr "" #: src/arm/gnunet-arm.c:761 msgid "Control services and the Automated Restart Manager (ARM)" msgstr "" #: src/arm/gnunet-service-arm.c:266 #, fuzzy msgid "Could not send status result to client\n" msgstr "Anfrage konnte nicht an gnunetd gesendet werden.\n" #: src/arm/gnunet-service-arm.c:302 #, fuzzy msgid "Could not send list result to client\n" msgstr "Anfrage konnte nicht an gnunetd gesendet werden.\n" #: src/arm/gnunet-service-arm.c:529 #, fuzzy, c-format msgid "Failed to start service `%s'\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/arm/gnunet-service-arm.c:540 #, fuzzy, c-format msgid "Starting service `%s'\n" msgstr "Collection `%s' begonnen.\n" #: src/arm/gnunet-service-arm.c:639 #, fuzzy, c-format msgid "Unable to create socket for service `%s': %s\n" msgstr "Fehler beim Anlegen des Benutzerkontos:" #: src/arm/gnunet-service-arm.c:661 #, c-format msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:695 #, c-format msgid "ARM now monitors connections to service `%s' at `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:831 #, fuzzy, c-format msgid "Preparing to stop `%s'\n" msgstr "Collection `%s' begonnen.\n" #: src/arm/gnunet-service-arm.c:1100 #, fuzzy, c-format msgid "Restarting service `%s'.\n" msgstr "Collection `%s' begonnen.\n" #: src/arm/gnunet-service-arm.c:1193 msgid "exit" msgstr "" #: src/arm/gnunet-service-arm.c:1198 msgid "signal" msgstr "" #: src/arm/gnunet-service-arm.c:1203 #, fuzzy msgid "unknown" msgstr "Unbekannter Fehler" #: src/arm/gnunet-service-arm.c:1209 #, fuzzy, c-format msgid "Service `%s' took %s to terminate\n" msgstr "Dienst gelöscht.\n" #: src/arm/gnunet-service-arm.c:1231 #, c-format msgid "Service `%s' terminated normally, will restart at any time\n" msgstr "" #: src/arm/gnunet-service-arm.c:1246 #, c-format msgid "Service `%s' terminated with status %s/%d, will restart in %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:1500 #, fuzzy, c-format msgid "Starting default services `%s'\n" msgstr "Collection `%s' begonnen.\n" #: src/arm/gnunet-service-arm.c:1511 #, c-format msgid "Default service `%s' not configured correctly!\n" msgstr "" #: src/arm/gnunet-service-arm.c:1524 msgid "" "No default services configured, GNUnet will not really start right now.\n" msgstr "" #: src/arm/mockup-service.c:41 msgid "Initiating shutdown as requested by client.\n" msgstr "" #: src/ats/ats_api_performance.c:468 #, fuzzy, c-format msgid "Received %s message\n" msgstr "ungültige `%s' Nachricht empfangen\n" #: src/ats/ats_api_performance.c:511 #, fuzzy, c-format msgid "Received last message for %s \n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/ats/gnunet-ats-solver-eval.c:2199 src/ats/gnunet-ats-solver-eval.c:2233 #: src/ats/gnunet-service-ats_addresses.c:1980 #: src/ats/gnunet-service-ats_addresses.c:2024 #, c-format msgid "" "Could not load quota for network `%s': `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2205 #: src/ats/gnunet-service-ats_addresses.c:1987 #, c-format msgid "Outbound quota configure for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2212 #: src/ats/gnunet-service-ats_addresses.c:1995 #, c-format msgid "" "No outbound quota configured for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2239 #: src/ats/gnunet-service-ats_addresses.c:2031 #, c-format msgid "Inbound quota configured for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2246 #: src/ats/gnunet-service-ats_addresses.c:2039 #, c-format msgid "" "No outbound quota configure for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2671 #: src/ats-tests/gnunet-solver-eval.c:919 msgid "solver to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2674 src/ats/gnunet-ats-solver-eval.c:2677 #: src/ats-tests/gnunet-solver-eval.c:922 #: src/ats-tests/gnunet-solver-eval.c:925 msgid "experiment to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2680 #, fuzzy msgid "print logging" msgstr "Collection `%s' begonnen.\n" #: src/ats/gnunet-service-ats_addresses.c:2217 #, c-format msgid "Initializing solver `%s '`%s'\n" msgstr "" #: src/ats/gnunet-service-ats_addresses.c:2220 #, fuzzy, c-format msgid "Failed to initialize solver `%s'!\n" msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n" #: src/ats/gnunet-service-ats_addresses.c:2243 #, fuzzy msgid "Failed to initialize solver!\n" msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n" #: src/ats/plugin_ats_mlp.c:892 msgid "Problem size too large, cannot allocate memory!\n" msgstr "" #: src/ats/plugin_ats_mlp.c:1329 #, fuzzy, c-format msgid "Adding address for peer `%s' multiple times\n" msgstr "Adresse des Knotens `%s' konnte nicht ermittelt werden.\n" #: src/ats/plugin_ats_mlp.c:1376 #, c-format msgid "Updating address property `%s' for peer `%s' %p not added before\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2122 #, c-format msgid "" "Adjusting inconsistent outbound quota configuration for network `%s', is " "%llu must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2131 #, c-format msgid "" "Adjusting inconsistent inbound quota configuration for network `%s', is %llu " "must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2142 #, c-format msgid "" "Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2150 #, c-format msgid "" "Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2161 #, c-format msgid "Using default quota configuration for network `%s' (in/out) %llu/%llu\n" msgstr "" #: src/ats/plugin_ats_proportional.c:1511 #, fuzzy, c-format msgid "Invalid network type `%u' `%s': Disconnect!\n" msgstr "IP des Hosts `%s' konnte nicht ermittelt werden: %s\n" #: src/ats-tests/ats-testing.c:72 msgid "Benchmarking done\n" msgstr "" #: src/ats-tests/ats-testing.c:105 #, fuzzy, c-format msgid "Failed to connect peer 0 and %u\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/ats-tests/ats-testing.c:413 #, c-format msgid "Connected master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:419 #, fuzzy, c-format msgid "Failed to connect master peer [%u] with slave [%u]\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/ats-tests/ats-testing.c:450 msgid "Connecting peers on CORE level\n" msgstr "" #: src/ats-tests/ats-testing.c:461 #, c-format msgid "Connecting master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:470 #, fuzzy, c-format msgid "Could not connect master [%u] and slave [%u]\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/ats-tests/ats-testing.c:490 src/ats-tests/ats-testing.c:671 #, fuzzy msgid "Initialization failed, shutdown\n" msgstr "Initialisierung des Plugin Mechanismuses fehlgeschlagen: %s!\n" #: src/ats-tests/ats-testing-log.c:842 msgid "Stop logging\n" msgstr "" #: src/ats-tests/ats-testing-log.c:893 #, fuzzy, c-format msgid "Start logging `%s'\n" msgstr "Collection `%s' begonnen.\n" #: src/ats-tests/gnunet-ats-sim.c:86 #, c-format msgid "" "Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. " "= %u KiB/s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:169 #, c-format msgid "%u address resolutions had a timeout\n" msgstr "" #: src/ats-tool/gnunet-ats.c:171 #, c-format msgid "ATS returned results for %u addresses\n" msgstr "" #: src/ats-tool/gnunet-ats.c:232 #, fuzzy, c-format msgid "" "Peer `%s' plugin `%s', address `%s', `%s' bw out: %u Bytes/s, bw in %u Bytes/" "s, %s\n" msgstr "Knoten `%s' mit Vertrauen %8u und Adresse `%s'\n" #: src/ats-tool/gnunet-ats.c:413 #, c-format msgid "Quota for network `%11s' (in/out): %10s / %10s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:433 src/core/gnunet-core.c:163 #: src/namestore/gnunet-namestore.c:550 src/transport/gnunet-transport.c:1246 #, fuzzy, c-format msgid "Service `%s' is not running\n" msgstr "`%s' ist keine Datei.\n" #: src/ats-tool/gnunet-ats.c:445 src/transport/gnunet-transport.c:1255 #, fuzzy, c-format msgid "Failed to parse peer identity `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/ats-tool/gnunet-ats.c:454 #, c-format msgid "Please select one operation : %s or %s or %s or %s or %s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:470 src/ats-tool/gnunet-ats.c:489 #: src/ats-tool/gnunet-ats.c:506 src/ats-tool/gnunet-ats.c:543 #, fuzzy, c-format msgid "Cannot connect to ATS service, exiting...\n" msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/ats-tool/gnunet-ats.c:478 src/ats-tool/gnunet-ats.c:495 #, fuzzy, c-format msgid "Cannot issue request to ATS service, exiting...\n" msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/ats-tool/gnunet-ats.c:515 #, fuzzy, c-format msgid "No preference type given!\n" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/ats-tool/gnunet-ats.c:520 #, c-format msgid "No peer given!\n" msgstr "" #: src/ats-tool/gnunet-ats.c:536 msgid "Valid type required\n" msgstr "" #: src/ats-tool/gnunet-ats.c:594 msgid "get list of active addresses currently used" msgstr "" #: src/ats-tool/gnunet-ats.c:596 msgid "get list of all active addresses" msgstr "" #: src/ats-tool/gnunet-ats.c:599 #, fuzzy msgid "do not resolve IP addresses to hostnames" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/ats-tool/gnunet-ats.c:601 msgid "monitor mode" msgstr "" #: src/ats-tool/gnunet-ats.c:603 #, fuzzy msgid "set preference for the given peer" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/ats-tool/gnunet-ats.c:605 msgid "print all configured quotas" msgstr "" #: src/ats-tool/gnunet-ats.c:607 msgid "peer id" msgstr "" #: src/ats-tool/gnunet-ats.c:610 msgid "preference type to set: latency | bandwidth" msgstr "" #: src/ats-tool/gnunet-ats.c:612 msgid "preference value" msgstr "" #: src/ats-tool/gnunet-ats.c:615 msgid "verbose output (include ATS address properties)" msgstr "" #: src/ats-tool/gnunet-ats.c:622 #, fuzzy msgid "Print information about ATS state" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/consensus/gnunet-consensus-profiler.c:437 #: src/secretsharing/gnunet-secretsharing-profiler.c:535 #, fuzzy msgid "number of peers in consensus" msgstr "Anzahl an Durchläufen" #: src/consensus/gnunet-consensus-profiler.c:440 msgid "how many peers receive one value?" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:443 #: src/set/gnunet-set-profiler.c:286 src/set/gnunet-set-profiler.c:289 #: src/set/gnunet-set-profiler.c:292 #, fuzzy msgid "number of values" msgstr "Anzahl an Durchläufen" #: src/consensus/gnunet-consensus-profiler.c:446 #, fuzzy msgid "consensus timeout" msgstr "# Sitzungsschlüssel akzeptiert" #: src/consensus/gnunet-consensus-profiler.c:449 msgid "delay until consensus starts" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:452 #: src/secretsharing/gnunet-secretsharing-profiler.c:550 msgid "be more verbose (print received values)" msgstr "" #: src/conversation/conversation_api.c:557 #: src/conversation/conversation_api_call.c:470 msgid "Connection to conversation service lost, trying to reconnect\n" msgstr "" #: src/conversation/gnunet-conversation.c:264 #, c-format msgid "Incoming call from `%s'. Please /accept #%u or /cancel %u the call.\n" msgstr "" #: src/conversation/gnunet-conversation.c:286 #, c-format msgid "Call from `%s' terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:319 #, c-format msgid "Call from `%s' suspended by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:324 #, c-format msgid "Call from `%s' resumed by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:342 #, c-format msgid "Ego `%s' no longer available, phone is now down.\n" msgstr "" #: src/conversation/gnunet-conversation.c:356 #, fuzzy msgid "Failed to setup phone (internal error)\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/conversation/gnunet-conversation.c:368 #, c-format msgid "" "Phone active on line %u. Type `/help' for a list of available commands\n" msgstr "" #: src/conversation/gnunet-conversation.c:390 #, c-format msgid "Resolved address of `%s'. Now ringing other party.\n" msgstr "" #: src/conversation/gnunet-conversation.c:397 #, fuzzy, c-format msgid "Connection established to `%s'\n" msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #: src/conversation/gnunet-conversation.c:404 #, fuzzy, c-format msgid "Failed to resolve `%s'\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/conversation/gnunet-conversation.c:411 msgid "Call terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:417 #, c-format msgid "Connection to `%s' suspended (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:423 #, c-format msgid "Connection to `%s' resumed (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:428 msgid "Error with the call, restarting it\n" msgstr "" #: src/conversation/gnunet-conversation.c:495 #, fuzzy, c-format msgid "Unknown command `%s'\n" msgstr "Unbekannte Operation `%s'\n" #: src/conversation/gnunet-conversation.c:511 #: src/conversation/gnunet-conversation.c:525 #, fuzzy, c-format msgid "Ego `%s' not available\n" msgstr "gconfig ist nicht verfügbar\n" #: src/conversation/gnunet-conversation.c:518 #: src/conversation/gnunet-conversation.c:575 msgid "You are calling someone else already, hang up first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:533 #: src/conversation/gnunet-conversation.c:588 #, c-format msgid "You are answering call from `%s', hang up or suspend that call first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:544 msgid "Call recipient missing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:599 msgid "There is no incoming call to accept here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:616 #, c-format msgid "There is no incoming call `%s' to accept right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:647 msgid "We currently do not have an address.\n" msgstr "" #: src/conversation/gnunet-conversation.c:670 #, c-format msgid "We are currently trying to locate the private key for the ego `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:675 #, c-format msgid "We are listening for incoming calls for ego `%s' on line %u.\n" msgstr "" #: src/conversation/gnunet-conversation.c:681 #: src/conversation/gnunet-conversation.c:705 #, c-format msgid "You are having a conversation with `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:686 msgid "" "We had an internal error setting up our phone line. You can still make " "calls.\n" msgstr "" #: src/conversation/gnunet-conversation.c:695 #, fuzzy, c-format msgid "We are trying to find the network address to call `%s'.\n" msgstr "GNUnet verwendet nun die IP-Adresse %u.%u.%u.%u.\n" #: src/conversation/gnunet-conversation.c:700 #, c-format msgid "We are calling `%s', his phone should be ringing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:719 msgid "Calls waiting:\n" msgstr "" #: src/conversation/gnunet-conversation.c:725 #, fuzzy, c-format msgid "#%u: `%s'\n" msgstr "Ich bin Peer `%s'.\n" #: src/conversation/gnunet-conversation.c:753 #: src/conversation/gnunet-conversation.c:768 msgid "There is no call that could be suspended right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:801 #: src/conversation/gnunet-conversation.c:817 msgid "There is no call that could be resumed right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:824 #, c-format msgid "Already talking with `%s', cannot resume a call right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:833 msgid "There is no incoming call to resume here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:850 #, c-format msgid "There is no incoming call `%s' to resume right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:885 msgid "There is no call that could be cancelled right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:893 msgid "There is no incoming call to refuse here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:910 #, c-format msgid "There is no incoming call `%s' to refuse right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:937 msgid "Use `/address' to find out which address this phone should have in GNS" msgstr "" #: src/conversation/gnunet-conversation.c:939 msgid "Use `/call USER.gnu' to call USER" msgstr "" #: src/conversation/gnunet-conversation.c:941 msgid "Use `/accept #NUM' to accept incoming call #NUM" msgstr "" #: src/conversation/gnunet-conversation.c:943 msgid "Use `/suspend' to suspend the active call" msgstr "" #: src/conversation/gnunet-conversation.c:945 msgid "" "Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming " "calls, no argument is needed to resume the current outgoing call." msgstr "" #: src/conversation/gnunet-conversation.c:947 msgid "Use `/cancel' to reject or terminate a call" msgstr "" #: src/conversation/gnunet-conversation.c:949 msgid "Use `/status' to print status information" msgstr "" #: src/conversation/gnunet-conversation.c:951 #, fuzzy msgid "Use `/quit' to terminate gnunet-conversation" msgstr "Erlaubt es Clients die Konfiguration von gnunetd abzufragen" #: src/conversation/gnunet-conversation.c:953 msgid "Use `/help command' to get help for a specific command" msgstr "" #: src/conversation/gnunet-conversation.c:1151 #, fuzzy, c-format msgid "Name of our ego changed to `%s'\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/conversation/gnunet-conversation.c:1164 #, fuzzy, c-format msgid "Our ego `%s' was deleted!\n" msgstr "Pseudonym `%s' wurde gelöscht.\n" #: src/conversation/gnunet-conversation.c:1199 #, fuzzy msgid "You must specify the NAME of an ego to use\n" msgstr "Sie müssen eine Liste von Dateien zum Einfügen angeben.\n" #: src/conversation/gnunet-conversation.c:1223 #, fuzzy msgid "Failed to start gnunet-helper-w32-console\n" msgstr "Fehler beim Starten der Collection.\n" #: src/conversation/gnunet-conversation.c:1249 msgid "sets the NAME of the ego to use for the phone (and name resolution)" msgstr "" #: src/conversation/gnunet-conversation.c:1252 msgid "sets the LINE to use for the phone" msgstr "" #: src/conversation/gnunet-conversation.c:1276 msgid "Enables having a conversation with other GNUnet users." msgstr "" #: src/conversation/gnunet-conversation-test.c:121 #, c-format msgid "" "\n" "End of transmission. Have a GNU day.\n" msgstr "" #: src/conversation/gnunet-conversation-test.c:149 #, c-format msgid "" "\n" "We are now playing your recording back. If you can hear it, your audio " "settings are working..." msgstr "" #: src/conversation/gnunet-conversation-test.c:215 #, c-format msgid "" "We will now be recording you for %s. After that time, the recording will be " "played back to you..." msgstr "" #: src/conversation/gnunet-conversation-test.c:248 #: src/multicast/gnunet-multicast.c:70 src/revocation/gnunet-revocation.c:522 #: src/template/gnunet-template.c:70 #, fuzzy msgid "help text" msgstr "Hilfetext für -t" #: src/conversation/gnunet-helper-audio-playback.c:305 #, fuzzy, c-format msgid "pa_stream_write() failed: %s\n" msgstr "`%s' schlug fehl: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:587 msgid "gnunet-helper-audio-playback - Got signal, exiting\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:612 #: src/conversation/gnunet-helper-audio-record.c:545 #, fuzzy msgid "Connection established.\n" msgstr "Collection beendet.\n" #: src/conversation/gnunet-helper-audio-playback.c:617 #: src/conversation/gnunet-helper-audio-record.c:550 #, fuzzy, c-format msgid "pa_stream_new() failed: %s\n" msgstr "`%s' schlug fehl: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:631 #, c-format msgid "pa_stream_connect_playback() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:644 #: src/conversation/gnunet-helper-audio-record.c:576 #, fuzzy, c-format msgid "Connection failure: %s\n" msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #: src/conversation/gnunet-helper-audio-playback.c:665 #: src/conversation/gnunet-helper-audio-record.c:599 msgid "Wrong Spec\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:671 #: src/conversation/gnunet-helper-audio-record.c:605 #, fuzzy msgid "pa_mainloop_new() failed.\n" msgstr "Absicherung fehlgeschlagen bei %s:%d.\n" #: src/conversation/gnunet-helper-audio-playback.c:685 #: src/conversation/gnunet-helper-audio-record.c:620 #, fuzzy msgid "pa_context_new() failed.\n" msgstr "Absicherung fehlgeschlagen bei %s:%d.\n" #: src/conversation/gnunet-helper-audio-playback.c:692 #: src/conversation/gnunet-helper-audio-record.c:626 #, fuzzy, c-format msgid "pa_context_connect() failed: %s\n" msgstr "`%s' schlug fehl: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:698 #: src/conversation/gnunet-helper-audio-record.c:632 #, fuzzy msgid "pa_mainloop_run() failed.\n" msgstr "Absicherung fehlgeschlagen bei %s:%d.\n" #: src/conversation/gnunet-helper-audio-playback.c:768 #, c-format msgid "Read error from STDIN: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback-gst.c:325 #, c-format msgid "Read error from STDIN: %d %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:344 #, fuzzy, c-format msgid "opus_encode_float() failed: %s. Aborting\n" msgstr "`%s' schlug fehl: %s\n" #: src/conversation/gnunet-helper-audio-record.c:420 #, fuzzy, c-format msgid "pa_stream_peek() failed: %s\n" msgstr "`%s' schlug fehl: %s\n" #: src/conversation/gnunet-helper-audio-record.c:458 msgid "Got signal, exiting.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:483 #, fuzzy msgid "Stream successfully created.\n" msgstr "Zugriff verweigert für `%s' bei %s:%d.\n" #: src/conversation/gnunet-helper-audio-record.c:488 #, fuzzy, c-format msgid "pa_stream_get_buffer_attr() failed: %s\n" msgstr "`%s' schlug fehl: %s\n" #: src/conversation/gnunet-helper-audio-record.c:496 #, c-format msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:500 #, c-format msgid "Using sample spec '%s', channel map '%s'.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:507 #, fuzzy, c-format msgid "Connected to device %s (%u, %ssuspended).\n" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/conversation/gnunet-helper-audio-record.c:516 #, c-format msgid "Stream error: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:563 #, fuzzy, c-format msgid "pa_stream_connect_record() failed: %s\n" msgstr "" "\n" "Fehler beim Uploaden der Datei: %s\n" #: src/conversation/gnunet-helper-audio-record.c:676 #, fuzzy msgid "ogg_stream_init() failed.\n" msgstr "`%s' schlug fehl: %s\n" #: src/conversation/gnunet-helper-audio-record.c:721 #, fuzzy, c-format msgid "Failed to allocate %d bytes for second packet\n" msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #: src/conversation/gnunet-service-conversation.c:841 msgid "Mesh audio channel not ready; audio data dropped\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:932 #, c-format msgid "" "No available phone for incoming call on line %u, sending HANG_UP signal\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:1338 #, fuzzy, c-format msgid "Received incoming channel on port %u\n" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/conversation/microphone.c:121 #, fuzzy msgid "Could not start record audio helper\n" msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #: src/conversation/plugin_gnsrecord_conversation.c:116 #, fuzzy, c-format msgid "Unable to parse PHONE record `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/conversation/speaker.c:75 #, fuzzy msgid "Could not start playback audio helper.\n" msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #: src/core/core_api.c:767 msgid "Client was disconnected from core service, trying to reconnect.\n" msgstr "" #: src/core/gnunet-core.c:80 #, fuzzy, c-format msgid "Peer `%s'\n" msgstr "Ich bin Peer `%s'.\n" #: src/core/gnunet-core.c:110 src/core/gnunet-core.c:138 #: src/transport/gnunet-transport.c:910 src/transport/gnunet-transport.c:930 #, c-format msgid "%24s: %-17s %4s (%u connections in total)\n" msgstr "" #: src/core/gnunet-core.c:112 src/transport/gnunet-transport.c:911 #, fuzzy msgid "Connected to" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/core/gnunet-core.c:140 src/transport/gnunet-transport.c:931 #, fuzzy msgid "Disconnected from" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/core/gnunet-core.c:211 src/peerinfo-tool/gnunet-peerinfo.c:694 #, fuzzy, c-format msgid "Invalid command line argument `%s'\n" msgstr "Ungültige Kommandozeilen Parameter:\n" #: src/core/gnunet-core.c:233 src/transport/gnunet-transport.c:1486 #, fuzzy msgid "provide information about all current connections (continuously)" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/core/gnunet-core.c:244 #, fuzzy msgid "Print information about connected peers." msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/core/gnunet-service-core.c:105 #, fuzzy msgid "Core service is lacking HOSTKEY configuration setting. Exiting.\n" msgstr "GNUnet Konfiguration" #: src/core/gnunet-service-core.c:126 #, c-format msgid "Core service of `%4s' ready.\n" msgstr "" #: src/core/gnunet-service-core_clients.c:370 #, fuzzy msgid "# send requests dropped (disconnected)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/core/gnunet-service-core_clients.c:480 #, fuzzy msgid "# messages discarded (session disconnected)" msgstr "# defragmentierter Nachrichten" #: src/core/gnunet-service-core_clients.c:526 #, fuzzy, c-format msgid "# bytes of messages of type %u received" msgstr "# Bytes Rauschen empfangen" #: src/core/gnunet-service-core_kx.c:535 msgid "# bytes encrypted" msgstr "# Bytes verschlüsselt" #: src/core/gnunet-service-core_kx.c:586 msgid "# bytes decrypted" msgstr "# Bytes entschlüsselt" #: src/core/gnunet-service-core_kx.c:673 msgid "# key exchanges initiated" msgstr "" #: src/core/gnunet-service-core_kx.c:713 msgid "# key exchanges stopped" msgstr "" #: src/core/gnunet-service-core_kx.c:810 msgid "# old ephemeral keys ignored" msgstr "" #: src/core/gnunet-service-core_kx.c:816 #, fuzzy msgid "# ephemeral keys received" msgstr "# verschlüsselter PING Nachrichten empfangen" #: src/core/gnunet-service-core_kx.c:850 #, c-format msgid "" "Ephemeral key message from peer `%s' rejected as its validity range does not " "match our system time (%llu not in [%llu,%llu]).\n" msgstr "" #: src/core/gnunet-service-core_kx.c:861 #, fuzzy msgid "# EPHEMERAL_KEY messages received" msgstr "# defragmentierter Nachrichten" #: src/core/gnunet-service-core_kx.c:951 #: src/transport/gnunet-service-transport_validation.c:1016 #, fuzzy msgid "# PING messages received" msgstr "# PING Nachrichten erstellt" #: src/core/gnunet-service-core_kx.c:959 #, fuzzy msgid "# PING messages dropped (out of order)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/core/gnunet-service-core_kx.c:986 #, c-format msgid "" "Received PING from `%s' for different identity: I am `%s', PONG identity: `" "%s'\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1003 #, fuzzy msgid "# PONG messages created" msgstr "# PING Nachrichten erstellt" #: src/core/gnunet-service-core_kx.c:1029 #, fuzzy msgid "# sessions terminated by timeout" msgstr "# Bytes verworfen von TCP (ausgehend)" #: src/core/gnunet-service-core_kx.c:1039 #, fuzzy msgid "# keepalive messages sent" msgstr "# Klartext PING Nachrichten gesendet" #: src/core/gnunet-service-core_kx.c:1096 #: src/transport/gnunet-service-transport_validation.c:1328 #, fuzzy msgid "# PONG messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/core/gnunet-service-core_kx.c:1102 #, fuzzy msgid "# PONG messages dropped (connection down)" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/core/gnunet-service-core_kx.c:1107 #, fuzzy msgid "# PONG messages dropped (out of order)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/core/gnunet-service-core_kx.c:1137 #, fuzzy msgid "# PONG messages decrypted" msgstr "# PING Nachrichten erstellt" #: src/core/gnunet-service-core_kx.c:1171 #, fuzzy msgid "# session keys confirmed via PONG" msgstr "# Knotenankündigungen empfangen" #: src/core/gnunet-service-core_kx.c:1181 #, fuzzy msgid "# timeouts prevented via PONG" msgstr "# Bytes empfangen über TCP" #: src/core/gnunet-service-core_kx.c:1188 #, fuzzy msgid "# rekey operations confirmed via PONG" msgstr "# Knotenankündigungen empfangen" #: src/core/gnunet-service-core_kx.c:1328 #, fuzzy msgid "# DATA message dropped (out of order)" msgstr "# Bytes verworfen von UDP (outgoing)" #: src/core/gnunet-service-core_kx.c:1335 #, c-format msgid "" "Session to peer `%s' went down due to key expiration (should not happen)\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1338 #, fuzzy msgid "# sessions terminated by key expiration" msgstr "# Bytes verworfen von TCP (ausgehend)" #: src/core/gnunet-service-core_kx.c:1383 #: src/core/gnunet-service-core_kx.c:1408 #, fuzzy msgid "# bytes dropped (duplicates)" msgstr "# Bytes verworfen von UDP (outgoing)" #: src/core/gnunet-service-core_kx.c:1395 #, fuzzy msgid "# bytes dropped (out of sequence)" msgstr "# Bytes verworfen von UDP (outgoing)" #: src/core/gnunet-service-core_kx.c:1437 #, fuzzy msgid "# bytes dropped (ancient message)" msgstr "# Bytes verworfen von UDP (outgoing)" #: src/core/gnunet-service-core_kx.c:1445 #, fuzzy msgid "# bytes of payload decrypted" msgstr "# Bytes entschlüsselt" #: src/core/gnunet-service-core_kx.c:1480 #, fuzzy msgid "# PAYLOAD dropped (out of order)" msgstr "# Bytes verworfen von UDP (outgoing)" #: src/core/gnunet-service-core_neighbours.c:168 #, fuzzy msgid "# sessions terminated by transport disconnect" msgstr "# Knotenankündigungen empfangen" #: src/core/gnunet-service-core_neighbours.c:184 #: src/core/gnunet-service-core_neighbours.c:335 msgid "# neighbour entries allocated" msgstr "" #: src/core/gnunet-service-core_neighbours.c:252 msgid "# encrypted bytes given to transport" msgstr "" #: src/core/gnunet-service-core_neighbours.c:418 #, fuzzy, c-format msgid "Unsupported message of type %u (%u bytes) received from peer `%s'\n" msgstr "Ungültige Nachricht des Typs %u empfangen. Nachricht wird verworfen.\n" #: src/core/gnunet-service-core_sessions.c:216 #: src/core/gnunet-service-core_sessions.c:288 #: src/dht/gnunet-service-dht_neighbours.c:662 #: src/dht/gnunet-service-dht_neighbours.c:727 #: src/dht/gnunet-service-xdht_neighbours.c:1304 #: src/fs/gnunet-service-fs_cp.c:606 src/fs/gnunet-service-fs_cp.c:1501 #: src/topology/gnunet-daemon-topology.c:707 #: src/topology/gnunet-daemon-topology.c:808 #: src/transport/gnunet-service-transport_neighbours.c:917 #: src/transport/gnunet-service-transport_neighbours.c:1141 #: src/transport/gnunet-service-transport_neighbours.c:3142 #: src/transport/gnunet-service-transport_neighbours.c:3438 #, fuzzy msgid "# peers connected" msgstr "# verbundener Knoten" #: src/core/gnunet-service-core_sessions.c:255 #, fuzzy msgid "# type map refreshes sent" msgstr "# p2p Trace-Antworten gesendet" #: src/core/gnunet-service-core_sessions.c:426 msgid "# messages discarded (expired prior to transmission)" msgstr "" #: src/core/gnunet-service-core_typemap.c:110 #: src/core/gnunet-service-core_typemap.c:121 #, fuzzy msgid "# type maps received" msgstr "# verschlüsselter PING Nachrichten empfangen" #: src/core/gnunet-service-core_typemap.c:151 msgid "# updates to my type map" msgstr "" #: src/datacache/datacache.c:115 src/datacache/datacache.c:266 #: src/datastore/gnunet-service-datastore.c:838 #, fuzzy msgid "# bytes stored" msgstr "# bytes in der Datenbank" #: src/datacache/datacache.c:117 src/datacache/datacache.c:268 #, fuzzy msgid "# items stored" msgstr "# bytes in der Datenbank" #: src/datacache/datacache.c:143 src/datacache/datacache.c:150 #: src/datastore/gnunet-service-datastore.c:1487 #: src/datastore/gnunet-service-datastore.c:1498 #, fuzzy, c-format msgid "No `%s' specified for `%s' in configuration!\n" msgstr "In der Konfigurationsdatei wurden keine Anwendungen definiert!\n" #: src/datacache/datacache.c:184 #, c-format msgid "Loading `%s' datacache plugin\n" msgstr "" #: src/datacache/datacache.c:192 #, fuzzy, c-format msgid "Failed to load datacache plugin for `%s'\n" msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n" #: src/datacache/datacache.c:295 #, fuzzy msgid "# requests received" msgstr "# Client Trace-Anfragen empfangen" #: src/datacache/datacache.c:304 msgid "# requests filtered by bloom filter" msgstr "" #: src/datacache/plugin_datacache_heap.c:406 #, fuzzy msgid "Heap datacache running\n" msgstr "sqlite Datenspeicher" #: src/datacache/plugin_datacache_postgres.c:392 msgid "Postgres datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:69 #: src/datacache/plugin_datacache_sqlite.c:72 #: src/datastore/plugin_datastore_mysql.c:806 #: src/datastore/plugin_datastore_mysql.c:820 #: src/datastore/plugin_datastore_sqlite.c:57 src/mysql/mysql.c:41 #: src/mysql/mysql.c:48 src/mysql/mysql.c:522 src/mysql/mysql.c:531 #: src/mysql/mysql.c:591 src/mysql/mysql.c:607 #: src/namecache/plugin_namecache_postgres.c:52 #: src/namecache/plugin_namecache_sqlite.c:52 #: src/namestore/plugin_namestore_postgres.c:52 #: src/namestore/plugin_namestore_sqlite.c:52 #: src/testbed/generate-underlay-topology.c:47 #: src/testbed/gnunet-daemon-latency-logger.c:52 #: src/testbed/gnunet-daemon-testbed-underlay.c:55 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:51 #: src/util/crypto_mpi.c:39 src/include/gnunet_common.h:602 #: src/include/gnunet_common.h:611 src/scalarproduct/scalarproduct.h:50 #, c-format msgid "`%s' failed at %s:%d with error: %s\n" msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #: src/datacache/plugin_datacache_sqlite.c:450 msgid "Sqlite datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:484 #: src/datastore/plugin_datastore_sqlite.c:404 #: src/namecache/plugin_namecache_sqlite.c:295 #: src/namestore/plugin_namestore_sqlite.c:327 msgid "Tried to close sqlite without finalizing all prepared statements.\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:491 #, fuzzy, c-format msgid "Failed to close statement %p: %d\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/datacache/plugin_datacache_template.c:125 msgid "Template datacache running\n" msgstr "" #: src/datastore/datastore_api.c:310 #, fuzzy msgid "Failed to transmit request to drop database.\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/datastore/datastore_api.c:394 msgid "# queue entry timeouts" msgstr "" #: src/datastore/datastore_api.c:443 msgid "# queue overflows" msgstr "" #: src/datastore/datastore_api.c:471 #, fuzzy msgid "# queue entries created" msgstr "# dht Anfragen weitergeleitet" #: src/datastore/datastore_api.c:491 #, fuzzy msgid "# Requests dropped from datastore queue" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/datastore/datastore_api.c:533 msgid "# datastore connections (re)created" msgstr "" #: src/datastore/datastore_api.c:616 src/scalarproduct/scalarproduct_api.c:279 #, fuzzy msgid "# transmission request failures" msgstr "# Klartext PONG Nachrichten empfangen" #: src/datastore/datastore_api.c:638 #, fuzzy msgid "# bytes sent to datastore" msgstr "# bytes in der Datenbank" #: src/datastore/datastore_api.c:770 #, fuzzy msgid "Failed to receive status response from database." msgstr "" "\n" "Fehler beim Empfangen der Antwort von gnunetd.\n" #: src/datastore/datastore_api.c:784 msgid "Error reading response from datastore service" msgstr "" #: src/datastore/datastore_api.c:796 src/datastore/datastore_api.c:802 #, fuzzy msgid "Invalid error message received from datastore service" msgstr "Ungültige `%s' Nachricht von Knoten `%s' empfangen.\n" #: src/datastore/datastore_api.c:806 #, fuzzy msgid "# status messages received" msgstr "# verschlüsselter PING Nachrichten empfangen" #: src/datastore/datastore_api.c:876 #, fuzzy msgid "# PUT requests executed" msgstr "# dht Anfragen weitergeleitet" #: src/datastore/datastore_api.c:944 #, fuzzy msgid "# RESERVE requests executed" msgstr "# dht Anfragen weitergeleitet" #: src/datastore/datastore_api.c:1005 msgid "# RELEASE RESERVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1065 #, fuzzy msgid "# UPDATE requests executed" msgstr "# dht Anfragen weitergeleitet" #: src/datastore/datastore_api.c:1129 #, fuzzy msgid "# REMOVE requests executed" msgstr "# dht Anfragen weitergeleitet" #: src/datastore/datastore_api.c:1174 #, fuzzy msgid "Failed to receive response from database.\n" msgstr "" "\n" "Fehler beim Empfangen der Antwort von gnunetd.\n" #: src/datastore/datastore_api.c:1233 #, fuzzy msgid "# Results received" msgstr "# Bytes empfangen über TCP" #: src/datastore/datastore_api.c:1300 msgid "# GET REPLICATION requests executed" msgstr "" #: src/datastore/datastore_api.c:1363 msgid "# GET ZERO ANONYMITY requests executed" msgstr "" #: src/datastore/datastore_api.c:1424 #, fuzzy msgid "# GET requests executed" msgstr "# dht Anfragen weitergeleitet" #: src/datastore/gnunet-datastore.c:114 #, fuzzy, c-format msgid "Failed to store item: %s, aborting\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/datastore/gnunet-datastore.c:200 #, c-format msgid "Cannot use the same configuration for source and destination\n" msgstr "" #: src/datastore/gnunet-datastore.c:246 msgid "" "specifies the configuration to use to access an alternative datastore; will " "merge that datastore into our current datastore" msgstr "" #: src/datastore/gnunet-datastore.c:255 #, fuzzy msgid "Manipulate GNUnet datastore" msgstr "" "Einen Wert aus der Konfigurationsdatei auf der Standardausgabe ausgeben" #: src/datastore/gnunet-service-datastore.c:351 #, fuzzy msgid "# bytes expired" msgstr "# Bytes empfangen über TCP" #: src/datastore/gnunet-service-datastore.c:425 msgid "# bytes purged (low-priority)" msgstr "" #: src/datastore/gnunet-service-datastore.c:483 #: src/gns/gnunet-gns-helper-service-w32.c:223 msgid "Transmission to client failed!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:514 #: src/gns/gnunet-gns-helper-service-w32.c:262 msgid "Shutdown in progress, aborting transmission.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:630 msgid "# results found" msgstr "" #: src/datastore/gnunet-service-datastore.c:673 #, c-format msgid "" "Insufficient space (%llu bytes are available) to satisfy `%s' request for " "%llu bytes\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:684 #, c-format msgid "" "The requested amount (%llu bytes) is larger than the cache size (%llu " "bytes)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:688 msgid "" "Insufficient space to satisfy request and requested amount is larger than " "cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:694 msgid "Insufficient space to satisfy request" msgstr "" #: src/datastore/gnunet-service-datastore.c:699 #: src/datastore/gnunet-service-datastore.c:751 #: src/datastore/gnunet-service-datastore.c:964 #: src/datastore/gnunet-service-datastore.c:1421 msgid "# reserved" msgstr "" #: src/datastore/gnunet-service-datastore.c:764 msgid "Could not find matching reservation" msgstr "" #: src/datastore/gnunet-service-datastore.c:850 #, c-format msgid "Need %llu bytes more space (%llu allowed, using %llu)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1010 #, fuzzy msgid "# GET requests received" msgstr "# Client Trace-Anfragen empfangen" #: src/datastore/gnunet-service-datastore.c:1022 msgid "# requests filtered by bloomfilter" msgstr "" #: src/datastore/gnunet-service-datastore.c:1050 #, fuzzy msgid "# UPDATE requests received" msgstr "# Client Trace-Anfragen empfangen" #: src/datastore/gnunet-service-datastore.c:1080 #, fuzzy msgid "# GET REPLICATION requests received" msgstr "# Client Trace-Anfragen empfangen" #: src/datastore/gnunet-service-datastore.c:1113 #, fuzzy msgid "# GET ZERO ANONYMITY requests received" msgstr "# Client Trace-Anfragen empfangen" #: src/datastore/gnunet-service-datastore.c:1138 #, fuzzy msgid "Content not found" msgstr "Kommando `%s' wurde nicht gefunden!\n" #: src/datastore/gnunet-service-datastore.c:1146 msgid "# bytes removed (explicit request)" msgstr "" #: src/datastore/gnunet-service-datastore.c:1178 #, fuzzy msgid "# REMOVE requests received" msgstr "# Client Trace-Anfragen empfangen" #: src/datastore/gnunet-service-datastore.c:1220 #, c-format msgid "Datastore payload inaccurate (%lld < %lld). Trying to fix.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1281 #, c-format msgid "Loading `%s' datastore plugin\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1290 #, fuzzy, c-format msgid "Failed to load datastore plugin for `%s'\n" msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #: src/datastore/gnunet-service-datastore.c:1492 #, fuzzy, c-format msgid "# bytes used in file-sharing datastore `%s'" msgstr "# bytes erlaubt in der Datenbank" #: src/datastore/gnunet-service-datastore.c:1503 msgid "# quota" msgstr "" #: src/datastore/gnunet-service-datastore.c:1505 msgid "# cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:1518 #, c-format msgid "Could not use specified filename `%s' for bloomfilter.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1536 #: src/datastore/gnunet-service-datastore.c:1552 #, fuzzy, c-format msgid "Failed to remove bogus bloomfilter file `%s'\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/datastore/gnunet-service-datastore.c:1582 #, fuzzy msgid "Failed to initialize bloomfilter.\n" msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n" #: src/datastore/gnunet-service-datastore.c:1611 msgid "Rebuilding bloomfilter. Please be patient.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1616 msgid "Plugin does not support get_keys function. Please fix!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1619 msgid "Bloomfilter construction complete.\n" msgstr "" #: src/datastore/plugin_datastore_heap.c:820 #, fuzzy msgid "Heap database running\n" msgstr "sqlite Datenspeicher" #: src/datastore/plugin_datastore_mysql.c:783 #, fuzzy, c-format msgid "Failed to prepare statement `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/datastore/plugin_datastore_mysql.c:791 #, fuzzy, c-format msgid "`%s' for `%s' failed at %s:%d with error: %s\n" msgstr "`%s' an `%s' schlug fehl bei %s:%d mit dem Fehler: %s\n" #: src/datastore/plugin_datastore_mysql.c:1022 msgid "Mysql database running\n" msgstr "" #: src/datastore/plugin_datastore_postgres.c:824 #, fuzzy msgid "Failed to drop table from database.\n" msgstr "" "\n" "Fehler beim Empfangen der Antwort von gnunetd.\n" #: src/datastore/plugin_datastore_postgres.c:860 #: src/namecache/plugin_namecache_postgres.c:414 #: src/namestore/plugin_namestore_postgres.c:569 msgid "Postgres database running\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:57 #: src/testbed/generate-underlay-topology.c:50 #: src/testbed/gnunet-daemon-latency-logger.c:55 #: src/testbed/gnunet-daemon-testbed-underlay.c:58 #, fuzzy, c-format msgid "`%s' failed at %s:%u with error: %s" msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #: src/datastore/plugin_datastore_sqlite.c:255 #: src/namecache/plugin_namecache_sqlite.c:193 #: src/namestore/plugin_namestore_sqlite.c:204 #: src/psycstore/plugin_psycstore_sqlite.c:319 #, c-format msgid "Unable to initialize SQLite: %s.\n" msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n" #: src/datastore/plugin_datastore_sqlite.c:663 #, fuzzy msgid "Invalid data in database. Trying to fix (by deletion).\n" msgstr "Ungültige Daten in %s. Korrektur wird versucht (durch Löschung).\n" #: src/datastore/plugin_datastore_sqlite.c:1156 msgid "sqlite version to old to determine size, assuming zero\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1175 #, c-format msgid "" "Using sqlite page utilization to estimate payload (%llu pages of size %llu " "bytes)\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1215 #: src/namecache/plugin_namecache_sqlite.c:583 #: src/namestore/plugin_namestore_sqlite.c:719 #, fuzzy msgid "Sqlite database running\n" msgstr "sqlite Datenspeicher" #: src/datastore/plugin_datastore_template.c:257 msgid "Template database running\n" msgstr "" #: src/dht/dht_api.c:376 #, fuzzy msgid "Failed to connect to the DHT service!\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/dht/gnunet-dht-get.c:133 #, c-format msgid "" "Result %d, type %d:\n" "%.*s\n" msgstr "" #: src/dht/gnunet-dht-get.c:159 msgid "Must provide key for DHT GET!\n" msgstr "" #: src/dht/gnunet-dht-get.c:165 src/dht/gnunet-dht-monitor.c:225 #, fuzzy msgid "Failed to connect to DHT service!\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/dht/gnunet-dht-get.c:173 msgid "Issueing DHT GET with key" msgstr "" #: src/dht/gnunet-dht-get.c:189 src/dht/gnunet-dht-monitor.c:262 #: src/dht/gnunet-dht-put.c:198 msgid "the query key" msgstr "" #: src/dht/gnunet-dht-get.c:192 msgid "how many parallel requests (replicas) to create" msgstr "" #: src/dht/gnunet-dht-get.c:195 src/dht/gnunet-dht-monitor.c:265 msgid "the type of data to look for" msgstr "" #: src/dht/gnunet-dht-get.c:198 src/dht/gnunet-dht-put.c:210 msgid "how long to execute this query before giving up?" msgstr "" #: src/dht/gnunet-dht-get.c:201 src/dht/gnunet-dht-put.c:201 msgid "use DHT's demultiplex everywhere option" msgstr "" #: src/dht/gnunet-dht-get.c:204 src/dht/gnunet-dht-monitor.c:271 #: src/dht/gnunet-dht-put.c:213 src/fs/gnunet-auto-share.c:753 #: src/fs/gnunet-download.c:328 src/fs/gnunet-publish.c:877 #: src/fs/gnunet-search.c:301 src/fs/gnunet-unindex.c:168 #: src/nse/gnunet-nse-profiler.c:873 msgid "be verbose (print progress information)" msgstr "" #: src/dht/gnunet-dht-get.c:225 msgid "Issue a GET request to the GNUnet DHT, prints results." msgstr "" #: src/dht/gnunet-dht-monitor.c:268 msgid "how long should the monitor command run" msgstr "" #: src/dht/gnunet-dht-monitor.c:293 msgid "Prints all packets that go through the DHT." msgstr "" #: src/dht/gnunet-dht-put.c:118 #, fuzzy msgid "PUT request sent with key" msgstr "# gap Anfragen insgesamt empfangen" #: src/dht/gnunet-dht-put.c:121 msgid "Timeout sending PUT request!\n" msgstr "" #: src/dht/gnunet-dht-put.c:124 #, fuzzy msgid "PUT request not confirmed!\n" msgstr "# gap Anfragen insgesamt empfangen" #: src/dht/gnunet-dht-put.c:153 msgid "Must provide KEY and DATA for DHT put!\n" msgstr "" #: src/dht/gnunet-dht-put.c:160 #, fuzzy, c-format msgid "Could not connect to %s service!\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/dht/gnunet-dht-put.c:176 #, c-format msgid "Issuing put request for `%s' with data `%s'!\n" msgstr "" #: src/dht/gnunet-dht-put.c:192 msgid "the data to insert under the key" msgstr "" #: src/dht/gnunet-dht-put.c:195 msgid "how long to store this entry in the dht (in seconds)" msgstr "" #: src/dht/gnunet-dht-put.c:204 msgid "how many replicas to create" msgstr "" #: src/dht/gnunet-dht-put.c:207 msgid "the type to insert data as" msgstr "" #: src/dht/gnunet-dht-put.c:236 msgid "Issue a PUT request to the GNUnet DHT insert DATA under KEY." msgstr "" #: src/dht/gnunet-service-dht.c:172 src/dht/gnunet-service-xdht.c:176 #, fuzzy msgid "Failed to connect to transport service!\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/dht/gnunet-service-dht_clients.c:417 #: src/dht/gnunet-service-xdht_clients.c:838 #, fuzzy msgid "# GET requests from clients injected" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_clients.c:513 #: src/dht/gnunet-service-xdht_clients.c:927 #, fuzzy msgid "# PUT requests received from clients" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/dht/gnunet-service-dht_clients.c:597 #: src/dht/gnunet-service-xdht_clients.c:1013 #, fuzzy msgid "# GET requests received from clients" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/dht/gnunet-service-dht_clients.c:798 #: src/dht/gnunet-service-xdht_clients.c:1214 #, fuzzy msgid "# GET STOP requests received from clients" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/dht/gnunet-service-dht_clients.c:1039 #: src/dht/gnunet-service-xdht_clients.c:498 msgid "# Key match, type mismatches in REPLY to CLIENT" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1052 #: src/dht/gnunet-service-xdht_clients.c:511 msgid "# Duplicate REPLIES to CLIENT request dropped" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1089 #: src/dht/gnunet-service-xdht_clients.c:548 #, fuzzy, c-format msgid "Unsupported block type (%u) in request!\n" msgstr "Ungültige Nachricht des Typs %u empfangen. Nachricht wird verworfen.\n" #: src/dht/gnunet-service-dht_clients.c:1112 #: src/dht/gnunet-service-xdht_clients.c:571 #, fuzzy msgid "# RESULTS queued for clients" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/dht/gnunet-service-dht_clients.c:1166 #: src/dht/gnunet-service-dht_clients.c:1209 #: src/dht/gnunet-service-xdht_clients.c:625 #: src/dht/gnunet-service-xdht_clients.c:668 msgid "# REPLIES ignored for CLIENTS (no match)" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1176 #: src/dht/gnunet-service-xdht_clients.c:635 #, fuzzy msgid "Could not pass reply to client, message too big!\n" msgstr "'join' Nachricht konnte nicht an gnunetd gesendet werden.\n" #: src/dht/gnunet-service-dht_datacache.c:68 #: src/dht/gnunet-service-xdht_datacache.c:68 #, fuzzy, c-format msgid "%s request received, but have no datacache!\n" msgstr "# Bytes empfangen über TCP" #: src/dht/gnunet-service-dht_datacache.c:78 #: src/dht/gnunet-service-xdht_datacache.c:78 msgid "# ITEMS stored in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:165 #: src/dht/gnunet-service-xdht_datacache.c:165 msgid "# Good RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:176 #: src/dht/gnunet-service-xdht_datacache.c:176 msgid "# Duplicate RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:182 #: src/dht/gnunet-service-xdht_datacache.c:182 msgid "# Invalid RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:188 #: src/dht/gnunet-service-xdht_datacache.c:188 msgid "# Irrelevant RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:200 #: src/dht/gnunet-service-xdht_datacache.c:200 msgid "# Unsupported RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:203 #: src/dht/gnunet-service-xdht_datacache.c:203 #, c-format msgid "Unsupported block type (%u) in local response!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:234 #: src/dht/gnunet-service-xdht_datacache.c:234 #, fuzzy msgid "# GET requests given to datacache" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_hello.c:84 #: src/dht/gnunet-service-xdht_hello.c:82 #, fuzzy msgid "# HELLOs obtained from peerinfo" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/dht/gnunet-service-dht_neighbours.c:516 msgid "# Preference updates given to core" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:610 #, fuzzy msgid "# FIND PEER messages initiated" msgstr "# PING Nachrichten erstellt" #: src/dht/gnunet-service-dht_neighbours.c:764 #, fuzzy msgid "# Queued messages discarded (peer disconnected)" msgstr "# defragmentierter Nachrichten" #: src/dht/gnunet-service-dht_neighbours.c:819 #: src/dht/gnunet-service-xdht_neighbours.c:703 #, fuzzy msgid "# Bytes transmitted to other peers" msgstr "# Bytes des Typs %d übertragen" #: src/dht/gnunet-service-dht_neighbours.c:857 #: src/dht/gnunet-service-xdht_neighbours.c:742 #, fuzzy msgid "# Bytes of bandwidth requested from core" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_neighbours.c:889 #, fuzzy msgid "# requests TTL-dropped" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_neighbours.c:1093 #: src/dht/gnunet-service-dht_neighbours.c:1130 msgid "# Peers excluded from routing due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1108 #: src/dht/gnunet-service-dht_neighbours.c:1145 #, fuzzy msgid "# Peer selection failed" msgstr " Verbindung fehlgeschlagen\n" #: src/dht/gnunet-service-dht_neighbours.c:1287 #, fuzzy msgid "# PUT requests routed" msgstr "# dht Anfragen weitergeleitet" #: src/dht/gnunet-service-dht_neighbours.c:1316 #, fuzzy msgid "# PUT messages queued for transmission" msgstr "# PING Nachrichten erstellt" #: src/dht/gnunet-service-dht_neighbours.c:1323 #: src/dht/gnunet-service-dht_neighbours.c:1440 #: src/dht/gnunet-service-dht_neighbours.c:1543 #: src/dht/gnunet-service-xdht_neighbours.c:794 #: src/dht/gnunet-service-xdht_neighbours.c:860 #: src/dht/gnunet-service-xdht_neighbours.c:919 #: src/dht/gnunet-service-xdht_neighbours.c:981 #: src/dht/gnunet-service-xdht_neighbours.c:1041 #, fuzzy msgid "# P2P messages dropped due to full queue" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/dht/gnunet-service-dht_neighbours.c:1405 #, fuzzy msgid "# GET requests routed" msgstr "# dht Anfragen weitergeleitet" #: src/dht/gnunet-service-dht_neighbours.c:1432 #, fuzzy msgid "# GET messages queued for transmission" msgstr "# PING Nachrichten erstellt" #: src/dht/gnunet-service-dht_neighbours.c:1550 #, fuzzy msgid "# RESULT messages queued for transmission" msgstr "# PING Nachrichten erstellt" #: src/dht/gnunet-service-dht_neighbours.c:1636 #, fuzzy msgid "# P2P PUT requests received" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_neighbours.c:1639 #, fuzzy msgid "# P2P PUT bytes received" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_neighbours.c:1803 msgid "# FIND PEER requests ignored due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1811 msgid "# FIND PEER requests ignored due to lack of HELLO" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1904 #, fuzzy msgid "# P2P GET requests received" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_neighbours.c:1907 #, fuzzy msgid "# P2P GET bytes received" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_neighbours.c:1961 #, fuzzy msgid "# P2P FIND PEER requests processed" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_neighbours.c:1975 #, fuzzy msgid "# P2P GET requests ONLY routed" msgstr "# dht Anfragen weitergeleitet" #: src/dht/gnunet-service-dht_neighbours.c:2052 #, fuzzy msgid "# P2P RESULTS received" msgstr "# Bytes empfangen über TCP" #: src/dht/gnunet-service-dht_neighbours.c:2055 #, fuzzy msgid "# P2P RESULT bytes received" msgstr "# Bytes empfangen über TCP" #: src/dht/gnunet-service-dht_nse.c:59 src/dht/gnunet-service-xdht_nse.c:59 #, fuzzy msgid "# Network size estimates received" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-dht_routing.c:211 msgid "# Good REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:220 msgid "# Duplicate REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:226 msgid "# Invalid REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:232 msgid "# Irrelevant REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:244 msgid "# Unsupported REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:317 msgid "# Entries removed from routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:399 msgid "# Entries added to routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:417 #, fuzzy msgid "# DHT requests combined" msgstr "# Client Trace-Anfragen empfangen" #: src/dht/gnunet-service-xdht_neighbours.c:1398 #, c-format msgid "" "\n" "SUPU %s, %s, %d,my_identity = %s" msgstr "" #: src/dht/gnunet-service-xdht_neighbours.c:1514 #: src/dht/gnunet-service-xdht_neighbours.c:1524 #: src/dht/gnunet-service-xdht_neighbours.c:1530 #: src/dht/gnunet-service-xdht_neighbours.c:1536 #: src/dht/gnunet-service-xdht_neighbours.c:1545 #, c-format msgid "" "\n" "SUPU %s, %s, %d" msgstr "" #: src/dht/plugin_block_dht.c:138 #, fuzzy, c-format msgid "Block not of type %u\n" msgstr "Kein Transport des Typs %d bekannt.\n" #: src/dht/plugin_block_dht.c:145 msgid "Size mismatch for block\n" msgstr "" #: src/dht/plugin_block_dht.c:155 #, c-format msgid "Block of type %u is malformed\n" msgstr "" #: src/dns/dnsparser.c:257 #, fuzzy, c-format msgid "Failed to convert DNS IDNA name `%s' to UTF-8: %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/dns/dnsparser.c:856 #, fuzzy, c-format msgid "Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/dns/dnsstub.c:175 #, fuzzy, c-format msgid "Could not bind to any port: %s\n" msgstr "IP des Hosts `%s' konnte nicht ermittelt werden: %s\n" #: src/dns/dnsstub.c:295 src/dns/dnsstub.c:383 #, fuzzy, c-format msgid "Failed to send DNS request to %s\n" msgstr "HTTP Anfrage konnte nicht an Host `%s' gesendet werden: %s\n" #: src/dns/dnsstub.c:299 #, fuzzy, c-format msgid "Sent DNS request to %s\n" msgstr "# Client Trace-Anfragen empfangen" #: src/dns/dnsstub.c:368 #, c-format msgid "Configured DNS exit `%s' is not working / valid.\n" msgstr "" #: src/dns/dnsstub.c:440 #, c-format msgid "Received DNS response that is too small (%u bytes)" msgstr "" #: src/dns/gnunet-dns-monitor.c:355 msgid "only monitor DNS queries" msgstr "" #: src/dns/gnunet-dns-monitor.c:358 msgid "only monitor DNS replies" msgstr "" #: src/dns/gnunet-dns-monitor.c:369 msgid "Monitor DNS queries." msgstr "" #: src/dns/gnunet-dns-redirector.c:236 msgid "set A records" msgstr "" #: src/dns/gnunet-dns-redirector.c:239 msgid "set AAAA records" msgstr "" #: src/dns/gnunet-dns-redirector.c:251 msgid "Change DNS replies to point elsewhere." msgstr "" #: src/dns/gnunet-service-dns.c:456 msgid "# DNS requests answered via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:603 msgid "# DNS exit failed (failed to open socket)" msgstr "" #: src/dns/gnunet-service-dns.c:714 msgid "# External DNS response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:792 msgid "# Client response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:907 msgid "Received malformed IPv4-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:923 msgid "Received malformed IPv6-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:932 #, c-format msgid "Got non-IP packet with %u bytes and protocol %u from TUN\n" msgstr "" #: src/dns/gnunet-service-dns.c:942 msgid "# Non-DNS UDP packet received via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:1009 #, fuzzy msgid "# DNS requests received via TUN interface" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/dns/gnunet-service-dns.c:1049 src/exit/gnunet-daemon-exit.c:3514 #, c-format msgid "`%s' must be installed SUID, refusing to run\n" msgstr "" #: src/dns/gnunet-service-dns.c:1069 src/exit/gnunet-daemon-exit.c:3571 #, fuzzy msgid "need a valid IPv4 or IPv6 address\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/dv/gnunet-dv.c:169 msgid "verbose output" msgstr "" #: src/dv/gnunet-dv.c:178 #, fuzzy msgid "Print information about DV state" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/exit/gnunet-daemon-exit.c:802 #, c-format msgid "Got duplicate service records for `%s:%u'\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:853 #, fuzzy msgid "# Bytes transmitted via mesh channels" msgstr "# Bytes des Typs %d übertragen" #: src/exit/gnunet-daemon-exit.c:970 src/exit/gnunet-daemon-exit.c:2397 #: src/exit/gnunet-daemon-exit.c:2654 src/vpn/gnunet-service-vpn.c:1407 #: src/vpn/gnunet-service-vpn.c:1797 src/vpn/gnunet-service-vpn.c:1960 msgid "# ICMPv4 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1007 src/exit/gnunet-daemon-exit.c:2456 #: src/exit/gnunet-daemon-exit.c:2713 src/vpn/gnunet-service-vpn.c:1463 #: src/vpn/gnunet-service-vpn.c:1856 src/vpn/gnunet-service-vpn.c:1993 msgid "# ICMPv6 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1047 msgid "# ICMP packets dropped (not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1054 msgid "ICMP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1130 msgid "UDP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1204 msgid "TCP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1256 #, fuzzy msgid "# Packets received from TUN" msgstr "# Bytes empfangen über HTTP" #: src/exit/gnunet-daemon-exit.c:1270 #, fuzzy msgid "# Bytes received from TUN" msgstr "# Bytes empfangen über HTTP" #: src/exit/gnunet-daemon-exit.c:1296 msgid "IPv4 packet options received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1323 #, c-format msgid "IPv4 packet with unsupported next header %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1369 #, c-format msgid "IPv6 packet with unsupported next header %d received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1377 #, c-format msgid "Packet from unknown protocol %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1759 #, fuzzy msgid "# TCP packets sent via TUN" msgstr "# Bytes gesendet über UDP" #: src/exit/gnunet-daemon-exit.c:1872 #, fuzzy msgid "# TCP service creation requests received via mesh" msgstr "# Client Trace-Anfragen empfangen" #: src/exit/gnunet-daemon-exit.c:1875 src/exit/gnunet-daemon-exit.c:1968 #: src/exit/gnunet-daemon-exit.c:2073 src/exit/gnunet-daemon-exit.c:2321 #: src/exit/gnunet-daemon-exit.c:2570 src/exit/gnunet-daemon-exit.c:2859 #: src/exit/gnunet-daemon-exit.c:2966 #, fuzzy msgid "# Bytes received from MESH" msgstr "# Bytes empfangen über HTTP" #: src/exit/gnunet-daemon-exit.c:1909 src/exit/gnunet-daemon-exit.c:2990 #, c-format msgid "No service %s found for %s on port %d!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1914 #, fuzzy msgid "# TCP requests dropped (no such service)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/exit/gnunet-daemon-exit.c:1971 #, fuzzy msgid "# TCP IP-exit creation requests received via mesh" msgstr "# Client Trace-Anfragen empfangen" #: src/exit/gnunet-daemon-exit.c:2076 #, fuzzy msgid "# TCP data requests received via mesh" msgstr "# Client Trace-Anfragen empfangen" #: src/exit/gnunet-daemon-exit.c:2090 #, fuzzy msgid "# TCP DATA requests dropped (no session)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/exit/gnunet-daemon-exit.c:2150 #, fuzzy msgid "# ICMP packets sent via TUN" msgstr "# Bytes gesendet über UDP" #: src/exit/gnunet-daemon-exit.c:2324 #, fuzzy msgid "# ICMP IP-exit requests received via mesh" msgstr "# Client Trace-Anfragen empfangen" #: src/exit/gnunet-daemon-exit.c:2573 #, fuzzy msgid "# ICMP service requests received via mesh" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/exit/gnunet-daemon-exit.c:2639 src/vpn/gnunet-service-vpn.c:1397 #: src/vpn/gnunet-service-vpn.c:1954 msgid "# ICMPv4 packets dropped (impossible PT to v6)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2698 src/vpn/gnunet-service-vpn.c:1433 #: src/vpn/gnunet-service-vpn.c:1445 src/vpn/gnunet-service-vpn.c:1844 msgid "# ICMPv6 packets dropped (impossible PT to v4)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2748 #, fuzzy msgid "# UDP packets sent via TUN" msgstr "# Bytes gesendet über UDP" #: src/exit/gnunet-daemon-exit.c:2862 #, fuzzy msgid "# UDP IP-exit requests received via mesh" msgstr "# Client Trace-Anfragen empfangen" #: src/exit/gnunet-daemon-exit.c:2969 #, fuzzy msgid "# UDP service requests received via mesh" msgstr "# Client Trace-Anfragen empfangen" #: src/exit/gnunet-daemon-exit.c:2995 #, fuzzy msgid "# UDP requests dropped (no such service)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/exit/gnunet-daemon-exit.c:3031 #, fuzzy msgid "# Inbound MESH channels created" msgstr "# dht Anfragen weitergeleitet" #: src/exit/gnunet-daemon-exit.c:3235 src/exit/gnunet-daemon-exit.c:3245 #, fuzzy, c-format msgid "Option `%s' for domain `%s' is not formatted correctly!\n" msgstr "%s: Option `%s' ist mehrdeutig\n" #: src/exit/gnunet-daemon-exit.c:3259 src/exit/gnunet-daemon-exit.c:3267 #, c-format msgid "`%s' is not a valid port number (for domain `%s')!" msgstr "" #: src/exit/gnunet-daemon-exit.c:3300 #, c-format msgid "No addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3314 src/exit/gnunet-daemon-exit.c:3326 #, c-format msgid "Service `%s' configured for IPv4, but IPv4 is disabled!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3337 #, c-format msgid "No IP addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3527 msgid "" "This system does not support IPv4, will disable IPv4 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3535 msgid "" "This system does not support IPv6, will disable IPv6 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3542 msgid "" "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use " "ENABLE_IPv4=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3548 msgid "" "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use " "ENABLE_IPv6=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3554 src/exit/gnunet-daemon-exit.c:3717 #: src/pt/gnunet-daemon-pt.c:1247 msgid "No useful service enabled. Exiting.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3664 msgid "Must be a number" msgstr "" #: src/exit/gnunet-daemon-exit.c:3813 msgid "Daemon to run to provide an IP exit node for the VPN" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:55 msgid "Experimentation daemon shutting down ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:77 msgid "Experimentation daemon starting ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:83 #, fuzzy msgid "Failed to create statistics!\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/experimentation/gnunet-daemon-experimentation.c:120 msgid "GNUnet experimentation daemon" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:241 #, c-format msgid "Experiment `%s': Experiment signature is invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:250 #, c-format msgid "" "Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu " "sec. \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:303 #, c-format msgid "Experiment `%s': Issuer missing\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:312 #, c-format msgid "Experiment `%s': Issuer invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:320 #, c-format msgid "Experiment `%s': Issuer not accepted!\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:330 #, c-format msgid "Experiment `%s': Version missing or invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:339 #, c-format msgid "Experiment `%s': Required capabilities missing \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:345 #, c-format msgid "Experiment `%s': Required capabilities invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:390 #, fuzzy, c-format msgid "Failed to parse file `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:420 #: src/experimentation/gnunet-daemon-experimentation_experiments.c:452 msgid "" "No valid experiment issuers configured! Set value to public keys of issuers! " "Exiting.\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:435 #, fuzzy msgid "Invalid value for public key\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:473 #, fuzzy, c-format msgid "Cannot read experiments file `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:221 #, c-format msgid "Cannot send message to peer `%s' for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:309 #, c-format msgid "Sending experimentation request to peer %s\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:453 #, c-format msgid "Added peer `%s' as active node\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:891 #, fuzzy, c-format msgid "Connected to peer %s\n" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:921 #, fuzzy, c-format msgid "Disconnected from peer %s\n" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:1104 #, fuzzy msgid "Failed to connect to CORE service!\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:108 #, c-format msgid "Peer `%s' did not respond to request for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:143 #, fuzzy, c-format msgid "Starting inbound experiment `%s' with peer `%s'\n" msgstr "Collection `%s' begonnen.\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:276 #, fuzzy, c-format msgid "Starting outbound experiment `%s' with peer `%s'\n" msgstr "Collection `%s' begonnen.\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:294 #, fuzzy, c-format msgid "Received %s message from peer %s for experiment `%s'\n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/fragmentation/defragmentation.c:270 msgid "# acknowledgements sent for fragment" msgstr "" #: src/fragmentation/defragmentation.c:456 #, fuzzy msgid "# fragments received" msgstr "# verworfener Nachrichten" #: src/fragmentation/defragmentation.c:521 #, fuzzy msgid "# duplicate fragments received" msgstr "# Bytes empfangen über TCP" #: src/fragmentation/defragmentation.c:534 msgid "# messages defragmented" msgstr "# defragmentierter Nachrichten" #: src/fragmentation/fragmentation.c:208 #, fuzzy msgid "# fragments transmitted" msgstr "# Selbstbekanntmachungen übertragen" #: src/fragmentation/fragmentation.c:211 #, fuzzy msgid "# fragments retransmitted" msgstr "# Selbstbekanntmachungen übertragen" #: src/fragmentation/fragmentation.c:237 #, fuzzy msgid "# fragments wrap arounds" msgstr "# Selbstbekanntmachungen übertragen" #: src/fragmentation/fragmentation.c:281 msgid "# messages fragmented" msgstr "# fragmentierter Nachrichten" #: src/fragmentation/fragmentation.c:284 msgid "# total size of fragmented messages" msgstr "" #: src/fragmentation/fragmentation.c:405 #, fuzzy msgid "# fragment acknowledgements received" msgstr "# Knotenankündigungen empfangen" #: src/fragmentation/fragmentation.c:411 msgid "# bits removed from fragmentation ACKs" msgstr "" #: src/fragmentation/fragmentation.c:435 #, fuzzy msgid "# fragmentation transmissions completed" msgstr "# Klartext PONG Nachrichten empfangen" #: src/fs/fs_api.c:465 #, fuzzy, c-format msgid "Could not open file `%s': %s" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_api.c:474 #, fuzzy, c-format msgid "Could not read file `%s': %s" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_api.c:480 #, c-format msgid "Short read reading from file `%s'!" msgstr "" #: src/fs/fs_api.c:1066 #, fuzzy, c-format msgid "Failed to resume publishing information `%s': %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_api.c:1571 #, c-format msgid "Failure while resuming publishing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:1585 #, fuzzy, c-format msgid "Failed to resume publishing operation `%s': %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_api.c:2242 #, c-format msgid "Failure while resuming unindexing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2252 #, fuzzy, c-format msgid "Failed to resume unindexing operation `%s': %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_api.c:2378 src/fs/fs_api.c:2619 #, fuzzy, c-format msgid "Failed to resume sub-download `%s': %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_api.c:2395 #, fuzzy, c-format msgid "Failed to resume sub-search `%s': %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_api.c:2409 src/fs/fs_api.c:2428 src/fs/fs_api.c:2911 #, c-format msgid "Failure while resuming search operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2610 #, c-format msgid "Failed to resume sub-download `%s': could not open file `%s'\n" msgstr "" #: src/fs/fs_api.c:2855 msgid "Could not resume running search, will resume as paused search\n" msgstr "" #: src/fs/fs_api.c:2949 #, c-format msgid "Failure while resuming download operation `%s': %s\n" msgstr "" #: src/fs/fs_directory.c:208 #, fuzzy msgid "MAGIC mismatch. This is not a GNUnet directory.\n" msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #: src/fs/fs_download.c:322 #, fuzzy msgid "" "Recursive downloads of directories larger than 4 GB are not supported on 32-" "bit systems\n" msgstr "Rekursiver Download des Verzeichnisses `%s' bei %llu von %llu Bytes.\n" #: src/fs/fs_download.c:342 msgid "Directory too large for system address space\n" msgstr "" #: src/fs/fs_download.c:523 src/fs/fs_download.c:535 #, fuzzy, c-format msgid "Failed to open file `%s' for writing" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_download.c:905 #, fuzzy, c-format msgid "Failed to create directory for recursive download of `%s'\n" msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n" #: src/fs/fs_download.c:987 #, c-format msgid "" "Internal error or bogus download URI (expected %u bytes at depth %u and " "offset %llu/%llu, got %u bytes)" msgstr "" #: src/fs/fs_download.c:1013 msgid "internal error decrypting content" msgstr "" #: src/fs/fs_download.c:1036 #, fuzzy, c-format msgid "Download failed: could not open file `%s': %s" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_download.c:1046 #, fuzzy, c-format msgid "Failed to seek to offset %llu in file `%s': %s" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_download.c:1055 #, fuzzy, c-format msgid "Failed to write block of %u bytes at offset %llu in file `%s': %s" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_download.c:1153 #, fuzzy msgid "internal error decoding tree" msgstr "=\tFehler beim Lesen des Verzeichnisses.\n" #: src/fs/fs_download.c:1944 #, fuzzy msgid "Invalid URI" msgstr "Ungültiger Parameter: `%s'\n" #: src/fs/fs_getopt.c:192 #, c-format msgid "" "Unknown metadata type in metadata option `%s'. Using metadata type " "`unknown' instead.\n" msgstr "" #: src/fs/fs_list_indexed.c:90 #, fuzzy, c-format msgid "Failed to receive response for `%s' request from `%s' service.\n" msgstr "Fehler beim Empfangen der Antwort von gnunetd auf die `%s' Nachricht\n" #: src/fs/fs_list_indexed.c:113 #, fuzzy, c-format msgid "Failed to receive valid response for `%s' request from `%s' service.\n" msgstr "Fehler beim Empfangen der Antwort von gnunetd auf die `%s' Nachricht\n" #: src/fs/fs_list_indexed.c:151 #, fuzzy, c-format msgid "Failed to not connect to `%s' service.\n" msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/fs/fs_misc.c:126 #, fuzzy, c-format msgid "Did not find mime type `%s' in extension list.\n" msgstr "Knoten `%s' konnte nicht in der Routing Tabelle gefunden werden!\n" #: src/fs/fs_namespace.c:207 #, fuzzy, c-format msgid "Failed to open `%s' for writing: %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_namespace.c:229 #, fuzzy, c-format msgid "Failed to write `%s': %s\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/fs/fs_namespace.c:320 #, fuzzy, c-format msgid "Failed to read `%s': %s\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/fs/fs_namespace.c:466 #, fuzzy msgid "Failed to connect to datastore." msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/fs/fs_publish.c:125 src/fs/fs_publish.c:415 #, fuzzy, c-format msgid "Publishing failed: %s" msgstr "" "\n" "Fehler beim Uploaden der Datei: %s\n" #: src/fs/fs_publish.c:667 src/fs/fs_publish.c:684 src/fs/fs_publish.c:723 #: src/fs/fs_publish.c:744 src/fs/fs_publish.c:768 src/fs/fs_publish.c:914 #, fuzzy, c-format msgid "Can not index file `%s': %s. Will try to insert instead.\n" msgstr "Indizieren der Datei `%s' schlug fehl. Versuch Datei einzufügen...\n" #: src/fs/fs_publish.c:669 msgid "timeout on index-start request to `fs' service" msgstr "" #: src/fs/fs_publish.c:681 #, fuzzy msgid "unknown error" msgstr "Unbekannter Fehler" #: src/fs/fs_publish.c:725 msgid "failed to compute hash" msgstr "" #: src/fs/fs_publish.c:745 msgid "filename too long" msgstr "" #: src/fs/fs_publish.c:770 #, fuzzy msgid "could not connect to `fs' service" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/fs/fs_publish.c:793 #, fuzzy, c-format msgid "Failed to get file identifiers for `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/fs/fs_publish.c:862 #, fuzzy, c-format msgid "Recursive upload failed at `%s': %s" msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #: src/fs/fs_publish.c:868 #, fuzzy, c-format msgid "Recursive upload failed: %s" msgstr "" "\n" "Fehler beim Uploaden der Datei: %s\n" #: src/fs/fs_publish.c:915 #, fuzzy msgid "needs to be an actual file" msgstr "`%s' ist keine normale Datei.\n" #: src/fs/fs_publish.c:1151 #, c-format msgid "Insufficient space for publishing: %s" msgstr "" #: src/fs/fs_publish.c:1243 #, c-format msgid "Reserving space for %u entries and %llu bytes for publication\n" msgstr "" #: src/fs/fs_publish_ksk.c:219 #, fuzzy msgid "Could not connect to datastore." msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/fs/fs_publish_ublock.c:219 #, fuzzy msgid "Internal error." msgstr "Unbekannter Fehler.\n" #: src/fs/fs_search.c:813 #, fuzzy, c-format msgid "Failed to parse URI `%s': %s\n" msgstr "Datei `%s' hat URI: %s\n" #: src/fs/fs_search.c:872 #, c-format msgid "Got result with unknown block type `%d', ignoring" msgstr "" #: src/fs/fs_unindex.c:59 msgid "Failed to find given position in file" msgstr "" #: src/fs/fs_unindex.c:64 #, fuzzy msgid "Failed to read file" msgstr "Zustellung der Nachricht `%s' fehlgeschlagen.\n" #: src/fs/fs_unindex.c:234 msgid "Unexpected time for a response from `fs' service." msgstr "" #: src/fs/fs_unindex.c:242 msgid "Timeout waiting for `fs' service." msgstr "" #: src/fs/fs_unindex.c:250 #, fuzzy msgid "Invalid response from `fs' service." msgstr "Ungültige Antwort auf `%s'.\n" #: src/fs/fs_unindex.c:291 #, fuzzy msgid "Failed to connect to FS service for unindexing." msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/fs/fs_unindex.c:347 src/fs/fs_unindex.c:359 #, fuzzy msgid "Failed to get KSKs from directory scan." msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #: src/fs/fs_unindex.c:355 #, fuzzy, c-format msgid "Internal error scanning `%s'.\n" msgstr "=\tFehler beim Lesen des Verzeichnisses.\n" #: src/fs/fs_unindex.c:414 #, fuzzy, c-format msgid "Failed to remove UBlock: %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/fs_unindex.c:562 src/fs/fs_unindex.c:626 #, fuzzy msgid "Failed to connect to `datastore' service." msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/fs/fs_unindex.c:639 #, fuzzy msgid "Failed to open file for unindexing." msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/fs/fs_unindex.c:673 #, fuzzy msgid "Failed to compute hash of file." msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/fs/fs_uri.c:222 #, no-c-format msgid "`%' must be followed by HEX number" msgstr "" #: src/fs/fs_uri.c:281 #, fuzzy msgid "Malformed KSK URI (must not begin or end with `+')" msgstr "Ungültige URL `%s' (muss mit `%s' beginnen)\n" #: src/fs/fs_uri.c:299 msgid "`++' not allowed in KSK URI" msgstr "" #: src/fs/fs_uri.c:306 msgid "Quotes not balanced in KSK URI" msgstr "" #: src/fs/fs_uri.c:376 msgid "Malformed SKS URI" msgstr "" #: src/fs/fs_uri.c:419 src/fs/fs_uri.c:434 msgid "Malformed CHK URI" msgstr "" #: src/fs/fs_uri.c:512 src/fs/fs_uri.c:580 msgid "SKS URI malformed" msgstr "" #: src/fs/fs_uri.c:527 src/fs/fs_uri.c:537 msgid "LOC URI malformed" msgstr "" #: src/fs/fs_uri.c:545 src/fs/fs_uri.c:553 msgid "LOC URI malformed (could not decode public key)" msgstr "" #: src/fs/fs_uri.c:559 msgid "SKS URI malformed (could not find signature)" msgstr "" #: src/fs/fs_uri.c:565 src/fs/fs_uri.c:574 msgid "SKS URI malformed (could not decode signature)" msgstr "" #: src/fs/fs_uri.c:586 msgid "SKS URI malformed (could not parse expiration time)" msgstr "" #: src/fs/fs_uri.c:598 msgid "SKS URI malformed (signature failed validation)" msgstr "" #: src/fs/fs_uri.c:636 msgid "Unrecognized URI type" msgstr "" #: src/fs/fs_uri.c:860 #, fuzzy msgid "Lacking key configuration settings.\n" msgstr "GNUnet Konfiguration" #: src/fs/fs_uri.c:866 #, fuzzy, c-format msgid "Could not access hostkey file `%s'.\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/fs/fs_uri.c:1050 src/fs/fs_uri.c:1077 msgid "No keywords specified!\n" msgstr "Keine Schlüsselwörter angegeben!\n" #: src/fs/fs_uri.c:1083 msgid "Number of double-quotes not balanced!\n" msgstr "" #: src/fs/gnunet-auto-share.c:236 #, fuzzy, c-format msgid "Failed to load state: %s\n" msgstr "Fehler beim Starten der Collection.\n" #: src/fs/gnunet-auto-share.c:289 src/fs/gnunet-auto-share.c:299 #: src/fs/gnunet-auto-share.c:309 #, fuzzy, c-format msgid "Failed to save state to file %s\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/fs/gnunet-auto-share.c:401 #, c-format msgid "Publication of `%s' done\n" msgstr "" #: src/fs/gnunet-auto-share.c:488 #, fuzzy, c-format msgid "Publishing `%s'\n" msgstr "" "\n" "Fehler beim Uploaden der Datei: %s\n" #: src/fs/gnunet-auto-share.c:497 #, fuzzy, c-format msgid "Failed to run `%s'\n" msgstr "Fehler beim Starten der Collection.\n" #: src/fs/gnunet-auto-share.c:686 #, fuzzy, c-format msgid "" "You must specify one and only one directory name for automatic publication.\n" msgstr "Sie dürfen nur eine Datei zum Deindizieren angeben.\n" #: src/fs/gnunet-auto-share.c:737 src/fs/gnunet-publish.c:824 msgid "set the desired LEVEL of sender-anonymity" msgstr "Gewünschten Grad an Sender-Anonymität festlegen" #: src/fs/gnunet-auto-share.c:741 src/fs/gnunet-publish.c:828 msgid "disable adding the creation time to the metadata of the uploaded file" msgstr "" #: src/fs/gnunet-auto-share.c:744 src/fs/gnunet-publish.c:831 msgid "do not use libextractor to add keywords or metadata" msgstr "" #: src/fs/gnunet-auto-share.c:747 src/fs/gnunet-publish.c:855 msgid "specify the priority of the content" msgstr "Die Priorität des Inhalts angeben" #: src/fs/gnunet-auto-share.c:750 src/fs/gnunet-publish.c:862 msgid "set the desired replication LEVEL" msgstr "" #: src/fs/gnunet-auto-share.c:770 msgid "Automatically publish files from a directory on GNUnet" msgstr "" #: src/fs/gnunet-daemon-fsprofiler.c:660 msgid "Daemon to use file-sharing to measure its performance." msgstr "" #: src/fs/gnunet-directory.c:49 #, c-format msgid "\t\n" msgstr "" #: src/fs/gnunet-directory.c:94 #, fuzzy, c-format msgid "Directory `%s' meta data:\n" msgstr "==> Verzeichnis `%s':\n" #: src/fs/gnunet-directory.c:97 #, fuzzy, c-format msgid "Directory `%s' contents:\n" msgstr "==> Verzeichnis `%s':\n" #: src/fs/gnunet-directory.c:132 #, fuzzy msgid "You must specify a filename to inspect.\n" msgstr "Sie müssen eine Liste von Dateien zum Einfügen angeben.\n" #: src/fs/gnunet-directory.c:145 #, fuzzy, c-format msgid "Failed to read directory `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/fs/gnunet-directory.c:154 #, fuzzy, c-format msgid "`%s' is not a GNUnet directory\n" msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #: src/fs/gnunet-directory.c:183 #, fuzzy msgid "Display contents of a GNUnet directory" msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #: src/fs/gnunet-download.c:137 #, fuzzy, c-format msgid "Starting download `%s'.\n" msgstr "Collection `%s' begonnen.\n" #: src/fs/gnunet-download.c:147 #, fuzzy msgid "" msgstr "Unbekannter Fehler" #: src/fs/gnunet-download.c:157 #, c-format msgid "" "Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to " "download\n" msgstr "" #: src/fs/gnunet-download.c:179 #, fuzzy, c-format msgid "Error downloading: %s.\n" msgstr "Fehler beim Download: %s\n" #: src/fs/gnunet-download.c:194 #, fuzzy, c-format msgid "Downloading `%s' done (%s/s).\n" msgstr "Upload abgewiesen!" #: src/fs/gnunet-download.c:209 src/fs/gnunet-publish.c:286 #: src/fs/gnunet-search.c:200 src/fs/gnunet-unindex.c:108 #, c-format msgid "Unexpected status: %d\n" msgstr "" #: src/fs/gnunet-download.c:234 #, fuzzy msgid "You need to specify a URI argument.\n" msgstr "Sie müssen einen Empfänger angeben!\n" #: src/fs/gnunet-download.c:240 src/fs/gnunet-publish.c:665 #, fuzzy, c-format msgid "Failed to parse URI: %s\n" msgstr "Datei `%s' hat URI: %s\n" #: src/fs/gnunet-download.c:247 msgid "Only CHK or LOC URIs supported.\n" msgstr "" #: src/fs/gnunet-download.c:254 msgid "Target filename must be specified.\n" msgstr "" #: src/fs/gnunet-download.c:268 src/fs/gnunet-publish.c:797 #: src/fs/gnunet-search.c:250 src/fs/gnunet-unindex.c:140 #, fuzzy, c-format msgid "Could not initialize `%s' subsystem.\n" msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/fs/gnunet-download.c:305 src/fs/gnunet-search.c:289 msgid "set the desired LEVEL of receiver-anonymity" msgstr "Den Grad LEVEL der gewünschten Empfänger-Anonymität setzen" #: src/fs/gnunet-download.c:308 msgid "delete incomplete downloads (when aborted with CTRL-C)" msgstr "" #: src/fs/gnunet-download.c:311 src/fs/gnunet-search.c:292 msgid "only search the local peer (no P2P network search)" msgstr "" #: src/fs/gnunet-download.c:314 msgid "write the file to FILENAME" msgstr "Schreibe die Datei in DATEINAME" #: src/fs/gnunet-download.c:318 msgid "set the maximum number of parallel downloads that is allowed" msgstr "" #: src/fs/gnunet-download.c:322 msgid "set the maximum number of parallel requests for blocks that is allowed" msgstr "" #: src/fs/gnunet-download.c:325 msgid "download a GNUnet directory recursively" msgstr "Das GNUnet Verzeichnis rekursiv herunterladen" #: src/fs/gnunet-download.c:339 msgid "" "Download files from GNUnet using a GNUnet CHK or LOC URI (gnunet://fs/" "chk/...)" msgstr "" #: src/fs/gnunet-fs.c:117 msgid "print a list of all indexed files" msgstr "" #: src/fs/gnunet-fs.c:127 #, fuzzy msgid "Special file-sharing operations" msgstr "Alle Optionen anzeigen" #: src/fs/gnunet-fs-profiler.c:193 msgid "run the experiment with COUNT peers" msgstr "" #: src/fs/gnunet-fs-profiler.c:196 msgid "specifies name of a file with the HOSTS the testbed should use" msgstr "" #: src/fs/gnunet-fs-profiler.c:199 msgid "automatically terminate experiment after DELAY" msgstr "" #: src/fs/gnunet-fs-profiler.c:208 msgid "run a testbed to measure file-sharing performance" msgstr "" #: src/fs/gnunet-publish.c:231 src/fs/gnunet-publish.c:243 #, c-format msgid "Publishing `%s' at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-publish.c:250 #, fuzzy, c-format msgid "Error publishing: %s.\n" msgstr "Fehler beim Download: %s\n" #: src/fs/gnunet-publish.c:260 #, c-format msgid "Publishing `%s' done.\n" msgstr "" #: src/fs/gnunet-publish.c:264 #, fuzzy, c-format msgid "URI is `%s'.\n" msgstr "Ich bin Peer `%s'.\n" #: src/fs/gnunet-publish.c:283 #, fuzzy msgid "Cleanup after abort complete.\n" msgstr "`%s' Startvorgang abgeschlossen.\n" #: src/fs/gnunet-publish.c:401 #, fuzzy, c-format msgid "Meta data for file `%s' (%s)\n" msgstr "Daten des Moduls `%s' werden aktualisiert\n" #: src/fs/gnunet-publish.c:403 #, fuzzy, c-format msgid "Keywords for file `%s' (%s)\n" msgstr "Schlüsselwörter für Datei `%s':\n" #: src/fs/gnunet-publish.c:542 #, fuzzy msgid "Could not publish\n" msgstr "`%s' konnte nicht aufgelöst werden: %s\n" #: src/fs/gnunet-publish.c:565 #, fuzzy msgid "Could not start publishing.\n" msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #: src/fs/gnunet-publish.c:598 #, fuzzy, c-format msgid "Scanning directory `%s'.\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/fs/gnunet-publish.c:600 #, fuzzy, c-format msgid "Scanning file `%s'.\n" msgstr "Collection `%s' begonnen.\n" #: src/fs/gnunet-publish.c:605 #, c-format msgid "There was trouble processing file `%s', skipping it.\n" msgstr "" #: src/fs/gnunet-publish.c:610 #, fuzzy msgid "Preprocessing complete.\n" msgstr "GNUnet wurde erfolgreich heruntergefahren.\n" #: src/fs/gnunet-publish.c:614 #, fuzzy, c-format msgid "Extracting meta data from file `%s' complete.\n" msgstr "Daten des Moduls `%s' werden aktualisiert\n" #: src/fs/gnunet-publish.c:618 msgid "Meta data extraction has finished.\n" msgstr "" #: src/fs/gnunet-publish.c:625 #, fuzzy msgid "Internal error scanning directory.\n" msgstr "=\tFehler beim Lesen des Verzeichnisses.\n" #: src/fs/gnunet-publish.c:656 #, fuzzy, c-format msgid "Selected pseudonym `%s' unknown\n" msgstr "Namespace `%s' hat das Rating %d.\n" #: src/fs/gnunet-publish.c:682 #, fuzzy, c-format msgid "Failed to access `%s': %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/gnunet-publish.c:695 msgid "" "Failed to start meta directory scanner. Is gnunet-helper-publish-fs " "installed?\n" msgstr "" #: src/fs/gnunet-publish.c:747 #, c-format msgid "Cannot extract metadata from a URI!\n" msgstr "" #: src/fs/gnunet-publish.c:754 #, c-format msgid "You must specify one and only one filename for insertion.\n" msgstr "Sie dürfen nur eine Datei zum Deindizieren angeben.\n" #: src/fs/gnunet-publish.c:760 #, fuzzy, c-format msgid "You must NOT specify an URI and a filename.\n" msgstr "Sie müssen einen Empfänger angeben!\n" #: src/fs/gnunet-publish.c:768 src/vpn/gnunet-vpn.c:209 #, fuzzy, c-format msgid "Option `%s' is required when using option `%s'.\n" msgstr "Option `%s' macht keinen Sinn ohne die Option `%s'.\n" #: src/fs/gnunet-publish.c:778 src/fs/gnunet-publish.c:785 #: src/transport/gnunet-transport.c:1284 src/transport/gnunet-transport.c:1314 #: src/transport/gnunet-transport.c:1344 #, c-format msgid "Option `%s' makes no sense without option `%s'.\n" msgstr "Option `%s' macht keinen Sinn ohne die Option `%s'.\n" #: src/fs/gnunet-publish.c:835 msgid "" "print list of extracted keywords that would be used, but do not perform " "upload" msgstr "" "Liste der extrahierten Schlüsselworte, die verwendet werden würden, " "ausgeben, aber keinen Upload durchführen" #: src/fs/gnunet-publish.c:839 msgid "" "add an additional keyword for the top-level file or directory (this option " "can be specified multiple times)" msgstr "" "Ein zusätzliches Schlüsselwort für die Datei oder das Verzeichnis auf der " "obersten Ebene hinzufügen (diese Option kann mehrmals angegeben werden)" #: src/fs/gnunet-publish.c:843 msgid "set the meta-data for the given TYPE to the given VALUE" msgstr "" "Die Meta-Daten des angegebenen Typs TYPE auf den angegebenen Wert VALUE " "setzen" #: src/fs/gnunet-publish.c:846 msgid "" "do not index, perform full insertion (stores entire file in encrypted form " "in GNUnet database)" msgstr "" "Nicht indizieren, sondern komplett einfügen (speichert die gesamte Datei in " "verschlüsselter Form in der GNUnet Datenbank)" #: src/fs/gnunet-publish.c:851 msgid "" "specify ID of an updated version to be published in the future (for " "namespace insertions only)" msgstr "" "ID einer aktualisierten Version angeben, die in der Zukunft veröffentlich " "werden soll. (nur für das Einfügen in Namespaces)" #: src/fs/gnunet-publish.c:859 msgid "publish the files under the pseudonym NAME (place file into namespace)" msgstr "" "Die Datei unter dem Pseudonym NAME veröffentlichen (platziert die Datei in " "einem Namespace)" #: src/fs/gnunet-publish.c:865 msgid "" "only simulate the process but do not do any actual publishing (useful to " "compute URIs)" msgstr "" #: src/fs/gnunet-publish.c:869 msgid "" "set the ID of this version of the publication (for namespace insertions only)" msgstr "" "die ID dieser Version der Veröffentlichung setzen (nur für das Einfügen in " "Namespaces)" #: src/fs/gnunet-publish.c:873 msgid "" "URI to be published (can be used instead of passing a file to add keywords " "to the file with the respective URI)" msgstr "" #: src/fs/gnunet-publish.c:889 msgid "Publish a file or directory on GNUnet" msgstr "" #: src/fs/gnunet-search.c:114 #, c-format msgid "Failed to write directory with search results to `%s'\n" msgstr "" #: src/fs/gnunet-search.c:191 #, fuzzy, c-format msgid "Error searching: %s.\n" msgstr "Fehler beim Verlassen der DHT.\n" #: src/fs/gnunet-search.c:240 #, fuzzy msgid "Could not create keyword URI from arguments.\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/fs/gnunet-search.c:264 #, fuzzy msgid "Could not start searching.\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/fs/gnunet-search.c:295 msgid "write search results to file starting with PREFIX" msgstr "" #: src/fs/gnunet-search.c:298 msgid "automatically terminate search after DELAY" msgstr "" #: src/fs/gnunet-search.c:305 msgid "automatically terminate search after VALUE results are found" msgstr "" #: src/fs/gnunet-search.c:316 msgid "Search GNUnet for files that were published on GNUnet" msgstr "" #: src/fs/gnunet-service-fs.c:271 msgid "# running average P2P latency (ms)" msgstr "" #: src/fs/gnunet-service-fs.c:326 src/fs/gnunet-service-fs.c:539 #, fuzzy msgid "# Loopback routes suppressed" msgstr "# gap Routing erfolgreich (insgesamt)" #: src/fs/gnunet-service-fs.c:639 src/hostlist/gnunet-daemon-hostlist.c:288 #: src/topology/gnunet-daemon-topology.c:1254 #: src/topology/gnunet-daemon-topology.c:1261 #, fuzzy, c-format msgid "Failed to connect to `%s' service.\n" msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/fs/gnunet-service-fs_cp.c:682 #, fuzzy msgid "# migration stop messages received" msgstr "# verschlüsselter PING Nachrichten empfangen" #: src/fs/gnunet-service-fs_cp.c:686 #, c-format msgid "Migration of content to peer `%s' blocked for %s\n" msgstr "" #: src/fs/gnunet-service-fs_cp.c:721 #, fuzzy msgid "# replies transmitted to other peers" msgstr "# Bytes des Typs %d übertragen" #: src/fs/gnunet-service-fs_cp.c:727 msgid "# replies dropped" msgstr "" #: src/fs/gnunet-service-fs_cp.c:752 src/fs/gnunet-service-fs_cp.c:1301 msgid "# P2P searches active" msgstr "" #: src/fs/gnunet-service-fs_cp.c:845 msgid "# artificial delays introduced (ms)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:898 #, fuzzy msgid "# replies dropped due to type mismatch" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/fs/gnunet-service-fs_cp.c:906 #, fuzzy msgid "# replies received for other peers" msgstr "# Bytes des Typs %d empfangen" #: src/fs/gnunet-service-fs_cp.c:920 msgid "# replies dropped due to insufficient cover traffic" msgstr "" #: src/fs/gnunet-service-fs_cp.c:958 msgid "# P2P searches destroyed due to ultimate reply" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1026 #, fuzzy msgid "# requests done for free (low load)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/fs/gnunet-service-fs_cp.c:1051 msgid "# request dropped, priority insufficient" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1061 #, fuzzy msgid "# requests done for a price (normal load)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/fs/gnunet-service-fs_cp.c:1139 msgid "# GET requests received (from other peers)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1173 #, fuzzy msgid "# requests dropped due to initiator not being connected" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/fs/gnunet-service-fs_cp.c:1195 #, fuzzy msgid "# requests dropped due to missing reverse route" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/fs/gnunet-service-fs_cp.c:1246 #, fuzzy msgid "# requests dropped due TTL underflow" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/fs/gnunet-service-fs_cp.c:1270 #, fuzzy msgid "# requests dropped due to higher-TTL request" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/fs/gnunet-service-fs_cp.c:1299 #, fuzzy msgid "# P2P query messages received and processed" msgstr "# verschlüsselter PING Nachrichten empfangen" #: src/fs/gnunet-service-fs_cp.c:1670 #, fuzzy msgid "# migration stop messages sent" msgstr "# verschlüsselter PING Nachrichten empfangen" #: src/fs/gnunet-service-fs_indexing.c:130 #: src/fs/gnunet-service-fs_indexing.c:181 #, fuzzy, c-format msgid "Could not open `%s'.\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/gnunet-service-fs_indexing.c:142 #, fuzzy, c-format msgid "Error writing `%s'.\n" msgstr "Fehler beim Anlegen des Benutzers" #: src/fs/gnunet-service-fs_indexing.c:237 #, c-format msgid "" "Index request received for file `%s' is already indexed as `%s'. Permitting " "anyway.\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:275 #, c-format msgid "Hash mismatch trying to index file `%s' which has hash `%s'\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:477 #, fuzzy, c-format msgid "Failed to delete bogus block: %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/fs/gnunet-service-fs_indexing.c:542 msgid "# index blocks removed: original file inaccessible" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:557 #, fuzzy, c-format msgid "Could not access indexed file `%s' (%s) at offset %llu: %s\n" msgstr "`%s' konnte nicht aufgelöst werden: %s\n" #: src/fs/gnunet-service-fs_indexing.c:559 #, fuzzy msgid "not indexed" msgstr "Deindizierung schlug fehl." #: src/fs/gnunet-service-fs_indexing.c:574 #, fuzzy, c-format msgid "Indexed file `%s' changed at offset %llu\n" msgstr "Indizierung der Daten schlug an Position %i fehl.\n" #: src/fs/gnunet-service-fs_lc.c:202 src/fs/gnunet-service-fs_lc.c:368 #, fuzzy msgid "# client searches active" msgstr "# gap Anfragen insgesamt empfangen" #: src/fs/gnunet-service-fs_lc.c:256 #, fuzzy msgid "# replies received for local clients" msgstr "# gap Anfragen insgesamt empfangen" #: src/fs/gnunet-service-fs_lc.c:327 #, fuzzy msgid "# client searches received" msgstr "# gap Anfragen insgesamt empfangen" #: src/fs/gnunet-service-fs_lc.c:362 msgid "# client searches updated (merged content seen list)" msgstr "" #: src/fs/gnunet-service-fs_mesh_client.c:484 #, fuzzy msgid "# replies received via mesh" msgstr "# Bytes empfangen über TCP" #: src/fs/gnunet-service-fs_mesh_client.c:498 #, fuzzy msgid "# replies received via mesh dropped" msgstr "# Bytes empfangen über TCP" #: src/fs/gnunet-service-fs_mesh_server.c:260 #, fuzzy msgid "# Blocks transferred via mesh" msgstr "# Bytes des Typs %d übertragen" #: src/fs/gnunet-service-fs_mesh_server.c:352 #, fuzzy msgid "# queries received via mesh not answered" msgstr "# Bytes empfangen über TCP" #: src/fs/gnunet-service-fs_mesh_server.c:432 #, fuzzy msgid "# queries received via mesh" msgstr "# Bytes empfangen über TCP" #: src/fs/gnunet-service-fs_mesh_server.c:476 #, fuzzy msgid "# mesh client connections rejected" msgstr "GNUnet Konfiguration" #: src/fs/gnunet-service-fs_mesh_server.c:482 #: src/fs/gnunet-service-fs_mesh_server.c:522 #, fuzzy msgid "# mesh connections active" msgstr "# verbundener Knoten" #: src/fs/gnunet-service-fs_pe.c:269 msgid "# average retransmission delay (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:400 #, fuzzy msgid "# transmission failed (core has no bandwidth)" msgstr "Kein Transport des Typs %d bekannt.\n" #: src/fs/gnunet-service-fs_pe.c:433 #, fuzzy msgid "# query messages sent to other peers" msgstr "# Bytes ausgehender Nachrichten verworfen" #: src/fs/gnunet-service-fs_pe.c:484 msgid "# delay heap timeout (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:492 #, fuzzy msgid "# query plans executed" msgstr "# dht Anfragen weitergeleitet" #: src/fs/gnunet-service-fs_pe.c:552 #, fuzzy msgid "# requests merged" msgstr "# Client Trace-Anfragen empfangen" #: src/fs/gnunet-service-fs_pe.c:560 #, fuzzy msgid "# requests refreshed" msgstr "# Client Trace-Anfragen empfangen" #: src/fs/gnunet-service-fs_pe.c:616 src/fs/gnunet-service-fs_pe.c:700 #: src/fs/gnunet-service-fs_pe.c:771 msgid "# query plan entries" msgstr "" #: src/fs/gnunet-service-fs_pr.c:311 #, fuzzy msgid "# Pending requests created" msgstr "# Client Trace-Anfragen empfangen" #: src/fs/gnunet-service-fs_pr.c:394 src/fs/gnunet-service-fs_pr.c:645 #, fuzzy msgid "# Pending requests active" msgstr "# Client Trace-Anfragen empfangen" #: src/fs/gnunet-service-fs_pr.c:814 #, fuzzy msgid "# replies received and matched" msgstr "# Bytes empfangen über TCP" #: src/fs/gnunet-service-fs_pr.c:844 msgid "# duplicate replies discarded (bloomfilter)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:853 msgid "# irrelevant replies discarded" msgstr "" #: src/fs/gnunet-service-fs_pr.c:867 #, c-format msgid "Unsupported block type %u\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:880 msgid "# results found locally" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1001 msgid "# Datastore `PUT' failures" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1029 #, fuzzy msgid "# storage requests dropped due to high load" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/fs/gnunet-service-fs_pr.c:1064 #, fuzzy msgid "# Replies received from DHT" msgstr "# Bytes empfangen über HTTP" #: src/fs/gnunet-service-fs_pr.c:1192 #, fuzzy msgid "# Replies received from MESH" msgstr "# Bytes empfangen über HTTP" #: src/fs/gnunet-service-fs_pr.c:1244 #, c-format msgid "Datastore lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1264 #, c-format msgid "On-demand lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1311 msgid "# Datastore lookups concluded (no results)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1326 msgid "# Datastore lookups concluded (seen all)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1335 msgid "# Datastore lookups aborted (more than MAX_RESULTS)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1350 msgid "# requested DBLOCK or IBLOCK not found" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1364 msgid "# on-demand blocks matched requests" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1377 msgid "# on-demand lookups performed successfully" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1382 msgid "# on-demand lookups failed" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1409 src/fs/gnunet-service-fs_pr.c:1449 #: src/fs/gnunet-service-fs_pr.c:1590 msgid "# Datastore lookups concluded (error queueing)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1467 msgid "# Datastore lookups concluded (found last result)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1478 msgid "# Datastore lookups concluded (load too high)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1566 msgid "# Datastore lookups initiated" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1651 #, fuzzy msgid "# GAP PUT messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/fs/gnunet-service-fs_push.c:631 msgid "time required, content pushing disabled" msgstr "" #: src/fs/gnunet-unindex.c:89 #, c-format msgid "Unindexing at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-unindex.c:95 #, fuzzy, c-format msgid "Error unindexing: %s.\n" msgstr "" "\n" "Fehler beim Deindizieren der Datei: %s\n" #: src/fs/gnunet-unindex.c:100 #, fuzzy msgid "Unindexing done.\n" msgstr "Dateien deindizieren." #: src/fs/gnunet-unindex.c:130 #, fuzzy, c-format msgid "You must specify one and only one filename for unindexing.\n" msgstr "Sie dürfen nur eine Datei zum Deindizieren angeben.\n" #: src/fs/gnunet-unindex.c:147 #, fuzzy msgid "Could not start unindex operation.\n" msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #: src/fs/gnunet-unindex.c:179 msgid "Unindex a file that was previously indexed with gnunet-publish." msgstr "" #: src/gns/gns_api.c:393 #, fuzzy msgid "Failed to deserialize lookup reply from GNS service!\n" msgstr "Fehler beim Empfangen der Antwort von gnunetd auf die `%s' Nachricht\n" #: src/gns/gnunet-bcd.c:123 #, fuzzy, c-format msgid "Refusing `%s' request to HTTP server\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/gns/gnunet-bcd.c:355 src/hostlist/hostlist-server.c:567 #, fuzzy, c-format msgid "Invalid port number %llu. Exiting.\n" msgstr "Ungültige Parameter. Abbruch.\n" #: src/gns/gnunet-bcd.c:360 #, c-format msgid "Businesscard HTTP server starts on %llu\n" msgstr "" #: src/gns/gnunet-bcd.c:374 #, fuzzy, c-format msgid "Could not start businesscard HTTP server on port %u\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/gns/gnunet-bcd.c:519 msgid "Run HTTP serve on port PORT (default is 8888)" msgstr "" #: src/gns/gnunet-bcd.c:531 msgid "GNUnet HTTP server to create business cards" msgstr "" #: src/gns/gnunet-dns2gns.c:228 #, fuzzy msgid "Failed to pack DNS response into UDP packet!\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/gns/gnunet-dns2gns.c:400 #, fuzzy, c-format msgid "Cannot parse DNS request from %s\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/gns/gnunet-dns2gns.c:416 #, fuzzy, c-format msgid "Received malformed DNS request from %s\n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/gns/gnunet-dns2gns.c:424 #, fuzzy, c-format msgid "Received unsupported DNS request from %s\n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/gns/gnunet-dns2gns.c:701 msgid "No ego configured for `dns2gns` subsystem\n" msgstr "" #: src/gns/gnunet-dns2gns.c:727 #, fuzzy msgid "No DNS server specified!\n" msgstr "Keine Schlüsselwörter angegeben!\n" #: src/gns/gnunet-dns2gns.c:749 #, fuzzy msgid "No valid GNS zone specified!\n" msgstr "Keine Schlüsselwörter angegeben!\n" #: src/gns/gnunet-dns2gns.c:770 msgid "IP of recursive DNS resolver to use (required)" msgstr "" #: src/gns/gnunet-dns2gns.c:773 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:776 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:779 msgid "UDP port to listen on for inbound DNS requests; default: 53" msgstr "" #: src/gns/gnunet-dns2gns.c:782 msgid "Public key of the GNS zone to use (overrides default)" msgstr "" #: src/gns/gnunet-dns2gns.c:795 msgid "GNUnet DNS-to-GNS proxy (a DNS server)" msgstr "" #: src/gns/gnunet-gns.c:227 #, c-format msgid "Please specify name to lookup!\n" msgstr "" #: src/gns/gnunet-gns.c:308 #, c-format msgid "Ego for `%s' not found, cannot perform lookup.\n" msgstr "" #: src/gns/gnunet-gns.c:347 src/gns/gnunet-gns-helper-service-w32.c:798 #, c-format msgid "" "Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-" "gns-import.sh?\n" msgstr "" #: src/gns/gnunet-gns.c:386 src/gns/gnunet-gns-helper-service-w32.c:828 #, fuzzy, c-format msgid "Failed to connect to GNS\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/gns/gnunet-gns.c:399 #, c-format msgid "Public key `%s' is not well-formed\n" msgstr "" #: src/gns/gnunet-gns.c:449 msgid "Lookup a record for the given name" msgstr "" #: src/gns/gnunet-gns.c:452 #, fuzzy msgid "Specify the type of the record to lookup" msgstr "Die Priorität des Inhalts angeben" #: src/gns/gnunet-gns.c:455 #, fuzzy msgid "Specify timeout for the lookup" msgstr "Die Priorität des Inhalts angeben" #: src/gns/gnunet-gns.c:458 msgid "No unneeded output" msgstr "" #: src/gns/gnunet-gns.c:461 #, fuzzy msgid "Specify the public key of the zone to lookup the record in" msgstr "Die Priorität des Inhalts angeben" #: src/gns/gnunet-gns.c:464 #, fuzzy msgid "Specify the name of the ego of the zone to lookup the record in" msgstr "Die Priorität des Inhalts angeben" #: src/gns/gnunet-gns.c:478 #, fuzzy msgid "GNUnet GNS resolver tool" msgstr "GNUnet Netzwerk Topologie tracen." #: src/gns/gnunet-gns-helper-service-w32.c:768 #, c-format msgid "" "Ego for `gns-short' not found. This is not really fatal, but i'll pretend " "that it is and refuse to perform a lookup. Did you run gnunet-gns-import." "sh?\n" msgstr "" #: src/gns/gnunet-gns-helper-service-w32.c:838 #, fuzzy, c-format msgid "Failed to connect to identity service\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/gns/gnunet-gns-import.c:479 msgid "This program will import some GNS authorities into your GNS namestore." msgstr "" #: src/gns/gnunet-gns-proxy.c:105 src/hostlist/hostlist-client.c:469 #: src/hostlist/hostlist-client.c:683 src/hostlist/hostlist-client.c:689 #: src/hostlist/hostlist-client.c:741 src/hostlist/hostlist-client.c:750 #: src/hostlist/hostlist-client.c:871 src/hostlist/hostlist-client.c:963 #: src/hostlist/hostlist-client.c:968 #: src/transport/plugin_transport_http_client.c:1062 #: src/transport/plugin_transport_http_client.c:1077 #, c-format msgid "%s failed at %s:%d: `%s'\n" msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #: src/gns/gnunet-gns-proxy.c:833 #, fuzzy, c-format msgid "Unsupported CURL SSL backend %d\n" msgstr "Ungültige Nachricht des Typs %u empfangen. Nachricht wird verworfen.\n" #: src/gns/gnunet-gns-proxy.c:856 #, fuzzy, c-format msgid "Failed to fetch CN from cert: %s\n" msgstr "HTTP Anfrage konnte nicht an Host `%s' gesendet werden: %s\n" #: src/gns/gnunet-gns-proxy.c:879 #, fuzzy, c-format msgid "Failed to initialize DANE: %s\n" msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n" #: src/gns/gnunet-gns-proxy.c:892 #, fuzzy, c-format msgid "Failed to parse DANE record: %s\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/gns/gnunet-gns-proxy.c:907 #, fuzzy, c-format msgid "Failed to verify TLS connection using DANE: %s\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/gns/gnunet-gns-proxy.c:917 #, c-format msgid "Failed DANE verification failed with GnuTLS verify status code: %u\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:941 #, c-format msgid "SSL certificate subject name (%s) does not match `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1086 #, c-format msgid "Cookie domain `%s' supplied by server is invalid\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1602 #, fuzzy, c-format msgid "Unsupported HTTP method `%s'\n" msgstr "Ungültige Nachricht des Typs %u empfangen. Nachricht wird verworfen.\n" #: src/gns/gnunet-gns-proxy.c:1973 #, fuzzy, c-format msgid "Unable to import private key from file `%s'\n" msgstr "Fehler beim Anlegen des Benutzerkontos:" #: src/gns/gnunet-gns-proxy.c:2003 #, fuzzy, c-format msgid "Unable to import certificate %s\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/gns/gnunet-gns-proxy.c:2177 #, fuzzy, c-format msgid "Failed to start HTTPS server for `%s'\n" msgstr "Fehler beim Starten der Collection.\n" #: src/gns/gnunet-gns-proxy.c:2196 #, fuzzy msgid "Failed to pass client to MHD\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/gns/gnunet-gns-proxy.c:2504 #, fuzzy, c-format msgid "Unsupported socks version %d\n" msgstr "Ungültige Nachricht des Typs %u empfangen. Nachricht wird verworfen.\n" #: src/gns/gnunet-gns-proxy.c:2533 #, fuzzy, c-format msgid "Unsupported socks command %d\n" msgstr "Ungültige Nachricht des Typs %u empfangen. Nachricht wird verworfen.\n" #: src/gns/gnunet-gns-proxy.c:2551 src/gns/gnunet-gns-proxy.c:2580 msgid "SSL connection to plain IPv4 address requested\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2631 #, fuzzy, c-format msgid "Unsupported socks address type %d\n" msgstr "Ungültige Nachricht des Typs %u empfangen. Nachricht wird verworfen.\n" #: src/gns/gnunet-gns-proxy.c:2970 msgid "No ego configured for `shorten-zone`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3010 #, c-format msgid "No ego configured for `%s`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3072 #, fuzzy, c-format msgid "Failed to load SSL/TLS key and certificate from `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/gns/gnunet-gns-proxy.c:3113 msgid "listen on specified port (default: 7777)" msgstr "" #: src/gns/gnunet-gns-proxy.c:3116 msgid "pem file to use as CA" msgstr "" #: src/gns/gnunet-gns-proxy.c:3135 msgid "GNUnet GNS proxy" msgstr "" #: src/gns/gnunet-service-gns.c:862 #, fuzzy msgid "Failed to connect to the namestore!\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/gns/gnunet-service-gns.c:870 #, fuzzy msgid "Failed to connect to the namecache!\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/gns/gnunet-service-gns.c:903 #, fuzzy msgid "Could not connect to DHT!\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/gns/gnunet-service-gns.c:919 #, fuzzy msgid "valid public key required" msgstr "Ungültiger Parameter: `%s'\n" #: src/gns/gnunet-service-gns_interceptor.c:263 #, fuzzy msgid "Error converting GNS response to DNS response!\n" msgstr "Fehler beim Konvertieren von Parametern in URI!\n" #: src/gns/gnunet-service-gns_interceptor.c:369 #, fuzzy msgid "Failed to connect to the DNS service!\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/gns/gnunet-service-gns_resolver.c:816 #, fuzzy msgid "Failed to parse DNS response\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/gns/gnunet-service-gns_resolver.c:958 #, c-format msgid "Skipping record of unsupported type %d\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1317 #, c-format msgid "GNS lookup resulted in DNS name that is too long (`%s')\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1817 msgid "GNS lookup recursion failed (no delegation record found)\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1841 #, fuzzy, c-format msgid "Failed to cache GNS resolution: %s\n" msgstr "HTTP Anfrage konnte nicht an Host `%s' gesendet werden: %s\n" #: src/gns/gnunet-service-gns_resolver.c:2123 #, c-format msgid "Zone %s was revoked, resolution fails\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:2272 #, c-format msgid "Hostname `%s' is not well-formed, resolution fails\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:151 #, fuzzy, c-format msgid "Unable to parse PKEY record `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/gns/plugin_gnsrecord_gns.c:180 #, fuzzy, c-format msgid "Unable to parse GNS2DNS record `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/gns/plugin_gnsrecord_gns.c:201 #, fuzzy, c-format msgid "Failed to serialize GNS2DNS record with value `%s'\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/gns/plugin_gnsrecord_gns.c:217 #, fuzzy, c-format msgid "Unable to parse VPN record string `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:293 #, fuzzy, c-format msgid "Unable to parse IPv4 address `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:314 #, fuzzy, c-format msgid "Failed to serialize NS record with value `%s'\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:336 #, fuzzy, c-format msgid "Failed to serialize CNAME record with value `%s'\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:420 #, fuzzy, c-format msgid "Failed to serialize CERT record with %u bytes\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:452 #, fuzzy, c-format msgid "Unable to parse SOA record `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:471 #, fuzzy, c-format msgid "Failed to serialize SOA record with mname `%s' and rname `%s'\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:494 #, fuzzy, c-format msgid "Failed to serialize PTR record with value `%s'\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:514 #, fuzzy, c-format msgid "Unable to parse MX record `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:529 #, fuzzy, c-format msgid "Failed to serialize MX record with hostname `%s'\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:549 #, fuzzy, c-format msgid "Unable to parse IPv6 address `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:567 #, fuzzy, c-format msgid "Unable to parse TLSA record string `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/hello/gnunet-hello.c:123 msgid "Call with name of HELLO file to modify.\n" msgstr "" #: src/hello/gnunet-hello.c:129 #, fuzzy, c-format msgid "Error accessing file `%s': %s\n" msgstr "Fehler beim Anlegen des Benutzers" #: src/hello/gnunet-hello.c:137 #, c-format msgid "File `%s' is too big to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:144 #, c-format msgid "File `%s' is too small to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:154 src/hello/gnunet-hello.c:183 #, fuzzy, c-format msgid "Error opening file `%s': %s\n" msgstr "Fehler beim Anlegen des Benutzers" #: src/hello/gnunet-hello.c:170 #, fuzzy, c-format msgid "Did not find well-formed HELLO in file `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/hello/gnunet-hello.c:195 #, fuzzy, c-format msgid "Error writing HELLO to file `%s': %s\n" msgstr "Fehler beim Anlegen des Benutzers" #: src/hello/gnunet-hello.c:203 #, c-format msgid "Modified %u addresses \n" msgstr "" #: src/hello/hello.c:944 #, fuzzy msgid "Failed to parse HELLO message: missing expiration time\n" msgstr "Fehler beim Speichern der Konfiguration!" #: src/hello/hello.c:953 #, fuzzy msgid "Failed to parse HELLO message: invalid expiration time\n" msgstr "Fehler beim Speichern der Konfiguration!" #: src/hello/hello.c:963 #, fuzzy msgid "Failed to parse HELLO message: malformed\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/hello/hello.c:973 #, fuzzy msgid "Failed to parse HELLO message: missing transport plugin\n" msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #: src/hello/hello.c:990 #, c-format msgid "Plugin `%s' not found\n" msgstr "" #: src/hello/hello.c:999 #, c-format msgid "Plugin `%s' does not support URIs yet\n" msgstr "" #: src/hello/hello.c:1018 #, fuzzy, c-format msgid "Failed to parse `%s' as an address for plugin `%s'\n" msgstr "Fehler beim Binden an UDP Port %d.\n" #: src/hostlist/gnunet-daemon-hostlist.c:259 msgid "" "None of the functions for the hostlist daemon were enabled. I have no " "reason to run!\n" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:308 msgid "advertise our hostlist to other peers" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:313 msgid "" "bootstrap using hostlists (it is highly recommended that you always use this " "option)" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:316 msgid "enable learning about hostlist servers from other peers" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:320 msgid "provide a hostlist server" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:335 msgid "GNUnet hostlist server and client" msgstr "" #: src/hostlist/hostlist-client.c:288 msgid "# bytes downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:309 src/hostlist/hostlist-client.c:339 #, fuzzy msgid "# invalid HELLOs downloaded from hostlist servers" msgstr "# Hellos per HTTP heruntergeladen" #: src/hostlist/hostlist-client.c:312 src/hostlist/hostlist-client.c:342 #, fuzzy, c-format msgid "Invalid `%s' message received from hostlist at `%s'\n" msgstr "Ungültige `%s' Nachricht von Knoten `%s' empfangen.\n" #: src/hostlist/hostlist-client.c:330 #, fuzzy msgid "# valid HELLOs downloaded from hostlist servers" msgstr "# Hellos per HTTP heruntergeladen" #: src/hostlist/hostlist-client.c:592 src/hostlist/hostlist-client.c:1333 msgid "# advertised hostlist URIs" msgstr "" #: src/hostlist/hostlist-client.c:622 #, c-format msgid "# advertised URI `%s' downloaded" msgstr "" #: src/hostlist/hostlist-client.c:664 #, c-format msgid "" "Advertised hostlist with URI `%s' could not be downloaded. Advertised URI " "gets dismissed.\n" msgstr "" #: src/hostlist/hostlist-client.c:802 #, fuzzy, c-format msgid "Timeout trying to download hostlist from `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/hostlist/hostlist-client.c:816 #, c-format msgid "Download limit of %u bytes exceeded, stopping download\n" msgstr "" #: src/hostlist/hostlist-client.c:836 #, fuzzy, c-format msgid "Download of hostlist from `%s' failed: `%s'\n" msgstr "" "Upload von `%s' komplett, derzeitige durchschnittliche Geschwindigkeit " "beträgt %8.3f KB/s.\n" #: src/hostlist/hostlist-client.c:842 #, fuzzy, c-format msgid "Download of hostlist `%s' completed.\n" msgstr "" "Upload von `%s' komplett, derzeitige durchschnittliche Geschwindigkeit " "beträgt %8.3f KB/s.\n" #: src/hostlist/hostlist-client.c:850 #, c-format msgid "Adding successfully tested hostlist `%s' datastore.\n" msgstr "" #: src/hostlist/hostlist-client.c:903 #, c-format msgid "Bootstrapping using hostlist at `%s'.\n" msgstr "" #: src/hostlist/hostlist-client.c:911 msgid "# hostlist downloads initiated" msgstr "" #: src/hostlist/hostlist-client.c:1040 src/hostlist/hostlist-client.c:1506 msgid "# milliseconds between hostlist downloads" msgstr "" #: src/hostlist/hostlist-client.c:1049 #, c-format msgid "Have %u/%u connections. Will consider downloading hostlist in %s\n" msgstr "" #: src/hostlist/hostlist-client.c:1109 src/hostlist/hostlist-client.c:1125 #, fuzzy msgid "# active connections" msgstr "GNUnet Konfiguration" #: src/hostlist/hostlist-client.c:1280 #, fuzzy, c-format msgid "Loading saved hostlist entries from file `%s' \n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/hostlist/hostlist-client.c:1285 #, fuzzy, c-format msgid "Hostlist file `%s' does not exist\n" msgstr "Sitzungsschlüssel von Knoten `%s' konnte nicht überprüft werden.\n" #: src/hostlist/hostlist-client.c:1296 #, fuzzy, c-format msgid "Could not open file `%s' for reading to load hostlists: %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/hostlist/hostlist-client.c:1329 #, c-format msgid "%u hostlist URIs loaded from file\n" msgstr "" #: src/hostlist/hostlist-client.c:1331 msgid "# hostlist URIs read from file" msgstr "" #: src/hostlist/hostlist-client.c:1376 #, fuzzy, c-format msgid "Could not open file `%s' for writing to save hostlists: %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/hostlist/hostlist-client.c:1381 #, fuzzy, c-format msgid "Writing %u hostlist URIs to `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/hostlist/hostlist-client.c:1405 src/hostlist/hostlist-client.c:1422 #, c-format msgid "Error writing hostlist URIs to file `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:1417 msgid "# hostlist URIs written to file" msgstr "" #: src/hostlist/hostlist-client.c:1471 msgid "Learning is enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1483 msgid "Learning is not enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1495 #, c-format msgid "" "Since learning is not enabled on this peer, hostlist file `%s' was removed\n" msgstr "" #: src/hostlist/hostlist-client.c:1499 #, fuzzy, c-format msgid "Hostlist file `%s' could not be removed\n" msgstr "Sitzungsschlüssel von Knoten `%s' konnte nicht überprüft werden.\n" #: src/hostlist/hostlist-server.c:137 #, fuzzy msgid "bytes in hostlist" msgstr "# bytes in der Datenbank" #: src/hostlist/hostlist-server.c:161 msgid "expired addresses encountered" msgstr "" #: src/hostlist/hostlist-server.c:189 src/hostlist/hostlist-server.c:425 #: src/peerinfo-tool/gnunet-peerinfo.c:350 #: src/peerinfo-tool/gnunet-peerinfo.c:419 #: src/peerinfo-tool/gnunet-peerinfo.c:490 #: src/topology/gnunet-daemon-topology.c:925 #, fuzzy, c-format msgid "Error in communication with PEERINFO service: %s\n" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/hostlist/hostlist-server.c:210 msgid "HELLOs without addresses encountered (ignored)" msgstr "" #: src/hostlist/hostlist-server.c:224 msgid "bytes not included in hostlist (size limit)" msgstr "" #: src/hostlist/hostlist-server.c:268 #, fuzzy, c-format msgid "Refusing `%s' request to hostlist server\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/hostlist/hostlist-server.c:271 #, fuzzy msgid "hostlist requests refused (not HTTP GET)" msgstr "# Client Trace-Anfragen empfangen" #: src/hostlist/hostlist-server.c:284 #, c-format msgid "Refusing `%s' request with %llu bytes of upload data\n" msgstr "" #: src/hostlist/hostlist-server.c:288 #, fuzzy msgid "hostlist requests refused (upload data)" msgstr "# Client Trace-Anfragen empfangen" #: src/hostlist/hostlist-server.c:296 msgid "Could not handle hostlist request since I do not have a response yet\n" msgstr "" #: src/hostlist/hostlist-server.c:299 #, fuzzy msgid "hostlist requests refused (not ready)" msgstr "# Client Trace-Anfragen empfangen" #: src/hostlist/hostlist-server.c:303 msgid "Received request for our hostlist\n" msgstr "" #: src/hostlist/hostlist-server.c:304 #, fuzzy msgid "hostlist requests processed" msgstr "# Client Trace-Anfragen empfangen" #: src/hostlist/hostlist-server.c:346 #, fuzzy msgid "# hostlist advertisements send" msgstr "# Bekanntmachungen von anderen übertragen" #: src/hostlist/hostlist-server.c:390 msgid "Advertisement message could not be queued by core\n" msgstr "" #: src/hostlist/hostlist-server.c:557 src/peerinfo-tool/gnunet-peerinfo.c:639 #: src/transport/gnunet-service-transport.c:1114 #, fuzzy msgid "Could not access PEERINFO service. Exiting.\n" msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #: src/hostlist/hostlist-server.c:576 #, c-format msgid "Hostlist service starts on %s:%llu\n" msgstr "" #: src/hostlist/hostlist-server.c:590 #, fuzzy, c-format msgid "Address to obtain hostlist: `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/hostlist/hostlist-server.c:630 #, fuzzy, c-format msgid "`%s' is not a valid IP address! Ignoring BINDTOIP.\n" msgstr "`%s' ist nicht verfügbar." #: src/hostlist/hostlist-server.c:673 #, fuzzy, c-format msgid "Could not start hostlist HTTP server on port %u\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/identity/gnunet-identity.c:165 #, fuzzy, c-format msgid "Failed to create ego: %s\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/identity/gnunet-identity.c:184 #, fuzzy, c-format msgid "Failed to set default ego: %s\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/identity/gnunet-identity.c:327 msgid "create ego NAME" msgstr "" #: src/identity/gnunet-identity.c:330 msgid "delete ego NAME " msgstr "" #: src/identity/gnunet-identity.c:333 msgid "display all egos" msgstr "" #: src/identity/gnunet-identity.c:336 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)" msgstr "" #: src/identity/gnunet-identity.c:339 msgid "run in monitor mode egos" msgstr "" #: src/identity/gnunet-identity.c:342 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)" msgstr "" #: src/identity/gnunet-identity.c:351 msgid "Maintain egos" msgstr "" #: src/identity/gnunet-service-identity.c:338 msgid "no default known" msgstr "" #: src/identity/gnunet-service-identity.c:362 msgid "default configured, but ego unknown (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:439 #: src/identity/gnunet-service-identity.c:670 #: src/identity/gnunet-service-identity.c:778 #, fuzzy, c-format msgid "Failed to write subsystem default identifier map to `%s'.\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/identity/gnunet-service-identity.c:446 msgid "Unknown ego specified for service (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:516 msgid "identifier already in use for another ego" msgstr "" #: src/identity/gnunet-service-identity.c:647 msgid "target name already exists" msgstr "" #: src/identity/gnunet-service-identity.c:686 #: src/identity/gnunet-service-identity.c:795 msgid "no matching ego found" msgstr "" #: src/identity/gnunet-service-identity.c:829 #, fuzzy, c-format msgid "Failed to parse ego information in `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/identity/gnunet-service-identity.c:902 #, fuzzy, c-format msgid "Failed to parse subsystem identity configuration file `%s'\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/identity/gnunet-service-identity.c:914 #, fuzzy, c-format msgid "Failed to create directory `%s' for storing egos\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/mesh/gnunet-mesh.c:357 #, fuzzy, c-format msgid "Invalid target `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/mesh/gnunet-mesh.c:607 #, fuzzy, c-format msgid "Invalid peer ID `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/mesh/gnunet-mesh.c:650 #, fuzzy, c-format msgid "Invalid tunnel owner `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/mesh/gnunet-mesh.c:716 msgid "You must NOT give a TARGETwhen using 'request all' options\n" msgstr "" #: src/mesh/gnunet-mesh.c:807 #, fuzzy msgid "provide information about a particular connection" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/mesh/gnunet-mesh.c:810 msgid "activate echo mode" msgstr "" #: src/mesh/gnunet-mesh.c:816 msgid "port to listen to (default; 0)" msgstr "" #: src/mesh/gnunet-mesh.c:819 src/mesh/gnunet-mesh.c:822 #, fuzzy msgid "provide information about all peers" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/mesh/gnunet-mesh.c:825 #, fuzzy msgid "provide information about a particular tunnel" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/mesh/gnunet-mesh.c:828 #, fuzzy msgid "provide information about all tunnels" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/mesh/gnunet-service-mesh_peer.c:390 msgid "Wrong CORE service\n" msgstr "" #: src/mysql/mysql.c:174 #, c-format msgid "Trying to use file `%s' for MySQL configuration.\n" msgstr "Versuche, Datei `%s' für MySQL Konfiguration zu verwenden.\n" #: src/mysql/mysql.c:181 #, fuzzy, c-format msgid "Could not access file `%s': %s\n" msgstr "`%s' konnte nicht aufgelöst werden: %s\n" #: src/namecache/gnunet-namecache.c:109 #, fuzzy, c-format msgid "No records found for `%s'" msgstr "Dienst `%s' konnte nicht ordentlich entladen werden!\n" #: src/namecache/gnunet-namecache.c:124 src/namestore/gnunet-namestore.c:397 #, c-format msgid "\tCorrupt or unsupported record of type %u\n" msgstr "" #: src/namecache/gnunet-namecache.c:185 #, fuzzy, c-format msgid "You must specify which zone should be accessed\n" msgstr "Gibt an, welcher TRANSPORT getestet werden soll" #: src/namecache/gnunet-namecache.c:195 src/namestore/gnunet-namestore.c:695 #, fuzzy, c-format msgid "Invalid public key for reverse lookup `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/namecache/gnunet-namecache.c:203 #, fuzzy, c-format msgid "You must specify a name\n" msgstr "Sie müssen einen Empfänger angeben!\n" #: src/namecache/gnunet-namecache.c:234 src/namestore/gnunet-namestore.c:931 msgid "name of the record to add/delete/display" msgstr "" #: src/namecache/gnunet-namecache.c:237 #, fuzzy msgid "spezifies the public key of the zone to look in" msgstr "Die Priorität des Inhalts angeben" #: src/namecache/gnunet-namecache.c:248 src/namestore/gnunet-namestore.c:963 #, fuzzy msgid "GNUnet zone manipulation tool" msgstr "GNUnet Konfiguration" #: src/namecache/namecache_api.c:276 msgid "Namecache failed to cache block" msgstr "" #: src/namecache/plugin_namecache_postgres.c:89 #: src/namestore/plugin_namestore_postgres.c:96 #, fuzzy msgid "Failed to create indices\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/namestore/gnunet-namestore.c:303 #, fuzzy, c-format msgid "Adding record failed: %s\n" msgstr "" "\n" "Fehler beim Uploaden der Datei: %s\n" #: src/namestore/gnunet-namestore.c:332 #, fuzzy, c-format msgid "Deleting record failed, record does not exist%s%s\n" msgstr "" "\n" "Fehler beim Uploaden der Datei: %s\n" #: src/namestore/gnunet-namestore.c:339 #, fuzzy, c-format msgid "Deleting record failed%s%s\n" msgstr "" "\n" "Fehler beim Uploaden der Datei: %s\n" #: src/namestore/gnunet-namestore.c:558 #, c-format msgid "No options given\n" msgstr "" #: src/namestore/gnunet-namestore.c:569 #: src/namestore/gnunet-namestore-fcfsd.c:970 #, fuzzy msgid "Failed to connect to namestore\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/namestore/gnunet-namestore.c:577 src/namestore/gnunet-namestore.c:586 #: src/namestore/gnunet-namestore.c:603 src/namestore/gnunet-namestore.c:625 #: src/namestore/gnunet-namestore.c:665 #, fuzzy, c-format msgid "Missing option `%s' for operation `%s'\n" msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #: src/namestore/gnunet-namestore.c:578 src/namestore/gnunet-namestore.c:587 #: src/namestore/gnunet-namestore.c:604 src/namestore/gnunet-namestore.c:626 msgid "add" msgstr "" #: src/namestore/gnunet-namestore.c:595 #, fuzzy, c-format msgid "Unsupported type `%s'\n" msgstr "Ungültige Nachricht des Typs %u empfangen. Nachricht wird verworfen.\n" #: src/namestore/gnunet-namestore.c:615 #, fuzzy, c-format msgid "Value `%s' invalid for record type `%s'\n" msgstr "%s: Symbolwert `%s' ist ungültig für %s\n" #: src/namestore/gnunet-namestore.c:651 #, fuzzy, c-format msgid "Invalid time format `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/namestore/gnunet-namestore.c:666 msgid "del" msgstr "" #: src/namestore/gnunet-namestore.c:715 #: src/peerinfo-tool/gnunet-peerinfo.c:723 #, fuzzy, c-format msgid "Invalid URI `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/namestore/gnunet-namestore.c:750 #, fuzzy, c-format msgid "Invalid nick `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/namestore/gnunet-namestore.c:790 #, fuzzy, c-format msgid "Ego `%s' not known to identity service\n" msgstr "`%s': unbekannter Dienst: %s\n" #: src/namestore/gnunet-namestore.c:817 #, fuzzy, c-format msgid "No default ego configured in identity service\n" msgstr "`%s': unbekannter Dienst: %s\n" #: src/namestore/gnunet-namestore.c:853 #, fuzzy, c-format msgid "Identity service is not running\n" msgstr "`%s' ist keine Datei.\n" #: src/namestore/gnunet-namestore.c:865 #, fuzzy, c-format msgid "Cannot connect to identity service\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/namestore/gnunet-namestore.c:913 msgid "add record" msgstr "" #: src/namestore/gnunet-namestore.c:916 msgid "delete record" msgstr "" #: src/namestore/gnunet-namestore.c:919 msgid "display records" msgstr "" #: src/namestore/gnunet-namestore.c:922 msgid "" "expiration time for record to use (for adding only), \"never\" is possible" msgstr "" #: src/namestore/gnunet-namestore.c:925 #, fuzzy msgid "set the desired nick name for the zone" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/namestore/gnunet-namestore.c:928 #, fuzzy msgid "monitor changes in the namestore" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/namestore/gnunet-namestore.c:934 #, fuzzy msgid "determine our name for the given PKEY" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/namestore/gnunet-namestore.c:937 msgid "type of the record to add/delete/display" msgstr "" #: src/namestore/gnunet-namestore.c:940 msgid "URI to import into our zone" msgstr "" #: src/namestore/gnunet-namestore.c:943 msgid "value of the record to add/delete" msgstr "" #: src/namestore/gnunet-namestore.c:946 msgid "create or list public record" msgstr "" #: src/namestore/gnunet-namestore.c:949 msgid "" "create shadow record (only valid if all other records of the same type have " "expired" msgstr "" #: src/namestore/gnunet-namestore.c:952 msgid "name of the ego controlling the zone" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:464 #, fuzzy, c-format msgid "Unsupported form value `%s'\n" msgstr "Kommando `%s' wird nicht unterstützt. Vorgang wird abgebrochen.\n" #: src/namestore/gnunet-namestore-fcfsd.c:491 #, fuzzy, c-format msgid "Failed to create record for domain `%s': %s\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/namestore/gnunet-namestore-fcfsd.c:525 #, c-format msgid "Found existing name `%s' for the given key\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:534 msgid "Error when mapping zone to name\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:596 #, c-format msgid "Found %u existing records for domain `%s'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:652 #, fuzzy, c-format msgid "Failed to create page for `%s'\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/namestore/gnunet-namestore-fcfsd.c:668 #, fuzzy, c-format msgid "Failed to setup post processor for `%s'\n" msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n" #: src/namestore/gnunet-namestore-fcfsd.c:704 msgid "Domain name must not contain `.'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:712 msgid "Domain name must not contain `+'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:910 msgid "No ego configured for `fcfsd` subsystem\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:936 #, fuzzy msgid "Failed to start HTTP server\n" msgstr "Fehler beim Starten der Collection.\n" #: src/namestore/gnunet-namestore-fcfsd.c:978 #, fuzzy msgid "Failed to connect to identity\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/namestore/gnunet-namestore-fcfsd.c:1011 msgid "GNU Name System First Come First Serve name registration service" msgstr "" #: src/namestore/gnunet-service-namestore.c:655 #, fuzzy, c-format msgid "Failed to replicate block in namecache: %s\n" msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n" #: src/namestore/namestore_api.c:275 msgid "Namestore failed to store record\n" msgstr "" #: src/nat/gnunet-nat-server.c:279 #, c-format msgid "Please pass valid port number as the first argument! (got `%s')\n" msgstr "" #: src/nat/gnunet-nat-server.c:321 msgid "GNUnet NAT traversal test helper daemon" msgstr "" #: src/nat/nat_auto.c:170 msgid "NAT traversal with ICMP Server timed out.\n" msgstr "" #: src/nat/nat_auto.c:203 msgid "NAT traversal with ICMP Server succeeded.\n" msgstr "" #: src/nat/nat_auto.c:204 msgid "NAT traversal with ICMP Server failed.\n" msgstr "" #: src/nat/nat_auto.c:225 #, fuzzy msgid "Testing connection reversal with ICMP server.\n" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/nat/nat_auto.c:274 #, fuzzy, c-format msgid "Detected external IP `%s'\n" msgstr "Ungültiger RPC `%s' empfangen.\n" #: src/nat/nat_auto.c:344 msgid "This system has a global IPv6 address, setting IPv6 to supported.\n" msgstr "" #: src/nat/nat_auto.c:360 #, fuzzy, c-format msgid "Detected internal network address `%s'.\n" msgstr "GNUnet verwendet nun die IP-Adresse %u.%u.%u.%u.\n" #: src/nat/nat_auto.c:413 msgid "upnpc found, enabling its use\n" msgstr "" #: src/nat/nat_auto.c:414 #, fuzzy msgid "upnpc not found\n" msgstr "Kommando `%s' wurde nicht gefunden!\n" #: src/nat/nat_auto.c:447 msgid "gnunet-helper-nat-server found, testing it\n" msgstr "" #: src/nat/nat_auto.c:448 msgid "No working gnunet-helper-nat-server found\n" msgstr "" #: src/nat/nat_auto.c:482 msgid "gnunet-helper-nat-client found, enabling it\n" msgstr "" #: src/nat/nat_auto.c:483 msgid "gnunet-helper-nat-client not found or behind NAT, disabling it\n" msgstr "" #: src/nat/nat.c:867 #, c-format msgid "gnunet-helper-nat-server generated malformed address `%s'\n" msgstr "" #: src/nat/nat.c:917 #, fuzzy, c-format msgid "Failed to start %s\n" msgstr "Fehler beim Starten der Collection.\n" #: src/nat/nat.c:1205 msgid "malformed" msgstr "" #: src/nat/nat.c:1276 src/nat/nat.c:1288 #, c-format msgid "" "Configuration requires `%s', but binary is not installed properly (SUID bit " "not set). Option disabled.\n" msgstr "" #: src/nat/nat.c:1426 msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n" msgstr "" #: src/nat/nat.c:1442 #, c-format msgid "Running gnunet-helper-nat-client %s %s %u\n" msgstr "" #: src/nat/nat_mini.c:155 msgid "no valid address was returned by `external-ip'" msgstr "" #: src/nat/nat_mini.c:175 msgid "`external-ip' command not found" msgstr "" #: src/nat/nat_mini.c:201 msgid "`external-ip' command not found\n" msgstr "" #: src/nat/nat_mini.c:366 #, fuzzy msgid "Failed to run `upnpc` command" msgstr "Fehler beim Starten der Collection.\n" #: src/nat/nat_mini.c:512 msgid "`upnpc' command took too long, process killed" msgstr "" #: src/nat/nat_mini.c:540 msgid "`upnpc' command failed to establish port mapping" msgstr "" #: src/nat/nat_mini.c:604 msgid "`upnpc' command not found\n" msgstr "" #: src/nat/nat_mini.c:608 #, fuzzy msgid "`upnpc` command not found" msgstr "Kommando `%s' wurde nicht gefunden!\n" #: src/nat/nat_test.c:351 #, fuzzy msgid "Failed to connect to `gnunet-nat-server'\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/nat/nat_test.c:423 #, c-format msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n" msgstr "" #: src/nse/gnunet-nse.c:117 #, fuzzy msgid "NSE service is not running\n" msgstr "`%s' ist keine Datei.\n" #: src/nse/gnunet-nse.c:122 msgid "Error while checking if NSE service is running or not\n" msgstr "" #: src/nse/gnunet-nse.c:168 #, fuzzy msgid "Show network size estimates from NSE service." msgstr "# Client Trace-Anfragen empfangen" #: src/nse/gnunet-nse-profiler.c:858 #, fuzzy msgid "limit to the number of connections to NSE services, 0 for none" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/nse/gnunet-nse-profiler.c:861 msgid "name of the file for writing connection information and statistics" msgstr "" #: src/nse/gnunet-nse-profiler.c:864 src/testbed/gnunet-testbed-profiler.c:306 msgid "name of the file with the login information for the testbed" msgstr "" #: src/nse/gnunet-nse-profiler.c:867 msgid "name of the file for writing the main results" msgstr "" #: src/nse/gnunet-nse-profiler.c:870 msgid "Number of peers to run in each round, separated by commas" msgstr "" #: src/nse/gnunet-nse-profiler.c:876 msgid "delay between rounds" msgstr "" #: src/nse/gnunet-nse-profiler.c:885 #, fuzzy msgid "Measure quality and performance of the NSE service." msgstr "Auf den Dienst konnte nicht zugegriffen werden" #: src/nse/gnunet-service-nse.c:1517 #: src/revocation/gnunet-service-revocation.c:789 src/util/gnunet-scrypt.c:248 msgid "Value is too large.\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:215 #, fuzzy, c-format msgid "Removing expired address of transport `%s'\n" msgstr "Verfügbare(r) Transport(e): %s\n" #: src/peerinfo/gnunet-service-peerinfo.c:352 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s': %s\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/peerinfo/gnunet-service-peerinfo.c:371 #: src/peerinfo/gnunet-service-peerinfo.c:388 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/peerinfo/gnunet-service-peerinfo.c:466 msgid "# peers known" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:503 #, c-format msgid "" "File `%s' in directory `%s' does not match naming convention. Removed.\n" msgstr "" "Die Datei `%s' im Verzeichnis `%s' entspricht nicht der Namenskonvention. " "Datei wurde entfernt.\n" #: src/peerinfo/gnunet-service-peerinfo.c:653 #, fuzzy, c-format msgid "Scanning directory `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/peerinfo/gnunet-service-peerinfo.c:658 #, fuzzy, c-format msgid "Still no peers found in `%s'!\n" msgstr "Dienst `%s' konnte nicht ordentlich entladen werden!\n" #: src/peerinfo/gnunet-service-peerinfo.c:994 #, fuzzy, c-format msgid "Cleaning up directory `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/peerinfo/gnunet-service-peerinfo.c:1287 #, c-format msgid "Importing HELLOs from `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:1298 msgid "Skipping import of included HELLOs\n" msgstr "" #: src/peerinfo/peerinfo_api.c:236 msgid "aborted due to explicit disconnect request" msgstr "" #: src/peerinfo/peerinfo_api.c:356 #, fuzzy msgid "failed to transmit request (service down?)" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/peerinfo/peerinfo_api.c:506 #, fuzzy msgid "Failed to receive response from `PEERINFO' service." msgstr "Fehler beim Empfangen der Antwort von gnunetd auf die `%s' Nachricht\n" #: src/peerinfo/peerinfo_api.c:547 src/peerinfo/peerinfo_api.c:566 #: src/peerinfo/peerinfo_api.c:581 src/peerinfo/peerinfo_api.c:592 #: src/peerinfo/peerinfo_api.c:603 #, fuzzy msgid "Received invalid message from `PEERINFO' service." msgstr "Ungültige `%s' Anfrage von `%s' empfangen.\n" #: src/peerinfo/peerinfo_api.c:678 #, fuzzy msgid "Timeout transmitting iteration request to `PEERINFO' service." msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/peerinfo/peerinfo_api_notify.c:268 #, fuzzy, c-format msgid "Could not connect to `%s' service.\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:232 #, fuzzy, c-format msgid "%sPeer `%s'\n" msgstr "Ich bin Peer `%s'.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:239 #, c-format msgid "\tExpires: %s \t %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:428 #, fuzzy, c-format msgid "Failure: Did not receive %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:436 #, fuzzy, c-format msgid "Failure: Received invalid %s\n" msgstr "ungültige `%s' Nachricht empfangen: %s.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:445 #, fuzzy, c-format msgid "Failed to write HELLO with %u bytes to file `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/peerinfo-tool/gnunet-peerinfo.c:458 #, c-format msgid "Wrote %s HELLO containing %u addresses with %u bytes to file `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:522 #, fuzzy, c-format msgid "Failure adding HELLO: %s\n" msgstr "Fehler bei %s:%d.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:633 #, fuzzy, c-format msgid "Service `%s' is not running, please start GNUnet\n" msgstr "`%s' ist keine Datei.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:654 src/util/gnunet-scrypt.c:224 #, fuzzy, c-format msgid "Loading hostkey from `%s' failed.\n" msgstr "Das Parsen des Hello von `%s' schlug fehl.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:745 #, c-format msgid "I am peer `%s'.\n" msgstr "Ich bin Peer `%s'.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:789 msgid "don't resolve host names" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:792 msgid "output only the identity strings" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:795 msgid "include friend-only information" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:798 msgid "output our own identity only" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:801 msgid "list all known peers" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:804 msgid "dump hello to file" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:807 msgid "also output HELLO uri(s)" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:810 msgid "add given HELLO uri to the database" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:821 #, fuzzy msgid "Print information about peers." msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:105 #: src/transport/gnunet-service-transport_plugins.c:128 #, fuzzy, c-format msgid "Starting transport plugins `%s'\n" msgstr "Teste Transport(e) %s\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:109 #: src/transport/gnunet-service-transport_plugins.c:133 #, fuzzy, c-format msgid "Loading `%s' transport plugin\n" msgstr "Teste Transport(e) %s\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:129 #: src/transport/gnunet-service-transport_plugins.c:165 #, fuzzy, c-format msgid "Failed to load transport plugin for `%s'\n" msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #: src/postgres/postgres.c:59 #, fuzzy, c-format msgid "`%s:%s' failed at %s:%d with error: %s" msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #: src/postgres/postgres.c:148 #, fuzzy, c-format msgid "Unable to initialize Postgres: %s" msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n" #: src/psycstore/gnunet-service-psycstore.c:200 #, fuzzy msgid "Failed to store membership information!\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/psycstore/gnunet-service-psycstore.c:224 #, fuzzy msgid "Failed to test membership!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/psycstore/gnunet-service-psycstore.c:246 #, fuzzy msgid "Failed to store fragment!\n" msgstr "Fehler beim Starten der Collection.\n" #: src/psycstore/gnunet-service-psycstore.c:272 #, fuzzy msgid "Failed to get fragment!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/psycstore/gnunet-service-psycstore.c:299 #, fuzzy msgid "Failed to get message!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/psycstore/gnunet-service-psycstore.c:328 #, fuzzy msgid "Failed to get message fragment!\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/psycstore/gnunet-service-psycstore.c:356 #, fuzzy msgid "Failed to get master counters!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/psycstore/gnunet-service-psycstore.c:392 #: src/psycstore/gnunet-service-psycstore.c:465 msgid "Tried to set invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:408 #, fuzzy msgid "Failed to begin modifying state!\n" msgstr "Fehler beim Starten der Collection.\n" #: src/psycstore/gnunet-service-psycstore.c:431 #, fuzzy, c-format msgid "Unknown operator: %c\n" msgstr "Unbekannte Operation `%s'\n" #: src/psycstore/gnunet-service-psycstore.c:441 #, fuzzy msgid "Failed to end modifying state!\n" msgstr "Fehler beim Starten der Collection.\n" #: src/psycstore/gnunet-service-psycstore.c:479 #, fuzzy msgid "Failed to begin synchronizing state!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/psycstore/gnunet-service-psycstore.c:495 #, fuzzy msgid "Failed to end synchronizing state!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/psycstore/gnunet-service-psycstore.c:515 #: src/psycstore/gnunet-service-psycstore.c:534 #, fuzzy msgid "Failed to reset state!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/psycstore/gnunet-service-psycstore.c:557 #: src/psycstore/gnunet-service-psycstore.c:608 msgid "Tried to get invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:584 #: src/psycstore/gnunet-service-psycstore.c:623 #, fuzzy msgid "Failed to get state variable!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/psycstore/plugin_psycstore_sqlite.c:60 #, fuzzy, c-format msgid "`%s' failed at %s:%d with error: %s (%d)\n" msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #: src/psycstore/plugin_psycstore_sqlite.c:253 #, fuzzy, c-format msgid "" "Error preparing SQL query: %s\n" " %s\n" msgstr "Fehler beim Anlegen des Benutzers" #: src/psycstore/plugin_psycstore_sqlite.c:276 #, fuzzy, c-format msgid "" "Error executing SQL query: %s\n" " %s\n" msgstr "Fehler beim Anlegen des Benutzers" #: src/psycstore/plugin_psycstore_sqlite.c:1796 #, fuzzy msgid "SQLite database running\n" msgstr "sqlite Datenspeicher" #: src/pt/gnunet-daemon-pt.c:482 #, fuzzy msgid "Failed to pack DNS request. Dropping.\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/pt/gnunet-daemon-pt.c:488 #, fuzzy msgid "# DNS requests mapped to VPN" msgstr "# Client Trace-Anfragen empfangen" #: src/pt/gnunet-daemon-pt.c:541 msgid "# DNS records modified" msgstr "" #: src/pt/gnunet-daemon-pt.c:717 msgid "# DNS replies intercepted" msgstr "" #: src/pt/gnunet-daemon-pt.c:723 #, fuzzy msgid "Failed to parse DNS request. Dropping.\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/pt/gnunet-daemon-pt.c:826 #, fuzzy msgid "# DNS requests dropped (timeout)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/pt/gnunet-daemon-pt.c:883 #, fuzzy msgid "# DNS requests intercepted" msgstr "# Client Trace-Anfragen empfangen" #: src/pt/gnunet-daemon-pt.c:888 #, fuzzy msgid "# DNS requests dropped (DNS mesh channel down)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/pt/gnunet-daemon-pt.c:896 #, fuzzy msgid "# DNS requests dropped (malformed)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/pt/gnunet-daemon-pt.c:969 #, fuzzy msgid "# DNS replies received" msgstr "# Client Trace-Anfragen empfangen" #: src/pt/gnunet-daemon-pt.c:985 #, fuzzy msgid "# DNS replies dropped (too late?)" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/pt/gnunet-daemon-pt.c:1261 src/pt/gnunet-daemon-pt.c:1270 #: src/pt/gnunet-daemon-pt.c:1290 src/pt/gnunet-daemon-pt.c:1301 #: src/pt/gnunet-daemon-pt.c:1310 #, fuzzy, c-format msgid "Failed to connect to %s service. Exiting.\n" msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/pt/gnunet-daemon-pt.c:1347 msgid "Daemon to run to perform IP protocol translation to GNUnet" msgstr "" #: src/regex/gnunet-daemon-regexprofiler.c:270 #: src/regex/gnunet-regex-simulation-profiler.c:659 #, fuzzy, c-format msgid "%s service is lacking key configuration settings (%s). Exiting.\n" msgstr "GNUnet Konfiguration" #: src/regex/gnunet-daemon-regexprofiler.c:380 msgid "Daemon to announce regular expressions for the peer using mesh." msgstr "" #: src/regex/gnunet-regex-profiler.c:1288 #, fuzzy msgid "No configuration file given. Exiting\n" msgstr "Konfigurationsdatei FILENAME verwenden" #: src/regex/gnunet-regex-profiler.c:1299 #, fuzzy msgid "Configuration option \"regex_prefix\" missing. Exiting\n" msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #: src/regex/gnunet-regex-profiler.c:1328 #: src/regex/gnunet-regex-simulation-profiler.c:622 #, c-format msgid "No policy directory specified on command line. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1334 #: src/regex/gnunet-regex-simulation-profiler.c:629 #, c-format msgid "Specified policies directory does not exist. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1341 #, fuzzy, c-format msgid "No files found in `%s'\n" msgstr "Dienst `%s' konnte nicht ordentlich entladen werden!\n" #: src/regex/gnunet-regex-profiler.c:1350 msgid "No search strings file given. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1370 #, fuzzy msgid "Error loading search strings. Exiting.\n" msgstr "Fehler beim Verlassen der DHT.\n" #: src/regex/gnunet-regex-profiler.c:1455 #, fuzzy msgid "name of the file for writing statistics" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/regex/gnunet-regex-profiler.c:1458 msgid "wait TIMEOUT before ending the experiment" msgstr "" #: src/regex/gnunet-regex-profiler.c:1461 msgid "directory with policy files" msgstr "" #: src/regex/gnunet-regex-profiler.c:1464 #, fuzzy msgid "name of file with input strings" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/regex/gnunet-regex-profiler.c:1467 #, fuzzy msgid "name of file with hosts' names" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/regex/gnunet-regex-profiler.c:1479 msgid "Profiler for regex" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:689 msgid "name of the table to write DFAs" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:692 msgid "maximum path compression length" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:705 msgid "Profiler for regex library" msgstr "" #: src/regex/regex_api.c:131 #, fuzzy, c-format msgid "Regex `%s' is too long!\n" msgstr "`%s' ist keine Datei.\n" #: src/revocation/gnunet-revocation.c:126 #, fuzzy, c-format msgid "Key `%s' is valid\n" msgstr "Format des Pseudonyms `%s' ist ungültig.\n" #: src/revocation/gnunet-revocation.c:131 #, fuzzy, c-format msgid "Key `%s' has been revoked\n" msgstr "Dienst gelöscht.\n" #: src/revocation/gnunet-revocation.c:137 #, fuzzy msgid "Internal error\n" msgstr "Unbekannter Fehler.\n" #: src/revocation/gnunet-revocation.c:163 #, c-format msgid "Key for ego `%s' is still valid, revocation failed (!)\n" msgstr "" #: src/revocation/gnunet-revocation.c:168 #, fuzzy msgid "Revocation failed (!)\n" msgstr "Absicherung fehlgeschlagen bei %s:%d.\n" #: src/revocation/gnunet-revocation.c:173 #, c-format msgid "Key for ego `%s' has been successfully revoked\n" msgstr "" #: src/revocation/gnunet-revocation.c:178 msgid "Revocation successful.\n" msgstr "" #: src/revocation/gnunet-revocation.c:183 msgid "Internal error, key revocation might have failed\n" msgstr "" #: src/revocation/gnunet-revocation.c:294 #, c-format msgid "Revocation certificate for `%s' stored in `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:324 #, fuzzy, c-format msgid "Ego `%s' not found.\n" msgstr "`%s' fehlgeschlagen: Tabelle nicht gefunden!\n" #: src/revocation/gnunet-revocation.c:345 #, c-format msgid "Error: revocation certificate in `%s' is not for `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:365 msgid "Revocation certificate ready\n" msgstr "" #: src/revocation/gnunet-revocation.c:375 msgid "Revocation certificate not ready, calculating proof of work\n" msgstr "" #: src/revocation/gnunet-revocation.c:407 #, fuzzy, c-format msgid "Public key `%s' malformed\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/revocation/gnunet-revocation.c:421 msgid "" "Testing and revoking at the same time is not allowed, only executing test.\n" msgstr "" #: src/revocation/gnunet-revocation.c:441 #, fuzzy msgid "No filename to store revocation certificate given.\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/revocation/gnunet-revocation.c:463 #, fuzzy, c-format msgid "Failed to read revocation certificate from `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/revocation/gnunet-revocation.c:488 #, fuzzy msgid "No action specified. Nothing to do.\n" msgstr "Keine Oberfläche angegeben, verwende Standard\n" #: src/revocation/gnunet-revocation.c:504 msgid "use NAME for the name of the revocation file" msgstr "" #: src/revocation/gnunet-revocation.c:507 msgid "" "revoke the private key associated for the the private key associated with " "the ego NAME " msgstr "" #: src/revocation/gnunet-revocation.c:510 msgid "actually perform revocation, otherwise we just do the precomputation" msgstr "" #: src/revocation/gnunet-revocation.c:513 msgid "test if the public key KEY has been revoked" msgstr "" #: src/revocation/gnunet-service-revocation.c:272 msgid "Duplicate revocation received from peer. Ignored.\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:434 #, c-format msgid "Error computing revocation set union with %s\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:486 msgid "SET service crashed, terminating revocation service\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:812 #, fuzzy msgid "Could not open revocation database file!" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/scalarproduct/gnunet-scalarproduct.c:225 #, fuzzy msgid "You must specify at least one message ID to check!\n" msgstr "Sie müssen eine Liste von Dateien zum Einfügen angeben.\n" #: src/scalarproduct/gnunet-scalarproduct.c:232 msgid "This program needs a session identifier for comparing vectors.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:239 msgid "Please give a session key for --input_key!\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:251 #, c-format msgid "" "Tried to set initiator mode, as peer ID was given. However, `%s' is not a " "valid peer identifier.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:278 #: src/scalarproduct/gnunet-scalarproduct.c:314 #, fuzzy, c-format msgid "Could not convert `%s' to int32_t.\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/scalarproduct/gnunet-scalarproduct.c:286 msgid "Need elements to compute the vectorproduct, got none.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:346 #, fuzzy, c-format msgid "Could not convert `%s' to integer.\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/scalarproduct/gnunet-scalarproduct.c:407 msgid "" "A comma separated list of elements to compare as vector with our remote peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:410 msgid "" "A comma separated mask to select which elements should actually be compared." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:413 msgid "" "[Optional] peer to calculate our scalarproduct with. If this parameter is " "not given, the service will wait for a remote peer to compute the request." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:416 msgid "Transaction ID shared with peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:425 msgid "Calculate the Vectorproduct with a GNUnet peer." msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:541 #, fuzzy, c-format msgid "Client (%p) disconnected from us.\n" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:613 #: src/scalarproduct/gnunet-service-scalarproduct.c:702 #, fuzzy, c-format msgid "Could not send message to client (%p)!\n" msgstr "Nachricht konnte nicht an gnunetd gesendet werden.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:619 #, c-format msgid "Sending session-end notification to client (%p) for session %s\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:712 #, c-format msgid "Sent result to client (%p), this session (%s) has ended!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:766 #: src/scalarproduct/gnunet-service-scalarproduct.c:855 #, fuzzy msgid "Could not send service-response message via mesh!)\n" msgstr "Nachricht konnte nicht an gnunetd gesendet werden.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1028 #, c-format msgid "Failed to communicate with `%s', scalar product calculation aborted.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1099 #: src/scalarproduct/gnunet-service-scalarproduct.c:1208 #, fuzzy msgid "Transmitting service request.\n" msgstr "Collection `%s' begonnen.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1108 #, fuzzy msgid "Could not send service-request multipart message to channel!\n" msgstr "Nachricht konnte nicht an gnunetd gesendet werden.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1147 #, fuzzy, c-format msgid "Successfully created new channel to peer (%s)!\n" msgstr "Zugriff verweigert für `%s' bei %s:%d.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1217 #, fuzzy msgid "Could not send message to channel!\n" msgstr "Nachricht konnte nicht an gnunetd gesendet werden.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1274 #, fuzzy msgid "Too short message received from client!\n" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1287 #, fuzzy msgid "Invalid message received from client, session information incorrect!\n" msgstr "Ungültige `%s' Nachricht von Knoten `%s' empfangen.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1298 #, c-format msgid "" "Duplicate session information received, cannot create new session with key `" "%s'\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1318 #, c-format msgid "" "Got client-request-session with key %s, preparing channel to remote " "service.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1354 #, c-format msgid "Creating new channel for session with key %s.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1399 #, c-format msgid "" "Got client-responder-session with key %s and a matching service-request-" "session set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1409 #, c-format msgid "" "Got client-responder-session with key %s but NO matching service-request-" "session set, queuing element for later use.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1439 #, fuzzy, c-format msgid "New incoming channel from peer %s.\n" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1471 #, c-format msgid "Peer disconnected, terminating session %s with peer (%s)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1672 #: src/scalarproduct/gnunet-service-scalarproduct.c:1814 #, c-format msgid "Got session with key %s and a matching element set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1681 #: src/scalarproduct/gnunet-service-scalarproduct.c:1821 #, c-format msgid "Got session with key %s without a matching element set, queueing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1771 #, c-format msgid "" "Got message with duplicate session key (`%s'), ignoring service request.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2014 msgid "Shutting down, initiating cleanup.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2100 #, fuzzy msgid "Connect to MESH failed\n" msgstr " Verbindung fehlgeschlagen (Bug?)\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:2104 #, fuzzy msgid "Mesh initialized\n" msgstr " Verbindung fehlgeschlagen\n" #: src/scalarproduct/scalarproduct_api.c:246 #, fuzzy msgid "# SUC responder result messages received" msgstr "# verschlüsselter PING Nachrichten empfangen" #: src/scalarproduct/scalarproduct_api.c:300 #, fuzzy msgid "# bytes sent to scalarproduct" msgstr "# bytes in der Datenbank" #: src/scalarproduct/scalarproduct_api.c:345 #: src/scalarproduct/scalarproduct_api.c:440 #, fuzzy msgid "Failed to connect to the scalarproduct service\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/scalarproduct/scalarproduct_api.c:353 #: src/scalarproduct/scalarproduct_api.c:448 #, fuzzy msgid "Failed to send a message to the statistics service\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/scalarproduct/scalarproduct_api.c:387 #: src/scalarproduct/scalarproduct_api.c:485 #, fuzzy msgid "Failed to send a message to the scalarproduct service\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/secretsharing/gnunet-secretsharing-profiler.c:538 msgid "dkg start delay" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:541 msgid "dkg timeout" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:544 msgid "threshold" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:547 msgid "also profile decryption" msgstr "" #: src/set/gnunet-service-set.c:1431 #, fuzzy msgid "Could not connect to mesh service\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/set/gnunet-set-ibf-profiler.c:221 #, fuzzy msgid "number of element in set A-B" msgstr "Anzahl an Durchläufen" #: src/set/gnunet-set-ibf-profiler.c:224 #, fuzzy msgid "number of element in set B-A" msgstr "Anzahl an Durchläufen" #: src/set/gnunet-set-ibf-profiler.c:227 msgid "number of common elements in A and B" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:230 msgid "hash num" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:233 msgid "ibf size" msgstr "" #: src/set/gnunet-set-profiler.c:295 msgid "oeration to execute" msgstr "" #: src/statistics/gnunet-service-statistics.c:280 #, fuzzy, c-format msgid "Loading %llu bytes of statistics from `%s'\n" msgstr "Dateien aus dem GNUnet herunterladen." #: src/statistics/gnunet-service-statistics.c:346 #, fuzzy, c-format msgid "Wrote %llu bytes of statistics to `%s'\n" msgstr "Dateien aus dem GNUnet herunterladen." #: src/statistics/gnunet-statistics.c:140 #, fuzzy msgid "Failed to obtain statistics.\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/statistics/gnunet-statistics.c:142 #, fuzzy, c-format msgid "Failed to obtain statistics from host `%s:%llu'\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/statistics/gnunet-statistics.c:189 msgid "Missing argument: subsystem \n" msgstr "" #: src/statistics/gnunet-statistics.c:195 msgid "Missing argument: name\n" msgstr "" #: src/statistics/gnunet-statistics.c:226 #, c-format msgid "No subsystem or name given\n" msgstr "" #: src/statistics/gnunet-statistics.c:234 #, fuzzy, c-format msgid "Failed to initialize watch routine\n" msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n" #: src/statistics/gnunet-statistics.c:261 #, fuzzy, c-format msgid "Trying to connect to remote host, but service `%s' is not running\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/statistics/gnunet-statistics.c:269 #, fuzzy, c-format msgid "A port is required to connect to host `%s'\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/statistics/gnunet-statistics.c:276 #, c-format msgid "A port has to be between 1 and 65535 to connect to host `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:308 #, fuzzy, c-format msgid "Invalid argument `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/statistics/gnunet-statistics.c:334 msgid "limit output to statistics for the given NAME" msgstr "" #: src/statistics/gnunet-statistics.c:337 msgid "make the value being set persistent" msgstr "" #: src/statistics/gnunet-statistics.c:340 msgid "limit output to the given SUBSYSTEM" msgstr "" #: src/statistics/gnunet-statistics.c:343 msgid "just print the statistics value" msgstr "" #: src/statistics/gnunet-statistics.c:346 msgid "watch value continuously" msgstr "" #: src/statistics/gnunet-statistics.c:349 msgid "connect to remote host" msgstr "" #: src/statistics/gnunet-statistics.c:352 msgid "port for remote host" msgstr "" #: src/statistics/gnunet-statistics.c:364 msgid "Print statistics about GNUnet operations." msgstr "Statistiken der GNUnet Aktivitäten ausgeben." #: src/statistics/statistics_api.c:519 #, fuzzy msgid "Could not save some persistent statistics\n" msgstr "" "IP(v4) dieses Hosts konnte nicht ermittelt werden. Bitte geben Sie die IP in " "der Konfigurationsdatei an.\n" #: src/statistics/statistics_api.c:1090 msgid "" "Failed to receive acknowledgement from statistics service, some statistics " "might have been lost!\n" msgstr "" #: src/testbed/generate-underlay-topology.c:223 msgid "Need atleast 2 arguments\n" msgstr "" #: src/testbed/generate-underlay-topology.c:228 msgid "Database filename missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:235 msgid "Topology string missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:240 #, fuzzy, c-format msgid "Invalid topology: %s\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/testbed/generate-underlay-topology.c:252 #, c-format msgid "An argument is missing for given topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:258 #, fuzzy, c-format msgid "Invalid argument `%s' given as topology argument\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/testbed/generate-underlay-topology.c:266 #, c-format msgid "Filename argument missing for topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:280 #, c-format msgid "Second argument for topology `%s' is missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:286 #, fuzzy, c-format msgid "Invalid argument `%s'; expecting unsigned int\n" msgstr "Ungültiger Parameter für `%s' bei %s:%d.\n" #: src/testbed/generate-underlay-topology.c:335 #: src/testbed/gnunet-testbed-profiler.c:293 msgid "create COUNT number of peers" msgstr "" #: src/testbed/generate-underlay-topology.c:344 msgid "" "Generates SQLite3 database representing a given underlay topology.\n" "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" "The following options are available for TOPO followed by TOPOOPTS if " "applicable:\n" "\t LINE\n" "\t RING\n" "\t RANDOM \n" "\t SMALL_WORLD \n" "\t SMALL_WORLD_RING \n" "\t CLIQUE\n" "\t 2D_TORUS\n" "\t SCALE_FREE \n" "\t FROM_FILE \n" "TOPOOPTS:\n" "\t num_rnd_links: The number of random links\n" "\t cap: the maximum number of links a node can have\n" "\t m: the number of links a node should have while joining the network\n" "\t filename: the path of the file which contains topology information\n" "NOTE: the format of the above file is descibed here: https://www.gnunet.org/" "content/topology-file-format\n" msgstr "" #: src/testbed/gnunet-daemon-latency-logger.c:325 msgid "Daemon to log latency values of connections to neighbours" msgstr "" #: src/testbed/gnunet-daemon-testbed-blacklist.c:264 msgid "" "Daemon to restrict incoming transport layer connections during testbed " "deployments" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:235 src/testing/list-keys.c:50 #: src/testing/testing.c:293 src/util/gnunet-ecc.c:217 #, c-format msgid "Incorrect hostkey file format: %s\n" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:474 msgid "Daemon to restrict underlay network in testbed deployments" msgstr "" #: src/testbed/gnunet-service-testbed_cpustatus.c:730 #, c-format msgid "" "Cannot open %s for writing load statistics. Not logging load statistics\n" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1015 #, fuzzy msgid "Misconfiguration (can't connect to the ARM service)" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/testbed/gnunet-service-testbed_peers.c:1021 msgid "Request doesn't fit into a message" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1059 #, fuzzy, c-format msgid "%s service can't be started because ARM is shutting down" msgstr "`%s' fährt herunter.\n" #: src/testbed/gnunet_testbed_mpi_spawn.c:125 #, fuzzy msgid "Waiting for child to exit.\n" msgstr "" "Warte darauf, dass sich andere Knoten verbinden (%u Iterationen " "verbleiben)...\n" #: src/testbed/gnunet_testbed_mpi_spawn.c:247 #, fuzzy, c-format msgid "Spawning process `%s'\n" msgstr "Collection `%s' begonnen.\n" #: src/testbed/gnunet-testbed-profiler.c:267 #, fuzzy, c-format msgid "Exiting as the number of peers is %u\n" msgstr "Maximale Anzahl an Chat Clients erreicht.\n" #: src/testbed/gnunet-testbed-profiler.c:296 msgid "tolerate COUNT number of continious timeout failures" msgstr "" #: src/testbed/gnunet-testbed-profiler.c:299 msgid "" "run profiler in non-interactive mode where upon testbed setup the profiler " "does not wait for a keystroke but continues to run until a termination " "signal is received" msgstr "" #: src/testbed/testbed_api_hosts.c:415 #, fuzzy, c-format msgid "Hosts file %s not found\n" msgstr "`%s' fehlgeschlagen: Tabelle nicht gefunden!\n" #: src/testbed/testbed_api_hosts.c:423 #, fuzzy, c-format msgid "Hosts file %s has no data\n" msgstr "Sitzungsschlüssel von Knoten `%s' konnte nicht überprüft werden.\n" #: src/testbed/testbed_api_hosts.c:430 #, fuzzy, c-format msgid "Hosts file %s cannot be read\n" msgstr "Sitzungsschlüssel von Knoten `%s' konnte nicht überprüft werden.\n" #: src/testbed/testbed_api_hosts.c:570 #, c-format msgid "The function %s is only available when compiled with (--with-ll)\n" msgstr "" #: src/testbed/testbed_api_hosts.c:1586 #, fuzzy, c-format msgid "Adding host %u failed with error: %s\n" msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #: src/testbed/testbed_api_testbed.c:819 msgid "Linking controllers failed. Exiting" msgstr "" #: src/testbed/testbed_api_testbed.c:988 #, c-format msgid "Host registration failed for a host. Error: %s\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1054 msgid "Controller crash detected. Shutting down.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1143 #, c-format msgid "Host %s cannot start testbed\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1147 msgid "Testbed cannot be started on localhost\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1185 #, fuzzy msgid "Cannot start the master controller" msgstr "GNUnet testbed Controller starten." #: src/testbed/testbed_api_testbed.c:1203 msgid "Shutting down testbed due to timeout while setup.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1263 msgid "No hosts loaded from LoadLeveler. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1275 msgid "No hosts loaded. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1299 msgid "Specified topology must be supported by testbed" msgstr "" #: src/testbed/testbed_api_testbed.c:1349 #, c-format msgid "" "Maximum number of edges a peer can have in a scale free topology cannot be " "more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_testbed.c:1365 #, c-format msgid "" "The number of edges that can established when adding a new node to scale " "free topology cannot be more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_topology.c:960 #, fuzzy, c-format msgid "Topology file %s not found\n" msgstr "`%s' fehlgeschlagen: Tabelle nicht gefunden!\n" #: src/testbed/testbed_api_topology.c:966 #, fuzzy, c-format msgid "Topology file %s has no data\n" msgstr "Sitzungsschlüssel von Knoten `%s' konnte nicht überprüft werden.\n" #: src/testbed/testbed_api_topology.c:973 #, fuzzy, c-format msgid "Topology file %s cannot be read\n" msgstr "Sitzungsschlüssel von Knoten `%s' konnte nicht überprüft werden.\n" #: src/testbed/testbed_api_topology.c:995 #, fuzzy, c-format msgid "Failed to read peer index from toology file: %s" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/testbed/testbed_api_topology.c:1004 #: src/testbed/testbed_api_topology.c:1028 #, c-format msgid "Value in given topology file: %s out of range\n" msgstr "" #: src/testbed/testbed_api_topology.c:1010 #: src/testbed/testbed_api_topology.c:1034 #, fuzzy, c-format msgid "Failed to read peer index from topology file: %s" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/testbed/testbed_api_topology.c:1016 #: src/testbed/testbed_api_topology.c:1040 msgid "Topology file needs more peers than given ones\n" msgstr "" #: src/testbed/testbed_api_topology.c:1074 #, fuzzy, c-format msgid "Ignoring to connect peer %u to peer %u\n" msgstr "Verbindung zu %u.%u.%u.%u:%u fehlgeschlagen: %s\n" #: src/testing/gnunet-testing.c:173 #, fuzzy, c-format msgid "Could not extract hostkey %u (offset too large?)\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/testing/gnunet-testing.c:258 #, c-format msgid "Unknown command, use 'q' to quit or 'r' to restart peer\n" msgstr "" #: src/testing/gnunet-testing.c:355 #, fuzzy msgid "create unique configuration files" msgstr "" "Einen Wert aus der Konfigurationsdatei auf der Standardausgabe ausgeben" #: src/testing/gnunet-testing.c:357 msgid "extract hostkey file from pre-computed hostkey list" msgstr "" #: src/testing/gnunet-testing.c:359 #, fuzzy msgid "" "number of unique configuration files to create, or number of the hostkey to " "extract" msgstr "" "Einen Wert aus der Konfigurationsdatei auf der Standardausgabe ausgeben" #: src/testing/gnunet-testing.c:361 #, fuzzy msgid "configuration template" msgstr "GNUnet Konfiguration" #: src/testing/gnunet-testing.c:363 msgid "run the given service, wait on stdin for 'r' (restart) or 'q' (quit)" msgstr "" #: src/testing/gnunet-testing.c:376 msgid "Command line tool to access the testing library" msgstr "" #: src/testing/list-keys.c:90 msgid "list COUNT number of keys" msgstr "" #: src/testing/list-keys.c:93 msgid "skip COUNT number of keys in the beginning" msgstr "" #: src/testing/testing.c:277 #, c-format msgid "Hostkeys file not found: %s\n" msgstr "" #: src/testing/testing.c:718 #, fuzzy, c-format msgid "Key number %u does not exist\n" msgstr "Anzahl an Nachrichten, die pro Durchlauf verwendet wird" #: src/testing/testing.c:1157 #, c-format msgid "" "You attempted to create a testbed with more than %u hosts. Please " "precompute more hostkeys first.\n" msgstr "" #: src/testing/testing.c:1166 #, fuzzy, c-format msgid "Failed to initialize hostkey for peer %u\n" msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n" #: src/testing/testing.c:1176 #, fuzzy msgid "PRIVATE_KEY option in PEER section missing in configuration\n" msgstr "In der Konfigurationsdatei wurden keine Anwendungen definiert!\n" #: src/testing/testing.c:1189 #, fuzzy msgid "Failed to create configuration for peer (not enough free ports?)\n" msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #: src/testing/testing.c:1203 #, fuzzy, c-format msgid "Cannot open hostkey file `%s': %s\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/testing/testing.c:1215 #, fuzzy, c-format msgid "Failed to write hostkey file for peer %u: %s\n" msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #: src/testing/testing.c:1240 #, fuzzy, c-format msgid "Failed to write configuration file `%s' for peer %u: %s\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/testing/testing.c:1342 #, fuzzy, c-format msgid "Failed to start `%s': %s\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/testing/testing.c:1706 #, fuzzy, c-format msgid "Failed to load configuration from %s\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/topology/friends.c:100 #, fuzzy, c-format msgid "Syntax error in FRIENDS file at offset %llu, skipping bytes `%.*s'.\n" msgstr "Syntaxfehler in Topologieangabe, überspringe Bytes `%s'.\n" #: src/topology/friends.c:154 #, c-format msgid "Directory for file `%s' does not seem to be writable.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:255 msgid "# peers blacklisted" msgstr "" #: src/topology/gnunet-daemon-topology.c:388 #, fuzzy msgid "# connect requests issued to transport" msgstr "# Client Trace-Anfragen empfangen" #: src/topology/gnunet-daemon-topology.c:728 #: src/topology/gnunet-daemon-topology.c:813 #, fuzzy msgid "# friends connected" msgstr "# verbundener Knoten" #: src/topology/gnunet-daemon-topology.c:993 msgid "Failed to connect to core service, can not manage topology!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1022 #, c-format msgid "Found myself `%s' in friend list (useless, ignored)\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1029 #, fuzzy, c-format msgid "Found friend `%s' in configuration\n" msgstr " gconfig\tGTK Konfiguration\n" #: src/topology/gnunet-daemon-topology.c:1050 msgid "Encountered errors parsing friends list!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1052 #, fuzzy msgid "# friends in configuration" msgstr " gconfig\tGTK Konfiguration\n" #: src/topology/gnunet-daemon-topology.c:1057 msgid "" "Fewer friends specified than required by minimum friend count. Will only " "connect to friends.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1063 msgid "" "More friendly connections required than target total number of connections.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1094 #, fuzzy msgid "# HELLO messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/topology/gnunet-daemon-topology.c:1151 #, fuzzy msgid "# HELLO messages gossipped" msgstr "# ausgehender Nachrichten verworfen" #: src/topology/gnunet-daemon-topology.c:1290 msgid "GNUnet topology control (maintaining P2P mesh and F2F constraints)" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:271 #, fuzzy, c-format msgid "Adding blacklisting entry for peer `%s'\n" msgstr "Adresse des Knotens `%s' konnte nicht ermittelt werden.\n" #: src/transport/gnunet-service-transport_blacklist.c:279 #, c-format msgid "Adding blacklisting entry for peer `%s':`%s'\n" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:464 #: src/transport/gnunet-service-transport_blacklist.c:745 msgid "# disconnects due to blacklist" msgstr "" #: src/transport/gnunet-service-transport.c:220 #, fuzzy msgid "# bytes payload discarded due to not connected peer" msgstr "# Knotenankündigungen empfangen" #: src/transport/gnunet-service-transport.c:424 #, fuzzy msgid "# bytes total received" msgstr "# gap Anfragen insgesamt empfangen" #: src/transport/gnunet-service-transport.c:515 #, fuzzy msgid "# bytes payload received" msgstr "# Bytes entschlüsselt" #: src/transport/gnunet-service-transport.c:686 #, fuzzy, c-format msgid "Could not obtain a valid network for `%s' %s (%s)\n" msgstr "" "Es konnte keine IP für das Gerät `%s' unter Verwendung von `%s' ermittelt " "werden.\n" #: src/transport/gnunet-service-transport.c:733 #, c-format msgid "" "Address or session unknown: failed to update properties for peer `%s' plugin " "`%s' address `%s' session %p\n" msgstr "" #: src/transport/gnunet-service-transport.c:1084 #, fuzzy msgid "Transport service is lacking key configuration settings. Exiting.\n" msgstr "GNUnet Konfiguration" #: src/transport/gnunet-service-transport_clients.c:432 #, c-format msgid "Dropping message of type %u and size %u, have %u/%u messages pending\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:439 #, fuzzy msgid "# messages dropped due to slow client" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/transport/gnunet-service-transport_clients.c:596 #, c-format msgid "Rejecting control connection from peer `%s', which is not me!\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:737 msgid "# bytes payload dropped (other peer was not connected)" msgstr "" #: src/transport/gnunet-service-transport_clients.c:770 #, fuzzy, c-format msgid "Blacklist refuses connection attempt to peer `%s'\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/transport/gnunet-service-transport_clients.c:776 #, fuzzy, c-format msgid "Blacklist allows connection attempt to peer `%s'\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/transport/gnunet-service-transport_clients.c:801 #, fuzzy msgid "# REQUEST CONNECT messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_clients.c:815 #, fuzzy, c-format msgid "Received a request connect message for peer `%s'\n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/transport/gnunet-service-transport_clients.c:826 #, fuzzy msgid "# REQUEST DISCONNECT messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_clients.c:840 #, fuzzy, c-format msgid "Received a request disconnect message for peer `%s'\n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/transport/gnunet-service-transport_hello.c:181 msgid "# refreshed my HELLO" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1095 #, fuzzy msgid "# DISCONNECT messages sent" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_neighbours.c:1220 #: src/transport/gnunet-service-transport_neighbours.c:1629 #, fuzzy msgid "# bytes in message queue for other peers" msgstr "# Bytes ausgehender Nachrichten verworfen" #: src/transport/gnunet-service-transport_neighbours.c:1225 #, fuzzy msgid "# messages transmitted to other peers" msgstr "# Bytes des Typs %d übertragen" #: src/transport/gnunet-service-transport_neighbours.c:1230 #, fuzzy msgid "# transmission failures for messages to other peers" msgstr "# Bytes ausgehender Nachrichten verworfen" #: src/transport/gnunet-service-transport_neighbours.c:1287 msgid "# messages timed out while in transport queue" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1343 #, fuzzy msgid "# keepalives sent" msgstr "# p2p Trace-Antworten gesendet" #: src/transport/gnunet-service-transport_neighbours.c:1376 #, fuzzy msgid "# KEEPALIVE messages discarded (peer unknown)" msgstr "# defragmentierter Nachrichten" #: src/transport/gnunet-service-transport_neighbours.c:1384 #, fuzzy msgid "# KEEPALIVE messages discarded (no session)" msgstr "# defragmentierter Nachrichten" #: src/transport/gnunet-service-transport_neighbours.c:1431 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (not connected)" msgstr "# defragmentierter Nachrichten" #: src/transport/gnunet-service-transport_neighbours.c:1440 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (not expected)" msgstr "# defragmentierter Nachrichten" #: src/transport/gnunet-service-transport_neighbours.c:1448 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (address changed)" msgstr "# defragmentierter Nachrichten" #: src/transport/gnunet-service-transport_neighbours.c:1456 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (wrong nonce)" msgstr "# defragmentierter Nachrichten" #: src/transport/gnunet-service-transport_neighbours.c:1534 #, fuzzy msgid "# messages discarded due to lack of neighbour record" msgstr "# defragmentierter Nachrichten" #: src/transport/gnunet-service-transport_neighbours.c:1568 #, fuzzy msgid "# bandwidth quota violations by other peers" msgstr "Verfolgt die Bandbreitennutzung von gnunetd" #: src/transport/gnunet-service-transport_neighbours.c:1584 msgid "# ms throttling suggested" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1678 #, fuzzy, c-format msgid "" "Failed to send CONNECT message to peer `%s' using address `%s' session %p\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/transport/gnunet-service-transport_neighbours.c:1705 msgid "# Failed attempts to switch addresses (failed to send CONNECT CONT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1751 #, fuzzy msgid "# SESSION_CONNECT messages sent" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_neighbours.c:1767 #, fuzzy, c-format msgid "Failed to transmit CONNECT message via plugin to %s\n" msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/transport/gnunet-service-transport_neighbours.c:1794 msgid "# Failed attempts to switch addresses (failed to send CONNECT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1844 #, c-format msgid "" "Failed to send CONNECT_ACK message to peer `%s' using address `%s' session " "%p\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1899 #, fuzzy msgid "# CONNECT_ACK messages sent" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_neighbours.c:1914 #, fuzzy, c-format msgid "Failed to transmit CONNECT_ACK message via plugin to %s\n" msgstr "`%s' Dienst konnte nicht initialisiert werden.\n" #: src/transport/gnunet-service-transport_neighbours.c:2192 #, fuzzy, c-format msgid "Blacklisting disapproved to connect to peer `%s'\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/transport/gnunet-service-transport_neighbours.c:2312 #, fuzzy msgid "# CONNECT messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_neighbours.c:2317 #, c-format msgid "CONNECT request from peer `%s' ignored due impending shutdown\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2590 msgid "# Attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3012 #, fuzzy msgid "# Failed attempts to switch addresses (no response)" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/transport/gnunet-service-transport_neighbours.c:3107 #, fuzzy msgid "# CONNECT_ACK messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_neighbours.c:3115 #, fuzzy msgid "# unexpected CONNECT_ACK messages (no peer)" msgstr "COUNT Nachrichten versenden" #: src/transport/gnunet-service-transport_neighbours.c:3129 #: src/transport/gnunet-service-transport_neighbours.c:3164 #, fuzzy msgid "# unexpected CONNECT_ACK messages (not ready)" msgstr "COUNT Nachrichten versenden" #: src/transport/gnunet-service-transport_neighbours.c:3176 #, fuzzy msgid "# unexpected CONNECT_ACK messages (waiting on ATS)" msgstr "COUNT Nachrichten versenden" #: src/transport/gnunet-service-transport_neighbours.c:3200 msgid "# Successful attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3208 #, fuzzy msgid "# unexpected CONNECT_ACK messages (disconnecting)" msgstr "COUNT Nachrichten versenden" #: src/transport/gnunet-service-transport_neighbours.c:3396 #, fuzzy msgid "# SESSION_ACK messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_neighbours.c:3424 #, fuzzy msgid "# unexpected SESSION_ACK messages" msgstr "# verschlüsselter PONG Nachrichten gesendet" #: src/transport/gnunet-service-transport_neighbours.c:3490 msgid "# SET QUOTA messages ignored (no such peer)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3505 msgid "# disconnects due to quota of 0" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3545 msgid "# disconnect messages ignored (malformed)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3551 #, fuzzy msgid "# DISCONNECT messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/gnunet-service-transport_neighbours.c:3560 msgid "# disconnect messages ignored (timestamp)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3687 #, fuzzy msgid "# disconnected from peer upon explicit request" msgstr "# gap Anfragen verworfen: Kollision in RT" #: src/transport/gnunet-service-transport_plugins.c:120 msgid "Transport service is lacking NEIGHBOUR_LIMIT option.\n" msgstr "" #: src/transport/gnunet-service-transport_plugins.c:178 #: src/transport/gnunet-service-transport_plugins.c:186 #: src/transport/gnunet-service-transport_plugins.c:194 #: src/transport/gnunet-service-transport_plugins.c:202 #: src/transport/gnunet-service-transport_plugins.c:210 #: src/transport/gnunet-service-transport_plugins.c:218 #: src/transport/gnunet-service-transport_plugins.c:226 #: src/transport/gnunet-service-transport_plugins.c:234 #: src/transport/gnunet-service-transport_plugins.c:242 #: src/transport/gnunet-service-transport_plugins.c:250 #: src/transport/gnunet-service-transport_plugins.c:258 #, fuzzy, c-format msgid "Missing function `%s' in transport plugin for `%s'\n" msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #: src/transport/gnunet-service-transport_plugins.c:265 #, fuzzy, c-format msgid "Did not load plugin `%s' due to missing functions\n" msgstr "Fehler beim Laden des Plugins `%s' bei %s:%d. Plugin wird entladen.\n" #: src/transport/gnunet-service-transport_validation.c:488 msgid "# address records discarded" msgstr "" #: src/transport/gnunet-service-transport_validation.c:558 #, c-format msgid "" "Not transmitting `%s' with `%s', message too big (%u bytes!). This should " "not happen.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:616 #, fuzzy msgid "# PING without HELLO messages sent" msgstr "# Klartext PING Nachrichten gesendet" #: src/transport/gnunet-service-transport_validation.c:722 msgid "# address revalidations started" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1011 #, fuzzy msgid "# PING message for different peer received" msgstr "# PING Nachrichten erstellt" #: src/transport/gnunet-service-transport_validation.c:1062 #, c-format msgid "Plugin `%s' not available, cannot confirm having this address\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1072 msgid "# failed address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1075 #, c-format msgid "Address `%s' is not one of my addresses, not confirming PING\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1083 msgid "# successful address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1095 #, c-format msgid "" "Not confirming PING from peer `%s' with address `%s' since I cannot confirm " "having this address.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1103 #, c-format msgid "Received a PING message with validation bug from `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1157 #, fuzzy, c-format msgid "Failed to create PONG signature for peer `%s'\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/transport/gnunet-service-transport_validation.c:1206 msgid "# PONGs unicast via reliable transport" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1215 msgid "# PONGs multicast to all available addresses" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1356 msgid "# PONGs dropped, no matching pending validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1371 msgid "# PONGs dropped, signature expired" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1493 #, fuzzy, c-format msgid "Validation received new %s message for peer `%s' with size %u\n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/transport/gnunet-service-transport_validation.c:1500 #, fuzzy, c-format msgid "Adding `%s' without addresses for peer `%s'\n" msgstr "Adresse des Knotens `%s' konnte nicht ermittelt werden.\n" #: src/transport/gnunet-transport.c:367 #, fuzzy, c-format msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/transport/gnunet-transport.c:375 #, fuzzy, c-format msgid "Received %llu bytes/s (%llu bytes in %s)\n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/transport/gnunet-transport.c:415 #, fuzzy, c-format msgid "Failed to connect to `%s'\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/transport/gnunet-transport.c:428 #, fuzzy, c-format msgid "Failed to resolve address for peer `%s'\n" msgstr "Fehler beim Binden an UDP Port %d.\n" #: src/transport/gnunet-transport.c:438 #, fuzzy msgid "Failed to list connections, timeout occured\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #: src/transport/gnunet-transport.c:559 #, fuzzy, c-format msgid "" "Peer `%s' %s %s\n" "\t%s%s\n" "\t%s%s\n" "\t%s%s\n" msgstr "Ich bin Peer `%s'.\n" #: src/transport/gnunet-transport.c:586 #, fuzzy, c-format msgid "Peer `%s' %s `%s' \n" msgstr "Ich bin Peer `%s'.\n" #: src/transport/gnunet-transport.c:712 msgid "No transport plugins configured, peer will never communicate\n" msgstr "" #: src/transport/gnunet-transport.c:726 #, c-format msgid "No port configured for plugin `%s', cannot test it\n" msgstr "" #: src/transport/gnunet-transport.c:789 #, fuzzy, c-format msgid "Transmitting %u bytes to %s\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/transport/gnunet-transport.c:810 #, fuzzy, c-format msgid "Successfully connected to `%s'\n" msgstr "Zugriff verweigert für `%s' bei %s:%d.\n" #: src/transport/gnunet-transport.c:834 #, c-format msgid "" "Successfully connected to `%s', starting to send benchmark data in %u Kb " "blocks\n" msgstr "" #: src/transport/gnunet-transport.c:865 #, fuzzy, c-format msgid "Successfully disconnected from `%s'\n" msgstr "Zugriff verweigert für `%s' bei %s:%d.\n" #: src/transport/gnunet-transport.c:888 #, fuzzy, c-format msgid "Disconnected from peer `%s' while benchmarking\n" msgstr "`%s' hat sich mit `%s' verbunden.\n" #: src/transport/gnunet-transport.c:950 #, fuzzy, c-format msgid "Received %u bytes from %s\n" msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #: src/transport/gnunet-transport.c:975 #, c-format msgid "Peer `%s': %s %s in state `%s' until %s\n" msgstr "" #: src/transport/gnunet-transport.c:986 #, fuzzy, c-format msgid "Peer `%s': %s %s\n" msgstr "Ich bin Peer `%s'.\n" #: src/transport/gnunet-transport.c:1197 src/transport/gnunet-transport.c:1222 #, fuzzy msgid "Failed to send connect request to transport service\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/transport/gnunet-transport.c:1266 #, c-format msgid "" "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, " "%s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1274 #, c-format msgid "" "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1293 src/transport/gnunet-transport.c:1323 #: src/transport/gnunet-transport.c:1353 src/transport/gnunet-transport.c:1376 #: src/transport/gnunet-transport.c:1419 #, fuzzy msgid "Failed to connect to transport service\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/transport/gnunet-transport.c:1302 src/transport/gnunet-transport.c:1332 #: src/transport/gnunet-transport.c:1362 #, fuzzy msgid "Failed to send request to transport service\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/transport/gnunet-transport.c:1381 msgid "Starting to receive benchmark data\n" msgstr "" #: src/transport/gnunet-transport.c:1465 #, fuzzy msgid "print information for all peers (instead of only connected peers )" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/transport/gnunet-transport.c:1468 msgid "measure how fast we are receiving data from all peers (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1471 #, fuzzy msgid "connect to a peer" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/transport/gnunet-transport.c:1474 #, fuzzy msgid "disconnect to a peer" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/transport/gnunet-transport.c:1477 #, fuzzy msgid "print information for all pending validations " msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/transport/gnunet-transport.c:1480 #, fuzzy msgid "print information for all pending validations continously" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/transport/gnunet-transport.c:1483 #, fuzzy msgid "provide information about all current connections (once)" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/transport/gnunet-transport.c:1489 #, fuzzy msgid "" "provide information about all connects and disconnect events (continuously)" msgstr "Informationen über andere GNUnet Knoten ausgeben." #: src/transport/gnunet-transport.c:1491 #, fuzzy msgid "do not resolve hostnames" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/transport/gnunet-transport.c:1493 msgid "peer identity" msgstr "" #: src/transport/gnunet-transport.c:1495 msgid "send data for benchmarking to the other peer (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1498 msgid "test transport configuration (involves external server)" msgstr "" #: src/transport/gnunet-transport.c:1507 #, fuzzy msgid "Direct access to transport service." msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/transport/plugin_transport_bluetooth.c:621 msgid "# Bluetooth ACKs sent" msgstr "" #: src/transport/plugin_transport_bluetooth.c:640 #, fuzzy msgid "# Bluetooth messages defragmented" msgstr "# defragmentierter Nachrichten" #: src/transport/plugin_transport_bluetooth.c:686 #: src/transport/plugin_transport_bluetooth.c:737 #: src/transport/plugin_transport_bluetooth.c:1942 #, fuzzy msgid "# Bluetooth sessions allocated" msgstr "# Sitzungsschlüssel akzeptiert" #: src/transport/plugin_transport_bluetooth.c:837 #, fuzzy msgid "# Bluetooth message fragments sent" msgstr "# fragmentierter Nachrichten" #: src/transport/plugin_transport_bluetooth.c:861 msgid "# Bluetooth messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_bluetooth.c:969 #: src/transport/plugin_transport_bluetooth.c:1054 #: src/transport/plugin_transport_bluetooth.c:1944 #, fuzzy msgid "# Bluetooth MAC endpoints allocated" msgstr "# Client Trace-Anfragen empfangen" #: src/transport/plugin_transport_bluetooth.c:1307 #, fuzzy msgid "# HELLO messages received via Bluetooth" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_bluetooth.c:1331 #, fuzzy msgid "# fragments received via Bluetooth" msgstr "# verworfener Nachrichten" #: src/transport/plugin_transport_bluetooth.c:1341 #, fuzzy msgid "# ACKs received via Bluetooth" msgstr "# Bytes empfangen über TCP" #: src/transport/plugin_transport_bluetooth.c:1401 #, fuzzy msgid "# Bluetooth DATA messages discarded due to CRC32 error" msgstr "# defragmentierter Nachrichten" #: src/transport/plugin_transport_bluetooth.c:1512 #, fuzzy msgid "# DATA messages received via Bluetooth" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_bluetooth.c:1547 #, fuzzy msgid "# Bluetooth DATA messages processed" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_bluetooth.c:1610 #, fuzzy msgid "# HELLO beacons sent via Bluetooth" msgstr "# Bytes gesendet über UDP" #: src/transport/plugin_transport_bluetooth.c:1723 msgid "Bluetooth address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1923 #, c-format msgid "Helper binary `%s' not SUID, cannot run bluetooth transport\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1622 #, c-format msgid "Could not initialize curl multi handle, failed to start %s plugin!\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1697 #: src/transport/plugin_transport_http_server.c:3007 #, fuzzy, c-format msgid "Shutting down plugin `%s'\n" msgstr "Teste Transport(e) %s\n" #: src/transport/plugin_transport_http_client.c:1722 #: src/transport/plugin_transport_http_server.c:3063 #, fuzzy, c-format msgid "Shutdown for plugin `%s' complete\n" msgstr "" "Upload von `%s' komplett, derzeitige durchschnittliche Geschwindigkeit " "beträgt %8.3f KB/s.\n" #: src/transport/plugin_transport_http_client.c:1750 #: src/transport/plugin_transport_http_server.c:2907 #, fuzzy, c-format msgid "Maximum number of connections is %u\n" msgstr "Maximale Anzahl an Chat Clients erreicht.\n" #: src/transport/plugin_transport_http_server.c:1402 #, c-format msgid "" "Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data " "size %u\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1663 #, c-format msgid "Accepting connection (%u of %u) from `%s'\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1671 #, c-format msgid "" "Server reached maximum number connections (%u), rejecting new connection\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1958 msgid "" "Could not create a new TLS certificate, program `gnunet-transport-" "certificate-creation' could not be started!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1982 #, c-format msgid "No usable TLS certificate found and creating one at `%s/%s' failed!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2405 #, fuzzy msgid "Require valid port number for service in configuration!\n" msgstr "In der Konfigurationsdatei wurden keine Anwendungen definiert!\n" #: src/transport/plugin_transport_http_server.c:2437 src/util/service.c:698 #, fuzzy, c-format msgid "Failed to resolve `%s': %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/transport/plugin_transport_http_server.c:2454 src/util/service.c:715 #, fuzzy, c-format msgid "Failed to find %saddress for `%s'.\n" msgstr "Fehler beim Binden an UDP Port %d.\n" #: src/transport/plugin_transport_http_server.c:2565 #, c-format msgid "Found %u addresses to report to NAT service\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2637 msgid "Disabling IPv6 since it is not supported on this system!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2730 #, c-format msgid "IPv4 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2744 #, c-format msgid "IPv6 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2751 #, fuzzy msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n" msgstr "Netzwerkbekanntmachungen wurden per Konfiguration deaktiviert!\n" #: src/transport/plugin_transport_http_server.c:2762 #, fuzzy msgid "Port is required! Fix in configuration\n" msgstr " gconfig\tGTK Konfiguration\n" #: src/transport/plugin_transport_http_server.c:2769 #, fuzzy, c-format msgid "Using port %u\n" msgstr "Teste Transport(e) %s\n" #: src/transport/plugin_transport_http_server.c:2784 #, fuzzy, c-format msgid "Specific IPv4 address `%s' in configuration file is invalid!\n" msgstr "" "Sie müssen für `%s' in der Sektion `%s' der Konfigurationsdatei eine " "positive Zahl angeben.\n" #: src/transport/plugin_transport_http_server.c:2794 #, fuzzy, c-format msgid "Binding to IPv4 address %s\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/transport/plugin_transport_http_server.c:2815 #, fuzzy, c-format msgid "Specific IPv6 address `%s' in configuration file is invalid!\n" msgstr "" "Sie müssen für `%s' in der Sektion `%s' der Konfigurationsdatei eine " "positive Zahl angeben.\n" #: src/transport/plugin_transport_http_server.c:2825 #, fuzzy, c-format msgid "Binding to IPv6 address %s\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/transport/plugin_transport_http_server.c:2877 #, fuzzy, c-format msgid "Using external hostname `%s'\n" msgstr "Collection `%s' begonnen.\n" #: src/transport/plugin_transport_http_server.c:2893 #, fuzzy, c-format msgid "Notifying transport only about hostname `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/transport/plugin_transport_smtp.c:223 #, fuzzy, c-format msgid "Received malformed message via %s. Ignored.\n" msgstr "" "Es wurde eine ungültige Nachricht per SMTP empfangen (ungültige Größe).\n" #: src/transport/plugin_transport_smtp.c:310 #, fuzzy msgid "SMTP filter string to invalid, lacks ': '\n" msgstr "SMTP Filterstring zu lang, wurde auf `%s' abgeschnitten\n" #: src/transport/plugin_transport_smtp.c:319 #, c-format msgid "SMTP filter string to long, capped to `%s'\n" msgstr "SMTP Filterstring zu lang, wurde auf `%s' abgeschnitten\n" #: src/transport/plugin_transport_smtp.c:414 #: src/transport/plugin_transport_smtp.c:424 #: src/transport/plugin_transport_smtp.c:437 #: src/transport/plugin_transport_smtp.c:456 #: src/transport/plugin_transport_smtp.c:479 #: src/transport/plugin_transport_smtp.c:487 #: src/transport/plugin_transport_smtp.c:500 #: src/transport/plugin_transport_smtp.c:511 #, fuzzy, c-format msgid "SMTP: `%s' failed: %s.\n" msgstr "`%s' schlug fehl: %s\n" #: src/transport/plugin_transport_smtp.c:652 #, fuzzy msgid "No email-address specified, can not start SMTP transport.\n" msgstr "" "Kein Filter für E-Mail angegeben, es kann keine Bekanntmachung erstellt " "werden.\n" #: src/transport/plugin_transport_smtp.c:664 #, fuzzy msgid "# bytes received via SMTP" msgstr "# Bytes empfangen über TCP" #: src/transport/plugin_transport_smtp.c:665 #, fuzzy msgid "# bytes sent via SMTP" msgstr "# Bytes gesendet über TCP" #: src/transport/plugin_transport_smtp.c:667 #, fuzzy msgid "# bytes dropped by SMTP (outgoing)" msgstr "# Bytes verworfen von TCP (ausgehend)" #: src/transport/plugin_transport_tcp.c:555 #, c-format msgid "Unexpected address length: %u bytes\n" msgstr "" #: src/transport/plugin_transport_tcp.c:762 #: src/transport/plugin_transport_tcp.c:928 #: src/transport/plugin_transport_tcp.c:2005 #: src/transport/plugin_transport_tcp.c:2558 #, fuzzy msgid "# TCP sessions active" msgstr "# Sitzungsschlüssel akzeptiert" #: src/transport/plugin_transport_tcp.c:795 #: src/transport/plugin_transport_tcp.c:921 #: src/transport/plugin_transport_tcp.c:1009 #: src/transport/plugin_transport_tcp.c:1056 #: src/transport/plugin_transport_tcp.c:1219 #: src/transport/plugin_transport_tcp.c:1237 #, fuzzy msgid "# bytes currently in TCP buffers" msgstr "# Bytes gesendet über TCP" #: src/transport/plugin_transport_tcp.c:798 #, fuzzy msgid "# bytes discarded by TCP (disconnect)" msgstr "# Bytes verworfen von TCP (ausgehend)" #: src/transport/plugin_transport_tcp.c:1012 #, fuzzy msgid "# bytes discarded by TCP (timeout)" msgstr "# Bytes verworfen von TCP (ausgehend)" #: src/transport/plugin_transport_tcp.c:1059 #, fuzzy msgid "# bytes transmitted via TCP" msgstr "# Bytes des Typs %d übertragen" #: src/transport/plugin_transport_tcp.c:1193 #, c-format msgid "Trying to send with invalid session %p\n" msgstr "" #: src/transport/plugin_transport_tcp.c:1462 msgid "# requests to create session with invalid address" msgstr "" #: src/transport/plugin_transport_tcp.c:1567 msgid "# transport-service disconnect requests for TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:2055 #, fuzzy msgid "# TCP WELCOME messages received" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_tcp.c:2215 msgid "# bytes received via TCP" msgstr "# Bytes empfangen über TCP" #: src/transport/plugin_transport_tcp.c:2279 msgid "# network-level TCP disconnect events" msgstr "" #: src/transport/plugin_transport_tcp.c:2437 src/util/service.c:582 #: src/util/service.c:588 #, c-format msgid "Require valid port number for service `%s' in configuration!\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2451 #, fuzzy msgid "Failed to start service.\n" msgstr "Fehler beim Starten der Collection.\n" #: src/transport/plugin_transport_tcp.c:2547 #, fuzzy, c-format msgid "TCP transport listening on port %llu\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/transport/plugin_transport_tcp.c:2551 msgid "TCP transport not listening on any port (client only)\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2554 #, c-format msgid "TCP transport advertises itself as being on port %llu\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:167 #, fuzzy msgid "# IPv6 multicast HELLO beacons received via udp" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_udp_broadcasting.c:210 #, fuzzy msgid "# IPv4 broadcast HELLO beacons received via udp" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_udp_broadcasting.c:603 msgid "" "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:626 #, c-format msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n" msgstr "" #: src/transport/plugin_transport_udp.c:1513 #, c-format msgid "" "Trying to create session for address of unexpected length %u (should be %u " "or %u)\n" msgstr "" #: src/transport/plugin_transport_udp.c:2602 #, c-format msgid "" "UDP could not transmit message to `%s': Network seems down, please check " "your network configuration\n" msgstr "" #: src/transport/plugin_transport_udp.c:2616 msgid "" "UDP could not transmit IPv6 message! Please check your network configuration " "and disable IPv6 if your connection does not have a global IPv6 address\n" msgstr "" #: src/transport/plugin_transport_udp.c:2961 #, fuzzy msgid "Failed to open UDP sockets\n" msgstr "Fehler beim Binden an UDP6 Port %d.\n" #: src/transport/plugin_transport_udp.c:3056 #, c-format msgid "Given `%s' option is out of range: %llu > %u\n" msgstr "" #: src/transport/plugin_transport_udp.c:3097 #, fuzzy, c-format msgid "Invalid IPv6 address: `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/transport/plugin_transport_udp.c:3168 #, fuzzy msgid "Failed to create network sockets, plugin failed\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/transport/plugin_transport_unix.c:1321 #, fuzzy, c-format msgid "Cannot create path to `%s'\n" msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #: src/transport/plugin_transport_unix.c:1652 #, fuzzy msgid "No UNIXPATH given in configuration!\n" msgstr "Fehler beim Speichern der Konfiguration!" #: src/transport/plugin_transport_unix.c:1688 #, fuzzy msgid "Failed to open UNIX listen socket\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/transport/plugin_transport_wlan.c:620 msgid "# WLAN ACKs sent" msgstr "" #: src/transport/plugin_transport_wlan.c:639 #, fuzzy msgid "# WLAN messages defragmented" msgstr "# defragmentierter Nachrichten" #: src/transport/plugin_transport_wlan.c:688 #: src/transport/plugin_transport_wlan.c:772 #: src/transport/plugin_transport_wlan.c:1948 #, fuzzy msgid "# WLAN sessions allocated" msgstr "# Sitzungsschlüssel akzeptiert" #: src/transport/plugin_transport_wlan.c:876 #, fuzzy msgid "# WLAN message fragments sent" msgstr "# fragmentierter Nachrichten" #: src/transport/plugin_transport_wlan.c:900 msgid "# WLAN messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_wlan.c:1008 #: src/transport/plugin_transport_wlan.c:1098 #: src/transport/plugin_transport_wlan.c:1950 #, fuzzy msgid "# WLAN MAC endpoints allocated" msgstr "# Client Trace-Anfragen empfangen" #: src/transport/plugin_transport_wlan.c:1302 #, fuzzy msgid "# HELLO messages received via WLAN" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_wlan.c:1326 #, fuzzy msgid "# fragments received via WLAN" msgstr "# verworfener Nachrichten" #: src/transport/plugin_transport_wlan.c:1336 #, fuzzy msgid "# ACKs received via WLAN" msgstr "# Bytes empfangen über TCP" #: src/transport/plugin_transport_wlan.c:1396 #, fuzzy msgid "# WLAN DATA messages discarded due to CRC32 error" msgstr "# defragmentierter Nachrichten" #: src/transport/plugin_transport_wlan.c:1518 #, fuzzy msgid "# DATA messages received via WLAN" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_wlan.c:1553 #, fuzzy msgid "# WLAN DATA messages processed" msgstr "# verschlüsselter PONG Nachrichten empfangen" #: src/transport/plugin_transport_wlan.c:1616 #, fuzzy msgid "# HELLO beacons sent via WLAN" msgstr "# Bytes gesendet über UDP" #: src/transport/plugin_transport_wlan.c:1729 msgid "WLAN address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_wlan.c:1929 #, c-format msgid "Helper binary `%s' not SUID, cannot run WLAN transport\n" msgstr "" #: src/transport/transport_api.c:739 #, fuzzy, c-format msgid "Received unexpected message of type %u in %s:%u\n" msgstr "Es wurde eine unbekannte Testbed Nachricht des Typs %u empfangen.\n" #: src/transport/transport-testing.c:584 #, fuzzy msgid "Failed to initialize testing library!\n" msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n" #: src/tun/regex.c:129 #, c-format msgid "Bad mask: %d\n" msgstr "" #: src/util/bio.c:170 src/util/bio.c:178 #, fuzzy, c-format msgid "Error reading `%s': %s" msgstr "Fehler beim Anlegen des Benutzers" #: src/util/bio.c:180 #, fuzzy msgid "End of file" msgstr "Eine Konfigurationsdatei laden" #: src/util/bio.c:237 #, c-format msgid "Error reading length of string `%s'" msgstr "" #: src/util/bio.c:247 #, c-format msgid "String `%s' longer than allowed (%u > %u)" msgstr "" #: src/util/bio.c:293 #, c-format msgid "Serialized metadata `%s' larger than allowed (%u>%u)" msgstr "" #: src/util/bio.c:307 #, c-format msgid "Metadata `%s' failed to deserialize" msgstr "" #: src/util/client.c:261 src/util/client.c:858 src/util/service.c:619 #, c-format msgid "UNIXPATH `%s' too long, maximum length is %llu\n" msgstr "" #: src/util/client.c:265 src/util/client.c:863 src/util/service.c:623 #, fuzzy, c-format msgid "Using `%s' instead\n" msgstr "%s: Option `%s' ist mehrdeutig\n" #: src/util/client.c:360 #, c-format msgid "" "Could not determine valid hostname and port for service `%s' from " "configuration.\n" msgstr "" #: src/util/client.c:368 #, c-format msgid "Need a non-empty hostname for service `%s'.\n" msgstr "" #: src/util/client.c:1008 #, fuzzy, c-format msgid "Could not connect to service `%s', configuration broken.\n" msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #: src/util/client.c:1020 #, fuzzy, c-format msgid "Failure to transmit request to service `%s'\n" msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #: src/util/client.c:1303 msgid "Could not submit request, not expecting to receive a response.\n" msgstr "" #: src/util/common_logging.c:254 src/util/common_logging.c:1039 msgid "DEBUG" msgstr "DEBUG" #: src/util/common_logging.c:256 src/util/common_logging.c:1037 msgid "INFO" msgstr "INFO" #: src/util/common_logging.c:258 src/util/common_logging.c:1035 msgid "WARNING" msgstr "WARNUNG" #: src/util/common_logging.c:260 src/util/common_logging.c:1033 msgid "ERROR" msgstr "FEHLER" #: src/util/common_logging.c:262 src/util/common_logging.c:1041 msgid "NONE" msgstr "" #: src/util/common_logging.c:391 #, fuzzy, c-format msgid "Failed to create or access directory for log file `%s'\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/util/common_logging.c:817 #, c-format msgid "Message `%.*s' repeated %u times in the last %s\n" msgstr "" #: src/util/common_logging.c:1042 msgid "INVALID" msgstr "" #: src/util/common_logging.c:1157 #, fuzzy msgid "unknown address" msgstr "Unbekannter Fehler" #: src/util/common_logging.c:1196 #, fuzzy msgid "invalid address" msgstr "Ungültige Parameter: " #: src/util/common_logging.c:1214 #, fuzzy, c-format msgid "Configuration fails to specify option `%s' in section `%s'!\n" msgstr "" "Die Konfigurationsdatei muss in der Sektion `%s' unter `%s' ein Verzeichnis " "angeben, in dem FS Daten gespeichert werden.\n" #: src/util/common_logging.c:1235 #, fuzzy, c-format msgid "" "Configuration specifies invalid value for option `%s' in section `%s': %s\n" msgstr "" "Die Konfigurationsdatei muss in der Sektion `%s' unter `%s' ein Verzeichnis " "angeben, in dem FS Daten gespeichert werden.\n" #: src/util/configuration.c:288 #, fuzzy, c-format msgid "Syntax error while deserializing in line %u\n" msgstr "Syntaxfehler in Konfigurationsdatei `%s' in Zeile %d.\n" #: src/util/configuration.c:996 #, c-format msgid "" "Configuration value '%s' for '%s' in section '%s' is not in set of legal " "choices\n" msgstr "" #: src/util/configuration.c:1066 #, c-format msgid "Recursive expansion suspected, aborting $-expansion for term `%s'\n" msgstr "" #: src/util/configuration.c:1098 #, fuzzy, c-format msgid "Missing closing `%s' in option `%s'\n" msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #: src/util/configuration.c:1172 #, c-format msgid "" "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined " "as an environmental variable\n" msgstr "" #: src/util/connection.c:423 #, fuzzy, c-format msgid "Access denied to `%s'\n" msgstr "Zugriff verweigert für `%s' bei %s:%d.\n" #: src/util/connection.c:438 #, c-format msgid "Accepting connection from `%s': %p\n" msgstr "" #: src/util/connection.c:553 #, fuzzy, c-format msgid "" "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n" msgstr "Fehler beim Aufbauen einer Verbindung mit gnunetd.\n" #: src/util/connection.c:751 src/util/connection.c:919 #, fuzzy, c-format msgid "Trying to connect to `%s' (%p)\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/util/connection.c:910 #, fuzzy, c-format msgid "Attempt to connect to `%s' failed\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/util/container_bloomfilter.c:531 #, c-format msgid "" "Size of file on disk is incorrect for this Bloom filter (want %llu, have " "%llu)\n" msgstr "" #: src/util/crypto_ecc.c:702 src/util/crypto_ecc.c:740 #: src/util/crypto_ecc.c:858 src/util/crypto_ecc.c:896 #, fuzzy, c-format msgid "Could not acquire lock on file `%s': %s...\n" msgstr "PID konnte nicht in Datei `%s' geschrieben werden: %s.\n" #: src/util/crypto_ecc.c:707 src/util/crypto_ecc.c:863 #, fuzzy msgid "Creating a new private key. This may take a while.\n" msgstr "Ein neuer Hostkey wird erzeugt (dies kann eine Weile dauern).\n" #: src/util/crypto_ecc.c:744 src/util/crypto_ecc.c:900 msgid "This may be ok if someone is currently generating a private key.\n" msgstr "" #: src/util/crypto_ecc.c:774 src/util/crypto_ecc.c:930 #, c-format msgid "" "When trying to read key file `%s' I found %u bytes but I need at least %u.\n" msgstr "" #: src/util/crypto_ecc.c:778 src/util/crypto_ecc.c:934 msgid "This may be ok if someone is currently generating a key.\n" msgstr "" #: src/util/crypto_ecc.c:1016 #, fuzzy msgid "Could not load peer's private key\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/util/crypto_ecc.c:1120 #, fuzzy, c-format msgid "ECC signing failed at %s:%d: %s\n" msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #: src/util/crypto_ecc.c:1170 #, fuzzy, c-format msgid "EdDSA signing failed at %s:%d: %s\n" msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #: src/util/crypto_ecc.c:1244 #, fuzzy, c-format msgid "ECDSA signature verification failed at %s:%d: %s\n" msgstr "RSA Signaturüberprüfung fehlgeschlagen bei %s:%d: %s\n" #: src/util/crypto_ecc.c:1301 #, fuzzy, c-format msgid "EdDSA signature verification failed at %s:%d: %s\n" msgstr "RSA Signaturüberprüfung fehlgeschlagen bei %s:%d: %s\n" #: src/util/crypto_random.c:284 #, c-format msgid "libgcrypt has not the expected version (version %s is required).\n" msgstr "" "libgcrypt hat nicht die erwartete Version (Version %s wird vorausgesetzt).\n" #: src/util/disk.c:1184 #, fuzzy, c-format msgid "Expected `%s' to be a directory!\n" msgstr "`%s' erwartet, dass `%s' ein Verzeichnis ist!\n" #: src/util/disk.c:1546 src/util/service.c:1318 #, fuzzy, c-format msgid "Cannot obtain information about user `%s': %s\n" msgstr "Fehler beim Speichern der Konfigurationsdatei: `%s': %s.\n" #: src/util/getopt.c:568 #, c-format msgid "%s: option `%s' is ambiguous\n" msgstr "%s: Option `%s' ist mehrdeutig\n" #: src/util/getopt.c:592 #, c-format msgid "%s: option `--%s' does not allow an argument\n" msgstr "%s: Option '--%s' erlaubt keinen Parameter\n" #: src/util/getopt.c:597 #, c-format msgid "%s: option `%c%s' does not allow an argument\n" msgstr "%s: Option '%c%s' erlaubt keinen Parameter\n" #: src/util/getopt.c:614 src/util/getopt.c:781 #, c-format msgid "%s: option `%s' requires an argument\n" msgstr "%s: Option `%s' benötigt einen Parameter\n" #: src/util/getopt.c:643 #, c-format msgid "%s: unrecognized option `--%s'\n" msgstr "%s: unbekannte Option '--%s'\n" #: src/util/getopt.c:647 #, c-format msgid "%s: unrecognized option `%c%s'\n" msgstr "%s: unbekannte Option '%c%s'\n" #: src/util/getopt.c:672 #, c-format msgid "%s: illegal option -- %c\n" msgstr "%s: unerlaubte Option -- %c\n" #: src/util/getopt.c:674 #, c-format msgid "%s: invalid option -- %c\n" msgstr "%s: ungültige Option -- %c\n" #: src/util/getopt.c:702 src/util/getopt.c:829 #, c-format msgid "%s: option requires an argument -- %c\n" msgstr "%s: Option benötigt einen Parameter -- %c\n" #: src/util/getopt.c:750 #, c-format msgid "%s: option `-W %s' is ambiguous\n" msgstr "%s: Option '-W %s' ist mehrdeutig\n" #: src/util/getopt.c:768 #, c-format msgid "%s: option `-W %s' does not allow an argument\n" msgstr "%s: Option '-W %s' erlaubt keinen Parameter\n" #: src/util/getopt.c:933 #, fuzzy, c-format msgid "Use %s to get a list of options.\n" msgstr "Verwenden Sie --help, um eine Liste der Optionen zu erhalten.\n" #: src/util/getopt_helpers.c:84 #, c-format msgid "" "Arguments mandatory for long options are also mandatory for short options.\n" msgstr "" "Parameter, die für lange Optionen zwingend sind, sind auch für kurze " "Optionen zwingend.\n" #: src/util/getopt_helpers.c:268 src/util/getopt_helpers.c:326 #, c-format msgid "You must pass a number to the `%s' option.\n" msgstr "Sie müssen für die Option `%s' zusätzlich eine Zahl angeben.\n" #: src/util/getopt_helpers.c:298 #, fuzzy, c-format msgid "You must pass relative time to the `%s' option.\n" msgstr "Sie müssen eine positive Zahl zu der Option `%s' übergeben.\n" #: src/util/gnunet-config.c:90 #, c-format msgid "--section argument is required\n" msgstr "" #: src/util/gnunet-config.c:133 #, c-format msgid "--option argument required to set value\n" msgstr "" #: src/util/gnunet-config.c:160 msgid "obtain option of value as a filename (with $-expansion)" msgstr "" #: src/util/gnunet-config.c:163 msgid "name of the section to access" msgstr "" #: src/util/gnunet-config.c:166 msgid "name of the option to access" msgstr "" #: src/util/gnunet-config.c:169 msgid "value to set" msgstr "" #: src/util/gnunet-config.c:178 #, fuzzy msgid "Manipulate GNUnet configuration files" msgstr "" "Einen Wert aus der Konfigurationsdatei auf der Standardausgabe ausgeben" #: src/util/gnunet-ecc.c:75 #, fuzzy, c-format msgid "Failed to open `%s': %s\n" msgstr "Datei wurde als `%s' gespeichert.\n" #: src/util/gnunet-ecc.c:81 #, c-format msgid "Generating %u keys, please wait" msgstr "" #: src/util/gnunet-ecc.c:97 #, fuzzy, c-format msgid "" "\n" "Failed to write to `%s': %s\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/util/gnunet-ecc.c:107 #, fuzzy, c-format msgid "" "\n" "Finished!\n" msgstr "Fertigstellen" #: src/util/gnunet-ecc.c:110 #, c-format msgid "" "\n" "Error, %u keys not generated\n" msgstr "" #: src/util/gnunet-ecc.c:199 #, fuzzy, c-format msgid "Hostkeys file `%s' not found\n" msgstr "`%s' fehlgeschlagen: Tabelle nicht gefunden!\n" #: src/util/gnunet-ecc.c:210 #, fuzzy, c-format msgid "Hostkeys file `%s' is empty\n" msgstr "Sitzungsschlüssel von Knoten `%s' konnte nicht überprüft werden.\n" #: src/util/gnunet-ecc.c:232 #, fuzzy, c-format msgid "Could not read hostkey file: %s\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/util/gnunet-ecc.c:283 msgid "No hostkey file specified on command line\n" msgstr "" #: src/util/gnunet-ecc.c:349 msgid "list keys included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:352 msgid "number of keys to list included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:355 msgid "create COUNT public-private key pairs (for testing)" msgstr "" #: src/util/gnunet-ecc.c:358 msgid "print the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:361 msgid "print the hash of the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:364 msgid "print examples of ECC operations (used for compatibility testing)" msgstr "" #: src/util/gnunet-ecc.c:375 msgid "Manipulate GNUnet private ECC key files" msgstr "" #: src/util/gnunet-resolver.c:149 msgid "perform a reverse lookup" msgstr "" #: src/util/gnunet-resolver.c:160 msgid "Use build-in GNUnet stub resolver" msgstr "" #: src/util/gnunet-scrypt.c:279 msgid "number of bits to require for the proof of work" msgstr "" #: src/util/gnunet-scrypt.c:282 msgid "file with private key, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:285 msgid "file with proof of work, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:288 msgid "time to wait between calculations" msgstr "" #: src/util/gnunet-scrypt.c:299 #, fuzzy msgid "Manipulate GNUnet proof of work files" msgstr "" "Einen Wert aus der Konfigurationsdatei auf der Standardausgabe ausgeben" #: src/util/gnunet-service-resolver.c:299 #, fuzzy, c-format msgid "Could not resolve `%s' (%s): %s\n" msgstr "`%s' konnte nicht aufgelöst werden: %s\n" #: src/util/gnunet-service-resolver.c:371 #: src/util/gnunet-service-resolver.c:412 #, c-format msgid "Could not find IP of host `%s': %s\n" msgstr "IP des Hosts `%s' konnte nicht ermittelt werden: %s\n" #: src/util/gnunet-uri.c:84 #, c-format msgid "No URI specified on command line\n" msgstr "" #: src/util/gnunet-uri.c:89 #, fuzzy, c-format msgid "Invalid URI: does not start with `%s'\n" msgstr "Ungültige Antwort auf `%s'.\n" #: src/util/gnunet-uri.c:96 #, c-format msgid "Invalid URI: fails to specify subsystem\n" msgstr "" #: src/util/gnunet-uri.c:106 #, c-format msgid "No handler known for subsystem `%s'\n" msgstr "" #: src/util/gnunet-uri.c:168 msgid "Perform default-actions for GNUnet URIs" msgstr "" #: src/util/helper.c:338 #, fuzzy, c-format msgid "Error reading from `%s': %s\n" msgstr "Fehler beim Anlegen des Benutzers" #: src/util/helper.c:383 #, fuzzy, c-format msgid "Failed to parse inbound message from helper `%s'\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/util/helper.c:609 #, fuzzy, c-format msgid "Error writing to `%s': %s\n" msgstr "Fehler beim Anlegen des Benutzers" #: src/util/network.c:134 #, c-format msgid "Unable to shorten unix path `%s' while keeping name unique\n" msgstr "" #: src/util/network.c:1355 src/util/network.c:1480 #, c-format msgid "" "Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n" msgstr "" #: src/util/os_installation.c:421 #, c-format msgid "" "Could not determine installation path for %s. Set `%s' environment " "variable.\n" msgstr "" #: src/util/os_installation.c:766 #, fuzzy, c-format msgid "Could not find binary `%s' in PATH!\n" msgstr "Knoten `%s' konnte nicht in der Routing Tabelle gefunden werden!\n" #: src/util/os_installation.c:826 #, fuzzy, c-format msgid "CreateProcess failed for binary %s (%d).\n" msgstr "`%s' fehlgeschlagen für Laufwerk %s: %u\n" #: src/util/os_installation.c:836 #, c-format msgid "GetExitCodeProcess failed for binary %s (%d).\n" msgstr "" #: src/util/plugin.c:87 #, c-format msgid "Initialization of plugin mechanism failed: %s!\n" msgstr "Initialisierung des Plugin Mechanismuses fehlgeschlagen: %s!\n" #: src/util/plugin.c:148 #, fuzzy, c-format msgid "`%s' failed to resolve method '%s' with error: %s\n" msgstr "" "`%s' konnte die Methode '%s%s' nicht auflösen. Ort: %s:%d. Fehler: %s\n" #: src/util/plugin.c:223 #, fuzzy, c-format msgid "`%s' failed for library `%s' with error: %s\n" msgstr "`%s' fehlgeschlagen für die Bibliothek `%s'. Ort: %s:%d. Fehler: %s\n" #: src/util/plugin.c:382 #, fuzzy msgid "Could not determine plugin installation path.\n" msgstr "Öffentliche IP-Adresse konnte nicht ermittelt werden.\n" #: src/util/program.c:246 src/util/service.c:1452 #, fuzzy, c-format msgid "Malformed configuration file `%s', exit ...\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/util/program.c:258 src/util/service.c:1467 #, fuzzy, c-format msgid "Could not access configuration file `%s'\n" msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #: src/util/program.c:263 src/util/service.c:1462 #, fuzzy msgid "Malformed configuration, exit ...\n" msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #: src/util/resolver_api.c:198 #, fuzzy, c-format msgid "Must specify `%s' for `%s' in configuration!\n" msgstr "Versuche, Datei `%s' für MySQL Konfiguration zu verwenden.\n" #: src/util/resolver_api.c:216 #, fuzzy, c-format msgid "" "Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n" msgstr "" "Sie müssen für `%s' in der Sektion `%s' der Konfigurationsdatei eine " "positive Zahl angeben.\n" #: src/util/resolver_api.c:348 #, fuzzy, c-format msgid "Timeout trying to resolve IP address `%s'.\n" msgstr "GNUnet verwendet nun die IP-Adresse %u.%u.%u.%u.\n" #: src/util/resolver_api.c:352 #, fuzzy, c-format msgid "Timeout trying to resolve hostname `%s'.\n" msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #: src/util/resolver_api.c:908 #, fuzzy, c-format msgid "Could not resolve our FQDN : %s\n" msgstr "`%s' konnte nicht aufgelöst werden: %s\n" #: src/util/scheduler.c:813 msgid "Looks like we're busy waiting...\n" msgstr "" #: src/util/scheduler.c:948 #, c-format msgid "Attempt to cancel dead task %llu!\n" msgstr "" #: src/util/server.c:484 #, fuzzy, c-format msgid "`%s' failed for port %d (%s).\n" msgstr "`%s' fehlgeschlagen für Laufwerk %s: %u\n" #: src/util/server.c:493 #, fuzzy, c-format msgid "`%s' failed for port %d (%s): address already in use\n" msgstr "`%s' schlug fehl für Port %d: %s. Läuft gnunetd bereits?\n" #: src/util/server.c:499 #, fuzzy, c-format msgid "`%s' failed for `%s': address already in use\n" msgstr "`%s' schlug fehl für Port %d: %s. Läuft gnunetd bereits?\n" #: src/util/server.c:892 #, c-format msgid "" "Processing code for message of type %u did not call " "`GNUNET_SERVER_receive_done' after %s\n" msgstr "" #: src/util/service.c:347 #, fuzzy, c-format msgid "Unknown address family %d\n" msgstr "Unbekannte Operation `%s'\n" #: src/util/service.c:354 #, c-format msgid "Access from `%s' denied to service `%s'\n" msgstr "" #: src/util/service.c:409 #, c-format msgid "Could not parse IPv4 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:446 #, c-format msgid "Could not parse IPv6 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:563 #, c-format msgid "" "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n" msgstr "" #: src/util/service.c:653 #, c-format msgid "" "Disabling UNIX domain socket support for service `%s', failed to create UNIX " "domain socket: %s\n" msgstr "" #: src/util/service.c:669 #, c-format msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n" msgstr "" #: src/util/service.c:903 msgid "Could not access a pre-bound socket, will try to bind myself\n" msgstr "" #: src/util/service.c:952 src/util/service.c:970 #, c-format msgid "Specified value for `%s' of service `%s' is invalid\n" msgstr "" #: src/util/service.c:995 #, c-format msgid "Could not access pre-bound socket %u, will try to bind myself\n" msgstr "" #: src/util/service.c:1165 #, fuzzy, c-format msgid "Failed to start `%s' at `%s'\n" msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #: src/util/service.c:1207 #, fuzzy, c-format msgid "Service `%s' runs at %s\n" msgstr "Knoten `%s' mit Vertrauen %8u und Adresse `%s'\n" #: src/util/service.c:1256 msgid "Service process failed to initialize\n" msgstr "" #: src/util/service.c:1260 msgid "Service process could not initialize server function\n" msgstr "" #: src/util/service.c:1264 msgid "Service process failed to report status\n" msgstr "" #: src/util/service.c:1319 msgid "No such user" msgstr "" #: src/util/service.c:1332 #, c-format msgid "Cannot change user/group to `%s': %s\n" msgstr "Benutzer/Gruppe kann nicht zu `%s' gewechselt werden: %s\n" #: src/util/service.c:1402 msgid "do daemonize (detach from terminal)" msgstr "" #: src/util/signal.c:89 #, fuzzy, c-format msgid "signal (%d, %p) returned %d.\n" msgstr "Aufruf von `%s' gibt %d zurück.\n" #: src/util/strings.c:145 msgid "b" msgstr "b" #: src/util/strings.c:433 #, c-format msgid "Character sets requested were `%s'->`%s'\n" msgstr "" #: src/util/strings.c:561 msgid "Failed to expand `$HOME': environment variable `HOME' not set" msgstr "" #: src/util/strings.c:658 msgid "µs" msgstr "" #: src/util/strings.c:662 msgid "forever" msgstr "" #: src/util/strings.c:664 msgid "0 ms" msgstr "" #: src/util/strings.c:670 msgid "ms" msgstr "ms" #: src/util/strings.c:676 msgid "s" msgstr "s" #: src/util/strings.c:682 msgid "m" msgstr "m" #: src/util/strings.c:688 msgid "h" msgstr "h" #: src/util/strings.c:695 #, fuzzy msgid "day" msgstr " Tage" #: src/util/strings.c:697 #, fuzzy msgid "days" msgstr " Tage" #: src/util/strings.c:726 msgid "end of time" msgstr "" #: src/util/strings.c:1159 msgid "IPv6 address did not start with `['\n" msgstr "" #: src/util/strings.c:1167 msgid "IPv6 address did contain ':' to separate port number\n" msgstr "" #: src/util/strings.c:1173 msgid "IPv6 address did contain ']' before ':' to separate port number\n" msgstr "" #: src/util/strings.c:1180 msgid "IPv6 address did contain a valid port number after the last ':'\n" msgstr "" #: src/util/strings.c:1189 #, fuzzy, c-format msgid "Invalid IPv6 address `%s': %s\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/util/strings.c:1395 src/util/strings.c:1411 msgid "Port not in range\n" msgstr "" #: src/util/strings.c:1420 #, fuzzy, c-format msgid "Malformed port policy `%s'\n" msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #: src/util/strings.c:1503 src/util/strings.c:1534 src/util/strings.c:1582 #: src/util/strings.c:1603 #, c-format msgid "Invalid format for IP: `%s'\n" msgstr "Ungültiges Format für IP: `%s'\n" #: src/util/strings.c:1560 #, c-format msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)." msgstr "Ungültige Netzwerk Notation ('/%d ist nicht gültig in IPv4 CIDR)." #: src/util/strings.c:1612 #, fuzzy, c-format msgid "Invalid format: `%s'\n" msgstr "Ungültiger Parameter: `%s'\n" #: src/util/strings.c:1664 #, c-format msgid "Invalid network notation (does not end with ';': `%s')\n" msgstr "Ungültige Netzwerk Notation (endet nicht mit ';': `%s')\n" #: src/util/strings.c:1714 #, fuzzy, c-format msgid "Wrong format `%s' for netmask\n" msgstr "Falsches Format `%s' für Netzmaske: %s\n" #: src/util/strings.c:1745 #, fuzzy, c-format msgid "Wrong format `%s' for network\n" msgstr "Falsches Format `%s' für Netzwerk: %s\n" #: src/vpn/gnunet-service-vpn.c:550 src/vpn/gnunet-service-vpn.c:1086 #, fuzzy msgid "# Active channels" msgstr "GNUnet Konfiguration" #: src/vpn/gnunet-service-vpn.c:642 #, fuzzy msgid "# Bytes given to mesh for transmission" msgstr "# PING Nachrichten erstellt" #: src/vpn/gnunet-service-vpn.c:680 #, fuzzy msgid "# Bytes dropped in mesh queue (overflow)" msgstr "# Bytes verworfen von UDP (outgoing)" #: src/vpn/gnunet-service-vpn.c:753 #, fuzzy msgid "# Mesh channels created" msgstr "# dht Anfragen weitergeleitet" #: src/vpn/gnunet-service-vpn.c:784 #, fuzzy msgid "Failed to setup mesh channel!\n" msgstr "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #: src/vpn/gnunet-service-vpn.c:978 #, c-format msgid "Protocol %u not supported, dropping\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1305 msgid "# ICMPv4 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1326 msgid "# ICMPv6 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1531 #, fuzzy msgid "# Packets received from TUN interface" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/vpn/gnunet-service-vpn.c:1564 src/vpn/gnunet-service-vpn.c:1600 #, c-format msgid "Packet received for unmapped destination `%s' (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1610 msgid "Received IPv4 packet with options (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1624 #, c-format msgid "Received packet of unknown protocol %d from TUN (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1706 #, fuzzy msgid "# ICMP packets received from mesh" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/vpn/gnunet-service-vpn.c:2045 #, fuzzy msgid "# UDP packets received from mesh" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/vpn/gnunet-service-vpn.c:2200 #, fuzzy msgid "# TCP packets received from mesh" msgstr "Empfangene Client-Nachricht ist ungültig.\n" #: src/vpn/gnunet-service-vpn.c:2351 msgid "Failed to find unallocated IPv4 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2406 #, fuzzy msgid "Failed to find unallocated IPv6 address in VPN's range\n" msgstr "Die öffentliche IPv6-Adresse konnte nicht ermittelt werden!\n" #: src/vpn/gnunet-service-vpn.c:2447 src/vpn/gnunet-service-vpn.c:2663 #, fuzzy msgid "# Active destinations" msgstr "GNUnet Konfiguration" #: src/vpn/gnunet-service-vpn.c:2715 msgid "Failed to allocate IP address for new destination\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2982 #, fuzzy msgid "Must specify valid IPv6 address" msgstr "`%s' ist nicht verfügbar." #: src/vpn/gnunet-service-vpn.c:3006 msgid "Must specify valid IPv6 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3014 msgid "IPv6 support disabled as this system does not support IPv6\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:3027 #, fuzzy msgid "Must specify valid IPv4 address" msgstr "`%s' ist nicht verfügbar." #: src/vpn/gnunet-service-vpn.c:3040 msgid "Must specify valid IPv4 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3050 msgid "IPv4 support disabled as this system does not support IPv4\n" msgstr "" #: src/vpn/gnunet-vpn.c:147 #, fuzzy msgid "Error creating tunnel\n" msgstr "Hostkey wurde erfolgreich erzeugt.\n" #: src/vpn/gnunet-vpn.c:190 src/vpn/gnunet-vpn.c:221 #, fuzzy, c-format msgid "Option `%s' makes no sense with option `%s'.\n" msgstr "Option `%s' macht keinen Sinn ohne die Option `%s'.\n" #: src/vpn/gnunet-vpn.c:203 #, fuzzy, c-format msgid "Option `%s' or `%s' is required.\n" msgstr "%s: Option `%s' ist mehrdeutig\n" #: src/vpn/gnunet-vpn.c:215 #, fuzzy, c-format msgid "Option `%s' or `%s' is required when using option `%s'.\n" msgstr "Option `%s' macht keinen Sinn ohne die Option `%s'.\n" #: src/vpn/gnunet-vpn.c:235 #, fuzzy, c-format msgid "`%s' is not a valid peer identifier.\n" msgstr "`%s' ist nicht verfügbar." #: src/vpn/gnunet-vpn.c:255 #, fuzzy, c-format msgid "`%s' is not a valid IP address.\n" msgstr "`%s' ist nicht verfügbar." #: src/vpn/gnunet-vpn.c:290 msgid "request that result should be an IPv4 address" msgstr "" #: src/vpn/gnunet-vpn.c:293 msgid "request that result should be an IPv6 address" msgstr "" #: src/vpn/gnunet-vpn.c:296 msgid "how long should the mapping be valid for new tunnels?" msgstr "" #: src/vpn/gnunet-vpn.c:299 msgid "destination IP for the tunnel" msgstr "" #: src/vpn/gnunet-vpn.c:302 msgid "peer offering the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:305 msgid "name of the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:308 #, fuzzy msgid "service is offered via TCP" msgstr "# Bytes empfangen über TCP" #: src/vpn/gnunet-vpn.c:311 #, fuzzy msgid "service is offered via UDP" msgstr "# Bytes empfangen über UDP" #: src/vpn/gnunet-vpn.c:323 msgid "Setup tunnels via VPN." msgstr "" #: src/include/gnunet_common.h:566 src/include/gnunet_common.h:573 #: src/include/gnunet_common.h:581 #, fuzzy, c-format msgid "Assertion failed at %s:%d.\n" msgstr "Absicherung fehlgeschlagen bei %s:%d.\n" #: src/include/gnunet_common.h:593 #, fuzzy, c-format msgid "External protocol violation detected at %s:%d.\n" msgstr "Absicherung fehlgeschlagen bei %s:%d.\n" #: src/include/gnunet_common.h:620 src/include/gnunet_common.h:629 #, fuzzy, c-format msgid "`%s' failed on file `%s' at %s:%d with error: %s\n" msgstr "`%s' schlug bei Datei `%s' fehl. Ort: %s:%d. Fehler: %s\n" #, fuzzy #~ msgid "# TRAIL SETUP requests received" #~ msgstr "# Client Trace-Anfragen empfangen" #, fuzzy #~ msgid "# TRAIL SETUP bytes received" #~ msgstr "# Client Trace-Anfragen empfangen" #, fuzzy #~ msgid "provide information about a particular channel" #~ msgstr "Informationen über andere GNUnet Knoten ausgeben." #, fuzzy #~ msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED" #~ msgstr "Informationen über andere GNUnet Knoten ausgeben." #, fuzzy #~ msgid "Could not find option `%s:%s' in configuration.\n" #~ msgstr "Knoten `%s' konnte nicht in der Routing Tabelle gefunden werden!\n" #, fuzzy #~ msgid "Peer `%s' disconnected\n" #~ msgstr "# verbundener Knoten" #, fuzzy #~ msgid "Transport plugin: `%s' port %llu\n" #~ msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #, fuzzy #~ msgid "Found %u transport plugins: `%s'\n" #~ msgstr "Teste Transport(e) %s\n" #, fuzzy #~ msgid "Failed to parse HELLO in file `%s': %s %u \n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "Internal error %d\n" #~ msgstr "Unbekannter Fehler.\n" #, fuzzy #~ msgid "Aborting call to `%s'\n" #~ msgstr "Fehler beim Anlegen des Benutzers" #, fuzzy #~ msgid "You are already in a conversation with `%s'.\n" #~ msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #, fuzzy #~ msgid "Print information about mesh tunnels and peers." #~ msgstr "Informationen über andere GNUnet Knoten ausgeben." #, fuzzy #~ msgid "" #~ "%s service is lacking key configuration settings (%s). Using default " #~ "(%u).\n" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "Loading block plugin `%s'\n" #~ msgstr "Teste Transport(e) %s\n" #, fuzzy #~ msgid "Invalid value `%s'\n" #~ msgstr "Ungültiger Parameter: `%s'\n" #, fuzzy #~ msgid "Found issuer for public key `%s'\n" #~ msgstr "Teste Transport(e) %s\n" #, fuzzy #~ msgid "No issuer for public key `%s'\n" #~ msgstr "Dienst `%s' konnte nicht ordentlich entladen werden!\n" #, fuzzy #~ msgid "Invalid work requirement for NSE service. Exiting.\n" #~ msgstr "Ungültige Parameter. Abbruch.\n" #, fuzzy #~ msgid "Failed to get slave counters!\n" #~ msgstr "" #~ "Statistiken über den Netzwerkverkehr konnten nicht ermittelt werden.\n" #, fuzzy #~ msgid "Could not translate remote public key to sexpression!\n" #~ msgstr "Die öffentliche IPv6-Adresse konnte nicht ermittelt werden.\n" #, fuzzy #~ msgid "" #~ "Could not translate E[a%d] to MPI!\n" #~ "%s/%s\n" #~ msgstr "" #~ "Es konnte keine IP für das Gerät `%s' unter Verwendung von `%s' ermittelt " #~ "werden.\n" #, fuzzy #~ msgid "Job command file not given. Exiting\n" #~ msgstr "Konfigurationsdatei FILENAME verwenden" #, fuzzy #~ msgid "Error while decoding key %u\n" #~ msgstr "Fehler beim Download: %s\n" #, fuzzy #~ msgid "Could not read friends list `%s'\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "Failed to read friends list from `%s': out of memory\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #~ msgid "Failed to read friends list from `%s'\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "" #~ "Syntax error in topology specification at offset %llu, skipping bytes.\n" #~ msgstr "Syntaxfehler in Topolgieangabe, Bytes werden übersprungen.\n" #, fuzzy #~ msgid "" #~ "Syntax error in topology specification at offset %llu, skipping bytes `" #~ "%s'.\n" #~ msgstr "Syntaxfehler in Topologieangabe, überspringe Bytes `%s'.\n" #, fuzzy #~ msgid "ECC signature verification failed at %s:%d: %s\n" #~ msgstr "RSA Signaturüberprüfung fehlgeschlagen bei %s:%d: %s\n" #, fuzzy #~ msgid "No `%s' specified for service `%s' in configuration.\n" #~ msgstr "In der Konfigurationsdatei wurden keine Anwendungen definiert!\n" #, fuzzy #~ msgid "# peers connected to mesh tunnels" #~ msgstr "# verbundener Knoten" #, fuzzy #~ msgid "Failed to parse metadata about pseudonym from file `%s': %s\n" #~ msgstr "Fehler beim Parsen der Gerätedaten von `%s' bei %s:%d.\n" #, fuzzy #~ msgid "no-name" #~ msgstr "Name anzeigen" #, fuzzy #~ msgid "Option `%s' ignored\n" #~ msgstr "%s: Option `%s' ist mehrdeutig\n" #, fuzzy #~ msgid "" #~ "add an additional keyword for the advertisment (this option can be " #~ "specified multiple times)" #~ msgstr "" #~ "Ein zusätzliches Schlüsselwort für alle Dateien und Verzeichnisse " #~ "hinzufügen (diese Option kann mehrmals angegeben werden)" #, fuzzy #~ msgid "specify ID of the root of the namespace" #~ msgstr "das Rating eines Namespaces setzen" #, fuzzy #~ msgid "change rating of namespace ID by VALUE" #~ msgstr "das Rating eines Namespaces setzen" #, fuzzy #~ msgid "try to shorten a given name" #~ msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #, fuzzy #~ msgid "Failed to read or create private zone key\n" #~ msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n" #, fuzzy #~ msgid "Unable to initialize resolver!\n" #~ msgstr "SQLite Datenbank konnte nicht initialisiert werden: %s.\n" #, fuzzy #~ msgid "Using default zone file `%s'\n" #~ msgstr "Collection `%s' begonnen.\n" #, fuzzy #~ msgid "Failed to write zone key to file `%s': %s\n" #~ msgstr "Datei wurde als `%s' gespeichert.\n" #, fuzzy #~ msgid "No directory to load zonefiles specified in configuration\n" #~ msgstr "In der Konfigurationsdatei wurden keine Anwendungen definiert!\n" #, fuzzy #~ msgid "name of the template configuration file to use (optional)" #~ msgstr "" #~ "Einen Wert aus der Konfigurationsdatei auf der Standardausgabe ausgeben" #, fuzzy #~ msgid "number of peers to start" #~ msgstr "Anzahl an Durchläufen" #, fuzzy #~ msgid "Failed to read or generate private key: %s\n" #~ msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n" #, fuzzy #~ msgid "Transport service is unable to access hostkey. Exiting.\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "Failed to create or read private key for namespace `%s'\n" #~ msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n" #, fuzzy #~ msgid "Failed to read namespace private key file `%s', deleting it!\n" #~ msgstr "" #~ "Der Eintrag konnte dem Namespace `%s' nicht hinzugefügt werden (existiert " #~ "er?)\n" #, fuzzy #~ msgid "print names of local namespaces" #~ msgstr "das Rating eines Namespaces setzen" #, fuzzy #~ msgid "Failed to create namespace `%s' (illegal filename?)\n" #~ msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #, fuzzy #~ msgid "# Replies received from STREAM" #~ msgstr "# Bytes empfangen über HTTP" #, fuzzy #~ msgid "Mesh service could not access hostkey: %s. Exiting.\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "No valid expiration time for operation `%s'\n" #~ msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #, fuzzy #~ msgid "Failed to find record to remove\n" #~ msgstr "Verbindung zu gnunetd konnte nicht hergestellt werden.\n" #, fuzzy #~ msgid "Could not parse zone key file `%s'\n" #~ msgstr "Konfigurationsdatei `%s' konnte nicht geparst werden.\n" #, fuzzy #~ msgid "Failed to create new signature" #~ msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #, fuzzy #~ msgid "Failed to put new set of records in database" #~ msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #, fuzzy #~ msgid "Failed to remove records from database" #~ msgstr "" #~ "\n" #~ "Fehler beim Empfangen der Antwort von gnunetd.\n" #, fuzzy #~ msgid "Failed to access database" #~ msgstr "Datei wurde als `%s' gespeichert.\n" #, fuzzy #~ msgid "unknown internal error in namestore" #~ msgstr "=\tFehler beim Lesen des Verzeichnisses.\n" #, fuzzy #~ msgid "NSE service could not access hostkey: %s\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "" #~ "Error loading search strings.Given file does not contain enough strings. " #~ "Exiting.\n" #~ msgstr "Fehler beim Verlassen der DHT.\n" #, fuzzy #~ msgid "Transport service could not access hostkey: %s. Exiting.\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (too long, %llu bytes). " #~ "Deleting it.\n" #~ msgstr "Die Datei `%s' enthält kein Pseudonym.\n" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (failed decode, %llu " #~ "bytes). Deleting it.\n" #~ msgstr "Die Datei `%s' enthält kein Pseudonym.\n" #, fuzzy #~ msgid "File `%s' does not contain a valid private key. Deleting it.\n" #~ msgstr "Die Datei `%s' enthält kein Pseudonym.\n" #, fuzzy #~ msgid "gnunet-ecc failed" #~ msgstr "gnunet-update ausführen" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (too long, %llu bytes). " #~ "Renaming it.\n" #~ msgstr "Die Datei `%s' enthält kein Pseudonym.\n" #, fuzzy #~ msgid "gnunet-rsa failed" #~ msgstr "gnunet-update ausführen" #~ msgid "RSA signature verification failed at %s:%d: %s\n" #~ msgstr "RSA Signaturüberprüfung fehlgeschlagen bei %s:%d: %s\n" #, fuzzy #~ msgid "`%s' failed for drive `%S': %u\n" #~ msgstr "`%s' fehlgeschlagen für Laufwerk %s: %u\n" #, fuzzy #~ msgid "Failed to transmit shutdown request to client.\n" #~ msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #, fuzzy #~ msgid "Service `%s' was already running.\n" #~ msgstr "Diese Suche läuft bereits!\n" #, fuzzy #~ msgid "Service `%s' has been started.\n" #~ msgstr "Dienst gelöscht.\n" #, fuzzy #~ msgid "Service `%s' was already being stopped.\n" #~ msgstr "Dienst gelöscht.\n" #, fuzzy #~ msgid "Service `%s' was already not running.\n" #~ msgstr "Diese Suche läuft bereits!\n" #, fuzzy #~ msgid "Error communicating with ARM service.\n" #~ msgstr "Informationen über andere GNUnet Knoten ausgeben." #, fuzzy #~ msgid "Timeout communicating with ARM service.\n" #~ msgstr "Informationen über andere GNUnet Knoten ausgeben." #, fuzzy #~ msgid "Error in communication with PEERINFO service\n" #~ msgstr "Informationen über andere GNUnet Knoten ausgeben." #, fuzzy #~ msgid "%s Received message from %s of type %d, distance %u!\n" #~ msgstr "Beschädigte Nachricht von Knoten `%s' in %s:%d empfangen.\n" #, fuzzy #~ msgid "Creating a peer failed. Error: %s\n" #~ msgstr "" #~ "\n" #~ "Fehler beim Uploaden der Datei: %s\n" #, fuzzy #~ msgid "Exiting\n" #~ msgstr "" #~ "\n" #~ "Abbruch.\n" #, fuzzy #~ msgid "Could not read blacklist file `%s'\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "Failed to read blacklist from `%s'\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "Syntax error in blacklist file at offset %llu, giving up!\n" #~ msgstr "Syntaxfehler in Konfigurationsdatei `%s' in Zeile %d.\n" #, fuzzy #~ msgid "Syntax error in blacklist file at offset %llu, skipping bytes.\n" #~ msgstr "Syntaxfehler in Topolgieangabe, Bytes werden übersprungen.\n" #, fuzzy #~ msgid "Failed to read hostkey: %s\n" #~ msgstr "Fehler beim Starten der Collection.\n" #, fuzzy #~ msgid "# session keys received" #~ msgstr "# Sitzungsschlüssel abgelehnt" #, fuzzy #~ msgid "`%s' is for `%s', not for me. Ignoring.\n" #~ msgstr "Größe der `%s' Nachricht ist zu kurz. Nachricht wird ignoriert.\n" #, fuzzy #~ msgid "# SET_KEY and PING messages created" #~ msgstr "# PING Nachrichten erstellt" #, fuzzy #~ msgid "Message received far too old (%s). Content ignored.\n" #~ msgstr "Empfangene Client-Nachricht ist ungültig.\n" #, fuzzy #~ msgid "Unknown error" #~ msgstr "Unbekannter Fehler" #, fuzzy #~ msgid "Failed to serialize meta data" #~ msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n" #, fuzzy #~ msgid "Failed to connect to datastore service" #~ msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #, fuzzy #~ msgid "Failed to parse URI `%s' from KBlock!\n" #~ msgstr "Datei `%s' hat URI: %s\n" #, fuzzy #~ msgid "Regexprofiler could not access hostkey: %s. Exiting.\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "Could not access STATISTICS service. Exiting.\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "Failed to open named pipe `%s' for reading: %s\n" #~ msgstr "Datei wurde als `%s' gespeichert.\n" #, fuzzy #~ msgid "Failed to open named pipe `%s' for writing: %s\n" #~ msgstr "Datei wurde als `%s' gespeichert.\n" #, fuzzy #~ msgid "session identifier" #~ msgstr "# Sitzungen aufgebaut" #, fuzzy #~ msgid "Mesh service could not access hostkey. Exiting.\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "" #~ "provide inthe 'struct GNUNET_TRANSPORT_PeerIterateContextformation about " #~ "all tunnels (continuously)" #~ msgstr "Informationen über andere GNUnet Knoten ausgeben." #, fuzzy #~ msgid "Error receiving response to `%s' request from ARM for service `%s'\n" #~ msgstr "Beschädigte Antwort auf `%s' von Knoten `%s' empfangen.\n" #, fuzzy #~ msgid "Asked to start service `%s' within %llu ms\n" #~ msgstr "`%s': Nachricht wurde nicht innerhalb %llu ms empfangen.\n" #, fuzzy #~ msgid "Stopping service `%s' within %llu ms\n" #~ msgstr "Keine Antwort innerhalb %llums erhalten.\n" #, fuzzy #~ msgid "Fatal configuration error: `%s' option in section `%s' missing.\n" #~ msgstr "" #~ "Es muss eine Liste von Freunden in der Konfigurationsdatei unter `%s' in " #~ "der Sektion `%s' angegeben werden.\n" #, fuzzy #~ msgid "Configuration file `%s' for service `%s' not valid: %s\n" #~ msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #, fuzzy #~ msgid "Could not transmit confirmation receipt\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "Unknown message type: '%u'\n" #~ msgstr "Unbekannte Operation `%s'\n" #, fuzzy #~ msgid "Configuration option `%s' in section `%s' missing\n" #~ msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #, fuzzy #~ msgid "Failed to access chat home directory `%s'\n" #~ msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #, fuzzy #~ msgid "Failed to create/open key in file `%s'\n" #~ msgstr "Datei wurde als `%s' gespeichert.\n" #, fuzzy #~ msgid "Could not serialize metadata\n" #~ msgstr "Konnte libgnunetutil nicht initialisieren!\n" #, fuzzy #~ msgid "(%s) `%s' said: %s\n" #~ msgstr "`%s' %s schlug fehl: %s\n" #, fuzzy #~ msgid "(%s) `%s' said to you: %s\n" #~ msgstr "`%s' %s schlug fehl: %s\n" #, fuzzy #~ msgid "(%s) `%s' said for sure: %s\n" #~ msgstr "`%s' fehlgeschlagen für Laufwerk %s: %u\n" #, fuzzy #~ msgid "(%s) `%s' said to you for sure: %s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you received: %s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you and only you received: %s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "(%s) `%s' was confirmed that you received from him or her: %s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "" #~ "(%s) `%s' was confirmed that you and only you received from him or her: " #~ "%s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "(%s) `%s' said off the record: %s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "`%s' left the room\n" #~ msgstr "Fehler beim Binden an UDP Port %d.\n" #, fuzzy #~ msgid "Could not change username\n" #~ msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #, fuzzy #~ msgid "Joining room `%s' as user `%s'...\n" #~ msgstr "Ungültige Antwort auf `%s' von Knoten `%s' empfangen.\n" #, fuzzy #~ msgid "Changed username to `%s'\n" #~ msgstr "Benutzer/Gruppe kann nicht zu `%s' gewechselt werden: %s\n" #, fuzzy #~ msgid "Failed to join room `%s'\n" #~ msgstr "Fehler beim Binden an UDP Port %d.\n" #, fuzzy #~ msgid "Failed to queue a message notification\n" #~ msgstr "Fehler beim Speichern der Konfiguration!" #, fuzzy #~ msgid "Failed to queue a join notification\n" #~ msgstr "Fehler beim Abfragen der Netzwerkverkehrsbedingungen von gnunetd.\n" #, fuzzy #~ msgid "Failed to queue a confirmation receipt\n" #~ msgstr "Fehler beim Speichern der Konfiguration!" #, fuzzy #~ msgid "Failed to queue a leave notification\n" #~ msgstr "Fehler beim Speichern der Konfiguration!" #, fuzzy #~ msgid "Connected to %s service!\n" #~ msgstr "`%s' hat sich mit `%s' verbunden.\n" #, fuzzy #~ msgid "Configuration fails to specify `%s' in section `%s'\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss in der Sektion `%s' unter `%s' ein " #~ "Verzeichnis angeben, in dem FS Daten gespeichert werden.\n" #, fuzzy #~ msgid "Configuration fails to specify `%s', assuming default value." #~ msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #, fuzzy #~ msgid "Key file `%s' for private zone does not exist!\n" #~ msgstr "Anzahl an Nachrichten, die pro Durchlauf verwendet wird" #, fuzzy #~ msgid "Option `%s' not specified in configuration section `%s'\n" #~ msgstr "" #~ "Option `%s' ist in der Konfigurationsdatei in der Sektion `%s' nicht " #~ "gesetzt, sie wird auf %dm gesetzt.\n" #, fuzzy #~ msgid "Peer is lacking HOSTKEY configuration setting.\n" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "`scp' did not complete cleanly.\n" #~ msgstr "`%s' ist zu keinem Knoten verbunden.\n" #, fuzzy #~ msgid "Failed to create pipe for `gnunet-peerinfo' process.\n" #~ msgstr "Fehler beim Starten der Collection.\n" #, fuzzy #~ msgid "Could not start `%s' process to create hostkey.\n" #~ msgstr "" #~ "IP(v4) dieses Hosts konnte nicht ermittelt werden. Bitte geben Sie die IP " #~ "in der Konfigurationsdatei an.\n" #, fuzzy #~ msgid "Failed to start `ssh' process.\n" #~ msgstr "Fehler beim Starten der Collection.\n" #, fuzzy #~ msgid "Error reading from gnunet-peerinfo: %s\n" #~ msgstr "Fehler beim Lesen von Informationen von gnunetd.\n" #, fuzzy #~ msgid "Malformed output from gnunet-peerinfo!\n" #~ msgstr "Fehler beim Lesen von Informationen von gnunetd.\n" #, fuzzy #~ msgid "Could not start `%s' process to start GNUnet.\n" #~ msgstr "" #~ "IP(v4) dieses Hosts konnte nicht ermittelt werden. Bitte geben Sie die IP " #~ "in der Konfigurationsdatei an.\n" #, fuzzy #~ msgid "Failed to start `gnunet-arm' process.\n" #~ msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #, fuzzy #~ msgid "shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n" #~ msgstr "`%s' ist zu keinem Knoten verbunden.\n" #, fuzzy #~ msgid "Could not start `%s' process to copy configuration directory.\n" #~ msgstr "" #~ "IP(v4) dieses Hosts konnte nicht ermittelt werden. Bitte geben Sie die IP " #~ "in der Konfigurationsdatei an.\n" #, fuzzy #~ msgid "Terminating peer `%4s'\n" #~ msgstr "Zugriff verweigert für `%s' bei %s:%d.\n" #, fuzzy #~ msgid "Setting d->dead on peer `%4s'\n" #~ msgstr "Collection `%s' begonnen.\n" #, fuzzy #~ msgid "Failed to write new configuration to disk." #~ msgstr "Fehler beim Speichern der Konfiguration!" #, fuzzy #~ msgid "Could not start `%s' process to copy configuration file.\n" #~ msgstr "" #~ "IP(v4) dieses Hosts konnte nicht ermittelt werden. Bitte geben Sie die IP " #~ "in der Konfigurationsdatei an.\n" #, fuzzy #~ msgid "Failed to copy new configuration to remote machine." #~ msgstr "Fehler beim Speichern der Konfiguration!" #, fuzzy #~ msgid "Peers failed to connect" #~ msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden." #, fuzzy #~ msgid "Failed to connect to core service of first peer!\n" #~ msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #, fuzzy #~ msgid "Invalid value `%s' for option `%s' in section `%s': expected float\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss in der Sektion `%s' unter `%s' ein " #~ "Verzeichnis angeben, in dem FS Daten gespeichert werden.\n" #, fuzzy #~ msgid "" #~ "No `%s' specified in peer configuration in section `%s', cannot copy " #~ "friends file!\n" #~ msgstr "" #~ "Option `%s' ist in der Konfigurationsdatei in der Sektion `%s' nicht " #~ "gesetzt, sie wird auf %dm gesetzt.\n" #, fuzzy #~ msgid "Unknown topology specification, can't connect peers!\n" #~ msgstr "Syntaxfehler in Topolgieangabe, Bytes werden übersprungen.\n" #, fuzzy #~ msgid "Could not create configuration for peer number %u on `%s'!\n" #~ msgstr "Auf die Namespace Informationen konnte nicht zugegriffen werden.\n" #, fuzzy #~ msgid "Failed to find option %s in section %s!\n" #~ msgstr "Fehler beim Binden an UDP Port %d.\n" #, fuzzy #~ msgid "Invalid configuration option `%s' in section `%s'\n" #~ msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #, fuzzy #~ msgid "Missing configuration option `%s' in section `%s'\n" #~ msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #, fuzzy #~ msgid "I am host `%s'. Read private key from `%s'.\n" #~ msgstr "Aufruf von `%s' mit Schlüssel `%s'.\n" #, fuzzy #~ msgid "internal error" #~ msgstr "Unbekannter Fehler.\n" #, fuzzy #~ msgid "Got %u bytes from helper `%s'\n" #~ msgstr "GAP hat ungültige Inhalte von `%s' empfangen.\n" #, fuzzy #~ msgid "Could not create namespace `%s'\n" #~ msgstr "Namespace `%s' konnte nicht erstellt werden (existiert bereits?).\n" #, fuzzy #~ msgid "Stored zonekey for zone `%s' in file `%s'\n" #~ msgstr "Datei wurde als `%s' gespeichert.\n" #, fuzzy #~ msgid "Namestore removed record successfully" #~ msgstr "Der GNUnet Dienst wurde erfolgreich installiert.\n" #, fuzzy #~ msgid "Could not read hostkeys file, specify hostkey file with -H!\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "access (%s, X_OK) failed: %s\n" #~ msgstr "`%s' schlug fehl: %s\n" #, fuzzy #~ msgid "# Peers connected" #~ msgstr "# verbundener Knoten" #, fuzzy #~ msgid "%s failed for `%s' at %s:%d: `%s'\n" #~ msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #, fuzzy #~ msgid "Failed to transmit shutdown ACK.\n" #~ msgstr "Fehler beim Starten der Collection.\n" #, fuzzy #~ msgid "Unable to initialize Postgres with configuration `%s': %s" #~ msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #, fuzzy #~ msgid "Target is %d connections per peer." #~ msgstr "Fehler beim Aufbauen einer Verbindung mit gnunetd.\n" #, fuzzy #~ msgid "Copying file with RENAME (%s,%s)\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "Copying file with command scp %s %s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "Finished copying all blacklist files!\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "Failed during blacklist file copying!\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "# bytes payload received for other peers" #~ msgstr "# Bytes des Typs %d empfangen" #, fuzzy #~ msgid "# peers disconnected due to timeout" #~ msgstr "# geschlossener Verbindungen (HANGUP gesendet)" #, fuzzy #~ msgid "# peers disconnected due to global disconnect" #~ msgstr "# Knotenankündigungen empfangen" #, fuzzy #~ msgid "# messages not sent (no such peer or not connected)" #~ msgstr "# defragmentierter Nachrichten" #, fuzzy #~ msgid "# unexpected CONNECT_ACK messages" #~ msgstr "COUNT Nachrichten versenden" #, fuzzy #~ msgid "# wlan session created" #~ msgstr "# Sitzungsschlüssel akzeptiert" #, fuzzy #~ msgid "# wlan pending fragments" #~ msgstr "# verworfener Nachrichten" #, fuzzy #~ msgid "# wlan fragments send" #~ msgstr "# verworfener Nachrichten" #, fuzzy #~ msgid "# wlan whole messages received" #~ msgstr "# verschlüsselter PING Nachrichten empfangen" #, fuzzy #~ msgid "# wlan hello messages received" #~ msgstr "# verschlüsselter PING Nachrichten empfangen" #, fuzzy #~ msgid "# wlan fragments received" #~ msgstr "# verworfener Nachrichten" #, fuzzy #~ msgid "# wlan acks received" #~ msgstr "# gap Anfragen insgesamt empfangen" #, fuzzy #~ msgid "# wlan messages for this client received" #~ msgstr "# verschlüsselter PING Nachrichten empfangen" #, fuzzy #~ msgid "# wlan messages inside WLAN_HELPER_DATA received" #~ msgstr "# verschlüsselter PING Nachrichten empfangen" #, fuzzy #~ msgid "Failed to send to `%s': %s\n" #~ msgstr "Datei wurde als `%s' gespeichert.\n" #, fuzzy #~ msgid "Could not access file: %s\n" #~ msgstr "`%s' konnte nicht aufgelöst werden: %s\n" #, fuzzy #~ msgid "`%s' failed on file `%s': %s" #~ msgstr "`%s' fehlgeschlagen für Laufwerk %s: %u\n" #, fuzzy #~ msgid "# bytes TCP was asked to transmit" #~ msgstr "# Bytes des Typs %d übertragen" #, fuzzy #~ msgid "# bytes discarded by TCP (failed to connect)" #~ msgstr "# Bytes verworfen von TCP (ausgehend)" #, fuzzy #~ msgid "# wlan messages queued" #~ msgstr "# verschlüsselter PING Nachrichten empfangen" #~ msgid "print this help" #~ msgstr "Gibt diese Hilfe aus" #~ msgid "print the version number" #~ msgstr "Versionsnummer ausgeben" #~ msgid "be verbose" #~ msgstr "umfangreiche Meldungen ausgeben" #, fuzzy #~ msgid "Failed to start service `%s'!\n" #~ msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #, fuzzy #~ msgid "Binary implementing service `%s' not known!\n" #~ msgstr "" #~ "Signatur kann nicht verifiziert werden, der Knoten `%s' ist uns nicht " #~ "bekannt!\n" #, fuzzy #~ msgid "Service `%s' stopped\n" #~ msgstr "Dienst gelöscht.\n" #, fuzzy #~ msgid "Unable to accept connection for service `%s': %s\n" #~ msgstr "Fehler beim Speichern der Konfigurationsdatei `%s':" #, fuzzy #~ msgid "Failed to transmit request to DATASTORE.\n" #~ msgstr "Fehler beim Senden einer `%s' Anfrage an den SMTP Server.\n" #, fuzzy #~ msgid "Failed to create IPv4 broadcast socket on port %d\n" #~ msgstr "Fehler beim Aktualisieren der Daten des Moduls `%s'\n" #, fuzzy #~ msgid "Failed to load block plugin `%s'\n" #~ msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #, fuzzy #~ msgid "Could not resolve our FQDN : %s %u\n" #~ msgstr "`%s' konnte nicht aufgelöst werden: %s\n" #, fuzzy #~ msgid "Failed to load dhtlog plugin for `%s'\n" #~ msgstr "Fehler beim Lesen der Freunde-Liste von `%s'\n" #, fuzzy #~ msgid "Found peer `%s'\n" #~ msgstr "Ich bin Peer `%s'.\n" #, fuzzy #~ msgid "Failed to initialize MySQL database connection for dhtlog.\n" #~ msgstr "SQLite Datenbank konnte nicht initialisiert werden.\n" #, fuzzy #~ msgid "Loading udp transport plugin\n" #~ msgstr "Teste Transport(e) %s\n" #, fuzzy #~ msgid "curl failed for `%s' at %s:%d: `%s'\n" #~ msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #, fuzzy #~ msgid "Phase 3: sending messages\n" #~ msgstr "Zustellung der Nachricht `%s' fehlgeschlagen.\n" #, fuzzy #~ msgid "Loading HTTPS transport plugin `%s'\n" #~ msgstr "Teste Transport(e) %s\n" #, fuzzy #~ msgid "Failed to load transport plugin for https\n" #~ msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #, fuzzy #~ msgid "Fail! Could not connect peers\n" #~ msgstr "`%s': Verbindung konnte nicht hergestellt werden.\n" #, fuzzy #~ msgid "Loading tcp transport plugin\n" #~ msgstr "Teste Transport(e) %s\n" #, fuzzy #~ msgid "Failed to load transport plugin for tcp\n" #~ msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #, fuzzy #~ msgid "# HTTP peers active" #~ msgstr "# Bytes empfangen über TCP" #, fuzzy #~ msgid "Misconfigured address to bind to in configuration!\n" #~ msgstr "In der Konfigurationsdatei wurden keine Anwendungen definiert!\n" #, fuzzy #~ msgid "Required configuration options missing in section `%s'\n" #~ msgstr "" #~ "Es muss eine Liste von Freunden in der Konfigurationsdatei unter `%s' in " #~ "der Sektion `%s' angegeben werden.\n" #, fuzzy #~ msgid "Loading HTTP transport plugin `%s'\n" #~ msgstr "Teste Transport(e) %s\n" #, fuzzy #~ msgid "Failed to load transport plugin for http\n" #~ msgstr "Anwendung `%s' konnte nicht initialisiert werden.\n" #, fuzzy #~ msgid "# PING messages decrypted" #~ msgstr "# PING Nachrichten erstellt" #, fuzzy #~ msgid "# bytes successfully transmitted by plugins" #~ msgstr "# Bytes des Typs %d übertragen" #, fuzzy #~ msgid "# connected addresses" #~ msgstr "# verbundener Knoten" #, fuzzy #~ msgid "# transport failed to selected peer address" #~ msgstr "Transport %d wird ausgewählten anderen Knoten bekannt gegeben.\n" #, fuzzy #~ msgid "# peer addresses considered valid" #~ msgstr "# Knotenankündigungen empfangen" #, fuzzy #~ msgid "# PING with HELLO messages sent" #~ msgstr "# PING Nachrichten erstellt" #, fuzzy #~ msgid "# HELLOs received for validation" #~ msgstr "# Blöcke migriert" #, fuzzy #~ msgid "Received `%s' message from `%s' destined for `%s' which is not me!\n" #~ msgstr "Empfangener PING ist nicht an uns gerichtet!\n" #, fuzzy #~ msgid "Could not send PONG to `%s': no address available\n" #~ msgstr "Knoten `%s' konnte nicht in der Routing Tabelle gefunden werden!\n" #, fuzzy #~ msgid "# HELLO messages received from other peers" #~ msgstr "Ungültige `%s' Nachricht von Knoten `%s' empfangen.\n" #~ msgid "Error" #~ msgstr "Fehler" #~ msgid "Help" #~ msgstr "Hilfe" #, fuzzy #~ msgid "Error!" #~ msgstr "Fehler" #~ msgid "No" #~ msgstr "Nein" #~ msgid "Yes" #~ msgstr "Ja" #, fuzzy #~ msgid "Abort" #~ msgstr "_über" #, fuzzy #~ msgid "Ok" #~ msgstr "k" #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://gnunet.org/\n" #~ "and join our community at\n" #~ "\thttp://gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "the GNUnet team" #~ msgstr "" #~ "Willkommen bei GNUnet!\n" #~ "\n" #~ "Dieser Assistent wird Ihnen einige grundlegende Fragen stellen, um GNUnet " #~ "zu konfigurieren.\n" #~ "\n" #~ "Bitte besuchen Sie unsere Homepage\n" #~ "\thttp://gnunet.org\n" #~ "und schließen Sie sich unserer Community an:\n" #~ "\thttps://gnunet.org/drupal/\n" #~ "\n" #~ "Viel Spaß,\n" #~ "\n" #~ "das GNUnet-Team" #~ msgid "" #~ "Choose the network interface that connects your computer to the internet " #~ "from the list below." #~ msgstr "" #~ "Wählen Sie das Netzwerkgerät, das Ihren Computer mit dem Internet " #~ "verbindet, aus unten stehender Liste." #~ msgid "" #~ "The \"Network interface\" is the device that connects your computer to " #~ "the internet. This is usually a modem, an ISDN card or a network card in " #~ "case you are using DSL." #~ msgstr "" #~ "Das \"Netzwerkgerät\" ist das Gerät, das Ihren Computer mit dem Internet " #~ "verbindet. Dies ist üblicherweise ein Modem, eine ISDN-Karte oder eine " #~ "Netzwerkkarte falls Sie DSL nutzen." #, fuzzy #~ msgid "Network configuration: interface" #~ msgstr "Netzwerkgerät:" #~ msgid "" #~ "What is the name of the network interface that connects your computer to " #~ "the Internet?" #~ msgstr "" #~ "Was ist der Name des Netzwerkgerätes, das Ihren Computer mit dem Internet " #~ "verbindet?" #, fuzzy #~ msgid "Network configuration: IP" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "What is this computer's public IP address or hostname?" #~ msgstr "" #~ "Wie heißt die öffentliche IP-Adresse oder der öffentliche Name dieses " #~ "Computers?\n" #~ "Wenn Sie nicht sicher sind, lassen Sie dieses Feld leer." #, fuzzy #~ msgid "" #~ "If your provider always assigns the same IP-Address to you (a \"static\" " #~ "IP-Address), enter it into the \"IP-Address\" field. If your IP-Address " #~ "changes every now and then (\"dynamic\" IP-Address) but there's a " #~ "hostname that always points to your actual IP-Address (\"Dynamic DNS\"), " #~ "you can also enter it here.\n" #~ "If left empty, GNUnet will try to automatically detect the IP.\n" #~ "You can specify a hostname, GNUnet will then use DNS to resolve it.\n" #~ "If in doubt, leave this empty." #~ msgstr "" #~ "Wenn Ihr Provider Ihnen immer die gleiche IP-Adresse zuweist (eine " #~ "\"statische\" IP-Adresse), so geben Sie diese in das \"IP-Adresse\"-Feld " #~ "ein. Wenn sich Ihre IP-Adresse immer wieder ändert (\"dynamische\" IP-" #~ "Adresse), es jedoch einen Rechnernamen gibt, der immer auf Ihre aktuelle " #~ "IP-Adresse verweist, so können Sie diesen ebenfalls eintragen.\n" #~ "Wenn Sie nicht sicher sind, so können Sie das Feld leer lassen. GNUnet " #~ "wird dann versuchen, Ihre IP-Adresse automatisch zu bestimmen." #, fuzzy #~ msgid "Bandwidth configuration: upload" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "How much upstream bandwidth (in bytes/s) may be used?" #~ msgstr "Wieviel Upstream (Bytes/s) darf verwendet werden?" #, fuzzy #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "The \"upstream\" is the data channel through which data is *sent* to the " #~ "internet. The limit is the maximum amount which GNUnet is allowed to use. " #~ "If you have a flatrate, you can set it to the maximum speed of your " #~ "internet connection. You should not use a value that is higher than what " #~ "your actual connection allows." #~ msgstr "" #~ "Hier können Sie GNUnets Ressourcenverwendung einschränken.\n" #~ "\n" #~ "Der \"Upstream\" ist der Datenkanal, durch den Daten an das Internet " #~ "*gesendet* werden. Das Limit ist entweder das gesamte Maximum für diesem " #~ "Computer oder wieviel GNUnet selbst verwenden darf. Dies können Sie " #~ "später festlegen. Wenn Sie eine Flatrate haben, können Sie die maximale " #~ "Geschwindigkeit Ihrer Internetverbindung angeben." #, fuzzy #~ msgid "Bandwidth configuration: download" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "How much downstream bandwidth (in bytes/s) may be used?" #~ msgstr "Wieviel Downstream (Bytes/s) darf verwendet werden?" #, fuzzy #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "The \"downstream\" is the data channel through which data is *received* " #~ "from the internet. The limit is the maximum amount which GNUnet is " #~ "allowed to use. If you have a flatrate, you can set it to the maximum " #~ "speed of your internet connection. You should not use a value that is " #~ "higher than what your actual connection allows." #~ msgstr "" #~ "Hier können Sie GNUnets Ressourcenverwendung einschränken.\n" #~ "\n" #~ "Der \"Downstream\" ist der Datenkanal, durch den Daten vom Internet " #~ "*empfangen* werden. Das Limit ist entweder das gesamte Maximum für diesem " #~ "Computer oder wieviel GNUnet selbst verwenden darf. Dies können Sie " #~ "später festlegen. Wenn Sie eine Flatrate haben, können Sie die maximale " #~ "Geschwindigkeit Ihrer Internetverbindung angeben." #, fuzzy #~ msgid "Quota configuration" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "" #~ "The GNUnet datastore contains all content that GNUnet needs to store " #~ "(indexed, inserted and migrated content)." #~ msgstr "" #~ "Was ist die maximale Größe des GNUnet Datenspeichers (in MB)?\n" #~ "Der GNUnet Datenspeicher enthält alle Daten, die GNUnet erzeugt " #~ "(Indexdaten, eingefügte und migrierte Inhalte)." #, fuzzy #~ msgid "Daemon configuration: user account" #~ msgstr "Fehler beim Anlegen des Benutzerkontos:" #, fuzzy #~ msgid "" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "user account under which the GNUnet service is started at system " #~ "startup.\n" #~ "\n" #~ "However, GNUnet may not be able to access files other than its own. This " #~ "includes files you want to publish in GNUnet. You'll have to grant read " #~ "permissions to the user specified below.\n" #~ "\n" #~ "Leave the field empty to run GNUnet with system privileges.\n" #~ msgstr "" #~ "Geben Sie den Benutzer an, dem der GNUnet Dienst gehören soll.\n" #~ "\n" #~ "Aus Sicherheitsgründen ist es eine gute Idee, dieses Setup ein neues " #~ "Benutzerkonto anlegen zu lassen, unter dem der GNUnet Dienst beim " #~ "Systemstart läuft.\n" #~ "\n" #~ "Natürlich kann GNUnet dann nur auf seine eigenen Dateien zugreifen. Dies " #~ "betrifft auch Dateien, die Sie im GNUnet veröffentlichen möchten. Sie " #~ "müssen dann dem unten angegebenen Benutzerkonto zuerst Leseberechtigungen " #~ "geben.\n" #~ "\n" #~ "Lassen Sie dieses Feld leer, wenn Sie GNUnet mit Systemprivilegien laufen " #~ "lassen möchten.\n" #~ "\n" #~ "GNUnet Benutzer:" #, fuzzy #~ msgid "" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "group for the chosen user account.\n" #~ "\n" #~ "You can also specify a already existent group here.\n" #~ "\n" #~ "Only members of this group will be allowed to start and stop the the " #~ "GNUnet server and have access to GNUnet server data.\n" #~ msgstr "" #~ "Definieren Sie eine Gruppe, der der GNUnet Dienst gehört.\n" #~ "\n" #~ "Aus Sicherheitsgründen ist es eine gute Idee, dieses Setup eine neue " #~ "Gruppe für das gewählte Benutzerkonto anlegen zu lassen.\n" #~ "\n" #~ "Sie können hier auch eine bestehende Gruppe angeben.\n" #~ "\n" #~ "Nur Mitglieder dieser Gruppe dürfen den GNUnet Server starten und " #~ "anhalten und haben Zugriff auf die Daten des GNUnet Servers.\n" #~ "\n" #~ "GNUnet Gruppe:" #, fuzzy #~ msgid "" #~ "If you say \"yes\" here, the GNUnet background process will be " #~ "automatically started when you turn on your computer. If you say \"no\" " #~ "here, you have to launch GNUnet yourself each time you want to use it." #~ msgstr "" #~ "Möchten Sie GNUnet als Systemdienst starten?\n" #~ "\n" #~ "Wenn Sie hier \"Ja\" sagen, so wird der GNUnet Hintergrundprozess " #~ "jedesmal automatisch gestartet, wenn Sie Ihren Computer einschalten. Wenn " #~ "Sie hier \"Nein\" sagen, so müssen Sie GNUnet jedesmal selbst starten, " #~ "wenn Sie es verwenden möchten." #, fuzzy #~ msgid "Unable to create user account for daemon." #~ msgstr "Fehler beim Anlegen des Benutzerkontos:" #, fuzzy #~ msgid "Save configuration?" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "GNUnet Configuration" #~ msgstr "GNUnet Konfiguration" #~ msgid "Back" #~ msgstr "Zurück" #~ msgid "Up" #~ msgstr "Oben" #~ msgid "Cancel" #~ msgstr "Abbrechen" #, fuzzy #~ msgid "Configuration unchanged, no need to save.\n" #~ msgstr "" #~ "Konfiguration oder die GNUnet Version hat sich geändert. Sie müssen `%s' " #~ "ausführen!\n" #, fuzzy #~ msgid "Do you wish to save your new configuration?" #~ msgstr "Möchten Sie Ihre Einstellungen speichern?" #, fuzzy #~ msgid "" #~ "\n" #~ "Your configuration changes were NOT saved.\n" #~ msgstr "Konfigurationsdatei `%s' wurde erzeugt.\n" #~ msgid "This version of Windows doesn't support services.\n" #~ msgstr "Diese Version von Windows unterstützt keine Dienste.\n" #~ msgid "Error: can't open Service Control Manager: %s\n" #~ msgstr "Fehler: der Dienstemanager konnte nicht geöffnet werden: %s\n" #~ msgid "Error: can't create service: %s\n" #~ msgstr "Fehler: Dienst konnte nicht angelegt werden: %s\n" #~ msgid "Error: can't access service: %s\n" #~ msgstr "Fehler: auf den Dienst konnte nicht zugegriffen werden: %s\n" #~ msgid "Error: can't delete service: %s\n" #~ msgstr "Fehler: Dienst konnte nicht gelöscht werden: %s\n" #, fuzzy #~ msgid "Configuration changed. Save?" #~ msgstr "" #~ "Konfiguration oder die GNUnet Version hat sich geändert. Sie müssen `%s' " #~ "ausführen!\n" #, fuzzy #~ msgid "Error saving configuration." #~ msgstr "Fehler beim Speichern der Konfiguration!" #, fuzzy #~ msgid "(unknown connection)" #~ msgstr "Netzwerkverbindung" #, fuzzy #~ msgid "Do you want to save the new configuration?" #~ msgstr "Möchten Sie Ihre Einstellungen speichern?" #~ msgid "Unable to change startup process:" #~ msgstr "Startprozeß konnte nicht geändert werden:" #~ msgid "generate configuration for gnunetd, the GNUnet daemon" #~ msgstr "Generiere Konfiguration für gnunetd, den GNUnet Daemon" #~ msgid "Tool to setup GNUnet." #~ msgstr "Werkzeug für die Einrichtung von GNUnet." #, fuzzy #~ msgid "Too many arguments.\n" #~ msgstr "Ungültige Kommandozeilen Parameter.\n" #, fuzzy #~ msgid "Configuration file `%s' must be a filename (but is a directory).\n" #~ msgstr "" #~ "Konfigurationsdatei `%s' nicht gefunden. Bitte führen Sie gnunet-setup " #~ "aus!\n" #, fuzzy #~ msgid "Undefined option.\n" #~ msgstr "Weitere Einstellungen" #, fuzzy #~ msgid "yes" #~ msgstr "Ja" #, fuzzy #~ msgid "Yes\n" #~ msgstr "Ja" #, fuzzy #~ msgid "No\n" #~ msgstr "Nein" #, fuzzy #~ msgid "Help\n" #~ msgstr "Hilfe" #, fuzzy #~ msgid "Abort\n" #~ msgstr "_über" #, fuzzy #~ msgid "Configuration was unchanged, no need to save.\n" #~ msgstr "" #~ "Konfiguration oder die GNUnet Version hat sich geändert. Sie müssen `%s' " #~ "ausführen!\n" #~ msgid "Can't open Service Control Manager" #~ msgstr "Der Dienstemanager konnte nicht geöffnet werden" #~ msgid "Can't create service" #~ msgstr "Der Dienst konnte nicht angelegt werden" #~ msgid "Error changing the permissions of the GNUnet directory" #~ msgstr "Fehler beim Ändern der Berechtigungen des GNUnet Verzeichnisses" #, fuzzy #~ msgid "Cannot write to the registry" #~ msgstr "Konnte nicht in die Registry schreiben" #~ msgid "Can't delete the service" #~ msgstr "Dienst konnte nicht gelöscht werden" #~ msgid "This version of Windows does not support multiple users." #~ msgstr "Diese Version von Windows ist nicht Mehrbenutzerfähig." #~ msgid "Error accessing local security policy" #~ msgstr "Fehler beim Zugriff auf die lokale Sicherheitsrichtlinie" #~ msgid "Error granting service right to user" #~ msgstr "Fehler beim Zuweisen des Dienstrechtes dem Benutzer" #~ msgid "Unknown error while creating a new user" #~ msgstr "Unbekannter Fehler beim Anlegen des neuen Benutzers" #, fuzzy #~ msgid "" #~ "Configuration does not satisfy constraints of configuration specification " #~ "file `%s'!\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss in der Sektion `%s' unter `%s' ein " #~ "Verzeichnis für FS Daten angeben.\n" #~ msgid "FATAL" #~ msgstr "SCHWERWIEGEND" #~ msgid "NOTHING" #~ msgstr "NICHTS" #, fuzzy #~ msgid "Syntax error in configuration entry HOST in section NETWORK: `%s'\n" #~ msgstr "Syntaxfehler in Konfigurationsdatei `%s' in Zeile %d.\n" #, fuzzy #~ msgid "Error connecting to %s:%u. Is the daemon running?\n" #~ msgstr "Verbindung zu %u.%u.%u.%u:%u fehlgeschlagen: %s\n" #, fuzzy #~ msgid "Cannot connect to %s:%u: %s\n" #~ msgstr "Verbindung zu %u.%u.%u.%u:%u fehlgeschlagen: %s\n" #, fuzzy #~ msgid "Reading result from gnunetd failed, reply invalid!\n" #~ msgstr "`%s' fehlgeschlagen, Antwort ist ungültig!\n" #, fuzzy #~ msgid "No interface specified in section `%s' under `%s'!\n" #~ msgstr "" #~ "Es sind keine Netzwerkgeräte in der Konfigurationsdatei in der Sektion `" #~ "%s' unter `%s' definiert!\n" #, fuzzy #~ msgid "" #~ "Could not find interface `%s' using `%s', trying to find another " #~ "interface.\n" #~ msgstr "" #~ "Gerät `%s' konnte in `%s' nicht gefunden werden, es wird versucht, ein " #~ "anderes Gerät zu finden.\n" #~ msgid "Could not find an IP address for interface `%s'.\n" #~ msgstr "Es konnte keine IP-Adresse für das Gerät `%s' ermittelt werden.\n" #, fuzzy #~ msgid "" #~ "There is more than one IP address specified for interface `%s'.\n" #~ "GNUnet will use %s.\n" #~ msgstr "" #~ "Es ist mehr als eine IP-Adresse für das Gerät `%s' angegeben.\n" #~ "GNUnet wird %u.%u.%u.%u. verwenden.\n" #~ msgid "Could not resolve `%s' to determine our IP address: %s\n" #~ msgstr "" #~ "`%s' konnte nicht aufgelöst werden, um unsere IP-Adresse zu ermitteln: " #~ "%s\n" #, fuzzy #~ msgid "Received malformed message (too small) from connection. Closing.\n" #~ msgstr "" #~ "Es wurde per TCP von einem anderen Knoten eine ungültige Nachricht (Größe " #~ "%u) empfangen. Verbindung wird geschlossen.\n" #, fuzzy #~ msgid "`%s' returned with error code %u" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #~ msgid "Can't create semaphore: %i" #~ msgstr "Semaphore konnte nicht angelegt werden: %i" #~ msgid "Cannot query the CPU usage (Windows NT).\n" #~ msgstr "CPU Nutzung kann nicht ermittelt werden (Windows NT).\n" #~ msgid "Cannot query the CPU usage (Win 9x)\n" #~ msgstr "CPU Nutzung kann nicht ermittelt werden (Win 9x).\n" #~ msgid "" #~ "No network interfaces defined in configuration section `%s' under `%s'!\n" #~ msgstr "" #~ "Es sind keine Netzwerkgeräte in der Konfigurationsdatei in der Sektion `" #~ "%s' unter `%s' definiert!\n" #, fuzzy #~ msgid "Command `%s' failed with error code %u\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #, fuzzy #~ msgid "Real-time delay violation (%llu ms) at %s:%u\n" #~ msgstr "Unerwartete sehr große Allokierung (%u Bytes) bei %s:%d!\n" #, fuzzy #~ msgid "Deadlock due to `%s'.\n" #~ msgstr "Durch `%s' ist ein Deadlock bei %s:%d entstanden\n" #, fuzzy #~ msgid "Lock acquired for too long (%llu ms) at %s:%u\n" #~ msgstr "Unerwartete sehr große Allokierung (%u Bytes) bei %s:%d!\n" #~ msgid "Availability test failed for `%s' at %s:%d.\n" #~ msgstr "Verfügbarkeitstest für `%s' fehlgeschlagen bei %s:%d.\n" #, fuzzy #~ msgid "Failed to load state service. Trying to do without.\n" #~ msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #, fuzzy #~ msgid "Starting datastore conversion (this may take a while).\n" #~ msgstr "Ein neuer Hostkey wird erzeugt (dies kann eine Weile dauern).\n" #, fuzzy #~ msgid "Failed to load sqstore service. Check your configuration!\n" #~ msgstr "Der Transportdienst auf Port %d konnte nicht gestartet werden.\n" #, fuzzy #~ msgid "" #~ "%s:%d - RPC %s:%p could not be registered: another callback is already " #~ "using this name (%p)\n" #~ msgstr "" #~ "%s::%s - RPC %s:%p konnte nicht registriert werden: ein anderer Callback " #~ "verwendet bereits diesen Namen (%p)\n" #, fuzzy #~ msgid "%s:%d - async RPC %s:%p could not be unregistered: not found\n" #~ msgstr "" #~ "%s::%s - async RPC %s:%p konnte nicht unregistriert werden: nicht " #~ "gefunden\n" #~ msgid "`%s' registering handlers %d %d %d\n" #~ msgstr "`%s' registriert Handler %d %d %d\n" #~ msgid "Using %u messages of size %u for %u times.\n" #~ msgstr "Verwende %u Nachrichten der Größe %u %umal.\n" #~ msgid "Times: max %16llu min %16llu mean %12.3f variance %12.3f\n" #~ msgstr "Zeiten: Max %16llu Min %16llu Mittel %12.3f Varianz %12.3f\n" #~ msgid "Loss: max %16u min %16u mean %12.3f variance %12.3f\n" #~ msgstr "Verloren: Max %16u Min %16u Mittel %12.3f Varianz %12.3f\n" #~ msgid "Running benchmark...\n" #~ msgstr "Benchmark läuft...\n" #~ msgid "allows profiling of direct peer-to-peer connections" #~ msgstr "Ermöglicht das Untersuchen direkter Peer-to-Peer Verbindungen" #~ msgid "Start GNUnet transport benchmarking tool." #~ msgstr "GNUnet Transport Benchmarking Werkzeug starten." #~ msgid "output in gnuplot format" #~ msgstr "Ausgabe im gnuplot Format" #~ msgid "number of messages to use per iteration" #~ msgstr "Anzahl an Nachrichten, die pro Durchlauf verwendet wird" #~ msgid "receiver host identifier (ENC file name)" #~ msgstr "Bezeichner des Empfängerhosts (ENC Dateiname)" #~ msgid "message size" #~ msgstr "Nachrichtengröße" #~ msgid "sleep for SPACE ms after each a message block" #~ msgstr "Für SPACE ms nach jedem Nachrichtenblock pausieren" #~ msgid "number of messages in a message block" #~ msgstr "Anzahl an Nachrichten in einem Nachrichtenblock" #~ msgid "Error establishing connection with gnunetd.\n" #~ msgstr "Fehler beim Aufbauen einer Verbindung mit gnunetd.\n" #~ msgid "You must specify a receiver!\n" #~ msgstr "Sie müssen einen Empfänger angeben!\n" #~ msgid "Invalid receiver peer ID specified (`%s' is not valid name).\n" #~ msgstr "" #~ "Ungültige Empfängerknoten ID angegeben (`%s' ist kein gültiger Name).\n" #~ msgid "Time:\n" #~ msgstr "Zeit:\n" #~ msgid "\tmax %llums\n" #~ msgstr "\tMax %llums\n" #~ msgid "\tmin %llums\n" #~ msgstr "\tMin %llums\n" #~ msgid "\tmean %8.4fms\n" #~ msgstr "\tMittel %8.4fms\n" #~ msgid "\tvariance %8.4fms\n" #~ msgstr "\tVarianz %8.4fms\n" #~ msgid "Loss:\n" #~ msgstr "Verlust:\n" #~ msgid "\tmax %u\n" #~ msgstr "\tMax %u\n" #~ msgid "\tmin %u\n" #~ msgstr "\tMin %u\n" #~ msgid "\tmean %8.4f\n" #~ msgstr "\tMittel %8.4fms\n" #~ msgid "\tvariance %8.4f\n" #~ msgstr "\tVarianz %8.4f\n" #~ msgid "Output format not known, this should not happen.\n" #~ msgstr "Ausgabeformat ist unbekannt, dies sollte nicht passieren.\n" #~ msgid "" #~ "\n" #~ "Did not receive the message from gnunetd. Is gnunetd running?\n" #~ msgstr "" #~ "\n" #~ "Es wurde keine Nachricht von gnunetd empfangen. Läuft gnunetd?\n" #, fuzzy #~ msgid "# bytes received in plaintext of type %d" #~ msgstr "# Bytes des Typs %d empfangen" #, fuzzy #~ msgid "# bytes allocated by SQLite" #~ msgstr "# bytes erlaubt in der Datenbank" #~ msgid "" #~ "Failed to load MySQL database module. Check that MySQL is running and " #~ "configured properly!\n" #~ msgstr "" #~ "Fehler beim Laden des MySQL Datenbankmoduls. Prüfen Sie, ob MySQL läuft " #~ "und richtig eingerichtet ist!\n" #~ msgid "probe network to the given DEPTH" #~ msgstr "Netzwerk bis zur angegebenen Tiefe DEPTH sondieren" #~ msgid "" #~ "specify output format; 0 for human readable output, 1 for dot, 2 for vcg" #~ msgstr "" #~ "Gibt das Ausgabeformat an: 0 für menschen-lesbar, 1 für dot, 2 für vcg" #, fuzzy #~ msgid "use PRIORITY for the priority of the trace request" #~ msgstr "PRIO als Priorität für die Trace Anfragen verwenden" #~ msgid "wait DELAY seconds for replies" #~ msgstr "DELAY Sekunden auf Antworten warten" #~ msgid "" #~ "Format specification invalid. Use 0 for user-readable, 1 for dot, 2 for " #~ "vcg.\n" #~ msgstr "" #~ "Formatangabe ungültig. Verwenden Sie 0 für menschen-lesbar, 1 für dot und " #~ "2 für vcg.\n" #~ msgid "allows mapping of the network topology" #~ msgstr "Erlaubt die Kartographierung der Netzwerktopologie" #, fuzzy #~ msgid "HELLO message from `%s' has an invalid signature. Dropping.\n" #~ msgstr "" #~ "Hello Nachricht von `%s' ist ungültig (Signatur ist ungültig). Nachricht " #~ "wurde verworfen.\n" #, fuzzy #~ msgid "HELLO message has expiration too far in the future. Dropping.\n" #~ msgstr "" #~ "Empfangene Hello Nachricht ist ungültig (Ablaufzeit über Limit). " #~ "Nachricht wurde verworfen.\n" #, fuzzy #~ msgid "Could not send HELLO+PING, ping buffer full.\n" #~ msgstr "Hellos+PING konnten nicht gesendet werden, Ping Puffer ist voll.\n" #~ msgid "" #~ "Announcing ourselves pointless: no other peers are known to us so far.\n" #~ msgstr "" #~ "Bekanntmachung von uns zwecklos: bis jetzt sind uns keine anderen Knoten " #~ "bekannt.\n" #, fuzzy #~ msgid "# Peer advertisements of type NAT received" #~ msgstr "# Knotenankündigungen empfangen" #, fuzzy #~ msgid "# Peer advertisements updating earlier HELLOs" #~ msgstr "# Knotenankündigungen empfangen" #, fuzzy #~ msgid "# Peer advertisements for unsupported transport" #~ msgstr "# Knotenankündigungen empfangen" #, fuzzy #~ msgid "# Peer advertisements not confirmed due to ping busy" #~ msgstr "# Knotenankündigungen empfangen" #, fuzzy #~ msgid "# Peer advertisements not confirmed due to lack of self ad" #~ msgstr "# Knotenankündigungen empfangen" #, fuzzy #~ msgid "# Peer advertisements not confirmed due to send error" #~ msgstr "# Knotenankündigungen empfangen" #~ msgid "`%s' registering handler %d (plaintext and ciphertext)\n" #~ msgstr "`%s' registriert Handler %d (Plaintext und Ciphertext)\n" #~ msgid "" #~ "ensures that this peer is known by other peers and discovers other peers" #~ msgstr "" #~ "Stellt sicher, dass dieser Knoten anderen Knoten bekannt ist und entdeckt " #~ "andere Knoten" #~ msgid "`%s' registering handler %d\n" #~ msgstr "`%s' registriert Handler %d\n" #, fuzzy #~ msgid "`%s' registering CS handlers %d and %d\n" #~ msgstr "`%s' registriert Handler %d und %d\n" #~ msgid "enables P2P-chat (incomplete)" #~ msgstr "Ermöglicht P2P-Chat" #, fuzzy #~ msgid "Existing key in file `%s' failed format check, creating new key.\n" #~ msgstr "" #~ "Formatüberprüfung schlug für die existierende Hostkeydatei `%s' fehl, es " #~ "wird ein neuer Hostkey erzeugt.\n" #, fuzzy #~ msgid "Creating new key for this nickname (this may take a while).\n" #~ msgstr "Ein neuer Hostkey wird erzeugt (dies kann eine Weile dauern).\n" #, fuzzy #~ msgid "# max bytes allowed in dstore" #~ msgstr "# bytes erlaubt in der Datenbank" #~ msgid "Transport library `%s' did not provide required function '%s%s'.\n" #~ msgstr "" #~ "Transport Bibliothek `%s' stellt nicht die benötigte Funktion '%s%s' zur " #~ "Verfügung.\n" #, fuzzy #~ msgid "Query (get KEY, put KEY VALUE) DHT table." #~ msgstr "" #~ "Eine DHT Tabelle abfragen (get KEY, put KEY VALUE, remove KEY VALUE)." #, fuzzy #~ msgid "allow TIME ms to process a GET command" #~ msgstr "TIME ms erlauben, um jedes Kommando zu bearbeiten" #, fuzzy #~ msgid "Issuing `%s(%s,%s)' command.\n" #~ msgstr "'%s(%s,%s)' fehlgeschlagen.\n" #~ msgid "Command `%s' requires an argument (`%s').\n" #~ msgstr "Kommando `%s' benötigt eine zusätzliche Angabe (`%s').\n" #~ msgid "Command `%s' requires two arguments (`%s' and `%s').\n" #~ msgstr "Kommando `%s' benötigt zwei zusätzliche Angaben (`%s' und `%s').\n" #, fuzzy #~ msgid "# dht discovery messages sent" #~ msgstr "# verschlüsselter PING Nachrichten empfangen" #, fuzzy #~ msgid "# dht put requests received" #~ msgstr "# Client Trace-Anfragen empfangen" #, fuzzy #~ msgid "`%s' registering p2p handlers: %d %d %d\n" #~ msgstr "`%s' registriert Handler %d %d %d\n" #~ msgid "`%s' failed. Terminating connection to client.\n" #~ msgstr "`%s' fehlgeschlagen. Beende Verbindung zu Client.\n" #, fuzzy #~ msgid "`%s' registering client handlers: %d %d\n" #~ msgstr "`%s' registriert Client-Handler %d\n" #~ msgid "" #~ "Existing hostkey in file `%s' failed format check, creating new hostkey.\n" #~ msgstr "" #~ "Formatüberprüfung schlug für die existierende Hostkeydatei `%s' fehl, es " #~ "wird ein neuer Hostkey erzeugt.\n" #~ msgid "Done creating hostkey.\n" #~ msgstr "Hostkey wurde erfolgreich erzeugt.\n" #, fuzzy #~ msgid "Removed file `%s' containing invalid HELLO data.\n" #~ msgstr "Datei `%s' enthielt ungültige Hello Daten und wurde entfernt.\n" #~ msgid "Signature failed verification: signature invalid.\n" #~ msgstr "" #~ "Verifikation einer Signatur fehlgeschlagen: Signatur ist ungültig.\n" #~ msgid "Received malformed `%s' message. Dropping.\n" #~ msgstr "Beschädigte `%s' Nachricht empfangen. Nachricht wird verworfen.\n" #~ msgid "Received ping for another peer. Dropping.\n" #~ msgstr "Ping für einen anderen Knoten empfangen. Ping wird verworfen.\n" #~ msgid "" #~ "Could not match PONG against any PING. Try increasing MAX_PING_PONG " #~ "constant.\n" #~ msgstr "" #~ "PONG konnte keinem PING zugeordnet werden. Versuchen Sie die Konstante " #~ "MAX_PING_PONG hochzusetzen.\n" #~ msgid "Cannot create PING, table full. Try increasing MAX_PING_PONG.\n" #~ msgstr "" #~ "PING konnte nicht erstellt werden, da die Tabelle voll ist. Versuchen " #~ "Sie, die Konstante MAX_PING_PONG hochzusetzen.\n" #~ msgid "# plaintext PONG messages received" #~ msgstr "# Klartext PONG Nachrichten empfangen" #~ msgid "# encrypted PING messages received" #~ msgstr "# verschlüsselter PING Nachrichten empfangen" #~ msgid "# encrypted PING messages sent" #~ msgstr "# verschlüsselter PING Nachrichten gesendet" #~ msgid "`%s' registering handlers %d %d (plaintext and ciphertext)\n" #~ msgstr "`%s' registriert Handler %d %d (Plaintext und Ciphertext)\n" #~ msgid "Cannot encrypt sessionkey, peer `%s' not known!\n" #~ msgstr "" #~ "Sitzungsschlüssel kann nicht verschlüsselt werden, Knoten `%s' ist uns " #~ "nicht bekannt!\n" #, fuzzy #~ msgid "Could not create any HELLO for myself (have transports `%s')!\n" #~ msgstr "Hostkey konnte nicht erzeugt werden!\n" #, fuzzy #~ msgid "" #~ "Session key received from peer `%s' has invalid format (discarded).\n" #~ msgstr "Empfangene Nachricht ist ungültig.\n" #, fuzzy #~ msgid "Session key received from peer `%s' is for `%s' and not for me!\n" #~ msgstr "Empfangene Nachricht ist ungültig.\n" #~ msgid "setkey `%s' from `%s' fails CRC check (have: %u, want %u).\n" #~ msgstr "" #~ "setkey `%s' von `%s' hat eine ungültige CRC Prüfsumme (tatsächlich: %u, " #~ "erwartet: %u).\n" #, fuzzy #~ msgid "" #~ "Error parsing encrypted session key from `%s', given message part size is " #~ "invalid.\n" #~ msgstr "" #~ "Fehler beim Parsen des Verschlüsselten Sitzungsschlüssels, gegebene " #~ "Nachrichtenteilgröße ist ungültig.\n" #, fuzzy #~ msgid "Unknown type in embedded message from `%s': %u (size: %u)\n" #~ msgstr "Unbekannter Typ in engebetteter Nachricht: %u (%u bytes)\n" #~ msgid "# session keys sent" #~ msgstr "# Sitzungsschlüssel gesendet" #~ msgid "automate creation of a namespace by starting a collection" #~ msgstr "" #~ "Erstellung eines Namespaces durch das Anfangen einer Collection " #~ "automatisieren" #~ msgid "create a new pseudonym under the given NICKNAME" #~ msgstr "Neues Pseudonym unter dem angegebenen NICKNAME erstellen" #~ msgid "delete the pseudonym with the given NICKNAME" #~ msgstr "Pseudonym mit dem angegeben NICKNAME löschen" #~ msgid "end automated building of a namespace (ends collection)" #~ msgstr "" #~ "Automatisierte Erstellung eines Namespaces beenden (beendet Collection)" #~ msgid "" #~ "Create new pseudonyms, delete pseudonyms or list existing pseudonyms." #~ msgstr "" #~ "Erstellen von neuen Pseudonymen, Löschen von Pseudonymen und Auflisten " #~ "von bestehenden Pseudonymen." #~ msgid "" #~ "use the given keyword to advertise the namespace (use when creating a new " #~ "pseudonym)" #~ msgstr "" #~ "Das angegebene schlüsselwort verwenden, um den Namespace bekanntzumachen " #~ "(zu verwenden, wenn ein neues Pseudonym erstellt wird)" #, fuzzy #~ msgid "specify metadata describing the namespace or collection" #~ msgstr "" #~ "Automatisierte Erstellung eines Namespaces beenden (beendet Collection)" #~ msgid "" #~ "do not generate an advertisement for this namespace (use when creating a " #~ "new pseudonym)" #~ msgstr "" #~ "Keine Bekanntmachung für diesen Namespace erstellen (zu verwenden, wenn " #~ "ein neues Pseudonym erstellt wird)" #~ msgid "do not list the pseudonyms from the pseudonym database" #~ msgstr "Keine Ausgabe der Pseudonyme in der Pseudonymdatenbank" #~ msgid "" #~ "specify IDENTIFIER to be the address of the entrypoint to content in the " #~ "namespace (use when creating a new pseudonym)" #~ msgstr "" #~ "IDENTIFIER als Adresse angeben, die der Einsprungspunkt zu den Inhalten " #~ "im Namespace ist (zu verwenden, wenn ein neues Pseudonym erstellt wird)" #~ msgid "Namespace `%s' (%s) has rating %d.\n" #~ msgstr "Namespace `%s' (%s) hat das Rating %d.\n" #~ msgid "\tRating (after update): %d\n" #~ msgstr "\tRating (nach Update): %d\n" #~ msgid "Failed to stop collection (not active?).\n" #~ msgstr "Fehler beim Beenden der Collection (nicht aktiv?).\n" #~ msgid "Error deleting pseudonym `%s' (does not exist?).\n" #~ msgstr "Fehler beim Löschen des Pseudonyms `%s' (existiert nicht?).\n" #, fuzzy #~ msgid "Started collection.\n" #~ msgstr "Collection `%s' begonnen.\n" #~ msgid "Namespace `%s' created (root: %s).\n" #~ msgstr "Namespace `%s' wurde erstellt (Root: %s).\n" #, fuzzy #~ msgid "You must specify a name for the collection (`%s' option).\n" #~ msgstr "" #~ "Sie müssen einen Namen für die PID Datei in Sektion `%s' unter `%s' " #~ "angeben.\n" #~ msgid "%d files found in directory.\n" #~ msgstr "%d Dateien im Verzeichnis gefunden.\n" #~ msgid "Perform directory related operations." #~ msgstr "Verzeichnisbezogene Operationen durchführen." #~ msgid "" #~ "remove all entries from the directory database and stop tracking URIs" #~ msgstr "" #~ "Alle Einträge aus der Verzeichnis Datenbank löschen und das Verfolgen von " #~ "URIs abbrechen" #~ msgid "list entries from the directory database" #~ msgstr "Einträge aus der Verzeichnis Datenbank auflisten" #~ msgid "start tracking entries for the directory database" #~ msgstr "Anfangen, Einträge für die Verzeichnis Datenbank zu verfolgen" #~ msgid "Listed %d matching entries.\n" #~ msgstr "%d übereinstimmende Einträge aufgelistet.\n" #, fuzzy #~ msgid "Upload of `%s' at %llu out of %llu bytes.\n" #~ msgstr "Download der Datei `%s' bei %16llu von %16llu Bytes (%8.3f kbps)\n" #, fuzzy #~ msgid "Upload aborted.\n" #~ msgstr "" #~ "\n" #~ "Upload abgebrochen.\n" #, fuzzy #~ msgid "Uploading suspended.\n" #~ msgstr "Upload abgewiesen!" #, fuzzy #~ msgid "" #~ "run in debug mode; gnunet-auto-share will not daemonize and error " #~ "messages will be written to stderr instead of a logfile" #~ msgstr "" #~ "Im Debug-Modus ausführen. gnunetd wird nicht im Hintergrund laufen und " #~ "Fehlermeldungen werden nicht in die Protokolldatei, sondern auf die " #~ "Standardfehlerausgabe (stderr) geschrieben." #, fuzzy #~ msgid "" #~ "do not use libextractor to add additional references to directory entries " #~ "and/or the published file" #~ msgstr "" #~ "benutze libextractor um weitere direkte Referenzen zu Dateien in " #~ "Verzeichnissen zu erzeugen" #~ msgid "Created entry `%s' in namespace `%s'\n" #~ msgstr "Eintag `%s' in Namespace `%s' wurde erstellt\n" #~ msgid "" #~ "%16llu of %16llu bytes inserted (estimating %6s to completion) - %s\n" #~ msgstr "" #~ "%16llu von %16llu Bytes eingefügt (geschätzte %6s bis Fertigstellung) - " #~ "%s\n" #~ msgid "" #~ "Upload of `%s' complete, %llu bytes took %llu seconds (%8.3f KiB/s).\n" #~ msgstr "" #~ "Upload von `%s' komplett, %llu Bytes brauchten %llu Sekunden (%8.3f KB/" #~ "s).\n" #~ msgid "" #~ "\n" #~ "Upload aborted.\n" #~ msgstr "" #~ "\n" #~ "Upload abgebrochen.\n" #, fuzzy #~ msgid "" #~ "\n" #~ "Error uploading file: %s" #~ msgstr "" #~ "\n" #~ "Fehler beim Uploaden der Datei: %s\n" #~ msgid "" #~ "even if gnunetd is running on the local machine, force the creation of a " #~ "copy instead of making a link to the GNUnet share directory" #~ msgstr "" #~ "Obwohl gnunetd auf der lokalen Maschiene läuft die Erstellung einer Kopie " #~ "anstelle der Erzeugung eines Links auf das GNUnet Share-Verzeichnis " #~ "erzwingen." #~ msgid "Make files available to GNUnet for sharing." #~ msgstr "Dateien GNUnet zum Filesharing zur Verfügung stellen." #~ msgid "Could not access namespace `%s' (does not exist?).\n" #~ msgstr "Konnte nicht auf den Namespace `%s' zugreifen (existiert nicht?).\n" #~ msgid "Search GNUnet for files." #~ msgstr "Das GNUnet nach Dateien durchsuchen." #~ msgid "write encountered (decrypted) search results to FILENAME" #~ msgstr "Begegnete (entschlüsselte) Suchergebnisse in FILENAME schreiben" #~ msgid "" #~ "%16llu of %16llu bytes unindexed (estimating %llu seconds to " #~ "completion) " #~ msgstr "" #~ "%16llu von %16llu Bytes deindiziert (schätze %llu Sekunden bis " #~ "Fertigstellung) " #~ msgid "" #~ "\n" #~ "Unindexing of `%s' complete, %llu bytes took %llu seconds (%8.3f KiB/s).\n" #~ msgstr "" #~ "\n" #~ "Deindizierung von `%s' abgeschlossen, %llu Bytes benötigten %llu Sekunden " #~ "(%8.3f kbps).\n" #, fuzzy #~ msgid "Not enough arguments. You must specify a filename.\n" #~ msgstr "" #~ "Nicht genügend Parameter. Sie müssen eine GNUnet Datei URI angeben\n" #~ msgid "`%s' failed. Is `%s' a file?\n" #~ msgstr "`%s' schlug fehl. Ist `%s' eine Datei?\n" #~ msgid "Download files from GNUnet." #~ msgstr "Dateien aus dem GNUnet herunterladen." #~ msgid "Download of file `%s' at %16llu out of %16llu bytes (%8.3f KiB/s)\n" #~ msgstr "Download der Datei `%s' bei %16llu von %16llu Bytes (%8.3f kbps)\n" #~ msgid "Download aborted.\n" #~ msgstr "Download abgebrochen.\n" #~ msgid "Download of file `%s' complete. Speed was %8.3f KiB per second.\n" #~ msgstr "" #~ "Download der Datei `%s' abgeschlossen. Geschwindigkeit war %8.3f KB/s.\n" #~ msgid "Not enough arguments. You must specify a GNUnet file URI\n" #~ msgstr "" #~ "Nicht genügend Parameter. Sie müssen eine GNUnet Datei URI angeben\n" #~ msgid "URI `%s' invalid for gnunet-download.\n" #~ msgstr "URI `%s' ist ungültig für gnunet-download.\n" #, fuzzy #~ msgid "No filename specified, using `%s' instead (for now).\n" #~ msgstr "Kein Tabellenname angegeben, verwende `%s'.\n" #, fuzzy #~ msgid "Downloading %d files from directory `%s'.\n" #~ msgstr "Dateien aus dem GNUnet herunterladen." #~ msgid "File stored as `%s'.\n" #~ msgstr "Datei wurde als `%s' gespeichert.\n" #~ msgid "Collecting file identifiers disabled.\n" #~ msgstr "Einsammeln von Dateibezeichnern deaktiviert.\n" #~ msgid "Cannot get size of file `%s'" #~ msgstr "Die Größe der Datei `%s' konnte nicht ermittelt werden" #~ msgid "Cannot hash `%s'.\n" #~ msgstr "`%s' konnte nicht gehashed werden.\n" #~ msgid "Initialization for indexing file `%s' failed.\n" #~ msgstr "Initialisierung der Indizierung der Datei `%s' fehlgeschlagen.\n" #, fuzzy #~ msgid "Cannot open file `%s': `%s'" #~ msgstr "Konfigurationsdatei `%s' konnte nicht geöffnet werden.\n" #~ msgid "Renaming of file `%s' to `%s' failed: %s\n" #~ msgstr "Umbenennen der Datei `%s' zu `%s' fehlgeschlagen: %s\n" #~ msgid "Could not rename file `%s' to `%s': file exists\n" #~ msgstr "" #~ "Datei `%s' konnte nicht zu `%s' umbenannt werden: Datei existiert " #~ "bereits\n" #~ msgid "CHK URI not allowed for search.\n" #~ msgstr "CHK URI ist nicht erlaubt für Suchen.\n" #~ msgid "LOC URI not allowed for search.\n" #~ msgstr "LOC URI ist nicht erlaubt für Suchen.\n" #, fuzzy #~ msgid "Format of file `%s' is invalid, trying to remove.\n" #~ msgstr "Format der Datei `%s' ist ungültig.\n" #~ msgid "" #~ "Decrypted content does not match key. This is either a bug or a " #~ "maliciously inserted file. Download aborted.\n" #~ msgstr "" #~ "Entschlüsselter Inhalt entspricht nicht dem Schlüssel. Dies ist entweder " #~ "ein Bug oder eine mit bösen Absichten eingefügte Datei. Download wurde " #~ "abgebrochen.\n" #, fuzzy #~ msgid "Application aborted." #~ msgstr "_Optionen" #~ msgid "FSUI state file `%s' had syntax error at offset %u.\n" #~ msgstr "FSUI Statusdatei `%s' hatte einen Syntaxfehler bei Offset %u.\n" #, fuzzy #~ msgid "# gap content total planned" #~ msgstr "# gap Anfragen insgesamt empfangen" #~ msgid "# gap requests total received" #~ msgstr "# gap Anfragen insgesamt empfangen" #, fuzzy #~ msgid "" #~ "`%s' registering client handlers %d %d %d %d %d %d %d %d and P2P handlers " #~ "%d %d\n" #~ msgstr "`%s' registriert die Client Handler %d %d %d %d %d %d %d %d %d\n" #~ msgid "enables (anonymous) file-sharing" #~ msgstr "Ermöglicht (anonymes) Filesharing" #~ msgid "" #~ "Because the file `%s' has been unavailable for 3 days it got removed from " #~ "your share. Please unindex files before deleting them as the index now " #~ "contains invalid references!\n" #~ msgstr "" #~ "Weil die Datei `%s' nun seit 3 Tagen nicht zur Verfügung steht, wurde Sie " #~ "aus Ihrem Share entfernt. Bitte deindizieren Sie Dateien, bevor Sie sie " #~ "löschen, da Ihr Index nun ungültige Referenzen enthält!\n" #~ msgid "" #~ "Unindexed ODB block `%s' from offset %llu already missing from " #~ "datastore.\n" #~ msgstr "" #~ "Deindizierter ODB Block `%s' vom Offset %llu fehlt bereits im " #~ "Datenspeicher.\n" #, fuzzy #~ msgid "# gap client requests tracked" #~ msgstr "# gap Anfragen insgesamt empfangen" #~ msgid "# blocks migrated" #~ msgstr "# Blöcke migriert" #, fuzzy #~ msgid "# blocks injected for migration" #~ msgstr "# Blöcke migriert" #, fuzzy #~ msgid "# on-demand fetches for migration" #~ msgstr "# Blöcke migriert" #, fuzzy #~ msgid "# gap queries dropped (table full)" #~ msgstr "# gap falsche Antworten" #, fuzzy #~ msgid "# gap queries dropped (redundant)" #~ msgstr "# gap falsche Antworten" #, fuzzy #~ msgid "# trust earned" #~ msgstr "# dht Anfragen weitergeleitet" #, fuzzy #~ msgid "Friend list of %s:%d\n" #~ msgstr "Es konnte keine Verbindung mit gnunetd hergestellt werden.\n" #, fuzzy #~ msgid "Bootstrap data obtained from `%s' is invalid.\n" #~ msgstr "Format des Pseudonyms `%s' ist ungültig.\n" #~ msgid "`%s' registering client handler %d\n" #~ msgstr "`%s' registriert Client-Handler %d\n" #~ msgid "`%s' registering client handler %d and %d\n" #~ msgstr "`%s' registriert Client-Handler %d and %d\n" #~ msgid "Uptime (seconds)" #~ msgstr "Laufzeit (Sekunden)" #~ msgid "% of allowed network load (up)" #~ msgstr "% of allowed network load (up)" #~ msgid "% of allowed network load (down)" #~ msgstr "% of allowed network load (down)" #~ msgid "% of allowed cpu load" #~ msgstr "% of allowed cpu load" #, fuzzy #~ msgid "% of allowed io load" #~ msgstr "% of allowed cpu load" #, fuzzy #~ msgid "`%s' registering client handlers %d %d %d and p2p handler %d\n" #~ msgstr "`%s' registriert die Client Handler %d %d %d %d %d %d %d %d %d\n" #~ msgid "keeps statistics about gnunetd's operation" #~ msgstr "Hält Statistiken über Betrieb von gnunetd" #~ msgid "Supported peer-to-peer messages:\n" #~ msgstr "unterstützte Peer-to-Peer Nachrichten:\n" #~ msgid "Supported client-server messages:\n" #~ msgstr "unterstützte Client-Server Nachrichten:\n" #~ msgid "prints supported protocol messages" #~ msgstr "gibt unterstützte Protokollnachrichten aus" #, fuzzy #~ msgid "VPN Received unknown IP version %d...\n" #~ msgstr "Es wurde eine unbekannte Testbed Nachricht des Typs %u empfangen.\n" #, fuzzy #~ msgid "Cannot open tunnel device: %s" #~ msgstr "Konfigurationsdatei `%s' konnte nicht geöffnet werden.\n" #, fuzzy #~ msgid "Cannot set interface IPv6 address for gnu%d because %s\n" #~ msgstr "Es konnte keine IP-Adresse für das Gerät `%s' ermittelt werden.\n" #, fuzzy #~ msgid "Cannot add route IPv6 address for gnu%s because %s\n" #~ msgstr "Es konnte keine IP-Adresse für das Gerät `%s' ermittelt werden.\n" #, fuzzy #~ msgid "`%s' initialising RFC4913 module %d and %d\n" #~ msgstr "`%s' registriert Handler %d und %d\n" #, fuzzy #~ msgid "enables IPv6 over GNUnet (incomplete)" #~ msgstr "Ermöglicht P2P-Chat" #~ msgid "Application module `%s' already initialized!\n" #~ msgstr "Anwendungsmodul `%s' ist bereits initialisiert!\n" #~ msgid "Could not shutdown `%s': application not loaded\n" #~ msgstr "" #~ "`%s' kann nicht heruntergefahren werden: Anwendung ist nicht geladen\n" #~ msgid "Could not shutdown application `%s': not initialized\n" #~ msgstr "" #~ "Anwendung `%s' kann nicht heruntergefahren werden: sie ist nicht " #~ "initialisiert\n" #~ msgid "Could not find '%s%s' method in library `%s'.\n" #~ msgstr "Methode '%s%s' kann in Bibliothek `%s' nicht gefunden werden.\n" #~ msgid "Could not release %p: service not loaded\n" #~ msgstr "%p kann nicht freigegeben werden: Dienst ist nicht geladen\n" #~ msgid "Could not properly shutdown application `%s'.\n" #~ msgstr "Anwendung `%s' konnte nicht ordentlich heruntergefahren werden.\n" #~ msgid "Could not properly unload service `%s'!\n" #~ msgstr "Dienst `%s' konnte nicht ordentlich entladen werden!\n" #~ msgid "Updates GNUnet datastructures after version change." #~ msgstr "GNUnet Datenstrukturen nach einer Versionsänderung aktualisieren." #~ msgid "run as user LOGIN" #~ msgstr "als Benutzer LOGIN ausführen" #~ msgid "run in client mode (for getting client configuration values)" #~ msgstr "" #~ "Im Benuter-Modus laufen (um benutzerspezifische " #~ "Konfigurationseinstellungen zu holen" #~ msgid "" #~ "run in debug mode; gnunetd will not daemonize and error messages will be " #~ "written to stderr instead of a logfile" #~ msgstr "" #~ "Im Debug-Modus ausführen. gnunetd wird nicht im Hintergrund laufen und " #~ "Fehlermeldungen werden nicht in die Protokolldatei, sondern auf die " #~ "Standardfehlerausgabe (stderr) geschrieben." #~ msgid "Starts the gnunetd daemon." #~ msgstr "Startet den gnunetd Daemonen." #, fuzzy #~ msgid "specify username as which gnunetd should run" #~ msgstr "Gibt an, auf welchem Host gnunetd läuft" #~ msgid "Configuration or GNUnet version changed. You need to run `%s'!\n" #~ msgstr "" #~ "Konfiguration oder die GNUnet Version hat sich geändert. Sie müssen `%s' " #~ "ausführen!\n" #~ msgid "The `%s' request received from client is malformed.\n" #~ msgstr "Die `%s' Anfrage, die vom Client empfangen wurde, ist beschädigt.\n" #~ msgid "" #~ "Malformed network specification in the configuration in section `%s' for " #~ "entry `%s': %s\n" #~ msgstr "" #~ "Beschädigte Netzwerkangabe in der Konfigurationsdatei in Sektion `%s' für " #~ "Eintrag `%s': %s\n" #, fuzzy #~ msgid "Registering failed, message type %d already in use.\n" #~ msgstr "%s schlug fehl, Nachrichten Typ %d ist bereits in Verwendung.\n" #, fuzzy #~ msgid "Unable to obtain filesystem information for `%s': %u\n" #~ msgstr "Fehler beim Speichern der Konfigurationsdatei: `%s': %s.\n" #, fuzzy #~ msgid "`%s' message invalid (signature invalid).\n" #~ msgstr "Hello Nachricht ist ungültig (Signatur ist ungültig).\n" #~ msgid "`%s' selected %d out of %d messages (MTU: %d).\n" #~ msgstr "`%s' wählte %d von %d Nachrichten aus (MTU: %d).\n" #~ msgid "Message details: %u: length %d, priority: %d\n" #~ msgstr "Nachrichten Details: %u: Länge %d, Priorität: %d\n" #~ msgid "Message from `%s' discarded: invalid format.\n" #~ msgstr "Nachricht von `%s' verworfen: ungültiges Format.\n" #~ msgid "Invalid sequence number %u <= %u, dropping message.\n" #~ msgstr "Ungültige Sequenznummer %u <= %u, Nachricht wird verworfen.\n" #~ msgid "Message received more than one day old. Dropped.\n" #~ msgstr "" #~ "Empfangene Nachricht ist mehr als ein Tag alt. Nachricht wird verworfen.\n" #~ msgid "# connections closed (HANGUP sent)" #~ msgstr "# geschlossener Verbindungen (HANGUP gesendet)" #~ msgid "# bytes noise sent" #~ msgstr "# Bytes Rauschen gesendet" #, fuzzy #~ msgid "# total bytes per second receive limit" #~ msgstr "# Bytes Rauschen empfangen" #, fuzzy #~ msgid "# total number of messages in send buffers" #~ msgstr "Anzahl an Nachrichten in einem Nachrichtenblock" #, fuzzy #~ msgid "# total number of bytes we were allowed to send but did not" #~ msgstr "Anzahl an Nachrichten in einem Nachrichtenblock" #, fuzzy #~ msgid "# total number of bytes we were allowed to sent" #~ msgstr "Anzahl an Nachrichten in einem Nachrichtenblock" #~ msgid "`%s': Could not create hello.\n" #~ msgstr "`%s': Hello konnte nicht erzeugt werden.\n" #~ msgid "`%s': Could not send.\n" #~ msgstr "`%s': Kann nicht senden.\n" #~ msgid "`%s': Could not disconnect.\n" #~ msgstr "`%s': Verbindung konnte nicht getrennt werden.\n" #, fuzzy #~ msgid "" #~ "`%s' transport OK. It took %ums to transmit %llu messages of %llu bytes " #~ "each.\n" #~ msgstr "" #~ "`%s' Transport funktioniert. Es dauerte %ums, um %d Nachrichten zu je %d " #~ "Bytes zu übertragen.\n" #, fuzzy #~ msgid " Transport %d is not being tested\n" #~ msgstr " Transport %d ist nicht verfügbar\n" #~ msgid "" #~ "\n" #~ "Contacting `%s'." #~ msgstr "" #~ "\n" #~ "Kontaktiere `%s'." #, fuzzy #~ msgid "OK!\n" #~ msgstr "OK" #~ msgid "Tool to test if GNUnet transport services are operational." #~ msgstr "" #~ "Werkzeug, mit dem getestet werden kann, ob die GNUnet Transport Dienste " #~ "funktionsfähig sind." #~ msgid "ping peers from HOSTLISTURL that match transports" #~ msgstr "Knoten aus HOSTLISTURL anpingen, deren Transports passen" #~ msgid "send messages with SIZE bytes payload" #~ msgstr "Nachrichten mit SIZE Bytes Nutzlast versenden" #~ msgid "specifies after how many MS to time-out" #~ msgstr "Gibt an, nach wievielen MS die Zeit abgelaufen sein soll" #~ msgid "Available transport(s): %s\n" #~ msgstr "Verfügbare(r) Transport(e): %s\n" #, fuzzy #~ msgid "" #~ "\n" #~ "%d out of %d peers contacted successfully (%d times transport " #~ "unavailable).\n" #~ msgstr "" #~ "%d von %d Knoten erfolgreich kontaktiert (%d mal war der Transport nicht " #~ "verfügbar).\n" #, fuzzy #~ msgid "%s failed for url `%s' and post-data `%s' at %s:%d: `%s'\n" #~ msgstr "`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'.\n" #~ msgid "# bytes sent via HTTP" #~ msgstr "# Bytes gesendet über HTTP" #~ msgid "# bytes dropped by HTTP (outgoing)" #~ msgstr "# Bytes verworfen von HTTP" #, fuzzy #~ msgid "# HTTP connect calls" #~ msgstr "# verbundener Knoten" #, fuzzy #~ msgid "Failed to obtain my (external) %s address!\n" #~ msgstr "Fehler beim Bestimmen der (externen) IP-Adresse!\n" #, fuzzy #~ msgid "MTU %llu for `%s' is probably too low!\n" #~ msgstr "" #~ "MTU für `%s' ist möglicherweise zu gering (Fragmentierung ist nicht " #~ "implementiert!)\n" #~ msgid "specify host on which gnunetd is running" #~ msgstr "Gibt an, auf welchem Host gnunetd läuft" #~ msgid "No help available." #~ msgstr "Keine Hilfe verfügbar." #, fuzzy #~ msgid "Show rarely used options" #~ msgstr "Maskierte Optionen anzeigen" #, fuzzy #~ msgid "Meta-configuration" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "Full pathname of GNUnet HOME directory" #~ msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #, fuzzy #~ msgid "Full pathname of GNUnet directory for file-sharing data" #~ msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #, fuzzy #~ msgid "Full pathname to the directory with the key-value database" #~ msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #, fuzzy #~ msgid "Note that the kvstore is currently not used." #~ msgstr "# gap Routingschächte im Moment in Verwendung" #, fuzzy #~ msgid "Full pathname of GNUnet directory for indexed files symbolic links" #~ msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #, fuzzy #~ msgid "Run gnunetd as this group." #~ msgstr "gnunet-update ausführen" #, fuzzy #~ msgid "General settings" #~ msgstr "Weitere Einstellungen" #, fuzzy #~ msgid "Settings for restricting connections to friends" #~ msgstr "`%s' fehlgeschlagen. Beende Verbindung zu Client.\n" #, fuzzy #~ msgid "Configuration file that specifies the MySQL username and password" #~ msgstr "" #~ "Konfiguration oder die GNUnet Version hat sich geändert. Sie müssen `%s' " #~ "ausführen!\n" #, fuzzy #~ msgid "Configuration of the MySQL database" #~ msgstr "" #~ "Konfiguration oder die GNUnet Version hat sich geändert. Sie müssen `%s' " #~ "ausführen!\n" #, fuzzy #~ msgid "MB of diskspace GNUnet can use for anonymous file sharing" #~ msgstr "Ermöglicht (anonymes) Filesharing" #, fuzzy #~ msgid "Number of entries in the migration buffer" #~ msgstr "Anzahl an Nachrichten in einem Nachrichtenblock" #, fuzzy #~ msgid "Options for anonymous file sharing" #~ msgstr "Ermöglicht (anonymes) Filesharing" #, fuzzy #~ msgid "Applications" #~ msgstr "_Optionen" #, fuzzy #~ msgid "Network interface" #~ msgstr "Netzwerkgerät:" #, fuzzy #~ msgid "Network interface to monitor" #~ msgstr "Netzwerkgerät:" #, fuzzy #~ msgid "Load management" #~ msgstr "Ungültige Kommandozeilen Parameter.\n" #, fuzzy #~ msgid "This is equivalent to the -H option. The format is IP:PORT." #~ msgstr "Wert der Option anzeigen" #, fuzzy #~ msgid "General options" #~ msgstr "Weitere Einstellungen" #, fuzzy #~ msgid "Options related to gnunet-gtk" #~ msgstr "Nicht verbunden zu gnunetd." #, fuzzy #~ msgid "Full pathname of GNUnet client HOME directory" #~ msgstr "Dateiformat fehlerhaft (kein GNUnet Verzeichnis?)\n" #, fuzzy #~ msgid "# bytes received via TCP6" #~ msgstr "# Bytes empfangen über TCP" #, fuzzy #~ msgid "# bytes sent via TCP6" #~ msgstr "# Bytes gesendet über TCP" #, fuzzy #~ msgid "# bytes dropped by TCP6 (outgoing)" #~ msgstr "# Bytes verworfen von TCP (ausgehend)" #~ msgid "UDP6: Could not determine my public IPv6 address.\n" #~ msgstr "UDP6: Öffentliche IPv6-Adresse konnte nicht ermittelt werden.\n" #, fuzzy #~ msgid "# bytes received via UDP6" #~ msgstr "# Bytes empfangen über UDP" #, fuzzy #~ msgid "# bytes sent via UDP6" #~ msgstr "# Bytes gesendet über UDP" #, fuzzy #~ msgid "# bytes dropped by UDP6 (outgoing)" #~ msgstr "# Bytes verworfen von UDP (outgoing)" #~ msgid "HTTP: Could not determine my public IP address.\n" #~ msgstr "HTTP: öffentliche IP-Adresse konnte nicht ermittelt werden.\n" #, fuzzy #~ msgid "Received malformed message instead of welcome message. Closing.\n" #~ msgstr "" #~ "Es wurde per TCP von einem anderen Knoten eine ungültige Nachricht (Größe " #~ "%u) empfangen. Verbindung wird geschlossen.\n" #, fuzzy #~ msgid "Received malformed message from tcp-peer connection. Closing.\n" #~ msgstr "" #~ "Es wurde per TCP von einem anderen Knoten eine ungültige Nachricht (Größe " #~ "%u) empfangen. Verbindung wird geschlossen.\n" #, fuzzy #~ msgid "TCP: Could not determine my public IP address.\n" #~ msgstr "HTTP: öffentliche IP-Adresse konnte nicht ermittelt werden.\n" #~ msgid "Cannot connect to %u.%u.%u.%u:%u: %s\n" #~ msgstr "Verbindung zu %u.%u.%u.%u:%u fehlgeschlagen: %s\n" #~ msgid "UDP: Could not determine my public IP address.\n" #~ msgstr "UDP: öffentliche IP-Adresse konnte nicht ermittelt werden.\n" #~ msgid "Failed to send message of size %d via UDP to %u.%u.%u.%u:%u: %s\n" #~ msgstr "" #~ "Eine Nachricht der Größe %d konnte nicht per UDP an %u.%u.%u.%u:%u " #~ "versendet werden: %s\n" #, fuzzy #~ msgid "Received malformed message from udp-peer connection. Closing.\n" #~ msgstr "" #~ "Es wurde per TCP von einem anderen Knoten eine ungültige Nachricht (Größe " #~ "%u) empfangen. Verbindung wird geschlossen.\n" #~ msgid "'%s(%s,%s)' succeeded\n" #~ msgstr "'%s(%s,%s)' erfolgreich abgeschlossen\n" #~ msgid "'%s(%s,%s)' failed.\n" #~ msgstr "'%s(%s,%s)' fehlgeschlagen.\n" #~ msgid "" #~ "%s::%s - RPC %s:%p could not be unregistered: another callback registered " #~ "under that name: %p\n" #~ msgstr "" #~ "%s::%s - RPC %s:%p konnte nicht unregistriert werden: ein anderer " #~ "Callback ist unter diesem Namen registiert: %p\n" #~ msgid "%s::%s - RPC %s:%p could not be unregistered: not found\n" #~ msgstr "" #~ "%s::%s - RPC %s:%p konnte nicht unregistriert werden: nicht gefunden\n" #~ msgid "Dropping RPC request %u: message malformed.\n" #~ msgstr "RPC Anfrage %u wird verworfen: Nachricht ist beschädigt.\n" #~ msgid "`%s' called with timeout above 1 hour (bug?)\n" #~ msgstr "`%s' mit einem Timeout von über einer Stunde aufgerufen (Fehler?)\n" #~ msgid "RPC not unregistered: %s:%p\n" #~ msgstr "RPC nicht unregistriert: %s:%p\n" #~ msgid "RPC async reply invalid.\n" #~ msgstr "RPC async Antwort ungültig.\n" #~ msgid "async RPC reply not received.\n" #~ msgstr "async RPC Antwort nicht empfangen.\n" #~ msgid "" #~ "Cover traffic requested but traffic service not loaded. Rejecting " #~ "request.\n" #~ msgstr "" #~ "Verdeckender Netzwerkverkehr angefordert, aber der Verkehrsdienst wurde " #~ "nicht geladen. Anfrage wird abgelehnt.\n" #~ msgid "Cannot satisfy desired level of anonymity, ignoring request.\n" #~ msgstr "" #~ "Gewünschter Grad an Anonymität kann nicht erreicht werden, Anfrage wird " #~ "ignoriert.\n" #~ msgid "# gap requests policy: immediate drop" #~ msgstr "# gap Anfragen mit taktischer Entscheidung: sofortiges Verwerfen" #~ msgid "# gap requests policy: not routed" #~ msgstr "# gap Anfragen mit taktischer Entscheidung: kein Routing" #~ msgid "# gap requests policy: not answered" #~ msgstr "# gap Anfragen mit taktischer Entscheidung: nicht Antworten" #~ msgid "# gap requests processed: attempted add to RT" #~ msgstr "# gap Anfragen verarbeitet: versucht, der RT hinzuzufügen" #~ msgid "# gap requests processed: local result" #~ msgstr "# gap Anfragen verarbeitet: lokales Ergebnis" #~ msgid "# gap requests forwarded (counting each peer)" #~ msgstr "#gap Anfragen weitergeleitet (jeder Knoten gezählt)" #~ msgid "# gap duplicate requests (pending)" #~ msgstr "# gap doppelte Anfragen (unfertig)" #~ msgid "# gap duplicate requests that were re-tried" #~ msgstr "# gap doppelte Anfragen, die wiederholt wurden" #~ msgid "# gap re-try ttl difference (cummulative)" #~ msgstr "# gap Wiederholungs-TTL-Differenz (kummulativ)" #~ msgid "# gap reply duplicates" #~ msgstr "#gap doppelte Antworten" #~ msgid "# gap routing slots currently in use" #~ msgstr "# gap Routingschächte im Moment in Verwendung" #, fuzzy #~ msgid "# gap rewards pending" #~ msgstr "# gap doppelte Anfragen (unfertig)" #, fuzzy #~ msgid "# gap response weights" #~ msgstr "# gap falsche Antworten" #~ msgid "" #~ "Traffic service failed to load; gap cannot ensure cover-traffic " #~ "availability.\n" #~ msgstr "" #~ "Verkehrsdienst konnte nicht geladen werden, GAP kann keinen verdeckenden " #~ "Netzwerkverkehr sicherstellen.\n" #~ msgid "`%s' registering handlers %d %d\n" #~ msgstr "`%s' registriert Handler %d %d\n" #~ msgid "" #~ "set interval for availability of updates to SECONDS (for namespace " #~ "insertions only)" #~ msgstr "" #~ "Intervall der Verfügbarkeit von Updates auf SECONDS setzen (nur für das " #~ "Einfügen in Namespaces)" #~ msgid "" #~ "specifies this as an aperiodic but updated publication (for namespace " #~ "insertions only)" #~ msgstr "" #~ "Dies als unregelmäßige aber aktualisierbare Veröffentlichung kennzeichnen " #~ "(nur für das Einfügen in Namespaces)" #~ msgid "specify creation time for SBlock (see man-page for format)" #~ msgstr "Erstellungszeit für den SBLOCK angeben (s. Manpage zum Format)" #~ msgid "" #~ "ID of the previous version of the content (for namespace update only)" #~ msgstr "" #~ "ID der vorherigen Version des Inhalts (nur für das Einfügen in Namespaces)" #~ msgid "Parsing time failed. Use `%s' format.\n" #~ msgstr "Das Parsen der Zeit schlug fehl. Verwenden Sie das `%s' Format.\n" #~ msgid "exit after receiving LIMIT results" #~ msgstr "Abbrechen, nachdem LIMIT Ergebnisse empfangen wurden" #~ msgid "wait DELAY seconds for search results before aborting" #~ msgstr "TIMEOUT Sekunden auf Suchergebnisse warten, bevor abgebrochen wird" #, fuzzy #~ msgid "# FS currently tracked queries from clients" #~ msgstr "# Client Trace-Antworten gesendet" #~ msgid "Indexed file disappeared, deleting block for query `%s'\n" #~ msgstr "" #~ "Indizierte Datei ist verschwunden, Block für Anfrage `%s' wird gelöscht\n" #~ msgid "" #~ "Configuration file must specify directory for storage of FS data in " #~ "section `%s' under `%s'.\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss ein Verzeichnis für die Speicherung von FS " #~ "Daten in der Sektion `%s' unter `%s' angeben.\n" #~ msgid "AND" #~ msgstr "UND" #~ msgid "Error running search (no reason given)." #~ msgstr "Das Starten der Suche schlug fehl (Ursache unbekannt)." #~ msgid "Download failed (no reason given)" #~ msgstr "ECRS Download schlug fehl (Ursache unbekannt)." #~ msgid "Could not unlink temporary file `%s': %s\n" #~ msgstr "Temporäre Datei `%s' konnte nicht gelöscht werden: %s\n" #~ msgid "Write(%d, %p, %d) failed: %s\n" #~ msgstr "Write(%d, %p, %d) schlug fehl: %s\n" #~ msgid "" #~ "Content `%s' seems to be not available on the network (tried %u times).\n" #~ msgstr "" #~ "Inhalt `%s' scheint im Netzwerk nicht verfügbar zu sein (%u mal " #~ "versucht).\n" #~ msgid "Cannot create pseudonym `%s', file `%s' exists.\n" #~ msgstr "" #~ "Pseudonym `%s' kann nicht erstellt werden, da die Datei `%s' bereits " #~ "existiert.\n" #~ msgid "Publication interval for periodic publication changed." #~ msgstr "" #~ "Veröffentlichungsintervall für periodische Veröffentlichung wurde " #~ "geändert." #~ msgid "" #~ "Publishing update for periodically updated content more than a week ahead " #~ "of schedule.\n" #~ msgstr "" #~ "Veröffentlichungsdatum für periodisch aktualisierten Inhalt ist mehr als " #~ "eine Woche früher als geplant.\n" #~ msgid "Message received from peer is invalid.\n" #~ msgstr "Empfangene Nachricht ist ungültig.\n" #~ msgid "Now %d of %d chat clients at this node.\n" #~ msgstr "Jetzt sind %d von %d auf diesem Knoten.\n" #, fuzzy #~ msgid "Invalid data in %s (NCS). Trying to fix (by deletion).\n" #~ msgstr "Ungültige Daten in %s. Korrektur wird versucht (durch Löschung).\n" #, fuzzy #~ msgid "`%s' failed at %s:%d with error `%s' after %llums\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #~ msgid "" #~ "Directory `%s' in directory `%s' does not match naming convention. " #~ "Removed.\n" #~ msgstr "" #~ "Die Datei `%s' im Verzeichnis `%s' entspricht nicht der Namenskonvention. " #~ "Datei wurde entfernt.\n" #~ msgid "Start GNUnet-testbed helper." #~ msgstr "GNUnet-testbed Helfer starten." #~ msgid "Cannot connect to LOOPBACK port %d: %s\n" #~ msgstr "Verbindung zum LOOPBACK port %d schlug fehl: %s\n" #~ msgid "Could not execute `%s': %s\n" #~ msgstr "`%s' konnte nicht ausgeführt werden: %s\n" #~ msgid "No client service started. Trying again in 30 seconds.\n" #~ msgstr "Kein Client Dienst gestartet. Erneuter Versuch in 30 Sekunden.\n" #~ msgid "" #~ "Error (%s) binding the TCP listener to port %d. No proxy service " #~ "started.\n" #~ "Trying again in %d seconds...\n" #~ msgstr "" #~ "Fehler (%s) beim Binden des TCP Listeners an den Port %d. Der Proxy " #~ "Dienst wurde nicht gestartet.\n" #~ "Erneuter Versuch in %d Sekunden...\n" #~ msgid "Rejected unauthorized connection from %u.%u.%u.%u.\n" #~ msgstr "Unauthorisierte Verbindung von %u.%u.%u.%u. wurde abgewiesen.\n" #~ msgid "Protocol violation on socket. Expected command.\n" #~ msgstr "Protokollverletzung auf Socket. Kommando erwartet.\n" #~ msgid "Malformed entry in the configuration in section %s under %s: %s\n" #~ msgstr "" #~ "Beschädigter Eintrag in der Konfigurationsdatei in Sektion %s unter %s: " #~ "%s\n" #~ msgid "Could not send acknowledgement back to client.\n" #~ msgstr "Bestätigung konnte nicht an Client zurück gesendet werden.\n" #~ msgid "size of `%s' message is wrong. Ignoring.\n" #~ msgstr "Größe der `%s' Nachricht ist falsch. Nachricht wird ignoriert.\n" #~ msgid "TESTBED could not generate hello message for protocol %u\n" #~ msgstr "" #~ "Das TESTBED konnte keine Hello Nachricht für das Protokoll %u erzeugen\n" #~ msgid "received invalid `%s' message (empty module name)\n" #~ msgstr "ungültige `%s' Nachricht empfangen (leerer Modulname)\n" #~ msgid "loading module `%s' failed. Notifying client.\n" #~ msgstr "das Laden von Modul `%s' schlug fehl. Client wird benachrichtigt.\n" #~ msgid "unloading module failed. Notifying client.\n" #~ msgstr "das Entladen des Moduls schlug fehl. Client wird benachrichtigt.\n" #~ msgid "'..' is not allowed in file name (%s).\n" #~ msgstr "'..' ist nicht erlaubt in einem Dateinamen (%s).\n" #~ msgid "Empty filename for UPLOAD_FILE message is invalid!\n" #~ msgstr "Leerer Dateiname für UPLOAD_FILE Nachricht ist ungültig!\n" #~ msgid "Filename for UPLOAD_FILE message is not null-terminated (invalid!)\n" #~ msgstr "" #~ "Dateiname für UPLOAD_FILE Nachricht ist nicht Null-terminiert " #~ "(ungültig!)\n" #~ msgid "Invalid message received at %s:%d." #~ msgstr "Ungültige Nachricht empfangen bei %s:%d." #~ msgid "received invalid testbed message of size %u\n" #~ msgstr "ungültige Testbed Nachricht der Größe %u empfangen\n" #~ msgid "" #~ "Received testbed message of type %u but unexpected size %u, expected %u\n" #~ msgstr "" #~ "Empfangene Testbed Nachricht des Typs %u hat die unerwartete Größe %u, es " #~ "wurde %u erwartet\n" #~ msgid "No testbed URL given, not registered.\n" #~ msgstr "" #~ "Keine Testbed URL angegeben, es wurde keine Registrierung vorgenommen.\n" #~ msgid "Could not resolve name of HTTP proxy `%s'.\n" #~ msgstr "Der Name des HTTP Proxies `%s' konnte nicht aufgelöst werden.\n" #~ msgid "Malformed http URL: `%s' at `%s'. Testbed-client not registered.\n" #~ msgstr "" #~ "Beschädigte HTTP URL: `%s' bei `%s'. Testbed-Client wurde nicht " #~ "registriert.\n" #~ msgid "Could not register testbed, host `%s' unknown\n" #~ msgstr "" #~ "Testbed konnte nicht registriert werden, Host `%s' ist nicht bekannt.\n" #~ msgid "Failed so send HTTP request `%s' to host `%s': %s\n" #~ msgstr "Fehler beim Senden der HTTP Anfrage `%s' an Host `%s': %s\n" #~ msgid "Exit register (error: no http response read).\n" #~ msgstr "Abbruch der Registrierung (Fehler: keine HTTP Antwort gelesen).\n" #~ msgid "allows construction of a P2P-testbed (incomplete)" #~ msgstr "Ermöglicht die Konstruktion einer P2P-Testumgebung (inkomplett)" #, fuzzy #~ msgid "`%s' failed at %s:%d in %s with error: %s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #~ msgid "GNUnet configuration assistant" #~ msgstr "GNUnet Konfigurationsassistent" #, fuzzy #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://gnunet.org\n" #~ "and join our community at\n" #~ "\thttps://gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "The GNUnet team" #~ msgstr "" #~ "Willkommen bei GNUnet!\n" #~ "\n" #~ "Dieser Assistent wird Ihnen einige grundlegende Fragen stellen, um GNUnet " #~ "zu konfigurieren.\n" #~ "\n" #~ "Bitte besuchen Sie unsere Homepage\n" #~ "\thttp://gnunet.org\n" #~ "und schließen Sie sich unserer Community an:\n" #~ "\thttps://gnunet.org/drupal/\n" #~ "\n" #~ "Viel Spaß,\n" #~ "\n" #~ "das GNUnet-Team" #~ msgid "Next" #~ msgstr "Weiter" #~ msgid "" #~ "Enter information about your network connection here.\n" #~ "\n" #~ "The \"Network interface\" is the device that connects your computer to " #~ "the internet. This is usually a modem, an ISDN card or a network card in " #~ "case you are using DSL.\n" #~ "\n" #~ "If your provider always assigns the same IP-Address to you (a \"static\" " #~ "IP-Address), enter it into the \"IP-Address\" field. If your IP-Address " #~ "changes every now and then (\"dynamic\" IP-Address) but there's a " #~ "hostname that always points to your actual IP-Address (\"Dynamic DNS\"), " #~ "you can also enter it here.\n" #~ "If in doubt, leave the field empty. GNUnet will then try to determine " #~ "your IP-Address.\n" #~ "\n" #~ "If you are connected to the internet through another computer doing SNAT, " #~ "a router or a \"hardware firewall\" and other computers on the internet " #~ "cannot connect to this computer, check the last option on this page. " #~ "Leave it unchecked on direct connections through modems, ISDN cards and " #~ "DNAT (also known as \"port forwarding\")." #~ msgstr "" #~ "Geben Sie hier Ihre Netzwerkinformationen ein.\n" #~ "\n" #~ "Das \"Netzwerkgerät\" ist das Gerät, das Ihren Computer mit dem Internet " #~ "verbindet. Dies ist normalerweise ein Modem, eine ISDN-Karte oder eine " #~ "Netzwerkkarte für den Fall, dass Sie DSL benutzen.\n" #~ "\n" #~ "Wenn Ihnen Ihr Provider immer die gleiche IP-Adresse zuweist (eine " #~ "\"statische\" IP-Adresse), geben Sie diese in das \"IP-Adresse\"-Feld " #~ "ein. Wenn Ihre IP-Adresse sich hin und wieder ändert (\"dynamische\" IP-" #~ "Adresse), es jedoch einen Hostnamen gibt, der immer auf Ihre aktuelle IP-" #~ "Adresse zeigt (\"Dynamisches DNS\"), so können Sie ihn auch eingeben.\n" #~ "Im Zweifel lassen Sie das Feld leer. GNUnet wird dann versuchen, die IP-" #~ "Adresse automatisch zu bestimmen.\n" #~ "\n" #~ "Wenn Sie nicht direkt mit dem Internet verbunden sind, sondern dies über " #~ "einen anderen Rechner mit SNAT, einem Router oder einer \"Hardware " #~ "Firewall\" geschieht und andere Computer im Internet keine Verbindung mit " #~ "diesem Computer herstellen können, so aktivieren Sie die letzte Option " #~ "auf dieser Seite. Lassen Sie sie jedoch deaktiviert, wenn Sie eine " #~ "direkte Verbindung über ein Modem, eine ISDN-Karte oder einen anderen " #~ "Rechner mit DNAT (auch bekannt als \"Port forwarding\") zum Internet " #~ "haben." #~ msgid "Computer cannot receive inbound connections (SNAT/Firewall)" #~ msgstr "" #~ "Computer kann keine ankommenden Verbindungen akzeptieren (SNAT/Firewall)" #~ msgid "IP-Address/Hostname:" #~ msgstr "IP-Adresse/Hostname:" #, fuzzy #~ msgid "Network interface:" #~ msgstr "Netzwerkgerät:" #~ msgid "" #~ "You can limit GNUnet's ressource usage here.\n" #~ "\n" #~ "\"Bandwidth limitation\" is how much data may be sent per second. If you " #~ "have a flatrate you can set it to the maximum speed of your internet " #~ "connection.\n" #~ "\n" #~ "The \"Max. CPU usage\" is the percentage of processor time GNUnet is " #~ "allowed to use." #~ msgstr "" #~ "Hier können Sie GNUnet's Ressourcennutzung einschränken.\n" #~ "\n" #~ "\"Bandbreitenbeschränkung\" gibt an, wieviele Daten maximal pro Sekunde " #~ "übetragen werden dürfen. Wenn Sie eine Flatrate haben, können Sie diese " #~ "Werte auf die maximal erreichbare Geschwindigkeit Ihrer " #~ "Internetverbindung setzen.\n" #~ "\n" #~ "Die \"Max. CPU Nutzung\" gibt den Prozentsatz an CPU-Zeit an, den GNUnet " #~ "für sich verwenden darf." #~ msgid "Downstream (Bytes/s):" #~ msgstr "Downstream (Bytes/s):" #~ msgid "Upstream (Bytes/s):" #~ msgstr "Upstream (Bytes/s):" #~ msgid "Bandwidth limitation" #~ msgstr "Bandbreitenbeschränkung" #~ msgid "Use denoted bandwidth for GNUnet" #~ msgstr "Angegebene Bandbreite für GNUnet verwenden" #~ msgid "Share denoted bandwidth with other applications" #~ msgstr "Angegebene Bandbreite mit anderen Anwendungen teilen" #~ msgid "Bandwidth sharing" #~ msgstr "Aufteilung der Bandbreite" #~ msgid "Max. CPU usage (%):" #~ msgstr "Max. CPU Nutzung (%):" #~ msgid "CPU usage" #~ msgstr "CPU Nutzung" #~ msgid "Load limitation" #~ msgstr "Lastbeschränkung" #~ msgid "" #~ "GNUnet is able to store data from other peers in your datastore. This is " #~ "useful if an adversary has access to your inserted content and you need " #~ "to deny that the content is yours. With \"content migration\" on, the " #~ "content could have \"migrated\" over the internet to your node without " #~ "your knowledge.\n" #~ "It also helps to spread popular content over different peers to enhance " #~ "availability.\n" #~ "\n" #~ "The GNUnet datastore contains all data that GNUnet generates (index data, " #~ "inserted and migrated content). Its maximum size can be specified below.\n" #~ "\n" #~ "If you are an experienced user, you may want to tweak your GNUnet " #~ "installation using the enhanced configurator.\n" #~ "\n" #~ "After changing the configuration and/or updating GNUnet, it is sometimes " #~ "required to run gnunet-update to update internal data structures. " #~ "Depending on the changes made, this may take some time." #~ msgstr "" #~ "GNUnet ist in der Lage, Daten von anderen Knoten in Ihrem Datenspeicher " #~ "zu speichern. Das ist nützlich, wenn ein Widersacher Zugriff auf Ihre " #~ "eingefügten Inhalte erlangt und Sie abstreiten müssen, dass diese Daten " #~ "Ihnen gehören. Mit \"Inhaltsmigration\" angeschaltet können die Inhalte " #~ "über das Internet von einem anderen Knoten zu Ihrem Rechner ohne Ihr " #~ "Wissen \"gewandert\" sein.\n" #~ "Außerdem hilft es, beliebte Inhalte über verschiedene Netzteilnehmer zu " #~ "verteilen, um so die Verfügbarkeit zu erhöhen.\n" #~ "\n" #~ "Der GNUnet Datenspeicher enthält alle Daten, die GNUnet erzeugt " #~ "(Indexdaten, eingefügte und migrierte Inhalte). Seine maximale Größe kann " #~ "unten angegeben werden.\n" #~ "\n" #~ "Wenn Sie ein fortgeschrittener Benutzer sind, möchten Sie vielleicht " #~ "weitere Feinjustierungen an GNUnet über den \"erweiterten Konfigurator\" " #~ "vornehmen.\n" #~ "Nachdem die Konfiguration verändert und/oder GNUnet upgedated wurde ist " #~ "es manchmal nötig, gnunet-update auszuführen, um interne Datenstrukturen " #~ "zu aktualisieren. Abhängig von den gemachten Änderungen kann dies etwas " #~ "Zeit in Anspruch nehmen." #~ msgid "Store migrated content" #~ msgstr "Migrierte Inhalte speichern" #~ msgid "Maximum datastore size (MB):" #~ msgstr "Maximale Größe des Datenspeichers (MB):" #~ msgid "Start the GNUnet background process on computer startup" #~ msgstr "" #~ "GNUnet Hintergrundprozeß beim Starten des Computers automatisch starten" #~ msgid "Open the enhanced configurator" #~ msgstr "Erweiterten Konfigurator starten" #, fuzzy #~ msgid "Run gnunet-update" #~ msgstr "gnunet-update schlug fehlt!" #, fuzzy #~ msgid "Other settings" #~ msgstr "Weitere Einstellungen" #~ msgid "" #~ "Define the user and the group owning the GNUnet service here.\n" #~ "\n" #~ "For security reasons, it is a good idea to let this setup create a new " #~ "user account and a new group under which the GNUnet service is started at " #~ "system startup.\n" #~ "\n" #~ "However, GNUnet may not be able to access files other than its own. This " #~ "includes files you want to publish in GNUnet. You'll have to grant read " #~ "permissions to the user specified below.\n" #~ "\n" #~ "Leave the fields empty to run GNUnet with system privileges." #~ msgstr "" #~ "Geben Sie den Benutzer und die Gruppe an, der der GNUnet Dienst gehören " #~ "soll.\n" #~ "\n" #~ "Aus Sicherheitsgründen ist es eine gute Idee, dieses Setup ein neues " #~ "Benutzerkonto und eine neue Gruppe anlegen zu lassen, unter der der " #~ "GNUnet Dienst beim Systemstart läuft.\n" #~ "\n" #~ "Natürlich kann GNUnet dann nur auf seine eigenen Dateien zugreifen. Dies " #~ "betrifft auch Dateien, die Sie im GNUnet veröffentlichen möchten. Sie " #~ "müssen dann dem unten angegebenen Benutzerkonto zuerst Leseberechtigungen " #~ "geben.\n" #~ "\n" #~ "Lassen Sie dieses Feld leer, wenn Sie GNUnet mit Systemprivilegien laufen " #~ "lassen möchten." #~ msgid "User account:" #~ msgstr "Benutzerkonto:" #~ msgid "Group:" #~ msgstr "Gruppe:" #, fuzzy #~ msgid "Save configuration" #~ msgstr "GNUnet Konfiguration" #, fuzzy #~ msgid "Show copyright information for gnunet-setup." #~ msgstr "Fehler beim Lesen von Informationen von gnunetd.\n" #, fuzzy #~ msgid "About gnunet-setup" #~ msgstr "gnunet-update ausführen" #, fuzzy #~ msgid "This is the configuration tool for GNUnet." #~ msgstr "" #~ "Einen Wert aus der Konfigurationsdatei auf der Standardausgabe ausgeben" #~ msgid "Not for English ;-)" #~ msgstr "Nils Durner and Christian Grothoff" #, fuzzy #~ msgid "Description" #~ msgstr "Frage" #, fuzzy #~ msgid "Section" #~ msgstr "Frage" #, fuzzy #~ msgid "Option" #~ msgstr "_Optionen" #~ msgid "TRACEKIT: routing table full, trace request dropped\n" #~ msgstr "TRACEKIT: Routing-Tabelle ist voll, Trace-Anfrage wird verworfen\n" #~ msgid "TRACEKIT: received invalid `%s' message\n" #~ msgstr "TRACEKIT: ungültige `%s' Nachricht empfangen\n" #~ msgid "Format specification invalid. Use 0 for user-readable, 1 for dot\n" #~ msgstr "" #~ "Formatangabe ungültig. Verwenden Sie 0 für menschen-lesbar und 1 für dot\n" #~ msgid "Peer `%s' did not report back.\n" #~ msgstr "Knoten `%s' hat sich nicht zurückgemeldet.\n" #~ msgid "" #~ "You must specify the name of a pipe for the SMTP transport in section `" #~ "%s' under `%s'.\n" #~ msgstr "" #~ "Für den SMTP Transport müssen Sie den Namen einer Pipe in Sektion `%s', " #~ "Eintrag `%s' eintragen.\n" #~ msgid "Sending E-mail to `%s' failed.\n" #~ msgstr "Das Senden einer E-Mail an `%s' schlug fehl.\n" #~ msgid "%.*s filter %s (SMTP)" #~ msgstr "%.*s filter %s (SMTP)" #~ msgid "MTU for `%s' is probably too low (fragmentation not implemented!)\n" #~ msgstr "" #~ "MTU für `%s' ist möglicherweise zu gering (Fragmentierung ist nicht " #~ "implementiert!)\n" #, fuzzy #~ msgid "Network configuration: NAT" #~ msgstr "GNUnet Konfiguration" #~ msgid "" #~ "Is this machine behind NAT?\n" #~ "\n" #~ "If you are connected to the internet through another computer doing SNAT, " #~ "a router or a \"hardware firewall\" and other computers on the internet " #~ "cannot connect to this computer, say \"yes\" here. Answer \"no\" on " #~ "direct connections through modems, ISDN cards and DNAT (also known as " #~ "\"port forwarding\")." #~ msgstr "" #~ "Ist diese Maschine hinter NAT?\n" #~ "\n" #~ "Wenn Sie mit dem Internet über einen anderen Computer per SNAT, einem " #~ "Router oder einer \"Hardware Firewall\" verbunden sind und andere " #~ "Computer im Internet keine Verbindung zu diesem Computer herstellen " #~ "können, so sagen Sie hier \"Ja\". Antworten Sie \"Nein\" bei direkten " #~ "Verbindungen über Modem, ISDN-Karten und DNAT (auch bekannt als \"Port " #~ "forwarding\")." #, fuzzy #~ msgid "Configuration of the logging system" #~ msgstr "" #~ "Konfiguration oder die GNUnet Version hat sich geändert. Sie müssen `%s' " #~ "ausführen!\n" #, fuzzy #~ msgid "Run gnunetd as this user." #~ msgstr "gnunet-update ausführen" #, fuzzy #~ msgid "Run gnunetd during system startup?" #~ msgstr "gnunet-update ausführen" #, fuzzy #~ msgid "Path settings" #~ msgstr "Weitere Einstellungen" #~ msgid "specify nickname" #~ msgstr "Spitznamen angeben" #~ msgid "Start GNUnet chat client." #~ msgstr "GNUnet chat client starten" #~ msgid "You must specify a nickname (use option `%s').\n" #~ msgstr "" #~ "Sie müssen einen Spitznamen angeben (verwenden Sie die Option `%s').\n" #~ msgid "mysql datastore" #~ msgstr "mysql Datenspeicher" #, fuzzy #~ msgid "" #~ "`%s' failed at %s:%d with error: I/%s S/%s SC/%s SS/%s SSC/%s U/%s D/%s " #~ "DG/%s\n" #~ msgstr "`%s' schlug bei %s:%d mit dem Fehler %s fehl\n" #~ msgid "Database failed to delete `%s'.\n" #~ msgstr "Die Datenbank konnte `%s' nicht löschen.\n" #, fuzzy #~ msgid "Error log:\n" #~ msgstr "Fehler" #, fuzzy #~ msgid "# bytes received via TCP-OLD" #~ msgstr "# Bytes empfangen über TCP" #, fuzzy #~ msgid "# bytes sent via TCP-OLD" #~ msgstr "# Bytes gesendet über TCP" #, fuzzy #~ msgid "# bytes dropped by TCP-OLD (outgoing)" #~ msgstr "# Bytes verworfen von TCP (ausgehend)" #~ msgid "hello advertisement for protocol %d received.\n" #~ msgstr "Hello Ankündigung für Protokoll %d empfangen.\n" #~ msgid "`%s' failed (%d, %u). Will not send PING.\n" #~ msgstr "`%s' fehlgeschlagen (%d, %u). PING wird nicht gesendet.\n" #~ msgid "Removing hello from peer `%s' (expired %ds ago).\n" #~ msgstr "Hello von Knoten `%s' wird entfernt (lief vor %ds ab).\n" #~ msgid "Waiting for gnunetd to start (%u iterations left)...\n" #~ msgstr "Warte auf den Start von gnunetd (%u Iterationen verbleiben)...\n" #, fuzzy #~ msgid "Deleting expired content. This may take a while.\n" #~ msgstr "Ein neuer Hostkey wird erzeugt (dies kann eine Weile dauern).\n" #~ msgid "User `%s' not known, cannot change UID to it.\n" #~ msgstr "" #~ "Benutzer `%s' ist nicht bekannt, UID kann nicht gewechselt werden.\n" #~ msgid "" #~ "Expected welcome on http connection, got garbage. Closing connection.\n" #~ msgstr "" #~ "Es wurde eine Willkommensnachricht erwartet, tatsächlich wurde jedoch " #~ "keine gesendet. HTTP-Verbindung wird geschlossen.\n" #~ msgid "%s: Rejected connection from blacklisted address %u.%u.%u.%u.\n" #~ msgstr "" #~ "%s: Abgewiesene Verbindung von schwarzgelisteter Adresse %u.%u.%u.%u.\n" #~ msgid "" #~ "Could not bind the HTTP listener to port %d. No transport service " #~ "started.\n" #~ msgstr "" #~ "HTTP-Listener konnte nicht an Port %d gebunden werden. Der Transport " #~ "Dienst wurde nicht gestartet.\n" #~ msgid "Unexpected reply to `%s' operation.\n" #~ msgstr "Unerwartete Antwort zu `%s' Operation.\n" #~ msgid "join table called NAME" #~ msgstr "Tabelle NAME anschließen" #~ msgid "Malformed optional field `%s' received from peer `%s'.\n" #~ msgstr "Ungültiges optionales Feld `%s' empfangen von Knoten `%s'.\n" #~ msgid "Malformed response to `%s' on master table.\n" #~ msgstr "Beschädigte Antwort auf `%s' in Master Tabelle.\n" #~ msgid "Invalid response to `%s' from `%s'\n" #~ msgstr "Ungültige Antwort auf `%s' von `%s'\n" #~ msgid "RPC for `%s' received for table that we do not participate in!\n" #~ msgstr "" #~ "RPC für `%s' empfangen für eine Tabelle, an der wir nicht beteiligt " #~ "sind!\n" #~ msgid "`%s' failed. Terminating connection to client.\n" #~ msgstr "`%s' fehlgeschlagen. Beende Verbindung zu Client.\n" #~ msgid "" #~ "`%s' called with cron job not in queue, adding. This may not be what you " #~ "want.\n" #~ msgstr "" #~ "`%s' aufgerufen wobei Cron Job nicht Warteschlange ist. Er wird " #~ "hinzugefügt. Das ist möglicherweise nicht, was Sie wollen.\n" #~ msgid "" #~ "Share denoted bandwidth with other applications?\n" #~ "\n" #~ "Say \"yes\" here, if you don't want other network traffic to interfere " #~ "with GNUnet's operation, but still wish to constrain GNUnet's bandwidth " #~ "usage to values entered in the previous steps, or if you can't reliably " #~ "measure the maximum capabilities of your connection. \"No\" can be very " #~ "useful if other applications are causing a lot of traffic on your LAN. " #~ "In this case, you do not want to limit the traffic that GNUnet can " #~ "inflict on your internet connection whenever your high-speed LAN gets " #~ "used (e.g. by NFS)." #~ msgstr "" #~ "Angegebene Bandbreite mit anderen Anwendungen teilen?\n" #~ "\n" #~ "Sagen Sie hier \"Ja\", wenn Sie nicht möchten, dass anderer " #~ "Netzwerkverkehr GNUnets Funktion stört aber dennoch GNUnets Bandbreite " #~ "gemäß den Angaben in den vorherigen Schritten einschränken möchten oder " #~ "Sie die maximalen Möglichkeiten Ihrer Internetverbindung nicht " #~ "zuverlässig messen können. \"Nein\" kann nützlich sein, wenn andere " #~ "Anwendungen viel Netzwerkverkehr in Ihrem LAN verursachen. In diesem Fall " #~ "möchten Sie nicht GNUnets Netzwerkverkehr über die Internetverbindung " #~ "einschränken, wann immer Ihre Hochgeschwindigkeits-LAN-Verbindung " #~ "verwendet wird (z.B. durch NFS)." #~ msgid "How much CPU (in %) may be used?" #~ msgstr "Wieviel CPU (in %) darf verwendet werden?" #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "This is the percentage of processor time GNUnet is allowed to use." #~ msgstr "" #~ "Hier können Sie GNUnets Ressourcenverwendung einschränken.\n" #~ "\n" #~ "Dies ist der Prozentsatz an Prozessorzeit, den GNUnet verwenden darf." #~ msgid "" #~ "Store migrated content?\n" #~ "\n" #~ "GNUnet is able to store data from other peers in your datastore. This is " #~ "useful if an adversary has access to your inserted content and you need " #~ "to deny that the content is yours. With \"content migration\" on, the " #~ "content could have \"migrated\" over the internet to your node without " #~ "your knowledge.\n" #~ "It also helps to spread popular content over different peers to enhance " #~ "availability." #~ msgstr "" #~ "Sollen migrierte Inhalte gespeichert werden?\n" #~ "GNUnet ist in der Lage, Daten von anderen Knoten in Ihrem Datenspeicher " #~ "zu speichern. Das ist nützlich, wenn ein Widersacher Zugriff auf Ihre " #~ "eingefügten Inhalte erlangt und Sie abstreiten müssen, dass diese Daten " #~ "Ihnen gehören. Ist die \"Inhaltsmigration\" angeschaltet, so können die " #~ "Inhalte über das Internet von einem anderen Knoten zu Ihrem Rechner ohne " #~ "Ihr Wissen \"gewandert\" sein.\n" #~ "Außerdem hilft es, beliebte Inhalte über verschiedene Netzteilnehmer zu " #~ "verteilen, um so die Verfügbarkeit zu erhöhen." #~ msgid "" #~ "If you are an experienced user, you may want to tweak your GNUnet " #~ "installation using the enhanced configurator.\n" #~ "\n" #~ "Do you want to start it after saving your configuration?" #~ msgstr "" #~ "Wenn Sie ein erfahrener Benutzer sind, so möchten Sie vielleicht Ihre " #~ "GNUnet Installation über den erweiterten Konfigurator optimieren.\n" #~ "\n" #~ "Möchten Sie ihn starten, nachdem Ihre Konfiguration gespeichert wurde?" #~ msgid "" #~ "Unable to save configuration file %s: %s.\n" #~ "\n" #~ "Try again?" #~ msgstr "" #~ "Konfigurationsdatei %s kann nicht gespeichert werden: %s.\n" #~ "\n" #~ "Soll es nochmals versucht werden?" #~ msgid "Failed to send `%s'. Closing connection.\n" #~ msgstr "Fehler beim Senden von `%s'. Verbindung wird geschlossen.\n" #~ msgid "Received invalid `%s' request (size %d)\n" #~ msgstr "Ungültige Anfrage `%s' empfangen (Größe %d)\n" #~ msgid "Received invalid `%s' request (wrong table)\n" #~ msgstr "Ungültige Anfrage `%s' empfangen (falsche Tabelle)\n" #~ msgid "Received unknown request type %d at %s:%d\n" #~ msgstr "Unbekannte Anfrageart %d empfangen bei %s:%d\n" #~ msgid "This client already participates in the given DHT!\n" #~ msgstr "Dieser Client beteiligt sich bereits an der angegebenen DHT!\n" #~ msgid "Cannot leave DHT: table not known!\n" #~ msgstr "DHT kann nicht verlassen werden: Tabelle unbekannt!\n" #~ msgid "gnunetd signaled error in response to `%s' message\n" #~ msgstr "gnunetd gab in Bezug auf die `%s' Nachricht einen Fehler zurück.\n" #~ msgid "Failed to send `%s' message to gnunetd\n" #~ msgstr "Fehler beim Senden der `%s' Nachricht an gnunetd\n" #~ msgid "Join a DHT." #~ msgstr "Einer DHT anschließen." #~ msgid "allow SIZE bytes of memory for the local table" #~ msgstr "SIZE bytes an Speicher für die lokale Tabelle erlauben" #~ msgid "Call to `%s' with value '%.*s' (%d bytes).\n" #~ msgstr "Aufruf von `%s' mit Wert '%.*s' (%d Bytes).\n" #~ msgid "Error joining DHT.\n" #~ msgstr "Fehler beim Beitreten zu der DHT.\n" #~ msgid "Joined DHT. Press CTRL-C to leave.\n" #~ msgstr "Der DHT beigetreten. Drücken Sie STRG-C, um sie zu verlassen.\n" #~ msgid "sendAck failed. Terminating connection to client.\n" #~ msgstr "sendAck fehlgeschlagen. Beende Verbindung zu Client.\n" #, fuzzy #~ msgid "Upload failed (consult logs)." #~ msgstr "ECRS Download schlug fehl (siehe Protokolldateien)." #~ msgid "Could not resolve name of SMTP server `%s': %s" #~ msgstr "Der Name des SMTP servers `%s' konnte nicht aufgelöst werden: %s" #~ msgid "SMTP server send unexpected response at %s:%d.\n" #~ msgstr "Der SMTP server sendete eine unerwartete Antwort bei %s:%d.\n" #~ msgid "" #~ "SMTP server failed to respond with 250 confirmation code to `%s' " #~ "request.\n" #~ msgstr "" #~ "SMTP Server antwortete nicht mit einem 250 Bestätigungscode auf eine `%s' " #~ "Anfrage.\n" #~ msgid "query table called NAME" #~ msgstr "Frage Tabelle mit dem Namen NAME ab" #~ msgid "No commands specified.\n" #~ msgstr "Keine Kommandos angegeben.\n" #~ msgid "Superflous arguments (ignored).\n" #~ msgstr "überflüssige Parameter (werden ignoriert).\n" #~ msgid "Query `%s' had no results.\n" #~ msgstr "Abfrage `%s' hatte keine Ergebnisse.\n" #~ msgid "FSUI persistence: error restoring download\n" #~ msgstr "FSUI Beständigkeit: Fehler beim Wiederherstellen des Downloads\n" #~ msgid "ECRS download suspending." #~ msgstr "ECRS download wird eingefroren." #~ msgid "Upload failed." #~ msgstr "Upload fehlgeschlagen." #~ msgid "Cannot upload directory without using recursion." #~ msgstr "" #~ "Verzeichnis kann nicht ohne die Verwendung von Rekursion hochgeladen " #~ "werden." #, fuzzy #~ msgid "expected `%s' to be a directory!\n" #~ msgstr "`%s' erwartet, dass `%s' ein Verzeichnis ist!\n" #~ msgid "Sorry, no help is available for this option.\n" #~ msgstr "Sorry, für diese Option steht keine Hilfe zur Verfügung.\n" #~ msgid "" #~ "Cannot determine port to bind to. Define in configuration file in " #~ "section `%s' under `%s' or in `%s' under %s/%s.\n" #~ msgstr "" #~ "Der Port, an dem Verbindungen entgegengenommen werden sollen, konnte " #~ "nicht ermittelt werden. Bitte definieren Sie ihn in der " #~ "Konfigurationsdatei in der Sektion `%s' unter `%s' oder in `%s' unter %s/" #~ "%s.\n" #, fuzzy #~ msgid "UDP6: select returned, but ioctl reports %d bytes available!\n" #~ msgstr "" #~ "UDP: select kam zurück aber ioctl berichtet, dass 0 Bytes verfügbar " #~ "sind!\n" #~ msgid "Received invalid UDP6 message from %s:%d, dropping.\n" #~ msgstr "" #~ "Ungültige UDP6 Nachricht von %s:%d empfangen, Nachricht wird ignoriert.\n" #~ msgid "Packet received from %s:%d (UDP6) failed format check." #~ msgstr "" #~ "Die Formatüberprüfung des Pakets, das von %s:%d (UDP6) empfangen wurde, " #~ "schlug fehl." #~ msgid "%s: Rejected connection from blacklisted address %s.\n" #~ msgstr "%s: Zurückgewiesene Verbindung von schwarzgelisteter Adresse %s.\n" #~ msgid "" #~ "Expected welcome message on tcp connection, got garbage (%u, %u). " #~ "Closing.\n" #~ msgstr "" #~ "Es wurde eine Willkommensnachricht erwartet, über die TCP Verbindung " #~ "wurde aber keine gesendet (%u, %u). Verbindung wird geschlossen.\n" #, fuzzy #~ msgid "UDP: select returned, but ioctl reports %d bytes available!\n" #~ msgstr "" #~ "UDP: select kam zurück aber ioctl berichtet, dass 0 Bytes verfügbar " #~ "sind!\n" #~ msgid "Received invalid UDP message from %u.%u.%u.%u:%u, dropping.\n" #~ msgstr "" #~ "Es wurde eine ungültige UDP Nachricht von %u.%u.%u.%u:%u empfangen, " #~ "Nachricht wird ignoriert.\n" #~ msgid "Packet received from %u.%u.%u.%u:%u (UDP) failed format check.\n" #~ msgstr "" #~ "Ein Paket empfangen von %u.%u.%u.%u:%u (UDP) hat ein ungültiges Format.\n" #~ msgid "Expected welcome message on tcp connection, got garbage. Closing.\n" #~ msgstr "" #~ "Es wurde eine Willkommensnachricht erwartet, über die TCP Verbindung " #~ "wurde jedoch keine gesendet. Verbindung wird geschlossen.\n" #~ msgid "" #~ "Received malformed message from tcp6-peer connection. Closing " #~ "connection.\n" #~ msgstr "" #~ "über die TCP6-Verbindung zu einem anderen Knoten wurde eine ungültige " #~ "Nachricht empfangen. Verbindung wird geschlossen.\n" #~ msgid "Version mismatch (`%s' vs. '%*.s'), run gnunet-update!\n" #~ msgstr "" #~ "Versionen stimmen nicht überein (`%s' vs. '%*.s'), lassen Sie gnunet-" #~ "update laufen!\n" #~ msgid "" #~ "Configuration file must specify directory for storing FS data in section `" #~ "%s' under `%s'.\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss in der Sektion `%s' unter `%s' ein " #~ "Verzeichnis angeben, in dem FS Daten gespeichert werden.\n" #~ msgid "" #~ "Configuration file must specify a directory for GNUnet to store per-peer " #~ "data under %s%s\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss unter %s%s ein Verzeichnis angeben, in dem " #~ "GNUnet knotenspezifische Daten speichern kann.\n" #~ msgid "%s `%s' returned no known hosts!\n" #~ msgstr "%s `%s' ergab keine bekannten Knoten!\n" #~ msgid "" #~ "You should specify at least one transport service under option `%s' in " #~ "section `%s'.\n" #~ msgstr "" #~ "Sie sollten mindestens einen Transport Dienst unter der Option `%s' in " #~ "der Sektion `%s' angegeben.\n" #~ msgid "" #~ "specify that the contents of the namespace are of the given MIMETYPE (use " #~ "when creating a new pseudonym)" #~ msgstr "" #~ "Angeben, dass die Inhalte des Namespaces vom angegebenen MIMETYOE sind " #~ "(zu verwenden, wenn ein neues Pseudonym erstellt wird)" #~ msgid "" #~ "specify NAME to be the realname of the user controlling the namespace " #~ "(use when creating a new pseudonym)" #~ msgstr "" #~ "NAME als den Realnamen des Benutzers angeben, der den Namespace verwaltet " #~ "(zu verwenden, wenn ein neues Pseudonym erstellt wird)" #~ msgid "" #~ "use DESCRIPTION to describe the content of the namespace (use when " #~ "creating a new pseudonym)" #~ msgstr "" #~ "DESCRIPTION als Beschreibung der Inhalte des Namespaces verwenden (zu " #~ "verwenden, wenn ein neues Pseudonym erstellt wird)" #~ msgid "" #~ "specify the given URI as an address that contains more information about " #~ "the namespace (use when creating a new pseudonym)" #~ msgstr "" #~ "die angegebene URI als die Adresse angeben, die weitere Informationen " #~ "über den Namespace enthält (zu verwenden, wenn ein neues Pseudonym " #~ "erstellt wird)" #~ msgid "%8u of %8u bytes deleted." #~ msgstr "%8u von %8u Bytes gelöscht." #~ msgid "specify the file to delete from GNUnet (obligatory, file must exist)" #~ msgstr "" #~ "vom GNUnet zu löschende Datei angeben (obgligatorisch, Datei muss " #~ "existieren)" #~ msgid "" #~ "Remove file from GNUnet. The specified file is not removed\n" #~ "from the filesystem but just from the local GNUnet datastore." #~ msgstr "" #~ "Datei auf GNUnet löschen. Die angegebene Datei wird nicht aus dem " #~ "Dateisystem gelöscht, sondern aus dem lokalen GNUnet Datenspeicher." #~ msgid "You must specify a filename (option -f)\n" #~ msgstr "Sie müssen eine Datei angeben (Option -f)\n" #~ msgid "" #~ "Error deleting file %s.\n" #~ "Probably a few blocks were already missing from the database.\n" #~ msgstr "" #~ "Fehler beim Löschen der Datei %s.\n" #~ "Möglicherweise fehlen bereits einige wenige Datenblöcke in der " #~ "Datenbank.\n" #~ msgid "gnunet-directory [OPTIONS] [FILENAMES]" #~ msgstr "gnunet-directory [OPTIONEN] [DATEINAMEN]" #~ msgid "process directories recursively" #~ msgstr "Verzeichnisse rekursiv bearbeiten" #~ msgid "Only one file or directory can be specified at a time.\n" #~ msgstr "Nur eine Datei oder Verzeichnis kann auf einmal angegeben werden.\n" #~ msgid "You must specify a file or directory to upload.\n" #~ msgstr "Sie müssen eine Datei oder Verzeichnis für den Upload angeben.\n" #~ msgid "Not enough arguments. You must specify a keyword or identifier.\n" #~ msgstr "" #~ "Nicht genügend Parameter. Sie müssen ein Schlüsselwort oder einen " #~ "Bezeichner angeben.\n" #~ msgid "LEVEL" #~ msgstr "GRAD" #~ msgid "FILENAME" #~ msgstr "DATEINAME" #~ msgid "" #~ "Configuration file must specify a directory for GNUnet to store per-peer " #~ "data under %s%s.\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss unter %s%s ein Verzeichnis für GNUnet " #~ "angeben, in dem Knotenbezogene Daten gespeichert werden.\n" #~ msgid "Template for gnunet-clients." #~ msgstr "Vorlage für gnunet-clients." #~ msgid "Invalid port \"%s\" in hostlist specification, trying port %d.\n" #~ msgstr "Ungültiger Port \"%s\" in Angabe der Hostlist, versuche Port %d.\n" #~ msgid "Could not download list of peer contacts, host `%s' unknown.\n" #~ msgstr "" #~ "Die Liste mit Knotenkontakten konnte nicht heruntergeladen werden, Host `" #~ "%s' ist unbekannt.\n" #~ msgid "Parsing HTTP response for URL `%s' failed.\n" #~ msgstr "Das Parsen der HTTP Antwort für die URL `%s' schlug fehl.\n" #~ msgid "Could not resolve name of HTTP proxy `%s'. Trying without a proxy.\n" #~ msgstr "" #~ "Der Name des HTTP Proxies `%s' konnte nicht aufgelöst werden. Es wird " #~ "ohne Proxy versucht.\n" #~ msgid "Did not receive reply from gnunetd about traffic conditions.\n" #~ msgstr "Keine Antwort von gnunetd über die Netzwerkverkehrsbedingungen.\n" #~ msgid "" #~ "Configuration file must specify a directory for GNUnet to store per-peer " #~ "data under %s\\%s.\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss unter %s\\%s ein Verzeichnis für GNUnet " #~ "angeben, in dem knotenbezogene Daten gespeichert werden.\n" #~ msgid "Option `%s' makes no sense without option `%s'." #~ msgstr "Option `%s' macht keinen Sinn ohne die Option `%s'." #~ msgid "Updated data for %d applications.\n" #~ msgstr "Daten für %d Anwendungen wurden aktualisiert.\n" #~ msgid "Argument %d: `%s'\n" #~ msgstr "Parameter %d: `%s'\n" #~ msgid "FATAL: Identity plugin not found!\n" #~ msgstr "SCHWERWIEGEND: Identity Plugin wurde nicht gefunden!\n" #~ msgid "You must specify a non-empty set of transports to test!\n" #~ msgstr "" #~ "Sie müssen eine Menge an Transporten angeben, die getestet werden " #~ "sollen!\n" #~ msgid "Available MODEs:\n" #~ msgstr "Verfügbare MODEs:\n" #~ msgid " config\t\ttext-based configuration\n" #~ msgstr " config\t\ttext-basierte Konfiguration\n" #~ msgid " menuconfig\ttext-based menu\n" #~ msgstr "menuconfig\ttext-basiertes Menü\n" #~ msgid " wizard-curses\tBasic text-based graphical configuration\n" #~ msgstr " wizard-curses\tEinfache text-basierte grafische Konfiguration\n" #~ msgid "" #~ " wizard-gtk\tBasic GTK configuration\n" #~ "\n" #~ msgstr "" #~ " wizard-gtk\tEinfache GTK Konfiguration\n" #~ "\n" #~ msgid "gnunet-setup must have write-access to the configuration file `%s'\n" #~ msgstr "" #~ "gnunet-setup benötigt Schreibberechtigungen für die Konfigurationsdatei `" #~ "%s'\n" #~ msgid "" #~ "Can only run wizard to configure gnunetd.\n" #~ "Did you forget the `%s' option?\n" #~ msgstr "" #~ "Der Assistent kann nur zur Einrichtung von gnunetd gestartet werden.\n" #~ "Haben Sie die `%s'-Option vergessen?\n" #~ msgid "Gtk GNUnet Configurator" #~ msgstr "Gtk GNUnet Konfigurator" #~ msgid "_File" #~ msgstr "_Datei" #~ msgid "_Load" #~ msgstr "_öffnen" #~ msgid "Save the config in .config" #~ msgstr "Die Konfiguration in .config speichern" #~ msgid "_Save" #~ msgstr "_Speichern" #~ msgid "_Quit" #~ msgstr "_Beenden" #~ msgid "Show _name" #~ msgstr "_Name anzeigen" #~ msgid "Show range (Y/M/N)" #~ msgstr "Bereich anzeigen (Y/M/N)" #~ msgid "Show _range" #~ msgstr "_Bereich anzeigen" #~ msgid "Show _data" #~ msgstr "_Daten anzeigen" #~ msgid "Show all _options" #~ msgstr "Alle _Optionen anzeigen" #~ msgid "_Help" #~ msgstr "_Hilfe" #~ msgid "_Introduction" #~ msgstr "_Einführung" #~ msgid "Goes up of one level (single view)" #~ msgstr "Bewegt sich eine Ebene nach oben (einfache Ansicht)" #~ msgid "Load" #~ msgstr "Laden" #~ msgid "Save a config file" #~ msgstr "Konfigurationsdatei speichern" #~ msgid "Save" #~ msgstr "Speichern" #~ msgid "Single view" #~ msgstr "Einfache Ansicht" #~ msgid "Single" #~ msgstr "Einfach" #~ msgid "Split view" #~ msgstr "Geteilte Ansicht" #~ msgid "Split" #~ msgstr "Geteilt" #~ msgid "Full view" #~ msgstr "Volle Ansicht" #~ msgid "Full" #~ msgstr "Voll" #~ msgid "Collapse the whole tree in the right frame" #~ msgstr "Den gesamten Baum im rechten Frame kollabieren" #~ msgid "Collapse" #~ msgstr "Kollabieren" #~ msgid "Expand the whole tree in the right frame" #~ msgstr "Den gesamten Baum im rechten Frame expandieren" #~ msgid "Expand" #~ msgstr "Expandieren" #, fuzzy #~ msgid "Introduction" #~ msgstr "_Einführung" #~ msgid "inlining configration file `%s'\n" #~ msgstr "Binde Konfigurationsdatei `%s' ein\n" #~ msgid "" #~ "Configuration file not found. Please run GNUnet Setup (Client " #~ "Configuration) first." #~ msgstr "" #~ "Die Konfigurationsdatei wurde nicht gefunden. Bitte führen Sie zuerst " #~ "GNUnet Setup (Client Konfiguration) aus." #~ msgid "Configuration file `%s' not found. Run `gnunet-setup -d'!\n" #~ msgstr "" #~ "Konfigurationsdatei `%s' nicht gefunden. Bitte führen Sie `gnunet-setup -" #~ "d' aus!\n" #~ msgid "Cron stopped\n" #~ msgstr "Cron angehalten\n" #~ msgid "Caught signal %d.\n" #~ msgstr "Signal %d empfangen.\n" #~ msgid "Invalid network notation (additional characters: `%s')." #~ msgstr "Ungültige Netzwerk Notation (zusätzliche Zeichen: `%s')." #~ msgid "FAILURE" #~ msgstr "FEHLSCHLAG" #~ msgid "MESSAGE" #~ msgstr "MELDUNG" #~ msgid "CRON" #~ msgstr "CRON" #~ msgid "EVERYTHING" #~ msgstr "ALLES" #~ msgid "Invalid LOGLEVEL `%s' specified.\n" #~ msgstr "Ungültiger LOGLEVEL `%s' angegeben.\n" #~ msgid "Failure at %s:%d.\n" #~ msgstr "Fehler bei %s:%d.\n" #~ msgid "" #~ "Cannot determine port of gnunetd server. Define in configuration file in " #~ "section `%s' under `%s'.\n" #~ msgstr "" #~ "Der Port des gnunetd Servers konnte nicht ermittelt werden. Definieren " #~ "Sie ihn in der Sektion `%s' unter `%s'.\n" #~ msgid "" #~ "Usage: %s\n" #~ "%s\n" #~ "\n" #~ msgstr "" #~ "Verwendung: %s\n" #~ "%s\n" #~ "\n" #~ msgid "g" #~ msgstr "g" #~ msgid "t" #~ msgstr "t" #~ msgid "`%s' failed, other side closed connection.\n" #~ msgstr "" #~ "`%s' fehlgeschlagen, die andere Seite hat die Verbindung geschlossen\n" #~ msgid "Attempted path to `%s' was `%s'.\n" #~ msgstr "Versuchter Pfad für `%s' war `%s'.\n" #~ msgid "set verbosity to LEVEL" #~ msgstr "Umfang der Meldungen auf LEVEL setzen" #~ msgid "_License" #~ msgstr "_Lizenz" #~ msgid "Sorry, no help available for this option yet." #~ msgstr "Sorry, für diese Option steht noch keine Hilfe zur Verfügung" #~ msgid "Couldn't find pixmap file: %s" #~ msgstr "Pixmapdatei %s konnte nicht gefunden werden" #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://www.gnunet.org\n" #~ "and join our community at\n" #~ "\thttp://www.gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "the GNUnet team" #~ msgstr "" #~ "Willkommen bei GNUnet!\n" #~ "\n" #~ "Dieser Assistent wird Ihnen einige grundlegende Fragen stellen, um GNUnet " #~ "zu konfigurieren.\n" #~ "\n" #~ "Bitte besuchen Sie unsere Homepage\n" #~ "\thttp://gnunet.org\n" #~ "und schließen Sie sich unserer Community an:\n" #~ "\thttps://gnunet.org/drupal/\n" #~ "\n" #~ "Viel Spaß,\n" #~ "\n" #~ "das GNUnet-Team" #~ msgid "" #~ "You must specify a directory for FS files in the configuration in section " #~ "`%s' under `%s'." #~ msgstr "" #~ "Sie müssen ein Verzeichnis für FS Dateien in der Konfigurationsdatei in " #~ "der Sektion `%s' unter `%s' angeben." #~ msgid "Invalid data in MySQL database. Please verify integrity!\n" #~ msgstr "" #~ "Ungültige Daten in der MySQL Datenbank. Bitte überprüfen Sie die " #~ "Integrität!\n" #~ msgid "SQL Database corrupt, ignoring result.\n" #~ msgstr "SQL Datenbank beschädigt, Ergebnis wird ignoriert.\n" #~ msgid "Invalid data in database. Please verify integrity!\n" #~ msgstr "" #~ "Es befinden sich ungültige Daten in Datenbank. Bitte überprüfen Sie die " #~ "Integrität!\n" #~ msgid "menuconfig is not available\n" #~ msgstr " menuconfig ist nicht verfügbar\n" #~ msgid "wizard-curses is not available\n" #~ msgstr "wizard-curses ist nicht verfügbar\n" #~ msgid "wizard-gtk is not available\n" #~ msgstr "wizard-gtk ist nicht verfügbar\n" #~ msgid "" #~ "Indexing file `%s' failed. Check file permissions and consult your GNUnet " #~ "server's logs.\n" #~ msgstr "" #~ "Indizierung der Datei `%s' schlug fehl. Bitte prüfen Sie die " #~ "Dateiberechtigungen und ziehen Sie die Protokolldateien des GNUnet-" #~ "Servers zu Rate.\n" #~ msgid "Show _debug info" #~ msgstr "_Debug Informationen anzeigen" #~ msgid "" #~ "USAGE: gnunet-setup MODULE\n" #~ "\n" #~ "MODULE\n" #~ " recreate\trecreate configuration files\n" #~ " config\t\ttext-based configuration\n" #~ " menuconfig\ttext-based menu\n" #~ " gconfig\tGTK configuration\n" #~ " wizard-curses\tBasic text-based graphical configuration\n" #~ " wizard-gtk\tBasic GTK configuration\n" #~ "\n" #~ msgstr "" #~ "Verwendung: gnunet-setup MODUL\n" #~ "\n" #~ "MODUL\n" #~ " recreate\tKonfigurationsdateien neu erzeugen\n" #~ " config\t\tText-basierte Konfiguration\n" #~ " menuconfig\tText-basiertes Menü\n" #~ " gconfig\tGTK Konfiguration\n" #~ " wizard-curses\tEinfache text-basierte grafische Konfiguration\n" #~ " wizard-gtk\tEinfache GTK Konfiguration\n" #~ "\n" #~ msgid "Please specify a path where the configuration files will be stored." #~ msgstr "" #~ "Bitte geben Sie den Pfad an, wohin die Konfigurationsdateien gespeichert " #~ "werden." #~ msgid "Session with peer `%s' confirmed, but I cannot connect! (bug?)\n" #~ msgstr "" #~ "Sitzung mit Knoten `%s' ist bestätigt es kann jedoch nicht verbunden " #~ "werden! (Bug?)\n" #~ msgid "LOGLEVEL not specified, that is not ok.\n" #~ msgstr "LOGLEVEL wurde nicht angegeben, das ist nicht in Ordnung.\n" #~ msgid "" #~ "Interfaces string (%s) in configuration section `%s' under `%s' is " #~ "malformed.\n" #~ msgstr "" #~ "Geräteangabe (%s) in der Konfigurationssektion `%s' unter `%s' ist " #~ "beschädigt.\n" #~ msgid "" #~ "No network interfaces specified in the configuration file in section `%s' " #~ "under `%s'.\n" #~ msgstr "" #~ "Es sind keine Netzwerkgeräte in der Konfigurationsdatei in der Sektion " #~ "'%s' unter `%s' definiert.\n" #~ msgid "Failed to parse interface data `%s' output at %s:%d.\n" #~ msgstr "Fehler beim Parsen der Gerätedaten `%s' Ausgabe bei %s:%d.\n" #~ msgid "Could not decoding file `%s' at %s:%d.\n" #~ msgstr "Datei `%s' konnte nicht dekodiert werden bei %s:%d.\n" #~ msgid "" #~ "Configuration file must specify directory for network identities in " #~ "section %s under %s.\n" #~ msgstr "" #~ "Die Konfigurationsdatei muss in Sektion %s unter %s ein Verzeichnis für " #~ "Identitäten angeben.\n" #~ msgid "Sender %u.%u.%u.%u is blacklisted, dropping message.\n" #~ msgstr "" #~ "Sender %u.%u.%u.%u steht auf schwarzer Liste, Nachricht wird ignoriert.\n" #~ msgid "Sender %s is blacklisted, dropping message.\n" #~ msgstr "Sender %s steht auf schwarzer Liste, Nachricht wird ignoriert.\n" #~ msgid "Removed file `%s' containing invalid peer advertisement.\n" #~ msgstr "" #~ "Datei `%s' enthielt eine ungültige Knotenbekanntmachung und wurde " #~ "entfernt.\n" #~ msgid "Removed invalid HELO file `%s'\n" #~ msgstr "Ungültige HELO Datei `%s' wurde entfernt.\n" #~ msgid "Could not determine IP address of the local machine!\n" #~ msgstr "IP-Adresse der lokalen Maschiene konnte nicht ermittelt werden!\n" #~ msgid "Could not determine IP(v6) address of the local machine!\n" #~ msgstr "" #~ "IP(v6)-Adresse der lokalen Maschiene konnte nicht ermittelt werden!\n" #~ msgid "" #~ "Could not find IP(v6) for this host. Please provide the IP in the " #~ "configuration file.\n" #~ msgstr "" #~ "IP(v6) dieses Hosts konnte nicht ermittelt werden. Bitte geben Sie die IP " #~ "in der Konfigurationsdatei an.\n" #~ msgid "Save _as" #~ msgstr "Speichern _unter" #~ msgid "Save the config in a file" #~ msgstr "Die Konfiguration in einer Datei speichern" #~ msgid "Error: can't open Service Control Manager: %s (%i)\n" #~ msgstr "Fehler: der Dienstemanager konnte nicht geöffnet werden: %s (%i)\n" #~ msgid "Error: can't create service: %s (#%i)\n" #~ msgstr "Fehler: Dienst konnte nicht erzeugt werden: %s (#%i)\n" gnunet-0.10.1/po/sv.gmo0000644000175000017500000000752712320736475011610 00000000000000Þ•*l;¼¨©»Íæ-H%f-Œ.º é& 1QKq%½ãéï/5;R7ŽÆ)Þ+14f+n$š1¿ñ'óA_ad#fŠv¥ 0 B Y v . ¿ %Ý . /2 b &ƒ ª Ä `Þ /? o {  ˜ 1 Ï >î 6- d )} /§ 7× 3(K6t«"­ÐDÒ>(  %'# &*)" $  !# bytes decrypted# bytes encrypted# bytes received via TCP%s: illegal option -- %c %s: invalid option -- %c %s: option `%c%s' does not allow an argument %s: option `%s' is ambiguous %s: option `%s' requires an argument %s: option `--%s' does not allow an argument %s: option `-W %s' does not allow an argument %s: option `-W %s' is ambiguous %s: option requires an argument -- %c %s: unrecognized option `%c%s' %s: unrecognized option `--%s' Arguments mandatory for long options are also mandatory for short options. Cannot change user/group to `%s': %s DEBUGERRORI am peer `%s'. INFOInitialization of plugin mechanism failed: %s! Invalid format for IP: `%s' Invalid network notation ('/%d' is not legal in IPv4 CIDR).Invalid network notation (does not end with ';': `%s') No keywords specified! Print statistics about GNUnet operations.SMTP filter string to long, capped to `%s' Trying to use file `%s' for MySQL configuration. WARNINGYou must pass a number to the `%s' option. `%s' failed at %s:%d with error: %s `%s' failed on file `%s' at %s:%d with error: %s bdownload a GNUnet directory recursivelyhlibgcrypt has not the expected version (version %s is required). mmssspecify the priority of the contentwrite the file to FILENAMEProject-Id-Version: GNUnet 0.7.0b Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org POT-Creation-Date: 2014-04-08 11:11+0200 PO-Revision-Date: 2006-01-21 17:16+0100 Last-Translator: Daniel Nylander Language-Team: Swedish Language: sv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # byte dekrypterade# byte krypterade# byte mottogs via TCP%s: otillÃ¥ten flagga -- %c %s: ogiltig flagga -- %c %s: flagga "%c%s" tillÃ¥ter inte ett argument %s: flagga "%s" är tvetydig %s: flagga "%s" kräver ett argument %s: flagga "--%s" tillÃ¥ter inte ett argument %s: flagga "-W %s" tillÃ¥ter inte ett argument %s: flagga "-W %s" är tvetydig %s: flagga kräver ett argument -- %c %s: okänd flagga "%c%s" %s: okänd flagga "--%s" Argument som är obligatoriska för lÃ¥nga flaggor är ocksÃ¥ obligatoriska för korta flaggor. Kan inte ändra användare/grupp till "%s": %s FELSÖKNINGFELJag är ändpunkt "%s". INFOInitiering av insticksmekanism misslyckades: %s! Ogiltigt format för IP: "%s" Ogiltig nätverksnotation ("/%d" är inte giltig i IPv4 CIDR).Ogiltig nätverksnotation (slutar inte med ";": "%s") Inga nyckelord angivna! Skriv ut statistik om GNUnet-operationer.SMTP-filtersträng för lÃ¥ng, kapad till "%s" Försöker använda fil "%s" för MySQL-konfiguration. VARNINGDu mÃ¥ste skicka med ett nummer till flaggan "%s". "%s" misslyckades vid %s:%d med fel: %s "%s" misslyckades för fil "%s" vid %s:%d med fel: %s bhämta en GNUnet-katalog rekursivthlibgcrypt har inte den förväntande versionen (version %s krävs). mmssange prioritet för innehÃ¥lletskriv filen till FILNAMNgnunet-0.10.1/po/gnunet.pot0000644000175000017500000063025412320736474012476 00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR Christian Grothoff # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n" "POT-Creation-Date: 2014-04-08 11:11+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/arm/arm_api.c:337 msgid "Client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/arm_monitor_api.c:321 msgid "" "Monitoring client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/gnunet-arm.c:164 #, c-format msgid "Failed to remove configuration file %s\n" msgstr "" #: src/arm/gnunet-arm.c:170 #, c-format msgid "Failed to remove servicehome directory %s\n" msgstr "" #: src/arm/gnunet-arm.c:216 src/testbed/gnunet-service-testbed_peers.c:1013 msgid "Message was sent successfully" msgstr "" #: src/arm/gnunet-arm.c:218 msgid "Misconfiguration (can not connect to the ARM service)" msgstr "" #: src/arm/gnunet-arm.c:220 src/testbed/gnunet-service-testbed_peers.c:1017 msgid "We disconnected from ARM before we could send a request" msgstr "" #: src/arm/gnunet-arm.c:222 src/testbed/gnunet-service-testbed_peers.c:1019 msgid "ARM API is busy" msgstr "" #: src/arm/gnunet-arm.c:224 msgid "Request does not fit into a message" msgstr "" #: src/arm/gnunet-arm.c:226 src/testbed/gnunet-service-testbed_peers.c:1023 msgid "Request timed out" msgstr "" #: src/arm/gnunet-arm.c:228 src/testbed/gnunet-service-testbed_peers.c:1025 msgid "Unknown request status" msgstr "" #: src/arm/gnunet-arm.c:244 src/testbed/gnunet-service-testbed_peers.c:1041 #, c-format msgid "%s is stopped" msgstr "" #: src/arm/gnunet-arm.c:246 src/testbed/gnunet-service-testbed_peers.c:1043 #, c-format msgid "%s is starting" msgstr "" #: src/arm/gnunet-arm.c:248 src/testbed/gnunet-service-testbed_peers.c:1045 #, c-format msgid "%s is stopping" msgstr "" #: src/arm/gnunet-arm.c:250 src/testbed/gnunet-service-testbed_peers.c:1047 #, c-format msgid "%s is starting already" msgstr "" #: src/arm/gnunet-arm.c:252 src/testbed/gnunet-service-testbed_peers.c:1049 #, c-format msgid "%s is stopping already" msgstr "" #: src/arm/gnunet-arm.c:254 src/testbed/gnunet-service-testbed_peers.c:1051 #, c-format msgid "%s is started already" msgstr "" #: src/arm/gnunet-arm.c:256 src/testbed/gnunet-service-testbed_peers.c:1053 #, c-format msgid "%s is stopped already" msgstr "" #: src/arm/gnunet-arm.c:258 src/testbed/gnunet-service-testbed_peers.c:1055 #, c-format msgid "%s service is not known to ARM" msgstr "" #: src/arm/gnunet-arm.c:260 src/testbed/gnunet-service-testbed_peers.c:1057 #, c-format msgid "%s service failed to start" msgstr "" #: src/arm/gnunet-arm.c:262 #, c-format msgid "%s service cannot be started because ARM is shutting down" msgstr "" #: src/arm/gnunet-arm.c:264 src/testbed/gnunet-service-testbed_peers.c:1061 #, c-format msgid "%.s Unknown result code." msgstr "" #: src/arm/gnunet-arm.c:297 msgid "Fatal error initializing ARM API.\n" msgstr "" #: src/arm/gnunet-arm.c:326 src/arm/gnunet-arm.c:335 #, c-format msgid "Failed to start the ARM service: %s\n" msgstr "" #: src/arm/gnunet-arm.c:369 #, c-format msgid "Failed to send a stop request to the ARM service: %s\n" msgstr "" #: src/arm/gnunet-arm.c:379 #, c-format msgid "Failed to stop the ARM service: %s\n" msgstr "" #: src/arm/gnunet-arm.c:421 #, c-format msgid "Failed to send a request to start the `%s' service: %%s\n" msgstr "" #: src/arm/gnunet-arm.c:431 #, c-format msgid "Failed to start the `%s' service: %s\n" msgstr "" #: src/arm/gnunet-arm.c:468 #, c-format msgid "Failed to send a request to kill the `%s' service: %%s\n" msgstr "" #: src/arm/gnunet-arm.c:479 #, c-format msgid "Failed to kill the `%s' service: %s\n" msgstr "" #: src/arm/gnunet-arm.c:517 #, c-format msgid "Failed to request a list of services: %s\n" msgstr "" #: src/arm/gnunet-arm.c:525 msgid "Error communicating with ARM. ARM not running?\n" msgstr "" #: src/arm/gnunet-arm.c:530 msgid "Running services:\n" msgstr "" #: src/arm/gnunet-arm.c:612 #, c-format msgid "Now only monitoring, press CTRL-C to stop.\n" msgstr "" #: src/arm/gnunet-arm.c:643 #, c-format msgid "Stopped %s.\n" msgstr "" #: src/arm/gnunet-arm.c:646 #, c-format msgid "Starting %s...\n" msgstr "" #: src/arm/gnunet-arm.c:649 #, c-format msgid "Stopping %s...\n" msgstr "" #: src/arm/gnunet-arm.c:660 #, c-format msgid "Unknown status %u for service %s.\n" msgstr "" #: src/arm/gnunet-arm.c:724 msgid "stop all GNUnet services" msgstr "" #: src/arm/gnunet-arm.c:726 msgid "start a particular service" msgstr "" #: src/arm/gnunet-arm.c:728 msgid "stop a particular service" msgstr "" #: src/arm/gnunet-arm.c:730 msgid "start all GNUnet default services" msgstr "" #: src/arm/gnunet-arm.c:733 msgid "stop and start all GNUnet default services" msgstr "" #: src/arm/gnunet-arm.c:736 msgid "delete config file and directory on exit" msgstr "" #: src/arm/gnunet-arm.c:739 msgid "monitor ARM activities" msgstr "" #: src/arm/gnunet-arm.c:741 msgid "don't print status messages" msgstr "" #: src/arm/gnunet-arm.c:744 msgid "timeout in MSECS milliseconds for completing current operation" msgstr "" #: src/arm/gnunet-arm.c:746 msgid "list currently running services" msgstr "" #: src/arm/gnunet-arm.c:748 msgid "don't let gnunet-service-arm inherit standard output" msgstr "" #: src/arm/gnunet-arm.c:750 msgid "don't let gnunet-service-arm inherit standard error" msgstr "" #: src/arm/gnunet-arm.c:761 msgid "Control services and the Automated Restart Manager (ARM)" msgstr "" #: src/arm/gnunet-service-arm.c:266 msgid "Could not send status result to client\n" msgstr "" #: src/arm/gnunet-service-arm.c:302 msgid "Could not send list result to client\n" msgstr "" #: src/arm/gnunet-service-arm.c:529 #, c-format msgid "Failed to start service `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:540 #, c-format msgid "Starting service `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:639 #, c-format msgid "Unable to create socket for service `%s': %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:661 #, c-format msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:695 #, c-format msgid "ARM now monitors connections to service `%s' at `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:831 #, c-format msgid "Preparing to stop `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:1100 #, c-format msgid "Restarting service `%s'.\n" msgstr "" #: src/arm/gnunet-service-arm.c:1193 msgid "exit" msgstr "" #: src/arm/gnunet-service-arm.c:1198 msgid "signal" msgstr "" #: src/arm/gnunet-service-arm.c:1203 msgid "unknown" msgstr "" #: src/arm/gnunet-service-arm.c:1209 #, c-format msgid "Service `%s' took %s to terminate\n" msgstr "" #: src/arm/gnunet-service-arm.c:1231 #, c-format msgid "Service `%s' terminated normally, will restart at any time\n" msgstr "" #: src/arm/gnunet-service-arm.c:1246 #, c-format msgid "Service `%s' terminated with status %s/%d, will restart in %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:1500 #, c-format msgid "Starting default services `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:1511 #, c-format msgid "Default service `%s' not configured correctly!\n" msgstr "" #: src/arm/gnunet-service-arm.c:1524 msgid "" "No default services configured, GNUnet will not really start right now.\n" msgstr "" #: src/arm/mockup-service.c:41 msgid "Initiating shutdown as requested by client.\n" msgstr "" #: src/ats/ats_api_performance.c:468 #, c-format msgid "Received %s message\n" msgstr "" #: src/ats/ats_api_performance.c:511 #, c-format msgid "Received last message for %s \n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2199 src/ats/gnunet-ats-solver-eval.c:2233 #: src/ats/gnunet-service-ats_addresses.c:1980 #: src/ats/gnunet-service-ats_addresses.c:2024 #, c-format msgid "" "Could not load quota for network `%s': `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2205 #: src/ats/gnunet-service-ats_addresses.c:1987 #, c-format msgid "Outbound quota configure for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2212 #: src/ats/gnunet-service-ats_addresses.c:1995 #, c-format msgid "" "No outbound quota configured for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2239 #: src/ats/gnunet-service-ats_addresses.c:2031 #, c-format msgid "Inbound quota configured for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2246 #: src/ats/gnunet-service-ats_addresses.c:2039 #, c-format msgid "" "No outbound quota configure for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2671 #: src/ats-tests/gnunet-solver-eval.c:919 msgid "solver to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2674 src/ats/gnunet-ats-solver-eval.c:2677 #: src/ats-tests/gnunet-solver-eval.c:922 #: src/ats-tests/gnunet-solver-eval.c:925 msgid "experiment to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2680 msgid "print logging" msgstr "" #: src/ats/gnunet-service-ats_addresses.c:2217 #, c-format msgid "Initializing solver `%s '`%s'\n" msgstr "" #: src/ats/gnunet-service-ats_addresses.c:2220 #, c-format msgid "Failed to initialize solver `%s'!\n" msgstr "" #: src/ats/gnunet-service-ats_addresses.c:2243 msgid "Failed to initialize solver!\n" msgstr "" #: src/ats/plugin_ats_mlp.c:892 msgid "Problem size too large, cannot allocate memory!\n" msgstr "" #: src/ats/plugin_ats_mlp.c:1329 #, c-format msgid "Adding address for peer `%s' multiple times\n" msgstr "" #: src/ats/plugin_ats_mlp.c:1376 #, c-format msgid "Updating address property `%s' for peer `%s' %p not added before\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2122 #, c-format msgid "" "Adjusting inconsistent outbound quota configuration for network `%s', is " "%llu must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2131 #, c-format msgid "" "Adjusting inconsistent inbound quota configuration for network `%s', is %llu " "must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2142 #, c-format msgid "" "Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2150 #, c-format msgid "" "Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2161 #, c-format msgid "Using default quota configuration for network `%s' (in/out) %llu/%llu\n" msgstr "" #: src/ats/plugin_ats_proportional.c:1511 #, c-format msgid "Invalid network type `%u' `%s': Disconnect!\n" msgstr "" #: src/ats-tests/ats-testing.c:72 msgid "Benchmarking done\n" msgstr "" #: src/ats-tests/ats-testing.c:105 #, c-format msgid "Failed to connect peer 0 and %u\n" msgstr "" #: src/ats-tests/ats-testing.c:413 #, c-format msgid "Connected master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:419 #, c-format msgid "Failed to connect master peer [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:450 msgid "Connecting peers on CORE level\n" msgstr "" #: src/ats-tests/ats-testing.c:461 #, c-format msgid "Connecting master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:470 #, c-format msgid "Could not connect master [%u] and slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:490 src/ats-tests/ats-testing.c:671 msgid "Initialization failed, shutdown\n" msgstr "" #: src/ats-tests/ats-testing-log.c:842 msgid "Stop logging\n" msgstr "" #: src/ats-tests/ats-testing-log.c:893 #, c-format msgid "Start logging `%s'\n" msgstr "" #: src/ats-tests/gnunet-ats-sim.c:86 #, c-format msgid "" "Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. " "= %u KiB/s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:169 #, c-format msgid "%u address resolutions had a timeout\n" msgstr "" #: src/ats-tool/gnunet-ats.c:171 #, c-format msgid "ATS returned results for %u addresses\n" msgstr "" #: src/ats-tool/gnunet-ats.c:232 #, c-format msgid "" "Peer `%s' plugin `%s', address `%s', `%s' bw out: %u Bytes/s, bw in %u Bytes/" "s, %s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:413 #, c-format msgid "Quota for network `%11s' (in/out): %10s / %10s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:433 src/core/gnunet-core.c:163 #: src/namestore/gnunet-namestore.c:550 src/transport/gnunet-transport.c:1246 #, c-format msgid "Service `%s' is not running\n" msgstr "" #: src/ats-tool/gnunet-ats.c:445 src/transport/gnunet-transport.c:1255 #, c-format msgid "Failed to parse peer identity `%s'\n" msgstr "" #: src/ats-tool/gnunet-ats.c:454 #, c-format msgid "Please select one operation : %s or %s or %s or %s or %s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:470 src/ats-tool/gnunet-ats.c:489 #: src/ats-tool/gnunet-ats.c:506 src/ats-tool/gnunet-ats.c:543 #, c-format msgid "Cannot connect to ATS service, exiting...\n" msgstr "" #: src/ats-tool/gnunet-ats.c:478 src/ats-tool/gnunet-ats.c:495 #, c-format msgid "Cannot issue request to ATS service, exiting...\n" msgstr "" #: src/ats-tool/gnunet-ats.c:515 #, c-format msgid "No preference type given!\n" msgstr "" #: src/ats-tool/gnunet-ats.c:520 #, c-format msgid "No peer given!\n" msgstr "" #: src/ats-tool/gnunet-ats.c:536 msgid "Valid type required\n" msgstr "" #: src/ats-tool/gnunet-ats.c:594 msgid "get list of active addresses currently used" msgstr "" #: src/ats-tool/gnunet-ats.c:596 msgid "get list of all active addresses" msgstr "" #: src/ats-tool/gnunet-ats.c:599 msgid "do not resolve IP addresses to hostnames" msgstr "" #: src/ats-tool/gnunet-ats.c:601 msgid "monitor mode" msgstr "" #: src/ats-tool/gnunet-ats.c:603 msgid "set preference for the given peer" msgstr "" #: src/ats-tool/gnunet-ats.c:605 msgid "print all configured quotas" msgstr "" #: src/ats-tool/gnunet-ats.c:607 msgid "peer id" msgstr "" #: src/ats-tool/gnunet-ats.c:610 msgid "preference type to set: latency | bandwidth" msgstr "" #: src/ats-tool/gnunet-ats.c:612 msgid "preference value" msgstr "" #: src/ats-tool/gnunet-ats.c:615 msgid "verbose output (include ATS address properties)" msgstr "" #: src/ats-tool/gnunet-ats.c:622 msgid "Print information about ATS state" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:437 #: src/secretsharing/gnunet-secretsharing-profiler.c:535 msgid "number of peers in consensus" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:440 msgid "how many peers receive one value?" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:443 #: src/set/gnunet-set-profiler.c:286 src/set/gnunet-set-profiler.c:289 #: src/set/gnunet-set-profiler.c:292 msgid "number of values" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:446 msgid "consensus timeout" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:449 msgid "delay until consensus starts" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:452 #: src/secretsharing/gnunet-secretsharing-profiler.c:550 msgid "be more verbose (print received values)" msgstr "" #: src/conversation/conversation_api.c:557 #: src/conversation/conversation_api_call.c:470 msgid "Connection to conversation service lost, trying to reconnect\n" msgstr "" #: src/conversation/gnunet-conversation.c:264 #, c-format msgid "Incoming call from `%s'. Please /accept #%u or /cancel %u the call.\n" msgstr "" #: src/conversation/gnunet-conversation.c:286 #, c-format msgid "Call from `%s' terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:319 #, c-format msgid "Call from `%s' suspended by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:324 #, c-format msgid "Call from `%s' resumed by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:342 #, c-format msgid "Ego `%s' no longer available, phone is now down.\n" msgstr "" #: src/conversation/gnunet-conversation.c:356 msgid "Failed to setup phone (internal error)\n" msgstr "" #: src/conversation/gnunet-conversation.c:368 #, c-format msgid "" "Phone active on line %u. Type `/help' for a list of available commands\n" msgstr "" #: src/conversation/gnunet-conversation.c:390 #, c-format msgid "Resolved address of `%s'. Now ringing other party.\n" msgstr "" #: src/conversation/gnunet-conversation.c:397 #, c-format msgid "Connection established to `%s'\n" msgstr "" #: src/conversation/gnunet-conversation.c:404 #, c-format msgid "Failed to resolve `%s'\n" msgstr "" #: src/conversation/gnunet-conversation.c:411 msgid "Call terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:417 #, c-format msgid "Connection to `%s' suspended (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:423 #, c-format msgid "Connection to `%s' resumed (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:428 msgid "Error with the call, restarting it\n" msgstr "" #: src/conversation/gnunet-conversation.c:495 #, c-format msgid "Unknown command `%s'\n" msgstr "" #: src/conversation/gnunet-conversation.c:511 #: src/conversation/gnunet-conversation.c:525 #, c-format msgid "Ego `%s' not available\n" msgstr "" #: src/conversation/gnunet-conversation.c:518 #: src/conversation/gnunet-conversation.c:575 msgid "You are calling someone else already, hang up first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:533 #: src/conversation/gnunet-conversation.c:588 #, c-format msgid "You are answering call from `%s', hang up or suspend that call first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:544 msgid "Call recipient missing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:599 msgid "There is no incoming call to accept here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:616 #, c-format msgid "There is no incoming call `%s' to accept right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:647 msgid "We currently do not have an address.\n" msgstr "" #: src/conversation/gnunet-conversation.c:670 #, c-format msgid "We are currently trying to locate the private key for the ego `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:675 #, c-format msgid "We are listening for incoming calls for ego `%s' on line %u.\n" msgstr "" #: src/conversation/gnunet-conversation.c:681 #: src/conversation/gnunet-conversation.c:705 #, c-format msgid "You are having a conversation with `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:686 msgid "" "We had an internal error setting up our phone line. You can still make " "calls.\n" msgstr "" #: src/conversation/gnunet-conversation.c:695 #, c-format msgid "We are trying to find the network address to call `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:700 #, c-format msgid "We are calling `%s', his phone should be ringing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:719 msgid "Calls waiting:\n" msgstr "" #: src/conversation/gnunet-conversation.c:725 #, c-format msgid "#%u: `%s'\n" msgstr "" #: src/conversation/gnunet-conversation.c:753 #: src/conversation/gnunet-conversation.c:768 msgid "There is no call that could be suspended right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:801 #: src/conversation/gnunet-conversation.c:817 msgid "There is no call that could be resumed right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:824 #, c-format msgid "Already talking with `%s', cannot resume a call right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:833 msgid "There is no incoming call to resume here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:850 #, c-format msgid "There is no incoming call `%s' to resume right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:885 msgid "There is no call that could be cancelled right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:893 msgid "There is no incoming call to refuse here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:910 #, c-format msgid "There is no incoming call `%s' to refuse right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:937 msgid "Use `/address' to find out which address this phone should have in GNS" msgstr "" #: src/conversation/gnunet-conversation.c:939 msgid "Use `/call USER.gnu' to call USER" msgstr "" #: src/conversation/gnunet-conversation.c:941 msgid "Use `/accept #NUM' to accept incoming call #NUM" msgstr "" #: src/conversation/gnunet-conversation.c:943 msgid "Use `/suspend' to suspend the active call" msgstr "" #: src/conversation/gnunet-conversation.c:945 msgid "" "Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming " "calls, no argument is needed to resume the current outgoing call." msgstr "" #: src/conversation/gnunet-conversation.c:947 msgid "Use `/cancel' to reject or terminate a call" msgstr "" #: src/conversation/gnunet-conversation.c:949 msgid "Use `/status' to print status information" msgstr "" #: src/conversation/gnunet-conversation.c:951 msgid "Use `/quit' to terminate gnunet-conversation" msgstr "" #: src/conversation/gnunet-conversation.c:953 msgid "Use `/help command' to get help for a specific command" msgstr "" #: src/conversation/gnunet-conversation.c:1151 #, c-format msgid "Name of our ego changed to `%s'\n" msgstr "" #: src/conversation/gnunet-conversation.c:1164 #, c-format msgid "Our ego `%s' was deleted!\n" msgstr "" #: src/conversation/gnunet-conversation.c:1199 msgid "You must specify the NAME of an ego to use\n" msgstr "" #: src/conversation/gnunet-conversation.c:1223 msgid "Failed to start gnunet-helper-w32-console\n" msgstr "" #: src/conversation/gnunet-conversation.c:1249 msgid "sets the NAME of the ego to use for the phone (and name resolution)" msgstr "" #: src/conversation/gnunet-conversation.c:1252 msgid "sets the LINE to use for the phone" msgstr "" #: src/conversation/gnunet-conversation.c:1276 msgid "Enables having a conversation with other GNUnet users." msgstr "" #: src/conversation/gnunet-conversation-test.c:121 #, c-format msgid "" "\n" "End of transmission. Have a GNU day.\n" msgstr "" #: src/conversation/gnunet-conversation-test.c:149 #, c-format msgid "" "\n" "We are now playing your recording back. If you can hear it, your audio " "settings are working..." msgstr "" #: src/conversation/gnunet-conversation-test.c:215 #, c-format msgid "" "We will now be recording you for %s. After that time, the recording will be " "played back to you..." msgstr "" #: src/conversation/gnunet-conversation-test.c:248 #: src/multicast/gnunet-multicast.c:70 src/revocation/gnunet-revocation.c:522 #: src/template/gnunet-template.c:70 msgid "help text" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:305 #, c-format msgid "pa_stream_write() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:587 msgid "gnunet-helper-audio-playback - Got signal, exiting\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:612 #: src/conversation/gnunet-helper-audio-record.c:545 msgid "Connection established.\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:617 #: src/conversation/gnunet-helper-audio-record.c:550 #, c-format msgid "pa_stream_new() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:631 #, c-format msgid "pa_stream_connect_playback() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:644 #: src/conversation/gnunet-helper-audio-record.c:576 #, c-format msgid "Connection failure: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:665 #: src/conversation/gnunet-helper-audio-record.c:599 msgid "Wrong Spec\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:671 #: src/conversation/gnunet-helper-audio-record.c:605 msgid "pa_mainloop_new() failed.\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:685 #: src/conversation/gnunet-helper-audio-record.c:620 msgid "pa_context_new() failed.\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:692 #: src/conversation/gnunet-helper-audio-record.c:626 #, c-format msgid "pa_context_connect() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:698 #: src/conversation/gnunet-helper-audio-record.c:632 msgid "pa_mainloop_run() failed.\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:768 #, c-format msgid "Read error from STDIN: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback-gst.c:325 #, c-format msgid "Read error from STDIN: %d %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:344 #, c-format msgid "opus_encode_float() failed: %s. Aborting\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:420 #, c-format msgid "pa_stream_peek() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:458 msgid "Got signal, exiting.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:483 msgid "Stream successfully created.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:488 #, c-format msgid "pa_stream_get_buffer_attr() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:496 #, c-format msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:500 #, c-format msgid "Using sample spec '%s', channel map '%s'.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:507 #, c-format msgid "Connected to device %s (%u, %ssuspended).\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:516 #, c-format msgid "Stream error: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:563 #, c-format msgid "pa_stream_connect_record() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:676 msgid "ogg_stream_init() failed.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:721 #, c-format msgid "Failed to allocate %d bytes for second packet\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:841 msgid "Mesh audio channel not ready; audio data dropped\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:932 #, c-format msgid "" "No available phone for incoming call on line %u, sending HANG_UP signal\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:1338 #, c-format msgid "Received incoming channel on port %u\n" msgstr "" #: src/conversation/microphone.c:121 msgid "Could not start record audio helper\n" msgstr "" #: src/conversation/plugin_gnsrecord_conversation.c:116 #, c-format msgid "Unable to parse PHONE record `%s'\n" msgstr "" #: src/conversation/speaker.c:75 msgid "Could not start playback audio helper.\n" msgstr "" #: src/core/core_api.c:767 msgid "Client was disconnected from core service, trying to reconnect.\n" msgstr "" #: src/core/gnunet-core.c:80 #, c-format msgid "Peer `%s'\n" msgstr "" #: src/core/gnunet-core.c:110 src/core/gnunet-core.c:138 #: src/transport/gnunet-transport.c:910 src/transport/gnunet-transport.c:930 #, c-format msgid "%24s: %-17s %4s (%u connections in total)\n" msgstr "" #: src/core/gnunet-core.c:112 src/transport/gnunet-transport.c:911 msgid "Connected to" msgstr "" #: src/core/gnunet-core.c:140 src/transport/gnunet-transport.c:931 msgid "Disconnected from" msgstr "" #: src/core/gnunet-core.c:211 src/peerinfo-tool/gnunet-peerinfo.c:694 #, c-format msgid "Invalid command line argument `%s'\n" msgstr "" #: src/core/gnunet-core.c:233 src/transport/gnunet-transport.c:1486 msgid "provide information about all current connections (continuously)" msgstr "" #: src/core/gnunet-core.c:244 msgid "Print information about connected peers." msgstr "" #: src/core/gnunet-service-core.c:105 msgid "Core service is lacking HOSTKEY configuration setting. Exiting.\n" msgstr "" #: src/core/gnunet-service-core.c:126 #, c-format msgid "Core service of `%4s' ready.\n" msgstr "" #: src/core/gnunet-service-core_clients.c:370 msgid "# send requests dropped (disconnected)" msgstr "" #: src/core/gnunet-service-core_clients.c:480 msgid "# messages discarded (session disconnected)" msgstr "" #: src/core/gnunet-service-core_clients.c:526 #, c-format msgid "# bytes of messages of type %u received" msgstr "" #: src/core/gnunet-service-core_kx.c:535 msgid "# bytes encrypted" msgstr "" #: src/core/gnunet-service-core_kx.c:586 msgid "# bytes decrypted" msgstr "" #: src/core/gnunet-service-core_kx.c:673 msgid "# key exchanges initiated" msgstr "" #: src/core/gnunet-service-core_kx.c:713 msgid "# key exchanges stopped" msgstr "" #: src/core/gnunet-service-core_kx.c:810 msgid "# old ephemeral keys ignored" msgstr "" #: src/core/gnunet-service-core_kx.c:816 msgid "# ephemeral keys received" msgstr "" #: src/core/gnunet-service-core_kx.c:850 #, c-format msgid "" "Ephemeral key message from peer `%s' rejected as its validity range does not " "match our system time (%llu not in [%llu,%llu]).\n" msgstr "" #: src/core/gnunet-service-core_kx.c:861 msgid "# EPHEMERAL_KEY messages received" msgstr "" #: src/core/gnunet-service-core_kx.c:951 #: src/transport/gnunet-service-transport_validation.c:1016 msgid "# PING messages received" msgstr "" #: src/core/gnunet-service-core_kx.c:959 msgid "# PING messages dropped (out of order)" msgstr "" #: src/core/gnunet-service-core_kx.c:986 #, c-format msgid "" "Received PING from `%s' for different identity: I am `%s', PONG identity: `" "%s'\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1003 msgid "# PONG messages created" msgstr "" #: src/core/gnunet-service-core_kx.c:1029 msgid "# sessions terminated by timeout" msgstr "" #: src/core/gnunet-service-core_kx.c:1039 msgid "# keepalive messages sent" msgstr "" #: src/core/gnunet-service-core_kx.c:1096 #: src/transport/gnunet-service-transport_validation.c:1328 msgid "# PONG messages received" msgstr "" #: src/core/gnunet-service-core_kx.c:1102 msgid "# PONG messages dropped (connection down)" msgstr "" #: src/core/gnunet-service-core_kx.c:1107 msgid "# PONG messages dropped (out of order)" msgstr "" #: src/core/gnunet-service-core_kx.c:1137 msgid "# PONG messages decrypted" msgstr "" #: src/core/gnunet-service-core_kx.c:1171 msgid "# session keys confirmed via PONG" msgstr "" #: src/core/gnunet-service-core_kx.c:1181 msgid "# timeouts prevented via PONG" msgstr "" #: src/core/gnunet-service-core_kx.c:1188 msgid "# rekey operations confirmed via PONG" msgstr "" #: src/core/gnunet-service-core_kx.c:1328 msgid "# DATA message dropped (out of order)" msgstr "" #: src/core/gnunet-service-core_kx.c:1335 #, c-format msgid "" "Session to peer `%s' went down due to key expiration (should not happen)\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1338 msgid "# sessions terminated by key expiration" msgstr "" #: src/core/gnunet-service-core_kx.c:1383 #: src/core/gnunet-service-core_kx.c:1408 msgid "# bytes dropped (duplicates)" msgstr "" #: src/core/gnunet-service-core_kx.c:1395 msgid "# bytes dropped (out of sequence)" msgstr "" #: src/core/gnunet-service-core_kx.c:1437 msgid "# bytes dropped (ancient message)" msgstr "" #: src/core/gnunet-service-core_kx.c:1445 msgid "# bytes of payload decrypted" msgstr "" #: src/core/gnunet-service-core_kx.c:1480 msgid "# PAYLOAD dropped (out of order)" msgstr "" #: src/core/gnunet-service-core_neighbours.c:168 msgid "# sessions terminated by transport disconnect" msgstr "" #: src/core/gnunet-service-core_neighbours.c:184 #: src/core/gnunet-service-core_neighbours.c:335 msgid "# neighbour entries allocated" msgstr "" #: src/core/gnunet-service-core_neighbours.c:252 msgid "# encrypted bytes given to transport" msgstr "" #: src/core/gnunet-service-core_neighbours.c:418 #, c-format msgid "Unsupported message of type %u (%u bytes) received from peer `%s'\n" msgstr "" #: src/core/gnunet-service-core_sessions.c:216 #: src/core/gnunet-service-core_sessions.c:288 #: src/dht/gnunet-service-dht_neighbours.c:662 #: src/dht/gnunet-service-dht_neighbours.c:727 #: src/dht/gnunet-service-xdht_neighbours.c:1304 #: src/fs/gnunet-service-fs_cp.c:606 src/fs/gnunet-service-fs_cp.c:1501 #: src/topology/gnunet-daemon-topology.c:707 #: src/topology/gnunet-daemon-topology.c:808 #: src/transport/gnunet-service-transport_neighbours.c:917 #: src/transport/gnunet-service-transport_neighbours.c:1141 #: src/transport/gnunet-service-transport_neighbours.c:3142 #: src/transport/gnunet-service-transport_neighbours.c:3438 msgid "# peers connected" msgstr "" #: src/core/gnunet-service-core_sessions.c:255 msgid "# type map refreshes sent" msgstr "" #: src/core/gnunet-service-core_sessions.c:426 msgid "# messages discarded (expired prior to transmission)" msgstr "" #: src/core/gnunet-service-core_typemap.c:110 #: src/core/gnunet-service-core_typemap.c:121 msgid "# type maps received" msgstr "" #: src/core/gnunet-service-core_typemap.c:151 msgid "# updates to my type map" msgstr "" #: src/datacache/datacache.c:115 src/datacache/datacache.c:266 #: src/datastore/gnunet-service-datastore.c:838 msgid "# bytes stored" msgstr "" #: src/datacache/datacache.c:117 src/datacache/datacache.c:268 msgid "# items stored" msgstr "" #: src/datacache/datacache.c:143 src/datacache/datacache.c:150 #: src/datastore/gnunet-service-datastore.c:1487 #: src/datastore/gnunet-service-datastore.c:1498 #, c-format msgid "No `%s' specified for `%s' in configuration!\n" msgstr "" #: src/datacache/datacache.c:184 #, c-format msgid "Loading `%s' datacache plugin\n" msgstr "" #: src/datacache/datacache.c:192 #, c-format msgid "Failed to load datacache plugin for `%s'\n" msgstr "" #: src/datacache/datacache.c:295 msgid "# requests received" msgstr "" #: src/datacache/datacache.c:304 msgid "# requests filtered by bloom filter" msgstr "" #: src/datacache/plugin_datacache_heap.c:406 msgid "Heap datacache running\n" msgstr "" #: src/datacache/plugin_datacache_postgres.c:392 msgid "Postgres datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:69 #: src/datacache/plugin_datacache_sqlite.c:72 #: src/datastore/plugin_datastore_mysql.c:806 #: src/datastore/plugin_datastore_mysql.c:820 #: src/datastore/plugin_datastore_sqlite.c:57 src/mysql/mysql.c:41 #: src/mysql/mysql.c:48 src/mysql/mysql.c:522 src/mysql/mysql.c:531 #: src/mysql/mysql.c:591 src/mysql/mysql.c:607 #: src/namecache/plugin_namecache_postgres.c:52 #: src/namecache/plugin_namecache_sqlite.c:52 #: src/namestore/plugin_namestore_postgres.c:52 #: src/namestore/plugin_namestore_sqlite.c:52 #: src/testbed/generate-underlay-topology.c:47 #: src/testbed/gnunet-daemon-latency-logger.c:52 #: src/testbed/gnunet-daemon-testbed-underlay.c:55 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:51 #: src/util/crypto_mpi.c:39 src/include/gnunet_common.h:602 #: src/include/gnunet_common.h:611 src/scalarproduct/scalarproduct.h:50 #, c-format msgid "`%s' failed at %s:%d with error: %s\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:450 msgid "Sqlite datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:484 #: src/datastore/plugin_datastore_sqlite.c:404 #: src/namecache/plugin_namecache_sqlite.c:295 #: src/namestore/plugin_namestore_sqlite.c:327 msgid "Tried to close sqlite without finalizing all prepared statements.\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:491 #, c-format msgid "Failed to close statement %p: %d\n" msgstr "" #: src/datacache/plugin_datacache_template.c:125 msgid "Template datacache running\n" msgstr "" #: src/datastore/datastore_api.c:310 msgid "Failed to transmit request to drop database.\n" msgstr "" #: src/datastore/datastore_api.c:394 msgid "# queue entry timeouts" msgstr "" #: src/datastore/datastore_api.c:443 msgid "# queue overflows" msgstr "" #: src/datastore/datastore_api.c:471 msgid "# queue entries created" msgstr "" #: src/datastore/datastore_api.c:491 msgid "# Requests dropped from datastore queue" msgstr "" #: src/datastore/datastore_api.c:533 msgid "# datastore connections (re)created" msgstr "" #: src/datastore/datastore_api.c:616 src/scalarproduct/scalarproduct_api.c:279 msgid "# transmission request failures" msgstr "" #: src/datastore/datastore_api.c:638 msgid "# bytes sent to datastore" msgstr "" #: src/datastore/datastore_api.c:770 msgid "Failed to receive status response from database." msgstr "" #: src/datastore/datastore_api.c:784 msgid "Error reading response from datastore service" msgstr "" #: src/datastore/datastore_api.c:796 src/datastore/datastore_api.c:802 msgid "Invalid error message received from datastore service" msgstr "" #: src/datastore/datastore_api.c:806 msgid "# status messages received" msgstr "" #: src/datastore/datastore_api.c:876 msgid "# PUT requests executed" msgstr "" #: src/datastore/datastore_api.c:944 msgid "# RESERVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1005 msgid "# RELEASE RESERVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1065 msgid "# UPDATE requests executed" msgstr "" #: src/datastore/datastore_api.c:1129 msgid "# REMOVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1174 msgid "Failed to receive response from database.\n" msgstr "" #: src/datastore/datastore_api.c:1233 msgid "# Results received" msgstr "" #: src/datastore/datastore_api.c:1300 msgid "# GET REPLICATION requests executed" msgstr "" #: src/datastore/datastore_api.c:1363 msgid "# GET ZERO ANONYMITY requests executed" msgstr "" #: src/datastore/datastore_api.c:1424 msgid "# GET requests executed" msgstr "" #: src/datastore/gnunet-datastore.c:114 #, c-format msgid "Failed to store item: %s, aborting\n" msgstr "" #: src/datastore/gnunet-datastore.c:200 #, c-format msgid "Cannot use the same configuration for source and destination\n" msgstr "" #: src/datastore/gnunet-datastore.c:246 msgid "" "specifies the configuration to use to access an alternative datastore; will " "merge that datastore into our current datastore" msgstr "" #: src/datastore/gnunet-datastore.c:255 msgid "Manipulate GNUnet datastore" msgstr "" #: src/datastore/gnunet-service-datastore.c:351 msgid "# bytes expired" msgstr "" #: src/datastore/gnunet-service-datastore.c:425 msgid "# bytes purged (low-priority)" msgstr "" #: src/datastore/gnunet-service-datastore.c:483 #: src/gns/gnunet-gns-helper-service-w32.c:223 msgid "Transmission to client failed!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:514 #: src/gns/gnunet-gns-helper-service-w32.c:262 msgid "Shutdown in progress, aborting transmission.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:630 msgid "# results found" msgstr "" #: src/datastore/gnunet-service-datastore.c:673 #, c-format msgid "" "Insufficient space (%llu bytes are available) to satisfy `%s' request for " "%llu bytes\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:684 #, c-format msgid "" "The requested amount (%llu bytes) is larger than the cache size (%llu " "bytes)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:688 msgid "" "Insufficient space to satisfy request and requested amount is larger than " "cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:694 msgid "Insufficient space to satisfy request" msgstr "" #: src/datastore/gnunet-service-datastore.c:699 #: src/datastore/gnunet-service-datastore.c:751 #: src/datastore/gnunet-service-datastore.c:964 #: src/datastore/gnunet-service-datastore.c:1421 msgid "# reserved" msgstr "" #: src/datastore/gnunet-service-datastore.c:764 msgid "Could not find matching reservation" msgstr "" #: src/datastore/gnunet-service-datastore.c:850 #, c-format msgid "Need %llu bytes more space (%llu allowed, using %llu)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1010 msgid "# GET requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1022 msgid "# requests filtered by bloomfilter" msgstr "" #: src/datastore/gnunet-service-datastore.c:1050 msgid "# UPDATE requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1080 msgid "# GET REPLICATION requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1113 msgid "# GET ZERO ANONYMITY requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1138 msgid "Content not found" msgstr "" #: src/datastore/gnunet-service-datastore.c:1146 msgid "# bytes removed (explicit request)" msgstr "" #: src/datastore/gnunet-service-datastore.c:1178 msgid "# REMOVE requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1220 #, c-format msgid "Datastore payload inaccurate (%lld < %lld). Trying to fix.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1281 #, c-format msgid "Loading `%s' datastore plugin\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1290 #, c-format msgid "Failed to load datastore plugin for `%s'\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1492 #, c-format msgid "# bytes used in file-sharing datastore `%s'" msgstr "" #: src/datastore/gnunet-service-datastore.c:1503 msgid "# quota" msgstr "" #: src/datastore/gnunet-service-datastore.c:1505 msgid "# cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:1518 #, c-format msgid "Could not use specified filename `%s' for bloomfilter.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1536 #: src/datastore/gnunet-service-datastore.c:1552 #, c-format msgid "Failed to remove bogus bloomfilter file `%s'\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1582 msgid "Failed to initialize bloomfilter.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1611 msgid "Rebuilding bloomfilter. Please be patient.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1616 msgid "Plugin does not support get_keys function. Please fix!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1619 msgid "Bloomfilter construction complete.\n" msgstr "" #: src/datastore/plugin_datastore_heap.c:820 msgid "Heap database running\n" msgstr "" #: src/datastore/plugin_datastore_mysql.c:783 #, c-format msgid "Failed to prepare statement `%s'\n" msgstr "" #: src/datastore/plugin_datastore_mysql.c:791 #, c-format msgid "`%s' for `%s' failed at %s:%d with error: %s\n" msgstr "" #: src/datastore/plugin_datastore_mysql.c:1022 msgid "Mysql database running\n" msgstr "" #: src/datastore/plugin_datastore_postgres.c:824 msgid "Failed to drop table from database.\n" msgstr "" #: src/datastore/plugin_datastore_postgres.c:860 #: src/namecache/plugin_namecache_postgres.c:414 #: src/namestore/plugin_namestore_postgres.c:569 msgid "Postgres database running\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:57 #: src/testbed/generate-underlay-topology.c:50 #: src/testbed/gnunet-daemon-latency-logger.c:55 #: src/testbed/gnunet-daemon-testbed-underlay.c:58 #, c-format msgid "`%s' failed at %s:%u with error: %s" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:255 #: src/namecache/plugin_namecache_sqlite.c:193 #: src/namestore/plugin_namestore_sqlite.c:204 #: src/psycstore/plugin_psycstore_sqlite.c:319 #, c-format msgid "Unable to initialize SQLite: %s.\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:663 msgid "Invalid data in database. Trying to fix (by deletion).\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1156 msgid "sqlite version to old to determine size, assuming zero\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1175 #, c-format msgid "" "Using sqlite page utilization to estimate payload (%llu pages of size %llu " "bytes)\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1215 #: src/namecache/plugin_namecache_sqlite.c:583 #: src/namestore/plugin_namestore_sqlite.c:719 msgid "Sqlite database running\n" msgstr "" #: src/datastore/plugin_datastore_template.c:257 msgid "Template database running\n" msgstr "" #: src/dht/dht_api.c:376 msgid "Failed to connect to the DHT service!\n" msgstr "" #: src/dht/gnunet-dht-get.c:133 #, c-format msgid "" "Result %d, type %d:\n" "%.*s\n" msgstr "" #: src/dht/gnunet-dht-get.c:159 msgid "Must provide key for DHT GET!\n" msgstr "" #: src/dht/gnunet-dht-get.c:165 src/dht/gnunet-dht-monitor.c:225 msgid "Failed to connect to DHT service!\n" msgstr "" #: src/dht/gnunet-dht-get.c:173 msgid "Issueing DHT GET with key" msgstr "" #: src/dht/gnunet-dht-get.c:189 src/dht/gnunet-dht-monitor.c:262 #: src/dht/gnunet-dht-put.c:198 msgid "the query key" msgstr "" #: src/dht/gnunet-dht-get.c:192 msgid "how many parallel requests (replicas) to create" msgstr "" #: src/dht/gnunet-dht-get.c:195 src/dht/gnunet-dht-monitor.c:265 msgid "the type of data to look for" msgstr "" #: src/dht/gnunet-dht-get.c:198 src/dht/gnunet-dht-put.c:210 msgid "how long to execute this query before giving up?" msgstr "" #: src/dht/gnunet-dht-get.c:201 src/dht/gnunet-dht-put.c:201 msgid "use DHT's demultiplex everywhere option" msgstr "" #: src/dht/gnunet-dht-get.c:204 src/dht/gnunet-dht-monitor.c:271 #: src/dht/gnunet-dht-put.c:213 src/fs/gnunet-auto-share.c:753 #: src/fs/gnunet-download.c:328 src/fs/gnunet-publish.c:877 #: src/fs/gnunet-search.c:301 src/fs/gnunet-unindex.c:168 #: src/nse/gnunet-nse-profiler.c:873 msgid "be verbose (print progress information)" msgstr "" #: src/dht/gnunet-dht-get.c:225 msgid "Issue a GET request to the GNUnet DHT, prints results." msgstr "" #: src/dht/gnunet-dht-monitor.c:268 msgid "how long should the monitor command run" msgstr "" #: src/dht/gnunet-dht-monitor.c:293 msgid "Prints all packets that go through the DHT." msgstr "" #: src/dht/gnunet-dht-put.c:118 msgid "PUT request sent with key" msgstr "" #: src/dht/gnunet-dht-put.c:121 msgid "Timeout sending PUT request!\n" msgstr "" #: src/dht/gnunet-dht-put.c:124 msgid "PUT request not confirmed!\n" msgstr "" #: src/dht/gnunet-dht-put.c:153 msgid "Must provide KEY and DATA for DHT put!\n" msgstr "" #: src/dht/gnunet-dht-put.c:160 #, c-format msgid "Could not connect to %s service!\n" msgstr "" #: src/dht/gnunet-dht-put.c:176 #, c-format msgid "Issuing put request for `%s' with data `%s'!\n" msgstr "" #: src/dht/gnunet-dht-put.c:192 msgid "the data to insert under the key" msgstr "" #: src/dht/gnunet-dht-put.c:195 msgid "how long to store this entry in the dht (in seconds)" msgstr "" #: src/dht/gnunet-dht-put.c:204 msgid "how many replicas to create" msgstr "" #: src/dht/gnunet-dht-put.c:207 msgid "the type to insert data as" msgstr "" #: src/dht/gnunet-dht-put.c:236 msgid "Issue a PUT request to the GNUnet DHT insert DATA under KEY." msgstr "" #: src/dht/gnunet-service-dht.c:172 src/dht/gnunet-service-xdht.c:176 msgid "Failed to connect to transport service!\n" msgstr "" #: src/dht/gnunet-service-dht_clients.c:417 #: src/dht/gnunet-service-xdht_clients.c:838 msgid "# GET requests from clients injected" msgstr "" #: src/dht/gnunet-service-dht_clients.c:513 #: src/dht/gnunet-service-xdht_clients.c:927 msgid "# PUT requests received from clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:597 #: src/dht/gnunet-service-xdht_clients.c:1013 msgid "# GET requests received from clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:798 #: src/dht/gnunet-service-xdht_clients.c:1214 msgid "# GET STOP requests received from clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1039 #: src/dht/gnunet-service-xdht_clients.c:498 msgid "# Key match, type mismatches in REPLY to CLIENT" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1052 #: src/dht/gnunet-service-xdht_clients.c:511 msgid "# Duplicate REPLIES to CLIENT request dropped" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1089 #: src/dht/gnunet-service-xdht_clients.c:548 #, c-format msgid "Unsupported block type (%u) in request!\n" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1112 #: src/dht/gnunet-service-xdht_clients.c:571 msgid "# RESULTS queued for clients" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1166 #: src/dht/gnunet-service-dht_clients.c:1209 #: src/dht/gnunet-service-xdht_clients.c:625 #: src/dht/gnunet-service-xdht_clients.c:668 msgid "# REPLIES ignored for CLIENTS (no match)" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1176 #: src/dht/gnunet-service-xdht_clients.c:635 msgid "Could not pass reply to client, message too big!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:68 #: src/dht/gnunet-service-xdht_datacache.c:68 #, c-format msgid "%s request received, but have no datacache!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:78 #: src/dht/gnunet-service-xdht_datacache.c:78 msgid "# ITEMS stored in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:165 #: src/dht/gnunet-service-xdht_datacache.c:165 msgid "# Good RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:176 #: src/dht/gnunet-service-xdht_datacache.c:176 msgid "# Duplicate RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:182 #: src/dht/gnunet-service-xdht_datacache.c:182 msgid "# Invalid RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:188 #: src/dht/gnunet-service-xdht_datacache.c:188 msgid "# Irrelevant RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:200 #: src/dht/gnunet-service-xdht_datacache.c:200 msgid "# Unsupported RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:203 #: src/dht/gnunet-service-xdht_datacache.c:203 #, c-format msgid "Unsupported block type (%u) in local response!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:234 #: src/dht/gnunet-service-xdht_datacache.c:234 msgid "# GET requests given to datacache" msgstr "" #: src/dht/gnunet-service-dht_hello.c:84 #: src/dht/gnunet-service-xdht_hello.c:82 msgid "# HELLOs obtained from peerinfo" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:516 msgid "# Preference updates given to core" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:610 msgid "# FIND PEER messages initiated" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:764 msgid "# Queued messages discarded (peer disconnected)" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:819 #: src/dht/gnunet-service-xdht_neighbours.c:703 msgid "# Bytes transmitted to other peers" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:857 #: src/dht/gnunet-service-xdht_neighbours.c:742 msgid "# Bytes of bandwidth requested from core" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:889 msgid "# requests TTL-dropped" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1093 #: src/dht/gnunet-service-dht_neighbours.c:1130 msgid "# Peers excluded from routing due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1108 #: src/dht/gnunet-service-dht_neighbours.c:1145 msgid "# Peer selection failed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1287 msgid "# PUT requests routed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1316 msgid "# PUT messages queued for transmission" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1323 #: src/dht/gnunet-service-dht_neighbours.c:1440 #: src/dht/gnunet-service-dht_neighbours.c:1543 #: src/dht/gnunet-service-xdht_neighbours.c:794 #: src/dht/gnunet-service-xdht_neighbours.c:860 #: src/dht/gnunet-service-xdht_neighbours.c:919 #: src/dht/gnunet-service-xdht_neighbours.c:981 #: src/dht/gnunet-service-xdht_neighbours.c:1041 msgid "# P2P messages dropped due to full queue" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1405 msgid "# GET requests routed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1432 msgid "# GET messages queued for transmission" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1550 msgid "# RESULT messages queued for transmission" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1636 msgid "# P2P PUT requests received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1639 msgid "# P2P PUT bytes received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1803 msgid "# FIND PEER requests ignored due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1811 msgid "# FIND PEER requests ignored due to lack of HELLO" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1904 msgid "# P2P GET requests received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1907 msgid "# P2P GET bytes received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1961 msgid "# P2P FIND PEER requests processed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1975 msgid "# P2P GET requests ONLY routed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:2052 msgid "# P2P RESULTS received" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:2055 msgid "# P2P RESULT bytes received" msgstr "" #: src/dht/gnunet-service-dht_nse.c:59 src/dht/gnunet-service-xdht_nse.c:59 msgid "# Network size estimates received" msgstr "" #: src/dht/gnunet-service-dht_routing.c:211 msgid "# Good REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:220 msgid "# Duplicate REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:226 msgid "# Invalid REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:232 msgid "# Irrelevant REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:244 msgid "# Unsupported REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:317 msgid "# Entries removed from routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:399 msgid "# Entries added to routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:417 msgid "# DHT requests combined" msgstr "" #: src/dht/gnunet-service-xdht_neighbours.c:1398 #, c-format msgid "" "\n" "SUPU %s, %s, %d,my_identity = %s" msgstr "" #: src/dht/gnunet-service-xdht_neighbours.c:1514 #: src/dht/gnunet-service-xdht_neighbours.c:1524 #: src/dht/gnunet-service-xdht_neighbours.c:1530 #: src/dht/gnunet-service-xdht_neighbours.c:1536 #: src/dht/gnunet-service-xdht_neighbours.c:1545 #, c-format msgid "" "\n" "SUPU %s, %s, %d" msgstr "" #: src/dht/plugin_block_dht.c:138 #, c-format msgid "Block not of type %u\n" msgstr "" #: src/dht/plugin_block_dht.c:145 msgid "Size mismatch for block\n" msgstr "" #: src/dht/plugin_block_dht.c:155 #, c-format msgid "Block of type %u is malformed\n" msgstr "" #: src/dns/dnsparser.c:257 #, c-format msgid "Failed to convert DNS IDNA name `%s' to UTF-8: %s\n" msgstr "" #: src/dns/dnsparser.c:856 #, c-format msgid "Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n" msgstr "" #: src/dns/dnsstub.c:175 #, c-format msgid "Could not bind to any port: %s\n" msgstr "" #: src/dns/dnsstub.c:295 src/dns/dnsstub.c:383 #, c-format msgid "Failed to send DNS request to %s\n" msgstr "" #: src/dns/dnsstub.c:299 #, c-format msgid "Sent DNS request to %s\n" msgstr "" #: src/dns/dnsstub.c:368 #, c-format msgid "Configured DNS exit `%s' is not working / valid.\n" msgstr "" #: src/dns/dnsstub.c:440 #, c-format msgid "Received DNS response that is too small (%u bytes)" msgstr "" #: src/dns/gnunet-dns-monitor.c:355 msgid "only monitor DNS queries" msgstr "" #: src/dns/gnunet-dns-monitor.c:358 msgid "only monitor DNS replies" msgstr "" #: src/dns/gnunet-dns-monitor.c:369 msgid "Monitor DNS queries." msgstr "" #: src/dns/gnunet-dns-redirector.c:236 msgid "set A records" msgstr "" #: src/dns/gnunet-dns-redirector.c:239 msgid "set AAAA records" msgstr "" #: src/dns/gnunet-dns-redirector.c:251 msgid "Change DNS replies to point elsewhere." msgstr "" #: src/dns/gnunet-service-dns.c:456 msgid "# DNS requests answered via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:603 msgid "# DNS exit failed (failed to open socket)" msgstr "" #: src/dns/gnunet-service-dns.c:714 msgid "# External DNS response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:792 msgid "# Client response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:907 msgid "Received malformed IPv4-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:923 msgid "Received malformed IPv6-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:932 #, c-format msgid "Got non-IP packet with %u bytes and protocol %u from TUN\n" msgstr "" #: src/dns/gnunet-service-dns.c:942 msgid "# Non-DNS UDP packet received via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:1009 msgid "# DNS requests received via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:1049 src/exit/gnunet-daemon-exit.c:3514 #, c-format msgid "`%s' must be installed SUID, refusing to run\n" msgstr "" #: src/dns/gnunet-service-dns.c:1069 src/exit/gnunet-daemon-exit.c:3571 msgid "need a valid IPv4 or IPv6 address\n" msgstr "" #: src/dv/gnunet-dv.c:169 msgid "verbose output" msgstr "" #: src/dv/gnunet-dv.c:178 msgid "Print information about DV state" msgstr "" #: src/exit/gnunet-daemon-exit.c:802 #, c-format msgid "Got duplicate service records for `%s:%u'\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:853 msgid "# Bytes transmitted via mesh channels" msgstr "" #: src/exit/gnunet-daemon-exit.c:970 src/exit/gnunet-daemon-exit.c:2397 #: src/exit/gnunet-daemon-exit.c:2654 src/vpn/gnunet-service-vpn.c:1407 #: src/vpn/gnunet-service-vpn.c:1797 src/vpn/gnunet-service-vpn.c:1960 msgid "# ICMPv4 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1007 src/exit/gnunet-daemon-exit.c:2456 #: src/exit/gnunet-daemon-exit.c:2713 src/vpn/gnunet-service-vpn.c:1463 #: src/vpn/gnunet-service-vpn.c:1856 src/vpn/gnunet-service-vpn.c:1993 msgid "# ICMPv6 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1047 msgid "# ICMP packets dropped (not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1054 msgid "ICMP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1130 msgid "UDP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1204 msgid "TCP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1256 msgid "# Packets received from TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:1270 msgid "# Bytes received from TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:1296 msgid "IPv4 packet options received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1323 #, c-format msgid "IPv4 packet with unsupported next header %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1369 #, c-format msgid "IPv6 packet with unsupported next header %d received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1377 #, c-format msgid "Packet from unknown protocol %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1759 msgid "# TCP packets sent via TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:1872 msgid "# TCP service creation requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:1875 src/exit/gnunet-daemon-exit.c:1968 #: src/exit/gnunet-daemon-exit.c:2073 src/exit/gnunet-daemon-exit.c:2321 #: src/exit/gnunet-daemon-exit.c:2570 src/exit/gnunet-daemon-exit.c:2859 #: src/exit/gnunet-daemon-exit.c:2966 msgid "# Bytes received from MESH" msgstr "" #: src/exit/gnunet-daemon-exit.c:1909 src/exit/gnunet-daemon-exit.c:2990 #, c-format msgid "No service %s found for %s on port %d!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1914 msgid "# TCP requests dropped (no such service)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1971 msgid "# TCP IP-exit creation requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2076 msgid "# TCP data requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2090 msgid "# TCP DATA requests dropped (no session)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2150 msgid "# ICMP packets sent via TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:2324 msgid "# ICMP IP-exit requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2573 msgid "# ICMP service requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2639 src/vpn/gnunet-service-vpn.c:1397 #: src/vpn/gnunet-service-vpn.c:1954 msgid "# ICMPv4 packets dropped (impossible PT to v6)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2698 src/vpn/gnunet-service-vpn.c:1433 #: src/vpn/gnunet-service-vpn.c:1445 src/vpn/gnunet-service-vpn.c:1844 msgid "# ICMPv6 packets dropped (impossible PT to v4)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2748 msgid "# UDP packets sent via TUN" msgstr "" #: src/exit/gnunet-daemon-exit.c:2862 msgid "# UDP IP-exit requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2969 msgid "# UDP service requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:2995 msgid "# UDP requests dropped (no such service)" msgstr "" #: src/exit/gnunet-daemon-exit.c:3031 msgid "# Inbound MESH channels created" msgstr "" #: src/exit/gnunet-daemon-exit.c:3235 src/exit/gnunet-daemon-exit.c:3245 #, c-format msgid "Option `%s' for domain `%s' is not formatted correctly!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3259 src/exit/gnunet-daemon-exit.c:3267 #, c-format msgid "`%s' is not a valid port number (for domain `%s')!" msgstr "" #: src/exit/gnunet-daemon-exit.c:3300 #, c-format msgid "No addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3314 src/exit/gnunet-daemon-exit.c:3326 #, c-format msgid "Service `%s' configured for IPv4, but IPv4 is disabled!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3337 #, c-format msgid "No IP addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3527 msgid "" "This system does not support IPv4, will disable IPv4 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3535 msgid "" "This system does not support IPv6, will disable IPv6 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3542 msgid "" "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use " "ENABLE_IPv4=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3548 msgid "" "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use " "ENABLE_IPv6=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3554 src/exit/gnunet-daemon-exit.c:3717 #: src/pt/gnunet-daemon-pt.c:1247 msgid "No useful service enabled. Exiting.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3664 msgid "Must be a number" msgstr "" #: src/exit/gnunet-daemon-exit.c:3813 msgid "Daemon to run to provide an IP exit node for the VPN" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:55 msgid "Experimentation daemon shutting down ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:77 msgid "Experimentation daemon starting ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:83 msgid "Failed to create statistics!\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:120 msgid "GNUnet experimentation daemon" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:241 #, c-format msgid "Experiment `%s': Experiment signature is invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:250 #, c-format msgid "" "Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu " "sec. \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:303 #, c-format msgid "Experiment `%s': Issuer missing\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:312 #, c-format msgid "Experiment `%s': Issuer invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:320 #, c-format msgid "Experiment `%s': Issuer not accepted!\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:330 #, c-format msgid "Experiment `%s': Version missing or invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:339 #, c-format msgid "Experiment `%s': Required capabilities missing \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:345 #, c-format msgid "Experiment `%s': Required capabilities invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:390 #, c-format msgid "Failed to parse file `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:420 #: src/experimentation/gnunet-daemon-experimentation_experiments.c:452 msgid "" "No valid experiment issuers configured! Set value to public keys of issuers! " "Exiting.\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:435 msgid "Invalid value for public key\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:473 #, c-format msgid "Cannot read experiments file `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:221 #, c-format msgid "Cannot send message to peer `%s' for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:309 #, c-format msgid "Sending experimentation request to peer %s\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:453 #, c-format msgid "Added peer `%s' as active node\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:891 #, c-format msgid "Connected to peer %s\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:921 #, c-format msgid "Disconnected from peer %s\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:1104 msgid "Failed to connect to CORE service!\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:108 #, c-format msgid "Peer `%s' did not respond to request for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:143 #, c-format msgid "Starting inbound experiment `%s' with peer `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:276 #, c-format msgid "Starting outbound experiment `%s' with peer `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:294 #, c-format msgid "Received %s message from peer %s for experiment `%s'\n" msgstr "" #: src/fragmentation/defragmentation.c:270 msgid "# acknowledgements sent for fragment" msgstr "" #: src/fragmentation/defragmentation.c:456 msgid "# fragments received" msgstr "" #: src/fragmentation/defragmentation.c:521 msgid "# duplicate fragments received" msgstr "" #: src/fragmentation/defragmentation.c:534 msgid "# messages defragmented" msgstr "" #: src/fragmentation/fragmentation.c:208 msgid "# fragments transmitted" msgstr "" #: src/fragmentation/fragmentation.c:211 msgid "# fragments retransmitted" msgstr "" #: src/fragmentation/fragmentation.c:237 msgid "# fragments wrap arounds" msgstr "" #: src/fragmentation/fragmentation.c:281 msgid "# messages fragmented" msgstr "" #: src/fragmentation/fragmentation.c:284 msgid "# total size of fragmented messages" msgstr "" #: src/fragmentation/fragmentation.c:405 msgid "# fragment acknowledgements received" msgstr "" #: src/fragmentation/fragmentation.c:411 msgid "# bits removed from fragmentation ACKs" msgstr "" #: src/fragmentation/fragmentation.c:435 msgid "# fragmentation transmissions completed" msgstr "" #: src/fs/fs_api.c:465 #, c-format msgid "Could not open file `%s': %s" msgstr "" #: src/fs/fs_api.c:474 #, c-format msgid "Could not read file `%s': %s" msgstr "" #: src/fs/fs_api.c:480 #, c-format msgid "Short read reading from file `%s'!" msgstr "" #: src/fs/fs_api.c:1066 #, c-format msgid "Failed to resume publishing information `%s': %s\n" msgstr "" #: src/fs/fs_api.c:1571 #, c-format msgid "Failure while resuming publishing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:1585 #, c-format msgid "Failed to resume publishing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2242 #, c-format msgid "Failure while resuming unindexing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2252 #, c-format msgid "Failed to resume unindexing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2378 src/fs/fs_api.c:2619 #, c-format msgid "Failed to resume sub-download `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2395 #, c-format msgid "Failed to resume sub-search `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2409 src/fs/fs_api.c:2428 src/fs/fs_api.c:2911 #, c-format msgid "Failure while resuming search operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2610 #, c-format msgid "Failed to resume sub-download `%s': could not open file `%s'\n" msgstr "" #: src/fs/fs_api.c:2855 msgid "Could not resume running search, will resume as paused search\n" msgstr "" #: src/fs/fs_api.c:2949 #, c-format msgid "Failure while resuming download operation `%s': %s\n" msgstr "" #: src/fs/fs_directory.c:208 msgid "MAGIC mismatch. This is not a GNUnet directory.\n" msgstr "" #: src/fs/fs_download.c:322 msgid "" "Recursive downloads of directories larger than 4 GB are not supported on 32-" "bit systems\n" msgstr "" #: src/fs/fs_download.c:342 msgid "Directory too large for system address space\n" msgstr "" #: src/fs/fs_download.c:523 src/fs/fs_download.c:535 #, c-format msgid "Failed to open file `%s' for writing" msgstr "" #: src/fs/fs_download.c:905 #, c-format msgid "Failed to create directory for recursive download of `%s'\n" msgstr "" #: src/fs/fs_download.c:987 #, c-format msgid "" "Internal error or bogus download URI (expected %u bytes at depth %u and " "offset %llu/%llu, got %u bytes)" msgstr "" #: src/fs/fs_download.c:1013 msgid "internal error decrypting content" msgstr "" #: src/fs/fs_download.c:1036 #, c-format msgid "Download failed: could not open file `%s': %s" msgstr "" #: src/fs/fs_download.c:1046 #, c-format msgid "Failed to seek to offset %llu in file `%s': %s" msgstr "" #: src/fs/fs_download.c:1055 #, c-format msgid "Failed to write block of %u bytes at offset %llu in file `%s': %s" msgstr "" #: src/fs/fs_download.c:1153 msgid "internal error decoding tree" msgstr "" #: src/fs/fs_download.c:1944 msgid "Invalid URI" msgstr "" #: src/fs/fs_getopt.c:192 #, c-format msgid "" "Unknown metadata type in metadata option `%s'. Using metadata type " "`unknown' instead.\n" msgstr "" #: src/fs/fs_list_indexed.c:90 #, c-format msgid "Failed to receive response for `%s' request from `%s' service.\n" msgstr "" #: src/fs/fs_list_indexed.c:113 #, c-format msgid "Failed to receive valid response for `%s' request from `%s' service.\n" msgstr "" #: src/fs/fs_list_indexed.c:151 #, c-format msgid "Failed to not connect to `%s' service.\n" msgstr "" #: src/fs/fs_misc.c:126 #, c-format msgid "Did not find mime type `%s' in extension list.\n" msgstr "" #: src/fs/fs_namespace.c:207 #, c-format msgid "Failed to open `%s' for writing: %s\n" msgstr "" #: src/fs/fs_namespace.c:229 #, c-format msgid "Failed to write `%s': %s\n" msgstr "" #: src/fs/fs_namespace.c:320 #, c-format msgid "Failed to read `%s': %s\n" msgstr "" #: src/fs/fs_namespace.c:466 msgid "Failed to connect to datastore." msgstr "" #: src/fs/fs_publish.c:125 src/fs/fs_publish.c:415 #, c-format msgid "Publishing failed: %s" msgstr "" #: src/fs/fs_publish.c:667 src/fs/fs_publish.c:684 src/fs/fs_publish.c:723 #: src/fs/fs_publish.c:744 src/fs/fs_publish.c:768 src/fs/fs_publish.c:914 #, c-format msgid "Can not index file `%s': %s. Will try to insert instead.\n" msgstr "" #: src/fs/fs_publish.c:669 msgid "timeout on index-start request to `fs' service" msgstr "" #: src/fs/fs_publish.c:681 msgid "unknown error" msgstr "" #: src/fs/fs_publish.c:725 msgid "failed to compute hash" msgstr "" #: src/fs/fs_publish.c:745 msgid "filename too long" msgstr "" #: src/fs/fs_publish.c:770 msgid "could not connect to `fs' service" msgstr "" #: src/fs/fs_publish.c:793 #, c-format msgid "Failed to get file identifiers for `%s'\n" msgstr "" #: src/fs/fs_publish.c:862 #, c-format msgid "Recursive upload failed at `%s': %s" msgstr "" #: src/fs/fs_publish.c:868 #, c-format msgid "Recursive upload failed: %s" msgstr "" #: src/fs/fs_publish.c:915 msgid "needs to be an actual file" msgstr "" #: src/fs/fs_publish.c:1151 #, c-format msgid "Insufficient space for publishing: %s" msgstr "" #: src/fs/fs_publish.c:1243 #, c-format msgid "Reserving space for %u entries and %llu bytes for publication\n" msgstr "" #: src/fs/fs_publish_ksk.c:219 msgid "Could not connect to datastore." msgstr "" #: src/fs/fs_publish_ublock.c:219 msgid "Internal error." msgstr "" #: src/fs/fs_search.c:813 #, c-format msgid "Failed to parse URI `%s': %s\n" msgstr "" #: src/fs/fs_search.c:872 #, c-format msgid "Got result with unknown block type `%d', ignoring" msgstr "" #: src/fs/fs_unindex.c:59 msgid "Failed to find given position in file" msgstr "" #: src/fs/fs_unindex.c:64 msgid "Failed to read file" msgstr "" #: src/fs/fs_unindex.c:234 msgid "Unexpected time for a response from `fs' service." msgstr "" #: src/fs/fs_unindex.c:242 msgid "Timeout waiting for `fs' service." msgstr "" #: src/fs/fs_unindex.c:250 msgid "Invalid response from `fs' service." msgstr "" #: src/fs/fs_unindex.c:291 msgid "Failed to connect to FS service for unindexing." msgstr "" #: src/fs/fs_unindex.c:347 src/fs/fs_unindex.c:359 msgid "Failed to get KSKs from directory scan." msgstr "" #: src/fs/fs_unindex.c:355 #, c-format msgid "Internal error scanning `%s'.\n" msgstr "" #: src/fs/fs_unindex.c:414 #, c-format msgid "Failed to remove UBlock: %s\n" msgstr "" #: src/fs/fs_unindex.c:562 src/fs/fs_unindex.c:626 msgid "Failed to connect to `datastore' service." msgstr "" #: src/fs/fs_unindex.c:639 msgid "Failed to open file for unindexing." msgstr "" #: src/fs/fs_unindex.c:673 msgid "Failed to compute hash of file." msgstr "" #: src/fs/fs_uri.c:222 #, no-c-format msgid "`%' must be followed by HEX number" msgstr "" #: src/fs/fs_uri.c:281 msgid "Malformed KSK URI (must not begin or end with `+')" msgstr "" #: src/fs/fs_uri.c:299 msgid "`++' not allowed in KSK URI" msgstr "" #: src/fs/fs_uri.c:306 msgid "Quotes not balanced in KSK URI" msgstr "" #: src/fs/fs_uri.c:376 msgid "Malformed SKS URI" msgstr "" #: src/fs/fs_uri.c:419 src/fs/fs_uri.c:434 msgid "Malformed CHK URI" msgstr "" #: src/fs/fs_uri.c:512 src/fs/fs_uri.c:580 msgid "SKS URI malformed" msgstr "" #: src/fs/fs_uri.c:527 src/fs/fs_uri.c:537 msgid "LOC URI malformed" msgstr "" #: src/fs/fs_uri.c:545 src/fs/fs_uri.c:553 msgid "LOC URI malformed (could not decode public key)" msgstr "" #: src/fs/fs_uri.c:559 msgid "SKS URI malformed (could not find signature)" msgstr "" #: src/fs/fs_uri.c:565 src/fs/fs_uri.c:574 msgid "SKS URI malformed (could not decode signature)" msgstr "" #: src/fs/fs_uri.c:586 msgid "SKS URI malformed (could not parse expiration time)" msgstr "" #: src/fs/fs_uri.c:598 msgid "SKS URI malformed (signature failed validation)" msgstr "" #: src/fs/fs_uri.c:636 msgid "Unrecognized URI type" msgstr "" #: src/fs/fs_uri.c:860 msgid "Lacking key configuration settings.\n" msgstr "" #: src/fs/fs_uri.c:866 #, c-format msgid "Could not access hostkey file `%s'.\n" msgstr "" #: src/fs/fs_uri.c:1050 src/fs/fs_uri.c:1077 msgid "No keywords specified!\n" msgstr "" #: src/fs/fs_uri.c:1083 msgid "Number of double-quotes not balanced!\n" msgstr "" #: src/fs/gnunet-auto-share.c:236 #, c-format msgid "Failed to load state: %s\n" msgstr "" #: src/fs/gnunet-auto-share.c:289 src/fs/gnunet-auto-share.c:299 #: src/fs/gnunet-auto-share.c:309 #, c-format msgid "Failed to save state to file %s\n" msgstr "" #: src/fs/gnunet-auto-share.c:401 #, c-format msgid "Publication of `%s' done\n" msgstr "" #: src/fs/gnunet-auto-share.c:488 #, c-format msgid "Publishing `%s'\n" msgstr "" #: src/fs/gnunet-auto-share.c:497 #, c-format msgid "Failed to run `%s'\n" msgstr "" #: src/fs/gnunet-auto-share.c:686 #, c-format msgid "" "You must specify one and only one directory name for automatic publication.\n" msgstr "" #: src/fs/gnunet-auto-share.c:737 src/fs/gnunet-publish.c:824 msgid "set the desired LEVEL of sender-anonymity" msgstr "" #: src/fs/gnunet-auto-share.c:741 src/fs/gnunet-publish.c:828 msgid "disable adding the creation time to the metadata of the uploaded file" msgstr "" #: src/fs/gnunet-auto-share.c:744 src/fs/gnunet-publish.c:831 msgid "do not use libextractor to add keywords or metadata" msgstr "" #: src/fs/gnunet-auto-share.c:747 src/fs/gnunet-publish.c:855 msgid "specify the priority of the content" msgstr "" #: src/fs/gnunet-auto-share.c:750 src/fs/gnunet-publish.c:862 msgid "set the desired replication LEVEL" msgstr "" #: src/fs/gnunet-auto-share.c:770 msgid "Automatically publish files from a directory on GNUnet" msgstr "" #: src/fs/gnunet-daemon-fsprofiler.c:660 msgid "Daemon to use file-sharing to measure its performance." msgstr "" #: src/fs/gnunet-directory.c:49 #, c-format msgid "\t\n" msgstr "" #: src/fs/gnunet-directory.c:94 #, c-format msgid "Directory `%s' meta data:\n" msgstr "" #: src/fs/gnunet-directory.c:97 #, c-format msgid "Directory `%s' contents:\n" msgstr "" #: src/fs/gnunet-directory.c:132 msgid "You must specify a filename to inspect.\n" msgstr "" #: src/fs/gnunet-directory.c:145 #, c-format msgid "Failed to read directory `%s'\n" msgstr "" #: src/fs/gnunet-directory.c:154 #, c-format msgid "`%s' is not a GNUnet directory\n" msgstr "" #: src/fs/gnunet-directory.c:183 msgid "Display contents of a GNUnet directory" msgstr "" #: src/fs/gnunet-download.c:137 #, c-format msgid "Starting download `%s'.\n" msgstr "" #: src/fs/gnunet-download.c:147 msgid "" msgstr "" #: src/fs/gnunet-download.c:157 #, c-format msgid "" "Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to " "download\n" msgstr "" #: src/fs/gnunet-download.c:179 #, c-format msgid "Error downloading: %s.\n" msgstr "" #: src/fs/gnunet-download.c:194 #, c-format msgid "Downloading `%s' done (%s/s).\n" msgstr "" #: src/fs/gnunet-download.c:209 src/fs/gnunet-publish.c:286 #: src/fs/gnunet-search.c:200 src/fs/gnunet-unindex.c:108 #, c-format msgid "Unexpected status: %d\n" msgstr "" #: src/fs/gnunet-download.c:234 msgid "You need to specify a URI argument.\n" msgstr "" #: src/fs/gnunet-download.c:240 src/fs/gnunet-publish.c:665 #, c-format msgid "Failed to parse URI: %s\n" msgstr "" #: src/fs/gnunet-download.c:247 msgid "Only CHK or LOC URIs supported.\n" msgstr "" #: src/fs/gnunet-download.c:254 msgid "Target filename must be specified.\n" msgstr "" #: src/fs/gnunet-download.c:268 src/fs/gnunet-publish.c:797 #: src/fs/gnunet-search.c:250 src/fs/gnunet-unindex.c:140 #, c-format msgid "Could not initialize `%s' subsystem.\n" msgstr "" #: src/fs/gnunet-download.c:305 src/fs/gnunet-search.c:289 msgid "set the desired LEVEL of receiver-anonymity" msgstr "" #: src/fs/gnunet-download.c:308 msgid "delete incomplete downloads (when aborted with CTRL-C)" msgstr "" #: src/fs/gnunet-download.c:311 src/fs/gnunet-search.c:292 msgid "only search the local peer (no P2P network search)" msgstr "" #: src/fs/gnunet-download.c:314 msgid "write the file to FILENAME" msgstr "" #: src/fs/gnunet-download.c:318 msgid "set the maximum number of parallel downloads that is allowed" msgstr "" #: src/fs/gnunet-download.c:322 msgid "set the maximum number of parallel requests for blocks that is allowed" msgstr "" #: src/fs/gnunet-download.c:325 msgid "download a GNUnet directory recursively" msgstr "" #: src/fs/gnunet-download.c:339 msgid "" "Download files from GNUnet using a GNUnet CHK or LOC URI (gnunet://fs/" "chk/...)" msgstr "" #: src/fs/gnunet-fs.c:117 msgid "print a list of all indexed files" msgstr "" #: src/fs/gnunet-fs.c:127 msgid "Special file-sharing operations" msgstr "" #: src/fs/gnunet-fs-profiler.c:193 msgid "run the experiment with COUNT peers" msgstr "" #: src/fs/gnunet-fs-profiler.c:196 msgid "specifies name of a file with the HOSTS the testbed should use" msgstr "" #: src/fs/gnunet-fs-profiler.c:199 msgid "automatically terminate experiment after DELAY" msgstr "" #: src/fs/gnunet-fs-profiler.c:208 msgid "run a testbed to measure file-sharing performance" msgstr "" #: src/fs/gnunet-publish.c:231 src/fs/gnunet-publish.c:243 #, c-format msgid "Publishing `%s' at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-publish.c:250 #, c-format msgid "Error publishing: %s.\n" msgstr "" #: src/fs/gnunet-publish.c:260 #, c-format msgid "Publishing `%s' done.\n" msgstr "" #: src/fs/gnunet-publish.c:264 #, c-format msgid "URI is `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:283 msgid "Cleanup after abort complete.\n" msgstr "" #: src/fs/gnunet-publish.c:401 #, c-format msgid "Meta data for file `%s' (%s)\n" msgstr "" #: src/fs/gnunet-publish.c:403 #, c-format msgid "Keywords for file `%s' (%s)\n" msgstr "" #: src/fs/gnunet-publish.c:542 msgid "Could not publish\n" msgstr "" #: src/fs/gnunet-publish.c:565 msgid "Could not start publishing.\n" msgstr "" #: src/fs/gnunet-publish.c:598 #, c-format msgid "Scanning directory `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:600 #, c-format msgid "Scanning file `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:605 #, c-format msgid "There was trouble processing file `%s', skipping it.\n" msgstr "" #: src/fs/gnunet-publish.c:610 msgid "Preprocessing complete.\n" msgstr "" #: src/fs/gnunet-publish.c:614 #, c-format msgid "Extracting meta data from file `%s' complete.\n" msgstr "" #: src/fs/gnunet-publish.c:618 msgid "Meta data extraction has finished.\n" msgstr "" #: src/fs/gnunet-publish.c:625 msgid "Internal error scanning directory.\n" msgstr "" #: src/fs/gnunet-publish.c:656 #, c-format msgid "Selected pseudonym `%s' unknown\n" msgstr "" #: src/fs/gnunet-publish.c:682 #, c-format msgid "Failed to access `%s': %s\n" msgstr "" #: src/fs/gnunet-publish.c:695 msgid "" "Failed to start meta directory scanner. Is gnunet-helper-publish-fs " "installed?\n" msgstr "" #: src/fs/gnunet-publish.c:747 #, c-format msgid "Cannot extract metadata from a URI!\n" msgstr "" #: src/fs/gnunet-publish.c:754 #, c-format msgid "You must specify one and only one filename for insertion.\n" msgstr "" #: src/fs/gnunet-publish.c:760 #, c-format msgid "You must NOT specify an URI and a filename.\n" msgstr "" #: src/fs/gnunet-publish.c:768 src/vpn/gnunet-vpn.c:209 #, c-format msgid "Option `%s' is required when using option `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:778 src/fs/gnunet-publish.c:785 #: src/transport/gnunet-transport.c:1284 src/transport/gnunet-transport.c:1314 #: src/transport/gnunet-transport.c:1344 #, c-format msgid "Option `%s' makes no sense without option `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:835 msgid "" "print list of extracted keywords that would be used, but do not perform " "upload" msgstr "" #: src/fs/gnunet-publish.c:839 msgid "" "add an additional keyword for the top-level file or directory (this option " "can be specified multiple times)" msgstr "" #: src/fs/gnunet-publish.c:843 msgid "set the meta-data for the given TYPE to the given VALUE" msgstr "" #: src/fs/gnunet-publish.c:846 msgid "" "do not index, perform full insertion (stores entire file in encrypted form " "in GNUnet database)" msgstr "" #: src/fs/gnunet-publish.c:851 msgid "" "specify ID of an updated version to be published in the future (for " "namespace insertions only)" msgstr "" #: src/fs/gnunet-publish.c:859 msgid "publish the files under the pseudonym NAME (place file into namespace)" msgstr "" #: src/fs/gnunet-publish.c:865 msgid "" "only simulate the process but do not do any actual publishing (useful to " "compute URIs)" msgstr "" #: src/fs/gnunet-publish.c:869 msgid "" "set the ID of this version of the publication (for namespace insertions only)" msgstr "" #: src/fs/gnunet-publish.c:873 msgid "" "URI to be published (can be used instead of passing a file to add keywords " "to the file with the respective URI)" msgstr "" #: src/fs/gnunet-publish.c:889 msgid "Publish a file or directory on GNUnet" msgstr "" #: src/fs/gnunet-search.c:114 #, c-format msgid "Failed to write directory with search results to `%s'\n" msgstr "" #: src/fs/gnunet-search.c:191 #, c-format msgid "Error searching: %s.\n" msgstr "" #: src/fs/gnunet-search.c:240 msgid "Could not create keyword URI from arguments.\n" msgstr "" #: src/fs/gnunet-search.c:264 msgid "Could not start searching.\n" msgstr "" #: src/fs/gnunet-search.c:295 msgid "write search results to file starting with PREFIX" msgstr "" #: src/fs/gnunet-search.c:298 msgid "automatically terminate search after DELAY" msgstr "" #: src/fs/gnunet-search.c:305 msgid "automatically terminate search after VALUE results are found" msgstr "" #: src/fs/gnunet-search.c:316 msgid "Search GNUnet for files that were published on GNUnet" msgstr "" #: src/fs/gnunet-service-fs.c:271 msgid "# running average P2P latency (ms)" msgstr "" #: src/fs/gnunet-service-fs.c:326 src/fs/gnunet-service-fs.c:539 msgid "# Loopback routes suppressed" msgstr "" #: src/fs/gnunet-service-fs.c:639 src/hostlist/gnunet-daemon-hostlist.c:288 #: src/topology/gnunet-daemon-topology.c:1254 #: src/topology/gnunet-daemon-topology.c:1261 #, c-format msgid "Failed to connect to `%s' service.\n" msgstr "" #: src/fs/gnunet-service-fs_cp.c:682 msgid "# migration stop messages received" msgstr "" #: src/fs/gnunet-service-fs_cp.c:686 #, c-format msgid "Migration of content to peer `%s' blocked for %s\n" msgstr "" #: src/fs/gnunet-service-fs_cp.c:721 msgid "# replies transmitted to other peers" msgstr "" #: src/fs/gnunet-service-fs_cp.c:727 msgid "# replies dropped" msgstr "" #: src/fs/gnunet-service-fs_cp.c:752 src/fs/gnunet-service-fs_cp.c:1301 msgid "# P2P searches active" msgstr "" #: src/fs/gnunet-service-fs_cp.c:845 msgid "# artificial delays introduced (ms)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:898 msgid "# replies dropped due to type mismatch" msgstr "" #: src/fs/gnunet-service-fs_cp.c:906 msgid "# replies received for other peers" msgstr "" #: src/fs/gnunet-service-fs_cp.c:920 msgid "# replies dropped due to insufficient cover traffic" msgstr "" #: src/fs/gnunet-service-fs_cp.c:958 msgid "# P2P searches destroyed due to ultimate reply" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1026 msgid "# requests done for free (low load)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1051 msgid "# request dropped, priority insufficient" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1061 msgid "# requests done for a price (normal load)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1139 msgid "# GET requests received (from other peers)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1173 msgid "# requests dropped due to initiator not being connected" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1195 msgid "# requests dropped due to missing reverse route" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1246 msgid "# requests dropped due TTL underflow" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1270 msgid "# requests dropped due to higher-TTL request" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1299 msgid "# P2P query messages received and processed" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1670 msgid "# migration stop messages sent" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:130 #: src/fs/gnunet-service-fs_indexing.c:181 #, c-format msgid "Could not open `%s'.\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:142 #, c-format msgid "Error writing `%s'.\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:237 #, c-format msgid "" "Index request received for file `%s' is already indexed as `%s'. Permitting " "anyway.\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:275 #, c-format msgid "Hash mismatch trying to index file `%s' which has hash `%s'\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:477 #, c-format msgid "Failed to delete bogus block: %s\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:542 msgid "# index blocks removed: original file inaccessible" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:557 #, c-format msgid "Could not access indexed file `%s' (%s) at offset %llu: %s\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:559 msgid "not indexed" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:574 #, c-format msgid "Indexed file `%s' changed at offset %llu\n" msgstr "" #: src/fs/gnunet-service-fs_lc.c:202 src/fs/gnunet-service-fs_lc.c:368 msgid "# client searches active" msgstr "" #: src/fs/gnunet-service-fs_lc.c:256 msgid "# replies received for local clients" msgstr "" #: src/fs/gnunet-service-fs_lc.c:327 msgid "# client searches received" msgstr "" #: src/fs/gnunet-service-fs_lc.c:362 msgid "# client searches updated (merged content seen list)" msgstr "" #: src/fs/gnunet-service-fs_mesh_client.c:484 msgid "# replies received via mesh" msgstr "" #: src/fs/gnunet-service-fs_mesh_client.c:498 msgid "# replies received via mesh dropped" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:260 msgid "# Blocks transferred via mesh" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:352 msgid "# queries received via mesh not answered" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:432 msgid "# queries received via mesh" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:476 msgid "# mesh client connections rejected" msgstr "" #: src/fs/gnunet-service-fs_mesh_server.c:482 #: src/fs/gnunet-service-fs_mesh_server.c:522 msgid "# mesh connections active" msgstr "" #: src/fs/gnunet-service-fs_pe.c:269 msgid "# average retransmission delay (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:400 msgid "# transmission failed (core has no bandwidth)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:433 msgid "# query messages sent to other peers" msgstr "" #: src/fs/gnunet-service-fs_pe.c:484 msgid "# delay heap timeout (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:492 msgid "# query plans executed" msgstr "" #: src/fs/gnunet-service-fs_pe.c:552 msgid "# requests merged" msgstr "" #: src/fs/gnunet-service-fs_pe.c:560 msgid "# requests refreshed" msgstr "" #: src/fs/gnunet-service-fs_pe.c:616 src/fs/gnunet-service-fs_pe.c:700 #: src/fs/gnunet-service-fs_pe.c:771 msgid "# query plan entries" msgstr "" #: src/fs/gnunet-service-fs_pr.c:311 msgid "# Pending requests created" msgstr "" #: src/fs/gnunet-service-fs_pr.c:394 src/fs/gnunet-service-fs_pr.c:645 msgid "# Pending requests active" msgstr "" #: src/fs/gnunet-service-fs_pr.c:814 msgid "# replies received and matched" msgstr "" #: src/fs/gnunet-service-fs_pr.c:844 msgid "# duplicate replies discarded (bloomfilter)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:853 msgid "# irrelevant replies discarded" msgstr "" #: src/fs/gnunet-service-fs_pr.c:867 #, c-format msgid "Unsupported block type %u\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:880 msgid "# results found locally" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1001 msgid "# Datastore `PUT' failures" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1029 msgid "# storage requests dropped due to high load" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1064 msgid "# Replies received from DHT" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1192 msgid "# Replies received from MESH" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1244 #, c-format msgid "Datastore lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1264 #, c-format msgid "On-demand lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1311 msgid "# Datastore lookups concluded (no results)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1326 msgid "# Datastore lookups concluded (seen all)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1335 msgid "# Datastore lookups aborted (more than MAX_RESULTS)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1350 msgid "# requested DBLOCK or IBLOCK not found" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1364 msgid "# on-demand blocks matched requests" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1377 msgid "# on-demand lookups performed successfully" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1382 msgid "# on-demand lookups failed" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1409 src/fs/gnunet-service-fs_pr.c:1449 #: src/fs/gnunet-service-fs_pr.c:1590 msgid "# Datastore lookups concluded (error queueing)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1467 msgid "# Datastore lookups concluded (found last result)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1478 msgid "# Datastore lookups concluded (load too high)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1566 msgid "# Datastore lookups initiated" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1651 msgid "# GAP PUT messages received" msgstr "" #: src/fs/gnunet-service-fs_push.c:631 msgid "time required, content pushing disabled" msgstr "" #: src/fs/gnunet-unindex.c:89 #, c-format msgid "Unindexing at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-unindex.c:95 #, c-format msgid "Error unindexing: %s.\n" msgstr "" #: src/fs/gnunet-unindex.c:100 msgid "Unindexing done.\n" msgstr "" #: src/fs/gnunet-unindex.c:130 #, c-format msgid "You must specify one and only one filename for unindexing.\n" msgstr "" #: src/fs/gnunet-unindex.c:147 msgid "Could not start unindex operation.\n" msgstr "" #: src/fs/gnunet-unindex.c:179 msgid "Unindex a file that was previously indexed with gnunet-publish." msgstr "" #: src/gns/gns_api.c:393 msgid "Failed to deserialize lookup reply from GNS service!\n" msgstr "" #: src/gns/gnunet-bcd.c:123 #, c-format msgid "Refusing `%s' request to HTTP server\n" msgstr "" #: src/gns/gnunet-bcd.c:355 src/hostlist/hostlist-server.c:567 #, c-format msgid "Invalid port number %llu. Exiting.\n" msgstr "" #: src/gns/gnunet-bcd.c:360 #, c-format msgid "Businesscard HTTP server starts on %llu\n" msgstr "" #: src/gns/gnunet-bcd.c:374 #, c-format msgid "Could not start businesscard HTTP server on port %u\n" msgstr "" #: src/gns/gnunet-bcd.c:519 msgid "Run HTTP serve on port PORT (default is 8888)" msgstr "" #: src/gns/gnunet-bcd.c:531 msgid "GNUnet HTTP server to create business cards" msgstr "" #: src/gns/gnunet-dns2gns.c:228 msgid "Failed to pack DNS response into UDP packet!\n" msgstr "" #: src/gns/gnunet-dns2gns.c:400 #, c-format msgid "Cannot parse DNS request from %s\n" msgstr "" #: src/gns/gnunet-dns2gns.c:416 #, c-format msgid "Received malformed DNS request from %s\n" msgstr "" #: src/gns/gnunet-dns2gns.c:424 #, c-format msgid "Received unsupported DNS request from %s\n" msgstr "" #: src/gns/gnunet-dns2gns.c:701 msgid "No ego configured for `dns2gns` subsystem\n" msgstr "" #: src/gns/gnunet-dns2gns.c:727 msgid "No DNS server specified!\n" msgstr "" #: src/gns/gnunet-dns2gns.c:749 msgid "No valid GNS zone specified!\n" msgstr "" #: src/gns/gnunet-dns2gns.c:770 msgid "IP of recursive DNS resolver to use (required)" msgstr "" #: src/gns/gnunet-dns2gns.c:773 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:776 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:779 msgid "UDP port to listen on for inbound DNS requests; default: 53" msgstr "" #: src/gns/gnunet-dns2gns.c:782 msgid "Public key of the GNS zone to use (overrides default)" msgstr "" #: src/gns/gnunet-dns2gns.c:795 msgid "GNUnet DNS-to-GNS proxy (a DNS server)" msgstr "" #: src/gns/gnunet-gns.c:227 #, c-format msgid "Please specify name to lookup!\n" msgstr "" #: src/gns/gnunet-gns.c:308 #, c-format msgid "Ego for `%s' not found, cannot perform lookup.\n" msgstr "" #: src/gns/gnunet-gns.c:347 src/gns/gnunet-gns-helper-service-w32.c:798 #, c-format msgid "" "Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-" "gns-import.sh?\n" msgstr "" #: src/gns/gnunet-gns.c:386 src/gns/gnunet-gns-helper-service-w32.c:828 #, c-format msgid "Failed to connect to GNS\n" msgstr "" #: src/gns/gnunet-gns.c:399 #, c-format msgid "Public key `%s' is not well-formed\n" msgstr "" #: src/gns/gnunet-gns.c:449 msgid "Lookup a record for the given name" msgstr "" #: src/gns/gnunet-gns.c:452 msgid "Specify the type of the record to lookup" msgstr "" #: src/gns/gnunet-gns.c:455 msgid "Specify timeout for the lookup" msgstr "" #: src/gns/gnunet-gns.c:458 msgid "No unneeded output" msgstr "" #: src/gns/gnunet-gns.c:461 msgid "Specify the public key of the zone to lookup the record in" msgstr "" #: src/gns/gnunet-gns.c:464 msgid "Specify the name of the ego of the zone to lookup the record in" msgstr "" #: src/gns/gnunet-gns.c:478 msgid "GNUnet GNS resolver tool" msgstr "" #: src/gns/gnunet-gns-helper-service-w32.c:768 #, c-format msgid "" "Ego for `gns-short' not found. This is not really fatal, but i'll pretend " "that it is and refuse to perform a lookup. Did you run gnunet-gns-import." "sh?\n" msgstr "" #: src/gns/gnunet-gns-helper-service-w32.c:838 #, c-format msgid "Failed to connect to identity service\n" msgstr "" #: src/gns/gnunet-gns-import.c:479 msgid "This program will import some GNS authorities into your GNS namestore." msgstr "" #: src/gns/gnunet-gns-proxy.c:105 src/hostlist/hostlist-client.c:469 #: src/hostlist/hostlist-client.c:683 src/hostlist/hostlist-client.c:689 #: src/hostlist/hostlist-client.c:741 src/hostlist/hostlist-client.c:750 #: src/hostlist/hostlist-client.c:871 src/hostlist/hostlist-client.c:963 #: src/hostlist/hostlist-client.c:968 #: src/transport/plugin_transport_http_client.c:1062 #: src/transport/plugin_transport_http_client.c:1077 #, c-format msgid "%s failed at %s:%d: `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:833 #, c-format msgid "Unsupported CURL SSL backend %d\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:856 #, c-format msgid "Failed to fetch CN from cert: %s\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:879 #, c-format msgid "Failed to initialize DANE: %s\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:892 #, c-format msgid "Failed to parse DANE record: %s\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:907 #, c-format msgid "Failed to verify TLS connection using DANE: %s\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:917 #, c-format msgid "Failed DANE verification failed with GnuTLS verify status code: %u\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:941 #, c-format msgid "SSL certificate subject name (%s) does not match `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1086 #, c-format msgid "Cookie domain `%s' supplied by server is invalid\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1602 #, c-format msgid "Unsupported HTTP method `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1973 #, c-format msgid "Unable to import private key from file `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2003 #, c-format msgid "Unable to import certificate %s\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2177 #, c-format msgid "Failed to start HTTPS server for `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2196 msgid "Failed to pass client to MHD\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2504 #, c-format msgid "Unsupported socks version %d\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2533 #, c-format msgid "Unsupported socks command %d\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2551 src/gns/gnunet-gns-proxy.c:2580 msgid "SSL connection to plain IPv4 address requested\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2631 #, c-format msgid "Unsupported socks address type %d\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2970 msgid "No ego configured for `shorten-zone`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3010 #, c-format msgid "No ego configured for `%s`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3072 #, c-format msgid "Failed to load SSL/TLS key and certificate from `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3113 msgid "listen on specified port (default: 7777)" msgstr "" #: src/gns/gnunet-gns-proxy.c:3116 msgid "pem file to use as CA" msgstr "" #: src/gns/gnunet-gns-proxy.c:3135 msgid "GNUnet GNS proxy" msgstr "" #: src/gns/gnunet-service-gns.c:862 msgid "Failed to connect to the namestore!\n" msgstr "" #: src/gns/gnunet-service-gns.c:870 msgid "Failed to connect to the namecache!\n" msgstr "" #: src/gns/gnunet-service-gns.c:903 msgid "Could not connect to DHT!\n" msgstr "" #: src/gns/gnunet-service-gns.c:919 msgid "valid public key required" msgstr "" #: src/gns/gnunet-service-gns_interceptor.c:263 msgid "Error converting GNS response to DNS response!\n" msgstr "" #: src/gns/gnunet-service-gns_interceptor.c:369 msgid "Failed to connect to the DNS service!\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:816 msgid "Failed to parse DNS response\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:958 #, c-format msgid "Skipping record of unsupported type %d\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1317 #, c-format msgid "GNS lookup resulted in DNS name that is too long (`%s')\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1817 msgid "GNS lookup recursion failed (no delegation record found)\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1841 #, c-format msgid "Failed to cache GNS resolution: %s\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:2123 #, c-format msgid "Zone %s was revoked, resolution fails\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:2272 #, c-format msgid "Hostname `%s' is not well-formed, resolution fails\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:151 #, c-format msgid "Unable to parse PKEY record `%s'\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:180 #, c-format msgid "Unable to parse GNS2DNS record `%s'\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:201 #, c-format msgid "Failed to serialize GNS2DNS record with value `%s'\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:217 #, c-format msgid "Unable to parse VPN record string `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:293 #, c-format msgid "Unable to parse IPv4 address `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:314 #, c-format msgid "Failed to serialize NS record with value `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:336 #, c-format msgid "Failed to serialize CNAME record with value `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:420 #, c-format msgid "Failed to serialize CERT record with %u bytes\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:452 #, c-format msgid "Unable to parse SOA record `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:471 #, c-format msgid "Failed to serialize SOA record with mname `%s' and rname `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:494 #, c-format msgid "Failed to serialize PTR record with value `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:514 #, c-format msgid "Unable to parse MX record `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:529 #, c-format msgid "Failed to serialize MX record with hostname `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:549 #, c-format msgid "Unable to parse IPv6 address `%s'\n" msgstr "" #: src/gnsrecord/plugin_gnsrecord_dns.c:567 #, c-format msgid "Unable to parse TLSA record string `%s'\n" msgstr "" #: src/hello/gnunet-hello.c:123 msgid "Call with name of HELLO file to modify.\n" msgstr "" #: src/hello/gnunet-hello.c:129 #, c-format msgid "Error accessing file `%s': %s\n" msgstr "" #: src/hello/gnunet-hello.c:137 #, c-format msgid "File `%s' is too big to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:144 #, c-format msgid "File `%s' is too small to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:154 src/hello/gnunet-hello.c:183 #, c-format msgid "Error opening file `%s': %s\n" msgstr "" #: src/hello/gnunet-hello.c:170 #, c-format msgid "Did not find well-formed HELLO in file `%s'\n" msgstr "" #: src/hello/gnunet-hello.c:195 #, c-format msgid "Error writing HELLO to file `%s': %s\n" msgstr "" #: src/hello/gnunet-hello.c:203 #, c-format msgid "Modified %u addresses \n" msgstr "" #: src/hello/hello.c:944 msgid "Failed to parse HELLO message: missing expiration time\n" msgstr "" #: src/hello/hello.c:953 msgid "Failed to parse HELLO message: invalid expiration time\n" msgstr "" #: src/hello/hello.c:963 msgid "Failed to parse HELLO message: malformed\n" msgstr "" #: src/hello/hello.c:973 msgid "Failed to parse HELLO message: missing transport plugin\n" msgstr "" #: src/hello/hello.c:990 #, c-format msgid "Plugin `%s' not found\n" msgstr "" #: src/hello/hello.c:999 #, c-format msgid "Plugin `%s' does not support URIs yet\n" msgstr "" #: src/hello/hello.c:1018 #, c-format msgid "Failed to parse `%s' as an address for plugin `%s'\n" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:259 msgid "" "None of the functions for the hostlist daemon were enabled. I have no " "reason to run!\n" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:308 msgid "advertise our hostlist to other peers" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:313 msgid "" "bootstrap using hostlists (it is highly recommended that you always use this " "option)" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:316 msgid "enable learning about hostlist servers from other peers" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:320 msgid "provide a hostlist server" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:335 msgid "GNUnet hostlist server and client" msgstr "" #: src/hostlist/hostlist-client.c:288 msgid "# bytes downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:309 src/hostlist/hostlist-client.c:339 msgid "# invalid HELLOs downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:312 src/hostlist/hostlist-client.c:342 #, c-format msgid "Invalid `%s' message received from hostlist at `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:330 msgid "# valid HELLOs downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:592 src/hostlist/hostlist-client.c:1333 msgid "# advertised hostlist URIs" msgstr "" #: src/hostlist/hostlist-client.c:622 #, c-format msgid "# advertised URI `%s' downloaded" msgstr "" #: src/hostlist/hostlist-client.c:664 #, c-format msgid "" "Advertised hostlist with URI `%s' could not be downloaded. Advertised URI " "gets dismissed.\n" msgstr "" #: src/hostlist/hostlist-client.c:802 #, c-format msgid "Timeout trying to download hostlist from `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:816 #, c-format msgid "Download limit of %u bytes exceeded, stopping download\n" msgstr "" #: src/hostlist/hostlist-client.c:836 #, c-format msgid "Download of hostlist from `%s' failed: `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:842 #, c-format msgid "Download of hostlist `%s' completed.\n" msgstr "" #: src/hostlist/hostlist-client.c:850 #, c-format msgid "Adding successfully tested hostlist `%s' datastore.\n" msgstr "" #: src/hostlist/hostlist-client.c:903 #, c-format msgid "Bootstrapping using hostlist at `%s'.\n" msgstr "" #: src/hostlist/hostlist-client.c:911 msgid "# hostlist downloads initiated" msgstr "" #: src/hostlist/hostlist-client.c:1040 src/hostlist/hostlist-client.c:1506 msgid "# milliseconds between hostlist downloads" msgstr "" #: src/hostlist/hostlist-client.c:1049 #, c-format msgid "Have %u/%u connections. Will consider downloading hostlist in %s\n" msgstr "" #: src/hostlist/hostlist-client.c:1109 src/hostlist/hostlist-client.c:1125 msgid "# active connections" msgstr "" #: src/hostlist/hostlist-client.c:1280 #, c-format msgid "Loading saved hostlist entries from file `%s' \n" msgstr "" #: src/hostlist/hostlist-client.c:1285 #, c-format msgid "Hostlist file `%s' does not exist\n" msgstr "" #: src/hostlist/hostlist-client.c:1296 #, c-format msgid "Could not open file `%s' for reading to load hostlists: %s\n" msgstr "" #: src/hostlist/hostlist-client.c:1329 #, c-format msgid "%u hostlist URIs loaded from file\n" msgstr "" #: src/hostlist/hostlist-client.c:1331 msgid "# hostlist URIs read from file" msgstr "" #: src/hostlist/hostlist-client.c:1376 #, c-format msgid "Could not open file `%s' for writing to save hostlists: %s\n" msgstr "" #: src/hostlist/hostlist-client.c:1381 #, c-format msgid "Writing %u hostlist URIs to `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:1405 src/hostlist/hostlist-client.c:1422 #, c-format msgid "Error writing hostlist URIs to file `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:1417 msgid "# hostlist URIs written to file" msgstr "" #: src/hostlist/hostlist-client.c:1471 msgid "Learning is enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1483 msgid "Learning is not enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1495 #, c-format msgid "" "Since learning is not enabled on this peer, hostlist file `%s' was removed\n" msgstr "" #: src/hostlist/hostlist-client.c:1499 #, c-format msgid "Hostlist file `%s' could not be removed\n" msgstr "" #: src/hostlist/hostlist-server.c:137 msgid "bytes in hostlist" msgstr "" #: src/hostlist/hostlist-server.c:161 msgid "expired addresses encountered" msgstr "" #: src/hostlist/hostlist-server.c:189 src/hostlist/hostlist-server.c:425 #: src/peerinfo-tool/gnunet-peerinfo.c:350 #: src/peerinfo-tool/gnunet-peerinfo.c:419 #: src/peerinfo-tool/gnunet-peerinfo.c:490 #: src/topology/gnunet-daemon-topology.c:925 #, c-format msgid "Error in communication with PEERINFO service: %s\n" msgstr "" #: src/hostlist/hostlist-server.c:210 msgid "HELLOs without addresses encountered (ignored)" msgstr "" #: src/hostlist/hostlist-server.c:224 msgid "bytes not included in hostlist (size limit)" msgstr "" #: src/hostlist/hostlist-server.c:268 #, c-format msgid "Refusing `%s' request to hostlist server\n" msgstr "" #: src/hostlist/hostlist-server.c:271 msgid "hostlist requests refused (not HTTP GET)" msgstr "" #: src/hostlist/hostlist-server.c:284 #, c-format msgid "Refusing `%s' request with %llu bytes of upload data\n" msgstr "" #: src/hostlist/hostlist-server.c:288 msgid "hostlist requests refused (upload data)" msgstr "" #: src/hostlist/hostlist-server.c:296 msgid "Could not handle hostlist request since I do not have a response yet\n" msgstr "" #: src/hostlist/hostlist-server.c:299 msgid "hostlist requests refused (not ready)" msgstr "" #: src/hostlist/hostlist-server.c:303 msgid "Received request for our hostlist\n" msgstr "" #: src/hostlist/hostlist-server.c:304 msgid "hostlist requests processed" msgstr "" #: src/hostlist/hostlist-server.c:346 msgid "# hostlist advertisements send" msgstr "" #: src/hostlist/hostlist-server.c:390 msgid "Advertisement message could not be queued by core\n" msgstr "" #: src/hostlist/hostlist-server.c:557 src/peerinfo-tool/gnunet-peerinfo.c:639 #: src/transport/gnunet-service-transport.c:1114 msgid "Could not access PEERINFO service. Exiting.\n" msgstr "" #: src/hostlist/hostlist-server.c:576 #, c-format msgid "Hostlist service starts on %s:%llu\n" msgstr "" #: src/hostlist/hostlist-server.c:590 #, c-format msgid "Address to obtain hostlist: `%s'\n" msgstr "" #: src/hostlist/hostlist-server.c:630 #, c-format msgid "`%s' is not a valid IP address! Ignoring BINDTOIP.\n" msgstr "" #: src/hostlist/hostlist-server.c:673 #, c-format msgid "Could not start hostlist HTTP server on port %u\n" msgstr "" #: src/identity/gnunet-identity.c:165 #, c-format msgid "Failed to create ego: %s\n" msgstr "" #: src/identity/gnunet-identity.c:184 #, c-format msgid "Failed to set default ego: %s\n" msgstr "" #: src/identity/gnunet-identity.c:327 msgid "create ego NAME" msgstr "" #: src/identity/gnunet-identity.c:330 msgid "delete ego NAME " msgstr "" #: src/identity/gnunet-identity.c:333 msgid "display all egos" msgstr "" #: src/identity/gnunet-identity.c:336 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)" msgstr "" #: src/identity/gnunet-identity.c:339 msgid "run in monitor mode egos" msgstr "" #: src/identity/gnunet-identity.c:342 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)" msgstr "" #: src/identity/gnunet-identity.c:351 msgid "Maintain egos" msgstr "" #: src/identity/gnunet-service-identity.c:338 msgid "no default known" msgstr "" #: src/identity/gnunet-service-identity.c:362 msgid "default configured, but ego unknown (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:439 #: src/identity/gnunet-service-identity.c:670 #: src/identity/gnunet-service-identity.c:778 #, c-format msgid "Failed to write subsystem default identifier map to `%s'.\n" msgstr "" #: src/identity/gnunet-service-identity.c:446 msgid "Unknown ego specified for service (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:516 msgid "identifier already in use for another ego" msgstr "" #: src/identity/gnunet-service-identity.c:647 msgid "target name already exists" msgstr "" #: src/identity/gnunet-service-identity.c:686 #: src/identity/gnunet-service-identity.c:795 msgid "no matching ego found" msgstr "" #: src/identity/gnunet-service-identity.c:829 #, c-format msgid "Failed to parse ego information in `%s'\n" msgstr "" #: src/identity/gnunet-service-identity.c:902 #, c-format msgid "Failed to parse subsystem identity configuration file `%s'\n" msgstr "" #: src/identity/gnunet-service-identity.c:914 #, c-format msgid "Failed to create directory `%s' for storing egos\n" msgstr "" #: src/mesh/gnunet-mesh.c:357 #, c-format msgid "Invalid target `%s'\n" msgstr "" #: src/mesh/gnunet-mesh.c:607 #, c-format msgid "Invalid peer ID `%s'\n" msgstr "" #: src/mesh/gnunet-mesh.c:650 #, c-format msgid "Invalid tunnel owner `%s'\n" msgstr "" #: src/mesh/gnunet-mesh.c:716 msgid "You must NOT give a TARGETwhen using 'request all' options\n" msgstr "" #: src/mesh/gnunet-mesh.c:807 msgid "provide information about a particular connection" msgstr "" #: src/mesh/gnunet-mesh.c:810 msgid "activate echo mode" msgstr "" #: src/mesh/gnunet-mesh.c:816 msgid "port to listen to (default; 0)" msgstr "" #: src/mesh/gnunet-mesh.c:819 src/mesh/gnunet-mesh.c:822 msgid "provide information about all peers" msgstr "" #: src/mesh/gnunet-mesh.c:825 msgid "provide information about a particular tunnel" msgstr "" #: src/mesh/gnunet-mesh.c:828 msgid "provide information about all tunnels" msgstr "" #: src/mesh/gnunet-service-mesh_peer.c:390 msgid "Wrong CORE service\n" msgstr "" #: src/mysql/mysql.c:174 #, c-format msgid "Trying to use file `%s' for MySQL configuration.\n" msgstr "" #: src/mysql/mysql.c:181 #, c-format msgid "Could not access file `%s': %s\n" msgstr "" #: src/namecache/gnunet-namecache.c:109 #, c-format msgid "No records found for `%s'" msgstr "" #: src/namecache/gnunet-namecache.c:124 src/namestore/gnunet-namestore.c:397 #, c-format msgid "\tCorrupt or unsupported record of type %u\n" msgstr "" #: src/namecache/gnunet-namecache.c:185 #, c-format msgid "You must specify which zone should be accessed\n" msgstr "" #: src/namecache/gnunet-namecache.c:195 src/namestore/gnunet-namestore.c:695 #, c-format msgid "Invalid public key for reverse lookup `%s'\n" msgstr "" #: src/namecache/gnunet-namecache.c:203 #, c-format msgid "You must specify a name\n" msgstr "" #: src/namecache/gnunet-namecache.c:234 src/namestore/gnunet-namestore.c:931 msgid "name of the record to add/delete/display" msgstr "" #: src/namecache/gnunet-namecache.c:237 msgid "spezifies the public key of the zone to look in" msgstr "" #: src/namecache/gnunet-namecache.c:248 src/namestore/gnunet-namestore.c:963 msgid "GNUnet zone manipulation tool" msgstr "" #: src/namecache/namecache_api.c:276 msgid "Namecache failed to cache block" msgstr "" #: src/namecache/plugin_namecache_postgres.c:89 #: src/namestore/plugin_namestore_postgres.c:96 msgid "Failed to create indices\n" msgstr "" #: src/namestore/gnunet-namestore.c:303 #, c-format msgid "Adding record failed: %s\n" msgstr "" #: src/namestore/gnunet-namestore.c:332 #, c-format msgid "Deleting record failed, record does not exist%s%s\n" msgstr "" #: src/namestore/gnunet-namestore.c:339 #, c-format msgid "Deleting record failed%s%s\n" msgstr "" #: src/namestore/gnunet-namestore.c:558 #, c-format msgid "No options given\n" msgstr "" #: src/namestore/gnunet-namestore.c:569 #: src/namestore/gnunet-namestore-fcfsd.c:970 msgid "Failed to connect to namestore\n" msgstr "" #: src/namestore/gnunet-namestore.c:577 src/namestore/gnunet-namestore.c:586 #: src/namestore/gnunet-namestore.c:603 src/namestore/gnunet-namestore.c:625 #: src/namestore/gnunet-namestore.c:665 #, c-format msgid "Missing option `%s' for operation `%s'\n" msgstr "" #: src/namestore/gnunet-namestore.c:578 src/namestore/gnunet-namestore.c:587 #: src/namestore/gnunet-namestore.c:604 src/namestore/gnunet-namestore.c:626 msgid "add" msgstr "" #: src/namestore/gnunet-namestore.c:595 #, c-format msgid "Unsupported type `%s'\n" msgstr "" #: src/namestore/gnunet-namestore.c:615 #, c-format msgid "Value `%s' invalid for record type `%s'\n" msgstr "" #: src/namestore/gnunet-namestore.c:651 #, c-format msgid "Invalid time format `%s'\n" msgstr "" #: src/namestore/gnunet-namestore.c:666 msgid "del" msgstr "" #: src/namestore/gnunet-namestore.c:715 #: src/peerinfo-tool/gnunet-peerinfo.c:723 #, c-format msgid "Invalid URI `%s'\n" msgstr "" #: src/namestore/gnunet-namestore.c:750 #, c-format msgid "Invalid nick `%s'\n" msgstr "" #: src/namestore/gnunet-namestore.c:790 #, c-format msgid "Ego `%s' not known to identity service\n" msgstr "" #: src/namestore/gnunet-namestore.c:817 #, c-format msgid "No default ego configured in identity service\n" msgstr "" #: src/namestore/gnunet-namestore.c:853 #, c-format msgid "Identity service is not running\n" msgstr "" #: src/namestore/gnunet-namestore.c:865 #, c-format msgid "Cannot connect to identity service\n" msgstr "" #: src/namestore/gnunet-namestore.c:913 msgid "add record" msgstr "" #: src/namestore/gnunet-namestore.c:916 msgid "delete record" msgstr "" #: src/namestore/gnunet-namestore.c:919 msgid "display records" msgstr "" #: src/namestore/gnunet-namestore.c:922 msgid "" "expiration time for record to use (for adding only), \"never\" is possible" msgstr "" #: src/namestore/gnunet-namestore.c:925 msgid "set the desired nick name for the zone" msgstr "" #: src/namestore/gnunet-namestore.c:928 msgid "monitor changes in the namestore" msgstr "" #: src/namestore/gnunet-namestore.c:934 msgid "determine our name for the given PKEY" msgstr "" #: src/namestore/gnunet-namestore.c:937 msgid "type of the record to add/delete/display" msgstr "" #: src/namestore/gnunet-namestore.c:940 msgid "URI to import into our zone" msgstr "" #: src/namestore/gnunet-namestore.c:943 msgid "value of the record to add/delete" msgstr "" #: src/namestore/gnunet-namestore.c:946 msgid "create or list public record" msgstr "" #: src/namestore/gnunet-namestore.c:949 msgid "" "create shadow record (only valid if all other records of the same type have " "expired" msgstr "" #: src/namestore/gnunet-namestore.c:952 msgid "name of the ego controlling the zone" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:464 #, c-format msgid "Unsupported form value `%s'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:491 #, c-format msgid "Failed to create record for domain `%s': %s\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:525 #, c-format msgid "Found existing name `%s' for the given key\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:534 msgid "Error when mapping zone to name\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:596 #, c-format msgid "Found %u existing records for domain `%s'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:652 #, c-format msgid "Failed to create page for `%s'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:668 #, c-format msgid "Failed to setup post processor for `%s'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:704 msgid "Domain name must not contain `.'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:712 msgid "Domain name must not contain `+'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:910 msgid "No ego configured for `fcfsd` subsystem\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:936 msgid "Failed to start HTTP server\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:978 msgid "Failed to connect to identity\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:1011 msgid "GNU Name System First Come First Serve name registration service" msgstr "" #: src/namestore/gnunet-service-namestore.c:655 #, c-format msgid "Failed to replicate block in namecache: %s\n" msgstr "" #: src/namestore/namestore_api.c:275 msgid "Namestore failed to store record\n" msgstr "" #: src/nat/gnunet-nat-server.c:279 #, c-format msgid "Please pass valid port number as the first argument! (got `%s')\n" msgstr "" #: src/nat/gnunet-nat-server.c:321 msgid "GNUnet NAT traversal test helper daemon" msgstr "" #: src/nat/nat_auto.c:170 msgid "NAT traversal with ICMP Server timed out.\n" msgstr "" #: src/nat/nat_auto.c:203 msgid "NAT traversal with ICMP Server succeeded.\n" msgstr "" #: src/nat/nat_auto.c:204 msgid "NAT traversal with ICMP Server failed.\n" msgstr "" #: src/nat/nat_auto.c:225 msgid "Testing connection reversal with ICMP server.\n" msgstr "" #: src/nat/nat_auto.c:274 #, c-format msgid "Detected external IP `%s'\n" msgstr "" #: src/nat/nat_auto.c:344 msgid "This system has a global IPv6 address, setting IPv6 to supported.\n" msgstr "" #: src/nat/nat_auto.c:360 #, c-format msgid "Detected internal network address `%s'.\n" msgstr "" #: src/nat/nat_auto.c:413 msgid "upnpc found, enabling its use\n" msgstr "" #: src/nat/nat_auto.c:414 msgid "upnpc not found\n" msgstr "" #: src/nat/nat_auto.c:447 msgid "gnunet-helper-nat-server found, testing it\n" msgstr "" #: src/nat/nat_auto.c:448 msgid "No working gnunet-helper-nat-server found\n" msgstr "" #: src/nat/nat_auto.c:482 msgid "gnunet-helper-nat-client found, enabling it\n" msgstr "" #: src/nat/nat_auto.c:483 msgid "gnunet-helper-nat-client not found or behind NAT, disabling it\n" msgstr "" #: src/nat/nat.c:867 #, c-format msgid "gnunet-helper-nat-server generated malformed address `%s'\n" msgstr "" #: src/nat/nat.c:917 #, c-format msgid "Failed to start %s\n" msgstr "" #: src/nat/nat.c:1205 msgid "malformed" msgstr "" #: src/nat/nat.c:1276 src/nat/nat.c:1288 #, c-format msgid "" "Configuration requires `%s', but binary is not installed properly (SUID bit " "not set). Option disabled.\n" msgstr "" #: src/nat/nat.c:1426 msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n" msgstr "" #: src/nat/nat.c:1442 #, c-format msgid "Running gnunet-helper-nat-client %s %s %u\n" msgstr "" #: src/nat/nat_mini.c:155 msgid "no valid address was returned by `external-ip'" msgstr "" #: src/nat/nat_mini.c:175 msgid "`external-ip' command not found" msgstr "" #: src/nat/nat_mini.c:201 msgid "`external-ip' command not found\n" msgstr "" #: src/nat/nat_mini.c:366 msgid "Failed to run `upnpc` command" msgstr "" #: src/nat/nat_mini.c:512 msgid "`upnpc' command took too long, process killed" msgstr "" #: src/nat/nat_mini.c:540 msgid "`upnpc' command failed to establish port mapping" msgstr "" #: src/nat/nat_mini.c:604 msgid "`upnpc' command not found\n" msgstr "" #: src/nat/nat_mini.c:608 msgid "`upnpc` command not found" msgstr "" #: src/nat/nat_test.c:351 msgid "Failed to connect to `gnunet-nat-server'\n" msgstr "" #: src/nat/nat_test.c:423 #, c-format msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n" msgstr "" #: src/nse/gnunet-nse.c:117 msgid "NSE service is not running\n" msgstr "" #: src/nse/gnunet-nse.c:122 msgid "Error while checking if NSE service is running or not\n" msgstr "" #: src/nse/gnunet-nse.c:168 msgid "Show network size estimates from NSE service." msgstr "" #: src/nse/gnunet-nse-profiler.c:858 msgid "limit to the number of connections to NSE services, 0 for none" msgstr "" #: src/nse/gnunet-nse-profiler.c:861 msgid "name of the file for writing connection information and statistics" msgstr "" #: src/nse/gnunet-nse-profiler.c:864 src/testbed/gnunet-testbed-profiler.c:306 msgid "name of the file with the login information for the testbed" msgstr "" #: src/nse/gnunet-nse-profiler.c:867 msgid "name of the file for writing the main results" msgstr "" #: src/nse/gnunet-nse-profiler.c:870 msgid "Number of peers to run in each round, separated by commas" msgstr "" #: src/nse/gnunet-nse-profiler.c:876 msgid "delay between rounds" msgstr "" #: src/nse/gnunet-nse-profiler.c:885 msgid "Measure quality and performance of the NSE service." msgstr "" #: src/nse/gnunet-service-nse.c:1517 #: src/revocation/gnunet-service-revocation.c:789 src/util/gnunet-scrypt.c:248 msgid "Value is too large.\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:215 #, c-format msgid "Removing expired address of transport `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:352 #, c-format msgid "Failed to parse HELLO in file `%s': %s\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:371 #: src/peerinfo/gnunet-service-peerinfo.c:388 #, c-format msgid "Failed to parse HELLO in file `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:466 msgid "# peers known" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:503 #, c-format msgid "" "File `%s' in directory `%s' does not match naming convention. Removed.\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:653 #, c-format msgid "Scanning directory `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:658 #, c-format msgid "Still no peers found in `%s'!\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:994 #, c-format msgid "Cleaning up directory `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:1287 #, c-format msgid "Importing HELLOs from `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:1298 msgid "Skipping import of included HELLOs\n" msgstr "" #: src/peerinfo/peerinfo_api.c:236 msgid "aborted due to explicit disconnect request" msgstr "" #: src/peerinfo/peerinfo_api.c:356 msgid "failed to transmit request (service down?)" msgstr "" #: src/peerinfo/peerinfo_api.c:506 msgid "Failed to receive response from `PEERINFO' service." msgstr "" #: src/peerinfo/peerinfo_api.c:547 src/peerinfo/peerinfo_api.c:566 #: src/peerinfo/peerinfo_api.c:581 src/peerinfo/peerinfo_api.c:592 #: src/peerinfo/peerinfo_api.c:603 msgid "Received invalid message from `PEERINFO' service." msgstr "" #: src/peerinfo/peerinfo_api.c:678 msgid "Timeout transmitting iteration request to `PEERINFO' service." msgstr "" #: src/peerinfo/peerinfo_api_notify.c:268 #, c-format msgid "Could not connect to `%s' service.\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:232 #, c-format msgid "%sPeer `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:239 #, c-format msgid "\tExpires: %s \t %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:428 #, c-format msgid "Failure: Did not receive %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:436 #, c-format msgid "Failure: Received invalid %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:445 #, c-format msgid "Failed to write HELLO with %u bytes to file `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:458 #, c-format msgid "Wrote %s HELLO containing %u addresses with %u bytes to file `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:522 #, c-format msgid "Failure adding HELLO: %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:633 #, c-format msgid "Service `%s' is not running, please start GNUnet\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:654 src/util/gnunet-scrypt.c:224 #, c-format msgid "Loading hostkey from `%s' failed.\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:745 #, c-format msgid "I am peer `%s'.\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:789 msgid "don't resolve host names" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:792 msgid "output only the identity strings" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:795 msgid "include friend-only information" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:798 msgid "output our own identity only" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:801 msgid "list all known peers" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:804 msgid "dump hello to file" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:807 msgid "also output HELLO uri(s)" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:810 msgid "add given HELLO uri to the database" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:821 msgid "Print information about peers." msgstr "" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:105 #: src/transport/gnunet-service-transport_plugins.c:128 #, c-format msgid "Starting transport plugins `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:109 #: src/transport/gnunet-service-transport_plugins.c:133 #, c-format msgid "Loading `%s' transport plugin\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:129 #: src/transport/gnunet-service-transport_plugins.c:165 #, c-format msgid "Failed to load transport plugin for `%s'\n" msgstr "" #: src/postgres/postgres.c:59 #, c-format msgid "`%s:%s' failed at %s:%d with error: %s" msgstr "" #: src/postgres/postgres.c:148 #, c-format msgid "Unable to initialize Postgres: %s" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:200 msgid "Failed to store membership information!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:224 msgid "Failed to test membership!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:246 msgid "Failed to store fragment!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:272 msgid "Failed to get fragment!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:299 msgid "Failed to get message!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:328 msgid "Failed to get message fragment!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:356 msgid "Failed to get master counters!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:392 #: src/psycstore/gnunet-service-psycstore.c:465 msgid "Tried to set invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:408 msgid "Failed to begin modifying state!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:431 #, c-format msgid "Unknown operator: %c\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:441 msgid "Failed to end modifying state!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:479 msgid "Failed to begin synchronizing state!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:495 msgid "Failed to end synchronizing state!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:515 #: src/psycstore/gnunet-service-psycstore.c:534 msgid "Failed to reset state!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:557 #: src/psycstore/gnunet-service-psycstore.c:608 msgid "Tried to get invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:584 #: src/psycstore/gnunet-service-psycstore.c:623 msgid "Failed to get state variable!\n" msgstr "" #: src/psycstore/plugin_psycstore_sqlite.c:60 #, c-format msgid "`%s' failed at %s:%d with error: %s (%d)\n" msgstr "" #: src/psycstore/plugin_psycstore_sqlite.c:253 #, c-format msgid "" "Error preparing SQL query: %s\n" " %s\n" msgstr "" #: src/psycstore/plugin_psycstore_sqlite.c:276 #, c-format msgid "" "Error executing SQL query: %s\n" " %s\n" msgstr "" #: src/psycstore/plugin_psycstore_sqlite.c:1796 msgid "SQLite database running\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:482 msgid "Failed to pack DNS request. Dropping.\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:488 msgid "# DNS requests mapped to VPN" msgstr "" #: src/pt/gnunet-daemon-pt.c:541 msgid "# DNS records modified" msgstr "" #: src/pt/gnunet-daemon-pt.c:717 msgid "# DNS replies intercepted" msgstr "" #: src/pt/gnunet-daemon-pt.c:723 msgid "Failed to parse DNS request. Dropping.\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:826 msgid "# DNS requests dropped (timeout)" msgstr "" #: src/pt/gnunet-daemon-pt.c:883 msgid "# DNS requests intercepted" msgstr "" #: src/pt/gnunet-daemon-pt.c:888 msgid "# DNS requests dropped (DNS mesh channel down)" msgstr "" #: src/pt/gnunet-daemon-pt.c:896 msgid "# DNS requests dropped (malformed)" msgstr "" #: src/pt/gnunet-daemon-pt.c:969 msgid "# DNS replies received" msgstr "" #: src/pt/gnunet-daemon-pt.c:985 msgid "# DNS replies dropped (too late?)" msgstr "" #: src/pt/gnunet-daemon-pt.c:1261 src/pt/gnunet-daemon-pt.c:1270 #: src/pt/gnunet-daemon-pt.c:1290 src/pt/gnunet-daemon-pt.c:1301 #: src/pt/gnunet-daemon-pt.c:1310 #, c-format msgid "Failed to connect to %s service. Exiting.\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:1347 msgid "Daemon to run to perform IP protocol translation to GNUnet" msgstr "" #: src/regex/gnunet-daemon-regexprofiler.c:270 #: src/regex/gnunet-regex-simulation-profiler.c:659 #, c-format msgid "%s service is lacking key configuration settings (%s). Exiting.\n" msgstr "" #: src/regex/gnunet-daemon-regexprofiler.c:380 msgid "Daemon to announce regular expressions for the peer using mesh." msgstr "" #: src/regex/gnunet-regex-profiler.c:1288 msgid "No configuration file given. Exiting\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1299 msgid "Configuration option \"regex_prefix\" missing. Exiting\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1328 #: src/regex/gnunet-regex-simulation-profiler.c:622 #, c-format msgid "No policy directory specified on command line. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1334 #: src/regex/gnunet-regex-simulation-profiler.c:629 #, c-format msgid "Specified policies directory does not exist. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1341 #, c-format msgid "No files found in `%s'\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1350 msgid "No search strings file given. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1370 msgid "Error loading search strings. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1455 msgid "name of the file for writing statistics" msgstr "" #: src/regex/gnunet-regex-profiler.c:1458 msgid "wait TIMEOUT before ending the experiment" msgstr "" #: src/regex/gnunet-regex-profiler.c:1461 msgid "directory with policy files" msgstr "" #: src/regex/gnunet-regex-profiler.c:1464 msgid "name of file with input strings" msgstr "" #: src/regex/gnunet-regex-profiler.c:1467 msgid "name of file with hosts' names" msgstr "" #: src/regex/gnunet-regex-profiler.c:1479 msgid "Profiler for regex" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:689 msgid "name of the table to write DFAs" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:692 msgid "maximum path compression length" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:705 msgid "Profiler for regex library" msgstr "" #: src/regex/regex_api.c:131 #, c-format msgid "Regex `%s' is too long!\n" msgstr "" #: src/revocation/gnunet-revocation.c:126 #, c-format msgid "Key `%s' is valid\n" msgstr "" #: src/revocation/gnunet-revocation.c:131 #, c-format msgid "Key `%s' has been revoked\n" msgstr "" #: src/revocation/gnunet-revocation.c:137 msgid "Internal error\n" msgstr "" #: src/revocation/gnunet-revocation.c:163 #, c-format msgid "Key for ego `%s' is still valid, revocation failed (!)\n" msgstr "" #: src/revocation/gnunet-revocation.c:168 msgid "Revocation failed (!)\n" msgstr "" #: src/revocation/gnunet-revocation.c:173 #, c-format msgid "Key for ego `%s' has been successfully revoked\n" msgstr "" #: src/revocation/gnunet-revocation.c:178 msgid "Revocation successful.\n" msgstr "" #: src/revocation/gnunet-revocation.c:183 msgid "Internal error, key revocation might have failed\n" msgstr "" #: src/revocation/gnunet-revocation.c:294 #, c-format msgid "Revocation certificate for `%s' stored in `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:324 #, c-format msgid "Ego `%s' not found.\n" msgstr "" #: src/revocation/gnunet-revocation.c:345 #, c-format msgid "Error: revocation certificate in `%s' is not for `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:365 msgid "Revocation certificate ready\n" msgstr "" #: src/revocation/gnunet-revocation.c:375 msgid "Revocation certificate not ready, calculating proof of work\n" msgstr "" #: src/revocation/gnunet-revocation.c:407 #, c-format msgid "Public key `%s' malformed\n" msgstr "" #: src/revocation/gnunet-revocation.c:421 msgid "" "Testing and revoking at the same time is not allowed, only executing test.\n" msgstr "" #: src/revocation/gnunet-revocation.c:441 msgid "No filename to store revocation certificate given.\n" msgstr "" #: src/revocation/gnunet-revocation.c:463 #, c-format msgid "Failed to read revocation certificate from `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:488 msgid "No action specified. Nothing to do.\n" msgstr "" #: src/revocation/gnunet-revocation.c:504 msgid "use NAME for the name of the revocation file" msgstr "" #: src/revocation/gnunet-revocation.c:507 msgid "" "revoke the private key associated for the the private key associated with " "the ego NAME " msgstr "" #: src/revocation/gnunet-revocation.c:510 msgid "actually perform revocation, otherwise we just do the precomputation" msgstr "" #: src/revocation/gnunet-revocation.c:513 msgid "test if the public key KEY has been revoked" msgstr "" #: src/revocation/gnunet-service-revocation.c:272 msgid "Duplicate revocation received from peer. Ignored.\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:434 #, c-format msgid "Error computing revocation set union with %s\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:486 msgid "SET service crashed, terminating revocation service\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:812 msgid "Could not open revocation database file!" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:225 msgid "You must specify at least one message ID to check!\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:232 msgid "This program needs a session identifier for comparing vectors.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:239 msgid "Please give a session key for --input_key!\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:251 #, c-format msgid "" "Tried to set initiator mode, as peer ID was given. However, `%s' is not a " "valid peer identifier.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:278 #: src/scalarproduct/gnunet-scalarproduct.c:314 #, c-format msgid "Could not convert `%s' to int32_t.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:286 msgid "Need elements to compute the vectorproduct, got none.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:346 #, c-format msgid "Could not convert `%s' to integer.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:407 msgid "" "A comma separated list of elements to compare as vector with our remote peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:410 msgid "" "A comma separated mask to select which elements should actually be compared." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:413 msgid "" "[Optional] peer to calculate our scalarproduct with. If this parameter is " "not given, the service will wait for a remote peer to compute the request." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:416 msgid "Transaction ID shared with peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:425 msgid "Calculate the Vectorproduct with a GNUnet peer." msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:541 #, c-format msgid "Client (%p) disconnected from us.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:613 #: src/scalarproduct/gnunet-service-scalarproduct.c:702 #, c-format msgid "Could not send message to client (%p)!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:619 #, c-format msgid "Sending session-end notification to client (%p) for session %s\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:712 #, c-format msgid "Sent result to client (%p), this session (%s) has ended!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:766 #: src/scalarproduct/gnunet-service-scalarproduct.c:855 msgid "Could not send service-response message via mesh!)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1028 #, c-format msgid "Failed to communicate with `%s', scalar product calculation aborted.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1099 #: src/scalarproduct/gnunet-service-scalarproduct.c:1208 msgid "Transmitting service request.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1108 msgid "Could not send service-request multipart message to channel!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1147 #, c-format msgid "Successfully created new channel to peer (%s)!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1217 msgid "Could not send message to channel!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1274 msgid "Too short message received from client!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1287 msgid "Invalid message received from client, session information incorrect!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1298 #, c-format msgid "" "Duplicate session information received, cannot create new session with key `" "%s'\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1318 #, c-format msgid "" "Got client-request-session with key %s, preparing channel to remote " "service.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1354 #, c-format msgid "Creating new channel for session with key %s.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1399 #, c-format msgid "" "Got client-responder-session with key %s and a matching service-request-" "session set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1409 #, c-format msgid "" "Got client-responder-session with key %s but NO matching service-request-" "session set, queuing element for later use.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1439 #, c-format msgid "New incoming channel from peer %s.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1471 #, c-format msgid "Peer disconnected, terminating session %s with peer (%s)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1672 #: src/scalarproduct/gnunet-service-scalarproduct.c:1814 #, c-format msgid "Got session with key %s and a matching element set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1681 #: src/scalarproduct/gnunet-service-scalarproduct.c:1821 #, c-format msgid "Got session with key %s without a matching element set, queueing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1771 #, c-format msgid "" "Got message with duplicate session key (`%s'), ignoring service request.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2014 msgid "Shutting down, initiating cleanup.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2100 msgid "Connect to MESH failed\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2104 msgid "Mesh initialized\n" msgstr "" #: src/scalarproduct/scalarproduct_api.c:246 msgid "# SUC responder result messages received" msgstr "" #: src/scalarproduct/scalarproduct_api.c:300 msgid "# bytes sent to scalarproduct" msgstr "" #: src/scalarproduct/scalarproduct_api.c:345 #: src/scalarproduct/scalarproduct_api.c:440 msgid "Failed to connect to the scalarproduct service\n" msgstr "" #: src/scalarproduct/scalarproduct_api.c:353 #: src/scalarproduct/scalarproduct_api.c:448 msgid "Failed to send a message to the statistics service\n" msgstr "" #: src/scalarproduct/scalarproduct_api.c:387 #: src/scalarproduct/scalarproduct_api.c:485 msgid "Failed to send a message to the scalarproduct service\n" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:538 msgid "dkg start delay" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:541 msgid "dkg timeout" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:544 msgid "threshold" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:547 msgid "also profile decryption" msgstr "" #: src/set/gnunet-service-set.c:1431 msgid "Could not connect to mesh service\n" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:221 msgid "number of element in set A-B" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:224 msgid "number of element in set B-A" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:227 msgid "number of common elements in A and B" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:230 msgid "hash num" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:233 msgid "ibf size" msgstr "" #: src/set/gnunet-set-profiler.c:295 msgid "oeration to execute" msgstr "" #: src/statistics/gnunet-service-statistics.c:280 #, c-format msgid "Loading %llu bytes of statistics from `%s'\n" msgstr "" #: src/statistics/gnunet-service-statistics.c:346 #, c-format msgid "Wrote %llu bytes of statistics to `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:140 msgid "Failed to obtain statistics.\n" msgstr "" #: src/statistics/gnunet-statistics.c:142 #, c-format msgid "Failed to obtain statistics from host `%s:%llu'\n" msgstr "" #: src/statistics/gnunet-statistics.c:189 msgid "Missing argument: subsystem \n" msgstr "" #: src/statistics/gnunet-statistics.c:195 msgid "Missing argument: name\n" msgstr "" #: src/statistics/gnunet-statistics.c:226 #, c-format msgid "No subsystem or name given\n" msgstr "" #: src/statistics/gnunet-statistics.c:234 #, c-format msgid "Failed to initialize watch routine\n" msgstr "" #: src/statistics/gnunet-statistics.c:261 #, c-format msgid "Trying to connect to remote host, but service `%s' is not running\n" msgstr "" #: src/statistics/gnunet-statistics.c:269 #, c-format msgid "A port is required to connect to host `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:276 #, c-format msgid "A port has to be between 1 and 65535 to connect to host `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:308 #, c-format msgid "Invalid argument `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:334 msgid "limit output to statistics for the given NAME" msgstr "" #: src/statistics/gnunet-statistics.c:337 msgid "make the value being set persistent" msgstr "" #: src/statistics/gnunet-statistics.c:340 msgid "limit output to the given SUBSYSTEM" msgstr "" #: src/statistics/gnunet-statistics.c:343 msgid "just print the statistics value" msgstr "" #: src/statistics/gnunet-statistics.c:346 msgid "watch value continuously" msgstr "" #: src/statistics/gnunet-statistics.c:349 msgid "connect to remote host" msgstr "" #: src/statistics/gnunet-statistics.c:352 msgid "port for remote host" msgstr "" #: src/statistics/gnunet-statistics.c:364 msgid "Print statistics about GNUnet operations." msgstr "" #: src/statistics/statistics_api.c:519 msgid "Could not save some persistent statistics\n" msgstr "" #: src/statistics/statistics_api.c:1090 msgid "" "Failed to receive acknowledgement from statistics service, some statistics " "might have been lost!\n" msgstr "" #: src/testbed/generate-underlay-topology.c:223 msgid "Need atleast 2 arguments\n" msgstr "" #: src/testbed/generate-underlay-topology.c:228 msgid "Database filename missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:235 msgid "Topology string missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:240 #, c-format msgid "Invalid topology: %s\n" msgstr "" #: src/testbed/generate-underlay-topology.c:252 #, c-format msgid "An argument is missing for given topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:258 #, c-format msgid "Invalid argument `%s' given as topology argument\n" msgstr "" #: src/testbed/generate-underlay-topology.c:266 #, c-format msgid "Filename argument missing for topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:280 #, c-format msgid "Second argument for topology `%s' is missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:286 #, c-format msgid "Invalid argument `%s'; expecting unsigned int\n" msgstr "" #: src/testbed/generate-underlay-topology.c:335 #: src/testbed/gnunet-testbed-profiler.c:293 msgid "create COUNT number of peers" msgstr "" #: src/testbed/generate-underlay-topology.c:344 msgid "" "Generates SQLite3 database representing a given underlay topology.\n" "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" "The following options are available for TOPO followed by TOPOOPTS if " "applicable:\n" "\t LINE\n" "\t RING\n" "\t RANDOM \n" "\t SMALL_WORLD \n" "\t SMALL_WORLD_RING \n" "\t CLIQUE\n" "\t 2D_TORUS\n" "\t SCALE_FREE \n" "\t FROM_FILE \n" "TOPOOPTS:\n" "\t num_rnd_links: The number of random links\n" "\t cap: the maximum number of links a node can have\n" "\t m: the number of links a node should have while joining the network\n" "\t filename: the path of the file which contains topology information\n" "NOTE: the format of the above file is descibed here: https://www.gnunet.org/" "content/topology-file-format\n" msgstr "" #: src/testbed/gnunet-daemon-latency-logger.c:325 msgid "Daemon to log latency values of connections to neighbours" msgstr "" #: src/testbed/gnunet-daemon-testbed-blacklist.c:264 msgid "" "Daemon to restrict incoming transport layer connections during testbed " "deployments" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:235 src/testing/list-keys.c:50 #: src/testing/testing.c:293 src/util/gnunet-ecc.c:217 #, c-format msgid "Incorrect hostkey file format: %s\n" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:474 msgid "Daemon to restrict underlay network in testbed deployments" msgstr "" #: src/testbed/gnunet-service-testbed_cpustatus.c:730 #, c-format msgid "" "Cannot open %s for writing load statistics. Not logging load statistics\n" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1015 msgid "Misconfiguration (can't connect to the ARM service)" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1021 msgid "Request doesn't fit into a message" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1059 #, c-format msgid "%s service can't be started because ARM is shutting down" msgstr "" #: src/testbed/gnunet_testbed_mpi_spawn.c:125 msgid "Waiting for child to exit.\n" msgstr "" #: src/testbed/gnunet_testbed_mpi_spawn.c:247 #, c-format msgid "Spawning process `%s'\n" msgstr "" #: src/testbed/gnunet-testbed-profiler.c:267 #, c-format msgid "Exiting as the number of peers is %u\n" msgstr "" #: src/testbed/gnunet-testbed-profiler.c:296 msgid "tolerate COUNT number of continious timeout failures" msgstr "" #: src/testbed/gnunet-testbed-profiler.c:299 msgid "" "run profiler in non-interactive mode where upon testbed setup the profiler " "does not wait for a keystroke but continues to run until a termination " "signal is received" msgstr "" #: src/testbed/testbed_api_hosts.c:415 #, c-format msgid "Hosts file %s not found\n" msgstr "" #: src/testbed/testbed_api_hosts.c:423 #, c-format msgid "Hosts file %s has no data\n" msgstr "" #: src/testbed/testbed_api_hosts.c:430 #, c-format msgid "Hosts file %s cannot be read\n" msgstr "" #: src/testbed/testbed_api_hosts.c:570 #, c-format msgid "The function %s is only available when compiled with (--with-ll)\n" msgstr "" #: src/testbed/testbed_api_hosts.c:1586 #, c-format msgid "Adding host %u failed with error: %s\n" msgstr "" #: src/testbed/testbed_api_testbed.c:819 msgid "Linking controllers failed. Exiting" msgstr "" #: src/testbed/testbed_api_testbed.c:988 #, c-format msgid "Host registration failed for a host. Error: %s\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1054 msgid "Controller crash detected. Shutting down.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1143 #, c-format msgid "Host %s cannot start testbed\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1147 msgid "Testbed cannot be started on localhost\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1185 msgid "Cannot start the master controller" msgstr "" #: src/testbed/testbed_api_testbed.c:1203 msgid "Shutting down testbed due to timeout while setup.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1263 msgid "No hosts loaded from LoadLeveler. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1275 msgid "No hosts loaded. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1299 msgid "Specified topology must be supported by testbed" msgstr "" #: src/testbed/testbed_api_testbed.c:1349 #, c-format msgid "" "Maximum number of edges a peer can have in a scale free topology cannot be " "more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_testbed.c:1365 #, c-format msgid "" "The number of edges that can established when adding a new node to scale " "free topology cannot be more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_topology.c:960 #, c-format msgid "Topology file %s not found\n" msgstr "" #: src/testbed/testbed_api_topology.c:966 #, c-format msgid "Topology file %s has no data\n" msgstr "" #: src/testbed/testbed_api_topology.c:973 #, c-format msgid "Topology file %s cannot be read\n" msgstr "" #: src/testbed/testbed_api_topology.c:995 #, c-format msgid "Failed to read peer index from toology file: %s" msgstr "" #: src/testbed/testbed_api_topology.c:1004 #: src/testbed/testbed_api_topology.c:1028 #, c-format msgid "Value in given topology file: %s out of range\n" msgstr "" #: src/testbed/testbed_api_topology.c:1010 #: src/testbed/testbed_api_topology.c:1034 #, c-format msgid "Failed to read peer index from topology file: %s" msgstr "" #: src/testbed/testbed_api_topology.c:1016 #: src/testbed/testbed_api_topology.c:1040 msgid "Topology file needs more peers than given ones\n" msgstr "" #: src/testbed/testbed_api_topology.c:1074 #, c-format msgid "Ignoring to connect peer %u to peer %u\n" msgstr "" #: src/testing/gnunet-testing.c:173 #, c-format msgid "Could not extract hostkey %u (offset too large?)\n" msgstr "" #: src/testing/gnunet-testing.c:258 #, c-format msgid "Unknown command, use 'q' to quit or 'r' to restart peer\n" msgstr "" #: src/testing/gnunet-testing.c:355 msgid "create unique configuration files" msgstr "" #: src/testing/gnunet-testing.c:357 msgid "extract hostkey file from pre-computed hostkey list" msgstr "" #: src/testing/gnunet-testing.c:359 msgid "" "number of unique configuration files to create, or number of the hostkey to " "extract" msgstr "" #: src/testing/gnunet-testing.c:361 msgid "configuration template" msgstr "" #: src/testing/gnunet-testing.c:363 msgid "run the given service, wait on stdin for 'r' (restart) or 'q' (quit)" msgstr "" #: src/testing/gnunet-testing.c:376 msgid "Command line tool to access the testing library" msgstr "" #: src/testing/list-keys.c:90 msgid "list COUNT number of keys" msgstr "" #: src/testing/list-keys.c:93 msgid "skip COUNT number of keys in the beginning" msgstr "" #: src/testing/testing.c:277 #, c-format msgid "Hostkeys file not found: %s\n" msgstr "" #: src/testing/testing.c:718 #, c-format msgid "Key number %u does not exist\n" msgstr "" #: src/testing/testing.c:1157 #, c-format msgid "" "You attempted to create a testbed with more than %u hosts. Please " "precompute more hostkeys first.\n" msgstr "" #: src/testing/testing.c:1166 #, c-format msgid "Failed to initialize hostkey for peer %u\n" msgstr "" #: src/testing/testing.c:1176 msgid "PRIVATE_KEY option in PEER section missing in configuration\n" msgstr "" #: src/testing/testing.c:1189 msgid "Failed to create configuration for peer (not enough free ports?)\n" msgstr "" #: src/testing/testing.c:1203 #, c-format msgid "Cannot open hostkey file `%s': %s\n" msgstr "" #: src/testing/testing.c:1215 #, c-format msgid "Failed to write hostkey file for peer %u: %s\n" msgstr "" #: src/testing/testing.c:1240 #, c-format msgid "Failed to write configuration file `%s' for peer %u: %s\n" msgstr "" #: src/testing/testing.c:1342 #, c-format msgid "Failed to start `%s': %s\n" msgstr "" #: src/testing/testing.c:1706 #, c-format msgid "Failed to load configuration from %s\n" msgstr "" #: src/topology/friends.c:100 #, c-format msgid "Syntax error in FRIENDS file at offset %llu, skipping bytes `%.*s'.\n" msgstr "" #: src/topology/friends.c:154 #, c-format msgid "Directory for file `%s' does not seem to be writable.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:255 msgid "# peers blacklisted" msgstr "" #: src/topology/gnunet-daemon-topology.c:388 msgid "# connect requests issued to transport" msgstr "" #: src/topology/gnunet-daemon-topology.c:728 #: src/topology/gnunet-daemon-topology.c:813 msgid "# friends connected" msgstr "" #: src/topology/gnunet-daemon-topology.c:993 msgid "Failed to connect to core service, can not manage topology!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1022 #, c-format msgid "Found myself `%s' in friend list (useless, ignored)\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1029 #, c-format msgid "Found friend `%s' in configuration\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1050 msgid "Encountered errors parsing friends list!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1052 msgid "# friends in configuration" msgstr "" #: src/topology/gnunet-daemon-topology.c:1057 msgid "" "Fewer friends specified than required by minimum friend count. Will only " "connect to friends.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1063 msgid "" "More friendly connections required than target total number of connections.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1094 msgid "# HELLO messages received" msgstr "" #: src/topology/gnunet-daemon-topology.c:1151 msgid "# HELLO messages gossipped" msgstr "" #: src/topology/gnunet-daemon-topology.c:1290 msgid "GNUnet topology control (maintaining P2P mesh and F2F constraints)" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:271 #, c-format msgid "Adding blacklisting entry for peer `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:279 #, c-format msgid "Adding blacklisting entry for peer `%s':`%s'\n" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:464 #: src/transport/gnunet-service-transport_blacklist.c:745 msgid "# disconnects due to blacklist" msgstr "" #: src/transport/gnunet-service-transport.c:220 msgid "# bytes payload discarded due to not connected peer" msgstr "" #: src/transport/gnunet-service-transport.c:424 msgid "# bytes total received" msgstr "" #: src/transport/gnunet-service-transport.c:515 msgid "# bytes payload received" msgstr "" #: src/transport/gnunet-service-transport.c:686 #, c-format msgid "Could not obtain a valid network for `%s' %s (%s)\n" msgstr "" #: src/transport/gnunet-service-transport.c:733 #, c-format msgid "" "Address or session unknown: failed to update properties for peer `%s' plugin " "`%s' address `%s' session %p\n" msgstr "" #: src/transport/gnunet-service-transport.c:1084 msgid "Transport service is lacking key configuration settings. Exiting.\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:432 #, c-format msgid "Dropping message of type %u and size %u, have %u/%u messages pending\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:439 msgid "# messages dropped due to slow client" msgstr "" #: src/transport/gnunet-service-transport_clients.c:596 #, c-format msgid "Rejecting control connection from peer `%s', which is not me!\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:737 msgid "# bytes payload dropped (other peer was not connected)" msgstr "" #: src/transport/gnunet-service-transport_clients.c:770 #, c-format msgid "Blacklist refuses connection attempt to peer `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:776 #, c-format msgid "Blacklist allows connection attempt to peer `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:801 msgid "# REQUEST CONNECT messages received" msgstr "" #: src/transport/gnunet-service-transport_clients.c:815 #, c-format msgid "Received a request connect message for peer `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:826 msgid "# REQUEST DISCONNECT messages received" msgstr "" #: src/transport/gnunet-service-transport_clients.c:840 #, c-format msgid "Received a request disconnect message for peer `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_hello.c:181 msgid "# refreshed my HELLO" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1095 msgid "# DISCONNECT messages sent" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1220 #: src/transport/gnunet-service-transport_neighbours.c:1629 msgid "# bytes in message queue for other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1225 msgid "# messages transmitted to other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1230 msgid "# transmission failures for messages to other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1287 msgid "# messages timed out while in transport queue" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1343 msgid "# keepalives sent" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1376 msgid "# KEEPALIVE messages discarded (peer unknown)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1384 msgid "# KEEPALIVE messages discarded (no session)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1431 msgid "# KEEPALIVE_RESPONSE messages discarded (not connected)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1440 msgid "# KEEPALIVE_RESPONSE messages discarded (not expected)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1448 msgid "# KEEPALIVE_RESPONSE messages discarded (address changed)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1456 msgid "# KEEPALIVE_RESPONSE messages discarded (wrong nonce)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1534 msgid "# messages discarded due to lack of neighbour record" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1568 msgid "# bandwidth quota violations by other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1584 msgid "# ms throttling suggested" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1678 #, c-format msgid "" "Failed to send CONNECT message to peer `%s' using address `%s' session %p\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1705 msgid "# Failed attempts to switch addresses (failed to send CONNECT CONT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1751 msgid "# SESSION_CONNECT messages sent" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1767 #, c-format msgid "Failed to transmit CONNECT message via plugin to %s\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1794 msgid "# Failed attempts to switch addresses (failed to send CONNECT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1844 #, c-format msgid "" "Failed to send CONNECT_ACK message to peer `%s' using address `%s' session " "%p\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1899 msgid "# CONNECT_ACK messages sent" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1914 #, c-format msgid "Failed to transmit CONNECT_ACK message via plugin to %s\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2192 #, c-format msgid "Blacklisting disapproved to connect to peer `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2312 msgid "# CONNECT messages received" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2317 #, c-format msgid "CONNECT request from peer `%s' ignored due impending shutdown\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2590 msgid "# Attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3012 msgid "# Failed attempts to switch addresses (no response)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3107 msgid "# CONNECT_ACK messages received" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3115 msgid "# unexpected CONNECT_ACK messages (no peer)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3129 #: src/transport/gnunet-service-transport_neighbours.c:3164 msgid "# unexpected CONNECT_ACK messages (not ready)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3176 msgid "# unexpected CONNECT_ACK messages (waiting on ATS)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3200 msgid "# Successful attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3208 msgid "# unexpected CONNECT_ACK messages (disconnecting)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3396 msgid "# SESSION_ACK messages received" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3424 msgid "# unexpected SESSION_ACK messages" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3490 msgid "# SET QUOTA messages ignored (no such peer)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3505 msgid "# disconnects due to quota of 0" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3545 msgid "# disconnect messages ignored (malformed)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3551 msgid "# DISCONNECT messages received" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3560 msgid "# disconnect messages ignored (timestamp)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3687 msgid "# disconnected from peer upon explicit request" msgstr "" #: src/transport/gnunet-service-transport_plugins.c:120 msgid "Transport service is lacking NEIGHBOUR_LIMIT option.\n" msgstr "" #: src/transport/gnunet-service-transport_plugins.c:178 #: src/transport/gnunet-service-transport_plugins.c:186 #: src/transport/gnunet-service-transport_plugins.c:194 #: src/transport/gnunet-service-transport_plugins.c:202 #: src/transport/gnunet-service-transport_plugins.c:210 #: src/transport/gnunet-service-transport_plugins.c:218 #: src/transport/gnunet-service-transport_plugins.c:226 #: src/transport/gnunet-service-transport_plugins.c:234 #: src/transport/gnunet-service-transport_plugins.c:242 #: src/transport/gnunet-service-transport_plugins.c:250 #: src/transport/gnunet-service-transport_plugins.c:258 #, c-format msgid "Missing function `%s' in transport plugin for `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_plugins.c:265 #, c-format msgid "Did not load plugin `%s' due to missing functions\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:488 msgid "# address records discarded" msgstr "" #: src/transport/gnunet-service-transport_validation.c:558 #, c-format msgid "" "Not transmitting `%s' with `%s', message too big (%u bytes!). This should " "not happen.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:616 msgid "# PING without HELLO messages sent" msgstr "" #: src/transport/gnunet-service-transport_validation.c:722 msgid "# address revalidations started" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1011 msgid "# PING message for different peer received" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1062 #, c-format msgid "Plugin `%s' not available, cannot confirm having this address\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1072 msgid "# failed address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1075 #, c-format msgid "Address `%s' is not one of my addresses, not confirming PING\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1083 msgid "# successful address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1095 #, c-format msgid "" "Not confirming PING from peer `%s' with address `%s' since I cannot confirm " "having this address.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1103 #, c-format msgid "Received a PING message with validation bug from `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1157 #, c-format msgid "Failed to create PONG signature for peer `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1206 msgid "# PONGs unicast via reliable transport" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1215 msgid "# PONGs multicast to all available addresses" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1356 msgid "# PONGs dropped, no matching pending validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1371 msgid "# PONGs dropped, signature expired" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1493 #, c-format msgid "Validation received new %s message for peer `%s' with size %u\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1500 #, c-format msgid "Adding `%s' without addresses for peer `%s'\n" msgstr "" #: src/transport/gnunet-transport.c:367 #, c-format msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n" msgstr "" #: src/transport/gnunet-transport.c:375 #, c-format msgid "Received %llu bytes/s (%llu bytes in %s)\n" msgstr "" #: src/transport/gnunet-transport.c:415 #, c-format msgid "Failed to connect to `%s'\n" msgstr "" #: src/transport/gnunet-transport.c:428 #, c-format msgid "Failed to resolve address for peer `%s'\n" msgstr "" #: src/transport/gnunet-transport.c:438 msgid "Failed to list connections, timeout occured\n" msgstr "" #: src/transport/gnunet-transport.c:559 #, c-format msgid "" "Peer `%s' %s %s\n" "\t%s%s\n" "\t%s%s\n" "\t%s%s\n" msgstr "" #: src/transport/gnunet-transport.c:586 #, c-format msgid "Peer `%s' %s `%s' \n" msgstr "" #: src/transport/gnunet-transport.c:712 msgid "No transport plugins configured, peer will never communicate\n" msgstr "" #: src/transport/gnunet-transport.c:726 #, c-format msgid "No port configured for plugin `%s', cannot test it\n" msgstr "" #: src/transport/gnunet-transport.c:789 #, c-format msgid "Transmitting %u bytes to %s\n" msgstr "" #: src/transport/gnunet-transport.c:810 #, c-format msgid "Successfully connected to `%s'\n" msgstr "" #: src/transport/gnunet-transport.c:834 #, c-format msgid "" "Successfully connected to `%s', starting to send benchmark data in %u Kb " "blocks\n" msgstr "" #: src/transport/gnunet-transport.c:865 #, c-format msgid "Successfully disconnected from `%s'\n" msgstr "" #: src/transport/gnunet-transport.c:888 #, c-format msgid "Disconnected from peer `%s' while benchmarking\n" msgstr "" #: src/transport/gnunet-transport.c:950 #, c-format msgid "Received %u bytes from %s\n" msgstr "" #: src/transport/gnunet-transport.c:975 #, c-format msgid "Peer `%s': %s %s in state `%s' until %s\n" msgstr "" #: src/transport/gnunet-transport.c:986 #, c-format msgid "Peer `%s': %s %s\n" msgstr "" #: src/transport/gnunet-transport.c:1197 src/transport/gnunet-transport.c:1222 msgid "Failed to send connect request to transport service\n" msgstr "" #: src/transport/gnunet-transport.c:1266 #, c-format msgid "" "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, " "%s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1274 #, c-format msgid "" "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1293 src/transport/gnunet-transport.c:1323 #: src/transport/gnunet-transport.c:1353 src/transport/gnunet-transport.c:1376 #: src/transport/gnunet-transport.c:1419 msgid "Failed to connect to transport service\n" msgstr "" #: src/transport/gnunet-transport.c:1302 src/transport/gnunet-transport.c:1332 #: src/transport/gnunet-transport.c:1362 msgid "Failed to send request to transport service\n" msgstr "" #: src/transport/gnunet-transport.c:1381 msgid "Starting to receive benchmark data\n" msgstr "" #: src/transport/gnunet-transport.c:1465 msgid "print information for all peers (instead of only connected peers )" msgstr "" #: src/transport/gnunet-transport.c:1468 msgid "measure how fast we are receiving data from all peers (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1471 msgid "connect to a peer" msgstr "" #: src/transport/gnunet-transport.c:1474 msgid "disconnect to a peer" msgstr "" #: src/transport/gnunet-transport.c:1477 msgid "print information for all pending validations " msgstr "" #: src/transport/gnunet-transport.c:1480 msgid "print information for all pending validations continously" msgstr "" #: src/transport/gnunet-transport.c:1483 msgid "provide information about all current connections (once)" msgstr "" #: src/transport/gnunet-transport.c:1489 msgid "" "provide information about all connects and disconnect events (continuously)" msgstr "" #: src/transport/gnunet-transport.c:1491 msgid "do not resolve hostnames" msgstr "" #: src/transport/gnunet-transport.c:1493 msgid "peer identity" msgstr "" #: src/transport/gnunet-transport.c:1495 msgid "send data for benchmarking to the other peer (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1498 msgid "test transport configuration (involves external server)" msgstr "" #: src/transport/gnunet-transport.c:1507 msgid "Direct access to transport service." msgstr "" #: src/transport/plugin_transport_bluetooth.c:621 msgid "# Bluetooth ACKs sent" msgstr "" #: src/transport/plugin_transport_bluetooth.c:640 msgid "# Bluetooth messages defragmented" msgstr "" #: src/transport/plugin_transport_bluetooth.c:686 #: src/transport/plugin_transport_bluetooth.c:737 #: src/transport/plugin_transport_bluetooth.c:1942 msgid "# Bluetooth sessions allocated" msgstr "" #: src/transport/plugin_transport_bluetooth.c:837 msgid "# Bluetooth message fragments sent" msgstr "" #: src/transport/plugin_transport_bluetooth.c:861 msgid "# Bluetooth messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_bluetooth.c:969 #: src/transport/plugin_transport_bluetooth.c:1054 #: src/transport/plugin_transport_bluetooth.c:1944 msgid "# Bluetooth MAC endpoints allocated" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1307 msgid "# HELLO messages received via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1331 msgid "# fragments received via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1341 msgid "# ACKs received via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1401 msgid "# Bluetooth DATA messages discarded due to CRC32 error" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1512 msgid "# DATA messages received via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1547 msgid "# Bluetooth DATA messages processed" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1610 msgid "# HELLO beacons sent via Bluetooth" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1723 msgid "Bluetooth address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1923 #, c-format msgid "Helper binary `%s' not SUID, cannot run bluetooth transport\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1622 #, c-format msgid "Could not initialize curl multi handle, failed to start %s plugin!\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1697 #: src/transport/plugin_transport_http_server.c:3007 #, c-format msgid "Shutting down plugin `%s'\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1722 #: src/transport/plugin_transport_http_server.c:3063 #, c-format msgid "Shutdown for plugin `%s' complete\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1750 #: src/transport/plugin_transport_http_server.c:2907 #, c-format msgid "Maximum number of connections is %u\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1402 #, c-format msgid "" "Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data " "size %u\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1663 #, c-format msgid "Accepting connection (%u of %u) from `%s'\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1671 #, c-format msgid "" "Server reached maximum number connections (%u), rejecting new connection\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1958 msgid "" "Could not create a new TLS certificate, program `gnunet-transport-" "certificate-creation' could not be started!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1982 #, c-format msgid "No usable TLS certificate found and creating one at `%s/%s' failed!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2405 msgid "Require valid port number for service in configuration!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2437 src/util/service.c:698 #, c-format msgid "Failed to resolve `%s': %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2454 src/util/service.c:715 #, c-format msgid "Failed to find %saddress for `%s'.\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2565 #, c-format msgid "Found %u addresses to report to NAT service\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2637 msgid "Disabling IPv6 since it is not supported on this system!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2730 #, c-format msgid "IPv4 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2744 #, c-format msgid "IPv6 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2751 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2762 msgid "Port is required! Fix in configuration\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2769 #, c-format msgid "Using port %u\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2784 #, c-format msgid "Specific IPv4 address `%s' in configuration file is invalid!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2794 #, c-format msgid "Binding to IPv4 address %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2815 #, c-format msgid "Specific IPv6 address `%s' in configuration file is invalid!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2825 #, c-format msgid "Binding to IPv6 address %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2877 #, c-format msgid "Using external hostname `%s'\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2893 #, c-format msgid "Notifying transport only about hostname `%s'\n" msgstr "" #: src/transport/plugin_transport_smtp.c:223 #, c-format msgid "Received malformed message via %s. Ignored.\n" msgstr "" #: src/transport/plugin_transport_smtp.c:310 msgid "SMTP filter string to invalid, lacks ': '\n" msgstr "" #: src/transport/plugin_transport_smtp.c:319 #, c-format msgid "SMTP filter string to long, capped to `%s'\n" msgstr "" #: src/transport/plugin_transport_smtp.c:414 #: src/transport/plugin_transport_smtp.c:424 #: src/transport/plugin_transport_smtp.c:437 #: src/transport/plugin_transport_smtp.c:456 #: src/transport/plugin_transport_smtp.c:479 #: src/transport/plugin_transport_smtp.c:487 #: src/transport/plugin_transport_smtp.c:500 #: src/transport/plugin_transport_smtp.c:511 #, c-format msgid "SMTP: `%s' failed: %s.\n" msgstr "" #: src/transport/plugin_transport_smtp.c:652 msgid "No email-address specified, can not start SMTP transport.\n" msgstr "" #: src/transport/plugin_transport_smtp.c:664 msgid "# bytes received via SMTP" msgstr "" #: src/transport/plugin_transport_smtp.c:665 msgid "# bytes sent via SMTP" msgstr "" #: src/transport/plugin_transport_smtp.c:667 msgid "# bytes dropped by SMTP (outgoing)" msgstr "" #: src/transport/plugin_transport_tcp.c:555 #, c-format msgid "Unexpected address length: %u bytes\n" msgstr "" #: src/transport/plugin_transport_tcp.c:762 #: src/transport/plugin_transport_tcp.c:928 #: src/transport/plugin_transport_tcp.c:2005 #: src/transport/plugin_transport_tcp.c:2558 msgid "# TCP sessions active" msgstr "" #: src/transport/plugin_transport_tcp.c:795 #: src/transport/plugin_transport_tcp.c:921 #: src/transport/plugin_transport_tcp.c:1009 #: src/transport/plugin_transport_tcp.c:1056 #: src/transport/plugin_transport_tcp.c:1219 #: src/transport/plugin_transport_tcp.c:1237 msgid "# bytes currently in TCP buffers" msgstr "" #: src/transport/plugin_transport_tcp.c:798 msgid "# bytes discarded by TCP (disconnect)" msgstr "" #: src/transport/plugin_transport_tcp.c:1012 msgid "# bytes discarded by TCP (timeout)" msgstr "" #: src/transport/plugin_transport_tcp.c:1059 msgid "# bytes transmitted via TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:1193 #, c-format msgid "Trying to send with invalid session %p\n" msgstr "" #: src/transport/plugin_transport_tcp.c:1462 msgid "# requests to create session with invalid address" msgstr "" #: src/transport/plugin_transport_tcp.c:1567 msgid "# transport-service disconnect requests for TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:2055 msgid "# TCP WELCOME messages received" msgstr "" #: src/transport/plugin_transport_tcp.c:2215 msgid "# bytes received via TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:2279 msgid "# network-level TCP disconnect events" msgstr "" #: src/transport/plugin_transport_tcp.c:2437 src/util/service.c:582 #: src/util/service.c:588 #, c-format msgid "Require valid port number for service `%s' in configuration!\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2451 msgid "Failed to start service.\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2547 #, c-format msgid "TCP transport listening on port %llu\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2551 msgid "TCP transport not listening on any port (client only)\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2554 #, c-format msgid "TCP transport advertises itself as being on port %llu\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:167 msgid "# IPv6 multicast HELLO beacons received via udp" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:210 msgid "# IPv4 broadcast HELLO beacons received via udp" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:603 msgid "" "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:626 #, c-format msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n" msgstr "" #: src/transport/plugin_transport_udp.c:1513 #, c-format msgid "" "Trying to create session for address of unexpected length %u (should be %u " "or %u)\n" msgstr "" #: src/transport/plugin_transport_udp.c:2602 #, c-format msgid "" "UDP could not transmit message to `%s': Network seems down, please check " "your network configuration\n" msgstr "" #: src/transport/plugin_transport_udp.c:2616 msgid "" "UDP could not transmit IPv6 message! Please check your network configuration " "and disable IPv6 if your connection does not have a global IPv6 address\n" msgstr "" #: src/transport/plugin_transport_udp.c:2961 msgid "Failed to open UDP sockets\n" msgstr "" #: src/transport/plugin_transport_udp.c:3056 #, c-format msgid "Given `%s' option is out of range: %llu > %u\n" msgstr "" #: src/transport/plugin_transport_udp.c:3097 #, c-format msgid "Invalid IPv6 address: `%s'\n" msgstr "" #: src/transport/plugin_transport_udp.c:3168 msgid "Failed to create network sockets, plugin failed\n" msgstr "" #: src/transport/plugin_transport_unix.c:1321 #, c-format msgid "Cannot create path to `%s'\n" msgstr "" #: src/transport/plugin_transport_unix.c:1652 msgid "No UNIXPATH given in configuration!\n" msgstr "" #: src/transport/plugin_transport_unix.c:1688 msgid "Failed to open UNIX listen socket\n" msgstr "" #: src/transport/plugin_transport_wlan.c:620 msgid "# WLAN ACKs sent" msgstr "" #: src/transport/plugin_transport_wlan.c:639 msgid "# WLAN messages defragmented" msgstr "" #: src/transport/plugin_transport_wlan.c:688 #: src/transport/plugin_transport_wlan.c:772 #: src/transport/plugin_transport_wlan.c:1948 msgid "# WLAN sessions allocated" msgstr "" #: src/transport/plugin_transport_wlan.c:876 msgid "# WLAN message fragments sent" msgstr "" #: src/transport/plugin_transport_wlan.c:900 msgid "# WLAN messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_wlan.c:1008 #: src/transport/plugin_transport_wlan.c:1098 #: src/transport/plugin_transport_wlan.c:1950 msgid "# WLAN MAC endpoints allocated" msgstr "" #: src/transport/plugin_transport_wlan.c:1302 msgid "# HELLO messages received via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1326 msgid "# fragments received via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1336 msgid "# ACKs received via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1396 msgid "# WLAN DATA messages discarded due to CRC32 error" msgstr "" #: src/transport/plugin_transport_wlan.c:1518 msgid "# DATA messages received via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1553 msgid "# WLAN DATA messages processed" msgstr "" #: src/transport/plugin_transport_wlan.c:1616 msgid "# HELLO beacons sent via WLAN" msgstr "" #: src/transport/plugin_transport_wlan.c:1729 msgid "WLAN address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_wlan.c:1929 #, c-format msgid "Helper binary `%s' not SUID, cannot run WLAN transport\n" msgstr "" #: src/transport/transport_api.c:739 #, c-format msgid "Received unexpected message of type %u in %s:%u\n" msgstr "" #: src/transport/transport-testing.c:584 msgid "Failed to initialize testing library!\n" msgstr "" #: src/tun/regex.c:129 #, c-format msgid "Bad mask: %d\n" msgstr "" #: src/util/bio.c:170 src/util/bio.c:178 #, c-format msgid "Error reading `%s': %s" msgstr "" #: src/util/bio.c:180 msgid "End of file" msgstr "" #: src/util/bio.c:237 #, c-format msgid "Error reading length of string `%s'" msgstr "" #: src/util/bio.c:247 #, c-format msgid "String `%s' longer than allowed (%u > %u)" msgstr "" #: src/util/bio.c:293 #, c-format msgid "Serialized metadata `%s' larger than allowed (%u>%u)" msgstr "" #: src/util/bio.c:307 #, c-format msgid "Metadata `%s' failed to deserialize" msgstr "" #: src/util/client.c:261 src/util/client.c:858 src/util/service.c:619 #, c-format msgid "UNIXPATH `%s' too long, maximum length is %llu\n" msgstr "" #: src/util/client.c:265 src/util/client.c:863 src/util/service.c:623 #, c-format msgid "Using `%s' instead\n" msgstr "" #: src/util/client.c:360 #, c-format msgid "" "Could not determine valid hostname and port for service `%s' from " "configuration.\n" msgstr "" #: src/util/client.c:368 #, c-format msgid "Need a non-empty hostname for service `%s'.\n" msgstr "" #: src/util/client.c:1008 #, c-format msgid "Could not connect to service `%s', configuration broken.\n" msgstr "" #: src/util/client.c:1020 #, c-format msgid "Failure to transmit request to service `%s'\n" msgstr "" #: src/util/client.c:1303 msgid "Could not submit request, not expecting to receive a response.\n" msgstr "" #: src/util/common_logging.c:254 src/util/common_logging.c:1039 msgid "DEBUG" msgstr "" #: src/util/common_logging.c:256 src/util/common_logging.c:1037 msgid "INFO" msgstr "" #: src/util/common_logging.c:258 src/util/common_logging.c:1035 msgid "WARNING" msgstr "" #: src/util/common_logging.c:260 src/util/common_logging.c:1033 msgid "ERROR" msgstr "" #: src/util/common_logging.c:262 src/util/common_logging.c:1041 msgid "NONE" msgstr "" #: src/util/common_logging.c:391 #, c-format msgid "Failed to create or access directory for log file `%s'\n" msgstr "" #: src/util/common_logging.c:817 #, c-format msgid "Message `%.*s' repeated %u times in the last %s\n" msgstr "" #: src/util/common_logging.c:1042 msgid "INVALID" msgstr "" #: src/util/common_logging.c:1157 msgid "unknown address" msgstr "" #: src/util/common_logging.c:1196 msgid "invalid address" msgstr "" #: src/util/common_logging.c:1214 #, c-format msgid "Configuration fails to specify option `%s' in section `%s'!\n" msgstr "" #: src/util/common_logging.c:1235 #, c-format msgid "" "Configuration specifies invalid value for option `%s' in section `%s': %s\n" msgstr "" #: src/util/configuration.c:288 #, c-format msgid "Syntax error while deserializing in line %u\n" msgstr "" #: src/util/configuration.c:996 #, c-format msgid "" "Configuration value '%s' for '%s' in section '%s' is not in set of legal " "choices\n" msgstr "" #: src/util/configuration.c:1066 #, c-format msgid "Recursive expansion suspected, aborting $-expansion for term `%s'\n" msgstr "" #: src/util/configuration.c:1098 #, c-format msgid "Missing closing `%s' in option `%s'\n" msgstr "" #: src/util/configuration.c:1172 #, c-format msgid "" "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined " "as an environmental variable\n" msgstr "" #: src/util/connection.c:423 #, c-format msgid "Access denied to `%s'\n" msgstr "" #: src/util/connection.c:438 #, c-format msgid "Accepting connection from `%s': %p\n" msgstr "" #: src/util/connection.c:553 #, c-format msgid "" "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n" msgstr "" #: src/util/connection.c:751 src/util/connection.c:919 #, c-format msgid "Trying to connect to `%s' (%p)\n" msgstr "" #: src/util/connection.c:910 #, c-format msgid "Attempt to connect to `%s' failed\n" msgstr "" #: src/util/container_bloomfilter.c:531 #, c-format msgid "" "Size of file on disk is incorrect for this Bloom filter (want %llu, have " "%llu)\n" msgstr "" #: src/util/crypto_ecc.c:702 src/util/crypto_ecc.c:740 #: src/util/crypto_ecc.c:858 src/util/crypto_ecc.c:896 #, c-format msgid "Could not acquire lock on file `%s': %s...\n" msgstr "" #: src/util/crypto_ecc.c:707 src/util/crypto_ecc.c:863 msgid "Creating a new private key. This may take a while.\n" msgstr "" #: src/util/crypto_ecc.c:744 src/util/crypto_ecc.c:900 msgid "This may be ok if someone is currently generating a private key.\n" msgstr "" #: src/util/crypto_ecc.c:774 src/util/crypto_ecc.c:930 #, c-format msgid "" "When trying to read key file `%s' I found %u bytes but I need at least %u.\n" msgstr "" #: src/util/crypto_ecc.c:778 src/util/crypto_ecc.c:934 msgid "This may be ok if someone is currently generating a key.\n" msgstr "" #: src/util/crypto_ecc.c:1016 msgid "Could not load peer's private key\n" msgstr "" #: src/util/crypto_ecc.c:1120 #, c-format msgid "ECC signing failed at %s:%d: %s\n" msgstr "" #: src/util/crypto_ecc.c:1170 #, c-format msgid "EdDSA signing failed at %s:%d: %s\n" msgstr "" #: src/util/crypto_ecc.c:1244 #, c-format msgid "ECDSA signature verification failed at %s:%d: %s\n" msgstr "" #: src/util/crypto_ecc.c:1301 #, c-format msgid "EdDSA signature verification failed at %s:%d: %s\n" msgstr "" #: src/util/crypto_random.c:284 #, c-format msgid "libgcrypt has not the expected version (version %s is required).\n" msgstr "" #: src/util/disk.c:1184 #, c-format msgid "Expected `%s' to be a directory!\n" msgstr "" #: src/util/disk.c:1546 src/util/service.c:1318 #, c-format msgid "Cannot obtain information about user `%s': %s\n" msgstr "" #: src/util/getopt.c:568 #, c-format msgid "%s: option `%s' is ambiguous\n" msgstr "" #: src/util/getopt.c:592 #, c-format msgid "%s: option `--%s' does not allow an argument\n" msgstr "" #: src/util/getopt.c:597 #, c-format msgid "%s: option `%c%s' does not allow an argument\n" msgstr "" #: src/util/getopt.c:614 src/util/getopt.c:781 #, c-format msgid "%s: option `%s' requires an argument\n" msgstr "" #: src/util/getopt.c:643 #, c-format msgid "%s: unrecognized option `--%s'\n" msgstr "" #: src/util/getopt.c:647 #, c-format msgid "%s: unrecognized option `%c%s'\n" msgstr "" #: src/util/getopt.c:672 #, c-format msgid "%s: illegal option -- %c\n" msgstr "" #: src/util/getopt.c:674 #, c-format msgid "%s: invalid option -- %c\n" msgstr "" #: src/util/getopt.c:702 src/util/getopt.c:829 #, c-format msgid "%s: option requires an argument -- %c\n" msgstr "" #: src/util/getopt.c:750 #, c-format msgid "%s: option `-W %s' is ambiguous\n" msgstr "" #: src/util/getopt.c:768 #, c-format msgid "%s: option `-W %s' does not allow an argument\n" msgstr "" #: src/util/getopt.c:933 #, c-format msgid "Use %s to get a list of options.\n" msgstr "" #: src/util/getopt_helpers.c:84 #, c-format msgid "" "Arguments mandatory for long options are also mandatory for short options.\n" msgstr "" #: src/util/getopt_helpers.c:268 src/util/getopt_helpers.c:326 #, c-format msgid "You must pass a number to the `%s' option.\n" msgstr "" #: src/util/getopt_helpers.c:298 #, c-format msgid "You must pass relative time to the `%s' option.\n" msgstr "" #: src/util/gnunet-config.c:90 #, c-format msgid "--section argument is required\n" msgstr "" #: src/util/gnunet-config.c:133 #, c-format msgid "--option argument required to set value\n" msgstr "" #: src/util/gnunet-config.c:160 msgid "obtain option of value as a filename (with $-expansion)" msgstr "" #: src/util/gnunet-config.c:163 msgid "name of the section to access" msgstr "" #: src/util/gnunet-config.c:166 msgid "name of the option to access" msgstr "" #: src/util/gnunet-config.c:169 msgid "value to set" msgstr "" #: src/util/gnunet-config.c:178 msgid "Manipulate GNUnet configuration files" msgstr "" #: src/util/gnunet-ecc.c:75 #, c-format msgid "Failed to open `%s': %s\n" msgstr "" #: src/util/gnunet-ecc.c:81 #, c-format msgid "Generating %u keys, please wait" msgstr "" #: src/util/gnunet-ecc.c:97 #, c-format msgid "" "\n" "Failed to write to `%s': %s\n" msgstr "" #: src/util/gnunet-ecc.c:107 #, c-format msgid "" "\n" "Finished!\n" msgstr "" #: src/util/gnunet-ecc.c:110 #, c-format msgid "" "\n" "Error, %u keys not generated\n" msgstr "" #: src/util/gnunet-ecc.c:199 #, c-format msgid "Hostkeys file `%s' not found\n" msgstr "" #: src/util/gnunet-ecc.c:210 #, c-format msgid "Hostkeys file `%s' is empty\n" msgstr "" #: src/util/gnunet-ecc.c:232 #, c-format msgid "Could not read hostkey file: %s\n" msgstr "" #: src/util/gnunet-ecc.c:283 msgid "No hostkey file specified on command line\n" msgstr "" #: src/util/gnunet-ecc.c:349 msgid "list keys included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:352 msgid "number of keys to list included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:355 msgid "create COUNT public-private key pairs (for testing)" msgstr "" #: src/util/gnunet-ecc.c:358 msgid "print the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:361 msgid "print the hash of the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:364 msgid "print examples of ECC operations (used for compatibility testing)" msgstr "" #: src/util/gnunet-ecc.c:375 msgid "Manipulate GNUnet private ECC key files" msgstr "" #: src/util/gnunet-resolver.c:149 msgid "perform a reverse lookup" msgstr "" #: src/util/gnunet-resolver.c:160 msgid "Use build-in GNUnet stub resolver" msgstr "" #: src/util/gnunet-scrypt.c:279 msgid "number of bits to require for the proof of work" msgstr "" #: src/util/gnunet-scrypt.c:282 msgid "file with private key, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:285 msgid "file with proof of work, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:288 msgid "time to wait between calculations" msgstr "" #: src/util/gnunet-scrypt.c:299 msgid "Manipulate GNUnet proof of work files" msgstr "" #: src/util/gnunet-service-resolver.c:299 #, c-format msgid "Could not resolve `%s' (%s): %s\n" msgstr "" #: src/util/gnunet-service-resolver.c:371 #: src/util/gnunet-service-resolver.c:412 #, c-format msgid "Could not find IP of host `%s': %s\n" msgstr "" #: src/util/gnunet-uri.c:84 #, c-format msgid "No URI specified on command line\n" msgstr "" #: src/util/gnunet-uri.c:89 #, c-format msgid "Invalid URI: does not start with `%s'\n" msgstr "" #: src/util/gnunet-uri.c:96 #, c-format msgid "Invalid URI: fails to specify subsystem\n" msgstr "" #: src/util/gnunet-uri.c:106 #, c-format msgid "No handler known for subsystem `%s'\n" msgstr "" #: src/util/gnunet-uri.c:168 msgid "Perform default-actions for GNUnet URIs" msgstr "" #: src/util/helper.c:338 #, c-format msgid "Error reading from `%s': %s\n" msgstr "" #: src/util/helper.c:383 #, c-format msgid "Failed to parse inbound message from helper `%s'\n" msgstr "" #: src/util/helper.c:609 #, c-format msgid "Error writing to `%s': %s\n" msgstr "" #: src/util/network.c:134 #, c-format msgid "Unable to shorten unix path `%s' while keeping name unique\n" msgstr "" #: src/util/network.c:1355 src/util/network.c:1480 #, c-format msgid "" "Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n" msgstr "" #: src/util/os_installation.c:421 #, c-format msgid "" "Could not determine installation path for %s. Set `%s' environment " "variable.\n" msgstr "" #: src/util/os_installation.c:766 #, c-format msgid "Could not find binary `%s' in PATH!\n" msgstr "" #: src/util/os_installation.c:826 #, c-format msgid "CreateProcess failed for binary %s (%d).\n" msgstr "" #: src/util/os_installation.c:836 #, c-format msgid "GetExitCodeProcess failed for binary %s (%d).\n" msgstr "" #: src/util/plugin.c:87 #, c-format msgid "Initialization of plugin mechanism failed: %s!\n" msgstr "" #: src/util/plugin.c:148 #, c-format msgid "`%s' failed to resolve method '%s' with error: %s\n" msgstr "" #: src/util/plugin.c:223 #, c-format msgid "`%s' failed for library `%s' with error: %s\n" msgstr "" #: src/util/plugin.c:382 msgid "Could not determine plugin installation path.\n" msgstr "" #: src/util/program.c:246 src/util/service.c:1452 #, c-format msgid "Malformed configuration file `%s', exit ...\n" msgstr "" #: src/util/program.c:258 src/util/service.c:1467 #, c-format msgid "Could not access configuration file `%s'\n" msgstr "" #: src/util/program.c:263 src/util/service.c:1462 msgid "Malformed configuration, exit ...\n" msgstr "" #: src/util/resolver_api.c:198 #, c-format msgid "Must specify `%s' for `%s' in configuration!\n" msgstr "" #: src/util/resolver_api.c:216 #, c-format msgid "" "Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n" msgstr "" #: src/util/resolver_api.c:348 #, c-format msgid "Timeout trying to resolve IP address `%s'.\n" msgstr "" #: src/util/resolver_api.c:352 #, c-format msgid "Timeout trying to resolve hostname `%s'.\n" msgstr "" #: src/util/resolver_api.c:908 #, c-format msgid "Could not resolve our FQDN : %s\n" msgstr "" #: src/util/scheduler.c:813 msgid "Looks like we're busy waiting...\n" msgstr "" #: src/util/scheduler.c:948 #, c-format msgid "Attempt to cancel dead task %llu!\n" msgstr "" #: src/util/server.c:484 #, c-format msgid "`%s' failed for port %d (%s).\n" msgstr "" #: src/util/server.c:493 #, c-format msgid "`%s' failed for port %d (%s): address already in use\n" msgstr "" #: src/util/server.c:499 #, c-format msgid "`%s' failed for `%s': address already in use\n" msgstr "" #: src/util/server.c:892 #, c-format msgid "" "Processing code for message of type %u did not call " "`GNUNET_SERVER_receive_done' after %s\n" msgstr "" #: src/util/service.c:347 #, c-format msgid "Unknown address family %d\n" msgstr "" #: src/util/service.c:354 #, c-format msgid "Access from `%s' denied to service `%s'\n" msgstr "" #: src/util/service.c:409 #, c-format msgid "Could not parse IPv4 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:446 #, c-format msgid "Could not parse IPv6 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:563 #, c-format msgid "" "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n" msgstr "" #: src/util/service.c:653 #, c-format msgid "" "Disabling UNIX domain socket support for service `%s', failed to create UNIX " "domain socket: %s\n" msgstr "" #: src/util/service.c:669 #, c-format msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n" msgstr "" #: src/util/service.c:903 msgid "Could not access a pre-bound socket, will try to bind myself\n" msgstr "" #: src/util/service.c:952 src/util/service.c:970 #, c-format msgid "Specified value for `%s' of service `%s' is invalid\n" msgstr "" #: src/util/service.c:995 #, c-format msgid "Could not access pre-bound socket %u, will try to bind myself\n" msgstr "" #: src/util/service.c:1165 #, c-format msgid "Failed to start `%s' at `%s'\n" msgstr "" #: src/util/service.c:1207 #, c-format msgid "Service `%s' runs at %s\n" msgstr "" #: src/util/service.c:1256 msgid "Service process failed to initialize\n" msgstr "" #: src/util/service.c:1260 msgid "Service process could not initialize server function\n" msgstr "" #: src/util/service.c:1264 msgid "Service process failed to report status\n" msgstr "" #: src/util/service.c:1319 msgid "No such user" msgstr "" #: src/util/service.c:1332 #, c-format msgid "Cannot change user/group to `%s': %s\n" msgstr "" #: src/util/service.c:1402 msgid "do daemonize (detach from terminal)" msgstr "" #: src/util/signal.c:89 #, c-format msgid "signal (%d, %p) returned %d.\n" msgstr "" #: src/util/strings.c:145 msgid "b" msgstr "" #: src/util/strings.c:433 #, c-format msgid "Character sets requested were `%s'->`%s'\n" msgstr "" #: src/util/strings.c:561 msgid "Failed to expand `$HOME': environment variable `HOME' not set" msgstr "" #: src/util/strings.c:658 msgid "µs" msgstr "" #: src/util/strings.c:662 msgid "forever" msgstr "" #: src/util/strings.c:664 msgid "0 ms" msgstr "" #: src/util/strings.c:670 msgid "ms" msgstr "" #: src/util/strings.c:676 msgid "s" msgstr "" #: src/util/strings.c:682 msgid "m" msgstr "" #: src/util/strings.c:688 msgid "h" msgstr "" #: src/util/strings.c:695 msgid "day" msgstr "" #: src/util/strings.c:697 msgid "days" msgstr "" #: src/util/strings.c:726 msgid "end of time" msgstr "" #: src/util/strings.c:1159 msgid "IPv6 address did not start with `['\n" msgstr "" #: src/util/strings.c:1167 msgid "IPv6 address did contain ':' to separate port number\n" msgstr "" #: src/util/strings.c:1173 msgid "IPv6 address did contain ']' before ':' to separate port number\n" msgstr "" #: src/util/strings.c:1180 msgid "IPv6 address did contain a valid port number after the last ':'\n" msgstr "" #: src/util/strings.c:1189 #, c-format msgid "Invalid IPv6 address `%s': %s\n" msgstr "" #: src/util/strings.c:1395 src/util/strings.c:1411 msgid "Port not in range\n" msgstr "" #: src/util/strings.c:1420 #, c-format msgid "Malformed port policy `%s'\n" msgstr "" #: src/util/strings.c:1503 src/util/strings.c:1534 src/util/strings.c:1582 #: src/util/strings.c:1603 #, c-format msgid "Invalid format for IP: `%s'\n" msgstr "" #: src/util/strings.c:1560 #, c-format msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)." msgstr "" #: src/util/strings.c:1612 #, c-format msgid "Invalid format: `%s'\n" msgstr "" #: src/util/strings.c:1664 #, c-format msgid "Invalid network notation (does not end with ';': `%s')\n" msgstr "" #: src/util/strings.c:1714 #, c-format msgid "Wrong format `%s' for netmask\n" msgstr "" #: src/util/strings.c:1745 #, c-format msgid "Wrong format `%s' for network\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:550 src/vpn/gnunet-service-vpn.c:1086 msgid "# Active channels" msgstr "" #: src/vpn/gnunet-service-vpn.c:642 msgid "# Bytes given to mesh for transmission" msgstr "" #: src/vpn/gnunet-service-vpn.c:680 msgid "# Bytes dropped in mesh queue (overflow)" msgstr "" #: src/vpn/gnunet-service-vpn.c:753 msgid "# Mesh channels created" msgstr "" #: src/vpn/gnunet-service-vpn.c:784 msgid "Failed to setup mesh channel!\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:978 #, c-format msgid "Protocol %u not supported, dropping\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1305 msgid "# ICMPv4 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1326 msgid "# ICMPv6 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1531 msgid "# Packets received from TUN interface" msgstr "" #: src/vpn/gnunet-service-vpn.c:1564 src/vpn/gnunet-service-vpn.c:1600 #, c-format msgid "Packet received for unmapped destination `%s' (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1610 msgid "Received IPv4 packet with options (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1624 #, c-format msgid "Received packet of unknown protocol %d from TUN (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1706 msgid "# ICMP packets received from mesh" msgstr "" #: src/vpn/gnunet-service-vpn.c:2045 msgid "# UDP packets received from mesh" msgstr "" #: src/vpn/gnunet-service-vpn.c:2200 msgid "# TCP packets received from mesh" msgstr "" #: src/vpn/gnunet-service-vpn.c:2351 msgid "Failed to find unallocated IPv4 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2406 msgid "Failed to find unallocated IPv6 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2447 src/vpn/gnunet-service-vpn.c:2663 msgid "# Active destinations" msgstr "" #: src/vpn/gnunet-service-vpn.c:2715 msgid "Failed to allocate IP address for new destination\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2982 msgid "Must specify valid IPv6 address" msgstr "" #: src/vpn/gnunet-service-vpn.c:3006 msgid "Must specify valid IPv6 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3014 msgid "IPv6 support disabled as this system does not support IPv6\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:3027 msgid "Must specify valid IPv4 address" msgstr "" #: src/vpn/gnunet-service-vpn.c:3040 msgid "Must specify valid IPv4 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3050 msgid "IPv4 support disabled as this system does not support IPv4\n" msgstr "" #: src/vpn/gnunet-vpn.c:147 msgid "Error creating tunnel\n" msgstr "" #: src/vpn/gnunet-vpn.c:190 src/vpn/gnunet-vpn.c:221 #, c-format msgid "Option `%s' makes no sense with option `%s'.\n" msgstr "" #: src/vpn/gnunet-vpn.c:203 #, c-format msgid "Option `%s' or `%s' is required.\n" msgstr "" #: src/vpn/gnunet-vpn.c:215 #, c-format msgid "Option `%s' or `%s' is required when using option `%s'.\n" msgstr "" #: src/vpn/gnunet-vpn.c:235 #, c-format msgid "`%s' is not a valid peer identifier.\n" msgstr "" #: src/vpn/gnunet-vpn.c:255 #, c-format msgid "`%s' is not a valid IP address.\n" msgstr "" #: src/vpn/gnunet-vpn.c:290 msgid "request that result should be an IPv4 address" msgstr "" #: src/vpn/gnunet-vpn.c:293 msgid "request that result should be an IPv6 address" msgstr "" #: src/vpn/gnunet-vpn.c:296 msgid "how long should the mapping be valid for new tunnels?" msgstr "" #: src/vpn/gnunet-vpn.c:299 msgid "destination IP for the tunnel" msgstr "" #: src/vpn/gnunet-vpn.c:302 msgid "peer offering the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:305 msgid "name of the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:308 msgid "service is offered via TCP" msgstr "" #: src/vpn/gnunet-vpn.c:311 msgid "service is offered via UDP" msgstr "" #: src/vpn/gnunet-vpn.c:323 msgid "Setup tunnels via VPN." msgstr "" #: src/include/gnunet_common.h:566 src/include/gnunet_common.h:573 #: src/include/gnunet_common.h:581 #, c-format msgid "Assertion failed at %s:%d.\n" msgstr "" #: src/include/gnunet_common.h:593 #, c-format msgid "External protocol violation detected at %s:%d.\n" msgstr "" #: src/include/gnunet_common.h:620 src/include/gnunet_common.h:629 #, c-format msgid "`%s' failed on file `%s' at %s:%d with error: %s\n" msgstr "" gnunet-0.10.1/po/stamp-po0000644000175000017500000000001212320736475012115 00000000000000timestamp gnunet-0.10.1/po/sv.po0000644000175000017500000112274512320736474011444 00000000000000# Swedish translation of GNUnet. # Copyright (C) 2006 Free Software Foundation, Inc. # This file is distributed under the same license as the GNUnet package. # Daniel Nylander , 2006. # msgid "" msgstr "" "Project-Id-Version: GNUnet 0.7.0b\n" "Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org\n" "POT-Creation-Date: 2014-04-08 11:11+0200\n" "PO-Revision-Date: 2006-01-21 17:16+0100\n" "Last-Translator: Daniel Nylander \n" "Language-Team: Swedish \n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: src/arm/arm_api.c:337 msgid "Client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/arm_monitor_api.c:321 msgid "" "Monitoring client was disconnected from arm service, trying to reconnect.\n" msgstr "" #: src/arm/gnunet-arm.c:164 #, fuzzy, c-format msgid "Failed to remove configuration file %s\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/arm/gnunet-arm.c:170 #, fuzzy, c-format msgid "Failed to remove servicehome directory %s\n" msgstr "Filformatsfel (inte en GNUnet-katalog?)\n" #: src/arm/gnunet-arm.c:216 src/testbed/gnunet-service-testbed_peers.c:1013 msgid "Message was sent successfully" msgstr "" #: src/arm/gnunet-arm.c:218 #, fuzzy msgid "Misconfiguration (can not connect to the ARM service)" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/arm/gnunet-arm.c:220 src/testbed/gnunet-service-testbed_peers.c:1017 #, fuzzy msgid "We disconnected from ARM before we could send a request" msgstr "# av anslutna parter" #: src/arm/gnunet-arm.c:222 src/testbed/gnunet-service-testbed_peers.c:1019 msgid "ARM API is busy" msgstr "" #: src/arm/gnunet-arm.c:224 msgid "Request does not fit into a message" msgstr "" #: src/arm/gnunet-arm.c:226 src/testbed/gnunet-service-testbed_peers.c:1023 #, fuzzy msgid "Request timed out" msgstr "# sessionsnycklar accepterade" #: src/arm/gnunet-arm.c:228 src/testbed/gnunet-service-testbed_peers.c:1025 #, fuzzy msgid "Unknown request status" msgstr "Okänd operation \"%s\"\n" #: src/arm/gnunet-arm.c:244 src/testbed/gnunet-service-testbed_peers.c:1041 #, fuzzy, c-format msgid "%s is stopped" msgstr "# byte krypterade" #: src/arm/gnunet-arm.c:246 src/testbed/gnunet-service-testbed_peers.c:1043 #, fuzzy, c-format msgid "%s is starting" msgstr "\"%s\" startar\n" #: src/arm/gnunet-arm.c:248 src/testbed/gnunet-service-testbed_peers.c:1045 #, c-format msgid "%s is stopping" msgstr "" #: src/arm/gnunet-arm.c:250 src/testbed/gnunet-service-testbed_peers.c:1047 #, fuzzy, c-format msgid "%s is starting already" msgstr "\"%s\" startar\n" #: src/arm/gnunet-arm.c:252 src/testbed/gnunet-service-testbed_peers.c:1049 #, c-format msgid "%s is stopping already" msgstr "" #: src/arm/gnunet-arm.c:254 src/testbed/gnunet-service-testbed_peers.c:1051 #, c-format msgid "%s is started already" msgstr "" #: src/arm/gnunet-arm.c:256 src/testbed/gnunet-service-testbed_peers.c:1053 #, c-format msgid "%s is stopped already" msgstr "" #: src/arm/gnunet-arm.c:258 src/testbed/gnunet-service-testbed_peers.c:1055 #, fuzzy, c-format msgid "%s service is not known to ARM" msgstr "\"%s\" är inte en fil.\n" #: src/arm/gnunet-arm.c:260 src/testbed/gnunet-service-testbed_peers.c:1057 #, fuzzy, c-format msgid "%s service failed to start" msgstr "Misslyckades att starta samling.\n" #: src/arm/gnunet-arm.c:262 #, c-format msgid "%s service cannot be started because ARM is shutting down" msgstr "" #: src/arm/gnunet-arm.c:264 src/testbed/gnunet-service-testbed_peers.c:1061 #, c-format msgid "%.s Unknown result code." msgstr "" #: src/arm/gnunet-arm.c:297 msgid "Fatal error initializing ARM API.\n" msgstr "" #: src/arm/gnunet-arm.c:326 src/arm/gnunet-arm.c:335 #, fuzzy, c-format msgid "Failed to start the ARM service: %s\n" msgstr "Misslyckades att starta samling.\n" #: src/arm/gnunet-arm.c:369 #, fuzzy, c-format msgid "Failed to send a stop request to the ARM service: %s\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/arm/gnunet-arm.c:379 #, fuzzy, c-format msgid "Failed to stop the ARM service: %s\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/arm/gnunet-arm.c:421 #, fuzzy, c-format msgid "Failed to send a request to start the `%s' service: %%s\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/arm/gnunet-arm.c:431 #, fuzzy, c-format msgid "Failed to start the `%s' service: %s\n" msgstr "Misslyckades att starta samling.\n" #: src/arm/gnunet-arm.c:468 #, fuzzy, c-format msgid "Failed to send a request to kill the `%s' service: %%s\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/arm/gnunet-arm.c:479 #, fuzzy, c-format msgid "Failed to kill the `%s' service: %s\n" msgstr "Fel vid %s:%d.\n" #: src/arm/gnunet-arm.c:517 #, fuzzy, c-format msgid "Failed to request a list of services: %s\n" msgstr "Misslyckades att starta samling.\n" #: src/arm/gnunet-arm.c:525 #, fuzzy msgid "Error communicating with ARM. ARM not running?\n" msgstr "Skriv ut information om GNUnets motparter." #: src/arm/gnunet-arm.c:530 #, fuzzy msgid "Running services:\n" msgstr "Startade samling \"%s\".\n" #: src/arm/gnunet-arm.c:612 #, c-format msgid "Now only monitoring, press CTRL-C to stop.\n" msgstr "" #: src/arm/gnunet-arm.c:643 #, c-format msgid "Stopped %s.\n" msgstr "" #: src/arm/gnunet-arm.c:646 #, fuzzy, c-format msgid "Starting %s...\n" msgstr "Startade samling \"%s\".\n" #: src/arm/gnunet-arm.c:649 #, c-format msgid "Stopping %s...\n" msgstr "" #: src/arm/gnunet-arm.c:660 #, fuzzy, c-format msgid "Unknown status %u for service %s.\n" msgstr "Okänd operation \"%s\"\n" #: src/arm/gnunet-arm.c:724 msgid "stop all GNUnet services" msgstr "" #: src/arm/gnunet-arm.c:726 msgid "start a particular service" msgstr "" #: src/arm/gnunet-arm.c:728 msgid "stop a particular service" msgstr "" #: src/arm/gnunet-arm.c:730 msgid "start all GNUnet default services" msgstr "" #: src/arm/gnunet-arm.c:733 msgid "stop and start all GNUnet default services" msgstr "" #: src/arm/gnunet-arm.c:736 msgid "delete config file and directory on exit" msgstr "" #: src/arm/gnunet-arm.c:739 msgid "monitor ARM activities" msgstr "" #: src/arm/gnunet-arm.c:741 msgid "don't print status messages" msgstr "" #: src/arm/gnunet-arm.c:744 msgid "timeout in MSECS milliseconds for completing current operation" msgstr "" #: src/arm/gnunet-arm.c:746 #, fuzzy msgid "list currently running services" msgstr "Startade samling \"%s\".\n" #: src/arm/gnunet-arm.c:748 msgid "don't let gnunet-service-arm inherit standard output" msgstr "" #: src/arm/gnunet-arm.c:750 msgid "don't let gnunet-service-arm inherit standard error" msgstr "" #: src/arm/gnunet-arm.c:761 msgid "Control services and the Automated Restart Manager (ARM)" msgstr "" #: src/arm/gnunet-service-arm.c:266 #, fuzzy msgid "Could not send status result to client\n" msgstr "Kunde inte skicka begäran till gnunetd.\n" #: src/arm/gnunet-service-arm.c:302 #, fuzzy msgid "Could not send list result to client\n" msgstr "Kunde inte skicka begäran till gnunetd.\n" #: src/arm/gnunet-service-arm.c:529 #, fuzzy, c-format msgid "Failed to start service `%s'\n" msgstr "Misslyckades att starta samling.\n" #: src/arm/gnunet-service-arm.c:540 #, fuzzy, c-format msgid "Starting service `%s'\n" msgstr "Startade samling \"%s\".\n" #: src/arm/gnunet-service-arm.c:639 #, fuzzy, c-format msgid "Unable to create socket for service `%s': %s\n" msgstr "Kunde inte skapa användarkonto:" #: src/arm/gnunet-service-arm.c:661 #, c-format msgid "Unable to bind listening socket for service `%s' to address `%s': %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:695 #, c-format msgid "ARM now monitors connections to service `%s' at `%s'\n" msgstr "" #: src/arm/gnunet-service-arm.c:831 #, fuzzy, c-format msgid "Preparing to stop `%s'\n" msgstr "Startade samling \"%s\".\n" #: src/arm/gnunet-service-arm.c:1100 #, fuzzy, c-format msgid "Restarting service `%s'.\n" msgstr "Startade samling \"%s\".\n" #: src/arm/gnunet-service-arm.c:1193 msgid "exit" msgstr "" #: src/arm/gnunet-service-arm.c:1198 msgid "signal" msgstr "" #: src/arm/gnunet-service-arm.c:1203 #, fuzzy msgid "unknown" msgstr "Okänt fel" #: src/arm/gnunet-service-arm.c:1209 #, fuzzy, c-format msgid "Service `%s' took %s to terminate\n" msgstr "Tjänst borttagen.\n" #: src/arm/gnunet-service-arm.c:1231 #, c-format msgid "Service `%s' terminated normally, will restart at any time\n" msgstr "" #: src/arm/gnunet-service-arm.c:1246 #, c-format msgid "Service `%s' terminated with status %s/%d, will restart in %s\n" msgstr "" #: src/arm/gnunet-service-arm.c:1500 #, fuzzy, c-format msgid "Starting default services `%s'\n" msgstr "Startade samling \"%s\".\n" #: src/arm/gnunet-service-arm.c:1511 #, c-format msgid "Default service `%s' not configured correctly!\n" msgstr "" #: src/arm/gnunet-service-arm.c:1524 msgid "" "No default services configured, GNUnet will not really start right now.\n" msgstr "" #: src/arm/mockup-service.c:41 msgid "Initiating shutdown as requested by client.\n" msgstr "" #: src/ats/ats_api_performance.c:468 #, fuzzy, c-format msgid "Received %s message\n" msgstr "mottog ogiltigt \"%s\" meddelande\n" #: src/ats/ats_api_performance.c:511 #, fuzzy, c-format msgid "Received last message for %s \n" msgstr "Mottog ogiltigt \"%s\" meddelande frÃ¥n \"%s\".\n" #: src/ats/gnunet-ats-solver-eval.c:2199 src/ats/gnunet-ats-solver-eval.c:2233 #: src/ats/gnunet-service-ats_addresses.c:1980 #: src/ats/gnunet-service-ats_addresses.c:2024 #, c-format msgid "" "Could not load quota for network `%s': `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2205 #: src/ats/gnunet-service-ats_addresses.c:1987 #, c-format msgid "Outbound quota configure for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2212 #: src/ats/gnunet-service-ats_addresses.c:1995 #, c-format msgid "" "No outbound quota configured for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2239 #: src/ats/gnunet-service-ats_addresses.c:2031 #, c-format msgid "Inbound quota configured for network `%s' is %llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2246 #: src/ats/gnunet-service-ats_addresses.c:2039 #, c-format msgid "" "No outbound quota configure for network `%s', assigning default bandwidth " "%llu\n" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2671 #: src/ats-tests/gnunet-solver-eval.c:919 msgid "solver to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2674 src/ats/gnunet-ats-solver-eval.c:2677 #: src/ats-tests/gnunet-solver-eval.c:922 #: src/ats-tests/gnunet-solver-eval.c:925 msgid "experiment to use" msgstr "" #: src/ats/gnunet-ats-solver-eval.c:2680 #, fuzzy msgid "print logging" msgstr "Startade samling \"%s\".\n" #: src/ats/gnunet-service-ats_addresses.c:2217 #, c-format msgid "Initializing solver `%s '`%s'\n" msgstr "" #: src/ats/gnunet-service-ats_addresses.c:2220 #, fuzzy, c-format msgid "Failed to initialize solver `%s'!\n" msgstr "Kunde inte initiera SQLite.\n" #: src/ats/gnunet-service-ats_addresses.c:2243 #, fuzzy msgid "Failed to initialize solver!\n" msgstr "Kunde inte initiera SQLite.\n" #: src/ats/plugin_ats_mlp.c:892 msgid "Problem size too large, cannot allocate memory!\n" msgstr "" #: src/ats/plugin_ats_mlp.c:1329 #, fuzzy, c-format msgid "Adding address for peer `%s' multiple times\n" msgstr "Motpart \"%s\" med pÃ¥litlighet %8u och adress \"%s\"\n" #: src/ats/plugin_ats_mlp.c:1376 #, c-format msgid "Updating address property `%s' for peer `%s' %p not added before\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2122 #, c-format msgid "" "Adjusting inconsistent outbound quota configuration for network `%s', is " "%llu must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2131 #, c-format msgid "" "Adjusting inconsistent inbound quota configuration for network `%s', is %llu " "must be at least %llu\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2142 #, c-format msgid "" "Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2150 #, c-format msgid "" "Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n" msgstr "" #: src/ats/plugin_ats_mlp.c:2161 #, c-format msgid "Using default quota configuration for network `%s' (in/out) %llu/%llu\n" msgstr "" #: src/ats/plugin_ats_proportional.c:1511 #, fuzzy, c-format msgid "Invalid network type `%u' `%s': Disconnect!\n" msgstr "Kan inte öppna konfigurationsfil \"%s\".\n" #: src/ats-tests/ats-testing.c:72 msgid "Benchmarking done\n" msgstr "" #: src/ats-tests/ats-testing.c:105 #, fuzzy, c-format msgid "Failed to connect peer 0 and %u\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/ats-tests/ats-testing.c:413 #, c-format msgid "Connected master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:419 #, fuzzy, c-format msgid "Failed to connect master peer [%u] with slave [%u]\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/ats-tests/ats-testing.c:450 msgid "Connecting peers on CORE level\n" msgstr "" #: src/ats-tests/ats-testing.c:461 #, c-format msgid "Connecting master [%u] with slave [%u]\n" msgstr "" #: src/ats-tests/ats-testing.c:470 #, fuzzy, c-format msgid "Could not connect master [%u] and slave [%u]\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/ats-tests/ats-testing.c:490 src/ats-tests/ats-testing.c:671 #, fuzzy msgid "Initialization failed, shutdown\n" msgstr "Initiering av insticksmekanism misslyckades: %s!\n" #: src/ats-tests/ats-testing-log.c:842 msgid "Stop logging\n" msgstr "" #: src/ats-tests/ats-testing-log.c:893 #, fuzzy, c-format msgid "Start logging `%s'\n" msgstr "Startade samling \"%s\".\n" #: src/ats-tests/gnunet-ats-sim.c:86 #, c-format msgid "" "Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. " "= %u KiB/s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:169 #, c-format msgid "%u address resolutions had a timeout\n" msgstr "" #: src/ats-tool/gnunet-ats.c:171 #, c-format msgid "ATS returned results for %u addresses\n" msgstr "" #: src/ats-tool/gnunet-ats.c:232 #, fuzzy, c-format msgid "" "Peer `%s' plugin `%s', address `%s', `%s' bw out: %u Bytes/s, bw in %u Bytes/" "s, %s\n" msgstr "Motpart \"%s\" med pÃ¥litlighet %8u och adress \"%s\"\n" #: src/ats-tool/gnunet-ats.c:413 #, c-format msgid "Quota for network `%11s' (in/out): %10s / %10s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:433 src/core/gnunet-core.c:163 #: src/namestore/gnunet-namestore.c:550 src/transport/gnunet-transport.c:1246 #, fuzzy, c-format msgid "Service `%s' is not running\n" msgstr "\"%s\" är inte en fil.\n" #: src/ats-tool/gnunet-ats.c:445 src/transport/gnunet-transport.c:1255 #, fuzzy, c-format msgid "Failed to parse peer identity `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/ats-tool/gnunet-ats.c:454 #, c-format msgid "Please select one operation : %s or %s or %s or %s or %s\n" msgstr "" #: src/ats-tool/gnunet-ats.c:470 src/ats-tool/gnunet-ats.c:489 #: src/ats-tool/gnunet-ats.c:506 src/ats-tool/gnunet-ats.c:543 #, fuzzy, c-format msgid "Cannot connect to ATS service, exiting...\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/ats-tool/gnunet-ats.c:478 src/ats-tool/gnunet-ats.c:495 #, fuzzy, c-format msgid "Cannot issue request to ATS service, exiting...\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/ats-tool/gnunet-ats.c:515 #, fuzzy, c-format msgid "No preference type given!\n" msgstr "Skriv ut information om GNUnets motparter." #: src/ats-tool/gnunet-ats.c:520 #, c-format msgid "No peer given!\n" msgstr "" #: src/ats-tool/gnunet-ats.c:536 msgid "Valid type required\n" msgstr "" #: src/ats-tool/gnunet-ats.c:594 msgid "get list of active addresses currently used" msgstr "" #: src/ats-tool/gnunet-ats.c:596 msgid "get list of all active addresses" msgstr "" #: src/ats-tool/gnunet-ats.c:599 #, fuzzy msgid "do not resolve IP addresses to hostnames" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/ats-tool/gnunet-ats.c:601 msgid "monitor mode" msgstr "" #: src/ats-tool/gnunet-ats.c:603 #, fuzzy msgid "set preference for the given peer" msgstr "Skriv ut information om GNUnets motparter." #: src/ats-tool/gnunet-ats.c:605 msgid "print all configured quotas" msgstr "" #: src/ats-tool/gnunet-ats.c:607 msgid "peer id" msgstr "" #: src/ats-tool/gnunet-ats.c:610 msgid "preference type to set: latency | bandwidth" msgstr "" #: src/ats-tool/gnunet-ats.c:612 msgid "preference value" msgstr "" #: src/ats-tool/gnunet-ats.c:615 msgid "verbose output (include ATS address properties)" msgstr "" #: src/ats-tool/gnunet-ats.c:622 #, fuzzy msgid "Print information about ATS state" msgstr "Skriv ut information om GNUnets motparter." #: src/consensus/gnunet-consensus-profiler.c:437 #: src/secretsharing/gnunet-secretsharing-profiler.c:535 #, fuzzy msgid "number of peers in consensus" msgstr "antal iterationer" #: src/consensus/gnunet-consensus-profiler.c:440 msgid "how many peers receive one value?" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:443 #: src/set/gnunet-set-profiler.c:286 src/set/gnunet-set-profiler.c:289 #: src/set/gnunet-set-profiler.c:292 #, fuzzy msgid "number of values" msgstr "antal iterationer" #: src/consensus/gnunet-consensus-profiler.c:446 #, fuzzy msgid "consensus timeout" msgstr "# sessionsnycklar accepterade" #: src/consensus/gnunet-consensus-profiler.c:449 msgid "delay until consensus starts" msgstr "" #: src/consensus/gnunet-consensus-profiler.c:452 #: src/secretsharing/gnunet-secretsharing-profiler.c:550 msgid "be more verbose (print received values)" msgstr "" #: src/conversation/conversation_api.c:557 #: src/conversation/conversation_api_call.c:470 msgid "Connection to conversation service lost, trying to reconnect\n" msgstr "" #: src/conversation/gnunet-conversation.c:264 #, c-format msgid "Incoming call from `%s'. Please /accept #%u or /cancel %u the call.\n" msgstr "" #: src/conversation/gnunet-conversation.c:286 #, c-format msgid "Call from `%s' terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:319 #, c-format msgid "Call from `%s' suspended by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:324 #, c-format msgid "Call from `%s' resumed by other user\n" msgstr "" #: src/conversation/gnunet-conversation.c:342 #, c-format msgid "Ego `%s' no longer available, phone is now down.\n" msgstr "" #: src/conversation/gnunet-conversation.c:356 #, fuzzy msgid "Failed to setup phone (internal error)\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/conversation/gnunet-conversation.c:368 #, c-format msgid "" "Phone active on line %u. Type `/help' for a list of available commands\n" msgstr "" #: src/conversation/gnunet-conversation.c:390 #, c-format msgid "Resolved address of `%s'. Now ringing other party.\n" msgstr "" #: src/conversation/gnunet-conversation.c:397 #, fuzzy, c-format msgid "Connection established to `%s'\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/conversation/gnunet-conversation.c:404 #, fuzzy, c-format msgid "Failed to resolve `%s'\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/conversation/gnunet-conversation.c:411 msgid "Call terminated\n" msgstr "" #: src/conversation/gnunet-conversation.c:417 #, c-format msgid "Connection to `%s' suspended (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:423 #, c-format msgid "Connection to `%s' resumed (by other user)\n" msgstr "" #: src/conversation/gnunet-conversation.c:428 msgid "Error with the call, restarting it\n" msgstr "" #: src/conversation/gnunet-conversation.c:495 #, fuzzy, c-format msgid "Unknown command `%s'\n" msgstr "Okänd operation \"%s\"\n" #: src/conversation/gnunet-conversation.c:511 #: src/conversation/gnunet-conversation.c:525 #, c-format msgid "Ego `%s' not available\n" msgstr "" #: src/conversation/gnunet-conversation.c:518 #: src/conversation/gnunet-conversation.c:575 msgid "You are calling someone else already, hang up first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:533 #: src/conversation/gnunet-conversation.c:588 #, c-format msgid "You are answering call from `%s', hang up or suspend that call first!\n" msgstr "" #: src/conversation/gnunet-conversation.c:544 msgid "Call recipient missing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:599 msgid "There is no incoming call to accept here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:616 #, c-format msgid "There is no incoming call `%s' to accept right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:647 msgid "We currently do not have an address.\n" msgstr "" #: src/conversation/gnunet-conversation.c:670 #, c-format msgid "We are currently trying to locate the private key for the ego `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:675 #, c-format msgid "We are listening for incoming calls for ego `%s' on line %u.\n" msgstr "" #: src/conversation/gnunet-conversation.c:681 #: src/conversation/gnunet-conversation.c:705 #, c-format msgid "You are having a conversation with `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:686 msgid "" "We had an internal error setting up our phone line. You can still make " "calls.\n" msgstr "" #: src/conversation/gnunet-conversation.c:695 #, c-format msgid "We are trying to find the network address to call `%s'.\n" msgstr "" #: src/conversation/gnunet-conversation.c:700 #, c-format msgid "We are calling `%s', his phone should be ringing.\n" msgstr "" #: src/conversation/gnunet-conversation.c:719 msgid "Calls waiting:\n" msgstr "" #: src/conversation/gnunet-conversation.c:725 #, fuzzy, c-format msgid "#%u: `%s'\n" msgstr "Jag är ändpunkt \"%s\".\n" #: src/conversation/gnunet-conversation.c:753 #: src/conversation/gnunet-conversation.c:768 msgid "There is no call that could be suspended right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:801 #: src/conversation/gnunet-conversation.c:817 msgid "There is no call that could be resumed right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:824 #, c-format msgid "Already talking with `%s', cannot resume a call right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:833 msgid "There is no incoming call to resume here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:850 #, c-format msgid "There is no incoming call `%s' to resume right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:885 msgid "There is no call that could be cancelled right now.\n" msgstr "" #: src/conversation/gnunet-conversation.c:893 msgid "There is no incoming call to refuse here!\n" msgstr "" #: src/conversation/gnunet-conversation.c:910 #, c-format msgid "There is no incoming call `%s' to refuse right now!\n" msgstr "" #: src/conversation/gnunet-conversation.c:937 msgid "Use `/address' to find out which address this phone should have in GNS" msgstr "" #: src/conversation/gnunet-conversation.c:939 msgid "Use `/call USER.gnu' to call USER" msgstr "" #: src/conversation/gnunet-conversation.c:941 msgid "Use `/accept #NUM' to accept incoming call #NUM" msgstr "" #: src/conversation/gnunet-conversation.c:943 msgid "Use `/suspend' to suspend the active call" msgstr "" #: src/conversation/gnunet-conversation.c:945 msgid "" "Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming " "calls, no argument is needed to resume the current outgoing call." msgstr "" #: src/conversation/gnunet-conversation.c:947 msgid "Use `/cancel' to reject or terminate a call" msgstr "" #: src/conversation/gnunet-conversation.c:949 msgid "Use `/status' to print status information" msgstr "" #: src/conversation/gnunet-conversation.c:951 #, fuzzy msgid "Use `/quit' to terminate gnunet-conversation" msgstr "tillÃ¥ter klienter att fastställa gnunetds konfiguration" #: src/conversation/gnunet-conversation.c:953 msgid "Use `/help command' to get help for a specific command" msgstr "" #: src/conversation/gnunet-conversation.c:1151 #, fuzzy, c-format msgid "Name of our ego changed to `%s'\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/conversation/gnunet-conversation.c:1164 #, fuzzy, c-format msgid "Our ego `%s' was deleted!\n" msgstr "Pseudonym \"%s\" togs bort.\n" #: src/conversation/gnunet-conversation.c:1199 #, fuzzy msgid "You must specify the NAME of an ego to use\n" msgstr "Du mÃ¥ste ange en lista av filer att lägga in.\n" #: src/conversation/gnunet-conversation.c:1223 #, fuzzy msgid "Failed to start gnunet-helper-w32-console\n" msgstr "Misslyckades att starta samling.\n" #: src/conversation/gnunet-conversation.c:1249 msgid "sets the NAME of the ego to use for the phone (and name resolution)" msgstr "" #: src/conversation/gnunet-conversation.c:1252 msgid "sets the LINE to use for the phone" msgstr "" #: src/conversation/gnunet-conversation.c:1276 msgid "Enables having a conversation with other GNUnet users." msgstr "" #: src/conversation/gnunet-conversation-test.c:121 #, c-format msgid "" "\n" "End of transmission. Have a GNU day.\n" msgstr "" #: src/conversation/gnunet-conversation-test.c:149 #, c-format msgid "" "\n" "We are now playing your recording back. If you can hear it, your audio " "settings are working..." msgstr "" #: src/conversation/gnunet-conversation-test.c:215 #, c-format msgid "" "We will now be recording you for %s. After that time, the recording will be " "played back to you..." msgstr "" #: src/conversation/gnunet-conversation-test.c:248 #: src/multicast/gnunet-multicast.c:70 src/revocation/gnunet-revocation.c:522 #: src/template/gnunet-template.c:70 #, fuzzy msgid "help text" msgstr "hjälptext för -t" #: src/conversation/gnunet-helper-audio-playback.c:305 #, fuzzy, c-format msgid "pa_stream_write() failed: %s\n" msgstr "\"%s\" %s misslyckades: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:587 msgid "gnunet-helper-audio-playback - Got signal, exiting\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:612 #: src/conversation/gnunet-helper-audio-record.c:545 #, fuzzy msgid "Connection established.\n" msgstr "Samling stoppad.\n" #: src/conversation/gnunet-helper-audio-playback.c:617 #: src/conversation/gnunet-helper-audio-record.c:550 #, fuzzy, c-format msgid "pa_stream_new() failed: %s\n" msgstr "\"%s\" %s misslyckades: %s\n" #: src/conversation/gnunet-helper-audio-playback.c:631 #, c-format msgid "pa_stream_connect_playback() failed: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:644 #: src/conversation/gnunet-helper-audio-record.c:576 #, fuzzy, c-format msgid "Connection failure: %s\n" msgstr " Anslutning misslyckades (fel?)\n" #: src/conversation/gnunet-helper-audio-playback.c:665 #: src/conversation/gnunet-helper-audio-record.c:599 msgid "Wrong Spec\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback.c:671 #: src/conversation/gnunet-helper-audio-record.c:605 #, fuzzy msgid "pa_mainloop_new() failed.\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/conversation/gnunet-helper-audio-playback.c:685 #: src/conversation/gnunet-helper-audio-record.c:620 #, fuzzy msgid "pa_context_new() failed.\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/conversation/gnunet-helper-audio-playback.c:692 #: src/conversation/gnunet-helper-audio-record.c:626 #, fuzzy, c-format msgid "pa_context_connect() failed: %s\n" msgstr "# av anslutna parter" #: src/conversation/gnunet-helper-audio-playback.c:698 #: src/conversation/gnunet-helper-audio-record.c:632 #, fuzzy msgid "pa_mainloop_run() failed.\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/conversation/gnunet-helper-audio-playback.c:768 #, c-format msgid "Read error from STDIN: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-playback-gst.c:325 #, c-format msgid "Read error from STDIN: %d %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:344 #, fuzzy, c-format msgid "opus_encode_float() failed: %s. Aborting\n" msgstr "# av anslutna parter" #: src/conversation/gnunet-helper-audio-record.c:420 #, fuzzy, c-format msgid "pa_stream_peek() failed: %s\n" msgstr "\"%s\" %s misslyckades: %s\n" #: src/conversation/gnunet-helper-audio-record.c:458 msgid "Got signal, exiting.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:483 #, fuzzy msgid "Stream successfully created.\n" msgstr "Ã…tkomst nekad för \"%s\" vid %s:%d.\n" #: src/conversation/gnunet-helper-audio-record.c:488 #, fuzzy, c-format msgid "pa_stream_get_buffer_attr() failed: %s\n" msgstr "\"%s\" %s misslyckades: %s\n" #: src/conversation/gnunet-helper-audio-record.c:496 #, c-format msgid "Buffer metrics: maxlength=%u, fragsize=%u\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:500 #, c-format msgid "Using sample spec '%s', channel map '%s'.\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:507 #, fuzzy, c-format msgid "Connected to device %s (%u, %ssuspended).\n" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/conversation/gnunet-helper-audio-record.c:516 #, c-format msgid "Stream error: %s\n" msgstr "" #: src/conversation/gnunet-helper-audio-record.c:563 #, fuzzy, c-format msgid "pa_stream_connect_record() failed: %s\n" msgstr "" "\n" "Fel vid uppladdning av fil: %s\n" #: src/conversation/gnunet-helper-audio-record.c:676 #, fuzzy msgid "ogg_stream_init() failed.\n" msgstr "\"%s\" %s misslyckades: %s\n" #: src/conversation/gnunet-helper-audio-record.c:721 #, fuzzy, c-format msgid "Failed to allocate %d bytes for second packet\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/conversation/gnunet-service-conversation.c:841 msgid "Mesh audio channel not ready; audio data dropped\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:932 #, c-format msgid "" "No available phone for incoming call on line %u, sending HANG_UP signal\n" msgstr "" #: src/conversation/gnunet-service-conversation.c:1338 #, fuzzy, c-format msgid "Received incoming channel on port %u\n" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/conversation/microphone.c:121 #, fuzzy msgid "Could not start record audio helper\n" msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #: src/conversation/plugin_gnsrecord_conversation.c:116 #, fuzzy, c-format msgid "Unable to parse PHONE record `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/conversation/speaker.c:75 #, fuzzy msgid "Could not start playback audio helper.\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/core/core_api.c:767 msgid "Client was disconnected from core service, trying to reconnect.\n" msgstr "" #: src/core/gnunet-core.c:80 #, fuzzy, c-format msgid "Peer `%s'\n" msgstr "Jag är ändpunkt \"%s\".\n" #: src/core/gnunet-core.c:110 src/core/gnunet-core.c:138 #: src/transport/gnunet-transport.c:910 src/transport/gnunet-transport.c:930 #, c-format msgid "%24s: %-17s %4s (%u connections in total)\n" msgstr "" #: src/core/gnunet-core.c:112 src/transport/gnunet-transport.c:911 #, fuzzy msgid "Connected to" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/core/gnunet-core.c:140 src/transport/gnunet-transport.c:931 #, fuzzy msgid "Disconnected from" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/core/gnunet-core.c:211 src/peerinfo-tool/gnunet-peerinfo.c:694 #, fuzzy, c-format msgid "Invalid command line argument `%s'\n" msgstr "Ogiltiga kommandoradsargument:\n" #: src/core/gnunet-core.c:233 src/transport/gnunet-transport.c:1486 #, fuzzy msgid "provide information about all current connections (continuously)" msgstr "Skriv ut information om GNUnets motparter." #: src/core/gnunet-core.c:244 #, fuzzy msgid "Print information about connected peers." msgstr "Skriv ut information om GNUnets motparter." #: src/core/gnunet-service-core.c:105 #, fuzzy msgid "Core service is lacking HOSTKEY configuration setting. Exiting.\n" msgstr "GNUnet-konfiguration" #: src/core/gnunet-service-core.c:126 #, c-format msgid "Core service of `%4s' ready.\n" msgstr "" #: src/core/gnunet-service-core_clients.c:370 msgid "# send requests dropped (disconnected)" msgstr "" #: src/core/gnunet-service-core_clients.c:480 #, fuzzy msgid "# messages discarded (session disconnected)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/core/gnunet-service-core_clients.c:526 #, fuzzy, c-format msgid "# bytes of messages of type %u received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/core/gnunet-service-core_kx.c:535 msgid "# bytes encrypted" msgstr "# byte krypterade" #: src/core/gnunet-service-core_kx.c:586 msgid "# bytes decrypted" msgstr "# byte dekrypterade" #: src/core/gnunet-service-core_kx.c:673 msgid "# key exchanges initiated" msgstr "" #: src/core/gnunet-service-core_kx.c:713 msgid "# key exchanges stopped" msgstr "" #: src/core/gnunet-service-core_kx.c:810 msgid "# old ephemeral keys ignored" msgstr "" #: src/core/gnunet-service-core_kx.c:816 #, fuzzy msgid "# ephemeral keys received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/core/gnunet-service-core_kx.c:850 #, c-format msgid "" "Ephemeral key message from peer `%s' rejected as its validity range does not " "match our system time (%llu not in [%llu,%llu]).\n" msgstr "" #: src/core/gnunet-service-core_kx.c:861 #, fuzzy msgid "# EPHEMERAL_KEY messages received" msgstr "# PING-meddelanden skapade" #: src/core/gnunet-service-core_kx.c:951 #: src/transport/gnunet-service-transport_validation.c:1016 #, fuzzy msgid "# PING messages received" msgstr "# PING-meddelanden skapade" #: src/core/gnunet-service-core_kx.c:959 #, fuzzy msgid "# PING messages dropped (out of order)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/core/gnunet-service-core_kx.c:986 #, c-format msgid "" "Received PING from `%s' for different identity: I am `%s', PONG identity: `" "%s'\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1003 #, fuzzy msgid "# PONG messages created" msgstr "# PING-meddelanden skapade" #: src/core/gnunet-service-core_kx.c:1029 #, fuzzy msgid "# sessions terminated by timeout" msgstr "# byte kastade via TCP (utgÃ¥ende)" #: src/core/gnunet-service-core_kx.c:1039 #, fuzzy msgid "# keepalive messages sent" msgstr "# PING-meddelanden i klartext skickade" #: src/core/gnunet-service-core_kx.c:1096 #: src/transport/gnunet-service-transport_validation.c:1328 #, fuzzy msgid "# PONG messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/core/gnunet-service-core_kx.c:1102 #, fuzzy msgid "# PONG messages dropped (connection down)" msgstr "# krypterade PONG-meddelanden mottagna" #: src/core/gnunet-service-core_kx.c:1107 #, fuzzy msgid "# PONG messages dropped (out of order)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/core/gnunet-service-core_kx.c:1137 #, fuzzy msgid "# PONG messages decrypted" msgstr "# PING-meddelanden skapade" #: src/core/gnunet-service-core_kx.c:1171 #, fuzzy msgid "# session keys confirmed via PONG" msgstr "# sessionnycklar vägrade" #: src/core/gnunet-service-core_kx.c:1181 #, fuzzy msgid "# timeouts prevented via PONG" msgstr "# byte mottogs via TCP" #: src/core/gnunet-service-core_kx.c:1188 #, fuzzy msgid "# rekey operations confirmed via PONG" msgstr "# sessionnycklar vägrade" #: src/core/gnunet-service-core_kx.c:1328 #, fuzzy msgid "# DATA message dropped (out of order)" msgstr "# byte kastade via UDP (utgÃ¥ende)" #: src/core/gnunet-service-core_kx.c:1335 #, c-format msgid "" "Session to peer `%s' went down due to key expiration (should not happen)\n" msgstr "" #: src/core/gnunet-service-core_kx.c:1338 #, fuzzy msgid "# sessions terminated by key expiration" msgstr "# byte kastade via TCP (utgÃ¥ende)" #: src/core/gnunet-service-core_kx.c:1383 #: src/core/gnunet-service-core_kx.c:1408 #, fuzzy msgid "# bytes dropped (duplicates)" msgstr "# byte kastade via UDP (utgÃ¥ende)" #: src/core/gnunet-service-core_kx.c:1395 #, fuzzy msgid "# bytes dropped (out of sequence)" msgstr "# byte kastade via UDP (utgÃ¥ende)" #: src/core/gnunet-service-core_kx.c:1437 #, fuzzy msgid "# bytes dropped (ancient message)" msgstr "# byte kastade via UDP (utgÃ¥ende)" #: src/core/gnunet-service-core_kx.c:1445 #, fuzzy msgid "# bytes of payload decrypted" msgstr "# byte dekrypterade" #: src/core/gnunet-service-core_kx.c:1480 #, fuzzy msgid "# PAYLOAD dropped (out of order)" msgstr "# byte kastade via UDP (utgÃ¥ende)" #: src/core/gnunet-service-core_neighbours.c:168 #, fuzzy msgid "# sessions terminated by transport disconnect" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/core/gnunet-service-core_neighbours.c:184 #: src/core/gnunet-service-core_neighbours.c:335 msgid "# neighbour entries allocated" msgstr "" #: src/core/gnunet-service-core_neighbours.c:252 msgid "# encrypted bytes given to transport" msgstr "" #: src/core/gnunet-service-core_neighbours.c:418 #, c-format msgid "Unsupported message of type %u (%u bytes) received from peer `%s'\n" msgstr "" #: src/core/gnunet-service-core_sessions.c:216 #: src/core/gnunet-service-core_sessions.c:288 #: src/dht/gnunet-service-dht_neighbours.c:662 #: src/dht/gnunet-service-dht_neighbours.c:727 #: src/dht/gnunet-service-xdht_neighbours.c:1304 #: src/fs/gnunet-service-fs_cp.c:606 src/fs/gnunet-service-fs_cp.c:1501 #: src/topology/gnunet-daemon-topology.c:707 #: src/topology/gnunet-daemon-topology.c:808 #: src/transport/gnunet-service-transport_neighbours.c:917 #: src/transport/gnunet-service-transport_neighbours.c:1141 #: src/transport/gnunet-service-transport_neighbours.c:3142 #: src/transport/gnunet-service-transport_neighbours.c:3438 #, fuzzy msgid "# peers connected" msgstr "# av anslutna parter" #: src/core/gnunet-service-core_sessions.c:255 msgid "# type map refreshes sent" msgstr "" #: src/core/gnunet-service-core_sessions.c:426 msgid "# messages discarded (expired prior to transmission)" msgstr "" #: src/core/gnunet-service-core_typemap.c:110 #: src/core/gnunet-service-core_typemap.c:121 #, fuzzy msgid "# type maps received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/core/gnunet-service-core_typemap.c:151 msgid "# updates to my type map" msgstr "" #: src/datacache/datacache.c:115 src/datacache/datacache.c:266 #: src/datastore/gnunet-service-datastore.c:838 #, fuzzy msgid "# bytes stored" msgstr "# byte krypterade" #: src/datacache/datacache.c:117 src/datacache/datacache.c:268 #, fuzzy msgid "# items stored" msgstr "# byte krypterade" #: src/datacache/datacache.c:143 src/datacache/datacache.c:150 #: src/datastore/gnunet-service-datastore.c:1487 #: src/datastore/gnunet-service-datastore.c:1498 #, fuzzy, c-format msgid "No `%s' specified for `%s' in configuration!\n" msgstr "Inga applikationer definierade i konfiguration!\n" #: src/datacache/datacache.c:184 #, c-format msgid "Loading `%s' datacache plugin\n" msgstr "" #: src/datacache/datacache.c:192 #, fuzzy, c-format msgid "Failed to load datacache plugin for `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/datacache/datacache.c:295 #, fuzzy msgid "# requests received" msgstr "# byte mottogs via TCP" #: src/datacache/datacache.c:304 msgid "# requests filtered by bloom filter" msgstr "" #: src/datacache/plugin_datacache_heap.c:406 msgid "Heap datacache running\n" msgstr "" #: src/datacache/plugin_datacache_postgres.c:392 msgid "Postgres datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:69 #: src/datacache/plugin_datacache_sqlite.c:72 #: src/datastore/plugin_datastore_mysql.c:806 #: src/datastore/plugin_datastore_mysql.c:820 #: src/datastore/plugin_datastore_sqlite.c:57 src/mysql/mysql.c:41 #: src/mysql/mysql.c:48 src/mysql/mysql.c:522 src/mysql/mysql.c:531 #: src/mysql/mysql.c:591 src/mysql/mysql.c:607 #: src/namecache/plugin_namecache_postgres.c:52 #: src/namecache/plugin_namecache_sqlite.c:52 #: src/namestore/plugin_namestore_postgres.c:52 #: src/namestore/plugin_namestore_sqlite.c:52 #: src/testbed/generate-underlay-topology.c:47 #: src/testbed/gnunet-daemon-latency-logger.c:52 #: src/testbed/gnunet-daemon-testbed-underlay.c:55 #: src/testbed/testbed_api_hosts.c:69 src/util/crypto_ecc.c:51 #: src/util/crypto_mpi.c:39 src/include/gnunet_common.h:602 #: src/include/gnunet_common.h:611 src/scalarproduct/scalarproduct.h:50 #, c-format msgid "`%s' failed at %s:%d with error: %s\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #: src/datacache/plugin_datacache_sqlite.c:450 msgid "Sqlite datacache running\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:484 #: src/datastore/plugin_datastore_sqlite.c:404 #: src/namecache/plugin_namecache_sqlite.c:295 #: src/namestore/plugin_namestore_sqlite.c:327 msgid "Tried to close sqlite without finalizing all prepared statements.\n" msgstr "" #: src/datacache/plugin_datacache_sqlite.c:491 #, fuzzy, c-format msgid "Failed to close statement %p: %d\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/datacache/plugin_datacache_template.c:125 msgid "Template datacache running\n" msgstr "" #: src/datastore/datastore_api.c:310 #, fuzzy msgid "Failed to transmit request to drop database.\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/datastore/datastore_api.c:394 msgid "# queue entry timeouts" msgstr "" #: src/datastore/datastore_api.c:443 msgid "# queue overflows" msgstr "" #: src/datastore/datastore_api.c:471 #, fuzzy msgid "# queue entries created" msgstr "# PING-meddelanden skapade" #: src/datastore/datastore_api.c:491 msgid "# Requests dropped from datastore queue" msgstr "" #: src/datastore/datastore_api.c:533 #, fuzzy msgid "# datastore connections (re)created" msgstr "Nätverksanslutning" #: src/datastore/datastore_api.c:616 src/scalarproduct/scalarproduct_api.c:279 #, fuzzy msgid "# transmission request failures" msgstr "# klartext PONG-meddelanden mottagna" #: src/datastore/datastore_api.c:638 #, fuzzy msgid "# bytes sent to datastore" msgstr "# byte krypterade" #: src/datastore/datastore_api.c:770 #, fuzzy msgid "Failed to receive status response from database." msgstr "Misslyckades att ta emot svar till \"%s\" meddelande frÃ¥n gnunetd\n" #: src/datastore/datastore_api.c:784 msgid "Error reading response from datastore service" msgstr "" #: src/datastore/datastore_api.c:796 src/datastore/datastore_api.c:802 #, fuzzy msgid "Invalid error message received from datastore service" msgstr "Ogiltigt meddelande mottogs den %s:%d." #: src/datastore/datastore_api.c:806 #, fuzzy msgid "# status messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/datastore/datastore_api.c:876 msgid "# PUT requests executed" msgstr "" #: src/datastore/datastore_api.c:944 msgid "# RESERVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1005 msgid "# RELEASE RESERVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1065 msgid "# UPDATE requests executed" msgstr "" #: src/datastore/datastore_api.c:1129 msgid "# REMOVE requests executed" msgstr "" #: src/datastore/datastore_api.c:1174 #, fuzzy msgid "Failed to receive response from database.\n" msgstr "Misslyckades att ta emot svar till \"%s\" meddelande frÃ¥n gnunetd\n" #: src/datastore/datastore_api.c:1233 #, fuzzy msgid "# Results received" msgstr "# byte mottogs via TCP" #: src/datastore/datastore_api.c:1300 msgid "# GET REPLICATION requests executed" msgstr "" #: src/datastore/datastore_api.c:1363 msgid "# GET ZERO ANONYMITY requests executed" msgstr "" #: src/datastore/datastore_api.c:1424 msgid "# GET requests executed" msgstr "" #: src/datastore/gnunet-datastore.c:114 #, fuzzy, c-format msgid "Failed to store item: %s, aborting\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/datastore/gnunet-datastore.c:200 #, c-format msgid "Cannot use the same configuration for source and destination\n" msgstr "" #: src/datastore/gnunet-datastore.c:246 msgid "" "specifies the configuration to use to access an alternative datastore; will " "merge that datastore into our current datastore" msgstr "" #: src/datastore/gnunet-datastore.c:255 #, fuzzy msgid "Manipulate GNUnet datastore" msgstr "skriv ut ett värde frÃ¥n konfigurationsfilen till standard ut" #: src/datastore/gnunet-service-datastore.c:351 #, fuzzy msgid "# bytes expired" msgstr "# byte mottogs via TCP" #: src/datastore/gnunet-service-datastore.c:425 msgid "# bytes purged (low-priority)" msgstr "" #: src/datastore/gnunet-service-datastore.c:483 #: src/gns/gnunet-gns-helper-service-w32.c:223 msgid "Transmission to client failed!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:514 #: src/gns/gnunet-gns-helper-service-w32.c:262 msgid "Shutdown in progress, aborting transmission.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:630 msgid "# results found" msgstr "" #: src/datastore/gnunet-service-datastore.c:673 #, c-format msgid "" "Insufficient space (%llu bytes are available) to satisfy `%s' request for " "%llu bytes\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:684 #, c-format msgid "" "The requested amount (%llu bytes) is larger than the cache size (%llu " "bytes)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:688 msgid "" "Insufficient space to satisfy request and requested amount is larger than " "cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:694 msgid "Insufficient space to satisfy request" msgstr "" #: src/datastore/gnunet-service-datastore.c:699 #: src/datastore/gnunet-service-datastore.c:751 #: src/datastore/gnunet-service-datastore.c:964 #: src/datastore/gnunet-service-datastore.c:1421 msgid "# reserved" msgstr "" #: src/datastore/gnunet-service-datastore.c:764 msgid "Could not find matching reservation" msgstr "" #: src/datastore/gnunet-service-datastore.c:850 #, c-format msgid "Need %llu bytes more space (%llu allowed, using %llu)\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1010 #, fuzzy msgid "# GET requests received" msgstr "# byte mottogs via TCP" #: src/datastore/gnunet-service-datastore.c:1022 msgid "# requests filtered by bloomfilter" msgstr "" #: src/datastore/gnunet-service-datastore.c:1050 #, fuzzy msgid "# UPDATE requests received" msgstr "# byte mottogs via TCP" #: src/datastore/gnunet-service-datastore.c:1080 msgid "# GET REPLICATION requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1113 msgid "# GET ZERO ANONYMITY requests received" msgstr "" #: src/datastore/gnunet-service-datastore.c:1138 #, fuzzy msgid "Content not found" msgstr "Kommando \"%s\" hittades inte!\n" #: src/datastore/gnunet-service-datastore.c:1146 msgid "# bytes removed (explicit request)" msgstr "" #: src/datastore/gnunet-service-datastore.c:1178 #, fuzzy msgid "# REMOVE requests received" msgstr "# byte mottogs via TCP" #: src/datastore/gnunet-service-datastore.c:1220 #, c-format msgid "Datastore payload inaccurate (%lld < %lld). Trying to fix.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1281 #, c-format msgid "Loading `%s' datastore plugin\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1290 #, fuzzy, c-format msgid "Failed to load datastore plugin for `%s'\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/datastore/gnunet-service-datastore.c:1492 #, fuzzy, c-format msgid "# bytes used in file-sharing datastore `%s'" msgstr "# byte krypterade" #: src/datastore/gnunet-service-datastore.c:1503 msgid "# quota" msgstr "" #: src/datastore/gnunet-service-datastore.c:1505 msgid "# cache size" msgstr "" #: src/datastore/gnunet-service-datastore.c:1518 #, c-format msgid "Could not use specified filename `%s' for bloomfilter.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1536 #: src/datastore/gnunet-service-datastore.c:1552 #, fuzzy, c-format msgid "Failed to remove bogus bloomfilter file `%s'\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/datastore/gnunet-service-datastore.c:1582 #, fuzzy msgid "Failed to initialize bloomfilter.\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/datastore/gnunet-service-datastore.c:1611 msgid "Rebuilding bloomfilter. Please be patient.\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1616 msgid "Plugin does not support get_keys function. Please fix!\n" msgstr "" #: src/datastore/gnunet-service-datastore.c:1619 msgid "Bloomfilter construction complete.\n" msgstr "" #: src/datastore/plugin_datastore_heap.c:820 msgid "Heap database running\n" msgstr "" #: src/datastore/plugin_datastore_mysql.c:783 #, fuzzy, c-format msgid "Failed to prepare statement `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/datastore/plugin_datastore_mysql.c:791 #, fuzzy, c-format msgid "`%s' for `%s' failed at %s:%d with error: %s\n" msgstr "\"%s\" till \"%s\" misslyckades vid %s:%d med fel: %s\n" #: src/datastore/plugin_datastore_mysql.c:1022 msgid "Mysql database running\n" msgstr "" #: src/datastore/plugin_datastore_postgres.c:824 #, fuzzy msgid "Failed to drop table from database.\n" msgstr "Misslyckades att ta emot svar till \"%s\" meddelande frÃ¥n gnunetd\n" #: src/datastore/plugin_datastore_postgres.c:860 #: src/namecache/plugin_namecache_postgres.c:414 #: src/namestore/plugin_namestore_postgres.c:569 msgid "Postgres database running\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:57 #: src/testbed/generate-underlay-topology.c:50 #: src/testbed/gnunet-daemon-latency-logger.c:55 #: src/testbed/gnunet-daemon-testbed-underlay.c:58 #, fuzzy, c-format msgid "`%s' failed at %s:%u with error: %s" msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #: src/datastore/plugin_datastore_sqlite.c:255 #: src/namecache/plugin_namecache_sqlite.c:193 #: src/namestore/plugin_namestore_sqlite.c:204 #: src/psycstore/plugin_psycstore_sqlite.c:319 #, fuzzy, c-format msgid "Unable to initialize SQLite: %s.\n" msgstr "Kunde inte initiera SQLite.\n" #: src/datastore/plugin_datastore_sqlite.c:663 msgid "Invalid data in database. Trying to fix (by deletion).\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1156 msgid "sqlite version to old to determine size, assuming zero\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1175 #, c-format msgid "" "Using sqlite page utilization to estimate payload (%llu pages of size %llu " "bytes)\n" msgstr "" #: src/datastore/plugin_datastore_sqlite.c:1215 #: src/namecache/plugin_namecache_sqlite.c:583 #: src/namestore/plugin_namestore_sqlite.c:719 msgid "Sqlite database running\n" msgstr "" #: src/datastore/plugin_datastore_template.c:257 msgid "Template database running\n" msgstr "" #: src/dht/dht_api.c:376 #, fuzzy msgid "Failed to connect to the DHT service!\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/dht/gnunet-dht-get.c:133 #, c-format msgid "" "Result %d, type %d:\n" "%.*s\n" msgstr "" #: src/dht/gnunet-dht-get.c:159 msgid "Must provide key for DHT GET!\n" msgstr "" #: src/dht/gnunet-dht-get.c:165 src/dht/gnunet-dht-monitor.c:225 #, fuzzy msgid "Failed to connect to DHT service!\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/dht/gnunet-dht-get.c:173 msgid "Issueing DHT GET with key" msgstr "" #: src/dht/gnunet-dht-get.c:189 src/dht/gnunet-dht-monitor.c:262 #: src/dht/gnunet-dht-put.c:198 msgid "the query key" msgstr "" #: src/dht/gnunet-dht-get.c:192 msgid "how many parallel requests (replicas) to create" msgstr "" #: src/dht/gnunet-dht-get.c:195 src/dht/gnunet-dht-monitor.c:265 msgid "the type of data to look for" msgstr "" #: src/dht/gnunet-dht-get.c:198 src/dht/gnunet-dht-put.c:210 msgid "how long to execute this query before giving up?" msgstr "" #: src/dht/gnunet-dht-get.c:201 src/dht/gnunet-dht-put.c:201 msgid "use DHT's demultiplex everywhere option" msgstr "" #: src/dht/gnunet-dht-get.c:204 src/dht/gnunet-dht-monitor.c:271 #: src/dht/gnunet-dht-put.c:213 src/fs/gnunet-auto-share.c:753 #: src/fs/gnunet-download.c:328 src/fs/gnunet-publish.c:877 #: src/fs/gnunet-search.c:301 src/fs/gnunet-unindex.c:168 #: src/nse/gnunet-nse-profiler.c:873 msgid "be verbose (print progress information)" msgstr "" #: src/dht/gnunet-dht-get.c:225 msgid "Issue a GET request to the GNUnet DHT, prints results." msgstr "" #: src/dht/gnunet-dht-monitor.c:268 msgid "how long should the monitor command run" msgstr "" #: src/dht/gnunet-dht-monitor.c:293 msgid "Prints all packets that go through the DHT." msgstr "" #: src/dht/gnunet-dht-put.c:118 #, fuzzy msgid "PUT request sent with key" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-dht-put.c:121 msgid "Timeout sending PUT request!\n" msgstr "" #: src/dht/gnunet-dht-put.c:124 #, fuzzy msgid "PUT request not confirmed!\n" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-dht-put.c:153 msgid "Must provide KEY and DATA for DHT put!\n" msgstr "" #: src/dht/gnunet-dht-put.c:160 #, fuzzy, c-format msgid "Could not connect to %s service!\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/dht/gnunet-dht-put.c:176 #, c-format msgid "Issuing put request for `%s' with data `%s'!\n" msgstr "" #: src/dht/gnunet-dht-put.c:192 msgid "the data to insert under the key" msgstr "" #: src/dht/gnunet-dht-put.c:195 msgid "how long to store this entry in the dht (in seconds)" msgstr "" #: src/dht/gnunet-dht-put.c:204 msgid "how many replicas to create" msgstr "" #: src/dht/gnunet-dht-put.c:207 msgid "the type to insert data as" msgstr "" #: src/dht/gnunet-dht-put.c:236 msgid "Issue a PUT request to the GNUnet DHT insert DATA under KEY." msgstr "" #: src/dht/gnunet-service-dht.c:172 src/dht/gnunet-service-xdht.c:176 #, fuzzy msgid "Failed to connect to transport service!\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/dht/gnunet-service-dht_clients.c:417 #: src/dht/gnunet-service-xdht_clients.c:838 #, fuzzy msgid "# GET requests from clients injected" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_clients.c:513 #: src/dht/gnunet-service-xdht_clients.c:927 #, fuzzy msgid "# PUT requests received from clients" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/dht/gnunet-service-dht_clients.c:597 #: src/dht/gnunet-service-xdht_clients.c:1013 #, fuzzy msgid "# GET requests received from clients" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/dht/gnunet-service-dht_clients.c:798 #: src/dht/gnunet-service-xdht_clients.c:1214 #, fuzzy msgid "# GET STOP requests received from clients" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/dht/gnunet-service-dht_clients.c:1039 #: src/dht/gnunet-service-xdht_clients.c:498 msgid "# Key match, type mismatches in REPLY to CLIENT" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1052 #: src/dht/gnunet-service-xdht_clients.c:511 msgid "# Duplicate REPLIES to CLIENT request dropped" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1089 #: src/dht/gnunet-service-xdht_clients.c:548 #, c-format msgid "Unsupported block type (%u) in request!\n" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1112 #: src/dht/gnunet-service-xdht_clients.c:571 #, fuzzy msgid "# RESULTS queued for clients" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/dht/gnunet-service-dht_clients.c:1166 #: src/dht/gnunet-service-dht_clients.c:1209 #: src/dht/gnunet-service-xdht_clients.c:625 #: src/dht/gnunet-service-xdht_clients.c:668 msgid "# REPLIES ignored for CLIENTS (no match)" msgstr "" #: src/dht/gnunet-service-dht_clients.c:1176 #: src/dht/gnunet-service-xdht_clients.c:635 #, fuzzy msgid "Could not pass reply to client, message too big!\n" msgstr "Kunde inte skicka meddelande till gnunetd\n" #: src/dht/gnunet-service-dht_datacache.c:68 #: src/dht/gnunet-service-xdht_datacache.c:68 #, fuzzy, c-format msgid "%s request received, but have no datacache!\n" msgstr "# byte mottagna av typen %d" #: src/dht/gnunet-service-dht_datacache.c:78 #: src/dht/gnunet-service-xdht_datacache.c:78 msgid "# ITEMS stored in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:165 #: src/dht/gnunet-service-xdht_datacache.c:165 msgid "# Good RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:176 #: src/dht/gnunet-service-xdht_datacache.c:176 msgid "# Duplicate RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:182 #: src/dht/gnunet-service-xdht_datacache.c:182 msgid "# Invalid RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:188 #: src/dht/gnunet-service-xdht_datacache.c:188 msgid "# Irrelevant RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:200 #: src/dht/gnunet-service-xdht_datacache.c:200 msgid "# Unsupported RESULTS found in datacache" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:203 #: src/dht/gnunet-service-xdht_datacache.c:203 #, c-format msgid "Unsupported block type (%u) in local response!\n" msgstr "" #: src/dht/gnunet-service-dht_datacache.c:234 #: src/dht/gnunet-service-xdht_datacache.c:234 #, fuzzy msgid "# GET requests given to datacache" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_hello.c:84 #: src/dht/gnunet-service-xdht_hello.c:82 #, fuzzy msgid "# HELLOs obtained from peerinfo" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/dht/gnunet-service-dht_neighbours.c:516 msgid "# Preference updates given to core" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:610 #, fuzzy msgid "# FIND PEER messages initiated" msgstr "# PING-meddelanden skapade" #: src/dht/gnunet-service-dht_neighbours.c:764 #, fuzzy msgid "# Queued messages discarded (peer disconnected)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/dht/gnunet-service-dht_neighbours.c:819 #: src/dht/gnunet-service-xdht_neighbours.c:703 #, fuzzy msgid "# Bytes transmitted to other peers" msgstr "# byte skickade av typen %d" #: src/dht/gnunet-service-dht_neighbours.c:857 #: src/dht/gnunet-service-xdht_neighbours.c:742 msgid "# Bytes of bandwidth requested from core" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:889 #, fuzzy msgid "# requests TTL-dropped" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:1093 #: src/dht/gnunet-service-dht_neighbours.c:1130 msgid "# Peers excluded from routing due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1108 #: src/dht/gnunet-service-dht_neighbours.c:1145 msgid "# Peer selection failed" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1287 #, fuzzy msgid "# PUT requests routed" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:1316 #, fuzzy msgid "# PUT messages queued for transmission" msgstr "# PING-meddelanden skapade" #: src/dht/gnunet-service-dht_neighbours.c:1323 #: src/dht/gnunet-service-dht_neighbours.c:1440 #: src/dht/gnunet-service-dht_neighbours.c:1543 #: src/dht/gnunet-service-xdht_neighbours.c:794 #: src/dht/gnunet-service-xdht_neighbours.c:860 #: src/dht/gnunet-service-xdht_neighbours.c:919 #: src/dht/gnunet-service-xdht_neighbours.c:981 #: src/dht/gnunet-service-xdht_neighbours.c:1041 #, fuzzy msgid "# P2P messages dropped due to full queue" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/dht/gnunet-service-dht_neighbours.c:1405 #, fuzzy msgid "# GET requests routed" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:1432 #, fuzzy msgid "# GET messages queued for transmission" msgstr "# PING-meddelanden skapade" #: src/dht/gnunet-service-dht_neighbours.c:1550 #, fuzzy msgid "# RESULT messages queued for transmission" msgstr "# PING-meddelanden skapade" #: src/dht/gnunet-service-dht_neighbours.c:1636 #, fuzzy msgid "# P2P PUT requests received" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:1639 #, fuzzy msgid "# P2P PUT bytes received" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:1803 msgid "# FIND PEER requests ignored due to Bloomfilter" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1811 msgid "# FIND PEER requests ignored due to lack of HELLO" msgstr "" #: src/dht/gnunet-service-dht_neighbours.c:1904 #, fuzzy msgid "# P2P GET requests received" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:1907 #, fuzzy msgid "# P2P GET bytes received" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:1961 #, fuzzy msgid "# P2P FIND PEER requests processed" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:1975 #, fuzzy msgid "# P2P GET requests ONLY routed" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_neighbours.c:2052 #, fuzzy msgid "# P2P RESULTS received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/dht/gnunet-service-dht_neighbours.c:2055 #, fuzzy msgid "# P2P RESULT bytes received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/dht/gnunet-service-dht_nse.c:59 src/dht/gnunet-service-xdht_nse.c:59 #, fuzzy msgid "# Network size estimates received" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-dht_routing.c:211 msgid "# Good REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:220 msgid "# Duplicate REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:226 msgid "# Invalid REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:232 msgid "# Irrelevant REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:244 msgid "# Unsupported REPLIES matched against routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:317 msgid "# Entries removed from routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:399 msgid "# Entries added to routing table" msgstr "" #: src/dht/gnunet-service-dht_routing.c:417 #, fuzzy msgid "# DHT requests combined" msgstr "# byte mottogs via TCP" #: src/dht/gnunet-service-xdht_neighbours.c:1398 #, c-format msgid "" "\n" "SUPU %s, %s, %d,my_identity = %s" msgstr "" #: src/dht/gnunet-service-xdht_neighbours.c:1514 #: src/dht/gnunet-service-xdht_neighbours.c:1524 #: src/dht/gnunet-service-xdht_neighbours.c:1530 #: src/dht/gnunet-service-xdht_neighbours.c:1536 #: src/dht/gnunet-service-xdht_neighbours.c:1545 #, c-format msgid "" "\n" "SUPU %s, %s, %d" msgstr "" #: src/dht/plugin_block_dht.c:138 #, fuzzy, c-format msgid "Block not of type %u\n" msgstr "Ingen transport av typ %d är känd.\n" #: src/dht/plugin_block_dht.c:145 msgid "Size mismatch for block\n" msgstr "" #: src/dht/plugin_block_dht.c:155 #, c-format msgid "Block of type %u is malformed\n" msgstr "" #: src/dns/dnsparser.c:257 #, fuzzy, c-format msgid "Failed to convert DNS IDNA name `%s' to UTF-8: %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/dns/dnsparser.c:856 #, fuzzy, c-format msgid "Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/dns/dnsstub.c:175 #, fuzzy, c-format msgid "Could not bind to any port: %s\n" msgstr "Kunde inte köra \"%s\": %s\n" #: src/dns/dnsstub.c:295 src/dns/dnsstub.c:383 #, fuzzy, c-format msgid "Failed to send DNS request to %s\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/dns/dnsstub.c:299 #, fuzzy, c-format msgid "Sent DNS request to %s\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/dns/dnsstub.c:368 #, c-format msgid "Configured DNS exit `%s' is not working / valid.\n" msgstr "" #: src/dns/dnsstub.c:440 #, c-format msgid "Received DNS response that is too small (%u bytes)" msgstr "" #: src/dns/gnunet-dns-monitor.c:355 msgid "only monitor DNS queries" msgstr "" #: src/dns/gnunet-dns-monitor.c:358 msgid "only monitor DNS replies" msgstr "" #: src/dns/gnunet-dns-monitor.c:369 msgid "Monitor DNS queries." msgstr "" #: src/dns/gnunet-dns-redirector.c:236 msgid "set A records" msgstr "" #: src/dns/gnunet-dns-redirector.c:239 msgid "set AAAA records" msgstr "" #: src/dns/gnunet-dns-redirector.c:251 msgid "Change DNS replies to point elsewhere." msgstr "" #: src/dns/gnunet-service-dns.c:456 msgid "# DNS requests answered via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:603 msgid "# DNS exit failed (failed to open socket)" msgstr "" #: src/dns/gnunet-service-dns.c:714 msgid "# External DNS response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:792 msgid "# Client response discarded (no matching request)" msgstr "" #: src/dns/gnunet-service-dns.c:907 msgid "Received malformed IPv4-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:923 msgid "Received malformed IPv6-UDP packet on TUN interface.\n" msgstr "" #: src/dns/gnunet-service-dns.c:932 #, c-format msgid "Got non-IP packet with %u bytes and protocol %u from TUN\n" msgstr "" #: src/dns/gnunet-service-dns.c:942 msgid "# Non-DNS UDP packet received via TUN interface" msgstr "" #: src/dns/gnunet-service-dns.c:1009 #, fuzzy msgid "# DNS requests received via TUN interface" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/dns/gnunet-service-dns.c:1049 src/exit/gnunet-daemon-exit.c:3514 #, c-format msgid "`%s' must be installed SUID, refusing to run\n" msgstr "" #: src/dns/gnunet-service-dns.c:1069 src/exit/gnunet-daemon-exit.c:3571 #, fuzzy msgid "need a valid IPv4 or IPv6 address\n" msgstr "Ogiltigt svar pÃ¥ \"%s\".\n" #: src/dv/gnunet-dv.c:169 msgid "verbose output" msgstr "" #: src/dv/gnunet-dv.c:178 #, fuzzy msgid "Print information about DV state" msgstr "Skriv ut information om GNUnets motparter." #: src/exit/gnunet-daemon-exit.c:802 #, c-format msgid "Got duplicate service records for `%s:%u'\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:853 #, fuzzy msgid "# Bytes transmitted via mesh channels" msgstr "# byte skickade av typen %d" #: src/exit/gnunet-daemon-exit.c:970 src/exit/gnunet-daemon-exit.c:2397 #: src/exit/gnunet-daemon-exit.c:2654 src/vpn/gnunet-service-vpn.c:1407 #: src/vpn/gnunet-service-vpn.c:1797 src/vpn/gnunet-service-vpn.c:1960 msgid "# ICMPv4 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1007 src/exit/gnunet-daemon-exit.c:2456 #: src/exit/gnunet-daemon-exit.c:2713 src/vpn/gnunet-service-vpn.c:1463 #: src/vpn/gnunet-service-vpn.c:1856 src/vpn/gnunet-service-vpn.c:1993 msgid "# ICMPv6 packets dropped (type not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1047 msgid "# ICMP packets dropped (not allowed)" msgstr "" #: src/exit/gnunet-daemon-exit.c:1054 msgid "ICMP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1130 msgid "UDP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1204 msgid "TCP Packet dropped, have no matching connection information\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1256 #, fuzzy msgid "# Packets received from TUN" msgstr "# byte mottagna via HTTP" #: src/exit/gnunet-daemon-exit.c:1270 #, fuzzy msgid "# Bytes received from TUN" msgstr "# byte mottagna via HTTP" #: src/exit/gnunet-daemon-exit.c:1296 msgid "IPv4 packet options received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1323 #, c-format msgid "IPv4 packet with unsupported next header %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1369 #, c-format msgid "IPv6 packet with unsupported next header %d received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1377 #, c-format msgid "Packet from unknown protocol %u received. Ignored.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1759 #, fuzzy msgid "# TCP packets sent via TUN" msgstr "# byte skickade via UDP" #: src/exit/gnunet-daemon-exit.c:1872 msgid "# TCP service creation requests received via mesh" msgstr "" #: src/exit/gnunet-daemon-exit.c:1875 src/exit/gnunet-daemon-exit.c:1968 #: src/exit/gnunet-daemon-exit.c:2073 src/exit/gnunet-daemon-exit.c:2321 #: src/exit/gnunet-daemon-exit.c:2570 src/exit/gnunet-daemon-exit.c:2859 #: src/exit/gnunet-daemon-exit.c:2966 #, fuzzy msgid "# Bytes received from MESH" msgstr "# byte mottagna via HTTP" #: src/exit/gnunet-daemon-exit.c:1909 src/exit/gnunet-daemon-exit.c:2990 #, c-format msgid "No service %s found for %s on port %d!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:1914 #, fuzzy msgid "# TCP requests dropped (no such service)" msgstr "# byte mottogs via TCP" #: src/exit/gnunet-daemon-exit.c:1971 #, fuzzy msgid "# TCP IP-exit creation requests received via mesh" msgstr "# byte mottogs via TCP" #: src/exit/gnunet-daemon-exit.c:2076 #, fuzzy msgid "# TCP data requests received via mesh" msgstr "# byte mottogs via TCP" #: src/exit/gnunet-daemon-exit.c:2090 #, fuzzy msgid "# TCP DATA requests dropped (no session)" msgstr "# byte mottogs via TCP" #: src/exit/gnunet-daemon-exit.c:2150 #, fuzzy msgid "# ICMP packets sent via TUN" msgstr "# byte skickade via UDP" #: src/exit/gnunet-daemon-exit.c:2324 #, fuzzy msgid "# ICMP IP-exit requests received via mesh" msgstr "# byte mottogs via TCP" #: src/exit/gnunet-daemon-exit.c:2573 #, fuzzy msgid "# ICMP service requests received via mesh" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/exit/gnunet-daemon-exit.c:2639 src/vpn/gnunet-service-vpn.c:1397 #: src/vpn/gnunet-service-vpn.c:1954 msgid "# ICMPv4 packets dropped (impossible PT to v6)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2698 src/vpn/gnunet-service-vpn.c:1433 #: src/vpn/gnunet-service-vpn.c:1445 src/vpn/gnunet-service-vpn.c:1844 msgid "# ICMPv6 packets dropped (impossible PT to v4)" msgstr "" #: src/exit/gnunet-daemon-exit.c:2748 #, fuzzy msgid "# UDP packets sent via TUN" msgstr "# byte skickade via UDP" #: src/exit/gnunet-daemon-exit.c:2862 #, fuzzy msgid "# UDP IP-exit requests received via mesh" msgstr "# byte mottogs via TCP" #: src/exit/gnunet-daemon-exit.c:2969 #, fuzzy msgid "# UDP service requests received via mesh" msgstr "# byte mottogs via TCP" #: src/exit/gnunet-daemon-exit.c:2995 #, fuzzy msgid "# UDP requests dropped (no such service)" msgstr "# byte mottogs via TCP" #: src/exit/gnunet-daemon-exit.c:3031 #, fuzzy msgid "# Inbound MESH channels created" msgstr "# PING-meddelanden skapade" #: src/exit/gnunet-daemon-exit.c:3235 src/exit/gnunet-daemon-exit.c:3245 #, fuzzy, c-format msgid "Option `%s' for domain `%s' is not formatted correctly!\n" msgstr "%s: flagga \"%s\" är tvetydig\n" #: src/exit/gnunet-daemon-exit.c:3259 src/exit/gnunet-daemon-exit.c:3267 #, c-format msgid "`%s' is not a valid port number (for domain `%s')!" msgstr "" #: src/exit/gnunet-daemon-exit.c:3300 #, c-format msgid "No addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3314 src/exit/gnunet-daemon-exit.c:3326 #, c-format msgid "Service `%s' configured for IPv4, but IPv4 is disabled!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3337 #, c-format msgid "No IP addresses found for hostname `%s' of service `%s'!\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3527 msgid "" "This system does not support IPv4, will disable IPv4 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3535 msgid "" "This system does not support IPv6, will disable IPv6 functions despite them " "being enabled in the configuration\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3542 msgid "" "Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use " "ENABLE_IPv4=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3548 msgid "" "Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use " "ENABLE_IPv6=YES\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3554 src/exit/gnunet-daemon-exit.c:3717 #: src/pt/gnunet-daemon-pt.c:1247 msgid "No useful service enabled. Exiting.\n" msgstr "" #: src/exit/gnunet-daemon-exit.c:3664 msgid "Must be a number" msgstr "" #: src/exit/gnunet-daemon-exit.c:3813 msgid "Daemon to run to provide an IP exit node for the VPN" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:55 msgid "Experimentation daemon shutting down ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:77 msgid "Experimentation daemon starting ...\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation.c:83 #, fuzzy msgid "Failed to create statistics!\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/experimentation/gnunet-daemon-experimentation.c:120 msgid "GNUnet experimentation daemon" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:241 #, c-format msgid "Experiment `%s': Experiment signature is invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:250 #, c-format msgid "" "Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu " "sec. \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:303 #, c-format msgid "Experiment `%s': Issuer missing\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:312 #, c-format msgid "Experiment `%s': Issuer invalid\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:320 #, c-format msgid "Experiment `%s': Issuer not accepted!\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:330 #, c-format msgid "Experiment `%s': Version missing or invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:339 #, c-format msgid "Experiment `%s': Required capabilities missing \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:345 #, c-format msgid "Experiment `%s': Required capabilities invalid \n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:390 #, fuzzy, c-format msgid "Failed to parse file `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:420 #: src/experimentation/gnunet-daemon-experimentation_experiments.c:452 msgid "" "No valid experiment issuers configured! Set value to public keys of issuers! " "Exiting.\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:435 #, fuzzy msgid "Invalid value for public key\n" msgstr "Ogiltigt argument: \"%s\"\n" #: src/experimentation/gnunet-daemon-experimentation_experiments.c:473 #, fuzzy, c-format msgid "Cannot read experiments file `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:221 #, c-format msgid "Cannot send message to peer `%s' for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:309 #, c-format msgid "Sending experimentation request to peer %s\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:453 #, c-format msgid "Added peer `%s' as active node\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:891 #, fuzzy, c-format msgid "Connected to peer %s\n" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:921 #, fuzzy, c-format msgid "Disconnected from peer %s\n" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/experimentation/gnunet-daemon-experimentation_nodes.c:1104 #, fuzzy msgid "Failed to connect to CORE service!\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:108 #, c-format msgid "Peer `%s' did not respond to request for experiment `%s'\n" msgstr "" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:143 #, fuzzy, c-format msgid "Starting inbound experiment `%s' with peer `%s'\n" msgstr "Startade samling \"%s\".\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:276 #, fuzzy, c-format msgid "Starting outbound experiment `%s' with peer `%s'\n" msgstr "Startade samling \"%s\".\n" #: src/experimentation/gnunet-daemon-experimentation_scheduler.c:294 #, fuzzy, c-format msgid "Received %s message from peer %s for experiment `%s'\n" msgstr "Mottog ogiltigt \"%s\" meddelande frÃ¥n \"%s\".\n" #: src/fragmentation/defragmentation.c:270 msgid "# acknowledgements sent for fragment" msgstr "" #: src/fragmentation/defragmentation.c:456 #, fuzzy msgid "# fragments received" msgstr "# byte mottogs via TCP" #: src/fragmentation/defragmentation.c:521 #, fuzzy msgid "# duplicate fragments received" msgstr "# byte mottogs via TCP" #: src/fragmentation/defragmentation.c:534 msgid "# messages defragmented" msgstr "" #: src/fragmentation/fragmentation.c:208 #, fuzzy msgid "# fragments transmitted" msgstr "# byte skickade av typen %d" #: src/fragmentation/fragmentation.c:211 #, fuzzy msgid "# fragments retransmitted" msgstr "# byte skickade av typen %d" #: src/fragmentation/fragmentation.c:237 #, fuzzy msgid "# fragments wrap arounds" msgstr "# byte skickade av typen %d" #: src/fragmentation/fragmentation.c:281 msgid "# messages fragmented" msgstr "" #: src/fragmentation/fragmentation.c:284 msgid "# total size of fragmented messages" msgstr "" #: src/fragmentation/fragmentation.c:405 msgid "# fragment acknowledgements received" msgstr "" #: src/fragmentation/fragmentation.c:411 msgid "# bits removed from fragmentation ACKs" msgstr "" #: src/fragmentation/fragmentation.c:435 #, fuzzy msgid "# fragmentation transmissions completed" msgstr "# klartext PONG-meddelanden mottagna" #: src/fs/fs_api.c:465 #, fuzzy, c-format msgid "Could not open file `%s': %s" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/fs/fs_api.c:474 #, fuzzy, c-format msgid "Could not read file `%s': %s" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/fs/fs_api.c:480 #, c-format msgid "Short read reading from file `%s'!" msgstr "" #: src/fs/fs_api.c:1066 #, fuzzy, c-format msgid "Failed to resume publishing information `%s': %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_api.c:1571 #, c-format msgid "Failure while resuming publishing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:1585 #, fuzzy, c-format msgid "Failed to resume publishing operation `%s': %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_api.c:2242 #, c-format msgid "Failure while resuming unindexing operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2252 #, fuzzy, c-format msgid "Failed to resume unindexing operation `%s': %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_api.c:2378 src/fs/fs_api.c:2619 #, fuzzy, c-format msgid "Failed to resume sub-download `%s': %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_api.c:2395 #, fuzzy, c-format msgid "Failed to resume sub-search `%s': %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_api.c:2409 src/fs/fs_api.c:2428 src/fs/fs_api.c:2911 #, c-format msgid "Failure while resuming search operation `%s': %s\n" msgstr "" #: src/fs/fs_api.c:2610 #, c-format msgid "Failed to resume sub-download `%s': could not open file `%s'\n" msgstr "" #: src/fs/fs_api.c:2855 msgid "Could not resume running search, will resume as paused search\n" msgstr "" #: src/fs/fs_api.c:2949 #, c-format msgid "Failure while resuming download operation `%s': %s\n" msgstr "" #: src/fs/fs_directory.c:208 #, fuzzy msgid "MAGIC mismatch. This is not a GNUnet directory.\n" msgstr "Filformatsfel (inte en GNUnet-katalog?)\n" #: src/fs/fs_download.c:322 msgid "" "Recursive downloads of directories larger than 4 GB are not supported on 32-" "bit systems\n" msgstr "" #: src/fs/fs_download.c:342 msgid "Directory too large for system address space\n" msgstr "" #: src/fs/fs_download.c:523 src/fs/fs_download.c:535 #, fuzzy, c-format msgid "Failed to open file `%s' for writing" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_download.c:905 #, fuzzy, c-format msgid "Failed to create directory for recursive download of `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/fs/fs_download.c:987 #, c-format msgid "" "Internal error or bogus download URI (expected %u bytes at depth %u and " "offset %llu/%llu, got %u bytes)" msgstr "" #: src/fs/fs_download.c:1013 msgid "internal error decrypting content" msgstr "" #: src/fs/fs_download.c:1036 #, fuzzy, c-format msgid "Download failed: could not open file `%s': %s" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/fs/fs_download.c:1046 #, fuzzy, c-format msgid "Failed to seek to offset %llu in file `%s': %s" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_download.c:1055 #, fuzzy, c-format msgid "Failed to write block of %u bytes at offset %llu in file `%s': %s" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_download.c:1153 #, fuzzy msgid "internal error decoding tree" msgstr "=\tFel vid läsning av katalog.\n" #: src/fs/fs_download.c:1944 #, fuzzy msgid "Invalid URI" msgstr "Ogiltiga argument: " #: src/fs/fs_getopt.c:192 #, c-format msgid "" "Unknown metadata type in metadata option `%s'. Using metadata type " "`unknown' instead.\n" msgstr "" #: src/fs/fs_list_indexed.c:90 #, fuzzy, c-format msgid "Failed to receive response for `%s' request from `%s' service.\n" msgstr "Misslyckades att ta emot svar till \"%s\" meddelande frÃ¥n gnunetd\n" #: src/fs/fs_list_indexed.c:113 #, fuzzy, c-format msgid "Failed to receive valid response for `%s' request from `%s' service.\n" msgstr "Misslyckades att ta emot svar till \"%s\" meddelande frÃ¥n gnunetd\n" #: src/fs/fs_list_indexed.c:151 #, fuzzy, c-format msgid "Failed to not connect to `%s' service.\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/fs/fs_misc.c:126 #, fuzzy, c-format msgid "Did not find mime type `%s' in extension list.\n" msgstr "Kunde inte hitta motpart \"%s\" i routingtabell!\n" #: src/fs/fs_namespace.c:207 #, fuzzy, c-format msgid "Failed to open `%s' for writing: %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_namespace.c:229 #, fuzzy, c-format msgid "Failed to write `%s': %s\n" msgstr "Fel vid %s:%d.\n" #: src/fs/fs_namespace.c:320 #, fuzzy, c-format msgid "Failed to read `%s': %s\n" msgstr "Fel vid %s:%d.\n" #: src/fs/fs_namespace.c:466 #, fuzzy msgid "Failed to connect to datastore." msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/fs/fs_publish.c:125 src/fs/fs_publish.c:415 #, fuzzy, c-format msgid "Publishing failed: %s" msgstr "" "\n" "Fel vid uppladdning av fil: %s\n" #: src/fs/fs_publish.c:667 src/fs/fs_publish.c:684 src/fs/fs_publish.c:723 #: src/fs/fs_publish.c:744 src/fs/fs_publish.c:768 src/fs/fs_publish.c:914 #, fuzzy, c-format msgid "Can not index file `%s': %s. Will try to insert instead.\n" msgstr "Indexering av fil \"%s\" misslyckades. Försöker att infoga fil...\n" #: src/fs/fs_publish.c:669 msgid "timeout on index-start request to `fs' service" msgstr "" #: src/fs/fs_publish.c:681 #, fuzzy msgid "unknown error" msgstr "Okänt fel" #: src/fs/fs_publish.c:725 msgid "failed to compute hash" msgstr "" #: src/fs/fs_publish.c:745 msgid "filename too long" msgstr "" #: src/fs/fs_publish.c:770 #, fuzzy msgid "could not connect to `fs' service" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/fs/fs_publish.c:793 #, fuzzy, c-format msgid "Failed to get file identifiers for `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/fs/fs_publish.c:862 #, fuzzy, c-format msgid "Recursive upload failed at `%s': %s" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/fs/fs_publish.c:868 #, fuzzy, c-format msgid "Recursive upload failed: %s" msgstr "" "\n" "Fel vid uppladdning av fil: %s\n" #: src/fs/fs_publish.c:915 msgid "needs to be an actual file" msgstr "" #: src/fs/fs_publish.c:1151 #, c-format msgid "Insufficient space for publishing: %s" msgstr "" #: src/fs/fs_publish.c:1243 #, c-format msgid "Reserving space for %u entries and %llu bytes for publication\n" msgstr "" #: src/fs/fs_publish_ksk.c:219 #, fuzzy msgid "Could not connect to datastore." msgstr "Kunde inte ansluta till gnunetd.\n" #: src/fs/fs_publish_ublock.c:219 #, fuzzy msgid "Internal error." msgstr "Okänt fel.\n" #: src/fs/fs_search.c:813 #, fuzzy, c-format msgid "Failed to parse URI `%s': %s\n" msgstr "Fil \"%s\" har URI: %s\n" #: src/fs/fs_search.c:872 #, c-format msgid "Got result with unknown block type `%d', ignoring" msgstr "" #: src/fs/fs_unindex.c:59 msgid "Failed to find given position in file" msgstr "" #: src/fs/fs_unindex.c:64 #, fuzzy msgid "Failed to read file" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_unindex.c:234 msgid "Unexpected time for a response from `fs' service." msgstr "" #: src/fs/fs_unindex.c:242 msgid "Timeout waiting for `fs' service." msgstr "" #: src/fs/fs_unindex.c:250 #, fuzzy msgid "Invalid response from `fs' service." msgstr "Ogiltigt svar till \"%s\" frÃ¥n \"%s\"\n" #: src/fs/fs_unindex.c:291 #, fuzzy msgid "Failed to connect to FS service for unindexing." msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/fs/fs_unindex.c:347 src/fs/fs_unindex.c:359 #, fuzzy msgid "Failed to get KSKs from directory scan." msgstr "Filformatsfel (inte en GNUnet-katalog?)\n" #: src/fs/fs_unindex.c:355 #, fuzzy, c-format msgid "Internal error scanning `%s'.\n" msgstr "=\tFel vid läsning av katalog.\n" #: src/fs/fs_unindex.c:414 #, fuzzy, c-format msgid "Failed to remove UBlock: %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/fs_unindex.c:562 src/fs/fs_unindex.c:626 #, fuzzy msgid "Failed to connect to `datastore' service." msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/fs/fs_unindex.c:639 #, fuzzy msgid "Failed to open file for unindexing." msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/fs/fs_unindex.c:673 #, fuzzy msgid "Failed to compute hash of file." msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/fs/fs_uri.c:222 #, no-c-format msgid "`%' must be followed by HEX number" msgstr "" #: src/fs/fs_uri.c:281 #, fuzzy msgid "Malformed KSK URI (must not begin or end with `+')" msgstr "Ogiltig URL \"%s\" (mÃ¥ste börja med \"%s\")\n" #: src/fs/fs_uri.c:299 msgid "`++' not allowed in KSK URI" msgstr "" #: src/fs/fs_uri.c:306 msgid "Quotes not balanced in KSK URI" msgstr "" #: src/fs/fs_uri.c:376 msgid "Malformed SKS URI" msgstr "" #: src/fs/fs_uri.c:419 src/fs/fs_uri.c:434 msgid "Malformed CHK URI" msgstr "" #: src/fs/fs_uri.c:512 src/fs/fs_uri.c:580 msgid "SKS URI malformed" msgstr "" #: src/fs/fs_uri.c:527 src/fs/fs_uri.c:537 msgid "LOC URI malformed" msgstr "" #: src/fs/fs_uri.c:545 src/fs/fs_uri.c:553 msgid "LOC URI malformed (could not decode public key)" msgstr "" #: src/fs/fs_uri.c:559 msgid "SKS URI malformed (could not find signature)" msgstr "" #: src/fs/fs_uri.c:565 src/fs/fs_uri.c:574 msgid "SKS URI malformed (could not decode signature)" msgstr "" #: src/fs/fs_uri.c:586 msgid "SKS URI malformed (could not parse expiration time)" msgstr "" #: src/fs/fs_uri.c:598 msgid "SKS URI malformed (signature failed validation)" msgstr "" #: src/fs/fs_uri.c:636 msgid "Unrecognized URI type" msgstr "" #: src/fs/fs_uri.c:860 #, fuzzy msgid "Lacking key configuration settings.\n" msgstr "GNUnet-konfiguration" #: src/fs/fs_uri.c:866 #, fuzzy, c-format msgid "Could not access hostkey file `%s'.\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/fs/fs_uri.c:1050 src/fs/fs_uri.c:1077 msgid "No keywords specified!\n" msgstr "Inga nyckelord angivna!\n" #: src/fs/fs_uri.c:1083 msgid "Number of double-quotes not balanced!\n" msgstr "" #: src/fs/gnunet-auto-share.c:236 #, fuzzy, c-format msgid "Failed to load state: %s\n" msgstr "Misslyckades att starta samling.\n" #: src/fs/gnunet-auto-share.c:289 src/fs/gnunet-auto-share.c:299 #: src/fs/gnunet-auto-share.c:309 #, fuzzy, c-format msgid "Failed to save state to file %s\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/fs/gnunet-auto-share.c:401 #, c-format msgid "Publication of `%s' done\n" msgstr "" #: src/fs/gnunet-auto-share.c:488 #, fuzzy, c-format msgid "Publishing `%s'\n" msgstr "" "\n" "Fel vid uppladdning av fil: %s\n" #: src/fs/gnunet-auto-share.c:497 #, fuzzy, c-format msgid "Failed to run `%s'\n" msgstr "Misslyckades att starta samling.\n" #: src/fs/gnunet-auto-share.c:686 #, fuzzy, c-format msgid "" "You must specify one and only one directory name for automatic publication.\n" msgstr "Du mÃ¥ste ange en och endast en fil att avindexera.\n" #: src/fs/gnunet-auto-share.c:737 src/fs/gnunet-publish.c:824 msgid "set the desired LEVEL of sender-anonymity" msgstr "" #: src/fs/gnunet-auto-share.c:741 src/fs/gnunet-publish.c:828 msgid "disable adding the creation time to the metadata of the uploaded file" msgstr "" #: src/fs/gnunet-auto-share.c:744 src/fs/gnunet-publish.c:831 msgid "do not use libextractor to add keywords or metadata" msgstr "" #: src/fs/gnunet-auto-share.c:747 src/fs/gnunet-publish.c:855 msgid "specify the priority of the content" msgstr "ange prioritet för innehÃ¥llet" #: src/fs/gnunet-auto-share.c:750 src/fs/gnunet-publish.c:862 msgid "set the desired replication LEVEL" msgstr "" #: src/fs/gnunet-auto-share.c:770 msgid "Automatically publish files from a directory on GNUnet" msgstr "" #: src/fs/gnunet-daemon-fsprofiler.c:660 msgid "Daemon to use file-sharing to measure its performance." msgstr "" #: src/fs/gnunet-directory.c:49 #, c-format msgid "\t\n" msgstr "" #: src/fs/gnunet-directory.c:94 #, fuzzy, c-format msgid "Directory `%s' meta data:\n" msgstr "==> Katalog \"%s\":\n" #: src/fs/gnunet-directory.c:97 #, fuzzy, c-format msgid "Directory `%s' contents:\n" msgstr "==> Katalog \"%s\":\n" #: src/fs/gnunet-directory.c:132 #, fuzzy msgid "You must specify a filename to inspect.\n" msgstr "Du mÃ¥ste ange en lista av filer att lägga in.\n" #: src/fs/gnunet-directory.c:145 #, fuzzy, c-format msgid "Failed to read directory `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/fs/gnunet-directory.c:154 #, fuzzy, c-format msgid "`%s' is not a GNUnet directory\n" msgstr "Filformatsfel (inte en GNUnet-katalog?)\n" #: src/fs/gnunet-directory.c:183 #, fuzzy msgid "Display contents of a GNUnet directory" msgstr "Filformatsfel (inte en GNUnet-katalog?)\n" #: src/fs/gnunet-download.c:137 #, fuzzy, c-format msgid "Starting download `%s'.\n" msgstr "Startade samling \"%s\".\n" #: src/fs/gnunet-download.c:147 #, fuzzy msgid "" msgstr "Okänt fel" #: src/fs/gnunet-download.c:157 #, c-format msgid "" "Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to " "download\n" msgstr "" #: src/fs/gnunet-download.c:179 #, fuzzy, c-format msgid "Error downloading: %s.\n" msgstr "Fel vid nedladdning: %s\n" #: src/fs/gnunet-download.c:194 #, fuzzy, c-format msgid "Downloading `%s' done (%s/s).\n" msgstr "Uppladdning vägrades!" #: src/fs/gnunet-download.c:209 src/fs/gnunet-publish.c:286 #: src/fs/gnunet-search.c:200 src/fs/gnunet-unindex.c:108 #, c-format msgid "Unexpected status: %d\n" msgstr "" #: src/fs/gnunet-download.c:234 #, fuzzy msgid "You need to specify a URI argument.\n" msgstr "Du mÃ¥ste ange en och endast en fil att avindexera.\n" #: src/fs/gnunet-download.c:240 src/fs/gnunet-publish.c:665 #, fuzzy, c-format msgid "Failed to parse URI: %s\n" msgstr "Fil \"%s\" har URI: %s\n" #: src/fs/gnunet-download.c:247 msgid "Only CHK or LOC URIs supported.\n" msgstr "" #: src/fs/gnunet-download.c:254 msgid "Target filename must be specified.\n" msgstr "" #: src/fs/gnunet-download.c:268 src/fs/gnunet-publish.c:797 #: src/fs/gnunet-search.c:250 src/fs/gnunet-unindex.c:140 #, fuzzy, c-format msgid "Could not initialize `%s' subsystem.\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/fs/gnunet-download.c:305 src/fs/gnunet-search.c:289 msgid "set the desired LEVEL of receiver-anonymity" msgstr "" #: src/fs/gnunet-download.c:308 msgid "delete incomplete downloads (when aborted with CTRL-C)" msgstr "" #: src/fs/gnunet-download.c:311 src/fs/gnunet-search.c:292 msgid "only search the local peer (no P2P network search)" msgstr "" #: src/fs/gnunet-download.c:314 msgid "write the file to FILENAME" msgstr "skriv filen till FILNAMN" #: src/fs/gnunet-download.c:318 msgid "set the maximum number of parallel downloads that is allowed" msgstr "" #: src/fs/gnunet-download.c:322 msgid "set the maximum number of parallel requests for blocks that is allowed" msgstr "" #: src/fs/gnunet-download.c:325 msgid "download a GNUnet directory recursively" msgstr "hämta en GNUnet-katalog rekursivt" #: src/fs/gnunet-download.c:339 msgid "" "Download files from GNUnet using a GNUnet CHK or LOC URI (gnunet://fs/" "chk/...)" msgstr "" #: src/fs/gnunet-fs.c:117 msgid "print a list of all indexed files" msgstr "" #: src/fs/gnunet-fs.c:127 #, fuzzy msgid "Special file-sharing operations" msgstr "Visa alla alternativ" #: src/fs/gnunet-fs-profiler.c:193 msgid "run the experiment with COUNT peers" msgstr "" #: src/fs/gnunet-fs-profiler.c:196 msgid "specifies name of a file with the HOSTS the testbed should use" msgstr "" #: src/fs/gnunet-fs-profiler.c:199 msgid "automatically terminate experiment after DELAY" msgstr "" #: src/fs/gnunet-fs-profiler.c:208 msgid "run a testbed to measure file-sharing performance" msgstr "" #: src/fs/gnunet-publish.c:231 src/fs/gnunet-publish.c:243 #, c-format msgid "Publishing `%s' at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-publish.c:250 #, fuzzy, c-format msgid "Error publishing: %s.\n" msgstr "Fel vid nedladdning: %s\n" #: src/fs/gnunet-publish.c:260 #, c-format msgid "Publishing `%s' done.\n" msgstr "" #: src/fs/gnunet-publish.c:264 #, fuzzy, c-format msgid "URI is `%s'.\n" msgstr "Jag är ändpunkt \"%s\".\n" #: src/fs/gnunet-publish.c:283 #, fuzzy msgid "Cleanup after abort complete.\n" msgstr "\"%s\" uppstart klar.\n" #: src/fs/gnunet-publish.c:401 #, fuzzy, c-format msgid "Meta data for file `%s' (%s)\n" msgstr "Uppdaterar data för modul \"%s\"\n" #: src/fs/gnunet-publish.c:403 #, fuzzy, c-format msgid "Keywords for file `%s' (%s)\n" msgstr "Nyckelord för fil \"%s\":\n" #: src/fs/gnunet-publish.c:542 #, fuzzy msgid "Could not publish\n" msgstr "Kunde inte köra \"%s\": %s\n" #: src/fs/gnunet-publish.c:565 #, fuzzy msgid "Could not start publishing.\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/fs/gnunet-publish.c:598 #, fuzzy, c-format msgid "Scanning directory `%s'.\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/fs/gnunet-publish.c:600 #, fuzzy, c-format msgid "Scanning file `%s'.\n" msgstr "Startade samling \"%s\".\n" #: src/fs/gnunet-publish.c:605 #, c-format msgid "There was trouble processing file `%s', skipping it.\n" msgstr "" #: src/fs/gnunet-publish.c:610 #, fuzzy msgid "Preprocessing complete.\n" msgstr "Nedstängning klar.\n" #: src/fs/gnunet-publish.c:614 #, fuzzy, c-format msgid "Extracting meta data from file `%s' complete.\n" msgstr "Uppdaterar data för modul \"%s\"\n" #: src/fs/gnunet-publish.c:618 msgid "Meta data extraction has finished.\n" msgstr "" #: src/fs/gnunet-publish.c:625 #, fuzzy msgid "Internal error scanning directory.\n" msgstr "=\tFel vid läsning av katalog.\n" #: src/fs/gnunet-publish.c:656 #, fuzzy, c-format msgid "Selected pseudonym `%s' unknown\n" msgstr "Namnrymd \"%s\" skapad(rot: %s).\n" #: src/fs/gnunet-publish.c:682 #, fuzzy, c-format msgid "Failed to access `%s': %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/gnunet-publish.c:695 msgid "" "Failed to start meta directory scanner. Is gnunet-helper-publish-fs " "installed?\n" msgstr "" #: src/fs/gnunet-publish.c:747 #, c-format msgid "Cannot extract metadata from a URI!\n" msgstr "" #: src/fs/gnunet-publish.c:754 #, fuzzy, c-format msgid "You must specify one and only one filename for insertion.\n" msgstr "Du mÃ¥ste ange en och endast en fil att avindexera.\n" #: src/fs/gnunet-publish.c:760 #, fuzzy, c-format msgid "You must NOT specify an URI and a filename.\n" msgstr "Du mÃ¥ste ange en och endast en fil att avindexera.\n" #: src/fs/gnunet-publish.c:768 src/vpn/gnunet-vpn.c:209 #, fuzzy, c-format msgid "Option `%s' is required when using option `%s'.\n" msgstr "Kommando \"%s\" kräver ett argument (\"%s\").\n" #: src/fs/gnunet-publish.c:778 src/fs/gnunet-publish.c:785 #: src/transport/gnunet-transport.c:1284 src/transport/gnunet-transport.c:1314 #: src/transport/gnunet-transport.c:1344 #, c-format msgid "Option `%s' makes no sense without option `%s'.\n" msgstr "" #: src/fs/gnunet-publish.c:835 msgid "" "print list of extracted keywords that would be used, but do not perform " "upload" msgstr "" #: src/fs/gnunet-publish.c:839 msgid "" "add an additional keyword for the top-level file or directory (this option " "can be specified multiple times)" msgstr "" #: src/fs/gnunet-publish.c:843 msgid "set the meta-data for the given TYPE to the given VALUE" msgstr "" #: src/fs/gnunet-publish.c:846 msgid "" "do not index, perform full insertion (stores entire file in encrypted form " "in GNUnet database)" msgstr "" #: src/fs/gnunet-publish.c:851 msgid "" "specify ID of an updated version to be published in the future (for " "namespace insertions only)" msgstr "" #: src/fs/gnunet-publish.c:859 msgid "publish the files under the pseudonym NAME (place file into namespace)" msgstr "" #: src/fs/gnunet-publish.c:865 msgid "" "only simulate the process but do not do any actual publishing (useful to " "compute URIs)" msgstr "" #: src/fs/gnunet-publish.c:869 msgid "" "set the ID of this version of the publication (for namespace insertions only)" msgstr "" #: src/fs/gnunet-publish.c:873 msgid "" "URI to be published (can be used instead of passing a file to add keywords " "to the file with the respective URI)" msgstr "" #: src/fs/gnunet-publish.c:889 msgid "Publish a file or directory on GNUnet" msgstr "" #: src/fs/gnunet-search.c:114 #, c-format msgid "Failed to write directory with search results to `%s'\n" msgstr "" #: src/fs/gnunet-search.c:191 #, fuzzy, c-format msgid "Error searching: %s.\n" msgstr "Fel vid lämning av DHT.\n" #: src/fs/gnunet-search.c:240 #, fuzzy msgid "Could not create keyword URI from arguments.\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/fs/gnunet-search.c:264 #, fuzzy msgid "Could not start searching.\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/fs/gnunet-search.c:295 msgid "write search results to file starting with PREFIX" msgstr "" #: src/fs/gnunet-search.c:298 msgid "automatically terminate search after DELAY" msgstr "" #: src/fs/gnunet-search.c:305 msgid "automatically terminate search after VALUE results are found" msgstr "" #: src/fs/gnunet-search.c:316 msgid "Search GNUnet for files that were published on GNUnet" msgstr "" #: src/fs/gnunet-service-fs.c:271 msgid "# running average P2P latency (ms)" msgstr "" #: src/fs/gnunet-service-fs.c:326 src/fs/gnunet-service-fs.c:539 msgid "# Loopback routes suppressed" msgstr "" #: src/fs/gnunet-service-fs.c:639 src/hostlist/gnunet-daemon-hostlist.c:288 #: src/topology/gnunet-daemon-topology.c:1254 #: src/topology/gnunet-daemon-topology.c:1261 #, fuzzy, c-format msgid "Failed to connect to `%s' service.\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/fs/gnunet-service-fs_cp.c:682 #, fuzzy msgid "# migration stop messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/fs/gnunet-service-fs_cp.c:686 #, c-format msgid "Migration of content to peer `%s' blocked for %s\n" msgstr "" #: src/fs/gnunet-service-fs_cp.c:721 #, fuzzy msgid "# replies transmitted to other peers" msgstr "# byte skickade av typen %d" #: src/fs/gnunet-service-fs_cp.c:727 msgid "# replies dropped" msgstr "" #: src/fs/gnunet-service-fs_cp.c:752 src/fs/gnunet-service-fs_cp.c:1301 msgid "# P2P searches active" msgstr "" #: src/fs/gnunet-service-fs_cp.c:845 msgid "# artificial delays introduced (ms)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:898 #, fuzzy msgid "# replies dropped due to type mismatch" msgstr "# byte mottagna av typen %d" #: src/fs/gnunet-service-fs_cp.c:906 #, fuzzy msgid "# replies received for other peers" msgstr "# byte mottagna av typen %d" #: src/fs/gnunet-service-fs_cp.c:920 msgid "# replies dropped due to insufficient cover traffic" msgstr "" #: src/fs/gnunet-service-fs_cp.c:958 msgid "# P2P searches destroyed due to ultimate reply" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1026 msgid "# requests done for free (low load)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1051 msgid "# request dropped, priority insufficient" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1061 msgid "# requests done for a price (normal load)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1139 msgid "# GET requests received (from other peers)" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1173 msgid "# requests dropped due to initiator not being connected" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1195 msgid "# requests dropped due to missing reverse route" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1246 msgid "# requests dropped due TTL underflow" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1270 msgid "# requests dropped due to higher-TTL request" msgstr "" #: src/fs/gnunet-service-fs_cp.c:1299 #, fuzzy msgid "# P2P query messages received and processed" msgstr "# krypterade PONG-meddelanden mottagna" #: src/fs/gnunet-service-fs_cp.c:1670 #, fuzzy msgid "# migration stop messages sent" msgstr "# krypterade PONG-meddelanden mottagna" #: src/fs/gnunet-service-fs_indexing.c:130 #: src/fs/gnunet-service-fs_indexing.c:181 #, fuzzy, c-format msgid "Could not open `%s'.\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/fs/gnunet-service-fs_indexing.c:142 #, fuzzy, c-format msgid "Error writing `%s'.\n" msgstr "Fel vid skapandet av användare" #: src/fs/gnunet-service-fs_indexing.c:237 #, c-format msgid "" "Index request received for file `%s' is already indexed as `%s'. Permitting " "anyway.\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:275 #, c-format msgid "Hash mismatch trying to index file `%s' which has hash `%s'\n" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:477 #, fuzzy, c-format msgid "Failed to delete bogus block: %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/fs/gnunet-service-fs_indexing.c:542 msgid "# index blocks removed: original file inaccessible" msgstr "" #: src/fs/gnunet-service-fs_indexing.c:557 #, fuzzy, c-format msgid "Could not access indexed file `%s' (%s) at offset %llu: %s\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/fs/gnunet-service-fs_indexing.c:559 #, fuzzy msgid "not indexed" msgstr "Avindexering misslyckades." #: src/fs/gnunet-service-fs_indexing.c:574 #, fuzzy, c-format msgid "Indexed file `%s' changed at offset %llu\n" msgstr "Indexering av data misslyckades vid position %i.\n" #: src/fs/gnunet-service-fs_lc.c:202 src/fs/gnunet-service-fs_lc.c:368 #, fuzzy msgid "# client searches active" msgstr "# klartext PONG-meddelanden mottagna" #: src/fs/gnunet-service-fs_lc.c:256 #, fuzzy msgid "# replies received for local clients" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/fs/gnunet-service-fs_lc.c:327 #, fuzzy msgid "# client searches received" msgstr "# klartext PONG-meddelanden mottagna" #: src/fs/gnunet-service-fs_lc.c:362 msgid "# client searches updated (merged content seen list)" msgstr "" #: src/fs/gnunet-service-fs_mesh_client.c:484 #, fuzzy msgid "# replies received via mesh" msgstr "# byte mottagna av typen %d" #: src/fs/gnunet-service-fs_mesh_client.c:498 #, fuzzy msgid "# replies received via mesh dropped" msgstr "# byte mottagna av typen %d" #: src/fs/gnunet-service-fs_mesh_server.c:260 #, fuzzy msgid "# Blocks transferred via mesh" msgstr "# byte skickade av typen %d" #: src/fs/gnunet-service-fs_mesh_server.c:352 #, fuzzy msgid "# queries received via mesh not answered" msgstr "# byte mottogs via TCP" #: src/fs/gnunet-service-fs_mesh_server.c:432 #, fuzzy msgid "# queries received via mesh" msgstr "# byte mottogs via TCP" #: src/fs/gnunet-service-fs_mesh_server.c:476 #, fuzzy msgid "# mesh client connections rejected" msgstr "Nätverksanslutning" #: src/fs/gnunet-service-fs_mesh_server.c:482 #: src/fs/gnunet-service-fs_mesh_server.c:522 #, fuzzy msgid "# mesh connections active" msgstr "Nätverksanslutning" #: src/fs/gnunet-service-fs_pe.c:269 msgid "# average retransmission delay (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:400 #, fuzzy msgid "# transmission failed (core has no bandwidth)" msgstr "Ingen transport av typ %d är känd.\n" #: src/fs/gnunet-service-fs_pe.c:433 #, fuzzy msgid "# query messages sent to other peers" msgstr "# byte skickade av typen %d" #: src/fs/gnunet-service-fs_pe.c:484 msgid "# delay heap timeout (ms)" msgstr "" #: src/fs/gnunet-service-fs_pe.c:492 msgid "# query plans executed" msgstr "" #: src/fs/gnunet-service-fs_pe.c:552 #, fuzzy msgid "# requests merged" msgstr "# byte mottogs via TCP" #: src/fs/gnunet-service-fs_pe.c:560 #, fuzzy msgid "# requests refreshed" msgstr "# byte mottogs via TCP" #: src/fs/gnunet-service-fs_pe.c:616 src/fs/gnunet-service-fs_pe.c:700 #: src/fs/gnunet-service-fs_pe.c:771 msgid "# query plan entries" msgstr "" #: src/fs/gnunet-service-fs_pr.c:311 #, fuzzy msgid "# Pending requests created" msgstr "# byte mottogs via TCP" #: src/fs/gnunet-service-fs_pr.c:394 src/fs/gnunet-service-fs_pr.c:645 msgid "# Pending requests active" msgstr "" #: src/fs/gnunet-service-fs_pr.c:814 #, fuzzy msgid "# replies received and matched" msgstr "# byte mottagna av typen %d" #: src/fs/gnunet-service-fs_pr.c:844 msgid "# duplicate replies discarded (bloomfilter)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:853 msgid "# irrelevant replies discarded" msgstr "" #: src/fs/gnunet-service-fs_pr.c:867 #, c-format msgid "Unsupported block type %u\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:880 msgid "# results found locally" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1001 msgid "# Datastore `PUT' failures" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1029 #, fuzzy msgid "# storage requests dropped due to high load" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/fs/gnunet-service-fs_pr.c:1064 #, fuzzy msgid "# Replies received from DHT" msgstr "# byte mottagna via HTTP" #: src/fs/gnunet-service-fs_pr.c:1192 #, fuzzy msgid "# Replies received from MESH" msgstr "# byte mottagna via HTTP" #: src/fs/gnunet-service-fs_pr.c:1244 #, c-format msgid "Datastore lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1264 #, c-format msgid "On-demand lookup already took %s!\n" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1311 msgid "# Datastore lookups concluded (no results)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1326 msgid "# Datastore lookups concluded (seen all)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1335 msgid "# Datastore lookups aborted (more than MAX_RESULTS)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1350 msgid "# requested DBLOCK or IBLOCK not found" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1364 msgid "# on-demand blocks matched requests" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1377 msgid "# on-demand lookups performed successfully" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1382 msgid "# on-demand lookups failed" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1409 src/fs/gnunet-service-fs_pr.c:1449 #: src/fs/gnunet-service-fs_pr.c:1590 msgid "# Datastore lookups concluded (error queueing)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1467 msgid "# Datastore lookups concluded (found last result)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1478 msgid "# Datastore lookups concluded (load too high)" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1566 msgid "# Datastore lookups initiated" msgstr "" #: src/fs/gnunet-service-fs_pr.c:1651 #, fuzzy msgid "# GAP PUT messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/fs/gnunet-service-fs_push.c:631 msgid "time required, content pushing disabled" msgstr "" #: src/fs/gnunet-unindex.c:89 #, c-format msgid "Unindexing at %llu/%llu (%s remaining)\n" msgstr "" #: src/fs/gnunet-unindex.c:95 #, fuzzy, c-format msgid "Error unindexing: %s.\n" msgstr "" "\n" "Fel vid avindexering av fil: %s\n" #: src/fs/gnunet-unindex.c:100 #, fuzzy msgid "Unindexing done.\n" msgstr "Avindexera filer." #: src/fs/gnunet-unindex.c:130 #, fuzzy, c-format msgid "You must specify one and only one filename for unindexing.\n" msgstr "Du mÃ¥ste ange en och endast en fil att avindexera.\n" #: src/fs/gnunet-unindex.c:147 #, fuzzy msgid "Could not start unindex operation.\n" msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #: src/fs/gnunet-unindex.c:179 msgid "Unindex a file that was previously indexed with gnunet-publish." msgstr "" #: src/gns/gns_api.c:393 #, fuzzy msgid "Failed to deserialize lookup reply from GNS service!\n" msgstr "Misslyckades att ta emot svar till \"%s\" meddelande frÃ¥n gnunetd\n" #: src/gns/gnunet-bcd.c:123 #, c-format msgid "Refusing `%s' request to HTTP server\n" msgstr "" #: src/gns/gnunet-bcd.c:355 src/hostlist/hostlist-server.c:567 #, fuzzy, c-format msgid "Invalid port number %llu. Exiting.\n" msgstr "Ogiltiga argument. Avslutar.\n" #: src/gns/gnunet-bcd.c:360 #, c-format msgid "Businesscard HTTP server starts on %llu\n" msgstr "" #: src/gns/gnunet-bcd.c:374 #, fuzzy, c-format msgid "Could not start businesscard HTTP server on port %u\n" msgstr "Misslyckades att starta samling.\n" #: src/gns/gnunet-bcd.c:519 msgid "Run HTTP serve on port PORT (default is 8888)" msgstr "" #: src/gns/gnunet-bcd.c:531 msgid "GNUnet HTTP server to create business cards" msgstr "" #: src/gns/gnunet-dns2gns.c:228 #, fuzzy msgid "Failed to pack DNS response into UDP packet!\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/gns/gnunet-dns2gns.c:400 #, fuzzy, c-format msgid "Cannot parse DNS request from %s\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/gns/gnunet-dns2gns.c:416 #, fuzzy, c-format msgid "Received malformed DNS request from %s\n" msgstr "Mottog ogiltig \"%s\" begäran (storlek %d)\n" #: src/gns/gnunet-dns2gns.c:424 #, fuzzy, c-format msgid "Received unsupported DNS request from %s\n" msgstr "Mottog okänd typ av begäran %d vid %s:%d\n" #: src/gns/gnunet-dns2gns.c:701 msgid "No ego configured for `dns2gns` subsystem\n" msgstr "" #: src/gns/gnunet-dns2gns.c:727 #, fuzzy msgid "No DNS server specified!\n" msgstr "Inga nyckelord angivna!\n" #: src/gns/gnunet-dns2gns.c:749 #, fuzzy msgid "No valid GNS zone specified!\n" msgstr "Inga nyckelord angivna!\n" #: src/gns/gnunet-dns2gns.c:770 msgid "IP of recursive DNS resolver to use (required)" msgstr "" #: src/gns/gnunet-dns2gns.c:773 msgid "Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:776 msgid "Authoritative DNS suffix to use (optional); default: zkey.eu" msgstr "" #: src/gns/gnunet-dns2gns.c:779 msgid "UDP port to listen on for inbound DNS requests; default: 53" msgstr "" #: src/gns/gnunet-dns2gns.c:782 msgid "Public key of the GNS zone to use (overrides default)" msgstr "" #: src/gns/gnunet-dns2gns.c:795 msgid "GNUnet DNS-to-GNS proxy (a DNS server)" msgstr "" #: src/gns/gnunet-gns.c:227 #, c-format msgid "Please specify name to lookup!\n" msgstr "" #: src/gns/gnunet-gns.c:308 #, c-format msgid "Ego for `%s' not found, cannot perform lookup.\n" msgstr "" #: src/gns/gnunet-gns.c:347 src/gns/gnunet-gns-helper-service-w32.c:798 #, c-format msgid "" "Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-" "gns-import.sh?\n" msgstr "" #: src/gns/gnunet-gns.c:386 src/gns/gnunet-gns-helper-service-w32.c:828 #, fuzzy, c-format msgid "Failed to connect to GNS\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/gns/gnunet-gns.c:399 #, c-format msgid "Public key `%s' is not well-formed\n" msgstr "" #: src/gns/gnunet-gns.c:449 msgid "Lookup a record for the given name" msgstr "" #: src/gns/gnunet-gns.c:452 #, fuzzy msgid "Specify the type of the record to lookup" msgstr "ange prioritet för innehÃ¥llet" #: src/gns/gnunet-gns.c:455 #, fuzzy msgid "Specify timeout for the lookup" msgstr "ange prioritet för innehÃ¥llet" #: src/gns/gnunet-gns.c:458 msgid "No unneeded output" msgstr "" #: src/gns/gnunet-gns.c:461 #, fuzzy msgid "Specify the public key of the zone to lookup the record in" msgstr "ange prioritet för innehÃ¥llet" #: src/gns/gnunet-gns.c:464 #, fuzzy msgid "Specify the name of the ego of the zone to lookup the record in" msgstr "ange prioritet för innehÃ¥llet" #: src/gns/gnunet-gns.c:478 #, fuzzy msgid "GNUnet GNS resolver tool" msgstr "SpÃ¥ra GNUnets nätverkstopologi." #: src/gns/gnunet-gns-helper-service-w32.c:768 #, c-format msgid "" "Ego for `gns-short' not found. This is not really fatal, but i'll pretend " "that it is and refuse to perform a lookup. Did you run gnunet-gns-import." "sh?\n" msgstr "" #: src/gns/gnunet-gns-helper-service-w32.c:838 #, fuzzy, c-format msgid "Failed to connect to identity service\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/gns/gnunet-gns-import.c:479 msgid "This program will import some GNS authorities into your GNS namestore." msgstr "" #: src/gns/gnunet-gns-proxy.c:105 src/hostlist/hostlist-client.c:469 #: src/hostlist/hostlist-client.c:683 src/hostlist/hostlist-client.c:689 #: src/hostlist/hostlist-client.c:741 src/hostlist/hostlist-client.c:750 #: src/hostlist/hostlist-client.c:871 src/hostlist/hostlist-client.c:963 #: src/hostlist/hostlist-client.c:968 #: src/transport/plugin_transport_http_client.c:1062 #: src/transport/plugin_transport_http_client.c:1077 #, fuzzy, c-format msgid "%s failed at %s:%d: `%s'\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/gns/gnunet-gns-proxy.c:833 #, fuzzy, c-format msgid "Unsupported CURL SSL backend %d\n" msgstr "Kommando \"%s\" stöds ej. Avbryter.\n" #: src/gns/gnunet-gns-proxy.c:856 #, fuzzy, c-format msgid "Failed to fetch CN from cert: %s\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/gns/gnunet-gns-proxy.c:879 #, fuzzy, c-format msgid "Failed to initialize DANE: %s\n" msgstr "Kunde inte initiera SQLite.\n" #: src/gns/gnunet-gns-proxy.c:892 #, fuzzy, c-format msgid "Failed to parse DANE record: %s\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/gns/gnunet-gns-proxy.c:907 #, fuzzy, c-format msgid "Failed to verify TLS connection using DANE: %s\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/gns/gnunet-gns-proxy.c:917 #, c-format msgid "Failed DANE verification failed with GnuTLS verify status code: %u\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:941 #, c-format msgid "SSL certificate subject name (%s) does not match `%s'\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1086 #, c-format msgid "Cookie domain `%s' supplied by server is invalid\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:1602 #, fuzzy, c-format msgid "Unsupported HTTP method `%s'\n" msgstr "Kommando \"%s\" stöds ej. Avbryter.\n" #: src/gns/gnunet-gns-proxy.c:1973 #, fuzzy, c-format msgid "Unable to import private key from file `%s'\n" msgstr "Kunde inte skapa användarkonto:" #: src/gns/gnunet-gns-proxy.c:2003 #, fuzzy, c-format msgid "Unable to import certificate %s\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/gns/gnunet-gns-proxy.c:2177 #, fuzzy, c-format msgid "Failed to start HTTPS server for `%s'\n" msgstr "Misslyckades att starta samling.\n" #: src/gns/gnunet-gns-proxy.c:2196 #, fuzzy msgid "Failed to pass client to MHD\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/gns/gnunet-gns-proxy.c:2504 #, fuzzy, c-format msgid "Unsupported socks version %d\n" msgstr "Kommando \"%s\" stöds ej. Avbryter.\n" #: src/gns/gnunet-gns-proxy.c:2533 #, fuzzy, c-format msgid "Unsupported socks command %d\n" msgstr "Kommando \"%s\" stöds ej. Avbryter.\n" #: src/gns/gnunet-gns-proxy.c:2551 src/gns/gnunet-gns-proxy.c:2580 msgid "SSL connection to plain IPv4 address requested\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:2631 #, fuzzy, c-format msgid "Unsupported socks address type %d\n" msgstr "Kommando \"%s\" stöds ej. Avbryter.\n" #: src/gns/gnunet-gns-proxy.c:2970 msgid "No ego configured for `shorten-zone`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3010 #, c-format msgid "No ego configured for `%s`\n" msgstr "" #: src/gns/gnunet-gns-proxy.c:3072 #, fuzzy, c-format msgid "Failed to load SSL/TLS key and certificate from `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/gns/gnunet-gns-proxy.c:3113 msgid "listen on specified port (default: 7777)" msgstr "" #: src/gns/gnunet-gns-proxy.c:3116 msgid "pem file to use as CA" msgstr "" #: src/gns/gnunet-gns-proxy.c:3135 msgid "GNUnet GNS proxy" msgstr "" #: src/gns/gnunet-service-gns.c:862 #, fuzzy msgid "Failed to connect to the namestore!\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/gns/gnunet-service-gns.c:870 #, fuzzy msgid "Failed to connect to the namecache!\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/gns/gnunet-service-gns.c:903 #, fuzzy msgid "Could not connect to DHT!\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/gns/gnunet-service-gns.c:919 #, fuzzy msgid "valid public key required" msgstr "Ogiltigt argument: \"%s\"\n" #: src/gns/gnunet-service-gns_interceptor.c:263 msgid "Error converting GNS response to DNS response!\n" msgstr "" #: src/gns/gnunet-service-gns_interceptor.c:369 #, fuzzy msgid "Failed to connect to the DNS service!\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/gns/gnunet-service-gns_resolver.c:816 #, fuzzy msgid "Failed to parse DNS response\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/gns/gnunet-service-gns_resolver.c:958 #, c-format msgid "Skipping record of unsupported type %d\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1317 #, c-format msgid "GNS lookup resulted in DNS name that is too long (`%s')\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1817 msgid "GNS lookup recursion failed (no delegation record found)\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:1841 #, fuzzy, c-format msgid "Failed to cache GNS resolution: %s\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/gns/gnunet-service-gns_resolver.c:2123 #, c-format msgid "Zone %s was revoked, resolution fails\n" msgstr "" #: src/gns/gnunet-service-gns_resolver.c:2272 #, c-format msgid "Hostname `%s' is not well-formed, resolution fails\n" msgstr "" #: src/gns/plugin_gnsrecord_gns.c:151 #, fuzzy, c-format msgid "Unable to parse PKEY record `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/gns/plugin_gnsrecord_gns.c:180 #, fuzzy, c-format msgid "Unable to parse GNS2DNS record `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/gns/plugin_gnsrecord_gns.c:201 #, fuzzy, c-format msgid "Failed to serialize GNS2DNS record with value `%s'\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/gns/plugin_gnsrecord_gns.c:217 #, fuzzy, c-format msgid "Unable to parse VPN record string `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:293 #, fuzzy, c-format msgid "Unable to parse IPv4 address `%s'\n" msgstr "Ogiltigt svar pÃ¥ \"%s\".\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:314 #, fuzzy, c-format msgid "Failed to serialize NS record with value `%s'\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:336 #, fuzzy, c-format msgid "Failed to serialize CNAME record with value `%s'\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:420 #, fuzzy, c-format msgid "Failed to serialize CERT record with %u bytes\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:452 #, fuzzy, c-format msgid "Unable to parse SOA record `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:471 #, fuzzy, c-format msgid "Failed to serialize SOA record with mname `%s' and rname `%s'\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:494 #, fuzzy, c-format msgid "Failed to serialize PTR record with value `%s'\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:514 #, fuzzy, c-format msgid "Unable to parse MX record `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:529 #, fuzzy, c-format msgid "Failed to serialize MX record with hostname `%s'\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:549 #, fuzzy, c-format msgid "Unable to parse IPv6 address `%s'\n" msgstr "Ogiltigt svar pÃ¥ \"%s\".\n" #: src/gnsrecord/plugin_gnsrecord_dns.c:567 #, fuzzy, c-format msgid "Unable to parse TLSA record string `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/hello/gnunet-hello.c:123 msgid "Call with name of HELLO file to modify.\n" msgstr "" #: src/hello/gnunet-hello.c:129 #, fuzzy, c-format msgid "Error accessing file `%s': %s\n" msgstr "Fel vid skapandet av användare" #: src/hello/gnunet-hello.c:137 #, c-format msgid "File `%s' is too big to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:144 #, c-format msgid "File `%s' is too small to be a HELLO\n" msgstr "" #: src/hello/gnunet-hello.c:154 src/hello/gnunet-hello.c:183 #, fuzzy, c-format msgid "Error opening file `%s': %s\n" msgstr "Fel vid skapandet av användare" #: src/hello/gnunet-hello.c:170 #, fuzzy, c-format msgid "Did not find well-formed HELLO in file `%s'\n" msgstr "%d filer hittades i katalog.\n" #: src/hello/gnunet-hello.c:195 #, fuzzy, c-format msgid "Error writing HELLO to file `%s': %s\n" msgstr "Fel vid skapandet av användare" #: src/hello/gnunet-hello.c:203 #, c-format msgid "Modified %u addresses \n" msgstr "" #: src/hello/hello.c:944 #, fuzzy msgid "Failed to parse HELLO message: missing expiration time\n" msgstr "Kunde inte spara konfiguration!" #: src/hello/hello.c:953 #, fuzzy msgid "Failed to parse HELLO message: invalid expiration time\n" msgstr "Kunde inte spara konfiguration!" #: src/hello/hello.c:963 #, fuzzy msgid "Failed to parse HELLO message: malformed\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/hello/hello.c:973 #, fuzzy msgid "Failed to parse HELLO message: missing transport plugin\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/hello/hello.c:990 #, c-format msgid "Plugin `%s' not found\n" msgstr "" #: src/hello/hello.c:999 #, c-format msgid "Plugin `%s' does not support URIs yet\n" msgstr "" #: src/hello/hello.c:1018 #, fuzzy, c-format msgid "Failed to parse `%s' as an address for plugin `%s'\n" msgstr "Misslyckades att binda till UDP-port %d.\n" #: src/hostlist/gnunet-daemon-hostlist.c:259 msgid "" "None of the functions for the hostlist daemon were enabled. I have no " "reason to run!\n" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:308 msgid "advertise our hostlist to other peers" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:313 msgid "" "bootstrap using hostlists (it is highly recommended that you always use this " "option)" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:316 msgid "enable learning about hostlist servers from other peers" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:320 msgid "provide a hostlist server" msgstr "" #: src/hostlist/gnunet-daemon-hostlist.c:335 msgid "GNUnet hostlist server and client" msgstr "" #: src/hostlist/hostlist-client.c:288 msgid "# bytes downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:309 src/hostlist/hostlist-client.c:339 msgid "# invalid HELLOs downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:312 src/hostlist/hostlist-client.c:342 #, fuzzy, c-format msgid "Invalid `%s' message received from hostlist at `%s'\n" msgstr "Ogiltigt meddelande mottogs den %s:%d." #: src/hostlist/hostlist-client.c:330 msgid "# valid HELLOs downloaded from hostlist servers" msgstr "" #: src/hostlist/hostlist-client.c:592 src/hostlist/hostlist-client.c:1333 msgid "# advertised hostlist URIs" msgstr "" #: src/hostlist/hostlist-client.c:622 #, c-format msgid "# advertised URI `%s' downloaded" msgstr "" #: src/hostlist/hostlist-client.c:664 #, c-format msgid "" "Advertised hostlist with URI `%s' could not be downloaded. Advertised URI " "gets dismissed.\n" msgstr "" #: src/hostlist/hostlist-client.c:802 #, fuzzy, c-format msgid "Timeout trying to download hostlist from `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/hostlist/hostlist-client.c:816 #, c-format msgid "Download limit of %u bytes exceeded, stopping download\n" msgstr "" #: src/hostlist/hostlist-client.c:836 #, fuzzy, c-format msgid "Download of hostlist from `%s' failed: `%s'\n" msgstr "" "Uppladdning av \"%s\" klar, aktuell genomsnittshastighet är %8.3f kbps.\n" #: src/hostlist/hostlist-client.c:842 #, fuzzy, c-format msgid "Download of hostlist `%s' completed.\n" msgstr "" "Uppladdning av \"%s\" klar, aktuell genomsnittshastighet är %8.3f kbps.\n" #: src/hostlist/hostlist-client.c:850 #, c-format msgid "Adding successfully tested hostlist `%s' datastore.\n" msgstr "" #: src/hostlist/hostlist-client.c:903 #, c-format msgid "Bootstrapping using hostlist at `%s'.\n" msgstr "" #: src/hostlist/hostlist-client.c:911 msgid "# hostlist downloads initiated" msgstr "" #: src/hostlist/hostlist-client.c:1040 src/hostlist/hostlist-client.c:1506 msgid "# milliseconds between hostlist downloads" msgstr "" #: src/hostlist/hostlist-client.c:1049 #, c-format msgid "Have %u/%u connections. Will consider downloading hostlist in %s\n" msgstr "" #: src/hostlist/hostlist-client.c:1109 src/hostlist/hostlist-client.c:1125 #, fuzzy msgid "# active connections" msgstr "Nätverksanslutning" #: src/hostlist/hostlist-client.c:1280 #, fuzzy, c-format msgid "Loading saved hostlist entries from file `%s' \n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/hostlist/hostlist-client.c:1285 #, fuzzy, c-format msgid "Hostlist file `%s' does not exist\n" msgstr "antal meddelanden att använda per iteration" #: src/hostlist/hostlist-client.c:1296 #, fuzzy, c-format msgid "Could not open file `%s' for reading to load hostlists: %s\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/hostlist/hostlist-client.c:1329 #, c-format msgid "%u hostlist URIs loaded from file\n" msgstr "" #: src/hostlist/hostlist-client.c:1331 msgid "# hostlist URIs read from file" msgstr "" #: src/hostlist/hostlist-client.c:1376 #, fuzzy, c-format msgid "Could not open file `%s' for writing to save hostlists: %s\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/hostlist/hostlist-client.c:1381 #, fuzzy, c-format msgid "Writing %u hostlist URIs to `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/hostlist/hostlist-client.c:1405 src/hostlist/hostlist-client.c:1422 #, c-format msgid "Error writing hostlist URIs to file `%s'\n" msgstr "" #: src/hostlist/hostlist-client.c:1417 msgid "# hostlist URIs written to file" msgstr "" #: src/hostlist/hostlist-client.c:1471 msgid "Learning is enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1483 msgid "Learning is not enabled on this peer\n" msgstr "" #: src/hostlist/hostlist-client.c:1495 #, c-format msgid "" "Since learning is not enabled on this peer, hostlist file `%s' was removed\n" msgstr "" #: src/hostlist/hostlist-client.c:1499 #, c-format msgid "Hostlist file `%s' could not be removed\n" msgstr "" #: src/hostlist/hostlist-server.c:137 #, fuzzy msgid "bytes in hostlist" msgstr "# byte krypterade" #: src/hostlist/hostlist-server.c:161 msgid "expired addresses encountered" msgstr "" #: src/hostlist/hostlist-server.c:189 src/hostlist/hostlist-server.c:425 #: src/peerinfo-tool/gnunet-peerinfo.c:350 #: src/peerinfo-tool/gnunet-peerinfo.c:419 #: src/peerinfo-tool/gnunet-peerinfo.c:490 #: src/topology/gnunet-daemon-topology.c:925 #, fuzzy, c-format msgid "Error in communication with PEERINFO service: %s\n" msgstr "Skriv ut information om GNUnets motparter." #: src/hostlist/hostlist-server.c:210 msgid "HELLOs without addresses encountered (ignored)" msgstr "" #: src/hostlist/hostlist-server.c:224 msgid "bytes not included in hostlist (size limit)" msgstr "" #: src/hostlist/hostlist-server.c:268 #, c-format msgid "Refusing `%s' request to hostlist server\n" msgstr "" #: src/hostlist/hostlist-server.c:271 msgid "hostlist requests refused (not HTTP GET)" msgstr "" #: src/hostlist/hostlist-server.c:284 #, c-format msgid "Refusing `%s' request with %llu bytes of upload data\n" msgstr "" #: src/hostlist/hostlist-server.c:288 msgid "hostlist requests refused (upload data)" msgstr "" #: src/hostlist/hostlist-server.c:296 msgid "Could not handle hostlist request since I do not have a response yet\n" msgstr "" #: src/hostlist/hostlist-server.c:299 msgid "hostlist requests refused (not ready)" msgstr "" #: src/hostlist/hostlist-server.c:303 msgid "Received request for our hostlist\n" msgstr "" #: src/hostlist/hostlist-server.c:304 msgid "hostlist requests processed" msgstr "" #: src/hostlist/hostlist-server.c:346 msgid "# hostlist advertisements send" msgstr "" #: src/hostlist/hostlist-server.c:390 msgid "Advertisement message could not be queued by core\n" msgstr "" #: src/hostlist/hostlist-server.c:557 src/peerinfo-tool/gnunet-peerinfo.c:639 #: src/transport/gnunet-service-transport.c:1114 #, fuzzy msgid "Could not access PEERINFO service. Exiting.\n" msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #: src/hostlist/hostlist-server.c:576 #, c-format msgid "Hostlist service starts on %s:%llu\n" msgstr "" #: src/hostlist/hostlist-server.c:590 #, fuzzy, c-format msgid "Address to obtain hostlist: `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/hostlist/hostlist-server.c:630 #, fuzzy, c-format msgid "`%s' is not a valid IP address! Ignoring BINDTOIP.\n" msgstr "\"%s\" är inte tillgänglig." #: src/hostlist/hostlist-server.c:673 #, c-format msgid "Could not start hostlist HTTP server on port %u\n" msgstr "" #: src/identity/gnunet-identity.c:165 #, fuzzy, c-format msgid "Failed to create ego: %s\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/identity/gnunet-identity.c:184 #, fuzzy, c-format msgid "Failed to set default ego: %s\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/identity/gnunet-identity.c:327 msgid "create ego NAME" msgstr "" #: src/identity/gnunet-identity.c:330 msgid "delete ego NAME " msgstr "" #: src/identity/gnunet-identity.c:333 msgid "display all egos" msgstr "" #: src/identity/gnunet-identity.c:336 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)" msgstr "" #: src/identity/gnunet-identity.c:339 msgid "run in monitor mode egos" msgstr "" #: src/identity/gnunet-identity.c:342 msgid "" "set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)" msgstr "" #: src/identity/gnunet-identity.c:351 msgid "Maintain egos" msgstr "" #: src/identity/gnunet-service-identity.c:338 msgid "no default known" msgstr "" #: src/identity/gnunet-service-identity.c:362 msgid "default configured, but ego unknown (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:439 #: src/identity/gnunet-service-identity.c:670 #: src/identity/gnunet-service-identity.c:778 #, fuzzy, c-format msgid "Failed to write subsystem default identifier map to `%s'.\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/identity/gnunet-service-identity.c:446 msgid "Unknown ego specified for service (internal error)" msgstr "" #: src/identity/gnunet-service-identity.c:516 msgid "identifier already in use for another ego" msgstr "" #: src/identity/gnunet-service-identity.c:647 msgid "target name already exists" msgstr "" #: src/identity/gnunet-service-identity.c:686 #: src/identity/gnunet-service-identity.c:795 msgid "no matching ego found" msgstr "" #: src/identity/gnunet-service-identity.c:829 #, fuzzy, c-format msgid "Failed to parse ego information in `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/identity/gnunet-service-identity.c:902 #, fuzzy, c-format msgid "Failed to parse subsystem identity configuration file `%s'\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/identity/gnunet-service-identity.c:914 #, fuzzy, c-format msgid "Failed to create directory `%s' for storing egos\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/mesh/gnunet-mesh.c:357 #, fuzzy, c-format msgid "Invalid target `%s'\n" msgstr "Ogiltigt argument: \"%s\"\n" #: src/mesh/gnunet-mesh.c:607 #, fuzzy, c-format msgid "Invalid peer ID `%s'\n" msgstr "Ogiltiga argument: " #: src/mesh/gnunet-mesh.c:650 #, fuzzy, c-format msgid "Invalid tunnel owner `%s'\n" msgstr "Ogiltigt format för IP: \"%s\"\n" #: src/mesh/gnunet-mesh.c:716 msgid "You must NOT give a TARGETwhen using 'request all' options\n" msgstr "" #: src/mesh/gnunet-mesh.c:807 #, fuzzy msgid "provide information about a particular connection" msgstr "Skriv ut information om GNUnets motparter." #: src/mesh/gnunet-mesh.c:810 msgid "activate echo mode" msgstr "" #: src/mesh/gnunet-mesh.c:816 msgid "port to listen to (default; 0)" msgstr "" #: src/mesh/gnunet-mesh.c:819 src/mesh/gnunet-mesh.c:822 #, fuzzy msgid "provide information about all peers" msgstr "Skriv ut information om GNUnets motparter." #: src/mesh/gnunet-mesh.c:825 #, fuzzy msgid "provide information about a particular tunnel" msgstr "Skriv ut information om GNUnets motparter." #: src/mesh/gnunet-mesh.c:828 #, fuzzy msgid "provide information about all tunnels" msgstr "Skriv ut information om GNUnets motparter." #: src/mesh/gnunet-service-mesh_peer.c:390 msgid "Wrong CORE service\n" msgstr "" #: src/mysql/mysql.c:174 #, c-format msgid "Trying to use file `%s' for MySQL configuration.\n" msgstr "Försöker använda fil \"%s\" för MySQL-konfiguration.\n" #: src/mysql/mysql.c:181 #, fuzzy, c-format msgid "Could not access file `%s': %s\n" msgstr "Kunde inte köra \"%s\": %s\n" #: src/namecache/gnunet-namecache.c:109 #, fuzzy, c-format msgid "No records found for `%s'" msgstr "%d filer hittades i katalog.\n" #: src/namecache/gnunet-namecache.c:124 src/namestore/gnunet-namestore.c:397 #, c-format msgid "\tCorrupt or unsupported record of type %u\n" msgstr "" #: src/namecache/gnunet-namecache.c:185 #, fuzzy, c-format msgid "You must specify which zone should be accessed\n" msgstr "anger vilken TRANSPORT som ska testas" #: src/namecache/gnunet-namecache.c:195 src/namestore/gnunet-namestore.c:695 #, fuzzy, c-format msgid "Invalid public key for reverse lookup `%s'\n" msgstr "Ogiltigt argument: \"%s\"\n" #: src/namecache/gnunet-namecache.c:203 #, fuzzy, c-format msgid "You must specify a name\n" msgstr "Du mÃ¥ste ange en mottagare!\n" #: src/namecache/gnunet-namecache.c:234 src/namestore/gnunet-namestore.c:931 msgid "name of the record to add/delete/display" msgstr "" #: src/namecache/gnunet-namecache.c:237 #, fuzzy msgid "spezifies the public key of the zone to look in" msgstr "ange prioritet för innehÃ¥llet" #: src/namecache/gnunet-namecache.c:248 src/namestore/gnunet-namestore.c:963 #, fuzzy msgid "GNUnet zone manipulation tool" msgstr "GNUnet-konfiguration" #: src/namecache/namecache_api.c:276 msgid "Namecache failed to cache block" msgstr "" #: src/namecache/plugin_namecache_postgres.c:89 #: src/namestore/plugin_namestore_postgres.c:96 #, fuzzy msgid "Failed to create indices\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/namestore/gnunet-namestore.c:303 #, fuzzy, c-format msgid "Adding record failed: %s\n" msgstr "" "\n" "Fel vid uppladdning av fil: %s\n" #: src/namestore/gnunet-namestore.c:332 #, fuzzy, c-format msgid "Deleting record failed, record does not exist%s%s\n" msgstr "" "\n" "Fel vid uppladdning av fil: %s\n" #: src/namestore/gnunet-namestore.c:339 #, fuzzy, c-format msgid "Deleting record failed%s%s\n" msgstr "" "\n" "Fel vid uppladdning av fil: %s\n" #: src/namestore/gnunet-namestore.c:558 #, c-format msgid "No options given\n" msgstr "" #: src/namestore/gnunet-namestore.c:569 #: src/namestore/gnunet-namestore-fcfsd.c:970 #, fuzzy msgid "Failed to connect to namestore\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/namestore/gnunet-namestore.c:577 src/namestore/gnunet-namestore.c:586 #: src/namestore/gnunet-namestore.c:603 src/namestore/gnunet-namestore.c:625 #: src/namestore/gnunet-namestore.c:665 #, fuzzy, c-format msgid "Missing option `%s' for operation `%s'\n" msgstr "Konfigurationsfil \"%s\" skapad.\n" #: src/namestore/gnunet-namestore.c:578 src/namestore/gnunet-namestore.c:587 #: src/namestore/gnunet-namestore.c:604 src/namestore/gnunet-namestore.c:626 msgid "add" msgstr "" #: src/namestore/gnunet-namestore.c:595 #, fuzzy, c-format msgid "Unsupported type `%s'\n" msgstr "Kommando \"%s\" stöds ej. Avbryter.\n" #: src/namestore/gnunet-namestore.c:615 #, fuzzy, c-format msgid "Value `%s' invalid for record type `%s'\n" msgstr "%s: symbolvärde \"%s\" ogiltigt för %s\n" #: src/namestore/gnunet-namestore.c:651 #, fuzzy, c-format msgid "Invalid time format `%s'\n" msgstr "Ogiltigt format för IP: \"%s\"\n" #: src/namestore/gnunet-namestore.c:666 msgid "del" msgstr "" #: src/namestore/gnunet-namestore.c:715 #: src/peerinfo-tool/gnunet-peerinfo.c:723 #, fuzzy, c-format msgid "Invalid URI `%s'\n" msgstr "Ogiltiga argument: " #: src/namestore/gnunet-namestore.c:750 #, fuzzy, c-format msgid "Invalid nick `%s'\n" msgstr "Ogiltiga argument: " #: src/namestore/gnunet-namestore.c:790 #, fuzzy, c-format msgid "Ego `%s' not known to identity service\n" msgstr "\"%s\": okänd tjänst: %s\n" #: src/namestore/gnunet-namestore.c:817 #, fuzzy, c-format msgid "No default ego configured in identity service\n" msgstr "\"%s\": okänd tjänst: %s\n" #: src/namestore/gnunet-namestore.c:853 #, fuzzy, c-format msgid "Identity service is not running\n" msgstr "\"%s\" är inte en fil.\n" #: src/namestore/gnunet-namestore.c:865 #, fuzzy, c-format msgid "Cannot connect to identity service\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/namestore/gnunet-namestore.c:913 msgid "add record" msgstr "" #: src/namestore/gnunet-namestore.c:916 msgid "delete record" msgstr "" #: src/namestore/gnunet-namestore.c:919 msgid "display records" msgstr "" #: src/namestore/gnunet-namestore.c:922 msgid "" "expiration time for record to use (for adding only), \"never\" is possible" msgstr "" #: src/namestore/gnunet-namestore.c:925 #, fuzzy msgid "set the desired nick name for the zone" msgstr "Skriv ut information om GNUnets motparter." #: src/namestore/gnunet-namestore.c:928 #, fuzzy msgid "monitor changes in the namestore" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/namestore/gnunet-namestore.c:934 #, fuzzy msgid "determine our name for the given PKEY" msgstr "Skriv ut information om GNUnets motparter." #: src/namestore/gnunet-namestore.c:937 msgid "type of the record to add/delete/display" msgstr "" #: src/namestore/gnunet-namestore.c:940 msgid "URI to import into our zone" msgstr "" #: src/namestore/gnunet-namestore.c:943 msgid "value of the record to add/delete" msgstr "" #: src/namestore/gnunet-namestore.c:946 msgid "create or list public record" msgstr "" #: src/namestore/gnunet-namestore.c:949 msgid "" "create shadow record (only valid if all other records of the same type have " "expired" msgstr "" #: src/namestore/gnunet-namestore.c:952 #, fuzzy msgid "name of the ego controlling the zone" msgstr "Visa värde av alternativet" #: src/namestore/gnunet-namestore-fcfsd.c:464 #, fuzzy, c-format msgid "Unsupported form value `%s'\n" msgstr "Kommando \"%s\" stöds ej. Avbryter.\n" #: src/namestore/gnunet-namestore-fcfsd.c:491 #, fuzzy, c-format msgid "Failed to create record for domain `%s': %s\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/namestore/gnunet-namestore-fcfsd.c:525 #, c-format msgid "Found existing name `%s' for the given key\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:534 msgid "Error when mapping zone to name\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:596 #, c-format msgid "Found %u existing records for domain `%s'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:652 #, fuzzy, c-format msgid "Failed to create page for `%s'\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/namestore/gnunet-namestore-fcfsd.c:668 #, fuzzy, c-format msgid "Failed to setup post processor for `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/namestore/gnunet-namestore-fcfsd.c:704 msgid "Domain name must not contain `.'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:712 msgid "Domain name must not contain `+'\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:910 msgid "No ego configured for `fcfsd` subsystem\n" msgstr "" #: src/namestore/gnunet-namestore-fcfsd.c:936 #, fuzzy msgid "Failed to start HTTP server\n" msgstr "Misslyckades att starta samling.\n" #: src/namestore/gnunet-namestore-fcfsd.c:978 #, fuzzy msgid "Failed to connect to identity\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/namestore/gnunet-namestore-fcfsd.c:1011 msgid "GNU Name System First Come First Serve name registration service" msgstr "" #: src/namestore/gnunet-service-namestore.c:655 #, fuzzy, c-format msgid "Failed to replicate block in namecache: %s\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/namestore/namestore_api.c:275 msgid "Namestore failed to store record\n" msgstr "" #: src/nat/gnunet-nat-server.c:279 #, c-format msgid "Please pass valid port number as the first argument! (got `%s')\n" msgstr "" #: src/nat/gnunet-nat-server.c:321 msgid "GNUnet NAT traversal test helper daemon" msgstr "" #: src/nat/nat_auto.c:170 msgid "NAT traversal with ICMP Server timed out.\n" msgstr "" #: src/nat/nat_auto.c:203 msgid "NAT traversal with ICMP Server succeeded.\n" msgstr "" #: src/nat/nat_auto.c:204 msgid "NAT traversal with ICMP Server failed.\n" msgstr "" #: src/nat/nat_auto.c:225 #, fuzzy msgid "Testing connection reversal with ICMP server.\n" msgstr "Skriv ut information om GNUnets motparter." #: src/nat/nat_auto.c:274 #, fuzzy, c-format msgid "Detected external IP `%s'\n" msgstr "Mottog ogiltig RPC \"%s\".\n" #: src/nat/nat_auto.c:344 msgid "This system has a global IPv6 address, setting IPv6 to supported.\n" msgstr "" #: src/nat/nat_auto.c:360 #, c-format msgid "Detected internal network address `%s'.\n" msgstr "" #: src/nat/nat_auto.c:413 msgid "upnpc found, enabling its use\n" msgstr "" #: src/nat/nat_auto.c:414 #, fuzzy msgid "upnpc not found\n" msgstr "Kommando \"%s\" hittades inte!\n" #: src/nat/nat_auto.c:447 msgid "gnunet-helper-nat-server found, testing it\n" msgstr "" #: src/nat/nat_auto.c:448 msgid "No working gnunet-helper-nat-server found\n" msgstr "" #: src/nat/nat_auto.c:482 msgid "gnunet-helper-nat-client found, enabling it\n" msgstr "" #: src/nat/nat_auto.c:483 msgid "gnunet-helper-nat-client not found or behind NAT, disabling it\n" msgstr "" #: src/nat/nat.c:867 #, c-format msgid "gnunet-helper-nat-server generated malformed address `%s'\n" msgstr "" #: src/nat/nat.c:917 #, fuzzy, c-format msgid "Failed to start %s\n" msgstr "Misslyckades att starta samling.\n" #: src/nat/nat.c:1205 msgid "malformed" msgstr "" #: src/nat/nat.c:1276 src/nat/nat.c:1288 #, c-format msgid "" "Configuration requires `%s', but binary is not installed properly (SUID bit " "not set). Option disabled.\n" msgstr "" #: src/nat/nat.c:1426 msgid "Internal IP address not known, cannot use ICMP NAT traversal method\n" msgstr "" #: src/nat/nat.c:1442 #, c-format msgid "Running gnunet-helper-nat-client %s %s %u\n" msgstr "" #: src/nat/nat_mini.c:155 msgid "no valid address was returned by `external-ip'" msgstr "" #: src/nat/nat_mini.c:175 msgid "`external-ip' command not found" msgstr "" #: src/nat/nat_mini.c:201 msgid "`external-ip' command not found\n" msgstr "" #: src/nat/nat_mini.c:366 #, fuzzy msgid "Failed to run `upnpc` command" msgstr "Misslyckades att starta samling.\n" #: src/nat/nat_mini.c:512 msgid "`upnpc' command took too long, process killed" msgstr "" #: src/nat/nat_mini.c:540 msgid "`upnpc' command failed to establish port mapping" msgstr "" #: src/nat/nat_mini.c:604 msgid "`upnpc' command not found\n" msgstr "" #: src/nat/nat_mini.c:608 #, fuzzy msgid "`upnpc` command not found" msgstr "Kommando \"%s\" hittades inte!\n" #: src/nat/nat_test.c:351 #, fuzzy msgid "Failed to connect to `gnunet-nat-server'\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/nat/nat_test.c:423 #, c-format msgid "Failed to create listen socket bound to `%s' for NAT test: %s\n" msgstr "" #: src/nse/gnunet-nse.c:117 #, fuzzy msgid "NSE service is not running\n" msgstr "\"%s\" är inte en fil.\n" #: src/nse/gnunet-nse.c:122 msgid "Error while checking if NSE service is running or not\n" msgstr "" #: src/nse/gnunet-nse.c:168 #, fuzzy msgid "Show network size estimates from NSE service." msgstr "# byte mottogs via TCP" #: src/nse/gnunet-nse-profiler.c:858 #, fuzzy msgid "limit to the number of connections to NSE services, 0 for none" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/nse/gnunet-nse-profiler.c:861 msgid "name of the file for writing connection information and statistics" msgstr "" #: src/nse/gnunet-nse-profiler.c:864 src/testbed/gnunet-testbed-profiler.c:306 msgid "name of the file with the login information for the testbed" msgstr "" #: src/nse/gnunet-nse-profiler.c:867 msgid "name of the file for writing the main results" msgstr "" #: src/nse/gnunet-nse-profiler.c:870 msgid "Number of peers to run in each round, separated by commas" msgstr "" #: src/nse/gnunet-nse-profiler.c:876 msgid "delay between rounds" msgstr "" #: src/nse/gnunet-nse-profiler.c:885 #, fuzzy msgid "Measure quality and performance of the NSE service." msgstr "Kan inte tillgÃ¥ tjänsten" #: src/nse/gnunet-service-nse.c:1517 #: src/revocation/gnunet-service-revocation.c:789 src/util/gnunet-scrypt.c:248 msgid "Value is too large.\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:215 #, fuzzy, c-format msgid "Removing expired address of transport `%s'\n" msgstr "Tillgängliga transport(er): %s\n" #: src/peerinfo/gnunet-service-peerinfo.c:352 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s': %s\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/peerinfo/gnunet-service-peerinfo.c:371 #: src/peerinfo/gnunet-service-peerinfo.c:388 #, fuzzy, c-format msgid "Failed to parse HELLO in file `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/peerinfo/gnunet-service-peerinfo.c:466 msgid "# peers known" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:503 #, c-format msgid "" "File `%s' in directory `%s' does not match naming convention. Removed.\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:653 #, fuzzy, c-format msgid "Scanning directory `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/peerinfo/gnunet-service-peerinfo.c:658 #, c-format msgid "Still no peers found in `%s'!\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:994 #, fuzzy, c-format msgid "Cleaning up directory `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/peerinfo/gnunet-service-peerinfo.c:1287 #, c-format msgid "Importing HELLOs from `%s'\n" msgstr "" #: src/peerinfo/gnunet-service-peerinfo.c:1298 msgid "Skipping import of included HELLOs\n" msgstr "" #: src/peerinfo/peerinfo_api.c:236 msgid "aborted due to explicit disconnect request" msgstr "" #: src/peerinfo/peerinfo_api.c:356 #, fuzzy msgid "failed to transmit request (service down?)" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/peerinfo/peerinfo_api.c:506 #, fuzzy msgid "Failed to receive response from `PEERINFO' service." msgstr "Misslyckades att ta emot svar till \"%s\" meddelande frÃ¥n gnunetd\n" #: src/peerinfo/peerinfo_api.c:547 src/peerinfo/peerinfo_api.c:566 #: src/peerinfo/peerinfo_api.c:581 src/peerinfo/peerinfo_api.c:592 #: src/peerinfo/peerinfo_api.c:603 #, fuzzy msgid "Received invalid message from `PEERINFO' service." msgstr "mottog ogiltigt \"%s\" meddelande: %s.\n" #: src/peerinfo/peerinfo_api.c:678 #, fuzzy msgid "Timeout transmitting iteration request to `PEERINFO' service." msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/peerinfo/peerinfo_api_notify.c:268 #, fuzzy, c-format msgid "Could not connect to `%s' service.\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:232 #, fuzzy, c-format msgid "%sPeer `%s'\n" msgstr "Jag är ändpunkt \"%s\".\n" #: src/peerinfo-tool/gnunet-peerinfo.c:239 #, c-format msgid "\tExpires: %s \t %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:428 #, fuzzy, c-format msgid "Failure: Did not receive %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:436 #, c-format msgid "Failure: Received invalid %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:445 #, fuzzy, c-format msgid "Failed to write HELLO with %u bytes to file `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/peerinfo-tool/gnunet-peerinfo.c:458 #, c-format msgid "Wrote %s HELLO containing %u addresses with %u bytes to file `%s'\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:522 #, c-format msgid "Failure adding HELLO: %s\n" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:633 #, fuzzy, c-format msgid "Service `%s' is not running, please start GNUnet\n" msgstr "\"%s\" är inte en fil.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:654 src/util/gnunet-scrypt.c:224 #, fuzzy, c-format msgid "Loading hostkey from `%s' failed.\n" msgstr "Tolkning av HTTP-svar för URL \"%s\" misslyckades.\n" #: src/peerinfo-tool/gnunet-peerinfo.c:745 #, c-format msgid "I am peer `%s'.\n" msgstr "Jag är ändpunkt \"%s\".\n" #: src/peerinfo-tool/gnunet-peerinfo.c:789 msgid "don't resolve host names" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:792 msgid "output only the identity strings" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:795 msgid "include friend-only information" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:798 msgid "output our own identity only" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:801 msgid "list all known peers" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:804 msgid "dump hello to file" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:807 msgid "also output HELLO uri(s)" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:810 msgid "add given HELLO uri to the database" msgstr "" #: src/peerinfo-tool/gnunet-peerinfo.c:821 #, fuzzy msgid "Print information about peers." msgstr "Skriv ut information om GNUnets motparter." #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:105 #: src/transport/gnunet-service-transport_plugins.c:128 #, fuzzy, c-format msgid "Starting transport plugins `%s'\n" msgstr "Testar transport(er) %s\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:109 #: src/transport/gnunet-service-transport_plugins.c:133 #, fuzzy, c-format msgid "Loading `%s' transport plugin\n" msgstr "Testar transport(er) %s\n" #: src/peerinfo-tool/gnunet-peerinfo_plugins.c:129 #: src/transport/gnunet-service-transport_plugins.c:165 #, fuzzy, c-format msgid "Failed to load transport plugin for `%s'\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/postgres/postgres.c:59 #, fuzzy, c-format msgid "`%s:%s' failed at %s:%d with error: %s" msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #: src/postgres/postgres.c:148 #, fuzzy, c-format msgid "Unable to initialize Postgres: %s" msgstr "Kunde inte initiera SQLite.\n" #: src/psycstore/gnunet-service-psycstore.c:200 #, fuzzy msgid "Failed to store membership information!\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/psycstore/gnunet-service-psycstore.c:224 #, fuzzy msgid "Failed to test membership!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/psycstore/gnunet-service-psycstore.c:246 #, fuzzy msgid "Failed to store fragment!\n" msgstr "Misslyckades att starta samling.\n" #: src/psycstore/gnunet-service-psycstore.c:272 #, fuzzy msgid "Failed to get fragment!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/psycstore/gnunet-service-psycstore.c:299 #, fuzzy msgid "Failed to get message!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/psycstore/gnunet-service-psycstore.c:328 #, fuzzy msgid "Failed to get message fragment!\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/psycstore/gnunet-service-psycstore.c:356 #, fuzzy msgid "Failed to get master counters!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/psycstore/gnunet-service-psycstore.c:392 #: src/psycstore/gnunet-service-psycstore.c:465 msgid "Tried to set invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:408 #, fuzzy msgid "Failed to begin modifying state!\n" msgstr "Misslyckades att starta samling.\n" #: src/psycstore/gnunet-service-psycstore.c:431 #, fuzzy, c-format msgid "Unknown operator: %c\n" msgstr "Okänd operation \"%s\"\n" #: src/psycstore/gnunet-service-psycstore.c:441 #, fuzzy msgid "Failed to end modifying state!\n" msgstr "Misslyckades att starta samling.\n" #: src/psycstore/gnunet-service-psycstore.c:479 #, fuzzy msgid "Failed to begin synchronizing state!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/psycstore/gnunet-service-psycstore.c:495 #, fuzzy msgid "Failed to end synchronizing state!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/psycstore/gnunet-service-psycstore.c:515 #: src/psycstore/gnunet-service-psycstore.c:534 #, fuzzy msgid "Failed to reset state!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/psycstore/gnunet-service-psycstore.c:557 #: src/psycstore/gnunet-service-psycstore.c:608 msgid "Tried to get invalid state variable name!\n" msgstr "" #: src/psycstore/gnunet-service-psycstore.c:584 #: src/psycstore/gnunet-service-psycstore.c:623 #, fuzzy msgid "Failed to get state variable!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/psycstore/plugin_psycstore_sqlite.c:60 #, fuzzy, c-format msgid "`%s' failed at %s:%d with error: %s (%d)\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #: src/psycstore/plugin_psycstore_sqlite.c:253 #, fuzzy, c-format msgid "" "Error preparing SQL query: %s\n" " %s\n" msgstr "Fel vid skapandet av användare" #: src/psycstore/plugin_psycstore_sqlite.c:276 #, fuzzy, c-format msgid "" "Error executing SQL query: %s\n" " %s\n" msgstr "Fel vid skapandet av användare" #: src/psycstore/plugin_psycstore_sqlite.c:1796 msgid "SQLite database running\n" msgstr "" #: src/pt/gnunet-daemon-pt.c:482 #, fuzzy msgid "Failed to pack DNS request. Dropping.\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/pt/gnunet-daemon-pt.c:488 #, fuzzy msgid "# DNS requests mapped to VPN" msgstr "# byte mottogs via TCP" #: src/pt/gnunet-daemon-pt.c:541 msgid "# DNS records modified" msgstr "" #: src/pt/gnunet-daemon-pt.c:717 msgid "# DNS replies intercepted" msgstr "" #: src/pt/gnunet-daemon-pt.c:723 #, fuzzy msgid "Failed to parse DNS request. Dropping.\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/pt/gnunet-daemon-pt.c:826 #, fuzzy msgid "# DNS requests dropped (timeout)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/pt/gnunet-daemon-pt.c:883 #, fuzzy msgid "# DNS requests intercepted" msgstr "# byte mottogs via TCP" #: src/pt/gnunet-daemon-pt.c:888 #, fuzzy msgid "# DNS requests dropped (DNS mesh channel down)" msgstr "# byte mottogs via TCP" #: src/pt/gnunet-daemon-pt.c:896 #, fuzzy msgid "# DNS requests dropped (malformed)" msgstr "# byte mottogs via TCP" #: src/pt/gnunet-daemon-pt.c:969 #, fuzzy msgid "# DNS replies received" msgstr "# byte mottogs via TCP" #: src/pt/gnunet-daemon-pt.c:985 #, fuzzy msgid "# DNS replies dropped (too late?)" msgstr "# byte mottagna av typen %d" #: src/pt/gnunet-daemon-pt.c:1261 src/pt/gnunet-daemon-pt.c:1270 #: src/pt/gnunet-daemon-pt.c:1290 src/pt/gnunet-daemon-pt.c:1301 #: src/pt/gnunet-daemon-pt.c:1310 #, fuzzy, c-format msgid "Failed to connect to %s service. Exiting.\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/pt/gnunet-daemon-pt.c:1347 msgid "Daemon to run to perform IP protocol translation to GNUnet" msgstr "" #: src/regex/gnunet-daemon-regexprofiler.c:270 #: src/regex/gnunet-regex-simulation-profiler.c:659 #, fuzzy, c-format msgid "%s service is lacking key configuration settings (%s). Exiting.\n" msgstr "GNUnet-konfiguration" #: src/regex/gnunet-daemon-regexprofiler.c:380 msgid "Daemon to announce regular expressions for the peer using mesh." msgstr "" #: src/regex/gnunet-regex-profiler.c:1288 #, fuzzy msgid "No configuration file given. Exiting\n" msgstr "använd konfigurationsfil FILNAMN" #: src/regex/gnunet-regex-profiler.c:1299 #, fuzzy msgid "Configuration option \"regex_prefix\" missing. Exiting\n" msgstr "Konfigurationsfil \"%s\" skapad.\n" #: src/regex/gnunet-regex-profiler.c:1328 #: src/regex/gnunet-regex-simulation-profiler.c:622 #, c-format msgid "No policy directory specified on command line. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1334 #: src/regex/gnunet-regex-simulation-profiler.c:629 #, c-format msgid "Specified policies directory does not exist. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1341 #, fuzzy, c-format msgid "No files found in `%s'\n" msgstr "%d filer hittades i katalog.\n" #: src/regex/gnunet-regex-profiler.c:1350 msgid "No search strings file given. Exiting.\n" msgstr "" #: src/regex/gnunet-regex-profiler.c:1370 #, fuzzy msgid "Error loading search strings. Exiting.\n" msgstr "Fel vid lämning av DHT.\n" #: src/regex/gnunet-regex-profiler.c:1455 #, fuzzy msgid "name of the file for writing statistics" msgstr "Visa värde av alternativet" #: src/regex/gnunet-regex-profiler.c:1458 msgid "wait TIMEOUT before ending the experiment" msgstr "" #: src/regex/gnunet-regex-profiler.c:1461 msgid "directory with policy files" msgstr "" #: src/regex/gnunet-regex-profiler.c:1464 #, fuzzy msgid "name of file with input strings" msgstr "Visa värde av alternativet" #: src/regex/gnunet-regex-profiler.c:1467 #, fuzzy msgid "name of file with hosts' names" msgstr "Visa värde av alternativet" #: src/regex/gnunet-regex-profiler.c:1479 msgid "Profiler for regex" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:689 #, fuzzy msgid "name of the table to write DFAs" msgstr "Visa värde av alternativet" #: src/regex/gnunet-regex-simulation-profiler.c:692 msgid "maximum path compression length" msgstr "" #: src/regex/gnunet-regex-simulation-profiler.c:705 msgid "Profiler for regex library" msgstr "" #: src/regex/regex_api.c:131 #, fuzzy, c-format msgid "Regex `%s' is too long!\n" msgstr "\"%s\" är inte en fil.\n" #: src/revocation/gnunet-revocation.c:126 #, fuzzy, c-format msgid "Key `%s' is valid\n" msgstr "Formatet pÃ¥ pseudonym \"%s\" är ogiltig.\n" #: src/revocation/gnunet-revocation.c:131 #, fuzzy, c-format msgid "Key `%s' has been revoked\n" msgstr "Tjänst borttagen.\n" #: src/revocation/gnunet-revocation.c:137 #, fuzzy msgid "Internal error\n" msgstr "Okänt fel.\n" #: src/revocation/gnunet-revocation.c:163 #, c-format msgid "Key for ego `%s' is still valid, revocation failed (!)\n" msgstr "" #: src/revocation/gnunet-revocation.c:168 #, fuzzy msgid "Revocation failed (!)\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/revocation/gnunet-revocation.c:173 #, c-format msgid "Key for ego `%s' has been successfully revoked\n" msgstr "" #: src/revocation/gnunet-revocation.c:178 msgid "Revocation successful.\n" msgstr "" #: src/revocation/gnunet-revocation.c:183 msgid "Internal error, key revocation might have failed\n" msgstr "" #: src/revocation/gnunet-revocation.c:294 #, c-format msgid "Revocation certificate for `%s' stored in `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:324 #, fuzzy, c-format msgid "Ego `%s' not found.\n" msgstr "\"%s\" misslyckades: tabell hittades inte!\n" #: src/revocation/gnunet-revocation.c:345 #, c-format msgid "Error: revocation certificate in `%s' is not for `%s'\n" msgstr "" #: src/revocation/gnunet-revocation.c:365 msgid "Revocation certificate ready\n" msgstr "" #: src/revocation/gnunet-revocation.c:375 msgid "Revocation certificate not ready, calculating proof of work\n" msgstr "" #: src/revocation/gnunet-revocation.c:407 #, fuzzy, c-format msgid "Public key `%s' malformed\n" msgstr "Ogiltigt argument: \"%s\"\n" #: src/revocation/gnunet-revocation.c:421 msgid "" "Testing and revoking at the same time is not allowed, only executing test.\n" msgstr "" #: src/revocation/gnunet-revocation.c:441 #, fuzzy msgid "No filename to store revocation certificate given.\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/revocation/gnunet-revocation.c:463 #, fuzzy, c-format msgid "Failed to read revocation certificate from `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/revocation/gnunet-revocation.c:488 #, fuzzy msgid "No action specified. Nothing to do.\n" msgstr "Inget tabellnamn angivet, använder \"%s\".\n" #: src/revocation/gnunet-revocation.c:504 msgid "use NAME for the name of the revocation file" msgstr "" #: src/revocation/gnunet-revocation.c:507 msgid "" "revoke the private key associated for the the private key associated with " "the ego NAME " msgstr "" #: src/revocation/gnunet-revocation.c:510 msgid "actually perform revocation, otherwise we just do the precomputation" msgstr "" #: src/revocation/gnunet-revocation.c:513 msgid "test if the public key KEY has been revoked" msgstr "" #: src/revocation/gnunet-service-revocation.c:272 msgid "Duplicate revocation received from peer. Ignored.\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:434 #, c-format msgid "Error computing revocation set union with %s\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:486 msgid "SET service crashed, terminating revocation service\n" msgstr "" #: src/revocation/gnunet-service-revocation.c:812 #, fuzzy msgid "Could not open revocation database file!" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/scalarproduct/gnunet-scalarproduct.c:225 #, fuzzy msgid "You must specify at least one message ID to check!\n" msgstr "Du mÃ¥ste ange en lista av filer att lägga in.\n" #: src/scalarproduct/gnunet-scalarproduct.c:232 msgid "This program needs a session identifier for comparing vectors.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:239 msgid "Please give a session key for --input_key!\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:251 #, c-format msgid "" "Tried to set initiator mode, as peer ID was given. However, `%s' is not a " "valid peer identifier.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:278 #: src/scalarproduct/gnunet-scalarproduct.c:314 #, fuzzy, c-format msgid "Could not convert `%s' to int32_t.\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/scalarproduct/gnunet-scalarproduct.c:286 msgid "Need elements to compute the vectorproduct, got none.\n" msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:346 #, fuzzy, c-format msgid "Could not convert `%s' to integer.\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/scalarproduct/gnunet-scalarproduct.c:407 msgid "" "A comma separated list of elements to compare as vector with our remote peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:410 msgid "" "A comma separated mask to select which elements should actually be compared." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:413 msgid "" "[Optional] peer to calculate our scalarproduct with. If this parameter is " "not given, the service will wait for a remote peer to compute the request." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:416 msgid "Transaction ID shared with peer." msgstr "" #: src/scalarproduct/gnunet-scalarproduct.c:425 msgid "Calculate the Vectorproduct with a GNUnet peer." msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:541 #, fuzzy, c-format msgid "Client (%p) disconnected from us.\n" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:613 #: src/scalarproduct/gnunet-service-scalarproduct.c:702 #, fuzzy, c-format msgid "Could not send message to client (%p)!\n" msgstr "Kunde inte skicka begäran till gnunetd.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:619 #, c-format msgid "Sending session-end notification to client (%p) for session %s\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:712 #, c-format msgid "Sent result to client (%p), this session (%s) has ended!\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:766 #: src/scalarproduct/gnunet-service-scalarproduct.c:855 msgid "Could not send service-response message via mesh!)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1028 #, c-format msgid "Failed to communicate with `%s', scalar product calculation aborted.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1099 #: src/scalarproduct/gnunet-service-scalarproduct.c:1208 #, fuzzy msgid "Transmitting service request.\n" msgstr "Startade samling \"%s\".\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1108 #, fuzzy msgid "Could not send service-request multipart message to channel!\n" msgstr "Kunde inte skicka begäran till gnunetd.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1147 #, fuzzy, c-format msgid "Successfully created new channel to peer (%s)!\n" msgstr "Ã…tkomst nekad för \"%s\" vid %s:%d.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1217 #, fuzzy msgid "Could not send message to channel!\n" msgstr "Kunde inte skicka begäran till gnunetd.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1274 #, fuzzy msgid "Too short message received from client!\n" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1287 #, fuzzy msgid "Invalid message received from client, session information incorrect!\n" msgstr "Ogiltigt meddelande mottogs den %s:%d." #: src/scalarproduct/gnunet-service-scalarproduct.c:1298 #, c-format msgid "" "Duplicate session information received, cannot create new session with key `" "%s'\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1318 #, c-format msgid "" "Got client-request-session with key %s, preparing channel to remote " "service.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1354 #, c-format msgid "Creating new channel for session with key %s.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1399 #, c-format msgid "" "Got client-responder-session with key %s and a matching service-request-" "session set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1409 #, c-format msgid "" "Got client-responder-session with key %s but NO matching service-request-" "session set, queuing element for later use.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1439 #, fuzzy, c-format msgid "New incoming channel from peer %s.\n" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:1471 #, c-format msgid "Peer disconnected, terminating session %s with peer (%s)\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1672 #: src/scalarproduct/gnunet-service-scalarproduct.c:1814 #, c-format msgid "Got session with key %s and a matching element set, processing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1681 #: src/scalarproduct/gnunet-service-scalarproduct.c:1821 #, c-format msgid "Got session with key %s without a matching element set, queueing.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:1771 #, c-format msgid "" "Got message with duplicate session key (`%s'), ignoring service request.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2014 msgid "Shutting down, initiating cleanup.\n" msgstr "" #: src/scalarproduct/gnunet-service-scalarproduct.c:2100 #, fuzzy msgid "Connect to MESH failed\n" msgstr " Anslutning misslyckades (fel?)\n" #: src/scalarproduct/gnunet-service-scalarproduct.c:2104 #, fuzzy msgid "Mesh initialized\n" msgstr " Anslutning misslyckades\n" #: src/scalarproduct/scalarproduct_api.c:246 #, fuzzy msgid "# SUC responder result messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/scalarproduct/scalarproduct_api.c:300 #, fuzzy msgid "# bytes sent to scalarproduct" msgstr "# byte krypterade" #: src/scalarproduct/scalarproduct_api.c:345 #: src/scalarproduct/scalarproduct_api.c:440 #, fuzzy msgid "Failed to connect to the scalarproduct service\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/scalarproduct/scalarproduct_api.c:353 #: src/scalarproduct/scalarproduct_api.c:448 #, fuzzy msgid "Failed to send a message to the statistics service\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/scalarproduct/scalarproduct_api.c:387 #: src/scalarproduct/scalarproduct_api.c:485 #, fuzzy msgid "Failed to send a message to the scalarproduct service\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/secretsharing/gnunet-secretsharing-profiler.c:538 msgid "dkg start delay" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:541 msgid "dkg timeout" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:544 msgid "threshold" msgstr "" #: src/secretsharing/gnunet-secretsharing-profiler.c:547 msgid "also profile decryption" msgstr "" #: src/set/gnunet-service-set.c:1431 #, fuzzy msgid "Could not connect to mesh service\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/set/gnunet-set-ibf-profiler.c:221 #, fuzzy msgid "number of element in set A-B" msgstr "antal iterationer" #: src/set/gnunet-set-ibf-profiler.c:224 #, fuzzy msgid "number of element in set B-A" msgstr "antal iterationer" #: src/set/gnunet-set-ibf-profiler.c:227 msgid "number of common elements in A and B" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:230 msgid "hash num" msgstr "" #: src/set/gnunet-set-ibf-profiler.c:233 msgid "ibf size" msgstr "" #: src/set/gnunet-set-profiler.c:295 msgid "oeration to execute" msgstr "" #: src/statistics/gnunet-service-statistics.c:280 #, fuzzy, c-format msgid "Loading %llu bytes of statistics from `%s'\n" msgstr "Ladda ner filer frÃ¥n GNUnet." #: src/statistics/gnunet-service-statistics.c:346 #, fuzzy, c-format msgid "Wrote %llu bytes of statistics to `%s'\n" msgstr "Ladda ner filer frÃ¥n GNUnet." #: src/statistics/gnunet-statistics.c:140 #, fuzzy msgid "Failed to obtain statistics.\n" msgstr "Misslyckades att binda till UDP-port %d.\n" #: src/statistics/gnunet-statistics.c:142 #, fuzzy, c-format msgid "Failed to obtain statistics from host `%s:%llu'\n" msgstr "Misslyckades att binda till UDP-port %d.\n" #: src/statistics/gnunet-statistics.c:189 msgid "Missing argument: subsystem \n" msgstr "" #: src/statistics/gnunet-statistics.c:195 msgid "Missing argument: name\n" msgstr "" #: src/statistics/gnunet-statistics.c:226 #, c-format msgid "No subsystem or name given\n" msgstr "" #: src/statistics/gnunet-statistics.c:234 #, fuzzy, c-format msgid "Failed to initialize watch routine\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/statistics/gnunet-statistics.c:261 #, fuzzy, c-format msgid "Trying to connect to remote host, but service `%s' is not running\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/statistics/gnunet-statistics.c:269 #, fuzzy, c-format msgid "A port is required to connect to host `%s'\n" msgstr "Kan inte ansluta till %u.%u.%u.%u:%u: %s\n" #: src/statistics/gnunet-statistics.c:276 #, c-format msgid "A port has to be between 1 and 65535 to connect to host `%s'\n" msgstr "" #: src/statistics/gnunet-statistics.c:308 #, fuzzy, c-format msgid "Invalid argument `%s'\n" msgstr "Ogiltigt argument: \"%s\"\n" #: src/statistics/gnunet-statistics.c:334 msgid "limit output to statistics for the given NAME" msgstr "" #: src/statistics/gnunet-statistics.c:337 msgid "make the value being set persistent" msgstr "" #: src/statistics/gnunet-statistics.c:340 msgid "limit output to the given SUBSYSTEM" msgstr "" #: src/statistics/gnunet-statistics.c:343 msgid "just print the statistics value" msgstr "" #: src/statistics/gnunet-statistics.c:346 msgid "watch value continuously" msgstr "" #: src/statistics/gnunet-statistics.c:349 msgid "connect to remote host" msgstr "" #: src/statistics/gnunet-statistics.c:352 msgid "port for remote host" msgstr "" #: src/statistics/gnunet-statistics.c:364 msgid "Print statistics about GNUnet operations." msgstr "Skriv ut statistik om GNUnet-operationer." #: src/statistics/statistics_api.c:519 #, fuzzy msgid "Could not save some persistent statistics\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/statistics/statistics_api.c:1090 msgid "" "Failed to receive acknowledgement from statistics service, some statistics " "might have been lost!\n" msgstr "" #: src/testbed/generate-underlay-topology.c:223 msgid "Need atleast 2 arguments\n" msgstr "" #: src/testbed/generate-underlay-topology.c:228 msgid "Database filename missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:235 msgid "Topology string missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:240 #, fuzzy, c-format msgid "Invalid topology: %s\n" msgstr "Ogiltigt argument: \"%s\"\n" #: src/testbed/generate-underlay-topology.c:252 #, c-format msgid "An argument is missing for given topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:258 #, fuzzy, c-format msgid "Invalid argument `%s' given as topology argument\n" msgstr "Ogiltigt argument: \"%s\"\n" #: src/testbed/generate-underlay-topology.c:266 #, c-format msgid "Filename argument missing for topology `%s'\n" msgstr "" #: src/testbed/generate-underlay-topology.c:280 #, c-format msgid "Second argument for topology `%s' is missing\n" msgstr "" #: src/testbed/generate-underlay-topology.c:286 #, fuzzy, c-format msgid "Invalid argument `%s'; expecting unsigned int\n" msgstr "Ogiltigt argument: \"%s\"\n" #: src/testbed/generate-underlay-topology.c:335 #: src/testbed/gnunet-testbed-profiler.c:293 msgid "create COUNT number of peers" msgstr "" #: src/testbed/generate-underlay-topology.c:344 msgid "" "Generates SQLite3 database representing a given underlay topology.\n" "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" "The following options are available for TOPO followed by TOPOOPTS if " "applicable:\n" "\t LINE\n" "\t RING\n" "\t RANDOM \n" "\t SMALL_WORLD \n" "\t SMALL_WORLD_RING \n" "\t CLIQUE\n" "\t 2D_TORUS\n" "\t SCALE_FREE \n" "\t FROM_FILE \n" "TOPOOPTS:\n" "\t num_rnd_links: The number of random links\n" "\t cap: the maximum number of links a node can have\n" "\t m: the number of links a node should have while joining the network\n" "\t filename: the path of the file which contains topology information\n" "NOTE: the format of the above file is descibed here: https://www.gnunet.org/" "content/topology-file-format\n" msgstr "" #: src/testbed/gnunet-daemon-latency-logger.c:325 msgid "Daemon to log latency values of connections to neighbours" msgstr "" #: src/testbed/gnunet-daemon-testbed-blacklist.c:264 msgid "" "Daemon to restrict incoming transport layer connections during testbed " "deployments" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:235 src/testing/list-keys.c:50 #: src/testing/testing.c:293 src/util/gnunet-ecc.c:217 #, c-format msgid "Incorrect hostkey file format: %s\n" msgstr "" #: src/testbed/gnunet-daemon-testbed-underlay.c:474 msgid "Daemon to restrict underlay network in testbed deployments" msgstr "" #: src/testbed/gnunet-service-testbed_cpustatus.c:730 #, c-format msgid "" "Cannot open %s for writing load statistics. Not logging load statistics\n" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1015 #, fuzzy msgid "Misconfiguration (can't connect to the ARM service)" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/testbed/gnunet-service-testbed_peers.c:1021 msgid "Request doesn't fit into a message" msgstr "" #: src/testbed/gnunet-service-testbed_peers.c:1059 #, c-format msgid "%s service can't be started because ARM is shutting down" msgstr "" #: src/testbed/gnunet_testbed_mpi_spawn.c:125 #, fuzzy msgid "Waiting for child to exit.\n" msgstr "Väntar pÃ¥ att motparter ska ansluta (%u iterationer kvar)...\n" #: src/testbed/gnunet_testbed_mpi_spawn.c:247 #, fuzzy, c-format msgid "Spawning process `%s'\n" msgstr "Startade samling \"%s\".\n" #: src/testbed/gnunet-testbed-profiler.c:267 #, fuzzy, c-format msgid "Exiting as the number of peers is %u\n" msgstr "Maximalt antal chattklienter uppnÃ¥tt.\n" #: src/testbed/gnunet-testbed-profiler.c:296 msgid "tolerate COUNT number of continious timeout failures" msgstr "" #: src/testbed/gnunet-testbed-profiler.c:299 msgid "" "run profiler in non-interactive mode where upon testbed setup the profiler " "does not wait for a keystroke but continues to run until a termination " "signal is received" msgstr "" #: src/testbed/testbed_api_hosts.c:415 #, fuzzy, c-format msgid "Hosts file %s not found\n" msgstr "\"%s\" misslyckades: tabell hittades inte!\n" #: src/testbed/testbed_api_hosts.c:423 #, c-format msgid "Hosts file %s has no data\n" msgstr "" #: src/testbed/testbed_api_hosts.c:430 #, c-format msgid "Hosts file %s cannot be read\n" msgstr "" #: src/testbed/testbed_api_hosts.c:570 #, c-format msgid "The function %s is only available when compiled with (--with-ll)\n" msgstr "" #: src/testbed/testbed_api_hosts.c:1586 #, fuzzy, c-format msgid "Adding host %u failed with error: %s\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #: src/testbed/testbed_api_testbed.c:819 msgid "Linking controllers failed. Exiting" msgstr "" #: src/testbed/testbed_api_testbed.c:988 #, c-format msgid "Host registration failed for a host. Error: %s\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1054 msgid "Controller crash detected. Shutting down.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1143 #, c-format msgid "Host %s cannot start testbed\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1147 msgid "Testbed cannot be started on localhost\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1185 msgid "Cannot start the master controller" msgstr "" #: src/testbed/testbed_api_testbed.c:1203 msgid "Shutting down testbed due to timeout while setup.\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1263 msgid "No hosts loaded from LoadLeveler. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1275 msgid "No hosts loaded. Need at least one host\n" msgstr "" #: src/testbed/testbed_api_testbed.c:1299 msgid "Specified topology must be supported by testbed" msgstr "" #: src/testbed/testbed_api_testbed.c:1349 #, c-format msgid "" "Maximum number of edges a peer can have in a scale free topology cannot be " "more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_testbed.c:1365 #, c-format msgid "" "The number of edges that can established when adding a new node to scale " "free topology cannot be more than %u. Given `%s = %llu'" msgstr "" #: src/testbed/testbed_api_topology.c:960 #, fuzzy, c-format msgid "Topology file %s not found\n" msgstr "\"%s\" misslyckades: tabell hittades inte!\n" #: src/testbed/testbed_api_topology.c:966 #, c-format msgid "Topology file %s has no data\n" msgstr "" #: src/testbed/testbed_api_topology.c:973 #, c-format msgid "Topology file %s cannot be read\n" msgstr "" #: src/testbed/testbed_api_topology.c:995 #, fuzzy, c-format msgid "Failed to read peer index from toology file: %s" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/testbed/testbed_api_topology.c:1004 #: src/testbed/testbed_api_topology.c:1028 #, c-format msgid "Value in given topology file: %s out of range\n" msgstr "" #: src/testbed/testbed_api_topology.c:1010 #: src/testbed/testbed_api_topology.c:1034 #, fuzzy, c-format msgid "Failed to read peer index from topology file: %s" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/testbed/testbed_api_topology.c:1016 #: src/testbed/testbed_api_topology.c:1040 msgid "Topology file needs more peers than given ones\n" msgstr "" #: src/testbed/testbed_api_topology.c:1074 #, fuzzy, c-format msgid "Ignoring to connect peer %u to peer %u\n" msgstr "Kan inte ansluta till %u.%u.%u.%u:%u: %s\n" #: src/testing/gnunet-testing.c:173 #, fuzzy, c-format msgid "Could not extract hostkey %u (offset too large?)\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/testing/gnunet-testing.c:258 #, c-format msgid "Unknown command, use 'q' to quit or 'r' to restart peer\n" msgstr "" #: src/testing/gnunet-testing.c:355 #, fuzzy msgid "create unique configuration files" msgstr "skriv ut ett värde frÃ¥n konfigurationsfilen till standard ut" #: src/testing/gnunet-testing.c:357 msgid "extract hostkey file from pre-computed hostkey list" msgstr "" #: src/testing/gnunet-testing.c:359 #, fuzzy msgid "" "number of unique configuration files to create, or number of the hostkey to " "extract" msgstr "skriv ut ett värde frÃ¥n konfigurationsfilen till standard ut" #: src/testing/gnunet-testing.c:361 #, fuzzy msgid "configuration template" msgstr "Konfigurationsfil \"%s\" skapad.\n" #: src/testing/gnunet-testing.c:363 msgid "run the given service, wait on stdin for 'r' (restart) or 'q' (quit)" msgstr "" #: src/testing/gnunet-testing.c:376 msgid "Command line tool to access the testing library" msgstr "" #: src/testing/list-keys.c:90 msgid "list COUNT number of keys" msgstr "" #: src/testing/list-keys.c:93 msgid "skip COUNT number of keys in the beginning" msgstr "" #: src/testing/testing.c:277 #, c-format msgid "Hostkeys file not found: %s\n" msgstr "" #: src/testing/testing.c:718 #, fuzzy, c-format msgid "Key number %u does not exist\n" msgstr "antal meddelanden att använda per iteration" #: src/testing/testing.c:1157 #, c-format msgid "" "You attempted to create a testbed with more than %u hosts. Please " "precompute more hostkeys first.\n" msgstr "" #: src/testing/testing.c:1166 #, fuzzy, c-format msgid "Failed to initialize hostkey for peer %u\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/testing/testing.c:1176 #, fuzzy msgid "PRIVATE_KEY option in PEER section missing in configuration\n" msgstr "Inga applikationer definierade i konfiguration!\n" #: src/testing/testing.c:1189 #, fuzzy msgid "Failed to create configuration for peer (not enough free ports?)\n" msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #: src/testing/testing.c:1203 #, fuzzy, c-format msgid "Cannot open hostkey file `%s': %s\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/testing/testing.c:1215 #, fuzzy, c-format msgid "Failed to write hostkey file for peer %u: %s\n" msgstr "Kunde inte skapa användarkonto:" #: src/testing/testing.c:1240 #, fuzzy, c-format msgid "Failed to write configuration file `%s' for peer %u: %s\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/testing/testing.c:1342 #, fuzzy, c-format msgid "Failed to start `%s': %s\n" msgstr "Fel vid %s:%d.\n" #: src/testing/testing.c:1706 #, fuzzy, c-format msgid "Failed to load configuration from %s\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/topology/friends.c:100 #, fuzzy, c-format msgid "Syntax error in FRIENDS file at offset %llu, skipping bytes `%.*s'.\n" msgstr "Syntaxfel i konfigurationsfil \"%s\" pÃ¥ rad %d.\n" #: src/topology/friends.c:154 #, c-format msgid "Directory for file `%s' does not seem to be writable.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:255 msgid "# peers blacklisted" msgstr "" #: src/topology/gnunet-daemon-topology.c:388 #, fuzzy msgid "# connect requests issued to transport" msgstr "# byte mottogs via TCP" #: src/topology/gnunet-daemon-topology.c:728 #: src/topology/gnunet-daemon-topology.c:813 #, fuzzy msgid "# friends connected" msgstr "# av anslutna parter" #: src/topology/gnunet-daemon-topology.c:993 msgid "Failed to connect to core service, can not manage topology!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1022 #, c-format msgid "Found myself `%s' in friend list (useless, ignored)\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1029 #, fuzzy, c-format msgid "Found friend `%s' in configuration\n" msgstr " gconfig\tGTK-konfiguration\n" #: src/topology/gnunet-daemon-topology.c:1050 msgid "Encountered errors parsing friends list!\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1052 #, fuzzy msgid "# friends in configuration" msgstr " gconfig\tGTK-konfiguration\n" #: src/topology/gnunet-daemon-topology.c:1057 msgid "" "Fewer friends specified than required by minimum friend count. Will only " "connect to friends.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1063 msgid "" "More friendly connections required than target total number of connections.\n" msgstr "" #: src/topology/gnunet-daemon-topology.c:1094 #, fuzzy msgid "# HELLO messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/topology/gnunet-daemon-topology.c:1151 msgid "# HELLO messages gossipped" msgstr "" #: src/topology/gnunet-daemon-topology.c:1290 msgid "GNUnet topology control (maintaining P2P mesh and F2F constraints)" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:271 #, fuzzy, c-format msgid "Adding blacklisting entry for peer `%s'\n" msgstr "Motpart \"%s\" med pÃ¥litlighet %8u och adress \"%s\"\n" #: src/transport/gnunet-service-transport_blacklist.c:279 #, c-format msgid "Adding blacklisting entry for peer `%s':`%s'\n" msgstr "" #: src/transport/gnunet-service-transport_blacklist.c:464 #: src/transport/gnunet-service-transport_blacklist.c:745 msgid "# disconnects due to blacklist" msgstr "" #: src/transport/gnunet-service-transport.c:220 #, fuzzy msgid "# bytes payload discarded due to not connected peer" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/gnunet-service-transport.c:424 #, fuzzy msgid "# bytes total received" msgstr "# byte krypterade" #: src/transport/gnunet-service-transport.c:515 #, fuzzy msgid "# bytes payload received" msgstr "# byte dekrypterade" #: src/transport/gnunet-service-transport.c:686 #, fuzzy, c-format msgid "Could not obtain a valid network for `%s' %s (%s)\n" msgstr "Kunde inte köra \"%s\": %s\n" #: src/transport/gnunet-service-transport.c:733 #, c-format msgid "" "Address or session unknown: failed to update properties for peer `%s' plugin " "`%s' address `%s' session %p\n" msgstr "" #: src/transport/gnunet-service-transport.c:1084 #, fuzzy msgid "Transport service is lacking key configuration settings. Exiting.\n" msgstr "GNUnet-konfiguration" #: src/transport/gnunet-service-transport_clients.c:432 #, c-format msgid "Dropping message of type %u and size %u, have %u/%u messages pending\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:439 msgid "# messages dropped due to slow client" msgstr "" #: src/transport/gnunet-service-transport_clients.c:596 #, c-format msgid "Rejecting control connection from peer `%s', which is not me!\n" msgstr "" #: src/transport/gnunet-service-transport_clients.c:737 msgid "# bytes payload dropped (other peer was not connected)" msgstr "" #: src/transport/gnunet-service-transport_clients.c:770 #, fuzzy, c-format msgid "Blacklist refuses connection attempt to peer `%s'\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-service-transport_clients.c:776 #, fuzzy, c-format msgid "Blacklist allows connection attempt to peer `%s'\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-service-transport_clients.c:801 #, fuzzy msgid "# REQUEST CONNECT messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_clients.c:815 #, fuzzy, c-format msgid "Received a request connect message for peer `%s'\n" msgstr "Mottog ogiltigt \"%s\" meddelande frÃ¥n \"%s\".\n" #: src/transport/gnunet-service-transport_clients.c:826 #, fuzzy msgid "# REQUEST DISCONNECT messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_clients.c:840 #, fuzzy, c-format msgid "Received a request disconnect message for peer `%s'\n" msgstr "Mottog ogiltigt \"%s\" meddelande frÃ¥n \"%s\".\n" #: src/transport/gnunet-service-transport_hello.c:181 msgid "# refreshed my HELLO" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1095 #, fuzzy msgid "# DISCONNECT messages sent" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_neighbours.c:1220 #: src/transport/gnunet-service-transport_neighbours.c:1629 msgid "# bytes in message queue for other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1225 #, fuzzy msgid "# messages transmitted to other peers" msgstr "# byte skickade av typen %d" #: src/transport/gnunet-service-transport_neighbours.c:1230 #, fuzzy msgid "# transmission failures for messages to other peers" msgstr "# byte skickade av typen %d" #: src/transport/gnunet-service-transport_neighbours.c:1287 msgid "# messages timed out while in transport queue" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1343 #, fuzzy msgid "# keepalives sent" msgstr "# sessionsnycklar skickade" #: src/transport/gnunet-service-transport_neighbours.c:1376 #, fuzzy msgid "# KEEPALIVE messages discarded (peer unknown)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/gnunet-service-transport_neighbours.c:1384 #, fuzzy msgid "# KEEPALIVE messages discarded (no session)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/gnunet-service-transport_neighbours.c:1431 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (not connected)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/gnunet-service-transport_neighbours.c:1440 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (not expected)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/gnunet-service-transport_neighbours.c:1448 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (address changed)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/gnunet-service-transport_neighbours.c:1456 #, fuzzy msgid "# KEEPALIVE_RESPONSE messages discarded (wrong nonce)" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/gnunet-service-transport_neighbours.c:1534 #, fuzzy msgid "# messages discarded due to lack of neighbour record" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/gnunet-service-transport_neighbours.c:1568 msgid "# bandwidth quota violations by other peers" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1584 msgid "# ms throttling suggested" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1678 #, fuzzy, c-format msgid "" "Failed to send CONNECT message to peer `%s' using address `%s' session %p\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-service-transport_neighbours.c:1705 msgid "# Failed attempts to switch addresses (failed to send CONNECT CONT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1751 #, fuzzy msgid "# SESSION_CONNECT messages sent" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_neighbours.c:1767 #, fuzzy, c-format msgid "Failed to transmit CONNECT message via plugin to %s\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/transport/gnunet-service-transport_neighbours.c:1794 msgid "# Failed attempts to switch addresses (failed to send CONNECT)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1844 #, c-format msgid "" "Failed to send CONNECT_ACK message to peer `%s' using address `%s' session " "%p\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:1899 #, fuzzy msgid "# CONNECT_ACK messages sent" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_neighbours.c:1914 #, fuzzy, c-format msgid "Failed to transmit CONNECT_ACK message via plugin to %s\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/transport/gnunet-service-transport_neighbours.c:2192 #, fuzzy, c-format msgid "Blacklisting disapproved to connect to peer `%s'\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-service-transport_neighbours.c:2312 #, fuzzy msgid "# CONNECT messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_neighbours.c:2317 #, c-format msgid "CONNECT request from peer `%s' ignored due impending shutdown\n" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:2590 msgid "# Attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3012 #, fuzzy msgid "# Failed attempts to switch addresses (no response)" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/transport/gnunet-service-transport_neighbours.c:3107 #, fuzzy msgid "# CONNECT_ACK messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_neighbours.c:3115 #, fuzzy msgid "# unexpected CONNECT_ACK messages (no peer)" msgstr "skicka ANTAL meddelanden" #: src/transport/gnunet-service-transport_neighbours.c:3129 #: src/transport/gnunet-service-transport_neighbours.c:3164 #, fuzzy msgid "# unexpected CONNECT_ACK messages (not ready)" msgstr "skicka ANTAL meddelanden" #: src/transport/gnunet-service-transport_neighbours.c:3176 #, fuzzy msgid "# unexpected CONNECT_ACK messages (waiting on ATS)" msgstr "skicka ANTAL meddelanden" #: src/transport/gnunet-service-transport_neighbours.c:3200 msgid "# Successful attempts to switch addresses" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3208 #, fuzzy msgid "# unexpected CONNECT_ACK messages (disconnecting)" msgstr "skicka ANTAL meddelanden" #: src/transport/gnunet-service-transport_neighbours.c:3396 #, fuzzy msgid "# SESSION_ACK messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_neighbours.c:3424 #, fuzzy msgid "# unexpected SESSION_ACK messages" msgstr "# krypterade PONG-meddelanden skickade" #: src/transport/gnunet-service-transport_neighbours.c:3490 msgid "# SET QUOTA messages ignored (no such peer)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3505 msgid "# disconnects due to quota of 0" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3545 msgid "# disconnect messages ignored (malformed)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3551 #, fuzzy msgid "# DISCONNECT messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/gnunet-service-transport_neighbours.c:3560 msgid "# disconnect messages ignored (timestamp)" msgstr "" #: src/transport/gnunet-service-transport_neighbours.c:3687 #, fuzzy msgid "# disconnected from peer upon explicit request" msgstr "# av anslutna parter" #: src/transport/gnunet-service-transport_plugins.c:120 msgid "Transport service is lacking NEIGHBOUR_LIMIT option.\n" msgstr "" #: src/transport/gnunet-service-transport_plugins.c:178 #: src/transport/gnunet-service-transport_plugins.c:186 #: src/transport/gnunet-service-transport_plugins.c:194 #: src/transport/gnunet-service-transport_plugins.c:202 #: src/transport/gnunet-service-transport_plugins.c:210 #: src/transport/gnunet-service-transport_plugins.c:218 #: src/transport/gnunet-service-transport_plugins.c:226 #: src/transport/gnunet-service-transport_plugins.c:234 #: src/transport/gnunet-service-transport_plugins.c:242 #: src/transport/gnunet-service-transport_plugins.c:250 #: src/transport/gnunet-service-transport_plugins.c:258 #, fuzzy, c-format msgid "Missing function `%s' in transport plugin for `%s'\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/transport/gnunet-service-transport_plugins.c:265 #, c-format msgid "Did not load plugin `%s' due to missing functions\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:488 msgid "# address records discarded" msgstr "" #: src/transport/gnunet-service-transport_validation.c:558 #, c-format msgid "" "Not transmitting `%s' with `%s', message too big (%u bytes!). This should " "not happen.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:616 #, fuzzy msgid "# PING without HELLO messages sent" msgstr "# PING-meddelanden i klartext skickade" #: src/transport/gnunet-service-transport_validation.c:722 msgid "# address revalidations started" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1011 #, fuzzy msgid "# PING message for different peer received" msgstr "# PING-meddelanden skapade" #: src/transport/gnunet-service-transport_validation.c:1062 #, c-format msgid "Plugin `%s' not available, cannot confirm having this address\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1072 msgid "# failed address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1075 #, c-format msgid "Address `%s' is not one of my addresses, not confirming PING\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1083 msgid "# successful address checks during validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1095 #, c-format msgid "" "Not confirming PING from peer `%s' with address `%s' since I cannot confirm " "having this address.\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1103 #, c-format msgid "Received a PING message with validation bug from `%s'\n" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1157 #, fuzzy, c-format msgid "Failed to create PONG signature for peer `%s'\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/transport/gnunet-service-transport_validation.c:1206 msgid "# PONGs unicast via reliable transport" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1215 msgid "# PONGs multicast to all available addresses" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1356 msgid "# PONGs dropped, no matching pending validation" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1371 msgid "# PONGs dropped, signature expired" msgstr "" #: src/transport/gnunet-service-transport_validation.c:1493 #, fuzzy, c-format msgid "Validation received new %s message for peer `%s' with size %u\n" msgstr "Mottog ogiltigt \"%s\" meddelande frÃ¥n \"%s\".\n" #: src/transport/gnunet-service-transport_validation.c:1500 #, fuzzy, c-format msgid "Adding `%s' without addresses for peer `%s'\n" msgstr "Motpart \"%s\" med pÃ¥litlighet %8u och adress \"%s\"\n" #: src/transport/gnunet-transport.c:367 #, fuzzy, c-format msgid "Transmitted %llu bytes/s (%llu bytes in %s)\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/transport/gnunet-transport.c:375 #, c-format msgid "Received %llu bytes/s (%llu bytes in %s)\n" msgstr "" #: src/transport/gnunet-transport.c:415 #, fuzzy, c-format msgid "Failed to connect to `%s'\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-transport.c:428 #, fuzzy, c-format msgid "Failed to resolve address for peer `%s'\n" msgstr "Misslyckades att binda till UDP-port %d.\n" #: src/transport/gnunet-transport.c:438 #, fuzzy msgid "Failed to list connections, timeout occured\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-transport.c:559 #, fuzzy, c-format msgid "" "Peer `%s' %s %s\n" "\t%s%s\n" "\t%s%s\n" "\t%s%s\n" msgstr "Jag är ändpunkt \"%s\".\n" #: src/transport/gnunet-transport.c:586 #, fuzzy, c-format msgid "Peer `%s' %s `%s' \n" msgstr "Jag är ändpunkt \"%s\".\n" #: src/transport/gnunet-transport.c:712 msgid "No transport plugins configured, peer will never communicate\n" msgstr "" #: src/transport/gnunet-transport.c:726 #, c-format msgid "No port configured for plugin `%s', cannot test it\n" msgstr "" #: src/transport/gnunet-transport.c:789 #, fuzzy, c-format msgid "Transmitting %u bytes to %s\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/transport/gnunet-transport.c:810 #, fuzzy, c-format msgid "Successfully connected to `%s'\n" msgstr "Ã…tkomst nekad för \"%s\" vid %s:%d.\n" #: src/transport/gnunet-transport.c:834 #, c-format msgid "" "Successfully connected to `%s', starting to send benchmark data in %u Kb " "blocks\n" msgstr "" #: src/transport/gnunet-transport.c:865 #, fuzzy, c-format msgid "Successfully disconnected from `%s'\n" msgstr "Ã…tkomst nekad för \"%s\" vid %s:%d.\n" #: src/transport/gnunet-transport.c:888 #, fuzzy, c-format msgid "Disconnected from peer `%s' while benchmarking\n" msgstr "\"%s\" ansluten till \"%s\".\n" #: src/transport/gnunet-transport.c:950 #, c-format msgid "Received %u bytes from %s\n" msgstr "" #: src/transport/gnunet-transport.c:975 #, c-format msgid "Peer `%s': %s %s in state `%s' until %s\n" msgstr "" #: src/transport/gnunet-transport.c:986 #, fuzzy, c-format msgid "Peer `%s': %s %s\n" msgstr "Jag är ändpunkt \"%s\".\n" #: src/transport/gnunet-transport.c:1197 src/transport/gnunet-transport.c:1222 #, fuzzy msgid "Failed to send connect request to transport service\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-transport.c:1266 #, c-format msgid "" "Multiple operations given. Please choose only one operation: %s, %s, %s, %s, " "%s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1274 #, c-format msgid "" "No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s\n" msgstr "" #: src/transport/gnunet-transport.c:1293 src/transport/gnunet-transport.c:1323 #: src/transport/gnunet-transport.c:1353 src/transport/gnunet-transport.c:1376 #: src/transport/gnunet-transport.c:1419 #, fuzzy msgid "Failed to connect to transport service\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-transport.c:1302 src/transport/gnunet-transport.c:1332 #: src/transport/gnunet-transport.c:1362 #, fuzzy msgid "Failed to send request to transport service\n" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-transport.c:1381 msgid "Starting to receive benchmark data\n" msgstr "" #: src/transport/gnunet-transport.c:1465 #, fuzzy msgid "print information for all peers (instead of only connected peers )" msgstr "Skriv ut information om GNUnets motparter." #: src/transport/gnunet-transport.c:1468 msgid "measure how fast we are receiving data from all peers (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1471 #, fuzzy msgid "connect to a peer" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-transport.c:1474 #, fuzzy msgid "disconnect to a peer" msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/gnunet-transport.c:1477 #, fuzzy msgid "print information for all pending validations " msgstr "Skriv ut information om GNUnets motparter." #: src/transport/gnunet-transport.c:1480 #, fuzzy msgid "print information for all pending validations continously" msgstr "Skriv ut information om GNUnets motparter." #: src/transport/gnunet-transport.c:1483 #, fuzzy msgid "provide information about all current connections (once)" msgstr "Skriv ut information om GNUnets motparter." #: src/transport/gnunet-transport.c:1489 #, fuzzy msgid "" "provide information about all connects and disconnect events (continuously)" msgstr "Skriv ut information om GNUnets motparter." #: src/transport/gnunet-transport.c:1491 #, fuzzy msgid "do not resolve hostnames" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/transport/gnunet-transport.c:1493 msgid "peer identity" msgstr "" #: src/transport/gnunet-transport.c:1495 msgid "send data for benchmarking to the other peer (until CTRL-C)" msgstr "" #: src/transport/gnunet-transport.c:1498 msgid "test transport configuration (involves external server)" msgstr "" #: src/transport/gnunet-transport.c:1507 #, fuzzy msgid "Direct access to transport service." msgstr "Misslyckades att ansluta till gnunetd.\n" #: src/transport/plugin_transport_bluetooth.c:621 msgid "# Bluetooth ACKs sent" msgstr "" #: src/transport/plugin_transport_bluetooth.c:640 #, fuzzy msgid "# Bluetooth messages defragmented" msgstr "# PING-meddelanden skapade" #: src/transport/plugin_transport_bluetooth.c:686 #: src/transport/plugin_transport_bluetooth.c:737 #: src/transport/plugin_transport_bluetooth.c:1942 #, fuzzy msgid "# Bluetooth sessions allocated" msgstr "# sessionsnycklar accepterade" #: src/transport/plugin_transport_bluetooth.c:837 #, fuzzy msgid "# Bluetooth message fragments sent" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_bluetooth.c:861 msgid "# Bluetooth messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_bluetooth.c:969 #: src/transport/plugin_transport_bluetooth.c:1054 #: src/transport/plugin_transport_bluetooth.c:1944 #, fuzzy msgid "# Bluetooth MAC endpoints allocated" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_bluetooth.c:1307 #, fuzzy msgid "# HELLO messages received via Bluetooth" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_bluetooth.c:1331 #, fuzzy msgid "# fragments received via Bluetooth" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_bluetooth.c:1341 #, fuzzy msgid "# ACKs received via Bluetooth" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_bluetooth.c:1401 #, fuzzy msgid "# Bluetooth DATA messages discarded due to CRC32 error" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/plugin_transport_bluetooth.c:1512 #, fuzzy msgid "# DATA messages received via Bluetooth" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_bluetooth.c:1547 #, fuzzy msgid "# Bluetooth DATA messages processed" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_bluetooth.c:1610 #, fuzzy msgid "# HELLO beacons sent via Bluetooth" msgstr "# byte skickade via UDP" #: src/transport/plugin_transport_bluetooth.c:1723 msgid "Bluetooth address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_bluetooth.c:1923 #, c-format msgid "Helper binary `%s' not SUID, cannot run bluetooth transport\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1622 #, c-format msgid "Could not initialize curl multi handle, failed to start %s plugin!\n" msgstr "" #: src/transport/plugin_transport_http_client.c:1697 #: src/transport/plugin_transport_http_server.c:3007 #, fuzzy, c-format msgid "Shutting down plugin `%s'\n" msgstr "Testar transport(er) %s\n" #: src/transport/plugin_transport_http_client.c:1722 #: src/transport/plugin_transport_http_server.c:3063 #, fuzzy, c-format msgid "Shutdown for plugin `%s' complete\n" msgstr "" "Uppladdning av \"%s\" klar, aktuell genomsnittshastighet är %8.3f kbps.\n" #: src/transport/plugin_transport_http_client.c:1750 #: src/transport/plugin_transport_http_server.c:2907 #, fuzzy, c-format msgid "Maximum number of connections is %u\n" msgstr "Maximalt antal chattklienter uppnÃ¥tt.\n" #: src/transport/plugin_transport_http_server.c:1402 #, c-format msgid "" "Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data " "size %u\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1663 #, c-format msgid "Accepting connection (%u of %u) from `%s'\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1671 #, c-format msgid "" "Server reached maximum number connections (%u), rejecting new connection\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1958 msgid "" "Could not create a new TLS certificate, program `gnunet-transport-" "certificate-creation' could not be started!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:1982 #, c-format msgid "No usable TLS certificate found and creating one at `%s/%s' failed!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2405 #, fuzzy msgid "Require valid port number for service in configuration!\n" msgstr "Inga applikationer definierade i konfiguration!\n" #: src/transport/plugin_transport_http_server.c:2437 src/util/service.c:698 #, fuzzy, c-format msgid "Failed to resolve `%s': %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/transport/plugin_transport_http_server.c:2454 src/util/service.c:715 #, fuzzy, c-format msgid "Failed to find %saddress for `%s'.\n" msgstr "Misslyckades att binda till UDP-port %d.\n" #: src/transport/plugin_transport_http_server.c:2565 #, c-format msgid "Found %u addresses to report to NAT service\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2637 msgid "Disabling IPv6 since it is not supported on this system!\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2730 #, c-format msgid "IPv4 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2744 #, c-format msgid "IPv6 support is %s\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2751 msgid "Neither IPv4 nor IPv6 are enabled! Fix in configuration\n" msgstr "" #: src/transport/plugin_transport_http_server.c:2762 #, fuzzy msgid "Port is required! Fix in configuration\n" msgstr " gconfig\tGTK-konfiguration\n" #: src/transport/plugin_transport_http_server.c:2769 #, fuzzy, c-format msgid "Using port %u\n" msgstr "Testar transport(er) %s\n" #: src/transport/plugin_transport_http_server.c:2784 #, fuzzy, c-format msgid "Specific IPv4 address `%s' in configuration file is invalid!\n" msgstr "" "Du mÃ¥ste ange ett positivt nummer för \"%s\" i konfigurationen i sektion \"%s" "\".\n" #: src/transport/plugin_transport_http_server.c:2794 #, fuzzy, c-format msgid "Binding to IPv4 address %s\n" msgstr "Ogiltigt svar pÃ¥ \"%s\".\n" #: src/transport/plugin_transport_http_server.c:2815 #, fuzzy, c-format msgid "Specific IPv6 address `%s' in configuration file is invalid!\n" msgstr "" "Du mÃ¥ste ange ett positivt nummer för \"%s\" i konfigurationen i sektion \"%s" "\".\n" #: src/transport/plugin_transport_http_server.c:2825 #, fuzzy, c-format msgid "Binding to IPv6 address %s\n" msgstr "Ogiltigt svar pÃ¥ \"%s\".\n" #: src/transport/plugin_transport_http_server.c:2877 #, fuzzy, c-format msgid "Using external hostname `%s'\n" msgstr "Startade samling \"%s\".\n" #: src/transport/plugin_transport_http_server.c:2893 #, fuzzy, c-format msgid "Notifying transport only about hostname `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/transport/plugin_transport_smtp.c:223 #, fuzzy, c-format msgid "Received malformed message via %s. Ignored.\n" msgstr "Mottog ogiltigt \"%s\" meddelande frÃ¥n \"%s\".\n" # capped är inte ett bra ord IMHO #: src/transport/plugin_transport_smtp.c:310 #, fuzzy msgid "SMTP filter string to invalid, lacks ': '\n" msgstr "SMTP-filtersträng för lÃ¥ng, kapad till \"%s\"\n" # capped är inte ett bra ord IMHO #: src/transport/plugin_transport_smtp.c:319 #, c-format msgid "SMTP filter string to long, capped to `%s'\n" msgstr "SMTP-filtersträng för lÃ¥ng, kapad till \"%s\"\n" #: src/transport/plugin_transport_smtp.c:414 #: src/transport/plugin_transport_smtp.c:424 #: src/transport/plugin_transport_smtp.c:437 #: src/transport/plugin_transport_smtp.c:456 #: src/transport/plugin_transport_smtp.c:479 #: src/transport/plugin_transport_smtp.c:487 #: src/transport/plugin_transport_smtp.c:500 #: src/transport/plugin_transport_smtp.c:511 #, fuzzy, c-format msgid "SMTP: `%s' failed: %s.\n" msgstr "\"%s\" %s misslyckades: %s\n" #: src/transport/plugin_transport_smtp.c:652 msgid "No email-address specified, can not start SMTP transport.\n" msgstr "" #: src/transport/plugin_transport_smtp.c:664 #, fuzzy msgid "# bytes received via SMTP" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_smtp.c:665 #, fuzzy msgid "# bytes sent via SMTP" msgstr "# byte skickades via TCP" #: src/transport/plugin_transport_smtp.c:667 #, fuzzy msgid "# bytes dropped by SMTP (outgoing)" msgstr "# byte kastade via TCP (utgÃ¥ende)" #: src/transport/plugin_transport_tcp.c:555 #, c-format msgid "Unexpected address length: %u bytes\n" msgstr "" #: src/transport/plugin_transport_tcp.c:762 #: src/transport/plugin_transport_tcp.c:928 #: src/transport/plugin_transport_tcp.c:2005 #: src/transport/plugin_transport_tcp.c:2558 #, fuzzy msgid "# TCP sessions active" msgstr "# sessionsnycklar accepterade" #: src/transport/plugin_transport_tcp.c:795 #: src/transport/plugin_transport_tcp.c:921 #: src/transport/plugin_transport_tcp.c:1009 #: src/transport/plugin_transport_tcp.c:1056 #: src/transport/plugin_transport_tcp.c:1219 #: src/transport/plugin_transport_tcp.c:1237 #, fuzzy msgid "# bytes currently in TCP buffers" msgstr "# byte skickades via TCP" #: src/transport/plugin_transport_tcp.c:798 #, fuzzy msgid "# bytes discarded by TCP (disconnect)" msgstr "# byte kastade via TCP (utgÃ¥ende)" #: src/transport/plugin_transport_tcp.c:1012 #, fuzzy msgid "# bytes discarded by TCP (timeout)" msgstr "# byte kastade via TCP (utgÃ¥ende)" #: src/transport/plugin_transport_tcp.c:1059 #, fuzzy msgid "# bytes transmitted via TCP" msgstr "# byte skickade av typen %d" #: src/transport/plugin_transport_tcp.c:1193 #, c-format msgid "Trying to send with invalid session %p\n" msgstr "" #: src/transport/plugin_transport_tcp.c:1462 msgid "# requests to create session with invalid address" msgstr "" #: src/transport/plugin_transport_tcp.c:1567 msgid "# transport-service disconnect requests for TCP" msgstr "" #: src/transport/plugin_transport_tcp.c:2055 #, fuzzy msgid "# TCP WELCOME messages received" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_tcp.c:2215 msgid "# bytes received via TCP" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_tcp.c:2279 msgid "# network-level TCP disconnect events" msgstr "" #: src/transport/plugin_transport_tcp.c:2437 src/util/service.c:582 #: src/util/service.c:588 #, c-format msgid "Require valid port number for service `%s' in configuration!\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2451 #, fuzzy msgid "Failed to start service.\n" msgstr "Misslyckades att starta samling.\n" #: src/transport/plugin_transport_tcp.c:2547 #, c-format msgid "TCP transport listening on port %llu\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2551 msgid "TCP transport not listening on any port (client only)\n" msgstr "" #: src/transport/plugin_transport_tcp.c:2554 #, c-format msgid "TCP transport advertises itself as being on port %llu\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:167 #, fuzzy msgid "# IPv6 multicast HELLO beacons received via udp" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_udp_broadcasting.c:210 #, fuzzy msgid "# IPv4 broadcast HELLO beacons received via udp" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_udp_broadcasting.c:603 msgid "" "Disabling HELLO broadcasting due to friend-to-friend only configuration!\n" msgstr "" #: src/transport/plugin_transport_udp_broadcasting.c:626 #, c-format msgid "Failed to set IPv4 broadcast option for broadcast socket on port %d\n" msgstr "" #: src/transport/plugin_transport_udp.c:1513 #, c-format msgid "" "Trying to create session for address of unexpected length %u (should be %u " "or %u)\n" msgstr "" #: src/transport/plugin_transport_udp.c:2602 #, c-format msgid "" "UDP could not transmit message to `%s': Network seems down, please check " "your network configuration\n" msgstr "" #: src/transport/plugin_transport_udp.c:2616 msgid "" "UDP could not transmit IPv6 message! Please check your network configuration " "and disable IPv6 if your connection does not have a global IPv6 address\n" msgstr "" #: src/transport/plugin_transport_udp.c:2961 #, fuzzy msgid "Failed to open UDP sockets\n" msgstr "Misslyckades att binda till UDP6-port %d.\n" #: src/transport/plugin_transport_udp.c:3056 #, c-format msgid "Given `%s' option is out of range: %llu > %u\n" msgstr "" #: src/transport/plugin_transport_udp.c:3097 #, fuzzy, c-format msgid "Invalid IPv6 address: `%s'\n" msgstr "Ogiltigt svar pÃ¥ \"%s\".\n" #: src/transport/plugin_transport_udp.c:3168 #, fuzzy msgid "Failed to create network sockets, plugin failed\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/transport/plugin_transport_unix.c:1321 #, fuzzy, c-format msgid "Cannot create path to `%s'\n" msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #: src/transport/plugin_transport_unix.c:1652 #, fuzzy msgid "No UNIXPATH given in configuration!\n" msgstr "Kunde inte spara konfiguration!" #: src/transport/plugin_transport_unix.c:1688 #, fuzzy msgid "Failed to open UNIX listen socket\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/transport/plugin_transport_wlan.c:620 msgid "# WLAN ACKs sent" msgstr "" #: src/transport/plugin_transport_wlan.c:639 #, fuzzy msgid "# WLAN messages defragmented" msgstr "# PING-meddelanden skapade" #: src/transport/plugin_transport_wlan.c:688 #: src/transport/plugin_transport_wlan.c:772 #: src/transport/plugin_transport_wlan.c:1948 #, fuzzy msgid "# WLAN sessions allocated" msgstr "# sessionsnycklar accepterade" #: src/transport/plugin_transport_wlan.c:876 #, fuzzy msgid "# WLAN message fragments sent" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_wlan.c:900 msgid "# WLAN messages pending (with fragmentation)" msgstr "" #: src/transport/plugin_transport_wlan.c:1008 #: src/transport/plugin_transport_wlan.c:1098 #: src/transport/plugin_transport_wlan.c:1950 #, fuzzy msgid "# WLAN MAC endpoints allocated" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_wlan.c:1302 #, fuzzy msgid "# HELLO messages received via WLAN" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_wlan.c:1326 #, fuzzy msgid "# fragments received via WLAN" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_wlan.c:1336 #, fuzzy msgid "# ACKs received via WLAN" msgstr "# byte mottogs via TCP" #: src/transport/plugin_transport_wlan.c:1396 #, fuzzy msgid "# WLAN DATA messages discarded due to CRC32 error" msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #: src/transport/plugin_transport_wlan.c:1518 #, fuzzy msgid "# DATA messages received via WLAN" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_wlan.c:1553 #, fuzzy msgid "# WLAN DATA messages processed" msgstr "# krypterade PONG-meddelanden mottagna" #: src/transport/plugin_transport_wlan.c:1616 #, fuzzy msgid "# HELLO beacons sent via WLAN" msgstr "# byte skickade via UDP" #: src/transport/plugin_transport_wlan.c:1729 msgid "WLAN address with invalid size encountered\n" msgstr "" #: src/transport/plugin_transport_wlan.c:1929 #, c-format msgid "Helper binary `%s' not SUID, cannot run WLAN transport\n" msgstr "" #: src/transport/transport_api.c:739 #, fuzzy, c-format msgid "Received unexpected message of type %u in %s:%u\n" msgstr "Mottog skadat meddelande frÃ¥n motpart \"%s\"i %s:%d.\n" #: src/transport/transport-testing.c:584 #, fuzzy msgid "Failed to initialize testing library!\n" msgstr "Misslyckades att initiera tjänsten \"%s\".\n" #: src/tun/regex.c:129 #, c-format msgid "Bad mask: %d\n" msgstr "" #: src/util/bio.c:170 src/util/bio.c:178 #, fuzzy, c-format msgid "Error reading `%s': %s" msgstr "Fel vid skapandet av användare" #: src/util/bio.c:180 #, fuzzy msgid "End of file" msgstr "Läs in en konfigurationsfil" #: src/util/bio.c:237 #, c-format msgid "Error reading length of string `%s'" msgstr "" #: src/util/bio.c:247 #, c-format msgid "String `%s' longer than allowed (%u > %u)" msgstr "" #: src/util/bio.c:293 #, c-format msgid "Serialized metadata `%s' larger than allowed (%u>%u)" msgstr "" #: src/util/bio.c:307 #, c-format msgid "Metadata `%s' failed to deserialize" msgstr "" #: src/util/client.c:261 src/util/client.c:858 src/util/service.c:619 #, c-format msgid "UNIXPATH `%s' too long, maximum length is %llu\n" msgstr "" #: src/util/client.c:265 src/util/client.c:863 src/util/service.c:623 #, fuzzy, c-format msgid "Using `%s' instead\n" msgstr "%s: flagga \"%s\" är tvetydig\n" #: src/util/client.c:360 #, c-format msgid "" "Could not determine valid hostname and port for service `%s' from " "configuration.\n" msgstr "" #: src/util/client.c:368 #, c-format msgid "Need a non-empty hostname for service `%s'.\n" msgstr "" #: src/util/client.c:1008 #, fuzzy, c-format msgid "Could not connect to service `%s', configuration broken.\n" msgstr "Kunde inte ansluta till gnunetd.\n" #: src/util/client.c:1020 #, fuzzy, c-format msgid "Failure to transmit request to service `%s'\n" msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #: src/util/client.c:1303 msgid "Could not submit request, not expecting to receive a response.\n" msgstr "" #: src/util/common_logging.c:254 src/util/common_logging.c:1039 msgid "DEBUG" msgstr "FELSÖKNING" #: src/util/common_logging.c:256 src/util/common_logging.c:1037 msgid "INFO" msgstr "INFO" #: src/util/common_logging.c:258 src/util/common_logging.c:1035 msgid "WARNING" msgstr "VARNING" #: src/util/common_logging.c:260 src/util/common_logging.c:1033 msgid "ERROR" msgstr "FEL" #: src/util/common_logging.c:262 src/util/common_logging.c:1041 msgid "NONE" msgstr "" #: src/util/common_logging.c:391 #, fuzzy, c-format msgid "Failed to create or access directory for log file `%s'\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/util/common_logging.c:817 #, c-format msgid "Message `%.*s' repeated %u times in the last %s\n" msgstr "" #: src/util/common_logging.c:1042 msgid "INVALID" msgstr "" #: src/util/common_logging.c:1157 msgid "unknown address" msgstr "" #: src/util/common_logging.c:1196 msgid "invalid address" msgstr "" #: src/util/common_logging.c:1214 #, fuzzy, c-format msgid "Configuration fails to specify option `%s' in section `%s'!\n" msgstr "Konfigurationsfil \"%s\" skapad.\n" #: src/util/common_logging.c:1235 #, fuzzy, c-format msgid "" "Configuration specifies invalid value for option `%s' in section `%s': %s\n" msgstr "Konfigurationsfil \"%s\" hittades inte. Kör \"gnunet-setup -d\"!\n" #: src/util/configuration.c:288 #, fuzzy, c-format msgid "Syntax error while deserializing in line %u\n" msgstr "Syntaxfel i konfigurationsfil \"%s\" pÃ¥ rad %d.\n" #: src/util/configuration.c:996 #, c-format msgid "" "Configuration value '%s' for '%s' in section '%s' is not in set of legal " "choices\n" msgstr "" #: src/util/configuration.c:1066 #, c-format msgid "Recursive expansion suspected, aborting $-expansion for term `%s'\n" msgstr "" #: src/util/configuration.c:1098 #, fuzzy, c-format msgid "Missing closing `%s' in option `%s'\n" msgstr "Konfigurationsfil \"%s\" skapad.\n" #: src/util/configuration.c:1172 #, c-format msgid "" "Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined " "as an environmental variable\n" msgstr "" #: src/util/connection.c:423 #, fuzzy, c-format msgid "Access denied to `%s'\n" msgstr "Ã…tkomst nekad för \"%s\" vid %s:%d.\n" #: src/util/connection.c:438 #, c-format msgid "Accepting connection from `%s': %p\n" msgstr "" #: src/util/connection.c:553 #, fuzzy, c-format msgid "" "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n" msgstr "Misslyckades att starta samling.\n" #: src/util/connection.c:751 src/util/connection.c:919 #, fuzzy, c-format msgid "Trying to connect to `%s' (%p)\n" msgstr "Kan inte ansluta till %u.%u.%u.%u:%u: %s\n" #: src/util/connection.c:910 #, fuzzy, c-format msgid "Attempt to connect to `%s' failed\n" msgstr " Anslutning misslyckades\n" #: src/util/container_bloomfilter.c:531 #, c-format msgid "" "Size of file on disk is incorrect for this Bloom filter (want %llu, have " "%llu)\n" msgstr "" #: src/util/crypto_ecc.c:702 src/util/crypto_ecc.c:740 #: src/util/crypto_ecc.c:858 src/util/crypto_ecc.c:896 #, fuzzy, c-format msgid "Could not acquire lock on file `%s': %s...\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/util/crypto_ecc.c:707 src/util/crypto_ecc.c:863 #, fuzzy msgid "Creating a new private key. This may take a while.\n" msgstr "Skapar ny värdnyckel (det här kan ta en stund).\n" #: src/util/crypto_ecc.c:744 src/util/crypto_ecc.c:900 msgid "This may be ok if someone is currently generating a private key.\n" msgstr "" #: src/util/crypto_ecc.c:774 src/util/crypto_ecc.c:930 #, c-format msgid "" "When trying to read key file `%s' I found %u bytes but I need at least %u.\n" msgstr "" #: src/util/crypto_ecc.c:778 src/util/crypto_ecc.c:934 msgid "This may be ok if someone is currently generating a key.\n" msgstr "" #: src/util/crypto_ecc.c:1016 #, fuzzy msgid "Could not load peer's private key\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/util/crypto_ecc.c:1120 #, fuzzy, c-format msgid "ECC signing failed at %s:%d: %s\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/util/crypto_ecc.c:1170 #, fuzzy, c-format msgid "EdDSA signing failed at %s:%d: %s\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/util/crypto_ecc.c:1244 #, fuzzy, c-format msgid "ECDSA signature verification failed at %s:%d: %s\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/util/crypto_ecc.c:1301 #, fuzzy, c-format msgid "EdDSA signature verification failed at %s:%d: %s\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/util/crypto_random.c:284 #, c-format msgid "libgcrypt has not the expected version (version %s is required).\n" msgstr "libgcrypt har inte den förväntande versionen (version %s krävs).\n" #: src/util/disk.c:1184 #, fuzzy, c-format msgid "Expected `%s' to be a directory!\n" msgstr "\"%s\" förväntade att \"%s\" skulle vara en katalog!\n" #: src/util/disk.c:1546 src/util/service.c:1318 #, fuzzy, c-format msgid "Cannot obtain information about user `%s': %s\n" msgstr "Kan inte öppna konfigurationsfil \"%s\".\n" #: src/util/getopt.c:568 #, c-format msgid "%s: option `%s' is ambiguous\n" msgstr "%s: flagga \"%s\" är tvetydig\n" #: src/util/getopt.c:592 #, c-format msgid "%s: option `--%s' does not allow an argument\n" msgstr "%s: flagga \"--%s\" tillÃ¥ter inte ett argument\n" #: src/util/getopt.c:597 #, c-format msgid "%s: option `%c%s' does not allow an argument\n" msgstr "%s: flagga \"%c%s\" tillÃ¥ter inte ett argument\n" #: src/util/getopt.c:614 src/util/getopt.c:781 #, c-format msgid "%s: option `%s' requires an argument\n" msgstr "%s: flagga \"%s\" kräver ett argument\n" #: src/util/getopt.c:643 #, c-format msgid "%s: unrecognized option `--%s'\n" msgstr "%s: okänd flagga \"--%s\"\n" #: src/util/getopt.c:647 #, c-format msgid "%s: unrecognized option `%c%s'\n" msgstr "%s: okänd flagga \"%c%s\"\n" #: src/util/getopt.c:672 #, c-format msgid "%s: illegal option -- %c\n" msgstr "%s: otillÃ¥ten flagga -- %c\n" #: src/util/getopt.c:674 #, c-format msgid "%s: invalid option -- %c\n" msgstr "%s: ogiltig flagga -- %c\n" #: src/util/getopt.c:702 src/util/getopt.c:829 #, c-format msgid "%s: option requires an argument -- %c\n" msgstr "%s: flagga kräver ett argument -- %c\n" #: src/util/getopt.c:750 #, c-format msgid "%s: option `-W %s' is ambiguous\n" msgstr "%s: flagga \"-W %s\" är tvetydig\n" #: src/util/getopt.c:768 #, c-format msgid "%s: option `-W %s' does not allow an argument\n" msgstr "%s: flagga \"-W %s\" tillÃ¥ter inte ett argument\n" #: src/util/getopt.c:933 #, fuzzy, c-format msgid "Use %s to get a list of options.\n" msgstr "Använd --help för att fÃ¥ en lista pÃ¥ flaggor.\n" #: src/util/getopt_helpers.c:84 #, c-format msgid "" "Arguments mandatory for long options are also mandatory for short options.\n" msgstr "" "Argument som är obligatoriska för lÃ¥nga flaggor är ocksÃ¥ obligatoriska för " "korta flaggor.\n" #: src/util/getopt_helpers.c:268 src/util/getopt_helpers.c:326 #, c-format msgid "You must pass a number to the `%s' option.\n" msgstr "Du mÃ¥ste skicka med ett nummer till flaggan \"%s\".\n" #: src/util/getopt_helpers.c:298 #, fuzzy, c-format msgid "You must pass relative time to the `%s' option.\n" msgstr "Du mÃ¥ste skicka med ett nummer till flaggan \"%s\".\n" #: src/util/gnunet-config.c:90 #, c-format msgid "--section argument is required\n" msgstr "" #: src/util/gnunet-config.c:133 #, c-format msgid "--option argument required to set value\n" msgstr "" #: src/util/gnunet-config.c:160 msgid "obtain option of value as a filename (with $-expansion)" msgstr "" #: src/util/gnunet-config.c:163 msgid "name of the section to access" msgstr "" #: src/util/gnunet-config.c:166 #, fuzzy msgid "name of the option to access" msgstr "Visa värde av alternativet" #: src/util/gnunet-config.c:169 msgid "value to set" msgstr "" #: src/util/gnunet-config.c:178 #, fuzzy msgid "Manipulate GNUnet configuration files" msgstr "skriv ut ett värde frÃ¥n konfigurationsfilen till standard ut" #: src/util/gnunet-ecc.c:75 #, fuzzy, c-format msgid "Failed to open `%s': %s\n" msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #: src/util/gnunet-ecc.c:81 #, c-format msgid "Generating %u keys, please wait" msgstr "" #: src/util/gnunet-ecc.c:97 #, fuzzy, c-format msgid "" "\n" "Failed to write to `%s': %s\n" msgstr "Fel vid %s:%d.\n" #: src/util/gnunet-ecc.c:107 #, fuzzy, c-format msgid "" "\n" "Finished!\n" msgstr "Slutför" #: src/util/gnunet-ecc.c:110 #, c-format msgid "" "\n" "Error, %u keys not generated\n" msgstr "" #: src/util/gnunet-ecc.c:199 #, fuzzy, c-format msgid "Hostkeys file `%s' not found\n" msgstr "\"%s\" misslyckades: tabell hittades inte!\n" #: src/util/gnunet-ecc.c:210 #, fuzzy, c-format msgid "Hostkeys file `%s' is empty\n" msgstr "antal meddelanden att använda per iteration" #: src/util/gnunet-ecc.c:232 #, fuzzy, c-format msgid "Could not read hostkey file: %s\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/util/gnunet-ecc.c:283 msgid "No hostkey file specified on command line\n" msgstr "" #: src/util/gnunet-ecc.c:349 msgid "list keys included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:352 msgid "number of keys to list included in a file (for testing)" msgstr "" #: src/util/gnunet-ecc.c:355 msgid "create COUNT public-private key pairs (for testing)" msgstr "" #: src/util/gnunet-ecc.c:358 msgid "print the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:361 msgid "print the hash of the public key in ASCII format" msgstr "" #: src/util/gnunet-ecc.c:364 msgid "print examples of ECC operations (used for compatibility testing)" msgstr "" #: src/util/gnunet-ecc.c:375 #, fuzzy msgid "Manipulate GNUnet private ECC key files" msgstr "skriv ut ett värde frÃ¥n konfigurationsfilen till standard ut" #: src/util/gnunet-resolver.c:149 msgid "perform a reverse lookup" msgstr "" #: src/util/gnunet-resolver.c:160 msgid "Use build-in GNUnet stub resolver" msgstr "" #: src/util/gnunet-scrypt.c:279 msgid "number of bits to require for the proof of work" msgstr "" #: src/util/gnunet-scrypt.c:282 msgid "file with private key, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:285 msgid "file with proof of work, otherwise default is used" msgstr "" #: src/util/gnunet-scrypt.c:288 msgid "time to wait between calculations" msgstr "" #: src/util/gnunet-scrypt.c:299 #, fuzzy msgid "Manipulate GNUnet proof of work files" msgstr "skriv ut ett värde frÃ¥n konfigurationsfilen till standard ut" #: src/util/gnunet-service-resolver.c:299 #, fuzzy, c-format msgid "Could not resolve `%s' (%s): %s\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/util/gnunet-service-resolver.c:371 #: src/util/gnunet-service-resolver.c:412 #, c-format msgid "Could not find IP of host `%s': %s\n" msgstr "" #: src/util/gnunet-uri.c:84 #, c-format msgid "No URI specified on command line\n" msgstr "" #: src/util/gnunet-uri.c:89 #, fuzzy, c-format msgid "Invalid URI: does not start with `%s'\n" msgstr "Ogiltig nätverksnotation (slutar inte med \";\": \"%s\")\n" #: src/util/gnunet-uri.c:96 #, c-format msgid "Invalid URI: fails to specify subsystem\n" msgstr "" #: src/util/gnunet-uri.c:106 #, c-format msgid "No handler known for subsystem `%s'\n" msgstr "" #: src/util/gnunet-uri.c:168 msgid "Perform default-actions for GNUnet URIs" msgstr "" #: src/util/helper.c:338 #, fuzzy, c-format msgid "Error reading from `%s': %s\n" msgstr "Fel vid skapandet av användare" #: src/util/helper.c:383 #, fuzzy, c-format msgid "Failed to parse inbound message from helper `%s'\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/util/helper.c:609 #, fuzzy, c-format msgid "Error writing to `%s': %s\n" msgstr "Fel vid skapandet av användare" #: src/util/network.c:134 #, c-format msgid "Unable to shorten unix path `%s' while keeping name unique\n" msgstr "" #: src/util/network.c:1355 src/util/network.c:1480 #, c-format msgid "" "Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n" msgstr "" #: src/util/os_installation.c:421 #, c-format msgid "" "Could not determine installation path for %s. Set `%s' environment " "variable.\n" msgstr "" #: src/util/os_installation.c:766 #, fuzzy, c-format msgid "Could not find binary `%s' in PATH!\n" msgstr "Kunde inte hitta motpart \"%s\" i routingtabell!\n" # drive = hard drive ? #: src/util/os_installation.c:826 #, fuzzy, c-format msgid "CreateProcess failed for binary %s (%d).\n" msgstr "\"%s\" misslyckades för enhet %s: %u\n" #: src/util/os_installation.c:836 #, c-format msgid "GetExitCodeProcess failed for binary %s (%d).\n" msgstr "" #: src/util/plugin.c:87 #, c-format msgid "Initialization of plugin mechanism failed: %s!\n" msgstr "Initiering av insticksmekanism misslyckades: %s!\n" #: src/util/plugin.c:148 #, fuzzy, c-format msgid "`%s' failed to resolve method '%s' with error: %s\n" msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n" #: src/util/plugin.c:223 #, fuzzy, c-format msgid "`%s' failed for library `%s' with error: %s\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #: src/util/plugin.c:382 #, fuzzy msgid "Could not determine plugin installation path.\n" msgstr "Kunde inte fastställa min publika IPv6-adress.\n" #: src/util/program.c:246 src/util/service.c:1452 #, fuzzy, c-format msgid "Malformed configuration file `%s', exit ...\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/util/program.c:258 src/util/service.c:1467 #, fuzzy, c-format msgid "Could not access configuration file `%s'\n" msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #: src/util/program.c:263 src/util/service.c:1462 #, fuzzy msgid "Malformed configuration, exit ...\n" msgstr "Kunde inte spara konfigurationsfil \"%s\":" #: src/util/resolver_api.c:198 #, fuzzy, c-format msgid "Must specify `%s' for `%s' in configuration!\n" msgstr "Försöker använda fil \"%s\" för MySQL-konfiguration.\n" #: src/util/resolver_api.c:216 #, fuzzy, c-format msgid "" "Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n" msgstr "" "Du mÃ¥ste ange ett positivt nummer för \"%s\" i konfigurationen i sektion \"%s" "\".\n" #: src/util/resolver_api.c:348 #, c-format msgid "Timeout trying to resolve IP address `%s'.\n" msgstr "" #: src/util/resolver_api.c:352 #, fuzzy, c-format msgid "Timeout trying to resolve hostname `%s'.\n" msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #: src/util/resolver_api.c:908 #, fuzzy, c-format msgid "Could not resolve our FQDN : %s\n" msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #: src/util/scheduler.c:813 msgid "Looks like we're busy waiting...\n" msgstr "" #: src/util/scheduler.c:948 #, c-format msgid "Attempt to cancel dead task %llu!\n" msgstr "" # drive = hard drive ? #: src/util/server.c:484 #, fuzzy, c-format msgid "`%s' failed for port %d (%s).\n" msgstr "\"%s\" misslyckades för enhet %s: %u\n" #: src/util/server.c:493 #, fuzzy, c-format msgid "`%s' failed for port %d (%s): address already in use\n" msgstr "\"%s\" misslyckades för port %d: %s. Körs verkligen gnunetd?\n" #: src/util/server.c:499 #, fuzzy, c-format msgid "`%s' failed for `%s': address already in use\n" msgstr "\"%s\" misslyckades för port %d: %s. Körs verkligen gnunetd?\n" #: src/util/server.c:892 #, c-format msgid "" "Processing code for message of type %u did not call " "`GNUNET_SERVER_receive_done' after %s\n" msgstr "" #: src/util/service.c:347 #, fuzzy, c-format msgid "Unknown address family %d\n" msgstr "Okänd operation \"%s\"\n" #: src/util/service.c:354 #, c-format msgid "Access from `%s' denied to service `%s'\n" msgstr "" #: src/util/service.c:409 #, c-format msgid "Could not parse IPv4 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:446 #, c-format msgid "Could not parse IPv6 network specification `%s' for `%s:%s'\n" msgstr "" #: src/util/service.c:563 #, c-format msgid "" "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n" msgstr "" #: src/util/service.c:653 #, c-format msgid "" "Disabling UNIX domain socket support for service `%s', failed to create UNIX " "domain socket: %s\n" msgstr "" #: src/util/service.c:669 #, c-format msgid "Have neither PORT nor UNIXPATH for service `%s', but one is required\n" msgstr "" #: src/util/service.c:903 msgid "Could not access a pre-bound socket, will try to bind myself\n" msgstr "" #: src/util/service.c:952 src/util/service.c:970 #, c-format msgid "Specified value for `%s' of service `%s' is invalid\n" msgstr "" #: src/util/service.c:995 #, c-format msgid "Could not access pre-bound socket %u, will try to bind myself\n" msgstr "" #: src/util/service.c:1165 #, fuzzy, c-format msgid "Failed to start `%s' at `%s'\n" msgstr "Fel vid %s:%d.\n" #: src/util/service.c:1207 #, fuzzy, c-format msgid "Service `%s' runs at %s\n" msgstr "Motpart \"%s\" med pÃ¥litlighet %8u och adress \"%s\"\n" #: src/util/service.c:1256 msgid "Service process failed to initialize\n" msgstr "" #: src/util/service.c:1260 msgid "Service process could not initialize server function\n" msgstr "" #: src/util/service.c:1264 msgid "Service process failed to report status\n" msgstr "" #: src/util/service.c:1319 msgid "No such user" msgstr "" #: src/util/service.c:1332 #, c-format msgid "Cannot change user/group to `%s': %s\n" msgstr "Kan inte ändra användare/grupp till \"%s\": %s\n" #: src/util/service.c:1402 msgid "do daemonize (detach from terminal)" msgstr "" #: src/util/signal.c:89 #, fuzzy, c-format msgid "signal (%d, %p) returned %d.\n" msgstr "Anrop till \"%s\" returnerade %d.\n" #: src/util/strings.c:145 msgid "b" msgstr "b" #: src/util/strings.c:433 #, c-format msgid "Character sets requested were `%s'->`%s'\n" msgstr "" #: src/util/strings.c:561 msgid "Failed to expand `$HOME': environment variable `HOME' not set" msgstr "" #: src/util/strings.c:658 msgid "µs" msgstr "" #: src/util/strings.c:662 msgid "forever" msgstr "" #: src/util/strings.c:664 msgid "0 ms" msgstr "" #: src/util/strings.c:670 msgid "ms" msgstr "ms" #: src/util/strings.c:676 msgid "s" msgstr "s" #: src/util/strings.c:682 msgid "m" msgstr "m" #: src/util/strings.c:688 msgid "h" msgstr "h" #: src/util/strings.c:695 #, fuzzy msgid "day" msgstr " dagar" #: src/util/strings.c:697 #, fuzzy msgid "days" msgstr " dagar" #: src/util/strings.c:726 msgid "end of time" msgstr "" #: src/util/strings.c:1159 msgid "IPv6 address did not start with `['\n" msgstr "" #: src/util/strings.c:1167 msgid "IPv6 address did contain ':' to separate port number\n" msgstr "" #: src/util/strings.c:1173 msgid "IPv6 address did contain ']' before ':' to separate port number\n" msgstr "" #: src/util/strings.c:1180 msgid "IPv6 address did contain a valid port number after the last ':'\n" msgstr "" #: src/util/strings.c:1189 #, fuzzy, c-format msgid "Invalid IPv6 address `%s': %s\n" msgstr "Ogiltigt svar pÃ¥ \"%s\".\n" #: src/util/strings.c:1395 src/util/strings.c:1411 msgid "Port not in range\n" msgstr "" #: src/util/strings.c:1420 #, fuzzy, c-format msgid "Malformed port policy `%s'\n" msgstr "Misslyckades att starta samling.\n" #: src/util/strings.c:1503 src/util/strings.c:1534 src/util/strings.c:1582 #: src/util/strings.c:1603 #, c-format msgid "Invalid format for IP: `%s'\n" msgstr "Ogiltigt format för IP: \"%s\"\n" #: src/util/strings.c:1560 #, c-format msgid "Invalid network notation ('/%d' is not legal in IPv4 CIDR)." msgstr "Ogiltig nätverksnotation (\"/%d\" är inte giltig i IPv4 CIDR)." #: src/util/strings.c:1612 #, fuzzy, c-format msgid "Invalid format: `%s'\n" msgstr "Ogiltigt format för IP: \"%s\"\n" #: src/util/strings.c:1664 #, c-format msgid "Invalid network notation (does not end with ';': `%s')\n" msgstr "Ogiltig nätverksnotation (slutar inte med \";\": \"%s\")\n" #: src/util/strings.c:1714 #, fuzzy, c-format msgid "Wrong format `%s' for netmask\n" msgstr "Fel format \"%s\" för nätmask: %s\n" #: src/util/strings.c:1745 #, fuzzy, c-format msgid "Wrong format `%s' for network\n" msgstr "Fel format \"%s\" för nätverk: %s\n" #: src/vpn/gnunet-service-vpn.c:550 src/vpn/gnunet-service-vpn.c:1086 #, fuzzy msgid "# Active channels" msgstr "Nätverksanslutning" #: src/vpn/gnunet-service-vpn.c:642 #, fuzzy msgid "# Bytes given to mesh for transmission" msgstr "# PING-meddelanden skapade" #: src/vpn/gnunet-service-vpn.c:680 #, fuzzy msgid "# Bytes dropped in mesh queue (overflow)" msgstr "# byte kastade via UDP (utgÃ¥ende)" #: src/vpn/gnunet-service-vpn.c:753 #, fuzzy msgid "# Mesh channels created" msgstr "# PING-meddelanden skapade" #: src/vpn/gnunet-service-vpn.c:784 #, fuzzy msgid "Failed to setup mesh channel!\n" msgstr "Kunde inte skapa värdnyckel!\n" #: src/vpn/gnunet-service-vpn.c:978 #, c-format msgid "Protocol %u not supported, dropping\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1305 msgid "# ICMPv4 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1326 msgid "# ICMPv6 packets dropped (not allowed)" msgstr "" #: src/vpn/gnunet-service-vpn.c:1531 #, fuzzy msgid "# Packets received from TUN interface" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/vpn/gnunet-service-vpn.c:1564 src/vpn/gnunet-service-vpn.c:1600 #, c-format msgid "Packet received for unmapped destination `%s' (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1610 msgid "Received IPv4 packet with options (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1624 #, c-format msgid "Received packet of unknown protocol %d from TUN (dropping it)\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:1706 #, fuzzy msgid "# ICMP packets received from mesh" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/vpn/gnunet-service-vpn.c:2045 #, fuzzy msgid "# UDP packets received from mesh" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/vpn/gnunet-service-vpn.c:2200 #, fuzzy msgid "# TCP packets received from mesh" msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #: src/vpn/gnunet-service-vpn.c:2351 msgid "Failed to find unallocated IPv4 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2406 msgid "Failed to find unallocated IPv6 address in VPN's range\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2447 src/vpn/gnunet-service-vpn.c:2663 #, fuzzy msgid "# Active destinations" msgstr "Nätverksanslutning" #: src/vpn/gnunet-service-vpn.c:2715 msgid "Failed to allocate IP address for new destination\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:2982 #, fuzzy msgid "Must specify valid IPv6 address" msgstr "\"%s\" är inte tillgänglig." #: src/vpn/gnunet-service-vpn.c:3006 msgid "Must specify valid IPv6 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3014 msgid "IPv6 support disabled as this system does not support IPv6\n" msgstr "" #: src/vpn/gnunet-service-vpn.c:3027 #, fuzzy msgid "Must specify valid IPv4 address" msgstr "\"%s\" är inte tillgänglig." #: src/vpn/gnunet-service-vpn.c:3040 msgid "Must specify valid IPv4 mask" msgstr "" #: src/vpn/gnunet-service-vpn.c:3050 msgid "IPv4 support disabled as this system does not support IPv4\n" msgstr "" #: src/vpn/gnunet-vpn.c:147 #, fuzzy msgid "Error creating tunnel\n" msgstr "Klar med skapandet av värdnyckel.\n" #: src/vpn/gnunet-vpn.c:190 src/vpn/gnunet-vpn.c:221 #, fuzzy, c-format msgid "Option `%s' makes no sense with option `%s'.\n" msgstr "Kommando \"%s\" kräver ett argument (\"%s\").\n" #: src/vpn/gnunet-vpn.c:203 #, fuzzy, c-format msgid "Option `%s' or `%s' is required.\n" msgstr "%s: flagga \"%s\" är tvetydig\n" #: src/vpn/gnunet-vpn.c:215 #, fuzzy, c-format msgid "Option `%s' or `%s' is required when using option `%s'.\n" msgstr "Kommando \"%s\" kräver ett argument (\"%s\").\n" #: src/vpn/gnunet-vpn.c:235 #, fuzzy, c-format msgid "`%s' is not a valid peer identifier.\n" msgstr "\"%s\" är inte en vanlig fil.\n" #: src/vpn/gnunet-vpn.c:255 #, fuzzy, c-format msgid "`%s' is not a valid IP address.\n" msgstr "\"%s\" är inte tillgänglig." #: src/vpn/gnunet-vpn.c:290 msgid "request that result should be an IPv4 address" msgstr "" #: src/vpn/gnunet-vpn.c:293 msgid "request that result should be an IPv6 address" msgstr "" #: src/vpn/gnunet-vpn.c:296 msgid "how long should the mapping be valid for new tunnels?" msgstr "" #: src/vpn/gnunet-vpn.c:299 msgid "destination IP for the tunnel" msgstr "" #: src/vpn/gnunet-vpn.c:302 msgid "peer offering the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:305 msgid "name of the service we would like to access" msgstr "" #: src/vpn/gnunet-vpn.c:308 #, fuzzy msgid "service is offered via TCP" msgstr "# byte mottogs via TCP" #: src/vpn/gnunet-vpn.c:311 #, fuzzy msgid "service is offered via UDP" msgstr "# byte mottagna via UDP" #: src/vpn/gnunet-vpn.c:323 msgid "Setup tunnels via VPN." msgstr "" #: src/include/gnunet_common.h:566 src/include/gnunet_common.h:573 #: src/include/gnunet_common.h:581 #, fuzzy, c-format msgid "Assertion failed at %s:%d.\n" msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #: src/include/gnunet_common.h:593 #, c-format msgid "External protocol violation detected at %s:%d.\n" msgstr "" #: src/include/gnunet_common.h:620 src/include/gnunet_common.h:629 #, c-format msgid "`%s' failed on file `%s' at %s:%d with error: %s\n" msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n" #, fuzzy #~ msgid "# TRAIL SETUP requests received" #~ msgstr "# byte mottogs via TCP" #, fuzzy #~ msgid "# TRAIL SETUP bytes received" #~ msgstr "# byte mottogs via TCP" #, fuzzy #~ msgid "provide information about a particular channel" #~ msgstr "Skriv ut information om GNUnets motparter." #, fuzzy #~ msgid "provide information about all tunnels (continuously) NOT IMPLEMENTED" #~ msgstr "Skriv ut information om GNUnets motparter." #, fuzzy #~ msgid "Could not find option `%s:%s' in configuration.\n" #~ msgstr "Kunde inte hitta motpart \"%s\" i routingtabell!\n" #, fuzzy #~ msgid "Peer `%s' disconnected\n" #~ msgstr "# av anslutna parter" #, fuzzy #~ msgid "Transport plugin: `%s' port %llu\n" #~ msgstr "Testar transport(er) %s\n" #, fuzzy #~ msgid "Found %u transport plugins: `%s'\n" #~ msgstr "Testar transport(er) %s\n" #, fuzzy #~ msgid "Failed to parse HELLO in file `%s': %s %u \n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Internal error %d\n" #~ msgstr "Okänt fel.\n" #, fuzzy #~ msgid "Aborting call to `%s'\n" #~ msgstr "Fel vid skapandet av användare" #, fuzzy #~ msgid "You are already in a conversation with `%s'.\n" #~ msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #, fuzzy #~ msgid "Print information about mesh tunnels and peers." #~ msgstr "Skriv ut information om GNUnets motparter." #, fuzzy #~ msgid "" #~ "%s service is lacking key configuration settings (%s). Using default " #~ "(%u).\n" #~ msgstr "GNUnet-konfiguration" #, fuzzy #~ msgid "Loading block plugin `%s'\n" #~ msgstr "Testar transport(er) %s\n" #, fuzzy #~ msgid "Invalid value `%s'\n" #~ msgstr "Ogiltigt argument: \"%s\"\n" #, fuzzy #~ msgid "Found issuer for public key `%s'\n" #~ msgstr "Testar transport(er) %s\n" #, fuzzy #~ msgid "No issuer for public key `%s'\n" #~ msgstr "%d filer hittades i katalog.\n" #, fuzzy #~ msgid "Invalid work requirement for NSE service. Exiting.\n" #~ msgstr "Ogiltiga argument. Avslutar.\n" #, fuzzy #~ msgid "Failed to get slave counters!\n" #~ msgstr "Kunde inte skapa värdnyckel!\n" #, fuzzy #~ msgid "" #~ "Could not translate E[a%d] to MPI!\n" #~ "%s/%s\n" #~ msgstr "Kunde inte köra \"%s\": %s\n" #, fuzzy #~ msgid "Job command file not given. Exiting\n" #~ msgstr "använd konfigurationsfil FILNAMN" #, fuzzy #~ msgid "Error while decoding key %u\n" #~ msgstr "Fel vid nedladdning: %s\n" #, fuzzy #~ msgid "Could not read friends list `%s'\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Failed to read friends list from `%s': out of memory\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #~ msgid "Failed to read friends list from `%s'\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "ECC signature verification failed at %s:%d: %s\n" #~ msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #, fuzzy #~ msgid "No `%s' specified for service `%s' in configuration.\n" #~ msgstr "Inga applikationer definierade i konfiguration!\n" #, fuzzy #~ msgid "# peers connected to mesh tunnels" #~ msgstr "# av anslutna parter" #, fuzzy #~ msgid "Failed to parse metadata about pseudonym from file `%s': %s\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "no-name" #~ msgstr "Visa namn" #, fuzzy #~ msgid "Option `%s' ignored\n" #~ msgstr "%s: flagga \"%s\" är tvetydig\n" #, fuzzy #~ msgid "specify ID of the root of the namespace" #~ msgstr "ange prioritet för innehÃ¥llet" #, fuzzy #~ msgid "try to shorten a given name" #~ msgstr "Misslyckades att ansluta till gnunetd.\n" #, fuzzy #~ msgid "Failed to read or create private zone key\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Unable to initialize resolver!\n" #~ msgstr "Kunde inte initiera SQLite.\n" #, fuzzy #~ msgid "Using default zone file `%s'\n" #~ msgstr "Startade samling \"%s\".\n" #, fuzzy #~ msgid "Failed to write zone key to file `%s': %s\n" #~ msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #, fuzzy #~ msgid "No directory to load zonefiles specified in configuration\n" #~ msgstr "Inga applikationer definierade i konfiguration!\n" #, fuzzy #~ msgid "name of the template configuration file to use (optional)" #~ msgstr "skriv ut ett värde frÃ¥n konfigurationsfilen till standard ut" #, fuzzy #~ msgid "number of peers to start" #~ msgstr "antal iterationer" #, fuzzy #~ msgid "Failed to read or generate private key: %s\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Transport service is unable to access hostkey. Exiting.\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "Failed to create or read private key for namespace `%s'\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Failed to create namespace `%s' (illegal filename?)\n" #~ msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #, fuzzy #~ msgid "# Replies received from STREAM" #~ msgstr "# byte mottagna via HTTP" #, fuzzy #~ msgid "Mesh service could not access hostkey: %s. Exiting.\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "No valid expiration time for operation `%s'\n" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "Failed to find record to remove\n" #~ msgstr "Kunde inte ansluta till gnunetd.\n" #, fuzzy #~ msgid "Could not parse zone key file `%s'\n" #~ msgstr "Kunde inte tolka konfigurationsfil \"%s\".\n" #, fuzzy #~ msgid "Failed to create new signature" #~ msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #, fuzzy #~ msgid "Failed to put new set of records in database" #~ msgstr "Misslyckades att skicka HTTP-begäran till värd \"%s\": %s\n" #, fuzzy #~ msgid "Failed to remove records from database" #~ msgstr "Misslyckades att ta emot svar till \"%s\" meddelande frÃ¥n gnunetd\n" #, fuzzy #~ msgid "Failed to access database" #~ msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #, fuzzy #~ msgid "unknown internal error in namestore" #~ msgstr "=\tFel vid läsning av katalog.\n" #, fuzzy #~ msgid "NSE service could not access hostkey: %s\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "" #~ "Error loading search strings.Given file does not contain enough strings. " #~ "Exiting.\n" #~ msgstr "Fel vid lämning av DHT.\n" #, fuzzy #~ msgid "Transport service could not access hostkey: %s. Exiting.\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (too long, %llu bytes). " #~ "Deleting it.\n" #~ msgstr "Filen \"%s\" innehÃ¥ller ingen pseudonym.\n" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (failed decode, %llu " #~ "bytes). Deleting it.\n" #~ msgstr "Filen \"%s\" innehÃ¥ller ingen pseudonym.\n" #, fuzzy #~ msgid "File `%s' does not contain a valid private key. Deleting it.\n" #~ msgstr "Filen \"%s\" innehÃ¥ller ingen pseudonym.\n" #, fuzzy #~ msgid "gnunet-ecc failed" #~ msgstr "gnunet-update misslyckades!" #, fuzzy #~ msgid "" #~ "File `%s' does not contain a valid private key (too long, %llu bytes). " #~ "Renaming it.\n" #~ msgstr "Filen \"%s\" innehÃ¥ller ingen pseudonym.\n" #, fuzzy #~ msgid "gnunet-rsa failed" #~ msgstr "gnunet-update misslyckades!" # drive = hard drive ? #, fuzzy #~ msgid "`%s' failed for drive `%S': %u\n" #~ msgstr "\"%s\" misslyckades för enhet %s: %u\n" #, fuzzy #~ msgid "Service `%s' was already running.\n" #~ msgstr "\"%s\" är inte en fil.\n" #, fuzzy #~ msgid "Service `%s' has been started.\n" #~ msgstr "Tjänst borttagen.\n" #, fuzzy #~ msgid "Service `%s' was already being stopped.\n" #~ msgstr "Tjänst borttagen.\n" #, fuzzy #~ msgid "Service `%s' was already not running.\n" #~ msgstr "\"%s\" är inte en fil.\n" #, fuzzy #~ msgid "Error communicating with ARM service.\n" #~ msgstr "Skriv ut information om GNUnets motparter." #, fuzzy #~ msgid "Timeout communicating with ARM service.\n" #~ msgstr "Skriv ut information om GNUnets motparter." #, fuzzy #~ msgid "Error in communication with PEERINFO service\n" #~ msgstr "Skriv ut information om GNUnets motparter." #, fuzzy #~ msgid "%s Received message from %s of type %d, distance %u!\n" #~ msgstr "Mottog skadat meddelande frÃ¥n motpart \"%s\"i %s:%d.\n" #, fuzzy #~ msgid "Creating a peer failed. Error: %s\n" #~ msgstr "" #~ "\n" #~ "Fel vid uppladdning av fil: %s\n" #, fuzzy #~ msgid "Exiting\n" #~ msgstr "" #~ "\n" #~ "Avslutar.\n" #, fuzzy #~ msgid "Could not read blacklist file `%s'\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Failed to read blacklist from `%s'\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Syntax error in blacklist file at offset %llu, giving up!\n" #~ msgstr "Syntaxfel i konfigurationsfil \"%s\" pÃ¥ rad %d.\n" #, fuzzy #~ msgid "Failed to read hostkey: %s\n" #~ msgstr "Misslyckades att starta samling.\n" #, fuzzy #~ msgid "# session keys received" #~ msgstr "# sessionnycklar vägrade" #, fuzzy #~ msgid "`%s' is for `%s', not for me. Ignoring.\n" #~ msgstr "storlek pÃ¥ \"%s\" meddelande är för litet. Ignorerar.\n" #, fuzzy #~ msgid "# SET_KEY and PING messages created" #~ msgstr "# PING-meddelanden skapade" #, fuzzy #~ msgid "Message received far too old (%s). Content ignored.\n" #~ msgstr "Meddelande mottaget frÃ¥n klient är ogiltig.\n" #, fuzzy #~ msgid "Unknown error" #~ msgstr "Okänt fel" #, fuzzy #~ msgid "Failed to serialize meta data" #~ msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #, fuzzy #~ msgid "Failed to connect to datastore service" #~ msgstr "Misslyckades att ansluta till gnunetd.\n" #, fuzzy #~ msgid "Failed to parse URI `%s' from KBlock!\n" #~ msgstr "Fil \"%s\" har URI: %s\n" #, fuzzy #~ msgid "Regexprofiler could not access hostkey: %s. Exiting.\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "Could not access STATISTICS service. Exiting.\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "Failed to open named pipe `%s' for reading: %s\n" #~ msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #, fuzzy #~ msgid "Failed to open named pipe `%s' for writing: %s\n" #~ msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #, fuzzy #~ msgid "session identifier" #~ msgstr "# sessioner etablerade" #, fuzzy #~ msgid "Mesh service could not access hostkey. Exiting.\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "" #~ "provide inthe 'struct GNUNET_TRANSPORT_PeerIterateContextformation about " #~ "all tunnels (continuously)" #~ msgstr "Skriv ut information om GNUnets motparter." #, fuzzy #~ msgid "I am host `%s'. Read private key from `%s'.\n" #~ msgstr "Anrop till \"%s\" med nyckel \"%s\".\n" #, fuzzy #~ msgid "Asked to start service `%s' within %llu ms\n" #~ msgstr "\"%s\": Mottog inte meddelande inom %llu ms.\n" #, fuzzy #~ msgid "Stopping service `%s' within %llu ms\n" #~ msgstr "Inget svar mottaget inom %llums.\n" #, fuzzy #~ msgid "Configuration file `%s' for service `%s' not valid: %s\n" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "Could not transmit confirmation receipt\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "Unknown message type: '%u'\n" #~ msgstr "Okänd operation \"%s\"\n" #, fuzzy #~ msgid "Configuration option `%s' in section `%s' missing\n" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "Failed to access chat home directory `%s'\n" #~ msgstr "Filformatsfel (inte en GNUnet-katalog?)\n" #, fuzzy #~ msgid "Failed to create/open key in file `%s'\n" #~ msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #, fuzzy #~ msgid "Could not serialize metadata\n" #~ msgstr "Kunde inte initiera libgnunetutil!\n" #, fuzzy #~ msgid "(%s) `%s' said: %s\n" #~ msgstr "\"%s\" %s misslyckades: %s\n" #, fuzzy #~ msgid "(%s) `%s' said to you: %s\n" #~ msgstr "\"%s\" %s misslyckades: %s\n" # drive = hard drive ? #, fuzzy #~ msgid "(%s) `%s' said for sure: %s\n" #~ msgstr "\"%s\" misslyckades för enhet %s: %u\n" # drive = hard drive ? #, fuzzy #~ msgid "(%s) `%s' said to you for sure: %s\n" #~ msgstr "\"%s\" misslyckades för enhet %s: %u\n" #, fuzzy #~ msgid "(%s) `%s' said off the record: %s\n" #~ msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #, fuzzy #~ msgid "Could not change username\n" #~ msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #, fuzzy #~ msgid "Joining room `%s' as user `%s'...\n" #~ msgstr "Ogiltigt svar till \"%s\" frÃ¥n motpart \"%s\".\n" #, fuzzy #~ msgid "Changed username to `%s'\n" #~ msgstr "Kan inte ändra användare/grupp till \"%s\": %s\n" #, fuzzy #~ msgid "Failed to join room `%s'\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Failed to queue a message notification\n" #~ msgstr "Kunde inte spara konfiguration!" #, fuzzy #~ msgid "Failed to queue a join notification\n" #~ msgstr "Kunde inte spara konfiguration!" #, fuzzy #~ msgid "Failed to queue a confirmation receipt\n" #~ msgstr "Kunde inte spara konfiguration!" #, fuzzy #~ msgid "Failed to queue a leave notification\n" #~ msgstr "Kunde inte spara konfiguration!" #, fuzzy #~ msgid "Connected to %s service!\n" #~ msgstr "\"%s\" ansluten till \"%s\".\n" #, fuzzy #~ msgid "Configuration fails to specify `%s' in section `%s'\n" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "Configuration fails to specify `%s', assuming default value." #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "Option `%s' not specified in configuration section `%s'\n" #~ msgstr "Inga applikationer definierade i konfiguration!\n" #, fuzzy #~ msgid "Peer is lacking HOSTKEY configuration setting.\n" #~ msgstr "GNUnet-konfiguration" #, fuzzy #~ msgid "`scp' did not complete cleanly.\n" #~ msgstr "\"%s\" är inte ansluten till nÃ¥gon ändpunkt.\n" #, fuzzy #~ msgid "Failed to create pipe for `gnunet-peerinfo' process.\n" #~ msgstr "Misslyckades att starta samling.\n" #, fuzzy #~ msgid "Could not start `%s' process to create hostkey.\n" #~ msgstr "Kunde inte skapa värdnyckel!\n" #, fuzzy #~ msgid "Failed to start `ssh' process.\n" #~ msgstr "Misslyckades att starta samling.\n" #, fuzzy #~ msgid "Malformed output from gnunet-peerinfo!\n" #~ msgstr "Misslyckades att starta samling.\n" #, fuzzy #~ msgid "Could not start `%s' process to start GNUnet.\n" #~ msgstr "Kunde inte skapa värdnyckel!\n" #, fuzzy #~ msgid "Failed to start `gnunet-arm' process.\n" #~ msgstr "Misslyckades att ansluta till gnunetd.\n" #, fuzzy #~ msgid "shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n" #~ msgstr "\"%s\" är inte ansluten till nÃ¥gon ändpunkt.\n" #, fuzzy #~ msgid "Could not start `%s' process to copy configuration directory.\n" #~ msgstr "Kunde inte skapa värdnyckel!\n" #, fuzzy #~ msgid "Terminating peer `%4s'\n" #~ msgstr "Ã…tkomst nekad för \"%s\" vid %s:%d.\n" #, fuzzy #~ msgid "Setting d->dead on peer `%4s'\n" #~ msgstr "Startade samling \"%s\".\n" #, fuzzy #~ msgid "Failed to write new configuration to disk." #~ msgstr "Kunde inte spara konfiguration!" #, fuzzy #~ msgid "Could not start `%s' process to copy configuration file.\n" #~ msgstr "Kunde inte skapa värdnyckel!\n" #, fuzzy #~ msgid "Failed to copy new configuration to remote machine." #~ msgstr "Kunde inte spara konfiguration!" #, fuzzy #~ msgid "Peers failed to connect" #~ msgstr "Misslyckades att ansluta till gnunetd.\n" #, fuzzy #~ msgid "Failed to connect to core service of first peer!\n" #~ msgstr "Misslyckades att starta samling.\n" #, fuzzy #~ msgid "Invalid value `%s' for option `%s' in section `%s': expected float\n" #~ msgstr "Konfigurationsfil \"%s\" hittades inte. Kör \"gnunet-setup -d\"!\n" #, fuzzy #~ msgid "Could not create configuration for peer number %u on `%s'!\n" #~ msgstr "Kunde inte komma Ã¥t namnrymdsinformation.\n" #, fuzzy #~ msgid "Failed to find option %s in section %s!\n" #~ msgstr "Misslyckades att binda till UDP-port %d.\n" #, fuzzy #~ msgid "Invalid configuration option `%s' in section `%s'\n" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "Missing configuration option `%s' in section `%s'\n" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "internal error" #~ msgstr "Okänt fel.\n" #, fuzzy #~ msgid "Could not create namespace `%s'\n" #~ msgstr "Kunde inte skapa namnrymd \"%s\" (existerar?).\n" #, fuzzy #~ msgid "Stored zonekey for zone `%s' in file `%s'\n" #~ msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #, fuzzy #~ msgid "Could not read hostkeys file, specify hostkey file with -H!\n" #~ msgstr "Kunde inte skapa värdnyckel!\n" #, fuzzy #~ msgid "access (%s, X_OK) failed: %s\n" #~ msgstr "\"%s\" %s misslyckades: %s\n" #, fuzzy #~ msgid "# Peers connected" #~ msgstr "# av anslutna parter" #, fuzzy #~ msgid "%s failed for `%s' at %s:%d: `%s'\n" #~ msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #, fuzzy #~ msgid "Failed to transmit shutdown ACK.\n" #~ msgstr "Misslyckades att starta samling.\n" #, fuzzy #~ msgid "Unable to initialize Postgres with configuration `%s': %s" #~ msgstr "Kunde inte spara konfigurationsfil \"%s\":" #, fuzzy #~ msgid "Target is %d connections per peer." #~ msgstr "Misslyckades att starta samling.\n" #, fuzzy #~ msgid "Copying file with RENAME (%s,%s)\n" #~ msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #, fuzzy #~ msgid "Copying file with command scp %s %s\n" #~ msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #, fuzzy #~ msgid "Finished copying all blacklist files!\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Failed during blacklist file copying!\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "# bytes payload received for other peers" #~ msgstr "# byte mottagna av typen %d" #, fuzzy #~ msgid "# peers disconnected due to timeout" #~ msgstr "# av anslutna parter" #, fuzzy #~ msgid "# peers disconnected due to global disconnect" #~ msgstr "Nätverksannonsering avstängd i konfigurationen!\n" #, fuzzy #~ msgid "# unexpected CONNECT_ACK messages" #~ msgstr "skicka ANTAL meddelanden" #, fuzzy #~ msgid "# wlan session created" #~ msgstr "# sessionsnycklar accepterade" #, fuzzy #~ msgid "# wlan pending fragments" #~ msgstr "# byte mottogs via TCP" #, fuzzy #~ msgid "# wlan whole messages received" #~ msgstr "# krypterade PONG-meddelanden mottagna" #, fuzzy #~ msgid "# wlan hello messages received" #~ msgstr "# krypterade PONG-meddelanden mottagna" #, fuzzy #~ msgid "# wlan fragments received" #~ msgstr "# byte mottogs via TCP" #, fuzzy #~ msgid "# wlan acks received" #~ msgstr "# klartext PONG-meddelanden mottagna" #, fuzzy #~ msgid "# wlan messages for this client received" #~ msgstr "# krypterade PONG-meddelanden mottagna" #, fuzzy #~ msgid "# wlan messages inside WLAN_HELPER_DATA received" #~ msgstr "# krypterade PONG-meddelanden mottagna" #, fuzzy #~ msgid "Could not access file: %s\n" #~ msgstr "Kunde inte köra \"%s\": %s\n" # drive = hard drive ? #, fuzzy #~ msgid "`%s' failed on file `%s': %s" #~ msgstr "\"%s\" misslyckades för enhet %s: %u\n" #, fuzzy #~ msgid "# bytes TCP was asked to transmit" #~ msgstr "# byte skickade av typen %d" #, fuzzy #~ msgid "# bytes discarded by TCP (failed to connect)" #~ msgstr "# byte kastade via TCP (utgÃ¥ende)" #, fuzzy #~ msgid "# wlan messages queued" #~ msgstr "# krypterade PONG-meddelanden mottagna" #~ msgid "print this help" #~ msgstr "skriv ut denna hjälp" #~ msgid "print the version number" #~ msgstr "skriv ut versionsnummer" #~ msgid "be verbose" #~ msgstr "var informativ" #, fuzzy #~ msgid "Failed to start service `%s'!\n" #~ msgstr "Misslyckades att starta samling.\n" #, fuzzy #~ msgid "Service `%s' stopped\n" #~ msgstr "Tjänst borttagen.\n" #, fuzzy #~ msgid "Unable to accept connection for service `%s': %s\n" #~ msgstr "Kunde inte spara konfigurationsfil \"%s\":" #, fuzzy #~ msgid "Failed to create IPv4 broadcast socket on port %d\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Failed to load block plugin `%s'\n" #~ msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #, fuzzy #~ msgid "Could not resolve our FQDN : %s %u\n" #~ msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #, fuzzy #~ msgid "Failed to load dhtlog plugin for `%s'\n" #~ msgstr "Misslyckades att läsa kompislista frÃ¥n \"%s\"\n" #, fuzzy #~ msgid "Found peer `%s'\n" #~ msgstr "Jag är ändpunkt \"%s\".\n" #, fuzzy #~ msgid "Loading udp transport plugin\n" #~ msgstr "Testar transport(er) %s\n" #, fuzzy #~ msgid "curl failed for `%s' at %s:%d: `%s'\n" #~ msgstr "\"%s\" misslyckades vid %s:%d med fel: \"%s\".\n" #, fuzzy #~ msgid "Phase 3: sending messages\n" #~ msgstr "Misslyckades att leverera \"%s\" meddelande.\n" #, fuzzy #~ msgid "Loading HTTPS transport plugin `%s'\n" #~ msgstr "Testar transport(er) %s\n" #, fuzzy #~ msgid "Failed to load transport plugin for https\n" #~ msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #, fuzzy #~ msgid "Fail! Could not connect peers\n" #~ msgstr "\"%s\": Kunde inte ansluta.\n" #, fuzzy #~ msgid "Loading tcp transport plugin\n" #~ msgstr "Testar transport(er) %s\n" #, fuzzy #~ msgid "Failed to load transport plugin for tcp\n" #~ msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #, fuzzy #~ msgid "Misconfigured address to bind to in configuration!\n" #~ msgstr "Inga applikationer definierade i konfiguration!\n" #, fuzzy #~ msgid "Failed to load transport plugin for http\n" #~ msgstr "Kunde inte slÃ¥ upp \"%s\": %s\n" #, fuzzy #~ msgid "# PING messages decrypted" #~ msgstr "# PING-meddelanden skapade" #, fuzzy #~ msgid "# bytes successfully transmitted by plugins" #~ msgstr "# byte skickade av typen %d" #, fuzzy #~ msgid "# connected addresses" #~ msgstr "# av anslutna parter" #, fuzzy #~ msgid "# transport failed to selected peer address" #~ msgstr "Annonserar min transport %d till valda ändpunkter.\n" #, fuzzy #~ msgid "# PING with HELLO messages sent" #~ msgstr "# PING-meddelanden skapade" #, fuzzy #~ msgid "Received `%s' message from `%s' destined for `%s' which is not me!\n" #~ msgstr "Mottog PING som ej var ämnat för oss!\n" #, fuzzy #~ msgid "Could not send PONG to `%s': no address available\n" #~ msgstr "Kunde inte hitta motpart \"%s\" i routingtabell!\n" #~ msgid "Error" #~ msgstr "Fel" #~ msgid "Help" #~ msgstr "Hjälp" #, fuzzy #~ msgid "Error!" #~ msgstr "Fel" #~ msgid "No" #~ msgstr "Nej" #~ msgid "Yes" #~ msgstr "Ja" #, fuzzy #~ msgid "Abort" #~ msgstr "_Om" #, fuzzy #~ msgid "Ok" #~ msgstr "k" #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://gnunet.org/\n" #~ "and join our community at\n" #~ "\thttp://gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "the GNUnet team" #~ msgstr "" #~ "Välkommen till GNUnet!\n" #~ "\n" #~ "Denna assistant kommer att frÃ¥ga dig nÃ¥gra enkla frÃ¥gor för att " #~ "konfigurera GNUnet.\n" #~ "\n" #~ "Vänligen besök pÃ¥ webbplats pÃ¥\n" #~ "\thttp://gnunet.org/\n" #~ "och gÃ¥ med i vÃ¥r gemenskap pÃ¥\n" #~ "\thttp://gnunet.org/drupal/\n" #~ "\n" #~ "Ha det sÃ¥ kul,\n" #~ "\n" #~ "the GNUnet team" #, fuzzy #~ msgid "Network configuration: interface" #~ msgstr "Nätverksgränssnitt:" #, fuzzy #~ msgid "Network configuration: IP" #~ msgstr "GNUnet-konfiguration" #, fuzzy #~ msgid "Bandwidth configuration: upload" #~ msgstr "GNUnet-konfiguration" #, fuzzy #~ msgid "How much upstream bandwidth (in bytes/s) may be used?" #~ msgstr "Hur mycket CPU (i %) fÃ¥r användas?" #, fuzzy #~ msgid "Bandwidth configuration: download" #~ msgstr "GNUnet-konfiguration" #, fuzzy #~ msgid "How much downstream bandwidth (in bytes/s) may be used?" #~ msgstr "Hur mycket CPU (i %) fÃ¥r användas?" #, fuzzy #~ msgid "Quota configuration" #~ msgstr "GNUnet-konfiguration" #, fuzzy #~ msgid "Daemon configuration: user account" #~ msgstr "Kunde inte skapa användarkonto:" #, fuzzy #~ msgid "Save configuration?" #~ msgstr "GNUnet-konfiguration" #, fuzzy #~ msgid "GNUnet Configuration" #~ msgstr "GNUnet-konfiguration" #~ msgid "Back" #~ msgstr "Tillbaka" #~ msgid "Up" #~ msgstr "Upp" #~ msgid "Cancel" #~ msgstr "Avbryt" #, fuzzy #~ msgid "Configuration unchanged, no need to save.\n" #~ msgstr "" #~ "Konfiguration eller version av GNUnet ändrad. Du behöver köra \"%s\"!\n" #, fuzzy #~ msgid "Do you wish to save your new configuration?" #~ msgstr "Vill du spara dina inställningar?" #~ msgid "This version of Windows doesn't support services.\n" #~ msgstr "Denna version av Windows har inte stöd för tjänster.\n" #~ msgid "Error: can't create service: %s\n" #~ msgstr "Fel: kan inte skapa tjänst: %s\n" #~ msgid "Error: can't delete service: %s\n" #~ msgstr "Fel: kan inte ta bort tjänst: %s\n" #, fuzzy #~ msgid "Configuration changed. Save?" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "Error saving configuration." #~ msgstr "Kunde inte spara konfiguration!" #, fuzzy #~ msgid "(unknown connection)" #~ msgstr "Nätverksanslutning" #, fuzzy #~ msgid "Do you want to save the new configuration?" #~ msgstr "Vill du spara dina inställningar?" #~ msgid "Tool to setup GNUnet." #~ msgstr "Verktyg för att ställa in GNUnet." #, fuzzy #~ msgid "Too many arguments.\n" #~ msgstr "Ogiltiga kommandoradsargument.\n" #, fuzzy #~ msgid "Configuration file `%s' must be a filename (but is a directory).\n" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "yes" #~ msgstr "Ja" #, fuzzy #~ msgid "Yes\n" #~ msgstr "Ja" #, fuzzy #~ msgid "No\n" #~ msgstr "Nej" #, fuzzy #~ msgid "Help\n" #~ msgstr "Hjälp" #, fuzzy #~ msgid "Abort\n" #~ msgstr "_Om" #, fuzzy #~ msgid "Configuration was unchanged, no need to save.\n" #~ msgstr "" #~ "Konfiguration eller version av GNUnet ändrad. Du behöver köra \"%s\"!\n" #~ msgid "Can't create service" #~ msgstr "Kan inte skapa tjänst" #~ msgid "Error changing the permissions of the GNUnet directory" #~ msgstr "Fel vid ändring av rättigheterna pÃ¥ GNUnet-katalogen" #, fuzzy #~ msgid "Cannot write to the registry" #~ msgstr "Kan inte skriva till registret" #~ msgid "Can't delete the service" #~ msgstr "Kan inte ta bort tjänsten" #~ msgid "This version of Windows does not support multiple users." #~ msgstr "Denna version för Windows har inte stöd för flera användare." #~ msgid "Error accessing local security policy" #~ msgstr "Fel vid Ã¥tkomst av lokal säkerhetspolicy" #~ msgid "Unknown error while creating a new user" #~ msgstr "Okänt fel vid skapandet av ny användare" #~ msgid "FATAL" #~ msgstr "ÖDESDIGER" #~ msgid "NOTHING" #~ msgstr "INGET" #, fuzzy #~ msgid "Syntax error in configuration entry HOST in section NETWORK: `%s'\n" #~ msgstr "Syntaxfel i konfigurationsfil \"%s\" pÃ¥ rad %d.\n" #, fuzzy #~ msgid "Reading result from gnunetd failed, reply invalid!\n" #~ msgstr "\"%s\" misslyckades, svar ogiltigt!\n" #, fuzzy #~ msgid "No interface specified in section `%s' under `%s'!\n" #~ msgstr "" #~ "Inga nätverksgränssnitt angivna i konfigurationssektionen \"%s\" under " #~ "\"%s\"!\n" #, fuzzy #~ msgid "`%s' returned with error code %u" #~ msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #~ msgid "Can't create semaphore: %i" #~ msgstr "Kan inte skapa semafor: %i" #~ msgid "Cannot query the CPU usage (Windows NT).\n" #~ msgstr "Kan inte frÃ¥ga efter CPU-användning (Windows NT).\n" #~ msgid "Cannot query the CPU usage (Win 9x)\n" #~ msgstr "Kan inte frÃ¥ga efter CPU-användning (Win 9x).\n" #~ msgid "" #~ "No network interfaces defined in configuration section `%s' under `%s'!\n" #~ msgstr "" #~ "Inga nätverksgränssnitt angivna i konfigurationssektionen \"%s\" under " #~ "\"%s\"!\n" #, fuzzy #~ msgid "Command `%s' failed with error code %u\n" #~ msgstr "\"%s\" misslyckades vid %s:%d med fel: %s\n" #, fuzzy #~ msgid "Real-time delay violation (%llu ms) at %s:%u\n" #~ msgstr "Icke-förväntad mycket stor allokering (%u byte) vid %s:%d!\n" #~ msgid "Availability test failed for `%s' at %s:%d.\n" #~ msgstr "Tillgänglighetstest misslyckades för \"%s\" vid %s:%d.\n" #, fuzzy #~ msgid "Starting datastore conversion (this may take a while).\n" #~ msgstr "Skapar ny värdnyckel (det här kan ta en stund).\n" #, fuzzy #~ msgid "" #~ "%s:%d - RPC %s:%p could not be registered: another callback is already " #~ "using this name (%p)\n" #~ msgstr "%s::%s - RPC %s:%p kunde inte avregistreras: hittades inte\n" #, fuzzy #~ msgid "%s:%d - async RPC %s:%p could not be unregistered: not found\n" #~ msgstr "%s::%s - RPC %s:%p kunde inte avregistreras: hittades inte\n" #~ msgid "`%s' registering handlers %d %d %d\n" #~ msgstr "\"%s\" registrerar handtag %d %d %d\n" #~ msgid "output in gnuplot format" #~ msgstr "utdata i gnuplot-format" #~ msgid "number of messages to use per iteration" #~ msgstr "antal meddelanden att använda per iteration" #~ msgid "message size" #~ msgstr "meddelandestorlek" #~ msgid "number of messages in a message block" #~ msgstr "antal meddelanden i ett meddelandeblock" #~ msgid "You must specify a receiver!\n" #~ msgstr "Du mÃ¥ste ange en mottagare!\n" #~ msgid "Time:\n" #~ msgstr "Tid:\n" #~ msgid "\tmax %llums\n" #~ msgstr "\tmax %llums\n" #~ msgid "\tmin %llums\n" #~ msgstr "\tmin %llums\n" #~ msgid "\tmax %u\n" #~ msgstr "\tmax %u\n" #~ msgid "\tmin %u\n" #~ msgstr "\tmin %u\n" #~ msgid "Output format not known, this should not happen.\n" #~ msgstr "Utdataformat är inte känt, detta bör inte hända.\n" #, fuzzy #~ msgid "# bytes received in plaintext of type %d" #~ msgstr "# byte mottagna av typen %d" #, fuzzy #~ msgid "use PRIORITY for the priority of the trace request" #~ msgstr "ange prioritet för innehÃ¥llet" #~ msgid "allows mapping of the network topology" #~ msgstr "tillÃ¥ter kartläggning av nätverkstopologin" #, fuzzy #~ msgid "HELLO message from `%s' has an invalid signature. Dropping.\n" #~ msgstr "Meddelande frÃ¥n \"%s\" kastades bort: ogiltigt format.\n" #~ msgid "`%s' registering handler %d (plaintext and ciphertext)\n" #~ msgstr "\"%s\" registrerar handtag %d (klartext och kryptotext)\n" #~ msgid "`%s' registering handler %d\n" #~ msgstr "\"%s\" registrerar handtag %d\n" #, fuzzy #~ msgid "`%s' registering CS handlers %d and %d\n" #~ msgstr "\"%s\" registrerar handtagen %d och %d\n" #~ msgid "enables P2P-chat (incomplete)" #~ msgstr "aktiverar P2P-chatt (ej komplett)" #, fuzzy #~ msgid "Existing key in file `%s' failed format check, creating new key.\n" #~ msgstr "" #~ "Existerande värdnyckel i filen \"%s\" felade vid formatkontroll, skapar " #~ "en ny värdnyckel.\n" #, fuzzy #~ msgid "Creating new key for this nickname (this may take a while).\n" #~ msgstr "Skapar ny värdnyckel (det här kan ta en stund).\n" #, fuzzy #~ msgid "allow TIME ms to process a GET command" #~ msgstr "tillÃ¥t TID ms för behandling av varje kommando" #, fuzzy #~ msgid "Issuing `%s(%s,%s)' command.\n" #~ msgstr "\"%s(%s,%s)\" misslyckades.\n" #~ msgid "Command `%s' requires an argument (`%s').\n" #~ msgstr "Kommando \"%s\" kräver ett argument (\"%s\").\n" #~ msgid "Command `%s' requires two arguments (`%s' and `%s').\n" #~ msgstr "Kommando \"%s\" kräver tvÃ¥ argument (\"%s\" och \"%s\").\n" #, fuzzy #~ msgid "# dht discovery messages sent" #~ msgstr "# krypterade PONG-meddelanden skickade" #, fuzzy #~ msgid "`%s' registering p2p handlers: %d %d %d\n" #~ msgstr "\"%s\" registrerar handtag %d %d %d\n" #~ msgid "`%s' failed. Terminating connection to client.\n" #~ msgstr "\"%s\" misslyckades. Terminerar anslutning till klient.\n" #, fuzzy #~ msgid "`%s' registering client handlers: %d %d\n" #~ msgstr "\"%s\" registrerar klienthandtag %d\n" #~ msgid "" #~ "Existing hostkey in file `%s' failed format check, creating new hostkey.\n" #~ msgstr "" #~ "Existerande värdnyckel i filen \"%s\" felade vid formatkontroll, skapar " #~ "en ny värdnyckel.\n" #~ msgid "Done creating hostkey.\n" #~ msgstr "Klar med skapandet av värdnyckel.\n" #~ msgid "Cannot create PING, table full. Try increasing MAX_PING_PONG.\n" #~ msgstr "" #~ "Kan inte skapa PING, tabell är full. Försök att öka MAX_PING_PONG.\n" #~ msgid "# plaintext PONG messages received" #~ msgstr "# klartext PONG-meddelanden mottagna" #~ msgid "# encrypted PING messages received" #~ msgstr "# krypterade PING-meddelanden mottagna" #~ msgid "# encrypted PING messages sent" #~ msgstr "# krypterade PING-meddelanden skickade" #~ msgid "`%s' registering handlers %d %d (plaintext and ciphertext)\n" #~ msgstr "\"%s\" registrerar handtag %d %d (klartext och kryptotext)\n" #, fuzzy #~ msgid "Cannot encrypt sessionkey, peer `%s' not known!\n" #~ msgstr "Kan inte kryptera sessionsnyckel, andra parten är inte känd!\n" #, fuzzy #~ msgid "" #~ "Session key received from peer `%s' has invalid format (discarded).\n" #~ msgstr "Meddelande mottaget frÃ¥n motpart är ogiltig.\n" #~ msgid "create a new pseudonym under the given NICKNAME" #~ msgstr "skapa en ny pseudonym under angivet SMEKNAMN" #~ msgid "delete the pseudonym with the given NICKNAME" #~ msgstr "ta bort pseudonymen med angivet SMEKNAMN" #~ msgid "" #~ "Create new pseudonyms, delete pseudonyms or list existing pseudonyms." #~ msgstr "" #~ "Skapa nya pseudonymer, ta bort pseudonymer eller lista existerande " #~ "pseudonymer." #~ msgid "Failed to stop collection (not active?).\n" #~ msgstr "Misslyckades att stoppa samling (inte aktiv?).\n" #~ msgid "Error deleting pseudonym `%s' (does not exist?).\n" #~ msgstr "Fel vid borttagning av pseudonym \"%s\" (existerar den?).\n" #, fuzzy #~ msgid "Started collection.\n" #~ msgstr "Startade samling \"%s\".\n" #, fuzzy #~ msgid "You must specify a name for the collection (`%s' option).\n" #~ msgstr "" #~ "Du mÃ¥ste ange ett namn för PID-filen i sektion \"%s\" under \"%s\".\n" #~ msgid "Perform directory related operations." #~ msgstr "Genomför katalogrelaterade operationer." #~ msgid "Listed %d matching entries.\n" #~ msgstr "Listade %d matchande poster.\n" #, fuzzy #~ msgid "Upload of `%s' at %llu out of %llu bytes.\n" #~ msgstr "Hämtning av fil \"%s\" vid %16llu av %16llu byte (%8.3f kbps)\n" #, fuzzy #~ msgid "Upload aborted.\n" #~ msgstr "Nedladdning avbruten." #, fuzzy #~ msgid "Uploading suspended.\n" #~ msgstr "Uppladdning misslyckades.\n" #, fuzzy #~ msgid "" #~ "do not use libextractor to add additional references to directory entries " #~ "and/or the published file" #~ msgstr "" #~ "använd libextractor för att lägga till ytterligare direktreferenser till " #~ "katalogposter" #~ msgid "Created entry `%s' in namespace `%s'\n" #~ msgstr "Skapade post \"%s\" i namnrymd \"%s\"\n" #, fuzzy #~ msgid "" #~ "%16llu of %16llu bytes inserted (estimating %6s to completion) - %s\n" #~ msgstr "%16llu av %16llu byte inlagda (uppskattar %s till färdigställd)\n" #, fuzzy #~ msgid "" #~ "Upload of `%s' complete, %llu bytes took %llu seconds (%8.3f KiB/s).\n" #~ msgstr "" #~ "Uppladdning av \"%s\" klar, %llu byte tog %llu sekunder (%8.3f kbps).\n" #, fuzzy #~ msgid "" #~ "\n" #~ "Upload aborted.\n" #~ msgstr "Nedladdning avbruten." #, fuzzy #~ msgid "" #~ "\n" #~ "Error uploading file: %s" #~ msgstr "" #~ "\n" #~ "Fel vid uppladdning av fil: %s\n" #~ msgid "" #~ "even if gnunetd is running on the local machine, force the creation of a " #~ "copy instead of making a link to the GNUnet share directory" #~ msgstr "" #~ "även om gnunetd körs pÃ¥ den lokala maskinen, tvinga fram skapandet av en " #~ "kopia istället för att göra en länk till GNUnets utdelade katalog" #~ msgid "Make files available to GNUnet for sharing." #~ msgstr "Gör filer tillgängliga via utdelning till GNUnet." #~ msgid "Search GNUnet for files." #~ msgstr "Sök GNUnet efter filer." #~ msgid "" #~ "%16llu of %16llu bytes unindexed (estimating %llu seconds to " #~ "completion) " #~ msgstr "" #~ "%16llu av %16llu byte avindexerat (uppskattar %llu sekunder till " #~ "färdigställd) " #, fuzzy #~ msgid "" #~ "\n" #~ "Unindexing of `%s' complete, %llu bytes took %llu seconds (%8.3f KiB/s).\n" #~ msgstr "" #~ "\n" #~ "Avindexering av \"%s\" klar, %llu byte tog %llu sekunder (%8.3f kbps).\n" #, fuzzy #~ msgid "Not enough arguments. You must specify a filename.\n" #~ msgstr "" #~ "Inte tillräckligt med argument. Du mÃ¥ste ange en URI till en GNUnet-fil\n" #~ msgid "`%s' failed. Is `%s' a file?\n" #~ msgstr "\"%s\" misslyckades. Är \"%s\" en fil?\n" #~ msgid "Download files from GNUnet." #~ msgstr "Ladda ner filer frÃ¥n GNUnet." #, fuzzy #~ msgid "Download of file `%s' at %16llu out of %16llu bytes (%8.3f KiB/s)\n" #~ msgstr "Hämtning av fil \"%s\" vid %16llu av %16llu byte (%8.3f kbps)\n" #, fuzzy #~ msgid "Download aborted.\n" #~ msgstr "Nedladdning avbruten." #, fuzzy #~ msgid "Download of file `%s' complete. Speed was %8.3f KiB per second.\n" #~ msgstr "" #~ "Hämtning av fil \"%s\" färdig. Hastigheten var %8.3f kilobyte per " #~ "sekund.\n" #~ msgid "Not enough arguments. You must specify a GNUnet file URI\n" #~ msgstr "" #~ "Inte tillräckligt med argument. Du mÃ¥ste ange en URI till en GNUnet-fil\n" #~ msgid "URI `%s' invalid for gnunet-download.\n" #~ msgstr "URI \"%s\" ogiltig för gnunet-download.\n" #, fuzzy #~ msgid "No filename specified, using `%s' instead (for now).\n" #~ msgstr "Inget tabellnamn angivet, använder \"%s\".\n" #, fuzzy #~ msgid "Downloading %d files from directory `%s'.\n" #~ msgstr "Ladda ner filer frÃ¥n GNUnet." #~ msgid "File stored as `%s'.\n" #~ msgstr "Fil lagrad som \"%s\".\n" #~ msgid "Cannot get size of file `%s'" #~ msgstr "Kan inte hämta storlek pÃ¥ fil \"%s\"" #~ msgid "Initialization for indexing file `%s' failed.\n" #~ msgstr "Initiering av indexering av fil \"%s\" misslyckades.\n" #, fuzzy #~ msgid "Cannot open file `%s': `%s'" #~ msgstr "Kan inte öppna konfigurationsfil \"%s\".\n" #~ msgid "Renaming of file `%s' to `%s' failed: %s\n" #~ msgstr "Namnbyte pÃ¥ fil \"%s\" till \"%s\" misslyckades: %s\n" #~ msgid "Could not rename file `%s' to `%s': file exists\n" #~ msgstr "Kunde inte byta namn pÃ¥ fil \"%s\" till \"%s\": filen existerar\n" #~ msgid "CHK URI not allowed for search.\n" #~ msgstr "CHK URI tillÃ¥ts inte för sökning.\n" #~ msgid "LOC URI not allowed for search.\n" #~ msgstr "LOC URI tillÃ¥ts inte för sökning.\n" #, fuzzy #~ msgid "Format of file `%s' is invalid, trying to remove.\n" #~ msgstr "Formatet pÃ¥ filen \"%s\" är ogiltig.\n" #~ msgid "" #~ "Decrypted content does not match key. This is either a bug or a " #~ "maliciously inserted file. Download aborted.\n" #~ msgstr "" #~ "Dekrypterat innehÃ¥ll stämmer inte med nyckeln. Det är antingen ett fel " #~ "eller en fil inlagd med onda avsikter. Hämtning avbruten.\n" #, fuzzy #~ msgid "" #~ "`%s' registering client handlers %d %d %d %d %d %d %d %d and P2P handlers " #~ "%d %d\n" #~ msgstr "\"%s\" registrerar klienthandtagen %d och %d\n" #~ msgid "enables (anonymous) file-sharing" #~ msgstr "aktiverar (anonym) fildelning" #, fuzzy #~ msgid "Friend list of %s:%d\n" #~ msgstr "Fel vid %s:%d.\n" #, fuzzy #~ msgid "Bootstrap data obtained from `%s' is invalid.\n" #~ msgstr "Formatet pÃ¥ pseudonym \"%s\" är ogiltig.\n" #~ msgid "`%s' registering client handler %d\n" #~ msgstr "\"%s\" registrerar klienthandtag %d\n" #~ msgid "`%s' registering client handler %d and %d\n" #~ msgstr "\"%s\" registrerar klienthandtagen %d och %d\n" #~ msgid "Uptime (seconds)" #~ msgstr "Upptid (sekunder)" #, fuzzy #~ msgid "`%s' registering client handlers %d %d %d and p2p handler %d\n" #~ msgstr "\"%s\" registrerar klienthandtagen %d och %d\n" #~ msgid "keeps statistics about gnunetd's operation" #~ msgstr "behÃ¥ller statistik om gnunetds operation" #~ msgid "prints supported protocol messages" #~ msgstr "skriver ut stödda protokollmeddelanden" #, fuzzy #~ msgid "Cannot open tunnel device: %s" #~ msgstr "Kan inte öppna konfigurationsfil \"%s\".\n" #, fuzzy #~ msgid "`%s' initialising RFC4913 module %d and %d\n" #~ msgstr "\"%s\" registrerar handtagen %d och %d\n" #, fuzzy #~ msgid "enables IPv6 over GNUnet (incomplete)" #~ msgstr "aktiverar P2P-chatt (ej komplett)" #~ msgid "Updates GNUnet datastructures after version change." #~ msgstr "Uppdaterar GNUnets datastruktur efter versionsändring." #~ msgid "run as user LOGIN" #~ msgstr "kör som användare LOGIN" #~ msgid "run in client mode (for getting client configuration values)" #~ msgstr "kör i klientläge (för att hämta värden frÃ¥n klientkonfiguration)" #~ msgid "Starts the gnunetd daemon." #~ msgstr "Startar gnunetd-demonen." #, fuzzy #~ msgid "specify username as which gnunetd should run" #~ msgstr "ange värd pÃ¥ vilken gnunetd körs" #~ msgid "Configuration or GNUnet version changed. You need to run `%s'!\n" #~ msgstr "" #~ "Konfiguration eller version av GNUnet ändrad. Du behöver köra \"%s\"!\n" #, fuzzy #~ msgid "Unable to obtain filesystem information for `%s': %u\n" #~ msgstr "Kunde inte spara konfigurationsfil \"%s\":" #, fuzzy #~ msgid "`%s' message invalid (signature invalid).\n" #~ msgstr "\"%s\" misslyckades, svar ogiltigt!\n" #~ msgid "`%s' selected %d out of %d messages (MTU: %d).\n" #~ msgstr "\"%s\" valda %d av %d meddelanden (MTU: %d).\n" #~ msgid "Message details: %u: length %d, priority: %d\n" #~ msgstr "Detaljer om meddelande: %u: längd %d, prioritet: %d\n" #~ msgid "Message from `%s' discarded: invalid format.\n" #~ msgstr "Meddelande frÃ¥n \"%s\" kastades bort: ogiltigt format.\n" #, fuzzy #~ msgid "# total number of messages in send buffers" #~ msgstr "antal meddelanden i ett meddelandeblock" #~ msgid "`%s': Could not send.\n" #~ msgstr "\"%s\": Kunde inte skicka.\n" #~ msgid "`%s': Could not disconnect.\n" #~ msgstr "\"%s\": Kunde inte koppla ned.\n" #, fuzzy #~ msgid "" #~ "`%s' transport OK. It took %ums to transmit %llu messages of %llu bytes " #~ "each.\n" #~ msgstr "" #~ "\"%s\" transport OK. Det tog %ums att överföra %d meddelanden pÃ¥ %d byte " #~ "styck.\n" #, fuzzy #~ msgid " Transport %d is not being tested\n" #~ msgstr " Transport %d ej tillgänglig\n" #~ msgid "" #~ "\n" #~ "Contacting `%s'." #~ msgstr "" #~ "\n" #~ "Kontaktar \"%s\"." #, fuzzy #~ msgid "OK!\n" #~ msgstr "OK" #~ msgid "send messages with SIZE bytes payload" #~ msgstr "skicka meddelanden med STORLEK bytes nyttolast" #~ msgid "specifies after how many MS to time-out" #~ msgstr "anger timeout efter antal MS" #~ msgid "Available transport(s): %s\n" #~ msgstr "Tillgängliga transport(er): %s\n" #, fuzzy #~ msgid "%s failed for url `%s' and post-data `%s' at %s:%d: `%s'\n" #~ msgstr "\"%s\" misslyckades för fil \"%s\" vid %s:%d med fel: %s\n" #~ msgid "# bytes sent via HTTP" #~ msgstr "# byte skickade via HTTP" #~ msgid "# bytes dropped by HTTP (outgoing)" #~ msgstr "# byte kastade via HTTP (utgÃ¥ende)" #, fuzzy #~ msgid "# HTTP connect calls" #~ msgstr "# av anslutna parter" #~ msgid "specify host on which gnunetd is running" #~ msgstr "ange värd pÃ¥ vilken gnunetd körs" #, fuzzy #~ msgid "No help available." #~ msgstr "\"%s\" är inte tillgänglig." #, fuzzy #~ msgid "Show rarely used options" #~ msgstr "Visa alla alternativ" #, fuzzy #~ msgid "Meta-configuration" #~ msgstr "GNUnet-konfiguration" #, fuzzy #~ msgid "Full pathname of GNUnet HOME directory" #~ msgstr "Filformatsfel (inte en GNUnet-katalog?)\n" #, fuzzy #~ msgid "Run gnunetd as this group." #~ msgstr "Kör gnunet-update" #, fuzzy #~ msgid "General settings" #~ msgstr "Andra inställningar" #, fuzzy #~ msgid "Settings for restricting connections to friends" #~ msgstr "\"%s\" misslyckades. Terminerar anslutning till klient.\n" #, fuzzy #~ msgid "Configuration of the MySQL database" #~ msgstr "Konfigurationsfil \"%s\" skapad.\n" #, fuzzy #~ msgid "Options for anonymous file sharing" #~ msgstr "aktiverar (anonym) fildelning" #, fuzzy #~ msgid "Applications" #~ msgstr "_Alternativ" #, fuzzy #~ msgid "Network interface" #~ msgstr "Nätverksgränssnitt:" #, fuzzy #~ msgid "Network interface to monitor" #~ msgstr "Nätverksgränssnitt:" #, fuzzy #~ msgid "General options" #~ msgstr "Visa alla alternativ" #, fuzzy #~ msgid "Options related to gnunet-gtk" #~ msgstr "Ej ansluten till gnunetd." #~ msgid "`%s' failed (%d, %u). Will not send PING.\n" #~ msgstr "\"%s\" misslyckades (%d, %u). Kommer inte skicka PING.\n" #~ msgid "Could not resolve name of HTTP proxy `%s'. Trying without a proxy.\n" #~ msgstr "" #~ "Kunde inte slÃ¥ upp namn för HTTP-proxy \"%s\". Försöker utan proxy.\n" #~ msgid "Now %d of %d chat clients at this node.\n" #~ msgstr "Nu är det %d av %d chattklienter pÃ¥ den här noden.\n" #~ msgid "specify nickname" #~ msgstr "ange smeknamn" #~ msgid "Start GNUnet chat client." #~ msgstr "Starta GNUnets chattklient." #~ msgid "You must specify a nickname (use option `%s').\n" #~ msgstr "Du mÃ¥ste ange ett smeknamn (använd flagga \"%s\").\n" #~ msgid "Database failed to delete `%s'.\n" #~ msgstr "Databas misslyckades att ta bort \"%s\".\n" #~ msgid "`%s' failed. Terminating connection to client.\n" #~ msgstr "\"%s\" misslyckades. Terminerar anslutning till klient.\n" #~ msgid "sendAck failed. Terminating connection to client.\n" #~ msgstr "sendAck misslyckades. Terminerar anslutning till klient.\n" #~ msgid "`%s' called with timeout above 1 hour (bug?)\n" #~ msgstr "\"%s\" anropad med timeout över 1 timma (fel?)\n" #~ msgid "allow SIZE bytes of memory for the local table" #~ msgstr "tillÃ¥t STORLEK byte av minne för lokaltabellen" #~ msgid "Superflous arguments (ignored).\n" #~ msgstr "Onödiga argument (ignorerade).\n" #~ msgid "Call to `%s' with value '%.*s' (%d bytes).\n" #~ msgstr "Anrop till \"%s\" med värde \"%.*s\" (%d byte).\n" #~ msgid "query table called NAME" #~ msgstr "frÃ¥ga tabell kallad NAME" #~ msgid "No commands specified.\n" #~ msgstr "Inga kommandon angivna.\n" #~ msgid "'%s(%s,%s)' succeeded\n" #~ msgstr "\"%s(%s,%s)\" lyckades\n" #~ msgid "Failed to send `%s'. Closing connection.\n" #~ msgstr "Misslyckades att skicka \"%s\". Stänger anslutning.\n" #~ msgid "Received invalid `%s' request (wrong table)\n" #~ msgstr "Mottog ogiltig \"%s\" begäran (fel tabell)\n" #~ msgid "gnunetd signaled error in response to `%s' message\n" #~ msgstr "gnunetd signalerade fel i svar till \"%s\" meddelande\n" #~ msgid "Failed to send `%s' message to gnunetd\n" #~ msgstr "Misslyckades att skicka \"%s\" meddelande till gnunetd\n" #~ msgid "Unexpected reply to `%s' operation.\n" #~ msgstr "Oväntat svar till \"%s\" operation.\n" #~ msgid "Waiting for gnunetd to start (%u iterations left)...\n" #~ msgstr "Väntar pÃ¥ att gnunetd ska starta (%u iterationer kvar)...\n" #~ msgid "Write(%d, %p, %d) failed: %s\n" #~ msgstr "Skrivning(%d, %p, %d) misslyckades: %s\n" #~ msgid "Cannot create pseudonym `%s', file `%s' exists.\n" #~ msgstr "Kan inte skapa pseudonym \"%s\", filen \"%s\" existerar.\n" #~ msgid "AND" #~ msgstr "OCH" #~ msgid "Publication interval for periodic publication changed." #~ msgstr "Publiseringsintervall för periodisk publisering har ändrats." #~ msgid "Indexed file disappeared, deleting block for query `%s'\n" #~ msgstr "Indexerad fil försvann, tar bort block för frÃ¥ga \"%s\"\n" #~ msgid "%8u of %8u bytes deleted." #~ msgstr "%8u av %8u byte togs bort." #~ msgid "specify the file to delete from GNUnet (obligatory, file must exist)" #~ msgstr "" #~ "ange filen att ta bort frÃ¥n GNUnet (obligatorisk, filen mÃ¥ste existera)" #~ msgid "" #~ "Remove file from GNUnet. The specified file is not removed\n" #~ "from the filesystem but just from the local GNUnet datastore." #~ msgstr "" #~ "Ta bort fil frÃ¥n GNUnet. Den angivna filen tas inte bort frÃ¥n\n" #~ "filsystemet utan bara frÃ¥n det lokala GNUnet-datalagret." #~ msgid "You must specify a filename (option -f)\n" #~ msgstr "Du mÃ¥ste ange ett filnamn (flagga -f)\n" #~ msgid "gnunet-directory [OPTIONS] [FILENAMES]" #~ msgstr "gnunet-directory [FLAGGOR] [FILNAMN]" #~ msgid "LEVEL" #~ msgstr "NIVÃ…" #~ msgid "FILENAME" #~ msgstr "FILNAMN" #~ msgid "process directories recursively" #~ msgstr "bearbeta kataloger rekursivt" #~ msgid "Only one file or directory can be specified at a time.\n" #~ msgstr "Endast en fil eller katalog kan anges samtidigt.\n" #~ msgid "You must specify a file or directory to upload.\n" #~ msgstr "Du mÃ¥ste ange en fil eller katalog att ladda upp.\n" #~ msgid "Not enough arguments. You must specify a keyword or identifier.\n" #~ msgstr "" #~ "Inte tillräckligt med argument. Du mÃ¥ste ange ett nyckelord eller " #~ "identifierare.\n" #~ msgid "`%s' registering handlers %d %d\n" #~ msgstr "\"%s\" registrerar handtag %d %d\n" #~ msgid "" #~ "Configuration file must specify a directory for GNUnet to store per-peer " #~ "data under %s%s\n" #~ msgstr "" #~ "Konfigurationsfil mÃ¥ste ange en katalog för GNUnet att lagra motpartsdata " #~ "under %s%s\n" #~ msgid "%s `%s' returned no known hosts!\n" #~ msgstr "%s \"%s\" returnerade inga kända värdar!\n" #~ msgid "Template for gnunet-clients." #~ msgstr "Mall för gnunet-clients." #~ msgid "Start GNUnet-testbed helper." #~ msgstr "Starta hjälpprogrammet GNUnet-testbed." #~ msgid "size of `%s' message is wrong. Ignoring.\n" #~ msgstr "storlek pÃ¥ \"%s\" meddelande är fel. Ignorerar.\n" #~ msgid "'..' is not allowed in file name (%s).\n" #~ msgstr "\"..\" tillÃ¥ts inte i filnamn (%s).\n" #~ msgid "Could not resolve name of HTTP proxy `%s'.\n" #~ msgstr "Kunde inte slÃ¥ upp namn för HTTP-proxy \"%s\".\n" #~ msgid "Failed so send HTTP request `%s' to host `%s': %s\n" #~ msgstr "Misslyckades att skicka HTTP-begäran \"%s\" till värd \"%s\": %s\n" #~ msgid "Peer `%s' did not report back.\n" #~ msgstr "Motpart \"%s\" rapporterade inte tillbaka.\n" #~ msgid "Sorry, no help is available for this option.\n" #~ msgstr "Tyvärr, ingen hjälp är tillgänglig för den här flaggan.\n" #~ msgid "_File" #~ msgstr "_Fil" #~ msgid "_Load" #~ msgstr "_Läs in" #~ msgid "_Save" #~ msgstr "_Spara" #~ msgid "Save the config in .config" #~ msgstr "Spara konfigurationen i .config" #~ msgid "_Quit" #~ msgstr "_Avsluta" #~ msgid "Show _name" #~ msgstr "Visa _namn" #~ msgid "Show _range" #~ msgstr "Visa _omfÃ¥ng" #~ msgid "Show range (Y/M/N)" #~ msgstr "Visa omfÃ¥ng (Y/M/N)" #~ msgid "Show _data" #~ msgstr "Visa _data" #~ msgid "Show all _options" #~ msgstr "Visa alla a_lternativ" #~ msgid "_Help" #~ msgstr "_Hjälp" #~ msgid "_Introduction" #~ msgstr "_Introduktion" #~ msgid "_License" #~ msgstr "_Licens" #~ msgid "Goes up of one level (single view)" #~ msgstr "GÃ¥r upp en nivÃ¥ (enkel vy)" #~ msgid "Load" #~ msgstr "Läs in" #~ msgid "Save a config file" #~ msgstr "Spara en konfigurationsfil" #~ msgid "Save" #~ msgstr "Spara" #~ msgid "Single view" #~ msgstr "Enkel vy" #~ msgid "Single" #~ msgstr "Enkel" #~ msgid "Split view" #~ msgstr "Dela vy" #~ msgid "Split" #~ msgstr "Dela" #~ msgid "Full view" #~ msgstr "Full vy" #~ msgid "Full" #~ msgstr "Full" #~ msgid "Collapse" #~ msgstr "Fäll in" #~ msgid "Expand" #~ msgstr "Expandera" #~ msgid "Sorry, no help available for this option yet." #~ msgstr "Tyvärr, ingen hjälp tillgänglig för den här flaggan ännu." #~ msgid "Couldn't find pixmap file: %s" #~ msgstr "Kunde inte htta bildfil: %s" #~ msgid "Available MODEs:\n" #~ msgstr "Tillgängliga lägen:\n" #~ msgid " config\t\ttext-based configuration\n" #~ msgstr " config\t\ttextbaserad konfiguration\n" #~ msgid " menuconfig\ttext-based menu\n" #~ msgstr " menuconfig\ttextbaserad meny\n" #~ msgid " wizard-curses\tBasic text-based graphical configuration\n" #~ msgstr " wizard-curses\tEnkel textbaserad grafisk konfiguration\n" #~ msgid "" #~ " wizard-gtk\tBasic GTK configuration\n" #~ "\n" #~ msgstr "" #~ " wizard-gtk\tEnkel GTK-konfiguration\n" #~ "\n" #~ msgid "gnunet-setup must have write-access to the configuration file `%s'\n" #~ msgstr "" #~ "gnunet-setup mÃ¥ste ha skrivrättighet till konfigurationsfilen \"%s\"\n" #~ msgid "" #~ "Can only run wizard to configure gnunetd.\n" #~ "Did you forget the `%s' option?\n" #~ msgstr "" #~ "Kan endast köra vägvisaren för att konfigurera gnunetd.\n" #~ "Glömde du flaggan \"%s\"?\n" #~ msgid "" #~ "You can limit GNUnet's resource usage here.\n" #~ "\n" #~ "This is the percentage of processor time GNUnet is allowed to use." #~ msgstr "" #~ "Du kan begränsa GNUnets resursanvändning här.\n" #~ "\n" #~ "Det här är det procenttal som GNUnet tillÃ¥ts använda av processortiden." #~ msgid "" #~ "Welcome to GNUnet!\n" #~ "\n" #~ "This assistant will ask you a few basic questions in order to configure " #~ "GNUnet.\n" #~ "\n" #~ "Please visit our homepage at\n" #~ "\thttp://www.gnunet.org\n" #~ "and join our community at\n" #~ "\thttp://www.gnunet.org/drupal/\n" #~ "\n" #~ "Have a lot of fun,\n" #~ "\n" #~ "the GNUnet team" #~ msgstr "" #~ "Välkommen till GNUnet!\n" #~ "\n" #~ "Denna assistant kommer att frÃ¥ga dig nÃ¥gra enkla frÃ¥gor för att " #~ "konfigurera GNUnet.\n" #~ "\n" #~ "Besök pÃ¥ webbplats pÃ¥\n" #~ "\thttp://gnunet.org/\n" #~ "och gÃ¥ med i vÃ¥r gemenskap pÃ¥\n" #~ "\thttp://www.gnunet.org/drupal/\n" #~ "\n" #~ "Ha det sÃ¥ kul,\n" #~ "\n" #~ "GNUnet-laget" #~ msgid "Next" #~ msgstr "Nästa" #~ msgid "IP-Address/Hostname:" #~ msgstr "IP-adress/Värdnamn:" #~ msgid "Bandwidth limitation" #~ msgstr "Bandbreddsbegränsning" #~ msgid "Bandwidth sharing" #~ msgstr "Bandbreddsdelning" #~ msgid "Max. CPU usage (%):" #~ msgstr "Max. CPU-användning (%):" #~ msgid "CPU usage" #~ msgstr "CPU-användning" #~ msgid "Question" #~ msgstr "FrÃ¥ga" #~ msgid "Group:" #~ msgstr "Grupp:" #~ msgid "User account:" #~ msgstr "Användarkonto:" #~ msgid "You must specify a non-empty set of transports to test!\n" #~ msgstr "Du mÃ¥ste ange en icke-tom uppsättning av transporter att testa!\n" #~ msgid "Updated data for %d applications.\n" #~ msgstr "Uppdaterade data för %d program.\n" #~ msgid "Argument %d: `%s'\n" #~ msgstr "Argument %d: \"%s\"\n" #~ msgid "%s: Rejected connection from blacklisted address %u.%u.%u.%u.\n" #~ msgstr "%s: Vägrade anslutning frÃ¥n svartlistad adress %u.%u.%u.%u.\n" #~ msgid "HTTP: Could not determine my public IP address.\n" #~ msgstr "HTTP: Kunde inte fastställa min publika IP-adress.\n" #~ msgid "Could not resolve name of SMTP server `%s': %s" #~ msgstr "Kunde inte slÃ¥ upp namnet för SMTP-server \"%s\": %s" #~ msgid "" #~ "You must specify the name of a pipe for the SMTP transport in section `" #~ "%s' under `%s'.\n" #~ msgstr "" #~ "Du mÃ¥ste ange ett namn pÃ¥ röret för SMTP-transporten i sektion \"%s\" " #~ "under \"%s\".\n" #~ msgid "Sending E-mail to `%s' failed.\n" #~ msgstr "Sändning av e-post till \"%s\" misslyckades.\n" #~ msgid "%.*s filter %s (SMTP)" #~ msgstr "%.*s filter %s (SMTP)" #~ msgid "Configuration file `%s' not found. Run gnunet-setup!\n" #~ msgstr "Konfigurationsfil \"%s\" hittades inte. Kör gnunet-setup!\n" #~ msgid "" #~ "Configuration file not found. Please run GNUnet Setup (Client " #~ "Configuration) first." #~ msgstr "" #~ "Konfigurationsfil hittades inte. Vänligen kör konfigurationen för GNUnet " #~ "(klientkonfiguration) först." #~ msgid "Cron stopped\n" #~ msgstr "Cron stoppad\n" #~ msgid "Caught signal %d.\n" #~ msgstr "FÃ¥ngade signal %d.\n" #~ msgid "Invalid network notation (additional characters: `%s')." #~ msgstr "Ogiltig nätverksnotation (ytterligare tecken: \"%s\")." #~ msgid "FAILURE" #~ msgstr "MISSLYCKANDE" #~ msgid "MESSAGE" #~ msgstr "MEDDELANDE" #~ msgid "CRON" #~ msgstr "CRON" #~ msgid "EVERYTHING" #~ msgstr "ALLT" #~ msgid "Invalid LOGLEVEL `%s' specified.\n" #~ msgstr "Ogiltig LOGGNIVÃ… \"%s\" angiven.\n" #~ msgid "" #~ "Usage: %s\n" #~ "%s\n" #~ "\n" #~ msgstr "" #~ "Användning: %s\n" #~ "%s\n" #~ "\n" #~ msgid "" #~ "Configuration file must specify a directory for GNUnet to store per-peer " #~ "data under %s\\%s.\n" #~ msgstr "" #~ "Konfigurationsfil mÃ¥ste ange en katalog för GNUnet att lagra motpartsdata " #~ "under %s\\%s.\n" #~ msgid "g" #~ msgstr "g" #~ msgid "t" #~ msgstr "t" #~ msgid "`%s' failed, other side closed connection.\n" #~ msgstr "\"%s\" misslyckades, andra sidan har stängt anslutningen.\n" #~ msgid "Attempted path to `%s' was `%s'.\n" #~ msgstr "Försökt sökväg till \"%s\" var \"%s\".\n" #~ msgid "set verbosity to LEVEL" #~ msgstr "sätt informationsnivÃ¥ till NIVÃ…" gnunet-0.10.1/po/boldquot.sed0000644000175000017500000000033111374167231012760 00000000000000s/"\([^"]*\)"/“\1â€/g s/`\([^`']*\)'/‘\1’/g s/ '\([^`']*\)' / ‘\1’ /g s/ '\([^`']*\)'$/ ‘\1’/g s/^'\([^`']*\)' /‘\1’ /g s/“â€/""/g s/“/“/g s/â€/â€/g s/‘/‘/g s/’/’/g gnunet-0.10.1/po/remove-potcdate.sin0000644000175000017500000000066011374167231014250 00000000000000# Sed script that remove the POT-Creation-Date line in the header entry # from a POT file. # # The distinction between the first and the following occurrences of the # pattern is achieved by looking at the hold space. /^"POT-Creation-Date: .*"$/{ x # Test if the hold space is empty. s/P/P/ ta # Yes it was empty. First occurrence. Remove the line. g d bb :a # The hold space was nonempty. Following occurrences. Do nothing. x :b } gnunet-0.10.1/po/ChangeLog0000644000175000017500000000110011374167231012177 000000000000002007-02-08 gettextize * Makefile.in.in: Upgrade to gettext-0.16.1. * Rules-quot: Upgrade to gettext-0.16.1. 2004-08-21 gettextize * Makefile.in.in: New file, from gettext-0.14. * boldquot.sed: New file, from gettext-0.14. * en@boldquot.header: New file, from gettext-0.14. * en@quot.header: New file, from gettext-0.14. * insert-header.sin: New file, from gettext-0.14. * quot.sed: New file, from gettext-0.14. * remove-potcdate.sin: New file, from gettext-0.14. * Rules-quot: New file, from gettext-0.14. gnunet-0.10.1/po/de.gmo0000644000175000017500000001471512320736475011545 00000000000000Þ•:ìO¼øù 6Nd~˜-²à%þ-$.R &¢ÉéK %U#{Ÿ¥G«ó/ 9;V7’Ê0â) += 1i !› ½ +Å :ñ $, kQ ½ ^¿ ' F AH Š Œ N FÞ % M' +u )¡ 7Ë ^ #b † ¡ /F]y˜1µç+!M*m+˜,Ä"ñ+@^Z|9×4FL`S´È=Í! C-9q#«4Ï-82<k8¨á@é5*-`•Ž${&-¢ÐKÒ o#\“ðYò=L1ŠN¼~ "Š­:5 .)4 79'1"$%- /3*+26(#8 & ,!0# bytes decrypted# bytes encrypted# bytes received via TCP# messages defragmented# messages fragmented%s failed at %s:%d: `%s' %s: illegal option -- %c %s: invalid option -- %c %s: option `%c%s' does not allow an argument %s: option `%s' is ambiguous %s: option `%s' requires an argument %s: option `--%s' does not allow an argument %s: option `-W %s' does not allow an argument %s: option `-W %s' is ambiguous %s: option requires an argument -- %c %s: unrecognized option `%c%s' %s: unrecognized option `--%s' Arguments mandatory for long options are also mandatory for short options. Cannot change user/group to `%s': %s Could not find IP of host `%s': %s DEBUGERRORFile `%s' in directory `%s' does not match naming convention. Removed. I am peer `%s'. INFOInitialization of plugin mechanism failed: %s! Invalid format for IP: `%s' Invalid network notation ('/%d' is not legal in IPv4 CIDR).Invalid network notation (does not end with ';': `%s') No keywords specified! Option `%s' makes no sense without option `%s'. Print statistics about GNUnet operations.SMTP filter string to long, capped to `%s' Trying to use file `%s' for MySQL configuration. Unable to initialize SQLite: %s. WARNINGYou must pass a number to the `%s' option. You must specify one and only one filename for insertion. `%s' failed at %s:%d with error: %s add an additional keyword for the top-level file or directory (this option can be specified multiple times)bdo not index, perform full insertion (stores entire file in encrypted form in GNUnet database)download a GNUnet directory recursivelyhlibgcrypt has not the expected version (version %s is required). mmsprint list of extracted keywords that would be used, but do not perform uploadpublish the files under the pseudonym NAME (place file into namespace)sset the ID of this version of the publication (for namespace insertions only)set the desired LEVEL of receiver-anonymityset the desired LEVEL of sender-anonymityset the meta-data for the given TYPE to the given VALUEspecify ID of an updated version to be published in the future (for namespace insertions only)specify the priority of the contentwrite the file to FILENAMEProject-Id-Version: GNUnet 0.7.0b Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org POT-Creation-Date: 2014-04-08 11:11+0200 PO-Revision-Date: 2006-03-17 21:37+0100 Last-Translator: Nils Durner Language-Team: German Language: de MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=2; plural=(n != 1); # Bytes entschlüsselt# Bytes verschlüsselt# Bytes empfangen über TCP# defragmentierter Nachrichten# fragmentierter Nachrichten`%s' schlug fehl bei %s:%d mit dem Fehler: `%s'. %s: unerlaubte Option -- %c %s: ungültige Option -- %c %s: Option '%c%s' erlaubt keinen Parameter %s: Option `%s' ist mehrdeutig %s: Option `%s' benötigt einen Parameter %s: Option '--%s' erlaubt keinen Parameter %s: Option '-W %s' erlaubt keinen Parameter %s: Option '-W %s' ist mehrdeutig %s: Option benötigt einen Parameter -- %c %s: unbekannte Option '%c%s' %s: unbekannte Option '--%s' Parameter, die für lange Optionen zwingend sind, sind auch für kurze Optionen zwingend. Benutzer/Gruppe kann nicht zu `%s' gewechselt werden: %s IP des Hosts `%s' konnte nicht ermittelt werden: %s DEBUGFEHLERDie Datei `%s' im Verzeichnis `%s' entspricht nicht der Namenskonvention. Datei wurde entfernt. Ich bin Peer `%s'. INFOInitialisierung des Plugin Mechanismuses fehlgeschlagen: %s! Ungültiges Format für IP: `%s' Ungültige Netzwerk Notation ('/%d ist nicht gültig in IPv4 CIDR).Ungültige Netzwerk Notation (endet nicht mit ';': `%s') Keine Schlüsselwörter angegeben! Option `%s' macht keinen Sinn ohne die Option `%s'. Statistiken der GNUnet Aktivitäten ausgeben.SMTP Filterstring zu lang, wurde auf `%s' abgeschnitten Versuche, Datei `%s' für MySQL Konfiguration zu verwenden. SQLite Datenbank konnte nicht initialisiert werden: %s. WARNUNGSie müssen für die Option `%s' zusätzlich eine Zahl angeben. Sie dürfen nur eine Datei zum Deindizieren angeben. `%s' schlug bei %s:%d mit dem Fehler %s fehl Ein zusätzliches Schlüsselwort für die Datei oder das Verzeichnis auf der obersten Ebene hinzufügen (diese Option kann mehrmals angegeben werden)bNicht indizieren, sondern komplett einfügen (speichert die gesamte Datei in verschlüsselter Form in der GNUnet Datenbank)Das GNUnet Verzeichnis rekursiv herunterladenhlibgcrypt hat nicht die erwartete Version (Version %s wird vorausgesetzt). mmsListe der extrahierten Schlüsselworte, die verwendet werden würden, ausgeben, aber keinen Upload durchführenDie Datei unter dem Pseudonym NAME veröffentlichen (platziert die Datei in einem Namespace)sdie ID dieser Version der Veröffentlichung setzen (nur für das Einfügen in Namespaces)Den Grad LEVEL der gewünschten Empfänger-Anonymität setzenGewünschten Grad an Sender-Anonymität festlegenDie Meta-Daten des angegebenen Typs TYPE auf den angegebenen Wert VALUE setzenID einer aktualisierten Version angeben, die in der Zukunft veröffentlich werden soll. (nur für das Einfügen in Namespaces)Die Priorität des Inhalts angebenSchreibe die Datei in DATEINAMEgnunet-0.10.1/po/vi.gmo0000644000175000017500000002602312320736475011566 00000000000000Þ•Y䬨©"»Þð #9Q#g‹¥¿-Ù %% -K .y ¨ &É ð  K0 %| $¢ .Ç Qö #H l  “ !™ =» ]ù GW Ÿ ° /µ å ; 7> Lv :à þ &#0J0{)¬,Ö*+.Zr1‘oÃ!3WU6­ä,ì+:E$€,¥1Ò2k7£6¥EÜ^"'šÂAÄ ,NIF˜ßMá)/7Y^‘#ðÄ/ô*; Uv–)¶"à6$:,_(Œ8µ&î38I9‚)¼0æ,,DvqBèA+?m‰­;7.s ¢­+³bßfBf©#408'iD‘CÖQ ]l Ê $å ) !C4!Lx!-Å!>ó!@2"6s"ª">É"<#¥E#$ë#£$E´$ ú$G%6N%7…%0½%?î%I.&Qx&…Ê&P'HR'N›'–ê'%(/§(×(LÙ(&)()*+) V)mw)]å)C*`E*L¦*Gó*‡;+-Ã+!ñ+A I? !84+TX<;V>- E6= GW1" 5'C&H$#7@DNKLYB(9S, *.QPR0M%J:/FU)3O2# bytes decrypted# bytes dropped by SMTP (outgoing)# bytes encrypted# bytes received via SMTP# bytes received via TCP# bytes sent via SMTP# messages defragmented# messages fragmented# requests filtered by bloom filter%s failed at %s:%d: `%s' %s: illegal option -- %c %s: invalid option -- %c %s: option `%c%s' does not allow an argument %s: option `%s' is ambiguous %s: option `%s' requires an argument %s: option `--%s' does not allow an argument %s: option `-W %s' does not allow an argument %s: option `-W %s' is ambiguous %s: option requires an argument -- %c %s: unrecognized option `%c%s' %s: unrecognized option `--%s' Arguments mandatory for long options are also mandatory for short options. Cannot change user/group to `%s': %s Cannot extract metadata from a URI! Cannot obtain information about user `%s': %s Configuration value '%s' for '%s' in section '%s' is not in set of legal choices Could not find IP of host `%s': %s Could not resolve `%s' (%s): %s DEBUGERRORExpected `%s' to be a directory! Failed to expand `$HOME': environment variable `HOME' not setFewer friends specified than required by minimum friend count. Will only connect to friends. File `%s' in directory `%s' does not match naming convention. Removed. I am peer `%s'. INFOInitialization of plugin mechanism failed: %s! Invalid format for IP: `%s' Invalid network notation ('/%d' is not legal in IPv4 CIDR).Invalid network notation (does not end with ';': `%s') More friendly connections required than target total number of connections. No email-address specified, can not start SMTP transport. No keywords specified! No such userNumber of double-quotes not balanced! Option `%s' is required when using option `%s'. Option `%s' makes no sense without option `%s'. Print statistics about GNUnet operations.Received malformed message via %s. Ignored. SMTP filter string to invalid, lacks ': ' SMTP filter string to long, capped to `%s' SMTP: `%s' failed: %s. Still no peers found in `%s'! Trying to use file `%s' for MySQL configuration. URI to be published (can be used instead of passing a file to add keywords to the file with the respective URI)Unable to initialize SQLite: %s. Unknown metadata type in metadata option `%s'. Using metadata type `unknown' instead. Use `/help command' to get help for a specific commandWARNINGYou must NOT specify an URI and a filename. You must pass a number to the `%s' option. You must specify one and only one filename for insertion. `%s' failed at %s:%d with error: %s `%s' failed for library `%s' with error: %s `%s' failed on file `%s' at %s:%d with error: %s `%s' failed to resolve method '%s' with error: %s add an additional keyword for the top-level file or directory (this option can be specified multiple times)bdelete incomplete downloads (when aborted with CTRL-C)disable adding the creation time to the metadata of the uploaded filedo not index, perform full insertion (stores entire file in encrypted form in GNUnet database)don't resolve host namesdownload a GNUnet directory recursivelyhlibgcrypt has not the expected version (version %s is required). mmsoutput only the identity stringsoutput our own identity onlyprint list of extracted keywords that would be used, but do not perform uploadpublish the files under the pseudonym NAME (place file into namespace)sset the ID of this version of the publication (for namespace insertions only)set the desired LEVEL of sender-anonymityset the meta-data for the given TYPE to the given VALUEspecify ID of an updated version to be published in the future (for namespace insertions only)specify the priority of the contentwrite the file to FILENAMEProject-Id-Version: gnunet 0.8.0a Report-Msgid-Bugs-To: gnunet-developers@mail.gnu.org POT-Creation-Date: 2014-04-08 11:11+0200 PO-Revision-Date: 2008-09-10 22:05+0930 Last-Translator: Clytie Siddall Language-Team: Vietnamese Language: vi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plural-Forms: nplurals=1; plural=0; X-Generator: LocFactoryEditor 1.7b3 # các byte đã giải mã# các byte loại Ä‘i bởi SMTP (Ä‘i ra)# các byte đã mã hoá# các byte đã nhận qua SMTP# các byte đã nhận qua TCP# các byte đã gá»­i qua SMTP# các thông báo được chắp liá»n# các thông báo bị tế phân# các yêu cầu được lá»c theo bá»™ lá»c bloom%s bị lá»—i tại %s:%d: « %s » %s: tùy chá»n không được phép -- %c %s: tùy chá»n không hợp lệ -- %c %s: tùy chá»n « %c%s » không cho phép đối số %s: tùy chá»n « %s » là mÆ¡ hồ %s: tùy chá»n « %s » cần thiết đối số %s: tùy chá»n « --%s » không cho phép đối số %s: tùy chá»n « -W %s » không cho phép đối số %s: tùy chá»n « -W %s » là mÆ¡ hồ %s: tùy chá»n cần thiết đối số -- %c %s: không nhận ra tùy chá»n « %c%s » %s: không nhận ra tùy chá»n « --%s » Má»i đối số bắt buá»™c phải sá»­ dụng vá»›i tùy chá»n dài cÅ©ng bắt buá»™c vá»›i tùy chá»n ngắn. Không thể thay đổi ngưá»i dùng/nhóm thành « %s »: %s Không thể trích siêu dữ liệu ra má»™t địa chỉ URI. Không thể lấy thông tin vá» ngưá»i dùng « %s »: %s Giá trị cấu hình « %s » cho « %s » trong phần « %s » không phải nằm trong tập hợp các sá»± chá»n được phép Không tìm thấy địa chỉ IP cá»§a máy « %s »: %s Không thể giải quyết « %s » (%s): %s Gá»  Lá»–ILá»–IMong đợi « %s » là má»™t thư mục. Lá»—i mở rá»™ng biến môi trưá»ng « $HOME »: chưa đặt biến môi trưá»ng « HOME »Xác định quá ít bạn bè (dưới số tối thiểu). Sẽ chỉ kết nối tá»›i bạn bè. Tập tin « %s » trong thư mục « %s » không tùy theo quy ước đặt tên. Bị gỡ bá». Tôi là đồng đẳng « %s ». TINLá»—i sÆ¡ khởi cÆ¡ chế phần bổ sung: %s Äịa chỉ IP định dạng sai: %s Ký hiệu mạng sai (« /%d » không hợp lệ trong CIDR IPv4).Ký hiệu mạng sai (không kết thúc vá»›i « ; »: « %s ») Cần thiết nhiá»u kết nối bạn bè hÆ¡n tổng số kết nối đích. Chưa ghi rõ địa chỉ thư Ä‘iện tá»­ nên không tạo được truyá»n tải SMTP. Chưa ghi rõ từ khoá. Không có ngưá»i dùng như vậyCó dấu nháy kép thừa hay thiếu. Tùy chá»n « %s » cần thiết khi dùng tùy chá»n « %s ». Tùy chá»n « %s » không có nghÄ©a khi không có tùy chá»n « %s ». In ra thống kê vá» các thao tác GNUnet.Nhận được thông báo dạng sai qua %s. Bị bá» qua. Chuá»—i lá»c vào SMTP không hợp lệ, còn thiếu « : » Chuá»—i lá»c vào SMTP quá dài, tối Ä‘a « %s » SMTP: « %s » bị lá»—i: %s Vẫn còn không tìm thấy đồng đẳng trong « %s ». Äang thá»­ dùng tập tin « %s » cho cấu hình MySQL. Äịa chỉ URI cần công bố (có thể được dùng thay vào gá»­i má»™t tập tin để thêm từ khoá vào tập tin có địa chỉ URI tương ứng)Không thể sÆ¡ khởi SQLite: %s. Không rõ kiểu siêu dữ liệu trong tùy chá»n siêu dữ liệu « %s ». Äang ùng kiểu siêu dữ liệu « không rõ » (unknown) để thay thế. Gõ chuá»—i « /help LỆNH » để xem trợ giúp vá» lệnh đóCẢNH BÃOKHÔNG cho phép ghi rõ cả hai địa chỉ URI và tên tập tin. Phải gá»­i má»™t con số cho tùy chá»n « %s ». Phải ghi rõ chỉ má»™t tên tập tin để chèn. « %s » bị lá»—i tại %s:%d vá»›i lá»—i: %s « %s » thất bại cho thư viện « %s » vá»›i lá»—i: %s « %s » thất bại ở tập tin « %s » tại %s:%d vá»›i lá»—i: %s « %s » không giải quyết được phương pháp « %s », vá»›i lá»—i: %s thêm má»™t từ khoá bổ sung cho tập tin hoặc thư mục ở cấp đầu (có thể chỉ ra tùy chá»n này nhiá»u lần)bxoá việc tải vá» không hoàn thành (khi há»§y bở dùng CTRL-C)tắt thêm giá» tạo vào siêu dữ liệu cá»§a tập tin đã tải lênkhông đánh chỉ mục, thá»±c hiện việc chèn đầy đủ (chứa toàn bá»™ tập tin ở dạng mã hóa trong cÆ¡ sở dữ liệu GNUnet)không quyết định các tên máytải xuống đệ quy má»™t thư mục GNUnetglibgcrypt không có phiên bản mong đợi (yêu cầu phiên bản %s). pmgchỉ xuất những chuá»—i nhận diệnchỉ xuất nhận diện mìnhin ra danh sách các từ khóa đã giải phóng cần sá»­ dụng, nhưng không thá»±c hiện tải lêncông bố các tập tin dưới biệt hiệu TÊN (đặt tập tin vào không gian tên)gđặt mã số cá»§a phiên bản này cá»§a sá»± công bố (chỉ cho chèn không gian tên)đặt CẤP mong muốn cá»§a tình trạng nặc danh cá»§a ngưá»i gá»­iđặt siêu dữ liệu cho KIỂU đưa ra thành GIÃ_TRỊ chỉ rachỉ ra mã số cá»§a má»™t phiên bản đã cập nhật để công bố trong tương lai (chỉ cho sá»± chèn không gian tên)xác định mức ưu tiên cá»§a ná»™i dungghi tập tin vào TÊN_TẬP_TINgnunet-0.10.1/ABOUT-NLS0000644000175000017500000023334011374167231011253 000000000000001 Notes on the Free Translation Project *************************************** Free software is going international! The Free Translation Project is a way to get maintainers of free software, translators, and users all together, so that free software will gradually become able to speak many languages. A few packages already provide translations for their messages. If you found this `ABOUT-NLS' file inside a distribution, you may assume that the distributed package does use GNU `gettext' internally, itself available at your nearest GNU archive site. But you do _not_ need to install GNU `gettext' prior to configuring, installing or using this package with messages translated. Installers will find here some useful hints. These notes also explain how users should proceed for getting the programs to use the available translations. They tell how people wanting to contribute and work on translations can contact the appropriate team. When reporting bugs in the `intl/' directory or bugs which may be related to internationalization, you should tell about the version of `gettext' which is used. The information can be found in the `intl/VERSION' file, in internationalized packages. 1.1 Quick configuration advice ============================== If you want to exploit the full power of internationalization, you should configure it using ./configure --with-included-gettext to force usage of internationalizing routines provided within this package, despite the existence of internationalizing capabilities in the operating system where this package is being installed. So far, only the `gettext' implementation in the GNU C library version 2 provides as many features (such as locale alias, message inheritance, automatic charset conversion or plural form handling) as the implementation here. It is also not possible to offer this additional functionality on top of a `catgets' implementation. Future versions of GNU `gettext' will very likely convey even more functionality. So it might be a good idea to change to GNU `gettext' as soon as possible. So you need _not_ provide this option if you are using GNU libc 2 or you have installed a recent copy of the GNU gettext package with the included `libintl'. 1.2 INSTALL Matters =================== Some packages are "localizable" when properly installed; the programs they contain can be made to speak your own native language. Most such packages use GNU `gettext'. Other packages have their own ways to internationalization, predating GNU `gettext'. By default, this package will be installed to allow translation of messages. It will automatically detect whether the system already provides the GNU `gettext' functions. If not, the included GNU `gettext' library will be used. This library is wholly contained within this package, usually in the `intl/' subdirectory, so prior installation of the GNU `gettext' package is _not_ required. Installers may use special options at configuration time for changing the default behaviour. The commands: ./configure --with-included-gettext ./configure --disable-nls will, respectively, bypass any pre-existing `gettext' to use the internationalizing routines provided within this package, or else, _totally_ disable translation of messages. When you already have GNU `gettext' installed on your system and run configure without an option for your new package, `configure' will probably detect the previously built and installed `libintl.a' file and will decide to use this. This might not be desirable. You should use the more recent version of the GNU `gettext' library. I.e. if the file `intl/VERSION' shows that the library which comes with this package is more recent, you should use ./configure --with-included-gettext to prevent auto-detection. The configuration process will not test for the `catgets' function and therefore it will not be used. The reason is that even an emulation of `gettext' on top of `catgets' could not provide all the extensions of the GNU `gettext' library. Internationalized packages usually have many `po/LL.po' files, where LL gives an ISO 639 two-letter code identifying the language. Unless translations have been forbidden at `configure' time by using the `--disable-nls' switch, all available translations are installed together with the package. However, the environment variable `LINGUAS' may be set, prior to configuration, to limit the installed set. `LINGUAS' should then contain a space separated list of two-letter codes, stating which languages are allowed. 1.3 Using This Package ====================== As a user, if your language has been installed for this package, you only have to set the `LANG' environment variable to the appropriate `LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, and `CC' is an ISO 3166 two-letter country code. For example, let's suppose that you speak German and live in Germany. At the shell prompt, merely execute `setenv LANG de_DE' (in `csh'), `export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). This can be done from your `.login' or `.profile' file, once and for all. You might think that the country code specification is redundant. But in fact, some languages have dialects in different countries. For example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The country code serves to distinguish the dialects. The locale naming convention of `LL_CC', with `LL' denoting the language and `CC' denoting the country, is the one use on systems based on GNU libc. On other systems, some variations of this scheme are used, such as `LL' or `LL_CC.ENCODING'. You can get the list of locales supported by your system for your language by running the command `locale -a | grep '^LL''. Not all programs have translations for all languages. By default, an English message is shown in place of a nonexistent translation. If you understand other languages, you can set up a priority list of languages. This is done through a different environment variable, called `LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' for the purpose of message handling, but you still need to have `LANG' set to the primary language; this is required by other parts of the system libraries. For example, some Swedish users who would rather read translations in German than English for when Swedish is not available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. Special advice for Norwegian users: The language code for Norwegian bokma*l changed from `no' to `nb' recently (in 2003). During the transition period, while some message catalogs for this language are installed under `nb' and some older ones under `no', it's recommended for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and older translations are used. In the `LANGUAGE' environment variable, but not in the `LANG' environment variable, `LL_CC' combinations can be abbreviated as `LL' to denote the language's main dialect. For example, `de' is equivalent to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' (Portuguese as spoken in Portugal) in this context. 1.4 Translating Teams ===================== For the Free Translation Project to be a success, we need interested people who like their own language and write it well, and who are also able to synergize with other translators speaking the same language. Each translation team has its own mailing list. The up-to-date list of teams can be found at the Free Translation Project's homepage, `http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" area. If you'd like to volunteer to _work_ at translating messages, you should become a member of the translating team for your own language. The subscribing address is _not_ the same as the list itself, it has `-request' appended. For example, speakers of Swedish can send a message to `sv-request@li.org', having this message body: subscribe Keep in mind that team members are expected to participate _actively_ in translations, or at solving translational difficulties, rather than merely lurking around. If your team does not exist yet and you want to start one, or if you are unsure about what to do or how to get started, please write to `translation@iro.umontreal.ca' to reach the coordinator for all translator teams. The English team is special. It works at improving and uniformizing the terminology in use. Proven linguistic skills are praised more than programming skills, here. 1.5 Available Packages ====================== Languages are not equally supported in all packages. The following matrix shows the current state of internationalization, as of October 2006. The matrix shows, in regard of each package, for which languages PO files have been submitted to translation coordination, with a translation percentage of at least 50%. Ready PO files af am ar az be bg bs ca cs cy da de el en en_GB eo +----------------------------------------------------+ GNUnet | [] | a2ps | [] [] [] [] [] | aegis | () | ant-phone | () | anubis | [] | ap-utils | | aspell | [] [] [] [] [] | bash | [] [] [] | batchelor | [] | bfd | | bibshelf | [] | binutils | [] | bison | [] [] | bison-runtime | | bluez-pin | [] [] [] [] [] | cflow | [] | clisp | [] [] | console-tools | [] [] | coreutils | [] [] [] | cpio | | cpplib | [] [] [] | cryptonit | [] | darkstat | [] () [] | dialog | [] [] [] [] [] [] | diffutils | [] [] [] [] [] [] | doodle | [] | e2fsprogs | [] [] | enscript | [] [] [] [] | error | [] [] [] [] | fetchmail | [] [] () [] | fileutils | [] [] | findutils | [] [] [] | flex | [] [] [] | fslint | [] | gas | | gawk | [] [] [] | gbiff | [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] | gettext-runtime | [] [] [] [] [] | gettext-tools | [] [] | gimp-print | [] [] [] [] | gip | [] | gliv | [] | glunarclock | [] | gmult | [] [] | gnubiff | () | gnucash | () () [] | gnucash-glossary | [] () | gnuedu | | gnulib | [] [] [] [] [] [] | gnunet-gtk | | gnutls | | gpe-aerial | [] [] | gpe-beam | [] [] | gpe-calendar | | gpe-clock | [] [] | gpe-conf | [] [] | gpe-contacts | | gpe-edit | [] | gpe-filemanager | | gpe-go | [] | gpe-login | [] [] | gpe-ownerinfo | [] [] | gpe-package | | gpe-sketchbook | [] [] | gpe-su | [] [] | gpe-taskmanager | [] [] | gpe-timesheet | [] | gpe-today | [] [] | gpe-todo | | gphoto2 | [] [] [] [] | gprof | [] [] | gpsdrive | () () | gramadoir | [] [] | grep | [] [] [] [] [] [] | gretl | | gsasl | | gss | | gst-plugins | [] [] [] [] | gst-plugins-base | [] [] [] | gst-plugins-good | [] [] [] [] [] [] [] | gstreamer | [] [] [] [] [] [] [] | gtick | () | gtkam | [] [] [] | gtkorphan | [] [] | gtkspell | [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] | id-utils | [] [] | impost | | indent | [] [] [] | iso_3166 | [] [] | iso_3166_2 | | iso_4217 | [] | iso_639 | [] [] | jpilot | [] | jtag | | jwhois | | kbd | [] [] [] [] | keytouch | | keytouch-editor | | keytouch-keyboa... | | latrine | () | ld | [] | leafpad | [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] | libextractor | [] | libgpewidget | [] [] [] | libgpg-error | [] | libgphoto2 | [] [] | libgphoto2_port | [] [] | libgsasl | | libiconv | [] [] | libidn | [] [] | lifelines | [] () | lilypond | [] | lingoteach | | lynx | [] [] [] [] | m4 | [] [] [] [] | mailutils | [] | make | [] [] | man-db | [] () [] [] | minicom | [] [] [] | mysecretdiary | [] [] | nano | [] [] [] | nano_1_0 | [] () [] [] | opcodes | [] | parted | | pilot-qof | [] | psmisc | [] | pwdutils | | python | | qof | | radius | [] | recode | [] [] [] [] [] [] | rpm | [] [] | screem | | scrollkeeper | [] [] [] [] [] [] [] [] | sed | [] [] [] | sh-utils | [] [] | shared-mime-info | [] [] [] [] | sharutils | [] [] [] [] [] [] | shishi | | silky | | skencil | [] () | sketch | [] () | solfege | | soundtracker | [] [] | sp | [] | stardict | [] | system-tools-ba... | [] [] [] [] [] [] [] [] [] | tar | [] | texinfo | [] [] [] | textutils | [] [] [] | tin | () () | tp-robot | [] | tuxpaint | [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] [] [] | vorbis-tools | [] [] [] [] | wastesedge | () | wdiff | [] [] [] [] | wget | [] [] | xchat | [] [] [] [] [] [] | xkeyboard-config | | xpad | [] [] | +----------------------------------------------------+ af am ar az be bg bs ca cs cy da de el en en_GB eo 10 0 1 2 9 22 1 42 41 2 60 95 16 1 17 16 es et eu fa fi fr ga gl gu he hi hr hu id is it +--------------------------------------------------+ GNUnet | | a2ps | [] [] [] () | aegis | | ant-phone | [] | anubis | [] | ap-utils | [] [] | aspell | [] [] [] | bash | [] [] [] | batchelor | [] [] | bfd | [] | bibshelf | [] [] [] | binutils | [] [] [] | bison | [] [] [] [] [] [] | bison-runtime | [] [] [] [] [] | bluez-pin | [] [] [] [] [] | cflow | [] | clisp | [] [] | console-tools | | coreutils | [] [] [] [] [] [] | cpio | [] [] [] | cpplib | [] [] | cryptonit | [] | darkstat | [] () [] [] [] | dialog | [] [] [] [] [] [] [] [] | diffutils | [] [] [] [] [] [] [] [] [] | doodle | [] [] | e2fsprogs | [] [] [] | enscript | [] [] [] | error | [] [] [] [] [] | fetchmail | [] | fileutils | [] [] [] [] [] [] | findutils | [] [] [] [] | flex | [] [] [] | fslint | [] | gas | [] [] | gawk | [] [] [] [] | gbiff | [] | gcal | [] [] | gcc | [] | gettext-examples | [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] | gettext-tools | [] [] [] | gimp-print | [] [] | gip | [] [] [] | gliv | () | glunarclock | [] [] [] | gmult | [] [] [] | gnubiff | () () | gnucash | () () () | gnucash-glossary | [] [] | gnuedu | [] | gnulib | [] [] [] [] [] [] [] [] | gnunet-gtk | | gnutls | | gpe-aerial | [] [] | gpe-beam | [] [] | gpe-calendar | | gpe-clock | [] [] [] [] | gpe-conf | [] | gpe-contacts | [] [] | gpe-edit | [] [] [] [] | gpe-filemanager | [] | gpe-go | [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] [] [] [] | gpe-package | [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] [] | gpe-taskmanager | [] [] [] | gpe-timesheet | [] [] [] [] | gpe-today | [] [] [] [] | gpe-todo | [] | gphoto2 | [] [] [] [] [] | gprof | [] [] [] [] | gpsdrive | () () [] () | gramadoir | [] [] | grep | [] [] [] [] [] [] [] [] [] [] [] [] | gretl | [] [] [] | gsasl | [] [] | gss | [] | gst-plugins | [] [] [] | gst-plugins-base | [] [] | gst-plugins-good | [] [] [] | gstreamer | [] [] [] | gtick | [] | gtkam | [] [] [] [] | gtkorphan | [] [] | gtkspell | [] [] [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] [] [] [] [] [] [] [] [] | id-utils | [] [] [] [] [] | impost | [] [] | indent | [] [] [] [] [] [] [] [] [] [] | iso_3166 | [] [] [] | iso_3166_2 | [] | iso_4217 | [] [] [] [] | iso_639 | [] [] [] [] [] | jpilot | [] [] | jtag | [] | jwhois | [] [] [] [] [] | kbd | [] [] | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | latrine | [] [] [] | ld | [] [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] | libextractor | [] | libgpewidget | [] [] [] [] [] | libgpg-error | | libgphoto2 | [] [] [] | libgphoto2_port | [] [] | libgsasl | [] [] | libiconv | [] [] | libidn | [] [] | lifelines | () | lilypond | [] | lingoteach | [] [] [] | lynx | [] [] [] | m4 | [] [] [] [] | mailutils | [] [] | make | [] [] [] [] [] [] [] [] | man-db | () | minicom | [] [] [] [] | mysecretdiary | [] [] [] | nano | [] [] [] [] [] [] | nano_1_0 | [] [] [] [] [] | opcodes | [] [] [] [] | parted | [] [] [] [] | pilot-qof | | psmisc | [] [] [] | pwdutils | | python | | qof | [] | radius | [] [] | recode | [] [] [] [] [] [] [] [] | rpm | [] [] | screem | | scrollkeeper | [] [] [] | sed | [] [] [] [] [] | sh-utils | [] [] [] [] [] [] [] | shared-mime-info | [] [] [] [] [] [] | sharutils | [] [] [] [] [] [] [] [] | shishi | | silky | [] | skencil | [] [] | sketch | [] [] | solfege | [] | soundtracker | [] [] [] | sp | [] | stardict | [] | system-tools-ba... | [] [] [] [] [] [] [] [] | tar | [] [] [] [] [] [] [] | texinfo | [] [] | textutils | [] [] [] [] [] | tin | [] () | tp-robot | [] [] [] [] | tuxpaint | [] [] | unicode-han-tra... | | unicode-transla... | [] [] | util-linux | [] [] [] [] [] [] [] | vorbis-tools | [] [] | wastesedge | () | wdiff | [] [] [] [] [] [] [] [] | wget | [] [] [] [] [] [] [] [] | xchat | [] [] [] [] [] [] [] [] | xkeyboard-config | [] [] [] [] | xpad | [] [] [] | +--------------------------------------------------+ es et eu fa fi fr ga gl gu he hi hr hu id is it 88 22 14 2 40 115 61 14 1 8 1 6 59 31 0 52 ja ko ku ky lg lt lv mk mn ms mt nb ne nl nn no +-------------------------------------------------+ GNUnet | | a2ps | () [] [] () | aegis | () | ant-phone | [] | anubis | [] [] [] | ap-utils | [] | aspell | [] [] | bash | [] | batchelor | [] [] | bfd | | bibshelf | [] | binutils | | bison | [] [] [] | bison-runtime | [] [] [] | bluez-pin | [] [] [] | cflow | | clisp | [] | console-tools | | coreutils | [] | cpio | | cpplib | [] | cryptonit | [] | darkstat | [] [] | dialog | [] [] | diffutils | [] [] [] | doodle | | e2fsprogs | [] | enscript | [] | error | [] | fetchmail | [] [] | fileutils | [] [] | findutils | [] | flex | [] [] | fslint | [] [] | gas | | gawk | [] [] | gbiff | [] | gcal | | gcc | | gettext-examples | [] [] | gettext-runtime | [] [] [] | gettext-tools | [] [] | gimp-print | [] [] | gip | [] [] | gliv | [] | glunarclock | [] [] | gmult | [] [] | gnubiff | | gnucash | () () | gnucash-glossary | [] | gnuedu | | gnulib | [] [] [] [] | gnunet-gtk | | gnutls | | gpe-aerial | [] | gpe-beam | [] | gpe-calendar | [] | gpe-clock | [] [] [] | gpe-conf | [] [] | gpe-contacts | [] | gpe-edit | [] [] [] | gpe-filemanager | [] [] | gpe-go | [] [] [] | gpe-login | [] [] [] | gpe-ownerinfo | [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] | gpe-su | [] [] [] | gpe-taskmanager | [] [] [] [] | gpe-timesheet | [] | gpe-today | [] [] | gpe-todo | [] | gphoto2 | [] [] | gprof | | gpsdrive | () () () | gramadoir | () | grep | [] [] [] [] | gretl | | gsasl | [] | gss | | gst-plugins | [] | gst-plugins-base | | gst-plugins-good | [] | gstreamer | [] | gtick | | gtkam | [] | gtkorphan | [] | gtkspell | [] [] | gutenprint | | hello | [] [] [] [] [] [] | id-utils | [] | impost | | indent | [] [] | iso_3166 | [] | iso_3166_2 | [] | iso_4217 | [] [] [] | iso_639 | [] [] | jpilot | () () () | jtag | | jwhois | [] | kbd | [] | keytouch | [] | keytouch-editor | | keytouch-keyboa... | | latrine | [] | ld | | leafpad | [] [] | libc | [] [] [] [] [] | libexif | | libextractor | | libgpewidget | [] | libgpg-error | | libgphoto2 | [] | libgphoto2_port | [] | libgsasl | [] | libiconv | | libidn | [] [] | lifelines | [] | lilypond | | lingoteach | [] | lynx | [] [] | m4 | [] [] | mailutils | | make | [] [] [] | man-db | () | minicom | [] | mysecretdiary | [] | nano | [] [] [] | nano_1_0 | [] [] [] | opcodes | [] | parted | [] [] | pilot-qof | | psmisc | [] [] [] | pwdutils | | python | | qof | | radius | | recode | [] | rpm | [] [] | screem | [] | scrollkeeper | [] [] [] [] | sed | [] [] | sh-utils | [] [] | shared-mime-info | [] [] [] [] [] | sharutils | [] [] | shishi | | silky | [] | skencil | | sketch | | solfege | | soundtracker | | sp | () | stardict | [] [] | system-tools-ba... | [] [] [] [] | tar | [] [] [] | texinfo | [] [] [] | textutils | [] [] [] | tin | | tp-robot | [] | tuxpaint | [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] | vorbis-tools | [] | wastesedge | [] | wdiff | [] [] | wget | [] [] | xchat | [] [] [] [] | xkeyboard-config | [] | xpad | [] [] [] | +-------------------------------------------------+ ja ko ku ky lg lt lv mk mn ms mt nb ne nl nn no 52 24 2 2 1 3 0 2 3 21 0 15 1 97 5 1 nso or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta +------------------------------------------------------+ GNUnet | | a2ps | () [] [] [] [] [] [] | aegis | () () | ant-phone | [] [] | anubis | [] [] [] | ap-utils | () | aspell | [] [] | bash | [] [] [] | batchelor | [] [] | bfd | | bibshelf | [] | binutils | [] [] | bison | [] [] [] [] [] | bison-runtime | [] [] [] [] | bluez-pin | [] [] [] [] [] [] [] [] [] | cflow | [] | clisp | [] | console-tools | [] | coreutils | [] [] [] [] | cpio | [] [] [] | cpplib | [] | cryptonit | [] [] | darkstat | [] [] [] [] [] [] | dialog | [] [] [] [] [] [] [] [] [] | diffutils | [] [] [] [] [] [] | doodle | [] [] | e2fsprogs | [] [] | enscript | [] [] [] [] [] | error | [] [] [] [] | fetchmail | [] [] [] | fileutils | [] [] [] [] [] | findutils | [] [] [] [] [] [] | flex | [] [] [] [] [] | fslint | [] [] [] [] | gas | | gawk | [] [] [] [] | gbiff | [] | gcal | [] | gcc | [] | gettext-examples | [] [] [] [] [] [] [] [] | gettext-runtime | [] [] [] [] [] [] [] [] | gettext-tools | [] [] [] [] [] [] [] | gimp-print | [] [] | gip | [] [] [] [] | gliv | [] [] [] [] | glunarclock | [] [] [] [] [] [] | gmult | [] [] [] [] | gnubiff | () | gnucash | () [] | gnucash-glossary | [] [] [] | gnuedu | | gnulib | [] [] [] [] [] | gnunet-gtk | [] | gnutls | [] [] | gpe-aerial | [] [] [] [] [] [] [] | gpe-beam | [] [] [] [] [] [] [] | gpe-calendar | [] | gpe-clock | [] [] [] [] [] [] [] [] | gpe-conf | [] [] [] [] [] [] [] | gpe-contacts | [] [] [] [] [] | gpe-edit | [] [] [] [] [] [] [] [] | gpe-filemanager | [] [] | gpe-go | [] [] [] [] [] [] | gpe-login | [] [] [] [] [] [] [] [] | gpe-ownerinfo | [] [] [] [] [] [] [] [] | gpe-package | [] [] | gpe-sketchbook | [] [] [] [] [] [] [] [] | gpe-su | [] [] [] [] [] [] [] [] | gpe-taskmanager | [] [] [] [] [] [] [] [] | gpe-timesheet | [] [] [] [] [] [] [] [] | gpe-today | [] [] [] [] [] [] [] [] | gpe-todo | [] [] [] [] | gphoto2 | [] [] [] [] [] | gprof | [] [] [] | gpsdrive | [] [] [] | gramadoir | [] [] | grep | [] [] [] [] [] [] [] [] | gretl | [] | gsasl | [] [] [] | gss | [] [] [] | gst-plugins | [] [] [] [] | gst-plugins-base | [] | gst-plugins-good | [] [] [] [] | gstreamer | [] [] [] | gtick | [] | gtkam | [] [] [] [] | gtkorphan | [] | gtkspell | [] [] [] [] [] [] [] [] | gutenprint | [] | hello | [] [] [] [] [] [] [] [] | id-utils | [] [] [] [] | impost | [] | indent | [] [] [] [] [] [] | iso_3166 | [] [] [] [] [] [] | iso_3166_2 | | iso_4217 | [] [] [] [] | iso_639 | [] [] [] [] | jpilot | | jtag | [] | jwhois | [] [] [] [] | kbd | [] [] [] | keytouch | [] | keytouch-editor | [] | keytouch-keyboa... | [] | latrine | [] [] | ld | [] | leafpad | [] [] [] [] [] [] | libc | [] [] [] [] [] | libexif | [] | libextractor | [] [] | libgpewidget | [] [] [] [] [] [] [] | libgpg-error | [] [] | libgphoto2 | [] | libgphoto2_port | [] [] [] | libgsasl | [] [] [] [] | libiconv | [] [] | libidn | [] [] () | lifelines | [] [] | lilypond | | lingoteach | [] | lynx | [] [] [] | m4 | [] [] [] [] [] | mailutils | [] [] [] [] | make | [] [] [] [] | man-db | [] [] | minicom | [] [] [] [] [] | mysecretdiary | [] [] [] [] | nano | [] [] [] | nano_1_0 | [] [] [] [] | opcodes | [] [] | parted | [] | pilot-qof | [] | psmisc | [] [] | pwdutils | [] [] | python | | qof | [] [] | radius | [] [] | recode | [] [] [] [] [] [] [] | rpm | [] [] [] [] | screem | | scrollkeeper | [] [] [] [] [] [] [] | sed | [] [] [] [] [] [] [] [] [] | sh-utils | [] [] [] | shared-mime-info | [] [] [] [] [] | sharutils | [] [] [] [] | shishi | [] | silky | [] | skencil | [] [] [] | sketch | [] [] [] | solfege | [] | soundtracker | [] [] | sp | | stardict | [] [] [] | system-tools-ba... | [] [] [] [] [] [] [] [] [] | tar | [] [] [] [] [] | texinfo | [] [] [] [] | textutils | [] [] [] | tin | () | tp-robot | [] | tuxpaint | [] [] [] [] [] | unicode-han-tra... | | unicode-transla... | | util-linux | [] [] [] [] | vorbis-tools | [] [] | wastesedge | | wdiff | [] [] [] [] [] [] | wget | [] [] [] [] | xchat | [] [] [] [] [] [] [] | xkeyboard-config | [] [] | xpad | [] [] [] | +------------------------------------------------------+ nso or pa pl pt pt_BR rm ro ru rw sk sl sq sr sv ta 0 2 3 58 30 54 5 73 72 4 40 46 11 50 128 2 tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu +---------------------------------------------------+ GNUnet | [] | 2 a2ps | [] [] [] | 19 aegis | | 0 ant-phone | [] [] | 6 anubis | [] [] [] | 11 ap-utils | () [] | 4 aspell | [] [] [] | 15 bash | [] | 11 batchelor | [] [] | 9 bfd | | 1 bibshelf | [] | 7 binutils | [] [] [] | 9 bison | [] [] [] | 19 bison-runtime | [] [] [] | 15 bluez-pin | [] [] [] [] [] [] | 28 cflow | [] [] | 5 clisp | | 6 console-tools | [] [] | 5 coreutils | [] [] | 16 cpio | [] [] [] | 9 cpplib | [] [] [] [] | 11 cryptonit | | 5 darkstat | [] () () | 15 dialog | [] [] [] [] [] | 30 diffutils | [] [] [] [] | 28 doodle | [] | 6 e2fsprogs | [] [] | 10 enscript | [] [] [] | 16 error | [] [] [] [] | 18 fetchmail | [] [] | 12 fileutils | [] [] [] | 18 findutils | [] [] [] | 17 flex | [] [] | 15 fslint | [] | 9 gas | [] | 3 gawk | [] [] | 15 gbiff | [] | 5 gcal | [] | 5 gcc | [] [] [] | 6 gettext-examples | [] [] [] [] [] [] | 27 gettext-runtime | [] [] [] [] [] [] | 28 gettext-tools | [] [] [] [] [] | 19 gimp-print | [] [] | 12 gip | [] [] | 12 gliv | [] [] | 8 glunarclock | [] [] [] | 15 gmult | [] [] [] [] | 15 gnubiff | [] | 1 gnucash | () | 2 gnucash-glossary | [] [] | 9 gnuedu | [] | 2 gnulib | [] [] [] [] [] | 28 gnunet-gtk | | 1 gnutls | | 2 gpe-aerial | [] [] | 14 gpe-beam | [] [] | 14 gpe-calendar | [] | 3 gpe-clock | [] [] [] [] | 21 gpe-conf | [] [] | 14 gpe-contacts | [] [] | 10 gpe-edit | [] [] [] [] | 20 gpe-filemanager | [] | 6 gpe-go | [] [] | 15 gpe-login | [] [] [] [] [] | 21 gpe-ownerinfo | [] [] [] [] | 21 gpe-package | [] | 6 gpe-sketchbook | [] [] | 16 gpe-su | [] [] [] | 20 gpe-taskmanager | [] [] [] | 20 gpe-timesheet | [] [] [] [] | 18 gpe-today | [] [] [] [] [] | 21 gpe-todo | [] | 7 gphoto2 | [] [] [] [] | 20 gprof | [] [] | 11 gpsdrive | | 4 gramadoir | [] | 7 grep | [] [] [] [] | 34 gretl | | 4 gsasl | [] [] | 8 gss | [] | 5 gst-plugins | [] [] [] | 15 gst-plugins-base | [] [] [] | 9 gst-plugins-good | [] [] [] [] [] | 20 gstreamer | [] [] [] | 17 gtick | [] | 3 gtkam | [] | 13 gtkorphan | [] | 7 gtkspell | [] [] [] [] [] [] | 26 gutenprint | | 3 hello | [] [] [] [] [] | 37 id-utils | [] [] | 14 impost | [] | 4 indent | [] [] [] [] | 25 iso_3166 | [] [] [] [] | 16 iso_3166_2 | | 2 iso_4217 | [] [] | 14 iso_639 | [] | 14 jpilot | [] [] [] [] | 7 jtag | [] | 3 jwhois | [] [] [] | 13 kbd | [] [] | 12 keytouch | [] | 4 keytouch-editor | | 2 keytouch-keyboa... | [] | 3 latrine | [] [] | 8 ld | [] [] [] [] | 8 leafpad | [] [] [] [] | 23 libc | [] [] [] | 23 libexif | [] | 4 libextractor | [] | 5 libgpewidget | [] [] [] | 19 libgpg-error | [] | 4 libgphoto2 | [] | 8 libgphoto2_port | [] [] [] | 11 libgsasl | [] | 8 libiconv | [] | 7 libidn | [] [] | 10 lifelines | | 4 lilypond | | 2 lingoteach | [] | 6 lynx | [] [] [] | 15 m4 | [] [] [] | 18 mailutils | [] | 8 make | [] [] [] | 20 man-db | [] | 6 minicom | [] | 14 mysecretdiary | [] [] | 12 nano | [] [] | 17 nano_1_0 | [] [] [] | 18 opcodes | [] [] | 10 parted | [] [] [] | 10 pilot-qof | [] | 3 psmisc | [] | 10 pwdutils | [] | 3 python | | 0 qof | [] | 4 radius | [] | 6 recode | [] [] [] | 25 rpm | [] [] [] [] | 14 screem | [] | 2 scrollkeeper | [] [] [] [] | 26 sed | [] [] [] | 22 sh-utils | [] | 15 shared-mime-info | [] [] [] [] | 24 sharutils | [] [] [] | 23 shishi | | 1 silky | [] | 4 skencil | [] | 7 sketch | | 6 solfege | | 2 soundtracker | [] [] | 9 sp | [] | 3 stardict | [] [] [] [] | 11 system-tools-ba... | [] [] [] [] [] [] [] | 37 tar | [] [] [] [] | 20 texinfo | [] [] [] | 15 textutils | [] [] [] | 17 tin | | 1 tp-robot | [] [] [] | 10 tuxpaint | [] [] [] | 16 unicode-han-tra... | | 0 unicode-transla... | | 2 util-linux | [] [] [] | 20 vorbis-tools | [] [] | 11 wastesedge | | 1 wdiff | [] [] | 22 wget | [] [] [] | 19 xchat | [] [] [] [] | 29 xkeyboard-config | [] [] [] [] | 11 xpad | [] [] [] | 14 +---------------------------------------------------+ 77 teams tg th tk tr uk ven vi wa xh zh_CN zh_HK zh_TW zu 170 domains 0 1 1 77 39 0 136 10 1 48 5 54 0 2028 Some counters in the preceding matrix are higher than the number of visible blocks let us expect. This is because a few extra PO files are used for implementing regional variants of languages, or language dialects. For a PO file in the matrix above to be effective, the package to which it applies should also have been internationalized and distributed as such by its maintainer. There might be an observable lag between the mere existence a PO file and its wide availability in a distribution. If October 2006 seems to be old, you may fetch a more recent copy of this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date matrix with full percentage details can be found at `http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. 1.6 Using `gettext' in new packages =================================== If you are writing a freely available program and want to internationalize it you are welcome to use GNU `gettext' in your package. Of course you have to respect the GNU Library General Public License which covers the use of the GNU `gettext' library. This means in particular that even non-free programs can use `libintl' as a shared library, whereas only free software can use `libintl' as a static library or use modified versions of `libintl'. Once the sources are changed appropriately and the setup can handle the use of `gettext' the only thing missing are the translations. The Free Translation Project is also available for packages which are not developed inside the GNU project. Therefore the information given above applies also for every other Free Software Project. Contact `translation@iro.umontreal.ca' to make the `.pot' files available to the translation teams. gnunet-0.10.1/configure0000755000175000017500000352752712320752055011747 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for gnunet 0.10.1. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and bug-gnunet@gnu.org $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='gnunet' PACKAGE_TARNAME='gnunet' PACKAGE_VERSION='0.10.1' PACKAGE_STRING='gnunet 0.10.1' PACKAGE_BUGREPORT='bug-gnunet@gnu.org' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" gt_needs= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS gitcommand svnversioncommand USE_COVERAGE_FALSE USE_COVERAGE_TRUE AUTOSTART HAVE_EXPERIMENTAL_FALSE HAVE_EXPERIMENTAL_TRUE HAVE_TESTING_FALSE HAVE_TESTING_TRUE HAVE_BENCHMARKS_FALSE HAVE_BENCHMARKS_TRUE JAVAPORT HAVE_EXPENSIVE_TESTS_FALSE HAVE_EXPENSIVE_TESTS_TRUE MONKEYPREFIX ENABLE_MONKEY_FALSE ENABLE_MONKEY_TRUE ENABLE_TEST_RUN_FALSE ENABLE_TEST_RUN_TRUE ENABLE_NSE_HISTOGRAM_FALSE ENABLE_NSE_HISTOGRAM_TRUE ENABLE_SUPERMUC_FALSE ENABLE_SUPERMUC_TRUE HAVE_GNUTLS_DANE_FALSE HAVE_GNUTLS_DANE_TRUE HAVE_GNUTLS_FALSE HAVE_GNUTLS_TRUE GNUNETDNS_GROUP INSTALL_NSS_FALSE INSTALL_NSS_TRUE NSS_DIR HAVE_SUDO_FALSE HAVE_SUDO_TRUE SUDO_BINARY DLLDIR LIBPREFIX EXT_LIBS EXT_LIB_PATH GN_LIBINTL GN_INTLINCL GN_PLUGIN_LDFLAGS GN_LIB_LDFLAGS WANT_FRAMEWORK_FALSE WANT_FRAMEWORK_TRUE LIBOBJS POSUB LTLIBINTL LIBINTL INTLLIBS INTL_MACOSX_LIBS XGETTEXT_EXTRA_OPTIONS MSGMERGE XGETTEXT_015 XGETTEXT GMSGFMT_015 MSGFMT_015 GMSGFMT MSGFMT GETTEXT_MACRO_VERSION USE_NLS HAVE_PYTHON_FALSE HAVE_PYTHON_TRUE pkgpyexecdir pyexecdir pkgpythondir pythondir PYTHON_PLATFORM PYTHON_EXEC_PREFIX PYTHON_PREFIX PYTHON_VERSION PYTHON HAVE_MHD_FALSE HAVE_MHD_TRUE HAVE_MYSQLE_FALSE HAVE_MYSQLE_TRUE HAVE_MYSQL_FALSE HAVE_MYSQL_TRUE MYSQL_CPPFLAGS MYSQL_LDFLAGS Z_LIBS Z_CFLAGS POSTGRES_LDFLAGS POSTGRES_CPPFLAGS HAVE_POSTGRES_FALSE HAVE_POSTGRES_TRUE SQLITE_LDFLAGS SQLITE_CPPFLAGS HAVE_SQLITE_FALSE HAVE_SQLITE_TRUE LTLIBUNISTRING LIBUNISTRING HAVE_LIBUNISTRING LTLIBICONV LIBICONV HAVE_GLIBCNSS_FALSE HAVE_GLIBCNSS_TRUE HAVE_LIBGLPK_FALSE HAVE_LIBGLPK_TRUE HAVE_LIBGNURL_FALSE HAVE_LIBGNURL_TRUE LIBGNURL LIBGNURL_CPPFLAGS _libgnurl_config BUILD_GST_HELPERS_FALSE BUILD_GST_HELPERS_TRUE BUILD_PULSE_HELPERS_FALSE BUILD_PULSE_HELPERS_TRUE GST_LIBS GST_CFLAGS PKG_CONFIG HAVE_OGG_FALSE HAVE_OGG_TRUE HAVE_LIBBLUETOOTH_FALSE HAVE_LIBBLUETOOTH_TRUE LIBGCRYPT_LIBS LIBGCRYPT_CFLAGS LIBGCRYPT_CONFIG build_target GNU_FALSE GNU_TRUE LINUX_FALSE LINUX_TRUE OPENBSD_FALSE OPENBSD_TRUE XFREEBSD_FALSE XFREEBSD_TRUE SOLARIS_FALSE SOLARIS_TRUE MINGW_FALSE MINGW_TRUE CYGWIN_FALSE CYGWIN_TRUE DARWIN_FALSE DARWIN_TRUE UNIXONLY DEFAULT_INTERFACE X_EXTRA_LIBS X_LIBS X_PRE_LIBS X_CFLAGS XMKMF CXXCPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED LIBTOOL OBJDUMP DLLTOOL AS LN_S am__fastdepOBJC_FALSE am__fastdepOBJC_TRUE OBJCDEPMODE ac_ct_OBJC OBJCFLAGS OBJC am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE ac_ct_CXX CXXFLAGS CXX CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking enable_static enable_shared with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_largefile with_x with_libgcrypt_prefix enable_gcc_hardening enable_linker_hardening enable_logging enable_poisoning with_libgnurl with_libidn with_extractor with_ltdl enable_rpath with_libiconv_prefix with_libunistring_prefix with_sqlite with_postgres with_zlib with_mysql enable_mysql_version_check with_microhttpd enable_nls with_libintl_prefix enable_framework with_sudo with_nssdir with_gnunetdns with_gnutls enable_supermuc enable_nse_histogram enable_testruns enable_monkey enable_expensivetests enable_javaports enable_benchmarks enable_testing enable_experimental enable_autostart enable_heapstats enable_windows_workarounds enable_coverage ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CXX CXXFLAGS CCC OBJC OBJCFLAGS CXXCPP XMKMF PYTHON' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures gnunet 0.10.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/gnunet] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of gnunet 0.10.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-largefile omit support for large files --enable-gcc-hardening enable compiler security checks --enable-linker-hardening enable linker security fixups --enable-logging[=value] Enable logging calls. Possible values: yes,no,verbose,veryverbose ('yes' is the default) --enable-poisoning enable poisoning of freed memory (good for debugging) --disable-rpath do not hardcode runtime library paths --disable-mysql-version-check do not check MySQL version --disable-nls do not use Native Language Support --enable-framework enable Mac OS X framework build helpers --enable-supermuc build GNUnet with support to run on the SuperMUC (default is NO) --enable-nse-histogram have NSE send timestamp information to testbed logger for generating histogram of received messages. NOT useful for production (default is NO) --disable-testruns disable running tests on make check (default is YES) --enable-monkey enable running with monkey --enable-expensivetests enable running expensive testcases --enable-javaports use non-zero ports for services with Java bindings (default is NO) --enable-benchmarks enable running benchmarks during make check --disable-testing do not build gnunet-testing --enable-experimental enable compiling experimental code --disable-autostart do not start peer's services by default --enable-heapstats enable expensive heap statistics --enable-windows_workarounds enable workarounds used on Windows (only useful for test cases) --enable-coverage compile the library with code coverage support Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-x use the X Window System --with-libgcrypt-prefix=PFX prefix where LIBGCRYPT is installed (optional) --with-libgnurl=PREFIX look for the gnurl library in PREFIX/lib and headers in PREFIX/include --with-libidn=DIR Support IDN (needs GNU Libidn) --with-extractor=PFX base of libextractor installation --with-ltdl=PFX base of libltdl installation --with-gnu-ld assume the C compiler uses GNU ld default=no --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib --without-libiconv-prefix don't search for libiconv in includedir and libdir --with-libunistring-prefix[=DIR] search for libunistring in DIR/include and DIR/lib --without-libunistring-prefix don't search for libunistring in includedir and libdir --with-sqlite=PFX base of SQLite installation --with-postgres=PFX base of postgres installation --with-zlib[=DIR] use libz in DIR --with-mysql=PFX base of MySQL installation --with-microhttpd=PFX base of libmicrohttpd installation --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib --without-libintl-prefix don't search for libintl in includedir and libdir --with-sudo=PATH path to sudo binary (or just yes) --with-nssdir=PATH where to install NSS plugins --with-gnunetdns=GRPNAME name for gnunetdns group --with-gnutls=PFX base of gnutls installation Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor CXX C++ compiler command CXXFLAGS C++ compiler flags OBJC Objective C compiler command OBJCFLAGS Objective C compiler flags CXXCPP C++ preprocessor XMKMF Path to xmkmf, Makefile generator for X Window System PYTHON the Python interpreter Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF gnunet configure 0.10.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_objc_try_compile LINENO # ----------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_objc_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_objc_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_objc_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## --------------------------------- ## ## Report this to bug-gnunet@gnu.org ## ## --------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 &5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by gnunet $as_me 0.10.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi gt_needs="$gt_needs " # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- am__api_version='1.14' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='gnunet' VERSION='0.10.1' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' ac_config_headers="$ac_config_headers gnunet_config.h" for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi ac_ext=m ac_cpp='$OBJCPP $CPPFLAGS' ac_compile='$OBJC -c $OBJCFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$OBJC -o conftest$ac_exeext $OBJCFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_objc_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in gcc objcc objc cc CC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJC"; then ac_cv_prog_OBJC="$OBJC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJC=$ac_cv_prog_OBJC if test -n "$OBJC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJC" >&5 $as_echo "$OBJC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$OBJC" && break done fi if test -z "$OBJC"; then ac_ct_OBJC=$OBJC for ac_prog in gcc objcc objc cc CC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJC"; then ac_cv_prog_ac_ct_OBJC="$ac_ct_OBJC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJC=$ac_cv_prog_ac_ct_OBJC if test -n "$ac_ct_OBJC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJC" >&5 $as_echo "$ac_ct_OBJC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_OBJC" && break done if test "x$ac_ct_OBJC" = x; then OBJC="gcc" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJC=$ac_ct_OBJC fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for Objective C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Objective C compiler" >&5 $as_echo_n "checking whether we are using the GNU Objective C compiler... " >&6; } if ${ac_cv_objc_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_objc_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_objc_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objc_compiler_gnu" >&5 $as_echo "$ac_cv_objc_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GOBJC=yes else GOBJC= fi ac_test_OBJCFLAGS=${OBJCFLAGS+set} ac_save_OBJCFLAGS=$OBJCFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $OBJC accepts -g" >&5 $as_echo_n "checking whether $OBJC accepts -g... " >&6; } if ${ac_cv_prog_objc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_objc_werror_flag=$ac_objc_werror_flag ac_objc_werror_flag=yes ac_cv_prog_objc_g=no OBJCFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_objc_try_compile "$LINENO"; then : ac_cv_prog_objc_g=yes else OBJCFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_objc_try_compile "$LINENO"; then : else ac_objc_werror_flag=$ac_save_objc_werror_flag OBJCFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_objc_try_compile "$LINENO"; then : ac_cv_prog_objc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_objc_werror_flag=$ac_save_objc_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_objc_g" >&5 $as_echo "$ac_cv_prog_objc_g" >&6; } if test "$ac_test_OBJCFLAGS" = set; then OBJCFLAGS=$ac_save_OBJCFLAGS elif test $ac_cv_prog_objc_g = yes; then if test "$GOBJC" = yes; then OBJCFLAGS="-g -O2" else OBJCFLAGS="-g" fi else if test "$GOBJC" = yes; then OBJCFLAGS="-O2" else OBJCFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$OBJC" am_compiler_list='gcc3 gcc' { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_OBJC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_OBJC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_OBJC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_OBJC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_OBJC_dependencies_compiler_type" >&5 $as_echo "$am_cv_OBJC_dependencies_compiler_type" >&6; } OBJCDEPMODE=depmode=$am_cv_OBJC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_OBJC_dependencies_compiler_type" = gcc3; then am__fastdepOBJC_TRUE= am__fastdepOBJC_FALSE='#' else am__fastdepOBJC_TRUE='#' am__fastdepOBJC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf # Set options # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=no fi enable_dlopen=yes enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. set dummy ${ac_tool_prefix}as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AS="${ac_tool_prefix}as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AS=$ac_cv_prog_AS if test -n "$AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 $as_echo "$AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AS"; then ac_ct_AS=$AS # Extract the first word of "as", so it can be a program name with args. set dummy as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AS"; then ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AS="as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AS=$ac_cv_prog_ac_ct_AS if test -n "$ac_ct_AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 $as_echo "$ac_ct_AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AS" = x; then AS="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AS=$ac_ct_AS fi else AS="$ac_cv_prog_AS" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi ;; esac test -z "$AS" && AS=as test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$OBJDUMP" && OBJDUMP=objdump # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu else _lt_caught_CXX_error=yes fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= compiler_needs_object_CXX=no export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_direct_absolute_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no inherit_rpath_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds reload_flag_CXX=$reload_flag reload_cmds_CXX=$reload_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC compiler_CXX=$CC for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes file_list_spec_CXX='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec_CXX='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. always_export_symbols_CXX=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty # executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath__CXX+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath__CXX"; then lt_cv_aix_libpath__CXX="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath__CXX fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX='$convenience' fi archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds its shared # libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_CXX=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_CXX=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=yes file_list_spec_CXX='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' enable_shared_with_static_runtimes_CXX=yes # Don't use ranlib old_postinstall_cmds_CXX='chmod 644 $oldlib' postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc_CXX=no hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec_CXX='' fi link_all_deplibs_CXX=yes allow_undefined_flag_CXX="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" if test "$lt_cv_apple_cc_single_mod" != "yes"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi else ld_shlibs_CXX=no fi ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; haiku*) archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs_CXX=yes ;; hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: case $host_cpu in hppa*64*|ia64*) ;; *) export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; *) hardcode_direct_CXX=yes hardcode_direct_absolute_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC*) case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; interix[3-9]*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: inherit_rpath_CXX=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac archive_cmds_need_lc_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [1-5].* | *pgcpp\ [1-5].*) prelink_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' old_archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' archive_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' hardcode_libdir_flag_spec_CXX='-R$libdir' whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object_CXX=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) ld_shlibs_CXX=yes ;; openbsd2*) # C++ shared libraries are fairly broken ld_shlibs_CXX=no ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no hardcode_direct_absolute_CXX=yes archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' export_dynamic_flag_spec_CXX='${wl}-E' whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else ld_shlibs_CXX=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx*) case $host in osf3*) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' ;; *) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' ;; esac hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_CXX=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag_CXX='${wl}-z,text' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag_CXX='${wl}-z,text' allow_undefined_flag_CXX='${wl}-z,nodefs' archive_cmds_need_lc_CXX=no hardcode_shlibpath_var_CXX=no hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes export_dynamic_flag_spec_CXX='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ '"$old_archive_cmds_CXX" reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ '"$reload_cmds_CXX" ;; *) archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX="${prev}${p}" else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX="${prev}${p}" else postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken case $host_os in interix[3-9]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. predep_objects_CXX= postdep_objects_CXX= postdeps_CXX= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then postdeps_CXX='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then postdeps_CXX='-library=Cstd -library=Crun' fi ;; esac ;; esac case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac compiler_lib_search_dirs_CXX= if test -n "${compiler_lib_search_path_CXX}"; then compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic_CXX='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static_CXX= ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix[4-9]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; dgux*) case $cc_basename in ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fPIC' lt_prog_compiler_static_CXX='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-fpic' lt_prog_compiler_static_CXX='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) # IBM XL 8.0, 9.0 on PPC and BlueGene lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-qpic' lt_prog_compiler_static_CXX='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic_CXX='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works_CXX=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works_CXX=yes fi else lt_cv_prog_compiler_static_works_CXX=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then : else lt_prog_compiler_static_CXX= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' case $host_os in aix[4-9]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' ;; esac ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs_CXX=no ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no with_gnu_ld_CXX=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc_CXX=no else lt_cv_archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 $as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || test -n "$runpath_var_CXX" || test "X$hardcode_automatic_CXX" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test "$hardcode_action_CXX" = relink || test "$inherit_rpath_CXX" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_commands="$ac_config_commands libtool" # Only expand once: # large file support # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : break fi rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 $as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac rm -rf conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 $as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } if ${ac_cv_sys_largefile_source+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* for off_t */ #include int main () { int (*fp) (FILE *, off_t, int) = fseeko; return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_sys_largefile_source=no; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGEFILE_SOURCE 1 #include /* for off_t */ #include int main () { int (*fp) (FILE *, off_t, int) = fseeko; return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_sys_largefile_source=1; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_cv_sys_largefile_source=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 $as_echo "$ac_cv_sys_largefile_source" >&6; } case $ac_cv_sys_largefile_source in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source _ACEOF ;; esac rm -rf conftest* # We used to try defining _XOPEN_SOURCE=500 too, to work around a bug # in glibc 2.1.3, but that breaks too many other things. # If you want fseeko and ftello with glibc, upgrade to a fixed glibc. if test $ac_cv_sys_largefile_source != unknown; then $as_echo "#define HAVE_FSEEKO 1" >>confdefs.h fi if test "$enable_shared" = "no" then as_fn_error $? "GNUnet only works with shared libraries. Sorry." "$LINENO" 5 fi CFLAGS="-Wall $CFLAGS" # use '-fno-strict-aliasing', but only if the compiler can take it if gcc -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then CFLAGS="-fno-strict-aliasing $CFLAGS" fi # Use Linux interface name unless the OS has a different preference DEFAULT_INTERFACE="\"eth0\"" funcstocheck="getnameinfo gethostname gethostbyname gethostbyaddr getaddrinfo" # Srcdir in a form that native compiler understands (i.e. DOS path on W32) native_srcdir=$srcdir # Check system type case "$host_os" in *darwin* | *rhapsody* | *macosx*) cat >>confdefs.h <<_ACEOF #define DARWIN 1 _ACEOF CPPFLAGS="-D_APPLE_C_SOURCE $CPPFLAGS" CFLAGS="-fno-common $CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The VPN application cannot be compiled on your OS" >&5 $as_echo "$as_me: WARNING: The VPN application cannot be compiled on your OS" >&2;} build_target="darwin" DEFAULT_INTERFACE="\"en0\"" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; linux*) cat >>confdefs.h <<_ACEOF #define LINUX 1 _ACEOF build_target="linux" LIBPREFIX= DLLDIR=lib UNIXONLY="#" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 $as_echo_n "checking for X... " >&6; } # Check whether --with-x was given. if test "${with_x+set}" = set; then : withval=$with_x; fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else case $x_includes,$x_libraries in #( *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : $as_echo_n "(cached) " >&6 else # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no rm -f -r conftest.dir if mkdir conftest.dir; then cd conftest.dir cat >Imakefile <<'_ACEOF' incroot: @echo incroot='${INCROOT}' usrlibdir: @echo usrlibdir='${USRLIBDIR}' libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl dylib la dll; do if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && test -f "$ac_im_libdir/libX11.$ac_extension"; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ac_x_includes= ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /usr/lib64 | /lib | /lib64) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -f -r conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R7/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R7 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R7/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R7 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # We can compile using X headers with no special include directory. ac_x_includes= else for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.i conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { XrmInitialize () ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else LIBS=$ac_save_LIBS for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl dylib la dll; do if test -r "$ac_dir/libX11.$ac_extension"; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no case $ac_x_includes,$ac_x_libraries in #( no,* | *,no | *\'*) # Didn't find X, or a directory has "'" in its name. ac_cv_have_x="have_x=no";; #( *) # Record where we found X for the cache. ac_cv_have_x="have_x=yes\ ac_x_includes='$ac_x_includes'\ ac_x_libraries='$ac_x_libraries'" esac fi ;; #( *) have_x=yes;; esac eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 $as_echo "$have_x" >&6; } no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes\ ac_x_includes='$x_includes'\ ac_x_libraries='$x_libraries'" { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 $as_echo "libraries $x_libraries, headers $x_includes" >&6; } fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. $as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 $as_echo_n "checking whether -R must be followed by a space... " >&6; } ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" ac_xsave_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } X_LIBS="$X_LIBS -R$x_libraries" else LIBS="$ac_xsave_LIBS -R $x_libraries" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } X_LIBS="$X_LIBS -R $x_libraries" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 $as_echo "neither works" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_c_werror_flag=$ac_xsave_c_werror_flag LIBS=$ac_xsave_LIBS fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn Johnson says this is needed for Ultrix, if the X # libraries were built with DECnet support. And Karl Berry says # the Alpha needs dnet_stub (dnet does not exist). ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char XOpenDisplay (); int main () { return XOpenDisplay (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnet_dnet_ntoa=yes else ac_cv_lib_dnet_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet_stub $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnet_stub_dnet_ntoa=yes else ac_cv_lib_dnet_stub_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_xsave_LIBS" # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to T.E. Dickey. # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" if test "x$ac_cv_func_gethostbyname" = xyes; then : fi if test $ac_cv_func_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } if ${ac_cv_lib_nsl_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_gethostbyname=yes else ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 $as_echo_n "checking for gethostbyname in -lbsd... " >&6; } if ${ac_cv_lib_bsd_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bsd_gethostbyname=yes else ac_cv_lib_bsd_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 $as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says Simon Leinen: it contains gethostby* # variants that don't use the name server (or something). -lsocket # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" if test "x$ac_cv_func_connect" = xyes; then : fi if test $ac_cv_func_connect = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 $as_echo_n "checking for connect in -lsocket... " >&6; } if ${ac_cv_lib_socket_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); int main () { return connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_connect=yes else ac_cv_lib_socket_connect=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 $as_echo "$ac_cv_lib_socket_connect" >&6; } if test "x$ac_cv_lib_socket_connect" = xyes; then : X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi fi # Guillermo Gomez says -lposix is necessary on A/UX. ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" if test "x$ac_cv_func_remove" = xyes; then : fi if test $ac_cv_func_remove = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 $as_echo_n "checking for remove in -lposix... " >&6; } if ${ac_cv_lib_posix_remove+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lposix $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char remove (); int main () { return remove (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_posix_remove=yes else ac_cv_lib_posix_remove=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 $as_echo "$ac_cv_lib_posix_remove" >&6; } if test "x$ac_cv_lib_posix_remove" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" if test "x$ac_cv_func_shmat" = xyes; then : fi if test $ac_cv_func_shmat = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 $as_echo_n "checking for shmat in -lipc... " >&6; } if ${ac_cv_lib_ipc_shmat+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lipc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shmat (); int main () { return shmat (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ipc_shmat=yes else ac_cv_lib_ipc_shmat=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 $as_echo "$ac_cv_lib_ipc_shmat" >&6; } if test "x$ac_cv_lib_ipc_shmat" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS=$LDFLAGS test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # John Interrante, Karl Berry { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 $as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char IceConnectionNumber (); int main () { return IceConnectionNumber (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ICE_IceConnectionNumber=yes else ac_cv_lib_ICE_IceConnectionNumber=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 $as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi LDFLAGS=$ac_save_LDFLAGS fi ;; *freebsd*) cat >>confdefs.h <<_ACEOF #define SOMEBSD 1 _ACEOF cat >>confdefs.h <<_ACEOF #define FREEBSD 1 _ACEOF CFLAGS="-D_THREAD_SAFE $CFLAGS" build_target="freebsd" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *openbsd*) cat >>confdefs.h <<_ACEOF #define SOMEBSD 1 _ACEOF cat >>confdefs.h <<_ACEOF #define OPENBSD 1 _ACEOF LIBS=`echo $LIBS | sed -e "s/-ldl//"` build_target="openbsd" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *netbsd*) cat >>confdefs.h <<_ACEOF #define SOMEBSD 1 _ACEOF cat >>confdefs.h <<_ACEOF #define NETBSD 1 _ACEOF LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *solaris*) cat >>confdefs.h <<_ACEOF #define SOLARIS 1 _ACEOF cat >>confdefs.h <<_ACEOF #define _REENTRANT 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_init in -lresolv" >&5 $as_echo_n "checking for res_init in -lresolv... " >&6; } if ${ac_cv_lib_resolv_res_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lresolv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char res_init (); int main () { return res_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_resolv_res_init=yes else ac_cv_lib_resolv_res_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_init" >&5 $as_echo "$ac_cv_lib_resolv_res_init" >&6; } if test "x$ac_cv_lib_resolv_res_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRESOLV 1 _ACEOF LIBS="-lresolv $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nanosleep in -lrt" >&5 $as_echo_n "checking for nanosleep in -lrt... " >&6; } if ${ac_cv_lib_rt_nanosleep+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char nanosleep (); int main () { return nanosleep (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rt_nanosleep=yes else ac_cv_lib_rt_nanosleep=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_nanosleep" >&5 $as_echo "$ac_cv_lib_rt_nanosleep" >&6; } if test "x$ac_cv_lib_rt_nanosleep" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRT 1 _ACEOF LIBS="-lrt $LIBS" fi build_target="solaris" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *arm-linux*) cat >>confdefs.h <<_ACEOF #define LINUX 1 _ACEOF CFLAGS="-D_REENTRANT -fPIC -pipe $CFLAGS" build_target="linux" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *cygwin*) cat >>confdefs.h <<_ACEOF #define CYGWIN 1 _ACEOF cat >>confdefs.h <<_ACEOF #define WINDOWS 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gettext in -lintl" >&5 $as_echo_n "checking for gettext in -lintl... " >&6; } if ${ac_cv_lib_intl_gettext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gettext (); int main () { return gettext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_gettext=yes else ac_cv_lib_intl_gettext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_gettext" >&5 $as_echo "$ac_cv_lib_intl_gettext" >&6; } if test "x$ac_cv_lib_intl_gettext" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBINTL 1 _ACEOF LIBS="-lintl $LIBS" fi CFLAGS="-mms-bitfields $CFLAGS" build_target="cygwin" LIBPREFIX=lib DLLDIR=bin ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi UNIXONLY="" ;; *mingw*) cat >>confdefs.h <<_ACEOF #define MINGW 1 _ACEOF cat >>confdefs.h <<_ACEOF #define WINDOWS 1 _ACEOF cat >>confdefs.h <<_ACEOF #define _WIN32 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gettext in -lintl" >&5 $as_echo_n "checking for gettext in -lintl... " >&6; } if ${ac_cv_lib_intl_gettext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gettext (); int main () { return gettext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_gettext=yes else ac_cv_lib_intl_gettext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_gettext" >&5 $as_echo "$ac_cv_lib_intl_gettext" >&6; } if test "x$ac_cv_lib_intl_gettext" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBINTL 1 _ACEOF LIBS="-lintl $LIBS" fi LDFLAGS="$LDFLAGS -Wl,--export-all-symbols" LIBS="$LIBS -lws2_32 -lplibc -lgnurx -lole32" CFLAGS="-mms-bitfields $CFLAGS" CPPFLAGS="-D_WIN32_WINNT=0x0501 -DHAVE_STAT64=1 -D__USE_MINGW_ANSI_STDIO=1 $CPPFLAGS" build_target="mingw" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CXX_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi LIBPREFIX=lib DLLDIR=bin UNIXONLY="" funcstocheck="" native_srcdir=$(cd $srcdir; pwd -W) ;; gnu*) cat >>confdefs.h <<_ACEOF #define GNU 1 _ACEOF build_target="gnu" UNIXONLY="#" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: Unrecognised OS $host_os" >&5 $as_echo "Unrecognised OS $host_os" >&6; } cat >>confdefs.h <<_ACEOF #define OTHEROS 1 _ACEOF UNIXONLY="" ;; esac cat >>confdefs.h <<_ACEOF #define GNUNET_DEFAULT_INTERFACE $DEFAULT_INTERFACE _ACEOF # Disable TCP-based IPC on systems that support UNIX domain # sockets in default configuratin: { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build target" >&5 $as_echo_n "checking for build target... " >&6; } if test "$build_target" = "darwin"; then DARWIN_TRUE= DARWIN_FALSE='#' else DARWIN_TRUE='#' DARWIN_FALSE= fi if test "$build_target" = "cygwin"; then CYGWIN_TRUE= CYGWIN_FALSE='#' else CYGWIN_TRUE='#' CYGWIN_FALSE= fi if test "$build_target" = "mingw"; then MINGW_TRUE= MINGW_FALSE='#' else MINGW_TRUE='#' MINGW_FALSE= fi if test "$build_target" = "solaris"; then SOLARIS_TRUE= SOLARIS_FALSE='#' else SOLARIS_TRUE='#' SOLARIS_FALSE= fi if test "$build_target" = "freebsd"; then XFREEBSD_TRUE= XFREEBSD_FALSE='#' else XFREEBSD_TRUE='#' XFREEBSD_FALSE= fi if test "$build_target" = "openbsd"; then OPENBSD_TRUE= OPENBSD_FALSE='#' else OPENBSD_TRUE='#' OPENBSD_FALSE= fi if test "$build_target" = "linux"; then LINUX_TRUE= LINUX_FALSE='#' else LINUX_TRUE='#' LINUX_FALSE= fi if test "$build_target" = "gnu"; then GNU_TRUE= GNU_FALSE='#' else GNU_TRUE='#' GNU_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $build_target" >&5 $as_echo "$build_target" >&6; } if false; then am__fastdepOBJC_TRUE= am__fastdepOBJC_FALSE='#' else am__fastdepOBJC_TRUE='#' am__fastdepOBJC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether unaligned 64-bit access works" >&5 $as_echo_n "checking whether unaligned 64-bit access works... " >&6; } if ${ac_cv_unaligned_64_access+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ struct S { int a,b,c;}; int main () { struct S s = {0,0,0}; long long * p = (long long *) &s.b; void *bp = malloc (50); long long x = *p; long long *be = (long long*) &bp[1]; long long y = *be; return (int) x*y; ; return 0; }, ac_cv_unaligned_64_access=yes, ac_cv_unaligned_64_access=no, ac_cv_unaligned_64_access=no _ACEOF if ac_fn_c_try_run "$LINENO"; then : fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_unaligned_64_access" >&5 $as_echo "$ac_cv_unaligned_64_access" >&6; } case "$ac_cv_unaligned_64_access" in *yes) value=1;; *) value=0;; esac cat >>confdefs.h <<_ACEOF #define HAVE_UNALIGNED_64_ACCESS $value _ACEOF # some other checks for standard libs { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 $as_echo_n "checking for library containing gethostbyname... " >&6; } if ${ac_cv_search_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF for ac_lib in '' nsl ws2_32; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gethostbyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gethostbyname+:} false; then : break fi done if ${ac_cv_search_gethostbyname+:} false; then : else ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 $as_echo "$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socket=yes else ac_cv_lib_socket_socket=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 $as_echo "$ac_cv_lib_socket_socket" >&6; } if test "x$ac_cv_lib_socket_socket" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSOCKET 1 _ACEOF LIBS="-lsocket $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for log in -lm" >&5 $as_echo_n "checking for log in -lm... " >&6; } if ${ac_cv_lib_m_log+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char log (); int main () { return log (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_log=yes else ac_cv_lib_m_log=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_log" >&5 $as_echo "$ac_cv_lib_m_log" >&6; } if test "x$ac_cv_lib_m_log" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getloadavg in -lc" >&5 $as_echo_n "checking for getloadavg in -lc... " >&6; } if ${ac_cv_lib_c_getloadavg+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getloadavg (); int main () { return getloadavg (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_getloadavg=yes else ac_cv_lib_c_getloadavg=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_getloadavg" >&5 $as_echo "$ac_cv_lib_c_getloadavg" >&6; } if test "x$ac_cv_lib_c_getloadavg" = xyes; then : $as_echo "#define HAVE_GETLOADAVG 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" "#include " if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes; then : $as_echo "#define HAVE_TM_GMTOFF 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "_stati64" "ac_cv_have_decl__stati64" "$ac_includes_default" if test "x$ac_cv_have_decl__stati64" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL__STATI64 $ac_have_decl _ACEOF # 'save' libs; only those libs found so far will be # linked against _everywhere_. For the others, we # will be more selective! SAVE_LIBS=$LIBS # libgnurx (regex library for W32) gnurx=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for regexec in -lgnurx" >&5 $as_echo_n "checking for regexec in -lgnurx... " >&6; } if ${ac_cv_lib_gnurx_regexec+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnurx $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char regexec (); int main () { return regexec (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnurx_regexec=yes else ac_cv_lib_gnurx_regexec=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnurx_regexec" >&5 $as_echo "$ac_cv_lib_gnurx_regexec" >&6; } if test "x$ac_cv_lib_gnurx_regexec" = xyes; then : gnurx=1 fi if test "x$gnurx" = "x0" -a "x$build_target" = "xmingw" then as_fn_error $? "on W32 GNUnet needs libgnurx" "$LINENO" 5 fi # libgcrypt gcrypt=0 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.6.0 # Check whether --with-libgcrypt-prefix was given. if test "${with_libgcrypt_prefix+set}" = set; then : withval=$with_libgcrypt_prefix; libgcrypt_config_prefix="$withval" else libgcrypt_config_prefix="" fi if test x$libgcrypt_config_prefix != x ; then if test x${LIBGCRYPT_CONFIG+set} != xset ; then LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config fi fi # Extract the first word of "libgcrypt-config", so it can be a program name with args. set dummy libgcrypt-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $LIBGCRYPT_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_LIBGCRYPT_CONFIG" && ac_cv_path_LIBGCRYPT_CONFIG="no" ;; esac fi LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG if test -n "$LIBGCRYPT_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5 $as_echo "$LIBGCRYPT_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi tmp="$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION" if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` else req_libgcrypt_api=0 min_libgcrypt_version="$tmp" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5 $as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; } ok=no if test "$LIBGCRYPT_CONFIG" != "no" ; then req_major=`echo $min_libgcrypt_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` req_minor=`echo $min_libgcrypt_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` req_micro=`echo $min_libgcrypt_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` major=`echo $libgcrypt_config_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'` minor=`echo $libgcrypt_config_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'` micro=`echo $libgcrypt_config_version | \ sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'` if test "$major" -gt "$req_major"; then ok=yes else if test "$major" -eq "$req_major"; then if test "$minor" -gt "$req_minor"; then ok=yes else if test "$minor" -eq "$req_minor"; then if test "$micro" -ge "$req_micro"; then ok=yes fi fi fi fi fi fi if test $ok = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test $ok = yes; then # If we have a recent libgcrypt, we should also check that the # API is compatible if test "$req_libgcrypt_api" -gt 0 ; then tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` if test "$tmp" -gt 0 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGCRYPT API version" >&5 $as_echo_n "checking LIBGCRYPT API version... " >&6; } if test "$req_libgcrypt_api" -eq "$tmp" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5 $as_echo "okay" >&6; } else ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match (want=$req_libgcrypt_api got=$tmp)" >&5 $as_echo "does not match (want=$req_libgcrypt_api got=$tmp)" >&6; } fi fi fi fi if test $ok = yes; then LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` gcrypt=1 else LIBGCRYPT_CFLAGS="" LIBGCRYPT_LIBS="" : fi ac_fn_c_check_decl "$LINENO" "gcry_mpi_set_opaque_copy" "ac_cv_have_decl_gcry_mpi_set_opaque_copy" "#include " if test "x$ac_cv_have_decl_gcry_mpi_set_opaque_copy" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GCRY_MPI_SET_OPAQUE_COPY $ac_have_decl _ACEOF if test $gcrypt = 0 then as_fn_error $? " *** *** You need libgcrypt to build this program. ** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/libgcrypt/ *** (at least version $NEED_LIBGCRYPT_VERSION (API $NEED_LIBGCRYPT_API) *** is required.) ***" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define NEED_LIBGCRYPT_VERSION "$NEED_LIBGCRYPT_VERSION" _ACEOF # Adam shostack suggests the following for Windows: # -D_FORTIFY_SOURCE=2 -fstack-protector-all # Check whether --enable-gcc-hardening was given. if test "${enable_gcc_hardening+set}" = set; then : enableval=$enable_gcc_hardening; if test x$enableval = xyes; then CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -fstack-protector-all" CFLAGS="$CFLAGS -fwrapv -fPIE -Wstack-protector" CFLAGS="$CFLAGS --param ssp-buffer-size=1" LDFLAGS="$LDFLAGS -pie" fi fi # Linker hardening options # Currently these options are ELF specific - you can't use this with MacOSX # Check whether --enable-linker-hardening was given. if test "${enable_linker_hardening+set}" = set; then : enableval=$enable_linker_hardening; if test x$enableval = xyes; then LDFLAGS="$LDFLAGS -z relro -z now" fi fi extra_logging=GNUNET_NO # Check whether --enable-logging was given. if test "${enable_logging+set}" = set; then : enableval=$enable_logging; if test "x$enableval" = "xyes"; then : elif test "x$enableval" = "xno"; then : $as_echo "#define GNUNET_CULL_LOGGING /**/" >>confdefs.h elif test "x$enableval" = "xverbose"; then : extra_logging=GNUNET_YES test "x$enableval" = "xveryverbose" else extra_logging=\(GNUNET_YES+1\) fi fi cat >>confdefs.h <<_ACEOF #define GNUNET_EXTRA_LOGGING $extra_logging _ACEOF # should memory poisoning be enabled? { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to poison freed memory" >&5 $as_echo_n "checking whether to poison freed memory... " >&6; } # Check whether --enable-poisoning was given. if test "${enable_poisoning+set}" = set; then : enableval=$enable_poisoning; enable_poisoning=${enableval} else if test "x$extra_logging" != "xGNUNET_NO"; then enable_poisoning="defaults to yes (extra logging is enabled)" else enable_poisoning=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_poisoning" >&5 $as_echo "$enable_poisoning" >&6; } if test ! "x$enable_poisoning" = "xno"; then enable_poisoning=1 else enable_poisoning=0 fi cat >>confdefs.h <<_ACEOF #define ENABLE_POISONING $enable_poisoning _ACEOF if test $build = $target then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working HMAC" >&5 $as_echo_n "checking for working HMAC... " >&6; } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu LIBS="$LIBS $LIBGCRYPT_LIBS" CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS" if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { gcry_md_hd_t mac; unsigned char data[] = { 0xbf, 0x16, 0x6e, 0x46, 0x3a, 0x6c, 0xf3, 0x93, 0xa7, 0x72, 0x11, 0xa1, 0xdc, 0x0b, 0x07, 0xdb, 0x1a, 0x5e, 0xd9, 0xb9, 0x81, 0xbe, 0xea, 0xe4, 0x31, 0x5f, 0x24, 0xff, 0xfe, 0x50, 0x8a, 0xde }; unsigned char key[] = { 0xfc, 0x62, 0x76, 0x35 }; unsigned char result[] = {0xa2, 0xb, 0x1, 0xd9, 0xc0, 0x8b, 0x5a, 0x12, 0x80, 0xd5, 0x50, 0x12, 0x8e, 0xd0, 0x5b, 0xb6, 0x5c, 0x87, 0x24, 0xe2, 0xd0, 0xd2, 0xaf, 0x63, 0xae, 0xd1, 0xd6, 0x64, 0x14, 0xe3, 0x6e, 0x61, 0x5b, 0xd, 0xba, 0x17, 0x7d, 0xd3, 0x10, 0xb1, 0x37, 0x41, 0x91, 0x7d, 0xeb, 0x1, 0x4d, 0x71, 0xe8, 0x59, 0x71, 0x42, 0x8e, 0xd6, 0xf3, 0x29, 0x3b, 0x90, 0xf2, 0xd1, 0xaf, 0x65, 0x1e, 0xb3}; if (!gcry_check_version (GCRYPT_VERSION)) { fprintf (stderr, "Version mismatch %s <-> %s \n", gcry_check_version (NULL), GCRYPT_VERSION); return 1; } gcry_control (GCRYCTL_DISABLE_SECMEM, 0); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); if (gcry_md_open(&mac, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR) { fprintf (stderr, "gcry_md_open error\n"); return 2; } gcry_md_setkey (mac, key, sizeof (key)); gcry_md_write (mac, data, sizeof (data)); if (memcmp(gcry_md_read (mac, 0), result, gcry_md_get_algo_dlen (gcry_md_get_algo (mac))) != 0) { fprintf (stderr, "memcmp error\n"); return 3; } gcry_md_close (mac); return 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else RESULT=$? if test $RESULT = 3 then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "HMAC test vector does not match. This is a known problem with libgcrypt 1.2.2 on Windows and fixed in 1.4.6. See \`config.log' for more details" "$LINENO" 5; } fi if test $RESULT = 2 then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "HMAC test failed See \`config.log' for more details" "$LINENO" 5; } fi if test $RESULT = 1 then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "libgcrypt header version does not match library version See \`config.log' for more details" "$LINENO" 5; } fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi # $build = $target # check for bluetooth library bluetooth=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ba2str in -lbluetooth" >&5 $as_echo_n "checking for ba2str in -lbluetooth... " >&6; } if ${ac_cv_lib_bluetooth_ba2str+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbluetooth $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ba2str (); int main () { return ba2str (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bluetooth_ba2str=yes else ac_cv_lib_bluetooth_ba2str=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bluetooth_ba2str" >&5 $as_echo "$ac_cv_lib_bluetooth_ba2str" >&6; } if test "x$ac_cv_lib_bluetooth_ba2str" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "bluetooth/bluetooth.h" "ac_cv_header_bluetooth_bluetooth_h" "$ac_includes_default" if test "x$ac_cv_header_bluetooth_bluetooth_h" = xyes; then : bluetooth=1 fi fi if test "$bluetooth" = 1 then if true; then HAVE_LIBBLUETOOTH_TRUE= HAVE_LIBBLUETOOTH_FALSE='#' else HAVE_LIBBLUETOOTH_TRUE='#' HAVE_LIBBLUETOOTH_FALSE= fi $as_echo "#define HAVE_LIBBLUETOOTH 1" >>confdefs.h else if false; then HAVE_LIBBLUETOOTH_TRUE= HAVE_LIBBLUETOOTH_FALSE='#' else HAVE_LIBBLUETOOTH_TRUE='#' HAVE_LIBBLUETOOTH_FALSE= fi fi if test "$build_target" = "mingw" then bluetooth=1 fi # check for libpulse(audio) library pulse=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pa_stream_peek in -lpulse" >&5 $as_echo_n "checking for pa_stream_peek in -lpulse... " >&6; } if ${ac_cv_lib_pulse_pa_stream_peek+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpulse $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pa_stream_peek (); int main () { return pa_stream_peek (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pulse_pa_stream_peek=yes else ac_cv_lib_pulse_pa_stream_peek=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pulse_pa_stream_peek" >&5 $as_echo "$ac_cv_lib_pulse_pa_stream_peek" >&6; } if test "x$ac_cv_lib_pulse_pa_stream_peek" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "pulse/simple.h" "ac_cv_header_pulse_simple_h" "$ac_includes_default" if test "x$ac_cv_header_pulse_simple_h" = xyes; then : pulse=1 fi fi if test "$pulse" = 1 then $as_echo "#define HAVE_PULSE 1" >>confdefs.h fi if test "$build_target" = "mingw" then pulse=0 fi # check for libopus(audio) library opus=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for opus_decode_float in -lopus" >&5 $as_echo_n "checking for opus_decode_float in -lopus... " >&6; } if ${ac_cv_lib_opus_opus_decode_float+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lopus $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opus_decode_float (); int main () { return opus_decode_float (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_opus_opus_decode_float=yes else ac_cv_lib_opus_opus_decode_float=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opus_opus_decode_float" >&5 $as_echo "$ac_cv_lib_opus_opus_decode_float" >&6; } if test "x$ac_cv_lib_opus_opus_decode_float" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "opus/opus.h" "ac_cv_header_opus_opus_h" "$ac_includes_default" if test "x$ac_cv_header_opus_opus_h" = xyes; then : ac_fn_c_check_decl "$LINENO" "OPUS_SET_GAIN" "ac_cv_have_decl_OPUS_SET_GAIN" "#include " if test "x$ac_cv_have_decl_OPUS_SET_GAIN" = xyes; then : opus=1 fi fi fi if test "$opus" = 1 then $as_echo "#define HAVE_OPUS 1" >>confdefs.h fi # libogg { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ogg_stream_flush_fill in -logg" >&5 $as_echo_n "checking for ogg_stream_flush_fill in -logg... " >&6; } if ${ac_cv_lib_ogg_ogg_stream_flush_fill+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-logg $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ogg_stream_flush_fill (); int main () { return ogg_stream_flush_fill (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ogg_ogg_stream_flush_fill=yes else ac_cv_lib_ogg_ogg_stream_flush_fill=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ogg_ogg_stream_flush_fill" >&5 $as_echo "$ac_cv_lib_ogg_ogg_stream_flush_fill" >&6; } if test "x$ac_cv_lib_ogg_ogg_stream_flush_fill" = xyes; then : for ac_header in ogg/ogg.h do : ac_fn_c_check_header_mongrel "$LINENO" "ogg/ogg.h" "ac_cv_header_ogg_ogg_h" "$ac_includes_default" if test "x$ac_cv_header_ogg_ogg_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_OGG_OGG_H 1 _ACEOF if true; then HAVE_OGG_TRUE= HAVE_OGG_FALSE='#' else HAVE_OGG_TRUE='#' HAVE_OGG_FALSE= fi ogg=1 $as_echo "#define HAVE_OGG 1" >>confdefs.h else if false; then HAVE_OGG_TRUE= HAVE_OGG_FALSE='#' else HAVE_OGG_TRUE='#' HAVE_OGG_FALSE= fi ogg=0 $as_echo "#define HAVE_OGG 0" >>confdefs.h fi done else if false; then HAVE_OGG_TRUE= HAVE_OGG_FALSE='#' else HAVE_OGG_TRUE='#' HAVE_OGG_FALSE= fi ogg=0 fi gst=0 succeeded=no if test -z "$PKG_CONFIG"; then # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test "$PKG_CONFIG" = "no" ; then echo "*** The pkg-config script could not be found. Make sure it is" echo "*** in your path, or set the PKG_CONFIG environment variable" echo "*** to the full path to pkg-config." echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." else PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glib-2.0 gobject-2.0 gstreamer-1.0 gstreamer-app-1.0 gstreamer-audio-1.0" >&5 $as_echo_n "checking for glib-2.0 gobject-2.0 gstreamer-1.0 gstreamer-app-1.0 gstreamer-audio-1.0... " >&6; } if $PKG_CONFIG --exists "glib-2.0 gobject-2.0 gstreamer-1.0 gstreamer-app-1.0 gstreamer-audio-1.0" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } succeeded=yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking GST_CFLAGS" >&5 $as_echo_n "checking GST_CFLAGS... " >&6; } GST_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 gobject-2.0 gstreamer-1.0 gstreamer-app-1.0 gstreamer-audio-1.0"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GST_CFLAGS" >&5 $as_echo "$GST_CFLAGS" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking GST_LIBS" >&5 $as_echo_n "checking GST_LIBS... " >&6; } GST_LIBS=`$PKG_CONFIG --libs "glib-2.0 gobject-2.0 gstreamer-1.0 gstreamer-app-1.0 gstreamer-audio-1.0"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GST_LIBS" >&5 $as_echo "$GST_LIBS" >&6; } else GST_CFLAGS="" GST_LIBS="" ## If we have a custom action on failure, don't print errors, but ## do set a variable so people can do so. GST_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "glib-2.0 gobject-2.0 gstreamer-1.0 gstreamer-app-1.0 gstreamer-audio-1.0"` fi else echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." echo "*** See http://www.freedesktop.org/software/pkgconfig" fi fi if test $succeeded = yes; then gst=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else gst=0 { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } fi # Pulse Audio if test "x$pulse" != "x1" -o "x$opus" != "x1" -o "x$ogg" != "x1" then if test "x$gst" != "x1" then conversation_backend=none if false; then BUILD_PULSE_HELPERS_TRUE= BUILD_PULSE_HELPERS_FALSE='#' else BUILD_PULSE_HELPERS_TRUE='#' BUILD_PULSE_HELPERS_FALSE= fi if false; then BUILD_GST_HELPERS_TRUE= BUILD_GST_HELPERS_FALSE='#' else BUILD_GST_HELPERS_TRUE='#' BUILD_GST_HELPERS_FALSE= fi else conversation_backend=gst if false; then BUILD_PULSE_HELPERS_TRUE= BUILD_PULSE_HELPERS_FALSE='#' else BUILD_PULSE_HELPERS_TRUE='#' BUILD_PULSE_HELPERS_FALSE= fi if true; then BUILD_GST_HELPERS_TRUE= BUILD_GST_HELPERS_FALSE='#' else BUILD_GST_HELPERS_TRUE='#' BUILD_GST_HELPERS_FALSE= fi fi else conversation_backend=pulse if true; then BUILD_PULSE_HELPERS_TRUE= BUILD_PULSE_HELPERS_FALSE='#' else BUILD_PULSE_HELPERS_TRUE='#' BUILD_PULSE_HELPERS_FALSE= fi if false; then BUILD_GST_HELPERS_TRUE= BUILD_GST_HELPERS_FALSE='#' else BUILD_GST_HELPERS_TRUE='#' BUILD_GST_HELPERS_FALSE= fi fi # libgnurl # Check whether --with-libgnurl was given. if test "${with_libgnurl+set}" = set; then : withval=$with_libgnurl; _libgnurl_with=$withval else _libgnurl_with=yes fi if test "$_libgnurl_with" != "no" ; then for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done _libgnurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[1]+256*A[2]+A[3]; print X;}'" _libgnurl_try_link=yes if test -d "$_libgnurl_with" ; then LIBGNURL_CPPFLAGS="-I$withval/include" _libgnurl_ldflags="-L$withval/lib" # Extract the first word of "gnurl-config", so it can be a program name with args. set dummy gnurl-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path__libgnurl_config+:} false; then : $as_echo_n "(cached) " >&6 else case $_libgnurl_config in [\\/]* | ?:[\\/]*) ac_cv_path__libgnurl_config="$_libgnurl_config" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in "$withval/bin" do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path__libgnurl_config="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi _libgnurl_config=$ac_cv_path__libgnurl_config if test -n "$_libgnurl_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_libgnurl_config" >&5 $as_echo "$_libgnurl_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else # Extract the first word of "gnurl-config", so it can be a program name with args. set dummy gnurl-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path__libgnurl_config+:} false; then : $as_echo_n "(cached) " >&6 else case $_libgnurl_config in [\\/]* | ?:[\\/]*) ac_cv_path__libgnurl_config="$_libgnurl_config" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path__libgnurl_config="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi _libgnurl_config=$ac_cv_path__libgnurl_config if test -n "$_libgnurl_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_libgnurl_config" >&5 $as_echo "$_libgnurl_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test x$_libgnurl_config != "x" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the version of libgnurl" >&5 $as_echo_n "checking for the version of libgnurl... " >&6; } if ${libgnurl_cv_lib_gnurl_version+:} false; then : $as_echo_n "(cached) " >&6 else libgnurl_cv_lib_gnurl_version=`$_libgnurl_config --version | $AWK '{print $2}'` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgnurl_cv_lib_gnurl_version" >&5 $as_echo "$libgnurl_cv_lib_gnurl_version" >&6; } _libgnurl_version=`echo $libgnurl_cv_lib_gnurl_version | $_libgnurl_version_parse` _libgnurl_wanted=`echo 7.34.0 | $_libgnurl_version_parse` if test $_libgnurl_wanted -gt 0 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libgnurl >= version 7.34.0" >&5 $as_echo_n "checking for libgnurl >= version 7.34.0... " >&6; } if ${libgnurl_cv_lib_version_ok+:} false; then : $as_echo_n "(cached) " >&6 else if test $_libgnurl_version -ge $_libgnurl_wanted ; then libgnurl_cv_lib_version_ok=yes else libgnurl_cv_lib_version_ok=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgnurl_cv_lib_version_ok" >&5 $as_echo "$libgnurl_cv_lib_version_ok" >&6; } fi if test $_libgnurl_wanted -eq 0 || test x$libgnurl_cv_lib_version_ok = xyes ; then if test x"$LIBGNURL_CPPFLAGS" = "x" ; then LIBGNURL_CPPFLAGS=`$_libgnurl_config --cflags` fi if test x"$LIBGNURL" = "x" ; then LIBGNURL=`$_libgnurl_config --libs` # This is so silly, but Apple actually has a bug in their # gnurl-config script. Fixed in Tiger, but there are still # lots of Panther installs around. case "${host}" in powerpc-apple-darwin7*) LIBGNURL=`echo $LIBGNURL | sed -e 's|-arch i386||g'` ;; esac fi # All gnurl-config scripts support --feature _libgnurl_features=`$_libgnurl_config --feature` # Is it modern enough to have --protocols? (7.12.4) if test $_libgnurl_version -ge 461828 ; then _libgnurl_protocols=`$_libgnurl_config --protocols` fi else _libgnurl_try_link=no fi unset _libgnurl_wanted fi if test $_libgnurl_try_link = yes ; then # we didn't find gnurl-config, so let's see if the user-supplied # link line (or failing that, "-lgnurl") is enough. LIBGNURL=${LIBGNURL-"$_libgnurl_ldflags -lgnurl"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libgnurl is usable" >&5 $as_echo_n "checking whether libgnurl is usable... " >&6; } if ${libgnurl_cv_lib_gnurl_usable+:} false; then : $as_echo_n "(cached) " >&6 else _libgnurl_save_cppflags=$CPPFLAGS CPPFLAGS="$LIBGNURL_CPPFLAGS $CPPFLAGS" _libgnurl_save_libs=$LIBS LIBS="$LIBGNURL $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { /* Try and use a few common options to force a failure if we are missing symbols or can't link. */ int x; curl_easy_setopt(NULL,CURLOPT_URL,NULL); x=CURL_ERROR_SIZE; x=CURLOPT_WRITEFUNCTION; x=CURLOPT_FILE; x=CURLOPT_ERRORBUFFER; x=CURLOPT_STDERR; x=CURLOPT_VERBOSE; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : libgnurl_cv_lib_gnurl_usable=yes else libgnurl_cv_lib_gnurl_usable=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS=$_libgnurl_save_cppflags LIBS=$_libgnurl_save_libs unset _libgnurl_save_cppflags unset _libgnurl_save_libs fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgnurl_cv_lib_gnurl_usable" >&5 $as_echo "$libgnurl_cv_lib_gnurl_usable" >&6; } if test $libgnurl_cv_lib_gnurl_usable = yes ; then # Does gnurl_free() exist in this version of libgnurl? # If not, fake it with free() _libgnurl_save_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LIBGNURL_CPPFLAGS" _libgnurl_save_libs=$LIBS LIBS="$LIBS $LIBGNURL" ac_fn_c_check_func "$LINENO" "curl_free" "ac_cv_func_curl_free" if test "x$ac_cv_func_curl_free" = xyes; then : else $as_echo "#define curl_free free" >>confdefs.h fi CPPFLAGS=$_libgnurl_save_cppflags LIBS=$_libgnurl_save_libs unset _libgnurl_save_cppflags unset _libgnurl_save_libs $as_echo "#define HAVE_LIBGNURL 1" >>confdefs.h for _libgnurl_feature in $_libgnurl_features ; do cat >>confdefs.h <<_ACEOF #define `$as_echo "libgnurl_feature_$_libgnurl_feature" | $as_tr_cpp` 1 _ACEOF eval `$as_echo "libgnurl_feature_$_libgnurl_feature" | $as_tr_sh`=yes done if test "x$_libgnurl_protocols" = "x" ; then # We don't have --protocols, so just assume that all # protocols are available _libgnurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" if test x$libgnurl_feature_SSL = xyes ; then _libgnurl_protocols="$_libgnurl_protocols HTTPS" # FTPS wasn't standards-compliant until version # 7.11.0 (0x070b00 == 461568) if test $_libgnurl_version -ge 461568; then _libgnurl_protocols="$_libgnurl_protocols FTPS" fi fi # RTSP, IMAP, POP3 and SMTP were added in # 7.20.0 (0x071400 == 463872) if test $_libgnurl_version -ge 463872; then _libgnurl_protocols="$_libgnurl_protocols RTSP IMAP POP3 SMTP" fi fi for _libgnurl_protocol in $_libgnurl_protocols ; do cat >>confdefs.h <<_ACEOF #define `$as_echo "libgnurl_protocol_$_libgnurl_protocol" | $as_tr_cpp` 1 _ACEOF eval `$as_echo "libgnurl_protocol_$_libgnurl_protocol" | $as_tr_sh`=yes done else unset LIBGNURL unset LIBGNURL_CPPFLAGS fi fi unset _libgnurl_try_link unset _libgnurl_version_parse unset _libgnurl_config unset _libgnurl_feature unset _libgnurl_features unset _libgnurl_protocol unset _libgnurl_protocols unset _libgnurl_version unset _libgnurl_ldflags fi if test x$_libgnurl_with = xno || test x$libgnurl_cv_lib_gnurl_usable != xyes ; then # This is the IF-NO path gnurl=0 else # This is the IF-YES path gnurl=1 fi unset _libgnurl_with if test "$gnurl" = 1 then if true; then HAVE_LIBGNURL_TRUE= HAVE_LIBGNURL_FALSE='#' else HAVE_LIBGNURL_TRUE='#' HAVE_LIBGNURL_FALSE= fi $as_echo "#define HAVE_LIBGNURL 1" >>confdefs.h else if false; then HAVE_LIBGNURL_TRUE= HAVE_LIBGNURL_FALSE='#' else HAVE_LIBGNURL_TRUE='#' HAVE_LIBGNURL_FALSE= fi fi # libidn { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Libidn can be used" >&5 $as_echo_n "checking if Libidn can be used... " >&6; } # Check whether --with-libidn was given. if test "${with_libidn+set}" = set; then : withval=$with_libidn; libidn=$withval else libidn=yes fi if test "$libidn" != "no"; then if test "$libidn" != "yes"; then LDFLAGS="${LDFLAGS} -L$libidn/lib" CPPFLAGS="${CPPFLAGS} -I$libidn/include" fi fi libidn=no ac_fn_c_check_header_mongrel "$LINENO" "idna.h" "ac_cv_header_idna_h" "$ac_includes_default" if test "x$ac_cv_header_idna_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stringprep_check_version in -lidn" >&5 $as_echo_n "checking for stringprep_check_version in -lidn... " >&6; } if ${ac_cv_lib_idn_stringprep_check_version+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lidn $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char stringprep_check_version (); int main () { return stringprep_check_version (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_idn_stringprep_check_version=yes else ac_cv_lib_idn_stringprep_check_version=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_idn_stringprep_check_version" >&5 $as_echo "$ac_cv_lib_idn_stringprep_check_version" >&6; } if test "x$ac_cv_lib_idn_stringprep_check_version" = xyes; then : libidn=yes LIBS="${LIBS} -lidn" fi fi if test "$libidn" != "yes"; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "GNUnet requires libidn. libidn-1.13 should be sufficient, newer versions work too. See \`config.log' for more details" "$LINENO" 5; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libidn" >&5 $as_echo "$libidn" >&6; } # restore LIBS LIBS=$SAVE_LIBS for ac_header in glpk.h do : ac_fn_c_check_header_mongrel "$LINENO" "glpk.h" "ac_cv_header_glpk_h" "$ac_includes_default" if test "x$ac_cv_header_glpk_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GLPK_H 1 _ACEOF glpk=true else gplk=false fi done # GLPK must support glpk_init_env, version >= 4.43 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glp_init_env in -lglpk" >&5 $as_echo_n "checking for glp_init_env in -lglpk... " >&6; } if ${ac_cv_lib_glpk_glp_init_env+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lglpk $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char glp_init_env (); int main () { return glp_init_env (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_glpk_glp_init_env=yes else ac_cv_lib_glpk_glp_init_env=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_glpk_glp_init_env" >&5 $as_echo "$ac_cv_lib_glpk_glp_init_env" >&6; } if test "x$ac_cv_lib_glpk_glp_init_env" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBGLPK 1 _ACEOF LIBS="-lglpk $LIBS" else gplk=false fi # GLPK must support atm MLP presolving, version >= 4.32 ac_fn_c_check_member "$LINENO" "glp_iocp" "presolve" "ac_cv_member_glp_iocp_presolve" "#include " if test "x$ac_cv_member_glp_iocp_presolve" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GLP_IOCP_PRESOLVE 1 _ACEOF else gplk=false fi if test x$gplk = xfalse then if false; then HAVE_LIBGLPK_TRUE= HAVE_LIBGLPK_FALSE='#' else HAVE_LIBGLPK_TRUE='#' HAVE_LIBGLPK_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GNUnet requires GLPK >= 4.32" >&5 $as_echo "$as_me: WARNING: GNUnet requires GLPK >= 4.32" >&2;} else if true; then HAVE_LIBGLPK_TRUE= HAVE_LIBGLPK_FALSE='#' else HAVE_LIBGLPK_TRUE='#' HAVE_LIBGLPK_FALSE= fi $as_echo "#define HAVE_LIBGLPK 1" >>confdefs.h fi for ac_header in nss.h do : ac_fn_c_check_header_mongrel "$LINENO" "nss.h" "ac_cv_header_nss_h" "$ac_includes_default" if test "x$ac_cv_header_nss_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NSS_H 1 _ACEOF nss=true else nss=false fi done if test x$nss = xfalse then if false; then HAVE_GLIBCNSS_TRUE= HAVE_GLIBCNSS_FALSE='#' else HAVE_GLIBCNSS_TRUE='#' HAVE_GLIBCNSS_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No GNU libc nss header, will not build NSS plugin" >&5 $as_echo "$as_me: WARNING: No GNU libc nss header, will not build NSS plugin" >&2;} else if true; then HAVE_GLIBCNSS_TRUE= HAVE_GLIBCNSS_FALSE='#' else HAVE_GLIBCNSS_TRUE='#' HAVE_GLIBCNSS_FALSE= fi fi # test for kvm and kstat (for CPU stats under BSD/Solaris) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kvm_open in -lkvm" >&5 $as_echo_n "checking for kvm_open in -lkvm... " >&6; } if ${ac_cv_lib_kvm_kvm_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lkvm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char kvm_open (); int main () { return kvm_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_kvm_kvm_open=yes else ac_cv_lib_kvm_kvm_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kvm_kvm_open" >&5 $as_echo "$ac_cv_lib_kvm_kvm_open" >&6; } if test "x$ac_cv_lib_kvm_kvm_open" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBKVM 1 _ACEOF LIBS="-lkvm $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5 $as_echo_n "checking for kstat_open in -lkstat... " >&6; } if ${ac_cv_lib_kstat_kstat_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lkstat $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char kstat_open (); int main () { return kstat_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_kstat_kstat_open=yes else ac_cv_lib_kstat_kstat_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5 $as_echo "$ac_cv_lib_kstat_kstat_open" >&6; } if test "x$ac_cv_lib_kstat_kstat_open" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBKSTAT 1 _ACEOF LIBS="-lkstat $LIBS" fi # test for libextractor extractor=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libextractor" >&5 $as_echo_n "checking for libextractor... " >&6; } # Check whether --with-extractor was given. if test "${with_extractor+set}" = set; then : withval=$with_extractor; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_extractor" >&5 $as_echo "$with_extractor" >&6; } case $with_extractor in no) ;; yes) for ac_header in extractor.h do : ac_fn_c_check_header_mongrel "$LINENO" "extractor.h" "ac_cv_header_extractor_h" "$ac_includes_default" if test "x$ac_cv_header_extractor_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EXTRACTOR_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXTRACTOR_plugin_add_defaults in -lextractor" >&5 $as_echo_n "checking for EXTRACTOR_plugin_add_defaults in -lextractor... " >&6; } if ${ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lextractor $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char EXTRACTOR_plugin_add_defaults (); int main () { return EXTRACTOR_plugin_add_defaults (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults=yes else ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" >&5 $as_echo "$ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" >&6; } if test "x$ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" = xyes; then : extractor=1 fi fi done ;; *) LDFLAGS="-L$with_extractor/lib $LDFLAGS" CPPFLAGS="-I$with_extractor/include $CPPFLAGS" for ac_header in extractor.h do : ac_fn_c_check_header_mongrel "$LINENO" "extractor.h" "ac_cv_header_extractor_h" "$ac_includes_default" if test "x$ac_cv_header_extractor_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EXTRACTOR_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXTRACTOR_plugin_add_defaults in -lextractor" >&5 $as_echo_n "checking for EXTRACTOR_plugin_add_defaults in -lextractor... " >&6; } if ${ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lextractor $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char EXTRACTOR_plugin_add_defaults (); int main () { return EXTRACTOR_plugin_add_defaults (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults=yes else ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" >&5 $as_echo "$ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" >&6; } if test "x$ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" = xyes; then : EXT_LIB_PATH="-L$with_extractor/lib $EXT_LIB_PATH" extractor=1 fi fi done ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: --with-extractor not specified" >&5 $as_echo "--with-extractor not specified" >&6; } for ac_header in extractor.h do : ac_fn_c_check_header_mongrel "$LINENO" "extractor.h" "ac_cv_header_extractor_h" "$ac_includes_default" if test "x$ac_cv_header_extractor_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EXTRACTOR_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXTRACTOR_plugin_add_defaults in -lextractor" >&5 $as_echo_n "checking for EXTRACTOR_plugin_add_defaults in -lextractor... " >&6; } if ${ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lextractor $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char EXTRACTOR_plugin_add_defaults (); int main () { return EXTRACTOR_plugin_add_defaults (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults=yes else ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" >&5 $as_echo "$ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" >&6; } if test "x$ac_cv_lib_extractor_EXTRACTOR_plugin_add_defaults" = xyes; then : extractor=1 fi fi done fi if test "$extractor" != 1 then as_fn_error $? "GNUnet requires libextractor" "$LINENO" 5 fi # restore LIBS LIBS=$SAVE_LIBS # Check for libltdl header (#2999) ltdl=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libltdl" >&5 $as_echo_n "checking for libltdl... " >&6; } # Check whether --with-ltdl was given. if test "${with_ltdl+set}" = set; then : withval=$with_ltdl; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_ltdl" >&5 $as_echo "$with_ltdl" >&6; } case $with_ltdl in no) ;; yes) for ac_header in ltdl.h do : ac_fn_c_check_header_mongrel "$LINENO" "ltdl.h" "ac_cv_header_ltdl_h" "$ac_includes_default" if test "x$ac_cv_header_ltdl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LTDL_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lt_dlopenext in -lltdl" >&5 $as_echo_n "checking for lt_dlopenext in -lltdl... " >&6; } if ${ac_cv_lib_ltdl_lt_dlopenext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lltdl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lt_dlopenext (); int main () { return lt_dlopenext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ltdl_lt_dlopenext=yes else ac_cv_lib_ltdl_lt_dlopenext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ltdl_lt_dlopenext" >&5 $as_echo "$ac_cv_lib_ltdl_lt_dlopenext" >&6; } if test "x$ac_cv_lib_ltdl_lt_dlopenext" = xyes; then : ltdl=1 fi fi done ;; *) LDFLAGS="-L$with_ltdl/lib $LDFLAGS" CPPFLAGS="-I$with_ltdl/include $CPPFLAGS" for ac_header in ltdl.h do : ac_fn_c_check_header_mongrel "$LINENO" "ltdl.h" "ac_cv_header_ltdl_h" "$ac_includes_default" if test "x$ac_cv_header_ltdl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LTDL_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lt_dlopenext in -lltdl" >&5 $as_echo_n "checking for lt_dlopenext in -lltdl... " >&6; } if ${ac_cv_lib_ltdl_lt_dlopenext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lltdl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lt_dlopenext (); int main () { return lt_dlopenext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ltdl_lt_dlopenext=yes else ac_cv_lib_ltdl_lt_dlopenext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ltdl_lt_dlopenext" >&5 $as_echo "$ac_cv_lib_ltdl_lt_dlopenext" >&6; } if test "x$ac_cv_lib_ltdl_lt_dlopenext" = xyes; then : EXT_LIB_PATH="-L$with_ltdl/lib $EXT_LIB_PATH" ltdl=1 fi fi done ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: --with-ltdl not specified" >&5 $as_echo "--with-ltdl not specified" >&6; } for ac_header in ltdl.h do : ac_fn_c_check_header_mongrel "$LINENO" "ltdl.h" "ac_cv_header_ltdl_h" "$ac_includes_default" if test "x$ac_cv_header_ltdl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LTDL_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lt_dlopenext in -lltdl" >&5 $as_echo_n "checking for lt_dlopenext in -lltdl... " >&6; } if ${ac_cv_lib_ltdl_lt_dlopenext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lltdl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lt_dlopenext (); int main () { return lt_dlopenext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ltdl_lt_dlopenext=yes else ac_cv_lib_ltdl_lt_dlopenext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ltdl_lt_dlopenext" >&5 $as_echo "$ac_cv_lib_ltdl_lt_dlopenext" >&6; } if test "x$ac_cv_lib_ltdl_lt_dlopenext" = xyes; then : ltdl=1 fi fi done fi if test x$ltdl = x1 then { $as_echo "$as_me:${as_lineno-$LINENO}: result: libltdl found" >&5 $as_echo "libltdl found" >&6; } else as_fn_error $? "GNUnet requires libltdl (from GNU libtool), try installing libltdl-dev" "$LINENO" 5 fi # restore LIBS LIBS=$SAVE_LIBS # test for libunistring if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5 $as_echo_n "checking for ld used by GCC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | [A-Za-z]:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${acl_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$acl_cv_path_LD" if test -n "$LD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${acl_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 &5 $as_echo "$acl_cv_prog_gnu_ld" >&6; } with_gnu_ld=$acl_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 $as_echo_n "checking for shared library run path origin... " >&6; } if ${acl_cv_rpath+:} false; then : $as_echo_n "(cached) " >&6 else CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 $as_echo "$acl_cv_rpath" >&6; } wl="$acl_cv_wl" libext="$acl_cv_libext" shlibext="$acl_cv_shlibext" hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" hardcode_direct="$acl_cv_hardcode_direct" hardcode_minus_L="$acl_cv_hardcode_minus_L" # Check whether --enable-rpath was given. if test "${enable_rpath+set}" = set; then : enableval=$enable_rpath; : else enable_rpath=yes fi acl_libdirstem=lib searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test -n "$searchpath"; then acl_save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) acl_libdirstem=lib64 ;; esac ;; esac fi done IFS="$acl_save_IFS" fi use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libiconv-prefix was given. if test "${with_libiconv_prefix+set}" = set; then : withval=$with_libiconv_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi fi LIBICONV= LTLIBICONV= INCICONV= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='iconv ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" \ && { test -f "$additional_libdir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$additional_libdir/lib$name.dll.a"; }; }; then found_dir="$additional_libdir" if test -f "$additional_libdir/lib$name.$shlibext"; then found_so="$additional_libdir/lib$name.$shlibext" else found_so="$additional_libdir/lib$name.dll.a" fi if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" \ && { test -f "$dir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$dir/lib$name.dll.a"; }; }; then found_dir="$dir" if test -f "$dir/lib$name.$shlibext"; then found_so="$dir/lib$name.$shlibext" else found_so="$dir/lib$name.dll.a" fi if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" else LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBICONV; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" ;; esac done fi else LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" done fi am_save_CPPFLAGS="$CPPFLAGS" for element in $INCICONV; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 $as_echo_n "checking for iconv... " >&6; } if ${am_cv_func_iconv+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_lib_iconv=yes am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$am_save_LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 $as_echo "$am_cv_func_iconv" >&6; } if test "$am_cv_func_iconv" = yes; then $as_echo "#define HAVE_ICONV 1" >>confdefs.h fi if test "$am_cv_lib_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 $as_echo_n "checking how to link with libiconv... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 $as_echo "$LIBICONV" >&6; } else CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi if test "$am_cv_func_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5 $as_echo_n "checking for iconv declaration... " >&6; } if ${am_cv_proto_iconv+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : am_cv_proto_iconv_arg1="" else am_cv_proto_iconv_arg1="const" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" fi am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_t:- }$am_cv_proto_iconv" >&5 $as_echo "${ac_t:- }$am_cv_proto_iconv" >&6; } cat >>confdefs.h <<_ACEOF #define ICONV_CONST $am_cv_proto_iconv_arg1 _ACEOF fi if test -n "$LIBICONV"; then use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libunistring-prefix was given. if test "${with_libunistring_prefix+set}" = set; then : withval=$with_libunistring_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi fi LIBUNISTRING= LTLIBUNISTRING= INCUNISTRING= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='unistring ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" \ && { test -f "$additional_libdir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$additional_libdir/lib$name.dll.a"; }; }; then found_dir="$additional_libdir" if test -f "$additional_libdir/lib$name.$shlibext"; then found_so="$additional_libdir/lib$name.$shlibext" else found_so="$additional_libdir/lib$name.dll.a" fi if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" \ && { test -f "$dir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$dir/lib$name.dll.a"; }; }; then found_dir="$dir" if test -f "$dir/lib$name.$shlibext"; then found_so="$dir/lib$name.$shlibext" else found_so="$dir/lib$name.dll.a" fi if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_a" else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCUNISTRING="${INCUNISTRING}${INCUNISTRING:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$dep" LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }$dep" ;; esac done fi else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-l$name" LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-R$found_dir" done fi ac_save_CPPFLAGS="$CPPFLAGS" for element in $INCUNISTRING; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libunistring" >&5 $as_echo_n "checking for libunistring... " >&6; } if ${ac_cv_libunistring+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_LIBS="$LIBS" LIBS="$LIBS $LIBUNISTRING" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { u8_strconv_from_locale((char*)0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_libunistring=yes else ac_cv_libunistring=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libunistring" >&5 $as_echo "$ac_cv_libunistring" >&6; } if test "$ac_cv_libunistring" = yes; then HAVE_LIBUNISTRING=yes $as_echo "#define HAVE_LIBUNISTRING 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libunistring" >&5 $as_echo_n "checking how to link with libunistring... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBUNISTRING" >&5 $as_echo "$LIBUNISTRING" >&6; } else HAVE_LIBUNISTRING=no CPPFLAGS="$ac_save_CPPFLAGS" LIBUNISTRING= LTLIBUNISTRING= fi if test "$ac_cv_libunistring" != yes; then unset ac_cv_libunistring glus_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libunistring-prefix was given. if test "${with_libunistring_prefix+set}" = set; then : withval=$with_libunistring_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi fi LIBUNISTRING= LTLIBUNISTRING= INCUNISTRING= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='unistring ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" \ && { test -f "$additional_libdir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$additional_libdir/lib$name.dll.a"; }; }; then found_dir="$additional_libdir" if test -f "$additional_libdir/lib$name.$shlibext"; then found_so="$additional_libdir/lib$name.$shlibext" else found_so="$additional_libdir/lib$name.dll.a" fi if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" \ && { test -f "$dir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$dir/lib$name.dll.a"; }; }; then found_dir="$dir" if test -f "$dir/lib$name.$shlibext"; then found_so="$dir/lib$name.$shlibext" else found_so="$dir/lib$name.dll.a" fi if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_a" else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCUNISTRING="${INCUNISTRING}${INCUNISTRING:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$dep" LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }$dep" ;; esac done fi else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-l$name" LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-R$found_dir" done fi ac_save_CPPFLAGS="$CPPFLAGS" for element in $INCUNISTRING; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libunistring" >&5 $as_echo_n "checking for libunistring... " >&6; } if ${ac_cv_libunistring+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_LIBS="$LIBS" LIBS="$LIBS $LIBUNISTRING" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { u8_strconv_from_locale((char*)0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_libunistring=yes else ac_cv_libunistring=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libunistring" >&5 $as_echo "$ac_cv_libunistring" >&6; } if test "$ac_cv_libunistring" = yes; then HAVE_LIBUNISTRING=yes $as_echo "#define HAVE_LIBUNISTRING 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libunistring" >&5 $as_echo_n "checking how to link with libunistring... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBUNISTRING" >&5 $as_echo "$LIBUNISTRING" >&6; } else HAVE_LIBUNISTRING=no CPPFLAGS="$ac_save_CPPFLAGS" LIBUNISTRING= LTLIBUNISTRING= fi if test -n "$LIBUNISTRING"; then LIBUNISTRING="$LIBUNISTRING $LIBICONV" LTLIBUNISTRING="$LTLIBUNISTRING $LTLIBICONV" fi LIBS="$glus_save_LIBS" fi else use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libunistring-prefix was given. if test "${with_libunistring_prefix+set}" = set; then : withval=$with_libunistring_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi fi LIBUNISTRING= LTLIBUNISTRING= INCUNISTRING= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='unistring ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" \ && { test -f "$additional_libdir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$additional_libdir/lib$name.dll.a"; }; }; then found_dir="$additional_libdir" if test -f "$additional_libdir/lib$name.$shlibext"; then found_so="$additional_libdir/lib$name.$shlibext" else found_so="$additional_libdir/lib$name.dll.a" fi if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" \ && { test -f "$dir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$dir/lib$name.dll.a"; }; }; then found_dir="$dir" if test -f "$dir/lib$name.$shlibext"; then found_so="$dir/lib$name.$shlibext" else found_so="$dir/lib$name.dll.a" fi if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_so" else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$found_a" else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCUNISTRING="${INCUNISTRING}${INCUNISTRING:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBUNISTRING; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$dep" LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }$dep" ;; esac done fi else LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }-l$name" LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBUNISTRING="${LIBUNISTRING}${LIBUNISTRING:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBUNISTRING="${LTLIBUNISTRING}${LTLIBUNISTRING:+ }-R$found_dir" done fi ac_save_CPPFLAGS="$CPPFLAGS" for element in $INCUNISTRING; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libunistring" >&5 $as_echo_n "checking for libunistring... " >&6; } if ${ac_cv_libunistring+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_LIBS="$LIBS" LIBS="$LIBS $LIBUNISTRING" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { u8_strconv_from_locale((char*)0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_libunistring=yes else ac_cv_libunistring=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libunistring" >&5 $as_echo "$ac_cv_libunistring" >&6; } if test "$ac_cv_libunistring" = yes; then HAVE_LIBUNISTRING=yes $as_echo "#define HAVE_LIBUNISTRING 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libunistring" >&5 $as_echo_n "checking how to link with libunistring... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBUNISTRING" >&5 $as_echo "$LIBUNISTRING" >&6; } else HAVE_LIBUNISTRING=no CPPFLAGS="$ac_save_CPPFLAGS" LIBUNISTRING= LTLIBUNISTRING= fi fi if test $HAVE_LIBUNISTRING = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libunistring version" >&5 $as_echo_n "checking for libunistring version... " >&6; } if ${gl_cv_libunistring_version+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "_LIBUNISTRING_VERSION" "gl_libunistring_hexversion" "#include "; then : fi if test $gl_libunistring_hexversion = 9; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : gl_cv_libunistring_version092=true else gl_cv_libunistring_version092=false fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if $gl_cv_libunistring_version092; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF case "$host_os" in aix*) gl_absname_cpp="$ac_cpp -C" ;; *) gl_absname_cpp="$ac_cpp" ;; esac gl_cv_absolute_unistr_h=`(eval "$gl_absname_cpp conftest.$ac_ext") 2>&5 | sed -n '\#/unistr.h#{ s#.*"\(.*/unistr.h\)".*#\1# s#^/[^/]#//&# p q }'` if test -n "$gl_cv_absolute_unistr_h" \ && grep 'Copy no more than N units of SRC to DEST. Return a pointer' $gl_cv_absolute_unistr_h > /dev/null; then gl_libunistring_hexversion=2307 else gl_libunistring_hexversion=2306 fi else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include casing_suffix_context_t ct; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : gl_cv_libunistring_version091=true else gl_cv_libunistring_version091=false fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if $gl_cv_libunistring_version091; then gl_libunistring_hexversion=2305 else gl_libunistring_hexversion=2304 fi fi fi gl_libunistring_major=`expr $gl_libunistring_hexversion / 65536` gl_libunistring_minor=`expr $gl_libunistring_hexversion / 256 % 256` gl_libunistring_subminor=`expr $gl_libunistring_hexversion % 256` gl_cv_libunistring_version="$gl_libunistring_major.$gl_libunistring_minor.$gl_libunistring_subminor" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_libunistring_version" >&5 $as_echo "$gl_cv_libunistring_version" >&6; } LIBUNISTRING_VERSION="$gl_cv_libunistring_version" fi if test $HAVE_LIBUNISTRING != yes; then as_fn_error $? "GNUnet requires libunistring" "$LINENO" 5 fi if test $gl_libunistring_hexversion -le 2305; then as_fn_error $? "GNUnet requires libunistring >= 0.9.1.1" "$LINENO" 5 fi # restore LIBS LIBS=$SAVE_LIBS # Checks for standard header files. ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if eval \${$as_ac_Header+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$as_ac_Header=yes" else eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # Check for headers that are ALWAYS required for ac_header in fcntl.h math.h errno.h ctype.h limits.h stdio.h stdlib.h string.h unistd.h stdarg.h signal.h locale.h sys/stat.h sys/types.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else as_fn_error $? "Compiling GNUnet requires standard UNIX headers files" "$LINENO" 5 fi done # Checks for headers that are only required on some systems or opional (and where we do NOT abort if they are not there) for ac_header in malloc.h malloc/malloc.h langinfo.h sys/param.h sys/mount.h sys/statvfs.h sys/select.h sockLib.h sys/mman.h sys/msg.h sys/vfs.h arpa/inet.h fcntl.h libintl.h netdb.h netinet/in.h netinet/in_systm.h netinet/ip.h sys/ioctl.h sys/socket.h sys/time.h unistd.h kstat.h sys/sysinfo.h kvm.h sys/file.h sys/resource.h ifaddrs.h mach/mach.h stddef.h sys/timeb.h terminos.h argz.h ucred.h sys/ucred.h endian.h sys/endian.h execinfo.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done SAVE_LDFLAGS=$LDFLAGS SAVE_CPPFLAGS=$CPPFLAGS # test for sqlite sqlite=false { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLite" >&5 $as_echo_n "checking for SQLite... " >&6; } # Check whether --with-sqlite was given. if test "${with_sqlite+set}" = set; then : withval=$with_sqlite; { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$with_sqlite\"" >&5 $as_echo "\"$with_sqlite\"" >&6; } case $with_sqlite in no) ;; yes) for ac_header in sqlite3.h do : ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" if test "x$ac_cv_header_sqlite3_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SQLITE3_H 1 _ACEOF sqlite=true fi done ;; *) LDFLAGS="-L$with_sqlite/lib $LDFLAGS" CPPFLAGS="-I$with_sqlite/include $CPPFLAGS" for ac_header in sqlite3.h do : ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" if test "x$ac_cv_header_sqlite3_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SQLITE3_H 1 _ACEOF EXT_LIB_PATH="-L$with_sqlite/lib $EXT_LIB_PATH" SQLITE_LDFLAGS="-L$with_sqlite/lib" SQLITE_CPPFLAGS="-I$with_sqlite/include" sqlite=true fi done LDFLAGS=$SAVE_LDFLAGS CPPFLAGS=$SAVE_CPPFLAGS ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: --with-sqlite not specified" >&5 $as_echo "--with-sqlite not specified" >&6; } for ac_header in sqlite3.h do : ac_fn_c_check_header_mongrel "$LINENO" "sqlite3.h" "ac_cv_header_sqlite3_h" "$ac_includes_default" if test "x$ac_cv_header_sqlite3_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SQLITE3_H 1 _ACEOF sqlite=true fi done fi if test x$sqlite = xtrue; then HAVE_SQLITE_TRUE= HAVE_SQLITE_FALSE='#' else HAVE_SQLITE_TRUE='#' HAVE_SQLITE_FALSE= fi # test for postgres postgres=false { $as_echo "$as_me:${as_lineno-$LINENO}: checking for postgres" >&5 $as_echo_n "checking for postgres... " >&6; } # Check whether --with-postgres was given. if test "${with_postgres+set}" = set; then : withval=$with_postgres; { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$with_postgres\"" >&5 $as_echo "\"$with_postgres\"" >&6; } case $with_postgres in no) ;; yes) for ac_header in postgresql/libpq-fe.h do : ac_fn_c_check_header_mongrel "$LINENO" "postgresql/libpq-fe.h" "ac_cv_header_postgresql_libpq_fe_h" "$ac_includes_default" if test "x$ac_cv_header_postgresql_libpq_fe_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POSTGRESQL_LIBPQ_FE_H 1 _ACEOF postgres=true fi done ;; *) LDFLAGS="-L$with_postgres/lib $LDFLAGS" CPPFLAGS="-I$with_postgres/include $CPPFLAGS" for ac_header in postgresql/libpq-fe.h do : ac_fn_c_check_header_mongrel "$LINENO" "postgresql/libpq-fe.h" "ac_cv_header_postgresql_libpq_fe_h" "$ac_includes_default" if test "x$ac_cv_header_postgresql_libpq_fe_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POSTGRESQL_LIBPQ_FE_H 1 _ACEOF EXT_LIB_PATH="-L$with_postgres/lib $EXT_LIB_PATH" POSTGRES_LDFLAGS="-L$with_postgres/lib" POSTGRES_CPPFLAGS="-I$with_postgres/include" postgres=true fi done LDFLAGS=$SAVE_LDFLAGS CPPFLAGS=$SAVE_CPPFLAGS ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: --with-postgres not specified" >&5 $as_echo "--with-postgres not specified" >&6; } for ac_header in postgresql/libpq-fe.h do : ac_fn_c_check_header_mongrel "$LINENO" "postgresql/libpq-fe.h" "ac_cv_header_postgresql_libpq_fe_h" "$ac_includes_default" if test "x$ac_cv_header_postgresql_libpq_fe_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POSTGRESQL_LIBPQ_FE_H 1 _ACEOF postgres=true fi done fi if test x$postgres = xtrue; then HAVE_POSTGRES_TRUE= HAVE_POSTGRES_FALSE='#' else HAVE_POSTGRES_TRUE='#' HAVE_POSTGRES_FALSE= fi # test for zlib SAVE_LDFLAGS=$LDFLAGS SAVE_CPPFLAGS=$CPPFLAGS # Check whether --with-zlib was given. if test "${with_zlib+set}" = set; then : withval=$with_zlib; if test "$withval" = "no"; then : as_fn_error $? "GNUnet requires zlib" "$LINENO" 5 elif test "$withval" != "yes"; then : Z_DIR=$withval CPPFLAGS="${CPPFLAGS} -I$withval/include" LDFLAGS="${LDFLAGS} -L$withval/lib" fi fi ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : else as_fn_error $? "GNUnet requires zlib" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress2 in -lz" >&5 $as_echo_n "checking for compress2 in -lz... " >&6; } if ${ac_cv_lib_z_compress2+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char compress2 (); int main () { return compress2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_compress2=yes else ac_cv_lib_z_compress2=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress2" >&5 $as_echo "$ac_cv_lib_z_compress2" >&6; } if test "x$ac_cv_lib_z_compress2" = xyes; then : $as_echo "#define HAVE_ZLIB /**/" >>confdefs.h if test "x${Z_DIR}" != "x"; then Z_CFLAGS="-I${Z_DIR}/include" Z_LIBS="-L${Z_DIR}/lib -lz" else Z_LIBS="-lz" fi else as_fn_error $? "GNUnet requires zlib" "$LINENO" 5 fi LDFLAGS=$SAVE_LDFLAGS CPPFLAGS=$SAVE_CPPFLAGS # mysql & windows ac_fn_c_check_type "$LINENO" "sigset_t" "ac_cv_type_sigset_t" "#include " if test "x$ac_cv_type_sigset_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SIGSET_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "#include " if test "x$ac_cv_type_off_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_OFF_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "#include " if test "x$ac_cv_type_size_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SIZE_T 1 _ACEOF fi if test "$build_target" = "mingw" then CYGWIN_MYSQL_MAGIC="#include " fi # test for mysql mysql=false mysqlfail=false SAVE_LDFLAGS=$LDFLAGS SAVE_CPPFLAGS=$CPPFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql" >&5 $as_echo_n "checking for mysql... " >&6; } # Check whether --with-mysql was given. if test "${with_mysql+set}" = set; then : withval=$with_mysql; { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$with_mysql\"" >&5 $as_echo "\"$with_mysql\"" >&6; } if test "$with_mysql" != "no" then if test "$with_mysql" != "yes" then LDFLAGS="-L$with_mysql/lib -L$with_mysql/lib/mysql $LDFLAGS $ZLIBS" CPPFLAGS="-I$with_mysql/include $CPPFLAGS" fi for ac_header in mysql/mysql.h do : ac_fn_c_check_header_compile "$LINENO" "mysql/mysql.h" "ac_cv_header_mysql_mysql_h" "$CYGWIN_MYSQL_MAGIC " if test "x$ac_cv_header_mysql_mysql_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MYSQL_MYSQL_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient" >&5 $as_echo_n "checking for mysql_init in -lmysqlclient... " >&6; } if ${ac_cv_lib_mysqlclient_mysql_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mysql_init (); int main () { return mysql_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_mysqlclient_mysql_init=yes else ac_cv_lib_mysqlclient_mysql_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_init" >&5 $as_echo "$ac_cv_lib_mysqlclient_mysql_init" >&6; } if test "x$ac_cv_lib_mysqlclient_mysql_init" = xyes; then : MYSQL_LDFLAGS="-L$with_mysql/lib -L$with_mysql/lib/mysql" MYSQL_CPPFLAGS="-I$with_mysql/include" mysql=true fi fi done fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: --with-mysql not specified" >&5 $as_echo "--with-mysql not specified" >&6; } if test -d "/usr/lib64/mysql"; then MYSQL_LIBDIR="/usr/lib64/mysql" elif test -d "/usr/lib/mysql"; then MYSQL_LIBDIR="/usr/lib/mysql" else MYSQL_LIBDIR="/usr/lib" fi LDFLAGS="-L$MYSQL_LIBDIR $LDFLAGS $ZLIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient" >&5 $as_echo_n "checking for mysql_init in -lmysqlclient... " >&6; } if ${ac_cv_lib_mysqlclient_mysql_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mysql_init (); int main () { return mysql_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_mysqlclient_mysql_init=yes else ac_cv_lib_mysqlclient_mysql_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_init" >&5 $as_echo "$ac_cv_lib_mysqlclient_mysql_init" >&6; } if test "x$ac_cv_lib_mysqlclient_mysql_init" = xyes; then : for ac_header in mysql/mysql.h do : ac_fn_c_check_header_compile "$LINENO" "mysql/mysql.h" "ac_cv_header_mysql_mysql_h" "$CYGWIN_MYSQL_MAGIC " if test "x$ac_cv_header_mysql_mysql_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MYSQL_MYSQL_H 1 _ACEOF MYSQL_LDFLAGS="-L$MYSQL_LIBDIR" mysql=true fi done fi fi # additional version check for mysql # Check whether --enable-mysql-version-check was given. if test "${enable_mysql_version_check+set}" = set; then : enableval=$enable_mysql_version_check; else enable_mysql_version_check=yes fi if test "$mysql" = "true" -a "x$enable_mysql_version_check" = "xyes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking mysql version" >&5 $as_echo_n "checking mysql version... " >&6; } if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $CYGWIN_MYSQL_MAGIC #include int main () { if (MYSQL_VERSION_ID < 40100) return(-1); else return(0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : mysql=true else mysql=false fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test "$mysql" = "false" then mysqlfail=true { $as_echo "$as_me:${as_lineno-$LINENO}: result: fail, >= 4.1 required" >&5 $as_echo "fail, >= 4.1 required" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi fi if test x$mysql = xtrue; then HAVE_MYSQL_TRUE= HAVE_MYSQL_FALSE='#' else HAVE_MYSQL_TRUE='#' HAVE_MYSQL_FALSE= fi if test "0" = "1"; then HAVE_MYSQLE_TRUE= HAVE_MYSQLE_FALSE='#' else HAVE_MYSQLE_TRUE='#' HAVE_MYSQLE_FALSE= fi # restore LIBS LIBS=$SAVE_LIBS LDFLAGS=$SAVE_LDFLAGS CPPFLAGS=$SAVE_CPPFLAGS if test "$sqlite" = 0 -a "$mysql" = 0 then as_fn_error $? "GNUnet requires SQLite or MySQL" "$LINENO" 5 fi # libmicrohttpd lmhd=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmicrohttpd" >&5 $as_echo_n "checking for libmicrohttpd... " >&6; } # Check whether --with-microhttpd was given. if test "${with_microhttpd+set}" = set; then : withval=$with_microhttpd; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_microhttpd" >&5 $as_echo "$with_microhttpd" >&6; } case $with_microhttpd in no) ;; yes) for ac_header in microhttpd.h do : ac_fn_c_check_header_compile "$LINENO" "microhttpd.h" "ac_cv_header_microhttpd_h" "#include \"$native_srcdir/src/include/platform.h\" " if test "x$ac_cv_header_microhttpd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MICROHTTPD_H 1 _ACEOF ac_fn_c_check_decl "$LINENO" "MHD_OPTION_PER_IP_CONNECTION_LIMIT" "ac_cv_have_decl_MHD_OPTION_PER_IP_CONNECTION_LIMIT" "#include \"$native_srcdir/src/include/platform.h\" #include " if test "x$ac_cv_have_decl_MHD_OPTION_PER_IP_CONNECTION_LIMIT" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MHD_start_daemon in -lmicrohttpd" >&5 $as_echo_n "checking for MHD_start_daemon in -lmicrohttpd... " >&6; } if ${ac_cv_lib_microhttpd_MHD_start_daemon+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmicrohttpd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char MHD_start_daemon (); int main () { return MHD_start_daemon (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_microhttpd_MHD_start_daemon=yes else ac_cv_lib_microhttpd_MHD_start_daemon=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_microhttpd_MHD_start_daemon" >&5 $as_echo "$ac_cv_lib_microhttpd_MHD_start_daemon" >&6; } if test "x$ac_cv_lib_microhttpd_MHD_start_daemon" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmicrohttpd >= 0.9.31" >&5 $as_echo_n "checking for libmicrohttpd >= 0.9.31... " >&6; } if test "$cross_compiling" = yes; then : lmhd=1 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "$native_srcdir/src/include/platform.h" #include int main () { return MHD_VERSION >= 0x0093002 ? 0 : 1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } lmhd=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi fi done ;; *) LDFLAGS="-L$with_microhttpd/lib $LDFLAGS" CPPFLAGS="-I$with_microhttpd/include $CPPFLAGS" for ac_header in microhttpd.h do : ac_fn_c_check_header_compile "$LINENO" "microhttpd.h" "ac_cv_header_microhttpd_h" "#include \"$native_srcdir/src/include/platform.h\" " if test "x$ac_cv_header_microhttpd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MICROHTTPD_H 1 _ACEOF ac_fn_c_check_decl "$LINENO" "MHD_OPTION_PER_IP_CONNECTION_LIMIT" "ac_cv_have_decl_MHD_OPTION_PER_IP_CONNECTION_LIMIT" "#include \"$native_srcdir/src/include/platform.h\" #include " if test "x$ac_cv_have_decl_MHD_OPTION_PER_IP_CONNECTION_LIMIT" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MHD_start_daemon in -lmicrohttpd" >&5 $as_echo_n "checking for MHD_start_daemon in -lmicrohttpd... " >&6; } if ${ac_cv_lib_microhttpd_MHD_start_daemon+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmicrohttpd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char MHD_start_daemon (); int main () { return MHD_start_daemon (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_microhttpd_MHD_start_daemon=yes else ac_cv_lib_microhttpd_MHD_start_daemon=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_microhttpd_MHD_start_daemon" >&5 $as_echo "$ac_cv_lib_microhttpd_MHD_start_daemon" >&6; } if test "x$ac_cv_lib_microhttpd_MHD_start_daemon" = xyes; then : EXT_LIB_PATH="-L$with_microhttpd/lib $EXT_LIB_PATH" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmicrohttpd >= 0.9.31" >&5 $as_echo_n "checking for libmicrohttpd >= 0.9.31... " >&6; } if test "$cross_compiling" = yes; then : lmhd=1 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "$native_srcdir/src/include/platform.h" #include int main () { return MHD_VERSION >= 0x0093002 ? 0 : 1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } lmhd=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi fi done ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: --with-microhttpd not specified" >&5 $as_echo "--with-microhttpd not specified" >&6; } for ac_header in microhttpd.h do : ac_fn_c_check_header_compile "$LINENO" "microhttpd.h" "ac_cv_header_microhttpd_h" "#include \"$native_srcdir/src/include/platform.h\" " if test "x$ac_cv_header_microhttpd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MICROHTTPD_H 1 _ACEOF ac_fn_c_check_decl "$LINENO" "MHD_OPTION_PER_IP_CONNECTION_LIMIT" "ac_cv_have_decl_MHD_OPTION_PER_IP_CONNECTION_LIMIT" "#include \"$native_srcdir/src/include/platform.h\" #include " if test "x$ac_cv_have_decl_MHD_OPTION_PER_IP_CONNECTION_LIMIT" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MHD_start_daemon in -lmicrohttpd" >&5 $as_echo_n "checking for MHD_start_daemon in -lmicrohttpd... " >&6; } if ${ac_cv_lib_microhttpd_MHD_start_daemon+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmicrohttpd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char MHD_start_daemon (); int main () { return MHD_start_daemon (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_microhttpd_MHD_start_daemon=yes else ac_cv_lib_microhttpd_MHD_start_daemon=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_microhttpd_MHD_start_daemon" >&5 $as_echo "$ac_cv_lib_microhttpd_MHD_start_daemon" >&6; } if test "x$ac_cv_lib_microhttpd_MHD_start_daemon" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmicrohttpd >= 0.9.31" >&5 $as_echo_n "checking for libmicrohttpd >= 0.9.31... " >&6; } if test "$cross_compiling" = yes; then : lmhd=1 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "$native_srcdir/src/include/platform.h" #include int main () { return MHD_VERSION >= 0x0093002 ? 0 : 1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } lmhd=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi fi done fi if test x$lmhd = x1; then HAVE_MHD_TRUE= HAVE_MHD_FALSE='#' else HAVE_MHD_TRUE='#' HAVE_MHD_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAVE_MHD $lmhd _ACEOF # restore LIBS LIBS=$SAVE_LIBS # check for python & pexpect (used for some testcases only) if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= 2.6" >&5 $as_echo_n "checking whether $PYTHON version is >= 2.6... " >&6; } prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '2.6'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 ($PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Python interpreter is too old" "$LINENO" 5 fi am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 2.6" >&5 $as_echo_n "checking for a Python interpreter with version >= 2.6... " >&6; } if ${am_cv_pathless_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do test "$am_cv_pathless_PYTHON" = none && break prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '2.6'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5 ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5 $as_echo "$am_cv_pathless_PYTHON" >&6; } # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args. set dummy $am_cv_pathless_PYTHON; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else case $PYTHON in [\\/]* | ?:[\\/]*) ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PYTHON=$ac_cv_path_PYTHON if test -n "$PYTHON"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 $as_echo "$PYTHON" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi am_display_PYTHON=$am_cv_pathless_PYTHON fi if test "$PYTHON" = :; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 $as_echo_n "checking for $am_display_PYTHON version... " >&6; } if ${am_cv_python_version+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 $as_echo "$am_cv_python_version" >&6; } PYTHON_VERSION=$am_cv_python_version PYTHON_PREFIX='${prefix}' PYTHON_EXEC_PREFIX='${exec_prefix}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 $as_echo_n "checking for $am_display_PYTHON platform... " >&6; } if ${am_cv_python_platform+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 $as_echo "$am_cv_python_platform" >&6; } PYTHON_PLATFORM=$am_cv_python_platform # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[:3] == '2.7': can_use_sysconfig = 0 except ImportError: pass" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 $as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } if ${am_cv_python_pythondir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 $as_echo "$am_cv_python_pythondir" >&6; } pythondir=$am_cv_python_pythondir pkgpythondir=\${pythondir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 $as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } if ${am_cv_python_pyexecdir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 $as_echo "$am_cv_python_pyexecdir" >&6; } pyexecdir=$am_cv_python_pyexecdir pkgpyexecdir=\${pyexecdir}/$PACKAGE fi if test "$PYTHON" != :; then HAVE_PYTHON_TRUE= HAVE_PYTHON_FALSE='#' else HAVE_PYTHON_TRUE='#' HAVE_PYTHON_FALSE= fi # check for gettext mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 $as_echo_n "checking whether NLS is requested... " >&6; } # Check whether --enable-nls was given. if test "${enable_nls+set}" = set; then : enableval=$enable_nls; USE_NLS=$enableval else USE_NLS=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 $as_echo "$USE_NLS" >&6; } GETTEXT_MACRO_VERSION=0.18 # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case "$MSGFMT" in [\\/]* | ?:[\\/]*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" ;; esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 $as_echo "$MSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GMSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case $GMSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT if test -n "$GMSGFMT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 $as_echo "$GMSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; *) MSGFMT_015=$MSGFMT ;; esac case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; *) GMSGFMT_015=$GMSGFMT ;; esac # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_XGETTEXT+:} false; then : $as_echo_n "(cached) " >&6 else case "$XGETTEXT" in [\\/]* | ?:[\\/]*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" ;; esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 $as_echo "$XGETTEXT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f messages.po case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; *) XGETTEXT_015=$XGETTEXT ;; esac # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGMERGE+:} false; then : $as_echo_n "(cached) " >&6 else case "$MSGMERGE" in [\\/]* | ?:[\\/]*) ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&5 if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" ;; esac fi MSGMERGE="$ac_cv_path_MSGMERGE" if test "$MSGMERGE" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 $as_echo "$MSGMERGE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$localedir" || localedir='${datadir}/locale' test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= ac_config_commands="$ac_config_commands po-directories" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 $as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : $as_echo_n "(cached) " >&6 else gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { CFPreferencesCopyAppValue(NULL, NULL) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : gt_cv_func_CFPreferencesCopyAppValue=yes else gt_cv_func_CFPreferencesCopyAppValue=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$gt_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 $as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then $as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 $as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : $as_echo_n "(cached) " >&6 else gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { CFLocaleCopyCurrent(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : gt_cv_func_CFLocaleCopyCurrent=yes else gt_cv_func_CFLocaleCopyCurrent=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$gt_save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 $as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } if test $gt_cv_func_CFLocaleCopyCurrent = yes; then $as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi LIBINTL= LTLIBINTL= POSUB= case " $gt_needs " in *" need-formatstring-macros "*) gt_api_version=3 ;; *" need-ngettext "*) gt_api_version=2 ;; *) gt_api_version=1 ;; esac gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no if test $gt_api_version -ge 3; then gt_revision_test_code=' #ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; ' else gt_revision_test_code= fi if test $gt_api_version -ge 2; then gt_expression_test_code=' + * ngettext ("", "", 0)' else gt_expression_test_code= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 $as_echo_n "checking for GNU gettext in libc... " >&6; } if eval \${$gt_func_gnugettext_libc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings; int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$gt_func_gnugettext_libc=yes" else eval "$gt_func_gnugettext_libc=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$gt_func_gnugettext_libc { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then am_save_CPPFLAGS="$CPPFLAGS" for element in $INCICONV; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 $as_echo_n "checking for iconv... " >&6; } if ${am_cv_func_iconv+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_lib_iconv=yes am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$am_save_LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 $as_echo "$am_cv_func_iconv" >&6; } if test "$am_cv_func_iconv" = yes; then $as_echo "#define HAVE_ICONV 1" >>confdefs.h fi if test "$am_cv_lib_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 $as_echo_n "checking how to link with libiconv... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 $as_echo "$LIBICONV" >&6; } else CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi use_additional=yes acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" # Check whether --with-libintl-prefix was given. if test "${with_libintl_prefix+set}" = set; then : withval=$with_libintl_prefix; if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi fi LIBINTL= LTLIBINTL= INCINTL= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='intl ' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" else : fi else found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" \ && { test -f "$additional_libdir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$additional_libdir/lib$name.dll.a"; }; }; then found_dir="$additional_libdir" if test -f "$additional_libdir/lib$name.$shlibext"; then found_so="$additional_libdir/lib$name.$shlibext" else found_so="$additional_libdir/lib$name.dll.a" fi if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" \ && { test -f "$dir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$dir/lib$name.dll.a"; }; }; then found_dir="$dir" if test -f "$dir/lib$name.$shlibext"; then found_so="$dir/lib$name.$shlibext" else found_so="$dir/lib$name.dll.a" fi if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi if test "$hardcode_direct" = yes; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" else LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" fi fi additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INCINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" fi fi fi fi fi if test -n "$found_la"; then save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIBINTL; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" ;; esac done fi else LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" else for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then for found_dir in $ltrpathdirs; do LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 $as_echo_n "checking for GNU gettext in libintl... " >&6; } if eval \${$gt_func_gnugettext_libintl+:} false; then : $as_echo_n "(cached) " >&6 else gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$gt_func_gnugettext_libintl=yes" else eval "$gt_func_gnugettext_libintl=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *); int main () { bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" eval "$gt_func_gnugettext_libintl=yes" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS" fi eval ac_res=\$$gt_func_gnugettext_libintl { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else LIBINTL= LTLIBINTL= INCINTL= fi if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then $as_echo "#define ENABLE_NLS 1" >>confdefs.h else USE_NLS=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 $as_echo_n "checking whether to use NLS... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 $as_echo "$USE_NLS" >&6; } if test "$USE_NLS" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 $as_echo_n "checking where the gettext function comes from... " >&6; } if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 $as_echo "$gt_source" >&6; } fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 $as_echo_n "checking how to link with libintl... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 $as_echo "$LIBINTL" >&6; } for element in $INCINTL; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done fi $as_echo "#define HAVE_GETTEXT 1" >>confdefs.h $as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h fi POSUB=po fi INTLLIBS="$LIBINTL" # check for iconv am_save_CPPFLAGS="$CPPFLAGS" for element in $INCICONV; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 $as_echo_n "checking for iconv... " >&6; } if ${am_cv_func_iconv+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_lib_iconv=yes am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$am_save_LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 $as_echo "$am_cv_func_iconv" >&6; } if test "$am_cv_func_iconv" = yes; then $as_echo "#define HAVE_ICONV 1" >>confdefs.h fi if test "$am_cv_lib_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 $as_echo_n "checking how to link with libiconv... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 $as_echo "$LIBICONV" >&6; } else CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi if test "$am_cv_func_iconv" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5 $as_echo_n "checking for iconv declaration... " >&6; } if ${am_cv_proto_iconv+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : am_cv_proto_iconv_arg1="" else am_cv_proto_iconv_arg1="const" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" fi am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_t:- }$am_cv_proto_iconv" >&5 $as_echo "${ac_t:- }$am_cv_proto_iconv" >&6; } cat >>confdefs.h <<_ACEOF #define ICONV_CONST $am_cv_proto_iconv_arg1 _ACEOF fi # Checks for standard typedefs, structures, and compiler characteristics. ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" if test "x$ac_cv_type_mode_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define mode_t int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat file-mode macros are broken" >&5 $as_echo_n "checking whether stat file-mode macros are broken... " >&6; } if ${ac_cv_header_stat_broken+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if defined S_ISBLK && defined S_IFDIR extern char c1[S_ISBLK (S_IFDIR) ? -1 : 1]; #endif #if defined S_ISBLK && defined S_IFCHR extern char c2[S_ISBLK (S_IFCHR) ? -1 : 1]; #endif #if defined S_ISLNK && defined S_IFREG extern char c3[S_ISLNK (S_IFREG) ? -1 : 1]; #endif #if defined S_ISSOCK && defined S_IFREG extern char c4[S_ISSOCK (S_IFREG) ? -1 : 1]; #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stat_broken=no else ac_cv_header_stat_broken=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stat_broken" >&5 $as_echo "$ac_cv_header_stat_broken" >&6; } if test $ac_cv_header_stat_broken = yes; then $as_echo "#define STAT_MACROS_BROKEN 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 $as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } if ${ac_cv_header_stdbool_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: true is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) 0.5 == true ? 1 : -1]; /* See body of main program for 'e'. */ char f[(_Bool) 0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; enum { j = false, k = true, l = false * true, m = true * 256 }; /* The following fails for HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ _Bool n[m]; char o[sizeof n == m * sizeof n[0] ? 1 : -1]; char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; /* Catch a bug in an HP-UX C compiler. See http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html */ _Bool q = true; _Bool *pq = &q; int main () { bool e = &s; *pq |= q; *pq |= ! q; /* Refer to every declared value, to avoid compiler optimizations. */ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + !m + !n + !o + !p + !q + !pq); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdbool_h=yes else ac_cv_header_stdbool_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 $as_echo "$ac_cv_header_stdbool_h" >&6; } ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" if test "x$ac_cv_type__Bool" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE__BOOL 1 _ACEOF fi if test $ac_cv_header_stdbool_h = yes; then $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct sockaddr_in" "sin_len" "ac_cv_member_struct_sockaddr_in_sin_len" " #include #include #include " if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes; then : $as_echo "#define HAVE_SOCKADDR_IN_SIN_LEN 1" >>confdefs.h fi # Checks for library functions. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether closedir returns void" >&5 $as_echo_n "checking whether closedir returns void... " >&6; } if ${ac_cv_func_closedir_void+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_closedir_void=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #include <$ac_header_dirent> #ifndef __cplusplus int closedir (); #endif int main () { return closedir (opendir (".")) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_closedir_void=no else ac_cv_func_closedir_void=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_closedir_void" >&5 $as_echo "$ac_cv_func_closedir_void" >&6; } if test $ac_cv_func_closedir_void = yes; then $as_echo "#define CLOSEDIR_VOID 1" >>confdefs.h fi for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if ${ac_cv_func_fork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if ${ac_cv_func_vfork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi if test $ac_cv_c_compiler_gnu = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 $as_echo_n "checking whether $CC needs -traditional... " >&6; } if ${ac_cv_prog_gcc_traditional+:} false; then : $as_echo_n "(cached) " >&6 else ac_pattern="Autoconf.*'x'" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Autoconf TIOCGETP _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then : ac_cv_prog_gcc_traditional=yes else ac_cv_prog_gcc_traditional=no fi rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Autoconf TCGETA _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then : ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 $as_echo "$ac_cv_prog_gcc_traditional" >&6; } if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 $as_echo_n "checking for working memcmp... " >&6; } if ${ac_cv_func_memcmp_working+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_memcmp_working=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = '\100', c1 = '\200', c2 = '\201'; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) return 1; /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) return 1; } return 0; } ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_memcmp_working=yes else ac_cv_func_memcmp_working=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 $as_echo "$ac_cv_func_memcmp_working" >&6; } test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac for ac_header in sys/select.h sys/socket.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking types of arguments for select" >&5 $as_echo_n "checking types of arguments for select... " >&6; } if ${ac_cv_func_select_args+:} false; then : $as_echo_n "(cached) " >&6 else for ac_arg234 in 'fd_set *' 'int *' 'void *'; do for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif int main () { extern int select ($ac_arg1, $ac_arg234, $ac_arg234, $ac_arg234, $ac_arg5); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done done done # Provide a safe default value. : "${ac_cv_func_select_args=int,int *,struct timeval *}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_select_args" >&5 $as_echo "$ac_cv_func_select_args" >&6; } ac_save_IFS=$IFS; IFS=',' set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'` IFS=$ac_save_IFS shift cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG1 $1 _ACEOF cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG234 ($2) _ACEOF cat >>confdefs.h <<_ACEOF #define SELECT_TYPE_ARG5 ($3) _ACEOF rm -f conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi for ac_header in unistd.h do : ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_unistd_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UNISTD_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working chown" >&5 $as_echo_n "checking for working chown... " >&6; } if ${ac_cv_func_chown_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_chown_works=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #include int main () { char *f = "conftest.chown"; struct stat before, after; if (creat (f, 0600) < 0) return 1; if (stat (f, &before) < 0) return 1; if (chown (f, (uid_t) -1, (gid_t) -1) == -1) return 1; if (stat (f, &after) < 0) return 1; return ! (before.st_uid == after.st_uid && before.st_gid == after.st_gid); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_chown_works=yes else ac_cv_func_chown_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f conftest.chown fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_chown_works" >&5 $as_echo "$ac_cv_func_chown_works" >&6; } if test $ac_cv_func_chown_works = yes; then $as_echo "#define HAVE_CHOWN 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 $as_echo_n "checking return type of signal handlers... " >&6; } if ${ac_cv_type_signal+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_signal=int else ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 $as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5 $as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; } if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then : $as_echo_n "(cached) " >&6 else rm -f conftest.sym conftest.file echo >conftest.file if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then if test "$cross_compiling" = yes; then : ac_cv_func_lstat_dereferences_slashed_symlink=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; /* Linux will dereference the symlink and fail, as required by POSIX. That is better in the sense that it means we will not have to compile and use the lstat wrapper. */ return lstat ("conftest.sym/", &sbuf) == 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_lstat_dereferences_slashed_symlink=yes else ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi else # If the `ln -s' command failed, then we probably don't even # have an lstat function. ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f conftest.sym conftest.file fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 $as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && cat >>confdefs.h <<_ACEOF #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 _ACEOF if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then case " $LIBOBJS " in *" lstat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS lstat.$ac_objext" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5 $as_echo_n "checking whether stat accepts an empty string... " >&6; } if ${ac_cv_func_stat_empty_string_bug+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_stat_empty_string_bug=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; return stat ("", &sbuf) == 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_stat_empty_string_bug=no else ac_cv_func_stat_empty_string_bug=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5 $as_echo "$ac_cv_func_stat_empty_string_bug" >&6; } if test $ac_cv_func_stat_empty_string_bug = yes; then case " $LIBOBJS " in *" stat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS stat.$ac_objext" ;; esac cat >>confdefs.h <<_ACEOF #define HAVE_STAT_EMPTY_STRING_BUG 1 _ACEOF fi for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" if test "x$ac_cv_func_strftime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRFTIME 1 _ACEOF else # strftime is in -lintl on SCO UNIX. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 $as_echo_n "checking for strftime in -lintl... " >&6; } if ${ac_cv_lib_intl_strftime+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char strftime (); int main () { return strftime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_strftime=yes else ac_cv_lib_intl_strftime=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 $as_echo "$ac_cv_lib_intl_strftime" >&6; } if test "x$ac_cv_lib_intl_strftime" = xyes; then : $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h LIBS="-lintl $LIBS" fi fi done for ac_func in vprintf do : ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf" if test "x$ac_cv_func_vprintf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VPRINTF 1 _ACEOF ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt" if test "x$ac_cv_func__doprnt" = xyes; then : $as_echo "#define HAVE_DOPRNT 1" >>confdefs.h fi fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 $as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if ${ac_cv_header_sys_wait_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_sys_wait_h=yes else ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 $as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" if test "x$ac_cv_type_off_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define off_t long int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi for ac_func in atoll stat64 strnlen mremap getrlimit setrlimit sysconf initgroups strndup gethostbyname2 getpeerucred getpeereid setresuid $funcstocheck getifaddrs freeifaddrs getresgid mallinfo malloc_size malloc_usable_size getrusage random srandom stat statfs statvfs do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # restore LIBS LIBS=$SAVE_LIBS GN_INTLINCL="" GN_LIBINTL="$LTLIBINTL" # Check whether --enable-framework was given. if test "${enable_framework+set}" = set; then : enableval=$enable_framework; enable_framework_build=$enableval fi if test x$enable_framework_build = xyes; then WANT_FRAMEWORK_TRUE= WANT_FRAMEWORK_FALSE='#' else WANT_FRAMEWORK_TRUE='#' WANT_FRAMEWORK_FALSE= fi if test x$enable_framework_build = xyes then $as_echo "#define FRAMEWORK_BUILD 1" >>confdefs.h GN_INTLINCL='-I$(top_srcdir)/src/intlemu' GN_LIBINTL='$(top_builddir)/src/intlemu/libintlemu.la -framework CoreFoundation' for element in $GN_INTLINCL; do haveit= for x in $CPPFLAGS; do acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" eval x=\"$x\" exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" fi done fi GN_LIB_LDFLAGS="-export-dynamic -no-undefined" GN_PLUGIN_LDFLAGS="-export-dynamic -avoid-version -module -no-undefined" # test for sudo { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sudo" >&5 $as_echo_n "checking for sudo... " >&6; } # Check whether --with-sudo was given. if test "${with_sudo+set}" = set; then : withval=$with_sudo; { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$with_sudo\"" >&5 $as_echo "\"$with_sudo\"" >&6; } case $with_sudo in no) SUDO_BINARY= ;; yes) SUDO_BINARY=sudo ;; *) SUDO_BINARY=$with_sudo ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$SUDO_BINARY" != "x" -o -w /; then HAVE_SUDO_TRUE= HAVE_SUDO_FALSE='#' else HAVE_SUDO_TRUE='#' HAVE_SUDO_FALSE= fi # test for nssdir { $as_echo "$as_me:${as_lineno-$LINENO}: checking with nssdir" >&5 $as_echo_n "checking with nssdir... " >&6; } # Check whether --with-nssdir was given. if test "${with_nssdir+set}" = set; then : withval=$with_nssdir; { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$with_nssdir\"" >&5 $as_echo "\"$with_nssdir\"" >&6; } case $with_nssdir in no) NSS_DIR= install_nss=0 ;; yes) NSS_DIR="/lib" install_nss=1 ;; *) NSS_DIR=$with_nssdir install_nss=1 ;; esac else if test "x$SUDO_BINARY" != "x" -o -w / then NSS_DIR="/lib" install_nss=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, to /lib" >&5 $as_echo "yes, to /lib" >&6; } else NSS_DIR= install_nss=0 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test "x$install_nss" != "x0"; then INSTALL_NSS_TRUE= INSTALL_NSS_FALSE='#' else INSTALL_NSS_TRUE='#' INSTALL_NSS_FALSE= fi # test for gnunetdns group name GNUNETDNS_GROUP=gnunetdns { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnunetdns group name" >&5 $as_echo_n "checking for gnunetdns group name... " >&6; } # Check whether --with-gnunetdns was given. if test "${with_gnunetdns+set}" = set; then : withval=$with_gnunetdns; { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$with_gnunetdns\"" >&5 $as_echo "\"$with_gnunetdns\"" >&6; } case $with_gnunetdns in no) GNUNETDNS_GROUP=gnunet ;; yes) GNUNETDNS_GROUP=gnunetdns ;; *) GNUNETDNS_GROUP=$with_gnunetdns ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: gnunetdns" >&5 $as_echo "gnunetdns" >&6; } fi # gnutls gnutls=0 gnutls_dane=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnutls" >&5 $as_echo_n "checking for gnutls... " >&6; } # Check whether --with-gnutls was given. if test "${with_gnutls+set}" = set; then : withval=$with_gnutls; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_gnutls" >&5 $as_echo "$with_gnutls" >&6; } case $with_gnutls in no) ;; yes) for ac_header in gnutls/abstract.h do : ac_fn_c_check_header_mongrel "$LINENO" "gnutls/abstract.h" "ac_cv_header_gnutls_abstract_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_abstract_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_ABSTRACT_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnutls_priority_set in -lgnutls" >&5 $as_echo_n "checking for gnutls_priority_set in -lgnutls... " >&6; } if ${ac_cv_lib_gnutls_gnutls_priority_set+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gnutls_priority_set (); int main () { return gnutls_priority_set (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnutls_gnutls_priority_set=yes else ac_cv_lib_gnutls_gnutls_priority_set=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnutls_gnutls_priority_set" >&5 $as_echo "$ac_cv_lib_gnutls_gnutls_priority_set" >&6; } if test "x$ac_cv_lib_gnutls_gnutls_priority_set" = xyes; then : gnutls=true fi fi done for ac_header in gnutls/dane.h do : ac_fn_c_check_header_mongrel "$LINENO" "gnutls/dane.h" "ac_cv_header_gnutls_dane_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_dane_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_DANE_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dane_verify_crt_raw in -lgnutls-dane" >&5 $as_echo_n "checking for dane_verify_crt_raw in -lgnutls-dane... " >&6; } if ${ac_cv_lib_gnutls_dane_dane_verify_crt_raw+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls-dane $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dane_verify_crt_raw (); int main () { return dane_verify_crt_raw (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnutls_dane_dane_verify_crt_raw=yes else ac_cv_lib_gnutls_dane_dane_verify_crt_raw=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnutls_dane_dane_verify_crt_raw" >&5 $as_echo "$ac_cv_lib_gnutls_dane_dane_verify_crt_raw" >&6; } if test "x$ac_cv_lib_gnutls_dane_dane_verify_crt_raw" = xyes; then : gnutls_dane=1 fi fi done ;; *) LDFLAGS="-L$with_gnutls/lib $LDFLAGS" CPPFLAGS="-I$with_gnutls/include $CPPFLAGS" for ac_header in gnutls/abstract.h do : ac_fn_c_check_header_mongrel "$LINENO" "gnutls/abstract.h" "ac_cv_header_gnutls_abstract_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_abstract_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_ABSTRACT_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnutls_priority_set in -lgnutls" >&5 $as_echo_n "checking for gnutls_priority_set in -lgnutls... " >&6; } if ${ac_cv_lib_gnutls_gnutls_priority_set+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gnutls_priority_set (); int main () { return gnutls_priority_set (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnutls_gnutls_priority_set=yes else ac_cv_lib_gnutls_gnutls_priority_set=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnutls_gnutls_priority_set" >&5 $as_echo "$ac_cv_lib_gnutls_gnutls_priority_set" >&6; } if test "x$ac_cv_lib_gnutls_gnutls_priority_set" = xyes; then : EXT_LIB_PATH="-L$with_gnutls/lib $EXT_LIB_PATH" gnutls=true fi fi done for ac_header in gnutls/dane.h do : ac_fn_c_check_header_mongrel "$LINENO" "gnutls/dane.h" "ac_cv_header_gnutls_dane_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_dane_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_DANE_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dane_verify_crt_raw in -lgnutls-dane" >&5 $as_echo_n "checking for dane_verify_crt_raw in -lgnutls-dane... " >&6; } if ${ac_cv_lib_gnutls_dane_dane_verify_crt_raw+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls-dane $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dane_verify_crt_raw (); int main () { return dane_verify_crt_raw (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnutls_dane_dane_verify_crt_raw=yes else ac_cv_lib_gnutls_dane_dane_verify_crt_raw=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnutls_dane_dane_verify_crt_raw" >&5 $as_echo "$ac_cv_lib_gnutls_dane_dane_verify_crt_raw" >&6; } if test "x$ac_cv_lib_gnutls_dane_dane_verify_crt_raw" = xyes; then : gnutls_dane=1 fi fi done ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: --with-gnutls not specified" >&5 $as_echo "--with-gnutls not specified" >&6; } for ac_header in gnutls/abstract.h do : ac_fn_c_check_header_mongrel "$LINENO" "gnutls/abstract.h" "ac_cv_header_gnutls_abstract_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_abstract_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_ABSTRACT_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnutls_priority_set in -lgnutls" >&5 $as_echo_n "checking for gnutls_priority_set in -lgnutls... " >&6; } if ${ac_cv_lib_gnutls_gnutls_priority_set+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gnutls_priority_set (); int main () { return gnutls_priority_set (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnutls_gnutls_priority_set=yes else ac_cv_lib_gnutls_gnutls_priority_set=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnutls_gnutls_priority_set" >&5 $as_echo "$ac_cv_lib_gnutls_gnutls_priority_set" >&6; } if test "x$ac_cv_lib_gnutls_gnutls_priority_set" = xyes; then : gnutls=true fi fi done for ac_header in gnutls/dane.h do : ac_fn_c_check_header_mongrel "$LINENO" "gnutls/dane.h" "ac_cv_header_gnutls_dane_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_dane_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_DANE_H 1 _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dane_verify_crt_raw in -lgnutls-dane" >&5 $as_echo_n "checking for dane_verify_crt_raw in -lgnutls-dane... " >&6; } if ${ac_cv_lib_gnutls_dane_dane_verify_crt_raw+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgnutls-dane $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dane_verify_crt_raw (); int main () { return dane_verify_crt_raw (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gnutls_dane_dane_verify_crt_raw=yes else ac_cv_lib_gnutls_dane_dane_verify_crt_raw=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnutls_dane_dane_verify_crt_raw" >&5 $as_echo "$ac_cv_lib_gnutls_dane_dane_verify_crt_raw" >&6; } if test "x$ac_cv_lib_gnutls_dane_dane_verify_crt_raw" = xyes; then : gnutls_dane=1 fi fi done fi if test x$gnutls = xtrue; then HAVE_GNUTLS_TRUE= HAVE_GNUTLS_FALSE='#' else HAVE_GNUTLS_TRUE='#' HAVE_GNUTLS_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS $gnutls _ACEOF if test x$gnutls_dane = x1; then HAVE_GNUTLS_DANE_TRUE= HAVE_GNUTLS_DANE_FALSE='#' else HAVE_GNUTLS_DANE_TRUE='#' HAVE_GNUTLS_DANE_FALSE= fi cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_DANE $gnutls_dane _ACEOF # Test if we are building for superMUC { $as_echo "$as_me:${as_lineno-$LINENO}: checking if GNUnet is being configured to run on the SuperMUC" >&5 $as_echo_n "checking if GNUnet is being configured to run on the SuperMUC... " >&6; } # Check whether --enable-supermuc was given. if test "${enable_supermuc+set}" = set; then : enableval=$enable_supermuc; if test "x$enable_supermuc" = "xno" then supermuc=0 else supermuc=1 fi else supermuc=0 enable_supermuc=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_SUPERMUC" >&5 $as_echo "$enable_SUPERMUC" >&6; } if test "x$supermuc" = "x1"; then ENABLE_SUPERMUC_TRUE= ENABLE_SUPERMUC_FALSE='#' else ENABLE_SUPERMUC_TRUE='#' ENABLE_SUPERMUC_FALSE= fi cat >>confdefs.h <<_ACEOF #define ENABLE_SUPERMUC $supermuc _ACEOF # Check if NSE has to send timestamp information to testbed logger for # generating histogram of messages received { $as_echo "$as_me:${as_lineno-$LINENO}: checking if NSE has to send timestamp information to testbed logger" >&5 $as_echo_n "checking if NSE has to send timestamp information to testbed logger... " >&6; } # Check whether --enable-nse-histogram was given. if test "${enable_nse_histogram+set}" = set; then : enableval=$enable_nse_histogram; if test "x$enableval" = "xno" then nse_histogram=0 else nse_histogram=1 fi else nse_histogram=0 enable_nse_histogram=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_nse_histogram" >&5 $as_echo "$enable_nse_histogram" >&6; } if test "x$nse_histogram" = "x1"; then ENABLE_NSE_HISTOGRAM_TRUE= ENABLE_NSE_HISTOGRAM_FALSE='#' else ENABLE_NSE_HISTOGRAM_TRUE='#' ENABLE_NSE_HISTOGRAM_FALSE= fi cat >>confdefs.h <<_ACEOF #define ENABLE_NSE_HISTOGRAM $nse_histogram _ACEOF # should 'make check' run tests? { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to run tests" >&5 $as_echo_n "checking whether to run tests... " >&6; } # Check whether --enable-testruns was given. if test "${enable_testruns+set}" = set; then : enableval=$enable_testruns; enable_tests_run=${enableval} else enable_tests_run=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_test_run" >&5 $as_echo "$enable_test_run" >&6; } if test "x$enable_tests_run" = "xyes"; then ENABLE_TEST_RUN_TRUE= ENABLE_TEST_RUN_FALSE='#' else ENABLE_TEST_RUN_TRUE='#' ENABLE_TEST_RUN_FALSE= fi # should monkey be used when running (certain) services? { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to run with monkey" >&5 $as_echo_n "checking whether to run with monkey... " >&6; } # Check whether --enable-monkey was given. if test "${enable_monkey+set}" = set; then : enableval=$enable_monkey; enable_monkey=${enableval} else enable_monkey=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_monkey" >&5 $as_echo "$enable_monkey" >&6; } if test "x$enable_monkey" = "xyes"; then ENABLE_MONKEY_TRUE= ENABLE_MONKEY_FALSE='#' else ENABLE_MONKEY_TRUE='#' ENABLE_MONKEY_FALSE= fi if test "x$enable_monkey" = "xyes" then MONKEYPREFIX="pathologist -d $(eval echo ${datarootdir}/gnunet/gnunet.sqlite) -p 30 --" else MONKEYPREFIX="" fi # should expensive tests be run? { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to run expensive tests" >&5 $as_echo_n "checking whether to run expensive tests... " >&6; } # Check whether --enable-expensivetests was given. if test "${enable_expensivetests+set}" = set; then : enableval=$enable_expensivetests; enable_expensive=${enableval} else enable_expensive=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_expensive" >&5 $as_echo "$enable_expensive" >&6; } if test "x$enable_expensive" = "xyes"; then HAVE_EXPENSIVE_TESTS_TRUE= HAVE_EXPENSIVE_TESTS_FALSE='#' else HAVE_EXPENSIVE_TESTS_TRUE='#' HAVE_EXPENSIVE_TESTS_FALSE= fi # should ports be open for Java services? { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable ports for gnunet-java" >&5 $as_echo_n "checking whether to enable ports for gnunet-java... " >&6; } # Check whether --enable-javaports was given. if test "${enable_javaports+set}" = set; then : enableval=$enable_javaports; enable_java_ports=${enableval} else enable_java_ports=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_java_ports" >&5 $as_echo "$enable_java_ports" >&6; } if test "x$enable_java_ports" = "xyes" then JAVAPORT="" else JAVAPORT="$UNIXONLY" fi # should benchmarks be run? { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to run benchmarks during make check" >&5 $as_echo_n "checking whether to run benchmarks during make check... " >&6; } # Check whether --enable-benchmarks was given. if test "${enable_benchmarks+set}" = set; then : enableval=$enable_benchmarks; enable_benchmarks=${enableval} else enable_benchmarks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_benchmarks" >&5 $as_echo "$enable_benchmarks" >&6; } if test "x$enable_benchmarks" = "xyes"; then HAVE_BENCHMARKS_TRUE= HAVE_BENCHMARKS_FALSE='#' else HAVE_BENCHMARKS_TRUE='#' HAVE_BENCHMARKS_FALSE= fi # should gnunet-testing be compiled { $as_echo "$as_me:${as_lineno-$LINENO}: checking wether to compile gnunet-testing" >&5 $as_echo_n "checking wether to compile gnunet-testing... " >&6; } # Check whether --enable-testing was given. if test "${enable_testing+set}" = set; then : enableval=$enable_testing; enable_testing=${enableval} else enable_testing=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_testing" >&5 $as_echo "$enable_testing" >&6; } if test "x$enable_testing" = "xyes"; then HAVE_TESTING_TRUE= HAVE_TESTING_FALSE='#' else HAVE_TESTING_TRUE='#' HAVE_TESTING_FALSE= fi # should experimental code be compiled (code that may not yet compile)? { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compile experimental code" >&5 $as_echo_n "checking whether to compile experimental code... " >&6; } # Check whether --enable-experimental was given. if test "${enable_experimental+set}" = set; then : enableval=$enable_experimental; enable_experimental=${enableval} else enable_experimental=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_experimental" >&5 $as_echo "$enable_experimental" >&6; } if test "x$enable_experimental" = "xyes"; then HAVE_EXPERIMENTAL_TRUE= HAVE_EXPERIMENTAL_FALSE='#' else HAVE_EXPERIMENTAL_TRUE='#' HAVE_EXPERIMENTAL_FALSE= fi # should services be started by default when a peer starts? Some services may # choose to never start by default and it is upto the service/module developer to # decide it by having "AUTOSTART = NO" instead of "AUTOSTART = @AUTOSTART" in # the service/module's conf.in file. AUTOSTART="YES" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to auto-start peer's services by default" >&5 $as_echo_n "checking whether to auto-start peer's services by default... " >&6; } # Check whether --enable-autostart was given. if test "${enable_autostart+set}" = set; then : enableval=$enable_autostart; enable_autostart=${enableval} if test "x$enable_autostart" == "xno" then AUTOSTART="NO" fi else enable_autostart=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_autostart" >&5 $as_echo "$enable_autostart" >&6; } #AM_CONDITIONAL([HAVE_AUTOSTART], [test "x$enable_autostart" = "xyes"]) # should memory statistics be kept (very expensive CPU-wise!) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to create expensive statistics on memory use" >&5 $as_echo_n "checking whether to create expensive statistics on memory use... " >&6; } # Check whether --enable-heapstats was given. if test "${enable_heapstats+set}" = set; then : enableval=$enable_heapstats; enable_heapstats=1 else enable_heapstats=0 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_heapstats" >&5 $as_echo "$enable_heapstats" >&6; } cat >>confdefs.h <<_ACEOF #define ENABLE_HEAP_STATISTICS $enable_heapstats _ACEOF # should code be enabled that works around missing OS functionality on Windows? # used for test cases if test $build_target = "mingw" then workarounds=1 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int s = socket (0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define HAVE_SOCKET 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_SOCKET 0 _ACEOF fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int s = select (0, NULL, NULL, NULL, NULL); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define HAVE_SELECT 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_SELECT 0 _ACEOF fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct in_addr i; char *s = inet_ntoa (i); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define HAVE_INET_NTOA 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_INET_NTOA 0 _ACEOF fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int s = getnameinfo (NULL, 0, NULL, 0, NULL, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETNAMEINFO 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_GETNAMEINFO 0 _ACEOF fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int s = gethostname (NULL, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETHOSTNAME 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_GETHOSTNAME 0 _ACEOF fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { void *s = gethostbyname (NULL); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETHOSTBYNAME 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_GETHOSTBYNAME 0 _ACEOF fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { void *s = gethostbyaddr (NULL, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETHOSTBYADDR 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_GETHOSTBYADDR 0 _ACEOF fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int s = getaddrinfo (NULL, NULL, NULL, NULL); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETADDRINFO 1 _ACEOF else cat >>confdefs.h <<_ACEOF #define HAVE_GETADDRINFO 1 _ACEOF fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable windows workarounds" >&5 $as_echo_n "checking whether to enable windows workarounds... " >&6; } # Check whether --enable-windows_workarounds was given. if test "${enable_windows_workarounds+set}" = set; then : enableval=$enable_windows_workarounds; enable_workarounds=${enableval} else enable_workarounds=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_workarounds" >&5 $as_echo "$enable_workarounds" >&6; } if test x$enable_windows_workarounds = "xyes" then workarounds=1 else workarounds=0 fi fi cat >>confdefs.h <<_ACEOF #define ENABLE_WINDOWS_WORKAROUNDS $workarounds _ACEOF # gcov compilation { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to compile with support for code coverage analysis" >&5 $as_echo_n "checking whether to compile with support for code coverage analysis... " >&6; } # Check whether --enable-coverage was given. if test "${enable_coverage+set}" = set; then : enableval=$enable_coverage; use_gcov=${enableval} else use_gcov=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $use_gcov" >&5 $as_echo "$use_gcov" >&6; } if test "x$use_gcov" = "xyes"; then USE_COVERAGE_TRUE= USE_COVERAGE_FALSE='#' else USE_COVERAGE_TRUE='#' USE_COVERAGE_FALSE= fi # version info # Extract the first word of "svnversion", so it can be a program name with args. set dummy svnversion; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_svnversioncommand+:} false; then : $as_echo_n "(cached) " >&6 else case $svnversioncommand in [\\/]* | ?:[\\/]*) ac_cv_path_svnversioncommand="$svnversioncommand" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_svnversioncommand="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi svnversioncommand=$ac_cv_path_svnversioncommand if test -n "$svnversioncommand"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svnversioncommand" >&5 $as_echo "$svnversioncommand" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "git", so it can be a program name with args. set dummy git; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_gitcommand+:} false; then : $as_echo_n "(cached) " >&6 else case $gitcommand in [\\/]* | ?:[\\/]*) ac_cv_path_gitcommand="$gitcommand" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_gitcommand="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi gitcommand=$ac_cv_path_gitcommand if test -n "$gitcommand"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gitcommand" >&5 $as_echo "$gitcommand" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for source being under a VCS" >&5 $as_echo_n "checking for source being under a VCS... " >&6; } svn_version= gitsvn_version= if test ! "X$svnversioncommand" = "X"; then : svn_version=$(cd $srcdir ; $svnversioncommand -n 2>/dev/null) fi if test ! "X$gitcommand" = "X"; then : gitsvn_version=$(cd $srcdir ; git log -1 2>/dev/null | grep "git-svn-id" | sed -e 's/.*@\([0-9]\+\) .*/\1/') fi if test "X$svn_version" = "X" -o "X$svn_version" = "Xexported" -o "X$svn_version" = "XUnversioned directory"; then : if test "X$gitsvn_version" = "X"; then : vcs_name="no" vcs_version="\"release\"" else vcs_name="yes, git-svn" vcs_version="\"svn-r$gitsvn_version\"" fi else vcs_name="yes, svn" vcs_version="\"svn-r$svn_version\"" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $vcs_name" >&5 $as_echo "$vcs_name" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking VCS version" >&5 $as_echo_n "checking VCS version... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $vcs_version" >&5 $as_echo "$vcs_version" >&6; } cat >>confdefs.h <<_ACEOF #define VCS_VERSION $vcs_version _ACEOF ac_config_files="$ac_config_files Makefile contrib/Makefile doc/Makefile doc/man/Makefile doc/doxygen/Makefile m4/Makefile po/Makefile.in src/Makefile src/arm/Makefile src/arm/arm.conf src/ats/Makefile src/ats/ats.conf src/ats-tool/Makefile src/ats-tests/Makefile src/block/Makefile src/core/Makefile src/core/core.conf src/consensus/Makefile src/consensus/consensus.conf src/conversation/Makefile src/conversation/conversation.conf src/datacache/Makefile src/datastore/Makefile src/datastore/datastore.conf src/dht/Makefile src/dht/dht.conf src/dns/Makefile src/dns/dns.conf src/dv/Makefile src/dv/dv.conf src/env/Makefile src/exit/Makefile src/experimentation/Makefile src/experimentation/experimentation.conf src/fragmentation/Makefile src/fs/Makefile src/fs/fs.conf src/gns/Makefile src/gns/gns.conf src/gns/nss/Makefile src/gnsrecord/Makefile src/hello/Makefile src/identity/Makefile src/identity/identity.conf src/include/Makefile src/integration-tests/Makefile src/hostlist/Makefile src/mesh/Makefile src/mesh/mesh.conf src/multicast/Makefile src/multicast/multicast.conf src/mysql/Makefile src/namecache/Makefile src/namecache/namecache.conf src/namestore/Makefile src/namestore/namestore.conf src/nat/Makefile src/nse/Makefile src/nse/nse.conf src/peerinfo/Makefile src/peerinfo/peerinfo.conf src/peerinfo-tool/Makefile src/postgres/Makefile src/psyc/Makefile src/psyc/psyc.conf src/psycstore/Makefile src/psycstore/psycstore.conf src/pt/Makefile src/regex/Makefile src/regex/regex.conf src/revocation/Makefile src/revocation/revocation.conf src/secretsharing/Makefile src/secretsharing/secretsharing.conf src/scalarproduct/Makefile src/scalarproduct/scalarproduct.conf src/set/Makefile src/set/set.conf src/statistics/Makefile src/statistics/statistics.conf src/template/Makefile src/testbed/Makefile src/testbed/testbed.conf src/testing/Makefile src/topology/Makefile src/transport/Makefile src/transport/transport.conf src/tun/Makefile src/util/Makefile src/util/resolver.conf src/vpn/Makefile src/vpn/vpn.conf pkgconfig/Makefile pkgconfig/gnunetarm.pc pkgconfig/gnunetats.pc pkgconfig/gnunetblock.pc pkgconfig/gnunetconsensus.pc pkgconfig/gnunetconversation.pc pkgconfig/gnunetcore.pc pkgconfig/gnunetdatacache.pc pkgconfig/gnunetdatastore.pc pkgconfig/gnunetdht.pc pkgconfig/gnunetdns.pc pkgconfig/gnunetdnsparser.pc pkgconfig/gnunetdnsstub.pc pkgconfig/gnunetdv.pc pkgconfig/gnunetenv.pc pkgconfig/gnunetfragmentation.pc pkgconfig/gnunetfs.pc pkgconfig/gnunetgns.pc pkgconfig/gnunethello.pc pkgconfig/gnunetidentity.pc pkgconfig/gnunetmesh.pc pkgconfig/gnunetmicrophone.pc pkgconfig/gnunetmulticast.pc pkgconfig/gnunetmysql.pc pkgconfig/gnunetnamestore.pc pkgconfig/gnunetnat.pc pkgconfig/gnunetnse.pc pkgconfig/gnunetpeerinfo.pc pkgconfig/gnunetpostgres.pc pkgconfig/gnunetpsyc.pc pkgconfig/gnunetpsycstore.pc pkgconfig/gnunetregex.pc pkgconfig/gnunetrevocation.pc pkgconfig/gnunetscalarproduct.pc pkgconfig/gnunetset.pc pkgconfig/gnunetspeaker.pc pkgconfig/gnunetstatistics.pc pkgconfig/gnunettestbed.pc pkgconfig/gnunettesting.pc pkgconfig/gnunettransport.pc pkgconfig/gnunettun.pc pkgconfig/gnunetutil.pc pkgconfig/gnunetvpn.pc" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepOBJC_TRUE}" && test -z "${am__fastdepOBJC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepOBJC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${DARWIN_TRUE}" && test -z "${DARWIN_FALSE}"; then as_fn_error $? "conditional \"DARWIN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${CYGWIN_TRUE}" && test -z "${CYGWIN_FALSE}"; then as_fn_error $? "conditional \"CYGWIN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MINGW_TRUE}" && test -z "${MINGW_FALSE}"; then as_fn_error $? "conditional \"MINGW\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${SOLARIS_TRUE}" && test -z "${SOLARIS_FALSE}"; then as_fn_error $? "conditional \"SOLARIS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${XFREEBSD_TRUE}" && test -z "${XFREEBSD_FALSE}"; then as_fn_error $? "conditional \"XFREEBSD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OPENBSD_TRUE}" && test -z "${OPENBSD_FALSE}"; then as_fn_error $? "conditional \"OPENBSD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LINUX_TRUE}" && test -z "${LINUX_FALSE}"; then as_fn_error $? "conditional \"LINUX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GNU_TRUE}" && test -z "${GNU_FALSE}"; then as_fn_error $? "conditional \"GNU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepOBJC_TRUE}" && test -z "${am__fastdepOBJC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepOBJC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBBLUETOOTH_TRUE}" && test -z "${HAVE_LIBBLUETOOTH_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBBLUETOOTH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBBLUETOOTH_TRUE}" && test -z "${HAVE_LIBBLUETOOTH_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBBLUETOOTH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_OGG_TRUE}" && test -z "${HAVE_OGG_FALSE}"; then as_fn_error $? "conditional \"HAVE_OGG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_OGG_TRUE}" && test -z "${HAVE_OGG_FALSE}"; then as_fn_error $? "conditional \"HAVE_OGG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_OGG_TRUE}" && test -z "${HAVE_OGG_FALSE}"; then as_fn_error $? "conditional \"HAVE_OGG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_PULSE_HELPERS_TRUE}" && test -z "${BUILD_PULSE_HELPERS_FALSE}"; then as_fn_error $? "conditional \"BUILD_PULSE_HELPERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_GST_HELPERS_TRUE}" && test -z "${BUILD_GST_HELPERS_FALSE}"; then as_fn_error $? "conditional \"BUILD_GST_HELPERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_PULSE_HELPERS_TRUE}" && test -z "${BUILD_PULSE_HELPERS_FALSE}"; then as_fn_error $? "conditional \"BUILD_PULSE_HELPERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_GST_HELPERS_TRUE}" && test -z "${BUILD_GST_HELPERS_FALSE}"; then as_fn_error $? "conditional \"BUILD_GST_HELPERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_PULSE_HELPERS_TRUE}" && test -z "${BUILD_PULSE_HELPERS_FALSE}"; then as_fn_error $? "conditional \"BUILD_PULSE_HELPERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_GST_HELPERS_TRUE}" && test -z "${BUILD_GST_HELPERS_FALSE}"; then as_fn_error $? "conditional \"BUILD_GST_HELPERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBGNURL_TRUE}" && test -z "${HAVE_LIBGNURL_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBGNURL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBGNURL_TRUE}" && test -z "${HAVE_LIBGNURL_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBGNURL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBGLPK_TRUE}" && test -z "${HAVE_LIBGLPK_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBGLPK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBGLPK_TRUE}" && test -z "${HAVE_LIBGLPK_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBGLPK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GLIBCNSS_TRUE}" && test -z "${HAVE_GLIBCNSS_FALSE}"; then as_fn_error $? "conditional \"HAVE_GLIBCNSS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GLIBCNSS_TRUE}" && test -z "${HAVE_GLIBCNSS_FALSE}"; then as_fn_error $? "conditional \"HAVE_GLIBCNSS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_SQLITE_TRUE}" && test -z "${HAVE_SQLITE_FALSE}"; then as_fn_error $? "conditional \"HAVE_SQLITE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_POSTGRES_TRUE}" && test -z "${HAVE_POSTGRES_FALSE}"; then as_fn_error $? "conditional \"HAVE_POSTGRES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_MYSQL_TRUE}" && test -z "${HAVE_MYSQL_FALSE}"; then as_fn_error $? "conditional \"HAVE_MYSQL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_MYSQLE_TRUE}" && test -z "${HAVE_MYSQLE_FALSE}"; then as_fn_error $? "conditional \"HAVE_MYSQLE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_MHD_TRUE}" && test -z "${HAVE_MHD_FALSE}"; then as_fn_error $? "conditional \"HAVE_MHD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_PYTHON_TRUE}" && test -z "${HAVE_PYTHON_FALSE}"; then as_fn_error $? "conditional \"HAVE_PYTHON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_FRAMEWORK_TRUE}" && test -z "${WANT_FRAMEWORK_FALSE}"; then as_fn_error $? "conditional \"WANT_FRAMEWORK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_SUDO_TRUE}" && test -z "${HAVE_SUDO_FALSE}"; then as_fn_error $? "conditional \"HAVE_SUDO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${INSTALL_NSS_TRUE}" && test -z "${INSTALL_NSS_FALSE}"; then as_fn_error $? "conditional \"INSTALL_NSS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GNUTLS_TRUE}" && test -z "${HAVE_GNUTLS_FALSE}"; then as_fn_error $? "conditional \"HAVE_GNUTLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GNUTLS_DANE_TRUE}" && test -z "${HAVE_GNUTLS_DANE_FALSE}"; then as_fn_error $? "conditional \"HAVE_GNUTLS_DANE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SUPERMUC_TRUE}" && test -z "${ENABLE_SUPERMUC_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SUPERMUC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_NSE_HISTOGRAM_TRUE}" && test -z "${ENABLE_NSE_HISTOGRAM_FALSE}"; then as_fn_error $? "conditional \"ENABLE_NSE_HISTOGRAM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_TEST_RUN_TRUE}" && test -z "${ENABLE_TEST_RUN_FALSE}"; then as_fn_error $? "conditional \"ENABLE_TEST_RUN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_MONKEY_TRUE}" && test -z "${ENABLE_MONKEY_FALSE}"; then as_fn_error $? "conditional \"ENABLE_MONKEY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_EXPENSIVE_TESTS_TRUE}" && test -z "${HAVE_EXPENSIVE_TESTS_FALSE}"; then as_fn_error $? "conditional \"HAVE_EXPENSIVE_TESTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_BENCHMARKS_TRUE}" && test -z "${HAVE_BENCHMARKS_FALSE}"; then as_fn_error $? "conditional \"HAVE_BENCHMARKS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_TESTING_TRUE}" && test -z "${HAVE_TESTING_FALSE}"; then as_fn_error $? "conditional \"HAVE_TESTING\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_EXPERIMENTAL_TRUE}" && test -z "${HAVE_EXPERIMENTAL_FALSE}"; then as_fn_error $? "conditional \"HAVE_EXPERIMENTAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_COVERAGE_TRUE}" && test -z "${USE_COVERAGE_FALSE}"; then as_fn_error $? "conditional \"USE_COVERAGE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by gnunet $as_me 0.10.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ gnunet config.status 0.10.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in AS \ DLLTOOL \ OBJDUMP \ SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib \ compiler_lib_search_dirs \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ LD_CXX \ reload_flag_CXX \ compiler_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_static_CXX \ lt_cv_prog_compiler_c_o_CXX \ export_dynamic_flag_spec_CXX \ whole_archive_flag_spec_CXX \ compiler_needs_object_CXX \ with_gnu_ld_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_separator_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX \ file_list_spec_CXX \ compiler_lib_search_dirs_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec \ reload_cmds_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ export_symbols_cmds_CXX \ prelink_cmds_CXX \ postlink_cmds_CXX; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' # Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake < 1.5. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "gnunet_config.h") CONFIG_HEADERS="$CONFIG_HEADERS gnunet_config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/man/Makefile") CONFIG_FILES="$CONFIG_FILES doc/man/Makefile" ;; "doc/doxygen/Makefile") CONFIG_FILES="$CONFIG_FILES doc/doxygen/Makefile" ;; "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/arm/Makefile") CONFIG_FILES="$CONFIG_FILES src/arm/Makefile" ;; "src/arm/arm.conf") CONFIG_FILES="$CONFIG_FILES src/arm/arm.conf" ;; "src/ats/Makefile") CONFIG_FILES="$CONFIG_FILES src/ats/Makefile" ;; "src/ats/ats.conf") CONFIG_FILES="$CONFIG_FILES src/ats/ats.conf" ;; "src/ats-tool/Makefile") CONFIG_FILES="$CONFIG_FILES src/ats-tool/Makefile" ;; "src/ats-tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/ats-tests/Makefile" ;; "src/block/Makefile") CONFIG_FILES="$CONFIG_FILES src/block/Makefile" ;; "src/core/Makefile") CONFIG_FILES="$CONFIG_FILES src/core/Makefile" ;; "src/core/core.conf") CONFIG_FILES="$CONFIG_FILES src/core/core.conf" ;; "src/consensus/Makefile") CONFIG_FILES="$CONFIG_FILES src/consensus/Makefile" ;; "src/consensus/consensus.conf") CONFIG_FILES="$CONFIG_FILES src/consensus/consensus.conf" ;; "src/conversation/Makefile") CONFIG_FILES="$CONFIG_FILES src/conversation/Makefile" ;; "src/conversation/conversation.conf") CONFIG_FILES="$CONFIG_FILES src/conversation/conversation.conf" ;; "src/datacache/Makefile") CONFIG_FILES="$CONFIG_FILES src/datacache/Makefile" ;; "src/datastore/Makefile") CONFIG_FILES="$CONFIG_FILES src/datastore/Makefile" ;; "src/datastore/datastore.conf") CONFIG_FILES="$CONFIG_FILES src/datastore/datastore.conf" ;; "src/dht/Makefile") CONFIG_FILES="$CONFIG_FILES src/dht/Makefile" ;; "src/dht/dht.conf") CONFIG_FILES="$CONFIG_FILES src/dht/dht.conf" ;; "src/dns/Makefile") CONFIG_FILES="$CONFIG_FILES src/dns/Makefile" ;; "src/dns/dns.conf") CONFIG_FILES="$CONFIG_FILES src/dns/dns.conf" ;; "src/dv/Makefile") CONFIG_FILES="$CONFIG_FILES src/dv/Makefile" ;; "src/dv/dv.conf") CONFIG_FILES="$CONFIG_FILES src/dv/dv.conf" ;; "src/env/Makefile") CONFIG_FILES="$CONFIG_FILES src/env/Makefile" ;; "src/exit/Makefile") CONFIG_FILES="$CONFIG_FILES src/exit/Makefile" ;; "src/experimentation/Makefile") CONFIG_FILES="$CONFIG_FILES src/experimentation/Makefile" ;; "src/experimentation/experimentation.conf") CONFIG_FILES="$CONFIG_FILES src/experimentation/experimentation.conf" ;; "src/fragmentation/Makefile") CONFIG_FILES="$CONFIG_FILES src/fragmentation/Makefile" ;; "src/fs/Makefile") CONFIG_FILES="$CONFIG_FILES src/fs/Makefile" ;; "src/fs/fs.conf") CONFIG_FILES="$CONFIG_FILES src/fs/fs.conf" ;; "src/gns/Makefile") CONFIG_FILES="$CONFIG_FILES src/gns/Makefile" ;; "src/gns/gns.conf") CONFIG_FILES="$CONFIG_FILES src/gns/gns.conf" ;; "src/gns/nss/Makefile") CONFIG_FILES="$CONFIG_FILES src/gns/nss/Makefile" ;; "src/gnsrecord/Makefile") CONFIG_FILES="$CONFIG_FILES src/gnsrecord/Makefile" ;; "src/hello/Makefile") CONFIG_FILES="$CONFIG_FILES src/hello/Makefile" ;; "src/identity/Makefile") CONFIG_FILES="$CONFIG_FILES src/identity/Makefile" ;; "src/identity/identity.conf") CONFIG_FILES="$CONFIG_FILES src/identity/identity.conf" ;; "src/include/Makefile") CONFIG_FILES="$CONFIG_FILES src/include/Makefile" ;; "src/integration-tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/integration-tests/Makefile" ;; "src/hostlist/Makefile") CONFIG_FILES="$CONFIG_FILES src/hostlist/Makefile" ;; "src/mesh/Makefile") CONFIG_FILES="$CONFIG_FILES src/mesh/Makefile" ;; "src/mesh/mesh.conf") CONFIG_FILES="$CONFIG_FILES src/mesh/mesh.conf" ;; "src/multicast/Makefile") CONFIG_FILES="$CONFIG_FILES src/multicast/Makefile" ;; "src/multicast/multicast.conf") CONFIG_FILES="$CONFIG_FILES src/multicast/multicast.conf" ;; "src/mysql/Makefile") CONFIG_FILES="$CONFIG_FILES src/mysql/Makefile" ;; "src/namecache/Makefile") CONFIG_FILES="$CONFIG_FILES src/namecache/Makefile" ;; "src/namecache/namecache.conf") CONFIG_FILES="$CONFIG_FILES src/namecache/namecache.conf" ;; "src/namestore/Makefile") CONFIG_FILES="$CONFIG_FILES src/namestore/Makefile" ;; "src/namestore/namestore.conf") CONFIG_FILES="$CONFIG_FILES src/namestore/namestore.conf" ;; "src/nat/Makefile") CONFIG_FILES="$CONFIG_FILES src/nat/Makefile" ;; "src/nse/Makefile") CONFIG_FILES="$CONFIG_FILES src/nse/Makefile" ;; "src/nse/nse.conf") CONFIG_FILES="$CONFIG_FILES src/nse/nse.conf" ;; "src/peerinfo/Makefile") CONFIG_FILES="$CONFIG_FILES src/peerinfo/Makefile" ;; "src/peerinfo/peerinfo.conf") CONFIG_FILES="$CONFIG_FILES src/peerinfo/peerinfo.conf" ;; "src/peerinfo-tool/Makefile") CONFIG_FILES="$CONFIG_FILES src/peerinfo-tool/Makefile" ;; "src/postgres/Makefile") CONFIG_FILES="$CONFIG_FILES src/postgres/Makefile" ;; "src/psyc/Makefile") CONFIG_FILES="$CONFIG_FILES src/psyc/Makefile" ;; "src/psyc/psyc.conf") CONFIG_FILES="$CONFIG_FILES src/psyc/psyc.conf" ;; "src/psycstore/Makefile") CONFIG_FILES="$CONFIG_FILES src/psycstore/Makefile" ;; "src/psycstore/psycstore.conf") CONFIG_FILES="$CONFIG_FILES src/psycstore/psycstore.conf" ;; "src/pt/Makefile") CONFIG_FILES="$CONFIG_FILES src/pt/Makefile" ;; "src/regex/Makefile") CONFIG_FILES="$CONFIG_FILES src/regex/Makefile" ;; "src/regex/regex.conf") CONFIG_FILES="$CONFIG_FILES src/regex/regex.conf" ;; "src/revocation/Makefile") CONFIG_FILES="$CONFIG_FILES src/revocation/Makefile" ;; "src/revocation/revocation.conf") CONFIG_FILES="$CONFIG_FILES src/revocation/revocation.conf" ;; "src/secretsharing/Makefile") CONFIG_FILES="$CONFIG_FILES src/secretsharing/Makefile" ;; "src/secretsharing/secretsharing.conf") CONFIG_FILES="$CONFIG_FILES src/secretsharing/secretsharing.conf" ;; "src/scalarproduct/Makefile") CONFIG_FILES="$CONFIG_FILES src/scalarproduct/Makefile" ;; "src/scalarproduct/scalarproduct.conf") CONFIG_FILES="$CONFIG_FILES src/scalarproduct/scalarproduct.conf" ;; "src/set/Makefile") CONFIG_FILES="$CONFIG_FILES src/set/Makefile" ;; "src/set/set.conf") CONFIG_FILES="$CONFIG_FILES src/set/set.conf" ;; "src/statistics/Makefile") CONFIG_FILES="$CONFIG_FILES src/statistics/Makefile" ;; "src/statistics/statistics.conf") CONFIG_FILES="$CONFIG_FILES src/statistics/statistics.conf" ;; "src/template/Makefile") CONFIG_FILES="$CONFIG_FILES src/template/Makefile" ;; "src/testbed/Makefile") CONFIG_FILES="$CONFIG_FILES src/testbed/Makefile" ;; "src/testbed/testbed.conf") CONFIG_FILES="$CONFIG_FILES src/testbed/testbed.conf" ;; "src/testing/Makefile") CONFIG_FILES="$CONFIG_FILES src/testing/Makefile" ;; "src/topology/Makefile") CONFIG_FILES="$CONFIG_FILES src/topology/Makefile" ;; "src/transport/Makefile") CONFIG_FILES="$CONFIG_FILES src/transport/Makefile" ;; "src/transport/transport.conf") CONFIG_FILES="$CONFIG_FILES src/transport/transport.conf" ;; "src/tun/Makefile") CONFIG_FILES="$CONFIG_FILES src/tun/Makefile" ;; "src/util/Makefile") CONFIG_FILES="$CONFIG_FILES src/util/Makefile" ;; "src/util/resolver.conf") CONFIG_FILES="$CONFIG_FILES src/util/resolver.conf" ;; "src/vpn/Makefile") CONFIG_FILES="$CONFIG_FILES src/vpn/Makefile" ;; "src/vpn/vpn.conf") CONFIG_FILES="$CONFIG_FILES src/vpn/vpn.conf" ;; "pkgconfig/Makefile") CONFIG_FILES="$CONFIG_FILES pkgconfig/Makefile" ;; "pkgconfig/gnunetarm.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetarm.pc" ;; "pkgconfig/gnunetats.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetats.pc" ;; "pkgconfig/gnunetblock.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetblock.pc" ;; "pkgconfig/gnunetconsensus.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetconsensus.pc" ;; "pkgconfig/gnunetconversation.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetconversation.pc" ;; "pkgconfig/gnunetcore.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetcore.pc" ;; "pkgconfig/gnunetdatacache.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetdatacache.pc" ;; "pkgconfig/gnunetdatastore.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetdatastore.pc" ;; "pkgconfig/gnunetdht.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetdht.pc" ;; "pkgconfig/gnunetdns.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetdns.pc" ;; "pkgconfig/gnunetdnsparser.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetdnsparser.pc" ;; "pkgconfig/gnunetdnsstub.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetdnsstub.pc" ;; "pkgconfig/gnunetdv.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetdv.pc" ;; "pkgconfig/gnunetenv.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetenv.pc" ;; "pkgconfig/gnunetfragmentation.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetfragmentation.pc" ;; "pkgconfig/gnunetfs.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetfs.pc" ;; "pkgconfig/gnunetgns.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetgns.pc" ;; "pkgconfig/gnunethello.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunethello.pc" ;; "pkgconfig/gnunetidentity.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetidentity.pc" ;; "pkgconfig/gnunetmesh.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetmesh.pc" ;; "pkgconfig/gnunetmicrophone.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetmicrophone.pc" ;; "pkgconfig/gnunetmulticast.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetmulticast.pc" ;; "pkgconfig/gnunetmysql.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetmysql.pc" ;; "pkgconfig/gnunetnamestore.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetnamestore.pc" ;; "pkgconfig/gnunetnat.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetnat.pc" ;; "pkgconfig/gnunetnse.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetnse.pc" ;; "pkgconfig/gnunetpeerinfo.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetpeerinfo.pc" ;; "pkgconfig/gnunetpostgres.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetpostgres.pc" ;; "pkgconfig/gnunetpsyc.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetpsyc.pc" ;; "pkgconfig/gnunetpsycstore.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetpsycstore.pc" ;; "pkgconfig/gnunetregex.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetregex.pc" ;; "pkgconfig/gnunetrevocation.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetrevocation.pc" ;; "pkgconfig/gnunetscalarproduct.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetscalarproduct.pc" ;; "pkgconfig/gnunetset.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetset.pc" ;; "pkgconfig/gnunetspeaker.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetspeaker.pc" ;; "pkgconfig/gnunetstatistics.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetstatistics.pc" ;; "pkgconfig/gnunettestbed.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunettestbed.pc" ;; "pkgconfig/gnunettesting.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunettesting.pc" ;; "pkgconfig/gnunettransport.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunettransport.pc" ;; "pkgconfig/gnunettun.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunettun.pc" ;; "pkgconfig/gnunetutil.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetutil.pc" ;; "pkgconfig/gnunetvpn.pc") CONFIG_FILES="$CONFIG_FILES pkgconfig/gnunetvpn.pc" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="CXX " # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static # Assembler program. AS=$lt_AS # DLL creation program. DLLTOOL=$lt_DLLTOOL # Object dumper program. OBJDUMP=$lt_OBJDUMP # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects postdep_objects=$lt_postdep_objects predeps=$lt_predeps postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" cat <<_LT_EOF >> "$ofile" # ### BEGIN LIBTOOL TAG CONFIG: CXX # The linker used to build libraries. LD=$lt_LD_CXX # How to create reloadable object files. reload_flag=$lt_reload_flag_CXX reload_cmds=$lt_reload_cmds_CXX # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds_CXX # A language specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU compiler? with_gcc=$GCC_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object_CXX # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld_CXX # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute_CXX # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic_CXX # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath_CXX # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds_CXX # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds_CXX # Specify filename containing input files. file_list_spec=$lt_file_list_spec_CXX # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # The directories searched by this compiler when creating a shared library. compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX # Dependencies to place before and after the objects being linked to # create a shared library. predep_objects=$lt_predep_objects_CXX postdep_objects=$lt_postdep_objects_CXX predeps=$lt_predeps_CXX postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # ### END LIBTOOL TAG CONFIG: CXX _LT_EOF ;; "po-directories":C) for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) # Compute UPDATEPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) # Compute DUMMYPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) # Compute GMOFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= UPDATEPOFILES= DUMMYPOFILES= GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # Finally: summary! # warn user if mysql found but not used due to version if test "$mysqlfail" = "true" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: MySQL found, but too old. MySQL support will not be compiled." >&5 $as_echo "$as_me: NOTICE: MySQL found, but too old. MySQL support will not be compiled." >&6;} fi # sqlite if test "x$sqlite" = "x0" then as_fn_error $? "ERROR: sqlite3 not found, but sqlite3 is required." "$LINENO" 5 fi # libgnurl if test "x$gnurl" = "x0" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: libgnurl not found. http client support will not be compiled." >&5 $as_echo "$as_me: NOTICE: libgnurl not found. http client support will not be compiled." >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libgnurl not found. hostlist daemon will not be compiled, and you probably WANT hostlist daemon" >&5 $as_echo "$as_me: WARNING: libgnurl not found. hostlist daemon will not be compiled, and you probably WANT hostlist daemon" >&2;} fi # bluetooth if test "x$bluetooth" = "x0" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: bluetooth library not found. bluetooth support will not be compiled." >&5 $as_echo "$as_me: NOTICE: bluetooth library not found. bluetooth support will not be compiled." >&6;} fi #gnutls if test x$gnutls != xtrue then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: GnuTLS not found, gnunet-gns-proxy will not be built" >&5 $as_echo "$as_me: NOTICE: GnuTLS not found, gnunet-gns-proxy will not be built" >&6;} else if test "x$gnutls_dane" != "x1" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: GnuTLS has no DANE support, DANE validation will not be possible" >&5 $as_echo "$as_me: NOTICE: GnuTLS has no DANE support, DANE validation will not be possible" >&6;} fi fi # java ports if test "x$enable_java_ports" = "xyes" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: opening ports for gnunet-java bindings by default." >&5 $as_echo "$as_me: NOTICE: opening ports for gnunet-java bindings by default." >&6;} fi # MHD if test "x$lmhd" != "x1" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: libmicrohttpd not found, http transport will not be installed." >&5 $as_echo "$as_me: NOTICE: libmicrohttpd not found, http transport will not be installed." >&6;} fi # conversation if test "x$conversation_backend" == "xnone" then if test "x$pulse" != "x1" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: libpulse(audio) not found, conversation will not be built." >&5 $as_echo "$as_me: NOTICE: libpulse(audio) not found, conversation will not be built." >&6;} fi if test "x$opus" != "x1" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: libopus not found, conversation will not be built." >&5 $as_echo "$as_me: NOTICE: libopus not found, conversation will not be built." >&6;} fi if test "x$gst" != "x1" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: GStreamer not found, conversation will not be built." >&5 $as_echo "$as_me: NOTICE: GStreamer not found, conversation will not be built." >&6;} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: Database support is set to MySQL: $mysql, SQLite: $sqlite, Postgres: $postgres" >&5 $as_echo "$as_me: NOTICE: Database support is set to MySQL: $mysql, SQLite: $sqlite, Postgres: $postgres" >&6;} if test "$enable_framework_build" = "yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: Mac OS X framework build enabled." >&5 $as_echo "$as_me: NOTICE: Mac OS X framework build enabled." >&6;} fi if test "x$SUDO_BINARY" = "x" -a ! -w / then { $as_echo "$as_me:${as_lineno-$LINENO}: NOTICE: --with-sudo not specified and not running as 'root', will not install GNS NSS library" >&5 $as_echo "$as_me: NOTICE: --with-sudo not specified and not running as 'root', will not install GNS NSS library" >&6;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: ******************************************** Please make sure NOW that you have created a user and group 'gnunet' and additionally a group 'gnunetdns': addgroup gnunetdns adduser gnunet Make sure that '/var/lib/gnunet' is owned (and writable) by user 'gnunet'. Then, you can compile GNUnet with make After that, run (if necessary as 'root') make install to install everything. Each GNUnet user should be added to the 'gnunet' group (may require fresh login to come into effect): adduser USERNAME gnunet (run the above command as root once for each of your users, replacing \"USERNAME\" with the respective login names). If you have a global IP address, no further configuration is required. Optionally, download and compile gnunet-gtk to get a GUI for file-sharing and configuration. This is particularly recommended if your network setup is non-trivial, as gnunet-setup can be used to test in the GUI if your network configuration is working. gnunet-setup should be run as the \"gnunet\" user under X. As it does very little with the network, running it as \"root\" is likely also harmless. You can also run it as a normal user, but then you have to copy ~/.gnunet/gnunet.conf\" over to the \"gnunet\" user's home directory in the end. Once you have configured your peer, run (as the 'gnunet' user) gnunet-arm -s to start the peer. You can then run the various GNUnet-tools as your \"normal\" user (who should only be in the group 'gnunet'). ********************************************" >&5 $as_echo "$as_me: ******************************************** Please make sure NOW that you have created a user and group 'gnunet' and additionally a group 'gnunetdns': addgroup gnunetdns adduser gnunet Make sure that '/var/lib/gnunet' is owned (and writable) by user 'gnunet'. Then, you can compile GNUnet with make After that, run (if necessary as 'root') make install to install everything. Each GNUnet user should be added to the 'gnunet' group (may require fresh login to come into effect): adduser USERNAME gnunet (run the above command as root once for each of your users, replacing \"USERNAME\" with the respective login names). If you have a global IP address, no further configuration is required. Optionally, download and compile gnunet-gtk to get a GUI for file-sharing and configuration. This is particularly recommended if your network setup is non-trivial, as gnunet-setup can be used to test in the GUI if your network configuration is working. gnunet-setup should be run as the \"gnunet\" user under X. As it does very little with the network, running it as \"root\" is likely also harmless. You can also run it as a normal user, but then you have to copy ~/.gnunet/gnunet.conf\" over to the \"gnunet\" user's home directory in the end. Once you have configured your peer, run (as the 'gnunet' user) gnunet-arm -s to start the peer. You can then run the various GNUnet-tools as your \"normal\" user (who should only be in the group 'gnunet'). ********************************************" >&6;} gnunet-0.10.1/src/0000755000175000017500000000000012320755627010672 500000000000000gnunet-0.10.1/src/conversation/0000755000175000017500000000000012320755627013404 500000000000000gnunet-0.10.1/src/conversation/conversation.conf.in0000644000175000017500000000042012267431203017275 00000000000000[conversation] AUTOSTART = @AUTOSTART@ BINARY = gnunet-service-conversation UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-conversation.sock HOSTNAME = localhost @UNIXONLY@ PORT = 2106 ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES gnunet-0.10.1/src/conversation/conversation_api_call.c0000644000175000017500000004346712261236532020035 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/conversation_api_call.c * @brief call API to the conversation service * @author Simon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_conversation_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gns_service.h" #include "conversation.h" /** * Possible states of the phone. */ enum CallState { /** * We still need to lookup the callee. */ CS_LOOKUP = 0, /** * The call is ringing. */ CS_RINGING, /** * The call is in an active conversation. */ CS_ACTIVE, /** * The call is in termination. */ CS_SHUTDOWN, /** * The call was suspended by the caller. */ CS_SUSPENDED_CALLER, /** * The call was suspended by the callee. */ CS_SUSPENDED_CALLEE, /** * The call was suspended by both caller and callee. */ CS_SUSPENDED_BOTH }; /** * Handle for an outgoing call. */ struct GNUNET_CONVERSATION_Call { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to talk with CONVERSATION service. */ struct GNUNET_CLIENT_Connection *client; /** * Our caller identity. */ struct GNUNET_IDENTITY_Ego *caller_id; /** * Target callee as a GNS address/name. */ char *callee; /** * Our speaker. */ struct GNUNET_SPEAKER_Handle *speaker; /** * Our microphone. */ struct GNUNET_MICROPHONE_Handle *mic; /** * Function to call with events. */ GNUNET_CONVERSATION_CallEventHandler event_handler; /** * Closure for @e event_handler */ void *event_handler_cls; /** * Handle for transmitting to the CONVERSATION service. */ struct GNUNET_MQ_Handle *mq; /** * Connection to GNS (can be NULL). */ struct GNUNET_GNS_Handle *gns; /** * Active GNS lookup (or NULL). */ struct GNUNET_GNS_LookupRequest *gns_lookup; /** * Target phone record, only valid after the lookup is done. */ struct GNUNET_CONVERSATION_PhoneRecord phone_record; /** * State machine for the call. */ enum CallState state; }; /** * The call got disconnected, reconnect to the service. * * @param call call to reconnect */ static void reconnect_call (struct GNUNET_CONVERSATION_Call *call); /** * Process recorded audio data. * * @param cls closure with the `struct GNUNET_CONVERSATION_Call` * @param data_size number of bytes in @a data * @param data audio data to play */ static void transmit_call_audio (void *cls, size_t data_size, const void *data) { struct GNUNET_CONVERSATION_Call *call = cls; struct GNUNET_MQ_Envelope *e; struct ClientAudioMessage *am; GNUNET_assert (CS_ACTIVE == call->state); e = GNUNET_MQ_msg_extra (am, data_size, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO); memcpy (&am[1], data, data_size); GNUNET_MQ_send (call->mq, e); } /** * We received a `struct ClientPhoneSuspendMessage` * * @param cls the `struct GNUNET_CONVERSATION_Call` * @param msg the message */ static void handle_call_suspend (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Call *call = cls; switch (call->state) { case CS_LOOKUP: GNUNET_break (0); reconnect_call (call); break; case CS_RINGING: GNUNET_break_op (0); reconnect_call (call); break; case CS_SUSPENDED_CALLER: call->state = CS_SUSPENDED_BOTH; call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_SUSPENDED); break; case CS_SUSPENDED_CALLEE: case CS_SUSPENDED_BOTH: GNUNET_break_op (0); break; case CS_ACTIVE: call->state = CS_SUSPENDED_CALLEE; call->speaker->disable_speaker (call->speaker->cls); call->mic->disable_microphone (call->mic->cls); call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_SUSPENDED); break; case CS_SHUTDOWN: GNUNET_CONVERSATION_call_stop (call); break; } } /** * We received a `struct ClientPhoneResumeMessage` * * @param cls the `struct GNUNET_CONVERSATION_Call` * @param msg the message */ static void handle_call_resume (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Call *call = cls; switch (call->state) { case CS_LOOKUP: GNUNET_break (0); reconnect_call (call); break; case CS_RINGING: GNUNET_break_op (0); reconnect_call (call); break; case CS_SUSPENDED_CALLER: GNUNET_break_op (0); break; case CS_SUSPENDED_CALLEE: call->state = CS_ACTIVE; call->speaker->enable_speaker (call->speaker->cls); call->mic->enable_microphone (call->mic->cls, &transmit_call_audio, call); call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_RESUMED); break; case CS_SUSPENDED_BOTH: call->state = CS_SUSPENDED_CALLER; call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_RESUMED); break; case CS_ACTIVE: GNUNET_break_op (0); break; case CS_SHUTDOWN: GNUNET_CONVERSATION_call_stop (call); break; } } /** * We received a `struct ClientPhonePickedupMessage` * * @param cls the `struct GNUNET_CONVERSATION_Call` * @param msg the message */ static void handle_call_picked_up (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Call *call = cls; switch (call->state) { case CS_LOOKUP: GNUNET_break (0); reconnect_call (call); break; case CS_RINGING: call->state = CS_ACTIVE; call->speaker->enable_speaker (call->speaker->cls); call->mic->enable_microphone (call->mic->cls, &transmit_call_audio, call); call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_PICKED_UP); break; case CS_SUSPENDED_CALLER: case CS_SUSPENDED_CALLEE: case CS_SUSPENDED_BOTH: case CS_ACTIVE: GNUNET_break (0); reconnect_call (call); break; case CS_SHUTDOWN: GNUNET_CONVERSATION_call_stop (call); break; } } /** * We received a `struct ClientPhoneHangupMessage` * * @param cls the `struct GNUNET_CONVERSATION_Call` * @param msg the message */ static void handle_call_hangup (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Call *call = cls; GNUNET_CONVERSATION_CallEventHandler eh; void *eh_cls; switch (call->state) { case CS_LOOKUP: GNUNET_break (0); reconnect_call (call); break; case CS_RINGING: case CS_SUSPENDED_CALLER: case CS_SUSPENDED_CALLEE: case CS_SUSPENDED_BOTH: case CS_ACTIVE: eh = call->event_handler; eh_cls = call->event_handler_cls; GNUNET_CONVERSATION_call_stop (call); eh (eh_cls, GNUNET_CONVERSATION_EC_CALL_HUNG_UP); return; case CS_SHUTDOWN: GNUNET_CONVERSATION_call_stop (call); break; } } /** * We received a `struct ClientAudioMessage` * * @param cls the `struct GNUNET_CONVERSATION_Call` * @param msg the message */ static void handle_call_audio_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Call *call = cls; const struct ClientAudioMessage *am; am = (const struct ClientAudioMessage *) msg; switch (call->state) { case CS_LOOKUP: GNUNET_break (0); reconnect_call (call); break; case CS_RINGING: GNUNET_break (0); reconnect_call (call); break; case CS_SUSPENDED_CALLER: /* can happen: we suspended, other peer did not yet learn about this. */ break; case CS_SUSPENDED_CALLEE: case CS_SUSPENDED_BOTH: /* can (rarely) also happen: other peer suspended, but mesh might have had delayed data on the unreliable channel */ break; case CS_ACTIVE: call->speaker->play (call->speaker->cls, ntohs (msg->size) - sizeof (struct ClientAudioMessage), &am[1]); break; case CS_SHUTDOWN: GNUNET_CONVERSATION_call_stop (call); break; } } /** * Iterator called on obtained result for a GNS lookup. * * @param cls closure with the `struct GNUNET_CONVERSATION_Call` * @param rd_count number of records in @a rd * @param rd the records in reply */ static void handle_gns_response (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_CONVERSATION_Call *call = cls; uint32_t i; struct GNUNET_MQ_Envelope *e; struct ClientCallMessage *ccm; GNUNET_break (NULL != call->gns_lookup); GNUNET_break (CS_LOOKUP == call->state); call->gns_lookup = NULL; for (i=0;iphone_record, rd[i].data, rd[i].data_size); e = GNUNET_MQ_msg (ccm, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL); ccm->line = call->phone_record.line; ccm->target = call->phone_record.peer; ccm->caller_id = *GNUNET_IDENTITY_ego_get_private_key (call->caller_id); GNUNET_MQ_send (call->mq, e); call->state = CS_RINGING; call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_RINGING); return; } } /* not found */ call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_GNS_FAIL); GNUNET_CONVERSATION_call_stop (call); } /** * We encountered an error talking with the conversation service. * * @param cls the `struct GNUNET_CONVERSATION_Call` * @param error details about the error */ static void call_error_handler (void *cls, enum GNUNET_MQ_Error error) { struct GNUNET_CONVERSATION_Call *call = cls; if (CS_SHUTDOWN == call->state) { GNUNET_CONVERSATION_call_stop (call); return; } GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Connection to conversation service lost, trying to reconnect\n")); reconnect_call (call); } /** * The call got disconnected, reconnect to the service. * * @param call call to reconnect */ static void reconnect_call (struct GNUNET_CONVERSATION_Call *call) { static struct GNUNET_MQ_MessageHandler handlers[] = { { &handle_call_suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND, sizeof (struct ClientPhoneSuspendMessage) }, { &handle_call_resume, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME, sizeof (struct ClientPhoneResumeMessage) }, { &handle_call_picked_up, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP, sizeof (struct ClientPhonePickedupMessage) }, { &handle_call_hangup, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP, sizeof (struct ClientPhoneHangupMessage) }, { &handle_call_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO, 0 }, { NULL, 0, 0 } }; struct GNUNET_CRYPTO_EcdsaPublicKey my_zone; if (CS_ACTIVE == call->state) { call->speaker->disable_speaker (call->speaker->cls); call->mic->disable_microphone (call->mic->cls); } if (NULL != call->mq) { GNUNET_MQ_destroy (call->mq); call->mq = NULL; } if (NULL != call->client) { GNUNET_CLIENT_disconnect (call->client); call->client = NULL; } call->state = CS_SHUTDOWN; call->client = GNUNET_CLIENT_connect ("conversation", call->cfg); if (NULL == call->client) { call->event_handler (call->event_handler_cls, GNUNET_CONVERSATION_EC_CALL_ERROR); return; } call->mq = GNUNET_MQ_queue_for_connection_client (call->client, handlers, &call_error_handler, call); call->state = CS_LOOKUP; GNUNET_IDENTITY_ego_get_public_key (call->caller_id, &my_zone); call->gns_lookup = GNUNET_GNS_lookup (call->gns, call->callee, &my_zone, GNUNET_GNSRECORD_TYPE_PHONE, GNUNET_NO, NULL /* FIXME: add shortening support */, &handle_gns_response, call); GNUNET_assert (NULL != call->gns_lookup); } /** * Call the phone of another user. * * @param cfg configuration to use, specifies our phone service * @param caller_id identity of the caller * @param callee GNS name of the callee (used to locate the callee's record) * @param speaker speaker to use (will be used automatically immediately once the * #GNUNET_CONVERSATION_EC_CALL_PICKED_UP event is generated); we will NOT generate * a ring tone on the speaker * @param mic microphone to use (will be used automatically immediately once the * #GNUNET_CONVERSATION_EC_CALL_PICKED_UP event is generated) * @param event_handler how to notify the owner of the phone about events * @param event_handler_cls closure for @a event_handler */ struct GNUNET_CONVERSATION_Call * GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_IDENTITY_Ego *caller_id, const char *callee, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic, GNUNET_CONVERSATION_CallEventHandler event_handler, void *event_handler_cls) { struct GNUNET_CONVERSATION_Call *call; call = GNUNET_new (struct GNUNET_CONVERSATION_Call); call->cfg = cfg; call->caller_id = caller_id; call->callee = GNUNET_strdup (callee); call->speaker = speaker; call->mic = mic; call->event_handler = event_handler; call->event_handler_cls = event_handler_cls; call->gns = GNUNET_GNS_connect (cfg); reconnect_call (call); if ( (NULL == call->client) || (NULL == call->gns) ) { GNUNET_CONVERSATION_call_stop (call); return NULL; } return call; } /** * Terminate a call. The call may be ringing or ready at this time. * * @param call call to terminate */ void GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call) { if ( (NULL != call->speaker) && (CS_ACTIVE == call->state) ) call->speaker->disable_speaker (call->speaker->cls); if ( (NULL != call->mic) && (CS_ACTIVE == call->state) ) call->mic->disable_microphone (call->mic->cls); if (CS_SHUTDOWN != call->state) { call->state = CS_SHUTDOWN; } if (NULL != call->mq) { GNUNET_MQ_destroy (call->mq); call->mq = NULL; } if (NULL != call->client) { GNUNET_CLIENT_disconnect (call->client); call->client = NULL; } if (NULL != call->gns_lookup) { GNUNET_GNS_lookup_cancel (call->gns_lookup); call->gns_lookup = NULL; } if (NULL != call->gns) { GNUNET_GNS_disconnect (call->gns); call->gns = NULL; } GNUNET_free (call->callee); GNUNET_free (call); } /** * Pause a call. Temporarily suspends the use of speaker and * microphone. * * @param call call to pause */ void GNUNET_CONVERSATION_call_suspend (struct GNUNET_CONVERSATION_Call *call) { struct GNUNET_MQ_Envelope *e; struct ClientPhoneSuspendMessage *suspend; GNUNET_assert ( (CS_SUSPENDED_CALLEE == call->state) || (CS_ACTIVE == call->state) ); if (CS_ACTIVE == call->state) { call->speaker->disable_speaker (call->speaker->cls); call->mic->disable_microphone (call->mic->cls); } call->speaker = NULL; call->mic = NULL; e = GNUNET_MQ_msg (suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); GNUNET_MQ_send (call->mq, e); if (CS_SUSPENDED_CALLER == call->state) call->state = CS_SUSPENDED_BOTH; else call->state = CS_SUSPENDED_CALLER; } /** * Resumes a call after #GNUNET_CONVERSATION_call_suspend. * * @param call call to resume * @param speaker speaker to use * a ring tone on the speaker * @param mic microphone to use */ void GNUNET_CONVERSATION_call_resume (struct GNUNET_CONVERSATION_Call *call, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic) { struct GNUNET_MQ_Envelope *e; struct ClientPhoneResumeMessage *resume; GNUNET_assert ( (CS_SUSPENDED_CALLER == call->state) || (CS_SUSPENDED_BOTH == call->state) ); e = GNUNET_MQ_msg (resume, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME); GNUNET_MQ_send (call->mq, e); call->speaker = speaker; call->mic = mic; if (CS_SUSPENDED_CALLER == call->state) { call->state = CS_ACTIVE; call->speaker->enable_speaker (call->speaker->cls); call->mic->enable_microphone (call->mic->cls, &transmit_call_audio, call); } else { call->state = CS_SUSPENDED_CALLEE; } } /* end of conversation_api_call.c */ gnunet-0.10.1/src/conversation/gnunet-helper-audio-playback-gst.c0000644000175000017500000002201712320530515021710 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/gnunet-helper-audio-playback-gst.c * @brief program to playback audio data to the speaker (GStreamer version) * @author LRN */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "conversation.h" #include "gnunet_constants.h" #include "gnunet_core_service.h" #include #include #include #include #define DEBUG_READ_PURE_OGG 1 /** * How much data to read in one go */ #define MAXLINE 4096 /** * Max number of microseconds to buffer in audiosink. * Default is 200000 */ #define BUFFER_TIME 1000 /** * Min number of microseconds to buffer in audiosink. * Default is 10000 */ #define LATENCY_TIME 1000 /** * Tokenizer for the data we get from stdin */ struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst; /** * Main pipeline. */ static GstElement *pipeline; /** * Appsrc instance into which we write data for the pipeline. */ static GstElement *source; static GstElement *demuxer; static GstElement *decoder; static GstElement *conv; static GstElement *resampler; static GstElement *sink; /** * Set to 1 to break the reading loop */ static int abort_read; static void sink_child_added (GstChildProxy *child_proxy, GObject *object, gchar *name, gpointer user_data) { if (GST_IS_AUDIO_BASE_SRC (object)) g_object_set (object, "buffer-time", (gint64) BUFFER_TIME, "latency-time", (gint64) LATENCY_TIME, NULL); } static void ogg_pad_added (GstElement *element, GstPad *pad, gpointer data) { GstPad *sinkpad; GstElement *decoder = (GstElement *) data; /* We can now link this pad with the opus-decoder sink pad */ sinkpad = gst_element_get_static_pad (decoder, "sink"); gst_pad_link (pad, sinkpad); gst_element_link_many (decoder, conv, resampler, sink, NULL); gst_object_unref (sinkpad); } static void quit () { if (NULL != source) gst_app_src_end_of_stream (GST_APP_SRC (source)); if (NULL != pipeline) gst_element_set_state (pipeline, GST_STATE_NULL); abort_read = 1; } static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bus message\n"); switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "End of stream\n"); quit (); break; case GST_MESSAGE_ERROR: { gchar *debug; GError *error; gst_message_parse_error (msg, &error, &debug); g_free (debug); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error: %s\n", error->message); g_error_free (error); quit (); break; } default: break; } return TRUE; } static void signalhandler (int s) { quit (); } static int feed_buffer_to_gst (const char *audio, size_t b_len) { GstBuffer *b; gchar *bufspace; GstFlowReturn flow; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Feeding %u bytes to GStreamer\n", (unsigned int) b_len); bufspace = g_memdup (audio, b_len); b = gst_buffer_new_wrapped (bufspace, b_len); if (NULL == b) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to wrap a buffer\n"); g_free (bufspace); return GNUNET_SYSERR; } flow = gst_app_src_push_buffer (GST_APP_SRC (source), b); /* They all return GNUNET_OK, because currently player stops when * data stops coming. This might need to be changed for the player * to also stop when pipeline breaks. */ switch (flow) { case GST_FLOW_OK: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fed %u bytes to the pipeline\n", (unsigned int) b_len); break; case GST_FLOW_FLUSHING: /* buffer was dropped, because pipeline state is not PAUSED or PLAYING */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Dropped a buffer\n"); break; case GST_FLOW_EOS: /* end of stream */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "EOS\n"); break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unexpected push result\n"); break; } return GNUNET_OK; } /** * Message callback */ static int stdin_receiver (void *cls, void *client, const struct GNUNET_MessageHeader *msg) { struct AudioMessage *audio; size_t b_len; switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO: audio = (struct AudioMessage *) msg; b_len = ntohs (audio->header.size) - sizeof (struct AudioMessage); feed_buffer_to_gst ((const char *) &audio[1], b_len); break; default: break; } return GNUNET_OK; } int main (int argc, char **argv) { GstBus *bus; guint bus_watch_id; uint64_t toff; typedef void (*SignalHandlerPointer) (int); SignalHandlerPointer inthandler, termhandler; #ifdef DEBUG_READ_PURE_OGG int read_pure_ogg = getenv ("GNUNET_READ_PURE_OGG") ? 1 : 0; #endif inthandler = signal (SIGINT, signalhandler); termhandler = signal (SIGTERM, signalhandler); #ifdef WINDOWS setmode (0, _O_BINARY); #endif /* Initialisation */ gst_init (&argc, &argv); GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("gnunet-helper-audio-playback", "WARNING", NULL)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audio sink starts\n"); stdin_mst = GNUNET_SERVER_mst_create (&stdin_receiver, NULL); /* Create gstreamer elements */ pipeline = gst_pipeline_new ("audio-player"); source = gst_element_factory_make ("appsrc", "audio-input"); demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer"); decoder = gst_element_factory_make ("opusdec", "opus-decoder"); conv = gst_element_factory_make ("audioconvert", "converter"); resampler= gst_element_factory_make ("audioresample", "resampler"); sink = gst_element_factory_make ("autoaudiosink", "audiosink"); if (!pipeline || !source || !conv || !resampler || !decoder || !demuxer || !sink) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "One element could not be created. Exiting.\n"); return -1; } g_signal_connect (sink, "child-added", G_CALLBACK (sink_child_added), NULL); g_signal_connect (demuxer, "pad-added", G_CALLBACK (ogg_pad_added), decoder); /* Keep a reference to it, we operate on it */ gst_object_ref (GST_OBJECT (source)); /* Set up the pipeline */ /* we feed appsrc as fast as possible, it just blocks when it's full */ g_object_set (G_OBJECT (source), /* "format", GST_FORMAT_TIME,*/ "block", TRUE, "is-live", TRUE, NULL); g_object_set (G_OBJECT (decoder), /* "plc", FALSE,*/ /* "apply-gain", TRUE,*/ "use-inband-fec", TRUE, NULL); /* we add a message handler */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus_watch_id = gst_bus_add_watch (bus, bus_call, pipeline); gst_object_unref (bus); /* we add all elements into the pipeline */ /* audio-input | ogg-demuxer | opus-decoder | converter | resampler | audiosink */ gst_bin_add_many (GST_BIN (pipeline), source, demuxer, decoder, conv, resampler, sink, NULL); /* we link the elements together */ gst_element_link_many (source, demuxer, NULL); /* Set the pipeline to "playing" state*/ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Now playing\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running...\n"); /* Iterate */ toff = 0; while (!abort_read) { char readbuf[MAXLINE]; int ret; ret = read (0, readbuf, sizeof (readbuf)); if (0 > ret) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Read error from STDIN: %d %s\n"), ret, strerror (errno)); break; } toff += ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d bytes of audio data (total: %llu)\n", (int) ret, toff); if (0 == ret) break; #ifdef DEBUG_READ_PURE_OGG if (read_pure_ogg) { feed_buffer_to_gst (readbuf, ret); } else #endif GNUNET_SERVER_mst_receive (stdin_mst, NULL, readbuf, ret, GNUNET_NO, GNUNET_NO); } GNUNET_SERVER_mst_destroy (stdin_mst); signal (SIGINT, inthandler); signal (SIGINT, termhandler); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Returned, stopping playback\n"); quit (); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Deleting pipeline\n"); gst_object_unref (GST_OBJECT (source)); source = NULL; gst_object_unref (GST_OBJECT (pipeline)); pipeline = NULL; g_source_remove (bus_watch_id); return 0; } gnunet-0.10.1/src/conversation/test_conversation_api_twocalls.c0000644000175000017500000003551112255773026022007 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/test_conversation_api_twocalls.c * @brief testcase for conversation_api.c * * This test performs the operations of TWO calls made to a phone * where the phone user picks up one, suspends it, picks up the * second one; eventually, the initiator hangs up, the callee * resumes the first call, and then the initiator hangs up the * second call. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_conversation_service.h" #include "gnunet_identity_service.h" #include "gnunet_namestore_service.h" #define FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 25) #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) #define LOG_DEBUG(...) \ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_IDENTITY_Handle *id; static struct GNUNET_IDENTITY_Operation *op; static struct GNUNET_CONVERSATION_Phone *phone; static struct GNUNET_NAMESTORE_Handle *ns; static struct GNUNET_CONVERSATION_Call *call1; static struct GNUNET_CONVERSATION_Call *call2; static struct GNUNET_NAMESTORE_QueueEntry *qe; static struct GNUNET_CONVERSATION_Caller *active_caller1; static struct GNUNET_CONVERSATION_Caller *active_caller2; static char *gns_name; static char *gns_caller_id; static GNUNET_MICROPHONE_RecordedDataCallback phone_rdc; static void *phone_rdc_cls; static GNUNET_SCHEDULER_TaskIdentifier phone_task; /** * Variable for recognizing caller1 */ static const char *caller1 = "caller1"; /** * Variable for recognizing caller2 */ static const char *caller2 = "caller2"; /** * Variable for recognizing callee */ static const char *phone0 = "phone"; #define CALLER1 &caller1 #define CALLER2 &caller2 #define PHONE0 &phone0 #define CLS_STR(caller) (*((char **)caller)) /** * Did caller1 call finish successfully */ static int call1_finished; /** * Did caller2 call finish successfully */ static int call2_finished; struct MicContext { GNUNET_MICROPHONE_RecordedDataCallback rdc; void *rdc_cls; GNUNET_SCHEDULER_TaskIdentifier call_task; }; static struct MicContext call1_mic_ctx; static struct MicContext call2_mic_ctx; //static struct MicContext phone_mic_ctx; static void phone_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { char buf[32]; GNUNET_assert (NULL != phone_rdc); GNUNET_snprintf (buf, sizeof (buf), "phone"); phone_rdc (phone_rdc_cls, strlen (buf) + 1, buf); phone_task = GNUNET_SCHEDULER_add_delayed (FREQ, &phone_send, NULL); } static void call_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MicContext *mc = cls; char buf[32]; GNUNET_assert (NULL != mc->rdc); GNUNET_snprintf (buf, sizeof (buf), "call"); mc->rdc (mc->rdc_cls, strlen (buf) + 1, buf); mc->call_task = GNUNET_SCHEDULER_add_delayed (FREQ, &call_send, mc); } static int enable_speaker (void *cls) { const char *origin = CLS_STR (cls); LOG_DEBUG ("Speaker %s enabled\n", origin); return GNUNET_OK; } static void disable_speaker (void *cls) { const char *origin = CLS_STR (cls); LOG_DEBUG ("Speaker %s disabled\n", origin); } static void play (void *cls, size_t data_size, const void *data) { static unsigned int phone_i; static unsigned int call_i; if (0 == strncmp ("call", data, data_size)) call_i++; else if (0 == strncmp ("phone", data, data_size)) phone_i++; else { LOG_DEBUG ("Received unexpected data %.*s\n", (int) data_size, (const char *) data); } if ( (20 < call_i) && (20 < phone_i) && (CALLER2 == cls) ) { /* time to hang up ... */ GNUNET_CONVERSATION_call_stop (call2); call2 = NULL; /* reset counters */ call_i = 0; phone_i = 0; call2_finished = GNUNET_YES; } if ( (20 < call_i) && (20 < phone_i) && (CALLER1 == cls) ) { /* time to hang up ... */ GNUNET_CONVERSATION_call_stop (call1); call1 = NULL; call_i = 0; phone_i = 0; call1_finished = GNUNET_YES; } } static void destroy_speaker (void *cls) { const char *origin = CLS_STR (cls); LOG_DEBUG ("Speaker %s destroyed\n", origin); } static struct GNUNET_SPEAKER_Handle call1_speaker = { &enable_speaker, &play, &disable_speaker, &destroy_speaker, CALLER1 }; static struct GNUNET_SPEAKER_Handle call2_speaker = { &enable_speaker, &play, &disable_speaker, &destroy_speaker, CALLER2 }; static struct GNUNET_SPEAKER_Handle phone_speaker = { &enable_speaker, &play, &disable_speaker, &destroy_speaker, PHONE0 }; static int enable_mic (void *cls, GNUNET_MICROPHONE_RecordedDataCallback rdc, void *rdc_cls) { const char *origin = CLS_STR (cls); struct MicContext *mc; LOG_DEBUG ("Mic %s enabled\n", origin); if (PHONE0 == cls) { phone_rdc = rdc; phone_rdc_cls = rdc_cls; GNUNET_break (GNUNET_SCHEDULER_NO_TASK == phone_task); phone_task = GNUNET_SCHEDULER_add_now (&phone_send, NULL); return GNUNET_OK; } mc = (CALLER1 == cls) ? &call1_mic_ctx : &call2_mic_ctx; mc->rdc = rdc; mc->rdc_cls = rdc_cls; GNUNET_break (GNUNET_SCHEDULER_NO_TASK == mc->call_task); mc->call_task = GNUNET_SCHEDULER_add_now (&call_send, mc); return GNUNET_OK; } static void disable_mic (void *cls) { const char *origin = CLS_STR (cls); struct MicContext *mc; LOG_DEBUG ("Mic %s disabled\n", origin); if (PHONE0 == cls) { phone_rdc = NULL; phone_rdc_cls = NULL; GNUNET_SCHEDULER_cancel (phone_task); phone_task = GNUNET_SCHEDULER_NO_TASK; return; } mc = (CALLER1 == cls) ? &call1_mic_ctx : &call2_mic_ctx; mc->rdc = NULL; mc->rdc_cls = NULL; GNUNET_SCHEDULER_cancel (mc->call_task); mc->call_task = GNUNET_SCHEDULER_NO_TASK; } static void destroy_mic (void *cls) { const char *origin = CLS_STR (cls); LOG_DEBUG ("Mic %s destroyed\n", origin); } static struct GNUNET_MICROPHONE_Handle call1_mic = { &enable_mic, &disable_mic, &destroy_mic, CALLER1 }; static struct GNUNET_MICROPHONE_Handle call2_mic = { &enable_mic, &disable_mic, &destroy_mic, CALLER2 }; static struct GNUNET_MICROPHONE_Handle phone_mic = { &enable_mic, &disable_mic, &destroy_mic, PHONE0 }; /** * Signature of the main function of a task. * * @param cls closure * @param tc context information (why was this task triggered now) */ static void end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SCHEDULER_shutdown (); if (NULL != op) { GNUNET_IDENTITY_cancel (op); op = NULL; } if (NULL != call1) { GNUNET_CONVERSATION_call_stop (call1); call1 = NULL; } if (NULL != call2) { GNUNET_CONVERSATION_call_stop (call2); call2 = NULL; } if (NULL != phone) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from PHONE service.\n"); GNUNET_CONVERSATION_phone_destroy (phone); phone = NULL; } if (NULL != id) { GNUNET_IDENTITY_disconnect (id); id = NULL; } if (NULL != qe) { GNUNET_NAMESTORE_cancel (qe); qe = NULL; } if (NULL != ns) { GNUNET_NAMESTORE_disconnect (ns); ns = NULL; } } static void caller_event_handler (void *cls, enum GNUNET_CONVERSATION_CallerEventCode code) { switch (code) { case GNUNET_CONVERSATION_EC_CALLER_SUSPEND: case GNUNET_CONVERSATION_EC_CALLER_RESUME: LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected caller code: %d\n", code); break; } } static void phone_event_handler (void *cls, enum GNUNET_CONVERSATION_PhoneEventCode code, struct GNUNET_CONVERSATION_Caller *caller, const char *caller_id) { const char *cid; GNUNET_break (0 == strcmp (caller_id, gns_caller_id)); switch (code) { case GNUNET_CONVERSATION_EC_PHONE_RING: if (NULL == active_caller1) { active_caller1 = caller; cid = "caller1"; GNUNET_CONVERSATION_caller_pick_up (caller, &caller_event_handler, (void *) cid, &phone_speaker, &phone_mic); } else { GNUNET_CONVERSATION_caller_suspend (active_caller1); active_caller2 = caller; cid = "caller2"; GNUNET_CONVERSATION_caller_pick_up (caller, &caller_event_handler, (void *) cid, &phone_speaker, &phone_mic); } break; case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP: if (caller == active_caller2) { active_caller2 = NULL; GNUNET_CONVERSATION_caller_resume (active_caller1, &phone_speaker, &phone_mic); } else if (caller == active_caller1) { active_caller1 = NULL; GNUNET_break (NULL == active_caller2); GNUNET_SCHEDULER_shutdown (); } break; default: LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected phone code: %d\n", code); break; } } static void call_event_handler (void *cls, enum GNUNET_CONVERSATION_CallEventCode code) { const char *cid = cls; switch (code) { case GNUNET_CONVERSATION_EC_CALL_RINGING: break; case GNUNET_CONVERSATION_EC_CALL_PICKED_UP: LOG_DEBUG ("Call %s picked\n", cid); break; case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL: LOG_DEBUG ("Call %s GNS lookup failed \n", cid); case GNUNET_CONVERSATION_EC_CALL_HUNG_UP: LOG_DEBUG ("Call %s hungup\n", cid); if (0 == strcmp (cid, "call1")) call1 = NULL; else call2 = NULL; break; case GNUNET_CONVERSATION_EC_CALL_SUSPENDED: LOG_DEBUG ("Call %s suspended\n", cid); break; case GNUNET_CONVERSATION_EC_CALL_RESUMED: LOG_DEBUG ("Call %s resumed\n", cid); break; case GNUNET_CONVERSATION_EC_CALL_ERROR: GNUNET_break (0); break; } } static void caller_ego_create_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); } static void namestore_put_cont (void *cls, int32_t success, const char *emsg) { qe = NULL; GNUNET_assert (GNUNET_YES == success); GNUNET_assert (NULL == emsg); GNUNET_assert (NULL == op); op = GNUNET_IDENTITY_create (id, "caller-ego", &caller_ego_create_cont, NULL); } static void identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { struct GNUNET_GNSRECORD_Data rd; struct GNUNET_CRYPTO_EcdsaPublicKey pub; if (NULL == name) return; if (NULL == ego) return; if (0 == strcmp (name, "phone-ego")) { GNUNET_IDENTITY_ego_get_public_key (ego, &pub); GNUNET_asprintf (&gns_name, "phone.%s", GNUNET_GNSRECORD_pkey_to_zkey (&pub)); phone = GNUNET_CONVERSATION_phone_create (cfg, ego, &phone_event_handler, NULL); GNUNET_assert (NULL != phone); memset (&rd, 0, sizeof (rd)); GNUNET_CONVERSATION_phone_get_record (phone, &rd); GNUNET_assert (rd.record_type == GNUNET_GNSRECORD_TYPE_PHONE); rd.expiration_time = UINT64_MAX; qe = GNUNET_NAMESTORE_records_store (ns, GNUNET_IDENTITY_ego_get_private_key (ego), "phone" /* GNS label */, 1, &rd, &namestore_put_cont, NULL); return; } if (0 == strcmp (name, "caller-ego")) { GNUNET_IDENTITY_ego_get_public_key (ego, &pub); GNUNET_asprintf (&gns_caller_id, "%s", GNUNET_GNSRECORD_pkey_to_zkey (&pub)); call1 = GNUNET_CONVERSATION_call_start (cfg, ego, gns_name, &call1_speaker, &call1_mic, &call_event_handler, (void *) "call1"); call2 = GNUNET_CONVERSATION_call_start (cfg, ego, gns_name, &call2_speaker, &call2_mic, &call_event_handler, (void *) "call2"); return; } } static void phone_ego_create_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_TESTING_Peer *peer) { cfg = c; GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test, NULL); id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); op = GNUNET_IDENTITY_create (id, "phone-ego", &phone_ego_create_cont, NULL); ns = GNUNET_NAMESTORE_connect (cfg); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test_conversation_api_twocalls", "test_conversation.conf", &run, NULL)) return 1; if (call1_finished && call2_finished) return 0; return 1; } /* end of test_conversation_api_twocalls.c */ gnunet-0.10.1/src/conversation/gnunet-helper-audio-record.c0000644000175000017500000004443112267431203020615 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/gnunet-helper-audio-record.c * @brief program to record audio data from the microphone * @author Siomon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "conversation.h" #include "gnunet_constants.h" #include "gnunet_core_service.h" #include #include #include #include #include #include #include #define DEBUG_RECORD_PURE_OGG 1 /** * Sampling rate */ #define SAMPLING_RATE 48000 /** * How many ms of audio to buffer before encoding them. * Possible values: * 60, 40, 20, 10, 5, 2.5 */ #define FRAME_SIZE_MS 40 /** * How many samples to buffer before encoding them. */ #define FRAME_SIZE (SAMPLING_RATE / 1000 * FRAME_SIZE_MS) /** * Pages are commited when their size goes over this value. * Note that in practice we flush pages VERY often (every frame), * which means that pages NEVER really get to be this big. * With one-packet-per-page, pages are roughly 100-300 bytes each. * * This value is chosen to make MAX_PAYLOAD_BYTES=1024 fit * into a single page. */ #define PAGE_WATERLINE 800 /** * Maximum length of opus payload */ #define MAX_PAYLOAD_BYTES 1024 /** * Number of channels */ #define CHANNELS 1 /** * Configures the encoder's expected packet loss percentage. * * Higher values will trigger progressively more loss resistant behavior * in the encoder at the expense of quality at a given bitrate * in the lossless case, but greater quality under loss. */ #define CONV_OPUS_PACKET_LOSS_PERCENTAGE 1 /** * Configures the encoder's computational complexity. * * The supported range is 0-10 inclusive with 10 representing * the highest complexity. */ #define CONV_OPUS_ENCODING_COMPLEXITY 10 /** * Configures the encoder's use of inband forward error correction (FEC). * * Note: This is only applicable to the LPC layer. */ #define CONV_OPUS_INBAND_FEC 1 /** * Configures the type of signal being encoded. * * This is a hint which helps the encoder's mode selection. * * Possible values: * OPUS_AUTO - (default) Encoder detects the type automatically. * OPUS_SIGNAL_VOICE - Bias thresholds towards choosing LPC or Hybrid modes. * OPUS_SIGNAL_MUSIC - Bias thresholds towards choosing MDCT modes. */ #define CONV_OPUS_SIGNAL OPUS_AUTO /** * Coding mode. * * Possible values: * OPUS_APPLICATION_VOIP - gives best quality at a given bitrate for voice * signals. It enhances the input signal by high-pass filtering and * emphasizing formants and harmonics. Optionally it includes in-band forward * error correction to protect against packet loss. Use this mode for typical * VoIP applications. Because of the enhancement, even at high bitrates * the output may sound different from the input. * OPUS_APPLICATION_AUDIO - gives best quality at a given bitrate for most * non-voice signals like music. Use this mode for music and mixed * (music/voice) content, broadcast, and applications requiring less than * 15 ms of coding delay. * OPUS_APPLICATION_RESTRICTED_LOWDELAY - configures low-delay mode that * disables the speech-optimized mode in exchange for slightly reduced delay. * This mode can only be set on an newly initialized or freshly reset encoder * because it changes the codec delay. */ #define CONV_OPUS_APP_TYPE OPUS_APPLICATION_VOIP /** * Specification for recording. May change in the future to spec negotiation. */ static pa_sample_spec sample_spec = { .format = PA_SAMPLE_FLOAT32LE, .rate = SAMPLING_RATE, .channels = CHANNELS }; GNUNET_NETWORK_STRUCT_BEGIN /* OggOpus spec says the numbers must be in little-endian order */ struct OpusHeadPacket { uint8_t magic[8]; uint8_t version; uint8_t channels; uint16_t preskip GNUNET_PACKED; uint32_t sampling_rate GNUNET_PACKED; uint16_t gain GNUNET_PACKED; uint8_t channel_mapping; }; struct OpusCommentsPacket { uint8_t magic[8]; uint32_t vendor_length; /* followed by: char vendor[vendor_length]; uint32_t string_count; followed by @a string_count pairs of: uint32_t string_length; char string[string_length]; */ }; GNUNET_NETWORK_STRUCT_END /** * Pulseaudio mainloop api */ static pa_mainloop_api *mainloop_api; /** * Pulseaudio mainloop */ static pa_mainloop *m; /** * Pulseaudio context */ static pa_context *context; /** * Pulseaudio recording stream */ static pa_stream *stream_in; /** * Pulseaudio io events */ static pa_io_event *stdio_event; /** * OPUS encoder */ static OpusEncoder *enc; /** * Buffer for encoded data */ static unsigned char *opus_data; /** * PCM data buffer for one OPUS frame */ static float *pcm_buffer; /** * Length of the pcm data needed for one OPUS frame */ static int pcm_length; /** * Audio buffer */ static char *transmit_buffer; /** * Length of audio buffer */ static size_t transmit_buffer_length; /** * Read index for transmit buffer */ static size_t transmit_buffer_index; /** * Audio message skeleton */ static struct AudioMessage *audio_message; /** * Ogg muxer state */ static ogg_stream_state os; /** * Ogg packet id */ static int32_t packet_id; /** * Ogg granule for current packet */ static int64_t enc_granulepos; #ifdef DEBUG_RECORD_PURE_OGG /** * 1 to not to write GNUnet message headers, * producing pure playable ogg output */ static int dump_pure_ogg; #endif /** * Pulseaudio shutdown task */ static void quit (int ret) { mainloop_api->quit (mainloop_api, ret); exit (ret); } static void write_data (const char *ptr, size_t msg_size) { ssize_t ret; size_t off; off = 0; while (off < msg_size) { ret = write (1, &ptr[off], msg_size - off); if (0 >= ret) { if (-1 == ret) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "write"); quit (2); } off += ret; } } static void write_page (ogg_page *og) { static unsigned long long toff; size_t msg_size; msg_size = sizeof (struct AudioMessage) + og->header_len + og->body_len; audio_message->header.size = htons ((uint16_t) msg_size); memcpy (&audio_message[1], og->header, og->header_len); memcpy (((char *) &audio_message[1]) + og->header_len, og->body, og->body_len); toff += msg_size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %u bytes of audio data (total: %llu)\n", (unsigned int) msg_size, toff); #ifdef DEBUG_RECORD_PURE_OGG if (dump_pure_ogg) write_data ((const char *) &audio_message[1], og->header_len + og->body_len); else #endif write_data ((const char *) audio_message, msg_size); } /** * Creates OPUS packets from PCM data */ static void packetizer () { char *nbuf; size_t new_size; int32_t len; ogg_packet op; ogg_page og; while (transmit_buffer_length >= transmit_buffer_index + pcm_length) { memcpy (pcm_buffer, &transmit_buffer[transmit_buffer_index], pcm_length); transmit_buffer_index += pcm_length; len = opus_encode_float (enc, pcm_buffer, FRAME_SIZE, opus_data, MAX_PAYLOAD_BYTES); if (len < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("opus_encode_float() failed: %s. Aborting\n"), opus_strerror (len)); quit (5); } if (len > UINT16_MAX - sizeof (struct AudioMessage)) { GNUNET_break (0); continue; } /* As per OggOpus spec, granule is calculated as if the audio had 48kHz sampling rate. */ enc_granulepos += FRAME_SIZE * 48000 / SAMPLING_RATE; op.packet = (unsigned char *) opus_data; op.bytes = len; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = enc_granulepos; op.packetno = packet_id++; ogg_stream_packetin (&os, &op); while (ogg_stream_flush_fill (&os, &og, PAGE_WATERLINE)) { if (og.header_len + og.body_len > UINT16_MAX - sizeof (struct AudioMessage)) { GNUNET_assert (0); continue; } write_page (&og); } } new_size = transmit_buffer_length - transmit_buffer_index; if (0 != new_size) { nbuf = pa_xmalloc (new_size); memmove (nbuf, &transmit_buffer[transmit_buffer_index], new_size); pa_xfree (transmit_buffer); transmit_buffer = nbuf; } else { pa_xfree (transmit_buffer); transmit_buffer = NULL; } transmit_buffer_index = 0; transmit_buffer_length = new_size; } /** * Pulseaudio callback when new data is available. */ static void stream_read_callback (pa_stream * s, size_t length, void *userdata) { const void *data; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u/%u bytes of PCM data\n", length, pcm_length); GNUNET_assert (NULL != s); GNUNET_assert (length > 0); if (stdio_event) mainloop_api->io_enable (stdio_event, PA_IO_EVENT_OUTPUT); if (pa_stream_peek (s, (const void **) &data, &length) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_peek() failed: %s\n"), pa_strerror (pa_context_errno (context))); quit (1); return; } GNUNET_assert (NULL != data); GNUNET_assert (length > 0); if (NULL != transmit_buffer) { transmit_buffer = pa_xrealloc (transmit_buffer, transmit_buffer_length + length); memcpy (&transmit_buffer[transmit_buffer_length], data, length); transmit_buffer_length += length; } else { transmit_buffer = pa_xmalloc (length); memcpy (transmit_buffer, data, length); transmit_buffer_length = length; transmit_buffer_index = 0; } pa_stream_drop (s); packetizer (); } /** * Exit callback for SIGTERM and SIGINT */ static void exit_signal_callback (pa_mainloop_api * m, pa_signal_event * e, int sig, void *userdata) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Got signal, exiting.\n")); quit (1); } /** * Pulseaudio stream state callback */ static void stream_state_callback (pa_stream * s, void *userdata) { GNUNET_assert (NULL != s); switch (pa_stream_get_state (s)) { case PA_STREAM_CREATING: case PA_STREAM_TERMINATED: break; case PA_STREAM_READY: { const pa_buffer_attr *a; char cmt[PA_CHANNEL_MAP_SNPRINT_MAX]; char sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Stream successfully created.\n")); if (!(a = pa_stream_get_buffer_attr (s))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_get_buffer_attr() failed: %s\n"), pa_strerror (pa_context_errno (pa_stream_get_context (s)))); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Buffer metrics: maxlength=%u, fragsize=%u\n"), a->maxlength, a->fragsize); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Using sample spec '%s', channel map '%s'.\n"), pa_sample_spec_snprint (sst, sizeof (sst), pa_stream_get_sample_spec (s)), pa_channel_map_snprint (cmt, sizeof (cmt), pa_stream_get_channel_map (s))); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connected to device %s (%u, %ssuspended).\n"), pa_stream_get_device_name (s), pa_stream_get_device_index (s), pa_stream_is_suspended (s) ? "" : "not "); } break; case PA_STREAM_FAILED: default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Stream error: %s\n"), pa_strerror (pa_context_errno (pa_stream_get_context (s)))); quit (1); } } /** * Pulseaudio context state callback */ static void context_state_callback (pa_context * c, void *userdata) { GNUNET_assert (c); switch (pa_context_get_state (c)) { case PA_CONTEXT_CONNECTING: case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; case PA_CONTEXT_READY: { int r; pa_buffer_attr na; GNUNET_assert (!stream_in); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connection established.\n")); if (! (stream_in = pa_stream_new (c, "GNUNET_VoIP recorder", &sample_spec, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_new() failed: %s\n"), pa_strerror (pa_context_errno (c))); goto fail; } pa_stream_set_state_callback (stream_in, &stream_state_callback, NULL); pa_stream_set_read_callback (stream_in, &stream_read_callback, NULL); memset (&na, 0, sizeof (na)); na.maxlength = UINT32_MAX; na.fragsize = pcm_length; if ((r = pa_stream_connect_record (stream_in, NULL, &na, PA_STREAM_ADJUST_LATENCY)) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_connect_record() failed: %s\n"), pa_strerror (pa_context_errno (c))); goto fail; } break; } case PA_CONTEXT_TERMINATED: quit (0); break; case PA_CONTEXT_FAILED: default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Connection failure: %s\n"), pa_strerror (pa_context_errno (c))); goto fail; } return; fail: quit (1); } /** * Pulsaudio init */ static void pa_init () { int r; int i; if (!pa_sample_spec_valid (&sample_spec)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong Spec\n")); } /* set up main record loop */ if (!(m = pa_mainloop_new ())) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_new() failed.\n")); } mainloop_api = pa_mainloop_get_api (m); /* listen to signals */ r = pa_signal_init (mainloop_api); GNUNET_assert (r == 0); pa_signal_new (SIGINT, &exit_signal_callback, NULL); pa_signal_new (SIGTERM, &exit_signal_callback, NULL); /* connect to the main pulseaudio context */ if (!(context = pa_context_new (mainloop_api, "GNUNET VoIP"))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_new() failed.\n")); } pa_context_set_state_callback (context, &context_state_callback, NULL); if (pa_context_connect (context, NULL, 0, NULL) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_connect() failed: %s\n"), pa_strerror (pa_context_errno (context))); } if (pa_mainloop_run (m, &i) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_run() failed.\n")); } } /** * OPUS init */ static void opus_init () { int err; pcm_length = FRAME_SIZE * CHANNELS * sizeof (float); pcm_buffer = pa_xmalloc (pcm_length); opus_data = GNUNET_malloc (MAX_PAYLOAD_BYTES); enc = opus_encoder_create (SAMPLING_RATE, CHANNELS, CONV_OPUS_APP_TYPE, &err); opus_encoder_ctl (enc, OPUS_SET_PACKET_LOSS_PERC (CONV_OPUS_PACKET_LOSS_PERCENTAGE)); opus_encoder_ctl (enc, OPUS_SET_COMPLEXITY (CONV_OPUS_ENCODING_COMPLEXITY)); opus_encoder_ctl (enc, OPUS_SET_INBAND_FEC (CONV_OPUS_INBAND_FEC)); opus_encoder_ctl (enc, OPUS_SET_SIGNAL (OPUS_SIGNAL_VOICE)); } static void ogg_init () { int serialno; struct OpusHeadPacket headpacket; struct OpusCommentsPacket *commentspacket; size_t commentspacket_len; serialno = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 0x7FFFFFFF); /*Initialize Ogg stream struct*/ if (-1 == ogg_stream_init (&os, serialno)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("ogg_stream_init() failed.\n")); exit (3); } packet_id = 0; /*Write header*/ { ogg_packet op; ogg_page og; const char *opusver; int vendor_length; memcpy (headpacket.magic, "OpusHead", 8); headpacket.version = 1; headpacket.channels = CHANNELS; headpacket.preskip = GNUNET_htole16 (0); headpacket.sampling_rate = GNUNET_htole32 (SAMPLING_RATE); headpacket.gain = GNUNET_htole16 (0); headpacket.channel_mapping = 0; /* Mono or stereo */ op.packet = (unsigned char *) &headpacket; op.bytes = sizeof (headpacket); op.b_o_s = 1; op.e_o_s = 0; op.granulepos = 0; op.packetno = packet_id++; ogg_stream_packetin (&os, &op); /* Head packet must be alone on its page */ while (ogg_stream_flush (&os, &og)) { write_page (&og); } commentspacket_len = sizeof (*commentspacket); opusver = opus_get_version_string (); vendor_length = strlen (opusver); commentspacket_len += vendor_length; commentspacket_len += sizeof (uint32_t); commentspacket = (struct OpusCommentsPacket *) malloc (commentspacket_len); if (NULL == commentspacket) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to allocate %d bytes for second packet\n"), commentspacket_len); exit (5); } memcpy (commentspacket->magic, "OpusTags", 8); commentspacket->vendor_length = GNUNET_htole32 (vendor_length); memcpy (&commentspacket[1], opusver, vendor_length); *(uint32_t *) &((char *) &commentspacket[1])[vendor_length] = \ GNUNET_htole32 (0); /* no tags */ op.packet = (unsigned char *) commentspacket; op.bytes = commentspacket_len; op.b_o_s = 0; op.e_o_s = 0; op.granulepos = 0; op.packetno = packet_id++; ogg_stream_packetin (&os, &op); /* Comment packets must not be mixed with audio packets on their pages */ while (ogg_stream_flush (&os, &og)) { write_page (&og); } free (commentspacket); } } /** * The main function for the record helper. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *argv[]) { GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("gnunet-helper-audio-record", "WARNING", NULL)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audio source starts\n"); audio_message = GNUNET_malloc (UINT16_MAX); audio_message->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO); #ifdef DEBUG_RECORD_PURE_OGG dump_pure_ogg = getenv ("GNUNET_RECORD_PURE_OGG") ? 1 : 0; #endif ogg_init (); opus_init (); pa_init (); return 0; } gnunet-0.10.1/src/conversation/test_conversation_api_reject.c0000644000175000017500000002001512255773026021424 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/test_conversation_api_reject.c * @brief testcase for conversation_api.c * * This test performs the operations of a call to a phone * where the phone user immediately hangs up (rejecting the * call). */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_conversation_service.h" #include "gnunet_identity_service.h" #include "gnunet_namestore_service.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 25) static int ok = 1; static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_IDENTITY_Handle *id; static struct GNUNET_IDENTITY_Operation *op; static struct GNUNET_CONVERSATION_Phone *phone; static struct GNUNET_NAMESTORE_Handle *ns; static struct GNUNET_CONVERSATION_Call *call; static struct GNUNET_NAMESTORE_QueueEntry *qe; static char *gns_name; static char *gns_caller_id; static int enable_speaker (void *cls) { GNUNET_break (0); return GNUNET_SYSERR; } static void disable_speaker (void *cls) { GNUNET_break (0); } static void play (void *cls, size_t data_size, const void *data) { GNUNET_break (0); } static void destroy_speaker (void *cls) { } static struct GNUNET_SPEAKER_Handle call_speaker = { &enable_speaker, &play, &disable_speaker, &destroy_speaker, "caller" }; static int enable_mic (void *cls, GNUNET_MICROPHONE_RecordedDataCallback rdc, void *rdc_cls) { GNUNET_break (0); return GNUNET_SYSERR; } static void disable_mic (void *cls) { GNUNET_break (0); } static void destroy_mic (void *cls) { } static struct GNUNET_MICROPHONE_Handle call_mic = { &enable_mic, &disable_mic, &destroy_mic, "caller" }; /** * Signature of the main function of a task. * * @param cls closure * @param tc context information (why was this task triggered now) */ static void end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SCHEDULER_shutdown (); if (NULL != op) { GNUNET_IDENTITY_cancel (op); op = NULL; } if (NULL != call) { GNUNET_CONVERSATION_call_stop (call); call = NULL; } if (NULL != phone) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from PHONE service.\n"); GNUNET_CONVERSATION_phone_destroy (phone); phone = NULL; } if (NULL != id) { GNUNET_IDENTITY_disconnect (id); id = NULL; } if (NULL != qe) { GNUNET_NAMESTORE_cancel (qe); qe = NULL; } if (NULL != ns) { GNUNET_NAMESTORE_disconnect (ns); ns = NULL; } } static void phone_event_handler (void *cls, enum GNUNET_CONVERSATION_PhoneEventCode code, struct GNUNET_CONVERSATION_Caller *caller, const char *caller_id) { static enum GNUNET_CONVERSATION_PhoneEventCode expect = GNUNET_CONVERSATION_EC_PHONE_RING; GNUNET_break (0 == strcmp (caller_id, gns_caller_id)); GNUNET_break (code == expect); switch (code) { case GNUNET_CONVERSATION_EC_PHONE_RING: GNUNET_CONVERSATION_caller_hang_up (caller); break; default: fprintf (stderr, "Unexpected phone code: %d\n", code); break; } } static void call_event_handler (void *cls, enum GNUNET_CONVERSATION_CallEventCode code) { static enum GNUNET_CONVERSATION_CallEventCode expect = GNUNET_CONVERSATION_EC_CALL_RINGING; GNUNET_break (code == expect); switch (code) { case GNUNET_CONVERSATION_EC_CALL_RINGING: expect = GNUNET_CONVERSATION_EC_CALL_HUNG_UP; break; case GNUNET_CONVERSATION_EC_CALL_HUNG_UP: call = NULL; ok = 0; GNUNET_SCHEDULER_shutdown (); expect = -1; break; case GNUNET_CONVERSATION_EC_CALL_PICKED_UP: case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL: case GNUNET_CONVERSATION_EC_CALL_SUSPENDED: case GNUNET_CONVERSATION_EC_CALL_RESUMED: case GNUNET_CONVERSATION_EC_CALL_ERROR: fprintf (stderr, "Unexpected call code: %d\n", code); break; } } static void caller_ego_create_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); } static void namestore_put_cont (void *cls, int32_t success, const char *emsg) { qe = NULL; GNUNET_assert (GNUNET_YES == success); GNUNET_assert (NULL == emsg); GNUNET_assert (NULL == op); op = GNUNET_IDENTITY_create (id, "caller-ego", &caller_ego_create_cont, NULL); } static void identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { struct GNUNET_GNSRECORD_Data rd; struct GNUNET_CRYPTO_EcdsaPublicKey pub; if (NULL == name) return; if (NULL == ego) return; if (0 == strcmp (name, "phone-ego")) { GNUNET_IDENTITY_ego_get_public_key (ego, &pub); GNUNET_asprintf (&gns_name, "phone.%s", GNUNET_GNSRECORD_pkey_to_zkey (&pub)); phone = GNUNET_CONVERSATION_phone_create (cfg, ego, &phone_event_handler, NULL); GNUNET_assert (NULL != phone); memset (&rd, 0, sizeof (rd)); GNUNET_CONVERSATION_phone_get_record (phone, &rd); GNUNET_assert (rd.record_type == GNUNET_GNSRECORD_TYPE_PHONE); rd.expiration_time = UINT64_MAX; qe = GNUNET_NAMESTORE_records_store (ns, GNUNET_IDENTITY_ego_get_private_key (ego), "phone" /* GNS label */, 1, &rd, &namestore_put_cont, NULL); return; } if (0 == strcmp (name, "caller-ego")) { GNUNET_IDENTITY_ego_get_public_key (ego, &pub); GNUNET_asprintf (&gns_caller_id, "%s", GNUNET_GNSRECORD_pkey_to_zkey (&pub)); call = GNUNET_CONVERSATION_call_start (cfg, ego, gns_name, &call_speaker, &call_mic, &call_event_handler, NULL); return; } } static void phone_ego_create_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_TESTING_Peer *peer) { cfg = c; GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test, NULL); id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); op = GNUNET_IDENTITY_create (id, "phone-ego", &phone_ego_create_cont, NULL); ns = GNUNET_NAMESTORE_connect (cfg); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test_conversation_api", "test_conversation.conf", &run, NULL)) return 1; return ok; } /* end of test_conversation_api_reject.c */ gnunet-0.10.1/src/conversation/test_conversation_api.c0000644000175000017500000003003212255773026020070 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/test_conversation_api.c * @brief testcase for conversation_api.c * * This test performs the operations of a call to a phone * where the phone user picks up and then the call is * terminated by the party that initiated the call. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_conversation_service.h" #include "gnunet_identity_service.h" #include "gnunet_namestore_service.h" #define FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 25) static int ok = 1; static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_IDENTITY_Handle *id; static struct GNUNET_IDENTITY_Operation *op; static struct GNUNET_CONVERSATION_Phone *phone; static struct GNUNET_NAMESTORE_Handle *ns; static struct GNUNET_CONVERSATION_Call *call; static struct GNUNET_NAMESTORE_QueueEntry *qe; static struct GNUNET_CONVERSATION_Caller *active_caller; static char *gns_name; static char *gns_caller_id; static GNUNET_MICROPHONE_RecordedDataCallback phone_rdc; static void *phone_rdc_cls; static GNUNET_MICROPHONE_RecordedDataCallback call_rdc; static void *call_rdc_cls; static GNUNET_SCHEDULER_TaskIdentifier phone_task; static GNUNET_SCHEDULER_TaskIdentifier call_task; static void phone_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static unsigned int i; char buf[32]; GNUNET_assert (NULL != phone_rdc); GNUNET_snprintf (buf, sizeof (buf), "phone-%u", i++); phone_rdc (phone_rdc_cls, strlen (buf) + 1, buf); phone_task = GNUNET_SCHEDULER_add_delayed (FREQ, &phone_send, NULL); } static void call_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static unsigned int i; char buf[32]; GNUNET_assert (NULL != call_rdc); GNUNET_snprintf (buf, sizeof (buf), "call-%u", i++); call_rdc (call_rdc_cls, strlen (buf) + 1, buf); call_task = GNUNET_SCHEDULER_add_delayed (FREQ, &call_send, NULL); } static int enable_speaker (void *cls) { const char *origin = cls; fprintf (stderr, "Speaker %s enabled\n", origin); return GNUNET_OK; } static void disable_speaker (void *cls) { const char *origin = cls; fprintf (stderr, "Speaker %s disabled\n", origin); } static void play (void *cls, size_t data_size, const void *data) { const char *origin = cls; static unsigned int phone_i = 1; static unsigned int call_i; char buf[32]; if (0 == strcmp (origin, "phone")) GNUNET_snprintf (buf, sizeof (buf), "call-%u", call_i++); else GNUNET_snprintf (buf, sizeof (buf), "phone-%u", phone_i++); if ( (data_size != strlen (buf) + 1) || (0 != strncmp (buf, data, data_size)) ) { fprintf (stderr, "Expected %s, received %.*s\n", buf, (int) data_size, (const char *) data); } else { fprintf (stderr, "."); } if ( (20 < call_i) && (20 < phone_i) && (NULL != call) ) { /* time to hang up ... */ GNUNET_CONVERSATION_call_stop (call); call = NULL; } } static void destroy_speaker (void *cls) { const char *origin = cls; fprintf (stderr, "Speaker %s destroyed\n", origin); } static struct GNUNET_SPEAKER_Handle call_speaker = { &enable_speaker, &play, &disable_speaker, &destroy_speaker, "caller" }; static struct GNUNET_SPEAKER_Handle phone_speaker = { &enable_speaker, &play, &disable_speaker, &destroy_speaker, "phone" }; static int enable_mic (void *cls, GNUNET_MICROPHONE_RecordedDataCallback rdc, void *rdc_cls) { const char *origin = cls; fprintf (stderr, "Mic %s enabled\n", origin); if (0 == strcmp (origin, "phone")) { phone_rdc = rdc; phone_rdc_cls = rdc_cls; phone_task = GNUNET_SCHEDULER_add_now (&phone_send, NULL); } else { call_rdc = rdc; call_rdc_cls = rdc_cls; call_task = GNUNET_SCHEDULER_add_now (&call_send, NULL); } return GNUNET_OK; } static void disable_mic (void *cls) { const char *origin = cls; fprintf (stderr, "Mic %s disabled\n", origin); if (0 == strcmp (origin, "phone")) { phone_rdc = NULL; phone_rdc_cls = NULL; GNUNET_SCHEDULER_cancel (phone_task); phone_task = GNUNET_SCHEDULER_NO_TASK; } else { call_rdc = NULL; call_rdc_cls = NULL; GNUNET_SCHEDULER_cancel (call_task); call_task = GNUNET_SCHEDULER_NO_TASK; } } static void destroy_mic (void *cls) { const char *origin = cls; fprintf (stderr, "Mic %s destroyed\n", origin); } static struct GNUNET_MICROPHONE_Handle call_mic = { &enable_mic, &disable_mic, &destroy_mic, "caller" }; static struct GNUNET_MICROPHONE_Handle phone_mic = { &enable_mic, &disable_mic, &destroy_mic, "phone" }; /** * Signature of the main function of a task. * * @param cls closure * @param tc context information (why was this task triggered now) */ static void end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SCHEDULER_shutdown (); if (NULL != op) { GNUNET_IDENTITY_cancel (op); op = NULL; } if (NULL != call) { GNUNET_CONVERSATION_call_stop (call); call = NULL; } if (NULL != phone) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from PHONE service.\n"); GNUNET_CONVERSATION_phone_destroy (phone); phone = NULL; } if (NULL != id) { GNUNET_IDENTITY_disconnect (id); id = NULL; } if (NULL != qe) { GNUNET_NAMESTORE_cancel (qe); qe = NULL; } if (NULL != ns) { GNUNET_NAMESTORE_disconnect (ns); ns = NULL; } } static void caller_event_handler (void *cls, enum GNUNET_CONVERSATION_CallerEventCode code) { switch (code) { case GNUNET_CONVERSATION_EC_CALLER_SUSPEND: case GNUNET_CONVERSATION_EC_CALLER_RESUME: fprintf (stderr, "Unexpected caller code: %d\n", code); break; } } static void phone_event_handler (void *cls, enum GNUNET_CONVERSATION_PhoneEventCode code, struct GNUNET_CONVERSATION_Caller *caller, const char *caller_id) { static enum GNUNET_CONVERSATION_PhoneEventCode expect = GNUNET_CONVERSATION_EC_PHONE_RING; GNUNET_break (0 == strcmp (caller_id, gns_caller_id)); GNUNET_break (code == expect); switch (code) { case GNUNET_CONVERSATION_EC_PHONE_RING: active_caller = caller; GNUNET_CONVERSATION_caller_pick_up (caller, &caller_event_handler, NULL, &phone_speaker, &phone_mic); expect = GNUNET_CONVERSATION_EC_PHONE_HUNG_UP; break; case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP: GNUNET_break (caller == active_caller); active_caller = NULL; ok = 0; GNUNET_SCHEDULER_shutdown (); break; default: fprintf (stderr, "Unexpected phone code: %d\n", code); break; } } static void call_event_handler (void *cls, enum GNUNET_CONVERSATION_CallEventCode code) { static enum GNUNET_CONVERSATION_CallEventCode expect = GNUNET_CONVERSATION_EC_CALL_RINGING; GNUNET_break (code == expect); switch (code) { case GNUNET_CONVERSATION_EC_CALL_RINGING: expect = GNUNET_CONVERSATION_EC_CALL_PICKED_UP; break; case GNUNET_CONVERSATION_EC_CALL_PICKED_UP: expect = -1; break; case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL: case GNUNET_CONVERSATION_EC_CALL_HUNG_UP: call = NULL; fprintf (stderr, "Unexpected call code: %d\n", code); break; case GNUNET_CONVERSATION_EC_CALL_SUSPENDED: case GNUNET_CONVERSATION_EC_CALL_RESUMED: case GNUNET_CONVERSATION_EC_CALL_ERROR: fprintf (stderr, "Unexpected call code: %d\n", code); break; } } static void caller_ego_create_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); } static void namestore_put_cont (void *cls, int32_t success, const char *emsg) { qe = NULL; GNUNET_assert (GNUNET_YES == success); GNUNET_assert (NULL == emsg); GNUNET_assert (NULL == op); op = GNUNET_IDENTITY_create (id, "caller-ego", &caller_ego_create_cont, NULL); } static void identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { struct GNUNET_GNSRECORD_Data rd; struct GNUNET_CRYPTO_EcdsaPublicKey pub; if (NULL == name) return; if (NULL == ego) return; if (0 == strcmp (name, "phone-ego")) { GNUNET_IDENTITY_ego_get_public_key (ego, &pub); GNUNET_asprintf (&gns_name, "phone.%s", GNUNET_GNSRECORD_pkey_to_zkey (&pub)); phone = GNUNET_CONVERSATION_phone_create (cfg, ego, &phone_event_handler, NULL); GNUNET_assert (NULL != phone); memset (&rd, 0, sizeof (rd)); GNUNET_CONVERSATION_phone_get_record (phone, &rd); GNUNET_assert (rd.record_type == GNUNET_GNSRECORD_TYPE_PHONE); rd.expiration_time = UINT64_MAX; qe = GNUNET_NAMESTORE_records_store (ns, GNUNET_IDENTITY_ego_get_private_key (ego), "phone" /* GNS label */, 1, &rd, &namestore_put_cont, NULL); return; } if (0 == strcmp (name, "caller-ego")) { GNUNET_IDENTITY_ego_get_public_key (ego, &pub); GNUNET_asprintf (&gns_caller_id, "%s", GNUNET_GNSRECORD_pkey_to_zkey (&pub)); call = GNUNET_CONVERSATION_call_start (cfg, ego, gns_name, &call_speaker, &call_mic, &call_event_handler, NULL); return; } } static void phone_ego_create_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_TESTING_Peer *peer) { cfg = c; GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test, NULL); id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); op = GNUNET_IDENTITY_create (id, "phone-ego", &phone_ego_create_cont, NULL); ns = GNUNET_NAMESTORE_connect (cfg); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test_conversation_api", "test_conversation.conf", &run, NULL)) return 1; return ok; } /* end of test_conversation_api.c */ gnunet-0.10.1/src/conversation/conversation_api.c0000644000175000017500000006015212251306467017034 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/conversation_api.c * @brief phone and caller API to the conversation service * @author Simon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_conversation_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gns_service.h" #include "conversation.h" /** * Possible states of a caller. */ enum CallerState { /** * We still need to reverse lookup the caller ID. */ CS_RESOLVE, /** * The phone is ringing (user knows about incoming call). */ CS_RINGING, /** * The phone is in an active conversation. */ CS_ACTIVE, /** * We suspended the conversation. */ CS_CALLEE_SUSPENDED, /** * Caller suspended the conversation. */ CS_CALLER_SUSPENDED, /** * Both sides suspended the conversation. */ CS_BOTH_SUSPENDED }; /** * A caller is the handle we have for an incoming call. */ struct GNUNET_CONVERSATION_Caller { /** * We keep all callers in a DLL. */ struct GNUNET_CONVERSATION_Caller *next; /** * We keep all callers in a DLL. */ struct GNUNET_CONVERSATION_Caller *prev; /** * Our phone. */ struct GNUNET_CONVERSATION_Phone *phone; /** * Function to call for phone events. */ GNUNET_CONVERSATION_CallerEventHandler event_handler; /** * Closure for @e event_handler */ void *event_handler_cls; /** * Speaker, or NULL if none is attached. */ struct GNUNET_SPEAKER_Handle *speaker; /** * Microphone, or NULL if none is attached. */ struct GNUNET_MICROPHONE_Handle *mic; /** * Active NAMESTORE lookup (or NULL). */ struct GNUNET_NAMESTORE_QueueEntry *qe; /** * Identity of the person calling us. */ struct GNUNET_CRYPTO_EcdsaPublicKey caller_id; /** * Caller ID of the person calling us as a string. */ char *caller_id_str; /** * Internal handle to identify the caller with the service. */ uint32_t cid; /** * State machine for the phone. */ enum CallerState state; }; /** * Possible states of a phone. */ enum PhoneState { /** * We still need to register the phone. */ PS_REGISTER = 0, /** * We are waiting for calls. */ PS_READY }; /** * A phone is a device that can ring to signal an incoming call and * that you can pick up to answer the call and hang up to terminate * the call. You can also hang up a ringing phone immediately * (without picking it up) to stop it from ringing. Phones have * caller ID. You can ask the phone for its record and make that * record available (via GNS) to enable others to call you. * Multiple phones maybe connected to the same line (the line is * something rather internal to a phone and not obvious from it). * You can only have one conversation per phone at any time. */ struct GNUNET_CONVERSATION_Phone { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to talk with CONVERSATION service. */ struct GNUNET_CLIENT_Connection *client; /** * We keep all callers in a DLL. */ struct GNUNET_CONVERSATION_Caller *caller_head; /** * We keep all callers in a DLL. */ struct GNUNET_CONVERSATION_Caller *caller_tail; /** * Function to call for phone events. */ GNUNET_CONVERSATION_PhoneEventHandler event_handler; /** * Closure for @e event_handler */ void *event_handler_cls; /** * Connection to NAMESTORE (for reverse lookup). */ struct GNUNET_NAMESTORE_Handle *ns; /** * Handle for transmitting to the CONVERSATION service. */ struct GNUNET_MQ_Handle *mq; /** * This phone's record. */ struct GNUNET_CONVERSATION_PhoneRecord my_record; /** * My GNS zone. */ struct GNUNET_CRYPTO_EcdsaPrivateKey my_zone; /** * State machine for the phone. */ enum PhoneState state; }; /** * The phone got disconnected, reconnect to the service. * * @param phone phone to reconnect */ static void reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone); /** * We have resolved the caller ID using our name service. * * @param cls the `struct GNUNET_CONVERSATION_Caller` * @param zone our zone used for resolution * @param label name of the caller * @param rd_count number of records we have in @a rd * @param rd records we have for the caller's label */ static void handle_caller_name (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_CONVERSATION_Caller *caller = cls; struct GNUNET_CONVERSATION_Phone *phone = caller->phone; char *name; caller->qe = NULL; if (NULL == label) name = GNUNET_strdup (GNUNET_GNSRECORD_pkey_to_zkey (&caller->caller_id)); else GNUNET_asprintf (&name, "%s.gnu", label); caller->caller_id_str = name; caller->state = CS_RINGING; phone->event_handler (phone->event_handler_cls, GNUNET_CONVERSATION_EC_PHONE_RING, caller, name); } /** * Process recorded audio data. * * @param cls closure with the `struct GNUNET_CONVERSATION_Caller` * @param data_size number of bytes in @a data * @param data audio data to play */ static void transmit_phone_audio (void *cls, size_t data_size, const void *data) { struct GNUNET_CONVERSATION_Caller *caller = cls; struct GNUNET_CONVERSATION_Phone *phone = caller->phone; struct GNUNET_MQ_Envelope *e; struct ClientAudioMessage *am; e = GNUNET_MQ_msg_extra (am, data_size, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO); am->cid = caller->cid; memcpy (&am[1], data, data_size); GNUNET_MQ_send (phone->mq, e); } /** * We received a `struct ClientPhoneRingMessage` * * @param cls the `struct GNUNET_CONVERSATION_Phone` * @param msg the message */ static void handle_phone_ring (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Phone *phone = cls; const struct ClientPhoneRingMessage *ring; struct GNUNET_CONVERSATION_Caller *caller; ring = (const struct ClientPhoneRingMessage *) msg; switch (phone->state) { case PS_REGISTER: GNUNET_assert (0); break; case PS_READY: caller = GNUNET_new (struct GNUNET_CONVERSATION_Caller); caller->phone = phone; GNUNET_CONTAINER_DLL_insert (phone->caller_head, phone->caller_tail, caller); caller->state = CS_RESOLVE; caller->caller_id = ring->caller_id; caller->cid = ring->cid; caller->qe = GNUNET_NAMESTORE_zone_to_name (phone->ns, &phone->my_zone, &ring->caller_id, &handle_caller_name, caller); break; } } /** * We received a `struct ClientPhoneHangupMessage`. * * @param cls the `struct GNUNET_CONVERSATION_Phone` * @param msg the message */ static void handle_phone_hangup (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Phone *phone = cls; const struct ClientPhoneHangupMessage *hang; struct GNUNET_CONVERSATION_Caller *caller; hang = (const struct ClientPhoneHangupMessage *) msg; for (caller = phone->caller_head; NULL != caller; caller = caller->next) if (hang->cid == caller->cid) break; if (NULL == caller) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received HANG_UP message for unknown caller ID %u\n", (unsigned int) hang->cid); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received HANG_UP message, terminating call with `%s'\n", caller->caller_id_str); switch (caller->state) { case CS_RESOLVE: /* application doesn't even know about call yet */ GNUNET_NAMESTORE_cancel (caller->qe); caller->qe = NULL; break; case CS_RINGING: phone->event_handler (phone->event_handler_cls, GNUNET_CONVERSATION_EC_PHONE_HUNG_UP, caller, caller->caller_id_str); break; case CS_ACTIVE: caller->speaker->disable_speaker (caller->speaker->cls); caller->mic->disable_microphone (caller->mic->cls); phone->event_handler (phone->event_handler_cls, GNUNET_CONVERSATION_EC_PHONE_HUNG_UP, caller, caller->caller_id_str); break; case CS_CALLEE_SUSPENDED: case CS_CALLER_SUSPENDED: case CS_BOTH_SUSPENDED: phone->event_handler (phone->event_handler_cls, GNUNET_CONVERSATION_EC_PHONE_HUNG_UP, caller, caller->caller_id_str); break; } GNUNET_CONTAINER_DLL_remove (phone->caller_head, phone->caller_tail, caller); GNUNET_free (caller); } /** * We received a `struct ClientPhoneSuspendMessage`. * * @param cls the `struct GNUNET_CONVERSATION_Phone` * @param msg the message */ static void handle_phone_suspend (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Phone *phone = cls; struct GNUNET_CONVERSATION_Caller *caller; const struct ClientPhoneSuspendMessage *suspend; suspend = (const struct ClientPhoneSuspendMessage *) msg; for (caller = phone->caller_head; NULL != caller; caller = caller->next) if (suspend->cid == caller->cid) break; if (NULL == caller) return; switch (caller->state) { case CS_RESOLVE: GNUNET_break_op (0); break; case CS_RINGING: GNUNET_break_op (0); break; case CS_ACTIVE: caller->state = CS_CALLER_SUSPENDED; caller->speaker->disable_speaker (caller->speaker->cls); caller->mic->disable_microphone (caller->mic->cls); caller->event_handler (caller->event_handler_cls, GNUNET_CONVERSATION_EC_CALLER_SUSPEND); break; case CS_CALLEE_SUSPENDED: caller->state = CS_BOTH_SUSPENDED; caller->event_handler (caller->event_handler_cls, GNUNET_CONVERSATION_EC_CALLER_SUSPEND); break; case CS_CALLER_SUSPENDED: case CS_BOTH_SUSPENDED: GNUNET_break_op (0); break; } } /** * We received a `struct ClientPhoneResumeMessage`. * * @param cls the `struct GNUNET_CONVERSATION_Phone` * @param msg the message */ static void handle_phone_resume (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Phone *phone = cls; struct GNUNET_CONVERSATION_Caller *caller; const struct ClientPhoneResumeMessage *resume; resume = (const struct ClientPhoneResumeMessage *) msg; for (caller = phone->caller_head; NULL != caller; caller = caller->next) if (resume->cid == caller->cid) break; if (NULL == caller) return; switch (caller->state) { case CS_RESOLVE: GNUNET_break_op (0); break; case CS_RINGING: GNUNET_break_op (0); break; case CS_ACTIVE: case CS_CALLEE_SUSPENDED: GNUNET_break_op (0); break; case CS_CALLER_SUSPENDED: caller->state = CS_ACTIVE; caller->speaker->enable_speaker (caller->speaker->cls); caller->mic->enable_microphone (caller->mic->cls, &transmit_phone_audio, caller); caller->event_handler (caller->event_handler_cls, GNUNET_CONVERSATION_EC_CALLER_RESUME); break; case CS_BOTH_SUSPENDED: caller->state = CS_CALLEE_SUSPENDED; caller->event_handler (caller->event_handler_cls, GNUNET_CONVERSATION_EC_CALLER_RESUME); break; } } /** * We received a `struct ClientAudioMessage` * * @param cls the `struct GNUNET_CONVERSATION_Phone` * @param msg the message */ static void handle_phone_audio_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONVERSATION_Phone *phone = cls; const struct ClientAudioMessage *am; struct GNUNET_CONVERSATION_Caller *caller; am = (const struct ClientAudioMessage *) msg; for (caller = phone->caller_head; NULL != caller; caller = caller->next) if (am->cid == caller->cid) break; if (NULL == caller) return; switch (caller->state) { case CS_RESOLVE: GNUNET_break_op (0); break; case CS_RINGING: GNUNET_break_op (0); break; case CS_ACTIVE: caller->speaker->play (caller->speaker->cls, ntohs (msg->size) - sizeof (struct ClientAudioMessage), &am[1]); break; case CS_CALLEE_SUSPENDED: case CS_CALLER_SUSPENDED: case CS_BOTH_SUSPENDED: break; } } /** * We encountered an error talking with the conversation service. * * @param cls the `struct GNUNET_CONVERSATION_Phone` * @param error details about the error */ static void phone_error_handler (void *cls, enum GNUNET_MQ_Error error) { struct GNUNET_CONVERSATION_Phone *phone = cls; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Connection to conversation service lost, trying to reconnect\n")); reconnect_phone (phone); } /** * Clean up all callers of the given phone. * * @param phone phone to clean up callers for */ static void clean_up_callers (struct GNUNET_CONVERSATION_Phone *phone) { struct GNUNET_CONVERSATION_Caller *caller; while (NULL != (caller = phone->caller_head)) { /* make sure mic/speaker are disabled *before* callback */ if (CS_ACTIVE == caller->state) { caller->speaker->disable_speaker (caller->speaker->cls); caller->mic->disable_microphone (caller->mic->cls); caller->state = CS_CALLER_SUSPENDED; } phone->event_handler (phone->event_handler_cls, GNUNET_CONVERSATION_EC_PHONE_HUNG_UP, caller, caller->caller_id_str); GNUNET_CONVERSATION_caller_hang_up (caller); } } /** * The phone got disconnected, reconnect to the service. * * @param phone phone to reconnect */ static void reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone) { static struct GNUNET_MQ_MessageHandler handlers[] = { { &handle_phone_ring, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING, sizeof (struct ClientPhoneRingMessage) }, { &handle_phone_hangup, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP, sizeof (struct ClientPhoneHangupMessage) }, { &handle_phone_suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND, sizeof (struct ClientPhoneSuspendMessage) }, { &handle_phone_resume, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME, sizeof (struct ClientPhoneResumeMessage) }, { &handle_phone_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO, 0 }, { NULL, 0, 0 } }; struct GNUNET_MQ_Envelope *e; struct ClientPhoneRegisterMessage *reg; clean_up_callers (phone); if (NULL != phone->mq) { GNUNET_MQ_destroy (phone->mq); phone->mq = NULL; } if (NULL != phone->client) { GNUNET_CLIENT_disconnect (phone->client); phone->client = NULL; } phone->state = PS_REGISTER; phone->client = GNUNET_CLIENT_connect ("conversation", phone->cfg); if (NULL == phone->client) return; phone->mq = GNUNET_MQ_queue_for_connection_client (phone->client, handlers, &phone_error_handler, phone); e = GNUNET_MQ_msg (reg, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER); reg->line = phone->my_record.line; GNUNET_MQ_send (phone->mq, e); phone->state = PS_READY; } /** * Create a new phone. * * @param cfg configuration for the phone; specifies the phone service and * which line the phone is to be connected to * @param ego ego to use for name resolution (when determining caller ID) * @param event_handler how to notify the owner of the phone about events * @param event_handler_cls closure for @a event_handler * @return NULL on error (no valid line configured) */ struct GNUNET_CONVERSATION_Phone * GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_Ego *ego, GNUNET_CONVERSATION_PhoneEventHandler event_handler, void *event_handler_cls) { struct GNUNET_CONVERSATION_Phone *phone; unsigned long long line; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "CONVERSATION", "LINE", &line)) return NULL; if (line >= (1 << 31)) return NULL; phone = GNUNET_new (struct GNUNET_CONVERSATION_Phone); if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &phone->my_record.peer)) { GNUNET_break (0); GNUNET_free (phone); return NULL; } phone->cfg = cfg; phone->my_zone = *GNUNET_IDENTITY_ego_get_private_key (ego); phone->event_handler = event_handler; phone->event_handler_cls = event_handler_cls; phone->ns = GNUNET_NAMESTORE_connect (cfg); phone->my_record.line = htonl ((uint32_t) line); phone->my_record.version = htonl (0); reconnect_phone (phone); if ( (NULL == phone->client) || (NULL == phone->ns) ) { GNUNET_break (0); GNUNET_CONVERSATION_phone_destroy (phone); return NULL; } return phone; } /** * Fill in a namestore record with the contact information * for this phone. Note that the filled in "data" value * is only valid until the phone is destroyed. * * @param phone phone to create a record for * @param rd namestore record to fill in */ void GNUNET_CONVERSATION_phone_get_record (struct GNUNET_CONVERSATION_Phone *phone, struct GNUNET_GNSRECORD_Data *rd) { rd->data = &phone->my_record; rd->expiration_time = 0; rd->data_size = sizeof (struct GNUNET_CONVERSATION_PhoneRecord); rd->record_type = GNUNET_GNSRECORD_TYPE_PHONE; rd->flags = GNUNET_GNSRECORD_RF_NONE; } /** * Picks up a (ringing) phone. This will connect the speaker * to the microphone of the other party, and vice versa. * * @param caller handle that identifies which caller should be answered * @param event_handler how to notify about events by the caller * @param event_handler_cls closure for @a event_handler * @param speaker speaker to use * @param mic microphone to use */ void GNUNET_CONVERSATION_caller_pick_up (struct GNUNET_CONVERSATION_Caller *caller, GNUNET_CONVERSATION_CallerEventHandler event_handler, void *event_handler_cls, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic) { struct GNUNET_CONVERSATION_Phone *phone = caller->phone; struct GNUNET_MQ_Envelope *e; struct ClientPhonePickupMessage *pick; GNUNET_assert (CS_RINGING == caller->state); caller->speaker = speaker; caller->mic = mic; e = GNUNET_MQ_msg (pick, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP); pick->cid = caller->cid; GNUNET_MQ_send (phone->mq, e); caller->state = CS_ACTIVE; caller->event_handler = event_handler; caller->event_handler_cls = event_handler_cls; caller->speaker->enable_speaker (caller->speaker->cls); caller->mic->enable_microphone (caller->mic->cls, &transmit_phone_audio, caller); } /** * Hang up up a (possibly ringing) phone. This will notify the other * party that we are no longer interested in talking with them. * * @param caller conversation to hang up on */ void GNUNET_CONVERSATION_caller_hang_up (struct GNUNET_CONVERSATION_Caller *caller) { struct GNUNET_CONVERSATION_Phone *phone = caller->phone; struct GNUNET_MQ_Envelope *e; struct ClientPhoneHangupMessage *hang; switch (caller->state) { case CS_RESOLVE: GNUNET_NAMESTORE_cancel (caller->qe); caller->qe = NULL; break; case CS_ACTIVE: caller->speaker->disable_speaker (caller->speaker->cls); caller->mic->disable_microphone (caller->mic->cls); break; default: break; } GNUNET_CONTAINER_DLL_remove (phone->caller_head, phone->caller_tail, caller); GNUNET_free_non_null (caller->caller_id_str); GNUNET_free (caller); e = GNUNET_MQ_msg (hang, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); GNUNET_MQ_send (phone->mq, e); } /** * Destroys a phone. * * @param phone phone to destroy */ void GNUNET_CONVERSATION_phone_destroy (struct GNUNET_CONVERSATION_Phone *phone) { clean_up_callers (phone); if (NULL != phone->ns) { GNUNET_NAMESTORE_disconnect (phone->ns); phone->ns = NULL; } if (NULL != phone->mq) { GNUNET_MQ_destroy (phone->mq); phone->mq = NULL; } if (NULL != phone->client) { GNUNET_CLIENT_disconnect (phone->client); phone->client = NULL; } GNUNET_free (phone); } /** * Pause conversation of an active call. This will disconnect the speaker * and the microphone. The call can later be resumed with * #GNUNET_CONVERSATION_caller_resume. * * @param caller call to suspend */ void GNUNET_CONVERSATION_caller_suspend (struct GNUNET_CONVERSATION_Caller *caller) { struct GNUNET_CONVERSATION_Phone *phone = caller->phone; struct GNUNET_MQ_Envelope *e; struct ClientPhoneSuspendMessage *suspend; GNUNET_assert ( (CS_ACTIVE == caller->state) || (CS_CALLER_SUSPENDED == caller->state) ); if (CS_ACTIVE == caller->state) { caller->speaker->disable_speaker (caller->speaker->cls); caller->mic->disable_microphone (caller->mic->cls); } caller->speaker = NULL; caller->mic = NULL; e = GNUNET_MQ_msg (suspend, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); suspend->cid = caller->cid; GNUNET_MQ_send (phone->mq, e); if (CS_ACTIVE == caller->state) caller->state = CS_CALLEE_SUSPENDED; else caller->state = CS_BOTH_SUSPENDED; } /** * Resume suspended conversation of a phone. * * @param caller call to resume * @param speaker speaker to use * @param mic microphone to use */ void GNUNET_CONVERSATION_caller_resume (struct GNUNET_CONVERSATION_Caller *caller, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic) { struct GNUNET_CONVERSATION_Phone *phone = caller->phone; struct GNUNET_MQ_Envelope *e; struct ClientPhoneResumeMessage *resume; GNUNET_assert ( (CS_CALLEE_SUSPENDED == caller->state) || (CS_BOTH_SUSPENDED == caller->state) ); caller->speaker = speaker; caller->mic = mic; e = GNUNET_MQ_msg (resume, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME); resume->cid = caller->cid; GNUNET_MQ_send (phone->mq, e); if (CS_CALLEE_SUSPENDED == caller->state) { caller->state = CS_ACTIVE; caller->speaker->enable_speaker (caller->speaker->cls); caller->mic->enable_microphone (caller->mic->cls, &transmit_phone_audio, caller); } else { caller->state = CS_CALLER_SUSPENDED; } } /* end of conversation_api.c */ gnunet-0.10.1/src/conversation/gnunet-conversation.c0000644000175000017500000007036112274162760017505 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/gnunet-conversation.c * @brief conversation implementation * @author Simon Dieterle * @author Andreas Fuchs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_conversation_service.h" #include "gnunet_namestore_service.h" #ifdef WINDOWS #include "../util/gnunet-helper-w32-console.h" #endif /** * Maximum length allowed for the command line input. */ #define MAX_MESSAGE_LENGTH 1024 #define XSTRINGIFY(x) STRINGIFY(x) #define STRINGIFY(x) (#x) #ifdef WINDOWS /** * Helper that reads the console for us. */ struct GNUNET_HELPER_Handle *stdin_hlp; #endif /** * Possible states of the phone. */ enum PhoneState { /** * We're waiting for our own idenitty. */ PS_LOOKUP_EGO, /** * We're listening for calls */ PS_LISTEN, /** * We accepted an incoming phone call. */ PS_ACCEPTED, /** * Internal error */ PS_ERROR }; /** * States for current outgoing call. */ enum CallState { /** * We are looking up some other participant. */ CS_RESOLVING, /** * We are now ringing the other participant. */ CS_RINGING, /** * The other party accepted our call and we are now connected. */ CS_CONNECTED, /** * The call is currently suspended (by us). */ CS_SUSPENDED }; /** * List of incoming calls */ struct CallList { /** * A DLL. */ struct CallList *prev; /** * A DLL. */ struct CallList *next; /** * Handle to hang up or activate. */ struct GNUNET_CONVERSATION_Caller *caller; /** * String identifying the caller. */ char *caller_id; /** * Unique number of the call. */ unsigned int caller_num; }; /** * Phone handle */ static struct GNUNET_CONVERSATION_Phone *phone; /** * Call handle (for active outgoing call). */ static struct GNUNET_CONVERSATION_Call *call; /** * Caller handle (for active incoming call). */ static struct CallList *cl_active; /** * Head of calls waiting to be accepted. */ static struct CallList *cl_head; /** * Tail of calls waiting to be accepted. */ static struct CallList *cl_tail; /** * Desired phone line. */ static unsigned int line; /** * Task which handles the commands */ static GNUNET_SCHEDULER_TaskIdentifier handle_cmd_task; /** * Our speaker. */ static struct GNUNET_SPEAKER_Handle *speaker; /** * Our microphone. */ static struct GNUNET_MICROPHONE_Handle *mic; /** * Our configuration. */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Our ego. */ static struct GNUNET_IDENTITY_Ego *caller_id; /** * Handle to identity service. */ static struct GNUNET_IDENTITY_Handle *id; /** * Name of our ego. */ static char *ego_name; /** * Name of conversation partner (if any). */ static char *peer_name; /** * File handle for stdin. */ static struct GNUNET_DISK_FileHandle *stdin_fh; /** * Our phone's current state. */ static enum PhoneState phone_state; /** * Our call's current state. */ static enum CallState call_state; /** * Counts the number of incoming calls we have had so far. */ static unsigned int caller_num_gen; /** * GNS address for this phone. */ static char *address; /** * Be verbose. */ static int verbose; /** * Function called with an event emitted by a phone. * * @param cls closure * @param code type of the event * @param caller handle for the caller * @param caller_id name of the caller in GNS */ static void phone_event_handler (void *cls, enum GNUNET_CONVERSATION_PhoneEventCode code, struct GNUNET_CONVERSATION_Caller *caller, const char *caller_id) { struct CallList *cl; switch (code) { case GNUNET_CONVERSATION_EC_PHONE_RING: FPRINTF (stdout, _("Incoming call from `%s'. Please /accept #%u or /cancel %u the call.\n"), caller_id, caller_num_gen, caller_num_gen); cl = GNUNET_new (struct CallList); cl->caller = caller; cl->caller_id = GNUNET_strdup (caller_id); cl->caller_num = caller_num_gen++; GNUNET_CONTAINER_DLL_insert (cl_head, cl_tail, cl); break; case GNUNET_CONVERSATION_EC_PHONE_HUNG_UP: for (cl = cl_head; NULL != cl; cl = cl->next) if (caller == cl->caller) break; if (NULL == cl) { GNUNET_break (0); return; } FPRINTF (stdout, _("Call from `%s' terminated\n"), cl->caller_id); GNUNET_CONTAINER_DLL_remove (cl_head, cl_tail, cl); GNUNET_free (cl->caller_id); if (cl == cl_active) { cl_active = NULL; phone_state = PS_LISTEN; } GNUNET_free (cl); break; } } /** * Function called with an event emitted by a caller. * * @param cls closure with the `struct CallList` of the caller * @param code type of the event issued by the caller */ static void caller_event_handler (void *cls, enum GNUNET_CONVERSATION_CallerEventCode code) { struct CallList *cl = cls; switch (code) { case GNUNET_CONVERSATION_EC_CALLER_SUSPEND: FPRINTF (stdout, _("Call from `%s' suspended by other user\n"), cl->caller_id); break; case GNUNET_CONVERSATION_EC_CALLER_RESUME: FPRINTF (stdout, _("Call from `%s' resumed by other user\n"), cl->caller_id); break; } } /** * Start our phone. */ static void start_phone () { struct GNUNET_GNSRECORD_Data rd; if (NULL == caller_id) { FPRINTF (stderr, _("Ego `%s' no longer available, phone is now down.\n"), ego_name); phone_state = PS_LOOKUP_EGO; return; } GNUNET_assert (NULL == phone); phone = GNUNET_CONVERSATION_phone_create (cfg, caller_id, &phone_event_handler, NULL); /* FIXME: get record and print full GNS record info later here... */ if (NULL == phone) { FPRINTF (stderr, "%s", _("Failed to setup phone (internal error)\n")); phone_state = PS_ERROR; } else { GNUNET_CONVERSATION_phone_get_record (phone, &rd); GNUNET_free_non_null (address); address = GNUNET_GNSRECORD_value_to_string (rd.record_type, rd.data, rd.data_size); FPRINTF (stdout, _("Phone active on line %u. Type `/help' for a list of available commands\n"), (unsigned int) line); phone_state = PS_LISTEN; } } /** * Function called with an event emitted by a call. * * @param cls closure, NULL * @param code type of the event on the call */ static void call_event_handler (void *cls, enum GNUNET_CONVERSATION_CallEventCode code) { switch (code) { case GNUNET_CONVERSATION_EC_CALL_RINGING: GNUNET_break (CS_RESOLVING == call_state); FPRINTF (stdout, _("Resolved address of `%s'. Now ringing other party.\n"), peer_name); call_state = CS_RINGING; break; case GNUNET_CONVERSATION_EC_CALL_PICKED_UP: GNUNET_break (CS_RINGING == call_state); FPRINTF (stdout, _("Connection established to `%s'\n"), peer_name); call_state = CS_CONNECTED; break; case GNUNET_CONVERSATION_EC_CALL_GNS_FAIL: GNUNET_break (CS_RESOLVING == call_state); FPRINTF (stdout, _("Failed to resolve `%s'\n"), ego_name); call = NULL; break; case GNUNET_CONVERSATION_EC_CALL_HUNG_UP: FPRINTF (stdout, "%s", _("Call terminated\n")); call = NULL; break; case GNUNET_CONVERSATION_EC_CALL_SUSPENDED: GNUNET_break (CS_CONNECTED == call_state); FPRINTF (stdout, _("Connection to `%s' suspended (by other user)\n"), peer_name); break; case GNUNET_CONVERSATION_EC_CALL_RESUMED: GNUNET_break (CS_CONNECTED == call_state); FPRINTF (stdout, _("Connection to `%s' resumed (by other user)\n"), peer_name); break; case GNUNET_CONVERSATION_EC_CALL_ERROR: FPRINTF (stdout, _("Error with the call, restarting it\n")); call_state = CS_RESOLVING; break; } } /** * Function declareation for executing a action * * @param arguments arguments given to the function */ typedef void (*ActionFunction) (const char *arguments); /** * Structure which defines a command */ struct VoipCommand { /** * Command the user needs to enter. */ const char *command; /** * Function to call on command. */ ActionFunction Action; /** * Help text for the command. */ const char *helptext; }; /** * Action function to print help for the command shell. * * @param args arguments given to the command */ static void do_help (const char *args); /** * Terminate the client * * @param args arguments given to the command */ static void do_quit (const char *args) { GNUNET_SCHEDULER_shutdown (); } /** * Handler for unknown command. * * @param msg arguments given to the command */ static void do_unknown (const char *msg) { FPRINTF (stderr, _("Unknown command `%s'\n"), msg); } /** * Initiating a new call * * @param arg arguments given to the command */ static void do_call (const char *arg) { if (NULL == caller_id) { FPRINTF (stderr, _("Ego `%s' not available\n"), ego_name); return; } if (NULL != call) { FPRINTF (stderr, _("You are calling someone else already, hang up first!\n")); return; } switch (phone_state) { case PS_LOOKUP_EGO: FPRINTF (stderr, _("Ego `%s' not available\n"), ego_name); return; case PS_LISTEN: /* ok to call! */ break; case PS_ACCEPTED: FPRINTF (stderr, _("You are answering call from `%s', hang up or suspend that call first!\n"), peer_name); return; case PS_ERROR: /* ok to call */ break; } GNUNET_free_non_null (peer_name); if (NULL == arg) { FPRINTF (stderr, _("Call recipient missing.\n")); do_help ("/call"); return; } peer_name = GNUNET_strdup (arg); call_state = CS_RESOLVING; GNUNET_assert (NULL == call); call = GNUNET_CONVERSATION_call_start (cfg, caller_id, arg, speaker, mic, &call_event_handler, NULL); } /** * Accepting an incoming call * * @param args arguments given to the command */ static void do_accept (const char *args) { struct CallList *cl; char buf[32]; if ( (NULL != call) && (CS_SUSPENDED != call_state) ) { FPRINTF (stderr, _("You are calling someone else already, hang up first!\n")); return; } switch (phone_state) { case PS_LOOKUP_EGO: GNUNET_break (0); break; case PS_LISTEN: /* this is the expected state */ break; case PS_ACCEPTED: FPRINTF (stderr, _("You are answering call from `%s', hang up or suspend that call first!\n"), peer_name); return; case PS_ERROR: GNUNET_break (0); break; } cl = cl_head; if (NULL == cl) { FPRINTF (stderr, _("There is no incoming call to accept here!\n")); return; } if ( (NULL != cl->next) || (NULL != args) ) { for (cl = cl_head; NULL != cl; cl = cl->next) { GNUNET_snprintf (buf, sizeof (buf), "%u", cl->caller_num); if (0 == strcmp (buf, args)) break; } } if (NULL == cl) { FPRINTF (stderr, _("There is no incoming call `%s' to accept right now!\n"), args); return; } GNUNET_CONTAINER_DLL_remove (cl_head, cl_tail, cl); cl_active = cl; GNUNET_free_non_null (peer_name); peer_name = GNUNET_strdup (cl->caller_id); phone_state = PS_ACCEPTED; GNUNET_CONVERSATION_caller_pick_up (cl->caller, &caller_event_handler, cl, speaker, mic); } /** * Print address information for this phone. * * @param args arguments given to the command */ static void do_address (const char *args) { if (NULL == address) { FPRINTF (stdout, "%s", _("We currently do not have an address.\n")); return; } FPRINTF (stdout, "%s\n", address); } /** * Accepting an incoming call * * @param args arguments given to the command */ static void do_status (const char *args) { struct CallList *cl; switch (phone_state) { case PS_LOOKUP_EGO: FPRINTF (stdout, _("We are currently trying to locate the private key for the ego `%s'.\n"), ego_name); break; case PS_LISTEN: FPRINTF (stdout, _("We are listening for incoming calls for ego `%s' on line %u.\n"), ego_name, line); break; case PS_ACCEPTED: FPRINTF (stdout, _("You are having a conversation with `%s'.\n"), peer_name); break; case PS_ERROR: FPRINTF (stdout, _("We had an internal error setting up our phone line. You can still make calls.\n")); break; } if (NULL != call) { switch (call_state) { case CS_RESOLVING: FPRINTF (stdout, _("We are trying to find the network address to call `%s'.\n"), peer_name); break; case CS_RINGING: FPRINTF (stdout, _("We are calling `%s', his phone should be ringing.\n"), peer_name); break; case CS_CONNECTED: FPRINTF (stdout, _("You are having a conversation with `%s'.\n"), peer_name); break; case CS_SUSPENDED: /* ok to accept incoming call right now */ break; } } if ( (NULL != cl_head) && ( (cl_head != cl_active) || (cl_head != cl_tail) ) ) { FPRINTF (stdout, "%s", _("Calls waiting:\n")); for (cl = cl_head; NULL != cl; cl = cl->next) { if (cl == cl_active) continue; FPRINTF (stdout, _("#%u: `%s'\n"), cl->caller_num, cl->caller_id); } FPRINTF (stdout, "%s", "\n"); } } /** * Suspending a call * * @param args arguments given to the command */ static void do_suspend (const char *args) { if (NULL != call) { switch (call_state) { case CS_RESOLVING: case CS_RINGING: case CS_SUSPENDED: FPRINTF (stderr, "%s", _("There is no call that could be suspended right now.\n")); return; case CS_CONNECTED: call_state = CS_SUSPENDED; GNUNET_CONVERSATION_call_suspend (call); return; } } switch (phone_state) { case PS_LOOKUP_EGO: case PS_LISTEN: case PS_ERROR: FPRINTF (stderr, "%s", _("There is no call that could be suspended right now.\n")); return; case PS_ACCEPTED: /* expected state, do rejection logic */ break; } GNUNET_assert (NULL != cl_active); GNUNET_CONVERSATION_caller_suspend (cl_active->caller); cl_active = NULL; phone_state = PS_LISTEN; } /** * Resuming a call * * @param args arguments given to the command */ static void do_resume (const char *args) { struct CallList *cl; char buf[32]; if (NULL != call) { switch (call_state) { case CS_RESOLVING: case CS_RINGING: case CS_CONNECTED: FPRINTF (stderr, "%s", _("There is no call that could be resumed right now.\n")); return; case CS_SUSPENDED: call_state = CS_CONNECTED; GNUNET_CONVERSATION_call_resume (call, speaker, mic); return; } } switch (phone_state) { case PS_LOOKUP_EGO: case PS_ERROR: FPRINTF (stderr, "%s", _("There is no call that could be resumed right now.\n")); return; case PS_LISTEN: /* expected state, do resume logic */ break; case PS_ACCEPTED: FPRINTF (stderr, _("Already talking with `%s', cannot resume a call right now.\n"), peer_name); return; } GNUNET_assert (NULL == cl_active); cl = cl_head; if (NULL == cl) { FPRINTF (stderr, _("There is no incoming call to resume here!\n")); return; } if ( (NULL != cl->next) || (NULL != args) ) { for (cl = cl_head; NULL != cl; cl = cl->next) { GNUNET_snprintf (buf, sizeof (buf), "%u", cl->caller_num); if (0 == strcmp (buf, args)) break; } } if (NULL == cl) { FPRINTF (stderr, _("There is no incoming call `%s' to resume right now!\n"), args); return; } cl_active = cl; GNUNET_CONVERSATION_caller_resume (cl_active->caller, speaker, mic); phone_state = PS_ACCEPTED; } /** * Rejecting a call * * @param args arguments given to the command */ static void do_reject (const char *args) { struct CallList *cl; char buf[32]; if (NULL != call) { GNUNET_CONVERSATION_call_stop (call); call = NULL; return; } switch (phone_state) { case PS_LOOKUP_EGO: case PS_ERROR: FPRINTF (stderr, "%s", _("There is no call that could be cancelled right now.\n")); return; case PS_LISTEN: /* look for active incoming calls to refuse */ cl = cl_head; if (NULL == cl) { FPRINTF (stderr, _("There is no incoming call to refuse here!\n")); return; } if ( (NULL != cl->next) || (NULL != args) ) { for (cl = cl_head; NULL != cl; cl = cl->next) { GNUNET_snprintf (buf, sizeof (buf), "%u", cl->caller_num); if (0 == strcmp (buf, args)) break; } } if (NULL == cl) { FPRINTF (stderr, _("There is no incoming call `%s' to refuse right now!\n"), args); return; } GNUNET_CONVERSATION_caller_hang_up (cl->caller); GNUNET_CONTAINER_DLL_remove (cl_head, cl_tail, cl); GNUNET_free (cl->caller_id); GNUNET_free (cl); break; case PS_ACCEPTED: /* expected state, do rejection logic */ GNUNET_assert (NULL != cl_active); GNUNET_CONVERSATION_caller_hang_up (cl_active->caller); cl_active = NULL; phone_state = PS_LISTEN; break; } } /** * List of supported commands. */ static struct VoipCommand commands[] = { {"/address", &do_address, gettext_noop ("Use `/address' to find out which address this phone should have in GNS")}, {"/call", &do_call, gettext_noop ("Use `/call USER.gnu' to call USER")}, {"/accept", &do_accept, gettext_noop ("Use `/accept #NUM' to accept incoming call #NUM")}, {"/suspend", &do_suspend, gettext_noop ("Use `/suspend' to suspend the active call")}, {"/resume", &do_resume, gettext_noop ("Use `/resume [#NUM]' to resume a call, #NUM is needed to resume incoming calls, no argument is needed to resume the current outgoing call.")}, {"/cancel", &do_reject, gettext_noop ("Use `/cancel' to reject or terminate a call")}, {"/status", &do_status, gettext_noop ("Use `/status' to print status information")}, {"/quit", &do_quit, gettext_noop ("Use `/quit' to terminate gnunet-conversation")}, {"/help", &do_help, gettext_noop ("Use `/help command' to get help for a specific command")}, {"", &do_unknown, NULL}, {NULL, NULL, NULL}, }; /** * Action function to print help for the command shell. * * @param args arguments given to the command */ static void do_help (const char *args) { unsigned int i; i = 0; while ( (NULL != args) && (0 != strlen (args)) && (commands[i].Action != &do_help)) { if (0 == strncasecmp (&args[1], &commands[i].command[1], strlen (args) - 1)) { FPRINTF (stdout, "%s\n", gettext (commands[i].helptext)); return; } i++; } i = 0; FPRINTF (stdout, "%s", "Available commands:\n"); while (commands[i].Action != &do_help) { FPRINTF (stdout, "%s\n", gettext (commands[i].command)); i++; } FPRINTF (stdout, "%s", "\n"); FPRINTF (stdout, "%s\n", gettext (commands[i].helptext)); } /** * Task run during shutdown. * * @param cls NULL * @param tc unused */ static void do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { #ifdef WINDOWS if (NULL != stdin_hlp) { GNUNET_HELPER_stop (stdin_hlp, GNUNET_NO); stdin_hlp = NULL; } #endif if (NULL != call) { GNUNET_CONVERSATION_call_stop (call); call = NULL; } if (NULL != phone) { GNUNET_CONVERSATION_phone_destroy (phone); phone = NULL; } if (GNUNET_SCHEDULER_NO_TASK != handle_cmd_task) { GNUNET_SCHEDULER_cancel (handle_cmd_task); handle_cmd_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != id) { GNUNET_IDENTITY_disconnect (id); id = NULL; } GNUNET_SPEAKER_destroy (speaker); speaker = NULL; GNUNET_MICROPHONE_destroy (mic); mic = NULL; GNUNET_free (ego_name); ego_name = NULL; GNUNET_free_non_null (peer_name); phone_state = PS_ERROR; } static void handle_command_string (char *message, size_t str_len) { size_t i; const char *ptr; if (0 == str_len) return; if (message[str_len - 1] == '\n') message[str_len - 1] = '\0'; if (message[str_len - 2] == '\r') message[str_len - 2] = '\0'; if (0 == strlen (message)) return; i = 0; while ((NULL != commands[i].command) && (0 != strncasecmp (commands[i].command, message, strlen (commands[i].command)))) i++; ptr = &message[strlen (commands[i].command)]; while (isspace ((int) *ptr)) ptr++; if ('\0' == *ptr) ptr = NULL; commands[i].Action (ptr); } #ifdef WINDOWS int console_reader_chars (void *cls, void *client, const struct GNUNET_MessageHeader *message) { char *chars; size_t str_size; switch (ntohs (message->type)) { case GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS: chars = (char *) &message[1]; str_size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); if (chars[str_size - 1] != '\0') return GNUNET_SYSERR; /* FIXME: is it ok that we pass part of a const struct to * this function that may mangle the contents? */ handle_command_string (chars, str_size - 1); break; default: GNUNET_break (0); break; } return GNUNET_OK; } #endif /** * Task to handle commands from the terminal. * * @param cls NULL * @param tc scheduler context */ static void handle_command (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { char message[MAX_MESSAGE_LENGTH + 1]; handle_cmd_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdin_fh, &handle_command, NULL); /* read message from command line and handle it */ memset (message, 0, MAX_MESSAGE_LENGTH + 1); if (NULL == fgets (message, MAX_MESSAGE_LENGTH, stdin)) return; handle_command_string (message, strlen (message)); } /** * Function called by identity service with information about egos. * * @param cls NULL * @param ego ego handle * @param ctx unused * @param name name of the ego */ static void identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { if (NULL == name) return; if (ego == caller_id) { if (verbose) FPRINTF (stdout, _("Name of our ego changed to `%s'\n"), name); GNUNET_free (ego_name); ego_name = GNUNET_strdup (name); return; } if (0 != strcmp (name, ego_name)) return; if (NULL == ego) { if (verbose) FPRINTF (stdout, _("Our ego `%s' was deleted!\n"), ego_name); caller_id = NULL; return; } caller_id = ego; GNUNET_CONFIGURATION_set_value_number (cfg, "CONVERSATION", "LINE", line); start_phone (); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { cfg = GNUNET_CONFIGURATION_dup (c); speaker = GNUNET_SPEAKER_create_from_hardware (cfg); mic = GNUNET_MICROPHONE_create_from_hardware (cfg); if (NULL == ego_name) { FPRINTF (stderr, "%s", _("You must specify the NAME of an ego to use\n")); return; } id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL); #ifdef WINDOWS if (stdin_fh == NULL) { static char cpid[64]; static char *args[] = {"gnunet-helper-w32-console.exe", "chars", XSTRINGIFY (MAX_MESSAGE_LENGTH), cpid, NULL}; snprintf (cpid, 64, "%d", GetCurrentProcessId ()); stdin_hlp = GNUNET_HELPER_start ( GNUNET_NO, "gnunet-helper-w32-console", args, console_reader_chars, NULL, NULL); if (NULL == stdin_hlp) { FPRINTF (stderr, "%s", _("Failed to start gnunet-helper-w32-console\n")); return; } } else #endif handle_cmd_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI, &handle_command, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task, NULL); } /** * The main function to conversation. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'e', "ego", "NAME", gettext_noop ("sets the NAME of the ego to use for the phone (and name resolution)"), 1, &GNUNET_GETOPT_set_string, &ego_name}, {'p', "phone", "LINE", gettext_noop ("sets the LINE to use for the phone"), 1, &GNUNET_GETOPT_set_uint, &line}, GNUNET_GETOPT_OPTION_END }; int ret; #ifndef WINDOWS int flags; flags = fcntl (0, F_GETFL, 0); flags |= O_NONBLOCK; fcntl (0, F_SETFL, flags); stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0); #else if (FILE_TYPE_CHAR == GetFileType ((HANDLE) _get_osfhandle (0))) { stdin_fh = NULL; } else stdin_fh = GNUNET_DISK_get_handle_from_int_fd (0); #endif if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-conversation", gettext_noop ("Enables having a conversation with other GNUnet users."), options, &run, NULL); GNUNET_free ((void *) argv); if (NULL != cfg) { GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; } return (GNUNET_OK == ret) ? 0 : 1; } /* end of gnunet-conversation.c */ gnunet-0.10.1/src/conversation/gnunet-helper-audio-playback.c0000644000175000017500000005122012267431203021117 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/gnunet-helper-audio-playback.c * @brief program to playback audio data to the speaker * @author Siomon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "conversation.h" #include "gnunet_constants.h" #include "gnunet_core_service.h" #include #include #include #include #include #include #include #define DEBUG_READ_PURE_OGG 1 #define DEBUG_DUMP_DECODED_OGG 1 #define MAXLINE 4096 #define SAMPLING_RATE 48000 #define CHANNELS 1 /* 120ms at 48000 */ #define MAX_FRAME_SIZE (960 * 6) /** * Pulseaudio specification. May change in the future. */ static pa_sample_spec sample_spec = { .format = PA_SAMPLE_FLOAT32LE, .rate = SAMPLING_RATE, .channels = CHANNELS }; #ifdef DEBUG_DUMP_DECODED_OGG static int dump_to_stdout; #endif /** * Pulseaudio mainloop api */ static pa_mainloop_api *mainloop_api; /** * Pulseaudio threaded mainloop */ static pa_threaded_mainloop *m; /** * Pulseaudio context */ static pa_context *context; /** * Pulseaudio output stream */ static pa_stream *stream_out; /** * OPUS decoder */ static OpusDecoder *dec; /** * PCM data buffer */ static float *pcm_buffer; /** * Number of samples for one frame */ static int frame_size; /** * Pipe we use to signal the main loop that we are ready to receive. */ static int ready_pipe[2]; /** * Ogg I/O state. */ static ogg_sync_state oy; /** * Ogg stream state. */ static ogg_stream_state os; static int channels; static int preskip; static float gain; GNUNET_NETWORK_STRUCT_BEGIN /* OggOpus spec says the numbers must be in little-endian order */ struct OpusHeadPacket { uint8_t magic[8]; uint8_t version; uint8_t channels; uint16_t preskip GNUNET_PACKED; uint32_t sampling_rate GNUNET_PACKED; uint16_t gain GNUNET_PACKED; uint8_t channel_mapping; }; GNUNET_NETWORK_STRUCT_END /*Process an Opus header and setup the opus decoder based on it. It takes several pointers for header values which are needed elsewhere in the code.*/ static OpusDecoder * process_header (ogg_packet *op) { int err; OpusDecoder *dec; struct OpusHeadPacket header; if (op->bytes < sizeof (header)) return NULL; memcpy (&header, op->packet, sizeof (header)); header.preskip = GNUNET_le16toh (header.preskip); header.sampling_rate = GNUNET_le32toh (header.sampling_rate); header.gain = GNUNET_le16toh (header.gain); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Header: v%u, %u-ch, skip %u, %uHz, %u gain\n", header.version, header.channels, header.preskip, header.sampling_rate, header.gain); channels = header.channels; preskip = header.preskip; if (header.channel_mapping != 0) { fprintf (stderr, "This implementation does not support non-mono streams\n"); return NULL; } dec = opus_decoder_create (SAMPLING_RATE, channels, &err); if (OPUS_OK != err) { fprintf (stderr, "Cannot create encoder: %s\n", opus_strerror (err)); return NULL; } if (!dec) { fprintf (stderr, "Decoder initialization failed: %s\n", opus_strerror (err)); return NULL; } if (0 != header.gain) { /*Gain API added in a newer libopus version, if we don't have it we apply the gain ourselves. We also add in a user provided manual gain at the same time.*/ int gainadj = (int) header.gain; err = opus_decoder_ctl (dec, OPUS_SET_GAIN (gainadj)); if(OPUS_UNIMPLEMENTED == err) { gain = pow (10.0, gainadj / 5120.0); } else if (OPUS_OK != err) { fprintf (stderr, "Error setting gain: %s\n", opus_strerror (err)); return NULL; } } return dec; } #ifdef DEBUG_DUMP_DECODED_OGG static size_t fwrite_le32(opus_int32 i32, FILE *file) { unsigned char buf[4]; buf[0]=(unsigned char)(i32&0xFF); buf[1]=(unsigned char)(i32>>8&0xFF); buf[2]=(unsigned char)(i32>>16&0xFF); buf[3]=(unsigned char)(i32>>24&0xFF); return fwrite(buf,4,1,file); } static size_t fwrite_le16(int i16, FILE *file) { unsigned char buf[2]; buf[0]=(unsigned char)(i16&0xFF); buf[1]=(unsigned char)(i16>>8&0xFF); return fwrite(buf,2,1,file); } static int write_wav_header() { int ret; FILE *file = stdout; ret = fprintf (file, "RIFF") >= 0; ret &= fwrite_le32 (0x7fffffff, file); ret &= fprintf (file, "WAVEfmt ") >= 0; ret &= fwrite_le32 (16, file); ret &= fwrite_le16 (1, file); ret &= fwrite_le16 (channels, file); ret &= fwrite_le32 (SAMPLING_RATE, file); ret &= fwrite_le32 (2*channels*SAMPLING_RATE, file); ret &= fwrite_le16 (2*channels, file); ret &= fwrite_le16 (16, file); ret &= fprintf (file, "data") >= 0; ret &= fwrite_le32 (0x7fffffff, file); return !ret ? -1 : 16; } #endif static int64_t audio_write (int64_t maxout) { int64_t sampout = 0; int tmp_skip; unsigned out_len; unsigned to_write; float *output; #ifdef DEBUG_DUMP_DECODED_OGG static int wrote_wav_header; if (dump_to_stdout && !wrote_wav_header) { write_wav_header (); wrote_wav_header = 1; } #endif maxout = 0 > maxout ? 0 : maxout; do { tmp_skip = (preskip > frame_size) ? (int) frame_size : preskip; preskip -= tmp_skip; output = pcm_buffer + channels * tmp_skip; out_len = frame_size - tmp_skip; if (out_len > MAX_FRAME_SIZE) exit (6); frame_size = 0; to_write = out_len < maxout ? out_len : (unsigned) maxout; if (0 < maxout) { int64_t wrote = 0; wrote = to_write; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing %u * %u * %u = %u bytes into PA\n", to_write, channels, sizeof (float), to_write * channels * sizeof (float)); #ifdef DEBUG_DUMP_DECODED_OGG if (dump_to_stdout) { # define fminf(_x,_y) ((_x)<(_y)?(_x):(_y)) # define fmaxf(_x,_y) ((_x)>(_y)?(_x):(_y)) # define float2int(flt) ((int)(floor(.5+flt))) int i; int16_t *out = alloca(sizeof(short)*MAX_FRAME_SIZE*channels); for (i=0;i<(int)out_len*channels;i++) out[i]=(short)float2int(fmaxf(-32768,fminf(output[i]*32768.f,32767))); fwrite (out, 2 * channels, out_lenquit (mainloop_api, ret); exit (ret); } static void ogg_demux_and_decode () { ogg_page og; static int stream_init; int64_t page_granule = 0; ogg_packet op; static int has_opus_stream; static int has_tags_packet; static int32_t opus_serialno; static int64_t link_out; static int64_t packet_count; int eos = 0; static int total_links; static int gran_offset; while (1 == ogg_sync_pageout (&oy, &og)) { if (0 == stream_init) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initialized the stream\n"); ogg_stream_init (&os, ogg_page_serialno (&og)); stream_init = 1; } if (ogg_page_serialno (&og) != os.serialno) { /* so all streams are read. */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Re-set serial number\n"); ogg_stream_reset_serialno (&os, ogg_page_serialno (&og)); } /*Add page to the bitstream*/ ogg_stream_pagein (&os, &og); page_granule = ogg_page_granulepos (&og); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reading page that ends at %" PRId64 "\n", page_granule); /*Extract all available packets*/ while (1 == ogg_stream_packetout (&os, &op)) { /*OggOpus streams are identified by a magic string in the initial stream header.*/ if (op.b_o_s && op.bytes >= 8 && !memcmp (op.packet, "OpusHead", 8)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got Opus Header\n"); if (has_opus_stream && has_tags_packet) { /*If we're seeing another BOS OpusHead now it means the stream is chained without an EOS. This can easily happen if record helper is terminated unexpectedly. */ has_opus_stream = 0; if (dec) opus_decoder_destroy (dec); dec = NULL; fprintf (stderr, "\nWarning: stream %" PRId64 " ended without EOS and a new stream began.\n", (int64_t) os.serialno); } if (!has_opus_stream) { if (packet_count > 0 && opus_serialno == os.serialno) { fprintf (stderr, "\nError: Apparent chaining without changing serial number (%" PRId64 "==%" PRId64 ").\n", (int64_t) opus_serialno, (int64_t) os.serialno); quit(1); } opus_serialno = os.serialno; has_opus_stream = 1; has_tags_packet = 0; link_out = 0; packet_count = 0; eos = 0; total_links++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got header for stream %" PRId64 ", this is %dth link\n", (int64_t) opus_serialno, total_links); } else { fprintf (stderr, "\nWarning: ignoring opus stream %" PRId64 "\n", (int64_t) os.serialno); } } if (!has_opus_stream || os.serialno != opus_serialno) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "breaking out\n"); break; } /*If first packet in a logical stream, process the Opus header*/ if (0 == packet_count) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoding header\n"); dec = process_header (&op); if (!dec) quit (1); if (0 != ogg_stream_packetout (&os, &op) || 255 == og.header[og.header_len - 1]) { /*The format specifies that the initial header and tags packets are on their own pages. To aid implementors in discovering that their files are wrong we reject them explicitly here. In some player designs files like this would fail even without an explicit test.*/ fprintf (stderr, "Extra packets on initial header page. Invalid stream.\n"); quit (1); } /*Remember how many samples at the front we were told to skip so that we can adjust the timestamp counting.*/ gran_offset = preskip; if (!pcm_buffer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Allocating %u * %u * %u = %u bytes of buffer space\n", MAX_FRAME_SIZE, channels, sizeof (float), MAX_FRAME_SIZE * channels * sizeof (float)); pcm_buffer = pa_xmalloc (sizeof (float) * MAX_FRAME_SIZE * channels); } } else if (1 == packet_count) { has_tags_packet = 1; if (0 != ogg_stream_packetout (&os, &op) || 255 == og.header[og.header_len - 1]) { fprintf (stderr, "Extra packets on initial tags page. Invalid stream.\n"); quit (1); } } else { int ret; int64_t maxout; int64_t outsamp; /*End of stream condition*/ if (op.e_o_s && os.serialno == opus_serialno) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got EOS\n"); eos = 1; /* don't care for anything except opus eos */ } /*Decode Opus packet*/ ret = opus_decode_float (dec, (const unsigned char *) op.packet, op.bytes, pcm_buffer, MAX_FRAME_SIZE, 0); /*If the decoder returned less than zero, we have an error.*/ if (0 > ret) { fprintf (stderr, "Decoding error: %s\n", opus_strerror (ret)); break; } frame_size = ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decoded %d bytes/channel (%d bytes) from %u compressed bytes\n", ret, ret * channels, op.bytes); /*Apply header gain, if we're not using an opus library new enough to do this internally.*/ if (0 != gain) { int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Applying gain %f\n", gain); for (i = 0; i < frame_size * channels; i++) pcm_buffer[i] *= gain; } /*This handles making sure that our output duration respects the final end-trim by not letting the output sample count get ahead of the granpos indicated value.*/ maxout = ((page_granule - gran_offset) * SAMPLING_RATE / 48000) - link_out; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing audio packet %" PRId64 ", at most %" PRId64 " samples\n", packet_count, maxout); outsamp = audio_write (0 > maxout ? 0 : maxout); link_out += outsamp; } packet_count++; } if (eos) { has_opus_stream = 0; if (dec) opus_decoder_destroy (dec); dec = NULL; } } } /** * Message callback */ static int stdin_receiver (void *cls, void *client, const struct GNUNET_MessageHeader *msg) { struct AudioMessage *audio; char *data; size_t payload_len; switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO: audio = (struct AudioMessage *) msg; payload_len = ntohs (audio->header.size) - sizeof (struct AudioMessage); /*Get the ogg buffer for writing*/ data = ogg_sync_buffer (&oy, payload_len); /*Read bitstream from input file*/ memcpy (data, (const unsigned char *) &audio[1], payload_len); ogg_sync_wrote (&oy, payload_len); ogg_demux_and_decode (); break; default: break; } return GNUNET_OK; } /** * Callback when data is there for playback */ static void stream_write_callback (pa_stream * s, size_t length, void *userdata) { /* unblock 'main' */ if (-1 != ready_pipe[1]) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unblocking main loop!\n"); write (ready_pipe[1], "r", 1); } } /** * Exit callback for SIGTERM and SIGINT */ static void exit_signal_callback (pa_mainloop_api * m, pa_signal_event * e, int sig, void *userdata) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("gnunet-helper-audio-playback - Got signal, exiting\n")); quit (1); } /** * Pulseaudio stream state callback */ static void context_state_callback (pa_context * c, void *userdata) { int p; GNUNET_assert (NULL != c); switch (pa_context_get_state (c)) { case PA_CONTEXT_CONNECTING: case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; case PA_CONTEXT_READY: { GNUNET_assert (!stream_out); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connection established.\n")); if (!(stream_out = pa_stream_new (c, "GNUNET VoIP playback", &sample_spec, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_new() failed: %s\n"), pa_strerror (pa_context_errno (c))); goto fail; } pa_stream_set_write_callback (stream_out, &stream_write_callback, NULL); if ((p = pa_stream_connect_playback (stream_out, NULL, NULL, PA_STREAM_ADJUST_LATENCY | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL)) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_connect_playback() failed: %s\n"), pa_strerror (pa_context_errno (c))); goto fail; } break; } case PA_CONTEXT_TERMINATED: quit (0); break; case PA_CONTEXT_FAILED: default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Connection failure: %s\n"), pa_strerror (pa_context_errno (c))); goto fail; } return; fail: quit (1); } /** * Pulseaudio initialization */ static void pa_init () { int r; if (!pa_sample_spec_valid (&sample_spec)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Wrong Spec\n")); } /* set up threaded playback mainloop */ if (!(m = pa_threaded_mainloop_new ())) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_new() failed.\n")); } mainloop_api = pa_threaded_mainloop_get_api (m); /* listen to signals */ r = pa_signal_init (mainloop_api); GNUNET_assert (r == 0); pa_signal_new (SIGINT, exit_signal_callback, NULL); pa_signal_new (SIGTERM, exit_signal_callback, NULL); /* connect to the main pulseaudio context */ if (!(context = pa_context_new (mainloop_api, "GNUnet VoIP"))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_new() failed.\n")); } pa_context_set_state_callback (context, context_state_callback, NULL); if (pa_context_connect (context, NULL, 0, NULL) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_context_connect() failed: %s\n"), pa_strerror (pa_context_errno (context))); } if (pa_threaded_mainloop_start (m) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_mainloop_run() failed.\n")); } } static void ogg_init () { ogg_sync_init (&oy); } static void drain_callback (pa_stream*s, int success, void *userdata) { pa_threaded_mainloop_signal (m, 0); } /** * The main function for the playback helper. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *argv[]) { static unsigned long long toff; char readbuf[MAXLINE]; struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst; char c; ssize_t ret; #ifdef DEBUG_READ_PURE_OGG int read_pure_ogg = getenv ("GNUNET_READ_PURE_OGG") ? 1 : 0; #endif GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("gnunet-helper-audio-playback", "WARNING", NULL)); if (0 != pipe (ready_pipe)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "pipe"); return 1; } stdin_mst = GNUNET_SERVER_mst_create (&stdin_receiver, NULL); ogg_init (); pa_init (); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for PulseAudio to be ready.\n"); GNUNET_assert (1 == read (ready_pipe[0], &c, 1)); close (ready_pipe[0]); close (ready_pipe[1]); ready_pipe[0] = -1; ready_pipe[1] = -1; #ifdef DEBUG_DUMP_DECODED_OGG dump_to_stdout = getenv ("GNUNET_DUMP_DECODED_OGG") ? 1 : 0; #endif while (1) { ret = read (0, readbuf, sizeof (readbuf)); toff += ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d bytes of audio data (total: %llu)\n", (int) ret, toff); if (0 > ret) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Read error from STDIN: %s\n"), strerror (errno)); break; } if (0 == ret) break; #ifdef DEBUG_READ_PURE_OGG if (read_pure_ogg) { char *data = ogg_sync_buffer (&oy, ret); memcpy (data, readbuf, ret); ogg_sync_wrote (&oy, ret); ogg_demux_and_decode (); } else #endif GNUNET_SERVER_mst_receive (stdin_mst, NULL, readbuf, ret, GNUNET_NO, GNUNET_NO); } GNUNET_SERVER_mst_destroy (stdin_mst); if (stream_out) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Locking\n"); pa_threaded_mainloop_lock (m); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Draining\n"); pa_operation *o = pa_stream_drain (stream_out, drain_callback, NULL); while (pa_operation_get_state (o) == PA_OPERATION_RUNNING) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting\n"); pa_threaded_mainloop_wait (m); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unreffing\n"); pa_operation_unref (o); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unlocking\n"); pa_threaded_mainloop_unlock (m); } return 0; } gnunet-0.10.1/src/conversation/speaker.c0000644000175000017500000001034712225777501015126 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/speaker.c * @brief API to access an audio speaker; provides access to hardware speakers * @author Simon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_speaker_lib.h" #include "conversation.h" /** * Internal data structures for the speaker. */ struct Speaker { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for the playback helper */ struct GNUNET_HELPER_Handle *playback_helper; }; /** * Function that enables a speaker. * * @param cls closure with the `struct Speaker` * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int enable (void *cls) { struct Speaker *spe = cls; static char *playback_helper_argv[] = { "gnunet-helper-audio-playback", NULL }; spe->playback_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-audio-playback", playback_helper_argv, NULL, NULL, spe); if (NULL == spe->playback_helper) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not start playback audio helper.\n")); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Function that disables a speaker. * * @param cls closure with the `struct Speaker` */ static void disable (void *cls) { struct Speaker *spe = cls; if (NULL == spe->playback_helper) { GNUNET_break (0); return; } GNUNET_break (GNUNET_OK == GNUNET_HELPER_kill (spe->playback_helper, GNUNET_NO)); GNUNET_HELPER_destroy (spe->playback_helper); spe->playback_helper = NULL; } /** * Function to destroy a speaker. * * @param cls closure with the `struct Speaker` */ static void destroy (void *cls) { struct Speaker *spe = cls; if (NULL != spe->playback_helper) disable (spe); } /** * Function to cause a speaker to play audio data. * * @param cls clsoure with the `struct Speaker` * @param data_size number of bytes in @a data * @param data audio data to play, format is * opaque to the API but should be OPUS. */ static void play (void *cls, size_t data_size, const void *data) { struct Speaker *spe = cls; char buf[sizeof (struct AudioMessage) + data_size]; struct AudioMessage *am; if (NULL == spe->playback_helper) { GNUNET_break (0); return; } am = (struct AudioMessage *) buf; am->header.size = htons (sizeof (struct AudioMessage) + data_size); am->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO); memcpy (&am[1], data, data_size); (void) GNUNET_HELPER_send (spe->playback_helper, &am->header, GNUNET_NO, NULL, NULL); } /** * Create a speaker that corresponds to the speaker hardware * of our system. * * @param cfg configuration to use * @return NULL on error */ struct GNUNET_SPEAKER_Handle * GNUNET_SPEAKER_create_from_hardware (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_SPEAKER_Handle *speaker; struct Speaker *spe; spe = GNUNET_new (struct Speaker); spe->cfg = cfg; speaker = GNUNET_new (struct GNUNET_SPEAKER_Handle); speaker->cls = spe; speaker->enable_speaker = &enable; speaker->play = &play; speaker->disable_speaker = &disable; speaker->destroy_speaker = &destroy; return speaker; } /** * Destroy a speaker. * * @param speaker speaker to destroy */ void GNUNET_SPEAKER_destroy (struct GNUNET_SPEAKER_Handle *speaker) { speaker->destroy_speaker (speaker->cls); GNUNET_free (speaker); } /* end of speaker.c */ gnunet-0.10.1/src/conversation/gnunet-service-conversation.c0000644000175000017500000013426112261236532021136 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/gnunet-service-conversation.c * @brief conversation service implementation * @author Simon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_mesh_service.h" #include "gnunet_conversation_service.h" #include "conversation.h" /** * How long is our signature on a call valid? Needs to be long enough for time zone * differences and network latency to not matter. No strong need for it to be short, * but we simply like all signatures to eventually expire. */ #define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS /** * A line connects a local client with a mesh channel (or, if it is an * open line, is waiting for a mesh channel). */ struct Line; /** * The possible connection status */ enum ChannelStatus { /** * Our phone is ringing, waiting for the client to pick up. */ CS_CALLEE_RINGING, /** * We are talking! */ CS_CALLEE_CONNECTED, /** * We're in shutdown, sending hangup messages before cleaning up. */ CS_CALLEE_SHUTDOWN, /** * We are waiting for the phone to be picked up. */ CS_CALLER_CALLING, /** * We are talking! */ CS_CALLER_CONNECTED, /** * We're in shutdown, sending hangup messages before cleaning up. */ CS_CALLER_SHUTDOWN }; /** * A `struct Channel` represents a mesh channel, which is a P2P * connection to another conversation service. Multiple channels can * be attached the the same `struct Line`, which represents a local * client. We keep them in a linked list. */ struct Channel { /** * This is a DLL. */ struct Channel *next; /** * This is a DLL. */ struct Channel *prev; /** * Line associated with the channel. */ struct Line *line; /** * Handle for the reliable channel (contol data) */ struct GNUNET_MESH_Channel *channel_reliable; /** * Handle for unreliable channel (audio data) */ struct GNUNET_MESH_Channel *channel_unreliable; /** * Transmit handle for pending audio messages */ struct GNUNET_MESH_TransmitHandle *unreliable_mth; /** * Message queue for control messages */ struct GNUNET_MQ_Handle *reliable_mq; /** * Target of the line, if we are the caller. */ struct GNUNET_PeerIdentity target; /** * Temporary buffer for audio data. */ void *audio_data; /** * Number of bytes in @e audio_data. */ size_t audio_size; /** * Channel identifier. */ uint32_t cid; /** * Remote line number. */ uint32_t remote_line; /** * Current status of this line. */ enum ChannelStatus status; /** * #GNUNET_YES if the channel was suspended by the other peer. */ int8_t suspended_remote; /** * #GNUNET_YES if the channel was suspended by the local client. */ int8_t suspended_local; }; /** * A `struct Line` connects a local client with mesh channels. */ struct Line { /** * Kept in a DLL. */ struct Line *next; /** * Kept in a DLL. */ struct Line *prev; /** * This is a DLL. */ struct Channel *channel_head; /** * This is a DLL. */ struct Channel *channel_tail; /** * Handle to the line client. */ struct GNUNET_SERVER_Client *client; /** * Generator for channel IDs. */ uint32_t cid_gen; /** * Our line number. */ uint32_t local_line; }; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Notification context containing all connected clients. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Handle for mesh */ static struct GNUNET_MESH_Handle *mesh; /** * Identity of this peer. */ static struct GNUNET_PeerIdentity my_identity; /** * Head of DLL of active lines. */ static struct Line *lines_head; /** * Tail of DLL of active lines. */ static struct Line *lines_tail; /** * Counter for generating local line numbers. * FIXME: randomize generation in the future * to eliminate information leakage. */ static uint32_t local_line_cnt; /** * Function to register a phone. * * @param cls closure, NULL * @param client the client from which the message is * @param message the message from the client */ static void handle_client_register_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ClientPhoneRegisterMessage *msg; struct Line *line; msg = (const struct ClientPhoneRegisterMessage *) message; line = GNUNET_SERVER_client_get_user_context (client, struct Line); if (NULL != line) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } line = GNUNET_new (struct Line); line->client = client; GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_client_set_user_context (client, line); GNUNET_CONTAINER_DLL_insert (lines_head, lines_tail, line); line->local_line = ntohl (msg->line) & (~ (1 << 31)); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Function to handle a pickup request message from the client * * @param cls closure, NULL * @param client the client from which the message is * @param message the message from the client */ static void handle_client_pickup_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ClientPhonePickupMessage *msg; struct GNUNET_MQ_Envelope *e; struct MeshPhonePickupMessage *mppm; struct Line *line; struct Channel *ch; msg = (const struct ClientPhonePickupMessage *) message; line = GNUNET_SERVER_client_get_user_context (client, struct Line); if (NULL == line) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } for (ch = line->channel_head; NULL != ch; ch = ch->next) if (msg->cid == ch->cid) break; if (NULL == ch) { /* could have been destroyed asynchronously, ignore message */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); GNUNET_SERVER_receive_done (client, GNUNET_YES); return; } switch (ch->status) { case CS_CALLEE_RINGING: ch->status = CS_CALLEE_CONNECTED; break; case CS_CALLEE_CONNECTED: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; case CS_CALLEE_SHUTDOWN: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ignoring client's PICKUP message, line is in SHUTDOWN\n"); break; case CS_CALLER_CALLING: case CS_CALLER_CONNECTED: case CS_CALLER_SHUTDOWN: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_break (CS_CALLEE_CONNECTED == ch->status); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending PICK_UP message to mesh\n"); e = GNUNET_MQ_msg (mppm, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP); GNUNET_MQ_send (ch->reliable_mq, e); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Destroy a channel. * * @param ch channel to destroy. */ static void destroy_line_mesh_channels (struct Channel *ch) { struct Line *line = ch->line; struct GNUNET_MESH_Channel *t; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying mesh channels\n"); if (NULL != ch->reliable_mq) { GNUNET_MQ_destroy (ch->reliable_mq); ch->reliable_mq = NULL; } if (NULL != ch->unreliable_mth) { GNUNET_MESH_notify_transmit_ready_cancel (ch->unreliable_mth); ch->unreliable_mth = NULL; } if (NULL != (t = ch->channel_unreliable)) { ch->channel_unreliable = NULL; GNUNET_MESH_channel_destroy (t); } if (NULL != (t = ch->channel_reliable)) { ch->channel_reliable = NULL; GNUNET_MESH_channel_destroy (t); } GNUNET_CONTAINER_DLL_remove (line->channel_head, line->channel_tail, ch); GNUNET_free_non_null (ch->audio_data); GNUNET_free (ch); } /** * We are done signalling shutdown to the other peer. Close down * the channel. * * @param cls the `struct Channel` to reset/terminate */ static void mq_done_finish_caller_shutdown (void *cls) { struct Channel *ch = cls; switch (ch->status) { case CS_CALLEE_RINGING: GNUNET_break (0); break; case CS_CALLEE_CONNECTED: GNUNET_break (0); break; case CS_CALLEE_SHUTDOWN: destroy_line_mesh_channels (ch); break; case CS_CALLER_CALLING: GNUNET_break (0); break; case CS_CALLER_CONNECTED: GNUNET_break (0); break; case CS_CALLER_SHUTDOWN: destroy_line_mesh_channels (ch); break; } } /** * Function to handle a hangup request message from the client * * @param cls closure, NULL * @param client the client from which the message is * @param message the message from the client */ static void handle_client_hangup_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ClientPhoneHangupMessage *msg; struct GNUNET_MQ_Envelope *e; struct MeshPhoneHangupMessage *mhum; struct Line *line; struct Channel *ch; msg = (const struct ClientPhoneHangupMessage *) message; line = GNUNET_SERVER_client_get_user_context (client, struct Line); if (NULL == line) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } for (ch = line->channel_head; NULL != ch; ch = ch->next) if (msg->cid == ch->cid) break; if (NULL == ch) { /* could have been destroyed asynchronously, ignore message */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } switch (ch->status) { case CS_CALLEE_RINGING: ch->status = CS_CALLEE_SHUTDOWN; break; case CS_CALLEE_CONNECTED: ch->status = CS_CALLEE_SHUTDOWN; break; case CS_CALLEE_SHUTDOWN: /* maybe the other peer closed asynchronously... */ GNUNET_SERVER_receive_done (client, GNUNET_OK); return; case CS_CALLER_CALLING: ch->status = CS_CALLER_SHUTDOWN; break; case CS_CALLER_CONNECTED: ch->status = CS_CALLER_SHUTDOWN; break; case CS_CALLER_SHUTDOWN: /* maybe the other peer closed asynchronously... */ GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending HANG_UP message via mesh\n"); e = GNUNET_MQ_msg (mhum, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP); GNUNET_MQ_notify_sent (e, &mq_done_finish_caller_shutdown, ch); GNUNET_MQ_send (ch->reliable_mq, e); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Function to handle a suspend request message from the client * * @param cls closure, NULL * @param client the client from which the message is * @param message the message from the client */ static void handle_client_suspend_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ClientPhoneSuspendMessage *msg; struct GNUNET_MQ_Envelope *e; struct MeshPhoneSuspendMessage *mhum; struct Line *line; struct Channel *ch; msg = (const struct ClientPhoneSuspendMessage *) message; line = GNUNET_SERVER_client_get_user_context (client, struct Line); if (NULL == line) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } for (ch = line->channel_head; NULL != ch; ch = ch->next) if (msg->cid == ch->cid) break; if (NULL == ch) { /* could have been destroyed asynchronously, ignore message */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_YES == ch->suspended_local) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } switch (ch->status) { case CS_CALLEE_RINGING: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; case CS_CALLEE_CONNECTED: ch->suspended_local = GNUNET_YES; break; case CS_CALLEE_SHUTDOWN: /* maybe the other peer closed asynchronously... */ GNUNET_SERVER_receive_done (client, GNUNET_OK); return; case CS_CALLER_CALLING: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; case CS_CALLER_CONNECTED: ch->suspended_local = GNUNET_YES; break; case CS_CALLER_SHUTDOWN: /* maybe the other peer closed asynchronously... */ GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SUSPEND message via mesh\n"); e = GNUNET_MQ_msg (mhum, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_SUSPEND); GNUNET_MQ_send (ch->reliable_mq, e); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Function to handle a resume request message from the client * * @param cls closure, NULL * @param client the client from which the message is * @param message the message from the client */ static void handle_client_resume_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ClientPhoneResumeMessage *msg; struct GNUNET_MQ_Envelope *e; struct MeshPhoneResumeMessage *mhum; struct Line *line; struct Channel *ch; msg = (const struct ClientPhoneResumeMessage *) message; line = GNUNET_SERVER_client_get_user_context (client, struct Line); if (NULL == line) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } for (ch = line->channel_head; NULL != ch; ch = ch->next) if (msg->cid == ch->cid) break; if (NULL == ch) { /* could have been destroyed asynchronously, ignore message */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_YES != ch->suspended_local) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } switch (ch->status) { case CS_CALLEE_RINGING: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; case CS_CALLEE_CONNECTED: ch->suspended_local = GNUNET_NO; break; case CS_CALLEE_SHUTDOWN: /* maybe the other peer closed asynchronously... */ GNUNET_SERVER_receive_done (client, GNUNET_OK); return; case CS_CALLER_CALLING: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; case CS_CALLER_CONNECTED: ch->suspended_local = GNUNET_NO; break; case CS_CALLER_SHUTDOWN: /* maybe the other peer closed asynchronously... */ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending RESUME message via mesh\n"); e = GNUNET_MQ_msg (mhum, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RESUME); GNUNET_MQ_send (ch->reliable_mq, e); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Function to handle call request from the client * * @param cls closure, NULL * @param client the client from which the message is * @param message the message from the client */ static void handle_client_call_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ClientCallMessage *msg; struct Line *line; struct Channel *ch; struct GNUNET_MQ_Envelope *e; struct MeshPhoneRingMessage *ring; msg = (const struct ClientCallMessage *) message; line = GNUNET_SERVER_client_get_user_context (client, struct Line); if (NULL != line) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } line = GNUNET_new (struct Line); line->client = client; line->local_line = (local_line_cnt++) | (1 << 31); GNUNET_SERVER_client_set_user_context (client, line); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_CONTAINER_DLL_insert (lines_head, lines_tail, line); ch = GNUNET_new (struct Channel); ch->line = line; GNUNET_CONTAINER_DLL_insert (line->channel_head, line->channel_tail, ch); ch->target = msg->target; ch->remote_line = ntohl (msg->line); ch->status = CS_CALLER_CALLING; ch->channel_reliable = GNUNET_MESH_channel_create (mesh, ch, &msg->target, GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL, GNUNET_MESH_OPTION_RELIABLE); ch->reliable_mq = GNUNET_MESH_mq_create (ch->channel_reliable); e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING); ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING); ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); GNUNET_CRYPTO_ecdsa_key_get_public (&msg->caller_id, &ring->caller_id); ring->remote_line = msg->line; ring->source_line = htonl (line->local_line); ring->target = msg->target; ring->source = my_identity; ring->expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT)); GNUNET_CRYPTO_ecdsa_sign (&msg->caller_id, &ring->purpose, &ring->signature); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending RING message via mesh\n"); GNUNET_MQ_send (ch->reliable_mq, e); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Transmit audio data via unreliable mesh channel. * * @param cls the `struct Channel` we are transmitting for * @param size number of bytes available in @a buf * @param buf where to copy the data * @return number of bytes copied to @a buf */ static size_t transmit_line_audio (void *cls, size_t size, void *buf) { struct Channel *ch = cls; struct MeshAudioMessage *mam = buf; ch->unreliable_mth = NULL; if ( (NULL == buf) || (size < sizeof (struct MeshAudioMessage) + ch->audio_size) ) { /* eh, other error handling? */ return 0; } mam->header.size = htons (sizeof (struct MeshAudioMessage) + ch->audio_size); mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO); mam->remote_line = htonl (ch->remote_line); mam->source_line = htonl (ch->line->local_line); memcpy (&mam[1], ch->audio_data, ch->audio_size); GNUNET_free (ch->audio_data); ch->audio_data = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %u bytes of audio data from line %u to remote line %u via mesh\n", ch->audio_size, ch->line->local_line, ch->remote_line); return sizeof (struct MeshAudioMessage) + ch->audio_size; } /** * Function to handle audio data from the client * * @param cls closure, NULL * @param client the client from which the message is * @param message the message from the client */ static void handle_client_audio_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ClientAudioMessage *msg; struct Line *line; struct Channel *ch; size_t size; size = ntohs (message->size) - sizeof (struct ClientAudioMessage); msg = (const struct ClientAudioMessage *) message; line = GNUNET_SERVER_client_get_user_context (client, struct Line); if (NULL == line) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } for (ch = line->channel_head; NULL != ch; ch = ch->next) if (msg->cid == ch->cid) break; if (NULL == ch) { /* could have been destroyed asynchronously, ignore message */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel %u not found\n", msg->cid); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } switch (ch->status) { case CS_CALLEE_RINGING: case CS_CALLER_CALLING: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; case CS_CALLEE_CONNECTED: case CS_CALLER_CONNECTED: /* common case, handled below */ break; case CS_CALLEE_SHUTDOWN: case CS_CALLER_SHUTDOWN: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Mesh audio channel in shutdown; audio data dropped\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_YES == ch->suspended_local) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "This channel is suspended locally\n"); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (NULL == ch->channel_unreliable) { GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, _("Mesh audio channel not ready; audio data dropped\n")); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (NULL != ch->unreliable_mth) { /* NOTE: we may want to not do this and instead combine the data */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth insufficient; dropping previous audio data segment with %u bytes\n", (unsigned int) ch->audio_size); GNUNET_MESH_notify_transmit_ready_cancel (ch->unreliable_mth); ch->unreliable_mth = NULL; GNUNET_free (ch->audio_data); ch->audio_data = NULL; } ch->audio_size = size; ch->audio_data = GNUNET_malloc (ch->audio_size); memcpy (ch->audio_data, &msg[1], size); ch->unreliable_mth = GNUNET_MESH_notify_transmit_ready (ch->channel_unreliable, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct MeshAudioMessage) + ch->audio_size, &transmit_line_audio, ch); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * We are done signalling shutdown to the other peer. * Destroy the channel. * * @param cls the `struct GNUNET_MESH_channel` to destroy */ static void mq_done_destroy_channel (void *cls) { struct GNUNET_MESH_Channel *channel = cls; GNUNET_MESH_channel_destroy (channel); } /** * Function to handle a ring message incoming over mesh * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK */ static int handle_mesh_ring_message (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { const struct MeshPhoneRingMessage *msg; struct Line *line; struct Channel *ch; struct GNUNET_MQ_Envelope *e; struct MeshPhoneHangupMessage *hang_up; struct ClientPhoneRingMessage cring; struct GNUNET_MQ_Handle *reliable_mq; msg = (const struct MeshPhoneRingMessage *) message; if ( (msg->purpose.size != htonl (sizeof (struct GNUNET_PeerIdentity) * 2 + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING, &msg->purpose, &msg->signature, &msg->caller_id)) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_MESH_receive_done (channel); /* needed? */ for (line = lines_head; NULL != line; line = line->next) if (line->local_line == ntohl (msg->remote_line)) break; if (NULL == line) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("No available phone for incoming call on line %u, sending HANG_UP signal\n"), ntohl (msg->remote_line)); e = GNUNET_MQ_msg (hang_up, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP); GNUNET_MQ_notify_sent (e, &mq_done_destroy_channel, channel); reliable_mq = GNUNET_MESH_mq_create (channel); GNUNET_MQ_send (reliable_mq, e); /* FIXME: do we need to clean up reliable_mq somehow/somewhere? */ return GNUNET_OK; } ch = GNUNET_new (struct Channel); ch->line = line; GNUNET_CONTAINER_DLL_insert (line->channel_head, line->channel_tail, ch); ch->status = CS_CALLEE_RINGING; ch->remote_line = ntohl (msg->source_line); ch->channel_reliable = channel; ch->reliable_mq = GNUNET_MESH_mq_create (ch->channel_reliable); ch->cid = line->cid_gen++; ch->target = msg->source; *channel_ctx = ch; cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING); cring.header.size = htons (sizeof (cring)); cring.cid = ch->cid; cring.caller_id = msg->caller_id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending RING message to client. CID %u:(%u, %u)\n", ch->cid, ch->remote_line, line->local_line); GNUNET_SERVER_notification_context_unicast (nc, line->client, &cring.header, GNUNET_NO); return GNUNET_OK; } /** * Function to handle a hangup message incoming over mesh * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK */ static int handle_mesh_hangup_message (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; struct Line *line; struct ClientPhoneHangupMessage hup; enum ChannelStatus status; if (NULL == ch) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "HANGUP message received for non-existing line, dropping channel.\n"); return GNUNET_SYSERR; } line = ch->line; *channel_ctx = NULL; hup.header.size = htons (sizeof (hup)); hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); hup.cid = ch->cid; status = ch->status; GNUNET_MESH_receive_done (channel); destroy_line_mesh_channels (ch); switch (status) { case CS_CALLEE_RINGING: case CS_CALLEE_CONNECTED: break; case CS_CALLEE_SHUTDOWN: return GNUNET_OK; case CS_CALLER_CALLING: case CS_CALLER_CONNECTED: break; case CS_CALLER_SHUTDOWN: return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending HANG UP message to client\n"); GNUNET_SERVER_notification_context_unicast (nc, line->client, &hup.header, GNUNET_NO); return GNUNET_OK; } /** * Function to handle a pickup message incoming over mesh * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK */ static int handle_mesh_pickup_message (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; struct Line *line; struct ClientPhonePickupMessage pick; if (NULL == ch) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PICKUP message received for non-existing channel, dropping channel.\n"); return GNUNET_SYSERR; } line = ch->line; GNUNET_MESH_receive_done (channel); switch (ch->status) { case CS_CALLEE_RINGING: case CS_CALLEE_CONNECTED: GNUNET_break_op (0); destroy_line_mesh_channels (ch); return GNUNET_SYSERR; case CS_CALLEE_SHUTDOWN: GNUNET_break_op (0); destroy_line_mesh_channels (ch); break; case CS_CALLER_CALLING: ch->status = CS_CALLER_CONNECTED; break; case CS_CALLER_CONNECTED: GNUNET_break_op (0); return GNUNET_OK; case CS_CALLER_SHUTDOWN: GNUNET_break_op (0); mq_done_finish_caller_shutdown (ch); return GNUNET_SYSERR; } pick.header.size = htons (sizeof (pick)); pick.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP); pick.cid = ch->cid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending PICKED UP message to client\n"); GNUNET_SERVER_notification_context_unicast (nc, line->client, &pick.header, GNUNET_NO); ch->channel_unreliable = GNUNET_MESH_channel_create (mesh, ch, &ch->target, GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO, GNUNET_MESH_OPTION_DEFAULT); if (NULL == ch->channel_unreliable) { GNUNET_break (0); } return GNUNET_OK; } /** * Function to handle a suspend message incoming over mesh * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK */ static int handle_mesh_suspend_message (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; struct Line *line; struct ClientPhoneSuspendMessage suspend; if (NULL == ch) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SUSPEND message received for non-existing line, dropping channel.\n"); return GNUNET_SYSERR; } line = ch->line; suspend.header.size = htons (sizeof (suspend)); suspend.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND); suspend.cid = ch->cid; GNUNET_MESH_receive_done (channel); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending channel CID: %u(%u:%u)\n", ch->cid, ch->remote_line, line->local_line); switch (ch->status) { case CS_CALLEE_RINGING: GNUNET_break_op (0); break; case CS_CALLEE_CONNECTED: ch->suspended_remote = GNUNET_YES; break; case CS_CALLEE_SHUTDOWN: return GNUNET_OK; case CS_CALLER_CALLING: GNUNET_break_op (0); break; case CS_CALLER_CONNECTED: ch->suspended_remote = GNUNET_YES; break; case CS_CALLER_SHUTDOWN: return GNUNET_OK; } GNUNET_SERVER_notification_context_unicast (nc, line->client, &suspend.header, GNUNET_NO); return GNUNET_OK; } /** * Function to handle a resume message incoming over mesh * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK */ static int handle_mesh_resume_message (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct Channel *ch = *channel_ctx; struct Line *line; struct ClientPhoneResumeMessage resume; if (NULL == ch) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RESUME message received for non-existing line, dropping channel.\n"); return GNUNET_SYSERR; } line = ch->line; resume.header.size = htons (sizeof (resume)); resume.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME); resume.cid = ch->cid; GNUNET_MESH_receive_done (channel); if (GNUNET_YES != ch->suspended_remote) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RESUME message received for non-suspended channel, dropping channel.\n"); return GNUNET_SYSERR; } switch (ch->status) { case CS_CALLEE_RINGING: GNUNET_break (0); break; case CS_CALLEE_CONNECTED: ch->suspended_remote = GNUNET_NO; break; case CS_CALLEE_SHUTDOWN: return GNUNET_OK; case CS_CALLER_CALLING: GNUNET_break (0); break; case CS_CALLER_CONNECTED: ch->suspended_remote = GNUNET_NO; break; case CS_CALLER_SHUTDOWN: return GNUNET_OK; } GNUNET_SERVER_notification_context_unicast (nc, line->client, &resume.header, GNUNET_NO); return GNUNET_OK; } /** * Function to handle an audio message incoming over mesh * * @param cls closure, NULL * @param channel the channel over which the message arrived * @param channel_ctx the channel context, can be NULL * or point to the `struct Channel` * @param message the incoming message * @return #GNUNET_OK */ static int handle_mesh_audio_message (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { const struct MeshAudioMessage *msg; struct Channel *ch = *channel_ctx; struct Line *line; struct GNUNET_PeerIdentity sender; size_t msize = ntohs (message->size) - sizeof (struct MeshAudioMessage); char buf[msize + sizeof (struct ClientAudioMessage)]; struct ClientAudioMessage *cam; const union GNUNET_MESH_ChannelInfo *info; msg = (const struct MeshAudioMessage *) message; if (NULL == ch) { info = GNUNET_MESH_channel_get_info (channel, GNUNET_MESH_OPTION_PEER); if (NULL == info) { GNUNET_break (0); return GNUNET_SYSERR; } sender = info->peer; for (line = lines_head; NULL != line; line = line->next) if (line->local_line == ntohl (msg->remote_line)) { for (ch = line->channel_head; NULL != ch; ch = ch->next) { if ( (CS_CALLEE_CONNECTED == ch->status) && (0 == memcmp (&ch->target, &sender, sizeof (struct GNUNET_PeerIdentity))) && (NULL == ch->channel_unreliable) && (ch->remote_line == ntohl (msg->source_line)) ) break; } break; } if (NULL == line) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes of AUDIO data for non-existing line %u, dropping.\n", msize, ntohl (msg->remote_line)); return GNUNET_SYSERR; } if (NULL == ch) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes of AUDIO data for unknown sender.\n", msize); return GNUNET_SYSERR; } if ((GNUNET_YES == ch->suspended_local) || (GNUNET_YES == ch->suspended_remote)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes of AUDIO data on suspended channel CID %u:(%u:%u); dropping\n", msize, ch->cid, ch->remote_line, line->local_line); GNUNET_MESH_receive_done (channel); return GNUNET_OK; } ch->channel_unreliable = channel; *channel_ctx = ch; } GNUNET_MESH_receive_done (channel); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarding %u bytes of AUDIO data to client CID %u:(%u:%u)\n", msize, ch->cid, ch->remote_line, ch->line->local_line); cam = (struct ClientAudioMessage *) buf; cam->header.size = htons (sizeof (buf)); cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO); cam->cid = ch->cid; memcpy (&cam[1], &msg[1], msize); GNUNET_SERVER_notification_context_unicast (nc, ch->line->client, &cam->header, GNUNET_YES); return GNUNET_OK; } /** * Method called whenever another peer has added us to a channel * the other peer initiated. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel * @param port port * @param options channel option flags * @return initial channel context for the channel; * (can be NULL -- that's not an error) */ static void * inbound_channel (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received incoming channel on port %u\n"), (unsigned int) port); return NULL; } /** * Function called whenever an inbound channel is destroyed. Should clean up * any associated state. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored; * may point to the `struct Channel` */ static void inbound_end (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { struct Channel *ch = channel_ctx; struct Line *line; struct ClientPhoneHangupMessage hup; if (NULL == ch) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh channel destroyed, but channel is unknown to us\n"); return; } line = ch->line; if (ch->channel_unreliable == channel) { if (NULL != ch->unreliable_mth) { GNUNET_MESH_notify_transmit_ready_cancel (ch->unreliable_mth); ch->unreliable_mth = NULL; } ch->channel_unreliable = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unreliable channel destroyed\n"); return; } if (ch->channel_reliable != channel) { /* recursive call, I'm the one destroying 'ch' right now */ return; } ch->channel_reliable = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh channel destroyed by mesh in state %d\n", ch->status); hup.header.size = htons (sizeof (hup)); hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP); hup.cid = ch->cid; switch (ch->status) { case CS_CALLEE_RINGING: case CS_CALLEE_CONNECTED: GNUNET_SERVER_notification_context_unicast (nc, line->client, &hup.header, GNUNET_NO); break; case CS_CALLEE_SHUTDOWN: break; case CS_CALLER_CALLING: case CS_CALLER_CONNECTED: GNUNET_SERVER_notification_context_unicast (nc, line->client, &hup.header, GNUNET_NO); break; case CS_CALLER_SHUTDOWN: break; } destroy_line_mesh_channels (ch); } /** * A client disconnected. Remove all of its data structure entries. * * @param cls closure, NULL * @param client identification of the client */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct Line *line; if (NULL == client) return; line = GNUNET_SERVER_client_get_user_context (client, struct Line); if (NULL == line) return; GNUNET_SERVER_client_set_user_context (client, (void *)NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, closing line\n"); GNUNET_CONTAINER_DLL_remove (lines_head, lines_tail, line); while (NULL != line->channel_head) destroy_line_mesh_channels (line->channel_head); GNUNET_free (line); } /** * Shutdown nicely * * @param cls closure, NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Line *line; struct Channel *ch; while (NULL != (line = lines_head)) { while (NULL != (ch = line->channel_head)) destroy_line_mesh_channels (ch); GNUNET_CONTAINER_DLL_remove (lines_head, lines_tail, line); GNUNET_SERVER_client_set_user_context (line->client, (void *) NULL); GNUNET_free (line); } if (NULL != mesh) { GNUNET_MESH_disconnect (mesh); mesh = NULL; } if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } } /** * Main function that will be run by the scheduler. * * @param cls closure * @param server server handle * @param c configuration */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { {&handle_client_register_message, NULL, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER, sizeof (struct ClientPhoneRegisterMessage)}, {&handle_client_pickup_message, NULL, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP, sizeof (struct ClientPhonePickupMessage) }, {&handle_client_suspend_message, NULL, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND, sizeof (struct ClientPhoneSuspendMessage) }, {&handle_client_resume_message, NULL, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME, sizeof (struct ClientPhoneResumeMessage) }, {&handle_client_hangup_message, NULL, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP, sizeof (struct ClientPhoneHangupMessage) }, {&handle_client_call_message, NULL, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL, sizeof (struct ClientCallMessage) }, {&handle_client_audio_message, NULL, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO, 0}, {NULL, NULL, 0, 0} }; static struct GNUNET_MESH_MessageHandler mesh_handlers[] = { {&handle_mesh_ring_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING, sizeof (struct MeshPhoneRingMessage)}, {&handle_mesh_hangup_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP, sizeof (struct MeshPhoneHangupMessage)}, {&handle_mesh_pickup_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP, sizeof (struct MeshPhonePickupMessage)}, {&handle_mesh_suspend_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_SUSPEND, sizeof (struct MeshPhoneSuspendMessage)}, {&handle_mesh_resume_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RESUME, sizeof (struct MeshPhoneResumeMessage)}, {&handle_mesh_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO, 0}, {NULL, 0, 0} }; static uint32_t ports[] = { GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL, GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO, 0 }; cfg = c; GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_get_peer_identity (cfg, &my_identity)); mesh = GNUNET_MESH_connect (cfg, NULL, &inbound_channel, &inbound_end, mesh_handlers, ports); if (NULL == mesh) { GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } nc = GNUNET_SERVER_notification_context_create (server, 16); GNUNET_SERVER_add_handlers (server, server_handlers); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); } /** * The main function for the conversation service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "conversation", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-conversation.c */ gnunet-0.10.1/src/conversation/Makefile.in0000644000175000017500000023747012320752060015372 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-conversation-test$(EXEEXT) \ gnunet-conversation$(EXEEXT) libexec_PROGRAMS = gnunet-service-conversation$(EXEEXT) \ $(am__EXEEXT_1) $(am__EXEEXT_2) check_PROGRAMS = test_conversation_api$(EXEEXT) \ test_conversation_api_reject$(EXEEXT) \ test_conversation_api_twocalls$(EXEEXT) subdir = src/conversation DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/conversation.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = conversation.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunet_plugin_gnsrecord_conversation_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunet_plugin_gnsrecord_conversation_la_OBJECTS = \ plugin_gnsrecord_conversation.lo libgnunet_plugin_gnsrecord_conversation_la_OBJECTS = \ $(am_libgnunet_plugin_gnsrecord_conversation_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_gnsrecord_conversation_la_LINK = $(LIBTOOL) \ $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_gnsrecord_conversation_la_LDFLAGS) \ $(LDFLAGS) -o $@ libgnunetconversation_la_DEPENDENCIES = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetconversation_la_OBJECTS = conversation_api.lo \ conversation_api_call.lo libgnunetconversation_la_OBJECTS = \ $(am_libgnunetconversation_la_OBJECTS) libgnunetconversation_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetconversation_la_LDFLAGS) \ $(LDFLAGS) -o $@ libgnunetmicrophone_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetmicrophone_la_OBJECTS = microphone.lo libgnunetmicrophone_la_OBJECTS = $(am_libgnunetmicrophone_la_OBJECTS) libgnunetmicrophone_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetmicrophone_la_LDFLAGS) \ $(LDFLAGS) -o $@ libgnunetspeaker_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetspeaker_la_OBJECTS = speaker.lo libgnunetspeaker_la_OBJECTS = $(am_libgnunetspeaker_la_OBJECTS) libgnunetspeaker_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetspeaker_la_LDFLAGS) \ $(LDFLAGS) -o $@ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@am__EXEEXT_1 = gnunet-helper-audio-record$(EXEEXT) @BUILD_PULSE_HELPERS_TRUE@am__EXEEXT_1 = \ @BUILD_PULSE_HELPERS_TRUE@ gnunet-helper-audio-record$(EXEEXT) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@am__EXEEXT_2 = gnunet-helper-audio-playback$(EXEEXT) @BUILD_PULSE_HELPERS_TRUE@am__EXEEXT_2 = gnunet-helper-audio-playback$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_conversation_OBJECTS = gnunet-conversation.$(OBJEXT) gnunet_conversation_OBJECTS = $(am_gnunet_conversation_OBJECTS) gnunet_conversation_DEPENDENCIES = libgnunetmicrophone.la \ libgnunetspeaker.la libgnunetconversation.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) gnunet_conversation_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(gnunet_conversation_LDFLAGS) \ $(LDFLAGS) -o $@ am_gnunet_conversation_test_OBJECTS = \ gnunet-conversation-test.$(OBJEXT) gnunet_conversation_test_OBJECTS = \ $(am_gnunet_conversation_test_OBJECTS) gnunet_conversation_test_DEPENDENCIES = libgnunetmicrophone.la \ libgnunetspeaker.la $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) gnunet_conversation_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(gnunet_conversation_test_LDFLAGS) \ $(LDFLAGS) -o $@ am__gnunet_helper_audio_playback_SOURCES_DIST = \ gnunet-helper-audio-playback-gst.c \ gnunet-helper-audio-playback.c @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@am_gnunet_helper_audio_playback_OBJECTS = gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.$(OBJEXT) @BUILD_PULSE_HELPERS_TRUE@am_gnunet_helper_audio_playback_OBJECTS = gnunet_helper_audio_playback-gnunet-helper-audio-playback.$(OBJEXT) gnunet_helper_audio_playback_OBJECTS = \ $(am_gnunet_helper_audio_playback_OBJECTS) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_playback_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(am__DEPENDENCIES_1) \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(am__DEPENDENCIES_1) @BUILD_PULSE_HELPERS_TRUE@gnunet_helper_audio_playback_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ @BUILD_PULSE_HELPERS_TRUE@ $(am__DEPENDENCIES_1) gnunet_helper_audio_playback_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) \ $(gnunet_helper_audio_playback_LDFLAGS) $(LDFLAGS) -o $@ am__gnunet_helper_audio_record_SOURCES_DIST = \ gnunet-helper-audio-record-gst.c gnunet-helper-audio-record.c @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@am_gnunet_helper_audio_record_OBJECTS = gnunet_helper_audio_record-gnunet-helper-audio-record-gst.$(OBJEXT) @BUILD_PULSE_HELPERS_TRUE@am_gnunet_helper_audio_record_OBJECTS = gnunet_helper_audio_record-gnunet-helper-audio-record.$(OBJEXT) gnunet_helper_audio_record_OBJECTS = \ $(am_gnunet_helper_audio_record_OBJECTS) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_record_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(am__DEPENDENCIES_1) \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(am__DEPENDENCIES_1) @BUILD_PULSE_HELPERS_TRUE@gnunet_helper_audio_record_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ @BUILD_PULSE_HELPERS_TRUE@ $(am__DEPENDENCIES_1) gnunet_helper_audio_record_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) \ $(gnunet_helper_audio_record_LDFLAGS) $(LDFLAGS) -o $@ am_gnunet_service_conversation_OBJECTS = \ gnunet-service-conversation.$(OBJEXT) gnunet_service_conversation_OBJECTS = \ $(am_gnunet_service_conversation_OBJECTS) gnunet_service_conversation_DEPENDENCIES = libgnunetconversation.la \ libgnunetspeaker.la libgnunetmicrophone.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) gnunet_service_conversation_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(gnunet_service_conversation_LDFLAGS) \ $(LDFLAGS) -o $@ am_test_conversation_api_OBJECTS = test_conversation_api.$(OBJEXT) test_conversation_api_OBJECTS = $(am_test_conversation_api_OBJECTS) test_conversation_api_DEPENDENCIES = libgnunetconversation.la \ libgnunetspeaker.la libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(test_conversation_api_LDFLAGS) \ $(LDFLAGS) -o $@ am_test_conversation_api_reject_OBJECTS = \ test_conversation_api_reject.$(OBJEXT) test_conversation_api_reject_OBJECTS = \ $(am_test_conversation_api_reject_OBJECTS) test_conversation_api_reject_DEPENDENCIES = libgnunetconversation.la \ libgnunetspeaker.la libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_reject_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(test_conversation_api_reject_LDFLAGS) \ $(LDFLAGS) -o $@ am_test_conversation_api_twocalls_OBJECTS = \ test_conversation_api_twocalls.$(OBJEXT) test_conversation_api_twocalls_OBJECTS = \ $(am_test_conversation_api_twocalls_OBJECTS) test_conversation_api_twocalls_DEPENDENCIES = \ libgnunetconversation.la libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_twocalls_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) \ $(test_conversation_api_twocalls_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_gnsrecord_conversation_la_SOURCES) \ $(libgnunetconversation_la_SOURCES) \ $(libgnunetmicrophone_la_SOURCES) \ $(libgnunetspeaker_la_SOURCES) $(gnunet_conversation_SOURCES) \ $(gnunet_conversation_test_SOURCES) \ $(gnunet_helper_audio_playback_SOURCES) \ $(gnunet_helper_audio_record_SOURCES) \ $(gnunet_service_conversation_SOURCES) \ $(test_conversation_api_SOURCES) \ $(test_conversation_api_reject_SOURCES) \ $(test_conversation_api_twocalls_SOURCES) DIST_SOURCES = $(libgnunet_plugin_gnsrecord_conversation_la_SOURCES) \ $(libgnunetconversation_la_SOURCES) \ $(libgnunetmicrophone_la_SOURCES) \ $(libgnunetspeaker_la_SOURCES) $(gnunet_conversation_SOURCES) \ $(gnunet_conversation_test_SOURCES) \ $(am__gnunet_helper_audio_playback_SOURCES_DIST) \ $(am__gnunet_helper_audio_record_SOURCES_DIST) \ $(gnunet_service_conversation_SOURCES) \ $(test_conversation_api_SOURCES) \ $(test_conversation_api_reject_SOURCES) \ $(test_conversation_api_twocalls_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ check recheck distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(prefix)/lib/gnunet/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . plugindir = $(libdir)/gnunet @MINGW_TRUE@WINFLAGS = -no-undefined -Wl,--export-all-symbols AM_CPPFLAGS = \ $(GNUNET_CPPFLAGS) \ -I$(top_srcdir)/src/include \ -I$(top_srcdir) lib_LTLIBRARIES = \ libgnunetmicrophone.la \ libgnunetspeaker.la \ libgnunetconversation.la pkgcfgdir = $(prefix)/share/gnunet/config.d/ plugin_LTLIBRARIES = \ libgnunet_plugin_gnsrecord_conversation.la libgnunet_plugin_gnsrecord_conversation_la_SOURCES = \ plugin_gnsrecord_conversation.c libgnunet_plugin_gnsrecord_conversation_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_gnsrecord_conversation_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunetmicrophone_la_SOURCES = \ microphone.c libgnunetmicrophone_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetmicrophone_la_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetspeaker_la_SOURCES = \ speaker.c libgnunetspeaker_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetspeaker_la_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetconversation_la_SOURCES = \ conversation_api.c \ conversation_api_call.c \ conversation.h libgnunetconversation_la_LIBADD = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunetconversation_la_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@AUDIO_HELPER_RECD = gnunet-helper-audio-record @BUILD_PULSE_HELPERS_TRUE@AUDIO_HELPER_RECD = gnunet-helper-audio-record @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@AUDIO_HELPER_PLAY = gnunet-helper-audio-playback @BUILD_PULSE_HELPERS_TRUE@AUDIO_HELPER_PLAY = gnunet-helper-audio-playback @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@AUDIO_TESTS = $(check_PROGRAMS) @BUILD_PULSE_HELPERS_TRUE@AUDIO_TESTS = $(check_PROGRAMS) AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(AUDIO_TESTS) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_record_SOURCES = \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ gnunet-helper-audio-record-gst.c @BUILD_PULSE_HELPERS_TRUE@gnunet_helper_audio_record_SOURCES = \ @BUILD_PULSE_HELPERS_TRUE@ gnunet-helper-audio-record.c @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_record_LDADD = \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(top_builddir)/src/util/libgnunetutil.la \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(GST_LIBS) \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(INTLLIBS) @BUILD_PULSE_HELPERS_TRUE@gnunet_helper_audio_record_LDADD = \ @BUILD_PULSE_HELPERS_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @BUILD_PULSE_HELPERS_TRUE@ -lpulse -lopus -logg \ @BUILD_PULSE_HELPERS_TRUE@ $(INTLLIBS) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_record_LDFLAGS = \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(GNUNET_LDFLAGS) $(WINFLAGS) $(GST_LDFLAGS) @BUILD_PULSE_HELPERS_TRUE@gnunet_helper_audio_record_LDFLAGS = \ @BUILD_PULSE_HELPERS_TRUE@ $(GNUNET_LDFLAGS) $(WINFLAGS) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_playback_SOURCES = \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ gnunet-helper-audio-playback-gst.c @BUILD_PULSE_HELPERS_TRUE@gnunet_helper_audio_playback_SOURCES = \ @BUILD_PULSE_HELPERS_TRUE@ gnunet-helper-audio-playback.c @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_playback_LDADD = \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(top_builddir)/src/util/libgnunetutil.la \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(GST_LIBS) \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(INTLLIBS) @BUILD_PULSE_HELPERS_TRUE@gnunet_helper_audio_playback_LDADD = \ @BUILD_PULSE_HELPERS_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @BUILD_PULSE_HELPERS_TRUE@ -lpulse -lopus -logg \ @BUILD_PULSE_HELPERS_TRUE@ $(INTLLIBS) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_playback_LDFLAGS = \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(GNUNET_LDFLAGS) $(WINFLAGS) $(GST_LDFLAGS) @BUILD_PULSE_HELPERS_TRUE@gnunet_helper_audio_playback_LDFLAGS = \ @BUILD_PULSE_HELPERS_TRUE@ $(GNUNET_LDFLAGS) $(WINFLAGS) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_record_CFLAGS = \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(GST_CFLAGS) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@gnunet_helper_audio_playback_CFLAGS = \ @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@ $(GST_CFLAGS) gnunet_service_conversation_SOURCES = \ gnunet-service-conversation.c gnunet_service_conversation_LDADD = \ libgnunetconversation.la \ libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(INTLLIBS) gnunet_service_conversation_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) gnunet_conversation_SOURCES = \ gnunet-conversation.c gnunet_conversation_LDADD = \ libgnunetmicrophone.la \ libgnunetspeaker.la \ libgnunetconversation.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(INTLLIBS) gnunet_conversation_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) gnunet_conversation_test_SOURCES = \ gnunet-conversation-test.c gnunet_conversation_test_LDADD = \ libgnunetmicrophone.la \ libgnunetspeaker.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(INTLLIBS) gnunet_conversation_test_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) test_conversation_api_SOURCES = \ test_conversation_api.c test_conversation_api_LDADD = \ libgnunetconversation.la \ libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic test_conversation_api_twocalls_SOURCES = \ test_conversation_api_twocalls.c test_conversation_api_twocalls_LDADD = \ libgnunetconversation.la \ libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_twocalls_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic test_conversation_api_reject_SOURCES = \ test_conversation_api_reject.c test_conversation_api_reject_LDADD = \ libgnunetconversation.la \ libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_reject_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic pkgcfg_DATA = conversation.conf EXTRA_DIST = test_conversation.conf all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/conversation/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/conversation/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): conversation.conf: $(top_builddir)/config.status $(srcdir)/conversation.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_gnsrecord_conversation.la: $(libgnunet_plugin_gnsrecord_conversation_la_OBJECTS) $(libgnunet_plugin_gnsrecord_conversation_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_gnsrecord_conversation_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_gnsrecord_conversation_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_gnsrecord_conversation_la_OBJECTS) $(libgnunet_plugin_gnsrecord_conversation_la_LIBADD) $(LIBS) libgnunetconversation.la: $(libgnunetconversation_la_OBJECTS) $(libgnunetconversation_la_DEPENDENCIES) $(EXTRA_libgnunetconversation_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetconversation_la_LINK) -rpath $(libdir) $(libgnunetconversation_la_OBJECTS) $(libgnunetconversation_la_LIBADD) $(LIBS) libgnunetmicrophone.la: $(libgnunetmicrophone_la_OBJECTS) $(libgnunetmicrophone_la_DEPENDENCIES) $(EXTRA_libgnunetmicrophone_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetmicrophone_la_LINK) -rpath $(libdir) $(libgnunetmicrophone_la_OBJECTS) $(libgnunetmicrophone_la_LIBADD) $(LIBS) libgnunetspeaker.la: $(libgnunetspeaker_la_OBJECTS) $(libgnunetspeaker_la_DEPENDENCIES) $(EXTRA_libgnunetspeaker_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetspeaker_la_LINK) -rpath $(libdir) $(libgnunetspeaker_la_OBJECTS) $(libgnunetspeaker_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-conversation$(EXEEXT): $(gnunet_conversation_OBJECTS) $(gnunet_conversation_DEPENDENCIES) $(EXTRA_gnunet_conversation_DEPENDENCIES) @rm -f gnunet-conversation$(EXEEXT) $(AM_V_CCLD)$(gnunet_conversation_LINK) $(gnunet_conversation_OBJECTS) $(gnunet_conversation_LDADD) $(LIBS) gnunet-conversation-test$(EXEEXT): $(gnunet_conversation_test_OBJECTS) $(gnunet_conversation_test_DEPENDENCIES) $(EXTRA_gnunet_conversation_test_DEPENDENCIES) @rm -f gnunet-conversation-test$(EXEEXT) $(AM_V_CCLD)$(gnunet_conversation_test_LINK) $(gnunet_conversation_test_OBJECTS) $(gnunet_conversation_test_LDADD) $(LIBS) gnunet-helper-audio-playback$(EXEEXT): $(gnunet_helper_audio_playback_OBJECTS) $(gnunet_helper_audio_playback_DEPENDENCIES) $(EXTRA_gnunet_helper_audio_playback_DEPENDENCIES) @rm -f gnunet-helper-audio-playback$(EXEEXT) $(AM_V_CCLD)$(gnunet_helper_audio_playback_LINK) $(gnunet_helper_audio_playback_OBJECTS) $(gnunet_helper_audio_playback_LDADD) $(LIBS) gnunet-helper-audio-record$(EXEEXT): $(gnunet_helper_audio_record_OBJECTS) $(gnunet_helper_audio_record_DEPENDENCIES) $(EXTRA_gnunet_helper_audio_record_DEPENDENCIES) @rm -f gnunet-helper-audio-record$(EXEEXT) $(AM_V_CCLD)$(gnunet_helper_audio_record_LINK) $(gnunet_helper_audio_record_OBJECTS) $(gnunet_helper_audio_record_LDADD) $(LIBS) gnunet-service-conversation$(EXEEXT): $(gnunet_service_conversation_OBJECTS) $(gnunet_service_conversation_DEPENDENCIES) $(EXTRA_gnunet_service_conversation_DEPENDENCIES) @rm -f gnunet-service-conversation$(EXEEXT) $(AM_V_CCLD)$(gnunet_service_conversation_LINK) $(gnunet_service_conversation_OBJECTS) $(gnunet_service_conversation_LDADD) $(LIBS) test_conversation_api$(EXEEXT): $(test_conversation_api_OBJECTS) $(test_conversation_api_DEPENDENCIES) $(EXTRA_test_conversation_api_DEPENDENCIES) @rm -f test_conversation_api$(EXEEXT) $(AM_V_CCLD)$(test_conversation_api_LINK) $(test_conversation_api_OBJECTS) $(test_conversation_api_LDADD) $(LIBS) test_conversation_api_reject$(EXEEXT): $(test_conversation_api_reject_OBJECTS) $(test_conversation_api_reject_DEPENDENCIES) $(EXTRA_test_conversation_api_reject_DEPENDENCIES) @rm -f test_conversation_api_reject$(EXEEXT) $(AM_V_CCLD)$(test_conversation_api_reject_LINK) $(test_conversation_api_reject_OBJECTS) $(test_conversation_api_reject_LDADD) $(LIBS) test_conversation_api_twocalls$(EXEEXT): $(test_conversation_api_twocalls_OBJECTS) $(test_conversation_api_twocalls_DEPENDENCIES) $(EXTRA_test_conversation_api_twocalls_DEPENDENCIES) @rm -f test_conversation_api_twocalls$(EXEEXT) $(AM_V_CCLD)$(test_conversation_api_twocalls_LINK) $(test_conversation_api_twocalls_OBJECTS) $(test_conversation_api_twocalls_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conversation_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conversation_api_call.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-conversation-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-conversation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-conversation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record-gst.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/microphone.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_gnsrecord_conversation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speaker.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conversation_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conversation_api_reject.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_conversation_api_twocalls.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.o: gnunet-helper-audio-playback-gst.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) -MT gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.o -MD -MP -MF $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.Tpo -c -o gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.o `test -f 'gnunet-helper-audio-playback-gst.c' || echo '$(srcdir)/'`gnunet-helper-audio-playback-gst.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.Tpo $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-helper-audio-playback-gst.c' object='gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) -c -o gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.o `test -f 'gnunet-helper-audio-playback-gst.c' || echo '$(srcdir)/'`gnunet-helper-audio-playback-gst.c gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.obj: gnunet-helper-audio-playback-gst.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) -MT gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.obj -MD -MP -MF $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.Tpo -c -o gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.obj `if test -f 'gnunet-helper-audio-playback-gst.c'; then $(CYGPATH_W) 'gnunet-helper-audio-playback-gst.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-helper-audio-playback-gst.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.Tpo $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-helper-audio-playback-gst.c' object='gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) -c -o gnunet_helper_audio_playback-gnunet-helper-audio-playback-gst.obj `if test -f 'gnunet-helper-audio-playback-gst.c'; then $(CYGPATH_W) 'gnunet-helper-audio-playback-gst.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-helper-audio-playback-gst.c'; fi` gnunet_helper_audio_playback-gnunet-helper-audio-playback.o: gnunet-helper-audio-playback.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) -MT gnunet_helper_audio_playback-gnunet-helper-audio-playback.o -MD -MP -MF $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback.Tpo -c -o gnunet_helper_audio_playback-gnunet-helper-audio-playback.o `test -f 'gnunet-helper-audio-playback.c' || echo '$(srcdir)/'`gnunet-helper-audio-playback.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback.Tpo $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-helper-audio-playback.c' object='gnunet_helper_audio_playback-gnunet-helper-audio-playback.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) -c -o gnunet_helper_audio_playback-gnunet-helper-audio-playback.o `test -f 'gnunet-helper-audio-playback.c' || echo '$(srcdir)/'`gnunet-helper-audio-playback.c gnunet_helper_audio_playback-gnunet-helper-audio-playback.obj: gnunet-helper-audio-playback.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) -MT gnunet_helper_audio_playback-gnunet-helper-audio-playback.obj -MD -MP -MF $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback.Tpo -c -o gnunet_helper_audio_playback-gnunet-helper-audio-playback.obj `if test -f 'gnunet-helper-audio-playback.c'; then $(CYGPATH_W) 'gnunet-helper-audio-playback.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-helper-audio-playback.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback.Tpo $(DEPDIR)/gnunet_helper_audio_playback-gnunet-helper-audio-playback.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-helper-audio-playback.c' object='gnunet_helper_audio_playback-gnunet-helper-audio-playback.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_playback_CFLAGS) $(CFLAGS) -c -o gnunet_helper_audio_playback-gnunet-helper-audio-playback.obj `if test -f 'gnunet-helper-audio-playback.c'; then $(CYGPATH_W) 'gnunet-helper-audio-playback.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-helper-audio-playback.c'; fi` gnunet_helper_audio_record-gnunet-helper-audio-record-gst.o: gnunet-helper-audio-record-gst.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) -MT gnunet_helper_audio_record-gnunet-helper-audio-record-gst.o -MD -MP -MF $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record-gst.Tpo -c -o gnunet_helper_audio_record-gnunet-helper-audio-record-gst.o `test -f 'gnunet-helper-audio-record-gst.c' || echo '$(srcdir)/'`gnunet-helper-audio-record-gst.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record-gst.Tpo $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record-gst.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-helper-audio-record-gst.c' object='gnunet_helper_audio_record-gnunet-helper-audio-record-gst.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) -c -o gnunet_helper_audio_record-gnunet-helper-audio-record-gst.o `test -f 'gnunet-helper-audio-record-gst.c' || echo '$(srcdir)/'`gnunet-helper-audio-record-gst.c gnunet_helper_audio_record-gnunet-helper-audio-record-gst.obj: gnunet-helper-audio-record-gst.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) -MT gnunet_helper_audio_record-gnunet-helper-audio-record-gst.obj -MD -MP -MF $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record-gst.Tpo -c -o gnunet_helper_audio_record-gnunet-helper-audio-record-gst.obj `if test -f 'gnunet-helper-audio-record-gst.c'; then $(CYGPATH_W) 'gnunet-helper-audio-record-gst.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-helper-audio-record-gst.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record-gst.Tpo $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record-gst.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-helper-audio-record-gst.c' object='gnunet_helper_audio_record-gnunet-helper-audio-record-gst.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) -c -o gnunet_helper_audio_record-gnunet-helper-audio-record-gst.obj `if test -f 'gnunet-helper-audio-record-gst.c'; then $(CYGPATH_W) 'gnunet-helper-audio-record-gst.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-helper-audio-record-gst.c'; fi` gnunet_helper_audio_record-gnunet-helper-audio-record.o: gnunet-helper-audio-record.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) -MT gnunet_helper_audio_record-gnunet-helper-audio-record.o -MD -MP -MF $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record.Tpo -c -o gnunet_helper_audio_record-gnunet-helper-audio-record.o `test -f 'gnunet-helper-audio-record.c' || echo '$(srcdir)/'`gnunet-helper-audio-record.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record.Tpo $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-helper-audio-record.c' object='gnunet_helper_audio_record-gnunet-helper-audio-record.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) -c -o gnunet_helper_audio_record-gnunet-helper-audio-record.o `test -f 'gnunet-helper-audio-record.c' || echo '$(srcdir)/'`gnunet-helper-audio-record.c gnunet_helper_audio_record-gnunet-helper-audio-record.obj: gnunet-helper-audio-record.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) -MT gnunet_helper_audio_record-gnunet-helper-audio-record.obj -MD -MP -MF $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record.Tpo -c -o gnunet_helper_audio_record-gnunet-helper-audio-record.obj `if test -f 'gnunet-helper-audio-record.c'; then $(CYGPATH_W) 'gnunet-helper-audio-record.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-helper-audio-record.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record.Tpo $(DEPDIR)/gnunet_helper_audio_record-gnunet-helper-audio-record.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-helper-audio-record.c' object='gnunet_helper_audio_record-gnunet-helper-audio-record.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_helper_audio_record_CFLAGS) $(CFLAGS) -c -o gnunet_helper_audio_record-gnunet-helper-audio-record.obj `if test -f 'gnunet-helper-audio-record.c'; then $(CYGPATH_W) 'gnunet-helper-audio-record.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-helper-audio-record.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_conversation_api.log: test_conversation_api$(EXEEXT) @p='test_conversation_api$(EXEEXT)'; \ b='test_conversation_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_conversation_api_reject.log: test_conversation_api_reject$(EXEEXT) @p='test_conversation_api_reject$(EXEEXT)'; \ b='test_conversation_api_reject'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_conversation_api_twocalls.log: test_conversation_api_twocalls$(EXEEXT) @p='test_conversation_api_twocalls$(EXEEXT)'; \ b='test_conversation_api_twocalls'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-TESTS check-am clean clean-binPROGRAMS \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-pluginLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/conversation/gnunet-helper-audio-record-gst.c0000644000175000017500000002414612320530515021405 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/gnunet-helper-audio-record-gst.c * @brief program to record audio data from the microphone (GStreamer version) * @author LRN */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "conversation.h" #include "gnunet_constants.h" #include "gnunet_core_service.h" #include #include #include #include #define DEBUG_RECORD_PURE_OGG 1 /** * Number of channels. * Must be one of the following (from libopusenc documentation): * 1, 2 */ #define OPUS_CHANNELS 1 /** * Maximal size of a single opus packet. */ #define MAX_PAYLOAD_SIZE (1024 / OPUS_CHANNELS) /** * Size of a single frame fed to the encoder, in ms. * Must be one of the following (from libopus documentation): * 2.5, 5, 10, 20, 40 or 60 */ #define OPUS_FRAME_SIZE 40 /** * Expected packet loss to prepare for, in percents. */ #define PACKET_LOSS_PERCENTAGE 1 /** * Set to 1 to enable forward error correction. * Set to 0 to disable. */ #define INBAND_FEC_MODE 1 /** * Max number of microseconds to buffer in audiosource. * Default is 200000 */ #define BUFFER_TIME 1000 /* 1ms */ /** * Min number of microseconds to buffer in audiosource. * Default is 10000 */ #define LATENCY_TIME 1000 /* 1ms */ /** * Maximum delay in multiplexing streams, in ns. * Setting this to 0 forces page flushing, which * decreases delay, but increases overhead. */ #define OGG_MAX_DELAY 0 /** * Maximum delay for sending out a page, in ns. * Setting this to 0 forces page flushing, which * decreases delay, but increases overhead. */ #define OGG_MAX_PAGE_DELAY 0 /** * Main pipeline. */ static GstElement *pipeline; #ifdef DEBUG_RECORD_PURE_OGG static int dump_pure_ogg; #endif static void quit () { if (NULL != pipeline) gst_element_set_state (pipeline, GST_STATE_NULL); } static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bus message\n"); switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "End of stream\n"); quit (); break; case GST_MESSAGE_ERROR: { gchar *debug; GError *error; gst_message_parse_error (msg, &error, &debug); g_free (debug); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error: %s\n", error->message); g_error_free (error); quit (); break; } default: break; } return TRUE; } void source_child_added (GstChildProxy *child_proxy, GObject *object, gchar *name, gpointer user_data) { if (GST_IS_AUDIO_BASE_SRC (object)) g_object_set (object, "buffer-time", (gint64) BUFFER_TIME, "latency-time", (gint64) LATENCY_TIME, NULL); } static void signalhandler (int s) { quit (); } int main (int argc, char **argv) { GstElement *source, *filter, *encoder, *conv, *resampler, *sink, *oggmux; GstCaps *caps; GstBus *bus; guint bus_watch_id; struct AudioMessage audio_message; int abort_send = 0; typedef void (*SignalHandlerPointer) (int); SignalHandlerPointer inthandler, termhandler; inthandler = signal (SIGINT, signalhandler); termhandler = signal (SIGTERM, signalhandler); #ifdef DEBUG_RECORD_PURE_OGG dump_pure_ogg = getenv ("GNUNET_RECORD_PURE_OGG") ? 1 : 0; #endif #ifdef WINDOWS setmode (1, _O_BINARY); #endif /* Initialisation */ gst_init (&argc, &argv); GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("gnunet-helper-audio-record", "WARNING", NULL)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audio source starts\n"); audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO); /* Create gstreamer elements */ pipeline = gst_pipeline_new ("audio-recorder"); source = gst_element_factory_make ("autoaudiosrc", "audiosource"); filter = gst_element_factory_make ("capsfilter", "filter"); conv = gst_element_factory_make ("audioconvert", "converter"); resampler= gst_element_factory_make ("audioresample", "resampler"); encoder = gst_element_factory_make ("opusenc", "opus-encoder"); oggmux = gst_element_factory_make ("oggmux", "ogg-muxer"); sink = gst_element_factory_make ("appsink", "audio-output"); if (!pipeline || !filter || !source || !conv || !resampler || !encoder || !oggmux || !sink) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "One element could not be created. Exiting.\n"); return -1; } g_signal_connect (source, "child-added", G_CALLBACK (source_child_added), NULL); /* Set up the pipeline */ caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S16LE", /* "rate", G_TYPE_INT, SAMPLING_RATE,*/ "channels", G_TYPE_INT, OPUS_CHANNELS, /* "layout", G_TYPE_STRING, "interleaved",*/ NULL); g_object_set (G_OBJECT (filter), "caps", caps, NULL); gst_caps_unref (caps); g_object_set (G_OBJECT (encoder), /* "bitrate", 64000, */ /* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */ "inband-fec", INBAND_FEC_MODE, "packet-loss-percentage", PACKET_LOSS_PERCENTAGE, "max-payload-size", MAX_PAYLOAD_SIZE, "audio", FALSE, /* VoIP, not audio */ "frame-size", OPUS_FRAME_SIZE, NULL); g_object_set (G_OBJECT (oggmux), "max-delay", OGG_MAX_DELAY, "max-page-delay", OGG_MAX_PAGE_DELAY, NULL); /* we add a message handler */ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus_watch_id = gst_bus_add_watch (bus, bus_call, pipeline); gst_object_unref (bus); /* we add all elements into the pipeline */ /* audiosource | converter | resampler | opus-encoder | audio-output */ gst_bin_add_many (GST_BIN (pipeline), source, filter, conv, resampler, encoder, oggmux, sink, NULL); /* we link the elements together */ gst_element_link_many (source, filter, conv, resampler, encoder, oggmux, sink, NULL); /* Set the pipeline to "playing" state*/ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Now playing\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running...\n"); /* Iterate */ while (!abort_send) { GstSample *s; GstBuffer *b; GstMapInfo m; size_t len, msg_size; const char *ptr; int phase; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulling...\n"); s = gst_app_sink_pull_sample (GST_APP_SINK (sink)); if (NULL == s) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulled NULL\n"); break; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "...pulled!\n"); { const GstStructure *si; char *si_str; GstCaps *s_caps; char *caps_str; si = gst_sample_get_info (s); if (si) { si_str = gst_structure_to_string (si); if (si_str) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample %s\n", si_str); g_free (si_str); } } else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no info\n"); s_caps = gst_sample_get_caps (s); if (s_caps) { caps_str = gst_caps_to_string (s_caps); if (caps_str) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with caps %s\n", caps_str); g_free (caps_str); } } else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no caps\n"); } b = gst_sample_get_buffer (s); if (NULL == b || !gst_buffer_map (b, &m, GST_MAP_READ)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got NULL buffer %p or failed to map the buffer\n", b); gst_sample_unref (s); continue; } len = m.size; if (len > UINT16_MAX - sizeof (struct AudioMessage)) { GNUNET_break (0); len = UINT16_MAX - sizeof (struct AudioMessage); } msg_size = sizeof (struct AudioMessage) + len; audio_message.header.size = htons ((uint16_t) msg_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %u bytes of audio data\n", (unsigned int) msg_size); for (phase = 0; phase < 2; phase++) { size_t offset; size_t to_send; ssize_t ret; if (0 == phase) { #ifdef DEBUG_RECORD_PURE_OGG if (dump_pure_ogg) continue; #endif ptr = (const char *) &audio_message; to_send = sizeof (audio_message); } else { ptr = (const char *) m.data; to_send = len; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %u bytes on phase %d\n", (unsigned int) to_send, phase); for (offset = 0; offset < to_send; offset += ret) { ret = write (1, &ptr[offset], to_send - offset); if (0 >= ret) { if (-1 == ret) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n", (unsigned int) to_send - offset, (unsigned int) offset, (unsigned int) (to_send + offset), phase, strerror (errno)); abort_send = 1; break; } } if (abort_send) break; } gst_buffer_unmap (b, &m); gst_sample_unref (s); } signal (SIGINT, inthandler); signal (SIGINT, termhandler); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Returned, stopping playback\n"); quit (); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); pipeline = NULL; g_source_remove (bus_watch_id); return 0; } gnunet-0.10.1/src/conversation/microphone.c0000644000175000017500000001074112225777501015635 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/microphone.c * @brief API to access an audio microphone; provides access to hardware microphones; * actually just wraps the gnunet-helper-audio-record * @author Simon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_microphone_lib.h" #include "conversation.h" /** * Internal data structures for the microphone. */ struct Microphone { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for the record helper */ struct GNUNET_HELPER_Handle *record_helper; /** * Function to call with audio data (if we are enabled). */ GNUNET_MICROPHONE_RecordedDataCallback rdc; /** * Closure for @e rdc. */ void *rdc_cls; }; /** * Function to process the audio from the record helper * * @param cls clsoure with our `struct Microphone` * @param client NULL * @param msg the message from the helper * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int process_record_messages (void *cls, void *client, const struct GNUNET_MessageHeader *msg) { struct Microphone *mic = cls; const struct AudioMessage *am; if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO) { GNUNET_break (0); return GNUNET_SYSERR; } am = (const struct AudioMessage *) msg; mic->rdc (mic->rdc_cls, ntohs (msg->size) - sizeof (struct AudioMessage), &am[1]); return GNUNET_OK; } /** * Enable a microphone. * * @param cls clsoure with our `struct Microphone` * @param rdc function to call with recorded data * @param rdc_cls closure for @a dc */ static int enable (void *cls, GNUNET_MICROPHONE_RecordedDataCallback rdc, void *rdc_cls) { struct Microphone *mic = cls; static char * const record_helper_argv[] = { "gnunet-helper-audio-record", NULL }; mic->rdc = rdc; mic->rdc_cls = rdc_cls; mic->record_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-audio-record", record_helper_argv, &process_record_messages, NULL, mic); if (NULL == mic->record_helper) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not start record audio helper\n")); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Function that disables a microphone. * * @param cls clsoure */ static void disable (void *cls) { struct Microphone *mic = cls; if (NULL == mic->record_helper) { GNUNET_break (0); return; } GNUNET_break (GNUNET_OK == GNUNET_HELPER_kill (mic->record_helper, GNUNET_NO)); GNUNET_HELPER_destroy (mic->record_helper); mic->record_helper = NULL; } /** * Function to destroy a microphone. * * @param cls clsoure */ static void destroy (void *cls) { struct Microphone *mic = cls; if (NULL != mic->record_helper) disable (mic); } /** * Create a microphone that corresponds to the microphone hardware * of our system. * * @param cfg configuration to use * @return NULL on error */ struct GNUNET_MICROPHONE_Handle * GNUNET_MICROPHONE_create_from_hardware (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_MICROPHONE_Handle *microphone; struct Microphone *mic; mic = GNUNET_new (struct Microphone); mic->cfg = cfg; microphone = GNUNET_new (struct GNUNET_MICROPHONE_Handle); microphone->cls = mic; microphone->enable_microphone = &enable; microphone->disable_microphone = &disable; microphone->destroy_microphone = &destroy; return microphone; } /** * Destroy a microphone. * * @param microphone microphone to destroy */ void GNUNET_MICROPHONE_destroy (struct GNUNET_MICROPHONE_Handle *microphone) { microphone->destroy_microphone (microphone->cls); GNUNET_free (microphone); } /* end of microphone.c */ gnunet-0.10.1/src/conversation/test_conversation.conf0000644000175000017500000000007012252374775017746 00000000000000[conversation] LINE=1 [arm] DEFAULTSERVICES = topology gnunet-0.10.1/src/conversation/plugin_gnsrecord_conversation.c0000644000175000017500000001345512227705277021640 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/plugin_gnsrecord_conversation.c * @brief gnsrecord plugin to provide the API for fundamental GNS records * This includes the VPN record because GNS resolution * is expected to understand VPN records and (if needed) * map the result to A/AAAA. * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_conversation_service.h" #include "gnunet_gnsrecord_plugin.h" /** * Convert the 'value' of a record to a string. * * @param cls closure, unused * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in @a data * @return NULL on error, otherwise human-readable representation of the value */ static char * conversation_value_to_string (void *cls, uint32_t type, const void *data, size_t data_size) { switch (type) { case GNUNET_GNSRECORD_TYPE_PHONE: { const struct GNUNET_CONVERSATION_PhoneRecord *pr; char *ret; char *pkey; if (data_size != sizeof (struct GNUNET_CONVERSATION_PhoneRecord)) return NULL; pr = data; if (0 != ntohl (pr->version)) return NULL; pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&pr->peer.public_key); GNUNET_asprintf (&ret, "%u-%s", ntohl (pr->line), pkey); GNUNET_free (pkey); return ret; } default: return NULL; } } /** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param cls closure, unused * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ static int conversation_string_to_value (void *cls, uint32_t type, const char *s, void **data, size_t *data_size) { if (NULL == s) return GNUNET_SYSERR; switch (type) { case GNUNET_GNSRECORD_TYPE_PHONE: { struct GNUNET_CONVERSATION_PhoneRecord *pr; unsigned int line; const char *dash; struct GNUNET_PeerIdentity peer; if ( (NULL == (dash = strchr (s, '-'))) || (1 != sscanf (s, "%u-", &line)) || (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1, strlen (dash + 1), &peer.public_key)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PHONE record `%s'\n"), s); return GNUNET_SYSERR; } pr = GNUNET_new (struct GNUNET_CONVERSATION_PhoneRecord); pr->version = htonl (0); pr->line = htonl ((uint32_t) line); pr->peer = peer; *data = pr; *data_size = sizeof (struct GNUNET_CONVERSATION_PhoneRecord); return GNUNET_OK; } default: return GNUNET_SYSERR; } } /** * Mapping of record type numbers to human-readable * record type names. */ static struct { const char *name; uint32_t number; } name_map[] = { { "PHONE", GNUNET_GNSRECORD_TYPE_PHONE }, { NULL, UINT32_MAX } }; /** * Convert a type name (i.e. "AAAA") to the corresponding number. * * @param cls closure, unused * @param gns_typename name to convert * @return corresponding number, UINT32_MAX on error */ static uint32_t conversation_typename_to_number (void *cls, const char *gns_typename) { unsigned int i; i=0; while ( (name_map[i].name != NULL) && (0 != strcasecmp (gns_typename, name_map[i].name)) ) i++; return name_map[i].number; } /** * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") * * @param cls closure, unused * @param type number of a type to convert * @return corresponding typestring, NULL on error */ static const char * conversation_number_to_typename (void *cls, uint32_t type) { unsigned int i; i=0; while ( (name_map[i].name != NULL) && (type != name_map[i].number) ) i++; return name_map[i].name; } /** * Entry point for the plugin. * * @param cls NULL * @return the exported block API */ void * libgnunet_plugin_gnsrecord_conversation_init (void *cls) { struct GNUNET_GNSRECORD_PluginFunctions *api; api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions); api->value_to_string = &conversation_value_to_string; api->string_to_value = &conversation_string_to_value; api->typename_to_number = &conversation_typename_to_number; api->number_to_typename = &conversation_number_to_typename; return api; } /** * Exit point from the plugin. * * @param cls the return value from #libgnunet_plugin_block_test_init * @return NULL */ void * libgnunet_plugin_gnsrecord_conversation_done (void *cls) { struct GNUNET_GNSRECORD_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_gnsrecord_conversation.c */ gnunet-0.10.1/src/conversation/gnunet-conversation-test.c0000644000175000017500000001365512234016112020446 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/gnunet-conversation-test.c * @brief tool to test speaker and microphone (for end users!) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_speaker_lib.h" #include "gnunet_microphone_lib.h" /** * How long do we record before we replay? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * A recording we made. */ struct Recording { /** * Kept in a DLL. */ struct Recording *next; /** * Kept in a DLL. */ struct Recording *prev; /** * Number of bytes that follow. */ size_t size; }; /** * Final status code. */ static int ret; /** * Handle to the microphone. */ static struct GNUNET_MICROPHONE_Handle *microphone; /** * Handle to the speaker. */ static struct GNUNET_SPEAKER_Handle *speaker; /** * Task scheduled to switch from recording to playback. */ static GNUNET_SCHEDULER_TaskIdentifier switch_task; /** * The shutdown task. */ static GNUNET_SCHEDULER_TaskIdentifier st; /** * Head of DLL with recorded frames. */ static struct Recording *rec_head; /** * Tail of DLL with recorded frames. */ static struct Recording *rec_tail; /** * Terminate test. * * @param cls NULL * @param tc unused */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Recording *rec; if (GNUNET_SCHEDULER_NO_TASK != switch_task) GNUNET_SCHEDULER_cancel (switch_task); if (NULL != microphone) GNUNET_MICROPHONE_destroy (microphone); if (NULL != speaker) GNUNET_SPEAKER_destroy (speaker); while (NULL != (rec = rec_head)) { GNUNET_CONTAINER_DLL_remove (rec_head, rec_tail, rec); GNUNET_free (rec); } fprintf (stderr, _("\nEnd of transmission. Have a GNU day.\n")); } /** * Terminate recording process and switch to playback. * * @param cls NULL * @param tc unused */ static void switch_to_speaker (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Recording *rec; switch_task = GNUNET_SCHEDULER_NO_TASK; microphone->disable_microphone (microphone->cls); if (GNUNET_OK != speaker->enable_speaker (speaker->cls)) { fprintf (stderr, "Failed to enable microphone\n"); ret = 1; GNUNET_SCHEDULER_shutdown (); return; } fprintf (stderr, _("\nWe are now playing your recording back. If you can hear it, your audio settings are working...")); for (rec=rec_head; NULL != rec; rec = rec->next) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Replaying %u bytes\n", (unsigned int) rec->size); speaker->play (speaker->cls, rec->size, &rec[1]); } GNUNET_SCHEDULER_cancel (st); st = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &do_shutdown, NULL); } /** * Process recorded audio data. * * @param cls clsoure * @param data_size number of bytes in @a data * @param data audio data to play */ static void record (void *cls, size_t data_size, const void *data) { struct Recording *rec; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Recorded %u bytes\n", (unsigned int) data_size); rec = GNUNET_malloc (sizeof (struct Recording) + data_size); rec->size = data_size; memcpy (&rec[1], data, data_size); GNUNET_CONTAINER_DLL_insert_tail (rec_head, rec_tail, rec); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { microphone = GNUNET_MICROPHONE_create_from_hardware (cfg); GNUNET_assert (NULL != microphone); speaker = GNUNET_SPEAKER_create_from_hardware (cfg); GNUNET_assert (NULL != speaker); switch_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &switch_to_speaker, NULL); st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); fprintf (stderr, _("We will now be recording you for %s. After that time, the recording will be played back to you..."), GNUNET_STRINGS_relative_time_to_string (TIMEOUT, GNUNET_YES)); if (GNUNET_OK != microphone->enable_microphone (microphone->cls, &record, NULL)) { fprintf (stderr, "Failed to enable microphone\n"); ret = 1; GNUNET_SCHEDULER_shutdown (); return; } } /** * The main function of our code to test microphone and speaker. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-conversation-test", gettext_noop ("help text"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-conversation-test.c */ gnunet-0.10.1/src/conversation/Makefile.am0000644000175000017500000001455712320751517015366 00000000000000SUBDIRS = . plugindir = $(libdir)/gnunet if MINGW WINFLAGS = -no-undefined -Wl,--export-all-symbols endif AM_CPPFLAGS = \ $(GNUNET_CPPFLAGS) \ -I$(top_srcdir)/src/include \ -I$(top_srcdir) lib_LTLIBRARIES = \ libgnunetmicrophone.la \ libgnunetspeaker.la \ libgnunetconversation.la pkgcfgdir= $(prefix)/share/gnunet/config.d/ libexecdir= $(prefix)/lib/gnunet/libexec/ plugin_LTLIBRARIES = \ libgnunet_plugin_gnsrecord_conversation.la libgnunet_plugin_gnsrecord_conversation_la_SOURCES = \ plugin_gnsrecord_conversation.c libgnunet_plugin_gnsrecord_conversation_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_gnsrecord_conversation_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunetmicrophone_la_SOURCES = \ microphone.c libgnunetmicrophone_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetmicrophone_la_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetspeaker_la_SOURCES = \ speaker.c libgnunetspeaker_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetspeaker_la_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetconversation_la_SOURCES = \ conversation_api.c \ conversation_api_call.c \ conversation.h libgnunetconversation_la_LIBADD = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunetconversation_la_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 bin_PROGRAMS = \ gnunet-conversation-test \ gnunet-conversation libexec_PROGRAMS = \ gnunet-service-conversation check_PROGRAMS = \ test_conversation_api \ test_conversation_api_reject \ test_conversation_api_twocalls if BUILD_PULSE_HELPERS AUDIO_HELPER_RECD=gnunet-helper-audio-record AUDIO_HELPER_PLAY=gnunet-helper-audio-playback AUDIO_TESTS=$(check_PROGRAMS) else if BUILD_GST_HELPERS AUDIO_HELPER_RECD=gnunet-helper-audio-record AUDIO_HELPER_PLAY=gnunet-helper-audio-playback AUDIO_TESTS=$(check_PROGRAMS) endif endif libexec_PROGRAMS += \ $(AUDIO_HELPER_RECD) \ $(AUDIO_HELPER_PLAY) AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(AUDIO_TESTS) if BUILD_PULSE_HELPERS gnunet_helper_audio_record_SOURCES = \ gnunet-helper-audio-record.c gnunet_helper_audio_record_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -lpulse -lopus -logg \ $(INTLLIBS) gnunet_helper_audio_record_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) gnunet_helper_audio_playback_SOURCES = \ gnunet-helper-audio-playback.c gnunet_helper_audio_playback_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -lpulse -lopus -logg \ $(INTLLIBS) gnunet_helper_audio_playback_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) else if BUILD_GST_HELPERS gnunet_helper_audio_record_SOURCES = \ gnunet-helper-audio-record-gst.c gnunet_helper_audio_record_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GST_LIBS) \ $(INTLLIBS) gnunet_helper_audio_record_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) $(GST_LDFLAGS) gnunet_helper_audio_record_CFLAGS = \ $(GST_CFLAGS) gnunet_helper_audio_playback_SOURCES = \ gnunet-helper-audio-playback-gst.c gnunet_helper_audio_playback_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GST_LIBS) \ $(INTLLIBS) gnunet_helper_audio_playback_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) $(GST_LDFLAGS) gnunet_helper_audio_playback_CFLAGS = \ $(GST_CFLAGS) endif endif gnunet_service_conversation_SOURCES = \ gnunet-service-conversation.c gnunet_service_conversation_LDADD = \ libgnunetconversation.la \ libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(INTLLIBS) gnunet_service_conversation_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) gnunet_conversation_SOURCES = \ gnunet-conversation.c gnunet_conversation_LDADD = \ libgnunetmicrophone.la \ libgnunetspeaker.la \ libgnunetconversation.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(INTLLIBS) gnunet_conversation_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) gnunet_conversation_test_SOURCES = \ gnunet-conversation-test.c gnunet_conversation_test_LDADD = \ libgnunetmicrophone.la \ libgnunetspeaker.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(INTLLIBS) gnunet_conversation_test_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) test_conversation_api_SOURCES = \ test_conversation_api.c test_conversation_api_LDADD = \ libgnunetconversation.la \ libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic test_conversation_api_twocalls_SOURCES = \ test_conversation_api_twocalls.c test_conversation_api_twocalls_LDADD = \ libgnunetconversation.la \ libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_twocalls_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic test_conversation_api_reject_SOURCES = \ test_conversation_api_reject.c test_conversation_api_reject_LDADD = \ libgnunetconversation.la \ libgnunetspeaker.la \ libgnunetmicrophone.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_conversation_api_reject_LDFLAGS = \ $(GNUNET_LDFLAGS) $(WINFLAGS) -export-dynamic pkgcfg_DATA = conversation.conf EXTRA_DIST = test_conversation.conf gnunet-0.10.1/src/conversation/conversation.h0000644000175000017500000001552612254054615016213 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file conversation/conversation.h * @brief constants for network protocols * @author Siomon Dieterle * @author Andreas Fuchs */ #ifndef CONVERSATION_H #define CONVERSATION_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #define MAX_TRANSMIT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * Message to transmit the audio (between client and helpers). */ struct AudioMessage { /** * Type is #GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO */ struct GNUNET_MessageHeader header; /* followed by audio data */ }; /** * Client -> Service message to register a phone. */ struct ClientPhoneRegisterMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER */ struct GNUNET_MessageHeader header; /** * Phone line to register. */ uint32_t line GNUNET_PACKED; }; /** * Service -> Client message for phone is ringing. */ struct ClientPhoneRingMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING */ struct GNUNET_MessageHeader header; /** * CID, internal caller ID to identify which active call we are * talking about. */ uint32_t cid GNUNET_PACKED; /** * Who is calling us? */ struct GNUNET_CRYPTO_EcdsaPublicKey caller_id; }; /** * Service <-> Client message for phone was suspended. */ struct ClientPhoneSuspendMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND */ struct GNUNET_MessageHeader header; /** * CID, internal caller ID to identify which active call we are * talking about. */ uint32_t cid GNUNET_PACKED; }; /** * Service <-> Client message for phone was resumed. */ struct ClientPhoneResumeMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME */ struct GNUNET_MessageHeader header; /** * CID, internal caller ID to identify which active call we are * talking about. */ uint32_t cid GNUNET_PACKED; }; /** * Client -> Service pick up phone that is ringing. */ struct ClientPhonePickupMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP */ struct GNUNET_MessageHeader header; /** * CID, internal caller ID to identify which active call we are * talking about. */ uint32_t cid GNUNET_PACKED; }; /** * Client <-> Service hang up phone that may or may not be ringing. * Also sent in response to a (failed) `struct ClientCallMessage`. */ struct ClientPhoneHangupMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP */ struct GNUNET_MessageHeader header; /** * CID, internal caller ID to identify which active call we are * talking about. */ uint32_t cid GNUNET_PACKED; }; /** * Message Client <->Service to transmit the audio. */ struct ClientAudioMessage { /** * Type is #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO */ struct GNUNET_MessageHeader header; /** * CID, internal caller ID to identify which active call we are * sending data to. */ uint32_t cid GNUNET_PACKED; /* followed by audio data */ }; /** * Client -> Service message to call a phone. */ struct ClientCallMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL */ struct GNUNET_MessageHeader header; /** * Which phone line to call at the peer? */ uint32_t line GNUNET_PACKED; /** * Which peer is hosting the line? */ struct GNUNET_PeerIdentity target; /** * Identity of the caller. */ struct GNUNET_CRYPTO_EcdsaPrivateKey caller_id; }; /** * Service -> Client: other peer has picked up the phone, we are * now talking. */ struct ClientPhonePickedupMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP */ struct GNUNET_MessageHeader header; }; /** * Mesh message for phone is ringing. */ struct MeshPhoneRingMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING */ struct GNUNET_MessageHeader header; /** * Desired target line. */ uint32_t remote_line GNUNET_PACKED; /** * Purpose for the signature. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Who is calling us? (also who is signing). */ struct GNUNET_CRYPTO_EcdsaPublicKey caller_id; /** * Who are we calling? */ struct GNUNET_PeerIdentity target; /** * From where are we calling? */ struct GNUNET_PeerIdentity source; /** * When does the signature expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * Signature on the above. */ struct GNUNET_CRYPTO_EcdsaSignature signature; /** * Source line for audio data in the other direction. */ uint32_t source_line GNUNET_PACKED; }; /** * Mesh message for hanging up. */ struct MeshPhoneHangupMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP */ struct GNUNET_MessageHeader header; }; /** * Mesh message for picking up. */ struct MeshPhonePickupMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP */ struct GNUNET_MessageHeader header; }; /** * Mesh message for phone suspended. */ struct MeshPhoneSuspendMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_SUSPEND */ struct GNUNET_MessageHeader header; }; /** * Mesh message for phone resumed. */ struct MeshPhoneResumeMessage { /** * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RESUME */ struct GNUNET_MessageHeader header; }; /** * Mesh message to transmit the audio. */ struct MeshAudioMessage { /** * Type is #GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO */ struct GNUNET_MessageHeader header; /** * Target line on the receiving end. */ uint32_t remote_line GNUNET_PACKED; /** * The source line sending this data */ uint32_t source_line GNUNET_PACKED; /* followed by audio data */ }; #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_PROTOCOLS_CONVERSATION_H */ #endif /* end of gnunet_protocols_conversation.h */ gnunet-0.10.1/src/mysql/0000755000175000017500000000000012320755623012033 500000000000000gnunet-0.10.1/src/mysql/Makefile.in0000644000175000017500000005516512320752062014026 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = src/mysql DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetmysql_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetmysql_la_OBJECTS = mysql.lo libgnunetmysql_la_OBJECTS = $(am_libgnunetmysql_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetmysql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetmysql_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_MYSQL_TRUE@am_libgnunetmysql_la_rpath = -rpath $(libdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetmysql_la_SOURCES) DIST_SOURCES = $(libgnunetmysql_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage @HAVE_MYSQL_TRUE@lib_LTLIBRARIES = libgnunetmysql.la libgnunetmysql_la_SOURCES = \ mysql.c libgnunetmysql_la_LIBADD = $(MYSQL_LDFLAGS) -lmysqlclient \ $(top_builddir)/src/util/libgnunetutil.la libgnunetmysql_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/mysql/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/mysql/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetmysql.la: $(libgnunetmysql_la_OBJECTS) $(libgnunetmysql_la_DEPENDENCIES) $(EXTRA_libgnunetmysql_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetmysql_la_LINK) $(am_libgnunetmysql_la_rpath) $(libgnunetmysql_la_OBJECTS) $(libgnunetmysql_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mysql.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/mysql/Makefile.am0000644000175000017500000000066512320751517014014 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage endif if HAVE_MYSQL lib_LTLIBRARIES = libgnunetmysql.la endif libgnunetmysql_la_SOURCES = \ mysql.c libgnunetmysql_la_LIBADD = $(MYSQL_LDFLAGS) -lmysqlclient \ $(top_builddir)/src/util/libgnunetutil.la libgnunetmysql_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 gnunet-0.10.1/src/mysql/mysql.c0000644000175000017500000004701712255010512013261 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mysql/mysql.c * @brief library to help with access to a MySQL database * @author Christian Grothoff */ #include "platform.h" #include #include "gnunet_mysql_lib.h" /** * Maximum number of supported parameters for a prepared * statement. Increase if needed. */ #define MAX_PARAM 16 /** * Die with an error message that indicates * a failure of the command 'cmd' with the message given * by strerror(errno). */ #define DIE_MYSQL(cmd, dbh) do { GNUNET_log_from (GNUNET_ERROR_TYPE__ERROR, "mysql", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); GNUNET_abort(); } while(0); /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_MYSQL(level, cmd, dbh) do { GNUNET_log_from (level, "mysql", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, mysql_error((dbh)->dbf)); } while(0); /** * Mysql context. */ struct GNUNET_MYSQL_Context { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Our section. */ const char *section; /** * Handle to the mysql database. */ MYSQL *dbf; /** * Head of list of our prepared statements. */ struct GNUNET_MYSQL_StatementHandle *shead; /** * Tail of list of our prepared statements. */ struct GNUNET_MYSQL_StatementHandle *stail; /** * Filename of "my.cnf" (msyql configuration). */ char *cnffile; }; /** * Handle for a prepared statement. */ struct GNUNET_MYSQL_StatementHandle { /** * Kept in a DLL. */ struct GNUNET_MYSQL_StatementHandle *next; /** * Kept in a DLL. */ struct GNUNET_MYSQL_StatementHandle *prev; /** * Original query string. */ char *query; /** * Handle to MySQL prepared statement. */ MYSQL_STMT *statement; /** * Is the MySQL prepared statement valid, or do we need to re-initialize it? */ int valid; }; /** * Obtain the location of ".my.cnf". * * @param cfg our configuration * @param section the section * @return NULL on error */ static char * get_my_cnf_path (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section) { char *cnffile; char *home_dir; struct stat st; #ifndef WINDOWS struct passwd *pw; #endif int configured; #ifndef WINDOWS pw = getpwuid (getuid ()); if (!pw) { GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_ERROR, "mysql", "getpwuid"); return NULL; } if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, section, "CONFIG")) { GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG", &cnffile)); configured = GNUNET_YES; } else { home_dir = GNUNET_strdup (pw->pw_dir); GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); GNUNET_free (home_dir); configured = GNUNET_NO; } #else home_dir = (char *) GNUNET_malloc (_MAX_PATH + 1); plibc_conv_to_win_path ("~/", home_dir); GNUNET_asprintf (&cnffile, "%s/.my.cnf", home_dir); GNUNET_free (home_dir); configured = GNUNET_NO; #endif GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql", _("Trying to use file `%s' for MySQL configuration.\n"), cnffile); if ((0 != STAT (cnffile, &st)) || (0 != ACCESS (cnffile, R_OK)) || (!S_ISREG (st.st_mode))) { if (configured == GNUNET_YES) GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", _("Could not access file `%s': %s\n"), cnffile, STRERROR (errno)); GNUNET_free (cnffile); return NULL; } return cnffile; } /** * Open the connection with the database (and initialize * our default options). * * @param mc database context to initialze * @return GNUNET_OK on success */ static int iopen (struct GNUNET_MYSQL_Context *mc) { char *mysql_dbname; char *mysql_server; char *mysql_user; char *mysql_password; unsigned long long mysql_port; my_bool reconnect; unsigned int timeout; mc->dbf = mysql_init (NULL); if (mc->dbf == NULL) return GNUNET_SYSERR; if (mc->cnffile != NULL) mysql_options (mc->dbf, MYSQL_READ_DEFAULT_FILE, mc->cnffile); mysql_options (mc->dbf, MYSQL_READ_DEFAULT_GROUP, "client"); reconnect = 0; mysql_options (mc->dbf, MYSQL_OPT_RECONNECT, &reconnect); mysql_options (mc->dbf, MYSQL_OPT_CONNECT_TIMEOUT, (const void *) &timeout); mysql_options (mc->dbf, MYSQL_SET_CHARSET_NAME, "UTF8"); timeout = 60; /* in seconds */ mysql_options (mc->dbf, MYSQL_OPT_READ_TIMEOUT, (const void *) &timeout); mysql_options (mc->dbf, MYSQL_OPT_WRITE_TIMEOUT, (const void *) &timeout); mysql_dbname = NULL; if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "DATABASE")) GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (mc->cfg, mc->section, "DATABASE", &mysql_dbname)); else mysql_dbname = GNUNET_strdup ("gnunet"); mysql_user = NULL; if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "USER")) { GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (mc->cfg, mc->section, "USER", &mysql_user)); } mysql_password = NULL; if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "PASSWORD")) { GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (mc->cfg, mc->section, "PASSWORD", &mysql_password)); } mysql_server = NULL; if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "HOST")) { GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (mc->cfg, mc->section, "HOST", &mysql_server)); } mysql_port = 0; if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (mc->cfg, mc->section, "PORT")) { GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (mc->cfg, mc->section, "PORT", &mysql_port)); } GNUNET_assert (mysql_dbname != NULL); mysql_real_connect (mc->dbf, mysql_server, mysql_user, mysql_password, mysql_dbname, (unsigned int) mysql_port, NULL, CLIENT_IGNORE_SIGPIPE); GNUNET_free_non_null (mysql_server); GNUNET_free_non_null (mysql_user); GNUNET_free_non_null (mysql_password); GNUNET_free (mysql_dbname); if (mysql_error (mc->dbf)[0]) { LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_real_connect", mc); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Create a mysql context. * * @param cfg configuration * @param section configuration section to use to get MySQL configuration options * @return the mysql context */ struct GNUNET_MYSQL_Context * GNUNET_MYSQL_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section) { struct GNUNET_MYSQL_Context *mc; mc = GNUNET_new (struct GNUNET_MYSQL_Context); mc->cfg = cfg; mc->section = section; mc->cnffile = get_my_cnf_path (cfg, section); return mc; } /** * Close database connection and all prepared statements (we got a DB * error). * * @param mc mysql context */ void GNUNET_MYSQL_statements_invalidate (struct GNUNET_MYSQL_Context *mc) { struct GNUNET_MYSQL_StatementHandle *sh; for (sh = mc->shead; NULL != sh; sh = sh->next) { if (GNUNET_YES == sh->valid) { mysql_stmt_close (sh->statement); sh->valid = GNUNET_NO; } sh->statement = NULL; } if (NULL != mc->dbf) { mysql_close (mc->dbf); mc->dbf = NULL; } } /** * Destroy a mysql context. Also frees all associated prepared statements. * * @param mc context to destroy */ void GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc) { struct GNUNET_MYSQL_StatementHandle *sh; GNUNET_MYSQL_statements_invalidate (mc); while (NULL != (sh = mc->shead)) { GNUNET_CONTAINER_DLL_remove (mc->shead, mc->stail, sh); GNUNET_free (sh->query); GNUNET_free (sh); } GNUNET_free (mc); mysql_library_end (); } /** * Prepare a statement. Prepared statements are automatically discarded * when the MySQL context is destroyed. * * @param mc mysql context * @param query query text * @return prepared statement, NULL on error */ struct GNUNET_MYSQL_StatementHandle * GNUNET_MYSQL_statement_prepare (struct GNUNET_MYSQL_Context *mc, const char *query) { struct GNUNET_MYSQL_StatementHandle *sh; sh = GNUNET_new (struct GNUNET_MYSQL_StatementHandle); sh->query = GNUNET_strdup (query); GNUNET_CONTAINER_DLL_insert (mc->shead, mc->stail, sh); return sh; } /** * Run a SQL statement. * * @param mc mysql context * @param sql SQL statement to run * @return GNUNET_OK on success * GNUNET_SYSERR if there was a problem */ int GNUNET_MYSQL_statement_run (struct GNUNET_MYSQL_Context *mc, const char *sql) { if ((NULL == mc->dbf) && (GNUNET_OK != iopen (mc))) return GNUNET_SYSERR; mysql_query (mc->dbf, sql); if (mysql_error (mc->dbf)[0]) { LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_query", mc); GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Prepare a statement for running. * * @param mc mysql context * @param sh statement handle to prepare * @return GNUNET_OK on success */ static int prepare_statement (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *sh) { if (GNUNET_YES == sh->valid) return GNUNET_OK; if ((NULL == mc->dbf) && (GNUNET_OK != iopen (mc))) return GNUNET_SYSERR; sh->statement = mysql_stmt_init (mc->dbf); if (NULL == sh->statement) { GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } if (0 != mysql_stmt_prepare (sh->statement, sh->query, strlen (sh->query))) { LOG_MYSQL (GNUNET_ERROR_TYPE_ERROR, "mysql_stmt_prepare", mc); mysql_stmt_close (sh->statement); sh->statement = NULL; GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } sh->valid = GNUNET_YES; return GNUNET_OK; } /** * Get internal handle for a prepared statement. This function should rarely * be used, and if, with caution! On failures during the interaction with * the handle, you must call 'GNUNET_MYSQL_statements_invalidate'! * * @param mc mysql context * @param sh prepared statement to introspect * @return MySQL statement handle, NULL on error */ MYSQL_STMT * GNUNET_MYSQL_statement_get_stmt (struct GNUNET_MYSQL_Context * mc, struct GNUNET_MYSQL_StatementHandle * sh) { (void) prepare_statement (mc, sh); return sh->statement; } /** * Bind the parameters for the given MySQL statement * and run it. * * @param mc mysql context * @param sh statement to bind and run * @param ap arguments for the binding * @return GNUNET_SYSERR on error, GNUNET_OK on success */ static int init_params (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *sh, va_list ap) { MYSQL_BIND qbind[MAX_PARAM]; unsigned int pc; unsigned int off; enum enum_field_types ft; pc = mysql_stmt_param_count (sh->statement); if (pc > MAX_PARAM) { /* increase internal constant! */ GNUNET_break (0); return GNUNET_SYSERR; } memset (qbind, 0, sizeof (qbind)); off = 0; ft = 0; while ((pc > 0) && (-1 != (int) (ft = va_arg (ap, enum enum_field_types)))) { qbind[off].buffer_type = ft; switch (ft) { case MYSQL_TYPE_FLOAT: qbind[off].buffer = va_arg (ap, float *); break; case MYSQL_TYPE_LONGLONG: qbind[off].buffer = va_arg (ap, unsigned long long *); qbind[off].is_unsigned = va_arg (ap, int); break; case MYSQL_TYPE_LONG: qbind[off].buffer = va_arg (ap, unsigned int *); qbind[off].is_unsigned = va_arg (ap, int); break; case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: case MYSQL_TYPE_BLOB: qbind[off].buffer = va_arg (ap, void *); qbind[off].buffer_length = va_arg (ap, unsigned long); qbind[off].length = va_arg (ap, unsigned long *); break; default: /* unsupported type */ GNUNET_break (0); return GNUNET_SYSERR; } pc--; off++; } if (!((pc == 0) && (-1 != (int) ft) && (va_arg (ap, int) == -1))) { GNUNET_break (0); return GNUNET_SYSERR; } if (mysql_stmt_bind_param (sh->statement, qbind)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_param", __FILE__, __LINE__, mysql_stmt_error (sh->statement)); GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } if (mysql_stmt_execute (sh->statement)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_execute", __FILE__, __LINE__, mysql_stmt_error (sh->statement)); GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Run a prepared SELECT statement. * * @param mc mysql context * @param s statement to run * @param result_size number of elements in results array * @param results pointer to already initialized MYSQL_BIND * array (of sufficient size) for passing results * @param processor function to call on each result * @param processor_cls extra argument to processor * @param ap pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective * values (size + buffer-reference for pointers); terminated * with "-1" * @return GNUNET_SYSERR on error, otherwise * the number of successfully affected (or queried) rows */ int GNUNET_MYSQL_statement_run_prepared_select_va (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *s, unsigned int result_size, MYSQL_BIND * results, GNUNET_MYSQL_DataProcessor processor, void *processor_cls, va_list ap) { int ret; unsigned int rsize; int total; if (GNUNET_OK != prepare_statement (mc, s)) { GNUNET_break (0); return GNUNET_SYSERR; } if (GNUNET_OK != init_params (mc, s, ap)) { GNUNET_break (0); return GNUNET_SYSERR; } rsize = mysql_stmt_field_count (s->statement); if (rsize > result_size) { GNUNET_break (0); return GNUNET_SYSERR; } if (mysql_stmt_bind_result (s->statement, results)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_result", __FILE__, __LINE__, mysql_stmt_error (s->statement)); GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } total = 0; while (1) { ret = mysql_stmt_fetch (s->statement); if (ret == MYSQL_NO_DATA) break; if (ret != 0) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_fetch", __FILE__, __LINE__, mysql_stmt_error (s->statement)); GNUNET_MYSQL_statements_invalidate (mc); return GNUNET_SYSERR; } total++; if ((NULL == processor) || (GNUNET_OK != processor (processor_cls, rsize, results))) break; } mysql_stmt_reset (s->statement); return total; } /** * Run a prepared SELECT statement. * * @param mc mysql context * @param sh handle to SELECT statment * @param result_size number of elements in results array * @param results pointer to already initialized MYSQL_BIND * array (of sufficient size) for passing results * @param processor function to call on each result * @param processor_cls extra argument to processor * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective * values (size + buffer-reference for pointers); terminated * with "-1" * @return GNUNET_SYSERR on error, otherwise * the number of successfully affected (or queried) rows */ int GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *sh, unsigned int result_size, MYSQL_BIND * results, GNUNET_MYSQL_DataProcessor processor, void *processor_cls, ...) { va_list ap; int ret; va_start (ap, processor_cls); ret = GNUNET_MYSQL_statement_run_prepared_select_va (mc, sh, result_size, results, processor, processor_cls, ap); va_end (ap); return ret; } /** * Run a prepared statement that does NOT produce results. * * @param mc mysql context * @param sh handle to statment * @param insert_id NULL or address where to store the row ID of whatever * was inserted (only for INSERT statements!) * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective * values (size + buffer-reference for pointers); terminated * with "-1" * @return GNUNET_SYSERR on error, otherwise * the number of successfully affected rows */ int GNUNET_MYSQL_statement_run_prepared (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *sh, unsigned long long *insert_id, ...) { va_list ap; int affected; if (GNUNET_OK != prepare_statement (mc, sh)) return GNUNET_SYSERR; va_start (ap, insert_id); if (GNUNET_OK != init_params (mc, sh, ap)) { va_end (ap); return GNUNET_SYSERR; } va_end (ap); affected = mysql_stmt_affected_rows (sh->statement); if (NULL != insert_id) *insert_id = (unsigned long long) mysql_stmt_insert_id (sh->statement); mysql_stmt_reset (sh->statement); return affected; } /* end of mysql.c */ gnunet-0.10.1/src/env/0000755000175000017500000000000012320755627011462 500000000000000gnunet-0.10.1/src/env/test_env.c0000644000175000017500000000520712262754601013375 00000000000000/* * This file is part of GNUnet. * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file env/test_env.c * @brief Tests for the environment library. * @author Gabor X Toth */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_env_lib.h" struct GNUNET_ENV_Modifier mods[] = { { .oper = GNUNET_ENV_OP_SET, .name = "_foo", .value = "foo", .value_size = 3 }, { .oper = GNUNET_ENV_OP_ASSIGN, .name = "_foo_bar", .value = "foo bar", .value_size = 7 }, { .oper = GNUNET_ENV_OP_AUGMENT, .name = "_foo_bar_baz", .value = "foo bar baz", .value_size = 11 } }; struct ItCls { size_t n; }; int iterator (void *cls, enum GNUNET_ENV_Operator oper, const char *name, const char *value, uint32_t value_size) { struct ItCls *it_cls = cls; struct GNUNET_ENV_Modifier *m = &mods[it_cls->n++]; GNUNET_assert (oper == m->oper); GNUNET_assert (value_size == m->value_size); GNUNET_assert (0 == memcmp (name, m->name, strlen (m->name))); GNUNET_assert (0 == memcmp (value, m->value, m->value_size)); return GNUNET_YES; } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-env", "WARNING", NULL); struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); GNUNET_assert (NULL != env); int i, len = 3; for (i = 0; i < len; i++) { GNUNET_ENV_environment_add (env, mods[i].oper, mods[i].name, mods[i].value, mods[i].value_size); } struct ItCls it_cls = { .n = 0 }; GNUNET_ENV_environment_iterate (env, iterator, &it_cls); GNUNET_assert (len == it_cls.n); for (i = 0; i < len; i++) { enum GNUNET_ENV_Operator oper; const char *name; const void *value; size_t value_size; GNUNET_ENV_environment_shift (env, &oper, &name, &value, &value_size); GNUNET_assert (len - i - 1 == GNUNET_ENV_environment_get_count (env)); } GNUNET_ENV_environment_destroy (env); return 0; } gnunet-0.10.1/src/env/Makefile.in0000644000175000017500000011013112320752061013431 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @HAVE_TESTING_TRUE@check_PROGRAMS = test_env$(EXEEXT) subdir = src/env DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunetenv_la_OBJECTS = env.lo libgnunetenv_la_OBJECTS = $(am_libgnunetenv_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetenv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetenv_la_LDFLAGS) $(LDFLAGS) \ -o $@ am_test_env_OBJECTS = test_env.$(OBJEXT) test_env_OBJECTS = $(am_test_env_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetenv_la_SOURCES) $(test_env_SOURCES) DIST_SOURCES = $(libgnunetenv_la_SOURCES) $(test_env_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov lib_LTLIBRARIES = libgnunetenv.la libgnunetenv_la_SOURCES = \ env.c libgnunetenv_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetenv_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetenv_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_env_SOURCES = \ test_env.c test_env_LDADD = \ libgnunetenv.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_env_DEPENDENCIES = \ libgnunetenv.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/env/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/env/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetenv.la: $(libgnunetenv_la_OBJECTS) $(libgnunetenv_la_DEPENDENCIES) $(EXTRA_libgnunetenv_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetenv_la_LINK) -rpath $(libdir) $(libgnunetenv_la_OBJECTS) $(libgnunetenv_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list test_env$(EXEEXT): $(test_env_OBJECTS) $(test_env_DEPENDENCIES) $(EXTRA_test_env_DEPENDENCIES) @rm -f test_env$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_env_OBJECTS) $(test_env_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_env.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_env.log: test_env$(EXEEXT) @p='test_env$(EXEEXT)'; \ b='test_env'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/env/Makefile.am0000644000175000017500000000214112320751517013426 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif lib_LTLIBRARIES = libgnunetenv.la libgnunetenv_la_SOURCES = \ env.c libgnunetenv_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetenv_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetenv_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la if HAVE_TESTING check_PROGRAMS = \ test_env endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_env_SOURCES = \ test_env.c test_env_LDADD = \ libgnunetenv.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_env_DEPENDENCIES = \ libgnunetenv.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet-0.10.1/src/env/env.c0000644000175000017500000001111312262754601012327 00000000000000/* * This file is part of GNUnet. * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file env/env.c * @brief Library providing operations for the @e environment of * PSYC and Social messages, and for (de)serializing variable values. * @author Gabor X Toth */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_env_lib.h" /** * Environment for a message. * * Contains modifiers. */ struct GNUNET_ENV_Environment { struct GNUNET_ENV_Modifier *mod_head; struct GNUNET_ENV_Modifier *mod_tail; size_t mod_count; }; /** * Create an environment. * * @return A newly allocated environment. */ struct GNUNET_ENV_Environment * GNUNET_ENV_environment_create () { return GNUNET_new (struct GNUNET_ENV_Environment); } /** * Add a modifier to the environment. * * @param env The environment. * @param oper Operation to perform. * @param name Name of the variable. * @param value Value of the variable. * @param value_size Size of @a value. */ void GNUNET_ENV_environment_add (struct GNUNET_ENV_Environment *env, enum GNUNET_ENV_Operator oper, const char *name, const void *value, size_t value_size) { struct GNUNET_ENV_Modifier *mod = GNUNET_new (struct GNUNET_ENV_Modifier); mod->oper = oper; mod->name = name; mod->value = value; mod->value_size = value_size; GNUNET_CONTAINER_DLL_insert_tail (env->mod_head, env->mod_tail, mod); env->mod_count++; } /** * Get the modifier at the beginning of an environment. * * @param env * @param oper * @param name * @param value * @param value_size * * @return */ int GNUNET_ENV_environment_head (struct GNUNET_ENV_Environment *env, enum GNUNET_ENV_Operator *oper, const char **name, const void **value, size_t *value_size) { if (NULL == env->mod_head) return GNUNET_NO; struct GNUNET_ENV_Modifier *mod = env->mod_head; *oper = mod->oper; *name = mod->name; *value = mod->value; *value_size = mod->value_size; return GNUNET_YES; } /** * Get the modifier at the beginning of an environment and remove it. * * @param env * @param oper * @param name * @param value * @param value_size * * @return */ int GNUNET_ENV_environment_shift (struct GNUNET_ENV_Environment *env, enum GNUNET_ENV_Operator *oper, const char **name, const void **value, size_t *value_size) { if (NULL == env->mod_head) return GNUNET_NO; struct GNUNET_ENV_Modifier *mod = env->mod_head; *oper = mod->oper; *name = mod->name; *value = mod->value; *value_size = mod->value_size; GNUNET_CONTAINER_DLL_remove (env->mod_head, env->mod_tail, mod); GNUNET_free (mod); env->mod_count--; return GNUNET_YES; } /** * Iterate through all modifiers in the environment. * * @param env The environment. * @param it Iterator. * @param it_cls Closure for iterator. */ void GNUNET_ENV_environment_iterate (const struct GNUNET_ENV_Environment *env, GNUNET_ENV_Iterator it, void *it_cls) { struct GNUNET_ENV_Modifier *mod; for (mod = env->mod_head; NULL != mod; mod = mod->next) it (it_cls, mod->oper, mod->name, mod->value, mod->value_size); } /** * Get the number of modifiers in the environment. * * @param env The environment. * * @return Number of modifiers. */ size_t GNUNET_ENV_environment_get_count (const struct GNUNET_ENV_Environment *env) { return env->mod_count; } /** * Destroy an environment. * * @param env The environment to destroy. */ void GNUNET_ENV_environment_destroy (struct GNUNET_ENV_Environment *env) { struct GNUNET_ENV_Modifier *mod, *prev = NULL; for (mod = env->mod_head; NULL != mod; mod = mod->next) { if (NULL != prev) GNUNET_free (prev); prev = mod; } if (NULL != prev) GNUNET_free (prev); GNUNET_free (env); } gnunet-0.10.1/src/fragmentation/0000755000175000017500000000000012320755624013525 500000000000000gnunet-0.10.1/src/fragmentation/test_fragmentation_data.conf0000644000175000017500000000003012225230043021156 00000000000000 [nse] AUTOSTART = NO gnunet-0.10.1/src/fragmentation/defragmentation.c0000644000175000017500000003454212255010512016753 00000000000000/* This file is part of GNUnet (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/fragmentation/defragmentation.c * @brief library to help defragment messages * @author Christian Grothoff */ #include "platform.h" #include "gnunet_fragmentation_lib.h" #include "fragmentation.h" /** * Timestamps for fragments. */ struct FragTimes { /** * The time the fragment was received. */ struct GNUNET_TIME_Absolute time; /** * Number of the bit for the fragment (in [0,..,63]). */ unsigned int bit; }; /** * Information we keep for one message that is being assembled. Note * that we keep the context around even after the assembly is done to * handle 'stray' messages that are received 'late'. A message * context is ONLY discarded when the queue gets too big. */ struct MessageContext { /** * This is a DLL. */ struct MessageContext *next; /** * This is a DLL. */ struct MessageContext *prev; /** * Associated defragmentation context. */ struct GNUNET_DEFRAGMENT_Context *dc; /** * Pointer to the assembled message, allocated at the * end of this struct. */ const struct GNUNET_MessageHeader *msg; /** * Last time we received any update for this message * (least-recently updated message will be discarded * if we hit the queue size). */ struct GNUNET_TIME_Absolute last_update; /** * Task scheduled for transmitting the next ACK to the * other peer. */ GNUNET_SCHEDULER_TaskIdentifier ack_task; /** * When did we receive which fragment? Used to calculate * the time we should send the ACK. */ struct FragTimes frag_times[64]; /** * Which fragments have we gotten yet? bits that are 1 * indicate missing fragments. */ uint64_t bits; /** * Unique ID for this message. */ uint32_t fragment_id; /** * Which 'bit' did the last fragment we received correspond to? */ unsigned int last_bit; /** * For the current ACK round, which is the first relevant * offset in 'frag_times'? */ unsigned int frag_times_start_offset; /** * Which offset whould we write the next frag value into * in the 'frag_times' array? All smaller entries are valid. */ unsigned int frag_times_write_offset; /** * Total size of the message that we are assembling. */ uint16_t total_size; }; /** * Defragmentation context (one per connection). */ struct GNUNET_DEFRAGMENT_Context { /** * For statistics. */ struct GNUNET_STATISTICS_Handle *stats; /** * Head of list of messages we're defragmenting. */ struct MessageContext *head; /** * Tail of list of messages we're defragmenting. */ struct MessageContext *tail; /** * Closure for 'proc' and 'ackp'. */ void *cls; /** * Function to call with defragmented messages. */ GNUNET_FRAGMENT_MessageProcessor proc; /** * Function to call with acknowledgements. */ GNUNET_DEFRAGMENT_AckProcessor ackp; /** * Running average of the latency (delay between messages) for this * connection. */ struct GNUNET_TIME_Relative latency; /** * num_msgs how many fragmented messages * to we defragment at most at the same time? */ unsigned int num_msgs; /** * Current number of messages in the 'struct MessageContext' * DLL (smaller or equal to 'num_msgs'). */ unsigned int list_size; /** * Maximum message size for each fragment. */ uint16_t mtu; }; /** * Create a defragmentation context. * * @param stats statistics context * @param mtu the maximum message size for each fragment * @param num_msgs how many fragmented messages * to we defragment at most at the same time? * @param cls closure for proc and ackp * @param proc function to call with defragmented messages * @param ackp function to call with acknowledgements (to send * back to the other side) * @return the defragmentation context */ struct GNUNET_DEFRAGMENT_Context * GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, unsigned int num_msgs, void *cls, GNUNET_FRAGMENT_MessageProcessor proc, GNUNET_DEFRAGMENT_AckProcessor ackp) { struct GNUNET_DEFRAGMENT_Context *dc; dc = GNUNET_new (struct GNUNET_DEFRAGMENT_Context); dc->stats = stats; dc->cls = cls; dc->proc = proc; dc->ackp = ackp; dc->num_msgs = num_msgs; dc->mtu = mtu; dc->latency = GNUNET_TIME_UNIT_SECONDS; /* start with likely overestimate */ return dc; } /** * Destroy the given defragmentation context. * * @param dc defragmentation context */ void GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc) { struct MessageContext *mc; while (NULL != (mc = dc->head)) { GNUNET_CONTAINER_DLL_remove (dc->head, dc->tail, mc); dc->list_size--; if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) { GNUNET_SCHEDULER_cancel (mc->ack_task); mc->ack_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (mc); } GNUNET_assert (0 == dc->list_size); GNUNET_free (dc); } /** * Send acknowledgement to the other peer now. * * @param cls the message context * @param tc the scheduler context */ static void send_ack (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MessageContext *mc = cls; struct GNUNET_DEFRAGMENT_Context *dc = mc->dc; struct FragmentAcknowledgement fa; mc->ack_task = GNUNET_SCHEDULER_NO_TASK; fa.header.size = htons (sizeof (struct FragmentAcknowledgement)); fa.header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT_ACK); fa.fragment_id = htonl (mc->fragment_id); fa.bits = GNUNET_htonll (mc->bits); GNUNET_STATISTICS_update (mc->dc->stats, _("# acknowledgements sent for fragment"), 1, GNUNET_NO); dc->ackp (dc->cls, mc->fragment_id, &fa.header); } /** * This function is from the GNU Scientific Library, linear/fit.c, * (C) 2000 Brian Gough */ static void gsl_fit_mul (const double *x, const size_t xstride, const double *y, const size_t ystride, const size_t n, double *c1, double *cov_11, double *sumsq) { double m_x = 0, m_y = 0, m_dx2 = 0, m_dxdy = 0; size_t i; for (i = 0; i < n; i++) { m_x += (x[i * xstride] - m_x) / (i + 1.0); m_y += (y[i * ystride] - m_y) / (i + 1.0); } for (i = 0; i < n; i++) { const double dx = x[i * xstride] - m_x; const double dy = y[i * ystride] - m_y; m_dx2 += (dx * dx - m_dx2) / (i + 1.0); m_dxdy += (dx * dy - m_dxdy) / (i + 1.0); } /* In terms of y = b x */ { double s2 = 0, d2 = 0; double b = (m_x * m_y + m_dxdy) / (m_x * m_x + m_dx2); *c1 = b; /* Compute chi^2 = \sum (y_i - b * x_i)^2 */ for (i = 0; i < n; i++) { const double dx = x[i * xstride] - m_x; const double dy = y[i * ystride] - m_y; const double d = (m_y - b * m_x) + dy - b * dx; d2 += d * d; } s2 = d2 / (n - 1.0); /* chisq per degree of freedom */ *cov_11 = s2 * 1.0 / (n * (m_x * m_x + m_dx2)); *sumsq = d2; } } /** * Estimate the latency between messages based on the most recent * message time stamps. * * @param mc context with time stamps * @return average delay between time stamps (based on least-squares fit) */ static struct GNUNET_TIME_Relative estimate_latency (struct MessageContext *mc) { struct FragTimes *first; size_t total = mc->frag_times_write_offset - mc->frag_times_start_offset; double x[total]; double y[total]; size_t i; double c1; double cov11; double sumsq; struct GNUNET_TIME_Relative ret; first = &mc->frag_times[mc->frag_times_start_offset]; GNUNET_assert (total > 1); for (i = 0; i < total; i++) { x[i] = (double) i; y[i] = (double) (first[i].time.abs_value_us - first[0].time.abs_value_us); } gsl_fit_mul (x, 1, y, 1, total, &c1, &cov11, &sumsq); c1 += sqrt (sumsq); /* add 1 std dev */ ret.rel_value_us = (uint64_t) c1; if (0 == ret.rel_value_us) ret = GNUNET_TIME_UNIT_MICROSECONDS; /* always at least 1 */ return ret; } /** * Discard the message context that was inactive for the longest time. * * @param dc defragmentation context */ static void discard_oldest_mc (struct GNUNET_DEFRAGMENT_Context *dc) { struct MessageContext *old; struct MessageContext *pos; old = NULL; pos = dc->head; while (NULL != pos) { if ((old == NULL) || (old->last_update.abs_value_us > pos->last_update.abs_value_us)) old = pos; pos = pos->next; } GNUNET_assert (NULL != old); GNUNET_CONTAINER_DLL_remove (dc->head, dc->tail, old); dc->list_size--; if (GNUNET_SCHEDULER_NO_TASK != old->ack_task) { GNUNET_SCHEDULER_cancel (old->ack_task); old->ack_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (old); } /** * We have received a fragment. Process it. * * @param dc the context * @param msg the message that was received * @return GNUNET_OK on success, GNUNET_NO if this was a duplicate, GNUNET_SYSERR on error */ int GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, const struct GNUNET_MessageHeader *msg) { struct MessageContext *mc; const struct FragmentHeader *fh; uint16_t msize; uint16_t foff; uint32_t fid; char *mbuf; unsigned int bit; struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Relative delay; unsigned int bc; unsigned int b; unsigned int n; unsigned int num_fragments; int duplicate; int last; if (ntohs (msg->size) < sizeof (struct FragmentHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (ntohs (msg->size) > dc->mtu) { GNUNET_break_op (0); return GNUNET_SYSERR; } fh = (const struct FragmentHeader *) msg; msize = ntohs (fh->total_size); if (msize < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } fid = ntohl (fh->fragment_id); foff = ntohs (fh->offset); if (foff >= msize) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (0 != (foff % (dc->mtu - sizeof (struct FragmentHeader)))) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (dc->stats, _("# fragments received"), 1, GNUNET_NO); num_fragments = (ntohs (msg->size) + dc->mtu - sizeof (struct FragmentHeader)-1) / (dc->mtu - sizeof (struct FragmentHeader)); last = 0; for (mc = dc->head; NULL != mc; mc = mc->next) if (mc->fragment_id > fid) last++; mc = dc->head; while ((NULL != mc) && (fid != mc->fragment_id)) mc = mc->next; bit = foff / (dc->mtu - sizeof (struct FragmentHeader)); if (bit * (dc->mtu - sizeof (struct FragmentHeader)) + ntohs (msg->size) - sizeof (struct FragmentHeader) > msize) { /* payload extends past total message size */ GNUNET_break_op (0); return GNUNET_SYSERR; } if ((NULL != mc) && (msize != mc->total_size)) { /* inconsistent message size */ GNUNET_break_op (0); return GNUNET_SYSERR; } now = GNUNET_TIME_absolute_get (); if (NULL == mc) { mc = GNUNET_malloc (sizeof (struct MessageContext) + msize); mc->msg = (const struct GNUNET_MessageHeader *) &mc[1]; mc->dc = dc; mc->total_size = msize; mc->fragment_id = fid; mc->last_update = now; n = (msize + dc->mtu - sizeof (struct FragmentHeader) - 1) / (dc->mtu - sizeof (struct FragmentHeader)); if (n == 64) mc->bits = UINT64_MAX; /* set all 64 bit */ else mc->bits = (1LL << n) - 1; /* set lowest 'bits' bit */ if (dc->list_size >= dc->num_msgs) discard_oldest_mc (dc); GNUNET_CONTAINER_DLL_insert (dc->head, dc->tail, mc); dc->list_size++; } /* copy data to 'mc' */ if (0 != (mc->bits & (1LL << bit))) { mc->bits -= 1LL << bit; mbuf = (char *) &mc[1]; memcpy (&mbuf[bit * (dc->mtu - sizeof (struct FragmentHeader))], &fh[1], ntohs (msg->size) - sizeof (struct FragmentHeader)); mc->last_update = now; if (bit < mc->last_bit) mc->frag_times_start_offset = mc->frag_times_write_offset; mc->last_bit = bit; mc->frag_times[mc->frag_times_write_offset].time = now; mc->frag_times[mc->frag_times_write_offset].bit = bit; mc->frag_times_write_offset++; duplicate = GNUNET_NO; } else { duplicate = GNUNET_YES; GNUNET_STATISTICS_update (dc->stats, _("# duplicate fragments received"), 1, GNUNET_NO); } /* count number of missing fragments */ bc = 0; for (b = 0; b < 64; b++) if (0 != (mc->bits & (1LL << b))) bc++; /* notify about complete message */ if ((duplicate == GNUNET_NO) && (0 == mc->bits)) { GNUNET_STATISTICS_update (dc->stats, _("# messages defragmented"), 1, GNUNET_NO); /* message complete, notify! */ dc->proc (dc->cls, mc->msg); } /* send ACK */ if (mc->frag_times_write_offset - mc->frag_times_start_offset > 1) { dc->latency = estimate_latency (mc); } delay = GNUNET_TIME_relative_multiply (dc->latency, bc + 1); if ( (last + fid == num_fragments) || (0 == mc->bits) || (GNUNET_YES == duplicate)) { /* message complete or duplicate or last missing fragment in linear sequence; ACK now! */ delay = GNUNET_TIME_UNIT_ZERO; } if (GNUNET_SCHEDULER_NO_TASK != mc->ack_task) GNUNET_SCHEDULER_cancel (mc->ack_task); mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay, &send_ack, mc); if (duplicate == GNUNET_YES) return GNUNET_NO; return GNUNET_YES; } /* end of defragmentation.c */ gnunet-0.10.1/src/fragmentation/Makefile.in0000644000175000017500000011137012320752061015505 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_fragmentation$(EXEEXT) subdir = src/fragmentation DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetfragmentation_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetfragmentation_la_OBJECTS = fragmentation.lo \ defragmentation.lo libgnunetfragmentation_la_OBJECTS = \ $(am_libgnunetfragmentation_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetfragmentation_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetfragmentation_la_LDFLAGS) \ $(LDFLAGS) -o $@ am_test_fragmentation_OBJECTS = test_fragmentation.$(OBJEXT) test_fragmentation_OBJECTS = $(am_test_fragmentation_OBJECTS) test_fragmentation_DEPENDENCIES = \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetfragmentation_la_SOURCES) \ $(test_fragmentation_SOURCES) DIST_SOURCES = $(libgnunetfragmentation_la_SOURCES) \ $(test_fragmentation_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage lib_LTLIBRARIES = libgnunetfragmentation.la libgnunetfragmentation_la_SOURCES = \ fragmentation.c fragmentation.h \ defragmentation.c libgnunetfragmentation_la_LIBADD = -lm \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetfragmentation_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 2:0:0 @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_fragmentation_SOURCES = \ test_fragmentation.c test_fragmentation_LDADD = \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = test_fragmentation_data.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/fragmentation/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/fragmentation/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetfragmentation.la: $(libgnunetfragmentation_la_OBJECTS) $(libgnunetfragmentation_la_DEPENDENCIES) $(EXTRA_libgnunetfragmentation_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetfragmentation_la_LINK) -rpath $(libdir) $(libgnunetfragmentation_la_OBJECTS) $(libgnunetfragmentation_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list test_fragmentation$(EXEEXT): $(test_fragmentation_OBJECTS) $(test_fragmentation_DEPENDENCIES) $(EXTRA_test_fragmentation_DEPENDENCIES) @rm -f test_fragmentation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fragmentation_OBJECTS) $(test_fragmentation_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defragmentation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fragmentation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fragmentation.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_fragmentation.log: test_fragmentation$(EXEEXT) @p='test_fragmentation$(EXEEXT)'; \ b='test_fragmentation'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/fragmentation/Makefile.am0000644000175000017500000000173612320751517015505 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage endif lib_LTLIBRARIES = libgnunetfragmentation.la libgnunetfragmentation_la_SOURCES = \ fragmentation.c fragmentation.h \ defragmentation.c libgnunetfragmentation_la_LIBADD = -lm \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetfragmentation_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 2:0:0 check_PROGRAMS = \ test_fragmentation if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_fragmentation_SOURCES = \ test_fragmentation.c test_fragmentation_LDADD = \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = test_fragmentation_data.conf gnunet-0.10.1/src/fragmentation/test_fragmentation.c0000644000175000017500000001464512272461615017520 00000000000000/* This file is part of GNUnet (C) 2004, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fragmentation/test_fragmentation.c * @brief test for fragmentation.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_fragmentation_lib.h" #define DETAILS GNUNET_NO /** * Number of messages to transmit (note: each uses ~32k memory!) */ #define NUM_MSGS 500 /** * MTU to force on fragmentation (must be > 1k + 12) */ #define MTU 1111 /** * Simulate dropping of 1 out of how many messages? (must be > 1) */ #define DROPRATE 5 static int ret = 1; static unsigned int dups; static unsigned int fragc; static unsigned int frag_drops; static unsigned int acks; static unsigned int ack_drops; static struct GNUNET_DEFRAGMENT_Context *defrag; static struct GNUNET_BANDWIDTH_Tracker trackers[NUM_MSGS]; static struct GNUNET_FRAGMENT_Context *frags[NUM_MSGS]; static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int i; ret = 0; shutdown_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_DEFRAGMENT_context_destroy (defrag); defrag = NULL; for (i = 0; i < NUM_MSGS; i++) { if (frags[i] == NULL) continue; GNUNET_FRAGMENT_context_destroy (frags[i], NULL, NULL); frags[i] = NULL; } } static void proc_msgs (void *cls, const struct GNUNET_MessageHeader *hdr) { static unsigned int total; unsigned int i; const char *buf; #if DETAILS FPRINTF (stderr, "%s", "!"); /* message complete, good! */ #endif buf = (const char *) hdr; for (i = sizeof (struct GNUNET_MessageHeader); i < ntohs (hdr->size); i++) GNUNET_assert (buf[i] == (char) i); total++; #if ! DETAILS if (0 == (total % (NUM_MSGS / 100))) FPRINTF (stderr, "%s", "."); #endif /* tolerate 10% loss, i.e. due to duplicate fragment IDs */ if ((total >= NUM_MSGS - (NUM_MSGS / 10)) && (ret != 0)) { if (GNUNET_SCHEDULER_NO_TASK == shutdown_task) shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } /** * Process ACK (by passing to fragmenter) */ static void proc_acks (void *cls, uint32_t msg_id, const struct GNUNET_MessageHeader *hdr) { unsigned int i; int ret; if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) { ack_drops++; return; /* random drop */ } for (i = 0; i < NUM_MSGS; i++) { if (frags[i] == NULL) continue; ret = GNUNET_FRAGMENT_process_ack (frags[i], hdr); if (ret == GNUNET_OK) { #if DETAILS FPRINTF (stderr, "%s", "@"); /* good ACK */ #endif GNUNET_FRAGMENT_context_destroy (frags[i], NULL, NULL); frags[i] = NULL; acks++; return; } if (ret == GNUNET_NO) { #if DETAILS FPRINTF (stderr, "%s", "@"); /* good ACK */ #endif acks++; return; } } #if DETAILS FPRINTF (stderr, "%s", "_"); /* BAD: ack that nobody feels responsible for... */ #endif } /** * Process fragment (by passing to defrag). */ static void proc_frac (void *cls, const struct GNUNET_MessageHeader *hdr) { struct GNUNET_FRAGMENT_Context **fc = cls; int ret; GNUNET_FRAGMENT_context_transmission_done (*fc); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, DROPRATE)) { frag_drops++; return; /* random drop */ } if (NULL == defrag) { FPRINTF (stderr, "%s", "E"); /* Error: frag after shutdown!? */ return; } ret = GNUNET_DEFRAGMENT_process_fragment (defrag, hdr); if (ret == GNUNET_NO) { #if DETAILS FPRINTF (stderr, "%s", "?"); /* duplicate fragment */ #endif dups++; } else if (ret == GNUNET_OK) { #if DETAILS FPRINTF (stderr, "%s", "."); /* good fragment */ #endif fragc++; } } /** * Main function run with scheduler. */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { unsigned int i; struct GNUNET_MessageHeader *msg; char buf[MTU + 32 * 1024]; defrag = GNUNET_DEFRAGMENT_context_create (NULL, MTU, NUM_MSGS /* enough space for all */ , NULL, &proc_msgs, &proc_acks); for (i = 0; i < sizeof (buf); i++) buf[i] = (char) i; msg = (struct GNUNET_MessageHeader *) buf; for (i = 0; i < NUM_MSGS; i++) { msg->type = htons ((uint16_t) i); msg->size = htons (sizeof (struct GNUNET_MessageHeader) + (17 * i) % (32 * 1024)); frags[i] = GNUNET_FRAGMENT_context_create (NULL /* no stats */ , MTU, &trackers[i], GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_TIME_UNIT_SECONDS, msg, &proc_frac, &frags[i]); } } int main (int argc, char *argv[]) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; char *const argv_prog[] = { "test-fragmentation", "-c", "test_fragmentation_data.conf", "-L", "WARNING", NULL }; unsigned int i; GNUNET_log_setup ("test-fragmentation", "WARNING", NULL); for (i = 0; i < NUM_MSGS; i++) GNUNET_BANDWIDTH_tracker_init (&trackers[i], NULL, NULL, GNUNET_BANDWIDTH_value_init ((i + 1) * 1024), 100); GNUNET_PROGRAM_run (5, argv_prog, "test-fragmentation", "nohelp", options, &run, NULL); FPRINTF (stderr, "\nHad %u good fragments, %u duplicate fragments, %u acks and %u simulated drops of acks\n", fragc, dups, acks, ack_drops); return ret; } gnunet-0.10.1/src/fragmentation/fragmentation.h0000644000175000017500000000371312225777502016463 00000000000000/* This file is part of GNUnet (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/fragmentation/fragmentation.h * @brief library to help fragment messages * @author Christian Grothoff */ #ifndef FRAGMENTATION_H #define FRAGMENTATION_H #include "platform.h" #include "gnunet_fragmentation_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Header for a message fragment. Followed by the * original message. */ struct FragmentHeader { /** * Message header. */ struct GNUNET_MessageHeader header; /** * Unique fragment ID. */ uint32_t fragment_id; /** * Total message size of the original message. */ uint16_t total_size; /** * Absolute offset (in bytes) of this fragment in the original * message. Will be a multiple of the MTU. */ uint16_t offset; }; /** * Message fragment acknowledgement. */ struct FragmentAcknowledgement { /** * Message header. */ struct GNUNET_MessageHeader header; /** * Unique fragment ID. */ uint32_t fragment_id; /** * Bits that are being acknowledged, in big-endian. * (bits that are set correspond to fragments that * have not yet been received). */ uint64_t bits; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/fragmentation/fragmentation.c0000644000175000017500000003460312225777501016457 00000000000000/* This file is part of GNUnet (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/fragmentation/fragmentation.c * @brief library to help fragment messages * @author Christian Grothoff */ #include "platform.h" #include "gnunet_fragmentation_lib.h" #include "gnunet_protocols.h" #include "fragmentation.h" /** * Absolute minimum delay we impose between sending and expecting ACK to arrive. */ #define MIN_ACK_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 1) /** * Fragmentation context. */ struct GNUNET_FRAGMENT_Context { /** * Statistics to use. */ struct GNUNET_STATISTICS_Handle *stats; /** * Tracker for flow control. */ struct GNUNET_BANDWIDTH_Tracker *tracker; /** * Current expected delay for ACKs. */ struct GNUNET_TIME_Relative ack_delay; /** * Current expected delay between messages. */ struct GNUNET_TIME_Relative msg_delay; /** * Next allowed transmission time. */ struct GNUNET_TIME_Absolute delay_until; /** * Time we transmitted the last message of the last round. */ struct GNUNET_TIME_Absolute last_round; /** * Message to fragment (allocated at the end of this struct). */ const struct GNUNET_MessageHeader *msg; /** * Function to call for transmissions. */ GNUNET_FRAGMENT_MessageProcessor proc; /** * Closure for 'proc'. */ void *proc_cls; /** * Bitfield, set to 1 for each unacknowledged fragment. */ uint64_t acks; /** * Bitfield with all possible bits for 'acks' (used to mask the * ack we get back). */ uint64_t acks_mask; /** * Task performing work for the fragmenter. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Our fragmentation ID. (chosen at random) */ uint32_t fragment_id; /** * Round-robin selector for the next transmission. */ unsigned int next_transmission; /** * How many rounds of transmission have we completed so far? */ unsigned int num_rounds; /** * How many transmission have we completed in this round? */ unsigned int num_transmissions; /** * GNUNET_YES if we called 'proc' and are now waiting for 'GNUNET_FRAGMENT_transmission_done' */ int8_t proc_busy; /** * GNUNET_YES if we are waiting for an ACK. */ int8_t wack; /** * Target fragment size. */ uint16_t mtu; }; /** * Transmit the next fragment to the other peer. * * @param cls the 'struct GNUNET_FRAGMENT_Context' * @param tc scheduler context */ static void transmit_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FRAGMENT_Context *fc = cls; char msg[fc->mtu]; const char *mbuf; struct FragmentHeader *fh; struct GNUNET_TIME_Relative delay; unsigned int bit; size_t size; size_t fsize; int wrap; fc->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_NO == fc->proc_busy); if (0 == fc->acks) return; /* all done */ /* calculate delay */ wrap = 0; while (0 == (fc->acks & (1LL << fc->next_transmission))) { fc->next_transmission = (fc->next_transmission + 1) % 64; wrap |= (0 == fc->next_transmission); } bit = fc->next_transmission; size = ntohs (fc->msg->size); if (bit == size / (fc->mtu - sizeof (struct FragmentHeader))) fsize = (size % (fc->mtu - sizeof (struct FragmentHeader))) + sizeof (struct FragmentHeader); else fsize = fc->mtu; if (NULL != fc->tracker) delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, fsize); else delay = GNUNET_TIME_UNIT_ZERO; if (delay.rel_value_us > 0) { fc->task = GNUNET_SCHEDULER_add_delayed (delay, &transmit_next, fc); return; } fc->next_transmission = (fc->next_transmission + 1) % 64; wrap |= (0 == fc->next_transmission); while (0 == (fc->acks & (1LL << fc->next_transmission))) { fc->next_transmission = (fc->next_transmission + 1) % 64; wrap |= (0 == fc->next_transmission); } /* assemble fragmentation message */ mbuf = (const char *) &fc[1]; fh = (struct FragmentHeader *) msg; fh->header.size = htons (fsize); fh->header.type = htons (GNUNET_MESSAGE_TYPE_FRAGMENT); fh->fragment_id = htonl (fc->fragment_id); fh->total_size = fc->msg->size; /* already in big-endian */ fh->offset = htons ((fc->mtu - sizeof (struct FragmentHeader)) * bit); memcpy (&fh[1], &mbuf[bit * (fc->mtu - sizeof (struct FragmentHeader))], fsize - sizeof (struct FragmentHeader)); if (NULL != fc->tracker) GNUNET_BANDWIDTH_tracker_consume (fc->tracker, fsize); GNUNET_STATISTICS_update (fc->stats, _("# fragments transmitted"), 1, GNUNET_NO); if (0 != fc->last_round.abs_value_us) GNUNET_STATISTICS_update (fc->stats, _("# fragments retransmitted"), 1, GNUNET_NO); /* select next message to calculate delay */ bit = fc->next_transmission; size = ntohs (fc->msg->size); if (bit == size / (fc->mtu - sizeof (struct FragmentHeader))) fsize = size % (fc->mtu - sizeof (struct FragmentHeader)); else fsize = fc->mtu; if (NULL != fc->tracker) delay = GNUNET_BANDWIDTH_tracker_get_delay (fc->tracker, fsize); else delay = GNUNET_TIME_UNIT_ZERO; delay = GNUNET_TIME_relative_max (delay, GNUNET_TIME_relative_multiply (fc->msg_delay, (1 << fc->num_rounds))); if (wrap) { /* full round transmitted wait 2x delay for ACK before going again */ fc->num_rounds++; delay = GNUNET_TIME_relative_multiply (fc->ack_delay, 2); /* never use zero, need some time for ACK always */ delay = GNUNET_TIME_relative_max (MIN_ACK_DELAY, delay); fc->wack = GNUNET_YES; fc->last_round = GNUNET_TIME_absolute_get (); GNUNET_STATISTICS_update (fc->stats, _("# fragments wrap arounds"), 1, GNUNET_NO); } fc->proc_busy = GNUNET_YES; fc->delay_until = GNUNET_TIME_relative_to_absolute (delay); fc->num_transmissions++; fc->proc (fc->proc_cls, &fh->header); } /** * Create a fragmentation context for the given message. * Fragments the message into fragments of size "mtu" or * less. Calls 'proc' on each un-acknowledged fragment, * using both the expected 'delay' between messages and * acknowledgements and the given 'tracker' to guide the * frequency of calls to 'proc'. * * @param stats statistics context * @param mtu the maximum message size for each fragment * @param tracker bandwidth tracker to use for flow control (can be NULL) * @param msg_delay initial delay to insert between fragment transmissions * based on previous messages * @param ack_delay expected delay between fragment transmission * and ACK based on previous messages * @param msg the message to fragment * @param proc function to call for each fragment to transmit * @param proc_cls closure for proc * @return the fragmentation context */ struct GNUNET_FRAGMENT_Context * GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, struct GNUNET_BANDWIDTH_Tracker *tracker, struct GNUNET_TIME_Relative msg_delay, struct GNUNET_TIME_Relative ack_delay, const struct GNUNET_MessageHeader *msg, GNUNET_FRAGMENT_MessageProcessor proc, void *proc_cls) { struct GNUNET_FRAGMENT_Context *fc; size_t size; uint64_t bits; GNUNET_STATISTICS_update (stats, _("# messages fragmented"), 1, GNUNET_NO); GNUNET_assert (mtu >= 1024 + sizeof (struct FragmentHeader)); size = ntohs (msg->size); GNUNET_STATISTICS_update (stats, _("# total size of fragmented messages"), size, GNUNET_NO); GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); fc = GNUNET_malloc (sizeof (struct GNUNET_FRAGMENT_Context) + size); fc->stats = stats; fc->mtu = mtu; fc->tracker = tracker; fc->ack_delay = ack_delay; fc->msg_delay = msg_delay; fc->msg = (const struct GNUNET_MessageHeader *) &fc[1]; fc->proc = proc; fc->proc_cls = proc_cls; fc->fragment_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); memcpy (&fc[1], msg, size); bits = (size + mtu - sizeof (struct FragmentHeader) - 1) / (mtu - sizeof (struct FragmentHeader)); GNUNET_assert (bits <= 64); if (bits == 64) fc->acks_mask = UINT64_MAX; /* set all 64 bit */ else fc->acks_mask = (1LL << bits) - 1; /* set lowest 'bits' bit */ fc->acks = fc->acks_mask; fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, fc); return fc; } /** * Continuation to call from the 'proc' function after the fragment * has been transmitted (and hence the next fragment can now be * given to proc). * * @param fc fragmentation context */ void GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc) { GNUNET_assert (fc->proc_busy == GNUNET_YES); fc->proc_busy = GNUNET_NO; GNUNET_assert (fc->task == GNUNET_SCHEDULER_NO_TASK); fc->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (fc->delay_until), &transmit_next, fc); } /** * Process an acknowledgement message we got from the other * side (to control re-transmits). * * @param fc fragmentation context * @param msg acknowledgement message we received * @return GNUNET_OK if this ack completes the work of the 'fc' * (all fragments have been received); * GNUNET_NO if more messages are pending * GNUNET_SYSERR if this ack is not valid for this fc */ int GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, const struct GNUNET_MessageHeader *msg) { const struct FragmentAcknowledgement *fa; uint64_t abits; struct GNUNET_TIME_Relative ndelay; unsigned int ack_cnt; unsigned int snd_cnt; unsigned int i; if (sizeof (struct FragmentAcknowledgement) != ntohs (msg->size)) { GNUNET_break_op (0); return GNUNET_SYSERR; } fa = (const struct FragmentAcknowledgement *) msg; if (ntohl (fa->fragment_id) != fc->fragment_id) return GNUNET_SYSERR; /* not our ACK */ abits = GNUNET_ntohll (fa->bits); if ( (GNUNET_YES == fc->wack) && (0 != fc->num_transmissions) ) { /* normal ACK, can update running average of delay... */ fc->wack = GNUNET_NO; ndelay = GNUNET_TIME_absolute_get_duration (fc->last_round); fc->ack_delay.rel_value_us = (ndelay.rel_value_us / fc->num_transmissions + 3 * fc->ack_delay.rel_value_us) / 4; fc->num_transmissions = 0; /* calculate ratio msg sent vs. msg acked */ ack_cnt = 0; snd_cnt = 0; for (i=0;i<64;i++) { if (1 == (fc->acks_mask & (1 << i))) { snd_cnt++; if (0 == (abits & (1 << i))) ack_cnt++; } } if (0 == ack_cnt) { /* complete loss */ fc->msg_delay = GNUNET_TIME_relative_multiply (fc->msg_delay, snd_cnt); } else if (snd_cnt > ack_cnt) { /* some loss, slow down proportionally */ fprintf (stderr, "Prop loss\n"); fc->msg_delay.rel_value_us = ((fc->msg_delay.rel_value_us * ack_cnt) / snd_cnt); } else if (100 < fc->msg_delay.rel_value_us) { fc->msg_delay.rel_value_us -= 100; /* try a bit faster */ } fc->msg_delay = GNUNET_TIME_relative_min (fc->msg_delay, GNUNET_TIME_UNIT_SECONDS); } GNUNET_STATISTICS_update (fc->stats, _("# fragment acknowledgements received"), 1, GNUNET_NO); if (abits != (fc->acks & abits)) { /* ID collission or message reordering, count! This should be rare! */ GNUNET_STATISTICS_update (fc->stats, _("# bits removed from fragmentation ACKs"), 1, GNUNET_NO); } fc->acks = abits & fc->acks_mask; if (0 != fc->acks) { /* more to transmit, do so right now (if tracker permits...) */ if (fc->task != GNUNET_SCHEDULER_NO_TASK) { /* schedule next transmission now, no point in waiting... */ GNUNET_SCHEDULER_cancel (fc->task); fc->task = GNUNET_SCHEDULER_add_now (&transmit_next, fc); } else { /* only case where there is no task should be if we're waiting * for the right to transmit again (proc_busy set to YES) */ GNUNET_assert (GNUNET_YES == fc->proc_busy); } return GNUNET_NO; } /* all done */ GNUNET_STATISTICS_update (fc->stats, _("# fragmentation transmissions completed"), 1, GNUNET_NO); if (fc->task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (fc->task); fc->task = GNUNET_SCHEDULER_NO_TASK; } return GNUNET_OK; } /** * Destroy the given fragmentation context (stop calling 'proc', free * resources). * * @param fc fragmentation context * @param msg_delay where to store average delay between individual message transmissions the * last message (OUT only) * @param ack_delay where to store average delay between transmission and ACK for the * last message, set to FOREVER if the message was not fully transmitted (OUT only) */ void GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc, struct GNUNET_TIME_Relative *msg_delay, struct GNUNET_TIME_Relative *ack_delay) { if (fc->task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (fc->task); if (NULL != ack_delay) *ack_delay = fc->ack_delay; if (NULL != msg_delay) *msg_delay = GNUNET_TIME_relative_multiply (fc->msg_delay, fc->num_rounds); GNUNET_free (fc); } /* end of fragmentation.c */ gnunet-0.10.1/src/nat/0000755000175000017500000000000012320755624011451 500000000000000gnunet-0.10.1/src/nat/test_nat_mini.c0000644000175000017500000000670712262754601014403 00000000000000/* This file is part of GNUnet. (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * Testcase for port redirection and public IP address retrieval. * This test never fails, because there need to be a NAT box set up for tha * * @file nat/test_nat_mini.c * @brief Testcase for NAT library - mini * @author Christian Grothoff * * TODO: actually use ARM to start resolver service to make DNS work! */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_program_lib.h" #include "gnunet_scheduler_lib.h" #include "gnunet_nat_lib.h" /* Time to wait before stopping NAT, in seconds */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Function called on each address that the NAT service * believes to be valid for the transport. */ static void addr_callback (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen, const char *emsg) { fprintf (stderr, "Address changed: %s `%s' (%u bytes)\n", add_remove == GNUNET_YES ? "added" : "removed", GNUNET_a2s (addr, addrlen), (unsigned int) addrlen); } /** * Function that terminates the test. */ static void stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_MiniHandle *mini = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping NAT and quitting...\n"); GNUNET_NAT_mini_map_stop (mini); } #define PORT 10000 /** * Main function run with scheduler. */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAT_MiniHandle *mini; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting NAT redirection for port %u...\n", PORT); mini = GNUNET_NAT_mini_map_start (PORT, GNUNET_YES /* tcp */ , &addr_callback, NULL); if (NULL == mini) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Could not start UPnP interaction\n"); return; } GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, mini); } int main (int argc, char *const argv[]) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; char *const argv_prog[] = { "test-nat-mini", "-c", "test_nat_data.conf", "-L", "WARNING", NULL }; GNUNET_log_setup ("test-nat-mini", "WARNING", NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "UPnP test for NAT library, timeout set to %d seconds\n", TIMEOUT); GNUNET_PROGRAM_run (5, argv_prog, "test-nat-mini", "nohelp", options, &run, NULL); return 0; } /* end of test_nat_mini.c */ gnunet-0.10.1/src/nat/nat_mini.c0000644000175000017500000004461612306322124013333 00000000000000/* This file is part of GNUnet. (C) 2011-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nat/nat_mini.c * @brief functions for interaction with miniupnp; tested with miniupnpc 1.5 * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_nat_lib.h" #include "nat.h" #define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) /** * How long do we give upnpc to create a mapping? */ #define MAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) /** * How long do we give upnpc to remove a mapping? */ #define UNMAP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * How often do we check for changes in the mapping? */ #define MAP_REFRESH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) /** * Opaque handle to cancel "GNUNET_NAT_mini_get_external_ipv4" operation. */ struct GNUNET_NAT_ExternalHandle { /** * Function to call with the result. */ GNUNET_NAT_IPCallback cb; /** * Closure for @e cb. */ void *cb_cls; /** * Read task. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Handle to 'external-ip' process. */ struct GNUNET_OS_Process *eip; /** * Handle to stdout pipe of 'external-ip'. */ struct GNUNET_DISK_PipeHandle *opipe; /** * Read handle of @e opipe. */ const struct GNUNET_DISK_FileHandle *r; /** * When should this operation time out? */ struct GNUNET_TIME_Absolute timeout; /** * Number of bytes in 'buf' that are valid. */ size_t off; /** * Destination of our read operation (output of 'external-ip'). */ char buf[17]; }; /** * Read the output of 'external-ip' into buf. When complete, parse the * address and call our callback. * * @param cls the `struct GNUNET_NAT_ExternalHandle` * @param tc scheduler context */ static void read_external_ipv4 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_ExternalHandle *eh = cls; ssize_t ret; struct in_addr addr; int iret; eh->task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_YES == GNUNET_NETWORK_fdset_handle_isset (tc->read_ready, eh->r)) ret = GNUNET_DISK_file_read (eh->r, &eh->buf[eh->off], sizeof (eh->buf) - eh->off); else ret = -1; /* error reading, timeout, etc. */ if (ret > 0) { /* try to read more */ eh->off += ret; eh->task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining (eh->timeout), eh->r, &read_external_ipv4, eh); return; } iret = GNUNET_NO; if ((eh->off > 7) && (eh->buf[eh->off - 1] == '\n')) { eh->buf[eh->off - 1] = '\0'; if (1 == inet_pton (AF_INET, eh->buf, &addr)) { if (0 == addr.s_addr) iret = GNUNET_NO; /* got 0.0.0.0 */ else iret = GNUNET_OK; } } eh->cb (eh->cb_cls, (GNUNET_OK == iret) ? &addr : NULL, (GNUNET_OK == iret) ? NULL : _("no valid address was returned by `external-ip'")); GNUNET_NAT_mini_get_external_ipv4_cancel (eh); } /** * (Asynchronously) signal error invoking "external-ip" to client. * * @param cls the `struct GNUNET_NAT_ExternalHandle` (freed) * @param tc scheduler context */ static void signal_external_ip_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_ExternalHandle *eh = cls; eh->task = GNUNET_SCHEDULER_NO_TASK; eh->cb (eh->cb_cls, NULL, _("`external-ip' command not found")); GNUNET_free (eh); } /** * Try to get the external IPv4 address of this peer. * * @param timeout when to fail * @param cb function to call with result * @param cb_cls closure for @a cb * @return handle for cancellation (can only be used until @a cb is called), NULL on error */ struct GNUNET_NAT_ExternalHandle * GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout, GNUNET_NAT_IPCallback cb, void *cb_cls) { struct GNUNET_NAT_ExternalHandle *eh; eh = GNUNET_new (struct GNUNET_NAT_ExternalHandle); eh->cb = cb; eh->cb_cls = cb_cls; if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary ("external-ip", GNUNET_NO, NULL)) { LOG (GNUNET_ERROR_TYPE_INFO, _("`external-ip' command not found\n")); eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error, eh); return eh; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Running `external-ip' to determine our external IP\n"); eh->opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if (NULL == eh->opipe) { eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error, eh); return eh; } eh->eip = GNUNET_OS_start_process (GNUNET_NO, 0, NULL, eh->opipe, NULL, "external-ip", "external-ip", NULL); if (NULL == eh->eip) { GNUNET_DISK_pipe_close (eh->opipe); eh->task = GNUNET_SCHEDULER_add_now (&signal_external_ip_error, eh); return eh; } GNUNET_DISK_pipe_close_end (eh->opipe, GNUNET_DISK_PIPE_END_WRITE); eh->timeout = GNUNET_TIME_relative_to_absolute (timeout); eh->r = GNUNET_DISK_pipe_handle (eh->opipe, GNUNET_DISK_PIPE_END_READ); eh->task = GNUNET_SCHEDULER_add_read_file (timeout, eh->r, &read_external_ipv4, eh); return eh; } /** * Cancel operation. * * @param eh operation to cancel */ void GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh) { if (NULL != eh->eip) { (void) GNUNET_OS_process_kill (eh->eip, SIGKILL); GNUNET_OS_process_destroy (eh->eip); } if (NULL != eh->opipe) GNUNET_DISK_pipe_close (eh->opipe); if (GNUNET_SCHEDULER_NO_TASK != eh->task) GNUNET_SCHEDULER_cancel (eh->task); GNUNET_free (eh); } /** * Handle to a mapping created with upnpc. */ struct GNUNET_NAT_MiniHandle { /** * Function to call on mapping changes. */ GNUNET_NAT_MiniAddressCallback ac; /** * Closure for @e ac. */ void *ac_cls; /** * Command used to install the map. */ struct GNUNET_OS_CommandHandle *map_cmd; /** * Command used to refresh our map information. */ struct GNUNET_OS_CommandHandle *refresh_cmd; /** * Command used to remove the mapping. */ struct GNUNET_OS_CommandHandle *unmap_cmd; /** * Our current external mapping (if we have one). */ struct sockaddr_in current_addr; /** * We check the mapping periodically to see if it * still works. This task triggers the check. */ GNUNET_SCHEDULER_TaskIdentifier refresh_task; /** * Are we mapping TCP or UDP? */ int is_tcp; /** * Did we succeed with creating a mapping? */ int did_map; /** * Did we find our mapping during refresh scan? */ int found; /** * Which port are we mapping? */ uint16_t port; }; /** * Run "upnpc -l" to find out if our mapping changed. * * @param cls the `struct GNUNET_NAT_MiniHandle` * @param tc scheduler context */ static void do_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Process the output from the "upnpc -r" command. * * @param cls the `struct GNUNET_NAT_MiniHandle` * @param line line of output, NULL at the end */ static void process_map_output (void *cls, const char *line); /** * Run "upnpc -r" to map our internal port. * * @param mini our handle */ static void run_upnpc_r (struct GNUNET_NAT_MiniHandle *mini) { char pstr[6]; GNUNET_snprintf (pstr, sizeof (pstr), "%u", (unsigned int) mini->port); mini->map_cmd = GNUNET_OS_command_run (&process_map_output, mini, MAP_TIMEOUT, "upnpc", "upnpc", "-r", pstr, mini->is_tcp ? "tcp" : "udp", NULL); if (NULL == mini->map_cmd) { mini->ac (mini->ac_cls, GNUNET_SYSERR, NULL, 0, _("Failed to run `upnpc` command")); return; } } /** * Process the output from "upnpc -l" to see if our * external mapping changed. If so, do the notifications. * * @param cls the `struct GNUNET_NAT_MiniHandle` * @param line line of output, NULL at the end */ static void process_refresh_output (void *cls, const char *line) { struct GNUNET_NAT_MiniHandle *mini = cls; char pstr[9]; const char *s; unsigned int nport; struct in_addr exip; if (NULL == line) { GNUNET_OS_command_stop (mini->refresh_cmd); mini->refresh_cmd = NULL; if (GNUNET_NO == mini->found) { /* mapping disappeared, try to re-create */ if (GNUNET_YES == mini->did_map) { mini->ac (mini->ac_cls, GNUNET_NO, (const struct sockaddr *) &mini->current_addr, sizeof (mini->current_addr), NULL); mini->did_map = GNUNET_NO; } run_upnpc_r (mini); } return; } if (!mini->did_map) return; /* never mapped, won't find our mapping anyway */ /* we're looking for output of the form: * "ExternalIPAddress = 12.134.41.124" */ s = strstr (line, "ExternalIPAddress = "); if (NULL != s) { s += strlen ("ExternalIPAddress = "); if (1 != inet_pton (AF_INET, s, &exip)) return; /* skip */ if (exip.s_addr == mini->current_addr.sin_addr.s_addr) return; /* no change */ /* update mapping */ mini->ac (mini->ac_cls, GNUNET_NO, (const struct sockaddr *) &mini->current_addr, sizeof (mini->current_addr), NULL); mini->current_addr.sin_addr = exip; mini->ac (mini->ac_cls, GNUNET_YES, (const struct sockaddr *) &mini->current_addr, sizeof (mini->current_addr), NULL); return; } /* * we're looking for output of the form: * * "0 TCP 3000->192.168.2.150:3000 'libminiupnpc' ''" * "1 UDP 3001->192.168.2.150:3001 'libminiupnpc' ''" * * the pattern we look for is: * * "%s TCP PORT->STRING:OURPORT *" or * "%s UDP PORT->STRING:OURPORT *" */ GNUNET_snprintf (pstr, sizeof (pstr), ":%u ", mini->port); if (NULL == (s = strstr (line, "->"))) return; /* skip */ if (NULL == strstr (s, pstr)) return; /* skip */ if (1 != SSCANF (line, (mini->is_tcp) ? "%*u TCP %u->%*s:%*u %*s" : "%*u UDP %u->%*s:%*u %*s", &nport)) return; /* skip */ mini->found = GNUNET_YES; if (nport == ntohs (mini->current_addr.sin_port)) return; /* no change */ /* external port changed, update mapping */ mini->ac (mini->ac_cls, GNUNET_NO, (const struct sockaddr *) &mini->current_addr, sizeof (mini->current_addr), NULL); mini->current_addr.sin_port = htons ((uint16_t) nport); mini->ac (mini->ac_cls, GNUNET_YES, (const struct sockaddr *) &mini->current_addr, sizeof (mini->current_addr), NULL); } /** * Run "upnpc -l" to find out if our mapping changed. * * @param cls the 'struct GNUNET_NAT_MiniHandle' * @param tc scheduler context */ static void do_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_MiniHandle *mini = cls; int ac; mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, &do_refresh, mini); LOG (GNUNET_ERROR_TYPE_DEBUG, "Running `upnpc' to check if our mapping still exists\n"); mini->found = GNUNET_NO; ac = GNUNET_NO; if (NULL != mini->map_cmd) { /* took way too long, abort it! */ GNUNET_OS_command_stop (mini->map_cmd); mini->map_cmd = NULL; ac = GNUNET_YES; } if (NULL != mini->refresh_cmd) { /* took way too long, abort it! */ GNUNET_OS_command_stop (mini->refresh_cmd); mini->refresh_cmd = NULL; ac = GNUNET_YES; } mini->refresh_cmd = GNUNET_OS_command_run (&process_refresh_output, mini, MAP_TIMEOUT, "upnpc", "upnpc", "-l", NULL); if (GNUNET_YES == ac) mini->ac (mini->ac_cls, GNUNET_SYSERR, NULL, 0, _("`upnpc' command took too long, process killed")); } /** * Process the output from the 'upnpc -r' command. * * @param cls the `struct GNUNET_NAT_MiniHandle` * @param line line of output, NULL at the end */ static void process_map_output (void *cls, const char *line) { struct GNUNET_NAT_MiniHandle *mini = cls; const char *ipaddr; char *ipa; const char *pstr; unsigned int port; if (NULL == line) { GNUNET_OS_command_stop (mini->map_cmd); mini->map_cmd = NULL; if (GNUNET_YES != mini->did_map) mini->ac (mini->ac_cls, GNUNET_SYSERR, NULL, 0, _("`upnpc' command failed to establish port mapping")); if (GNUNET_SCHEDULER_NO_TASK == mini->refresh_task) mini->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, &do_refresh, mini); return; } /* * The upnpc output we're after looks like this: * * "external 87.123.42.204:3000 TCP is redirected to internal 192.168.2.150:3000" */ if ((NULL == (ipaddr = strstr (line, " "))) || (NULL == (pstr = strstr (ipaddr, ":"))) || (1 != SSCANF (pstr + 1, "%u", &port))) { return; /* skip line */ } ipa = GNUNET_strdup (ipaddr + 1); strstr (ipa, ":")[0] = '\0'; if (1 != inet_pton (AF_INET, ipa, &mini->current_addr.sin_addr)) { GNUNET_free (ipa); return; /* skip line */ } GNUNET_free (ipa); mini->current_addr.sin_port = htons (port); mini->current_addr.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN mini->current_addr.sin_len = sizeof (struct sockaddr_in); #endif mini->did_map = GNUNET_YES; mini->ac (mini->ac_cls, GNUNET_YES, (const struct sockaddr *) &mini->current_addr, sizeof (mini->current_addr), NULL); } /** * Start mapping the given port using (mini)upnpc. This function * should typically not be used directly (it is used within the * general-purpose #GNUNET_NAT_register() code). However, it can be * used if specifically UPnP-based NAT traversal is to be used or * tested. * * @param port port to map * @param is_tcp #GNUNET_YES to map TCP, #GNUNET_NO for UDP * @param ac function to call with mapping result * @param ac_cls closure for @a ac * @return NULL on error (no 'upnpc' installed) */ struct GNUNET_NAT_MiniHandle * GNUNET_NAT_mini_map_start (uint16_t port, int is_tcp, GNUNET_NAT_MiniAddressCallback ac, void *ac_cls) { struct GNUNET_NAT_MiniHandle *ret; if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)) { LOG (GNUNET_ERROR_TYPE_INFO, _("`upnpc' command not found\n")); ac (ac_cls, GNUNET_SYSERR, NULL, 0, _("`upnpc` command not found")); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Running `upnpc' to install mapping\n"); ret = GNUNET_new (struct GNUNET_NAT_MiniHandle); ret->ac = ac; ret->ac_cls = ac_cls; ret->is_tcp = is_tcp; ret->port = port; ret->refresh_task = GNUNET_SCHEDULER_add_delayed (MAP_REFRESH_FREQ, &do_refresh, ret); run_upnpc_r (ret); return ret; } /** * Process output from our 'unmap' command. * * @param cls the `struct GNUNET_NAT_MiniHandle` * @param line line of output, NULL at the end */ static void process_unmap_output (void *cls, const char *line) { struct GNUNET_NAT_MiniHandle *mini = cls; if (NULL == line) { LOG (GNUNET_ERROR_TYPE_DEBUG, "UPnP unmap done\n"); GNUNET_OS_command_stop (mini->unmap_cmd); mini->unmap_cmd = NULL; GNUNET_free (mini); return; } /* we don't really care about the output... */ } /** * Remove a mapping created with (mini)upnpc. Calling * this function will give 'upnpc' 1s to remove tha mapping, * so while this function is non-blocking, a task will be * left with the scheduler for up to 1s past this call. * * @param mini the handle */ void GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini) { char pstr[6]; if (GNUNET_SCHEDULER_NO_TASK != mini->refresh_task) { GNUNET_SCHEDULER_cancel (mini->refresh_task); mini->refresh_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != mini->refresh_cmd) { GNUNET_OS_command_stop (mini->refresh_cmd); mini->refresh_cmd = NULL; } if (NULL != mini->map_cmd) { GNUNET_OS_command_stop (mini->map_cmd); mini->map_cmd = NULL; } if (GNUNET_NO == mini->did_map) { GNUNET_free (mini); return; } mini->ac (mini->ac_cls, GNUNET_NO, (const struct sockaddr *) &mini->current_addr, sizeof (mini->current_addr), NULL); /* Note: oddly enough, deletion uses the external port whereas * addition uses the internal port; this rarely matters since they * often are the same, but it might... */ GNUNET_snprintf (pstr, sizeof (pstr), "%u", (unsigned int) ntohs (mini->current_addr.sin_port)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Unmapping port %u with UPnP\n", ntohs (mini->current_addr.sin_port)); mini->unmap_cmd = GNUNET_OS_command_run (&process_unmap_output, mini, UNMAP_TIMEOUT, "upnpc", "upnpc", "-d", pstr, mini->is_tcp ? "tcp" : "udp", NULL); } /* end of nat_mini.c */ gnunet-0.10.1/src/nat/gnunet-helper-nat-server-windows.c0000644000175000017500000003244712225777501020102 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/nat/gnunet-helper-nat-server-windows.c * @brief Windows tool to help bypass NATs using ICMP method * This code will work under W32 only * @author Christian Grothoff * * This program will send ONE ICMP message every 500 ms RAW sockets * to a DUMMY IP address and also listens for ICMP replies. Since * it uses RAW sockets, it must be run as an administrative user. * In order to keep the security risk of the resulting binary * minimal, the program ONLY opens the two RAW sockets with administrative * privileges, then drops them and only then starts to process * command line arguments. The code also does not link against * any shared libraries (except libc) and is strictly minimal * (except for checking for errors). The following list of people * have reviewed this code and considered it safe since the last * modification (if you reviewed it, please have your name added * to the list): * * - Nathan Evans * - Christian Grothoff */ #define _GNU_SOURCE #define FD_SETSIZE 1024 #include #include #include #include #include #include #include #include #include #include #include /** * Should we print some debug output? */ #define VERBOSE 0 /** * Must match IP given in the client. */ #define DUMMY_IP "192.0.2.86" /** * Default Port */ #define NAT_TRAV_PORT 22225 /** * Must match packet ID used by gnunet-helper-nat-client.c */ #define PACKET_ID 256 /** * TTL to use for our outgoing messages. */ #define IPDEFTTL 64 #define ICMP_ECHO 8 #define ICMP_TIME_EXCEEDED 11 /** * How often do we send our ICMP messages to receive replies? */ #define ICMP_SEND_FREQUENCY_MS 500 /** * IPv4 header. */ struct ip_header { /** * Version (4 bits) + Internet header length (4 bits) */ uint8_t vers_ihl; /** * Type of service */ uint8_t tos; /** * Total length */ uint16_t pkt_len; /** * Identification */ uint16_t id; /** * Flags (3 bits) + Fragment offset (13 bits) */ uint16_t flags_frag_offset; /** * Time to live */ uint8_t ttl; /** * Protocol */ uint8_t proto; /** * Header checksum */ uint16_t checksum; /** * Source address */ uint32_t src_ip; /** * Destination address */ uint32_t dst_ip; }; /** * Format of ICMP packet. */ struct icmp_ttl_exceeded_header { uint8_t type; uint8_t code; uint16_t checksum; uint32_t unused; /* followed by original payload */ }; struct icmp_echo_header { uint8_t type; uint8_t code; uint16_t checksum; uint32_t reserved; }; /** * Beginning of UDP packet. */ struct udp_header { uint16_t src_port; uint16_t dst_port; uint16_t length; uint16_t crc; }; /** * Will this binary be run in permissions testing mode? */ static boolean privilege_testing = FALSE; /** * Socket we use to receive "fake" ICMP replies. */ static SOCKET icmpsock; /** * Socket we use to send our ICMP requests. */ static SOCKET rawsock; /** * Socket we use to send our UDP requests. */ static SOCKET udpsock; /** * Target "dummy" address. */ static struct in_addr dummy; /** * CRC-16 for IP/ICMP headers. * * @param data what to calculate the CRC over * @param bytes number of bytes in data (must be multiple of 2) * @return the CRC 16. */ static uint16_t calc_checksum (const uint16_t * data, unsigned int bytes) { uint32_t sum; unsigned int i; sum = 0; for (i = 0; i < bytes / 2; i++) sum += data[i]; sum = (sum & 0xffff) + (sum >> 16); sum = htons (0xffff - sum); return sum; } /** * Convert IPv4 address from text to binary form. * * @param af address family * @param cp the address to print * @param buf where to write the address result * @return 1 on success */ static int inet_pton (int af, const char *cp, struct in_addr *buf) { buf->s_addr = inet_addr (cp); if (buf->s_addr == INADDR_NONE) { fprintf (stderr, "Error %d handling address %s", WSAGetLastError (), cp); return 0; } return 1; } /** * Send an ICMP message to the dummy IP. * * @param my_ip source address (our ip address) */ static void send_icmp_echo (const struct in_addr *my_ip) { char packet[sizeof (struct ip_header) + sizeof (struct icmp_echo_header)]; struct icmp_echo_header icmp_echo; struct ip_header ip_pkt; struct sockaddr_in dst; size_t off; int err; off = 0; ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; ip_pkt.pkt_len = htons (sizeof (packet)); ip_pkt.id = htons (PACKET_ID); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = IPDEFTTL; ip_pkt.proto = IPPROTO_ICMP; ip_pkt.checksum = 0; ip_pkt.src_ip = my_ip->s_addr; ip_pkt.dst_ip = dummy.s_addr; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (struct ip_header); icmp_echo.type = ICMP_ECHO; icmp_echo.code = 0; icmp_echo.reserved = 0; icmp_echo.checksum = 0; icmp_echo.checksum = htons (calc_checksum ((uint16_t *) & icmp_echo, sizeof (struct icmp_echo_header))); memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header)); off += sizeof (struct icmp_echo_header); memset (&dst, 0, sizeof (dst)); dst.sin_family = AF_INET; dst.sin_addr = dummy; err = sendto (rawsock, packet, off, 0, (struct sockaddr *) &dst, sizeof (dst)); if (err < 0) { #if VERBOSE fprintf (stderr, "sendto failed: %s\n", strerror (errno)); #endif } else if (err != off) { fprintf (stderr, "Error: partial send of ICMP message\n"); } } /** * Send a UDP message to the dummy IP. */ static void send_udp () { struct sockaddr_in dst; ssize_t err; memset (&dst, 0, sizeof (dst)); dst.sin_family = AF_INET; dst.sin_addr = dummy; dst.sin_port = htons (NAT_TRAV_PORT); err = sendto (udpsock, NULL, 0, 0, (struct sockaddr *) &dst, sizeof (dst)); if (err < 0) { #if VERBOSE fprintf (stderr, "sendto failed: %s\n", strerror (errno)); #endif } else if (0 != err) { fprintf (stderr, "Error: partial send of ICMP message\n"); } } /** * We've received an ICMP response. Process it. */ static void process_icmp_response () { char buf[65536]; ssize_t have; struct in_addr source_ip; struct ip_header ip_pkt; struct icmp_ttl_exceeded_header icmp_ttl; struct icmp_echo_header icmp_echo; struct udp_header udp_pkt; size_t off; uint16_t port; DWORD ssize; have = read (icmpsock, buf, sizeof (buf)); if (have == -1) { fprintf (stderr, "Error reading raw socket: %s\n", strerror (errno)); return; } #if VERBOSE fprintf (stderr, "Received message of %u bytes\n", (unsigned int) have); #endif if (have < (ssize_t) (sizeof (struct ip_header) + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct ip_header))) { /* malformed */ return; } off = 0; memcpy (&ip_pkt, &buf[off], sizeof (struct ip_header)); off += sizeof (struct ip_header); memcpy (&source_ip, &ip_pkt.src_ip, sizeof (source_ip)); memcpy (&icmp_ttl, &buf[off], sizeof (struct icmp_ttl_exceeded_header)); off += sizeof (struct icmp_ttl_exceeded_header); if ((ICMP_TIME_EXCEEDED != icmp_ttl.type) || (0 != icmp_ttl.code)) { /* different type than what we want */ return; } /* skip 2nd IP header */ memcpy (&ip_pkt, &buf[off], sizeof (struct ip_header)); off += sizeof (struct ip_header); switch (ip_pkt.proto) { case IPPROTO_ICMP: if (have != (sizeof (struct ip_header) * 2 + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct icmp_echo_header))) { /* malformed */ return; } /* grab ICMP ECHO content */ memcpy (&icmp_echo, &buf[off], sizeof (struct icmp_echo_header)); port = (uint16_t) ntohl (icmp_echo.reserved); break; case IPPROTO_UDP: if (have != (sizeof (struct ip_header) * 2 + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct udp_header))) { /* malformed */ return; } /* grab UDP content */ memcpy (&udp_pkt, &buf[off], sizeof (struct udp_header)); port = ntohs (udp_pkt.length); break; default: /* different type than what we want */ return; } ssize = sizeof (buf); WSAAddressToString ((LPSOCKADDR) & source_ip, sizeof (source_ip), NULL, buf, &ssize); if (port == 0) fprintf (stdout, "%s\n", buf); else fprintf (stdout, "%s:%u\n", buf, (unsigned int) port); fflush (stdout); } /** * Create an ICMP raw socket for reading. * * @return INVALID_SOCKET on error */ static SOCKET make_icmp_socket () { SOCKET ret; ret = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); if (INVALID_SOCKET == ret) { fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno)); return INVALID_SOCKET; } return ret; } /** * Create an ICMP raw socket for writing. * * @return INVALID_SOCKET on error */ static SOCKET make_raw_socket () { DWORD bOptVal = TRUE; int bOptLen = sizeof (bOptVal); rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); if (INVALID_SOCKET == rawsock) { fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno)); return INVALID_SOCKET; } if (0 != setsockopt (rawsock, SOL_SOCKET, SO_BROADCAST, (char *) &bOptVal, bOptLen)) { fprintf (stderr, "Error setting SO_BROADCAST to ON: %s\n", strerror (errno)); closesocket (rawsock); return INVALID_SOCKET; } if (0 != setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, (char *) &bOptVal, bOptLen)) { fprintf (stderr, "Error setting IP_HDRINCL to ON: %s\n", strerror (errno)); closesocket (rawsock); return INVALID_SOCKET; } return rawsock; } /** * Create a UDP socket for writing. * * @param my_ip source address (our ip address) * @return INVALID_SOCKET on error */ static SOCKET make_udp_socket (const struct in_addr *my_ip) { SOCKET ret; struct sockaddr_in addr; ret = socket (AF_INET, SOCK_DGRAM, 0); if (INVALID_SOCKET == ret) { fprintf (stderr, "Error opening UDP socket: %s\n", strerror (errno)); return INVALID_SOCKET; } memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_addr = *my_ip; addr.sin_port = htons (NAT_TRAV_PORT); if (0 != bind (ret, (struct sockaddr *) &addr, sizeof (addr))) { fprintf (stderr, "Error binding UDP socket to port %u: %s\n", NAT_TRAV_PORT, strerror (errno)); /* likely problematic, but not certain, try to continue */ } return ret; } int main (int argc, char *const *argv) { struct in_addr external; fd_set rs; struct timeval tv; WSADATA wsaData; unsigned int alt = 0; if ( (argc > 1) && (0 != strcmp (argv[1], "-d"))) { privilege_testing = TRUE; fprintf (stderr, "%s", "DEBUG: Running binary in privilege testing mode."); argv++; argc--; } if (2 != argc) { fprintf (stderr, "This program must be started with our (internal NAT) IP as the only argument.\n"); return 1; } if (1 != inet_pton (AF_INET, argv[1], &external)) { fprintf (stderr, "Error parsing IPv4 address: %s, error %s\n", argv[1], strerror (errno)); return 1; } if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) { fprintf (stderr, "Internal error converting dummy IP to binary.\n"); return 2; } if (WSAStartup (MAKEWORD (2, 1), &wsaData) != 0) { fprintf (stderr, "Failed to find Winsock 2.1 or better.\n"); return 2; } if (INVALID_SOCKET == (icmpsock = make_icmp_socket ())) { return 3; } if (INVALID_SOCKET == (make_raw_socket ())) { closesocket (icmpsock); return 3; } if (INVALID_SOCKET == (udpsock = make_udp_socket (&external))) { closesocket (icmpsock); closesocket (rawsock); return 3; } while ( ! privilege_testing) { FD_ZERO (&rs); FD_SET (icmpsock, &rs); tv.tv_sec = 0; tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000; if (-1 == select (icmpsock + 1, &rs, NULL, NULL, &tv)) { if (errno == EINTR) continue; fprintf (stderr, "select failed: %s\n", strerror (errno)); break; } if (FD_ISSET (icmpsock, &rs)) process_icmp_response (); if (0 == (++alt % 2)) send_icmp_echo (&external); else send_udp (); } /* select failed (internal error or OS out of resources) */ closesocket (icmpsock); closesocket (rawsock); closesocket (udpsock); WSACleanup (); if (privilege_testing) return 0; return 4; } /* end of gnunet-helper-nat-server-windows.c */ gnunet-0.10.1/src/nat/nat.h0000644000175000017500000000305012225777502012325 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/nat/nat.h * @brief Messages for interaction with gnunet-nat-server * @author Christian Grothoff * */ #ifndef NAT_H #define NAT_H #include "gnunet_util_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Request to test NAT traversal. */ struct GNUNET_NAT_TestMessage { /** * Header with type "GNUNET_MESSAGE_TYPE_NAT_TEST" */ struct GNUNET_MessageHeader header; /** * IPv4 target IP address */ uint32_t dst_ipv4; /** * Port to use, 0 to send dummy ICMP response. */ uint16_t dport; /** * Data to send OR advertised-port (in NBO) to use for dummy ICMP. */ uint16_t data; /** * GNUNET_YES for TCP, GNUNET_NO for UDP. */ int32_t is_tcp; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/nat/gnunet-helper-nat-client-windows.c0000644000175000017500000003120412225777501020040 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/nat/gnunet-helper-nat-client-windows.c * @brief Tool to help bypass NATs using ICMP method; must run as * administrator on W32 * This code is forx W32. * @author Nathan Evans * * This program will send ONE ICMP message using RAW sockets * to the IP address specified as the second argument. Since * it uses RAW sockets, it must be installed SUID or run as 'root'. * In order to keep the security risk of the resulting SUID binary * minimal, the program ONLY opens the RAW socket with root * privileges, then drops them and only then starts to process * command line arguments. The code also does not link against * any shared libraries (except libc) and is strictly minimal * (except for checking for errors). The following list of people * have reviewed this code and considered it safe since the last * modification (if you reviewed it, please have your name added * to the list): * * - Christian Grothoff * - Nathan Evans */ #define _GNU_SOURCE #define FD_SETSIZE 1024 #include #include #include #include #include #include #include #include #include #include #include #define ICMP_ECHO 8 #define IPDEFTTL 64 #define ICMP_TIME_EXCEEDED 11 /** * Must match IP given in the server. */ #define DUMMY_IP "192.0.2.86" #define NAT_TRAV_PORT 22225 /** * IPv4 header. */ struct ip_header { /** * Version (4 bits) + Internet header length (4 bits) */ uint8_t vers_ihl; /** * Type of service */ uint8_t tos; /** * Total length */ uint16_t pkt_len; /** * Identification */ uint16_t id; /** * Flags (3 bits) + Fragment offset (13 bits) */ uint16_t flags_frag_offset; /** * Time to live */ uint8_t ttl; /** * Protocol */ uint8_t proto; /** * Header checksum */ uint16_t checksum; /** * Source address */ uint32_t src_ip; /** * Destination address */ uint32_t dst_ip; }; /** * Format of ICMP packet. */ struct icmp_ttl_exceeded_header { uint8_t type; uint8_t code; uint16_t checksum; uint32_t unused; /* followed by original payload */ }; struct icmp_echo_header { uint8_t type; uint8_t code; uint16_t checksum; uint32_t reserved; }; /** * Beginning of UDP packet. */ struct udp_header { uint16_t src_port; uint16_t dst_port; uint16_t length; uint16_t crc; }; /** * Will this binary be run in permissions testing mode? */ static boolean privilege_testing = FALSE; /** * Socket we use to send our ICMP packets. */ static SOCKET rawsock; /** * Target "dummy" address. */ static struct in_addr dummy; /** * Port we are listening on (communicated to the server). */ static uint16_t port; /** * Convert IPv4 address from text to binary form. * * @param af address family * @param cp the address to print * @param buf where to write the address result * @return 1 on success */ static int inet_pton (int af, const char *cp, struct in_addr *buf) { buf->s_addr = inet_addr (cp); if (buf->s_addr == INADDR_NONE) { fprintf (stderr, "Error %d handling address %s", WSAGetLastError (), cp); return 0; } return 1; } /** * CRC-16 for IP/ICMP headers. * * @param data what to calculate the CRC over * @param bytes number of bytes in data (must be multiple of 2) * @return the CRC 16. */ static uint16_t calc_checksum (const uint16_t * data, unsigned int bytes) { uint32_t sum; unsigned int i; sum = 0; for (i = 0; i < bytes / 2; i++) sum += data[i]; sum = (sum & 0xffff) + (sum >> 16); sum = htons (0xffff - sum); return sum; } /** * Send an ICMP message to the target. * * @param my_ip source address * @param other target address */ static void send_icmp_udp (const struct in_addr *my_ip, const struct in_addr *other) { char packet[sizeof (struct ip_header) * 2 + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct udp_header)]; struct ip_header ip_pkt; struct icmp_ttl_exceeded_header icmp_pkt; struct udp_header udp_pkt; struct sockaddr_in dst; size_t off; int err; /* ip header: send to (known) ip address */ off = 0; ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; ip_pkt.pkt_len = htons (sizeof (packet)); ip_pkt.id = htons (256); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = 128; ip_pkt.proto = IPPROTO_ICMP; ip_pkt.checksum = 0; ip_pkt.src_ip = my_ip->s_addr; ip_pkt.dst_ip = other->s_addr; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (struct ip_header); icmp_pkt.type = ICMP_TIME_EXCEEDED; icmp_pkt.code = 0; icmp_pkt.checksum = 0; icmp_pkt.unused = 0; memcpy (&packet[off], &icmp_pkt, sizeof (struct icmp_ttl_exceeded_header)); off += sizeof (struct icmp_ttl_exceeded_header); /* ip header of the presumably 'lost' udp packet */ ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; ip_pkt.pkt_len = htons (sizeof (struct ip_header) + sizeof (struct udp_header)); ip_pkt.id = htons (0); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = 128; ip_pkt.proto = IPPROTO_UDP; ip_pkt.checksum = 0; ip_pkt.src_ip = other->s_addr; ip_pkt.dst_ip = dummy.s_addr; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (struct ip_header); /* build UDP header */ udp_pkt.src_port = htons (NAT_TRAV_PORT); udp_pkt.dst_port = htons (NAT_TRAV_PORT); udp_pkt.length = htons (port); udp_pkt.crc = 0; memcpy (&packet[off], &udp_pkt, sizeof (struct udp_header)); off += sizeof (struct udp_header); /* no go back to calculate ICMP packet checksum */ icmp_pkt.checksum = htons (calc_checksum ((uint16_t *) & packet[off], sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct ip_header) + sizeof (struct udp_header))); memcpy (&packet[sizeof (struct ip_header)], &icmp_pkt, sizeof (struct icmp_ttl_exceeded_header)); memset (&dst, 0, sizeof (dst)); dst.sin_family = AF_INET; dst.sin_addr = *other; err = sendto (rawsock, packet, sizeof (packet), 0, (struct sockaddr *) &dst, sizeof (dst)); if (err < 0) { fprintf (stderr, "sendto failed: %s\n", strerror (errno)); } else if (sizeof (packet) != (size_t) err) { fprintf (stderr, "Error: partial send of ICMP message\n"); } } /** * Send an ICMP message to the target. * * @param my_ip source address * @param other target address */ static void send_icmp (const struct in_addr *my_ip, const struct in_addr *other) { struct ip_header ip_pkt; struct icmp_ttl_exceeded_header icmp_ttl; struct icmp_echo_header icmp_echo; struct sockaddr_in dst; char packet[sizeof (struct ip_header) * 2 + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct icmp_echo_header)]; size_t off; int err; /* ip header: send to (known) ip address */ off = 0; ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; ip_pkt.pkt_len = htons (sizeof (packet)); ip_pkt.id = htons (256); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = IPDEFTTL; ip_pkt.proto = IPPROTO_ICMP; ip_pkt.checksum = 0; ip_pkt.src_ip = my_ip->s_addr; ip_pkt.dst_ip = other->s_addr; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (ip_pkt); /* icmp reply: time exceeded */ icmp_ttl.type = ICMP_TIME_EXCEEDED; icmp_ttl.code = 0; icmp_ttl.checksum = 0; icmp_ttl.unused = 0; memcpy (&packet[off], &icmp_ttl, sizeof (struct icmp_ttl_exceeded_header)); off += sizeof (struct icmp_ttl_exceeded_header); /* ip header of the presumably 'lost' udp packet */ ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; ip_pkt.pkt_len = htons (sizeof (struct ip_header) + sizeof (struct icmp_echo_header)); ip_pkt.id = htons (256); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ ip_pkt.proto = IPPROTO_ICMP; ip_pkt.src_ip = other->s_addr; ip_pkt.dst_ip = dummy.s_addr; ip_pkt.checksum = 0; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (struct ip_header); icmp_echo.type = ICMP_ECHO; icmp_echo.code = 0; icmp_echo.reserved = htonl (port); icmp_echo.checksum = 0; icmp_echo.checksum = htons (calc_checksum ((uint16_t *) & icmp_echo, sizeof (struct icmp_echo_header))); memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header)); /* no go back to calculate ICMP packet checksum */ off = sizeof (struct ip_header); icmp_ttl.checksum = htons (calc_checksum ((uint16_t *) & packet[off], sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct ip_header) + sizeof (struct icmp_echo_header))); memcpy (&packet[off], &icmp_ttl, sizeof (struct icmp_ttl_exceeded_header)); memset (&dst, 0, sizeof (dst)); dst.sin_family = AF_INET; dst.sin_addr = *other; err = sendto (rawsock, packet, sizeof (packet), 0, (struct sockaddr *) &dst, sizeof (dst)); if (err < 0) { fprintf (stderr, "sendto failed: %s\n", strerror (errno)); } else if (sizeof (packet) != (size_t) err) { fprintf (stderr, "Error: partial send of ICMP message\n"); } } /** * Create an ICMP raw socket. * * @return INVALID_SOCKET on error */ static SOCKET make_raw_socket () { DWORD bOptVal = TRUE; int bOptLen = sizeof (bOptVal); SOCKET ret; ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); if (INVALID_SOCKET == ret) { fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno)); return INVALID_SOCKET; } if (0 != setsockopt (ret, SOL_SOCKET, SO_BROADCAST, (char *) &bOptVal, bOptLen)) { fprintf (stderr, "Error setting SO_BROADCAST to ON: %s\n", strerror (errno)); closesocket (rawsock); return INVALID_SOCKET; } if (0 != setsockopt (ret, IPPROTO_IP, IP_HDRINCL, (char *) &bOptVal, bOptLen)) { fprintf (stderr, "Error setting IP_HDRINCL to ON: %s\n", strerror (errno)); closesocket (rawsock); return INVALID_SOCKET; } return ret; } int main (int argc, char *const *argv) { struct in_addr external; struct in_addr target; WSADATA wsaData; unsigned int p; if (argc > 1 && 0 != strcmp (argv[1], "-d")){ privilege_testing = TRUE; fprintf (stderr, "%s", "DEBUG: Running binary in privilege testing mode."); argv++; argc--; } if (argc != 4) { fprintf (stderr, "%s", "This program must be started with our IP, the targets external IP, and our port as arguments.\n"); return 1; } if ((1 != inet_pton (AF_INET, argv[1], &external)) || (1 != inet_pton (AF_INET, argv[2], &target))) { fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); return 1; } if ((1 != sscanf (argv[3], "%u", &p)) || (0 == p) || (0xFFFF < p)) { fprintf (stderr, "Error parsing port value `%s'\n", argv[3]); return 1; } port = (uint16_t) p; if (0 != WSAStartup (MAKEWORD (2, 1), &wsaData)) { fprintf (stderr, "%s", "Failed to find Winsock 2.1 or better.\n"); return 2; } if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) { fprintf (stderr, "%s", "Internal error converting dummy IP to binary.\n"); return 2; } if (-1 == (rawsock = make_raw_socket ())) return 3; if (!privilege_testing){ send_icmp (&external, &target); send_icmp_udp (&external, &target); } closesocket (rawsock); WSACleanup (); return 0; } /* end of gnunet-helper-nat-client-windows.c */ gnunet-0.10.1/src/nat/nat.c0000644000175000017500000012642412301361473012322 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nat/nat.c * @brief Library handling UPnP and NAT-PMP port forwarding and * external IP address retrieval * @author Milan Bouchet-Valat * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #include "gnunet_nat_lib.h" #include "nat.h" #define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) /** * How often do we scan for changes in our IP address from our local * interfaces? */ #define IFC_SCAN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) /** * How often do we scan for changes in how our hostname resolves? */ #define HOSTNAME_DNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 20) /** * How often do we scan for changes in how our external (dyndns) hostname resolves? */ #define DYNDNS_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7) /** * How long until we give up trying to resolve our own hostname? */ #define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * Where did the given local address originate from? * To be used for debugging as well as in the future * to remove all addresses from a certain source when * we reevaluate the source. */ enum LocalAddressSource { /** * Address was obtained by DNS resolution of the external hostname * given in the configuration (i.e. hole-punched DynDNS setup). */ LAL_EXTERNAL_IP, /** * Address was obtained by DNS resolution of the external hostname * given in the configuration (i.e. hole-punched DynDNS setup) * during the previous iteration (see #3213). */ LAL_EXTERNAL_IP_OLD, /** * Address was obtained by looking up our own hostname in DNS. */ LAL_HOSTNAME_DNS, /** * Address was obtained by scanning our hosts's network interfaces * and taking their address (no DNS involved). */ LAL_INTERFACE_ADDRESS, /** * Addresses we were explicitly bound to. */ LAL_BINDTO_ADDRESS, /** * Addresses from UPnP or PMP */ LAL_UPNP, /** * End of the list. */ LAL_END }; /** * List of local addresses that we currently deem valid. Actual * struct is followed by the 'struct sockaddr'. Note that the code * intentionally makes no attempt to ensure that a particular address * is only listed once (especially since it may come from different * sources, and the source is an "internal" construct). */ struct LocalAddressList { /** * This is a linked list. */ struct LocalAddressList *next; /** * Previous entry. */ struct LocalAddressList *prev; /** * Number of bytes of address that follow. */ socklen_t addrlen; /** * Origin of the local address. */ enum LocalAddressSource source; }; /** * Handle for miniupnp-based NAT traversal actions. */ struct MiniList { /** * Doubly-linked list. */ struct MiniList *next; /** * Doubly-linked list. */ struct MiniList *prev; /** * Handle to mini-action. */ struct GNUNET_NAT_MiniHandle *mini; /** * Local port number that was mapped. */ uint16_t port; }; /** * Handle for active NAT registrations. */ struct GNUNET_NAT_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Function to call when we learn about a new address. */ GNUNET_NAT_AddressCallback address_callback; /** * Function to call when we notice another peer asking for * connection reversal. */ GNUNET_NAT_ReversalCallback reversal_callback; /** * Closure for callbacks (@e address_callback and @e reversal_callback) */ void *callback_cls; /** * Handle for (DYN)DNS lookup of our external IP. */ struct GNUNET_RESOLVER_RequestHandle *ext_dns; /** * Handle for request of hostname resolution, non-NULL if pending. */ struct GNUNET_RESOLVER_RequestHandle *hostname_dns; /** * stdout pipe handle for the gnunet-helper-nat-server process */ struct GNUNET_DISK_PipeHandle *server_stdout; /** * stdout file handle (for reading) for the gnunet-helper-nat-server process */ const struct GNUNET_DISK_FileHandle *server_stdout_handle; /** * Linked list of currently valid addresses (head). */ struct LocalAddressList *lal_head; /** * Linked list of currently valid addresses (tail). */ struct LocalAddressList *lal_tail; /** * How long do we wait for restarting a crashed gnunet-helper-nat-server? */ struct GNUNET_TIME_Relative server_retry_delay; /** * ID of select gnunet-helper-nat-server stdout read task */ GNUNET_SCHEDULER_TaskIdentifier server_read_task; /** * ID of interface IP-scan task */ GNUNET_SCHEDULER_TaskIdentifier ifc_task; /** * ID of hostname DNS lookup task */ GNUNET_SCHEDULER_TaskIdentifier hostname_task; /** * ID of DynDNS lookup task */ GNUNET_SCHEDULER_TaskIdentifier dns_task; /** * ID of task to add addresses from bind. */ GNUNET_SCHEDULER_TaskIdentifier bind_task; /** * How often do we scan for changes in our IP address from our local * interfaces? */ struct GNUNET_TIME_Relative ifc_scan_frequency; /** * How often do we scan for changes in how our hostname resolves? */ struct GNUNET_TIME_Relative hostname_dns_frequency; /** * How often do we scan for changes in how our external (dyndns) hostname resolves? */ struct GNUNET_TIME_Relative dyndns_frequency; /** * The process id of the server process (if behind NAT) */ struct GNUNET_OS_Process *server_proc; /** * LAN address as passed by the caller (array). */ struct sockaddr **local_addrs; /** * Length of the @e local_addrs. */ socklen_t *local_addrlens; /** * List of handles for UPnP-traversal, one per local port (if * not IPv6-only). */ struct MiniList *mini_head; /** * List of handles for UPnP-traversal, one per local port (if * not IPv6-only). */ struct MiniList *mini_tail; /** * Number of entries in 'local_addrs' array. */ unsigned int num_local_addrs; /** * Our external address (according to config, UPnP may disagree...), * in dotted decimal notation, IPv4-only. Or NULL if not known. */ char *external_address; /** * Presumably our internal address (according to config) */ char *internal_address; /** * Is this transport configured to be behind a NAT? */ int behind_nat; /** * Has the NAT been punched? (according to config) */ int nat_punched; /** * Is this transport configured to allow connections to NAT'd peers? */ int enable_nat_client; /** * Should we run the gnunet-helper-nat-server? */ int enable_nat_server; /** * Are we allowed to try UPnP/PMP for NAT traversal? */ int enable_upnp; /** * Should we use local addresses (loopback)? (according to config) */ int use_localaddresses; /** * Should we return local addresses to clients */ int return_localaddress; /** * Should we do a DNS lookup of our hostname to find out our own IP? */ int use_hostname; /** * Is using IPv6 disabled? */ int disable_ipv6; /** * Is this TCP or UDP? */ int is_tcp; /** * Port we advertise to the outside. */ uint16_t adv_port; }; /** * Try to start the gnunet-helper-nat-server (if it is not * already running). * * @param h handle to NAT */ static void start_gnunet_nat_server (struct GNUNET_NAT_Handle *h); /** * Remove all addresses from the list of 'local' addresses * that originated from the given source. * * @param h handle to NAT * @param src source that identifies addresses to remove */ static void remove_from_address_list_by_source (struct GNUNET_NAT_Handle *h, enum LocalAddressSource src) { struct LocalAddressList *pos; struct LocalAddressList *next; next = h->lal_head; while (NULL != (pos = next)) { next = pos->next; if (pos->source != src) continue; GNUNET_CONTAINER_DLL_remove (h->lal_head, h->lal_tail, pos); if (NULL != h->address_callback) h->address_callback (h->callback_cls, GNUNET_NO, (const struct sockaddr *) &pos[1], pos->addrlen); GNUNET_free (pos); } } /** * Add the given address to the list of 'local' addresses, thereby * making it a 'legal' address for this peer to have. * * @param h handle to NAT * @param src where did the local address originate from? * @param arg the address, some `struct sockaddr` * @param arg_size number of bytes in @a arg */ static void add_to_address_list_as_is (struct GNUNET_NAT_Handle *h, enum LocalAddressSource src, const struct sockaddr *arg, socklen_t arg_size) { struct LocalAddressList *lal; lal = GNUNET_malloc (sizeof (struct LocalAddressList) + arg_size); memcpy (&lal[1], arg, arg_size); lal->addrlen = arg_size; lal->source = src; GNUNET_CONTAINER_DLL_insert (h->lal_head, h->lal_tail, lal); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address `%s' from source %d\n", GNUNET_a2s (arg, arg_size), src); if (NULL != h->address_callback) h->address_callback (h->callback_cls, GNUNET_YES, arg, arg_size); } /** * Add the given address to the list of 'local' addresses, thereby * making it a 'legal' address for this peer to have. Set the * port number in the process to the advertised port and possibly * also to zero (if we have the gnunet-helper-nat-server). * * @param h handle to NAT * @param src where did the local address originate from? * @param arg the address, some `struct sockaddr` * @param arg_size number of bytes in @a arg */ static void add_to_address_list (struct GNUNET_NAT_Handle *h, enum LocalAddressSource src, const struct sockaddr *arg, socklen_t arg_size) { struct sockaddr_in s4; const struct sockaddr_in *in4; struct sockaddr_in6 s6; const struct sockaddr_in6 *in6; if (arg_size == sizeof (struct sockaddr_in)) { in4 = (const struct sockaddr_in *) arg; s4 = *in4; s4.sin_port = htons (h->adv_port); add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4, sizeof (struct sockaddr_in)); if (GNUNET_YES == h->enable_nat_server) { /* also add with PORT = 0 to indicate NAT server is enabled */ s4.sin_port = htons (0); add_to_address_list_as_is (h, src, (const struct sockaddr *) &s4, sizeof (struct sockaddr_in)); } } else if (arg_size == sizeof (struct sockaddr_in6)) { if (GNUNET_YES != h->disable_ipv6) { in6 = (const struct sockaddr_in6 *) arg; s6 = *in6; s6.sin6_port = htons (h->adv_port); add_to_address_list_as_is (h, src, (const struct sockaddr *) &s6, sizeof (struct sockaddr_in6)); } } else { GNUNET_assert (0); } } /** * Add the given IP address to the list of 'local' addresses, thereby * making it a 'legal' address for this peer to have. * * @param h handle to NAT * @param src where did the local address originate from? * @param addr the address, some `struct in_addr` or `struct in6_addr` * @param addrlen number of bytes in addr */ static void add_ip_to_address_list (struct GNUNET_NAT_Handle *h, enum LocalAddressSource src, const void *addr, socklen_t addrlen) { struct sockaddr_in s4; const struct in_addr *in4; struct sockaddr_in6 s6; const struct in6_addr *in6; if (addrlen == sizeof (struct in_addr)) { in4 = (const struct in_addr *) addr; memset (&s4, 0, sizeof (s4)); s4.sin_family = AF_INET; s4.sin_port = 0; #if HAVE_SOCKADDR_IN_SIN_LEN s4.sin_len = (u_char) sizeof (struct sockaddr_in); #endif s4.sin_addr = *in4; add_to_address_list (h, src, (const struct sockaddr *) &s4, sizeof (struct sockaddr_in)); if (GNUNET_YES == h->enable_nat_server) { /* also add with PORT = 0 to indicate NAT server is enabled */ s4.sin_port = htons (0); add_to_address_list (h, src, (const struct sockaddr *) &s4, sizeof (struct sockaddr_in)); } } else if (addrlen == sizeof (struct in6_addr)) { if (GNUNET_YES != h->disable_ipv6) { in6 = (const struct in6_addr *) addr; memset (&s6, 0, sizeof (s6)); s6.sin6_family = AF_INET6; s6.sin6_port = htons (h->adv_port); #if HAVE_SOCKADDR_IN_SIN_LEN s6.sin6_len = (u_char) sizeof (struct sockaddr_in6); #endif s6.sin6_addr = *in6; add_to_address_list (h, src, (const struct sockaddr *) &s6, sizeof (struct sockaddr_in6)); } } else { GNUNET_assert (0); } } /** * Task to do DNS lookup on our external hostname to * get DynDNS-IP addresses. * * @param cls the NAT handle * @param tc scheduler context */ static void resolve_dns (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Our (external) hostname was resolved and the configuration says that * the NAT was hole-punched. * * @param cls the `struct GNUNET_NAT_Handle` * @param addr NULL on error, otherwise result of DNS lookup * @param addrlen number of bytes in @a addr */ static void process_external_ip (void *cls, const struct sockaddr *addr, socklen_t addrlen) { struct GNUNET_NAT_Handle *h = cls; struct in_addr dummy; if (NULL == addr) { h->ext_dns = NULL; /* Current iteration is over, remove 'old' IPs now */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Purging old IPs for external address\n"); remove_from_address_list_by_source (h, LAL_EXTERNAL_IP_OLD); if (1 == inet_pton (AF_INET, h->external_address, &dummy)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Got numeric IP for external address, not repeating lookup\n"); return; /* repated lookup pointless: was numeric! */ } h->dns_task = GNUNET_SCHEDULER_add_delayed (h->dyndns_frequency, &resolve_dns, h); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Got IP `%s' for external address `%s'\n", GNUNET_a2s (addr, addrlen), h->external_address); add_to_address_list (h, LAL_EXTERNAL_IP, addr, addrlen); } /** * Task to do a lookup on our hostname for IP addresses. * * @param cls the NAT handle * @param tc scheduler context */ static void resolve_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Function called by the resolver for each address obtained from DNS * for our own hostname. Add the addresses to the list of our IP * addresses. * * @param cls closure * @param addr one of the addresses of the host, NULL for the last address * @param addrlen length of the @a addr */ static void process_hostname_ip (void *cls, const struct sockaddr *addr, socklen_t addrlen) { struct GNUNET_NAT_Handle *h = cls; if (NULL == addr) { h->hostname_dns = NULL; h->hostname_task = GNUNET_SCHEDULER_add_delayed (h->hostname_dns_frequency, &resolve_hostname, h); return; } add_to_address_list (h, LAL_HOSTNAME_DNS, addr, addrlen); } /** * Add the IP of our network interface to the list of * our IP addresses. * * @param cls the `struct GNUNET_NAT_Handle` * @param name name of the interface * @param isDefault do we think this may be our default interface * @param addr address of the interface * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) * @param netmask the network mask (can be NULL for unknown or unassigned)) * @param addrlen number of bytes in @a addr and @a broadcast_addr * @return #GNUNET_OK to continue iterating */ static int process_interfaces (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen) { const static struct in6_addr any6 = IN6ADDR_ANY_INIT; struct GNUNET_NAT_Handle *h = cls; const struct sockaddr_in *s4; const struct sockaddr_in6 *s6; const void *ip; char buf[INET6_ADDRSTRLEN]; unsigned int i; int have_any; switch (addr->sa_family) { case AF_INET: /* check if we're bound to the "ANY" IP address */ have_any = GNUNET_NO; for (i=0;inum_local_addrs;i++) { if (h->local_addrs[i]->sa_family != AF_INET) continue; #ifndef INADDR_ANY #define INADDR_ANY 0 #endif if (INADDR_ANY == ((struct sockaddr_in*) h->local_addrs[i])->sin_addr.s_addr) { have_any = GNUNET_YES; break; } } if (GNUNET_NO == have_any) return GNUNET_OK; /* not bound to IP 0.0.0.0 but to specific IP addresses, do not use those from interfaces */ s4 = (struct sockaddr_in *) addr; ip = &s4->sin_addr; /* Check if address is in 127.0.0.0/8 */ uint32_t address = ntohl ((uint32_t) (s4->sin_addr.s_addr)); uint32_t value = (address & 0xFF000000) ^ 0x7F000000; if ((h->return_localaddress == GNUNET_NO) && (value == 0)) { return GNUNET_OK; } if (GNUNET_YES == h->use_localaddresses) { add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s4->sin_addr, sizeof (struct in_addr)); } break; case AF_INET6: /* check if we're bound to the "ANY" IP address */ have_any = GNUNET_NO; for (i=0;inum_local_addrs;i++) { if (h->local_addrs[i]->sa_family != AF_INET6) continue; if (0 == memcmp (&any6, &((struct sockaddr_in6*) h->local_addrs[i])->sin6_addr, sizeof (struct in6_addr))) { have_any = GNUNET_YES; break; } } if (GNUNET_NO == have_any) return GNUNET_OK; /* not bound to "ANY" IP (::0) but to specific IP addresses, do not use those from interfaces */ s6 = (struct sockaddr_in6 *) addr; if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr)) { /* skip link local addresses */ return GNUNET_OK; } if ((h->return_localaddress == GNUNET_NO) && (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr))) { return GNUNET_OK; } ip = &s6->sin6_addr; if (GNUNET_YES == h->use_localaddresses) { add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s6->sin6_addr, sizeof (struct in6_addr)); } break; default: GNUNET_break (0); return GNUNET_OK; } if ((h->internal_address == NULL) && (h->server_proc == NULL) && (h->server_read_task == GNUNET_SCHEDULER_NO_TASK) && (GNUNET_YES == isDefault) && ((addr->sa_family == AF_INET) || (addr->sa_family == AF_INET6))) { /* no internal address configured, but we found a "default" * interface, try using that as our 'internal' address */ h->internal_address = GNUNET_strdup (inet_ntop (addr->sa_family, ip, buf, sizeof (buf))); start_gnunet_nat_server (h); } return GNUNET_OK; } /** * Task that restarts the gnunet-helper-nat-server process after a crash * after a certain delay. * * @param cls the `struct GNUNET_NAT_Handle` * @param tc scheduler context */ static void restart_nat_server (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_Handle *h = cls; h->server_read_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; start_gnunet_nat_server (h); } /** * We have been notified that gnunet-helper-nat-server has written * something to stdout. Handle the output, then reschedule this * function to be called again once more is available. * * @param cls the NAT handle * @param tc the scheduling context */ static void nat_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_Handle *h = cls; char mybuf[40]; ssize_t bytes; size_t i; int port; const char *port_start; struct sockaddr_in sin_addr; h->server_read_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; memset (mybuf, 0, sizeof (mybuf)); bytes = GNUNET_DISK_file_read (h->server_stdout_handle, mybuf, sizeof (mybuf)); if (bytes < 1) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished reading from server stdout with code: %d\n", bytes); if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG)) GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill"); GNUNET_OS_process_wait (h->server_proc); GNUNET_OS_process_destroy (h->server_proc); h->server_proc = NULL; GNUNET_DISK_pipe_close (h->server_stdout); h->server_stdout = NULL; h->server_stdout_handle = NULL; /* now try to restart it */ h->server_retry_delay = GNUNET_TIME_STD_BACKOFF (h->server_retry_delay); h->server_read_task = GNUNET_SCHEDULER_add_delayed (h->server_retry_delay, &restart_nat_server, h); return; } port_start = NULL; for (i = 0; i < sizeof (mybuf); i++) { if (mybuf[i] == '\n') { mybuf[i] = '\0'; break; } if ((mybuf[i] == ':') && (i + 1 < sizeof (mybuf))) { mybuf[i] = '\0'; port_start = &mybuf[i + 1]; } } /* construct socket address of sender */ memset (&sin_addr, 0, sizeof (sin_addr)); sin_addr.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sin_addr.sin_len = sizeof (sin_addr); #endif if ((NULL == port_start) || (1 != SSCANF (port_start, "%d", &port)) || (-1 == inet_pton (AF_INET, mybuf, &sin_addr.sin_addr))) { /* should we restart gnunet-helper-nat-server? */ LOG (GNUNET_ERROR_TYPE_WARNING, "nat", _("gnunet-helper-nat-server generated malformed address `%s'\n"), mybuf); h->server_read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, h->server_stdout_handle, &nat_server_read, h); return; } sin_addr.sin_port = htons ((uint16_t) port); LOG (GNUNET_ERROR_TYPE_DEBUG, "gnunet-helper-nat-server read: %s:%d\n", mybuf, port); h->reversal_callback (h->callback_cls, (const struct sockaddr *) &sin_addr, sizeof (sin_addr)); h->server_read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, h->server_stdout_handle, &nat_server_read, h); } /** * Try to start the gnunet-helper-nat-server (if it is not * already running). * * @param h handle to NAT */ static void start_gnunet_nat_server (struct GNUNET_NAT_Handle *h) { char *binary; if ((h->behind_nat == GNUNET_YES) && (h->enable_nat_server == GNUNET_YES) && (h->internal_address != NULL) && (NULL != (h->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES)))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting `%s' at `%s'\n", "gnunet-helper-nat-server", h->internal_address); /* Start the server process */ binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); h->server_proc = GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout, NULL, binary, "gnunet-helper-nat-server", h->internal_address, NULL); GNUNET_free (binary); if (h->server_proc == NULL) { LOG (GNUNET_ERROR_TYPE_WARNING, "nat", _("Failed to start %s\n"), "gnunet-helper-nat-server"); GNUNET_DISK_pipe_close (h->server_stdout); h->server_stdout = NULL; } else { /* Close the write end of the read pipe */ GNUNET_DISK_pipe_close_end (h->server_stdout, GNUNET_DISK_PIPE_END_WRITE); h->server_stdout_handle = GNUNET_DISK_pipe_handle (h->server_stdout, GNUNET_DISK_PIPE_END_READ); h->server_read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, h->server_stdout_handle, &nat_server_read, h); } } } /** * Task to scan the local network interfaces for IP addresses. * * @param cls the NAT handle * @param tc scheduler context */ static void list_interfaces (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_Handle *h = cls; h->ifc_task = GNUNET_SCHEDULER_NO_TASK; remove_from_address_list_by_source (h, LAL_INTERFACE_ADDRESS); GNUNET_OS_network_interfaces_list (&process_interfaces, h); h->ifc_task = GNUNET_SCHEDULER_add_delayed (h->ifc_scan_frequency, &list_interfaces, h); } /** * Task to do a lookup on our hostname for IP addresses. * * @param cls the NAT handle * @param tc scheduler context */ static void resolve_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_Handle *h = cls; h->hostname_task = GNUNET_SCHEDULER_NO_TASK; remove_from_address_list_by_source (h, LAL_HOSTNAME_DNS); h->hostname_dns = GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, HOSTNAME_RESOLVE_TIMEOUT, &process_hostname_ip, h); } /** * Task to do DNS lookup on our external hostname to * get DynDNS-IP addresses. * * @param cls the NAT handle * @param tc scheduler context */ static void resolve_dns (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_Handle *h = cls; struct LocalAddressList *pos; h->dns_task = GNUNET_SCHEDULER_NO_TASK; for (pos = h->lal_head; NULL != pos; pos = pos->next) if (pos->source == LAL_EXTERNAL_IP) pos->source = LAL_EXTERNAL_IP_OLD; LOG (GNUNET_ERROR_TYPE_DEBUG, "Resolving external address `%s'\n", h->external_address); h->ext_dns = GNUNET_RESOLVER_ip_get (h->external_address, AF_INET, GNUNET_TIME_UNIT_MINUTES, &process_external_ip, h); } /** * Add or remove UPnP-mapped addresses. * * @param cls the `struct GNUNET_NAT_Handle` * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean * the previous (now invalid) one * @param addr either the previous or the new public IP address * @param addrlen actual lenght of @a addr * @param emsg NULL on success, otherwise an error message */ static void upnp_add (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen, const char *emsg) { struct GNUNET_NAT_Handle *h = cls; struct LocalAddressList *pos; struct LocalAddressList *next; if (GNUNET_YES == add_remove) { add_to_address_list (h, LAL_UPNP, addr, addrlen); return; } /* remove address */ next = h->lal_head; while (NULL != (pos = next)) { next = pos->next; if ((pos->source != LAL_UPNP) || (pos->addrlen != addrlen) || (0 != memcmp (&pos[1], addr, addrlen))) continue; GNUNET_CONTAINER_DLL_remove (h->lal_head, h->lal_tail, pos); if (NULL != h->address_callback) h->address_callback (h->callback_cls, GNUNET_NO, (const struct sockaddr *) &pos[1], pos->addrlen); GNUNET_free (pos); return; /* only remove once */ } /* asked to remove address that does not exist */ GNUNET_break (0); } /** * Try to add a port mapping using UPnP. * * @param h overall NAT handle * @param port port to map with UPnP */ static void add_minis (struct GNUNET_NAT_Handle *h, uint16_t port) { struct MiniList *ml; ml = h->mini_head; while (NULL != ml) { if (port == ml->port) return; /* already got this port */ ml = ml->next; } ml = GNUNET_new (struct MiniList); ml->port = port; ml->mini = GNUNET_NAT_mini_map_start (port, h->is_tcp, &upnp_add, h); GNUNET_CONTAINER_DLL_insert (h->mini_head, h->mini_tail, ml); } /** * Task to add addresses from original bind to set of valid addrs. * * @param cls the NAT handle * @param tc scheduler context */ static void add_from_bind (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static struct in6_addr any = IN6ADDR_ANY_INIT; struct GNUNET_NAT_Handle *h = cls; unsigned int i; struct sockaddr *sa; const struct sockaddr_in *v4; h->bind_task = GNUNET_SCHEDULER_NO_TASK; for (i = 0; i < h->num_local_addrs; i++) { sa = h->local_addrs[i]; switch (sa->sa_family) { case AF_INET: if (sizeof (struct sockaddr_in) != h->local_addrlens[i]) { GNUNET_break (0); break; } v4 = (const struct sockaddr_in *) sa; if (0 != v4->sin_addr.s_addr) add_to_address_list (h, LAL_BINDTO_ADDRESS, sa, sizeof (struct sockaddr_in)); if (h->enable_upnp) add_minis (h, ntohs (v4->sin_port)); break; case AF_INET6: if (sizeof (struct sockaddr_in6) != h->local_addrlens[i]) { GNUNET_break (0); break; } if (0 != memcmp (&((const struct sockaddr_in6 *) sa)->sin6_addr, &any, sizeof (struct in6_addr))) add_to_address_list (h, LAL_BINDTO_ADDRESS, sa, sizeof (struct sockaddr_in6)); break; default: break; } } } /** * Attempt to enable port redirection and detect public IP address contacting * UPnP or NAT-PMP routers on the local network. Use addr to specify to which * of the local host's addresses should the external port be mapped. The port * is taken from the corresponding sockaddr_in[6] field. * * @param cfg configuration to use * @param is_tcp #GNUNET_YES for TCP, #GNUNET_NO for UDP * @param adv_port advertised port (port we are either bound to or that our OS * locally performs redirection from to our bound port). * @param num_addrs number of addresses in 'addrs' * @param addrs the local addresses packets should be redirected to * @param addrlens actual lengths of the addresses * @param address_callback function to call everytime the public IP address changes * @param reversal_callback function to call if someone wants connection reversal from us * @param callback_cls closure for callbacks * @return NULL on error, otherwise handle that can be used to unregister */ struct GNUNET_NAT_Handle * GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, uint16_t adv_port, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t * addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls) { struct GNUNET_NAT_Handle *h; struct in_addr in_addr; unsigned int i; char *binary; LOG (GNUNET_ERROR_TYPE_DEBUG, "Registered with NAT service at port %u with %u IP bound local addresses\n", (unsigned int) adv_port, num_addrs); h = GNUNET_new (struct GNUNET_NAT_Handle); h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS; h->cfg = cfg; h->is_tcp = is_tcp; h->address_callback = address_callback; h->reversal_callback = reversal_callback; h->callback_cls = callback_cls; h->num_local_addrs = num_addrs; h->adv_port = adv_port; if (num_addrs != 0) { h->local_addrs = GNUNET_malloc (num_addrs * sizeof (struct sockaddr *)); h->local_addrlens = GNUNET_malloc (num_addrs * sizeof (socklen_t)); for (i = 0; i < num_addrs; i++) { GNUNET_assert (addrlens[i] > 0); GNUNET_assert (addrs[i] != NULL); h->local_addrlens[i] = addrlens[i]; h->local_addrs[i] = GNUNET_malloc (addrlens[i]); memcpy (h->local_addrs[i], addrs[i], addrlens[i]); } } h->bind_task = GNUNET_SCHEDULER_add_now (&add_from_bind, h); if (GNUNET_OK == GNUNET_CONFIGURATION_have_value (cfg, "nat", "INTERNAL_ADDRESS")) { (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat", "INTERNAL_ADDRESS", &h->internal_address); } if ((h->internal_address != NULL) && (inet_pton (AF_INET, h->internal_address, &in_addr) != 1)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "nat", "INTERNAL_ADDRESS", _("malformed")); GNUNET_free (h->internal_address); h->internal_address = NULL; } if (GNUNET_OK == GNUNET_CONFIGURATION_have_value (cfg, "nat", "EXTERNAL_ADDRESS")) { (void) GNUNET_CONFIGURATION_get_value_string (cfg, "nat", "EXTERNAL_ADDRESS", &h->external_address); } h->behind_nat = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "BEHIND_NAT"); h->nat_punched = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "PUNCHED_NAT"); h->enable_nat_client = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_CLIENT"); h->enable_nat_server = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_ICMP_SERVER"); h->enable_upnp = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_UPNP"); h->use_localaddresses = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_LOCALADDR"); h->return_localaddress = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "RETURN_LOCAL_ADDRESSES"); h->use_hostname = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_HOSTNAME"); h->disable_ipv6 = GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "DISABLEV6"); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "DYNDNS_FREQUENCY", &h->dyndns_frequency)) h->dyndns_frequency = DYNDNS_FREQUENCY; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "IFC_SCAN_FREQUENCY", &h->ifc_scan_frequency)) h->ifc_scan_frequency = IFC_SCAN_FREQUENCY; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "HOSTNAME_DNS_FREQUENCY", &h->hostname_dns_frequency)) h->hostname_dns_frequency = HOSTNAME_DNS_FREQUENCY; if (NULL == reversal_callback) h->enable_nat_server = GNUNET_NO; /* Check if NAT was hole-punched */ if ((NULL != h->address_callback) && (NULL != h->external_address) && (GNUNET_YES == h->nat_punched)) { h->dns_task = GNUNET_SCHEDULER_add_now (&resolve_dns, h); h->enable_nat_server = GNUNET_NO; h->enable_upnp = GNUNET_NO; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "No external IP address given to add to our list of addresses\n"); } /* Test for SUID binaries */ binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); if ((h->behind_nat == GNUNET_YES) && (GNUNET_YES == h->enable_nat_server) && (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d 127.0.0.1" ))) // use localhost as source for that one udp-port, ok for testing { h->enable_nat_server = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_WARNING, _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), "gnunet-helper-nat-server"); } GNUNET_free (binary); binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); if ((GNUNET_YES == h->enable_nat_client) && (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d 127.0.0.1 127.0.0.2 42"))) // none of these parameters are actually used in privilege testing mode { h->enable_nat_client = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), "gnunet-helper-nat-client"); } GNUNET_free (binary); start_gnunet_nat_server (h); /* FIXME: add support for UPnP, etc */ if (NULL != h->address_callback) { h->ifc_task = GNUNET_SCHEDULER_add_now (&list_interfaces, h); if (GNUNET_YES == h->use_hostname) h->hostname_task = GNUNET_SCHEDULER_add_now (&resolve_hostname, h); } return h; } /** * Stop port redirection and public IP address detection for the given handle. * This frees the handle, after having sent the needed commands to close open ports. * * @param h the handle to stop */ void GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h) { unsigned int i; struct LocalAddressList *lal; struct MiniList *ml; LOG (GNUNET_ERROR_TYPE_DEBUG, "NAT unregister called\n"); while (NULL != (ml = h->mini_head)) { GNUNET_CONTAINER_DLL_remove (h->mini_head, h->mini_tail, ml); if (NULL != ml->mini) GNUNET_NAT_mini_map_stop (ml->mini); GNUNET_free (ml); } if (NULL != h->ext_dns) { GNUNET_RESOLVER_request_cancel (h->ext_dns); h->ext_dns = NULL; } if (NULL != h->hostname_dns) { GNUNET_RESOLVER_request_cancel (h->hostname_dns); h->hostname_dns = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->server_read_task) { GNUNET_SCHEDULER_cancel (h->server_read_task); h->server_read_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != h->bind_task) { GNUNET_SCHEDULER_cancel (h->bind_task); h->bind_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != h->ifc_task) { GNUNET_SCHEDULER_cancel (h->ifc_task); h->ifc_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != h->hostname_task) { GNUNET_SCHEDULER_cancel (h->hostname_task); h->hostname_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != h->dns_task) { GNUNET_SCHEDULER_cancel (h->dns_task); h->dns_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != h->server_proc) { if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG)) GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill"); GNUNET_OS_process_wait (h->server_proc); GNUNET_OS_process_destroy (h->server_proc); h->server_proc = NULL; GNUNET_DISK_pipe_close (h->server_stdout); h->server_stdout = NULL; h->server_stdout_handle = NULL; } if (NULL != h->server_stdout) { GNUNET_DISK_pipe_close (h->server_stdout); h->server_stdout = NULL; h->server_stdout_handle = NULL; } while (NULL != (lal = h->lal_head)) { GNUNET_CONTAINER_DLL_remove (h->lal_head, h->lal_tail, lal); if (NULL != h->address_callback) h->address_callback (h->callback_cls, GNUNET_NO, (const struct sockaddr *) &lal[1], lal->addrlen); GNUNET_free (lal); } for (i = 0; i < h->num_local_addrs; i++) GNUNET_free (h->local_addrs[i]); GNUNET_free_non_null (h->local_addrs); GNUNET_free_non_null (h->local_addrlens); GNUNET_free_non_null (h->external_address); GNUNET_free_non_null (h->internal_address); GNUNET_free (h); } /** * We learned about a peer (possibly behind NAT) so run the * gnunet-helper-nat-client to send dummy ICMP responses to cause * that peer to connect to us (connection reversal). * * @param h handle (used for configuration) * @param sa the address of the peer (IPv4-only) * @return #GNUNET_SYSERR on error, #GNUNET_NO if nat client is disabled, * #GNUNET_OK otherwise */ int GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h, const struct sockaddr_in *sa) { char inet4[INET_ADDRSTRLEN]; char port_as_string[6]; struct GNUNET_OS_Process *proc; char *binary; if (GNUNET_YES != h->enable_nat_client) return GNUNET_NO; /* not permitted / possible */ if (h->internal_address == NULL) { LOG (GNUNET_ERROR_TYPE_WARNING, "nat", _("Internal IP address not known, cannot use ICMP NAT traversal method\n")); return GNUNET_SYSERR; } GNUNET_assert (sa->sin_family == AF_INET); if (NULL == inet_ntop (AF_INET, &sa->sin_addr, inet4, INET_ADDRSTRLEN)) { GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "inet_ntop"); return GNUNET_SYSERR; } GNUNET_snprintf (port_as_string, sizeof (port_as_string), "%d", h->adv_port); LOG (GNUNET_ERROR_TYPE_DEBUG, _("Running gnunet-helper-nat-client %s %s %u\n"), h->internal_address, inet4, (unsigned int) h->adv_port); binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); proc = GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL, binary, "gnunet-helper-nat-client", h->internal_address, inet4, port_as_string, NULL); GNUNET_free (binary); if (NULL == proc) return GNUNET_SYSERR; /* we know that the gnunet-helper-nat-client will terminate virtually * instantly */ GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); return GNUNET_OK; } /** * Test if the given address is (currently) a plausible IP address for this peer. * * @param h the handle returned by register * @param addr IP address to test (IPv4 or IPv6) * @param addrlen number of bytes in @a addr * @return #GNUNET_YES if the address is plausible, * #GNUNET_NO if the address is not plausible, * #GNUNET_SYSERR if the address is malformed */ int GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h, const void *addr, socklen_t addrlen) { struct LocalAddressList *pos; const struct sockaddr_in *in4; const struct sockaddr_in6 *in6; if ((addrlen != sizeof (struct in_addr)) && (addrlen != sizeof (struct in6_addr))) { GNUNET_break (0); return GNUNET_SYSERR; } for (pos = h->lal_head; NULL != pos; pos = pos->next) { if (pos->addrlen == sizeof (struct sockaddr_in)) { in4 = (struct sockaddr_in *) &pos[1]; if ((addrlen == sizeof (struct in_addr)) && (0 == memcmp (&in4->sin_addr, addr, sizeof (struct in_addr)))) return GNUNET_YES; } else if (pos->addrlen == sizeof (struct sockaddr_in6)) { in6 = (struct sockaddr_in6 *) &pos[1]; if ((addrlen == sizeof (struct in6_addr)) && (0 == memcmp (&in6->sin6_addr, addr, sizeof (struct in6_addr)))) return GNUNET_YES; } else { GNUNET_assert (0); } } LOG (GNUNET_ERROR_TYPE_WARNING, "Asked to validate one of my addresses and validation failed!\n"); return GNUNET_NO; } /* end of nat.c */ gnunet-0.10.1/src/nat/gnunet-helper-nat-client.c0000644000175000017500000003144312252137227016350 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/nat/gnunet-helper-nat-client.c * @brief Tool to help bypass NATs using ICMP method; must run as root (SUID will do) * This code will work under GNU/Linux only. * @author Christian Grothoff * * This program will send ONE ICMP message using RAW sockets * to the IP address specified as the second argument. Since * it uses RAW sockets, it must be installed SUID or run as 'root'. * In order to keep the security risk of the resulting SUID binary * minimal, the program ONLY opens the RAW socket with root * privileges, then drops them and only then starts to process * command line arguments. The code also does not link against * any shared libraries (except libc) and is strictly minimal * (except for checking for errors). The following list of people * have reviewed this code and considered it safe since the last * modification (if you reviewed it, please have your name added * to the list): * * - Christian Grothoff * - Nathan Evans * - Benjamin Kuperman (22 Aug 2010) */ #if HAVE_CONFIG_H /* Just needed for HAVE_SOCKADDR_IN_SIN_LEN test macro! */ #include "gnunet_config.h" #else #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include /* The following constant is missing from FreeBSD 9.2 */ #ifndef ICMP_TIME_EXCEEDED #define ICMP_TIME_EXCEEDED 11 #endif /** * Must match IP given in the server. */ #define DUMMY_IP "192.0.2.86" #define NAT_TRAV_PORT 22225 /** * Must match packet ID used by gnunet-helper-nat-server.c */ #define PACKET_ID 256 /** * IPv4 header. */ struct ip_header { /** * Version (4 bits) + Internet header length (4 bits) */ uint8_t vers_ihl; /** * Type of service */ uint8_t tos; /** * Total length */ uint16_t pkt_len; /** * Identification */ uint16_t id; /** * Flags (3 bits) + Fragment offset (13 bits) */ uint16_t flags_frag_offset; /** * Time to live */ uint8_t ttl; /** * Protocol */ uint8_t proto; /** * Header checksum */ uint16_t checksum; /** * Source address */ uint32_t src_ip; /** * Destination address */ uint32_t dst_ip; }; /** * Format of ICMP packet. */ struct icmp_ttl_exceeded_header { uint8_t type; uint8_t code; uint16_t checksum; uint32_t unused; /* followed by original payload */ }; struct icmp_echo_header { uint8_t type; uint8_t code; uint16_t checksum; uint32_t reserved; }; /** * Beginning of UDP packet. */ struct udp_header { uint16_t src_port; uint16_t dst_port; uint16_t length; uint16_t crc; }; /** * Socket we use to send our fake ICMP replies. */ static int rawsock; /** * Target "dummy" address of the packet we pretend to respond to. */ static struct in_addr dummy; /** * Our "source" port. */ static uint16_t port; /** * CRC-16 for IP/ICMP headers. * * @param data what to calculate the CRC over * @param bytes number of bytes in data (must be multiple of 2) * @return the CRC 16. */ static uint16_t calc_checksum (const uint16_t * data, unsigned int bytes) { uint32_t sum; unsigned int i; sum = 0; for (i = 0; i < bytes / 2; i++) sum += data[i]; sum = (sum & 0xffff) + (sum >> 16); sum = htons (0xffff - sum); return sum; } /** * Send an ICMP message to the target. * * @param my_ip source address * @param other target address */ static void send_icmp_udp (const struct in_addr *my_ip, const struct in_addr *other) { char packet[sizeof (struct ip_header) * 2 + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct udp_header)]; struct ip_header ip_pkt; struct icmp_ttl_exceeded_header icmp_pkt; struct udp_header udp_pkt; struct sockaddr_in dst; size_t off; int err; /* ip header: send to (known) ip address */ off = 0; ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; #ifdef FREEBSD ip_pkt.pkt_len = sizeof (packet); /* Workaround PR kern/21737 */ #else ip_pkt.pkt_len = htons (sizeof (packet)); #endif ip_pkt.id = htons (PACKET_ID); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = 128; ip_pkt.proto = IPPROTO_ICMP; ip_pkt.checksum = 0; ip_pkt.src_ip = my_ip->s_addr; ip_pkt.dst_ip = other->s_addr; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (struct ip_header); icmp_pkt.type = ICMP_TIME_EXCEEDED; icmp_pkt.code = 0; icmp_pkt.checksum = 0; icmp_pkt.unused = 0; memcpy (&packet[off], &icmp_pkt, sizeof (struct icmp_ttl_exceeded_header)); off += sizeof (struct icmp_ttl_exceeded_header); /* ip header of the presumably 'lost' udp packet */ ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; ip_pkt.pkt_len = htons (sizeof (struct ip_header) + sizeof (struct udp_header)); ip_pkt.id = htons (0); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = 128; ip_pkt.proto = IPPROTO_UDP; ip_pkt.checksum = 0; ip_pkt.src_ip = other->s_addr; ip_pkt.dst_ip = dummy.s_addr; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (struct ip_header); /* build UDP header */ udp_pkt.src_port = htons (NAT_TRAV_PORT); udp_pkt.dst_port = htons (NAT_TRAV_PORT); udp_pkt.length = htons (port); udp_pkt.crc = 0; memcpy (&packet[off], &udp_pkt, sizeof (struct udp_header)); off += sizeof (struct udp_header); /* set ICMP checksum */ icmp_pkt.checksum = htons (calc_checksum ((uint16_t *) & packet[sizeof (struct ip_header)], sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct ip_header) + sizeof (struct udp_header))); memcpy (&packet[sizeof (struct ip_header)], &icmp_pkt, sizeof (struct icmp_ttl_exceeded_header)); memset (&dst, 0, sizeof (dst)); dst.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN dst.sin_len = sizeof (struct sockaddr_in); #endif dst.sin_addr = *other; err = sendto (rawsock, packet, sizeof (packet), 0, (struct sockaddr *) &dst, sizeof (dst)); if (err < 0) { fprintf (stderr, "sendto failed: %s\n", strerror (errno)); } else if (sizeof (packet) != (size_t) err) { fprintf (stderr, "Error: partial send of ICMP message with size %lu\n", (unsigned long) off); } } /** * Send an ICMP message to the target. * * @param my_ip source address * @param other target address */ static void send_icmp (const struct in_addr *my_ip, const struct in_addr *other) { struct ip_header ip_pkt; struct icmp_ttl_exceeded_header icmp_ttl; struct icmp_echo_header icmp_echo; struct sockaddr_in dst; char packet[sizeof (struct ip_header) * 2 + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct icmp_echo_header)]; size_t off; int err; /* ip header: send to (known) ip address */ off = 0; ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; #ifdef FREEBSD ip_pkt.pkt_len = sizeof (packet); /* Workaround PR kern/21737 */ #else ip_pkt.pkt_len = htons (sizeof (packet)); #endif ip_pkt.id = htons (PACKET_ID); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = IPDEFTTL; ip_pkt.proto = IPPROTO_ICMP; ip_pkt.checksum = 0; ip_pkt.src_ip = my_ip->s_addr; ip_pkt.dst_ip = other->s_addr; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off = sizeof (ip_pkt); /* icmp reply: time exceeded */ icmp_ttl.type = ICMP_TIME_EXCEEDED; icmp_ttl.code = 0; icmp_ttl.checksum = 0; icmp_ttl.unused = 0; memcpy (&packet[off], &icmp_ttl, sizeof (struct icmp_ttl_exceeded_header)); off += sizeof (struct icmp_ttl_exceeded_header); /* ip header of the presumably 'lost' udp packet */ ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; ip_pkt.pkt_len = htons (sizeof (struct ip_header) + sizeof (struct icmp_echo_header)); ip_pkt.id = htons (PACKET_ID); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ ip_pkt.proto = IPPROTO_ICMP; ip_pkt.src_ip = other->s_addr; ip_pkt.dst_ip = dummy.s_addr; ip_pkt.checksum = 0; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (struct ip_header); icmp_echo.type = ICMP_ECHO; icmp_echo.code = 0; icmp_echo.reserved = htonl (port); icmp_echo.checksum = 0; icmp_echo.checksum = htons (calc_checksum ((uint16_t *) & icmp_echo, sizeof (struct icmp_echo_header))); memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header)); /* no go back to calculate ICMP packet checksum */ off = sizeof (struct ip_header); icmp_ttl.checksum = htons (calc_checksum ((uint16_t *) & packet[off], sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct ip_header) + sizeof (struct icmp_echo_header))); memcpy (&packet[off], &icmp_ttl, sizeof (struct icmp_ttl_exceeded_header)); /* prepare for transmission */ memset (&dst, 0, sizeof (dst)); dst.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN dst.sin_len = sizeof (struct sockaddr_in); #endif dst.sin_addr = *other; err = sendto (rawsock, packet, sizeof (packet), 0, (struct sockaddr *) &dst, sizeof (dst)); if (err < 0) { fprintf (stderr, "sendto failed: %s\n", strerror (errno)); } else if (sizeof (packet) != (size_t) err) { fprintf (stderr, "Error: partial send of ICMP message\n"); } } int main (int argc, char *const *argv) { const int one = 1; struct in_addr external; struct in_addr target; uid_t uid; unsigned int p; int raw_eno; int global_ret; /* Create an ICMP raw socket for writing (only operation that requires root) */ rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); raw_eno = errno; /* for later error checking */ /* now drop root privileges */ uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); global_ret = 1; goto cleanup; } #else if (0 != (setuid (uid) | seteuid (uid))) { fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); global_ret = 2; goto cleanup; } #endif if (-1 == rawsock) { fprintf (stderr, "Error opening RAW socket: %s\n", strerror (raw_eno)); global_ret = 3; goto cleanup; } if (0 != setsockopt (rawsock, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one))) { fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); global_ret = 4; goto cleanup; } if (0 != setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one))) { fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); global_ret = 5; goto cleanup; } if (4 != argc) { fprintf (stderr, "This program must be started with our IP, the targets external IP, and our port as arguments.\n"); global_ret = 6; goto cleanup; } if ((1 != inet_pton (AF_INET, argv[1], &external)) || (1 != inet_pton (AF_INET, argv[2], &target))) { fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); global_ret = 7; goto cleanup; } if ((1 != sscanf (argv[3], "%u", &p)) || (0 == p) || (0xFFFF < p)) { fprintf (stderr, "Error parsing port value `%s'\n", argv[3]); global_ret = 8; goto cleanup; } port = (uint16_t) p; if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) { fprintf (stderr, "Internal error converting dummy IP to binary.\n"); global_ret = 9; goto cleanup; } send_icmp (&external, &target); send_icmp_udp (&external, &target); global_ret = 0; cleanup: if (-1 != rawsock) (void) close (rawsock); return global_ret; } /* end of gnunet-helper-nat-client.c */ gnunet-0.10.1/src/nat/Makefile.in0000644000175000017500000014054712320755624013451 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-nat-server$(EXEEXT) libexec_PROGRAMS = $(am__EXEEXT_1) check_PROGRAMS = test_nat$(EXEEXT) test_nat_mini$(EXEEXT) \ test_nat_test$(EXEEXT) subdir = src/nat DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgcfg_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetnat_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetnat_la_OBJECTS = nat.lo nat_auto.lo nat_test.lo \ nat_mini.lo libgnunetnat_la_OBJECTS = $(am_libgnunetnat_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetnat_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetnat_la_LDFLAGS) $(LDFLAGS) \ -o $@ @LINUX_FALSE@@MINGW_TRUE@@XFREEBSD_FALSE@am__EXEEXT_1 = gnunet-helper-nat-server$(EXEEXT) \ @LINUX_FALSE@@MINGW_TRUE@@XFREEBSD_FALSE@ gnunet-helper-nat-client$(EXEEXT) @LINUX_FALSE@@XFREEBSD_TRUE@am__EXEEXT_1 = \ @LINUX_FALSE@@XFREEBSD_TRUE@ gnunet-helper-nat-server$(EXEEXT) \ @LINUX_FALSE@@XFREEBSD_TRUE@ gnunet-helper-nat-client$(EXEEXT) @LINUX_TRUE@am__EXEEXT_1 = gnunet-helper-nat-server$(EXEEXT) \ @LINUX_TRUE@ gnunet-helper-nat-client$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am__gnunet_helper_nat_client_SOURCES_DIST = \ gnunet-helper-nat-client.c gnunet-helper-nat-client-windows.c @LINUX_FALSE@@MINGW_TRUE@@XFREEBSD_FALSE@am__objects_1 = gnunet-helper-nat-client-windows.$(OBJEXT) @LINUX_FALSE@@XFREEBSD_TRUE@am__objects_1 = gnunet-helper-nat-client.$(OBJEXT) @LINUX_TRUE@am__objects_1 = gnunet-helper-nat-client.$(OBJEXT) am_gnunet_helper_nat_client_OBJECTS = $(am__objects_1) gnunet_helper_nat_client_OBJECTS = \ $(am_gnunet_helper_nat_client_OBJECTS) gnunet_helper_nat_client_LDADD = $(LDADD) am__gnunet_helper_nat_server_SOURCES_DIST = \ gnunet-helper-nat-server.c gnunet-helper-nat-server-windows.c @LINUX_FALSE@@MINGW_TRUE@@XFREEBSD_FALSE@am__objects_2 = gnunet-helper-nat-server-windows.$(OBJEXT) @LINUX_FALSE@@XFREEBSD_TRUE@am__objects_2 = gnunet-helper-nat-server.$(OBJEXT) @LINUX_TRUE@am__objects_2 = gnunet-helper-nat-server.$(OBJEXT) am_gnunet_helper_nat_server_OBJECTS = $(am__objects_2) gnunet_helper_nat_server_OBJECTS = \ $(am_gnunet_helper_nat_server_OBJECTS) gnunet_helper_nat_server_LDADD = $(LDADD) am_gnunet_nat_server_OBJECTS = gnunet-nat-server.$(OBJEXT) gnunet_nat_server_OBJECTS = $(am_gnunet_nat_server_OBJECTS) am_test_nat_OBJECTS = test_nat.$(OBJEXT) test_nat_OBJECTS = $(am_test_nat_OBJECTS) test_nat_DEPENDENCIES = $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_nat_mini_OBJECTS = test_nat_mini.$(OBJEXT) test_nat_mini_OBJECTS = $(am_test_nat_mini_OBJECTS) test_nat_mini_DEPENDENCIES = $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_nat_test_OBJECTS = test_nat_test.$(OBJEXT) test_nat_test_OBJECTS = $(am_test_nat_test_OBJECTS) test_nat_test_DEPENDENCIES = $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetnat_la_SOURCES) \ $(gnunet_helper_nat_client_SOURCES) \ $(gnunet_helper_nat_server_SOURCES) \ $(gnunet_nat_server_SOURCES) $(test_nat_SOURCES) \ $(test_nat_mini_SOURCES) $(test_nat_test_SOURCES) DIST_SOURCES = $(libgnunetnat_la_SOURCES) \ $(am__gnunet_helper_nat_client_SOURCES_DIST) \ $(am__gnunet_helper_nat_server_SOURCES_DIST) \ $(gnunet_nat_server_SOURCES) $(test_nat_SOURCES) \ $(test_nat_mini_SOURCES) $(test_nat_test_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @LINUX_FALSE@@XFREEBSD_TRUE@NATBIN = gnunet-helper-nat-server gnunet-helper-nat-client @LINUX_TRUE@NATBIN = gnunet-helper-nat-server gnunet-helper-nat-client @MINGW_TRUE@NATBIN = gnunet-helper-nat-server gnunet-helper-nat-client @LINUX_FALSE@@XFREEBSD_TRUE@NATSERVER = gnunet-helper-nat-server.c @LINUX_TRUE@NATSERVER = gnunet-helper-nat-server.c @MINGW_TRUE@NATSERVER = gnunet-helper-nat-server-windows.c @LINUX_FALSE@@XFREEBSD_TRUE@NATCLIENT = gnunet-helper-nat-client.c @LINUX_TRUE@NATCLIENT = gnunet-helper-nat-client.c @MINGW_TRUE@NATCLIENT = gnunet-helper-nat-client-windows.c pkgcfgdir = $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ nat.conf gnunet_nat_server_SOURCES = \ gnunet-nat-server.c nat.h gnunet_nat_server_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_nat_server_DEPENDENCIES = \ libgnunetnat.la gnunet_helper_nat_server_SOURCES = \ $(NATSERVER) gnunet_helper_nat_client_SOURCES = \ $(NATCLIENT) @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage lib_LTLIBRARIES = libgnunetnat.la libgnunetnat_la_SOURCES = \ nat.c nat.h \ nat_auto.c \ nat_test.c \ nat_mini.c libgnunetnat_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) @EXT_LIBS@ libgnunetnat_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:1:1 @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_nat_SOURCES = \ test_nat.c test_nat_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la test_nat_mini_SOURCES = \ test_nat_mini.c test_nat_mini_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la test_nat_test_SOURCES = \ test_nat_test.c test_nat_test_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_nat_data.conf \ test_nat_test_data.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/nat/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/nat/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetnat.la: $(libgnunetnat_la_OBJECTS) $(libgnunetnat_la_DEPENDENCIES) $(EXTRA_libgnunetnat_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetnat_la_LINK) -rpath $(libdir) $(libgnunetnat_la_OBJECTS) $(libgnunetnat_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-helper-nat-client$(EXEEXT): $(gnunet_helper_nat_client_OBJECTS) $(gnunet_helper_nat_client_DEPENDENCIES) $(EXTRA_gnunet_helper_nat_client_DEPENDENCIES) @rm -f gnunet-helper-nat-client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_helper_nat_client_OBJECTS) $(gnunet_helper_nat_client_LDADD) $(LIBS) gnunet-helper-nat-server$(EXEEXT): $(gnunet_helper_nat_server_OBJECTS) $(gnunet_helper_nat_server_DEPENDENCIES) $(EXTRA_gnunet_helper_nat_server_DEPENDENCIES) @rm -f gnunet-helper-nat-server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_helper_nat_server_OBJECTS) $(gnunet_helper_nat_server_LDADD) $(LIBS) gnunet-nat-server$(EXEEXT): $(gnunet_nat_server_OBJECTS) $(gnunet_nat_server_DEPENDENCIES) $(EXTRA_gnunet_nat_server_DEPENDENCIES) @rm -f gnunet-nat-server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_nat_server_OBJECTS) $(gnunet_nat_server_LDADD) $(LIBS) test_nat$(EXEEXT): $(test_nat_OBJECTS) $(test_nat_DEPENDENCIES) $(EXTRA_test_nat_DEPENDENCIES) @rm -f test_nat$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_nat_OBJECTS) $(test_nat_LDADD) $(LIBS) test_nat_mini$(EXEEXT): $(test_nat_mini_OBJECTS) $(test_nat_mini_DEPENDENCIES) $(EXTRA_test_nat_mini_DEPENDENCIES) @rm -f test_nat_mini$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_nat_mini_OBJECTS) $(test_nat_mini_LDADD) $(LIBS) test_nat_test$(EXEEXT): $(test_nat_test_OBJECTS) $(test_nat_test_DEPENDENCIES) $(EXTRA_test_nat_test_DEPENDENCIES) @rm -f test_nat_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_nat_test_OBJECTS) $(test_nat_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-nat-client-windows.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-nat-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-nat-server-windows.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-nat-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-nat-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nat_auto.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nat_mini.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nat_test.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_nat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_nat_mini.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_nat_test.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_nat.log: test_nat$(EXEEXT) @p='test_nat$(EXEEXT)'; \ b='test_nat'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_nat_mini.log: test_nat_mini$(EXEEXT) @p='test_nat_mini$(EXEEXT)'; \ b='test_nat_mini'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_nat_test.log: test_nat_test$(EXEEXT) @p='test_nat_test$(EXEEXT)'; \ b='test_nat_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @LINUX_FALSE@@XFREEBSD_FALSE@install-exec-hook: clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_pkgcfgDATA \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS .MAKE: check-am install-am install-exec-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am \ install-dist_pkgcfgDATA install-dvi install-dvi-am \ install-exec install-exec-am install-exec-hook install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-dist_pkgcfgDATA \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS @LINUX_TRUE@install-exec-hook: @LINUX_TRUE@ $(top_srcdir)/src/nat/install-nat-helper.sh $(libexecdir) $(SUDO_BINARY) || true @LINUX_FALSE@@XFREEBSD_TRUE@install-exec-hook: @LINUX_FALSE@@XFREEBSD_TRUE@ $(top_srcdir)/src/nat/install-nat-helper.sh $(libexecdir) $(SUDO_BINARY) || true @LINUX_TRUE@install-exec-hook: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/nat/gnunet-helper-nat-server.c0000644000175000017500000003343412247442021016375 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/nat/gnunet-helper-nat-server.c * @brief Tool to help bypass NATs using ICMP method; must run as root (SUID will do) * This code will work under GNU/Linux only (or maybe BSDs, but never W32) * @author Christian Grothoff * * This program will send ONE ICMP message every 500 ms RAW sockets * to a DUMMY IP address and also listens for ICMP replies. Since * it uses RAW sockets, it must be installed SUID or run as 'root'. * In order to keep the security risk of the resulting SUID binary * minimal, the program ONLY opens the two RAW sockets with root * privileges, then drops them and only then starts to process * command line arguments. The code also does not link against * any shared libraries (except libc) and is strictly minimal * (except for checking for errors). The following list of people * have reviewed this code and considered it safe since the last * modification (if you reviewed it, please have your name added * to the list): * * - Christian Grothoff * - Nathan Evans * - Benjamin Kuperman (22 Aug 2010) * - Jacob Appelbaum (19 Dec 2011) */ #if HAVE_CONFIG_H /* Just needed for HAVE_SOCKADDR_IN_SIN_LEN test macro! */ #include "gnunet_config.h" #else #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* The following constant is missing from FreeBSD 9.2 */ #ifndef ICMP_TIME_EXCEEDED #define ICMP_TIME_EXCEEDED 11 #endif /** * Should we print some debug output? */ #define VERBOSE 0 /** * Must match packet ID used by gnunet-helper-nat-client.c */ #define PACKET_ID 256 /** * Must match IP given in the client. */ #define DUMMY_IP "192.0.2.86" /** * Port for UDP */ #define NAT_TRAV_PORT 22225 /** * How often do we send our ICMP messages to receive replies? */ #define ICMP_SEND_FREQUENCY_MS 500 /** * IPv4 header. */ struct ip_header { /** * Version (4 bits) + Internet header length (4 bits) */ uint8_t vers_ihl; /** * Type of service */ uint8_t tos; /** * Total length */ uint16_t pkt_len; /** * Identification */ uint16_t id; /** * Flags (3 bits) + Fragment offset (13 bits) */ uint16_t flags_frag_offset; /** * Time to live */ uint8_t ttl; /** * Protocol */ uint8_t proto; /** * Header checksum */ uint16_t checksum; /** * Source address */ uint32_t src_ip; /** * Destination address */ uint32_t dst_ip; }; /** * Format of ICMP packet. */ struct icmp_ttl_exceeded_header { uint8_t type; uint8_t code; uint16_t checksum; uint32_t unused; /* followed by original payload */ }; struct icmp_echo_header { uint8_t type; uint8_t code; uint16_t checksum; uint32_t reserved; }; /** * Beginning of UDP packet. */ struct udp_header { uint16_t src_port; uint16_t dst_port; uint16_t length; uint16_t crc; }; /** * Socket we use to receive "fake" ICMP replies. */ static int icmpsock; /** * Socket we use to send our ICMP requests. */ static int rawsock; /** * Socket we use to send our UDP requests. */ static int udpsock; /** * Target "dummy" address. */ static struct in_addr dummy; /** * CRC-16 for IP/ICMP headers. * * @param data what to calculate the CRC over * @param bytes number of bytes in data (must be multiple of 2) * @return the CRC 16. */ static uint16_t calc_checksum (const uint16_t * data, unsigned int bytes) { uint32_t sum; unsigned int i; sum = 0; for (i = 0; i < bytes / 2; i++) sum += data[i]; sum = (sum & 0xffff) + (sum >> 16); sum = htons (0xffff - sum); return sum; } /** * Send an ICMP message to the dummy IP. * * @param my_ip source address (our ip address) */ static void send_icmp_echo (const struct in_addr *my_ip) { char packet[sizeof (struct ip_header) + sizeof (struct icmp_echo_header)]; struct icmp_echo_header icmp_echo; struct ip_header ip_pkt; struct sockaddr_in dst; size_t off; int err; off = 0; ip_pkt.vers_ihl = 0x45; ip_pkt.tos = 0; ip_pkt.pkt_len = htons (sizeof (packet)); ip_pkt.id = htons (PACKET_ID); ip_pkt.flags_frag_offset = 0; ip_pkt.ttl = IPDEFTTL; ip_pkt.proto = IPPROTO_ICMP; ip_pkt.checksum = 0; ip_pkt.src_ip = my_ip->s_addr; ip_pkt.dst_ip = dummy.s_addr; ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); off += sizeof (struct ip_header); icmp_echo.type = ICMP_ECHO; icmp_echo.code = 0; icmp_echo.checksum = 0; icmp_echo.reserved = 0; icmp_echo.checksum = htons (calc_checksum ((uint16_t *) & icmp_echo, sizeof (struct icmp_echo_header))); memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header)); off += sizeof (struct icmp_echo_header); memset (&dst, 0, sizeof (dst)); dst.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN dst.sin_len = sizeof (struct sockaddr_in); #endif dst.sin_addr = dummy; err = sendto (rawsock, packet, off, 0, (struct sockaddr *) &dst, sizeof (dst)); if (err < 0) { #if VERBOSE fprintf (stderr, "sendto failed: %s\n", strerror (errno)); #endif } else if (sizeof (packet) != err) { fprintf (stderr, "Error: partial send of ICMP message\n"); } } /** * Send a UDP message to the dummy IP. */ static void send_udp () { struct sockaddr_in dst; ssize_t err; memset (&dst, 0, sizeof (dst)); dst.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN dst.sin_len = sizeof (struct sockaddr_in); #endif dst.sin_addr = dummy; dst.sin_port = htons (NAT_TRAV_PORT); err = sendto (udpsock, NULL, 0, 0, (struct sockaddr *) &dst, sizeof (dst)); if (err < 0) { #if VERBOSE fprintf (stderr, "sendto failed: %s\n", strerror (errno)); #endif } else if (0 != err) { fprintf (stderr, "Error: partial send of ICMP message\n"); } } /** * We've received an ICMP response. Process it. */ static void process_icmp_response () { char buf[65536]; ssize_t have; struct in_addr source_ip; struct ip_header ip_pkt; struct icmp_ttl_exceeded_header icmp_ttl; struct icmp_echo_header icmp_echo; struct udp_header udp_pkt; size_t off; uint16_t port; have = read (icmpsock, buf, sizeof (buf)); if (-1 == have) { fprintf (stderr, "Error reading raw socket: %s\n", strerror (errno)); return; } #if VERBOSE fprintf (stderr, "Received message of %u bytes\n", (unsigned int) have); #endif if (have < (ssize_t) (sizeof (struct ip_header) + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct ip_header))) { /* malformed */ return; } off = 0; memcpy (&ip_pkt, &buf[off], sizeof (struct ip_header)); off += sizeof (struct ip_header); memcpy (&icmp_ttl, &buf[off], sizeof (struct icmp_ttl_exceeded_header)); off += sizeof (struct icmp_ttl_exceeded_header); if ((ICMP_TIME_EXCEEDED != icmp_ttl.type) || (0 != icmp_ttl.code)) { /* different type than what we want */ return; } /* skip 2nd IP header */ memcpy (&ip_pkt, &buf[off], sizeof (struct ip_header)); off += sizeof (struct ip_header); switch (ip_pkt.proto) { case IPPROTO_ICMP: if (have != (sizeof (struct ip_header) * 2 + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct icmp_echo_header))) { /* malformed */ return; } /* grab ICMP ECHO content */ memcpy (&icmp_echo, &buf[off], sizeof (struct icmp_echo_header)); port = (uint16_t) ntohl (icmp_echo.reserved); break; case IPPROTO_UDP: if (have != (sizeof (struct ip_header) * 2 + sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct udp_header))) { /* malformed */ return; } /* grab UDP content */ memcpy (&udp_pkt, &buf[off], sizeof (struct udp_header)); port = ntohs (udp_pkt.length); break; default: /* different type than what we want */ return; } source_ip.s_addr = ip_pkt.src_ip; if (port == 0) fprintf (stdout, "%s\n", inet_ntop (AF_INET, &source_ip, buf, sizeof (buf))); else fprintf (stdout, "%s:%u\n", inet_ntop (AF_INET, &source_ip, buf, sizeof (buf)), (unsigned int) port); fflush (stdout); } /** * Fully initialize the raw socket. * * @return -1 on error, 0 on success */ static int setup_raw_socket () { const int one = 1; if (-1 == setsockopt (rawsock, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one))) { fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); return -1; } if (-1 == setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one))) { fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); return -1; } return 0; } /** * Create a UDP socket for writing. * * @param my_ip source address (our ip address) * @return -1 on error */ static int make_udp_socket (const struct in_addr *my_ip) { int ret; struct sockaddr_in addr; ret = socket (AF_INET, SOCK_DGRAM, 0); if (-1 == ret) { fprintf (stderr, "Error opening UDP socket: %s\n", strerror (errno)); return -1; } memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN addr.sin_len = sizeof (struct sockaddr_in); #endif addr.sin_addr = *my_ip; addr.sin_port = htons (NAT_TRAV_PORT); if (0 != bind (ret, &addr, sizeof (addr))) { fprintf (stderr, "Error binding UDP socket to port %u: %s\n", NAT_TRAV_PORT, strerror (errno)); (void) close (ret); return -1; } return ret; } int main (int argc, char *const *argv) { struct in_addr external; fd_set rs; struct timeval tv; uid_t uid; unsigned int alt; int icmp_eno; int raw_eno; int global_ret; /* Create an ICMP raw socket for reading (we'll check errors later) */ icmpsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); icmp_eno = errno; /* Create an (ICMP) raw socket for writing (we'll check errors later) */ rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); raw_eno = errno; udpsock = -1; /* drop root rights */ uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); global_ret = 1; goto error_exit; } #else if (0 != (setuid (uid) | seteuid (uid))) { fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); global_ret = 2; goto error_exit; } #endif /* Now that we run without root rights, we can do error checking... */ if (2 != argc) { fprintf (stderr, "This program must be started with our (internal NAT) IP as the only argument.\n"); global_ret = 3; goto error_exit; } if (1 != inet_pton (AF_INET, argv[1], &external)) { fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); global_ret = 4; goto error_exit; } if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) { fprintf (stderr, "Internal error converting dummy IP to binary.\n"); global_ret = 5; goto error_exit; } /* error checking icmpsock */ if (-1 == icmpsock) { fprintf (stderr, "Error opening RAW socket: %s\n", strerror (icmp_eno)); global_ret = 6; goto error_exit; } if (icmpsock >= FD_SETSIZE) { /* this could happen if we were started with a large number of already-open file descriptors... */ fprintf (stderr, "Socket number too large (%d > %u)\n", icmpsock, (unsigned int) FD_SETSIZE); global_ret = 7; goto error_exit; } /* error checking rawsock */ if (-1 == rawsock) { fprintf (stderr, "Error opening RAW socket: %s\n", strerror (raw_eno)); global_ret = 8; goto error_exit; } /* no need to check 'rawsock' against FD_SETSIZE as it is never used with 'select' */ if (0 != setup_raw_socket ()) { global_ret = 9; goto error_exit; } if (-1 == (udpsock = make_udp_socket (&external))) { global_ret = 10; goto error_exit; } alt = 0; while (1) { FD_ZERO (&rs); FD_SET (icmpsock, &rs); tv.tv_sec = 0; tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000; if (-1 == select (icmpsock + 1, &rs, NULL, NULL, &tv)) { if (errno == EINTR) continue; fprintf (stderr, "select failed: %s\n", strerror (errno)); break; } if (1 == getppid ()) /* Check the parent process id, if 1 the parent has died, so we should die too */ break; if (FD_ISSET (icmpsock, &rs)) process_icmp_response (); if (0 == (++alt % 2)) send_icmp_echo (&external); else send_udp (); } /* select failed (internal error or OS out of resources) */ global_ret = 11; error_exit: if (-1 != icmpsock) (void) close (icmpsock); if (-1 != rawsock) (void) close (rawsock); if (-1 != udpsock) (void) close (udpsock); return global_ret; } /* end of gnunet-helper-nat-server.c */ gnunet-0.10.1/src/nat/test_nat.c0000644000175000017500000001205112225777501013357 00000000000000/* This file is part of GNUnet. (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * Testcase for port redirection and public IP address retrieval. * This test never fails, because there need to be a NAT box set up for that. * So we only get IP address and open the 2086 port using any NAT traversal * method available, wait for 30s, close ports and return. * Have a look at the logs and use NMAP to check that it works with your box. * * @file nat/test_nat.c * @brief Testcase for NAT library * @author Milan Bouchet-Valat * @author Christian Grothoff * * TODO: actually use ARM to start resolver service to make DNS work! */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_program_lib.h" #include "gnunet_scheduler_lib.h" #include "gnunet_nat_lib.h" /** * Time to wait before stopping NAT, in seconds */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Function called on each address that the NAT service * believes to be valid for the transport. */ static void addr_callback (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address changed: %s `%s' (%u bytes)\n", add_remove == GNUNET_YES ? "added" : "removed", GNUNET_a2s (addr, addrlen), (unsigned int) addrlen); } /** * Function that terminates the test. */ static void stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_Handle *nat = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping NAT and quitting...\n"); GNUNET_NAT_unregister (nat); } struct addr_cls { struct sockaddr *addr; socklen_t addrlen; }; /** * Return the address of the default interface, * or any interface with a valid address if the default is not valid * * @param cls the 'struct addr_cls' * @param name name of the interface * @param isDefault do we think this may be our default interface * @param addr address of the interface * @param addrlen number of bytes in addr * @return GNUNET_OK to continue iterating */ static int process_if (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen) { struct addr_cls *data = cls; if (addr == NULL) return GNUNET_OK; GNUNET_free_non_null (data->addr); data->addr = GNUNET_malloc (addrlen); memcpy (data->addr, addr, addrlen); data->addrlen = addrlen; if (isDefault) return GNUNET_SYSERR; return GNUNET_OK; } /** * Main function run with scheduler. */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAT_Handle *nat; struct addr_cls data; struct sockaddr *addr; data.addr = NULL; GNUNET_OS_network_interfaces_list (process_if, &data); if (NULL == data.addr) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not find a valid interface address!\n"); exit (GNUNET_SYSERR); } addr = data.addr; GNUNET_assert (addr->sa_family == AF_INET || addr->sa_family == AF_INET6); if (addr->sa_family == AF_INET) ((struct sockaddr_in *) addr)->sin_port = htons (2086); else ((struct sockaddr_in6 *) addr)->sin6_port = htons (2086); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting NAT redirection from address %s...\n", GNUNET_a2s (addr, data.addrlen)); nat = GNUNET_NAT_register (cfg, GNUNET_YES /* tcp */ , 2086, 1, (const struct sockaddr **) &addr, &data.addrlen, &addr_callback, NULL, NULL); GNUNET_free (addr); GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, nat); } int main (int argc, char *const argv[]) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; char *const argv_prog[] = { "test-nat", "-c", "test_nat_data.conf", NULL }; GNUNET_log_setup ("test-nat", "WARNING", NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testing NAT library, timeout set to %d seconds\n", TIMEOUT); GNUNET_PROGRAM_run (3, argv_prog, "test-nat", "nohelp", options, &run, NULL); return 0; } /* end of test_nat.c */ gnunet-0.10.1/src/nat/test_nat_test_data.conf0000644000175000017500000000232712225230043016100 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/nat-test # GNUNET_TEST_HOME = /var/lib/gnunet/ # configuration file is assumed to be the default, # which is what we want by default... [gnunet-nat-server] HOSTNAME = localhost PORT = 12345 [nat] # Are we behind NAT? BEHIND_NAT = NO # Is the NAT hole-punched? PUNCHED_NAT = YES # Disable UPNP by default until it gets cleaner! ENABLE_UPNP = NO # Use addresses from the local network interfaces (inluding loopback, but also others) USE_LOCALADDR = YES RETURN_LOCAL_ADDRESSES = YES # External IP address of the NAT box (if known); IPv4 dotted-decimal ONLY at this time (should allow DynDNS!) # normal interface IP address for non-NATed peers; # possibly auto-detected (using UPnP) if possible if not specified # EXTERNAL_ADDRESS = # Should we use ICMP-based NAT traversal to try connect to NATed peers # or, if we are behind NAT, to allow connections to us? ENABLE_ICMP_CLIENT = NO ENABLE_ICMP_SERVER = NO # IP address of the interface connected to the NAT box; IPv4 dotted-decimal ONLY; # normal interface IP address for non-NATed peers; # likely auto-detected (via interface list) if not specified (!) INTERNAL_ADDRESS = 127.0.0.1 # Disable IPv6 support DISABLEV6 = YES [nse] AUTOSTART = NO gnunet-0.10.1/src/nat/test_nat_test.c0000644000175000017500000000677312301361473014424 00000000000000/* This file is part of GNUnet. (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * Testcase for the NAT testing code. * * @file nat/test_nat_test.c * @brief Testcase for NAT testing functions * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_nat_lib.h" /** * Time to wait before stopping NAT test, in seconds */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) static int ret = 1; static struct GNUNET_NAT_Test *tst; static GNUNET_SCHEDULER_TaskIdentifier end; static void end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_NAT_test_stop (tst); } static void report_success (void *cls, int success, const char *emsg) { GNUNET_assert (GNUNET_OK == success); ret = 0; GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&end_test, NULL); } /** * Main function run with scheduler. */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { tst = GNUNET_NAT_test_start (cfg, GNUNET_YES, 1285, 1285, &report_success, NULL); if (NULL == tst) return; end = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_test, NULL); } int main (int argc, char *const argv[]) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; struct GNUNET_OS_Process *gns; int nat_res; char *const argv_prog[] = { "test-nat-test", "-c", "test_nat_test_data.conf", NULL }; GNUNET_log_setup ("test-nat-test", "WARNING", NULL); nat_res = GNUNET_OS_check_helper_binary ("gnunet-nat-server", GNUNET_NO, NULL); if (GNUNET_SYSERR == nat_res) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Cannot run NAT test: `%s' file not found\n", "gnunet-nat-server"); return 0; } gns = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, "gnunet-nat-server", "gnunet-nat-server", "-c", "test_nat_test_data.conf", "12345", NULL); GNUNET_assert (NULL != gns); GNUNET_PROGRAM_run (3, argv_prog, "test-nat-test", "nohelp", options, &run, NULL); GNUNET_break (0 == GNUNET_OS_process_kill (gns, GNUNET_TERM_SIG)); GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (gns)); GNUNET_OS_process_destroy (gns); if (0 != ret) fprintf (stderr, "NAT test failed to report success\n"); return ret; } /* end of test_nat_test.c */ gnunet-0.10.1/src/nat/Makefile.am0000644000175000017500000000466412320755176013441 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols NATBIN = gnunet-helper-nat-server gnunet-helper-nat-client NATSERVER = gnunet-helper-nat-server-windows.c NATCLIENT = gnunet-helper-nat-client-windows.c endif libexecdir= $(pkglibdir)/libexec/ pkgcfgdir= $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ nat.conf if LINUX NATBIN = gnunet-helper-nat-server gnunet-helper-nat-client NATSERVER = gnunet-helper-nat-server.c NATCLIENT = gnunet-helper-nat-client.c install-exec-hook: $(top_srcdir)/src/nat/install-nat-helper.sh $(libexecdir) $(SUDO_BINARY) || true else if XFREEBSD NATBIN = gnunet-helper-nat-server gnunet-helper-nat-client NATSERVER = gnunet-helper-nat-server.c NATCLIENT = gnunet-helper-nat-client.c install-exec-hook: $(top_srcdir)/src/nat/install-nat-helper.sh $(libexecdir) $(SUDO_BINARY) || true endif else install-exec-hook: endif bin_PROGRAMS = \ gnunet-nat-server libexec_PROGRAMS = \ $(NATBIN) gnunet_nat_server_SOURCES = \ gnunet-nat-server.c nat.h gnunet_nat_server_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_nat_server_DEPENDENCIES = \ libgnunetnat.la gnunet_helper_nat_server_SOURCES = \ $(NATSERVER) gnunet_helper_nat_client_SOURCES = \ $(NATCLIENT) if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif lib_LTLIBRARIES = libgnunetnat.la libgnunetnat_la_SOURCES = \ nat.c nat.h \ nat_auto.c \ nat_test.c \ nat_mini.c libgnunetnat_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) @EXT_LIBS@ libgnunetnat_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:1:1 check_PROGRAMS = \ test_nat \ test_nat_mini \ test_nat_test if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_nat_SOURCES = \ test_nat.c test_nat_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la test_nat_mini_SOURCES = \ test_nat_mini.c test_nat_mini_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la test_nat_test_SOURCES = \ test_nat_test.c test_nat_test_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_nat_data.conf \ test_nat_test_data.conf gnunet-0.10.1/src/nat/gnunet-nat-server.c0000644000175000017500000002114212255010512015104 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/nat/gnunet-nat-server.c * @brief Daemon to run on 'gnunet.org' to help test NAT traversal code * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_nat_lib.h" #include "gnunet_protocols.h" #include "nat.h" /** * Our server. */ static struct GNUNET_SERVER_Handle *server; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Try contacting the peer using autonomous * NAT traveral method. * * @param dst_ipv4 IPv4 address to send the fake ICMP message * @param dport destination port to include in ICMP message * @param is_tcp mark for TCP (GNUNET_YES) or UDP (GNUNET_NO) */ static void try_anat (uint32_t dst_ipv4, uint16_t dport, int is_tcp) { struct GNUNET_NAT_Handle *h; struct sockaddr_in sa; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking for connection reversal with %x and code %u\n", (unsigned int) dst_ipv4, (unsigned int) dport); h = GNUNET_NAT_register (cfg, is_tcp, dport, 0, NULL, NULL, NULL, NULL, NULL); memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_addr.s_addr = dst_ipv4; GNUNET_NAT_run_client (h, &sa); GNUNET_NAT_unregister (h); } /** * Closure for 'tcp_send'. */ struct TcpContext { /** * TCP socket. */ struct GNUNET_NETWORK_Handle *s; /** * Data to transmit. */ uint16_t data; }; /** * Task called by the scheduler once we can do the TCP send * (or once we failed to connect...). * * @param cls the 'struct TcpContext' * @param tc scheduler context */ static void tcp_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TcpContext *ctx = cls; if ((NULL != tc->write_ready) && (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s))) { if (-1 == GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data))) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send"); } GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR); } GNUNET_NETWORK_socket_close (ctx->s); GNUNET_free (ctx); } /** * Try to send 'data' to the * IP 'dst_ipv4' at port 'dport' via TCP. * * @param dst_ipv4 target IP * @param dport target port * @param data data to send */ static void try_send_tcp (uint32_t dst_ipv4, uint16_t dport, uint16_t data) { struct GNUNET_NETWORK_Handle *s; struct sockaddr_in sa; struct TcpContext *ctx; s = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); if (NULL == s) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket"); return; } memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_addr.s_addr = dst_ipv4; sa.sin_port = htons (dport); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending TCP message to `%s'\n", GNUNET_a2s ((struct sockaddr *) &sa, sizeof (sa))); if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, (const struct sockaddr *) &sa, sizeof (sa))) && (errno != EINPROGRESS)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect"); GNUNET_NETWORK_socket_close (s); return; } ctx = GNUNET_new (struct TcpContext); ctx->s = s; ctx->data = data; GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS, s, &tcp_send, ctx); } /** * Try to send 'data' to the * IP 'dst_ipv4' at port 'dport' via UDP. * * @param dst_ipv4 target IP * @param dport target port * @param data data to send */ static void try_send_udp (uint32_t dst_ipv4, uint16_t dport, uint16_t data) { struct GNUNET_NETWORK_Handle *s; struct sockaddr_in sa; s = GNUNET_NETWORK_socket_create (AF_INET, SOCK_DGRAM, 0); if (NULL == s) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket"); return; } memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_addr.s_addr = dst_ipv4; sa.sin_port = htons (dport); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending UDP packet to `%s'\n", GNUNET_a2s ((struct sockaddr *) &sa, sizeof (sa))); if (-1 == GNUNET_NETWORK_socket_sendto (s, &data, sizeof (data), (const struct sockaddr *) &sa, sizeof (sa))) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto"); GNUNET_NETWORK_socket_close (s); } /** * We've received a request to probe a NAT * traversal. Do it. * * @param cls unused * @param client handle to client (we always close) * @param msg message with details about what to test */ static void test (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct GNUNET_NAT_TestMessage *tm; uint16_t dport; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received test request\n"); tm = (const struct GNUNET_NAT_TestMessage *) msg; dport = ntohs (tm->dport); if (0 == dport) try_anat (tm->dst_ipv4, ntohs (tm->data), (int) ntohl (tm->is_tcp)); else if (GNUNET_YES == ntohl (tm->is_tcp)) try_send_tcp (tm->dst_ipv4, dport, tm->data); else try_send_udp (tm->dst_ipv4, dport, tm->data); GNUNET_SERVER_receive_done (client, GNUNET_NO); } /** * Task run during shutdown. * * @param cls unused * @param tc scheduler context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SERVER_destroy (server); server = NULL; } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST, sizeof (struct GNUNET_NAT_TestMessage)}, {NULL, NULL, 0, 0} }; unsigned int port; struct sockaddr_in in4; struct sockaddr_in6 in6; socklen_t slen[] = { sizeof (in4), sizeof (in6), 0 }; struct sockaddr *sa[] = { (struct sockaddr *) &in4, (struct sockaddr *) &in6, NULL }; cfg = c; if ((args[0] == NULL) || (1 != SSCANF (args[0], "%u", &port)) || (0 == port) || (65536 <= port)) { FPRINTF (stderr, _ ("Please pass valid port number as the first argument! (got `%s')\n"), args[0]); return; } memset (&in4, 0, sizeof (in4)); memset (&in6, 0, sizeof (in6)); in4.sin_family = AF_INET; in4.sin_port = htons ((uint16_t) port); in6.sin6_family = AF_INET6; in6.sin6_port = htons ((uint16_t) port); #if HAVE_SOCKADDR_IN_SIN_LEN in4.sin_len = sizeof (in4); in6.sin6_len = sizeof (in6); #endif server = GNUNET_SERVER_create (NULL, NULL, (struct sockaddr * const *) sa, slen, GNUNET_TIME_UNIT_SECONDS, GNUNET_YES); GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * Main function of gnunet-nat-server. * * @param argc number of command-line arguments * @param argv command line * @return 0 on success, -1 on error */ int main (int argc, char *const argv[]) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "gnunet-nat-server [options] PORT", _("GNUnet NAT traversal test helper daemon"), options, &run, NULL)) { GNUNET_free ((void*) argv); return 1; } GNUNET_free ((void*) argv); return 0; } /* end of gnunet-nat-server.c */ gnunet-0.10.1/src/nat/nat_test.c0000644000175000017500000003167612262754601013372 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nat/nat_test.c * @brief functions to test if the NAT configuration is successful at achieving NAT traversal (with the help of a gnunet-nat-server) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_nat_lib.h" #include "nat.h" #define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) #define NAT_SERVER_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) /** * Entry we keep for each incoming connection. */ struct NatActivity { /** * This is a doubly-linked list. */ struct NatActivity *next; /** * This is a doubly-linked list. */ struct NatActivity *prev; /** * Socket of the incoming connection. */ struct GNUNET_NETWORK_Handle *sock; /** * Handle of the master context. */ struct GNUNET_NAT_Test *h; /** * Task reading from the incoming connection. */ GNUNET_SCHEDULER_TaskIdentifier rtask; }; /** * Entry we keep for each connection to the gnunet-nat-service. */ struct ClientActivity { /** * This is a doubly-linked list. */ struct ClientActivity *next; /** * This is a doubly-linked list. */ struct ClientActivity *prev; /** * Socket of the incoming connection. */ struct GNUNET_CLIENT_Connection *client; }; /** * Handle to a NAT test. */ struct GNUNET_NAT_Test { /** * Configuration used */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Function to call with success report */ GNUNET_NAT_TestCallback report; /** * Closure for @e report. */ void *report_cls; /** * Handle to NAT traversal in use */ struct GNUNET_NAT_Handle *nat; /** * Handle to listen socket, or NULL */ struct GNUNET_NETWORK_Handle *lsock; /** * Head of list of nat activities. */ struct NatActivity *na_head; /** * Tail of list of nat activities. */ struct NatActivity *na_tail; /** * Head of list of client activities. */ struct ClientActivity *ca_head; /** * Tail of list of client activities. */ struct ClientActivity *ca_tail; /** * Identity of task for the listen socket (if any) */ GNUNET_SCHEDULER_TaskIdentifier ltask; /** * GNUNET_YES if we're testing TCP */ int is_tcp; /** * Data that should be transmitted or source-port. */ uint16_t data; /** * Advertised port to the other peer. */ uint16_t adv_port; }; /** * Function called from #GNUNET_NAT_register whenever someone asks us * to do connection reversal. * * @param cls closure, our `struct GNUNET_NAT_Handle` * @param addr public IP address of the other peer * @param addrlen actual lenght of the address */ static void reversal_cb (void *cls, const struct sockaddr *addr, socklen_t addrlen) { struct GNUNET_NAT_Test *h = cls; const struct sockaddr_in *sa; if (sizeof (struct sockaddr_in) != addrlen) return; sa = (const struct sockaddr_in *) addr; if (h->data != sa->sin_port) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Received connection reversal request for wrong port\n"); return; /* wrong port */ } /* report success */ h->report (h->report_cls, GNUNET_OK, NULL); } /** * Activity on our incoming socket. Read data from the * incoming connection. * * @param cls the `struct GNUNET_NAT_Test` * @param tc scheduler context */ static void do_udp_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_Test *tst = cls; uint16_t data; tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, tst->lsock, &do_udp_read, tst); if ((NULL != tc->write_ready) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, tst->lsock)) && (sizeof (data) == GNUNET_NETWORK_socket_recv (tst->lsock, &data, sizeof (data)))) { if (data == tst->data) tst->report (tst->report_cls, GNUNET_OK, NULL); else LOG (GNUNET_ERROR_TYPE_DEBUG, "Received data mismatches expected value\n"); } else LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to receive data from inbound connection\n"); } /** * Activity on our incoming socket. Read data from the * incoming connection. * * @param cls the `struct NatActivity` * @param tc scheduler context */ static void do_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct NatActivity *na = cls; struct GNUNET_NAT_Test *tst; uint16_t data; na->rtask = GNUNET_SCHEDULER_NO_TASK; tst = na->h; GNUNET_CONTAINER_DLL_remove (tst->na_head, tst->na_tail, na); if ((NULL != tc->write_ready) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, na->sock)) && (sizeof (data) == GNUNET_NETWORK_socket_recv (na->sock, &data, sizeof (data)))) { if (data == tst->data) tst->report (tst->report_cls, GNUNET_OK, NULL); else LOG (GNUNET_ERROR_TYPE_DEBUG, "Received data does not match expected value\n"); } else LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to receive data from inbound connection\n"); GNUNET_NETWORK_socket_close (na->sock); GNUNET_free (na); } /** * Activity on our listen socket. Accept the * incoming connection. * * @param cls the `struct GNUNET_NAT_Test` * @param tc scheduler context */ static void do_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_Test *tst = cls; struct GNUNET_NETWORK_Handle *s; struct NatActivity *wl; tst->ltask = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; tst->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, tst->lsock, &do_accept, tst); s = GNUNET_NETWORK_socket_accept (tst->lsock, NULL, NULL); if (NULL == s) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "accept"); return; /* odd error */ } LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an inbound connection, waiting for data\n"); wl = GNUNET_new (struct NatActivity); wl->sock = s; wl->h = tst; wl->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, wl->sock, &do_read, wl); GNUNET_CONTAINER_DLL_insert (tst->na_head, tst->na_tail, wl); } /** * Address-callback, used to send message to gnunet-nat-server. * * @param cls closure * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean * the previous (now invalid) one * @param addr either the previous or the new public IP address * @param addrlen actual length of the @a addr */ static void addr_cb (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { struct GNUNET_NAT_Test *h = cls; struct ClientActivity *ca; struct GNUNET_CLIENT_Connection *client; struct GNUNET_NAT_TestMessage msg; const struct sockaddr_in *sa; if (GNUNET_YES != add_remove) return; if (addrlen != sizeof (struct sockaddr_in)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "NAT test ignores IPv6 address `%s' returned from NAT library\n", GNUNET_a2s (addr, addrlen)); return; /* ignore IPv6 here */ } LOG (GNUNET_ERROR_TYPE_DEBUG, "Asking gnunet-nat-server to connect to `%s'\n", GNUNET_a2s (addr, addrlen)); sa = (const struct sockaddr_in *) addr; msg.header.size = htons (sizeof (struct GNUNET_NAT_TestMessage)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_NAT_TEST); msg.dst_ipv4 = sa->sin_addr.s_addr; msg.dport = sa->sin_port; msg.data = h->data; msg.is_tcp = htonl ((uint32_t) h->is_tcp); client = GNUNET_CLIENT_connect ("gnunet-nat-server", h->cfg); if (NULL == client) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to `gnunet-nat-server'\n")); return; } ca = GNUNET_new (struct ClientActivity); ca->client = client; GNUNET_CONTAINER_DLL_insert (h->ca_head, h->ca_tail, ca); GNUNET_break (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (client, &msg.header, NAT_SERVER_TIMEOUT, GNUNET_YES, NULL, NULL)); } /** * Start testing if NAT traversal works using the * given configuration (IPv4-only). * * @param cfg configuration for the NAT traversal * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP * @param bnd_port port to bind to, 0 for connection reversal * @param adv_port externally advertised port to use * @param report function to call with the result of the test * @param report_cls closure for @a report * @return handle to cancel NAT test */ struct GNUNET_NAT_Test * GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, uint16_t bnd_port, uint16_t adv_port, GNUNET_NAT_TestCallback report, void *report_cls) { struct GNUNET_NAT_Test *ret; struct sockaddr_in sa; const struct sockaddr *addrs[] = { (const struct sockaddr *) &sa }; const socklen_t addrlens[] = { sizeof (sa) }; memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_port = htons (bnd_port); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif ret = GNUNET_new (struct GNUNET_NAT_Test); ret->cfg = cfg; ret->is_tcp = is_tcp; ret->data = bnd_port; ret->adv_port = adv_port; ret->report = report; ret->report_cls = report_cls; if (0 == bnd_port) { ret->nat = GNUNET_NAT_register (cfg, is_tcp, 0, 0, NULL, NULL, &addr_cb, &reversal_cb, ret); } else { ret->lsock = GNUNET_NETWORK_socket_create (AF_INET, (is_tcp == GNUNET_YES) ? SOCK_STREAM : SOCK_DGRAM, 0); if ((ret->lsock == NULL) || (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret->lsock, (const struct sockaddr *) &sa, sizeof (sa)))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to create listen socket bound to `%s' for NAT test: %s\n"), GNUNET_a2s ((const struct sockaddr *) &sa, sizeof (sa)), STRERROR (errno)); if (NULL != ret->lsock) GNUNET_NETWORK_socket_close (ret->lsock); GNUNET_free (ret); return NULL; } if (GNUNET_YES == is_tcp) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_listen (ret->lsock, 5)); ret->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, ret->lsock, &do_accept, ret); } else { ret->ltask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, ret->lsock, &do_udp_read, ret); } LOG (GNUNET_ERROR_TYPE_DEBUG, "NAT test listens on port %u (%s)\n", bnd_port, (GNUNET_YES == is_tcp) ? "tcp" : "udp"); ret->nat = GNUNET_NAT_register (cfg, is_tcp, adv_port, 1, addrs, addrlens, &addr_cb, NULL, ret); } return ret; } /** * Stop an active NAT test. * * @param tst test to stop. */ void GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst) { struct NatActivity *pos; struct ClientActivity *cpos; LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping NAT test\n"); while (NULL != (cpos = tst->ca_head)) { GNUNET_CONTAINER_DLL_remove (tst->ca_head, tst->ca_tail, cpos); GNUNET_CLIENT_disconnect (cpos->client); GNUNET_free (cpos); } while (NULL != (pos = tst->na_head)) { GNUNET_CONTAINER_DLL_remove (tst->na_head, tst->na_tail, pos); GNUNET_SCHEDULER_cancel (pos->rtask); GNUNET_NETWORK_socket_close (pos->sock); GNUNET_free (pos); } if (GNUNET_SCHEDULER_NO_TASK != tst->ltask) GNUNET_SCHEDULER_cancel (tst->ltask); if (NULL != tst->lsock) GNUNET_NETWORK_socket_close (tst->lsock); GNUNET_NAT_unregister (tst->nat); GNUNET_free (tst); } /* end of nat_test.c */ gnunet-0.10.1/src/nat/nat_auto.c0000644000175000017500000003375212262754601013360 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nat/nat_auto.c * @brief functions for auto-configuration of the network * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #include "gnunet_nat_lib.h" #include "nat.h" #define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__) /** * How long do we wait for the NAT test to report success? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) /** * Phases of the auto configuration. */ enum AutoPhase { /** * Initial start value. */ AUTO_INIT = 0, /** * Test if we are online. */ AUTO_ONLINE, /** * Test our external IP. */ AUTO_EXTERNAL_IP, /** * Test our internal IP. */ AUTO_LOCAL_IP, /** * Test if NAT was punched. */ AUTO_NAT_PUNCHED, /** * Test if UPnP is working. */ AUTO_UPNPC, /** * Test if ICMP server works. */ AUTO_ICMP_SERVER, /** * Test if ICMP client works. */ AUTO_ICMP_CLIENT, /** * Last phase, we're done. */ AUTO_DONE }; /** * Handle to auto-configuration in progress. */ struct GNUNET_NAT_AutoHandle { /** * Handle to the active NAT test. */ struct GNUNET_NAT_Test *tst; /** * Function to call when done. */ GNUNET_NAT_AutoResultCallback fin_cb; /** * Closure for @e fin_cb. */ void *fin_cb_cls; /** * Handle for active 'GNUNET_NAT_mini_get_external_ipv4'-operation. */ struct GNUNET_NAT_ExternalHandle *eh; /** * Current configuration (with updates from previous phases) */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * Original configuration (used to calculate differences) */ struct GNUNET_CONFIGURATION_Handle *initial_cfg; /** * Task identifier for the timeout. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Where are we in the test? */ enum AutoPhase phase; /** * Do we have IPv6? */ int have_v6; }; /** * Run the next phase of the auto test. * * @param ah auto test handle */ static void next_phase (struct GNUNET_NAT_AutoHandle *ah); /** * Function called if NAT failed to confirm success. * Clean up and update GUI (with failure). * * @param cls closure with setup context * @param tc scheduler callback */ static void fail_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_AutoHandle *ah = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("NAT traversal with ICMP Server timed out.\n")); GNUNET_assert (NULL != ah->tst); ah->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_NAT_test_stop (ah->tst); ah->tst = NULL; GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_ICMP_SERVER", "NO"); next_phase (ah); } /** * Function called by NAT on success. * Clean up and update GUI (with success). * * @param cls the auto handle * @param success currently always #GNUNET_OK * @param emsg NULL on success, otherwise an error message */ static void result_callback (void *cls, int success, const char *emsg) { struct GNUNET_NAT_AutoHandle *ah = cls; GNUNET_SCHEDULER_cancel (ah->task); ah->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_NAT_test_stop (ah->tst); ah->tst = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, success ? _("NAT traversal with ICMP Server succeeded.\n") : _("NAT traversal with ICMP Server failed.\n")); GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_ICMP_SERVER", success ? "YES": "NO"); next_phase (ah); } /** * Main function for the connection reversal test. * * @param cls the `struct GNUNET_NAT_AutoHandle` * @param tc scheduler context */ static void reversal_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAT_AutoHandle *ah = cls; ah->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Testing connection reversal with ICMP server.\n")); GNUNET_RESOLVER_connect (ah->cfg); ah->tst = GNUNET_NAT_test_start (ah->cfg, GNUNET_YES, 0, 0, &result_callback, ah); if (NULL == ah->tst) { next_phase (ah); return; } ah->task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &fail_timeout, ah); } /** * Test if we are online at all. * * @param ah auto setup context */ static void test_online (struct GNUNET_NAT_AutoHandle *ah) { // FIXME: not implemented next_phase (ah); } /** * Set our external IPv4 address. * * @param cls closure with our setup context * @param addr the address, NULL on errors * @param emsg NULL on success, otherwise an error message */ static void set_external_ipv4 (void *cls, const struct in_addr *addr, const char *emsg) { struct GNUNET_NAT_AutoHandle *ah = cls; char buf[INET_ADDRSTRLEN]; ah->eh = NULL; if (NULL == addr) { next_phase (ah); return; } /* enable 'behind nat' */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Detected external IP `%s'\n"), inet_ntop (AF_INET, addr, buf, sizeof (buf))); GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "BEHIND_NAT", "YES"); /* set external IP address */ if (NULL == inet_ntop (AF_INET, addr, buf, sizeof (buf))) { GNUNET_break (0); next_phase (ah); return; } GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS", buf); next_phase (ah); } /** * Determine our external IPv4 address. * * @param ah auto setup context */ static void test_external_ip (struct GNUNET_NAT_AutoHandle *ah) { // FIXME: CPS? /* try to detect external IP */ ah->eh = GNUNET_NAT_mini_get_external_ipv4 (TIMEOUT, &set_external_ipv4, ah); } /** * Process list of local IP addresses. Find and set the * one of the default interface. * * @param cls our `struct GNUNET_NAT_AutoHandle` * @param name name of the interface (can be NULL for unknown) * @param isDefault is this presumably the default interface * @param addr address of this interface (can be NULL for unknown or unassigned) * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) * @param netmask the network mask (can be NULL for unknown or unassigned)) * @param addrlen length of the @a addr and @a broadcast_addr * @return GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort */ static int nipo (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen) { struct GNUNET_NAT_AutoHandle *ah = cls; const struct sockaddr_in *in; char buf[INET_ADDRSTRLEN]; if (!isDefault) return GNUNET_OK; if ( (sizeof (struct sockaddr_in6) == addrlen) && (0 != memcmp (&in6addr_loopback, &((const struct sockaddr_in6 *) addr)->sin6_addr, sizeof (struct in6_addr))) && (! IN6_IS_ADDR_LINKLOCAL(&((const struct sockaddr_in6 *) addr)->sin6_addr)) ) { ah->have_v6 = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("This system has a global IPv6 address, setting IPv6 to supported.\n")); return GNUNET_OK; } if (addrlen != sizeof (struct sockaddr_in)) return GNUNET_OK; in = (const struct sockaddr_in *) addr; /* set internal IP address */ if (NULL == inet_ntop (AF_INET, &in->sin_addr, buf, sizeof (buf))) { GNUNET_break (0); return GNUNET_OK; } GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS", buf); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Detected internal network address `%s'.\n"), buf); /* no need to continue iteration */ return GNUNET_SYSERR; } /** * Determine our local IP addresses; detect internal IP & IPv6-support * * @param ah auto setup context */ static void test_local_ip (struct GNUNET_NAT_AutoHandle *ah) { ah->have_v6 = GNUNET_NO; GNUNET_OS_network_interfaces_list (&nipo, ah); GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "DISABLEV6", (GNUNET_YES == ah->have_v6) ? "NO" : "YES"); next_phase (ah); } /** * Test if NAT has been punched * * @param ah auto setup context */ static void test_nat_punched (struct GNUNET_NAT_AutoHandle *ah) { // FIXME: not implemented next_phase (ah); } /** * Test if UPnPC works. * * @param ah auto setup context */ static void test_upnpc (struct GNUNET_NAT_AutoHandle *ah) { int have_upnpc; /* test if upnpc is available */ have_upnpc = (GNUNET_SYSERR != GNUNET_OS_check_helper_binary ("upnpc", GNUNET_NO, NULL)); /* FIXME: test if upnpc is actually working, that is, if transports start to work once we use UPnP */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, (have_upnpc) ? _("upnpc found, enabling its use\n") : _("upnpc not found\n")); GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "ENABLE_UPNP", (GNUNET_YES == have_upnpc) ? "YES" : "NO"); next_phase (ah); } /** * Test if ICMP server is working * * @param ah auto setup context */ static void test_icmp_server (struct GNUNET_NAT_AutoHandle *ah) { int hns; char *tmp; char *binary; tmp = NULL; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); hns = ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (ah->cfg, "nat", "EXTERNAL_ADDRESS", &tmp)) && (0 < strlen (tmp)) && (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, "nat", "BEHIND_NAT")) && (GNUNET_YES == GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d 127.0.0.1" ))); // use localhost as source for that one udp-port, ok for testing GNUNET_free_non_null (tmp); GNUNET_free (binary); GNUNET_log (GNUNET_ERROR_TYPE_INFO, (hns) ? _("gnunet-helper-nat-server found, testing it\n") : _("No working gnunet-helper-nat-server found\n")); if (hns) ah->task = GNUNET_SCHEDULER_add_now (&reversal_test, ah); else next_phase (ah); } /** * Test if ICMP client is working * * @param ah auto setup context */ static void test_icmp_client (struct GNUNET_NAT_AutoHandle *ah) { int hnc; char *tmp; char *binary; tmp = NULL; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); hnc = ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (ah->cfg, "nat", "INTERNAL_ADDRESS", &tmp)) && (0 < strlen (tmp)) && (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (ah->cfg, "nat", "BEHIND_NAT")) && (GNUNET_YES == GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d 127.0.0.1 127.0.0.2 42"))); // none of these parameters are actually used in privilege testing mode GNUNET_free_non_null (tmp); GNUNET_free (binary); GNUNET_log (GNUNET_ERROR_TYPE_INFO, (hnc) ? _("gnunet-helper-nat-client found, enabling it\n") : _("gnunet-helper-nat-client not found or behind NAT, disabling it\n")); next_phase (ah); } /** * Run the next phase of the auto test. */ static void next_phase (struct GNUNET_NAT_AutoHandle *ah) { struct GNUNET_CONFIGURATION_Handle *diff; ah->phase++; switch (ah->phase) { case AUTO_INIT: GNUNET_assert (0); break; case AUTO_ONLINE: test_online (ah); break; case AUTO_EXTERNAL_IP: test_external_ip (ah); break; case AUTO_LOCAL_IP: test_local_ip (ah); break; case AUTO_NAT_PUNCHED: test_nat_punched (ah); break; case AUTO_UPNPC: test_upnpc (ah); break; case AUTO_ICMP_SERVER: test_icmp_server (ah); break; case AUTO_ICMP_CLIENT: test_icmp_client (ah); break; case AUTO_DONE: diff = GNUNET_CONFIGURATION_get_diff (ah->initial_cfg, ah->cfg); ah->fin_cb (ah->fin_cb_cls, diff, NULL); GNUNET_CONFIGURATION_destroy (diff); GNUNET_NAT_autoconfig_cancel (ah); return; } } /** * Start auto-configuration routine. The resolver service should * be available when this function is called. * * @param cfg initial configuration * @param cb function to call with autoconfiguration result * @param cb_cls closure for @a cb * @return handle to cancel operation */ struct GNUNET_NAT_AutoHandle * GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_NAT_AutoResultCallback cb, void *cb_cls) { struct GNUNET_NAT_AutoHandle *ah; ah = GNUNET_new (struct GNUNET_NAT_AutoHandle); ah->fin_cb = cb; ah->fin_cb_cls = cb_cls; ah->cfg = GNUNET_CONFIGURATION_dup (cfg); ah->initial_cfg = GNUNET_CONFIGURATION_dup (cfg); /* never use loopback addresses if user wanted autoconfiguration */ GNUNET_CONFIGURATION_set_value_string (ah->cfg, "nat", "USE_LOCALADDR", "NO"); next_phase (ah); return ah; } /** * Abort autoconfiguration. * * @param ah handle for operation to abort */ void GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah) { if (NULL != ah->tst) { GNUNET_NAT_test_stop (ah->tst); ah->tst = NULL; } if (NULL != ah->eh) { GNUNET_NAT_mini_get_external_ipv4_cancel (ah->eh); ah->eh = NULL; } if (GNUNET_SCHEDULER_NO_TASK != ah->task) { GNUNET_SCHEDULER_cancel (ah->task); ah->task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONFIGURATION_destroy (ah->cfg); GNUNET_CONFIGURATION_destroy (ah->initial_cfg); GNUNET_free (ah); } /* end of nat_auto.c */ gnunet-0.10.1/src/nat/nat.conf0000644000175000017500000000274512225230043013015 00000000000000[nat] # Are we behind NAT? BEHIND_NAT = NO # Is the NAT hole-punched? PUNCHED_NAT = NO # Enable UPNP by default? ENABLE_UPNP = NO # Use addresses from the local network interfaces (inluding loopback, but also others) USE_LOCALADDR = YES # Use address obtained from a DNS lookup of our hostname USE_HOSTNAME = NO # External IP address of the NAT box (if known); IPv4 dotted-decimal ONLY at this time (should allow DynDNS!) # normal interface IP address for non-NATed peers; # possibly auto-detected (using UPnP) if possible if not specified # EXTERNAL_ADDRESS = # Should we use ICMP-based NAT traversal to try connect to NATed peers # or, if we are behind NAT, to allow connections to us? ENABLE_ICMP_CLIENT = NO ENABLE_ICMP_SERVER = NO # IP address of the interface connected to the NAT box; IPv4 dotted-decimal ONLY; # normal interface IP address for non-NATed peers; # likely auto-detected (via interface list) if not specified (!) # INTERNAL_ADDRESS = # Disable IPv6 support DISABLEV6 = NO # Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8) RETURN_LOCAL_ADDRESSES = NO # How often do we query the DNS resolver # for our hostname (to get our own IP) HOSTNAME_DNS_FREQUENCY = 20 min # How often do we iterate over our # network interfaces to check for changes # in our IP address? IFC_SCAN_FREQUENCY = 15 min # How often do we query the DNS resolver # for our hostname (to get our own IP) DYNDNS_FREQUENCY = 7 min [gnunet-nat-server] HOSTNAME = gnunet.org PORT = 5724 gnunet-0.10.1/src/nat/test_nat_data.conf0000644000175000017500000000506412225230043015042 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/nat-test # GNUNET_TEST_HOME = /var/lib/gnunet/ # configuration file is assumed to be the default, # which is what we want by default... [gnunetd] HOSTKEY = $GNUNET_TEST_HOME/.hostkey [TESTING] WEAKRANDOM = NO [client] [nat] # Are we behind NAT? BEHIND_NAT = YES # Is the NAT hole-punched? PUNCHED_NAT = NO # Disable UPNP by default until it gets cleaner! ENABLE_UPNP = YES # Use addresses from the local network interfaces (inluding loopback, but also others) USE_LOCALADDR = YES # External IP address of the NAT box (if known); IPv4 dotted-decimal ONLY at this time (should allow DynDNS!) # normal interface IP address for non-NATed peers; # possibly auto-detected (using UPnP) if possible if not specified # EXTERNAL_ADDRESS = # Should we use ICMP-based NAT traversal to try connect to NATed peers # or, if we are behind NAT, to allow connections to us? ENABLE_ICMP_CLIENT = NO ENABLE_ICMP_SERVER = NO # IP address of the interface connected to the NAT box; IPv4 dotted-decimal ONLY; # normal interface IP address for non-NATed peers; # likely auto-detected (via interface list) if not specified (!) # INTERNAL_ADDRESS = # Disable IPv6 support DISABLEV6 = NO [arm] PORT = 2087 HOSTNAME = localhost BINARY = gnunet-service-arm ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; DEFAULTSERVICES = topology hostlist UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-arm.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # GLOBAL_POSTFIX = -l $GNUNET_TEST_HOME/{}-logs # GLOBAL_PREFIX = # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = [statistics] AUTOSTART = YES PORT = 2088 HOSTNAME = localhost BINARY = gnunet-service-statistics ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = [resolver] AUTOSTART = YES PORT = 2089 HOSTNAME = localhost BINARY = gnunet-service-resolver ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = NO # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = [peerinfo] AUTOSTART = NO [transport] AUTOSTART = NO [core] AUTOSTART = NO [datastore] AUTOSTART = NO [fs] AUTOSTART = NO [dht] AUTOSTART = NO [mesh] AUTOSTART = NO [nse] AUTOSTART = NO [consensus] AUTOSTART = NO gnunet-0.10.1/src/gns/0000755000175000017500000000000012320755627011461 500000000000000gnunet-0.10.1/src/gns/gnunet-dns2gns.c0000644000175000017500000004742112255010512014411 00000000000000/* This file is part of GNUnet. (C) 2012-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnunet-dns2gns.c * @brief DNS server that translates DNS requests to GNS * @author Christian Grothoff */ #include "platform.h" #include #include #include #include #include #include "gns.h" /** * Timeout for DNS requests. */ #define TIMEOUT GNUNET_TIME_UNIT_MINUTES /** * Default suffix */ #define DNS_SUFFIX ".zkey.eu" /** * FCFS suffix */ #define FCFS_SUFFIX "fcfs.zkey.eu" /** * Data kept per request. */ struct Request { /** * Socket to use for sending the reply. */ struct GNUNET_NETWORK_Handle *lsock; /** * Destination address to use. */ const void *addr; /** * Initially, this is the DNS request, it will then be * converted to the DNS response. */ struct GNUNET_DNSPARSER_Packet *packet; /** * Our GNS request handle. */ struct GNUNET_GNS_LookupRequest *lookup; /** * Our DNS request handle */ struct GNUNET_DNSSTUB_RequestSocket *dns_lookup; /** * Task run on timeout or shutdown to clean up without * response. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Number of bytes in 'addr'. */ size_t addr_len; }; /** * Handle to GNS resolver. */ struct GNUNET_GNS_Handle *gns; /** * Stub resolver */ struct GNUNET_DNSSTUB_Context *dns_stub; /** * Listen socket for IPv4. */ static struct GNUNET_NETWORK_Handle *listen_socket4; /** * Listen socket for IPv6. */ static struct GNUNET_NETWORK_Handle *listen_socket6; /** * Task for IPv4 socket. */ static GNUNET_SCHEDULER_TaskIdentifier t4; /** * Task for IPv6 socket. */ static GNUNET_SCHEDULER_TaskIdentifier t6; /** * DNS suffix, suffix of this gateway in DNS; defaults to '.zkey.eu' */ static char *dns_suffix; /** * FCFS suffix, suffix of FCFS-authority in DNS; defaults to 'fcfs.zkey.eu'. */ static char *fcfs_suffix; /** * IP of DNS server */ static char *dns_ip; /** * UDP Port we listen on for inbound DNS requests. */ static unsigned int listen_port = 53; /** * Which GNS zone do we translate incoming DNS requests to? */ static struct GNUNET_CRYPTO_EcdsaPublicKey my_zone; /** * '-z' option with the main zone to use. */ static char *gns_zone_str; /** * Configuration to use. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Connection to identity service. */ static struct GNUNET_IDENTITY_Handle *identity; /** * Request for our ego. */ static struct GNUNET_IDENTITY_Operation *id_op; /** * Task run on shutdown. Cleans up everything. * * @param cls unused * @param tc scheduler context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != t4) GNUNET_SCHEDULER_cancel (t4); if (GNUNET_SCHEDULER_NO_TASK != t6) GNUNET_SCHEDULER_cancel (t6); if (NULL != listen_socket4) { GNUNET_NETWORK_socket_close (listen_socket4); listen_socket4 = NULL; } if (NULL != listen_socket6) { GNUNET_NETWORK_socket_close (listen_socket6); listen_socket6 = NULL; } if (NULL != id_op) { GNUNET_IDENTITY_cancel (id_op); id_op = NULL; } if (NULL != identity) { GNUNET_IDENTITY_disconnect (identity); identity = NULL; } GNUNET_GNS_disconnect (gns); gns = NULL; GNUNET_DNSSTUB_stop (dns_stub); dns_stub = NULL; } /** * Send the response for the given request and clean up. * * @param request context for the request. */ static void send_response (struct Request *request) { char *buf; size_t size; if (GNUNET_SYSERR == GNUNET_DNSPARSER_pack (request->packet, UINT16_MAX /* is this not too much? */, &buf, &size)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to pack DNS response into UDP packet!\n")); } else { if (size != GNUNET_NETWORK_socket_sendto (request->lsock, buf, size, request->addr, request->addr_len)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto"); GNUNET_free (buf); } GNUNET_SCHEDULER_cancel (request->timeout_task); GNUNET_DNSPARSER_free_packet (request->packet); GNUNET_free (request); } /** * Task run on timeout. Cleans up request. * * @param cls 'struct Request' of the request to clean up * @param tc scheduler context */ static void do_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Request *request = cls; if (NULL != request->packet) GNUNET_DNSPARSER_free_packet (request->packet); if (NULL != request->lookup) GNUNET_GNS_lookup_cancel (request->lookup); if (NULL != request->dns_lookup) GNUNET_DNSSTUB_resolve_cancel (request->dns_lookup); GNUNET_free (request); } /** * Iterator called on obtained result for a DNS lookup * * @param cls closure * @param rs the request socket * @param dns the DNS udp payload * @param r size of the DNS payload */ static void dns_result_processor (void *cls, struct GNUNET_DNSSTUB_RequestSocket *rs, const struct GNUNET_TUN_DnsHeader *dns, size_t r) { struct Request *request = cls; request->packet = GNUNET_DNSPARSER_parse ((char*)dns, r); send_response (request); } /** * Iterator called on obtained result for a GNS lookup. * * @param cls closure * @param rd_count number of records in @a rd * @param rd the records in reply */ static void result_processor (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct Request *request = cls; struct GNUNET_DNSPARSER_Packet *packet; uint32_t i; struct GNUNET_DNSPARSER_Record rec; request->lookup = NULL; packet = request->packet; packet->flags.query_or_response = 1; packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR; packet->flags.checking_disabled = 0; packet->flags.authenticated_data = 1; packet->flags.zero = 0; packet->flags.recursion_available = 1; packet->flags.message_truncated = 0; packet->flags.authoritative_answer = 0; //packet->flags.opcode = GNUNET_TUN_DNS_OPCODE_STATUS; // ??? for (i=0;iqueries[0].name); rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; rec.type = GNUNET_DNSPARSER_TYPE_A; rec.data.raw.data = GNUNET_new (struct in_addr); memcpy (rec.data.raw.data, rd[i].data, rd[i].data_size); rec.data.raw.data_len = sizeof (struct in_addr); GNUNET_array_append (packet->answers, packet->num_answers, rec); break; case GNUNET_DNSPARSER_TYPE_AAAA: GNUNET_assert (sizeof (struct in6_addr) == rd[i].data_size); rec.name = GNUNET_strdup (packet->queries[0].name); rec.data.raw.data = GNUNET_new (struct in6_addr); rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; rec.type = GNUNET_DNSPARSER_TYPE_AAAA; memcpy (rec.data.raw.data, rd[i].data, rd[i].data_size); rec.data.raw.data_len = sizeof (struct in6_addr); GNUNET_array_append (packet->answers, packet->num_answers, rec); break; case GNUNET_DNSPARSER_TYPE_CNAME: rec.name = GNUNET_strdup (packet->queries[0].name); rec.data.hostname = strdup (rd[i].data); rec.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; rec.type = GNUNET_DNSPARSER_TYPE_CNAME; memcpy (rec.data.hostname, rd[i].data, rd[i].data_size); GNUNET_array_append (packet->answers, packet->num_answers, rec); break; default: /* skip */ break; } } send_response (request); } /** * Handle DNS request. * * @param lsock socket to use for sending the reply * @param addr address to use for sending the reply * @param addr_len number of bytes in @a addr * @param udp_msg DNS request payload * @param udp_msg_size number of bytes in @a udp_msg */ static void handle_request (struct GNUNET_NETWORK_Handle *lsock, const void *addr, size_t addr_len, const char *udp_msg, size_t udp_msg_size) { struct Request *request; struct GNUNET_DNSPARSER_Packet *packet; char *name; size_t name_len; int type; int use_gns; packet = GNUNET_DNSPARSER_parse (udp_msg, udp_msg_size); if (NULL == packet) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Cannot parse DNS request from %s\n"), GNUNET_a2s (addr, addr_len)); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request for `%s' with flags %u, #answers %d, #auth %d, #additional %d\n", packet->queries[0].name, (unsigned int) packet->flags.query_or_response, (int) packet->num_answers, (int) packet->num_authority_records, (int) packet->num_additional_records); if ( (0 != packet->flags.query_or_response) || (0 != packet->num_answers) || (0 != packet->num_authority_records)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Received malformed DNS request from %s\n"), GNUNET_a2s (addr, addr_len)); GNUNET_DNSPARSER_free_packet (packet); return; } if ( (1 != packet->num_queries) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Received unsupported DNS request from %s\n"), GNUNET_a2s (addr, addr_len)); GNUNET_DNSPARSER_free_packet (packet); return; } request = GNUNET_malloc (sizeof (struct Request) + addr_len); request->lsock = lsock; request->packet = packet; request->addr = &request[1]; request->addr_len = addr_len; memcpy (&request[1], addr, addr_len); request->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &do_timeout, request); name = GNUNET_strdup (packet->queries[0].name); name_len = strlen (name); use_gns = GNUNET_NO; if ( (name_len > strlen (fcfs_suffix)) && (0 == strcasecmp (fcfs_suffix, &name[name_len - strlen (fcfs_suffix)])) ) { /* replace ".fcfs.zkey.eu" with ".gnu" */ strcpy (&name[name_len - strlen (fcfs_suffix)], ".gnu"); use_gns = GNUNET_YES; } else if ( (name_len > strlen (dns_suffix)) && (0 == strcasecmp (dns_suffix, &name[name_len - strlen (dns_suffix)])) ) { /* replace ".zkey.eu" with ".zkey" */ strcpy (&name[name_len - strlen (dns_suffix)], ".zkey"); use_gns = GNUNET_YES; } else if ( (name_len > strlen (".gnu")) && (0 == strcasecmp (".gnu", &name[name_len - strlen (".gnu")])) ) { /* name is in GNS */ use_gns = GNUNET_YES; } if (GNUNET_YES == use_gns) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling GNS on `%s'\n", name); type = packet->queries[0].type; request->lookup = GNUNET_GNS_lookup (gns, name, &my_zone, type, GNUNET_NO, NULL /* no shorten */, &result_processor, request); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using DNS resolver IP `%s' to resolve `%s'\n", dns_ip, name); GNUNET_DNSPARSER_free_packet (request->packet); request->packet = NULL; request->dns_lookup = GNUNET_DNSSTUB_resolve2 (dns_stub, udp_msg, udp_msg_size, &dns_result_processor, request); } GNUNET_free (name); } /** * Task to read IPv4 DNS packets. * * @param cls the 'listen_socket4' * @param tc scheduler context */ static void read_dns4 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_in v4; socklen_t addrlen; ssize_t size; GNUNET_assert (listen_socket4 == cls); t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, listen_socket4, &read_dns4, listen_socket4); if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason)) return; /* shutdown? */ size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket4); if (0 > size) { GNUNET_break (0); return; /* read error!? */ } { char buf[size]; addrlen = sizeof (v4); GNUNET_break (size == GNUNET_NETWORK_socket_recvfrom (listen_socket4, buf, size, (struct sockaddr *) &v4, &addrlen)); handle_request (listen_socket4, &v4, addrlen, buf, size); } } /** * Task to read IPv6 DNS packets. * * @param cls the 'listen_socket6' * @param tc scheduler context */ static void read_dns6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_in6 v6; socklen_t addrlen; ssize_t size; GNUNET_assert (listen_socket6 == cls); t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, listen_socket6, &read_dns6, listen_socket6); if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason)) return; /* shutdown? */ size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket6); if (0 > size) { GNUNET_break (0); return; /* read error!? */ } { char buf[size]; addrlen = sizeof (v6); GNUNET_break (size == GNUNET_NETWORK_socket_recvfrom (listen_socket6, buf, size, (struct sockaddr *) &v6, &addrlen)); handle_request (listen_socket6, &v6, addrlen, buf, size); } } /** * Start DNS daemon. */ static void run_dnsd () { if (NULL == dns_suffix) dns_suffix = DNS_SUFFIX; if (NULL == fcfs_suffix) fcfs_suffix = FCFS_SUFFIX; if (NULL == (gns = GNUNET_GNS_connect (cfg))) return; if (NULL == (dns_stub = GNUNET_DNSSTUB_start (dns_ip))) { GNUNET_GNS_disconnect (gns); gns = NULL; return; } listen_socket4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (NULL != listen_socket4) { struct sockaddr_in v4; memset (&v4, 0, sizeof (v4)); v4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif v4.sin_port = htons (listen_port); if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_socket4, (struct sockaddr *) &v4, sizeof (v4))) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); GNUNET_NETWORK_socket_close (listen_socket4); listen_socket4 = NULL; } } listen_socket6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (NULL != listen_socket6) { struct sockaddr_in6 v6; memset (&v6, 0, sizeof (v6)); v6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (v6); #endif v6.sin6_port = htons (listen_port); if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_socket6, (struct sockaddr *) &v6, sizeof (v6))) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); GNUNET_NETWORK_socket_close (listen_socket6); listen_socket6 = NULL; } } if ( (NULL == listen_socket4) && (NULL == listen_socket6) ) { GNUNET_GNS_disconnect (gns); gns = NULL; GNUNET_DNSSTUB_stop (dns_stub); dns_stub = NULL; return; } if (NULL != listen_socket4) t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, listen_socket4, &read_dns4, listen_socket4); if (NULL != listen_socket6) t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, listen_socket6, &read_dns6, listen_socket6); } /** * Method called to inform about the egos of this peer. * * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, * this function is only called ONCE, and 'NULL' being passed in * @a ego does indicate an error (i.e. name is taken or no default * value is known). If @a ego is non-NULL and if '*ctx' * is set in those callbacks, the value WILL be passed to a subsequent * call to the identity callback of #GNUNET_IDENTITY_connect (if * that one was not NULL). * * @param cls closure, NULL * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { id_op = NULL; if (NULL == ego) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No ego configured for `dns2gns` subsystem\n")); return; } GNUNET_IDENTITY_ego_get_public_key (ego, &my_zone); run_dnsd (); } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { cfg = c; if (NULL == dns_ip) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No DNS server specified!\n")); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); if (NULL == gns_zone_str) { identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); id_op = GNUNET_IDENTITY_get (identity, "dns2gns", &identity_cb, NULL); return; } if ( (NULL == gns_zone_str) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (gns_zone_str, strlen (gns_zone_str), &my_zone)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No valid GNS zone specified!\n")); GNUNET_SCHEDULER_shutdown (); return; } run_dnsd (); } /** * The main function for the dns2gns daemon. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'d', "dns", "IP", gettext_noop ("IP of recursive DNS resolver to use (required)"), 1, &GNUNET_GETOPT_set_string, &dns_ip}, {'f', "fcfs", "NAME", gettext_noop ("Authoritative FCFS suffix to use (optional); default: fcfs.zkey.eu"), 1, &GNUNET_GETOPT_set_string, &fcfs_suffix}, {'s', "suffix", "SUFFIX", gettext_noop ("Authoritative DNS suffix to use (optional); default: zkey.eu"), 1, &GNUNET_GETOPT_set_string, &dns_suffix}, {'p', "port", "UDPPORT", gettext_noop ("UDP port to listen on for inbound DNS requests; default: 53"), 1, &GNUNET_GETOPT_set_uint, &listen_port}, {'z', "zone", "PUBLICKEY", gettext_noop ("Public key of the GNS zone to use (overrides default)"), 1, &GNUNET_GETOPT_set_string, &gns_zone_str}, GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; GNUNET_log_setup ("gnunet-dns2gns", "WARNING", NULL); ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-dns2gns", _("GNUnet DNS-to-GNS proxy (a DNS server)"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-dns2gns.c */ gnunet-0.10.1/src/gns/w32nsp.c0000644000175000017500000005044712255010512012673 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/w32nsp.c * @brief W32 integration for GNS * @author LRN */ /* This code is partially based upon samples from the book * "Network Programming For Microsoft Windows, 2Nd Edition". */ #define VERBOSE 0 #if !VERBOSE # define DEBUGLOG(s, ...) #endif #if VERBOSE # define __printf__ printf # define DEBUGLOG(s, ...) printf (s, ##__VA_ARGS__) #endif #include #include #include #include #include #define WINDOWS 1 #define MINGW 1 #ifndef __BYTE_ORDER #ifdef _BYTE_ORDER #define __BYTE_ORDER _BYTE_ORDER #else #ifdef BYTE_ORDER #define __BYTE_ORDER BYTE_ORDER #endif #endif #endif #ifndef __BIG_ENDIAN #ifdef _BIG_ENDIAN #define __BIG_ENDIAN _BIG_ENDIAN #else #ifdef BIG_ENDIAN #define __BIG_ENDIAN BIG_ENDIAN #endif #endif #endif #ifndef __LITTLE_ENDIAN #ifdef _LITTLE_ENDIAN #define __LITTLE_ENDIAN _LITTLE_ENDIAN #else #ifdef LITTLE_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #endif #endif #include "w32resolver.h" #define INITGUID #include "gnunet_w32nsp_lib.h" #undef INITGUID #define NSPAPI_VERSION_MAJOR 4 #define NSPAPI_VERSION_MINOR 4 static CRITICAL_SECTION records_cs; struct record { SOCKET s; DWORD flags; uint8_t state; char *buf; wchar_t *name; }; static struct record *records = NULL; static size_t records_len = 0; static size_t records_size = 0; static int resize_records () { size_t new_size = records_len > 0 ? records_len * 2 : 5; struct record *new_records = malloc (new_size * sizeof (struct record)); if (new_records == NULL) { SetLastError (WSA_NOT_ENOUGH_MEMORY); return 0; } memcpy (new_records, records, records_len * sizeof (struct record)); memset (&new_records[records_len], 0, sizeof (struct record) * (new_size - records_len)); records_size = new_size; free (records); records = new_records; return 1; } static int add_record (SOCKET s, const wchar_t *name, DWORD flags) { int res = 1; int i; int empty = -1; //EnterCriticalSection (&records_cs); for (i = 0; i < records_len; i++) if (records[i].state == 0) break; empty = i; if (i == records_len) { res = resize_records (); if (res) empty = records_len++; } if (res) { struct record r; r.s = s; r.flags = flags; r.name = (wchar_t *) name; r.state = 1; r.buf = NULL; if (name) r.name = wcsdup (name); records[empty] = r; } //LeaveCriticalSection (&records_cs); return res; } /* These are not defined by mingw.org headers at the moment*/ typedef INT (WSPAPI *LPNSPIOCTL) (HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPDWORD,LPWSACOMPLETION,LPWSATHREADID); typedef struct _NSP_ROUTINE_XP { DWORD cbSize; DWORD dwMajorVersion; DWORD dwMinorVersion; LPNSPCLEANUP NSPCleanup; LPNSPLOOKUPSERVICEBEGIN NSPLookupServiceBegin; LPNSPLOOKUPSERVICENEXT NSPLookupServiceNext; LPNSPLOOKUPSERVICEEND NSPLookupServiceEnd; LPNSPSETSERVICE NSPSetService; LPNSPINSTALLSERVICECLASS NSPInstallServiceClass; LPNSPREMOVESERVICECLASS NSPRemoveServiceClass; LPNSPGETSERVICECLASSINFO NSPGetServiceClassInfo; LPNSPIOCTL NSPIoctl; } NSP_ROUTINE_XP; static SOCKET connect_to_dns_resolver () { struct sockaddr_in addr; SOCKET r; int ret; r = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == r) { SetLastError (16004); return r; } addr.sin_family = AF_INET; addr.sin_port = htons (5353); /* TCP 5353 is not registered; UDP 5353 is */ addr.sin_addr.s_addr = inet_addr ("127.0.0.1"); ret = connect (r, (struct sockaddr *) &addr, sizeof (addr)); if (SOCKET_ERROR == ret) { DWORD err = GetLastError (); closesocket (r); SetLastError (err); SetLastError (16005); r = INVALID_SOCKET; } return r; } static int send_name_to_ip_request (LPWSAQUERYSETW lpqsRestrictions, LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags, SOCKET *resolver) { struct GNUNET_W32RESOLVER_GetMessage *msg; int af4 = 0; int af6 = 0; char *buf; int ret = 1; int i; size_t size = sizeof (struct GNUNET_W32RESOLVER_GetMessage); size_t namelen = 0; if (lpqsRestrictions->lpszServiceInstanceName) namelen = sizeof (wchar_t) * (wcslen (lpqsRestrictions->lpszServiceInstanceName) + 1); size += namelen; buf = malloc (size); msg = (struct GNUNET_W32RESOLVER_GetMessage *) buf; msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST); if (lpqsRestrictions->dwNumberOfProtocols > 0) { int i; for (i = 0; i < lpqsRestrictions->dwNumberOfProtocols; i++) { if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET) af4 = 1; if (lpqsRestrictions->lpafpProtocols[0].iAddressFamily == AF_INET6) af6 = 1; } } if (af4 && !af6) msg->af = htonl (AF_INET); else if (af6 && !af4) msg->af = htonl (AF_INET6); else msg->af = htonl (AF_UNSPEC); if (lpqsRestrictions->lpszServiceInstanceName) memcpy (&msg[1], lpqsRestrictions->lpszServiceInstanceName, namelen); msg->sc_data1 = htonl (lpqsRestrictions->lpServiceClassId->Data1); msg->sc_data2 = htons (lpqsRestrictions->lpServiceClassId->Data2); msg->sc_data3 = htons (lpqsRestrictions->lpServiceClassId->Data3); for (i = 0; i < 8; i++) msg->sc_data4[i] = lpqsRestrictions->lpServiceClassId->Data4[i]; *resolver = connect_to_dns_resolver (); if (*resolver != INVALID_SOCKET) { if (size != send (*resolver, buf, size, 0)) { #if VERBOSE DWORD err = GetLastError (); #endif closesocket (*resolver); *resolver = INVALID_SOCKET; DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: failed to send request: %lu\n", err); SetLastError (WSATRY_AGAIN); ret = 0; } } else ret = 0; free (buf); return ret; } static int WSPAPI NSPCleanup (LPGUID lpProviderId) { DEBUGLOG ("NSPCleanup\n"); if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) { return NO_ERROR; } SetLastError (WSAEINVALIDPROVIDER); return SOCKET_ERROR; } BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: if (!InitializeCriticalSectionAndSpinCount (&records_cs, 0x00000400)) { return FALSE; } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: DeleteCriticalSection (&records_cs); break; } return TRUE; } static int WSPAPI GNUNET_W32NSP_LookupServiceBegin (LPGUID lpProviderId, LPWSAQUERYSETW lpqsRestrictions, LPWSASERVICECLASSINFOW lpServiceClassInfo, DWORD dwControlFlags, LPHANDLE lphLookup) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin\n"); if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) { SOCKET s; if (lpqsRestrictions->dwNameSpace != NS_DNS && lpqsRestrictions->dwNameSpace != NS_ALL) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: wrong namespace\n"); SetLastError (WSAEINVAL); return SOCKET_ERROR; } if (lpqsRestrictions->lpszServiceInstanceName != NULL) { wchar_t *s = lpqsRestrictions->lpszServiceInstanceName; size_t len = wcslen (s); if (len >= 5 && wcscmp (&s[len - 5], L".zkey") == 0) { } else if (len >= 4 && wcscmp (&s[len - 4], L".gnu") == 0) { } else { DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: unsupported TLD\n"); SetLastError (WSAEINVAL); return SOCKET_ERROR; } } if (send_name_to_ip_request (lpqsRestrictions, lpServiceClassInfo, dwControlFlags, &s)) { if (!(add_record (s, lpqsRestrictions->lpszServiceInstanceName, dwControlFlags))) { DWORD err = GetLastError (); DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: failed to add a record\n"); closesocket (s); SetLastError (err); return SOCKET_ERROR; } *lphLookup = (HANDLE) s; DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: OK (%lu)\n", GetLastError ()); return NO_ERROR; } return SOCKET_ERROR; } DEBUGLOG ("GNUNET_W32NSP_LookupServiceBegin: wrong provider\n"); SetLastError (WSAEINVALIDPROVIDER); return SOCKET_ERROR; } #define UnmarshallPtr(ptr, ptrtype, base) \ if (ptr) \ ptr = (ptrtype *) (base + (uintptr_t) ptr) static void UnmarshallWSAQUERYSETW (LPWSAQUERYSETW req) { int i; char *base = (char *) req; UnmarshallPtr (req->lpszServiceInstanceName, wchar_t, base); UnmarshallPtr (req->lpServiceClassId, GUID, base); UnmarshallPtr (req->lpVersion, WSAVERSION, base); UnmarshallPtr (req->lpszComment, wchar_t, base); UnmarshallPtr (req->lpNSProviderId, GUID, base); UnmarshallPtr (req->lpszContext, wchar_t, base); UnmarshallPtr (req->lpafpProtocols, AFPROTOCOLS, base); UnmarshallPtr (req->lpszQueryString, wchar_t, base); UnmarshallPtr (req->lpcsaBuffer, CSADDR_INFO, base); for (i = 0; i < req->dwNumberOfCsAddrs; i++) { UnmarshallPtr (req->lpcsaBuffer[i].LocalAddr.lpSockaddr, SOCKADDR, base); UnmarshallPtr (req->lpcsaBuffer[i].RemoteAddr.lpSockaddr, SOCKADDR, base); } UnmarshallPtr (req->lpBlob, BLOB, base); if (req->lpBlob) UnmarshallPtr (req->lpBlob->pBlobData, BYTE, base); } static int WSAAPI GNUNET_W32NSP_LookupServiceNext (HANDLE hLookup, DWORD dwControlFlags, LPDWORD lpdwBufferLength, LPWSAQUERYSETW lpqsResults) { /*DWORD effective_flags;*/ int i; struct GNUNET_MessageHeader header = {0, 0}; int rec = -1; int rc; int to_receive; int t; char *buf; DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext\n"); //EnterCriticalSection (&records_cs); for (i = 0; i < records_len; i++) { if (records[i].s == (SOCKET) hLookup) { rec = i; break; } } if (rec == -1) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: invalid handle\n"); SetLastError (WSA_INVALID_HANDLE); //LeaveCriticalSection (&records_cs); return SOCKET_ERROR; } if (records[rec].state & 4) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: session is closed\n"); SetLastError (WSA_E_NO_MORE); //LeaveCriticalSection (&records_cs); return SOCKET_ERROR; } /*effective_flags = dwControlFlags & records[rec].flags;*/ if (records[rec].buf) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: checking buffer\n"); header = *((struct GNUNET_MessageHeader *) records[rec].buf); if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n"); SetLastError (WSAEFAULT); //LeaveCriticalSection (&records_cs); return SOCKET_ERROR; } memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)records[rec].buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)); free (records[rec].buf); records[rec].buf = NULL; //LeaveCriticalSection (&records_cs); UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK (from buffer)\n"); return NO_ERROR; } records[rec].state |= 8; //LeaveCriticalSection (&records_cs); to_receive = sizeof (header); rc = 0; #if VERBOSE { unsigned long have; int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a header from %p, %lu bytes available\n", to_receive, hLookup, have); } #endif while (to_receive > 0) { t = recv ((SOCKET) hLookup, &((char *) &header)[rc], to_receive, 0); if (t > 0) { rc += t; to_receive -= t; } else break; } #if VERBOSE { unsigned long have; int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a header from %p, %lu bytes available\n", rc, hLookup, have); } #endif //EnterCriticalSection (&records_cs); records[rec].state &= ~8; if (rc != sizeof (header)) { if (records[rec].state & 2) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n"); SetLastError (WSA_E_CANCELLED); } else { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data for a header (rc %d != %u, state is 0x%0X)\n", rc, sizeof (header), records[rec].state); SetLastError (WSA_E_NO_MORE); } records[rec].state |= 4; //LeaveCriticalSection (&records_cs); return SOCKET_ERROR; } records[rec].state &= ~8; header.type = ntohs (header.type); header.size = ntohs (header.size); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: header type %d, header size %u\n", header.type, header.size); if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE || (header.type == GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE && header.size == sizeof (header))) { records[rec].state |= 4; if (header.type != GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE) DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: header type is wrong\n"); else DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: empty header - no data\n"); //LeaveCriticalSection (&records_cs); SetLastError (WSA_E_NO_MORE); return SOCKET_ERROR; } buf = malloc (header.size); if (buf == NULL) { records[rec].state |= 4; DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: malloc() failed\n"); //LeaveCriticalSection (&records_cs); SetLastError (WSA_E_NO_MORE); return SOCKET_ERROR; } records[rec].state |= 8; //LeaveCriticalSection (&records_cs); memcpy (buf, &header, sizeof (header)); to_receive = header.size - sizeof (header); rc = 0; #if VERBOSE { unsigned long have; int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: reading %d bytes as a body from %p, %lu bytes available\n", to_receive, hLookup, have); } #endif while (to_receive > 0) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: recv (%d)\n", to_receive); t = recv ((SOCKET) hLookup, &((char *) &((struct GNUNET_MessageHeader *) buf)[1])[rc], to_receive, 0); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: recv returned %d\n", t); if (t > 0) { rc += t; to_receive -= t; } else break; } #if VERBOSE { unsigned long have; int ior = ioctlsocket ((SOCKET) hLookup, FIONREAD, &have); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: read %d bytes as a body from %p, %lu bytes available\n", rc, hLookup, have); } #endif //EnterCriticalSection (&records_cs); records[rec].state &= ~8; if (rc != header.size - sizeof (header)) { free (buf); if (records[rec].state & 2) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: call cancelled\n"); SetLastError (WSA_E_CANCELLED); } else { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: failed to receive enough data for the rest (rc %d != %d, state is 0x%0X)\n", rc, header.size - sizeof (header), records[rec].state); SetLastError (WSA_E_NO_MORE); } records[rec].state |= 4; //LeaveCriticalSection (&records_cs); return SOCKET_ERROR; } if (*lpdwBufferLength < header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)) { DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: client buffer is too small\n"); SetLastError (WSAEFAULT); records[rec].buf = buf; //LeaveCriticalSection (&records_cs); return SOCKET_ERROR; } //LeaveCriticalSection (&records_cs); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: writing %d bytes into result buffer\n", header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)); memcpy (lpqsResults, &((struct GNUNET_W32RESOLVER_GetMessage *)buf)[1], header.size - sizeof (struct GNUNET_W32RESOLVER_GetMessage)); free (buf); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: OK\n"); UnmarshallWSAQUERYSETW ((LPWSAQUERYSETW) lpqsResults); DEBUGLOG ("GNUNET_W32NSP_LookupServiceNext: returning (%lu)\n", GetLastError ()); return NO_ERROR; } static int WSPAPI GNUNET_W32NSP_LookupServiceEnd (HANDLE hLookup) { int i; int rec = -1; DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd\n"); //EnterCriticalSection (&records_cs); for (i = 0; i < records_len; i++) { if (records[i].s == (SOCKET) hLookup) { rec = i; break; } } if (rec == -1) { SetLastError (WSA_INVALID_HANDLE); //LeaveCriticalSection (&records_cs); DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: invalid handle\n"); return SOCKET_ERROR; } records[rec].state |= 2; closesocket (records[rec].s); while (records[rec].state & 8) { //LeaveCriticalSection (&records_cs); Sleep (10); //EnterCriticalSection (&records_cs); } if (records[rec].buf) free (records[rec].buf); records[rec].buf = NULL; records[rec].state = 0; if (records[rec].name) free (records[rec].name); //LeaveCriticalSection (&records_cs); DEBUGLOG ("GNUNET_W32NSP_LookupServiceEnd: OK\n"); return NO_ERROR; } static int WSAAPI GNUNET_W32NSP_SetService (LPGUID lpProviderId, LPWSASERVICECLASSINFOW lpServiceClassInfo, LPWSAQUERYSETW lpqsRegInfo, WSAESETSERVICEOP essOperation, DWORD dwControlFlags) { DEBUGLOG ("GNUNET_W32NSP_SetService\n"); SetLastError (WSAEOPNOTSUPP); return SOCKET_ERROR; } static int WSAAPI GNUNET_W32NSP_InstallServiceClass (LPGUID lpProviderId, LPWSASERVICECLASSINFOW lpServiceClassInfo) { DEBUGLOG ("GNUNET_W32NSP_InstallServiceClass\n"); SetLastError (WSAEOPNOTSUPP); return SOCKET_ERROR; } static int WSAAPI GNUNET_W32NSP_RemoveServiceClass (LPGUID lpProviderId, LPGUID lpServiceClassId) { DEBUGLOG ("GNUNET_W32NSP_RemoveServiceClass\n"); SetLastError (WSAEOPNOTSUPP); return SOCKET_ERROR; } static int WSAAPI GNUNET_W32NSP_GetServiceClassInfo (LPGUID lpProviderId, LPDWORD lpdwBufSize, LPWSASERVICECLASSINFOW lpServiceClassInfo) { DEBUGLOG ("GNUNET_W32NSP_GetServiceClassInfo\n"); SetLastError (WSAEOPNOTSUPP); return SOCKET_ERROR; } static int WSAAPI GNUNET_W32NSP_Ioctl (HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion, LPWSATHREADID lpThreadId) { DEBUGLOG ("GNUNET_W32NSP_Ioctl\n"); SetLastError (WSAEOPNOTSUPP); return SOCKET_ERROR; } /** * This function is called by Winsock to hook up our provider. * It is the only function that [should be/is] exported by the * provider. All other routines are passed as pointers in lpnspRoutines. */ int WSAAPI GNUNET_W32NSP_NSPStartup (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines) { if (IsEqualGUID (lpProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS)) { if (!connect_to_dns_resolver ()) { return SOCKET_ERROR; } /* This assumes that NSP_ROUTINE struct doesn't have a NSPIoctl member. * If it does, you need to use FIELD_OFFSET() macro to get offset of NSPIoctl * and use that offset as cbSize. */ lpnspRoutines->cbSize = sizeof(NSP_ROUTINE); lpnspRoutines->dwMajorVersion = NSPAPI_VERSION_MAJOR; lpnspRoutines->dwMinorVersion = NSPAPI_VERSION_MINOR; lpnspRoutines->NSPCleanup = NSPCleanup; lpnspRoutines->NSPLookupServiceBegin = GNUNET_W32NSP_LookupServiceBegin; lpnspRoutines->NSPLookupServiceNext = GNUNET_W32NSP_LookupServiceNext; lpnspRoutines->NSPLookupServiceEnd = GNUNET_W32NSP_LookupServiceEnd; lpnspRoutines->NSPSetService = GNUNET_W32NSP_SetService; lpnspRoutines->NSPInstallServiceClass = GNUNET_W32NSP_InstallServiceClass; lpnspRoutines->NSPRemoveServiceClass = GNUNET_W32NSP_RemoveServiceClass; lpnspRoutines->NSPGetServiceClassInfo = GNUNET_W32NSP_GetServiceClassInfo; /*((NSP_ROUTINE_XP *) lpnspRoutines)->NSPIoctl = GNUNET_W32NSP_Ioctl;*/ lpnspRoutines->NSPIoctl = GNUNET_W32NSP_Ioctl; return NO_ERROR; } SetLastError (WSAEINVALIDPROVIDER); return SOCKET_ERROR; } gnunet-0.10.1/src/gns/w32nsp.def0000644000175000017500000000005612255010512013176 00000000000000EXPORTS NSPStartup=GNUNET_W32NSP_NSPStartup gnunet-0.10.1/src/gns/w32nsp-resolve.c0000644000175000017500000003723412261236532014360 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/w32nsp-resolve.c * @brief W32 integration for GNS * @author LRN */ #define INITGUID #include #include #include #include #include #include "gnunet_w32nsp_lib.h" #include typedef int (WSPAPI *LPNSPSTARTUP) (LPGUID lpProviderId, LPNSP_ROUTINE lpnspRoutines); GUID host = {0x0002a800,0,0,{ 0xC0,0,0,0,0,0,0,0x46 }}; GUID ip4 = {0x00090035,0,1,{ 0xc0,0,0,0,0,0,0,0x046}}; GUID ip6 = {0x00090035,0,0x001c, { 0xc0,0,0,0,0,0,0,0x046}}; DEFINE_GUID(W32_DNS, 0x22059D40, 0x7E9E, 0x11CF, 0xAE, 0x5A, 0x00, 0xAA, 0x00, 0xA7, 0x11, 0x2B); #define DEFINE_DNS_GUID(a,x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001); DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002); DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005); DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006); DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c); DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f); DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010); DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c); DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021); DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); // // Utility to turn a list of offsets into a list of addresses. Used // to convert structures returned as BLOBs. // VOID FixList(PCHAR ** List, PCHAR Base) { if(*List) { PCHAR * Addr; Addr = *List = (PCHAR *)( ((DWORD)*List + Base) ); while(*Addr) { *Addr = (PCHAR)(((DWORD)*Addr + Base)); Addr++; } } } // // Routine to convert a hostent returned in a BLOB to one with // usable pointers. The structure is converted in-place. // VOID UnpackHostEnt(struct hostent * hostent) { PCHAR pch; pch = (PCHAR)hostent; if(hostent->h_name) { hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch); } FixList(&hostent->h_aliases, pch); FixList(&hostent->h_addr_list, pch); } static void print_hostent (struct hostent *he) { int i; char **pAlias; printf("\tOfficial name: %s\n", he->h_name); for (i=0, pAlias = he->h_aliases; *pAlias != 0; pAlias++) { printf("\tAlternate name #%d: %s\n", ++i, *pAlias); } printf("\tAddress type: "); switch (he->h_addrtype) { case AF_INET: printf("AF_INET\n"); break; case AF_INET6: printf("AF_INET6\n"); break; case AF_NETBIOS: printf("AF_NETBIOS\n"); break; default: printf(" %d\n", he->h_addrtype); break; } printf("\tAddress length: %d\n", he->h_length); if (he->h_addrtype == AF_INET) { struct sockaddr_in addr; memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_port = 0; i = 0; while (he->h_addr_list[i] != 0) { char buf[1024]; DWORD buflen = 1024; addr.sin_addr = *(struct in_addr *) he->h_addr_list[i++]; if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen)) printf("\tIPv4 Address #%d: %s\n", i, buf); else printf("\tIPv4 Address #%d: Can't convert: %lu\n", i, GetLastError ()); } } else if (he->h_addrtype == AF_INET6) { struct sockaddr_in6 addr; memset (&addr, 0, sizeof (addr)); addr.sin6_family = AF_INET6; addr.sin6_port = 0; i = 0; while (he->h_addr_list[i] != 0) { char buf[1024]; DWORD buflen = 1024; addr.sin6_addr = *(struct in6_addr *) he->h_addr_list[i++]; if (NO_ERROR == WSAAddressToStringA ((LPSOCKADDR) &addr, sizeof (addr), NULL, buf, &buflen)) printf("\tIPv6 Address #%d: %s\n", i, buf); else printf("\tIPv6 Address #%d: Can't convert: %lu\n", i, GetLastError ()); } } } int main (int argc, char **argv) { int ret; int r = 1; WSADATA wsd; GUID prov; GUID sc; wchar_t *cmdl; int wargc; wchar_t **wargv; if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { fprintf (stderr, "WSAStartup() failed: %lu\n", GetLastError()); return 5; } cmdl = GetCommandLineW (); if (cmdl == NULL) { WSACleanup(); return 2; } wargv = CommandLineToArgvW (cmdl, &wargc); if (wargv == NULL) { WSACleanup(); return 3; } r = 4; if (wargc == 5) { if (wcscmp (wargv[1], L"A") == 0) sc = SVCID_DNS_TYPE_A; else if (wcscmp (wargv[1], L"AAAA") == 0) sc = SVCID_DNS_TYPE_AAAA; else if (wcscmp (wargv[1], L"name") == 0) sc = SVCID_HOSTNAME; else if (wcscmp (wargv[1], L"addr") == 0) sc = SVCID_INET_HOSTADDRBYNAME; else wargc -= 1; if (wcscmp (wargv[4], L"mswdns") == 0) prov = W32_DNS; else if (wcscmp (wargv[4], L"gnunetdns") == 0) prov = GNUNET_NAMESPACE_PROVIDER_DNS; else wargc -= 1; } else if (wargc == 3) { } else { fprintf (stderr, "Usage: %S \n" "record type - one of the following: A | AAAA | name | addr\n" "service name - a string to resolve; \" \" (a space) means 'blank'\n" "NSP library path - path to libw32nsp\n" "NSP id - one of the following: mswdns | gnunetdns\n", wargv[0]); } if (wargc == 5) { HMODULE nsp; nsp = LoadLibraryW (wargv[3]); if (nsp == NULL) { fprintf (stderr, "Failed to load library `%S'\n", wargv[3]); } else { LPNSPSTARTUP startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup"); if (startup == NULL) startup = (LPNSPSTARTUP) GetProcAddress (nsp, "NSPStartup@8"); if (startup != NULL) { NSP_ROUTINE api; api.cbSize = sizeof (api); ret = startup (&prov, &api); if (NO_ERROR != ret) fprintf (stderr, "startup failed: %lu\n", GetLastError ()); else { HANDLE lookup; WSAQUERYSETW search; char buf[4096]; WSAQUERYSETW *result = (WSAQUERYSETW *) buf; DWORD resultsize; DWORD err; memset (&search, 0, sizeof (search)); search.dwSize = sizeof (search); search.lpszServiceInstanceName = (wcscmp (wargv[2], L" ") == 0) ? NULL : wargv[2]; search.lpServiceClassId = ≻ search.lpNSProviderId = &prov; search.dwNameSpace = NS_ALL; ret = api.NSPLookupServiceBegin (&prov, &search, NULL, LUP_RETURN_ALL, &lookup); if (ret != NO_ERROR) { fprintf (stderr, "lookup start failed\n"); } else { resultsize = 4096; ret = api.NSPLookupServiceNext (lookup, LUP_RETURN_ALL, &resultsize, result); err = GetLastError (); if (ret != NO_ERROR) { fprintf (stderr, "lookup next failed: %lu\n", err); } else { int i; printf ("Got result:\n"); printf (" lpszServiceInstanceName: %S\n", result->lpszServiceInstanceName ? result->lpszServiceInstanceName : L"NULL"); if (result->lpServiceClassId) printf (" lpServiceClassId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n", result->lpServiceClassId->Data1, result->lpServiceClassId->Data2, result->lpServiceClassId->Data3, result->lpServiceClassId->Data4[0], result->lpServiceClassId->Data4[1], result->lpServiceClassId->Data4[2], result->lpServiceClassId->Data4[3], result->lpServiceClassId->Data4[4], result->lpServiceClassId->Data4[5], result->lpServiceClassId->Data4[6], result->lpServiceClassId->Data4[7]); else printf (" lpServiceClassId: NULL\n"); if (result->lpVersion) printf (" lpVersion: 0x%08lX, %d\n", result->lpVersion->dwVersion, result->lpVersion->ecHow); else printf (" lpVersion: NULL\n"); printf (" lpszComment: %S\n", result->lpszComment ? result->lpszComment : L"NULL"); printf (" dwNameSpace: %lu\n", result->dwNameSpace); if (result->lpNSProviderId) printf (" lpNSProviderId: { 0x%08lX,0x%04X,0x%04X, { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } }\n", result->lpNSProviderId->Data1, result->lpNSProviderId->Data2, result->lpNSProviderId->Data3, result->lpNSProviderId->Data4[0], result->lpNSProviderId->Data4[1], result->lpNSProviderId->Data4[2], result->lpNSProviderId->Data4[3], result->lpNSProviderId->Data4[4], result->lpNSProviderId->Data4[5], result->lpNSProviderId->Data4[6], result->lpNSProviderId->Data4[7]); else printf (" lpNSProviderId: NULL\n"); printf (" lpszContext: %S\n", result->lpszContext ? result->lpszContext : L"NULL"); printf (" dwNumberOfProtocols: %lu\n", result->dwNumberOfProtocols); printf (" lpszQueryString: %S\n", result->lpszQueryString ? result->lpszQueryString : L"NULL"); printf (" dwNumberOfCsAddrs: %lu\n", result->dwNumberOfCsAddrs); for (i = 0; i < result->dwNumberOfCsAddrs; i++) { switch (result->lpcsaBuffer[i].iSocketType) { case SOCK_STREAM: printf (" %d: iSocketType = SOCK_STREAM\n", i); break; case SOCK_DGRAM: printf (" %d: iSocketType = SOCK_DGRAM\n", i); break; default: printf (" %d: iSocketType = %d\n", i, result->lpcsaBuffer[i].iSocketType); } switch (result->lpcsaBuffer[i].iProtocol) { case IPPROTO_TCP: printf (" %d: iProtocol = IPPROTO_TCP\n", i); break; case IPPROTO_UDP: printf (" %d: iProtocol = IPPROTO_UDP\n", i); break; default: printf (" %d: iProtocol = %d\n", i, result->lpcsaBuffer[i].iProtocol); } switch (result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family) { case AF_INET: printf (" %d: loc family = AF_INET\n", i); break; case AF_INET6: printf (" %d: loc family = AF_INET6\n", i); break; default: printf (" %d: loc family = %hu\n", i, result->lpcsaBuffer[i].LocalAddr.lpSockaddr->sa_family); } switch (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family) { case AF_INET: printf (" %d: rem family = AF_INET\n", i); break; case AF_INET6: printf (" %d: rem family = AF_INET6\n", i); break; default: printf (" %d: rem family = %hu\n", i, result->lpcsaBuffer[i].RemoteAddr.lpSockaddr->sa_family); } char buf[1024]; DWORD buflen = 1024; if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].LocalAddr.lpSockaddr, result->lpcsaBuffer[i].LocalAddr.iSockaddrLength, NULL, buf, &buflen)) printf("\tLocal Address #%d: %s\n", i, buf); else printf("\tLocal Address #%d: Can't convert: %lu\n", i, GetLastError ()); buflen = 1024; if (NO_ERROR == WSAAddressToStringA (result->lpcsaBuffer[i].RemoteAddr.lpSockaddr, result->lpcsaBuffer[i].RemoteAddr.iSockaddrLength, NULL, buf, &buflen)) printf("\tRemote Address #%d: %s\n", i, buf); else printf("\tRemote Address #%d: Can't convert: %lu\n", i, GetLastError ()); } printf (" dwOutputFlags: 0x%08lX\n", result->dwOutputFlags); printf (" lpBlob: 0x%p\n", result->lpBlob); if (result->lpBlob) { struct hostent *he = malloc (result->lpBlob->cbSize); if (he != NULL) { memcpy (he, result->lpBlob->pBlobData, result->lpBlob->cbSize); UnpackHostEnt (he); print_hostent (he); free (he); } } } ret = api.NSPLookupServiceEnd (lookup); if (ret != NO_ERROR) printf ("NSPLookupServiceEnd() failed: %lu\n", GetLastError ()); } api.NSPCleanup (&prov); } } FreeLibrary (nsp); } } else if (wargc == 3) { int s; ADDRINFOW hints; ADDRINFOW *result; ADDRINFOW *pos; memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (0 != (s = GetAddrInfoW (wargv[2], NULL, &hints, &result))) { fprintf (stderr, "Cound not resolve `%S' using GetAddrInfoW: %lu\n", wargv[2], GetLastError ()); } else { for (pos = result; pos != NULL; pos = pos->ai_next) { wchar_t tmpbuf[1024]; DWORD buflen = 1024; if (0 == WSAAddressToStringW (pos->ai_addr, pos->ai_addrlen, NULL, tmpbuf, &buflen)) fprintf (stderr, "Result:\n" " flags: 0x%X\n" " family: 0x%X\n" " socktype: 0x%X\n" " protocol: 0x%X\n" " addrlen: %u\n" " addr: %S\n" " canonname: %S\n", pos->ai_flags, pos->ai_family, pos->ai_socktype, pos->ai_protocol, pos->ai_addrlen, tmpbuf, pos->ai_canonname); else fprintf (stderr, "Result:\n" " flags: 0x%X\n" " family: 0x%X\n" " socktype: 0x%X\n" " protocol: 0x%X\n" " addrlen: %u\n" " addr: %S\n" " canonname: %S\n", pos->ai_flags, pos->ai_family, pos->ai_socktype, pos->ai_protocol, pos->ai_addrlen, L"", pos->ai_canonname); } if (NULL != result) FreeAddrInfoW (result); } } WSACleanup(); return r; } gnunet-0.10.1/src/gns/gnunet-gns-proxy.c0000644000175000017500000023565512274707232015026 00000000000000/* This file is part of GNUnet. (C) 2012-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Martin Schanzenbach * @author Christian Grothoff * @file src/gns/gnunet-gns-proxy.c * @brief HTTP(S) proxy that rewrites URIs and fakes certificats to make GNS work * with legacy browsers * * TODO: * - double-check queueing logic */ #include "platform.h" #include #include #include #include #include #include #if HAVE_GNUTLS_DANE #include #endif #include #include "gnunet_util_lib.h" #include "gnunet_gns_service.h" #include "gnunet_identity_service.h" #include "gns.h" /** * Default Socks5 listen port. */ #define GNUNET_GNS_PROXY_PORT 7777 /** * Maximum supported length for a URI. * Should die. @deprecated */ #define MAX_HTTP_URI_LENGTH 2048 /** * Size of the buffer for the data upload / download. Must be * enough for curl, thus CURL_MAX_WRITE_SIZE is needed here (16k). */ #define IO_BUFFERSIZE CURL_MAX_WRITE_SIZE /** * Size of the read/write buffers for Socks. Uses * 256 bytes for the hostname (at most), plus a few * bytes overhead for the messages. */ #define SOCKS_BUFFERSIZE (256 + 32) /** * Port for plaintext HTTP. */ #define HTTP_PORT 80 /** * Port for HTTPS. */ #define HTTPS_PORT 443 /** * Largest allowed size for a PEM certificate. */ #define MAX_PEM_SIZE (10 * 1024) /** * After how long do we clean up unused MHD SSL/TLS instances? */ #define MHD_CACHE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) /** * After how long do we clean up Socks5 handles that failed to show any activity * with their respective MHD instance? */ #define HTTP_HANDSHAKE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) /** * Log curl error. * * @param level log level * @param fun name of curl_easy-function that gave the error * @param rc return code from curl */ #define LOG_CURL_EASY(level,fun,rc) GNUNET_log(level, _("%s failed at %s:%d: `%s'\n"), fun, __FILE__, __LINE__, curl_easy_strerror (rc)) /* *************** Socks protocol definitions (move to TUN?) ****************** */ /** * Which SOCKS version do we speak? */ #define SOCKS_VERSION_5 0x05 /** * Flag to set for 'no authentication'. */ #define SOCKS_AUTH_NONE 0 /** * Commands in Socks5. */ enum Socks5Commands { /** * Establish TCP/IP stream. */ SOCKS5_CMD_TCP_STREAM = 1, /** * Establish TCP port binding. */ SOCKS5_CMD_TCP_PORT = 2, /** * Establish UDP port binding. */ SOCKS5_CMD_UDP_PORT = 3 }; /** * Address types in Socks5. */ enum Socks5AddressType { /** * IPv4 address. */ SOCKS5_AT_IPV4 = 1, /** * IPv4 address. */ SOCKS5_AT_DOMAINNAME = 3, /** * IPv6 address. */ SOCKS5_AT_IPV6 = 4 }; /** * Status codes in Socks5 response. */ enum Socks5StatusCode { SOCKS5_STATUS_REQUEST_GRANTED = 0, SOCKS5_STATUS_GENERAL_FAILURE = 1, SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE = 2, SOCKS5_STATUS_NETWORK_UNREACHABLE = 3, SOCKS5_STATUS_HOST_UNREACHABLE = 4, SOCKS5_STATUS_CONNECTION_REFUSED_BY_HOST = 5, SOCKS5_STATUS_TTL_EXPIRED = 6, SOCKS5_STATUS_COMMAND_NOT_SUPPORTED = 7, SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED = 8 }; /** * Client hello in Socks5 protocol. */ struct Socks5ClientHelloMessage { /** * Should be #SOCKS_VERSION_5. */ uint8_t version; /** * How many authentication methods does the client support. */ uint8_t num_auth_methods; /* followed by supported authentication methods, 1 byte per method */ }; /** * Server hello in Socks5 protocol. */ struct Socks5ServerHelloMessage { /** * Should be #SOCKS_VERSION_5. */ uint8_t version; /** * Chosen authentication method, for us always #SOCKS_AUTH_NONE, * which skips the authentication step. */ uint8_t auth_method; }; /** * Client socks request in Socks5 protocol. */ struct Socks5ClientRequestMessage { /** * Should be #SOCKS_VERSION_5. */ uint8_t version; /** * Command code, we only uspport #SOCKS5_CMD_TCP_STREAM. */ uint8_t command; /** * Reserved, always zero. */ uint8_t resvd; /** * Address type, an `enum Socks5AddressType`. */ uint8_t addr_type; /* * Followed by either an ip4/ipv6 address or a domain name with a * length field (uint8_t) in front (depending on @e addr_type). * followed by port number in network byte order (uint16_t). */ }; /** * Server response to client requests in Socks5 protocol. */ struct Socks5ServerResponseMessage { /** * Should be #SOCKS_VERSION_5. */ uint8_t version; /** * Status code, an `enum Socks5StatusCode` */ uint8_t reply; /** * Always zero. */ uint8_t reserved; /** * Address type, an `enum Socks5AddressType`. */ uint8_t addr_type; /* * Followed by either an ip4/ipv6 address or a domain name with a * length field (uint8_t) in front (depending on @e addr_type). * followed by port number in network byte order (uint16_t). */ }; /* *********************** Datastructures for HTTP handling ****************** */ /** * A structure for CA cert/key */ struct ProxyCA { /** * The certificate */ gnutls_x509_crt_t cert; /** * The private key */ gnutls_x509_privkey_t key; }; /** * Structure for GNS certificates */ struct ProxyGNSCertificate { /** * The certificate as PEM */ char cert[MAX_PEM_SIZE]; /** * The private key as PEM */ char key[MAX_PEM_SIZE]; }; /** * A structure for all running Httpds */ struct MhdHttpList { /** * DLL for httpds */ struct MhdHttpList *prev; /** * DLL for httpds */ struct MhdHttpList *next; /** * the domain name to server (only important for SSL) */ char *domain; /** * The daemon handle */ struct MHD_Daemon *daemon; /** * Optional proxy certificate used */ struct ProxyGNSCertificate *proxy_cert; /** * The task ID */ GNUNET_SCHEDULER_TaskIdentifier httpd_task; /** * is this an ssl daemon? */ int is_ssl; }; /* ***************** Datastructures for Socks handling **************** */ /** * The socks phases. */ enum SocksPhase { /** * We're waiting to get the client hello. */ SOCKS5_INIT, /** * We're waiting to get the initial request. */ SOCKS5_REQUEST, /** * We are currently resolving the destination. */ SOCKS5_RESOLVING, /** * We're in transfer mode. */ SOCKS5_DATA_TRANSFER, /** * Finish writing the write buffer, then clean up. */ SOCKS5_WRITE_THEN_CLEANUP, /** * Socket has been passed to MHD, do not close it anymore. */ SOCKS5_SOCKET_WITH_MHD, /** * We've finished receiving upload data from MHD. */ SOCKS5_SOCKET_UPLOAD_STARTED, /** * We've finished receiving upload data from MHD. */ SOCKS5_SOCKET_UPLOAD_DONE, /** * We've finished uploading data via CURL and can now download. */ SOCKS5_SOCKET_DOWNLOAD_STARTED, /** * We've finished receiving download data from cURL. */ SOCKS5_SOCKET_DOWNLOAD_DONE }; /** * A structure for socks requests */ struct Socks5Request { /** * DLL. */ struct Socks5Request *next; /** * DLL. */ struct Socks5Request *prev; /** * The client socket */ struct GNUNET_NETWORK_Handle *sock; /** * Handle to GNS lookup, during #SOCKS5_RESOLVING phase. */ struct GNUNET_GNS_LookupRequest *gns_lookup; /** * Client socket read task */ GNUNET_SCHEDULER_TaskIdentifier rtask; /** * Client socket write task */ GNUNET_SCHEDULER_TaskIdentifier wtask; /** * Timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Read buffer */ char rbuf[SOCKS_BUFFERSIZE]; /** * Write buffer */ char wbuf[SOCKS_BUFFERSIZE]; /** * Buffer we use for moving data between MHD and curl (in both directions). */ char io_buf[IO_BUFFERSIZE]; /** * MHD HTTP instance handling this request, NULL for none. */ struct MhdHttpList *hd; /** * MHD response object for this request. */ struct MHD_Response *response; /** * the domain name to server (only important for SSL) */ char *domain; /** * DNS Legacy Host Name as given by GNS, NULL if not given. */ char *leho; /** * Payload of the (last) DANE record encountered. */ char *dane_data; /** * The URL to fetch */ char *url; /** * Handle to cURL */ CURL *curl; /** * HTTP request headers for the curl request. */ struct curl_slist *headers; /** * HTTP response code to give to MHD for the response. */ unsigned int response_code; /** * Number of bytes in @e dane_data. */ size_t dane_data_len; /** * Number of bytes already in read buffer */ size_t rbuf_len; /** * Number of bytes already in write buffer */ size_t wbuf_len; /** * Number of bytes already in the IO buffer. */ size_t io_len; /** * Once known, what's the target address for the connection? */ struct sockaddr_storage destination_address; /** * The socks state */ enum SocksPhase state; /** * Desired destination port. */ uint16_t port; }; /* *********************** Globals **************************** */ /** * The port the proxy is running on (default 7777) */ static unsigned long port = GNUNET_GNS_PROXY_PORT; /** * The CA file (pem) to use for the proxy CA */ static char *cafile_opt; /** * The listen socket of the proxy for IPv4 */ static struct GNUNET_NETWORK_Handle *lsock4; /** * The listen socket of the proxy for IPv6 */ static struct GNUNET_NETWORK_Handle *lsock6; /** * The listen task ID for IPv4 */ static GNUNET_SCHEDULER_TaskIdentifier ltask4; /** * The listen task ID for IPv6 */ static GNUNET_SCHEDULER_TaskIdentifier ltask6; /** * The cURL download task (curl multi API). */ static GNUNET_SCHEDULER_TaskIdentifier curl_download_task; /** * The cURL multi handle */ static CURLM *curl_multi; /** * Handle to the GNS service */ static struct GNUNET_GNS_Handle *gns_handle; /** * DLL for http/https daemons */ static struct MhdHttpList *mhd_httpd_head; /** * DLL for http/https daemons */ static struct MhdHttpList *mhd_httpd_tail; /** * Daemon for HTTP (we have one per SSL certificate, and then one for * all HTTP connections; this is the one for HTTP, not HTTPS). */ static struct MhdHttpList *httpd; /** * DLL of active socks requests. */ static struct Socks5Request *s5r_head; /** * DLL of active socks requests. */ static struct Socks5Request *s5r_tail; /** * The users local GNS master zone */ static struct GNUNET_CRYPTO_EcdsaPublicKey local_gns_zone; /** * The users local shorten zone */ static struct GNUNET_CRYPTO_EcdsaPrivateKey local_shorten_zone; /** * Is shortening enabled? */ static int do_shorten; /** * The CA for SSL certificate generation */ static struct ProxyCA proxy_ca; /** * Response we return on cURL failures. */ static struct MHD_Response *curl_failure_response; /** * Connection to identity service. */ static struct GNUNET_IDENTITY_Handle *identity; /** * Request for our ego. */ static struct GNUNET_IDENTITY_Operation *id_op; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /* ************************* Global helpers ********************* */ /** * Run MHD now, we have extra data ready for the callback. * * @param hd the daemon to run now. */ static void run_mhd_now (struct MhdHttpList *hd); /** * Clean up s5r handles. * * @param s5r the handle to destroy */ static void cleanup_s5r (struct Socks5Request *s5r) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up socks request\n"); if (NULL != s5r->curl) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up cURL handle\n"); curl_multi_remove_handle (curl_multi, s5r->curl); curl_easy_cleanup (s5r->curl); s5r->curl = NULL; } curl_slist_free_all (s5r->headers); if ( (NULL != s5r->response) && (curl_failure_response != s5r->response) ) MHD_destroy_response (s5r->response); if (GNUNET_SCHEDULER_NO_TASK != s5r->rtask) GNUNET_SCHEDULER_cancel (s5r->rtask); if (GNUNET_SCHEDULER_NO_TASK != s5r->timeout_task) GNUNET_SCHEDULER_cancel (s5r->timeout_task); if (GNUNET_SCHEDULER_NO_TASK != s5r->wtask) GNUNET_SCHEDULER_cancel (s5r->wtask); if (NULL != s5r->gns_lookup) GNUNET_GNS_lookup_cancel (s5r->gns_lookup); if (NULL != s5r->sock) { if (SOCKS5_SOCKET_WITH_MHD <= s5r->state) GNUNET_NETWORK_socket_free_memory_only_ (s5r->sock); else GNUNET_NETWORK_socket_close (s5r->sock); } GNUNET_CONTAINER_DLL_remove (s5r_head, s5r_tail, s5r); GNUNET_free_non_null (s5r->domain); GNUNET_free_non_null (s5r->leho); GNUNET_free_non_null (s5r->url); GNUNET_free_non_null (s5r->dane_data); GNUNET_free (s5r); } /* ************************* HTTP handling with cURL *********************** */ /** * Callback for MHD response generation. This function is called from * MHD whenever MHD expects to get data back. Copies data from the * io_buf, if available. * * @param cls closure with our `struct Socks5Request` * @param pos in buffer * @param buf where to copy data * @param max available space in @a buf * @return number of bytes written to @a buf */ static ssize_t mhd_content_cb (void *cls, uint64_t pos, char* buf, size_t max) { struct Socks5Request *s5r = cls; size_t bytes_to_copy; if ( (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) || (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) ) { /* we're still not done with the upload, do not yet start the download, the IO buffer is still full with upload data. */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pausing MHD download, not yet ready for download\n"); return 0; /* not yet ready for data download */ } bytes_to_copy = GNUNET_MIN (max, s5r->io_len); if ( (0 == bytes_to_copy) && (SOCKS5_SOCKET_DOWNLOAD_DONE != s5r->state) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pausing MHD download, no data available\n"); return 0; /* more data later */ } if ( (0 == bytes_to_copy) && (SOCKS5_SOCKET_DOWNLOAD_DONE == s5r->state) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Completed MHD download\n"); return MHD_CONTENT_READER_END_OF_STREAM; } memcpy (buf, s5r->io_buf, bytes_to_copy); memmove (s5r->io_buf, &s5r->io_buf[bytes_to_copy], s5r->io_len - bytes_to_copy); s5r->io_len -= bytes_to_copy; if (NULL != s5r->curl) curl_easy_pause (s5r->curl, CURLPAUSE_CONT); return bytes_to_copy; } /** * Check that the website has presented us with a valid SSL certificate. * The certificate must either match the domain name or the LEHO name * (or, if available, the TLSA record). * * @param s5r request to check for. * @return #GNUNET_OK if the certificate is valid */ static int check_ssl_certificate (struct Socks5Request *s5r) { unsigned int cert_list_size; const gnutls_datum_t *chainp; const struct curl_tlssessioninfo *tlsinfo; char certdn[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 3]; size_t size; gnutls_x509_crt_t x509_cert; int rc; const char *name; if (CURLE_OK != curl_easy_getinfo (s5r->curl, CURLINFO_TLS_SESSION, (struct curl_slist **) &tlsinfo)) return GNUNET_SYSERR; if (CURLSSLBACKEND_GNUTLS != tlsinfo->backend) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported CURL SSL backend %d\n"), tlsinfo->backend); return GNUNET_SYSERR; } chainp = gnutls_certificate_get_peers (tlsinfo->internals, &cert_list_size); if ( (! chainp) || (0 == cert_list_size) ) return GNUNET_SYSERR; size = sizeof (certdn); /* initialize an X.509 certificate structure. */ gnutls_x509_crt_init (&x509_cert); gnutls_x509_crt_import (x509_cert, chainp, GNUTLS_X509_FMT_DER); if (0 != (rc = gnutls_x509_crt_get_dn_by_oid (x509_cert, GNUTLS_OID_X520_COMMON_NAME, 0, /* the first and only one */ 0 /* no DER encoding */, certdn, &size))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to fetch CN from cert: %s\n"), gnutls_strerror(rc)); gnutls_x509_crt_deinit (x509_cert); return GNUNET_SYSERR; } /* check for TLSA/DANE records */ #if HAVE_GNUTLS_DANE if (NULL != s5r->dane_data) { char *dd[] = { s5r->dane_data, NULL }; int dlen[] = { s5r->dane_data_len, 0}; dane_state_t dane_state; dane_query_t dane_query; unsigned int verify; /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */ if (0 != (rc = dane_state_init (&dane_state, #ifdef DANE_F_IGNORE_DNSSEC DANE_F_IGNORE_DNSSEC | #endif DANE_F_IGNORE_LOCAL_RESOLVER))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to initialize DANE: %s\n"), dane_strerror(rc)); gnutls_x509_crt_deinit (x509_cert); return GNUNET_SYSERR; } if (0 != (rc = dane_raw_tlsa (dane_state, &dane_query, dd, dlen, GNUNET_YES, GNUNET_NO))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to parse DANE record: %s\n"), dane_strerror(rc)); dane_state_deinit (dane_state); gnutls_x509_crt_deinit (x509_cert); return GNUNET_SYSERR; } if (0 != (rc = dane_verify_crt_raw (dane_state, chainp, cert_list_size, gnutls_certificate_type_get (tlsinfo->internals), dane_query, 0, 0, &verify))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to verify TLS connection using DANE: %s\n"), dane_strerror(rc)); dane_query_deinit (dane_query); dane_state_deinit (dane_state); gnutls_x509_crt_deinit (x509_cert); return GNUNET_SYSERR; } if (0 != verify) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed DANE verification failed with GnuTLS verify status code: %u\n"), verify); dane_query_deinit (dane_query); dane_state_deinit (dane_state); gnutls_x509_crt_deinit (x509_cert); return GNUNET_SYSERR; } dane_query_deinit (dane_query); dane_state_deinit (dane_state); /* success! */ } else #endif { /* try LEHO or ordinary domain name X509 verification */ name = s5r->domain; if (NULL != s5r->leho) name = s5r->leho; if (NULL != name) { if (0 == (rc = gnutls_x509_crt_check_hostname (x509_cert, name))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("SSL certificate subject name (%s) does not match `%s'\n"), certdn, name); gnutls_x509_crt_deinit (x509_cert); return GNUNET_SYSERR; } } else { /* we did not even have the domain name!? */ GNUNET_break (0); return GNUNET_SYSERR; } } gnutls_x509_crt_deinit (x509_cert); return GNUNET_OK; } /** * We're getting an HTTP response header from cURL. Convert it to the * MHD response headers. Mostly copies the headers, but makes special * adjustments to "Set-Cookie" and "Location" headers as those may need * to be changed from the LEHO to the domain the browser expects. * * @param buffer curl buffer with a single line of header data; not 0-terminated! * @param size curl blocksize * @param nmemb curl blocknumber * @param cls our `struct Socks5Request *` * @return size of processed bytes */ static size_t curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) { struct Socks5Request *s5r = cls; size_t bytes = size * nmemb; char *ndup; const char *hdr_type; const char *cookie_domain; char *hdr_val; long resp_code; char *new_cookie_hdr; char *new_location; size_t offset; size_t delta_cdomain; int domain_matched; char *tok; if (NULL == s5r->response) { /* first, check SSL certificate */ if ( (HTTPS_PORT == s5r->port) && (GNUNET_OK != check_ssl_certificate (s5r)) ) return 0; GNUNET_break (CURLE_OK == curl_easy_getinfo (s5r->curl, CURLINFO_RESPONSE_CODE, &resp_code)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating MHD response with code %d\n", (int) resp_code); s5r->response_code = resp_code; s5r->response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, IO_BUFFERSIZE, &mhd_content_cb, s5r, NULL); if (NULL != s5r->leho) { char *cors_hdr; GNUNET_asprintf (&cors_hdr, (HTTPS_PORT == s5r->port) ? "https://%s" : "http://%s", s5r->leho); GNUNET_break (MHD_YES == MHD_add_response_header (s5r->response, MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, cors_hdr)); GNUNET_free (cors_hdr); } /* force connection to be closed after each request, as we do not support HTTP pipelining */ GNUNET_break (MHD_YES == MHD_add_response_header (s5r->response, MHD_HTTP_HEADER_CONNECTION, "close")); } ndup = GNUNET_strndup (buffer, bytes); hdr_type = strtok (ndup, ":"); if (NULL == hdr_type) { GNUNET_free (ndup); return bytes; } hdr_val = strtok (NULL, ""); if (NULL == hdr_val) { GNUNET_free (ndup); return bytes; } if (' ' == *hdr_val) hdr_val++; /* custom logic for certain header types */ new_cookie_hdr = NULL; if ( (NULL != s5r->leho) && (0 == strcasecmp (hdr_type, MHD_HTTP_HEADER_SET_COOKIE)) ) { new_cookie_hdr = GNUNET_malloc (strlen (hdr_val) + strlen (s5r->domain) + 1); offset = 0; domain_matched = GNUNET_NO; /* make sure we match domain at most once */ for (tok = strtok (hdr_val, ";"); NULL != tok; tok = strtok (NULL, ";")) { if ( (0 == strncasecmp (tok, " domain", strlen (" domain"))) && (GNUNET_NO == domain_matched) ) { domain_matched = GNUNET_YES; cookie_domain = tok + strlen (" domain") + 1; if (strlen (cookie_domain) < strlen (s5r->leho)) { delta_cdomain = strlen (s5r->leho) - strlen (cookie_domain); if (0 == strcasecmp (cookie_domain, s5r->leho + delta_cdomain)) { offset += sprintf (new_cookie_hdr + offset, " domain=%s;", s5r->domain); continue; } } else if (0 == strcmp (cookie_domain, s5r->leho)) { offset += sprintf (new_cookie_hdr + offset, " domain=%s;", s5r->domain); continue; } GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Cookie domain `%s' supplied by server is invalid\n"), tok); } memcpy (new_cookie_hdr + offset, tok, strlen (tok)); offset += strlen (tok); new_cookie_hdr[offset++] = ';'; } hdr_val = new_cookie_hdr; } new_location = NULL; if (0 == strcasecmp (MHD_HTTP_HEADER_LOCATION, hdr_type)) { char *leho_host; GNUNET_asprintf (&leho_host, (HTTPS_PORT != s5r->port) ? "http://%s" : "https://%s", s5r->leho); if (0 == strncmp (leho_host, hdr_val, strlen (leho_host))) { GNUNET_asprintf (&new_location, "%s%s%s", (HTTPS_PORT != s5r->port) ? "http://" : "https://", s5r->domain, hdr_val + strlen (leho_host)); hdr_val = new_location; } GNUNET_free (leho_host); } /* MHD does not allow certain characters in values, remove those */ if (NULL != (tok = strchr (hdr_val, '\n'))) *tok = '\0'; if (NULL != (tok = strchr (hdr_val, '\r'))) *tok = '\0'; if (NULL != (tok = strchr (hdr_val, '\t'))) *tok = '\0'; if (0 != strlen (hdr_val)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding header %s: %s to MHD response\n", hdr_type, hdr_val); GNUNET_break (MHD_YES == MHD_add_response_header (s5r->response, hdr_type, hdr_val)); } GNUNET_free (ndup); GNUNET_free_non_null (new_cookie_hdr); GNUNET_free_non_null (new_location); return bytes; } /** * Handle response payload data from cURL. Copies it into our `io_buf` to make * it available to MHD. * * @param ptr pointer to the data * @param size number of blocks of data * @param nmemb blocksize * @param ctx our `struct Socks5Request *` * @return number of bytes handled */ static size_t curl_download_cb (void *ptr, size_t size, size_t nmemb, void* ctx) { struct Socks5Request *s5r = ctx; size_t total = size * nmemb; if ( (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) || (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) ) { /* we're still not done with the upload, do not yet start the download, the IO buffer is still full with upload data. */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pausing CURL download, waiting for UPLOAD to finish\n"); return CURL_WRITEFUNC_PAUSE; /* not yet ready for data download */ } if (sizeof (s5r->io_buf) - s5r->io_len < total) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pausing CURL download, not enough space\n"); return CURL_WRITEFUNC_PAUSE; /* not enough space */ } memcpy (&s5r->io_buf[s5r->io_len], ptr, total); s5r->io_len += total; if (s5r->io_len == total) run_mhd_now (s5r->hd); return total; } /** * cURL callback for uploaded (PUT/POST) data. Copies it into our `io_buf` * to make it available to MHD. * * @param buf where to write the data * @param size number of bytes per member * @param nmemb number of members available in @a buf * @param cls our `struct Socks5Request` that generated the data * @return number of bytes copied to @a buf */ static size_t curl_upload_cb (void *buf, size_t size, size_t nmemb, void *cls) { struct Socks5Request *s5r = cls; size_t len = size * nmemb; size_t to_copy; if ( (0 == s5r->io_len) && (SOCKS5_SOCKET_UPLOAD_DONE != s5r->state) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pausing CURL UPLOAD, need more data\n"); return CURL_READFUNC_PAUSE; } if ( (0 == s5r->io_len) && (SOCKS5_SOCKET_UPLOAD_DONE == s5r->state) ) { s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Completed CURL UPLOAD\n"); return 0; /* upload finished, can now download */ } if ( (SOCKS5_SOCKET_UPLOAD_STARTED != s5r->state) || (SOCKS5_SOCKET_UPLOAD_DONE != s5r->state) ) { GNUNET_break (0); return CURL_READFUNC_ABORT; } to_copy = GNUNET_MIN (s5r->io_len, len); memcpy (buf, s5r->io_buf, to_copy); memmove (s5r->io_buf, &s5r->io_buf[to_copy], s5r->io_len - to_copy); s5r->io_len -= to_copy; if (s5r->io_len + to_copy == sizeof (s5r->io_buf)) run_mhd_now (s5r->hd); /* got more space for upload now */ return to_copy; } /* ************************** main loop of cURL interaction ****************** */ /** * Task that is run when we are ready to receive more data * from curl * * @param cls closure * @param tc task context */ static void curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Ask cURL for the select() sets and schedule cURL operations. */ static void curl_download_prepare () { CURLMcode mret; fd_set rs; fd_set ws; fd_set es; int max; struct GNUNET_NETWORK_FDSet *grs; struct GNUNET_NETWORK_FDSet *gws; long to; struct GNUNET_TIME_Relative rtime; if (GNUNET_SCHEDULER_NO_TASK != curl_download_task) { GNUNET_SCHEDULER_cancel (curl_download_task); curl_download_task = GNUNET_SCHEDULER_NO_TASK; } max = -1; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); if (CURLM_OK != (mret = curl_multi_fdset (curl_multi, &rs, &ws, &es, &max))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s failed at %s:%d: `%s'\n", "curl_multi_fdset", __FILE__, __LINE__, curl_multi_strerror (mret)); return; } to = -1; GNUNET_break (CURLM_OK == curl_multi_timeout (curl_multi, &to)); if (-1 == to) rtime = GNUNET_TIME_UNIT_FOREVER_REL; else rtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to); if (-1 != max) { grs = GNUNET_NETWORK_fdset_create (); gws = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); curl_download_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, rtime, grs, gws, &curl_task_download, curl_multi); GNUNET_NETWORK_fdset_destroy (gws); GNUNET_NETWORK_fdset_destroy (grs); } else { curl_download_task = GNUNET_SCHEDULER_add_delayed (rtime, &curl_task_download, curl_multi); } } /** * Task that is run when we are ready to receive more data from curl. * * @param cls closure, NULL * @param tc task context */ static void curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int running; int msgnum; struct CURLMsg *msg; CURLMcode mret; struct Socks5Request *s5r; curl_download_task = GNUNET_SCHEDULER_NO_TASK; do { running = 0; mret = curl_multi_perform (curl_multi, &running); while (NULL != (msg = curl_multi_info_read (curl_multi, &msgnum))) { GNUNET_break (CURLE_OK == curl_easy_getinfo (msg->easy_handle, CURLINFO_PRIVATE, (char **) &s5r )); if (NULL == s5r) { GNUNET_break (0); continue; } switch (msg->msg) { case CURLMSG_NONE: /* documentation says this is not used */ GNUNET_break (0); break; case CURLMSG_DONE: switch (msg->data.result) { case CURLE_OK: case CURLE_GOT_NOTHING: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CURL download completed.\n"); s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE; run_mhd_now (s5r->hd); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Download curl failed: %s\n", curl_easy_strerror (msg->data.result)); /* FIXME: indicate error somehow? close MHD connection badly as well? */ s5r->state = SOCKS5_SOCKET_DOWNLOAD_DONE; run_mhd_now (s5r->hd); break; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up cURL handle\n"); curl_multi_remove_handle (curl_multi, s5r->curl); curl_easy_cleanup (s5r->curl); s5r->curl = NULL; if (NULL == s5r->response) s5r->response = curl_failure_response; break; case CURLMSG_LAST: /* documentation says this is not used */ GNUNET_break (0); break; default: /* unexpected status code */ GNUNET_break (0); break; } }; } while (mret == CURLM_CALL_MULTI_PERFORM); if (CURLM_OK != mret) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_multi_strerror (mret)); if (0 == running) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending cURL multi loop, no more events pending\n"); return; /* nothing more in progress */ } curl_download_prepare (); } /* ********************************* MHD response generation ******************* */ /** * Read HTTP request header field from the request. Copies the fields * over to the 'headers' that will be given to curl. However, 'Host' * is substituted with the LEHO if present. We also change the * 'Connection' header value to "close" as the proxy does not support * pipelining. * * @param cls our `struct Socks5Request` * @param kind value kind * @param key field key * @param value field value * @return MHD_YES to continue to iterate */ static int con_val_iter (void *cls, enum MHD_ValueKind kind, const char *key, const char *value) { struct Socks5Request *s5r = cls; char *hdr; if ( (0 == strcasecmp (MHD_HTTP_HEADER_HOST, key)) && (NULL != s5r->leho) ) value = s5r->leho; if (0 == strcasecmp (MHD_HTTP_HEADER_CONNECTION, key)) value = "Close"; GNUNET_asprintf (&hdr, "%s: %s", key, value); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding HEADER `%s' to HTTP request\n", hdr); s5r->headers = curl_slist_append (s5r->headers, hdr); GNUNET_free (hdr); return MHD_YES; } /** * Main MHD callback for handling requests. * * @param cls unused * @param con MHD connection handle * @param url the url in the request * @param meth the HTTP method used ("GET", "PUT", etc.) * @param ver the HTTP version string (i.e. "HTTP/1.1") * @param upload_data the data being uploaded (excluding HEADERS, * for a POST that fits into memory and that is encoded * with a supported encoding, the POST data will NOT be * given in upload_data and is instead available as * part of MHD_get_connection_values; very large POST * data *will* be made available incrementally in * upload_data) * @param upload_data_size set initially to the size of the * @a upload_data provided; the method must update this * value to the number of bytes NOT processed; * @param con_cls pointer to location where we store the 'struct Request' * @return MHD_YES if the connection was handled successfully, * MHD_NO if the socket must be closed due to a serious * error while handling the request */ static int create_response (void *cls, struct MHD_Connection *con, const char *url, const char *meth, const char *ver, const char *upload_data, size_t *upload_data_size, void **con_cls) { struct Socks5Request *s5r = *con_cls; char *curlurl; char ipstring[INET6_ADDRSTRLEN]; char ipaddr[INET6_ADDRSTRLEN + 2]; const struct sockaddr *sa; const struct sockaddr_in *s4; const struct sockaddr_in6 *s6; uint16_t port; size_t left; if (NULL == s5r) { GNUNET_break (0); return MHD_NO; } if ( (NULL == s5r->curl) && (SOCKS5_SOCKET_WITH_MHD == s5r->state) ) { /* first time here, initialize curl handle */ sa = (const struct sockaddr *) &s5r->destination_address; switch (sa->sa_family) { case AF_INET: s4 = (const struct sockaddr_in *) &s5r->destination_address; if (NULL == inet_ntop (AF_INET, &s4->sin_addr, ipstring, sizeof (ipstring))) { GNUNET_break (0); return MHD_NO; } GNUNET_snprintf (ipaddr, sizeof (ipaddr), "%s", ipstring); port = ntohs (s4->sin_port); break; case AF_INET6: s6 = (const struct sockaddr_in6 *) &s5r->destination_address; if (NULL == inet_ntop (AF_INET6, &s6->sin6_addr, ipstring, sizeof (ipstring))) { GNUNET_break (0); return MHD_NO; } GNUNET_snprintf (ipaddr, sizeof (ipaddr), "[%s]", ipstring); port = ntohs (s6->sin6_port); break; default: GNUNET_break (0); return MHD_NO; } s5r->curl = curl_easy_init (); if (NULL == s5r->curl) return MHD_queue_response (con, MHD_HTTP_INTERNAL_SERVER_ERROR, curl_failure_response); curl_easy_setopt (s5r->curl, CURLOPT_HEADERFUNCTION, &curl_check_hdr); curl_easy_setopt (s5r->curl, CURLOPT_HEADERDATA, s5r); curl_easy_setopt (s5r->curl, CURLOPT_FOLLOWLOCATION, 0); curl_easy_setopt (s5r->curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); curl_easy_setopt (s5r->curl, CURLOPT_CONNECTTIMEOUT, 600L); curl_easy_setopt (s5r->curl, CURLOPT_TIMEOUT, 600L); curl_easy_setopt (s5r->curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt (s5r->curl, CURLOPT_HTTP_CONTENT_DECODING, 0); curl_easy_setopt (s5r->curl, CURLOPT_HTTP_TRANSFER_DECODING, 0); curl_easy_setopt (s5r->curl, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt (s5r->curl, CURLOPT_PRIVATE, s5r); curl_easy_setopt (s5r->curl, CURLOPT_VERBOSE, 0); GNUNET_asprintf (&curlurl, (HTTPS_PORT != s5r->port) ? "http://%s:%d%s" : "https://%s:%d%s", ipaddr, port, s5r->url); curl_easy_setopt (s5r->curl, CURLOPT_URL, curlurl); GNUNET_free (curlurl); if (0 == strcasecmp (meth, MHD_HTTP_METHOD_PUT)) { s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED; curl_easy_setopt (s5r->curl, CURLOPT_UPLOAD, 1); curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r); curl_easy_setopt (s5r->curl, CURLOPT_READFUNCTION, &curl_upload_cb); curl_easy_setopt (s5r->curl, CURLOPT_READDATA, s5r); } else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) { s5r->state = SOCKS5_SOCKET_UPLOAD_STARTED; curl_easy_setopt (s5r->curl, CURLOPT_POST, 1); curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r); curl_easy_setopt (s5r->curl, CURLOPT_READFUNCTION, &curl_upload_cb); curl_easy_setopt (s5r->curl, CURLOPT_READDATA, s5r); } else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_HEAD)) { s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; curl_easy_setopt (s5r->curl, CURLOPT_NOBODY, 1); } else if (0 == strcasecmp (meth, MHD_HTTP_METHOD_GET)) { s5r->state = SOCKS5_SOCKET_DOWNLOAD_STARTED; curl_easy_setopt (s5r->curl, CURLOPT_HTTPGET, 1); curl_easy_setopt (s5r->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); curl_easy_setopt (s5r->curl, CURLOPT_WRITEDATA, s5r); } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Unsupported HTTP method `%s'\n"), meth); curl_easy_cleanup (s5r->curl); s5r->curl = NULL; return MHD_NO; } if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_0)) { curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); } else if (0 == strcasecmp (ver, MHD_HTTP_VERSION_1_1)) { curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); } else { curl_easy_setopt (s5r->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_NONE); } if (HTTPS_PORT == s5r->port) { curl_easy_setopt (s5r->curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYPEER, 1L); /* Disable cURL checking the hostname, as we will check ourselves as only we have the domain name or the LEHO or the DANE record */ curl_easy_setopt (s5r->curl, CURLOPT_SSL_VERIFYHOST, 0L); } else { curl_easy_setopt (s5r->curl, CURLOPT_USE_SSL, CURLUSESSL_NONE); } if (CURLM_OK != curl_multi_add_handle (curl_multi, s5r->curl)) { GNUNET_break (0); curl_easy_cleanup (s5r->curl); s5r->curl = NULL; return MHD_NO; } MHD_get_connection_values (con, MHD_HEADER_KIND, &con_val_iter, s5r); curl_easy_setopt (s5r->curl, CURLOPT_HTTPHEADER, s5r->headers); curl_download_prepare (); return MHD_YES; } /* continuing to process request */ if (0 != *upload_data_size) { left = GNUNET_MIN (*upload_data_size, sizeof (s5r->io_buf) - s5r->io_len); memcpy (&s5r->io_buf[s5r->io_len], upload_data, left); s5r->io_len += left; *upload_data_size -= left; GNUNET_assert (NULL != s5r->curl); curl_easy_pause (s5r->curl, CURLPAUSE_CONT); curl_download_prepare (); return MHD_YES; } if (SOCKS5_SOCKET_UPLOAD_STARTED == s5r->state) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished processing UPLOAD\n"); s5r->state = SOCKS5_SOCKET_UPLOAD_DONE; } if (NULL == s5r->response) return MHD_YES; /* too early to queue response, did not yet get headers from cURL */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing response with MHD\n"); return MHD_queue_response (con, s5r->response_code, s5r->response); } /* ******************** MHD HTTP setup and event loop ******************** */ /** * Function called when MHD decides that we are done with a connection. * * @param cls NULL * @param connection connection handle * @param con_cls value as set by the last call to * the MHD_AccessHandlerCallback, should be our `struct Socks5Request` * @param toe reason for request termination (ignored) */ static void mhd_completed_cb (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe) { struct Socks5Request *s5r = *con_cls; if (NULL == s5r) return; if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "MHD encountered error handling request: %d\n", toe); cleanup_s5r (s5r); *con_cls = NULL; } /** * Function called when MHD first processes an incoming connection. * Gives us the respective URI information. * * We use this to associate the `struct MHD_Connection` with our * internal `struct Socks5Request` data structure (by checking * for matching sockets). * * @param cls the HTTP server handle (a `struct MhdHttpList`) * @param url the URL that is being requested * @param connection MHD connection object for the request * @return the `struct Socks5Request` that this @a connection is for */ static void * mhd_log_callback (void *cls, const char *url, struct MHD_Connection *connection) { struct Socks5Request *s5r; const union MHD_ConnectionInfo *ci; int sock; ci = MHD_get_connection_info (connection, MHD_CONNECTION_INFO_CONNECTION_FD); if (NULL == ci) { GNUNET_break (0); return NULL; } sock = ci->connect_fd; for (s5r = s5r_head; NULL != s5r; s5r = s5r->next) { if (GNUNET_NETWORK_get_fd (s5r->sock) == sock) { if (NULL != s5r->url) { GNUNET_break (0); return NULL; } s5r->url = GNUNET_strdup (url); GNUNET_SCHEDULER_cancel (s5r->timeout_task); s5r->timeout_task = GNUNET_SCHEDULER_NO_TASK; return s5r; } } GNUNET_break (0); return NULL; } /** * Kill the given MHD daemon. * * @param hd daemon to stop */ static void kill_httpd (struct MhdHttpList *hd) { GNUNET_CONTAINER_DLL_remove (mhd_httpd_head, mhd_httpd_tail, hd); GNUNET_free_non_null (hd->domain); MHD_stop_daemon (hd->daemon); if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task) { GNUNET_SCHEDULER_cancel (hd->httpd_task); hd->httpd_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free_non_null (hd->proxy_cert); if (hd == httpd) httpd = NULL; GNUNET_free (hd); } /** * Task run whenever HTTP server is idle for too long. Kill it. * * @param cls the `struct MhdHttpList *` * @param tc sched context */ static void kill_httpd_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MhdHttpList *hd = cls; hd->httpd_task = GNUNET_SCHEDULER_NO_TASK; kill_httpd (hd); } /** * Task run whenever HTTP server operations are pending. * * @param cls the `struct MhdHttpList *` of the daemon that is being run * @param tc sched context */ static void do_httpd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Schedule MHD. This function should be called initially when an * MHD is first getting its client socket, and will then automatically * always be called later whenever there is work to be done. * * @param hd the daemon to schedule */ static void schedule_httpd (struct MhdHttpList *hd) { fd_set rs; fd_set ws; fd_set es; struct GNUNET_NETWORK_FDSet *wrs; struct GNUNET_NETWORK_FDSet *wws; int max; int haveto; MHD_UNSIGNED_LONG_LONG timeout; struct GNUNET_TIME_Relative tv; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); max = -1; if (MHD_YES != MHD_get_fdset (hd->daemon, &rs, &ws, &es, &max)) { kill_httpd (hd); return; } haveto = MHD_get_timeout (hd->daemon, &timeout); if (MHD_YES == haveto) tv.rel_value_us = (uint64_t) timeout * 1000LL; else tv = GNUNET_TIME_UNIT_FOREVER_REL; if (-1 != max) { wrs = GNUNET_NETWORK_fdset_create (); wws = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); } else { wrs = NULL; wws = NULL; } if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task) GNUNET_SCHEDULER_cancel (hd->httpd_task); if ( (MHD_YES != haveto) && (-1 == max) && (hd != httpd) ) { /* daemon is idle, kill after timeout */ hd->httpd_task = GNUNET_SCHEDULER_add_delayed (MHD_CACHE_TIMEOUT, &kill_httpd_task, hd); } else { hd->httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, tv, wrs, wws, &do_httpd, hd); } if (NULL != wrs) GNUNET_NETWORK_fdset_destroy (wrs); if (NULL != wws) GNUNET_NETWORK_fdset_destroy (wws); } /** * Task run whenever HTTP server operations are pending. * * @param cls the `struct MhdHttpList` of the daemon that is being run * @param tc scheduler context */ static void do_httpd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MhdHttpList *hd = cls; hd->httpd_task = GNUNET_SCHEDULER_NO_TASK; MHD_run (hd->daemon); schedule_httpd (hd); } /** * Run MHD now, we have extra data ready for the callback. * * @param hd the daemon to run now. */ static void run_mhd_now (struct MhdHttpList *hd) { if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task) GNUNET_SCHEDULER_cancel (hd->httpd_task); hd->httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, hd); } /** * Read file in filename * * @param filename file to read * @param size pointer where filesize is stored * @return NULL on error */ static void* load_file (const char* filename, unsigned int* size) { void *buffer; uint64_t fsize; if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fsize, GNUNET_YES, GNUNET_YES)) return NULL; if (fsize > MAX_PEM_SIZE) return NULL; *size = (unsigned int) fsize; buffer = GNUNET_malloc (*size); if (fsize != GNUNET_DISK_fn_read (filename, buffer, (size_t) fsize)) { GNUNET_free (buffer); return NULL; } return buffer; } /** * Load PEM key from file * * @param key where to store the data * @param keyfile path to the PEM file * @return #GNUNET_OK on success */ static int load_key_from_file (gnutls_x509_privkey_t key, const char* keyfile) { gnutls_datum_t key_data; int ret; key_data.data = load_file (keyfile, &key_data.size); if (NULL == key_data.data) return GNUNET_SYSERR; ret = gnutls_x509_privkey_import (key, &key_data, GNUTLS_X509_FMT_PEM); if (GNUTLS_E_SUCCESS != ret) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to import private key from file `%s'\n"), keyfile); } GNUNET_free_non_null (key_data.data); return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK; } /** * Load cert from file * * @param crt struct to store data in * @param certfile path to pem file * @return #GNUNET_OK on success */ static int load_cert_from_file (gnutls_x509_crt_t crt, const char* certfile) { gnutls_datum_t cert_data; int ret; cert_data.data = load_file (certfile, &cert_data.size); if (NULL == cert_data.data) return GNUNET_SYSERR; ret = gnutls_x509_crt_import (crt, &cert_data, GNUTLS_X509_FMT_PEM); if (GNUTLS_E_SUCCESS != ret) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to import certificate %s\n"), certfile); } GNUNET_free_non_null (cert_data.data); return (GNUTLS_E_SUCCESS != ret) ? GNUNET_SYSERR : GNUNET_OK; } /** * Generate new certificate for specific name * * @param name the subject name to generate a cert for * @return a struct holding the PEM data, NULL on error */ static struct ProxyGNSCertificate * generate_gns_certificate (const char *name) { unsigned int serial; size_t key_buf_size; size_t cert_buf_size; gnutls_x509_crt_t request; time_t etime; struct tm *tm_data; struct ProxyGNSCertificate *pgc; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Generating TLS/SSL certificate for `%s'\n", name); GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&request)); GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_key (request, proxy_ca.key)); pgc = GNUNET_new (struct ProxyGNSCertificate); gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_COUNTRY_NAME, 0, "ZZ", 2); gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, "GNU Name System", 4); gnutls_x509_crt_set_dn_by_oid (request, GNUTLS_OID_X520_COMMON_NAME, 0, name, strlen (name)); GNUNET_break (GNUTLS_E_SUCCESS == gnutls_x509_crt_set_version (request, 3)); gnutls_rnd (GNUTLS_RND_NONCE, &serial, sizeof (serial)); gnutls_x509_crt_set_serial (request, &serial, sizeof (serial)); etime = time (NULL); tm_data = localtime (&etime); gnutls_x509_crt_set_activation_time (request, etime); tm_data->tm_year++; etime = mktime (tm_data); gnutls_x509_crt_set_expiration_time (request, etime); gnutls_x509_crt_sign (request, proxy_ca.cert, proxy_ca.key); key_buf_size = sizeof (pgc->key); cert_buf_size = sizeof (pgc->cert); gnutls_x509_crt_export (request, GNUTLS_X509_FMT_PEM, pgc->cert, &cert_buf_size); gnutls_x509_privkey_export (proxy_ca.key, GNUTLS_X509_FMT_PEM, pgc->key, &key_buf_size); gnutls_x509_crt_deinit (request); return pgc; } /** * Function called by MHD with errors, suppresses them all. * * @param cls closure * @param fm format string (`printf()`-style) * @param ap arguments to @a fm */ static void mhd_error_log_callback (void *cls, const char *fm, va_list ap) { /* do nothing */ } /** * Lookup (or create) an SSL MHD instance for a particular domain. * * @param domain the domain the SSL daemon has to serve * @return NULL on error */ static struct MhdHttpList * lookup_ssl_httpd (const char* domain) { struct MhdHttpList *hd; struct ProxyGNSCertificate *pgc; if (NULL == domain) { GNUNET_break (0); return NULL; } for (hd = mhd_httpd_head; NULL != hd; hd = hd->next) if ( (NULL != hd->domain) && (0 == strcmp (hd->domain, domain)) ) return hd; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting fresh MHD HTTPS instance for domain `%s'\n", domain); pgc = generate_gns_certificate (domain); hd = GNUNET_new (struct MhdHttpList); hd->is_ssl = GNUNET_YES; hd->domain = GNUNET_strdup (domain); hd->proxy_cert = pgc; hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | MHD_USE_NO_LISTEN_SOCKET, 0, NULL, NULL, &create_response, hd, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb, NULL, MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL, MHD_OPTION_EXTERNAL_LOGGER, &mhd_error_log_callback, NULL, MHD_OPTION_HTTPS_MEM_KEY, pgc->key, MHD_OPTION_HTTPS_MEM_CERT, pgc->cert, MHD_OPTION_END); if (NULL == hd->daemon) { GNUNET_free (pgc); GNUNET_free (hd); return NULL; } GNUNET_CONTAINER_DLL_insert (mhd_httpd_head, mhd_httpd_tail, hd); return hd; } /** * Task run when a Socks5Request somehow fails to be associated with * an MHD connection (i.e. because the client never speaks HTTP after * the SOCKS5 handshake). Clean up. * * @param cls the `struct Socks5Request *` * @param tc sched context */ static void timeout_s5r_handshake (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Socks5Request *s5r = cls; s5r->timeout_task = GNUNET_SCHEDULER_NO_TASK; cleanup_s5r (s5r); } /** * We're done with the Socks5 protocol, now we need to pass the * connection data through to the final destination, either * direct (if the protocol might not be HTTP), or via MHD * (if the port looks like it should be HTTP). * * @param s5r socks request that has reached the final stage */ static void setup_data_transfer (struct Socks5Request *s5r) { struct MhdHttpList *hd; int fd; const struct sockaddr *addr; socklen_t len; switch (s5r->port) { case HTTPS_PORT: hd = lookup_ssl_httpd (s5r->domain); if (NULL == hd) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start HTTPS server for `%s'\n"), s5r->domain); cleanup_s5r (s5r); return; } break; case HTTP_PORT: default: GNUNET_assert (NULL != httpd); hd = httpd; break; } fd = GNUNET_NETWORK_get_fd (s5r->sock); addr = GNUNET_NETWORK_get_addr (s5r->sock); len = GNUNET_NETWORK_get_addrlen (s5r->sock); s5r->state = SOCKS5_SOCKET_WITH_MHD; if (MHD_YES != MHD_add_connection (hd->daemon, fd, addr, len)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to pass client to MHD\n")); cleanup_s5r (s5r); return; } s5r->hd = hd; schedule_httpd (hd); s5r->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_HANDSHAKE_TIMEOUT, &timeout_s5r_handshake, s5r); } /* ********************* SOCKS handling ************************* */ /** * Write data from buffer to socks5 client, then continue with state machine. * * @param cls the closure with the `struct Socks5Request` * @param tc scheduler context */ static void do_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Socks5Request *s5r = cls; ssize_t len; s5r->wtask = GNUNET_SCHEDULER_NO_TASK; len = GNUNET_NETWORK_socket_send (s5r->sock, s5r->wbuf, s5r->wbuf_len); if (len <= 0) { /* write error: connection closed, shutdown, etc.; just clean up */ cleanup_s5r (s5r); return; } memmove (s5r->wbuf, &s5r->wbuf[len], s5r->wbuf_len - len); s5r->wbuf_len -= len; if (s5r->wbuf_len > 0) { /* not done writing */ s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_write, s5r); return; } /* we're done writing, continue with state machine! */ switch (s5r->state) { case SOCKS5_INIT: GNUNET_assert (0); break; case SOCKS5_REQUEST: GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s5r->rtask); break; case SOCKS5_DATA_TRANSFER: setup_data_transfer (s5r); return; case SOCKS5_WRITE_THEN_CLEANUP: cleanup_s5r (s5r); return; default: GNUNET_break (0); break; } } /** * Return a server response message indicating a failure to the client. * * @param s5r request to return failure code for * @param sc status code to return */ static void signal_socks_failure (struct Socks5Request *s5r, enum Socks5StatusCode sc) { struct Socks5ServerResponseMessage *s_resp; s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf[s5r->wbuf_len]; memset (s_resp, 0, sizeof (struct Socks5ServerResponseMessage)); s_resp->version = SOCKS_VERSION_5; s_resp->reply = sc; s5r->state = SOCKS5_WRITE_THEN_CLEANUP; if (GNUNET_SCHEDULER_NO_TASK != s5r->wtask) s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_write, s5r); } /** * Return a server response message indicating success. * * @param s5r request to return success status message for */ static void signal_socks_success (struct Socks5Request *s5r) { struct Socks5ServerResponseMessage *s_resp; s_resp = (struct Socks5ServerResponseMessage *) &s5r->wbuf[s5r->wbuf_len]; s_resp->version = SOCKS_VERSION_5; s_resp->reply = SOCKS5_STATUS_REQUEST_GRANTED; s_resp->reserved = 0; s_resp->addr_type = SOCKS5_AT_IPV4; /* zero out IPv4 address and port */ memset (&s_resp[1], 0, sizeof (struct in_addr) + sizeof (uint16_t)); s5r->wbuf_len += sizeof (struct Socks5ServerResponseMessage) + sizeof (struct in_addr) + sizeof (uint16_t); if (GNUNET_SCHEDULER_NO_TASK == s5r->wtask) s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_write, s5r); } /** * Process GNS results for target domain. * * @param cls the `struct Socks5Request` * @param rd_count number of records returned * @param rd record data */ static void handle_gns_result (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct Socks5Request *s5r = cls; uint32_t i; const struct GNUNET_GNSRECORD_Data *r; int got_ip; s5r->gns_lookup = NULL; got_ip = GNUNET_NO; for (i=0;irecord_type) { case GNUNET_DNSPARSER_TYPE_A: { struct sockaddr_in *in; if (sizeof (struct in_addr) != r->data_size) { GNUNET_break_op (0); break; } if (GNUNET_YES == got_ip) break; if (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET)) break; got_ip = GNUNET_YES; in = (struct sockaddr_in *) &s5r->destination_address; in->sin_family = AF_INET; memcpy (&in->sin_addr, r->data, r->data_size); in->sin_port = htons (s5r->port); #if HAVE_SOCKADDR_IN_SIN_LEN in->sin_len = sizeof (*in); #endif } break; case GNUNET_DNSPARSER_TYPE_AAAA: { struct sockaddr_in6 *in; if (sizeof (struct in6_addr) != r->data_size) { GNUNET_break_op (0); break; } if (GNUNET_YES == got_ip) break; if (GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET)) break; /* FIXME: allow user to disable IPv6 per configuration option... */ got_ip = GNUNET_YES; in = (struct sockaddr_in6 *) &s5r->destination_address; in->sin6_family = AF_INET6; memcpy (&in->sin6_addr, r->data, r->data_size); in->sin6_port = htons (s5r->port); #if HAVE_SOCKADDR_IN_SIN_LEN in->sin6_len = sizeof (*in); #endif } break; case GNUNET_GNSRECORD_TYPE_VPN: GNUNET_break (0); /* should have been translated within GNS */ break; case GNUNET_GNSRECORD_TYPE_LEHO: GNUNET_free_non_null (s5r->leho); s5r->leho = GNUNET_strndup (r->data, r->data_size); break; case GNUNET_DNSPARSER_TYPE_TLSA: GNUNET_free_non_null (s5r->dane_data); s5r->dane_data_len = r->data_size; s5r->dane_data = GNUNET_malloc (r->data_size); memcpy (s5r->dane_data, r->data, r->data_size); break; default: /* don't care */ break; } } if (GNUNET_YES != got_ip) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name resolution failed to yield useful IP address.\n"); signal_socks_failure (s5r, SOCKS5_STATUS_GENERAL_FAILURE); return; } s5r->state = SOCKS5_DATA_TRANSFER; signal_socks_success (s5r); } /** * Remove the first @a len bytes from the beginning of the read buffer. * * @param s5r the handle clear the read buffer for * @param len number of bytes in read buffer to advance */ static void clear_from_s5r_rbuf (struct Socks5Request *s5r, size_t len) { GNUNET_assert (len <= s5r->rbuf_len); memmove (s5r->rbuf, &s5r->rbuf[len], s5r->rbuf_len - len); s5r->rbuf_len -= len; } /** * Read data from incoming Socks5 connection * * @param cls the closure with the `struct Socks5Request` * @param tc the scheduler context */ static void do_s5r_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Socks5Request *s5r = cls; const struct Socks5ClientHelloMessage *c_hello; struct Socks5ServerHelloMessage *s_hello; const struct Socks5ClientRequestMessage *c_req; ssize_t rlen; size_t alen; s5r->rtask = GNUNET_SCHEDULER_NO_TASK; if ( (NULL != tc->read_ready) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, s5r->sock)) ) { rlen = GNUNET_NETWORK_socket_recv (s5r->sock, &s5r->rbuf[s5r->rbuf_len], sizeof (s5r->rbuf) - s5r->rbuf_len); if (rlen <= 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "socks5 client disconnected.\n"); cleanup_s5r (s5r); return; } s5r->rbuf_len += rlen; } s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_s5r_read, s5r); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing %u bytes of socks data in state %d\n", s5r->rbuf_len, s5r->state); switch (s5r->state) { case SOCKS5_INIT: c_hello = (const struct Socks5ClientHelloMessage*) &s5r->rbuf; if ( (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage)) || (s5r->rbuf_len < sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods) ) return; /* need more data */ if (SOCKS_VERSION_5 != c_hello->version) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported socks version %d\n"), (int) c_hello->version); cleanup_s5r (s5r); return; } clear_from_s5r_rbuf (s5r, sizeof (struct Socks5ClientHelloMessage) + c_hello->num_auth_methods); GNUNET_assert (0 == s5r->wbuf_len); s_hello = (struct Socks5ServerHelloMessage *) &s5r->wbuf; s5r->wbuf_len = sizeof (struct Socks5ServerHelloMessage); s_hello->version = SOCKS_VERSION_5; s_hello->auth_method = SOCKS_AUTH_NONE; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s5r->wtask); s5r->wtask = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_write, s5r); s5r->state = SOCKS5_REQUEST; return; case SOCKS5_REQUEST: c_req = (const struct Socks5ClientRequestMessage *) &s5r->rbuf; if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage)) return; switch (c_req->command) { case SOCKS5_CMD_TCP_STREAM: /* handled below */ break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported socks command %d\n"), (int) c_req->command); signal_socks_failure (s5r, SOCKS5_STATUS_COMMAND_NOT_SUPPORTED); return; } switch (c_req->addr_type) { case SOCKS5_AT_IPV4: { const struct in_addr *v4 = (const struct in_addr *) &c_req[1]; const uint16_t *port = (const uint16_t *) &v4[1]; struct sockaddr_in *in; s5r->port = ntohs (*port); if (HTTPS_PORT == s5r->port) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("SSL connection to plain IPv4 address requested\n")); signal_socks_failure (s5r, SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE); return; } alen = sizeof (struct in_addr); if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) + alen + sizeof (uint16_t)) return; /* need more data */ in = (struct sockaddr_in *) &s5r->destination_address; in->sin_family = AF_INET; in->sin_addr = *v4; in->sin_port = *port; #if HAVE_SOCKADDR_IN_SIN_LEN in->sin_len = sizeof (*in); #endif s5r->state = SOCKS5_DATA_TRANSFER; } break; case SOCKS5_AT_IPV6: { const struct in6_addr *v6 = (const struct in6_addr *) &c_req[1]; const uint16_t *port = (const uint16_t *) &v6[1]; struct sockaddr_in6 *in; s5r->port = ntohs (*port); if (HTTPS_PORT == s5r->port) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("SSL connection to plain IPv4 address requested\n")); signal_socks_failure (s5r, SOCKS5_STATUS_CONNECTION_NOT_ALLOWED_BY_RULE); return; } alen = sizeof (struct in6_addr); if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) + alen + sizeof (uint16_t)) return; /* need more data */ in = (struct sockaddr_in6 *) &s5r->destination_address; in->sin6_family = AF_INET6; in->sin6_addr = *v6; in->sin6_port = *port; #if HAVE_SOCKADDR_IN_SIN_LEN in->sin6_len = sizeof (*in); #endif s5r->state = SOCKS5_DATA_TRANSFER; } break; case SOCKS5_AT_DOMAINNAME: { const uint8_t *dom_len; const char *dom_name; const uint16_t *port; dom_len = (const uint8_t *) &c_req[1]; alen = *dom_len + 1; if (s5r->rbuf_len < sizeof (struct Socks5ClientRequestMessage) + alen + sizeof (uint16_t)) return; /* need more data */ dom_name = (const char *) &dom_len[1]; port = (const uint16_t*) &dom_name[*dom_len]; s5r->domain = GNUNET_strndup (dom_name, *dom_len); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requested connection is to %s:%d\n", s5r->domain, ntohs (*port)); s5r->state = SOCKS5_RESOLVING; s5r->port = ntohs (*port); s5r->gns_lookup = GNUNET_GNS_lookup (gns_handle, s5r->domain, &local_gns_zone, GNUNET_DNSPARSER_TYPE_A, GNUNET_NO /* only cached */, (GNUNET_YES == do_shorten) ? &local_shorten_zone : NULL, &handle_gns_result, s5r); break; } default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported socks address type %d\n"), (int) c_req->addr_type); signal_socks_failure (s5r, SOCKS5_STATUS_ADDRESS_TYPE_NOT_SUPPORTED); return; } clear_from_s5r_rbuf (s5r, sizeof (struct Socks5ClientRequestMessage) + alen + sizeof (uint16_t)); if (0 != s5r->rbuf_len) { /* read more bytes than healthy, why did the client send more!? */ GNUNET_break_op (0); signal_socks_failure (s5r, SOCKS5_STATUS_GENERAL_FAILURE); return; } if (SOCKS5_DATA_TRANSFER == s5r->state) { /* if we are not waiting for GNS resolution, signal success */ signal_socks_success (s5r); } /* We are done reading right now */ GNUNET_SCHEDULER_cancel (s5r->rtask); s5r->rtask = GNUNET_SCHEDULER_NO_TASK; return; case SOCKS5_RESOLVING: GNUNET_assert (0); return; case SOCKS5_DATA_TRANSFER: GNUNET_assert (0); return; default: GNUNET_assert (0); return; } } /** * Accept new incoming connections * * @param cls the closure with the lsock4 or lsock6 * @param tc the scheduler context */ static void do_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NETWORK_Handle *lsock = cls; struct GNUNET_NETWORK_Handle *s; struct Socks5Request *s5r; if (lsock == lsock4) ltask4 = GNUNET_SCHEDULER_NO_TASK; else ltask6 = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; if (lsock == lsock4) ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, lsock, &do_accept, lsock); else ltask6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, lsock, &do_accept, lsock); s = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL); if (NULL == s) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "accept"); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an inbound connection, waiting for data\n"); s5r = GNUNET_new (struct Socks5Request); GNUNET_CONTAINER_DLL_insert (s5r_head, s5r_tail, s5r); s5r->sock = s; s5r->state = SOCKS5_INIT; s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_s5r_read, s5r); } /* ******************* General / main code ********************* */ /** * Task run on shutdown * * @param cls closure * @param tc task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n"); while (NULL != mhd_httpd_head) kill_httpd (mhd_httpd_head); while (NULL != s5r_head) cleanup_s5r (s5r_head); if (NULL != lsock4) { GNUNET_NETWORK_socket_close (lsock4); lsock4 = NULL; } if (NULL != lsock6) { GNUNET_NETWORK_socket_close (lsock6); lsock6 = NULL; } if (NULL != id_op) { GNUNET_IDENTITY_cancel (id_op); id_op = NULL; } if (NULL != identity) { GNUNET_IDENTITY_disconnect (identity); identity = NULL; } if (NULL != curl_multi) { curl_multi_cleanup (curl_multi); curl_multi = NULL; } if (NULL != gns_handle) { GNUNET_GNS_disconnect (gns_handle); gns_handle = NULL; } if (GNUNET_SCHEDULER_NO_TASK != curl_download_task) { GNUNET_SCHEDULER_cancel (curl_download_task); curl_download_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != ltask4) { GNUNET_SCHEDULER_cancel (ltask4); ltask4 = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != ltask6) { GNUNET_SCHEDULER_cancel (ltask6); ltask6 = GNUNET_SCHEDULER_NO_TASK; } gnutls_x509_crt_deinit (proxy_ca.cert); gnutls_x509_privkey_deinit (proxy_ca.key); gnutls_global_deinit (); } /** * Create an IPv4 listen socket bound to our port. * * @return NULL on error */ static struct GNUNET_NETWORK_Handle * bind_v4 () { struct GNUNET_NETWORK_Handle *ls; struct sockaddr_in sa4; int eno; memset (&sa4, 0, sizeof (sa4)); sa4.sin_family = AF_INET; sa4.sin_port = htons (port); #if HAVE_SOCKADDR_IN_SIN_LEN sa4.sin_len = sizeof (sa4); #endif ls = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); if (NULL == ls) return NULL; if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4, sizeof (sa4))) { eno = errno; GNUNET_NETWORK_socket_close (ls); errno = eno; return NULL; } return ls; } /** * Create an IPv6 listen socket bound to our port. * * @return NULL on error */ static struct GNUNET_NETWORK_Handle * bind_v6 () { struct GNUNET_NETWORK_Handle *ls; struct sockaddr_in6 sa6; int eno; memset (&sa6, 0, sizeof (sa6)); sa6.sin6_family = AF_INET6; sa6.sin6_port = htons (port); #if HAVE_SOCKADDR_IN_SIN_LEN sa6.sin6_len = sizeof (sa6); #endif ls = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0); if (NULL == ls) return NULL; if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa6, sizeof (sa6))) { eno = errno; GNUNET_NETWORK_socket_close (ls); errno = eno; return NULL; } return ls; } /** * Continue initialization after we have our zone information. */ static void run_cont () { struct MhdHttpList *hd; /* Open listen socket for socks proxy */ lsock6 = bind_v6 (); if (NULL == lsock6) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); else { if (GNUNET_OK != GNUNET_NETWORK_socket_listen (lsock6, 5)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); GNUNET_NETWORK_socket_close (lsock6); lsock6 = NULL; } else { ltask6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, lsock6, &do_accept, lsock6); } } lsock4 = bind_v4 (); if (NULL == lsock4) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); else { if (GNUNET_OK != GNUNET_NETWORK_socket_listen (lsock4, 5)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); GNUNET_NETWORK_socket_close (lsock4); lsock4 = NULL; } else { ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, lsock4, &do_accept, lsock4); } } if ( (NULL == lsock4) && (NULL == lsock6) ) { GNUNET_SCHEDULER_shutdown (); return; } if (0 != curl_global_init (CURL_GLOBAL_WIN32)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "cURL global init failed!\n"); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Proxy listens on port %u\n", port); /* start MHD daemon for HTTP */ hd = GNUNET_new (struct MhdHttpList); hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET, 0, NULL, NULL, &create_response, hd, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, MHD_OPTION_NOTIFY_COMPLETED, &mhd_completed_cb, NULL, MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL, MHD_OPTION_END); if (NULL == hd->daemon) { GNUNET_free (hd); GNUNET_SCHEDULER_shutdown (); return; } httpd = hd; GNUNET_CONTAINER_DLL_insert (mhd_httpd_head, mhd_httpd_tail, hd); } /** * Method called to inform about the egos of the shorten zone of this peer. * * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, * this function is only called ONCE, and 'NULL' being passed in * @a ego does indicate an error (i.e. name is taken or no default * value is known). If @a ego is non-NULL and if '*ctx' * is set in those callbacks, the value WILL be passed to a subsequent * call to the identity callback of #GNUNET_IDENTITY_connect (if * that one was not NULL). * * @param cls closure, NULL * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void identity_shorten_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { id_op = NULL; if (NULL == ego) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No ego configured for `shorten-zone`\n")); } else { local_shorten_zone = *GNUNET_IDENTITY_ego_get_private_key (ego); do_shorten = GNUNET_YES; } run_cont (); } /** * Method called to inform about the egos of the master zone of this peer. * * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, * this function is only called ONCE, and 'NULL' being passed in * @a ego does indicate an error (i.e. name is taken or no default * value is known). If @a ego is non-NULL and if '*ctx' * is set in those callbacks, the value WILL be passed to a subsequent * call to the identity callback of #GNUNET_IDENTITY_connect (if * that one was not NULL). * * @param cls closure, NULL * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void identity_master_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { id_op = NULL; if (NULL == ego) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No ego configured for `%s`\n"), "gns-proxy"); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_IDENTITY_ego_get_public_key (ego, &local_gns_zone); id_op = GNUNET_IDENTITY_get (identity, "gns-short", &identity_shorten_cb, NULL); } /** * Main function that will be run * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char* cafile_cfg = NULL; char* cafile; cfg = c; if (NULL == (curl_multi = curl_multi_init ())) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create cURL multi handle!\n"); return; } cafile = cafile_opt; if (NULL == cafile) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns-proxy", "PROXY_CACERT", &cafile_cfg)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "gns-proxy", "PROXY_CACERT"); return; } cafile = cafile_cfg; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using %s as CA\n", cafile); gnutls_global_init (); gnutls_x509_crt_init (&proxy_ca.cert); gnutls_x509_privkey_init (&proxy_ca.key); if ( (GNUNET_OK != load_cert_from_file (proxy_ca.cert, cafile)) || (GNUNET_OK != load_key_from_file (proxy_ca.key, cafile)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to load SSL/TLS key and certificate from `%s'\n"), cafile); gnutls_x509_crt_deinit (proxy_ca.cert); gnutls_x509_privkey_deinit (proxy_ca.key); gnutls_global_deinit (); GNUNET_free_non_null (cafile_cfg); return; } GNUNET_free_non_null (cafile_cfg); if (NULL == (gns_handle = GNUNET_GNS_connect (cfg))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to connect to GNS!\n"); gnutls_x509_crt_deinit (proxy_ca.cert); gnutls_x509_privkey_deinit (proxy_ca.key); gnutls_global_deinit (); return; } identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); id_op = GNUNET_IDENTITY_get (identity, "gns-proxy", &identity_master_cb, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); } /** * The main function for gnunet-gns-proxy. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'p', "port", NULL, gettext_noop ("listen on specified port (default: 7777)"), 1, &GNUNET_GETOPT_set_ulong, &port}, {'a', "authority", NULL, gettext_noop ("pem file to use as CA"), 1, &GNUNET_GETOPT_set_string, &cafile_opt}, GNUNET_GETOPT_OPTION_END }; static const char* page = "gnunet-gns-proxy" "cURL fail"; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; GNUNET_log_setup ("gnunet-gns-proxy", "WARNING", NULL); curl_failure_response = MHD_create_response_from_buffer (strlen (page), (void*)page, MHD_RESPMEM_PERSISTENT); ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-gns-proxy", _("GNUnet GNS proxy"), options, &run, NULL)) ? 0 : 1; MHD_destroy_response (curl_failure_response); GNUNET_free_non_null ((char *) argv); GNUNET_CRYPTO_ecdsa_key_clear (&local_shorten_zone); return ret; } /* end of gnunet-gns-proxy.c */ gnunet-0.10.1/src/gns/gnunet-service-gns.c0000644000175000017500000006665712305564547015316 00000000000000/* This file is part of GNUnet. (C) 2011-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gnunet-service-gns.c * @brief GNU Name System (main service) * @author Martin Schanzenbach * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dns_service.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_dht_service.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_gns_service.h" #include "gnunet_statistics_service.h" #include "gns.h" #include "gnunet-service-gns_resolver.h" #include "gnunet-service-gns_shorten.h" #include "gnunet-service-gns_interceptor.h" #include "gnunet_protocols.h" /** * The initial interval in milliseconds btween puts in * a zone iteration */ #define INITIAL_PUT_INTERVAL GNUNET_TIME_UNIT_MILLISECONDS /** * The upper bound for the zone iteration interval in milliseconds */ #define MINIMUM_ZONE_ITERATION_INTERVAL GNUNET_TIME_UNIT_SECONDS /** * The default put interval for the zone iteration. In case * no option is found */ #define DEFAULT_ZONE_PUBLISH_TIME_WINDOW GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4) /** * The factor the current zone iteration interval is divided by for each * additional new record */ #define LATE_ITERATION_SPEEDUP_FACTOR 2 /** * How long until a DHT PUT attempt should time out? */ #define DHT_OPERATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * What replication level do we use for DHT PUT operations? */ #define DHT_GNS_REPLICATION_LEVEL 5 /** * Handle to a lookup operation from api */ struct ClientLookupHandle { /** * We keep these in a DLL. */ struct ClientLookupHandle *next; /** * We keep these in a DLL. */ struct ClientLookupHandle *prev; /** * Handle to the requesting client */ struct GNUNET_SERVER_Client *client; /** * Active handle for the lookup. */ struct GNS_ResolverHandle *lookup; /** * request id */ uint32_t request_id; }; /** * Handle for DHT PUT activity triggered from the namestore monitor. */ struct MonitorActivity { /** * Kept in a DLL. */ struct MonitorActivity *next; /** * Kept in a DLL. */ struct MonitorActivity *prev; /** * Handle for the DHT PUT operation. */ struct GNUNET_DHT_PutHandle *ph; }; /** * Our handle to the DHT */ static struct GNUNET_DHT_Handle *dht_handle; /** * Active DHT put operation (or NULL) */ static struct GNUNET_DHT_PutHandle *active_put; /** * Our handle to the namestore service */ static struct GNUNET_NAMESTORE_Handle *namestore_handle; /** * Our handle to the namecache service */ static struct GNUNET_NAMECACHE_Handle *namecache_handle; /** * Handle to iterate over our authoritative zone in namestore */ static struct GNUNET_NAMESTORE_ZoneIterator *namestore_iter; /** * Handle to monitor namestore changes to instant propagation. */ static struct GNUNET_NAMESTORE_ZoneMonitor *zmon; /** * Our notification context. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Head of the DLL. */ static struct ClientLookupHandle *clh_head; /** * Tail of the DLL. */ static struct ClientLookupHandle *clh_tail; /** * Head of monitor activities; kept in a DLL. */ static struct MonitorActivity *ma_head; /** * Tail of monitor activities; kept in a DLL. */ static struct MonitorActivity *ma_tail; /** * Useful for zone update for DHT put */ static unsigned long long num_public_records; /** * Last seen record count */ static unsigned long long last_num_public_records; /** * Minimum relative expiration time of records seem during the current * zone iteration. */ static struct GNUNET_TIME_Relative min_relative_record_time; /** * Zone iteration PUT interval. */ static struct GNUNET_TIME_Relative put_interval; /** * Default time window for zone iteration */ static struct GNUNET_TIME_Relative zone_publish_time_window_default; /** * Time window for zone iteration, adjusted based on relative record * expiration times in our zone. */ static struct GNUNET_TIME_Relative zone_publish_time_window; /** * zone publish task */ static GNUNET_SCHEDULER_TaskIdentifier zone_publish_task; /** * #GNUNET_YES if zone has never been published before */ static int first_zone_iteration; /** * #GNUNET_YES if ipv6 is supported */ static int v6_enabled; /** * #GNUNET_YES if ipv4 is supported */ static int v4_enabled; /** * Handle to the statistics service */ static struct GNUNET_STATISTICS_Handle *statistics; /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ClientLookupHandle *clh; struct MonitorActivity *ma; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down!\n"); GNUNET_SERVER_notification_context_destroy (nc); while (NULL != (clh = clh_head)) { GNUNET_SERVER_client_set_user_context (clh->client, (void *)NULL); GNS_resolver_lookup_cancel (clh->lookup); GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh); GNUNET_free (clh); } GNS_interceptor_done (); GNS_resolver_done (); GNS_shorten_done (); while (NULL != (ma = ma_head)) { GNUNET_DHT_put_cancel (ma->ph); GNUNET_CONTAINER_DLL_remove (ma_head, ma_tail, ma); GNUNET_free (ma); } if (NULL != statistics) { GNUNET_STATISTICS_destroy (statistics, GNUNET_NO); statistics = NULL; } if (GNUNET_SCHEDULER_NO_TASK != zone_publish_task) { GNUNET_SCHEDULER_cancel (zone_publish_task); zone_publish_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != namestore_iter) { GNUNET_NAMESTORE_zone_iteration_stop (namestore_iter); namestore_iter = NULL; } if (NULL != zmon) { GNUNET_NAMESTORE_zone_monitor_stop (zmon); zmon = NULL; } if (NULL != namestore_handle) { GNUNET_NAMESTORE_disconnect (namestore_handle); namestore_handle = NULL; } if (NULL != namecache_handle) { GNUNET_NAMECACHE_disconnect (namecache_handle); namecache_handle = NULL; } if (NULL != active_put) { GNUNET_DHT_put_cancel (active_put); active_put = NULL; } if (NULL != dht_handle) { GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; } } /** * Method called periodically that triggers iteration over authoritative records * * @param cls closure * @param tc task context */ static void publish_zone_dht_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { zone_publish_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_NAMESTORE_zone_iterator_next (namestore_iter); } /** * Periodically iterate over our zone and store everything in dht * * @param cls NULL * @param tc task context */ static void publish_zone_dht_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Continuation called from DHT once the PUT operation is done. * * @param cls closure, NULL if called from regular iteration, * `struct MonitorActivity` if called from #handle_monitor_event. * @param success #GNUNET_OK on success */ static void dht_put_continuation (void *cls, int success) { struct MonitorActivity *ma = cls; struct GNUNET_TIME_Relative next_put_interval; num_public_records++; if (NULL == ma) { active_put = NULL; if ( (num_public_records > last_num_public_records) && (GNUNET_NO == first_zone_iteration) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last record count was lower than current record count. Reducing interval.\n"); put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window, num_public_records); next_put_interval = GNUNET_TIME_relative_divide (put_interval, LATE_ITERATION_SPEEDUP_FACTOR); } else next_put_interval = put_interval; GNUNET_STATISTICS_set (statistics, "Current zone iteration interval (ms)", next_put_interval.rel_value_us / 1000LL, GNUNET_NO); zone_publish_task = GNUNET_SCHEDULER_add_delayed (next_put_interval, &publish_zone_dht_next, NULL); } else { GNUNET_CONTAINER_DLL_remove (ma_head, ma_tail, ma); GNUNET_free (ma); } } /** * Convert namestore records from the internal format to that * suitable for publication (removes private records, converts * to absolute expiration time). * * @param rd input records * @param rd_count size of the @a rd and @a rd_public arrays * @param rd_public where to write the converted records * @return number of records written to @a rd_public */ static unsigned int convert_records_for_export (const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *rd_public) { struct GNUNET_TIME_Absolute now; unsigned int rd_public_count; unsigned int i; rd_public_count = 0; now = GNUNET_TIME_absolute_get (); for (i=0;ipurpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); GNUNET_GNSRECORD_query_from_private_key (key, label, &query); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing %u record(s) for label `%s' in DHT with expiration `%s' under key %s\n", rd_public_count, label, GNUNET_STRINGS_absolute_time_to_string (expire), GNUNET_h2s (&query)); ret = GNUNET_DHT_put (dht_handle, &query, DHT_GNS_REPLICATION_LEVEL, GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, block_size, block, expire, DHT_OPERATION_TIMEOUT, &dht_put_continuation, pc_arg); GNUNET_free (block); return ret; } /** * Function used to put all records successively into the DHT. * * @param cls the closure (NULL) * @param key the private key of the authority (ours) * @param name the name of the records, NULL once the iteration is done * @param rd_count the number of records in @a rd * @param rd the record data */ static void put_gns_record (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_GNSRECORD_Data rd_public[rd_count]; unsigned int rd_public_count; if (NULL == name) { /* we're done with one iteration, calculate when to do the next one */ namestore_iter = NULL; last_num_public_records = num_public_records; first_zone_iteration = GNUNET_NO; if (0 == num_public_records) { /** * If no records are known (startup) or none present * we can safely set the interval to the value for a single * record */ put_interval = zone_publish_time_window; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "No records in namestore database.\n"); } else { zone_publish_time_window = GNUNET_TIME_relative_min (GNUNET_TIME_relative_divide (min_relative_record_time, 4), zone_publish_time_window_default); put_interval = GNUNET_TIME_relative_divide (zone_publish_time_window, num_public_records); } /* reset for next iteration */ min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL; put_interval = GNUNET_TIME_relative_max (MINIMUM_ZONE_ITERATION_INTERVAL, put_interval); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration finished. Adjusted zone iteration interval to %s\n", GNUNET_STRINGS_relative_time_to_string (put_interval, GNUNET_YES)); GNUNET_STATISTICS_set (statistics, "Current zone iteration interval (in ms)", put_interval.rel_value_us / 1000LL, GNUNET_NO); GNUNET_STATISTICS_update (statistics, "Number of zone iterations", 1, GNUNET_NO); GNUNET_STATISTICS_set (statistics, "Number of public records in DHT", last_num_public_records, GNUNET_NO); if (0 == num_public_records) zone_publish_task = GNUNET_SCHEDULER_add_delayed (put_interval, &publish_zone_dht_start, NULL); else zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, NULL); return; } rd_public_count = convert_records_for_export (rd, rd_count, rd_public); /* We got a set of records to publish */ if (0 == rd_public_count) { zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_next, NULL); return; } active_put = perform_dht_put (key, name, rd_public, rd_public_count, NULL); if (NULL == active_put) { GNUNET_break (0); dht_put_continuation (NULL, GNUNET_NO); } } /** * Periodically iterate over our zone and store everything in dht * * @param cls NULL * @param tc task context */ static void publish_zone_dht_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { zone_publish_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting DHT zone update!\n"); /* start counting again */ num_public_records = 0; namestore_iter = GNUNET_NAMESTORE_zone_iteration_start (namestore_handle, NULL, /* All zones */ &put_gns_record, NULL); } /** * Process a record that was stored in the namestore * (invoked by the monitor). * * @param cls closure, NULL * @param zone private key of the zone; NULL on disconnect * @param label label of the records; NULL on disconnect * @param rd_count number of entries in @a rd array, 0 if label was deleted * @param rd array of records with data to store */ static void handle_monitor_event (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_GNSRECORD_Data rd_public[rd_count]; unsigned int rd_public_count; struct MonitorActivity *ma; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u records for label `%s' via namestore monitor\n", rd_count, label); /* filter out records that are not public, and convert to absolute expiration time. */ rd_public_count = convert_records_for_export (rd, rd_count, rd_public); if (0 == rd_public_count) return; /* nothing to do */ ma = GNUNET_new (struct MonitorActivity); ma->ph = perform_dht_put (zone, label, rd, rd_count, ma); if (NULL == ma->ph) { /* PUT failed, do not remember operation */ GNUNET_free (ma); return; } GNUNET_CONTAINER_DLL_insert (ma_head, ma_tail, ma); } /* END DHT ZONE PROPAGATION */ /** * Reply to client with the result from our lookup. * * @param cls the closure (our client lookup handle) * @param rd_count the number of records in @a rd * @param rd the record data */ static void send_lookup_response (void* cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct ClientLookupHandle *clh = cls; struct GNUNET_GNS_ClientLookupResultMessage *rmsg; size_t len; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %d results\n", "LOOKUP_RESULT", rd_count); len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); rmsg = GNUNET_malloc (len + sizeof (struct GNUNET_GNS_ClientLookupResultMessage)); rmsg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT); rmsg->header.size = htons (len + sizeof(struct GNUNET_GNS_ClientLookupResultMessage)); rmsg->id = clh->request_id; rmsg->rd_count = htonl (rd_count); GNUNET_GNSRECORD_records_serialize (rd_count, rd, len, (char*) &rmsg[1]); GNUNET_SERVER_notification_context_unicast (nc, clh->client, &rmsg->header, GNUNET_NO); GNUNET_free (rmsg); GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh); GNUNET_SERVER_client_set_user_context (clh->client, (void *)NULL); GNUNET_free (clh); GNUNET_STATISTICS_update (statistics, "Completed lookups", 1, GNUNET_NO); GNUNET_STATISTICS_update (statistics, "Records resolved", rd_count, GNUNET_NO); } /** * Handle lookup requests from client * * @param cls the closure * @param client the client * @param message the message */ static void handle_lookup (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1]; struct ClientLookupHandle *clh; char *nameptr = name; const char *utf_in; const struct GNUNET_CRYPTO_EcdsaPrivateKey *key; uint16_t msg_size; const struct GNUNET_GNS_ClientLookupMessage *sh_msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "LOOKUP"); msg_size = ntohs (message->size); if (msg_size < sizeof (struct GNUNET_GNS_ClientLookupMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } sh_msg = (const struct GNUNET_GNS_ClientLookupMessage *) message; GNUNET_SERVER_notification_context_add (nc, client); if (GNUNET_YES == ntohs (sh_msg->have_key)) key = &sh_msg->shorten_key; else key = NULL; utf_in = (const char *) &sh_msg[1]; if ( ('\0' != utf_in[msg_size - sizeof (struct GNUNET_GNS_ClientLookupMessage) - 1]) || (strlen (utf_in) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STRINGS_utf8_tolower (utf_in, nameptr); GNUNET_SERVER_receive_done (client, GNUNET_OK); clh = GNUNET_new (struct ClientLookupHandle); GNUNET_SERVER_client_set_user_context (client, clh); GNUNET_CONTAINER_DLL_insert (clh_head, clh_tail, clh); clh->client = client; clh->request_id = sh_msg->id; if ( (GNUNET_DNSPARSER_TYPE_A == ntohl (sh_msg->type)) && (GNUNET_OK != v4_enabled) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "LOOKUP: Query for A record but AF_INET not supported!"); send_lookup_response (clh, 0, NULL); return; } if ( (GNUNET_DNSPARSER_TYPE_AAAA == ntohl (sh_msg->type)) && (GNUNET_OK != v6_enabled) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "LOOKUP: Query for AAAA record but AF_INET6 not supported!"); send_lookup_response (clh, 0, NULL); return; } clh->lookup = GNS_resolver_lookup (&sh_msg->zone, ntohl (sh_msg->type), name, key, (enum GNUNET_GNS_LocalOptions) ntohs (sh_msg->options), &send_lookup_response, clh); GNUNET_STATISTICS_update (statistics, "Lookup attempts", 1, GNUNET_NO); } /** * One of our clients disconnected, clean up after it. * * @param cls NULL * @param client the client that disconnected */ static void notify_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ClientLookupHandle *clh; if (NULL == client) return; clh = GNUNET_SERVER_client_get_user_context (client, struct ClientLookupHandle); if (NULL == clh) return; GNS_resolver_lookup_cancel (clh->lookup); GNUNET_CONTAINER_DLL_remove (clh_head, clh_tail, clh); GNUNET_free (clh); } /** * The zone monitor is now in SYNC with the current state of the * name store. Start to perform periodic iterations. * * @param cls NULL */ static void monitor_sync_event (void *cls) { zone_publish_task = GNUNET_SCHEDULER_add_now (&publish_zone_dht_start, NULL); } /** * Process GNS requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { { &handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0}, {NULL, NULL, 0, 0} }; struct GNUNET_CRYPTO_EcdsaPublicKey dns_root; unsigned long long max_parallel_bg_queries = 0; char *dns_root_name; v6_enabled = GNUNET_NETWORK_test_pf (PF_INET6); v4_enabled = GNUNET_NETWORK_test_pf (PF_INET); min_relative_record_time = GNUNET_TIME_UNIT_FOREVER_REL; namestore_handle = GNUNET_NAMESTORE_connect (c); if (NULL == namestore_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to the namestore!\n")); GNUNET_SCHEDULER_shutdown (); return; } namecache_handle = GNUNET_NAMECACHE_connect (c); if (NULL == namecache_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to the namecache!\n")); GNUNET_SCHEDULER_shutdown (); return; } put_interval = INITIAL_PUT_INTERVAL; zone_publish_time_window_default = DEFAULT_ZONE_PUBLISH_TIME_WINDOW; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (c, "gns", "ZONE_PUBLISH_TIME_WINDOW", &zone_publish_time_window_default)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Time window for zone iteration: %s\n", GNUNET_STRINGS_relative_time_to_string (zone_publish_time_window, GNUNET_YES)); } zone_publish_time_window = zone_publish_time_window_default; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (c, "gns", "MAX_PARALLEL_BACKGROUND_QUERIES", &max_parallel_bg_queries)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Number of allowed parallel background queries: %llu\n", max_parallel_bg_queries); } dht_handle = GNUNET_DHT_connect (c, (unsigned int) max_parallel_bg_queries); if (NULL == dht_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not connect to DHT!\n")); GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); return; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (c, "gns", "DNS_ROOT", &dns_root_name)) { if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (dns_root_name, strlen (dns_root_name), &dns_root)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "gns", "DNS_ROOT", _("valid public key required")); GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); GNUNET_free (dns_root_name); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "DNS hijacking with root `%s' enabled. Connecting to DNS service.\n", dns_root_name); GNUNET_free (dns_root_name); if (GNUNET_SYSERR == GNS_interceptor_init (&dns_root, c)) { GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); return; } } GNS_resolver_init (namecache_handle, dht_handle, c, max_parallel_bg_queries); GNS_shorten_init (namestore_handle, namecache_handle, dht_handle); GNUNET_SERVER_disconnect_notify (server, ¬ify_client_disconnect, NULL); /* Schedule periodic put for our records. */ first_zone_iteration = GNUNET_YES; GNUNET_SERVER_add_handlers (server, handlers); statistics = GNUNET_STATISTICS_create ("gns", c); nc = GNUNET_SERVER_notification_context_create (server, 1); zmon = GNUNET_NAMESTORE_zone_monitor_start (c, NULL, GNUNET_NO, &handle_monitor_event, &monitor_sync_event, NULL); GNUNET_break (NULL != zmon); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for the GNS service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "gns", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; return ret; } /* end of gnunet-service-gns.c */ gnunet-0.10.1/src/gns/gnunet-service-gns_shorten.c0000644000175000017500000002724012245714542017034 00000000000000/* This file is part of GNUnet. (C) 2011-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gnunet-service-gns_shorten.c * @brief GNUnet GNS shortening logic * @author Martin Schanzenbach * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dht_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_namestore_service.h" #include "gnunet_resolver_service.h" #include "gnunet_gns_service.h" #include "gns.h" #include "gnunet-service-gns_shorten.h" #include "gnunet_vpn_service.h" /** * Default DHT timeout for lookups. */ #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * DHT replication level */ #define DHT_GNS_REPLICATION_LEVEL 5 /** * Handle for a PSEU lookup used to shorten names. */ struct GetPseuAuthorityHandle { /** * DLL */ struct GetPseuAuthorityHandle *next; /** * DLL */ struct GetPseuAuthorityHandle *prev; /** * Private key of the (shorten) zone to store the resulting * pseudonym in. */ struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_zone_key; /** * Original label (used if no PSEU record is found). */ char label[GNUNET_DNSPARSER_MAX_LABEL_LENGTH + 1]; /** * Suggested label based on NICK record */ char * suggested_label; /** * Label we are currently trying out */ char *current_label; /** * The zone for which we are trying to find the PSEU record. */ struct GNUNET_CRYPTO_EcdsaPublicKey target_zone; /** * Handle for DHT lookups. Should be NULL if no lookups are in progress */ struct GNUNET_DHT_GetHandle *get_handle; /** * Handle to namestore request */ struct GNUNET_NAMESTORE_QueueEntry *namestore_task; /** * Handle to namecache request */ struct GNUNET_NAMECACHE_QueueEntry *namecache_task; /** * Task to abort DHT lookup operation. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; /** * Head of PSEU/shorten operations list. */ static struct GetPseuAuthorityHandle *gph_head; /** * Tail of PSEU/shorten operations list. */ static struct GetPseuAuthorityHandle *gph_tail; /** * Our handle to the namestore service */ static struct GNUNET_NAMESTORE_Handle *namestore_handle; /** * Our handle to the namecache service */ static struct GNUNET_NAMECACHE_Handle *namecache_handle; /** * Resolver handle to the dht */ static struct GNUNET_DHT_Handle *dht_handle; /** * Cleanup a 'struct GetPseuAuthorityHandle', terminating all * pending activities. * * @param gph handle to terminate */ static void free_get_pseu_authority_handle (struct GetPseuAuthorityHandle *gph) { if (NULL != gph->get_handle) { GNUNET_DHT_get_stop (gph->get_handle); gph->get_handle = NULL; } if (NULL != gph->namestore_task) { GNUNET_NAMESTORE_cancel (gph->namestore_task); gph->namestore_task = NULL; } if (NULL != gph->namecache_task) { GNUNET_NAMECACHE_cancel (gph->namecache_task); gph->namecache_task = NULL; } if (GNUNET_SCHEDULER_NO_TASK != gph->timeout_task) { GNUNET_SCHEDULER_cancel (gph->timeout_task); gph->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_DLL_remove (gph_head, gph_tail, gph); GNUNET_free_non_null (gph->current_label); GNUNET_free (gph); } /** * Continuation for pkey record creation (shorten) * * @param cls a GetPseuAuthorityHandle * @param success unused * @param emsg unused */ static void create_pkey_cont (void* cls, int32_t success, const char *emsg) { struct GetPseuAuthorityHandle* gph = cls; gph->namestore_task = NULL; free_get_pseu_authority_handle (gph); } /** * Namestore calls this function if we have record for this name. * (or with rd_count=0 to indicate no matches). * * @param cls the pending query * @param rd_count the number of records with 'name' * @param rd the record data */ static void process_pseu_lookup_ns (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); /** * We obtained a result for our query to the shorten zone from * the namestore. Try to decrypt. * * @param cls the handle to our shorten operation * @param block resulting encrypted block */ static void process_pseu_block_ns (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct GetPseuAuthorityHandle *gph = cls; struct GNUNET_CRYPTO_EcdsaPublicKey pub; gph->namecache_task = NULL; if (NULL == block) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namecache did not return information for label `%s' \n", gph->current_label); process_pseu_lookup_ns (gph, 0, NULL); return; } GNUNET_CRYPTO_ecdsa_key_get_public (&gph->shorten_zone_key, &pub); if (GNUNET_OK != GNUNET_GNSRECORD_block_decrypt (block, &pub, gph->current_label, &process_pseu_lookup_ns, gph)) { GNUNET_break (0); free_get_pseu_authority_handle (gph); return; } } /** * Lookup in the namecache for the shorten zone the given label. * * @param gph the handle to our shorten operation * @param label the label to lookup */ static void perform_nick_lookup (struct GetPseuAuthorityHandle *gph, const char *label) { struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_HashCode query; GNUNET_CRYPTO_ecdsa_key_get_public (&gph->shorten_zone_key, &pub); GNUNET_free_non_null (gph->current_label); gph->current_label = GNUNET_strdup (label); GNUNET_GNSRECORD_query_from_public_key (&pub, label, &query); gph->namecache_task = GNUNET_NAMECACHE_lookup_block (namecache_handle, &query, &process_pseu_block_ns, gph); } /** * Namestore calls this function if we have record for this name. * (or with rd_count=0 to indicate no matches). * * @param cls the pending query * @param rd_count the number of records with 'name' * @param rd the record data */ static void process_pseu_lookup_ns (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GetPseuAuthorityHandle *gph = cls; struct GNUNET_GNSRECORD_Data new_pkey; gph->namestore_task = NULL; if (rd_count > 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' already taken, cannot shorten.\n", gph->current_label); /* if this was not yet the original label, try one more time, this time not using PSEU but the original label */ if (0 == strcmp (gph->current_label, gph->label)) { free_get_pseu_authority_handle (gph); } else { perform_nick_lookup (gph, gph->label); } return; } /* name is available */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shortening `%s' to `%s'\n", GNUNET_GNSRECORD_z2s (&gph->target_zone), gph->current_label); new_pkey.expiration_time = UINT64_MAX; new_pkey.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); new_pkey.data = &gph->target_zone; new_pkey.record_type = GNUNET_GNSRECORD_TYPE_PKEY; new_pkey.flags = GNUNET_GNSRECORD_RF_NONE | GNUNET_GNSRECORD_RF_PRIVATE; gph->namestore_task = GNUNET_NAMESTORE_records_store (namestore_handle, &gph->shorten_zone_key, gph->current_label, 1, &new_pkey, &create_pkey_cont, gph); } /** * Callback called by namestore for a zone to name result. We're * trying to see if a short name for a given zone already exists. * * @param cls the closure * @param zone_key the zone we queried * @param name the name found or NULL * @param rd_len number of records for the name * @param rd the record data (PKEY) for the name */ static void process_zone_to_name_discover (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { struct GetPseuAuthorityHandle* gph = cls; #if 0 struct GNUNET_HashCode lookup_key; #endif gph->namestore_task = NULL; if (0 != rd_len) { /* we found a match in our own zone */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shortening aborted, name `%s' already reserved for the zone\n", name); free_get_pseu_authority_handle (gph); return; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shortening continuing, no name not reserved in shorten zone\n"); } /* record does not yet exist, check if suggested label is available */ perform_nick_lookup (gph, gph->suggested_label); } /** * Start shortening algorithm, try to allocate a nice short * canonical name for @a pub in @a shorten_zone, using * @a original_label as one possible suggestion. * * @param original_label original label for the zone * @param suggested_label suggested label for the zone * @param pub public key of the zone to shorten * @param shorten_zone private key of the target zone for the new record */ void GNS_shorten_start (const char *original_label, const char *suggested_label, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone) { struct GetPseuAuthorityHandle *gph; struct GNUNET_CRYPTO_EcdsaPublicKey shorten_pub; if (strlen (original_label) > GNUNET_DNSPARSER_MAX_LABEL_LENGTH) { GNUNET_break (0); return; } GNUNET_CRYPTO_ecdsa_key_get_public (shorten_zone, &shorten_pub); if (0 == memcmp (&shorten_pub, pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) { /* Do not shorten the shorten zone */ return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting shortening process for `%s' with old label `%s' and suggested nickname `%s'\n", GNUNET_GNSRECORD_z2s (pub), original_label, suggested_label); gph = GNUNET_new (struct GetPseuAuthorityHandle); gph->shorten_zone_key = *shorten_zone; gph->target_zone = *pub; gph->suggested_label = GNUNET_strdup (suggested_label); strcpy (gph->label, original_label); GNUNET_CONTAINER_DLL_insert (gph_head, gph_tail, gph); /* first, check if we *already* have a record for this zone */ gph->namestore_task = GNUNET_NAMESTORE_zone_to_name (namestore_handle, shorten_zone, pub, &process_zone_to_name_discover, gph); } /** * Initialize the shortening subsystem * * @param nh the namestore handle * @param nc the namecache handle * @param dht the dht handle */ void GNS_shorten_init (struct GNUNET_NAMESTORE_Handle *nh, struct GNUNET_NAMECACHE_Handle *nc, struct GNUNET_DHT_Handle *dht) { namestore_handle = nh; namecache_handle = nc; dht_handle = dht; } /** * Shutdown shortening. */ void GNS_shorten_done () { /* abort active shorten operations */ while (NULL != gph_head) free_get_pseu_authority_handle (gph_head); dht_handle = NULL; namestore_handle = NULL; namecache_handle = NULL; } /* end of gnunet-service-gns_shorten.c */ gnunet-0.10.1/src/gns/gnunet-service-gns_resolver.c0000644000175000017500000020564712305564547017231 00000000000000/* This file is part of GNUnet. (C) 2011-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gnunet-service-gns_resolver.c * @brief GNU Name System resolver logic * @author Martin Schanzenbach * @author Christian Grothoff * * TODO: * - GNS: handle special SRV names --- no delegation, direct lookup; * can likely be done in 'resolver_lookup_get_next_label'. (#3003) * - revocation checks (use REVOCATION service!), (#3004) * - DNAME support (#3005) */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dnsstub_lib.h" #include "gnunet_dht_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_dns_service.h" #include "gnunet_resolver_service.h" #include "gnunet_revocation_service.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_tun_lib.h" #include "gnunet_gns_service.h" #include "gns.h" #include "gnunet-service-gns_resolver.h" #include "gnunet-service-gns_shorten.h" #include "gnunet_vpn_service.h" /** * Default DHT timeout for lookups. */ #define DHT_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * Default timeout for DNS lookups. */ #define DNS_LOOKUP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Default timeout for VPN redirections. */ #define VPN_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) /** * DHT replication level */ #define DHT_GNS_REPLICATION_LEVEL 5 /** * How deep do we allow recursions to go before we abort? */ #define MAX_RECURSION 256 /** * DLL to hold the authority chain we had to pass in the resolution * process. */ struct AuthorityChain { /** * This is a DLL. */ struct AuthorityChain *prev; /** * This is a DLL. */ struct AuthorityChain *next; /** * Resolver handle this entry in the chain belongs to. */ struct GNS_ResolverHandle *rh; /** * label/name corresponding to the authority */ char *label; /** * label/name suggested for shortening to the authority */ char *suggested_shortening_label; /** * Do we already try to shorten this authority? */ int shortening_started; /** * #GNUNET_YES if the authority was a GNS authority, * #GNUNET_NO if the authority was a DNS authority. */ int gns_authority; /** * Information about the resolver authority for this label. */ union { /** * The zone of the GNS authority */ struct GNUNET_CRYPTO_EcdsaPublicKey gns_authority; struct { /** * Domain of the DNS resolver that is the authority. * (appended to construct the DNS name to resolve; * this is NOT the DNS name of the DNS server!). */ char name[GNUNET_DNSPARSER_MAX_NAME_LENGTH + 1]; /** * IP address of the DNS resolver that is authoritative. * (this implementation currently only supports one * IP at a time). */ struct sockaddr_storage dns_ip; } dns_authority; } authority_info; }; /** * A result we got from DNS. */ struct DnsResult { /** * Kept in DLL. */ struct DnsResult *next; /** * Kept in DLL. */ struct DnsResult *prev; /** * Binary value stored in the DNS record (appended to this struct) */ const void *data; /** * Expiration time for the DNS record, 0 if we didn't * get anything useful (i.e. 'gethostbyname' was used). */ uint64_t expiration_time; /** * Number of bytes in @e data. */ size_t data_size; /** * Type of the GNS/DNS record. */ uint32_t record_type; }; /** * Closure for #vpn_allocation_cb. */ struct VpnContext { /** * Which resolution process are we processing. */ struct GNS_ResolverHandle *rh; /** * Handle to the VPN request that we were performing. */ struct GNUNET_VPN_RedirectionRequest *vpn_request; /** * Number of records serialized in @e rd_data. */ unsigned int rd_count; /** * Serialized records. */ char *rd_data; /** * Number of bytes in @e rd_data. */ size_t rd_data_size; }; /** * Information we keep during the resolution of an * IP address for a DNS server while handling a * GNS2DNS record. */ struct Gns2DnsContext { /** * DNS domain in which the resolution will continue * (first part of the GNS2DNS record). */ char *ns; /** * Handle for the resolution of the IP part of the * GNS2DNS record. Will return to us the addresses * of the DNS resolver to use. */ struct GNS_ResolverHandle *rh; }; /** * Handle to a currenty pending resolution. On result (positive or * negative) the #GNS_ResultProcessor is called. */ struct GNS_ResolverHandle { /** * DLL */ struct GNS_ResolverHandle *next; /** * DLL */ struct GNS_ResolverHandle *prev; /** * The top-level GNS authoritative zone to query */ struct GNUNET_CRYPTO_EcdsaPublicKey authority_zone; /** * called when resolution phase finishes */ GNS_ResultProcessor proc; /** * closure passed to @e proc */ void* proc_cls; /** * Handle used during GNS2DNS resolution for looking up the * IP address of the DNS server. */ struct Gns2DnsContext *g2dc; /** * Handle for DHT lookups. should be NULL if no lookups are in progress */ struct GNUNET_DHT_GetHandle *get_handle; /** * Handle to a VPN request, NULL if none is active. */ struct VpnContext *vpn_ctx; /** * Socket for a DNS request, NULL if none is active. */ struct GNUNET_DNSSTUB_RequestSocket *dns_request; /** * Handle for standard DNS resolution, NULL if none is active. */ struct GNUNET_RESOLVER_RequestHandle *std_resolve; /** * Pending Namecache lookup task */ struct GNUNET_NAMECACHE_QueueEntry *namecache_qe; /** * Pending revocation check. */ struct GNUNET_REVOCATION_Query *rev_check; /** * Heap node associated with this lookup. Used to limit number of * concurrent requests. */ struct GNUNET_CONTAINER_HeapNode *dht_heap_node; /** * DLL to store the authority chain */ struct AuthorityChain *ac_head; /** * DLL to store the authority chain */ struct AuthorityChain *ac_tail; /** * Private key of the shorten zone, NULL to not shorten. */ struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_key; /** * ID of a task associated with the resolution process. */ GNUNET_SCHEDULER_TaskIdentifier task_id; /** * The name to resolve */ char *name; /** * DLL of results we got from DNS. */ struct DnsResult *dns_result_head; /** * DLL of results we got from DNS. */ struct DnsResult *dns_result_tail; /** * Current offset in 'name' where we are resolving. */ size_t name_resolution_pos; /** * Use only cache */ enum GNUNET_GNS_LocalOptions options; /** * Desired type for the resolution. */ int record_type; /** * We increment the loop limiter for each step in a recursive * resolution. If it passes our threshold (i.e. due to * self-recursion in the resolution, i.e CNAME fun), we stop. */ unsigned int loop_limiter; }; /** * Active namestore caching operations. */ struct CacheOps { /** * Organized in a DLL. */ struct CacheOps *next; /** * Organized in a DLL. */ struct CacheOps *prev; /** * Pending Namestore caching task. */ struct GNUNET_NAMECACHE_QueueEntry *namecache_qe_cache; }; /** * Our handle to the namecache service */ static struct GNUNET_NAMECACHE_Handle *namecache_handle; /** * Our handle to the vpn service */ static struct GNUNET_VPN_Handle *vpn_handle; /** * Resolver handle to the dht */ static struct GNUNET_DHT_Handle *dht_handle; /** * Handle to perform DNS lookups. */ static struct GNUNET_DNSSTUB_Context *dns_handle; /** * Heap for limiting parallel DHT lookups */ static struct GNUNET_CONTAINER_Heap *dht_lookup_heap; /** * Maximum amount of parallel queries to the DHT */ static unsigned long long max_allowed_background_queries; /** * Head of resolver lookup list */ static struct GNS_ResolverHandle *rlh_head; /** * Tail of resolver lookup list */ static struct GNS_ResolverHandle *rlh_tail; /** * Organized in a DLL. */ static struct CacheOps *co_head; /** * Organized in a DLL. */ static struct CacheOps *co_tail; /** * Use namecache */ static int use_cache; /** * Global configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; #if 0 /** * Check if name is in srv format (_x._y.xxx) * * @param name * @return #GNUNET_YES if true */ static int is_srv (const char *name) { char *ndup; int ret; if (*name != '_') return GNUNET_NO; if (NULL == strstr (name, "._")) return GNUNET_NO; ret = GNUNET_YES; ndup = GNUNET_strdup (name); strtok (ndup, "."); if (NULL == strtok (NULL, ".")) ret = GNUNET_NO; if (NULL == strtok (NULL, ".")) ret = GNUNET_NO; if (NULL != strtok (NULL, ".")) ret = GNUNET_NO; GNUNET_free (ndup); return ret; } #endif /** * Determine if this name is canonical (is a legal name in a zone, without delegation); * note that we do not test that the name does not contain illegal characters, we only * test for delegation. Note that service records (i.e. _foo._srv) are canonical names * even though they consist of multiple labels. * * Examples: * a.b.gnu = not canonical * a = canonical * _foo._srv = canonical * _f.bar = not canonical * * @param name the name to test * @return #GNUNET_YES if canonical */ static int is_canonical (const char *name) { const char *pos; const char *dot; if (NULL == strchr (name, '.')) return GNUNET_YES; if ('_' != name[0]) return GNUNET_NO; pos = &name[1]; while (NULL != (dot = strchr (pos, '.'))) if ('_' != dot[1]) return GNUNET_NO; else pos = dot + 1; return GNUNET_YES; } /* ************************** Resolution **************************** */ /** * Expands a name ending in .+ with the zone of origin. * * @param rh resolution context * @param name name to modify (to be free'd or returned) * @return updated name */ static char * translate_dot_plus (struct GNS_ResolverHandle *rh, char *name) { char *ret; size_t s_len = strlen (name); if (0 != strcmp (&name[s_len - 2], ".+")) return name; /* did not end in ".+" */ GNUNET_assert (GNUNET_YES == rh->ac_tail->gns_authority); GNUNET_asprintf (&ret, "%.*s.%s", (int) (s_len - 2), name, GNUNET_GNSRECORD_pkey_to_zkey (&rh->ac_tail->authority_info.gns_authority)); GNUNET_free (name); return ret; } /** * Task scheduled to asynchronously fail a resolution. * * @param cls the 'struct GNS_ResolverHandle' of the resolution to fail * @param tc task context */ static void fail_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNS_ResolverHandle *rh = cls; rh->task_id = GNUNET_SCHEDULER_NO_TASK; rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); } #if (defined WINDOWS) || (defined DARWIN) /* Don't have this on W32, here's a naive implementation * Was somehow removed on OS X ... */ void * memrchr (const void *s, int c, size_t n) { const unsigned char *ucs = s; ssize_t i; for (i = n - 1; i >= 0; i--) if (c == (int) ucs[i]) return (void *) &ucs[i]; return NULL; } #endif /** * Get the next, rightmost label from the name that we are trying to resolve, * and update the resolution position accordingly. * * @param rh handle to the resolution operation to get the next label from * @return NULL if there are no more labels */ static char * resolver_lookup_get_next_label (struct GNS_ResolverHandle *rh) { const char *rp; const char *dot; size_t len; if (0 == rh->name_resolution_pos) return NULL; dot = memrchr (rh->name, (int) '.', rh->name_resolution_pos); if (NULL == dot) { /* done, this was the last one */ len = rh->name_resolution_pos; rp = rh->name; rh->name_resolution_pos = 0; } else { /* advance by one label */ len = rh->name_resolution_pos - (dot - rh->name) - 1; rp = dot + 1; rh->name_resolution_pos = dot - rh->name; } return GNUNET_strndup (rp, len); } /** * Gives the cummulative result obtained to the callback and clean up the request. * * @param rh resolution process that has culminated in a result */ static void transmit_lookup_dns_result (struct GNS_ResolverHandle *rh) { struct DnsResult *pos; unsigned int n; unsigned int i; n = 0; for (pos = rh->dns_result_head; NULL != pos; pos = pos->next) n++; { struct GNUNET_GNSRECORD_Data rd[n]; i = 0; for (pos = rh->dns_result_head; NULL != pos; pos = pos->next) { rd[i].data = pos->data; rd[i].data_size = pos->data_size; rd[i].record_type = pos->record_type; if (0 == pos->expiration_time) { rd[i].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; rd[i].expiration_time = 0; } else { rd[i].flags = GNUNET_GNSRECORD_RF_NONE; rd[i].expiration_time = pos->expiration_time; } i++; } GNUNET_assert (i == n); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting standard DNS result with %u records\n", n); rh->proc (rh->proc_cls, n, rd); } GNS_resolver_lookup_cancel (rh); } /** * Add a result from DNS to the records to be returned to the application. * * @param rh resolution request to extend with a result * @param expiration_time expiration time for the answer * @param record_type DNS record type of the answer * @param data_size number of bytes in @a data * @param data binary data to return in DNS record */ static void add_dns_result (struct GNS_ResolverHandle *rh, uint64_t expiration_time, uint32_t record_type, size_t data_size, const void *data) { struct DnsResult *res; res = GNUNET_malloc (sizeof (struct DnsResult) + data_size); res->expiration_time = expiration_time; res->data_size = data_size; res->record_type = record_type; res->data = &res[1]; memcpy (&res[1], data, data_size); GNUNET_CONTAINER_DLL_insert (rh->dns_result_head, rh->dns_result_tail, res); } /** * We had to do a DNS lookup. Convert the result (if any) and return * it. * * @param cls closure with the `struct GNS_ResolverHandle` * @param addr one of the addresses of the host, NULL for the last address * @param addrlen length of the address */ static void handle_dns_result (void *cls, const struct sockaddr *addr, socklen_t addrlen) { struct GNS_ResolverHandle *rh = cls; const struct sockaddr_in *sa4; const struct sockaddr_in6 *sa6; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes of DNS IP data\n", addrlen); if (NULL == addr) { rh->std_resolve = NULL; transmit_lookup_dns_result (rh); return; } switch (addr->sa_family) { case AF_INET: sa4 = (const struct sockaddr_in *) addr; add_dns_result (rh, 0 /* expiration time is unknown */, GNUNET_DNSPARSER_TYPE_A, sizeof (struct in_addr), &sa4->sin_addr); break; case AF_INET6: sa6 = (const struct sockaddr_in6 *) addr; add_dns_result (rh, 0 /* expiration time is unknown */, GNUNET_DNSPARSER_TYPE_AAAA, sizeof (struct in6_addr), &sa6->sin6_addr); break; default: GNUNET_break (0); break; } } /** * Task scheduled to continue with the resolution process. * * @param cls the 'struct GNS_ResolverHandle' of the resolution * @param tc task context */ static void recursive_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Begin the resolution process from 'name', starting with * the identification of the zone specified by 'name'. * * @param rh resolution to perform */ static void start_resolver_lookup (struct GNS_ResolverHandle *rh); /** * Function called with the result of a DNS resolution. * * @param cls the request handle of the resolution that * we were attempting to make * @param rs socket that received the response * @param dns dns response, never NULL * @param dns_len number of bytes in @a dns */ static void dns_result_parser (void *cls, struct GNUNET_DNSSTUB_RequestSocket *rs, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len) { struct GNS_ResolverHandle *rh = cls; struct GNUNET_DNSPARSER_Packet *p; const struct GNUNET_DNSPARSER_Record *rec; unsigned int rd_count; unsigned int i; rh->dns_request = NULL; GNUNET_SCHEDULER_cancel (rh->task_id); rh->task_id = GNUNET_SCHEDULER_NO_TASK; p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len); if (NULL == p) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to parse DNS response\n")); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received DNS response for `%s' with %u answers\n", rh->ac_tail->label, (unsigned int) p->num_answers); if ( (p->num_answers > 0) && (GNUNET_DNSPARSER_TYPE_CNAME == p->answers[0].type) && (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) ) { GNUNET_free (rh->name); rh->name = GNUNET_strdup (p->answers[0].data.hostname); start_resolver_lookup (rh); GNUNET_DNSPARSER_free_packet (p); return; } /* FIXME: add DNAME support */ /* convert from (parsed) DNS to (binary) GNS format! */ rd_count = p->num_answers + p->num_authority_records + p->num_additional_records; { struct GNUNET_GNSRECORD_Data rd[rd_count]; unsigned int skip; char buf[UINT16_MAX]; size_t buf_off; size_t buf_start; buf_off = 0; skip = 0; memset (rd, 0, sizeof (rd)); for (i=0;inum_answers) rec = &p->answers[i]; else if (i < p->num_answers + p->num_authority_records) rec = &p->authority_records[i - p->num_answers]; else rec = &p->authority_records[i - p->num_answers - p->num_authority_records]; /* As we copied the full DNS name to 'rh->ac_tail->label', this should be the correct check to see if this record is actually a record for our label... */ if (0 != strcmp (rec->name, rh->ac_tail->label)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dropping record `%s', does not match desired name `%s'\n", rec->name, rh->ac_tail->label); skip++; continue; } rd[i - skip].record_type = rec->type; rd[i - skip].expiration_time = rec->expiration_time.abs_value_us; switch (rec->type) { case GNUNET_DNSPARSER_TYPE_A: if (rec->data.raw.data_len != sizeof (struct in_addr)) { GNUNET_break_op (0); skip++; continue; } rd[i - skip].data_size = rec->data.raw.data_len; rd[i - skip].data = rec->data.raw.data; break; case GNUNET_DNSPARSER_TYPE_AAAA: if (rec->data.raw.data_len != sizeof (struct in6_addr)) { GNUNET_break_op (0); skip++; continue; } rd[i - skip].data_size = rec->data.raw.data_len; rd[i - skip].data = rec->data.raw.data; break; case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: case GNUNET_DNSPARSER_TYPE_NS: buf_start = buf_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (buf, sizeof (buf), &buf_off, rec->data.hostname)) { GNUNET_break (0); skip++; continue; } rd[i - skip].data_size = buf_off - buf_start; rd[i - skip].data = &buf[buf_start]; break; case GNUNET_DNSPARSER_TYPE_SOA: buf_start = buf_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_soa (buf, sizeof (buf), &buf_off, rec->data.soa)) { GNUNET_break (0); skip++; continue; } rd[i - skip].data_size = buf_off - buf_start; rd[i - skip].data = &buf[buf_start]; break; case GNUNET_DNSPARSER_TYPE_MX: buf_start = buf_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_mx (buf, sizeof (buf), &buf_off, rec->data.mx)) { GNUNET_break (0); skip++; continue; } rd[i - skip].data_size = buf_off - buf_start; rd[i - skip].data = &buf[buf_start]; break; case GNUNET_DNSPARSER_TYPE_SRV: buf_start = buf_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_srv (buf, sizeof (buf), &buf_off, rec->data.srv)) { GNUNET_break (0); skip++; continue; } rd[i - skip].data_size = buf_off - buf_start; rd[i - skip].data = &buf[buf_start]; break; default: GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Skipping record of unsupported type %d\n"), rec->type); skip++; continue; } } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning DNS response for `%s' with %u answers\n", rh->ac_tail->label, (unsigned int) p->num_answers); rh->proc (rh->proc_cls, rd_count - skip, rd); GNS_resolver_lookup_cancel (rh); } GNUNET_DNSPARSER_free_packet (p); } /** * Perform recursive DNS resolution. Asks the given DNS resolver to * resolve "rh->dns_name", possibly recursively proceeding following * NS delegations, CNAMES, etc., until 'rh->loop_limiter' bounds us or * we find the answer. * * @param rh resolution information */ static void recursive_dns_resolution (struct GNS_ResolverHandle *rh) { struct AuthorityChain *ac; socklen_t sa_len; struct GNUNET_DNSPARSER_Query *query; struct GNUNET_DNSPARSER_Packet *p; char *dns_request; size_t dns_request_length; ac = rh->ac_tail; GNUNET_assert (NULL != ac); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting DNS lookup for `%s'\n", ac->label); GNUNET_assert (GNUNET_NO == ac->gns_authority); switch (((const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip)->sa_family) { case AF_INET: sa_len = sizeof (struct sockaddr_in); break; case AF_INET6: sa_len = sizeof (struct sockaddr_in6); break; default: GNUNET_break (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } query = GNUNET_new (struct GNUNET_DNSPARSER_Query); query->name = GNUNET_strdup (ac->label); query->type = rh->record_type; query->dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; p = GNUNET_new (struct GNUNET_DNSPARSER_Packet); p->queries = query; p->num_queries = 1; p->id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT16_MAX); p->flags.opcode = GNUNET_TUN_DNS_OPCODE_QUERY; p->flags.recursion_desired = 1; if (GNUNET_OK != GNUNET_DNSPARSER_pack (p, 1024, &dns_request, &dns_request_length)) { GNUNET_break (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); } else { rh->dns_request = GNUNET_DNSSTUB_resolve (dns_handle, (const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip, sa_len, dns_request, dns_request_length, &dns_result_parser, rh); rh->task_id = GNUNET_SCHEDULER_add_delayed (DNS_LOOKUP_TIMEOUT, &fail_resolution, rh); } GNUNET_free (dns_request); GNUNET_DNSPARSER_free_packet (p); } /** * We encountered a CNAME record during our resolution. * Merge it into our chain. * * @param rh resolution we are performing * @param cname value of the cname record we got for the current * authority chain tail */ static void handle_gns_cname_result (struct GNS_ResolverHandle *rh, const char *cname) { size_t nlen; char *res; struct AuthorityChain *ac; nlen = strlen (cname); if ( (nlen > 2) && (0 == strcmp (".+", &cname[nlen - 2])) ) { /* CNAME resolution continues relative to current domain */ if (0 == rh->name_resolution_pos) { res = GNUNET_strndup (cname, nlen - 2); rh->name_resolution_pos = nlen - 2; } else { GNUNET_asprintf (&res, "%.*s.%.*s", (int) rh->name_resolution_pos, rh->name, (int) (nlen - 2), cname); rh->name_resolution_pos = strlen (res); } GNUNET_free (rh->name); rh->name = res; ac = GNUNET_new (struct AuthorityChain); ac->rh = rh; ac->gns_authority = GNUNET_YES; ac->authority_info.gns_authority = rh->ac_tail->authority_info.gns_authority; ac->label = resolver_lookup_get_next_label (rh); ac->suggested_shortening_label = NULL; ac->shortening_started = GNUNET_NO; /* add AC to tail */ GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, rh->ac_tail, ac); rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, rh); return; } /* name is absolute, start from the beginning */ GNUNET_free (rh->name); rh->name = GNUNET_strdup (cname); start_resolver_lookup (rh); } /** * Process a records that were decrypted from a block. * * @param cls closure with the 'struct GNS_ResolverHandle' * @param rd_count number of entries in @a rd array * @param rd array of records with data to store */ static void handle_gns_resolution_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); /** * Callback invoked from the VPN service once a redirection is * available. Provides the IP address that can now be used to * reach the requested destination. Replaces the "VPN" record * with the respective A/AAAA record and continues processing. * * @param cls closure * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; * will match 'result_af' from the request * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') * that the VPN allocated for the redirection; * traffic to this IP will now be redirected to the * specified target peer; NULL on error */ static void vpn_allocation_cb (void *cls, int af, const void *address) { struct VpnContext *vpn_ctx = cls; struct GNS_ResolverHandle *rh = vpn_ctx->rh; struct GNUNET_GNSRECORD_Data rd[vpn_ctx->rd_count]; unsigned int i; vpn_ctx->vpn_request = NULL; rh->vpn_ctx = NULL; GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_records_deserialize (vpn_ctx->rd_data_size, vpn_ctx->rd_data, vpn_ctx->rd_count, rd)); for (i=0;ird_count;i++) { if (GNUNET_GNSRECORD_TYPE_VPN == rd[i].record_type) { switch (af) { case AF_INET: rd[i].record_type = GNUNET_DNSPARSER_TYPE_A; rd[i].data_size = sizeof (struct in_addr); rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT).abs_value_us; rd[i].flags = 0; rd[i].data = address; break; case AF_INET6: rd[i].record_type = GNUNET_DNSPARSER_TYPE_AAAA; rd[i].expiration_time = GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT).abs_value_us; rd[i].flags = 0; rd[i].data = address; rd[i].data_size = sizeof (struct in6_addr); break; default: GNUNET_assert (0); } break; } } GNUNET_assert (i < vpn_ctx->rd_count); handle_gns_resolution_result (rh, vpn_ctx->rd_count, rd); GNUNET_free (vpn_ctx->rd_data); GNUNET_free (vpn_ctx); } /** * We've resolved the IP address for the DNS resolver to use * after encountering a GNS2DNS record. * * TODO: Right now we only foward the request to ONE DNS resolver, * even if we get multiple IP addresses back; a correct implementation * should try all DNS resolvers. * * @param cls the `struct GNS_ResolverHandle` where we encountered * the GNS2DNS record * @param rd_count number of records in @a rd * @param rd addresses for the DNS resolver (presumably) */ static void handle_gns2dns_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNS_ResolverHandle *rh = cls; struct AuthorityChain *ac; unsigned int j; struct sockaddr *sa; struct sockaddr_in v4; struct sockaddr_in6 v6; size_t sa_len; /* find suitable A/AAAA record */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u results for IP address of DNS server for GNS2DNS transition\n", rd_count); /* enable cleanup of 'rh' handle that comes next... */ GNUNET_CONTAINER_DLL_insert (rlh_head, rlh_tail, rh->g2dc->rh); rh->g2dc->rh = NULL; sa = NULL; sa_len = 0; for (j=0;jproc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } /* FIXME: might want to check if we support IPv4 here, and otherwise skip this one and hope we find another */ memset (&v4, 0, sizeof (v4)); sa_len = sizeof (v4); v4.sin_family = AF_INET; v4.sin_port = htons (53); #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = (u_char) sa_len; #endif memcpy (&v4.sin_addr, rd[j].data, sizeof (struct in_addr)); sa = (struct sockaddr *) &v4; break; case GNUNET_DNSPARSER_TYPE_AAAA: if (sizeof (struct in6_addr) != rd[j].data_size) { GNUNET_break_op (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } /* FIXME: might want to check if we support IPv6 here, and otherwise skip this one and hope we find another */ memset (&v6, 0, sizeof (v6)); sa_len = sizeof (v6); v6.sin6_family = AF_INET6; v6.sin6_port = htons (53); #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = (u_char) sa_len; #endif memcpy (&v6.sin6_addr, rd[j].data, sizeof (struct in6_addr)); sa = (struct sockaddr *) &v6; break; default: break; } if (NULL != sa) break; } if (NULL == sa) { /* we cannot continue; NS without A/AAAA */ rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } /* expand authority chain */ ac = GNUNET_new (struct AuthorityChain); ac->rh = rh; strcpy (ac->authority_info.dns_authority.name, rh->g2dc->ns); memcpy (&ac->authority_info.dns_authority.dns_ip, sa, sa_len); /* for DNS recursion, the label is the full DNS name, created from the remainder of the GNS name and the name in the NS record */ GNUNET_asprintf (&ac->label, "%.*s%s%s", (int) rh->name_resolution_pos, rh->name, (0 != rh->name_resolution_pos) ? "." : "", rh->g2dc->ns); GNUNET_free (rh->g2dc->ns); GNUNET_free (rh->g2dc); rh->g2dc = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will continue resolution using DNS server `%s' to resolve `%s'\n", GNUNET_a2s (sa, sa_len), ac->label); GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, rh->ac_tail, ac); if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("GNS lookup resulted in DNS name that is too long (`%s')\n"), ac->label); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } /* recurse */ rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, rh); } /** * Process a records that were decrypted from a block. * * @param cls closure with the `struct GNS_ResolverHandle` * @param rd_count number of entries in @a rd array * @param rd array of records with data to store */ static void handle_gns_resolution_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNS_ResolverHandle *rh = cls; struct AuthorityChain *ac; struct AuthorityChain *shorten_ac; unsigned int i; char *cname; struct VpnContext *vpn_ctx; const struct GNUNET_TUN_GnsVpnRecord *vpn; const char *vname; struct GNUNET_HashCode vhash; int af; char scratch[UINT16_MAX]; size_t scratch_off; size_t scratch_start; size_t off; struct GNUNET_GNSRECORD_Data rd_new[rd_count]; unsigned int rd_off; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Resolution succeeded for `%s' in zone %s, got %u records\n", rh->ac_tail->label, GNUNET_GNSRECORD_z2s (&rh->ac_tail->authority_info.gns_authority), rd_count); if (0 == rh->name_resolution_pos) { /* top-level match, are we done yet? */ if ( (rd_count > 0) && (GNUNET_DNSPARSER_TYPE_CNAME == rd[0].record_type) && (GNUNET_DNSPARSER_TYPE_CNAME != rh->record_type) ) { off = 0; cname = GNUNET_DNSPARSER_parse_name (rd[0].data, rd[0].data_size, &off); if ( (NULL == cname) || (off != rd[0].data_size) ) { GNUNET_break_op (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); GNUNET_free_non_null (cname); return; } handle_gns_cname_result (rh, cname); GNUNET_free (cname); return; } /* If A/AAAA was requested, but we got a VPN record, we convert it to A/AAAA using GNUnet VPN */ if ( (GNUNET_DNSPARSER_TYPE_A == rh->record_type) || (GNUNET_DNSPARSER_TYPE_AAAA == rh->record_type) ) { for (i=0;irecord_type) ? AF_INET : AF_INET6; if (sizeof (struct GNUNET_TUN_GnsVpnRecord) > rd[i].data_size) { GNUNET_break_op (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } vpn = (const struct GNUNET_TUN_GnsVpnRecord *) rd[i].data; vname = (const char *) &vpn[1]; if ('\0' != vname[rd[i].data_size - 1 - sizeof (struct GNUNET_TUN_GnsVpnRecord)]) { GNUNET_break_op (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } GNUNET_TUN_service_name_to_hash (vname, &vhash); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Attempting VPN allocation for %s-%s (AF: %d, proto %d)\n", GNUNET_i2s (&vpn->peer), vname, (int) af, (int) ntohs (vpn->proto)); vpn_ctx = GNUNET_new (struct VpnContext); rh->vpn_ctx = vpn_ctx; vpn_ctx->rh = rh; vpn_ctx->rd_data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd); vpn_ctx->rd_data = GNUNET_malloc (vpn_ctx->rd_data_size); vpn_ctx->rd_count = rd_count; GNUNET_assert (vpn_ctx->rd_data_size == GNUNET_GNSRECORD_records_serialize (rd_count, rd, vpn_ctx->rd_data_size, vpn_ctx->rd_data)); vpn_ctx->vpn_request = GNUNET_VPN_redirect_to_peer (vpn_handle, af, ntohs (vpn->proto), &vpn->peer, &vhash, GNUNET_TIME_relative_to_absolute (VPN_TIMEOUT), &vpn_allocation_cb, vpn_ctx); return; } case GNUNET_GNSRECORD_TYPE_GNS2DNS: { /* delegation to DNS */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found GNS2DNS record, delegating to DNS!\n"); goto do_recurse; } default: break; } /* end: switch */ } /* end: for rd */ } /* end: name_resolution_pos */ /* convert relative names in record values to absolute names, using 'scratch' array for memory allocations */ scratch_off = 0; rd_off = 0; shorten_ac = rh->ac_tail; for (i=0;imname = translate_dot_plus (rh, soa->mname); soa->rname = translate_dot_plus (rh, soa->rname); scratch_start = scratch_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_soa (scratch, sizeof (scratch), &scratch_off, soa)) { GNUNET_break (0); } else { rd_new[rd_off].data = &scratch[scratch_start]; rd_new[rd_off].data_size = scratch_off - scratch_start; rd_off++; } } if (NULL != soa) GNUNET_DNSPARSER_free_soa (soa); } break; case GNUNET_DNSPARSER_TYPE_MX: { struct GNUNET_DNSPARSER_MxRecord *mx; off = 0; mx = GNUNET_DNSPARSER_parse_mx (rd[i].data, rd[i].data_size, &off); if ( (NULL == mx) || (off != rd[i].data_size) ) { GNUNET_break_op (0); /* record not well-formed */ } else { mx->mxhost = translate_dot_plus (rh, mx->mxhost); scratch_start = scratch_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_mx (scratch, sizeof (scratch), &scratch_off, mx)) { GNUNET_break (0); } else { rd_new[rd_off].data = &scratch[scratch_start]; rd_new[rd_off].data_size = scratch_off - scratch_start; rd_off++; } } if (NULL != mx) GNUNET_DNSPARSER_free_mx (mx); } break; case GNUNET_DNSPARSER_TYPE_SRV: { struct GNUNET_DNSPARSER_SrvRecord *srv; off = 0; /* FIXME: passing rh->name here is is not necessarily what we want (SRV support not finished) */ srv = GNUNET_DNSPARSER_parse_srv (rh->name, rd[i].data, rd[i].data_size, &off); if ( (NULL == srv) || (off != rd[i].data_size) ) { GNUNET_break_op (0); /* record not well-formed */ } else { srv->domain_name = translate_dot_plus (rh, srv->domain_name); srv->target = translate_dot_plus (rh, srv->target); scratch_start = scratch_off; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_srv (scratch, sizeof (scratch), &scratch_off, srv)) { GNUNET_break (0); } else { rd_new[rd_off].data = &scratch[scratch_start]; rd_new[rd_off].data_size = scratch_off - scratch_start; rd_off++; } } if (NULL != srv) GNUNET_DNSPARSER_free_srv (srv); } break; case GNUNET_GNSRECORD_TYPE_NICK: { const char *nick; nick = rd[i].data; if ((rd[i].data_size > 0) && (nick[rd[i].data_size -1] != '\0')) { GNUNET_break_op (0); break; } if (NULL == shorten_ac->suggested_shortening_label) shorten_ac->suggested_shortening_label = GNUNET_strdup (nick); break; } case GNUNET_GNSRECORD_TYPE_PKEY: { struct GNUNET_CRYPTO_EcdsaPublicKey pub; if (rd[i].data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) { GNUNET_break_op (0); break; } memcpy (&pub, rd[i].data, rd[i].data_size); rd_off++; if (GNUNET_GNSRECORD_TYPE_PKEY != rh->record_type) { /* try to resolve "+" */ struct AuthorityChain *ac; ac = GNUNET_new (struct AuthorityChain); ac->rh = rh; ac->gns_authority = GNUNET_YES; ac->authority_info.gns_authority = pub; ac->label = GNUNET_strdup (GNUNET_GNS_MASTERZONE_STR); ac->suggested_shortening_label = NULL; ac->shortening_started = GNUNET_NO; GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, rh->ac_tail, ac); rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, rh); return; } } break; case GNUNET_GNSRECORD_TYPE_GNS2DNS: { /* delegation to DNS */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found GNS2DNS record, delegating to DNS!\n"); goto do_recurse; } default: rd_off++; break; } /* end: switch */ } /* end: for rd_count */ /* trigger shortening */ if ((NULL != rh->shorten_key) && (NULL != shorten_ac) && (GNUNET_NO == shorten_ac->shortening_started) && (NULL != shorten_ac->suggested_shortening_label)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start shortening for label `%s' based on nick `%s'\n", shorten_ac->label, shorten_ac->suggested_shortening_label); shorten_ac->shortening_started = GNUNET_YES; GNS_shorten_start (shorten_ac->label, shorten_ac->suggested_shortening_label, &shorten_ac->authority_info.gns_authority, rh->shorten_key); } /* yes, we are done, return result */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning GNS response for `%s' with %u answers\n", rh->ac_tail->label, rd_off); rh->proc (rh->proc_cls, rd_off, rd_new); GNS_resolver_lookup_cancel (rh); return; } do_recurse: /* need to recurse, check if we can */ for (i=0;iproc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } /* expand authority chain */ ac = GNUNET_new (struct AuthorityChain); ac->rh = rh; ac->gns_authority = GNUNET_YES; ac->suggested_shortening_label = NULL; ac->shortening_started = GNUNET_NO; memcpy (&ac->authority_info.gns_authority, rd[i].data, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); ac->label = resolver_lookup_get_next_label (rh); /* add AC to tail */ GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, rh->ac_tail, ac); /* recurse */ rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, rh); return; case GNUNET_GNSRECORD_TYPE_GNS2DNS: { /* resolution continues within DNS */ struct Gns2DnsContext *g2dc; char *ip; char *ns; off = 0; ns = GNUNET_DNSPARSER_parse_name (rd[i].data, rd[i].data_size, &off); ip = GNUNET_DNSPARSER_parse_name (rd[i].data, rd[i].data_size, &off); if ( (NULL == ns) || (NULL == ip) || (off != rd[i].data_size) ) { GNUNET_break_op (0); GNUNET_free_non_null (ns); GNUNET_free_non_null (ip); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resolving `%s' to determine IP address of DNS server for GNS2DNS transition\n", ip); /* resolve 'ip' to determine the IP(s) of the DNS resolver to use */ g2dc = GNUNET_new (struct Gns2DnsContext); g2dc->ns = ns; g2dc->rh = GNUNET_new (struct GNS_ResolverHandle); g2dc->rh->authority_zone = rh->ac_tail->authority_info.gns_authority; ip = translate_dot_plus (rh, ip); g2dc->rh->name = ip; g2dc->rh->name_resolution_pos = strlen (ip); g2dc->rh->proc = &handle_gns2dns_result; g2dc->rh->proc_cls = rh; g2dc->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY; g2dc->rh->options = GNUNET_GNS_LO_DEFAULT; g2dc->rh->loop_limiter = rh->loop_limiter + 1; rh->g2dc = g2dc; start_resolver_lookup (g2dc->rh); return; } case GNUNET_DNSPARSER_TYPE_CNAME: { char *cname; off = 0; cname = GNUNET_DNSPARSER_parse_name (rd[i].data, rd[i].data_size, &off); if ( (NULL == cname) || (off != rd[i].data_size) ) { GNUNET_break_op (0); /* record not well-formed */ rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); GNUNET_free_non_null (cname); return; } handle_gns_cname_result (rh, cname); GNUNET_free (cname); return; } /* FIXME: handle DNAME */ default: /* skip */ break; } } GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("GNS lookup recursion failed (no delegation record found)\n")); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); } /** * Function called once the namestore has completed the request for * caching a block. * * @param cls closure with the `struct CacheOps` * @param success #GNUNET_OK on success * @param emsg error message */ static void namecache_cache_continuation (void *cls, int32_t success, const char *emsg) { struct CacheOps *co = cls; co->namecache_qe_cache = NULL; if (NULL != emsg) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to cache GNS resolution: %s\n"), emsg); GNUNET_CONTAINER_DLL_remove (co_head, co_tail, co); GNUNET_free (co); } /** * Iterator called on each result obtained for a DHT * operation that expects a reply * * @param cls closure with the `struct GNS_ResolverHandle` * @param exp when will this value expire * @param key key of the result * @param get_path peers on reply path (or NULL if not recorded) * [0] = datastore's first neighbor, [length - 1] = local peer * @param get_path_length number of entries in @a get_path * @param put_path peers on the PUT path (or NULL if not recorded) * [0] = origin, [length - 1] = datastore * @param put_path_length number of entries in @a put_path * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data */ static void handle_dht_response (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { struct GNS_ResolverHandle *rh = cls; struct AuthorityChain *ac = rh->ac_tail; const struct GNUNET_GNSRECORD_Block *block; struct CacheOps *co; GNUNET_DHT_get_stop (rh->get_handle); rh->get_handle = NULL; GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node); rh->dht_heap_node = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handling response from the DHT\n"); if (size < sizeof (struct GNUNET_GNSRECORD_Block)) { /* how did this pass DHT block validation!? */ GNUNET_break (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } block = data; if (size != ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)) { /* how did this pass DHT block validation!? */ GNUNET_break (0); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } if (GNUNET_OK != GNUNET_GNSRECORD_block_decrypt (block, &ac->authority_info.gns_authority, ac->label, &handle_gns_resolution_result, rh)) { GNUNET_break_op (0); /* block was ill-formed */ rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received expired block from the DHT, will not cache it.\n"); return; } /* Cache well-formed blocks */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Caching response from the DHT in namecache\n"); co = GNUNET_new (struct CacheOps); co->namecache_qe_cache = GNUNET_NAMECACHE_block_cache (namecache_handle, block, &namecache_cache_continuation, co); GNUNET_CONTAINER_DLL_insert (co_head, co_tail, co); } /** * Initiate a DHT query for a set of GNS records. * * @param rh resolution handle * @param query key to use in the DHT lookup */ static void start_dht_request (struct GNS_ResolverHandle *rh, const struct GNUNET_HashCode *query) { struct GNS_ResolverHandle *rx; GNUNET_assert (NULL == rh->get_handle); rh->get_handle = GNUNET_DHT_get_start (dht_handle, GNUNET_BLOCK_TYPE_GNS_NAMERECORD, query, DHT_GNS_REPLICATION_LEVEL, GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, 0, &handle_dht_response, rh); rh->dht_heap_node = GNUNET_CONTAINER_heap_insert (dht_lookup_heap, rh, GNUNET_TIME_absolute_get ().abs_value_us); if (GNUNET_CONTAINER_heap_get_size (dht_lookup_heap) > max_allowed_background_queries) { /* fail longest-standing DHT request */ rx = GNUNET_CONTAINER_heap_peek (dht_lookup_heap); GNUNET_assert (NULL != rx); rx->proc (rx->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rx); } } /** * Process a records that were decrypted from a block that we got from * the namecache. Simply calls #handle_gns_resolution_result(). * * @param cls closure with the `struct GNS_ResolverHandle` * @param rd_count number of entries in @a rd array * @param rd array of records with data to store */ static void handle_gns_namecache_resolution_result (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNS_ResolverHandle *rh = cls; handle_gns_resolution_result (rh, rd_count, rd); } /** * Process a record that was stored in the namecache. * * @param cls closure with the `struct GNS_ResolverHandle` * @param block block that was stored in the namecache */ static void handle_namecache_block_response (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct GNS_ResolverHandle *rh = cls; struct AuthorityChain *ac = rh->ac_tail; const char *label = ac->label; const struct GNUNET_CRYPTO_EcdsaPublicKey *auth = &ac->authority_info.gns_authority; struct GNUNET_HashCode query; GNUNET_assert (NULL != rh->namecache_qe); rh->namecache_qe = NULL; if ( ( (GNUNET_GNS_LO_DEFAULT == rh->options) || ( (GNUNET_GNS_LO_LOCAL_MASTER == rh->options) && (ac != rh->ac_head) ) ) && ( (NULL == block) || (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) ) ) { /* namecache knows nothing; try DHT lookup */ GNUNET_GNSRECORD_query_from_public_key (auth, label, &query); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n", ac->label, GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority), GNUNET_h2s (&query)); start_dht_request (rh, &query); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result from namecache for label `%s'\n", ac->label); if ( (NULL == block) || (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (block->expiration_time)).rel_value_us) ) { /* DHT not permitted and no local result, fail */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resolution failed for `%s' in zone %s (DHT lookup not permitted by configuration)\n", ac->label, GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } if (GNUNET_OK != GNUNET_GNSRECORD_block_decrypt (block, auth, label, &handle_gns_namecache_resolution_result, rh)) { GNUNET_break_op (0); /* block was ill-formed */ /* try DHT instead */ GNUNET_GNSRECORD_query_from_public_key (auth, label, &query); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting DHT lookup for `%s' in zone `%s' under key `%s'\n", ac->label, GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority), GNUNET_h2s (&query)); start_dht_request (rh, &query); return; } } /** * Lookup tail of our authority chain in the namecache. * * @param rh query we are processing */ static void recursive_gns_resolution_namecache (struct GNS_ResolverHandle *rh) { struct AuthorityChain *ac = rh->ac_tail; struct GNUNET_HashCode query; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting GNS resolution for `%s' in zone %s\n", ac->label, GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); GNUNET_GNSRECORD_query_from_public_key (&ac->authority_info.gns_authority, ac->label, &query); if (GNUNET_YES == use_cache) { rh->namecache_qe = GNUNET_NAMECACHE_lookup_block (namecache_handle, &query, &handle_namecache_block_response, rh); GNUNET_assert (NULL != rh->namecache_qe); } else { start_dht_request (rh, &query); } } /** * Function called with the result from a revocation check. * * @param cls the `struct GNS_ResovlerHandle` * @param is_valid #GNUNET_YES if the zone was not yet revoked */ static void handle_revocation_result (void *cls, int is_valid) { struct GNS_ResolverHandle *rh = cls; struct AuthorityChain *ac = rh->ac_tail; rh->rev_check = NULL; if (GNUNET_YES != is_valid) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Zone %s was revoked, resolution fails\n"), GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } recursive_gns_resolution_namecache (rh); } /** * Perform revocation check on tail of our authority chain. * * @param rh query we are processing */ static void recursive_gns_resolution_revocation (struct GNS_ResolverHandle *rh) { struct AuthorityChain *ac = rh->ac_tail; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting revocation check for zone %s\n", GNUNET_GNSRECORD_z2s (&ac->authority_info.gns_authority)); rh->rev_check = GNUNET_REVOCATION_query (cfg, &ac->authority_info.gns_authority, &handle_revocation_result, rh); GNUNET_assert (NULL != rh->rev_check); } /** * Task scheduled to continue with the resolution process. * * @param cls the `struct GNS_ResolverHandle` of the resolution * @param tc task context */ static void recursive_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNS_ResolverHandle *rh = cls; rh->task_id = GNUNET_SCHEDULER_NO_TASK; if (MAX_RECURSION < rh->loop_limiter++) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Encountered unbounded recursion resolving `%s'\n", rh->name); rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); return; } if (GNUNET_YES == rh->ac_tail->gns_authority) recursive_gns_resolution_revocation (rh); else recursive_dns_resolution (rh); } /** * Begin the resolution process from 'name', starting with * the identification of the zone specified by 'name'. * * @param rh resolution to perform */ static void start_resolver_lookup (struct GNS_ResolverHandle *rh) { struct AuthorityChain *ac; char *y; struct in_addr v4; struct in6_addr v6; if (1 == inet_pton (AF_INET, rh->name, &v4)) { /* name is IPv4 address, pretend it's an A record */ struct GNUNET_GNSRECORD_Data rd; rd.data = &v4; rd.data_size = sizeof (v4); rd.expiration_time = UINT64_MAX; rd.record_type = GNUNET_DNSPARSER_TYPE_A; rd.flags = 0; rh->proc (rh->proc_cls, 1, &rd); GNS_resolver_lookup_cancel (rh); return; } if (1 == inet_pton (AF_INET6, rh->name, &v6)) { /* name is IPv6 address, pretend it's an AAAA record */ struct GNUNET_GNSRECORD_Data rd; rd.data = &v6; rd.data_size = sizeof (v6); rd.expiration_time = UINT64_MAX; rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA; rd.flags = 0; rh->proc (rh->proc_cls, 1, &rd); GNS_resolver_lookup_cancel (rh); return; } if ( ( (GNUNET_YES == is_canonical (rh->name)) && (0 != strcmp (GNUNET_GNS_TLD, rh->name)) ) || ( (GNUNET_YES != is_gnu_tld (rh->name)) && (GNUNET_YES != is_zkey_tld (rh->name)) ) ) { /* use standard DNS lookup */ int af; switch (rh->record_type) { case GNUNET_DNSPARSER_TYPE_A: af = AF_INET; break; case GNUNET_DNSPARSER_TYPE_AAAA: af = AF_INET6; break; default: af = AF_UNSPEC; break; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Doing standard DNS lookup for `%s'\n", rh->name); rh->std_resolve = GNUNET_RESOLVER_ip_get (rh->name, af, DNS_LOOKUP_TIMEOUT, &handle_dns_result, rh); return; } if (is_zkey_tld (rh->name)) { /* Name ends with ".zkey", try to replace authority zone with zkey authority */ GNUNET_free (resolver_lookup_get_next_label (rh)); /* will return "zkey" */ y = resolver_lookup_get_next_label (rh); /* will return 'y' coordinate */ if ( (NULL == y) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (y, strlen (y), &rh->authority_zone)) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Hostname `%s' is not well-formed, resolution fails\n"), rh->name); rh->task_id = GNUNET_SCHEDULER_add_now (&fail_resolution, rh); } GNUNET_free_non_null (y); } else { /* Name ends with ".gnu", eat ".gnu" and continue with resolution */ GNUNET_free (resolver_lookup_get_next_label (rh)); } ac = GNUNET_new (struct AuthorityChain); ac->rh = rh; ac->label = resolver_lookup_get_next_label (rh); ac->suggested_shortening_label = NULL; if (NULL == ac->label) /* name was just "gnu", so we default to label '+' */ ac->label = GNUNET_strdup (GNUNET_GNS_MASTERZONE_STR); ac->gns_authority = GNUNET_YES; ac->authority_info.gns_authority = rh->authority_zone; GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head, rh->ac_tail, ac); rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution, rh); } /** * Lookup of a record in a specific zone calls lookup result processor * on result. * * @param zone the zone to perform the lookup in * @param record_type the record type to look up * @param name the name to look up * @param shorten_key a private key for use with PSEU import (can be NULL) * @param options local options to control local lookup * @param proc the processor to call on result * @param proc_cls the closure to pass to @a proc * @return handle to cancel operation */ struct GNS_ResolverHandle * GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t record_type, const char *name, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_key, enum GNUNET_GNS_LocalOptions options, GNS_ResultProcessor proc, void *proc_cls) { struct GNS_ResolverHandle *rh; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, (NULL == shorten_key) ? "Starting lookup for `%s' with shortening disabled\n" : "Starting lookup for `%s' with shortening enabled\n", name); rh = GNUNET_new (struct GNS_ResolverHandle); GNUNET_CONTAINER_DLL_insert (rlh_head, rlh_tail, rh); rh->authority_zone = *zone; rh->proc = proc; rh->proc_cls = proc_cls; rh->options = options; rh->record_type = record_type; rh->name = GNUNET_strdup (name); rh->name_resolution_pos = strlen (name); if (NULL != shorten_key) { rh->shorten_key = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); *rh->shorten_key = *shorten_key; } start_resolver_lookup (rh); return rh; } /** * Cancel active resolution (i.e. client disconnected). * * @param rh resolution to abort */ void GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh) { struct DnsResult *dr; struct AuthorityChain *ac; struct VpnContext *vpn_ctx; GNUNET_CONTAINER_DLL_remove (rlh_head, rlh_tail, rh); while (NULL != (ac = rh->ac_head)) { GNUNET_CONTAINER_DLL_remove (rh->ac_head, rh->ac_tail, ac); GNUNET_free (ac->label); GNUNET_free_non_null (ac->suggested_shortening_label); GNUNET_free (ac); } if (NULL != rh->g2dc) { /* rh->g2dc->rh is NOT in the DLL yet, so to enable us using GNS_resolver_lookup_cancel here, we need to add it first... */ if (NULL != rh->g2dc->rh) { GNUNET_CONTAINER_DLL_insert (rlh_head, rlh_tail, rh->g2dc->rh); GNS_resolver_lookup_cancel (rh->g2dc->rh); rh->g2dc->rh = NULL; } GNUNET_free (rh->g2dc->ns); GNUNET_free (rh->g2dc); rh->g2dc = NULL; } if (GNUNET_SCHEDULER_NO_TASK != rh->task_id) { GNUNET_SCHEDULER_cancel (rh->task_id); rh->task_id = GNUNET_SCHEDULER_NO_TASK; } if (NULL != rh->get_handle) { GNUNET_DHT_get_stop (rh->get_handle); rh->get_handle = NULL; } if (NULL != rh->dht_heap_node) { GNUNET_CONTAINER_heap_remove_node (rh->dht_heap_node); rh->dht_heap_node = NULL; } if (NULL != (vpn_ctx = rh->vpn_ctx)) { GNUNET_VPN_cancel_request (vpn_ctx->vpn_request); GNUNET_free (vpn_ctx->rd_data); GNUNET_free (vpn_ctx); } if (NULL != rh->dns_request) { GNUNET_DNSSTUB_resolve_cancel (rh->dns_request); rh->dns_request = NULL; } if (NULL != rh->namecache_qe) { GNUNET_NAMECACHE_cancel (rh->namecache_qe); rh->namecache_qe = NULL; } if (NULL != rh->rev_check) { GNUNET_REVOCATION_query_cancel (rh->rev_check); rh->rev_check = NULL; } if (NULL != rh->std_resolve) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Canceling standard DNS resolution\n"); GNUNET_RESOLVER_request_cancel (rh->std_resolve); rh->std_resolve = NULL; } while (NULL != (dr = rh->dns_result_head)) { GNUNET_CONTAINER_DLL_remove (rh->dns_result_head, rh->dns_result_tail, dr); GNUNET_free (dr); } GNUNET_free_non_null (rh->shorten_key); GNUNET_free (rh->name); GNUNET_free (rh); } /* ***************** Resolver initialization ********************* */ /** * Initialize the resolver * * @param nc the namecache handle * @param dht the dht handle * @param c configuration handle * @param max_bg_queries maximum number of parallel background queries in dht */ void GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc, struct GNUNET_DHT_Handle *dht, const struct GNUNET_CONFIGURATION_Handle *c, unsigned long long max_bg_queries) { char *dns_ip; cfg = c; namecache_handle = nc; dht_handle = dht; dht_lookup_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); max_allowed_background_queries = max_bg_queries; if (GNUNET_SYSERR == (use_cache = GNUNET_CONFIGURATION_get_value_yesno (c, "gns", "USE_CACHE"))) use_cache = GNUNET_YES; if (GNUNET_NO == use_cache) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Namecache disabled\n"); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "gns", "DNS_RESOLVER", &dns_ip)) { /* user did not specify DNS resolver, use 8.8.8.8 */ dns_ip = GNUNET_strdup ("8.8.8.8"); } dns_handle = GNUNET_DNSSTUB_start (dns_ip); GNUNET_free (dns_ip); vpn_handle = GNUNET_VPN_connect (cfg); } /** * Shutdown resolver */ void GNS_resolver_done () { struct GNS_ResolverHandle *rh; struct CacheOps *co; /* abort active resolutions */ while (NULL != (rh = rlh_head)) { rh->proc (rh->proc_cls, 0, NULL); GNS_resolver_lookup_cancel (rh); } while (NULL != (co = co_head)) { GNUNET_CONTAINER_DLL_remove (co_head, co_tail, co); GNUNET_NAMECACHE_cancel (co->namecache_qe_cache); GNUNET_free (co); } GNUNET_CONTAINER_heap_destroy (dht_lookup_heap); dht_lookup_heap = NULL; GNUNET_DNSSTUB_stop (dns_handle); dns_handle = NULL; GNUNET_VPN_disconnect (vpn_handle); vpn_handle = NULL; dht_handle = NULL; namecache_handle = NULL; } /* *************** common helper functions (do not really belong here) *********** */ /** * Checks if @a name ends in ".TLD" * * @param name the name to check * @param tld the TLD to check for * @return GNUNET_YES or GNUNET_NO */ int is_tld (const char* name, const char* tld) { size_t offset = 0; if (strlen (name) <= strlen (tld)) return GNUNET_NO; offset = strlen (name) - strlen (tld); if (0 != strcmp (name + offset, tld)) return GNUNET_NO; return GNUNET_YES; } /* end of gnunet-service-gns_resolver.c */ gnunet-0.10.1/src/gns/test_gns_rel_expiration.sh0000755000175000017500000000327112261236532016666 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf /tmp/test-gnunet-gns-peer-1/ which timeout &> /dev/null && DO_TIMEOUT="timeout 5" TEST_IP="127.0.0.1" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C testego -c test_gns_lookup.conf gnunet-identity -C delegatedego -c test_gns_lookup.conf DELEGATED_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep delegatedego | awk '{print $3}') gnunet-namestore -p -z testego -a -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -p -z delegatedego -a -n www -t A -V $TEST_IP -e '5 s' -c test_gns_lookup.conf gnunet-arm -i gns -c test_gns_lookup.conf sleep 7 gnunet-namestore -z delegatedego -d -n www -t A -V $TEST_IP -e '5 s' -c test_gns_lookup.conf sleep 1 RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.b.gnu -t A -c test_gns_lookup.conf` sleep 6 RES_IP_EXP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.b.gnu -t A -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-identity -D testego -c test_gns_lookup.conf gnunet-identity -D delegatedego -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_IP_EXP" == "$TEST_IP" ] then echo "Failed to properly expire IP, got $RES_IP_EXP." exit 1 fi if [ "$RES_IP" == "$TEST_IP" ] then exit 0 else echo "Failed to properly resolve IP, got $RES_IP." exit 1 fi gnunet-0.10.1/src/gns/gnunet-service-gns_resolver.h0000644000175000017500000000650412305564547017225 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gnunet-service-gns_resolver.h * @brief GNUnet GNS service * @author Martin Schanzenbach */ #ifndef GNS_RESOLVER_H #define GNS_RESOLVER_H #include "gns.h" #include "gnunet_dht_service.h" #include "gnunet_gns_service.h" #include "gnunet_namecache_service.h" /** * Initialize the resolver subsystem. * MUST be called before #GNS_resolver_lookup. * * @param nc the namecache handle * @param dht handle to the dht * @param c configuration handle * @param max_bg_queries maximum amount of background queries */ void GNS_resolver_init (struct GNUNET_NAMECACHE_Handle *nc, struct GNUNET_DHT_Handle *dht, const struct GNUNET_CONFIGURATION_Handle *c, unsigned long long max_bg_queries); /** * Cleanup resolver: Terminate pending lookups */ void GNS_resolver_done (void); /** * Handle for an active request. */ struct GNS_ResolverHandle; /** * Function called with results for a GNS resolution. * * @param cls closure * @param rd_count number of records in @a rd * @param rd records returned for the lookup */ typedef void (*GNS_ResultProcessor)(void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd); /** * Lookup of a record in a specific zone * calls RecordLookupProcessor on result or timeout * * @param zone the zone to perform the lookup in * @param record_type the record type to look up * @param name the name to look up * @param shorten_key optional private key for authority caching, can be NULL * @param options options set to control local lookup * @param proc the processor to call * @param proc_cls the closure to pass to @a proc * @return handle to cancel operation */ struct GNS_ResolverHandle * GNS_resolver_lookup (const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t record_type, const char *name, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_key, enum GNUNET_GNS_LocalOptions options, GNS_ResultProcessor proc, void *proc_cls); /** * Cancel active resolution (i.e. client disconnected). * * @param rh resolution to abort */ void GNS_resolver_lookup_cancel (struct GNS_ResolverHandle *rh); /** * Generic function to check for TLDs. Checks if "name" ends in ".tld" * * @param name the name to check * @param tld the tld to check * @return #GNUNET_YES or #GNUNET_NO */ int is_tld (const char *name, const char *tld); /** * Checks for gnu/zkey */ #define is_gnu_tld(name) is_tld(name, GNUNET_GNS_TLD) #define is_zkey_tld(name) is_tld(name, GNUNET_GNS_TLD_ZKEY) #endif gnunet-0.10.1/src/gns/gns.conf.in0000644000175000017500000000212612274162760013443 00000000000000[gns] AUTOSTART = @AUTOSTART@ HOSTNAME = localhost BINARY = gnunet-service-gns UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-gns.sock @JAVAPORT@PORT = 2102 USER_SERVICE = YES # Do we require users that want to access GNS to run this process # (usually not a good idea) UNIX_MATCH_UID = NO # Do we require users that want to access GNS to be in the 'gnunet' group? UNIX_MATCH_GID = YES # How many queries is GNS allowed to perform in the background at the same time? MAX_PARALLEL_BACKGROUND_QUERIES = 1000 # How frequently do we try to publish our full zone? ZONE_PUBLISH_TIME_WINDOW = 4 h # Using caching or always ask DHT # USE_CACHE = YES # PREFIX = valgrind --leak-check=full --track-origins=yes [gns-proxy] BINARY = gnunet-gns-proxy AUTOSTART = NO USER_SERVICE = YES # Where is the certificate for the GNS proxy stored? PROXY_CACERT = $GNUNET_DATA_HOME/gns/gns_ca_cert.pem PROXY_UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-gns-proxy.sock [dns2gns] BINARY = gnunet-dns2gns AUTOSTART = NO USER_SERVICE = YES # -d: DNS resolver to use, -s: suffix to use, -f: fcfs suffix to use OPTIONS = -d 8.8.8.8 gnunet-0.10.1/src/gns/test_gns_zkey_lookup.sh0000755000175000017500000000254412261236532016217 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT which timeout &> /dev/null && DO_TIMEOUT="timeout 5" LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf /tmp/test-gnunet-gns-peer-1/ TEST_IP="127.0.0.1" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C delegatedego -c test_gns_lookup.conf DELEGATED_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep delegatedego | awk '{print $3}') gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -p -z delegatedego -a -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.${DELEGATED_PKEY}.zkey -t A -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -z delegatedego -d -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_IP" == "$TEST_IP" ] then exit 0 else echo "Failed to resolve to proper IP, got $RES_IP, wanted $TEST_IP." exit 1 fi gnunet-0.10.1/src/gns/test_gns_nick_shorten.conf0000644000175000017500000000075412250055470016641 00000000000000@INLINE@ test_gns_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-gns-peer-1/ [dht] AUTOSTART = YES [transport] PLUGINS = [arm] DEFAULTSERVICES = [gns] #PREFIX = valgrind --leak-check=full --track-origins=yes AUTOSTART = YES AUTO_IMPORT_PKEY = YES MAX_PARALLEL_BACKGROUND_QUERIES = 10 DEFAULT_LOOKUP_TIMEOUT = 15 s RECORD_PUT_INTERVAL = 1 h ZONE_PUBLISH_TIME_WINDOW = 1 h DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0 #USE_CACHE = NO [revocation] WORKBITS = 1 gnunet-0.10.1/src/gns/Makefile.in0000644000175000017500000020737412320752061013450 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-gns$(EXEEXT) $(am__EXEEXT_4) \ gnunet-dns2gns$(EXEEXT) $(am__EXEEXT_5) bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) gnunet-gns$(EXEEXT) \ $(am__EXEEXT_3) @HAVE_MHD_TRUE@@LINUX_TRUE@am__append_1 = gnunet-bcd @HAVE_GNUTLS_DANE_TRUE@am__append_2 = -lgnutls-dane subdir = src/gns DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/gns.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = gns.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am_libgnunet_plugin_block_gns_la_OBJECTS = plugin_block_gns.lo libgnunet_plugin_block_gns_la_OBJECTS = \ $(am_libgnunet_plugin_block_gns_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_block_gns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_block_gns_la_LDFLAGS) $(LDFLAGS) -o $@ am__DEPENDENCIES_1 = libgnunet_plugin_gnsrecord_gns_la_DEPENDENCIES = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunet_plugin_gnsrecord_gns_la_OBJECTS = \ plugin_gnsrecord_gns.lo libgnunet_plugin_gnsrecord_gns_la_OBJECTS = \ $(am_libgnunet_plugin_gnsrecord_gns_la_OBJECTS) libgnunet_plugin_gnsrecord_gns_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_gnsrecord_gns_la_LDFLAGS) $(LDFLAGS) -o $@ am_libgnunetgns_la_OBJECTS = gns_api.lo libgnunetgns_la_OBJECTS = $(am_libgnunetgns_la_OBJECTS) libgnunetgns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetgns_la_LDFLAGS) $(LDFLAGS) \ -o $@ libw32nsp_la_DEPENDENCIES = am_libw32nsp_la_OBJECTS = w32nsp.lo libw32nsp_la_OBJECTS = $(am_libw32nsp_la_OBJECTS) libw32nsp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libw32nsp_la_LDFLAGS) $(LDFLAGS) -o $@ @MINGW_TRUE@am_libw32nsp_la_rpath = -rpath $(libdir) @MINGW_TRUE@am__EXEEXT_1 = w32nsp-install$(EXEEXT) \ @MINGW_TRUE@ w32nsp-uninstall$(EXEEXT) w32nsp-resolve$(EXEEXT) @MINGW_TRUE@am__EXEEXT_2 = gnunet-gns-import$(EXEEXT) @HAVE_MHD_TRUE@@LINUX_TRUE@am__EXEEXT_3 = gnunet-bcd$(EXEEXT) @MINGW_TRUE@am__EXEEXT_4 = gnunet-gns-helper-service-w32$(EXEEXT) @HAVE_GNUTLS_TRUE@@HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_5 = gnunet-gns-proxy$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_bcd_OBJECTS = gnunet-bcd.$(OBJEXT) gnunet_bcd_OBJECTS = $(am_gnunet_bcd_OBJECTS) am_gnunet_dns2gns_OBJECTS = gnunet-dns2gns.$(OBJEXT) gnunet_dns2gns_OBJECTS = $(am_gnunet_dns2gns_OBJECTS) am_gnunet_gns_OBJECTS = gnunet-gns.$(OBJEXT) gnunet_gns_OBJECTS = $(am_gnunet_gns_OBJECTS) am_gnunet_gns_helper_service_w32_OBJECTS = \ gnunet-gns-helper-service-w32.$(OBJEXT) gnunet_gns_helper_service_w32_OBJECTS = \ $(am_gnunet_gns_helper_service_w32_OBJECTS) am_gnunet_gns_import_OBJECTS = gnunet-gns-import.$(OBJEXT) gnunet_gns_import_OBJECTS = $(am_gnunet_gns_import_OBJECTS) am_gnunet_gns_proxy_OBJECTS = gnunet-gns-proxy.$(OBJEXT) gnunet_gns_proxy_OBJECTS = $(am_gnunet_gns_proxy_OBJECTS) am_gnunet_service_gns_OBJECTS = gnunet-service-gns.$(OBJEXT) \ gnunet-service-gns_resolver.$(OBJEXT) \ gnunet-service-gns_shorten.$(OBJEXT) \ gnunet-service-gns_interceptor.$(OBJEXT) gnunet_service_gns_OBJECTS = $(am_gnunet_service_gns_OBJECTS) am_w32nsp_install_OBJECTS = w32nsp-install.$(OBJEXT) w32nsp_install_OBJECTS = $(am_w32nsp_install_OBJECTS) w32nsp_install_DEPENDENCIES = am_w32nsp_resolve_OBJECTS = w32nsp-resolve.$(OBJEXT) w32nsp_resolve_OBJECTS = $(am_w32nsp_resolve_OBJECTS) w32nsp_resolve_DEPENDENCIES = am_w32nsp_uninstall_OBJECTS = w32nsp-uninstall.$(OBJEXT) w32nsp_uninstall_OBJECTS = $(am_w32nsp_uninstall_OBJECTS) w32nsp_uninstall_DEPENDENCIES = SCRIPTS = $(bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_block_gns_la_SOURCES) \ $(libgnunet_plugin_gnsrecord_gns_la_SOURCES) \ $(libgnunetgns_la_SOURCES) $(libw32nsp_la_SOURCES) \ $(gnunet_bcd_SOURCES) $(gnunet_dns2gns_SOURCES) \ $(gnunet_gns_SOURCES) $(gnunet_gns_helper_service_w32_SOURCES) \ $(gnunet_gns_import_SOURCES) $(gnunet_gns_proxy_SOURCES) \ $(gnunet_service_gns_SOURCES) $(w32nsp_install_SOURCES) \ $(w32nsp_resolve_SOURCES) $(w32nsp_uninstall_SOURCES) DIST_SOURCES = $(libgnunet_plugin_block_gns_la_SOURCES) \ $(libgnunet_plugin_gnsrecord_gns_la_SOURCES) \ $(libgnunetgns_la_SOURCES) $(libw32nsp_la_SOURCES) \ $(gnunet_bcd_SOURCES) $(gnunet_dns2gns_SOURCES) \ $(gnunet_gns_SOURCES) $(gnunet_gns_helper_service_w32_SOURCES) \ $(gnunet_gns_import_SOURCES) $(gnunet_gns_proxy_SOURCES) \ $(gnunet_service_gns_SOURCES) $(w32nsp_install_SOURCES) \ $(w32nsp_resolve_SOURCES) $(w32nsp_uninstall_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ check recheck distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = . nss DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @HAVE_GLIBCNSS_TRUE@@INSTALL_NSS_TRUE@NSS_SUBDIR = nss SUBDIRS = . $(NSS_SUBDIR) EXTRA_DIST = \ test_gns_defaults.conf \ test_gns_lookup.conf \ test_gns_nick_shorten.conf \ test_gns_proxy.conf \ test_gns_simple_lookup.conf \ gns-helper-service-w32.conf \ w32nsp.def \ gnunet-gns-proxy-setup-ca \ zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey \ zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \ zonefiles/test_zonekey \ $(check_SCRIPTS) @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @MINGW_TRUE@DO_W32_HELPER = gnunet-gns-helper-service-w32 @MINGW_TRUE@DO_W32_NSP = libw32nsp.la @MINGW_TRUE@DO_W32_NSPTOOLS = w32nsp-install w32nsp-uninstall w32nsp-resolve @MINGW_TRUE@DO_W32_HS_CONF = gns-helper-service-w32.conf @MINGW_TRUE@DO_NONPOSIX_GNSIMPORT = gnunet-gns-import USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 pkgcfgdir = $(pkgdatadir)/config.d/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ gns.conf \ $(DO_W32_HS_CONF) lib_LTLIBRARIES = \ $(DO_W32_NSP) \ libgnunetgns.la @HAVE_GNUTLS_TRUE@@HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@DO_PROXY = gnunet-gns-proxy bin_SCRIPTS = gnunet-gns-proxy-setup-ca plugin_LTLIBRARIES = \ libgnunet_plugin_block_gns.la \ libgnunet_plugin_gnsrecord_gns.la libgnunet_plugin_gnsrecord_gns_la_SOURCES = \ plugin_gnsrecord_gns.c libgnunet_plugin_gnsrecord_gns_la_LIBADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_gnsrecord_gns_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) gnunet_gns_SOURCES = \ gnunet-gns.c gnunet_gns_LDADD = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_gns_DEPENDENCIES = \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetgns.la gnunet_bcd_SOURCES = \ gnunet-bcd.c gnunet_bcd_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) -lmicrohttpd gnunet_bcd_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_dns2gns_SOURCES = \ gnunet-dns2gns.c gnunet_dns2gns_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(GN_LIBINTL) gnunet_dns2gns_DEPENDENCIES = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ libgnunetgns.la gnunet_gns_proxy_SOURCES = \ gnunet-gns-proxy.c gnunet_gns_proxy_LDADD = -lmicrohttpd -lgnurl -lgnutls \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la $(GN_LIBINTL) \ $(am__append_2) gnunet_gns_proxy_DEPENDENCIES = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetgns.la gnunet_gns_helper_service_w32_SOURCES = \ gnunet-gns-helper-service-w32.c gnunet_gns_helper_service_w32_LDADD = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_gns_helper_service_w32_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ libgnunetgns.la gnunet_gns_import_SOURCES = \ gnunet-gns-import.c gnunet_gns_import_LDADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_gns_import_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/identity/libgnunetidentity.la w32nsp_install_SOURCES = \ w32nsp-install.c w32nsp_install_LDADD = -lws2_32 w32nsp_uninstall_SOURCES = \ w32nsp-uninstall.c w32nsp_uninstall_LDADD = -lws2_32 w32nsp_resolve_SOURCES = \ w32nsp-resolve.c w32nsp_resolve_LDADD = -lws2_32 gnunet_service_gns_SOURCES = \ gnunet-service-gns.c \ gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ gnunet-service-gns_shorten.c gnunet-service-gns_shorten.h \ gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h gnunet_service_gns_LDADD = \ -lm \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(USE_VPN) \ $(GN_LIBINTL) gnunet_service_gns_DEPENDENCIES = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(USE_VPN) libw32nsp_la_SOURCES = \ w32nsp.c libw32nsp_la_LIBADD = \ -lole32 -lws2_32 libw32nsp_la_LDFLAGS = \ -export-symbols $(top_srcdir)/src/gns/w32nsp.def \ -no-undefined -static-libgcc libgnunetgns_la_SOURCES = \ gns_api.c gns.h libgnunetgns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la libgnunetgns_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) libgnunetgns_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la libgnunet_plugin_block_gns_la_SOURCES = \ plugin_block_gns.c libgnunet_plugin_block_gns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la libgnunet_plugin_block_gns_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_gns_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la check_SCRIPTS = \ test_gns_lookup.sh \ test_gns_ipv6_lookup.sh\ test_gns_txt_lookup.sh\ test_gns_mx_lookup.sh \ test_gns_gns2dns_lookup.sh \ test_gns_dht_lookup.sh\ test_gns_delegated_lookup.sh \ test_gns_nick_shorten.sh\ test_gns_plus_lookup.sh\ test_gns_zkey_lookup.sh\ test_gns_rel_expiration.sh\ test_gns_soa_lookup.sh\ test_gns_revocation.sh\ test_gns_cname_lookup.sh @ENABLE_TEST_RUN_TRUE@@HAVE_SQLITE_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@@HAVE_SQLITE_TRUE@TESTS = $(check_SCRIPTS) all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gns/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/gns/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): gns.conf: $(top_builddir)/config.status $(srcdir)/gns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_block_gns.la: $(libgnunet_plugin_block_gns_la_OBJECTS) $(libgnunet_plugin_block_gns_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_block_gns_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_block_gns_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_gns_la_OBJECTS) $(libgnunet_plugin_block_gns_la_LIBADD) $(LIBS) libgnunet_plugin_gnsrecord_gns.la: $(libgnunet_plugin_gnsrecord_gns_la_OBJECTS) $(libgnunet_plugin_gnsrecord_gns_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_gnsrecord_gns_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_gnsrecord_gns_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_gnsrecord_gns_la_OBJECTS) $(libgnunet_plugin_gnsrecord_gns_la_LIBADD) $(LIBS) libgnunetgns.la: $(libgnunetgns_la_OBJECTS) $(libgnunetgns_la_DEPENDENCIES) $(EXTRA_libgnunetgns_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetgns_la_LINK) -rpath $(libdir) $(libgnunetgns_la_OBJECTS) $(libgnunetgns_la_LIBADD) $(LIBS) libw32nsp.la: $(libw32nsp_la_OBJECTS) $(libw32nsp_la_DEPENDENCIES) $(EXTRA_libw32nsp_la_DEPENDENCIES) $(AM_V_CCLD)$(libw32nsp_la_LINK) $(am_libw32nsp_la_rpath) $(libw32nsp_la_OBJECTS) $(libw32nsp_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-bcd$(EXEEXT): $(gnunet_bcd_OBJECTS) $(gnunet_bcd_DEPENDENCIES) $(EXTRA_gnunet_bcd_DEPENDENCIES) @rm -f gnunet-bcd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_bcd_OBJECTS) $(gnunet_bcd_LDADD) $(LIBS) gnunet-dns2gns$(EXEEXT): $(gnunet_dns2gns_OBJECTS) $(gnunet_dns2gns_DEPENDENCIES) $(EXTRA_gnunet_dns2gns_DEPENDENCIES) @rm -f gnunet-dns2gns$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_dns2gns_OBJECTS) $(gnunet_dns2gns_LDADD) $(LIBS) gnunet-gns$(EXEEXT): $(gnunet_gns_OBJECTS) $(gnunet_gns_DEPENDENCIES) $(EXTRA_gnunet_gns_DEPENDENCIES) @rm -f gnunet-gns$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_gns_OBJECTS) $(gnunet_gns_LDADD) $(LIBS) gnunet-gns-helper-service-w32$(EXEEXT): $(gnunet_gns_helper_service_w32_OBJECTS) $(gnunet_gns_helper_service_w32_DEPENDENCIES) $(EXTRA_gnunet_gns_helper_service_w32_DEPENDENCIES) @rm -f gnunet-gns-helper-service-w32$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_gns_helper_service_w32_OBJECTS) $(gnunet_gns_helper_service_w32_LDADD) $(LIBS) gnunet-gns-import$(EXEEXT): $(gnunet_gns_import_OBJECTS) $(gnunet_gns_import_DEPENDENCIES) $(EXTRA_gnunet_gns_import_DEPENDENCIES) @rm -f gnunet-gns-import$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_gns_import_OBJECTS) $(gnunet_gns_import_LDADD) $(LIBS) gnunet-gns-proxy$(EXEEXT): $(gnunet_gns_proxy_OBJECTS) $(gnunet_gns_proxy_DEPENDENCIES) $(EXTRA_gnunet_gns_proxy_DEPENDENCIES) @rm -f gnunet-gns-proxy$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_gns_proxy_OBJECTS) $(gnunet_gns_proxy_LDADD) $(LIBS) gnunet-service-gns$(EXEEXT): $(gnunet_service_gns_OBJECTS) $(gnunet_service_gns_DEPENDENCIES) $(EXTRA_gnunet_service_gns_DEPENDENCIES) @rm -f gnunet-service-gns$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_gns_OBJECTS) $(gnunet_service_gns_LDADD) $(LIBS) w32nsp-install$(EXEEXT): $(w32nsp_install_OBJECTS) $(w32nsp_install_DEPENDENCIES) $(EXTRA_w32nsp_install_DEPENDENCIES) @rm -f w32nsp-install$(EXEEXT) $(AM_V_CCLD)$(LINK) $(w32nsp_install_OBJECTS) $(w32nsp_install_LDADD) $(LIBS) w32nsp-resolve$(EXEEXT): $(w32nsp_resolve_OBJECTS) $(w32nsp_resolve_DEPENDENCIES) $(EXTRA_w32nsp_resolve_DEPENDENCIES) @rm -f w32nsp-resolve$(EXEEXT) $(AM_V_CCLD)$(LINK) $(w32nsp_resolve_OBJECTS) $(w32nsp_resolve_LDADD) $(LIBS) w32nsp-uninstall$(EXEEXT): $(w32nsp_uninstall_OBJECTS) $(w32nsp_uninstall_DEPENDENCIES) $(EXTRA_w32nsp_uninstall_DEPENDENCIES) @rm -f w32nsp-uninstall$(EXEEXT) $(AM_V_CCLD)$(LINK) $(w32nsp_uninstall_OBJECTS) $(w32nsp_uninstall_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gns_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-bcd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-dns2gns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns-helper-service-w32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns-import.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns-proxy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-gns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns_interceptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns_resolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-gns_shorten.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_gns.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_gnsrecord_gns.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32nsp-install.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32nsp-resolve.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32nsp-uninstall.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32nsp.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_gns_lookup.sh.log: test_gns_lookup.sh @p='test_gns_lookup.sh'; \ b='test_gns_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_ipv6_lookup.sh.log: test_gns_ipv6_lookup.sh @p='test_gns_ipv6_lookup.sh'; \ b='test_gns_ipv6_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_txt_lookup.sh.log: test_gns_txt_lookup.sh @p='test_gns_txt_lookup.sh'; \ b='test_gns_txt_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_mx_lookup.sh.log: test_gns_mx_lookup.sh @p='test_gns_mx_lookup.sh'; \ b='test_gns_mx_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_gns2dns_lookup.sh.log: test_gns_gns2dns_lookup.sh @p='test_gns_gns2dns_lookup.sh'; \ b='test_gns_gns2dns_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_dht_lookup.sh.log: test_gns_dht_lookup.sh @p='test_gns_dht_lookup.sh'; \ b='test_gns_dht_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_delegated_lookup.sh.log: test_gns_delegated_lookup.sh @p='test_gns_delegated_lookup.sh'; \ b='test_gns_delegated_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_nick_shorten.sh.log: test_gns_nick_shorten.sh @p='test_gns_nick_shorten.sh'; \ b='test_gns_nick_shorten.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_plus_lookup.sh.log: test_gns_plus_lookup.sh @p='test_gns_plus_lookup.sh'; \ b='test_gns_plus_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_zkey_lookup.sh.log: test_gns_zkey_lookup.sh @p='test_gns_zkey_lookup.sh'; \ b='test_gns_zkey_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_rel_expiration.sh.log: test_gns_rel_expiration.sh @p='test_gns_rel_expiration.sh'; \ b='test_gns_rel_expiration.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_soa_lookup.sh.log: test_gns_soa_lookup.sh @p='test_gns_soa_lookup.sh'; \ b='test_gns_soa_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_revocation.sh.log: test_gns_revocation.sh @p='test_gns_revocation.sh'; \ b='test_gns_revocation.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_cname_lookup.sh.log: test_gns_cname_lookup.sh @p='test_gns_cname_lookup.sh'; \ b='test_gns_cname_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-pluginLTLIBRARIES \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS \ install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-TESTS check-am clean clean-binPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-binSCRIPTS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libexecPROGRAMS install-man install-pdf install-pdf-am \ install-pkgcfgDATA install-pluginLTLIBRARIES install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/gns/test_gns_plus_lookup.sh0000755000175000017500000000247612261236532016224 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi which timeout &> /dev/null && DO_TIMEOUT="timeout 5" rm -rf /tmp/test-gnunet-gns-peer-1/ TEST_IP="127.0.0.1" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C delegatedego -c test_gns_lookup.conf DELEGATED_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep delegatedego | awk '{print $3}') gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -p -z delegatedego -a -n '+' -t A -V $TEST_IP -e never -c test_gns_lookup.conf RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u b.gnu -t A -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -z delegatedego -d -n '+' -t A -V $TEST_IP -e never -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_IP" == "$TEST_IP" ] then exit 0 else echo "Failed to resolve to proper IP, got $RES_IP." exit 1 fi gnunet-0.10.1/src/gns/gnunet-service-gns_shorten.h0000644000175000017500000000416312241134530017025 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gnunet-service-gns_shorten.h * @brief GNUnet GNS shortening API * @author Martin Schanzenbach */ #ifndef GNS_SHORTEN_H #define GNS_SHORTEN_H #include "gns.h" #include "gnunet_dht_service.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" /** * Initialize the shorten subsystem. * MUST be called before #GNS_shorten_start. * * @param nh handle to the namestore * @param nc the namecache handle * @param dht handle to the dht */ void GNS_shorten_init (struct GNUNET_NAMESTORE_Handle *nh, struct GNUNET_NAMECACHE_Handle *nc, struct GNUNET_DHT_Handle *dht); /** * Cleanup shorten: Terminate pending lookups */ void GNS_shorten_done (void); /** * Start shortening algorithm, try to allocate a nice short * canonical name for @a pub in @a shorten_zone, using * @a original_label as one possible suggestion. * * @param original_label original label for the zone * @param pub public key of the zone to shorten * @param shorten_zone private key of the target zone for the new record */ void GNS_shorten_start (const char *original_label, const char *suggested_label, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone); #endif gnunet-0.10.1/src/gns/test_gns_cname_lookup.sh0000755000175000017500000000524612272462700016322 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi # permissive DNS resolver we will use for the test DNS_RESOLVER="8.8.8.8" if ! nslookup gnunet.org $DNS_RESOLVER &> /dev/null then echo "Cannot reach DNS, skipping test" exit 77 fi rm -rf /tmp/test-gnunet-gns-peer-1/ TEST_DOMAIN_PLUS="www.gnu" TEST_DOMAIN_DNS="www3.gnu" TEST_IP_PLUS="127.0.0.1" TEST_IP_DNS="131.159.74.67" TEST_RECORD_CNAME_SERVER="server" TEST_RECORD_CNAME_PLUS="server.+" TEST_RECORD_CNAME_DNS="gnunet.org" TEST_RECORD_NAME_SERVER="server" TEST_RECORD_NAME_PLUS="www" TEST_RECORD_NAME_DNS="www3" which timeout &> /dev/null && DO_TIMEOUT="timeout 5" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t CNAME -V $TEST_RECORD_CNAME_DNS -e never -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_PLUS -t CNAME -V $TEST_RECORD_CNAME_PLUS -e never -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n $TEST_RECORD_CNAME_SERVER -t A -V $TEST_IP_PLUS -e never -c test_gns_lookup.conf RES_CNAME=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.gnu -t A -c test_gns_lookup.conf` RES_CNAME_RAW=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.gnu -t CNAME -c test_gns_lookup.conf` RES_CNAME_DNS=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www3.gnu -t A -c test_gns_lookup.conf` TESTEGOZONE=`gnunet-identity -c test_gns_lookup.conf -d | awk '{print $3}'` gnunet-namestore -p -z testego -d -n $TEST_RECORD_NAME_DNS -t CNAME -V $TEST_RECORD_CNAME_DNS -e never -c test_gns_lookup.conf gnunet-namestore -p -z testego -d -n $TEST_RECORD_NAME_PLUS -t CNAME -V $TEST_RECORD_CNAME_PLUS -e never -c test_gns_lookup.conf gnunet-namestore -p -z testego -d -n $TEST_RECORD_CNAME_SERVER -t A -V $TEST_IP_PLUS -e never -c test_gns_lookup.conf gnunet-identity -D testego -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_CNAME_RAW" == "server.$TESTEGOZONE.zkey" ] then echo "PASS: CNAME resulution from GNS" else echo "FAIL: CNAME resolution from GNS, got $RES_CNAME_RAW." exit 1 fi if [ "$RES_CNAME" == "$TEST_IP_PLUS" ] then echo "PASS: IP resulution from GNS" else echo "FAIL: IP resolution from GNS, got $RES_CNAME." exit 1 fi if [ "$RES_CNAME_DNS" == "$TEST_IP_DNS" ] then echo "PASS: IP resulution from DNS" exit 0 else echo "FAIL: IP resulution from DNS, got $RES_IP." exit 1 fi gnunet-0.10.1/src/gns/test_gns_ipv6_lookup.sh0000755000175000017500000000207012300637202016104 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf `gnunet-config -c test_gns_lookup.conf -s PATHS -o GNUNET_HOME -f` which timeout &> /dev/null && DO_TIMEOUT="timeout 30" TEST_IP="dead::beef" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n www -t AAAA -V $TEST_IP -e never -c test_gns_lookup.conf RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.gnu -t AAAA -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n www -t AAAA -V $TEST_IP -e never -c test_gns_lookup.conf gnunet-identity -D testego -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_IP" == "$TEST_IP" ] then exit 0 else echo "Failed to resolve to proper IP, got $RES_IP." exit 1 fi gnunet-0.10.1/src/gns/test_gns_lookup.sh0000755000175000017500000000202012261236532015142 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf `gnunet-config -c test_gns_lookup.conf -s PATHS -o GNUNET_HOME -f` which timeout &> /dev/null && DO_TIMEOUT="timeout 30" TEST_IP="127.0.0.1" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.gnu -t A -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf gnunet-identity -D testego -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf if [ "$RES_IP" == "$TEST_IP" ] then exit 0 else echo "FAIL: Failed to resolve to proper IP, got $RES_IP." exit 1 fi gnunet-0.10.1/src/gns/test_gns_delegated_lookup.sh0000755000175000017500000000250512261236532017150 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT which timeout &> /dev/null && DO_TIMEOUT="timeout 30" LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf /tmp/test-gnunet-gns-peer-1/ TEST_IP="127.0.0.1" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C delegatedego -c test_gns_lookup.conf DELEGATED_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep delegatedego | awk '{print $3}') gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -p -z delegatedego -a -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.b.gnu -t A -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -z delegatedego -d -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_IP" == "$TEST_IP" ] then exit 0 else echo "Failed to resolve to proper IP, got $RES_IP." exit 1 fi gnunet-0.10.1/src/gns/nss/0000755000175000017500000000000012320755627012264 500000000000000gnunet-0.10.1/src/gns/nss/nss_gns_query.c0000644000175000017500000000452412276375236015260 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "nss_gns_query.h" #include #include #include #include /** * Wrapper function that uses gnunet-gns cli tool to resolve * an IPv4/6 address. * * @param af address family * @param name the name to resolve * @param u the userdata (result struct) * @return -1 on error else 0 */ int gns_resolve_name (int af, const char *name, struct userdata *u) { FILE *p; char *cmd; char line[128]; if (AF_INET6 == af) { if (-1 == asprintf (&cmd, "%s -t AAAA -u %s\n", "gnunet-gns -r", name)) return -1; } else { if (-1 == asprintf (&cmd, "%s %s\n", "gnunet-gns -r -u", name)) return -1; } if (NULL == (p = popen (cmd, "r"))) { free (cmd); return -1; } while (NULL != fgets (line, sizeof(line), p)) { if (u->count >= MAX_ENTRIES) break; if (line[strlen(line)-1] == '\n') { line[strlen(line)-1] = '\0'; if (AF_INET == af) { if (inet_pton(af, line, &(u->data.ipv4[u->count]))) { u->count++; u->data_len += sizeof(ipv4_address_t); } else { pclose (p); free (cmd); return -1; } } else if (AF_INET6 == af) { if (inet_pton(af, line, &(u->data.ipv6[u->count]))) { u->count++; u->data_len += sizeof(ipv6_address_t); } else { pclose (p); free (cmd); return -1; } } } } pclose (p); free (cmd); return 0; } /* end of nss_gns_query.c */ gnunet-0.10.1/src/gns/nss/map-file0000644000175000017500000000044611752221411013610 00000000000000NSSGNS_0 { global: _nss_gns_gethostbyaddr_r; _nss_gns4_gethostbyaddr_r; _nss_gns6_gethostbyaddr_r; _nss_gns_gethostbyname_r; _nss_gns4_gethostbyname_r; _nss_gns6_gethostbyname_r; _nss_gns_gethostbyname2_r; _nss_gns4_gethostbyname2_r; _nss_gns6_gethostbyname2_r; local: *; }; gnunet-0.10.1/src/gns/nss/nss_gns.c0000644000175000017500000001400612276375236014027 00000000000000/*** This file is part of nss-gns. Parts taken from: nss.c in nss-mdns nss-mdns is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. nss-mdns is distributed in the hope that it will be useful, but1 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with nss-mdns; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ***/ #include #include #include #include #include #include #include #include #include #include #include "nss_gns_query.h" #include /** macro to align idx to 32bit boundary */ #define ALIGN(idx) do { \ if (idx % sizeof(void*)) \ idx += (sizeof(void*) - idx % sizeof(void*)); /* Align on 32 bit boundary */ \ } while(0) /** * function to check if name ends with a specific suffix * * @param name the name to check * @param suffix the suffix to check for * @return 1 if true */ static int ends_with(const char *name, const char* suffix) { size_t ln, ls; assert(name); assert(suffix); if ((ls = strlen(suffix)) > (ln = strlen(name))) return 0; return strcasecmp(name+ln-ls, suffix) == 0; } /** * Check if name is inside .gnu or .zkey TLD * * @param name name to check * @return 1 if true */ static int verify_name_allowed (const char *name) { return ends_with(name, ".gnu") || ends_with(name, ".zkey"); } /** * The gethostbyname hook executed by nsswitch * * @param name the name to resolve * @param af the address family to resolve * @param result the result hostent * @param buffer the result buffer * @param buflen length of the buffer * @param errnop idk * @param h_errnop idk * @return a nss_status code */ enum nss_status _nss_gns_gethostbyname2_r( const char *name, int af, struct hostent * result, char *buffer, size_t buflen, int *errnop, int *h_errnop) { struct userdata u; enum nss_status status = NSS_STATUS_UNAVAIL; int i; size_t address_length, l, idx, astart; int name_allowed; if (af == AF_UNSPEC) #ifdef NSS_IPV6_ONLY af = AF_INET6; #else af = AF_INET; #endif #ifdef NSS_IPV4_ONLY if (af != AF_INET) #elif NSS_IPV6_ONLY if (af != AF_INET6) #else if (af != AF_INET && af != AF_INET6) #endif { *errnop = EINVAL; *h_errnop = NO_RECOVERY; goto finish; } address_length = af == AF_INET ? sizeof(ipv4_address_t) : sizeof(ipv6_address_t); if (buflen < sizeof(char*)+ /* alias names */ strlen(name)+1) { /* official name */ *errnop = ERANGE; *h_errnop = NO_RECOVERY; status = NSS_STATUS_TRYAGAIN; goto finish; } u.count = 0; u.data_len = 0; name_allowed = verify_name_allowed(name); if (name_allowed) { if (!gns_resolve_name(af, name, &u) == 0) { status = NSS_STATUS_NOTFOUND; goto finish; } } else { status = NSS_STATUS_UNAVAIL; goto finish; } if (u.count == 0) { *errnop = ETIMEDOUT; *h_errnop = HOST_NOT_FOUND; status = NSS_STATUS_NOTFOUND; goto finish; } /* Alias names */ *((char**) buffer) = NULL; result->h_aliases = (char**) buffer; idx = sizeof(char*); /* Official name */ strcpy(buffer+idx, name); result->h_name = buffer+idx; idx += strlen(name)+1; ALIGN(idx); result->h_addrtype = af; result->h_length = address_length; /* Check if there's enough space for the addresses */ if (buflen < idx+u.data_len+sizeof(char*)*(u.count+1)) { *errnop = ERANGE; *h_errnop = NO_RECOVERY; status = NSS_STATUS_TRYAGAIN; goto finish; } /* Addresses */ astart = idx; l = u.count*address_length; memcpy(buffer+astart, &u.data, l); /* address_length is a multiple of 32bits, so idx is still aligned * correctly */ idx += l; /* Address array address_lenght is always a multiple of 32bits */ for (i = 0; i < u.count; i++) ((char**) (buffer+idx))[i] = buffer+astart+address_length*i; ((char**) (buffer+idx))[i] = NULL; result->h_addr_list = (char**) (buffer+idx); status = NSS_STATUS_SUCCESS; finish: return status; } /** * The gethostbyname hook executed by nsswitch * * @param name the name to resolve * @param result the result hostent * @param buffer the result buffer * @param buflen length of the buffer * @param errnop idk * @param h_errnop idk * @return a nss_status code */ enum nss_status _nss_gns_gethostbyname_r ( const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) { return _nss_gns_gethostbyname2_r( name, AF_UNSPEC, result, buffer, buflen, errnop, h_errnop); } /** * The gethostbyaddr hook executed by nsswitch * We can't do this so we always return NSS_STATUS_UNAVAIL * * @param addr the address to resolve * @param len the length of the address * @param af the address family of the address * @param result the result hostent * @param buffer the result buffer * @param buflen length of the buffer * @param errnop idk * @param h_errnop idk * @return NSS_STATUS_UNAVAIL */ enum nss_status _nss_gns_gethostbyaddr_r( const void* addr, int len, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) { *errnop = EINVAL; *h_errnop = NO_RECOVERY; //NOTE we allow to leak this into DNS so no NOTFOUND return NSS_STATUS_UNAVAIL; } gnunet-0.10.1/src/gns/nss/Makefile.in0000644000175000017500000010263512320752061014245 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # $Id$ # # This file taken and modified from nss-gns. # # nss-gns is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 3 of the # License, or (at your option) any later version. # # nss-gns is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with nss-gns; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = src/gns/nss DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(nssdir)" LTLIBRARIES = $(nss_LTLIBRARIES) libnss_gns_la_LIBADD = am__objects_1 = libnss_gns_la-nss_gns_query.lo am_libnss_gns_la_OBJECTS = $(am__objects_1) libnss_gns_la-nss_gns.lo libnss_gns_la_OBJECTS = $(am_libnss_gns_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libnss_gns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libnss_gns_la_CFLAGS) \ $(CFLAGS) $(libnss_gns_la_LDFLAGS) $(LDFLAGS) -o $@ @INSTALL_NSS_TRUE@@MINGW_FALSE@am_libnss_gns_la_rpath = -rpath \ @INSTALL_NSS_TRUE@@MINGW_FALSE@ $(nssdir) libnss_gns4_la_LIBADD = am__objects_2 = libnss_gns4_la-nss_gns_query.lo am__objects_3 = $(am__objects_2) libnss_gns4_la-nss_gns.lo am_libnss_gns4_la_OBJECTS = $(am__objects_3) libnss_gns4_la_OBJECTS = $(am_libnss_gns4_la_OBJECTS) libnss_gns4_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libnss_gns4_la_CFLAGS) $(CFLAGS) $(libnss_gns4_la_LDFLAGS) \ $(LDFLAGS) -o $@ @INSTALL_NSS_TRUE@@MINGW_FALSE@am_libnss_gns4_la_rpath = -rpath \ @INSTALL_NSS_TRUE@@MINGW_FALSE@ $(nssdir) libnss_gns6_la_LIBADD = am__objects_4 = libnss_gns6_la-nss_gns_query.lo am__objects_5 = $(am__objects_4) libnss_gns6_la-nss_gns.lo am_libnss_gns6_la_OBJECTS = $(am__objects_5) libnss_gns6_la_OBJECTS = $(am_libnss_gns6_la_OBJECTS) libnss_gns6_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libnss_gns6_la_CFLAGS) $(CFLAGS) $(libnss_gns6_la_LDFLAGS) \ $(LDFLAGS) -o $@ @INSTALL_NSS_TRUE@@MINGW_FALSE@am_libnss_gns6_la_rpath = -rpath \ @INSTALL_NSS_TRUE@@MINGW_FALSE@ $(nssdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libnss_gns_la_SOURCES) $(libnss_gns4_la_SOURCES) \ $(libnss_gns6_la_SOURCES) DIST_SOURCES = $(libnss_gns_la_SOURCES) $(libnss_gns4_la_SOURCES) \ $(libnss_gns6_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = map-file \ install-nss-plugin.sh \ uninstall-nss-plugin.sh AM_LDFLAGS = -avoid-version -module -export-dynamic nssdir = $(NSS_DIR) @INSTALL_NSS_TRUE@@MINGW_FALSE@nss_LTLIBRARIES = \ @INSTALL_NSS_TRUE@@MINGW_FALSE@ libnss_gns.la \ @INSTALL_NSS_TRUE@@MINGW_FALSE@ libnss_gns4.la \ @INSTALL_NSS_TRUE@@MINGW_FALSE@ libnss_gns6.la sources = nss_gns_query.h nss_gns_query.c # GNU Libc libnss_gns_la_SOURCES = $(sources) nss_gns.c libnss_gns_la_CFLAGS = $(AM_CFLAGS) -D_GNU_SOURCE libnss_gns_la_LDFLAGS = $(AM_LDFLAGS) -shrext .so.2 -Wl,-version-script=$(srcdir)/map-file libnss_gns4_la_SOURCES = $(libnss_gns_la_SOURCES) libnss_gns4_la_CFLAGS = $(libnss_gns_la_CFLAGS) -DNSS_IPV4_ONLY=1 libnss_gns4_la_LDFLAGS = $(libnss_gns_la_LDFLAGS) libnss_gns6_la_SOURCES = $(libnss_gns_la_SOURCES) libnss_gns6_la_CFLAGS = $(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1 libnss_gns6_la_LDFLAGS = $(libnss_gns_la_LDFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gns/nss/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/gns/nss/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-nssLTLIBRARIES: $(nss_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(nss_LTLIBRARIES)'; test -n "$(nssdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(nssdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(nssdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(nssdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(nssdir)"; \ } uninstall-nssLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(nss_LTLIBRARIES)'; test -n "$(nssdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(nssdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(nssdir)/$$f"; \ done clean-nssLTLIBRARIES: -test -z "$(nss_LTLIBRARIES)" || rm -f $(nss_LTLIBRARIES) @list='$(nss_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libnss_gns.la: $(libnss_gns_la_OBJECTS) $(libnss_gns_la_DEPENDENCIES) $(EXTRA_libnss_gns_la_DEPENDENCIES) $(AM_V_CCLD)$(libnss_gns_la_LINK) $(am_libnss_gns_la_rpath) $(libnss_gns_la_OBJECTS) $(libnss_gns_la_LIBADD) $(LIBS) libnss_gns4.la: $(libnss_gns4_la_OBJECTS) $(libnss_gns4_la_DEPENDENCIES) $(EXTRA_libnss_gns4_la_DEPENDENCIES) $(AM_V_CCLD)$(libnss_gns4_la_LINK) $(am_libnss_gns4_la_rpath) $(libnss_gns4_la_OBJECTS) $(libnss_gns4_la_LIBADD) $(LIBS) libnss_gns6.la: $(libnss_gns6_la_OBJECTS) $(libnss_gns6_la_DEPENDENCIES) $(EXTRA_libnss_gns6_la_DEPENDENCIES) $(AM_V_CCLD)$(libnss_gns6_la_LINK) $(am_libnss_gns6_la_rpath) $(libnss_gns6_la_OBJECTS) $(libnss_gns6_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns4_la-nss_gns.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns4_la-nss_gns_query.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns6_la-nss_gns.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns6_la-nss_gns_query.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns_la-nss_gns.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnss_gns_la-nss_gns_query.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libnss_gns_la-nss_gns_query.lo: nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -MT libnss_gns_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns_la-nss_gns_query.Tpo -c -o libnss_gns_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns_la-nss_gns_query.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns_query.c' object='libnss_gns_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -c -o libnss_gns_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c libnss_gns_la-nss_gns.lo: nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -MT libnss_gns_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns_la-nss_gns.Tpo -c -o libnss_gns_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns_la-nss_gns.Tpo $(DEPDIR)/libnss_gns_la-nss_gns.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns.c' object='libnss_gns_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns_la_CFLAGS) $(CFLAGS) -c -o libnss_gns_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c libnss_gns4_la-nss_gns_query.lo: nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -MT libnss_gns4_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns4_la-nss_gns_query.Tpo -c -o libnss_gns4_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns4_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns4_la-nss_gns_query.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns_query.c' object='libnss_gns4_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -c -o libnss_gns4_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c libnss_gns4_la-nss_gns.lo: nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -MT libnss_gns4_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns4_la-nss_gns.Tpo -c -o libnss_gns4_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns4_la-nss_gns.Tpo $(DEPDIR)/libnss_gns4_la-nss_gns.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns.c' object='libnss_gns4_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns4_la_CFLAGS) $(CFLAGS) -c -o libnss_gns4_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c libnss_gns6_la-nss_gns_query.lo: nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -MT libnss_gns6_la-nss_gns_query.lo -MD -MP -MF $(DEPDIR)/libnss_gns6_la-nss_gns_query.Tpo -c -o libnss_gns6_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns6_la-nss_gns_query.Tpo $(DEPDIR)/libnss_gns6_la-nss_gns_query.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns_query.c' object='libnss_gns6_la-nss_gns_query.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -c -o libnss_gns6_la-nss_gns_query.lo `test -f 'nss_gns_query.c' || echo '$(srcdir)/'`nss_gns_query.c libnss_gns6_la-nss_gns.lo: nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -MT libnss_gns6_la-nss_gns.lo -MD -MP -MF $(DEPDIR)/libnss_gns6_la-nss_gns.Tpo -c -o libnss_gns6_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnss_gns6_la-nss_gns.Tpo $(DEPDIR)/libnss_gns6_la-nss_gns.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nss_gns.c' object='libnss_gns6_la-nss_gns.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnss_gns6_la_CFLAGS) $(CFLAGS) -c -o libnss_gns6_la-nss_gns.lo `test -f 'nss_gns.c' || echo '$(srcdir)/'`nss_gns.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(nssdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @INSTALL_NSS_FALSE@install-data-hook: @MINGW_TRUE@install-data-hook: @INSTALL_NSS_FALSE@uninstall-hook: @MINGW_TRUE@uninstall-hook: clean: clean-am clean-am: clean-generic clean-libtool clean-nssLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nssLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-nssLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: install-am install-data-am install-strip uninstall-am .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-nssLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-hook install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man \ install-nssLTLIBRARIES install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-hook uninstall-nssLTLIBRARIES @INSTALL_NSS_TRUE@@MINGW_FALSE@install-data-hook: @INSTALL_NSS_TRUE@@MINGW_FALSE@ $(top_srcdir)/src/gns/nss/install-nss-plugin.sh $(SHELL) $(top_builddir) $(nssdir) $(SUDO_BINARY) @INSTALL_NSS_TRUE@@MINGW_FALSE@uninstall-hook: @INSTALL_NSS_TRUE@@MINGW_FALSE@ $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns.so.2" $(SUDO_BINARY) @INSTALL_NSS_TRUE@@MINGW_FALSE@ $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns4.so.2" $(SUDO_BINARY) @INSTALL_NSS_TRUE@@MINGW_FALSE@ $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns6.so.2" $(SUDO_BINARY) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/gns/nss/install-nss-plugin.sh0000755000175000017500000000035312171766515016311 00000000000000#!/bin/sh # $1 - shell # $2 - top_builddir # $3 - nssdir # $4 - sudo binary (empty if root) $4 $1 $2/libtool --mode=finish $3 echo LTINST: $4 $1 $2/libtool --mode=finish $3 $4 rm -f $3/libnss_gns.la $3/libnss_gns4.la $3/libnss_gns6.la gnunet-0.10.1/src/gns/nss/uninstall-nss-plugin.sh0000755000175000017500000000023512171766527016656 00000000000000#!/bin/sh # $1 - shell # $2 - top_builddir # $3 - nssdir+path of library to remove # $4 - sudo binary (empty if root) $4 $1 $2/libtool --mode=uninstall $3 gnunet-0.10.1/src/gns/nss/Makefile.am0000644000175000017500000000417412320751517014240 00000000000000# $Id$ # # This file taken and modified from nss-gns. # # nss-gns is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 3 of the # License, or (at your option) any later version. # # nss-gns is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with nss-gns; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # USA. EXTRA_DIST = map-file \ install-nss-plugin.sh \ uninstall-nss-plugin.sh AM_LDFLAGS=-avoid-version -module -export-dynamic nssdir = $(NSS_DIR) LIBTOOL = $(SUDO_BINARY) $(SHELL) $(top_builddir)/libtool if !MINGW if INSTALL_NSS nss_LTLIBRARIES = \ libnss_gns.la \ libnss_gns4.la \ libnss_gns6.la endif endif sources = nss_gns_query.h nss_gns_query.c # GNU Libc libnss_gns_la_SOURCES= $(sources) nss_gns.c libnss_gns_la_CFLAGS=$(AM_CFLAGS) -D_GNU_SOURCE libnss_gns_la_LDFLAGS=$(AM_LDFLAGS) -shrext .so.2 -Wl,-version-script=$(srcdir)/map-file libnss_gns4_la_SOURCES=$(libnss_gns_la_SOURCES) libnss_gns4_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV4_ONLY=1 libnss_gns4_la_LDFLAGS=$(libnss_gns_la_LDFLAGS) libnss_gns6_la_SOURCES=$(libnss_gns_la_SOURCES) libnss_gns6_la_CFLAGS=$(libnss_gns_la_CFLAGS) -DNSS_IPV6_ONLY=1 libnss_gns6_la_LDFLAGS=$(libnss_gns_la_LDFLAGS) if INSTALL_NSS if !MINGW install-data-hook: $(top_srcdir)/src/gns/nss/install-nss-plugin.sh $(SHELL) $(top_builddir) $(nssdir) $(SUDO_BINARY) uninstall-hook: $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns.so.2" $(SUDO_BINARY) $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns4.so.2" $(SUDO_BINARY) $(top_srcdir)/src/gns/nss/uninstall-nss-plugin.sh $(SHELL) $(top_builddir) "rm -f $(nssdir)/libnss_gns6.so.2" $(SUDO_BINARY) endif endifgnunet-0.10.1/src/gns/nss/nss_gns_query.h0000644000175000017500000000324012276375236015257 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef NSS_GNS_QUERY_H #define NSS_GNS_QUERY_H /** * Parts taken from nss-mdns */ #include /* Maximum number of entries to return */ #define MAX_ENTRIES 16 typedef struct { uint32_t address; } ipv4_address_t; typedef struct { uint8_t address[16]; } ipv6_address_t; struct userdata { int count; int data_len; /* only valid when doing reverse lookup */ union { ipv4_address_t ipv4[MAX_ENTRIES]; ipv6_address_t ipv6[MAX_ENTRIES]; char *name[MAX_ENTRIES]; } data; }; /** * Wrapper function that uses gnunet-gns cli tool to resolve * an IPv4/6 address. * * @param af address family * @param name the name to resolve * @param u the userdata (result struct) * @return -1 on error else 0 */ int gns_resolve_name(int af, const char *name, struct userdata *userdata); #endif gnunet-0.10.1/src/gns/gnunet-gns-helper-service-w32.c0000644000175000017500000006543112255010512017147 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnunet-gns-helper-service-w32.c * @brief an intermediary service to access distributed GNS * @author Christian Grothoff * @author LRN */ #define INITGUID #include "platform.h" #include #include #include #include #include #include "gnunet_w32nsp_lib.h" #include "w32resolver.h" #include #include #define DEFINE_DNS_GUID(a,x) DEFINE_GUID(a, 0x00090035, 0x0000, x, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) DEFINE_DNS_GUID(SVCID_DNS_TYPE_A, 0x0001); DEFINE_DNS_GUID(SVCID_DNS_TYPE_NS, 0x0002); DEFINE_DNS_GUID(SVCID_DNS_TYPE_CNAME, 0x0005); DEFINE_DNS_GUID(SVCID_DNS_TYPE_SOA, 0x0006); DEFINE_DNS_GUID(SVCID_DNS_TYPE_PTR, 0x000c); DEFINE_DNS_GUID(SVCID_DNS_TYPE_MX, 0x000f); DEFINE_DNS_GUID(SVCID_DNS_TYPE_TEXT, 0x0010); DEFINE_DNS_GUID(SVCID_DNS_TYPE_AAAA, 0x001c); DEFINE_DNS_GUID(SVCID_DNS_TYPE_SRV, 0x0021); DEFINE_GUID(SVCID_HOSTNAME, 0x0002a800, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); DEFINE_GUID(SVCID_INET_HOSTADDRBYNAME, 0x0002a803, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); struct request { /** * We keep these in a doubly-linked list (for cleanup). */ struct request *next; /** * We keep these in a doubly-linked list (for cleanup). */ struct request *prev; struct GNUNET_SERVER_Client *client; GUID sc; int af; wchar_t *name; char *u8name; struct GNUNET_GNS_LookupRequest *lookup_request; }; /** * Head of the doubly-linked list (for cleanup). */ static struct request *rq_head; /** * Tail of the doubly-linked list (for cleanup). */ static struct request *rq_tail; /** * Handle to GNS service. */ static struct GNUNET_GNS_Handle *gns; /** * Active operation on identity service. */ static struct GNUNET_IDENTITY_Operation *id_op; /** * Handle for identity service. */ static struct GNUNET_IDENTITY_Handle *identity; /** * Public key of the gns-master ego */ static struct GNUNET_CRYPTO_EcdsaPublicKey gns_master_pubkey; /** * Private key of the gns-short ego */ static struct GNUNET_CRYPTO_EcdsaPrivateKey gns_short_privkey; /** * Set to 1 once egos are obtained. */ static int got_egos = 0; /** * Task run on shutdown. Cleans up everything. * * @param cls unused * @param tc scheduler context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct request *rq; if (NULL != id_op) { GNUNET_IDENTITY_cancel (id_op); id_op = NULL; } if (NULL != identity) { GNUNET_IDENTITY_disconnect (identity); identity = NULL; } while (NULL != (rq = rq_head)) { if (NULL != rq->lookup_request) GNUNET_GNS_lookup_cancel(rq->lookup_request); GNUNET_CONTAINER_DLL_remove (rq_head, rq_tail, rq); GNUNET_free_non_null (rq->name); if (rq->u8name) free (rq->u8name); GNUNET_free (rq); } if (NULL != gns) { GNUNET_GNS_disconnect (gns); gns = NULL; } } /** * Context for transmitting replies to clients. */ struct TransmitCallbackContext { /** * We keep these in a doubly-linked list (for cleanup). */ struct TransmitCallbackContext *next; /** * We keep these in a doubly-linked list (for cleanup). */ struct TransmitCallbackContext *prev; /** * The message that we're asked to transmit. */ struct GNUNET_MessageHeader *msg; /** * Handle for the transmission request. */ struct GNUNET_SERVER_TransmitHandle *th; /** * Handle for the client to which to send */ struct GNUNET_SERVER_Client *client; }; /** * Head of the doubly-linked list (for cleanup). */ static struct TransmitCallbackContext *tcc_head; /** * Tail of the doubly-linked list (for cleanup). */ static struct TransmitCallbackContext *tcc_tail; /** * Have we already cleaned up the TCCs and are hence no longer * willing (or able) to transmit anything to anyone? */ static int cleaning_done; /** * Function called to notify a client about the socket * being ready to queue more data. "buf" will be * NULL and "size" zero if the socket was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_callback (void *cls, size_t size, void *buf) { struct TransmitCallbackContext *tcc = cls; size_t msize; tcc->th = NULL; GNUNET_CONTAINER_DLL_remove (tcc_head, tcc_tail, tcc); msize = ntohs (tcc->msg->size); if (size == 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Transmission to client failed!\n")); GNUNET_free (tcc->msg); GNUNET_free (tcc); return 0; } GNUNET_assert (size >= msize); memcpy (buf, tcc->msg, msize); GNUNET_free (tcc->msg); GNUNET_free (tcc); for (tcc = tcc_head; tcc; tcc = tcc->next) { if (NULL == tcc->th) { tcc->th = GNUNET_SERVER_notify_transmit_ready (tcc->client, ntohs (tcc->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_callback, tcc); break; } } return msize; } /** * Transmit the given message to the client. * * @param client target of the message * @param msg message to transmit, will be freed! */ static void transmit (struct GNUNET_SERVER_Client *client, struct GNUNET_MessageHeader *msg) { struct TransmitCallbackContext *tcc; if (GNUNET_YES == cleaning_done) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Shutdown in progress, aborting transmission.\n")); GNUNET_free (msg); return; } tcc = GNUNET_new (struct TransmitCallbackContext); tcc->msg = msg; tcc->client = client; tcc->th = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_callback, tcc); GNUNET_CONTAINER_DLL_insert (tcc_head, tcc_tail, tcc); } #define MarshallPtr(ptr, base, type) \ if (ptr) \ ptr = (type *) ((char *) ptr - (char *) base) void MarshallWSAQUERYSETW (WSAQUERYSETW *qs, GUID *sc) { int i; MarshallPtr (qs->lpszServiceInstanceName, qs, wchar_t); MarshallPtr (qs->lpServiceClassId, qs, GUID); MarshallPtr (qs->lpVersion, qs, WSAVERSION); MarshallPtr (qs->lpNSProviderId, qs, GUID); MarshallPtr (qs->lpszContext, qs, wchar_t); MarshallPtr (qs->lpafpProtocols, qs, AFPROTOCOLS); MarshallPtr (qs->lpszQueryString, qs, wchar_t); for (i = 0; i < qs->dwNumberOfCsAddrs; i++) { MarshallPtr (qs->lpcsaBuffer[i].LocalAddr.lpSockaddr, qs, SOCKADDR); MarshallPtr (qs->lpcsaBuffer[i].RemoteAddr.lpSockaddr, qs, SOCKADDR); } MarshallPtr (qs->lpcsaBuffer, qs, CSADDR_INFO); if (IsEqualGUID (&SVCID_INET_HOSTADDRBYNAME, sc) && qs->lpBlob != NULL && qs->lpBlob->pBlobData != NULL) { struct hostent *he; he = (struct hostent *) qs->lpBlob->pBlobData; for (i = 0; he->h_aliases[i] != NULL; i++) MarshallPtr (he->h_aliases[i], he, char); MarshallPtr (he->h_aliases, he, char *); MarshallPtr (he->h_name, he, char); for (i = 0; he->h_addr_list[i] != NULL; i++) MarshallPtr (he->h_addr_list[i], he, void); MarshallPtr (he->h_addr_list, he, char *); MarshallPtr (qs->lpBlob->pBlobData, qs, void); } MarshallPtr (qs->lpBlob, qs, BLOB); } static void process_lookup_result (void* cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int i, j, csanum; struct request *rq = (struct request *) cls; struct GNUNET_W32RESOLVER_GetMessage *msg; struct GNUNET_MessageHeader *msgend; WSAQUERYSETW *qs; size_t size; size_t size_recalc; char *ptr; size_t blobsize = 0; size_t blobaddrcount = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got lookup result with count %u for rq %p with client %p\n", rd_count, rq, rq->client); rq->lookup_request = NULL; if (rd_count == 0) { size = sizeof (struct GNUNET_MessageHeader); msg = GNUNET_malloc (size); msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); transmit (rq->client, &msg->header); GNUNET_CONTAINER_DLL_remove (rq_head, rq_tail, rq); GNUNET_free_non_null (rq->name); if (rq->u8name) free (rq->u8name); GNUNET_free (rq); return; } size = sizeof (struct GNUNET_W32RESOLVER_GetMessage) + sizeof (WSAQUERYSETW); size += (wcslen (rq->name) + 1) * sizeof (wchar_t); size += sizeof (GUID); /* lpszComment ? a TXT record? */ size += sizeof (GUID); /* lpszContext ? Not sure what it is */ csanum = 0; for (i = 0; i < rd_count; i++) { switch (rd[i].record_type) { case GNUNET_DNSPARSER_TYPE_A: if (rd[i].data_size != sizeof (struct in_addr)) continue; size += sizeof (CSADDR_INFO) + sizeof (struct sockaddr_in) * 2; csanum++; break; case GNUNET_DNSPARSER_TYPE_AAAA: if (rd[i].data_size != sizeof (struct in6_addr)) continue; size += sizeof (CSADDR_INFO) + sizeof (struct sockaddr_in6) * 2; csanum++; break; } } if (IsEqualGUID (&SVCID_INET_HOSTADDRBYNAME, &rq->sc)) { size += sizeof (BLOB); blobsize += sizeof (struct hostent); blobsize += strlen (rq->u8name) + 1; blobsize += sizeof (void *); /* For aliases */ blobsize += sizeof (void *); /* For addresses */ for (i = 0; i < rd_count; i++) { if ((rq->af == AF_INET || rq->af == AF_UNSPEC) && rd[i].record_type == GNUNET_DNSPARSER_TYPE_A) { blobsize += sizeof (void *); blobsize += sizeof (struct in_addr); blobaddrcount++; } else if (rq->af == AF_INET6 && rd[i].record_type == GNUNET_DNSPARSER_TYPE_AAAA) { blobsize += sizeof (void *); blobsize += sizeof (struct in6_addr); blobaddrcount++; } } size += blobsize; } size_recalc = sizeof (struct GNUNET_W32RESOLVER_GetMessage) + sizeof (WSAQUERYSETW); msg = GNUNET_malloc (size); msg->header.size = htons (size - sizeof (struct GNUNET_MessageHeader)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); msg->af = htonl (rq->af); msg->sc_data1 = htonl (rq->sc.Data1); msg->sc_data2 = htons (rq->sc.Data2); msg->sc_data3 = htons (rq->sc.Data3); for (i = 0; i < 8; i++) msg->sc_data4[i] = rq->sc.Data4[i]; qs = (WSAQUERYSETW *) &msg[1]; ptr = (char *) &qs[1]; GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); qs->dwSize = sizeof (WSAQUERYSETW); qs->lpszServiceInstanceName = (wchar_t *) ptr; ptr += (wcslen (rq->name) + 1) * sizeof (wchar_t); size_recalc += (wcslen (rq->name) + 1) * sizeof (wchar_t); GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); wcscpy (qs->lpszServiceInstanceName, rq->name); qs->lpServiceClassId = (GUID *) ptr; ptr += sizeof (GUID); size_recalc += sizeof (GUID); GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); memcpy (qs->lpServiceClassId, &rq->sc, sizeof (GUID)); qs->lpVersion = NULL; qs->dwNameSpace = NS_DNS; qs->lpNSProviderId = (GUID *) ptr; ptr += sizeof (GUID); size_recalc += sizeof (GUID); GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); memcpy (qs->lpNSProviderId, &GNUNET_NAMESPACE_PROVIDER_DNS, sizeof (GUID)); qs->lpszContext = NULL; qs->dwNumberOfProtocols = 0; qs->lpafpProtocols = NULL; /* Don't bother with this... */ qs->lpszQueryString = NULL; qs->dwNumberOfCsAddrs = rd_count; qs->lpcsaBuffer = (CSADDR_INFO *) ptr; ptr += sizeof (CSADDR_INFO) * csanum; j = 0; for (i = 0; i < rd_count; i++) { switch (rd[i].record_type) { case GNUNET_DNSPARSER_TYPE_A: if (rd[i].data_size != sizeof (struct in_addr)) continue; qs->lpcsaBuffer[j].iSocketType = SOCK_STREAM; qs->lpcsaBuffer[j].iProtocol = IPPROTO_TCP; qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength = sizeof (struct sockaddr_in); qs->lpcsaBuffer[j].LocalAddr.lpSockaddr = (SOCKADDR *) ptr; ptr += qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength; memset (qs->lpcsaBuffer[j].LocalAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength); ((struct sockaddr_in *)qs->lpcsaBuffer[j].LocalAddr.lpSockaddr)->sin_family = AF_INET; qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength = sizeof (struct sockaddr_in); qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr = (SOCKADDR *) ptr; ptr += qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength; memset (qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength); ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_family = AF_INET; ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_port = htonl (53); /* Don't ask why it's 53 */ ((struct sockaddr_in *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin_addr = *(struct in_addr *) rd[i].data; size_recalc += sizeof (CSADDR_INFO) + sizeof (struct sockaddr_in) * 2; j++; break; case GNUNET_DNSPARSER_TYPE_AAAA: if (rd[i].data_size != sizeof (struct in6_addr)) continue; qs->lpcsaBuffer[j].iSocketType = SOCK_STREAM; qs->lpcsaBuffer[j].iProtocol = IPPROTO_TCP; qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength = sizeof (struct sockaddr_in6); qs->lpcsaBuffer[j].LocalAddr.lpSockaddr = (SOCKADDR *) ptr; ptr += qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength; memset (qs->lpcsaBuffer[j].LocalAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].LocalAddr.iSockaddrLength); ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].LocalAddr.lpSockaddr)->sin6_family = AF_INET6; qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength = sizeof (struct sockaddr_in6); qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr = (SOCKADDR *) ptr; ptr += qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength; memset (qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr, 0, qs->lpcsaBuffer[j].RemoteAddr.iSockaddrLength); ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_family = AF_INET6; ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_port = htonl (53); /* Don't ask why it's 53 */ ((struct sockaddr_in6 *)qs->lpcsaBuffer[j].RemoteAddr.lpSockaddr)->sin6_addr = *(struct in6_addr *) rd[i].data; size_recalc += sizeof (CSADDR_INFO) + sizeof (struct sockaddr_in6) * 2; j++; break; default: break; } } GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); qs->dwOutputFlags = 0; if (IsEqualGUID (&SVCID_INET_HOSTADDRBYNAME, &rq->sc)) { struct hostent *he; qs->lpBlob = (BLOB *) ptr; ptr += sizeof (BLOB); size_recalc += sizeof (BLOB); GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); qs->lpBlob->cbSize = blobsize; qs->lpBlob->pBlobData = (BYTE *) ptr; ptr += sizeof (struct hostent); size_recalc += sizeof (struct hostent); GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); he = (struct hostent *) qs->lpBlob->pBlobData; he->h_name = (char *) ptr; ptr += strlen (rq->u8name) + 1; size_recalc += strlen (rq->u8name) + 1; GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); strcpy (he->h_name, rq->u8name); he->h_aliases = (char **) ptr; ptr += sizeof (void *); size_recalc += sizeof (void *); /* For aliases */ GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); he->h_aliases[0] = NULL; he->h_addrtype = rq->af; he->h_length = rq->af == AF_INET || rq->af == AF_UNSPEC ? sizeof (struct in_addr) : sizeof (struct in6_addr); he->h_addr_list = (char **) ptr; ptr += sizeof (void *) * (blobaddrcount + 1); size_recalc += sizeof (void *) * (blobaddrcount + 1); /* For addresses */ GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); j = 0; for (i = 0; i < rd_count; i++) { if ((rq->af == AF_INET || rq->af == AF_UNSPEC) && rd[i].record_type == GNUNET_DNSPARSER_TYPE_A) { he->h_addr_list[j] = (char *) ptr; ptr += sizeof (struct in_addr); size_recalc += sizeof (struct in_addr); GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); memcpy (he->h_addr_list[j], rd[i].data, sizeof (struct in_addr)); j++; } else if (rq->af == AF_INET6 && rd[i].record_type == GNUNET_DNSPARSER_TYPE_AAAA) { he->h_addr_list[j] = (char *) ptr; ptr += sizeof (struct in6_addr); size_recalc += sizeof (struct in6_addr); GNUNET_break (size_recalc == (size_t) ((char *) ptr - (char *) msg)); memcpy (he->h_addr_list[j], rd[i].data, sizeof (struct in6_addr)); j++; } } he->h_addr_list[j] = NULL; } msgend = GNUNET_new (struct GNUNET_MessageHeader); msgend->type = htons (GNUNET_MESSAGE_TYPE_W32RESOLVER_RESPONSE); msgend->size = htons (sizeof (struct GNUNET_MessageHeader)); if ((char *) ptr - (char *) msg != size || size_recalc != size || size_recalc != ((char *) ptr - (char *) msg)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error in WSAQUERYSETW size calc: expected %lu, got %lu (recalc %lu)\n", size, (unsigned long) ((char *) ptr - (char *) msg), size_recalc); } MarshallWSAQUERYSETW (qs, &rq->sc); transmit (rq->client, &msg->header); transmit (rq->client, msgend); GNUNET_CONTAINER_DLL_remove (rq_head, rq_tail, rq); GNUNET_free_non_null (rq->name); if (rq->u8name) free (rq->u8name); GNUNET_free (rq); } static void get_ip_from_hostname (struct GNUNET_SERVER_Client *client, const wchar_t *name, int af, GUID sc) { struct request *rq; char *hostname; size_t strl; size_t namelen; uint32_t rtype; if (IsEqualGUID (&SVCID_DNS_TYPE_A, &sc)) rtype = GNUNET_DNSPARSER_TYPE_A; else if (IsEqualGUID (&SVCID_DNS_TYPE_NS, &sc)) rtype = GNUNET_DNSPARSER_TYPE_NS; else if (IsEqualGUID (&SVCID_DNS_TYPE_CNAME, &sc)) rtype = GNUNET_DNSPARSER_TYPE_CNAME; else if (IsEqualGUID (&SVCID_DNS_TYPE_SOA, &sc)) rtype = GNUNET_DNSPARSER_TYPE_SOA; else if (IsEqualGUID (&SVCID_DNS_TYPE_PTR, &sc)) rtype = GNUNET_DNSPARSER_TYPE_PTR; else if (IsEqualGUID (&SVCID_DNS_TYPE_MX, &sc)) rtype = GNUNET_DNSPARSER_TYPE_MX; else if (IsEqualGUID (&SVCID_DNS_TYPE_TEXT, &sc)) rtype = GNUNET_DNSPARSER_TYPE_TXT; else if (IsEqualGUID (&SVCID_DNS_TYPE_AAAA, &sc)) rtype = GNUNET_DNSPARSER_TYPE_AAAA; else if (IsEqualGUID (&SVCID_DNS_TYPE_SRV, &sc)) rtype = GNUNET_DNSPARSER_TYPE_SRV; else if (IsEqualGUID (&SVCID_INET_HOSTADDRBYNAME, &sc)) rtype = GNUNET_DNSPARSER_TYPE_A; else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unknown GUID: %08X-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", sc.Data1, sc.Data2, sc.Data3, sc.Data4[0], sc.Data4[1], sc.Data4[2], sc.Data4[3], sc.Data4[4], sc.Data4[5], sc.Data4[6], sc.Data4[7]); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (name) namelen = wcslen (name); else namelen = 0; if (namelen > 0) hostname = (char *) u16_to_u8 (name, namelen + 1, NULL, &strl); else hostname = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "W32 DNS resolver asked to look up %s for `%s'.\n", af == AF_INET ? "IPv4" : af == AF_INET6 ? "IPv6" : "anything", hostname); rq = GNUNET_new (struct request); rq->sc = sc; rq->client = client; rq->af = af; if (rq->af != AF_INET && rq->af != AF_INET6) rq->af = AF_INET; if (namelen) { rq->name = GNUNET_malloc ((namelen + 1) * sizeof (wchar_t)); memcpy (rq->name, name, (namelen + 1) * sizeof (wchar_t)); rq->u8name = hostname; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Launching a lookup for client %p with rq %p\n", client, rq); rq->lookup_request = GNUNET_GNS_lookup (gns, hostname, &gns_master_pubkey, rtype, GNUNET_NO /* Use DHT */, &gns_short_privkey, &process_lookup_result, rq); if (NULL != rq->lookup_request) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup launched, waiting for a reply\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_CONTAINER_DLL_insert (rq_head, rq_tail, rq); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lookup was not launched, disconnecting the client\n"); GNUNET_free_non_null (rq->name); if (rq->u8name) free (rq->u8name); GNUNET_free (rq); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); } } /** * Handle GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { uint16_t msize; const struct GNUNET_W32RESOLVER_GetMessage *msg; GUID sc; uint16_t size; int i; const wchar_t *hostname; int af; if (!got_egos) { /* * FIXME: be done with GNUNET_OK, put the get request into a queue? * or postpone GNUNET_SERVER_add_handlers() until egos are obtained? */ GNUNET_SERVER_receive_done (client, GNUNET_NO); return; } msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_W32RESOLVER_GetMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_W32RESOLVER_GetMessage *) message; size = msize - sizeof (struct GNUNET_W32RESOLVER_GetMessage); af = ntohl (msg->af); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got NBO GUID: %08X-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", msg->sc_data1, msg->sc_data2, msg->sc_data3, msg->sc_data4[0], msg->sc_data4[1], msg->sc_data4[2], msg->sc_data4[3], msg->sc_data4[4], msg->sc_data4[5], msg->sc_data4[6], msg->sc_data4[7]); sc.Data1 = ntohl (msg->sc_data1); sc.Data2 = ntohs (msg->sc_data2); sc.Data3 = ntohs (msg->sc_data3); for (i = 0; i < 8; i++) sc.Data4[i] = msg->sc_data4[i]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got GUID: %08X-%04X-%04X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n", sc.Data1, sc.Data2, sc.Data3, sc.Data4[0], sc.Data4[1], sc.Data4[2], sc.Data4[3], sc.Data4[4], sc.Data4[5], sc.Data4[6], sc.Data4[7]); hostname = (const wchar_t *) &msg[1]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "name of %u bytes (last word is 0x%0X): %*S\n", size, hostname[size / 2 - 2], size / 2, hostname); if (hostname[size / 2 - 1] != L'\0') { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "name of length %u, not 0-terminated (%d-th word is 0x%0X): %*S\n", size, size / 2 - 1, hostname[size / 2 - 1], size, hostname); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } get_ip_from_hostname (client, hostname, af, sc); } /** * Method called to with the ego we are to use for shortening * during the lookup. * * @param cls closure (NULL, unused) * @param ego ego handle, NULL if not found * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void identity_shorten_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { id_op = NULL; if (NULL == ego) { fprintf (stderr, _("Ego for `gns-short' not found. This is not really fatal, but i'll pretend that it is and refuse to perform a lookup. Did you run gnunet-gns-import.sh?\n")); GNUNET_SCHEDULER_shutdown (); return; } gns_short_privkey = *GNUNET_IDENTITY_ego_get_private_key (ego); got_egos = 1; } /** * Method called to with the ego we are to use for the lookup, * when the ego is the one for the default master zone. * * @param cls closure (NULL, unused) * @param ego ego handle, NULL if not found * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void identity_master_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { id_op = NULL; if (NULL == ego) { fprintf (stderr, _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n")); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_IDENTITY_ego_get_public_key (ego, &gns_master_pubkey); id_op = GNUNET_IDENTITY_get (identity, "gns-short", &identity_shorten_cb, NULL); GNUNET_assert (NULL != id_op); } /** * Start up gns-helper-w32 service. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_get, NULL, GNUNET_MESSAGE_TYPE_W32RESOLVER_REQUEST, 0}, {NULL, NULL, 0, 0} }; gns = GNUNET_GNS_connect (cfg); if (NULL == gns) { fprintf (stderr, _("Failed to connect to GNS\n")); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); if (NULL == identity) { fprintf (stderr, _("Failed to connect to identity service\n")); GNUNET_SCHEDULER_shutdown (); return; } id_op = GNUNET_IDENTITY_get (identity, "gns-master", &identity_master_cb, NULL); GNUNET_assert (NULL != id_op); GNUNET_SERVER_add_handlers (server, handlers); } /** * The main function for gns-helper-w32. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; ret = GNUNET_SERVICE_run (argc, argv, "gns-helper-service-w32", GNUNET_SERVICE_OPTION_NONE, &run, NULL); return (GNUNET_OK == ret) ? 0 : 1; } /* end of gnunet-gns-helper-service-w32.c */ gnunet-0.10.1/src/gns/test_gns_gns2dns_lookup.sh0000755000175000017500000000662212261236532016614 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -r rm -rf /tmp/test-gnunet-gns-peer-1/ # IP address of 'uk.gnunet.org' TEST_IP_ALT2="81.187.252.184" # IP address of 'www.gnunet.org' TEST_IP="131.159.74.67" # IPv6 address of 'gnunet.org' TEST_IP6="2001:4ca0:2001:42:225:90ff:fe6b:d60" # permissive DNS resolver we will use for the test TEST_IP_GNS2DNS="8.8.8.8" # main label used during resolution TEST_RECORD_NAME="homepage" # various names we will use for resolution TEST_DOMAIN="www.${TEST_RECORD_NAME}.gnu" TEST_DOMAIN_ALT="${TEST_RECORD_NAME}.gnu" TEST_DOMAIN_ALT2="uk.${TEST_RECORD_NAME}.gnu" if ! nslookup gnunet.org $TEST_IP_GNS2DNS &> /dev/null then echo "Cannot reach DNS, skipping test" exit 77 fi # helper record for pointing to the DNS resolver TEST_RESOLVER_LABEL="resolver" # GNS2DNS record value: delegate to DNS domain 'gnunet.org' # using the TEST_RESOLVER_LABEL DNS server for resolution TEST_RECORD_GNS2DNS="gnunet.org@${TEST_RESOLVER_LABEL}.+" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C testego -c test_gns_lookup.conf # set IP address for DNS resolver for resolving in gnunet.org domain gnunet-namestore -p -z testego -a -n $TEST_RESOLVER_LABEL -t A -V $TEST_IP_GNS2DNS -e never -c test_gns_lookup.conf # map 'homepage.gnu' to 'gnunet.org' in DNS gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS -e never -c test_gns_lookup.conf which timeout &> /dev/null && DO_TIMEOUT="timeout 5" # lookup 'www.gnunet.org', IPv4 RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u $TEST_DOMAIN -t A -c test_gns_lookup.conf` # lookup 'www.gnunet.org', IPv6 RES_IP6=`$DO_TIMEOUT gnunet-gns --raw -z testego -u $TEST_DOMAIN -t AAAA -c test_gns_lookup.conf` # lookup 'gnunet.org', IPv4 RES_IP_ALT=`$DO_TIMEOUT gnunet-gns --raw -z testego -u $TEST_DOMAIN_ALT -t A -c test_gns_lookup.conf` # lookup 'uk.gnunet.org', IPv4 RES_IP_ALT2=`$DO_TIMEOUT gnunet-gns --raw -z testego -u $TEST_DOMAIN_ALT2 -t A -c test_gns_lookup.conf` # clean up gnunet-namestore -z testego -d -n $TEST_RESOLVER_LABEL -t A -V $TEST_IP_GNS2DNS -e never -c test_gns_lookup.conf gnunet-namestore -z testego -d -n $TEST_RECORD_NAME -t GNS2DNS -V $TEST_RECORD_GNS2DNS -e never -c test_gns_lookup.conf gnunet-identity -D testego -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ ret=0 if [ "$RES_IP" == "$TEST_IP" ] then echo "PASS: Resolved $TEST_DOMAIN to $RES_IP." else echo "Failed to resolve to proper IP for $TEST_DOMAIN, got $RES_IP, wanted $TEST_IP." ret=1 fi if [ "$RES_IP6" == "$TEST_IP6" ] then echo "PASS: Resolved $TEST_DOMAIN to $RES_IP6." else echo "Failed to resolve to proper IP for $TEST_DOMAIN, got $RES_IP6, wanted $TEST_IP6." ret=1 fi if [ "$RES_IP_ALT" == "$TEST_IP" ] then echo "PASS: Resolved $TEST_DOMAIN_ALT to $RES_IP_ALT." else echo "Failed to resolve to proper IP for $TEST_DOMAIN_ALT, got $RES_IP_ALT, wanted $TEST_IP." ret=1 fi if [ "$RES_IP_ALT2" == "$TEST_IP_ALT2" ] then echo "PASS: Resolved $TEST_DOMAIN_ALT2 to $RES_IP_ALT2." else echo "Failed to resolve to proper IP for $TEST_DOMAIN_ALT2, got $RES_IP_ALT2, wanted $TEST_IP_ALT2." ret=1 fi exit $ret gnunet-0.10.1/src/gns/test_gns_lookup.conf0000644000175000017500000000073412245716446015475 00000000000000@INLINE@ test_gns_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-gns-peer-1/ [dht] AUTOSTART = YES [transport] PLUGINS = [arm] DEFAULTSERVICES = [gns] #PREFIX = valgrind --leak-check=full --track-origins=yes AUTOSTART = YES AUTO_IMPORT_PKEY = YES MAX_PARALLEL_BACKGROUND_QUERIES = 10 DEFAULT_LOOKUP_TIMEOUT = 15 s RECORD_PUT_INTERVAL = 1 h ZONE_PUBLISH_TIME_WINDOW = 1 h DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0 [revocation] WORKBITS = 1 gnunet-0.10.1/src/gns/gnunet-gns-proxy-setup-ca0000644000175000017500000000317512227234273016310 00000000000000#!/bin/sh # This shell script will generate an X509 certificate for your gnunet-gns-proxy # and install it (for both GNUnet and your browser). # echo "Generating CA" options='' while getopts "c:" opt; do case $opt in c) options+="-c $OPTARG" ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done GNSCERT=`mktemp /tmp/gnscertXXXXXX.pem` GNSCAKY=`mktemp /tmp/gnscakeyXXXXXX.pem` GNSCANO=`mktemp /tmp/gnscakeynoencXXXXXX.pem` GNS_CA_CERT_PEM=`gnunet-config -s gns-proxy -o PROXY_CACERT -f $options` mkdir -p `dirname $GNS_CA_CERT_PEM` openssl req -new -x509 -days 3650 -extensions v3_ca -keyout $GNSCAKY -out $GNSCERT -subj "/C=ZZ/L=World/O=GNU/OU=GNUnet/CN=GNS CA/emailAddress=bounce@gnunet.org" -passout pass:"GNU Name System" echo "Removing passphrase from key" openssl rsa -passin pass:"GNU Name System" -in $GNSCAKY -out $GNSCANO cat $GNSCERT $GNSCANO > $GNS_CA_CERT_PEM echo "Importing CA into browsers" for f in ~/.mozilla/firefox/*.default do if [ -d $f ]; then echo "Importing CA info Firefox $f" certutil -D -n "GNS Proxy CA" -d ~/.mozilla/firefox/*.default >/dev/null 2&>1 certutil -A -n "GNS Proxy CA" -t CT,, -d ~/.mozilla/firefox/*.default < $GNSCERT fi done if [ -d ~/.pki/nssdb ]; then echo "Importing CA into Chrome" certutil -D -n "GNS Proxy CA" -d ~/.pki/nssdb >/dev/null 2&>1 certutil -A -n "GNS Proxy CA" -t CT,, -d ~/.pki/nssdb < $GNSCERT fi rm $GNSCAKY $GNSCANO $GNSCERT echo "You can now start gnunet-gns-proxy and configure your browser to use a SOCKS proxy on port 7777" gnunet-0.10.1/src/gns/w32nsp-install.c0000644000175000017500000000700412253574266014351 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/w32nsp-install.c * @brief W32 integration installer for GNS * @author LRN */ #define INITGUID #include #include #include #include "gnunet_w32nsp_lib.h" #include int main (int argc, char **argv) { int ret; int r = 1; WSADATA wsd; GUID id = GNUNET_NAMESPACE_PROVIDER_DNS; wchar_t *cmdl; int wargc; wchar_t **wargv; /* Allocate a 4K buffer to retrieve all the namespace providers */ DWORD dwInitialBufferLen = 4096; DWORD dwBufferLen; WSANAMESPACE_INFO *pi; int p_count; int i; if (WSAStartup (MAKEWORD (2,2), &wsd) != 0) { fprintf (stderr, "WSAStartup () failed: %lu\n", GetLastError ()); return 5; } dwBufferLen = dwInitialBufferLen; pi = malloc (dwBufferLen); if (NULL == pi) { fprintf (stderr, "malloc (%lu) failed: %d\n", dwBufferLen, errno); WSACleanup (); return 6; } p_count = WSAEnumNameSpaceProviders (&dwBufferLen, pi); if (SOCKET_ERROR == p_count) { DWORD err = GetLastError (); if (WSAEFAULT == err && dwBufferLen != dwInitialBufferLen) { free (pi); pi = malloc (dwBufferLen); if (pi == NULL) { fprintf (stderr, "malloc (%lu) failed: %d\n", dwBufferLen, errno); WSACleanup (); return 6; } p_count = WSAEnumNameSpaceProviders (&dwBufferLen, pi); if (SOCKET_ERROR == p_count) { fprintf (stderr, "WSAEnumNameSpaceProviders (&%lu, %p) failed: %lu\n", dwBufferLen, pi, GetLastError ()); free (pi); WSACleanup (); return 7; } } else { fprintf (stderr, "WSAEnumNameSpaceProviders (&%lu, %p) failed: %lu\n", dwBufferLen, pi, GetLastError ()); free (pi); WSACleanup (); return 8; } } for (i= 0; i < p_count; i++) { if (IsEqualGUID (&pi[i].NSProviderId, &id)) { fprintf (stderr, "GNUnet DNS provider is already installed\n"); free (pi); WSACleanup (); return 0; } } free (pi); cmdl = GetCommandLineW (); if (cmdl == NULL) { WSACleanup (); return 2; } wargv = CommandLineToArgvW (cmdl, &wargc); if (wargv == NULL) { WSACleanup (); return 3; } r = 4; if (wargc == 2) { ret = WSCInstallNameSpace (L"GNUnet DNS provider", wargv[1], NS_DNS, 0, &id); if (ret == NO_ERROR) { fprintf (stderr, "Installed GNUnet DNS provider\n"); r = 0; } else { r = 1; fprintf (stderr, "WSCInstallNameSpace (L\"GNUnet DNS provider\", \"%S\", %d, 0, %p) failed: %lu\n", wargv[1], NS_DNS, &id, GetLastError ()); } } else fprintf (stderr, "Usage: %S \n", wargv[0]); WSACleanup (); return r; } gnunet-0.10.1/src/gns/Makefile.am0000644000175000017500000002007012320751517013426 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if HAVE_GLIBCNSS if INSTALL_NSS NSS_SUBDIR = nss endif endif SUBDIRS = . $(NSS_SUBDIR) EXTRA_DIST = \ test_gns_defaults.conf \ test_gns_lookup.conf \ test_gns_nick_shorten.conf \ test_gns_proxy.conf \ test_gns_simple_lookup.conf \ gns-helper-service-w32.conf \ w32nsp.def \ gnunet-gns-proxy-setup-ca \ zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey \ zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey \ zonefiles/test_zonekey \ $(check_SCRIPTS) if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols DO_W32_HELPER = gnunet-gns-helper-service-w32 DO_W32_NSP = libw32nsp.la DO_W32_NSPTOOLS = w32nsp-install w32nsp-uninstall w32nsp-resolve DO_W32_HS_CONF = gns-helper-service-w32.conf DO_NONPOSIX_GNSIMPORT = gnunet-gns-import endif USE_VPN = $(top_builddir)/src/vpn/libgnunetvpn.la if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif pkgcfgdir = $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ gns.conf \ $(DO_W32_HS_CONF) lib_LTLIBRARIES = \ $(DO_W32_NSP) \ libgnunetgns.la if HAVE_MHD if HAVE_GNUTLS if HAVE_LIBGNURL DO_PROXY=gnunet-gns-proxy endif endif endif libexec_PROGRAMS = \ gnunet-service-gns \ $(DO_W32_HELPER) \ gnunet-dns2gns \ $(DO_PROXY) bin_PROGRAMS = \ $(DO_W32_NSPTOOLS) \ $(DO_NONPOSIX_GNSIMPORT) \ gnunet-gns if HAVE_MHD if LINUX bin_PROGRAMS += gnunet-bcd endif endif bin_SCRIPTS = gnunet-gns-proxy-setup-ca plugin_LTLIBRARIES = \ libgnunet_plugin_block_gns.la \ libgnunet_plugin_gnsrecord_gns.la libgnunet_plugin_gnsrecord_gns_la_SOURCES = \ plugin_gnsrecord_gns.c libgnunet_plugin_gnsrecord_gns_la_LIBADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_gnsrecord_gns_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) gnunet_gns_SOURCES = \ gnunet-gns.c gnunet_gns_LDADD = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_gns_DEPENDENCIES = \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetgns.la gnunet_bcd_SOURCES = \ gnunet-bcd.c gnunet_bcd_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) -lmicrohttpd gnunet_bcd_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_dns2gns_SOURCES = \ gnunet-dns2gns.c gnunet_dns2gns_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(GN_LIBINTL) gnunet_dns2gns_DEPENDENCIES = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ libgnunetgns.la gnunet_gns_proxy_SOURCES = \ gnunet-gns-proxy.c gnunet_gns_proxy_LDADD = -lmicrohttpd -lgnurl -lgnutls \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) if HAVE_GNUTLS_DANE gnunet_gns_proxy_LDADD += -lgnutls-dane endif gnunet_gns_proxy_DEPENDENCIES = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetgns.la gnunet_gns_helper_service_w32_SOURCES = \ gnunet-gns-helper-service-w32.c gnunet_gns_helper_service_w32_LDADD = \ $(top_builddir)/src/gns/libgnunetgns.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_gns_helper_service_w32_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ libgnunetgns.la gnunet_gns_import_SOURCES = \ gnunet-gns-import.c gnunet_gns_import_LDADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_gns_import_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/identity/libgnunetidentity.la w32nsp_install_SOURCES = \ w32nsp-install.c w32nsp_install_LDADD = -lws2_32 w32nsp_uninstall_SOURCES = \ w32nsp-uninstall.c w32nsp_uninstall_LDADD = -lws2_32 w32nsp_resolve_SOURCES = \ w32nsp-resolve.c w32nsp_resolve_LDADD = -lws2_32 gnunet_service_gns_SOURCES = \ gnunet-service-gns.c \ gnunet-service-gns_resolver.c gnunet-service-gns_resolver.h \ gnunet-service-gns_shorten.c gnunet-service-gns_shorten.h \ gnunet-service-gns_interceptor.c gnunet-service-gns_interceptor.h gnunet_service_gns_LDADD = \ -lm \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(USE_VPN) \ $(GN_LIBINTL) gnunet_service_gns_DEPENDENCIES = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(USE_VPN) libw32nsp_la_SOURCES = \ w32nsp.c libw32nsp_la_LIBADD = \ -lole32 -lws2_32 libw32nsp_la_LDFLAGS = \ -export-symbols $(top_srcdir)/src/gns/w32nsp.def \ -no-undefined -static-libgcc libgnunetgns_la_SOURCES = \ gns_api.c gns.h libgnunetgns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la libgnunetgns_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) libgnunetgns_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la libgnunet_plugin_block_gns_la_SOURCES = \ plugin_block_gns.c libgnunet_plugin_block_gns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la libgnunet_plugin_block_gns_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_gns_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la check_SCRIPTS = \ test_gns_lookup.sh \ test_gns_ipv6_lookup.sh\ test_gns_txt_lookup.sh\ test_gns_mx_lookup.sh \ test_gns_gns2dns_lookup.sh \ test_gns_dht_lookup.sh\ test_gns_delegated_lookup.sh \ test_gns_nick_shorten.sh\ test_gns_plus_lookup.sh\ test_gns_zkey_lookup.sh\ test_gns_rel_expiration.sh\ test_gns_soa_lookup.sh\ test_gns_revocation.sh\ test_gns_cname_lookup.sh if ENABLE_TEST_RUN if HAVE_SQLITE AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_SCRIPTS) endif endif gnunet-0.10.1/src/gns/test_gns_revocation.sh0000755000175000017500000000307712261236532016017 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT which timeout &> /dev/null && DO_TIMEOUT="timeout 5" LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf /tmp/test-gnunet-gns-peer-1/ TEST_IP="127.0.0.1" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C delegatedego -c test_gns_lookup.conf DELEGATED_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep delegatedego | awk '{print $3}') gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -p -z delegatedego -a -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.b.gnu -t A -c test_gns_lookup.conf` gnunet-revocation -R delegatedego -p -c test_gns_lookup.conf RES_IP_REV=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.b.gnu -t A -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -z delegatedego -d -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_IP" != "$TEST_IP" ] then echo "Failed to resolve to proper IP, got $RES_IP." exit 1 fi if [ "x$RES_IP_REV" == "x" ] then exit 0 else echo "Failed to revoke zone, got $RES_IP_REV." exit 1 fi gnunet-0.10.1/src/gns/gnunet-gns.c0000644000175000017500000002755412305564547013651 00000000000000/* This file is part of GNUnet. (C) 2012-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnunet-gns.c * @brief command line tool to access distributed GNS * @author Christian Grothoff */ #include "platform.h" #include #include #include #include #include #include /** * Configuration we are using. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to GNS service. */ static struct GNUNET_GNS_Handle *gns; /** * Desired timeout for the lookup (default is no timeout). */ static struct GNUNET_TIME_Relative timeout; /** * GNS name to lookup. (-u option) */ static char *lookup_name; /** * record type to look up (-t option) */ static char *lookup_type; /** * Identity of the zone to use for the lookup (-z option) */ static char *zone_ego_name; /** * Public key of the zone to use for the lookup (-p option) */ static char *public_key; /** * Set to GNUNET_GNS_LO_LOCAL_MASTER if we are looking up in the master zone. */ static enum GNUNET_GNS_LocalOptions local_options; /** * raw output */ static int raw; /** * Requested record type. */ static int rtype; /** * Handle to lookup request */ static struct GNUNET_GNS_LookupRequest *lookup_request; /** * Lookup an ego with the identity service. */ static struct GNUNET_IDENTITY_EgoLookup *el; /** * Handle for identity service. */ static struct GNUNET_IDENTITY_Handle *identity; /** * Active operation on identity service. */ static struct GNUNET_IDENTITY_Operation *id_op; /** * Task run on shutdown. Cleans up everything. * * @param cls unused * @param tc scheduler context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != el) { GNUNET_IDENTITY_ego_lookup_cancel (el); el = NULL; } if (NULL != id_op) { GNUNET_IDENTITY_cancel (id_op); id_op = NULL; } if (NULL != lookup_request) { GNUNET_GNS_lookup_cancel (lookup_request); lookup_request = NULL; } if (NULL != identity) { GNUNET_IDENTITY_disconnect (identity); identity = NULL; } if (NULL != gns) { GNUNET_GNS_disconnect (gns); gns = NULL; } } /** * Function called with the result of a GNS lookup. * * @param cls the 'const char *' name that was resolved * @param rd_count number of records returned * @param rd array of @a rd_count records with the results */ static void process_lookup_result (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { const char *name = cls; uint32_t i; const char *typename; char* string_val; lookup_request = NULL; if (!raw) { if (0 == rd_count) printf ("No results.\n"); else printf ("%s:\n", name); } for (i=0; i 4) && (0 == strcmp (".zkey", &lookup_name[strlen (lookup_name) - 4])) ) { /* no zone required, use 'anonymous' zone */ GNUNET_CRYPTO_ecdsa_key_get_public (GNUNET_CRYPTO_ecdsa_key_get_anonymous (), &pkey); lookup_with_public_key (&pkey); } else { GNUNET_break (NULL == id_op); id_op = GNUNET_IDENTITY_get (identity, "gns-master", &identity_master_cb, NULL); GNUNET_assert (NULL != id_op); } } /** * The main function for gnunet-gns. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'u', "lookup", "NAME", gettext_noop ("Lookup a record for the given name"), 1, &GNUNET_GETOPT_set_string, &lookup_name}, {'t', "type", "TYPE", gettext_noop ("Specify the type of the record to lookup"), 1, &GNUNET_GETOPT_set_string, &lookup_type}, { 'T', "timeout", "DELAY", gettext_noop ("Specify timeout for the lookup"), 1, &GNUNET_GETOPT_set_relative_time, &timeout }, {'r', "raw", NULL, gettext_noop ("No unneeded output"), 0, &GNUNET_GETOPT_set_one, &raw}, {'p', "public-key", "PKEY", gettext_noop ("Specify the public key of the zone to lookup the record in"), 1, &GNUNET_GETOPT_set_string, &public_key}, {'z', "zone", "NAME", gettext_noop ("Specify the name of the ego of the zone to lookup the record in"), 1, &GNUNET_GETOPT_set_string, &zone_ego_name}, GNUNET_GETOPT_OPTION_END }; int ret; timeout = GNUNET_TIME_UNIT_FOREVER_REL; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; GNUNET_log_setup ("gnunet-gns", "WARNING", NULL); ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-gns", _("GNUnet GNS resolver tool"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-gns.c */ gnunet-0.10.1/src/gns/gnunet-service-gns_interceptor.h0000644000175000017500000000265012225777503017717 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gnunet-service-gns_interceptor.h * @brief GNUnet GNS service * @author Martin Schanzenbach */ #ifndef GNUNET_GNS_INTERCEPTOR_H #define GNUNET_GNS_INTERCEPTOR_H #include "gnunet_util_lib.h" /** * Initialize DNS interceptor * * @param gnu_zone the zone we start lookups in * @param c the configuration * @return GNUNET_YES on success GNUNET_SYSERR on error */ int GNS_interceptor_init (const struct GNUNET_CRYPTO_EcdsaPublicKey *gnu_zone, const struct GNUNET_CONFIGURATION_Handle *c); /** * Stops the interceptor */ void GNS_interceptor_done (void); #endif gnunet-0.10.1/src/gns/test_gns_txt_lookup.sh0000755000175000017500000000207212261236532016050 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf /tmp/test-gnunet-gns-peer-1/ which timeout &> /dev/null && DO_TIMEOUT="timeout 30" TEST_TXT="GNS powered txt record data" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n testtxt -t TXT -V "$TEST_TXT" -e never -c test_gns_lookup.conf RES_TXT=`$DO_TIMEOUT gnunet-gns --raw -z testego -u testtxt.gnu -t TXT -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n testtxt -t TXT -V "$TEST_TXT" -e never -c test_gns_lookup.conf gnunet-identity -D testego -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_TXT" == "$TEST_TXT" ] then exit 0 else echo "Failed to resolve to proper TXT, got '$RES_TXT'." exit 1 fi gnunet-0.10.1/src/gns/gnunet-bcd.c0000644000175000017500000003705512251345306013575 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gnunet-bcd.c * @author Christian Grothoff * @brief HTTP server to create GNS business cards */ #include "platform.h" #include #include "gnunet_util_lib.h" /** * Error page to display if submitted GNS key is invalid. */ #define INVALID_GNSKEY "ErrorInvalid GNS public key given." /** * Error page to display on 404. */ #define NOT_FOUND "Error404 not found" /** * Handle to the HTTP server as provided by libmicrohttpd */ static struct MHD_Daemon *daemon_handle; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Our primary task for the HTTPD. */ static GNUNET_SCHEDULER_TaskIdentifier http_task; /** * Our main website. */ static struct MHD_Response *main_response; /** * Error: invalid gns key. */ static struct MHD_Response *invalid_gnskey_response; /** * Error: 404 */ static struct MHD_Response *not_found_response; /** * Absolute name of the 'gns-bcd.tex' file. */ static char *resfile; /** * Port number. */ static unsigned int port = 8888; struct Entry { const char *formname; const char *texname; }; /** * Main request handler. */ static int access_handler_callback (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t * upload_data_size, void **con_cls) { static int dummy; static const struct Entry map[] = { { "prefix", "prefix" }, { "name", "name" }, { "suffix", "suffix" }, { "street", "street" }, { "city", "city" }, { "phone", "phone" }, { "fax", "fax" }, { "email", "email"}, { "homepage", "homepage" }, { "orga", "orga"}, { "departmenti18n", "departmentde"}, { "departmenten", "departmenten"}, { "subdepartmenti18n", "subdepartmentde"}, { "subdepartmenten", "subdepartmenten"}, { "jobtitlei18n", "jobtitlegerman"}, { "jobtitleen", "jobtitleenglish"}, { "subdepartmenten", "subdepartmenten"}, { NULL, NULL } }; if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Refusing `%s' request to HTTP server\n"), method); return MHD_NO; } if (NULL == *con_cls) { (*con_cls) = &dummy; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE reply\n"); return MHD_YES; /* send 100 continue */ } if (0 == strcasecmp (url, "/")) return MHD_queue_response (connection, MHD_HTTP_OK, main_response); if (0 == strcasecmp (url, "/submit.pdf")) { unsigned int i; char *p; char *tmp; char *deffile; struct GNUNET_CRYPTO_EcdsaPublicKey pub; size_t slen; FILE *f; struct stat st; struct MHD_Response *response; int fd; int ret; const char *gpg_fp = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gpgfingerprint"); const char *gns_nick = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnsnick"); const char *gnskey = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "gnskey"); if ( (NULL == gnskey) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (gnskey, strlen (gnskey), &pub))) { return MHD_queue_response (connection, MHD_HTTP_OK, invalid_gnskey_response); } tmp = GNUNET_DISK_mkdtemp (gnskey); if (NULL == tmp) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mktemp", gnskey); return MHD_NO; } GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "def.tex"); f = FOPEN (deffile, "w"); if (NULL == f) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); GNUNET_free (deffile); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } for (i=0; NULL != map[i].formname; i++) { const char *val = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, map[i].formname); if (NULL != val) FPRINTF (f, "\\def\\%s{%s}\n", map[i].texname, val); else FPRINTF (f, "\\def\\%s{}\n", map[i].texname); } if (NULL != gpg_fp) { char *gpg1; char *gpg2; slen = strlen (gpg_fp); gpg1 = GNUNET_strndup (gpg_fp, slen / 2); gpg2 = GNUNET_strdup (&gpg_fp[slen / 2]); FPRINTF (f, "\\def\\gpglineone{%s}\n\\def\\gpglinetwo{%s}\n", gpg1, gpg2); GNUNET_free (gpg2); GNUNET_free (gpg1); } FPRINTF (f, "\\def\\gns{%s/%s}\n", gnskey, (NULL == gns_nick) ? "" : gns_nick); FCLOSE (f); GNUNET_asprintf (&p, "cd %s; cp %s gns-bcd.tex | pdflatex --enable-write18 gns-bcd.tex > /dev/null 2> /dev/null", tmp, resfile); GNUNET_free (deffile); ret = system (p); if (WIFSIGNALED (ret) || (0 != WEXITSTATUS(ret))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "system", p); GNUNET_asprintf (&deffile, "%s%s%s", tmp, DIR_SEPARATOR_STR, "gns-bcd.pdf"); fd = OPEN (deffile, O_RDONLY); if (-1 == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", deffile); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } GNUNET_break (0 == STAT (deffile, &st)); if (NULL == (response = MHD_create_response_from_fd ((size_t) st.st_size, fd))) { GNUNET_break (0); GNUNET_break (0 == CLOSE (fd)); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return MHD_NO; } (void) MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/pdf"); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); GNUNET_free (deffile); GNUNET_free (p); GNUNET_DISK_directory_remove (tmp); GNUNET_free (tmp); return ret; } return MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, not_found_response); } /** * Function that queries MHD's select sets and * starts the task waiting for them. */ static GNUNET_SCHEDULER_TaskIdentifier prepare_daemon (struct MHD_Daemon *daemon_handle); /** * Call MHD to process pending requests and then go back * and schedule the next run. */ static void run_daemon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MHD_Daemon *daemon_handle = cls; http_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_assert (MHD_YES == MHD_run (daemon_handle)); http_task = prepare_daemon (daemon_handle); } /** * Function that queries MHD's select sets and * starts the task waiting for them. */ static GNUNET_SCHEDULER_TaskIdentifier prepare_daemon (struct MHD_Daemon *daemon_handle) { GNUNET_SCHEDULER_TaskIdentifier ret; fd_set rs; fd_set ws; fd_set es; struct GNUNET_NETWORK_FDSet *wrs; struct GNUNET_NETWORK_FDSet *wws; int max; MHD_UNSIGNED_LONG_LONG timeout; int haveto; struct GNUNET_TIME_Relative tv; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); wrs = GNUNET_NETWORK_fdset_create (); wws = GNUNET_NETWORK_fdset_create (); max = -1; GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max)); haveto = MHD_get_timeout (daemon_handle, &timeout); if (haveto == MHD_YES) tv.rel_value_us = (uint64_t) timeout * 1000LL; else tv = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, tv, wrs, wws, &run_daemon, daemon_handle); GNUNET_NETWORK_fdset_destroy (wrs); GNUNET_NETWORK_fdset_destroy (wws); return ret; } /** * Start server offering our hostlist. * * @return #GNUNET_OK on success */ static int server_start () { if ((0 == port) || (port > UINT16_MAX)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Invalid port number %llu. Exiting.\n"), port); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Businesscard HTTP server starts on %llu\n"), port); daemon_handle = MHD_start_daemon (MHD_USE_DUAL_STACK | MHD_USE_DEBUG, (uint16_t) port, NULL /* accept_policy_callback */, NULL, &access_handler_callback, NULL, MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 512, MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 2, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 60, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (16 * 1024), MHD_OPTION_END); if (NULL == daemon_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not start businesscard HTTP server on port %u\n"), (unsigned short) port); return GNUNET_SYSERR; } http_task = prepare_daemon (daemon_handle); return GNUNET_OK; } /** * Stop HTTP server. */ static void server_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "HTTP server shutdown\n"); if (GNUNET_SCHEDULER_NO_TASK != http_task) { GNUNET_SCHEDULER_cancel (http_task); http_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != daemon_handle) { MHD_stop_daemon (daemon_handle); daemon_handle = NULL; } if (NULL != main_response) { MHD_destroy_response (main_response); main_response = NULL; } if (NULL != invalid_gnskey_response) { MHD_destroy_response (invalid_gnskey_response); invalid_gnskey_response = NULL; } if (NULL != not_found_response) { MHD_destroy_response (not_found_response); not_found_response = NULL; } if (NULL != resfile) { GNUNET_free (resfile); resfile = NULL; } } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct stat st; char *dir; char *fn; int fd; cfg = c; dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); GNUNET_assert (NULL != dir); GNUNET_asprintf (&fn, "%s%s%s", dir, DIR_SEPARATOR_STR, "gns-bcd.html"); GNUNET_asprintf (&resfile, "%s%s%s", dir, DIR_SEPARATOR_STR, "gns-bcd.tex"); GNUNET_free (dir); fd = OPEN (fn, O_RDONLY); if (-1 == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); GNUNET_free (fn); return; } if (0 != STAT (fn, &st)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); GNUNET_free (fn); CLOSE (fd); return; } GNUNET_free (fn); if (NULL == (main_response = MHD_create_response_from_fd ((size_t) st.st_size, fd))) { GNUNET_break (0); GNUNET_break (0 == CLOSE (fd)); return; } (void) MHD_add_response_header (main_response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); invalid_gnskey_response = MHD_create_response_from_buffer (strlen (INVALID_GNSKEY), INVALID_GNSKEY, MHD_RESPMEM_PERSISTENT); (void) MHD_add_response_header (invalid_gnskey_response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); not_found_response = MHD_create_response_from_buffer (strlen (NOT_FOUND), NOT_FOUND, MHD_RESPMEM_PERSISTENT); (void) MHD_add_response_header (not_found_response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); if (GNUNET_OK != server_start ()) return; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &server_stop, NULL); } /** * The main function for gnunet-gns. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'p', "port", "PORT", gettext_noop ("Run HTTP serve on port PORT (default is 8888)"), 1, &GNUNET_GETOPT_set_uint, &port}, GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; GNUNET_log_setup ("gnunet-bcd", "WARNING", NULL); ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-bcd", _("GNUnet HTTP server to create business cards"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-bcd.c */ gnunet-0.10.1/src/gns/w32nsp-uninstall.c0000644000175000017500000000120212253574266014706 00000000000000#define INITGUID #include #include #include #include "gnunet_w32nsp_lib.h" #include int main (int argc, char **argv) { int ret; GUID id = GNUNET_NAMESPACE_PROVIDER_DNS; WSADATA wsd; if (WSAStartup (MAKEWORD (2,2), &wsd) != 0) { fprintf (stderr, "WSAStartup () failed: %lu\n", GetLastError ()); return 5; } ret = WSCUnInstallNameSpace (&id); if (ret == NO_ERROR) { fprintf (stderr, "Uninstalled GNUnet DNS provider\n"); WSACleanup (); return 0; } fprintf (stderr, "WSCUnInstallNameSpace () failed: %lu\n", GetLastError ()); WSACleanup (); return 1; }gnunet-0.10.1/src/gns/gnunet-gns-import.c0000644000175000017500000003354412320530515015136 00000000000000/* This file is part of GNUnet. (C) 2012-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnunet-gns.c * @brief binary version of gnunet-gns-import.sh * (for OSes that have no POSIX shell). * @author LRN */ #include "platform.h" #include #include #include #include /** * Configuration we are using. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to IDENTITY service. */ static struct GNUNET_IDENTITY_Handle *sh; /** * Zone iterator for master zone */ struct GNUNET_NAMESTORE_ZoneIterator *list_it; /** * Handle to the namestore. */ static struct GNUNET_NAMESTORE_Handle *ns; /** * String version of PKEY for master-zone. */ static char *master_zone_pkey; /** * Binary version of PKEY for master-zone. */ static struct GNUNET_CRYPTO_EcdsaPrivateKey master_pk; /** * String version of PKEY for short-zone. */ static char *short_zone_pkey; /** * String version of PKEY for private-zone. */ static char *private_zone_pkey; /** * String version of PKEY for pin-zone. */ static char *pin_zone_pkey = "72QC35CO20UJN1E91KPJFNT9TG4CLKAPB4VK9S3Q758S9MLBRKOG"; /** * Set to GNUNET_YES if private record was found; */ static int found_private_rec = GNUNET_NO; /** * Set to GNUNET_YES if short record was found; */ static int found_short_rec = GNUNET_NO; /** * Set to GNUNET_YES if pin record was found; */ static int found_pin_rec = GNUNET_NO; /** * Exit code. */ static int ret; static int run_process_and_wait (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, enum GNUNET_OS_ProcessStatusType *st, unsigned long *code, const char *filename, ...) { static struct GNUNET_OS_Process *p; int arglen; char *arg; char *args; char *argp; va_list ap, apc1, apc2; va_start (ap, filename); va_copy (apc1, ap); va_copy (apc2, ap); arglen = 0; while (NULL != (arg = va_arg (apc1, char *))) arglen += strlen (arg) + 1; va_end (apc1); args = argp = GNUNET_malloc (arglen); while (NULL != (arg = va_arg (apc2, char *))) { strcpy (argp, arg); argp += strlen (arg); *argp = ' '; argp += 1; } va_end (apc2); if (arglen > 0) argp[-1] = '\0'; p = GNUNET_OS_start_process_va (pipe_control, std_inheritance, pipe_stdin, pipe_stdout, NULL, filename, ap); va_end (ap); if (NULL == p) { ret = 3; fprintf (stderr, "Failed to run `%s'\n", args); GNUNET_free (args); return 1; } if (GNUNET_OK != GNUNET_OS_process_wait (p)) { ret = 4; fprintf (stderr, "Failed to wait for `%s'\n", args); GNUNET_free (args); return 1; } switch (GNUNET_OS_process_status (p, st, code)) { case GNUNET_OK: break; case GNUNET_NO: ret = 5; fprintf (stderr, "`%s' is still running\n", args); GNUNET_free (args); return 1; default: case GNUNET_SYSERR: ret = 6; fprintf (stderr, "Failed to check the status of `%s'\n", args); GNUNET_free (args); return 1; } #ifdef WINDOWS if (GNUNET_OS_PROCESS_EXITED != *st || 0 != *code) { ret = 7; fprintf (stderr, "`%s' did not end correctly (%d, %d)\n", args, *st, *code); return 1; } #endif return 0; } static void check_pkey (unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd, char *pk, int *found_rec) { int i; for (i = 0; i < rd_len; i++) { char *s; if (GNUNET_GNSRECORD_TYPE_PKEY != rd[i].record_type || rd[i].data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) continue; s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type, rd[i].data, rd[i].data_size); if (NULL == s) continue; if (0 == strcmp (s, pk)) *found_rec = GNUNET_YES; GNUNET_free (s); } } /** * Process a record that was stored in the namestore. * * @param cls closure * @param zone_key private key of the zone * @param rname name that is being mapped (at most 255 characters long) * @param rd_len number of entries in @a rd array * @param rd array of records with data to store */ static void zone_iterator (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *rname, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { if (NULL != rname) { if (0 == strcmp (rname, "private")) check_pkey (rd_len, rd, private_zone_pkey, &found_private_rec); else if (0 == strcmp (rname, "short")) check_pkey (rd_len, rd, short_zone_pkey, &found_short_rec); else if (0 == strcmp (rname, "pin")) check_pkey (rd_len, rd, pin_zone_pkey, &found_pin_rec); } if (NULL == rname && 0 == rd_len && NULL == rd) { enum GNUNET_OS_ProcessStatusType st; unsigned long code; if (!found_private_rec) { if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-namestore", "gnunet-namestore", "-z", "master-zone", "-a", "-e", "never", "-n", "private", "-p", "-t", "PKEY", "-V", private_zone_pkey, NULL)) { ret = 8; return; } } if (!found_short_rec) { if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-namestore", "gnunet-namestore", "-z", "master-zone", "-a", "-e", "never", "-n", "short", "-p", "-t", "PKEY", "-V", short_zone_pkey, NULL)) { ret = 9; return; } } if (!found_pin_rec) { if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-namestore", "gnunet-namestore", "-z", "master-zone", "-a", "-e", "never", "-n", "pin", "-p", "-t", "PKEY", "-V", pin_zone_pkey, NULL)) { ret = 10; return; } } list_it = NULL; GNUNET_SCHEDULER_shutdown (); return; } GNUNET_NAMESTORE_zone_iterator_next (list_it); } /** * Get master-zone, short-zone and private-zone keys. * * This function is initially called for all egos and then again * whenever a ego's identifier changes or if it is deleted. At the * end of the initial pass over all egos, the function is once called * with 'NULL' for 'ego'. That does NOT mean that the callback won't * be invoked in the future or that there was an error. * * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', * this function is only called ONCE, and 'NULL' being passed in * 'ego' does indicate an error (i.e. name is taken or no default * value is known). If 'ego' is non-NULL and if '*ctx' * is set in those callbacks, the value WILL be passed to a subsequent * call to the identity callback of 'GNUNET_IDENTITY_connect' (if * that one was not NULL). * * When an identity is renamed, this function is called with the * (known) ego but the NEW identifier. * * When an identity is deleted, this function is called with the * (known) ego and "NULL" for the 'identifier'. In this case, * the 'ego' is henceforth invalid (and the 'ctx' should also be * cleaned up). * * @param cls closure * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param identifier identifier assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void get_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier) { static struct GNUNET_CRYPTO_EcdsaPublicKey pk; if (NULL == ego) { if (NULL == master_zone_pkey || NULL == short_zone_pkey || NULL == private_zone_pkey) { ret = 11; GNUNET_SCHEDULER_shutdown (); return; } list_it = GNUNET_NAMESTORE_zone_iteration_start (ns, &master_pk, &zone_iterator, NULL); if (NULL == list_it) { ret = 12; GNUNET_SCHEDULER_shutdown (); } return; } GNUNET_IDENTITY_ego_get_public_key (ego, &pk); if (NULL != identifier) { if (NULL == master_zone_pkey && 0 == strcmp ("master-zone", identifier)) { master_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); master_pk = *GNUNET_IDENTITY_ego_get_private_key (ego); } else if (NULL == short_zone_pkey && 0 == strcmp ("short-zone", identifier)) short_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); else if (NULL == private_zone_pkey && 0 == strcmp ("private-zone", identifier)) private_zone_pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); } } /** * Task run on shutdown. * * @param cls NULL * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_free_non_null (master_zone_pkey); master_zone_pkey = NULL; GNUNET_free_non_null (short_zone_pkey); short_zone_pkey = NULL; GNUNET_free_non_null (private_zone_pkey); private_zone_pkey = NULL; if (NULL != list_it) { GNUNET_NAMESTORE_zone_iteration_stop (list_it); list_it = NULL; } if (NULL != ns) { GNUNET_NAMESTORE_disconnect (ns); ns = NULL; } if (NULL != sh) { GNUNET_IDENTITY_disconnect (sh); sh = NULL; } } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { enum GNUNET_OS_ProcessStatusType st; unsigned long code; cfg = c; if (0 != run_process_and_wait (GNUNET_NO, 0, NULL, NULL, &st, &code, "gnunet-arm", "gnunet-arm", "-I", NULL)) { if (7 == ret) fprintf (stderr, "GNUnet is not running, please start GNUnet before running import\n"); return; } if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-C", "master-zone", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-C", "short-zone", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-C", "private-zone", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-C", "sks-zone", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-e", "short-zone", "-s", "gns-short", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-e", "master-zone", "-s", "gns-master", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-e", "master-zone", "-s", "namestore", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-e", "short-zone", "-s", "gns-proxy", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-e", "private-zone", "-s", "gns-private", NULL)) return; if (0 != run_process_and_wait (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, &st, &code, "gnunet-identity", "gnunet-identity", "-e", "sks-zone", "-s", "fs-sks", NULL)) return; ns = GNUNET_NAMESTORE_connect (cfg); sh = GNUNET_IDENTITY_connect (cfg, &get_ego, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for gnunet-gns. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int r; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; GNUNET_log_setup ("gnunet-gns-import", "WARNING", NULL); ret = 0; r = GNUNET_PROGRAM_run (argc, argv, "gnunet-gns-import", _("This program will import some GNS authorities into your GNS namestore."), options, &run, NULL); GNUNET_free ((void*) argv); return GNUNET_OK == r ? ret : 1; } /* end of gnunet-gns-import.c */ gnunet-0.10.1/src/gns/test_gns_dht_lookup.sh0000755000175000017500000000252312261236532016011 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT which timeout &> /dev/null && DO_TIMEOUT="timeout 30" LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi TEST_IP="127.0.0.1" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C delegatedego -c test_gns_lookup.conf DELEGATED_PKEY=$(gnunet-identity -d -c test_gns_lookup.conf | grep delegatedego | awk '{print $3}') gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-namestore -p -z delegatedego -a -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf gnunet-arm -i gns -c test_gns_lookup.conf sleep 0.5 gnunet-namestore -z delegatedego -d -n www -t A -V $TEST_IP -e never -c test_gns_lookup.conf RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.b.gnu -t A -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n b -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_IP" == "$TEST_IP" ] then exit 0 else echo "Failed to resolve to proper IP, got $RES_IP." exit 1 fi gnunet-0.10.1/src/gns/plugin_block_gns.c0000644000175000017500000001343312227705277015072 00000000000000/* This file is part of GNUnet (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/plugin_block_gns.c * @brief blocks used for GNS records * @author Martin Schanzenbach */ #include "platform.h" #include "gnunet_block_plugin.h" #include "gnunet_namestore_service.h" #include "gnunet_signatures.h" /** * Number of bits we set per entry in the bloomfilter. * Do not change! -from fs */ #define BLOOMFILTER_K 16 /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would * be done with the "get_key" function. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with @a query; possibly updated (!) * @param bf_mutator mutation value for @a bf * @param xquery extrended query data (can be NULL, depending on @a type) * @param xquery_size number of bytes in @a xquery * @param reply_block response to validate * @param reply_block_size number of bytes in @a reply_block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult block_plugin_gns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { const struct GNUNET_GNSRECORD_Block *block; struct GNUNET_HashCode h; struct GNUNET_HashCode chash; struct GNUNET_HashCode mhash; if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD) return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; if (NULL == reply_block) { if (0 != xquery_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; } /* this is a reply */ if (reply_block_size < sizeof (struct GNUNET_GNSRECORD_Block)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } block = reply_block; if (ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) != reply_block_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } GNUNET_CRYPTO_hash (&block->derived_key, sizeof (block->derived_key), &h); if (0 != memcmp (&h, query, sizeof (struct GNUNET_HashCode))) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (GNUNET_OK != GNUNET_GNSRECORD_block_verify (block)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (NULL != bf) { GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); if (NULL != *bf) { if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test(*bf, &mhash)) return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; } else { *bf = GNUNET_CONTAINER_bloomfilter_init(NULL, 8, BLOOMFILTER_K); } GNUNET_CONTAINER_bloomfilter_add(*bf, &mhash); } return GNUNET_BLOCK_EVALUATION_OK_MORE; } /** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param reply_block block to get the key for * @param reply_block_size number of bytes in @a reply_block * @param key set to the key (query) for the given block * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int block_plugin_gns_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *reply_block, size_t reply_block_size, struct GNUNET_HashCode *key) { const struct GNUNET_GNSRECORD_Block *block; if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD) return GNUNET_SYSERR; if (reply_block_size < sizeof (struct GNUNET_GNSRECORD_Block)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } block = reply_block; GNUNET_CRYPTO_hash (&block->derived_key, sizeof (block->derived_key), key); return GNUNET_OK; } /** * Entry point for the plugin. */ void * libgnunet_plugin_block_gns_init (void *cls) { static enum GNUNET_BLOCK_Type types[] = { GNUNET_BLOCK_TYPE_GNS_NAMERECORD, GNUNET_BLOCK_TYPE_ANY /* end of list */ }; struct GNUNET_BLOCK_PluginFunctions *api; api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_gns_evaluate; api->get_key = &block_plugin_gns_get_key; api->types = types; return api; } /** * Exit point from the plugin. */ void * libgnunet_plugin_block_gns_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_block_gns.c */ gnunet-0.10.1/src/gns/test_gns_mx_lookup.sh0000755000175000017500000000201612261236532015653 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf /tmp/test-gnunet-gns-peer-1/ which timeout &> /dev/null && DO_TIMEOUT="timeout 5" TEST_MX="5,mail.gnu" gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n www -t MX -V "$TEST_MX" -e never -c test_gns_lookup.conf RES_MX=`$DO_TIMEOUT gnunet-gns --raw -z testego -u www.gnu -t MX -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n www -t MX -V "$TEST_MX" -e never -c test_gns_lookup.conf gnunet-identity -D testego -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "$RES_MX" == "$TEST_MX" ] then exit 0 else echo "FAIL: did not get proper IP, got $RES_MX." exit 1 fi gnunet-0.10.1/src/gns/test_gns_defaults.conf0000644000175000017500000000111312245716446015763 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-gns-testing/ [namestore-sqlite] FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db [namecache-sqlite] FILENAME=$GNUNET_TEST_HOME/namecache/namecache.db [identity] # Directory where we store information about our egos EGODIR = $GNUNET_TEST_HOME/identity/egos/ [dhtcache] DATABASE = heap [transport] PLUGINS = tcp [transport-tcp] BINDTO = 127.0.0.1 [dns] AUTOSTART = NO [nse] AUTOSTART = NO [mesh] AUTOSTART = NO [datastore] AUTOSTART = NO [fs] AUTOSTART = NO [dv] AUTOSTART = NO [vpn] AUTOSTART = NO [consensus] AUTOSTART = NO gnunet-0.10.1/src/gns/plugin_gnsrecord_gns.c0000644000175000017500000002157212307322113015750 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/plugin_gnsrecord_gns.c * @brief gnsrecord plugin to provide the API for fundamental GNS records * This includes the VPN record because GNS resolution * is expected to understand VPN records and (if needed) * map the result to A/AAAA. * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_gnsrecord_plugin.h" /** * Convert the 'value' of a record to a string. * * @param cls closure, unused * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in @a data * @return NULL on error, otherwise human-readable representation of the value */ static char * gns_value_to_string (void *cls, uint32_t type, const void *data, size_t data_size) { const char *cdata; switch (type) { case GNUNET_GNSRECORD_TYPE_PKEY: if (data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) return NULL; return GNUNET_CRYPTO_ecdsa_public_key_to_string (data); case GNUNET_GNSRECORD_TYPE_NICK: return GNUNET_strndup (data, data_size); case GNUNET_GNSRECORD_TYPE_LEHO: return GNUNET_strndup (data, data_size); case GNUNET_GNSRECORD_TYPE_GNS2DNS: { char *ns; char *ip; size_t off; char *nstr; off = 0; ns = GNUNET_DNSPARSER_parse_name (data, data_size, &off); ip = GNUNET_DNSPARSER_parse_name (data, data_size, &off); if ( (NULL == ns) || (NULL == ip) || (off != data_size) ) { GNUNET_break_op (0); GNUNET_free_non_null (ns); GNUNET_free_non_null (ip); return NULL; } GNUNET_asprintf (&nstr, "%s@%s", ns, ip); GNUNET_free_non_null (ns); GNUNET_free_non_null (ip); return nstr; } case GNUNET_GNSRECORD_TYPE_VPN: { const struct GNUNET_TUN_GnsVpnRecord *vpn; char* vpn_str; cdata = data; if ( (data_size <= sizeof (struct GNUNET_TUN_GnsVpnRecord)) || ('\0' != cdata[data_size - 1]) ) return NULL; /* malformed */ vpn = data; GNUNET_asprintf (&vpn_str, "%u %s %s", (unsigned int) ntohs (vpn->proto), (const char*) GNUNET_i2s_full (&vpn->peer), (const char*) &vpn[1]); return vpn_str; } default: return NULL; } } /** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param cls closure, unused * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ static int gns_string_to_value (void *cls, uint32_t type, const char *s, void **data, size_t *data_size) { struct GNUNET_CRYPTO_EcdsaPublicKey pkey; struct GNUNET_TUN_GnsVpnRecord *vpn; char s_peer[103 + 1]; char s_serv[253 + 1]; unsigned int proto; if (NULL == s) return GNUNET_SYSERR; switch (type) { case GNUNET_GNSRECORD_TYPE_PKEY: if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse PKEY record `%s'\n"), s); return GNUNET_SYSERR; } *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); memcpy (*data, &pkey, sizeof (pkey)); *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_NICK: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_LEHO: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_GNSRECORD_TYPE_GNS2DNS: { char nsbuf[514]; char *cpy; char *at; size_t off; cpy = GNUNET_strdup (s); at = strchr (cpy, '@'); if (NULL == at) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse GNS2DNS record `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } *at = '\0'; at++; off = 0; if ( (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, cpy)) || (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, at)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize GNS2DNS record with value `%s'\n"), s); GNUNET_free (cpy); return GNUNET_SYSERR; } GNUNET_free (cpy); *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, nsbuf, off); return GNUNET_OK; } case GNUNET_GNSRECORD_TYPE_VPN: if (3 != SSCANF (s,"%u %103s %253s", &proto, s_peer, s_serv)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse VPN record string `%s'\n"), s); return GNUNET_SYSERR; } *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1; *data = vpn = GNUNET_malloc (*data_size); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer, strlen (s_peer), &vpn->peer.public_key)) { GNUNET_free (vpn); *data_size = 0; return GNUNET_SYSERR; } vpn->proto = htons ((uint16_t) proto); strcpy ((char*)&vpn[1], s_serv); return GNUNET_OK; default: return GNUNET_SYSERR; } } /** * Mapping of record type numbers to human-readable * record type names. */ static struct { const char *name; uint32_t number; } gns_name_map[] = { { "PKEY", GNUNET_GNSRECORD_TYPE_PKEY }, { "NICK", GNUNET_GNSRECORD_TYPE_NICK }, { "LEHO", GNUNET_GNSRECORD_TYPE_LEHO }, { "VPN", GNUNET_GNSRECORD_TYPE_VPN }, { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS }, { NULL, UINT32_MAX } }; /** * Convert a type name (i.e. "AAAA") to the corresponding number. * * @param cls closure, unused * @param gns_typename name to convert * @return corresponding number, UINT32_MAX on error */ static uint32_t gns_typename_to_number (void *cls, const char *gns_typename) { unsigned int i; i=0; while ( (gns_name_map[i].name != NULL) && (0 != strcasecmp (gns_typename, gns_name_map[i].name)) ) i++; return gns_name_map[i].number; } /** * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") * * @param cls closure, unused * @param type number of a type to convert * @return corresponding typestring, NULL on error */ static const char * gns_number_to_typename (void *cls, uint32_t type) { unsigned int i; i=0; while ( (gns_name_map[i].name != NULL) && (type != gns_name_map[i].number) ) i++; return gns_name_map[i].name; } /** * Entry point for the plugin. * * @param cls NULL * @return the exported block API */ void * libgnunet_plugin_gnsrecord_gns_init (void *cls) { struct GNUNET_GNSRECORD_PluginFunctions *api; api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions); api->value_to_string = &gns_value_to_string; api->string_to_value = &gns_string_to_value; api->typename_to_number = &gns_typename_to_number; api->number_to_typename = &gns_number_to_typename; return api; } /** * Exit point from the plugin. * * @param cls the return value from #libgnunet_plugin_block_test_init * @return NULL */ void * libgnunet_plugin_gnsrecord_gns_done (void *cls) { struct GNUNET_GNSRECORD_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_gnsrecord_gns.c */ gnunet-0.10.1/src/gns/test_gns_soa_lookup.sh0000755000175000017500000000273212261236532016016 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi which timeout &> /dev/null && DO_TIMEOUT="timeout 5" rm -rf /tmp/test-gnunet-gns-peer-1/ TEST_DOMAIN="homepage.gnu" # some public DNS resolver we can use TEST_IP_GNS2DNS="184.172.157.218" TEST_RECORD_NAME="homepage" TEST_RECORD_GNS2DNS="gnunet.org" if ! nslookup $TEST_RECORD_GNS2DNS $TEST_IP_GNS2DNS &> /dev/null then echo "Cannot reach DNS, skipping test" exit 77 fi gnunet-arm -s -c test_gns_lookup.conf gnunet-identity -C testego -c test_gns_lookup.conf gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME -t GNS2DNS -V ${TEST_RECORD_GNS2DNS}@${TEST_IP_GNS2DNS} -e never -c test_gns_lookup.conf RES_SOA=`$DO_TIMEOUT gnunet-gns --raw -z testego -u $TEST_DOMAIN -t SOA -c test_gns_lookup.conf` gnunet-namestore -z testego -d -n $TEST_RECORD_NAME -t GNS2DNS -V ${TEST_RECORD_GNS2DNS}@${TEST_IP_GNS2DNS} -e never -c test_gns_lookup.conf &> /dev/null gnunet-identity -D testego -c test_gns_lookup.conf gnunet-arm -e -c test_gns_lookup.conf rm -rf /tmp/test-gnunet-gns-peer-1/ if [ "x$RES_SOA" != "x" ] then echo "PASS: Resolved SOA for $TEST_DOMAIN to $RES_SOA." exit 0 else echo "Failed to resolve to proper SOA for $TEST_DOMAIN, got no result." exit 1 fi gnunet-0.10.1/src/gns/gns_api.c0000644000175000017500000003525312305564547013177 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gns_api.c * @brief library to access the GNS service * @author Martin Schanzenbach * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_arm_service.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_dht_service.h" #include "gns.h" #include "gnunet_gns_service.h" #define LOG(kind,...) GNUNET_log_from (kind, "gns-api",__VA_ARGS__) /** * Handle to a lookup request */ struct GNUNET_GNS_LookupRequest { /** * DLL */ struct GNUNET_GNS_LookupRequest *next; /** * DLL */ struct GNUNET_GNS_LookupRequest *prev; /** * handle to gns */ struct GNUNET_GNS_Handle *gns_handle; /** * processor to call on lookup result */ GNUNET_GNS_LookupResultProcessor lookup_proc; /** * processor closure */ void *proc_cls; /** * request id */ uint32_t r_id; }; /** * Entry in our list of messages to be (re-)transmitted. */ struct PendingMessage { /** * This is a doubly-linked list. */ struct PendingMessage *prev; /** * This is a doubly-linked list. */ struct PendingMessage *next; /** * Size of the message. */ size_t size; /** * request id */ uint32_t r_id; /** * This message has been transmitted. GNUNET_NO if the message is * in the "pending" DLL, GNUNET_YES if it has been transmitted to * the service via the current client connection. */ int transmitted; }; /** * Connection to the GNS service. */ struct GNUNET_GNS_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Currently pending transmission request (or NULL). */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of linked list of shorten messages we would like to transmit. */ struct PendingMessage *pending_head; /** * Tail of linked list of shorten messages we would like to transmit. */ struct PendingMessage *pending_tail; /** * Head of linked list of lookup messages we would like to transmit. */ struct GNUNET_GNS_LookupRequest *lookup_head; /** * Tail of linked list of lookup messages we would like to transmit. */ struct GNUNET_GNS_LookupRequest *lookup_tail; /** * Reconnect task */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * How long do we wait until we try to reconnect? */ struct GNUNET_TIME_Relative reconnect_backoff; /** * Request Id generator. Incremented by one for each request. */ uint32_t r_id_gen; /** * Did we start our receive loop yet? */ int in_receive; }; /** * Try to send messages from list of messages to send * @param handle GNS_Handle */ static void process_pending_messages (struct GNUNET_GNS_Handle *handle); /** * Reconnect to GNS service. * * @param handle the handle to the GNS service */ static void reconnect (struct GNUNET_GNS_Handle *handle) { GNUNET_assert (NULL == handle->client); LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to connect to GNS\n"); handle->client = GNUNET_CLIENT_connect ("gns", handle->cfg); GNUNET_assert (NULL != handle->client); process_pending_messages (handle); } /** * Reconnect to GNS * * @param cls the handle * @param tc task context */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_GNS_Handle *handle = cls; handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; reconnect (handle); } /** * Disconnect from service and then reconnect. * * @param handle our handle */ static void force_reconnect (struct GNUNET_GNS_Handle *handle) { struct GNUNET_GNS_LookupRequest *lh; struct PendingMessage *p; GNUNET_CLIENT_disconnect (handle->client); handle->client = NULL; handle->in_receive = GNUNET_NO; for (lh = handle->lookup_head; NULL != lh; lh = lh->next) { p = (struct PendingMessage *) &lh[1]; if (GNUNET_NO == p->transmitted) continue; p->transmitted = GNUNET_NO; GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, p); } handle->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (handle->reconnect_backoff); handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_backoff, &reconnect_task, handle); } /** * Transmit the next pending message, called by notify_transmit_ready * * @param cls the closure * @param size size of pending data * @param buf buffer with pending data * @return size data transmitted */ static size_t transmit_pending (void *cls, size_t size, void *buf); /** * Handler for messages received from the GNS service * * @param cls the 'struct GNUNET_GNS_Handle' * @param msg the incoming message */ static void process_message (void *cls, const struct GNUNET_MessageHeader *msg); /** * Try to send messages from list of messages to send * * @param handle the GNS handle */ static void process_pending_messages (struct GNUNET_GNS_Handle *handle) { struct PendingMessage *p = handle->pending_head; if (NULL == handle->client) return; /* wait for reconnect */ if (NULL != handle->th) return; /* transmission request already pending */ while ((NULL != p) && (p->transmitted == GNUNET_YES)) p = p->next; if (NULL == p) return; /* no messages pending */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to transmit %u bytes\n", (unsigned int) p->size); handle->th = GNUNET_CLIENT_notify_transmit_ready (handle->client, p->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_pending, handle); GNUNET_break (NULL != handle->th); } /** * Transmit the next pending message, called by notify_transmit_ready * * @param cls the closure * @param size size of pending data * @param buf buffer with pending data * @return size data transmitted */ static size_t transmit_pending (void *cls, size_t size, void *buf) { struct GNUNET_GNS_Handle *handle = cls; char *cbuf = buf; struct PendingMessage *p; size_t tsize; handle->th = NULL; if ((0 == size) || (NULL == buf)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission to GNS service failed!\n"); force_reconnect (handle); return 0; } if (NULL == (p = handle->pending_head)) return 0; tsize = 0; while ((NULL != (p = handle->pending_head)) && (p->size <= size)) { memcpy (&cbuf[tsize], &p[1], p->size); tsize += p->size; size -= p->size; p->transmitted = GNUNET_YES; GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, p); if (GNUNET_YES != handle->in_receive) { GNUNET_CLIENT_receive (handle->client, &process_message, handle, GNUNET_TIME_UNIT_FOREVER_REL); handle->in_receive = GNUNET_YES; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending %u bytes\n", (unsigned int) tsize); process_pending_messages (handle); return tsize; } /** * Process a given reply to the lookup request * * @param qe a queue entry * @param msg the lookup message received */ static void process_lookup_reply (struct GNUNET_GNS_LookupRequest *qe, const struct GNUNET_GNS_ClientLookupResultMessage *msg) { struct GNUNET_GNS_Handle *handle = qe->gns_handle; struct PendingMessage *p = (struct PendingMessage *) &qe[1]; GNUNET_GNS_LookupResultProcessor proc; void *proc_cls; uint32_t rd_count = ntohl (msg->rd_count); struct GNUNET_GNSRECORD_Data rd[rd_count]; size_t mlen; if (GNUNET_YES != p->transmitted) { /* service send reply to query we never managed to send!? */ GNUNET_break (0); force_reconnect (handle); return; } mlen = ntohs (msg->header.size); mlen -= sizeof (struct GNUNET_GNS_ClientLookupResultMessage); proc = qe->lookup_proc; proc_cls = qe->proc_cls; GNUNET_CONTAINER_DLL_remove (handle->lookup_head, handle->lookup_tail, qe); GNUNET_free (qe); if (GNUNET_SYSERR == GNUNET_GNSRECORD_records_deserialize (mlen, (const char*) &msg[1], rd_count, rd)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to deserialize lookup reply from GNS service!\n")); proc (proc_cls, 0, NULL); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Received lookup reply from GNS service (%u records)\n", (unsigned int) rd_count); proc (proc_cls, rd_count, rd); } } /** * Handler for messages received from the GNS service * * @param cls the 'struct GNUNET_GNS_Handle' * @param msg the incoming message */ static void process_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_GNS_Handle *handle = cls; struct GNUNET_GNS_LookupRequest *lr; const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg; uint32_t r_id; if (NULL == msg) { force_reconnect (handle); return; } GNUNET_CLIENT_receive (handle->client, &process_message, handle, GNUNET_TIME_UNIT_FOREVER_REL); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT: LOG (GNUNET_ERROR_TYPE_DEBUG, "Got LOOKUP_RESULT msg\n"); if (ntohs (msg->size) < sizeof (struct GNUNET_GNS_ClientLookupResultMessage)) { GNUNET_break (0); force_reconnect (handle); return; } lookup_msg = (const struct GNUNET_GNS_ClientLookupResultMessage *) msg; r_id = ntohl (lookup_msg->id); for (lr = handle->lookup_head; NULL != lr; lr = lr->next) if (lr->r_id == r_id) { process_lookup_reply(lr, lookup_msg); break; } break; default: GNUNET_break (0); force_reconnect (handle); return; } } /** * Initialize the connection with the GNS service. * * @param cfg configuration to use * @return handle to the GNS service, or NULL on error */ struct GNUNET_GNS_Handle * GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_GNS_Handle *handle; handle = GNUNET_new (struct GNUNET_GNS_Handle); handle->cfg = cfg; reconnect (handle); return handle; } /** * Shutdown connection with the GNS service. * * @param handle handle of the GNS connection to stop */ void GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle) { if (NULL != handle->client) { GNUNET_CLIENT_disconnect (handle->client); handle->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task) { GNUNET_SCHEDULER_cancel (handle->reconnect_task); handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_assert (NULL == handle->lookup_head); GNUNET_free (handle); } /** * Cancel pending lookup request * * @param lr the lookup request to cancel */ void GNUNET_GNS_lookup_cancel (struct GNUNET_GNS_LookupRequest *lr) { struct PendingMessage *p = (struct PendingMessage*) &lr[1]; GNUNET_assert (NULL != lr->gns_handle); if (GNUNET_NO == p->transmitted) GNUNET_CONTAINER_DLL_remove (lr->gns_handle->pending_head, lr->gns_handle->pending_tail, p); GNUNET_CONTAINER_DLL_remove (lr->gns_handle->lookup_head, lr->gns_handle->lookup_tail, lr); GNUNET_free (lr); } /** * Perform an asynchronous lookup operation on the GNS. * * @param handle handle to the GNS service * @param name the name to look up * @param zone the zone to start the resolution in * @param type the record type to look up * @param options local options for the lookup * @param shorten_zone_key the private key of the shorten zone (can be NULL) * @param proc processor to call on result * @param proc_cls closure for @a proc * @return handle to the get request */ struct GNUNET_GNS_LookupRequest* GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle, const char *name, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t type, enum GNUNET_GNS_LocalOptions options, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone_key, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls) { /* IPC to shorten gns names, return shorten_handle */ struct GNUNET_GNS_ClientLookupMessage *lookup_msg; struct GNUNET_GNS_LookupRequest *lr; size_t msize; struct PendingMessage *pending; if (NULL == name) { GNUNET_break (0); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to lookup `%s' in GNS\n", name); msize = sizeof (struct GNUNET_GNS_ClientLookupMessage) + strlen (name) + 1; if (msize > UINT16_MAX) { GNUNET_break (0); return NULL; } lr = GNUNET_malloc (sizeof (struct GNUNET_GNS_LookupRequest) + sizeof (struct PendingMessage) + msize); lr->gns_handle = handle; lr->lookup_proc = proc; lr->proc_cls = proc_cls; lr->r_id = handle->r_id_gen++; pending = (struct PendingMessage *)&lr[1]; pending->size = msize; pending->r_id = lr->r_id; GNUNET_CONTAINER_DLL_insert_tail (handle->lookup_head, handle->lookup_tail, lr); lookup_msg = (struct GNUNET_GNS_ClientLookupMessage *) &pending[1]; lookup_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_LOOKUP); lookup_msg->header.size = htons (msize); lookup_msg->id = htonl (lr->r_id); lookup_msg->options = htons ((uint16_t) options); lookup_msg->zone = *zone; lookup_msg->type = htonl (type); if (NULL != shorten_zone_key) { lookup_msg->have_key = htons (GNUNET_YES); lookup_msg->shorten_key = *shorten_zone_key; } memcpy (&lookup_msg[1], name, strlen (name) + 1); GNUNET_CONTAINER_DLL_insert_tail (handle->pending_head, handle->pending_tail, pending); process_pending_messages (handle); return lr; } /* end of gns_api.c */ gnunet-0.10.1/src/gns/test_gns_nick_shorten.sh0000755000175000017500000001012012261236532016317 00000000000000#!/bin/bash trap "gnunet-arm -e -c test_gns_nick_shorten.conf" SIGINT which timeout &> /dev/null && DO_TIMEOUT="timeout 5" # This test tests shortening functionality based on NICK records: # # zone "delegatedego": Alice's zone # zone "testego": Local zone with delegation to alice LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi # Deleting home directory from previous runs TEST_CONFIG="test_gns_nick_shorten.conf " rm -rf /tmp/test-gnunet-gns-peer-1/ TEST_IP="127.0.0.1" TEST_IP="127.0.0.2" TEST_NICK_EGO="ego" TEST_NICK_DELEGATED="alice" TEST_NAME="www.mybestfriendalice.gnu" TEST_NAME_SHORT="www.alice.short.gnu" # export GNUNET_FORCE_LOG="namestore;;;;DEBUG/gns;;;;DEBUG/;;;;WARNING" # Start gnunet echo "Starting arm with configuration $TEST_CONFIG" gnunet-arm -s -c $TEST_CONFIG # Create initial identities: short-zone, delegated-zone, testego echo "Creating identities" gnunet-identity -d -c $TEST_CONFIG gnunet-identity -C short-zone -c $TEST_CONFIG gnunet-identity -C delegatedego -c $TEST_CONFIG gnunet-identity -e short-zone -s gns-short -c $TEST_CONFIG gnunet-identity -C testego -c $TEST_CONFIG echo "Adding nick names for identities" gnunet-namestore -z testego -i $TEST_NICK_EGO -c $TEST_CONFIG gnunet-namestore -z delegatedego -i $TEST_NICK_DELEGATED -c $TEST_CONFIG # Adding label www in Alice's delegatedego zone echo "Adding www record with IP $TEST_IP" gnunet-namestore -p -z delegatedego -a -n www -t A -V $TEST_IP -e never -c test_gns_nick_shorten.conf # Retrieve PKEYs for delegation DELEGATED_PKEY=$(gnunet-identity -d -c $TEST_CONFIG| grep delegatedego | awk '{print $3}') echo "Alice's PKEY is $DELEGATED_PKEY" SHORTEN_PKEY=$(gnunet-identity -c test_gns_nick_shorten.conf -d | grep short-zone | awk '{print $3}') echo "Shorten PKEY is $SHORTEN_PKEY" # Delegate the name "short" to shortenzone gnunet-namestore -p -z testego -a -n short -t PKEY -V $SHORTEN_PKEY -e never -c test_gns_nick_shorten.conf # Delegate the name "mybestfriendalice" to alice gnunet-namestore -p -z testego -a -n mybestfriendalice -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_nick_shorten.conf # Perform lookup to shorten echo "Start gns..." gnunet-arm -c test_gns_nick_shorten.conf -i gns RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u $TEST_NAME -t A -c test_gns_nick_shorten.conf` sleep 1 echo "Lookup shortened names" PKEY_SHORT_RES=$($DO_TIMEOUT gnunet-gns --raw -c test_gns_nick_shorten.conf -z short-zone -u alice.gnu -t PKEY) echo "Resolving alice's PKEY in shorten zone: $PKEY_SHORT_RES" PKEY_RES=$($DO_TIMEOUT gnunet-gns --raw -c test_gns_nick_shorten.conf -z testego -u alice.short.gnu -t PKEY) echo "Resolving alice's PKEY in master zone: $PKEY_RES" RES=0 if [ "$DELEGATED_PKEY" == "$PKEY_SHORT_RES" ] then echo "PASS: Resolved delegation for shorten name in shortened zone" else echo "FAIL: Expected PKEY in $DELEGATED_PKEY, received PKEY '$PKEY_SHORT_RES' in shorten zone." RES=1 fi if [ "$DELEGATED_PKEY" == "$PKEY_RES" ] then echo "PASS: Resolved delegation for shorten name in master zone" else echo "FAIL: Expected PKEY in $DELEGATED_PKEY, received PKEY $PKEY_SHORT_RES in master zone." RES=1 fi if [ $RES -eq 0 ] then RES_IP=`$DO_TIMEOUT gnunet-gns --raw -z testego -u $TEST_NAME_SHORT -t A -c test_gns_nick_shorten.conf` if [ "$RES_IP" == "$TEST_IP" ] then echo "PASS: Received $TEST_IP for $TEST_NAME_SHORT" else echo "FAIL: Expected IP in $TEST_IP, received IP '$RES_IP' for $TEST_SHORT_NAME." RES=1 fi fi # Clean up echo "Clean up..." gnunet-namestore -z testego -d -n mybestfriendalice -t PKEY -V $DELEGATED_PKEY -e never -c test_gns_nick_shorten.conf gnunet-namestore -z delegatedego -d -n www -t A -V $TEST_IP -e never -c test_gns_nick_shorten.conf gnunet-identity -D -z testego -c $TEST_CONFIG gnunet-identity -D -z delegatedego -c $TEST_CONFIG gnunet-identity -D -z short-zone -c $TEST_CONFIG gnunet-arm -e -c test_gns_nick_shorten.conf rm -rf /tmp/test-gnunet-gns-peer-1/ exit $RES gnunet-0.10.1/src/gns/test_gns_simple_lookup.conf0000644000175000017500000000346212225230043017025 00000000000000@INLINE@ test_gns_defaults.conf [fs] AUTOSTART = NO [resolver] AUTOSTART = YES HOSTNAME = localhost [dht] AUTOSTART = YES ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost PORT = 12100 BINARY = gnunet-service-dht [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = tcp ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 PORT = 12365 [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [core] PORT = 12092 [arm] DEFAULTSERVICES = core dht namestore gns PORT = 12366 [transport-tcp] TIMEOUT = 300 s PORT = 12368 BINDTO = 127.0.0.1 [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunetd-gns-peer-1/ [nat] DISABLEV6 = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 USE_LOCALADDR = NO [dns] AUTOSTART = YES DNS_EXIT = 8.8.8.8 [gns] #PREFIX = valgrind --leak-check=full --track-origins=yes AUTOSTART = YES BINARY = gnunet-service-gns ZONEKEY = zonefiles/test_zonekey PRIVATE_ZONE = private PRIVATE_ZONEKEY = zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey SHORTEN_ZONE = short SHORTEN_ZONEKEY = zonefiles/188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey #ZONEKEY = $GNUNET_TEST_HOME/gns/zonekey.zkey HIJACK_DNS = NO UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-gns.sock AUTO_IMPORT_PKEY = YES MAX_PARALLEL_BACKGROUND_QUERIES = 10 DEFAULT_LOOKUP_TIMEOUT = 15 s RECORD_PUT_INTERVAL = 1 h [nse] AUTOSTART = NO [statistics] AUTOSTART = NO [namestore] PORT = 22371 AUTOSTART = YES UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-namestore-default.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES HOSTNAME = localhost BINARY = gnunet-service-namestore ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; DATABASE = sqlite ZONEFILE_DIRECTORY = $GNUNET_TEST_HOME [namestore-sqlite] FILENAME = $GNUNET_TEST_HOME/sqlite-default.db gnunet-0.10.1/src/gns/gns-helper-service-w32.conf0000644000175000017500000000013412225230043016341 00000000000000[gns-helper-service-w32] AUTOSTART = YES BINARY = gnunet-gns-helper-service-w32 PORT = 5353 gnunet-0.10.1/src/gns/gns.h0000644000175000017500000000516712305564547012354 00000000000000/* This file is part of GNUnet (C) 2012-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gns/gns.h * @brief IPC messages between GNS API and GNS service * @author Martin Schanzenbach */ #ifndef GNS_H #define GNS_H #include "gnunet_gns_service.h" /** * Name of the GNS TLD. */ #define GNUNET_GNS_TLD "gnu" /** * Name of the zone key TLD. */ #define GNUNET_GNS_TLD_ZKEY "zkey" /** * TLD name used to indicate relative names. */ #define GNUNET_GNS_TLD_PLUS "+" GNUNET_NETWORK_STRUCT_BEGIN /** * Message from client to GNS service to lookup records. */ struct GNUNET_GNS_ClientLookupMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_GNS_LOOKUP */ struct GNUNET_MessageHeader header; /** * Unique identifier for this request (for key collisions). */ uint32_t id GNUNET_PACKED; /** * Zone that is to be used for lookup */ struct GNUNET_CRYPTO_EcdsaPublicKey zone; /** * Local options for where to look for results * (an `enum GNUNET_GNS_LocalOptions` in NBO). */ int16_t options GNUNET_PACKED; /** * Is a shorten key attached? */ int16_t have_key GNUNET_PACKED; /** * the type of record to look up */ int32_t type GNUNET_PACKED; /** * The key for shorten, if @e have_key is set */ struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key; /* Followed by the zero-terminated name to look up */ }; /** * Message from GNS service to client: new results. */ struct GNUNET_GNS_ClientLookupResultMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT */ struct GNUNET_MessageHeader header; /** * Unique identifier for this request (for key collisions). */ uint32_t id GNUNET_PACKED; /** * The number of records contained in response */ uint32_t rd_count GNUNET_PACKED; /* followed by rd_count GNUNET_GNSRECORD_Data structs*/ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/gns/zonefiles/0000755000175000017500000000000012320755627013457 500000000000000gnunet-0.10.1/src/gns/zonefiles/OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey0000644000175000017500000000147212166505451023247 00000000000000:(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:nf¬ ™—ˆ¨« —&¦Ž„šÂ#¤º¥ÒŠL0é/¡1®PGsƒ¨mŸ4WÕì c€¾Ö‡…ˆÆþŠG0¯N\ó›) (5:curve10:NIST P-256) ) ) (11:private-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:nf¬ ™—ˆ¨« —&¦Ž„šÂ#¤º¥ÒŠL0é/¡1®PGsƒ¨mŸ4WÕì c€¾Ö‡…ˆÆþŠG0¯N\ó›) (1:d32:Ñðßû•ñ{èV"€5ÞÁi9 ô)tý§¡) ) ) ) gnunet-0.10.1/src/gns/zonefiles/test_zonekey0000644000175000017500000000147312153073163016042 00000000000000;(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:¨D‘9’ äugv¬Þ|+Õàhð­»}SDÞSèÙ=’µþ›2Þ¸—5'„?MGÖ¸è0§}Œ+qµ€ç|JǬ’) (5:curve10:NIST P-256) ) ) (11:private-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:¨D‘9’ äugv¬Þ|+Õàhð­»}SDÞSèÙ=’µþ›2Þ¸—5'„?MGÖ¸è0§}Œ+qµ€ç|JǬ’) (1:d33:½Åº¶*Dzòx»[ŠÚË ÓŸžpl¸R·Tþ) ) ) ) gnunet-0.10.1/src/gns/zonefiles/J7POEUT41A8PBFS7KVVDRF88GBOU4HK8PSU5QKVLVE3R9T91E99G.zkey0000644000175000017500000000147212166505451023457 00000000000000:(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:ùG1—@A}L¸ IÒú§Æƒj€Ü#°ÁÞ&Wx{`GŸØ¨Vù¯'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:ùG1—@A}L¸ IÒú§Æƒj€Ü#°ÁÞ&Wx{`GŸØ¨Vù¯packet; struct GNUNET_DNSPARSER_Query *query = &packet->queries[0]; uint32_t i; size_t len; int ret; char *buf; unsigned int num_answers; unsigned int skip_answers; unsigned int skip_additional; size_t off; /* Put records in the DNS packet */ num_answers = 0; for (i=0; i < rd_count; i++) if (rd[i].record_type == query->type) num_answers++; skip_answers = 0; skip_additional = 0; { struct GNUNET_DNSPARSER_Record answer_records[num_answers]; struct GNUNET_DNSPARSER_Record additional_records[rd_count - num_answers]; packet->answers = answer_records; packet->additional_records = additional_records; /* FIXME: need to handle #GNUNET_GNSRECORD_RF_SHADOW_RECORD option (by ignoring records where this flag is set if there is any other record of that type in the result set) */ for (i=0; i < rd_count; i++) { if (rd[i].record_type == query->type) { answer_records[i - skip_answers].name = query->name; answer_records[i - skip_answers].type = rd[i].record_type; switch(rd[i].record_type) { case GNUNET_DNSPARSER_TYPE_NS: case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: answer_records[i - skip_answers].data.hostname = GNUNET_DNSPARSER_parse_name (rd[i].data, rd[i].data_size, &off); if ( (off != rd[i].data_size) || (NULL == answer_records[i].data.hostname) ) { GNUNET_break_op (0); skip_answers++; } break; case GNUNET_DNSPARSER_TYPE_SOA: answer_records[i - skip_answers].data.soa = GNUNET_DNSPARSER_parse_soa (rd[i].data, rd[i].data_size, &off); if ( (off != rd[i].data_size) || (NULL == answer_records[i].data.soa) ) { GNUNET_break_op (0); skip_answers++; } break; case GNUNET_DNSPARSER_TYPE_SRV: /* FIXME: SRV is not yet supported */ skip_answers++; break; case GNUNET_DNSPARSER_TYPE_MX: answer_records[i - skip_answers].data.mx = GNUNET_DNSPARSER_parse_mx (rd[i].data, rd[i].data_size, &off); if ( (off != rd[i].data_size) || (NULL == answer_records[i].data.hostname) ) { GNUNET_break_op (0); skip_answers++; } break; default: answer_records[i - skip_answers].data.raw.data_len = rd[i].data_size; answer_records[i - skip_answers].data.raw.data = (char*)rd[i].data; break; } GNUNET_break (0 == (rd[i - skip_answers].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)); answer_records[i - skip_answers].expiration_time.abs_value_us = rd[i].expiration_time; answer_records[i - skip_answers].dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; } else { additional_records[i - skip_additional].name = query->name; additional_records[i - skip_additional].type = rd[i].record_type; switch(rd[i].record_type) { case GNUNET_DNSPARSER_TYPE_NS: case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: additional_records[i - skip_additional].data.hostname = GNUNET_DNSPARSER_parse_name (rd[i].data, rd[i].data_size, &off); if ( (off != rd[i].data_size) || (NULL == additional_records[i].data.hostname) ) { GNUNET_break_op (0); skip_additional++; } break; case GNUNET_DNSPARSER_TYPE_SOA: additional_records[i - skip_additional].data.soa = GNUNET_DNSPARSER_parse_soa (rd[i].data, rd[i].data_size, &off); if ( (off != rd[i].data_size) || (NULL == additional_records[i].data.hostname) ) { GNUNET_break_op (0); skip_additional++; } break; case GNUNET_DNSPARSER_TYPE_MX: additional_records[i - skip_additional].data.mx = GNUNET_DNSPARSER_parse_mx (rd[i].data, rd[i].data_size, &off); if ( (off != rd[i].data_size) || (NULL == additional_records[i].data.hostname) ) { GNUNET_break_op (0); skip_additional++; } break; case GNUNET_DNSPARSER_TYPE_SRV: /* FIXME: SRV is not yet supported */ skip_answers++; break; default: additional_records[i - skip_additional].data.raw.data_len = rd[i].data_size; additional_records[i - skip_additional].data.raw.data = (char*)rd[i].data; break; } GNUNET_break (0 == (rd[i - skip_additional].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)); additional_records[i - skip_additional].expiration_time.abs_value_us = rd[i].expiration_time; additional_records[i - skip_additional].dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET; } } packet->num_answers = num_answers - skip_answers; packet->num_additional_records = rd_count - num_answers - skip_additional; packet->flags.authoritative_answer = 1; if (NULL == rd) packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NAME_ERROR; else packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR; packet->flags.query_or_response = 1; ret = GNUNET_DNSPARSER_pack (packet, 1024, /* maximum allowed size for DNS reply */ &buf, &len); if (GNUNET_OK != ret) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Error converting GNS response to DNS response!\n")); } else { GNUNET_DNS_request_answer (ilh->request_handle, len, buf); GNUNET_free (buf); } packet->num_answers = 0; packet->answers = NULL; packet->num_additional_records = 0; packet->additional_records = NULL; GNUNET_DNSPARSER_free_packet (packet); } GNUNET_CONTAINER_DLL_remove (ilh_head, ilh_tail, ilh); GNUNET_free (ilh); } /** * The DNS request handler. Called for every incoming DNS request. * * @param cls closure, unused * @param rh request handle to user for reply * @param request_length number of bytes in @a request * @param request UDP payload of the DNS request */ static void handle_dns_request (void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request) { struct GNUNET_DNSPARSER_Packet *p; struct InterceptLookupHandle *ilh; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request. Processing.\n"); if (NULL == (p = GNUNET_DNSPARSER_parse (request, request_length))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received malformed DNS packet, leaving it untouched.\n"); GNUNET_DNS_request_forward (rh); GNUNET_DNSPARSER_free_packet (p); return; } /* Check TLD and decide if we or legacy dns is responsible */ if (1 != p->num_queries) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not exactly one query in DNS packet. Forwarding untouched.\n"); GNUNET_DNS_request_forward (rh); GNUNET_DNSPARSER_free_packet(p); return; } /* Check for GNS TLDs. */ if ( (GNUNET_YES == is_gnu_tld (p->queries[0].name)) || (GNUNET_YES == is_zkey_tld (p->queries[0].name)) || (0 == strcmp (p->queries[0].name, GNUNET_GNS_TLD)) ) { /* Start resolution in GNS */ ilh = GNUNET_new (struct InterceptLookupHandle); GNUNET_CONTAINER_DLL_insert (ilh_head, ilh_tail, ilh); ilh->packet = p; ilh->request_handle = rh; ilh->lookup = GNS_resolver_lookup (&zone, p->queries[0].type, p->queries[0].name, NULL /* FIXME: enable shorten for DNS intercepts? */, GNUNET_NO, &reply_to_dns, ilh); return; } /* This request does not concern us. Forward to real DNS. */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request for `%s' is forwarded to DNS untouched.\n", p->queries[0].name); GNUNET_DNS_request_forward (rh); GNUNET_DNSPARSER_free_packet (p); } /** * Initialized the interceptor * * @param gnu_zone the zone to work in * @param c the configuration * @return #GNUNET_OK on success */ int GNS_interceptor_init (const struct GNUNET_CRYPTO_EcdsaPublicKey *gnu_zone, const struct GNUNET_CONFIGURATION_Handle *c) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "DNS hijacking enabled. Connecting to DNS service.\n"); zone = *gnu_zone; dns_handle = GNUNET_DNS_connect (c, GNUNET_DNS_FLAG_PRE_RESOLUTION, &handle_dns_request, NULL); if (NULL == dns_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to the DNS service!\n")); return GNUNET_SYSERR; } return GNUNET_YES; } /** * Disconnect from interceptor */ void GNS_interceptor_done () { struct InterceptLookupHandle *ilh; while (NULL != (ilh = ilh_head)) { GNUNET_CONTAINER_DLL_remove (ilh_head, ilh_tail, ilh); GNS_resolver_lookup_cancel (ilh->lookup); GNUNET_DNS_request_drop (ilh->request_handle); GNUNET_DNSPARSER_free_packet (ilh->packet); GNUNET_free (ilh); } if (NULL != dns_handle) { GNUNET_DNS_disconnect (dns_handle); dns_handle = NULL; } } /* end of gnunet-service-gns_interceptor.c */ gnunet-0.10.1/src/gns/test_gns_proxy.conf0000644000175000017500000000103012225230043015311 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-gns-proxy/ [transport] PLUGINS = tcp [arm] DEFAULTSERVICES = statistics dns namestore gns PORT = 0 ALLOW_SHUTDOWN = YES [testing] WEAKRANDOM = YES HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat [gns] AUTOSTART = YES ZONEKEY = $GNUNET_TEST_HOME/.hostkey HIJACK_DNS = YES [gns-proxy] PROXY_CACERT = proxy/test_cert.pem PROXY_UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-gns-proxy.sock [namestore] AUTOSTART = YES [dns] PROVIDE_EXIT = NO #DNS_EXIT = 8.8.8.8 #PREFIX = valgrind --leak-check=full gnunet-0.10.1/src/vpn/0000755000175000017500000000000012320755627011475 500000000000000gnunet-0.10.1/src/vpn/vpn.conf.in0000644000175000017500000000060312250373167013470 00000000000000[vpn] AUTOSTART = @AUTOSTART@ @UNIXONLY@ PORT = 2105 HOSTNAME = localhost BINARY = gnunet-service-vpn ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES IPV6ADDR = 1234::1 IPV6PREFIX = 32 IPV4ADDR = 10.11.10.1 IPV4MASK = 255.255.0.0 VIRTDNS = 10.11.10.2 VIRTDNS6 = 1234::17 IFNAME = vpn-gnunet gnunet-0.10.1/src/vpn/vpn_api.c0000644000175000017500000003523712255060042013212 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file vpn/vpn_api.c * @brief library to access the VPN service and tell it how to redirect traffic * @author Christian Grothoff */ #include "platform.h" #include "gnunet_vpn_service.h" #include "vpn.h" /** * Opaque VPN handle */ struct GNUNET_VPN_Handle { /** * Configuration we use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Connection to VPN service. */ struct GNUNET_CLIENT_Connection *client; /** * Active transmission request. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of list of active redirection requests. */ struct GNUNET_VPN_RedirectionRequest *rr_head; /** * Tail of list of active redirection requests. */ struct GNUNET_VPN_RedirectionRequest *rr_tail; /** * Identifier of a reconnect task. */ GNUNET_SCHEDULER_TaskIdentifier rt; /** * How long do we wait until we try to reconnect? */ struct GNUNET_TIME_Relative backoff; /** * ID of the last request that was submitted to the service. */ uint64_t request_id_gen; }; /** * Opaque redirection request handle. */ struct GNUNET_VPN_RedirectionRequest { /** * Element in DLL. */ struct GNUNET_VPN_RedirectionRequest *next; /** * Element in DLL. */ struct GNUNET_VPN_RedirectionRequest *prev; /** * Pointer to the VPN struct. */ struct GNUNET_VPN_Handle *vh; /** * Target IP address for the redirection, or NULL for * redirection to service. Allocated after this struct. */ const void *addr; /** * Function to call with the designated IP address. */ GNUNET_VPN_AllocationCallback cb; /** * Closure for 'cb'. */ void *cb_cls; /** * For service redirection, identity of the peer offering the service. */ struct GNUNET_PeerIdentity peer; /** * For service redirection, service descriptor. */ struct GNUNET_HashCode serv; /** * At what time should the created service mapping expire? */ struct GNUNET_TIME_Absolute expiration_time; /** * non-zero if this request has been sent to the service. */ uint64_t request_id; /** * Desired address family for the result. */ int result_af; /** * Address family of 'addr'. AF_INET or AF_INET6. */ int addr_af; /** * For service redirection, IPPROT_UDP or IPPROTO_TCP. */ uint8_t protocol; }; /** * Disconnect from the service (communication error) and reconnect later. * * @param vh handle to reconnect. */ static void reconnect (struct GNUNET_VPN_Handle *vh); /** * Function called when we receive a message from the VPN service. * * @param cls the `struct GNUNET_VPN_Handle` * @param msg message received, NULL on timeout or fatal error */ static void receive_response (void *cls, const struct GNUNET_MessageHeader* msg) { struct GNUNET_VPN_Handle *vh = cls; const struct RedirectToIpResponseMessage *rm; struct GNUNET_VPN_RedirectionRequest *rr; size_t msize; size_t alen; int af; if (NULL == msg) { reconnect (vh); return; } if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP) || (sizeof (struct RedirectToIpResponseMessage) > (msize = ntohs (msg->size))) ) { GNUNET_break (0); reconnect (vh); return; } rm = (const struct RedirectToIpResponseMessage *) msg; af = (int) ntohl (rm->result_af); switch (af) { case AF_UNSPEC: alen = 0; break; case AF_INET: alen = sizeof (struct in_addr); break; case AF_INET6: alen = sizeof (struct in6_addr); break; default: GNUNET_break (0); reconnect (vh); return; } if ( (msize != alen + sizeof (struct RedirectToIpResponseMessage)) || (0 == rm->request_id) ) { GNUNET_break (0); reconnect (vh); return; } GNUNET_CLIENT_receive (vh->client, &receive_response, vh, GNUNET_TIME_UNIT_FOREVER_REL); for (rr = vh->rr_head; NULL != rr; rr = rr->next) { if (rr->request_id == rm->request_id) { GNUNET_CONTAINER_DLL_remove (vh->rr_head, vh->rr_tail, rr); rr->cb (rr->cb_cls, af, (af == AF_UNSPEC) ? NULL : &rm[1]); GNUNET_free (rr); break; } } } /** * We're ready to transmit a request to the VPN service. Do it. * * @param cls the 'struct GNUNET_VPN_Handle*' * @param size number of bytes available in buf * @param buf where to copy the request * @return number of bytes copied to 'buf' */ static size_t transmit_request (void *cls, size_t size, void *buf) { struct GNUNET_VPN_Handle *vh = cls; struct GNUNET_VPN_RedirectionRequest *rr; struct RedirectToIpRequestMessage rip; struct RedirectToServiceRequestMessage rs; char *cbuf; size_t alen; size_t ret; vh->th = NULL; /* find a pending request */ rr = vh->rr_head; while ( (NULL != rr) && (0 != rr->request_id) ) rr = rr->next; if (NULL == rr) return 0; if (0 == size) { reconnect (vh); return 0; } /* if first request, start receive loop */ if (0 == vh->request_id_gen) GNUNET_CLIENT_receive (vh->client, &receive_response, vh, GNUNET_TIME_UNIT_FOREVER_REL); if (NULL == rr->addr) { ret = sizeof (struct RedirectToServiceRequestMessage); GNUNET_assert (ret <= size); rs.header.size = htons ((uint16_t) ret); rs.header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE); rs.reserved = htonl (0); rs.expiration_time = GNUNET_TIME_absolute_hton (rr->expiration_time); rs.protocol = htonl (rr->protocol); rs.result_af = htonl (rr->result_af); rs.target = rr->peer; rs.service_descriptor = rr->serv; rs.request_id = rr->request_id = ++vh->request_id_gen; memcpy (buf, &rs, sizeof (struct RedirectToServiceRequestMessage)); } else { switch (rr->addr_af) { case AF_INET: alen = sizeof (struct in_addr); break; case AF_INET6: alen = sizeof (struct in6_addr); break; default: GNUNET_assert (0); return 0; } ret = alen + sizeof (struct RedirectToIpRequestMessage); GNUNET_assert (ret <= size); rip.header.size = htons ((uint16_t) ret); rip.header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP); rip.reserved = htonl (0); rip.expiration_time = GNUNET_TIME_absolute_hton (rr->expiration_time); rip.result_af = htonl (rr->result_af); rip.addr_af = htonl (rr->addr_af); rip.request_id = rr->request_id = ++vh->request_id_gen; cbuf = buf; memcpy (cbuf, &rip, sizeof (struct RedirectToIpRequestMessage)); memcpy (&cbuf[sizeof (struct RedirectToIpRequestMessage)], rr->addr, alen); } /* test if there are more pending requests */ while ( (NULL != rr) && (0 != rr->request_id) ) rr = rr->next; if (NULL != rr) vh->th = GNUNET_CLIENT_notify_transmit_ready (vh->client, sizeof (struct RedirectToServiceRequestMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_request, vh); return ret; } /** * Add a request to our request queue and transmit it. * * @param rr request to queue and transmit. */ static void queue_request (struct GNUNET_VPN_RedirectionRequest *rr) { struct GNUNET_VPN_Handle *vh; vh = rr->vh; GNUNET_CONTAINER_DLL_insert_tail (vh->rr_head, vh->rr_tail, rr); if ( (NULL == vh->th) && (NULL != vh->client) ) vh->th = GNUNET_CLIENT_notify_transmit_ready (vh->client, sizeof (struct RedirectToServiceRequestMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_request, vh); } /** * Connect to the VPN service and start again to transmit our requests. * * @param cls the 'struct GNUNET_VPN_Handle *' * @param tc scheduler context */ static void connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_VPN_Handle *vh = cls; vh->rt = GNUNET_SCHEDULER_NO_TASK; vh->client = GNUNET_CLIENT_connect ("vpn", vh->cfg); GNUNET_assert (NULL != vh->client); GNUNET_assert (NULL == vh->th); if (NULL != vh->rr_head) vh->th = GNUNET_CLIENT_notify_transmit_ready (vh->client, sizeof (struct RedirectToServiceRequestMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_request, vh); } /** * Disconnect from the service (communication error) and reconnect later. * * @param vh handle to reconnect. */ static void reconnect (struct GNUNET_VPN_Handle *vh) { struct GNUNET_VPN_RedirectionRequest *rr; if (NULL != vh->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (vh->th); vh->th = NULL; } GNUNET_CLIENT_disconnect (vh->client); vh->client = NULL; vh->request_id_gen = 0; for (rr = vh->rr_head; NULL != rr; rr = rr->next) rr->request_id = 0; vh->backoff = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (vh->backoff, 2), GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30))); vh->rt = GNUNET_SCHEDULER_add_delayed (vh->backoff, &connect_task, vh); } /** * Cancel redirection request with the service. * * @param rr request to cancel */ void GNUNET_VPN_cancel_request (struct GNUNET_VPN_RedirectionRequest *rr) { struct GNUNET_VPN_Handle *vh; vh = rr->vh; GNUNET_CONTAINER_DLL_remove (vh->rr_head, vh->rr_tail, rr); GNUNET_free (rr); } /** * Tell the VPN that a forwarding to a particular peer offering a * particular service is requested. The VPN is to reserve a * particular IP for the redirection and return it. The VPN will * begin the redirection as soon as possible and maintain it as long * as it is actively used and keeping it is feasible. Given resource * limitations, the longest inactive mappings will be destroyed. * * @param vh VPN handle * @param result_af desired address family for the returned allocation * can also be AF_UNSPEC * @param protocol protocol, IPPROTO_UDP or IPPROTO_TCP * @param peer target peer for the redirection * @param serv service descriptor to give to the peer * @param expiration_time at what time should the redirection expire? * (this should not impact connections that are active at that time) * @param cb function to call with the IP * @param cb_cls closure for cb * @return handle to cancel the request (means the callback won't be * invoked anymore; the mapping may or may not be established * anyway) */ struct GNUNET_VPN_RedirectionRequest * GNUNET_VPN_redirect_to_peer (struct GNUNET_VPN_Handle *vh, int result_af, uint8_t protocol, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HashCode *serv, struct GNUNET_TIME_Absolute expiration_time, GNUNET_VPN_AllocationCallback cb, void *cb_cls) { struct GNUNET_VPN_RedirectionRequest *rr; rr = GNUNET_new (struct GNUNET_VPN_RedirectionRequest); rr->vh = vh; rr->cb = cb; rr->cb_cls = cb_cls; rr->peer = *peer; rr->serv = *serv; rr->expiration_time = expiration_time; rr->result_af = result_af; rr->protocol = protocol; queue_request (rr); return rr; } /** * Tell the VPN that forwarding to the Internet via some exit node is * requested. Note that both UDP and TCP traffic will be forwarded, * but possibly to different exit nodes. The VPN is to reserve a * particular IP for the redirection and return it. The VPN will * begin the redirection as soon as possible and maintain it as long * as it is actively used and keeping it is feasible. Given resource * limitations, the longest inactive mappings will be destroyed. * * @param vh VPN handle * @param result_af desired address family for the returned allocation * @param addr_af address family for 'addr', AF_INET or AF_INET6 * @param addr destination IP address on the Internet; destination * port is to be taken from the VPN packet itself * @param expiration_time at what time should the redirection expire? * (this should not impact connections that are active at that time) * @param cb function to call with the IP * @param cb_cls closure for cb * @return handle to cancel the request (means the callback won't be * invoked anymore; the mapping may or may not be established * anyway) */ struct GNUNET_VPN_RedirectionRequest * GNUNET_VPN_redirect_to_ip (struct GNUNET_VPN_Handle *vh, int result_af, int addr_af, const void *addr, struct GNUNET_TIME_Absolute expiration_time, GNUNET_VPN_AllocationCallback cb, void *cb_cls) { struct GNUNET_VPN_RedirectionRequest *rr; size_t alen; switch (addr_af) { case AF_INET: alen = sizeof (struct in_addr); break; case AF_INET6: alen = sizeof (struct in6_addr); break; default: GNUNET_break (0); return NULL; } rr = GNUNET_malloc (sizeof (struct GNUNET_VPN_RedirectionRequest) + alen); rr->vh = vh; rr->addr = &rr[1]; rr->cb = cb; rr->cb_cls = cb_cls; rr->expiration_time = expiration_time; rr->result_af = result_af; rr->addr_af = addr_af; memcpy (&rr[1], addr, alen); queue_request (rr); return rr; } /** * Connect to the VPN service * * @param cfg configuration to use * @return VPN handle */ struct GNUNET_VPN_Handle * GNUNET_VPN_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_VPN_Handle *vh; vh = GNUNET_new (struct GNUNET_VPN_Handle); vh->cfg = cfg; vh->client = GNUNET_CLIENT_connect ("vpn", cfg); if (NULL == vh->client) { GNUNET_free (vh); return NULL; } return vh; } /** * Disconnect from the VPN service. * * @param vh VPN handle */ void GNUNET_VPN_disconnect (struct GNUNET_VPN_Handle *vh) { GNUNET_assert (NULL == vh->rr_head); if (NULL != vh->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (vh->th); vh->th = NULL; } if (NULL != vh->client) { GNUNET_CLIENT_disconnect (vh->client); vh->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != vh->rt) { GNUNET_SCHEDULER_cancel (vh->rt); vh->rt = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (vh); } /* end of vpn_api.c */ gnunet-0.10.1/src/vpn/gnunet-vpn.c0000644000175000017500000001743612255060435013666 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/vpn/gnunet-vpn.c * @brief Tool to manually request VPN tunnels to be created * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_tun_lib.h" #include "gnunet_vpn_service.h" /** * Handle to vpn service. */ static struct GNUNET_VPN_Handle *handle; /** * Opaque redirection request handle. */ static struct GNUNET_VPN_RedirectionRequest *request; /** * Option -p: destination peer identity for service */ static char *peer_id; /** * Option -s: service name (hash to get service descriptor) */ static char *service_name; /** * Option -i: target IP */ static char *target_ip; /** * Option -4: IPv4 requested. */ static int ipv4; /** * Option -6: IPv6 requested. */ static int ipv6; /** * Option -t: TCP requested. */ static int tcp; /** * Option -u: UDP requested. */ static int udp; /** * Selected level of verbosity. */ static int verbosity; /** * Global return value. */ static int ret; /** * Option '-d': duration of the mapping */ static struct GNUNET_TIME_Relative duration = { 5 * 60 * 1000} ; /** * Shutdown. */ static void do_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != request) { GNUNET_VPN_cancel_request (request); request = NULL; } if (NULL != handle) { GNUNET_VPN_disconnect (handle); handle = NULL; } GNUNET_free_non_null (peer_id); GNUNET_free_non_null (service_name); GNUNET_free_non_null (target_ip); } /** * Callback invoked from the VPN service once a redirection is * available. Provides the IP address that can now be used to * reach the requested destination. * * @param cls closure * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; * will match 'result_af' from the request * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') * that the VPN allocated for the redirection; * traffic to this IP will now be redirected to the * specified target peer; NULL on error */ static void allocation_cb (void *cls, int af, const void *address) { char buf[INET6_ADDRSTRLEN]; request = NULL; switch (af) { case AF_INET6: case AF_INET: FPRINTF (stdout, "%s\n", inet_ntop (af, address, buf, sizeof (buf))); break; case AF_UNSPEC: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error creating tunnel\n")); ret = 1; break; default: break; } GNUNET_SCHEDULER_shutdown (); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { int dst_af; int req_af; struct GNUNET_PeerIdentity peer; struct GNUNET_HashCode sd; const void *addr; struct in_addr v4; struct in6_addr v6; uint8_t protocol; struct GNUNET_TIME_Absolute etime; etime = GNUNET_TIME_relative_to_absolute (duration); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_disconnect, NULL); handle = GNUNET_VPN_connect (cfg); if (NULL == handle) goto error; req_af = AF_UNSPEC; if (ipv4) { if (ipv6) { FPRINTF (stderr, _("Option `%s' makes no sense with option `%s'.\n"), "-4", "-6"); goto error; } req_af = AF_INET; } if (ipv6) req_af = AF_INET6; if (NULL == target_ip) { if (NULL == service_name) { FPRINTF (stderr, _("Option `%s' or `%s' is required.\n"), "-i", "-s"); goto error; } if (NULL == peer_id) { FPRINTF (stderr, _("Option `%s' is required when using option `%s'.\n"), "-p", "-s"); goto error; } if (! (tcp | udp) ) { FPRINTF (stderr, _("Option `%s' or `%s' is required when using option `%s'.\n"), "-t", "-u", "-s"); goto error; } if (tcp & udp) { FPRINTF (stderr, _("Option `%s' makes no sense with option `%s'.\n"), "-t", "-u"); goto error; } if (tcp) protocol = IPPROTO_TCP; if (udp) protocol = IPPROTO_UDP; if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id, strlen (peer_id), &peer.public_key)) { FPRINTF (stderr, _("`%s' is not a valid peer identifier.\n"), peer_id); goto error; } GNUNET_TUN_service_name_to_hash (service_name, &sd); request = GNUNET_VPN_redirect_to_peer (handle, req_af, protocol, &peer, &sd, etime, &allocation_cb, NULL); } else { if (1 != inet_pton (AF_INET6, target_ip, &v6)) { if (1 != inet_pton (AF_INET, target_ip, &v4)) { FPRINTF (stderr, _("`%s' is not a valid IP address.\n"), target_ip); goto error; } else { dst_af = AF_INET; addr = &v4; } } else { dst_af = AF_INET6; addr = &v6; } request = GNUNET_VPN_redirect_to_ip (handle, req_af, dst_af, addr, etime, &allocation_cb, NULL); } return; error: GNUNET_SCHEDULER_shutdown (); ret = 1; } int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'4', "ipv4", NULL, gettext_noop ("request that result should be an IPv4 address"), 0, &GNUNET_GETOPT_set_one, &ipv4}, {'6', "ipv6", NULL, gettext_noop ("request that result should be an IPv6 address"), 0, &GNUNET_GETOPT_set_one, &ipv6}, {'d', "duration", "TIME", gettext_noop ("how long should the mapping be valid for new tunnels?"), 1, &GNUNET_GETOPT_set_relative_time, &duration}, {'i', "ip", "IP", gettext_noop ("destination IP for the tunnel"), 1, &GNUNET_GETOPT_set_string, &target_ip}, {'p', "peer", "PEERID", gettext_noop ("peer offering the service we would like to access"), 1, &GNUNET_GETOPT_set_string, &peer_id}, {'s', "service", "NAME", gettext_noop ("name of the service we would like to access"), 1, &GNUNET_GETOPT_set_string, &service_name}, {'t', "tcp", NULL, gettext_noop ("service is offered via TCP"), 0, &GNUNET_GETOPT_set_one, &tcp}, {'u', "udp", NULL, gettext_noop ("service is offered via UDP"), 0, &GNUNET_GETOPT_set_one, &udp}, GNUNET_GETOPT_OPTION_VERBOSE (&verbosity), GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-vpn", gettext_noop ("Setup tunnels via VPN."), options, &run, NULL)) ? ret : 1; GNUNET_free ((void *) argv); return ret; } /* end of gnunet-vpn.c */ gnunet-0.10.1/src/vpn/Makefile.in0000644000175000017500000010452312320752065013460 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = $(am__EXEEXT_1) gnunet-service-vpn$(EXEEXT) bin_PROGRAMS = gnunet-vpn$(EXEEXT) subdir = src/vpn DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/vpn.conf.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = vpn.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libgnunetvpn_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetvpn_la_OBJECTS = vpn_api.lo libgnunetvpn_la_OBJECTS = $(am_libgnunetvpn_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetvpn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetvpn_la_LDFLAGS) $(LDFLAGS) \ -o $@ @LINUX_FALSE@@MINGW_TRUE@am__EXEEXT_1 = gnunet-helper-vpn$(EXEEXT) @LINUX_TRUE@am__EXEEXT_1 = gnunet-helper-vpn$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am__gnunet_helper_vpn_SOURCES_DIST = gnunet-helper-vpn.c \ gnunet-helper-vpn-windows.c @MINGW_FALSE@am_gnunet_helper_vpn_OBJECTS = \ @MINGW_FALSE@ gnunet-helper-vpn.$(OBJEXT) @MINGW_TRUE@am_gnunet_helper_vpn_OBJECTS = \ @MINGW_TRUE@ gnunet-helper-vpn-windows.$(OBJEXT) gnunet_helper_vpn_OBJECTS = $(am_gnunet_helper_vpn_OBJECTS) gnunet_helper_vpn_DEPENDENCIES = gnunet_helper_vpn_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(gnunet_helper_vpn_LDFLAGS) $(LDFLAGS) \ -o $@ am_gnunet_service_vpn_OBJECTS = \ gnunet_service_vpn-gnunet-service-vpn.$(OBJEXT) gnunet_service_vpn_OBJECTS = $(am_gnunet_service_vpn_OBJECTS) am__DEPENDENCIES_1 = gnunet_service_vpn_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/regex/libgnunetregex.la \ $(am__DEPENDENCIES_1) gnunet_service_vpn_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(gnunet_service_vpn_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_gnunet_vpn_OBJECTS = gnunet-vpn.$(OBJEXT) gnunet_vpn_OBJECTS = $(am_gnunet_vpn_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetvpn_la_SOURCES) $(gnunet_helper_vpn_SOURCES) \ $(gnunet_service_vpn_SOURCES) $(gnunet_vpn_SOURCES) DIST_SOURCES = $(libgnunetvpn_la_SOURCES) \ $(am__gnunet_helper_vpn_SOURCES_DIST) \ $(gnunet_service_vpn_SOURCES) $(gnunet_vpn_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined,--export-all-symbols @LINUX_TRUE@VPNBIN = gnunet-helper-vpn @MINGW_TRUE@VPNBIN = gnunet-helper-vpn @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 pkgcfgdir = $(pkgdatadir)/config.d/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ vpn.conf lib_LTLIBRARIES = \ libgnunetvpn.la @MINGW_TRUE@gnunet_helper_vpn_LDFLAGS = \ @MINGW_TRUE@ -no-undefined -Wl,--export-all-symbols @MINGW_TRUE@gnunet_helper_vpn_LDADD = \ @MINGW_TRUE@ -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \ @MINGW_TRUE@ -lcomdlg32 -lgdi32 -liphlpapi @MINGW_FALSE@gnunet_helper_vpn_SOURCES = \ @MINGW_FALSE@ gnunet-helper-vpn.c @MINGW_TRUE@gnunet_helper_vpn_SOURCES = \ @MINGW_TRUE@ gnunet-helper-vpn-windows.c gnunet_service_vpn_SOURCES = \ gnunet-service-vpn.c gnunet_service_vpn_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/regex/libgnunetregex.la \ $(GN_LIBINTL) gnunet_service_vpn_CFLAGS = \ -I$(top_srcdir)/src/exit $(CFLAGS) gnunet_vpn_SOURCES = \ gnunet-vpn.c gnunet_vpn_LDADD = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_vpn_DEPENDENCIES = \ libgnunetvpn.la libgnunetvpn_la_SOURCES = \ vpn_api.c vpn.h libgnunetvpn_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) libgnunetvpn_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/vpn/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/vpn/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): vpn.conf: $(top_builddir)/config.status $(srcdir)/vpn.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetvpn.la: $(libgnunetvpn_la_OBJECTS) $(libgnunetvpn_la_DEPENDENCIES) $(EXTRA_libgnunetvpn_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetvpn_la_LINK) -rpath $(libdir) $(libgnunetvpn_la_OBJECTS) $(libgnunetvpn_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-helper-vpn$(EXEEXT): $(gnunet_helper_vpn_OBJECTS) $(gnunet_helper_vpn_DEPENDENCIES) $(EXTRA_gnunet_helper_vpn_DEPENDENCIES) @rm -f gnunet-helper-vpn$(EXEEXT) $(AM_V_CCLD)$(gnunet_helper_vpn_LINK) $(gnunet_helper_vpn_OBJECTS) $(gnunet_helper_vpn_LDADD) $(LIBS) gnunet-service-vpn$(EXEEXT): $(gnunet_service_vpn_OBJECTS) $(gnunet_service_vpn_DEPENDENCIES) $(EXTRA_gnunet_service_vpn_DEPENDENCIES) @rm -f gnunet-service-vpn$(EXEEXT) $(AM_V_CCLD)$(gnunet_service_vpn_LINK) $(gnunet_service_vpn_OBJECTS) $(gnunet_service_vpn_LDADD) $(LIBS) gnunet-vpn$(EXEEXT): $(gnunet_vpn_OBJECTS) $(gnunet_vpn_DEPENDENCIES) $(EXTRA_gnunet_vpn_DEPENDENCIES) @rm -f gnunet-vpn$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_vpn_OBJECTS) $(gnunet_vpn_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-vpn-windows.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-vpn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-vpn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_vpn-gnunet-service-vpn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vpn_api.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< gnunet_service_vpn-gnunet-service-vpn.o: gnunet-service-vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_vpn_CFLAGS) $(CFLAGS) -MT gnunet_service_vpn-gnunet-service-vpn.o -MD -MP -MF $(DEPDIR)/gnunet_service_vpn-gnunet-service-vpn.Tpo -c -o gnunet_service_vpn-gnunet-service-vpn.o `test -f 'gnunet-service-vpn.c' || echo '$(srcdir)/'`gnunet-service-vpn.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_vpn-gnunet-service-vpn.Tpo $(DEPDIR)/gnunet_service_vpn-gnunet-service-vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-vpn.c' object='gnunet_service_vpn-gnunet-service-vpn.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_vpn_CFLAGS) $(CFLAGS) -c -o gnunet_service_vpn-gnunet-service-vpn.o `test -f 'gnunet-service-vpn.c' || echo '$(srcdir)/'`gnunet-service-vpn.c gnunet_service_vpn-gnunet-service-vpn.obj: gnunet-service-vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_vpn_CFLAGS) $(CFLAGS) -MT gnunet_service_vpn-gnunet-service-vpn.obj -MD -MP -MF $(DEPDIR)/gnunet_service_vpn-gnunet-service-vpn.Tpo -c -o gnunet_service_vpn-gnunet-service-vpn.obj `if test -f 'gnunet-service-vpn.c'; then $(CYGPATH_W) 'gnunet-service-vpn.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-vpn.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_vpn-gnunet-service-vpn.Tpo $(DEPDIR)/gnunet_service_vpn-gnunet-service-vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-vpn.c' object='gnunet_service_vpn-gnunet-service-vpn.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_vpn_CFLAGS) $(CFLAGS) -c -o gnunet_service_vpn-gnunet-service-vpn.obj `if test -f 'gnunet-service-vpn.c'; then $(CYGPATH_W) 'gnunet-service-vpn.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-vpn.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: install-am install-exec-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-exec-hook install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA @LINUX_TRUE@install-exec-hook: @LINUX_TRUE@ $(top_srcdir)/src/vpn/install-vpn-helper.sh $(libexecdir) $(SUDO_BINARY) || true @LINUX_FALSE@install-exec-hook: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/vpn/gnunet-helper-vpn-windows.c0000644000175000017500000014556112267431203016632 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file vpn/gnunet-helper-vpn-windows.c * @brief the helper for the VPN service in win32 builds. * Opens a virtual network-interface, sends data received on the if to stdout, * sends data received on stdin to the interface * @author Christian M. Fuchs * * The following list of people have reviewed this code and considered * it safe since the last modification (if you reviewed it, please * have your name added to the list): * */ #include #include #include #include #ifndef __MINGW64_VERSION_MAJOR #include #include #else #include #include #endif #include #include "platform.h" #include "tap-windows.h" /** * Need 'struct GNUNET_HashCode' and 'struct GNUNET_PeerIdentity'. */ #include "gnunet_crypto_lib.h" /** * Need 'struct GNUNET_MessageHeader'. */ #include "gnunet_common.h" /** * Need VPN message types. */ #include "gnunet_protocols.h" /** * Should we print (interesting|debug) messages that can happen during * normal operation? */ #define DEBUG GNUNET_NO #if DEBUG /* FIXME: define with varargs... */ #define LOG_DEBUG(msg) fprintf (stderr, "%s", msg); #else #define LOG_DEBUG(msg) do {} while (0) #endif /** * Will this binary be run in permissions testing mode? */ static boolean privilege_testing = FALSE; /** * Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE) */ #define MAX_SIZE 65536 /** * Name or Path+Name of our win32 driver. * The .sys and .cat files HAVE to be in the same location as this file! */ #define INF_FILE "share/gnunet/openvpn-tap32/tapw32/OemWin2k.inf" /** * Name or Path+Name of our win64 driver. * The .sys and .cat files HAVE to be in the same location as this file! */ #define INF_FILE64 "share/gnunet/openvpn-tap32/tapw64/OemWin2k.inf" /** * Hardware ID used in the inf-file. * This might change over time, as openvpn advances their driver */ #define HARDWARE_ID "tap0901" /** * Minimum major-id of the driver version we can work with */ #define TAP_WIN_MIN_MAJOR 9 /** * Minimum minor-id of the driver version we can work with. * v <= 7 has buggy IPv6. * v == 8 is broken for small IPv4 Packets */ #define TAP_WIN_MIN_MINOR 9 /** * Time in seconds to wait for our virtual device to go up after telling it to do so. * * openvpn doesn't specify a value, 4 seems sane for testing, even for openwrt * (in fact, 4 was chosen by a fair dice roll...) */ #define TAP32_POSTUP_WAITTIME 4 /** * Location of the network interface list resides in registry. */ #define INTERFACE_REGISTRY_LOCATION "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" /** * Our local process' PID. Used for creating a sufficiently unique additional * hardware ID for our device. */ static char secondary_hwid[LINE_LEN / 2]; /** * Device's visible Name, used to identify a network device in netsh. * eg: "Local Area Connection 9" */ static char device_visible_name[256]; /** * This is our own local instance of a virtual network interface * It is (somewhat) equivalent to using tun/tap in unixoid systems * * Upon initialization, we create such an device node. * Upon termination, we remove it again. * * If we crash this device might stay around. */ static HDEVINFO DeviceInfo = INVALID_HANDLE_VALUE; /** * Registry Key we hand over to windows to spawn a new virtual interface */ static SP_DEVINFO_DATA DeviceNode; /** * GUID of our virtual device in the form of * {12345678-1234-1234-1234-123456789abc} - in hex */ static char device_guid[256]; /** * Possible states of an IO facility. */ enum IO_State { /** * overlapped I/O is ready for work */ IOSTATE_READY = 0, /** * overlapped I/O has been queued */ IOSTATE_QUEUED, /** * overlapped I/O has finished, but is waiting for it's write-partner */ IOSTATE_WAITING, /** * there is a full buffer waiting */ IOSTATE_RESUME, /** * Operlapped IO states for facility objects * overlapped I/O has failed, stop processing */ IOSTATE_FAILED }; /** * A IO Object + read/writebuffer + buffer-size for windows asynchronous IO handling */ struct io_facility { /** * The mode the state machine associated with this object is in. */ enum IO_State facility_state; /** * If the path is open or blocked in general (used for quickly checking) */ BOOL path_open; // BOOL is winbool (int), NOT boolean (unsigned char)! /** * Windows Object-Handle (used for accessing TAP and STDIN/STDOUT) */ HANDLE handle; /** * Overlaped IO structure used for asynchronous IO in windows. */ OVERLAPPED overlapped; /** * Buffer for reading things to and writing from... */ unsigned char buffer[MAX_SIZE]; /** * How much of this buffer was used when reading or how much data can be written */ DWORD buffer_size; /** * Amount of data actually written or read by readfile/writefile. */ DWORD buffer_size_processed; /** * How much of this buffer we have writte in total */ DWORD buffer_size_written; }; /** * ReOpenFile is only available as of XP SP2 and 2003 SP1 */ WINBASEAPI HANDLE WINAPI ReOpenFile (HANDLE, DWORD, DWORD, DWORD); /** * IsWow64Process definition for our is_win64, as this is a kernel function */ typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); /** * Determines if the host OS is win32 or win64 * * @return true if */ BOOL is_win64 () { #if defined(_WIN64) //this is a win64 binary, return TRUE; #elif defined(_WIN32) //this is a 32bit binary, and we need to check if we are running in WOW64 BOOL success = FALSE; BOOL on_wow64 = FALSE; LPFN_ISWOW64PROCESS IsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle ("kernel32"), "IsWow64Process"); if (NULL != IsWow64Process) success = IsWow64Process (GetCurrentProcess (), &on_wow64); return success && on_wow64; #endif } /** * Wrapper for executing a shellcommand in windows. * * @param command - the command + parameters to execute * @return * exitcode of the program executed, * * EINVAL (cmd/file not found) * * EPIPE (could not read STDOUT) */ static int execute_shellcommand (const char *command) { FILE *pipe; if ( (NULL == command) || (NULL == (pipe = _popen (command, "rt"))) ) return EINVAL; #if DEBUG fprintf (stderr, "DEBUG: Command output: \n"); char output[LINE_LEN]; while (NULL != fgets (output, sizeof (output), pipe)) fprintf (stderr, "%s", output); #endif return _pclose (pipe); } /** * @brief Sets the IPv6-Address given in address on the interface dev * * @param address the IPv6-Address * @param prefix_len the length of the network-prefix */ static int set_address6 (const char *address, unsigned long prefix_len) { int ret = EINVAL; char command[LINE_LEN]; struct sockaddr_in6 sa6; /* * parse the new address */ memset (&sa6, 0, sizeof (struct sockaddr_in6)); sa6.sin6_family = AF_INET6; if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr.s6_addr)) { fprintf (stderr, "ERROR: Failed to parse address `%s': %s\n", address, strerror (errno)); return -1; } /* * prepare the command */ snprintf (command, LINE_LEN, "netsh interface ipv6 add address \"%s\" %s/%d store=active", device_visible_name, address, prefix_len); /* * Set the address */ ret = execute_shellcommand (command); /* Did it work?*/ if (0 != ret) fprintf (stderr, "FATAL: Setting IPv6 address failed: %s\n", strerror (ret)); return ret; } /** * @brief Removes the IPv6-Address given in address from the interface dev * * @param address the IPv4-Address */ static void remove_address6 (const char *address) { char command[LINE_LEN]; int ret = EINVAL; // sanity checking was already done in set_address6 /* * prepare the command */ snprintf (command, LINE_LEN, "netsh interface ipv6 delete address \"%s\" store=persistent", device_visible_name); /* * Set the address */ ret = execute_shellcommand (command); /* Did it work?*/ if (0 != ret) fprintf (stderr, "FATAL: removing IPv6 address failed: %s\n", strerror (ret)); } /** * @brief Sets the IPv4-Address given in address on the interface dev * * @param address the IPv4-Address * @param mask the netmask */ static int set_address4 (const char *address, const char *mask) { int ret = EINVAL; char command[LINE_LEN]; struct sockaddr_in addr; addr.sin_family = AF_INET; /* * Parse the address */ if (1 != inet_pton (AF_INET, address, &addr.sin_addr.s_addr)) { fprintf (stderr, "ERROR: Failed to parse address `%s': %s\n", address, strerror (errno)); return -1; } // Set Device to Subnet-Mode? do we really need openvpn/tun.c:2925 ? /* * prepare the command */ snprintf (command, LINE_LEN, "netsh interface ipv4 add address \"%s\" %s %s store=active", device_visible_name, address, mask); /* * Set the address */ ret = execute_shellcommand (command); /* Did it work?*/ if (0 != ret) fprintf (stderr, "FATAL: Setting IPv4 address failed: %s\n", strerror (ret)); return ret; } /** * @brief Removes the IPv4-Address given in address from the interface dev * * @param address the IPv4-Address */ static void remove_address4 (const char *address) { char command[LINE_LEN]; int ret = EINVAL; // sanity checking was already done in set_address4 /* * prepare the command */ snprintf (command, LINE_LEN, "netsh interface ipv4 delete address \"%s\" gateway=all store=persistent", device_visible_name); /* * Set the address */ ret = execute_shellcommand (command); /* Did it work?*/ if (0 != ret) fprintf (stderr, "FATAL: removing IPv4 address failed: %s\n", strerror (ret)); } /** * Setup a new virtual interface to use for tunneling. * * @return: TRUE if setup was successful, else FALSE */ static BOOL setup_interface () { /* * where to find our inf-file. (+ the "full" path, after windows found") * * We do not directly input all the props here, because openvpn will update * these details over time. */ char inf_file_path[MAX_PATH]; char * temp_inf_filename; char hwidlist[LINE_LEN + 4]; char class_name[128]; GUID class_guid; int str_length = 0; /** * Set the device's hardware ID and add it to a list. * This information will later on identify this device in registry. */ strncpy (hwidlist, HARDWARE_ID, LINE_LEN); /** * this is kind of over-complicated, but allows keeps things independent of * how the openvpn-hwid is actually stored. * * A HWID list is double-\0 terminated and \0 separated */ str_length = strlen (hwidlist) + 1; strncpy (&hwidlist[str_length], secondary_hwid, LINE_LEN); str_length += strlen (&hwidlist[str_length]) + 1; /** * Locate the inf-file, we need to store it somewhere where the system can * find it. We need to pick the correct driver for win32/win64. */ if (is_win64()) GetFullPathNameA (INF_FILE64, MAX_PATH, inf_file_path, &temp_inf_filename); else GetFullPathNameA (INF_FILE, MAX_PATH, inf_file_path, &temp_inf_filename); fprintf (stderr, "INFO: Located our driver's .inf file at %s\n", inf_file_path); /** * Bootstrap our device info using the drivers inf-file */ if ( ! SetupDiGetINFClassA (inf_file_path, &class_guid, class_name, sizeof (class_name) / sizeof (char), NULL)) return FALSE; /** * Collect all the other needed information... * let the system fill our this form */ DeviceInfo = SetupDiCreateDeviceInfoList (&class_guid, NULL); if (DeviceInfo == INVALID_HANDLE_VALUE) return FALSE; DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA); if ( ! SetupDiCreateDeviceInfoA (DeviceInfo, class_name, &class_guid, NULL, 0, DICD_GENERATE_ID, &DeviceNode)) return FALSE; /* Deploy all the information collected into the registry */ if ( ! SetupDiSetDeviceRegistryPropertyA (DeviceInfo, &DeviceNode, SPDRP_HARDWAREID, (LPBYTE) hwidlist, str_length * sizeof (char))) return FALSE; /* Install our new class(=device) into the system */ if ( ! SetupDiCallClassInstaller (DIF_REGISTERDEVICE, DeviceInfo, &DeviceNode)) return FALSE; /* This system call tends to take a while (several seconds!) on "modern" Windoze systems */ if ( ! UpdateDriverForPlugAndPlayDevicesA (NULL, secondary_hwid, inf_file_path, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, NULL)) //reboot required? NEVER! return FALSE; fprintf (stderr, "DEBUG: successfully created a network device\n"); return TRUE; } /** * Remove our new virtual interface to use for tunneling. * This function must be called AFTER setup_interface! * * @return: TRUE if destruction was successful, else FALSE */ static BOOL remove_interface () { SP_REMOVEDEVICE_PARAMS remove; if (INVALID_HANDLE_VALUE == DeviceInfo) return FALSE; remove.ClassInstallHeader.cbSize = sizeof (SP_CLASSINSTALL_HEADER); remove.HwProfile = 0; remove.Scope = DI_REMOVEDEVICE_GLOBAL; remove.ClassInstallHeader.InstallFunction = DIF_REMOVE; /* * 1. Prepare our existing device information set, and place the * uninstall related information into the structure */ if ( ! SetupDiSetClassInstallParamsA (DeviceInfo, (PSP_DEVINFO_DATA) & DeviceNode, &remove.ClassInstallHeader, sizeof (remove))) return FALSE; /* * 2. Uninstall the virtual interface using the class installer */ if ( ! SetupDiCallClassInstaller (DIF_REMOVE, DeviceInfo, (PSP_DEVINFO_DATA) & DeviceNode)) return FALSE; SetupDiDestroyDeviceInfoList (DeviceInfo); fprintf (stderr, "DEBUG: removed interface successfully\n"); return TRUE; } /** * Do all the lookup necessary to retrieve the inteface's actual name * off the registry. * * @return: TRUE if we were able to lookup the interface's name, else FALSE */ static BOOL resolve_interface_name () { SP_DEVINFO_LIST_DETAIL_DATA device_details; char pnp_instance_id [MAX_DEVICE_ID_LEN]; HKEY adapter_key_handle; LONG status; DWORD len; int i = 0; int retrys; BOOL retval = FALSE; char adapter[] = INTERFACE_REGISTRY_LOCATION; /* We can obtain the PNP instance ID from our setupapi handle */ device_details.cbSize = sizeof (device_details); if (CR_SUCCESS != CM_Get_Device_ID_ExA (DeviceNode.DevInst, (PCHAR) pnp_instance_id, MAX_DEVICE_ID_LEN, 0, //must be 0 NULL)) //hMachine, we are local return FALSE; fprintf (stderr, "DEBUG: Resolving interface name for network device %s\n",pnp_instance_id); /* Registry is incredibly slow, retry for up to 30 seconds to allow registry to refresh */ for (retrys = 0; retrys < 120 && !retval; retrys++) { /* sleep for 250ms*/ Sleep (250); /* Now we can use this ID to locate the correct networks interface in registry */ if (ERROR_SUCCESS != RegOpenKeyExA ( HKEY_LOCAL_MACHINE, adapter, 0, KEY_READ, &adapter_key_handle)) return FALSE; /* Of course there is a multitude of entries here, with arbitrary names, * thus we need to iterate through there. */ while (!retval) { char instance_key[256]; char query_key [256]; HKEY instance_key_handle; char pnpinstanceid_name[] = "PnpInstanceID"; char pnpinstanceid_value[256]; char adaptername_name[] = "Name"; DWORD data_type; len = 256 * sizeof (char); /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */ status = RegEnumKeyExA ( adapter_key_handle, i, instance_key, &len, NULL, NULL, NULL, NULL); /* this may fail due to one of two reasons: * we are at the end of the list*/ if (ERROR_NO_MORE_ITEMS == status) break; // * we found a broken registry key, continue with the next key. if (ERROR_SUCCESS != status) goto cleanup; /* prepare our new query string: */ snprintf (query_key, 256, "%s\\%s\\Connection", adapter, instance_key); /* look inside instance_key\\Connection */ if (ERROR_SUCCESS != RegOpenKeyExA ( HKEY_LOCAL_MACHINE, query_key, 0, KEY_READ, &instance_key_handle)) goto cleanup; /* now, read our PnpInstanceID */ len = sizeof (pnpinstanceid_value); status = RegQueryValueExA (instance_key_handle, pnpinstanceid_name, NULL, //reserved, always NULL according to MSDN &data_type, (LPBYTE) pnpinstanceid_value, &len); if (status != ERROR_SUCCESS || data_type != REG_SZ) goto cleanup; /* compare the value we got to our devices PNPInstanceID*/ if (0 != strncmp (pnpinstanceid_value, pnp_instance_id, sizeof (pnpinstanceid_value) / sizeof (char))) goto cleanup; len = sizeof (device_visible_name); status = RegQueryValueExA ( instance_key_handle, adaptername_name, NULL, //reserved, always NULL according to MSDN &data_type, (LPBYTE) device_visible_name, &len); if (status != ERROR_SUCCESS || data_type != REG_SZ) goto cleanup; /* * we have successfully found OUR instance, * save the device GUID before exiting */ strncpy (device_guid, instance_key, 256); retval = TRUE; fprintf (stderr, "DEBUG: Interface Name lookup succeeded on retry %d, got \"%s\" %s\n", retrys, device_visible_name, device_guid); cleanup: RegCloseKey (instance_key_handle); ++i; } RegCloseKey (adapter_key_handle); } return retval; } /** * Determines the version of the installed TAP32 driver and checks if it's sufficiently new for GNUNET * * @param handle the handle to our tap device * @return TRUE if the version is sufficient, else FALSE */ static BOOL check_tapw32_version (HANDLE handle) { ULONG version[3]; DWORD len; memset (&(version), 0, sizeof (version)); if (DeviceIoControl (handle, TAP_WIN_IOCTL_GET_VERSION, &version, sizeof (version), &version, sizeof (version), &len, NULL)) fprintf (stderr, "INFO: TAP-Windows Driver Version %d.%d %s\n", (int) version[0], (int) version[1], (version[2] ? "(DEBUG)" : "")); if ((version[0] != TAP_WIN_MIN_MAJOR) || (version[1] < TAP_WIN_MIN_MINOR )){ fprintf (stderr, "FATAL: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d\n", TAP_WIN_MIN_MAJOR, TAP_WIN_MIN_MINOR); return FALSE; } return TRUE; } /** * Creates a tun-interface called dev; * * @return the fd to the tun or -1 on error */ static HANDLE init_tun () { char device_path[256]; HANDLE handle; if (! setup_interface ()) { errno = ENODEV; return INVALID_HANDLE_VALUE; } if (! resolve_interface_name ()) { errno = ENODEV; return INVALID_HANDLE_VALUE; } /* Open Windows TAP-Windows adapter */ snprintf (device_path, sizeof (device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid, TAP_WIN_SUFFIX); handle = CreateFile ( device_path, GENERIC_READ | GENERIC_WRITE, 0, /* was: FILE_SHARE_READ */ 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0 ); if (INVALID_HANDLE_VALUE == handle) { fprintf (stderr, "FATAL: CreateFile failed on TAP device: %s\n", device_path); return handle; } /* get driver version info */ if (! check_tapw32_version (handle)) { CloseHandle (handle); return INVALID_HANDLE_VALUE; } /* TODO (opt?): get MTU-Size */ fprintf (stderr, "DEBUG: successfully opened TAP device\n"); return handle; } /** * Brings a TAP device up and sets it to connected state. * * @param handle the handle to our TAP device * @return True if the operation succeeded, else false */ static BOOL tun_up (HANDLE handle) { ULONG status = TRUE; DWORD len; if (! DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, &status, sizeof (status), &status, sizeof (status), &len, NULL)) { fprintf (stderr, "FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)\n"); return FALSE; } /* Wait for the device to go UP, might take some time. */ Sleep (TAP32_POSTUP_WAITTIME * 1000); fprintf (stderr, "DEBUG: successfully set TAP device to UP\n"); return TRUE; } /** * Attempts to read off an input facility (tap or named pipe) in overlapped mode. * * 1. * If the input facility is in IOSTATE_READY, it will issue a new read operation to the * input handle. Then it goes into IOSTATE_QUEUED state. * In case the read succeeded instantly the input facility enters 3. * * 2. * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already. * If it has finished, go to state 3. * If it has failed, set IOSTATE_FAILED * * 3. * If the output facility is in state IOSTATE_READY, the read-buffer is copied to the output buffer. * The input facility enters state IOSTATE_READY * The output facility enters state IOSTATE_READY * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING * * IOSTATE_WAITING is reset by the output facility, once it has completed. * * @param input_facility input named pipe or file to work with. * @param output_facility output pipe or file to hand over data to. * @return false if an event reset was impossible (OS error), else true */ static BOOL attempt_read_tap (struct io_facility * input_facility, struct io_facility * output_facility) { struct GNUNET_MessageHeader * hdr; unsigned short size; switch (input_facility->facility_state) { case IOSTATE_READY: { if (! ResetEvent (input_facility->overlapped.hEvent)) { return FALSE; } input_facility->buffer_size = 0; /* Check how the task is handled */ if (ReadFile (input_facility->handle, input_facility->buffer, sizeof (input_facility->buffer) - sizeof (struct GNUNET_MessageHeader), &input_facility->buffer_size, &input_facility->overlapped)) {/* async event processed immediately*/ /* reset event manually*/ if (! SetEvent (input_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: tap read succeeded immediately\n"); /* we successfully read something from the TAP and now need to * send it our via STDOUT. Is that possible at the moment? */ if ((IOSTATE_READY == output_facility->facility_state || IOSTATE_WAITING == output_facility->facility_state) && (0 < input_facility->buffer_size)) { /* hand over this buffers content and apply message header for gnunet */ hdr = (struct GNUNET_MessageHeader *) output_facility->buffer; size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader); memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer, input_facility->buffer_size); output_facility->buffer_size = size; hdr->size = htons (size); hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); output_facility->facility_state = IOSTATE_READY; } else if (0 < input_facility->buffer_size) /* If we have have read our buffer, wait for our write-partner*/ input_facility->facility_state = IOSTATE_WAITING; } else /* operation was either queued or failed*/ { int err = GetLastError (); if (ERROR_IO_PENDING == err) { /* operation queued */ input_facility->facility_state = IOSTATE_QUEUED; } else { /* error occurred, let the rest of the elements finish */ input_facility->path_open = FALSE; input_facility->facility_state = IOSTATE_FAILED; if (IOSTATE_WAITING == output_facility->facility_state) output_facility->path_open = FALSE; fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish\n"); } } } return TRUE; // We are queued and should check if the read has finished case IOSTATE_QUEUED: { // there was an operation going on already, check if that has completed now. if (GetOverlappedResult (input_facility->handle, &input_facility->overlapped, &input_facility->buffer_size, FALSE)) {/* successful return for a queued operation */ if (! ResetEvent (input_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: tap read succeeded delayed\n"); /* we successfully read something from the TAP and now need to * send it our via STDOUT. Is that possible at the moment? */ if ((IOSTATE_READY == output_facility->facility_state || IOSTATE_WAITING == output_facility->facility_state) && 0 < input_facility->buffer_size) { /* hand over this buffers content and apply message header for gnunet */ hdr = (struct GNUNET_MessageHeader *) output_facility->buffer; size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader); memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer, input_facility->buffer_size); output_facility->buffer_size = size; hdr->size = htons(size); hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; } else if (0 < input_facility->buffer_size) { /* If we have have read our buffer, wait for our write-partner*/ input_facility->facility_state = IOSTATE_WAITING; // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? } } else { /* operation still pending/queued or failed? */ int err = GetLastError (); if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err)) { /* error occurred, let the rest of the elements finish */ input_facility->path_open = FALSE; input_facility->facility_state = IOSTATE_FAILED; if (IOSTATE_WAITING == output_facility->facility_state) output_facility->path_open = FALSE; fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish\n"); } } } return TRUE; case IOSTATE_RESUME: hdr = (struct GNUNET_MessageHeader *) output_facility->buffer; size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader); memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer, input_facility->buffer_size); output_facility->buffer_size = size; hdr->size = htons (size); hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; return TRUE; default: return TRUE; } } /** * Attempts to read off an input facility (tap or named pipe) in overlapped mode. * * 1. * If the input facility is in IOSTATE_READY, it will issue a new read operation to the * input handle. Then it goes into IOSTATE_QUEUED state. * In case the read succeeded instantly the input facility enters 3. * * 2. * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already. * If it has finished, go to state 3. * If it has failed, set IOSTATE_FAILED * * 3. * If the facility is finished with ready * The read-buffer is copied to the output buffer, except for the GNUNET_MessageHeader. * The input facility enters state IOSTATE_READY * The output facility enters state IOSTATE_READY * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING * * IOSTATE_WAITING is reset by the output facility, once it has completed. * * @param input_facility input named pipe or file to work with. * @param output_facility output pipe or file to hand over data to. * @return false if an event reset was impossible (OS error), else true */ static BOOL attempt_read_stdin (struct io_facility * input_facility, struct io_facility * output_facility) { struct GNUNET_MessageHeader * hdr; switch (input_facility->facility_state) { case IOSTATE_READY: { input_facility->buffer_size = 0; partial_read_iostate_ready: if (! ResetEvent (input_facility->overlapped.hEvent)) return FALSE; /* Check how the task is handled */ if (ReadFile (input_facility->handle, input_facility->buffer + input_facility->buffer_size, sizeof (input_facility->buffer) - input_facility->buffer_size, &input_facility->buffer_size_processed, &input_facility->overlapped)) {/* async event processed immediately*/ hdr = (struct GNUNET_MessageHeader *) input_facility->buffer; /* reset event manually*/ if (!SetEvent (input_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: stdin read succeeded immediately\n"); input_facility->buffer_size += input_facility->buffer_size_processed; if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER || ntohs (hdr->size) > sizeof (input_facility->buffer)) { fprintf (stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs (hdr->type), ntohs (hdr->size)); input_facility->facility_state = IOSTATE_READY; return TRUE; } /* we got the a part of a packet */ if (ntohs (hdr->size) > input_facility->buffer_size) goto partial_read_iostate_ready; /* have we read more than 0 bytes of payload? (sizeread > header)*/ if (input_facility->buffer_size > sizeof (struct GNUNET_MessageHeader) && ((IOSTATE_READY == output_facility->facility_state) || (IOSTATE_WAITING == output_facility->facility_state))) {/* we successfully read something from the TAP and now need to * send it our via STDOUT. Is that possible at the moment? */ /* hand over this buffers content and strip gnunet message header */ memcpy (output_facility->buffer, input_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader)); output_facility->buffer_size = input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; } else if (input_facility->buffer_size > sizeof (struct GNUNET_MessageHeader)) /* If we have have read our buffer, wait for our write-partner*/ input_facility->facility_state = IOSTATE_WAITING; else /* we read nothing */ input_facility->facility_state = IOSTATE_READY; } else /* operation was either queued or failed*/ { int err = GetLastError (); if (ERROR_IO_PENDING == err) /* operation queued */ input_facility->facility_state = IOSTATE_QUEUED; else { /* error occurred, let the rest of the elements finish */ input_facility->path_open = FALSE; input_facility->facility_state = IOSTATE_FAILED; if (IOSTATE_WAITING == output_facility->facility_state) output_facility->path_open = FALSE; fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish\n"); } } } return TRUE; // We are queued and should check if the read has finished case IOSTATE_QUEUED: { // there was an operation going on already, check if that has completed now. if (GetOverlappedResult (input_facility->handle, &input_facility->overlapped, &input_facility->buffer_size_processed, FALSE)) {/* successful return for a queued operation */ hdr = (struct GNUNET_MessageHeader *) input_facility->buffer; if (! ResetEvent (input_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: stdin read succeeded delayed\n"); input_facility->buffer_size += input_facility->buffer_size_processed; if ((ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) || (ntohs (hdr->size) > sizeof (input_facility->buffer))) { fprintf (stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs (hdr->type), ntohs (hdr->size)); input_facility->facility_state = IOSTATE_READY; return TRUE; } /* we got the a part of a packet */ if (ntohs (hdr->size) > input_facility->buffer_size ); goto partial_read_iostate_ready; /* we successfully read something from the TAP and now need to * send it our via STDOUT. Is that possible at the moment? */ if ((IOSTATE_READY == output_facility->facility_state || IOSTATE_WAITING == output_facility->facility_state) && input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader)) { /* hand over this buffers content and strip gnunet message header */ memcpy (output_facility->buffer, input_facility->buffer + sizeof(struct GNUNET_MessageHeader), input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader)); output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; } else if (input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader)) input_facility->facility_state = IOSTATE_WAITING; else input_facility->facility_state = IOSTATE_READY; } else { /* operation still pending/queued or failed? */ int err = GetLastError (); if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err)) { /* error occurred, let the rest of the elements finish */ input_facility->path_open = FALSE; input_facility->facility_state = IOSTATE_FAILED; if (IOSTATE_WAITING == output_facility->facility_state) output_facility->path_open = FALSE; fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish\n"); } } } return TRUE; case IOSTATE_RESUME: /* Our buffer was filled already but our write facility was busy. */ memcpy (output_facility->buffer, input_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader)); output_facility->buffer_size = input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; return TRUE; default: return TRUE; } } /** * Attempts to write to an output facility (tap or named pipe) in overlapped mode. * * TODO: high level description * * @param output_facility output pipe or file to hand over data to. * @param input_facility input named pipe or file to work with. * @return false if an event reset was impossible (OS error), else true */ static BOOL attempt_write (struct io_facility * output_facility, struct io_facility * input_facility) { switch (output_facility->facility_state) { case IOSTATE_READY: output_facility->buffer_size_written = 0; continue_partial_write: if (! ResetEvent (output_facility->overlapped.hEvent)) return FALSE; /* Check how the task was handled */ if (WriteFile (output_facility->handle, output_facility->buffer + output_facility->buffer_size_written, output_facility->buffer_size - output_facility->buffer_size_written, &output_facility->buffer_size_processed, &output_facility->overlapped)) {/* async event processed immediately*/ fprintf (stderr, "DEBUG: write succeeded immediately\n"); output_facility->buffer_size_written += output_facility->buffer_size_processed; /* reset event manually*/ if (! SetEvent (output_facility->overlapped.hEvent)) return FALSE; /* partial write */ if (output_facility->buffer_size_written < output_facility->buffer_size) goto continue_partial_write; /* we are now waiting for our buffer to be filled*/ output_facility->facility_state = IOSTATE_WAITING; /* we successfully wrote something and now need to reset our reader */ if (IOSTATE_WAITING == input_facility->facility_state) input_facility->facility_state = IOSTATE_RESUME; else if (IOSTATE_FAILED == input_facility->facility_state) output_facility->path_open = FALSE; } else /* operation was either queued or failed*/ { int err = GetLastError (); if (ERROR_IO_PENDING == err) { /* operation queued */ output_facility->facility_state = IOSTATE_QUEUED; } else { /* error occurred, close this path */ output_facility->path_open = FALSE; output_facility->facility_state = IOSTATE_FAILED; fprintf (stderr, "FATAL: Write to handle failed, exiting\n"); } } return TRUE; case IOSTATE_QUEUED: // there was an operation going on already, check if that has completed now. if (GetOverlappedResult (output_facility->handle, &output_facility->overlapped, &output_facility->buffer_size_processed, FALSE)) {/* successful return for a queued operation */ if (! ResetEvent (output_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: write succeeded delayed\n"); output_facility->buffer_size_written += output_facility->buffer_size_processed; /* partial write */ if (output_facility->buffer_size_written < output_facility->buffer_size) goto continue_partial_write; /* we are now waiting for our buffer to be filled*/ output_facility->facility_state = IOSTATE_WAITING; /* we successfully wrote something and now need to reset our reader */ if (IOSTATE_WAITING == input_facility->facility_state) input_facility->facility_state = IOSTATE_RESUME; else if (IOSTATE_FAILED == input_facility->facility_state) output_facility->path_open = FALSE; } else { /* operation still pending/queued or failed? */ int err = GetLastError (); if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err)) { /* error occurred, close this path */ output_facility->path_open = FALSE; output_facility->facility_state = IOSTATE_FAILED; fprintf (stderr, "FATAL: Write to handle failed, exiting\n"); } } default: return TRUE; } } /** * Initialize a overlapped structure * * @param elem the element to initilize * @param initial_state the initial state for this instance * @param signaled if the hEvent created should default to signaled or not * @return true on success, else false */ static BOOL initialize_io_facility (struct io_facility * elem, int initial_state, BOOL signaled) { elem->path_open = TRUE; elem->handle = INVALID_HANDLE_VALUE; elem->facility_state = initial_state; elem->buffer_size = 0; elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL); if (NULL == elem->overlapped.hEvent) return FALSE; return TRUE; } /** * Start forwarding to and from the tunnel. * * @param tap_handle device handle for interacting with the Virtual interface */ static void run (HANDLE tap_handle) { /* IO-Facility for reading from our virtual interface */ struct io_facility tap_read; /* IO-Facility for writing to our virtual interface */ struct io_facility tap_write; /* IO-Facility for reading from stdin */ struct io_facility std_in; /* IO-Facility for writing to stdout */ struct io_facility std_out; HANDLE parent_std_in_handle = GetStdHandle (STD_INPUT_HANDLE); HANDLE parent_std_out_handle = GetStdHandle (STD_OUTPUT_HANDLE); /* tun up: */ /* we do this HERE and not beforehand (in init_tun()), in contrast to openvpn * to remove the need to flush the arp cache, handle DHCP and wrong IPs. * * DHCP and such are all features we will never use in gnunet afaik. * But for openvpn those are essential. */ if ((privilege_testing) || (! tun_up (tap_handle))) goto teardown_final; /* Initialize our overlapped IO structures*/ if (! (initialize_io_facility (&tap_read, IOSTATE_READY, FALSE) && initialize_io_facility (&tap_write, IOSTATE_WAITING, TRUE) && initialize_io_facility (&std_in, IOSTATE_READY, FALSE) && initialize_io_facility (&std_out, IOSTATE_WAITING, TRUE))) goto teardown_final; /* Handles for STDIN and STDOUT */ tap_read.handle = tap_handle; tap_write.handle = tap_handle; #ifdef DEBUG_TO_CONSOLE /* Debug output to console STDIN/STDOUT*/ std_in.handle = parent_std_in_handle; std_out.handle = parent_std_out_handle; #else fprintf (stderr, "DEBUG: reopening stdin/out for overlapped IO\n"); /* * Find out the types of our handles. * This part is a problem, because in windows we need to handle files, * pipes and the console differently. */ if ((FILE_TYPE_PIPE != GetFileType (parent_std_in_handle)) || (FILE_TYPE_PIPE != GetFileType (parent_std_out_handle))) { fprintf (stderr, "ERROR: stdin/stdout must be named pipes\n"); goto teardown; } std_in.handle = ReOpenFile (parent_std_in_handle, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, FILE_FLAG_OVERLAPPED); if (INVALID_HANDLE_VALUE == std_in.handle) { fprintf (stderr, "FATAL: Could not reopen stdin for in overlapped mode, has to be a named pipe\n"); goto teardown; } std_out.handle = ReOpenFile (parent_std_out_handle, GENERIC_WRITE, FILE_SHARE_READ, FILE_FLAG_OVERLAPPED); if (INVALID_HANDLE_VALUE == std_out.handle) { fprintf (stderr, "FATAL: Could not reopen stdout for in overlapped mode, has to be a named pipe\n"); goto teardown; } #endif fprintf (stderr, "DEBUG: mainloop has begun\n"); while (std_out.path_open || tap_write.path_open) { /* perform READ from stdin if possible */ if (std_in.path_open && (! attempt_read_stdin (&std_in, &tap_write))) break; /* perform READ from tap if possible */ if (tap_read.path_open && (! attempt_read_tap (&tap_read, &std_out))) break; /* perform WRITE to tap if possible */ if (tap_write.path_open && (! attempt_write (&tap_write, &std_in))) break; /* perform WRITE to STDOUT if possible */ if (std_out.path_open && (! attempt_write (&std_out, &tap_read))) break; } fprintf (stderr, "DEBUG: teardown initiated\n"); teardown: CancelIo (tap_handle); CancelIo (std_in.handle); CancelIo (std_out.handle); teardown_final: CloseHandle (tap_handle); } /** * Open VPN tunnel interface. * * @param argc must be 6 * @param argv 0: binary name (gnunet-helper-vpn) * [1: dryrun/testrun (does not execute mainloop)] * 2: tunnel interface prefix (gnunet-vpn) * 3: IPv6 address (::1), "-" to disable * 4: IPv6 netmask length in bits (64), ignored if #2 is "-" * 5: IPv4 address (1.2.3.4), "-" to disable * 6: IPv4 netmask (255.255.0.0), ignored if #4 is "-" */ int main (int argc, char **argv) { char hwid[LINE_LEN]; HANDLE handle; int global_ret = 0; BOOL have_ip4 = FALSE; BOOL have_ip6 = FALSE; if (argc > 1 && 0 == strcmp (argv[1], "-d")){ privilege_testing = TRUE; fprintf (stderr, "%s", "DEBUG: Running binary in privilege testing mode."); argv++; argc--; } if (6 != argc) { fprintf (stderr, "%s", "FATAL: must supply 5 arguments\nUsage:\ngnunet-helper-vpn [-d] \n"); return 1; } strncpy (hwid, argv[1], LINE_LEN); hwid[LINE_LEN - 1] = '\0'; /* * We use our PID for finding/resolving the control-panel name of our virtual * device. PIDs are (of course) unique at runtime, thus we can safely use it * as additional hardware-id for our device. */ snprintf (secondary_hwid, LINE_LEN / 2, "%s-%d", hwid, _getpid ()); if (INVALID_HANDLE_VALUE == (handle = init_tun ())) { fprintf (stderr, "FATAL: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n", hwid, argv[2], argv[3], argv[4], argv[5]); global_ret = -1; goto cleanup; } fprintf (stderr, "DEBUG: Setting IPs, if needed\n"); if (0 != strcmp (argv[2], "-")) { const char *address = argv[2]; long prefix_len = atol (argv[3]); if ((prefix_len < 1) || (prefix_len > 127)) { fprintf (stderr, "FATAL: ipv6 prefix_len out of range\n"); global_ret = -1; goto cleanup; } fprintf (stderr, "DEBUG: Setting IP6 address: %s/%d\n",address,prefix_len); if (0 != (global_ret = set_address6 (address, prefix_len))) goto cleanup; have_ip6 = TRUE; } if (0 != strcmp (argv[4], "-")) { const char *address = argv[4]; const char *mask = argv[5]; fprintf (stderr, "DEBUG: Setting IP4 address: %s/%s\n",address,mask); if (0 != (global_ret = set_address4 (address, mask))) goto cleanup; have_ip4 = TRUE; } run (handle); cleanup: if (have_ip4) { const char *address = argv[4]; fprintf (stderr, "DEBUG: Removing IP4 address\n"); remove_address4 (address); } if (have_ip6) { const char *address = argv[2]; fprintf (stderr, "DEBUG: Removing IP6 address\n"); remove_address6 (address); } fprintf (stderr, "DEBUG: removing interface\n"); remove_interface (); fprintf (stderr, "DEBUG: graceful exit completed\n"); return global_ret; } gnunet-0.10.1/src/vpn/Makefile.am0000644000175000017500000000343212320751520013437 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined,--export-all-symbols VPNBIN = gnunet-helper-vpn endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ vpn.conf if LINUX VPNBIN = gnunet-helper-vpn install-exec-hook: $(top_srcdir)/src/vpn/install-vpn-helper.sh $(libexecdir) $(SUDO_BINARY) || true else install-exec-hook: endif lib_LTLIBRARIES = \ libgnunetvpn.la libexec_PROGRAMS = \ $(VPNBIN) \ gnunet-service-vpn bin_PROGRAMS = \ gnunet-vpn if MINGW gnunet_helper_vpn_LDFLAGS = \ -no-undefined -Wl,--export-all-symbols gnunet_helper_vpn_LDADD = \ -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \ -lcomdlg32 -lgdi32 -liphlpapi gnunet_helper_vpn_SOURCES = \ gnunet-helper-vpn-windows.c else gnunet_helper_vpn_SOURCES = \ gnunet-helper-vpn.c endif gnunet_service_vpn_SOURCES = \ gnunet-service-vpn.c gnunet_service_vpn_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/regex/libgnunetregex.la \ $(GN_LIBINTL) gnunet_service_vpn_CFLAGS = \ -I$(top_srcdir)/src/exit $(CFLAGS) gnunet_vpn_SOURCES = \ gnunet-vpn.c gnunet_vpn_LDADD = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_vpn_DEPENDENCIES = \ libgnunetvpn.la libgnunetvpn_la_SOURCES = \ vpn_api.c vpn.h libgnunetvpn_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) libgnunetvpn_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) gnunet-0.10.1/src/vpn/gnunet-helper-vpn.c0000644000175000017500000003470112225777501015143 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file vpn/gnunet-helper-vpn.c * @brief the helper for the VPN service. Opens a virtual network-interface, * sends data received on the if to stdout, sends data received on stdin to the * interface * @author Philipp Tölke * @author Christian Grothoff * * The following list of people have reviewed this code and considered * it safe since the last modification (if you reviewed it, please * have your name added to the list): * * - Philipp Tölke */ #include "platform.h" #include /** * Need 'struct GNUNET_MessageHeader'. */ #include "gnunet_crypto_lib.h" #include "gnunet_common.h" /** * Need VPN message types. */ #include "gnunet_protocols.h" /** * Should we print (interesting|debug) messages that can happen during * normal operation? */ #define DEBUG GNUNET_NO /** * Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE) */ #define MAX_SIZE 65536 #ifndef _LINUX_IN6_H /** * This is in linux/include/net/ipv6.h, but not always exported... */ struct in6_ifreq { struct in6_addr ifr6_addr; uint32_t ifr6_prefixlen; unsigned int ifr6_ifindex; }; #endif /** * Creates a tun-interface called dev; * * @param dev is asumed to point to a char[IFNAMSIZ] * if *dev == '\\0', uses the name supplied by the kernel; * @return the fd to the tun or -1 on error */ static int init_tun (char *dev) { struct ifreq ifr; int fd; if (NULL == dev) { errno = EINVAL; return -1; } if (-1 == (fd = open ("/dev/net/tun", O_RDWR))) { fprintf (stderr, "Error opening `%s': %s\n", "/dev/net/tun", strerror (errno)); return -1; } if (fd >= FD_SETSIZE) { fprintf (stderr, "File descriptor to large: %d", fd); (void) close (fd); return -1; } memset (&ifr, 0, sizeof (ifr)); ifr.ifr_flags = IFF_TUN; if ('\0' != *dev) strncpy (ifr.ifr_name, dev, IFNAMSIZ); if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr)) { fprintf (stderr, "Error with ioctl on `%s': %s\n", "/dev/net/tun", strerror (errno)); (void) close (fd); return -1; } strcpy (dev, ifr.ifr_name); return fd; } /** * @brief Sets the IPv6-Address given in address on the interface dev * * @param dev the interface to configure * @param address the IPv6-Address * @param prefix_len the length of the network-prefix */ static void set_address6 (const char *dev, const char *address, unsigned long prefix_len) { struct ifreq ifr; struct in6_ifreq ifr6; struct sockaddr_in6 sa6; int fd; /* * parse the new address */ memset (&sa6, 0, sizeof (struct sockaddr_in6)); sa6.sin6_family = AF_INET6; if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr)) { fprintf (stderr, "Failed to parse address `%s': %s\n", address, strerror (errno)); exit (1); } if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0))) { fprintf (stderr, "Error creating socket: %s\n", strerror (errno)); exit (1); } memset (&ifr, 0, sizeof (struct ifreq)); /* * Get the index of the if */ strncpy (ifr.ifr_name, dev, IFNAMSIZ); if (-1 == ioctl (fd, SIOGIFINDEX, &ifr)) { fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } memset (&ifr6, 0, sizeof (struct in6_ifreq)); ifr6.ifr6_addr = sa6.sin6_addr; ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; /* * Set the address */ if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Get the flags */ if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Add the UP and RUNNING flags */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } if (0 != close (fd)) { fprintf (stderr, "close failed: %s\n", strerror (errno)); exit (1); } } /** * @brief Sets the IPv4-Address given in address on the interface dev * * @param dev the interface to configure * @param address the IPv4-Address * @param mask the netmask */ static void set_address4 (const char *dev, const char *address, const char *mask) { int fd; struct sockaddr_in *addr; struct ifreq ifr; memset (&ifr, 0, sizeof (struct ifreq)); addr = (struct sockaddr_in *) &(ifr.ifr_addr); addr->sin_family = AF_INET; /* * Parse the address */ if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr)) { fprintf (stderr, "Failed to parse address `%s': %s\n", address, strerror (errno)); exit (1); } if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0))) { fprintf (stderr, "Error creating socket: %s\n", strerror (errno)); exit (1); } strncpy (ifr.ifr_name, dev, IFNAMSIZ); /* * Set the address */ if (-1 == ioctl (fd, SIOCSIFADDR, &ifr)) { fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Parse the netmask */ addr = (struct sockaddr_in *) &(ifr.ifr_netmask); if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr)) { fprintf (stderr, "Failed to parse address `%s': %s\n", mask, strerror (errno)); (void) close (fd); exit (1); } /* * Set the netmask */ if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Get the flags */ if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Add the UP and RUNNING flags */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } if (0 != close (fd)) { fprintf (stderr, "close failed: %s\n", strerror (errno)); (void) close (fd); exit (1); } } /** * Start forwarding to and from the tunnel. * * @param fd_tun tunnel FD */ static void run (int fd_tun) { /* * The buffer filled by reading from fd_tun */ unsigned char buftun[MAX_SIZE]; ssize_t buftun_size = 0; unsigned char *buftun_read = NULL; /* * The buffer filled by reading from stdin */ unsigned char bufin[MAX_SIZE]; ssize_t bufin_size = 0; size_t bufin_rpos = 0; unsigned char *bufin_read = NULL; fd_set fds_w; fd_set fds_r; /* read refers to reading from fd_tun, writing to stdout */ int read_open = 1; /* write refers to reading from stdin, writing to fd_tun */ int write_open = 1; while ((1 == read_open) || (1 == write_open)) { FD_ZERO (&fds_w); FD_ZERO (&fds_r); /* * We are supposed to read and the buffer is empty * -> select on read from tun */ if (read_open && (0 == buftun_size)) FD_SET (fd_tun, &fds_r); /* * We are supposed to read and the buffer is not empty * -> select on write to stdout */ if (read_open && (0 != buftun_size)) FD_SET (1, &fds_w); /* * We are supposed to write and the buffer is empty * -> select on read from stdin */ if (write_open && (NULL == bufin_read)) FD_SET (0, &fds_r); /* * We are supposed to write and the buffer is not empty * -> select on write to tun */ if (write_open && (NULL != bufin_read)) FD_SET (fd_tun, &fds_w); int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL); if (-1 == r) { if (EINTR == errno) continue; fprintf (stderr, "select failed: %s\n", strerror (errno)); exit (1); } if (r > 0) { if (FD_ISSET (fd_tun, &fds_r)) { buftun_size = read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader), MAX_SIZE - sizeof (struct GNUNET_MessageHeader)); if (-1 == buftun_size) { fprintf (stderr, "read-error: %s\n", strerror (errno)); shutdown (fd_tun, SHUT_RD); shutdown (1, SHUT_WR); read_open = 0; buftun_size = 0; } else if (0 == buftun_size) { fprintf (stderr, "EOF on tun\n"); shutdown (fd_tun, SHUT_RD); shutdown (1, SHUT_WR); read_open = 0; buftun_size = 0; } else { buftun_read = buftun; struct GNUNET_MessageHeader *hdr = (struct GNUNET_MessageHeader *) buftun; buftun_size += sizeof (struct GNUNET_MessageHeader); hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); hdr->size = htons (buftun_size); } } else if (FD_ISSET (1, &fds_w)) { ssize_t written = write (1, buftun_read, buftun_size); if (-1 == written) { #if !DEBUG if (errno != EPIPE) #endif fprintf (stderr, "write-error to stdout: %s\n", strerror (errno)); shutdown (fd_tun, SHUT_RD); shutdown (1, SHUT_WR); read_open = 0; buftun_size = 0; } else if (0 == written) { fprintf (stderr, "write returned 0!?\n"); exit (1); } else { buftun_size -= written; buftun_read += written; } } if (FD_ISSET (0, &fds_r)) { bufin_size = read (0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos); if (-1 == bufin_size) { fprintf (stderr, "read-error: %s\n", strerror (errno)); shutdown (0, SHUT_RD); shutdown (fd_tun, SHUT_WR); write_open = 0; bufin_size = 0; } else if (0 == bufin_size) { #if DEBUG fprintf (stderr, "EOF on stdin\n"); #endif shutdown (0, SHUT_RD); shutdown (fd_tun, SHUT_WR); write_open = 0; bufin_size = 0; } else { struct GNUNET_MessageHeader *hdr; PROCESS_BUFFER: bufin_rpos += bufin_size; if (bufin_rpos < sizeof (struct GNUNET_MessageHeader)) continue; hdr = (struct GNUNET_MessageHeader *) bufin; if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) { fprintf (stderr, "protocol violation!\n"); exit (1); } if (ntohs (hdr->size) > bufin_rpos) continue; bufin_read = bufin + sizeof (struct GNUNET_MessageHeader); bufin_size = ntohs (hdr->size) - sizeof (struct GNUNET_MessageHeader); bufin_rpos -= bufin_size + sizeof (struct GNUNET_MessageHeader); } } else if (FD_ISSET (fd_tun, &fds_w)) { ssize_t written = write (fd_tun, bufin_read, bufin_size); if (-1 == written) { fprintf (stderr, "write-error to tun: %s\n", strerror (errno)); shutdown (0, SHUT_RD); shutdown (fd_tun, SHUT_WR); write_open = 0; bufin_size = 0; } else if (0 == written) { fprintf (stderr, "write returned 0!?\n"); exit (1); } else { bufin_size -= written; bufin_read += written; if (0 == bufin_size) { memmove (bufin, bufin_read, bufin_rpos); bufin_read = NULL; /* start reading again */ bufin_size = 0; goto PROCESS_BUFFER; } } } } } } /** * Open VPN tunnel interface. * * @param argc must be 6 * @param argv 0: binary name (gnunet-helper-vpn) * 1: tunnel interface name (gnunet-vpn) * 2: IPv6 address (::1), "-" to disable * 3: IPv6 netmask length in bits (64), ignored if #2 is "-" * 4: IPv4 address (1.2.3.4), "-" to disable * 5: IPv4 netmask (255.255.0.0), ignored if #4 is "-" */ int main (int argc, char **argv) { char dev[IFNAMSIZ]; int fd_tun; int global_ret; if (6 != argc) { fprintf (stderr, "Fatal: must supply 5 arguments!\n"); return 1; } strncpy (dev, argv[1], IFNAMSIZ); dev[IFNAMSIZ - 1] = '\0'; if (-1 == (fd_tun = init_tun (dev))) { fprintf (stderr, "Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n", dev, argv[2], argv[3], argv[4], argv[5]); return 1; } if (0 != strcmp (argv[2], "-")) { const char *address = argv[2]; long prefix_len = atol (argv[3]); if ((prefix_len < 1) || (prefix_len > 127)) { fprintf (stderr, "Fatal: prefix_len out of range\n"); return 1; } set_address6 (dev, address, prefix_len); } if (0 != strcmp (argv[4], "-")) { const char *address = argv[4]; const char *mask = argv[5]; set_address4 (dev, address, mask); } uid_t uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); global_ret = 2; goto cleanup; } #else if (0 != (setuid (uid) | seteuid (uid))) { fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); global_ret = 2; goto cleanup; } #endif if (SIG_ERR == signal (SIGPIPE, SIG_IGN)) { fprintf (stderr, "Failed to protect against SIGPIPE: %s\n", strerror (errno)); /* no exit, we might as well die with SIGPIPE should it ever happen */ } run (fd_tun); global_ret = 0; cleanup: close (fd_tun); return global_ret; } gnunet-0.10.1/src/vpn/gnunet-service-vpn.c0000644000175000017500000025227412255074757015341 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file vpn/gnunet-service-vpn.c * @brief service that opens a virtual interface and allows its clients * to allocate IPs on the virtual interface and to then redirect * IP traffic received on those IPs via the GNUnet mesh * @author Philipp Toelke * @author Christian Grothoff * * TODO: * - keep multiple peers/mesh channels ready as alternative exits / * detect & recover from channel-to-exit failure gracefully */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_common.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet_mesh_service.h" #include "gnunet_statistics_service.h" #include "gnunet_constants.h" #include "gnunet_tun_lib.h" #include "gnunet_regex_service.h" #include "vpn.h" #include "exit.h" /** * Maximum number of messages we allow in the queue for mesh. */ #define MAX_MESSAGE_QUEUE_SIZE 4 /** * State we keep for each of our channels. */ struct ChannelState; /** * Information we track for each IP address to determine which channel * to send the traffic over to the destination. */ struct DestinationEntry; /** * List of channels we keep for each destination port for a given * destination entry. */ struct DestinationChannel { /** * Kept in a DLL. */ struct DestinationChannel *next; /** * Kept in a DLL. */ struct DestinationChannel *prev; /** * Destination entry list this `struct DestinationChannel` belongs with. */ struct DestinationEntry *destination; /** * Pre-allocated channel for this destination, or NULL for none. */ struct ChannelState *ts; /** * Destination port this channel state is used for. */ uint16_t destination_port; }; /** * Information we track for each IP address to determine which channel * to send the traffic over to the destination. */ struct DestinationEntry { /** * Key under which this entry is in the 'destination_map' (only valid * if 'heap_node != NULL'). */ struct GNUNET_HashCode key; /** * Head of DLL of channels associated with this destination. */ struct DestinationChannel *dt_head; /** * Tail of DLL of channels associated with this destination. */ struct DestinationChannel *dt_tail; /** * Entry for this entry in the destination_heap. */ struct GNUNET_CONTAINER_HeapNode *heap_node; /** * #GNUNET_NO if this is a channel to an Internet-exit, * #GNUNET_YES if this channel is to a service. */ int is_service; /** * Details about the connection (depending on is_service). */ union { struct { /** * The description of the service (only used for service channels). */ struct GNUNET_HashCode service_descriptor; /** * Peer offering the service. */ struct GNUNET_PeerIdentity target; } service_destination; struct { /** * Address family used (AF_INET or AF_INET6). */ int af; /** * IP address of the ultimate destination (only used for exit channels). */ union { /** * Address if af is AF_INET. */ struct in_addr v4; /** * Address if af is AF_INET6. */ struct in6_addr v6; } ip; } exit_destination; } details; }; /** * A messages we have in queue for a particular channel. */ struct ChannelMessageQueueEntry { /** * This is a doubly-linked list. */ struct ChannelMessageQueueEntry *next; /** * This is a doubly-linked list. */ struct ChannelMessageQueueEntry *prev; /** * Number of bytes in 'msg'. */ size_t len; /** * Message to transmit, allocated at the end of this struct. */ const void *msg; }; /** * State we keep for each of our channels. */ struct ChannelState { /** * Information about the channel to use, NULL if no channel * is available right now. */ struct GNUNET_MESH_Channel *channel; /** * Active query with REGEX to locate exit. */ struct GNUNET_REGEX_Search *search; /** * Active transmission handle, NULL for none. */ struct GNUNET_MESH_TransmitHandle *th; /** * Entry for this entry in the channel_heap, NULL as long as this * channel state is not fully bound. */ struct GNUNET_CONTAINER_HeapNode *heap_node; /** * Head of list of messages scheduled for transmission. */ struct ChannelMessageQueueEntry *tmq_head; /** * Tail of list of messages scheduled for transmission. */ struct ChannelMessageQueueEntry *tmq_tail; /** * Destination entry that has a pointer to this channel state; * NULL if this channel state is in the channel map. */ struct DestinationChannel *destination_container; /** * Destination to which this channel leads. Note that * this struct is NOT in the destination_map (but a * local copy) and that the 'heap_node' should always * be NULL. */ struct DestinationEntry destination; /** * Addess family used for this channel on the local TUN interface. */ int af; /** * Length of the doubly linked 'tmq_head/tmq_tail' list. */ unsigned int tmq_length; /** * IPPROTO_TCP or IPPROTO_UDP once bound. */ uint8_t protocol; /** * IP address of the source on our end, initially uninitialized. */ union { /** * Address if af is AF_INET. */ struct in_addr v4; /** * Address if af is AF_INET6. */ struct in6_addr v6; } source_ip; /** * Destination IP address used by the source on our end (this is the IP * that we pick freely within the VPN's channel IP range). */ union { /** * Address if af is AF_INET. */ struct in_addr v4; /** * Address if af is AF_INET6. */ struct in6_addr v6; } destination_ip; /** * Source port used by the sender on our end; 0 for uninitialized. */ uint16_t source_port; /** * Destination port used by the sender on our end; 0 for uninitialized. */ uint16_t destination_port; }; /** * Return value from 'main'. */ static int global_ret; /** * Configuration we use. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the mesh service. */ static struct GNUNET_MESH_Handle *mesh_handle; /** * Map from IP address to destination information (possibly with a * MESH channel handle for fast setup). */ static struct GNUNET_CONTAINER_MultiHashMap *destination_map; /** * Min-Heap sorted by activity time to expire old mappings. */ static struct GNUNET_CONTAINER_Heap *destination_heap; /** * Map from source and destination address (IP+port) to connection * information (mostly with the respective MESH channel handle). */ static struct GNUNET_CONTAINER_MultiHashMap *channel_map; /** * Min-Heap sorted by activity time to expire old mappings; values are * of type 'struct ChannelState'. */ static struct GNUNET_CONTAINER_Heap *channel_heap; /** * Statistics. */ static struct GNUNET_STATISTICS_Handle *stats; /** * The handle to the VPN helper process "gnunet-helper-vpn". */ static struct GNUNET_HELPER_Handle *helper_handle; /** * Arguments to the vpn helper. */ static char *vpn_argv[7]; /** * Length of the prefix of the VPN's IPv6 network. */ static unsigned long long ipv6prefix; /** * Notification context for sending replies to clients. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * If there are more than this number of address-mappings, old ones * will be removed */ static unsigned long long max_destination_mappings; /** * If there are more than this number of open channels, old ones * will be removed */ static unsigned long long max_channel_mappings; /** * Compute the key under which we would store an entry in the * destination_map for the given IP address. * * @param af address family (AF_INET or AF_INET6) * @param address IP address, struct in_addr or struct in6_addr * @param key where to store the key */ static void get_destination_key_from_ip (int af, const void *address, struct GNUNET_HashCode *key) { switch (af) { case AF_INET: GNUNET_CRYPTO_hash (address, sizeof (struct in_addr), key); break; case AF_INET6: GNUNET_CRYPTO_hash (address, sizeof (struct in6_addr), key); break; default: GNUNET_assert (0); break; } } /** * Compute the key under which we would store an entry in the * channel_map for the given socket address pair. * * @param af address family (AF_INET or AF_INET6) * @param protocol IPPROTO_TCP or IPPROTO_UDP * @param source_ip sender's source IP, struct in_addr or struct in6_addr * @param source_port sender's source port * @param destination_ip sender's destination IP, struct in_addr or struct in6_addr * @param destination_port sender's destination port * @param key where to store the key */ static void get_channel_key_from_ips (int af, uint8_t protocol, const void *source_ip, uint16_t source_port, const void *destination_ip, uint16_t destination_port, struct GNUNET_HashCode *key) { char *off; memset (key, 0, sizeof (struct GNUNET_HashCode)); /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash, so we put the ports in there (and hope for few collisions) */ off = (char*) key; memcpy (off, &source_port, sizeof (uint16_t)); off += sizeof (uint16_t); memcpy (off, &destination_port, sizeof (uint16_t)); off += sizeof (uint16_t); switch (af) { case AF_INET: memcpy (off, source_ip, sizeof (struct in_addr)); off += sizeof (struct in_addr); memcpy (off, destination_ip, sizeof (struct in_addr)); off += sizeof (struct in_addr); break; case AF_INET6: memcpy (off, source_ip, sizeof (struct in6_addr)); off += sizeof (struct in6_addr); memcpy (off, destination_ip, sizeof (struct in6_addr)); off += sizeof (struct in6_addr); break; default: GNUNET_assert (0); break; } memcpy (off, &protocol, sizeof (uint8_t)); /* off += sizeof (uint8_t); */ } /** * Notify the client about the result of its request. * * @param client client to notify * @param request_id original request ID to include in response * @param result_af resulting address family * @param addr resulting IP address */ static void send_client_reply (struct GNUNET_SERVER_Client *client, uint64_t request_id, int result_af, const void *addr) { char buf[sizeof (struct RedirectToIpResponseMessage) + sizeof (struct in6_addr)] GNUNET_ALIGN; struct RedirectToIpResponseMessage *res; size_t rlen; switch (result_af) { case AF_INET: rlen = sizeof (struct in_addr); break; case AF_INET6: rlen = sizeof (struct in6_addr); break; case AF_UNSPEC: rlen = 0; break; default: GNUNET_assert (0); return; } res = (struct RedirectToIpResponseMessage *) buf; res->header.size = htons (sizeof (struct RedirectToIpResponseMessage) + rlen); res->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP); res->result_af = htonl (result_af); res->request_id = request_id; memcpy (&res[1], addr, rlen); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_notification_context_unicast (nc, client, &res->header, GNUNET_NO); } /** * Free resources associated with a channel state. * * @param ts state to free */ static void free_channel_state (struct ChannelState *ts) { struct GNUNET_HashCode key; struct ChannelMessageQueueEntry *tnq; struct GNUNET_MESH_Channel *channel; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up channel state\n"); GNUNET_STATISTICS_update (stats, gettext_noop ("# Active channels"), -1, GNUNET_NO); while (NULL != (tnq = ts->tmq_head)) { GNUNET_CONTAINER_DLL_remove (ts->tmq_head, ts->tmq_tail, tnq); ts->tmq_length--; GNUNET_free (tnq); } GNUNET_assert (0 == ts->tmq_length); if (NULL != ts->th) { GNUNET_MESH_notify_transmit_ready_cancel (ts->th); ts->th = NULL; } GNUNET_assert (NULL == ts->destination.heap_node); if (NULL != (channel = ts->channel)) { ts->channel = NULL; GNUNET_MESH_channel_destroy (channel); } if (NULL != ts->search) { GNUNET_REGEX_search_cancel (ts->search); ts->search = NULL; } if (NULL != ts->heap_node) { GNUNET_CONTAINER_heap_remove_node (ts->heap_node); ts->heap_node = NULL; get_channel_key_from_ips (ts->af, ts->protocol, &ts->source_ip, ts->source_port, &ts->destination_ip, ts->destination_port, &key); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (channel_map, &key, ts)); } if (NULL != ts->destination_container) { GNUNET_assert (ts == ts->destination_container->ts); ts->destination_container->ts = NULL; ts->destination_container = NULL; } GNUNET_free (ts); } /** * Send a message from the message queue via mesh. * * @param cls the `struct ChannelState` with the message queue * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to @a buf */ static size_t send_to_peer_notify_callback (void *cls, size_t size, void *buf) { struct ChannelState *ts = cls; struct ChannelMessageQueueEntry *tnq; size_t ret; ts->th = NULL; if (NULL == buf) return 0; tnq = ts->tmq_head; GNUNET_assert (NULL != tnq); GNUNET_assert (size >= tnq->len); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %u bytes via mesh channel\n", tnq->len); GNUNET_CONTAINER_DLL_remove (ts->tmq_head, ts->tmq_tail, tnq); ts->tmq_length--; memcpy (buf, tnq->msg, tnq->len); ret = tnq->len; GNUNET_free (tnq); if (NULL != (tnq = ts->tmq_head)) ts->th = GNUNET_MESH_notify_transmit_ready (ts->channel, GNUNET_NO /* cork */, GNUNET_TIME_UNIT_FOREVER_REL, tnq->len, &send_to_peer_notify_callback, ts); GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes given to mesh for transmission"), ret, GNUNET_NO); return ret; } /** * Add the given message to the given channel and trigger the * transmission process. * * @param tnq message to queue * @param ts channel to queue the message for */ static void send_to_channel (struct ChannelMessageQueueEntry *tnq, struct ChannelState *ts) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing %u bytes for transmission via mesh channel\n", tnq->len); GNUNET_assert (NULL != ts->channel); GNUNET_CONTAINER_DLL_insert_tail (ts->tmq_head, ts->tmq_tail, tnq); ts->tmq_length++; if (ts->tmq_length > MAX_MESSAGE_QUEUE_SIZE) { struct ChannelMessageQueueEntry *dq; dq = ts->tmq_head; GNUNET_assert (dq != tnq); GNUNET_CONTAINER_DLL_remove (ts->tmq_head, ts->tmq_tail, dq); ts->tmq_length--; GNUNET_MESH_notify_transmit_ready_cancel (ts->th); ts->th = NULL; GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes dropped in mesh queue (overflow)"), dq->len, GNUNET_NO); GNUNET_free (dq); } if (NULL == ts->th) ts->th = GNUNET_MESH_notify_transmit_ready (ts->channel, GNUNET_NO /* cork */, GNUNET_TIME_UNIT_FOREVER_REL, tnq->len, &send_to_peer_notify_callback, ts); } /** * Regex has found a potential exit peer for us; consider using it. * * @param cls the 'struct ChannelState' * @param id Peer providing a regex that matches the string. * @param get_path Path of the get request. * @param get_path_length Lenght of @a get_path. * @param put_path Path of the put request. * @param put_path_length Length of the @a put_path. */ static void handle_regex_result (void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length) { struct ChannelState *ts = cls; unsigned int apptype; GNUNET_REGEX_search_cancel (ts->search); ts->search = NULL; switch (ts->af) { case AF_INET: apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY; break; case AF_INET6: apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY; break; default: GNUNET_break (0); return; } ts->channel = GNUNET_MESH_channel_create (mesh_handle, ts, id, apptype, GNUNET_MESH_OPTION_DEFAULT); } /** * Initialize the given destination entry's mesh channel. * * @param dt destination channel for which we need to setup a channel * @param client_af address family of the address returned to the client * @return channel state of the channel that was created */ static struct ChannelState * create_channel_to_destination (struct DestinationChannel *dt, int client_af) { struct ChannelState *ts; unsigned int apptype; GNUNET_STATISTICS_update (stats, gettext_noop ("# Mesh channels created"), 1, GNUNET_NO); GNUNET_assert (NULL == dt->ts); switch (client_af) { case AF_INET: apptype = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY; break; case AF_INET6: apptype = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY; break; default: GNUNET_break (0); return NULL; } ts = GNUNET_new (struct ChannelState); ts->af = client_af; ts->destination = *dt->destination; ts->destination.heap_node = NULL; /* copy is NOT in destination heap */ dt->ts = ts; ts->destination_container = dt; /* we are referenced from dt */ if (dt->destination->is_service) { ts->channel = GNUNET_MESH_channel_create (mesh_handle, ts, &dt->destination->details.service_destination.target, apptype, GNUNET_MESH_OPTION_DEFAULT); if (NULL == ts->channel) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to setup mesh channel!\n")); GNUNET_free (ts); return NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating channel to peer %s offering service %s\n", GNUNET_i2s (&dt->destination->details.service_destination.target), GNUNET_h2s (&dt->destination->details.service_destination.service_descriptor)); } else { char *policy; switch (dt->destination->details.exit_destination.af) { case AF_INET: { char address[GNUNET_TUN_IPV4_REGEXLEN]; GNUNET_TUN_ipv4toregexsearch (&dt->destination->details.exit_destination.ip.v4, dt->destination_port, address); GNUNET_asprintf (&policy, "%s%s", GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, address); break; } case AF_INET6: { char address[GNUNET_TUN_IPV6_REGEXLEN]; GNUNET_TUN_ipv6toregexsearch (&dt->destination->details.exit_destination.ip.v6, dt->destination_port, address); GNUNET_asprintf (&policy, "%s%s", GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, address); break; } default: GNUNET_assert (0); break; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting connect by string: %s\n", policy); ts->search = GNUNET_REGEX_search (cfg, policy, &handle_regex_result, ts); GNUNET_free (policy); } return ts; } /** * We have too many active channels. Clean up the oldest channel. * * @param except channel that must NOT be cleaned up, even if it is the oldest */ static void expire_channel (struct ChannelState *except) { struct ChannelState *ts; ts = GNUNET_CONTAINER_heap_peek (channel_heap); GNUNET_assert (NULL != ts); if (except == ts) return; /* can't do this */ free_channel_state (ts); } /** * Route a packet via mesh to the given destination. * * @param destination description of the destination * @param af address family on this end (AF_INET or AF_INET6) * @param protocol IPPROTO_TCP or IPPROTO_UDP or IPPROTO_ICMP or IPPROTO_ICMPV6 * @param source_ip source IP used by the sender (struct in_addr or struct in6_addr) * @param destination_ip destination IP used by the sender (struct in_addr or struct in6_addr) * @param payload payload of the packet after the IP header * @param payload_length number of bytes in @a payload */ static void route_packet (struct DestinationEntry *destination, int af, uint8_t protocol, const void *source_ip, const void *destination_ip, const void *payload, size_t payload_length) { struct GNUNET_HashCode key; struct ChannelState *ts; struct ChannelMessageQueueEntry *tnq; size_t alen; size_t mlen; int is_new; const struct GNUNET_TUN_UdpHeader *udp; const struct GNUNET_TUN_TcpHeader *tcp; const struct GNUNET_TUN_IcmpHeader *icmp; struct DestinationChannel *dt; uint16_t source_port; uint16_t destination_port; switch (protocol) { case IPPROTO_UDP: { if (payload_length < sizeof (struct GNUNET_TUN_UdpHeader)) { /* blame kernel? */ GNUNET_break (0); return; } tcp = NULL; /* make compiler happy */ icmp = NULL; /* make compiler happy */ udp = payload; if (udp->len < sizeof (struct GNUNET_TUN_UdpHeader)) { GNUNET_break_op (0); return; } source_port = ntohs (udp->source_port); destination_port = ntohs (udp->destination_port); get_channel_key_from_ips (af, IPPROTO_UDP, source_ip, source_port, destination_ip, destination_port, &key); } break; case IPPROTO_TCP: { if (payload_length < sizeof (struct GNUNET_TUN_TcpHeader)) { /* blame kernel? */ GNUNET_break (0); return; } udp = NULL; /* make compiler happy */ icmp = NULL; /* make compiler happy */ tcp = payload; if (tcp->off * 4 < sizeof (struct GNUNET_TUN_TcpHeader)) { GNUNET_break_op (0); return; } source_port = ntohs (tcp->source_port); destination_port = ntohs (tcp->destination_port); get_channel_key_from_ips (af, IPPROTO_TCP, source_ip, source_port, destination_ip, destination_port, &key); } break; case IPPROTO_ICMP: case IPPROTO_ICMPV6: { if ( (AF_INET == af) ^ (protocol == IPPROTO_ICMP) ) { GNUNET_break (0); return; } if (payload_length < sizeof (struct GNUNET_TUN_IcmpHeader)) { /* blame kernel? */ GNUNET_break (0); return; } tcp = NULL; /* make compiler happy */ udp = NULL; /* make compiler happy */ icmp = payload; source_port = 0; destination_port = 0; get_channel_key_from_ips (af, protocol, source_ip, 0, destination_ip, 0, &key); } break; default: GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Protocol %u not supported, dropping\n"), (unsigned int) protocol); return; } alen = 0; if (! destination->is_service) { switch (destination->details.exit_destination.af) { case AF_INET: alen = sizeof (struct in_addr); break; case AF_INET6: alen = sizeof (struct in6_addr); break; default: GNUNET_assert (0); } { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; char xbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing %s packet from %s:%u -> %s:%u to destination %s:%u\n", (protocol == IPPROTO_TCP) ? "TCP" : "UDP", inet_ntop (af, source_ip, sbuf, sizeof (sbuf)), source_port, inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)), destination_port, inet_ntop (destination->details.exit_destination.af, &destination->details.exit_destination.ip, xbuf, sizeof (xbuf)), destination_port); } for (dt = destination->dt_head; NULL != dt; dt = dt->next) if (dt->destination_port == destination_port) break; } else { { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing %s packet from %s:%u -> %s:%u to service %s at peer %s\n", (protocol == IPPROTO_TCP) ? "TCP" : "UDP", inet_ntop (af, source_ip, sbuf, sizeof (sbuf)), source_port, inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)), destination_port, GNUNET_h2s (&destination->details.service_destination.service_descriptor), GNUNET_i2s (&destination->details.service_destination.target)); } dt = destination->dt_head; } if (NULL == dt) { dt = GNUNET_new (struct DestinationChannel); dt->destination = destination; GNUNET_CONTAINER_DLL_insert (destination->dt_head, destination->dt_tail, dt); dt->destination_port = destination_port; } /* see if we have an existing channel for this destination */ ts = GNUNET_CONTAINER_multihashmap_get (channel_map, &key); if (NULL == ts) { /* need to either use the existing channel from the destination (if still available) or create a fresh one */ is_new = GNUNET_YES; if (NULL == dt->ts) ts = create_channel_to_destination (dt, af); else ts = dt->ts; if (NULL == ts) return; dt->ts = NULL; ts->destination_container = NULL; /* no longer 'contained' */ /* now bind existing "unbound" channel to our IP/port tuple */ ts->protocol = protocol; ts->af = af; if (AF_INET == af) { ts->source_ip.v4 = * (const struct in_addr *) source_ip; ts->destination_ip.v4 = * (const struct in_addr *) destination_ip; } else { ts->source_ip.v6 = * (const struct in6_addr *) source_ip; ts->destination_ip.v6 = * (const struct in6_addr *) destination_ip; } ts->source_port = source_port; ts->destination_port = destination_port; ts->heap_node = GNUNET_CONTAINER_heap_insert (channel_heap, ts, GNUNET_TIME_absolute_get ().abs_value_us); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (channel_map, &key, ts, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); GNUNET_STATISTICS_update (stats, gettext_noop ("# Active channels"), 1, GNUNET_NO); while (GNUNET_CONTAINER_multihashmap_size (channel_map) > max_channel_mappings) expire_channel (ts); } else { is_new = GNUNET_NO; GNUNET_CONTAINER_heap_update_cost (channel_heap, ts->heap_node, GNUNET_TIME_absolute_get ().abs_value_us); } GNUNET_assert (NULL != ts->channel); /* send via channel */ switch (protocol) { case IPPROTO_UDP: if (destination->is_service) { struct GNUNET_EXIT_UdpServiceMessage *usm; mlen = sizeof (struct GNUNET_EXIT_UdpServiceMessage) + payload_length - sizeof (struct GNUNET_TUN_UdpHeader); if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen); tnq->len = mlen; tnq->msg = &tnq[1]; usm = (struct GNUNET_EXIT_UdpServiceMessage *) &tnq[1]; usm->header.size = htons ((uint16_t) mlen); usm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE); /* if the source port is below 32000, we assume it has a special meaning; if not, we pick a random port (this is a heuristic) */ usm->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0; usm->destination_port = udp->destination_port; usm->service_descriptor = destination->details.service_destination.service_descriptor; memcpy (&usm[1], &udp[1], payload_length - sizeof (struct GNUNET_TUN_UdpHeader)); } else { struct GNUNET_EXIT_UdpInternetMessage *uim; struct in_addr *ip4dst; struct in6_addr *ip6dst; void *payload; mlen = sizeof (struct GNUNET_EXIT_UdpInternetMessage) + alen + payload_length - sizeof (struct GNUNET_TUN_UdpHeader); if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen); tnq->len = mlen; tnq->msg = &tnq[1]; uim = (struct GNUNET_EXIT_UdpInternetMessage *) &tnq[1]; uim->header.size = htons ((uint16_t) mlen); uim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET); uim->af = htonl (destination->details.exit_destination.af); uim->source_port = (ntohs (udp->source_port) < 32000) ? udp->source_port : 0; uim->destination_port = udp->destination_port; switch (destination->details.exit_destination.af) { case AF_INET: ip4dst = (struct in_addr *) &uim[1]; *ip4dst = destination->details.exit_destination.ip.v4; payload = &ip4dst[1]; break; case AF_INET6: ip6dst = (struct in6_addr *) &uim[1]; *ip6dst = destination->details.exit_destination.ip.v6; payload = &ip6dst[1]; break; default: GNUNET_assert (0); } memcpy (payload, &udp[1], payload_length - sizeof (struct GNUNET_TUN_UdpHeader)); } break; case IPPROTO_TCP: if (is_new) { if (destination->is_service) { struct GNUNET_EXIT_TcpServiceStartMessage *tsm; mlen = sizeof (struct GNUNET_EXIT_TcpServiceStartMessage) + payload_length - sizeof (struct GNUNET_TUN_TcpHeader); if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen); tnq->len = mlen; tnq->msg = &tnq[1]; tsm = (struct GNUNET_EXIT_TcpServiceStartMessage *) &tnq[1]; tsm->header.size = htons ((uint16_t) mlen); tsm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START); tsm->reserved = htonl (0); tsm->service_descriptor = destination->details.service_destination.service_descriptor; tsm->tcp_header = *tcp; memcpy (&tsm[1], &tcp[1], payload_length - sizeof (struct GNUNET_TUN_TcpHeader)); } else { struct GNUNET_EXIT_TcpInternetStartMessage *tim; struct in_addr *ip4dst; struct in6_addr *ip6dst; void *payload; mlen = sizeof (struct GNUNET_EXIT_TcpInternetStartMessage) + alen + payload_length - sizeof (struct GNUNET_TUN_TcpHeader); if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen); tnq->len = mlen; tnq->msg = &tnq[1]; tim = (struct GNUNET_EXIT_TcpInternetStartMessage *) &tnq[1]; tim->header.size = htons ((uint16_t) mlen); tim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START); tim->af = htonl (destination->details.exit_destination.af); tim->tcp_header = *tcp; switch (destination->details.exit_destination.af) { case AF_INET: ip4dst = (struct in_addr *) &tim[1]; *ip4dst = destination->details.exit_destination.ip.v4; payload = &ip4dst[1]; break; case AF_INET6: ip6dst = (struct in6_addr *) &tim[1]; *ip6dst = destination->details.exit_destination.ip.v6; payload = &ip6dst[1]; break; default: GNUNET_assert (0); } memcpy (payload, &tcp[1], payload_length - sizeof (struct GNUNET_TUN_TcpHeader)); } } else { struct GNUNET_EXIT_TcpDataMessage *tdm; mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + payload_length - sizeof (struct GNUNET_TUN_TcpHeader); if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen); tnq->len = mlen; tnq->msg = &tnq[1]; tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1]; tdm->header.size = htons ((uint16_t) mlen); tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT); tdm->reserved = htonl (0); tdm->tcp_header = *tcp; memcpy (&tdm[1], &tcp[1], payload_length - sizeof (struct GNUNET_TUN_TcpHeader)); } break; case IPPROTO_ICMP: case IPPROTO_ICMPV6: if (destination->is_service) { struct GNUNET_EXIT_IcmpServiceMessage *ism; mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader); if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen); tnq->msg = &tnq[1]; ism = (struct GNUNET_EXIT_IcmpServiceMessage *) &tnq[1]; ism->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE); ism->af = htonl (af); /* need to tell destination ICMP protocol family! */ ism->service_descriptor = destination->details.service_destination.service_descriptor; ism->icmp_header = *icmp; /* ICMP protocol translation will be done by the receiver (as we don't know the target AF); however, we still need to possibly discard the payload depending on the ICMP type */ switch (af) { case AF_INET: switch (icmp->type) { case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: break; case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: /* throw away ICMP payload, won't be useful for the other side anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; default: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (not allowed)"), 1, GNUNET_NO); return; } /* end of AF_INET */ break; case AF_INET6: switch (icmp->type) { case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: /* throw away ICMP payload, won't be useful for the other side anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY: break; default: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (not allowed)"), 1, GNUNET_NO); return; } /* end of AF_INET6 */ break; default: GNUNET_assert (0); break; } /* update length calculations, as payload_length may have changed */ mlen = sizeof (struct GNUNET_EXIT_IcmpServiceMessage) + alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader); tnq->len = mlen; ism->header.size = htons ((uint16_t) mlen); /* finally, copy payload (if there is any left...) */ memcpy (&ism[1], &icmp[1], payload_length - sizeof (struct GNUNET_TUN_IcmpHeader)); } else { struct GNUNET_EXIT_IcmpInternetMessage *iim; struct in_addr *ip4dst; struct in6_addr *ip6dst; void *payload; mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) + alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader); if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueueEntry) + mlen); tnq->msg = &tnq[1]; iim = (struct GNUNET_EXIT_IcmpInternetMessage *) &tnq[1]; iim->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET); iim->icmp_header = *icmp; /* Perform ICMP protocol-translation (depending on destination AF and source AF) and throw away ICMP payload depending on ICMP message type */ switch (af) { case AF_INET: switch (icmp->type) { case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: if (destination->details.exit_destination.af == AF_INET6) iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY; break; case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: if (destination->details.exit_destination.af == AF_INET6) iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST; break; case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: if (destination->details.exit_destination.af == AF_INET6) iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE; /* throw away IP-payload, exit will have to make it up anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: if (destination->details.exit_destination.af == AF_INET6) iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED; /* throw away IP-payload, exit will have to make it up anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: if (destination->details.exit_destination.af == AF_INET6) { GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"), 1, GNUNET_NO); GNUNET_free (tnq); return; } /* throw away IP-payload, exit will have to make it up anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; default: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 1, GNUNET_NO); GNUNET_free (tnq); return; } /* end of AF_INET */ break; case AF_INET6: switch (icmp->type) { case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: if (destination->details.exit_destination.af == AF_INET6) iim->icmp_header.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE; /* throw away IP-payload, exit will have to make it up anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: if (destination->details.exit_destination.af == AF_INET) iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED; /* throw away IP-payload, exit will have to make it up anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: if (destination->details.exit_destination.af == AF_INET) { GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"), 1, GNUNET_NO); GNUNET_free (tnq); return; } /* throw away IP-payload, exit will have to make it up anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: if (destination->details.exit_destination.af == AF_INET) { GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"), 1, GNUNET_NO); GNUNET_free (tnq); return; } /* throw away IP-payload, exit will have to make it up anyway */ payload_length = sizeof (struct GNUNET_TUN_IcmpHeader); break; case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: if (destination->details.exit_destination.af == AF_INET) iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST; break; case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY: if (destination->details.exit_destination.af == AF_INET) iim->icmp_header.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY; break; default: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 1, GNUNET_NO); GNUNET_free (tnq); return; } /* end of AF_INET6 */ break; default: GNUNET_assert (0); } /* update length calculations, as payload_length may have changed */ mlen = sizeof (struct GNUNET_EXIT_IcmpInternetMessage) + alen + payload_length - sizeof (struct GNUNET_TUN_IcmpHeader); tnq->len = mlen; iim->header.size = htons ((uint16_t) mlen); /* need to tell destination ICMP protocol family! */ iim->af = htonl (destination->details.exit_destination.af); switch (destination->details.exit_destination.af) { case AF_INET: ip4dst = (struct in_addr *) &iim[1]; *ip4dst = destination->details.exit_destination.ip.v4; payload = &ip4dst[1]; break; case AF_INET6: ip6dst = (struct in6_addr *) &iim[1]; *ip6dst = destination->details.exit_destination.ip.v6; payload = &ip6dst[1]; break; default: GNUNET_assert (0); } memcpy (payload, &icmp[1], payload_length - sizeof (struct GNUNET_TUN_IcmpHeader)); } break; default: /* not supported above, how can we get here !? */ GNUNET_assert (0); break; } send_to_channel (tnq, ts); } /** * Receive packets from the helper-process (someone send to the local * virtual channel interface). Find the destination mapping, and if it * exists, identify the correct MESH channel (or possibly create it) * and forward the packet. * * @param cls closure, NULL * @param client NULL * @param message message we got from the client (VPN channel interface) */ static int message_token (void *cls, void *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TUN_Layer2PacketHeader *tun; size_t mlen; struct GNUNET_HashCode key; struct DestinationEntry *de; GNUNET_STATISTICS_update (stats, gettext_noop ("# Packets received from TUN interface"), 1, GNUNET_NO); mlen = ntohs (message->size); if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) || (mlen < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)) ) { GNUNET_break (0); return GNUNET_OK; } tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1]; mlen -= (sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader)); switch (ntohs (tun->proto)) { case ETH_P_IPV6: { const struct GNUNET_TUN_IPv6Header *pkt6; if (mlen < sizeof (struct GNUNET_TUN_IPv6Header)) { /* blame kernel */ GNUNET_break (0); return GNUNET_OK; } pkt6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1]; get_destination_key_from_ip (AF_INET6, &pkt6->destination_address, &key); de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key); if (NULL == de) { char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Packet received for unmapped destination `%s' (dropping it)\n"), inet_ntop (AF_INET6, &pkt6->destination_address, buf, sizeof (buf))); return GNUNET_OK; } route_packet (de, AF_INET6, pkt6->next_header, &pkt6->source_address, &pkt6->destination_address, &pkt6[1], mlen - sizeof (struct GNUNET_TUN_IPv6Header)); } break; case ETH_P_IPV4: { struct GNUNET_TUN_IPv4Header *pkt4; if (mlen < sizeof (struct GNUNET_TUN_IPv4Header)) { /* blame kernel */ GNUNET_break (0); return GNUNET_OK; } pkt4 = (struct GNUNET_TUN_IPv4Header *) &tun[1]; get_destination_key_from_ip (AF_INET, &pkt4->destination_address, &key); de = GNUNET_CONTAINER_multihashmap_get (destination_map, &key); if (NULL == de) { char buf[INET_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Packet received for unmapped destination `%s' (dropping it)\n"), inet_ntop (AF_INET, &pkt4->destination_address, buf, sizeof (buf))); return GNUNET_OK; } if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received IPv4 packet with options (dropping it)\n")); return GNUNET_OK; } route_packet (de, AF_INET, pkt4->protocol, &pkt4->source_address, &pkt4->destination_address, &pkt4[1], mlen - sizeof (struct GNUNET_TUN_IPv4Header)); } break; default: GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received packet of unknown protocol %d from TUN (dropping it)\n"), (unsigned int) ntohs (tun->proto)); break; } return GNUNET_OK; } /** * Synthesize a plausible ICMP payload for an ICMP error * response on the given channel. * * @param ts channel information * @param ipp IPv4 header to fill in (ICMP payload) * @param udp "UDP" header to fill in (ICMP payload); might actually * also be the first 8 bytes of the TCP header */ static void make_up_icmpv4_payload (struct ChannelState *ts, struct GNUNET_TUN_IPv4Header *ipp, struct GNUNET_TUN_UdpHeader *udp) { GNUNET_TUN_initialize_ipv4_header (ipp, ts->protocol, sizeof (struct GNUNET_TUN_TcpHeader), &ts->source_ip.v4, &ts->destination_ip.v4); udp->source_port = htons (ts->source_port); udp->destination_port = htons (ts->destination_port); udp->len = htons (0); udp->crc = htons (0); } /** * Synthesize a plausible ICMP payload for an ICMP error * response on the given channel. * * @param ts channel information * @param ipp IPv6 header to fill in (ICMP payload) * @param udp "UDP" header to fill in (ICMP payload); might actually * also be the first 8 bytes of the TCP header */ static void make_up_icmpv6_payload (struct ChannelState *ts, struct GNUNET_TUN_IPv6Header *ipp, struct GNUNET_TUN_UdpHeader *udp) { GNUNET_TUN_initialize_ipv6_header (ipp, ts->protocol, sizeof (struct GNUNET_TUN_TcpHeader), &ts->source_ip.v6, &ts->destination_ip.v6); udp->source_port = htons (ts->source_port); udp->destination_port = htons (ts->destination_port); udp->len = htons (0); udp->crc = htons (0); } /** * We got an ICMP packet back from the MESH channel. Pass it on to the * local virtual interface via the helper. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our 'struct ChannelState *' * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_icmp_back (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *ts = *channel_ctx; const struct GNUNET_EXIT_IcmpToVPNMessage *i2v; size_t mlen; GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMP packets received from mesh"), 1, GNUNET_NO); mlen = ntohs (message->size); if (mlen < sizeof (struct GNUNET_EXIT_IcmpToVPNMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (NULL == ts->heap_node) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (AF_UNSPEC == ts->af) { GNUNET_break_op (0); return GNUNET_SYSERR; } i2v = (const struct GNUNET_EXIT_IcmpToVPNMessage *) message; mlen -= sizeof (struct GNUNET_EXIT_IcmpToVPNMessage); { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ICMP packet from mesh, sending %u bytes from %s -> %s via TUN\n", (unsigned int) mlen, inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)), inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf))); } switch (ts->af) { case AF_INET: { size_t size = sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_IcmpHeader) + sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen; { /* reserve some extra space in case we have an ICMP type here where we will need to make up the payload ourselves */ char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1]; struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1]; msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); tun->flags = htons (0); tun->proto = htons (ETH_P_IPV4); GNUNET_TUN_initialize_ipv4_header (ipv4, IPPROTO_ICMP, sizeof (struct GNUNET_TUN_IcmpHeader) + mlen, &ts->destination_ip.v4, &ts->source_ip.v4); *icmp = i2v->icmp_header; memcpy (&icmp[1], &i2v[1], mlen); /* For some ICMP types, we need to adjust (make up) the payload here. Also, depending on the AF used on the other side, we have to do ICMP PT (translate ICMP types) */ switch (ntohl (i2v->af)) { case AF_INET: switch (icmp->type) { case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: break; case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: { struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1]; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; if (mlen != 0) { /* sender did not strip ICMP payload? */ GNUNET_break_op (0); return GNUNET_SYSERR; } size += sizeof (struct GNUNET_TUN_IPv4Header) + 8; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); make_up_icmpv4_payload (ts, ipp, udp); } break; default: GNUNET_break_op (0); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 1, GNUNET_NO); return GNUNET_SYSERR; } /* end AF_INET */ break; case AF_INET6: /* ICMP PT 6-to-4 and possibly making up payloads */ switch (icmp->type) { case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE; { struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1]; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; if (mlen != 0) { /* sender did not strip ICMP payload? */ GNUNET_break_op (0); return GNUNET_SYSERR; } size += sizeof (struct GNUNET_TUN_IPv4Header) + 8; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); make_up_icmpv4_payload (ts, ipp, udp); } break; case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED; { struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1]; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; if (mlen != 0) { /* sender did not strip ICMP payload? */ GNUNET_break_op (0); return GNUNET_SYSERR; } size += sizeof (struct GNUNET_TUN_IPv4Header) + 8; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); make_up_icmpv4_payload (ts, ipp, udp); } break; case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"), 1, GNUNET_NO); return GNUNET_OK; case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST; break; case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY: icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY; break; default: GNUNET_break_op (0); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 1, GNUNET_NO); return GNUNET_SYSERR; } /* end AF_INET6 */ break; default: GNUNET_break_op (0); return GNUNET_SYSERR; } msg->size = htons (size); GNUNET_TUN_calculate_icmp_checksum (icmp, &i2v[1], mlen); (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL); } } break; case AF_INET6: { size_t size = sizeof (struct GNUNET_TUN_IPv6Header) + sizeof (struct GNUNET_TUN_IcmpHeader) + sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen; { char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1]; struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1]; msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); tun->flags = htons (0); tun->proto = htons (ETH_P_IPV6); GNUNET_TUN_initialize_ipv6_header (ipv6, IPPROTO_ICMPV6, sizeof (struct GNUNET_TUN_IcmpHeader) + mlen, &ts->destination_ip.v6, &ts->source_ip.v6); *icmp = i2v->icmp_header; memcpy (&icmp[1], &i2v[1], mlen); /* For some ICMP types, we need to adjust (make up) the payload here. Also, depending on the AF used on the other side, we have to do ICMP PT (translate ICMP types) */ switch (ntohl (i2v->af)) { case AF_INET: /* ICMP PT 4-to-6 and possibly making up payloads */ switch (icmp->type) { case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY; break; case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST; break; case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE; { struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1]; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; if (mlen != 0) { /* sender did not strip ICMP payload? */ GNUNET_break_op (0); return GNUNET_SYSERR; } size += sizeof (struct GNUNET_TUN_IPv6Header) + 8; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); make_up_icmpv6_payload (ts, ipp, udp); } break; case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED; { struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1]; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; if (mlen != 0) { /* sender did not strip ICMP payload? */ GNUNET_break_op (0); return GNUNET_SYSERR; } size += sizeof (struct GNUNET_TUN_IPv6Header) + 8; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); make_up_icmpv6_payload (ts, ipp, udp); } break; case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"), 1, GNUNET_NO); return GNUNET_OK; default: GNUNET_break_op (0); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 1, GNUNET_NO); return GNUNET_SYSERR; } /* end AF_INET */ break; case AF_INET6: switch (icmp->type) { case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: { struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1]; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; if (mlen != 0) { /* sender did not strip ICMP payload? */ GNUNET_break_op (0); return GNUNET_SYSERR; } size += sizeof (struct GNUNET_TUN_IPv6Header) + 8; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); make_up_icmpv6_payload (ts, ipp, udp); } break; case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: break; default: GNUNET_break_op (0); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 1, GNUNET_NO); return GNUNET_SYSERR; } /* end AF_INET6 */ break; default: GNUNET_break_op (0); return GNUNET_SYSERR; } msg->size = htons (size); GNUNET_TUN_calculate_icmp_checksum (icmp, &i2v[1], mlen); (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL); } } break; default: GNUNET_assert (0); } GNUNET_CONTAINER_heap_update_cost (channel_heap, ts->heap_node, GNUNET_TIME_absolute_get ().abs_value_us); return GNUNET_OK; } /** * We got a UDP packet back from the MESH channel. Pass it on to the * local virtual interface via the helper. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our 'struct ChannelState *' * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_udp_back (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *ts = *channel_ctx; const struct GNUNET_EXIT_UdpReplyMessage *reply; size_t mlen; GNUNET_STATISTICS_update (stats, gettext_noop ("# UDP packets received from mesh"), 1, GNUNET_NO); mlen = ntohs (message->size); if (mlen < sizeof (struct GNUNET_EXIT_UdpReplyMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (NULL == ts->heap_node) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (AF_UNSPEC == ts->af) { GNUNET_break_op (0); return GNUNET_SYSERR; } reply = (const struct GNUNET_EXIT_UdpReplyMessage *) message; mlen -= sizeof (struct GNUNET_EXIT_UdpReplyMessage); { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received UDP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n", (unsigned int) mlen, inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)), ts->destination_port, inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)), ts->source_port); } switch (ts->af) { case AF_INET: { size_t size = sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen; { char buf[size] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1]; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1]; msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); msg->size = htons (size); tun->flags = htons (0); tun->proto = htons (ETH_P_IPV4); GNUNET_TUN_initialize_ipv4_header (ipv4, IPPROTO_UDP, sizeof (struct GNUNET_TUN_UdpHeader) + mlen, &ts->destination_ip.v4, &ts->source_ip.v4); if (0 == ntohs (reply->source_port)) udp->source_port = htons (ts->destination_port); else udp->source_port = reply->source_port; if (0 == ntohs (reply->destination_port)) udp->destination_port = htons (ts->source_port); else udp->destination_port = reply->destination_port; udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader)); GNUNET_TUN_calculate_udp4_checksum (ipv4, udp, &reply[1], mlen); memcpy (&udp[1], &reply[1], mlen); (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL); } } break; case AF_INET6: { size_t size = sizeof (struct GNUNET_TUN_IPv6Header) + sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen; { char buf[size] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1]; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1]; msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); msg->size = htons (size); tun->flags = htons (0); tun->proto = htons (ETH_P_IPV6); GNUNET_TUN_initialize_ipv6_header (ipv6, IPPROTO_UDP, sizeof (struct GNUNET_TUN_UdpHeader) + mlen, &ts->destination_ip.v6, &ts->source_ip.v6); if (0 == ntohs (reply->source_port)) udp->source_port = htons (ts->destination_port); else udp->source_port = reply->source_port; if (0 == ntohs (reply->destination_port)) udp->destination_port = htons (ts->source_port); else udp->destination_port = reply->destination_port; udp->len = htons (mlen + sizeof (struct GNUNET_TUN_UdpHeader)); GNUNET_TUN_calculate_udp6_checksum (ipv6, udp, &reply[1], mlen); memcpy (&udp[1], &reply[1], mlen); (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL); } } break; default: GNUNET_assert (0); } GNUNET_CONTAINER_heap_update_cost (channel_heap, ts->heap_node, GNUNET_TIME_absolute_get ().abs_value_us); return GNUNET_OK; } /** * We got a TCP packet back from the MESH channel. Pass it on to the * local virtual interface via the helper. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our `struct ChannelState *` * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_tcp_back (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *ts = *channel_ctx; const struct GNUNET_EXIT_TcpDataMessage *data; size_t mlen; GNUNET_STATISTICS_update (stats, gettext_noop ("# TCP packets received from mesh"), 1, GNUNET_NO); mlen = ntohs (message->size); if (mlen < sizeof (struct GNUNET_EXIT_TcpDataMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (NULL == ts->heap_node) { GNUNET_break_op (0); return GNUNET_SYSERR; } data = (const struct GNUNET_EXIT_TcpDataMessage *) message; mlen -= sizeof (struct GNUNET_EXIT_TcpDataMessage); { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received TCP reply from mesh, sending %u bytes from %s:%u -> %s:%u via TUN\n", (unsigned int) mlen, inet_ntop (ts->af, &ts->destination_ip, sbuf, sizeof (sbuf)), ts->destination_port, inet_ntop (ts->af, &ts->source_ip, dbuf, sizeof (dbuf)), ts->source_port); } if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } switch (ts->af) { case AF_INET: { size_t size = sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_TcpHeader) + sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen; { char buf[size] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1]; struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv4[1]; msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); msg->size = htons (size); tun->flags = htons (0); tun->proto = htons (ETH_P_IPV4); GNUNET_TUN_initialize_ipv4_header (ipv4, IPPROTO_TCP, sizeof (struct GNUNET_TUN_TcpHeader) + mlen, &ts->destination_ip.v4, &ts->source_ip.v4); *tcp = data->tcp_header; tcp->source_port = htons (ts->destination_port); tcp->destination_port = htons (ts->source_port); GNUNET_TUN_calculate_tcp4_checksum (ipv4, tcp, &data[1], mlen); memcpy (&tcp[1], &data[1], mlen); (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL); } } break; case AF_INET6: { size_t size = sizeof (struct GNUNET_TUN_IPv6Header) + sizeof (struct GNUNET_TUN_TcpHeader) + sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + mlen; { char buf[size] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1]; struct GNUNET_TUN_TcpHeader *tcp = (struct GNUNET_TUN_TcpHeader *) &ipv6[1]; msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); msg->size = htons (size); tun->flags = htons (0); tun->proto = htons (ETH_P_IPV6); GNUNET_TUN_initialize_ipv6_header (ipv6, IPPROTO_TCP, sizeof (struct GNUNET_TUN_TcpHeader) + mlen, &ts->destination_ip.v6, &ts->source_ip.v6); *tcp = data->tcp_header; tcp->source_port = htons (ts->destination_port); tcp->destination_port = htons (ts->source_port); GNUNET_TUN_calculate_tcp6_checksum (ipv6, tcp, &data[1], mlen); memcpy (&tcp[1], &data[1], mlen); (void) GNUNET_HELPER_send (helper_handle, msg, GNUNET_YES, NULL, NULL); } } break; } GNUNET_CONTAINER_heap_update_cost (channel_heap, ts->heap_node, GNUNET_TIME_absolute_get ().abs_value_us); return GNUNET_OK; } /** * Allocate an IPv4 address from the range of the channel * for a new redirection. * * @param v4 where to store the address * @return #GNUNET_OK on success, * #GNUNET_SYSERR on error */ static int allocate_v4_address (struct in_addr *v4) { const char *ipv4addr = vpn_argv[4]; const char *ipv4mask = vpn_argv[5]; struct in_addr addr; struct in_addr mask; struct in_addr rnd; struct GNUNET_HashCode key; unsigned int tries; GNUNET_assert (1 == inet_pton (AF_INET, ipv4addr, &addr)); GNUNET_assert (1 == inet_pton (AF_INET, ipv4mask, &mask)); /* Given 192.168.0.1/255.255.0.0, we want a mask of '192.168.255.255', thus: */ mask.s_addr = addr.s_addr | ~mask.s_addr; tries = 0; do { tries++; if (tries > 16) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to find unallocated IPv4 address in VPN's range\n")); return GNUNET_SYSERR; } /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */ rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); v4->s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr; get_destination_key_from_ip (AF_INET, v4, &key); } while ( (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (destination_map, &key)) || (v4->s_addr == addr.s_addr) || (v4->s_addr == mask.s_addr) ); return GNUNET_OK; } /** * Allocate an IPv6 address from the range of the channel * for a new redirection. * * @param v6 where to store the address * @return #GNUNET_OK on success, * #GNUNET_SYSERR on error */ static int allocate_v6_address (struct in6_addr *v6) { const char *ipv6addr = vpn_argv[2]; struct in6_addr addr; struct in6_addr mask; struct in6_addr rnd; int i; struct GNUNET_HashCode key; unsigned int tries; GNUNET_assert (1 == inet_pton (AF_INET6, ipv6addr, &addr)); GNUNET_assert (ipv6prefix < 128); /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF, thus: */ mask = addr; for (i=127;i>=ipv6prefix;i--) mask.s6_addr[i / 8] |= (1 << (i % 8)); /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */ tries = 0; do { tries++; if (tries > 16) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to find unallocated IPv6 address in VPN's range\n")); return GNUNET_SYSERR; } for (i=0;i<16;i++) { rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); v6->s6_addr[i] = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i]; } get_destination_key_from_ip (AF_INET6, v6, &key); } while ( (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (destination_map, &key)) || (0 == memcmp (v6, &addr, sizeof (struct in6_addr))) || (0 == memcmp (v6, &mask, sizeof (struct in6_addr))) ); return GNUNET_OK; } /** * Free resources occupied by a destination entry. * * @param de entry to free */ static void free_destination_entry (struct DestinationEntry *de) { struct DestinationChannel *dt; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up destination entry\n"); GNUNET_STATISTICS_update (stats, gettext_noop ("# Active destinations"), -1, GNUNET_NO); while (NULL != (dt = de->dt_head)) { GNUNET_CONTAINER_DLL_remove (de->dt_head, de->dt_tail, dt); if (NULL != dt->ts) { free_channel_state (dt->ts); GNUNET_assert (NULL == dt->ts); } GNUNET_free (dt); } if (NULL != de->heap_node) { GNUNET_CONTAINER_heap_remove_node (de->heap_node); de->heap_node = NULL; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (destination_map, &de->key, de)); } GNUNET_free (de); } /** * We have too many active destinations. Clean up the oldest destination. * * @param except destination that must NOT be cleaned up, even if it is the oldest */ static void expire_destination (struct DestinationEntry *except) { struct DestinationEntry *de; de = GNUNET_CONTAINER_heap_peek (destination_heap); GNUNET_assert (NULL != de); if (except == de) return; /* can't do this */ free_destination_entry (de); } /** * Allocate an IP address for the response. * * @param result_af desired address family; set to the actual * address family; can initially be AF_UNSPEC if there * is no preference; will be set to AF_UNSPEC if the * allocation failed * @param addr set to either v4 or v6 depending on which * storage location was used; set to NULL if allocation failed * @param v4 storage space for an IPv4 address * @param v6 storage space for an IPv6 address * @return #GNUNET_OK normally, #GNUNET_SYSERR if `* result_af` was * an unsupported address family (not AF_INET, AF_INET6 or AF_UNSPEC) */ static int allocate_response_ip (int *result_af, void **addr, struct in_addr *v4, struct in6_addr *v6) { *addr = NULL; switch (*result_af) { case AF_INET: if (GNUNET_OK != allocate_v4_address (v4)) *result_af = AF_UNSPEC; else *addr = v4; break; case AF_INET6: if (GNUNET_OK != allocate_v6_address (v6)) *result_af = AF_UNSPEC; else *addr = v6; break; case AF_UNSPEC: if (GNUNET_OK == allocate_v4_address (v4)) { *addr = v4; *result_af = AF_INET; } else if (GNUNET_OK == allocate_v6_address (v6)) { *addr = v6; *result_af = AF_INET6; } break; default: GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; } /** * A client asks us to setup a redirection via some exit node to a * particular IP. Setup the redirection and give the client the * allocated IP. * * @param cls unused * @param client requesting client * @param message redirection request (a `struct RedirectToIpRequestMessage`) */ static void service_redirect_to_ip (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { size_t mlen; size_t alen; const struct RedirectToIpRequestMessage *msg; int addr_af; int result_af; struct in_addr v4; struct in6_addr v6; void *addr; struct DestinationEntry *de; struct GNUNET_HashCode key; /* validate and parse request */ mlen = ntohs (message->size); if (mlen < sizeof (struct RedirectToIpRequestMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } alen = mlen - sizeof (struct RedirectToIpRequestMessage); msg = (const struct RedirectToIpRequestMessage *) message; addr_af = (int) htonl (msg->addr_af); switch (addr_af) { case AF_INET: if (alen != sizeof (struct in_addr)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } break; case AF_INET6: if (alen != sizeof (struct in6_addr)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } break; default: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* allocate response IP */ result_af = (int) htonl (msg->result_af); if (GNUNET_OK != allocate_response_ip (&result_af, &addr, &v4, &v6)) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* send reply with our IP address */ send_client_reply (client, msg->request_id, result_af, addr); if (result_af == AF_UNSPEC) { /* failure, we're done */ GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Allocated address %s for redirection via exit to %s\n", inet_ntop (result_af, addr, sbuf, sizeof (sbuf)), inet_ntop (addr_af, &msg[1], dbuf, sizeof (dbuf))); } /* setup destination record */ de = GNUNET_new (struct DestinationEntry); de->is_service = GNUNET_NO; de->details.exit_destination.af = addr_af; memcpy (&de->details.exit_destination.ip, &msg[1], alen); get_destination_key_from_ip (result_af, addr, &key); de->key = key; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (destination_map, &key, de, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap, de, GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us); GNUNET_STATISTICS_update (stats, gettext_noop ("# Active destinations"), 1, GNUNET_NO); while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings) expire_destination (de); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * A client asks us to setup a redirection to a particular peer * offering a service. Setup the redirection and give the client the * allocated IP. * * @param cls unused * @param client requesting client * @param message redirection request (a `struct RedirectToPeerRequestMessage`) */ static void service_redirect_to_service (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct RedirectToServiceRequestMessage *msg; int result_af; struct in_addr v4; struct in6_addr v6; void *addr; struct DestinationEntry *de; struct GNUNET_HashCode key; struct ChannelState *ts; struct DestinationChannel *dt; /* parse request */ msg = (const struct RedirectToServiceRequestMessage *) message; /* allocate response IP */ result_af = (int) htonl (msg->result_af); if (GNUNET_OK != allocate_response_ip (&result_af, &addr, &v4, &v6)) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } send_client_reply (client, msg->request_id, result_af, addr); if (result_af == AF_UNSPEC) { /* failure, we're done */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to allocate IP address for new destination\n")); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } { char sbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Allocated address %s for redirection to service %s on peer %s\n", inet_ntop (result_af, addr, sbuf, sizeof (sbuf)), GNUNET_h2s (&msg->service_descriptor), GNUNET_i2s (&msg->target)); } /* setup destination record */ de = GNUNET_new (struct DestinationEntry); de->is_service = GNUNET_YES; de->details.service_destination.service_descriptor = msg->service_descriptor; de->details.service_destination.target = msg->target; get_destination_key_from_ip (result_af, addr, &key); de->key = key; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (destination_map, &key, de, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); de->heap_node = GNUNET_CONTAINER_heap_insert (destination_heap, de, GNUNET_TIME_absolute_ntoh (msg->expiration_time).abs_value_us); while (GNUNET_CONTAINER_multihashmap_size (destination_map) > max_destination_mappings) expire_destination (de); dt = GNUNET_new (struct DestinationChannel); dt->destination = de; GNUNET_CONTAINER_DLL_insert (de->dt_head, de->dt_tail, dt); ts = create_channel_to_destination (dt, result_af); switch (result_af) { case AF_INET: ts->destination_ip.v4 = v4; break; case AF_INET6: ts->destination_ip.v6 = v6; break; default: GNUNET_assert (0); } /* we're done */ GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Function called whenever a channel is destroyed. Should clean up * any associated state. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored (our `struct ChannelState`) */ static void channel_cleaner (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { struct ChannelState *ts = channel_ctx; ts->channel = NULL; /* we must not call GNUNET_MESH_channel_destroy() anymore */ free_channel_state (ts); } /** * Free memory occupied by an entry in the destination map. * * @param cls unused * @param key unused * @param value a `struct DestinationEntry *` * @return #GNUNET_OK (continue to iterate) */ static int cleanup_destination (void *cls, const struct GNUNET_HashCode *key, void *value) { struct DestinationEntry *de = value; free_destination_entry (de); return GNUNET_OK; } /** * Free memory occupied by an entry in the channel map. * * @param cls unused * @param key unused * @param value a `struct ChannelState *` * @return #GNUNET_OK (continue to iterate) */ static int cleanup_channel (void *cls, const struct GNUNET_HashCode *key, void *value) { struct ChannelState *ts = value; free_channel_state (ts); return GNUNET_OK; } /** * Function scheduled as very last function, cleans up after us * * @param cls unused * @param tc unused */ static void cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "VPN is shutting down\n"); if (NULL != destination_map) { GNUNET_CONTAINER_multihashmap_iterate (destination_map, &cleanup_destination, NULL); GNUNET_CONTAINER_multihashmap_destroy (destination_map); destination_map = NULL; } if (NULL != destination_heap) { GNUNET_CONTAINER_heap_destroy (destination_heap); destination_heap = NULL; } if (NULL != channel_map) { GNUNET_CONTAINER_multihashmap_iterate (channel_map, &cleanup_channel, NULL); GNUNET_CONTAINER_multihashmap_destroy (channel_map); channel_map = NULL; } if (NULL != channel_heap) { GNUNET_CONTAINER_heap_destroy (channel_heap); channel_heap = NULL; } if (NULL != mesh_handle) { GNUNET_MESH_disconnect (mesh_handle); mesh_handle = NULL; } if (NULL != helper_handle) { GNUNET_HELPER_stop (helper_handle, GNUNET_NO); helper_handle = NULL; } if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } for (i=0;i<5;i++) GNUNET_free_non_null (vpn_argv[i]); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param server the initialized server * @param cfg_ configuration */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg_) { static const struct GNUNET_SERVER_MessageHandler service_handlers[] = { /* callback, cls, type, size */ { &service_redirect_to_ip, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP, 0}, { &service_redirect_to_service, NULL, GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE, sizeof (struct RedirectToServiceRequestMessage) }, {NULL, NULL, 0, 0} }; static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = { { &receive_udp_back, GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY, 0}, { &receive_tcp_back, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN, 0}, { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0}, {NULL, 0, 0} }; char *ifname; char *ipv6addr; char *ipv6prefix_s; char *ipv4addr; char *ipv4mask; struct in_addr v4; struct in6_addr v6; char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn"); if (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please! { fprintf (stderr, "`%s' is not SUID, refusing to run.\n", "gnunet-helper-vpn"); GNUNET_free (binary); global_ret = 1; return; } GNUNET_free (binary); cfg = cfg_; stats = GNUNET_STATISTICS_create ("vpn", cfg); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_MAPPING", &max_destination_mappings)) max_destination_mappings = 200; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "MAX_TUNNELS", &max_channel_mappings)) max_channel_mappings = 200; destination_map = GNUNET_CONTAINER_multihashmap_create (max_destination_mappings * 2, GNUNET_NO); destination_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); channel_map = GNUNET_CONTAINER_multihashmap_create (max_channel_mappings * 2, GNUNET_NO); channel_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); vpn_argv[0] = GNUNET_strdup ("vpn-gnunet"); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IFNAME", &ifname)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IFNAME"); GNUNET_SCHEDULER_shutdown (); return; } vpn_argv[1] = ifname; ipv6addr = NULL; if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6)) { if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6ADDR", &ipv6addr) || (1 != inet_pton (AF_INET6, ipv6addr, &v6))) ) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6ADDR", _("Must specify valid IPv6 address")); GNUNET_SCHEDULER_shutdown (); GNUNET_free_non_null (ipv6addr); return; } vpn_argv[2] = ipv6addr; ipv6prefix_s = NULL; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "VPN", "IPV6PREFIX", &ipv6prefix_s)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV6PREFIX"); GNUNET_SCHEDULER_shutdown (); GNUNET_free_non_null (ipv6prefix_s); return; } vpn_argv[3] = ipv6prefix_s; if ( (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "VPN", "IPV6PREFIX", &ipv6prefix)) || (ipv6prefix >= 127) ) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK", _("Must specify valid IPv6 mask")); GNUNET_SCHEDULER_shutdown (); return; } } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("IPv6 support disabled as this system does not support IPv6\n")); vpn_argv[2] = GNUNET_strdup ("-"); vpn_argv[3] = GNUNET_strdup ("-"); } if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET)) { ipv4addr = NULL; if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4ADDR", &ipv4addr) || (1 != inet_pton (AF_INET, ipv4addr, &v4))) ) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4ADDR", _("Must specify valid IPv4 address")); GNUNET_SCHEDULER_shutdown (); GNUNET_free_non_null (ipv4addr); return; } vpn_argv[4] = ipv4addr; ipv4mask = NULL; if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "IPV4MASK", &ipv4mask) || (1 != inet_pton (AF_INET, ipv4mask, &v4))) ) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "VPN", "IPV4MASK", _("Must specify valid IPv4 mask")); GNUNET_SCHEDULER_shutdown (); GNUNET_free_non_null (ipv4mask); return; } vpn_argv[5] = ipv4mask; } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("IPv4 support disabled as this system does not support IPv4\n")); vpn_argv[4] = GNUNET_strdup ("-"); vpn_argv[5] = GNUNET_strdup ("-"); } vpn_argv[6] = NULL; mesh_handle = GNUNET_MESH_connect (cfg_, NULL, NULL, &channel_cleaner, mesh_handlers, NULL); helper_handle = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-vpn", vpn_argv, &message_token, NULL, NULL); nc = GNUNET_SERVER_notification_context_create (server, 1); GNUNET_SERVER_add_handlers (server, service_handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); } /** * The main function of the VPN service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "vpn", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? global_ret : 1; } /* end of gnunet-service-vpn.c */ gnunet-0.10.1/src/vpn/vpn.h0000644000175000017500000000724312225777503012400 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file vpn/vpn.h * @brief IPC messages between VPN library and VPN service * @author Christian Grothoff */ #ifndef VPN_H #define VPN_H #include "gnunet_util_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Message send by the VPN client to the VPN service requesting * the setup of a redirection from some IP via an exit node to * some global Internet address. */ struct RedirectToIpRequestMessage { /** * Type is #GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * How long should the redirection be maintained at most? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * Address family desired for the result (AF_INET or AF_INET6 or AF_UNSPEC, in nbo) */ int32_t result_af GNUNET_PACKED; /** * Address family used for the destination address (AF_INET or AF_INET6, in nbo) */ int32_t addr_af GNUNET_PACKED; /** * Unique ID to match a future response to this request. * Picked by the client. */ uint64_t request_id GNUNET_PACKED; /* followed by destination address ('struct in_addr' or 'struct in6_addr') */ }; /** * Message send by the VPN client to the VPN service requesting * the setup of a redirection from some IP to a service running * at a particular peer. */ struct RedirectToServiceRequestMessage { /** * Type is #GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * How long should the redirection be maintained at most? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * Desired protocol (IPPROTO_UDP or IPPROTO_TCP) */ int32_t protocol GNUNET_PACKED; /** * Address family desired for the result (AF_INET or AF_INET6 or AF_UNSPEC, in nbo) */ int32_t result_af GNUNET_PACKED; /** * Target peer offering the service. */ struct GNUNET_PeerIdentity target; /** * Service descriptor identifying the service. */ struct GNUNET_HashCode service_descriptor; /** * Unique ID to match a future response to this request. * Picked by the client. */ uint64_t request_id GNUNET_PACKED; }; /** * Response from the VPN service to a VPN client informing about * the IP that was assigned for the requested redirection. */ struct RedirectToIpResponseMessage { /** * Type is #GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP */ struct GNUNET_MessageHeader header; /** * Address family of the allocated address that follows; will match * "result_af" from the request, of be "AF_UNSPEC" on errors. */ int32_t result_af GNUNET_PACKED; /** * Unique ID to match the response to a request. */ uint64_t request_id GNUNET_PACKED; /* followed by destination address ('struct in_addr' or 'struct in6_addr') */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/multicast/0000755000175000017500000000000012320755627012677 500000000000000gnunet-0.10.1/src/multicast/multicast.conf.in0000644000175000017500000000060612250373167016077 00000000000000[multicast] AUTOSTART = @AUTOSTART@ PORT = 2109 HOSTNAME = localhost BINARY = gnunet-service-multicast ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-multicast.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = gnunet-0.10.1/src/multicast/test_multicast_api.c0000644000175000017500000000214512225777501016661 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file multicast/test_multicast_api.c * @brief testcase for multicast.c */ #include "platform.h" #include "gnunet_util_lib.h" static int check () { return 0; } int main (int argc, char *argv[]) { int ret; ret = check (); return ret; } /* end of test_multicast_api.c */ gnunet-0.10.1/src/multicast/multicast_api.c0000644000175000017500000007034712310570720015620 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file multicast/multicast_api.c * @brief multicast service; establish tunnels to distant peers * @author Christian Grothoff * @author Gabor X Toth */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_signatures.h" #include "gnunet_multicast_service.h" #include "multicast.h" #define LOG(kind,...) GNUNET_log_from (kind, "multicast-api",__VA_ARGS__) /** * Started origins. * Group's pub_key_hash -> struct GNUNET_MULTICAST_Origin */ static struct GNUNET_CONTAINER_MultiHashMap *origins; /** * Joined members. * group_key_hash -> struct GNUNET_MULTICAST_Member */ static struct GNUNET_CONTAINER_MultiHashMap *members; /** * Handle for a request to send a message to all multicast group members * (from the origin). */ struct GNUNET_MULTICAST_OriginMessageHandle { GNUNET_MULTICAST_OriginTransmitNotify notify; void *notify_cls; struct GNUNET_MULTICAST_Origin *origin; uint64_t message_id; uint64_t group_generation; uint64_t fragment_offset; }; struct GNUNET_MULTICAST_Group { uint8_t is_origin; }; /** * Handle for the origin of a multicast group. */ struct GNUNET_MULTICAST_Origin { struct GNUNET_MULTICAST_Group grp; struct GNUNET_MULTICAST_OriginMessageHandle msg_handle; struct GNUNET_CRYPTO_EddsaPrivateKey priv_key; GNUNET_MULTICAST_JoinCallback join_cb; GNUNET_MULTICAST_MembershipTestCallback mem_test_cb; GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb; GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb; GNUNET_MULTICAST_RequestCallback request_cb; GNUNET_MULTICAST_MessageCallback message_cb; void *cls; uint64_t next_fragment_id; struct GNUNET_CRYPTO_EddsaPublicKey pub_key; struct GNUNET_HashCode pub_key_hash; }; /** * Handle for a message to be delivered from a member to the origin. */ struct GNUNET_MULTICAST_MemberRequestHandle { GNUNET_MULTICAST_MemberTransmitNotify notify; void *notify_cls; struct GNUNET_MULTICAST_Member *member; uint64_t request_id; uint64_t fragment_offset; }; /** * Handle for a multicast group member. */ struct GNUNET_MULTICAST_Member { struct GNUNET_MULTICAST_Group grp; struct GNUNET_MULTICAST_MemberRequestHandle req_handle; struct GNUNET_CRYPTO_EddsaPublicKey group_key; struct GNUNET_CRYPTO_EddsaPrivateKey member_key; struct GNUNET_PeerIdentity origin; struct GNUNET_PeerIdentity relays; uint32_t relay_count; struct GNUNET_MessageHeader *join_request; GNUNET_MULTICAST_JoinCallback join_cb; GNUNET_MULTICAST_MembershipTestCallback member_test_cb; GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb; GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb; GNUNET_MULTICAST_MessageCallback message_cb; void *cls; uint64_t next_fragment_id; struct GNUNET_HashCode group_key_hash; }; /** * Handle that identifies a join request. * * Used to match calls to #GNUNET_MULTICAST_JoinCallback to the * corresponding calls to #GNUNET_MULTICAST_join_decision(). */ struct GNUNET_MULTICAST_JoinHandle { }; /** * Handle to pass back for the answer of a membership test. */ struct GNUNET_MULTICAST_MembershipTestHandle { }; /** * Opaque handle to a replay request from the multicast service. */ struct GNUNET_MULTICAST_ReplayHandle { }; /** * Handle for a replay request. */ struct GNUNET_MULTICAST_MemberReplayHandle { }; /** * Iterator callback for calling message callbacks for all groups. */ static int message_callback (void *cls, const struct GNUNET_HashCode *chan_key_hash, void *group) { const struct GNUNET_MessageHeader *msg = cls; struct GNUNET_MULTICAST_Group *grp = group; if (GNUNET_YES == grp->is_origin) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling origin's message callback " "for a message of type %u and size %u.\n", ntohs (msg->type), ntohs (msg->size)); struct GNUNET_MULTICAST_Origin *orig = (struct GNUNET_MULTICAST_Origin *) grp; orig->message_cb (orig->cls, msg); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling slave's message callback " "for a message of type %u and size %u.\n", ntohs (msg->type), ntohs (msg->size)); struct GNUNET_MULTICAST_Member *mem = (struct GNUNET_MULTICAST_Member *) grp; mem->message_cb (mem->cls, msg); } return GNUNET_YES; } /** * Handle a multicast message from the service. * * Call message callbacks of all origins and members of the destination group. * * @param grp Destination group of the message. * @param msg The message. */ static void handle_multicast_message (struct GNUNET_MULTICAST_Group *grp, const struct GNUNET_MULTICAST_MessageHeader *msg) { struct GNUNET_HashCode *hash; if (GNUNET_YES == grp->is_origin) { struct GNUNET_MULTICAST_Origin *orig = (struct GNUNET_MULTICAST_Origin *) grp; hash = &orig->pub_key_hash; } else { struct GNUNET_MULTICAST_Member *mem = (struct GNUNET_MULTICAST_Member *) grp; hash = &mem->group_key_hash; } if (origins != NULL) GNUNET_CONTAINER_multihashmap_get_multiple (origins, hash, message_callback, (void *) msg); if (members != NULL) GNUNET_CONTAINER_multihashmap_get_multiple (members, hash, message_callback, (void *) msg); } /** * Iterator callback for calling request callbacks of origins. */ static int request_callback (void *cls, const struct GNUNET_HashCode *chan_key_hash, void *origin) { const struct GNUNET_MULTICAST_RequestHeader *req = cls; struct GNUNET_MULTICAST_Origin *orig = origin; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling request callback for a request of type %u and size %u.\n", ntohs (req->header.type), ntohs (req->header.size)); orig->request_cb (orig->cls, &req->member_key, (const struct GNUNET_MessageHeader *) req, 0); return GNUNET_YES; } /** * Handle a multicast request from the service. * * Call request callbacks of all origins of the destination group. * * @param grp Destination group of the message. * @param msg The message. */ static void handle_multicast_request (const struct GNUNET_HashCode *group_key_hash, const struct GNUNET_MULTICAST_RequestHeader *req) { if (NULL != origins) GNUNET_CONTAINER_multihashmap_get_multiple (origins, group_key_hash, request_callback, (void *) req); } /** * Function to call with the decision made for a join request. * * Must be called once and only once in response to an invocation of the * #GNUNET_MULTICAST_JoinCallback. * * @param jh Join request handle. * @param is_admitted #GNUNET_YES if joining is approved, * #GNUNET_NO if it is disapproved * @param relay_count Number of relays given. * @param relays Array of suggested peers that might be useful relays to use * when joining the multicast group (essentially a list of peers that * are already part of the multicast group and might thus be willing * to help with routing). If empty, only this local peer (which must * be the multicast origin) is a good candidate for building the * multicast tree. Note that it is unnecessary to specify our own * peer identity in this array. * @param join_response Message to send in response to the joining peer; * can also be used to redirect the peer to a different group at the * application layer; this response is to be transmitted to the * peer that issued the request even if admission is denied. */ struct GNUNET_MULTICAST_ReplayHandle * GNUNET_MULTICAST_join_decision (struct GNUNET_MULTICAST_JoinHandle *jh, int is_admitted, unsigned int relay_count, const struct GNUNET_PeerIdentity *relays, const struct GNUNET_MessageHeader *join_response) { return NULL; } /** * Call informing multicast about the decision taken for a membership test. * * @param mth Handle that was given for the query. * @param result #GNUNET_YES if peer was a member, #GNUNET_NO if peer was not a member, * #GNUNET_SYSERR if we cannot answer the membership test. */ void GNUNET_MULTICAST_membership_test_result (struct GNUNET_MULTICAST_MembershipTestHandle *mth, int result) { } /** * Replay a message fragment for the multicast group. * * @param rh Replay handle identifying which replay operation was requested. * @param msg Replayed message fragment, NULL if unknown/error. * @param ec Error code. */ void GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh, const struct GNUNET_MessageHeader *msg, enum GNUNET_MULTICAST_ReplayErrorCode ec) { } /** * Indicate the end of the replay session. * * Invalidates the replay handle. * * @param rh Replay session to end. */ void GNUNET_MULTICAST_replay_response_end (struct GNUNET_MULTICAST_ReplayHandle *rh) { } /** * Replay a message for the multicast group. * * @param rh Replay handle identifying which replay operation was requested. * @param notify Function to call to get the message. * @param notify_cls Closure for @a notify. */ void GNUNET_MULTICAST_replay_response2 (struct GNUNET_MULTICAST_ReplayHandle *rh, GNUNET_MULTICAST_ReplayTransmitNotify notify, void *notify_cls) { } /** * Start a multicast group. * * Will advertise the origin in the P2P overlay network under the respective * public key so that other peer can find this peer to join it. Peers that * issue GNUNET_MULTICAST_member_join() can then transmit a join request to * either an existing group member or to the origin. If the joining is * approved, the member is cleared for @e replay and will begin to receive * messages transmitted to the group. If joining is disapproved, the failed * candidate will be given a response. Members in the group can send messages * to the origin (one at a time). * * @param cfg Configuration to use. * @param priv_key ECC key that will be used to sign messages for this * multicast session; public key is used to identify the multicast group; * @param next_fragment_id Next fragment ID to continue counting fragments from * when restarting the origin. 0 for a new group. * @param join_cb Function called to approve / disapprove joining of a peer. * @param mem_test_cb Function multicast can use to test group membership. * @param replay_frag_cb Function that can be called to replay a message fragment. * @param replay_msg_cb Function that can be called to replay a message. * @param request_cb Function called with message fragments from group members. * @param message_cb Function called with the message fragments sent to the * network by GNUNET_MULTICAST_origin_to_all(). These message fragments * should be stored for answering replay requests later. * @param cls Closure for the various callbacks that follow. * @return Handle for the origin, NULL on error. */ struct GNUNET_MULTICAST_Origin * GNUNET_MULTICAST_origin_start (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv_key, uint64_t next_fragment_id, GNUNET_MULTICAST_JoinCallback join_cb, GNUNET_MULTICAST_MembershipTestCallback mem_test_cb, GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb, GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb, GNUNET_MULTICAST_RequestCallback request_cb, GNUNET_MULTICAST_MessageCallback message_cb, void *cls) { struct GNUNET_MULTICAST_Origin *orig = GNUNET_malloc (sizeof (*orig)); orig->grp.is_origin = GNUNET_YES; orig->priv_key = *priv_key; orig->next_fragment_id = next_fragment_id; orig->join_cb = join_cb; orig->mem_test_cb = mem_test_cb; orig->replay_frag_cb = replay_frag_cb; orig->replay_msg_cb = replay_msg_cb; orig->request_cb = request_cb; orig->message_cb = message_cb; orig->cls = cls; GNUNET_CRYPTO_eddsa_key_get_public (&orig->priv_key, &orig->pub_key); GNUNET_CRYPTO_hash (&orig->pub_key, sizeof (orig->pub_key), &orig->pub_key_hash); if (NULL == origins) origins = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); GNUNET_CONTAINER_multihashmap_put (origins, &orig->pub_key_hash, orig, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); /* FIXME: send ORIGIN_START to service */ return orig; } /** * Stop a multicast group. * * @param origin Multicast group to stop. */ void GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *orig) { GNUNET_CONTAINER_multihashmap_remove (origins, &orig->pub_key_hash, orig); GNUNET_free (orig); } /* FIXME: for now just call clients' callbacks * without sending anything to multicast. */ static void schedule_origin_to_all (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_DEBUG, "schedule_origin_to_all()\n"); struct GNUNET_MULTICAST_Origin *orig = cls; struct GNUNET_MULTICAST_OriginMessageHandle *mh = &orig->msg_handle; size_t buf_size = GNUNET_MULTICAST_FRAGMENT_MAX_SIZE; char buf[GNUNET_MULTICAST_FRAGMENT_MAX_SIZE] = ""; struct GNUNET_MULTICAST_MessageHeader *msg = (struct GNUNET_MULTICAST_MessageHeader *) buf; int ret = mh->notify (mh->notify_cls, &buf_size, &msg[1]); if (! (GNUNET_YES == ret || GNUNET_NO == ret) || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < buf_size) { LOG (GNUNET_ERROR_TYPE_ERROR, "OriginTransmitNotify() returned error or invalid message size.\n"); /* FIXME: handle error */ return; } if (GNUNET_NO == ret && 0 == buf_size) return; /* Transmission paused. */ msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE); msg->header.size = htons (sizeof (*msg) + buf_size); msg->message_id = GNUNET_htonll (mh->message_id); msg->group_generation = mh->group_generation; /* FIXME: add fragment ID and signature in the service instead of here */ msg->fragment_id = GNUNET_ntohll (orig->next_fragment_id++); msg->fragment_offset = GNUNET_ntohll (mh->fragment_offset); mh->fragment_offset += sizeof (*msg) + buf_size; msg->purpose.size = htonl (sizeof (*msg) + buf_size - sizeof (msg->header) - sizeof (msg->hop_counter) - sizeof (msg->signature)); msg->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&orig->priv_key, &msg->purpose, &msg->signature)) { /* FIXME: handle error */ return; } /* FIXME: send msg to the service and only then call handle_multicast_message * with the returned signed message. */ handle_multicast_message (&orig->grp, msg); if (GNUNET_NO == ret) GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), schedule_origin_to_all, orig); } /** * Send a message to the multicast group. * * @param origin Handle to the multicast group. * @param message_id Application layer ID for the message. Opaque to multicast. * @param group_generation Group generation of the message. Documented in * `struct GNUNET_MULTICAST_MessageHeader`. * @param notify Function to call to get the message. * @param notify_cls Closure for @a notify. * @return NULL on error (i.e. request already pending). */ struct GNUNET_MULTICAST_OriginMessageHandle * GNUNET_MULTICAST_origin_to_all (struct GNUNET_MULTICAST_Origin *origin, uint64_t message_id, uint64_t group_generation, GNUNET_MULTICAST_OriginTransmitNotify notify, void *notify_cls) { struct GNUNET_MULTICAST_OriginMessageHandle *mh = &origin->msg_handle; mh->origin = origin; mh->message_id = message_id; mh->group_generation = group_generation; mh->notify = notify; mh->notify_cls = notify_cls; /* add some delay for testing */ GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), schedule_origin_to_all, origin); return &origin->msg_handle; } /** * Resume message transmission to multicast group. * * @param mh Request to cancel. */ void GNUNET_MULTICAST_origin_to_all_resume (struct GNUNET_MULTICAST_OriginMessageHandle *mh) { GNUNET_SCHEDULER_add_now (schedule_origin_to_all, mh->origin); } /** * Cancel request for message transmission to multicast group. * * @param mh Request to cancel. */ void GNUNET_MULTICAST_origin_to_all_cancel (struct GNUNET_MULTICAST_OriginMessageHandle *mh) { } /** * Join a multicast group. * * The entity joining is always the local peer. Further information about the * candidate can be provided in the @a join_request message. If the join fails, the * @a message_cb is invoked with a (failure) response and then with NULL. If * the join succeeds, outstanding (state) messages and ongoing multicast * messages will be given to the @a message_cb until the member decides to part * the group. The @a test_cb and @a replay_cb functions may be called at * anytime by the multicast service to support relaying messages to other * members of the group. * * @param cfg Configuration to use. * @param group_key ECC public key that identifies the group to join. * @param member_key ECC key that identifies the member and used to sign * requests sent to the origin. * @param origin Peer ID of the origin to send unicast requsets to. If NULL, * unicast requests are sent back via multiple hops on the reverse path * of multicast messages. * @param relay_count Number of peers in the @a relays array. * @param relays Peer identities of members of the group, which serve as relays * and can be used to join the group at. and send the @a join_request to. * If empty, the @a join_request is sent directly to the @a origin. * @param join_request Application-dependent join request to be passed to the peer * @a relay (might, for example, contain a user, bind user * identity/pseudonym to peer identity, application-level message to * origin, etc.). * @param join_cb Function called to approve / disapprove joining of a peer. * @param mem_test_cb Function multicast can use to test group membership. * @param replay_frag_cb Function that can be called to replay message fragments * this peer already knows from this group. NULL if this * client is unable to support replay. * @param replay_msg_cb Function that can be called to replay message fragments * this peer already knows from this group. NULL if this * client is unable to support replay. * @param message_cb Function to be called for all message fragments we * receive from the group, excluding those our @a replay_cb * already has. * @param cls Closure for callbacks. * @return Handle for the member, NULL on error. */ struct GNUNET_MULTICAST_Member * GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EddsaPublicKey *group_key, const struct GNUNET_CRYPTO_EddsaPrivateKey *member_key, const struct GNUNET_PeerIdentity *origin, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, const struct GNUNET_MessageHeader *join_request, GNUNET_MULTICAST_JoinCallback join_cb, GNUNET_MULTICAST_MembershipTestCallback member_test_cb, GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb, GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb, GNUNET_MULTICAST_MessageCallback message_cb, void *cls) { struct GNUNET_MULTICAST_Member *mem = GNUNET_malloc (sizeof (*mem)); mem->group_key = *group_key; mem->member_key = *member_key; mem->origin = *origin; mem->relay_count = relay_count; mem->relays = *relays; mem->join_cb = join_cb; mem->member_test_cb = member_test_cb; mem->replay_frag_cb = replay_frag_cb; mem->message_cb = message_cb; mem->cls = cls; if (NULL != join_request) { uint16_t size = ntohs (join_request->size); mem->join_request = GNUNET_malloc (size); memcpy (mem->join_request, join_request, size); } GNUNET_CRYPTO_hash (&mem->group_key, sizeof (mem->group_key), &mem->group_key_hash); if (NULL == members) members = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); GNUNET_CONTAINER_multihashmap_put (members, &mem->group_key_hash, mem, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); /* FIXME: send MEMBER_JOIN to service */ return mem; } /** * Part a multicast group. * * Disconnects from all group members and invalidates the @a member handle. * * An application-dependent part message can be transmitted beforehand using * #GNUNET_MULTICAST_member_to_origin()) * * @param member Membership handle. */ void GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *mem) { GNUNET_CONTAINER_multihashmap_remove (members, &mem->group_key_hash, mem); GNUNET_free (mem); } /** * Request a fragment to be replayed by fragment ID. * * Useful if messages below the @e max_known_fragment_id given when joining are * needed and not known to the client. * * @param member Membership handle. * @param fragment_id ID of a message fragment that this client would like to see replayed. * @param flags Additional flags for the replay request. It is used and defined * by the replay callback. FIXME: which replay callback? FIXME: use enum? * FIXME: why not pass reply cb here? * @return Replay request handle, NULL on error. */ struct GNUNET_MULTICAST_MemberReplayHandle * GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *member, uint64_t fragment_id, uint64_t flags) { return NULL; } /** * Request a message fragment to be replayed. * * Useful if messages below the @e max_known_fragment_id given when joining are * needed and not known to the client. * * @param member Membership handle. * @param message_id ID of the message this client would like to see replayed. * @param fragment_offset Offset of the fragment within the message to replay. * @param flags Additional flags for the replay request. It is used & defined * by the replay callback. * @param result_cb Function to be called for the replayed message. * @param result_cb_cls Closure for @a result_cb. * @return Replay request handle, NULL on error. */ struct GNUNET_MULTICAST_MemberReplayHandle * GNUNET_MULTICAST_member_replay_message (struct GNUNET_MULTICAST_Member *member, uint64_t message_id, uint64_t fragment_offset, uint64_t flags, GNUNET_MULTICAST_ResultCallback result_cb, void *result_cb_cls) { return NULL; } /** * Cancel a replay request. * * @param rh Request to cancel. */ void GNUNET_MULTICAST_member_replay_cancel (struct GNUNET_MULTICAST_MemberReplayHandle *rh) { } /* FIXME: for now just send back to the client what it sent. */ static void schedule_member_to_origin (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_DEBUG, "schedule_member_to_origin()\n"); struct GNUNET_MULTICAST_Member *mem = cls; struct GNUNET_MULTICAST_MemberRequestHandle *rh = &mem->req_handle; size_t buf_size = GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD; char buf[GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD] = ""; struct GNUNET_MULTICAST_RequestHeader *req = (struct GNUNET_MULTICAST_RequestHeader *) buf; int ret = rh->notify (rh->notify_cls, &buf_size, &req[1]); if (! (GNUNET_YES == ret || GNUNET_NO == ret) || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < buf_size) { LOG (GNUNET_ERROR_TYPE_ERROR, "MemberTransmitNotify() returned error or invalid message size.\n"); /* FIXME: handle error */ return; } if (GNUNET_NO == ret && 0 == buf_size) return; /* Transmission paused. */ req->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST); req->header.size = htons (sizeof (*req) + buf_size); req->request_id = GNUNET_htonll (rh->request_id); /* FIXME: add fragment ID and signature in the service instead of here */ req->fragment_id = GNUNET_ntohll (mem->next_fragment_id++); req->fragment_offset = GNUNET_ntohll (rh->fragment_offset); rh->fragment_offset += sizeof (*req) + buf_size; req->purpose.size = htonl (sizeof (*req) + buf_size - sizeof (req->header) - sizeof (req->member_key) - sizeof (req->signature)); req->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (&mem->member_key, &req->purpose, &req->signature)) { /* FIXME: handle error */ return; } /* FIXME: send req to the service and only then call handle_multicast_request * with the returned request. */ handle_multicast_request (&mem->group_key_hash, req); if (GNUNET_NO == ret) GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), schedule_member_to_origin, mem); } /** * Send a message to the origin of the multicast group. * * @param member Membership handle. * @param request_id Application layer ID for the request. Opaque to multicast. * @param notify Callback to call to get the message. * @param notify_cls Closure for @a notify. * @return Handle to cancel request, NULL on error (i.e. request already pending). */ struct GNUNET_MULTICAST_MemberRequestHandle * GNUNET_MULTICAST_member_to_origin (struct GNUNET_MULTICAST_Member *member, uint64_t request_id, GNUNET_MULTICAST_MemberTransmitNotify notify, void *notify_cls) { struct GNUNET_MULTICAST_MemberRequestHandle *rh = &member->req_handle; rh->member = member; rh->request_id = request_id; rh->notify = notify; rh->notify_cls = notify_cls; /* FIXME: remove delay, it's there only for testing */ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), schedule_member_to_origin, member); return &member->req_handle; } /** * Resume message transmission to origin. * * @param rh Request to cancel. */ void GNUNET_MULTICAST_member_to_origin_resume (struct GNUNET_MULTICAST_MemberRequestHandle *rh) { } /** * Cancel request for message transmission to origin. * * @param rh Request to cancel. */ void GNUNET_MULTICAST_member_to_origin_cancel (struct GNUNET_MULTICAST_MemberRequestHandle *rh) { } /* end of multicast_api.c */ gnunet-0.10.1/src/multicast/Makefile.in0000644000175000017500000012700412320752062014656 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-multicast$(EXEEXT) libexec_PROGRAMS = gnunet-service-multicast$(EXEEXT) check_PROGRAMS = test_multicast_api$(EXEEXT) subdir = src/multicast DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/multicast.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = multicast.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetmulticast_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetmulticast_la_OBJECTS = multicast_api.lo libgnunetmulticast_la_OBJECTS = $(am_libgnunetmulticast_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetmulticast_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetmulticast_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_multicast_OBJECTS = gnunet-multicast.$(OBJEXT) gnunet_multicast_OBJECTS = $(am_gnunet_multicast_OBJECTS) gnunet_multicast_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_gnunet_service_multicast_OBJECTS = \ gnunet-service-multicast.$(OBJEXT) gnunet_service_multicast_OBJECTS = \ $(am_gnunet_service_multicast_OBJECTS) gnunet_service_multicast_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_multicast_api_OBJECTS = test_multicast_api.$(OBJEXT) test_multicast_api_OBJECTS = $(am_test_multicast_api_OBJECTS) test_multicast_api_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetmulticast_la_SOURCES) $(gnunet_multicast_SOURCES) \ $(gnunet_service_multicast_SOURCES) \ $(test_multicast_api_SOURCES) DIST_SOURCES = $(libgnunetmulticast_la_SOURCES) \ $(gnunet_multicast_SOURCES) \ $(gnunet_service_multicast_SOURCES) \ $(test_multicast_api_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ multicast.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage lib_LTLIBRARIES = libgnunetmulticast.la libgnunetmulticast_la_SOURCES = \ multicast_api.c \ multicast.h libgnunetmulticast_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetmulticast_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 gnunet_multicast_SOURCES = \ gnunet-multicast.c gnunet_multicast_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_multicast_SOURCES = \ gnunet-service-multicast.c gnunet_service_multicast_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_multicast_api_SOURCES = \ test_multicast_api.c test_multicast_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/multicast/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/multicast/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): multicast.conf: $(top_builddir)/config.status $(srcdir)/multicast.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetmulticast.la: $(libgnunetmulticast_la_OBJECTS) $(libgnunetmulticast_la_DEPENDENCIES) $(EXTRA_libgnunetmulticast_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetmulticast_la_LINK) -rpath $(libdir) $(libgnunetmulticast_la_OBJECTS) $(libgnunetmulticast_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-multicast$(EXEEXT): $(gnunet_multicast_OBJECTS) $(gnunet_multicast_DEPENDENCIES) $(EXTRA_gnunet_multicast_DEPENDENCIES) @rm -f gnunet-multicast$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_multicast_OBJECTS) $(gnunet_multicast_LDADD) $(LIBS) gnunet-service-multicast$(EXEEXT): $(gnunet_service_multicast_OBJECTS) $(gnunet_service_multicast_DEPENDENCIES) $(EXTRA_gnunet_service_multicast_DEPENDENCIES) @rm -f gnunet-service-multicast$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_multicast_OBJECTS) $(gnunet_service_multicast_LDADD) $(LIBS) test_multicast_api$(EXEEXT): $(test_multicast_api_OBJECTS) $(test_multicast_api_DEPENDENCIES) $(EXTRA_test_multicast_api_DEPENDENCIES) @rm -f test_multicast_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_multicast_api_OBJECTS) $(test_multicast_api_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-multicast.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-multicast.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multicast_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_multicast_api.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_multicast_api.log: test_multicast_api$(EXEEXT) @p='test_multicast_api$(EXEEXT)'; \ b='test_multicast_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/multicast/Makefile.am0000644000175000017500000000245112320751517014647 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ multicast.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif lib_LTLIBRARIES = libgnunetmulticast.la libgnunetmulticast_la_SOURCES = \ multicast_api.c \ multicast.h libgnunetmulticast_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetmulticast_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 bin_PROGRAMS = \ gnunet-multicast libexec_PROGRAMS = \ gnunet-service-multicast gnunet_multicast_SOURCES = \ gnunet-multicast.c gnunet_multicast_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_multicast_SOURCES = \ gnunet-service-multicast.c gnunet_service_multicast_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) check_PROGRAMS = \ test_multicast_api if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_multicast_api_SOURCES = \ test_multicast_api.c test_multicast_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet-0.10.1/src/multicast/multicast.h0000644000175000017500000001505512306275771015004 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file multicast/multicast.h * @brief multicast IPC messages * @author Christian Grothoff * @author Gabor X Toth */ #ifndef MULTICAST_H #define MULTICAST_H GNUNET_NETWORK_STRUCT_BEGIN /** * Header of a join request sent to the origin or another member. */ struct GNUNET_MULTICAST_JoinRequest { /** * Header for the join request. */ struct GNUNET_MessageHeader header; /** * ECC signature of the rest of the fields of the join request. * * Signature must match the public key of the joining member. */ struct GNUNET_CRYPTO_EddsaSignature signature; /** * Purpose for the signature and size of the signed data. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Public key of the target group. */ struct GNUNET_CRYPTO_EddsaPublicKey group_key; /** * Public key of the joining member. */ struct GNUNET_CRYPTO_EddsaPublicKey member_key; /** * Peer identity of the joining member. */ struct GNUNET_PeerIdentity member_peer; /* Followed by request body. */ }; /** * Message sent from the client to the service to notify the service * about a join decision. */ struct MulticastJoinDecisionMessage { /** * */ struct GNUNET_MessageHeader header; /** * Unique ID that identifies the associated join test. */ uint32_t uid; /** * #GNUNET_YES if the peer was admitted. */ int32_t is_admitted; /** * Number of relays given. */ uint32_t relay_count; /* followed by 'relay_count' peer identities */ /* followed by the join response message */ }; /** * Message sent from the client to the service to notify the service * about the result of a membership test. */ struct MulticastMembershipTestResponseMessage { /** * */ struct GNUNET_MessageHeader header; /** * Unique ID that identifies the associated membership test. */ uint32_t uid; /** * #GNUNET_YES if the peer is a member, #GNUNET_NO if peer was not a member, * #GNUNET_SYSERR if we cannot answer the test. */ int32_t is_admitted; }; /** * Message sent from the client to the service to give the service * a replayed message. */ struct MulticastReplayResponseMessage { /** * */ struct GNUNET_MessageHeader header; /** * Unique ID that identifies the associated replay session. */ uint32_t uid; /** * An `enum GNUNET_MULTICAST_ReplayErrorCode` identifying issues (in NBO). */ int32_t error_code; /* followed by replayed message */ }; /** * Message sent from the client to the service to notify the service * about the end of a replay session. */ struct MulticastReplayEndMessage { /** * */ struct GNUNET_MessageHeader header; /** * Unique ID that identifies the associated replay session. */ uint32_t uid; }; /** * Message sent from the client to the service to notify the service * about the starting of a multicast group with this peers as its origin. */ struct MulticastOriginStartMessage { /** * */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved; /** * Private, non-ephemeral key for the mutlicast group. */ struct GNUNET_CRYPTO_EddsaPrivateKey group_key; /** * Last fragment ID, used to continue counting fragments if we resume operating * a group. */ uint64_t last_fragment_id; }; /** * Message sent from the client to the service to broadcast to all group * members. */ struct MulticastBroadcastMessage { /** * */ struct GNUNET_MessageHeader header; /** * #GNUNET_OK normally, #GNUNET_SYSERR if the origin aborted the * transmission. */ int32_t status; /** * Message ID. */ uint64_t message_id; /** * Group generation. */ uint64_t group_generation; /** * Total message size. */ uint64_t total_size; }; /** * Message sent from the client to the service to join a multicast group. */ struct MulticastJoinMessage { /** * */ struct GNUNET_MessageHeader header; /** * Number of relays we (think) we already know about. */ uint32_t relay_count; /** * Public non-ephemeral key of the mutlicast group. */ struct GNUNET_CRYPTO_EddsaPublicKey group_key; /** * Our private key for the group. */ struct GNUNET_CRYPTO_EddsaPrivateKey member_key; /* followed by 'relay_count' `struct GNUNET_PeerIdentity`s */ }; /** * Message sent from the client to the service OR the service to the * client asking for a message fragment to be replayed. */ struct MulticastReplayRequestMessage { /** * The message type can be either * #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST or * #GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL. */ struct GNUNET_MessageHeader header; /** * Replay request ID. */ uint32_t uid; /** * ID of the message that is being requested. */ uint64_t message_id; /** * Offset of the fragment that is being requested. */ uint64_t fragment_offset; /** * Additional flags for the request. */ uint64_t flags; }; /** * Message sent from the client to the service to unicast to the group origin. */ struct MulticastUnicastToOriginMessage { /** * */ struct GNUNET_MessageHeader header; /** * Reserved (always 0). */ uint32_t reserved; /** * Message ID. */ uint64_t message_id; /** * Total message size. */ uint64_t total_size; /* followed by payload */ }; /** * Message sent from the client to the service to * cancel unicast to the group origin. */ struct MulticastUnicastToOriginCancelMessage { /** * */ struct GNUNET_MessageHeader header; /** * Reserved (always 0). */ uint32_t reserved; /** * Message ID. */ uint64_t message_id; }; GNUNET_NETWORK_STRUCT_END #endif /* end of multicast.h */ gnunet-0.10.1/src/multicast/gnunet-multicast.c0000644000175000017500000000413412225777501016267 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file multicast/gnunet-multicast.c * @brief multicast for writing a tool * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" /* #include "gnunet_multicast_service.h" */ /** * Final status code. */ static int ret; /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { /* main code here */ } /** * The main function. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { /* FIMXE: add options here */ GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-multicast", gettext_noop ("help text"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-multicast.c */ gnunet-0.10.1/src/multicast/gnunet-service-multicast.c0000644000175000017500000000751512306275771017735 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file multicast/gnunet-service-multicast.c * @brief program that does multicast * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { /* FIXME: do clean up here */ } /** * Handle a connecting client starting an origin. */ static void handle_origin_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Handle a client stopping an origin. */ static void handle_origin_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Handle a connecting client joining a group. */ static void handle_member_join (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Handle a client parting a group. */ static void handle_member_part (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Incoming message from a client. */ static void handle_multicast_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Incoming request from a client. */ static void handle_multicast_request (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Process multicast requests. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { { &handle_origin_start, NULL, GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START, 0 }, { &handle_origin_stop, NULL, GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_STOP, 0 }, { &handle_member_join, NULL, GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN, 0 }, { &handle_member_part, NULL, GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_PART, 0 }, { &handle_multicast_message, NULL, GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE, 0 }, { &handle_multicast_request, NULL, GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST, 0 }, {NULL, NULL, 0, 0} }; /* FIXME: do setup here */ GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, NULL); } /** * The main function for the multicast service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "multicast", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-multicast.c */ gnunet-0.10.1/src/datacache/0000755000175000017500000000000012320755623012563 500000000000000gnunet-0.10.1/src/datacache/datacache.c0000644000175000017500000002227512255010512014540 00000000000000/* This file is part of GNUnet (C) 2004, 2005, 2006, 2007, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datacache/datacache.c * @brief datacache API implementation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_datacache_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_datacache_plugin.h" #define LOG(kind,...) GNUNET_log_from (kind, "datacache", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,op,fn) GNUNET_log_from_strerror_file (kind, "datacache", op, fn) /** * Internal state of the datacache library. */ struct GNUNET_DATACACHE_Handle { /** * Bloomfilter to quickly tell if we don't have the content. */ struct GNUNET_CONTAINER_BloomFilter *filter; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Opaque handle for the statistics service. */ struct GNUNET_STATISTICS_Handle *stats; /** * Configuration section to use. */ char *section; /** * API of the transport as returned by the plugin's * initialization function. */ struct GNUNET_DATACACHE_PluginFunctions *api; /** * Short name for the plugin (i.e. "sqlite"). */ char *short_name; /** * Name of the library (i.e. "gnunet_plugin_datacache_sqlite"). */ char *lib_name; /** * Name for the bloom filter file. */ char *bloom_name; /** * Environment provided to our plugin. */ struct GNUNET_DATACACHE_PluginEnvironment env; /** * How much space is in use right now? */ unsigned long long utilization; }; /** * Function called by plugins to notify the datacache * about content deletions. * * @param cls closure * @param key key of the content that was deleted * @param size number of bytes that were made available */ static void env_delete_notify (void *cls, const struct GNUNET_HashCode * key, size_t size) { struct GNUNET_DATACACHE_Handle *h = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Content under key `%s' discarded\n", GNUNET_h2s (key)); GNUNET_assert (h->utilization >= size); h->utilization -= size; GNUNET_CONTAINER_bloomfilter_remove (h->filter, key); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# bytes stored"), - (long long) size, GNUNET_NO); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# items stored"), -1, GNUNET_NO); } /** * Create a data cache. * * @param cfg configuration to use * @param section section in the configuration that contains our options * @return handle to use to access the service */ struct GNUNET_DATACACHE_Handle * GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section) { unsigned int bf_size; unsigned long long quota; struct GNUNET_DATACACHE_Handle *ret; char *libname; char *name; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size (cfg, section, "QUOTA", "a)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("No `%s' specified for `%s' in configuration!\n"), "QUOTA", section); return NULL; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, "DATABASE", &name)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("No `%s' specified for `%s' in configuration!\n"), "DATABASE", section); return NULL; } bf_size = quota / 32; /* 8 bit per entry, 1 bit per 32 kb in DB */ ret = GNUNET_new (struct GNUNET_DATACACHE_Handle); if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF")) { if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "DISABLE_BF_RC")) { ret->bloom_name = GNUNET_DISK_mktemp ("gnunet-datacachebloom"); } if (NULL != ret->bloom_name) { ret->filter = GNUNET_CONTAINER_bloomfilter_load (ret->bloom_name, quota / 1024, /* 8 bit per entry in DB, expect 1k entries */ 5); } if (NULL == ret->filter) { ret->filter = GNUNET_CONTAINER_bloomfilter_init (NULL, bf_size, 5); /* approx. 3% false positives at max use */ } } ret->stats = GNUNET_STATISTICS_create ("datacache", cfg); ret->section = GNUNET_strdup (section); ret->env.cfg = cfg; ret->env.delete_notify = &env_delete_notify; ret->env.section = ret->section; ret->env.cls = ret; ret->env.delete_notify = &env_delete_notify; ret->env.quota = quota; LOG (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' datacache plugin\n"), name); GNUNET_asprintf (&libname, "libgnunet_plugin_datacache_%s", name); ret->short_name = name; ret->lib_name = libname; ret->api = GNUNET_PLUGIN_load (libname, &ret->env); if (ret->api == NULL) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to load datacache plugin for `%s'\n"), name); GNUNET_DATACACHE_destroy (ret); return NULL; } return ret; } /** * Destroy a data cache (and free associated resources). * * @param h handle to the datastore */ void GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h) { if (NULL != h->filter) GNUNET_CONTAINER_bloomfilter_free (h->filter); if (h->api != NULL) GNUNET_break (NULL == GNUNET_PLUGIN_unload (h->lib_name, h->api)); GNUNET_free (h->lib_name); GNUNET_free (h->short_name); GNUNET_free (h->section); if (h->bloom_name != NULL) { if (0 != UNLINK (h->bloom_name)) GNUNET_log_from_strerror_file (GNUNET_ERROR_TYPE_WARNING, "datacache", "unlink", h->bloom_name); GNUNET_free (h->bloom_name); } GNUNET_STATISTICS_destroy (h->stats, GNUNET_NO); GNUNET_free (h); } /** * Store an item in the datastore. * * @param h handle to the datacache * @param key key to store data under * @param size number of bytes in data * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case * @param path_info_len number of entries in @a path_info * @param path_info a path through the network * @return #GNUNET_OK on success, #GNUNET_SYSERR on error, #GNUNET_NO if duplicate */ int GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info) { ssize_t used; used = h->api->put (h->api->cls, key, size, data, type, discard_time, path_info_len, path_info); if (-1 == used) { GNUNET_break (0); return GNUNET_SYSERR; } if (0 == used) { /* duplicate */ return GNUNET_NO; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Stored data under key `%s' in cache\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# bytes stored"), size, GNUNET_NO); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# items stored"), 1, GNUNET_NO); if (NULL != h->filter) GNUNET_CONTAINER_bloomfilter_add (h->filter, key); while (h->utilization + used > h->env.quota) GNUNET_assert (GNUNET_OK == h->api->del (h->api->cls)); h->utilization += used; return GNUNET_OK; } /** * Iterate over the results for a particular key * in the datacache. * * @param h handle to the datacache * @param key what to look up * @param type entries of which type are relevant? * @param iter maybe NULL (to just count) * @param iter_cls closure for iter * @return the number of results found */ unsigned int GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls) { GNUNET_STATISTICS_update (h->stats, gettext_noop ("# requests received"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing request for key `%s'\n", GNUNET_h2s (key)); if ( (NULL != h->filter) && (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_test (h->filter, key)) ) { GNUNET_STATISTICS_update (h->stats, gettext_noop ("# requests filtered by bloom filter"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Bloomfilter filters request for key `%s'\n", GNUNET_h2s (key)); return 0; /* can not be present */ } return h->api->get (h->api->cls, key, type, iter, iter_cls); } /* end of datacache_api.c */ gnunet-0.10.1/src/datacache/perf_datacache_data_sqlite.conf0000644000175000017500000000005612225230043020622 00000000000000[perfcache] QUOTA = 500 KB DATABASE = sqlite gnunet-0.10.1/src/datacache/test_datacache_data_heap.conf0000644000175000017500000000005212225230043020255 00000000000000[testcache] QUOTA = 1 MB DATABASE = heap gnunet-0.10.1/src/datacache/plugin_datacache_template.c0000644000175000017500000000766512255010512020017 00000000000000/* This file is part of GNUnet (C) 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datacache/plugin_datacache_template.c * @brief template for an implementation of a database backend for the datacache * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_datacache_plugin.h" /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATACACHE_PluginEnvironment *env; }; /** * Store an item in the datastore. * * @param cls closure (our "struct Plugin") * @param key key to store data under * @param size number of bytes in data * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case * @param path_info_len number of entries in 'path_info' * @param path_info a path through the network * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ static ssize_t template_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info) { GNUNET_break (0); return -1; } /** * Iterate over the results for a particular key * in the datastore. * * @param cls closure (our "struct Plugin") * @param key * @param type entries of which type are relevant? * @param iter maybe NULL (to just count) * @param iter_cls closure for iter * @return the number of results found */ static unsigned int template_plugin_get (void *cls, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls) { GNUNET_break (0); return 0; } /** * Delete the entry with the lowest expiration value * from the datacache right now. * * @param cls closure (our "struct Plugin") * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int template_plugin_del (void *cls) { GNUNET_break (0); return GNUNET_SYSERR; } /** * Entry point for the plugin. * * @param cls closure (the "struct GNUNET_DATACACHE_PluginEnvironmnet") * @return the plugin's closure (our "struct Plugin") */ void * libgnunet_plugin_datacache_template_init (void *cls) { struct GNUNET_DATACACHE_PluginEnvironment *env = cls; struct GNUNET_DATACACHE_PluginFunctions *api; struct Plugin *plugin; plugin = GNUNET_new (struct Plugin); plugin->env = env; api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions); api->cls = plugin; api->get = &template_plugin_get; api->put = &template_plugin_put; api->del = &template_plugin_del; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "template", _("Template datacache running\n")); return api; } /** * Exit point from the plugin. * * @param cls closure (our "struct Plugin") * @return NULL */ void * libgnunet_plugin_datacache_template_done (void *cls) { struct GNUNET_DATACACHE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_datacache_template.c */ gnunet-0.10.1/src/datacache/test_datacache_data_sqlite.conf0000644000175000017500000000005512225230043020644 00000000000000[testcache] QUOTA = 1 MB DATABASE = sqlite gnunet-0.10.1/src/datacache/datacache.conf0000644000175000017500000000010012225230043015222 00000000000000[datacache-postgres] CONFIG = connect_timeout=10; dbname=gnunet gnunet-0.10.1/src/datacache/test_datacache_data_postgres.conf0000644000175000017500000000016512225230043021213 00000000000000 [testcache] QUOTA = 1 MB DATABASE = postgres [datacache-postgres] CONFIG = connect_timeout=10; dbname=gnunetcheck gnunet-0.10.1/src/datacache/Makefile.in0000644000175000017500000017016512320752060014552 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = $(am__EXEEXT_2) $(am__EXEEXT_4) $(am__EXEEXT_6) subdir = src/datacache DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgcfg_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunet_plugin_datacache_heap_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunet_plugin_datacache_heap_la_OBJECTS = \ plugin_datacache_heap.lo libgnunet_plugin_datacache_heap_la_OBJECTS = \ $(am_libgnunet_plugin_datacache_heap_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_datacache_heap_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datacache_heap_la_LDFLAGS) $(LDFLAGS) -o $@ libgnunet_plugin_datacache_postgres_la_DEPENDENCIES = \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunet_plugin_datacache_postgres_la_OBJECTS = libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.lo libgnunet_plugin_datacache_postgres_la_OBJECTS = \ $(am_libgnunet_plugin_datacache_postgres_la_OBJECTS) libgnunet_plugin_datacache_postgres_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datacache_postgres_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_POSTGRES_TRUE@am_libgnunet_plugin_datacache_postgres_la_rpath = \ @HAVE_POSTGRES_TRUE@ -rpath $(plugindir) libgnunet_plugin_datacache_sqlite_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunet_plugin_datacache_sqlite_la_OBJECTS = \ plugin_datacache_sqlite.lo libgnunet_plugin_datacache_sqlite_la_OBJECTS = \ $(am_libgnunet_plugin_datacache_sqlite_la_OBJECTS) libgnunet_plugin_datacache_sqlite_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datacache_sqlite_la_LDFLAGS) $(LDFLAGS) -o \ $@ @HAVE_SQLITE_TRUE@am_libgnunet_plugin_datacache_sqlite_la_rpath = \ @HAVE_SQLITE_TRUE@ -rpath $(plugindir) libgnunet_plugin_datacache_template_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunet_plugin_datacache_template_la_OBJECTS = \ plugin_datacache_template.lo libgnunet_plugin_datacache_template_la_OBJECTS = \ $(am_libgnunet_plugin_datacache_template_la_OBJECTS) libgnunet_plugin_datacache_template_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datacache_template_la_LDFLAGS) $(LDFLAGS) \ -o $@ libgnunetdatacache_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetdatacache_la_OBJECTS = datacache.lo libgnunetdatacache_la_OBJECTS = $(am_libgnunetdatacache_la_OBJECTS) libgnunetdatacache_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetdatacache_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_BENCHMARKS_TRUE@@HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_1 = perf_datacache_sqlite$(EXEEXT) @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_2 = test_datacache_sqlite$(EXEEXT) \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ test_datacache_quota_sqlite$(EXEEXT) \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ $(am__EXEEXT_1) @HAVE_BENCHMARKS_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_3 = perf_datacache_heap$(EXEEXT) @HAVE_TESTING_TRUE@am__EXEEXT_4 = test_datacache_heap$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_datacache_quota_heap$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_3) @HAVE_BENCHMARKS_TRUE@@HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_5 = perf_datacache_postgres$(EXEEXT) @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_6 = test_datacache_postgres$(EXEEXT) \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ test_datacache_quota_postgres$(EXEEXT) \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ $(am__EXEEXT_5) am_perf_datacache_heap_OBJECTS = perf_datacache.$(OBJEXT) perf_datacache_heap_OBJECTS = $(am_perf_datacache_heap_OBJECTS) perf_datacache_heap_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_datacache_postgres_OBJECTS = perf_datacache.$(OBJEXT) perf_datacache_postgres_OBJECTS = \ $(am_perf_datacache_postgres_OBJECTS) perf_datacache_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_datacache_sqlite_OBJECTS = perf_datacache.$(OBJEXT) perf_datacache_sqlite_OBJECTS = $(am_perf_datacache_sqlite_OBJECTS) perf_datacache_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datacache_heap_OBJECTS = test_datacache.$(OBJEXT) test_datacache_heap_OBJECTS = $(am_test_datacache_heap_OBJECTS) test_datacache_heap_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datacache_postgres_OBJECTS = test_datacache.$(OBJEXT) test_datacache_postgres_OBJECTS = \ $(am_test_datacache_postgres_OBJECTS) test_datacache_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datacache_quota_heap_OBJECTS = test_datacache_quota.$(OBJEXT) test_datacache_quota_heap_OBJECTS = \ $(am_test_datacache_quota_heap_OBJECTS) test_datacache_quota_heap_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datacache_quota_postgres_OBJECTS = \ test_datacache_quota.$(OBJEXT) test_datacache_quota_postgres_OBJECTS = \ $(am_test_datacache_quota_postgres_OBJECTS) test_datacache_quota_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datacache_quota_sqlite_OBJECTS = \ test_datacache_quota.$(OBJEXT) test_datacache_quota_sqlite_OBJECTS = \ $(am_test_datacache_quota_sqlite_OBJECTS) test_datacache_quota_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datacache_sqlite_OBJECTS = test_datacache.$(OBJEXT) test_datacache_sqlite_OBJECTS = $(am_test_datacache_sqlite_OBJECTS) test_datacache_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_datacache_heap_la_SOURCES) \ $(libgnunet_plugin_datacache_postgres_la_SOURCES) \ $(libgnunet_plugin_datacache_sqlite_la_SOURCES) \ $(libgnunet_plugin_datacache_template_la_SOURCES) \ $(libgnunetdatacache_la_SOURCES) \ $(perf_datacache_heap_SOURCES) \ $(perf_datacache_postgres_SOURCES) \ $(perf_datacache_sqlite_SOURCES) \ $(test_datacache_heap_SOURCES) \ $(test_datacache_postgres_SOURCES) \ $(test_datacache_quota_heap_SOURCES) \ $(test_datacache_quota_postgres_SOURCES) \ $(test_datacache_quota_sqlite_SOURCES) \ $(test_datacache_sqlite_SOURCES) DIST_SOURCES = $(libgnunet_plugin_datacache_heap_la_SOURCES) \ $(libgnunet_plugin_datacache_postgres_la_SOURCES) \ $(libgnunet_plugin_datacache_sqlite_la_SOURCES) \ $(libgnunet_plugin_datacache_template_la_SOURCES) \ $(libgnunetdatacache_la_SOURCES) \ $(perf_datacache_heap_SOURCES) \ $(perf_datacache_postgres_SOURCES) \ $(perf_datacache_sqlite_SOURCES) \ $(test_datacache_heap_SOURCES) \ $(test_datacache_postgres_SOURCES) \ $(test_datacache_quota_heap_SOURCES) \ $(test_datacache_quota_postgres_SOURCES) \ $(test_datacache_quota_sqlite_SOURCES) \ $(test_datacache_sqlite_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ datacache.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIBS = -lgcov @HAVE_SQLITE_TRUE@SQLITE_PLUGIN = libgnunet_plugin_datacache_sqlite.la @HAVE_POSTGRES_TRUE@POSTGRES_PLUGIN = libgnunet_plugin_datacache_postgres.la lib_LTLIBRARIES = \ libgnunetdatacache.la libgnunetdatacache_la_SOURCES = \ datacache.c libgnunetdatacache_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetdatacache_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:1:0 plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ $(POSTGRES_PLUGIN) \ libgnunet_plugin_datacache_heap.la \ libgnunet_plugin_datacache_template.la libgnunet_plugin_datacache_sqlite_la_SOURCES = \ plugin_datacache_sqlite.c libgnunet_plugin_datacache_sqlite_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_datacache_heap_la_SOURCES = \ plugin_datacache_heap.c libgnunet_plugin_datacache_heap_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) libgnunet_plugin_datacache_heap_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_datacache_postgres_la_SOURCES = \ plugin_datacache_postgres.c libgnunet_plugin_datacache_postgres_la_LIBADD = \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_PLUGIN_LDFLAGS) $(POSTGRES_LDFLAGS) -lpq libgnunet_plugin_datacache_postgres_la_CPPFLAGS = \ $(POSTGRES_CPPFLAGS) $(AM_CPPFLAGS) libgnunet_plugin_datacache_postgres_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) $(POSTGRES_LDFLAGS) -lpq libgnunet_plugin_datacache_template_la_SOURCES = \ plugin_datacache_template.c libgnunet_plugin_datacache_template_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) libgnunet_plugin_datacache_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) @HAVE_BENCHMARKS_TRUE@@HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@SQLITE_BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@@HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ perf_datacache_sqlite @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@SQLITE_TESTS = \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ test_datacache_sqlite \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ test_datacache_quota_sqlite \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ $(SQLITE_BENCHMARKS) @HAVE_BENCHMARKS_TRUE@@HAVE_TESTING_TRUE@HEAP_BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@@HAVE_TESTING_TRUE@ perf_datacache_heap @HAVE_TESTING_TRUE@HEAP_TESTS = \ @HAVE_TESTING_TRUE@ test_datacache_heap \ @HAVE_TESTING_TRUE@ test_datacache_quota_heap \ @HAVE_TESTING_TRUE@ $(HEAP_BENCHMARKS) @HAVE_BENCHMARKS_TRUE@@HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@POSTGRES_BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@@HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ perf_datacache_postgres @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@POSTGRES_TESTS = \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ test_datacache_postgres \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ test_datacache_quota_postgres \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ $(POSTGRES_BENCHMARKS) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_datacache_sqlite_SOURCES = \ test_datacache.c test_datacache_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_quota_sqlite_SOURCES = \ test_datacache_quota.c test_datacache_quota_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datacache_sqlite_SOURCES = \ perf_datacache.c perf_datacache_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_heap_SOURCES = \ test_datacache.c test_datacache_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_quota_heap_SOURCES = \ test_datacache_quota.c test_datacache_quota_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datacache_heap_SOURCES = \ perf_datacache.c perf_datacache_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_postgres_SOURCES = \ test_datacache.c test_datacache_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_quota_postgres_SOURCES = \ test_datacache_quota.c test_datacache_quota_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datacache_postgres_SOURCES = \ perf_datacache.c perf_datacache_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_datacache_data_sqlite.conf \ perf_datacache_data_sqlite.conf \ test_datacache_data_heap.conf \ perf_datacache_data_heap.conf \ test_datacache_data_postgres.conf \ perf_datacache_data_postgres.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/datacache/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/datacache/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_datacache_heap.la: $(libgnunet_plugin_datacache_heap_la_OBJECTS) $(libgnunet_plugin_datacache_heap_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datacache_heap_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datacache_heap_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_datacache_heap_la_OBJECTS) $(libgnunet_plugin_datacache_heap_la_LIBADD) $(LIBS) libgnunet_plugin_datacache_postgres.la: $(libgnunet_plugin_datacache_postgres_la_OBJECTS) $(libgnunet_plugin_datacache_postgres_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datacache_postgres_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datacache_postgres_la_LINK) $(am_libgnunet_plugin_datacache_postgres_la_rpath) $(libgnunet_plugin_datacache_postgres_la_OBJECTS) $(libgnunet_plugin_datacache_postgres_la_LIBADD) $(LIBS) libgnunet_plugin_datacache_sqlite.la: $(libgnunet_plugin_datacache_sqlite_la_OBJECTS) $(libgnunet_plugin_datacache_sqlite_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datacache_sqlite_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datacache_sqlite_la_LINK) $(am_libgnunet_plugin_datacache_sqlite_la_rpath) $(libgnunet_plugin_datacache_sqlite_la_OBJECTS) $(libgnunet_plugin_datacache_sqlite_la_LIBADD) $(LIBS) libgnunet_plugin_datacache_template.la: $(libgnunet_plugin_datacache_template_la_OBJECTS) $(libgnunet_plugin_datacache_template_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datacache_template_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datacache_template_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_datacache_template_la_OBJECTS) $(libgnunet_plugin_datacache_template_la_LIBADD) $(LIBS) libgnunetdatacache.la: $(libgnunetdatacache_la_OBJECTS) $(libgnunetdatacache_la_DEPENDENCIES) $(EXTRA_libgnunetdatacache_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetdatacache_la_LINK) -rpath $(libdir) $(libgnunetdatacache_la_OBJECTS) $(libgnunetdatacache_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list perf_datacache_heap$(EXEEXT): $(perf_datacache_heap_OBJECTS) $(perf_datacache_heap_DEPENDENCIES) $(EXTRA_perf_datacache_heap_DEPENDENCIES) @rm -f perf_datacache_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_datacache_heap_OBJECTS) $(perf_datacache_heap_LDADD) $(LIBS) perf_datacache_postgres$(EXEEXT): $(perf_datacache_postgres_OBJECTS) $(perf_datacache_postgres_DEPENDENCIES) $(EXTRA_perf_datacache_postgres_DEPENDENCIES) @rm -f perf_datacache_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_datacache_postgres_OBJECTS) $(perf_datacache_postgres_LDADD) $(LIBS) perf_datacache_sqlite$(EXEEXT): $(perf_datacache_sqlite_OBJECTS) $(perf_datacache_sqlite_DEPENDENCIES) $(EXTRA_perf_datacache_sqlite_DEPENDENCIES) @rm -f perf_datacache_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_datacache_sqlite_OBJECTS) $(perf_datacache_sqlite_LDADD) $(LIBS) test_datacache_heap$(EXEEXT): $(test_datacache_heap_OBJECTS) $(test_datacache_heap_DEPENDENCIES) $(EXTRA_test_datacache_heap_DEPENDENCIES) @rm -f test_datacache_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datacache_heap_OBJECTS) $(test_datacache_heap_LDADD) $(LIBS) test_datacache_postgres$(EXEEXT): $(test_datacache_postgres_OBJECTS) $(test_datacache_postgres_DEPENDENCIES) $(EXTRA_test_datacache_postgres_DEPENDENCIES) @rm -f test_datacache_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datacache_postgres_OBJECTS) $(test_datacache_postgres_LDADD) $(LIBS) test_datacache_quota_heap$(EXEEXT): $(test_datacache_quota_heap_OBJECTS) $(test_datacache_quota_heap_DEPENDENCIES) $(EXTRA_test_datacache_quota_heap_DEPENDENCIES) @rm -f test_datacache_quota_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datacache_quota_heap_OBJECTS) $(test_datacache_quota_heap_LDADD) $(LIBS) test_datacache_quota_postgres$(EXEEXT): $(test_datacache_quota_postgres_OBJECTS) $(test_datacache_quota_postgres_DEPENDENCIES) $(EXTRA_test_datacache_quota_postgres_DEPENDENCIES) @rm -f test_datacache_quota_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datacache_quota_postgres_OBJECTS) $(test_datacache_quota_postgres_LDADD) $(LIBS) test_datacache_quota_sqlite$(EXEEXT): $(test_datacache_quota_sqlite_OBJECTS) $(test_datacache_quota_sqlite_DEPENDENCIES) $(EXTRA_test_datacache_quota_sqlite_DEPENDENCIES) @rm -f test_datacache_quota_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datacache_quota_sqlite_OBJECTS) $(test_datacache_quota_sqlite_LDADD) $(LIBS) test_datacache_sqlite$(EXEEXT): $(test_datacache_sqlite_OBJECTS) $(test_datacache_sqlite_DEPENDENCIES) $(EXTRA_test_datacache_sqlite_DEPENDENCIES) @rm -f test_datacache_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datacache_sqlite_OBJECTS) $(test_datacache_sqlite_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datacache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_datacache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_datacache_heap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_datacache_sqlite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_datacache_template.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_datacache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_datacache_quota.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.lo: plugin_datacache_postgres.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_datacache_postgres_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.Tpo -c -o libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.lo `test -f 'plugin_datacache_postgres.c' || echo '$(srcdir)/'`plugin_datacache_postgres.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.Tpo $(DEPDIR)/libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_datacache_postgres.c' object='libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_datacache_postgres_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_datacache_postgres_la-plugin_datacache_postgres.lo `test -f 'plugin_datacache_postgres.c' || echo '$(srcdir)/'`plugin_datacache_postgres.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_datacache_sqlite.log: test_datacache_sqlite$(EXEEXT) @p='test_datacache_sqlite$(EXEEXT)'; \ b='test_datacache_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datacache_quota_sqlite.log: test_datacache_quota_sqlite$(EXEEXT) @p='test_datacache_quota_sqlite$(EXEEXT)'; \ b='test_datacache_quota_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_datacache_sqlite.log: perf_datacache_sqlite$(EXEEXT) @p='perf_datacache_sqlite$(EXEEXT)'; \ b='perf_datacache_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datacache_heap.log: test_datacache_heap$(EXEEXT) @p='test_datacache_heap$(EXEEXT)'; \ b='test_datacache_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datacache_quota_heap.log: test_datacache_quota_heap$(EXEEXT) @p='test_datacache_quota_heap$(EXEEXT)'; \ b='test_datacache_quota_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_datacache_heap.log: perf_datacache_heap$(EXEEXT) @p='perf_datacache_heap$(EXEEXT)'; \ b='perf_datacache_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datacache_postgres.log: test_datacache_postgres$(EXEEXT) @p='test_datacache_postgres$(EXEEXT)'; \ b='test_datacache_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datacache_quota_postgres.log: test_datacache_quota_postgres$(EXEEXT) @p='test_datacache_quota_postgres$(EXEEXT)'; \ b='test_datacache_quota_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_datacache_postgres.log: perf_datacache_postgres$(EXEEXT) @p='perf_datacache_postgres$(EXEEXT)'; \ b='perf_datacache_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_pkgcfgDATA uninstall-libLTLIBRARIES \ uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-pluginLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dist_pkgcfgDATA install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-dist_pkgcfgDATA \ uninstall-libLTLIBRARIES uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/datacache/Makefile.am0000644000175000017500000001275512320751517014547 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ datacache.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIBS = -lgcov endif if HAVE_SQLITE SQLITE_PLUGIN = libgnunet_plugin_datacache_sqlite.la endif if HAVE_POSTGRES POSTGRES_PLUGIN = libgnunet_plugin_datacache_postgres.la endif lib_LTLIBRARIES = \ libgnunetdatacache.la libgnunetdatacache_la_SOURCES = \ datacache.c libgnunetdatacache_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetdatacache_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:1:0 plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ $(POSTGRES_PLUGIN) \ libgnunet_plugin_datacache_heap.la \ libgnunet_plugin_datacache_template.la libgnunet_plugin_datacache_sqlite_la_SOURCES = \ plugin_datacache_sqlite.c libgnunet_plugin_datacache_sqlite_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_datacache_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_datacache_heap_la_SOURCES = \ plugin_datacache_heap.c libgnunet_plugin_datacache_heap_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) libgnunet_plugin_datacache_heap_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_datacache_postgres_la_SOURCES = \ plugin_datacache_postgres.c libgnunet_plugin_datacache_postgres_la_LIBADD = \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_PLUGIN_LDFLAGS) $(POSTGRES_LDFLAGS) -lpq libgnunet_plugin_datacache_postgres_la_CPPFLAGS = \ $(POSTGRES_CPPFLAGS) $(AM_CPPFLAGS) libgnunet_plugin_datacache_postgres_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) $(POSTGRES_LDFLAGS) -lpq libgnunet_plugin_datacache_template_la_SOURCES = \ plugin_datacache_template.c libgnunet_plugin_datacache_template_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) libgnunet_plugin_datacache_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) if HAVE_TESTING if HAVE_SQLITE if HAVE_BENCHMARKS SQLITE_BENCHMARKS = \ perf_datacache_sqlite endif SQLITE_TESTS = \ test_datacache_sqlite \ test_datacache_quota_sqlite \ $(SQLITE_BENCHMARKS) endif if HAVE_BENCHMARKS HEAP_BENCHMARKS = \ perf_datacache_heap endif HEAP_TESTS = \ test_datacache_heap \ test_datacache_quota_heap \ $(HEAP_BENCHMARKS) if HAVE_POSTGRES if HAVE_BENCHMARKS POSTGRES_BENCHMARKS = \ perf_datacache_postgres endif POSTGRES_TESTS = \ test_datacache_postgres \ test_datacache_quota_postgres \ $(POSTGRES_BENCHMARKS) endif endif check_PROGRAMS = \ $(SQLITE_TESTS) \ $(HEAP_TESTS) \ $(POSTGRES_TESTS) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_datacache_sqlite_SOURCES = \ test_datacache.c test_datacache_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_quota_sqlite_SOURCES = \ test_datacache_quota.c test_datacache_quota_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datacache_sqlite_SOURCES = \ perf_datacache.c perf_datacache_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_heap_SOURCES = \ test_datacache.c test_datacache_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_quota_heap_SOURCES = \ test_datacache_quota.c test_datacache_quota_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datacache_heap_SOURCES = \ perf_datacache.c perf_datacache_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_postgres_SOURCES = \ test_datacache.c test_datacache_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la test_datacache_quota_postgres_SOURCES = \ test_datacache_quota.c test_datacache_quota_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datacache_postgres_SOURCES = \ perf_datacache.c perf_datacache_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_datacache_data_sqlite.conf \ perf_datacache_data_sqlite.conf \ test_datacache_data_heap.conf \ perf_datacache_data_heap.conf \ test_datacache_data_postgres.conf \ perf_datacache_data_postgres.conf gnunet-0.10.1/src/datacache/perf_datacache.c0000644000175000017500000001155712225777501015574 00000000000000/* This file is part of GNUnet. (C) 2006, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file datacache/perf_datacache.c * @brief Performance evaluation for the datacache implementations. * @author Nils Durner */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_datacache_lib.h" #include "gnunet_testing_lib.h" #include #define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__, __LINE__); goto FAILURE;} } while (0) #define ITERATIONS 10000 static int ok; static unsigned int found; /** * Name of plugin under test. */ static const char *plugin_name; static int checkIt (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int path_len, const struct GNUNET_PeerIdentity *path) { if ((size == sizeof (struct GNUNET_HashCode)) && (0 == memcmp (data, cls, size))) found++; return GNUNET_OK; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_DATACACHE_Handle *h; struct GNUNET_HashCode k; struct GNUNET_HashCode n; struct GNUNET_TIME_Absolute exp; struct GNUNET_TIME_Absolute start; unsigned int i; char gstr[128]; ok = 0; h = GNUNET_DATACACHE_create (cfg, "perfcache"); if (h == NULL) { FPRINTF (stderr, "%s", "Failed to initialize datacache. Database likely not setup, skipping test.\n"); return; } exp = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS); start = GNUNET_TIME_absolute_get (); memset (&k, 0, sizeof (struct GNUNET_HashCode)); for (i = 0; i < ITERATIONS; i++) { if (0 == i % (ITERATIONS / 80)) FPRINTF (stderr, "%s", "."); GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, sizeof (struct GNUNET_HashCode), (const char *) &n, 1 + i % 16, exp, 0, NULL)); k = n; } FPRINTF (stderr, "%s", "\n"); FPRINTF (stdout, "Stored %u items in %s\n", ITERATIONS, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GNUNET_snprintf (gstr, sizeof (gstr), "DATACACHE-%s", plugin_name); GAUGER (gstr, "Time to PUT item in datacache", GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL / ITERATIONS, "ms/item"); start = GNUNET_TIME_absolute_get (); memset (&k, 0, sizeof (struct GNUNET_HashCode)); for (i = 0; i < ITERATIONS; i++) { if (0 == i % (ITERATIONS / 80)) FPRINTF (stderr, "%s", "."); GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); GNUNET_DATACACHE_get (h, &k, 1 + i % 16, &checkIt, &n); k = n; } FPRINTF (stderr, "%s", "\n"); FPRINTF (stdout, "Found %u/%u items in %s (%u were deleted during storage processing)\n", found, ITERATIONS, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES), ITERATIONS - found); if (found > 0) GAUGER (gstr, "Time to GET item from datacache", GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL / found, "ms/item"); GNUNET_DATACACHE_destroy (h); ASSERT (ok == 0); return; FAILURE: if (h != NULL) GNUNET_DATACACHE_destroy (h); ok = GNUNET_SYSERR; } int main (int argc, char *argv[]) { char cfg_name[128]; char *const xargv[] = { "perf-datacache", "-c", cfg_name, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_log_setup ("perf-datacache", "WARNING", NULL); plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "perf_datacache_data_%s.conf", plugin_name); GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "perf-datacache", "nohelp", options, &run, NULL); if (ok != 0) FPRINTF (stderr, "Missed some perfcases: %d\n", ok); return ok; } /* end of perf_datacache.c */ gnunet-0.10.1/src/datacache/test_datacache_quota.c0000644000175000017500000000763212225777501017027 00000000000000/* This file is part of GNUnet. (C) 2006, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file datacache/test_datacache_quota.c * @brief Test for the quota code of the datacache implementations. * @author Nils Durner */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_datacache_lib.h" #include "gnunet_testing_lib.h" #define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__, __LINE__); goto FAILURE;} } while (0) static int ok; /** * Name of plugin under test. */ static const char *plugin_name; /** * Quota is 1 MB. Each iteration of the test puts in about 1 MB of * data. We do 10 iterations. Afterwards we check that the data from * the first 5 iterations has all been discarded and that at least * some of the data from the last iteration is still there. */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_DATACACHE_Handle *h; struct GNUNET_HashCode k; struct GNUNET_HashCode n; unsigned int i; unsigned int j; char buf[3200]; struct GNUNET_TIME_Absolute exp; ok = 0; h = GNUNET_DATACACHE_create (cfg, "testcache"); if (h == NULL) { FPRINTF (stderr, "%s", "Failed to initialize datacache. Database likely not setup, skipping test.\n"); return; } exp = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS); memset (buf, 1, sizeof (buf)); memset (&k, 0, sizeof (struct GNUNET_HashCode)); for (i = 0; i < 10; i++) { FPRINTF (stderr, "%s", "."); GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); for (j = i; j < sizeof (buf); j += 10) { exp.abs_value_us++; buf[j] = i; ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, j, buf, 1 + i, exp, 0, NULL)); ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); } k = n; } FPRINTF (stderr, "%s", "\n"); memset (&k, 0, sizeof (struct GNUNET_HashCode)); for (i = 0; i < 10; i++) { FPRINTF (stderr, "%s", "."); GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); if (i < 2) ASSERT (0 == GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); if (i == 9) ASSERT (0 < GNUNET_DATACACHE_get (h, &k, 1 + i, NULL, NULL)); k = n; } FPRINTF (stderr, "%s", "\n"); GNUNET_DATACACHE_destroy (h); return; FAILURE: if (h != NULL) GNUNET_DATACACHE_destroy (h); ok = GNUNET_SYSERR; } int main (int argc, char *argv[]) { char cfg_name[128]; char *const xargv[] = { "test-datacache-quota", "-c", cfg_name, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_log_setup ("test-datacache-quota", "WARNING", NULL); plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_datacache_data_%s.conf", plugin_name); GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "test-datacache-quota", "nohelp", options, &run, NULL); if (0 != ok) FPRINTF (stderr, "Missed some testcases: %d\n", ok); return ok; } /* end of test_datacache_quota.c */ gnunet-0.10.1/src/datacache/test_datacache.c0000644000175000017500000001017112225777501015606 00000000000000/* This file is part of GNUnet. (C) 2006, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file datacache/test_datacache.c * @brief Test for the datacache implementations. * @author Nils Durner */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_datacache_lib.h" #include "gnunet_testing_lib.h" #define ASSERT(x) do { if (! (x)) { printf("Error at %s:%d\n", __FILE__, __LINE__); goto FAILURE;} } while (0) static int ok; /** * Name of plugin under test. */ static const char *plugin_name; static int checkIt (void *cls, const struct GNUNET_HashCode *key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int path_len, const struct GNUNET_PeerIdentity *path) { if (size != sizeof (struct GNUNET_HashCode)) { GNUNET_break (0); ok = 2; } if (0 != memcmp (data, cls, size)) { GNUNET_break (0); ok = 3; } return GNUNET_OK; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_DATACACHE_Handle *h; struct GNUNET_HashCode k; struct GNUNET_HashCode n; struct GNUNET_TIME_Absolute exp; unsigned int i; ok = 0; h = GNUNET_DATACACHE_create (cfg, "testcache"); if (h == NULL) { FPRINTF (stderr, "%s", "Failed to initialize datacache. Database likely not setup, skipping test.\n"); return; } exp = GNUNET_TIME_absolute_get (); exp.abs_value_us += 5 * 60 * 1000 * 1000LL; memset (&k, 0, sizeof (struct GNUNET_HashCode)); for (i = 0; i < 100; i++) { GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, sizeof (struct GNUNET_HashCode), (const char *) &n, 1 + i % 16, exp, 0, NULL)); k = n; } memset (&k, 0, sizeof (struct GNUNET_HashCode)); for (i = 0; i < 100; i++) { GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); ASSERT (1 == GNUNET_DATACACHE_get (h, &k, 1 + i % 16, &checkIt, &n)); k = n; } memset (&k, 42, sizeof (struct GNUNET_HashCode)); GNUNET_CRYPTO_hash (&k, sizeof (struct GNUNET_HashCode), &n); ASSERT (GNUNET_OK == GNUNET_DATACACHE_put (h, &k, sizeof (struct GNUNET_HashCode), (const char *) &n, 792, GNUNET_TIME_UNIT_FOREVER_ABS, 0, NULL)); ASSERT (0 != GNUNET_DATACACHE_get (h, &k, 792, &checkIt, &n)); GNUNET_DATACACHE_destroy (h); ASSERT (ok == 0); return; FAILURE: if (h != NULL) GNUNET_DATACACHE_destroy (h); ok = GNUNET_SYSERR; } int main (int argc, char *argv[]) { char cfg_name[128]; char *const xargv[] = { "test-datacache", "-c", cfg_name, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_log_setup ("test-datacache", "WARNING", NULL); plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_datacache_data_%s.conf", plugin_name); GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "test-datacache", "nohelp", options, &run, NULL); if (0 != ok) FPRINTF (stderr, "Missed some testcases: %d\n", ok); return ok; } /* end of test_datacache.c */ gnunet-0.10.1/src/datacache/perf_datacache_data_postgres.conf0000644000175000017500000000016712225230043021172 00000000000000[perfcache] QUOTA = 500 KB DATABASE = postgres [datacache-postgres] CONFIG = connect_timeout=10; dbname=gnunetcheck gnunet-0.10.1/src/datacache/plugin_datacache_heap.c0000644000175000017500000002417212255010512017111 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datacache/plugin_datacache_heap.c * @brief heap-only implementation of a database backend for the datacache * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_datacache_plugin.h" #define LOG(kind,...) GNUNET_log_from (kind, "datacache-heap", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,op,fn) GNUNET_log_from_strerror_file (kind, "datacache-heap", op, fn) /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATACACHE_PluginEnvironment *env; /** * Our hash map. */ struct GNUNET_CONTAINER_MultiHashMap *map; /** * Heap for expirations. */ struct GNUNET_CONTAINER_Heap *heap; }; /** * Entry in the hash map. */ struct Value { /** * Key for the entry. */ struct GNUNET_HashCode key; /** * Expiration time. */ struct GNUNET_TIME_Absolute discard_time; /** * Corresponding node in the heap. */ struct GNUNET_CONTAINER_HeapNode *hn; /** * Path information. */ struct GNUNET_PeerIdentity *path_info; /** * Payload (actual payload follows this struct) */ size_t size; /** * Number of entries in 'path_info'. */ unsigned int path_info_len; /** * Type of the block. */ enum GNUNET_BLOCK_Type type; }; #define OVERHEAD (sizeof (struct Value) + 64) /** * Closure for 'put_cb'. */ struct PutContext { /** * Expiration time for the new value. */ struct GNUNET_TIME_Absolute discard_time; /** * Data for the new value. */ const char *data; /** * Heap from the plugin. */ struct GNUNET_CONTAINER_Heap *heap; /** * Path information. */ const struct GNUNET_PeerIdentity *path_info; /** * Number of bytes in 'data'. */ size_t size; /** * Type of the node. */ enum GNUNET_BLOCK_Type type; /** * Number of entries in 'path_info'. */ unsigned int path_info_len; /** * Value to set to GNUNET_YES if an equivalent block was found. */ int found; }; /** * Function called during PUT to detect if an equivalent block * already exists. * * @param cls the 'struct PutContext' * @param key the key for the value(s) * @param value an existing value * @return #GNUNET_YES if not found (to continue to iterate) */ static int put_cb (void *cls, const struct GNUNET_HashCode *key, void *value) { struct PutContext *put_ctx = cls; struct Value *val = value; if ( (val->size == put_ctx->size) && (val->type == put_ctx->type) && (0 == memcmp (&val[1], put_ctx->data, put_ctx->size)) ) { put_ctx->found = GNUNET_YES; val->discard_time = GNUNET_TIME_absolute_max (val->discard_time, put_ctx->discard_time); /* replace old path with new path */ GNUNET_array_grow (val->path_info, val->path_info_len, put_ctx->path_info_len); memcpy (val->path_info, put_ctx->path_info, put_ctx->path_info_len * sizeof (struct GNUNET_PeerIdentity)); GNUNET_CONTAINER_heap_update_cost (put_ctx->heap, val->hn, val->discard_time.abs_value_us); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got same value for key %s and type %d (size %u vs %u)\n", GNUNET_h2s (key), val->type, (unsigned int) val->size, (unsigned int) put_ctx->size); return GNUNET_NO; } return GNUNET_YES; } /** * Store an item in the datastore. * * @param cls closure (our `struct Plugin`) * @param key key to store data under * @param size number of bytes in data * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case * @param path_info_len number of entries in @a path_info * @param path_info a path through the network * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ static ssize_t heap_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info) { struct Plugin *plugin = cls; struct Value *val; struct PutContext put_ctx; put_ctx.found = GNUNET_NO; put_ctx.heap = plugin->heap; put_ctx.data = data; put_ctx.size = size; put_ctx.path_info = path_info; put_ctx.path_info_len = path_info_len; put_ctx.discard_time = discard_time; put_ctx.type = type; GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map, key, put_cb, &put_ctx); if (GNUNET_YES == put_ctx.found) return 0; val = GNUNET_malloc (sizeof (struct Value) + size); memcpy (&val[1], data, size); val->key = *key; val->type = type; val->discard_time = discard_time; val->size = size; GNUNET_array_grow (val->path_info, val->path_info_len, path_info_len); memcpy (val->path_info, path_info, path_info_len * sizeof (struct GNUNET_PeerIdentity)); (void) GNUNET_CONTAINER_multihashmap_put (plugin->map, &val->key, val, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); val->hn = GNUNET_CONTAINER_heap_insert (plugin->heap, val, val->discard_time.abs_value_us); return size + OVERHEAD; } /** * Closure for 'get_cb'. */ struct GetContext { /** * Function to call for each result. */ GNUNET_DATACACHE_Iterator iter; /** * Closure for 'iter'. */ void *iter_cls; /** * Number of results found. */ unsigned int cnt; /** * Block type requested. */ enum GNUNET_BLOCK_Type type; }; /** * Function called during GET to find matching blocks. * Only matches by type. * * @param cls the 'struct GetContext' * @param key the key for the value(s) * @param value an existing value * @return GNUNET_YES to continue to iterate */ static int get_cb (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GetContext *get_ctx = cls; struct Value *val = value; int ret; if ( (get_ctx->type != val->type) && (GNUNET_BLOCK_TYPE_ANY != get_ctx->type) ) return GNUNET_OK; if (NULL != get_ctx->iter) ret = get_ctx->iter (get_ctx->iter_cls, key, val->size, (const char *) &val[1], val->type, val->discard_time, val->path_info_len, val->path_info); else ret = GNUNET_YES; get_ctx->cnt++; return ret; } /** * Iterate over the results for a particular key * in the datastore. * * @param cls closure (our "struct Plugin") * @param key * @param type entries of which type are relevant? * @param iter maybe NULL (to just count) * @param iter_cls closure for iter * @return the number of results found */ static unsigned int heap_plugin_get (void *cls, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls) { struct Plugin *plugin = cls; struct GetContext get_ctx; get_ctx.type = type; get_ctx.iter = iter; get_ctx.iter_cls = iter_cls; get_ctx.cnt = 0; GNUNET_CONTAINER_multihashmap_get_multiple (plugin->map, key, get_cb, &get_ctx); return get_ctx.cnt; } /** * Delete the entry with the lowest expiration value * from the datacache right now. * * @param cls closure (our "struct Plugin") * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int heap_plugin_del (void *cls) { struct Plugin *plugin = cls; struct Value *val; val = GNUNET_CONTAINER_heap_remove_root (plugin->heap); if (NULL == val) return GNUNET_SYSERR; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (plugin->map, &val->key, val)); plugin->env->delete_notify (plugin->env->cls, &val->key, val->size + OVERHEAD); GNUNET_free_non_null (val->path_info); GNUNET_free (val); return GNUNET_OK; } /** * Entry point for the plugin. * * @param cls closure (the `struct GNUNET_DATACACHE_PluginEnvironmnet`) * @return the plugin's closure (our `struct Plugin`) */ void * libgnunet_plugin_datacache_heap_init (void *cls) { struct GNUNET_DATACACHE_PluginEnvironment *env = cls; struct GNUNET_DATACACHE_PluginFunctions *api; struct Plugin *plugin; plugin = GNUNET_new (struct Plugin); plugin->map = GNUNET_CONTAINER_multihashmap_create (1024, /* FIXME: base on quota! */ GNUNET_YES); plugin->heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); plugin->env = env; api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions); api->cls = plugin; api->get = &heap_plugin_get; api->put = &heap_plugin_put; api->del = &heap_plugin_del; LOG (GNUNET_ERROR_TYPE_INFO, _("Heap datacache running\n")); return api; } /** * Exit point from the plugin. * * @param cls closure (our "struct Plugin") * @return NULL */ void * libgnunet_plugin_datacache_heap_done (void *cls) { struct GNUNET_DATACACHE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; struct Value *val; while (NULL != (val = GNUNET_CONTAINER_heap_remove_root (plugin->heap))) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (plugin->map, &val->key, val)); GNUNET_free_non_null (val->path_info); GNUNET_free (val); } GNUNET_CONTAINER_heap_destroy (plugin->heap); GNUNET_CONTAINER_multihashmap_destroy (plugin->map); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_datacache_heap.c */ gnunet-0.10.1/src/datacache/plugin_datacache_sqlite.c0000644000175000017500000003727112255010512017501 00000000000000/* This file is part of GNUnet (C) 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datacache/plugin_datacache_sqlite.c * @brief sqlite for an implementation of a database backend for the datacache * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_datacache_plugin.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "datacache-sqlite", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,op,fn) GNUNET_log_from_strerror_file (kind, "datacache-sqlite", op, fn) /** * How much overhead do we assume per entry in the * datacache? */ #define OVERHEAD (sizeof(struct GNUNET_HashCode) + 32) /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATACACHE_PluginEnvironment *env; /** * Handle to the sqlite database. */ sqlite3 *dbh; /** * Filename used for the DB. */ char *fn; }; /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_SQLITE(db, level, cmd) do { LOG (level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db)); } while(0) #define SQLITE3_EXEC(db, cmd) do { emsg = NULL; if (SQLITE_OK != sqlite3_exec(db, cmd, NULL, NULL, &emsg)) { LOG (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, _("`%s' failed at %s:%d with error: %s\n"), "sqlite3_exec", __FILE__, __LINE__, emsg); sqlite3_free(emsg); } } while(0) /** * @brief Prepare a SQL statement */ static int sq_prepare (sqlite3 * dbh, const char *zSql, /* SQL statement, UTF-8 encoded */ sqlite3_stmt ** ppStmt) { /* OUT: Statement handle */ char *dummy; return sqlite3_prepare (dbh, zSql, strlen (zSql), ppStmt, (const char **) &dummy); } /** * Store an item in the datastore. * * @param cls closure (our "struct Plugin") * @param key key to store data under * @param size number of bytes in data * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case * @param path_info_len number of entries in 'path_info' * @param path_info array of peers that have processed the request * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ static ssize_t sqlite_plugin_put (void *cls, const struct GNUNET_HashCode *key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; int64_t dval; LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' of %u bytes with key `%4s' and expiration %s\n", "PUT", (unsigned int) size, GNUNET_h2s (key), GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (discard_time), GNUNET_YES)); dval = (int64_t) discard_time.abs_value_us; if (dval < 0) dval = INT64_MAX; if (sq_prepare (plugin->dbh, "INSERT INTO ds090 (type, expire, key, value, path) VALUES (?, ?, ?, ?, ?)", &stmt) != SQLITE_OK) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sq_prepare"); return -1; } if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) || (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, dval)) || (SQLITE_OK != sqlite3_bind_blob (stmt, 3, key, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT)) || (SQLITE_OK != sqlite3_bind_blob (stmt, 4, data, size, SQLITE_TRANSIENT)) || (SQLITE_OK != sqlite3_bind_blob (stmt, 5, path_info, path_info_len * sizeof (struct GNUNET_PeerIdentity), SQLITE_TRANSIENT))) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_xxx"); sqlite3_finalize (stmt); return -1; } if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); sqlite3_finalize (stmt); return -1; } if (SQLITE_OK != sqlite3_finalize (stmt)) LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_finalize"); return size + OVERHEAD; } /** * Iterate over the results for a particular key * in the datastore. * * @param cls closure (our "struct Plugin") * @param key * @param type entries of which type are relevant? * @param iter maybe NULL (to just count) * @param iter_cls closure for iter * @return the number of results found */ static unsigned int sqlite_plugin_get (void *cls, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute exp; unsigned int size; const char *dat; unsigned int cnt; unsigned int off; unsigned int total; unsigned int psize; char scratch[256]; int64_t ntime; const struct GNUNET_PeerIdentity *path; now = GNUNET_TIME_absolute_get (); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' for key `%4s'\n", "GET", GNUNET_h2s (key)); if (sq_prepare (plugin->dbh, "SELECT count(*) FROM ds090 WHERE key=? AND type=? AND expire >= ?", &stmt) != SQLITE_OK) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sq_prepare"); return 0; } ntime = (int64_t) now.abs_value_us; GNUNET_assert (ntime >= 0); if ((SQLITE_OK != sqlite3_bind_blob (stmt, 1, key, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT)) || (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) || (SQLITE_OK != sqlite3_bind_int64 (stmt, 3, now.abs_value_us))) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_xxx"); sqlite3_finalize (stmt); return 0; } if (SQLITE_ROW != sqlite3_step (stmt)) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite_step"); sqlite3_finalize (stmt); LOG (GNUNET_ERROR_TYPE_DEBUG, "No content found when processing `%s' for key `%4s'\n", "GET", GNUNET_h2s (key)); return 0; } total = sqlite3_column_int (stmt, 0); sqlite3_finalize (stmt); if ((total == 0) || (iter == NULL)) { if (0 == total) LOG (GNUNET_ERROR_TYPE_DEBUG, "No content found when processing `%s' for key `%4s'\n", "GET", GNUNET_h2s (key)); return total; } cnt = 0; off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, total); while (cnt < total) { off = (off + 1) % total; GNUNET_snprintf (scratch, sizeof (scratch), "SELECT value,expire,path FROM ds090 WHERE key=? AND type=? AND expire >= ? LIMIT 1 OFFSET %u", off); if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sq_prepare"); return cnt; } if ((SQLITE_OK != sqlite3_bind_blob (stmt, 1, key, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT)) || (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) || (SQLITE_OK != sqlite3_bind_int64 (stmt, 3, now.abs_value_us))) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_xxx"); sqlite3_finalize (stmt); return cnt; } if (sqlite3_step (stmt) != SQLITE_ROW) break; size = sqlite3_column_bytes (stmt, 0); dat = sqlite3_column_blob (stmt, 0); exp.abs_value_us = sqlite3_column_int64 (stmt, 1); psize = sqlite3_column_bytes (stmt, 2); if (0 != psize % sizeof (struct GNUNET_PeerIdentity)) { GNUNET_break (0); psize = 0; } psize /= sizeof (struct GNUNET_PeerIdentity); if (0 != psize) path = sqlite3_column_blob (stmt, 2); else path = NULL; ntime = (int64_t) exp.abs_value_us; if (ntime == INT64_MAX) exp = GNUNET_TIME_UNIT_FOREVER_ABS; cnt++; LOG (GNUNET_ERROR_TYPE_DEBUG, "Found %u-byte result when processing `%s' for key `%4s'\n", (unsigned int) size, "GET", GNUNET_h2s (key)); if (GNUNET_OK != iter (iter_cls, key, size, dat, type, exp, psize, path)) { sqlite3_finalize (stmt); break; } sqlite3_finalize (stmt); } return cnt; } /** * Delete the entry with the lowest expiration value * from the datacache right now. * * @param cls closure (our "struct Plugin") * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int sqlite_plugin_del (void *cls) { struct Plugin *plugin = cls; unsigned long long rowid; unsigned int dsize; sqlite3_stmt *stmt; sqlite3_stmt *dstmt; struct GNUNET_HashCode hc; LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s'\n", "DEL"); stmt = NULL; dstmt = NULL; if (sq_prepare (plugin->dbh, "SELECT _ROWID_,key,value FROM ds090 ORDER BY expire ASC LIMIT 1", &stmt) != SQLITE_OK) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sq_prepare"); if (stmt != NULL) (void) sqlite3_finalize (stmt); return GNUNET_SYSERR; } if (SQLITE_ROW != sqlite3_step (stmt)) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); (void) sqlite3_finalize (stmt); return GNUNET_SYSERR; } rowid = sqlite3_column_int64 (stmt, 0); GNUNET_assert (sqlite3_column_bytes (stmt, 1) == sizeof (struct GNUNET_HashCode)); memcpy (&hc, sqlite3_column_blob (stmt, 1), sizeof (struct GNUNET_HashCode)); dsize = sqlite3_column_bytes (stmt, 2); if (SQLITE_OK != sqlite3_finalize (stmt)) LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); if (sq_prepare (plugin->dbh, "DELETE FROM ds090 WHERE _ROWID_=?", &dstmt) != SQLITE_OK) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sq_prepare"); if (stmt != NULL) (void) sqlite3_finalize (stmt); return GNUNET_SYSERR; } if (SQLITE_OK != sqlite3_bind_int64 (dstmt, 1, rowid)) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); (void) sqlite3_finalize (dstmt); return GNUNET_SYSERR; } if (sqlite3_step (dstmt) != SQLITE_DONE) { LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); (void) sqlite3_finalize (dstmt); return GNUNET_SYSERR; } plugin->env->delete_notify (plugin->env->cls, &hc, dsize + OVERHEAD); if (SQLITE_OK != sqlite3_finalize (dstmt)) LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_finalize"); return GNUNET_OK; } /** * Entry point for the plugin. * * @param cls closure (the "struct GNUNET_DATACACHE_PluginEnvironmnet") * @return the plugin's closure (our "struct Plugin") */ void * libgnunet_plugin_datacache_sqlite_init (void *cls) { struct GNUNET_DATACACHE_PluginEnvironment *env = cls; struct GNUNET_DATACACHE_PluginFunctions *api; struct Plugin *plugin; char *fn; char *fn_utf8; sqlite3 *dbh; char *emsg; if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "datacache-sqlite", "IN_MEMORY")) { if (SQLITE_OK != sqlite3_open (":memory:", &dbh)) return NULL; fn_utf8 = NULL; } else { fn = GNUNET_DISK_mktemp ("gnunet-datacache"); if (fn == NULL) { GNUNET_break (0); return NULL; } /* fn should be UTF-8-encoded. If it isn't, it's a bug. */ fn_utf8 = GNUNET_strdup (fn); if (SQLITE_OK != sqlite3_open (fn_utf8, &dbh)) { GNUNET_free (fn); GNUNET_free (fn_utf8); return NULL; } GNUNET_free (fn); } SQLITE3_EXEC (dbh, "PRAGMA temp_store=MEMORY"); SQLITE3_EXEC (dbh, "PRAGMA locking_mode=EXCLUSIVE"); SQLITE3_EXEC (dbh, "PRAGMA journal_mode=OFF"); SQLITE3_EXEC (dbh, "PRAGMA synchronous=OFF"); SQLITE3_EXEC (dbh, "PRAGMA count_changes=OFF"); SQLITE3_EXEC (dbh, "PRAGMA page_size=4092"); if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "datacache-sqlite", "IN_MEMORY")) SQLITE3_EXEC (dbh, "PRAGMA sqlite_temp_store=3"); SQLITE3_EXEC (dbh, "CREATE TABLE ds090 (" " type INTEGER NOT NULL DEFAULT 0," " expire INTEGER NOT NULL DEFAULT 0," " key BLOB NOT NULL DEFAULT ''," " value BLOB NOT NULL DEFAULT ''," " path BLOB DEFAULT '')"); SQLITE3_EXEC (dbh, "CREATE INDEX idx_hashidx ON ds090 (key,type,expire)"); SQLITE3_EXEC (dbh, "CREATE INDEX idx_expire ON ds090 (expire)"); plugin = GNUNET_new (struct Plugin); plugin->env = env; plugin->dbh = dbh; plugin->fn = fn_utf8; api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions); api->cls = plugin; api->get = &sqlite_plugin_get; api->put = &sqlite_plugin_put; api->del = &sqlite_plugin_del; LOG (GNUNET_ERROR_TYPE_INFO, _("Sqlite datacache running\n")); return api; } /** * Exit point from the plugin. * * @param cls closure (our "struct Plugin") * @return NULL */ void * libgnunet_plugin_datacache_sqlite_done (void *cls) { struct GNUNET_DATACACHE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; int result; #if SQLITE_VERSION_NUMBER >= 3007000 sqlite3_stmt *stmt; #endif #if !WINDOWS || defined(__CYGWIN__) if ( (NULL != plugin->fn) && (0 != UNLINK (plugin->fn)) ) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", plugin->fn); GNUNET_free_non_null (plugin->fn); #endif result = sqlite3_close (plugin->dbh); #if SQLITE_VERSION_NUMBER >= 3007000 if (result == SQLITE_BUSY) { LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Tried to close sqlite without finalizing all prepared statements.\n")); stmt = sqlite3_next_stmt (plugin->dbh, NULL); while (stmt != NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Closing statement %p\n", stmt); result = sqlite3_finalize (stmt); if (result != SQLITE_OK) LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to close statement %p: %d\n"), stmt, result); stmt = sqlite3_next_stmt (plugin->dbh, NULL); } result = sqlite3_close (plugin->dbh); } #endif if (SQLITE_OK != result) LOG_SQLITE (plugin->dbh, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); #if WINDOWS && !defined(__CYGWIN__) if ( (NULL != plugin->fn) && (0 != UNLINK (plugin->fn)) ) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", plugin->fn); GNUNET_free_non_null (plugin->fn); #endif GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_datacache_sqlite.c */ gnunet-0.10.1/src/datacache/plugin_datacache_postgres.c0000644000175000017500000002714412255010512020044 00000000000000/* This file is part of GNUnet (C) 2006, 2009, 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datacache/plugin_datacache_postgres.c * @brief postgres for an implementation of a database backend for the datacache * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_postgres_lib.h" #include "gnunet_datacache_plugin.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "datacache-postgres", __VA_ARGS__) /** * Per-entry overhead estimate */ #define OVERHEAD (sizeof(struct GNUNET_HashCode) + 24) /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATACACHE_PluginEnvironment *env; /** * Native Postgres database handle. */ PGconn *dbh; }; /** * @brief Get a database handle * * @param plugin global context * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int init_connection (struct Plugin *plugin) { PGresult *ret; plugin->dbh = GNUNET_POSTGRES_connect (plugin->env->cfg, "datacache-postgres"); if (NULL == plugin->dbh) return GNUNET_SYSERR; ret = PQexec (plugin->dbh, "CREATE TEMPORARY TABLE gn090dc (" " type INTEGER NOT NULL DEFAULT 0," " discard_time BIGINT NOT NULL DEFAULT 0," " key BYTEA NOT NULL DEFAULT ''," " value BYTEA NOT NULL DEFAULT ''," " path BYTEA DEFAULT '')" "WITH OIDS"); if ( (ret == NULL) || ((PQresultStatus (ret) != PGRES_COMMAND_OK) && (0 != strcmp ("42P07", /* duplicate table */ PQresultErrorField (ret, PG_DIAG_SQLSTATE))))) { (void) GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "CREATE TABLE", "gn090dc"); PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } if (PQresultStatus (ret) == PGRES_COMMAND_OK) { if ((GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_key ON gn090dc (key)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_dt ON gn090dc (discard_time)"))) { PQclear (ret); PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } } PQclear (ret); ret = PQexec (plugin->dbh, "ALTER TABLE gn090dc ALTER value SET STORAGE EXTERNAL"); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090dc")) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } PQclear (ret); ret = PQexec (plugin->dbh, "ALTER TABLE gn090dc ALTER key SET STORAGE PLAIN"); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090dc")) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } PQclear (ret); if ((GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "getkt", "SELECT discard_time,type,value,path FROM gn090dc " "WHERE key=$1 AND type=$2 ", 2)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "getk", "SELECT discard_time,type,value,path FROM gn090dc " "WHERE key=$1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "getm", "SELECT length(value),oid,key FROM gn090dc " "ORDER BY discard_time ASC LIMIT 1", 0)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "delrow", "DELETE FROM gn090dc WHERE oid=$1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "put", "INSERT INTO gn090dc (type, discard_time, key, value, path) " "VALUES ($1, $2, $3, $4, $5)", 5))) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } return GNUNET_OK; } /** * Store an item in the datastore. * * @param cls closure (our "struct Plugin") * @param key key to store data under * @param size number of bytes in data * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case * @param path_info_len number of entries in 'path_info' * @param path_info a path through the network * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ static ssize_t postgres_plugin_put (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info) { struct Plugin *plugin = cls; PGresult *ret; uint32_t btype = htonl (type); uint64_t bexpi = GNUNET_TIME_absolute_hton (discard_time).abs_value_us__; const char *paramValues[] = { (const char *) &btype, (const char *) &bexpi, (const char *) key, (const char *) data, (const char *) path_info }; int paramLengths[] = { sizeof (btype), sizeof (bexpi), sizeof (struct GNUNET_HashCode), size, path_info_len * sizeof (struct GNUNET_PeerIdentity) }; const int paramFormats[] = { 1, 1, 1, 1, 1 }; ret = PQexecPrepared (plugin->dbh, "put", 5, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put")) return -1; PQclear (ret); return size + OVERHEAD; } /** * Iterate over the results for a particular key * in the datastore. * * @param cls closure (our "struct Plugin") * @param key * @param type entries of which type are relevant? * @param iter maybe NULL (to just count) * @param iter_cls closure for iter * @return the number of results found */ static unsigned int postgres_plugin_get (void *cls, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls) { struct Plugin *plugin = cls; uint32_t btype = htonl (type); const char *paramValues[] = { (const char *) key, (const char *) &btype, }; int paramLengths[] = { sizeof (struct GNUNET_HashCode), sizeof (btype), }; const int paramFormats[] = { 1, 1 }; struct GNUNET_TIME_Absolute expiration_time; uint32_t size; unsigned int cnt; unsigned int i; unsigned int path_len; const struct GNUNET_PeerIdentity *path; PGresult *res; res = PQexecPrepared (plugin->dbh, (type == 0) ? "getk" : "getkt", (type == 0) ? 1 : 2, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", (type == 0) ? "getk" : "getkt")) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (postgres error)\n"); return 0; } if (0 == (cnt = PQntuples (res))) { /* no result */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (no more results)\n"); PQclear (res); return 0; } if (iter == NULL) { PQclear (res); return cnt; } if ((4 != PQnfields (res)) || (sizeof (uint64_t) != PQfsize (res, 0)) || (sizeof (uint32_t) != PQfsize (res, 1))) { GNUNET_break (0); PQclear (res); return 0; } for (i = 0; i < cnt; i++) { expiration_time.abs_value_us = GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, i, 0)); type = ntohl (*(uint32_t *) PQgetvalue (res, i, 1)); size = PQgetlength (res, i, 2); path_len = PQgetlength (res, i, 3); if (0 != (path_len % sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); path_len = 0; } path_len %= sizeof (struct GNUNET_PeerIdentity); path = (const struct GNUNET_PeerIdentity *) PQgetvalue (res, i, 3); LOG (GNUNET_ERROR_TYPE_DEBUG, "Found result of size %u bytes and type %u in database\n", (unsigned int) size, (unsigned int) type); if (GNUNET_SYSERR == iter (iter_cls, key, size, PQgetvalue (res, i, 2), (enum GNUNET_BLOCK_Type) type, expiration_time, path_len, path)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (client error)\n"); PQclear (res); return cnt; } } PQclear (res); return cnt; } /** * Delete the entry with the lowest expiration value * from the datacache right now. * * @param cls closure (our "struct Plugin") * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int postgres_plugin_del (void *cls) { struct Plugin *plugin = cls; uint32_t size; uint32_t oid; struct GNUNET_HashCode key; PGresult *res; res = PQexecPrepared (plugin->dbh, "getm", 0, NULL, NULL, NULL, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", "getm")) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (postgres error)\n"); return 0; } if (0 == PQntuples (res)) { /* no result */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (no more results)\n"); PQclear (res); return GNUNET_SYSERR; } if ((3 != PQnfields (res)) || (sizeof (size) != PQfsize (res, 0)) || (sizeof (oid) != PQfsize (res, 1)) || (sizeof (struct GNUNET_HashCode) != PQgetlength (res, 0, 2))) { GNUNET_break (0); PQclear (res); return 0; } size = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); oid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); memcpy (&key, PQgetvalue (res, 0, 2), sizeof (struct GNUNET_HashCode)); PQclear (res); if (GNUNET_OK != GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, "delrow", oid)) return GNUNET_SYSERR; plugin->env->delete_notify (plugin->env->cls, &key, size + OVERHEAD); return GNUNET_OK; } /** * Entry point for the plugin. * * @param cls closure (the "struct GNUNET_DATACACHE_PluginEnvironmnet") * @return the plugin's closure (our "struct Plugin") */ void * libgnunet_plugin_datacache_postgres_init (void *cls) { struct GNUNET_DATACACHE_PluginEnvironment *env = cls; struct GNUNET_DATACACHE_PluginFunctions *api; struct Plugin *plugin; plugin = GNUNET_new (struct Plugin); plugin->env = env; if (GNUNET_OK != init_connection (plugin)) { GNUNET_free (plugin); return NULL; } api = GNUNET_new (struct GNUNET_DATACACHE_PluginFunctions); api->cls = plugin; api->get = &postgres_plugin_get; api->put = &postgres_plugin_put; api->del = &postgres_plugin_del; LOG (GNUNET_ERROR_TYPE_INFO, _("Postgres datacache running\n")); return api; } /** * Exit point from the plugin. * * @param cls closure (our "struct Plugin") * @return NULL */ void * libgnunet_plugin_datacache_postgres_done (void *cls) { struct GNUNET_DATACACHE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; PQfinish (plugin->dbh); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_datacache_postgres.c */ gnunet-0.10.1/src/datacache/perf_datacache_data_heap.conf0000644000175000017500000000005512225230043020235 00000000000000[perfcache] QUOTA = 500 KB DATABASE = heap gnunet-0.10.1/src/testing/0000755000175000017500000000000012320755623012343 500000000000000gnunet-0.10.1/src/testing/list-keys.c0000644000175000017500000000527212263473436014366 00000000000000#include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" static unsigned int nkeys; static unsigned int nskip; static int result; /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { char *idfile; struct GNUNET_DISK_FileHandle *f; void *data; struct GNUNET_DISK_MapHandle *map; struct GNUNET_CRYPTO_EddsaPrivateKey pkey; struct GNUNET_PeerIdentity id; unsigned int cnt; uint64_t fsize; unsigned int nmax; if ((NULL == args) || (NULL == args[0])) { FPRINTF (stderr, "Need the hostkey file\n"); return; } idfile = args[0]; if (GNUNET_OK != GNUNET_DISK_file_size (idfile, &fsize, GNUNET_YES, GNUNET_YES)) { GNUNET_break (0); return; } if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE)) { FPRINTF (stderr, _("Incorrect hostkey file format: %s\n"), idfile); return; } f = GNUNET_DISK_file_open (idfile, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == f) { GNUNET_break (0); return; } data = GNUNET_DISK_file_map (f, &map, GNUNET_DISK_MAP_TYPE_READ, fsize); if (NULL == data) { GNUNET_break (0); GNUNET_DISK_file_close (f); return; } nmax = fsize / GNUNET_TESTING_HOSTKEYFILESIZE; for (cnt = nskip; cnt < (nskip + nkeys); cnt++) { if (nskip + cnt >= nmax) { PRINTF ("Max keys %u reached\n", nmax); break; } (void) memcpy (&pkey, data + (cnt * GNUNET_TESTING_HOSTKEYFILESIZE), GNUNET_TESTING_HOSTKEYFILESIZE); GNUNET_CRYPTO_eddsa_key_get_public (&pkey, &id.public_key); PRINTF ("Key %u: %s\n", cnt, GNUNET_i2s_full (&id)); } result = GNUNET_OK; GNUNET_DISK_file_unmap (map); GNUNET_DISK_file_close (f); } int main (int argc, char *argv[]) { struct GNUNET_GETOPT_CommandLineOption option[] = { {'n', "num-keys", "COUNT", gettext_noop ("list COUNT number of keys"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &nkeys}, {'s', "skip", "COUNT", gettext_noop ("skip COUNT number of keys in the beginning"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &nskip}, GNUNET_GETOPT_OPTION_END }; int ret; result = GNUNET_SYSERR; nkeys = 10; ret = GNUNET_PROGRAM_run (argc, argv, "list-keys", "Lists the peer IDs corresponding to the given keys file\n", option, &run, NULL); if (GNUNET_OK != ret) return 1; if (GNUNET_SYSERR == result) return 1; return 0; } gnunet-0.10.1/src/testing/test_testing_servicestartup.c0000644000175000017500000000430112225777501020307 00000000000000/* This file is part of GNUnet (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testing/test_testing_new_servicestartup.c * @brief test case for testing service startup using new testing API * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Global test status */ static int test_success; /** * The testing callback function * * @param cls NULL * @param cfg the configuration with which the current testing service is run */ static void test_run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { GNUNET_assert (NULL == cls); GNUNET_assert (NULL != cfg); LOG (GNUNET_ERROR_TYPE_DEBUG, "Service arm started successfully\n"); test_success = GNUNET_YES; GNUNET_SCHEDULER_shutdown (); } /** * The main point of execution */ int main (int argc, char *argv[]) { test_success = GNUNET_NO; GNUNET_assert (0 == GNUNET_TESTING_service_run ("test-testing-servicestartup", "arm", "test_testing_defaults.conf", &test_run, NULL)); return (GNUNET_YES == test_success) ? 0 : 1; } /* end of test_testing_servicestartup.c */ gnunet-0.10.1/src/testing/test_testing_peerstartup2.c0000644000175000017500000001305112255010512017647 00000000000000/* This file is part of GNUnet (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testing/test_testing_new_peerstartup.c * @brief test case for testing peer startup and shutdown using new testing * library * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) #define FAIL_TEST(cond) \ do { \ if (!(cond)) { \ GNUNET_break (0); \ if (GNUNET_OK == status) { \ status = GNUNET_SYSERR; \ } \ } \ } while (0) \ /** * The status of the test */ int status; /** * The testing context */ struct TestingContext { /** * The testing system */ struct GNUNET_TESTING_System *system; /** * The peer which has been started by the testing system */ struct GNUNET_TESTING_Peer *peer; /** * The running configuration of the peer */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * State */ enum { PEER_INIT, PEER_STARTED, PEER_STOPPED } state; }; static void do_shutdown2 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestingContext *test_ctx = cls; if (NULL != test_ctx->peer) GNUNET_TESTING_peer_destroy (test_ctx->peer); if (NULL != test_ctx->cfg) GNUNET_CONFIGURATION_destroy (test_ctx->cfg); if (NULL != test_ctx->system) GNUNET_TESTING_system_destroy (test_ctx->system, GNUNET_YES); GNUNET_free (test_ctx); } /** * Task for shutdown * * @param cls the testing context * @param tc the tast context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void peer_status_cb (void *cls, struct GNUNET_TESTING_Peer *peer, int success) { struct TestingContext *test_ctx = cls; switch (test_ctx->state) { case PEER_INIT: FAIL_TEST (0); break; case PEER_STARTED: FAIL_TEST (GNUNET_YES == success); test_ctx->state = PEER_STOPPED; GNUNET_SCHEDULER_add_now (&do_shutdown2, cls); break; case PEER_STOPPED: FAIL_TEST (0); } } /** * Task for shutdown * * @param cls the testing context * @param tc the tast context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestingContext *test_ctx = cls; GNUNET_assert (NULL != test_ctx); if (NULL != test_ctx->peer) { FAIL_TEST (GNUNET_OK == GNUNET_TESTING_peer_stop_async (test_ctx->peer, &peer_status_cb, test_ctx)); } else do_shutdown2 (test_ctx, tc); } /** * Main point of test execution */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TestingContext *test_ctx; char *emsg; struct GNUNET_PeerIdentity id; test_ctx = GNUNET_new (struct TestingContext); test_ctx->system = GNUNET_TESTING_system_create ("test-gnunet-testing", "127.0.0.1", NULL, NULL); emsg = NULL; if (NULL == test_ctx->system) goto end; test_ctx->cfg = GNUNET_CONFIGURATION_dup (cfg); test_ctx->peer = GNUNET_TESTING_peer_configure (test_ctx->system, test_ctx->cfg, 0, &id, &emsg); if (NULL == test_ctx->peer) { if (NULL != emsg) printf ("Test failed upon error: %s", emsg); goto end; } if (GNUNET_OK != GNUNET_TESTING_peer_start (test_ctx->peer)) goto end; test_ctx->state = PEER_STARTED; FAIL_TEST (GNUNET_OK == GNUNET_TESTING_peer_stop_async (test_ctx->peer, &peer_status_cb, test_ctx)); GNUNET_TESTING_peer_stop_async_cancel (test_ctx->peer); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, test_ctx); return; end: FAIL_TEST (0); GNUNET_SCHEDULER_add_now (&do_shutdown, test_ctx); GNUNET_free_non_null (emsg); } int main (int argc, char *argv[]) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; status = GNUNET_OK; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test_testing_new_peerstartup", "test case for peerstartup using new testing library", options, &run, NULL)) return 1; return (GNUNET_OK == status) ? 0 : 1; } /* end of test_testing_peerstartup.c */ gnunet-0.10.1/src/testing/testing.c0000644000175000017500000015357012307312000014076 00000000000000/* This file is part of GNUnet (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testing/testing.c * @brief convenience API for writing testcases for GNUnet * Many testcases need to start and stop a peer/service * and this library is supposed to make that easier * for TESTCASES. Normal programs should always * use functions from gnunet_{util,arm}_lib.h. This API is * ONLY for writing testcases (or internal use of the testbed). * @author Christian Grothoff * */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_testing_lib.h" #define LOG(kind,...) \ GNUNET_log_from (kind, "testing-api", __VA_ARGS__) /** * We need pipe control only on WINDOWS */ #if WINDOWS #define PIPE_CONTROL GNUNET_YES #else #define PIPE_CONTROL GNUNET_NO #endif /** * Lowest port used for GNUnet testing. Should be high enough to not * conflict with other applications running on the hosts but be low * enough to not conflict with client-ports (typically starting around * 32k). */ #define LOW_PORT 12000 /** * Highest port used for GNUnet testing. Should be low enough to not * conflict with the port range for "local" ports (client apps; see * /proc/sys/net/ipv4/ip_local_port_range on Linux for example). */ #define HIGH_PORT 56000 struct SharedServiceInstance { struct SharedService *ss; char *cfg_fn; struct GNUNET_OS_Process *proc; char *unix_sock; char *port_str; unsigned int n_refs; }; struct SharedService { char *sname; struct SharedServiceInstance **instances; struct GNUNET_CONFIGURATION_Handle *cfg; unsigned int n_peers; unsigned int share; unsigned int n_instances; }; /** * Handle for a system on which GNUnet peers are executed; * a system is used for reserving unique paths and ports. */ struct GNUNET_TESTING_System { /** * Prefix (i.e. "/tmp/gnunet-testing/") we prepend to each * GNUNET_HOME. */ char *tmppath; /** * The trusted ip. Can either be a single ip address or a network address in * CIDR notation. */ char *trusted_ip; /** * our hostname */ char *hostname; /** * Hostkeys data, contains "GNUNET_TESTING_HOSTKEYFILESIZE * total_hostkeys" bytes. */ char *hostkeys_data; /** * memory map for 'hostkeys_data'. */ struct GNUNET_DISK_MapHandle *map; struct SharedService **shared_services; unsigned int n_shared_services; /** * Bitmap where each port that has already been reserved for some GNUnet peer * is recorded. Note that we make no distinction between TCP and UDP ports * and test if a port is already in use before assigning it to a peer/service. * If we detect that a port is already in use, we also mark it in this bitmap. * So all the bits that are zero merely indicate ports that MIGHT be available * for peers. */ uint32_t reserved_ports[65536 / 32]; /** * Counter we use to make service home paths unique on this system; * the full path consists of the tmppath and this number. Each * UNIXPATH for a peer is also modified to include the respective * path counter to ensure uniqueness. This field is incremented * by one for each configured peer. Even if peers are destroyed, * we never re-use path counters. */ uint32_t path_counter; /** * The number of hostkeys */ uint32_t total_hostkeys; /** * Lowest port we are allowed to use. */ uint16_t lowport; /** * Highest port we are allowed to use. */ uint16_t highport; }; /** * Handle for a GNUnet peer controlled by testing. */ struct GNUNET_TESTING_Peer { /** * The TESTING system associated with this peer */ struct GNUNET_TESTING_System *system; /** * Path to the configuration file for this peer. */ char *cfgfile; /** * Binary to be executed during 'GNUNET_TESTING_peer_start'. * Typically 'gnunet-service-arm' (but can be set to a * specific service by 'GNUNET_TESTING_service_run' if * necessary). */ char *main_binary; char *args; /** * Handle to the running binary of the service, NULL if the * peer/service is currently not running. */ struct GNUNET_OS_Process *main_process; /** * The handle to the peer's ARM service */ struct GNUNET_ARM_Handle *ah; /** * Handle to ARM monitoring */ struct GNUNET_ARM_MonitorHandle *mh; /** * The config of the peer */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The callback to call asynchronously when a peer is stopped */ GNUNET_TESTING_PeerStopCallback cb; /** * The closure for the above callback */ void *cb_cls; /** * The cached identity of this peer. Will be populated on call to * GNUNET_TESTING_peer_get_identity() */ struct GNUNET_PeerIdentity *id; struct SharedServiceInstance **ss_instances; /** * Array of ports currently allocated to this peer. These ports will be * released upon peer destroy and can be used by other peers which are * configured after. */ uint16_t *ports; /** * The number of ports in the above array */ unsigned int nports; /** * The keynumber of this peer's hostkey */ uint32_t key_number; }; /** * Testing includes a number of pre-created hostkeys for faster peer * startup. This function loads such keys into memory from a file. * * @param system the testing system handle * @return GNUNET_OK on success; GNUNET_SYSERR on error */ static int hostkeys_load (struct GNUNET_TESTING_System *system) { uint64_t fs; char *data_dir; char *filename; struct GNUNET_DISK_FileHandle *fd; GNUNET_assert (NULL == system->hostkeys_data); data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); GNUNET_asprintf (&filename, "%s/testing_hostkeys.ecc", data_dir); GNUNET_free (data_dir); if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Hostkeys file not found: %s\n"), filename); GNUNET_free (filename); return GNUNET_SYSERR; } /* Check hostkey file size, read entire thing into memory */ if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) fs = 0; if (0 == fs) { GNUNET_free (filename); return GNUNET_SYSERR; /* File is empty */ } if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Incorrect hostkey file format: %s\n"), filename); GNUNET_free (filename); return GNUNET_SYSERR; } fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename); GNUNET_free (filename); return GNUNET_SYSERR; } GNUNET_free (filename); system->hostkeys_data = GNUNET_DISK_file_map (fd, &system->map, GNUNET_DISK_MAP_TYPE_READ, fs); GNUNET_DISK_file_close (fd); if (NULL == system->hostkeys_data) return GNUNET_SYSERR; system->total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE; return GNUNET_OK; } /** * Function to remove the loaded hostkeys * * @param system the testing system handle */ static void hostkeys_unload (struct GNUNET_TESTING_System *system) { GNUNET_break (NULL != system->hostkeys_data); system->hostkeys_data = NULL; GNUNET_DISK_file_unmap (system->map); system->map = NULL; system->hostkeys_data = NULL; system->total_hostkeys = 0; } /** * Function to iterate over options. * * @param cls closure * @param section name of the section * @param option name of the option * @param value value of the option */ static void cfg_copy_iterator (void *cls, const char *section, const char *option, const char *value) { struct GNUNET_CONFIGURATION_Handle *cfg2 = cls; GNUNET_CONFIGURATION_set_value_string (cfg2, section, option, value); } /** * Create a system handle. There must only be one system * handle per operating system. * * @param testdir only the directory name without any path. This is used for * all service homes; the directory will be created in a temporary * location depending on the underlying OS. This variable will be * overridden with the value of the environmental variable * GNUNET_TESTING_PREFIX, if it exists. * @param trusted_ip the ip address which will be set as TRUSTED HOST in all * service configurations generated to allow control connections from * this ip. This can either be a single ip address or a network address * in CIDR notation. * @param hostname the hostname of the system we are using for testing; NULL for * localhost * @param shared_services NULL terminated array describing services that are to * be shared among peers * @param lowport lowest port number this system is allowed to allocate (inclusive) * @param highport highest port number this system is allowed to allocate (exclusive) * @return handle to this system, NULL on error */ struct GNUNET_TESTING_System * GNUNET_TESTING_system_create_with_portrange (const char *testdir, const char *trusted_ip, const char *hostname, const struct GNUNET_TESTING_SharedService * shared_services, uint16_t lowport, uint16_t highport) { struct GNUNET_TESTING_System *system; struct GNUNET_TESTING_SharedService tss; struct SharedService *ss; unsigned int cnt; GNUNET_assert (NULL != testdir); system = GNUNET_new (struct GNUNET_TESTING_System); if (NULL == (system->tmppath = getenv (GNUNET_TESTING_PREFIX))) system->tmppath = GNUNET_DISK_mkdtemp (testdir); else system->tmppath = GNUNET_strdup (system->tmppath); system->lowport = lowport; system->highport = highport; if (NULL == system->tmppath) { GNUNET_free (system); return NULL; } if (NULL != trusted_ip) system->trusted_ip = GNUNET_strdup (trusted_ip); if (NULL != hostname) system->hostname = GNUNET_strdup (hostname); if (GNUNET_OK != hostkeys_load (system)) { GNUNET_TESTING_system_destroy (system, GNUNET_YES); return NULL; } if (NULL == shared_services) return system; for (cnt = 0; NULL != shared_services[cnt].service; cnt++) { tss = shared_services[cnt]; ss = GNUNET_new (struct SharedService); ss->sname = GNUNET_strdup (tss.service); ss->cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, ss->sname, &cfg_copy_iterator, ss->cfg); GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "TESTING", &cfg_copy_iterator, ss->cfg); GNUNET_CONFIGURATION_iterate_section_values (tss.cfg, "PATHS", &cfg_copy_iterator, ss->cfg); ss->share = tss.share; GNUNET_array_append (system->shared_services, system->n_shared_services, ss); } return system; } /** * Create a system handle. There must only be one system handle per operating * system. Uses a default range for allowed ports. Ports are still tested for * availability. * * @param testdir only the directory name without any path. This is used for all * service homes; the directory will be created in a temporary location * depending on the underlying OS. This variable will be * overridden with the value of the environmental variable * GNUNET_TESTING_PREFIX, if it exists. * @param trusted_ip the ip address which will be set as TRUSTED HOST in all * service configurations generated to allow control connections from * this ip. This can either be a single ip address or a network address * in CIDR notation. * @param hostname the hostname of the system we are using for testing; NULL for * localhost * @param shared_services NULL terminated array describing services that are to * be shared among peers * @return handle to this system, NULL on error */ struct GNUNET_TESTING_System * GNUNET_TESTING_system_create (const char *testdir, const char *trusted_ip, const char *hostname, const struct GNUNET_TESTING_SharedService * shared_services) { return GNUNET_TESTING_system_create_with_portrange (testdir, trusted_ip, hostname, shared_services, LOW_PORT, HIGH_PORT); } static void cleanup_shared_service_instance (struct SharedServiceInstance *i) { if (NULL != i->cfg_fn) { (void) unlink (i->cfg_fn); GNUNET_free (i->cfg_fn); } GNUNET_free_non_null (i->unix_sock); GNUNET_free_non_null (i->port_str); GNUNET_break (NULL == i->proc); GNUNET_break (0 == i->n_refs); GNUNET_free (i); } static int start_shared_service_instance (struct SharedServiceInstance *i) { char *binary; char *libexec_binary; GNUNET_assert (NULL == i->proc); GNUNET_assert (NULL != i->cfg_fn); (void) GNUNET_asprintf (&binary, "gnunet-service-%s", i->ss->sname); libexec_binary = GNUNET_OS_get_libexec_binary_path (binary); GNUNET_free (binary); i->proc = GNUNET_OS_start_process (PIPE_CONTROL, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, libexec_binary, libexec_binary, "-c", i->cfg_fn, NULL); GNUNET_free (libexec_binary); if (NULL == i->proc) return GNUNET_SYSERR; return GNUNET_OK; } static void stop_shared_service_instance (struct SharedServiceInstance *i) { GNUNET_break (0 == i->n_refs); if (0 != GNUNET_OS_process_kill (i->proc, GNUNET_TERM_SIG)) LOG (GNUNET_ERROR_TYPE_WARNING, "Killing shared service instance (%s) failed\n", i->ss->sname); (void) GNUNET_OS_process_wait (i->proc); GNUNET_OS_process_destroy (i->proc); i->proc = NULL; } /** * Free system resources. * * @param system system to be freed * @param remove_paths should the 'testdir' and all subdirectories * be removed (clean up on shutdown)? */ void GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system, int remove_paths) { struct SharedService *ss; struct SharedServiceInstance *i; unsigned int ss_cnt; unsigned int i_cnt; if (NULL != system->hostkeys_data) hostkeys_unload (system); for (ss_cnt = 0; ss_cnt < system->n_shared_services; ss_cnt++) { ss = system->shared_services[ss_cnt]; for (i_cnt = 0; i_cnt < ss->n_instances; i_cnt++) { i = ss->instances[i_cnt]; if (NULL != i->proc) stop_shared_service_instance (i); cleanup_shared_service_instance (i); } GNUNET_free_non_null (ss->instances); GNUNET_CONFIGURATION_destroy (ss->cfg); GNUNET_free (ss->sname); GNUNET_free (ss); } GNUNET_free_non_null (system->shared_services); if (GNUNET_YES == remove_paths) GNUNET_DISK_directory_remove (system->tmppath); GNUNET_free (system->tmppath); GNUNET_free_non_null (system->trusted_ip); GNUNET_free_non_null (system->hostname); GNUNET_free (system); } /** * Reserve a TCP or UDP port for a peer. * * @param system system to use for reservation tracking * @return 0 if no free port was available */ uint16_t GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system) { struct GNUNET_NETWORK_Handle *socket; struct addrinfo hint; struct addrinfo *ret; struct addrinfo *ai; uint32_t *port_buckets; char *open_port_str; int bind_status; uint32_t xor_image; uint16_t index; uint16_t open_port; uint16_t pos; /* FIXME: Instead of using getaddrinfo we should try to determine the port status by the following heurestics. On systems which support both IPv4 and IPv6, only ports open on both address families are considered open. On system with either IPv4 or IPv6. A port is considered open if it's open in the respective address family */ hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */ hint.ai_socktype = 0; hint.ai_protocol = 0; hint.ai_addrlen = 0; hint.ai_addr = NULL; hint.ai_canonname = NULL; hint.ai_next = NULL; hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */ port_buckets = system->reserved_ports; for (index = (system->lowport / 32) + 1; index < (system->highport / 32); index++) { xor_image = (UINT32_MAX ^ port_buckets[index]); if (0 == xor_image) /* Ports in the bucket are full */ continue; pos = system->lowport % 32; while (pos < 32) { if (0 == ((xor_image >> pos) & 1U)) { pos++; continue; } open_port = (index * 32) + pos; if (open_port >= system->highport) return 0; GNUNET_asprintf (&open_port_str, "%u", (unsigned int) open_port); ret = NULL; GNUNET_assert (0 == getaddrinfo (NULL, open_port_str, &hint, &ret)); GNUNET_free (open_port_str); bind_status = GNUNET_NO; for (ai = ret; NULL != ai; ai = ai->ai_next) { socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_STREAM, 0); if (NULL == socket) continue; bind_status = GNUNET_NETWORK_socket_bind (socket, ai->ai_addr, ai->ai_addrlen); GNUNET_NETWORK_socket_close (socket); if (GNUNET_OK != bind_status) break; socket = GNUNET_NETWORK_socket_create (ai->ai_family, SOCK_DGRAM, 0); if (NULL == socket) continue; bind_status = GNUNET_NETWORK_socket_bind (socket, ai->ai_addr, ai->ai_addrlen); GNUNET_NETWORK_socket_close (socket); if (GNUNET_OK != bind_status) break; } port_buckets[index] |= (1U << pos); /* Set the port bit */ freeaddrinfo (ret); if (GNUNET_OK == bind_status) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Found a free port %u\n", (unsigned int) open_port); return open_port; } pos++; } } return 0; } /** * Release reservation of a TCP or UDP port for a peer * (used during GNUNET_TESTING_peer_destroy). * * @param system system to use for reservation tracking * @param port reserved port to release */ void GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system, uint16_t port) { uint32_t *port_buckets; uint16_t bucket; uint16_t pos; port_buckets = system->reserved_ports; bucket = port / 32; pos = port % 32; LOG (GNUNET_ERROR_TYPE_DEBUG, "Releasing port %u\n", port); if (0 == (port_buckets[bucket] & (1U << pos))) { GNUNET_break(0); /* Port was not reserved by us using reserve_port() */ return; } port_buckets[bucket] &= ~(1U << pos); } /** * Testing includes a number of pre-created hostkeys for * faster peer startup. This function can be used to * access the n-th key of those pre-created hostkeys; note * that these keys are ONLY useful for testing and not * secure as the private keys are part of the public * GNUnet source code. * * This is primarily a helper function used internally * by #GNUNET_TESTING_peer_configure. * * @param system the testing system handle * @param key_number desired pre-created hostkey to obtain * @param id set to the peer's identity (hash of the public * key; if NULL, GNUNET_SYSERR is returned immediately * @return NULL on error (not enough keys) */ struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system, uint32_t key_number, struct GNUNET_PeerIdentity *id) { struct GNUNET_CRYPTO_EddsaPrivateKey *private_key; if ((NULL == id) || (NULL == system->hostkeys_data)) return NULL; if (key_number >= system->total_hostkeys) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Key number %u does not exist\n"), key_number); return NULL; } private_key = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey); memcpy (private_key, system->hostkeys_data + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE), GNUNET_TESTING_HOSTKEYFILESIZE); GNUNET_CRYPTO_eddsa_key_get_public (private_key, &id->public_key); return private_key; } /** * Structure for holding data to build new configurations from a configuration * template */ struct UpdateContext { /** * The system for which we are building configurations */ struct GNUNET_TESTING_System *system; /** * The configuration we are building */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The customized service home path for this peer */ char *gnunet_home; /** * Array of ports currently allocated to this peer. These ports will be * released upon peer destroy and can be used by other peers which are * configured after. */ uint16_t *ports; /** * The number of ports in the above array */ unsigned int nports; /** * build status - to signal error while building a configuration */ int status; }; /** * Function to iterate over options. Copies * the options to the target configuration, * updating PORT values as needed. * * @param cls the UpdateContext * @param section name of the section * @param option name of the option * @param value value of the option */ static void update_config (void *cls, const char *section, const char *option, const char *value) { struct UpdateContext *uc = cls; unsigned int ival; char cval[12]; char uval[128]; char *single_variable; char *per_host_variable; unsigned long long num_per_host; uint16_t new_port; if (GNUNET_OK != uc->status) return; if (! ((0 == strcmp (option, "PORT")) || (0 == strcmp (option, "UNIXPATH")) || (0 == strcmp (option, "HOSTNAME")))) return; GNUNET_asprintf (&single_variable, "single_%s_per_host", section); GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section); if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival))) { if ((ival != 0) && (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing", single_variable))) { new_port = GNUNET_TESTING_reserve_port (uc->system); if (0 == new_port) { uc->status = GNUNET_SYSERR; GNUNET_free (single_variable); GNUNET_free (per_host_variable); return; } GNUNET_snprintf (cval, sizeof (cval), "%u", new_port); value = cval; GNUNET_array_append (uc->ports, uc->nports, new_port); } else if ((ival != 0) && (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing", single_variable)) && GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing", per_host_variable, &num_per_host)) { /* GNUNET_snprintf (cval, sizeof (cval), "%u", */ /* ival + ctx->fdnum % num_per_host); */ /* value = cval; */ GNUNET_break (0); /* FIXME */ } } if (0 == strcmp (option, "UNIXPATH")) { if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (uc->cfg, "testing", single_variable)) { GNUNET_snprintf (uval, sizeof (uval), "%s/%s.sock", uc->gnunet_home, section); value = uval; } else if ((GNUNET_YES == GNUNET_CONFIGURATION_get_value_number (uc->cfg, "testing", per_host_variable, &num_per_host)) && (num_per_host > 0)) { GNUNET_break(0); /* FIXME */ } } if (0 == strcmp (option, "HOSTNAME")) { value = (NULL == uc->system->hostname) ? "localhost" : uc->system->hostname; } GNUNET_free (single_variable); GNUNET_free (per_host_variable); GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, option, value); } /** * Section iterator to set ACCEPT_FROM/ACCEPT_FROM6 to include the address of * 'trusted_hosts' in all sections * * @param cls the UpdateContext * @param section name of the section */ static void update_config_sections (void *cls, const char *section) { struct UpdateContext *uc = cls; char **ikeys; char *val; char *ptr; char *orig_allowed_hosts; char *allowed_hosts; char *ACCEPT_FROM_key; uint16_t ikeys_cnt; uint16_t key; ikeys_cnt = 0; val = NULL; /* Ignore certain options from sections. See https://gnunet.org/bugs/view.php?id=2476 */ if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section, "TESTING_IGNORE_KEYS")) { GNUNET_assert (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "TESTING_IGNORE_KEYS", &val)); ptr = val; for (ikeys_cnt = 0; NULL != (ptr = strstr (ptr, ";")); ikeys_cnt++) ptr++; if (0 == ikeys_cnt) GNUNET_break (0); else { ikeys = GNUNET_malloc ((sizeof (char *)) * ikeys_cnt); ptr = val; for (key = 0; key < ikeys_cnt; key++) { ikeys[key] = ptr; ptr = strstr (ptr, ";"); *ptr = '\0'; ptr++; } } } if (0 != ikeys_cnt) { for (key = 0; key < ikeys_cnt; key++) { if (NULL != strstr (ikeys[key], "ADVERTISED_PORT")) break; } if ((key == ikeys_cnt) && (GNUNET_YES == GNUNET_CONFIGURATION_have_value (uc->cfg, section, "ADVERTISED_PORT"))) { if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, "PORT", &ptr)) { GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, "ADVERTISED_PORT", ptr); GNUNET_free (ptr); } } for (key = 0; key < ikeys_cnt; key++) { if (NULL != strstr (ikeys[key], "ACCEPT_FROM")) { GNUNET_free (ikeys); GNUNET_free (val); return; } } GNUNET_free (ikeys); } GNUNET_free_non_null (val); ACCEPT_FROM_key = "ACCEPT_FROM"; if ((NULL != uc->system->trusted_ip) && (NULL != strstr (uc->system->trusted_ip, ":"))) /* IPv6 in use */ ACCEPT_FROM_key = "ACCEPT_FROM6"; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (uc->cfg, section, ACCEPT_FROM_key, &orig_allowed_hosts)) { orig_allowed_hosts = GNUNET_strdup ("127.0.0.1;"); } if (NULL == uc->system->trusted_ip) allowed_hosts = GNUNET_strdup (orig_allowed_hosts); else GNUNET_asprintf (&allowed_hosts, "%s%s;", orig_allowed_hosts, uc->system->trusted_ip); GNUNET_free (orig_allowed_hosts); GNUNET_CONFIGURATION_set_value_string (uc->cfg, section, ACCEPT_FROM_key, allowed_hosts); GNUNET_free (allowed_hosts); } static struct SharedServiceInstance * associate_shared_service (struct GNUNET_TESTING_System *system, struct SharedService *ss, struct GNUNET_CONFIGURATION_Handle *cfg) { struct SharedServiceInstance *i; struct GNUNET_CONFIGURATION_Handle *temp; char *gnunet_home; uint32_t port; ss->n_peers++; if ( ((0 == ss->share) && (NULL == ss->instances)) || ( (0 != ss->share) && (ss->n_instances < ((ss->n_peers + ss->share - 1) / ss->share)) ) ) { i = GNUNET_new (struct SharedServiceInstance); i->ss = ss; (void) GNUNET_asprintf (&gnunet_home, "%s/shared/%s/%u", system->tmppath, ss->sname, ss->n_instances); (void) GNUNET_asprintf (&i->unix_sock, "%s/sock", gnunet_home); port = GNUNET_TESTING_reserve_port (system); if (0 == port) { GNUNET_free (gnunet_home); cleanup_shared_service_instance (i); return NULL; } GNUNET_array_append (ss->instances, ss->n_instances, i); temp = GNUNET_CONFIGURATION_dup (ss->cfg); (void) GNUNET_asprintf (&i->port_str, "%u", port); (void) GNUNET_asprintf (&i->cfg_fn, "%s/config", gnunet_home); GNUNET_CONFIGURATION_set_value_string (temp, "PATHS", "GNUNET_HOME", gnunet_home); GNUNET_free (gnunet_home); GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "UNIXPATH", i->unix_sock); GNUNET_CONFIGURATION_set_value_string (temp, ss->sname, "PORT", i->port_str); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write (temp, i->cfg_fn)) { GNUNET_CONFIGURATION_destroy (temp); cleanup_shared_service_instance (i); return NULL; } GNUNET_CONFIGURATION_destroy (temp); } else { GNUNET_assert (NULL != ss->instances); GNUNET_assert (0 < ss->n_instances); i = ss->instances[ss->n_instances - 1]; } GNUNET_CONFIGURATION_iterate_section_values(ss->cfg, ss->sname, &cfg_copy_iterator, cfg); GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "UNIXPATH", i->unix_sock); GNUNET_CONFIGURATION_set_value_string (cfg, ss->sname, "PORT", i->port_str); return i; } /** * Create a new configuration using the given configuration as a template; * ports and paths will be modified to select available ports on the local * system. The default configuration will be available in PATHS section under * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS * section to the temporary directory specific to this configuration. If we run * out of "*port" numbers, return #GNUNET_SYSERR. * * This is primarily a helper function used internally * by 'GNUNET_TESTING_peer_configure'. * * @param system system to use to coordinate resource usage * @param cfg template configuration to update * @param ports array with port numbers used in the created configuration. * Will be updated upon successful return. Can be NULL * @param nports the size of the `ports' array. Will be updated. * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - the configuration will * be incomplete and should not be used there upon */ static int GNUNET_TESTING_configuration_create_ (struct GNUNET_TESTING_System *system, struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t **ports, unsigned int *nports) { struct UpdateContext uc; char *default_config; uc.system = system; uc.cfg = cfg; uc.status = GNUNET_OK; uc.ports = NULL; uc.nports = 0; GNUNET_asprintf (&uc.gnunet_home, "%s/%u", system->tmppath, system->path_counter++); GNUNET_asprintf (&default_config, "%s/config", uc.gnunet_home); GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG", default_config); GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG", default_config); GNUNET_free (default_config); GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "GNUNET_HOME", uc.gnunet_home); /* make PORTs and UNIXPATHs unique */ GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc); /* allow connections to services from system trusted_ip host */ GNUNET_CONFIGURATION_iterate_sections (cfg, &update_config_sections, &uc); /* enable loopback-based connections between peers */ GNUNET_CONFIGURATION_set_value_string (cfg, "nat", "USE_LOCALADDR", "YES"); GNUNET_free (uc.gnunet_home); if ((NULL != ports) && (NULL != nports)) { *ports = uc.ports; *nports = uc.nports; } else GNUNET_free_non_null (uc.ports); return uc.status; } /** * Create a new configuration using the given configuration as a template; * ports and paths will be modified to select available ports on the local * system. The default configuration will be available in PATHS section under * the option DEFAULTCONFIG after the call. GNUNET_HOME is also set in PATHS * section to the temporary directory specific to this configuration. If we run * out of "*port" numbers, return SYSERR. * * This is primarily a helper function used internally * by 'GNUNET_TESTING_peer_configure'. * * @param system system to use to coordinate resource usage * @param cfg template configuration to update * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will * be incomplete and should not be used there upon */ int GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system, struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_TESTING_configuration_create_ (system, cfg, NULL, NULL); } /** * Configure a GNUnet peer. GNUnet must be installed on the local * system and available in the PATH. * * @param system system to use to coordinate resource usage * @param cfg configuration to use; will be UPDATED (to reflect needed * changes in port numbers and paths) * @param key_number number of the hostkey to use for the peer * @param id identifier for the daemon, will be set, can be NULL * @param emsg set to freshly allocated error message (set to NULL on success), * can be NULL * @return handle to the peer, NULL on error */ struct GNUNET_TESTING_Peer * GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system, struct GNUNET_CONFIGURATION_Handle *cfg, uint32_t key_number, struct GNUNET_PeerIdentity *id, char **emsg) { struct GNUNET_TESTING_Peer *peer; struct GNUNET_DISK_FileHandle *fd; char *hostkey_filename; char *config_filename; char *libexec_binary; char *emsg_; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; uint16_t *ports; struct SharedService *ss; struct SharedServiceInstance **ss_instances; unsigned int cnt; unsigned int nports; ports = NULL; nports = 0; ss_instances = NULL; if (NULL != emsg) *emsg = NULL; if (key_number >= system->total_hostkeys) { GNUNET_asprintf (&emsg_, _("You attempted to create a testbed with more than %u hosts. Please precompute more hostkeys first.\n"), (unsigned int) system->total_hostkeys); goto err_ret; } pk = NULL; if ((NULL != id) && (NULL == (pk = GNUNET_TESTING_hostkey_get (system, key_number, id)))) { GNUNET_asprintf (&emsg_, _("Failed to initialize hostkey for peer %u\n"), (unsigned int) key_number); goto err_ret; } if (NULL != pk) GNUNET_free (pk); if (GNUNET_NO == GNUNET_CONFIGURATION_have_value (cfg, "PEER", "PRIVATE_KEY")) { GNUNET_asprintf (&emsg_, _("PRIVATE_KEY option in PEER section missing in configuration\n")); goto err_ret; } /* Remove sections for shared services */ for (cnt = 0; cnt < system->n_shared_services; cnt++) { ss = system->shared_services[cnt]; GNUNET_CONFIGURATION_remove_section (cfg, ss->sname); } if (GNUNET_OK != GNUNET_TESTING_configuration_create_ (system, cfg, &ports, &nports)) { GNUNET_asprintf (&emsg_, _("Failed to create configuration for peer " "(not enough free ports?)\n")); goto err_ret; } GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &hostkey_filename)); fd = GNUNET_DISK_file_open (hostkey_filename, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == fd) { GNUNET_asprintf (&emsg_, _("Cannot open hostkey file `%s': %s\n"), hostkey_filename, STRERROR (errno)); GNUNET_free (hostkey_filename); goto err_ret; } GNUNET_free (hostkey_filename); if (GNUNET_TESTING_HOSTKEYFILESIZE != GNUNET_DISK_file_write (fd, system->hostkeys_data + (key_number * GNUNET_TESTING_HOSTKEYFILESIZE), GNUNET_TESTING_HOSTKEYFILESIZE)) { GNUNET_asprintf (&emsg_, _("Failed to write hostkey file for peer %u: %s\n"), (unsigned int) key_number, STRERROR (errno)); GNUNET_DISK_file_close (fd); goto err_ret; } GNUNET_DISK_file_close (fd); ss_instances = GNUNET_malloc (sizeof (struct SharedServiceInstance *) * system->n_shared_services); for (cnt=0; cnt < system->n_shared_services; cnt++) { ss = system->shared_services[cnt]; ss_instances[cnt] = associate_shared_service (system, ss, cfg); if (NULL == ss_instances[cnt]) { emsg_ = GNUNET_strdup ("FIXME"); goto err_ret; } } GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", "DEFAULTCONFIG", &config_filename)); if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config_filename)) { GNUNET_asprintf (&emsg_, _("Failed to write configuration file `%s' for peer %u: %s\n"), config_filename, (unsigned int) key_number, STRERROR (errno)); GNUNET_free (config_filename); goto err_ret; } peer = GNUNET_new (struct GNUNET_TESTING_Peer); peer->ss_instances = ss_instances; peer->cfgfile = config_filename; /* Free in peer_destroy */ peer->cfg = GNUNET_CONFIGURATION_dup (cfg); libexec_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "arm", "PREFIX", &peer->main_binary)) { /* No prefix */ GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary); peer->args = strdup (""); } else { peer->args = strdup (libexec_binary); } peer->system = system; peer->key_number = key_number; GNUNET_free (libexec_binary); peer->ports = ports; /* Free in peer_destroy */ peer->nports = nports; return peer; err_ret: GNUNET_free_non_null (ss_instances); GNUNET_free_non_null (ports); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_); if (NULL != emsg) *emsg = emsg_; else GNUNET_free (emsg_); return NULL; } /** * Obtain the peer identity from a peer handle. * * @param peer peer handle for which we want the peer's identity * @param id identifier for the daemon, will be set */ void GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer, struct GNUNET_PeerIdentity *id) { if (NULL != peer->id) { memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity)); return; } peer->id = GNUNET_new (struct GNUNET_PeerIdentity); GNUNET_free (GNUNET_TESTING_hostkey_get (peer->system, peer->key_number, peer->id)); memcpy (id, peer->id, sizeof (struct GNUNET_PeerIdentity)); } /** * Start the peer. * * @param peer peer to start * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running) */ int GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer) { struct SharedServiceInstance *i; unsigned int cnt; if (NULL != peer->main_process) { GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_assert (NULL != peer->cfgfile); for (cnt = 0; cnt < peer->system->n_shared_services; cnt++) { i = peer->ss_instances[cnt]; if ((0 == i->n_refs) && (GNUNET_SYSERR == start_shared_service_instance (i)) ) return GNUNET_SYSERR; i->n_refs++; } peer->main_binary = GNUNET_CONFIGURATION_expand_dollar (peer->cfg, peer->main_binary); peer->main_process = GNUNET_OS_start_process_s (PIPE_CONTROL, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, peer->main_binary, peer->args, "-c", peer->cfgfile, NULL); if (NULL == peer->main_process) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start `%s': %s\n"), peer->main_binary, STRERROR (errno)); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Start a service at a peer using its ARM service * * @param peer the peer whose service has to be started * @param service_name name of the service to start * @param timeout how long should the ARM API try to send the request to start * the service * @param cont the callback to call with result and status from ARM API * @param cont_cls the closure for the above callback * @return GNUNET_OK upon successfully queuing the service start request; * GNUNET_SYSERR upon error */ int GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer, const char *service_name, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ResultCallback cont, void *cont_cls) { if (NULL == peer->ah) return GNUNET_SYSERR; GNUNET_ARM_request_service_start (peer->ah, service_name, GNUNET_OS_INHERIT_STD_ALL, timeout, cont, cont_cls); return GNUNET_OK; } /** * Stop a service at a peer using its ARM service * * @param peer the peer whose service has to be stopped * @param service_name name of the service to stop * @param timeout how long should the ARM API try to send the request to stop * the service * @param cont the callback to call with result and status from ARM API * @param cont_cls the closure for the above callback * @return GNUNET_OK upon successfully queuing the service stop request; * GNUNET_SYSERR upon error */ int GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer, const char *service_name, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ResultCallback cont, void *cont_cls) { if (NULL == peer->ah) return GNUNET_SYSERR; GNUNET_ARM_request_service_stop (peer->ah, service_name, timeout, cont, cont_cls); return GNUNET_OK; } /** * Sends SIGTERM to the peer's main process * * @param peer the handle to the peer * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL * or upon any error while sending SIGTERM */ int GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer) { struct SharedServiceInstance *i; unsigned int cnt; if (NULL == peer->main_process) { GNUNET_break (0); return GNUNET_SYSERR; } if (0 != GNUNET_OS_process_kill (peer->main_process, GNUNET_TERM_SIG)) return GNUNET_SYSERR; for (cnt = 0; cnt < peer->system->n_shared_services; cnt++) { i = peer->ss_instances[cnt]; GNUNET_assert (0 != i->n_refs); i->n_refs--; if (0 == i->n_refs) stop_shared_service_instance (i); } return GNUNET_OK; } /** * Waits for a peer to terminate. The peer's main process will also be destroyed. * * @param peer the handle to the peer * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL * or upon any error while waiting */ int GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer) { int ret; if (NULL == peer->main_process) { GNUNET_break (0); return GNUNET_SYSERR; } ret = GNUNET_OS_process_wait (peer->main_process); GNUNET_OS_process_destroy (peer->main_process); peer->main_process = NULL; return ret; } /** * Stop the peer. * * @param peer peer to stop * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer) { if (GNUNET_SYSERR == GNUNET_TESTING_peer_kill (peer)) return GNUNET_SYSERR; if (GNUNET_SYSERR == GNUNET_TESTING_peer_wait (peer)) return GNUNET_SYSERR; return GNUNET_OK; } /** * Function called whenever we connect to or disconnect from ARM. * * @param cls closure * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected, * GNUNET_SYSERR on error. */ static void disconn_status (void *cls, int connected) { struct GNUNET_TESTING_Peer *peer = cls; if (GNUNET_SYSERR == connected) { peer->cb (peer->cb_cls, peer, connected); return; } if (GNUNET_YES == connected) { GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_kill (peer)); return; } GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer)); GNUNET_ARM_disconnect_and_free (peer->ah); peer->ah = NULL; peer->cb (peer->cb_cls, peer, GNUNET_YES); } /** * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled * through the GNUNET_TESTING_PeerStopCallback(). * * @param peer the peer to stop * @param cb the callback to signal peer shutdown * @param cb_cls closure for the above callback * @return GNUNET_OK upon successfully giving the request to the ARM API (this * does not mean that the peer is successfully stopped); GNUNET_SYSERR * upon any error. */ int GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer, GNUNET_TESTING_PeerStopCallback cb, void *cb_cls) { if (NULL == peer->main_process) return GNUNET_SYSERR; peer->ah = GNUNET_ARM_connect (peer->cfg, &disconn_status, peer); if (NULL == peer->ah) return GNUNET_SYSERR; peer->cb = cb; peer->cb_cls = cb_cls; return GNUNET_OK; } /** * Cancel a previous asynchronous peer stop request. * GNUNET_TESTING_peer_stop_async() should have been called before on the given * peer. It is an error to call this function if the peer stop callback was * already called * * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called * before. */ void GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer) { GNUNET_assert (NULL != peer->ah); GNUNET_ARM_disconnect_and_free (peer->ah); peer->ah = NULL; } /** * Destroy the peer. Releases resources locked during peer configuration. * If the peer is still running, it will be stopped AND a warning will be * printed (users of the API should stop the peer explicitly first). * * @param peer peer to destroy */ void GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer) { unsigned int cnt; if (NULL != peer->main_process) GNUNET_TESTING_peer_stop (peer); if (NULL != peer->ah) GNUNET_ARM_disconnect_and_free (peer->ah); if (NULL != peer->mh) GNUNET_ARM_monitor_disconnect_and_free (peer->mh); GNUNET_free (peer->cfgfile); if (NULL != peer->cfg) GNUNET_CONFIGURATION_destroy (peer->cfg); GNUNET_free (peer->main_binary); GNUNET_free (peer->args); GNUNET_free_non_null (peer->id); GNUNET_free_non_null (peer->ss_instances); if (NULL != peer->ports) { for (cnt = 0; cnt < peer->nports; cnt++) GNUNET_TESTING_release_port (peer->system, peer->ports[cnt]); GNUNET_free (peer->ports); } GNUNET_free (peer); } /** * Start a single peer and run a test using the testing library. * Starts a peer using the given configuration and then invokes the * given callback. This function ALSO initializes the scheduler loop * and should thus be called directly from "main". The testcase * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'. * * @param testdir only the directory name without any path. This is used for * all service homes; the directory will be created in a temporary * location depending on the underlying OS * @param cfgfilename name of the configuration file to use; * use NULL to only run with defaults * @param tm main function of the testcase * @param tm_cls closure for 'tm' * @return 0 on success, 1 on error */ int GNUNET_TESTING_peer_run (const char *testdir, const char *cfgfilename, GNUNET_TESTING_TestMain tm, void *tm_cls) { return GNUNET_TESTING_service_run (testdir, "arm", cfgfilename, tm, tm_cls); } /** * Structure for holding service data */ struct ServiceContext { /** * The configuration of the peer in which the service is run */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Callback to signal service startup */ GNUNET_TESTING_TestMain tm; /** * The peer in which the service is run. */ struct GNUNET_TESTING_Peer *peer; /** * Closure for the above callback */ void *tm_cls; }; /** * Callback to be called when SCHEDULER has been started * * @param cls the ServiceContext * @param tc the TaskContext */ static void service_run_main (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceContext *sc = cls; sc->tm (sc->tm_cls, sc->cfg, sc->peer); } /** * Start a single service (no ARM, except of course if the given * service name is 'arm') and run a test using the testing library. * Starts a service using the given configuration and then invokes the * given callback. This function ALSO initializes the scheduler loop * and should thus be called directly from "main". The testcase * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'. * * This function is useful if the testcase is for a single service * and if that service doesn't itself depend on other services. * * @param testdir only the directory name without any path. This is used for * all service homes; the directory will be created in a temporary * location depending on the underlying OS * @param service_name name of the service to run * @param cfgfilename name of the configuration file to use; * use NULL to only run with defaults * @param tm main function of the testcase * @param tm_cls closure for 'tm' * @return 0 on success, 1 on error */ int GNUNET_TESTING_service_run (const char *testdir, const char *service_name, const char *cfgfilename, GNUNET_TESTING_TestMain tm, void *tm_cls) { struct ServiceContext sc; struct GNUNET_TESTING_System *system; struct GNUNET_TESTING_Peer *peer; struct GNUNET_CONFIGURATION_Handle *cfg; char *binary; char *libexec_binary; GNUNET_log_setup (testdir, "WARNING", NULL); system = GNUNET_TESTING_system_create (testdir, "127.0.0.1", NULL, NULL); if (NULL == system) return 1; cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfgfilename)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to load configuration from %s\n"), cfgfilename); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_TESTING_system_destroy (system, GNUNET_YES); return 1; } peer = GNUNET_TESTING_peer_configure (system, cfg, 0, NULL, NULL); if (NULL == peer) { GNUNET_CONFIGURATION_destroy (cfg); hostkeys_unload (system); GNUNET_TESTING_system_destroy (system, GNUNET_YES); return 1; } GNUNET_free (peer->main_binary); GNUNET_free (peer->args); GNUNET_asprintf (&binary, "gnunet-service-%s", service_name); libexec_binary = GNUNET_OS_get_libexec_binary_path (binary); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, service_name, "PREFIX", &peer->main_binary)) { /* No prefix */ GNUNET_asprintf(&peer->main_binary, "%s", libexec_binary); peer->args = strdup (""); } else peer->args = strdup (libexec_binary); GNUNET_free (libexec_binary); GNUNET_free (binary); if (GNUNET_OK != GNUNET_TESTING_peer_start (peer)) { GNUNET_TESTING_peer_destroy (peer); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_TESTING_system_destroy (system, GNUNET_YES); return 1; } sc.cfg = cfg; sc.tm = tm; sc.tm_cls = tm_cls; sc.peer = peer; GNUNET_SCHEDULER_run (&service_run_main, &sc); /* Scheduler loop */ if ((NULL != peer->main_process) && (GNUNET_OK != GNUNET_TESTING_peer_stop (peer))) { GNUNET_TESTING_peer_destroy (peer); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_TESTING_system_destroy (system, GNUNET_YES); return 1; } GNUNET_TESTING_peer_destroy (peer); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_TESTING_system_destroy (system, GNUNET_YES); return 0; } /** * Sometimes we use the binary name to determine which specific * test to run. In those cases, the string after the last "_" * in 'argv[0]' specifies a string that determines the configuration * file or plugin to use. * * This function returns the respective substring, taking care * of issues such as binaries ending in '.exe' on W32. * * @param argv0 the name of the binary * @return string between the last '_' and the '.exe' (or the end of the string), * NULL if argv0 has no '_' */ char * GNUNET_TESTING_get_testname_from_underscore (const char *argv0) { size_t slen = strlen (argv0) + 1; char sbuf[slen]; char *ret; char *dot; memcpy (sbuf, argv0, slen); ret = strrchr (sbuf, '_'); if (NULL == ret) return NULL; ret++; /* skip underscore */ dot = strchr (ret, '.'); if (NULL != dot) *dot = '\0'; return GNUNET_strdup (ret); } /* end of testing.c */ gnunet-0.10.1/src/testing/test_testing_portreservation.c0000644000175000017500000000617612225777501020506 00000000000000/* This file is part of GNUnet (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testing/test_testing_new_portreservation.c * @brief test case for testing port reservation routines from the new testing * library API * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * The status of the test */ int status; /** * Main point of test execution */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_TESTING_System *system; uint16_t new_port1; uint16_t new_port2; uint16_t old_port1; system = GNUNET_TESTING_system_create ("/tmp/gnunet-testing-new", "localhost", NULL, NULL); GNUNET_assert (NULL != system); new_port1 = GNUNET_TESTING_reserve_port (system); LOG (GNUNET_ERROR_TYPE_DEBUG, "Reserved TCP port %u\n", new_port1); if (0 == new_port1) goto end; new_port2 = GNUNET_TESTING_reserve_port (system); LOG (GNUNET_ERROR_TYPE_DEBUG, "Reserved TCP port %u\n", new_port2); if (0 == new_port2) goto end; GNUNET_assert (new_port1 != new_port2); GNUNET_TESTING_release_port (system, new_port1); old_port1 = new_port1; new_port1 = 0; new_port1 = GNUNET_TESTING_reserve_port (system); LOG (GNUNET_ERROR_TYPE_DEBUG, "Reserved TCP port %u\n", new_port1); GNUNET_assert (0 != new_port1); GNUNET_assert (old_port1 == new_port1); GNUNET_TESTING_release_port (system, new_port1); GNUNET_TESTING_release_port (system, new_port2); status = GNUNET_OK; end: GNUNET_TESTING_system_destroy (system, GNUNET_YES); } int main (int argc, char *argv[]) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; status = GNUNET_SYSERR; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test_testing_new_portreservation", "test case for testing port reservation routines" " from the new testing library API", options, &run, NULL)) return 1; return (GNUNET_OK == status) ? 0 : 1; } /* end of test_testing_portreservation.c */ gnunet-0.10.1/src/testing/test_testing_peerstartup.c0000644000175000017500000000724212255010512017572 00000000000000/* This file is part of GNUnet (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testing/test_testing_new_peerstartup.c * @brief test case for testing peer startup and shutdown using new testing * library * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * The status of the test */ int status; /** * The testing context */ struct TestingContext { /** * The testing system */ struct GNUNET_TESTING_System *system; /** * The peer which has been started by the testing system */ struct GNUNET_TESTING_Peer *peer; /** * The running configuration of the peer */ struct GNUNET_CONFIGURATION_Handle *cfg; }; /** * Task for shutdown * * @param cls the testing context * @param tc the tast context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestingContext *test_ctx = cls; GNUNET_assert (NULL != test_ctx); if (NULL != test_ctx->peer) { (void) GNUNET_TESTING_peer_stop (test_ctx->peer); GNUNET_TESTING_peer_destroy (test_ctx->peer); } if (NULL != test_ctx->cfg) GNUNET_CONFIGURATION_destroy (test_ctx->cfg); if (NULL != test_ctx->system) GNUNET_TESTING_system_destroy (test_ctx->system, GNUNET_YES); GNUNET_free (test_ctx); } /** * Main point of test execution */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TestingContext *test_ctx; char *emsg; struct GNUNET_PeerIdentity id; test_ctx = GNUNET_new (struct TestingContext); test_ctx->system = GNUNET_TESTING_system_create ("test-gnunet-testing", "127.0.0.1", NULL, NULL); emsg = NULL; if (NULL == test_ctx->system) goto end; test_ctx->cfg = GNUNET_CONFIGURATION_dup (cfg); test_ctx->peer = GNUNET_TESTING_peer_configure (test_ctx->system, test_ctx->cfg, 0, &id, &emsg); if (NULL == test_ctx->peer) { if (NULL != emsg) printf ("Test failed upon error: %s", emsg); goto end; } if (GNUNET_OK != GNUNET_TESTING_peer_start (test_ctx->peer)) goto end; status = GNUNET_OK; end: GNUNET_SCHEDULER_add_now (&do_shutdown, test_ctx); GNUNET_free_non_null (emsg); } int main (int argc, char *argv[]) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; status = GNUNET_SYSERR; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test_testing_peerstartup", "test case for peerstartup using new testing library", options, &run, NULL)) return 1; return (GNUNET_OK == status) ? 0 : 1; } /* end of test_testing_peerstartup.c */ gnunet-0.10.1/src/testing/Makefile.in0000644000175000017500000013556612320752064014344 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-testing$(EXEEXT) noinst_PROGRAMS = list-keys$(EXEEXT) check_PROGRAMS = test_testing_portreservation$(EXEEXT) \ test_testing_servicestartup$(EXEEXT) \ test_testing_peerstartup$(EXEEXT) \ test_testing_peerstartup2$(EXEEXT) \ test_testing_sharedservices$(EXEEXT) @ENABLE_TEST_RUN_TRUE@TESTS = test_testing_portreservation$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testing_peerstartup$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testing_peerstartup2$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testing_servicestartup$(EXEEXT) subdir = src/testing DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgcfg_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunettesting_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/arm/libgnunetarm.la $(am__DEPENDENCIES_1) am_libgnunettesting_la_OBJECTS = testing.lo libgnunettesting_la_OBJECTS = $(am_libgnunettesting_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunettesting_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunettesting_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_testing_OBJECTS = gnunet-testing.$(OBJEXT) gnunet_testing_OBJECTS = $(am_gnunet_testing_OBJECTS) am_list_keys_OBJECTS = list-keys.$(OBJEXT) list_keys_OBJECTS = $(am_list_keys_OBJECTS) list_keys_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_testing_peerstartup_OBJECTS = \ test_testing_peerstartup.$(OBJEXT) test_testing_peerstartup_OBJECTS = \ $(am_test_testing_peerstartup_OBJECTS) test_testing_peerstartup_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_testing_peerstartup2_OBJECTS = \ test_testing_peerstartup2.$(OBJEXT) test_testing_peerstartup2_OBJECTS = \ $(am_test_testing_peerstartup2_OBJECTS) test_testing_peerstartup2_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_testing_portreservation_OBJECTS = \ test_testing_portreservation.$(OBJEXT) test_testing_portreservation_OBJECTS = \ $(am_test_testing_portreservation_OBJECTS) test_testing_portreservation_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_testing_servicestartup_OBJECTS = \ test_testing_servicestartup.$(OBJEXT) test_testing_servicestartup_OBJECTS = \ $(am_test_testing_servicestartup_OBJECTS) test_testing_servicestartup_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_testing_sharedservices_OBJECTS = \ test_testing_sharedservices.$(OBJEXT) test_testing_sharedservices_OBJECTS = \ $(am_test_testing_sharedservices_OBJECTS) test_testing_sharedservices_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunettesting_la_SOURCES) $(gnunet_testing_SOURCES) \ $(list_keys_SOURCES) $(test_testing_peerstartup_SOURCES) \ $(test_testing_peerstartup2_SOURCES) \ $(test_testing_portreservation_SOURCES) \ $(test_testing_servicestartup_SOURCES) \ $(test_testing_sharedservices_SOURCES) DIST_SOURCES = $(libgnunettesting_la_SOURCES) \ $(gnunet_testing_SOURCES) $(list_keys_SOURCES) \ $(test_testing_peerstartup_SOURCES) \ $(test_testing_peerstartup2_SOURCES) \ $(test_testing_portreservation_SOURCES) \ $(test_testing_servicestartup_SOURCES) \ $(test_testing_sharedservices_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov pkgcfgdir = $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ testing.conf lib_LTLIBRARIES = \ libgnunettesting.la libgnunettesting_la_SOURCES = \ testing.c libgnunettesting_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/arm/libgnunetarm.la \ $(LTLIBINTL) libgnunettesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 2:0:1 gnunet_testing_SOURCES = \ gnunet-testing.c gnunet_testing_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_testing_DEPENDENCIES = \ libgnunettesting.la list_keys_SOURCES = \ list-keys.c list_keys_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; test_testing_portreservation_SOURCES = \ test_testing_portreservation.c test_testing_portreservation_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_peerstartup_SOURCES = \ test_testing_peerstartup.c test_testing_peerstartup_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_peerstartup2_SOURCES = \ test_testing_peerstartup2.c test_testing_peerstartup2_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_servicestartup_SOURCES = \ test_testing_servicestartup.c test_testing_servicestartup_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_sharedservices_SOURCES = \ test_testing_sharedservices.c test_testing_sharedservices_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_testing_defaults.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/testing/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/testing/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunettesting.la: $(libgnunettesting_la_OBJECTS) $(libgnunettesting_la_DEPENDENCIES) $(EXTRA_libgnunettesting_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunettesting_la_LINK) -rpath $(libdir) $(libgnunettesting_la_OBJECTS) $(libgnunettesting_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-testing$(EXEEXT): $(gnunet_testing_OBJECTS) $(gnunet_testing_DEPENDENCIES) $(EXTRA_gnunet_testing_DEPENDENCIES) @rm -f gnunet-testing$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_testing_OBJECTS) $(gnunet_testing_LDADD) $(LIBS) list-keys$(EXEEXT): $(list_keys_OBJECTS) $(list_keys_DEPENDENCIES) $(EXTRA_list_keys_DEPENDENCIES) @rm -f list-keys$(EXEEXT) $(AM_V_CCLD)$(LINK) $(list_keys_OBJECTS) $(list_keys_LDADD) $(LIBS) test_testing_peerstartup$(EXEEXT): $(test_testing_peerstartup_OBJECTS) $(test_testing_peerstartup_DEPENDENCIES) $(EXTRA_test_testing_peerstartup_DEPENDENCIES) @rm -f test_testing_peerstartup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testing_peerstartup_OBJECTS) $(test_testing_peerstartup_LDADD) $(LIBS) test_testing_peerstartup2$(EXEEXT): $(test_testing_peerstartup2_OBJECTS) $(test_testing_peerstartup2_DEPENDENCIES) $(EXTRA_test_testing_peerstartup2_DEPENDENCIES) @rm -f test_testing_peerstartup2$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testing_peerstartup2_OBJECTS) $(test_testing_peerstartup2_LDADD) $(LIBS) test_testing_portreservation$(EXEEXT): $(test_testing_portreservation_OBJECTS) $(test_testing_portreservation_DEPENDENCIES) $(EXTRA_test_testing_portreservation_DEPENDENCIES) @rm -f test_testing_portreservation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testing_portreservation_OBJECTS) $(test_testing_portreservation_LDADD) $(LIBS) test_testing_servicestartup$(EXEEXT): $(test_testing_servicestartup_OBJECTS) $(test_testing_servicestartup_DEPENDENCIES) $(EXTRA_test_testing_servicestartup_DEPENDENCIES) @rm -f test_testing_servicestartup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testing_servicestartup_OBJECTS) $(test_testing_servicestartup_LDADD) $(LIBS) test_testing_sharedservices$(EXEEXT): $(test_testing_sharedservices_OBJECTS) $(test_testing_sharedservices_DEPENDENCIES) $(EXTRA_test_testing_sharedservices_DEPENDENCIES) @rm -f test_testing_sharedservices$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testing_sharedservices_OBJECTS) $(test_testing_sharedservices_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-testing.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list-keys.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testing_peerstartup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testing_peerstartup2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testing_portreservation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testing_servicestartup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testing_sharedservices.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testing.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_testing_portreservation.log: test_testing_portreservation$(EXEEXT) @p='test_testing_portreservation$(EXEEXT)'; \ b='test_testing_portreservation'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testing_peerstartup.log: test_testing_peerstartup$(EXEEXT) @p='test_testing_peerstartup$(EXEEXT)'; \ b='test_testing_peerstartup'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testing_peerstartup2.log: test_testing_peerstartup2$(EXEEXT) @p='test_testing_peerstartup2$(EXEEXT)'; \ b='test_testing_peerstartup2'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testing_servicestartup.log: test_testing_servicestartup$(EXEEXT) @p='test_testing_servicestartup$(EXEEXT)'; \ b='test_testing_servicestartup'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_pkgcfgDATA \ uninstall-libLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am \ install-dist_pkgcfgDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-dist_pkgcfgDATA uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/testing/testing.conf0000644000175000017500000000045112225230043014573 00000000000000[TESTING] # How long before failing a connection? CONNECT_TIMEOUT = 30 s # How many connect attempts should we make? CONNECT_ATTEMPTS = 3 # How many connections can happen simultaneously? MAX_OUTSTANDING_CONNECTIONS = 50 # Should we clean up the files on peer group shutdown? DELETE_FILES = YES gnunet-0.10.1/src/testing/gnunet-testing.c0000644000175000017500000002606512225777501015416 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testing/gnunet-testing.c * @brief tool to use testing functionality from cmd line * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #define LOG(kind,...) \ GNUNET_log_from (kind, "gnunet-testing", __VA_ARGS__) /** * Final status code. */ static int ret; /** * Filename of the hostkey file we should write, * null if we should not write a hostkey file. */ static char *create_hostkey; /** * Non-zero if we should create config files. */ static int create_cfg; /** * Number of config files to create. */ static unsigned int create_no; /** * Filename of the config template to be written. */ static char *create_cfg_template; /** * Service we are supposed to run. */ static char *run_service_name; /** * File handle to STDIN, for reading restart/quit commands. */ static struct GNUNET_DISK_FileHandle *fh; /** * Temporary filename, used with '-r' to write the configuration to. */ static char *tmpfilename; /** * Task identifier of the task that waits for stdin. */ static GNUNET_SCHEDULER_TaskIdentifier tid; /** * Peer started for '-r'. */ static struct GNUNET_TESTING_Peer *my_peer; static int create_unique_cfgs (const char * template, const unsigned int no) { struct GNUNET_TESTING_System *system; int fail; unsigned int cur; char *cur_file; struct GNUNET_CONFIGURATION_Handle *cfg_new; struct GNUNET_CONFIGURATION_Handle *cfg_tmpl; if (GNUNET_NO == GNUNET_DISK_file_test(template)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Configuration template `%s': file not found\n", create_cfg_template); return 1; } cfg_tmpl = GNUNET_CONFIGURATION_create(); /* load template */ if ((create_cfg_template != NULL) && (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl, create_cfg_template))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template); GNUNET_CONFIGURATION_destroy (cfg_tmpl); return 1; } /* load defaults */ if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_tmpl, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template); GNUNET_CONFIGURATION_destroy (cfg_tmpl); return 1; } fail = GNUNET_NO; system = GNUNET_TESTING_system_create ("testing", NULL /* controller */, NULL, NULL); for (cur = 0; cur < no; cur++) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating configuration no. %u \n", cur); if (create_cfg_template != NULL) GNUNET_asprintf (&cur_file,"%04u-%s",cur, create_cfg_template); else GNUNET_asprintf (&cur_file,"%04u%s",cur, ".conf"); cfg_new = GNUNET_CONFIGURATION_dup (cfg_tmpl); if (GNUNET_OK != GNUNET_TESTING_configuration_create (system, cfg_new)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create another configuration\n"); GNUNET_CONFIGURATION_destroy (cfg_new); fail = GNUNET_YES; break; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing configuration no. %u to file `%s' \n", cur, cur_file); if (GNUNET_OK != GNUNET_CONFIGURATION_write(cfg_new, cur_file)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write configuration no. %u \n", cur); fail = GNUNET_YES; } GNUNET_CONFIGURATION_destroy (cfg_new); GNUNET_free (cur_file); if (GNUNET_YES == fail) break; } GNUNET_CONFIGURATION_destroy(cfg_tmpl); GNUNET_TESTING_system_destroy (system, GNUNET_NO); if (GNUNET_YES == fail) return 1; return 0; } static int create_hostkeys (const unsigned int no) { struct GNUNET_TESTING_System *system; struct GNUNET_PeerIdentity id; struct GNUNET_DISK_FileHandle *fd; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; system = GNUNET_TESTING_system_create ("testing", NULL, NULL, NULL); pk = GNUNET_TESTING_hostkey_get (system, create_no, &id); if (NULL == pk) { fprintf (stderr, _("Could not extract hostkey %u (offset too large?)\n"), create_no); GNUNET_TESTING_system_destroy (system, GNUNET_YES); return 1; } (void) GNUNET_DISK_directory_create_for_file (create_hostkey); fd = GNUNET_DISK_file_open (create_hostkey, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); GNUNET_assert (fd != NULL); ret = GNUNET_DISK_file_write (fd, pk, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd)); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Wrote hostkey to file: `%s'\n", create_hostkey); GNUNET_free (pk); GNUNET_TESTING_system_destroy (system, GNUNET_YES); return 0; } /** * Cleanup called by signal handlers and when stdin is closed. * Removes the temporary file. * * @param cls unused * @param tc scheduler context */ static void cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != tmpfilename) { if (0 != UNLINK (tmpfilename)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", tmpfilename); } if (GNUNET_SCHEDULER_NO_TASK != tid) { GNUNET_SCHEDULER_cancel (tid); tid = GNUNET_SCHEDULER_NO_TASK; } if (NULL != fh) { GNUNET_DISK_file_close (fh); fh = NULL; } } /** * Called whenever we can read stdin non-blocking * * @param cls unused * @param tc scheduler context */ static void stdin_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int c; tid = GNUNET_SCHEDULER_NO_TASK; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; GNUNET_assert (0 != (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason)); c = getchar (); switch (c) { case EOF: case 'q': GNUNET_SCHEDULER_shutdown (); return; case 'r': if (GNUNET_OK != GNUNET_TESTING_peer_stop (my_peer)) LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to stop the peer\n"); if (GNUNET_OK != GNUNET_TESTING_peer_start (my_peer)) LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to start the peer\n"); printf ("restarted\n"); fflush (stdout); break; case '\n': case '\r': /* ignore whitespace */ break; default: fprintf (stderr, _("Unknown command, use 'q' to quit or 'r' to restart peer\n")); break; } tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, fh, &stdin_cb, NULL); } /** * Main function called by the testing library. * Executed inside a running scheduler. * * @param cls unused * @param cfg configuration of the peer that was started * @param peer handle to the peer */ static void testing_main (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { my_peer = peer; if (NULL == (tmpfilename = GNUNET_DISK_mktemp ("gnunet-testing"))) { GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_SYSERR == GNUNET_CONFIGURATION_write ((struct GNUNET_CONFIGURATION_Handle *) cfg, tmpfilename)) { GNUNET_break (0); return; } printf("ok\n%s\n", tmpfilename); fflush(stdout); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, NULL); fh = GNUNET_DISK_get_handle_from_native (stdin); tid = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, fh, &stdin_cb, NULL); } /** * Main function that will be running without scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run_no_scheduler (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { if (NULL != run_service_name) { ret = GNUNET_TESTING_service_run ("gnunet_service_test", run_service_name, cfgfile, &testing_main, NULL); return; } if (GNUNET_YES == create_cfg) { if (create_no > 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating %u configuration files based on template `%s'\n", create_no, create_cfg_template); ret = create_unique_cfgs (create_cfg_template, create_no); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n"); ret = 1; } } if (NULL != create_hostkey) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Extracting hostkey %u\n", create_no); ret = create_hostkeys (create_no); } GNUNET_free_non_null (create_cfg_template); } /** * The main function. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'C', "cfg", NULL, gettext_noop ("create unique configuration files"), GNUNET_NO, &GNUNET_GETOPT_set_one, &create_cfg}, {'k', "key", "FILENAME", gettext_noop ("extract hostkey file from pre-computed hostkey list"), GNUNET_YES, &GNUNET_GETOPT_set_string, &create_hostkey}, {'n', "number", "NUMBER", gettext_noop ("number of unique configuration files to create, or number of the hostkey to extract"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &create_no}, {'t', "template", "FILENAME", gettext_noop ("configuration template"), GNUNET_YES, &GNUNET_GETOPT_set_string, &create_cfg_template}, {'r', "run", "SERVICE", gettext_noop ("run the given service, wait on stdin for 'r' (restart) or 'q' (quit)"), GNUNET_YES, &GNUNET_GETOPT_set_string, &run_service_name}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; /* Run without scheduler, because we may want to call * GNUNET_TESTING_service_run, which starts the scheduler on its own. * Furthermore, the other functionality currently does not require the scheduler, too, * but beware when extending gnunet-testing. */ ret = (GNUNET_OK == GNUNET_PROGRAM_run2 (argc, argv, "gnunet-testing", gettext_noop ("Command line tool to access the testing library"), options, &run_no_scheduler, NULL, GNUNET_YES)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-testing.c */ gnunet-0.10.1/src/testing/Makefile.am0000644000175000017500000000466112320751520014316 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif pkgcfgdir= $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ testing.conf lib_LTLIBRARIES = \ libgnunettesting.la libgnunettesting_la_SOURCES = \ testing.c libgnunettesting_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/arm/libgnunetarm.la \ $(LTLIBINTL) libgnunettesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 2:0:1 bin_PROGRAMS = \ gnunet-testing noinst_PROGRAMS = \ list-keys gnunet_testing_SOURCES = \ gnunet-testing.c gnunet_testing_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_testing_DEPENDENCIES = \ libgnunettesting.la list_keys_SOURCES = \ list-keys.c list_keys_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) check_PROGRAMS = \ test_testing_portreservation \ test_testing_servicestartup \ test_testing_peerstartup \ test_testing_peerstartup2 \ test_testing_sharedservices if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ test_testing_portreservation \ test_testing_peerstartup \ test_testing_peerstartup2 \ test_testing_servicestartup endif test_testing_portreservation_SOURCES = \ test_testing_portreservation.c test_testing_portreservation_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_peerstartup_SOURCES = \ test_testing_peerstartup.c test_testing_peerstartup_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_peerstartup2_SOURCES = \ test_testing_peerstartup2.c test_testing_peerstartup2_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_servicestartup_SOURCES = \ test_testing_servicestartup.c test_testing_servicestartup_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_testing_sharedservices_SOURCES = \ test_testing_sharedservices.c test_testing_sharedservices_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_testing_defaults.conf gnunet-0.10.1/src/testing/test_testing_defaults.conf0000644000175000017500000000144012225230043017520 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-testing/ [resolver] PORT = 2564 [transport] PORT = 2565 PLUGINS = tcp [transport-tcp] TESTING_IGNORE_KEYS = SOMETHING;KEY1;ACCEPT_FROM; [arm] PORT = 2566 DEFAULTSERVICES = [statistics] PORT = 2567 [transport-tcp] PORT = 2568 BINDTO = 127.0.0.1 [peerinfo] PORT = 2569 [core] PORT = 2570 [dht] AUTOSTART = NO [nat] DISABLEV6 = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 USE_LOCALADDR = NO [dns] AUTOSTART = NO [nse] AUTOSTART = NO [mesh] AUTOSTART = NO [datastore] AUTOSTART = NO [fs] AUTOSTART = NO [dv] AUTOSTART = NO [chat] AUTOSTART = NO [vpn] AUTOSTART = NO [gns] AUTOSTART = NO [namestore] AUTOSTART = NO [lockmanager] AUTOSTART = NO [consensus] AUTOSTART = NO gnunet-0.10.1/src/testing/test_testing_sharedservices.c0000644000175000017500000001060212255010512020220 00000000000000/* This file is part of GNUnet (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testing/test_testing_sharedservices.c * @brief test case for testing service sharing among peers started by testing * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) #define NUM_PEERS 4 /** * The status of the test */ int status; /** * The testing context */ struct TestingContext { /** * The testing system */ struct GNUNET_TESTING_System *system; /** * The peer which has been started by the testing system */ struct GNUNET_TESTING_Peer *peers[NUM_PEERS]; /** * The running configuration of the peer */ struct GNUNET_CONFIGURATION_Handle *cfg; }; /** * Task for shutdown * * @param cls the testing context * @param tc the tast context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestingContext *test_ctx = cls; struct GNUNET_TESTING_Peer *peer; unsigned int cnt; GNUNET_assert (NULL != test_ctx); for (cnt = 0; cnt < NUM_PEERS; cnt++) { peer = test_ctx->peers[cnt]; if (NULL == peer) continue; (void) GNUNET_TESTING_peer_stop (peer); GNUNET_TESTING_peer_destroy (peer); } if (NULL != test_ctx->cfg) GNUNET_CONFIGURATION_destroy (test_ctx->cfg); if (NULL != test_ctx->system) GNUNET_TESTING_system_destroy (test_ctx->system, GNUNET_YES); GNUNET_free (test_ctx); } /** * Main point of test execution */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TestingContext *test_ctx; char *emsg; struct GNUNET_PeerIdentity id; struct GNUNET_TESTING_SharedService ss[] = { {"peerinfo", cfg, 2}, {NULL, NULL, 0} }; struct GNUNET_TESTING_Peer *peer; unsigned int cnt; test_ctx = GNUNET_new (struct TestingContext); test_ctx->system = GNUNET_TESTING_system_create ("test-gnunet-testing", "127.0.0.1", NULL, ss); emsg = NULL; if (NULL == test_ctx->system) goto end; test_ctx->cfg = GNUNET_CONFIGURATION_dup (cfg); for (cnt = 0; cnt < NUM_PEERS; cnt++) { peer = GNUNET_TESTING_peer_configure (test_ctx->system, test_ctx->cfg, 0, &id, &emsg); if (NULL == peer) { if (NULL != emsg) printf ("Test failed upon error: %s", emsg); goto end; } if (GNUNET_OK != GNUNET_TESTING_peer_start (peer)) { GNUNET_TESTING_peer_destroy (peer); goto end; } test_ctx->peers[cnt] = peer; } status = GNUNET_OK; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, test_ctx); return; end: GNUNET_SCHEDULER_add_now (&do_shutdown, test_ctx); GNUNET_free_non_null (emsg); } int main (int argc, char *argv[]) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; char *const argv2[] = { "test_testing_sharedservices", "-c", "test_testing_sharedservices.conf", NULL }; status = GNUNET_SYSERR; if (GNUNET_OK != GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testing_sharedservices", "test case for testing service sharing among peers started by testing", options, &run, NULL)) return 1; return (GNUNET_OK == status) ? 0 : 3; } /* end of test_testing_sharedservices.c */ gnunet-0.10.1/src/peerinfo/0000755000175000017500000000000012320755623012475 500000000000000gnunet-0.10.1/src/peerinfo/gnunet-service-peerinfo.c0000644000175000017500000011076612320466615017337 00000000000000/* This file is part of GNUnet. (C) 2001-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/gnunet-service-peerinfo.c * @brief maintains list of known peers * * Code to maintain the list of currently known hosts (in memory * structure of data/hosts/). * * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "peerinfo.h" /** * How often do we scan the HOST_DIR for new entries? */ #define DATA_HOST_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) /** * How often do we discard old entries in data/hosts/? */ #define DATA_HOST_CLEAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60) /** * In-memory cache of known hosts. */ struct HostEntry { /** * Identity of the peer. */ struct GNUNET_PeerIdentity identity; /** * Hello for the peer (can be NULL) */ struct GNUNET_HELLO_Message *hello; /** * Friend only hello for the peer (can be NULL) */ struct GNUNET_HELLO_Message *friend_only_hello; }; /** * Transmit context for GET requests */ struct TransmitContext { /** * Server transmit context */ struct GNUNET_SERVER_TransmitContext *tc; /** * Include friend only HELLOs #GNUNET_YES or #GNUNET_NO */ int friend_only; }; /** * Result of reading a file */ struct ReadHostFileContext { /** * Hello for the peer (can be NULL) */ struct GNUNET_HELLO_Message *hello; /** * Friend only hello for the peer (can be NULL) */ struct GNUNET_HELLO_Message *friend_only_hello; }; /** * Client notification context */ struct NotificationContext { /** * Next in DLL */ struct NotificationContext *prev; /** * Previous in DLL */ struct NotificationContext *next; /** * Server client */ struct GNUNET_SERVER_Client *client; /** * Interested in friend only HELLO? */ int include_friend_only; }; /** * The in-memory list of known hosts, mapping of * host IDs to 'struct HostEntry*' values. */ static struct GNUNET_CONTAINER_MultiPeerMap *hostmap; /** * Clients to immediately notify about all changes. */ static struct GNUNET_SERVER_NotificationContext *notify_list; /** * Directory where the hellos are stored in (peerinfo/) */ static char *networkIdDirectory; /** * Handle for reporting statistics. */ static struct GNUNET_STATISTICS_Handle *stats; /** * DLL of notification contexts: head */ static struct NotificationContext *nc_head; /** * DLL of notification contexts: tail */ static struct NotificationContext *nc_tail; /** * Notify all clients in the notify list about the * given host entry changing. * * @param he entry of the host for which we generate a notification * @param include_friend_only create public of friend-only message * @return generated notification message */ static struct InfoMessage * make_info_message (const struct HostEntry *he, int include_friend_only) { struct InfoMessage *im; struct GNUNET_HELLO_Message *src; size_t hs; if (GNUNET_YES == include_friend_only) src = he->friend_only_hello; else src = he->hello; hs = (NULL == src) ? 0 : GNUNET_HELLO_size (src); im = GNUNET_malloc (sizeof (struct InfoMessage) + hs); im->header.size = htons (hs + sizeof (struct InfoMessage)); im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO); im->peer = he->identity; if (NULL != src) memcpy (&im[1], src, hs); return im; } /** * Address iterator that causes expired entries to be discarded. * * @param cls pointer to the current time * @param address the address * @param expiration expiration time for the address * @return #GNUNET_NO if expiration smaller than the current time */ static int discard_expired (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { const struct GNUNET_TIME_Absolute *now = cls; if (now->abs_value_us > expiration.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Removing expired address of transport `%s'\n"), address->transport_name); return GNUNET_NO; } return GNUNET_OK; } /** * Address iterator that counts the remaining addresses. * * @param cls pointer to the counter * @param address the address * @param expiration expiration time for the address * @return #GNUNET_OK (always) */ static int count_addresses (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { unsigned int *cnt = cls; (*cnt)++; return GNUNET_OK; } /** * Get the filename under which we would store the GNUNET_HELLO_Message * for the given host and protocol. * * @param id peer for which we need the filename for the HELLO * @return filename of the form DIRECTORY/HOSTID */ static char * get_host_filename (const struct GNUNET_PeerIdentity *id) { char *fn; if (NULL == networkIdDirectory) return NULL; GNUNET_asprintf (&fn, "%s%s%s", networkIdDirectory, DIR_SEPARATOR_STR, GNUNET_i2s_full (id)); return fn; } /** * Broadcast information about the given entry to all * clients that care. * * @param entry entry to broadcast about */ static void notify_all (struct HostEntry *entry) { struct InfoMessage *msg_pub; struct InfoMessage *msg_friend; struct NotificationContext *cur; msg_pub = make_info_message (entry, GNUNET_NO); msg_friend = make_info_message (entry, GNUNET_YES); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying all clients about peer `%s'\n", GNUNET_i2s(&entry->identity)); for (cur = nc_head; NULL != cur; cur = cur->next) { if (GNUNET_NO == cur->include_friend_only) { GNUNET_SERVER_notification_context_unicast (notify_list, cur->client, &msg_pub->header, GNUNET_NO); } if (GNUNET_YES == cur->include_friend_only) { GNUNET_SERVER_notification_context_unicast (notify_list, cur->client, &msg_friend->header, GNUNET_NO); } } GNUNET_free (msg_pub); GNUNET_free (msg_friend); } /** * Bind a host address (hello) to a hostId. * * @param peer the peer for which this is a hello * @param hello the verified (!) hello message */ static void update_hello (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello); /** * Try to read the HELLOs in the given filename and discard expired * addresses. Removes the file if one the HELLO is malformed. If all * addresses are expired, the HELLO is also removed (but the HELLO * with the public key is still returned if it was found and valid). * The file can contain multiple HELLO messages. * * @param fn name of the file * @param unlink_garbage if #GNUNET_YES, try to remove useless files * @param r ReadHostFileContext to store the resutl */ static void read_host_file (const char *fn, int unlink_garbage, struct ReadHostFileContext *r) { char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; unsigned int size_total; struct GNUNET_TIME_Absolute now; unsigned int left; const struct GNUNET_HELLO_Message *hello; struct GNUNET_HELLO_Message *hello_clean; unsigned read_pos; int size_hello; r->friend_only_hello = NULL; r->hello = NULL; if (GNUNET_YES != GNUNET_DISK_file_test (fn)) return; size_total = GNUNET_DISK_fn_read (fn, buffer, sizeof (buffer)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %u bytes from `%s'\n", size_total, fn); if (size_total < sizeof (struct GNUNET_MessageHeader)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO in file `%s': %s\n"), fn, "Fail has invalid size"); if ( (GNUNET_YES == unlink_garbage) && (0 != UNLINK (fn)) && (ENOENT != errno) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); return; } read_pos = 0; while (read_pos < size_total) { hello = (const struct GNUNET_HELLO_Message *) &buffer[read_pos]; size_hello = GNUNET_HELLO_size (hello); if (0 == size_hello) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO in file `%s'\n"), fn); if ((GNUNET_YES == unlink_garbage) && (0 != UNLINK (fn)) && (ENOENT != errno) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); return; } now = GNUNET_TIME_absolute_get (); hello_clean = GNUNET_HELLO_iterate_addresses (hello, GNUNET_YES, &discard_expired, &now); if (NULL == hello_clean) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO in file `%s'\n"), fn); if ((GNUNET_YES == unlink_garbage) && (0 != UNLINK (fn)) && (ENOENT != errno) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); return; } left = 0; (void) GNUNET_HELLO_iterate_addresses (hello_clean, GNUNET_NO, &count_addresses, &left); if (0 == left) { GNUNET_free (hello_clean); break; } if (GNUNET_NO == GNUNET_HELLO_is_friend_only (hello_clean)) { if (NULL == r->hello) r->hello = hello_clean; else { GNUNET_break (0); GNUNET_free (r->hello); r->hello = hello_clean; } } else { if (NULL == r->friend_only_hello) r->friend_only_hello = hello_clean; else { GNUNET_break (0); GNUNET_free (r->friend_only_hello); r->friend_only_hello = hello_clean; } } read_pos += size_hello; } if (0 == left) { /* no addresses left, remove from disk */ if ( (GNUNET_YES == unlink_garbage) && (0 != UNLINK (fn)) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found `%s' and `%s' HELLO message in file\n", (NULL != r->hello) ? "public" : "NON-public", (NULL != r->friend_only_hello) ? "friend only" : "NO friend only"); } /** * Add a host to the list and notify clients about this event * * @param identity the identity of the host * @return the HostEntry */ static struct HostEntry * add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity) { struct HostEntry *entry; struct ReadHostFileContext r; char *fn; entry = GNUNET_CONTAINER_multipeermap_get (hostmap, identity); if (NULL == entry) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding new peer `%s'\n", GNUNET_i2s (identity)); GNUNET_STATISTICS_update (stats, gettext_noop ("# peers known"), 1, GNUNET_NO); entry = GNUNET_new (struct HostEntry); entry->identity = *identity; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (hostmap, &entry->identity, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); notify_all (entry); fn = get_host_filename (identity); if (NULL != fn) { read_host_file (fn, GNUNET_YES, &r); if (NULL != r.hello) update_hello (identity, r.hello); if (NULL != r.friend_only_hello) update_hello (identity, r.friend_only_hello); GNUNET_free_non_null (r.hello); GNUNET_free_non_null (r.friend_only_hello); GNUNET_free (fn); } } return entry; } /** * Remove a file that should not be there. LOG * success or failure. * * @param fullname name of the file to remove */ static void remove_garbage (const char *fullname) { if (0 == UNLINK (fullname)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, _ ("File `%s' in directory `%s' does not match naming convention. " "Removed.\n"), fullname, networkIdDirectory); else GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "unlink", fullname); } /** * Closure for 'hosts_directory_scan_callback'. */ struct DirScanContext { /** * #GNUNET_YES if we should remove files that are broken, * #GNUNET_NO if the directory we are iterating over should * be treated as read-only by us. */ int remove_files; /** * Counter for the number of (valid) entries found, incremented * by one for each match. */ unsigned int matched; }; /** * Function that is called on each HELLO file in a particular directory. * Try to parse the file and add the HELLO to our list. * * @param cls pointer to 'unsigned int' to increment for each file, or NULL * if the file is from a read-only, read-once resource directory * @param fullname name of the file to parse * @return #GNUNET_OK (continue iteration) */ static int hosts_directory_scan_callback (void *cls, const char *fullname) { struct DirScanContext *dsc = cls; struct GNUNET_PeerIdentity identity; struct ReadHostFileContext r; const char *filename; struct GNUNET_PeerIdentity id_public; struct GNUNET_PeerIdentity id_friend; struct GNUNET_PeerIdentity id; if (GNUNET_YES != GNUNET_DISK_file_test (fullname)) return GNUNET_OK; /* ignore non-files */ filename = strrchr (fullname, DIR_SEPARATOR); if ((NULL == filename) || (1 > strlen (filename))) filename = fullname; else filename ++; read_host_file (fullname, dsc->remove_files, &r); if ( (NULL == r.hello) && (NULL == r.friend_only_hello)) return GNUNET_OK; if (NULL != r.friend_only_hello) { if (GNUNET_OK != GNUNET_HELLO_get_id (r.friend_only_hello, &id_friend)) if (GNUNET_YES == dsc->remove_files) { remove_garbage (fullname); return GNUNET_OK; } id = id_friend; } if (NULL != r.hello) { if (GNUNET_OK != GNUNET_HELLO_get_id (r.hello, &id_public)) if (GNUNET_YES == dsc->remove_files) { remove_garbage (fullname); return GNUNET_OK; } id = id_public; } if ( (NULL != r.hello) && (NULL != r.friend_only_hello) && (0 != memcmp (&id_friend, &id_public, sizeof (id_friend))) ) { /* HELLOs are not for the same peer */ GNUNET_break (0); if (GNUNET_YES == dsc->remove_files) remove_garbage (fullname); return GNUNET_OK; } if (GNUNET_OK == GNUNET_CRYPTO_eddsa_public_key_from_string (filename, strlen (filename), &identity.public_key)) { if (0 != memcmp (&id, &identity, sizeof (id_friend))) { /* HELLOs are not for the same peer */ GNUNET_break (0); if (GNUNET_YES == dsc->remove_files) remove_garbage (fullname); return GNUNET_OK; } } /* ok, found something valid, remember HELLO */ add_host_to_known_hosts (&id); if (NULL != r.hello) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating peer `%s' public HELLO \n", GNUNET_i2s (&id)); update_hello (&id, r.hello); GNUNET_free (r.hello); } if (NULL != r.friend_only_hello) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating peer `%s' friend only HELLO \n", GNUNET_i2s (&id)); update_hello (&id, r.friend_only_hello); GNUNET_free (r.friend_only_hello); } dsc->matched++; return GNUNET_OK; } /** * Call this method periodically to scan data/hosts for new hosts. * * @param cls unused * @param tc scheduler context, aborted if reason is shutdown */ static void cron_scan_directory_data_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static unsigned int retries; struct DirScanContext dsc; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; if (GNUNET_SYSERR == GNUNET_DISK_directory_create (networkIdDirectory)) { GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ, GNUNET_SCHEDULER_PRIORITY_IDLE, &cron_scan_directory_data_hosts, NULL); return; } dsc.matched = 0; dsc.remove_files = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, _("Scanning directory `%s'\n"), networkIdDirectory); GNUNET_DISK_directory_scan (networkIdDirectory, &hosts_directory_scan_callback, &dsc); if ((0 == dsc.matched) && (0 == (++retries & 31))) GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, _("Still no peers found in `%s'!\n"), networkIdDirectory); GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ, GNUNET_SCHEDULER_PRIORITY_IDLE, &cron_scan_directory_data_hosts, NULL); } static struct GNUNET_HELLO_Message * update_friend_hello (const struct GNUNET_HELLO_Message *hello, const struct GNUNET_HELLO_Message *friend_hello) { struct GNUNET_HELLO_Message * res; struct GNUNET_HELLO_Message * tmp; struct GNUNET_CRYPTO_EddsaPublicKey pk; if (NULL != friend_hello) { res = GNUNET_HELLO_merge (hello, friend_hello); GNUNET_assert (GNUNET_YES == GNUNET_HELLO_is_friend_only (res)); return res; } if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &pk)) { GNUNET_break (0); return NULL; } tmp = GNUNET_HELLO_create (&pk, NULL, NULL, GNUNET_YES); res = GNUNET_HELLO_merge (hello, tmp); GNUNET_free (tmp); GNUNET_assert (GNUNET_YES == GNUNET_HELLO_is_friend_only (res)); return res; } /** * Bind a host address (hello) to a hostId. * * @param peer the peer for which this is a hello * @param hello the verified (!) hello message */ static void update_hello (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello) { char *fn; struct HostEntry *host; struct GNUNET_HELLO_Message *mrg; struct GNUNET_HELLO_Message **dest; struct GNUNET_TIME_Absolute delta; unsigned int cnt; unsigned int size; int friend_hello_type; int store_hello; int store_friend_hello; int pos; char *buffer; host = GNUNET_CONTAINER_multipeermap_get (hostmap, peer); GNUNET_assert (NULL != host); friend_hello_type = GNUNET_HELLO_is_friend_only (hello); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating %s HELLO for `%s'\n", (GNUNET_YES == friend_hello_type) ? "friend-only" : "public", GNUNET_i2s (peer)); dest = NULL; if (GNUNET_YES == friend_hello_type) { dest = &host->friend_only_hello; } else { dest = &host->hello; } if (NULL == (*dest)) { (*dest) = GNUNET_malloc (GNUNET_HELLO_size (hello)); memcpy ((*dest), hello, GNUNET_HELLO_size (hello)); } else { mrg = GNUNET_HELLO_merge ((*dest), hello); delta = GNUNET_HELLO_equals (mrg, (*dest), GNUNET_TIME_absolute_get ()); if (delta.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) { /* no differences, just ignore the update */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No change in %s HELLO for `%s'\n", (GNUNET_YES == friend_hello_type) ? "friend-only" : "public", GNUNET_i2s (peer)); GNUNET_free (mrg); return; } GNUNET_free ((*dest)); (*dest) = mrg; } if ((NULL != (host->hello)) && (GNUNET_NO == friend_hello_type)) { /* Update friend only hello */ mrg = update_friend_hello (host->hello, host->friend_only_hello); if (NULL != host->friend_only_hello) GNUNET_free (host->friend_only_hello); host->friend_only_hello = mrg; } if (NULL != host->hello) GNUNET_assert ((GNUNET_NO == GNUNET_HELLO_is_friend_only (host->hello))); if (NULL != host->friend_only_hello) GNUNET_assert ((GNUNET_YES == GNUNET_HELLO_is_friend_only(host->friend_only_hello))); fn = get_host_filename (peer); if ( (NULL != fn) && (GNUNET_OK == GNUNET_DISK_directory_create_for_file (fn)) ) { store_hello = GNUNET_NO; size = 0; cnt = 0; if (NULL != host->hello) (void) GNUNET_HELLO_iterate_addresses (host->hello, GNUNET_NO, &count_addresses, &cnt); if (cnt > 0) { store_hello = GNUNET_YES; size += GNUNET_HELLO_size (host->hello); } cnt = 0; if (NULL != host->friend_only_hello) (void) GNUNET_HELLO_iterate_addresses (host->friend_only_hello, GNUNET_NO, &count_addresses, &cnt); store_friend_hello = GNUNET_NO; if (0 < cnt) { store_friend_hello = GNUNET_YES; size += GNUNET_HELLO_size (host->friend_only_hello); } if ((GNUNET_NO == store_hello) && (GNUNET_NO == store_friend_hello)) { /* no valid addresses, don't put HELLO on disk; in fact, if one exists on disk, remove it */ (void) UNLINK (fn); } else { buffer = GNUNET_malloc (size); pos = 0; if (GNUNET_YES == store_hello) { memcpy (buffer, host->hello, GNUNET_HELLO_size (host->hello)); pos += GNUNET_HELLO_size (host->hello); } if (GNUNET_YES == store_friend_hello) { memcpy (&buffer[pos], host->friend_only_hello, GNUNET_HELLO_size (host->friend_only_hello)); pos += GNUNET_HELLO_size (host->friend_only_hello); } GNUNET_assert (pos == size); if (GNUNET_SYSERR == GNUNET_DISK_fn_write (fn, buffer, size, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stored %s %s HELLO in %s with total size %u\n", (GNUNET_YES == store_friend_hello) ? "friend-only": "", (GNUNET_YES == store_hello) ? "public": "", fn, size); GNUNET_free (buffer); } } GNUNET_free_non_null (fn); notify_all (host); } /** * Do transmit info about peer to given host. * * @param cls NULL to hit all hosts, otherwise specifies a particular target * @param key hostID * @param value information to transmit * @return #GNUNET_YES (continue to iterate) */ static int add_to_tc (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct TransmitContext *tc = cls; struct HostEntry *pos = value; struct InfoMessage *im; uint16_t hs; char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; hs = 0; im = (struct InfoMessage *) buf; if ((pos->hello != NULL) && (GNUNET_NO == tc->friend_only)) { /* Copy public HELLO */ hs = GNUNET_HELLO_size (pos->hello); GNUNET_assert (hs < GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct InfoMessage)); memcpy (&im[1], pos->hello, hs); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending public HELLO with size %u for peer `%4s'\n", hs, GNUNET_i2s (key)); } else if ((pos->friend_only_hello != NULL) && (GNUNET_YES == tc->friend_only)) { /* Copy friend only HELLO */ hs = GNUNET_HELLO_size (pos->friend_only_hello); GNUNET_assert (hs < GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct InfoMessage)); memcpy (&im[1], pos->friend_only_hello, hs); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending friend-only HELLO with size %u for peer `%4s'\n", hs, GNUNET_i2s (key)); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding no HELLO for peer `%s'\n", GNUNET_i2s (key)); } im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO); im->header.size = htons (sizeof (struct InfoMessage) + hs); im->reserved = htonl (0); im->peer = pos->identity; GNUNET_SERVER_transmit_context_append_message (tc->tc, &im->header); return GNUNET_YES; } /** * @brief delete expired HELLO entries in directory * * @param cls pointer to current time (struct GNUNET_TIME_Absolute) * @param fn filename to test to see if the HELLO expired * @return #GNUNET_OK (continue iteration) */ static int discard_hosts_helper (void *cls, const char *fn) { struct GNUNET_TIME_Absolute *now = cls; char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; const struct GNUNET_HELLO_Message *hello; struct GNUNET_HELLO_Message *new_hello; int read_size; unsigned int cur_hello_size; unsigned int new_hello_size; int read_pos; int write_pos; unsigned int cnt; char *writebuffer; read_size = GNUNET_DISK_fn_read (fn, buffer, sizeof (buffer)); if (read_size < sizeof (struct GNUNET_MessageHeader)) { if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "unlink", fn); return GNUNET_OK; } writebuffer = GNUNET_malloc (read_size); read_pos = 0; write_pos = 0; while (read_pos < read_size) { /* Check each HELLO */ hello = (const struct GNUNET_HELLO_Message *) &buffer[read_pos]; cur_hello_size = GNUNET_HELLO_size (hello); if (0 == cur_hello_size) { /* Invalid data, discard */ if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "unlink", fn); return GNUNET_OK; } new_hello = GNUNET_HELLO_iterate_addresses (hello, GNUNET_YES, &discard_expired, now); cnt = 0; if (NULL != new_hello) (void) GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_addresses, &cnt); if ( (NULL != new_hello) && (0 < cnt) ) { /* Store new HELLO to write it when done */ new_hello_size = GNUNET_HELLO_size (new_hello); memcpy (&writebuffer[write_pos], new_hello, new_hello_size); write_pos += new_hello_size; } read_pos += cur_hello_size; GNUNET_free_non_null (new_hello); } if (0 < write_pos) { GNUNET_DISK_fn_write (fn, writebuffer,write_pos, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ); } else if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "unlink", fn); GNUNET_free (writebuffer); return GNUNET_OK; } /** * Call this method periodically to scan peerinfo/ for ancient * HELLOs to expire. * * @param cls unused * @param tc scheduler context, aborted if reason is shutdown */ static void cron_clean_data_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Absolute now; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; now = GNUNET_TIME_absolute_get (); GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, _("Cleaning up directory `%s'\n"), networkIdDirectory); GNUNET_DISK_directory_scan (networkIdDirectory, &discard_hosts_helper, &now); GNUNET_SCHEDULER_add_delayed (DATA_HOST_CLEAN_FREQ, &cron_clean_data_hosts, NULL); } /** * Handle HELLO-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_hello (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_HELLO_Message *hello; struct GNUNET_PeerIdentity pid; hello = (const struct GNUNET_HELLO_Message *) message; if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received for peer `%4s'\n", "HELLO", GNUNET_i2s (&pid)); add_host_to_known_hosts (&pid); update_hello (&pid, hello); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ListPeerMessage *lpm; struct TransmitContext tcx; lpm = (const struct ListPeerMessage *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received for peer `%4s'\n", "GET", GNUNET_i2s (&lpm->peer)); tcx.friend_only = ntohl (lpm->include_friend_only); tcx.tc = GNUNET_SERVER_transmit_context_create (client); GNUNET_CONTAINER_multipeermap_get_multiple (hostmap, &lpm->peer, &add_to_tc, &tcx); GNUNET_SERVER_transmit_context_append_data (tcx.tc, NULL, 0, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END); GNUNET_SERVER_transmit_context_run (tcx.tc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Handle GET-ALL-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get_all (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ListAllPeersMessage *lapm; struct TransmitContext tcx; lapm = (const struct ListAllPeersMessage *) message; tcx.friend_only = ntohl (lapm->include_friend_only); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received\n", "GET_ALL"); GNUNET_SERVER_disable_receive_done_warning (client); tcx.tc = GNUNET_SERVER_transmit_context_create (client); GNUNET_CONTAINER_multipeermap_iterate (hostmap, &add_to_tc, &tcx); GNUNET_SERVER_transmit_context_append_data (tcx.tc, NULL, 0, GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END); GNUNET_SERVER_transmit_context_run (tcx.tc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Pass the given client the information we have in the respective * host entry; the client is already in the notification context. * * @param cls the `struct GNUNET_SERVER_Client` to notify * @param key key for the value (unused) * @param value the `struct HostEntry` to notify the client about * @return #GNUNET_YES (always, continue to iterate) */ static int do_notify_entry (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct NotificationContext *nc = cls; struct HostEntry *he = value; struct InfoMessage *msg; if ((NULL == he->hello) && (GNUNET_NO == nc->include_friend_only)) { /* We have no public hello */ return GNUNET_YES; } if ( (NULL == he->friend_only_hello) && (GNUNET_YES == nc->include_friend_only) ) { /* We have no friend hello */ return GNUNET_YES; } msg = make_info_message (he, nc->include_friend_only); GNUNET_SERVER_notification_context_unicast (notify_list, nc->client, &msg->header, GNUNET_NO); GNUNET_free (msg); return GNUNET_YES; } /** * Handle NOTIFY-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_notify (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct NotifyMessage *nm = (struct NotifyMessage *) message; struct NotificationContext *nc; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received\n", "NOTIFY"); nc = GNUNET_new (struct NotificationContext); nc->client = client; nc->include_friend_only = ntohl (nm->include_friend_only); GNUNET_CONTAINER_DLL_insert (nc_head, nc_tail, nc); GNUNET_SERVER_client_mark_monitor (client); GNUNET_SERVER_notification_context_add (notify_list, client); GNUNET_CONTAINER_multipeermap_iterate (hostmap, &do_notify_entry, nc); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Client disconnect callback * * @param cls unused * @param client server client */ static void disconnect_cb (void *cls,struct GNUNET_SERVER_Client *client) { struct NotificationContext *cur; for (cur = nc_head; NULL != cur; cur = cur->next) if (cur->client == client) break; if (NULL == cur) return; GNUNET_CONTAINER_DLL_remove (nc_head, nc_tail, cur); GNUNET_free (cur); } /** * Release memory taken by a host entry. * * @param cls NULL * @param key key of the host entry * @param value the `struct HostEntry` to free * @return #GNUNET_YES (continue to iterate) */ static int free_host_entry (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct HostEntry *he = value; GNUNET_free_non_null (he->hello); GNUNET_free_non_null (he->friend_only_hello); GNUNET_free (he); return GNUNET_YES; } /** * Clean up our state. Called during shutdown. * * @param cls unused * @param tc scheduler task context, unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct NotificationContext *cur; struct NotificationContext *next; GNUNET_SERVER_notification_context_destroy (notify_list); notify_list = NULL; for (cur = nc_head; NULL != cur; cur = next) { next = cur->next; GNUNET_CONTAINER_DLL_remove (nc_head, nc_tail, cur); GNUNET_free (cur); } GNUNET_CONTAINER_multipeermap_iterate (hostmap, &free_host_entry, NULL); GNUNET_CONTAINER_multipeermap_destroy (hostmap); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } } /** * Start up peerinfo service. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_hello, NULL, GNUNET_MESSAGE_TYPE_HELLO, 0}, {&handle_get, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET, sizeof (struct ListPeerMessage)}, {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL, sizeof (struct ListAllPeersMessage)}, {&handle_notify, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY, sizeof (struct NotifyMessage)}, {NULL, NULL, 0, 0} }; char *peerdir; char *ip; struct DirScanContext dsc; int noio; int use_included; hostmap = GNUNET_CONTAINER_multipeermap_create (1024, GNUNET_YES); stats = GNUNET_STATISTICS_create ("peerinfo", cfg); notify_list = GNUNET_SERVER_notification_context_create (server, 0); noio = GNUNET_CONFIGURATION_get_value_yesno (cfg, "peerinfo", "NO_IO"); use_included = GNUNET_CONFIGURATION_get_value_yesno (cfg, "peerinfo", "USE_INCLUDED_HELLOS"); if (GNUNET_SYSERR == use_included) use_included = GNUNET_NO; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); if (GNUNET_YES != noio) { GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "peerinfo", "HOSTS", &networkIdDirectory)); if (GNUNET_OK != GNUNET_DISK_directory_create (networkIdDirectory)) { GNUNET_SCHEDULER_shutdown (); return; } GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &cron_scan_directory_data_hosts, NULL); GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &cron_clean_data_hosts, NULL); if (GNUNET_YES == use_included) { ip = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); GNUNET_asprintf (&peerdir, "%shellos", ip); GNUNET_free(ip); GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Importing HELLOs from `%s'\n"), peerdir); dsc.matched = 0; dsc.remove_files = GNUNET_NO; GNUNET_DISK_directory_scan (peerdir, &hosts_directory_scan_callback, &dsc); GNUNET_free (peerdir); } else { GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Skipping import of included HELLOs\n")); } } GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, &disconnect_cb, NULL) ; } /** * The main function for the peerinfo service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "peerinfo", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; GNUNET_free_non_null (networkIdDirectory); return ret; } /* end of gnunet-service-peerinfo.c */ gnunet-0.10.1/src/peerinfo/peerinfo_api_notify.c0000644000175000017500000002010112255010511016566 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/peerinfo_api_notify.c * @brief notify API to access peerinfo service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_protocols.h" #include "peerinfo.h" #define LOG(kind,...) GNUNET_log_from (kind, "nse-api",__VA_ARGS__) /** * Context for the info handler. */ struct GNUNET_PEERINFO_NotifyContext { /** * Our connection to the PEERINFO service. */ struct GNUNET_CLIENT_Connection *client; /** * Function to call with information. */ GNUNET_PEERINFO_Processor callback; /** * Closure for callback. */ void *callback_cls; /** * Handle to our initial request for message transmission to * the peerinfo service. */ struct GNUNET_CLIENT_TransmitHandle *init; /** * Configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Tasked used for delayed re-connection attempt. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Include friend only HELLOs in callbacks */ int include_friend_only; }; /** * Send a request to the peerinfo service to start being * notified about all changes to peer information. * * @param nc our context */ static void request_notifications (struct GNUNET_PEERINFO_NotifyContext *nc); /** * Read notifications from the client handle and pass them * to the callback. * * @param nc our context */ static void receive_notifications (struct GNUNET_PEERINFO_NotifyContext *nc); /** * Task to re-try connecting to peerinfo. * * @param cls the 'struct GNUNET_PEERINFO_NotifyContext' * @param tc scheduler context */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PEERINFO_NotifyContext *nc = cls; nc->task = GNUNET_SCHEDULER_NO_TASK; nc->client = GNUNET_CLIENT_connect ("peerinfo", nc->cfg); if (NULL == nc->client) { /* ugh */ nc->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect, nc); return; } request_notifications (nc); } /** * Receive a peerinfo information message, process it and * go for more. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void process_notification (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_PEERINFO_NotifyContext *nc = cls; const struct InfoMessage *im; const struct GNUNET_HELLO_Message *hello; uint16_t ms; if (msg == NULL) { GNUNET_CLIENT_disconnect (nc->client); reconnect (nc, NULL); return; } ms = ntohs (msg->size); if ((ms < sizeof (struct InfoMessage)) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO)) { GNUNET_break (0); GNUNET_CLIENT_disconnect (nc->client); nc->client = GNUNET_CLIENT_connect ("peerinfo", nc->cfg); request_notifications (nc); return; } im = (const struct InfoMessage *) msg; hello = NULL; if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader)) { hello = (const struct GNUNET_HELLO_Message *) &im[1]; if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello)) { GNUNET_break (0); GNUNET_CLIENT_disconnect (nc->client); nc->client = GNUNET_CLIENT_connect ("peerinfo", nc->cfg); request_notifications (nc); return; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received information about peer `%s' from peerinfo database\n", GNUNET_i2s (&im->peer)); nc->callback (nc->callback_cls, &im->peer, hello, NULL); receive_notifications (nc); } /** * Read notifications from the client handle and pass them * to the callback. * * @param nc our context */ static void receive_notifications (struct GNUNET_PEERINFO_NotifyContext *nc) { GNUNET_CLIENT_receive (nc->client, &process_notification, nc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Transmit our init-notify request, start receiving. * * @param cls closure (our 'struct GNUNET_PEERINFO_NotifyContext') * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_notify_request (void *cls, size_t size, void *buf) { struct GNUNET_PEERINFO_NotifyContext *nc = cls; struct NotifyMessage nm; nc->init = NULL; if (buf == NULL) { GNUNET_CLIENT_disconnect (nc->client); nc->client = GNUNET_CLIENT_connect ("peerinfo", nc->cfg); request_notifications (nc); return 0; } GNUNET_assert (size >= sizeof (struct NotifyMessage)); nm.header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY); nm.header.size = htons (sizeof (struct NotifyMessage)); nm.include_friend_only = htonl (nc->include_friend_only); memcpy (buf, &nm, sizeof (struct NotifyMessage)); receive_notifications (nc); return sizeof (struct NotifyMessage); } /** * Send a request to the peerinfo service to start being * notified about all changes to peer information. * * @param nc our context */ static void request_notifications (struct GNUNET_PEERINFO_NotifyContext *nc) { GNUNET_assert (NULL == nc->init); nc->init = GNUNET_CLIENT_notify_transmit_ready (nc->client, sizeof (struct NotifyMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_notify_request, nc); } /** * Call a method whenever our known information about peers * changes. Initially calls the given function for all known * peers and then only signals changes. * * If include_friend_only is set to GNUNET_YES peerinfo will include HELLO * messages which are intended for friend to friend mode and which do not * have to be gossiped. Otherwise these messages are skipped. * * @param cfg configuration to use * @param include_friend_only include HELLO messages for friends only * @param callback the method to call for each peer * @param callback_cls closure for callback * @return NULL on error */ struct GNUNET_PEERINFO_NotifyContext * GNUNET_PEERINFO_notify (const struct GNUNET_CONFIGURATION_Handle *cfg, int include_friend_only, GNUNET_PEERINFO_Processor callback, void *callback_cls) { struct GNUNET_PEERINFO_NotifyContext *nc; struct GNUNET_CLIENT_Connection *client; client = GNUNET_CLIENT_connect ("peerinfo", cfg); if (client == NULL) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Could not connect to `%s' service.\n"), "peerinfo"); return NULL; } nc = GNUNET_new (struct GNUNET_PEERINFO_NotifyContext); nc->cfg = cfg; nc->client = client; nc->callback = callback; nc->callback_cls = callback_cls; nc->include_friend_only = include_friend_only; request_notifications (nc); return nc; } /** * Stop notifying about changes. * * @param nc context to stop notifying */ void GNUNET_PEERINFO_notify_cancel (struct GNUNET_PEERINFO_NotifyContext *nc) { if (NULL != nc->init) { GNUNET_CLIENT_notify_transmit_ready_cancel (nc->init); nc->init = NULL; } if (NULL != nc->client) GNUNET_CLIENT_disconnect (nc->client); if (GNUNET_SCHEDULER_NO_TASK != nc->task) GNUNET_SCHEDULER_cancel (nc->task); GNUNET_free (nc); } /* end of peerinfo_api_notify.c */ gnunet-0.10.1/src/peerinfo/perf_peerinfo_api.c0000644000175000017500000000711512320530515016230 00000000000000/* This file is part of GNUnet. (C) 2004, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/perf_peerinfo_api.c * @brief testcase for peerinfo_api.c, hopefully hammer the peerinfo service * @author Nathan Evans */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_peerinfo_service.h" #include "peerinfo.h" #include #define START_SERVICE 1 #define NUM_REQUESTS 5000 static struct GNUNET_PEERINFO_IteratorContext *ic[NUM_REQUESTS]; static struct GNUNET_PEERINFO_Handle *h; static unsigned int numpeers; static struct GNUNET_PeerIdentity pid; static int check_it (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { return GNUNET_OK; } static size_t address_generator (void *cls, size_t max, void *buf) { size_t *agc = cls; size_t ret; char *caddress; struct GNUNET_HELLO_Address address; if (*agc == 0) return 0; GNUNET_asprintf (&caddress, "Address%d", *agc); address.peer = pid; address.address_length = strlen (caddress) + 1; address.address = caddress; address.transport_name = "peerinfotest"; ret = GNUNET_HELLO_add_address (&address, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), buf, max); GNUNET_free (caddress); *agc = 0; return ret; } static void add_peer (size_t i) { struct GNUNET_HELLO_Message *h2; memset (&pid, i, sizeof (pid)); h2 = GNUNET_HELLO_create (&pid.public_key, &address_generator, &i, GNUNET_NO); GNUNET_PEERINFO_add_peer (h, h2, NULL, NULL); GNUNET_free (h2); } static void process (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { if (NULL != peer) { numpeers++; if (0 && (hello != NULL)) GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &check_it, NULL); } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { size_t i; h = GNUNET_PEERINFO_connect (cfg); GNUNET_assert (h != NULL); for (i = 0; i < NUM_REQUESTS; i++) { add_peer (i); ic[i] = GNUNET_PEERINFO_iterate (h, GNUNET_YES, NULL, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30), &process, cls); } } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_service_run ("perf-gnunet-peerinfo", "peerinfo", "test_peerinfo_api_data.conf", &run, NULL)) return 1; FPRINTF (stderr, "Received %u/%u calls before timeout\n", numpeers, NUM_REQUESTS * NUM_REQUESTS / 2); GAUGER ("PEERINFO", "Peerinfo lookups", numpeers / 30, "peers/s"); return 0; } /* end of perf_peerinfo_api.c */ gnunet-0.10.1/src/peerinfo/test_peerinfo_api_data.conf0000644000175000017500000000017712225230043017745 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-peerinfo/ [peerinfo] PORT = 22354 [dns] AUTOSTART = NO [nse] AUTOSTART = NO gnunet-0.10.1/src/peerinfo/peerinfo.h0000644000175000017500000000544712307312000014366 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/peerinfo.h * @brief common internal definitions for peerinfo service * @author Christian Grothoff */ #ifndef PEERINFO_H #define PEERINFO_H #include "gnunet_crypto_lib.h" #include "gnunet_time_lib.h" #include "gnunet_peerinfo_service.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Message requesting a listing of peers, * restricted to the specified peer identity. */ struct ListPeerMessage { /** * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_GET */ struct GNUNET_MessageHeader header; /** * Include friend only HELLOs and peers in callbacks */ uint32_t include_friend_only GNUNET_PACKED; /** * Restrict to peers with this identity (optional * field, check header.size!). */ struct GNUNET_PeerIdentity peer; }; /** * Message requesting a listing of all peers, * restricted to the specified peer identity. */ struct ListAllPeersMessage { /** * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL */ struct GNUNET_MessageHeader header; /** * Include friend only HELLOs and peers in callbacks */ uint32_t include_friend_only GNUNET_PACKED; }; /** * Header for all communications. */ struct NotifyMessage { /** * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY */ struct GNUNET_MessageHeader header; /** * Include friend only HELLOs and peers in callbacks */ uint32_t include_friend_only GNUNET_PACKED; }; /** * Message used to inform the client about * a particular peer; this message is optionally followed * by a HELLO message for the respective peer (if available). * Check the header.size field to see if a HELLO is * present. */ struct InfoMessage { /** * Type will be GNUNET_MESSAGE_TYPE_PEERINFO_INFO */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * About which peer are we talking here? */ struct GNUNET_PeerIdentity peer; }; GNUNET_NETWORK_STRUCT_END /*#ifndef PEERINFO_H*/ #endif /* end of peerinfo.h */ gnunet-0.10.1/src/peerinfo/test_peerinfo_api_friend_only.c0000644000175000017500000001004312225777501020651 00000000000000/* This file is part of GNUnet. (C) 2004, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/test_peerinfo_api_friend_only.c * @brief testcase friend only HELLO restrictions in for peerinfo * @author Christian Grothoff * @author Matthias Wachs * * TODO: * - test merging of HELLOs (add same peer twice...) */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_testing_lib.h" #include "peerinfo.h" static struct GNUNET_PEERINFO_IteratorContext *ic; static struct GNUNET_PEERINFO_Handle *h; static unsigned int retries; static int global_ret; static size_t address_generator (void *cls, size_t max, void *buf) { size_t *agc = cls; size_t ret; struct GNUNET_HELLO_Address address; if (0 == *agc) return 0; memset (&address.peer, 0, sizeof (struct GNUNET_PeerIdentity)); address.address = "Address"; address.transport_name = "peerinfotest"; address.address_length = *agc; ret = GNUNET_HELLO_add_address (&address, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), buf, max); (*agc)--; return ret; } struct GNUNET_PeerIdentity pid; static void add_peer () { struct GNUNET_HELLO_Message *h2; size_t agc; agc = 2; memset (&pid, 32, sizeof (pid)); h2 = GNUNET_HELLO_create (&pid.public_key, &address_generator, &agc, GNUNET_YES); GNUNET_PEERINFO_add_peer (h, h2, NULL, NULL); GNUNET_free (h2); } static void process (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { if (err_msg != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error in communication with PEERINFO service\n")); } if (peer == NULL) { ic = NULL; if ((3 == global_ret) && (retries < 50)) { /* try again */ retries++; add_peer (); ic = GNUNET_PEERINFO_iterate (h, GNUNET_NO, NULL, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15), &process, cls); return; } GNUNET_assert (peer == NULL); GNUNET_assert (2 == global_ret); GNUNET_PEERINFO_disconnect (h); h = NULL; global_ret = 0; return; } if (hello == NULL) { GNUNET_assert (3 == global_ret); global_ret = 2; } else { fprintf (stderr, "Received %s HELLO\n", (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello)) ? "friend only" : "public"); GNUNET_PEERINFO_disconnect (h); h = NULL; return; } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { h = GNUNET_PEERINFO_connect (cfg); GNUNET_assert (NULL != h); add_peer (); ic = GNUNET_PEERINFO_iterate (h, GNUNET_NO, &pid, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15), &process, cls); } int main (int argc, char *argv[]) { global_ret = 3; if (0 != GNUNET_TESTING_service_run ("test-peerinfo-api-friend-only", "peerinfo", "test_peerinfo_api_data.conf", &run, NULL)) return 1; return global_ret; } /* end of test_peerinfo_api_friend_only */ gnunet-0.10.1/src/peerinfo/test_peerinfo_shipped_hellos.c0000644000175000017500000000607012225777501020517 00000000000000/* This file is part of GNUnet. (C) 2004, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/test_peerinfo_api.c * @brief testcase for shipped HELLOs getting parsed * @author Christian Grothoff * @author Matthias Wachs * */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_testing_lib.h" #include "peerinfo.h" static struct GNUNET_PEERINFO_IteratorContext *ic; static struct GNUNET_PEERINFO_Handle *h; static int global_ret; static int addr_cb (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) {; int *addr = cls; (*addr) ++; return GNUNET_OK; } static void process (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { static unsigned int calls = 0; int addr; if (err_msg != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error in communication with PEERINFO service\n")); } if (NULL != peer) { addr = 0; if (NULL != hello) { GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &addr_cb, &addr); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got information about peer `%s' with %u addresses \n", GNUNET_i2s (peer), addr); calls++; } else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail: Got information about peer `%s' without HELLO \n", GNUNET_i2s (peer)); } else { if (0 == calls) { fprintf (stderr, "Failed: %u callbacks\n", calls); global_ret = 1; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u callbacks\n", calls); global_ret = 0; } } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { h = GNUNET_PEERINFO_connect (cfg); GNUNET_assert (NULL != h); ic = GNUNET_PEERINFO_iterate (h, GNUNET_YES, NULL, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15), &process, cls); } int main (int argc, char *argv[]) { global_ret = 3; if (0 != GNUNET_TESTING_service_run ("test_peerinfo_system_hellos", "peerinfo", "test_peerinfo_api_data.conf", &run, NULL)) return 1; return global_ret; } /* end of test_peerinfo_shipped_hellos.c */ gnunet-0.10.1/src/peerinfo/Makefile.in0000644000175000017500000013772412320752063014473 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-peerinfo$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = \ @HAVE_TESTING_TRUE@ test_peerinfo_shipped_hellos$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_peerinfo_api$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_peerinfo_api_friend_only$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_peerinfo_api_notify_friend_only$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_1) subdir = src/peerinfo DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/peerinfo.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = peerinfo.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetpeerinfo_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetpeerinfo_la_OBJECTS = peerinfo_api.lo \ peerinfo_api_notify.lo libgnunetpeerinfo_la_OBJECTS = $(am_libgnunetpeerinfo_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetpeerinfo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetpeerinfo_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_BENCHMARKS_TRUE@am__EXEEXT_1 = perf_peerinfo_api$(EXEEXT) PROGRAMS = $(libexec_PROGRAMS) am_gnunet_service_peerinfo_OBJECTS = \ gnunet-service-peerinfo.$(OBJEXT) gnunet_service_peerinfo_OBJECTS = \ $(am_gnunet_service_peerinfo_OBJECTS) gnunet_service_peerinfo_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_peerinfo_api_OBJECTS = perf_peerinfo_api.$(OBJEXT) perf_peerinfo_api_OBJECTS = $(am_perf_peerinfo_api_OBJECTS) perf_peerinfo_api_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_peerinfo_api_OBJECTS = test_peerinfo_api.$(OBJEXT) test_peerinfo_api_OBJECTS = $(am_test_peerinfo_api_OBJECTS) test_peerinfo_api_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_peerinfo_api_friend_only_OBJECTS = \ test_peerinfo_api_friend_only.$(OBJEXT) test_peerinfo_api_friend_only_OBJECTS = \ $(am_test_peerinfo_api_friend_only_OBJECTS) test_peerinfo_api_friend_only_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_peerinfo_api_notify_friend_only_OBJECTS = \ test_peerinfo_api_notify_friend_only.$(OBJEXT) test_peerinfo_api_notify_friend_only_OBJECTS = \ $(am_test_peerinfo_api_notify_friend_only_OBJECTS) test_peerinfo_api_notify_friend_only_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_peerinfo_shipped_hellos_OBJECTS = \ test_peerinfo_shipped_hellos.$(OBJEXT) test_peerinfo_shipped_hellos_OBJECTS = \ $(am_test_peerinfo_shipped_hellos_OBJECTS) test_peerinfo_shipped_hellos_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetpeerinfo_la_SOURCES) \ $(gnunet_service_peerinfo_SOURCES) \ $(perf_peerinfo_api_SOURCES) $(test_peerinfo_api_SOURCES) \ $(test_peerinfo_api_friend_only_SOURCES) \ $(test_peerinfo_api_notify_friend_only_SOURCES) \ $(test_peerinfo_shipped_hellos_SOURCES) DIST_SOURCES = $(libgnunetpeerinfo_la_SOURCES) \ $(gnunet_service_peerinfo_SOURCES) \ $(perf_peerinfo_api_SOURCES) $(test_peerinfo_api_SOURCES) \ $(test_peerinfo_api_friend_only_SOURCES) \ $(test_peerinfo_api_notify_friend_only_SOURCES) \ $(test_peerinfo_shipped_hellos_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ peerinfo.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov lib_LTLIBRARIES = libgnunetpeerinfo.la libgnunetpeerinfo_la_SOURCES = \ peerinfo_api.c peerinfo.h \ peerinfo_api_notify.c libgnunetpeerinfo_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) \ $(LTLIBINTL) libgnunetpeerinfo_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 gnunet_service_peerinfo_SOURCES = \ gnunet-service-peerinfo.c gnunet_service_peerinfo_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la @HAVE_BENCHMARKS_TRUE@PEERINFO_BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@ perf_peerinfo_api @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_peerinfo_shipped_hellos_SOURCES = \ test_peerinfo_shipped_hellos.c test_peerinfo_shipped_hellos_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_peerinfo_api_SOURCES = \ test_peerinfo_api.c test_peerinfo_api_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_peerinfo_api_friend_only_SOURCES = \ test_peerinfo_api_friend_only.c test_peerinfo_api_friend_only_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_peerinfo_api_notify_friend_only_SOURCES = \ test_peerinfo_api_notify_friend_only.c test_peerinfo_api_notify_friend_only_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_peerinfo_api_SOURCES = \ perf_peerinfo_api.c perf_peerinfo_api_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_peerinfo_api_data.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/peerinfo/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/peerinfo/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): peerinfo.conf: $(top_builddir)/config.status $(srcdir)/peerinfo.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetpeerinfo.la: $(libgnunetpeerinfo_la_OBJECTS) $(libgnunetpeerinfo_la_DEPENDENCIES) $(EXTRA_libgnunetpeerinfo_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetpeerinfo_la_LINK) -rpath $(libdir) $(libgnunetpeerinfo_la_OBJECTS) $(libgnunetpeerinfo_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-service-peerinfo$(EXEEXT): $(gnunet_service_peerinfo_OBJECTS) $(gnunet_service_peerinfo_DEPENDENCIES) $(EXTRA_gnunet_service_peerinfo_DEPENDENCIES) @rm -f gnunet-service-peerinfo$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_peerinfo_OBJECTS) $(gnunet_service_peerinfo_LDADD) $(LIBS) perf_peerinfo_api$(EXEEXT): $(perf_peerinfo_api_OBJECTS) $(perf_peerinfo_api_DEPENDENCIES) $(EXTRA_perf_peerinfo_api_DEPENDENCIES) @rm -f perf_peerinfo_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_peerinfo_api_OBJECTS) $(perf_peerinfo_api_LDADD) $(LIBS) test_peerinfo_api$(EXEEXT): $(test_peerinfo_api_OBJECTS) $(test_peerinfo_api_DEPENDENCIES) $(EXTRA_test_peerinfo_api_DEPENDENCIES) @rm -f test_peerinfo_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_peerinfo_api_OBJECTS) $(test_peerinfo_api_LDADD) $(LIBS) test_peerinfo_api_friend_only$(EXEEXT): $(test_peerinfo_api_friend_only_OBJECTS) $(test_peerinfo_api_friend_only_DEPENDENCIES) $(EXTRA_test_peerinfo_api_friend_only_DEPENDENCIES) @rm -f test_peerinfo_api_friend_only$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_peerinfo_api_friend_only_OBJECTS) $(test_peerinfo_api_friend_only_LDADD) $(LIBS) test_peerinfo_api_notify_friend_only$(EXEEXT): $(test_peerinfo_api_notify_friend_only_OBJECTS) $(test_peerinfo_api_notify_friend_only_DEPENDENCIES) $(EXTRA_test_peerinfo_api_notify_friend_only_DEPENDENCIES) @rm -f test_peerinfo_api_notify_friend_only$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_peerinfo_api_notify_friend_only_OBJECTS) $(test_peerinfo_api_notify_friend_only_LDADD) $(LIBS) test_peerinfo_shipped_hellos$(EXEEXT): $(test_peerinfo_shipped_hellos_OBJECTS) $(test_peerinfo_shipped_hellos_DEPENDENCIES) $(EXTRA_test_peerinfo_shipped_hellos_DEPENDENCIES) @rm -f test_peerinfo_shipped_hellos$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_peerinfo_shipped_hellos_OBJECTS) $(test_peerinfo_shipped_hellos_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-peerinfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peerinfo_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peerinfo_api_notify.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_peerinfo_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_peerinfo_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_peerinfo_api_friend_only.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_peerinfo_api_notify_friend_only.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_peerinfo_shipped_hellos.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_peerinfo_shipped_hellos.log: test_peerinfo_shipped_hellos$(EXEEXT) @p='test_peerinfo_shipped_hellos$(EXEEXT)'; \ b='test_peerinfo_shipped_hellos'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_peerinfo_api.log: test_peerinfo_api$(EXEEXT) @p='test_peerinfo_api$(EXEEXT)'; \ b='test_peerinfo_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_peerinfo_api_friend_only.log: test_peerinfo_api_friend_only$(EXEEXT) @p='test_peerinfo_api_friend_only$(EXEEXT)'; \ b='test_peerinfo_api_friend_only'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_peerinfo_api_notify_friend_only.log: test_peerinfo_api_notify_friend_only$(EXEEXT) @p='test_peerinfo_api_notify_friend_only$(EXEEXT)'; \ b='test_peerinfo_api_notify_friend_only'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_peerinfo_api.log: perf_peerinfo_api$(EXEEXT) @p='perf_peerinfo_api$(EXEEXT)'; \ b='perf_peerinfo_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/peerinfo/peerinfo.conf.in0000644000175000017500000000126712250373167015507 00000000000000[peerinfo] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2090 HOSTNAME = localhost BINARY = gnunet-service-peerinfo ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-peerinfo.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = HOSTS = $GNUNET_DATA_HOME/peerinfo/hosts/ # Option to disable all disk IO; only useful for testbed runs # (large-scale experiments); disables persistence of HELLOs! NO_IO = NO # Load HELLOs shipped with GNUnet USE_INCLUDED_HELLOS = YES [uri] hello = gnunet-peerinfo friend-hello = gnunet-peerinfo gnunet-0.10.1/src/peerinfo/test_peerinfo_api_notify_friend_only.c0000644000175000017500000001522312225777501022246 00000000000000/* This file is part of GNUnet. (C) 2004, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/test_peerinfo_api_notify_friend_only.c * @brief testcase friend only HELLO restrictions in for peerinfo * @author Christian Grothoff * @author Matthias Wachs * * TODO: * - test merging of HELLOs (add same peer twice...) */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_testing_lib.h" #include "peerinfo.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) static struct GNUNET_PEERINFO_Handle *h; static struct GNUNET_PEERINFO_NotifyContext *pnc_w_fo; static struct GNUNET_PEERINFO_NotifyContext *pnc_wo_fo; static const struct GNUNET_CONFIGURATION_Handle *mycfg; static int global_ret; /** * Did we get a HELLO callback for notification handle with friend HELLOS * (expected) */ static int res_cb_w_fo; /** * Did we get a HELLO callback for notification handle without friend HELLOS * (not expected) */ static int res_cb_wo_fo; struct GNUNET_PeerIdentity pid; GNUNET_SCHEDULER_TaskIdentifier timeout_task; static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_break (0); if (NULL != pnc_wo_fo) { GNUNET_PEERINFO_notify_cancel (pnc_wo_fo); pnc_wo_fo = NULL; } if (NULL != pnc_w_fo) { GNUNET_PEERINFO_notify_cancel (pnc_w_fo); pnc_w_fo = NULL; } if (NULL != h) { GNUNET_PEERINFO_disconnect (h); h = NULL; } global_ret = 255; } static void done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != pnc_w_fo) GNUNET_PEERINFO_notify_cancel (pnc_w_fo); pnc_w_fo = NULL; if (NULL != pnc_wo_fo) GNUNET_PEERINFO_notify_cancel (pnc_wo_fo); pnc_wo_fo = NULL; GNUNET_PEERINFO_disconnect (h); h = NULL; if (GNUNET_SCHEDULER_NO_TASK != timeout_task) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } if ((GNUNET_YES == res_cb_w_fo) && (GNUNET_NO == res_cb_wo_fo)) global_ret = 0; else GNUNET_break (0); } static size_t address_generator (void *cls, size_t max, void *buf) { size_t *agc = cls; size_t ret; struct GNUNET_HELLO_Address address; if (0 == *agc) return 0; memset (&address.peer, 0, sizeof (struct GNUNET_PeerIdentity)); address.address = "Address"; address.transport_name = "peerinfotest"; address.address_length = *agc; ret = GNUNET_HELLO_add_address (&address, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), buf, max); (*agc)--; return ret; } static void process_w_fo (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { if (err_msg != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error in communication with PEERINFO service\n")); GNUNET_SCHEDULER_add_now(&done, NULL); return; } if (NULL != peer) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received callback for peer `%s' %s HELLO\n", GNUNET_i2s (peer), (NULL != hello) ? "with" : "without"); if (NULL == hello) return; if (GNUNET_NO == GNUNET_HELLO_is_friend_only(hello)) { GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received %s HELLO for peer `%s'\n", (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello)) ? "friend only" : "public", GNUNET_i2s (peer)); if (0 == memcmp (&pid, peer, sizeof (pid))) { res_cb_w_fo = GNUNET_YES; GNUNET_SCHEDULER_add_now(&done, NULL); } return; } } static void process_wo_fo (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { if (err_msg != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error in communication with PEERINFO service\n")); GNUNET_SCHEDULER_add_now(&done, NULL); return; } if (NULL != peer) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received callback for peer `%s' %s HELLO\n", GNUNET_i2s (peer), (NULL != hello) ? "with" : "without"); if (NULL == hello) return; if (GNUNET_YES == GNUNET_HELLO_is_friend_only(hello)) { GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received %s HELLO for peer `%s'\n", (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello)) ? "friend only" : "public", GNUNET_i2s (peer)); if (0 == memcmp (&pid, peer, sizeof (pid))) { GNUNET_break (0); res_cb_wo_fo = GNUNET_YES; } } } static void add_peer_done (void *cls, const char *emsg) { if (NULL == emsg) { return; } else { GNUNET_break (0); GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); } } static void add_peer () { struct GNUNET_HELLO_Message *h2; size_t agc; agc = 2; memset (&pid, 32, sizeof (pid)); h2 = GNUNET_HELLO_create (&pid.public_key, &address_generator, &agc, GNUNET_YES); GNUNET_PEERINFO_add_peer (h, h2, &add_peer_done, NULL); GNUNET_free (h2); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); mycfg = cfg; pnc_w_fo = GNUNET_PEERINFO_notify (mycfg, GNUNET_YES, &process_w_fo, NULL); pnc_wo_fo = GNUNET_PEERINFO_notify (mycfg, GNUNET_NO, &process_wo_fo, NULL); h = GNUNET_PEERINFO_connect (cfg); GNUNET_assert (NULL != h); add_peer (); } int main (int argc, char *argv[]) { res_cb_w_fo = GNUNET_NO; res_cb_wo_fo = GNUNET_NO; global_ret = 3; if (0 != GNUNET_TESTING_service_run ("test-peerinfo-api-friend-only", "peerinfo", "test_peerinfo_api_data.conf", &run, NULL)) return 1; return global_ret; } /* end of test_peerinfo_api_notify_friend_only.c */ gnunet-0.10.1/src/peerinfo/test_peerinfo_api.c0000644000175000017500000001053712225777501016271 00000000000000/* This file is part of GNUnet. (C) 2004, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/test_peerinfo_api.c * @brief testcase for peerinfo_api.c * @author Christian Grothoff * * TODO: * - test merging of HELLOs (add same peer twice...) */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_testing_lib.h" #include "peerinfo.h" static struct GNUNET_PEERINFO_IteratorContext *ic; static struct GNUNET_PEERINFO_Handle *h; static unsigned int retries; static int global_ret; static int check_it (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { unsigned int *agc = cls; if (address != NULL) { GNUNET_assert (0 == strcmp ("peerinfotest", address->transport_name)); GNUNET_assert (0 == strncmp ("Address", address->address, address->address_length)); (*agc) -= (1 << (address->address_length - 1)); } return GNUNET_OK; } static size_t address_generator (void *cls, size_t max, void *buf) { size_t *agc = cls; size_t ret; struct GNUNET_HELLO_Address address; if (0 == *agc) return 0; memset (&address.peer, 0, sizeof (struct GNUNET_PeerIdentity)); address.address = "Address"; address.transport_name = "peerinfotest"; address.address_length = *agc; ret = GNUNET_HELLO_add_address (&address, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), buf, max); (*agc)--; return ret; } struct GNUNET_PeerIdentity pid; static void add_peer () { struct GNUNET_HELLO_Message *h2; size_t agc; agc = 2; memset (&pid, 32, sizeof (pid)); h2 = GNUNET_HELLO_create (&pid.public_key, &address_generator, &agc, GNUNET_NO); GNUNET_PEERINFO_add_peer (h, h2, NULL, NULL); GNUNET_free (h2); } static void process (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { unsigned int agc; if (err_msg != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error in communication with PEERINFO service\n")); } if (peer == NULL) { ic = NULL; if ((3 == global_ret) && (retries < 50)) { /* try again */ retries++; add_peer (); ic = GNUNET_PEERINFO_iterate (h, GNUNET_NO, NULL, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15), &process, cls); return; } GNUNET_assert (peer == NULL); GNUNET_assert (2 == global_ret); GNUNET_PEERINFO_disconnect (h); h = NULL; global_ret = 0; return; } if (hello != NULL) { GNUNET_assert (3 == global_ret); agc = 3; GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &check_it, &agc); GNUNET_assert (agc == 0); global_ret = 2; } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { h = GNUNET_PEERINFO_connect (cfg); GNUNET_assert (NULL != h); add_peer (); ic = GNUNET_PEERINFO_iterate (h, GNUNET_NO, &pid, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15), &process, cls); } int main (int argc, char *argv[]) { global_ret = 3; if (0 != GNUNET_TESTING_service_run ("test-gnunet-peerinfo", "peerinfo", "test_peerinfo_api_data.conf", &run, NULL)) return 1; return global_ret; } /* end of test_peerinfo_api.c */ gnunet-0.10.1/src/peerinfo/Makefile.am0000644000175000017500000000565112320751517014456 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ peerinfo.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif lib_LTLIBRARIES = libgnunetpeerinfo.la libgnunetpeerinfo_la_SOURCES = \ peerinfo_api.c peerinfo.h \ peerinfo_api_notify.c libgnunetpeerinfo_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) \ $(LTLIBINTL) libgnunetpeerinfo_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libexec_PROGRAMS = \ gnunet-service-peerinfo gnunet_service_peerinfo_SOURCES = \ gnunet-service-peerinfo.c gnunet_service_peerinfo_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la if HAVE_BENCHMARKS PEERINFO_BENCHMARKS = \ perf_peerinfo_api endif if HAVE_TESTING check_PROGRAMS = \ test_peerinfo_shipped_hellos \ test_peerinfo_api \ test_peerinfo_api_friend_only \ test_peerinfo_api_notify_friend_only \ $(PEERINFO_BENCHMARKS) endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_peerinfo_shipped_hellos_SOURCES = \ test_peerinfo_shipped_hellos.c test_peerinfo_shipped_hellos_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_peerinfo_api_SOURCES = \ test_peerinfo_api.c test_peerinfo_api_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_peerinfo_api_friend_only_SOURCES = \ test_peerinfo_api_friend_only.c test_peerinfo_api_friend_only_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_peerinfo_api_notify_friend_only_SOURCES = \ test_peerinfo_api_notify_friend_only.c test_peerinfo_api_notify_friend_only_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_peerinfo_api_SOURCES = \ perf_peerinfo_api.c perf_peerinfo_api_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_peerinfo_api_data.conf gnunet-0.10.1/src/peerinfo/peerinfo_api.c0000644000175000017500000005171012255010511015210 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo/peerinfo_api.c * @brief API to access peerinfo service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "peerinfo.h" #define LOG(kind,...) GNUNET_log_from (kind, "peerinfo-api",__VA_ARGS__) /** * Entry in the transmission queue to PEERINFO service. We use * the same structure for queueing 'iteration' requests and * actual 'add' messages. */ struct GNUNET_PEERINFO_AddContext { /** * This is a linked list. */ struct GNUNET_PEERINFO_AddContext *next; /** * This is a linked list. */ struct GNUNET_PEERINFO_AddContext *prev; /** * Handle to the PEERINFO service. */ struct GNUNET_PEERINFO_Handle *h; /** * Function to call after request has been transmitted, or NULL. */ GNUNET_PEERINFO_Continuation cont; /** * Closure for 'cont'. */ void *cont_cls; /** * Number of bytes of the request message (follows after this struct). */ size_t size; }; /** * Context for an iteration request. */ struct GNUNET_PEERINFO_IteratorContext { /** * Kept in a DLL. */ struct GNUNET_PEERINFO_IteratorContext *next; /** * Kept in a DLL. */ struct GNUNET_PEERINFO_IteratorContext *prev; /** * Handle to the PEERINFO service. */ struct GNUNET_PEERINFO_Handle *h; /** * Function to call with the results. */ GNUNET_PEERINFO_Processor callback; /** * Closure for 'callback'. */ void *callback_cls; /** * Our entry in the transmission queue. */ struct GNUNET_PEERINFO_AddContext *ac; /** * Task responsible for timeout. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Timeout for the operation. */ struct GNUNET_TIME_Absolute timeout; /** * Peer we are interested in (only valid if iteration was restricted to one peer). */ struct GNUNET_PeerIdentity peer; /** * Is 'peer' set? */ int have_peer; /** * Set to GNUNET_YES if we are currently receiving replies from the * service. */ int request_transmitted; }; /** * Handle to the peerinfo service. */ struct GNUNET_PEERINFO_Handle { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * Head of transmission queue. */ struct GNUNET_PEERINFO_AddContext *ac_head; /** * Tail of transmission queue. */ struct GNUNET_PEERINFO_AddContext *ac_tail; /** * Handle for the current transmission request, or NULL if none is pending. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of iterator DLL. */ struct GNUNET_PEERINFO_IteratorContext *ic_head; /** * Tail of iterator DLL. */ struct GNUNET_PEERINFO_IteratorContext *ic_tail; /** * ID for a reconnect task. */ GNUNET_SCHEDULER_TaskIdentifier r_task; /** * Are we now receiving? */ int in_receive; }; /** * Connect to the peerinfo service. * * @param cfg configuration to use * @return NULL on error (configuration related, actual connection * establishment may happen asynchronously). */ struct GNUNET_PEERINFO_Handle * GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_PEERINFO_Handle *h; h = GNUNET_new (struct GNUNET_PEERINFO_Handle); h->client = GNUNET_CLIENT_connect ("peerinfo", cfg); h->cfg = cfg; return h; } /** * Disconnect from the peerinfo service. Note that all iterators must * have completed or have been cancelled by the time this function is * called (otherwise, calling this function is a serious error). * Furthermore, if 'GNUNET_PEERINFO_add_peer' operations are still * pending, they will be cancelled silently on disconnect. * * @param h handle to disconnect */ void GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h) { struct GNUNET_PEERINFO_AddContext *ac; struct GNUNET_PEERINFO_IteratorContext *ic; while (NULL != (ic = h->ic_head)) { GNUNET_break (GNUNET_YES == ic->request_transmitted); ic->request_transmitted = GNUNET_NO; GNUNET_PEERINFO_iterate_cancel (ic); } while (NULL != (ac = h->ac_head)) { GNUNET_CONTAINER_DLL_remove (h->ac_head, h->ac_tail, ac); if (NULL != ac->cont) ac->cont (ac->cont_cls, _("aborted due to explicit disconnect request")); GNUNET_free (ac); } if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->r_task) { GNUNET_SCHEDULER_cancel (h->r_task); h->r_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (h); } /** * Check if we have a request pending in the transmission queue and are * able to transmit it right now. If so, schedule transmission. * * @param h handle to the service */ static void trigger_transmit (struct GNUNET_PEERINFO_Handle *h); /** * Close the existing connection to PEERINFO and reconnect. * * @param h handle to the service */ static void reconnect (struct GNUNET_PEERINFO_Handle *h); /** * Task scheduled to re-try connecting to the peerinfo service. * * @param cls the 'struct GNUNET_PEERINFO_Handle' * @param tc scheduler context */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PEERINFO_Handle *h = cls; h->r_task = GNUNET_SCHEDULER_NO_TASK; reconnect (h); } /** * Close the existing connection to PEERINFO and reconnect. * * @param h handle to the service */ static void reconnect (struct GNUNET_PEERINFO_Handle *h) { if (GNUNET_SCHEDULER_NO_TASK != h->r_task) { GNUNET_SCHEDULER_cancel (h->r_task); h->r_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->in_receive = GNUNET_NO; h->client = GNUNET_CLIENT_connect ("peerinfo", h->cfg); if (NULL == h->client) { h->r_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task, h); return; } trigger_transmit (h); } /** * Transmit the request at the head of the transmission queue * and trigger continuation (if any). * * @param cls the 'struct GNUNET_PEERINFO_Handle' (with the queue) * @param size size of the buffer (0 on error) * @param buf where to copy the message * @return number of bytes copied to buf */ static size_t do_transmit (void *cls, size_t size, void *buf) { struct GNUNET_PEERINFO_Handle *h = cls; struct GNUNET_PEERINFO_AddContext *ac = h->ac_head; size_t ret; h->th = NULL; if (NULL == ac) return 0; /* request was cancelled in the meantime */ if (NULL == buf) { /* peerinfo service died */ LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Failed to transmit message to `%s' service.\n", "PEERINFO"); GNUNET_CONTAINER_DLL_remove (h->ac_head, h->ac_tail, ac); reconnect (h); if (NULL != ac->cont) ac->cont (ac->cont_cls, _("failed to transmit request (service down?)")); GNUNET_free (ac); return 0; } ret = ac->size; if (size < ret) { /* change in head of queue (i.e. cancel + add), try again */ trigger_transmit (h); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting request of size %u to `%s' service.\n", ret, "PEERINFO"); memcpy (buf, &ac[1], ret); GNUNET_CONTAINER_DLL_remove (h->ac_head, h->ac_tail, ac); trigger_transmit (h); if (NULL != ac->cont) ac->cont (ac->cont_cls, NULL); GNUNET_free (ac); return ret; } /** * Check if we have a request pending in the transmission queue and are * able to transmit it right now. If so, schedule transmission. * * @param h handle to the service */ static void trigger_transmit (struct GNUNET_PEERINFO_Handle *h) { struct GNUNET_PEERINFO_AddContext *ac; if (NULL == (ac = h->ac_head)) return; /* no requests queued */ if (NULL != h->th) return; /* request already pending */ if (NULL == h->client) { /* disconnected, try to reconnect */ reconnect (h); return; } h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ac->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &do_transmit, h); } /** * Add a host to the persistent list. This method operates in * semi-reliable mode: if the transmission is not completed by * the time 'GNUNET_PEERINFO_disconnect' is called, it will be * aborted. Furthermore, if a second HELLO is added for the * same peer before the first one was transmitted, PEERINFO may * merge the two HELLOs prior to transmission to the service. * * @param h handle to the peerinfo service * @param hello the verified (!) HELLO message * @param cont continuation to call when done, NULL is allowed * @param cont_cls closure for 'cont' * @return handle to cancel add operation; all pending * 'add' operations will be cancelled automatically * on disconnect, so it is not necessary to keep this * handle (unless 'cont' is NULL and at some point * calling 'cont' must be prevented) */ struct GNUNET_PEERINFO_AddContext * GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h, const struct GNUNET_HELLO_Message *hello, GNUNET_PEERINFO_Continuation cont, void *cont_cls) { uint16_t hs = GNUNET_HELLO_size (hello); struct GNUNET_PEERINFO_AddContext *ac; struct GNUNET_PeerIdentity peer; GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (hello, &peer)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding peer `%s' to PEERINFO database (%u bytes of `%s')\n", GNUNET_i2s (&peer), hs, "HELLO"); ac = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_AddContext) + hs); ac->h = h; ac->size = hs; ac->cont = cont; ac->cont_cls = cont_cls; memcpy (&ac[1], hello, hs); GNUNET_CONTAINER_DLL_insert_tail (h->ac_head, h->ac_tail, ac); trigger_transmit (h); return ac; } /** * Cancel pending 'add' operation. Must only be called before * either 'cont' or 'GNUNET_PEERINFO_disconnect' are invoked. * * @param ac handle for the add operation to cancel */ void GNUNET_PEERINFO_add_peer_cancel (struct GNUNET_PEERINFO_AddContext *ac) { struct GNUNET_PEERINFO_Handle *h = ac->h; GNUNET_CONTAINER_DLL_remove (h->ac_head, h->ac_tail, ac); GNUNET_free (ac); } /** * Type of a function to call when we receive a message from the * service. Call the iterator with the result and (if applicable) * continue to receive more messages or trigger processing the next * event (if applicable). * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_PEERINFO_Handle *h = cls; struct GNUNET_PEERINFO_IteratorContext *ic = h->ic_head; const struct InfoMessage *im; const struct GNUNET_HELLO_Message *hello; GNUNET_PEERINFO_Processor cb; struct GNUNET_PeerIdentity id; void *cb_cls; uint16_t ms; h->in_receive = GNUNET_NO; if (NULL == msg) { /* peerinfo service died, signal error */ if (NULL != ic) { cb = ic->callback; cb_cls = ic->callback_cls; GNUNET_PEERINFO_iterate_cancel (ic); } else { cb = NULL; } reconnect (h); if (NULL != cb) cb (cb_cls, NULL, NULL, _("Failed to receive response from `PEERINFO' service.")); return; } if (NULL == ic) { /* didn't expect a response, reconnect */ reconnect (h); return; } ic->request_transmitted = GNUNET_NO; cb = ic->callback; cb_cls = ic->callback_cls; if (GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END == ntohs (msg->type)) { /* normal end of list of peers, signal end, process next pending request */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Received end of list of peers from `%s' service\n", "PEERINFO"); GNUNET_PEERINFO_iterate_cancel (ic); trigger_transmit (h); if ( (GNUNET_NO == h->in_receive) && (NULL != h->ic_head) ) { h->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &peerinfo_handler, h, GNUNET_TIME_absolute_get_remaining (h->ic_head->timeout)); } if (NULL != cb) cb (cb_cls, NULL, NULL, NULL); return; } ms = ntohs (msg->size); if ((ms < sizeof (struct InfoMessage)) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_PEERINFO_INFO)) { /* malformed message */ GNUNET_break (0); GNUNET_PEERINFO_iterate_cancel (ic); reconnect (h); if (NULL != cb) cb (cb_cls, NULL, NULL, _("Received invalid message from `PEERINFO' service.")); return; } im = (const struct InfoMessage *) msg; GNUNET_break (0 == ntohl (im->reserved)); if ( (GNUNET_YES == ic->have_peer) && (0 != memcmp (&ic->peer, &im->peer, sizeof (struct GNUNET_PeerIdentity))) ) { /* bogus message (from a different iteration call?); out of sequence! */ LOG (GNUNET_ERROR_TYPE_ERROR, "Received HELLO for peer `%s', expected peer `%s'\n", GNUNET_i2s (&im->peer), GNUNET_i2s (&ic->peer)); GNUNET_break (0); GNUNET_PEERINFO_iterate_cancel (ic); reconnect (h); if (NULL != cb) cb (cb_cls, NULL, NULL, _("Received invalid message from `PEERINFO' service.")); return; } hello = NULL; if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader)) { hello = (const struct GNUNET_HELLO_Message *) &im[1]; if (ms != sizeof (struct InfoMessage) + GNUNET_HELLO_size (hello)) { /* malformed message */ GNUNET_break (0); GNUNET_PEERINFO_iterate_cancel (ic); reconnect (h); if (NULL != cb) cb (cb_cls, NULL, NULL, _("Received invalid message from `PEERINFO' service.")); return; } if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &id)) { /* malformed message */ GNUNET_break (0); GNUNET_PEERINFO_iterate_cancel (ic); reconnect (h); if (NULL != cb) cb (cb_cls, NULL, NULL, _("Received invalid message from `PEERINFO' service.")); return; } if (0 != memcmp (&im->peer, &id, sizeof (struct GNUNET_PeerIdentity))) { /* malformed message */ GNUNET_break (0); GNUNET_PEERINFO_iterate_cancel (ic); reconnect (h); if (NULL != cb) cb (cb_cls, NULL, NULL, _("Received invalid message from `PEERINFO' service.")); return; } } /* normal data message */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes of `%s' information about peer `%s' from `%s' service\n", (hello == NULL) ? 0 : (unsigned int) GNUNET_HELLO_size (hello), "HELLO", GNUNET_i2s (&im->peer), "PEERINFO"); h->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &peerinfo_handler, h, GNUNET_TIME_absolute_get_remaining (ic->timeout)); if (NULL != cb) cb (cb_cls, &im->peer, hello, NULL); } /** * We've transmitted the iteration request. Now get ready to process * the results (or handle transmission error). * * @param cls the 'struct GNUNET_PEERINFO_IteratorContext' * @param emsg error message, NULL if transmission worked */ static void iterator_start_receive (void *cls, const char *emsg) { struct GNUNET_PEERINFO_IteratorContext *ic = cls; struct GNUNET_PEERINFO_Handle *h = ic->h; GNUNET_PEERINFO_Processor cb; void *cb_cls; ic->ac = NULL; if (NULL != emsg) { cb = ic->callback; cb_cls = ic->callback_cls; GNUNET_PEERINFO_iterate_cancel (ic); reconnect (h); if (NULL != cb) cb (cb_cls, NULL, NULL, emsg); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for response from `%s' service.\n", "PEERINFO"); ic->request_transmitted = GNUNET_YES; if (GNUNET_NO == h->in_receive) { h->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &peerinfo_handler, h, GNUNET_TIME_absolute_get_remaining (ic->timeout)); } } /** * Peerinfo iteration request has timed out. * * @param cls the 'struct GNUNET_PEERINFO_IteratorContext*' * @param tc scheduler context */ static void signal_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PEERINFO_IteratorContext *ic = cls; GNUNET_PEERINFO_Processor cb; void *cb_cls; ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; cb = ic->callback; cb_cls = ic->callback_cls; GNUNET_PEERINFO_iterate_cancel (ic); if (NULL != cb) cb (cb_cls, NULL, NULL, _("Timeout transmitting iteration request to `PEERINFO' service.")); } /** * Call a method for each known matching host. The callback method * will be invoked once for each matching host and then finally once * with a NULL pointer. After that final invocation, the iterator * context must no longer be used. * * Instead of calling this function with 'peer == NULL' it is often * better to use 'GNUNET_PEERINFO_notify'. * * @param h handle to the peerinfo service * @param include_friend_only include HELLO messages for friends only * @param peer restrict iteration to this peer only (can be NULL) * @param timeout how long to wait until timing out * @param callback the method to call for each peer * @param callback_cls closure for callback * @return iterator context */ struct GNUNET_PEERINFO_IteratorContext * GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h, int include_friend_only, const struct GNUNET_PeerIdentity *peer, struct GNUNET_TIME_Relative timeout, GNUNET_PEERINFO_Processor callback, void *callback_cls) { struct ListAllPeersMessage *lapm; struct ListPeerMessage *lpm; struct GNUNET_PEERINFO_IteratorContext *ic; struct GNUNET_PEERINFO_AddContext *ac; ic = GNUNET_new (struct GNUNET_PEERINFO_IteratorContext); if (NULL == peer) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting list of peers from PEERINFO service\n"); ac = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_AddContext) + sizeof (struct ListAllPeersMessage)); ac->size = sizeof (struct ListAllPeersMessage); lapm = (struct ListAllPeersMessage *) &ac[1]; lapm->header.size = htons (sizeof (struct ListAllPeersMessage)); lapm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL); lapm->include_friend_only = htonl (include_friend_only); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting information on peer `%4s' from PEERINFO service\n", GNUNET_i2s (peer)); ac = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_AddContext) + sizeof (struct ListPeerMessage)); ac->size = sizeof (struct ListPeerMessage); lpm = (struct ListPeerMessage *) &ac[1]; lpm->header.size = htons (sizeof (struct ListPeerMessage)); lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET); lpm->include_friend_only = htonl (include_friend_only); memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity)); ic->have_peer = GNUNET_YES; ic->peer = *peer; } ic->h = h; ic->ac = ac; ic->callback = callback; ic->callback_cls = callback_cls; ic->timeout = GNUNET_TIME_relative_to_absolute (timeout); ic->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &signal_timeout, ic); ac->cont = &iterator_start_receive; ac->cont_cls = ic; GNUNET_CONTAINER_DLL_insert_tail (h->ac_head, h->ac_tail, ac); GNUNET_CONTAINER_DLL_insert_tail (h->ic_head, h->ic_tail, ic); trigger_transmit (h); return ic; } /** * Cancel an iteration over peer information. * * @param ic context of the iterator to cancel */ void GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic) { struct GNUNET_PEERINFO_Handle *h; h = ic->h; if (GNUNET_SCHEDULER_NO_TASK != ic->timeout_task) { GNUNET_SCHEDULER_cancel (ic->timeout_task); ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; } ic->callback = NULL; if (GNUNET_YES == ic->request_transmitted) return; /* need to finish processing */ GNUNET_CONTAINER_DLL_remove (h->ic_head, h->ic_tail, ic); if (NULL != ic->ac) { GNUNET_CONTAINER_DLL_remove (h->ac_head, h->ac_tail, ic->ac); GNUNET_free (ic->ac); } GNUNET_free (ic); } /* end of peerinfo_api.c */ gnunet-0.10.1/src/hostlist/0000755000175000017500000000000012320755625012541 500000000000000gnunet-0.10.1/src/hostlist/test_gnunet_daemon_hostlist_peer2.conf0000644000175000017500000000155212225230043022225 00000000000000@INLINE@ test_hostlist_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-hostlist-peer-2/ [transport-tcp] PORT = 22968 [arm] PORT = 22966 DEFAULTSERVICES = hostlist topology UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 22967 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 22964 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 22969 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 22965 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [core] PORT = 22970 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-core.sock [hostlist] HTTPPORT = 12981 HOSTLISTFILE = hostlists_peer2.file OPTIONS = -b -p SERVERS = http://localhost:12980/ [ats] PORT = 22971 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-ats.sock gnunet-0.10.1/src/hostlist/hostlist.conf0000644000175000017500000000105212252137227015173 00000000000000[hostlist] # port for hostlist http server HTTPPORT = 8080 HOSTLISTFILE = $GNUNET_CONFIG_HOME/hostlist/learned.txt BINARY = gnunet-daemon-hostlist # Options: # -p : provide a hostlist as a hostlist servers # -b : bootstrap using configured hostlist servers # -e : enable learning advertised hostlists # -a : advertise hostlist to other servers OPTIONS = -b SERVERS = http://v10.gnunet.org/hostlist # http://ioerror.gnunet.org:65535/ # proxy for downloading hostlists HTTP-PROXY = # bind hostlist http server to a specific IPv4 or IPv6 # BINDTOIP = gnunet-0.10.1/src/hostlist/test_gnunet_daemon_hostlist_data.conf0000644000175000017500000000053012225230043022114 00000000000000@INLINE@ test_hostlist_defaults.conf [transport-tcp] PORT = 12968 [arm] PORT = 12966 DEFAULTSERVICES = hostlist topology [statistics] PORT = 12967 [resolver] PORT = 12964 [peerinfo] PORT = 12969 [transport] PORT = 12965 [core] PORT = 12970 [hostlist] HTTPPORT = 28080 SERVERS = http://gnunet.org:8080/ PORT = 23354 HOSTNAME = localhost gnunet-0.10.1/src/hostlist/test_gnunet_daemon_hostlist_learning.c0000644000175000017500000003714712301361473022324 00000000000000/* This file is part of GNUnet (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/test_gnunet_daemon_hostlist_learning.c * @brief test for gnunet_daemon_hostslist.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_core_service.h" #include "gnunet_transport_service.h" #include "gnunet_resolver_service.h" #include "gnunet_statistics_service.h" #define MAX_URL_LEN 1000 /** * How long until wait until testcases fails */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 180) #define CHECK_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) struct PeerContext { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_TRANSPORT_Handle *th; struct GNUNET_MessageHeader *hello; struct GNUNET_CORE_Handle *core; struct GNUNET_STATISTICS_Handle *stats; struct GNUNET_OS_Process *arm_proc; }; static int timeout; static int adv_sent; static int adv_arrived; static int learned_hostlist_saved; static int learned_hostlist_downloaded; static char *current_adv_uri; static const struct GNUNET_CONFIGURATION_Handle *cfg; static GNUNET_SCHEDULER_TaskIdentifier timeout_task; static GNUNET_SCHEDULER_TaskIdentifier check_task; static struct PeerContext adv_peer; static struct PeerContext learn_peer; static struct GNUNET_STATISTICS_GetHandle *download_stats; static struct GNUNET_STATISTICS_GetHandle *urisrecv_stat; static struct GNUNET_STATISTICS_GetHandle *advsent_stat; static void shutdown_testcase () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown testcase....\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != download_stats) { GNUNET_STATISTICS_get_cancel (download_stats); download_stats = NULL; } if (NULL != urisrecv_stat) { GNUNET_STATISTICS_get_cancel (urisrecv_stat); urisrecv_stat = NULL; } if (NULL != advsent_stat) { GNUNET_STATISTICS_get_cancel (advsent_stat); advsent_stat = NULL; } if (NULL != adv_peer.stats) { GNUNET_STATISTICS_destroy (adv_peer.stats, GNUNET_NO); adv_peer.stats = NULL; } if (NULL != learn_peer.stats) { GNUNET_STATISTICS_destroy (learn_peer.stats, GNUNET_NO); learn_peer.stats = NULL; } if (check_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (check_task); check_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != current_adv_uri) { GNUNET_free (current_adv_uri); current_adv_uri = NULL; } if (adv_peer.th != NULL) { GNUNET_TRANSPORT_disconnect (adv_peer.th); adv_peer.th = NULL; } if (learn_peer.th != NULL) { GNUNET_TRANSPORT_disconnect (learn_peer.th); learn_peer.th = NULL; } if (adv_peer.core != NULL) { GNUNET_CORE_disconnect (adv_peer.core); adv_peer.core = NULL; } if (learn_peer.core != NULL) { GNUNET_CORE_disconnect (learn_peer.core); learn_peer.core = NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Killing hostlist server ARM process.\n"); if (0 != GNUNET_OS_process_kill (adv_peer.arm_proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); if (GNUNET_OS_process_wait (adv_peer.arm_proc) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_OS_process_destroy (adv_peer.arm_proc); adv_peer.arm_proc = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Killing hostlist client ARM process.\n"); if (0 != GNUNET_OS_process_kill (learn_peer.arm_proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); if (GNUNET_OS_process_wait (learn_peer.arm_proc) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_OS_process_destroy (learn_peer.arm_proc); learn_peer.arm_proc = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown complete....\n"); } /** * Timeout, give up. */ static void timeout_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout while executing testcase, test failed.\n"); timeout = GNUNET_YES; shutdown_testcase (); } static void process_downloads_done (void *cls, int success) { download_stats = NULL; } static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_testcase (); } static int process_downloads (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { if ((value >= 2) && (learned_hostlist_downloaded == GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer has successfully downloaded advertised URI\n"); learned_hostlist_downloaded = GNUNET_YES; if ((learned_hostlist_saved == GNUNET_YES) && (adv_sent == GNUNET_YES)) { GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } return GNUNET_OK; } static void process_uris_recv_done (void *cls, int success) { urisrecv_stat = NULL; } static int process_uris_recv (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { if (((struct PeerContext *) cls == &learn_peer) && (value == 1) && (learned_hostlist_saved == GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer has successfully saved advertised URI\n"); learned_hostlist_saved = GNUNET_YES; if ((learned_hostlist_downloaded == GNUNET_YES) && (adv_sent == GNUNET_YES)) { GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } return GNUNET_OK; } static void process_adv_sent_done (void *cls, int success) { advsent_stat = NULL; } static int process_adv_sent (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { if ((value >= 1) && (adv_sent == GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Server has successfully sent advertisement\n"); adv_sent = GNUNET_YES; if ((learned_hostlist_downloaded == GNUNET_YES) && (learned_hostlist_saved == GNUNET_YES)) { GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } return GNUNET_OK; } /** * Check the server statistics regularly */ static void check_statistics (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { char *stat; check_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_asprintf (&stat, gettext_noop ("# advertised URI `%s' downloaded"), current_adv_uri); if (NULL != learn_peer.stats) { if (NULL != download_stats) GNUNET_STATISTICS_get_cancel (download_stats); download_stats = GNUNET_STATISTICS_get (learn_peer.stats, "hostlist", stat, GNUNET_TIME_UNIT_MINUTES, &process_downloads_done, &process_downloads, &learn_peer); if (NULL != urisrecv_stat) GNUNET_STATISTICS_get_cancel (urisrecv_stat); urisrecv_stat = GNUNET_STATISTICS_get (learn_peer.stats, "hostlist", gettext_noop ("# advertised hostlist URIs"), GNUNET_TIME_UNIT_MINUTES, &process_uris_recv_done, &process_uris_recv, &learn_peer); } GNUNET_free (stat); if (NULL != adv_peer.stats) { if (NULL != advsent_stat) GNUNET_STATISTICS_get_cancel (advsent_stat); advsent_stat = GNUNET_STATISTICS_get (adv_peer.stats, "hostlist", gettext_noop ("# hostlist advertisements send"), GNUNET_TIME_UNIT_MINUTES, &process_adv_sent_done, &process_adv_sent, NULL); } check_task = GNUNET_SCHEDULER_add_delayed (CHECK_INTERVALL, &check_statistics, NULL); } /** * Core handler for p2p hostlist advertisements */ static int ad_arrive_handler (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { char *hostname; char *expected_uri; unsigned long long port; const struct GNUNET_MessageHeader *incoming; const char *end; if (-1 == GNUNET_CONFIGURATION_get_value_number (adv_peer.cfg, "HOSTLIST", "HTTPPORT", &port)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not read advertising server's configuration\n"); return GNUNET_SYSERR; } if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (adv_peer.cfg, "HOSTLIST", "EXTERNAL_DNS_NAME", &hostname)) hostname = GNUNET_RESOLVER_local_fqdn_get (); GNUNET_asprintf (&expected_uri, "http://%s:%u/", hostname != NULL ? hostname : "localhost", (unsigned int) port); incoming = (const struct GNUNET_MessageHeader *) message; end = (const char *) &incoming[1]; if ('\0' != end[ntohs (message->size) - sizeof (struct GNUNET_MessageHeader) - 1]) { GNUNET_break (0); GNUNET_free (expected_uri); GNUNET_free_non_null (hostname); return GNUNET_SYSERR; } current_adv_uri = GNUNET_strdup (end); if (0 == strcmp (expected_uri, current_adv_uri)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received hostlist advertisement with URI `%s' as expected\n", current_adv_uri); adv_arrived = GNUNET_YES; adv_sent = GNUNET_YES; } else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected URI `%s' and received URI `%s' differ\n", expected_uri, current_adv_uri); GNUNET_free (expected_uri); GNUNET_free_non_null (hostname); return GNUNET_OK; } /** * List of handlers if we are learning. */ static struct GNUNET_CORE_MessageHandler learn_handlers[] = { {&ad_arrive_handler, GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT, 0}, {NULL, 0, 0} }; static void setup_learn_peer (struct PeerContext *p, const char *cfgname) { char *filename; unsigned int result; char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); p->cfg = GNUNET_CONFIGURATION_create (); p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-arm", "-c", cfgname, NULL); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (p->cfg, "HOSTLIST", "HOSTLISTFILE", &filename)) { if (GNUNET_YES == GNUNET_DISK_file_test (filename)) { result = UNLINK (filename); if (result == 0) GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Hostlist file `%s' was removed\n"), filename); } GNUNET_free (filename); } p->core = GNUNET_CORE_connect (p->cfg, NULL, NULL, NULL, NULL, NULL, GNUNET_NO, NULL, GNUNET_NO, learn_handlers); GNUNET_assert (NULL != p->core); p->stats = GNUNET_STATISTICS_create ("hostlist", p->cfg); GNUNET_assert (NULL != p->stats); GNUNET_free (binary); } static void setup_adv_peer (struct PeerContext *p, const char *cfgname) { char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); p->cfg = GNUNET_CONFIGURATION_create (); p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-arm", "-c", cfgname, NULL); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); p->stats = GNUNET_STATISTICS_create ("hostlist", p->cfg); GNUNET_assert (NULL != p->stats); GNUNET_free (binary); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { timeout = GNUNET_NO; adv_sent = GNUNET_NO; adv_arrived = 0; learned_hostlist_saved = GNUNET_NO; learned_hostlist_downloaded = GNUNET_NO; cfg = c; setup_adv_peer (&adv_peer, "test_learning_adv_peer.conf"); setup_learn_peer (&learn_peer, "test_learning_learn_peer.conf"); timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_error, NULL); check_task = GNUNET_SCHEDULER_add_delayed (CHECK_INTERVALL, &check_statistics, NULL); } static int check () { unsigned int failed; char *const argv[] = { "test-gnunet-daemon-hostlist-learning", "-c", "learning_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-gnunet-daemon-hostlist-learning", "nohelp", options, &run, NULL); failed = GNUNET_NO; if (timeout == GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Testcase timeout\n"); failed = GNUNET_YES; } if (adv_arrived != GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Learning peer did not receive advertisement from server\n"); failed = GNUNET_YES; } if (learned_hostlist_saved == GNUNET_NO) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Advertised hostlist was not saved in datastore\n"); failed = GNUNET_YES; } if (learned_hostlist_downloaded == GNUNET_NO) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Advertised hostlist could not be downloaded from server\n"); failed = GNUNET_YES; } if (adv_sent == GNUNET_NO) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Advertised was not sent from server to client\n"); failed = GNUNET_YES; } if (GNUNET_YES == failed) return GNUNET_YES; return GNUNET_NO; } int main (int argc, char *argv[]) { int ret; GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2"); GNUNET_log_setup ("test-gnunet-daemon-hostlist", "WARNING", NULL); #if !WINDOWS system ("gnunet-peerinfo -s -c test_learning_adv_peer.conf > /dev/null"); system ("gnunet-peerinfo -s -c test_learning_learn_peer.conf > /dev/null"); #else system ("gnunet-peerinfo -s -c test_learning_adv_peer.conf > NUL"); system ("gnunet-peerinfo -s -c test_learning_learn_peer.conf > NUL"); #endif ret = check (); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2"); if (GNUNET_YES == GNUNET_DISK_file_test ("hostlists_learn_peer.file")) { if (0 == UNLINK ("hostlists_learn_peer.file")) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Hostlist file hostlists_learn_peer.file was removed\n"); } return ret; } /* end of test_gnunet_daemon_hostlist_learning.c */ gnunet-0.10.1/src/hostlist/gnunet-daemon-hostlist.c0000644000175000017500000002112412261236531017227 00000000000000/* This file is part of GNUnet. (C) 2007, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/gnunet-daemon-hostlist.c * @brief code for bootstrapping via hostlist servers * @author Christian Grothoff */ #include #include "platform.h" #include "hostlist-client.h" #include "gnunet_core_service.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #if HAVE_MHD #include "hostlist-server.h" /** * Set if we are allowed to advertise our hostlist to others. */ static int advertising; /** * Set if the user wants us to run a hostlist server. */ static int provide_hostlist; /** * Handle to hostlist server's connect handler */ static GNUNET_CORE_ConnectEventHandler server_ch; /** * Handle to hostlist server's disconnect handler */ static GNUNET_CORE_DisconnectEventHandler server_dh; #endif /** * Set if we are allowed to learn about peers by accessing * hostlist servers. */ static int bootstrapping; /** * Set if the user allows us to learn about new hostlists * from the network. */ static int learning; /** * Statistics handle. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Handle to the core service (NULL until we've connected to it). */ static struct GNUNET_CORE_Handle *core; /** * Handle to the hostlist client's advertisement handler */ static GNUNET_CORE_MessageCallback client_adv_handler; /** * Handle to hostlist client's connect handler */ static GNUNET_CORE_ConnectEventHandler client_ch; /** * Handle to hostlist client's disconnect handler */ static GNUNET_CORE_DisconnectEventHandler client_dh; GNUNET_NETWORK_STRUCT_BEGIN /** * A HOSTLIST_ADV message is used to exchange information about * hostlist advertisements. This struct is always * followed by the actual url under which the hostlist can be obtained: * * 1) transport-name (0-terminated) * 2) address-length (uint32_t, network byte order; possibly * unaligned!) * 3) address expiration (GNUNET_TIME_AbsoluteNBO); possibly * unaligned!) * 4) address (address-length bytes; possibly unaligned!) */ struct GNUNET_HOSTLIST_ADV_Message { /** * Type will be GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT. */ struct GNUNET_MessageHeader header; /** * Always zero (for alignment). */ uint32_t reserved GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END static struct GNUNET_PeerIdentity me; static void core_init (void *cls, const struct GNUNET_PeerIdentity *my_identity) { me = *my_identity; } /** * Core handler for p2p hostlist advertisements * * @param cls closure * @param peer identity of the sender * @param message advertisement message we got * @return #GNUNET_OK on success */ static int advertisement_handler (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { GNUNET_assert (NULL != client_adv_handler); return (*client_adv_handler) (cls, peer, message); } /** * Method called whenever a given peer connects. Wrapper to call both * client's and server's functions * * @param cls closure * @param peer peer identity this notification is about */ static void connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { if (0 == memcmp (&me, peer, sizeof (struct GNUNET_PeerIdentity))) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "A new peer connected, notifying client and server\n"); if (NULL != client_ch) (*client_ch) (cls, peer); #if HAVE_MHD if (NULL != server_ch) (*server_ch) (cls, peer); #endif } /** * Method called whenever a given peer disconnects. Wrapper to call * both client's and server's functions * * @param cls closure * @param peer peer identity this notification is about */ static void disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { if (0 == memcmp (&me, peer, sizeof (struct GNUNET_PeerIdentity))) return; /* call hostlist client disconnect handler */ if (NULL != client_dh) (*client_dh) (cls, peer); #if HAVE_MHD /* call hostlist server disconnect handler */ if (NULL != server_dh) (*server_dh) (cls, peer); #endif } /** * Last task run during shutdown. Disconnects us from * the other services. */ static void cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist daemon is shutting down\n"); if (core != NULL) { GNUNET_CORE_disconnect (core); core = NULL; } if (bootstrapping) { GNUNET_HOSTLIST_client_stop (); } #if HAVE_MHD if (provide_hostlist) { GNUNET_HOSTLIST_server_stop (); } #endif if (stats != NULL) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_CORE_MessageHandler learn_handlers[] = { {&advertisement_handler, GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT, 0}, {NULL, 0, 0} }; static const struct GNUNET_CORE_MessageHandler no_learn_handlers[] = { {NULL, 0, 0} }; if ((!bootstrapping) && (!learning) #if HAVE_MHD && (!provide_hostlist) #endif ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("None of the functions for the hostlist daemon were enabled. I have no reason to run!\n")); return; } stats = GNUNET_STATISTICS_create ("hostlist", cfg); if (bootstrapping) GNUNET_HOSTLIST_client_start (cfg, stats, &client_ch, &client_dh, &client_adv_handler, learning); core = GNUNET_CORE_connect (cfg, NULL, &core_init, &connect_handler, &disconnect_handler, NULL, GNUNET_NO, NULL, GNUNET_NO, learning ? learn_handlers : no_learn_handlers); #if HAVE_MHD if (provide_hostlist) GNUNET_HOSTLIST_server_start (cfg, stats, core, &server_ch, &server_dh, advertising); #endif GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleaning_task, NULL); if (NULL == core) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to `%s' service.\n"), "core"); GNUNET_SCHEDULER_shutdown (); return; } } /** * The main function for the hostlist daemon. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { #if HAVE_MHD {'a', "advertise", NULL, gettext_noop ("advertise our hostlist to other peers"), GNUNET_NO, &GNUNET_GETOPT_set_one, &advertising}, #endif {'b', "bootstrap", NULL, gettext_noop ("bootstrap using hostlists (it is highly recommended that you always use this option)"), GNUNET_NO, &GNUNET_GETOPT_set_one, &bootstrapping}, {'e', "enable-learning", NULL, gettext_noop ("enable learning about hostlist servers from other peers"), GNUNET_NO, &GNUNET_GETOPT_set_one, &learning}, #if HAVE_MHD {'p', "provide-hostlist", NULL, gettext_noop ("provide a hostlist server"), GNUNET_NO, &GNUNET_GETOPT_set_one, &provide_hostlist}, #endif GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; GNUNET_log_setup ("hostlist", "WARNING", NULL); ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "hostlist", _("GNUnet hostlist server and client"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-daemon-hostlist.c */ gnunet-0.10.1/src/hostlist/hostlist-client.h0000644000175000017500000000603312225777503015764 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/hostlist-client.h * @brief hostlist support. Downloads HELLOs via HTTP. * @author Christian Grothoff */ #ifndef HOSTLIST_CLIENT_H #define HOSTLIST_CLIENT_H #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "gnunet_util_lib.h" #include "gnunet_time_lib.h" /** * Maximum number of hostlist that are saved */ #define MAX_NUMBER_HOSTLISTS 30 /** * Time intervall hostlists are saved to disk */ #define SAVING_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) /** * Time interval between two hostlist tests */ #define TESTING_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) /** * Time interval for download dispatcher before a download is re-scheduled */ #define WAITING_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * Defines concerning the hostlist quality metric */ /** * Initial quality of a new created hostlist */ #define HOSTLIST_INITIAL 10000 /** * Value subtracted each time a hostlist download fails */ #define HOSTLIST_FAILED_DOWNLOAD 100 /** * Value added each time a hostlist download is successful */ #define HOSTLIST_SUCCESSFUL_DOWNLOAD 100 /** * Value added for each valid HELLO recived during a hostlist download */ #define HOSTLIST_SUCCESSFUL_HELLO 1 /** * Start downloading hostlists from hostlist servers as necessary. * * @param c the configuration to use * @param st hande for publishing statistics * @param ch set to handler for connect notifications * @param dh set to handler for disconnect notifications * @param msgh set to handler for message handler notifications * @param learn set if client is learning new hostlists * @return GNUNET_OK on success */ int GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_STATISTICS_Handle *st, GNUNET_CORE_ConnectEventHandler *ch, GNUNET_CORE_DisconnectEventHandler *dh, GNUNET_CORE_MessageCallback *msgh, int learn); /** * Stop downloading hostlists from hostlist servers as necessary. */ void GNUNET_HOSTLIST_client_stop (void); #endif /* end of hostlist-client.h */ gnunet-0.10.1/src/hostlist/test_learning_learn_peer2.conf0000644000175000017500000000144212225230043020427 00000000000000@INLINE@ test_hostlist_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-hostlist-peer-3/ [transport-tcp] PORT = 32968 [arm] PORT = 32966 DEFAULTSERVICES = topology hostlist UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p3-service-arm.sock [statistics] PORT = 32967 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p3-service-statistics.sock [resolver] PORT = 32964 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p3-service-resolver.sock [peerinfo] PORT = 32969 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p3-service-peerinfo.sock [transport] PORT = 32965 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p3-service-transport.sock [core] PORT = 32970 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p3-service-core.sock [hostlist] HTTPPORT = 32980 HOSTLISTFILE = hostlists_learn_peer2.file OPTIONS = -b -e SERVERS = http://localhost:12981/ gnunet-0.10.1/src/hostlist/hostlist-server.c0000644000175000017500000005327312272513412016004 00000000000000/* This file is part of GNUnet. (C) 2008, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/hostlist-server.c * @author Christian Grothoff, Matthias Wachs * @brief application to provide an integrated hostlist HTTP server */ #include "platform.h" #include #include "hostlist-server.h" #include "gnunet_hello_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet-daemon-hostlist.h" #include "gnunet_resolver_service.h" /** * Handle to the HTTP server as provided by libmicrohttpd for IPv6. */ static struct MHD_Daemon *daemon_handle_v6; /** * Handle to the HTTP server as provided by libmicrohttpd for IPv4. */ static struct MHD_Daemon *daemon_handle_v4; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * For keeping statistics. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Handle to the core service (NULL until we've connected to it). */ static struct GNUNET_CORE_Handle *core; /** * Handle to the peerinfo notify service (NULL until we've connected to it). */ static struct GNUNET_PEERINFO_NotifyContext *notify; /** * Our primary task for IPv4. */ static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v4; /** * Our primary task for IPv6. */ static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v6; /** * Our canonical response. */ static struct MHD_Response *response; /** * Handle for accessing peerinfo service. */ static struct GNUNET_PEERINFO_Handle *peerinfo; /** * Set if we are allowed to advertise our hostlist to others. */ static int advertising; /** * Buffer for the hostlist address */ static char *hostlist_uri; /** * Context for host processor. */ struct HostSet { unsigned int size; char *data; struct GNUNET_PEERINFO_IteratorContext *pitr; }; /** * NULL if we are not currenlty iterating over peer information. */ static struct HostSet *builder; /** * Function that assembles our response. */ static void finish_response () { if (NULL != response) MHD_destroy_response (response); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating hostlist response with %u bytes\n", (unsigned int) builder->size); response = MHD_create_response_from_data (builder->size, builder->data, MHD_YES, MHD_NO); if ((NULL == daemon_handle_v4) && (NULL == daemon_handle_v6)) { MHD_destroy_response (response); response = NULL; } GNUNET_STATISTICS_set (stats, gettext_noop ("bytes in hostlist"), builder->size, GNUNET_YES); GNUNET_free (builder); builder = NULL; } /** * Set 'cls' to GNUNET_YES (we have an address!). * * @param cls closure, an 'int*' * @param address the address (ignored) * @param expiration expiration time (call is ignored if this is in the past) * @return GNUNET_SYSERR to stop iterating (unless expiration has occured) */ static int check_has_addr (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { int *arg = cls; if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) { GNUNET_STATISTICS_update (stats, gettext_noop ("expired addresses encountered"), 1, GNUNET_YES); return GNUNET_YES; /* ignore this address */ } *arg = GNUNET_YES; return GNUNET_SYSERR; } /** * Callback that processes each of the known HELLOs for the * hostlist response construction. */ static void host_processor (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { size_t old; size_t s; int has_addr; if (NULL != err_msg) { GNUNET_assert (NULL == peer); builder->pitr = NULL; GNUNET_free_non_null (builder->data); GNUNET_free (builder); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Error in communication with PEERINFO service: %s\n"), err_msg); return; } if (NULL == peer) { builder->pitr = NULL; finish_response (); return; } if (NULL == hello) return; has_addr = GNUNET_NO; GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &check_has_addr, &has_addr); if (GNUNET_NO == has_addr) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "HELLO for peer `%4s' has no address, not suitable for hostlist!\n", GNUNET_i2s (peer)); GNUNET_STATISTICS_update (stats, gettext_noop ("HELLOs without addresses encountered (ignored)"), 1, GNUNET_NO); return; } old = builder->size; s = GNUNET_HELLO_size (hello); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u bytes of `%s' from peer `%s' for hostlist.\n", (unsigned int) s, "HELLO", GNUNET_i2s (peer)); if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) || (old + s >= MAX_BYTES_PER_HOSTLISTS)) { GNUNET_STATISTICS_update (stats, gettext_noop ("bytes not included in hostlist (size limit)"), s, GNUNET_NO); return; /* too large, skip! */ } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding peer `%s' to hostlist (%u bytes)\n", GNUNET_i2s (peer), (unsigned int) s); GNUNET_array_grow (builder->data, builder->size, old + s); memcpy (&builder->data[old], hello, s); } /** * Hostlist access policy (very permissive, allows everything). */ static int accept_policy_callback (void *cls, const struct sockaddr *addr, socklen_t addrlen) { if (NULL == response) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request for hostlist, but I am not yet ready; rejecting!\n"); return MHD_NO; } return MHD_YES; /* accept all */ } /** * Main request handler. */ static int access_handler_callback (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t * upload_data_size, void **con_cls) { static int dummy; if (0 != strcmp (method, MHD_HTTP_METHOD_GET)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Refusing `%s' request to hostlist server\n"), method); GNUNET_STATISTICS_update (stats, gettext_noop ("hostlist requests refused (not HTTP GET)"), 1, GNUNET_YES); return MHD_NO; } if (NULL == *con_cls) { (*con_cls) = &dummy; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE reply\n"); return MHD_YES; /* send 100 continue */ } if (0 != *upload_data_size) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Refusing `%s' request with %llu bytes of upload data\n"), method, (unsigned long long) *upload_data_size); GNUNET_STATISTICS_update (stats, gettext_noop ("hostlist requests refused (upload data)"), 1, GNUNET_YES); return MHD_NO; /* do not support upload data */ } if (NULL == response) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not handle hostlist request since I do not have a response yet\n")); GNUNET_STATISTICS_update (stats, gettext_noop ("hostlist requests refused (not ready)"), 1, GNUNET_YES); return MHD_NO; /* internal error, no response yet */ } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received request for our hostlist\n")); GNUNET_STATISTICS_update (stats, gettext_noop ("hostlist requests processed"), 1, GNUNET_YES); return MHD_queue_response (connection, MHD_HTTP_OK, response); } /** * Handler called by core when core is ready to transmit message * @param cls closure * @param size size of buffer to copy message to * @param buf buffer to copy message to */ static size_t adv_transmit_ready (void *cls, size_t size, void *buf) { static uint64_t hostlist_adv_count; size_t transmission_size; size_t uri_size; /* Including \0 termination! */ struct GNUNET_MessageHeader header; char *cbuf; if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed, buffer invalid!\n"); return 0; } uri_size = strlen (hostlist_uri) + 1; transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size; header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT); header.size = htons (transmission_size); GNUNET_assert (size >= transmission_size); memcpy (buf, &header, sizeof (struct GNUNET_MessageHeader)); cbuf = buf; memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)], hostlist_uri, uri_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent advertisement message: Copied %u bytes into buffer!\n", (unsigned int) transmission_size); hostlist_adv_count++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " # Sent advertisement message: %u\n", hostlist_adv_count); GNUNET_STATISTICS_update (stats, gettext_noop ("# hostlist advertisements send"), 1, GNUNET_NO); return transmission_size; } /** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { size_t size; if (!advertising) return; if (NULL == hostlist_uri) return; size = strlen (hostlist_uri) + 1; if (size + sizeof (struct GNUNET_MessageHeader) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } size += sizeof (struct GNUNET_MessageHeader); if (NULL == core) { GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked core to transmit advertisement message with a size of %u bytes to peer `%s'\n", size, GNUNET_i2s (peer)); if (NULL == GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_ADV_TIMEOUT, peer, size, &adv_transmit_ready, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Advertisement message could not be queued by core\n")); } } /** * Method called whenever a given peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { /* nothing to do */ } /** * PEERINFO calls this function to let us know about a possible peer * that we might want to connect to. * * @param cls closure (not used) * @param peer potential peer to connect to * @param hello HELLO for this peer (or NULL) * @param err_msg NULL if successful, otherwise contains error message */ static void process_notify (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peerinfo is notifying us to rebuild our hostlist\n"); if (NULL != err_msg) GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Error in communication with PEERINFO service: %s\n"), err_msg); if (NULL != builder) { /* restart re-build already in progress ... */ GNUNET_PEERINFO_iterate_cancel (builder->pitr); GNUNET_free_non_null (builder->data); builder->size = 0; builder->data = NULL; } else { builder = GNUNET_new (struct HostSet); } GNUNET_assert (NULL != peerinfo); builder->pitr = GNUNET_PEERINFO_iterate (peerinfo, GNUNET_NO, NULL, GNUNET_TIME_UNIT_MINUTES, &host_processor, NULL); } /** * Function that queries MHD's select sets and * starts the task waiting for them. */ static GNUNET_SCHEDULER_TaskIdentifier prepare_daemon (struct MHD_Daemon *daemon_handle); /** * Call MHD to process pending requests and then go back * and schedule the next run. */ static void run_daemon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MHD_Daemon *daemon_handle = cls; if (daemon_handle == daemon_handle_v4) hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK; else hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_assert (MHD_YES == MHD_run (daemon_handle)); if (daemon_handle == daemon_handle_v4) hostlist_task_v4 = prepare_daemon (daemon_handle); else hostlist_task_v6 = prepare_daemon (daemon_handle); } #define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG /** * Function that queries MHD's select sets and * starts the task waiting for them. */ static GNUNET_SCHEDULER_TaskIdentifier prepare_daemon (struct MHD_Daemon *daemon_handle) { GNUNET_SCHEDULER_TaskIdentifier ret; fd_set rs; fd_set ws; fd_set es; struct GNUNET_NETWORK_FDSet *wrs; struct GNUNET_NETWORK_FDSet *wws; int max; UNSIGNED_MHD_LONG_LONG timeout; int haveto; struct GNUNET_TIME_Relative tv; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); wrs = GNUNET_NETWORK_fdset_create (); wws = GNUNET_NETWORK_fdset_create (); max = -1; GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max)); haveto = MHD_get_timeout (daemon_handle, &timeout); if (haveto == MHD_YES) tv.rel_value_us = (uint64_t) timeout * 1000LL; else tv = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, tv, wrs, wws, &run_daemon, daemon_handle); GNUNET_NETWORK_fdset_destroy (wrs); GNUNET_NETWORK_fdset_destroy (wws); return ret; } /** * Start server offering our hostlist. * * @return GNUNET_OK on success */ int GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_STATISTICS_Handle *st, struct GNUNET_CORE_Handle *co, GNUNET_CORE_ConnectEventHandler *server_ch, GNUNET_CORE_DisconnectEventHandler *server_dh, int advertise) { unsigned long long port; char *hostname; char *ip; size_t size; struct in_addr i4; struct in6_addr i6; struct sockaddr_in v4; struct sockaddr_in6 v6; const struct sockaddr *sa; advertising = advertise; if (!advertising) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Advertising not enabled on this hostlist server\n"); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Advertising enabled on this hostlist server\n"); cfg = c; stats = st; peerinfo = GNUNET_PEERINFO_connect (cfg); if (NULL == peerinfo) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not access PEERINFO service. Exiting.\n")); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "HOSTLIST", "HTTPPORT", &port)) return GNUNET_SYSERR; if ((0 == port) || (port > UINT16_MAX)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Invalid port number %llu. Exiting.\n"), port); return GNUNET_SYSERR; } if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST", "EXTERNAL_DNS_NAME", &hostname)) hostname = GNUNET_RESOLVER_local_fqdn_get (); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Hostlist service starts on %s:%llu\n"), hostname, port); if (NULL != hostname) { size = strlen (hostname); if (size + 15 > MAX_URL_LEN) { GNUNET_break (0); } else { GNUNET_asprintf (&hostlist_uri, "http://%s:%u/", hostname, (unsigned int) port); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Address to obtain hostlist: `%s'\n"), hostlist_uri); } GNUNET_free (hostname); } if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIP")) { GNUNET_break (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST", "BINDTOIP", &ip)); } else ip = NULL; if (NULL != ip) { if (1 == inet_pton (AF_INET, ip, &i4)) { memset (&v4, 0, sizeof (v4)); v4.sin_family = AF_INET; v4.sin_addr = i4; v4.sin_port = htons (port); #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif sa = (const struct sockaddr *) &v4; } else if (1 == inet_pton (AF_INET6, ip, &i6)) { memset (&v6, 0, sizeof (v6)); v6.sin6_family = AF_INET6; v6.sin6_addr = i6; v6.sin6_port = htons (port); #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (v6); #endif sa = (const struct sockaddr *) &v6; } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("`%s' is not a valid IP address! Ignoring BINDTOIP.\n"), ip); sa = NULL; } GNUNET_free (ip); } else sa = NULL; daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 | MHD_USE_DEBUG, (uint16_t) port, &accept_policy_callback, NULL, &access_handler_callback, NULL, MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 16, MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (16 * 1024), MHD_OPTION_SOCK_ADDR, sa, MHD_OPTION_END); daemon_handle_v4 = MHD_start_daemon (MHD_NO_FLAG | MHD_USE_DEBUG, (uint16_t) port, &accept_policy_callback, NULL, &access_handler_callback, NULL, MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 16, MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (16 * 1024), MHD_OPTION_SOCK_ADDR, sa, MHD_OPTION_END); if ((NULL == daemon_handle_v6) && (NULL == daemon_handle_v4)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not start hostlist HTTP server on port %u\n"), (unsigned short) port); return GNUNET_SYSERR; } core = co; *server_ch = &connect_handler; *server_dh = &disconnect_handler; if (daemon_handle_v4 != NULL) hostlist_task_v4 = prepare_daemon (daemon_handle_v4); if (daemon_handle_v6 != NULL) hostlist_task_v6 = prepare_daemon (daemon_handle_v6); notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO, &process_notify, NULL); return GNUNET_OK; } /** * Stop server offering our hostlist. */ void GNUNET_HOSTLIST_server_stop () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist server shutdown\n"); if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v6) { GNUNET_SCHEDULER_cancel (hostlist_task_v6); hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v4) { GNUNET_SCHEDULER_cancel (hostlist_task_v4); hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK; } if (NULL != daemon_handle_v4) { MHD_stop_daemon (daemon_handle_v4); daemon_handle_v4 = NULL; } if (NULL != daemon_handle_v6) { MHD_stop_daemon (daemon_handle_v6); daemon_handle_v6 = NULL; } if (NULL != response) { MHD_destroy_response (response); response = NULL; } if (NULL != notify) { GNUNET_PEERINFO_notify_cancel (notify); notify = NULL; } if (NULL != builder) { GNUNET_PEERINFO_iterate_cancel (builder->pitr); builder->pitr = NULL; GNUNET_free_non_null (builder->data); GNUNET_free (builder); } if (NULL != peerinfo) { GNUNET_PEERINFO_disconnect (peerinfo); peerinfo = NULL; } cfg = NULL; stats = NULL; core = NULL; } /* end of hostlist-server.c */ gnunet-0.10.1/src/hostlist/test_gnunet_daemon_hostlist_reconnect.c0000644000175000017500000001554112301361473022477 00000000000000/* This file is part of GNUnet (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/test_gnunet_daemon_hostlist_reconnect.c * @brief test for gnunet_daemon_hostslist.c; tries to re-start the peers * and connect a second time * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_transport_service.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 150) static int ok; static GNUNET_SCHEDULER_TaskIdentifier timeout_task; struct PeerContext { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_TRANSPORT_Handle *th; struct GNUNET_MessageHeader *hello; struct GNUNET_TRANSPORT_GetHelloHandle *ghh; struct GNUNET_OS_Process *arm_proc; }; static struct PeerContext p1; static struct PeerContext p2; static void clean_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != p1.ghh) { GNUNET_TRANSPORT_get_hello_cancel (p1.ghh); p1.ghh = NULL; } if (p1.th != NULL) { GNUNET_TRANSPORT_disconnect (p1.th); p1.th = NULL; } if (NULL != p2.ghh) { GNUNET_TRANSPORT_get_hello_cancel (p2.ghh); p2.ghh = NULL; } if (p2.th != NULL) { GNUNET_TRANSPORT_disconnect (p2.th); p2.th = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Timeout, give up. */ static void timeout_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout trying to connect peers, test failed.\n"); clean_up (NULL, tc); } /** * Function called to notify transport users that another * peer connected to us. * * @param cls closure * @param peer the peer that connected * @param latency current latency of the connection * @param distance in overlay hops, as given by transport plugin */ static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { if (peer == NULL) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected, shutting down.\n"); ok = 0; if (timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_now (&clean_up, NULL); } static void process_hello (void *cls, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; GNUNET_TRANSPORT_get_hello_cancel (p->ghh); p->ghh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received HELLO, starting hostlist service.\n"); } static void setup_peer (struct PeerContext *p, const char *cfgname) { char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); p->cfg = GNUNET_CONFIGURATION_create (); p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-arm", "-c", cfgname, NULL); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, NULL, ¬ify_connect, NULL); GNUNET_assert (p->th != NULL); p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &process_hello, p); GNUNET_free (binary); } static void waitpid_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Killing ARM process.\n"); if (0 != GNUNET_OS_process_kill (p->arm_proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; GNUNET_CONFIGURATION_destroy (p->cfg); } static void stop_arm (struct PeerContext *p) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking ARM to stop core service\n"); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &waitpid_task, p); } /** * Try again to connect to transport service. */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { stop_arm (&p1); stop_arm (&p2); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_assert (ok == 1); ok++; timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_error, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); setup_peer (&p1, "test_gnunet_daemon_hostlist_peer1.conf"); setup_peer (&p2, "test_gnunet_daemon_hostlist_peer2.conf"); } int main (int argcx, char *argvx[]) { static char *const argv[] = { "test-gnunet-daemon-hostlist", "-c", "test_gnunet_daemon_hostlist_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-3"); GNUNET_log_setup ("test-gnunet-daemon-hostlist", "WARNING", NULL); ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-gnunet-daemon-hostlist", "nohelp", options, &run, &ok); if (0 == ok) { FPRINTF (stderr, "%s", "."); /* now do it again */ ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-gnunet-daemon-hostlist", "nohelp", options, &run, &ok); FPRINTF (stderr, "%s", ".\n"); } GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-3"); return ok; } /* end of test_gnunet_daemon_hostlist_reconnect.c */ gnunet-0.10.1/src/hostlist/Makefile.in0000644000175000017500000014507712320752062014534 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @HAVE_LIBGNURL_TRUE@libexec_PROGRAMS = \ @HAVE_LIBGNURL_TRUE@ gnunet-daemon-hostlist$(EXEEXT) @HAVE_LIBGNURL_TRUE@check_PROGRAMS = \ @HAVE_LIBGNURL_TRUE@ test_gnunet_daemon_hostlist$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@ test_gnunet_daemon_hostlist_reconnect$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@ test_gnunet_daemon_hostlist_learning$(EXEEXT) @ENABLE_TEST_RUN_TRUE@@HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@TESTS = test_gnunet_daemon_hostlist$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@@HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@ test_gnunet_daemon_hostlist_reconnect$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@@HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@ test_gnunet_daemon_hostlist_learning$(EXEEXT) subdir = src/hostlist DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgcfg_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" PROGRAMS = $(libexec_PROGRAMS) am__gnunet_daemon_hostlist_SOURCES_DIST = gnunet-daemon-hostlist.c \ gnunet-daemon-hostlist.h hostlist-client.c hostlist-client.h \ hostlist-server.c hostlist-server.h @HAVE_MHD_TRUE@am__objects_1 = gnunet_daemon_hostlist-hostlist-server.$(OBJEXT) am_gnunet_daemon_hostlist_OBJECTS = \ gnunet_daemon_hostlist-gnunet-daemon-hostlist.$(OBJEXT) \ gnunet_daemon_hostlist-hostlist-client.$(OBJEXT) \ $(am__objects_1) gnunet_daemon_hostlist_OBJECTS = $(am_gnunet_daemon_hostlist_OBJECTS) am__DEPENDENCIES_1 = gnunet_daemon_hostlist_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_test_gnunet_daemon_hostlist_OBJECTS = \ test_gnunet_daemon_hostlist.$(OBJEXT) test_gnunet_daemon_hostlist_OBJECTS = \ $(am_test_gnunet_daemon_hostlist_OBJECTS) test_gnunet_daemon_hostlist_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_daemon_hostlist_learning_OBJECTS = \ test_gnunet_daemon_hostlist_learning.$(OBJEXT) test_gnunet_daemon_hostlist_learning_OBJECTS = \ $(am_test_gnunet_daemon_hostlist_learning_OBJECTS) test_gnunet_daemon_hostlist_learning_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_daemon_hostlist_reconnect_OBJECTS = \ test_gnunet_daemon_hostlist_reconnect.$(OBJEXT) test_gnunet_daemon_hostlist_reconnect_OBJECTS = \ $(am_test_gnunet_daemon_hostlist_reconnect_OBJECTS) test_gnunet_daemon_hostlist_reconnect_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gnunet_daemon_hostlist_SOURCES) \ $(test_gnunet_daemon_hostlist_SOURCES) \ $(test_gnunet_daemon_hostlist_learning_SOURCES) \ $(test_gnunet_daemon_hostlist_reconnect_SOURCES) DIST_SOURCES = $(am__gnunet_daemon_hostlist_SOURCES_DIST) \ $(test_gnunet_daemon_hostlist_SOURCES) \ $(test_gnunet_daemon_hostlist_learning_SOURCES) \ $(test_gnunet_daemon_hostlist_reconnect_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } DATA = $(dist_pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ hostlist.conf @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @HAVE_MHD_TRUE@HOSTLIST_SERVER_SOURCES = hostlist-server.c hostlist-server.h @HAVE_MHD_TRUE@GN_LIBMHD = -lmicrohttpd gnunet_daemon_hostlist_SOURCES = \ gnunet-daemon-hostlist.c gnunet-daemon-hostlist.h \ hostlist-client.c hostlist-client.h \ $(HOSTLIST_SERVER_SOURCES) gnunet_daemon_hostlist_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBMHD) \ @LIBGNURL@ \ $(GN_LIBINTL) gnunet_daemon_hostlist_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) @ENABLE_TEST_RUN_TRUE@@HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; test_gnunet_daemon_hostlist_SOURCES = \ test_gnunet_daemon_hostlist.c test_gnunet_daemon_hostlist_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_daemon_hostlist_reconnect_SOURCES = \ test_gnunet_daemon_hostlist_reconnect.c test_gnunet_daemon_hostlist_reconnect_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_daemon_hostlist_learning_SOURCES = \ test_gnunet_daemon_hostlist_learning.c test_gnunet_daemon_hostlist_learning_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_hostlist_defaults.conf \ test_gnunet_daemon_hostlist_data.conf \ test_gnunet_daemon_hostlist_peer1.conf \ test_gnunet_daemon_hostlist_peer2.conf \ test_learning_adv_peer.conf \ test_learning_learn_peer.conf \ test_learning_learn_peer2.conf \ learning_data.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/hostlist/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/hostlist/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-daemon-hostlist$(EXEEXT): $(gnunet_daemon_hostlist_OBJECTS) $(gnunet_daemon_hostlist_DEPENDENCIES) $(EXTRA_gnunet_daemon_hostlist_DEPENDENCIES) @rm -f gnunet-daemon-hostlist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_hostlist_OBJECTS) $(gnunet_daemon_hostlist_LDADD) $(LIBS) test_gnunet_daemon_hostlist$(EXEEXT): $(test_gnunet_daemon_hostlist_OBJECTS) $(test_gnunet_daemon_hostlist_DEPENDENCIES) $(EXTRA_test_gnunet_daemon_hostlist_DEPENDENCIES) @rm -f test_gnunet_daemon_hostlist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_daemon_hostlist_OBJECTS) $(test_gnunet_daemon_hostlist_LDADD) $(LIBS) test_gnunet_daemon_hostlist_learning$(EXEEXT): $(test_gnunet_daemon_hostlist_learning_OBJECTS) $(test_gnunet_daemon_hostlist_learning_DEPENDENCIES) $(EXTRA_test_gnunet_daemon_hostlist_learning_DEPENDENCIES) @rm -f test_gnunet_daemon_hostlist_learning$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_daemon_hostlist_learning_OBJECTS) $(test_gnunet_daemon_hostlist_learning_LDADD) $(LIBS) test_gnunet_daemon_hostlist_reconnect$(EXEEXT): $(test_gnunet_daemon_hostlist_reconnect_OBJECTS) $(test_gnunet_daemon_hostlist_reconnect_DEPENDENCIES) $(EXTRA_test_gnunet_daemon_hostlist_reconnect_DEPENDENCIES) @rm -f test_gnunet_daemon_hostlist_reconnect$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_daemon_hostlist_reconnect_OBJECTS) $(test_gnunet_daemon_hostlist_reconnect_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_daemon_hostlist-gnunet-daemon-hostlist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_daemon_hostlist-hostlist-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_daemon_hostlist-hostlist-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_daemon_hostlist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_daemon_hostlist_learning.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_daemon_hostlist_reconnect.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< gnunet_daemon_hostlist-gnunet-daemon-hostlist.o: gnunet-daemon-hostlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gnunet_daemon_hostlist-gnunet-daemon-hostlist.o -MD -MP -MF $(DEPDIR)/gnunet_daemon_hostlist-gnunet-daemon-hostlist.Tpo -c -o gnunet_daemon_hostlist-gnunet-daemon-hostlist.o `test -f 'gnunet-daemon-hostlist.c' || echo '$(srcdir)/'`gnunet-daemon-hostlist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_daemon_hostlist-gnunet-daemon-hostlist.Tpo $(DEPDIR)/gnunet_daemon_hostlist-gnunet-daemon-hostlist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-daemon-hostlist.c' object='gnunet_daemon_hostlist-gnunet-daemon-hostlist.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gnunet_daemon_hostlist-gnunet-daemon-hostlist.o `test -f 'gnunet-daemon-hostlist.c' || echo '$(srcdir)/'`gnunet-daemon-hostlist.c gnunet_daemon_hostlist-gnunet-daemon-hostlist.obj: gnunet-daemon-hostlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gnunet_daemon_hostlist-gnunet-daemon-hostlist.obj -MD -MP -MF $(DEPDIR)/gnunet_daemon_hostlist-gnunet-daemon-hostlist.Tpo -c -o gnunet_daemon_hostlist-gnunet-daemon-hostlist.obj `if test -f 'gnunet-daemon-hostlist.c'; then $(CYGPATH_W) 'gnunet-daemon-hostlist.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-daemon-hostlist.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_daemon_hostlist-gnunet-daemon-hostlist.Tpo $(DEPDIR)/gnunet_daemon_hostlist-gnunet-daemon-hostlist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-daemon-hostlist.c' object='gnunet_daemon_hostlist-gnunet-daemon-hostlist.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gnunet_daemon_hostlist-gnunet-daemon-hostlist.obj `if test -f 'gnunet-daemon-hostlist.c'; then $(CYGPATH_W) 'gnunet-daemon-hostlist.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-daemon-hostlist.c'; fi` gnunet_daemon_hostlist-hostlist-client.o: hostlist-client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gnunet_daemon_hostlist-hostlist-client.o -MD -MP -MF $(DEPDIR)/gnunet_daemon_hostlist-hostlist-client.Tpo -c -o gnunet_daemon_hostlist-hostlist-client.o `test -f 'hostlist-client.c' || echo '$(srcdir)/'`hostlist-client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_daemon_hostlist-hostlist-client.Tpo $(DEPDIR)/gnunet_daemon_hostlist-hostlist-client.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostlist-client.c' object='gnunet_daemon_hostlist-hostlist-client.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gnunet_daemon_hostlist-hostlist-client.o `test -f 'hostlist-client.c' || echo '$(srcdir)/'`hostlist-client.c gnunet_daemon_hostlist-hostlist-client.obj: hostlist-client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gnunet_daemon_hostlist-hostlist-client.obj -MD -MP -MF $(DEPDIR)/gnunet_daemon_hostlist-hostlist-client.Tpo -c -o gnunet_daemon_hostlist-hostlist-client.obj `if test -f 'hostlist-client.c'; then $(CYGPATH_W) 'hostlist-client.c'; else $(CYGPATH_W) '$(srcdir)/hostlist-client.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_daemon_hostlist-hostlist-client.Tpo $(DEPDIR)/gnunet_daemon_hostlist-hostlist-client.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostlist-client.c' object='gnunet_daemon_hostlist-hostlist-client.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gnunet_daemon_hostlist-hostlist-client.obj `if test -f 'hostlist-client.c'; then $(CYGPATH_W) 'hostlist-client.c'; else $(CYGPATH_W) '$(srcdir)/hostlist-client.c'; fi` gnunet_daemon_hostlist-hostlist-server.o: hostlist-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gnunet_daemon_hostlist-hostlist-server.o -MD -MP -MF $(DEPDIR)/gnunet_daemon_hostlist-hostlist-server.Tpo -c -o gnunet_daemon_hostlist-hostlist-server.o `test -f 'hostlist-server.c' || echo '$(srcdir)/'`hostlist-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_daemon_hostlist-hostlist-server.Tpo $(DEPDIR)/gnunet_daemon_hostlist-hostlist-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostlist-server.c' object='gnunet_daemon_hostlist-hostlist-server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gnunet_daemon_hostlist-hostlist-server.o `test -f 'hostlist-server.c' || echo '$(srcdir)/'`hostlist-server.c gnunet_daemon_hostlist-hostlist-server.obj: hostlist-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gnunet_daemon_hostlist-hostlist-server.obj -MD -MP -MF $(DEPDIR)/gnunet_daemon_hostlist-hostlist-server.Tpo -c -o gnunet_daemon_hostlist-hostlist-server.obj `if test -f 'hostlist-server.c'; then $(CYGPATH_W) 'hostlist-server.c'; else $(CYGPATH_W) '$(srcdir)/hostlist-server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_daemon_hostlist-hostlist-server.Tpo $(DEPDIR)/gnunet_daemon_hostlist-hostlist-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hostlist-server.c' object='gnunet_daemon_hostlist-hostlist-server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gnunet_daemon_hostlist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gnunet_daemon_hostlist-hostlist-server.obj `if test -f 'hostlist-server.c'; then $(CYGPATH_W) 'hostlist-server.c'; else $(CYGPATH_W) '$(srcdir)/hostlist-server.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_gnunet_daemon_hostlist.log: test_gnunet_daemon_hostlist$(EXEEXT) @p='test_gnunet_daemon_hostlist$(EXEEXT)'; \ b='test_gnunet_daemon_hostlist'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_daemon_hostlist_reconnect.log: test_gnunet_daemon_hostlist_reconnect$(EXEEXT) @p='test_gnunet_daemon_hostlist_reconnect$(EXEEXT)'; \ b='test_gnunet_daemon_hostlist_reconnect'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_daemon_hostlist_learning.log: test_gnunet_daemon_hostlist_learning$(EXEEXT) @p='test_gnunet_daemon_hostlist_learning$(EXEEXT)'; \ b='test_gnunet_daemon_hostlist_learning'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_pkgcfgDATA uninstall-libexecPROGRAMS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-dist_pkgcfgDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-dist_pkgcfgDATA \ uninstall-libexecPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/hostlist/test_learning_learn_peer.conf0000644000175000017500000000170012225230043020342 00000000000000@INLINE@ test_hostlist_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-hostlist-peer-2/ [transport-tcp] PORT = 12968 [arm] PORT = 12966 DEFAULTSERVICES = topology hostlist UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p1-service-arm.sock [statistics] PORT = 12967 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p1-service-statistics.sock [resolver] PORT = 12964 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p1-service-resolver.sock [peerinfo] PORT = 12969 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p1-service-peerinfo.sock [transport] PORT = 12965 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p1-service-transport.sock [core] PORT = 12970 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p1-service-core.sock [hostlist] HTTPPORT = 12980 HOSTLISTFILE = hostlists_learn_peer.file OPTIONS = -b -e SERVERS = http://localhost:12981/ [dht] AUTOSTART = NO [ats] PORT = 12971 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-ats-p1-service-core.sock gnunet-0.10.1/src/hostlist/hostlist-server.h0000644000175000017500000000344212225777503016015 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/hostlist-server.h * @brief hostlist support. Downloads HELLOs via HTTP. * @author Christian Grothoff */ #ifndef HOSTLIST_SERVER_H #define HOSTLIST_SERVER_H #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "gnunet_util_lib.h" #define GNUNET_ADV_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) /** * Start server offering our hostlist. * * @return GNUNET_OK on success */ int GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_STATISTICS_Handle *st, struct GNUNET_CORE_Handle *core, GNUNET_CORE_ConnectEventHandler *server_ch, GNUNET_CORE_DisconnectEventHandler *server_dh, int advertise); /** * Stop server offering our hostlist. */ void GNUNET_HOSTLIST_server_stop (void); #endif /* end of hostlist-server.h */ gnunet-0.10.1/src/hostlist/Makefile.am0000644000175000017500000000474212320751520014512 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ dist_pkgcfg_DATA = \ hostlist.conf if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif if HAVE_MHD HOSTLIST_SERVER_SOURCES = hostlist-server.c hostlist-server.h GN_LIBMHD = -lmicrohttpd endif if HAVE_LIBGNURL libexec_PROGRAMS = \ gnunet-daemon-hostlist endif gnunet_daemon_hostlist_SOURCES = \ gnunet-daemon-hostlist.c gnunet-daemon-hostlist.h \ hostlist-client.c hostlist-client.h \ $(HOSTLIST_SERVER_SOURCES) gnunet_daemon_hostlist_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBMHD) \ @LIBGNURL@ \ $(GN_LIBINTL) gnunet_daemon_hostlist_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) if HAVE_LIBGNURL check_PROGRAMS = \ test_gnunet_daemon_hostlist \ test_gnunet_daemon_hostlist_reconnect \ test_gnunet_daemon_hostlist_learning if HAVE_MHD if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ test_gnunet_daemon_hostlist \ test_gnunet_daemon_hostlist_reconnect \ test_gnunet_daemon_hostlist_learning endif endif endif test_gnunet_daemon_hostlist_SOURCES = \ test_gnunet_daemon_hostlist.c test_gnunet_daemon_hostlist_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_daemon_hostlist_reconnect_SOURCES = \ test_gnunet_daemon_hostlist_reconnect.c test_gnunet_daemon_hostlist_reconnect_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_daemon_hostlist_learning_SOURCES = \ test_gnunet_daemon_hostlist_learning.c test_gnunet_daemon_hostlist_learning_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_hostlist_defaults.conf \ test_gnunet_daemon_hostlist_data.conf \ test_gnunet_daemon_hostlist_peer1.conf \ test_gnunet_daemon_hostlist_peer2.conf \ test_learning_adv_peer.conf \ test_learning_learn_peer.conf \ test_learning_learn_peer2.conf \ learning_data.conf gnunet-0.10.1/src/hostlist/hostlist-client.c0000644000175000017500000012643512261236531015757 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/hostlist-client.c * @brief hostlist support. Downloads HELLOs via HTTP. * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "hostlist-client.h" #include "gnunet_core_service.h" #include "gnunet_hello_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet-daemon-hostlist.h" #include #include "gnunet_util_lib.h" /** * Number of connections that we must have to NOT download * hostlists anymore. */ #define MIN_CONNECTIONS 4 /** * Interval between two advertised hostlist tests */ #define TESTING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * A single hostlist obtained by hostlist advertisements */ struct Hostlist { /** * previous entry, used to manage entries in a double linked list */ struct Hostlist *prev; /** * next entry, used to manage entries in a double linked list */ struct Hostlist *next; /** * URI where hostlist can be obtained */ const char *hostlist_uri; /** * Value describing the quality of the hostlist, the bigger the better but (should) never < 0 * used for deciding which hostlist is replaced if MAX_NUMBER_HOSTLISTS in data structure is reached * intial value = HOSTLIST_INITIAL * increased every successful download by HOSTLIST_SUCCESSFULL_DOWNLOAD * increased every successful download by number of obtained HELLO messages * decreased every failed download by HOSTLIST_SUCCESSFULL_DOWNLOAD */ uint64_t quality; /** * Time the hostlist advertisement was recieved and the entry was created */ struct GNUNET_TIME_Absolute time_creation; /** * Last time the hostlist was obtained */ struct GNUNET_TIME_Absolute time_last_usage; /** * Number of HELLO messages obtained during last download */ uint32_t hello_count; /** * Number of times the hostlist was successfully obtained */ uint32_t times_used; }; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Statistics handle. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Transport handle. */ static struct GNUNET_TRANSPORT_Handle *transport; /** * Proxy that we are using (can be NULL). */ static char *proxy; /** * Number of bytes valid in 'download_buffer'. */ static size_t download_pos; /** * Current URL that we are using. */ static char *current_url; /** * Current CURL handle. */ static CURL *curl; /** * Current multi-CURL handle. */ static CURLM *multi; /** * How many bytes did we download from the current hostlist URL? */ static uint32_t stat_bytes_downloaded; /** * Amount of time we wait between hostlist downloads. */ static struct GNUNET_TIME_Relative hostlist_delay; /** * ID of the task, checking if hostlist download should take plate */ static GNUNET_SCHEDULER_TaskIdentifier ti_check_download; /** * ID of the task downloading the hostlist */ static GNUNET_SCHEDULER_TaskIdentifier ti_download; /** * ID of the task saving the hostlsit in a regular intervall */ static GNUNET_SCHEDULER_TaskIdentifier ti_saving_task; /** * ID of the task called to initiate a download */ static GNUNET_SCHEDULER_TaskIdentifier ti_download_dispatcher_task; /** * ID of the task controlling the locking between two hostlist tests */ static GNUNET_SCHEDULER_TaskIdentifier ti_testing_intervall_task; /** * At what time MUST the current hostlist request be done? */ static struct GNUNET_TIME_Absolute end_time; /** * Head of the linked list used to store hostlists */ static struct Hostlist *linked_list_head; /** * Tail of the linked list used to store hostlists */ static struct Hostlist *linked_list_tail; /** * Current hostlist used for downloading */ static struct Hostlist *current_hostlist; /** * Size of the linke list used to store hostlists */ static unsigned int linked_list_size; /** * Head of the linked list used to store hostlists */ static struct Hostlist *hostlist_to_test; /** * Handle for our statistics GET operation. */ static struct GNUNET_STATISTICS_GetHandle *sget; /** * Set to GNUNET_YES if the current URL had some problems. */ static int stat_bogus_url; /** * Value controlling if a hostlist is tested at the moment */ static int stat_testing_hostlist; /** * Value controlling if a hostlist testing is allowed at the moment */ static int stat_testing_allowed; /** * Value controlling if a hostlist download is running at the moment */ static int stat_download_in_progress; /** * Value saying if a preconfigured bootstrap server is used */ static unsigned int stat_use_bootstrap; /** * Set if we are allowed to learn new hostlists and use them */ static int stat_learning; /** * Value saying if hostlist download was successful */ static unsigned int stat_download_successful; /** * Value saying how many valid HELLO messages were obtained during download */ static unsigned int stat_hellos_obtained; /** * Number of active connections (according to core service). */ static unsigned int stat_connection_count; /** * Process downloaded bits by calling callback on each HELLO. * * @param ptr buffer with downloaded data * @param size size of a record * @param nmemb number of records downloaded * @param ctx unused * @return number of bytes that were processed (always size*nmemb) */ static size_t callback_download (void *ptr, size_t size, size_t nmemb, void *ctx) { static char download_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; const char *cbuf = ptr; const struct GNUNET_MessageHeader *msg; size_t total; size_t cpy; size_t left; uint16_t msize; total = size * nmemb; stat_bytes_downloaded += total; if ((total == 0) || (stat_bogus_url)) { return total; /* ok, no data or bogus data */ } GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes downloaded from hostlist servers"), (int64_t) total, GNUNET_NO); left = total; while ((left > 0) || (download_pos > 0)) { cpy = GNUNET_MIN (left, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - download_pos); memcpy (&download_buffer[download_pos], cbuf, cpy); cbuf += cpy; download_pos += cpy; left -= cpy; if (download_pos < sizeof (struct GNUNET_MessageHeader)) { GNUNET_assert (0 == left); break; } msg = (const struct GNUNET_MessageHeader *) download_buffer; msize = ntohs (msg->size); if (msize < sizeof (struct GNUNET_MessageHeader)) { GNUNET_STATISTICS_update (stats, gettext_noop ("# invalid HELLOs downloaded from hostlist servers"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Invalid `%s' message received from hostlist at `%s'\n"), "HELLO", current_url); stat_hellos_obtained++; stat_bogus_url = 1; return total; } if (download_pos < msize) { GNUNET_assert (left == 0); break; } if (GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message *) msg) == msize) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received valid `%s' message from hostlist server.\n", "HELLO"); GNUNET_STATISTICS_update (stats, gettext_noop ("# valid HELLOs downloaded from hostlist servers"), 1, GNUNET_NO); stat_hellos_obtained++; GNUNET_TRANSPORT_offer_hello (transport, msg, NULL, NULL); } else { GNUNET_STATISTICS_update (stats, gettext_noop ("# invalid HELLOs downloaded from hostlist servers"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Invalid `%s' message received from hostlist at `%s'\n"), "HELLO", current_url); stat_bogus_url = GNUNET_YES; stat_hellos_obtained++; return total; } memmove (download_buffer, &download_buffer[msize], download_pos - msize); download_pos -= msize; } return total; } /** * Obtain a hostlist URL that we should use. * * @return NULL if there is no URL available */ static char * get_bootstrap_server () { char *servers; char *ret; size_t urls; size_t pos; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST", "SERVERS", &servers)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, "hostlist", "SERVERS"); return NULL; } urls = 0; if (strlen (servers) > 0) { urls++; pos = strlen (servers) - 1; while (pos > 0) { if (servers[pos] == ' ') urls++; pos--; } } if (urls == 0) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, "hostlist", "SERVERS"); GNUNET_free (servers); return NULL; } urls = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, urls) + 1; pos = strlen (servers) - 1; while (pos > 0) { if (servers[pos] == ' ') { urls--; servers[pos] = '\0'; } if (urls == 0) { pos++; break; } pos--; } ret = GNUNET_strdup (&servers[pos]); GNUNET_free (servers); return ret; } /** * Method deciding if a preconfigured or advertisied hostlist is used on a 50:50 ratio * @return uri to use, NULL if there is no URL available */ static char * download_get_url () { uint32_t index; unsigned int counter; struct Hostlist *pos; if (GNUNET_NO == stat_learning) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using preconfigured bootstrap server\n"); current_hostlist = NULL; return get_bootstrap_server (); } if ((GNUNET_YES == stat_testing_hostlist) && (NULL != hostlist_to_test)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing new advertised hostlist if it is obtainable\n"); current_hostlist = hostlist_to_test; return GNUNET_strdup (hostlist_to_test->hostlist_uri); } if ((GNUNET_YES == stat_use_bootstrap) || (linked_list_size == 0)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using preconfigured bootstrap server\n"); current_hostlist = NULL; return get_bootstrap_server (); } index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, linked_list_size); counter = 0; pos = linked_list_head; while (counter < index) { pos = pos->next; counter++; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using learned hostlist `%s'\n", pos->hostlist_uri); current_hostlist = pos; return GNUNET_strdup (pos->hostlist_uri); } #define CURL_EASY_SETOPT(c, a, b) do { ret = curl_easy_setopt (c, a, b); if (CURLE_OK != ret) GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("%s failed at %s:%d: `%s'\n"), "curl_easy_setopt", __FILE__, __LINE__, curl_easy_strerror (ret)); } while (0) /** * Method to save hostlist to a file during hostlist client shutdown * @param shutdown set if called because of shutdown, entries in linked list will be destroyed */ static void save_hostlist_file (int shutdown); /** * add val2 to val1 with overflow check * * @param val1 value 1 * @param val2 value 2 * @return result */ static uint64_t checked_add (uint64_t val1, uint64_t val2) { static uint64_t temp; static uint64_t maxv; maxv = 0; maxv--; temp = val1 + val2; if (temp < val1) return maxv; return temp; } /** * Subtract val2 from val1 with underflow check * * @param val1 value 1 * @param val2 value 2 * @return result */ static uint64_t checked_sub (uint64_t val1, uint64_t val2) { if (val1 <= val2) return 0; return (val1 - val2); } /** * Method to check if a URI is in hostlist linked list * * @param uri uri to check * @return #GNUNET_YES if existing in linked list, #GNUNET_NO if not */ static int linked_list_contains (const char *uri) { struct Hostlist *pos; pos = linked_list_head; while (pos != NULL) { if (0 == strcmp (pos->hostlist_uri, uri)) return GNUNET_YES; pos = pos->next; } return GNUNET_NO; } /** * Method returning the hostlist element with the lowest quality in the datastore * @return hostlist with lowest quality */ static struct Hostlist * linked_list_get_lowest_quality () { struct Hostlist *pos; struct Hostlist *lowest; if (linked_list_size == 0) return NULL; lowest = linked_list_head; pos = linked_list_head->next; while (pos != NULL) { if (pos->quality < lowest->quality) lowest = pos; pos = pos->next; } return lowest; } /** * Method to insert a hostlist into the datastore. If datastore * contains maximum number of elements, the elements with lowest * quality is dismissed */ static void insert_hostlist () { struct Hostlist *lowest_quality; if (MAX_NUMBER_HOSTLISTS <= linked_list_size) { /* No free entries available, replace existing entry */ lowest_quality = linked_list_get_lowest_quality (); GNUNET_assert (lowest_quality != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing hostlist with URI `%s' which has the worst quality of all (%llu)\n", lowest_quality->hostlist_uri, (unsigned long long) lowest_quality->quality); GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail, lowest_quality); linked_list_size--; GNUNET_free (lowest_quality); } GNUNET_CONTAINER_DLL_insert (linked_list_head, linked_list_tail, hostlist_to_test); linked_list_size++; GNUNET_STATISTICS_set (stats, gettext_noop ("# advertised hostlist URIs"), linked_list_size, GNUNET_NO); stat_testing_hostlist = GNUNET_NO; } /** * Method updating hostlist statistics */ static void update_hostlist () { char *stat; if (((stat_use_bootstrap == GNUNET_NO) && (NULL != current_hostlist)) || ((stat_testing_hostlist == GNUNET_YES) && (NULL != current_hostlist))) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Updating hostlist statics for URI `%s'\n", current_hostlist->hostlist_uri); current_hostlist->hello_count = stat_hellos_obtained; current_hostlist->time_last_usage = GNUNET_TIME_absolute_get (); current_hostlist->quality = checked_add (current_hostlist->quality, (stat_hellos_obtained * HOSTLIST_SUCCESSFUL_HELLO)); if (GNUNET_YES == stat_download_successful) { current_hostlist->times_used++; current_hostlist->quality = checked_add (current_hostlist->quality, HOSTLIST_SUCCESSFUL_DOWNLOAD); GNUNET_asprintf (&stat, gettext_noop ("# advertised URI `%s' downloaded"), current_hostlist->hostlist_uri); GNUNET_STATISTICS_update (stats, stat, 1, GNUNET_YES); GNUNET_free (stat); } else current_hostlist->quality = checked_sub (current_hostlist->quality, HOSTLIST_FAILED_DOWNLOAD); } current_hostlist = NULL; /* Alternating the usage of preconfigured and learned hostlists */ if (stat_testing_hostlist == GNUNET_YES) return; if (GNUNET_YES == stat_learning) { if (stat_use_bootstrap == GNUNET_YES) stat_use_bootstrap = GNUNET_NO; else stat_use_bootstrap = GNUNET_YES; } else stat_use_bootstrap = GNUNET_YES; } /** * Clean up the state from the task that downloaded the * hostlist and schedule the next task. */ static void clean_up () { CURLMcode mret; if ((stat_testing_hostlist == GNUNET_YES) && (GNUNET_NO == stat_download_successful) && (NULL != hostlist_to_test)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Advertised hostlist with URI `%s' could not be downloaded. Advertised URI gets dismissed.\n"), hostlist_to_test->hostlist_uri); } if (stat_testing_hostlist == GNUNET_YES) { stat_testing_hostlist = GNUNET_NO; } if (NULL != hostlist_to_test) { GNUNET_free (hostlist_to_test); hostlist_to_test = NULL; } if (multi != NULL) { mret = curl_multi_remove_handle (multi, curl); if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_remove_handle", __FILE__, __LINE__, curl_multi_strerror (mret)); } mret = curl_multi_cleanup (multi); if (mret != CURLM_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_cleanup", __FILE__, __LINE__, curl_multi_strerror (mret)); multi = NULL; } if (curl != NULL) { curl_easy_cleanup (curl); curl = NULL; } GNUNET_free_non_null (current_url); current_url = NULL; stat_bytes_downloaded = 0; stat_download_in_progress = GNUNET_NO; } /** * Task that is run when we are ready to receive more data from the hostlist * server. * * @param cls closure, unused * @param tc task context, unused */ static void task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Ask CURL for the select set and then schedule the * receiving task with the scheduler. */ static void download_prepare () { CURLMcode mret; fd_set rs; fd_set ws; fd_set es; int max; struct GNUNET_NETWORK_FDSet *grs; struct GNUNET_NETWORK_FDSet *gws; long timeout; struct GNUNET_TIME_Relative rtime; max = -1; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); mret = curl_multi_fdset (multi, &rs, &ws, &es, &max); if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_fdset", __FILE__, __LINE__, curl_multi_strerror (mret)); clean_up (); return; } mret = curl_multi_timeout (multi, &timeout); if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_timeout", __FILE__, __LINE__, curl_multi_strerror (mret)); clean_up (); return; } rtime = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (end_time), GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, timeout)); grs = GNUNET_NETWORK_fdset_create (); gws = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task for hostlist download using cURL\n"); ti_download = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, rtime, grs, gws, &task_download, multi); GNUNET_NETWORK_fdset_destroy (gws); GNUNET_NETWORK_fdset_destroy (grs); } /** * Task that is run when we are ready to receive more data from the hostlist * server. * * @param cls closure, unused * @param tc task context, unused */ static void task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int running; struct CURLMsg *msg; CURLMcode mret; ti_download = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown requested while trying to download hostlist from `%s'\n", current_url); update_hostlist (); clean_up (); return; } if (0 == GNUNET_TIME_absolute_get_remaining (end_time).rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Timeout trying to download hostlist from `%s'\n"), current_url); update_hostlist (); clean_up (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ready for processing hostlist client request\n"); do { running = 0; if (stat_bytes_downloaded > MAX_BYTES_PER_HOSTLISTS) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Download limit of %u bytes exceeded, stopping download\n"), MAX_BYTES_PER_HOSTLISTS); clean_up (); return; } mret = curl_multi_perform (multi, &running); if (running == 0) { do { msg = curl_multi_info_read (multi, &running); GNUNET_break (msg != NULL); if (msg == NULL) break; switch (msg->msg) { case CURLMSG_DONE: if ((msg->data.result != CURLE_OK) && (msg->data.result != CURLE_GOT_NOTHING)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Download of hostlist from `%s' failed: `%s'\n"), current_url, curl_easy_strerror (msg->data.result)); else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Download of hostlist `%s' completed.\n"), current_url); stat_download_successful = GNUNET_YES; update_hostlist (); if (GNUNET_YES == stat_testing_hostlist) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Adding successfully tested hostlist `%s' datastore.\n"), current_url); insert_hostlist (); hostlist_to_test = NULL; stat_testing_hostlist = GNUNET_NO; } } clean_up (); return; default: break; } } while ((running > 0)); } } while (mret == CURLM_CALL_MULTI_PERFORM); if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("%s failed at %s:%d: `%s'\n"), "curl_multi_perform", __FILE__, __LINE__, curl_multi_strerror (mret)); clean_up (); } download_prepare (); } /** * Main function that will download a hostlist and process its * data. */ static void download_hostlist () { CURLcode ret; CURLMcode mret; current_url = download_get_url (); if (current_url == NULL) return; curl = curl_easy_init (); multi = NULL; if (curl == NULL) { GNUNET_break (0); clean_up (); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, _("Bootstrapping using hostlist at `%s'.\n"), current_url); stat_download_in_progress = GNUNET_YES; stat_download_successful = GNUNET_NO; stat_hellos_obtained = 0; stat_bytes_downloaded = 0; GNUNET_STATISTICS_update (stats, gettext_noop ("# hostlist downloads initiated"), 1, GNUNET_NO); if (proxy != NULL) CURL_EASY_SETOPT (curl, CURLOPT_PROXY, proxy); download_pos = 0; stat_bogus_url = 0; CURL_EASY_SETOPT (curl, CURLOPT_WRITEFUNCTION, &callback_download); if (ret != CURLE_OK) { clean_up (); return; } CURL_EASY_SETOPT (curl, CURLOPT_WRITEDATA, NULL); if (ret != CURLE_OK) { clean_up (); return; } CURL_EASY_SETOPT (curl, CURLOPT_FOLLOWLOCATION, 1); CURL_EASY_SETOPT (curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); CURL_EASY_SETOPT (curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); CURL_EASY_SETOPT (curl, CURLOPT_MAXREDIRS, 4); /* no need to abort if the above failed */ CURL_EASY_SETOPT (curl, CURLOPT_URL, current_url); if (ret != CURLE_OK) { clean_up (); return; } CURL_EASY_SETOPT (curl, CURLOPT_FAILONERROR, 1); #if 0 CURL_EASY_SETOPT (curl, CURLOPT_VERBOSE, 1); #endif CURL_EASY_SETOPT (curl, CURLOPT_BUFFERSIZE, GNUNET_SERVER_MAX_MESSAGE_SIZE); if (0 == strncmp (current_url, "http", 4)) CURL_EASY_SETOPT (curl, CURLOPT_USERAGENT, "GNUnet"); CURL_EASY_SETOPT (curl, CURLOPT_CONNECTTIMEOUT, 60L); CURL_EASY_SETOPT (curl, CURLOPT_TIMEOUT, 60L); #if 0 /* this should no longer be needed; we're now single-threaded! */ CURL_EASY_SETOPT (curl, CURLOPT_NOSIGNAL, 1); #endif multi = curl_multi_init (); if (multi == NULL) { GNUNET_break (0); /* clean_up (); */ return; } mret = curl_multi_add_handle (multi, curl); if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_add_handle", __FILE__, __LINE__, curl_multi_strerror (mret)); mret = curl_multi_cleanup (multi); if (mret != CURLM_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_cleanup", __FILE__, __LINE__, curl_multi_strerror (mret)); multi = NULL; clean_up (); return; } end_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); download_prepare (); } static void task_download_dispatcher (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { ti_download_dispatcher_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download is initiated...\n"); if (GNUNET_NO == stat_download_in_progress) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download can start immediately...\n"); download_hostlist (); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download in progess, have to wait...\n"); ti_download_dispatcher_task = GNUNET_SCHEDULER_add_delayed (WAITING_INTERVALL, &task_download_dispatcher, NULL); } } /** * Task that checks if we should try to download a hostlist. * If so, we initiate the download, otherwise we schedule * this task again for a later time. */ static void task_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static int once; struct GNUNET_TIME_Relative delay; ti_check_download = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; if (stats == NULL) { curl_global_cleanup (); return; /* in shutdown */ } if ( (stat_connection_count < MIN_CONNECTIONS) && (GNUNET_SCHEDULER_NO_TASK == ti_download_dispatcher_task) ) ti_download_dispatcher_task = GNUNET_SCHEDULER_add_now (&task_download_dispatcher, NULL); delay = hostlist_delay; if (0 == hostlist_delay.rel_value_us) hostlist_delay = GNUNET_TIME_UNIT_SECONDS; else hostlist_delay = GNUNET_TIME_relative_multiply (hostlist_delay, 2); if (hostlist_delay.rel_value_us > GNUNET_TIME_UNIT_HOURS.rel_value_us * (1 + stat_connection_count)) hostlist_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, (1 + stat_connection_count)); GNUNET_STATISTICS_set (stats, gettext_noop ("# milliseconds between hostlist downloads"), hostlist_delay.rel_value_us / 1000LL, GNUNET_YES); if (0 == once) { delay = GNUNET_TIME_UNIT_ZERO; once = 1; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Have %u/%u connections. Will consider downloading hostlist in %s\n"), stat_connection_count, MIN_CONNECTIONS, GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); ti_check_download = GNUNET_SCHEDULER_add_delayed (delay, &task_check, NULL); } /** * This tasks sets hostlist testing to allowed after intervall between to testings is reached * * @param cls closure * @param tc TaskContext */ static void task_testing_intervall_reset (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { ti_testing_intervall_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; stat_testing_allowed = GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing new hostlist advertisements is allowed again\n"); } /** * Task that writes hostlist entries to a file on a regular base * * @param cls closure * @param tc TaskContext */ static void task_hostlist_saving (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { ti_saving_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; save_hostlist_file (GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlists will be saved to file again in %s\n", GNUNET_STRINGS_relative_time_to_string(SAVING_INTERVALL, GNUNET_YES)); ti_saving_task = GNUNET_SCHEDULER_add_delayed (SAVING_INTERVALL, &task_hostlist_saving, NULL); } /** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void handler_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_assert (stat_connection_count < UINT_MAX); stat_connection_count++; GNUNET_STATISTICS_update (stats, gettext_noop ("# active connections"), 1, GNUNET_NO); } /** * Method called whenever a given peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void handler_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_assert (stat_connection_count > 0); stat_connection_count--; GNUNET_STATISTICS_update (stats, gettext_noop ("# active connections"), -1, GNUNET_NO); } /** * Method called whenever an advertisement message arrives. * * @param cls closure (always NULL) * @param peer the peer sending the message * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handler_advertisement (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { size_t size; size_t uri_size; const struct GNUNET_MessageHeader *incoming; const char *uri; struct Hostlist *hostlist; GNUNET_assert (ntohs (message->type) == GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT); size = ntohs (message->size); if (size <= sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } incoming = (const struct GNUNET_MessageHeader *) message; uri = (const char *) &incoming[1]; uri_size = size - sizeof (struct GNUNET_MessageHeader); if (uri[uri_size - 1] != '\0') { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist client recieved advertisement from `%s' containing URI `%s'\n", GNUNET_i2s (peer), uri); if (GNUNET_NO != linked_list_contains (uri)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URI `%s' is already known\n", uri); return GNUNET_OK; } if (GNUNET_NO == stat_testing_allowed) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Currently not accepting new advertisements: interval between to advertisements is not reached\n"); return GNUNET_SYSERR; } if (GNUNET_YES == stat_testing_hostlist) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Currently not accepting new advertisements: we are already testing a hostlist\n"); return GNUNET_SYSERR; } hostlist = GNUNET_malloc (sizeof (struct Hostlist) + uri_size); hostlist->hostlist_uri = (const char *) &hostlist[1]; memcpy (&hostlist[1], uri, uri_size); hostlist->time_creation = GNUNET_TIME_absolute_get (); hostlist->quality = HOSTLIST_INITIAL; hostlist_to_test = hostlist; stat_testing_hostlist = GNUNET_YES; stat_testing_allowed = GNUNET_NO; ti_testing_intervall_task = GNUNET_SCHEDULER_add_delayed (TESTING_INTERVAL, &task_testing_intervall_reset, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing new hostlist advertisements is locked for the next %s\n", GNUNET_STRINGS_relative_time_to_string (TESTING_INTERVAL, GNUNET_YES)); ti_download_dispatcher_task = GNUNET_SCHEDULER_add_now (&task_download_dispatcher, NULL); return GNUNET_OK; } /** * Continuation called by the statistics code once * we go the stat. Initiates hostlist download scheduling. * * @param cls closure * @param success #GNUNET_OK if statistics were * successfully obtained, #GNUNET_SYSERR if not. */ static void primary_task (void *cls, int success) { sget = NULL; GNUNET_assert (stats != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Statistics request done, scheduling hostlist download\n"); ti_check_download = GNUNET_SCHEDULER_add_now (&task_check, NULL); } /** * We've received the previous delay value from statistics. Remember it. * * @param cls NULL, unused * @param subsystem should be "hostlist", unused * @param name will be "milliseconds between hostlist downloads", unused * @param value previous delay value, in milliseconds (!) * @param is_persistent unused, will be GNUNET_YES */ static int process_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { hostlist_delay.rel_value_us = value * 1000LL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initial time between hostlist downloads is %s\n", GNUNET_STRINGS_relative_time_to_string (hostlist_delay, GNUNET_YES)); return GNUNET_OK; } /** * Method to load persistent hostlist file during hostlist client startup */ static void load_hostlist_file () { char *filename; char *uri; char *emsg; struct Hostlist *hostlist; uint32_t times_used; uint32_t hellos_returned; uint64_t quality; uint64_t last_used; uint64_t created; uint32_t counter; uri = NULL; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST", "HOSTLISTFILE", &filename)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, "hostlist", "HOSTLISTFILE"); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading saved hostlist entries from file `%s' \n"), filename); if (GNUNET_NO == GNUNET_DISK_file_test (filename)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Hostlist file `%s' does not exist\n"), filename); GNUNET_free (filename); return; } struct GNUNET_BIO_ReadHandle *rh = GNUNET_BIO_read_open (filename); if (NULL == rh) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Could not open file `%s' for reading to load hostlists: %s\n"), filename, STRERROR (errno)); GNUNET_free (filename); return; } counter = 0; while ((GNUNET_OK == GNUNET_BIO_read_string (rh, "url", &uri, MAX_URL_LEN)) && (NULL != uri) && (GNUNET_OK == GNUNET_BIO_read_int32 (rh, ×_used)) && (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &quality)) && (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &last_used)) && (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &created)) && (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &hellos_returned))) { hostlist = GNUNET_malloc (sizeof (struct Hostlist) + strlen (uri) + 1); hostlist->hello_count = hellos_returned; hostlist->hostlist_uri = (const char *) &hostlist[1]; memcpy (&hostlist[1], uri, strlen (uri) + 1); hostlist->quality = quality; hostlist->time_creation.abs_value_us = created; hostlist->time_last_usage.abs_value_us = last_used; GNUNET_CONTAINER_DLL_insert (linked_list_head, linked_list_tail, hostlist); linked_list_size++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added hostlist entry eith URI `%s' \n", hostlist->hostlist_uri); GNUNET_free (uri); uri = NULL; counter++; if (counter >= MAX_NUMBER_HOSTLISTS) break; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("%u hostlist URIs loaded from file\n"), counter); GNUNET_STATISTICS_set (stats, gettext_noop ("# hostlist URIs read from file"), counter, GNUNET_YES); GNUNET_STATISTICS_set (stats, gettext_noop ("# advertised hostlist URIs"), linked_list_size, GNUNET_NO); GNUNET_free_non_null (uri); emsg = NULL; (void) GNUNET_BIO_read_close (rh, &emsg); if (emsg != NULL) GNUNET_free (emsg); GNUNET_free (filename); } /** * Method to save persistent hostlist file during hostlist client shutdown * @param shutdown set if called because of shutdown, entries in linked list will be destroyed */ static void save_hostlist_file (int shutdown) { char *filename; struct Hostlist *pos; struct GNUNET_BIO_WriteHandle *wh; int ok; uint32_t counter; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST", "HOSTLISTFILE", &filename)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, "hostlist", "HOSTLISTFILE"); return; } if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename)) { GNUNET_free (filename); return; } wh = GNUNET_BIO_write_open (filename); if (NULL == wh) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not open file `%s' for writing to save hostlists: %s\n"), filename, STRERROR (errno)); GNUNET_free (filename); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Writing %u hostlist URIs to `%s'\n"), linked_list_size, filename); /* add code to write hostlists to file using bio */ ok = GNUNET_YES; counter = 0; while (NULL != (pos = linked_list_head)) { if (GNUNET_YES == shutdown) { GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail, pos); linked_list_size--; } if (GNUNET_YES == ok) { if ((GNUNET_OK != GNUNET_BIO_write_string (wh, pos->hostlist_uri)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->times_used)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, pos->quality)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, pos->time_last_usage.abs_value_us)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, pos->time_creation.abs_value_us)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->hello_count))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Error writing hostlist URIs to file `%s'\n"), filename); ok = GNUNET_NO; } } if (GNUNET_YES == shutdown) GNUNET_free (pos); counter++; if (counter >= MAX_NUMBER_HOSTLISTS) break; } GNUNET_STATISTICS_set (stats, gettext_noop ("# hostlist URIs written to file"), counter, GNUNET_YES); if (GNUNET_OK != GNUNET_BIO_write_close (wh)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Error writing hostlist URIs to file `%s'\n"), filename); GNUNET_free (filename); } /** * Start downloading hostlists from hostlist servers as necessary. */ int GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_STATISTICS_Handle *st, GNUNET_CORE_ConnectEventHandler *ch, GNUNET_CORE_DisconnectEventHandler *dh, GNUNET_CORE_MessageCallback *msgh, int learn) { char *filename; int result; GNUNET_assert (NULL != st); if (0 != curl_global_init (CURL_GLOBAL_WIN32)) { GNUNET_break (0); return GNUNET_SYSERR; } transport = GNUNET_TRANSPORT_connect (c, NULL, NULL, NULL, NULL, NULL); if (NULL == transport) { curl_global_cleanup (); return GNUNET_SYSERR; } cfg = c; stats = st; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST", "HTTP-PROXY", &proxy)) proxy = NULL; stat_learning = learn; *ch = &handler_connect; *dh = &handler_disconnect; linked_list_head = NULL; linked_list_tail = NULL; stat_use_bootstrap = GNUNET_YES; stat_testing_hostlist = GNUNET_NO; stat_testing_allowed = GNUNET_YES; if (GNUNET_YES == stat_learning) { *msgh = &handler_advertisement; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Learning is enabled on this peer\n")); load_hostlist_file (); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlists will be saved to file again in %s\n", GNUNET_STRINGS_relative_time_to_string (SAVING_INTERVALL, GNUNET_YES)); ti_saving_task = GNUNET_SCHEDULER_add_delayed (SAVING_INTERVALL, &task_hostlist_saving, NULL); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Learning is not enabled on this peer\n")); *msgh = NULL; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "HOSTLIST", "HOSTLISTFILE", &filename)) { if (GNUNET_YES == GNUNET_DISK_file_test (filename)) { result = remove (filename); if (result == 0) GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Since learning is not enabled on this peer, hostlist file `%s' was removed\n"), filename); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Hostlist file `%s' could not be removed\n"), filename); } } GNUNET_free (filename); } sget = GNUNET_STATISTICS_get (stats, "hostlist", gettext_noop ("# milliseconds between hostlist downloads"), GNUNET_TIME_UNIT_MINUTES, &primary_task, &process_stat, NULL); return GNUNET_OK; } /** * Stop downloading hostlists from hostlist servers as necessary. */ void GNUNET_HOSTLIST_client_stop () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist client shutdown\n"); if (NULL != sget) { GNUNET_STATISTICS_get_cancel (sget); sget = NULL; } stats = NULL; if (GNUNET_YES == stat_learning) save_hostlist_file (GNUNET_YES); if (ti_saving_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ti_saving_task); ti_saving_task = GNUNET_SCHEDULER_NO_TASK; } if (ti_download_dispatcher_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ti_download_dispatcher_task); ti_download_dispatcher_task = GNUNET_SCHEDULER_NO_TASK; } if (ti_testing_intervall_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ti_testing_intervall_task); ti_testing_intervall_task = GNUNET_SCHEDULER_NO_TASK; } if (ti_download != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ti_download); ti_download = GNUNET_SCHEDULER_NO_TASK; } if (ti_check_download != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ti_check_download); ti_check_download = GNUNET_SCHEDULER_NO_TASK; curl_global_cleanup (); } if (transport != NULL) { GNUNET_TRANSPORT_disconnect (transport); transport = NULL; } GNUNET_free_non_null (proxy); proxy = NULL; cfg = NULL; } /* end of hostlist-client.c */ gnunet-0.10.1/src/hostlist/test_hostlist_defaults.conf0000644000175000017500000000145012306305335020120 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-hostlist/ [resolver] PORT = 12464 [transport] PORT = 12465 PLUGINS = tcp [arm] PORT = 12466 DEFAULTSERVICES = hostlist [statistics] PORT = 12467 [tcp] PORT = 12468 [peerinfo] PORT = 12469 NO_IO = YES [core] PORT = 12470 [testing] WEAKRANDOM = YES [hostlist] HTTP-PROXY = [mesh] AUTOSTART = NO [dns] AUTOSTART = NO [nse] AUTOSTART = NO [datastore] AUTOSTART = NO [fs] AUTOSTART = NO [dht] AUTOSTART = NO [dv] AUTOSTART = NO [revocation] AUTOSTART = NO [gns] AUTOSTART = NO [vpn] AUTOSTART = NO [namestore] AUTOSTART = NO [namecache] AUTOSTART = NO [nat] RETURN_LOCAL_ADDRESSES = YES [consensus] AUTOSTART = NO [regex] AUTOSTART = NO [identity] AUTOSTART = NO [conversation] AUTOSTART = NO [psycstore] AUTOSTART = NO [set] AUTOSTART = NO gnunet-0.10.1/src/hostlist/gnunet-daemon-hostlist.h0000644000175000017500000000276012225777503017252 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/gnunet-daemon-hostlist.h * @brief common internal definitions for hostlist daemon * @author Matthias Wachs */ #include #include "platform.h" #include "hostlist-client.h" #include "hostlist-server.h" #include "gnunet_core_service.h" #include "gnunet_getopt_lib.h" #include "gnunet_protocols.h" #include "gnunet_program_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_strings_lib.h" #include "gnunet_time_lib.h" #include "gnunet_util_lib.h" /** * General hostlist daemon debugging. */ #define DEBUG_HOSTLIST GNUNET_EXTRA_LOGGING #define MAX_URL_LEN 1000 #define MAX_BYTES_PER_HOSTLISTS 500000 /* end of gnunet-daemon-hostlist.h */ gnunet-0.10.1/src/hostlist/learning_data.conf0000644000175000017500000000022612225230043016102 00000000000000@INLINE@ test_hostlist_defaults.conf [hostlist] HTTPPORT = 28080 OPTIONS = -b -e SERVERS = http://gnunet.org:8080/ PORT = 23354 HOSTNAME = localhost gnunet-0.10.1/src/hostlist/test_gnunet_daemon_hostlist.c0000644000175000017500000001507112301361473020435 00000000000000/* This file is part of GNUnet (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hostlist/test_gnunet_daemon_hostlist.c * @brief test for gnunet_daemon_hostslist.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_transport_service.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 150) static int ok; static GNUNET_SCHEDULER_TaskIdentifier timeout_task; struct PeerContext { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_TRANSPORT_Handle *th; struct GNUNET_MessageHeader *hello; struct GNUNET_TRANSPORT_GetHelloHandle *ghh; struct GNUNET_OS_Process *arm_proc; }; static struct PeerContext p1; static struct PeerContext p2; static void clean_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (p1.th != NULL) { if (p1.ghh != NULL) { GNUNET_TRANSPORT_get_hello_cancel (p1.ghh); p1.ghh = NULL; } GNUNET_TRANSPORT_disconnect (p1.th); p1.th = NULL; } if (p2.th != NULL) { if (p2.ghh != NULL) { GNUNET_TRANSPORT_get_hello_cancel (p2.ghh); p2.ghh = NULL; } GNUNET_TRANSPORT_disconnect (p2.th); p2.th = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Timeout, give up. */ static void timeout_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout trying to connect peers, test failed.\n"); clean_up (NULL, tc); } /** * Function called to notify transport users that another * peer connected to us. * * @param cls closure * @param peer the peer that connected * @param latency current latency of the connection * @param distance in overlay hops, as given by transport plugin */ static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { if (peer == NULL) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected, shutting down.\n"); ok = 0; if (timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_now (&clean_up, NULL); } static void process_hello (void *cls, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; GNUNET_TRANSPORT_get_hello_cancel (p->ghh); p->ghh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received HELLO, starting hostlist service.\n"); } static void setup_peer (struct PeerContext *p, const char *cfgname) { char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); p->cfg = GNUNET_CONFIGURATION_create (); p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-arm", "-c", cfgname, NULL); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, NULL, ¬ify_connect, NULL); GNUNET_assert (p->th != NULL); p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &process_hello, p); GNUNET_free (binary); } static void waitpid_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Killing ARM process.\n"); if (0 != GNUNET_OS_process_kill (p->arm_proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; GNUNET_CONFIGURATION_destroy (p->cfg); } static void stop_arm (struct PeerContext *p) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking ARM to stop core service\n"); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &waitpid_task, p); } /** * Try again to connect to transport service. */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { stop_arm (&p1); stop_arm (&p2); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_assert (ok == 1); ok++; timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_error, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); setup_peer (&p1, "test_gnunet_daemon_hostlist_peer1.conf"); setup_peer (&p2, "test_gnunet_daemon_hostlist_peer2.conf"); } static int check () { char *const argv[] = { "test-gnunet-daemon-hostlist", "-c", "test_gnunet_daemon_hostlist_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-gnunet-daemon-hostlist", "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist"); GNUNET_log_setup ("test-gnunet-daemon-hostlist", "WARNING", NULL); ret = check (); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist"); return ret; } /* end of test_gnunet_daemon_hostlist.c */ gnunet-0.10.1/src/hostlist/test_gnunet_daemon_hostlist_peer1.conf0000644000175000017500000000155212225230043022224 00000000000000@INLINE@ test_hostlist_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-hostlist-peer-1/ [transport-tcp] PORT = 12968 [arm] PORT = 12966 DEFAULTSERVICES = hostlist topology UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12967 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12964 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12969 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12965 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [core] PORT = 12970 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-core.sock [hostlist] HTTPPORT = 12980 HOSTLISTFILE = hostlists_peer1.file OPTIONS = -b -p SERVERS = http://localhost:12981/ [ats] PORT = 12971 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-ats.sock gnunet-0.10.1/src/hostlist/test_learning_adv_peer.conf0000644000175000017500000000173412225230043020022 00000000000000@INLINE@ test_hostlist_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-hostlist-peer-1/ [transport-tcp] PORT = 22968 [arm] PORT = 22966 DEFAULTSERVICES = topology hostlist UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p2-service-arm.sock [statistics] PORT = 22967 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p2-service-statistics.sock [resolver] PORT = 22964 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p2-service-resolver.sock [peerinfo] PORT = 22969 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p2-service-peerinfo.sock [transport] PORT = 22965 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p2-service-transport.sock [core] PORT = 22970 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-hostlist-p2-service-core.sock [hostlist] HTTPPORT = 12981 HOSTLISTFILE = hostlists_adv_peer.file OPTIONS = -p -a SERVERS = http://localhost:12981/ EXTERNAL_DNS_NAME = localhost [dht] AUTOSTART = NO [ats] PORT = 22971 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-ats-p2-service-core.sock gnunet-0.10.1/src/topology/0000755000175000017500000000000012320755625012544 500000000000000gnunet-0.10.1/src/topology/test_gnunet_daemon_topology_data.conf0000644000175000017500000000155712225230043022134 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-topology/ [resolver] PORT = 2664 [transport] PORT = 2665 PLUGINS = tcp #PREFIX = xterm -e xterm -T transport -e gdb -x cmd --args #PREFIX = valgrind --tool=memcheck --log-file=logs%p [arm] PORT = 2666 DEFAULTSERVICES = topology [testbed] OVERLAY_TOPOLOGY=LINE [statistics] PORT = 2667 [transport-tcp] PORT = 2668 BINDTO = 127.0.0.1 [nat] DISABLEV6 = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 USE_LOCALADDR = NO USE_HOSTNAME = NO [peerinfo] PORT = 2669 [core] PORT = 2670 [topology] #PREFIX = valgrind --tool=memcheck [fs] AUTOSTART = NO [datastore] AUTOSTART = NO [testing] WEAKRANDOM = YES [testing_old] HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat [dns] AUTOSTART = NO [namestore] AUTOSTART = NO [nse] AUTOSTART = NO [consensus] AUTOSTART = NO gnunet-0.10.1/src/topology/Makefile.in0000644000175000017500000012240512320752064014527 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-daemon-topology$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = \ @HAVE_TESTING_TRUE@ test_gnunet_daemon_topology$(EXEEXT) subdir = src/topology DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgcfg_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetfriends_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetfriends_la_OBJECTS = friends.lo libgnunetfriends_la_OBJECTS = $(am_libgnunetfriends_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetfriends_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetfriends_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(libexec_PROGRAMS) am_gnunet_daemon_topology_OBJECTS = gnunet-daemon-topology.$(OBJEXT) gnunet_daemon_topology_OBJECTS = $(am_gnunet_daemon_topology_OBJECTS) gnunet_daemon_topology_DEPENDENCIES = libgnunetfriends.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_gnunet_daemon_topology_OBJECTS = \ test_gnunet_daemon_topology.$(OBJEXT) test_gnunet_daemon_topology_OBJECTS = \ $(am_test_gnunet_daemon_topology_OBJECTS) test_gnunet_daemon_topology_DEPENDENCIES = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetfriends_la_SOURCES) \ $(gnunet_daemon_topology_SOURCES) \ $(test_gnunet_daemon_topology_SOURCES) DIST_SOURCES = $(libgnunetfriends_la_SOURCES) \ $(gnunet_daemon_topology_SOURCES) \ $(test_gnunet_daemon_topology_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 pkgcfgdir = $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ topology.conf lib_LTLIBRARIES = libgnunetfriends.la libgnunetfriends_la_SOURCES = \ friends.c libgnunetfriends_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetfriends_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 gnunet_daemon_topology_SOURCES = \ gnunet-daemon-topology.c gnunet_daemon_topology_LDADD = \ libgnunetfriends.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_gnunet_daemon_topology_SOURCES = \ test_gnunet_daemon_topology.c test_gnunet_daemon_topology_LDADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_gnunet_daemon_topology_data.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/topology/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/topology/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetfriends.la: $(libgnunetfriends_la_OBJECTS) $(libgnunetfriends_la_DEPENDENCIES) $(EXTRA_libgnunetfriends_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetfriends_la_LINK) -rpath $(libdir) $(libgnunetfriends_la_OBJECTS) $(libgnunetfriends_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-daemon-topology$(EXEEXT): $(gnunet_daemon_topology_OBJECTS) $(gnunet_daemon_topology_DEPENDENCIES) $(EXTRA_gnunet_daemon_topology_DEPENDENCIES) @rm -f gnunet-daemon-topology$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_topology_OBJECTS) $(gnunet_daemon_topology_LDADD) $(LIBS) test_gnunet_daemon_topology$(EXEEXT): $(test_gnunet_daemon_topology_OBJECTS) $(test_gnunet_daemon_topology_DEPENDENCIES) $(EXTRA_test_gnunet_daemon_topology_DEPENDENCIES) @rm -f test_gnunet_daemon_topology$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_daemon_topology_OBJECTS) $(test_gnunet_daemon_topology_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/friends.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-topology.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_daemon_topology.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_gnunet_daemon_topology.log: test_gnunet_daemon_topology$(EXEEXT) @p='test_gnunet_daemon_topology$(EXEEXT)'; \ b='test_gnunet_daemon_topology'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_pkgcfgDATA uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dist_pkgcfgDATA install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-dist_pkgcfgDATA \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/topology/friends.c0000644000175000017500000001336012316473376014272 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file topology/friends.c * @brief library to read and write the FRIENDS file * @author Christian Grothoff */ #include "platform.h" #include "gnunet_friends_lib.h" /** * Parse the FRIENDS file. * * @param cfg our configuration * @param cb function to call on each friend found * @param cb_cls closure for @a cb * @return #GNUNET_OK on success, #GNUNET_SYSERR on parsing errors */ int GNUNET_FRIENDS_parse (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_FRIENDS_Callback cb, void *cb_cls) { char *fn; char *data; size_t pos; size_t start; struct GNUNET_PeerIdentity pid; uint64_t fsize; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "TOPOLOGY", "FRIENDS", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "topology", "FRIENDS"); return GNUNET_SYSERR; } if ( (GNUNET_OK != GNUNET_DISK_file_test (fn)) && (GNUNET_OK != GNUNET_DISK_fn_write (fn, NULL, 0, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn); if ( (GNUNET_OK != GNUNET_DISK_file_size (fn, &fsize, GNUNET_NO, GNUNET_YES)) || (0 == fsize) ) { GNUNET_free (fn); return GNUNET_OK; } data = GNUNET_malloc_large (fsize); if (NULL == data) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "malloc"); GNUNET_free (fn); return GNUNET_SYSERR; } if (fsize != GNUNET_DISK_fn_read (fn, data, fsize)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "read", "fn"); GNUNET_free (fn); GNUNET_free (data); return GNUNET_SYSERR; } start = 0; pos = 0; while (pos < fsize) { while ((pos < fsize) && (! isspace ((int) data[pos]))) pos++; if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (&data[start], pos - start, &pid.public_key)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Syntax error in FRIENDS file at offset %llu, skipping bytes `%.*s'.\n"), (unsigned long long) pos, (int) (pos - start), &data[start]); pos++; start = pos; continue; } pos++; start = pos; cb (cb_cls, &pid); } GNUNET_free (data); GNUNET_free (fn); return GNUNET_OK; } /** * Handle for writing a friends file. */ struct GNUNET_FRIENDS_Writer { /** * Handle to the file. */ struct GNUNET_DISK_FileHandle *fh; }; /** * Start writing a fresh FRIENDS file. Will make a backup of the * old one. * * @param cfg configuration to use. * @return NULL on error */ struct GNUNET_FRIENDS_Writer * GNUNET_FRIENDS_write_start (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_FRIENDS_Writer *w; char *fn; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "TOPOLOGY", "FRIENDS", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "topology", "FRIENDS"); return NULL; } if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Directory for file `%s' does not seem to be writable.\n"), fn); return NULL; } if (GNUNET_OK == GNUNET_DISK_file_test (fn)) GNUNET_DISK_file_backup (fn); w = GNUNET_new (struct GNUNET_FRIENDS_Writer); w->fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_FAILIFEXISTS, GNUNET_DISK_PERM_USER_READ); GNUNET_free (fn); if (NULL == w->fh) { GNUNET_free (w); return NULL; } return w; } /** * Finish writing out the friends file. * * @param w write handle * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_FRIENDS_write_stop (struct GNUNET_FRIENDS_Writer *w) { int ret; ret = GNUNET_DISK_file_close (w->fh); GNUNET_free (w); return ret; } /** * Add a friend to the friends file. * * @param w write handle * @param friend_id friend to add * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_FRIENDS_write (struct GNUNET_FRIENDS_Writer *w, const struct GNUNET_PeerIdentity *friend_id) { char *buf; char *ret; size_t slen; ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&friend_id->public_key); GNUNET_asprintf (&buf, "%s\n", ret); GNUNET_free (ret); slen = strlen (buf); if (slen != GNUNET_DISK_file_write (w->fh, buf, slen)) { GNUNET_free (buf); return GNUNET_SYSERR; } GNUNET_free (buf); return GNUNET_OK; } /* end of friends.c */ gnunet-0.10.1/src/topology/Makefile.am0000644000175000017500000000270112320751517014514 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ dist_pkgcfg_DATA = \ topology.conf lib_LTLIBRARIES = libgnunetfriends.la libgnunetfriends_la_SOURCES = \ friends.c libgnunetfriends_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetfriends_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libexec_PROGRAMS = \ gnunet-daemon-topology gnunet_daemon_topology_SOURCES = \ gnunet-daemon-topology.c gnunet_daemon_topology_LDADD = \ libgnunetfriends.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) if HAVE_TESTING check_PROGRAMS = \ test_gnunet_daemon_topology endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_gnunet_daemon_topology_SOURCES = \ test_gnunet_daemon_topology.c test_gnunet_daemon_topology_LDADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_gnunet_daemon_topology_data.conf gnunet-0.10.1/src/topology/topology.conf0000644000175000017500000000024112225230043015166 00000000000000[topology] MINIMUM-FRIENDS = 0 FRIENDS-ONLY = NO TARGET-CONNECTION-COUNT = 16 FRIENDS = $GNUNET_CONFIG_HOME/topology/friends.txt BINARY = gnunet-daemon-topology gnunet-0.10.1/src/topology/test_gnunet_daemon_topology.c0000644000175000017500000000512412225777501020451 00000000000000/* This file is part of GNUnet. (C) 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file topology/test_gnunet_daemon_topology.c * @brief testcase for topology maintenance code */ #include "platform.h" #include "gnunet_testbed_service.h" #define NUM_PEERS 8 /** * How long until we give up on connecting the peers? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) static int ok; static unsigned int connect_left; static void notify_connect_complete (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { GNUNET_TESTBED_operation_done (op); if (NULL != emsg) { FPRINTF (stderr, "Failed to connect two peers: %s\n", emsg); GNUNET_SCHEDULER_shutdown (); ok = 1; return; } connect_left--; if (0 == connect_left) { /* FIXME: check that topology adds a few more links * in addition to those that were seeded */ GNUNET_SCHEDULER_shutdown (); } } static void do_connect (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { unsigned int i; GNUNET_assert (NUM_PEERS == num_peers); for (i=0;iis_friend == GNUNET_YES)) return GNUNET_OK; GNUNET_STATISTICS_update (stats, gettext_noop ("# peers blacklisted"), 1, GNUNET_NO); return GNUNET_SYSERR; } /** * Whitelist all peers that we blacklisted; we've passed * the minimum number of friends. */ static void whitelist_peers () { if (blacklist != NULL) { GNUNET_TRANSPORT_blacklist_cancel (blacklist); blacklist = NULL; } } /** * Check if an additional connection from the given peer is allowed. * * @param peer connection to check * @return GNUNET_OK if the connection is allowed */ static int is_connection_allowed (struct Peer *peer) { if (0 == memcmp (&my_identity, &peer->pid, sizeof (struct GNUNET_PeerIdentity))) return GNUNET_SYSERR; /* disallow connections to self */ if (peer->is_friend) return GNUNET_OK; if (GNUNET_YES == friends_only) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Determined that `%s' is not allowed to connect (not a friend)\n", GNUNET_i2s (&peer->pid)); return GNUNET_SYSERR; } if (friend_count >= minimum_friend_count) return GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Determined that `%s' is not allowed to connect (not enough connected friends)\n", GNUNET_i2s (&peer->pid)); return GNUNET_SYSERR; } /** * Free all resources associated with the given peer. * * @param cls closure (not used) * @param pid identity of the peer * @param value peer to free * @return GNUNET_YES (always: continue to iterate) */ static int free_peer (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) { struct Peer *pos = value; GNUNET_break (GNUNET_NO == pos->is_connected); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (peers, pid, pos)); if (pos->hello_req != NULL) GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req); if (pos->hello_delay_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (pos->hello_delay_task); if (pos->attempt_connect_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (pos->attempt_connect_task); if (pos->greylist_clean_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (pos->greylist_clean_task); GNUNET_free_non_null (pos->hello); if (pos->filter != NULL) GNUNET_CONTAINER_bloomfilter_free (pos->filter); GNUNET_free (pos); return GNUNET_YES; } /** * Discard peer entries for greylisted peers * where the greylisting has expired. * * @param cls 'struct Peer' to greylist * @param tc scheduler context */ static void remove_from_greylist (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Try to connect to the specified peer. * * @param pos peer to connect to */ static void attempt_connect (struct Peer *pos) { struct GNUNET_TIME_Relative rem; if ((connection_count >= target_connection_count) && (friend_count >= minimum_friend_count)) return; if (GNUNET_YES == pos->is_connected) return; if (GNUNET_OK != is_connection_allowed (pos)) return; if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value_us > 0) return; if (GNUNET_YES == pos->is_friend) rem = GREYLIST_AFTER_ATTEMPT_FRIEND; else rem = GREYLIST_AFTER_ATTEMPT; rem = GNUNET_TIME_relative_multiply (rem, connection_count); rem = GNUNET_TIME_relative_divide (rem, target_connection_count); if (pos->connect_attempts > 30) pos->connect_attempts = 30; rem = GNUNET_TIME_relative_multiply (rem, 1 << (++pos->connect_attempts)); rem = GNUNET_TIME_relative_max (rem, GREYLIST_AFTER_ATTEMPT_MIN); rem = GNUNET_TIME_relative_min (rem, GREYLIST_AFTER_ATTEMPT_MAX); pos->greylisted_until = GNUNET_TIME_relative_to_absolute (rem); if (pos->greylist_clean_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (pos->greylist_clean_task); pos->greylist_clean_task = GNUNET_SCHEDULER_add_delayed (rem, &remove_from_greylist, pos); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking to connect to `%s'\n", GNUNET_i2s (&pos->pid)); GNUNET_STATISTICS_update (stats, gettext_noop ("# connect requests issued to transport"), 1, GNUNET_NO); GNUNET_TRANSPORT_try_connect (transport, &pos->pid, NULL, NULL); /*FIXME TRY_CONNECT change */ } /** * Try to connect to the specified peer. * * @param cls peer to connect to * @param tc scheduler context */ static void do_attempt_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Peer *pos = cls; struct GNUNET_TIME_Relative delay; pos->attempt_connect_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_YES == pos->is_connected) return; delay = GNUNET_TIME_absolute_get_remaining (next_connect_attempt); if (delay.rel_value_us > 0) { pos->attempt_connect_task = GNUNET_SCHEDULER_add_delayed (delay, &do_attempt_connect, pos); return; } next_connect_attempt = GNUNET_TIME_relative_to_absolute (MAX_CONNECT_FREQUENCY_DELAY); attempt_connect (pos); } /** * Schedule a task to try to connect to the specified peer. * * @param pos peer to connect to */ static void schedule_attempt_connect (struct Peer *pos) { if (GNUNET_SCHEDULER_NO_TASK != pos->attempt_connect_task) return; pos->attempt_connect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (next_connect_attempt), &do_attempt_connect, pos); } /** * Discard peer entries for greylisted peers * where the greylisting has expired. * * @param cls 'struct Peer' to greylist * @param tc scheduler context */ static void remove_from_greylist (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Peer *pos = cls; struct GNUNET_TIME_Relative rem; pos->greylist_clean_task = GNUNET_SCHEDULER_NO_TASK; rem = GNUNET_TIME_absolute_get_remaining (pos->greylisted_until); if (0 == rem.rel_value_us) { schedule_attempt_connect (pos); } else { pos->greylist_clean_task = GNUNET_SCHEDULER_add_delayed (rem, &remove_from_greylist, pos); } if ((GNUNET_NO == pos->is_friend) && (GNUNET_NO == pos->is_connected) && (NULL == pos->hello)) { free_peer (NULL, &pos->pid, pos); return; } } /** * Create a new entry in the peer list. * * @param peer identity of the new entry * @param hello hello message, can be NULL * @param is_friend is the new entry for a friend? * @return the new entry */ static struct Peer * make_peer (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, int is_friend) { struct Peer *ret; ret = GNUNET_new (struct Peer); ret->pid = *peer; ret->is_friend = is_friend; if (hello != NULL) { ret->hello = GNUNET_malloc (GNUNET_HELLO_size (hello)); memcpy (ret->hello, hello, GNUNET_HELLO_size (hello)); } GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (peers, peer, ret, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return ret; } /** * Setup bloom filter for the given peer entry. * * @param peer entry to initialize */ static void setup_filter (struct Peer *peer) { struct GNUNET_HashCode hc; /* 2^{-5} chance of not sending a HELLO to a peer is * acceptably small (if the filter is 50% full); * 64 bytes of memory are small compared to the rest * of the data structure and would only really become * "useless" once a HELLO has been passed on to ~100 * other peers, which is likely more than enough in * any case; hence 64, 5 as bloomfilter parameters. */ peer->filter = GNUNET_CONTAINER_bloomfilter_init (NULL, 64, 5); peer->filter_expiration = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY); /* never send a peer its own HELLO */ GNUNET_CRYPTO_hash (&peer->pid, sizeof (struct GNUNET_PeerIdentity), &hc); GNUNET_CONTAINER_bloomfilter_add (peer->filter, &hc); } /** * Function to fill send buffer with HELLO. * * @param cls 'struct Peer' of the target peer * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ static size_t hello_advertising_ready (void *cls, size_t size, void *buf); /** * Closure for 'find_advertisable_hello'. */ struct FindAdvHelloContext { /** * Peer we want to advertise to. */ struct Peer *peer; /** * Where to store the result (peer selected for advertising). */ struct Peer *result; /** * Maximum HELLO size we can use right now. */ size_t max_size; struct GNUNET_TIME_Relative next_adv; }; /** * Find a peer that would be reasonable for advertising. * * @param cls closure * @param pid identity of a peer * @param value 'struct Peer*' for the peer we are considering * @return GNUNET_YES (continue iteration) */ static int find_advertisable_hello (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) { struct FindAdvHelloContext *fah = cls; struct Peer *pos = value; struct GNUNET_TIME_Relative rst_time; struct GNUNET_HashCode hc; size_t hs; if (pos == fah->peer) return GNUNET_YES; if (pos->hello == NULL) return GNUNET_YES; rst_time = GNUNET_TIME_absolute_get_remaining (pos->filter_expiration); if (0 == rst_time.rel_value_us) { /* time to discard... */ GNUNET_CONTAINER_bloomfilter_free (pos->filter); setup_filter (pos); } fah->next_adv = GNUNET_TIME_relative_min (rst_time, fah->next_adv); hs = GNUNET_HELLO_size (pos->hello); if (hs > fah->max_size) return GNUNET_YES; GNUNET_CRYPTO_hash (&fah->peer->pid, sizeof (struct GNUNET_PeerIdentity), &hc); if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (pos->filter, &hc)) fah->result = pos; return GNUNET_YES; } /** * Calculate when we would like to send the next HELLO to this * peer and ask for it. * * @param cls for which peer to schedule the HELLO * @param tc task context */ static void schedule_next_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Peer *pl = cls; struct FindAdvHelloContext fah; size_t next_want; struct GNUNET_TIME_Relative delay; pl->hello_delay_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_YES == pl->is_connected); if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; /* we're out of here */ if (pl->hello_req != NULL) return; /* did not finish sending the previous one */ /* find applicable HELLOs */ fah.peer = pl; fah.result = NULL; fah.max_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1; fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_CONTAINER_multipeermap_iterate (peers, &find_advertisable_hello, &fah); pl->hello_delay_task = GNUNET_SCHEDULER_add_delayed (fah.next_adv, &schedule_next_hello, pl); if (fah.result == NULL) return; next_want = GNUNET_HELLO_size (fah.result->hello); delay = GNUNET_TIME_absolute_get_remaining (pl->next_hello_allowed); if (0 == delay.rel_value_us) { /* now! */ pl->hello_req = GNUNET_CORE_notify_transmit_ready (handle, GNUNET_YES, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &pl->pid, next_want, &hello_advertising_ready, pl); } } /** * Cancel existing requests for sending HELLOs to this peer * and recalculate when we should send HELLOs to it based * on our current state (something changed!). * * @param cls closure, 'struct Peer' to skip, or NULL * @param pid identity of a peer * @param value 'struct Peer*' for the peer * @return GNUNET_YES (always) */ static int reschedule_hellos (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) { struct Peer *peer = value; struct Peer *skip = cls; if (skip == peer) return GNUNET_YES; if (!peer->is_connected) return GNUNET_YES; if (peer->hello_req != NULL) { GNUNET_CORE_notify_transmit_ready_cancel (peer->hello_req); peer->hello_req = NULL; } if (peer->hello_delay_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (peer->hello_delay_task); peer->hello_delay_task = GNUNET_SCHEDULER_NO_TASK; } peer->hello_delay_task = GNUNET_SCHEDULER_add_now (&schedule_next_hello, peer); return GNUNET_YES; } /** * Method called whenever a peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { struct Peer *pos; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core told us that we are connecting to `%s'\n", GNUNET_i2s (peer)); if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; connection_count++; GNUNET_STATISTICS_set (stats, gettext_noop ("# peers connected"), connection_count, GNUNET_NO); pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == pos) { pos = make_peer (peer, NULL, GNUNET_NO); GNUNET_break (GNUNET_OK == is_connection_allowed (pos)); } else { GNUNET_assert (GNUNET_NO == pos->is_connected); pos->greylisted_until.abs_value_us = 0; /* remove greylisting */ } pos->is_connected = GNUNET_YES; pos->connect_attempts = 0; /* re-set back-off factor */ if (pos->is_friend) { if ((friend_count == minimum_friend_count - 1) && (GNUNET_YES != friends_only)) whitelist_peers (); friend_count++; GNUNET_STATISTICS_set (stats, gettext_noop ("# friends connected"), friend_count, GNUNET_NO); } reschedule_hellos (NULL, peer, pos); } /** * Try to add more peers to our connection set. * * @param cls closure, not used * @param pid identity of a peer * @param value 'struct Peer*' for the peer * @return GNUNET_YES (continue to iterate) */ static int try_add_peers (void *cls, const struct GNUNET_PeerIdentity * pid, void *value) { struct Peer *pos = value; schedule_attempt_connect (pos); return GNUNET_YES; } /** * Last task run during shutdown. Disconnects us from * the transport and core. * * @param cls unused, NULL * @param tc scheduler context */ static void add_peer_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { add_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_CONTAINER_multipeermap_iterate (peers, &try_add_peers, NULL); } /** * Method called whenever a peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { struct Peer *pos; if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core told us that we disconnected from `%s'\n", GNUNET_i2s (peer)); pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == pos) { GNUNET_break (0); return; } if (pos->is_connected != GNUNET_YES) { GNUNET_break (0); return; } pos->is_connected = GNUNET_NO; connection_count--; if (NULL != pos->hello_req) { GNUNET_CORE_notify_transmit_ready_cancel (pos->hello_req); pos->hello_req = NULL; } if (GNUNET_SCHEDULER_NO_TASK != pos->hello_delay_task) { GNUNET_SCHEDULER_cancel (pos->hello_delay_task); pos->hello_delay_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_STATISTICS_set (stats, gettext_noop ("# peers connected"), connection_count, GNUNET_NO); if (pos->is_friend) { friend_count--; GNUNET_STATISTICS_set (stats, gettext_noop ("# friends connected"), friend_count, GNUNET_NO); } if (((connection_count < target_connection_count) || (friend_count < minimum_friend_count)) && (GNUNET_SCHEDULER_NO_TASK == add_task)) add_task = GNUNET_SCHEDULER_add_now (&add_peer_task, NULL); if ((friend_count < minimum_friend_count) && (blacklist == NULL)) blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL); } /** * Iterator called on each address. * * @param cls flag that we will set if we see any addresses * @param address the address of the peer * @param expiration when will the given address expire * @return GNUNET_SYSERR always, to terminate iteration */ static int address_iterator (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { int *flag = cls; *flag = GNUNET_YES; return GNUNET_SYSERR; } /** * We've gotten a HELLO from another peer. Consider it for * advertising. * * @param hello the HELLO we got */ static void consider_for_advertising (const struct GNUNET_HELLO_Message *hello) { int have_address; struct GNUNET_PeerIdentity pid; struct GNUNET_TIME_Absolute dt; struct GNUNET_HELLO_Message *nh; struct Peer *peer; uint16_t size; if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid)) { GNUNET_break (0); return; } if (0 == memcmp (&pid, &my_identity, sizeof (struct GNUNET_PeerIdentity))) return; /* that's me! */ have_address = GNUNET_NO; GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &address_iterator, &have_address); if (GNUNET_NO == have_address) return; /* no point in advertising this one... */ peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid); if (NULL == peer) { peer = make_peer (&pid, hello, GNUNET_NO); } else if (peer->hello != NULL) { dt = GNUNET_HELLO_equals (peer->hello, hello, GNUNET_TIME_absolute_get ()); if (dt.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) return; /* nothing new here */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found `%s' from peer `%s' for advertising\n", "HELLO", GNUNET_i2s (&pid)); if (peer->hello != NULL) { nh = GNUNET_HELLO_merge (peer->hello, hello); GNUNET_free (peer->hello); peer->hello = nh; } else { size = GNUNET_HELLO_size (hello); peer->hello = GNUNET_malloc (size); memcpy (peer->hello, hello, size); } if (peer->filter != NULL) GNUNET_CONTAINER_bloomfilter_free (peer->filter); setup_filter (peer); /* since we have a new HELLO to pick from, re-schedule all * HELLO requests that are not bound by the HELLO send rate! */ GNUNET_CONTAINER_multipeermap_iterate (peers, &reschedule_hellos, peer); } /** * PEERINFO calls this function to let us know about a possible peer * that we might want to connect to. * * @param cls closure (not used) * @param peer potential peer to connect to * @param hello HELLO for this peer (or NULL) * @param err_msg NULL if successful, otherwise contains error message */ static void process_peer (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { struct Peer *pos; if (err_msg != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Error in communication with PEERINFO service: %s\n"), err_msg); GNUNET_PEERINFO_notify_cancel (peerinfo_notify); peerinfo_notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO, &process_peer, NULL); return; } GNUNET_assert (peer != NULL); if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; /* that's me! */ if (hello == NULL) { /* free existing HELLO, if any */ pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL != pos) { GNUNET_free_non_null (pos->hello); pos->hello = NULL; if (pos->filter != NULL) { GNUNET_CONTAINER_bloomfilter_free (pos->filter); pos->filter = NULL; } if ((GNUNET_NO == pos->is_connected) && (GNUNET_NO == pos->is_friend) && (0 == GNUNET_TIME_absolute_get_remaining (pos-> greylisted_until).rel_value_us)) free_peer (NULL, &pos->pid, pos); } return; } consider_for_advertising (hello); pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (pos == NULL) pos = make_peer (peer, hello, GNUNET_NO); GNUNET_assert (NULL != pos); if (GNUNET_YES == pos->is_connected) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Already connected to peer `%s'\n", GNUNET_i2s (peer)); return; } if (GNUNET_TIME_absolute_get_remaining (pos->greylisted_until).rel_value_us > 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Already tried peer `%s' recently\n", GNUNET_i2s (peer)); return; /* peer still greylisted */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Considering connecting to peer `%s'\n", GNUNET_i2s (peer)); schedule_attempt_connect (pos); } /** * Function called after #GNUNET_CORE_connect has succeeded * (or failed for good). * * @param cls closure * @param my_id ID of this peer, NULL if we failed */ static void core_init (void *cls, const struct GNUNET_PeerIdentity *my_id) { if (NULL == my_id) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to connect to core service, can not manage topology!\n")); GNUNET_SCHEDULER_shutdown (); return; } my_identity = *my_id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am peer `%s'\n", GNUNET_i2s (my_id)); peerinfo_notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO, &process_peer, NULL); } /** * Process friend found in FRIENDS file. * * @param cls pointer to an `unsigned int` to be incremented per friend found * @param pid identity of the friend */ static void handle_friend (void *cls, const struct GNUNET_PeerIdentity *pid) { unsigned int *entries_found = cls; struct Peer *fl; if (0 == memcmp (pid, &my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Found myself `%s' in friend list (useless, ignored)\n"), GNUNET_i2s (pid)); return; } (*entries_found)++; fl = make_peer (pid, NULL, GNUNET_YES); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Found friend `%s' in configuration\n"), GNUNET_i2s (&fl->pid)); } /** * Read the friends file. */ static void read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg) { unsigned int entries_found; entries_found = 0; if (GNUNET_OK != GNUNET_FRIENDS_parse (cfg, &handle_friend, &entries_found)) { if ((friends_only) || (minimum_friend_count > 0)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Encountered errors parsing friends list!\n")); } GNUNET_STATISTICS_update (stats, gettext_noop ("# friends in configuration"), entries_found, GNUNET_NO); if ((minimum_friend_count > entries_found) && (friends_only == GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Fewer friends specified than required by minimum friend count. Will only connect to friends.\n")); } if ((minimum_friend_count > target_connection_count) && (friends_only == GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("More friendly connections required than target total number of connections.\n")); } } /** * This function is called whenever an encrypted HELLO message is * received. * * @param cls closure * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual HELLO message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_encrypted_hello (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { struct Peer *peer; struct GNUNET_PeerIdentity pid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received encrypted `%s' from peer `%s'", "HELLO", GNUNET_i2s (other)); if (GNUNET_OK != GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) message, &pid)) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (stats, gettext_noop ("# HELLO messages received"), 1, GNUNET_NO); peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid); if (NULL == peer) { if ((GNUNET_YES == friends_only) || (friend_count < minimum_friend_count)) return GNUNET_OK; } else { if ((GNUNET_YES != peer->is_friend) && (GNUNET_YES == friends_only)) return GNUNET_OK; if ((GNUNET_YES != peer->is_friend) && (friend_count < minimum_friend_count)) return GNUNET_OK; } if (transport != NULL) GNUNET_TRANSPORT_offer_hello (transport, message, NULL, NULL); return GNUNET_OK; } /** * Function to fill send buffer with HELLO. * * @param cls 'struct Peer' of the target peer * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t hello_advertising_ready (void *cls, size_t size, void *buf) { struct Peer *pl = cls; struct FindAdvHelloContext fah; size_t want; struct GNUNET_HashCode hc; pl->hello_req = NULL; GNUNET_assert (GNUNET_YES == pl->is_connected); /* find applicable HELLOs */ fah.peer = pl; fah.result = NULL; fah.max_size = size; fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_CONTAINER_multipeermap_iterate (peers, &find_advertisable_hello, &fah); want = 0; if (fah.result != NULL) { want = GNUNET_HELLO_size (fah.result->hello); GNUNET_assert (want <= size); memcpy (buf, fah.result->hello, want); GNUNET_CRYPTO_hash (&pl->pid, sizeof (struct GNUNET_PeerIdentity), &hc); GNUNET_CONTAINER_bloomfilter_add (fah.result->filter, &hc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' with %u bytes", "HELLO", (unsigned int) want); GNUNET_STATISTICS_update (stats, gettext_noop ("# HELLO messages gossipped"), 1, GNUNET_NO); } if (pl->hello_delay_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (pl->hello_delay_task); pl->next_hello_allowed = GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY); pl->hello_delay_task = GNUNET_SCHEDULER_add_now (&schedule_next_hello, pl); return want; } /** * Last task run during shutdown. Disconnects us from * the transport and core. * * @param cls unused, NULL * @param tc scheduler context */ static void cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != peerinfo_notify) { GNUNET_PEERINFO_notify_cancel (peerinfo_notify); peerinfo_notify = NULL; } GNUNET_TRANSPORT_disconnect (transport); transport = NULL; if (handle != NULL) { GNUNET_CORE_disconnect (handle); handle = NULL; } whitelist_peers (); if (GNUNET_SCHEDULER_NO_TASK != add_task) { GNUNET_SCHEDULER_cancel (add_task); add_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_multipeermap_iterate (peers, &free_peer, NULL); GNUNET_CONTAINER_multipeermap_destroy (peers); peers = NULL; if (stats != NULL) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { static struct GNUNET_CORE_MessageHandler handlers[] = { {&handle_encrypted_hello, GNUNET_MESSAGE_TYPE_HELLO, 0}, {NULL, 0, 0} }; unsigned long long opt; cfg = c; stats = GNUNET_STATISTICS_create ("topology", cfg); friends_only = GNUNET_CONFIGURATION_get_value_yesno (cfg, "TOPOLOGY", "FRIENDS-ONLY"); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "TOPOLOGY", "MINIMUM-FRIENDS", &opt)) opt = 0; minimum_friend_count = (unsigned int) opt; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "TOPOLOGY", "TARGET-CONNECTION-COUNT", &opt)) opt = 16; target_connection_count = (unsigned int) opt; peers = GNUNET_CONTAINER_multipeermap_create (target_connection_count * 2, GNUNET_NO); if ((friends_only == GNUNET_YES) || (minimum_friend_count > 0)) read_friends_file (cfg); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Topology would like %u connections with at least %u friends\n", target_connection_count, minimum_friend_count); if ((friend_count < minimum_friend_count) && (blacklist == NULL)) blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL); transport = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, NULL, NULL, NULL); handle = GNUNET_CORE_connect (cfg, NULL, &core_init, &connect_notify, &disconnect_notify, NULL, GNUNET_NO, NULL, GNUNET_NO, handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleaning_task, NULL); if (NULL == transport) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to `%s' service.\n"), "transport"); GNUNET_SCHEDULER_shutdown (); return; } if (NULL == handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to `%s' service.\n"), "core"); GNUNET_SCHEDULER_shutdown (); return; } } /** * The main function for the topology daemon. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-topology", _ ("GNUnet topology control (maintaining P2P mesh and F2F constraints)"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } #ifdef LINUX #include /** * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ void __attribute__ ((constructor)) GNUNET_ARM_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); malloc_trim (0); } #endif /* end of gnunet-daemon-topology.c */ gnunet-0.10.1/src/statistics/0000755000175000017500000000000012320755623013060 500000000000000gnunet-0.10.1/src/statistics/test_statistics_api_data.conf0000644000175000017500000000113212272425070020713 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-statistics/ [statistics] PORT = 22353 UNIXPATH = $GNUNET_RUNTIME_DIR/test-statistics-service-statistics.unix [arm] PORT = 22354 DEFAULTSERVICES = UNIXPATH = $GNUNET_RUNTIME_DIR/test-statistics-service-arm.unix [fs] AUTOSTART = NO [datastore] AUTOSTART = NO [dht] AUTOSTART = NO [transport] AUTOSTART = NO [core] AUTOSTART = NO [peerinfo] AUTOSTART = NO [dns] AUTOSTART = NO [nse] AUTOSTART = NO [lockmanager] AUTOSTART = NO [ats] AUTOSTART = NO [namestore] AUTOSTART = NO [gns] AUTOSTART = NO [vpn] AUTOSTART = NO [consensus] AUTOSTART = NO gnunet-0.10.1/src/statistics/statistics_api.c0000644000175000017500000011302512306304155016163 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file statistics/statistics_api.c * @brief API of the statistics service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "statistics.h" /** * How long do we wait until a statistics request for setting * a value times out? (The update will be lost if the * service does not react within this timeframe). */ #define SET_TRANSMIT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) #define LOG(kind,...) GNUNET_log_from (kind, "statistics-api",__VA_ARGS__) /** * Types of actions. */ enum ActionType { /** * Get a value. */ ACTION_GET, /** * Set a value. */ ACTION_SET, /** * Update a value. */ ACTION_UPDATE, /** * Watch a value. */ ACTION_WATCH }; /** * Entry kept for each value we are watching. */ struct GNUNET_STATISTICS_WatchEntry { /** * What subsystem is this action about? (never NULL) */ char *subsystem; /** * What value is this action about? (never NULL) */ char *name; /** * Function to call */ GNUNET_STATISTICS_Iterator proc; /** * Closure for proc */ void *proc_cls; }; /** * Linked list of things we still need to do. */ struct GNUNET_STATISTICS_GetHandle { /** * This is a doubly linked list. */ struct GNUNET_STATISTICS_GetHandle *next; /** * This is a doubly linked list. */ struct GNUNET_STATISTICS_GetHandle *prev; /** * Main statistics handle. */ struct GNUNET_STATISTICS_Handle *sh; /** * What subsystem is this action about? (can be NULL) */ char *subsystem; /** * What value is this action about? (can be NULL) */ char *name; /** * Continuation to call once action is complete. */ GNUNET_STATISTICS_Callback cont; /** * Function to call (for GET actions only). */ GNUNET_STATISTICS_Iterator proc; /** * Closure for proc and cont. */ void *cls; /** * Timeout for this action. */ struct GNUNET_TIME_Absolute timeout; /** * Task run on timeout. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Associated value. */ uint64_t value; /** * Flag for SET/UPDATE actions. */ int make_persistent; /** * Has the current iteration been aborted; for GET actions. */ int aborted; /** * Is this a GET, SET, UPDATE or WATCH? */ enum ActionType type; /** * Size of the message that we will be transmitting. */ uint16_t msize; }; /** * Handle for the service. */ struct GNUNET_STATISTICS_Handle { /** * Name of our subsystem. */ char *subsystem; /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Currently pending transmission request. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of the linked list of pending actions (first action * to be performed). */ struct GNUNET_STATISTICS_GetHandle *action_head; /** * Tail of the linked list of actions (for fast append). */ struct GNUNET_STATISTICS_GetHandle *action_tail; /** * Action we are currently busy with (action request has been * transmitted, we're now receiving the response from the * service). */ struct GNUNET_STATISTICS_GetHandle *current; /** * Array of watch entries. */ struct GNUNET_STATISTICS_WatchEntry **watches; /** * Task doing exponential back-off trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier backoff_task; /** * Time for next connect retry. */ struct GNUNET_TIME_Relative backoff; /** * Maximum heap size observed so far (if available). */ uint64_t peak_heap_size; /** * Maximum resident set side observed so far (if available). */ uint64_t peak_rss; /** * Size of the 'watches' array. */ unsigned int watches_size; /** * Should this handle auto-destruct once all actions have * been processed? */ int do_destroy; /** * Are we currently receiving from the service? */ int receiving; }; /** * Obtain statistics about this process's memory consumption and * report those as well (if they changed). */ static void update_memory_statistics (struct GNUNET_STATISTICS_Handle *h) { #if ENABLE_HEAP_STATISTICS uint64_t current_heap_size = 0; uint64_t current_rss = 0; if (GNUNET_NO != h->do_destroy) return; #if HAVE_MALLINFO { struct mallinfo mi; mi = mallinfo(); current_heap_size = mi.uordblks + mi.fordblks; } #endif #if HAVE_GETRUSAGE { struct rusage ru; if (0 == getrusage (RUSAGE_SELF, &ru)) { current_rss = 1024LL * ru.ru_maxrss; } } #endif if (current_heap_size > h->peak_heap_size) { h->peak_heap_size = current_heap_size; GNUNET_STATISTICS_set (h, "# peak heap size", current_heap_size, GNUNET_NO); } if (current_rss > h->peak_rss) { h->peak_rss = current_rss; GNUNET_STATISTICS_set (h, "# peak resident set size", current_rss, GNUNET_NO); } #endif } /** * Schedule the next action to be performed. * * @param h statistics handle to reconnect */ static void schedule_action (struct GNUNET_STATISTICS_Handle *h); /** * Transmit request to service that we want to watch * the development of a particular value. * * @param h statistics handle * @param watch watch entry of the value to watch */ static void schedule_watch_request (struct GNUNET_STATISTICS_Handle *h, struct GNUNET_STATISTICS_WatchEntry *watch) { struct GNUNET_STATISTICS_GetHandle *ai; size_t slen; size_t nlen; size_t nsize; slen = strlen (watch->subsystem) + 1; nlen = strlen (watch->name) + 1; nsize = sizeof (struct GNUNET_MessageHeader) + slen + nlen; if (nsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } ai = GNUNET_new (struct GNUNET_STATISTICS_GetHandle); ai->sh = h; ai->subsystem = GNUNET_strdup (watch->subsystem); ai->name = GNUNET_strdup (watch->name); ai->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; ai->msize = nsize; ai->type = ACTION_WATCH; ai->proc = watch->proc; ai->cls = watch->proc_cls; GNUNET_CONTAINER_DLL_insert_tail (h->action_head, h->action_tail, ai); schedule_action (h); } /** * Free memory associated with the given action item. * * @param gh action item to free */ static void free_action_item (struct GNUNET_STATISTICS_GetHandle *gh) { if (GNUNET_SCHEDULER_NO_TASK != gh->timeout_task) { GNUNET_SCHEDULER_cancel (gh->timeout_task); gh->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free_non_null (gh->subsystem); GNUNET_free_non_null (gh->name); GNUNET_free (gh); } /** * Disconnect from the statistics service. * * @param h statistics handle to disconnect from */ static void do_disconnect (struct GNUNET_STATISTICS_Handle *h) { struct GNUNET_STATISTICS_GetHandle *c; if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } h->receiving = GNUNET_NO; if (NULL != (c = h->current)) { h->current = NULL; if ( (NULL != c->cont) && (GNUNET_YES != c->aborted) ) { c->cont (c->cls, GNUNET_SYSERR); c->cont = NULL; } free_action_item (c); } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } } /** * Try to (re)connect to the statistics service. * * @param h statistics handle to reconnect * @return #GNUNET_YES on success, #GNUNET_NO on failure. */ static int try_connect (struct GNUNET_STATISTICS_Handle *h) { struct GNUNET_STATISTICS_GetHandle *gh; struct GNUNET_STATISTICS_GetHandle *gn; unsigned int i; if (GNUNET_SCHEDULER_NO_TASK != h->backoff_task) return GNUNET_NO; if (NULL != h->client) return GNUNET_YES; h->client = GNUNET_CLIENT_connect ("statistics", h->cfg); if (NULL != h->client) { gn = h->action_head; while (NULL != (gh = gn)) { gn = gh->next; if (gh->type == ACTION_WATCH) { GNUNET_CONTAINER_DLL_remove (h->action_head, h->action_tail, gh); free_action_item (gh); } } for (i = 0; i < h->watches_size; i++) { if (NULL != h->watches[i]) schedule_watch_request (h, h->watches[i]); } return GNUNET_YES; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect to statistics service!\n"); return GNUNET_NO; } /** * We've waited long enough, reconnect now. * * @param cls the `struct GNUNET_STATISTICS_Handle` to reconnect * @param tc scheduler context (unused) */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_STATISTICS_Handle *h = cls; h->backoff_task = GNUNET_SCHEDULER_NO_TASK; schedule_action (h); } /** * Task used by 'reconnect_later' to shutdown the handle * * @param cls the statistics handle * @param tc scheduler context */ static void do_destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_STATISTICS_Handle *h = cls; GNUNET_STATISTICS_destroy (h, GNUNET_NO); } /** * Reconnect at a later time, respecting back-off. * * @param h statistics handle */ static void reconnect_later (struct GNUNET_STATISTICS_Handle *h) { int loss; struct GNUNET_STATISTICS_GetHandle *gh; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->backoff_task); if (GNUNET_YES == h->do_destroy) { /* So we are shutting down and the service is not reachable. * Chances are that it's down for good and we are not going to connect to * it anymore. * Give up and don't sync the rest of the data. */ loss = GNUNET_NO; for (gh = h->action_head; NULL != gh; gh = gh->next) if ( (gh->make_persistent) && (ACTION_SET == gh->type) ) loss = GNUNET_YES; if (GNUNET_YES == loss) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Could not save some persistent statistics\n")); h->do_destroy = GNUNET_NO; GNUNET_SCHEDULER_add_continuation (&do_destroy, h, GNUNET_SCHEDULER_REASON_PREREQ_DONE); return; } h->backoff_task = GNUNET_SCHEDULER_add_delayed (h->backoff, &reconnect_task, h); h->backoff = GNUNET_TIME_STD_BACKOFF (h->backoff); } /** * Process a #GNUNET_MESSAGE_TYPE_STATISTICS_VALUE message. * * @param h statistics handle * @param msg message received from the service, never NULL * @return #GNUNET_OK if the message was well-formed */ static int process_statistics_value_message (struct GNUNET_STATISTICS_Handle *h, const struct GNUNET_MessageHeader *msg) { char *service; char *name; const struct GNUNET_STATISTICS_ReplyMessage *smsg; uint16_t size; if (h->current->aborted) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Iteration was aborted, ignoring VALUE\n"); return GNUNET_OK; /* don't bother */ } size = ntohs (msg->size); if (size < sizeof (struct GNUNET_STATISTICS_ReplyMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } smsg = (const struct GNUNET_STATISTICS_ReplyMessage *) msg; size -= sizeof (struct GNUNET_STATISTICS_ReplyMessage); if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &smsg[1], size, 2, &service, &name)) { GNUNET_break (0); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received valid statistic on `%s:%s': %llu\n", service, name, GNUNET_ntohll (smsg->value)); if (GNUNET_OK != h->current->proc (h->current->cls, service, name, GNUNET_ntohll (smsg->value), 0 != (ntohl (smsg->uid) & GNUNET_STATISTICS_PERSIST_BIT))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing of remaining statistics aborted by client.\n"); h->current->aborted = GNUNET_YES; } LOG (GNUNET_ERROR_TYPE_DEBUG, "VALUE processed successfully\n"); return GNUNET_OK; } /** * We have received a watch value from the service. Process it. * * @param h statistics handle * @param msg the watch value message * @return #GNUNET_OK if the message was well-formed, #GNUNET_SYSERR if not, * #GNUNET_NO if this watch has been cancelled */ static int process_watch_value (struct GNUNET_STATISTICS_Handle *h, const struct GNUNET_MessageHeader *msg) { const struct GNUNET_STATISTICS_WatchValueMessage *wvm; struct GNUNET_STATISTICS_WatchEntry *w; uint32_t wid; if (sizeof (struct GNUNET_STATISTICS_WatchValueMessage) != ntohs (msg->size)) { GNUNET_break (0); return GNUNET_SYSERR; } wvm = (const struct GNUNET_STATISTICS_WatchValueMessage *) msg; GNUNET_break (0 == ntohl (wvm->reserved)); wid = ntohl (wvm->wid); if (wid >= h->watches_size) { GNUNET_break (0); return GNUNET_SYSERR; } w = h->watches[wid]; if (NULL == w) return GNUNET_NO; (void) w->proc (w->proc_cls, w->subsystem, w->name, GNUNET_ntohll (wvm->value), 0 != (ntohl (wvm->flags) & GNUNET_STATISTICS_PERSIST_BIT)); return GNUNET_OK; } /** * Task used to destroy the statistics handle. * * @param cls the `struct GNUNET_STATISTICS_Handle` * @param tc the scheduler context */ static void destroy_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_STATISTICS_Handle *h = cls; GNUNET_STATISTICS_destroy (h, GNUNET_NO); } /** * Function called with messages from stats service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void receive_stats (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_STATISTICS_Handle *h = cls; struct GNUNET_STATISTICS_GetHandle *c; int ret; if (NULL == msg) { LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Error receiving statistics from service, is the service running?\n"); do_disconnect (h); reconnect_later (h); return; } switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_TEST: if (GNUNET_SYSERR != h->do_destroy) { /* not in shutdown, why do we get 'TEST'? */ GNUNET_break (0); do_disconnect (h); reconnect_later (h); return; } h->do_destroy = GNUNET_NO; GNUNET_SCHEDULER_add_continuation (&destroy_task, h, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_MESSAGE_TYPE_STATISTICS_END: LOG (GNUNET_ERROR_TYPE_DEBUG, "Received end of statistics marker\n"); if (NULL == (c = h->current)) { GNUNET_break (0); do_disconnect (h); reconnect_later (h); return; } h->backoff = GNUNET_TIME_UNIT_MILLISECONDS; if (h->watches_size > 0) { GNUNET_CLIENT_receive (h->client, &receive_stats, h, GNUNET_TIME_UNIT_FOREVER_REL); } else { h->receiving = GNUNET_NO; } h->current = NULL; schedule_action (h); if (NULL != c->cont) { c->cont (c->cls, GNUNET_OK); c->cont = NULL; } free_action_item (c); return; case GNUNET_MESSAGE_TYPE_STATISTICS_VALUE: if (GNUNET_OK != process_statistics_value_message (h, msg)) { do_disconnect (h); reconnect_later (h); return; } /* finally, look for more! */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing VALUE done, now reading more\n"); GNUNET_CLIENT_receive (h->client, &receive_stats, h, GNUNET_TIME_absolute_get_remaining (h-> current->timeout)); h->backoff = GNUNET_TIME_UNIT_MILLISECONDS; return; case GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE: if (GNUNET_OK != (ret = process_watch_value (h, msg))) { do_disconnect (h); if (GNUNET_NO == ret) h->backoff = GNUNET_TIME_UNIT_MILLISECONDS; reconnect_later (h); return; } h->backoff = GNUNET_TIME_UNIT_MILLISECONDS; GNUNET_assert (h->watches_size > 0); GNUNET_CLIENT_receive (h->client, &receive_stats, h, GNUNET_TIME_UNIT_FOREVER_REL); return; default: GNUNET_break (0); do_disconnect (h); reconnect_later (h); return; } } /** * Transmit a GET request (and if successful, start to receive * the response). * * @param handle statistics handle * @param size how many bytes can we write to @a buf * @param buf where to write requests to the service * @return number of bytes written to @a buf */ static size_t transmit_get (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf) { struct GNUNET_STATISTICS_GetHandle *c; struct GNUNET_MessageHeader *hdr; size_t slen1; size_t slen2; uint16_t msize; GNUNET_assert (NULL != (c = handle->current)); if (NULL == buf) { /* timeout / error */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission of request for statistics failed!\n"); do_disconnect (handle); reconnect_later (handle); return 0; } slen1 = strlen (c->subsystem) + 1; slen2 = strlen (c->name) + 1; msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader); GNUNET_assert (msize <= size); hdr = (struct GNUNET_MessageHeader *) buf; hdr->size = htons (msize); hdr->type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_GET); GNUNET_assert (slen1 + slen2 == GNUNET_STRINGS_buffer_fill ((char *) &hdr[1], slen1 + slen2, 2, c->subsystem, c->name)); if (GNUNET_YES != handle->receiving) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission of GET done, now reading response\n"); handle->receiving = GNUNET_YES; GNUNET_CLIENT_receive (handle->client, &receive_stats, handle, GNUNET_TIME_absolute_get_remaining (c->timeout)); } return msize; } /** * Transmit a WATCH request (and if successful, start to receive * the response). * * @param handle statistics handle * @param size how many bytes can we write to @a buf * @param buf where to write requests to the service * @return number of bytes written to @a buf */ static size_t transmit_watch (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf) { struct GNUNET_MessageHeader *hdr; size_t slen1; size_t slen2; uint16_t msize; if (NULL == buf) { /* timeout / error */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission of request for statistics failed!\n"); do_disconnect (handle); reconnect_later (handle); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting watch request for `%s'\n", handle->current->name); slen1 = strlen (handle->current->subsystem) + 1; slen2 = strlen (handle->current->name) + 1; msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader); GNUNET_assert (msize <= size); hdr = (struct GNUNET_MessageHeader *) buf; hdr->size = htons (msize); hdr->type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH); GNUNET_assert (slen1 + slen2 == GNUNET_STRINGS_buffer_fill ((char *) &hdr[1], slen1 + slen2, 2, handle->current->subsystem, handle->current->name)); if (GNUNET_YES != handle->receiving) { handle->receiving = GNUNET_YES; GNUNET_CLIENT_receive (handle->client, &receive_stats, handle, GNUNET_TIME_UNIT_FOREVER_REL); } GNUNET_assert (NULL == handle->current->cont); free_action_item (handle->current); handle->current = NULL; return msize; } /** * Transmit a SET/UPDATE request. * * @param handle statistics handle * @param size how many bytes can we write to @a buf * @param buf where to write requests to the service * @return number of bytes written to @a buf */ static size_t transmit_set (struct GNUNET_STATISTICS_Handle *handle, size_t size, void *buf) { struct GNUNET_STATISTICS_SetMessage *r; size_t slen; size_t nlen; size_t nsize; if (NULL == buf) { do_disconnect (handle); reconnect_later (handle); return 0; } slen = strlen (handle->current->subsystem) + 1; nlen = strlen (handle->current->name) + 1; nsize = sizeof (struct GNUNET_STATISTICS_SetMessage) + slen + nlen; if (size < nsize) { GNUNET_break (0); do_disconnect (handle); reconnect_later (handle); return 0; } r = buf; r->header.size = htons (nsize); r->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_SET); r->flags = 0; r->value = GNUNET_htonll (handle->current->value); if (handle->current->make_persistent) r->flags |= htonl (GNUNET_STATISTICS_SETFLAG_PERSISTENT); if (handle->current->type == ACTION_UPDATE) r->flags |= htonl (GNUNET_STATISTICS_SETFLAG_RELATIVE); GNUNET_assert (slen + nlen == GNUNET_STRINGS_buffer_fill ((char *) &r[1], slen + nlen, 2, handle->current->subsystem, handle->current->name)); GNUNET_assert (NULL == handle->current->cont); free_action_item (handle->current); handle->current = NULL; update_memory_statistics (handle); return nsize; } /** * Function called when we are ready to transmit a request to the service. * * @param cls the `struct GNUNET_STATISTICS_Handle` * @param size how many bytes can we write to @a buf * @param buf where to write requests to the service * @return number of bytes written to @a buf */ static size_t transmit_action (void *cls, size_t size, void *buf) { struct GNUNET_STATISTICS_Handle *h = cls; size_t ret; h->th = NULL; ret = 0; if (NULL != h->current) switch (h->current->type) { case ACTION_GET: ret = transmit_get (h, size, buf); break; case ACTION_SET: case ACTION_UPDATE: ret = transmit_set (h, size, buf); break; case ACTION_WATCH: ret = transmit_watch (h, size, buf); break; default: GNUNET_assert (0); break; } schedule_action (h); return ret; } /** * Get handle for the statistics service. * * @param subsystem name of subsystem using the service * @param cfg services configuration in use * @return handle to use */ struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create (const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_STATISTICS_Handle *ret; if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg, "statistics", "DISABLE")) return NULL; GNUNET_assert (NULL != subsystem); GNUNET_assert (NULL != cfg); ret = GNUNET_new (struct GNUNET_STATISTICS_Handle); ret->cfg = cfg; ret->subsystem = GNUNET_strdup (subsystem); ret->backoff = GNUNET_TIME_UNIT_MILLISECONDS; return ret; } /** * Destroy a handle (free all state associated with * it). * * @param h statistics handle to destroy * @param sync_first set to #GNUNET_YES if pending SET requests should * be completed */ void GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, int sync_first) { struct GNUNET_STATISTICS_GetHandle *pos; struct GNUNET_STATISTICS_GetHandle *next; struct GNUNET_TIME_Relative timeout; int i; if (NULL == h) return; GNUNET_assert (GNUNET_NO == h->do_destroy); // Don't call twice. if (GNUNET_SCHEDULER_NO_TASK != h->backoff_task) { GNUNET_SCHEDULER_cancel (h->backoff_task); h->backoff_task = GNUNET_SCHEDULER_NO_TASK; } if (sync_first) { if (NULL != h->current) { if (ACTION_GET == h->current->type) { if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } free_action_item (h->current); h->current = NULL; } } next = h->action_head; while (NULL != (pos = next)) { next = pos->next; if (ACTION_GET == pos->type) { GNUNET_CONTAINER_DLL_remove (h->action_head, h->action_tail, pos); free_action_item (pos); } } if ( (NULL == h->current) && (NULL != (h->current = h->action_head)) ) GNUNET_CONTAINER_DLL_remove (h->action_head, h->action_tail, h->current); h->do_destroy = GNUNET_YES; if ((NULL != h->current) && (NULL == h->th) && (NULL != h->client)) { timeout = GNUNET_TIME_absolute_get_remaining (h->current->timeout); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, h->current->msize, timeout, GNUNET_YES, &transmit_action, h); GNUNET_assert (NULL != h->th); } if (NULL != h->th) return; /* do not finish destruction just yet */ } while (NULL != (pos = h->action_head)) { GNUNET_CONTAINER_DLL_remove (h->action_head, h->action_tail, pos); free_action_item (pos); } do_disconnect (h); for (i = 0; i < h->watches_size; i++) { if (NULL == h->watches[i]) continue; GNUNET_free (h->watches[i]->subsystem); GNUNET_free (h->watches[i]->name); GNUNET_free (h->watches[i]); } GNUNET_array_grow (h->watches, h->watches_size, 0); GNUNET_free (h->subsystem); GNUNET_free (h); } /** * Function called to transmit TEST message to service to * confirm that the service has received all of our 'SET' * messages (during statistics disconnect/shutdown). * * @param cls the `struct GNUNET_STATISTICS_Handle` * @param size how many bytes can we write to @a buf * @param buf where to write requests to the service * @return number of bytes written to @a buf */ static size_t transmit_test_on_shutdown (void *cls, size_t size, void *buf) { struct GNUNET_STATISTICS_Handle *h = cls; struct GNUNET_MessageHeader hdr; h->th = NULL; if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to receive acknowledgement from statistics service, some statistics might have been lost!\n")); h->do_destroy = GNUNET_NO; GNUNET_SCHEDULER_add_continuation (&destroy_task, h, GNUNET_SCHEDULER_REASON_PREREQ_DONE); return 0; } hdr.type = htons (GNUNET_MESSAGE_TYPE_TEST); hdr.size = htons (sizeof (struct GNUNET_MessageHeader)); memcpy (buf, &hdr, sizeof (hdr)); if (GNUNET_YES != h->receiving) { h->receiving = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &receive_stats, h, GNUNET_TIME_UNIT_FOREVER_REL); } return sizeof (struct GNUNET_MessageHeader); } /** * Schedule the next action to be performed. * * @param h statistics handle */ static void schedule_action (struct GNUNET_STATISTICS_Handle *h) { struct GNUNET_TIME_Relative timeout; if ( (NULL != h->th) || (GNUNET_SCHEDULER_NO_TASK != h->backoff_task) ) return; /* action already pending */ if (GNUNET_YES != try_connect (h)) { reconnect_later (h); return; } if (NULL != h->current) return; /* action already pending */ /* schedule next action */ h->current = h->action_head; if (NULL == h->current) { if (GNUNET_YES == h->do_destroy) { h->do_destroy = GNUNET_SYSERR; /* in 'TEST' mode */ h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof (struct GNUNET_MessageHeader), SET_TRANSMIT_TIMEOUT, GNUNET_NO, &transmit_test_on_shutdown, h); } return; } GNUNET_CONTAINER_DLL_remove (h->action_head, h->action_tail, h->current); timeout = GNUNET_TIME_absolute_get_remaining (h->current->timeout); if (NULL == (h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, h->current->msize, timeout, GNUNET_YES, &transmit_action, h))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to statistics service.\n"); do_disconnect (h); reconnect_later (h); } } /** * We have run into a timeout on a #GNUNET_STATISTICS_get() operation, * call the continuation. * * @param cls the `struct GNUNET_STATISTICS_GetHandle` * @param tc scheduler context */ static void run_get_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_STATISTICS_GetHandle *gh = cls; GNUNET_STATISTICS_Callback cont = gh->cont; void *cont_cls = gh->cls; gh->timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_STATISTICS_get_cancel (gh); cont (cont_cls, GNUNET_SYSERR); } /** * Get statistic from the peer. * * @param handle identification of the statistics service * @param subsystem limit to the specified subsystem, NULL for our subsystem * @param name name of the statistic value, NULL for all values * @param timeout after how long should we give up (and call * cont with an error code)? * @param cont continuation to call when done (can be NULL) * This callback CANNOT destroy the statistics handle in the same call. * @param proc function to call on each value * @param cls closure for @a cont and @a proc * @return NULL on error */ struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, struct GNUNET_TIME_Relative timeout, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls) { size_t slen1; size_t slen2; struct GNUNET_STATISTICS_GetHandle *ai; if (NULL == handle) return NULL; GNUNET_assert (NULL != proc); GNUNET_assert (GNUNET_NO == handle->do_destroy); if (NULL == subsystem) subsystem = ""; if (NULL == name) name = ""; slen1 = strlen (subsystem) + 1; slen2 = strlen (name) + 1; GNUNET_assert (slen1 + slen2 + sizeof (struct GNUNET_MessageHeader) < GNUNET_SERVER_MAX_MESSAGE_SIZE); ai = GNUNET_new (struct GNUNET_STATISTICS_GetHandle); ai->sh = handle; ai->subsystem = GNUNET_strdup (subsystem); ai->name = GNUNET_strdup (name); ai->cont = cont; ai->proc = proc; ai->cls = cls; ai->timeout = GNUNET_TIME_relative_to_absolute (timeout); ai->type = ACTION_GET; ai->msize = slen1 + slen2 + sizeof (struct GNUNET_MessageHeader); ai->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &run_get_timeout, ai); GNUNET_CONTAINER_DLL_insert_tail (handle->action_head, handle->action_tail, ai); schedule_action (handle); return ai; } /** * Cancel a 'get' request. Must be called before the 'cont' * function is called. * * @param gh handle of the request to cancel */ void GNUNET_STATISTICS_get_cancel (struct GNUNET_STATISTICS_GetHandle *gh) { if (NULL == gh) return; if (GNUNET_SCHEDULER_NO_TASK != gh->timeout_task) { GNUNET_SCHEDULER_cancel (gh->timeout_task); gh->timeout_task = GNUNET_SCHEDULER_NO_TASK; } gh->cont = NULL; if (gh->sh->current == gh) { gh->aborted = GNUNET_YES; } else { GNUNET_CONTAINER_DLL_remove (gh->sh->action_head, gh->sh->action_tail, gh); GNUNET_free (gh->name); GNUNET_free (gh->subsystem); GNUNET_free (gh); } } /** * Watch statistics from the peer (be notified whenever they change). * * @param handle identification of the statistics service * @param subsystem limit to the specified subsystem, never NULL * @param name name of the statistic value, never NULL * @param proc function to call on each value * @param proc_cls closure for @a proc * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_STATISTICS_watch (struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Iterator proc, void *proc_cls) { struct GNUNET_STATISTICS_WatchEntry *w; if (NULL == handle) return GNUNET_SYSERR; w = GNUNET_new (struct GNUNET_STATISTICS_WatchEntry); w->subsystem = GNUNET_strdup (subsystem); w->name = GNUNET_strdup (name); w->proc = proc; w->proc_cls = proc_cls; GNUNET_array_append (handle->watches, handle->watches_size, w); schedule_watch_request (handle, w); return GNUNET_OK; } /** * Stop watching statistics from the peer. * * @param handle identification of the statistics service * @param subsystem limit to the specified subsystem, never NULL * @param name name of the statistic value, never NULL * @param proc function to call on each value * @param proc_cls closure for @a proc * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (no such watch) */ int GNUNET_STATISTICS_watch_cancel (struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Iterator proc, void *proc_cls) { struct GNUNET_STATISTICS_WatchEntry *w; unsigned int i; if (NULL == handle) return GNUNET_SYSERR; for (i=0;iwatches_size;i++) { w = handle->watches[i]; if (NULL == w) continue; if ( (w->proc == proc) && (w->proc_cls == proc_cls) && (0 == strcmp (w->name, name)) && (0 == strcmp (w->subsystem, subsystem)) ) { GNUNET_free (w->name); GNUNET_free (w->subsystem); GNUNET_free (w); handle->watches[i] = NULL; return GNUNET_OK; } } return GNUNET_SYSERR; } /** * Queue a request to change a statistic. * * @param h statistics handle * @param name name of the value * @param make_persistent should the value be kept across restarts? * @param value new value or change * @param type type of the action (#ACTION_SET or #ACTION_UPDATE) */ static void add_setter_action (struct GNUNET_STATISTICS_Handle *h, const char *name, int make_persistent, uint64_t value, enum ActionType type) { struct GNUNET_STATISTICS_GetHandle *ai; size_t slen; size_t nlen; size_t nsize; int64_t delta; slen = strlen (h->subsystem) + 1; nlen = strlen (name) + 1; nsize = sizeof (struct GNUNET_STATISTICS_SetMessage) + slen + nlen; if (nsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } for (ai = h->action_head; NULL != ai; ai = ai->next) { if (! ( (0 == strcmp (ai->subsystem, h->subsystem)) && (0 == strcmp (ai->name, name)) && ( (ACTION_UPDATE == ai->type) || (ACTION_SET == ai->type) ) ) ) continue; if (ACTION_SET == ai->type) { if (ACTION_UPDATE == type) { delta = (int64_t) value; if (delta > 0) { /* update old set by new delta */ ai->value += delta; } else { /* update old set by new delta, but never go negative */ if (ai->value < -delta) ai->value = 0; else ai->value += delta; } } else { /* new set overrides old set */ ai->value = value; } } else { if (ACTION_UPDATE == type) { /* make delta cummulative */ delta = (int64_t) value; ai->value += delta; } else { /* drop old 'update', use new 'set' instead */ ai->value = value; ai->type = type; } } ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); ai->make_persistent = make_persistent; return; } /* no existing entry matches, create a fresh one */ ai = GNUNET_new (struct GNUNET_STATISTICS_GetHandle); ai->sh = h; ai->subsystem = GNUNET_strdup (h->subsystem); ai->name = GNUNET_strdup (name); ai->timeout = GNUNET_TIME_relative_to_absolute (SET_TRANSMIT_TIMEOUT); ai->make_persistent = make_persistent; ai->msize = nsize; ai->value = value; ai->type = type; GNUNET_CONTAINER_DLL_insert_tail (h->action_head, h->action_tail, ai); schedule_action (h); } /** * Set statistic value for the peer. Will always use our * subsystem (the argument used when "handle" was created). * * @param handle identification of the statistics service * @param name name of the statistic value * @param value new value to set * @param make_persistent should the value be kept across restarts? */ void GNUNET_STATISTICS_set (struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent) { if (NULL == handle) return; GNUNET_assert (GNUNET_NO == handle->do_destroy); add_setter_action (handle, name, make_persistent, value, ACTION_SET); } /** * Set statistic value for the peer. Will always use our * subsystem (the argument used when "handle" was created). * * @param handle identification of the statistics service * @param name name of the statistic value * @param delta change in value (added to existing value) * @param make_persistent should the value be kept across restarts? */ void GNUNET_STATISTICS_update (struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent) { if (NULL == handle) return; if (0 == delta) return; GNUNET_assert (GNUNET_NO == handle->do_destroy); add_setter_action (handle, name, make_persistent, (uint64_t) delta, ACTION_UPDATE); } /* end of statistics_api.c */ gnunet-0.10.1/src/statistics/gnunet-statistics.c0000644000175000017500000002253712225777501016650 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file statistics/gnunet-statistics.c * @brief tool to obtain statistics * @author Christian Grothoff * @author Igor Wronsky */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "statistics.h" #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * Final status code. */ static int ret; /** * Set to subsystem that we're going to get stats for (or NULL for all). */ static char *subsystem; /** * Set to the specific stat value that we are after (or NULL for all). */ static char *name; /** * Make the value that is being set persistent. */ static int persistent; /** * Watch value continuously */ static int watch; /** * Quiet mode */ static int quiet; /** * Remote host */ static char *remote_host; /** * Remote host's port */ static unsigned long long remote_port; /** * Value to set */ static unsigned long long set_val; /** * Set operation */ static int set_value; /** * Callback function to process statistic values. * * @param cls closure * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration */ static int printer (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); const char * now_str; if (quiet == GNUNET_NO) { if (GNUNET_YES == watch) { now_str = GNUNET_STRINGS_absolute_time_to_string(now); FPRINTF (stdout, "%24s %s%12s %50s: %16llu \n", now_str, is_persistent ? "!" : " ", subsystem, _(name), (unsigned long long) value); } else { FPRINTF (stdout, "%s%12s %50s: %16llu \n", is_persistent ? "!" : " ", subsystem, _(name), (unsigned long long) value); } } else FPRINTF (stdout, "%llu\n", (unsigned long long) value); return GNUNET_OK; } /** * Function called last by the statistics code. * * @param cls closure * @param success #GNUNET_OK if statistics were * successfully obtained, #GNUNET_SYSERR if not. */ static void cleanup (void *cls, int success) { if (success != GNUNET_OK) { if (NULL == remote_host) FPRINTF (stderr, "%s", _("Failed to obtain statistics.\n")); else FPRINTF (stderr, _("Failed to obtain statistics from host `%s:%llu'\n"), remote_host, remote_port); ret = 1; } GNUNET_SCHEDULER_shutdown (); } /** * Function run on shutdown to clean up. * * @param cls the statistics handle * @param tc scheduler context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_STATISTICS_Handle *h = cls; if (NULL == h) return; if ( (GNUNET_YES == watch) && (NULL != subsystem) && (NULL != name) ) GNUNET_assert (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (h, subsystem, name, &printer, h)); GNUNET_STATISTICS_destroy (h, GNUNET_NO); h = NULL; } /** * Main task that does the actual work. * * @param cls closure with our configuration * @param tc schedueler context */ static void main_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_STATISTICS_Handle *h; if (set_value) { if (subsystem == NULL) { FPRINTF (stderr, "%s", _("Missing argument: subsystem \n")); ret = 1; return; } if (name == NULL) { FPRINTF (stderr, "%s", _("Missing argument: name\n")); ret = 1; return; } h = GNUNET_STATISTICS_create (subsystem, cfg); if (NULL == h) { ret = 1; return; } GNUNET_STATISTICS_set (h, name, (uint64_t) set_val, persistent); GNUNET_STATISTICS_destroy (h, GNUNET_YES); h = NULL; return; } if (NULL == (h = GNUNET_STATISTICS_create ("gnunet-statistics", cfg))) { ret = 1; return; } if (GNUNET_NO == watch) { if (NULL == GNUNET_STATISTICS_get (h, subsystem, name, GET_TIMEOUT, &cleanup, &printer, h)) cleanup (h, GNUNET_SYSERR); } else { if ((NULL == subsystem) || (NULL == name)) { printf (_("No subsystem or name given\n")); GNUNET_STATISTICS_destroy (h, GNUNET_NO); h = NULL; ret = 1; return; } if (GNUNET_OK != GNUNET_STATISTICS_watch (h, subsystem, name, &printer, h)) { fprintf (stderr, _("Failed to initialize watch routine\n")); GNUNET_SCHEDULER_add_now (&shutdown_task, h); return; } } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, h); } /** * Function called with th test result to see if the resolver is * running. * * @param cls closure with our configuration * @param result #GNUNET_YES if the resolver is running */ static void resolver_test_task (void *cls, int result) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; if (GNUNET_YES != result) { FPRINTF (stderr, _("Trying to connect to remote host, but service `%s' is not running\n"), "resolver"); return; } /* connect to a remote host */ if (0 == remote_port) { if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, "statistics", "PORT", &remote_port)) { FPRINTF (stderr, _("A port is required to connect to host `%s'\n"), remote_host); return; } } else if (65535 <= remote_port) { FPRINTF (stderr, _("A port has to be between 1 and 65535 to connect to host `%s'\n"), remote_host); return; } /* Manipulate configuration */ GNUNET_CONFIGURATION_set_value_string (cfg, "statistics", "UNIXPATH", ""); GNUNET_CONFIGURATION_set_value_string (cfg, "statistics", "HOSTNAME", remote_host); GNUNET_CONFIGURATION_set_value_number (cfg, "statistics", "PORT", remote_port); GNUNET_SCHEDULER_add_now (&main_task, cfg); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { set_value = GNUNET_NO; if (NULL != args[0]) { if (1 != SSCANF (args[0], "%llu", &set_val)) { FPRINTF (stderr, _("Invalid argument `%s'\n"), args[0]); ret = 1; return; } set_value = GNUNET_YES; } if (NULL != remote_host) GNUNET_CLIENT_service_test ("resolver", cfg, GNUNET_TIME_UNIT_SECONDS, &resolver_test_task, (void *) cfg); else GNUNET_SCHEDULER_add_now (&main_task, (void *) cfg); } /** * The main function to obtain statistics in GNUnet. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'n', "name", "NAME", gettext_noop ("limit output to statistics for the given NAME"), 1, &GNUNET_GETOPT_set_string, &name}, {'p', "persistent", NULL, gettext_noop ("make the value being set persistent"), 0, &GNUNET_GETOPT_set_one, &persistent}, {'s', "subsystem", "SUBSYSTEM", gettext_noop ("limit output to the given SUBSYSTEM"), 1, &GNUNET_GETOPT_set_string, &subsystem}, {'q', "quiet", NULL, gettext_noop ("just print the statistics value"), 0, &GNUNET_GETOPT_set_one, &quiet}, {'w', "watch", NULL, gettext_noop ("watch value continuously"), 0, &GNUNET_GETOPT_set_one, &watch}, {'r', "remote", NULL, gettext_noop ("connect to remote host"), 1, &GNUNET_GETOPT_set_string, &remote_host}, {'o', "port", NULL, gettext_noop ("port for remote host"), 1, &GNUNET_GETOPT_set_uint, &remote_port}, GNUNET_GETOPT_OPTION_END }; remote_port = 0; remote_host = NULL; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-statistics [options [value]]", gettext_noop ("Print statistics about GNUnet operations."), options, &run, NULL)) ? ret : 1; GNUNET_free_non_null (remote_host); GNUNET_free ((void*) argv); return ret; } /* end of gnunet-statistics.c */ gnunet-0.10.1/src/statistics/gnunet-service-statistics.c0000644000175000017500000005326012225777501020303 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file statistics/gnunet-service-statistics.c * @brief program that tracks statistics * @author Christian Grothoff */ #include "platform.h" #include "gnunet_bio_lib.h" #include "gnunet_container_lib.h" #include "gnunet_disk_lib.h" #include "gnunet_getopt_lib.h" #include "gnunet_protocols.h" #include "gnunet_service_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_strings_lib.h" #include "gnunet_time_lib.h" #include "statistics.h" /** * Watch entry. */ struct WatchEntry { /** * Watch entries are kept in a linked list. */ struct WatchEntry *next; /** * Watch entries are kept in a linked list. */ struct WatchEntry *prev; /** * For which client is this watch entry? */ struct GNUNET_SERVER_Client *client; /** * Last value we communicated to the client for this watch entry. */ uint64_t last_value; /** * Unique watch number for this client and this watched value. */ uint32_t wid; /** * Is last_value valid * GNUNET_NO : last_value is n/a, GNUNET_YES: last_value is valid */ int last_value_set; }; /** * Client entry. */ struct ClientEntry { /** * Clients are kept in a linked list. */ struct ClientEntry *next; /** * Clients are kept in a linked list. */ struct ClientEntry *prev; /** * Corresponding server handle. */ struct GNUNET_SERVER_Client *client; /** * Maximum watch ID used by this client so far. */ uint32_t max_wid; }; /** * Entry in the statistics list. */ struct StatsEntry { /** * This is a linked list. */ struct StatsEntry *next; /** * Name of the service, points into the * middle of msg. */ const char *service; /** * Name for the value, points into * the middle of msg. */ const char *name; /** * Message that can be used to set this value, * stored at the end of the memory used by * this struct. */ struct GNUNET_STATISTICS_SetMessage *msg; /** * Watch context for changes to this * value, or NULL for none. */ struct WatchEntry *we_head; /** * Watch context for changes to this * value, or NULL for none. */ struct WatchEntry *we_tail; /** * Our value. */ uint64_t value; /** * Unique ID. */ uint32_t uid; /** * Is this value persistent? */ int persistent; /** * Is this value set? * GNUNET_NO : value is n/a, GNUNET_YES: value is valid */ int set; }; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Linked list of our active statistics. */ static struct StatsEntry *start; /** * Head of linked list of connected clients. */ static struct ClientEntry *client_head; /** * Tail of linked list of connected clients. */ static struct ClientEntry *client_tail; /** * Handle to our server. */ static struct GNUNET_SERVER_Handle *srv; /** * Our notification context. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Counter used to generate unique values. */ static uint32_t uidgen; /** * Set to YES if we are shutting down as soon as possible. */ static int in_shutdown; /** * Inject a message to our server with a client of 'NULL'. * * @param cls the 'struct GNUNET_SERVER_Handle' * @param client unused * @param msg message to inject */ static int inject_message (void *cls, void *client, const struct GNUNET_MessageHeader *msg) { struct GNUNET_SERVER_Handle *server = cls; GNUNET_break (GNUNET_OK == GNUNET_SERVER_inject (server, NULL, msg)); return GNUNET_OK; } /** * Load persistent values from disk. Disk format is * exactly the same format that we also use for * setting the values over the network. * * @param server handle to the server context */ static void load (struct GNUNET_SERVER_Handle *server) { char *fn; struct GNUNET_BIO_ReadHandle *rh; uint64_t fsize; char *buf; struct GNUNET_SERVER_MessageStreamTokenizer *mst; char *emsg; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "STATISTICS", "DATABASE", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "STATISTICS", "DATABASE"); return; } if ( (GNUNET_OK != GNUNET_DISK_file_size (fn, &fsize, GNUNET_NO, GNUNET_YES)) || (0 == fsize) ) { GNUNET_free (fn); return; } buf = GNUNET_malloc (fsize); rh = GNUNET_BIO_read_open (fn); if (!rh) { GNUNET_free (buf); GNUNET_free (fn); return; } if (GNUNET_OK != GNUNET_BIO_read (rh, fn, buf, fsize)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "read", fn); GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, &emsg)); GNUNET_free (buf); GNUNET_free_non_null (emsg); GNUNET_free (fn); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading %llu bytes of statistics from `%s'\n"), fsize, fn); mst = GNUNET_SERVER_mst_create (&inject_message, server); GNUNET_break (GNUNET_OK == GNUNET_SERVER_mst_receive (mst, NULL, buf, fsize, GNUNET_YES, GNUNET_NO)); GNUNET_SERVER_mst_destroy (mst); GNUNET_free (buf); GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, &emsg)); GNUNET_free_non_null (emsg); GNUNET_free (fn); } /** * Write persistent statistics to disk. */ static void save () { struct StatsEntry *pos; char *fn; struct GNUNET_BIO_WriteHandle *wh; uint16_t size; unsigned long long total; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "STATISTICS", "DATABASE", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "STATISTICS", "DATABASE"); return; } (void) GNUNET_DISK_directory_create_for_file (fn); wh = GNUNET_BIO_write_open (fn); total = 0; while (NULL != (pos = start)) { start = pos->next; if ((pos->persistent) && (NULL != wh)) { size = htons (pos->msg->header.size); if (GNUNET_OK != GNUNET_BIO_write (wh, pos->msg, size)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn); if (GNUNET_OK != GNUNET_BIO_write_close (wh)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "close", fn); wh = NULL; } else total += size; } GNUNET_free (pos); } if (NULL != wh) { if (GNUNET_OK != GNUNET_BIO_write_close (wh)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "close", fn); if (total == 0) GNUNET_break (0 == UNLINK (fn)); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Wrote %llu bytes of statistics to `%s'\n"), total, fn); } GNUNET_free_non_null (fn); } /** * Transmit the given stats value. * * @param client receiver of the value * @param e value to transmit */ static void transmit (struct GNUNET_SERVER_Client *client, const struct StatsEntry *e) { struct GNUNET_STATISTICS_ReplyMessage *m; size_t size; size = sizeof (struct GNUNET_STATISTICS_ReplyMessage) + strlen (e->service) + 1 + strlen (e->name) + 1; GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); m = GNUNET_malloc (size); m->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_VALUE); m->header.size = htons (size); m->uid = htonl (e->uid); if (e->persistent) m->uid |= htonl (GNUNET_STATISTICS_PERSIST_BIT); m->value = GNUNET_htonll (e->value); size -= sizeof (struct GNUNET_STATISTICS_ReplyMessage); GNUNET_assert (size == GNUNET_STRINGS_buffer_fill ((char *) &m[1], size, 2, e->service, e->name)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting value for `%s:%s' (%d): %llu\n", e->service, e->name, e->persistent, e->value); GNUNET_SERVER_notification_context_unicast (nc, client, &m->header, GNUNET_NO); GNUNET_free (m); } /** * Does this entry match the request? * * @param e an entry * @param service name of service to match * @param name value to match * @return 1 if they match, 0 if not */ static int matches (const struct StatsEntry *e, const char *service, const char *name) { return ((0 == strlen (service)) || (0 == strcmp (service, e->service))) && ((0 == strlen (name)) || (0 == strcmp (name, e->name))); } /** * Find a client entry for the given client handle, or create one. * * @param client handle to match * @return corresponding client entry struct */ static struct ClientEntry * make_client_entry (struct GNUNET_SERVER_Client *client) { struct ClientEntry *ce; GNUNET_assert (client != NULL); ce = client_head; while (ce != NULL) { if (ce->client == client) return ce; ce = ce->next; } if (NULL == nc) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return NULL; } ce = GNUNET_new (struct ClientEntry); ce->client = client; GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ce); GNUNET_SERVER_notification_context_add (nc, client); return ce; } /** * Handle GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static void handle_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_MessageHeader end; char *service; char *name; struct StatsEntry *pos; size_t size; if ( (NULL != client) && (NULL == make_client_entry (client)) ) return; /* new client during shutdown */ size = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader); if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], size, 2, &service, &name)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request for statistics on `%s:%s'\n", strlen (service) ? service : "*", strlen (name) ? name : "*"); for (pos = start; NULL != pos; pos = pos->next) if (matches (pos, service, name)) transmit (client, pos); end.size = htons (sizeof (struct GNUNET_MessageHeader)); end.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_END); GNUNET_SERVER_notification_context_unicast (nc, client, &end, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Notify all clients listening about a change to a value. * * @param se value that changed */ static void notify_change (struct StatsEntry *se) { struct GNUNET_STATISTICS_WatchValueMessage wvm; struct WatchEntry *pos; for (pos = se->we_head; NULL != pos; pos = pos->next) { if (GNUNET_YES == pos->last_value_set) { if (pos->last_value == se->value) continue; } else { pos->last_value_set = GNUNET_YES; } wvm.header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE); wvm.header.size = htons (sizeof (struct GNUNET_STATISTICS_WatchValueMessage)); wvm.flags = htonl (se->persistent ? GNUNET_STATISTICS_PERSIST_BIT : 0); wvm.wid = htonl (pos->wid); wvm.reserved = htonl (0); wvm.value = GNUNET_htonll (se->value); GNUNET_SERVER_notification_context_unicast (nc, pos->client, &wvm.header, GNUNET_NO); pos->last_value = se->value; } } /** * Handle SET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_set (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { char *service; char *name; uint16_t msize; uint16_t size; const struct GNUNET_STATISTICS_SetMessage *msg; struct StatsEntry *pos; struct StatsEntry *prev; uint32_t flags; uint64_t value; int64_t delta; int changed; int initial_set; if ( (NULL != client) && (NULL == make_client_entry (client)) ) return; /* new client during shutdown */ msize = ntohs (message->size); if (msize < sizeof (struct GNUNET_STATISTICS_SetMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } size = msize - sizeof (struct GNUNET_STATISTICS_SetMessage); msg = (const struct GNUNET_STATISTICS_SetMessage *) message; if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &msg[1], size, 2, &service, &name)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } flags = ntohl (msg->flags); value = GNUNET_ntohll (msg->value); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request to update statistic on `%s:%s' (%u) to/by %llu\n", service, name, (unsigned int) flags, (unsigned long long) value); pos = start; prev = NULL; while (pos != NULL) { if (matches (pos, service, name)) { initial_set = 0; if ((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) { changed = (pos->value != value); pos->value = value; } else { delta = (int64_t) value; if ((delta < 0) && (pos->value < -delta)) { changed = (pos->value != 0); pos->value = 0; } else { changed = (delta != 0); GNUNET_break ((delta <= 0) || (pos->value + delta > pos->value)); pos->value += delta; } } if (GNUNET_NO == pos->set) { pos->set = GNUNET_YES; initial_set = 1; } pos->msg->value = GNUNET_htonll (pos->value); pos->msg->flags = msg->flags; pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT)); if (prev != NULL) { /* move to front for faster setting next time! */ prev->next = pos->next; pos->next = start; start = pos; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Statistic `%s:%s' updated to value %llu.\n", service, name, pos->value); if ((changed) || (1 == initial_set)) notify_change (pos); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } prev = pos; pos = pos->next; } pos = GNUNET_malloc (sizeof (struct StatsEntry) + msize); pos->next = start; if (((flags & GNUNET_STATISTICS_SETFLAG_RELATIVE) == 0) || (0 < (int64_t) GNUNET_ntohll (msg->value))) { pos->value = GNUNET_ntohll (msg->value); pos->set = GNUNET_YES; } else { pos->set = GNUNET_NO; } pos->uid = uidgen++; pos->persistent = (0 != (flags & GNUNET_STATISTICS_SETFLAG_PERSISTENT)); pos->msg = (void *) &pos[1]; memcpy (pos->msg, message, ntohs (message->size)); pos->service = (const char *) &pos->msg[1]; pos->name = &pos->service[strlen (pos->service) + 1]; start = pos; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New statistic on `%s:%s' with value %llu created.\n", service, name, pos->value); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle WATCH-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_watch (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { char *service; char *name; uint16_t msize; uint16_t size; struct StatsEntry *pos; struct ClientEntry *ce; struct WatchEntry *we; size_t slen; if (NULL == nc) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_client_mark_monitor (client); ce = make_client_entry (client); msize = ntohs (message->size); if (msize < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } size = msize - sizeof (struct GNUNET_MessageHeader); if (size != GNUNET_STRINGS_buffer_tokenize ((const char *) &message[1], size, 2, &service, &name)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request to watch statistic on `%s:%s'\n", service, name); pos = start; while (pos != NULL) { if (matches (pos, service, name)) break; pos = pos->next; } if (pos == NULL) { pos = GNUNET_malloc (sizeof (struct StatsEntry) + sizeof (struct GNUNET_STATISTICS_SetMessage) + size); pos->next = start; pos->uid = uidgen++; pos->set = GNUNET_NO; pos->msg = (void *) &pos[1]; pos->msg->header.size = htons (sizeof (struct GNUNET_STATISTICS_SetMessage) + size); pos->msg->header.type = htons (GNUNET_MESSAGE_TYPE_STATISTICS_SET); pos->service = (const char *) &pos->msg[1]; slen = strlen (service) + 1; memcpy ((void *) pos->service, service, slen); pos->name = &pos->service[slen]; memcpy ((void *) pos->name, name, strlen (name) + 1); start = pos; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New statistic on `%s:%s' with value %llu created.\n", service, name, pos->value); } we = GNUNET_new (struct WatchEntry); we->client = client; we->last_value_set = GNUNET_NO; we->wid = ce->max_wid++; GNUNET_CONTAINER_DLL_insert (pos->we_head, pos->we_tail, we); if (pos->value != 0) notify_change (pos); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Actually perform the shutdown. */ static void do_shutdown () { struct WatchEntry *we; struct StatsEntry *se; if (NULL == nc) return; save (); GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; GNUNET_assert (NULL == client_head); while (NULL != (se = start)) { start = se->next; while (NULL != (we = se->we_head)) { GNUNET_CONTAINER_DLL_remove (se->we_head, se->we_tail, we); GNUNET_free (we); } GNUNET_free (se); } } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { in_shutdown = GNUNET_YES; if (NULL != client_head) return; do_shutdown (); } /** * A client disconnected. Remove all of its data structure entries. * * @param cls closure, NULL * @param client identification of the client */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ClientEntry *ce; struct WatchEntry *we; struct WatchEntry *wen; struct StatsEntry *se; ce = client_head; while (NULL != ce) { if (ce->client == client) { GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce); GNUNET_free (ce); break; } ce = ce->next; } se = start; while (NULL != se) { wen = se->we_head; while (NULL != (we = wen)) { wen = we->next; if (we->client != client) continue; GNUNET_CONTAINER_DLL_remove (se->we_head, se->we_tail, we); GNUNET_free (we); } se = se->next; } if ( (NULL == client_head) && (GNUNET_YES == in_shutdown) ) do_shutdown (); } /** * Process statistics requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_set, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_SET, 0}, {&handle_get, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_GET, 0}, {&handle_watch, NULL, GNUNET_MESSAGE_TYPE_STATISTICS_WATCH, 0}, {NULL, NULL, 0, 0} }; cfg = c; srv = server; GNUNET_SERVER_add_handlers (server, handlers); nc = GNUNET_SERVER_notification_context_create (server, 16); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); load (server); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for the statistics service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "statistics", GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN, &run, NULL)) ? 0 : 1; } #ifdef LINUX #include /** * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ void __attribute__ ((constructor)) GNUNET_ARM_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); malloc_trim (0); } #endif /* end of gnunet-service-statistics.c */ gnunet-0.10.1/src/statistics/test_gnunet_statistics.py.in0000644000175000017500000001046212276413666020603 00000000000000#!@PYTHON@ from __future__ import print_function import os import sys import shutil import re import subprocess import time if os.name == "nt": tmp = os.getenv ("TEMP") else: tmp = "/tmp" if os.name == 'nt': st = './gnunet-statistics.exe' arm = 'gnunet-arm.exe' else: st = './gnunet-statistics' arm = 'gnunet-arm' run_st = [st, '-c', 'test_statistics_api_data.conf'] run_arm = [arm, '-c', 'test_statistics_api_data.conf'] debug = os.getenv ('DEBUG') if debug: run_arm += [debug.split (' ')] def cleanup (): shutil.rmtree (os.path.join (tmp, "test-gnunet-statistics"), True) def sub_run (args, want_stdo = True, want_stde = False, nofail = False): if want_stdo: stdo = subprocess.PIPE else: stdo = None if want_stde: stde = subprocess.PIPE else: stde = None p = subprocess.Popen (args, stdout = stdo, stderr = stde) stdo, stde = p.communicate () if not nofail: if p.returncode != 0: sys.exit (p.returncode) return (p.returncode, stdo, stde) def fail (result): print (result) r_arm (['-e'], want_stdo = False) sys.exit (1) def r_arm (extra_args, **kw): rc, stdo, stde = sub_run (run_arm + extra_args, **kw) if rc != 0: fail ("FAIL: error running {}".format (run_arm)) return (rc, stdo, stde) def r_st (extra_args, normal = True, **kw): rc, stdo, stde = sub_run (run_st + extra_args, **kw) if normal: if rc != 0: fail ("FAIL: error running {}".format (run_st)) else: if rc == 0: fail ("FAIL: expected error while running {}".format (run_st)) return (rc, stdo, stde) def restart (): print ("Restarting service...") t = r_arm (['-k', 'statistics']) time.sleep (1) t = r_arm (['-i', 'statistics']) time.sleep (1) cleanup () print ("Preparing: Starting service...") t = r_arm (['-s'], want_stdo = False) time.sleep (1) t = r_arm (['-i', 'statistics'], want_stdo = False) time.sleep (1) print ("TEST: Bad argument checking...", end='') r_st (['-x'], normal = False, nofail = True, want_stdo = False, want_stde = True) print ("PASS") print ("TEST: Set value...", end='') r_st (['-n', 'test', '-s', 'subsystem', b'42'], nofail = True, want_stdo = False) print ("PASS") print ("TEST: Set another value...", end='') r_st (['-n', 'other', '-s', 'osystem', b'43'], nofail = True, want_stdo = False) print ("PASS") print ("TEST: Viewing all stats...", end='') rc, stdo, stde = r_st ([], nofail = True, want_stdo = True) if len (stdo.splitlines ()) != 2: fail ("FAIL: unexpected output:\n{}".format (stdo)) print ("PASS") print ("TEST: Viewing stats by name...", end='') rc, stdo, stde = r_st (['-n', 'other'], nofail = True, want_stdo = True) if len ([x for x in stdo.splitlines () if re.search (b'43', x)]) != 1: fail ("FAIL: unexpected output:\n{}".format (stdo)) print ("PASS") print ("TEST: Viewing stats by subsystem...", end='') rc, stdo, stde = r_st (['-s', 'subsystem'], nofail = True, want_stdo = True) if len ([x for x in stdo.splitlines () if re.search (b'42', x)]) != 1: fail ("FAIL: unexpected output:\n{}".format (stdo)) print ("PASS") print ("TEST: Set persistent value...", end='') rc, stdo, stde = r_st (['-n', 'lasting', '-s', 'subsystem', '40', '-p'], nofail = True, want_stdo = False) rc, stdo, stde = r_st ([], nofail = True, want_stdo = True) if len ([x for x in stdo.splitlines () if re.search (b'40', x)]) != 1: fail ("FAIL: unexpected output:\n{}".format (stdo)) print ("PASS") restart () print ("TEST: Checking persistence...", end='') rc, stdo, stde = r_st ([], nofail = True, want_stdo = True) if len ([x for x in stdo.splitlines () if re.search (b'40', x)]) != 1: fail ("FAIL: unexpected output:\n{}".format (stdo)) print ("PASS") print ("TEST: Removing persistence...", end='') rc, stdo, stde = r_st (['-n', 'lasting', '-s', 'subsystem', '40'], nofail = True, want_stdo = False) rc, stdo, stde = r_st ([], nofail = True, want_stdo = True) if len ([x for x in stdo.splitlines () if re.search (b'!', x)]) != 0: fail ("FAIL: unexpected output:\n{}".format (stdo)) print ("PASS") restart () print ("TEST: Checking removed persistence...", end='') rc, stdo, stde = r_st ([], nofail = True, want_stdo = True) if len ([x for x in stdo.splitlines () if re.search (b'40', x)]) != 0: fail ("FAIL: unexpected output:\n{}".format (stdo)) print ("PASS") print ("Stopping service...") t = r_arm (['-e'], want_stdo = False) time.sleep (1) cleanup () gnunet-0.10.1/src/statistics/Makefile.in0000644000175000017500000014167312320755623015061 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-statistics$(EXEEXT) bin_PROGRAMS = gnunet-statistics$(EXEEXT) check_PROGRAMS = test_statistics_api$(EXEEXT) \ test_statistics_api_loop$(EXEEXT) \ test_statistics_api_watch$(EXEEXT) \ test_statistics_api_watch_zero_value$(EXEEXT) subdir = src/statistics DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/statistics.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = statistics.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetstatistics_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetstatistics_la_OBJECTS = statistics_api.lo libgnunetstatistics_la_OBJECTS = $(am_libgnunetstatistics_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetstatistics_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetstatistics_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_service_statistics_OBJECTS = \ gnunet-service-statistics.$(OBJEXT) gnunet_service_statistics_OBJECTS = \ $(am_gnunet_service_statistics_OBJECTS) am_gnunet_statistics_OBJECTS = gnunet-statistics.$(OBJEXT) gnunet_statistics_OBJECTS = $(am_gnunet_statistics_OBJECTS) am_test_statistics_api_OBJECTS = test_statistics_api.$(OBJEXT) test_statistics_api_OBJECTS = $(am_test_statistics_api_OBJECTS) test_statistics_api_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_statistics_api_loop_OBJECTS = \ test_statistics_api_loop.$(OBJEXT) test_statistics_api_loop_OBJECTS = \ $(am_test_statistics_api_loop_OBJECTS) test_statistics_api_loop_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_statistics_api_watch_OBJECTS = \ test_statistics_api_watch.$(OBJEXT) test_statistics_api_watch_OBJECTS = \ $(am_test_statistics_api_watch_OBJECTS) test_statistics_api_watch_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_statistics_api_watch_zero_value_OBJECTS = \ test_statistics_api_watch_zero_value.$(OBJEXT) test_statistics_api_watch_zero_value_OBJECTS = \ $(am_test_statistics_api_watch_zero_value_OBJECTS) test_statistics_api_watch_zero_value_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetstatistics_la_SOURCES) \ $(gnunet_service_statistics_SOURCES) \ $(gnunet_statistics_SOURCES) $(test_statistics_api_SOURCES) \ $(test_statistics_api_loop_SOURCES) \ $(test_statistics_api_watch_SOURCES) \ $(test_statistics_api_watch_zero_value_SOURCES) DIST_SOURCES = $(libgnunetstatistics_la_SOURCES) \ $(gnunet_service_statistics_SOURCES) \ $(gnunet_statistics_SOURCES) $(test_statistics_api_SOURCES) \ $(test_statistics_api_loop_SOURCES) \ $(test_statistics_api_watch_SOURCES) \ $(test_statistics_api_watch_zero_value_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ statistics.conf lib_LTLIBRARIES = libgnunetstatistics.la libgnunetstatistics_la_SOURCES = \ statistics_api.c statistics.h libgnunetstatistics_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetstatistics_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:3:1 gnunet_statistics_SOURCES = \ gnunet-statistics.c gnunet_statistics_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_statistics_DEPENDENCIES = \ libgnunetstatistics.la gnunet_service_statistics_SOURCES = \ gnunet-service-statistics.c gnunet_service_statistics_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_statistics_DEPENDENCIES = \ libgnunetstatistics.la @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) $(check_SCRIPTS) test_statistics_api_SOURCES = \ test_statistics_api.c test_statistics_api_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la test_statistics_api_loop_SOURCES = \ test_statistics_api_loop.c test_statistics_api_loop_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la test_statistics_api_watch_SOURCES = \ test_statistics_api_watch.c test_statistics_api_watch_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la test_statistics_api_watch_zero_value_SOURCES = \ test_statistics_api_watch_zero_value.c test_statistics_api_watch_zero_value_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la @HAVE_PYTHON_TRUE@check_SCRIPTS = \ @HAVE_PYTHON_TRUE@ test_gnunet_statistics.py do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' EXTRA_DIST = \ test_statistics_api_data.conf \ test_gnunet_statistics.py.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/statistics/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/statistics/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): statistics.conf: $(top_builddir)/config.status $(srcdir)/statistics.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetstatistics.la: $(libgnunetstatistics_la_OBJECTS) $(libgnunetstatistics_la_DEPENDENCIES) $(EXTRA_libgnunetstatistics_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetstatistics_la_LINK) -rpath $(libdir) $(libgnunetstatistics_la_OBJECTS) $(libgnunetstatistics_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-service-statistics$(EXEEXT): $(gnunet_service_statistics_OBJECTS) $(gnunet_service_statistics_DEPENDENCIES) $(EXTRA_gnunet_service_statistics_DEPENDENCIES) @rm -f gnunet-service-statistics$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_statistics_OBJECTS) $(gnunet_service_statistics_LDADD) $(LIBS) gnunet-statistics$(EXEEXT): $(gnunet_statistics_OBJECTS) $(gnunet_statistics_DEPENDENCIES) $(EXTRA_gnunet_statistics_DEPENDENCIES) @rm -f gnunet-statistics$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_statistics_OBJECTS) $(gnunet_statistics_LDADD) $(LIBS) test_statistics_api$(EXEEXT): $(test_statistics_api_OBJECTS) $(test_statistics_api_DEPENDENCIES) $(EXTRA_test_statistics_api_DEPENDENCIES) @rm -f test_statistics_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_statistics_api_OBJECTS) $(test_statistics_api_LDADD) $(LIBS) test_statistics_api_loop$(EXEEXT): $(test_statistics_api_loop_OBJECTS) $(test_statistics_api_loop_DEPENDENCIES) $(EXTRA_test_statistics_api_loop_DEPENDENCIES) @rm -f test_statistics_api_loop$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_statistics_api_loop_OBJECTS) $(test_statistics_api_loop_LDADD) $(LIBS) test_statistics_api_watch$(EXEEXT): $(test_statistics_api_watch_OBJECTS) $(test_statistics_api_watch_DEPENDENCIES) $(EXTRA_test_statistics_api_watch_DEPENDENCIES) @rm -f test_statistics_api_watch$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_statistics_api_watch_OBJECTS) $(test_statistics_api_watch_LDADD) $(LIBS) test_statistics_api_watch_zero_value$(EXEEXT): $(test_statistics_api_watch_zero_value_OBJECTS) $(test_statistics_api_watch_zero_value_DEPENDENCIES) $(EXTRA_test_statistics_api_watch_zero_value_DEPENDENCIES) @rm -f test_statistics_api_watch_zero_value$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_statistics_api_watch_zero_value_OBJECTS) $(test_statistics_api_watch_zero_value_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-statistics.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-statistics.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statistics_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_statistics_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_statistics_api_loop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_statistics_api_watch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_statistics_api_watch_zero_value.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_statistics_api.log: test_statistics_api$(EXEEXT) @p='test_statistics_api$(EXEEXT)'; \ b='test_statistics_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_statistics_api_loop.log: test_statistics_api_loop$(EXEEXT) @p='test_statistics_api_loop$(EXEEXT)'; \ b='test_statistics_api_loop'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_statistics_api_watch.log: test_statistics_api_watch$(EXEEXT) @p='test_statistics_api_watch$(EXEEXT)'; \ b='test_statistics_api_watch'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_statistics_api_watch_zero_value.log: test_statistics_api_watch_zero_value$(EXEEXT) @p='test_statistics_api_watch_zero_value$(EXEEXT)'; \ b='test_statistics_api_watch_zero_value'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_statistics.py.log: test_gnunet_statistics.py @p='test_gnunet_statistics.py'; \ b='test_gnunet_statistics.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA %.py: %.py.in Makefile $(do_subst) < $(srcdir)/$< > $@ chmod +x $@ test_gnunet_statistics.py: test_gnunet_statistics.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_statistics.py.in > test_gnunet_statistics.py chmod +x test_gnunet_statistics.py # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/statistics/test_statistics_api_loop.c0000644000175000017500000000637212301361474020263 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file statistics/test_statistics_api_loop.c * @brief testcase for statistics_api.c */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #define ROUNDS (1024 * 1024) static struct GNUNET_STATISTICS_Handle *h; static int check_1 (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_assert (0 == strcmp (name, "test-0")); GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api-loop")); GNUNET_assert (is_persistent == GNUNET_NO); return GNUNET_OK; } static void next (void *cls, int success) { int *ok = cls; GNUNET_STATISTICS_destroy (h, GNUNET_NO); GNUNET_assert (success == GNUNET_OK); *ok = 0; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { unsigned int i; char name[128]; h = GNUNET_STATISTICS_create ("test-statistics-api-loop", cfg); for (i = 0; i < ROUNDS; i++) { GNUNET_snprintf (name, sizeof (name), "test-%d", i % 256); GNUNET_STATISTICS_set (h, name, i, GNUNET_NO); GNUNET_snprintf (name, sizeof (name), "test-%d", i % 128); GNUNET_STATISTICS_update (h, name, 1, GNUNET_NO); } i = 0; GNUNET_break (NULL != GNUNET_STATISTICS_get (h, NULL, "test-0", GNUNET_TIME_UNIT_MINUTES, &next, &check_1, cls)); } int main (int argc, char *argv_ign[]) { int ok = 1; char *const argv[] = { "test-statistics-api", "-c", "test_statistics_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; struct GNUNET_OS_Process *proc; char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics"); proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-statistics", "-c", "test_statistics_api_data.conf", NULL); GNUNET_assert (NULL != proc); GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp", options, &run, &ok); if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); ok = 1; } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = NULL; GNUNET_free (binary); return ok; } /* end of test_statistics_api_loop.c */ gnunet-0.10.1/src/statistics/statistics.h0000644000175000017500000000624212225777503015354 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file statistics/statistics.h */ #ifndef STATISTICS_H #define STATISTICS_H #include "gnunet_common.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Statistics message. Contains how long the system is up * and one value. * * The struct is be followed by the service name and * name of the statistic, both 0-terminated. */ struct GNUNET_STATISTICS_ReplyMessage { /** * Type: GNUNET_MESSAGE_TYPE_STATISTICS_VALUE */ struct GNUNET_MessageHeader header; /** * Unique numerical identifier for the value (will * not change during the same client-session). Highest * bit will be set for persistent values. */ uint32_t uid GNUNET_PACKED; /** * The value. */ uint64_t value GNUNET_PACKED; }; #define GNUNET_STATISTICS_PERSIST_BIT (1<<31) #define GNUNET_STATISTICS_SETFLAG_ABSOLUTE 0 #define GNUNET_STATISTICS_SETFLAG_RELATIVE 1 #define GNUNET_STATISTICS_SETFLAG_PERSISTENT 2 /** * Message to set a statistic. Followed * by the subsystem name and the name of * the statistic (each 0-terminated). */ struct GNUNET_STATISTICS_SetMessage { /** * Type: GNUNET_MESSAGE_TYPE_STATISTICS_SET */ struct GNUNET_MessageHeader header; /** * 0 for absolute value, 1 for relative value; 2 to make persistent * (see GNUNET_STATISTICS_SETFLAG_*). */ uint32_t flags GNUNET_PACKED; /** * Value. Note that if this is a relative value, it will * be signed even though the type given here is unsigned. */ uint64_t value GNUNET_PACKED; }; /** * Message transmitted if a watched value changes. */ struct GNUNET_STATISTICS_WatchValueMessage { /** * Type: GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE */ struct GNUNET_MessageHeader header; /** * 0 for absolute value, 1 for relative value; 2 to make persistent * (see GNUNET_STATISTICS_SETFLAG_*). */ uint32_t flags GNUNET_PACKED; /** * Unique watch identification number (watch * requests are enumerated in the order they * are received, the first request having * a wid of zero). */ uint32_t wid GNUNET_PACKED; /** * Reserved (always 0). */ uint32_t reserved GNUNET_PACKED; /** * Value. Note that if this is a relative value, it will * be signed even though the type given here is unsigned. */ uint64_t value GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/statistics/test_statistics_api_watch_zero_value.c0000644000175000017500000001170212301361474022644 00000000000000/* This file is part of GNUnet. (C) 2009, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file statistics/test_statistics_api_watch_zero_value.c * @brief testcase for statistics_api.c watch functions with initial 0 value */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" static int ok; static int ok2; static struct GNUNET_STATISTICS_Handle *h; static struct GNUNET_STATISTICS_Handle *h2; static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; static void force_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { fprintf (stderr, "Timeout, failed to receive notifications: %d\n", ok); GNUNET_STATISTICS_destroy (h, GNUNET_NO); GNUNET_STATISTICS_destroy (h2, GNUNET_NO); ok = 7; } static void normal_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_STATISTICS_destroy (h, GNUNET_NO); GNUNET_STATISTICS_destroy (h2, GNUNET_NO); } static int watch_1 (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received value `%s' `%s' %llu\n", subsystem, name, value); GNUNET_assert (0 == strcmp (name, "test-1")); if ((0 == value) && (3 == ok)) { ok--; GNUNET_STATISTICS_set (h, "test-1", 42, GNUNET_NO); } if ((42 == value) && (2 == ok)) { ok--; GNUNET_STATISTICS_set (h, "test-1", 0, GNUNET_NO); } if ((0 == value) && (1 == ok)) { ok--; } if ((0 == ok) && (0 == ok2)) { GNUNET_SCHEDULER_cancel (shutdown_task); GNUNET_SCHEDULER_add_now (&normal_shutdown, NULL); } return GNUNET_OK; } static int watch_2 (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received value `%s' `%s' %llu\n", subsystem, name, value); GNUNET_assert (0 == strcmp (name, "test-2")); if ((42 == value) && (1 == ok2)) { ok2 = 0; if (0 == ok) { GNUNET_SCHEDULER_cancel (shutdown_task); GNUNET_SCHEDULER_add_now (&normal_shutdown, NULL); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received unexpected value %llu\n", value); GNUNET_break (0); GNUNET_SCHEDULER_cancel (shutdown_task); GNUNET_SCHEDULER_add_now (&normal_shutdown, NULL); } return GNUNET_OK; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { h = GNUNET_STATISTICS_create ("dummy", cfg); h2 = GNUNET_STATISTICS_create ("dummy-2", cfg); GNUNET_assert (GNUNET_OK == GNUNET_STATISTICS_watch (h, "dummy", "test-1", &watch_1, NULL)); GNUNET_assert (GNUNET_OK == GNUNET_STATISTICS_watch (h2, "dummy-2", "test-2", &watch_2, NULL)); /* Set initial value to 0 */ GNUNET_STATISTICS_set (h, "test-1", 0, GNUNET_NO); GNUNET_STATISTICS_set (h2, "test-2", 42, GNUNET_NO); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &force_shutdown, NULL); } int main (int argc, char *argv_ign[]) { char *const argv[] = { "test-statistics-api", "-c", "test_statistics_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; struct GNUNET_OS_Process *proc; char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics"); proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-statistics", "-c", "test_statistics_api_data.conf", NULL); GNUNET_assert (NULL != proc); ok = 3; ok2 = 1; GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp", options, &run, NULL); if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); ok = 1; } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = NULL; GNUNET_free (binary); if ((0 == ok) && (0 == ok2)) return 0; return 1; } /* end of test_statistics_api_watch_zero_value.c */ gnunet-0.10.1/src/statistics/Makefile.am0000644000175000017500000000551412320755211015032 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ statistics.conf lib_LTLIBRARIES = libgnunetstatistics.la libgnunetstatistics_la_SOURCES = \ statistics_api.c statistics.h libgnunetstatistics_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetstatistics_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:3:1 libexec_PROGRAMS = \ gnunet-service-statistics bin_PROGRAMS = \ gnunet-statistics gnunet_statistics_SOURCES = \ gnunet-statistics.c gnunet_statistics_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_statistics_DEPENDENCIES = \ libgnunetstatistics.la gnunet_service_statistics_SOURCES = \ gnunet-service-statistics.c gnunet_service_statistics_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_statistics_DEPENDENCIES = \ libgnunetstatistics.la check_PROGRAMS = \ test_statistics_api \ test_statistics_api_loop \ test_statistics_api_watch \ test_statistics_api_watch_zero_value if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) $(check_SCRIPTS) endif test_statistics_api_SOURCES = \ test_statistics_api.c test_statistics_api_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la test_statistics_api_loop_SOURCES = \ test_statistics_api_loop.c test_statistics_api_loop_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la test_statistics_api_watch_SOURCES = \ test_statistics_api_watch.c test_statistics_api_watch_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la test_statistics_api_watch_zero_value_SOURCES = \ test_statistics_api_watch_zero_value.c test_statistics_api_watch_zero_value_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la if HAVE_PYTHON check_SCRIPTS = \ test_gnunet_statistics.py endif do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' %.py: %.py.in Makefile $(do_subst) < $(srcdir)/$< > $@ chmod +x $@ test_gnunet_statistics.py: test_gnunet_statistics.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_statistics.py.in > test_gnunet_statistics.py chmod +x test_gnunet_statistics.py EXTRA_DIST = \ test_statistics_api_data.conf \ test_gnunet_statistics.py.in gnunet-0.10.1/src/statistics/statistics.conf.in0000644000175000017500000000067612250373167016460 00000000000000[statistics] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2088 HOSTNAME = localhost BINARY = gnunet-service-statistics ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES DATABASE = $GNUNET_DATA_HOME/statistics.dat # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = gnunet-0.10.1/src/statistics/test_statistics_api_watch.c0000644000175000017500000001031312301361474020406 00000000000000/* This file is part of GNUnet. (C) 2009, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file statistics/test_statistics_api_watch.c * @brief testcase for statistics_api.c watch functions * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" static int ok; static struct GNUNET_STATISTICS_Handle *h; static struct GNUNET_STATISTICS_Handle *h2; static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; static void force_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { fprintf (stderr, "Timeout, failed to receive notifications: %d\n", ok); GNUNET_STATISTICS_destroy (h, GNUNET_NO); GNUNET_STATISTICS_destroy (h2, GNUNET_NO); ok = 7; } static void normal_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_STATISTICS_destroy (h, GNUNET_NO); GNUNET_STATISTICS_destroy (h2, GNUNET_NO); } static int watch_1 (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_assert (value == 42); GNUNET_assert (0 == strcmp (name, "test-1")); ok &= ~1; if (0 == ok) { GNUNET_SCHEDULER_cancel (shutdown_task); GNUNET_SCHEDULER_add_now (&normal_shutdown, NULL); } return GNUNET_OK; } static int watch_2 (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_assert (value == 43); GNUNET_assert (0 == strcmp (name, "test-2")); ok &= ~2; if (0 == ok) { GNUNET_SCHEDULER_cancel (shutdown_task); GNUNET_SCHEDULER_add_now (&normal_shutdown, NULL); } return GNUNET_OK; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { h = GNUNET_STATISTICS_create ("dummy", cfg); GNUNET_assert (GNUNET_OK == GNUNET_STATISTICS_watch (h, "test-statistics-api-watch", "test-1", &watch_1, NULL)); GNUNET_assert (GNUNET_OK == GNUNET_STATISTICS_watch (h, "test-statistics-api-watch", "test-2", &watch_2, NULL)); h2 = GNUNET_STATISTICS_create ("test-statistics-api-watch", cfg); GNUNET_STATISTICS_set (h2, "test-1", 42, GNUNET_NO); GNUNET_STATISTICS_set (h2, "test-2", 43, GNUNET_NO); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &force_shutdown, NULL); } int main (int argc, char *argv_ign[]) { char *const argv[] = { "test-statistics-api", "-c", "test_statistics_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; struct GNUNET_OS_Process *proc; char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics"); proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-statistics", "-c", "test_statistics_api_data.conf", NULL); GNUNET_assert (NULL != proc); ok = 3; GNUNET_PROGRAM_run (3, argv, "test-statistics-api", "nohelp", options, &run, NULL); if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); ok = 1; } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = NULL; GNUNET_free (binary); return ok; } /* end of test_statistics_api_watch.c */ gnunet-0.10.1/src/statistics/test_statistics_api.c0000644000175000017500000001371212301361474017226 00000000000000/* This file is part of GNUnet. (C) 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file statistics/test_statistics_api.c * @brief testcase for statistics_api.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" static struct GNUNET_STATISTICS_Handle *h; static int check_1 (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received value %llu for `%s:%s\n", (unsigned long long) value, subsystem, name); GNUNET_assert (0 == strcmp (name, "test-1")); GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); GNUNET_assert (value == 1); GNUNET_assert (is_persistent == GNUNET_NO); return GNUNET_OK; } static int check_2 (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received value %llu for `%s:%s\n", (unsigned long long) value, subsystem, name); GNUNET_assert (0 == strcmp (name, "test-2")); GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); GNUNET_assert (value == 2); GNUNET_assert (is_persistent == GNUNET_NO); return GNUNET_OK; } static int check_3 (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received value %llu for `%s:%s\n", (unsigned long long) value, subsystem, name); GNUNET_assert (0 == strcmp (name, "test-3")); GNUNET_assert (0 == strcmp (subsystem, "test-statistics-api")); GNUNET_assert (value == 3); GNUNET_assert (is_persistent == GNUNET_YES); return GNUNET_OK; } static void next_fin (void *cls, int success) { int *ok = cls; GNUNET_STATISTICS_destroy (h, GNUNET_NO); GNUNET_assert (success == GNUNET_OK); *ok = 0; } static void next (void *cls, int success) { GNUNET_assert (success == GNUNET_OK); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Issuing GET request\n"); GNUNET_break (NULL != GNUNET_STATISTICS_get (h, NULL, "test-2", GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, cls)); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { h = GNUNET_STATISTICS_create ("test-statistics-api", cfg); GNUNET_STATISTICS_set (h, "test-1", 1, GNUNET_NO); GNUNET_STATISTICS_set (h, "test-2", 2, GNUNET_NO); GNUNET_STATISTICS_set (h, "test-3", 2, GNUNET_NO); GNUNET_STATISTICS_update (h, "test-3", 1, GNUNET_YES); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Issuing GET request\n"); GNUNET_break (NULL != GNUNET_STATISTICS_get (h, NULL, "test-1", GNUNET_TIME_UNIT_SECONDS, &next, &check_1, cls)); } static void run_more (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { h = GNUNET_STATISTICS_create ("test-statistics-api", cfg); GNUNET_break (NULL != GNUNET_STATISTICS_get (h, NULL, "test-3", GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_3, cls)); } int main (int argc, char *argv_ign[]) { int ok = 1; char *const argv[] = { "test-statistics-api", "-c", "test_statistics_api_data.conf", "-L", "WARNING", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; struct GNUNET_OS_Process *proc; char *binary; GNUNET_log_setup ("test_statistics_api", "WARNING", NULL); binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics"); proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-statistics", "-c", "test_statistics_api_data.conf", NULL); GNUNET_assert (NULL != proc); GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp", options, &run, &ok); if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); ok = 1; } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = NULL; if (ok != 0) { GNUNET_free (binary); return ok; } ok = 1; /* restart to check persistence! */ proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-statistics", "-c", "test_statistics_api_data.conf", NULL); GNUNET_PROGRAM_run (5, argv, "test-statistics-api", "nohelp", options, &run_more, &ok); if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); ok = 1; } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = NULL; GNUNET_free (binary); return ok; } /* end of test_statistics_api.c */ gnunet-0.10.1/src/experimentation/0000755000175000017500000000000012320755630014077 500000000000000gnunet-0.10.1/src/experimentation/gnunet-daemon-experimentation.h0000644000175000017500000002226312320530515022140 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file experimentation/gnunet-daemon-experimentation.h * @brief experimentation daemon * @author Christian Grothoff * @author Matthias Wachs */ #ifndef GNUNET_DAEMON_EXPERIMENTATION_H #define GNUNET_DAEMON_EXPERIMENTATION_H #include "platform.h" #include "gnunet_getopt_lib.h" #include "gnunet_util_lib.h" #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" /** * Timeout between request and expected response */ #define EXP_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Default experiment frequency */ #define EXP_DEFAULT_EXP_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 6) /** * Default experiment duration */ #define EXP_DEFAULT_EXP_DUR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Statistics handle shared between components */ extern struct GNUNET_STATISTICS_Handle *GED_stats; /** * Configuration handle shared between components */ extern struct GNUNET_CONFIGURATION_Handle *GED_cfg; /** * Capability value shared between components */ extern uint32_t GSE_node_capabilities; /** * Capabilities a node has or an experiment requires */ enum GNUNET_EXPERIMENTATION_capabilities { NONE = 0, PLUGIN_TCP = 1, PLUGIN_UDP = 2, PLUGIN_UNIX = 4, PLUGIN_HTTP_CLIENT = 8, PLUGIN_HTTP_SERVER = 16, PLUGIN_HTTPS_CLIENT = 32, PLUGIN_HTTPS_SERVER = 64, PLUGIN_WLAN = 128, HAVE_IPV6 = 256, BEHIND_NAT = 512 }; /** * Struct to store information about a specific experiment */ struct Experiment { /* Header */ /* ----------------- */ char *name; /** * Experiment issuer */ struct GNUNET_CRYPTO_EddsaPublicKey issuer; /** * Experiment version as timestamp of creation */ struct GNUNET_TIME_Absolute version; /** * Description */ char *description; /** * Required capabilities */ uint32_t required_capabilities; /* Experiment timing */ /* ----------------- */ /** * When to start experiment */ struct GNUNET_TIME_Absolute start; /** * When to end experiment */ struct GNUNET_TIME_Absolute stop; /** * How often to run experiment */ struct GNUNET_TIME_Relative frequency; /** * How long to run each execution */ struct GNUNET_TIME_Relative duration; /* Experiment itself */ /* ----------------- */ /* TBD */ }; /** * A experimentation node */ struct Node { /** * Peer id */ struct GNUNET_PeerIdentity id; /** * Task for response timeout */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Core transmission handle */ struct GNUNET_CORE_TransmitHandle *cth; /** * Node capabilities */ uint32_t capabilities; /** * Experiment version as timestamp of creation */ struct GNUNET_TIME_Absolute version; struct NodeComCtx *e_req_head; struct NodeComCtx *e_req_tail; /** * Array of issuers accepted by this neighbor. */ struct GNUNET_CRYPTO_EddsaPublicKey *issuer_id; unsigned int issuer_count; }; GNUNET_NETWORK_STRUCT_BEGIN /** * Experimentation request message * Used to detect experimentation capability * * This struct is followed by issuer identities: * (issuer_count * struct GNUNET_CRYPTO_EddsaPublicKey) * */ struct Experimentation_Request { struct GNUNET_MessageHeader msg; uint32_t capabilities GNUNET_PACKED; uint32_t issuer_count GNUNET_PACKED; }; /** * Experimentation response message * Sent if peer is running the daemon * * This struct is followed by issuer identities: * (issuer_count * struct GNUNET_CRYPTO_EddsaPublicKey) */ struct Experimentation_Response { struct GNUNET_MessageHeader msg; uint32_t capabilities GNUNET_PACKED; uint32_t issuer_count GNUNET_PACKED; }; /** * Struct to store information about an experiment issuer */ struct Issuer { struct GNUNET_CRYPTO_EddsaPublicKey pubkey; }; /** * Hashmap containing valid experiment issuers * (the key is the hash of the respective public key, * the values are of type `struct Issuer'). */ struct GNUNET_CONTAINER_MultiHashMap *valid_issuers; /** * Experiment start message * * struct is followed by string with length len_name */ struct GED_start_message { struct GNUNET_MessageHeader header; /** * String length of experiment name following the struct */ uint32_t len_name GNUNET_PACKED; /** * Experiment issuer */ struct GNUNET_CRYPTO_EddsaPublicKey issuer; /** * Experiment version as timestamp of creation */ struct GNUNET_TIME_AbsoluteNBO version_nbo; }; struct GED_start_ack_message { struct GNUNET_MessageHeader header; /** * String length of experiment name following the struct */ uint32_t len_name GNUNET_PACKED; /** * Experiment issuer */ struct GNUNET_CRYPTO_EddsaPublicKey issuer; /** * Experiment version as timestamp of creation */ struct GNUNET_TIME_AbsoluteNBO version_nbo; }; struct GED_stop_message { struct GNUNET_MessageHeader header; /** * String length of experiment name following the struct */ uint32_t len_name GNUNET_PACKED; /** * Experiment issuer */ struct GNUNET_CRYPTO_EddsaPublicKey issuer; /** * Experiment version as timestamp of creation */ struct GNUNET_TIME_AbsoluteNBO version_nbo; }; GNUNET_NETWORK_STRUCT_END int GED_nodes_rts (struct Node *n); int GED_nodes_send_start (struct Node *n, struct Experiment *e); /** * Confirm a experiment START with a node * * @return #GNUNET_NO if core was busy with sending, #GNUNET_OK otherwise */ int GED_nodes_send_start_ack (struct Node *n, struct Experiment *e); /** * Start the nodes management */ void GED_nodes_start (void); /** * Stop the nodes management */ void GED_nodes_stop (void); /** * Print a single capability value * * @param cap capability value * @return the string to print */ const char * GED_capability_to_str (uint32_t cap); /** * Are the capabilities provided? * * @param have bitstring containing the provided capabilities * @param desired bitstring containing the desired capabilities\ * @return #GNUNET_YES or #GNUNET_NO */ int GED_capabilities_have (uint32_t have, uint32_t desired); /** * Start the detecting capabilities */ void GED_capabilities_start (void); /** * Stop the detecting capabilities */ void GED_capabilities_stop (void); /** * Start experiments management * * @return #GNUNET_YES or #GNUNET_NO */ int GED_experiments_issuer_accepted (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer_ID); /* * Find an experiment based on issuer name and version * * @param issuer the issuer * @param name experiment name * @param version experiment version * @return the experiment or NULL if not found */ struct Experiment * GED_experiments_find (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer, const char *name, const struct GNUNET_TIME_Absolute version); typedef void (*GNUNET_EXPERIMENTATION_experiments_get_cb) (struct Node *n, struct Experiment *e); void GED_experiments_get (struct Node *n, struct GNUNET_CRYPTO_EddsaPublicKey *issuer, GNUNET_EXPERIMENTATION_experiments_get_cb get_cb); /** * Start experiments management * * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GED_experiments_start (void); /** * Stop experiments management */ void GED_experiments_stop (void); /** * Handle a START message from a remote node * * @param n the node * @param e the experiment */ void GED_scheduler_handle_start (struct Node *n, struct Experiment *e); /** * Handle a START_ACL message from a remote node * * @param n the node * @param e the experiment */ void GED_scheduler_handle_start_ack (struct Node *n, struct Experiment *e); /** * Handle a STOP message from a remote node * * @param n the node * @param e the experiment */ void GED_scheduler_handle_stop (struct Node *n, struct Experiment *e); /** * Add a new experiment for a node * * @param n the node * @param e the experiment * @param outbound are we initiator (#GNUNET_YES) or client (#GNUNET_NO)? */ void GED_scheduler_add (struct Node *n, struct Experiment *e, int outbound); /** * Start the scheduler component */ void GED_scheduler_start (void); /** * Stop the scheduler component */ void GED_scheduler_stop (void); /** * Start the storage component */ void GED_storage_start (void); /** * Stop the storage component */ void GED_storage_stop (void); #endif /* #ifndef GNUNET_DAEMON_EXPERIMENTATION_H */ /* end of gnunet-daemon-experimentation.h */ gnunet-0.10.1/src/experimentation/test_experiments.exp0000644000175000017500000000050412153073163020134 00000000000000[test-experiment-1] ISSUER = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG VERSION = 1 CAPABILITIES = 0 [test-experiment-2] ISSUER = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG VERSION = 1 CAPABILITIES = 0gnunet-0.10.1/src/experimentation/Makefile.in0000644000175000017500000012403012320752061016057 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = $(am__EXEEXT_1) @ENABLE_TEST_RUN_TRUE@TESTS = $(am__EXEEXT_1) libexec_PROGRAMS = gnunet-daemon-experimentation$(EXEEXT) subdir = src/experimentation DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/experimentation.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = experimentation.conf CONFIG_CLEAN_VPATH_FILES = @HAVE_EXPERIMENTAL_TRUE@am__EXEEXT_1 = test_experimentation_clique_connect$(EXEEXT) \ @HAVE_EXPERIMENTAL_TRUE@ test_experimentation_clique_run$(EXEEXT) am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" PROGRAMS = $(libexec_PROGRAMS) am_gnunet_daemon_experimentation_OBJECTS = \ gnunet-daemon-experimentation.$(OBJEXT) \ gnunet-daemon-experimentation_capabilities.$(OBJEXT) \ gnunet-daemon-experimentation_nodes.$(OBJEXT) \ gnunet-daemon-experimentation_scheduler.$(OBJEXT) \ gnunet-daemon-experimentation_experiments.$(OBJEXT) \ gnunet-daemon-experimentation_storage.$(OBJEXT) gnunet_daemon_experimentation_OBJECTS = \ $(am_gnunet_daemon_experimentation_OBJECTS) gnunet_daemon_experimentation_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_test_experimentation_clique_connect_OBJECTS = \ test_experimentation_clique_connect.$(OBJEXT) test_experimentation_clique_connect_OBJECTS = \ $(am_test_experimentation_clique_connect_OBJECTS) test_experimentation_clique_connect_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la am_test_experimentation_clique_run_OBJECTS = \ test_experimentation_clique_run.$(OBJEXT) test_experimentation_clique_run_OBJECTS = \ $(am_test_experimentation_clique_run_OBJECTS) test_experimentation_clique_run_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gnunet_daemon_experimentation_SOURCES) \ $(test_experimentation_clique_connect_SOURCES) \ $(test_experimentation_clique_run_SOURCES) DIST_SOURCES = $(gnunet_daemon_experimentation_SOURCES) \ $(test_experimentation_clique_connect_SOURCES) \ $(test_experimentation_clique_run_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ experimentation.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov @HAVE_EXPERIMENTAL_TRUE@TEXT_EXP_CLIQUE = test_experimentation_clique_connect test_experimentation_clique_run @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; gnunet_daemon_experimentation_SOURCES = \ gnunet-daemon-experimentation.c gnunet-daemon-experimentation.h \ gnunet-daemon-experimentation_capabilities.c \ gnunet-daemon-experimentation_nodes.c \ gnunet-daemon-experimentation_scheduler.c \ gnunet-daemon-experimentation_experiments.c \ gnunet-daemon-experimentation_storage.c gnunet_daemon_experimentation_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la test_experimentation_clique_connect_SOURCES = \ test_experimentation_clique_connect.c test_experimentation_clique_connect_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la test_experimentation_clique_run_SOURCES = \ test_experimentation_clique_run.c test_experimentation_clique_run_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la #test_experimentation_clique_run_SOURCES = \ # test_experimentation_clique_run.c #test_experimentation_clique_run_LDADD = \ # $(top_builddir)/src/util/libgnunetutil.la \ # $(top_builddir)/src/statistics/libgnunetstatistics.la \ # $(top_builddir)/src/testbed/libgnunettestbed.la EXTRA_DIST = \ test_experimentation_clique.conf \ test_experiments.exp all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/experimentation/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/experimentation/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): experimentation.conf: $(top_builddir)/config.status $(srcdir)/experimentation.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-daemon-experimentation$(EXEEXT): $(gnunet_daemon_experimentation_OBJECTS) $(gnunet_daemon_experimentation_DEPENDENCIES) $(EXTRA_gnunet_daemon_experimentation_DEPENDENCIES) @rm -f gnunet-daemon-experimentation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_experimentation_OBJECTS) $(gnunet_daemon_experimentation_LDADD) $(LIBS) test_experimentation_clique_connect$(EXEEXT): $(test_experimentation_clique_connect_OBJECTS) $(test_experimentation_clique_connect_DEPENDENCIES) $(EXTRA_test_experimentation_clique_connect_DEPENDENCIES) @rm -f test_experimentation_clique_connect$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_experimentation_clique_connect_OBJECTS) $(test_experimentation_clique_connect_LDADD) $(LIBS) test_experimentation_clique_run$(EXEEXT): $(test_experimentation_clique_run_OBJECTS) $(test_experimentation_clique_run_DEPENDENCIES) $(EXTRA_test_experimentation_clique_run_DEPENDENCIES) @rm -f test_experimentation_clique_run$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_experimentation_clique_run_OBJECTS) $(test_experimentation_clique_run_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-experimentation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-experimentation_capabilities.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-experimentation_experiments.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-experimentation_nodes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-experimentation_scheduler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-experimentation_storage.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_experimentation_clique_connect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_experimentation_clique_run.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_experimentation_clique_connect.log: test_experimentation_clique_connect$(EXEEXT) @p='test_experimentation_clique_connect$(EXEEXT)'; \ b='test_experimentation_clique_connect'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_experimentation_clique_run.log: test_experimentation_clique_run$(EXEEXT) @p='test_experimentation_clique_run$(EXEEXT)'; \ b='test_experimentation_clique_run'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libexecPROGRAMS install-man install-pdf install-pdf-am \ install-pkgcfgDATA install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/experimentation/experimentation.conf.in0000644000175000017500000000056612225230043020503 00000000000000[experimentation] AUTOSTART = NO # PORT = 2106 HOSTNAME = localhost BINARY = gnunet-daemon-experimentation ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-daemon-experimentation.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES ISSUERS = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG gnunet-0.10.1/src/experimentation/test_experimentation_clique_run.c0000644000175000017500000002612512226035651022670 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/experimentation/test_experimentation_clique_run.c * @brief test case to run experiments with experimentation daemons in a clique * @author Sree Harsha Totakura * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we want to start */ #define NUM_PEERS 2 #define NUM_ISSUER 1 #define NUM_EXPERIMENTS 2 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, (5 * NUM_PEERS) + 20) /** * Array of peers */ static struct GNUNET_TESTBED_Peer **peers; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * Shutdown task */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Testing result */ static int result; /** * Counter for counting overlay connections */ static unsigned int overlay_connects; /** * Information we track for a peer in the testbed. */ struct ExperimentationPeer { /** * Handle with testbed. */ struct GNUNET_TESTBED_Peer *daemon; /** * Testbed operation to connect to statistics service */ struct GNUNET_TESTBED_Operation *stat_op; /** * Handle to the statistics service */ struct GNUNET_STATISTICS_Handle *sh; unsigned int active_nodes; unsigned int requested_nodes; unsigned int inactive_nodes; unsigned int issuer; unsigned int experiments_active; unsigned int experiments_outbound_running; unsigned int experiments_inbound_running; }; struct ExperimentationPeer bp_slaves[NUM_PEERS]; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int peer; shutdown_task = GNUNET_SCHEDULER_NO_TASK; for (peer = 0; peer < NUM_PEERS; peer++) { if (NULL != bp_slaves[peer].stat_op) GNUNET_TESTBED_operation_done (bp_slaves[peer].stat_op); bp_slaves[peer].stat_op = NULL; } if (NULL != op) { GNUNET_TESTBED_operation_done (op); op = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_CONNECT: overlay_connects++; if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects) { result = GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers connected \n", NUM_PEERS); if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) { GNUNET_SCHEDULER_cancel (shutdown_task); } shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL); } break; case GNUNET_TESTBED_ET_OPERATION_FINISHED: break; default: GNUNET_break (0); result = GNUNET_SYSERR; GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } static void check_end () { static int last_in_experiments_value = 0; static int last_out_experiments_value = 0; unsigned int peer; unsigned int t_running_outbound_experiments = 0; unsigned int t_running_inbound_experiments = 0; for (peer = 0; peer < NUM_PEERS; peer++) { t_running_outbound_experiments += bp_slaves[peer].experiments_outbound_running; t_running_inbound_experiments += bp_slaves[peer].experiments_inbound_running; } //fprintf (stderr, "%u %u \n", t_running_outbound_experiments, t_running_inbound_experiments); if (last_in_experiments_value < t_running_inbound_experiments) fprintf (stderr, "."); last_in_experiments_value = t_running_inbound_experiments; if (last_out_experiments_value < t_running_outbound_experiments) fprintf (stderr, "."); last_out_experiments_value = t_running_outbound_experiments; if ((t_running_inbound_experiments == (NUM_PEERS * NUM_EXPERIMENTS)) && (t_running_outbound_experiments == (NUM_PEERS * NUM_EXPERIMENTS))) { fprintf (stderr, "\n"); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "All %u peers are running experiments\n", NUM_PEERS); GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } /** * Callback function to process statistic values. * * @param cls struct StatsContext * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int stat_iterator (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { struct ExperimentationPeer *peer = cls; if (0 == strcmp (name, "# experiments active")) { peer->experiments_active = value; } if (0 == strcmp (name, "# experiments outbound running")) { peer->experiments_outbound_running = value; } if (0 == strcmp (name, "# experiments inbound running")) { peer->experiments_inbound_running = value; } check_end (); return GNUNET_OK; } /** * Called after successfully opening a connection to a peer's statistics * service; we register statistics monitoring here. * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg ) { //struct GNUNET_STATISTICS_Handle *sh = ca_result; struct ExperimentationPeer *peer = cls; if (NULL != emsg) { GNUNET_break (0); return; } GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (peer->sh, "experimentation", "# experiments active", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (peer->sh, "experimentation", "# experiments outbound running", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (peer->sh, "experimentation", "# experiments inbound running", stat_iterator, peer)); } /** * Called to open a connection to the peer's statistics * * @param cls peer context * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * stat_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct ExperimentationPeer *peer = cls; peer->sh = GNUNET_STATISTICS_create ("experimentation", cfg); if (NULL == peer->sh) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create statistics \n"); return peer->sh; } /** * Called to disconnect from peer's statistics service * * @param cls peer context * @param op_result service handle returned from the connect adapter */ static void stat_disconnect_adapter (void *cls, void *op_result) { struct ExperimentationPeer *peer = cls; GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "experimentation", "# experiments active", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "experimentation", "# experiments outbound running", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "experimentation", "# experiments inbound running", stat_iterator, peer)); GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); peer->sh = NULL; } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { unsigned int peer; GNUNET_assert (NULL == cls); GNUNET_assert (NUM_PEERS == num_peers); GNUNET_assert (NULL != peers_); for (peer = 0; peer < num_peers; peer++) { GNUNET_assert (NULL != peers_[peer]); /* Connect to peer's statistic service */ bp_slaves[peer].stat_op = GNUNET_TESTBED_service_connect (NULL, peers_[peer], "statistics", &stat_comp_cb, &bp_slaves[peer], &stat_connect_adapter, &stat_disconnect_adapter, &bp_slaves[peer]); } peers = peers_; overlay_connects = 0; op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, NULL, NULL, GNUNET_TESTBED_TOPOLOGY_CLIQUE, /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */ /* NUM_PEERS, */ GNUNET_TESTBED_TOPOLOGY_OPTION_END); GNUNET_assert (NULL != op); shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL); } /** * Main function */ int main (int argc, char **argv) { uint64_t event_mask; result = GNUNET_SYSERR; event_mask = 0; event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); (void) GNUNET_TESTBED_test_run ("test_experimentation_clique_run", "test_experimentation_clique.conf", NUM_PEERS, event_mask, &controller_event_cb, NULL, &test_master, NULL); if (GNUNET_OK != result) return 1; return 0; } /* end of test_experimentation_clique_run.c */ gnunet-0.10.1/src/experimentation/Makefile.am0000644000175000017500000000416712320751520016055 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ experimentation.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif if HAVE_EXPERIMENTAL TEXT_EXP_CLIQUE = test_experimentation_clique_connect test_experimentation_clique_run endif check_PROGRAMS = \ $(TEXT_EXP_CLIQUE) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ $(TEXT_EXP_CLIQUE) endif libexec_PROGRAMS = \ gnunet-daemon-experimentation gnunet_daemon_experimentation_SOURCES = \ gnunet-daemon-experimentation.c gnunet-daemon-experimentation.h \ gnunet-daemon-experimentation_capabilities.c \ gnunet-daemon-experimentation_nodes.c \ gnunet-daemon-experimentation_scheduler.c \ gnunet-daemon-experimentation_experiments.c \ gnunet-daemon-experimentation_storage.c gnunet_daemon_experimentation_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la test_experimentation_clique_connect_SOURCES = \ test_experimentation_clique_connect.c test_experimentation_clique_connect_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la test_experimentation_clique_run_SOURCES = \ test_experimentation_clique_run.c test_experimentation_clique_run_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la #test_experimentation_clique_run_SOURCES = \ # test_experimentation_clique_run.c #test_experimentation_clique_run_LDADD = \ # $(top_builddir)/src/util/libgnunetutil.la \ # $(top_builddir)/src/statistics/libgnunetstatistics.la \ # $(top_builddir)/src/testbed/libgnunettestbed.la EXTRA_DIST = \ test_experimentation_clique.conf \ test_experiments.expgnunet-0.10.1/src/experimentation/test_experimentation_clique_connect.c0000644000175000017500000002742012226035634023515 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/experimentation/test_experimentation_clique_connect.c * @brief test case to connect experimentation daemons in a clique * @author Sree Harsha Totakura * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we want to start */ #define NUM_PEERS 2 #define NUM_ISSUER 1 #define NUM_EXPERIMENTS 2 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, (5 * NUM_PEERS) + 20) /** * Array of peers */ static struct GNUNET_TESTBED_Peer **peers; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * Shutdown task */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Testing result */ static int result; /** * Counter for counting overlay connections */ static unsigned int overlay_connects; /** * Information we track for a peer in the testbed. */ struct ExperimentationPeer { /** * Handle with testbed. */ struct GNUNET_TESTBED_Peer *daemon; /** * Testbed operation to connect to statistics service */ struct GNUNET_TESTBED_Operation *stat_op; /** * Handle to the statistics service */ struct GNUNET_STATISTICS_Handle *sh; unsigned int active_nodes; unsigned int requested_nodes; unsigned int inactive_nodes; unsigned int issuer; unsigned int experiments; }; struct ExperimentationPeer bp_slaves[NUM_PEERS]; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int peer; shutdown_task = GNUNET_SCHEDULER_NO_TASK; for (peer = 0; peer < NUM_PEERS; peer++) { if (NULL != bp_slaves[peer].stat_op) GNUNET_TESTBED_operation_done (bp_slaves[peer].stat_op); bp_slaves[peer].stat_op = NULL; } if (NULL != op) { GNUNET_TESTBED_operation_done (op); op = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_CONNECT: overlay_connects++; if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects) { result = GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers connected \n", NUM_PEERS); if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) { GNUNET_SCHEDULER_cancel (shutdown_task); } shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL); } break; case GNUNET_TESTBED_ET_OPERATION_FINISHED: break; default: GNUNET_break (0); result = GNUNET_SYSERR; GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } static void check_end () { static int last_active_value = 0; static int last_issuer_value = 0; static int last_experiments_value = 0; unsigned int peer; unsigned int total_active = 0; unsigned int total_inactive = 0; unsigned int total_requested = 0; unsigned int issuer = 0; unsigned int experiments = 0; for (peer = 0; peer < NUM_PEERS; peer++) { total_active += bp_slaves[peer].active_nodes; total_requested += bp_slaves[peer].requested_nodes; total_inactive += bp_slaves[peer].inactive_nodes; if (NUM_ISSUER == bp_slaves[peer].issuer) issuer ++; if (NUM_EXPERIMENTS == bp_slaves[peer].experiments) experiments ++; } if ((last_issuer_value < issuer) && (issuer == NUM_PEERS)) fprintf (stderr, "I"); last_issuer_value = issuer; if ((last_experiments_value < experiments) && (experiments == NUM_PEERS)) fprintf (stderr, "E"); last_experiments_value = experiments; if (last_active_value < total_active) fprintf (stderr, "."); last_active_value = total_active; if ((total_active == (NUM_PEERS * (NUM_PEERS -1))) && (total_requested == 0) && (total_inactive == 0) && (issuer == NUM_PEERS) && (experiments == NUM_PEERS)) { fprintf (stderr, "\n"); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All %u peers active in a clique\n", NUM_PEERS); GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } /** * Callback function to process statistic values. * * @param cls struct StatsContext * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int stat_iterator (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { struct ExperimentationPeer *peer = cls; if (0 == strcmp (name, "# nodes active")) { peer->active_nodes = value; } if (0 == strcmp (name, "# nodes inactive")) { peer->inactive_nodes = value; } if (0 == strcmp (name, "# nodes requested")) { peer->requested_nodes = value; } if (0 == strcmp (name, "# issuer")) { peer->issuer = value; } if (0 == strcmp (name, "# experiments")) { peer->experiments = value; } check_end (); return GNUNET_OK; } /** * Called after successfully opening a connection to a peer's statistics * service; we register statistics monitoring here. * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg ) { struct GNUNET_STATISTICS_Handle *sh = ca_result; struct ExperimentationPeer *peer = cls; if (NULL != emsg) { GNUNET_break (0); return; } GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, "experimentation", "# nodes active", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, "experimentation", "# nodes inactive", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, "experimentation", "# nodes requested", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, "experimentation", "# issuer", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, "experimentation", "# experiments", stat_iterator, peer)); } /** * Called to open a connection to the peer's statistics * * @param cls peer context * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * stat_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct ExperimentationPeer *peer = cls; peer->sh = GNUNET_STATISTICS_create ("experimentation", cfg); if (NULL == peer->sh) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create statistics \n"); return peer->sh; } /** * Called to disconnect from peer's statistics service * * @param cls peer context * @param op_result service handle returned from the connect adapter */ static void stat_disconnect_adapter (void *cls, void *op_result) { struct ExperimentationPeer *peer = cls; GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "experimentation", "# nodes active", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "experimentation", "# nodes inactive", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "experimentation", "# nodes requested", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "experimentation", "# issuer", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "experimentation", "# experiments", stat_iterator, peer)); GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); peer->sh = NULL; } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { unsigned int peer; GNUNET_assert (NULL == cls); GNUNET_assert (NUM_PEERS == num_peers); GNUNET_assert (NULL != peers_); for (peer = 0; peer < num_peers; peer++) { GNUNET_assert (NULL != peers_[peer]); /* Connect to peer's statistic service */ bp_slaves[peer].stat_op = GNUNET_TESTBED_service_connect (NULL, peers_[peer], "statistics", &stat_comp_cb, &bp_slaves[peer], &stat_connect_adapter, &stat_disconnect_adapter, &bp_slaves[peer]); } peers = peers_; overlay_connects = 0; op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, NULL, NULL, GNUNET_TESTBED_TOPOLOGY_CLIQUE, /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */ /* NUM_PEERS, */ GNUNET_TESTBED_TOPOLOGY_OPTION_END); GNUNET_assert (NULL != op); shutdown_task = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, do_shutdown, NULL); } /** * Main function */ int main (int argc, char **argv) { uint64_t event_mask; result = GNUNET_SYSERR; event_mask = 0; event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); (void) GNUNET_TESTBED_test_run ("test_experimentation_clique_connect", "test_experimentation_clique.conf", NUM_PEERS, event_mask, &controller_event_cb, NULL, &test_master, NULL); if (GNUNET_OK != result) return 1; return 0; } /* end of test_experimentation_clique_connect.c */ gnunet-0.10.1/src/experimentation/gnunet-daemon-experimentation_nodes.c0000644000175000017500000006776112272513460023345 00000000000000/* This file is part of GNUnet. (C) 2012-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file experimentation/gnunet-daemon-experimentation_nodes.c * @brief experimentation daemon: node management * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "gnunet-daemon-experimentation.h" #define FAST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Core handle */ static struct GNUNET_CORE_Handle *ch; /** * Peer's own identity */ static struct GNUNET_PeerIdentity me; /** * Nodes with a pending request */ static struct GNUNET_CONTAINER_MultiPeerMap *nodes_requested; /** * Active experimentation nodes */ static struct GNUNET_CONTAINER_MultiPeerMap *nodes_active; /** * Inactive experimentation nodes * To be excluded from future requests */ static struct GNUNET_CONTAINER_MultiPeerMap *nodes_inactive; struct NodeComCtx { struct NodeComCtx *prev; struct NodeComCtx *next; struct Node *n; struct Experiment *e; size_t size; GNUNET_CONNECTION_TransmitReadyNotify notify; void *notify_cls; }; /** * Update statistics * * @param m peermap to update values from */ static void update_stats (struct GNUNET_CONTAINER_MultiPeerMap *m) { GNUNET_assert (NULL != m); GNUNET_assert (NULL != GED_stats); if (m == nodes_active) { GNUNET_STATISTICS_set (GED_stats, "# nodes active", GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO); } else if (m == nodes_inactive) { GNUNET_STATISTICS_set (GED_stats, "# nodes inactive", GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO); } else if (m == nodes_requested) { GNUNET_STATISTICS_set (GED_stats, "# nodes requested", GNUNET_CONTAINER_multipeermap_size(m), GNUNET_NO); } else GNUNET_break (0); } /** * Clean up node * * @param cls the peermap to clean up * @param key key of the current node * @param value related node object * @return always #GNUNET_OK */ static int cleanup_node (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct Node *n; struct NodeComCtx *e_cur; struct NodeComCtx *e_next; struct GNUNET_CONTAINER_MultiPeerMap *cur = cls; n = value; if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task) { GNUNET_SCHEDULER_cancel (n->timeout_task); n->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != n->cth) { GNUNET_CORE_notify_transmit_ready_cancel (n->cth); n->cth = NULL; } e_next = n->e_req_head; while (NULL != (e_cur = e_next)) { e_next = e_cur->next; GNUNET_CONTAINER_DLL_remove (n->e_req_head, n->e_req_tail, e_cur); GNUNET_free (e_cur); } GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (cur, key, value)); GNUNET_free (value); return GNUNET_OK; } /** * Check if id passed is my id * * @param id the id to check * @return GNUNET_YES or GNUNET_NO */ static int is_me (const struct GNUNET_PeerIdentity *id) { if (0 == memcmp (&me, id, sizeof (me))) return GNUNET_YES; else return GNUNET_NO; } /** * Core startup callback * * @param cls unused * @param my_identity my id */ static void core_startup_handler (void *cls, const struct GNUNET_PeerIdentity *my_identity) { me = *my_identity; } static void schedule_transmisson (struct NodeComCtx *e_ctx); static size_t transmit_read_wrapper (void *cls, size_t bufsize, void *buf) { struct NodeComCtx *e_ctx = cls; struct NodeComCtx *next; size_t res = e_ctx->notify (e_ctx->notify_cls, bufsize, buf); e_ctx->n->cth = NULL; GNUNET_CONTAINER_DLL_remove (e_ctx->n->e_req_head, e_ctx->n->e_req_tail, e_ctx); next = e_ctx->n->e_req_head; GNUNET_free (e_ctx); if (NULL != next) { /* Schedule next message */ schedule_transmisson (next); } return res; } static void schedule_transmisson (struct NodeComCtx *e_ctx) { if (NULL != e_ctx->n->cth) return; e_ctx->n->cth = GNUNET_CORE_notify_transmit_ready (ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, FAST_TIMEOUT, &e_ctx->n->id, e_ctx->size, transmit_read_wrapper, e_ctx); if (NULL == e_ctx->n->cth) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Cannot send message to peer `%s' for experiment `%s'\n"), GNUNET_i2s(&e_ctx->n->id), e_ctx->e->name); GNUNET_free (e_ctx); } } /** * Remove experimentation request due to timeout * * @param cls the related node * @param tc scheduler's task context */ static void remove_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Node *n = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing request for peer %s due to timeout\n", GNUNET_i2s (&n->id)); if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_requested, &n->id)) { GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, &n->id, n)); update_stats (nodes_requested); GNUNET_CONTAINER_multipeermap_put (nodes_inactive, &n->id, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); update_stats (nodes_inactive); } n->timeout_task = GNUNET_SCHEDULER_NO_TASK; } static int append_public_key (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_CRYPTO_EddsaPublicKey **issuers = cls; struct Issuer *issuer = value; *issuers[0] = issuer->pubkey; *issuers = &((*issuers)[1]); return GNUNET_OK; } /** * Core's transmit notify callback to send request * * @param cls the related node * @param bufsize buffer size * @param buf the buffer to copy to * @return bytes passed */ static size_t send_experimentation_request_cb (void *cls, size_t bufsize, void *buf) { struct Node *n = cls; struct Experimentation_Request msg; unsigned int my_issuer_count = GNUNET_CONTAINER_multihashmap_size (valid_issuers); size_t msg_size = sizeof (msg); size_t ri_size = sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) * my_issuer_count; size_t total_size = msg_size + ri_size; struct GNUNET_CRYPTO_EddsaPublicKey *issuers; n->cth = NULL; if (NULL == buf) { /* client disconnected */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected\n"); if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task) GNUNET_SCHEDULER_cancel (n->timeout_task); GNUNET_SCHEDULER_add_now (&remove_request, n); return 0; } GNUNET_assert (bufsize >= total_size); msg.msg.size = htons (total_size); msg.msg.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_REQUEST); msg.capabilities = htonl (GSE_node_capabilities); msg.issuer_count = htonl (my_issuer_count); memcpy (buf, &msg, msg_size); issuers = (struct GNUNET_CRYPTO_EddsaPublicKey *) buf + msg_size; GNUNET_CONTAINER_multihashmap_iterate (valid_issuers, &append_public_key, &issuers); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Sending experimentation request to peer %s\n"), GNUNET_i2s (&n->id)); return total_size; } /** * Send request to peer to start add him to to the set of experimentation nodes * * @param peer the peer to send to */ static void send_experimentation_request (const struct GNUNET_PeerIdentity *peer) { struct Node *n; struct NodeComCtx *e_ctx; size_t size; size_t c_issuers; c_issuers = GNUNET_CONTAINER_multihashmap_size (valid_issuers); size = sizeof (struct Experimentation_Request) + c_issuers * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey); n = GNUNET_new (struct Node); n->id = *peer; n->timeout_task = GNUNET_SCHEDULER_add_delayed (EXP_RESPONSE_TIMEOUT, &remove_request, n); n->capabilities = NONE; e_ctx = GNUNET_new (struct NodeComCtx); e_ctx->n = n; e_ctx->e = NULL; e_ctx->size = size; e_ctx->notify = &send_experimentation_request_cb; e_ctx->notify_cls = n; GNUNET_CONTAINER_DLL_insert_tail(n->e_req_head, n->e_req_tail, e_ctx); schedule_transmisson (e_ctx); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (nodes_requested, peer, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); update_stats (nodes_requested); } /** * Core's transmit notify callback to send response * * @param cls the related node * @param bufsize buffer size * @param buf the buffer to copy to * @return bytes passed */ static size_t send_response_cb (void *cls, size_t bufsize, void *buf) { struct Node *n = cls; struct Experimentation_Response msg; size_t c_issuers = GNUNET_CONTAINER_multihashmap_size (valid_issuers); size_t ri_size = c_issuers * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey); size_t msg_size = sizeof (msg); size_t total_size = msg_size + ri_size; struct GNUNET_CRYPTO_EddsaPublicKey *issuers; n->cth = NULL; if (buf == NULL) { /* client disconnected */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected\n"); return 0; } GNUNET_assert (bufsize >= total_size); msg.msg.size = htons (total_size); msg.msg.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_RESPONSE); msg.capabilities = htonl (GSE_node_capabilities); msg.issuer_count = htonl (c_issuers); memcpy (buf, &msg, msg_size); issuers = (struct GNUNET_CRYPTO_EddsaPublicKey *) buf + msg_size; GNUNET_CONTAINER_multihashmap_iterate (valid_issuers, &append_public_key, &issuers); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending response to peer %s\n", GNUNET_i2s (&n->id)); return total_size; } static void get_experiments_cb (struct Node *n, struct Experiment *e) { static int counter = 0; if (NULL == e) return; /* Done */ /* Tell the scheduler to add a node with an experiment */ GED_scheduler_add (n, e, GNUNET_YES); counter ++; } struct Node * get_node (const struct GNUNET_PeerIdentity *id) { struct Node * res; struct Node * tmp; res = NULL; tmp = NULL; tmp = GNUNET_CONTAINER_multipeermap_get (nodes_active, id); if (res == NULL) res = tmp; tmp = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, id); if (res == NULL) res = tmp; else GNUNET_break (0); /* Multiple instances */ tmp = GNUNET_CONTAINER_multipeermap_get (nodes_requested, id); if (res == NULL) res = tmp; else GNUNET_break (0); /* Multiple instances */ return res; } /** * Set a specific node as active * * @param n the node */ static void node_make_active (struct Node *n) { int c1; GNUNET_CONTAINER_multipeermap_put (nodes_active, &n->id, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); update_stats (nodes_active); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Added peer `%s' as active node\n"), GNUNET_i2s (&n->id)); /* Request experiments for this node to start them */ for (c1 = 0; c1 < n->issuer_count; c1++) { GED_experiments_get (n, &n->issuer_id[c1], &get_experiments_cb); } } /** * Handle a request and send a response * * @param peer the source * @param message the message */ static void handle_request (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct Node *n; struct NodeComCtx *e_ctx; const struct Experimentation_Request *rm = (const struct Experimentation_Request *) message; const struct GNUNET_CRYPTO_EddsaPublicKey *rmi = (const struct GNUNET_CRYPTO_EddsaPublicKey *) &rm[1]; unsigned int my_issuer_count = GNUNET_CONTAINER_multihashmap_size (valid_issuers); int c1; int c2; uint32_t ic; uint32_t ic_accepted; int make_active; if (ntohs (message->size) < sizeof (struct Experimentation_Request)) { GNUNET_break (0); return; } ic = ntohl (rm->issuer_count); if (ntohs (message->size) != sizeof (struct Experimentation_Request) + ic * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) { GNUNET_break (0); return; } make_active = GNUNET_NO; if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer))) { /* Nothing to do */ } else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer))) { GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, peer, n)); if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task) { GNUNET_SCHEDULER_cancel (n->timeout_task); n->timeout_task = GNUNET_SCHEDULER_NO_TASK; } update_stats (nodes_requested); make_active = GNUNET_YES; } else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer))) { GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_inactive, peer, n)); update_stats (nodes_inactive); make_active = GNUNET_YES; } else { /* Create new node */ n = GNUNET_new (struct Node); n->id = *peer; n->capabilities = NONE; make_active = GNUNET_YES; } /* Update node */ n->capabilities = ntohl (rm->capabilities); /* Filter accepted issuer */ ic_accepted = 0; for (c1 = 0; c1 < ic; c1++) { if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1])) ic_accepted ++; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request from peer `%s' with %u issuers, we accepted %u issuer \n", GNUNET_i2s (peer), ic, ic_accepted); GNUNET_free_non_null (n->issuer_id); n->issuer_id = GNUNET_malloc (ic_accepted * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); c2 = 0; for (c1 = 0; c1 < ic; c1++) { if (GNUNET_YES == GED_experiments_issuer_accepted (&rmi[c1])) { n->issuer_id[c2] = rmi[c1]; c2 ++; } } n->issuer_count = ic_accepted; if (GNUNET_YES == make_active) node_make_active (n); /* Send response */ e_ctx = GNUNET_new (struct NodeComCtx); e_ctx->n = n; e_ctx->e = NULL; e_ctx->size = sizeof (struct Experimentation_Response) + my_issuer_count * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey); e_ctx->notify = &send_response_cb; e_ctx->notify_cls = n; GNUNET_CONTAINER_DLL_insert_tail(n->e_req_head, n->e_req_tail, e_ctx); schedule_transmisson (e_ctx); } /** * Handle a response * * @param peer the source * @param message the message */ static void handle_response (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct Node *n; const struct Experimentation_Response *rm = (const struct Experimentation_Response *) message; const struct GNUNET_CRYPTO_EddsaPublicKey *rmi = (const struct GNUNET_CRYPTO_EddsaPublicKey *) &rm[1]; uint32_t ic; uint32_t ic_accepted; int make_active; unsigned int c1; unsigned int c2; if (ntohs (message->size) < sizeof (struct Experimentation_Response)) { GNUNET_break (0); return; } ic = ntohl (rm->issuer_count); if (ntohs (message->size) != sizeof (struct Experimentation_Response) + ic * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) { GNUNET_break (0); return; } make_active = GNUNET_NO; if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n", "RESPONSE", "active", GNUNET_i2s (peer)); } else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n", "RESPONSE", "requested", GNUNET_i2s (peer)); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (nodes_requested, peer, n)); if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task) { GNUNET_SCHEDULER_cancel (n->timeout_task); n->timeout_task = GNUNET_SCHEDULER_NO_TASK; } update_stats (nodes_requested); make_active = GNUNET_YES; } else if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from peer `%s'\n", "RESPONSE", "inactive", GNUNET_i2s (peer)); GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_remove (nodes_inactive, peer, n)); update_stats (nodes_inactive); make_active = GNUNET_YES; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s from %s peer `%s'\n", "RESPONSE", "unknown", GNUNET_i2s (peer)); return; } /* Update */ n->capabilities = ntohl (rm->capabilities); /* Filter accepted issuer */ ic_accepted = 0; for (c1 = 0; c1 < ic; c1++) { if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1])) ic_accepted ++; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Response from peer `%s' with %u issuers, we accepted %u issuer \n", GNUNET_i2s (peer), ic, ic_accepted); GNUNET_free_non_null (n->issuer_id); n->issuer_id = GNUNET_malloc (ic_accepted * sizeof (struct GNUNET_PeerIdentity)); c2 = 0; for (c1 = 0; c1 < ic; c1++) { if (GNUNET_YES == GED_experiments_issuer_accepted(&rmi[c1])) { n->issuer_id[c2] = rmi[c1]; c2 ++; } } n->issuer_count = ic_accepted; if (GNUNET_YES == make_active) node_make_active (n); } /** * Handle a response * * @param peer the source * @param message the message */ static void handle_start (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { uint16_t size; uint32_t name_len; const struct GED_start_message *msg; const char *name; struct Node *n; struct Experiment *e; if (NULL == peer) { GNUNET_break (0); return; } if (NULL == message) { GNUNET_break (0); return; } size = ntohs (message->size); if (size < sizeof (struct GED_start_message)) { GNUNET_break (0); return; } msg = (const struct GED_start_message *) message; name_len = ntohl (msg->len_name); if (size != sizeof (struct GED_start_message) + name_len) { GNUNET_break (0); return; } n = get_node (peer); if (NULL == n) { GNUNET_break (0); return; } name = (const char *) &msg[1]; if (name[name_len-1] != '\0') { GNUNET_break (0); return; } if (name_len != strlen (name) + 1) { GNUNET_break (0); return; } e = GED_experiments_find (&msg->issuer, name, GNUNET_TIME_absolute_ntoh(msg->version_nbo)); if (NULL == e) { GNUNET_break (0); return; } GED_scheduler_handle_start (n, e); } /** * Handle a response * * @param peer the source * @param message the message */ static void handle_start_ack (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { uint16_t size; uint32_t name_len; const struct GED_start_ack_message *msg; const char *name; struct Node *n; struct Experiment *e; if (NULL == peer) { GNUNET_break (0); return; } if (NULL == message) { GNUNET_break (0); return; } size = ntohs (message->size); if (size < sizeof (struct GED_start_ack_message)) { GNUNET_break (0); return; } msg = (const struct GED_start_ack_message *) message; name_len = ntohl (msg->len_name); if (size != sizeof (struct GED_start_message) + name_len) { GNUNET_break (0); return; } n = get_node (peer); if (NULL == n) { GNUNET_break (0); return; } name = (const char *) &msg[1]; if (name[name_len-1] != '\0') { GNUNET_break (0); return; } if (name_len != strlen (name) + 1) { GNUNET_break (0); return; } e = GED_experiments_find (&msg->issuer, name, GNUNET_TIME_absolute_ntoh(msg->version_nbo)); if (NULL == e) { GNUNET_break (0); return; } GED_scheduler_handle_start_ack (n, e); } /** * Handle a response * * @param peer the source * @param message the message */ static void handle_stop (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { uint16_t size; uint32_t name_len; const struct GED_stop_message *msg; const char *name; struct Node *n; struct Experiment *e; if (NULL == peer) { GNUNET_break (0); return; } if (NULL == message) { GNUNET_break (0); return; } size = ntohs (message->size); if (size < sizeof (struct GED_stop_message)) { GNUNET_break (0); return; } msg = (const struct GED_stop_message *) message; name_len = ntohl (msg->len_name); if (size != sizeof (struct GED_start_message) + name_len) { GNUNET_break (0); return; } n = get_node (peer); if (NULL == n) { GNUNET_break (0); return; } name = (const char *) &msg[1]; if (name[name_len-1] != '\0') { GNUNET_break (0); return; } if (name_len != strlen (name) + 1) { GNUNET_break (0); return; } e = GED_experiments_find (&msg->issuer, name, GNUNET_TIME_absolute_ntoh(msg->version_nbo)); if (NULL == e) { GNUNET_break (0); return; } GED_scheduler_handle_stop (n, e); } /** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void core_connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { if (GNUNET_YES == is_me(peer)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Connected to peer %s\n"), GNUNET_i2s (peer)); if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_requested, peer)) return; /* We already sent a request */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_active, peer)) return; /* This peer is known as active */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (nodes_inactive, peer)) return; /* This peer is known as inactive */ send_experimentation_request (peer); } /** * Method called whenever a given peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void core_disconnect_handler (void *cls, const struct GNUNET_PeerIdentity * peer) { struct Node *n; if (GNUNET_YES == is_me(peer)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Disconnected from peer %s\n"), GNUNET_i2s (peer)); if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_requested, peer))) cleanup_node (nodes_requested, peer, n); if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_active, peer))) cleanup_node (nodes_active, peer, n); if (NULL != (n = GNUNET_CONTAINER_multipeermap_get (nodes_inactive, peer))) cleanup_node (nodes_inactive, peer, n); } /** * Handle a request and send a response * * @param cls unused * @param other the sender * @param message the message * @return GNUNET_OK to keep connection, GNUNET_SYSERR on error */ static int core_receive_handler (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { if (ntohs (message->size) < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); return GNUNET_SYSERR; } switch (ntohs (message->type)) { case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_REQUEST: handle_request (other, message); break; case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_RESPONSE: handle_response (other, message); break; case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START: handle_start (other, message); break; case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START_ACK: handle_start_ack (other, message); break; case GNUNET_MESSAGE_TYPE_EXPERIMENTATION_STOP: handle_stop (other, message); break; default: break; } return GNUNET_OK; } static size_t node_experiment_start_cb (void *cls, size_t bufsize, void *buf) { struct NodeComCtx *e_ctx = cls; struct GED_start_message *msg; size_t name_len; size_t size; if (NULL == buf) return 0; name_len = strlen(e_ctx->e->name) + 1; size = sizeof (struct GED_start_message) + name_len; msg = GNUNET_malloc (size); msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START); msg->issuer = e_ctx->e->issuer; msg->version_nbo = GNUNET_TIME_absolute_hton(e_ctx->e->version); msg->len_name = htonl (name_len); memcpy (&msg[1], e_ctx->e->name, name_len); memcpy (buf, msg, size); GNUNET_free (msg); return size; } static size_t node_experiment_start_ack_cb (void *cls, size_t bufsize, void *buf) { struct NodeComCtx *e_ctx = cls; struct GED_start_ack_message *msg; size_t name_len; size_t size; if (NULL == buf) return 0; name_len = strlen(e_ctx->e->name) + 1; size = sizeof (struct GED_start_ack_message) + name_len; msg = GNUNET_malloc (size); msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START_ACK); msg->issuer = e_ctx->e->issuer; msg->version_nbo = GNUNET_TIME_absolute_hton(e_ctx->e->version); msg->len_name = htonl (name_len); memcpy (&msg[1], e_ctx->e->name, name_len); memcpy (buf, msg, size); GNUNET_free (msg); return size; } /** * Confirm a experiment START with a node * * @return GNUNET_NO if core was busy with sending, GNUNET_OK otherwise */ int GED_nodes_send_start_ack (struct Node *n, struct Experiment *e) { struct NodeComCtx *e_ctx; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s for experiment request to peer `%s' for experiment `%s'\n", "START_ACK" ,GNUNET_i2s(&n->id), e->name); e_ctx = GNUNET_new (struct NodeComCtx); e_ctx->n = n; e_ctx->e = e; e_ctx->size = sizeof (struct GED_start_ack_message) + strlen (e->name) + 1; e_ctx->notify = &node_experiment_start_ack_cb; e_ctx->notify_cls = e_ctx; GNUNET_CONTAINER_DLL_insert_tail (n->e_req_head, n->e_req_tail, e_ctx); schedule_transmisson (e_ctx); return GNUNET_OK; } /** * Request a experiment to start with a node * * @return GNUNET_NO if core was busy with sending, GNUNET_OK otherwise */ int GED_nodes_send_start (struct Node *n, struct Experiment *e) { struct NodeComCtx *e_ctx; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s for experiment request to peer `%s' for experiment `%s'\n", "START", GNUNET_i2s(&n->id), e->name); e_ctx = GNUNET_new (struct NodeComCtx); e_ctx->n = n; e_ctx->e = e; e_ctx->size = sizeof (struct GED_start_message) + strlen (e->name) + 1; e_ctx->notify = &node_experiment_start_cb; e_ctx->notify_cls = e_ctx; GNUNET_CONTAINER_DLL_insert_tail (n->e_req_head, n->e_req_tail, e_ctx); schedule_transmisson (e_ctx); return GNUNET_OK; } /** * Start the nodes management */ void GED_nodes_start () { /* Connecting to core service to find partners */ ch = GNUNET_CORE_connect (GED_cfg, NULL, &core_startup_handler, &core_connect_handler, &core_disconnect_handler, &core_receive_handler, GNUNET_NO, NULL, GNUNET_NO, NULL); if (NULL == ch) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Failed to connect to CORE service!\n")); return; } nodes_requested = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); nodes_active = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); nodes_inactive = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); } /** * Stop the nodes management */ void GED_nodes_stop () { if (NULL != ch) { GNUNET_CORE_disconnect (ch); ch = NULL; } if (NULL != nodes_requested) { GNUNET_CONTAINER_multipeermap_iterate (nodes_requested, &cleanup_node, nodes_requested); update_stats (nodes_requested); GNUNET_CONTAINER_multipeermap_destroy (nodes_requested); nodes_requested = NULL; } if (NULL != nodes_active) { GNUNET_CONTAINER_multipeermap_iterate (nodes_active, &cleanup_node, nodes_active); update_stats (nodes_active); GNUNET_CONTAINER_multipeermap_destroy (nodes_active); nodes_active = NULL; } if (NULL != nodes_inactive) { GNUNET_CONTAINER_multipeermap_iterate (nodes_inactive, &cleanup_node, nodes_inactive); update_stats (nodes_inactive); GNUNET_CONTAINER_multipeermap_destroy (nodes_inactive); nodes_inactive = NULL; } } /* end of gnunet-daemon-experimentation_nodes.c */ gnunet-0.10.1/src/experimentation/gnunet-daemon-experimentation.c0000644000175000017500000000647712225777501022160 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file experimentation/gnunet-daemon-experimentation.c * @brief experimentation daemon * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "gnunet-daemon-experimentation.h" /** * Statistics handle shared between components */ struct GNUNET_STATISTICS_Handle *GED_stats; /** * Configuration handle shared between components */ struct GNUNET_CONFIGURATION_Handle *GED_cfg; /** * Task run during shutdown to stop all submodules of the experimentation daemon. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Experimentation daemon shutting down ...\n")); GED_scheduler_stop (); GED_nodes_stop (); GED_experiments_stop (); GED_storage_stop (); GED_capabilities_stop (); } /** * Function starting all submodules of the experimentation daemon. * * @param cls always NULL * @param args temaining command line arguments * @param cfgfile configuration file used * @param cfg configuration handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Experimentation daemon starting ...\n")); GED_cfg = (struct GNUNET_CONFIGURATION_Handle *) cfg; GED_stats = GNUNET_STATISTICS_create ("experimentation", cfg); if (NULL == GED_stats) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to create statistics!\n")); return; } GED_capabilities_start (); GED_storage_start (); if (GNUNET_SYSERR == GED_experiments_start ()) { GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); return; } GED_nodes_start (); GED_scheduler_start (); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for the experimentation daemon. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "experimentation", _("GNUnet experimentation daemon"), options, &run, NULL)) ? 0 : 1; } /* end of gnunet-daemon-experimentation.c */ gnunet-0.10.1/src/experimentation/gnunet-daemon-experimentation_capabilities.c0000644000175000017500000001065012225777501024655 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file experimentation/gnunet-daemon-experimentation_capabilities.c * @brief experimentation daemon: capabilities management * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "gnunet-daemon-experimentation.h" /** * Capability value shared between components */ uint32_t GSE_node_capabilities; /** * Capabilities defined at the moment */ #define GNUNET_EXPERIMENTATION_capabilities_count 11 /** * Capabilities a node has or an experiment requires string */ #define GNUNET_EXPERIMENTATION_capabilities_string {"NONE", "PLUGIN_TCP", "PLUGIN_UDP", "PLUGIN_UNIX", "PLUGIN_HTTP_CLIENT", "PLUGIN_HTTP_SERVER", "PLUGIN_HTTPS_CLIENT", "PLUGIN_HTTPS_SERVER", "PLUGIN_WLAN", "HAVE_IPV6", "BEHIND_NAT"} /** * Print a single capability value * * @param cap capability value * @return the string to print */ const char * GED_capability_to_str (uint32_t cap) { char * capstr[] = GNUNET_EXPERIMENTATION_capabilities_string; unsigned index = 0; uint32_t test = 0; if (0 == cap) return capstr[0]; index = (log(cap) / log (2)) + 1; test = 1 << (index - 1); if (test != cap) return "UNDEFINED"; if (index < GNUNET_EXPERIMENTATION_capabilities_count) return capstr[index]; else return "UNDEFINED"; } /** * Are the capabilities provided? * * @param have bitstring containing the provided capabilities * @param desired bitstring containing the desired capabilities\ * @return GNUNET_YES or GNUNET_NO */ int GED_capabilities_have (uint32_t have, uint32_t desired) { if (desired == (desired & have)) return GNUNET_YES; else return GNUNET_NO; } /** * Start the detecting capabilities */ void GED_capabilities_start () { char *plugins; char *pos; unsigned int c1; uint32_t index; GSE_node_capabilities = NONE; /* Plugins configured */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (GED_cfg, "TRANSPORT", "PLUGINS", &plugins)) { for (pos = strtok (plugins, " "); pos != NULL; pos = strtok (NULL, " ")) { if (0 == strcmp (pos, "tcp")) GSE_node_capabilities |= PLUGIN_TCP; else if (0 == strcmp (pos, "udp")) GSE_node_capabilities |= PLUGIN_UDP; else if (0 == strcmp (pos, "unix")) GSE_node_capabilities |= PLUGIN_UNIX; else if (0 == strcmp (pos, "http_client")) GSE_node_capabilities |= PLUGIN_HTTP_CLIENT; else if (0 == strcmp (pos, "http_server")) GSE_node_capabilities |= PLUGIN_HTTP_SERVER; else if (0 == strcmp (pos, "https_client")) GSE_node_capabilities |= PLUGIN_HTTP_CLIENT; else if (0 == strcmp (pos, "https_server")) GSE_node_capabilities |= PLUGIN_HTTPS_SERVER; else if (0 == strcmp (pos, "wlan")) GSE_node_capabilities |= PLUGIN_WLAN; } GNUNET_free (plugins); } /* IPv6 enabled * FIXE: just having it not enabled is not really sufficient */ if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno (GED_cfg, "NAT", "DISABLEV6")) GSE_node_capabilities |= HAVE_IPV6; /* Behind NAT */ if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (GED_cfg, "NAT", "BEHIND_NAT")) GSE_node_capabilities |= BEHIND_NAT; for (c1 = 0 ; c1 < 32; c1++) { index = 1; index = index << c1; if (GNUNET_YES == GED_capabilities_have (GSE_node_capabilities, index)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "We have `%s'\n", GED_capability_to_str(index)); } } } /** * Stop the detecting capabilities */ void GED_capabilities_stop () { } /* end of gnunet-daemon-experimentation_capabilities.c */ gnunet-0.10.1/src/experimentation/test_experimentation_clique.conf0000644000175000017500000000227212225230043022473 00000000000000[testbed] AUTOSTART = NO PORT = 12113 ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost NEIGHBOUR_LIMIT = 100 TOPOLOGY = RANDOM #PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args [fs] AUTOSTART = NO [resolver] AUTOSTART = NO [mesh] AUTOSTART = NO [dht] AUTOSTART = YES DISABLE_TRY_CONNECT = NO [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = udp ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 PORT = 12365 [experimentation] #PREFIX = valgrind --leak-check=full ISSUERS = TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG EXPERIMENTS = test_experiments.exp [ats] WAN_QUOTA_OUT = 3932160 WAN_QUOTA_IN = 3932160 [core] PORT = 12092 AUTOSTART = YES USE_EPHEMERAL_KEYS = NO [arm] DEFAULTSERVICES = core transport experimentation dht PORT = 12366 [transport-udp] TIMEOUT = 300 s PORT = 12368 [PATHS] GNUNET_TEST_HOME = /tmp/test-experimentation/ [dns] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART = NO [nat] RETURN_LOCAL_ADDRESSES = YES [gns-helper-service-w32] AUTOSTART = NO [consensus] AUTOSTART = NO [gns] AUTOSTART = NO [statistics] AUTOSTART = YES [peerinfo] NO_IO = YES gnunet-0.10.1/src/experimentation/gnunet-daemon-experimentation_storage.c0000644000175000017500000000253612225777501023674 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file experimentation/gnunet-daemon-experimentation_storage.c * @brief experimentation daemon: store results * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "gnunet-daemon-experimentation.h" /** * Start the storage component */ void GED_storage_start () { } /** * Stop the storage component */ void GED_storage_stop () { } /* end of gnunet-daemon-experimentation_storage.c */ gnunet-0.10.1/src/experimentation/gnunet-daemon-experimentation_experiments.c0000644000175000017500000003233012225777501024566 00000000000000/* This file is part of GNUnet. (C) 2012,2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file experimentation/gnunet-daemon-experimentation_experiments.c * @brief experimentation daemon: experiment management * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "gnunet-daemon-experimentation.h" /** * Hashmap containing valid experiment issuers. */ struct GNUNET_CONTAINER_MultiHashMap *valid_issuers; /** * Hashmap containing valid experiments */ static struct GNUNET_CONTAINER_MultiHashMap *experiments; /** * Verify experiment signature * * @param i issuer * @param e experiment * @return #GNUNET_OK or #GNUNET_SYSERR */ static int experiment_verify (struct Issuer *i, struct Experiment *e) { GNUNET_assert (NULL != i); GNUNET_assert (NULL != e); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Verification: to be implemented\n"); return GNUNET_OK; } static int free_experiment (void *cls, const struct GNUNET_HashCode * key, void *value) { struct Experiment *e = value; GNUNET_break (0 == GNUNET_CONTAINER_multihashmap_remove (experiments, key, value)); GNUNET_free_non_null (e->description); GNUNET_free_non_null (e->name); GNUNET_free (e); return GNUNET_OK; } /** * Free issuer element * * @param cls unused * @param key the key * @param value the issuer element to free * @return GNUNET_OK to continue */ static int free_issuer (void *cls, const struct GNUNET_HashCode * key, void *value) { struct Issuer *i = value; GNUNET_break (0 == GNUNET_CONTAINER_multihashmap_remove (valid_issuers, key, i)); GNUNET_free (i); return GNUNET_OK; } /** * Is peer a valid issuer * * @return #GNUNET_YES or #GNUNET_NO */ int GED_experiments_issuer_accepted (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer_id) { struct GNUNET_HashCode hash; GNUNET_CRYPTO_hash (issuer_id, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), &hash); if (GNUNET_CONTAINER_multihashmap_contains (valid_issuers, &hash)) return GNUNET_YES; return GNUNET_NO; } /** * Get the key under which the given experiment is stored in the * experiment map. */ static void get_experiment_key (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer, const char *name, const struct GNUNET_TIME_Absolute version, struct GNUNET_HashCode *key) { GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_kdf (key, sizeof (struct GNUNET_HashCode), issuer, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), name, strlen (name), &version, sizeof (version), NULL, 0)); } /** * Find an experiment based on issuer name and version * * @param issuer the issuer * @param name experiment name * @param version experiment version * @return the experiment or NULL if not found */ struct Experiment * GED_experiments_find (const struct GNUNET_CRYPTO_EddsaPublicKey *issuer, const char *name, const struct GNUNET_TIME_Absolute version) { struct GNUNET_HashCode hc; get_experiment_key (issuer, name, version, &hc); return GNUNET_CONTAINER_multihashmap_get (experiments, &hc); } struct GetCtx { struct Node *n; GNUNET_EXPERIMENTATION_experiments_get_cb get_cb; struct GNUNET_CRYPTO_EddsaPublicKey *issuer; }; static int get_it (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GetCtx *get_ctx = cls; struct Experiment *e = value; if (0 == memcmp (&e->issuer, get_ctx->issuer, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) get_ctx->get_cb (get_ctx->n, e); return GNUNET_OK; } void GED_experiments_get (struct Node *n, struct GNUNET_CRYPTO_EddsaPublicKey *issuer, GNUNET_EXPERIMENTATION_experiments_get_cb get_cb) { struct GetCtx get_ctx; GNUNET_assert (NULL != n); GNUNET_assert (NULL != experiments); GNUNET_assert (NULL != get_cb); get_ctx.n = n; get_ctx.get_cb = get_cb; get_ctx.issuer = issuer; GNUNET_CONTAINER_multihashmap_iterate (experiments, &get_it, &get_ctx); get_cb (n, NULL); // FIXME: ugly, end is easily signalled as we return: synchronous API! } /** * Add a new experiment */ int GNUNET_EXPERIMENTATION_experiments_add (struct Issuer *i, const char *name, const struct GNUNET_CRYPTO_EddsaPublicKey *issuer_id, struct GNUNET_TIME_Absolute version, char *description, uint32_t required_capabilities, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative frequency, struct GNUNET_TIME_Relative duration, struct GNUNET_TIME_Absolute stop) { struct Experiment *e; struct GNUNET_HashCode hc; e = GNUNET_new (struct Experiment); e->name = GNUNET_strdup (name); e->issuer = *issuer_id; e->version = version; if (NULL != description) e->description = GNUNET_strdup (description); e->required_capabilities = required_capabilities; e->start = start; e->frequency = frequency; e->duration = duration; e->stop = stop; /* verify experiment */ if (GNUNET_SYSERR == experiment_verify (i, e)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Experiment `%s': Experiment signature is invalid\n"), name); GNUNET_free (e); GNUNET_free_non_null (e->name); GNUNET_free_non_null (e->description); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Adding experiment `%s' running from `%s' to `%s' every %llu sec. for %llu sec. \n"), e->name, GNUNET_STRINGS_absolute_time_to_string (start), GNUNET_STRINGS_absolute_time_to_string (stop), (long long unsigned int) frequency.rel_value_us / 1000000LL, (long long unsigned int) duration.rel_value_us / 1000000LL); get_experiment_key (&e->issuer, name, version, &hc); GNUNET_CONTAINER_multihashmap_put (experiments, &hc, e, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GNUNET_STATISTICS_set (GED_stats, "# experiments", GNUNET_CONTAINER_multihashmap_size (experiments), GNUNET_NO); return GNUNET_OK; } /** * Parse a configuration section containing experiments * * @param cls configuration handle * @param name section name */ static void exp_file_iterator (void *cls, const char *name) { struct GNUNET_CONFIGURATION_Handle *exp = cls; struct Issuer *i; char *val; unsigned long long number; /* Experiment values */ struct GNUNET_CRYPTO_EddsaPublicKey issuer; struct GNUNET_TIME_Absolute version; char *description; uint32_t required_capabilities; struct GNUNET_TIME_Absolute start ; struct GNUNET_TIME_Absolute stop; struct GNUNET_TIME_Relative frequency; struct GNUNET_TIME_Relative duration; struct GNUNET_HashCode phash; /* Mandatory fields */ /* Issuer */ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (exp, name, "ISSUER", &val)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Experiment `%s': Issuer missing\n"), name); return; } if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_public_key_from_string (val, strlen (val), &issuer)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Experiment `%s': Issuer invalid\n"), name); GNUNET_free (val); return; } GNUNET_CRYPTO_hash (&issuer, sizeof (issuer), &phash); if (NULL == (i = GNUNET_CONTAINER_multihashmap_get (valid_issuers, &phash))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Experiment `%s': Issuer not accepted!\n"), name); GNUNET_free (val); return; } GNUNET_free (val); /* Version */ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "VERSION", &number)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Experiment `%s': Version missing or invalid \n"), name); return; } version.abs_value_us = number; // FIXME: what is this supposed to be? Version != TIME!??? /* Required capabilities */ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "CAPABILITIES", &number)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Experiment `%s': Required capabilities missing \n"), name); return; } if (number > UINT32_MAX) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Experiment `%s': Required capabilities invalid \n"), name); return; } required_capabilities = number; /* Optional fields */ /* Description */ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (exp, name, "DESCRIPTION", &description)) description = NULL; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "START", (long long unsigned int *) &start.abs_value_us)) start = GNUNET_TIME_UNIT_ZERO_ABS; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (exp, name, "FREQUENCY", &frequency)) frequency = EXP_DEFAULT_EXP_FREQ; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (exp, name, "DURATION", &duration)) duration = EXP_DEFAULT_EXP_DUR; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (exp, name, "STOP", (long long unsigned int *)&stop.abs_value_us)) stop = GNUNET_TIME_UNIT_FOREVER_ABS; GNUNET_EXPERIMENTATION_experiments_add (i, name, &issuer, version, description, required_capabilities, start, frequency, duration, stop); GNUNET_free_non_null (description); } /** * Load experiments from file * * @param file source file */ static void load_file (const char * file) { struct GNUNET_CONFIGURATION_Handle *exp = GNUNET_CONFIGURATION_create(); if (NULL == exp) return; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_parse (exp, file)) { GNUNET_CONFIGURATION_destroy (exp); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse file `%s'\n"), file); return; } GNUNET_CONFIGURATION_iterate_sections (exp, &exp_file_iterator, exp); GNUNET_CONFIGURATION_destroy (exp); } /** * Start experiments management */ int GED_experiments_start () { struct Issuer *i; char *issuers; char *file; char *pos; struct GNUNET_CRYPTO_EddsaPublicKey issuer_ID; struct GNUNET_HashCode hash; /* Load valid issuer */ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (GED_cfg, "EXPERIMENTATION", "ISSUERS", &issuers)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No valid experiment issuers configured! Set value to public keys of issuers! Exiting.\n")); GED_experiments_stop (); return GNUNET_SYSERR; } valid_issuers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); for (pos = strtok (issuers, " "); pos != NULL; pos = strtok (NULL, " ")) { if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_public_key_from_string (pos, strlen (pos), &issuer_ID)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "EXPERIMENTATION", "ISSUERS", _("Invalid value for public key\n")); GED_experiments_stop (); GNUNET_free (issuers); return GNUNET_SYSERR; } i = GNUNET_new (struct Issuer); i->pubkey = issuer_ID; GNUNET_CRYPTO_hash( &issuer_ID, sizeof (issuer_ID), &hash); GNUNET_CONTAINER_multihashmap_put (valid_issuers, &hash, i, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); } GNUNET_free (issuers); if (0 == GNUNET_CONTAINER_multihashmap_size (valid_issuers)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No valid experiment issuers configured! Set value to public keys of issuers! Exiting.\n")); GED_experiments_stop (); return GNUNET_SYSERR; } GNUNET_STATISTICS_set (GED_stats, "# issuer", GNUNET_CONTAINER_multihashmap_size (valid_issuers), GNUNET_NO); experiments = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO); /* Load experiments from file */ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (GED_cfg, "EXPERIMENTATION", "EXPERIMENTS", &file)) return GNUNET_OK; if (GNUNET_YES != GNUNET_DISK_file_test (file)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot read experiments file `%s'\n"), file); GNUNET_free (file); return GNUNET_OK; } load_file (file); GNUNET_free (file); return GNUNET_OK; } /** * Stop experiments management */ void GED_experiments_stop () { if (NULL != valid_issuers) { GNUNET_CONTAINER_multihashmap_iterate (valid_issuers, &free_issuer, NULL); GNUNET_CONTAINER_multihashmap_destroy (valid_issuers); } valid_issuers = NULL; if (NULL != experiments) { GNUNET_CONTAINER_multihashmap_iterate (experiments, &free_experiment, NULL); GNUNET_CONTAINER_multihashmap_destroy (experiments); } experiments = NULL; } /* end of gnunet-daemon-experimentation_experiments.c */ gnunet-0.10.1/src/experimentation/gnunet-daemon-experimentation_scheduler.c0000644000175000017500000003222612255010511024165 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file experimentation/gnunet-daemon-experimentation_scheduler.c * @brief experimentation daemon: execute experiments * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "gnunet-daemon-experimentation.h" /** * An experiment is added during startup as not running NOT_RUNNING * * The scheduler then decides to schedule it and sends a request to the * remote peer, if core cannot send since it is busy we wait for some time * and change state to BUSY, if we can send we change to REQUESTED and wait * for remote peers ACK. * * When we receive an ACK we change to STARTED and when scheduler decides that * the experiment is finished we change to STOPPED. */ enum ExperimentState { /* Experiment is added and waiting to be executed */ NOT_RUNNING, /* Cannot send request to remote peer, core is busy*/ BUSY, /* We requested experiment and wait for remote peer to ACK */ REQUESTED, /* Experiment is running */ STARTED, /* Experiment is done */ STOPPED }; struct ScheduledExperiment { struct ScheduledExperiment *next; struct ScheduledExperiment *prev; struct Experiment *e; struct Node *n; int state; int outbound; GNUNET_SCHEDULER_TaskIdentifier task; }; struct ScheduledExperiment *waiting_in_head; struct ScheduledExperiment *waiting_in_tail; struct ScheduledExperiment *running_in_head; struct ScheduledExperiment *running_in_tail; struct ScheduledExperiment *waiting_out_head; struct ScheduledExperiment *waiting_out_tail; struct ScheduledExperiment *running_out_head; struct ScheduledExperiment *running_out_tail; static unsigned int experiments_scheduled; static unsigned int experiments_outbound_running; static unsigned int experiments_inbound_running; static unsigned int experiments_requested; static struct ScheduledExperiment * find_experiment (struct ScheduledExperiment *head, struct ScheduledExperiment *tail, struct Node *n, struct Experiment *e, int outbound) { struct ScheduledExperiment *cur; for (cur = head; NULL != cur; cur = cur->next) { if ((cur->n == n) && (cur->e == e) && (cur->outbound == outbound)) /* Node and experiment are equal */ break; } return cur; } static void request_timeout (void *cls,const struct GNUNET_SCHEDULER_TaskContext* tc) { struct ScheduledExperiment *se = cls; se->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Peer `%s' did not respond to request for experiment `%s'\n"), GNUNET_i2s (&se->n->id), se->e->name); GNUNET_CONTAINER_DLL_remove (waiting_out_head, waiting_out_tail, se); GNUNET_free (se); /* Remove experiment */ GNUNET_assert (experiments_requested > 0); experiments_requested --; GNUNET_STATISTICS_set (GED_stats, "# experiments requested", experiments_requested, GNUNET_NO); } static void run_experiment_inbound (void *cls,const struct GNUNET_SCHEDULER_TaskContext* tc) { struct ScheduledExperiment *se = cls; struct GNUNET_TIME_Relative start; struct GNUNET_TIME_Relative end; se->task = GNUNET_SCHEDULER_NO_TASK; switch (se->state) { case NOT_RUNNING: /* Send START_ACK message */ GED_nodes_send_start_ack (se->n, se->e); se->state = REQUESTED; /* Schedule to run */ start = GNUNET_TIME_absolute_get_remaining(se->e->start); if (0 == start.rel_value_us) se->task = GNUNET_SCHEDULER_add_now (&run_experiment_inbound, se); else se->task = GNUNET_SCHEDULER_add_delayed (start, &run_experiment_inbound, se); break; case REQUESTED: experiments_inbound_running ++; GNUNET_STATISTICS_set (GED_stats, "# experiments inbound running", experiments_inbound_running, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting inbound experiment `%s' with peer `%s'\n"), se->e->name, GNUNET_i2s (&se->n->id)); se->state = STARTED; se->task = GNUNET_SCHEDULER_add_now (&run_experiment_inbound, se); break; case STARTED: /* Experiment is running */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running %s experiment `%s' peer for `%s'\n", "inbound", GNUNET_i2s (&se->n->id), se->e->name); /* do work here */ /* Reschedule */ end = GNUNET_TIME_absolute_get_remaining(GNUNET_TIME_absolute_add (se->e->stop, se->e->frequency)); if (0 == end.rel_value_us) { se->state = STOPPED; return; /* End of experiment is reached */ } /* Reschedule */ se->task = GNUNET_SCHEDULER_add_delayed (se->e->frequency, &run_experiment_inbound, se); break; case STOPPED: /* Experiment expired */ break; default: break; } } static void run_experiment_outbound (void *cls,const struct GNUNET_SCHEDULER_TaskContext* tc) { struct ScheduledExperiment *se = cls; struct GNUNET_TIME_Relative end; se->task = GNUNET_SCHEDULER_NO_TASK; switch (se->state) { case NOT_RUNNING: /* Send START message */ GED_nodes_send_start (se->n, se->e); se->state = REQUESTED; se->task = GNUNET_SCHEDULER_add_delayed (EXP_RESPONSE_TIMEOUT, &request_timeout, se); experiments_requested ++; GNUNET_STATISTICS_set (GED_stats, "# experiments requested", experiments_requested, GNUNET_NO); break; case REQUESTED: /* Expecting START_ACK */ GNUNET_break (0); break; case STARTED: /* Experiment is running */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running %s experiment `%s' peer for `%s'\n", "outbound", GNUNET_i2s (&se->n->id), se->e->name); /* do work here */ /* Reschedule */ end = GNUNET_TIME_absolute_get_remaining(GNUNET_TIME_absolute_add (se->e->stop, se->e->frequency)); if (0 == end.rel_value_us) { se->state = STOPPED; return; /* End of experiment is reached */ } /* Reschedule */ se->task = GNUNET_SCHEDULER_add_delayed (se->e->frequency, &run_experiment_outbound, se); break; case STOPPED: /* Experiment expired */ break; default: break; } } /** * Handle a START message from a remote node * * @param n the node * @param e the experiment */ void GED_scheduler_handle_start (struct Node *n, struct Experiment *e) { if ((NULL != find_experiment (waiting_in_head, waiting_in_tail, n, e, GNUNET_NO)) || (NULL != find_experiment (running_in_head, running_in_tail, n, e, GNUNET_NO))) { GNUNET_break_op (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s message from peer %s for experiment `%s'\n", "START", GNUNET_i2s (&n->id), e->name); GED_scheduler_add (n, e, GNUNET_NO); } /** * Handle a START_ACK message from a remote node * * @param n the node * @param e the experiment */ void GED_scheduler_handle_start_ack (struct Node *n, struct Experiment *e) { struct ScheduledExperiment *se; if (NULL == (se = find_experiment (waiting_out_head, waiting_out_tail, n, e, GNUNET_YES))) { GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s message from peer %s for requested experiment `%s'\n", "START_ACK", GNUNET_i2s (&n->id), e->name); if (GNUNET_SCHEDULER_NO_TASK != se->task) { GNUNET_SCHEDULER_cancel (se->task); /* *Canceling timeout task */ se->task = GNUNET_SCHEDULER_NO_TASK; } /* Remove from waiting list, add to running list */ GNUNET_CONTAINER_DLL_remove (waiting_out_head, waiting_out_tail, se); GNUNET_CONTAINER_DLL_insert (running_out_head, running_out_tail, se); /* Change state and schedule to run */ experiments_outbound_running ++; GNUNET_STATISTICS_set (GED_stats, "# experiments outbound running", experiments_outbound_running, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting outbound experiment `%s' with peer `%s'\n"), e->name, GNUNET_i2s (&n->id)); se->state = STARTED; se->task = GNUNET_SCHEDULER_add_now (&run_experiment_outbound, se); } /** * Handle a STOP message from a remote node * * @param n the node * @param e the experiment */ void GED_scheduler_handle_stop (struct Node *n, struct Experiment *e) { struct ScheduledExperiment *se; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Received %s message from peer %s for experiment `%s'\n"), "STOP", GNUNET_i2s (&n->id), e->name); if (NULL != (se = find_experiment (waiting_in_head, waiting_in_tail, n, e, GNUNET_NO))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s message from peer %s for waiting experiment `%s'\n", "STOP", GNUNET_i2s (&n->id), e->name); } if (NULL != (se = find_experiment (running_in_head, running_in_tail, n, e, GNUNET_NO))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %s message from peer %s for running experiment `%s'\n", "STOP", GNUNET_i2s (&n->id), e->name); } } /** * Add a new experiment for a node * * @param n the node * @param e the experiment * @param outbound are we initiator (GNUNET_YES) or client (GNUNET_NO)? */ void GED_scheduler_add (struct Node *n, struct Experiment *e, int outbound) { struct ScheduledExperiment *se; struct GNUNET_TIME_Relative start; struct GNUNET_TIME_Relative end; GNUNET_assert ((GNUNET_YES == outbound) || (GNUNET_NO == outbound)); start = GNUNET_TIME_absolute_get_remaining(e->start); end = GNUNET_TIME_absolute_get_remaining(e->stop); if (0 == end.rel_value_us) return; /* End of experiment is reached */ /* Add additional checks here if required */ se = GNUNET_new (struct ScheduledExperiment); se->state = NOT_RUNNING; se->outbound = outbound; se->e = e; se->n = n; if (GNUNET_YES == outbound) { if (0 == start.rel_value_us) se->task = GNUNET_SCHEDULER_add_now (&run_experiment_outbound, se); else se->task = GNUNET_SCHEDULER_add_delayed (start, &run_experiment_outbound, se); GNUNET_CONTAINER_DLL_insert (waiting_out_head, waiting_out_tail, se); } else { if (0 == start.rel_value_us) se->task = GNUNET_SCHEDULER_add_now (&run_experiment_inbound, se); else se->task = GNUNET_SCHEDULER_add_delayed (start, &run_experiment_inbound, se); GNUNET_CONTAINER_DLL_insert (waiting_in_head, waiting_in_tail, se); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added %s experiment `%s' for node to be scheduled\n", (GNUNET_YES == outbound) ? "outbound" : "inbound", e->name, GNUNET_i2s(&se->n->id)); experiments_scheduled ++; GNUNET_STATISTICS_set (GED_stats, "# experiments scheduled", experiments_scheduled, GNUNET_NO); } /** * Start the scheduler component */ void GED_scheduler_start () { experiments_requested = 0; experiments_scheduled = 0; } /** * Stop the scheduler component */ void GED_scheduler_stop () { struct ScheduledExperiment *cur; struct ScheduledExperiment *next; next = waiting_in_head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove (waiting_in_head, waiting_in_tail, cur); if (GNUNET_SCHEDULER_NO_TASK != cur->task) { GNUNET_SCHEDULER_cancel (cur->task); cur->task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (cur); GNUNET_assert (experiments_scheduled > 0); experiments_scheduled --; GNUNET_STATISTICS_set (GED_stats, "# experiments scheduled", experiments_scheduled, GNUNET_NO); } next = running_in_head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove (running_in_head, running_in_tail, cur); if (GNUNET_SCHEDULER_NO_TASK != cur->task) { GNUNET_SCHEDULER_cancel (cur->task); cur->task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (cur); GNUNET_assert (experiments_outbound_running > 0); experiments_inbound_running --; GNUNET_STATISTICS_set (GED_stats, "# experiments inbound running", experiments_inbound_running, GNUNET_NO); } next = waiting_out_head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove (waiting_out_head, waiting_out_tail, cur); if (GNUNET_SCHEDULER_NO_TASK != cur->task) { GNUNET_SCHEDULER_cancel (cur->task); cur->task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (cur); GNUNET_assert (experiments_scheduled > 0); experiments_scheduled --; GNUNET_STATISTICS_set (GED_stats, "# experiments scheduled", experiments_scheduled, GNUNET_NO); } next = running_out_head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove (running_out_head, running_out_tail, cur); if (GNUNET_SCHEDULER_NO_TASK != cur->task) { GNUNET_SCHEDULER_cancel (cur->task); cur->task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (cur); GNUNET_assert (experiments_outbound_running > 0); experiments_outbound_running --; GNUNET_STATISTICS_set (GED_stats, "# experiments outbound running", experiments_outbound_running, GNUNET_NO); } } /* end of gnunet-daemon-experimentation_scheduler.c */ gnunet-0.10.1/src/include/0000755000175000017500000000000012320755622012310 500000000000000gnunet-0.10.1/src/include/gnunet_datastore_plugin.h0000644000175000017500000002400712225777503017336 00000000000000/* This file is part of GNUnet (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_datastore_plugin.h * @brief API for the database backend plugins. * @author Christian Grothoff */ #ifndef PLUGIN_DATASTORE_H #define PLUGIN_DATASTORE_H #include "gnunet_block_lib.h" #include "gnunet_configuration_lib.h" #include "gnunet_datastore_service.h" #include "gnunet_statistics_service.h" #include "gnunet_scheduler_lib.h" /** * How many bytes of overhead will we assume per entry * in any DB (for reservations)? */ #define GNUNET_DATASTORE_ENTRY_OVERHEAD 256 /** * Function invoked to notify service of disk utilization * changes. * * @param cls closure * @param delta change in disk utilization, * 0 for "reset to empty" */ typedef void (*DiskUtilizationChange) (void *cls, int delta); /** * The datastore service will pass a pointer to a struct * of this type as the first and only argument to the * entry point of each datastore plugin. */ struct GNUNET_DATASTORE_PluginEnvironment { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Function to call on disk utilization change. */ DiskUtilizationChange duc; /** * Closure. */ void *cls; }; /** * An processor over a set of items stored in the datastore. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum * @return #GNUNET_OK to keep the item * #GNUNET_NO to delete the item */ typedef int (*PluginDatumProcessor) (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid); /** * Get an estimate of how much space the database is * currently using. * * @param cls closure * @return number of bytes used on disk */ typedef unsigned long long (*PluginEstimateSize) (void *cls); /** * Store an item in the datastore. If the item is already present, * the priorities and replication levels are summed up and the higher * expiration time and lower anonymity level is used. * * @param cls closure * @param key key for the item * @param size number of bytes in @a data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param msg set to an error message (on failure) * @return #GNUNET_OK on success, * #GNUNET_SYSERR on failure */ typedef int (*PluginPut) (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, char **msg); /** * An processor over a set of keys stored in the datastore. * * @param cls closure * @param key key in the data store * @param count how many values are stored under this key in the datastore */ typedef void (*PluginKeyProcessor) (void *cls, const struct GNUNET_HashCode *key, unsigned int count); /** * Get all of the keys in the datastore. * * @param cls closure * @param proc function to call on each key * @param proc_cls closure for @a proc */ typedef void (*PluginGetKeys) (void *cls, PluginKeyProcessor proc, void *proc_cls); /** * Get one of the results for a particular key in the datastore. * * @param cls closure * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param key key to match, never NULL * @param vhash hash of the value, maybe NULL (to * match all values that have the right key). * Note that for DBlocks there is no difference * betwen key and vhash, but for other blocks * there may be! * @param type entries of which type are relevant? * Use 0 for any type. * @param min find the smallest key that is larger than the given min, * NULL for no minimum (return smallest key) * @param proc function to call on the matching value; * proc should be called with NULL if there is no result * @param proc_cls closure for @a proc */ typedef void (*PluginGetKey) (void *cls, uint64_t offset, const struct GNUNET_HashCode * key, const struct GNUNET_HashCode * vhash, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls); /** * Get a random item (additional constraints may apply depending on * the specific implementation). Calls @a proc with all values ZERO or * NULL if no item applies, otherwise @a proc is called once and only * once with an item. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for @a proc */ typedef void (*PluginGetRandom) (void *cls, PluginDatumProcessor proc, void *proc_cls); /** * Update the priority for a particular key in the datastore. If * the expiration time in value is different than the time found in * the datastore, the higher value should be kept. For the * anonymity level, the lower value is to be used. The specified * priority should be added to the existing priority, ignoring the * priority in value. * * @param cls closure * @param uid unique identifier of the datum * @param delta by how much should the priority * change? If priority + delta < 0 the * priority should be set to 0 (never go * negative). * @param expire new expiration time should be the * MAX of any existing expiration time and * this value * @param msg set to an error message (on error) * @return #GNUNET_OK on success */ typedef int (*PluginUpdate) (void *cls, uint64_t uid, int delta, struct GNUNET_TIME_Absolute expire, char **msg); /** * Select a single item from the datastore at the specified offset * (among those applicable). * * @param cls closure * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param type entries of which type should be considered? * Must not be zero (ANY). * @param proc function to call on the matching value * @param proc_cls closure for @a proc */ typedef void (*PluginGetType) (void *cls, uint64_t offset, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls); /** * Drop database. * * @param cls closure */ typedef void (*PluginDrop) (void *cls); /** * Each plugin is required to return a pointer to a struct of this * type as the return value from its entry point. */ struct GNUNET_DATASTORE_PluginFunctions { /** * Closure to use for all of the following callbacks * (except "next_request"). */ void *cls; /** * Calculate the current on-disk size of the SQ store. Estimates * are fine, if that's the only thing available. */ PluginEstimateSize estimate_size; /** * Function to store an item in the datastore. */ PluginPut put; /** * Update the priority for a particular key in the datastore. If * the expiration time in value is different than the time found in * the datastore, the higher value should be kept. For the * anonymity level, the lower value is to be used. The specified * priority should be added to the existing priority, ignoring the * priority in value. */ PluginUpdate update; /** * Get a particular datum matching a given hash from the datastore. */ PluginGetKey get_key; /** * Get datum (of the specified type) with anonymity level zero. * This function is allowed to ignore the 'offset' argument * and instead return a random result (with zero anonymity of * the correct type) if implementing an offset is expensive. */ PluginGetType get_zero_anonymity; /** * Function to get a random item with high replication score from * the database, lowering the item's replication score. Returns a * single random item from those with the highest replication * counters. The item's replication counter is decremented by one * IF it was positive before. */ PluginGetRandom get_replication; /** * Function to get a random expired item or, if none are expired, * either the oldest entry or one with a low priority (depending * on what was efficiently implementable). */ PluginGetRandom get_expiration; /** * Delete the database. The next operation is * guaranteed to be unloading of the module. */ PluginDrop drop; /** * Iterate over all keys in the database. */ PluginGetKeys get_keys; }; #endif gnunet-0.10.1/src/include/gnunet_datastore_service.h0000644000175000017500000004117712247442021017473 00000000000000/* This file is part of GNUnet (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_datastore_service.h * @brief API that can be used manage the * datastore for files stored on a GNUnet node; * note that the datastore is NOT responsible for * on-demand encoding, that is achieved using * a special kind of entry. * @author Christian Grothoff */ #ifndef GNUNET_DATASTORE_SERVICE_H #define GNUNET_DATASTORE_SERVICE_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Entry in the queue. */ struct GNUNET_DATASTORE_QueueEntry; /** * Handle to the datastore service. */ struct GNUNET_DATASTORE_Handle; /** * Maximum size of a value that can be stored in the datastore. */ #define GNUNET_DATASTORE_MAX_VALUE_SIZE 65536 /** * Connect to the datastore service. * * @param cfg configuration to use * @return handle to use to access the service */ struct GNUNET_DATASTORE_Handle * GNUNET_DATASTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Disconnect from the datastore service (and free * associated resources). * * @param h handle to the datastore * @param drop set to GNUNET_YES to delete all data in datastore (!) */ void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h, int drop); /** * Continuation called to notify client about result of the * operation. * * @param cls closure * @param success #GNUNET_SYSERR on failure (including timeout/queue drop) * #GNUNET_NO if content was already there * #GNUNET_YES (or other positive value) on success * @param min_expiration minimum expiration time required for 0-priority content to be stored * by the datacache at this time, zero for unknown, forever if we have no * space for 0-priority content * @param msg NULL on success, otherwise an error message */ typedef void (*GNUNET_DATASTORE_ContinuationWithStatus) (void *cls, int32_t success, struct GNUNET_TIME_Absolute min_expiration, const char *msg); /** * Reserve space in the datastore. This function should be used * to avoid "out of space" failures during a longer sequence of "put" * operations (for example, when a file is being inserted). * * @param h handle to the datastore * @param amount how much space (in bytes) should be reserved (for content only) * @param entries how many entries will be created (to calculate per-entry overhead) * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response (or before dying in queue) * @param cont continuation to call when done; "success" will be set to * a positive reservation value if space could be reserved. * @param cont_cls closure for cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h, uint64_t amount, uint32_t entries, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls); /** * Store an item in the datastore. If the item is already present, * the priorities and replication values are summed up and the higher * expiration time and lower anonymity level is used. * * @param h handle to the datastore * @param rid reservation ID to use (from "reserve"); use 0 if no * prior reservation was made * @param key key for the value * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication how often should the content be replicated to other peers? * @param expiration expiration time for the content * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout timeout for the operation * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h, uint32_t rid, const struct GNUNET_HashCode *key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls); /** * Signal that all of the data for which a reservation was made has * been stored and that whatever excess space might have been reserved * can now be released. * * @param h handle to the datastore * @param rid reservation ID (value of "success" in original continuation * from the "reserve" function). * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h, uint32_t rid, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls); /** * Update a value in the datastore. * * @param h handle to the datastore * @param uid identifier for the value * @param priority how much to increase the priority of the value * @param expiration new expiration value should be MAX of existing and this argument * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h, uint64_t uid, uint32_t priority, struct GNUNET_TIME_Absolute expiration, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls); /** * Explicitly remove some content from the database. @a cont will be * called with status #GNUNET_OK if content was removed, #GNUNET_NO if * no matching entry was found and #GNUNET_SYSERR on all other types * of errors. * * @param h handle to the datastore * @param key key for the value * @param size number of bytes in @a data * @param data content stored * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h, const struct GNUNET_HashCode * key, size_t size, const void *data, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls); /** * Process a datum that was stored in the datastore. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ typedef void (*GNUNET_DATASTORE_DatumProcessor) (void *cls, const struct GNUNET_HashCode *key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid); /** * Get a result for a particular key from the datastore. The processor * will only be called once. * * @param h handle to the datastore * @param offset offset of the result (modulo num-results); set to * a random 64-bit value initially; then increment by * one each time; detect that all results have been found by uid * being again the first uid ever returned. * @param key maybe NULL (to match all entries) * @param type desired type, 0 for any * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param proc function to call on a matching value; * or with a NULL value if no datum matches * @param proc_cls closure for @a proc * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_key (struct GNUNET_DATASTORE_Handle *h, uint64_t offset, const struct GNUNET_HashCode *key, enum GNUNET_BLOCK_Type type, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls); /** * Get a single zero-anonymity value from the datastore. * Note that some implementations can ignore the 'offset' and * instead return a random zero-anonymity value. In that case, * detecting the wrap-around based on a repeating UID is at best * probabilistic. * * @param h handle to the datastore * @param offset offset of the result (modulo num-results); set to * a random 64-bit value initially; then increment by * one each time; detect that all results have been found by uid * being again the first uid ever returned. * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param type allowed type for the operation (never zero) * @param proc function to call on a random value; it * will be called once with a value (if available) * or with NULL if none value exists. * @param proc_cls closure for proc * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_zero_anonymity (struct GNUNET_DATASTORE_Handle *h, uint64_t offset, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, enum GNUNET_BLOCK_Type type, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls); /** * Get a random value from the datastore for content replication. * Returns a single, random value among those with the highest * replication score, lowering positive replication scores by one for * the chosen value (if only content with a replication score exists, * a random value is returned and replication scores are not changed). * * @param h handle to the datastore * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param proc function to call on a random value; it * will be called once with a value (if available) * and always once with a value of NULL. * @param proc_cls closure for proc * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_for_replication (struct GNUNET_DATASTORE_Handle *h, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls); /** * Cancel a datastore operation. The final callback from the * operation must not have been done yet. * * @param qe operation to cancel */ void GNUNET_DATASTORE_cancel (struct GNUNET_DATASTORE_QueueEntry *qe); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_datastore_service.h */ #endif gnunet-0.10.1/src/include/gnunet_namestore_service.h0000644000175000017500000002425612241134530017476 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_namestore_service.h * @brief API that can be used to store naming information on a GNUnet node; * Naming information can either be records for which this peer/user * is authoritative, or blocks which are cached, encrypted naming * data from other peers. * @author Christian Grothoff */ #ifndef GNUNET_NAMESTORE_SERVICE_H #define GNUNET_NAMESTORE_SERVICE_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_gnsrecord_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Entry in the queue. */ struct GNUNET_NAMESTORE_QueueEntry; /** * Handle to the namestore service. */ struct GNUNET_NAMESTORE_Handle; /** * Handle to the namestore zone iterator. */ struct GNUNET_NAMESTORE_ZoneIterator; /** * Connect to the namestore service. * * @param cfg configuration to use * @return handle to use to access the service */ struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Disconnect from the namestore service (and free associated * resources). Must not be called from within operation callbacks of * the API. * * @param h handle to the namestore */ void GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h); /** * Continuation called to notify client about result of the * operation. * * @param cls closure * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) * #GNUNET_NO if content was already there or not found * #GNUNET_YES (or other positive value) on success * @param emsg NULL on success, otherwise an error message */ typedef void (*GNUNET_NAMESTORE_ContinuationWithStatus) (void *cls, int32_t success, const char *emsg); /** * Store an item in the namestore. If the item is already present, * it is replaced with the new record. Use an empty array to * remove all records under the given name. * * @param h handle to the namestore * @param pkey private key of the zone * @param label name that is being mapped * @param rd_count number of records in the 'rd' array * @param rd array of records with data to store * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return handle to abort the request */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls); /** * Process a record that was stored in the namestore. * * @param cls closure * @param zone private key of the zone; NULL on disconnect * @param label label of the records; NULL on disconnect * @param rd_count number of entries in @a rd array, 0 if label was deleted * @param rd array of records with data to store */ typedef void (*GNUNET_NAMESTORE_RecordMonitor) (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); /** * Set the desired nick name for a zone * * @param h handle to the namestore * @param pkey private key of the zone * @param nick the nick name to set * @param cont continuation to call when done * @param cont_cls closure for 'cont' * @return handle to abort the request */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_set_nick (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *nick, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls); /** * Lookup an item in the namestore. * * @param h handle to the namestore * @param pkey private key of the zone * @param label name that is being mapped * @param rm function to call with the result (with 0 records if we don't have that label) * @param rm_cls closure for @a rm * @return handle to abort the request */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *label, GNUNET_NAMESTORE_RecordMonitor rm, void *rm_cls); /** * Look for an existing PKEY delegation record for a given public key. * Returns at most one result to the processor. * * @param h handle to the namestore * @param zone public key of the zone to look up in, never NULL * @param value_zone public key of the target zone (value), never NULL * @param proc function to call on the matching records, or with * NULL (rd_count == 0) if there are no matching records * @param proc_cls closure for @a proc * @return a handle that can be used to * cancel */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls); /** * Cancel a namestore operation. The final callback from the * operation must not have been done yet. Must be called on any * namestore operation that has not yet completed prior to calling * #GNUNET_NAMESTORE_disconnect. * * @param qe operation to cancel */ void GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe); /** * Starts a new zone iteration (used to periodically PUT all of our * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once * immediately, and then again after * #GNUNET_NAMESTORE_zone_iterator_next is invoked. * * @param h handle to the namestore * @param zone zone to access, NULL for all zones * @param proc function to call on each name from the zone; it * will be called repeatedly with a value (if available) * and always once at the end with a label of NULL. * @param proc_cls closure for @a proc * @return an iterator handle to use for iteration */ struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls); /** * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start * for the next record. * * @param it the iterator */ void GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it); /** * Stops iteration and releases the namestore handle for further calls. Must * be called on any iteration that has not yet completed prior to calling * #GNUNET_NAMESTORE_disconnect. * * @param it the iterator */ void GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it); /** * Handle for a monitoring activity. */ struct GNUNET_NAMESTORE_ZoneMonitor; /** * Function called once the monitor has caught up with the current * state of the database. Will be called AGAIN after each disconnect * (record monitor called with 'NULL' for zone_key) once we're again * in sync. * * @param cls closure */ typedef void (*GNUNET_NAMESTORE_RecordsSynchronizedCallback)(void *cls); /** * Begin monitoring a zone for changes. Will first call the @a * monitor function on all existing records in the selected zone(s) if * @a iterate_first is #GNUNET_YES. In any case, we will then call @a * sync_cb, and then afterwards call the @a monitor whenever a record * changes. If the namestore disconnects, the @a monitor function is * called with a disconnect event; if the connection is * re-established, the process begins from the start (depending on @a * iterate_first, we first do all existing records, then @a sync, then * updates). * * @param cfg configuration to use to connect to namestore * @param zone zone to monitor, NULL for all zones * @param iterate_first #GNUNET_YES to first iterate over all existing records, * #GNUNET_NO to only return changes that happen from now on * @param monitor function to call on zone changes * @param sync_cb function called when we're in sync with the namestore * @param cls closure for @a monitor and @a sync_cb * @return handle to stop monitoring */ struct GNUNET_NAMESTORE_ZoneMonitor * GNUNET_NAMESTORE_zone_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, int iterate_first, GNUNET_NAMESTORE_RecordMonitor monitor, GNUNET_NAMESTORE_RecordsSynchronizedCallback sync_cb, void *cls); /** * Stop monitoring a zone for changes. * * @param zm handle to the monitor activity to stop */ void GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_namestore_service.h */ #endif gnunet-0.10.1/src/include/gnunet_configuration_lib.h0000644000175000017500000004023512306275771017470 00000000000000/* This file is part of GNUnet. (C) 2006, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_configuration_lib.h * @brief configuration API * @author Christian Grothoff * @defgroup configuration Configuration management * @{ */ #ifndef GNUNET_CONFIGURATION_LIB_H #define GNUNET_CONFIGURATION_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * A configuration object. */ struct GNUNET_CONFIGURATION_Handle; /** * Create a new configuration object. * @return fresh configuration object */ struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create (void); /** * Duplicate an existing configuration object. * * @param cfg configuration to duplicate * @return duplicate configuration */ struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Destroy configuration object. * * @param cfg configuration to destroy */ void GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg); /** * Load configuration. This function will first parse the * defaults and then parse the specific configuration file * to overwrite the defaults. * * @param cfg configuration to update * @param filename name of the configuration file, NULL to load defaults * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename); /** * Load default configuration. This function will parse the * defaults from the given defaults_d directory. * * @param cfg configuration to update * @param defaults_d directory with the defaults * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d); /** * Parse a configuration file, add all of the options in the * file to the configuration environment. * * @param cfg configuration to update * @param filename name of the configuration file * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename); /** * Serializes the given configuration. * * @param cfg configuration to serialize * @param size will be set to the size of the serialized memory block * @return the memory block where the serialized configuration is * present. This memory should be freed by the caller */ char * GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size); /** * De-serializes configuration * * @param cfg configuration to update * @param mem the memory block of serialized configuration * @param size the size of the memory block * @param allow_inline set to #GNUNET_YES if we recursively load configuration * from inlined configurations; #GNUNET_NO if not and raise warnings * when we come across them * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, const size_t size, int allow_inline); /** * Write configuration file. * * @param cfg configuration to write * @param filename where to write the configuration * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename); /** * Write only configuration entries that have been changed to configuration file * @param cfg_default default configuration * @param cfg_new new configuration * @param filename where to write the configuration diff between default and new * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new, const char *filename); /** * Compute configuration with only entries that have been changed * * @param cfg_default original configuration * @param cfg_new new configuration * @return configuration with only the differences, never NULL */ struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new); /** * Test if there are configuration options that were * changed since the last save. * * @param cfg configuration to inspect * @return #GNUNET_NO if clean, #GNUNET_YES if dirty, #GNUNET_SYSERR on error (i.e. last save failed) */ int GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Function to iterate over options. * * @param cls closure * @param section name of the section * @param option name of the option * @param value value of the option */ typedef void (*GNUNET_CONFIGURATION_Iterator) (void *cls, const char *section, const char *option, const char *value); /** * Function to iterate over section. * * @param cls closure * @param section name of the section */ typedef void (*GNUNET_CONFIGURATION_Section_Iterator) (void *cls, const char *section); /** * Iterate over all options in the configuration. * * @param cfg configuration to inspect * @param iter function to call on each option * @param iter_cls closure for @a iter */ void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls); /** * Iterate over all sections in the configuration. * * @param cfg configuration to inspect * @param iter function to call on each section * @param iter_cls closure for @a iter */ void GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Section_Iterator iter, void *iter_cls); /** * Remove the given section and all options in it. * * @param cfg configuration to inspect * @param section name of the section to remove */ void GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section); /** * Get a configuration value that should be a number. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param number where to store the numeric value of the option * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number); /** * Get a configuration value that should be a relative time. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param time set to the time value stored in the configuration * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time); /** * Get a configuration value that should be a size in bytes. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param size set to the size in bytes as stored in the configuration * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size); /** * Test if we have a value for a particular option * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @return #GNUNET_YES if so, #GNUNET_NO if not. */ int GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option); /** * Get a configuration value that should be a string. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param value will be set to a freshly allocated configuration * value, or NULL if option is not specified * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value); /** * Get a configuration value that should be the name of a file * or directory. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param value will be set to a freshly allocated configuration * value, or NULL if option is not specified * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value); /** * Iterate over the set of filenames stored in a configuration value. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param cb function to call on each filename * @param cb_cls closure for @a cb * @return number of filenames iterated over, -1 on error */ int GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, GNUNET_FileNameCallback cb, void *cb_cls); /** * Iterate over values of a section in the configuration. * * @param cfg configuration to inspect * @param section the section * @param iter function to call on each option * @param iter_cls closure for @a iter */ void GNUNET_CONFIGURATION_iterate_section_values (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls); /** * Get a configuration value that should be in a set of * predefined strings * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param choices NULL-terminated list of legal values * @param value will be set to an entry in the legal list, * or NULL if option is not specified and no default given * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value); /** * Get a configuration value that should be in a set of * "YES" or "NO". * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @return #GNUNET_YES, #GNUNET_NO or if option has no valid value, #GNUNET_SYSERR */ int GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option); /** * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" * where either in the "PATHS" section or the environtment "FOO" is * set to "DIRECTORY". We also support default expansion, * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is * set in PATHS or the environment, and otherwise to "default". Note * that "default" itself can also be a $-expression, thus * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined * to VAR2. * * @param cfg configuration to use for path expansion * @param orig string to $-expand (will be freed!) Note that multiple * $-expressions can be present in this string. They will all be * $-expanded. * @return $-expanded string */ char * GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig); /** * Set a configuration value that should be a number. * * @param cfg configuration to update * @param section section of interest * @param option option of interest * @param number value to set */ void GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long number); /** * Set a configuration value that should be a string. * * @param cfg configuration to update * @param section section of interest * @param option option of interest * @param value value to set */ void GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value); /** * Remove a filename from a configuration value that * represents a list of filenames * * @param cfg configuration to update * @param section section of interest * @param option option of interest * @param value filename to remove * @return #GNUNET_OK on success, * #GNUNET_SYSERR if the filename is not in the list */ int GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value); /** * Append a filename to a configuration value that * represents a list of filenames * * @param cfg configuration to update * @param section section of interest * @param option option of interest * @param value filename to append * @return #GNUNET_OK on success, * #GNUNET_SYSERR if the filename already in the list */ int GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value); /** @} */ /* end of group configuration */ #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_mq_lib.h0000644000175000017500000003522212264756022015232 00000000000000/* This file is part of GNUnet. (C) 2012-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Florian Dold * @file include/gnunet_mq_lib.h * @brief general purpose message queue * @defgroup mq general purpose message queue * @{ */ #ifndef GNUNET_MQ_H #define GNUNET_MQ_H /** * Allocate an envelope, with extra space allocated after the space needed * by the message struct. * The allocated message will already have the type and size field set. * * @param mvar variable to store the allocated message in; * must have a header field * @param esize extra space to allocate after the message * @param type type of the message * @return the MQ message */ #define GNUNET_MQ_msg_extra(mvar, esize, type) GNUNET_MQ_msg_(((struct GNUNET_MessageHeader**) &(mvar)), (esize) + sizeof *(mvar), (type)) /** * Allocate a GNUNET_MQ_Envelope. * The contained message will already have the type and size field set. * * @param mvar variable to store the allocated message in; * must have a header field * @param type type of the message * @return the allocated envelope */ #define GNUNET_MQ_msg(mvar, type) GNUNET_MQ_msg_extra(mvar, 0, type) /** * Allocate a GNUNET_MQ_Envelope, where the message only consists of a header. * The allocated message will already have the type and size field set. * * @param type type of the message */ #define GNUNET_MQ_msg_header(type) GNUNET_MQ_msg_ (NULL, sizeof (struct GNUNET_MessageHeader), type) /** * Allocate a GNUNET_MQ_Envelope, where the message only consists of a header and extra space. * The allocated message will already have the type and size field set. * * @param mh pointer that will changed to point at to the allocated message header * @param esize extra space to allocate after the message header * @param type type of the message */ #define GNUNET_MQ_msg_header_extra(mh, esize, type) GNUNET_MQ_msg_ (&mh, (esize) + sizeof (struct GNUNET_MessageHeader), type) /** * Allocate a GNUNET_MQ_Envelope, and append a payload message after the given * message struct. * * @param mvar pointer to a message struct, will be changed to point at the newly allocated message, * whose size is 'sizeof(*mvar) + ntohs (mh->size)' * @param type message type of the allocated message, has no effect on the nested message * @param mh message to nest * @return a newly allocated 'struct GNUNET_MQ_Envelope *' */ #define GNUNET_MQ_msg_nested_mh(mvar, type, mh) GNUNET_MQ_msg_nested_mh_((((void)(mvar)->header), (struct GNUNET_MessageHeader**) &(mvar)), sizeof (*(mvar)), (type), mh) /** * Return a pointer to the message at the end of the given message. * * @param var pointer to a message struct, the type of the expression determines the base size, * the space after the base size is the nested message * @return a 'struct GNUNET_MessageHeader *' that points at the nested message of the given message, * or NULL if the given message in @a var does not have any space after the message struct */ #define GNUNET_MQ_extract_nested_mh(var) GNUNET_MQ_extract_nested_mh_ ((struct GNUNET_MessageHeader *) (var), sizeof (*(var))) /** * Implementation of the GNUNET_MQ_extract_nexted_mh macro. * * @param mh message header to extract nested message header from * @param base_size size of the message before the nested message's header appears * @return pointer to the nested message, does not copy the message */ struct GNUNET_MessageHeader * GNUNET_MQ_extract_nested_mh_ (const struct GNUNET_MessageHeader *mh, uint16_t base_size); /** * Implementation of the GNUNET_MQ_msg_nested_mh macro. * * @param mhp pointer to the message header pointer that will be changed to allocate at * the newly allocated space for the message. * @param base_size size of the data before the nested message * @param type type of the message in the envelope * @param nested_mh the message to append to the message after base_size */ struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_nested_mh_ (struct GNUNET_MessageHeader **mhp, uint16_t base_size, uint16_t type, const struct GNUNET_MessageHeader *nested_mh); /** * End-marker for the handlers array */ #define GNUNET_MQ_HANDLERS_END {NULL, 0, 0} /** * Opaque handle to a message queue. */ struct GNUNET_MQ_Handle; /** * Opaque handle to an envelope. */ struct GNUNET_MQ_Envelope; /** * Error codes for the queue. */ enum GNUNET_MQ_Error { /** * FIXME: document! */ GNUNET_MQ_ERROR_READ = 1, /** * FIXME: document! */ GNUNET_MQ_ERROR_WRITE = 2, /** * FIXME: document! */ GNUNET_MQ_ERROR_TIMEOUT = 4 }; /** * Called when a message has been received. * * @param cls closure * @param msg the received message */ typedef void (*GNUNET_MQ_MessageCallback) (void *cls, const struct GNUNET_MessageHeader *msg); /** * Signature of functions implementing the * sending functionality of a message queue. * * @param mq the message queue * @param msg the message to send * @param impl_state state of the implementation */ typedef void (*GNUNET_MQ_SendImpl) (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state); /** * Signature of functions implementing the * destruction of a message queue. * Implementations must not free @a mq, but should * take care of @a impl_state. * * @param mq the message queue to destroy * @param impl_state state of the implementation */ typedef void (*GNUNET_MQ_DestroyImpl) (struct GNUNET_MQ_Handle *mq, void *impl_state); /** * Implementation function that cancels the currently sent message. * * @param mq message queue * @param impl_state state specific to the implementation */ typedef void (*GNUNET_MQ_CancelImpl) (struct GNUNET_MQ_Handle *mq, void *impl_state); /** * Callback used for notifications * * @param cls closure */ typedef void (*GNUNET_MQ_NotifyCallback) (void *cls); /** * Generic error handler, called with the appropriate * error code and the same closure specified at the creation of * the message queue. * Not every message queue implementation supports an error handler. * * @param cls closure, same closure as for the message handlers * @param error error code */ typedef void (*GNUNET_MQ_ErrorHandler) (void *cls, enum GNUNET_MQ_Error error); /** * Message handler for a specific message type. */ struct GNUNET_MQ_MessageHandler { /** * Callback, called every time a new message of * the specified type has been receied. */ GNUNET_MQ_MessageCallback cb; /** * Type of the message this handler covers. */ uint16_t type; /** * Expected size of messages of this type. Use 0 for * variable-size. If non-zero, messages of the given * type will be discarded (and the connection closed) * if they do not have the right size. */ uint16_t expected_size; }; /** * Create a new envelope. * * @param mhp message header to store the allocated message header in, can be NULL * @param size size of the message to allocate * @param type type of the message, will be set in the allocated message * @return the allocated MQ message */ struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_ (struct GNUNET_MessageHeader **mhp, uint16_t size, uint16_t type); /** * Discard the message queue message, free all * allocated resources. Must be called in the event * that a message is created but should not actually be sent. * * @param mqm the message to discard */ void GNUNET_MQ_discard (struct GNUNET_MQ_Envelope *mqm); /** * Send a message with the give message queue. * May only be called once per message. * * @param mq message queue * @param ev the envelope with the message to send. */ void GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev); /** * Cancel sending the message. Message must have been sent with * #GNUNET_MQ_send before. May not be called after the notify sent * callback has been called * * @param ev queued envelope to cancel */ void GNUNET_MQ_send_cancel (struct GNUNET_MQ_Envelope *ev); /** * Associate the assoc_data in mq with a unique request id. * * @param mq message queue, id will be unique for the queue * @param assoc_data to associate */ uint32_t GNUNET_MQ_assoc_add (struct GNUNET_MQ_Handle *mq, void *assoc_data); /** * Get the data associated with a request id in a queue * * @param mq the message queue with the association * @param request_id the request id we are interested in * @return the associated data */ void * GNUNET_MQ_assoc_get (struct GNUNET_MQ_Handle *mq, uint32_t request_id); /** * Remove the association for a request id * * @param mq the message queue with the association * @param request_id the request id we want to remove * @return the associated data */ void * GNUNET_MQ_assoc_remove (struct GNUNET_MQ_Handle *mq, uint32_t request_id); /** * Create a message queue for a GNUNET_CLIENT_Connection. * If handlers are specfied, receive messages from the connection. * * @param connection the client connection * @param handlers handlers for receiving messages * @param error_handler error handler * @param cls closure for the handlers * @return the message queue */ struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_connection_client (struct GNUNET_CLIENT_Connection *connection, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls); /** * Create a message queue for a GNUNET_SERVER_Client. * * @param client the client * @return the message queue */ struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_server_client (struct GNUNET_SERVER_Client *client); /** * Create a message queue for the specified handlers. * * @param send function the implements sending messages * @param destroy function that implements destroying the queue * @param cancel function that implements canceling a message * @param impl_state for the queue, passed to @a send, @a destroy and @a cancel * @param handlers array of message handlers * @param error_handler handler for read and write errors * @param cls closure for message handlers and error handler * @return a new message queue */ struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks (GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls); /** * Replace the handlers of a message queue with new handlers. Takes * effect immediately, even for messages that already have been * received, but for with the handler has not been called. * * If the message queue does not support receiving messages, * this function has no effect. * * @param mq message queue * @param new_handlers new handlers * @param cls new closure for the handlers */ void GNUNET_MQ_replace_handlers (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MQ_MessageHandler *new_handlers, void *cls); /** * Call a callback once the envelope has been sent, that is, * sending it can not be canceled anymore. * There can be only one notify sent callback per envelope. * * @param ev message to call the notify callback for * @param cb the notify callback * @param cls closure for the callback */ void GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *ev, GNUNET_MQ_NotifyCallback cb, void *cls); /** * Destroy the message queue. * * @param mq message queue to destroy */ void GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq); /** * Call the message message handler that was registered * for the type of the given message in the given message queue. * * This function is indended to be used for the implementation * of message queues. * * @param mq message queue with the handlers * @param mh message to dispatch */ void GNUNET_MQ_inject_message (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *mh); /** * Call the error handler of a message queue with the given * error code. If there is no error handler, log a warning. * * This function is intended to be used for the implementation * of message queues. * * @param mq message queue * @param error the error type */ void GNUNET_MQ_inject_error (struct GNUNET_MQ_Handle *mq, enum GNUNET_MQ_Error error); /** * Call the send implementation for the next queued message, * if any. * Only useful for implementing message queues, * results in undefined behavior if not used carefully. * * @param mq message queue to send the next message with */ void GNUNET_MQ_impl_send_continue (struct GNUNET_MQ_Handle *mq); /** * Get the message that should currently be sent. * The returned message is only valid until #GNUNET_MQ_impl_send_continue * is called. * Fails if there is no current message. * Only useful for implementing message queues, * results in undefined behavior if not used carefully. * * @param mq message queue with the current message, only valid * until #GNUNET_MQ_impl_send_continue is called * @return message to send, never NULL */ const struct GNUNET_MessageHeader * GNUNET_MQ_impl_current (struct GNUNET_MQ_Handle *mq); /** * Get the implementation state associated with the * message queue. * * While the GNUNET_MQ_Impl* callbacks receive the * implementation state, continuations that are scheduled * by the implementation function often only have one closure * argument, with this function it is possible to get at the * implementation state when only passing the GNUNET_MQ_Handle * as closure. * * @param mq message queue with the current message * @return message to send, never NULL */ void * GNUNET_MQ_impl_state (struct GNUNET_MQ_Handle *mq); /** @} */ /* end of group mq */ #endif gnunet-0.10.1/src/include/gnunet_disk_lib.h0000644000175000017500000005361012225777503015554 00000000000000/* This file is part of GNUnet. (C) 2001-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_disk_lib.h * @brief disk IO apis * @author Christian Grothoff */ #ifndef GNUNET_DISK_LIB_H #define GNUNET_DISK_LIB_H /** * Handle used to manage a pipe. */ struct GNUNET_DISK_PipeHandle; /** * Type of a handle. */ enum GNUNET_FILE_Type { /** * Handle represents a file. */ GNUNET_DISK_HANLDE_TYPE_FILE, /** * Handle represents a pipe. */ GNUNET_DISK_HANLDE_TYPE_PIPE }; /** * Handle used to access files (and pipes). */ struct GNUNET_DISK_FileHandle { #if WINDOWS /** * File handle under W32. */ HANDLE h; /** * Type */ enum GNUNET_FILE_Type type; /** * Structure for overlapped reading (for pipes) */ OVERLAPPED *oOverlapRead; /** * Structure for overlapped writing (for pipes) */ OVERLAPPED *oOverlapWrite; #else /** * File handle on other OSes. */ int fd; #endif }; /* we need size_t, and since it can be both unsigned int or unsigned long long, this IS platform dependent; but "stdlib.h" should be portable 'enough' to be unconditionally available... */ #include #include "gnunet_configuration_lib.h" #include "gnunet_scheduler_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Specifies how a file should be opened. */ enum GNUNET_DISK_OpenFlags { /** * Open the file for reading */ GNUNET_DISK_OPEN_READ = 1, /** * Open the file for writing */ GNUNET_DISK_OPEN_WRITE = 2, /** * Open the file for both reading and writing */ GNUNET_DISK_OPEN_READWRITE = 3, /** * Fail if file already exists */ GNUNET_DISK_OPEN_FAILIFEXISTS = 4, /** * Truncate file if it exists */ GNUNET_DISK_OPEN_TRUNCATE = 8, /** * Create file if it doesn't exist */ GNUNET_DISK_OPEN_CREATE = 16, /** * Append to the file */ GNUNET_DISK_OPEN_APPEND = 32 }; /** * Specifies what type of memory map is desired. */ enum GNUNET_DISK_MapType { /** * Read-only memory map. */ GNUNET_DISK_MAP_TYPE_READ = 1, /** * Write-able memory map. */ GNUNET_DISK_MAP_TYPE_WRITE = 2, /** * Read-write memory map. */ GNUNET_DISK_MAP_TYPE_READWRITE = 3 }; /** * File access permissions, UNIX-style. */ enum GNUNET_DISK_AccessPermissions { /** * Nobody is allowed to do anything to the file. */ GNUNET_DISK_PERM_NONE = 0, /** * Owner can read. */ GNUNET_DISK_PERM_USER_READ = 1, /** * Owner can write. */ GNUNET_DISK_PERM_USER_WRITE = 2, /** * Owner can execute. */ GNUNET_DISK_PERM_USER_EXEC = 4, /** * Group can read. */ GNUNET_DISK_PERM_GROUP_READ = 8, /** * Group can write. */ GNUNET_DISK_PERM_GROUP_WRITE = 16, /** * Group can execute. */ GNUNET_DISK_PERM_GROUP_EXEC = 32, /** * Everybody can read. */ GNUNET_DISK_PERM_OTHER_READ = 64, /** * Everybody can write. */ GNUNET_DISK_PERM_OTHER_WRITE = 128, /** * Everybody can execute. */ GNUNET_DISK_PERM_OTHER_EXEC = 256 }; /** * Constants for specifying how to seek. Do not change values or order, * some of the code depends on the specific numeric values! */ enum GNUNET_DISK_Seek { /** * Seek an absolute position (from the start of the file). */ GNUNET_DISK_SEEK_SET = 0, /** * Seek a relative position (from the current offset). */ GNUNET_DISK_SEEK_CUR = 1, /** * Seek an absolute position from the end of the file. */ GNUNET_DISK_SEEK_END = 2 }; /** * Enumeration identifying the two ends of a pipe. */ enum GNUNET_DISK_PipeEnd { /** * The reading-end of a pipe. */ GNUNET_DISK_PIPE_END_READ = 0, /** * The writing-end of a pipe. */ GNUNET_DISK_PIPE_END_WRITE = 1 }; /** * Checks whether a handle is invalid * * @param h handle to check * @return #GNUNET_YES if invalid, #GNUNET_NO if valid */ int GNUNET_DISK_handle_invalid (const struct GNUNET_DISK_FileHandle *h); /** * Check that fil corresponds to a filename * (of a file that exists and that is not a directory). * * @param fil filename to check * @return #GNUNET_YES if yes, #GNUNET_NO if not a file, #GNUNET_SYSERR if something * else (will print an error message in that case, too). */ int GNUNET_DISK_file_test (const char *fil); /** * Move a file out of the way (create a backup) by * renaming it to "orig.NUM~" where NUM is the smallest * number that is not used yet. * * @param fil name of the file to back up */ void GNUNET_DISK_file_backup (const char *fil); /** * Move the read/write pointer in a file * @param h handle of an open file * @param offset position to move to * @param whence specification to which position the offset parameter relates to * @return the new position on success, GNUNET_SYSERR otherwise */ off_t GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle *h, off_t offset, enum GNUNET_DISK_Seek whence); /** * Get the size of the file (or directory) of the given file (in * bytes). * * @param filename name of the file or directory * @param size set to the size of the file (or, * in the case of directories, the sum * of all sizes of files in the directory) * @param include_symbolic_links should symbolic links be * included? * @param single_file_mode #GNUNET_YES to only get size of one file * and return #GNUNET_SYSERR for directories. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_DISK_file_size (const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode); /** * Obtain some unique identifiers for the given file * that can be used to identify it in the local system. * This function is used between GNUnet processes to * quickly check if two files with the same absolute path * are actually identical. The two processes represent * the same peer but may communicate over the network * (and the file may be on an NFS volume). This function * may not be supported on all operating systems. * * @param filename name of the file * @param dev set to the device ID * @param ino set to the inode ID * @return GNUNET_OK on success */ int GNUNET_DISK_file_get_identifiers (const char *filename, uint64_t *dev, uint64_t *ino); /** * Create an (empty) temporary file on disk. If the given name is not * an absolute path, the current 'TMPDIR' will be prepended. In any case, * 6 random characters will be appended to the name to create a unique * filename. * * @param t component to use for the name; * does NOT contain "XXXXXX" or "/tmp/". * @return NULL on error, otherwise name of fresh * file on disk in directory for temporary files */ char * GNUNET_DISK_mktemp (const char *t); /** * Create an (empty) temporary directory on disk. If the given name is not an * absolute path, the current 'TMPDIR' will be prepended. In any case, 6 * random characters will be appended to the name to create a unique name. * * @param t component to use for the name; * does NOT contain "XXXXXX" or "/tmp/". * @return NULL on error, otherwise name of freshly created directory */ char * GNUNET_DISK_mkdtemp (const char *t); /** * Open a file. Note that the access permissions will only be * used if a new file is created and if the underlying operating * system supports the given permissions. * * @param fn file name to be opened * @param flags opening flags, a combination of GNUNET_DISK_OPEN_xxx bit flags * @param perm permissions for the newly created file, use * #GNUNET_DISK_PERM_NONE if a file could not be created by this * call (because of flags) * @return IO handle on success, NULL on error */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm); /** * Get the size of an open file. * * @param fh open file handle * @param size where to write size of the file * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_file_handle_size (struct GNUNET_DISK_FileHandle *fh, off_t *size); /** * Creates an interprocess channel * * @param blocking_read creates an asynchronous pipe for reading if set to #GNUNET_NO * @param blocking_write creates an asynchronous pipe for writing if set to #GNUNET_NO * @param inherit_read 1 to make read handle inheritable, 0 otherwise (NT only) * @param inherit_write 1 to make write handle inheritable, 0 otherwise (NT only) * @return handle to the new pipe, NULL on error */ struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int inherit_write); /** * Creates a pipe object from a couple of file descriptors. * Useful for wrapping existing pipe FDs. * * @param blocking_read creates an asynchronous pipe for reading if set to #GNUNET_NO * @param blocking_write creates an asynchronous pipe for writing if set to #GNUNET_NO * @param fd an array of two fd values. One of them may be -1 for read-only or write-only pipes * * @return handle to the new pipe, NULL on error */ struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]); /** * Closes an interprocess channel * @param p pipe * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p); /** * Closes one half of an interprocess channel * * @param p pipe to close end of * @param end which end of the pipe to close * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_pipe_close_end (struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end); /** * Detaches one of the ends from the pipe. * Detached end is a fully-functional FileHandle, it will * not be affected by anything you do with the pipe afterwards. * Each end of a pipe can only be detched from it once (i.e. * it is not duplicated). * * @param p pipe to detach an end from * @param end which end of the pipe to detach * @return Detached end on success, NULL on failure * (or if that end is not present or is closed). */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_detach_end (struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end); /** * Close an open file. * * @param h file handle * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h); /** * Get the handle to a particular pipe end * * @param p pipe * @param n end to access * @return handle for the respective end */ const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle (const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n); #if WINDOWS /** * Get a GNUnet file handle from a W32 handle (W32-only). * Do not call on non-W32 platforms (returns NULL). * * @param handle native handle * @return GNUnet file handle corresponding to the W32 handle */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_w32_handle (HANDLE osfh); #else /** * Update POSIX permissions mask of a file on disk. If both argumets * are #GNUNET_NO, the file is made world-read-write-executable (777). * * @param fn name of the file to update * @param require_uid_match #GNUNET_YES means 700 * @param require_gid_match #GNUNET_YES means 770 unless @a require_uid_match is set */ void GNUNET_DISK_fix_permissions (const char *fn, int require_uid_match, int require_gid_match); #endif /** * Get a handle from a native integer FD. * * @param fno native integer file descriptor * @return file handle corresponding to the descriptor */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd (int fno); /** * Get a handle from a native FD. * * @param fd native file descriptor * @return file handle corresponding to the descriptor */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_native (FILE *fd); /** * Read the contents of a binary file into a buffer. * * @param h handle to an open file * @param result the buffer to write the result to * @param len the maximum number of bytes to read * @return the number of bytes read on success, #GNUNET_SYSERR on failure */ ssize_t GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle *h, void *result, size_t len); /** * Read the contents of a binary file into a buffer. * Guarantees not to block (returns GNUNET_SYSERR and sets errno to EAGAIN * when no data can be read). * * @param h handle to an open file * @param result the buffer to write the result to * @param len the maximum number of bytes to read * @return the number of bytes read on success, #GNUNET_SYSERR on failure */ ssize_t GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h, void *result, size_t len); /** * Read the contents of a binary file into a buffer. * * @param fn file name * @param result the buffer to write the result to * @param len the maximum number of bytes to read * @return number of bytes read, #GNUNET_SYSERR on failure */ ssize_t GNUNET_DISK_fn_read (const char *fn, void *result, size_t len); /** * Write a buffer to a file. * * @param h handle to open file * @param buffer the data to write * @param n number of bytes to write * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n); /** * Write a buffer to a file, blocking, if necessary. * * @param h handle to open file * @param buffer the data to write * @param n number of bytes to write * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t GNUNET_DISK_file_write_blocking (const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n); /** * Write a buffer to a file. If the file is longer than * the given buffer size, it will be truncated. * * @param fn file name * @param buffer the data to write * @param n number of bytes to write * @param mode file permissions * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t GNUNET_DISK_fn_write (const char *fn, const void *buffer, size_t n, enum GNUNET_DISK_AccessPermissions mode); /** * Copy a file. * * @param src file to copy * @param dst destination file name * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_file_copy (const char *src, const char *dst); /** * Scan a directory for files. * * @param dir_name the name of the directory * @param callback the method to call for each file * @param callback_cls closure for @a callback * @return the number of files found, -1 on error */ int GNUNET_DISK_directory_scan (const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls); /** * Opaque handle used for iterating over a directory. */ struct GNUNET_DISK_DirectoryIterator; /** * Function called to iterate over a directory. * * @param cls closure * @param di argument to pass to #GNUNET_DISK_directory_iterator_next to * get called on the next entry (or finish cleanly); * NULL on error (will be the last call in that case) * @param filename complete filename (absolute path) * @param dirname directory name (absolute path) */ typedef void (*GNUNET_DISK_DirectoryIteratorCallback) (void *cls, struct GNUNET_DISK_DirectoryIterator *di, const char *filename, const char *dirname); /** * This function must be called during the DiskIteratorCallback * (exactly once) to schedule the task to process the next * filename in the directory (if there is one). * * @param iter opaque handle for the iterator * @param can set to #GNUNET_YES to terminate the iteration early * @return #GNUNET_YES if iteration will continue, * #GNUNET_NO if this was the last entry (and iteration is complete), * #GNUNET_SYSERR if @a can was #GNUNET_YES */ int GNUNET_DISK_directory_iterator_next (struct GNUNET_DISK_DirectoryIterator *iter, int can); /** * Scan a directory for files using the scheduler to run a task for * each entry. The name of the directory must be expanded first (!). * If a scheduler does not need to be used, GNUNET_DISK_directory_scan * may provide a simpler API. * * @param prio priority to use * @param dir_name the name of the directory * @param callback the method to call for each file * @param callback_cls closure for @a callback * @return #GNUNET_YES if directory is not empty and @a callback * will be called later, #GNUNET_NO otherwise, #GNUNET_SYSERR on error. */ int GNUNET_DISK_directory_iterator_start (enum GNUNET_SCHEDULER_Priority prio, const char *dir_name, GNUNET_DISK_DirectoryIteratorCallback callback, void *callback_cls); /** * Create the directory structure for storing * a file. * * @param filename name of a file in the directory * @returns #GNUNET_OK on success, #GNUNET_SYSERR on failure, * #GNUNET_NO if directory exists but is not writeable */ int GNUNET_DISK_directory_create_for_file (const char *filename); /** * Test if @a fil is a directory and listable. Optionally, also check if the * directory is readable. Will not print an error message if the directory does * not exist. Will log errors if #GNUNET_SYSERR is returned (i.e., a file exists * with the same name). * * @param fil filename to test * @param is_readable #GNUNET_YES to additionally check if @a fil is readable; * #GNUNET_NO to disable this check * @return #GNUNET_YES if yes, #GNUNET_NO if not; #GNUNET_SYSERR if it * does not exist or `stat`ed */ int GNUNET_DISK_directory_test (const char *fil, int is_readable); /** * Remove all files in a directory (rm -rf). Call with * caution. * * @param filename the file to remove * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_directory_remove (const char *filename); /** * Implementation of "mkdir -p" * * @param dir the directory to create * @returns #GNUNET_SYSERR on failure, #GNUNET_OK otherwise */ int GNUNET_DISK_directory_create (const char *dir); /** * Lock a part of a file. * * @param fh file handle * @param lock_start absolute position from where to lock * @param lock_end absolute position until where to lock * @param excl #GNUNET_YES for an exclusive lock * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_file_lock (struct GNUNET_DISK_FileHandle *fh, off_t lock_start, off_t lock_end, int excl); /** * Unlock a part of a file. * * @param fh file handle * @param unlock_start absolute position from where to unlock * @param unlock_end absolute position until where to unlock * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_file_unlock (struct GNUNET_DISK_FileHandle *fh, off_t unlock_start, off_t unlock_end); /** * @brief Removes special characters as ':' from a filename. * @param fn the filename to canonicalize */ void GNUNET_DISK_filename_canonicalize (char *fn); /** * @brief Change owner of a file * @param filename file to change * @param user new owner of the file * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_DISK_file_change_owner (const char *filename, const char *user); /** * Opaque handle for a memory-mapping operation. */ struct GNUNET_DISK_MapHandle; /** * Map a file into memory * @param h open file handle * @param m handle to the new mapping (will be set) * @param access access specification, GNUNET_DISK_MAP_TYPE_xxx * @param len size of the mapping * @return pointer to the mapped memory region, NULL on failure */ void * GNUNET_DISK_file_map (const struct GNUNET_DISK_FileHandle *h, struct GNUNET_DISK_MapHandle **m, enum GNUNET_DISK_MapType access, size_t len); /** * Unmap a file * * @param h mapping handle * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_file_unmap (struct GNUNET_DISK_MapHandle *h); /** * Write file changes to disk * @param h handle to an open file * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_DISK_LIB_H */ #endif /* end of gnunet_disk_lib.h */ gnunet-0.10.1/src/include/platform.h0000644000175000017500000001274012262754601014232 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/platform.h * @brief plaform specific includes and defines * @author Nils Durner * @author Christian Grothoff * This file should never be included by installed * header files (those starting with "gnunet_"). */ #ifndef PLATFORM_H #define PLATFORM_H #ifndef HAVE_USED_CONFIG_H #define HAVE_USED_CONFIG_H #if HAVE_CONFIG_H #include "gnunet_config.h" #endif #endif #ifdef WINDOWS #define BREAKPOINT asm("int $3;"); #define GNUNET_SIGCHLD 17 #else #define BREAKPOINT #define GNUNET_SIGCHLD SIGCHLD #endif #ifdef HAVE_SYS_TYPES_H #include #endif /** * These may be expensive, but good for debugging... */ #define ALLOW_EXTRA_CHECKS GNUNET_YES /** * For strptime (glibc2 needs this). */ #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 499 #endif #ifndef _REENTRANT #define _REENTRANT #endif /* configuration options */ #define VERBOSE_STATS 0 #ifdef CYGWIN #include #endif #ifdef _MSC_VER #ifndef FD_SETSIZE #define FD_SETSIZE 1024 #endif #include #include #else #ifndef MINGW #include #include #include #if HAVE_NETINET_IN_H #include #endif #if HAVE_NETINET_IN_SYSTM_H #include #endif #if HAVE_NETINET_IP_H #include /* superset of previous */ #endif #include #include #include #include #include #include #else #include "winproc.h" #endif #endif #include #include #include #include #include #include #include #include #ifdef WINDOWS #include /* for alloca(), on other OSes it's in stdlib.h */ #endif #ifdef HAVE_MALLOC_H #include /* for mallinfo on GNU */ #endif #ifndef _MSC_VER #include /* KLB_FIX */ #endif #include #include #ifndef _MSC_VER #include /* KLB_FIX */ #endif #include #include #if HAVE_SYS_PARAM_H #include #endif #if TIME_WITH_SYS_TIME #include #include #else #if HAVE_SYS_TIME_H #include #else #include #endif #endif #ifdef SOMEBSD #include #endif #ifdef FREEBSD #include #endif #ifdef DARWIN #include #include #include #endif #if defined(LINUX) || defined(GNU) #include #endif #ifdef SOLARIS #include #include #include #include #endif #if HAVE_UCRED_H #include #endif #if HAVE_SYS_UCRED_H #include #endif #ifdef CYGWIN #include #include #endif #if HAVE_IFADDRS_H #include #endif #include #include #if HAVE_VFORK_H #include #endif #include #if HAVE_SYS_RESOURCE_H #include #endif #if HAVE_ENDIAN_H #include #endif #if HAVE_SYS_ENDIAN_H #include #endif #include "plibc.h" #include #ifndef FRAMEWORK_BUILD #include "gettext.h" /** * GNU gettext support macro. */ #define _(String) dgettext("gnunet",String) #define LIBEXTRACTOR_GETTEXT_DOMAIN "libextractor" #else #include "libintlemu.h" #define _(String) dgettext("org.gnunet.gnunet",String) #define LIBEXTRACTOR_GETTEXT_DOMAIN "org.gnunet.libextractor" #endif #ifdef CYGWIN #define SIOCGIFCONF _IOW('s', 100, struct ifconf) /* get if list */ #define SIOCGIFFLAGS _IOW('s', 101, struct ifreq) /* Get if flags */ #define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ #endif #ifndef MINGW #include #endif #ifdef FREEBSD #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN #endif #ifdef DARWIN #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN /* not available on darwin, override configure */ #undef HAVE_STAT64 #undef HAVE_MREMAP #endif #if !HAVE_ATOLL long long atoll (const char *nptr); #endif #if ENABLE_NLS #include "langinfo.h" #endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)(-1)) #endif #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif /** * AI_NUMERICSERV not defined in windows. Then we just do without. */ #ifndef AI_NUMERICSERV #define AI_NUMERICSERV 0 #endif #if defined(__sparc__) #define MAKE_UNALIGNED(val) ({ __typeof__((val)) __tmp; memmove(&__tmp, &(val), sizeof((val))); __tmp; }) #else #define MAKE_UNALIGNED(val) val #endif #if WINDOWS #define FDTYPE HANDLE #define SOCKTYPE SOCKET #else #define FDTYPE int #define SOCKTYPE int #endif /** * The termination signal */ #define GNUNET_TERM_SIG SIGTERM #endif gnunet-0.10.1/src/include/gnunet_crypto_lib.h0000644000175000017500000011355012320724374016134 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_crypto_lib.h * @brief cryptographic primitives for GNUnet * * @author Christian Grothoff * @author Krista Bennett * @author Gerd Knorr * @author Ioana Patrascu * @author Tzvetan Horozov * * @defgroup crypto Cryptographic operations * @defgroup hash Hashing and operations on hashes */ #ifndef GNUNET_CRYPTO_LIB_H #define GNUNET_CRYPTO_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * @brief A 512-bit hashcode */ struct GNUNET_HashCode; /** * The identity of the host (wraps the signing key of the peer). */ struct GNUNET_PeerIdentity; #include "gnunet_common.h" #include "gnunet_scheduler_lib.h" #include /** * @brief A 512-bit hashcode */ struct GNUNET_HashCode { uint32_t bits[512 / 8 / sizeof (uint32_t)]; /* = 16 */ }; /** * Maximum length of an ECC signature. * Note: round up to multiple of 8 minus 2 for alignment. */ #define GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH 126 /** * Desired quality level for random numbers. * @ingroup crypto */ enum GNUNET_CRYPTO_Quality { /** * No good quality of the operation is needed (i.e., * random numbers can be pseudo-random). * @ingroup crypto */ GNUNET_CRYPTO_QUALITY_WEAK, /** * High-quality operations are desired. * @ingroup crypto */ GNUNET_CRYPTO_QUALITY_STRONG, /** * Randomness for IVs etc. is required. * @ingroup crypto */ GNUNET_CRYPTO_QUALITY_NONCE }; /** * @brief length of the sessionkey in bytes (256 BIT sessionkey) */ #define GNUNET_CRYPTO_AES_KEY_LENGTH (256/8) /** * Length of a hash value */ #define GNUNET_CRYPTO_HASH_LENGTH (512/8) /** * How many characters (without 0-terminator) are our ASCII-encoded * public keys (ECDSA/EDDSA/ECDHE). */ #define GNUNET_CRYPTO_PKEY_ASCII_LENGTH 52 /** * @brief 0-terminated ASCII encoding of a struct GNUNET_HashCode. */ struct GNUNET_CRYPTO_HashAsciiEncoded { unsigned char encoding[104]; }; GNUNET_NETWORK_STRUCT_BEGIN /** * @brief header of what an ECC signature signs * this must be followed by "size - 8" bytes of * the actual signed data */ struct GNUNET_CRYPTO_EccSignaturePurpose { /** * How many bytes does this signature sign? * (including this purpose header); in network * byte order (!). */ uint32_t size GNUNET_PACKED; /** * What does this signature vouch for? This * must contain a GNUNET_SIGNATURE_PURPOSE_XXX * constant (from gnunet_signatures.h). In * network byte order! */ uint32_t purpose GNUNET_PACKED; }; /** * @brief an ECC signature using EdDSA. * See https://gnunet.org/ed25519 */ struct GNUNET_CRYPTO_EddsaSignature { /** * R value. */ unsigned char r[256 / 8]; /** * S value. */ unsigned char s[256 / 8]; }; /** * @brief an ECC signature using ECDSA */ struct GNUNET_CRYPTO_EcdsaSignature { /** * R value. */ unsigned char r[256 / 8]; /** * S value. */ unsigned char s[256 / 8]; }; /** * Public ECC key (always for Curve25519) encoded in a format suitable * for network transmission and EdDSA signatures. */ struct GNUNET_CRYPTO_EddsaPublicKey { /** * Q consists of an x- and a y-value, each mod p (256 bits), given * here in affine coordinates and Ed25519 standard compact format. */ unsigned char q_y[256 / 8]; }; /** * Public ECC key (always for Curve25519) encoded in a format suitable * for network transmission and ECDSA signatures. */ struct GNUNET_CRYPTO_EcdsaPublicKey { /** * Q consists of an x- and a y-value, each mod p (256 bits), given * here in affine coordinates and Ed25519 standard compact format. */ unsigned char q_y[256 / 8]; }; /** * The identity of the host (wraps the signing key of the peer). */ struct GNUNET_PeerIdentity { struct GNUNET_CRYPTO_EddsaPublicKey public_key; }; /** * Public ECC key (always for Curve25519) encoded in a format suitable * for network transmission and encryption (ECDH), * See http://cr.yp.to/ecdh.html */ struct GNUNET_CRYPTO_EcdhePublicKey { /** * Q consists of an x- and a y-value, each mod p (256 bits), given * here in affine coordinates and Ed25519 standard compact format. */ unsigned char q_y[256 / 8]; }; /** * Private ECC key encoded for transmission. To be used only for ECDH * key exchange (ECDHE to be precise). */ struct GNUNET_CRYPTO_EcdhePrivateKey { /** * d is a value mod n, where n has at most 256 bits. */ unsigned char d[256 / 8]; }; /** * Private ECC key encoded for transmission. To be used only for ECDSA * signatures. */ struct GNUNET_CRYPTO_EcdsaPrivateKey { /** * d is a value mod n, where n has at most 256 bits. */ unsigned char d[256 / 8]; }; /** * Private ECC key encoded for transmission. To be used only for EdDSA * signatures. */ struct GNUNET_CRYPTO_EddsaPrivateKey { /** * d is a value mod n, where n has at most 256 bits. */ unsigned char d[256 / 8]; }; /** * @brief type for session keys */ struct GNUNET_CRYPTO_SymmetricSessionKey { /** * Actual key for AES. */ unsigned char aes_key[GNUNET_CRYPTO_AES_KEY_LENGTH]; /** * Actual key for TwoFish. */ unsigned char twofish_key[GNUNET_CRYPTO_AES_KEY_LENGTH]; }; GNUNET_NETWORK_STRUCT_END /** * @brief IV for sym cipher * * NOTE: must be smaller (!) in size than the * `struct GNUNET_HashCode`. */ struct GNUNET_CRYPTO_SymmetricInitializationVector { unsigned char aes_iv[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; unsigned char twofish_iv[GNUNET_CRYPTO_AES_KEY_LENGTH / 2]; }; /** * @brief type for (message) authentication keys */ struct GNUNET_CRYPTO_AuthKey { unsigned char key[GNUNET_CRYPTO_HASH_LENGTH]; }; /** * Size of paillier plain texts and public keys. * Private keys and ciphertexts are twice this size. */ #define GNUNET_CRYPTO_PAILLIER_BITS 2048 /** * Paillier public key. */ struct GNUNET_CRYPTO_PaillierPublicKey { /** * N value. */ unsigned char n[GNUNET_CRYPTO_PAILLIER_BITS / 8]; }; /** * Paillier public key. */ struct GNUNET_CRYPTO_PaillierPrivateKey { /** * Lambda-component of the private key. */ unsigned char lambda[GNUNET_CRYPTO_PAILLIER_BITS / 8]; /** * Mu-component of the private key. */ unsigned char mu[GNUNET_CRYPTO_PAILLIER_BITS / 8]; }; /** * Paillier ciphertext. */ struct GNUNET_CRYPTO_PaillierCiphertext { /** * guaranteed minimum number of homomorphic operations with this ciphertext */ int32_t remaining_ops GNUNET_PACKED; /** * The bits of the ciphertext. */ unsigned char bits[GNUNET_CRYPTO_PAILLIER_BITS * 2 / 8]; }; /* **************** Functions and Macros ************* */ /** * @ingroup crypto * Seed a weak random generator. Only #GNUNET_CRYPTO_QUALITY_WEAK-mode generator * can be seeded. * * @param seed the seed to use */ void GNUNET_CRYPTO_seed_weak_random (int32_t seed); /** * Perform an incremental step in a CRC16 (for TCP/IP) calculation. * * @param sum current sum, initially 0 * @param buf buffer to calculate CRC over (must be 16-bit aligned) * @param len number of bytes in @a buf, must be multiple of 2 * @return updated crc sum (must be subjected to #GNUNET_CRYPTO_crc16_finish to get actual crc16) */ uint32_t GNUNET_CRYPTO_crc16_step (uint32_t sum, const void *buf, size_t len); /** * Convert results from GNUNET_CRYPTO_crc16_step to final crc16. * * @param sum cummulative sum * @return crc16 value */ uint16_t GNUNET_CRYPTO_crc16_finish (uint32_t sum); /** * @ingroup hash * Calculate the checksum of a buffer in one step. * * @param buf buffer to calculate CRC over (must be 16-bit aligned) * @param len number of bytes in @a buf, must be multiple of 2 * @return crc16 value */ uint16_t GNUNET_CRYPTO_crc16_n (const void *buf, size_t len); /** * @ingroup hash * Compute the CRC32 checksum for the first len * bytes of the buffer. * * @param buf the data over which we're taking the CRC * @param len the length of the buffer @a buf in bytes * @return the resulting CRC32 checksum */ int32_t GNUNET_CRYPTO_crc32_n (const void *buf, size_t len); /** * @ingroup crypto * Fill block with a random values. * * @param mode desired quality of the random number * @param buffer the buffer to fill * @param length buffer length */ void GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length); /** * @ingroup crypto * Produce a random value. * * @param mode desired quality of the random number * @param i the upper limit (exclusive) for the random number * @return a random value in the interval [0,@a i) (exclusive). */ uint32_t GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i); /** * @ingroup crypto * Random on unsigned 64-bit values. * * @param mode desired quality of the random number * @param max value returned will be in range [0,@a max) (exclusive) * @return random 64-bit number */ uint64_t GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max); /** * @ingroup crypto * Get an array with a random permutation of the * numbers 0...n-1. * @param mode #GNUNET_CRYPTO_QUALITY_STRONG if the strong (but expensive) PRNG should be used, * #GNUNET_CRYPTO_QUALITY_WEAK or #GNUNET_CRYPTO_QUALITY_NONCE otherwise * @param n the size of the array * @return the permutation array (allocated from heap) */ unsigned int * GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n); /** * @ingroup crypto * Create a new random session key. * * @param key key to initialize */ void GNUNET_CRYPTO_symmetric_create_session_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key); /** * @ingroup crypto * Encrypt a block using a symmetric sessionkey. * * @param block the block to encrypt * @param size the size of the @a block * @param sessionkey the key used to encrypt * @param iv the initialization vector to use, use INITVALUE * for streams. * @return the size of the encrypted block, -1 for errors */ ssize_t GNUNET_CRYPTO_symmetric_encrypt (const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result); /** * @ingroup crypto * Decrypt a given block using a symmetric sessionkey. * * @param block the data to decrypt, encoded as returned by encrypt * @param size how big is the block? * @param sessionkey the key used to decrypt * @param iv the initialization vector to use * @param result address to store the result at * @return -1 on failure, size of decrypted block on success */ ssize_t GNUNET_CRYPTO_symmetric_decrypt (const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result); /** * @ingroup crypto * @brief Derive an IV * @param iv initialization vector * @param skey session key * @param salt salt for the derivation * @param salt_len size of the @a salt * @param ... pairs of void * & size_t for context chunks, terminated by NULL */ void GNUNET_CRYPTO_symmetric_derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, const void *salt, size_t salt_len, ...); /** * @brief Derive an IV * @param iv initialization vector * @param skey session key * @param salt salt for the derivation * @param salt_len size of the @a salt * @param argp pairs of void * & size_t for context chunks, terminated by NULL */ void GNUNET_CRYPTO_symmetric_derive_iv_v (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, const void *salt, size_t salt_len, va_list argp); /** * @ingroup hash * Convert hash to ASCII encoding. * @param block the hash code * @param result where to store the encoding (struct GNUNET_CRYPTO_HashAsciiEncoded can be * safely cast to char*, a '\\0' termination is set). */ void GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode * block, struct GNUNET_CRYPTO_HashAsciiEncoded *result); /** * @ingroup hash * Convert ASCII encoding back to a 'struct GNUNET_HashCode' * * @param enc the encoding * @param enclen number of characters in @a enc (without 0-terminator, which can be missing) * @param result where to store the hash code * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding */ int GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, struct GNUNET_HashCode *result); /** * @ingroup hash * Convert ASCII encoding back to `struct GNUNET_HashCode` * * @param enc the encoding * @param result where to store the hash code * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding */ #define GNUNET_CRYPTO_hash_from_string(enc, result) \ GNUNET_CRYPTO_hash_from_string2 (enc, strlen(enc), result) /** * @ingroup hash * * Compute the distance between 2 hashcodes. The * computation must be fast, not involve @a a[0] or @a a[4] (they're used * elsewhere), and be somewhat consistent. And of course, the result * should be a positive number. * * @param a some hash code * @param b some hash code * @return number between 0 and UINT32_MAX */ uint32_t GNUNET_CRYPTO_hash_distance_u32 (const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b); /** * @ingroup hash * Compute hash of a given block. * * @param block the data to hash * @param size size of the @a block * @param ret pointer to where to write the hashcode */ void GNUNET_CRYPTO_hash (const void *block, size_t size, struct GNUNET_HashCode * ret); /** * @ingroup hash * Calculate HMAC of a message (RFC 2104) * * @param key secret key * @param plaintext input plaintext * @param plaintext_len length of @a plaintext * @param hmac where to store the hmac */ void GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode * hmac); /** * Function called once the hash computation over the * specified file has completed. * * @param cls closure * @param res resulting hash, NULL on error */ typedef void (*GNUNET_CRYPTO_HashCompletedCallback) (void *cls, const struct GNUNET_HashCode *res); /** * Handle to file hashing operation. */ struct GNUNET_CRYPTO_FileHashContext; /** * @ingroup hash * Compute the hash of an entire file. * * @param priority scheduling priority to use * @param filename name of file to hash * @param blocksize number of bytes to process in one task * @param callback function to call upon completion * @param callback_cls closure for @a callback * @return NULL on (immediate) errror */ struct GNUNET_CRYPTO_FileHashContext * GNUNET_CRYPTO_hash_file (enum GNUNET_SCHEDULER_Priority priority, const char *filename, size_t blocksize, GNUNET_CRYPTO_HashCompletedCallback callback, void *callback_cls); /** * Cancel a file hashing operation. * * @param fhc operation to cancel (callback must not yet have been invoked) */ void GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc); /** * @ingroup hash * Create a random hash code. * * @param mode desired quality level * @param result hash code that is randomized */ void GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result); /** * @ingroup hash * compute @a result = @a b - @a a * * @param a some hash code * @param b some hash code * @param result set to @a b - @a a */ void GNUNET_CRYPTO_hash_difference (const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b, struct GNUNET_HashCode *result); /** * @ingroup hash * compute @a result = @a a + @a delta * * @param a some hash code * @param delta some hash code * @param result set to @a a + @a delta */ void GNUNET_CRYPTO_hash_sum (const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *delta, struct GNUNET_HashCode *result); /** * @ingroup hash * compute result = a ^ b * * @param a some hash code * @param b some hash code * @param result set to @a a ^ @a b */ void GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode * a, const struct GNUNET_HashCode * b, struct GNUNET_HashCode * result); /** * @ingroup hash * Convert a hashcode into a key. * * @param hc hash code that serves to generate the key * @param skey set to a valid session key * @param iv set to a valid initialization vector */ void GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode * hc, struct GNUNET_CRYPTO_SymmetricSessionKey *skey, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv); /** * @ingroup hash * Obtain a bit from a hashcode. * * @param code the `struct GNUNET_HashCode` to index bit-wise * @param bit index into the hashcode, [0...159] * @return Bit \a bit from hashcode \a code, -1 for invalid index */ int GNUNET_CRYPTO_hash_get_bit (const struct GNUNET_HashCode *code, unsigned int bit); /** * @ingroup hash * Determine how many low order bits match in two * `struct GNUNET_HashCodes`. i.e. - 010011 and 011111 share * the first two lowest order bits, and therefore the * return value is two (NOT XOR distance, nor how many * bits match absolutely!). * * @param first the first hashcode * @param second the hashcode to compare first to * @return the number of bits that match */ unsigned int GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode *first, const struct GNUNET_HashCode *second); /** * @ingroup hash * Compare function for HashCodes, producing a total ordering * of all hashcodes. * * @param h1 some hash code * @param h2 some hash code * @return 1 if @a h1 > @a h2, -1 if @a h1 < @a h2 and 0 if @a h1 == @a h2. */ int GNUNET_CRYPTO_hash_cmp (const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2); /** * @ingroup hash * Find out which of the two GNUNET_CRYPTO_hash codes is closer to target * in the XOR metric (Kademlia). * * @param h1 some hash code * @param h2 some hash code * @param target some hash code * @return -1 if @a h1 is closer, 1 if @a h2 is closer and 0 if @a h1== @a h2. */ int GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2, const struct GNUNET_HashCode *target); /** * @ingroup hash * @brief Derive an authentication key * @param key authentication key * @param rkey root key * @param salt salt * @param salt_len size of the salt * @param argp pair of void * & size_t for context chunks, terminated by NULL */ void GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, const void *salt, size_t salt_len, va_list argp); /** * @ingroup hash * @brief Derive an authentication key * @param key authentication key * @param rkey root key * @param salt salt * @param salt_len size of the salt * @param ... pair of void * & size_t for context chunks, terminated by NULL */ void GNUNET_CRYPTO_hmac_derive_key (struct GNUNET_CRYPTO_AuthKey *key, const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, const void *salt, size_t salt_len, ...); /** * @ingroup hash * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... * @param xts salt * @param xts_len length of @a xts * @param skm source key material * @param skm_len length of @a skm * @param ... pair of void * & size_t for context chunks, terminated by NULL * @return #GNUNET_YES on success */ int GNUNET_CRYPTO_hkdf (void *result, size_t out_len, int xtr_algo, int prf_algo, const void *xts, size_t xts_len, const void *skm, size_t skm_len, ...); /** * @ingroup hash * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... * @param xts salt * @param xts_len length of @a xts * @param skm source key material * @param skm_len length of @a skm * @param argp va_list of void * & size_t pairs for context chunks * @return #GNUNET_YES on success */ int GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, const void *xts, size_t xts_len, const void *skm, size_t skm_len, va_list argp); /** * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xts salt * @param xts_len length of @a xts * @param skm source key material * @param skm_len length of @a skm * @param argp va_list of void * & size_t pairs for context chunks * @return #GNUNET_YES on success */ int GNUNET_CRYPTO_kdf_v (void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len, va_list argp); /** * @ingroup hash * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xts salt * @param xts_len length of @a xts * @param skm source key material * @param skm_len length of @a skm * @param ... void * & size_t pairs for context chunks * @return #GNUNET_YES on success */ int GNUNET_CRYPTO_kdf (void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len, ...); /** * @ingroup crypto * Extract the public key for the given private key. * * @param priv the private key * @param pub where to write the public key */ void GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_EcdsaPublicKey *pub); /** * @ingroup crypto * Extract the public key for the given private key. * * @param priv the private key * @param pub where to write the public key */ void GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub); /** * @ingroup crypto * Extract the public key for the given private key. * * @param priv the private key * @param pub where to write the public key */ void GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, struct GNUNET_CRYPTO_EcdhePublicKey *pub); /** * Convert a public key to a string. * * @param pub key to convert * @return string representing @a pub */ char * GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub); /** * Convert a public key to a string. * * @param pub key to convert * @return string representing @a pub */ char * GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub); /** * Convert a string representing a public key to a public key. * * @param enc encoded public key * @param enclen number of bytes in @a enc (without 0-terminator) * @param pub where to store the public key * @return #GNUNET_OK on success */ int GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc, size_t enclen, struct GNUNET_CRYPTO_EcdsaPublicKey *pub); /** * Convert a string representing a public key to a public key. * * @param enc encoded public key * @param enclen number of bytes in @a enc (without 0-terminator) * @param pub where to store the public key * @return #GNUNET_OK on success */ int GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub); /** * @ingroup crypto * Create a new private key by reading it from a file. If the * files does not exist, create a new key and write it to the * file. Caller must free return value. Note that this function * can not guarantee that another process might not be trying * the same operation on the same file at the same time. * If the contents of the file * are invalid the old file is deleted and a fresh key is * created. * * @param filename name of file to use to store the key * @return new private key, NULL on error (for example, * permission denied); free using #GNUNET_free */ struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename); /** * @ingroup crypto * Create a new private key by reading it from a file. If the * files does not exist, create a new key and write it to the * file. Caller must free return value. Note that this function * can not guarantee that another process might not be trying * the same operation on the same file at the same time. * If the contents of the file * are invalid the old file is deleted and a fresh key is * created. * * @param filename name of file to use to store the key * @return new private key, NULL on error (for example, * permission denied); free using #GNUNET_free */ struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename); struct GNUNET_CONFIGURATION_Handle; /** * @ingroup crypto * Create a new private key by reading our peer's key from * the file specified in the configuration. * * @param cfg the configuration to use * @return new private key, NULL on error (for example, * permission denied); free using #GNUNET_free */ struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * @ingroup crypto * Create a new private key. Caller must free return value. * * @return fresh private key; free using #GNUNET_free */ struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_create (void); /** * @ingroup crypto * Create a new private key. Caller must free return value. * * @return fresh private key; free using #GNUNET_free */ struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create (void); /** * @ingroup crypto * Create a new private key. Caller must free return value. * * @return fresh private key; free using #GNUNET_free */ struct GNUNET_CRYPTO_EcdhePrivateKey * GNUNET_CRYPTO_ecdhe_key_create (void); /** * @ingroup crypto * Clear memory that was used to store a private key. * * @param pk location of the key */ void GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk); /** * @ingroup crypto * Clear memory that was used to store a private key. * * @param pk location of the key */ void GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk); /** * @ingroup crypto * Clear memory that was used to store a private key. * * @param pk location of the key */ void GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk); /** * @ingroup crypto * Get the shared private key we use for anonymous users. * * @return "anonymous" private key; do not free */ const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_get_anonymous (void); /** * @ingroup crypto * Setup a hostkey file for a peer given the name of the * configuration file (!). This function is used so that * at a later point code can be certain that reading a * hostkey is fast (for example in time-dependent testcases). * * @param cfg_name name of the configuration file to use */ void GNUNET_CRYPTO_eddsa_setup_hostkey (const char *cfg_name); /** * @ingroup crypto * Retrieve the identity of the host's peer. * * @param cfg configuration to use * @param dst pointer to where to write the peer identity * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity * could not be retrieved */ int GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst); /** * Compare two Peer Identities. * * @param first first peer identity * @param second second peer identity * @return bigger than 0 if first > second, * 0 if they are the same * smaller than 0 if second > first */ int GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second); /** * @ingroup crypto * Derive key material from a public and a private ECC key. * * @param priv private key to use for the ECDH (x) * @param pub public key to use for the ECDH (yG) * @param key_material where to write the key material (xyG) * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material); /** * @ingroup crypto * EdDSA sign a given block. * * @param priv private key to use for the signing * @param purpose what to sign (size, purpose) * @param sig where to write the signature * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig); /** * @ingroup crypto * ECDSA Sign a given block. * * @param priv private key to use for the signing * @param purpose what to sign (size, purpose) * @param sig where to write the signature * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EcdsaSignature *sig); /** * @ingroup crypto * Verify EdDSA signature. * * @param purpose what is the purpose that the signature should have? * @param validate block to validate (size, purpose, data) * @param sig signature that is being validated * @param pub public key of the signer * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid */ int GNUNET_CRYPTO_eddsa_verify (uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub); /** * @ingroup crypto * Verify ECDSA signature. * * @param purpose what is the purpose that the signature should have? * @param validate block to validate (size, purpose, data) * @param sig signature that is being validated * @param pub public key of the signer * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid */ int GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EcdsaSignature *sig, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub); /** * @ingroup crypto * Derive a private key from a given private key and a label. * Essentially calculates a private key 'h = H(l,P) * d mod n' * where n is the size of the ECC group and P is the public * key associated with the private key 'd'. * * @param priv original private key * @param label label to use for key deriviation * @param context additional context to use for HKDF of 'h'; * typically the name of the subsystem/application * @return derived private key */ struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const char *label, const char *context); /** * @ingroup crypto * Derive a public key from a given public key and a label. * Essentially calculates a public key 'V = H(l,P) * P'. * * @param pub original public key * @param label label to use for key deriviation * @param context additional context to use for HKDF of 'h'. * typically the name of the subsystem/application * @param result where to write the derived public key */ void GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, const char *context, struct GNUNET_CRYPTO_EcdsaPublicKey *result); /** * Output the given MPI value to the given buffer in network * byte order. The MPI @a val may not be negative. * * @param buf where to output to * @param size number of bytes in @a buf * @param val value to write to @a buf */ void GNUNET_CRYPTO_mpi_print_unsigned (void *buf, size_t size, gcry_mpi_t val); /** * Convert data buffer into MPI value. * The buffer is interpreted as network * byte order, unsigned integer. * * @param result where to store MPI value (allocated) * @param data raw data (GCRYMPI_FMT_USG) * @param size number of bytes in @a data */ void GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result, const void *data, size_t size); /** * Create a freshly generated paillier public key. * * @param[out] public_key Where to store the public key? * @param[out] private_key Where to store the private key? */ void GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_key, struct GNUNET_CRYPTO_PaillierPrivateKey *private_key); /** * Encrypt a plaintext with a paillier public key. * * @param public_key Public key to use. * @param m Plaintext to encrypt. * @param desired_ops How many homomorphic ops the caller intends to use * @param[out] ciphertext Encrytion of @a plaintext with @a public_key. * @return guaranteed number of supported homomorphic operations >= 1, * or desired_ops, in case that is lower, * or -1 if less than one homomorphic operation is possible */ int GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const gcry_mpi_t m, int desired_ops, struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext); /** * Decrypt a paillier ciphertext with a private key. * * @param private_key Private key to use for decryption. * @param public_key Public key to use for decryption. * @param ciphertext Ciphertext to decrypt. * @param[out] m Decryption of @a ciphertext with @private_key. */ void GNUNET_CRYPTO_paillier_decrypt (const struct GNUNET_CRYPTO_PaillierPrivateKey *private_key, const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext, gcry_mpi_t m); /** * Compute a ciphertext that represents the sum of the plaintext in @a x1 and @a x2 * * Note that this operation can only be done a finite number of times * before an overflow occurs. * * @param public_key Public key to use for encryption. * @param c1 Paillier cipher text. * @param c2 Paillier cipher text. * @param[out] result Result of the homomorphic operation. * @return #GNUNET_OK if the result could be computed, * #GNUNET_SYSERR if no more homomorphic operations are remaining. */ int GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const struct GNUNET_CRYPTO_PaillierCiphertext *c1, const struct GNUNET_CRYPTO_PaillierCiphertext *c2, struct GNUNET_CRYPTO_PaillierCiphertext *result); /** * Get the number of remaining supported homomorphic operations. * * @param c Paillier cipher text. * @return the number of remaining homomorphic operations */ int GNUNET_CRYPTO_paillier_hom_get_remaining (const struct GNUNET_CRYPTO_PaillierCiphertext *c); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_CRYPTO_LIB_H */ #endif /* end of gnunet_crypto_lib.h */ gnunet-0.10.1/src/include/gnunet_namecache_plugin.h0000644000175000017500000000535412227705277017261 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_namecache_plugin.h * @brief plugin API for the namecache database backend * @author Christian Grothoff */ #ifndef GNUNET_NAMECACHE_PLUGIN_H #define GNUNET_NAMECACHE_PLUGIN_H #include "gnunet_util_lib.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Function called for matching blocks. * * @param cls closure * @param block lookup result */ typedef void (*GNUNET_NAMECACHE_BlockCallback) (void *cls, const struct GNUNET_GNSRECORD_Block *block); /** * @brief struct returned by the initialization function of the plugin */ struct GNUNET_NAMECACHE_PluginFunctions { /** * Closure to pass to all plugin functions. */ void *cls; /** * Cache a block in the datastore. Overwrites existing blocks * for the same zone and label. * * @param cls closure (internal context for the plugin) * @param block block to cache * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*cache_block) (void *cls, const struct GNUNET_GNSRECORD_Block *block); /** * Get the block for a particular zone and label in the * datastore. Will return at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param query hash of public key derived from the zone and the label * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ int (*lookup_block) (void *cls, const struct GNUNET_HashCode *query, GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls); }; #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_namecache_plugin.h */ #endif gnunet-0.10.1/src/include/gnunet_signal_lib.h0000644000175000017500000000541012245644744016074 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_signal_lib.h * @brief functions related to signals * @author Christian Grothoff */ #ifndef GNUNET_SIGNAL_LIB_H #define GNUNET_SIGNAL_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Context created when a signal handler is installed; * can be used to restore it to the previous state later. */ struct GNUNET_SIGNAL_Context; /** * A signal handler. Since different OSes have different signatures * for their handlers, the API only gives the most restrictive * signature -- no arguments, no return value. Note that this will * work even if the OS expects a function with arguments. However, * the implementation must guarantee that this handler is not called * for signals other than the one that it has been registered for. */ typedef void (*GNUNET_SIGNAL_Handler) (void); /** * Install a signal handler that will be run if the * given signal is received. * * @param signal the number of the signal * @param handler the function to call * @return context that can be used to restore, NULL on error */ struct GNUNET_SIGNAL_Context * GNUNET_SIGNAL_handler_install (int signal, GNUNET_SIGNAL_Handler handler); /** * Uninstall a previously installed signal hander. * * @param ctx context that was returned when the * signal handler was installed */ void GNUNET_SIGNAL_handler_uninstall (struct GNUNET_SIGNAL_Context *ctx); /** * Raise the given signal by calling the installed signal handlers. This will * not use the @em raise() system call but only calls the handlers registered * through GNUNET_SIGNAL_handler_install(). * * @param sig the signal to raise */ void GNUNET_SIGNAL_raise (const int sig); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_SIGNAL_LIB_H */ #endif /* end of gnunet_signal_lib.h */ gnunet-0.10.1/src/include/gnunet_identity_service.h0000644000175000017500000002210112233724131017320 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_identity_service.h * @brief Identity service; implements identity management for GNUnet * @author Christian Grothoff * * Egos in GNUnet are ECDSA keys. You assume an ego by using (signing * with) a particular private key. As GNUnet users are expected to * have many egos, we need an identity service to allow users to * manage their egos. The identity service manages the egos (private * keys) of the local user; it does NOT manage egos of other users * (public keys). For giving names to other users and manage their * public keys securely, we use GNS. * * @defgroup identity identity management service * @{ */ #ifndef GNUNET_IDENTITY_SERVICE_H #define GNUNET_IDENTITY_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Version number of GNUnet Identity API. */ #define GNUNET_IDENTITY_VERSION 0x00000000 /** * Handle to access the identity service. */ struct GNUNET_IDENTITY_Handle; /** * Handle for a ego. */ struct GNUNET_IDENTITY_Ego; /** * Handle for an operation with the identity service. */ struct GNUNET_IDENTITY_Operation; /** * Obtain the ECC key associated with a ego. * * @param ego the ego * @return associated ECC key, valid as long as the ego is valid */ const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego); /** * Obtain the ego representing 'anonymous' users. * * @return handle for the anonymous user, must not be freed */ const struct GNUNET_IDENTITY_Ego * GNUNET_IDENTITY_ego_get_anonymous (void); /** * Get the identifier (public key) of an ego. * * @param ego identity handle with the private key * @param pk set to ego's public key */ void GNUNET_IDENTITY_ego_get_public_key (const struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EcdsaPublicKey *pk); /** * Method called to inform about the egos of * this peer. * * When used with #GNUNET_IDENTITY_connect, this function is * initially called for all egos and then again whenever a * ego's name changes or if it is deleted. At the end of * the initial pass over all egos, the function is once called * with 'NULL' for @a ego. That does NOT mean that the callback won't * be invoked in the future or that there was an error. * * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, * this function is only called ONCE, and 'NULL' being passed in * @a ego does indicate an error (i.e. name is taken or no default * value is known). If @a ego is non-NULL and if '*ctx' * is set in those callbacks, the value WILL be passed to a subsequent * call to the identity callback of #GNUNET_IDENTITY_connect (if * that one was not NULL). * * When an identity is renamed, this function is called with the * (known) @a ego but the NEW @a name. * * When an identity is deleted, this function is called with the * (known) ego and "NULL" for the @a name. In this case, * the @a ego is henceforth invalid (and the @a ctx should also be * cleaned up). * * @param cls closure * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ typedef void (*GNUNET_IDENTITY_Callback)(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name); /** * Connect to the identity service. * * @param cfg Configuration to contact the identity service. * @param cb function to call on all identity events, can be NULL * @param cb_cls closure for @a cb * @return handle to communicate with identity service */ struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls); /** * Obtain the ego that is currently preferred/default * for a service. * * @param id identity service to query * @param service_name for which service is an identity wanted * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *id, const char *service_name, GNUNET_IDENTITY_Callback cb, void *cb_cls); /** * Function called once the requested operation has * been completed. * * @param cls closure * @param emsg NULL on success, otherwise an error message */ typedef void (*GNUNET_IDENTITY_Continuation)(void *cls, const char *emsg); /** * Set the preferred/default ego for a service. * * @param id identity service to inform * @param service_name for which service is an identity set * @param ego new default identity to be set for this service * @param cont function to call once the operation finished * @param cont_cls closure for @a cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *id, const char *service_name, struct GNUNET_IDENTITY_Ego *ego, GNUNET_IDENTITY_Continuation cont, void *cont_cls); /** * Disconnect from identity service. * * @param h identity service to disconnect */ void GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h); /** * Create a new ego with the given name. * * @param id identity service to use * @param name desired name * @param cont function to call with the result (will only be called once) * @param cont_cls closure for @a cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *id, const char *name, GNUNET_IDENTITY_Continuation cont, void *cont_cls); /** * Renames an existing ego. * * @param id identity service to use * @param old_name old name * @param new_name desired new name * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, const char *old_name, const char *new_name, GNUNET_IDENTITY_Continuation cb, void *cb_cls); /** * Delete an existing ego. * * @param id identity service to use * @param name name of the identity to delete * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, const char *name, GNUNET_IDENTITY_Continuation cb, void *cb_cls); /** * Cancel an identity operation. Note that the operation MAY still * be executed; this merely cancels the continuation; if the request * was already transmitted, the service may still choose to complete * the operation. * * @param op operation to cancel */ void GNUNET_IDENTITY_cancel (struct GNUNET_IDENTITY_Operation *op); /* ************* convenience API to lookup an ego ***************** */ /** * Function called with the result. * * @param cls closure * @param ego NULL on error / ego not found */ typedef void (*GNUNET_IDENTITY_EgoCallback)(void *cls, const struct GNUNET_IDENTITY_Ego *ego); /** * Handle for ego lookup. */ struct GNUNET_IDENTITY_EgoLookup; /** * Lookup an ego by name. * * @param cfg configuration to use * @param name name to look up * @param cb callback to invoke with the result * @param cb_cls closure for @a cb * @return NULL on error */ struct GNUNET_IDENTITY_EgoLookup * GNUNET_IDENTITY_ego_lookup (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name, GNUNET_IDENTITY_EgoCallback cb, void *cb_cls); /** * Abort ego lookup attempt. * * @param el handle for lookup to abort */ void GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group identity */ /* ifndef GNUNET_IDENTITY_SERVICE_H */ #endif /* end of gnunet_identity_service.h */ gnunet-0.10.1/src/include/gnunet_arm_service.h0000644000175000017500000002163412225777503016274 00000000000000/* This file is part of GNUnet (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_arm_service.h * @brief API to access gnunet-arm * @author Christian Grothoff */ #ifndef GNUNET_ARM_SERVICE_H #define GNUNET_ARM_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Version of the arm API. */ #define GNUNET_ARM_VERSION 0x00000002 /** * Statuses of the requests that client can send to ARM. */ enum GNUNET_ARM_RequestStatus { /** * Message was sent successfully. */ GNUNET_ARM_REQUEST_SENT_OK = 0, /** * Misconfiguration (can't connect to the ARM service). */ GNUNET_ARM_REQUEST_CONFIGURATION_ERROR = 1, /** * We disconnected from ARM, and request was not sent. */ GNUNET_ARM_REQUEST_DISCONNECTED = 2, /** * ARM API is busy (probably trying to connect to ARM), * and request was not sent. Try again later. */ GNUNET_ARM_REQUEST_BUSY = 3, /** * It was discovered that the request would be too long to fit in a message, * and thus it was not sent. */ GNUNET_ARM_REQUEST_TOO_LONG = 4, /** * Request time ran out before we had a chance to send it. */ GNUNET_ARM_REQUEST_TIMEOUT = 5 }; /** * Statuses of services. */ enum GNUNET_ARM_ServiceStatus { /** * Dummy message. */ GNUNET_ARM_SERVICE_MONITORING_STARTED = 0, /** * Service was stopped. */ GNUNET_ARM_SERVICE_STOPPED = 1, /** * Service starting was initiated */ GNUNET_ARM_SERVICE_STARTING = 2, /** * Service stopping was initiated */ GNUNET_ARM_SERVICE_STOPPING = 3 }; /** * Replies to ARM requests */ enum GNUNET_ARM_Result { /** * Service was stopped (never sent for ARM itself). */ GNUNET_ARM_RESULT_STOPPED = 0, /** * ARM stopping was initiated (there's no "stopped" for ARM itself). */ GNUNET_ARM_RESULT_STOPPING = 1, /** * Service starting was initiated */ GNUNET_ARM_RESULT_STARTING = 2, /** * Asked to start it, but it's already starting. */ GNUNET_ARM_RESULT_IS_STARTING_ALREADY = 3, /** * Asked to stop it, but it's already stopping. */ GNUNET_ARM_RESULT_IS_STOPPING_ALREADY = 4, /** * Asked to start it, but it's already started. */ GNUNET_ARM_RESULT_IS_STARTED_ALREADY = 5, /** * Asked to stop it, but it's already stopped. */ GNUNET_ARM_RESULT_IS_STOPPED_ALREADY = 6, /** * Asked to start or stop a service, but it's not known. */ GNUNET_ARM_RESULT_IS_NOT_KNOWN = 7, /** * Tried to start a service, but that failed for some reason. */ GNUNET_ARM_RESULT_START_FAILED = 8, /** * Asked to start something, but ARM is shutting down and can't comply. */ GNUNET_ARM_RESULT_IN_SHUTDOWN = 9 }; /** * Handle for interacting with ARM. */ struct GNUNET_ARM_Handle; /** * Function called whenever we connect to or disconnect from ARM. * * @param cls closure * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected, * GNUNET_SYSERR if there was an error. */ typedef void (*GNUNET_ARM_ConnectionStatusCallback) (void *cls, int connected); /** * Function called in response to a start/stop request. * Will be called when request was not sent successfully, * or when a reply comes. If the request was not sent successfully, * 'rs' will indicate that, and 'service' and 'result' will be undefined. * * @param cls closure * @param rs status of the request * @param service service name * @param result result of the operation */ typedef void (*GNUNET_ARM_ResultCallback) (void *cls, enum GNUNET_ARM_RequestStatus rs, const char *service, enum GNUNET_ARM_Result result); /** * Callback function invoked when list operation is complete. * Will be called when request was not sent successfully, * or when a reply comes. If the request was not sent successfully, * 'rs' will indicate that, and 'count' and 'list' will be undefined. * * @param cls closure * @param rs status of the request * @param count number of strings in the list * @param list list of running services */ typedef void (*GNUNET_ARM_ServiceListCallback) (void *cls, enum GNUNET_ARM_RequestStatus rs, unsigned int count, const char *const*list); /** * Set up a context for communicating with ARM, then * start connecting to the ARM service using that context. * * @param cfg configuration to use (needed to contact ARM; * the ARM service may internally use a different * configuration to determine how to start the service). * @param conn_status will be called when connecting/disconnecting * @param cls closure for conn_status * @return context to use for further ARM operations, NULL on error. */ struct GNUNET_ARM_Handle * GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ARM_ConnectionStatusCallback conn_status, void *cls); /** * Disconnect from the ARM service and destroy the handle. * * @param h the handle that was being used */ void GNUNET_ARM_disconnect_and_free (struct GNUNET_ARM_Handle *h); /** * Request a list of running services. * * @param h handle to ARM * @param timeout how long to wait before failing for good * @param cont callback to invoke after request is sent or is not sent * @param cont_cls closure for callback */ void GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ServiceListCallback cont, void *cont_cls); /** * Request a service to be stopped. * Stopping arm itself will not invalidate its handle, and * ARM API will try to restore connection to the ARM service, * even if ARM connection was lost because you asked for ARM to be stopped. * Call GNUNET_ARM_disconnect_and_free () to free the handle and prevent * further connection attempts. * * @param h handle to ARM * @param service_name name of the service * @param timeout how long to wait before failing for good * @param cont callback to invoke after request is sent or is not sent * @param cont_cls closure for callback */ void GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h, const char *service_name, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ResultCallback cont, void *cont_cls); /** * Request for a service to be started. * * @param h handle to ARM * @param service_name name of the service * @param std_inheritance inheritance of std streams * @param timeout how long to wait before failing for good * @param cont callback to invoke after request is sent or not sent * @param cont_cls closure for callback */ void GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h, const char *service_name, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ResultCallback cont, void *cont_cls); /** * Handle for monitoring ARM. */ struct GNUNET_ARM_MonitorHandle; /** * Function called in when a status update arrives. * * @param cls closure * @param arm handle to the arm connection * @param service service name * @param status status of the service */ typedef void (*GNUNET_ARM_ServiceStatusCallback) (void *cls, const char *service, enum GNUNET_ARM_ServiceStatus status); /** * Setup a context for monitoring ARM, then * start connecting to the ARM service for monitoring using that context. * * @param cfg configuration to use (needed to contact ARM; * the ARM service may internally use a different * configuration to determine how to start the service). * @param cont callback to invoke on status updates * @param cont_cls closure * @return context to use for further ARM monitor operations, NULL on error. */ struct GNUNET_ARM_MonitorHandle * GNUNET_ARM_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ARM_ServiceStatusCallback cont, void *cont_cls); /** * Disconnect from the ARM service and destroy the handle. * * @param h the handle that was being used */ void GNUNET_ARM_monitor_disconnect_and_free (struct GNUNET_ARM_MonitorHandle *h); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_consensus_service.h0000644000175000017500000001265412274162760017534 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_consensus_service.h * @brief multi-peer set reconciliation * @author Florian Dold */ #ifndef GNUNET_CONSENSUS_SERVICE_H #define GNUNET_CONSENSUS_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "gnunet_common.h" #include "gnunet_time_lib.h" #include "gnunet_configuration_lib.h" #include "gnunet_set_service.h" /** * Called when a new element was received from another peer, or an error occured. * May deliver duplicate values. * Elements given to a consensus operation by the local peer are NOT given * to this callback. * * @param cls closure * @param element new element, NULL on error */ typedef void (*GNUNET_CONSENSUS_ElementCallback) (void *cls, const struct GNUNET_SET_Element *element); /** * Opaque handle for the consensus service. */ struct GNUNET_CONSENSUS_Handle; /** * Create a consensus session. The set being reconciled is initially * empty. * * @param cfg * @param num_peers * @param peers array of peers participating in this consensus session * Inclusion of the local peer is optional. * @param session_id session identifier * Allows a group of peers to have more than consensus session. * @param start start time of the consensus, conclude should be called before * the start time. * @param deadline time when the consensus should have concluded * @param new_element_cb callback, called when a new element is added to the set by * another peer. Also called when an error occurs. * @param new_element_cls closure for new_element * @return handle to use, NULL on error */ struct GNUNET_CONSENSUS_Handle * GNUNET_CONSENSUS_create (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, const struct GNUNET_PeerIdentity *peers, const struct GNUNET_HashCode *session_id, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, GNUNET_CONSENSUS_ElementCallback new_element_cb, void *new_element_cls); /** * Called when an insertion (transmission to consensus service, which * does not imply fully consensus on this element with all other * peers) was successful. May not call GNUNET_CONSENSUS_destroy(); * schedule a task to call GNUNET_CONSENSUS_destroy() instead (if * needed). * * @param cls * @param success #GNUNET_OK on success, #GNUNET_SYSERR if * the insertion and thus the consensus failed for good */ typedef void (*GNUNET_CONSENSUS_InsertDoneCallback) (void *cls, int success); /** * Insert an element in the set being reconsiled. Only transmit changes to * other peers if GNUNET_CONSENSUS_begin() has been called. * Must not be called after GNUNET_CONSENSUS_conclude(). * May not call GNUNET_CONSENSUS_destroy(); schedule a task to call * GNUNET_CONSENSUS_destroy() instead (if needed). * * @param consensus handle for the consensus session * @param element the element to be inserted * @param idc function called when we are done with this element and it * is thus allowed to call GNUNET_CONSENSUS_insert() again * @param idc_cls closure for @a idc */ void GNUNET_CONSENSUS_insert (struct GNUNET_CONSENSUS_Handle *consensus, const struct GNUNET_SET_Element *element, GNUNET_CONSENSUS_InsertDoneCallback idc, void *idc_cls); /** * Called when a conclusion was successful. * * @param cls */ typedef void (*GNUNET_CONSENSUS_ConcludeCallback) (void *cls); /** * We are finished inserting new elements into the consensus; * try to conclude the consensus within a given time window. * * @param consensus consensus session * @param conclude called when the conclusion was successful * @param conclude_cls closure for the conclude callback */ void GNUNET_CONSENSUS_conclude (struct GNUNET_CONSENSUS_Handle *consensus, GNUNET_CONSENSUS_ConcludeCallback conclude, void *conclude_cls); /** * Destroy a consensus handle (free all state associated with * it, no longer call any of the callbacks). * * @param consensus handle to destroy */ void GNUNET_CONSENSUS_destroy (struct GNUNET_CONSENSUS_Handle *consensus); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_gnsrecord_plugin.h0000644000175000017500000001017412227705277017337 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_gnsrecord_plugin.h * @brief plugin API for GNS record types * @author Christian Grothoff * @defgroup gnsrecordplugin API to be implemented by applications defining new GNS record types * @{ */ #ifndef GNUNET_GNSRECORD_PLUGIN_H #define GNUNET_GNSRECORD_PLUGIN_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Function called to convert the binary value @a data of a record of * type @a type to a human-readable string. * * @param cls closure * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in @a data * @return NULL on error, otherwise human-readable representation of the value */ typedef char * (*GNUNET_GNSRECORD_ValueToStringFunction) (void *cls, uint32_t type, const void *data, size_t data_size); /** * Function called to convert human-readable version of the value @a s * of a record of type @a type to the respective binary * representation. * * @param cls closure * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ typedef int (*GNUNET_GNSRECORD_StringToValueFunction) (void *cls, uint32_t type, const char *s, void **data, size_t *data_size); /** * Function called to convert a type name (i.e. "AAAA") to the * corresponding number. * * @param cls closure * @param dns_typename name to convert * @return corresponding number, UINT32_MAX on error */ typedef uint32_t (*GNUNET_GNSRECORD_TypenameToNumberFunction) (void *cls, const char *dns_typename); /** * Function called to convert a type number (i.e. 1) to the * corresponding type string (i.e. "A") * * @param cls closure * @param type number of a type to convert * @return corresponding typestring, NULL on error */ typedef const char * (*GNUNET_GNSRECORD_NumberToTypenameFunction) (void *cls, uint32_t type); /** * Each plugin is required to return a pointer to a struct of this * type as the return value from its entry point. */ struct GNUNET_GNSRECORD_PluginFunctions { /** * Closure for all of the callbacks. */ void *cls; /** * Conversion to string. */ GNUNET_GNSRECORD_ValueToStringFunction value_to_string; /** * Conversion to binary. */ GNUNET_GNSRECORD_StringToValueFunction string_to_value; /** * Typename to number. */ GNUNET_GNSRECORD_TypenameToNumberFunction typename_to_number; /** * Number to typename. */ GNUNET_GNSRECORD_NumberToTypenameFunction number_to_typename; }; /** @} */ /* end of group gnsrecordplugin */ #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_protocols.h0000644000175000017500000016761012320462746016022 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_protocols.h * @brief constants for network protocols * @author Christian Grothoff * @defgroup protocols Types of messages used in GNUnet * @{ */ /******************************************************************************* * TODO: we need a way to register message types centrally (via some webpage). * For now: unofficial extensions should start at 48k, internal extensions * defined here should leave some room (4-10 additional messages to the previous * extension). ******************************************************************************/ #ifndef GNUNET_PROTOCOLS_H #define GNUNET_PROTOCOLS_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /******************************************************************************* * UTIL message types ******************************************************************************/ /** * Test if service is online. */ #define GNUNET_MESSAGE_TYPE_TEST 1 /** * Dummy messages for testing / benchmarking. */ #define GNUNET_MESSAGE_TYPE_DUMMY 2 /******************************************************************************* * RESOLVER message types ******************************************************************************/ /** * Request DNS resolution. */ #define GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST 4 /** * Response to a DNS resolution request. */ #define GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE 5 /******************************************************************************* * ARM message types ******************************************************************************/ /** * Request to ARM to start a service. */ #define GNUNET_MESSAGE_TYPE_ARM_START 8 /** * Request to ARM to stop a service. */ #define GNUNET_MESSAGE_TYPE_ARM_STOP 9 /** * Response from ARM. */ #define GNUNET_MESSAGE_TYPE_ARM_RESULT 10 /** * Status update from ARM. */ #define GNUNET_MESSAGE_TYPE_ARM_STATUS 11 /** * Request to ARM to list all currently running services */ #define GNUNET_MESSAGE_TYPE_ARM_LIST 12 /** * Response from ARM for listing currently running services */ #define GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT 13 /** * Request to ARM to notify client of service status changes */ #define GNUNET_MESSAGE_TYPE_ARM_MONITOR 14 /******************************************************************************* * HELLO message types ******************************************************************************/ /** * Previously used for HELLO messages used for communicating peer addresses. * Managed by libgnunethello. */ #define GNUNET_MESSAGE_TYPE_HELLO_LEGACY 16 /** * HELLO message with friend only flag used for communicating peer addresses. * Managed by libgnunethello. */ #define GNUNET_MESSAGE_TYPE_HELLO 17 /******************************************************************************* * FRAGMENTATION message types ******************************************************************************/ /** * FRAGMENT of a larger message. * Managed by libgnunetfragment. */ #define GNUNET_MESSAGE_TYPE_FRAGMENT 18 /** * Acknowledgement of a FRAGMENT of a larger message. * Managed by libgnunetfragment. */ #define GNUNET_MESSAGE_TYPE_FRAGMENT_ACK 19 /******************************************************************************* * Transport-WLAN message types ******************************************************************************/ /** * Type of data messages from the plugin to the gnunet-wlan-helper */ #define GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER 39 /** * Type of data messages from the gnunet-wlan-helper to the plugin */ #define GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER 40 /** * Control message between the gnunet-wlan-helper and the daemon (with the MAC). */ #define GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL 41 /** * Type of messages for advertisement over wlan */ #define GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT 42 /** * Type of messages for data over the wlan */ #define GNUNET_MESSAGE_TYPE_WLAN_DATA 43 /******************************************************************************* * Transport-DV message types ******************************************************************************/ /** * DV service to DV Plugin message, when a message is * unwrapped by the DV service and handed to the plugin * for processing */ #define GNUNET_MESSAGE_TYPE_DV_RECV 44 /** * DV Plugin to DV service message, indicating a message * should be sent out. */ #define GNUNET_MESSAGE_TYPE_DV_SEND 45 /** * DV service to DV api message, containing a confirmation * or failure of a DV_SEND message. */ #define GNUNET_MESSAGE_TYPE_DV_SEND_ACK 46 /** * P2P DV message encapsulating some real message */ #define GNUNET_MESSAGE_TYPE_DV_ROUTE 47 /** * DV Plugin to DV service message, indicating * startup. */ #define GNUNET_MESSAGE_TYPE_DV_START 48 /** * P2P DV message telling plugin that a peer connected */ #define GNUNET_MESSAGE_TYPE_DV_CONNECT 49 /** * P2P DV message telling plugin that a peer disconnected */ #define GNUNET_MESSAGE_TYPE_DV_DISCONNECT 50 /** * P2P DV message telling plugin that a message transmission failed (negative ACK) */ #define GNUNET_MESSAGE_TYPE_DV_SEND_NACK 51 /** * P2P DV message telling plugin that our distance to a peer changed */ #define GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED 52 /** * DV message box for boxing multiple messages. */ #define GNUNET_MESSAGE_TYPE_DV_BOX 53 /******************************************************************************* * Transport-UDP message types ******************************************************************************/ /** * Normal UDP message type. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE 56 /** * UDP ACK. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK 57 /******************************************************************************* * Transport-TCP message types ******************************************************************************/ /** * TCP NAT probe message, send from NAT'd peer to * other peer to establish bi-directional communication */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE 60 /** * Welcome message between TCP transports. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME 61 /** * Message to force transport to update bandwidth assignment (LEGACY) */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_ATS 62 /******************************************************************************* * NAT message types ******************************************************************************/ /** * Message to ask NAT server to perform traversal test */ #define GNUNET_MESSAGE_TYPE_NAT_TEST 63 /******************************************************************************* * CORE message types ******************************************************************************/ /** * Initial setup message from core client to core. */ #define GNUNET_MESSAGE_TYPE_CORE_INIT 64 /** * Response from core to core client to INIT message. */ #define GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY 65 /** * Notify clients about new peer-to-peer connections (triggered * after key exchange). */ #define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT 67 /** * Notify clients about peer disconnecting. */ #define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT 68 /** * Notify clients about peer status change. */ #define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE 69 /** * Notify clients about incoming P2P messages. */ #define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 70 /** * Notify clients about outgoing P2P transmissions. */ #define GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND 71 /** * Request from client to transmit message. */ #define GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST 74 /** * Confirmation from core that message can now be sent */ #define GNUNET_MESSAGE_TYPE_CORE_SEND_READY 75 /** * Client with message to transmit (after SEND_READY confirmation * was received). */ #define GNUNET_MESSAGE_TYPE_CORE_SEND 76 /** * Request for peer iteration from CORE service. */ #define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS 78 /** * Last reply from core to request for peer iteration from CORE service. */ #define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END 79 /** * Encapsulation for an encrypted message between peers. */ #define GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE 82 /** * Check that other peer is alive (challenge). */ #define GNUNET_MESSAGE_TYPE_CORE_PING 83 /** * Confirmation that other peer is alive. */ #define GNUNET_MESSAGE_TYPE_CORE_PONG 84 /** * Request by the other peer to terminate the connection. */ #define GNUNET_MESSAGE_TYPE_CORE_HANGUP 85 /** * gzip-compressed type map of the sender */ #define GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP 86 /** * uncompressed type map of the sender */ #define GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP 87 /** * Session key exchange between peers. */ #define GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY 88 /******************************************************************************* * DATASTORE message types ******************************************************************************/ /** * Message sent by datastore client on join. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE 92 /** * Message sent by datastore client on join. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE 93 /** * Message sent by datastore to client informing about status * processing a request * (in response to RESERVE, RELEASE_RESERVE, PUT, UPDATE and REMOVE requests). */ #define GNUNET_MESSAGE_TYPE_DATASTORE_STATUS 94 /** * Message sent by datastore client to store data. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_PUT 95 /** * Message sent by datastore client to update data. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE 96 /** * Message sent by datastore client to get data. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_GET 97 /** * Message sent by datastore client to get random data. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_GET_REPLICATION 98 /** * Message sent by datastore client to get random data. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_GET_ZERO_ANONYMITY 99 /** * Message sent by datastore to client providing requested data * (in response to GET or GET_RANDOM request). */ #define GNUNET_MESSAGE_TYPE_DATASTORE_DATA 100 /** * Message sent by datastore to client signaling end of matching data. * This message will also be sent for "GET_RANDOM", even though * "GET_RANDOM" returns at most one data item. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END 101 /** * Message sent by datastore client to remove data. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE 102 /** * Message sent by datastore client to drop the database. */ #define GNUNET_MESSAGE_TYPE_DATASTORE_DROP 103 /******************************************************************************* * FS message types ******************************************************************************/ /** * Message sent by fs client to start indexing. */ #define GNUNET_MESSAGE_TYPE_FS_INDEX_START 128 /** * Affirmative response to a request for start indexing. */ #define GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK 129 /** * Response to a request for start indexing that * refuses. */ #define GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED 130 /** * Request from client for list of indexed files. */ #define GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET 131 /** * Reply to client with an indexed file name. */ #define GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY 132 /** * Reply to client indicating end of list. */ #define GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END 133 /** * Request from client to unindex a file. */ #define GNUNET_MESSAGE_TYPE_FS_UNINDEX 134 /** * Reply to client indicating unindex receipt. */ #define GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK 135 /** * Client asks FS service to start a (keyword) search. */ #define GNUNET_MESSAGE_TYPE_FS_START_SEARCH 136 /** * P2P request for content (one FS to another). */ #define GNUNET_MESSAGE_TYPE_FS_GET 137 /** * P2P response with content or active migration of content. Also * used between the service and clients (in response to START_SEARCH). */ #define GNUNET_MESSAGE_TYPE_FS_PUT 138 /** * Peer asks us to stop migrating content towards it for a while. */ #define GNUNET_MESSAGE_TYPE_FS_MIGRATION_STOP 139 /** * P2P request for content (one FS to another via a mesh). */ #define GNUNET_MESSAGE_TYPE_FS_MESH_QUERY 140 /** * P2P answer for content (one FS to another via a mesh). */ #define GNUNET_MESSAGE_TYPE_FS_MESH_REPLY 141 /******************************************************************************* * DHT message types ******************************************************************************/ /** * Client wants to store item in DHT. */ #define GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT 142 /** * Client wants to lookup item in DHT. */ #define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET 143 /** * Client wants to stop search in DHT. */ #define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP 144 /** * Service returns result to client. */ #define GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT 145 /** * Peer is storing data in DHT. */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_PUT 146 /** * Peer tries to find data in DHT. */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_GET 147 /** * Data is returned to peer from DHT. */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT 148 /** * Receive information about transiting GETs */ #define GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET 149 /** * Receive information about transiting GET responses */ #define GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP 150 /** * Receive information about transiting PUTs */ #define GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT 151 /** * Receive information about transiting PUT responses (TODO) */ #define GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT_RESP 152 /** * Request information about transiting messages */ #define GNUNET_MESSAGE_TYPE_DHT_MONITOR_START 153 /** * Stop information about transiting messages */ #define GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP 154 /** * Acknowledge receiving PUT request */ #define GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK 155 /** * Certain results are already known to the client, filter those. */ #define GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN 156 /** * Trail setup request is received by a peer. */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP 157 /** * Trail to a particular peer is returned to this peer. */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT 158 /** * Verify if your immediate successor is still your immediate successor. */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR 159 /** * Notify your new immediate successor that you are its new predecessor. */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR 160 /** * Message which contains the immediate predecessor of requested successor */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT 161 /** * Message which contains the get result. */ #define GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT 162 /******************************************************************************* * HOSTLIST message types ******************************************************************************/ /** * Hostlist advertisement message */ #define GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT 160 /******************************************************************************* * STATISTICS message types ******************************************************************************/ /** * Set a statistical value. */ #define GNUNET_MESSAGE_TYPE_STATISTICS_SET 168 /** * Get a statistical value(s). */ #define GNUNET_MESSAGE_TYPE_STATISTICS_GET 169 /** * Response to a STATISTICS_GET message (with value). */ #define GNUNET_MESSAGE_TYPE_STATISTICS_VALUE 170 /** * Response to a STATISTICS_GET message (end of value stream). */ #define GNUNET_MESSAGE_TYPE_STATISTICS_END 171 /** * Watch changes to a statistical value. Message format is the same * as for GET, except that the subsystem and entry name must be given. */ #define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH 172 /** * Changes to a watched value. */ #define GNUNET_MESSAGE_TYPE_STATISTICS_WATCH_VALUE 173 /******************************************************************************* * VPN message types ******************************************************************************/ /** * Type of messages between the gnunet-vpn-helper and the daemon */ #define GNUNET_MESSAGE_TYPE_VPN_HELPER 185 /** * Type of messages containing an ICMP packet for a service. */ #define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE 190 /** * Type of messages containing an ICMP packet for the Internet. */ #define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET 191 /** * Type of messages containing an ICMP packet for the VPN */ #define GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN 192 /** * Type of messages containing an DNS request for a DNS exit service. */ #define GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET 193 /** * Type of messages containing an DNS reply from a DNS exit service. */ #define GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET 194 /** * Type of messages containing an TCP packet for a service. */ #define GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START 195 /** * Type of messages containing an TCP packet for the Internet. */ #define GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START 196 /** * Type of messages containing an TCP packet of an established connection. */ #define GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT 197 /** * Type of messages containing an TCP packet of an established connection. */ #define GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN 198 /** * Type of messages containing an UDP packet for a service. */ #define GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE 199 /** * Type of messages containing an UDP packet for the Internet. */ #define GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET 200 /** * Type of messages containing an UDP packet from a remote host */ #define GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY 201 /** * Client asks VPN service to setup an IP to redirect traffic * via an exit node to some global IP address. */ #define GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP 202 /** * Client asks VPN service to setup an IP to redirect traffic * to some peer offering a service. */ #define GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE 203 /** * VPN service responds to client with an IP to use for the * requested redirection. */ #define GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP 204 /******************************************************************************* * VPN-DNS message types ******************************************************************************/ /** * Initial message from client to DNS service for registration. */ #define GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT 211 /** * Type of messages between the gnunet-helper-dns and the service */ #define GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST 212 /** * Type of messages between the gnunet-helper-dns and the service */ #define GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE 213 /** * Type of messages between the gnunet-helper-dns and the service */ #define GNUNET_MESSAGE_TYPE_DNS_HELPER 214 /******************************************************************************* * MESH message types ******************************************************************************/ /** * Type of message used to transport messages throug a MESH-tunnel (LEGACY) */ #define GNUNET_MESSAGE_TYPE_MESH 215 /** * Type of message used to send another peer which messages we want to receive * through a mesh-tunnel (LEGACY) */ #define GNUNET_MESSAGE_TYPE_MESH_HELLO 216 /** * Request the creation of a connection */ #define GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE 256 /** * Send origin an ACK that the connection is complete */ #define GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK 257 /** * Notify that a connection is no longer valid */ #define GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN 258 /** * At some point, the route will spontaneously change TODO */ #define GNUNET_MESSAGE_TYPE_MESH_PATH_CHANGED 259 /** * Payload data (usually inside a encrypted tunnel). */ #define GNUNET_MESSAGE_TYPE_MESH_DATA 260 /** * Confirm payload data end-to-end. */ #define GNUNET_MESSAGE_TYPE_MESH_DATA_ACK 261 /** * Key exchange encapsulation. */ #define GNUNET_MESSAGE_TYPE_MESH_KX 262 /** * New ephemeral key. */ #define GNUNET_MESSAGE_TYPE_MESH_KX_EPHEMERAL 263 /** * Challenge to test peer's session key. */ #define GNUNET_MESSAGE_TYPE_MESH_KX_PING 264 /** * Answer to session key challenge. */ #define GNUNET_MESSAGE_TYPE_MESH_KX_PONG 265 /** * Request the destuction of a connection */ #define GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY 266 /** * Hop-by-hop, connection dependent ACK. */ #define GNUNET_MESSAGE_TYPE_MESH_ACK 268 /** * Poll for a hop-by-hop ACK. */ #define GNUNET_MESSAGE_TYPE_MESH_POLL 269 /** * Announce connection is still alive (direction sensitive). */ #define GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE 270 /** * Connect to the mesh service, specifying subscriptions */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT 272 /** * Ask the mesh service to create a new channel. */ #define GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE 273 /** * Ask the mesh service to destroy a channel. */ #define GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY 274 /** * Confirm the creation of a channel */ #define GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK 275 /** * Reject the creation of a channel */ #define GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK 276 /** * Encrypted data. (Payload, channel management, keepalive) */ #define GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED 280 /** * Payload client <-> service */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA 285 /** * Local ACK for data. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK 286 /** * Local information about all channels of service. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNELS 290 /** * Local information of service about a specific channel. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL 291 /** * Local information about all tunnels of service. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS 292 /** * Local information of service about a specific tunnel. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL 293 /** * Local information about all connections of service. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CONNECTIONS 294 /** * Local information of service about a specific connection. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CONNECTION 295 /** * Local information about all peers known to the service. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS 296 /** * Local information of service about a specific peer. */ #define GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEER 297 /** * Traffic (net-cat style) used by the Command Line Interface. */ #define GNUNET_MESSAGE_TYPE_MESH_CLI 298 /** * 640kb should be enough for everybody */ #define GNUNET_MESSAGE_TYPE_MESH_RESERVE_END 299 /******************************************************************************* * CHAT message types START ******************************************************************************/ /** * Message sent from client to join a chat room. */ #define GNUNET_MESSAGE_TYPE_CHAT_JOIN_REQUEST 300 /** * Message sent to client to indicate joining of another room member. */ #define GNUNET_MESSAGE_TYPE_CHAT_JOIN_NOTIFICATION 301 /** * Message sent to client to indicate leaving of another room member. */ #define GNUNET_MESSAGE_TYPE_CHAT_LEAVE_NOTIFICATION 302 /** * Notification sent by service to client indicating that we've received a chat * message. */ #define GNUNET_MESSAGE_TYPE_CHAT_MESSAGE_NOTIFICATION 303 /** * Request sent by client to transmit a chat message to another room members. */ #define GNUNET_MESSAGE_TYPE_CHAT_TRANSMIT_REQUEST 304 /** * Receipt sent from a message receiver to the service to confirm delivery of * a chat message. */ #define GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_RECEIPT 305 /** * Notification sent from the service to the original sender * to acknowledge delivery of a chat message. */ #define GNUNET_MESSAGE_TYPE_CHAT_CONFIRMATION_NOTIFICATION 306 /** * P2P message sent to indicate joining of another room member. */ #define GNUNET_MESSAGE_TYPE_CHAT_P2P_JOIN_NOTIFICATION 307 /** * P2P message sent to indicate leaving of another room member. */ #define GNUNET_MESSAGE_TYPE_CHAT_P2P_LEAVE_NOTIFICATION 308 /** * P2P message sent to a newly connected peer to request its known clients in * order to synchronize room members. */ #define GNUNET_MESSAGE_TYPE_CHAT_P2P_SYNC_REQUEST 309 /** * Notification sent from one peer to another to indicate that we have received * a chat message. */ #define GNUNET_MESSAGE_TYPE_CHAT_P2P_MESSAGE_NOTIFICATION 310 /** * P2P receipt confirming delivery of a chat message. */ #define GNUNET_MESSAGE_TYPE_CHAT_P2P_CONFIRMATION_RECEIPT 311 /******************************************************************************* * NSE (network size estimation) message types ******************************************************************************/ /** * client->service message indicating start */ #define GNUNET_MESSAGE_TYPE_NSE_START 321 /** * P2P message sent from nearest peer */ #define GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD 322 /** * service->client message indicating */ #define GNUNET_MESSAGE_TYPE_NSE_ESTIMATE 323 /******************************************************************************* * PEERINFO message types ******************************************************************************/ /** * Request update and listing of a peer. */ #define GNUNET_MESSAGE_TYPE_PEERINFO_GET 330 /** * Request update and listing of all peers. */ #define GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL 331 /** * Information about one of the peers. */ #define GNUNET_MESSAGE_TYPE_PEERINFO_INFO 332 /** * End of information about other peers. */ #define GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END 333 /** * Start notifying this client about all changes to * the known peers until it disconnects. */ #define GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY 334 /******************************************************************************* * ATS message types ******************************************************************************/ /** * Type of the 'struct ClientStartMessage' sent by clients to ATS to * identify the type of the client. */ #define GNUNET_MESSAGE_TYPE_ATS_START 340 /** * Type of the 'struct RequestAddressMessage' sent by clients to ATS * to request an address to help connect. */ #define GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS 341 /** * Type of the 'struct RequestAddressMessage' sent by clients to ATS * to request an address to help connect. */ #define GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL 342 /** * Type of the 'struct AddressUpdateMessage' sent by clients to ATS * to inform ATS about performance changes. */ #define GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE 343 /** * Type of the 'struct AddressDestroyedMessage' sent by clients to ATS * to inform ATS about an address being unavailable. */ #define GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED 344 /** * Type of the 'struct AddressSuggestionMessage' sent by ATS to clients * to suggest switching to a different address. */ #define GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION 345 /** * Type of the 'struct PeerInformationMessage' sent by ATS to clients * to inform about QoS for a particular connection. */ #define GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION 346 /** * Type of the 'struct ReservationRequestMessage' sent by clients to ATS * to ask for inbound bandwidth reservations. */ #define GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST 347 /** * Type of the 'struct ReservationResultMessage' sent by ATS to clients * in response to a reservation request. */ #define GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT 348 /** * Type of the 'struct ChangePreferenceMessage' sent by clients to ATS * to ask for allocation preference changes. */ #define GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE 349 /** * Type of the 'struct SessionReleaseMessage' sent by ATS to client * to confirm that a session ID was destroyed. */ #define GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE 350 /** * Type of the 'struct AddressUseMessage' sent by ATS to client * to confirm that an address is used or not used anymore */ #define GNUNET_MESSAGE_TYPE_ATS_ADDRESS_IN_USE 351 /** * Type of the 'struct AddressUseMessage' sent by ATS to client * to confirm that an address is used or not used anymore */ #define GNUNET_MESSAGE_TYPE_ATS_RESET_BACKOFF 352 /** * Type of the 'struct AddressUpdateMessage' sent by client to ATS * to add a new address */ #define GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD 353 /** * Type of the 'struct AddressListRequestMessage' sent by client to ATS * to request information about addresses */ #define GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST 354 /** * Type of the 'struct AddressListResponseMessage' sent by ATS to client * with information about addresses */ #define GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE 355 /** * Type of the 'struct ChangePreferenceMessage' sent by clients to ATS * to ask for allocation preference changes. */ #define GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK 356 /******************************************************************************* * TRANSPORT message types ******************************************************************************/ /** * Message from the core saying that the transport * server should start giving it messages. This * should automatically trigger the transmission of * a HELLO message. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_START 360 /** * Message from TRANSPORT notifying about a * client that connected to us. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT 361 /** * Message from TRANSPORT notifying about a * client that disconnected from us. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT 362 /** * Request to TRANSPORT to transmit a message. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND 363 /** * Confirmation from TRANSPORT that message for transmission has been * queued (and that the next message to this peer can now be passed to * the service). Note that this confirmation does NOT imply that the * message was fully transmitted. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK 364 /** * Message from TRANSPORT notifying about a * message that was received. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_RECV 365 /** * Message telling transport to limit its receive rate. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA 366 /** * Request to look addresses of peers in server. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING 367 /** * Response to the address lookup request. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY 368 /** * Register a client that wants to do blacklisting. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT 369 /** * Query to a blacklisting client (is this peer blacklisted)? */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY 370 /** * Reply from blacklisting client (answer to blacklist query). */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY 371 /** * Transport PING message */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_PING 372 /** * Transport PONG message */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_PONG 373 /** * Message for transport service from a client asking that a * connection be initiated with another peer. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT 374 /** * Transport CONNECT message exchanged between transport services to * indicate that a session should be marked as 'connected'. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT 375 /** * Transport CONNECT_ACK message exchanged between transport services to * indicate that a CONNECT message was accepted */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK 376 /** * Transport CONNECT_ACK message exchanged between transport services to * indicate that a CONNECT message was accepted */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK 377 /** * Transport DISCONNECT message exchanged between transport services to * indicate that a connection should be dropped. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT 378 /** * Request to monitor addresses used by a peer or all peers. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST 380 /** * Message send by a peer to notify the other to keep the session alive * and measure latency in a regular interval */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE 381 /** * Response to a #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE message to * measure latency in a regular interval */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE 382 /** * Response to #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST * request to iterate over all known addresses. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE 383 /** * Message send by a peer to notify the other to keep the session alive. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON 384 /** * Message containing traffic metrics for transport service */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC 385 /** * Request to monitor address validations by a peer or all peers. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST 386 /** * Response to #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST * request to iterate over all known addresses. */ #define GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE 387 /******************************************************************************* * FS-PUBLISH-HELPER IPC Messages ******************************************************************************/ /** * Progress information from the helper: found a file */ #define GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE 420 /** * Progress information from the helper: found a directory */ #define GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY 421 /** * Error signal from the helper. */ #define GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR 422 /** * Signal that helper skipped a file. */ #define GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE 423 /** * Signal that helper is done scanning the directory tree. */ #define GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE 424 /** * Extracted meta data from the helper. */ #define GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA 425 /** * Signal that helper is done. */ #define GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED 426 /******************************************************************************* * NAMECACHE message types ******************************************************************************/ /** * Client to service: lookup block */ #define GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK 431 /** * Service to client: result of block lookup */ #define GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE 432 /** * Client to service: cache a block */ #define GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE 433 /** * Service to client: result of block cache request */ #define GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE 434 /******************************************************************************* * NAMESTORE message types ******************************************************************************/ /** * Client to service: store records (as authority) */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE 435 /** * Service to client: result of store operation. */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE 436 /** * Client to service: lookup label */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP 437 /** * Service to client: lookup label */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE 438 /** * Client to service: "reverse" lookup for zone name based on zone key */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME 439 /** * Service to client: result of zone-to-name lookup. */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE 440 /** * Client to service: start monitoring (yields sequence of * "ZONE_ITERATION_RESPONSES" --- forever). */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START 441 /** * Service to client: you're now in sync. */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC 442 /** * Service to client: here is a (plaintext) record you requested. */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT 443 /** * Client to service: please start iteration; receives * "GNUNET_MESSAGE_TYPE_NAMESTORE_LOOKUP_NAME_RESPONSE" messages in return. */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START 445 /** * Client to service: next record in iteration please. */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT 447 /** * Client to service: stop iterating. */ #define GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP 448 /******************************************************************************* * LOCKMANAGER message types ******************************************************************************/ /** * Message to acquire Lock */ #define GNUNET_MESSAGE_TYPE_LOCKMANAGER_ACQUIRE 450 /** * Message to release lock */ #define GNUNET_MESSAGE_TYPE_LOCKMANAGER_RELEASE 451 /** * SUCESS reply from lockmanager */ #define GNUNET_MESSAGE_TYPE_LOCKMANAGER_SUCCESS 452 /******************************************************************************* * TESTBED message types ******************************************************************************/ /** * Initial message from a client to a testing control service */ #define GNUNET_MESSAGE_TYPE_TESTBED_INIT 460 /** * Message to add host */ #define GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST 461 /** * Message to signal that a add host succeeded */ #define GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS 462 /** * Message to link delegated controller to slave controller */ #define GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS 463 /** * Message to create a peer at a host */ #define GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER 464 /** * Message to reconfigure a peer */ #define GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER 465 /** * Message to start a peer at a host */ #define GNUNET_MESSAGE_TYPE_TESTBED_START_PEER 466 /** * Message to stop a peer at a host */ #define GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER 467 /** * Message to destroy a peer */ #define GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER 468 /** * Configure underlay link message */ #define GNUNET_MESSAGE_TYPE_TESTBED_CONFIGURE_UNDERLAY_LINK 469 /** * Message to connect peers in a overlay */ #define GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT 470 /** * Message for peer events */ #define GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT 471 /** * Message for peer connect events */ #define GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT 472 /** * Message for operation events */ #define GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT 473 /** * Message to signal successful peer creation */ #define GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS 474 /** * Message to signal a generic operation has been successful */ #define GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS 475 /** * Message to get a peer's information */ #define GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION 476 /** * Message containing the peer's information */ #define GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION 477 /** * Message to request a controller to make one of its peer to connect to another * peer using the contained HELLO */ #define GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT 478 /** * Message to request configuration of a slave controller */ #define GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION 479 /** * Message which contains the configuration of slave controller */ #define GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION 480 /** * Message to signal the result of GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS request */ #define GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT 481 /** * A controller receiving this message floods it to its directly-connected * sub-controllers and then stops and destroys all peers */ #define GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS 482 /** * Message to start/stop a service of a peer */ #define GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE 483 /** * Message to initialise a barrier. Messages of these type are flooded to all * sub-controllers */ #define GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT 484 /** * Message to cancel a barrier. This message is flooded to all sub-controllers */ #define GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL 485 /** * Message for signalling status of a barrier */ #define GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS 486 /** * Message sent by a peer when it has reached a barrier and is waiting for it to * be crossed */ #define GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT 487 /** * Not really a message, but for careful checks on the testbed messages; Should * always be the maximum and never be used to send messages with this type */ #define GNUNET_MESSAGE_TYPE_TESTBED_MAX 488 /** * The initialization message towards gnunet-testbed-helper */ #define GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT 495 /** * The reply message from gnunet-testbed-helper */ #define GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY 496 /****************************************************************************** * GNS. *****************************************************************************/ /** * Client would like to resolve a name. */ #define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 500 /** * Service response to name resolution request from client. */ #define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 501 /******************************************************************************* * CONSENSUS message types ******************************************************************************/ /** * Join a consensus session. Sent by client to service as first message. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN 520 /** * Insert an element. Sent by client to service. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT 521 /** * Begin accepting new elements from other participants. * Sent by client to service. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_BEGIN 522 /** * Sent by service when a new element is added. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT 523 /** * Sent by client to service in order to start the consensus conclusion. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE 524 /** * Sent by service to client in order to signal a completed consensus conclusion. * Last message sent in a consensus session. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE 525 /* message types 526-539 reserved for consensus client/service messages */ /** * Sent by client to service, telling whether a received element should * be accepted and propagated further or not. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_ACK 540 /** * Strata estimator. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_DELTA_ESTIMATE 541 /** * IBF containing all elements of a peer. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_DIFFERENCE_DIGEST 542 /** * One or more elements that are sent from peer to peer. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ELEMENTS 543 /** * Elements, and requests for further elements */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ELEMENTS_REQUEST 544 /** * Elements that a peer reports to be missing at the remote peer. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ELEMENTS_REPORT 545 /* * Initialization message for consensus p2p communication. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_HELLO 546 /** * Report that the peer is synced with the partner after successfuly decoding the invertible bloom filter. */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_SYNCED 547 /** * Interaction os over, got synched and reported all elements */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_FIN 548 /** * Abort a round, don't send requested elements anymore */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ABORT 548 /** * Abort a round, don't send requested elements anymore */ #define GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT 547 /******************************************************************************* * SET message types ******************************************************************************/ #define GNUNET_MESSAGE_TYPE_SET_REJECT 569 /** * Cancel a set operation */ #define GNUNET_MESSAGE_TYPE_SET_CANCEL 570 /** * Acknowledge result from iteration */ #define GNUNET_MESSAGE_TYPE_SET_ITER_ACK 571 /** * Create an empty set */ #define GNUNET_MESSAGE_TYPE_SET_RESULT 572 /** * Add element to set */ #define GNUNET_MESSAGE_TYPE_SET_ADD 573 /** * Remove element from set */ #define GNUNET_MESSAGE_TYPE_SET_REMOVE 574 /** * Listen for operation requests */ #define GNUNET_MESSAGE_TYPE_SET_LISTEN 575 /** * Accept a set request */ #define GNUNET_MESSAGE_TYPE_SET_ACCEPT 576 /** * Evaluate a set operation */ #define GNUNET_MESSAGE_TYPE_SET_EVALUATE 577 /** * Start a set operation with the given set */ #define GNUNET_MESSAGE_TYPE_SET_CONCLUDE 578 /** * Notify the client of a request from a remote peer */ #define GNUNET_MESSAGE_TYPE_SET_REQUEST 579 /** * Create a new local set */ #define GNUNET_MESSAGE_TYPE_SET_CREATE 580 /** * Request a set operation from a remote peer. */ #define GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST 581 /** * Strata estimator. */ #define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE 582 /** * Invertible bloom filter. */ #define GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF 583 /** * Actual set elements. */ #define GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS 584 /** * Requests for the elements with the given hashes. */ #define GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS 585 /** * Operation is done. */ #define GNUNET_MESSAGE_TYPE_SET_P2P_DONE 586 /** * Start iteration over set elements. */ #define GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST 587 /** * Element result for the iterating client. */ #define GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT 588 /** * Iteration end marker for the client. */ #define GNUNET_MESSAGE_TYPE_SET_ITER_DONE 589 /** * Information about the element count for intersection */ #define GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO 591 /** * Bloom filter message for intersection exchange started by Bob. */ #define GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF 592 /** * Bloom filter message for intersection exchange started by Bob. */ #define GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF_PART 593 /******************************************************************************* * TESTBED LOGGER message types ******************************************************************************/ /** * Message for TESTBED LOGGER */ #define GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG 600 /** * Message for TESTBED LOGGER acknowledgement */ #define GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_ACK 601 /******************************************************************************* * EXPERIMENTATION message types ******************************************************************************/ /** * Message for experimentation request */ #define GNUNET_MESSAGE_TYPE_EXPERIMENTATION_REQUEST 610 /** * Message for experimentation response */ #define GNUNET_MESSAGE_TYPE_EXPERIMENTATION_RESPONSE 611 /** * Message for experimentation response */ #define GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START 612 /** * Message for experimentation response */ #define GNUNET_MESSAGE_TYPE_EXPERIMENTATION_START_ACK 613 /** * Message for experimentation response */ #define GNUNET_MESSAGE_TYPE_EXPERIMENTATION_STOP 614 /** * Advertise regex capability. */ #define GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE 620 /** * Search for peer with matching capability. */ #define GNUNET_MESSAGE_TYPE_REGEX_SEARCH 621 /** * Result in response to regex search. */ #define GNUNET_MESSAGE_TYPE_REGEX_RESULT 622 /******************************************************************************* * IDENTITY message types ******************************************************************************/ /** * First message send from identity client to service (to subscribe to * updates). */ #define GNUNET_MESSAGE_TYPE_IDENTITY_START 624 /** * Generic response from identity service with success and/or error message. */ #define GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE 625 /** * Update about identity status from service to clients. */ #define GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE 626 /** * Client requests to know default identity for a subsystem. */ #define GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT 627 /** * Client sets default identity; or service informs about default identity. */ #define GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT 628 /** * Create new identity (client->service). */ #define GNUNET_MESSAGE_TYPE_IDENTITY_CREATE 629 /** * Rename existing identity (client->service). */ #define GNUNET_MESSAGE_TYPE_IDENTITY_RENAME 630 /** * Delete identity (client->service). */ #define GNUNET_MESSAGE_TYPE_IDENTITY_DELETE 631 /******************************************************************************* * REVOCATION message types ******************************************************************************/ /** * Client to service: was this key revoked? */ #define GNUNET_MESSAGE_TYPE_REVOCATION_QUERY 636 /** * Service to client: answer if key was revoked! */ #define GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE 637 /** * Client to service OR peer-to-peer: revoke this key! */ #define GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE 638 /** * Service to client: revocation confirmed */ #define GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE 639 /******************************************************************************* * SCALARPRODUCT message types ******************************************************************************/ /** * Client -> Vector-Product Service request message */ #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE 640 /** * Client -> Vector-Product Service request message */ #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB 641 /** * Vector-Product Service request -> remote VP Service */ #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB 642 /** * Vector-Product Service request -> remote VP Service Multipart */ #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART 643 /** * remote Vector-Product Service response -> requesting VP Service */ #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE 644 /** * remote Vector-Product Service response -> requesting VP Service Multipart */ #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE_MULTIPART 645 /** * Vector-Product Service response -> Client */ #define GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT 646 /******************************************************************************* * PSYCSTORE message types ******************************************************************************/ /** * Store a membership event. */ #define GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE 650 /** * Test for membership of a member at a particular point in time. */ #define GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST 651 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE 652 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET 653 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET 654 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET_FRAGMENT 655 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET 656 /* 657 */ #define GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY 658 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC 659 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_RESET 660 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_HASH_UPDATE 661 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET 662 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET_PREFIX 663 /** * Generic response from PSYCstore service with success and/or error message. */ #define GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE 664 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_FRAGMENT 665 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS 666 #define GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE 667 /******************************************************************************* * PSYC message types ******************************************************************************/ /** * C: client * S: service * M: muticast */ /** S->C: result of an operation */ #define GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE 680 /** C->S: request to start a master */ #define GNUNET_MESSAGE_TYPE_PSYC_MASTER_START 681 /** S->C: master start acknowledgement */ #define GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK 682 /** C->S: request to start a master */ #define GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN 683 /** S->C: slave join acknowledgement */ #define GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK 684 /* 685-686 */ /** M->S->C: incoming join request from multicast */ #define GNUNET_MESSAGE_TYPE_PSYC_JOIN_REQUEST 687 /** C->S->M: decision about a join request */ #define GNUNET_MESSAGE_TYPE_PSYC_JOIN_DECISION 688 /** C->S: request to remove channel slave from the membership database. */ #define GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_ADD 689 /** C->S: request to add channel slave to the membership database */ #define GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_RM 690 /** M<->S<->C: PSYC message which contains one or more message parts. */ #define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE 691 /** Message part: method */ #define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD 692 /** Message part: modifier */ #define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER 693 /** Message part: modifier continuation */ #define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT 694 /** Message part: data */ #define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA 695 /** Message part: end of message */ #define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END 696 /** Message part: message cancelled */ #define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL 697 /** S->C: message acknowledgment */ #define GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK 698 /* 699-700 */ /** C->S: client requests channel history from PSYCstore. */ #define GNUNET_MESSAGE_TYPE_PSYC_STORY_REQUEST 701 /** S->C: result for a channel history request */ #define GNUNET_MESSAGE_TYPE_PSYC_STORY_RESULT 702 /** C->S: request best matching state variable from PSYCstore. */ #define GNUNET_MESSAGE_TYPE_PSYC_STATE_GET 703 /** C->S: request state variables with a given prefix from PSYCstore. */ #define GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX 704 /** S->C: result for a state request. */ #define GNUNET_MESSAGE_TYPE_PSYC_STATE_RESULT 705 /******************************************************************************* * CONVERSATION message types ******************************************************************************/ /** * Message to transmit the audio between helper and speaker/microphone library. */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO 730 /** * Client -> Server message to register a phone. */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER 731 /** * Client -> Server message to reject/hangup a call */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP 732 /** * Client -> Server message to reject/hangup a call */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP 733 /** * Client <- Server message to indicate a ringing phone */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL 734 /** * Client <- Server message to indicate a ringing phone */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING 735 /** * Client <-> Server message to suspend connection. */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND 736 /** * Client <-> Server message to resume connection. */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME 737 /** * Client <-> Server message to send audio data. */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP 738 /** * Client <-> Server message to send audio data. */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO 739 /** * Mesh: call initiation */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RING 740 /** * Mesh: hang up / refuse call */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_HANG_UP 741 /** * Mesh: pick up phone (establish audio channel) */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_PICK_UP 742 /** * Mesh: phone suspended. */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_SUSPEND 743 /** * Mesh: phone resumed. */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_RESUME 744 /** * Mesh: audio data */ #define GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_AUDIO 745 /******************************************************************************* * MULTICAST message types ******************************************************************************/ /* WIP: no numbers assigned yet */ /** * Start an origin. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_START 750 /** * Stop an origin. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_ORIGIN_STOP 751 /** * Join a group as a member. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_JOIN 752 /** * Leave a group. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_MEMBER_PART 753 /** * Multicast message from the origin to all members. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE 754 /** * A unicast message from a group member to the origin. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST 755 /** * A peer wants to join the group. * * Unicast message to the origin or another group member. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_REQUEST /** * Response to a join request. * * Unicast message from a group member to the peer wanting to join. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_JOIN_DECISION /** * A peer wants to part the group. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_PART_REQUEST /** * Acknowledgement sent in response to a part request. * * Unicast message from a group member to the peer wanting to part. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_PART_ACK /** * Group terminated. */ #define GNUNET_MESSAGE_TYPE_MULTICAST_GROUP_END /** * */ #define GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST /** * */ #define GNUNET_MESSAGE_TYPE_MULTICAST_REPLAY_REQUEST_CANCEL /******************************************************************************* * SECRETSHARING message types ******************************************************************************/ /** * Establish a new session. */ #define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE 780 /** * Request the decryption of a ciphertext. */ #define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT 781 /** * The service succeeded in decrypting a ciphertext. */ #define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE 782 /** * The cryptosystem has been established. * Contains the peer's share. */ #define GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY 783 /** * Next available: 800 */ /******************************************************************************* * SOCIAL message types ******************************************************************************/ /** * Type used to match 'all' message types. */ #define GNUNET_MESSAGE_TYPE_ALL 65535 #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group protocols */ /* ifndef GNUNET_PROTOCOLS_H */ #endif /* end of gnunet_protocols.h */ gnunet-0.10.1/src/include/gnunet_testbed_service.h0000644000175000017500000017404512310570720017137 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_testbed_service.h * @brief API for writing tests and creating large-scale * emulation testbeds for GNUnet. * @author Christian Grothoff */ #ifndef GNUNET_TESTBED_SERVICE_H #define GNUNET_TESTBED_SERVICE_H #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Opaque handle to a host running experiments managed by the testbed framework. * The master process must be able to SSH to this host without password (via * ssh-agent). */ struct GNUNET_TESTBED_Host; /** * Opaque handle to a peer controlled by the testbed framework. A peer runs * at a particular host. */ struct GNUNET_TESTBED_Peer; /** * Opaque handle to an abstract operation to be executed by the testbed framework. */ struct GNUNET_TESTBED_Operation; /** * Handle to interact with a GNUnet testbed controller. Each * controller has at least one master handle which is created when the * controller is created; this master handle interacts with the * controller process, destroying it destroys the controller (by * closing stdin of the controller process). Additionally, * controllers can interact with each other (in a P2P fashion); those * links are established via TCP/IP on the controller's service port. */ struct GNUNET_TESTBED_Controller; /** * Create a host to run peers and controllers on. * * @param hostname name of the host, use "NULL" for localhost * @param username username to use for the login; may be NULL * @param cfg the configuration to use as a template while starting a controller * on this host. Operation queue sizes specific to a host are also * read from this configuration handle * @param port port number to use for ssh; use 0 to let ssh decide * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_create (const char *hostname, const char *username, const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t port); /** * Create a host to run peers and controllers on. This function is used * if a peer learns about a host via IPC between controllers (and thus * some higher-level controller has already determined the unique IDs). * * @param id global host ID assigned to the host; 0 is * reserved to always mean 'localhost' * @param hostname name of the host, use "NULL" for localhost * @param username username to use for the login; may be NULL * @param cfg the configuration to use as a template while starting a controller * on this host. Operation queue sizes specific to a host are also * read from this configuration handle * @param port port number to use for ssh; use 0 to let ssh decide * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname, const char *username, const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t port); /** * Load a set of hosts from a configuration file. The hostfile format is * specified at https://gnunet.org/content/hosts-file-format * * @param filename file with the host specification * @param cfg the configuration to use as a template while starting a controller * on any of the loaded hosts. Operation queue sizes specific to a host * are also read from this configuration handle * @param hosts set to the hosts found in the file; caller must free this if * number of hosts returned is greater than 0 * @return number of hosts returned in 'hosts', 0 on error */ unsigned int GNUNET_TESTBED_hosts_load_from_file (const char *filename, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTBED_Host ***hosts); /** * Loads the set of host allocated by the LoadLeveler Job Scheduler. This * function is only available when compiled with support for LoadLeveler and is * used for running on the SuperMUC * * @param cfg the configuration to use as a template while starting a controller * on any of the loaded hosts. Operation queue sizes specific to a host * are also read from this configuration handle * @param hosts set to the hosts found in the file; caller must free this if * number of hosts returned is greater than 0 * @return number of hosts returned in 'hosts', 0 on error */ unsigned int GNUNET_TESTBED_hosts_load_from_loadleveler (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTBED_Host ***hosts); /** * Destroy a host handle. Must only be called once everything * running on that host has been stopped. * * @param host handle to destroy */ void GNUNET_TESTBED_host_destroy (struct GNUNET_TESTBED_Host *host); /** * The handle for whether a host is habitable or not */ struct GNUNET_TESTBED_HostHabitableCheckHandle; /** * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to * inform whether the given host is habitable or not. The Handle returned by * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called * * @param cls the closure given to GNUNET_TESTBED_is_host_habitable() * @param host the host whose status is being reported; will be NULL if the host * given to GNUNET_TESTBED_is_host_habitable() is NULL * @param status GNUNET_YES if it is habitable; GNUNET_NO if not */ typedef void (*GNUNET_TESTBED_HostHabitableCallback) (void *cls, const struct GNUNET_TESTBED_Host *host, int status); /** * Checks whether a host can be used to start testbed service * * @param host the host to check * @param config the configuration handle to lookup the path of the testbed * helper * @param cb the callback to call to inform about habitability of the given host * @param cb_cls the closure for the callback * @return NULL upon any error or a handle which can be passed to * GNUNET_TESTBED_is_host_habitable_cancel() */ struct GNUNET_TESTBED_HostHabitableCheckHandle * GNUNET_TESTBED_is_host_habitable (const struct GNUNET_TESTBED_Host *host, const struct GNUNET_CONFIGURATION_Handle *config, GNUNET_TESTBED_HostHabitableCallback cb, void *cb_cls); /** * Function to cancel a request started using GNUNET_TESTBED_is_host_habitable() * * @param handle the habitability check handle */ void GNUNET_TESTBED_is_host_habitable_cancel (struct GNUNET_TESTBED_HostHabitableCheckHandle *handle); /** * Obtain the host's hostname. * * @param host handle to the host, NULL means 'localhost' * @return hostname of the host */ const char * GNUNET_TESTBED_host_get_hostname (const struct GNUNET_TESTBED_Host *host); /** * Enumeration with (at most 64) possible event types that * can be monitored using the testbed framework. */ enum GNUNET_TESTBED_EventType { /** * A peer has been started. */ GNUNET_TESTBED_ET_PEER_START = 0, /** * A peer has been stopped. */ GNUNET_TESTBED_ET_PEER_STOP = 1, /** * A connection between two peers was established. */ GNUNET_TESTBED_ET_CONNECT = 2, /** * A connection between two peers was torn down. */ GNUNET_TESTBED_ET_DISCONNECT = 3, /** * A requested testbed operation has been completed. */ GNUNET_TESTBED_ET_OPERATION_FINISHED = 4, }; /** * Types of information that can be requested about a peer. */ enum GNUNET_TESTBED_PeerInformationType { /** * Special value (not valid for requesting information) * that is used in the event struct if a 'generic' pointer * is returned (for other operations not related to this * enumeration). */ GNUNET_TESTBED_PIT_GENERIC = 0, /** * What configuration is the peer using? Returns a 'const struct * GNUNET_CONFIGURATION_Handle *'. Valid until * 'GNUNET_TESTNIG_operation_done' is called. However, the * values may be inaccurate if the peer is reconfigured in * the meantime. */ GNUNET_TESTBED_PIT_CONFIGURATION, /** * What is the identity of the peer? Returns a * 'const struct GNUNET_PeerIdentity *'. Valid until * 'GNUNET_TESTNIG_operation_done' is called. */ GNUNET_TESTBED_PIT_IDENTITY }; /** * Argument to GNUNET_TESTBED_ControllerCallback with details about * the event. */ struct GNUNET_TESTBED_EventInformation { /** * Type of the event. */ enum GNUNET_TESTBED_EventType type; /** * Handle for the corresponding operation that generated this event */ struct GNUNET_TESTBED_Operation *op; /** * Closure given while creating the above operation */ void *op_cls; /** * Details about the event. */ union { /** * Details about peer start event. */ struct { /** * Handle for the host where the peer * was started. */ struct GNUNET_TESTBED_Host *host; /** * Handle for the peer that was started. */ struct GNUNET_TESTBED_Peer *peer; } peer_start; /** * Details about peer stop event. */ struct { /** * Handle for the peer that was started. */ struct GNUNET_TESTBED_Peer *peer; } peer_stop; /** * Details about connect event. */ struct { /** * Handle for one of the connected peers. */ struct GNUNET_TESTBED_Peer *peer1; /** * Handle for one of the connected peers. */ struct GNUNET_TESTBED_Peer *peer2; } peer_connect; /** * Details about disconnect event. */ struct { /** * Handle for one of the disconnected peers. */ struct GNUNET_TESTBED_Peer *peer1; /** * Handle for one of the disconnected peers. */ struct GNUNET_TESTBED_Peer *peer2; } peer_disconnect; /** * Details about an operation finished event. */ struct { /** * Error message for the operation, NULL on success. */ const char *emsg; /** * No result (NULL pointer) or generic result * (whatever the GNUNET_TESTBED_ConnectAdapter returned). */ void *generic; } operation_finished; } details; }; /** * Signature of the event handler function called by the * respective event controller. * * @param cls closure * @param event information about the event */ typedef void (*GNUNET_TESTBED_ControllerCallback)(void *cls, const struct GNUNET_TESTBED_EventInformation *event); /** * Opaque Handle for Controller process */ struct GNUNET_TESTBED_ControllerProc; /** * Callback to signal successfull startup of the controller process * * @param cls the closure from GNUNET_TESTBED_controller_start() * @param cfg the configuration with which the controller has been started; * NULL if status is not GNUNET_OK * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ typedef void (*GNUNET_TESTBED_ControllerStatusCallback) (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, int status); /** * Starts a controller process at the given host. The given host's configration * is used as a Template configuration to use for the remote controller; the * remote controller will be started with a slightly modified configuration * (port numbers, unix domain sockets and service home values are changed as per * TESTING library on the remote host). The modified configuration replaces the * host's existing configuration before signalling success through the * GNUNET_TESTBED_ControllerStatusCallback() * * @param trusted_ip the ip address of the controller which will be set as TRUSTED * HOST(all connections form this ip are permitted by the testbed) when * starting testbed controller at host. This can either be a single ip * address or a network address in CIDR notation. * @param host the host where the controller has to be started. CANNOT be NULL. * @param cb function called when the controller is successfully started or * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be * called if cb is called with GNUNET_SYSERR as status. Will never be * called in the same task as 'GNUNET_TESTBED_controller_start' * (synchronous errors will be signalled by returning NULL). This * parameter cannot be NULL. * @param cls closure for above callbacks * @return the controller process handle, NULL on errors */ struct GNUNET_TESTBED_ControllerProc * GNUNET_TESTBED_controller_start (const char *trusted_ip, struct GNUNET_TESTBED_Host *host, GNUNET_TESTBED_ControllerStatusCallback cb, void *cls); /** * Stop the controller process (also will terminate all peers and controllers * dependent on this controller). This function blocks until the testbed has * been fully terminated (!). The controller status cb from * GNUNET_TESTBED_controller_start() will not be called. * * @param cproc the controller process handle */ void GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc); /** * Connect to a controller process. The configuration to use for the connection * is retreived from the given host where a controller is started using * GNUNET_TESTBED_controller_start(). * * @param host host to run the controller on; This should be the same host if * the controller was previously started with * GNUNET_TESTBED_controller_start() * @param event_mask bit mask with set of events to call 'cc' for; * or-ed values of "1LL" shifted by the * respective 'enum GNUNET_TESTBED_EventType' * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...") * @param cc controller callback to invoke on events * @param cc_cls closure for cc * @return handle to the controller */ struct GNUNET_TESTBED_Controller * GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host, uint64_t event_mask, GNUNET_TESTBED_ControllerCallback cc, void *cc_cls); /** * Stop the given controller (also will terminate all peers and * controllers dependent on this controller). This function * blocks until the testbed has been fully terminated (!). * * @param c handle to controller to stop */ void GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *c); /** * Opaque handle for host registration */ struct GNUNET_TESTBED_HostRegistrationHandle; /** * Callback which will be called to after a host registration succeeded or failed * * @param cls the closure * @param emsg the error message; NULL if host registration is successful */ typedef void (* GNUNET_TESTBED_HostRegistrationCompletion) (void *cls, const char *emsg); /** * Register a host with the controller. This makes the controller aware of the * host. A host should be registered at the controller before starting a * sub-controller on that host using GNUNET_TESTBED_controller_link(). * * @param controller the controller handle * @param host the host to register * @param cc the completion callback to call to inform the status of * registration. After calling this callback the registration handle * will be invalid. Cannot be NULL * @param cc_cls the closure for the cc * @return handle to the host registration which can be used to cancel the * registration; NULL if another registration handle is present and * is not cancelled */ struct GNUNET_TESTBED_HostRegistrationHandle * GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller, struct GNUNET_TESTBED_Host *host, GNUNET_TESTBED_HostRegistrationCompletion cc, void *cc_cls); /** * Cancel the pending registration. Note that the registration message will * already be queued to be sent to the service, cancellation has only the * effect that the registration completion callback for the registration is * never called and from our perspective the host is not registered until the * completion callback is called. * * @param handle the registration handle to cancel */ void GNUNET_TESTBED_cancel_registration (struct GNUNET_TESTBED_HostRegistrationHandle *handle); /** * Callback to be called when an operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ typedef void (*GNUNET_TESTBED_OperationCompletionCallback) (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg); /** * Create a link from slave controller to delegated controller. Whenever the * master controller is asked to start a peer at the delegated controller the * request will be routed towards slave controller (if a route exists). The * slave controller will then route it to the delegated controller. The * configuration of the delegated controller is given and is used to either * create the delegated controller or to connect to an existing controller. Note * that while starting the delegated controller the configuration will be * modified to accommodate available free ports. the 'is_subordinate' specifies * if the given delegated controller should be started and managed by the slave * controller, or if the delegated controller already has a master and the slave * controller connects to it as a non master controller. The success or failure * of this operation will be signalled through the * GNUNET_TESTBED_ControllerCallback() with an event of type * #GNUNET_TESTBED_ET_OPERATION_FINISHED * * @param op_cls the operation closure for the event which is generated to * signal success or failure of this operation * @param master handle to the master controller who creates the association * @param delegated_host requests to which host should be delegated; cannot be NULL * @param slave_host which host is used to run the slave controller; use NULL to * make the master controller connect to the delegated host * @param is_subordinate #GNUNET_YES if the controller at delegated_host should * be started by the slave controller; #GNUNET_NO if the slave * controller has to connect to the already started delegated * controller via TCP/IP * @return the operation handle */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_controller_link (void *op_cls, struct GNUNET_TESTBED_Controller *master, struct GNUNET_TESTBED_Host *delegated_host, struct GNUNET_TESTBED_Host *slave_host, int is_subordinate); /** * Function to acquire the configuration of a running slave controller. The * completion of the operation is signalled through the controller_cb from * GNUNET_TESTBED_controller_connect(). If the operation is successful the * handle to the configuration is available in the generic pointer of * operation_finished field of `struct GNUNET_TESTBED_EventInformation`. * * @param op_cls the closure for the operation * @param master the handle to master controller * @param slave_host the host where the slave controller is running; the handle * to the slave_host should remain valid until this operation is * cancelled or marked as finished * @return the operation handle; NULL if the slave_host is not registered at * master */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_get_slave_config (void *op_cls, struct GNUNET_TESTBED_Controller *master, struct GNUNET_TESTBED_Host *slave_host); /** * Functions of this signature are called when a peer has been successfully * created * * @param cls the closure from GNUNET_TESTBED_peer_create() * @param peer the handle for the created peer; NULL on any error during * creation * @param emsg NULL if peer is not NULL; else MAY contain the error description */ typedef void (*GNUNET_TESTBED_PeerCreateCallback) (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg); /** * Create the given peer at the specified host using the given * controller. If the given controller is not running on the target * host, it should find or create a controller at the target host and * delegate creating the peer. Explicit delegation paths can be setup * using 'GNUNET_TESTBED_controller_link'. If no explicit delegation * path exists, a direct link with a subordinate controller is setup * for the first delegated peer to a particular host; the subordinate * controller is then destroyed once the last peer that was delegated * to the remote host is stopped. * * Creating the peer only creates the handle to manipulate and further * configure the peer; use #GNUNET_TESTBED_peer_start and * #GNUNET_TESTBED_peer_stop to actually start/stop the peer's * processes. * * Note that the given configuration will be adjusted by the * controller to avoid port/path conflicts with other peers. * The "final" configuration can be obtained using * #GNUNET_TESTBED_peer_get_information. * * @param controller controller process to use * @param host host to run the peer on; cannot be NULL * @param cfg Template configuration to use for the peer. Should exist until * operation is cancelled or GNUNET_TESTBED_operation_done() is called * @param cb the callback to call when the peer has been created * @param cls the closure to the above callback * @return the operation handle */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_create (struct GNUNET_TESTBED_Controller *controller, struct GNUNET_TESTBED_Host *host, const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_TESTBED_PeerCreateCallback cb, void *cls); /** * Functions of this signature are called when a peer has been successfully * started or stopped. * * @param cls the closure from GNUNET_TESTBED_peer_start/stop() * @param emsg NULL on success; otherwise an error description */ typedef void (*GNUNET_TESTBED_PeerChurnCallback) (void *cls, const char *emsg); /** * Start the given peer. * * @param op_cls the closure for this operation; will be set in the event * information * @param peer peer to start * @param pcc function to call upon completion * @param pcc_cls closure for 'pcc' * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_start (void *op_cls, struct GNUNET_TESTBED_Peer *peer, GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls); /** * Stop the given peer. The handle remains valid (use * #GNUNET_TESTBED_peer_destroy to fully clean up the * state of the peer). * * @param op_cls the closure for this operation; will be set in the event * information * @param peer peer to stop * @param pcc function to call upon completion * @param pcc_cls closure for 'pcc' * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_stop (void *op_cls, struct GNUNET_TESTBED_Peer *peer, GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls); /** * Data returned from GNUNET_TESTBED_peer_get_information */ struct GNUNET_TESTBED_PeerInformation { /** * Peer information type; captures which of the types * in the 'op_result' is actually in use. */ enum GNUNET_TESTBED_PeerInformationType pit; /** * The result of the get information operation; Choose according to the pit */ union { /** * The configuration of the peer */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The identity of the peer */ struct GNUNET_PeerIdentity *id; } result; }; /** * Callback to be called when the requested peer information is available * The peer information in the callback is valid until the operation 'op' is canceled. * * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() * @param op the operation this callback corresponds to * @param pinfo the result; will be NULL if the operation has failed * @param emsg error message if the operation has failed; will be NULL if the * operation is successfull */ typedef void (*GNUNET_TESTBED_PeerInfoCallback) (void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg); /** * Request information about a peer. The controller callback will not be called * with event type #GNUNET_TESTBED_ET_OPERATION_FINISHED when result for this * operation is available. Instead, the GNUNET_TESTBED_PeerInfoCallback() will * be called. * The peer information in the callback is valid until the operation is canceled. * * @param peer peer to request information about * @param pit desired information * @param cb the convenience callback to be called when results for this * operation are available * @param cb_cls the closure for @a cb * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer, enum GNUNET_TESTBED_PeerInformationType pit, GNUNET_TESTBED_PeerInfoCallback cb, void *cb_cls); /** * Change @a peer configuration. Ports and paths cannot be changed this * way. * * @param peer peer to change configuration for * @param cfg new configuration * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer, const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Destroy the given peer; the peer should have been * stopped first (if it was started). * * @param peer peer to stop * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer); /** * Start or stop given service at a peer. This should not be called to * start/stop the peer's ARM service. Use GNUNET_TESTBED_peer_start(), * GNUNET_TESTBED_peer_stop() for starting/stopping peer's ARM service. Success * or failure of the generated operation is signalled through the controller * event callback and/or operation completion callback. * * @param op_cls the closure for the operation * @param peer the peer whose service is to be started/stopped * @param service_name the name of the service * @param cb the operation completion callback * @param cb_cls the closure for @a cb * @param start 1 to start the service; 0 to stop the service * @return an operation handle; NULL upon error (peer not running) */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_manage_service (void *op_cls, struct GNUNET_TESTBED_Peer *peer, const char *service_name, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls, unsigned int start); /** * Stops and destroys all peers. Is equivalent of calling * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers, * except that the peer stop event and operation finished event corresponding to * the respective functions are not generated. This function should be called * when there are no other pending operations. If there are pending operations, * it will return NULL * * @param c the controller to send this message to * @param op_cls closure for the operation * @param cb the callback to call when all peers are stopped and destroyed * @param cb_cls the closure for the callback * @return operation handle on success; NULL if any pending operations are * present */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c, void *op_cls, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls); /** * Options for peer connections. */ enum GNUNET_TESTBED_ConnectOption { /** * No option (not valid as an argument). */ GNUNET_TESTBED_CO_NONE = 0, /** * Allow or disallow a connection between the specified peers. * Followed by #GNUNET_NO (int) if a connection is disallowed * or #GNUNET_YES if a connection is allowed. Note that the * default (all connections allowed or disallowed) is * specified in the configuration of the controller. */ GNUNET_TESTBED_CO_ALLOW = 1, /** * FIXME: add (and implement) options to limit connection to * particular transports, force simulation of particular latencies * or message loss rates, or set bandwidth limitations. */ }; /** * Manipulate the P2P underlay topology by configuring a link * between two peers. * * @param op_cls closure argument to give with the operation event * @param p1 first peer * @param p2 second peer * @param co option to change * @param ap option-specific values * @return handle to the operation, NULL if configuring the link at this * time is not allowed */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_link_va (void *op_cls, struct GNUNET_TESTBED_Peer *p1, struct GNUNET_TESTBED_Peer *p2, enum GNUNET_TESTBED_ConnectOption co, va_list ap); /** * Manipulate the P2P underlay topology by configuring a link * between two peers. * * @param op_cls closure argument to give with the operation event * @param p1 first peer * @param p2 second peer * @param co option to change * @param ... option-specific values * @return handle to the operation, NULL if configuring the link at this * time is not allowed */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_link (void *op_cls, struct GNUNET_TESTBED_Peer *p1, struct GNUNET_TESTBED_Peer *p2, enum GNUNET_TESTBED_ConnectOption co, ...); /** * Topologies and topology options supported for testbeds. Options should always * end with GNUNET_TESTBED_TOPOLOGY_OPTION_END */ enum GNUNET_TESTBED_TopologyOption { /** * A clique (everyone connected to everyone else). No options. If there are N * peers this topology results in (N * (N -1)) connections. */ GNUNET_TESTBED_TOPOLOGY_CLIQUE, /** * Small-world network (2d torus plus random links). Followed * by the number of random links to add (unsigned int). */ GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD, /** * Small-world network (ring plus random links). Followed * by the number of random links to add (unsigned int). */ GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING, /** * Ring topology. No options. */ GNUNET_TESTBED_TOPOLOGY_RING, /** * 2-d torus. No options. */ GNUNET_TESTBED_TOPOLOGY_2D_TORUS, /** * Random graph. Followed by the number of random links to be established * (unsigned int) */ GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, /** * Certain percentage of peers are unable to communicate directly * replicating NAT conditions. Followed by the fraction of * NAT'ed peers (float). */ GNUNET_TESTBED_TOPOLOGY_INTERNAT, /** * Scale free topology. It is generated according to the method described in * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999. * * This options takes two arguments in the following order: an uint16_t to * determine the maximum number of edges a peer is permitted to have while * generating scale free topology, a good value for this argument is 70; and * an uint8_t to determine the number of edges to be established when adding a * new node to the scale free network, a good value for this argument is 4. */ GNUNET_TESTBED_TOPOLOGY_SCALE_FREE, /** * Straight line topology. No options. */ GNUNET_TESTBED_TOPOLOGY_LINE, /** * Read a topology from a given file. Followed by the name of the file (const char *). */ GNUNET_TESTBED_TOPOLOGY_FROM_FILE, /** * All peers are disconnected. No options. */ GNUNET_TESTBED_TOPOLOGY_NONE, /** * The options should always end with this */ GNUNET_TESTBED_TOPOLOGY_OPTION_END, /* The following are not topologies but influence how the topology has to be setup. These options should follow the topology specific options (if required by the chosen topology). Note that these should be given before GNUNET_TESTBED_TOPOLOGY_OPTION_END */ /** * How many times should the failed overlay connect operations be retried * before giving up. The default if this option is not specified is to retry * 3 times. This option takes and unsigned integer as a parameter. Use this * option with parameter 0 to disable retrying of failed overlay connect * operations. */ GNUNET_TESTBED_TOPOLOGY_RETRY_CNT }; /** * Configure overall network topology to have a particular shape. * * @param op_cls closure argument to give with the operation event * @param num_peers number of peers in 'peers' * @param peers array of 'num_peers' with the peers to configure * @param topo desired underlay topology to use * @param ap topology-specific options * @return handle to the operation, NULL if configuring the topology * is not allowed at this time */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, enum GNUNET_TESTBED_TopologyOption topo, va_list ap); /** * Configure overall network topology to have a particular shape. * * @param op_cls closure argument to give with the operation event * @param num_peers number of peers in 'peers' * @param peers array of 'num_peers' with the peers to configure * @param topo desired underlay topology to use * @param ... topology-specific options * @return handle to the operation, NULL if configuring the topology * is not allowed at this time */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_topology (void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, enum GNUNET_TESTBED_TopologyOption topo, ...); /** * Both peers must have been started before calling this function. * This function then obtains a HELLO from @a p1, gives it to @a p2 * and asks @a p2 to connect to @a p1. * * @param op_cls closure argument to give with the operation event * @param cb the callback to call when this operation has finished * @param cb_cls the closure for @a cb * @param p1 first peer * @param p2 second peer * @return handle to the operation, NULL if connecting these two * peers is fundamentally not possible at this time (peers * not running or underlay disallows) */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_connect (void *op_cls, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls, struct GNUNET_TESTBED_Peer *p1, struct GNUNET_TESTBED_Peer *p2); /** * Callbacks of this type are called when topology configuration is completed * * @param cls the operation closure given to * GNUNET_TESTBED_overlay_configure_topology_va() and * GNUNET_TESTBED_overlay_configure() calls * @param nsuccess the number of successful overlay connects * @param nfailures the number of overlay connects which failed */ typedef void (*GNUNET_TESTBED_TopologyCompletionCallback) (void *cls, unsigned int nsuccess, unsigned int nfailures); /** * All peers must have been started before calling this function. * This function then connects the given peers in the P2P overlay * using the given topology. * * @param op_cls closure argument to give with the peer connect operation events * generated through this function * @param num_peers number of peers in 'peers' * @param peers array of 'num_peers' with the peers to configure * @param max_connections the maximums number of overlay connections that will * be made to achieve the given topology * @param comp_cb the completion callback to call when the topology generation * is completed * @param comp_cb_cls closure for the @a comp_cb * @param topo desired underlay topology to use * @param va topology-specific options * @return handle to the operation, NULL if connecting these * peers is fundamentally not possible at this time (peers * not running or underlay disallows) or if num_peers is less than 2 */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int *max_connections, GNUNET_TESTBED_TopologyCompletionCallback comp_cb, void *comp_cb_cls, enum GNUNET_TESTBED_TopologyOption topo, va_list va); /** * All peers must have been started before calling this function. * This function then connects the given peers in the P2P overlay * using the given topology. * * @param op_cls closure argument to give with the peer connect operation events * generated through this function * @param num_peers number of peers in 'peers' * @param peers array of 'num_peers' with the peers to configure * @param max_connections the maximums number of overlay connections that will * be made to achieve the given topology * @param comp_cb the completion callback to call when the topology generation * is completed * @param comp_cb_cls closure for the above completion callback * @param topo desired underlay topology to use * @param ... topology-specific options * @return handle to the operation, NULL if connecting these * peers is fundamentally not possible at this time (peers * not running or underlay disallows) or if num_peers is less than 2 */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_configure_topology (void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int *max_connections, GNUNET_TESTBED_TopologyCompletionCallback comp_cb, void *comp_cb_cls, enum GNUNET_TESTBED_TopologyOption topo, ...); /** * Ask the testbed controller to write the current overlay topology to * a file. Naturally, the file will only contain a snapshot as the * topology may evolve all the time. * FIXME: needs continuation!? * * @param controller overlay controller to inspect * @param filename name of the file the topology should * be written to. */ void GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller *controller, const char *filename); /** * Adapter function called to establish a connection to * a service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ typedef void * (*GNUNET_TESTBED_ConnectAdapter)(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Adapter function called to destroy a connection to * a service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ typedef void (*GNUNET_TESTBED_DisconnectAdapter)(void *cls, void *op_result); /** * Callback to be called when a service connect operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ typedef void (*GNUNET_TESTBED_ServiceConnectCompletionCallback) (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg ); /** * Connect to a service offered by the given peer. Will ensure that * the request is queued to not overwhelm our ability to create and * maintain connections with other systems. The actual service * handle is then returned via the 'op_result' member in the event * callback. The @a ca callback is used to create the connection * when the time is right; the @a da callback will be used to * destroy the connection (upon #GNUNET_TESTBED_operation_done). * #GNUNET_TESTBED_operation_done can be used to abort this * operation until the event callback has been called. * * @param op_cls closure to pass in operation event // FIXME: didn't we say we'd no longer use the global callback for these? -CG * @param peer peer that runs the service * @param service_name name of the service to connect to * @param cb the callback to call when this operation is ready (that is, * right after the connect adapter returns) * @param cb_cls closure for @a cb * @param ca helper function to establish the connection * @param da helper function to close the connection * @param cada_cls closure for @a ca and @a da * @return handle for the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_service_connect (void *op_cls, struct GNUNET_TESTBED_Peer *peer, const char *service_name, GNUNET_TESTBED_ServiceConnectCompletionCallback cb, void *cb_cls, GNUNET_TESTBED_ConnectAdapter ca, GNUNET_TESTBED_DisconnectAdapter da, void *cada_cls); /** * This function is used to signal that the event information (struct * GNUNET_TESTBED_EventInformation) from an operation has been fully processed * i.e. if the event callback is ever called for this operation. If the event * callback for this operation has not yet been called, calling this function * cancels the operation, frees its resources and ensures the no event is * generated with respect to this operation. Note that however cancelling an * operation does NOT guarantee that the operation will be fully undone (or that * nothing ever happened). * * This function MUST be called for every operation to fully remove the * operation from the operation queue. After calling this function, if * operation is completed and its event information is of type * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!). * If the operation is generated from GNUNET_TESTBED_service_connect() then * calling this function on such as operation calls the disconnect adapter if * the connect adapter was ever called. * * @param operation operation to signal completion or cancellation */ void GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation); /** * Callback function to process statistic values from all peers. * * @param cls closure * @param peer the peer the statistic belong to * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ typedef int (*GNUNET_TESTBED_StatisticsIterator) (void *cls, const struct GNUNET_TESTBED_Peer *peer, const char *subsystem, const char *name, uint64_t value, int is_persistent); /** * Convenience method that iterates over all (running) peers * and retrieves all statistics from each peer. * * @param num_peers number of peers to iterate over * @param peers array of peers to iterate over * @param subsystem limit to the specified subsystem, NULL for all subsystems * @param name name of the statistic value, NULL for all values * @param proc processing function for each statistic retrieved * @param cont continuation to call once call is completed. The completion of this * operation is *ONLY* signalled through this callback -- no * GNUNET_TESTBED_ET_OPERATION_FINISHED is generated * @param cls closure to pass to proc and cont * @return operation handle to cancel the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_get_statistics (unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, const char *subsystem, const char *name, GNUNET_TESTBED_StatisticsIterator proc, GNUNET_TESTBED_OperationCompletionCallback cont, void *cls); /** * Return the index of the peer inside of the total peer array, * aka. the peer's "unique ID". * * @param peer Peer handle. * * @return The peer's unique ID. */ uint32_t GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer); /** * Handle for testbed run helper funtions */ struct GNUNET_TESTBED_RunHandle; /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers handle to peers run in the testbed. NULL upon timeout (see * GNUNET_TESTBED_test_run()). * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed * @see GNUNET_TESTBED_test_run() */ typedef void (*GNUNET_TESTBED_TestMaster)(void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed); /** * Convenience method for running a testbed with * a single call. Underlay and overlay topology * are configured using the "UNDERLAY" and "OVERLAY" * options in the "[testbed]" section of the configuration\ * (with possible options given in "UNDERLAY_XXX" and/or * "OVERLAY_XXX"). * * The test_master callback will be called once the testbed setup is finished or * upon a timeout. This timeout is given through the configuration file by * setting the option "SETUP_TIMEOUT" in "[TESTBED]" section. * * The testbed is to be terminated using a call to * "GNUNET_SCHEDULER_shutdown". * * @param host_filename name of the file with the 'hosts', NULL * to run everything on 'localhost' * @param cfg configuration to use (for testbed, controller and peers) * @param num_peers number of peers to start; FIXME: maybe put that ALSO into * cfg?; should be greater than 0 * @param event_mask bit mask with set of events to call 'cc' for; * or-ed values of "1LL" shifted by the * respective 'enum GNUNET_TESTBED_EventType' * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...") * @param cc controller callback to invoke on events; This callback is called * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't * set in the event_mask as this is the only way get access to the * handle of each peer * @param cc_cls closure for cc * @param test_master this callback will be called once the test is ready or * upon timeout * @param test_master_cls closure for 'test_master'. */ void GNUNET_TESTBED_run (const char *host_filename, const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, uint64_t event_mask, GNUNET_TESTBED_ControllerCallback cc, void *cc_cls, GNUNET_TESTBED_TestMaster test_master, void *test_master_cls); /** * Convenience method for running a "simple" test on the local system * with a single call from 'main'. Underlay and overlay topology are * configured using the "UNDERLAY" and "OVERLAY" options in the * "[TESTBED]" section of the configuration (with possible options * given in "UNDERLAY_XXX" and/or "OVERLAY_XXX"). * * The test_master callback will be called once the testbed setup is finished or * upon a timeout. This timeout is given through the configuration file by * setting the option "SETUP_TIMEOUT" in "[TESTBED]" section. * * The test is to be terminated using a call to * "GNUNET_SCHEDULER_shutdown". If starting the test fails, * the program is stopped without 'master' ever being run. * * NOTE: this function should be called from 'main', NOT from * within a GNUNET_SCHEDULER-loop. This function will initialze * the scheduler loop, the testbed and then pass control to * 'master'. * * @param testname name of the testcase (to configure logging, etc.) * @param cfg_filename configuration filename to use * (for testbed, controller and peers) * @param num_peers number of peers to start; should be greter than 0 * @param event_mask bit mask with set of events to call 'cc' for; * or-ed values of "1LL" shifted by the * respective 'enum GNUNET_TESTBED_EventType' * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...") * @param cc controller callback to invoke on events; This callback is called * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't * set in the event_mask as this is the only way get access to the * handle of each peer * @param cc_cls closure for @a cc * @param test_master this callback will be called once the test is ready or * upon timeout * @param test_master_cls closure for @a test_master. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_TESTBED_test_run (const char *testname, const char *cfg_filename, unsigned int num_peers, uint64_t event_mask, GNUNET_TESTBED_ControllerCallback cc, void *cc_cls, GNUNET_TESTBED_TestMaster test_master, void *test_master_cls); /** * Obtain handle to the master controller from a testbed run. The handle * returned should not be disconnected. * * @param h the testbed run handle * @return handle to the master controller */ struct GNUNET_TESTBED_Controller * GNUNET_TESTBED_run_get_controller_handle (struct GNUNET_TESTBED_RunHandle *h); /** * Opaque handle for barrier */ struct GNUNET_TESTBED_Barrier; /** * Status of a barrier */ enum GNUNET_TESTBED_BarrierStatus { /** * Barrier initialised successfully */ GNUNET_TESTBED_BARRIERSTATUS_INITIALISED = 1, /** * Barrier is crossed */ GNUNET_TESTBED_BARRIERSTATUS_CROSSED, /** * Error status */ GNUNET_TESTBED_BARRIERSTATUS_ERROR, }; /** * Functions of this type are to be given as callback argument to * GNUNET_TESTBED_barrier_init(). The callback will be called when status * information is available for the barrier. * * @param cls the closure given to GNUNET_TESTBED_barrier_init() * @param name the name of the barrier * @param barrier the barrier handle * @param status status of the barrier; GNUNET_OK if the barrier is crossed; * GNUNET_SYSERR upon error * @param emsg if the status were to be GNUNET_SYSERR, this parameter has the * error messsage */ typedef void (*GNUNET_TESTBED_barrier_status_cb) (void *cls, const char *name, struct GNUNET_TESTBED_Barrier *barrier, enum GNUNET_TESTBED_BarrierStatus status, const char *emsg); /** * Initialise a barrier and call the given callback when the required percentage * of peers (quorum) reach the barrier. * * @param controller the handle to the controller * @param name identification name of the barrier * @param quorum the percentage of peers that is required to reach the barrier. * Peers signal reaching a barrier by calling * GNUNET_TESTBED_barrier_reached(). * @param cb the callback to call when the barrier is reached or upon error. * Cannot be NULL. * @param cls closure for the above callback * @return barrier handle */ struct GNUNET_TESTBED_Barrier * GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, const char *name, unsigned int quorum, GNUNET_TESTBED_barrier_status_cb cb, void *cls); /** * Cancel a barrier. * * @param barrier the barrier handle */ void GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier); /** * Opaque handle for barrier wait */ struct GNUNET_TESTBED_BarrierWaitHandle; /** * Functions of this type are to be given as acallback argumetn to * GNUNET_TESTBED_barrier_wait(). The callback will be called when the barrier * corresponding given in GNUNET_TESTBED_barrier_wait() is crossed or cancelled. * * @param cls closure pointer given to GNUNET_TESTBED_barrier_wait() * @param name the barrier name * @param status GNUNET_SYSERR in case of error while waiting for the barrier; * GNUNET_OK if the barrier is crossed */ typedef void (*GNUNET_TESTBED_barrier_wait_cb) (void *cls, const char *name, int status); /** * Wait for a barrier to be crossed. This function should be called by the * peers which have been started by the testbed. If the peer is not started by * testbed this function may return error * * @param name the name of the barrier * @param cb the barrier wait callback * @param cls the closure for the above callback * @return barrier wait handle which can be used to cancel the waiting at * anytime before the callback is called. NULL upon error. */ struct GNUNET_TESTBED_BarrierWaitHandle * GNUNET_TESTBED_barrier_wait (const char *name, GNUNET_TESTBED_barrier_wait_cb cb, void *cls); /** * Cancel a barrier wait handle. Should not be called in or after the callback * given to GNUNET_TESTBED_barrier_wait() has been called. * * @param h the barrier wait handle */ void GNUNET_TESTBED_barrier_wait_cancel (struct GNUNET_TESTBED_BarrierWaitHandle *h); /** * Model for configuring underlay links of a peer * @ingroup underlay */ struct GNUNET_TESTBED_UnderlayLinkModel; /** * The type of GNUNET_TESTBED_UnderlayLinkModel * @ingroup underlay */ enum GNUNET_TESTBED_UnderlayLinkModelType { /** * The model is based on white listing of peers to which underlay connections * are permitted. Underlay connections to all other peers will not be * permitted. */ GNUNET_TESTBED_UNDERLAYLINKMODELTYPE_BLACKLIST, /** * The model is based on black listing of peers to which underlay connections * are not permitted. Underlay connections to all other peers will be * permitted */ GNUNET_TESTBED_UNDERLAYLINKMODELTYPE_WHITELIST }; /** * Create a GNUNET_TESTBED_UnderlayLinkModel for the given peer. A peer can * have ONLY ONE model and it can be either a blacklist or whitelist based one. * * @ingroup underlay * @param peer the peer for which the model has to be created * @param type the type of the model * @return the model */ struct GNUNET_TESTBED_UnderlayLinkModel * GNUNET_TESTBED_underlaylinkmodel_create (struct GNUNET_TESTBED_Peer *peer, enum GNUNET_TESTBED_UnderlayLinkModelType type); /** * Add a peer to the given model. Underlay connections to the given peer will * be permitted if the model is whitelist based; otherwise they will not be * permitted. * * @ingroup underlay * @param model the model * @param peer the peer to add */ void GNUNET_TESTBED_underlaylinkmodel_add_peer (struct GNUNET_TESTBED_UnderlayLinkModel *model, struct GNUNET_TESTBED_Peer *peer); /** * Set the metrics for a link to the given peer in the underlay model. The link * SHOULD be permittable according to the given model. * * @ingroup underlay * @param model the model * @param peer the other end peer of the link * @param latency latency of the link in microseconds * @param loss data loss of the link expressed as a percentage * @param bandwidth bandwidth of the link in kilobytes per second [kB/s] */ void GNUNET_TESTBED_underlaylinkmodel_set_link (struct GNUNET_TESTBED_UnderlayLinkModel *model, struct GNUNET_TESTBED_Peer *peer, uint32_t latency, uint32_t loss, uint32_t bandwidth); /** * Commit the model. The model is freed in this function(!). * * @ingroup underlay * @param model the model to commit */ void GNUNET_TESTBED_underlaylinkmodel_commit (struct GNUNET_TESTBED_UnderlayLinkModel *model); /** * Free the resources of the model. Use this function only if the model has not * be committed and has to be unallocated. The peer can then have another model * created. * * @ingroup underlay * @param model the model to unallocate */ void GNUNET_TESTBED_underlaylinkmodel_free (struct GNUNET_TESTBED_UnderlayLinkModel *model); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_namestore_plugin.h0000644000175000017500000001134512234007007017327 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_namestore_plugin.h * @brief plugin API for the namestore database backend * @author Christian Grothoff */ #ifndef GNUNET_NAMESTORE_PLUGIN_H #define GNUNET_NAMESTORE_PLUGIN_H #include "gnunet_util_lib.h" #include "gnunet_namestore_service.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Function called by for each matching record. * * @param cls closure * @param zone_key private key of the zone * @param label name that is being mapped (at most 255 characters long) * @param rd_count number of entries in @a rd array * @param rd array of records with data to store */ typedef void (*GNUNET_NAMESTORE_RecordIterator) (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); /** * @brief struct returned by the initialization function of the plugin */ struct GNUNET_NAMESTORE_PluginFunctions { /** * Closure to pass to all plugin functions. */ void *cls; /** * Store a record in the datastore for which we are the authority. * Removes any existing record in the same zone with the same name. * * @param cls closure (internal context for the plugin) * @param zone private key of the zone * @param label name of the record in the zone * @param rd_count number of entries in @a rd array, 0 to delete all records * @param rd array of records with data to store * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*store_records) (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); /** * Lookup records in the datastore for which we are the authority. * * @param cls closure (internal context for the plugin) * @param zone private key of the zone * @param label name of the record in the zone * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*lookup_records) (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls); /** * Iterate over the results for a particular zone in the * datastore. Will return at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param zone private key of the zone, NULL for all zones * @param offset offset in the list of all matching records * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ int (*iterate_records) (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, uint64_t offset, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls); /** * Look for an existing PKEY delegation record for a given public key. * Returns at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param zone private key of the zone to look up in, never NULL * @param value_zone public key of the target zone (value), never NULL * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ int (*zone_to_name) (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls); }; #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_namestore_plugin.h */ #endif gnunet-0.10.1/src/include/gnunet_gnsrecord_lib.h0000644000175000017500000003051712241134530016572 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_gnsrecord_lib.h * @brief API that can be used to manipulate GNS record data * @author Christian Grothoff */ #ifndef GNUNET_GNSRECORD_LIB_H #define GNUNET_GNSRECORD_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Maximum size of a value that can be stored in a GNS block. */ #define GNUNET_GNSRECORD_MAX_BLOCK_SIZE (63 * 1024) /** * Record type indicating any record/'*' */ #define GNUNET_GNSRECORD_TYPE_ANY 0 /** * Record type for GNS zone transfer ("PKEY"). */ #define GNUNET_GNSRECORD_TYPE_PKEY 65536 /** * Record type for GNS nick names ("NICK"). */ #define GNUNET_GNSRECORD_TYPE_NICK 65537 /** * Record type for GNS legacy hostnames ("LEHO"). */ #define GNUNET_GNSRECORD_TYPE_LEHO 65538 /** * Record type for VPN resolution */ #define GNUNET_GNSRECORD_TYPE_VPN 65539 /** * Record type for delegation to DNS. */ #define GNUNET_GNSRECORD_TYPE_GNS2DNS 65540 /** * Record type for a social place. */ #define GNUNET_GNSRECORD_TYPE_PLACE 65541 /** * Record type for a phone (of CONVERSATION). */ #define GNUNET_GNSRECORD_TYPE_PHONE 65542 /** * Flags that can be set for a record. */ enum GNUNET_GNSRECORD_Flags { /** * No special options. */ GNUNET_GNSRECORD_RF_NONE = 0, /** * This is a private record of this peer and it should * thus not be handed out to other peers. */ GNUNET_GNSRECORD_RF_PRIVATE = 2, /** * This record was added automatically by the system * and is pending user confimation. */ GNUNET_GNSRECORD_RF_PENDING = 4, /** * This expiration time of the record is a relative * time (not an absolute time). */ GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION = 8, /** * This record should not be used unless all (other) records with an absolute * expiration time have expired. */ GNUNET_GNSRECORD_RF_SHADOW_RECORD = 16 /** * When comparing flags for record equality for removal, * which flags should must match (in addition to the type, * name, expiration value and data of the record)? All flags * that are not listed here will be ignored for this purpose. * (for example, we don't expect that users will remember to * pass the '--private' option when removing a record from * the namestore, hence we don't require this particular option * to match upon removal). See also * #GNUNET_GNSRECORD_records_cmp. */ #define GNUNET_GNSRECORD_RF_RCMP_FLAGS (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION) }; /** * A GNS record. */ struct GNUNET_GNSRECORD_Data { /** * Binary value stored in the DNS record. Note: "data" must never * be individually 'malloc'ed, but instead always points into some * existing data area. */ const void *data; /** * Expiration time for the DNS record. Can be relative * or absolute, depending on 'flags'. Measured in the same * unit as GNUnet time (microseconds). */ uint64_t expiration_time; /** * Number of bytes in 'data'. */ size_t data_size; /** * Type of the GNS/DNS record. */ uint32_t record_type; /** * Flags for the record. */ enum GNUNET_GNSRECORD_Flags flags; }; GNUNET_NETWORK_STRUCT_BEGIN /** * Information we have in an encrypted block with record data (i.e. in the DHT). */ struct GNUNET_GNSRECORD_Block { /** * Signature of the block. */ struct GNUNET_CRYPTO_EcdsaSignature signature; /** * Derived key used for signing; hash of this is the query. */ struct GNUNET_CRYPTO_EcdsaPublicKey derived_key; /** * Number of bytes signed; also specifies the number of bytes * of encrypted data that follow. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Expiration time of the block. */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /* followed by encrypted data */ }; GNUNET_NETWORK_STRUCT_END /** * Process a records that were decrypted from a block. * * @param cls closure * @param rd_count number of entries in @a rd array * @param rd array of records with data to store */ typedef void (*GNUNET_GNSRECORD_RecordCallback) (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); /* ***************** API related to GNSRECORD plugins ************** */ /** * Convert the binary value @a data of a record of * type @a type to a human-readable string. * * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in @a data * @return NULL on error, otherwise human-readable representation of the value */ char * GNUNET_GNSRECORD_value_to_string (uint32_t type, const void *data, size_t data_size); /** * Convert human-readable version of the value @a s of a record * of type @a type to the respective binary representation. * * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ int GNUNET_GNSRECORD_string_to_value (uint32_t type, const char *s, void **data, size_t *data_size); /** * Convert a type name (i.e. "AAAA") to the corresponding number. * * @param dns_typename name to convert * @return corresponding number, UINT32_MAX on error */ uint32_t GNUNET_GNSRECORD_typename_to_number (const char *dns_typename); /** * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") * * @param type number of a type to convert * @return corresponding typestring, NULL on error */ const char * GNUNET_GNSRECORD_number_to_typename (uint32_t type); /* convenience APIs for serializing / deserializing GNS records */ /** * Calculate how many bytes we will need to serialize the given * records. * * @param rd_count number of records in the @a rd array * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements * @return the required size to serialize */ size_t GNUNET_GNSRECORD_records_get_size (unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); /** * Serialize the given records to the given destination buffer. * * @param rd_count number of records in the @a rd array * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements * @param dest_size size of the destination array @a dst * @param dest where to write the result * @return the size of serialized records, -1 if records do not fit */ ssize_t GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest); /** * Deserialize the given records to the given destination. * * @param len size of the serialized record data * @param src the serialized record data * @param rd_count number of records in the @a dest array * @param dest where to put the data * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_GNSRECORD_records_deserialize (size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest); /* ******* general APIs relating to blocks, records and labels ******** */ /** * Test if a given record is expired. * * @param rd record to test * @return #GNUNET_YES if the record is expired, * #GNUNET_NO if not */ int GNUNET_GNSRECORD_is_expired (const struct GNUNET_GNSRECORD_Data *rd); /** * Convert a UTF-8 string to UTF-8 lowercase * @param src source string * @return converted result */ char * GNUNET_GNSRECORD_string_to_lowercase (const char *src); /** * Convert a zone to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param z public key of a zone * @return string form; will be overwritten by next call to #GNUNET_GNSRECORD_z2s. */ const char * GNUNET_GNSRECORD_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z); /** * Convert public key to the respective absolute domain name in the * ".zkey" pTLD. * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param pkey a public key with a point on the eliptic curve * @return string "X.zkey" where X is the coordinates of the public * key in an encoding suitable for DNS labels. */ const char * GNUNET_GNSRECORD_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey); /** * Convert an absolute domain name in the ".zkey" pTLD to the * respective public key. * * @param zkey string "X.zkey" where X is the public * key in an encoding suitable for DNS labels. * @param pkey set to a public key on the eliptic curve * @return #GNUNET_SYSERR if @a zkey has the wrong syntax */ int GNUNET_GNSRECORD_zkey_to_pkey (const char *zkey, struct GNUNET_CRYPTO_EcdsaPublicKey *pkey); /** * Calculate the DHT query for a given @a label in a given @a zone. * * @param zone private key of the zone * @param label label of the record * @param query hash to use for the query */ void GNUNET_GNSRECORD_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, struct GNUNET_HashCode *query); /** * Calculate the DHT query for a given @a label in a given @a zone. * * @param pub public key of the zone * @param label label of the record * @param query hash to use for the query */ void GNUNET_GNSRECORD_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, struct GNUNET_HashCode *query); /** * Sign name and records * * @param key the private key * @param expire block expiration * @param label the name for the records * @param rd record data * @param rd_count number of records in @a rd */ struct GNUNET_GNSRECORD_Block * GNUNET_GNSRECORD_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count); /** * Check if a signature is valid. This API is used by the GNS Block * to validate signatures received from the network. * * @param block block to verify * @return #GNUNET_OK if the signature is valid */ int GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block); /** * Decrypt block. * * @param block block to decrypt * @param zone_key public key of the zone * @param label the name for the records * @param proc function to call with the result * @param proc_cls closure for @a proc * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was * not well-formed */ int GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls); /** * Compares if two records are equal * * @param a a record * @param b another record * @return #GNUNET_YES if the records are equal, or #GNUNET_NO if not. */ int GNUNET_GNSRECORD_records_cmp (const struct GNUNET_GNSRECORD_Data *a, const struct GNUNET_GNSRECORD_Data *b); /** * Returns the expiration time of the given block of records. The block * expiration time is the expiration time of the record with smallest * expiration time. * * @param rd_count number of records given in @a rd * @param rd array of records * @return absolute expiration time */ struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_hello_lib.h0000644000175000017500000003147312305564550015723 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_hello_lib.h * @brief helper library for handling HELLOs * @author Christian Grothoff */ #ifndef GNUNET_HELLO_LIB_H #define GNUNET_HELLO_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Prefix that every HELLO URI must start with. */ #define GNUNET_HELLO_URI_PREFIX "gnunet://hello/" /** * Prefix that every FRIEND HELLO URI must start with. */ #define GNUNET_FRIEND_HELLO_URI_PREFIX "gnunet://friend-hello/" /** * Additional local information about an address * * These information are only valid for the local peer and are not serialized * when a #GNUNET_HELLO_Message is created */ enum GNUNET_HELLO_AddressInfo { /** * No additional information */ GNUNET_HELLO_ADDRESS_INFO_NONE = 0, /** * This is an inbound address and cannot be used to initiate an outbound * connection to another peer */ GNUNET_HELLO_ADDRESS_INFO_INBOUND = 1 }; /** * An address for communicating with a peer. We frequently * need this tuple and the components cannot really be * separated. This is NOT the format that would be used * on the wire. */ struct GNUNET_HELLO_Address { /** * For which peer is this an address? */ struct GNUNET_PeerIdentity peer; /** * Name of the transport plugin enabling the communication using * this address. */ const char *transport_name; /** * Binary representation of the address (plugin-specific). */ const void *address; /** * Number of bytes in @e address. */ size_t address_length; /** * Extended information about address * * This field contains additional #GNUNET_HELLO_AddressInfo flags e.g. * to indicate an address is inbound and cannot be used to initiate an * outbound connection. * * These information are only valid for the local peer and are not serialized * when a #GNUNET_HELLO_Message is created */ enum GNUNET_HELLO_AddressInfo local_info; }; /** * Allocate an address struct. * * @param peer the peer * @param transport_name plugin name * @param address binary address * @param address_length number of bytes in @a address * @param local_info additional local information for the address * @return the address struct */ struct GNUNET_HELLO_Address * GNUNET_HELLO_address_allocate (const struct GNUNET_PeerIdentity *peer, const char *transport_name, const void *address, size_t address_length, enum GNUNET_HELLO_AddressInfo local_info); /** * Copy an address struct. * * @param address address to copy * @return a copy of the address struct */ struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy (const struct GNUNET_HELLO_Address *address); /** * Compare two addresses. Does NOT compare the peer identity, * that is assumed already to match! * * @param a1 first address * @param a2 second address * @return 0 if the addresses are equal, -1 if @a a1< @a a2, 1 if @a a1> @a a2. */ int GNUNET_HELLO_address_cmp (const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2); /** * Get the size of an address struct. * * @param address address * @return the size */ size_t GNUNET_HELLO_address_get_size (const struct GNUNET_HELLO_Address *address); /** * Check if an address has a local option set * * @param address the address to check * @param option the respective option to check for * @return #GNUNET_YES or #GNUNET_NO */ int GNUNET_HELLO_address_check_option (const struct GNUNET_HELLO_Address *address, enum GNUNET_HELLO_AddressInfo option); /** * Free an address. * * @param addr address to free */ #define GNUNET_HELLO_address_free(addr) GNUNET_free(addr) /** * A HELLO message is used to exchange information about * transports with other peers. This struct is guaranteed * to start with a `struct GNUNET_MessageHeader`, everything else * should be internal to the HELLO library. */ struct GNUNET_HELLO_Message; /** * Return HELLO type * * @param h HELLO Message to test * @return #GNUNET_YES or #GNUNET_NO */ int GNUNET_HELLO_is_friend_only (const struct GNUNET_HELLO_Message *h); /** * Copy the given address information into * the given buffer using the format of HELLOs. * * @param address address to add * @param expiration expiration for the address * @param target where to copy the address * @param max maximum number of bytes to copy to @a target * @return number of bytes copied, 0 if * the target buffer was not big enough. */ size_t GNUNET_HELLO_add_address (const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration, char *target, size_t max); /** * Callback function used to fill a buffer of max bytes with a list of * addresses in the format used by HELLOs. Should use * #GNUNET_HELLO_add_address() as a helper function. * * @param cls closure * @param max maximum number of bytes that can be written to @a buf * @param buf where to write the address information * @return number of bytes written, 0 to signal the * end of the iteration. */ typedef size_t (*GNUNET_HELLO_GenerateAddressListCallback) (void *cls, size_t max, void *buf); /** * Construct a HELLO message given the public key, * expiration time and an iterator that spews the * transport addresses. * * If friend only is set to #GNUNET_YES we create a FRIEND_HELLO which * will not be gossiped to other peers. * * @param publicKey public key to include in the HELLO * @param addrgen callback to invoke to get addresses * @param addrgen_cls closure for @a addrgen * @param friend_only should the returned HELLO be only visible to friends? * @return the hello message */ struct GNUNET_HELLO_Message * GNUNET_HELLO_create (const struct GNUNET_CRYPTO_EddsaPublicKey *publicKey, GNUNET_HELLO_GenerateAddressListCallback addrgen, void *addrgen_cls, int friend_only); /** * Return the size of the given HELLO message. * @param hello to inspect * @return the size, 0 if HELLO is invalid */ uint16_t GNUNET_HELLO_size (const struct GNUNET_HELLO_Message *hello); /** * Construct a HELLO message by merging the * addresses in two existing HELLOs (which * must be for the same peer). * * @param h1 first HELLO message * @param h2 the second HELLO message * @return the combined hello message */ struct GNUNET_HELLO_Message * GNUNET_HELLO_merge (const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2); /** * Test if two HELLO messages contain the same addresses. * If they only differ in expiration time, the lowest * expiration time larger than 'now' where they differ * is returned. * * @param h1 first HELLO message * @param h2 the second HELLO message * @param now time to use for deciding which addresses have * expired and should not be considered at all * @return absolute time forever if the two HELLOs are * totally identical; smallest timestamp >= now if * they only differ in timestamps; * zero if the some addresses with expirations >= now * do not match at all */ struct GNUNET_TIME_Absolute GNUNET_HELLO_equals (const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2, struct GNUNET_TIME_Absolute now); /** * Iterator callback to go over all addresses. * * @param cls closure * @param address the address * @param expiration expiration time * @return #GNUNET_OK to keep the address, * #GNUNET_NO to delete it from the HELLO * #GNUNET_SYSERR to stop iterating (but keep current address) */ typedef int (*GNUNET_HELLO_AddressIterator) (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration); /** * When does the last address in the given HELLO expire? * * @param msg HELLO to inspect * @return time the last address expires, 0 if there are no addresses in the HELLO */ struct GNUNET_TIME_Absolute GNUNET_HELLO_get_last_expiration (const struct GNUNET_HELLO_Message *msg); /** * Iterate over all of the addresses in the HELLO. * * @param msg HELLO to iterate over; client does not need to * have verified that msg is well-formed (beyond starting * with a GNUNET_MessageHeader of the right type). * @param return_modified if a modified copy should be returned, * otherwise NULL will be returned * @param it iterator to call on each address * @param it_cls closure for @a it * @return the modified HELLO or NULL */ struct GNUNET_HELLO_Message * GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg, int return_modified, GNUNET_HELLO_AddressIterator it, void *it_cls); /** * Iterate over addresses in "new_hello" that * are NOT already present in "old_hello". * * @param new_hello a HELLO message * @param old_hello a HELLO message * @param expiration_limit ignore addresses in old_hello * that expired before the given time stamp * @param it iterator to call on each address * @param it_cls closure for @a it */ void GNUNET_HELLO_iterate_new_addresses (const struct GNUNET_HELLO_Message *new_hello, const struct GNUNET_HELLO_Message *old_hello, struct GNUNET_TIME_Absolute expiration_limit, GNUNET_HELLO_AddressIterator it, void *it_cls); /** * Get the public key from a HELLO message. * * @param hello the hello message * @param publicKey where to copy the public key information, can be NULL * @return #GNUNET_SYSERR if the HELLO was malformed */ int GNUNET_HELLO_get_key (const struct GNUNET_HELLO_Message *hello, struct GNUNET_CRYPTO_EddsaPublicKey *publicKey); /** * Get the peer identity from a HELLO message. * * @param hello the hello message * @param peer where to store the peer's identity * @return #GNUNET_SYSERR if the HELLO was malformed */ int GNUNET_HELLO_get_id (const struct GNUNET_HELLO_Message *hello, struct GNUNET_PeerIdentity *peer); /** * Get the header from a HELLO message, used so other code * can correctly send HELLO messages. * * @param hello the hello message * * @return header or NULL if the HELLO was malformed */ struct GNUNET_MessageHeader * GNUNET_HELLO_get_header (struct GNUNET_HELLO_Message *hello); typedef struct GNUNET_TRANSPORT_PluginFunctions * (*GNUNET_HELLO_TransportPluginsFind) (const char *name); /** * Compose a hello URI string from a hello message. * * @param hello Hello message * @param plugins_find Function to find transport plugins by name * @return Hello URI string */ char * GNUNET_HELLO_compose_uri (const struct GNUNET_HELLO_Message *hello, GNUNET_HELLO_TransportPluginsFind plugins_find); /** * Parse a hello URI string to a hello message. * * @param uri URI string to parse * @param pubkey Pointer to struct where public key is parsed * @param hello Pointer to struct where hello message is parsed * @param plugins_find Function to find transport plugins by name * @return #GNUNET_OK on success, #GNUNET_SYSERR if the URI was invalid, #GNUNET_NO on other errors */ int GNUNET_HELLO_parse_uri (const char *uri, struct GNUNET_CRYPTO_EddsaPublicKey *pubkey, struct GNUNET_HELLO_Message **hello, GNUNET_HELLO_TransportPluginsFind plugins_find); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_HELLO_LIB_H */ #endif /* end of gnunet_hello_lib.h */ gnunet-0.10.1/src/include/gnunet_speaker_lib.h0000644000175000017500000000573712225777503016263 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_speaker_lib.h * @brief API to access an audio speaker; provides access to hardware speakers * @author Simon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #ifndef GNUNET_SPEAKER_SERVICE_H #define GNUNET_SPEAKER_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Function that enables a speaker. * * @param cls closure * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ typedef int (*GNUNET_SPEAKER_EnableCallback)(void *cls); /** * Function that disables a speaker. * * @param cls closure */ typedef void (*GNUNET_SPEAKER_DisableCallback)(void *cls); /** * Function to destroy a speaker. * * @param cls closure */ typedef void (*GNUNET_SPEAKER_DestroyCallback)(void *cls); /** * Function to cause a speaker to play audio data. * * @param cls closure * @param data_size number of bytes in @a data * @param data audio data to play, format is * opaque to the API but should be OPUS. */ typedef void (*GNUNET_SPEAKER_PlayCallback)(void *cls, size_t data_size, const void *data); /** * A speaker is a device that can play or record audio data. */ struct GNUNET_SPEAKER_Handle { /** * Turn on the speaker. */ GNUNET_SPEAKER_EnableCallback enable_speaker; /** * Play audio. */ GNUNET_SPEAKER_PlayCallback play; /** * Turn the speaker off. */ GNUNET_SPEAKER_DisableCallback disable_speaker; /** * Destroy the speaker. Called by #GNUNET_SPEAKER_destroy. */ GNUNET_SPEAKER_DestroyCallback destroy_speaker; /** * Closure for the callbacks. */ void *cls; }; /** * Create a speaker that corresponds to the speaker hardware * of our system. * * @param cfg configuration to use * @return NULL on error */ struct GNUNET_SPEAKER_Handle * GNUNET_SPEAKER_create_from_hardware (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Destroy a speaker. * * @param speaker speaker to destroy */ void GNUNET_SPEAKER_destroy (struct GNUNET_SPEAKER_Handle *speaker); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif /* end of gnunet_speaker_lib.h */ gnunet-0.10.1/src/include/gnunet_friends_lib.h0000644000175000017500000000530512316473376016254 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_friends_lib.h * @brief library to read and write the FRIENDS file * @author Christian Grothoff */ #ifndef GNUNET_FRIENDS_LIB_H #define GNUNET_FRIENDS_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Signature of a function called on each friend found. * * @param cls closure * @param friend_id peer identity of the friend */ typedef void (*GNUNET_FRIENDS_Callback)(void *cls, const struct GNUNET_PeerIdentity *friend_id); /** * Parse the FRIENDS file. * * @param cfg our configuration * @param cb function to call on each friend found * @param cb_cls closure for @a cb * @return #GNUNET_OK on success, #GNUNET_SYSERR on parsing errors */ int GNUNET_FRIENDS_parse (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_FRIENDS_Callback cb, void *cb_cls); /** * Handle for writing a friends file. */ struct GNUNET_FRIENDS_Writer; /** * Start writing a fresh FRIENDS file. Will make a backup of the * old one. * * @param cfg configuration to use. * @return NULL on error */ struct GNUNET_FRIENDS_Writer * GNUNET_FRIENDS_write_start (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Finish writing out the friends file. * * @param w write handle * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_FRIENDS_write_stop (struct GNUNET_FRIENDS_Writer *w); /** * Add a friend to the friends file. * * @param w write handle * @param friend_id friend to add * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_FRIENDS_write (struct GNUNET_FRIENDS_Writer *w, const struct GNUNET_PeerIdentity *friend_id); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_revocation_service.h0000644000175000017500000001106512225777503017663 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public Licerevocation as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licerevocation for more details. You should have received a copy of the GNU General Public Licerevocation along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GNUNET_REVOCATION_SERVICE_H_ #define GNUNET_REVOCATION_SERVICE_H_ /** * @file include/gnunet_revocation_service.h * @brief API to perform and access key revocations * @author Christian Grothoff * @defgroup revocation key revocation service * @{ */ #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Version of the key revocation API. */ #define GNUNET_REVOCATION_VERSION 0x00000000 /** * Handle for the key revocation query. */ struct GNUNET_REVOCATION_Query; /** * Callback to call with the result of a key revocation query. * * @param cls closure * @param is_valid #GNUNET_NO of the key is/was revoked, * #GNUNET_YES if the key is still valid, * #GNUNET_SYSERR if we had trouble querying the service * */ typedef void (*GNUNET_REVOCATION_Callback) (void *cls, int is_valid); /** * Check if a key was revoked. * * @param cfg the configuration to use * @param key key to check for revocation * @param func funtion to call with the result of the check * @param func_cls closure to pass to @a func * @return handle to use in #GNUNET_REVOCATION_query_cancel to stop REVOCATION from invoking the callback */ struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls); /** * Cancel key revocation check. * * @param q query to cancel */ void GNUNET_REVOCATION_query_cancel (struct GNUNET_REVOCATION_Query *q); /** * Handle for the key revocation operation. */ struct GNUNET_REVOCATION_Handle; /** * Perform key revocation. * * @param cfg the configuration to use * @param key public key of the key to revoke * @param sig signature to use on the revocation (should have been * created using #GNUNET_REVOCATION_sign_revocation). * @param pow proof of work to use (should have been created by * iteratively calling #GNUNET_REVOCATION_check_pow) * @param func funtion to call with the result of the check * (called with `is_valid` being #GNUNET_NO if * the revocation worked). * @param func_cls closure to pass to @a func * @return handle to use in #GNUNET_REVOCATION_revoke_cancel to stop REVOCATION from invoking the callback */ struct GNUNET_REVOCATION_Handle * GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPublicKey *key, const struct GNUNET_CRYPTO_EcdsaSignature *sig, uint64_t pow, GNUNET_REVOCATION_Callback func, void *func_cls); /** * Cancel key revocation. * * @param h operation to cancel */ void GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h); /** * Check if the given proof-of-work value * would be acceptable for revoking the given key. * * @param key key to check for * @param pow proof of work value * @param matching_bits how many bits must match (configuration) * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not */ int GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, uint64_t pow, unsigned int matching_bits); /** * Create a revocation signature. * * @param key private key of the key to revoke * @param sig where to write the revocation signature */ void GNUNET_REVOCATION_sign_revocation (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, struct GNUNET_CRYPTO_EcdsaSignature *sig); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group revocation */ #endif /* GNUNET_REVOCATION_SERVICE_H_ */ gnunet-0.10.1/src/include/gnunet_fragmentation_lib.h0000644000175000017500000001567512225777503017471 00000000000000/* This file is part of GNUnet (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_fragmentation_lib.h * @brief library to help fragment messages * @author Christian Grothoff * * TODO: consider additional flow-control for sending from * fragmentation based on continuations. */ #ifndef GNUNET_FRAGMENTATION_LIB_H #define GNUNET_FRAGMENTATION_LIB_H #include "gnunet_util_lib.h" #include "gnunet_bandwidth_lib.h" #include "gnunet_statistics_service.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Fragmentation context. */ struct GNUNET_FRAGMENT_Context; /** * Function that is called with messages created by the fragmentation * module. In the case of the 'proc' callback of the * GNUNET_FRAGMENT_context_create function, this function must * eventually call 'GNUNET_FRAGMENT_context_transmission_done'. * * @param cls closure * @param msg the message that was created */ typedef void (*GNUNET_FRAGMENT_MessageProcessor) (void *cls, const struct GNUNET_MessageHeader * msg); /** * Create a fragmentation context for the given message. * Fragments the message into fragments of size "mtu" or * less. Calls 'proc' on each un-acknowledged fragment, * using both the expected 'delay' between messages and * acknowledgements and the given 'tracker' to guide the * frequency of calls to 'proc'. * * @param stats statistics context * @param mtu the maximum message size for each fragment * @param tracker bandwidth tracker to use for flow control (can be NULL) * @param msg_delay initial delay to insert between fragment transmissions * based on previous messages * @param ack_delay expected delay between fragment transmission * and ACK based on previous messages * @param msg the message to fragment * @param proc function to call for each fragment to transmit * @param proc_cls closure for proc * @return the fragmentation context */ struct GNUNET_FRAGMENT_Context * GNUNET_FRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, struct GNUNET_BANDWIDTH_Tracker *tracker, struct GNUNET_TIME_Relative msg_delay, struct GNUNET_TIME_Relative ack_delay, const struct GNUNET_MessageHeader *msg, GNUNET_FRAGMENT_MessageProcessor proc, void *proc_cls); /** * Continuation to call from the 'proc' function after the fragment * has been transmitted (and hence the next fragment can now be * given to proc). * * @param fc fragmentation context */ void GNUNET_FRAGMENT_context_transmission_done (struct GNUNET_FRAGMENT_Context *fc); /** * Process an acknowledgement message we got from the other * side (to control re-transmits). * * @param fc fragmentation context * @param msg acknowledgement message we received * @return GNUNET_OK if this ack completes the work of the 'fc' * (all fragments have been received); * GNUNET_NO if more messages are pending * GNUNET_SYSERR if this ack is not valid for this fc */ int GNUNET_FRAGMENT_process_ack (struct GNUNET_FRAGMENT_Context *fc, const struct GNUNET_MessageHeader *msg); /** * Destroy the given fragmentation context (stop calling 'proc', free * resources). * * @param fc fragmentation context * @param msg_delay where to store average delay between individual message transmissions the * last message (OUT only) * @param ack_delay where to store average delay between transmission and ACK for the * last message, set to FOREVER if the message was not fully transmitted (OUT only) */ void GNUNET_FRAGMENT_context_destroy (struct GNUNET_FRAGMENT_Context *fc, struct GNUNET_TIME_Relative *msg_delay, struct GNUNET_TIME_Relative *ack_delay); /** * Defragmentation context (one per connection). */ struct GNUNET_DEFRAGMENT_Context; /** * Function that is called with acknowledgement messages created by * the fragmentation module. Acknowledgements are cummulative, * so it is OK to only transmit the 'latest' ack message for the same * message ID. * * @param cls closure * @param id unique message ID (modulo collisions) * @param msg the message that was created */ typedef void (*GNUNET_DEFRAGMENT_AckProcessor) (void *cls, uint32_t id, const struct GNUNET_MessageHeader * msg); /** * Create a defragmentation context. * * @param stats statistics context * @param mtu the maximum message size for each fragment * @param num_msgs how many fragmented messages * to we defragment at most at the same time? * @param cls closure for proc and ackp * @param proc function to call with defragmented messages * @param ackp function to call with acknowledgements (to send * back to the other side) * @return the defragmentation context */ struct GNUNET_DEFRAGMENT_Context * GNUNET_DEFRAGMENT_context_create (struct GNUNET_STATISTICS_Handle *stats, uint16_t mtu, unsigned int num_msgs, void *cls, GNUNET_FRAGMENT_MessageProcessor proc, GNUNET_DEFRAGMENT_AckProcessor ackp); /** * Destroy the given defragmentation context. * * @param dc defragmentation context */ void GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc); /** * We have received a fragment. Process it. * * @param dc the context * @param msg the message that was received * @return GNUNET_OK on success, GNUNET_NO if this was a duplicate, GNUNET_SYSERR on error */ int GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc, const struct GNUNET_MessageHeader *msg); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_fragmentation_lib.h */ #endif gnunet-0.10.1/src/include/gnunet_transport_plugin.h0000644000175000017500000005633612316473376017420 00000000000000/* This file is part of GNUnet (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_transport_plugin.h * @brief API for the transport services. This header * specifies the struct that is given to the plugin's entry * method and the other struct that must be returned. * Note that the destructors of transport plugins will * be given the value returned by the constructor * and is expected to return a NULL pointer. * @author Christian Grothoff */ #ifndef PLUGIN_TRANSPORT_H #define PLUGIN_TRANSPORT_H #include "gnunet_configuration_lib.h" #include "gnunet_scheduler_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_ats_service.h" #define TRANSPORT_SESSION_INBOUND_STRING "" /** * Opaque pointer that plugins can use to distinguish specific * connections to a given peer. Typically used by stateful plugins to * allow the service to refer to specific streams instead of a more * general notion of "some connection" to the given peer. This is * useful since sometimes (i.e. for inbound TCP connections) a * connection may not have an address that can be used for meaningful * distinction between sessions to the same peer. * * Each 'struct Session' MUST start with the 'struct GNUNET_PeerIdentity' * of the peer the session is for (which will be used for some error * checking by the ATS code). */ struct Session; /** * Every 'struct Session' must begin with this header. */ struct SessionHeader { /* empty, for now */ }; /** * Function that will be called whenever the plugin internally * cleans up a session pointer and hence the service needs to * discard all of those sessions as well. Plugins that do not * use sessions can simply omit calling this function and always * use NULL wherever a session pointer is needed. This function * should be called BEFORE a potential "TransmitContinuation" * from the "TransmitFunction". * * @param cls closure * @param peer which peer was the session for * @param session which session is being destroyed */ typedef void (*GNUNET_TRANSPORT_SessionEnd) (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session); /** * Plugin tells transport service about a new inbound session * * @param cls unused * @param address the address * @param session the new session * @param ats ats information * @param ats_count number of @a ats information */ typedef void (*GNUNET_TRANSPORT_SessionStart) (void *cls, struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * Function called by the transport for each received message. * This function should also be called with "NULL" for the * message to signal that the other peer disconnected. * * @param cls closure * @param peer (claimed) identity of the other peer * @param message the message, NULL if we only care about * learning about the delay until we should receive again * @param session identifier used for this session (NULL for plugins * that do not offer bi-directional communication to the sender * using the same "connection") * @param sender_address binary address of the sender (if we established the * connection or are otherwise sure of it; should be NULL * for inbound TCP/UDP connections since it it not clear * that we could establish ourselves a connection to that * IP address and get the same system) * @param sender_address_len number of bytes in @a sender_address * @return how long the plugin should wait until receiving more data; * returning #GNUNET_TIME_UNIT_FOREVER_REL means that the * connection should be closed */ typedef struct GNUNET_TIME_Relative (*GNUNET_TRANSPORT_PluginReceiveCallback) (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message); /** * Function that will be called to figure if an address is an loopback, * LAN, WAN etc. address * * @param cls closure * @param addr binary address * @param addrlen length of the @a addr * @return ATS Information containing the network type */ typedef struct GNUNET_ATS_Information (*GNUNET_TRANSPORT_AddressToType) (void *cls, const struct sockaddr *addr, size_t addrlen); /** * Function called when quality properties of an address change. * * @param cls closure * @param peer peer * @param address address * @param address_len length of the @a address * @param session session * @param ats ATS information * @param ats_count number entries in the @a ats array */ typedef void (*GNUNET_TRANSPORT_UpdateAddressMetrics) (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * Function that will be called for each address the transport * is aware that it might be reachable under. * * @param cls closure * @param add_remove should the address added (#GNUNET_YES) or removed (#GNUNET_NO) from the * set of valid addresses? * @param address the address to add or remove */ typedef void (*GNUNET_TRANSPORT_AddressNotification) (void *cls, int add_remove, const struct GNUNET_HELLO_Address *address); /** * Function that will be called whenever the plugin receives data over * the network and wants to determine how long it should wait until * the next time it reads from the given peer. Note that some plugins * (such as UDP) may not be able to wait (for a particular peer), so * the waiting part is optional. Plugins that can wait should call * this function, sleep the given amount of time, and call it again * (with zero bytes read) UNTIL it returns zero and only then read. * * @param cls closure * @param peer which peer did we read data from * @param amount_recved number of bytes read (can be zero) * @return how long to wait until reading more from this peer * (to enforce inbound quotas); returning #GNUNET_TIME_UNIT_FOREVER_REL * means that the connection should be closed */ typedef struct GNUNET_TIME_Relative (*GNUNET_TRANSPORT_TrafficReport) (void *cls, const struct GNUNET_PeerIdentity *peer, size_t amount_recved); typedef void (*GNUNET_TRANSPORT_RegisterQuotaNotification) (void *cls, const struct GNUNET_PeerIdentity *peer, const char *plugin, struct Session *session); typedef void (*GNUNET_TRANSPORT_UnregisterQuotaNotification) (void *cls, const struct GNUNET_PeerIdentity *peer, const char *plugin, struct Session *session); /** * Function that returns a HELLO message. */ typedef const struct GNUNET_MessageHeader * (*GNUNET_TRANSPORT_GetHelloCallback) (void); /** * The transport service will pass a pointer to a struct * of this type as the first and only argument to the * entry point of each transport plugin. */ struct GNUNET_TRANSPORT_PluginEnvironment { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Identity of this peer. */ const struct GNUNET_PeerIdentity *my_identity; /** * Closure for the various callbacks. */ void *cls; /** * Handle for reporting statistics. */ struct GNUNET_STATISTICS_Handle *stats; /** * Function that should be called by the transport plugin * whenever a message is received. If this field is "NULL", * the plugin should load in 'stub' mode and NOT fully * initialize and instead only return an API with the * 'address_pretty_printer', 'address_to_string' and * 'string_to_address' functions. */ GNUNET_TRANSPORT_PluginReceiveCallback receive; /** * Function that returns our HELLO. */ GNUNET_TRANSPORT_GetHelloCallback get_our_hello; /** * Function that must be called by each plugin to notify the * transport service about the addresses under which the transport * provided by the plugin can be reached. */ GNUNET_TRANSPORT_AddressNotification notify_address; /** * Function that must be called by the plugin when a non-NULL * session handle stops being valid (is destroyed). */ GNUNET_TRANSPORT_SessionEnd session_end; /** * Function called by the plugin when a new (incoming) session was created * not explicitly created using the the get_session function */ GNUNET_TRANSPORT_SessionStart session_start; /** * Function that will be called to figure if an address is an loopback, * LAN, WAN etc. address */ GNUNET_TRANSPORT_AddressToType get_address_type; /** * Function that will be called to figure if an address is an loopback, * LAN, WAN etc. address */ GNUNET_TRANSPORT_UpdateAddressMetrics update_address_metrics; GNUNET_TRANSPORT_RegisterQuotaNotification register_quota_notification; GNUNET_TRANSPORT_UnregisterQuotaNotification unregister_quota_notification; /** * What is the maximum number of connections that this transport * should allow? Transports that do not have sessions (such as * UDP) can ignore this value. */ uint32_t max_connections; }; /** * Function called by the #GNUNET_TRANSPORT_TransmitFunction * upon "completion". In the case that a peer disconnects, * this function must be called for each pending request * (with a 'failure' indication) AFTER notifying the service * about the disconnect event (so that the service won't try * to transmit more messages, believing the connection still * exists...). * * @param cls closure * @param target who was the recipient of the message? * @param result #GNUNET_OK on success * #GNUNET_SYSERR if the target disconnected; * disconnect will ALSO be signalled using * the ReceiveCallback. * @param size_payload bytes of payload from transport service in message * @param size_on_wire bytes required on wire for transmission, * 0 if result == #GNUNET_SYSERR */ typedef void (*GNUNET_TRANSPORT_TransmitContinuation) (void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire); /** * The new send function with just the session and no address * * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param session which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in @a msgbuf * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for @a cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ typedef ssize_t (*GNUNET_TRANSPORT_TransmitFunction) (void *cls, struct Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls); /** * Function that can be called to force a disconnect from the * specified neighbour for the given session only. . This should * also cancel all previously scheduled transmissions for this * session. Obviously the transmission may have been partially * completed already, which is OK. The plugin is supposed to close * the connection (if applicable). * * @param cls closure with the `struct Plugin` * @param session session to destroy * @return #GNUNET_OK on success */ typedef int (*GNUNET_TRANSPORT_DisconnectSessionFunction) (void *cls, struct Session *session); /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ typedef unsigned int (*GNUNET_TRANSPORT_QueryKeepaliveFactorFunction) (void *cls); /** * Function that can be called to force a disconnect from the * specified neighbour. This should also cancel all previously * scheduled transmissions. Obviously the transmission may have been * partially completed already, which is OK. The plugin is supposed * to close the connection (if applicable) and no longer call the * transmit continuation(s). * * @param cls closure * @param target peer for which the last transmission is * to be cancelled */ typedef void (*GNUNET_TRANSPORT_DisconnectPeerFunction) (void *cls, const struct GNUNET_PeerIdentity *target); /** * Function called by the pretty printer for the resolved address for * each human-readable address obtained. * * @param cls closure * @param address one of the names for the host, NULL * on the last call to the callback */ typedef void (*GNUNET_TRANSPORT_AddressStringCallback) (void *cls, const char *address); /** * Convert the transports address to a nice, human-readable * format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the @a addr * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for @a asc */ typedef void (*GNUNET_TRANSPORT_AddressPrettyPrinter) (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls); /** * Another peer has suggested an address for this peer and transport * plugin. Check that this could be a valid address. This function * is not expected to 'validate' the address in the sense of trying to * connect to it but simply to see if the binary format is technically * legal for establishing a connection to this peer (and make sure that * the address really corresponds to our network connection/settings * and not some potential man-in-the-middle). * * @param addr pointer to the address * @param addrlen length of @a addr * @return #GNUNET_OK if this is a plausible address for this peer * and transport, #GNUNET_SYSERR if not */ typedef int (*GNUNET_TRANSPORT_CheckAddress) (void *cls, const void *addr, size_t addrlen); /** * Create a new session to transmit data to the target * This session will used to send data to this peer and the plugin will * notify us by calling the env->session_end function * * @param cls the plugin * @param address the hello address * @return the session if the address is valid, NULL otherwise */ typedef struct Session * (*GNUNET_TRANSPORT_CreateSession) (void *cls, const struct GNUNET_HELLO_Address *address); /** * Function that will be called whenever the transport service wants to * notify the plugin that a session is still active and in use and * therefore the session timeout for this session has to be updated * * @param cls closure * @param peer which peer was the session for * @param session which session is being updated */ typedef void (*GNUNET_TRANSPORT_UpdateSessionTimeout) (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session); typedef void (*GNUNET_TRANSPORT_UpdateInboundDelay) (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session, struct GNUNET_TIME_Relative delay); /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param addr binary address * @param addr_len length of the @a addr * @return string representing the same address */ typedef const char * (*GNUNET_TRANSPORT_AddressToString) (void *cls, const void *addr, size_t addrlen); /** * Function called to convert a string address to * a binary address. * * @param cls closure (`struct Plugin*`) * @param addr string address * @param addrlen length of the @a addr including \0 termination * @param buf location to store the buffer * If the function returns #GNUNET_SYSERR, its contents are undefined. * @param added length of created address * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ typedef int (*GNUNET_TRANSPORT_StringToAddress) (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added); /** * Function to obtain the network type for a session * * @param cls closure ('struct Plugin*') * @param session the session * @return the network type */ typedef enum GNUNET_ATS_Network_Type (*GNUNET_TRANSPORT_GetNetworkType) (void *cls, struct Session *session); /** * Each plugin is required to return a pointer to a struct of this * type as the return value from its entry point. */ struct GNUNET_TRANSPORT_PluginFunctions { /** * Closure for all of the callbacks. */ void *cls; /** * Function that the transport service will use to transmit data to * another peer. May be NULL for plugins that only support * receiving data. After this call, the plugin call the specified * continuation with success or error before notifying us about the * target having disconnected. */ GNUNET_TRANSPORT_TransmitFunction send; /** * Function that can be used to force the plugin to disconnect from * the given peer and cancel all previous transmissions (and their * continuations). */ GNUNET_TRANSPORT_DisconnectPeerFunction disconnect_peer; /** * Function that can be used to force the plugin to disconnect from * the given peer and cancel all previous transmissions (and their * continuations). */ GNUNET_TRANSPORT_DisconnectSessionFunction disconnect_session; /** * Function that will be called whenever the transport service wants to * notify the plugin that a session is still active and in use and * therefore the session timeout for this session has to be updated */ GNUNET_TRANSPORT_UpdateSessionTimeout update_session_timeout; GNUNET_TRANSPORT_UpdateInboundDelay update_inbound_delay; /** * Function that will be called whenever the transport service wants to * notify the plugin that the inbound quota changed and that the plugin * should update it's delay for the next receive value */ //GNUNET_TRANSPORT_UpdateNextReceiveTimeout update_next_receive_timeout; /** * Function that is used to query keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. */ GNUNET_TRANSPORT_QueryKeepaliveFactorFunction query_keepalive_factor; /** * Function to pretty-print addresses. NOTE: this function is not * yet used by transport-service, but will be used in the future * once the transport-API has been completed. */ GNUNET_TRANSPORT_AddressPrettyPrinter address_pretty_printer; /** * Function that will be called to check if a binary address * for this plugin is well-formed and corresponds to an * address for THIS peer (as per our configuration). Naturally, * if absolutely necessary, plugins can be a bit conservative in * their answer, but in general plugins should make sure that the * address does not redirect traffic to a 3rd party that might * try to man-in-the-middle our traffic. */ GNUNET_TRANSPORT_CheckAddress check_address; /** * Function that will be called to convert a binary address * to a string (numeric conversion only). */ GNUNET_TRANSPORT_AddressToString address_to_string; /** * Function that will be called to convert a string address * to binary (numeric conversion only). */ GNUNET_TRANSPORT_StringToAddress string_to_address; /** * Function that will be called tell the plugin to create a session * object */ GNUNET_TRANSPORT_CreateSession get_session; /** * Function to obtain the network type for a session */ GNUNET_TRANSPORT_GetNetworkType get_network; }; /*#ifndef PLUGIN_TRANSPORT_H*/ #endif /* end of gnunet_transport_plugin.h */ gnunet-0.10.1/src/include/gnunet_dns_service.h0000644000175000017500000001332112225777503016273 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_dns_service.h * @brief API to access the DNS service. * @author Christian Grothoff */ #ifndef GNUNET_DNS_SERVICE_H #define GNUNET_DNS_SERVICE_H #include "gnunet_util_lib.h" /** * Opaque DNS handle */ struct GNUNET_DNS_Handle; /** * Handle to identify an individual DNS request. */ struct GNUNET_DNS_RequestHandle; /** * Flags that specify when to call the client's handler. */ enum GNUNET_DNS_Flags { /** * Useless option: never call the client. */ GNUNET_DNS_FLAG_NEVER = 0, /** * Set this flag to see all requests first prior to resolution * (for monitoring). Clients that set this flag must then * call "GNUNET_DNS_request_forward" when they process a request * for the first time. Caling "GNUNET_DNS_request_answer" is * not allowed for MONITOR peers. */ GNUNET_DNS_FLAG_REQUEST_MONITOR = 1, /** * This client should be called on requests that have not * yet been resolved as this client provides a resolution * service. Note that this does not guarantee that the * client will see all requests as another client might be * called first and that client might have already done the * resolution, in which case other pre-resolution clients * won't see the request anymore. */ GNUNET_DNS_FLAG_PRE_RESOLUTION = 2, /** * This client wants to be called on the results of a DNS resolution * (either resolved by PRE-RESOLUTION clients or the global DNS). * The client then has a chance to modify the answer (or cause it to * be dropped). There is no guarantee that other POST-RESOLUTION * client's won't modify (or drop) the answer afterwards. */ GNUNET_DNS_FLAG_POST_RESOLUTION = 4, /** * Set this flag to see all requests just before they are * returned to the network. Clients that set this flag must then * call "GNUNET_DNS_request_forward" when they process a request * for the last time. Caling "GNUNET_DNS_request_answer" is * not allowed for MONITOR peers. */ GNUNET_DNS_FLAG_RESPONSE_MONITOR = 8 }; /** * Signature of a function that is called whenever the DNS service * encounters a DNS request and needs to do something with it. The * function has then the chance to generate or modify the response by * calling one of the three "GNUNET_DNS_request_*" continuations. * * When a request is intercepted, this function is called first to * give the client a chance to do the complete address resolution; * "rdata" will be NULL for this first call for a DNS request, unless * some other client has already filled in a response. * * If multiple clients exist, all of them are called before the global * DNS. The global DNS is only called if all of the clients' * functions call GNUNET_DNS_request_forward. Functions that call * GNUNET_DNS_request_forward will be called again before a final * response is returned to the application. If any of the clients' * functions call GNUNET_DNS_request_drop, the response is dropped. * * @param cls closure * @param rh request handle to user for reply * @param request_length number of bytes in request * @param request udp payload of the DNS request */ typedef void (*GNUNET_DNS_RequestHandler)(void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request); /** * If a GNUNET_DNS_RequestHandler calls this function, the client * has no desire to interfer with the request and it should * continue to be processed normally. * * @param rh request that should now be forwarded */ void GNUNET_DNS_request_forward (struct GNUNET_DNS_RequestHandle *rh); /** * If a GNUNET_DNS_RequestHandler calls this function, the request is * to be dropped and no response should be generated. * * @param rh request that should now be dropped */ void GNUNET_DNS_request_drop (struct GNUNET_DNS_RequestHandle *rh); /** * If a GNUNET_DNS_RequestHandler calls this function, the request is * supposed to be answered with the data provided to this call (with * the modifications the function might have made). The reply given * must always be a valid DNS reply and not a mutated DNS request. * * @param rh request that should now be answered * @param reply_length size of reply (uint16_t to force sane size) * @param reply reply data */ void GNUNET_DNS_request_answer (struct GNUNET_DNS_RequestHandle *rh, uint16_t reply_length, const char *reply); /** * Connect to the service-dns * * @param cfg configuration to use * @param flags when to call rh * @param rh function to call with DNS requests * @param rh_cls closure to pass to rh * @return DNS handle */ struct GNUNET_DNS_Handle * GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_DNS_Flags flags, GNUNET_DNS_RequestHandler rh, void *rh_cls); /** * Disconnect from the DNS service. * * @param dh DNS handle */ void GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *dh); #endif gnunet-0.10.1/src/include/gnunet_secretsharing_service.h0000644000175000017500000002657412274162760020363 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_secretsharing_service.h * @brief verifiable additive secret sharing and cooperative decryption * @author Florian Dold */ #ifndef GNUNET_SECRETSHARING_SERVICE_H #define GNUNET_SECRETSHARING_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "gnunet_common.h" #include "gnunet_time_lib.h" #include "gnunet_configuration_lib.h" #include /** * Number of bits for secretsharing elements. * Must be smaller than the Pallier key size used internally * by the secretsharing service. * When changing this value, other internal parameters must also * be adjusted. */ #define GNUNET_SECRETSHARING_ELGAMAL_BITS 1024 /** * The q-parameter for ElGamal encryption, a 1024-bit safe prime. */ #define GNUNET_SECRETSHARING_ELGAMAL_P_HEX \ "0x08a347d3d69e8b2dd7d1b12a08dfbccbebf4ca" \ "6f4269a0814e158a34312964d946b3ef22882317" \ "2bcf30fc08f772774cb404f9bc002a6f66b09a79" \ "d810d67c4f8cb3bedc6060e3c8ef874b1b64df71" \ "6c7d2b002da880e269438d5a776e6b5f253c8df5" \ "6a16b1c7ce58def07c03db48238aadfc52a354a2" \ "7ed285b0c1675cad3f3" /** * The q-parameter for ElGamal encryption, * a 1023-bit Sophie Germain prime, q = (p-1)/2 */ #define GNUNET_SECRETSHARING_ELGAMAL_Q_HEX \ "0x0451a3e9eb4f4596ebe8d895046fde65f5fa65" \ "37a134d040a70ac51a1894b26ca359f79144118b" \ "95e7987e047bb93ba65a027cde001537b3584d3c" \ "ec086b3e27c659df6e303071e477c3a58db26fb8" \ "b63e958016d4407134a1c6ad3bb735af929e46fa" \ "b50b58e3e72c6f783e01eda411c556fe2951aa51" \ "3f6942d860b3ae569f9" /** * The g-parameter for ElGamal encryption, * a generator of the unique size q subgroup of Z_p^* */ #define GNUNET_SECRETSHARING_ELGAMAL_G_HEX \ "0x05c00c36d2e822950087ef09d8252994adc4e4" \ "8fe3ec70269f035b46063aff0c99b633fd64df43" \ "02442e1914c829a41505a275438871f365e91c12" \ "3d5303ef9e90f4b8cb89bf86cc9b513e74a72634" \ "9cfd9f953674fab5d511e1c078fc72d72b34086f" \ "c82b4b951989eb85325cb203ff98df76bc366bba" \ "1d7024c3650f60d0da" /** * Session that will eventually establish a shared secred between * the involved peers and allow encryption and cooperative decryption. */ struct GNUNET_SECRETSHARING_Session; /** * Share of a secret shared with a group of peers. * Contains the secret share itself, the public key, the list of peers, and the * exponential commitments to the secret shares of the other peers. */ struct GNUNET_SECRETSHARING_Share; /** * Handle to cancel a cooperative decryption operation. */ struct GNUNET_SECRETSHARING_DecryptionHandle; /** * Public key of a group sharing a secret. */ struct GNUNET_SECRETSHARING_PublicKey { uint32_t bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 / sizeof (uint32_t)]; }; /** * Encrypted field element. */ struct GNUNET_SECRETSHARING_Ciphertext { uint32_t c1_bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 / sizeof (uint32_t)]; uint32_t c2_bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 / sizeof (uint32_t)]; }; /** * Plain, unencrypted message that can be encrypted with * a group public key. * Note that we are not operating in GF(2^n), thus not every * bit pattern is a valid plain text. */ struct GNUNET_SECRETSHARING_Plaintext { /** * Value of the message. */ uint32_t bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 / sizeof (uint32_t)]; }; /** * Called once the secret has been established with all peers, or the deadline is due. * * Note that the number of peers can be smaller than 'k' (this threshold parameter), which * makes the threshold crypto system useless. However, in this case one can still determine which peers * were able to participate in the secret sharing successfully. * * If the secret sharing failed, num_ready_peers is 0 and my_share and public_key is NULL. * * After this callback has been called, the secretsharing session will be invalid. * * @param cls closure * @param my_share the share of this peer * @param public_key public key of the session * @param num_ready_peers number of peers in @a ready_peers * @param ready_peers peers that successfuly participated in establishing * the shared secret */ typedef void (*GNUNET_SECRETSHARING_SecretReadyCallback) (void *cls, struct GNUNET_SECRETSHARING_Share *my_share, struct GNUNET_SECRETSHARING_PublicKey *public_key, unsigned int num_ready_peers, struct GNUNET_PeerIdentity *ready_peers); /** * Called when a decryption has succeeded. * * @param cls closure * @param data decrypted value * @param data_size number of bytes in @a data */ typedef void (*GNUNET_SECRETSHARING_DecryptCallback) (void *cls, const struct GNUNET_SECRETSHARING_Plaintext *plaintext); /** * Create a session that will eventually establish a shared secret * with the other peers. * * @param cfg configuration to use * @param num_peers number of peers in 'peers' * @param peers array of peers that we will share secrets with, can optionally contain the local peer * @param session_id unique session id * @param start When should all peers be available for sharing the secret? * Random number generation can take place before the start time. * @param deadline point in time where the session must be established; taken as hint * by underlying consensus sessions * @param threshold minimum number of peers that must cooperate to decrypt a value * @param cb called when the secret has been established * @param cls closure for cb */ struct GNUNET_SECRETSHARING_Session * GNUNET_SECRETSHARING_create_session (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, const struct GNUNET_PeerIdentity *peers, const struct GNUNET_HashCode *session_id, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, unsigned int threshold, GNUNET_SECRETSHARING_SecretReadyCallback cb, void *cls); /** * Destroy a secret sharing session. * The secret ready callback will not be called. * * @param session session to destroy */ void GNUNET_SECRETSHARING_session_destroy (struct GNUNET_SECRETSHARING_Session *session); /** * Encrypt a value. This operation is executed locally, no communication is * necessary. * * This is a helper function, encryption can be done soley with a session's public key * and the crypto system parameters. * * @param public_key public key to use for decryption * @param message message to encrypt * @param message_size number of bytes in @a message * @param result_ciphertext pointer to store the resulting ciphertext * @return #GNUNET_YES on succes, #GNUNET_SYSERR if the message is invalid (invalid range) */ int GNUNET_SECRETSHARING_encrypt (const struct GNUNET_SECRETSHARING_PublicKey *public_key, const struct GNUNET_SECRETSHARING_Plaintext *plaintext, struct GNUNET_SECRETSHARING_Ciphertext *result_ciphertext); /** * Publish the given ciphertext for decryption. Once a sufficient (>=k) number of peers has * published the same value, it will be decrypted. * * When the operation is canceled, the decrypt_cb is not called anymore, but the calling * peer may already have irrevocably contributed his share for the decryption of the value. * * @param cfg configuration to use * @param share our secret share to use for decryption * @param ciphertext ciphertext to publish in order to decrypt it (if enough peers agree) * @param decrypt_cb callback called once the decryption succeeded * @param start By when should the cooperation for decryption start? * @param deadline By when should the decryption be finished? * @param decrypt_cb_cls closure for @a decrypt_cb * @return handle to cancel the operation */ struct GNUNET_SECRETSHARING_DecryptionHandle * GNUNET_SECRETSHARING_decrypt (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SECRETSHARING_Share *share, const struct GNUNET_SECRETSHARING_Ciphertext *ciphertext, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, GNUNET_SECRETSHARING_DecryptCallback decrypt_cb, void *decrypt_cb_cls); /** * Cancel a decryption. * * The decrypt_cb is not called anymore, but the calling * peer may already have irrevocably contributed his share for the decryption of the value. * * @param decryption_handle decryption to cancel */ void GNUNET_SECRETSHARING_decrypt_cancel (struct GNUNET_SECRETSHARING_DecryptionHandle *decryption_handle); /** * Read a share from its binary representation. * * @param data Binary representation of the share. * @param len Length of @a data. * @param[out] readlen Number of bytes read, * ignored if NULL. * @return The share, or NULL on error. */ struct GNUNET_SECRETSHARING_Share * GNUNET_SECRETSHARING_share_read (const void *data, size_t len, size_t *readlen); /** * Convert a share to its binary representation. * Can be called with a NULL @a buf to get the size of the share. * * @param share Share to write. * @param buf Buffer to write to. * @param buflen Number of writable bytes in @a buf. * @param[out] writelen Pointer to store number of bytes written, * ignored if NULL. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure. */ int GNUNET_SECRETSHARING_share_write (const struct GNUNET_SECRETSHARING_Share *share, void *buf, size_t buflen, size_t *writelen); void GNUNET_SECRETSHARING_share_destroy (struct GNUNET_SECRETSHARING_Share *share); int GNUNET_SECRETSHARING_plaintext_generate (struct GNUNET_SECRETSHARING_Plaintext *plaintext, gcry_mpi_t exponent); int GNUNET_SECRETSHARING_plaintext_generate_i (struct GNUNET_SECRETSHARING_Plaintext *plaintext, int64_t exponent); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_helper_lib.h0000644000175000017500000001252512225777503016101 00000000000000/* This file is part of GNUnet. (C) 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_helper_lib.h * @brief API for dealing with (SUID) helper processes that communicate via * GNUNET_MessageHeaders on stdin/stdout * @author Philipp Toelke * @author Christian Grothoff */ #ifndef GNUNET_HELPER_LIB_H #define GNUNET_HELPER_LIB_H #include "gnunet_scheduler_lib.h" #include "gnunet_server_lib.h" /** * The handle to a helper process. */ struct GNUNET_HELPER_Handle; /** * Callback that will be called when the helper process dies. This is not called * when the helper process is stoped using GNUNET_HELPER_stop() * * @param cls the closure from GNUNET_HELPER_start() */ typedef void (*GNUNET_HELPER_ExceptionCallback) (void *cls); /** * Starts a helper and begins reading from it. The helper process is * restarted when it dies except when it is stopped using GNUNET_HELPER_stop() * or when the exp_cb callback is not NULL. * * @param with_control_pipe does the helper support the use of a control pipe for signalling? * @param binary_name name of the binary to run * @param binary_argv NULL-terminated list of arguments to give when starting the binary (this * argument must not be modified by the client for * the lifetime of the helper handle) * @param cb function to call if we get messages from the helper * @param exp_cb the exception callback to call. Set this to NULL if the helper * process has to be restarted automatically when it dies/crashes * @param cb_cls closure for the above callbacks * @return the new Handle, NULL on error */ struct GNUNET_HELPER_Handle * GNUNET_HELPER_start (int with_control_pipe, const char *binary_name, char *const binary_argv[], GNUNET_SERVER_MessageTokenizerCallback cb, GNUNET_HELPER_ExceptionCallback exp_cb, void *cb_cls); /** * Sends termination signal to the helper process. The helper process is not * reaped; call GNUNET_HELPER_wait() for reaping the dead helper process. * * @param h the helper handle * @param soft_kill if #GNUNET_YES, signals termination by closing the helper's * stdin; #GNUNET_NO to signal termination by sending SIGTERM to helper * @return #GNUNET_OK on success; #GNUNET_SYSERR on error */ int GNUNET_HELPER_kill (struct GNUNET_HELPER_Handle *h, int soft_kill); /** * Reap the helper process. This call is blocking (!). The helper process * should either be sent a termination signal before or should be dead before * calling this function * * @param h the helper handle * @return #GNUNET_OK on success; #GNUNET_SYSERR on error */ int GNUNET_HELPER_wait (struct GNUNET_HELPER_Handle *h); /** * Free's the resources occupied by the helper handle * * @param h the helper handle to free */ void GNUNET_HELPER_destroy (struct GNUNET_HELPER_Handle *h); /** * Kills the helper, closes the pipe, frees the handle and calls wait() on the * helper process * * @param h handle to helper to stop * @param soft_kill if #GNUNET_YES, signals termination by closing the helper's * stdin; #GNUNET_NO to signal termination by sending SIGTERM to helper */ void GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h, int soft_kill); /** * Continuation function. * * @param cls closure * @param result #GNUNET_OK on success, * #GNUNET_NO if helper process died * #GNUNET_SYSERR during GNUNET_HELPER_destroy */ typedef void (*GNUNET_HELPER_Continuation)(void *cls, int result); /** * Handle to cancel 'send' */ struct GNUNET_HELPER_SendHandle; /** * Send an message to the helper. * * @param h helper to send message to * @param msg message to send * @param can_drop can the message be dropped if there is already one in the queue? * @param cont continuation to run once the message is out (#GNUNET_OK on succees, #GNUNET_NO * if the helper process died, #GNUNET_SYSERR during #GNUNET_HELPER_destroy). * @param cont_cls closure for @a cont * @return NULL if the message was dropped, * otherwise handle to cancel @a cont (actual transmission may * not be abortable) */ struct GNUNET_HELPER_SendHandle * GNUNET_HELPER_send (struct GNUNET_HELPER_Handle *h, const struct GNUNET_MessageHeader *msg, int can_drop, GNUNET_HELPER_Continuation cont, void *cont_cls); /** * Cancel a #GNUNET_HELPER_send operation. If possible, transmitting * the message is also aborted, but at least 'cont' won't be called. * * @param sh operation to cancel */ void GNUNET_HELPER_send_cancel (struct GNUNET_HELPER_SendHandle *sh); #endif /* end of include guard: GNUNET_HELPER_LIB_H */ gnunet-0.10.1/src/include/gnunet_datacache_lib.h0000644000175000017500000001050312225777503016511 00000000000000/* This file is part of GNUnet (C) 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_datacache_lib.h * @brief datacache is a simple, transient hash table * of bounded size with content expiration. * In contrast to the sqstore there is * no prioritization, deletion or iteration. * All of the data is discarded when the peer shuts down! * @author Christian Grothoff */ #ifndef GNUNET_DATACACHE_LIB_H #define GNUNET_DATACACHE_LIB_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Handle to the cache. */ struct GNUNET_DATACACHE_Handle; /** * Create a data cache. * * @param cfg configuration to use * @param section section in the configuration that contains our options * @return handle to use to access the service */ struct GNUNET_DATACACHE_Handle * GNUNET_DATACACHE_create (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section); /** * Destroy a data cache (and free associated resources). * * @param h handle to the datastore */ void GNUNET_DATACACHE_destroy (struct GNUNET_DATACACHE_Handle *h); /** * An iterator over a set of items stored in the datacache. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param exp when will the content expire? * @param path_info_len number of entries in 'path_info' * @param path_info a path through the network * @return GNUNET_OK to continue iterating, GNUNET_SYSERR to abort */ typedef int (*GNUNET_DATACACHE_Iterator) (void *cls, const struct GNUNET_HashCode *key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info); /** * Store an item in the datacache. * * @param h handle to the datacache * @param key key to store data under * @param size number of bytes in data * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case * @param path_info_len number of entries in 'path_info' * @param path_info a path through the network * @return GNUNET_OK on success, GNUNET_SYSERR on error, GNUNET_NO if duplicate */ int GNUNET_DATACACHE_put (struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info); /** * Iterate over the results for a particular key * in the datacache. * * @param h handle to the datacache * @param key what to look up * @param type entries of which type are relevant? * @param iter maybe NULL (to just count) * @param iter_cls closure for iter * @return the number of results found */ unsigned int GNUNET_DATACACHE_get (struct GNUNET_DATACACHE_Handle *h, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_datacache_lib.h */ #endif gnunet-0.10.1/src/include/gnunet_block_plugin.h0000644000175000017500000000734112225777503016444 00000000000000/* This file is part of GNUnet (C) 2010,2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_block_plugin.h * @brief API for block plugins. Each block plugin must conform to * the API specified by this header. * @author Christian Grothoff * @defgroup block API to be implemented by applications storing data in the DHT * @{ */ #ifndef PLUGIN_BLOCK_H #define PLUGIN_BLOCK_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the @a reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would * be done with the "get_key" function. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for @a bf * @param xquery extrended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param reply_block response to validate * @param reply_block_size number of bytes in @a reply_block * @return characterization of result */ typedef enum GNUNET_BLOCK_EvaluationResult (*GNUNET_BLOCK_EvaluationFunction) (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size); /** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param block block to get the key for * @param block_size number of bytes in @a block * @param key set to the key (query) for the given block * @return #GNUNET_YES on success, * #GNUNET_NO if the block is malformed * #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ typedef int (*GNUNET_BLOCK_GetKeyFunction) (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode * key); /** * Each plugin is required to return a pointer to a struct of this * type as the return value from its entry point. */ struct GNUNET_BLOCK_PluginFunctions { /** * Closure for all of the callbacks. */ void *cls; /** * 0-terminated array of block types supported by this plugin. */ const enum GNUNET_BLOCK_Type *types; /** * Main function of a block plugin. Allows us to check if a * block matches a query. */ GNUNET_BLOCK_EvaluationFunction evaluate; /** * Obtain the key for a given block (if possible). */ GNUNET_BLOCK_GetKeyFunction get_key; }; /** @} */ /* end of group block */ #endif gnunet-0.10.1/src/include/gnunet_util_lib.h0000644000175000017500000000351412225777503015575 00000000000000/* This file is part of GNUnet (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_util_lib.h * @brief convenience header including all headers of subsystems in * gnunet_util library * @author Christian Grothoff */ #ifndef GNUNET_UTIL_LIB_H #define GNUNET_UTIL_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_crypto_lib.h" #include "gnunet_bandwidth_lib.h" #include "gnunet_bio_lib.h" #include "gnunet_connection_lib.h" #include "gnunet_client_lib.h" #include "gnunet_container_lib.h" #include "gnunet_getopt_lib.h" #include "gnunet_helper_lib.h" #include "gnunet_mq_lib.h" #include "gnunet_os_lib.h" #include "gnunet_peer_lib.h" #include "gnunet_plugin_lib.h" #include "gnunet_program_lib.h" #include "gnunet_protocols.h" #include "gnunet_server_lib.h" #include "gnunet_service_lib.h" #include "gnunet_signal_lib.h" #include "gnunet_strings_lib.h" #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_mesh_service.h0000644000175000017500000005143512320530515016435 00000000000000/* This file is part of GNUnet. (C) 2009 - 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_mesh_service.h * @brief mesh service; establish channels to distant peers * @author Christian Grothoff */ #ifndef GNUNET_MESH_SERVICE_H #define GNUNET_MESH_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" /** * Version number of GNUnet-mesh API. */ #define GNUNET_MESH_VERSION 0x00000003 /** * Opaque handle to the service. */ struct GNUNET_MESH_Handle; /** * Opaque handle to a channel. */ struct GNUNET_MESH_Channel; /** * Hash to be used in Mesh communication. Only 256 bits needed, * instead of the 512 from @c GNUNET_HashCode. * */ struct GNUNET_MESH_Hash { unsigned char bits[256 / 8]; }; /** * Channel options. * Second line indicates filed in the MeshChannelInfo union carrying the answer. */ enum GNUNET_MESH_ChannelOption { /** * Default options: unreliable, default buffering, not out of order. */ GNUNET_MESH_OPTION_DEFAULT = 0x0, /** * Disable buffering on intermediate nodes (for minimum latency). * Yes/No. */ GNUNET_MESH_OPTION_NOBUFFER = 0x1, /** * Enable channel reliability, lost messages will be retransmitted. * Yes/No. */ GNUNET_MESH_OPTION_RELIABLE = 0x2, /** * Enable out of order delivery of messages. * Yes/No. */ GNUNET_MESH_OPTION_OOORDER = 0x4, /** * Who is the peer at the other end of the channel. * Only for use in @c GNUNET_MESH_channel_get_info * struct GNUNET_PeerIdentity *peer */ GNUNET_MESH_OPTION_PEER = 0x8 }; /** * Functions with this signature are called whenever a message is * received. * * Each time the function must call #GNUNET_MESH_receive_done on the channel * in order to receive the next message. This doesn't need to be immediate: * can be delayed if some processing is done on the message. * * @param cls Closure (set from #GNUNET_MESH_connect). * @param channel Connection to the other end. * @param channel_ctx Place to store local state associated with the channel. * @param message The actual message. * @return #GNUNET_OK to keep the channel open, * #GNUNET_SYSERR to close it (signal serious error). */ typedef int (*GNUNET_MESH_MessageCallback) (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message); /** * Message handler. Each struct specifies how to handle on particular * type of message received. */ struct GNUNET_MESH_MessageHandler { /** * Function to call for messages of "type". */ GNUNET_MESH_MessageCallback callback; /** * Type of the message this handler covers. */ uint16_t type; /** * Expected size of messages of this type. Use 0 for variable-size. * If non-zero, messages of the given type will be discarded if they * do not have the right size. */ uint16_t expected_size; }; /** * Method called whenever another peer has added us to a channel * the other peer initiated. * Only called (once) upon reception of data with a message type which was * subscribed to in #GNUNET_MESH_connect. * * A call to #GNUNET_MESH_channel_destroy causes te channel to be ignored. In * this case the handler MUST return NULL. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel * @param port Port this channel is for. * @param options MeshOption flag field, with all active option bits set to 1. * * @return initial channel context for the channel * (can be NULL -- that's not an error) */ typedef void *(GNUNET_MESH_InboundChannelNotificationHandler) (void *cls, struct GNUNET_MESH_Channel * channel, const struct GNUNET_PeerIdentity * initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options); /** * Function called whenever a channel is destroyed. Should clean up * any associated state. * * It must NOT call #GNUNET_MESH_channel_destroy on the channel. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ typedef void (GNUNET_MESH_ChannelEndHandler) (void *cls, const struct GNUNET_MESH_Channel * channel, void *channel_ctx); /** * Connect to the mesh service. * * @param cfg Configuration to use. * @param cls Closure for the various callbacks that follow (including * handlers in the handlers array). * @param new_channel Function called when an *incoming* channel is created. * Can be NULL if no inbound channels are desired. * See @a ports. * @param cleaner Function called when a channel is destroyed by the remote peer. * It is NOT called if #GNUNET_MESH_channel_destroy is called on * the channel. * @param handlers Callbacks for messages we care about, NULL-terminated. Each * one must call #GNUNET_MESH_receive_done on the channel to * receive the next message. Messages of a type that is not * in the handlers array are ignored if received. * @param ports NULL or 0-terminated array of port numbers for incoming channels. * See @a new_channel. * * @return handle to the mesh service NULL on error * (in this case, init is never called) */ struct GNUNET_MESH_Handle * GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_MESH_InboundChannelNotificationHandler new_channel, GNUNET_MESH_ChannelEndHandler cleaner, const struct GNUNET_MESH_MessageHandler *handlers, const uint32_t *ports); /** * Disconnect from the mesh service. All channels will be destroyed. All channel * disconnect callbacks will be called on any still connected peers, notifying * about their disconnection. The registered inbound channel cleaner will be * called should any inbound channels still exist. * * @param handle connection to mesh to disconnect */ void GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle); /** * Create a new channel towards a remote peer. * * If the destination port is not open by any peer or the destination peer * does not accept the channel, #GNUNET_MESH_ChannelEndHandler will be called * for this channel. * * @param h mesh handle * @param channel_ctx client's channel context to associate with the channel * @param peer peer identity the channel should go to * @param port Port number. * @param options MeshOption flag field, with all desired option bits set to 1. * * @return handle to the channel */ struct GNUNET_MESH_Channel * GNUNET_MESH_channel_create (struct GNUNET_MESH_Handle *h, void *channel_ctx, const struct GNUNET_PeerIdentity *peer, uint32_t port, enum GNUNET_MESH_ChannelOption options); /** * Destroy an existing channel. * * The existing end callback for the channel will be called immediately. * Any pending outgoing messages will be sent but no incoming messages will be * accepted and no data callbacks will be called. * * @param channel Channel handle, becomes invalid after this call. */ void GNUNET_MESH_channel_destroy (struct GNUNET_MESH_Channel *channel); /** * Struct to retrieve info about a channel. */ union GNUNET_MESH_ChannelInfo { /** * #GNUNET_YES / #GNUNET_NO, for binary flags. */ int yes_no; /** * Peer on the other side of the channel */ const struct GNUNET_PeerIdentity peer; }; /** * Get information about a channel. * * @param channel Channel handle. * @param option Query type GNUNET_MESH_OPTION_* * @param ... dependant on option, currently not used * @return Union with an answer to the query. */ const union GNUNET_MESH_ChannelInfo * GNUNET_MESH_channel_get_info (struct GNUNET_MESH_Channel *channel, enum GNUNET_MESH_ChannelOption option, ...); /** * Handle for a transmission request. */ struct GNUNET_MESH_TransmitHandle; /** * Ask the mesh to call @a notify once it is ready to transmit the * given number of bytes to the specified channel. * Only one call can be active at any time, to issue another request, * wait for the callback or cancel the current request. * * @param channel channel to use for transmission * @param cork is corking allowed for this transmission? * @param maxdelay how long can the message wait? * @param notify_size how many bytes of buffer space does notify want? * @param notify function to call when buffer space is available; * will be called with NULL on timeout or if the overall queue * for this peer is larger than queue_size and this is currently * the message with the lowest priority * @param notify_cls closure for @a notify * @return non-NULL if the notify callback was queued, * NULL if we can not even queue the request (insufficient * memory); if NULL is returned, @a notify will NOT be called. */ struct GNUNET_MESH_TransmitHandle * GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Channel *channel, int cork, struct GNUNET_TIME_Relative maxdelay, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls); /** * Cancel the specified transmission-ready notification. * * @param th handle that was returned by "notify_transmit_ready". */ void GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th); /** * Indicate readiness to receive the next message on a channel. * * Should only be called once per handler called. * * @param channel Channel that will be allowed to call another handler. */ void GNUNET_MESH_receive_done (struct GNUNET_MESH_Channel *channel); /******************************************************************************/ /******************** MONITORING /DEBUG API *************************/ /******************************************************************************/ /* The following calls are not useful for normal MESH operation, but for */ /* debug and monitoring of the mesh state. They can be safely ignored. */ /* The API can change at any point without notice. */ /* Please contact the developer if you consider any of this calls useful for */ /* normal mesh applications. */ /******************************************************************************/ /** * Method called to retrieve information about a specific channel the mesh peer * is aware of, including all transit nodes. * * @param cls Closure. * @param root Root of the channel. * @param dest Destination of the channel. * @param port Destination port of the channel. * @param root_channel_number Local number for root, if known. * @param dest_channel_number Local number for dest, if known. * @param public_channel_numbe Number for P2P, always known. */ typedef void (*GNUNET_MESH_ChannelCB) (void *cls, const struct GNUNET_PeerIdentity *root, const struct GNUNET_PeerIdentity *dest, uint32_t port, uint32_t root_channel_number, uint32_t dest_channel_number, uint32_t public_channel_number); /** * Method called to retrieve information about all peers in MESH, called * once per peer. * * After last peer has been reported, an additional call with NULL is done. * * @param cls Closure. * @param peer Peer, or NULL on "EOF". * @param tunnel Do we have a tunnel towards this peer? * @param n_paths Number of known paths towards this peer. * @param best_path How long is the best path? * (0 = unknown, 1 = ourselves, 2 = neighbor) */ typedef void (*GNUNET_MESH_PeersCB) (void *cls, const struct GNUNET_PeerIdentity *peer, int tunnel, unsigned int n_paths, unsigned int best_path); /** * Method called to retrieve information about a specific peer * known to the service. * * @param cls Closure. * @param peer Peer ID. * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO * @param n_paths Number of paths known towards peer. * @param paths Array of PEER_IDs representing all paths to reach the peer. * Each path starts with the local peer. * Each path ends with the destination peer (given in @c peer). */ typedef void (*GNUNET_MESH_PeerCB) (void *cls, const struct GNUNET_PeerIdentity *peer, int tunnel, int neighbor, unsigned int n_paths, struct GNUNET_PeerIdentity *paths); /** * Method called to retrieve information about all tunnels in MESH, called * once per tunnel. * * After last tunnel has been reported, an additional call with NULL is done. * * @param cls Closure. * @param peer Destination peer, or NULL on "EOF". * @param channels Number of channels. * @param connections Number of connections. * @param estate Encryption state. * @param cstate Connectivity state. */ typedef void (*GNUNET_MESH_TunnelsCB) (void *cls, const struct GNUNET_PeerIdentity *peer, unsigned int channels, unsigned int connections, uint16_t estate, uint16_t cstate); /** * Method called to retrieve information about a specific tunnel the mesh peer * has established, o`r is trying to establish. * * @param cls Closure. * @param peer Peer towards whom the tunnel is directed. * @param n_channels Number of channels. * @param n_connections Number of connections. * @param channels Channels. * @param connections Connections. * @param estate Encryption state. * @param cstate Connectivity state. */ typedef void (*GNUNET_MESH_TunnelCB) (void *cls, const struct GNUNET_PeerIdentity *peer, unsigned int n_channels, unsigned int n_connections, uint32_t *channels, struct GNUNET_MESH_Hash *connections, unsigned int estate, unsigned int cstate); /** * Request information about a specific channel of the running mesh peer. * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param peer ID of the other end of the channel. * @param channel_number Channel number. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. */ void GNUNET_MESH_get_channel (struct GNUNET_MESH_Handle *h, struct GNUNET_PeerIdentity *peer, uint32_t channel_number, GNUNET_MESH_ChannelCB callback, void *callback_cls); /** * Request information about peers known to the running mesh service. * The callback will be called for every peer known to the service. * Only one info request (of any kind) can be active at once. * * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_get_peers (struct GNUNET_MESH_Handle *h, GNUNET_MESH_PeersCB callback, void *callback_cls); /** * Cancel a peer info request. The callback will not be called (anymore). * * WARNING: unstable API, likely to change in the future! * * @param h Mesh handle. * * @return Closure given to GNUNET_MESH_get_peers. */ void * GNUNET_MESH_get_peers_cancel (struct GNUNET_MESH_Handle *h); /** * Request information about a peer known to the running mesh peer. * The callback will be called for the tunnel once. * Only one info request (of any kind) can be active at once. * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param id Peer whose tunnel to examine. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_get_peer (struct GNUNET_MESH_Handle *h, const struct GNUNET_PeerIdentity *id, GNUNET_MESH_PeerCB callback, void *callback_cls); /** * Request information about tunnels of the running mesh peer. * The callback will be called for every tunnel of the service. * Only one info request (of any kind) can be active at once. * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h, GNUNET_MESH_TunnelsCB callback, void *callback_cls); /** * Cancel a monitor request. The monitor callback will not be called. * * @param h Mesh handle. * * @return Closure given to GNUNET_MESH_monitor, if any. */ void * GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h); /** * Request information about a tunnel of the running mesh peer. * The callback will be called for the tunnel once. * Only one info request (of any kind) can be active at once. * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param id Peer whose tunnel to examine. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_get_tunnel (struct GNUNET_MESH_Handle *h, const struct GNUNET_PeerIdentity *id, GNUNET_MESH_TunnelCB callback, void *callback_cls); /** * Create a message queue for a mesh channel. * The message queue can only be used to transmit messages, * not to receive them. * * @param channel the channel to create the message qeue for * @return a message queue to messages over the channel */ struct GNUNET_MQ_Handle * GNUNET_MESH_mq_create (struct GNUNET_MESH_Channel *channel); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_MESH_SERVICE_H */ #endif /* end of gnunet_mesh_service.h */ gnunet-0.10.1/src/include/gnunet_nat_lib.h0000644000175000017500000002522712262754601015402 00000000000000/* This file is part of GNUnet. (C) 2007-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_nat_lib.h * @brief Library handling UPnP and NAT-PMP port forwarding and * external IP address retrieval * @author Christian Grothoff * @author Milan Bouchet-Valat */ #ifndef GNUNET_NAT_LIB_H #define GNUNET_NAT_LIB_H #include "gnunet_util_lib.h" /** * Signature of the callback passed to #GNUNET_NAT_register() for * a function to call whenever our set of 'valid' addresses changes. * * @param cls closure * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean * the previous (now invalid) one * @param addr either the previous or the new public IP address * @param addrlen actual length of the @a addr */ typedef void (*GNUNET_NAT_AddressCallback) (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen); /** * Signature of the callback passed to #GNUNET_NAT_register(). * for a function to call whenever someone asks us to do connection * reversal. * * @param cls closure * @param addr public IP address of the other peer * @param addrlen actual lenght of the @a addr */ typedef void (*GNUNET_NAT_ReversalCallback) (void *cls, const struct sockaddr *addr, socklen_t addrlen); /** * Handle for active NAT registrations. */ struct GNUNET_NAT_Handle; /** * Attempt to enable port redirection and detect public IP address * contacting UPnP or NAT-PMP routers on the local network. Use addr * to specify to which of the local host's addresses should the * external port be mapped. The port is taken from the corresponding * sockaddr_in[6] field. The NAT module should call the given * callback for any 'plausible' external address. * * @param cfg configuration to use * @param is_tcp #GNUNET_YES for TCP, #GNUNET_NO for UDP * @param adv_port advertised port (port we are either bound to or that our OS * locally performs redirection from to our bound port). * @param num_addrs number of addresses in @a addrs * @param addrs list of local addresses packets should be redirected to * @param addrlens actual lengths of the addresses in @a addrs * @param address_callback function to call everytime the public IP address changes * @param reversal_callback function to call if someone wants connection reversal from us, * NULL if connection reversal is not supported * @param callback_cls closure for callbacks * @return NULL on error, otherwise handle that can be used to unregister */ struct GNUNET_NAT_Handle * GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, uint16_t adv_port, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls); /** * Test if the given address is (currently) a plausible IP address for * this peer. * * @param h the handle returned by register * @param addr IP address to test (IPv4 or IPv6) * @param addrlen number of bytes in @a addr * @return #GNUNET_YES if the address is plausible, * #GNUNET_NO if the address is not plausible, * #GNUNET_SYSERR if the address is malformed */ int GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h, const void *addr, socklen_t addrlen); /** * We learned about a peer (possibly behind NAT) so run the * gnunet-nat-client to send dummy ICMP responses to cause * that peer to connect to us (connection reversal). * * @param h handle (used for configuration) * @param sa the address of the peer (IPv4-only) * @return #GNUNET_SYSERR on error, #GNUNET_NO if nat client is disabled, * #GNUNET_OK otherwise */ int GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h, const struct sockaddr_in *sa); /** * Stop port redirection and public IP address detection for the given * handle. This frees the handle, after having sent the needed * commands to close open ports. * * @param h the handle to stop */ void GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h); /** * Handle to a NAT test. */ struct GNUNET_NAT_Test; /** * Function called to report success or failure for * NAT configuration test. * * @param cls closure * @param success #GNUNET_OK on success, #GNUNET_NO on failure, * #GNUNET_SYSERR if the test could not be * properly started (internal failure) * @param emsg NULL on success, otherwise may include an error message */ typedef void (*GNUNET_NAT_TestCallback) (void *cls, int success, const char *emsg); /** * Start testing if NAT traversal works using the * given configuration (IPv4-only). * * @param cfg configuration for the NAT traversal * @param is_tcp #GNUNET_YES to test TCP, #GNUNET_NO to test UDP * @param bnd_port port to bind to, 0 for connection reversal * @param adv_port externally advertised port to use * @param report function to call with the result of the test * @param report_cls closure for @a report * @return handle to cancel NAT test */ struct GNUNET_NAT_Test * GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp, uint16_t bnd_port, uint16_t adv_port, GNUNET_NAT_TestCallback report, void *report_cls); /** * Stop an active NAT test. * * @param tst test to stop. */ void GNUNET_NAT_test_stop (struct GNUNET_NAT_Test *tst); /** * Signature of a callback that is given an IP address. * * @param cls closure * @param addr the address, NULL on errors * @param emsg NULL on success, otherwise may include an error message */ typedef void (*GNUNET_NAT_IPCallback) (void *cls, const struct in_addr *addr, const char *emsg); /** * Opaque handle to cancel #GNUNET_NAT_mini_get_external_ipv4() operation. */ struct GNUNET_NAT_ExternalHandle; /** * Try to get the external IPv4 address of this peer. * * @param timeout when to fail * @param cb function to call with result * @param cb_cls closure for @a cb * @return handle for cancellation (can only be used until @a cb is called), NULL on error */ struct GNUNET_NAT_ExternalHandle * GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout, GNUNET_NAT_IPCallback cb, void *cb_cls); /** * Cancel operation. * * @param eh operation to cancel */ void GNUNET_NAT_mini_get_external_ipv4_cancel (struct GNUNET_NAT_ExternalHandle *eh); /** * Handle to a mapping created with upnpc. */ struct GNUNET_NAT_MiniHandle; /** * Signature of the callback passed to #GNUNET_NAT_register() for * a function to call whenever our set of 'valid' addresses changes. * * @param cls closure * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean * the previous (now invalid) one * @param addr either the previous or the new public IP address * @param addrlen actual length of the @a addr */ typedef void (*GNUNET_NAT_MiniAddressCallback) (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen, const char *emsg); /** * Start mapping the given port using (mini)upnpc. This function * should typically not be used directly (it is used within the * general-purpose #GNUNET_NAT_register() code). However, it can be * used if specifically UPnP-based NAT traversal is to be used or * tested. * * @param port port to map * @param is_tcp #GNUNET_YES to map TCP, #GNUNET_NO for UDP * @param ac function to call with mapping result * @param ac_cls closure for @a ac * @return NULL on error */ struct GNUNET_NAT_MiniHandle * GNUNET_NAT_mini_map_start (uint16_t port, int is_tcp, GNUNET_NAT_MiniAddressCallback ac, void *ac_cls); /** * Remove a mapping created with (mini)upnpc. Calling * this function will give 'upnpc' 1s to remove the mapping, * so while this function is non-blocking, a task will be * left with the scheduler for up to 1s past this call. * * @param mini the handle */ void GNUNET_NAT_mini_map_stop (struct GNUNET_NAT_MiniHandle *mini); /** * Handle to auto-configuration in progress. */ struct GNUNET_NAT_AutoHandle; /** * Function called with the result from the autoconfiguration. * * @param cls closure * @param diff minimal suggested changes to the original configuration * to make it work (as best as we can) * @param emsg NULL on success, otherwise may include an error message */ typedef void (*GNUNET_NAT_AutoResultCallback)(void *cls, const struct GNUNET_CONFIGURATION_Handle *diff, const char *emsg); /** * Start auto-configuration routine. The resolver service should * be available when this function is called. * * @param cfg initial configuration * @param cb function to call with autoconfiguration result * @param cb_cls closure for @a cb * @return handle to cancel operation */ struct GNUNET_NAT_AutoHandle * GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_NAT_AutoResultCallback cb, void *cb_cls); /** * Abort autoconfiguration. * * @param ah handle for operation to abort */ void GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah); #endif /* end of gnunet_nat_lib.h */ gnunet-0.10.1/src/include/gnunet_multicast_service.h0000644000175000017500000007371612310570720017515 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_multicast_service.h * @brief multicast service; establish tunnels to distant peers * @author Christian Grothoff * @author Gabor X Toth */ #ifndef GNUNET_MULTICAST_SERVICE_H #define GNUNET_MULTICAST_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" /** * Version number of GNUnet-multicast API. */ #define GNUNET_MULTICAST_VERSION 0x00000000 /** * Opaque handle for a multicast group member. */ struct GNUNET_MULTICAST_Member; /** * Handle for the origin of a multicast group. */ struct GNUNET_MULTICAST_Origin; enum GNUNET_MULTICAST_MessageFlags { /** * First fragment of a message. */ GNUNET_MULTICAST_MESSAGE_FIRST_FRAGMENT = 1 << 0, /** * Last fragment of a message. */ GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT = 1 << 1, /** * OR'ed flags if message is not fragmented. */ GNUNET_MULTICAST_MESSAGE_NOT_FRAGMENTED = GNUNET_MULTICAST_MESSAGE_FIRST_FRAGMENT | GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT, /** * Historic message, used only locally when replaying messages from local * storage. */ GNUNET_MULTICAST_MESSAGE_HISTORIC = 1 << 30 }; GNUNET_NETWORK_STRUCT_BEGIN /** * Header of a multicast message fragment. * * This format is public as the replay mechanism must replay message fragments using the * same format. This is needed as we want to integrity-check message fragments within * the multicast layer to avoid multicasting mal-formed messages. */ struct GNUNET_MULTICAST_MessageHeader { /** * Header for all multicast message fragments from the origin. */ struct GNUNET_MessageHeader header; /** * Number of hops this message fragment has taken since the origin. * * Helpful to determine shortest paths to the origin among honest peers for * unicast requests from members. Updated at each hop and thus not signed and * not secure. */ uint32_t hop_counter GNUNET_PACKED; /** * ECC signature of the message fragment. * * Signature must match the public key of the multicast group. */ struct GNUNET_CRYPTO_EddsaSignature signature; /** * Purpose for the signature and size of the signed data. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Number of the message fragment, monotonically increasing starting from 1. */ uint64_t fragment_id GNUNET_PACKED; /** * Byte offset of this @e fragment of the @e message. */ uint64_t fragment_offset GNUNET_PACKED; /** * Number of the message this fragment belongs to. * * Set in GNUNET_MULTICAST_origin_to_all(). */ uint64_t message_id GNUNET_PACKED; /** * Counter that monotonically increases whenever a member parts the group. * * Set in GNUNET_MULTICAST_origin_to_all(). * * It has significance in case of replay requests: when a member has missed * messages and gets a replay request: in this case if the @a group_generation * is still the same before and after the missed messages, it means that no * @e join or @e part operations happened during the missed messages. */ uint64_t group_generation GNUNET_PACKED; /** * Flags for this message fragment. * * @see enum GNUNET_MULTICAST_MessageFlags */ uint32_t flags GNUNET_PACKED; /* Followed by message body. */ }; /** * Header of a request from a member to the origin. */ struct GNUNET_MULTICAST_RequestHeader { /** * Header for all requests from a member to the origin. */ struct GNUNET_MessageHeader header; /** * Public key of the sending member. */ struct GNUNET_CRYPTO_EddsaPublicKey member_key; /** * ECC signature of the request fragment. * * Signature must match the public key of the multicast group. */ struct GNUNET_CRYPTO_EddsaSignature signature; /** * Purpose for the signature and size of the signed data. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Number of the request fragment. * Monotonically increasing from 1. */ uint64_t fragment_id GNUNET_PACKED; /** * Byte offset of this @e fragment of the @e request. */ uint64_t fragment_offset GNUNET_PACKED; /** * Number of the request this fragment belongs to. * * Set in GNUNET_MULTICAST_origin_to_all(). */ uint64_t request_id GNUNET_PACKED; /** * Flags for this request. */ enum GNUNET_MULTICAST_MessageFlags flags GNUNET_PACKED; /* Followed by request body. */ }; GNUNET_NETWORK_STRUCT_END /** * Maximum size of a multicast message fragment. */ #define GNUNET_MULTICAST_FRAGMENT_MAX_SIZE 63 * 1024 #define GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD \ GNUNET_MULTICAST_FRAGMENT_MAX_SIZE \ - sizeof (struct GNUNET_MULTICAST_MessageHeader) /** * Handle that identifies a join request. * * Used to match calls to #GNUNET_MULTICAST_JoinCallback to the * corresponding calls to #GNUNET_MULTICAST_join_decision(). */ struct GNUNET_MULTICAST_JoinHandle; /** * Function to call with the decision made for a join request. * * Must be called once and only once in response to an invocation of the * #GNUNET_MULTICAST_JoinCallback. * * @param jh Join request handle. * @param is_admitted #GNUNET_YES if joining is approved, * #GNUNET_NO if it is disapproved * @param relay_count Number of relays given. * @param relays Array of suggested peers that might be useful relays to use * when joining the multicast group (essentially a list of peers that * are already part of the multicast group and might thus be willing * to help with routing). If empty, only this local peer (which must * be the multicast origin) is a good candidate for building the * multicast tree. Note that it is unnecessary to specify our own * peer identity in this array. * @param join_response Message to send in response to the joining peer; * can also be used to redirect the peer to a different group at the * application layer; this response is to be transmitted to the * peer that issued the request even if admission is denied. */ struct GNUNET_MULTICAST_ReplayHandle * GNUNET_MULTICAST_join_decision (struct GNUNET_MULTICAST_JoinHandle *jh, int is_admitted, unsigned int relay_count, const struct GNUNET_PeerIdentity *relays, const struct GNUNET_MessageHeader *join_response); /** * Method called whenever another peer wants to join the multicast group. * * Implementations of this function must call GNUNET_MULTICAST_join_decision() * with the decision. * * @param cls Closure. * @param peer Identity of the member that wants to join. * @param join_req Application-dependent join message from the new member * (might, for example, contain a user, * bind user identity/pseudonym to peer identity, application-level * message to origin, etc.). * @param jh Join handle to pass to GNUNET_MULTICAST_join_decison(). */ typedef void (*GNUNET_MULTICAST_JoinCallback) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *member_key, const struct GNUNET_MessageHeader *join_req, struct GNUNET_MULTICAST_JoinHandle *jh); /** * Handle to pass back for the answer of a membership test. */ struct GNUNET_MULTICAST_MembershipTestHandle; /** * Call informing multicast about the decision taken for a membership test. * * @param mth Handle that was given for the query. * @param result #GNUNET_YES if peer was a member, #GNUNET_NO if peer was not a member, * #GNUNET_SYSERR if we cannot answer the membership test. */ void GNUNET_MULTICAST_membership_test_result (struct GNUNET_MULTICAST_MembershipTestHandle *mth, int result); /** * Method called to test if a member was in the group at a particular time. * * It is called when a replay request is received to determine if the requested * message can be replayed. * * @param cls Closure. * @param member_key Identity of the member that we want to test. * @param message_id Message ID for which to perform the test. * @param group_generation Group generation of the message. It has relevance if * the message consists of multiple fragments with different group * generations. * @param mth Handle to give to GNUNET_MULTICAST_membership_test_answer(). */ typedef void (*GNUNET_MULTICAST_MembershipTestCallback) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *member_key, uint64_t message_id, uint64_t group_generation, struct GNUNET_MULTICAST_MembershipTestHandle *mth); /** * Function called whenever a group member has transmitted a request * to the origin (other than joining or leaving). * * FIXME: need to distinguish between origin cancelling a message (some fragments * were sent, then the rest 'discarded') and the case where we got disconnected; * right now, both would mean 'msg' is NULL, but they could be quite different... * So the semantics from the receiver side of * GNUNET_MULTICAST_member_to_origin_cancel() are not clear here. Maybe we * should do something with the flags in this case? * * @param cls Closure (set from GNUNET_MULTICAST_origin_start). * @param sender Identity of the sender. * @param req Request to the origin. * @param flags Flags for the request. */ typedef void (*GNUNET_MULTICAST_RequestCallback) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *member_key, const struct GNUNET_MessageHeader *req, enum GNUNET_MULTICAST_MessageFlags flags); /** * Function called whenever a group member is receiving a message fragment from * the origin. * * If admission to the group is denied, this function is called once with the * response of the @e origin (as given to GNUNET_MULTICAST_join_decision()) and * then a second time with NULL to indicate that the connection failed for good. * * FIXME: need to distinguish between origin cancelling a message (some fragments * were sent, then the rest 'discarded') and the case where we got disconnected; * right now, both would mean 'msg' is NULL, but they could be quite different... * So the semantics from the receiver side of * GNUNET_MULTICAST_origin_to_all_cancel() are not clear here. * * @param cls Closure (set from GNUNET_MULTICAST_member_join()) * @param msg Message from the origin, NULL if the origin shut down * (or we were kicked out, and we should thus call * GNUNET_MULTICAST_member_part() next) */ typedef void (*GNUNET_MULTICAST_MessageCallback) (void *cls, const struct GNUNET_MessageHeader *msg); /** * Function called with the result of an asynchronous operation. * * @see GNUNET_MULTICAST_replay_fragment() * * @param result Result of the operation. */ typedef void (*GNUNET_MULTICAST_ResultCallback) (void *cls, int result); /** * Opaque handle to a replay request from the multicast service. */ struct GNUNET_MULTICAST_ReplayHandle; /** * Functions with this signature are called whenever the multicast service needs * a message fragment to be replayed by fragment_id. * * Implementations of this function MUST call GNUNET_MULTICAST_replay() ONCE * (with a message or an error); however, if the origin is destroyed or the * group is left, the replay handle must no longer be used. * * @param cls Closure (set from GNUNET_MULTICAST_origin_start() * or GNUNET_MULTICAST_member_join()). * @param member_key The member requesting replay. * @param fragment_id Which message fragment should be replayed. * @param flags Flags for the replay. * @param rh Handle to pass to message transmit function. */ typedef void (*GNUNET_MULTICAST_ReplayFragmentCallback) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *member_key, uint64_t fragment_id, uint64_t flags, struct GNUNET_MULTICAST_ReplayHandle *rh); /** * Functions with this signature are called whenever the multicast service needs * a message fragment to be replayed by message_id and fragment_offset. * * Implementations of this function MUST call GNUNET_MULTICAST_replay() ONCE * (with a message or an error); however, if the origin is destroyed or the * group is left, the replay handle must no longer be used. * * @param cls Closure (set from GNUNET_MULTICAST_origin_start() * or GNUNET_MULTICAST_member_join()). * @param member_key The member requesting replay. * @param message_id Which message should be replayed. * @param fragment_offset Offset of the fragment within of @a message_id to be replayed. * @param flags Flags for the replay. * @param rh Handle to pass to message transmit function. */ typedef void (*GNUNET_MULTICAST_ReplayMessageCallback) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *member_key, uint64_t message_id, uint64_t fragment_offset, uint64_t flags, struct GNUNET_MULTICAST_ReplayHandle *rh); /** * Possible error codes during replay. */ enum GNUNET_MULTICAST_ReplayErrorCode { /** * Everything is fine. */ GNUNET_MULTICAST_REC_OK = 0, /** * Message fragment not found in the message store. * * Either discarded if it is too old, or not arrived yet if this member has * missed some messages. */ GNUNET_MULTICAST_REC_NOT_FOUND = 1, /** * Fragment ID counter was larger than the highest counter this * replay function has ever encountered; thus it is likely the * origin never sent it and we're at the HEAD of the multicast * stream as far as this node is concerned. * * FIXME: needed? */ GNUNET_MULTICAST_REC_PAST_HEAD = 2, /** * Access is denied to the requested fragment, membership test did not pass. */ GNUNET_MULTICAST_REC_ACCESS_DENIED = 3, /** * Internal error (i.e. database error). Try some other peer. */ GNUNET_MULTICAST_REC_INTERNAL_ERROR = 4 }; /** * Replay a message fragment for the multicast group. * * @param rh Replay handle identifying which replay operation was requested. * @param msg Replayed message fragment, NULL if unknown/error. * @param ec Error code. */ void GNUNET_MULTICAST_replay_response (struct GNUNET_MULTICAST_ReplayHandle *rh, const struct GNUNET_MessageHeader *msg, enum GNUNET_MULTICAST_ReplayErrorCode ec); /** * Indicate the end of the replay session. * * Invalidates the replay handle. * * @param rh Replay session to end. */ void GNUNET_MULTICAST_replay_response_end (struct GNUNET_MULTICAST_ReplayHandle *rh); /** * Function called to provide data for a transmission for a replay. * * @see GNUNET_MULTICAST_replay2() */ typedef int (*GNUNET_MULTICAST_ReplayTransmitNotify) (void *cls, size_t *data_size, void *data); /** * Replay a message for the multicast group. * * @param rh Replay handle identifying which replay operation was requested. * @param notify Function to call to get the message. * @param notify_cls Closure for @a notify. */ void GNUNET_MULTICAST_replay_response2 (struct GNUNET_MULTICAST_ReplayHandle *rh, GNUNET_MULTICAST_ReplayTransmitNotify notify, void *notify_cls); /** * Start a multicast group. * * Will advertise the origin in the P2P overlay network under the respective * public key so that other peer can find this peer to join it. Peers that * issue GNUNET_MULTICAST_member_join() can then transmit a join request to * either an existing group member or to the origin. If the joining is * approved, the member is cleared for @e replay and will begin to receive * messages transmitted to the group. If joining is disapproved, the failed * candidate will be given a response. Members in the group can send messages * to the origin (one at a time). * * @param cfg Configuration to use. * @param priv_key ECC key that will be used to sign messages for this * multicast session; public key is used to identify the multicast group; * @param next_fragment_id Next fragment ID to continue counting fragments from * when restarting the origin. 1 for a new group. * @param join_cb Function called to approve / disapprove joining of a peer. * @param member_test_cb Function multicast can use to test group membership. * @param replay_frag_cb Function that can be called to replay a message fragment. * @param replay_msg_cb Function that can be called to replay a message. * @param request_cb Function called with message fragments from group members. * @param message_cb Function called with the message fragments sent to the * network by GNUNET_MULTICAST_origin_to_all(). These message fragments * should be stored for answering replay requests later. * @param cls Closure for the various callbacks that follow. * @return Handle for the origin, NULL on error. */ struct GNUNET_MULTICAST_Origin * GNUNET_MULTICAST_origin_start (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv_key, uint64_t next_fragment_id, GNUNET_MULTICAST_JoinCallback join_cb, GNUNET_MULTICAST_MembershipTestCallback member_test_cb, GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb, GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb, GNUNET_MULTICAST_RequestCallback request_cb, GNUNET_MULTICAST_MessageCallback message_cb, void *cls); /** * Function called to provide data for a transmission from the origin to all * members. * * Note that returning #GNUNET_OK or #GNUNET_SYSERR (but not #GNUNET_NO) * invalidates the respective transmission handle. * * @param cls Closure. * @param[in,out] data_size Initially set to the number of bytes available in * @a data, should be set to the number of bytes written to data. * @param[out] data Where to write the body of the message to give to the * method. The function must copy at most @a data_size bytes to @a data. * @return #GNUNET_SYSERR on error (fatal, aborts transmission) * #GNUNET_NO on success, if more data is to be transmitted later. * Should be used if @a data_size was not big enough to take all the * data. If 0 is returned in @a data_size the transmission is paused, * and can be resumed with GNUNET_MULTICAST_origin_to_all_resume(). * #GNUNET_YES if this completes the transmission (all data supplied) */ typedef int (*GNUNET_MULTICAST_OriginTransmitNotify) (void *cls, size_t *data_size, void *data); /** * Handle for a request to send a message to all multicast group members * (from the origin). */ struct GNUNET_MULTICAST_OriginMessageHandle; /** * Send a message to the multicast group. * * @param origin Handle to the multicast group. * @param message_id Application layer ID for the message. Opaque to multicast. * @param group_generation Group generation of the message. Documented in * GNUNET_MULTICAST_MessageHeader. * @param notify Function to call to get the message. * @param notify_cls Closure for @a notify. * @return NULL on error (i.e. request already pending). */ struct GNUNET_MULTICAST_OriginMessageHandle * GNUNET_MULTICAST_origin_to_all (struct GNUNET_MULTICAST_Origin *origin, uint64_t message_id, uint64_t group_generation, GNUNET_MULTICAST_OriginTransmitNotify notify, void *notify_cls); /** * Resume message transmission to multicast group. * * @param mh Request to cancel. */ void GNUNET_MULTICAST_origin_to_all_resume (struct GNUNET_MULTICAST_OriginMessageHandle *mh); /** * Cancel request for message transmission to multicast group. * * @param mh Request to cancel. */ void GNUNET_MULTICAST_origin_to_all_cancel (struct GNUNET_MULTICAST_OriginMessageHandle *mh); /** * Stop a multicast group. * * @param origin Multicast group to stop. */ void GNUNET_MULTICAST_origin_stop (struct GNUNET_MULTICAST_Origin *origin); /** * Join a multicast group. * * The entity joining is always the local peer. Further information about the * candidate can be provided in the @a join_request message. If the join fails, the * @a message_cb is invoked with a (failure) response and then with NULL. If * the join succeeds, outstanding (state) messages and ongoing multicast * messages will be given to the @a message_cb until the member decides to part * the group. The @a mem_test_cb and @a replay_cb functions may be called at * anytime by the multicast service to support relaying messages to other * members of the group. * * @param cfg Configuration to use. * @param group_key ECC public key that identifies the group to join. * @param member_key ECC key that identifies the member and used to sign * requests sent to the origin. * @param origin Peer ID of the origin to send unicast requsets to. If NULL, * unicast requests are sent back via multiple hops on the reverse path * of multicast messages. * @param relay_count Number of peers in the @a relays array. * @param relays Peer identities of members of the group, which serve as relays * and can be used to join the group at. and send the @a join_request to. * If empty, the @a join_request is sent directly to the @a origin. * @param join_request Application-dependent join request to be passed to the peer * @a relay (might, for example, contain a user, bind user * identity/pseudonym to peer identity, application-level message to * origin, etc.). * @param join_cb Function called to approve / disapprove joining of a peer. * @param mem_test_cb Function multicast can use to test group membership. * @param replay_frag_cb Function that can be called to replay message fragments * this peer already knows from this group. NULL if this * client is unable to support replay. * @param replay_msg_cb Function that can be called to replay message fragments * this peer already knows from this group. NULL if this * client is unable to support replay. * @param message_cb Function to be called for all message fragments we * receive from the group, excluding those our @a replay_cb * already has. * @param cls Closure for callbacks. * @return Handle for the member, NULL on error. */ struct GNUNET_MULTICAST_Member * GNUNET_MULTICAST_member_join (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EddsaPublicKey *group_key, const struct GNUNET_CRYPTO_EddsaPrivateKey *member_key, const struct GNUNET_PeerIdentity *origin, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, const struct GNUNET_MessageHeader *join_request, GNUNET_MULTICAST_JoinCallback join_cb, GNUNET_MULTICAST_MembershipTestCallback mem_test_cb, GNUNET_MULTICAST_ReplayFragmentCallback replay_frag_cb, GNUNET_MULTICAST_ReplayMessageCallback replay_msg_cb, GNUNET_MULTICAST_MessageCallback message_cb, void *cls); /** * Handle for a replay request. */ struct GNUNET_MULTICAST_MemberReplayHandle; /** * Request a fragment to be replayed by fragment ID. * * Useful if messages below the @e max_known_fragment_id given when joining are * needed and not known to the client. * * @param member Membership handle. * @param fragment_id ID of a message fragment that this client would like to see replayed. * @param flags Additional flags for the replay request. It is used and defined * by the replay callback. FIXME: which replay callback? FIXME: use enum? * FIXME: why not pass reply cb here? * @return Replay request handle, NULL on error. */ struct GNUNET_MULTICAST_MemberReplayHandle * GNUNET_MULTICAST_member_replay_fragment (struct GNUNET_MULTICAST_Member *member, uint64_t fragment_id, uint64_t flags); /** * Request a message fr to be replayed. * * Useful if messages below the @e max_known_fragment_id given when joining are * needed and not known to the client. * * @param member Membership handle. * @param message_id ID of the message this client would like to see replayed. * @param fragment_offset Offset of the fragment within the message to replay. * @param flags Additional flags for the replay request. It is used & defined * by the replay callback. * @param result_cb Function to be called for the replayed message. * @param result_cb_cls Closure for @a result_cb. * @return Replay request handle, NULL on error. */ struct GNUNET_MULTICAST_MemberReplayHandle * GNUNET_MULTICAST_member_replay_message (struct GNUNET_MULTICAST_Member *member, uint64_t message_id, uint64_t fragment_offset, uint64_t flags, GNUNET_MULTICAST_ResultCallback result_cb, void *result_cb_cls); /** * Cancel a replay request. * * @param rh Request to cancel. */ void GNUNET_MULTICAST_member_replay_cancel (struct GNUNET_MULTICAST_MemberReplayHandle *rh); /** * Part a multicast group. * * Disconnects from all group members and invalidates the @a member handle. * * An application-dependent part message can be transmitted beforehand using * #GNUNET_MULTICAST_member_to_origin()) * * @param member Membership handle. */ void GNUNET_MULTICAST_member_part (struct GNUNET_MULTICAST_Member *member); /** * Function called to provide data for a transmission from a member to the origin. * * Note that returning #GNUNET_OK or #GNUNET_SYSERR (but not #GNUNET_NO) * invalidates the respective transmission handle. * * @param cls Closure. * @param[in,out] data_size Initially set to the number of bytes available in * @a data, should be set to the number of bytes written to data. * @param[out] data Where to write the body of the message to give to the * method. The function must copy at most @a data_size bytes to @a data. * @return #GNUNET_SYSERR on error (fatal, aborts transmission) * #GNUNET_NO on success, if more data is to be transmitted later. * Should be used if @a data_size was not big enough to take all the * data. If 0 is returned in @a data_size the transmission is paused, * and can be resumed with GNUNET_MULTICAST_member_to_origin_resume(). * #GNUNET_YES if this completes the transmission (all data supplied) */ typedef int (*GNUNET_MULTICAST_MemberTransmitNotify) (void *cls, size_t *data_size, void *data); /** * Handle for a message to be delivered from a member to the origin. */ struct GNUNET_MULTICAST_MemberRequestHandle; /** * Send a message to the origin of the multicast group. * * @param member Membership handle. * @param request_id Application layer ID for the request. Opaque to multicast. * @param notify Callback to call to get the message. * @param notify_cls Closure for @a notify. * @return Handle to cancel request, NULL on error (i.e. request already pending). */ struct GNUNET_MULTICAST_MemberRequestHandle * GNUNET_MULTICAST_member_to_origin (struct GNUNET_MULTICAST_Member *member, uint64_t request_id, GNUNET_MULTICAST_MemberTransmitNotify notify, void *notify_cls); /** * Resume message transmission to origin. * * @param rh Request to cancel. */ void GNUNET_MULTICAST_member_to_origin_resume (struct GNUNET_MULTICAST_MemberRequestHandle *rh); /** * Cancel request for message transmission to origin. * * @param rh Request to cancel. */ void GNUNET_MULTICAST_member_to_origin_cancel (struct GNUNET_MULTICAST_MemberRequestHandle *rh); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_MULTICAST_SERVICE_H */ #endif /* end of gnunet_multicast_service.h */ gnunet-0.10.1/src/include/gnunet_bandwidth_lib.h0000644000175000017500000002235412305564550016562 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_bandwidth_lib.h * @brief functions related to bandwidth (unit) * @author Christian Grothoff */ #ifndef GNUNET_BANDWIDTH_LIB_H #define GNUNET_BANDWIDTH_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_common.h" #include "gnunet_time_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * 32-bit bandwidth used for network exchange by GNUnet, in bytes per second. */ struct GNUNET_BANDWIDTH_Value32NBO { /** * The actual value (bytes per second). */ uint32_t value__ GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /** * Callback to be called by the bandwidth tracker if the tracker * was updated and the client should update it's delay values * * @param cls a closure to pass */ typedef void (*GNUNET_BANDWIDTH_TrackerUpdateCallback) (void *cls); /** * Callback to be called by the bandwidth tracker if the tracker * was updated and the client should update it's delay values * * @param cls a closure to pass */ typedef void (*GNUNET_BANDWIDTH_ExcessNotificationCallback) (void *cls); /** * Struct to track available bandwidth. Combines a time stamp with a * number of bytes transmitted, a quota and a maximum amount that * carries over. Not opaque so that it can be inlined into data * structures (reducing malloc-ing); however, values should not be * accessed directly by clients (hence the '__'). */ struct GNUNET_BANDWIDTH_Tracker { /** * Closure for @e update_cb. */ void *update_cb_cls; /** * Function we call if the tracker's bandwidth is increased and a * previously returned timeout might now expire earlier. */ GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb; /** * Closure for @e excess_cb. */ void *excess_cb_cls; /** * Function we call if the tracker is about to throw * away bandwidth due to excess (max carry exceeded). */ GNUNET_BANDWIDTH_ExcessNotificationCallback excess_cb; /** * Number of bytes consumed since we last updated the tracker. */ int64_t consumption_since_last_update__; /** * Task scheduled to call the @e excess_cb once we have * reached the maximum bandwidth the tracker can hold. */ GNUNET_SCHEDULER_TaskIdentifier excess_task; /** * Time when we last updated the tracker. */ struct GNUNET_TIME_Absolute last_update__; /** * Bandwidth limit to enforce in bytes per s. */ uint32_t available_bytes_per_s__; /** * Maximum number of seconds over which bandwidth may "accumulate". * Note that additionally, we also always allow at least * #GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. */ uint32_t max_carry_s__; }; /** * Create a new bandwidth value. * * @param bytes_per_second value to create * @return the new bandwidth value */ struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init (uint32_t bytes_per_second); /** * Maximum possible bandwidth value. */ #define GNUNET_BANDWIDTH_VALUE_MAX GNUNET_BANDWIDTH_value_init(UINT32_MAX) /** * At the given bandwidth, calculate how much traffic will be * available until the given deadline. * * @param bps bandwidth * @param deadline when is the deadline * @return number of bytes available at bps until deadline */ uint64_t GNUNET_BANDWIDTH_value_get_available_until (struct GNUNET_BANDWIDTH_Value32NBO bps, struct GNUNET_TIME_Relative deadline); /** * At the given bandwidth, calculate how long it would take for * 'size' bytes to be transmitted. * * @param bps bandwidth * @param size number of bytes we want to have available * @return how long it would take */ struct GNUNET_TIME_Relative GNUNET_BANDWIDTH_value_get_delay_for (struct GNUNET_BANDWIDTH_Value32NBO bps, uint64_t size); /** * Compute the MIN of two bandwidth values. * * @param b1 first value * @param b2 second value * @return the min of b1 and b2 */ struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_min (struct GNUNET_BANDWIDTH_Value32NBO b1, struct GNUNET_BANDWIDTH_Value32NBO b2); /** * Initialize bandwidth tracker. Note that in addition to the * 'max_carry_s' limit, we also always allow at least * GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the * bytes-per-second limit is so small that within 'max_carry_s' not * even GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is * ignored and replaced by GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in * bytes). * * @param av tracker to initialize * @param update_cb callback to notify a client about the tracker being updated * @param update_cb_cls cls for the callback * @param bytes_per_second_limit initial limit to assume * @param max_carry_s maximum number of seconds unused bandwidth * may accumulate before it expires */ void GNUNET_BANDWIDTH_tracker_init (struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s); /** * Initialize bandwidth tracker. Note that in addition to the * 'max_carry_s' limit, we also always allow at least * GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the * bytes-per-second limit is so small that within 'max_carry_s' not * even GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is * ignored and replaced by GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in * bytes). * * @param av tracker to initialize * @param update_cb callback to notify a client about the tracker being updated * @param update_cb_cls cls for the @a update_cb callback * @param bytes_per_second_limit initial limit to assume * @param max_carry_s maximum number of seconds unused bandwidth * may accumulate before it expires * @param excess_cb callback to notify if we have excess bandwidth * @param excess_cb_cls closure for @a excess_cb */ void GNUNET_BANDWIDTH_tracker_init2 (struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s, GNUNET_BANDWIDTH_ExcessNotificationCallback excess_cb, void *excess_cb_cls); /** * Stop notifying about tracker updates and excess notifications * * @param av the respective trackers */ void GNUNET_BANDWIDTH_tracker_notification_stop (struct GNUNET_BANDWIDTH_Tracker *av); /** * Notify the tracker that a certain number of bytes of bandwidth have * been consumed. Note that it is legal to consume bytes even if not * enough bandwidth is available (in that case, * #GNUNET_BANDWIDTH_tracker_get_delay() may return non-zero delay values * even for a size of zero for a while). * * @param av tracker to update * @param size number of bytes consumed * @return #GNUNET_YES if this consumption is above the limit */ int GNUNET_BANDWIDTH_tracker_consume (struct GNUNET_BANDWIDTH_Tracker *av, ssize_t size); /** * Compute how long we should wait until consuming 'size' * bytes of bandwidth in order to stay within the given * quota. * * @param av tracker to query * @param size number of bytes we would like to consume * @return time to wait for consumption to be OK */ struct GNUNET_TIME_Relative GNUNET_BANDWIDTH_tracker_get_delay (struct GNUNET_BANDWIDTH_Tracker *av, size_t size); /** * Compute how many bytes are available for consumption right now. * quota. * * @param av tracker to query * @return number of bytes available for consumption right now */ int64_t GNUNET_BANDWIDTH_tracker_get_available (struct GNUNET_BANDWIDTH_Tracker *av); /** * Update quota of bandwidth tracker. * * @param av tracker to initialize * @param bytes_per_second_limit new limit to assume */ void GNUNET_BANDWIDTH_tracker_update_quota (struct GNUNET_BANDWIDTH_Tracker *av, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_BANDWIDTH_LIB_H */ #endif /* end of gnunet_bandwidth_lib.h */ gnunet-0.10.1/src/include/gnunet_ats_service.h0000644000175000017500000006665212316473376016317 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_ats_service.h * @brief automatic transport selection and outbound bandwidth determination * @author Christian Grothoff * @author Matthias Wachs */ #ifndef GNUNET_ATS_SERVICE_H #define GNUNET_ATS_SERVICE_H #include "gnunet_constants.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" /** * Number of network types supported by ATS */ #define GNUNET_ATS_NetworkTypeCount 6 /** * ATS network types as array initializer */ #define GNUNET_ATS_NetworkType {GNUNET_ATS_NET_UNSPECIFIED, GNUNET_ATS_NET_LOOPBACK, GNUNET_ATS_NET_LAN, GNUNET_ATS_NET_WAN, GNUNET_ATS_NET_WLAN, GNUNET_ATS_NET_BT} /** * ATS network types as string array initializer */ #define GNUNET_ATS_NetworkTypeString {"UNSPECIFIED", "LOOPBACK", "LAN", "WAN", "WLAN", "BLUETOOTH"} enum GNUNET_ATS_Network_Type { GNUNET_ATS_NET_UNSPECIFIED = 0, GNUNET_ATS_NET_LOOPBACK = 1, GNUNET_ATS_NET_LAN = 2, GNUNET_ATS_NET_WAN = 3, GNUNET_ATS_NET_WLAN = 4, GNUNET_ATS_NET_BT = 5 }; /** * Default bandwidth assigned to a network : 64 KB/s */ #define GNUNET_ATS_DefaultBandwidth 65536 /** * Undefined value for a GNUNET_ATS_Property */ #define GNUNET_ATS_VALUE_UNDEFINED UINT32_MAX /** * String representation for GNUNET_ATS_VALUE_UNDEFINED */ #define GNUNET_ATS_VALUE_UNDEFINED_STR "undefined" /** * Maximum bandwidth assigned to a network : 4095 MB/s */ #define GNUNET_ATS_MaxBandwidth UINT32_MAX /** * Textual equivalent for GNUNET_ATS_MaxBandwidth */ #define GNUNET_ATS_MaxBandwidthString "unlimited" /** * Number of property types supported by ATS */ #define GNUNET_ATS_PropertyCount 11 /** * ATS properties types as string array initializer */ #define GNUNET_ATS_PropertyStrings {"TERMINATOR", "UTILIZATION_UP", "UTILIZATION_DOWN", "UTILIZATION_PAYLOAD_UP", "UTILIZATION_PAYLOAD_DOWN", "NETWORK_TYPE", "DELAY", "DISTANCE", "COST_WAN", "COST_LAN", "COST_WLAN"} /** * Enum defining all known property types for ATS Enum values are used * in the GNUNET_ATS_Information struct as * (key,value)-pairs. * * Cost are always stored in uint32_t, so all units used to define costs * have to be normalized to fit in uint32_t [0 .. UINT32_MAX-1] * * UINT32_MAX is reserved for uninitialized values GNUNET_ATS_VALUE_UNDEFINED */ enum GNUNET_ATS_Property { /** * End of the array. * @deprecated */ GNUNET_ATS_ARRAY_TERMINATOR = 0, /** * Actual traffic on this connection from this peer to the other peer. * Includes transport overhead * * Unit: [bytes/second] */ GNUNET_ATS_UTILIZATION_OUT, /** * Actual traffic on this connection from the other peer to this peer. * Includes transport overhead * * Unit: [bytes/second] */ GNUNET_ATS_UTILIZATION_IN, /** * Actual traffic on this connection from this peer to the other peer. * Only payload from layers > transport * * Unit: [bytes/second] */ GNUNET_ATS_UTILIZATION_PAYLOAD_OUT, /** * Actual traffic on this connection from the other peer to this peer. * Only payload from layers > transport * * Unit: [bytes/second] */ GNUNET_ATS_UTILIZATION_PAYLOAD_IN, /** * Is this address located in WAN, LAN or a loopback address * Value is element of GNUNET_ATS_Network_Type */ GNUNET_ATS_NETWORK_TYPE, /** * Delay * Time between when the time packet is sent and the packet arrives * * Unit: [microseconds] * * Examples: * * LAN : 1 * WLAN : 2 * Dialup: 500 */ GNUNET_ATS_QUALITY_NET_DELAY, /** * Distance on network layer (required for distance-vector routing). * * Unit: [DV-hops] */ GNUNET_ATS_QUALITY_NET_DISTANCE, /** * Network overhead on WAN (Wide-Area Network) * * How many bytes are sent on the WAN when 1 kilobyte (1024 bytes) * of application data is transmitted? * A factor used with connect cost, bandwidth cost and energy cost * to describe the overhead produced by the transport protocol * * Unit: [bytes/kb] * * Interpretation: less is better * * Examples: * * TCP/IPv4 over Ethernet: 1024 + 38 + 20 + 20 = 1102 [bytes/kb] * TCP/IPv6 over Ethernet: 1024 + 38 + 20 + 40 = 1122 [bytes/kb] * UDP/IPv4 over Ethernet: 1024 + 38 + 20 + 8 = 1090 [bytes/kb] * UDP/IPv6 over Ethernet: 1024 + 38 + 40 + 8 = 1110 [bytes/kb] */ GNUNET_ATS_COST_WAN, /** * Network overhead on LAN (Local-Area Network) * * How many bytes are sent on the LAN when 1 kilobyte (1024 bytes) * of application data is transmitted? * A factor used with connect cost, bandwidth cost and energy cost * to describe the overhead produced by the transport protocol * * Unit: [bytes/kb] * * Interpretation: less is better * * Examples: * * TCP/IPv4 over Ethernet: 1024 + 38 + 20 + 20 = 1102 [bytes/kb] * TCP/IPv6 over Ethernet: 1024 + 38 + 20 + 40 = 1122 [bytes/kb] * UDP/IPv4 over Ethernet: 1024 + 38 + 20 + 8 = 1090 [bytes/kb] * UDP/IPv6 over Ethernet: 1024 + 38 + 40 + 8 = 1110 [bytes/kb] */ GNUNET_ATS_COST_LAN, /** * Network overhead on WLAN (Wireless Local Area Network) * * How many bytes are sent on the LAN when 1 kilobyte (1024 bytes) * of application data is transmitted? * A factor used with connect cost, bandwidth cost and energy cost * to describe the overhead produced by the transport protocol * * Unit: [bytes/kb] * * Interpretation: less is better * * Examples: * * TCP/IPv4 over Ethernet: 1024 + 38 + 20 + 20 = 1102 [bytes/kb] * TCP/IPv6 over Ethernet: 1024 + 38 + 20 + 40 = 1122 [bytes/kb] * UDP/IPv4 over Ethernet: 1024 + 38 + 20 + 8 = 1090 [bytes/kb] * UDP/IPv6 over Ethernet: 1024 + 38 + 40 + 8 = 1110 [bytes/kb] */ GNUNET_ATS_COST_WLAN /* Cost related values */ /* =================== */ /** * Volume based cost in financial units to transmit data * * Note: This value is not bound to a specific currency or unit and only * used locally. * "cent" just refers the smallest amount of money in the respective * currency. * * Unit: [cent/MB] * * Interpretation: less is better * * Examples: * LAN: 0 [cent/MB] * 2G : 10 [cent/MB] */ // GNUNET_ATS_COST_FINANCIAL_PER_VOLUME = 1, /** * Time based cost in financial units to transmit data * * Note: This value is not bound to a specific currency or unit and only * used locally. * "cent" just refers the smallest amount of money in the respective * currency. * * Unit: [cent/h] * * Interpretation: less is better * * Examples: * LAN : 0 [cent/h] * Dialup: 10 [cent/h] */ // GNUNET_ATS_COST_FINANCIAL_PER_TIME = 2, /** * Computational costs * * Effort of preparing data to be sent with this transport * Includes encoding, encryption and conversion of data * Partial values can be summed up: c_sum = c_enc + c_enc + c_conv * Resulting values depend on local system properties, e.g. CPU * * Unit: [ms/GB] * * Interpretation: less is better * * Examples: * * HTTPS with AES CBC-256: 7,382 * HTTPS with AES CBC-128: 5,279 * HTTPS with RC4-1024: 2,652 */ // GNUNET_ATS_COST_COMPUTATIONAL = 3, /** * Energy consumption * * Energy consumption using this transport when sending with a certain * power at a certain bitrate. This is only an approximation based on: * Energy consumption E = P / D * * with: * Power P in Watt (J/s) * Datarate D in MBit/s * * Conversion between power P and dBm used by WLAN in radiotap's dBm TX power: * * Lp(dbm) = 10 log10 (P/ 1mW) * * => P = 1 mW * 10^(Lp(dbm)/10) * * Unit: [mJ/MB] * * Interpretation: less is better * * Examples: * * LAN: 0 * WLAN: 89 (600 mW @ 802.11g /w 54 MBit/s) * Bluetooth: 267 (100 mW @ BT2.0 EDR /w 3 MBit/s) */ // GNUNET_ATS_COST_ENERGY_CONSUMPTION = 4, /** * Connect cost * How many bytes are transmitted to initiate a new connection using * this transport? * * Unit: [bytes] * * Interpretation: less is better * * Examples: * * UDP (No connection) : * 0 bytes * TCP (TCP 3-Way handshake): * 220 bytes Ethernet, 172 bytes TCP/IP, 122 bytes TCP * HTTP (TCP + Header) : * 477 bytes Ethernet, 429 bytes TCP/IP, 374 bytes TCP, 278 bytes HTTP * HTTPS HTTP+TLS Handshake: * 2129 bytes Ethernet, 1975 bytes TCP/IP, 1755 bytes TCP, 1403 bytes HTTPS * * */ // GNUNET_ATS_COST_CONNECT = 5, /** * Bandwidth cost * * How many bandwidth is available to consume? * Used to calculate which impact sending data with this transport has * * Unit: [kB/s] * * Interpretation: more is better * * Examples: * LAN: 12,800 (100 MBit/s) * WLAN: 6,912 (54 MBit/s) * Dial-up: 8 (64 Kbit/s) * */ // GNUNET_ATS_COST_BANDWITH_AVAILABLE = 6, /** * Network overhead * * How many bytes are sent over the wire when 1 kilobyte (1024 bytes) * of application data is transmitted? * A factor used with connect cost, bandwidth cost and energy cost * to describe the overhead produced by the transport protocol * * Unit: [bytes/kb] * * Interpretation: less is better * * Examples: * * TCP/IPv4 over Ethernet: 1024 + 38 + 20 + 20 = 1102 [bytes/kb] * TCP/IPv6 over Ethernet: 1024 + 38 + 20 + 40 = 1122 [bytes/kb] * UDP/IPv4 over Ethernet: 1024 + 38 + 20 + 8 = 1090 [bytes/kb] * UDP/IPv6 over Ethernet: 1024 + 38 + 40 + 8 = 1110 [bytes/kb] */ // GNUNET_ATS_COST_NETWORK_OVERHEAD = 7, /* Quality related values */ /* ====================== */ /* Physical layer quality properties */ /** * Signal strength on physical layer * * Unit: [dBm] */ // GNUNET_ATS_QUALITY_PHY_SIGNAL_STRENGTH = 1025, /** * Collision rate on physical layer * * Unit: [B/s] */ // GNUNET_ATS_QUALITY_PHY_COLLISION_RATE = 1026, /** * Error rate on physical layer * * Unit: [B/s] */ // GNUNET_ATS_QUALITY_PHY_ERROR_RATE = 1027, /** * Jitter * Time variations of the delay * 1st derivative of a delay function * * Unit: [ms] */ // GNUNET_ATS_QUALITY_NET_JITTER = 1029, /** * Error rate on network layer * * Unit: [B/s] * * Examples: * * LAN : 0 * WLAN : 400 * Bluetooth : 100 * Note: This numbers are just assumptions as an example, not * measured or somehow determined */ // GNUNET_ATS_QUALITY_NET_ERRORRATE = 1030, /** * Drop rate on network layer * Bytes actively dismissed by a network component during transmission * Reasons for dropped data can be full queues, congestion, quota violations... * * Unit: [B/s] * * Examples: * * LAN : 0 * WLAN : 400 * Bluetooth : 100 * Note: This numbers are just assumptions as an example, not * measured or somehow determined */ // GNUNET_ATS_QUALITY_NET_DROPRATE = 1031, /** * Loss rate on network layer * Bytes lost during transmission * Reasons can be collisions, ... * * Unit: [B/s] * * Examples: * * LAN : 0 * WLAN : 40 * Bluetooth : 10 * Note: This numbers are just assumptions as an example, not measured * or somehow determined */ // GNUNET_ATS_QUALITY_NET_LOSSRATE = 1032, /** * Throughput on network layer * * Unit: [kB/s] * * Examples: * * LAN : 3400 * WLAN : 1200 * Dialup: 4 * */ // GNUNET_ATS_QUALITY_NET_THROUGHPUT = 1033, /* Availability related values */ /* =========================== */ /** * Is a peer reachable? */ // GNUNET_ATS_AVAILABILITY_REACHABLE = 2048, /** * Is there a connection established to a peer using this transport */ // GNUNET_ATS_AVAILABILITY_CONNECTED = 2049 }; /** * Number of ATS quality properties */ #define GNUNET_ATS_QualityPropertiesCount 2 /** * ATS quality properties as array initializer */ #define GNUNET_ATS_QualityProperties {GNUNET_ATS_QUALITY_NET_DELAY, GNUNET_ATS_QUALITY_NET_DISTANCE} /** * ATS quality properties as string array initializer */ #define GNUNET_ATS_QualityPropertiesString {"Delay", "Distance"} GNUNET_NETWORK_STRUCT_BEGIN /** * struct used to communicate the transport's properties like cost and * quality of service as well as high-level constraints on resource * consumption. * * +---+ * +-----------+ Constraints | | Plugin properties +---------+ * | Highlevel |------------> |ATS| <------------------|Transport| * | Component | ATS struct | | ATS struct | Plugin | * +-----------+ | | +---------+ * +---+ * * This structure will be used by transport plugins to communicate * costs to ATS or by higher level components to tell ATS their * constraints. Always a pair of (GNUNET_ATS_Property, * uint32_t value). Value is always uint32_t, so all units used to * define costs have to be normalized to fit uint32_t. */ struct GNUNET_ATS_Information { /** * ATS property type, in network byte order. */ uint32_t type GNUNET_PACKED; /** * ATS property value, in network byte order. */ uint32_t value GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /* ******************************** Scheduling API ***************************** */ /** * Handle to the ATS subsystem for bandwidth/transport scheduling information. */ struct GNUNET_ATS_SchedulingHandle; /** * Handle for address suggestion requests */ struct GNUNET_ATS_SuggestHandle; /** * Opaque session handle, defined by plugins. Contents not known to ATS. */ struct Session; /** * Signature of a function called by ATS with the current bandwidth * and address preferences as determined by ATS. * * If an address is available immediately the address will be included. If no * address can be suggested, address, session, bandwidth and ATS information will * be NULL/0. ATS will suggest an address as soon as it can provide such an * address * * @param cls closure * @param address suggested address (including peer identity of the peer) * @param session session to use * @param bandwidth_out assigned outbound bandwidth for the connection * @param bandwidth_in assigned inbound bandwidth for the connection * @param ats performance data for the address (as far as known) * @param ats_count number of performance records in @a ats */ typedef void (*GNUNET_ATS_AddressSuggestionCallback) (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * Initialize the ATS subsystem. * * @param cfg configuration to use * @param suggest_cb notification to call whenever the suggestation changed * @param suggest_cb_cls closure for 'suggest_cb' * @return ats context */ struct GNUNET_ATS_SchedulingHandle * GNUNET_ATS_scheduling_init (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ATS_AddressSuggestionCallback suggest_cb, void *suggest_cb_cls); /** * Client is done with ATS scheduling, release resources. * * @param sh handle to release */ void GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh); /** * We would like to reset the address suggestion block time for this * peer * * @param sh handle * @param peer identity of the peer we want to reset */ void GNUNET_ATS_reset_backoff (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_PeerIdentity *peer); /** * We would like to establish a new connection with a peer. ATS * should suggest a good address to begin with. * * @param sh handle * @param peer identity of the peer we need an address for * @param cont the continuation to indicate success to call with the address * @param cont_cls the cls for the continuation * @return suggestion handle */ struct GNUNET_ATS_SuggestHandle * GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_PeerIdentity *peer, GNUNET_ATS_AddressSuggestionCallback cont, void *cont_cls); /** * We want to cancel ATS suggesting addresses for a peer. * * @param sh handle * @param peer identity of the peer */ void GNUNET_ATS_suggest_address_cancel (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_PeerIdentity *peer); /** * Convert a ATS property to a string * * @param type the atsi type * @return a string or NULL if invalid */ const char * GNUNET_ATS_print_property_type (uint32_t type); /** * Convert a GNUNET_ATS_NetworkType to a string * * @param net the network type * @return a string or NULL if invalid */ const char * GNUNET_ATS_print_network_type (uint32_t net); /** * Returns where the address is located: LAN or WAN or ... * @param sh the GNUNET_ATS_SchedulingHandle handle * @param addr address * @param addrlen address length * @return location as GNUNET_ATS_Information */ struct GNUNET_ATS_Information GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle *sh, const struct sockaddr * addr, socklen_t addrlen); /** * Test if a address and a session is known to ATS * * @param sh the scheduling handle * @param address the address * @param session the session * @return #GNUNET_YES or #GNUNET_NO */ int GNUNET_ATS_session_known (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session); /** * We have a new address ATS should know. Addresses have to be added with this * function before they can be: updated, set in use and destroyed * * @param sh handle * @param address the address * @param session session handle (if available) * @param ats performance data for the address * @param ats_count number of performance records in @a ats */ int GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * We have updated performance statistics for a given address. Note * that this function can be called for addresses that are currently * in use as well as addresses that are valid but not actively in use. * Furthermore, the peer may not even be connected to us right now (in * which case the call may be ignored or the information may be stored * for later use). Update bandwidth assignments. * * @param sh handle * @param address updated address * @param session session handle (if available) * @param ats performance data for the address * @param ats_count number of performance records in @a ats * @return #GNUNET_OK or #GNUNET_SYSERR */ int GNUNET_ATS_address_update (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * An address is now in use or not used any more. * * @param sh handle * @param address the address * @param session session handle * @param in_use #GNUNET_YES if this address is now used, #GNUNET_NO * if address is not used any more */ void GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session, int in_use); /** * An address got destroyed, stop including it as a valid address. * * If a session is given, only the session will be removed, if no session is * given the full address will be deleted. * * @param sh handle * @param address the address * @param session session handle that is no longer valid (if available) */ void GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session); /* ******************************** Performance API ***************************** */ /** * ATS Handle to obtain and/or modify performance information. */ struct GNUNET_ATS_PerformanceHandle; /** * Signature of a function that is called with QoS information about an address. * * @param cls closure * @param address the address * @param address_active is this address actively used to maintain a connection * to a peer * @param bandwidth_out assigned outbound bandwidth for the connection * @param bandwidth_in assigned inbound bandwidth for the connection * @param ats performance data for the address (as far as known) * @param ats_count number of performance records in 'ats' */ typedef void (*GNUNET_ATS_AddressInformationCallback) (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * Handle for an address listing operation */ struct GNUNET_ATS_AddressListHandle; /** * Get handle to access performance API of the ATS subsystem. * * @param cfg configuration to use * @param addr_info_cb callback called when performance characteristics for * an address change * @param addr_info_cb_cls closure for infocb * @return ats performance context */ struct GNUNET_ATS_PerformanceHandle * GNUNET_ATS_performance_init (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ATS_AddressInformationCallback addr_info_cb, void *addr_info_cb_cls); /** * Get information about addresses known to the ATS subsystem. * * @param handle the performance handle to use * @param peer peer idm can be NULL for all peers * @param all GNUNET_YES to get information about all addresses or GNUNET_NO to * get only address currently used * @param infocb callback to call with the addresses, * will callback with address == NULL when done * @param infocb_cls closure for infocb * @return ats performance context */ struct GNUNET_ATS_AddressListHandle * GNUNET_ATS_performance_list_addresses ( struct GNUNET_ATS_PerformanceHandle *handle, const struct GNUNET_PeerIdentity *peer, int all, GNUNET_ATS_AddressInformationCallback infocb, void *infocb_cls); /** * Cancel a pending address listing operation * * @param handle the GNUNET_ATS_AddressListHandle handle to cancel */ void GNUNET_ATS_performance_list_addresses_cancel ( struct GNUNET_ATS_AddressListHandle *handle); /** * Client is done using the ATS performance subsystem, release resources. * * @param ph handle */ void GNUNET_ATS_performance_done (struct GNUNET_ATS_PerformanceHandle *ph); /** * Function called with reservation result. * * @param cls closure * @param peer identifies the peer * @param amount set to the amount that was actually reserved or unreserved; * either the full requested amount or zero (no partial reservations) * @param res_delay if the reservation could not be satisfied (amount was 0), how * long should the client wait until re-trying? */ typedef void (*GNUNET_ATS_ReservationCallback) (void *cls, const struct GNUNET_PeerIdentity * peer, int32_t amount, struct GNUNET_TIME_Relative res_delay); /** * Context that can be used to cancel a peer information request. */ struct GNUNET_ATS_ReservationContext; /** * Reserve inbound bandwidth from the given peer. ATS will look at * the current amount of traffic we receive from the peer and ensure * that the peer could add 'amount' of data to its stream. * * @param ph performance handle * @param peer identifies the peer * @param amount reserve N bytes for receiving, negative * amounts can be used to undo a (recent) reservation; * @param rcb function to call with the resulting reservation information * @param rcb_cls closure for info * @return NULL on error * @deprecated will be replaced soon */ struct GNUNET_ATS_ReservationContext * GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, int32_t amount, GNUNET_ATS_ReservationCallback rcb, void *rcb_cls); /** * Cancel request for reserving bandwidth. * * @param rc context returned by the original GNUNET_ATS_reserve_bandwidth call */ void GNUNET_ATS_reserve_bandwidth_cancel (struct GNUNET_ATS_ReservationContext *rc); /** * Number of preference types supported by ATS */ #define GNUNET_ATS_PreferenceCount 3 /** * ATS preference types as array initializer */ #define GNUNET_ATS_PreferenceType {GNUNET_ATS_PREFERENCE_END, GNUNET_ATS_PREFERENCE_BANDWIDTH, GNUNET_ATS_PREFERENCE_LATENCY} /** * ATS preference types as string array initializer */ #define GNUNET_ATS_PreferenceTypeString {"END", "BANDWIDTH", "LATENCY"} /** * Enum defining all known preference categories. */ enum GNUNET_ATS_PreferenceKind { /** * End of preference list. */ GNUNET_ATS_PREFERENCE_END = 0, /** * Change the peer's bandwidth value (value per byte of bandwidth in * the goal function) to the given amount. The argument is followed * by a double value giving the desired value (can be negative). * Preference changes are forgotten if peers disconnect. */ GNUNET_ATS_PREFERENCE_BANDWIDTH, /** * Change the peer's latency value to the given amount. The * argument is followed by a double value giving the desired value * (can be negative). The absolute score in the goal function is * the inverse of the latency in microseconds (minimum: 1 * microsecond) multiplied by the latency preferences. */ GNUNET_ATS_PREFERENCE_LATENCY }; /** * Convert a GNUNET_ATS_PreferenceType to a string * * @param type the preference type * @return a string or NULL if invalid */ const char * GNUNET_ATS_print_preference_type (uint32_t type); /** * Change preferences for the given peer. Preference changes are forgotten if peers * disconnect. * * @param ph performance handle * @param peer identifies the peer * @param ... 0-terminated specification of the desired changes */ void GNUNET_ATS_performance_change_preference ( struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, ...); /** * Application feedback on how good preference requirements are fulfilled * for the preferences included in the given time scope [now - scope .. now] * * An application notifies ATS if (and only if) it has feedback information * for specific properties. This values are valid until the feedback scores are * updated by the application. * * If the application has no feedback for this preference kind the application * will not explicitly call for this property and will not include it in this * function call. * * @param ph performance handle * @param scope the time interval this valid for: [now - scope .. now] * @param peer identifies the peer * @param ... 0-terminated specification of the desired changes */ void GNUNET_ATS_performance_give_feedback (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, ...); #endif /* end of file gnunet-service-transport_ats.h */ gnunet-0.10.1/src/include/gnunet_psyc_service.h0000644000175000017500000007724212310570720016464 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_psyc_service.h * @brief PSYC service; high-level access to the PSYC protocol * note that clients of this API are NOT expected to * understand the PSYC message format, only the semantics! * Parsing (and serializing) the PSYC stream format is done * within the implementation of the libgnunetpsyc library, * and this API deliberately exposes as little as possible * of the actual data stream format to the application! * @author Christian Grothoff * @author Gabor X Toth * * NOTE: * - this API does not know about psyc's "root" and "places"; * there is no 'root' in GNUnet-Psyc as we're decentralized; * 'places' and 'persons' are combined within the same * abstraction, that of a "channel". Channels are identified * and accessed in this API using a public/private key. * Higher-level applications should use NAMES within GNS * to obtain public keys, and the distinction between * 'places' and 'persons' can then be made with the help * of the naming system (and/or conventions). * Channels are (as in PSYC) organized into a hierarchy; each * channel master (the one with the private key) is then * the operator of the multicast group (its Origin in * the terminology of the multicast API). * - The API supports passing large amounts of data using * 'streaming' for the argument passed to a method. State * and variables must fit into memory and cannot be streamed * (thus, no passing of 4 GB of data in a variable; * once we implement this, we might want to create a * @c \#define for the maximum size of a variable). * - PSYC defines standard variables, methods, etc. This * library deliberately abstracts over all of these; a * higher-level API should combine the naming system (GNS) * and standard methods (message, join, part, warn, * fail, error) and variables (action, color, time, * tag, etc.). However, this API does take over the * routing variables, specifically 'context' (channel), * and 'source'. We only kind-of support 'target', as * the target is either everyone in the group or the * origin, and never just a single member of the group; * for such individual messages, an application needs to * construct an 'inbox' channel where the master (only) * receives messages (but never forwards; private responses * would be transmitted by joining the senders 'inbox' * channel -- or a inbox#bob subchannel). The * goal for all of this is to keep the abstractions in this * API minimal: interaction with multicast, try \& slice, * state/variable/channel management. Higher-level * operations belong elsewhere (so maybe this API should * be called 'PSYC-low', whereas a higher-level API * implementing defaults for standard methods and * variables might be called 'PSYC-std' or 'PSYC-high'. */ #ifndef GNUNET_PSYC_SERVICE_H #define GNUNET_PSYC_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" #include "gnunet_env_lib.h" #include "gnunet_multicast_service.h" /** * Version number of GNUnet-PSYC API. */ #define GNUNET_PSYC_VERSION 0x00000000 /** * Policy flags for a channel. */ enum GNUNET_PSYC_ChannelFlags { /** * Admission must be confirmed by the master. */ GNUNET_PSYC_CHANNEL_ADMISSION_CONTROL = 1 << 0, /** * Past messages are only available to slaves who were admitted at the time * they were sent to the channel. */ GNUNET_PSYC_CHANNEL_RESTRICTED_HISTORY = 1 << 1 }; /** * PSYC channel policies. */ enum GNUNET_PSYC_Policy { /** * Anyone can join the channel, without announcing his presence; * all messages are always public and can be distributed freely. * Joins may be announced, but this is not required. */ GNUNET_PSYC_CHANNEL_ANONYMOUS = 0, /** * The master must approve membership to the channel, messages must only be * distributed to current channel slaves. This includes the channel * state as well as transient messages. */ GNUNET_PSYC_CHANNEL_PRIVATE = GNUNET_PSYC_CHANNEL_ADMISSION_CONTROL | GNUNET_PSYC_CHANNEL_RESTRICTED_HISTORY #if IDEAS_FOR_FUTURE /** * Anyone can freely join the channel (no approval required); * however, messages must only be distributed to current channel * slaves, so the master must still acknowledge that the slave * joined before transient messages are delivered. As approval is * guaranteed, the presistent channel state can be synchronized freely * immediately, prior to master confirmation. */ GNUNET_PSYC_CHANNEL_OPEN = GNUNET_PSYC_CHANNEL_RESTRICTED_HISTORY, /** * The master must approve joins to the channel, but past messages can be * freely distributed to slaves. */ GNUNET_PSYC_CHANNEL_CLOSED = GNUNET_PSYC_CHANNEL_ADMISSION_CONTROL, #endif }; enum GNUNET_PSYC_MessageFlags { /** * Historic message, retrieved from PSYCstore. */ GNUNET_PSYC_MESSAGE_HISTORIC = 1 << 0, /** * Request from slave to master. */ GNUNET_PSYC_MESSAGE_REQUEST = 1 << 1 }; GNUNET_NETWORK_STRUCT_BEGIN /** * Header of a PSYC message. */ struct GNUNET_PSYC_MessageHeader { /** * Generic message header with size and type information. */ struct GNUNET_MessageHeader header; /** * Flags for this message fragment. * * @see enum GNUNET_PSYC_MessageFlags */ uint32_t flags GNUNET_PACKED; /** * Number of the message this message part belongs to. * Monotonically increasing from 1. */ uint64_t message_id GNUNET_PACKED; /** * Sending slave's public key. * Not set if the message is from the master. */ struct GNUNET_CRYPTO_EddsaPublicKey slave_key; /* Followed by concatenated PSYC message parts: * messages with GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_* types */ }; /** * The method of a message. */ struct GNUNET_PSYC_MessageMethod { /** * Type: GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD */ struct GNUNET_MessageHeader header; /** * OR'ed GNUNET_PSYC_MasterTransmitFlags */ uint32_t flags GNUNET_PACKED; /* Followed by NUL-terminated method name. */ }; /** * A modifier of a message. */ struct GNUNET_PSYC_MessageModifier { /** * Type: GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER */ struct GNUNET_MessageHeader header; /** * Size of value. */ uint32_t value_size GNUNET_PACKED; /** * Size of name, including NUL terminator. */ uint16_t name_size GNUNET_PACKED; /** * enum GNUNET_ENV_Operator */ uint8_t oper; /* Followed by NUL-terminated name, then the value. */ }; GNUNET_NETWORK_STRUCT_END #define GNUNET_PSYC_MODIFIER_MAX_PAYLOAD \ GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD \ - sizeof (struct GNUNET_PSYC_MessageModifier) #define GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD \ GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD \ - sizeof (struct GNUNET_MessageHeader) #define GNUNET_PSYC_DATA_MAX_PAYLOAD \ GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD \ - sizeof (struct GNUNET_MessageHeader) /** * Handle that identifies a join request. * * Used to match calls to #GNUNET_PSYC_JoinCallback to the * corresponding calls to GNUNET_PSYC_join_decision(). */ struct GNUNET_PSYC_JoinHandle; /** * Method called from PSYC upon receiving part of a message. * * @param cls Closure. * @param msg Message part, one of the following types: * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_HEADER * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA */ typedef void (*GNUNET_PSYC_MessageCallback) (void *cls, uint64_t message_id, uint32_t flags, const struct GNUNET_MessageHeader *msg); /** * Method called from PSYC upon receiving a join request. * * @param cls Closure. * @param slave requesting to join. * @param method_name Method name in the join request. * @param variable_count Number of elements in the @a variables array. * @param variables Transient variables for the join request. * @param data Data stream given to the method (might not be zero-terminated * if data is binary). * @param data_size Number of bytes in @a data. * @param jh Join handle to use with GNUNET_PSYC_join_decision() */ typedef void (*GNUNET_PSYC_JoinCallback) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, const char *method_name, size_t variable_count, const struct GNUNET_ENV_Modifier *variables, const void *data, size_t data_size, struct GNUNET_PSYC_JoinHandle *jh); /** * Function to call with the decision made for a join request. * * Must be called once and only once in response to an invocation of the * #GNUNET_PSYC_JoinCallback. * * @param jh Join request handle. * @param is_admitted #GNUNET_YES if joining is approved, * #GNUNET_NO if it is disapproved. * @param relay_count Number of relays given. * @param relays Array of suggested peers that might be useful relays to use * when joining the multicast group (essentially a list of peers that * are already part of the multicast group and might thus be willing * to help with routing). If empty, only this local peer (which must * be the multicast origin) is a good candidate for building the * multicast tree. Note that it is unnecessary to specify our own * peer identity in this array. * @param method_name Method name for the message transmitted with the response. * @param env Environment containing transient variables for the message, * or NULL. * @param data Data of the message. * @param data_size Size of @a data. */ void GNUNET_PSYC_join_decision (struct GNUNET_PSYC_JoinHandle *jh, int is_admitted, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, const char *method_name, const struct GNUNET_ENV_Environment *env, const void *data, size_t data_size); /** * Handle for the master of a PSYC channel. */ struct GNUNET_PSYC_Master; /** * Function called after the channel master started. * * @param cls Closure. * @param max_message_id Last message ID sent to the channel. */ typedef void (*GNUNET_PSYC_MasterStartCallback) (void *cls, uint64_t max_message_id); /** * Start a PSYC master channel. * * Will start a multicast group identified by the given ECC key. Messages * received from group members will be given to the respective handler methods. * If a new member wants to join a group, the "join" method handler will be * invoked; the join handler must then generate a "join" message to approve the * joining of the new member. The channel can also change group membership * without explicit requests. Note that PSYC doesn't itself "understand" join * or part messages, the respective methods must call other PSYC functions to * inform PSYC about the meaning of the respective events. * * @param cfg Configuration to use (to connect to PSYC service). * @param channel_key ECC key that will be used to sign messages for this * PSYC session. The public key is used to identify the PSYC channel. * Note that end-users will usually not use the private key directly, but * rather look it up in GNS for places managed by other users, or select * a file with the private key(s) when setting up their own channels * FIXME: we'll likely want to use NOT the p521 curve here, but a cheaper * one in the future. * @param policy Channel policy specifying join and history restrictions. * Used to automate join decisions. * @param message_cb Function to invoke on message parts received from slaves. * @param join_cb Function to invoke when a peer wants to join. * @param master_started_cb Function to invoke after the channel master started. * @param cls Closure for @a method and @a join_cb. * @return Handle for the channel master, NULL on error. */ struct GNUNET_PSYC_Master * GNUNET_PSYC_master_start (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key, enum GNUNET_PSYC_Policy policy, GNUNET_PSYC_MessageCallback message_cb, GNUNET_PSYC_JoinCallback join_cb, GNUNET_PSYC_MasterStartCallback master_started_cb, void *cls); /** * Function called to provide data for a transmission via PSYC. * * Note that returning #GNUNET_YES or #GNUNET_SYSERR (but not #GNUNET_NO) * invalidates the respective transmission handle. * * @param cls Closure. * @param[in,out] data_size Initially set to the number of bytes available in * @a data, should be set to the number of bytes written to data. * @param[out] data Where to write the body of the message to give to the * method. The function must copy at most @a data_size bytes to @a data. * @return #GNUNET_SYSERR on error (fatal, aborts transmission) * #GNUNET_NO on success, if more data is to be transmitted later. * Should be used if @a data_size was not big enough to take all the * data. If 0 is returned in @a data_size the transmission is paused, * and can be resumed with GNUNET_PSYC_master_transmit_resume(). * #GNUNET_YES if this completes the transmission (all data supplied) */ typedef int (*GNUNET_PSYC_TransmitNotifyData) (void *cls, uint16_t *data_size, void *data); /** * Function called to provide a modifier for a transmission via PSYC. * * Note that returning #GNUNET_YES or #GNUNET_SYSERR (but not #GNUNET_NO) * invalidates the respective transmission handle. * * @param cls Closure. * @param[in,out] data_size Initially set to the number of bytes available in * @a data, should be set to the number of bytes written to data. * @param[out] data Where to write the modifier's name and value. * The function must copy at most @a data_size bytes to @a data. * When this callback is first called for a modifier, @a data should * contain: "name\0value". If the whole value does not fit, subsequent * calls to this function should write continuations of the value to * @a data. * @param[out] oper Where to write the operator of the modifier. * Only needed during the first call to this callback at the beginning * of the modifier. In case of subsequent calls asking for value * continuations @a oper is set to #NULL. * @param[out] value_size Where to write the full size of the value. * Only needed during the first call to this callback at the beginning * of the modifier. In case of subsequent calls asking for value * continuations @a value_size is set to #NULL. * @return #GNUNET_SYSERR on error (fatal, aborts transmission) * #GNUNET_NO on success, if more data is to be transmitted later. * Should be used if @a data_size was not big enough to take all the * data for the modifier's value (the name must be always returned * during the first call to this callback). * If 0 is returned in @a data_size the transmission is paused, * and can be resumed with GNUNET_PSYC_master_transmit_resume(). * #GNUNET_YES if this completes the modifier (the whole value is supplied). */ typedef int (*GNUNET_PSYC_TransmitNotifyModifier) (void *cls, uint16_t *data_size, void *data, uint8_t *oper, uint32_t *value_size); /** * Flags for transmitting messages to a channel by the master. */ enum GNUNET_PSYC_MasterTransmitFlags { GNUNET_PSYC_MASTER_TRANSMIT_NONE = 0, /** * Whether this message should reset the channel state, * i.e. remove all previously stored state variables. */ GNUNET_PSYC_MASTER_TRANSMIT_RESET_STATE = 1 << 0, /** * Whether we need to increment the group generation counter after * transmitting this message. */ GNUNET_PSYC_MASTER_TRANSMIT_INC_GROUP_GEN = 1 << 1, /** * Add PSYC header variable with the hash of the current channel state. */ GNUNET_PSYC_MASTER_TRANSMIT_ADD_STATE_HASH = 1 << 2 }; /** * Handle for a pending PSYC transmission operation. */ struct GNUNET_PSYC_MasterTransmitHandle; /** * Send a message to call a method to all members in the PSYC channel. * * @param master Handle to the PSYC channel. * @param method_name Which method should be invoked. * @param notify_mod Function to call to obtain modifiers. * @param notify_data Function to call to obtain fragments of the data. * @param notify_cls Closure for @a notify_mod and @a notify_data. * @param flags Flags for the message being transmitted. * @return Transmission handle, NULL on error (i.e. more than one request queued). */ struct GNUNET_PSYC_MasterTransmitHandle * GNUNET_PSYC_master_transmit (struct GNUNET_PSYC_Master *master, const char *method_name, GNUNET_PSYC_TransmitNotifyModifier notify_mod, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_cls, enum GNUNET_PSYC_MasterTransmitFlags flags); /** * Resume transmission to the channel. * * @param th Handle of the request that is being resumed. */ void GNUNET_PSYC_master_transmit_resume (struct GNUNET_PSYC_MasterTransmitHandle *th); /** * Abort transmission request to channel. * * @param th Handle of the request that is being aborted. */ void GNUNET_PSYC_master_transmit_cancel (struct GNUNET_PSYC_MasterTransmitHandle *th); /** * Stop a PSYC master channel. * * @param master PSYC channel master to stop. */ void GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *master); /** * Handle for a PSYC channel slave. */ struct GNUNET_PSYC_Slave; /** * Function called after the slave joined. * * @param cls Closure. * @param max_message_id Last message ID sent to the channel. */ typedef void (*GNUNET_PSYC_SlaveJoinCallback) (void *cls, uint64_t max_message_id); /** * Join a PSYC channel. * * The entity joining is always the local peer. The user must immediately use * the GNUNET_PSYC_slave_transmit() functions to transmit a @e join_msg to the * channel; if the join request succeeds, the channel state (and @e recent * method calls) will be replayed to the joining member. There is no explicit * notification on failure (as the channel may simply take days to approve, * and disapproval is simply being ignored). * * @param cfg Configuration to use. * @param channel_key ECC public key that identifies the channel we wish to join. * @param slave_key ECC private-public key pair that identifies the slave, and * used by multicast to sign the join request and subsequent unicast * requests sent to the master. * @param origin Peer identity of the origin. * @param relay_count Number of peers in the @a relays array. * @param relays Peer identities of members of the multicast group, which serve * as relays and used to join the group at. * @param message_cb Function to invoke on message parts received from the * channel, typically at least contains method handlers for @e join and * @e part. * @param join_cb function invoked once we have joined with the current * message ID of the channel * @param slave_joined_cb Function to invoke when a peer wants to join. * @param cls Closure for @a message_cb and @a slave_joined_cb. * @param method_name Method name for the join request. * @param env Environment containing transient variables for the request, or NULL. * @param data Payload for the join message. * @param data_size Number of bytes in @a data. * @return Handle for the slave, NULL on error. */ struct GNUNET_PSYC_Slave * GNUNET_PSYC_slave_join (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPrivateKey *slave_key, const struct GNUNET_PeerIdentity *origin, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, GNUNET_PSYC_MessageCallback message_cb, GNUNET_PSYC_JoinCallback join_cb, GNUNET_PSYC_SlaveJoinCallback slave_joined_cb, void *cls, const char *method_name, const struct GNUNET_ENV_Environment *env, const void *data, uint16_t data_size); /** * Part a PSYC channel. * * Will terminate the connection to the PSYC service. Polite clients should * first explicitly send a part request (via GNUNET_PSYC_slave_transmit()). * * @param slave Slave handle. */ void GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slave); /** * Flags for transmitting messages to the channel master by a slave. */ enum GNUNET_PSYC_SlaveTransmitFlags { GNUNET_PSYC_SLAVE_TRANSMIT_NONE = 0 }; /** * Handle for a pending PSYC transmission operation. */ struct GNUNET_PSYC_SlaveTransmitHandle; /** * Request a message to be sent to the channel master. * * @param slave Slave handle. * @param method_name Which (PSYC) method should be invoked (on host). * @param notify_mod Function to call to obtain modifiers. * @param notify_data Function to call to obtain fragments of the data. * @param notify_cls Closure for @a notify. * @param flags Flags for the message being transmitted. * @return Transmission handle, NULL on error (i.e. more than one request queued). */ struct GNUNET_PSYC_SlaveTransmitHandle * GNUNET_PSYC_slave_transmit (struct GNUNET_PSYC_Slave *slave, const char *method_name, GNUNET_PSYC_TransmitNotifyModifier notify_mod, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_cls, enum GNUNET_PSYC_SlaveTransmitFlags flags); /** * Resume transmission to the master. * * @param th Handle of the request that is being resumed. */ void GNUNET_PSYC_slave_transmit_resume (struct GNUNET_PSYC_SlaveTransmitHandle *th); /** * Abort transmission request to master. * * @param th Handle of the request that is being aborted. */ void GNUNET_PSYC_slave_transmit_cancel (struct GNUNET_PSYC_SlaveTransmitHandle *th); /** * Handle to access PSYC channel operations for both the master and slaves. */ struct GNUNET_PSYC_Channel; /** * Convert a channel @a master to a @e channel handle to access the @e channel * APIs. * * @param master Channel master handle. * @return Channel handle, valid for as long as @a master is valid. */ struct GNUNET_PSYC_Channel * GNUNET_PSYC_master_get_channel (struct GNUNET_PSYC_Master *master); /** * Convert @a slave to a @e channel handle to access the @e channel APIs. * * @param slave Slave handle. * @return Channel handle, valid for as long as @a slave is valid. */ struct GNUNET_PSYC_Channel * GNUNET_PSYC_slave_get_channel (struct GNUNET_PSYC_Slave *slave); /** * Add a slave to the channel's membership list. * * Note that this will NOT generate any PSYC traffic, it will merely update the * local database to modify how we react to membership test queries. * The channel master still needs to explicitly transmit a @e join message to * notify other channel members and they then also must still call this function * in their respective methods handling the @e join message. This way, how @e * join and @e part operations are exactly implemented is still up to the * application; for example, there might be a @e part_all method to kick out * everyone. * * Note that channel slaves are explicitly trusted to execute such methods * correctly; not doing so correctly will result in either denying other slaves * access or offering access to channel data to non-members. * * @param channel Channel handle. * @param slave_key Identity of channel slave to add. * @param announced_at ID of the message that announced the membership change. * @param effective_since Addition of slave is in effect since this message ID. */ void GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *channel, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t announced_at, uint64_t effective_since); /** * Remove a slave from the channel's membership list. * * Note that this will NOT generate any PSYC traffic, it will merely update the * local database to modify how we react to membership test queries. * The channel master still needs to explicitly transmit a @e part message to * notify other channel members and they then also must still call this function * in their respective methods handling the @e part message. This way, how * @e join and @e part operations are exactly implemented is still up to the * application; for example, there might be a @e part_all message to kick out * everyone. * * Note that channel members are explicitly trusted to perform these * operations correctly; not doing so correctly will result in either * denying members access or offering access to channel data to * non-members. * * @param channel Channel handle. * @param slave_key Identity of channel slave to remove. * @param announced_at ID of the message that announced the membership change. */ void GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *channel, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t announced_at); /** * Function called to inform a member about stored state values for a channel. * * @param cls Closure. * @param name Name of the state variable. A NULL value indicates that there * are no more state variables to be returned. * @param value Value of the state variable. * @param value_size Number of bytes in @a value. */ typedef void (*GNUNET_PSYC_StateCallback) (void *cls, const char *name, const void *value, size_t value_size); /** * Function called when a requested operation has finished. * * @param cls Closure. */ typedef void (*GNUNET_PSYC_FinishCallback) (void *cls); /** * Handle to a story telling operation. */ struct GNUNET_PSYC_Story; /** * Request to be told the message history of the channel. * * Historic messages (but NOT the state at the time) will be replayed (given to * the normal method handlers) if available and if access is permitted. * * To get the latest message, use 0 for both the start and end message ID. * * @param channel Which channel should be replayed? * @param start_message_id Earliest interesting point in history. * @param end_message_id Last (exclusive) interesting point in history. * @param message_cb Function to invoke on message parts received from the story. * @param finish_cb Function to call when the requested story has been fully * told (counting message IDs might not suffice, as some messages * might be secret and thus the listener would not know the story is * finished without being told explicitly); once this function * has been called, the client must not call * GNUNET_PSYC_channel_story_tell_cancel() anymore. * @param cls Closure for the callbacks. * @return Handle to cancel story telling operation. */ struct GNUNET_PSYC_Story * GNUNET_PSYC_channel_story_tell (struct GNUNET_PSYC_Channel *channel, uint64_t start_message_id, uint64_t end_message_id, GNUNET_PSYC_MessageCallback message_cb, GNUNET_PSYC_FinishCallback finish_cb, void *cls); /** * Abort story telling. * * This function must not be called from within method handlers (as given to * GNUNET_PSYC_slave_join()) of the slave. * * @param story Story telling operation to stop. */ void GNUNET_PSYC_channel_story_tell_cancel (struct GNUNET_PSYC_Story *story); /** * Handle for a state query operation. */ struct GNUNET_PSYC_StateQuery; /** * Retrieve the best matching channel state variable. * * If the requested variable name is not present in the state, the nearest * less-specific name is matched; for example, requesting "_a_b" will match "_a" * if "_a_b" does not exist. * * @param channel Channel handle. * @param full_name Full name of the requested variable, the actual variable * returned might have a shorter name.. * @param cb Function called once when a matching state variable is found. * Not called if there's no matching state variable. * @param cb_cls Closure for the callbacks. * @return Handle that can be used to cancel the query operation. */ struct GNUNET_PSYC_StateQuery * GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel, const char *full_name, GNUNET_PSYC_StateCallback cb, void *cb_cls); /** * Return all channel state variables whose name matches a given prefix. * * A name matches if it starts with the given @a name_prefix, thus requesting * the empty prefix ("") will match all values; requesting "_a_b" will also * return values stored under "_a_b_c". * * The @a state_cb is invoked on all matching state variables asynchronously, as * the state is stored in and retrieved from the PSYCstore, * * @param channel Channel handle. * @param name_prefix Prefix of the state variable name to match. * @param cb Function to call with the matching state variables. * @param cb_cls Closure for the callbacks. * @return Handle that can be used to cancel the query operation. */ struct GNUNET_PSYC_StateQuery * GNUNET_PSYC_channel_state_get_prefix (struct GNUNET_PSYC_Channel *channel, const char *name_prefix, GNUNET_PSYC_StateCallback cb, void *cb_cls); /** * Cancel a state query operation. * * @param query Handle for the operation to cancel. */ void GNUNET_PSYC_channel_state_get_cancel (struct GNUNET_PSYC_StateQuery *query); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_PSYC_SERVICE_H */ #endif /* end of gnunet_psyc_service.h */ gnunet-0.10.1/src/include/gnunet_program_lib.h0000644000175000017500000000713312225777503016270 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_program_lib.h * @brief functions related to starting programs * @author Christian Grothoff * @defgroup program functions for writing command-line programs * @{ */ #ifndef GNUNET_PROGRAM_LIB_H #define GNUNET_PROGRAM_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_configuration_lib.h" #include "gnunet_getopt_lib.h" #include "gnunet_scheduler_lib.h" /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ typedef void (*GNUNET_PROGRAM_Main) (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle * cfg); /** * Run a standard GNUnet command startup sequence (initialize loggers * and configuration, parse options). * * @param argc number of command line arguments in @a argv * @param argv command line arguments * @param binaryName our expected name * @param binaryHelp help text for the program * @param options command line options * @param task main function to run * @param task_cls closure for @a task * @param run_without_scheduler #GNUNET_NO start the scheduler, * #GNUNET_YES do not start the scheduler just run the main task * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_PROGRAM_run2 (int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls, int run_without_scheduler); /** * Run a standard GNUnet command startup sequence (initialize loggers * and configuration, parse options). * * @param argc number of command line arguments * @param argv command line arguments * @param binaryName our expected name * @param binaryHelp helptext for "-h" option (about the app) * @param options command line options * @param task main function to run * @param task_cls closure for @a task * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_PROGRAM_run (int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group program */ /* ifndef GNUNET_PROGRAM_LIB_H */ #endif /* end of gnunet_program_lib.h */ gnunet-0.10.1/src/include/Makefile.in0000644000175000017500000006627512320752062014310 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = src/include DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(am__gnunetinclude_HEADERS_DIST) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__gnunetinclude_HEADERS_DIST = platform.h plibc.h winproc.h \ gettext.h gnunet_applications.h gnunet_arm_service.h \ gnunet_ats_service.h gnunet_ats_plugin.h \ gnunet_bandwidth_lib.h gnunet_bio_lib.h gnunet_block_lib.h \ gnunet_block_plugin.h gnunet_client_lib.h gnunet_common.h \ gnunet_constants.h gnunet_configuration_lib.h \ gnunet_connection_lib.h gnunet_consensus_service.h \ gnunet_container_lib.h gnunet_conversation_service.h \ gnunet_core_service.h gnunet_crypto_lib.h \ gnunet_datacache_lib.h gnunet_datacache_plugin.h \ gnunet_datastore_service.h gnunet_datastore_plugin.h \ gnunet_dht_service.h gnunet_disk_lib.h gnunet_dnsparser_lib.h \ gnunet_dnsstub_lib.h gnunet_dns_service.h gnunet_dv_service.h \ gnunet_env_lib.h gnunet_fragmentation_lib.h \ gnunet_friends_lib.h gnunet_fs_service.h gnunet_getopt_lib.h \ gnunet_gns_service.h gnunet_gnsrecord_lib.h \ gnunet_gnsrecord_plugin.h gnunet_hello_lib.h \ gnunet_helper_lib.h gnunet_identity_service.h \ gnunet_load_lib.h gnunet_mesh_service.h \ gnunet_microphone_lib.h gnunet_multicast_service.h \ gnunet_mq_lib.h gnunet_mysql_lib.h gnunet_namecache_plugin.h \ gnunet_namecache_service.h gnunet_namestore_plugin.h \ gnunet_namestore_service.h gnunet_nat_lib.h \ gnunet_network_lib.h gnunet_nse_service.h gnunet_os_lib.h \ gnunet_peer_lib.h gnunet_peerinfo_service.h \ gnunet_plugin_lib.h gnunet_postgres_lib.h \ gnunet_psycstore_plugin.h gnunet_psycstore_service.h \ gnunet_psyc_service.h gnunet_program_lib.h gnunet_protocols.h \ gnunet_resolver_service.h gnunet_regex_service.h \ gnunet_revocation_service.h gnunet_scalarproduct_service.h \ gnunet_scheduler_lib.h gnunet_secretsharing_service.h \ gnunet_server_lib.h gnunet_service_lib.h gnunet_set_service.h \ gnunet_signal_lib.h gnunet_signatures.h gnunet_speaker_lib.h \ gnunet_statistics_service.h gnunet_strings_lib.h \ gnunet_testbed_service.h gnunet_testbed_logger_service.h \ gnunet_testing_lib.h gnunet_time_lib.h \ gnunet_transport_service.h gnunet_transport_plugin.h \ gnunet_tun_lib.h gnunet_util_lib.h gnunet_vpn_service.h am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(gnunetincludedir)" HEADERS = $(gnunetinclude_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . gnunetincludedir = $(includedir)/gnunet @MINGW_TRUE@WINPROC = winproc.h EXTRA_DIST = \ gauger.h \ block_fs.h \ block_dns.h \ block_regex.h gnunetinclude_HEADERS = \ platform.h plibc.h $(WINPROC) gettext.h \ gnunet_applications.h \ gnunet_arm_service.h \ gnunet_ats_service.h \ gnunet_ats_plugin.h \ gnunet_bandwidth_lib.h \ gnunet_bio_lib.h \ gnunet_block_lib.h \ gnunet_block_plugin.h \ gnunet_client_lib.h \ gnunet_common.h \ gnunet_constants.h \ gnunet_configuration_lib.h \ gnunet_connection_lib.h \ gnunet_consensus_service.h \ gnunet_container_lib.h \ gnunet_conversation_service.h \ gnunet_core_service.h \ gnunet_crypto_lib.h \ gnunet_datacache_lib.h \ gnunet_datacache_plugin.h \ gnunet_datastore_service.h \ gnunet_datastore_plugin.h \ gnunet_dht_service.h \ gnunet_disk_lib.h \ gnunet_dnsparser_lib.h \ gnunet_dnsstub_lib.h \ gnunet_dns_service.h \ gnunet_dv_service.h \ gnunet_env_lib.h \ gnunet_fragmentation_lib.h \ gnunet_friends_lib.h \ gnunet_fs_service.h \ gnunet_getopt_lib.h \ gnunet_gns_service.h \ gnunet_gnsrecord_lib.h \ gnunet_gnsrecord_plugin.h \ gnunet_hello_lib.h \ gnunet_helper_lib.h \ gnunet_identity_service.h \ gnunet_load_lib.h \ gnunet_mesh_service.h \ gnunet_microphone_lib.h \ gnunet_multicast_service.h \ gnunet_mq_lib.h \ gnunet_mysql_lib.h \ gnunet_namecache_plugin.h \ gnunet_namecache_service.h \ gnunet_namestore_plugin.h \ gnunet_namestore_service.h \ gnunet_nat_lib.h \ gnunet_network_lib.h \ gnunet_nse_service.h \ gnunet_os_lib.h \ gnunet_peer_lib.h \ gnunet_peerinfo_service.h \ gnunet_plugin_lib.h \ gnunet_postgres_lib.h \ gnunet_psycstore_plugin.h \ gnunet_psycstore_service.h \ gnunet_psyc_service.h \ gnunet_program_lib.h \ gnunet_protocols.h \ gnunet_resolver_service.h \ gnunet_regex_service.h \ gnunet_revocation_service.h \ gnunet_scalarproduct_service.h \ gnunet_scheduler_lib.h \ gnunet_secretsharing_service.h \ gnunet_server_lib.h \ gnunet_service_lib.h \ gnunet_set_service.h \ gnunet_signal_lib.h \ gnunet_signatures.h \ gnunet_speaker_lib.h \ gnunet_statistics_service.h \ gnunet_strings_lib.h \ gnunet_testbed_service.h \ gnunet_testbed_logger_service.h \ gnunet_testing_lib.h \ gnunet_time_lib.h \ gnunet_transport_service.h \ gnunet_transport_plugin.h \ gnunet_tun_lib.h \ gnunet_util_lib.h \ gnunet_vpn_service.h all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/include/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-gnunetincludeHEADERS: $(gnunetinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(gnunetinclude_HEADERS)'; test -n "$(gnunetincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gnunetincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gnunetincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(gnunetincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(gnunetincludedir)" || exit $$?; \ done uninstall-gnunetincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(gnunetinclude_HEADERS)'; test -n "$(gnunetincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(gnunetincludedir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(gnunetincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-gnunetincludeHEADERS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-gnunetincludeHEADERS .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am \ install-gnunetincludeHEADERS install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am \ uninstall-gnunetincludeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/include/gnunet_psycstore_service.h0000644000175000017500000004516012230245055017534 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_psycstore_service.h * @brief PSYCstore service; implements persistent storage for the PSYC service * @author Gabor X Toth * @author Christian Grothoff */ #ifndef GNUNET_PSYCSTORE_SERVICE_H #define GNUNET_PSYCSTORE_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" #include "gnunet_env_lib.h" #include "gnunet_multicast_service.h" #include "gnunet_psyc_service.h" /** * Version number of GNUnet PSYCstore API. */ #define GNUNET_PSYCSTORE_VERSION 0x00000000 /** * Flags for stored messages. */ enum GNUNET_PSYCSTORE_MessageFlags { /** * The message contains state modifiers. */ GNUNET_PSYCSTORE_MESSAGE_STATE = 1 << 0, /** * The state modifiers have been applied to the state store. */ GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED = 1 << 1, /** * The message contains a state hash. */ GNUNET_PSYCSTORE_MESSAGE_STATE_HASH = 1 << 2 }; /** * Handle for a PSYCstore */ struct GNUNET_PSYCSTORE_Handle; /** * Connect to the PSYCstore service. * * @param cfg Configuration to use. * * @return Handle for the connecton. */ struct GNUNET_PSYCSTORE_Handle * GNUNET_PSYCSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Disconnect from the PSYCstore service. * * @param h Handle for the connection. */ void GNUNET_PSYCSTORE_disconnect (struct GNUNET_PSYCSTORE_Handle *h); /** * Handle for an operation on the PSYCSTORE (useful to cancel the operation). */ struct GNUNET_PSYCSTORE_OperationHandle; /** * Function called with the result of an asynchronous operation. * * @param result #GNUNET_SYSERR on error, * #GNUNET_YES on success or if the peer was a member, * #GNUNET_NO if the peer was not a member */ typedef void (*GNUNET_PSYCSTORE_ResultCallback) (void *cls, int64_t result, const char *err_msg); /** * Store join/leave events for a PSYC channel in order to be able to answer * membership test queries later. * * @param h Handle for the PSYCstore. * @param channel_key The channel where the event happened. * @param slave_key Public key of joining/leaving slave. * @param did_join #GNUNET_YES on join, #GNUNET_NO on part. * @param announced_at ID of the message that announced the membership change. * @param effective_since Message ID this membership change is in effect since. * For joins it is <= announced_at, for parts it is always 0. * @param group_generation In case of a part, the last group generation the * slave has access to. It has relevance when a larger message have * fragments with different group generations. * @param rcb Callback to call with the result of the storage operation. * @param rcb_cls Closure for the callback. * * @return Operation handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_membership_store (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, int did_join, uint64_t announced_at, uint64_t effective_since, uint64_t group_generation, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls); /** * Test if a member was admitted to the channel at the given message ID. * * This is useful when relaying and replaying messages to check if a particular * slave has access to the message fragment with a given group generation. It * is also used when handling join requests to determine whether the slave is * currently admitted to the channel. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param slave_key Public key of slave whose membership to check. * @param message_id Message ID for which to do the membership test. * @param group_generation Group generation of the fragment of the message to * test. It has relevance if the message consists of multiple fragments * with different group generations. * @param rcb Callback to call with the test result. * @param rcb_cls Closure for the callback. * * @return Operation handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_membership_test (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t message_id, uint64_t group_generation, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls); /** * Store a message fragment sent to a channel. * * @param h Handle for the PSYCstore. * @param channel_key The channel the message belongs to. * @param message Message to store. * @param psycstore_flags Flags indicating whether the PSYC message contains * state modifiers. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_fragment_store (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_MULTICAST_MessageHeader *message, uint32_t psycstore_flags, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls); /** * Function called with one message fragment, as the result of a * GNUNET_PSYCSTORE_fragment_get() or GNUNET_PSYCSTORE_message_get() call. * * @param cls Closure. * @param message The retrieved message fragment. A NULL value indicates that * there are no more results to be returned. * @param psycstore_flags Flags stored with the message. * * @return #GNUNET_NO to stop calling this callback with further fragments, * #GNUNET_YES to continue. */ typedef int (*GNUNET_PSYCSTORE_FragmentCallback) (void *cls, struct GNUNET_MULTICAST_MessageHeader *message, enum GNUNET_PSYCSTORE_MessageFlags psycstore_flags); /** * Retrieve a message fragment by fragment ID. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param fragment_id Fragment ID to check. Use 0 to get the latest message fragment. * @param fcb Callback to call with the retrieved fragment. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t fragment_id, GNUNET_PSYCSTORE_FragmentCallback fcb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls); /** * Retrieve all fragments of a message. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id Message ID to check. Use 0 to get the latest message. * @param fcb Callback to call with the retrieved fragments. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, GNUNET_PSYCSTORE_FragmentCallback fcb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls); /** * Retrieve a fragment of message specified by its message ID and fragment * offset. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id Message ID to check. Use 0 to get the latest message. * @param fragment_offset Offset of the fragment to retrieve. * @param fcb Callback to call with the retrieved fragments. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_message_get_fragment (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t fragment_offset, GNUNET_PSYCSTORE_FragmentCallback fcb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls); /** * Callback used to return the latest value of counters for the channel master. * * @see GNUNET_PSYCSTORE_counters_get() * * @param cls Closure. * @param result_code Status code for the operation: * #GNUNET_OK: success, counter values are returned. * #GNUNET_NO: no message has been sent to the channel yet. * #GNUNET_SYSERR: an error occurred. * @param max_fragment_id Latest message fragment ID, used by multicast. * @param max_message_id Latest message ID, used by PSYC. * @param max_group_generation Latest group generation, used by PSYC. * @param max_state_message_id Latest message ID containing state modifiers that * was applied to the state store. Used for the state sync process. */ typedef void (*GNUNET_PSYCSTORE_CountersCallback) (void *cls, int result_code, uint64_t max_fragment_id, uint64_t max_message_id, uint64_t max_group_generation, uint64_t max_state_message_id); /** * Retrieve latest values of counters for a channel. * * The current value of counters are needed * - when a channel master is restarted, so that it can continue incrementing * the counters from their last value. * - when a channel slave rejoins and starts the state synchronization process. * * @param h Handle for the PSYCstore. * @param channel_key Public key that identifies the channel. * @param ccb Callback to call with the result. * @param ccb_cls Closure for the @a ccb callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_counters_get (struct GNUNET_PSYCSTORE_Handle *h, struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, GNUNET_PSYCSTORE_CountersCallback ccb, void *ccb_cls); /** * Apply modifiers of a message to the current channel state. * * An error is returned if there are missing messages containing state * operations before the current one. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id ID of the message that contains the @a modifiers. * @param state_delta Value of the @e state_delta PSYC header variable of the message. * @param modifier_count Number of elements in the @a modifiers array. * @param modifiers List of modifiers to apply. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the @a rcb callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_modify (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t state_delta, size_t modifier_count, const struct GNUNET_ENV_Modifier *modifiers, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls); /** * Store synchronized state. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id ID of the message that contains the state_hash PSYC header variable. * @param modifier_count Number of elements in the @a modifiers array. * @param modifiers Full state to store. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, size_t modifier_count, const struct GNUNET_ENV_Modifier *modifiers, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls); /** * Reset the state of a channel. * * Delete all state variables stored for the given channel. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_reset (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls); /** * Update signed values of state variables in the state store. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id Message ID that contained the state @a hash. * @param hash Hash of the serialized full state. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the callback. * */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_hash_update (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, const struct GNUNET_HashCode *hash, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls); /** * Function called with the value of a state variable. * * @param cls Closure. * @param name Name of the state variable. A NULL value indicates that there are no more * state variables to be returned. * @param value Value of the state variable. * @param value_size Number of bytes in @a value. * * @return #GNUNET_NO to stop calling this callback with further variables, * #GNUNET_YES to continue. */; typedef int (*GNUNET_PSYCSTORE_StateCallback) (void *cls, const char *name, const void *value, size_t value_size); /** * Retrieve the best matching state variable. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param name Name of variable to match, the returned variable might be less specific. * @param scb Callback to return the matching state variable. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_get (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, GNUNET_PSYCSTORE_StateCallback scb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls); /** * Retrieve all state variables for a channel with the given prefix. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param name_prefix Prefix of state variable names to match. * @param scb Callback to return matching state variables. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_get_prefix (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name_prefix, GNUNET_PSYCSTORE_StateCallback scb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls); /** * Cancel an operation. * * @param op Handle for the operation to cancel. */ void GNUNET_PSYCSTORE_operation_cancel (struct GNUNET_PSYCSTORE_OperationHandle *op); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_PSYCSTORE_SERVICE_H */ #endif /* end of gnunet_psycstore_service.h */ gnunet-0.10.1/src/include/block_dns.h0000644000175000017500000000312412225777503014345 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/block_dns.h * @author Christian Grothoff */ #ifndef BLOCK_DNS_H #define BLOCK_DNS_H #include "gnunet_util_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * This is the structure describing an DNS exit service. */ struct GNUNET_DNS_Advertisement { /** * Signature of the peer affirming that he is offering the service. */ struct GNUNET_CRYPTO_EddsaSignature signature; /** * Beginning of signed portion of the record, signs everything until * the end of the struct. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * When does this signature expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The peer providing this service */ struct GNUNET_PeerIdentity peer; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/include/gnunet_nse_service.h0000644000175000017500000000614412225777503016301 00000000000000/* This file is part of GNUnet (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GNUNET_NSE_SERVICE_H_ #define GNUNET_NSE_SERVICE_H_ /** * @file include/gnunet_nse_service.h * @brief API to retrieve the current network size estimate, * also to register for notifications whenever a new * network size estimate is calculated. * @author Nathan Evans * @defgroup nse network size estimation service * @{ */ #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Version of the network size estimation API. */ #define GNUNET_NSE_VERSION 0x00000000 /** * Handle for the network size estimation service. */ struct GNUNET_NSE_Handle; /** * Callback to call when network size estimate is updated. * * @param cls closure * @param timestamp time when the estimate was received from the server (or created by the server) * @param logestimate the log(Base 2) value of the current network size estimate * @param std_dev standard deviation for the estimate * */ typedef void (*GNUNET_NSE_Callback) (void *cls, struct GNUNET_TIME_Absolute timestamp, double logestimate, double std_dev); /** * Convert the logarithmic estimated returned to the 'GNUNET_NSE_Callback' * into an absolute estimate in terms of the number of peers in the network. * * @param loge logarithmic estimate * @return absolute number of peers in the network (estimated) */ #define GNUNET_NSE_log_estimate_to_n(loge) pow(2.0, (loge)) /** * Connect to the network size estimation service. * * @param cfg the configuration to use * @param func funtion to call with network size estimate * @param func_cls closure to pass to @a func * @return handle to use in #GNUNET_NSE_disconnect to stop NSE from invoking the callbacks */ struct GNUNET_NSE_Handle * GNUNET_NSE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_NSE_Callback func, void *func_cls); /** * Disconnect from network size estimation service * * @param h handle to destroy */ void GNUNET_NSE_disconnect (struct GNUNET_NSE_Handle *h); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group nse */ #endif /* GNUNET_NSE_SERVICE_H_ */ gnunet-0.10.1/src/include/gnunet_dnsstub_lib.h0000644000175000017500000000641212225777503016302 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_dnsstub_lib.h * @brief API for helper library to send DNS requests to DNS resolver * @author Christian Grothoff */ #ifndef GNUNET_DNSSTUB_LIB_H #define GNUNET_DNSSTUB_LIB_H #include "gnunet_common.h" #include "gnunet_tun_lib.h" /** * Opaque handle to the stub resolver. */ struct GNUNET_DNSSTUB_Context; /** * Opaque handle to a socket doing UDP requests. */ struct GNUNET_DNSSTUB_RequestSocket; /** * Start a DNS stub resolver. * * @param dns_ip target IP address to use * @return NULL on error */ struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start (const char *dns_ip); /** * Cleanup DNSSTUB resolver. * * @param ctx stub resolver to clean up */ void GNUNET_DNSSTUB_stop (struct GNUNET_DNSSTUB_Context *ctx); /** * Function called with the result of a DNS resolution. * * @param cls closure * @param rs socket that received the response * @param dns dns response, never NULL * @param dns_len number of bytes in 'dns' */ typedef void (*GNUNET_DNSSTUB_ResultCallback)(void *cls, struct GNUNET_DNSSTUB_RequestSocket *rs, const struct GNUNET_TUN_DnsHeader *dns, size_t dns_len); /** * Perform DNS resolution using given address. * * @param ctx stub resolver to use * @param sa the socket address * @param sa_len the socket length * @param request DNS request to transmit * @param request_len number of bytes in msg * @param rc function to call with result * @param rc_cls closure for 'rc' * @return socket used for the request, NULL on error */ struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa, socklen_t sa_len, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls); /** * Perform DNS resolution using our default IP from init. * * @param ctx stub resolver to use * @param request DNS request to transmit * @param request_len number of bytes in msg * @param rc function to call with result * @param rc_cls closure for 'rc' * @return socket used for the request, NULL on error */ struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls); /** * Cancel DNS resolution. * * @param rs resolution to cancel */ void GNUNET_DNSSTUB_resolve_cancel (struct GNUNET_DNSSTUB_RequestSocket *rs); #endif gnunet-0.10.1/src/include/gnunet_scheduler_lib.h0000644000175000017500000005204512265530043016567 00000000000000/* This file is part of GNUnet (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_scheduler_lib.h * @brief API to schedule computations using continuation passing style * @author Christian Grothoff * @defgroup scheduler Event loop (scheduler) * @{ */ #ifndef GNUNET_SCHEDULER_LIB_H #define GNUNET_SCHEDULER_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Opaque reference to a task. */ typedef unsigned long long GNUNET_SCHEDULER_TaskIdentifier; /** * Constant used to indicate that the scheduled * task has no others as prerequisites. */ #define GNUNET_SCHEDULER_NO_TASK ((GNUNET_SCHEDULER_TaskIdentifier) 0) /** * Reasons why the schedule may have triggered * the task now. */ enum GNUNET_SCHEDULER_Reason { /** * This is the very first task run during startup. */ GNUNET_SCHEDULER_REASON_STARTUP = 0, /** * We are shutting down and are running all shutdown-related tasks * (regardless of timeout, etc.). */ GNUNET_SCHEDULER_REASON_SHUTDOWN = 1, /** * The specified timeout has expired. * (also set if the delay given was 0). */ GNUNET_SCHEDULER_REASON_TIMEOUT = 2, /** * The reading socket is ready. */ GNUNET_SCHEDULER_REASON_READ_READY = 4, /** * The writing socket is ready. */ GNUNET_SCHEDULER_REASON_WRITE_READY = 8, /** * The prerequisite task is done. */ GNUNET_SCHEDULER_REASON_PREREQ_DONE = 16 }; /** * Valid task priorities. Use these, do not * pass random integers! */ enum GNUNET_SCHEDULER_Priority { /** * Run with the same priority as the current job. */ GNUNET_SCHEDULER_PRIORITY_KEEP = 0, /** * Run when otherwise idle. */ GNUNET_SCHEDULER_PRIORITY_IDLE = 1, /** * Run as background job (higher than idle, * lower than default). */ GNUNET_SCHEDULER_PRIORITY_BACKGROUND = 2, /** * Run with the default priority (normal * P2P operations). Any task that is scheduled * without an explicit priority being specified * will run with this priority. */ GNUNET_SCHEDULER_PRIORITY_DEFAULT = 3, /** * Run with high priority (important requests). * Higher than DEFAULT. */ GNUNET_SCHEDULER_PRIORITY_HIGH = 4, /** * Run with priority for interactive tasks. * Higher than "HIGH". */ GNUNET_SCHEDULER_PRIORITY_UI = 5, /** * Run with priority for urgent tasks. Use * for things like aborts and shutdowns that * need to preempt "UI"-level tasks. * Higher than "UI". */ GNUNET_SCHEDULER_PRIORITY_URGENT = 6, /** * This is an internal priority level that is only used for tasks * that are being triggered due to shutdown (they have automatically * highest priority). User code must not use this priority level * directly. Tasks run with this priority level that internally * schedule other tasks will see their original priority level * be inherited (unless otherwise specified). */ GNUNET_SCHEDULER_PRIORITY_SHUTDOWN = 7, /** * Number of priorities (must be the last priority). * This priority must not be used by clients. */ GNUNET_SCHEDULER_PRIORITY_COUNT = 8 }; #include "gnunet_time_lib.h" #include "gnunet_network_lib.h" /** * Context information passed to each scheduler task. */ struct GNUNET_SCHEDULER_TaskContext { /** * Reason why the task is run now */ enum GNUNET_SCHEDULER_Reason reason; /** * Set of file descriptors ready for reading; * note that additional bits may be set * that were not in the original request */ const struct GNUNET_NETWORK_FDSet *read_ready; /** * Set of file descriptors ready for writing; * note that additional bits may be set * that were not in the original request. */ const struct GNUNET_NETWORK_FDSet *write_ready; }; /** * Signature of the main function of a task. * * @param cls closure * @param tc context information (why was this task triggered now) */ typedef void (*GNUNET_SCHEDULER_Task) (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc); /** * Signature of the select function used by the scheduler. * #GNUNET_NETWORK_socket_select matches it. * * @param cls closure * @param rfds set of sockets to be checked for readability * @param wfds set of sockets to be checked for writability * @param efds set of sockets to be checked for exceptions * @param timeout relative value when to return * @return number of selected sockets, #GNUNET_SYSERR on error */ typedef int (*GNUNET_SCHEDULER_select) (void *cls, struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, struct GNUNET_TIME_Relative timeout); /** * Initialize and run scheduler. This function will return when all * tasks have completed. On systems with signals, receiving a SIGTERM * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown * to be run after the active task is complete. As a result, SIGTERM * causes all active tasks to be scheduled with reason * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added * afterwards will execute normally!). Note that any particular * signal will only shut down one scheduler; applications should * always only create a single scheduler. * * @param task task to run first (and immediately) * @param task_cls closure of task */ void GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls); /** * Request the shutdown of the scheduler. Marks all currently * pending tasks as ready because of shutdown. This will * cause all tasks to run (as soon as possible, respecting * priorities and prerequisite tasks). Note that tasks * scheduled AFTER this call may still be delayed arbitrarily. */ void GNUNET_SCHEDULER_shutdown (void); /** * Get information about the current load of this scheduler. Use this * function to determine if an elective task should be added or simply * dropped (if the decision should be made based on the number of * tasks ready to run). * * @param p priority-level to query, use KEEP to query the level * of the current task, use COUNT to get the sum over * all priority levels * @return number of tasks pending right now */ unsigned int GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p); /** * Obtain the reason code for why the current task was * started. Will return the same value as * the GNUNET_SCHEDULER_TaskContext's reason field. * * @return reason(s) why the current task is run */ enum GNUNET_SCHEDULER_Reason GNUNET_SCHEDULER_get_reason (void); /** * Cancel the task with the specified identifier. * The task must not yet have run. * * @param task id of the task to cancel * @return the closure of the callback of the cancelled task */ void * GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task); /** * Continue the current execution with the given function. This is * similar to the other "add" functions except that there is no delay * and the reason code can be specified. * * @param task main function of the task * @param task_cls closure of task * @param reason reason for task invocation */ void GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, void *task_cls, enum GNUNET_SCHEDULER_Reason reason); /** * Continue the current execution with the given function. This is * similar to the other "add" functions except that there is no delay * and the reason code can be specified. * * @param task main function of the task * @param task_cls closure for @a task * @param reason reason for task invocation * @param priority priority to use for the task */ void GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, void *task_cls, enum GNUNET_SCHEDULER_Reason reason, enum GNUNET_SCHEDULER_Priority priority); /** * Schedule a new task to be run with a specified priority. * * @param prio how important is the new task? * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run as soon as possible. Note that this * does not guarantee that this will be the next task that is being * run, as other tasks with higher priority (or that are already ready * to run) might get to run first. Just as with delays, clients must * not rely on any particular order of execution between tasks * scheduled concurrently. * * The task will be run with the DEFAULT priority. * * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run as soon as possible with the * (transitive) ignore-shutdown flag either explicitly set or * explicitly enabled. This task (and all tasks created from it, * other than by another call to this function) will either count or * not count for the 'lifeness' of the process. This API is only * useful in a few special cases. * * @param lifeness #GNUNET_YES if the task counts for lifeness, #GNUNET_NO if not. * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay. The task * will be scheduled for execution once the delay has expired. It * will be run with the DEFAULT priority. * * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay. The task * will be scheduled for execution once the delay has expired. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param priority priority to use for the task * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready for reading. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. * * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param rfd read file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified priority and to be * run after the specified delay or when the specified file descriptor * is ready for reading. The delay can be used as a timeout on the * socket being ready. The task will be scheduled for execution once * either the delay has expired or the socket operation is ready. It * will be run with the DEFAULT priority. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param priority priority to use for the task * @param rfd read file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready for writing. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. * * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param wfd write file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param priority priority of the task * @param fd file-descriptor * @param on_read whether to poll the file-descriptor for readability * @param on_write whether to poll the file-descriptor for writability * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until "task" is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *fd, int on_read, int on_write, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready for reading. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. * * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param rfd read file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until "task" is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready for writing. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. * * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param wfd write file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *wfd, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param priority priority of the task * @param fd file-descriptor * @param on_read whether to poll the file-descriptor for readability * @param on_write whether to poll the file-descriptor for writability * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_DISK_FileHandle *fd, int on_read, int on_write, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Schedule a new task to be run with a specified delay or when any of * the specified file descriptor sets is ready. The delay can be used * as a timeout on the socket(s) being ready. The task will be * scheduled for execution once either the delay has expired or any of * the socket operations is ready. This is the most general * function of the "add" family. Note that the "prerequisite_task" * must be satisfied in addition to any of the other conditions. In * other words, the task will be started when * * (prerequisite-run) * && (delay-ready * || any-rs-ready * || any-ws-ready * || shutdown-active) * * * @param prio how important is this task? * @param delay how long should we wait? Use #GNUNET_TIME_UNIT_FOREVER_REL for "forever", * which means that the task will only be run after we receive SIGTERM * @param rs set of file descriptors we want to read (can be NULL) * @param ws set of file descriptors we want to write (can be NULL) * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until "task" is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_Task task, void *task_cls); /** * Sets the select function to use in the scheduler (scheduler_select). * * @param new_select new select function to use (NULL to reset to default) * @param new_select_cls closure for 'new_select' */ void GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select, void *new_select_cls); /** @} */ /* end of group scheduler */ #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_env_lib.h0000644000175000017500000001755212262754601015412 00000000000000/* * This file is part of GNUnet. * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_env_lib.h * @brief Library providing operations for the @e environment of * PSYC and Social messages, and for (de)serializing variable values. * @author Gabor X Toth */ #ifndef GNUNET_ENV_LIB_H #define GNUNET_ENV_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Possible operations on PSYC state (persistent) and transient variables (per message). */ enum GNUNET_ENV_Operator { /** * Set value of a transient variable. */ GNUNET_ENV_OP_SET = ':', /** * Assign value for a persistent state variable. * * If an assigned value is NULL, the variable is deleted. */ GNUNET_ENV_OP_ASSIGN = '=', /** * Augment state variable. * * Used for appending strings, adding numbers, and adding new items to a list or dictionary. */ GNUNET_ENV_OP_AUGMENT = '+', /** * Diminish state variable. * * Used for subtracting numbers, and removing items from a list or dictionary. */ GNUNET_ENV_OP_DIMINISH = '-', /** * Update state variable. * * Used for modifying a single item of a list or dictionary. */ GNUNET_ENV_OP_UPDATE = '@', }; /** * PSYC variable types. */ enum GNUNET_ENV_Type { GNUNET_ENV_TYPE_DATA = 0, GNUNET_ENV_TYPE_NUMBER, GNUNET_ENV_TYPE_LIST, GNUNET_ENV_TYPE_DICT }; /** * PSYC state modifier. */ struct GNUNET_ENV_Modifier { /** * State operation. */ enum GNUNET_ENV_Operator oper; /** * Variable name. */ const char *name; /** * Size of @a value. */ size_t value_size; /** * Value of variable. */ const void *value; /** * Next modifier. */ struct GNUNET_ENV_Modifier *next; /** * Previous modifier. */ struct GNUNET_ENV_Modifier *prev; }; /** * Environment for a message. * * Contains modifiers. */ struct GNUNET_ENV_Environment; /** * Create an environment. * * @return A newly allocated environment. */ struct GNUNET_ENV_Environment * GNUNET_ENV_environment_create (); /** * Add a modifier to the environment. * * @param env The environment. * @param oper Operation to perform. * @param name Name of the variable. * @param value Value of the variable. * @param value_size Size of @a value. */ void GNUNET_ENV_environment_add (struct GNUNET_ENV_Environment *env, enum GNUNET_ENV_Operator oper, const char *name, const void *value, size_t value_size); /** * Remove a modifier at the beginning of the environment. */ int GNUNET_ENV_environment_shift (struct GNUNET_ENV_Environment *env, enum GNUNET_ENV_Operator *oper, const char **name, const void **value, size_t *value_size); /** * Get the modifier at the beginning of the environment. */ int GNUNET_ENV_environment_head (struct GNUNET_ENV_Environment *env, enum GNUNET_ENV_Operator *oper, const char **name, const void **value, size_t *value_size); /** * Iterator for modifiers in the environment. * * @param cls Closure. * @param mod Modifier. * * @return #GNUNET_YES to continue iterating, * #GNUNET_NO to stop. */ typedef int (*GNUNET_ENV_Iterator) (void *cls, enum GNUNET_ENV_Operator oper, const char *name, const char *value, uint32_t value_size); /** * Iterate through all modifiers in the environment. * * @param env The environment. * @param it Iterator. * @param it_cls Closure for iterator. */ void GNUNET_ENV_environment_iterate (const struct GNUNET_ENV_Environment *env, GNUNET_ENV_Iterator it, void *it_cls); /** * Get the number of modifiers in the environment. * * @param env The environment. * * @return Number of modifiers. */ size_t GNUNET_ENV_environment_get_count (const struct GNUNET_ENV_Environment *env); /** * Destroy an environment. * * @param env The environment to destroy. */ void GNUNET_ENV_environment_destroy (struct GNUNET_ENV_Environment *env); /** * Get the type of variable. * * @param name Name of the variable. * * @return Variable type. */ enum GNUNET_ENV_Type GNUNET_ENV_var_get_type (char *name); /** * Perform an operation on a variable. * * @param name Name of variable. * @param current_value Current value of variable. * @param current_value_size Size of @a current_value. * @param oper Operator. * @param args Arguments for the operation. * @param args_size Size of @a args. * @param return_value Return value. * @param return_value_size Size of @a return_value. * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int GNUNET_ENV_operation (char *name, void *current_value, size_t current_value_size, enum GNUNET_ENV_Operator oper, void *args, size_t args_size, void **return_value, size_t *return_value_size); /** * Get the variable's value as an integer. * * @param size Size of value. * @param value Raw value of variable. * @param[out] number Value converted to a 64-bit integer. * * @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid). */ int GNUNET_ENV_value_to_number (size_t size, const void *value, int64_t *number); /** * Get the variable's value as a list. * * @param size Size of value. * @param value Raw value of variable. * @param[out] list A newly created list holding the elements. * * @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid). */ int GNUNET_ENV_value_to_list (size_t size, const void *value, struct GNUNET_CONTAINER_SList **list); /** * Get the variable's value as a dictionary. * * @param size Size of value. * @param value Raw value of variable. * @param[out] dict A newly created hashmap holding the elements of the dictionary. * * @return #GNUNET_OK on success, #GNUNET_SYSERR if an error occurred (e.g. the value is invalid). */ int GNUNET_ENV_value_to_dict (size_t size, const void *value, struct GNUNET_CONTAINER_MultiHashMap **dict); /** * Create a PSYC variable value from an integer. * * @param number The number to convert. * @param[out] value_size Size of returned value. * * @return A newly allocated value or NULL on error. */ void * GNUNET_ENV_value_from_number (int64_t number, size_t *value_size); /** * Create a PSYC variable value from a list. * * @param list The list to convert. * @param[out] value_size Size of returned value. * * @return A newly allocated value or NULL on error. */ void * GNUNET_ENV_value_from_list (struct GNUNET_CONTAINER_SList *list, size_t *value_size); /** * Create a PSYC variable value from a dictionary. * * @param dict The dict to convert. * @param[out] value_size Size of returned value. * * @return A newly allocated value or NULL on error. */ void * GNUNET_ENV_value_from_dict (struct GNUNET_CONTAINER_MultiHashMap *dict, size_t *value_size); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_ENV_LIB_H */ #endif /* end of gnunet_env_lib.h */ gnunet-0.10.1/src/include/gnunet_common.h0000644000175000017500000007014112320754602015251 00000000000000/* This file is part of GNUnet. (C) 2006-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_common.h * @brief commonly used definitions; globals in this file * are exempt from the rule that the module name ("common") * must be part of the symbol name. * * @author Christian Grothoff * @author Nils Durner * * @defgroup logging Logging * @defgroup memory Memory management */ #ifndef GNUNET_COMMON_H #define GNUNET_COMMON_H #if HAVE_SYS_SOCKET_H #include #endif #if HAVE_NETINET_IN_H #include #endif #ifdef MINGW #include "winproc.h" #endif #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_STDARG_H #include #endif #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Version of the API (for entire gnunetutil.so library). */ #define GNUNET_UTIL_VERSION 0x000A0100 /** * Named constants for return values. The following invariants hold: * `GNUNET_NO == 0` (to allow `if (GNUNET_NO)`) `GNUNET_OK != * GNUNET_SYSERR`, `GNUNET_OK != GNUNET_NO`, `GNUNET_NO != * GNUNET_SYSERR` and finally `GNUNET_YES != GNUNET_NO`. */ #define GNUNET_OK 1 #define GNUNET_SYSERR -1 #define GNUNET_YES 1 #define GNUNET_NO 0 #define GNUNET_MIN(a,b) (((a) < (b)) ? (a) : (b)) #define GNUNET_MAX(a,b) (((a) > (b)) ? (a) : (b)) /* some systems use one underscore only, and mingw uses no underscore... */ #ifndef __BYTE_ORDER #ifdef _BYTE_ORDER #define __BYTE_ORDER _BYTE_ORDER #else #ifdef BYTE_ORDER #define __BYTE_ORDER BYTE_ORDER #endif #endif #endif #ifndef __BIG_ENDIAN #ifdef _BIG_ENDIAN #define __BIG_ENDIAN _BIG_ENDIAN #else #ifdef BIG_ENDIAN #define __BIG_ENDIAN BIG_ENDIAN #endif #endif #endif #ifndef __LITTLE_ENDIAN #ifdef _LITTLE_ENDIAN #define __LITTLE_ENDIAN _LITTLE_ENDIAN #else #ifdef LITTLE_ENDIAN #define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #endif #endif /** * @ingroup logging * define #GNUNET_EXTRA_LOGGING if using this header outside the GNUnet source * tree where gnunet_config.h is unavailable */ #ifndef GNUNET_EXTRA_LOGGING #define GNUNET_EXTRA_LOGGING 0 #endif /** * Endian operations */ # if __BYTE_ORDER == __LITTLE_ENDIAN # define GNUNET_htobe16(x) __bswap_16 (x) # define GNUNET_htole16(x) (x) # define GNUNET_be16toh(x) __bswap_16 (x) # define GNUNET_le16toh(x) (x) # define GNUNET_htobe32(x) __bswap_32 (x) # define GNUNET_htole32(x) (x) # define GNUNET_be32toh(x) __bswap_32 (x) # define GNUNET_le32toh(x) (x) # define GNUNET_htobe64(x) __bswap_64 (x) # define GNUNET_htole64(x) (x) # define GNUNET_be64toh(x) __bswap_64 (x) # define GNUNET_le64toh(x) (x) #endif # if __BYTE_ORDER == __BIG_ENDIAN # define GNUNET_htobe16(x) (x) # define GNUNET_htole16(x) __bswap_16 (x) # define GNUNET_be16toh(x) (x) # define GNUNET_le16toh(x) __bswap_16 (x) # define GNUNET_htobe32(x) (x) # define GNUNET_htole32(x) __bswap_32 (x) # define GNUNET_be32toh(x) (x) # define GNUNET_le32toh(x) __bswap_32 (x) # define GNUNET_htobe64(x) (x) # define GNUNET_htole64(x) __bswap_64 (x) # define GNUNET_be64toh(x) (x) # define GNUNET_le64toh(x) __bswap_64 (x) #endif /** * gcc-ism to get packed structs. */ #define GNUNET_PACKED __attribute__((packed)) /** * gcc-ism to get gcc bitfield layout when compiling with -mms-bitfields */ #if MINGW #define GNUNET_GCC_STRUCT_LAYOUT __attribute__((gcc_struct)) #else #define GNUNET_GCC_STRUCT_LAYOUT #endif /** * gcc-ism to force alignment; we use this to align char-arrays * that may then be cast to 'struct's. See also gcc * bug #33594. */ #ifdef __BIGGEST_ALIGNMENT__ #define GNUNET_ALIGN __attribute__((aligned (__BIGGEST_ALIGNMENT__))) #else #define GNUNET_ALIGN __attribute__((aligned (8))) #endif /** * gcc-ism to document unused arguments */ #define GNUNET_UNUSED __attribute__((unused)) /** * gcc-ism to document functions that don't return */ #define GNUNET_NORETURN __attribute__((noreturn)) #if MINGW #if __GNUC__ > 3 /** * gcc 4.x-ism to pack structures even on W32 (to be used before structs); * Using this would cause structs to be unaligned on the stack on Sparc, * so we *only* use this on W32 (see #670578 from Debian); fortunately, * W32 doesn't run on sparc anyway. */ #define GNUNET_NETWORK_STRUCT_BEGIN \ _Pragma("pack(push)") \ _Pragma("pack(1)") /** * gcc 4.x-ism to pack structures even on W32 (to be used after structs) * Using this would cause structs to be unaligned on the stack on Sparc, * so we *only* use this on W32 (see #670578 from Debian); fortunately, * W32 doesn't run on sparc anyway. */ #define GNUNET_NETWORK_STRUCT_END _Pragma("pack(pop)") #else #error gcc 4.x or higher required on W32 systems #endif #else /** * Define as empty, GNUNET_PACKED should suffice, but this won't work on W32 */ #define GNUNET_NETWORK_STRUCT_BEGIN /** * Define as empty, GNUNET_PACKED should suffice, but this won't work on W32; */ #define GNUNET_NETWORK_STRUCT_END #endif /* ************************ super-general types *********************** */ GNUNET_NETWORK_STRUCT_BEGIN /** * Header for all communications. */ struct GNUNET_MessageHeader { /** * The length of the struct (in bytes, including the length field itself), * in big-endian format. */ uint16_t size GNUNET_PACKED; /** * The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format. */ uint16_t type GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /** * Function called with a filename. * * @param cls closure * @param filename complete filename (absolute path) * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, * #GNUNET_SYSERR to abort iteration with error! */ typedef int (*GNUNET_FileNameCallback) (void *cls, const char *filename); /* ****************************** logging ***************************** */ /** * @ingroup logging * Types of errors. */ enum GNUNET_ErrorType { GNUNET_ERROR_TYPE_UNSPECIFIED = -1, GNUNET_ERROR_TYPE_NONE = 0, GNUNET_ERROR_TYPE_ERROR = 1, GNUNET_ERROR_TYPE_WARNING = 2, GNUNET_ERROR_TYPE_INFO = 4, GNUNET_ERROR_TYPE_DEBUG = 8, GNUNET_ERROR_TYPE_INVALID = 16, GNUNET_ERROR_TYPE_BULK = 32 }; /** * @ingroup logging * User-defined handler for log messages. * * @param cls closure * @param kind severeity * @param component what component is issuing the message? * @param date when was the message logged? * @param message what is the message */ typedef void (*GNUNET_Logger) (void *cls, enum GNUNET_ErrorType kind, const char *component, const char *date, const char *message); /** * @ingroup logging * Get the number of log calls that are going to be skipped * * @return number of log calls to be ignored */ int GNUNET_get_log_skip (); #if !defined(GNUNET_CULL_LOGGING) int GNUNET_get_log_call_status (int caller_level, const char *comp, const char *file, const char *function, int line); #endif /** * @ingroup logging * Main log function. * * @param kind how serious is the error? * @param message what is the message (format string) * @param ... arguments for format string */ void GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...); /* from glib */ #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) #define _GNUNET_BOOLEAN_EXPR(expr) \ __extension__ ({ \ int _gnunet_boolean_var_; \ if (expr) \ _gnunet_boolean_var_ = 1; \ else \ _gnunet_boolean_var_ = 0; \ _gnunet_boolean_var_; \ }) #define GN_LIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 1)) #define GN_UNLIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 0)) #else #define GN_LIKELY(expr) (expr) #define GN_UNLIKELY(expr) (expr) #endif #if !defined(GNUNET_LOG_CALL_STATUS) #define GNUNET_LOG_CALL_STATUS -1 #endif /** * @ingroup logging * Log function that specifies an alternative component. * This function should be used by plugins. * * @param kind how serious is the error? * @param comp component responsible for generating the message * @param message what is the message (format string) * @param ... arguments for format string */ void GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp, const char *message, ...); #if !defined(GNUNET_CULL_LOGGING) #define GNUNET_log_from(kind,comp,...) do { int log_line = __LINE__;\ static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\ if ((GNUNET_EXTRA_LOGGING > 0) || ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0)) { \ if (GN_UNLIKELY(log_call_enabled == -1))\ log_call_enabled = GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), (comp), __FILE__, __FUNCTION__, log_line); \ if (GN_UNLIKELY(GNUNET_get_log_skip () > 0)) { GNUNET_log_skip (-1, GNUNET_NO); }\ else {\ if (GN_UNLIKELY(log_call_enabled))\ GNUNET_log_from_nocheck ((kind), comp, __VA_ARGS__); \ }\ }\ } while (0) #define GNUNET_log(kind,...) do { int log_line = __LINE__;\ static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\ if ((GNUNET_EXTRA_LOGGING > 0) || ((GNUNET_ERROR_TYPE_DEBUG & (kind)) == 0)) { \ if (GN_UNLIKELY(log_call_enabled == -1))\ log_call_enabled = GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), NULL, __FILE__, __FUNCTION__, log_line);\ if (GN_UNLIKELY(GNUNET_get_log_skip () > 0)) { GNUNET_log_skip (-1, GNUNET_NO); }\ else {\ if (GN_UNLIKELY(log_call_enabled))\ GNUNET_log_nocheck ((kind), __VA_ARGS__); \ }\ }\ } while (0) #else #define GNUNET_log(...) #define GNUNET_log_from(...) #endif /** * @ingroup logging * Log error message about missing configuration option. * * @param kind log level * @param section section with missing option * @param option name of missing option */ void GNUNET_log_config_missing (enum GNUNET_ErrorType kind, const char *section, const char *option); /** * @ingroup logging * Log error message about invalid configuration option value. * * @param kind log level * @param section section with invalid option * @param option name of invalid option * @param required what is required that is invalid about the option */ void GNUNET_log_config_invalid (enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required); /** * @ingroup logging * Abort the process, generate a core dump if possible. */ void GNUNET_abort (void) GNUNET_NORETURN; /** * @ingroup logging * Ignore the next @a n calls to the log function. * * @param n number of log calls to ignore (could be negative) * @param check_reset GNUNET_YES to assert that the log skip counter is currently zero */ void GNUNET_log_skip (int n, int check_reset); /** * @ingroup logging * Setup logging. * * @param comp default component to use * @param loglevel what types of messages should be logged * @param logfile change logging to logfile (use NULL to keep stderr) * @return #GNUNET_OK on success, #GNUNET_SYSERR if logfile could not be opened */ int GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile); /** * @ingroup logging * Add a custom logger. * * @param logger log function * @param logger_cls closure for @a logger */ void GNUNET_logger_add (GNUNET_Logger logger, void *logger_cls); /** * @ingroup logging * Remove a custom logger. * * @param logger log function * @param logger_cls closure for logger */ void GNUNET_logger_remove (GNUNET_Logger logger, void *logger_cls); /** * @ingroup logging * Convert a hash value to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param hc the hash code * @return string */ const char * GNUNET_h2s (const struct GNUNET_HashCode * hc); /** * @ingroup logging * Convert a hash value to a string (for printing debug messages). * This prints all 104 characters of a hashcode! * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param hc the hash code * @return string */ const char * GNUNET_h2s_full (const struct GNUNET_HashCode * hc); /** * @ingroup logging * Convert a peer identity to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param pid the peer identity * @return string form of the pid; will be overwritten by next * call to #GNUNET_i2s. */ const char * GNUNET_i2s (const struct GNUNET_PeerIdentity *pid); /** * @ingroup logging * Convert a peer identity to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param pid the peer identity * @return string form of the pid; will be overwritten by next * call to #GNUNET_i2s. */ const char * GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid); /** * @ingroup logging * Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string * (for printing debug messages). This is one of the very few calls * in the entire API that is NOT reentrant! * * @param addr the address * @param addrlen the length of the address * @return nicely formatted string for the address * will be overwritten by next call to GNUNET_a2s. */ const char * GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen); /** * @ingroup logging * Convert error type to string. * * @param kind type to convert * @return string corresponding to the type */ const char * GNUNET_error_type_to_string (enum GNUNET_ErrorType kind); /** * @ingroup logging * Use this for fatal errors that cannot be handled */ #define GNUNET_assert(cond) do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d.\n"), __FILE__, __LINE__); GNUNET_abort(); } } while(0) /** * @ingroup logging * Use this for fatal errors that cannot be handled */ #define GNUNET_assert_at(cond, f, l) do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d.\n"), f, l); GNUNET_abort(); } } while(0) /** * @ingroup logging * Use this for internal assertion violations that are * not fatal (can be handled) but should not occur. */ #define GNUNET_break(cond) do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Assertion failed at %s:%d.\n"), __FILE__, __LINE__); } } while(0) /** * @ingroup logging * Use this for assertion violations caused by other * peers (i.e. protocol violations). We do not want to * confuse end-users (say, some other peer runs an * older, broken or incompatible GNUnet version), but * we still want to see these problems during * development and testing. "OP == other peer". */ #define GNUNET_break_op(cond) do { if (! (cond)) { GNUNET_log(GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, _("External protocol violation detected at %s:%d.\n"), __FILE__, __LINE__); } } while(0) /** * @ingroup logging * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by strerror(errno). */ #define GNUNET_log_strerror(level, cmd) do { GNUNET_log(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, STRERROR(errno)); } while(0) /** * @ingroup logging * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by strerror(errno). */ #define GNUNET_log_from_strerror(level, component, cmd) do { GNUNET_log_from (level, component, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, STRERROR(errno)); } while(0) /** * @ingroup logging * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by strerror(errno). */ #define GNUNET_log_strerror_file(level, cmd, filename) do { GNUNET_log(level, _("`%s' failed on file `%s' at %s:%d with error: %s\n"), cmd, filename,__FILE__, __LINE__, STRERROR(errno)); } while(0) /** * @ingroup logging * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by strerror(errno). */ #define GNUNET_log_from_strerror_file(level, component, cmd, filename) do { GNUNET_log_from (level, component, _("`%s' failed on file `%s' at %s:%d with error: %s\n"), cmd, filename,__FILE__, __LINE__, STRERROR(errno)); } while(0) /* ************************* endianess conversion ****************** */ /** * Convert unsigned 64-bit integer to host-byte-order. * @param n the value in network byte order * @return the same value in host byte order */ uint64_t GNUNET_ntohll (uint64_t n); /** * Convert unsigned 64-bit integer to network-byte-order. * @param n the value in host byte order * @return the same value in network byte order */ uint64_t GNUNET_htonll (uint64_t n); /** * Convert double to network-byte-order. * @param d the value in network byte order * @return the same value in host byte order */ double GNUNET_hton_double (double d); /** * Convert double to host-byte-order * @param d the value in network byte order * @return the same value in host byte order */ double GNUNET_ntoh_double (double d); /* ************************* allocation functions ****************** */ /** * @ingroup memory * Maximum allocation with GNUNET_malloc macro. */ #define GNUNET_MAX_MALLOC_CHECKED (1024 * 1024 * 40) /** * @ingroup memory * Allocate a struct or union of the given @a type. * Wrapper around #GNUNET_malloc that returns a pointer * to the newly created object of the correct type. * * @param type name of the struct or union, i.e. pass 'struct Foo'. */ #define GNUNET_new(type) (type *) GNUNET_malloc (sizeof (type)) /** * @ingroup memory * Allocate a size @a n array with structs or unions of the given @a type. * Wrapper around #GNUNET_malloc that returns a pointer * to the newly created objects of the correct type. * * @param n number of elements in the array * @param type name of the struct or union, i.e. pass 'struct Foo'. */ #define GNUNET_new_array(n, type) (type *) GNUNET_malloc ((n) * sizeof (type)) /** * @ingroup memory * Wrapper around malloc. Allocates size bytes of memory. * The memory will be zero'ed out. * * @param size the number of bytes to allocate, must be * smaller than 40 MB. * @return pointer to size bytes of memory, never NULL (!) */ #define GNUNET_malloc(size) GNUNET_xmalloc_(size, __FILE__, __LINE__) /** * @ingroup memory * Allocate and initialize a block of memory. * * @param buf data to initalize the block with * @param size the number of bytes in buf (and size of the allocation) * @return pointer to size bytes of memory, never NULL (!) */ #define GNUNET_memdup(buf,size) GNUNET_xmemdup_(buf, size, __FILE__, __LINE__) /** * @ingroup memory * Wrapper around malloc. Allocates size bytes of memory. * The memory will be zero'ed out. * * @param size the number of bytes to allocate * @return pointer to size bytes of memory, NULL if we do not have enough memory */ #define GNUNET_malloc_large(size) GNUNET_xmalloc_unchecked_(size, __FILE__, __LINE__) /** * @ingroup memory * Wrapper around realloc. Rellocates size bytes of memory. * * @param ptr the pointer to reallocate * @param size the number of bytes to reallocate * @return pointer to size bytes of memory */ #define GNUNET_realloc(ptr, size) GNUNET_xrealloc_(ptr, size, __FILE__, __LINE__) /** * @ingroup memory * Wrapper around free. Frees the memory referred to by ptr. * Note that is is generally better to free memory that was * allocated with #GNUNET_array_grow using #GNUNET_array_grow(mem, size, 0) instead of #GNUNET_free. * * @param ptr location where to free the memory. ptr must have * been returned by #GNUNET_strdup, #GNUNET_strndup, #GNUNET_malloc or #GNUNET_array_grow earlier. */ #define GNUNET_free(ptr) GNUNET_xfree_(ptr, __FILE__, __LINE__) /** * @ingroup memory * Free the memory pointed to by ptr if ptr is not NULL. * Equivalent to `if (NULL != ptr) GNUNET_free(ptr)`. * * @param ptr the location in memory to free */ #define GNUNET_free_non_null(ptr) do { void * __x__ = ptr; if (__x__ != NULL) { GNUNET_free(__x__); } } while(0) /** * @ingroup memory * Wrapper around #GNUNET_xstrdup_. Makes a copy of the zero-terminated string * pointed to by a. * * @param a pointer to a zero-terminated string * @return a copy of the string including zero-termination */ #define GNUNET_strdup(a) GNUNET_xstrdup_(a,__FILE__,__LINE__) /** * @ingroup memory * Wrapper around #GNUNET_xstrndup_. Makes a partial copy of the string * pointed to by a. * * @param a pointer to a string * @param length of the string to duplicate * @return a partial copy of the string including zero-termination */ #define GNUNET_strndup(a,length) GNUNET_xstrndup_(a,length,__FILE__,__LINE__) /** * @ingroup memory * Grow a well-typed (!) array. This is a convenience * method to grow a vector @a arr of size @a size * to the new (target) size @a tsize. *

* * Example (simple, well-typed stack): * *

 * static struct foo * myVector = NULL;
 * static int myVecLen = 0;
 *
 * static void push(struct foo * elem) {
 *   GNUNET_array_grow(myVector, myVecLen, myVecLen+1);
 *   memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
 * }
 *
 * static void pop(struct foo * elem) {
 *   if (myVecLen == 0) die();
 *   memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
 *   GNUNET_array_grow(myVector, myVecLen, myVecLen-1);
 * }
 * 
* * @param arr base-pointer of the vector, may be NULL if size is 0; * will be updated to reflect the new address. The TYPE of * arr is important since size is the number of elements and * not the size in bytes * @param size the number of elements in the existing vector (number * of elements to copy over) * @param tsize the target size for the resulting vector, use 0 to * free the vector (then, arr will be NULL afterwards). */ #define GNUNET_array_grow(arr,size,tsize) GNUNET_xgrow_((void**)&arr, sizeof(arr[0]), &size, tsize, __FILE__, __LINE__) /** * @ingroup memory * Append an element to a list (growing the * list by one). */ #define GNUNET_array_append(arr,size,element) do { GNUNET_array_grow(arr,size,size+1); arr[size-1] = element; } while(0) /** * @ingroup memory * Like snprintf, just aborts if the buffer is of insufficient size. * * @param buf pointer to buffer that is written to * @param size number of bytes in @a buf * @param format format strings * @param ... data for format string * @return number of bytes written to buf or negative value on error */ int GNUNET_snprintf (char *buf, size_t size, const char *format, ...); /** * @ingroup memory * Like asprintf, just portable. * * @param buf set to a buffer of sufficient size (allocated, caller must free) * @param format format string (see printf, fprintf, etc.) * @param ... data for format string * @return number of bytes in "*buf" excluding 0-termination */ int GNUNET_asprintf (char **buf, const char *format, ...); /* ************** internal implementations, use macros above! ************** */ /** * Allocate memory. Checks the return value, aborts if no more * memory is available. Don't use GNUNET_xmalloc_ directly. Use the * #GNUNET_malloc macro. * The memory will be zero'ed out. * * @param size number of bytes to allocate * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) * @return allocated memory, never NULL */ void * GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber); /** * Allocate and initialize memory. Checks the return value, aborts if no more * memory is available. Don't use GNUNET_xmemdup_ directly. Use the * #GNUNET_memdup macro. * * @param buf buffer to initialize from (must contain size bytes) * @param size number of bytes to allocate * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) * @return allocated memory, never NULL */ void * GNUNET_xmemdup_ (const void *buf, size_t size, const char *filename, int linenumber); /** * Allocate memory. This function does not check if the allocation * request is within reasonable bounds, allowing allocations larger * than 40 MB. If you don't expect the possibility of very large * allocations, use #GNUNET_malloc instead. The memory will be zero'ed * out. * * @param size number of bytes to allocate * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) * @return pointer to size bytes of memory, NULL if we do not have enough memory */ void * GNUNET_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber); /** * Reallocate memory. Checks the return value, aborts if no more * memory is available. */ void * GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber); /** * Free memory. Merely a wrapper for the case that we * want to keep track of allocations. Don't use GNUNET_xfree_ * directly. Use the #GNUNET_free macro. * * @param ptr pointer to memory to free * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) */ void GNUNET_xfree_ (void *ptr, const char *filename, int linenumber); /** * Dup a string. Don't call GNUNET_xstrdup_ directly. Use the #GNUNET_strdup macro. * @param str string to duplicate * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) * @return the duplicated string */ char * GNUNET_xstrdup_ (const char *str, const char *filename, int linenumber); /** * Dup partially a string. Don't call GNUNET_xstrndup_ directly. Use the #GNUNET_strndup macro. * * @param str string to duplicate * @param len length of the string to duplicate * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) * @return the duplicated string */ char * GNUNET_xstrndup_ (const char *str, size_t len, const char *filename, int linenumber); /** * Grow an array, the new elements are zeroed out. * Grows old by (*oldCount-newCount)*elementSize * bytes and sets *oldCount to newCount. * * Don't call GNUNET_xgrow_ directly. Use the #GNUNET_array_grow macro. * * @param old address of the pointer to the array * *old may be NULL * @param elementSize the size of the elements of the array * @param oldCount address of the number of elements in the *old array * @param newCount number of elements in the new array, may be 0 (then *old will be NULL afterwards) * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) */ void GNUNET_xgrow_ (void **old, size_t elementSize, unsigned int *oldCount, unsigned int newCount, const char *filename, int linenumber); /** * @ingroup memory * Create a copy of the given message. * * @param msg message to copy * @return duplicate of the message */ struct GNUNET_MessageHeader * GNUNET_copy_message (const struct GNUNET_MessageHeader *msg); #if __STDC_VERSION__ < 199901L #if __GNUC__ >= 2 #define __func__ __FUNCTION__ #else #define __func__ "" #endif #endif #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif /*GNUNET_COMMON_H_ */ gnunet-0.10.1/src/include/gnunet_container_lib.h0000644000175000017500000017064212307322113016571 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_container_lib.h * @brief container classes for GNUnet * @author Christian Grothoff * @author Nils Durner * @defgroup hashmap multi hash-map * @defgroup heap min- or max-heap with arbitrary element removal * @defgroup bloomfilter Bloom filter (probabilistic set tests) * @defgroup dll Doubly-linked list * @defgroup metadata Meta data (GNU libextractor key-value pairs) */ #ifndef GNUNET_CONTAINER_LIB_H #define GNUNET_CONTAINER_LIB_H /* add error and config prototypes */ #include "gnunet_crypto_lib.h" #include #ifndef EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME /* hack for LE < 0.6.3 */ #define EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME 180 #endif #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /* ******************* bloomfilter ***************** */ /** * @brief bloomfilter representation (opaque) * @ingroup bloomfilter */ struct GNUNET_CONTAINER_BloomFilter; /** * @ingroup bloomfilter * Iterator over struct GNUNET_HashCodes. * * @param cls closure * @param next set to the next hash code * @return #GNUNET_YES if next was updated * #GNUNET_NO if there are no more entries */ typedef int (*GNUNET_HashCodeIterator) (void *cls, struct GNUNET_HashCode *next); /** * @ingroup bloomfilter * Load a Bloom filter from a file. * * @param filename the name of the file (or the prefix) * @param size the size of the bloom-filter (number of * bytes of storage space to use); will be rounded up * to next power of 2 * @param k the number of #GNUNET_CRYPTO_hash-functions to apply per * element (number of bits set per element in the set) * @return the bloomfilter */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, unsigned int k); /** * @ingroup bloomfilter * Create a Bloom filter from raw bits. * * @param data the raw bits in memory (maybe NULL, * in which case all bits should be considered * to be zero). * @param size the size of the bloom-filter (number of * bytes of storage space to use); also size of @a data * -- unless data is NULL. Must be a power of 2. * @param k the number of #GNUNET_CRYPTO_hash-functions to apply per * element (number of bits set per element in the set) * @return the bloomfilter */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init (const char *data, size_t size, unsigned int k); /** * @ingroup bloomfilter * Copy the raw data of this Bloom filter into * the given data array. * * @param data where to write the data * @param size the size of the given @a data array * @return #GNUNET_SYSERR if the data array of the wrong size */ int GNUNET_CONTAINER_bloomfilter_get_raw_data (const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size); /** * @ingroup bloomfilter * Test if an element is in the filter. * * @param e the element * @param bf the filter * @return #GNUNET_YES if the element is in the filter, #GNUNET_NO if not */ int GNUNET_CONTAINER_bloomfilter_test (const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e); /** * @ingroup bloomfilter * Add an element to the filter. * * @param bf the filter * @param e the element */ void GNUNET_CONTAINER_bloomfilter_add (struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e); /** * @ingroup bloomfilter * Remove an element from the filter. * * @param bf the filter * @param e the element to remove */ void GNUNET_CONTAINER_bloomfilter_remove (struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *e); /** * @ingroup bloomfilter * Create a copy of a bloomfilter. * * @param bf the filter * @return copy of bf */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_copy (const struct GNUNET_CONTAINER_BloomFilter *bf); /** * @ingroup bloomfilter * Free the space associcated with a filter * in memory, flush to drive if needed (do not * free the space on the drive). * * @param bf the filter */ void GNUNET_CONTAINER_bloomfilter_free (struct GNUNET_CONTAINER_BloomFilter *bf); /** * Get the number of the addresses set per element in the bloom filter. * * @param bf the filter * @return addresses set per element in the bf */ size_t GNUNET_CONTAINER_bloomfilter_get_element_addresses (const struct GNUNET_CONTAINER_BloomFilter *bf); /** * @ingroup bloomfilter * Get size of the bloom filter. * * @param bf the filter * @return number of bytes used for the data of the bloom filter */ size_t GNUNET_CONTAINER_bloomfilter_get_size (const struct GNUNET_CONTAINER_BloomFilter *bf); /** * @ingroup bloomfilter * Reset a Bloom filter to empty. * * @param bf the filter */ void GNUNET_CONTAINER_bloomfilter_clear (struct GNUNET_CONTAINER_BloomFilter *bf); /** * @ingroup bloomfilter * "or" the entries of the given raw data array with the * data of the given Bloom filter. Assumes that * the @a size of the @a data array and the current filter * match. * * @param bf the filter * @param data data to OR-in * @param size size of @a data * @return #GNUNET_OK on success */ int GNUNET_CONTAINER_bloomfilter_or (struct GNUNET_CONTAINER_BloomFilter *bf, const char *data, size_t size); /** * @ingroup bloomfilter * "or" the entries of the given raw data array with the * data of the given Bloom filter. Assumes that * the size of the two filters matches. * * @param bf the filter * @param to_or the bloomfilter to or-in * @return #GNUNET_OK on success */ int GNUNET_CONTAINER_bloomfilter_or2 (struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_CONTAINER_BloomFilter *to_or); /** * @ingroup bloomfilter * Resize a bloom filter. Note that this operation * is pretty costly. Essentially, the Bloom filter * needs to be completely re-build. * * @param bf the filter * @param iterator an iterator over all elements stored in the BF * @param iterator_cls closure for @a iterator * @param size the new size for the filter * @param k the new number of #GNUNET_CRYPTO_hash-function to apply per element */ void GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf, GNUNET_HashCodeIterator iterator, void *iterator_cls, size_t size, unsigned int k); /* ****************** metadata ******************* */ /** * @ingroup metadata * Meta data to associate with a file, directory or namespace. */ struct GNUNET_CONTAINER_MetaData; /** * @ingroup metadata * Create a fresh meta data container. * * @return empty meta-data container */ struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_create (void); /** * @ingroup metadata * Duplicate a MetaData token. * * @param md what to duplicate * @return duplicate meta-data container */ struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData *md); /** * @ingroup metadata * Free meta data. * * @param md what to free */ void GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md); /** * @ingroup metadata * Test if two MDs are equal. We consider them equal if * the meta types, formats and content match (we do not * include the mime types and plugins names in this * consideration). * * @param md1 first value to check * @param md2 other value to check * @return #GNUNET_YES if they are equal */ int GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData *md1, const struct GNUNET_CONTAINER_MetaData *md2); /** * @ingroup metadata * Extend metadata. * * @param md metadata to extend * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_size number of bytes in data * @return #GNUNET_OK on success, #GNUNET_SYSERR if this entry already exists * data_mime_type and plugin_name are not considered for "exists" checks */ int GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size); /** * @ingroup metadata * Extend metadata. Merges the meta data from the second argument * into the first, discarding duplicate key-value pairs. * * @param md metadata to extend * @param in metadata to merge */ void GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md, const struct GNUNET_CONTAINER_MetaData *in); /** * @ingroup metadata * Remove an item. * * @param md metadata to manipulate * @param type type of the item to remove * @param data specific value to remove, NULL to remove all * entries of the given type * @param data_size number of bytes in data * @return #GNUNET_OK on success, #GNUNET_SYSERR if the item does not exist in md */ int GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type, const char *data, size_t data_size); /** * @ingroup metadata * Remove all items in the container. * * @param md metadata to manipulate */ void GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md); /** * @ingroup metadata * Add the current time as the publication date * to the meta-data. * * @param md metadata to modify */ void GNUNET_CONTAINER_meta_data_add_publication_date (struct GNUNET_CONTAINER_MetaData *md); /** * @ingroup metadata * Iterate over MD entries. * * @param md metadata to inspect * @param iter function to call on each entry, return 0 to continue to iterate * and 1 to abort iteration in this function (GNU libextractor API!) * @param iter_cls closure for @a iter * @return number of entries */ int GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md, EXTRACTOR_MetaDataProcessor iter, void *iter_cls); /** * @ingroup metadata * Get the first MD entry of the given type. Caller * is responsible for freeing the return value. * Also, only meta data items that are strings (0-terminated) * are returned by this function. * * @param md metadata to inspect * @param type type to look for * @return NULL if no entry was found */ char * GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type); /** * @ingroup metadata * Get the first matching MD entry of the given types. Caller is * responsible for freeing the return value. Also, only meta data * items that are strings (0-terminated) are returned by this * function. * * @param md metadata to inspect * @param ... -1-terminated list of types * @return NULL if we do not have any such entry, * otherwise client is responsible for freeing the value! */ char * GNUNET_CONTAINER_meta_data_get_first_by_types (const struct GNUNET_CONTAINER_MetaData *md, ...); /** * @ingroup metadata * Get a thumbnail from the meta-data (if present). Only matches meta * data with mime type "image" and binary format. * * @param md metadata to inspect * @param thumb will be set to the thumbnail data. Must be * freed by the caller! * @return number of bytes in thumbnail, 0 if not available */ size_t GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData *md, unsigned char **thumb); /** * @ingroup metadata * Options for metadata serialization. */ enum GNUNET_CONTAINER_MetaDataSerializationOptions { /** * @ingroup metadata * Serialize all of the data. */ GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL = 0, /** * @ingroup metadata * If not enough space is available, it is acceptable * to only serialize some of the metadata. */ GNUNET_CONTAINER_META_DATA_SERIALIZE_PART = 1, /** * @ingroup metadata * Speed is of the essence, do not allow compression. */ GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS = 2 }; /** * @ingroup metadata * Serialize meta-data to target. * * @param md metadata to serialize * @param target where to write the serialized metadata; * *target can be NULL, in which case memory is allocated * @param max maximum number of bytes available * @param opt is it ok to just write SOME of the * meta-data to match the size constraint, * possibly discarding some data? * @return number of bytes written on success, * -1 on error (typically: not enough * space) */ ssize_t GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData *md, char **target, size_t max, enum GNUNET_CONTAINER_MetaDataSerializationOptions opt); /** * @ingroup metadata * Get the size of the full meta-data in serialized form. * * @param md metadata to inspect * @return number of bytes needed for serialization, -1 on error */ ssize_t GNUNET_CONTAINER_meta_data_get_serialized_size (const struct GNUNET_CONTAINER_MetaData *md); /** * @ingroup metadata * Deserialize meta-data. Initializes md. * * @param input serialized meta-data. * @param size number of bytes available * @return MD on success, NULL on error (i.e. * bad format) */ struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size); /* ******************************* HashMap **************************** */ /** * @ingroup hashmap * Opaque handle for a HashMap. */ struct GNUNET_CONTAINER_MultiHashMap; /** * @ingroup hashmap * Opaque handle to an iterator over * a multihashmap. */ struct GNUNET_CONTAINER_MultiHashMapIterator; /** * @ingroup hashmap * Options for storing values in the HashMap. */ enum GNUNET_CONTAINER_MultiHashMapOption { /** * @ingroup hashmap * If a value with the given key exists, replace it. Note that the * old value would NOT be freed by replace (the application has to * make sure that this happens if required). */ GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE, /** * @ingroup hashmap * Allow multiple values with the same key. */ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, /** * @ingroup hashmap * There must only be one value per key; storing a value should fail * if a value under the same key already exists. */ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, /** * @ingroup hashmap There must only be one value per key, but don't * bother checking if a value already exists (faster than * #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY; implemented * just like #GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE but this * option documents better what is intended if * #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY is what is * desired). */ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST }; /** * @ingroup hashmap * Iterator over hash map entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ typedef int (*GNUNET_CONTAINER_HashMapIterator) (void *cls, const struct GNUNET_HashCode *key, void *value); /** * @ingroup hashmap * Create a multi hash map. * * @param len initial size (map will grow as needed) * @param do_not_copy_keys #GNUNET_NO is always safe and should be used by default; * #GNUNET_YES means that on 'put', the 'key' does not have * to be copied as the destination of the pointer is * guaranteed to be life as long as the value is stored in * the hashmap. This can significantly reduce memory * consumption, but of course is also a recipie for * heap corruption if the assumption is not true. Only * use this if (1) memory use is important in this case and * (2) you have triple-checked that the invariant holds * @return NULL on error */ struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create (unsigned int len, int do_not_copy_keys); /** * @ingroup hashmap * Destroy a hash map. Will not free any values * stored in the hash map! * * @param map the map */ void GNUNET_CONTAINER_multihashmap_destroy (struct GNUNET_CONTAINER_MultiHashMap *map); /** * @ingroup hashmap * Given a key find a value in the map matching the key. * * @param map the map * @param key what to look for * @return NULL if no value was found; note that * this is indistinguishable from values that just * happen to be NULL; use "contains" to test for * key-value pairs with value NULL */ void * GNUNET_CONTAINER_multihashmap_get (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key); /** * @ingroup hashmap * Remove the given key-value pair from the map. Note that if the * key-value pair is in the map multiple times, only one of the pairs * will be removed. * * @param map the map * @param key key of the key-value pair * @param value value of the key-value pair * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair * is not in the map */ int GNUNET_CONTAINER_multihashmap_remove (struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value); /** * @ingroup hashmap * Remove all entries for the given key from the map. * Note that the values would not be "freed". * * @param map the map * @param key identifies values to be removed * @return number of values removed */ int GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key); /** * @ingroup hashmap * Check if the map contains any value under the given * key (including values that are NULL). * * @param map the map * @param key the key to test if a value exists for it * @return #GNUNET_YES if such a value exists, * #GNUNET_NO if not */ int GNUNET_CONTAINER_multihashmap_contains (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode * key); /** * @ingroup hashmap * Check if the map contains the given value under the given * key. * * @param map the map * @param key the key to test if a value exists for it * @param value value to test for * @return #GNUNET_YES if such a value exists, * #GNUNET_NO if not */ int GNUNET_CONTAINER_multihashmap_contains_value (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value); /** * @ingroup hashmap * Store a key-value pair in the map. * * @param map the map * @param key key to use * @param value value to use * @param opt options for put * @return #GNUNET_OK on success, * #GNUNET_NO if a value was replaced (with REPLACE) * #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the * value already exists */ int GNUNET_CONTAINER_multihashmap_put (struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt); /** * @ingroup hashmap * Get the number of key-value pairs in the map. * * @param map the map * @return the number of key value pairs */ unsigned int GNUNET_CONTAINER_multihashmap_size (const struct GNUNET_CONTAINER_MultiHashMap *map); /** * @ingroup hashmap * Iterate over all entries in the map. * * @param map the map * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap_iterate (const struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_HashMapIterator it, void *it_cls); /** * @ingroup hashmap * Create an iterator for a multihashmap. * The iterator can be used to retrieve all the elements in the multihashmap * one by one, without having to handle all elements at once (in contrast to * #GNUNET_CONTAINER_multihashmap_iterate). Note that the iterator can not be * used anymore if elements have been removed from 'map' after the creation of * the iterator, or 'map' has been destroyed. Adding elements to 'map' may * result in skipped or repeated elements. * * @param map the map to create an iterator for * @return an iterator over the given multihashmap @a map */ struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create (const struct GNUNET_CONTAINER_MultiHashMap *map); /** * @ingroup hashmap * Retrieve the next element from the hash map at the iterator's * position. If there are no elements left, #GNUNET_NO is returned, * and @a key and @a value are not modified. This operation is only * allowed if no elements have been removed from the multihashmap * since the creation of @a iter, and the map has not been destroyed. * Adding elements may result in repeating or skipping elements. * * @param iter the iterator to get the next element from * @param key pointer to store the key in, can be NULL * @param value pointer to store the value in, can be NULL * @return #GNUNET_YES we returned an element, * #GNUNET_NO if we are out of elements */ int GNUNET_CONTAINER_multihashmap_iterator_next (struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value); /** * @ingroup hashmap * Destroy a multihashmap iterator. * * @param iter the iterator to destroy */ void GNUNET_CONTAINER_multihashmap_iterator_destroy (struct GNUNET_CONTAINER_MultiHashMapIterator *iter); /** * @ingroup hashmap * Iterate over all entries in the map that match a particular key. * * @param map the map * @param key key that the entries must correspond to * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode * key, GNUNET_CONTAINER_HashMapIterator it, void *it_cls); /* ***************** Version of Multihashmap for peer identities ****************** */ /** * @ingroup hashmap * Iterator over hash map entries. * * @param cls closure * @param key current public key * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ typedef int (*GNUNET_CONTAINER_PeerMapIterator) (void *cls, const struct GNUNET_PeerIdentity *key, void *value); struct GNUNET_CONTAINER_MultiPeerMap; /** * @ingroup hashmap * Create a multi peer map (hash map for public keys of peers). * * @param len initial size (map will grow as needed) * @param do_not_copy_keys #GNUNET_NO is always safe and should be used by default; * #GNUNET_YES means that on 'put', the 'key' does not have * to be copied as the destination of the pointer is * guaranteed to be life as long as the value is stored in * the hashmap. This can significantly reduce memory * consumption, but of course is also a recipie for * heap corruption if the assumption is not true. Only * use this if (1) memory use is important in this case and * (2) you have triple-checked that the invariant holds * @return NULL on error */ struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create (unsigned int len, int do_not_copy_keys); /** * @ingroup hashmap * Destroy a hash map. Will not free any values * stored in the hash map! * * @param map the map */ void GNUNET_CONTAINER_multipeermap_destroy (struct GNUNET_CONTAINER_MultiPeerMap *map); /** * @ingroup hashmap * Given a key find a value in the map matching the key. * * @param map the map * @param key what to look for * @return NULL if no value was found; note that * this is indistinguishable from values that just * happen to be NULL; use "contains" to test for * key-value pairs with value NULL */ void * GNUNET_CONTAINER_multipeermap_get (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key); /** * @ingroup hashmap * Remove the given key-value pair from the map. Note that if the * key-value pair is in the map multiple times, only one of the pairs * will be removed. * * @param map the map * @param key key of the key-value pair * @param value value of the key-value pair * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair * is not in the map */ int GNUNET_CONTAINER_multipeermap_remove (struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity * key, const void *value); /** * @ingroup hashmap * Remove all entries for the given key from the map. * Note that the values would not be "freed". * * @param map the map * @param key identifies values to be removed * @return number of values removed */ int GNUNET_CONTAINER_multipeermap_remove_all (struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key); /** * @ingroup hashmap * Check if the map contains any value under the given * key (including values that are NULL). * * @param map the map * @param key the key to test if a value exists for it * @return #GNUNET_YES if such a value exists, * #GNUNET_NO if not */ int GNUNET_CONTAINER_multipeermap_contains (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key); /** * @ingroup hashmap * Check if the map contains the given value under the given * key. * * @param map the map * @param key the key to test if a value exists for it * @param value value to test for * @return #GNUNET_YES if such a value exists, * #GNUNET_NO if not */ int GNUNET_CONTAINER_multipeermap_contains_value (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity * key, const void *value); /** * @ingroup hashmap * Store a key-value pair in the map. * * @param map the map * @param key key to use * @param value value to use * @param opt options for put * @return #GNUNET_OK on success, * #GNUNET_NO if a value was replaced (with REPLACE) * #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the * value already exists */ int GNUNET_CONTAINER_multipeermap_put (struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt); /** * @ingroup hashmap * Get the number of key-value pairs in the map. * * @param map the map * @return the number of key value pairs */ unsigned int GNUNET_CONTAINER_multipeermap_size (const struct GNUNET_CONTAINER_MultiPeerMap *map); /** * @ingroup hashmap * Iterate over all entries in the map. * * @param map the map * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multipeermap_iterate (const struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls); struct GNUNET_CONTAINER_MultiPeerMapIterator; /** * @ingroup hashmap * Create an iterator for a multihashmap. * The iterator can be used to retrieve all the elements in the multihashmap * one by one, without having to handle all elements at once (in contrast to * #GNUNET_CONTAINER_multipeermap_iterate). Note that the iterator can not be * used anymore if elements have been removed from @a map after the creation of * the iterator, or 'map' has been destroyed. Adding elements to @a map may * result in skipped or repeated elements. * * @param map the map to create an iterator for * @return an iterator over the given multihashmap @a map */ struct GNUNET_CONTAINER_MultiPeerMapIterator * GNUNET_CONTAINER_multipeermap_iterator_create (const struct GNUNET_CONTAINER_MultiPeerMap *map); /** * @ingroup hashmap * Retrieve the next element from the hash map at the iterator's * position. If there are no elements left, #GNUNET_NO is returned, * and @a key and @a value are not modified. This operation is only * allowed if no elements have been removed from the multihashmap * since the creation of @a iter, and the map has not been destroyed. * Adding elements may result in repeating or skipping elements. * * @param iter the iterator to get the next element from * @param key pointer to store the key in, can be NULL * @param value pointer to store the value in, can be NULL * @return #GNUNET_YES we returned an element, * #GNUNET_NO if we are out of elements */ int GNUNET_CONTAINER_multipeermap_iterator_next (struct GNUNET_CONTAINER_MultiPeerMapIterator *iter, struct GNUNET_PeerIdentity *key, const void **value); /** * @ingroup hashmap * Destroy a multipeermap iterator. * * @param iter the iterator to destroy */ void GNUNET_CONTAINER_multipeermap_iterator_destroy (struct GNUNET_CONTAINER_MultiPeerMapIterator *iter); /** * @ingroup hashmap * Iterate over all entries in the map that match a particular key. * * @param map the map * @param key public key that the entries must correspond to * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multipeermap_get_multiple (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls); /* Version of multihashmap with 32 bit keys */ /** * @ingroup hashmap * Opaque handle for the 32-bit key HashMap. */ struct GNUNET_CONTAINER_MultiHashMap32; /** * @ingroup hashmap * Opaque handle to an iterator over * a 32-bit key multihashmap. */ struct GNUNET_CONTAINER_MultiHashMap32Iterator; /** * @ingroup hashmap * Iterator over hash map entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ typedef int (*GNUNET_CONTAINER_HashMapIterator32) (void *cls, uint32_t key, void *value); /** * @ingroup hashmap * Create a 32-bit key multi hash map. * * @param len initial size (map will grow as needed) * @return NULL on error */ struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create (unsigned int len); /** * @ingroup hashmap * Destroy a 32-bit key hash map. Will not free any values * stored in the hash map! * * @param map the map */ void GNUNET_CONTAINER_multihashmap32_destroy (struct GNUNET_CONTAINER_MultiHashMap32 *map); /** * @ingroup hashmap * Get the number of key-value pairs in the map. * * @param map the map * @return the number of key value pairs */ unsigned int GNUNET_CONTAINER_multihashmap32_size (const struct GNUNET_CONTAINER_MultiHashMap32 *map); /** * @ingroup hashmap * Given a key find a value in the map matching the key. * * @param map the map * @param key what to look for * @return NULL if no value was found; note that * this is indistinguishable from values that just * happen to be NULL; use "contains" to test for * key-value pairs with value NULL */ void * GNUNET_CONTAINER_multihashmap32_get (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key); /** * @ingroup hashmap * Iterate over all entries in the map. * * @param map the map * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap32_iterate (const struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_HashMapIterator32 it, void *it_cls); /** * @ingroup hashmap * Remove the given key-value pair from the map. Note that if the * key-value pair is in the map multiple times, only one of the pairs * will be removed. * * @param map the map * @param key key of the key-value pair * @param value value of the key-value pair * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair * is not in the map */ int GNUNET_CONTAINER_multihashmap32_remove (struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value); /** * @ingroup hashmap * Remove all entries for the given key from the map. * Note that the values would not be "freed". * * @param map the map * @param key identifies values to be removed * @return number of values removed */ int GNUNET_CONTAINER_multihashmap32_remove_all (struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key); /** * @ingroup hashmap * Check if the map contains any value under the given * key (including values that are NULL). * * @param map the map * @param key the key to test if a value exists for it * @return #GNUNET_YES if such a value exists, * #GNUNET_NO if not */ int GNUNET_CONTAINER_multihashmap32_contains (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key); /** * @ingroup hashmap * Check if the map contains the given value under the given * key. * * @param map the map * @param key the key to test if a value exists for it * @param value value to test for * @return #GNUNET_YES if such a value exists, * #GNUNET_NO if not */ int GNUNET_CONTAINER_multihashmap32_contains_value (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value); /** * @ingroup hashmap * Store a key-value pair in the map. * * @param map the map * @param key key to use * @param value value to use * @param opt options for put * @return #GNUNET_OK on success, * #GNUNET_NO if a value was replaced (with REPLACE) * #GNUNET_SYSERR if #GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the * value already exists */ int GNUNET_CONTAINER_multihashmap32_put (struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt); /** * @ingroup hashmap * Iterate over all entries in the map that match a particular key. * * @param map the map * @param key key that the entries must correspond to * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap32_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_HashMapIterator32 it, void *it_cls); /** * Create an iterator for a 32-bit multihashmap. * The iterator can be used to retrieve all the elements in the multihashmap * one by one, without having to handle all elements at once (in contrast to * #GNUNET_CONTAINER_multihashmap32_iterate). Note that the iterator can not be * used anymore if elements have been removed from 'map' after the creation of * the iterator, or 'map' has been destroyed. Adding elements to 'map' may * result in skipped or repeated elements. * * @param map the map to create an iterator for * @return an iterator over the given multihashmap map */ struct GNUNET_CONTAINER_MultiHashMap32Iterator * GNUNET_CONTAINER_multihashmap32_iterator_create (const struct GNUNET_CONTAINER_MultiHashMap32 *map); /** * Retrieve the next element from the hash map at the iterator's position. * If there are no elements left, GNUNET_NO is returned, and 'key' and 'value' * are not modified. * This operation is only allowed if no elements have been removed from the * multihashmap since the creation of 'iter', and the map has not been destroyed. * Adding elements may result in repeating or skipping elements. * * @param iter the iterator to get the next element from * @param key pointer to store the key in, can be NULL * @param value pointer to store the value in, can be NULL * @return #GNUNET_YES we returned an element, * #GNUNET_NO if we are out of elements */ int GNUNET_CONTAINER_multihashmap32_iterator_next (struct GNUNET_CONTAINER_MultiHashMap32Iterator *iter, uint32_t *key, const void **value); /** * Destroy a 32-bit multihashmap iterator. * * @param iter the iterator to destroy */ void GNUNET_CONTAINER_multihashmap32_iterator_destroy (struct GNUNET_CONTAINER_MultiHashMapIterator *iter); /* ******************** doubly-linked list *************** */ /* To avoid mistakes: head->prev == tail->next == NULL */ /** * @ingroup dll * Insert an element at the head of a DLL. Assumes that head, tail and * element are structs with prev and next fields. * * @param head pointer to the head of the DLL * @param tail pointer to the tail of the DLL * @param element element to insert */ #define GNUNET_CONTAINER_DLL_insert(head,tail,element) do { \ GNUNET_assert ( ( (element)->prev == NULL) && ((head) != (element))); \ GNUNET_assert ( ( (element)->next == NULL) && ((tail) != (element))); \ (element)->next = (head); \ (element)->prev = NULL; \ if ((tail) == NULL) \ (tail) = element; \ else \ (head)->prev = element; \ (head) = (element); } while (0) /** * @ingroup dll * Insert an element at the tail of a DLL. Assumes that head, tail and * element are structs with prev and next fields. * * @param head pointer to the head of the DLL * @param tail pointer to the tail of the DLL * @param element element to insert */ #define GNUNET_CONTAINER_DLL_insert_tail(head,tail,element) do { \ GNUNET_assert ( ( (element)->prev == NULL) && ((head) != (element))); \ GNUNET_assert ( ( (element)->next == NULL) && ((tail) != (element))); \ (element)->prev = (tail); \ (element)->next = NULL; \ if ((head) == NULL) \ (head) = element; \ else \ (tail)->next = element; \ (tail) = (element); } while (0) /** * @ingroup dll * Insert an element into a DLL after the given other element. Insert * at the head if the other element is NULL. * * @param head pointer to the head of the DLL * @param tail pointer to the tail of the DLL * @param other prior element, NULL for insertion at head of DLL * @param element element to insert */ #define GNUNET_CONTAINER_DLL_insert_after(head,tail,other,element) do { \ GNUNET_assert ( ( (element)->prev == NULL) && ((head) != (element))); \ GNUNET_assert ( ( (element)->next == NULL) && ((tail) != (element))); \ (element)->prev = (other); \ if (NULL == other) \ { \ (element)->next = (head); \ (head) = (element); \ } \ else \ { \ (element)->next = (other)->next; \ (other)->next = (element); \ } \ if (NULL == (element)->next) \ (tail) = (element); \ else \ (element)->next->prev = (element); } while (0) /** * @ingroup dll * Insert an element into a DLL before the given other element. Insert * at the tail if the other element is NULL. * * @param head pointer to the head of the DLL * @param tail pointer to the tail of the DLL * @param other prior element, NULL for insertion at head of DLL * @param element element to insert */ #define GNUNET_CONTAINER_DLL_insert_before(head,tail,other,element) do { \ GNUNET_assert ( ( (element)->prev == NULL) && ((head) != (element))); \ GNUNET_assert ( ( (element)->next == NULL) && ((tail) != (element))); \ (element)->next = (other); \ if (NULL == other) \ { \ (element)->prev = (tail); \ (tail) = (element); \ } \ else \ { \ (element)->prev = (other)->prev; \ (other)->prev = (element); \ } \ if (NULL == (element)->prev) \ (head) = (element); \ else \ (element)->prev->next = (element); } while (0) /** * @ingroup dll * Remove an element from a DLL. Assumes that head, tail and * element point to structs with prev and next fields. * * Using the head or tail pointer as the element * argument does NOT work with this macro. * Make sure to store head/tail in another pointer * and use it to remove the head or tail of the list. * * @param head pointer to the head of the DLL * @param tail pointer to the tail of the DLL * @param element element to remove */ #define GNUNET_CONTAINER_DLL_remove(head,tail,element) do { \ GNUNET_assert ( ( (element)->prev != NULL) || ((head) == (element))); \ GNUNET_assert ( ( (element)->next != NULL) || ((tail) == (element))); \ if ((element)->prev == NULL) \ (head) = (element)->next; \ else \ (element)->prev->next = (element)->next; \ if ((element)->next == NULL) \ (tail) = (element)->prev; \ else \ (element)->next->prev = (element)->prev; \ (element)->next = NULL; \ (element)->prev = NULL; } while (0) /* ************ Multi-DLL interface, allows DLL elements to be in multiple lists at the same time *********************** */ /** * @ingroup dll * Insert an element at the head of a MDLL. Assumes that head, tail and * element are structs with prev and next fields. * * @param mdll suffix name for the next and prev pointers in the element * @param head pointer to the head of the MDLL * @param tail pointer to the tail of the MDLL * @param element element to insert */ #define GNUNET_CONTAINER_MDLL_insert(mdll,head,tail,element) do { \ GNUNET_assert ( ( (element)->prev_##mdll == NULL) && ((head) != (element))); \ GNUNET_assert ( ( (element)->next_##mdll == NULL) && ((tail) != (element))); \ (element)->next_##mdll = (head); \ (element)->prev_##mdll = NULL; \ if ((tail) == NULL) \ (tail) = element; \ else \ (head)->prev_##mdll = element; \ (head) = (element); } while (0) /** * @ingroup dll * Insert an element at the tail of a MDLL. Assumes that head, tail and * element are structs with prev and next fields. * * @param mdll suffix name for the next and prev pointers in the element * @param head pointer to the head of the MDLL * @param tail pointer to the tail of the MDLL * @param element element to insert */ #define GNUNET_CONTAINER_MDLL_insert_tail(mdll,head,tail,element) do { \ GNUNET_assert ( ( (element)->prev_##mdll == NULL) && ((head) != (element))); \ GNUNET_assert ( ( (element)->next_##mdll == NULL) && ((tail) != (element))); \ (element)->prev_##mdll = (tail); \ (element)->next_##mdll = NULL; \ if ((head) == NULL) \ (head) = element; \ else \ (tail)->next_##mdll = element; \ (tail) = (element); } while (0) /** * @ingroup dll * Insert an element into a MDLL after the given other element. Insert * at the head if the other element is NULL. * * @param mdll suffix name for the next and prev pointers in the element * @param head pointer to the head of the MDLL * @param tail pointer to the tail of the MDLL * @param other prior element, NULL for insertion at head of MDLL * @param element element to insert */ #define GNUNET_CONTAINER_MDLL_insert_after(mdll,head,tail,other,element) do { \ GNUNET_assert ( ( (element)->prev_##mdll == NULL) && ((head) != (element))); \ GNUNET_assert ( ( (element)->next_##mdll == NULL) && ((tail) != (element))); \ (element)->prev_##mdll = (other); \ if (NULL == other) \ { \ (element)->next_##mdll = (head); \ (head) = (element); \ } \ else \ { \ (element)->next_##mdll = (other)->next_##mdll; \ (other)->next_##mdll = (element); \ } \ if (NULL == (element)->next_##mdll) \ (tail) = (element); \ else \ (element)->next->prev_##mdll = (element); } while (0) /** * @ingroup dll * Insert an element into a MDLL before the given other element. Insert * at the tail if the other element is NULL. * * @param mdll suffix name for the next and prev pointers in the element * @param head pointer to the head of the MDLL * @param tail pointer to the tail of the MDLL * @param other prior element, NULL for insertion at head of MDLL * @param element element to insert */ #define GNUNET_CONTAINER_MDLL_insert_before(mdll,head,tail,other,element) do { \ GNUNET_assert ( ( (element)->prev_##mdll == NULL) && ((head) != (element))); \ GNUNET_assert ( ( (element)->next_##mdll == NULL) && ((tail) != (element))); \ (element)->next_##mdll = (other); \ if (NULL == other) \ { \ (element)->prev = (tail); \ (tail) = (element); \ } \ else \ { \ (element)->prev_##mdll = (other)->prev_##mdll; \ (other)->prev_##mdll = (element); \ } \ if (NULL == (element)->prev_##mdll) \ (head) = (element); \ else \ (element)->prev_##mdll->next_##mdll = (element); } while (0) /** * @ingroup dll * Remove an element from a MDLL. Assumes * that head, tail and element are structs * with prev and next fields. * * @param mdll suffix name for the next and prev pointers in the element * @param head pointer to the head of the MDLL * @param tail pointer to the tail of the MDLL * @param element element to remove */ #define GNUNET_CONTAINER_MDLL_remove(mdll,head,tail,element) do { \ GNUNET_assert ( ( (element)->prev_##mdll != NULL) || ((head) == (element))); \ GNUNET_assert ( ( (element)->next_##mdll != NULL) || ((tail) == (element))); \ if ((element)->prev_##mdll == NULL) \ (head) = (element)->next_##mdll; \ else \ (element)->prev_##mdll->next_##mdll = (element)->next_##mdll; \ if ((element)->next_##mdll == NULL) \ (tail) = (element)->prev_##mdll; \ else \ (element)->next_##mdll->prev_##mdll = (element)->prev_##mdll; \ (element)->next_##mdll = NULL; \ (element)->prev_##mdll = NULL; } while (0) /* ******************** Heap *************** */ /** * @ingroup heap * Cost by which elements in a heap can be ordered. */ typedef uint64_t GNUNET_CONTAINER_HeapCostType; /** * @ingroup heap * Heap type, either max or min. */ enum GNUNET_CONTAINER_HeapOrder { /** * @ingroup heap * Heap with the maximum cost at the root. */ GNUNET_CONTAINER_HEAP_ORDER_MAX, /** * @ingroup heap * Heap with the minimum cost at the root. */ GNUNET_CONTAINER_HEAP_ORDER_MIN }; /** * @ingroup heap * Handle to a Heap. */ struct GNUNET_CONTAINER_Heap; /** * @ingroup heap * Handle to a node in a heap. */ struct GNUNET_CONTAINER_HeapNode; /** * @ingroup heap * Create a new heap. * * @param order how should the heap be sorted? * @return handle to the heap */ struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create (enum GNUNET_CONTAINER_HeapOrder order); /** * @ingroup heap * Destroys the heap. Only call on a heap that * is already empty. * * @param heap heap to destroy */ void GNUNET_CONTAINER_heap_destroy (struct GNUNET_CONTAINER_Heap *heap); /** * @ingroup heap * Get element stored at root of heap. * * @param heap heap to inspect * @return NULL if heap is empty */ void * GNUNET_CONTAINER_heap_peek (const struct GNUNET_CONTAINER_Heap *heap); /** * @ingroup heap * Get the current size of the heap * * @param heap the heap to get the size of * @return number of elements stored */ unsigned int GNUNET_CONTAINER_heap_get_size (const struct GNUNET_CONTAINER_Heap *heap); /** * @ingroup heap * Get the current cost of the node * * @param node the node to get the cost of * @return cost of the node */ GNUNET_CONTAINER_HeapCostType GNUNET_CONTAINER_heap_node_get_cost (const struct GNUNET_CONTAINER_HeapNode *node); /** * @ingroup heap * Iterator for heap * * @param cls closure * @param node internal node of the heap * @param element value stored at the node * @param cost cost associated with the node * @return #GNUNET_YES if we should continue to iterate, * #GNUNET_NO if not. */ typedef int (*GNUNET_CONTAINER_HeapIterator) (void *cls, struct GNUNET_CONTAINER_HeapNode * node, void *element, GNUNET_CONTAINER_HeapCostType cost); /** * @ingroup heap * Iterate over all entries in the heap. * * @param heap the heap * @param iterator function to call on each entry * @param iterator_cls closure for @a iterator */ void GNUNET_CONTAINER_heap_iterate (const struct GNUNET_CONTAINER_Heap *heap, GNUNET_CONTAINER_HeapIterator iterator, void *iterator_cls); /** * @ingroup heap * Perform a random walk of the tree. The walk is biased * towards elements closer to the root of the tree (since * each walk starts at the root and ends at a random leaf). * The heap internally tracks the current position of the * walk. * * @param heap heap to walk * @return data stored at the next random node in the walk; * NULL if the tree is empty. */ void * GNUNET_CONTAINER_heap_walk_get_next (struct GNUNET_CONTAINER_Heap *heap); /** * @ingroup heap * Inserts a new element into the heap. * * @param heap heap to modify * @param element element to insert * @param cost cost for the element * @return node for the new element */ struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert (struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost); /** * @ingroup heap * Remove root of the heap. * * @param heap heap to modify * @return element data stored at the root node */ void * GNUNET_CONTAINER_heap_remove_root (struct GNUNET_CONTAINER_Heap *heap); /** * @ingroup heap * Removes a node from the heap. * * @param node node to remove * @return element data stored at the node, NULL if heap is empty */ void * GNUNET_CONTAINER_heap_remove_node (struct GNUNET_CONTAINER_HeapNode *node); /** * @ingroup heap * Updates the cost of any node in the tree * * @param heap heap to modify * @param node node for which the cost is to be changed * @param new_cost new cost for the node */ void GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_Heap *heap, struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost); /* ******************** Singly linked list *************** */ /** * Possible ways for how data stored in the linked list * might be allocated. * @deprecated use DLL macros */ enum GNUNET_CONTAINER_SListDisposition { /** * Single-linked list must copy the buffer. * @deprecated use DLL macros */ GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT = 0, /** * Data is static, no need to copy or free. * @deprecated use DLL macros */ GNUNET_CONTAINER_SLIST_DISPOSITION_STATIC = 2, /** * Data is dynamic, do not copy but free when done. * @deprecated use DLL macros */ GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC = 4 }; struct GNUNET_CONTAINER_SList_Elem; /** * Handle to a singly linked list * @deprecated use DLL macros */ struct GNUNET_CONTAINER_SList; /** * Handle to a singly linked list iterator * @deprecated use DLL macros */ struct GNUNET_CONTAINER_SList_Iterator { /** * Linked list that we are iterating over. */ struct GNUNET_CONTAINER_SList *list; /** * Last element accessed. */ struct GNUNET_CONTAINER_SList_Elem *last; /** * Current list element. */ struct GNUNET_CONTAINER_SList_Elem *elem; }; /** * Add a new element to the list * @param l list * @param disp memory disposition * @param buf payload buffer * @param len length of the buffer * @deprecated use DLL macros */ void GNUNET_CONTAINER_slist_add (struct GNUNET_CONTAINER_SList *l, enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, size_t len); /** * Add a new element to the end of the list * @param l list * @param disp memory disposition * @param buf payload buffer * @param len length of the buffer * @deprecated use DLL macros */ void GNUNET_CONTAINER_slist_add_end (struct GNUNET_CONTAINER_SList *l, enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, size_t len); /** * Append a singly linked list to another * @param dst list to append to * @param src source * @deprecated use DLL macros */ void GNUNET_CONTAINER_slist_append (struct GNUNET_CONTAINER_SList *dst, struct GNUNET_CONTAINER_SList *src); /** * Create a new singly linked list * @return the new list * @deprecated use DLL macros */ struct GNUNET_CONTAINER_SList * GNUNET_CONTAINER_slist_create (void); /** * Destroy a singly linked list * @param l the list to be destroyed * @deprecated use DLL macros */ void GNUNET_CONTAINER_slist_destroy (struct GNUNET_CONTAINER_SList *l); /** * Return the beginning of a list * * @param l list * @return iterator pointing to the beginning (by value! Either allocate the * structure on the stack, or use GNUNET_malloc() yourself! All other * functions do take pointer to this struct though) * @deprecated use DLL macros */ struct GNUNET_CONTAINER_SList_Iterator GNUNET_CONTAINER_slist_begin (struct GNUNET_CONTAINER_SList *l); /** * Clear a list * * @param l list * @deprecated use DLL macros */ void GNUNET_CONTAINER_slist_clear (struct GNUNET_CONTAINER_SList *l); /** * Check if a list contains a certain element * @param l list * @param buf payload buffer to find * @param len length of the payload (number of bytes in buf) * @return GNUNET_YES if found, GNUNET_NO otherwise * @deprecated use DLL macros */ int GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l, const void *buf, size_t len); /** * Check if a list contains a certain element using 'compare' function * * @param l list * @param buf payload buffer to find * @param len length of the payload (number of bytes in buf) * @param compare comparison function * * @return NULL if the 'buf' could not be found, pointer to the * list element, if found * @deprecated use DLL macros */ void * GNUNET_CONTAINER_slist_contains2 (const struct GNUNET_CONTAINER_SList *l, const void *buf, size_t len, int (*compare)(const void *, const size_t, const void *, const size_t)); /** * Count the elements of a list * @param l list * @return number of elements in the list * @deprecated use DLL macros */ int GNUNET_CONTAINER_slist_count (const struct GNUNET_CONTAINER_SList *l); /** * Remove an element from the list * @param i iterator that points to the element to be removed * @deprecated use DLL macros */ void GNUNET_CONTAINER_slist_erase (struct GNUNET_CONTAINER_SList_Iterator *i); /** * Insert an element into a list at a specific position * @param before where to insert the new element * @param disp memory disposition * @param buf payload buffer * @param len length of the payload * @deprecated use DLL macros */ void GNUNET_CONTAINER_slist_insert (struct GNUNET_CONTAINER_SList_Iterator *before, enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, size_t len); /** * Advance an iterator to the next element * @param i iterator * @return GNUNET_YES on success, GNUNET_NO if the end has been reached * @deprecated use DLL macros */ int GNUNET_CONTAINER_slist_next (struct GNUNET_CONTAINER_SList_Iterator *i); /** * Check if an iterator points beyond the end of a list * @param i iterator * @return GNUNET_YES if the end has been reached, GNUNET_NO if the iterator * points to a valid element * @deprecated use DLL macros */ int GNUNET_CONTAINER_slist_end (struct GNUNET_CONTAINER_SList_Iterator *i); /** * Retrieve the element at a specific position in a list * * @param i iterator * @param len set to the payload length * @return payload * @deprecated use DLL macros */ void * GNUNET_CONTAINER_slist_get (const struct GNUNET_CONTAINER_SList_Iterator *i, size_t *len); /** * Release an iterator * @param i iterator * @deprecated use DLL macros */ void GNUNET_CONTAINER_slist_iter_destroy (struct GNUNET_CONTAINER_SList_Iterator *i); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_CONTAINER_LIB_H */ #endif /* end of gnunet_container_lib.h */ gnunet-0.10.1/src/include/gnunet_dht_service.h0000644000175000017500000003312412225777503016271 00000000000000/* This file is part of GNUnet (C) 2004-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_dht_service.h * @brief API to the DHT service * @author Christian Grothoff * @defgroup dht Distributed Hash Table * @{ */ #ifndef GNUNET_DHT_SERVICE_H #define GNUNET_DHT_SERVICE_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_hello_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Default republication frequency for stored data in the DHT. */ #define GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 60) /** * Connection to the DHT service. */ struct GNUNET_DHT_Handle; /** * Handle to control a get operation. */ struct GNUNET_DHT_GetHandle; /** * Handle to control a find peer operation. */ struct GNUNET_DHT_FindPeerHandle; /** * Options for routing. */ enum GNUNET_DHT_RouteOption { /** * Default. Do nothing special. */ GNUNET_DHT_RO_NONE = 0, /** * Each peer along the way should look at 'enc' (otherwise * only the k-peers closest to the key should look at it). */ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE = 1, /** * We should keep track of the route that the message * took in the P2P network. */ GNUNET_DHT_RO_RECORD_ROUTE = 2, /** * This is a 'FIND-PEER' request, so approximate results are fine. */ GNUNET_DHT_RO_FIND_PEER = 4, /** * Possible message option for query key randomization. */ GNUNET_DHT_RO_BART = 8 }; /** * Initialize the connection with the DHT service. * * @param cfg configuration to use * @param ht_len size of the internal hash table to use for * processing multiple GET/FIND requests in parallel * @return NULL on error */ struct GNUNET_DHT_Handle * GNUNET_DHT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int ht_len); /** * Shutdown connection with the DHT service. * * @param handle connection to shut down */ void GNUNET_DHT_disconnect (struct GNUNET_DHT_Handle *handle); /* *************** Standard API: get and put ******************* */ /** * Opaque handle to cancel a PUT operation. */ struct GNUNET_DHT_PutHandle; /** * Type of a PUT continuation. You must not call * #GNUNET_DHT_disconnect in this continuation. * * @param cls closure * @param success #GNUNET_OK if the PUT was transmitted, * #GNUNET_NO on timeout, * #GNUNET_SYSERR on disconnect from service * after the PUT message was transmitted * (so we don't know if it was received or not) */ typedef void (*GNUNET_DHT_PutContinuation)(void *cls, int success); /** * Perform a PUT operation storing data in the DHT. * * @param handle handle to DHT service * @param key the key to store under * @param desired_replication_level estimate of how many * nearest peers this request should reach * @param options routing options for this message * @param type type of the value * @param size number of bytes in @a data; must be less than 64k * @param data the data to store * @param exp desired expiration time for the value * @param timeout how long to wait for transmission of this request * @param cont continuation to call when done (transmitting request to service) * You must not call #GNUNET_DHT_disconnect in this continuation * @param cont_cls closure for @a cont * @return handle to cancel the "PUT" operation, NULL on error * (size too big) */ struct GNUNET_DHT_PutHandle * GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, size_t size, const void *data, struct GNUNET_TIME_Absolute exp, struct GNUNET_TIME_Relative timeout, GNUNET_DHT_PutContinuation cont, void *cont_cls); /** * Cancels a DHT PUT operation. Note that the PUT request may still * go out over the network (we can't stop that); However, if the PUT * has not yet been sent to the service, cancelling the PUT will stop * this from happening (but there is no way for the user of this API * to tell if that is the case). The only use for this API is to * prevent a later call to 'cont' from #GNUNET_DHT_put (i.e. because * the system is shutting down). * * @param ph put operation to cancel ('cont' will no longer be called) */ void GNUNET_DHT_put_cancel (struct GNUNET_DHT_PutHandle *ph); /** * Iterator called on each result obtained for a DHT * operation that expects a reply * * @param cls closure * @param exp when will this value expire * @param key key of the result * @param get_path peers on reply path (or NULL if not recorded) * [0] = datastore's first neighbor, [length - 1] = local peer * @param get_path_length number of entries in @a get_path * @param put_path peers on the PUT path (or NULL if not recorded) * [0] = origin, [length - 1] = datastore * @param put_path_length number of entries in @a put_path * @param type type of the result * @param size number of bytes in @a data * @param data pointer to the result data */ typedef void (*GNUNET_DHT_GetIterator) (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data); /** * Perform an asynchronous GET operation on the DHT identified. See * also #GNUNET_BLOCK_evaluate. * * @param handle handle to the DHT service * @param type expected type of the response object * @param key the key to look up * @param desired_replication_level estimate of how many nearest peers this request should reach * @param options routing options for this message * @param xquery extended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param iter function to call on each result * @param iter_cls closure for @a iter * * @return handle to stop the async get */ struct GNUNET_DHT_GetHandle * GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, const void *xquery, size_t xquery_size, GNUNET_DHT_GetIterator iter, void *iter_cls); /** * Tell the DHT not to return any of the following known results * to this client. * * @param get_handle get operation for which results should be filtered * @param num_results number of results to be blocked that are * provided in this call (size of the @a results array) * @param results array of hash codes over the 'data' of the results * to be blocked */ void GNUNET_DHT_get_filter_known_results (struct GNUNET_DHT_GetHandle *get_handle, unsigned int num_results, const struct GNUNET_HashCode *results); /** * Stop async DHT-get. Frees associated resources. * * @param get_handle GET operation to stop. * * On return get_handle will no longer be valid, caller * must not use again!!! */ void GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle); /* *************** Extended API: monitor ******************* */ /** * Handle to monitor requests */ struct GNUNET_DHT_MonitorHandle; /** * Callback called on each GET request going through the DHT. * * @param cls Closure. * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in @a path (or 0 if not recorded). * @param path peers on the GET path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param key Key of the requested data. */ typedef void (*GNUNET_DHT_MonitorGetCB) (void *cls, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode * key); /** * Callback called on each GET reply going through the DHT. * * @param cls Closure. * @param type The type of data in the result. * @param get_path Peers on GET path (or NULL if not recorded). * @param get_path_length number of entries in @a get_path. * @param put_path peers on the PUT path (or NULL if not recorded). * @param put_path_length number of entries in @a get_path. * @param exp Expiration time of the data. * @param key Key of the data. * @param data Pointer to the result data. * @param size Number of bytes in @a data. */ typedef void (*GNUNET_DHT_MonitorGetRespCB) (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const void *data, size_t size); /** * Callback called on each PUT request going through the DHT. * * @param cls Closure. * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in @a path (or 0 if not recorded). * @param path peers on the PUT path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param exp Expiration time of the data. * @param key Key under which data is to be stored. * @param data Pointer to the data carried. * @param size Number of bytes in data. */ typedef void (*GNUNET_DHT_MonitorPutCB) (void *cls, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const void *data, size_t size); /** * Start monitoring the local DHT service. * * @param handle Handle to the DHT service. * @param type Type of blocks that are of interest. * @param key Key of data of interest, NULL for all. * @param get_cb Callback to process monitored get messages. * @param get_resp_cb Callback to process monitored get response messages. * @param put_cb Callback to process monitored put messages. * @param cb_cls Closure for callbacks * @return Handle to stop monitoring. */ struct GNUNET_DHT_MonitorHandle * GNUNET_DHT_monitor_start (struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, GNUNET_DHT_MonitorGetCB get_cb, GNUNET_DHT_MonitorGetRespCB get_resp_cb, GNUNET_DHT_MonitorPutCB put_cb, void *cb_cls); /** * Stop monitoring. * On return handle will no longer be valid, caller must not use again!!! * * @param handle The handle to the monitor request returned by monitor_start. */ void GNUNET_DHT_monitor_stop (struct GNUNET_DHT_MonitorHandle *handle); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group dht */ #endif /* gnunet_dht_service.h */ gnunet-0.10.1/src/include/gnunet_load_lib.h0000644000175000017500000000555212225777503015543 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_load_lib.h * @brief functions related to load calculations * @author Christian Grothoff */ #ifndef GNUNET_LOAD_LIB_H #define GNUNET_LOAD_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_common.h" #include "gnunet_time_lib.h" /** * Opaque load handle. */ struct GNUNET_LOAD_Value; /** * Create a new load value. * * @param autodecline speed at which this value should automatically * decline in the absence of external events; at the given * frequency, 0-load values will be added to the load * @return the new load value */ struct GNUNET_LOAD_Value * GNUNET_LOAD_value_init (struct GNUNET_TIME_Relative autodecline); /** * Change the value by which the load automatically declines. * * @param load load to update * @param autodecline frequency of load decline */ void GNUNET_LOAD_value_set_decline (struct GNUNET_LOAD_Value *load, struct GNUNET_TIME_Relative autodecline); /** * Free a load value. * * @param lv value to free */ #define GNUNET_LOAD_value_free(lv) GNUNET_free (lv) /** * Get the current load. * * @param load load handle * @return zero for below-average load, otherwise * number of std. devs we are above average; * 100 if the latest updates were so large * that we could not do proper calculations */ double GNUNET_LOAD_get_load (struct GNUNET_LOAD_Value *load); /** * Get the average value given to update so far. * * @param load load handle * @return zero if update was never called */ double GNUNET_LOAD_get_average (struct GNUNET_LOAD_Value *load); /** * Update the current load. * * @param load to update * @param data latest measurement value (for example, delay) */ void GNUNET_LOAD_update (struct GNUNET_LOAD_Value *load, uint64_t data); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_LOAD_LIB_H */ #endif /* end of gnunet_load_lib.h */ gnunet-0.10.1/src/include/gnunet_network_lib.h0000644000175000017500000003251112225777503016310 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_network_lib.h * @brief basic low-level networking interface * @author Nils Durner */ #ifndef GNUNET_NETWORK_LIB_H #define GNUNET_NETWORK_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * @brief handle to a socket */ struct GNUNET_NETWORK_Handle; /** * @brief collection of IO descriptors */ struct GNUNET_NETWORK_FDSet { /** * Maximum number of any socket socket descriptor in the set (plus one) */ int nsds; /** * Bitset with the descriptors. */ fd_set sds; #ifdef WINDOWS /** * Linked list of handles */ struct GNUNET_CONTAINER_SList *handles; #endif }; #include "gnunet_disk_lib.h" #include "gnunet_time_lib.h" /** * Test if the given protocol family is supported by this system. * * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX) * @return #GNUNET_OK if the PF is supported */ int GNUNET_NETWORK_test_pf (int pf); /** * Given a unixpath that is too long (larger than UNIX_PATH_MAX), * shorten it to an acceptable length while keeping it unique * and making sure it remains a valid filename (if possible). * * @param unixpath long path, will be freed (or same pointer returned * with moved 0-termination). * @return shortened unixpath, NULL on error */ char * GNUNET_NETWORK_shorten_unixpath (char *unixpath); /** * Accept a new connection on a socket. Configure it for non-blocking * IO and mark it as non-inheritable to child processes (set the * close-on-exec flag). * * @param desc bound socket * @param address address of the connecting peer, may be NULL * @param address_len length of address * @return client socket */ struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len); /** * Box a native socket (and check that it is a socket). * * @param fd socket to box * @return NULL on error (including not supported on target platform) */ struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native (SOCKTYPE fd); /** * Set if a socket should use blocking or non-blocking IO. * * @param fd socket * @param doBlock blocking mode * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock); /** * Bind a socket to a particular address. * * @param desc socket to bind * @param address address to be bound * @param address_len length of address * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len); /** * Close a socket. * * @param desc socket to close * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc); /** * Only free memory of a socket, keep the file descriptor untouched. * * @param desc socket */ void GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc); /** * Connect a socket to some remote address. * * @param desc socket to connect * @param address peer address * @param address_len of address * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len); /** * Get socket options * * @param desc socket to inspect * @param level protocol level of the option * @param optname identifier of the option * @param optval options * @param optlen length of optval * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc, int level, int optname, void *optval, socklen_t * optlen); /** * Listen on a socket * * @param desc socket to start listening on * @param backlog length of the listen queue * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc, int backlog); /** * How much data is available to be read on this descriptor? * * @param desc socket * @returns #GNUNET_NO if no data is available, or on error! */ ssize_t GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *desc); /** * Read data from a socket (always non-blocking). * * @param desc socket * @param buffer buffer * @param length length of buffer * @param src_addr either the source to recv from, or all zeroes * to be filled in by recvfrom * @param addrlen length of the addr */ ssize_t GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen); /** * Read data from a connected socket (always non-blocking). * * @param desc socket * @param buffer buffer * @param length length of buffer * @return number of bytes read */ ssize_t GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length); /** * Check if sockets meet certain conditions * @param rfds set of sockets to be checked for readability * @param wfds set of sockets to be checked for writability * @param efds set of sockets to be checked for exceptions * @param timeout relative value when to return * @return number of selected sockets, #GNUNET_SYSERR on error */ int GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, struct GNUNET_TIME_Relative timeout); /** * Send data (always non-blocking). * * @param desc socket * @param buffer data to send * @param length size of the buffer * @return number of bytes sent, #GNUNET_SYSERR on error */ ssize_t GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length); /** * Send data to a particular destination (always non-blocking). * This function only works for UDP sockets. * * @param desc socket * @param message data to send * @param length size of the data * @param dest_addr destination address * @param dest_len length of address * @return number of bytes sent, #GNUNET_SYSERR on error */ ssize_t GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len); /** * Set socket option * * @param fd socket * @param level protocol level of the option * @param option_name option identifier * @param option_value value to set * @param option_len size of option_value * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level, int option_name, const void *option_value, socklen_t option_len); /** * Shut down socket operations * * @param desc socket * @param how type of shutdown * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how); /** * Disable the "CORK" feature for communication with the given socket, * forcing the OS to immediately flush the buffer on transmission * instead of potentially buffering multiple messages. Essentially * reduces the OS send buffers to zero. * * @param desc socket * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc); /** * Create a new socket. Configure it for non-blocking IO and * mark it as non-inheritable to child processes (set the * close-on-exec flag). * * @param domain domain of the socket * @param type socket type * @param protocol network protocol * @return new socket, NULL on error */ struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create (int domain, int type, int protocol); /** * Reset FD set (clears all file descriptors). * * @param fds fd set to clear */ void GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds); /** * Add a socket to the FD set * * @param fds fd set * @param desc socket to add */ void GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc); #if WINDOWS /** * Add a W32 file handle to the fd set * * @param fds fd set * @param h the file handle to add */ void GNUNET_NETWORK_fdset_handle_set_native_w32_handle (struct GNUNET_NETWORK_FDSet *fds, HANDLE h); #endif /** * Check whether a socket is part of the fd set * * @param fds fd set * @param desc socket * @return #GNUNET_YES if the socket is in the set */ int GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc); /** * Add one fd set to another (computes the union). * * @param dst the fd set to add to * @param src the fd set to add from */ void GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, const struct GNUNET_NETWORK_FDSet *src); /** * Copy one fd set to another * * @param to destination * @param from source */ void GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, const struct GNUNET_NETWORK_FDSet *from); /** * Return file descriptor for this network handle * * @param desc wrapper to process * @return POSIX file descriptor */ int GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc); /** * Return the sockaddr for this network handle * * @param desc wrapper to process * @return POSIX file descriptor */ struct sockaddr* GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc); /** * Return sockaddr length for this network handle * * @param desc wrapper to process * @return socklen_t for sockaddr */ socklen_t GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc); /** * Copy a native fd set into the GNUnet representation. * * @param to destination * @param from native source set * @param nfds the biggest socket number in from + 1 */ void GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to, const fd_set *from, int nfds); /** * Set a native fd in a set * * @param to destination * @param nfd native FD to set */ void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd); /** * Test native fd in a set * * @param to set to test, NULL for empty set * @param nfd native FD to test, -1 for none * @return GNUNET_YES if to contains nfd */ int GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to, int nfd); /** * Add a file handle to the fd set * * @param fds fd set * @param h the file handle to add */ void GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_DISK_FileHandle *h); /** * Check if a file handle is part of an fd set * @param fds fd set * @param h file handle * @return #GNUNET_YES if the file handle is part of the set */ int GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_DISK_FileHandle *h); /** * Checks if two fd sets overlap * * @param fds1 first fd set * @param fds2 second fd set * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise */ int GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, const struct GNUNET_NETWORK_FDSet *fds2); /** * Creates an fd set * * @return a new fd set */ struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create (void); /** * Releases the associated memory of an fd set * * @param fds fd set */ void GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif /* GNUNET_NETWORK_LIB_H */ gnunet-0.10.1/src/include/gnunet_bio_lib.h0000644000175000017500000001743312225777503015376 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_bio_lib.h * @brief buffered IO API * @author Christian Grothoff * @defgroup bio Buffered binary disk IO (with endianess conversion) * @{ */ #ifndef GNUNET_BIO_LIB_H #define GNUNET_BIO_LIB_H #include "gnunet_container_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * @ingroup bio * Handle for buffered reading. */ struct GNUNET_BIO_ReadHandle; /** * Open a file for reading. * * @param fn file name to be opened * @return IO handle on success, NULL on error */ struct GNUNET_BIO_ReadHandle * GNUNET_BIO_read_open (const char *fn); /** * Close an open file. Reports if any errors reading * from the file were encountered. * * @param h file handle * @param emsg set to the error message * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, char **emsg); /** * Read the contents of a binary file into a buffer. * * @param h handle to an open file * @param what describes what is being read (for error message creation) * @param result the buffer to write the result to * @param len the number of bytes to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, const char *what, void *result, size_t len); /** * Read the contents of a binary file into a buffer. * * @param h handle to an open file * @param file name of the source file * @param line line number in the source file * @param result the buffer to write the result to * @param len the number of bytes to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read_fn (struct GNUNET_BIO_ReadHandle *h, const char *file, int line, void *result, size_t len); /** * Read 0-terminated string from a file. * * @param h handle to an open file * @param what describes what is being read (for error message creation) * @param result the buffer to store a pointer to the (allocated) string to * (note that *result could be set to NULL as well) * @param max_length maximum allowed length for the string * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, const char *what, char **result, size_t max_length); /** * Read metadata container from a file. * * @param h handle to an open file * @param what describes what is being read (for error message creation) * @param result the buffer to store a pointer to the (allocated) metadata * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h, const char *what, struct GNUNET_CONTAINER_MetaData **result); /** * Read a float. * * @param h hande to open file * @param f address of float to read */ #define GNUNET_BIO_read_float(h, f) (GNUNET_BIO_read_fn (h, __FILE__, __LINE__, f, sizeof(float))) /** * Read a double. * * @param h hande to open file * @param f address of double to read */ #define GNUNET_BIO_read_double(h, f) (GNUNET_BIO_read_fn (h, __FILE__, __LINE__, f, sizeof(double))) /** * Read an (u)int32_t. * * @param h hande to open file * @param file name of the source file * @param line line number in the code * @param i address of 32-bit integer to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h, const char *file, int line, int32_t * i); /** * Read an (u)int32_t. * * @param h hande to open file * @param i address of 32-bit integer to read */ #define GNUNET_BIO_read_int32(h, i) GNUNET_BIO_read_int32__ (h, __FILE__, __LINE__, (int32_t*) i) /** * Read an (u)int64_t. * * @param h hande to open file * @param file name of the source file * @param line line number in the code * @param i address of 64-bit integer to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h, const char *file, int line, int64_t * i); /** * Read an (u)int64_t. * * @param h hande to open file * @param i address of 64-bit integer to read */ #define GNUNET_BIO_read_int64(h, i) GNUNET_BIO_read_int64__ (h, __FILE__, __LINE__, (int64_t*) i) /** * Handle for buffered writing. */ struct GNUNET_BIO_WriteHandle; /** * Open a file for writing. * * @param fn file name to be opened * @return IO handle on success, NULL on error */ struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open (const char *fn); /** * Close an open file for writing. * * @param h file handle * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h); /** * Write a buffer to a file. * * @param h handle to open file * @param buffer the data to write * @param n number of bytes to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, const void *buffer, size_t n); /** * Force a buffered writer to flush its buffer * * @param h the writer handle * @return #GNUNET_OK upon success. Upon failure #GNUNET_SYSERR is returned and * the file is closed */ int GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h); /** * Write a string to a file. * * @param h handle to open file * @param s string to write (can be NULL) * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, const char *s); /** * Write metadata container to a file. * * @param h handle to open file * @param m metadata to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, const struct GNUNET_CONTAINER_MetaData *m); /** * Write a float. * * @param h hande to open file * @param f float to write (must be a variable) */ #define GNUNET_BIO_write_float(h, f) GNUNET_BIO_write (h, &f, sizeof(float)) /** * Write a double. * * @param h hande to open file * @param f double to write (must be a variable) */ #define GNUNET_BIO_write_double(h, f) GNUNET_BIO_write (h, &f, sizeof(double)) /** * Write an (u)int32_t. * * @param h hande to open file * @param i 32-bit integer to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h, int32_t i); /** * Write an (u)int64_t. * * @param h hande to open file * @param i 64-bit integer to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h, int64_t i); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group bio */ /* ifndef GNUNET_BIO_LIB_H */ #endif /* end of gnunet_bio_lib.h */ gnunet-0.10.1/src/include/winproc.h0000644000175000017500000002613112225777503014073 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/winproc.h * @brief Definitions for MS Windows * @author Nils Durner */ #ifndef _WINPROC_H #define _WINPROC_H #include #include #include #include #include #include #include #ifndef FD_SETSIZE #define FD_SETSIZE 1024 #endif #include #include #include #include #include #include #include #include /* #define BYTE_ORDER */ #include #include #include #ifdef __cplusplus extern "C" { #endif #ifndef MAX_NAME_LENGTH #define MAX_NAME_LENGTH 25 #endif typedef DWORD WINAPI (*TNtQuerySystemInformation) (int, PVOID, ULONG, PULONG); typedef DWORD WINAPI (*TGetIfEntry) (PMIB_IFROW pIfRow); typedef DWORD WINAPI (*TGetIpAddrTable) (PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder); typedef DWORD WINAPI (*TGetIfTable) (PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder); typedef DWORD WINAPI (*TGetBestInterfaceEx) (struct sockaddr *, PDWORD); /* TODO: Explicitly import -A variants (i.e. TCreateHardLinkA) or -W * variants (TCreateHardLinkW), etc. */ typedef DWORD WINAPI (*TCreateHardLink) (LPCTSTR lpFileName, LPCTSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes); typedef SC_HANDLE WINAPI (*TOpenSCManager) (LPCTSTR lpMachineName, LPCTSTR lpDatabaseName, DWORD dwDesiredAccess); typedef SC_HANDLE WINAPI (*TCreateService) (SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPCTSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, LPCTSTR lpServiceStartName, LPCTSTR lpPassword); typedef BOOL WINAPI (*TCloseServiceHandle) (SC_HANDLE hSCObject); typedef BOOL WINAPI (*TDeleteService) (SC_HANDLE hService); typedef SERVICE_STATUS_HANDLE WINAPI (*TRegisterServiceCtrlHandler) (LPCTSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc); typedef BOOL WINAPI (*TSetServiceStatus) (SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus); typedef BOOL WINAPI (*TStartServiceCtrlDispatcher) (const LPSERVICE_TABLE_ENTRY lpServiceTable); typedef BOOL WINAPI (*TControlService) (SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus); typedef SC_HANDLE WINAPI (*TOpenService) (SC_HANDLE hSCManager, LPCTSTR lpServiceName, DWORD dwDesiredAccess); typedef DWORD WINAPI (*TGetAdaptersInfo) (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen); typedef NET_API_STATUS WINAPI (*TNetUserAdd) (LPCWSTR, DWORD, PBYTE, PDWORD); typedef NET_API_STATUS WINAPI (*TNetUserSetInfo) (LPCWSTR servername, LPCWSTR username, DWORD level, LPBYTE buf, LPDWORD param_err); typedef NTSTATUS NTAPI (*TLsaOpenPolicy) (PLSA_UNICODE_STRING, PLSA_OBJECT_ATTRIBUTES, ACCESS_MASK, PLSA_HANDLE); typedef NTSTATUS NTAPI (*TLsaAddAccountRights) (LSA_HANDLE, PSID, PLSA_UNICODE_STRING, ULONG); typedef NTSTATUS NTAPI (*TLsaRemoveAccountRights) (LSA_HANDLE, PSID, BOOLEAN, PLSA_UNICODE_STRING, ULONG); typedef NTSTATUS NTAPI (*TLsaClose) (LSA_HANDLE); typedef BOOL WINAPI (*TLookupAccountName) (LPCTSTR lpSystemName, LPCTSTR lpAccountName, PSID Sid, LPDWORD cbSid, LPTSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse); typedef BOOL WINAPI (*TGetFileSecurity) (LPCTSTR lpFileName, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength, LPDWORD lpnLengthNeeded); typedef BOOL WINAPI (*TInitializeSecurityDescriptor) (PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision); typedef BOOL WINAPI (*TGetSecurityDescriptorDacl) (PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbDaclPresent, PACL * pDacl, LPBOOL lpbDaclDefaulted); typedef BOOL WINAPI (*TGetAclInformation) (PACL pAcl, LPVOID pAclInformation, DWORD nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass); typedef BOOL WINAPI (*TInitializeAcl) (PACL pAcl, DWORD nAclLength, DWORD dwAclRevision); typedef BOOL WINAPI (*TGetAce) (PACL pAcl, DWORD dwAceIndex, LPVOID * pAce); typedef BOOL WINAPI (*TEqualSid) (PSID pSid1, PSID pSid2); typedef BOOL WINAPI (*TAddAce) (PACL pAcl, DWORD dwAceRevision, DWORD dwStartingAceIndex, LPVOID pAceList, DWORD nAceListLength); typedef BOOL WINAPI (*TAddAccessAllowedAce) (PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid); typedef BOOL WINAPI (*TSetNamedSecurityInfo) (LPTSTR pObjectName, SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo, PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl); extern TGetBestInterfaceEx GNGetBestInterfaceEx; extern TNtQuerySystemInformation GNNtQuerySystemInformation; extern TGetIfEntry GNGetIfEntry; extern TGetIpAddrTable GNGetIpAddrTable; extern TGetIfTable GNGetIfTable; extern TCreateHardLink GNCreateHardLink; extern TOpenSCManager GNOpenSCManager; extern TCreateService GNCreateService; extern TCloseServiceHandle GNCloseServiceHandle; extern TDeleteService GNDeleteService; extern TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler; extern TSetServiceStatus GNSetServiceStatus; extern TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher; extern TControlService GNControlService; extern TOpenService GNOpenService; extern TGetAdaptersInfo GNGetAdaptersInfo; extern TNetUserAdd GNNetUserAdd; extern TNetUserSetInfo GNNetUserSetInfo; extern TLsaOpenPolicy GNLsaOpenPolicy; extern TLsaAddAccountRights GNLsaAddAccountRights; extern TLsaRemoveAccountRights GNLsaRemoveAccountRights; extern TLsaClose GNLsaClose; extern TLookupAccountName GNLookupAccountName; extern TGetFileSecurity GNGetFileSecurity; extern TInitializeSecurityDescriptor GNInitializeSecurityDescriptor; extern TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl; extern TGetAclInformation GNGetAclInformation; extern TInitializeAcl GNInitializeAcl; extern TGetAce GNGetAce; extern TEqualSid GNEqualSid; extern TAddAce GNAddAce; extern TAddAccessAllowedAce GNAddAccessAllowedAce; extern TSetNamedSecurityInfo GNSetNamedSecurityInfo; BOOL CreateShortcut (const char *pszSrc, const char *pszDest); BOOL DereferenceShortcut (char *pszShortcut); long QueryRegistry (HKEY hMainKey, const char *pszKey, const char *pszSubKey, char *pszBuffer, long *pdLength); int ListNICs (void (*callback) (void *, const char *, int), void *cls); BOOL AddPathAccessRights (char *lpszFileName, char *lpszAccountName, DWORD dwAccessMask); char *winErrorStr (const char *prefix, int dwErr); void EnumNICs (PMIB_IFTABLE * pIfTable, PMIB_IPADDRTABLE * pAddrTable); #define ENUMNICS3_MASK_OK 0x01 #define ENUMNICS3_BCAST_OK 0x02 struct EnumNICs3_results { unsigned char flags; int is_default; char pretty_name[1001]; size_t addr_size; SOCKADDR_STORAGE address; SOCKADDR_STORAGE mask; SOCKADDR_STORAGE broadcast; }; int EnumNICs3 (struct EnumNICs3_results **, int *EnumNICs3_results_count); void EnumNICs3_free (struct EnumNICs3_results *); int GNInitWinEnv (); void GNShutdownWinEnv (); BOOL SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout); #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_dv_service.h0000644000175000017500000001114412252673741016120 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file include/gnunet_dv_service.h * @brief DV service API (should only be used by the DV plugin) */ #ifndef GNUNET_SERVICE_DV_H #define GNUNET_SERVICE_DV_H #include "gnunet_util_lib.h" #include "gnunet_ats_service.h" /** * Signature of a function to be called if DV * starts to be able to talk to a peer. * * @param cls closure * @param peer newly connected peer * @param distance distance to the peer * @param network the peer is located in */ typedef void (*GNUNET_DV_ConnectCallback)(void *cls, const struct GNUNET_PeerIdentity *peer, uint32_t distance, enum GNUNET_ATS_Network_Type network); /** * Signature of a function to be called if DV * distance to a peer is changed. * * @param cls closure * @param peer connected peer * @param distance new distance to the peer * @param network this network will be used to reach the next hop */ typedef void (*GNUNET_DV_DistanceChangedCallback)(void *cls, const struct GNUNET_PeerIdentity *peer, uint32_t distance, enum GNUNET_ATS_Network_Type network); /** * Signature of a function to be called if DV * is no longer able to talk to a peer. * * @param cls closure * @param peer peer that disconnected */ typedef void (*GNUNET_DV_DisconnectCallback)(void *cls, const struct GNUNET_PeerIdentity *peer); /** * Signature of a function to be called if DV * receives a message for this peer. * * @param cls closure * @param sender sender of the message * @param distance how far did the message travel * @param msg actual message payload */ typedef void (*GNUNET_DV_MessageReceivedCallback)(void *cls, const struct GNUNET_PeerIdentity *sender, uint32_t distance, const struct GNUNET_MessageHeader *msg); /** * Signature of a function called once the delivery of a * message has been successful. * * @param cls closure * @param ok GNUNET_OK on success, GNUNET_SYSERR on error */ typedef void (*GNUNET_DV_MessageSentCallback)(void *cls, int ok); /** * Handle to the DV service. */ struct GNUNET_DV_ServiceHandle; /** * Connect to the DV service. * * @param cfg configuration * @param cls closure for callbacks * @param connect_cb function to call on connects * @param distance_cb function to call if distances change * @param disconnect_cb function to call on disconnects * @param message_cb function to call if we receive messages * @return handle to access the service */ struct GNUNET_DV_ServiceHandle * GNUNET_DV_service_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_DV_ConnectCallback connect_cb, GNUNET_DV_DistanceChangedCallback distance_cb, GNUNET_DV_DisconnectCallback disconnect_cb, GNUNET_DV_MessageReceivedCallback message_cb); /** * Disconnect from DV service. * * @param sh service handle */ void GNUNET_DV_service_disconnect (struct GNUNET_DV_ServiceHandle *sh); /** * Handle for a send operation. */ struct GNUNET_DV_TransmitHandle; /** * Send a message via DV service. * * @param sh service handle * @param target intended recpient * @param msg message payload * @param cb function to invoke when done * @param cb_cls closure for 'cb' * @return handle to cancel the operation */ struct GNUNET_DV_TransmitHandle * GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh, const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, GNUNET_DV_MessageSentCallback cb, void *cb_cls); /** * Abort send operation (naturally, the message may have * already been transmitted; this only stops the 'cb' * from being called again). * * @param th send operation to cancel */ void GNUNET_DV_send_cancel (struct GNUNET_DV_TransmitHandle *th); #endif gnunet-0.10.1/src/include/gnunet_tun_lib.h0000644000175000017500000004662212255060370015423 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_tun_lib.h * @brief standard TCP/IP network structs and IP checksum calculations for TUN interaction * @author Philipp Toelke * @author Christian Grothoff */ #ifndef GNUNET_TUN_LIB_H #define GNUNET_TUN_LIB_H #include "gnunet_util_lib.h" /* see http://www.iana.org/assignments/ethernet-numbers */ #ifndef ETH_P_IPV4 /** * Number for IPv4 */ #define ETH_P_IPV4 0x0800 #endif #ifndef ETH_P_IPV6 /** * Number for IPv6 */ #define ETH_P_IPV6 0x86DD #endif /** * Maximum regex string length for use with #GNUNET_TUN_ipv4toregexsearch. * * 8 bytes for IPv4, 4 bytes for port, 1 byte for "4", 2 bytes for "-", * one byte for 0-termination. */ #define GNUNET_TUN_IPV4_REGEXLEN 16 /** * Maximum regex string length for use with #GNUNET_TUN_ipv6toregexsearch * * 32 bytes for IPv4, 4 bytes for port, 1 byte for "4", 2 bytes for "-", * one byte for 0-termination. */ #define GNUNET_TUN_IPV6_REGEXLEN 40 GNUNET_NETWORK_STRUCT_BEGIN /** * Header from Linux TUN interface. */ struct GNUNET_TUN_Layer2PacketHeader { /** * Some flags (unused). */ uint16_t flags GNUNET_PACKED; /** * Here we get an ETH_P_-number. */ uint16_t proto GNUNET_PACKED; }; /** * Standard IPv4 header. */ struct GNUNET_TUN_IPv4Header { #if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int header_length:4 GNUNET_PACKED; unsigned int version:4 GNUNET_PACKED; #elif __BYTE_ORDER == __BIG_ENDIAN unsigned int version:4 GNUNET_PACKED; unsigned int header_length:4 GNUNET_PACKED; #else #error byteorder undefined #endif uint8_t diff_serv; /** * Length of the packet, including this header. */ uint16_t total_length GNUNET_PACKED; /** * Unique random ID for matching up fragments. */ uint16_t identification GNUNET_PACKED; unsigned int flags:3 GNUNET_PACKED; unsigned int fragmentation_offset:13 GNUNET_PACKED; /** * How many more hops can this packet be forwarded? */ uint8_t ttl; /** * L4-protocol, for example, IPPROTO_UDP or IPPROTO_TCP. */ uint8_t protocol; /** * Checksum. */ uint16_t checksum GNUNET_PACKED; /** * Origin of the packet. */ struct in_addr source_address GNUNET_PACKED; /** * Destination of the packet. */ struct in_addr destination_address GNUNET_PACKED; } GNUNET_GCC_STRUCT_LAYOUT; /** * Standard IPv6 header. */ struct GNUNET_TUN_IPv6Header { #if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int traffic_class_h:4 GNUNET_PACKED; unsigned int version:4 GNUNET_PACKED; unsigned int traffic_class_l:4 GNUNET_PACKED; unsigned int flow_label:20 GNUNET_PACKED; #elif __BYTE_ORDER == __BIG_ENDIAN unsigned int version:4 GNUNET_PACKED; unsigned int traffic_class:8 GNUNET_PACKED; unsigned int flow_label:20 GNUNET_PACKED; #else #error byteorder undefined #endif /** * Length of the payload, excluding this header. */ uint16_t payload_length GNUNET_PACKED; /** * For example, IPPROTO_UDP or IPPROTO_TCP. */ uint8_t next_header; /** * How many more hops can this packet be forwarded? */ uint8_t hop_limit; /** * Origin of the packet. */ struct in6_addr source_address GNUNET_PACKED; /** * Destination of the packet. */ struct in6_addr destination_address GNUNET_PACKED; } GNUNET_GCC_STRUCT_LAYOUT; /** * TCP packet header. */ struct GNUNET_TUN_TcpHeader { /** * Source port (in NBO). */ uint16_t source_port GNUNET_PACKED; /** * Destination port (in NBO). */ uint16_t destination_port GNUNET_PACKED; /** * Sequence number. */ uint32_t seq GNUNET_PACKED; /** * Acknowledgement number. */ uint32_t ack GNUNET_PACKED; #if __BYTE_ORDER == __LITTLE_ENDIAN /** * Reserved. Must be zero. */ unsigned int reserved : 4 GNUNET_PACKED; /** * Number of 32-bit words in TCP header. */ unsigned int off : 4 GNUNET_PACKED; #elif __BYTE_ORDER == __BIG_ENDIAN /** * Number of 32-bit words in TCP header. */ unsigned int off : 4 GNUNET_PACKED; /** * Reserved. Must be zero. */ unsigned int reserved : 4 GNUNET_PACKED; #else #error byteorder undefined #endif /** * Flags (SYN, FIN, ACK, etc.) */ uint8_t flags; /** * Window size. */ uint16_t window_size GNUNET_PACKED; /** * Checksum. */ uint16_t crc GNUNET_PACKED; /** * Urgent pointer. */ uint16_t urgent_pointer GNUNET_PACKED; } GNUNET_GCC_STRUCT_LAYOUT; /** * UDP packet header. */ struct GNUNET_TUN_UdpHeader { /** * Source port (in NBO). */ uint16_t source_port GNUNET_PACKED; /** * Destination port (in NBO). */ uint16_t destination_port GNUNET_PACKED; /** * Number of bytes of payload. */ uint16_t len GNUNET_PACKED; /** * Checksum. */ uint16_t crc GNUNET_PACKED; }; /** * A few common DNS classes (ok, only one is common, but I list a * couple more to make it clear what we're talking about here). */ #define GNUNET_TUN_DNS_CLASS_INTERNET 1 #define GNUNET_TUN_DNS_CLASS_CHAOS 3 #define GNUNET_TUN_DNS_CLASS_HESIOD 4 #define GNUNET_TUN_DNS_OPCODE_QUERY 0 #define GNUNET_TUN_DNS_OPCODE_INVERSE_QUERY 1 #define GNUNET_TUN_DNS_OPCODE_STATUS 2 /** * RFC 1035 codes. */ #define GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR 0 #define GNUNET_TUN_DNS_RETURN_CODE_FORMAT_ERROR 1 #define GNUNET_TUN_DNS_RETURN_CODE_SERVER_FAILURE 2 #define GNUNET_TUN_DNS_RETURN_CODE_NAME_ERROR 3 #define GNUNET_TUN_DNS_RETURN_CODE_NOT_IMPLEMENTED 4 #define GNUNET_TUN_DNS_RETURN_CODE_REFUSED 5 /** * RFC 2136 codes */ #define GNUNET_TUN_DNS_RETURN_CODE_YXDOMAIN 6 #define GNUNET_TUN_DNS_RETURN_CODE_YXRRSET 7 #define GNUNET_TUN_DNS_RETURN_CODE_NXRRSET 8 #define GNUNET_TUN_DNS_RETURN_CODE_NOT_AUTH 9 #define GNUNET_TUN_DNS_RETURN_CODE_NOT_ZONE 10 /** * DNS flags (largely RFC 1035 / RFC 2136). */ struct GNUNET_TUN_DnsFlags { #if __BYTE_ORDER == __LITTLE_ENDIAN /** * Set to 1 if recursion is desired (client -> server) */ unsigned int recursion_desired : 1 GNUNET_PACKED; /** * Set to 1 if message is truncated */ unsigned int message_truncated : 1 GNUNET_PACKED; /** * Set to 1 if this is an authoritative answer */ unsigned int authoritative_answer : 1 GNUNET_PACKED; /** * See GNUNET_TUN_DNS_OPCODE_ defines. */ unsigned int opcode : 4 GNUNET_PACKED; /** * query:0, response:1 */ unsigned int query_or_response : 1 GNUNET_PACKED; /** * See GNUNET_TUN_DNS_RETURN_CODE_ defines. */ unsigned int return_code : 4 GNUNET_PACKED; /** * See RFC 4035. */ unsigned int checking_disabled : 1 GNUNET_PACKED; /** * Response has been cryptographically verified, RFC 4035. */ unsigned int authenticated_data : 1 GNUNET_PACKED; /** * Always zero. */ unsigned int zero : 1 GNUNET_PACKED; /** * Set to 1 if recursion is available (server -> client) */ unsigned int recursion_available : 1 GNUNET_PACKED; #elif __BYTE_ORDER == __BIG_ENDIAN /** * query:0, response:1 */ unsigned int query_or_response : 1 GNUNET_PACKED; /** * See GNUNET_TUN_DNS_OPCODE_ defines. */ unsigned int opcode : 4 GNUNET_PACKED; /** * Set to 1 if this is an authoritative answer */ unsigned int authoritative_answer : 1 GNUNET_PACKED; /** * Set to 1 if message is truncated */ unsigned int message_truncated : 1 GNUNET_PACKED; /** * Set to 1 if recursion is desired (client -> server) */ unsigned int recursion_desired : 1 GNUNET_PACKED; /** * Set to 1 if recursion is available (server -> client) */ unsigned int recursion_available : 1 GNUNET_PACKED; /** * Always zero. */ unsigned int zero : 1 GNUNET_PACKED; /** * Response has been cryptographically verified, RFC 4035. */ unsigned int authenticated_data : 1 GNUNET_PACKED; /** * See RFC 4035. */ unsigned int checking_disabled : 1 GNUNET_PACKED; /** * See GNUNET_TUN_DNS_RETURN_CODE_ defines. */ unsigned int return_code : 4 GNUNET_PACKED; #else #error byteorder undefined #endif } GNUNET_GCC_STRUCT_LAYOUT; /** * DNS header. */ struct GNUNET_TUN_DnsHeader { /** * Unique identifier for the request/response. */ uint16_t id GNUNET_PACKED; /** * Flags. */ struct GNUNET_TUN_DnsFlags flags; /** * Number of queries. */ uint16_t query_count GNUNET_PACKED; /** * Number of answers. */ uint16_t answer_rcount GNUNET_PACKED; /** * Number of authoritative answers. */ uint16_t authority_rcount GNUNET_PACKED; /** * Number of additional records. */ uint16_t additional_rcount GNUNET_PACKED; }; /** * Payload of DNS SOA record (header). */ struct GNUNET_TUN_DnsSoaRecord { /** * The version number of the original copy of the zone. (NBO) */ uint32_t serial GNUNET_PACKED; /** * Time interval before the zone should be refreshed. (NBO) */ uint32_t refresh GNUNET_PACKED; /** * Time interval that should elapse before a failed refresh should * be retried. (NBO) */ uint32_t retry GNUNET_PACKED; /** * Time value that specifies the upper limit on the time interval * that can elapse before the zone is no longer authoritative. (NBO) */ uint32_t expire GNUNET_PACKED; /** * The bit minimum TTL field that should be exported with any RR * from this zone. (NBO) */ uint32_t minimum GNUNET_PACKED; }; /** * Payload of DNS SRV record (header). */ struct GNUNET_TUN_DnsSrvRecord { /** * Preference for this entry (lower value is higher preference). Clients * will contact hosts from the lowest-priority group first and fall back * to higher priorities if the low-priority entries are unavailable. (NBO) */ uint16_t prio GNUNET_PACKED; /** * Relative weight for records with the same priority. Clients will use * the hosts of the same (lowest) priority with a probability proportional * to the weight given. (NBO) */ uint16_t weight GNUNET_PACKED; /** * TCP or UDP port of the service. (NBO) */ uint16_t port GNUNET_PACKED; /* followed by 'target' name */ }; /** * Payload of DNS CERT record. */ struct GNUNET_TUN_DnsCertRecord { /** * Certificate type */ uint16_t cert_type; /** * Certificate KeyTag */ uint16_t cert_tag; /** * Algorithm */ uint8_t algorithm; /* Followed by the certificate */ }; /** * Payload of DNSSEC TLSA record. * http://datatracker.ietf.org/doc/draft-ietf-dane-protocol/ */ struct GNUNET_TUN_DnsTlsaRecord { /** * Certificate usage * 0: CA cert * 1: Entity cert * 2: Trust anchor * 3: domain-issued cert */ uint8_t usage; /** * Selector * What part will be matched against the cert * presented by server * 0: Full cert (in binary) * 1: Full cert (in DER) */ uint8_t selector; /** * Matching type (of selected content) * 0: exact match * 1: SHA-256 hash * 2: SHA-512 hash */ uint8_t matching_type; /** * followed by certificate association data * The "certificate association data" to be matched. * These bytes are either raw data (that is, the full certificate or * its SubjectPublicKeyInfo, depending on the selector) for matching * type 0, or the hash of the raw data for matching types 1 and 2. * The data refers to the certificate in the association, not to the * TLS ASN.1 Certificate object. * * The data is represented as a string of hex chars */ }; /** * Payload of GNS VPN record */ struct GNUNET_TUN_GnsVpnRecord { /** * The peer to contact */ struct GNUNET_PeerIdentity peer; /** * The protocol to use */ uint16_t proto; /* followed by the servicename */ }; /** * DNS query prefix. */ struct GNUNET_TUN_DnsQueryLine { /** * Desired type (GNUNET_DNSPARSER_TYPE_XXX). (NBO) */ uint16_t type GNUNET_PACKED; /** * Desired class (usually GNUNET_TUN_DNS_CLASS_INTERNET). (NBO) */ uint16_t dns_traffic_class GNUNET_PACKED; }; /** * General DNS record prefix. */ struct GNUNET_TUN_DnsRecordLine { /** * Record type (GNUNET_DNSPARSER_TYPE_XXX). (NBO) */ uint16_t type GNUNET_PACKED; /** * Record class (usually GNUNET_TUN_DNS_CLASS_INTERNET). (NBO) */ uint16_t dns_traffic_class GNUNET_PACKED; /** * Expiration for the record (in seconds). (NBO) */ uint32_t ttl GNUNET_PACKED; /** * Number of bytes of data that follow. (NBO) */ uint16_t data_len GNUNET_PACKED; }; #define GNUNET_TUN_ICMPTYPE_ECHO_REPLY 0 #define GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE 3 #define GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH 4 #define GNUNET_TUN_ICMPTYPE_REDIRECT_MESSAGE 5 #define GNUNET_TUN_ICMPTYPE_ECHO_REQUEST 8 #define GNUNET_TUN_ICMPTYPE_ROUTER_ADVERTISEMENT 9 #define GNUNET_TUN_ICMPTYPE_ROUTER_SOLICITATION 10 #define GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED 11 #define GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE 1 #define GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG 2 #define GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED 3 #define GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM 4 #define GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST 128 #define GNUNET_TUN_ICMPTYPE6_ECHO_REPLY 129 /** * ICMP header. */ struct GNUNET_TUN_IcmpHeader { uint8_t type; uint8_t code; uint16_t crc GNUNET_PACKED; union { /** * ICMP Echo (request/reply) */ struct { uint16_t identifier GNUNET_PACKED; uint16_t sequence_number GNUNET_PACKED; } echo; /** * ICMP Destination Unreachable (RFC 1191) */ struct ih_pmtu { uint16_t empty GNUNET_PACKED; uint16_t next_hop_mtu GNUNET_PACKED; /* followed by original IP header + first 8 bytes of original IP datagram */ } destination_unreachable; /** * ICMP Redirect */ struct in_addr redirect_gateway_address GNUNET_PACKED; /** * MTU for packets that are too big (IPv6). */ uint32_t packet_too_big_mtu GNUNET_PACKED; } quench; }; GNUNET_NETWORK_STRUCT_END /** * Initialize an IPv4 header. * * @param ip header to initialize * @param protocol protocol to use (i.e. IPPROTO_UDP) * @param payload_length number of bytes of payload that follow (excluding IPv4 header) * @param src source IP address to use * @param dst destination IP address to use */ void GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst); /** * Initialize an IPv6 header. * * @param ip header to initialize * @param protocol protocol to use (i.e. IPPROTO_UDP) * @param payload_length number of bytes of payload that follow (excluding IPv4 header) * @param src source IP address to use * @param dst destination IP address to use */ void GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst); /** * Calculate IPv4 TCP checksum. * * @param ip ipv4 header fully initialized * @param tcp TCP header (initialized except for CRC) * @param payload the TCP payload * @param payload_length number of bytes of TCP @a payload */ void GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length); /** * Calculate IPv6 TCP checksum. * * @param ip ipv6 header fully initialized * @param tcp TCP header (initialized except for CRC) * @param payload the TCP payload * @param payload_length number of bytes of TCP payload */ void GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length); /** * Calculate IPv4 UDP checksum. * * @param ip ipv4 header fully initialized * @param udp UDP header (initialized except for CRC) * @param payload the UDP payload * @param payload_length number of bytes of UDP @a payload */ void GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length); /** * Calculate IPv6 UDP checksum. * * @param ip ipv6 header fully initialized * @param udp UDP header (initialized except for CRC) * @param payload the UDP payload * @param payload_length number of bytes of @a payload */ void GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length); /** * Calculate ICMP checksum. * * @param icmp IMCP header (initialized except for CRC) * @param payload the ICMP payload * @param payload_length number of bytes of @a payload */ void GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp, const void *payload, uint16_t payload_length); /** * Create a regex in @a rxstr from the given @a ip and @a port. * * @param ip IPv4 representation. * @param port destination port * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN * bytes long. */ void GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip, uint16_t port, char *rxstr); /** * Create a regex in @a rxstr from the given @a ipv6 and @a port. * * @param ipv6 IPv6 representation. * @param port destination port * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN * bytes long. */ void GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6, uint16_t port, char *rxstr); /** * Convert an exit policy to a regular expression. The exit policy * specifies a set of subnets this peer is willing to serve as an * exit for; the resulting regular expression will match the * IPv6 address strings as returned by #GNUNET_TUN_ipv6toregexsearch. * * @param policy exit policy specification * @return regular expression, NULL on error */ char * GNUNET_TUN_ipv6policy2regex (const char *policy); /** * Convert an exit policy to a regular expression. The exit policy * specifies a set of subnets this peer is willing to serve as an * exit for; the resulting regular expression will match the * IPv4 address strings as returned by #GNUNET_TUN_ipv4toregexsearch. * * @param policy exit policy specification * @return regular expression, NULL on error */ char * GNUNET_TUN_ipv4policy2regex (const char *policy); /** * Hash the service name of a hosted service to the * hash code that is used to identify the service on * the network. * * @param service_name a string * @param hc corresponding hash */ void GNUNET_TUN_service_name_to_hash (const char *service_name, struct GNUNET_HashCode *hc); #endif gnunet-0.10.1/src/include/gnunet_datacache_plugin.h0000644000175000017500000001012712225777503017243 00000000000000/* This file is part of GNUnet (C) 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_datacache_plugin.h * @brief API for database backends for the datacache * @author Christian Grothoff */ #ifndef PLUGIN_DATACACHE_H #define PLUGIN_DATACACHE_H #include "gnunet_datacache_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Function called by plugins to notify the datacache * about content deletions. * * @param cls closure * @param key key of the content that was deleted * @param size number of bytes that were made available */ typedef void (*GNUNET_DATACACHE_DeleteNotifyCallback) (void *cls, const struct GNUNET_HashCode * key, size_t size); /** * The datastore service will pass a pointer to a struct * of this type as the first and only argument to the * entry point of each datastore plugin. */ struct GNUNET_DATACACHE_PluginEnvironment { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Configuration section to use. */ const char *section; /** * Closure to use for callbacks. */ void *cls; /** * Function to call whenever the plugin needs to * discard content that it was asked to store. */ GNUNET_DATACACHE_DeleteNotifyCallback delete_notify; /** * How much space are we allowed to use? */ unsigned long long quota; }; /** * @brief struct returned by the initialization function of the plugin */ struct GNUNET_DATACACHE_PluginFunctions { /** * Closure to pass to all plugin functions. */ void *cls; /** * Store an item in the datastore. * * @param cls closure (internal context for the plugin) * @param size number of bytes in data * @param data data to store * @param type type of the value * @param discard_time when to discard the value in any case * @param path_info_len number of entries in 'path_info' * @param path_info a path through the network * @return 0 if duplicate, -1 on error, number of bytes used otherwise */ ssize_t (*put) (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute discard_time, unsigned int path_info_len, const struct GNUNET_PeerIdentity *path_info); /** * Iterate over the results for a particular key * in the datastore. * * @param cls closure (internal context for the plugin) * @param key * @param type entries of which type are relevant? * @param iter maybe NULL (to just count) * @param iter_cls closure for iter * @return the number of results found */ unsigned int (*get) (void *cls, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, GNUNET_DATACACHE_Iterator iter, void *iter_cls); /** * Delete the entry with the lowest expiration value * from the datacache right now. * * @param cls closure (internal context for the plugin) * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int (*del) (void *cls); }; #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_datacache_plugin.h */ #endif gnunet-0.10.1/src/include/gnunet_strings_lib.h0000644000175000017500000004311212261236531016276 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_strings_lib.h * @brief strings and string handling functions (including malloc * and string tokenizing) * * @author Christian Grothoff * @author Krista Bennett * @author Gerd Knorr * @author Ioana Patrascu * @author Tzvetan Horozov */ #ifndef GNUNET_STRINGS_LIB_H #define GNUNET_STRINGS_LIB_H /* we need size_t, and since it can be both unsigned int or unsigned long long, this IS platform dependent; but "stdlib.h" should be portable 'enough' to be unconditionally available... */ #include #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_time_lib.h" /** * Convert a given fancy human-readable size to bytes. * * @param fancy_size human readable string (i.e. 1 MB) * @param size set to the size in bytes * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size, unsigned long long *size); /** * Convert a given fancy human-readable time to our internal * representation. * * @param fancy_time human readable string (i.e. 1 minute) * @param rtime set to the relative time * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time, struct GNUNET_TIME_Relative *rtime); /** * @ingroup time * Convert a given fancy human-readable time to our internal * representation. The human-readable time is expected to be * in local time, whereas the returned value will be in UTC. * * @param fancy_time human readable string (i.e. %Y-%m-%d %H:%M:%S) * @param atime set to the absolute time * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time, struct GNUNET_TIME_Absolute *atime); /** * Convert a given filesize into a fancy human-readable format. * * @param size number of bytes * @return fancy representation of the size (possibly rounded) for humans */ char * GNUNET_STRINGS_byte_size_fancy (unsigned long long size); /** * Convert the len characters long character sequence * given in input that is in the given input charset * to a string in given output charset. * * @param input input string * @param len number of bytes in @a input * @param input_charset character set used for @a input * @param output_charset desired character set for the return value * @return the converted string (0-terminated), * if conversion fails, a copy of the orignal * string is returned. */ char * GNUNET_STRINGS_conv (const char *input, size_t len, const char *input_charset, const char *output_charset); /** * Convert the len characters long character sequence * given in input that is in the given charset * to UTF-8. * * @param input the input string (not necessarily 0-terminated) * @param len the number of bytes in the @a input * @param charset character set to convert from * @return the converted string (0-terminated) */ char * GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset); /** * Convert the len bytes-long UTF-8 string * given in input to the given charset. * * @param input the input string (not necessarily 0-terminated) * @param len the number of bytes in the @a input * @param charset character set to convert to * @return the converted string (0-terminated), * if conversion fails, a copy of the orignal * string is returned. */ char * GNUNET_STRINGS_from_utf8 (const char *input, size_t len, const char *charset); /** * Convert the utf-8 input string to lower case. * Output needs to be allocated appropriately. * * @param input input string * @param output output buffer */ void GNUNET_STRINGS_utf8_tolower (const char *input, char *output); /** * Convert the utf-8 input string to upper case. * Output needs to be allocated appropriately. * * @param input input string * @param output output buffer */ void GNUNET_STRINGS_utf8_toupper (const char *input, char *output); /** * Complete filename (a la shell) from abbrevition. * * @param fil the name of the file, may contain ~/ or * be relative to the current directory * @return the full file name, * NULL is returned on error */ char * GNUNET_STRINGS_filename_expand (const char *fil); /** * Fill a buffer of the given size with count 0-terminated strings * (given as varargs). If "buffer" is NULL, only compute the amount * of space required (sum of "strlen(arg)+1"). * * Unlike using "snprintf" with "%s", this function will add * 0-terminators after each string. The * "GNUNET_string_buffer_tokenize" function can be used to parse the * buffer back into individual strings. * * @param buffer the buffer to fill with strings, can * be NULL in which case only the necessary * amount of space will be calculated * @param size number of bytes available in buffer * @param count number of strings that follow * @param ... count 0-terminated strings to copy to buffer * @return number of bytes written to the buffer * (or number of bytes that would have been written) */ size_t GNUNET_STRINGS_buffer_fill (char *buffer, size_t size, unsigned int count, ...); /** * Given a buffer of a given size, find "count" 0-terminated strings * in the buffer and assign the count (varargs) of type "const char**" * to the locations of the respective strings in the buffer. * * @param buffer the buffer to parse * @param size size of the @a buffer * @param count number of strings to locate * @param ... pointers to where to store the strings * @return offset of the character after the last 0-termination * in the buffer, or 0 on error. */ unsigned int GNUNET_STRINGS_buffer_tokenize (const char *buffer, size_t size, unsigned int count, ...); /** * @ingroup time * Like `asctime`, except for GNUnet time. Converts a GNUnet internal * absolute time (which is in UTC) to a string in local time. * Note that the returned value will be overwritten if this function * is called again. * * @param t the absolute time to convert * @return timestamp in human-readable form in local time */ const char * GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t); /** * @ingroup time * Give relative time in human-readable fancy format. * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param delta time in milli seconds * @param do_round are we allowed to round a bit? * @return string in human-readable form */ const char * GNUNET_STRINGS_relative_time_to_string (struct GNUNET_TIME_Relative delta, int do_round); /** * "man basename" * Returns a pointer to a part of filename (allocates nothing)! * * @param filename filename to extract basename from * @return short (base) name of the file (that is, everything following the * last directory separator in filename. If filename ends with a * directory separator, the result will be a zero-length string. * If filename has no directory separators, the result is filename * itself. */ const char * GNUNET_STRINGS_get_short_name (const char *filename); /** * Convert binary data to ASCII encoding. The ASCII encoding is rather * GNUnet specific. It was chosen such that it only uses characters * in [0-9A-V], can be produced without complex arithmetics and uses a * small number of characters. The GNUnet encoding uses 103 characters. * Does not append 0-terminator, but returns a pointer to the place where * it should be placed, if needed. * * @param data data to encode * @param size size of data (in bytes) * @param out buffer to fill * @param out_size size of the buffer. Must be large enough to hold * ((size*8) + (((size*8) % 5) > 0 ? 5 - ((size*8) % 5) : 0)) / 5 * @return pointer to the next byte in 'out' or NULL on error. */ char * GNUNET_STRINGS_data_to_string (const void *data, size_t size, char *out, size_t out_size); /** * Convert ASCII encoding back to data * out_size must match exactly the size of the data before it was encoded. * * @param enc the encoding * @param enclen number of characters in 'enc' (without 0-terminator, which can be missing) * @param out location where to store the decoded data * @param out_size size of the output buffer @a out * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding */ int GNUNET_STRINGS_string_to_data (const char *enc, size_t enclen, void *out, size_t out_size); /** * Encode into Base64. * * @param data the data to encode * @param len the length of the input * @param output where to write the output (*output should be NULL, * is allocated) * @return the size of the output */ size_t GNUNET_STRINGS_base64_encode (const char *data, size_t len, char **output); /** * Decode from Base64. * * @param data the data to encode * @param len the length of the input * @param output where to write the output (*output should be NULL, * is allocated) * @return the size of the output */ size_t GNUNET_STRINGS_base64_decode (const char *data, size_t len, char **output); /** * Parse a path that might be an URI. * * @param path path to parse. Must be NULL-terminated. * @param scheme_part a pointer to 'char *' where a pointer to a string that * represents the URI scheme will be stored. Can be NULL. The string is * allocated by the function, and should be freed by GNUNET_free() when * it is no longer needed. * @param path_part a pointer to 'const char *' where a pointer to the path * part of the URI will be stored. Can be NULL. Points to the same block * of memory as 'path', and thus must not be freed. Might point to '\0', * if path part is zero-length. * @return #GNUNET_YES if it's an URI, #GNUNET_NO otherwise. If 'path' is not * an URI, '* scheme_part' and '*path_part' will remain unchanged * (if they weren't NULL). */ int GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part, const char **path_part); /** * Check whether filename is absolute or not, and if it's an URI * * @param filename filename to check * @param can_be_uri #GNUNET_YES to check for being URI, #GNUNET_NO - to * assume it's not URI * @param r_is_uri a pointer to an int that is set to #GNUNET_YES if 'filename' * is URI and to GNUNET_NO otherwise. Can be NULL. If 'can_be_uri' is * not #GNUNET_YES, *r_is_uri is set to #GNUNET_NO. * @param r_uri_scheme a pointer to a char * that is set to a pointer to URI scheme. * The string is allocated by the function, and should be freed with * GNUNET_free (). Can be NULL. * @return #GNUNET_YES if 'filename' is absolute, #GNUNET_NO otherwise. */ int GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri, int *r_is_uri, char **r_uri_scheme); /** * Flags for what we should check a file for. */ enum GNUNET_STRINGS_FilenameCheck { /** * Check that it exists. */ GNUNET_STRINGS_CHECK_EXISTS = 0x00000001, /** * Check that it is a directory. */ GNUNET_STRINGS_CHECK_IS_DIRECTORY = 0x00000002, /** * Check that it is a link. */ GNUNET_STRINGS_CHECK_IS_LINK = 0x00000004, /** * Check that the path is an absolute path. */ GNUNET_STRINGS_CHECK_IS_ABSOLUTE = 0x00000008 }; /** * Perform checks on @a filename. FIXME: some duplication with * "GNUNET_DISK_"-APIs. We should unify those. * * @param filename file to check * @param checks checks to perform * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them * fails, #GNUNET_SYSERR when a check can't be performed */ int GNUNET_STRINGS_check_filename (const char *filename, enum GNUNET_STRINGS_FilenameCheck checks); /** * Tries to convert @a zt_addr string to an IPv6 address. * The string is expected to have the format "[ABCD::01]:80". * * @param zt_addr 0-terminated string. May be mangled by the function. * @param addrlen length of zt_addr (not counting 0-terminator). * @param r_buf a buffer to fill. Initially gets filled with zeroes, * then its sin6_port, sin6_family and sin6_addr are set appropriately. * @return #GNUNET_OK if conversion succeded. #GNUNET_SYSERR otherwise, in which * case the contents of r_buf are undefined. */ int GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, uint16_t addrlen, struct sockaddr_in6 *r_buf); /** * Tries to convert @a zt_addr string to an IPv4 address. * The string is expected to have the format "1.2.3.4:80". * * @param zt_addr 0-terminated string. May be mangled by the function. * @param addrlen length of zt_addr (not counting 0-terminator). * @param r_buf a buffer to fill. * @return #GNUNET_OK if conversion succeded. #GNUNET_SYSERR otherwise, in which case * the contents of r_buf are undefined. */ int GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen, struct sockaddr_in *r_buf); /** * Tries to convert @a addr string to an IP (v4 or v6) address. * Will automatically decide whether to treat 'addr' as v4 or v6 address. * * @param addr a string, may not be 0-terminated. * @param addrlen number of bytes in @a addr (if addr is 0-terminated, * 0-terminator should not be counted towards addrlen). * @param r_buf a buffer to fill. * @return #GNUNET_OK if conversion succeded. #GNUNET_SYSERR otherwise, in which * case the contents of r_buf are undefined. */ int GNUNET_STRINGS_to_address_ip (const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf); /** * Returns utf-8 encoded arguments. Does nothing (returns a copy of * @a argc and @a argv) on any platform other than W32. Returned @a * argv has `u8argv[u8argc] == NULL`. Returned @a argv is a single * memory block, and can be freed with a single GNUNET_free() call. * * @param argc argc (as given by main()) * @param argv argv (as given by main()) * @param u8argc a location to store new argc in (though it's th same as argc) * @param u8argv a location to store new argv in * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv); /* ***************** IPv4/IPv6 parsing ****************** */ struct GNUNET_STRINGS_PortPolicy { /** * Starting port range (0 if none given). */ uint16_t start_port; /** * End of port range (0 if none given). */ uint16_t end_port; /** * #GNUNET_YES if the port range should be negated * ("!" in policy). */ int negate_portrange; }; /** * @brief IPV4 network in CIDR notation. */ struct GNUNET_STRINGS_IPv4NetworkPolicy { /** * IPv4 address. */ struct in_addr network; /** * IPv4 netmask. */ struct in_addr netmask; /** * Policy for port access. */ struct GNUNET_STRINGS_PortPolicy pp; }; /** * @brief network in CIDR notation for IPV6. */ struct GNUNET_STRINGS_IPv6NetworkPolicy { /** * IPv6 address. */ struct in6_addr network; /** * IPv6 netmask. */ struct in6_addr netmask; /** * Policy for port access. */ struct GNUNET_STRINGS_PortPolicy pp; }; /** * Parse an IPv4 network policy. The argument specifies a list of * subnets. The format is (network[/netmask][:[!]SPORT-DPORT];)* * (no whitespace, must be terminated with a semicolon). The network * must be given in dotted-decimal notation. The netmask can be given * in CIDR notation (/16) or in dotted-decimal (/255.255.0.0). * * @param routeListX a string specifying the IPv4 subnets * @return the converted list, terminated with all zeros; * NULL if the synatx is flawed */ struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX); /** * Parse an IPv6 network policy. The argument specifies a list of * subnets. The format is (network[/netmask[:[!]SPORT[-DPORT]]];)* * (no whitespace, must be terminated with a semicolon). The network * must be given in colon-hex notation. The netmask must be given in * CIDR notation (/16) or can be omitted to specify a single host. * Note that the netmask is mandatory if ports are specified. * * @param routeListX a string specifying the policy * @return the converted list, 0-terminated, NULL if the synatx is flawed */ struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_UTIL_STRING_H */ #endif /* end of gnunet_util_string.h */ gnunet-0.10.1/src/include/gnunet_resolver_service.h0000644000175000017500000001213512225777503017352 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_resolver_service.h * @brief functions related to doing DNS lookups * @author Christian Grothoff * @defgroup resolver asynchronous standard DNS lookups * @{ */ #ifndef GNUNET_RESOLVER_SERVICE_H #define GNUNET_RESOLVER_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_configuration_lib.h" #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" /** * Function called by the resolver for each address obtained from DNS. * * @param cls closure * @param addr one of the addresses of the host, NULL for the last address * @param addrlen length of @a addr */ typedef void (*GNUNET_RESOLVER_AddressCallback) (void *cls, const struct sockaddr *addr, socklen_t addrlen); /** * Handle to a request given to the resolver. Can be used to cancel * the request prior to the timeout or successful execution. */ struct GNUNET_RESOLVER_RequestHandle; /** * Create the connection to the resolver service. * * @param cfg configuration to use */ void GNUNET_RESOLVER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Destroy the connection to the resolver service. */ void GNUNET_RESOLVER_disconnect (void); /** * Convert a string to one or more IP addresses. * * @param hostname the hostname to resolve * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" * @param callback function to call with addresses * @param callback_cls closure for @a callback * @param timeout how long to try resolving * @return handle that can be used to cancel the request, NULL on error */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get (const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls); /** * Resolve our hostname to an IP address. * * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" * @param callback function to call with addresses * @param cls closure for @a callback * @param timeout how long to try resolving * @return handle that can be used to cancel the request, NULL on error */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_resolve (int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *cls); /** * Function called by the resolver for each hostname obtained from DNS. * * @param cls closure * @param hostname one of the names for the host, NULL * on the last call to the callback */ typedef void (*GNUNET_RESOLVER_HostnameCallback) (void *cls, const char *hostname); /** * Get local fully qualified domain name * * @return local hostname, caller must free */ char * GNUNET_RESOLVER_local_fqdn_get (void); /** * Perform a reverse DNS lookup. * * @param sa host address * @param salen length of @a sa * @param do_resolve use #GNUNET_NO to return numeric hostname * @param timeout how long to try resolving * @param callback function to call with hostnames * @param cls closure for @a callback * @return handle that can be used to cancel the request, NULL on error */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls); /** * Cancel a request that is still pending with the resolver. * Note that a client MUST NOT cancel a request that has * been completed (i.e, the callback has been called to * signal timeout or the final result). * * @param rh handle of request to cancel */ void GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group resolver */ /* ifndef GNUNET_RESOLVER_SERVICE_H */ #endif /* end of gnunet_resolver_service.h */ gnunet-0.10.1/src/include/gnunet_testing_lib.h0000644000175000017500000003705012225777503016277 00000000000000/* This file is part of GNUnet (C) 2008, 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_testing_lib.h * @brief convenience API for writing testcases for GNUnet; * can start/stop one or more peers on a system; * testing is responsible for managing private keys, * ports and paths; it is a low-level library that * does not support higher-level functions such as * P2P connection, topology management or distributed * testbed maintenance (those are in gnunet_testbed_service.h) * @author Christian Grothoff */ #ifndef GNUNET_TESTING_LIB_H #define GNUNET_TESTING_LIB_H #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_arm_service.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Size of each hostkey in the hostkey file (in BYTES). */ #define GNUNET_TESTING_HOSTKEYFILESIZE sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey) /** * The environmental variable, if set, that dictates where testing should place * generated peer configurations */ #define GNUNET_TESTING_PREFIX "GNUNET_TESTING_PREFIX" /** * Handle for a system on which GNUnet peers are executed; * a system is used for reserving unique paths and ports. */ struct GNUNET_TESTING_System; /** * Handle for a GNUnet peer controlled by testing. */ struct GNUNET_TESTING_Peer; /** * Specification of a service that is to be shared among peers */ struct GNUNET_TESTING_SharedService { /** * The name of the service. */ const char *service; /** * The configuration template for the service. Cannot be NULL */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * The number of peers which share an instance of the service. 0 for sharing * among all peers */ unsigned int share; }; /** * Create a system handle. There must only be one system handle per operating * system. Uses a default range for allowed ports. Ports are still tested for * availability. * * @param testdir only the directory name without any path. This is used for all * service homes; the directory will be created in a temporary location * depending on the underlying OS. This variable will be * overridden with the value of the environmental variable * GNUNET_TESTING_PREFIX, if it exists. * @param trusted_ip the ip address which will be set as TRUSTED HOST in all * service configurations generated to allow control connections from * this ip. This can either be a single ip address or a network address * in CIDR notation. * @param hostname the hostname of the system we are using for testing; NULL for * localhost * @param shared_services NULL terminated array describing services that are to * be shared among peers * @return handle to this system, NULL on error */ struct GNUNET_TESTING_System * GNUNET_TESTING_system_create (const char *testdir, const char *trusted_ip, const char *hostname, const struct GNUNET_TESTING_SharedService * shared_services); /** * Create a system handle. There must only be one system * handle per operating system. Use this function directly * if multiple system objects are created for the same host * (only really useful when testing --- or to make the port * range configureable). * * @param testdir only the directory name without any path. This is used for * all service homes; the directory will be created in a temporary * location depending on the underlying OS. This variable will be * overridden with the value of the environmental variable * GNUNET_TESTING_PREFIX, if it exists. * @param trusted_ip the ip address which will be set as TRUSTED HOST in all * service configurations generated to allow control connections from * this ip. This can either be a single ip address or a network address * in CIDR notation. * @param hostname the hostname of the system we are using for testing; NULL for * localhost * @param shared_services NULL terminated array describing services that are to * be shared among peers * @param lowport lowest port number this system is allowed to allocate (inclusive) * @param highport highest port number this system is allowed to allocate (exclusive) * @return handle to this system, NULL on error */ struct GNUNET_TESTING_System * GNUNET_TESTING_system_create_with_portrange (const char *testdir, const char *trusted_ip, const char *hostname, const struct GNUNET_TESTING_SharedService * shared_services, uint16_t lowport, uint16_t highport); /** * Free system resources. * * @param system system to be freed * @param remove_paths should the 'testdir' and all subdirectories * be removed (clean up on shutdown)? */ void GNUNET_TESTING_system_destroy (struct GNUNET_TESTING_System *system, int remove_paths); /** * Testing includes a number of pre-created hostkeys for * faster peer startup. This function can be used to * access the n-th key of those pre-created hostkeys; note * that these keys are ONLY useful for testing and not * secure as the private keys are part of the public * GNUnet source code. * * This is primarily a helper function used internally * by 'GNUNET_TESTING_peer_configure'. * * @param system the testing system handle * @param key_number desired pre-created hostkey to obtain * @param id set to the peer's identity (hash of the public * key; if NULL, GNUNET_SYSERR is returned immediately * @return NULL on error (not enough keys) */ struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_TESTING_hostkey_get (const struct GNUNET_TESTING_System *system, uint32_t key_number, struct GNUNET_PeerIdentity *id); /** * Reserve a port for a peer. * * @param system system to use for reservation tracking * @return 0 if no free port was available */ uint16_t GNUNET_TESTING_reserve_port (struct GNUNET_TESTING_System *system); /** * Release reservation of a TCP or UDP port for a peer * (used during GNUNET_TESTING_peer_destroy). * * @param system system to use for reservation tracking * @param port reserved port to release */ void GNUNET_TESTING_release_port (struct GNUNET_TESTING_System *system, uint16_t port); /** * Create a new configuration using the given configuration as a template; * ports and paths will be modified to select available ports on the local * system. The default configuration will be available in PATHS section under * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS * section to the temporary directory specific to this configuration. If we run * out of "*port" numbers, return SYSERR. * * This is primarily a helper function used internally * by 'GNUNET_TESTING_peer_configure'. * * @param system system to use to coordinate resource usage * @param cfg template configuration to update * @return GNUNET_OK on success, GNUNET_SYSERR on error - the configuration will * be incomplete and should not be used there upon */ int GNUNET_TESTING_configuration_create (struct GNUNET_TESTING_System *system, struct GNUNET_CONFIGURATION_Handle *cfg); // FIXME: add dual to 'release' ports again... /** * Configure a GNUnet peer. GNUnet must be installed on the local * system and available in the PATH. * * @param system system to use to coordinate resource usage * @param cfg configuration to use; will be UPDATED (to reflect needed * changes in port numbers and paths) * @param key_number number of the hostkey to use for the peer * @param id identifier for the daemon, will be set, can be NULL * @param emsg set to freshly allocated error message (set to NULL on success), * can be NULL * @return handle to the peer, NULL on error */ struct GNUNET_TESTING_Peer * GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system, struct GNUNET_CONFIGURATION_Handle *cfg, uint32_t key_number, struct GNUNET_PeerIdentity *id, char **emsg); /** * Obtain the peer identity from a peer handle. * * @param peer peer handle for which we want the peer's identity * @param id identifier for the daemon, will be set */ void GNUNET_TESTING_peer_get_identity (struct GNUNET_TESTING_Peer *peer, struct GNUNET_PeerIdentity *id); /** * Start the peer. * * @param peer peer to start * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer already running) */ int GNUNET_TESTING_peer_start (struct GNUNET_TESTING_Peer *peer); /** * Stop the peer. This call is blocking as it kills the peer's main ARM process * by sending a SIGTERM and waits on it. For asynchronous shutdown of peer, see * GNUNET_TESTING_peer_stop_async(). * * @param peer peer to stop * @return GNUNET_OK on success, GNUNET_SYSERR on error (i.e. peer not running) */ int GNUNET_TESTING_peer_stop (struct GNUNET_TESTING_Peer *peer); /** * Destroy the peer. Releases resources locked during peer configuration. * If the peer is still running, it will be stopped AND a warning will be * printed (users of the API should stop the peer explicitly first). * * @param peer peer to destroy */ void GNUNET_TESTING_peer_destroy (struct GNUNET_TESTING_Peer *peer); /** * Sends SIGTERM to the peer's main process * * @param peer the handle to the peer * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL * or upon any error while sending SIGTERM */ int GNUNET_TESTING_peer_kill (struct GNUNET_TESTING_Peer *peer); /** * Waits for a peer to terminate. The peer's main process will also be destroyed. * * @param peer the handle to the peer * @return GNUNET_OK if successful; GNUNET_SYSERR if the main process is NULL * or upon any error while waiting */ int GNUNET_TESTING_peer_wait (struct GNUNET_TESTING_Peer *peer); /** * Callback to inform whether the peer is running or stopped. * * @param cls the closure given to GNUNET_TESTING_peer_stop_async() * @param peer the respective peer whose status is being reported * @param success GNUNET_YES if the peer is stopped; GNUNET_SYSERR upon any * error */ typedef void (*GNUNET_TESTING_PeerStopCallback) (void *cls, struct GNUNET_TESTING_Peer * peer, int success); /** * Stop a peer asynchronously using ARM API. Peer's shutdown is signaled * through the GNUNET_TESTING_PeerStopCallback(). * * @param peer the peer to stop * @param cb the callback to signal peer shutdown * @param cb_cls closure for the above callback * @return GNUNET_OK upon successfully giving the request to the ARM API (this * does not mean that the peer is successfully stopped); GNUNET_SYSERR * upon any error. */ int GNUNET_TESTING_peer_stop_async (struct GNUNET_TESTING_Peer *peer, GNUNET_TESTING_PeerStopCallback cb, void *cb_cls); /** * Cancel a previous asynchronous peer stop request. * GNUNET_TESTING_peer_stop_async() should have been called before on the given * peer. It is an error to call this function if the peer stop callback was * already called * * @param peer the peer on which GNUNET_TESTING_peer_stop_async() was called * before. */ void GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer); /** * Signature of the 'main' function for a (single-peer) testcase that * is run using 'GNUNET_TESTING_peer_run'. * * @param cls closure * @param cfg configuration of the peer that was started * @param peer identity of the peer that was created */ typedef void (*GNUNET_TESTING_TestMain) (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer); /** * Start a single peer and run a test using the testing library. * Starts a peer using the given configuration and then invokes the * given callback. This function ALSO initializes the scheduler loop * and should thus be called directly from "main". The testcase * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'. * * @param testdir only the directory name without any path. This is used for * all service homes; the directory will be created in a temporary * location depending on the underlying OS * @param cfgfilename name of the configuration file to use; * use NULL to only run with defaults * @param tm main function of the testcase * @param tm_cls closure for 'tm' * @return 0 on success, 1 on error */ int GNUNET_TESTING_peer_run (const char *testdir, const char *cfgfilename, GNUNET_TESTING_TestMain tm, void *tm_cls); /** * Start a single service (no ARM, except of course if the given * service name is 'arm') and run a test using the testing library. * Starts a service using the given configuration and then invokes the * given callback. This function ALSO initializes the scheduler loop * and should thus be called directly from "main". The testcase * should self-terminate by invoking 'GNUNET_SCHEDULER_shutdown'. * * This function is useful if the testcase is for a single service * and if that service doesn't itself depend on other services. * * @param testdir only the directory name without any path. This is used for * all service homes; the directory will be created in a temporary * location depending on the underlying OS * @param service_name name of the service to run * @param cfgfilename name of the configuration file to use; * use NULL to only run with defaults * @param tm main function of the testcase * @param tm_cls closure for 'tm' * @return 0 on success, 1 on error */ int GNUNET_TESTING_service_run (const char *testdir, const char *service_name, const char *cfgfilename, GNUNET_TESTING_TestMain tm, void *tm_cls); /** * Sometimes we use the binary name to determine which specific * test to run. In those cases, the string after the last "_" * in 'argv[0]' specifies a string that determines the configuration * file or plugin to use. * * This function returns the respective substring, taking care * of issues such as binaries ending in '.exe' on W32. * * @param argv0 the name of the binary * @return string between the last '_' and the '.exe' (or the end of the string), * NULL if argv0 has no '_' */ char * GNUNET_TESTING_get_testname_from_underscore (const char *argv0); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_conversation_service.h0000644000175000017500000003102012255133650020205 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_conversation_service.h * @brief API to the conversation service * @author Simon Dieterle * @author Andreas Fuchs * @author Christian Grothoff * * * NOTE: This API is deliberately deceptively simple; the idea * is that advanced features (such as answering machines) will * be done with a separate service (an answering machine service) * with its own APIs; the speaker/microphone abstractions are * used to facilitate plugging in custom logic for implementing * such a service later by creating "software" versions of * speakers and microphones that record to disk or play a file. * Notifications about missed calls should similarly be done * using a separate service; CONVERSATION is supposed to be just * the "bare bones" voice service. * * As this is supposed to be a "secure" service, caller ID is of * course provided as part of the basic implementation, as only the * CONVERSATION service can know for sure who it is that we are * talking to. */ #ifndef GNUNET_CONVERSATION_SERVICE_H #define GNUNET_CONVERSATION_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" #include "gnunet_identity_service.h" #include "gnunet_namestore_service.h" #include "gnunet_speaker_lib.h" #include "gnunet_microphone_lib.h" /** * Version of the conversation API. */ #define GNUNET_CONVERSATION_VERSION 0x00000003 /** * Handle to identify a particular caller. A caller is an entity that * initiate a call to a phone. This struct identifies the caller to * the user operating the phone. The entity that initiated the call * will have a `struct GNUNET_CONVERSATION_Call`. */ struct GNUNET_CONVERSATION_Caller; GNUNET_NETWORK_STRUCT_BEGIN /** * A phone record specifies which peer is hosting a given user and * may also specify the phone line that is used (typically zero). * The version is also right now always zero. */ struct GNUNET_CONVERSATION_PhoneRecord { /** * Version of the phone record, for now always zero. We may * use other versions for anonymously hosted phone lines in * the future. */ uint32_t version GNUNET_PACKED; /** * Phone line to use at the peer. */ uint32_t line GNUNET_PACKED; /** * Identity of the peer hosting the phone service. */ struct GNUNET_PeerIdentity peer; }; GNUNET_NETWORK_STRUCT_END /** * Information about active callers to a phone. */ enum GNUNET_CONVERSATION_PhoneEventCode { /** * We are the callee and the phone is ringing. * We should accept the call or hang up. */ GNUNET_CONVERSATION_EC_PHONE_RING, /** * The conversation was terminated by the caller. * We must no longer use the caller's handle. */ GNUNET_CONVERSATION_EC_PHONE_HUNG_UP }; /** * Function called with an event emitted by a phone. * * @param cls closure * @param code type of the event * @param caller handle for the caller * @param caller_id name of the caller in GNS */ typedef void (*GNUNET_CONVERSATION_PhoneEventHandler)(void *cls, enum GNUNET_CONVERSATION_PhoneEventCode code, struct GNUNET_CONVERSATION_Caller *caller, const char *caller_id); /** * Information about the current status of a call. Each call * progresses from ring over ready to terminated. Steps may * be skipped. */ enum GNUNET_CONVERSATION_CallerEventCode { /** * We are the callee and the caller suspended the call. Note that * both sides can independently suspend and resume calls; a call is * only "working" of both sides are active. */ GNUNET_CONVERSATION_EC_CALLER_SUSPEND, /** * We are the callee and the caller resumed the call. Note that * both sides can independently suspend and resume calls; a call is * only "working" of both sides are active. */ GNUNET_CONVERSATION_EC_CALLER_RESUME }; /** * Function called with an event emitted by a caller. * These events are only generated after the phone is * picked up. * * @param cls closure * @param code type of the event for this caller */ typedef void (*GNUNET_CONVERSATION_CallerEventHandler)(void *cls, enum GNUNET_CONVERSATION_CallerEventCode code); /** * A phone is a device that can ring to signal an incoming call and * that you can pick up to answer the call and hang up to terminate * the call. You can also hang up a ringing phone immediately * (without picking it up) to stop it from ringing. Phones have * caller ID. You can ask the phone for its record and make that * record available (via GNS) to enable others to call you. * Multiple phones maybe connected to the same line (the line is * something rather internal to a phone and not obvious from it). * You can only have one conversation per phone at any time. */ struct GNUNET_CONVERSATION_Phone; /** * Create a new phone. * * @param cfg configuration for the phone; specifies the phone service and * which line the phone is to be connected to * @param ego ego to use for name resolution (when determining caller ID) * @param event_handler how to notify the owner of the phone about events * @param event_handler_cls closure for @a event_handler */ struct GNUNET_CONVERSATION_Phone * GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_IDENTITY_Ego *ego, GNUNET_CONVERSATION_PhoneEventHandler event_handler, void *event_handler_cls); /** * Fill in a namestore record with the contact information * for this phone. Note that the filled in "data" value * is only valid until the phone is destroyed. * * @param phone phone to create a record for * @param rd namestore record to fill in */ void GNUNET_CONVERSATION_phone_get_record (struct GNUNET_CONVERSATION_Phone *phone, struct GNUNET_GNSRECORD_Data *rd); /** * Picks up a (ringing) phone call. This will connect the speaker * to the microphone of the other party, and vice versa. * * @param caller handle that identifies which caller should be answered * @param event_handler how to notify about events by the caller * @param event_handler_cls closure for @a event_handler * @param speaker speaker to use * @param mic microphone to use */ void GNUNET_CONVERSATION_caller_pick_up (struct GNUNET_CONVERSATION_Caller *caller, GNUNET_CONVERSATION_CallerEventHandler event_handler, void *event_handler_cls, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic); /** * Pause conversation of an active call. This will disconnect the speaker * and the microphone. The call can later be resumed with * #GNUNET_CONVERSATION_caller_resume. * * @param caller call to suspend */ void GNUNET_CONVERSATION_caller_suspend (struct GNUNET_CONVERSATION_Caller *caller); /** * Resume suspended conversation of a phone. * * @param caller call to resume * @param speaker speaker to use * @param mic microphone to use */ void GNUNET_CONVERSATION_caller_resume (struct GNUNET_CONVERSATION_Caller *caller, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic); /** * Hang up up a (possibly ringing or paused) phone. This will notify * the caller that we are no longer interested in talking with them. * * @param caller who should we hang up on */ void GNUNET_CONVERSATION_caller_hang_up (struct GNUNET_CONVERSATION_Caller *caller); /** * Destroys a phone. * * @param phone phone to destroy */ void GNUNET_CONVERSATION_phone_destroy (struct GNUNET_CONVERSATION_Phone *phone); /* *********************** CALL API ************************ */ /** * Handle for an outgoing call. */ struct GNUNET_CONVERSATION_Call; /** * Information about the current status of a call. */ enum GNUNET_CONVERSATION_CallEventCode { /** * We are the caller and are now ringing the other party (GNS lookup * succeeded). */ GNUNET_CONVERSATION_EC_CALL_RINGING, /** * We are the caller and are now ready to talk as the callee picked up. */ GNUNET_CONVERSATION_EC_CALL_PICKED_UP, /** * We are the caller and failed to locate a phone record in GNS. * After this invocation, the respective call handle will be * automatically destroyed and the client must no longer call * #GNUNET_CONVERSATION_call_stop or any other function on the * call object. */ GNUNET_CONVERSATION_EC_CALL_GNS_FAIL, /** * We are the caller and the callee called * #GNUNET_CONVERSATION_caller_hang_up. After this invocation, the * respective call handle will be automatically destroyed and the * client must no longer call #GNUNET_CONVERSATION_call_stop. */ GNUNET_CONVERSATION_EC_CALL_HUNG_UP, /** * We are the caller and the callee suspended the call. Note that * both sides can independently suspend and resume calls; a call is * only "working" of both sides are active. */ GNUNET_CONVERSATION_EC_CALL_SUSPENDED, /** * We are the caller and the callee suspended the call. Note that * both sides can independently suspend and resume calls; a call is * only "working" of both sides are active. */ GNUNET_CONVERSATION_EC_CALL_RESUMED, /** * We had an error handing the call, and are now restarting it * (back to lookup). This happens, for example, if the peer * is restarted during a call. */ GNUNET_CONVERSATION_EC_CALL_ERROR }; /** * Function called with an event emitted for a call. * * @param cls closure * @param code type of the event on the call */ typedef void (*GNUNET_CONVERSATION_CallEventHandler)(void *cls, enum GNUNET_CONVERSATION_CallEventCode code); /** * Call the phone of another user. * * @param cfg configuration to use, specifies our phone service * @param caller_id identity of the caller * @param callee GNS name of the callee (used to locate the callee's record) * @param speaker speaker to use (will be used automatically immediately once the * #GNUNET_CONVERSATION_EC_CALL_PICKED_UP event is generated); we will NOT generate * a ring tone on the speaker * @param mic microphone to use (will be used automatically immediately once the * #GNUNET_CONVERSATION_EC_CALL_PICKED_UP event is generated) * @param event_handler how to notify the owner of the phone about events * @param event_handler_cls closure for @a event_handler */ struct GNUNET_CONVERSATION_Call * GNUNET_CONVERSATION_call_start (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_IDENTITY_Ego *caller_id, const char *callee, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic, GNUNET_CONVERSATION_CallEventHandler event_handler, void *event_handler_cls); /** * Pause a call. Temporarily suspends the use of speaker and * microphone. * * @param call call to pause */ void GNUNET_CONVERSATION_call_suspend (struct GNUNET_CONVERSATION_Call *call); /** * Resumes a call after #GNUNET_CONVERSATION_call_suspend. * * @param call call to resume * @param speaker speaker to use * @param mic microphone to use */ void GNUNET_CONVERSATION_call_resume (struct GNUNET_CONVERSATION_Call *call, struct GNUNET_SPEAKER_Handle *speaker, struct GNUNET_MICROPHONE_Handle *mic); /** * Terminate a call. The call may be ringing or ready at this time. * * @param call call to terminate */ void GNUNET_CONVERSATION_call_stop (struct GNUNET_CONVERSATION_Call *call); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_set_service.h0000644000175000017500000003040212245626213016272 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_set_service.h * @brief two-peer set operations * @author Florian Dold * @author Christian Grothoff */ #ifndef GNUNET_SET_SERVICE_H #define GNUNET_SET_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_common.h" #include "gnunet_time_lib.h" #include "gnunet_configuration_lib.h" /** * Maximum size of a context message for set operation requests. */ #define GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE ((1<<16) - 1024) /** * Opaque handle to a set. */ struct GNUNET_SET_Handle; /** * Opaque handle to a set operation request from another peer. */ struct GNUNET_SET_Request; /** * Opaque handle to a listen operation. */ struct GNUNET_SET_ListenHandle; /** * Opaque handle to a set operation. */ struct GNUNET_SET_OperationHandle; /** * The operation that a set set supports. */ enum GNUNET_SET_OperationType { /** * A purely local set that does not support any * operation. */ GNUNET_SET_OPERATION_NONE, /** * Set intersection, only return elements that are in both sets. */ GNUNET_SET_OPERATION_INTERSECTION, /** * Set union, return all elements that are in at least one of the sets. */ GNUNET_SET_OPERATION_UNION }; /** * Status for the result callback */ enum GNUNET_SET_Status { /** * Everything went ok. */ GNUNET_SET_STATUS_OK, /** * There was a timeout. */ GNUNET_SET_STATUS_TIMEOUT, /** * The other peer refused to to the operation with us, * or something went wrong. */ GNUNET_SET_STATUS_FAILURE, /** * Success, all elements have been returned (but the other * peer might still be receiving some from us, so we are not done). */ GNUNET_SET_STATUS_HALF_DONE, /** * Success, all elements have been sent (and received). */ GNUNET_SET_STATUS_DONE }; /** * The way results are given to the client. */ enum GNUNET_SET_ResultMode { /** * Client gets every element in the resulting set. */ GNUNET_SET_RESULT_FULL, /** * Client gets only elements that have been added to the set. * Only works with set union. */ GNUNET_SET_RESULT_ADDED, /** * Client gets only elements that have been removed from the set. * Only works with set intersection. */ GNUNET_SET_RESULT_REMOVED }; /** * Element stored in a set. */ struct GNUNET_SET_Element { /** * Number of bytes in the buffer pointed to by data. */ uint16_t size; /** * Application-specific element type. */ uint16_t type; /** * Actual data of the element */ const void *data; }; /** * Continuation used for some of the set operations * * @param cls closure */ typedef void (*GNUNET_SET_Continuation) (void *cls); /** * Callback for set operation results. Called for each element * in the result set. * * @param cls closure * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK * @param status see `enum GNUNET_SET_Status` */ typedef void (*GNUNET_SET_ResultIterator) (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status); /** * Iterator for set elements. * * @param cls closure * @param element the current element, NULL if all elements have been * iterated over * @return #GNUNET_YES to continue iterating, #GNUNET_NO to stop. */ typedef int (*GNUNET_SET_ElementIterator) (void *cls, const struct GNUNET_SET_Element *element); /** * Called when another peer wants to do a set operation with the * local peer. If a listen error occurs, the @a request is NULL. * * @param cls closure * @param other_peer the other peer * @param context_msg message with application specific information from * the other peer * @param request request from the other peer (never NULL), use GNUNET_SET_accept() * to accept it, otherwise the request will be refused * Note that we can't just return value from the listen callback, * as it is also necessary to specify the set we want to do the * operation with, whith sometimes can be derived from the context * message. It's necessary to specify the timeout. */ typedef void (*GNUNET_SET_ListenCallback) (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request); /** * Create an empty set, supporting the specified operation. * * @param cfg configuration to use for connecting to the * set service * @param op operation supported by the set * Note that the operation has to be specified * beforehand, as certain set operations need to maintain * data structures spefific to the operation * @return a handle to the set */ struct GNUNET_SET_Handle * GNUNET_SET_create (const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op); /** * Add an element to the given set. * After the element has been added (in the sense of being * transmitted to the set service), @a cont will be called. * Calls to #GNUNET_SET_add_element can be queued * * @param set set to add element to * @param element element to add to the set * @param cont continuation called after the element has been added * @param cont_cls closure for @a cont * @return #GNUNET_OK on success, #GNUNET_SYSERR if the * set is invalid (e.g. the set service crashed) */ int GNUNET_SET_add_element (struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls); /** * Remove an element to the given set. * After the element has been removed (in the sense of the * request being transmitted to the set service), cont will be called. * Calls to remove_element can be queued * * @param set set to remove element from * @param element element to remove from the set * @param cont continuation called after the element has been removed * @param cont_cls closure for @a cont * @return #GNUNET_OK on success, #GNUNET_SYSERR if the * set is invalid (e.g. the set service crashed) */ int GNUNET_SET_remove_element (struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls); /** * Destroy the set handle, and free all associated resources. */ void GNUNET_SET_destroy (struct GNUNET_SET_Handle *set); /** * Prepare a set operation to be evaluated with another peer. * The evaluation will not start until the client provides * a local set with GNUNET_SET_commit(). * * @param other_peer peer with the other set * @param app_id hash for the application using the set * @param context_msg additional information for the request * @param salt salt used for the set operation; sometimes set operations * fail due to hash collisions, using a different salt for each operation * makes it harder for an attacker to exploit this * @param result_mode specified how results will be returned, * see `enum GNUNET_SET_ResultMode`. * @param result_cb called on error or success * @param result_cls closure for @a result_cb * @return a handle to cancel the operation */ struct GNUNET_SET_OperationHandle * GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, uint16_t salt, enum GNUNET_SET_ResultMode result_mode, GNUNET_SET_ResultIterator result_cb, void *result_cls); /** * Wait for set operation requests for the given application ID. * If the connection to the set service is lost, the listener is * re-created transparently with exponential backoff. * * @param cfg configuration to use for connecting to * the set service * @param operation operation we want to listen for * @param app_id id of the application that handles set operation requests * @param listen_cb called for each incoming request matching the operation * and application id * @param listen_cls handle for listen_cb * @return a handle that can be used to cancel the listen operation */ struct GNUNET_SET_ListenHandle * GNUNET_SET_listen (const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op_type, const struct GNUNET_HashCode *app_id, GNUNET_SET_ListenCallback listen_cb, void *listen_cls); /** * Cancel the given listen operation. * After calling cancel, the listen callback for this listen handle * will not be called again. * * @param lh handle for the listen operation */ void GNUNET_SET_listen_cancel (struct GNUNET_SET_ListenHandle *lh); /** * Accept a request we got via GNUNET_SET_listen(). Must be called during * GNUNET_SET_listen(), as the `struct GNUNET_SET_Request` becomes invalid * afterwards. * Call GNUNET_SET_commit() to provide the local set to use for the operation, * and to begin the exchange with the remote peer. * * @param request request to accept * @param result_mode specified how results will be returned, * see `enum GNUNET_SET_ResultMode`. * @param result_cb callback for the results * @param result_cls closure for @a result_cb * @return a handle to cancel the operation */ struct GNUNET_SET_OperationHandle * GNUNET_SET_accept (struct GNUNET_SET_Request *request, enum GNUNET_SET_ResultMode result_mode, GNUNET_SET_ResultIterator result_cb, void *result_cls); /** * Commit a set to be used with a set operation. * This function is called once we have fully constructed * the set that we want to use for the operation. At this * time, the P2P protocol can then begin to exchange the * set information and call the result callback with the * result information. * * @param oh handle to the set operation * @param set the set to use for the operation * @return #GNUNET_OK on success, #GNUNET_SYSERR if the * set is invalid (e.g. the set service crashed) */ int GNUNET_SET_commit (struct GNUNET_SET_OperationHandle *oh, struct GNUNET_SET_Handle *set); /** * Cancel the given set operation. * May not be called after the operation's GNUNET_SET_ResultIterator has been * called with a status that indicates error, timeout or done. * * @param oh set operation to cancel */ void GNUNET_SET_operation_cancel (struct GNUNET_SET_OperationHandle *oh); /** * Iterate over all elements in the given set. * Note that this operation involves transferring every element of the set * from the service to the client, and is thus costly. * Only one iteration per set may be active at the same time. * * @param set the set to iterate over * @param iter the iterator to call for each element * @param cls closure for 'iter' * @return GNUNET_YES if the iteration started successfuly, * GNUNET_SYSERR if the set is invalid (e.g. the server crashed, disconnected) */ int GNUNET_SET_iterate (struct GNUNET_SET_Handle *set, GNUNET_SET_ElementIterator iter, void *cls); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_psycstore_plugin.h0000644000175000017500000002352012225777503017402 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_psycstore_plugin.h * @brief plugin API for the PSYCstore database backend * @author Gabor X Toth */ #ifndef GNUNET_PSYCSTORE_PLUGIN_H #define GNUNET_PSYCSTORE_PLUGIN_H #include "gnunet_util_lib.h" #include "gnunet_psycstore_service.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Struct returned by the initialization function of the plugin. */ struct GNUNET_PSYCSTORE_PluginFunctions { /** * Closure to pass to all plugin functions. */ void *cls; /** * Store join/leave events for a PSYC channel in order to be able to answer * membership test queries later. * * @see GNUNET_PSYCSTORE_membership_store() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*membership_store) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, int did_join, uint64_t announced_at, uint64_t effective_since, uint64_t group_generation); /** * Test if a member was admitted to the channel at the given message ID. * * @see GNUNET_PSYCSTORE_membership_test() * * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not, * #GNUNET_SYSERR if there was en error. */ int (*membership_test) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t message_id); /** * Store a message fragment sent to a channel. * * @see GNUNET_PSYCSTORE_fragment_store() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*fragment_store) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_MULTICAST_MessageHeader *message, uint32_t psycstore_flags); /** * Set additional flags for a given message. * * They are OR'd with any existing flags set. * * @param cls Closure. * @param channel_key Public key of the channel. * @param message_id ID of the message. * @param psycstore_flags OR'd GNUNET_PSYCSTORE_MessageFlags. * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*message_add_flags) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t psycstore_flags); /** * Retrieve a message fragment by fragment ID. * * @see GNUNET_PSYCSTORE_fragment_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*fragment_get) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t fragment_id, GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls); /** * Retrieve all fragments of a message. * * @see GNUNET_PSYCSTORE_message_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*message_get) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t *returned_fragments, GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls); /** * Retrieve a fragment of message specified by its message ID and fragment * offset. * * @see GNUNET_PSYCSTORE_message_get_fragment() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*message_get_fragment) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t fragment_offset, GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls); /** * Retrieve the max. values of message counters for a channel. * * @see GNUNET_PSYCSTORE_counters_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*counters_message_get) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t *max_fragment_id, uint64_t *max_message_id, uint64_t *max_group_generation); /** * Retrieve the max. values of state counters for a channel. * * @see GNUNET_PSYCSTORE_counters_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*counters_state_get) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t *max_state_message_id); /** * Begin modifying current state. * * @see GNUNET_PSYCSTORE_state_modify() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_modify_begin) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t state_delta); /** * Set the current value of a state variable. * * The state modification process is started with state_modify_begin(), * which is followed by one or more calls to this function, * and finished with state_modify_end(). * * @see GNUNET_PSYCSTORE_state_modify() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_modify_set) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, const void *value, size_t value_size); /** * End modifying current state. * * @see GNUNET_PSYCSTORE_state_modify() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_modify_end) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id); /** * Begin synchronizing state. * * @see GNUNET_PSYCSTORE_state_sync() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_sync_begin) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key); /** * Set the value of a state variable while synchronizing state. * * The state synchronization process is started with state_sync_begin(), * which is followed by one or more calls to this function, * and finished with state_sync_end(). * * @see GNUNET_PSYCSTORE_state_sync() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_sync_set) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, const void *value, size_t value_size); /** * End synchronizing state. * * @see GNUNET_PSYCSTORE_state_sync() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_sync_end) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id); /** * Reset the state of a channel. * * Delete all state variables stored for the given channel. * * @see GNUNET_PSYCSTORE_state_reset() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_reset) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key); /** * Update signed state values from the current ones. * * Sets value_signed = value_current for each variable for the given channel. */ int (*state_update_signed) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key); /** * Retrieve a state variable by name (exact match). * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_get) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls); /** * Retrieve all state variables for a channel with the given prefix. * * @see GNUNET_PSYCSTORE_state_get_prefix() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_get_prefix) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls); /** * Retrieve all signed state variables for a channel. * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ int (*state_get_signed) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls); }; #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_psycstore_plugin.h */ #endif gnunet-0.10.1/src/include/plibc.h0000644000175000017500000007502612276375236013515 00000000000000/* This file is part of PlibC. (C) 2005, 2006, 2007, 2008, 2009, 2010 Nils Durner (and other contributing authors) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * @file include/plibc.h * @brief PlibC header * @attention This file is usually not installed under Unix, * so ship it with your application * @version $Revision$ */ #ifndef _PLIBC_H_ #define _PLIBC_H_ #ifndef SIGALRM #define SIGALRM 14 #endif #ifdef __cplusplus extern "C" { #endif #include #ifdef Q_OS_WIN32 #define WINDOWS 1 #endif #define HAVE_PLIBC_FD 0 #ifdef WINDOWS #if ENABLE_NLS #include "langinfo.h" #endif #include #include #include #include #include #include #include #include #include #include #define __BYTE_ORDER BYTE_ORDER #define __BIG_ENDIAN BIG_ENDIAN /* Conflicts with our definitions */ #define __G_WIN32_H__ /* Convert LARGE_INTEGER to double */ #define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + \ (double)((x).LowPart)) #ifndef HAVE_DECL__STATI64 struct _stati64 { _dev_t st_dev; _ino_t st_ino; _mode_t st_mode; short st_nlink; short st_uid; short st_gid; _dev_t st_rdev; __int64 st_size; time_t st_atime; time_t st_mtime; time_t st_ctime; }; #endif typedef unsigned int sa_family_t; struct sockaddr_un { short sun_family; /*AF_UNIX*/ char sun_path[108]; /*path name */ }; #ifndef pid_t #define pid_t DWORD #endif #ifndef error_t #define error_t int #endif #ifndef WEXITSTATUS #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) #endif #ifndef MSG_DONTWAIT #define MSG_DONTWAIT 0 #endif enum { _SC_PAGESIZE = 30, _SC_PAGE_SIZE = 30 }; #if !defined(EACCESS) # define EACCESS EACCES #endif /* Thanks to the Cygwin project */ #if !defined(ENOCSI) # define ENOCSI 43 /* No CSI structure available */ #endif #if !defined(EL2HLT) # define EL2HLT 44 /* Level 2 halted */ #endif #if !defined(EDEADLK) # define EDEADLK 45 /* Deadlock condition */ #endif #if !defined(ENOLCK) # define ENOLCK 46 /* No record locks available */ #endif #if !defined(EBADE) # define EBADE 50 /* Invalid exchange */ #endif #if !defined(EBADR) # define EBADR 51 /* Invalid request descriptor */ #endif #if !defined(EXFULL) # define EXFULL 52 /* Exchange full */ #endif #if !defined(ENOANO) # define ENOANO 53 /* No anode */ #endif #if !defined(EBADRQC) # define EBADRQC 54 /* Invalid request code */ #endif #if !defined(EBADSLT) # define EBADSLT 55 /* Invalid slot */ #endif #if !defined(EDEADLOCK) # define EDEADLOCK EDEADLK /* File locking deadlock error */ #endif #if !defined(EBFONT) # define EBFONT 57 /* Bad font file fmt */ #endif #if !defined(ENOSTR) # define ENOSTR 60 /* Device not a stream */ #endif #if !defined(ENODATA) # define ENODATA 61 /* No data (for no delay io) */ #endif #if !defined(ETIME) # define ETIME 62 /* Timer expired */ #endif #if !defined(ENOSR) # define ENOSR 63 /* Out of streams resources */ #endif #if !defined(ENONET) # define ENONET 64 /* Machine is not on the network */ #endif #if !defined(ENOPKG) # define ENOPKG 65 /* Package not installed */ #endif #if !defined(EREMOTE) # define EREMOTE 66 /* The object is remote */ #endif #if !defined(ENOLINK) # define ENOLINK 67 /* The link has been severed */ #endif #if !defined(EADV) # define EADV 68 /* Advertise error */ #endif #if !defined(ESRMNT) # define ESRMNT 69 /* Srmount error */ #endif #if !defined(ECOMM) # define ECOMM 70 /* Communication error on send */ #endif #if !defined(EMULTIHOP) # define EMULTIHOP 74 /* Multihop attempted */ #endif #if !defined(ELBIN) # define ELBIN 75 /* Inode is remote (not really error) */ #endif #if !defined(EDOTDOT) # define EDOTDOT 76 /* Cross mount point (not really error) */ #endif #if !defined(EBADMSG) # define EBADMSG 77 /* Trying to read unreadable message */ #endif #if !defined(ENOTUNIQ) # define ENOTUNIQ 80 /* Given log. name not unique */ #endif #if !defined(EBADFD) # define EBADFD 81 /* f.d. invalid for this operation */ #endif #if !defined(EREMCHG) # define EREMCHG 82 /* Remote address changed */ #endif #if !defined(ELIBACC) # define ELIBACC 83 /* Can't access a needed shared lib */ #endif #if !defined(ELIBBAD) # define ELIBBAD 84 /* Accessing a corrupted shared lib */ #endif #if !defined(ELIBSCN) # define ELIBSCN 85 /* .lib section in a.out corrupted */ #endif #if !defined(ELIBMAX) # define ELIBMAX 86 /* Attempting to link in too many libs */ #endif #if !defined(ELIBEXEC) # define ELIBEXEC 87 /* Attempting to exec a shared library */ #endif #if !defined(ENOSYS) # define ENOSYS 88 /* Function not implemented */ #endif #if !defined(ENMFILE) # define ENMFILE 89 /* No more files */ #endif #if !defined(ENOTEMPTY) # define ENOTEMPTY 90 /* Directory not empty */ #endif #if !defined(ENAMETOOLONG) # define ENAMETOOLONG 91 /* File or path name too long */ #endif #if !defined(EPFNOSUPPORT) # define EPFNOSUPPORT 96 /* Protocol family not supported */ #endif #if !defined(ENOSHARE) # define ENOSHARE 97 /* No such host or network path */ #endif #if !defined(ENOMEDIUM) # define ENOMEDIUM 98 /* No medium (in tape drive) */ #endif #if !defined(ESHUTDOWN) # define ESHUTDOWN 99 /* Can't send after socket shutdown */ #endif #if !defined(EADDRINUSE) # define EADDRINUSE 100 /* Address already in use */ #endif #if !defined(EADDRNOTAVAIL) # define EADDRNOTAVAIL 101 /* Address not available */ #endif #if !defined(EAFNOSUPPORT) # define EAFNOSUPPORT 102 /* Address family not supported by protocol family */ #endif #if !defined(EALREADY) # define EALREADY 103 /* Socket already connected */ #endif #if !defined(ECANCELED) # define ECANCELED 105 /* Connection cancelled */ #endif #if !defined(ECONNABORTED) # define ECONNABORTED 106 /* Connection aborted */ #endif #if !defined(ECONNREFUSED) # define ECONNREFUSED 107 /* Connection refused */ #endif #if !defined(ECONNRESET) # define ECONNRESET 108 /* Connection reset by peer */ #endif #if !defined(EDESTADDRREQ) # define EDESTADDRREQ 109 /* Destination address required */ #endif #if !defined(EHOSTUNREACH) # define EHOSTUNREACH 110 /* Host is unreachable */ #endif #if !defined(ECONNABORTED) # define ECONNABORTED 111 /* Connection aborted */ #endif #if !defined(EINPROGRESS) # define EINPROGRESS 112 /* Connection already in progress */ #endif #if !defined(EISCONN) # define EISCONN 113 /* Socket is already connected */ #endif #if !defined(ELOOP) # define ELOOP 114 /* Too many symbolic links */ #endif #if !defined(EMSGSIZE) # define EMSGSIZE 115 /* Message too long */ #endif #if !defined(ENETDOWN) # define ENETDOWN 116 /* Network interface is not configured */ #endif #if !defined(ENETRESET) # define ENETRESET 117 /* Connection aborted by network */ #endif #if !defined(ENETUNREACH) # define ENETUNREACH 118 /* Network is unreachable */ #endif #if !defined(ENOBUFS) # define ENOBUFS 119 /* No buffer space available */ #endif #if !defined(EHOSTDOWN) # define EHOSTDOWN 120 /* Host is down */ #endif #if !defined(EPROCLIM) # define EPROCLIM 121 /* Too many processes */ #endif #if !defined(EDQUOT) # define EDQUOT 122 /* Disk quota exceeded */ #endif #if !defined(ENOPROTOOPT) # define ENOPROTOOPT 123 /* Protocol not available */ #endif #if !defined(ESOCKTNOSUPPORT) # define ESOCKTNOSUPPORT 124 /* Socket type not supported */ #endif #if !defined(ESTALE) # define ESTALE 125 /* Unknown error */ #endif #if !defined(ENOTCONN) # define ENOTCONN 126 /* Socket is not connected */ #endif #if !defined(ETOOMANYREFS) # define ETOOMANYREFS 127 /* Too many references: cannot splice */ #endif #if !defined(ENOTSOCK) # define ENOTSOCK 128 /* Socket operation on non-socket */ #endif #if !defined(ENOTSUP) # define ENOTSUP 129 /* Not supported */ #endif #if !defined(EOPNOTSUPP) # define EOPNOTSUPP 130 /* Operation not supported on transport endpoint */ #endif #if !defined(EUSERS) # define EUSERS 131 /* Too many users */ #endif #if !defined(EOVERFLOW) # define EOVERFLOW 132 /* Value too large for defined data type */ #endif #if !defined(EOWNERDEAD) # define EOWNERDEAD 133 /* Unknown error */ #endif #if !defined(EPROTO) # define EPROTO 134 /* Protocol error */ #endif #if !defined(EPROTONOSUPPORT) # define EPROTONOSUPPORT 135 /* Unknown protocol */ #endif #if !defined(EPROTOTYPE) # define EPROTOTYPE 136 /* Protocol wrong type for socket */ #endif #if !defined(ECASECLASH) # define ECASECLASH 137 /* Filename exists with different case */ #endif #if !defined(ETIMEDOUT) /* Make sure it's the same as WSATIMEDOUT */ # define ETIMEDOUT 138 /* Connection timed out */ #endif #if !defined(EWOULDBLOCK) || EWOULDBLOCK == 140 # undef EWOULDBLOCK /* MinGW-w64 defines it as 140, but we want it as EAGAIN */ # define EWOULDBLOCK EAGAIN /* Operation would block */ #endif #undef HOST_NOT_FOUND #define HOST_NOT_FOUND 1 #undef TRY_AGAIN #define TRY_AGAIN 2 #undef NO_RECOVERY #define NO_RECOVERY 3 #undef NO_ADDRESS #define NO_ADDRESS 4 #define PROT_READ 0x1 #define PROT_WRITE 0x2 #define MAP_SHARED 0x1 #define MAP_PRIVATE 0x2 /* unsupported */ #define MAP_FIXED 0x10 #define MAP_ANONYMOUS 0x20 /* unsupported */ #define MAP_FAILED ((void *)-1) #define MS_ASYNC 1 /* sync memory asynchronously */ #define MS_INVALIDATE 2 /* invalidate the caches */ #define MS_SYNC 4 /* synchronous memory sync */ struct statfs { long f_type; /* type of filesystem (see below) */ long f_bsize; /* optimal transfer block size */ long f_blocks; /* total data blocks in file system */ long f_bfree; /* free blocks in fs */ long f_bavail; /* free blocks avail to non-superuser */ long f_files; /* total file nodes in file system */ long f_ffree; /* free file nodes in fs */ long f_fsid; /* file system id */ long f_namelen; /* maximum length of filenames */ long f_spare[6]; /* spare for later */ }; #define sleep(secs) (Sleep(secs * 1000)) /*********************** statfs *****************************/ /* fake block size */ #define FAKED_BLOCK_SIZE 512 /* linux-compatible values for fs type */ #define MSDOS_SUPER_MAGIC 0x4d44 #define NTFS_SUPER_MAGIC 0x5346544E /*********************** End of statfs ***********************/ #define SHUT_RDWR SD_BOTH /* Operations for flock() */ #define LOCK_SH 1 /* shared lock */ #define LOCK_EX 2 /* exclusive lock */ #define LOCK_NB 4 /* or'd with one of the above to prevent blocking */ #define LOCK_UN 8 /* remove lock */ /* Not supported under MinGW */ #define S_IRGRP 0 #define S_IWGRP 0 #define S_IROTH 0 #define S_IXGRP 0 #define S_IWOTH 0 #define S_IXOTH 0 #define S_ISUID 0 #define S_ISGID 0 #define S_ISVTX 0 #define S_IRWXG 0 #define S_IRWXO 0 #define SHUT_WR SD_SEND #define SHUT_RD SD_RECEIVE #define SHUT_RDWR SD_BOTH #define SIGKILL 9 #define SIGTERM 15 #define SetErrnoFromWinError(e) _SetErrnoFromWinError(e, __FILE__, __LINE__) BOOL _plibc_CreateShortcut(const char *pszSrc, const char *pszDest); BOOL _plibc_CreateShortcutW(const wchar_t *pwszSrc, const wchar_t *pwszDest); BOOL _plibc_DereferenceShortcut(char *pszShortcut); BOOL _plibc_DereferenceShortcutW(wchar_t *pwszShortcut); char *plibc_ChooseDir(char *pszTitle, unsigned long ulFlags); wchar_t *plibc_ChooseDirW(wchar_t *pwszTitle, unsigned long ulFlags); char *plibc_ChooseFile(char *pszTitle, unsigned long ulFlags); wchar_t *plibc_ChooseFileW(wchar_t *pwszTitle, unsigned long ulFlags); long QueryRegistry(HKEY hMainKey, const char *pszKey, const char *pszSubKey, char *pszBuffer, long *pdLength); long QueryRegistryW(HKEY hMainKey, const wchar_t *pszKey, const wchar_t *pszSubKey, wchar_t *pszBuffer, long *pdLength); BOOL __win_IsHandleMarkedAsBlocking(int hHandle); void __win_SetHandleBlockingMode(int s, BOOL bBlocking); void __win_DiscardHandleBlockingMode(int s); int _win_isSocketValid(int s); int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows); int plibc_conv_to_win_pathw(const wchar_t *pszUnix, wchar_t *pwszWindows); int plibc_conv_to_win_pathwconv(const char *pszUnix, wchar_t *pwszWindows); int plibc_conv_to_win_pathwconv_ex(const char *pszUnix, wchar_t *pszWindows, int derefLinks); unsigned plibc_get_handle_count(); typedef void (*TPanicProc) (int, char *); void plibc_set_panic_proc(TPanicProc proc); void plibc_set_stat_size_size(int iLength); void plibc_set_stat_time_size(int iLength); int flock(int fd, int operation); int fsync(int fildes); int inet_pton(int af, const char *src, void *dst); int inet_pton4(const char *src, u_char *dst, int pton); #if USE_IPV6 int inet_pton6(const char *src, u_char *dst); #endif int statfs(const char *path, struct statfs *buf); const char *hstrerror(int err); int mkstemp(char *tmplate); char *strptime (const char *buf, const char *format, struct tm *tm); const char *inet_ntop(int af, const void *src, char *dst, size_t size); #ifndef gmtime_r struct tm *gmtime_r(const time_t *clock, struct tm *result); #endif int plibc_init(char *pszOrg, char *pszApp); int plibc_init_utf8(char *pszOrg, char *pszApp, int utf8_mode); void plibc_shutdown(); int plibc_initialized(); void _SetErrnoFromWinError(long lWinError, char *pszCaller, int iLine); void SetErrnoFromWinsockError(long lWinError); void SetHErrnoFromWinError(long lWinError); void SetErrnoFromHRESULT(HRESULT hRes); int GetErrnoFromWinsockError(long lWinError); FILE *_win_fopen(const char *filename, const char *mode); int _win_fclose(FILE *); DIR *_win_opendir(const char *dirname); struct dirent *_win_readdir(DIR *dirp); int _win_closedir(DIR *dirp); int _win_open(const char *filename, int oflag, ...); #ifdef ENABLE_NLS char *_win_bindtextdomain(const char *domainname, const char *dirname); #endif int _win_chdir(const char *path); int _win_close(int fd); int _win_creat(const char *path, mode_t mode); char *_win_ctime(const time_t *clock); char *_win_ctime_r(const time_t *clock, char *buf); int _win_fstat(int handle, struct stat *buffer); int _win_ftruncate(int fildes, off_t length); int _win_truncate(const char *fname, int distance); int _win_kill(pid_t pid, int sig); int _win_pipe(int *phandles); intptr_t _win_mkfifo(const char *path, mode_t mode); int _win_rmdir(const char *path); int _win_access( const char *path, int mode ); int _win_chmod(const char *filename, int pmode); char *realpath(const char *file_name, char *resolved_name); long _win_random(void); void _win_srandom(unsigned int seed); int _win_remove(const char *path); int _win_rename(const char *oldname, const char *newname); int _win_stat(const char *path, struct stat *buffer); int _win_stati64(const char *path, struct _stati64 *buffer); long _win_sysconf(int name); int _win_unlink(const char *filename); int _win_write(int fildes, const void *buf, size_t nbyte); int _win_read(int fildes, void *buf, size_t nbyte); size_t _win_fwrite(const void *buffer, size_t size, size_t count, FILE *stream); size_t _win_fread( void *buffer, size_t size, size_t count, FILE *stream ); int _win_symlink(const char *path1, const char *path2); void *_win_mmap(void *start, size_t len, int access, int flags, int fd, unsigned long long offset); int _win_msync(void *start, size_t length, int flags); int _win_munmap(void *start, size_t length); int _win_lstat(const char *path, struct stat *buf); int _win_lstati64(const char *path, struct _stati64 *buf); int _win_readlink(const char *path, char *buf, size_t bufsize); int _win_accept(int s, struct sockaddr *addr, int *addrlen); pid_t _win_waitpid(pid_t pid, int *stat_loc, int options); int _win_bind(int s, const struct sockaddr *name, int namelen); int _win_connect(int s,const struct sockaddr *name, int namelen); int _win_getpeername(int s, struct sockaddr *name, int *namelen); int _win_getsockname(int s, struct sockaddr *name, int *namelen); int _win_getsockopt(int s, int level, int optname, char *optval, int *optlen); int _win_listen(int s, int backlog); int _win_recv(int s, char *buf, int len, int flags); int _win_recvfrom(int s, void *buf, int len, int flags, struct sockaddr *from, int *fromlen); int _win_select(int max_fd, fd_set * rfds, fd_set * wfds, fd_set * efds, const struct timeval *tv); int _win_send(int s, const char *buf, int len, int flags); int _win_sendto(int s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen); int _win_setsockopt(int s, int level, int optname, const void *optval, int optlen); int _win_shutdown(int s, int how); int _win_socket(int af, int type, int protocol); int _win_socketpair(int af, int type, int protocol, int socket_vector[2]); struct hostent *_win_gethostbyaddr(const char *addr, int len, int type); struct hostent *_win_gethostbyname(const char *name); struct hostent *gethostbyname2(const char *name, int af); char *_win_strerror(int errnum); int IsWinNT(); char *index(const char *s, int c); char *_win_strtok_r (char *ptr, const char *sep, char **end); #if !HAVE_STRNDUP char *strndup (const char *s, size_t n); #endif #if !HAVE_STRNLEN && (!defined(__MINGW64_VERSION_MAJOR) || !defined(_INC_STRING)) size_t strnlen (const char *str, size_t maxlen); #endif char *stpcpy(char *dest, const char *src); char *strcasestr(const char *haystack_start, const char *needle_start); #ifndef __MINGW64_VERSION_MAJOR #define strcasecmp(a, b) stricmp(a, b) #define strncasecmp(a, b, c) strnicmp(a, b, c) #endif #ifndef wcscasecmp #define wcscasecmp(a, b) wcsicmp(a, b) #endif #ifndef wcsncasecmp #define wcsncasecmp(a, b, c) wcsnicmp(a, b, c) #endif #ifndef strtok_r /* winpthreads defines it in pthread.h */ #define strtok_r _win_strtok_r #endif #endif /* WINDOWS */ #ifndef WINDOWS #define DIR_SEPARATOR '/' #define DIR_SEPARATOR_STR "/" #define PATH_SEPARATOR ':' #define PATH_SEPARATOR_STR ":" #define NEWLINE "\n" #ifdef ENABLE_NLS #define BINDTEXTDOMAIN(d, n) bindtextdomain(d, n) #endif #define CREAT(p, m) creat(p, m) #define PLIBC_CTIME(c) ctime(c) #define CTIME_R(c, b) ctime_r(c, b) #undef FOPEN #define FOPEN(f, m) fopen(f, m) #define FCLOSE(f) fclose(f) #define FTRUNCATE(f, l) ftruncate(f, l) #define TRUNCATE(f, l) truncate(f, l) #define OPENDIR(d) opendir(d) #define CLOSEDIR(d) closedir(d) #define READDIR(d) readdir(d) #define OPEN open #define CHDIR(d) chdir(d) #define CLOSE(f) close(f) #define LSEEK(f, o, w) lseek(f, o, w) #define RMDIR(f) rmdir(f) #define ACCESS(p, m) access(p, m) #define CHMOD(f, p) chmod(f, p) #define FSTAT(h, b) fstat(h, b) #define PLIBC_KILL(p, s) kill(p, s) #define PIPE(h) pipe(h) #define REMOVE(p) remove(p) #define RENAME(o, n) rename(o, n) #define STAT(p, b) stat(p, b) #define STAT64(p, b) stat64(p, b) #define SYSCONF(n) sysconf(n) #define UNLINK(f) unlink(f) #define WRITE(f, b, n) write(f, b, n) #define READ(f, b, n) read(f, b, n) #define GN_FREAD(b, s, c, f) fread(b, s, c, f) #define GN_FWRITE(b, s, c, f) fwrite(b, s, c, f) #define SYMLINK(a, b) symlink(a, b) #define MMAP(s, l, p, f, d, o) mmap(s, l, p, f, d, o) #define MKFIFO(p, m) mkfifo(p, m) #define MSYNC(s, l, f) msync(s, l, f) #define MUNMAP(s, l) munmap(s, l) #define STRERROR(i) strerror(i) #define RANDOM() random() #define SRANDOM(s) srandom(s) #define READLINK(p, b, s) readlink(p, b, s) #define LSTAT(p, b) lstat(p, b) #define LSTAT64(p, b) lstat64(p, b) #define PRINTF printf #define FPRINTF fprintf #define VPRINTF(f, a) vprintf(f, a) #define VFPRINTF(s, f, a) vfprintf(s, f, a) #define VSPRINTF(d, f, a) vsprintf(d, f, a) #define VSNPRINTF(str, size, fmt, a) vsnprintf(str, size, fmt, a) #define _REAL_SNPRINTF snprintf #define SPRINTF sprintf #define VSSCANF(s, f, a) vsscanf(s, f, a) #define SSCANF sscanf #define VFSCANF(s, f, a) vfscanf(s, f, a) #define VSCANF(f, a) vscanf(f, a) #define SCANF scanf #define FSCANF fscanf #define WAITPID(p, s, o) waitpid(p, s, o) #define ACCEPT(s, a, l) accept(s, a, l) #define BIND(s, n, l) bind(s, n, l) #define CONNECT(s, n, l) connect(s, n, l) #define GETPEERNAME(s, n, l) getpeername(s, n, l) #define GETSOCKNAME(s, n, l) getsockname(s, n, l) #define GETSOCKOPT(s, l, o, v, p) getsockopt(s, l, o, v, p) #define LISTEN(s, b) listen(s, b) #define RECV(s, b, l, f) recv(s, b, l, f) #define RECVFROM(s, b, l, f, r, o) recvfrom(s, b, l, f, r, o) #define SELECT(n, r, w, e, t) select(n, r, w, e, t) #define SEND(s, b, l, f) send(s, b, l, f) #define SENDTO(s, b, l, f, o, n) sendto(s, b, l, f, o, n) #define SETSOCKOPT(s, l, o, v, n) setsockopt(s, l, o, v, n) #define SHUTDOWN(s, h) shutdown(s, h) #define SOCKET(a, t, p) socket(a, t, p) #define SOCKETPAIR(a, t, p, v) socketpair(a, t, p, v) #define GETHOSTBYADDR(a, l, t) gethostbyaddr(a, l, t) #define GETHOSTBYNAME(n) gethostbyname(n) #define GETTIMEOFDAY(t, n) gettimeofday(t, n) #define INSQUE(e, p) insque(e, p) #define REMQUE(e) remque(e) #define HSEARCH(i, a) hsearch(i, a) #define HCREATE(n) hcreate(n) #define HDESTROY() hdestroy() #define HSEARCH_R(i, a, r, h) hsearch_r(i, a, r, h) #define HCREATE_R(n, h) hcreate_r(n, h) #define HDESTROY_R(h) hdestroy_r(h) #define TSEARCH(k, r, c) tsearch(k, r, c) #define TFIND(k, r, c) tfind(k, r, c) #define TDELETE(k, r, c) tdelete(k, r, c) #define TWALK(r, a) twalk(r, a) #define TDESTROY(r, f) tdestroy(r, f) #define LFIND(k, b, n, s, c) lfind(k, b, n, s, c) #define LSEARCH(k, b, n, s, c) lsearch(k, b, n, s, c) #define STRUCT_STAT64 struct stat64 #else #define DIR_SEPARATOR '\\' #define DIR_SEPARATOR_STR "\\" #define PATH_SEPARATOR ';' #define PATH_SEPARATOR_STR ";" #define NEWLINE "\r\n" #ifdef ENABLE_NLS #define BINDTEXTDOMAIN(d, n) _win_bindtextdomain(d, n) #endif #define CREAT(p, m) _win_creat(p, m) #define PLIBC_CTIME(c) _win_ctime(c) #define CTIME_R(c, b) _win_ctime_r(c, b) #define FOPEN(f, m) _win_fopen(f, m) #define FCLOSE(f) _win_fclose(f) #define FTRUNCATE(f, l) _win_ftruncate(f, l) #define TRUNCATE(f, l) _win_truncate(f, l) #define OPENDIR(d) _win_opendir(d) #define CLOSEDIR(d) _win_closedir(d) #define READDIR(d) _win_readdir(d) #define OPEN _win_open #define CHDIR(d) _win_chdir(d) #define CLOSE(f) _win_close(f) #define PLIBC_KILL(p, s) _win_kill(p, s) #define LSEEK(f, o, w) lseek(f, o, w) #define FSTAT(h, b) _win_fstat(h, b) #define RMDIR(f) _win_rmdir(f) #define ACCESS(p, m) _win_access(p, m) #define CHMOD(f, p) _win_chmod(f, p) #define PIPE(h) _win_pipe(h) #define RANDOM() _win_random() #define SRANDOM(s) _win_srandom(s) #define REMOVE(p) _win_remove(p) #define RENAME(o, n) _win_rename(o, n) #define STAT(p, b) _win_stat(p, b) #define STAT64(p, b) _win_stati64(p, b) #define SYSCONF(n) _win_sysconf(n) #define UNLINK(f) _win_unlink(f) #define WRITE(f, b, n) _win_write(f, b, n) #define READ(f, b, n) _win_read(f, b, n) #define GN_FREAD(b, s, c, f) _win_fread(b, s, c, f) #define GN_FWRITE(b, s, c, f) _win_fwrite(b, s, c, f) #define SYMLINK(a, b) _win_symlink(a, b) #define MMAP(s, l, p, f, d, o) _win_mmap(s, l, p, f, d, o) #define MKFIFO(p, m) _win_mkfifo(p, m) #define MSYNC(s, l, f) _win_msync(s, l, f) #define MUNMAP(s, l) _win_munmap(s, l) #define STRERROR(i) _win_strerror(i) #define READLINK(p, b, s) _win_readlink(p, b, s) #define LSTAT(p, b) _win_lstat(p, b) #define LSTAT64(p, b) _win_lstati64(p, b) #define PRINTF printf #define FPRINTF fprintf #define VPRINTF(f, a) vprintf(f, a) #define VFPRINTF(s, f, a) vfprintf(s, f, a) #define VSPRINTF(d, f, a) vsprintf(d, f, a) #define VSNPRINTF(str, size, fmt, a) vsnprintf(str, size, fmt, a) #define _REAL_SNPRINTF snprintf #define SPRINTF sprintf #define VSSCANF(s, f, a) vsscanf(s, f, a) #define SSCANF sscanf #define VFSCANF(s, f, a) vfscanf(s, f, a) #define VSCANF(f, a) vscanf(f, a) #define SCANF scanf #define FSCANF fscanf #define WAITPID(p, s, o) _win_waitpid(p, s, o) #define ACCEPT(s, a, l) _win_accept(s, a, l) #define BIND(s, n, l) _win_bind(s, n, l) #define CONNECT(s, n, l) _win_connect(s, n, l) #define GETPEERNAME(s, n, l) _win_getpeername(s, n, l) #define GETSOCKNAME(s, n, l) _win_getsockname(s, n, l) #define GETSOCKOPT(s, l, o, v, p) _win_getsockopt(s, l, o, v, p) #define LISTEN(s, b) _win_listen(s, b) #define RECV(s, b, l, f) _win_recv(s, b, l, f) #define RECVFROM(s, b, l, f, r, o) _win_recvfrom(s, b, l, f, r, o) #define SELECT(n, r, w, e, t) _win_select(n, r, w, e, t) #define SEND(s, b, l, f) _win_send(s, b, l, f) #define SENDTO(s, b, l, f, o, n) _win_sendto(s, b, l, f, o, n) #define SETSOCKOPT(s, l, o, v, n) _win_setsockopt(s, l, o, v, n) #define SHUTDOWN(s, h) _win_shutdown(s, h) #define SOCKET(a, t, p) _win_socket(a, t, p) #define SOCKETPAIR(a, t, p, v) _win_socketpair(a, t, p, v) #define GETHOSTBYADDR(a, l, t) _win_gethostbyaddr(a, l, t) #define GETHOSTBYNAME(n) _win_gethostbyname(n) #define GETTIMEOFDAY(t, n) gettimeofday(t, n) #define INSQUE(e, p) _win_insque(e, p) #define REMQUE(e) _win_remque(e) #define HSEARCH(i, a) _win_hsearch(i, a) #define HCREATE(n) _win_hcreate(n) #define HDESTROY() _win_hdestroy() #define HSEARCH_R(i, a, r, h) _win_hsearch_r(i, a, r, h) #define HCREATE_R(n, h) _win_hcreate_r(n, h) #define HDESTROY_R(h) _win_hdestroy_r(h) #define TSEARCH(k, r, c) _win_tsearch(k, r, c) #define TFIND(k, r, c) _win_tfind(k, r, c) #define TDELETE(k, r, c) _win_tdelete(k, r, c) #define TWALK(r, a) _win_twalk(r, a) #define TDESTROY(r, f) _win_tdestroy(r, f) #define LFIND(k, b, n, s, c) _win_lfind(k, b, n, s, c) #define LSEARCH(k, b, n, s, c) _win_lsearch(k, b, n, s, c) #define STRUCT_STAT64 struct _stati64 #endif /* search.h */ /* Prototype structure for a linked-list data structure. This is the type used by the `insque' and `remque' functions. */ struct PLIBC_SEARCH_QELEM { struct qelem *q_forw; struct qelem *q_back; char q_data[1]; }; /* Insert ELEM into a doubly-linked list, after PREV. */ void _win_insque (void *__elem, void *__prev); /* Unlink ELEM from the doubly-linked list that it is in. */ void _win_remque (void *__elem); /* For use with hsearch(3). */ typedef int (*PLIBC_SEARCH__compar_fn_t) (__const void *, __const void *); typedef PLIBC_SEARCH__compar_fn_t _win_comparison_fn_t; /* Action which shall be performed in the call the hsearch. */ typedef enum { PLIBC_SEARCH_FIND, PLIBC_SEARCH_ENTER } PLIBC_SEARCH_ACTION; typedef struct PLIBC_SEARCH_entry { char *key; void *data; } PLIBC_SEARCH_ENTRY; /* The reentrant version has no static variables to maintain the state. Instead the interface of all functions is extended to take an argument which describes the current status. */ typedef struct _PLIBC_SEARCH_ENTRY { unsigned int used; PLIBC_SEARCH_ENTRY entry; } _PLIBC_SEARCH_ENTRY; /* Family of hash table handling functions. The functions also have reentrant counterparts ending with _r. The non-reentrant functions all work on a signle internal hashing table. */ /* Search for entry matching ITEM.key in internal hash table. If ACTION is `FIND' return found entry or signal error by returning NULL. If ACTION is `ENTER' replace existing data (if any) with ITEM.data. */ PLIBC_SEARCH_ENTRY *_win_hsearch (PLIBC_SEARCH_ENTRY __item, PLIBC_SEARCH_ACTION __action); /* Create a new hashing table which will at most contain NEL elements. */ int _win_hcreate (size_t __nel); /* Destroy current internal hashing table. */ void _win_hdestroy (void); /* Data type for reentrant functions. */ struct PLIBC_SEARCH_hsearch_data { struct _PLIBC_SEARCH_ENTRY *table; unsigned int size; unsigned int filled; }; /* Reentrant versions which can handle multiple hashing tables at the same time. */ int _win_hsearch_r (PLIBC_SEARCH_ENTRY __item, PLIBC_SEARCH_ACTION __action, PLIBC_SEARCH_ENTRY **__retval, struct PLIBC_SEARCH_hsearch_data *__htab); int _win_hcreate_r (size_t __nel, struct PLIBC_SEARCH_hsearch_data *__htab); void _win_hdestroy_r (struct PLIBC_SEARCH_hsearch_data *__htab); /* The tsearch routines are very interesting. They make many assumptions about the compiler. It assumes that the first field in node must be the "key" field, which points to the datum. Everything depends on that. */ /* For tsearch */ typedef enum { PLIBC_SEARCH_preorder, PLIBC_SEARCH_postorder, PLIBC_SEARCH_endorder, PLIBC_SEARCH_leaf } PLIBC_SEARCH_VISIT; /* Search for an entry matching the given KEY in the tree pointed to by *ROOTP and insert a new element if not found. */ void *_win_tsearch (__const void *__key, void **__rootp, PLIBC_SEARCH__compar_fn_t __compar); /* Search for an entry matching the given KEY in the tree pointed to by *ROOTP. If no matching entry is available return NULL. */ void *_win_tfind (__const void *__key, void *__const *__rootp, PLIBC_SEARCH__compar_fn_t __compar); /* Remove the element matching KEY from the tree pointed to by *ROOTP. */ void *_win_tdelete (__const void *__restrict __key, void **__restrict __rootp, PLIBC_SEARCH__compar_fn_t __compar); typedef void (*PLIBC_SEARCH__action_fn_t) (__const void *__nodep, PLIBC_SEARCH_VISIT __value, int __level); /* Walk through the whole tree and call the ACTION callback for every node or leaf. */ void _win_twalk (__const void *__root, PLIBC_SEARCH__action_fn_t __action); /* Callback type for function to free a tree node. If the keys are atomic data this function should do nothing. */ typedef void (*PLIBC_SEARCH__free_fn_t) (void *__nodep); /* Destroy the whole tree, call FREEFCT for each node or leaf. */ void _win_tdestroy (void *__root, PLIBC_SEARCH__free_fn_t __freefct); /* Perform linear search for KEY by comparing by COMPAR in an array [BASE,BASE+NMEMB*SIZE). */ void *_win_lfind (__const void *__key, __const void *__base, size_t *__nmemb, size_t __size, PLIBC_SEARCH__compar_fn_t __compar); /* Perform linear search for KEY by comparing by COMPAR function in array [BASE,BASE+NMEMB*SIZE) and insert entry if not found. */ void *_win_lsearch (__const void *__key, void *__base, size_t *__nmemb, size_t __size, PLIBC_SEARCH__compar_fn_t __compar); #ifdef __cplusplus } #endif #endif //_PLIBC_H_ /* end of plibc.h */ gnunet-0.10.1/src/include/gnunet_ats_plugin.h0000644000175000017500000003245412236662246016143 00000000000000/* This file is part of GNUnet (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_ats_plugin.h * @brief API for the ATS solvers. This header * specifies the struct that is given to the plugin's entry * method and the other struct that must be returned. * Note that the destructors of ATS plugins will * be given the value returned by the constructor * and is expected to return a NULL pointer. * @author Christian Grothoff */ #ifndef PLUGIN_ATS_H #define PLUGIN_ATS_H #include "gnunet_ats_service.h" #include "gnunet_statistics_service.h" struct ATS_Address; /* * Solver API * ---------- */ /** * Change the preference for a peer * * @param handle the solver handle * @param client the client sending this request * @param peer the peer id * @param kind the preference kind to change * @param score the new preference score * @param pref_rel the normalized preference value for this kind over all clients */ typedef void (*GAS_solver_address_change_preference) (void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel); /** * Give feedback about the current assignment * * @param handle the solver handle * @param application the application sending this request * @param peer the peer id * @param scope the time interval for this feedback: [now - scope .. now] * @param kind the preference kind for this feedback * @param score the feedback score */ typedef void (*GAS_solver_address_feedback_preference) (void *solver, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score); /** * Notify the solver about a bulk operation changing possibly a lot of values * Solver will not resolve until all bulk operations are marked as done * * @param solver the solver */ typedef void (*GAS_solver_bulk_start) (void *solver); /** * Mark a bulk operation as done * Solver will resolve if values have changed * * @param solver the solver */ typedef void (*GAS_solver_bulk_stop) (void *solver); /** * Add a single address within a network to the solver * * @param solver the solver Handle * @param addresses the address hashmap containing all addresses * @param address the address to add * @param network network type of this address */ typedef void (*GAS_solver_address_add) (void *solver, struct ATS_Address *address, uint32_t network); /** * Delete an address or just the session from the solver * * @param solver the solver Handle * @param addresses the address hashmap containing all addresses * @param address the address to delete * @param session_only remove address or just session */ typedef void (*GAS_solver_address_delete) (void *solver, struct ATS_Address *address, int session_only); /** * Transport properties for this address have changed * * @param solver solver handle * @param address the address * @param type the ATSI type in HBO * @param abs_value the absolute value of the property * @param rel_value the normalized value */ typedef void (*GAS_solver_address_property_changed) (void *solver, struct ATS_Address *address, uint32_t type, uint32_t abs_value, double rel_value); /** * Transport session for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param cur_session the current session * @param new_session the new session */ typedef void (*GAS_solver_address_session_changed) (void *solver, struct ATS_Address *address, uint32_t cur_session, uint32_t new_session); /** * Transport session for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param in_use usage state */ typedef void (*GAS_solver_address_inuse_changed) (void *solver, struct ATS_Address *address, int in_use); /** * Network scope for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param current_network the current network * @param new_network the new network */ typedef void (*GAS_solver_address_network_changed) (void *solver, struct ATS_Address *address, uint32_t current_network, uint32_t new_network); /** * Get the prefered address for a peer from solver * * @param solver the solver to use * @param addresses the address hashmap containing all addresses * @param peer the peer */ typedef const struct ATS_Address * (*GAS_solver_get_preferred_address) (void *solver, const struct GNUNET_PeerIdentity *peer); /** * Stop getting the prefered address for a peer from solver * * @param solver the solver to use * @param addresses the address hashmap containing all addresses * @param peer the peer */ typedef void (*GAS_solver_stop_get_preferred_address) (void *solver, const struct GNUNET_PeerIdentity *peer); /** * Solver functions * * Each solver is required to set up this struct contained in the plugin * environment struct in during startup */ struct GNUNET_ATS_SolverFunctions { /** * Add a new address for a peer to the solver * * The address is already contained in the addresses hashmap! */ GAS_solver_address_add s_add; /** * Update the properties of an address in the solver */ GAS_solver_address_property_changed s_address_update_property; /** * Update the session of an address in the solver */ GAS_solver_address_session_changed s_address_update_session; /** * Notify the solver that in address is (not) actively used by transport * to communicate with a remote peer */ GAS_solver_address_inuse_changed s_address_update_inuse; /** * Notify solver that the network an address is located in has changed */ GAS_solver_address_network_changed s_address_update_network; /** * Tell solver to notify ATS if the address to use changes for a specific * peer using the bandwidth changed callback * * The solver must only notify about changes for peers with pending address * requests! */ GAS_solver_get_preferred_address s_get; /** * Tell solver stop notifying ATS about changes for this peers * * The solver must only notify about changes for peers with pending address * requests! */ GAS_solver_stop_get_preferred_address s_get_stop; /** * Delete an address in the solver * * The address is not contained in the address hashmap anymore! */ GAS_solver_address_delete s_del; /** * Change relative preference for quality in solver */ GAS_solver_address_change_preference s_pref; /** * Give feedback about the current assignment */ GAS_solver_address_feedback_preference s_feedback; /** * Start a bulk operation * * Used if many values have to be updated at the same time. * When a bulk operation is pending the solver does not have to resolve * the problem since more updates will follow anyway * * For each call to bulk_start, a call to bulk_stop is required! */ GAS_solver_bulk_start s_bulk_start; /** * Bulk operation done * * If no more bulk operations are pending, the solver can solve the problem * with the updated values */ GAS_solver_bulk_stop s_bulk_stop; }; /** * Operation codes for solver information callback * * Order of calls is expected to be: * GAS_OP_SOLVE_START * * GAS_OP_SOLVE_STOP * GAS_OP_SOLVE_UPDATE_NOTIFICATION_START * GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP * */ enum GAS_Solver_Operation { /** * A solution iteration has been started */ GAS_OP_SOLVE_START, /** * A solution iteration has been finished */ GAS_OP_SOLVE_STOP, /** * The setup of the problem as a preparation to solve it was started */ GAS_OP_SOLVE_SETUP_START, /** * The setup of the problem as a preparation to solve is finished */ GAS_OP_SOLVE_SETUP_STOP, /** * Solving of the LP problem was started * MLP solver only */ GAS_OP_SOLVE_MLP_LP_START, /** * Solving of the LP problem is done * MLP solver only */ GAS_OP_SOLVE_MLP_LP_STOP, /** * Solving of the MLP problem was started * MLP solver only */ GAS_OP_SOLVE_MLP_MLP_START, /** * Solving of the MLP problem is done * MLP solver only */ GAS_OP_SOLVE_MLP_MLP_STOP, /** * After the problem was finished, start notifications about changes * to addresses */ GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, /** * After the problem was finished, notifications about changes to addresses * are done */ GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP }; /** * Status of a GAS_Solver_Operation operation */ enum GAS_Solver_Status { /** * Success */ GAS_STAT_SUCCESS, /** * Failure */ GAS_STAT_FAIL }; /** * Status of the operation */ enum GAS_Solver_Additional_Information { /** * No more specific information */ GAS_INFO_NONE, /** * A full solution process is performed * Quite specific to the MLP solver */ GAS_INFO_FULL, /** * An existing solution was reused * Quite specific to the MLP solver */ GAS_INFO_UPDATED, /** * The proportional solver had to recalculate for a single network */ GAS_INFO_PROP_SINGLE, /** * The proportional solver had to recalculate for all networks */ GAS_INFO_PROP_ALL }; /** * Callback to call with additional information * Used for measurement * * @param cls the closure * @param op the operation * @param peer the peer id * @param kind the preference kind to change * @param score the new preference score * @param pref_rel the normalized preference value for this kind over all clients */ typedef void (*GAS_solver_information_callback) (void *cls, enum GAS_Solver_Operation op, enum GAS_Solver_Status stat, enum GAS_Solver_Additional_Information); /** * Callback to call from solver when bandwidth for address has changed * * @param address the with changed bandwidth assigned */ typedef void (*GAS_bandwidth_changed_cb) (void *cls, struct ATS_Address *address); /** * Callback to call from solver to obtain application preference values for a * peer * * @param cls the cls * @param id the peer id * @return carry of double values containing the preferences with * GNUNET_ATS_PreferenceCount elements */ typedef const double * (*GAS_get_preferences) (void *cls, const struct GNUNET_PeerIdentity *id); /** * Callback to call from solver to obtain transport properties for an * address * * @param cls the cls * @param address the address * @return carry of double values containing the preferences with * GNUNET_ATS_PreferenceCount elements */ typedef const double * (*GAS_get_properties) (void *cls, const struct ATS_Address *address); /** * The ATS service will pass a pointer to a struct * of this type as the first and only argument to the * entry point of each ATS solver. */ struct GNUNET_ATS_PluginEnvironment { /** * Configuration handle to be used by the solver */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Statistics handle to be used by the solver */ const struct GNUNET_STATISTICS_Handle *stats; /** * Hashmap containing all addresses available */ struct GNUNET_CONTAINER_MultiPeerMap *addresses; /** * ATS addresses callback to be notified about bandwidth assignment changes */ GAS_bandwidth_changed_cb bandwidth_changed_cb; /** * ATS addresses closure to be notified about bandwidth assignment changes */ void *bw_changed_cb_cls; /** * ATS addresses function to obtain preference values */ GAS_get_preferences get_preferences; /** * ATS addresses function closure to obtain preference values */ void *get_preference_cls; /** * ATS addresses function to obtain property values */ GAS_get_properties get_property; /** * ATS addresses function closure to obtain property values */ void *get_property_cls; /** * Callback for solver to call with status information, * can be NULL */ GAS_solver_information_callback info_cb; /** * Closure for information callback, * can be NULL */ void *info_cb_cls; /** * The ATS solver plugin functions to call */ struct GNUNET_ATS_SolverFunctions sf; /** * Available networks */ int networks[GNUNET_ATS_NetworkTypeCount]; /** * Number of networks available */ int network_count; /** * Array of configured outbound quotas * Order according to networks in network array */ unsigned long long out_quota[GNUNET_ATS_NetworkTypeCount]; /** * Array of configured inbound quotas * Order according to networks in network array */ unsigned long long in_quota[GNUNET_ATS_NetworkTypeCount]; }; #endif gnunet-0.10.1/src/include/gnunet_core_service.h0000644000175000017500000003174412272517717016451 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_core_service.h * @brief core service; this is the main API for encrypted P2P * communications * @author Christian Grothoff * @defgroup core encrypted direct communication between peers * @{ */ #ifndef GNUNET_CORE_SERVICE_H #define GNUNET_CORE_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" /** * Version number of GNUnet-core API. */ #define GNUNET_CORE_VERSION 0x00000001 /** * Traffic priorities. */ enum GNUNET_CORE_Priority { /** * Lowest priority, i.e. background traffic (i.e. fs) */ GNUNET_CORE_PRIO_BACKGROUND = 0, /** * Normal traffic (i.e. mesh/dv relay, DHT) */ GNUNET_CORE_PRIO_BEST_EFFORT = 1, /** * Urgent traffic (local peer, i.e. conversation). */ GNUNET_CORE_PRIO_URGENT = 2, /** * Highest priority, control traffic (i.e. NSE, Core/Mesh KX). */ GNUNET_CORE_PRIO_CRITICAL_CONTROL = 3 }; /** * Opaque handle to the service. */ struct GNUNET_CORE_Handle; /** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about */ typedef void (*GNUNET_CORE_ConnectEventHandler) (void *cls, const struct GNUNET_PeerIdentity *peer); /** * Method called whenever a peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ typedef void (*GNUNET_CORE_DisconnectEventHandler) (void *cls, const struct GNUNET_PeerIdentity *peer); /** * Functions with this signature are called whenever a message is * received or transmitted. * * @param cls closure (set from #GNUNET_CORE_connect) * @param peer the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close connection to the peer (signal serious error) */ typedef int (*GNUNET_CORE_MessageCallback) (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message); /** * Message handler. Each struct specifies how to handle on particular * type of message received. */ struct GNUNET_CORE_MessageHandler { /** * Function to call for messages of @e type. */ GNUNET_CORE_MessageCallback callback; /** * Type of the message this handler covers. */ uint16_t type; /** * Expected size of messages of this type. Use 0 for variable-size. * If non-zero, messages of the given type will be discarded if they * do not have the right size. */ uint16_t expected_size; }; /** * Function called after #GNUNET_CORE_connect has succeeded (or failed * for good). Note that the private key of the peer is intentionally * not exposed here; if you need it, your process should try to read * the private key file directly (which should work if you are * authorized...). Implementations of this function must not call * #GNUNET_CORE_disconnect (other than by scheduling a new task to * do this later). * * @param cls closure * @param my_identity ID of this peer, NULL if we failed */ typedef void (*GNUNET_CORE_StartupCallback) (void *cls, const struct GNUNET_PeerIdentity *my_identity); /** * Connect to the core service. Note that the connection may complete * (or fail) asynchronously. This function primarily causes the given * callback notification functions to be invoked whenever the * specified event happens. The maximum number of queued * notifications (queue length) is per client; the queue is shared * across all types of notifications. So a slow client that registers * for @a outbound_notify also risks missing @a inbound_notify messages. * Certain events (such as connect/disconnect notifications) are not * subject to queue size limitations. * * @param cfg configuration to use * @param cls closure for the various callbacks that follow (including handlers in the handlers array) * @param init callback to call once we have successfully * connected to the core service * @param connects function to call on peer connect, can be NULL * @param disconnects function to call on peer disconnect / timeout, can be NULL * @param inbound_notify function to call for all inbound messages, can be NULL * note that the core is allowed to drop notifications about inbound * messages if the client does not process them fast enough (for this * notification type, a bounded queue is used) * @param inbound_hdr_only set to #GNUNET_YES if @a inbound_notify will only read the * `struct GNUNET_MessageHeader` and hence we do not need to give it the full message; * can be used to improve efficiency, ignored if inbound_notify is NULL * note that the core is allowed to drop notifications about inbound * messages if the client does not process them fast enough (for this * notification type, a bounded queue is used) * @param outbound_notify function to call for all outbound messages, can be NULL; * note that the core is allowed to drop notifications about outbound * messages if the client does not process them fast enough (for this * notification type, a bounded queue is used) * @param outbound_hdr_only set to #GNUNET_YES if @a outbound_notify will only read the * `struct GNUNET_MessageHeader` and hence we do not need to give it the full message * can be used to improve efficiency, ignored if outbound_notify is NULL * note that the core is allowed to drop notifications about outbound * messages if the client does not process them fast enough (for this * notification type, a bounded queue is used) * @param handlers callbacks for messages we care about, NULL-terminated * note that the core is allowed to drop notifications about inbound * messages if the client does not process them fast enough (for this * notification type, a bounded queue is used) * @return handle to the core service (only useful for disconnect until @a init is called), * NULL on error (in this case, init is never called) */ struct GNUNET_CORE_Handle * GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_CORE_StartupCallback init, GNUNET_CORE_ConnectEventHandler connects, GNUNET_CORE_DisconnectEventHandler disconnects, GNUNET_CORE_MessageCallback inbound_notify, int inbound_hdr_only, GNUNET_CORE_MessageCallback outbound_notify, int outbound_hdr_only, const struct GNUNET_CORE_MessageHandler *handlers); /** * Disconnect from the core service. This function can only * be called *after* all pending #GNUNET_CORE_notify_transmit_ready * requests have been explicitly cancelled. * * @param handle connection to core to disconnect */ void GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle); /** * Handle for a transmission request. */ struct GNUNET_CORE_TransmitHandle; /** * Ask the core to call @a notify once it is ready to transmit the * given number of bytes to the specified @a target. Must only be * called after a connection to the respective peer has been * established (and the client has been informed about this). You may * have one request of this type pending for each connected peer at * any time. If a peer disconnects, the application MUST call * #GNUNET_CORE_notify_transmit_ready_cancel on the respective * transmission request, if one such request is pending. * * @param handle connection to core service * @param cork is corking allowed for this transmission? * @param priority how important is the message? * @param maxdelay how long can the message wait? Only effective if @a cork is #GNUNET_YES * @param target who should receive the message, never NULL (can be this peer's identity for loopback) * @param notify_size how many bytes of buffer space does notify want? * @param notify function to call when buffer space is available; * will be called with NULL on timeout; clients MUST cancel * all pending transmission requests DURING the disconnect * handler * @param notify_cls closure for @a notify * @return non-NULL if the notify callback was queued, * NULL if we can not even queue the request (request already pending); * if NULL is returned, "notify" will NOT be called. */ struct GNUNET_CORE_TransmitHandle * GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, int cork, enum GNUNET_CORE_Priority priority, struct GNUNET_TIME_Relative maxdelay, const struct GNUNET_PeerIdentity *target, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls); /** * Cancel the specified transmission-ready notification. * * @param th handle that was returned by "notify_transmit_ready". */ void GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle *th); /** * Iterate over all connected peers. Calls @a peer_cb with each * connected peer, and then once with NULL to indicate that all peers * have been handled. Normal users of the CORE API are not expected * to use this function. It is different in that it truly lists * all connections, not just those relevant to the application. This * function is used by special applications for diagnostics. This * function is NOT part of the 'versioned', 'official' API. * * FIXME: we should probably make it possible to 'cancel' the * operation... * * @param cfg configuration handle * @param peer_cb function to call with the peer information * @param cb_cls closure for @a peer_cb * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors */ int GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CORE_ConnectEventHandler peer_cb, void *cb_cls); /** * Check if the given peer is currently connected. This function is for special * cirumstances (GNUNET_TESTBED uses it), normal users of the CORE API are * expected to track which peers are connected based on the connect/disconnect * callbacks from #GNUNET_CORE_connect. This function is NOT part of the * 'versioned', 'official' API. This function returns * synchronously after looking in the CORE API cache. * * @param h the core handle * @param pid the identity of the peer to check if it has been connected to us * @return #GNUNET_YES if the peer is connected to us; #GNUNET_NO if not */ int GNUNET_CORE_is_peer_connected_sync (const struct GNUNET_CORE_Handle *h, const struct GNUNET_PeerIdentity *pid); /** * Create a message queue for sending messages to a peer with CORE. * Messages may only be queued with #GNUNET_MQ_send once the init callback has * been called for the given handle. * There must only be one queue per peer for each core handle. * The message queue can only be used to transmit messages, * not to receive them. * * @param h the core handle * @param target the target peer for this queue, may not be NULL * @return a message queue for sending messages over the core handle * to the target peer */ struct GNUNET_MQ_Handle * GNUNET_CORE_mq_create (struct GNUNET_CORE_Handle *h, const struct GNUNET_PeerIdentity *target); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group core */ /* ifndef GNUNET_CORE_SERVICE_H */ #endif /* end of gnunet_core_service.h */ gnunet-0.10.1/src/include/gnunet_transport_service.h0000644000175000017500000007272412320466615017552 00000000000000/* This file is part of GNUnet. (C) 2009-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_transport_service.h * @brief low-level P2P IO * @author Christian Grothoff */ #ifndef GNUNET_TRANSPORT_SERVICE_H #define GNUNET_TRANSPORT_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" #include "gnunet_ats_service.h" /** * Version number of the transport API. */ #define GNUNET_TRANSPORT_VERSION 0x00000001 /** * Possible state of a neighbour. Initially, we are #GNUNET_TRANSPORT_PS_NOT_CONNECTED. * * Then, there are two main paths. If we receive a CONNECT message, we give * the inbound address to ATS. After the check we ask ATS for a suggestion * (#GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS). If ATS makes a suggestion, we * send our CONNECT_ACK and go to #GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK. * If we receive a SESSION_ACK, we go to #GNUNET_TRANSPORT_PS_CONNECTED * (and notify everyone about the new connection). If the operation times out, * we go to #GNUNET_TRANSPORT_PS_DISCONNECT. * * The other case is where we transmit a CONNECT message first. We * start with #GNUNET_TRANSPORT_PS_INIT_ATS. If we get an address, we send * the CONNECT message and go to state #GNUNET_TRANSPORT_PS_CONNECT_SENT. * Once we receive a CONNECT_ACK, we go to #GNUNET_TRANSPORT_PS_CONNECTED * (and notify everyone about the new connection and send * back a SESSION_ACK). If the operation times out, we go to * #GNUNET_TRANSPORT_PS_DISCONNECT. * * If the session is in trouble (i.e. transport-level disconnect or * timeout), we go to #GNUNET_TRANSPORT_PS_RECONNECT_ATS where we ask ATS for a new * address (we don't notify anyone about the disconnect yet). Once we * have a new address, we enter #GNUNET_TRANSPORT_PS_RECONNECT_SENT and send a * CONNECT message. If we receive a * CONNECT_ACK, we go to #GNUNET_TRANSPORT_PS_CONNECTED and nobody noticed that we had * trouble; we also send a SESSION_ACK at this time just in case. If * the operation times out, we go to #GNUNET_TRANSPORT_PS_DISCONNECT (and notify everyone * about the lost connection). * * If ATS decides to switch addresses while we have a normal * connection, we go to #GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT * and send a SESSION_CONNECT. If we get a SESSION_ACK back, we switch the * primary connection to the suggested alternative from ATS, go back * to #GNUNET_TRANSPORT_PS_CONNECTED and send a SESSION_ACK to the other peer just to be * sure. If the operation times out * we go to #GNUNET_TRANSPORT_PS_CONNECTED (and notify ATS that the given alternative * address is "invalid"). * * Once a session is in #GNUNET_TRANSPORT_PS_DISCONNECT, it is cleaned up and then goes * to (#GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED). If we receive an explicit disconnect * request, we can go from any state to #GNUNET_TRANSPORT_PS_DISCONNECT, possibly after * generating disconnect notifications. * * Note that it is quite possible that while we are in any of these * states, we could receive a 'CONNECT' request from the other peer. * We then enter a 'weird' state where we pursue our own primary state * machine (as described above), but with the 'send_connect_ack' flag * set to 1. If our state machine allows us to send a 'CONNECT_ACK' * (because we have an acceptable address), we send the 'CONNECT_ACK' * and set the 'send_connect_ack' to 2. If we then receive a * 'SESSION_ACK', we go to #GNUNET_TRANSPORT_PS_CONNECTED (and reset 'send_connect_ack' * to 0). * */ enum GNUNET_TRANSPORT_PeerState { /** * Fresh peer or completely disconnected */ GNUNET_TRANSPORT_PS_NOT_CONNECTED = 0, /** * Asked to initiate connection, trying to get address from ATS */ GNUNET_TRANSPORT_PS_INIT_ATS, /** * Sent CONNECT message to other peer, waiting for CONNECT_ACK */ GNUNET_TRANSPORT_PS_CONNECT_SENT, /** * Received a CONNECT, asking ATS about address suggestions. */ GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS, /** * CONNECT request from other peer was CONNECT_ACK'ed, waiting for * SESSION_ACK. */ GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK, /** * Got our CONNECT_ACK/SESSION_ACK, connection is up. */ GNUNET_TRANSPORT_PS_CONNECTED, /** * Connection got into trouble, rest of the system still believes * it to be up, but we're getting a new address from ATS. */ GNUNET_TRANSPORT_PS_RECONNECT_ATS, /** * Sent CONNECT over new address (either by ATS telling us to switch * addresses or from RECONNECT_ATS); if this fails, we need to tell * the rest of the system about a disconnect. */ GNUNET_TRANSPORT_PS_RECONNECT_SENT, /** * We have some primary connection, but ATS suggested we switch * to some alternative; we now sent a CONNECT message for the * alternative session to the other peer and waiting for a * CONNECT_ACK to make this our primary connection. */ GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT, /** * Disconnect in progress (we're sending the DISCONNECT message to the * other peer; after that is finished, the state will be cleaned up). */ GNUNET_TRANSPORT_PS_DISCONNECT, /** * We're finished with the disconnect; and are cleaning up the state * now! We put the struct into this state when we are really in the * task that calls 'free' on it and are about to remove the record * from the map. We should never find a 'struct NeighbourMapEntry' * in this state in the map. Accessing a 'struct NeighbourMapEntry' * in this state virtually always means using memory that has been * freed (the exception being the cleanup code in #free_neighbour()). */ GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED }; /** * Current state of a validation process */ enum GNUNET_TRANSPORT_ValidationState { /** * Undefined state * * Used for final callback indicating operation done */ GNUNET_TRANSPORT_VS_NONE, /** * Fresh validation entry * * Entry was just created, no validation process was executed */ GNUNET_TRANSPORT_VS_NEW, /** * Updated validation entry * * This is an update for an existing validation entry */ GNUNET_TRANSPORT_VS_UPDATE, /** * Timeout for validation entry * * A timeout occured during the validation process */ GNUNET_TRANSPORT_VS_TIMEOUT, /** * Validation entry is removed * * The validation entry is getting removed due to a failed validation */ GNUNET_TRANSPORT_VS_REMOVE }; /** * Function called by the transport for each received message. * * @param cls closure * @param peer (claimed) identity of the other peer * @param message the message * @param ats performance data * @param ats_count number of entries in @a ats */ typedef void (*GNUNET_TRANSPORT_ReceiveCallback) (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Opaque handle to the service. */ struct GNUNET_TRANSPORT_Handle; /** * Function called to notify transport users that another * peer connected to us. * * @param cls closure * @param peer the peer that connected * @param ats performance data * @param ats_count number of entries in @a ats (excluding 0-termination) */ typedef void (*GNUNET_TRANSPORT_NotifyConnect) (void *cls, const struct GNUNET_PeerIdentity *peer); /** * Function called to notify transport users that another * peer disconnected from us. * * @param cls closure * @param peer the peer that disconnected */ typedef void (*GNUNET_TRANSPORT_NotifyDisconnect) (void *cls, const struct GNUNET_PeerIdentity *peer); /** * Function to call with result of the try connect request. * * * @param cls closure * @param result #GNUNET_OK if message was transmitted to transport service * #GNUNET_SYSERR if message was not transmitted to transport service */ typedef void (*GNUNET_TRANSPORT_TryConnectCallback) (void *cls, const int result); /** * Function to call with a textual representation of an address. * This function will be called several times with different possible * textual representations, and a last time with NULL to signal the end * of the iteration. * * @param cls closure * @param address NULL on error or end of iteration, * otherwise 0-terminated printable UTF-8 string */ typedef void (*GNUNET_TRANSPORT_AddressToStringCallback) (void *cls, const char *address); /** * Function to call with information about a peer * * If one_shot was set to #GNUNET_YES to iterate over all peers once, * a final call with NULL for peer and address will follow when done. * In this case state and timeout do not contain valid values. * * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called from * within this function! * * * @param cls closure * @param peer peer this update is about, * NULL if this is the final last callback for a iteration operation * @param address address, NULL for disconnect notification in monitor mode * @param state current state this peer is in * @param state_timeout timeout for the current state of the peer */ typedef void (*GNUNET_TRANSPORT_PeerIterateCallback) (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout); /** * Function to call with validation information about a peer * * This function is called by the transport validation monitoring api to * indicate a change to a validation entry. The information included represent * the current state of the validation entry, * * If the monitoring was called with one_shot=GNUNET_YES, a final callback * with peer==NULL and address==NULL is executed. * * @param cls closure * @param peer peer this update is about, * NULL if this is the final last callback for a iteration operation * @param address address, * NULL for disconnect notification in monitor mode * @param last_validation when was this address last validated * @param valid_until when does this address expire * @param next_validation time of the next validation operation * @param state state in the validation state machine */ typedef void (*GNUNET_TRANSPORT_ValidationIterateCallback) (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state); /** * Connect to the transport service. Note that the connection may * complete (or fail) asynchronously. * * @param cfg configuration to use * @param self our own identity (API should check that it matches * the identity found by transport), or NULL (no check) * @param cls closure for the callbacks * @param rec receive function to call, or NULL * @param nc function to call on connect events, or NULL * @param nd function to call on disconnect events, or NULL * @return NULL on error */ struct GNUNET_TRANSPORT_Handle * GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, void *cls, GNUNET_TRANSPORT_ReceiveCallback rec, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd); /** * Function called if we have "excess" bandwidth to a peer. * The notification will happen the first time we have excess * bandwidth, and then only again after the client has performed * some transmission to the peer. * * Excess bandwidth is defined as being allowed (by ATS) to send * more data, and us reaching the limit of the capacity build-up * (which, if we go past it, means we don't use available bandwidth). * See also the "max carry" in `struct GNUNET_BANDWIDTH_Tracker`. * * @param cls the closure * @param peer peer that we have excess bandwidth to */ typedef void (*GNUNET_TRANSPORT_NotifyExcessBandwidth)(void *cls, const struct GNUNET_PeerIdentity *neighbour); /** * Connect to the transport service. Note that the connection may * complete (or fail) asynchronously. * * @param cfg configuration to use * @param self our own identity (API should check that it matches * the identity found by transport), or NULL (no check) * @param cls closure for the callbacks * @param rec receive function to call, or NULL * @param nc function to call on connect events, or NULL * @param nd function to call on disconnect events, or NULL * @param neb function to call if we have excess bandwidth to a peer * @return NULL on error */ struct GNUNET_TRANSPORT_Handle * GNUNET_TRANSPORT_connect2 (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, void *cls, GNUNET_TRANSPORT_ReceiveCallback rec, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd, GNUNET_TRANSPORT_NotifyExcessBandwidth neb); /** * Disconnect from the transport service. * * @param handle handle returned from connect */ void GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle); /** * Opaque handle for a transmission-ready request. */ struct GNUNET_TRANSPORT_TryConnectHandle; /** * Ask the transport service to establish a connection to * the given peer. * * @param handle connection to transport service * @param target who we should try to connect to * @param cb callback to be called when request was transmitted to transport * service * @param cb_cls closure for the callback @a cb * @return a `struct GNUNET_TRANSPORT_TryConnectHandle` handle or * NULL on failure (@a cb will not be called) */ struct GNUNET_TRANSPORT_TryConnectHandle * GNUNET_TRANSPORT_try_connect (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *target, GNUNET_TRANSPORT_TryConnectCallback cb, void *cb_cls); /** * Cancel the request to transport to try a connect * Callback will not be called * * @param tch GNUNET_TRANSPORT_TryConnectHandle handle to cancel */ void GNUNET_TRANSPORT_try_connect_cancel (struct GNUNET_TRANSPORT_TryConnectHandle *tch); /** * Ask the transport service to establish a disconnect from * the given peer. * * @param handle connection to transport service * @param target who we should try to disconnect from * @param cb callback to be called when request was transmitted to transport * service * @param cb_cls closure for the callback @a cb * @return a `struct GNUNET_TRANSPORT_TryConnectHandle` handle or * NULL on failure (@a cb will not be called) */ struct GNUNET_TRANSPORT_TryConnectHandle * GNUNET_TRANSPORT_try_disconnect (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *target, GNUNET_TRANSPORT_TryConnectCallback cb, void *cb_cls); /** * Cancel the request to transport to try a disconnect * Callback will not be called * * @param tch GNUNET_TRANSPORT_TryConnectHandle handle to cancel */ void GNUNET_TRANSPORT_try_disconnect_cancel (struct GNUNET_TRANSPORT_TryConnectHandle *tch); /** * Opaque handle for a transmission-ready request. */ struct GNUNET_TRANSPORT_TransmitHandle; /** * Function called to notify a client about the connection begin ready * to queue more data. @a buf will be NULL and @a size zero if the * connection was closed for writing in the meantime. * * @param cls closure * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ typedef size_t (*GNUNET_TRANSPORT_TransmitReadyNotify) (void *cls, size_t size, void *buf); /** * Check if we could queue a message of the given size for * transmission. The transport service will take both its internal * buffers and bandwidth limits imposed by the other peer into * consideration when answering this query. * * @param handle connection to transport service * @param target who should receive the message * @param size how big is the message we want to transmit? * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param notify function to call when we are ready to * send such a message * @param notify_cls closure for @a notify * @return NULL if someone else is already waiting to be notified * non-NULL if the notify callback was queued (can be used to cancel * using GNUNET_TRANSPORT_notify_transmit_ready_cancel) */ struct GNUNET_TRANSPORT_TransmitHandle * GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *target, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_TransmitReadyNotify notify, void *notify_cls); /** * Cancel the specified transmission-ready notification. * * @param th handle of the transmission notification request to cancel */ void GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct GNUNET_TRANSPORT_TransmitHandle *th); /** * Function called whenever there is an update to the * HELLO of this peer. * * @param cls closure * @param hello our updated HELLO */ typedef void (*GNUNET_TRANSPORT_HelloUpdateCallback) (void *cls, const struct GNUNET_MessageHeader *hello); /** * Handle to cancel a #GNUNET_TRANSPORT_get_hello() operation. */ struct GNUNET_TRANSPORT_GetHelloHandle; /** * Checks if a given peer is connected to us * * @param handle connection to transport service * @param peer the peer to check * @return #GNUNET_YES (connected) or #GNUNET_NO (disconnected) */ int GNUNET_TRANSPORT_check_peer_connected (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *peer); /** * Set transport metrics for a peer and a direction * * @param handle transport handle * @param peer the peer to set the metric for * @param inbound set inbound direction (#GNUNET_YES or #GNUNET_NO) * @param outbound set outbound direction (#GNUNET_YES or #GNUNET_NO) * @param ats the metric as ATS information * @param ats_count the number of metrics * * Supported ATS values: * #GNUNET_ATS_QUALITY_NET_DELAY (value in ms) * #GNUNET_ATS_QUALITY_NET_DISTANCE (value in count(hops)) * * Example * To enforce a delay of 10 ms for peer p1 in sending direction use: * * struct GNUNET_ATS_Information ats; * ats.type = ntohl (GNUNET_ATS_QUALITY_NET_DELAY); * ats.value = ntohl (10); * GNUNET_TRANSPORT_set_traffic_metric (th, p1, TM_SEND, &ats, 1); * * Note: * Delay restrictions in receiving direction will be enforced with * 1 message delay. */ void GNUNET_TRANSPORT_set_traffic_metric (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *peer, int inbound, int outbound, const struct GNUNET_ATS_Information *ats, size_t ats_count); /** * Obtain updates on changes to the HELLO message for this peer. The callback * given in this function is never called synchronously. * * @param handle connection to transport service * @param rec function to call with the HELLO * @param rec_cls closure for @a rec * @return handle to cancel the operation */ struct GNUNET_TRANSPORT_GetHelloHandle * GNUNET_TRANSPORT_get_hello (struct GNUNET_TRANSPORT_Handle *handle, GNUNET_TRANSPORT_HelloUpdateCallback rec, void *rec_cls); /** * Stop receiving updates about changes to our HELLO message. * * @param ghh handle to cancel */ void GNUNET_TRANSPORT_get_hello_cancel (struct GNUNET_TRANSPORT_GetHelloHandle *ghh); struct GNUNET_TRANSPORT_OfferHelloHandle; /** * Offer the transport service the HELLO of another peer. Note that * the transport service may just ignore this message if the HELLO is * malformed or useless due to our local configuration. * * @param handle connection to transport service * @param hello the hello message * @param cont continuation to call when HELLO has been sent, * tc reason #GNUNET_SCHEDULER_REASON_TIMEOUT for fail * tc reasong #GNUNET_SCHEDULER_REASON_READ_READY for success * @param cls closure for continuation * @return a GNUNET_TRANSPORT_OfferHelloHandle handle or NULL on failure, * in case of failure cont will not be called * */ struct GNUNET_TRANSPORT_OfferHelloHandle * GNUNET_TRANSPORT_offer_hello (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_MessageHeader *hello, GNUNET_SCHEDULER_Task cont, void *cls); /** * Cancel the request to transport to offer the HELLO message * * @param ohh the `struct GNUNET_TRANSPORT_OfferHelloHandle` to cancel */ void GNUNET_TRANSPORT_offer_hello_cancel (struct GNUNET_TRANSPORT_OfferHelloHandle *ohh); /** * Handle to cancel a pending address lookup. */ struct GNUNET_TRANSPORT_AddressToStringContext; /** * Convert a binary address into a human readable address. * * @param cfg configuration to use * @param address address to convert (binary format) * @param numeric should (IP) addresses be displayed in numeric form * (otherwise do reverse DNS lookup) * @param timeout how long is the lookup allowed to take at most * @param aluc function to call with the results * @param aluc_cls closure for @a aluc * @return handle to cancel the operation, NULL on error */ struct GNUNET_TRANSPORT_AddressToStringContext * GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HELLO_Address *address, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressToStringCallback aluc, void *aluc_cls); /** * Cancel request for address conversion. * * @param pic the context handle */ void GNUNET_TRANSPORT_address_to_string_cancel (struct GNUNET_TRANSPORT_AddressToStringContext *pic); /** * Convert a transport state to a human readable string. * * @param state the state */ const char * GNUNET_TRANSPORT_ps2s (enum GNUNET_TRANSPORT_PeerState state); /** * Check if a state is defined as connected * * @param state the state value * @return #GNUNET_YES or #GNUNET_NO */ int GNUNET_TRANSPORT_is_connected (enum GNUNET_TRANSPORT_PeerState state); /** * Convert validation state to human-readable string. * * @param state the state value * @return corresponding string */ const char * GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state); struct GNUNET_TRANSPORT_PeerMonitoringContext; /** * Return information about a specific peer or all peers currently known to * transport service once or in monitoring mode. To obtain information about * a specific peer, a peer identity can be passed. To obtain information about * all peers currently known to transport service, NULL can be passed as peer * identity. * * For each peer, the callback is called with information about the address used * to communicate with this peer, the state this peer is currently in and the * the current timeout for this state. * * Upon completion, the 'GNUNET_TRANSPORT_PeerIterateCallback' is called one * more time with 'NULL'. After this, the operation must no longer be * explicitly canceled. * * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the * the peer_callback! * * @param cfg configuration to use * @param peer a specific peer identity to obtain information for, * NULL for all peers * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL), * #GNUNET_NO to monitor peers continuously * @param timeout how long is the lookup allowed to take at most * @param peer_callback function to call with the results * @param peer_callback_cls closure for @a peer_callback */ struct GNUNET_TRANSPORT_PeerMonitoringContext * GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *peer, int one_shot, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_PeerIterateCallback peer_callback, void *peer_callback_cls); /** * Cancel request to monitor peers * * @param pic handle for the request to cancel */ void GNUNET_TRANSPORT_monitor_peers_cancel (struct GNUNET_TRANSPORT_PeerMonitoringContext *pic); struct GNUNET_TRANSPORT_ValidationMonitoringContext; /** * Return information about pending address validation operations for a specific * or all peers * * @param cfg configuration to use * @param peer a specific peer identity to obtain validation entries for, * NULL for all peers * @param one_shot #GNUNET_YES to return all entries and then end (with NULL+NULL), * #GNUNET_NO to monitor validation entries continuously * @param timeout how long is the lookup allowed to take at most * @param validation_callback function to call with the results * @param validation_callback_cls closure for @a validation_callback */ struct GNUNET_TRANSPORT_ValidationMonitoringContext * GNUNET_TRANSPORT_monitor_validation_entries (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *peer, int one_shot, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_ValidationIterateCallback validation_callback, void *validation_callback_cls); /** * Return information about all current pending validation operations * * @param vic handle for the request to cancel */ void GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic); /** * Handle for blacklisting peers. */ struct GNUNET_TRANSPORT_Blacklist; /** * Function that decides if a connection is acceptable or not. * * @param cls closure * @param pid peer to approve or disapproave * @return #GNUNET_OK if the connection is allowed, #GNUNET_SYSERR if not */ typedef int (*GNUNET_TRANSPORT_BlacklistCallback) (void *cls, const struct GNUNET_PeerIdentity * pid); /** * Install a blacklist callback. The service will be queried for all * existing connections as well as any fresh connections to check if * they are permitted. If the blacklisting callback is unregistered, * all hosts that were denied in the past will automatically be * whitelisted again. Cancelling the blacklist handle is also the * only way to re-enable connections from peers that were previously * blacklisted. * * @param cfg configuration to use * @param cb callback to invoke to check if connections are allowed * @param cb_cls closure for @a cb * @return NULL on error, otherwise handle for cancellation */ struct GNUNET_TRANSPORT_Blacklist * GNUNET_TRANSPORT_blacklist (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_TRANSPORT_BlacklistCallback cb, void *cb_cls); /** * Abort the blacklist. Note that this function is the only way for * removing a peer from the blacklist. * * @param br handle of the request that is to be cancelled */ void GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_TRANSPORT_SERVICE_H */ #endif /* end of gnunet_transport_service.h */ gnunet-0.10.1/src/include/Makefile.am0000644000175000017500000000466212320751520014265 00000000000000SUBDIRS = . gnunetincludedir = $(includedir)/gnunet if MINGW WINPROC = winproc.h endif EXTRA_DIST = \ gauger.h \ block_fs.h \ block_dns.h \ block_regex.h gnunetinclude_HEADERS = \ platform.h plibc.h $(WINPROC) gettext.h \ gnunet_applications.h \ gnunet_arm_service.h \ gnunet_ats_service.h \ gnunet_ats_plugin.h \ gnunet_bandwidth_lib.h \ gnunet_bio_lib.h \ gnunet_block_lib.h \ gnunet_block_plugin.h \ gnunet_client_lib.h \ gnunet_common.h \ gnunet_constants.h \ gnunet_configuration_lib.h \ gnunet_connection_lib.h \ gnunet_consensus_service.h \ gnunet_container_lib.h \ gnunet_conversation_service.h \ gnunet_core_service.h \ gnunet_crypto_lib.h \ gnunet_datacache_lib.h \ gnunet_datacache_plugin.h \ gnunet_datastore_service.h \ gnunet_datastore_plugin.h \ gnunet_dht_service.h \ gnunet_disk_lib.h \ gnunet_dnsparser_lib.h \ gnunet_dnsstub_lib.h \ gnunet_dns_service.h \ gnunet_dv_service.h \ gnunet_env_lib.h \ gnunet_fragmentation_lib.h \ gnunet_friends_lib.h \ gnunet_fs_service.h \ gnunet_getopt_lib.h \ gnunet_gns_service.h \ gnunet_gnsrecord_lib.h \ gnunet_gnsrecord_plugin.h \ gnunet_hello_lib.h \ gnunet_helper_lib.h \ gnunet_identity_service.h \ gnunet_load_lib.h \ gnunet_mesh_service.h \ gnunet_microphone_lib.h \ gnunet_multicast_service.h \ gnunet_mq_lib.h \ gnunet_mysql_lib.h \ gnunet_namecache_plugin.h \ gnunet_namecache_service.h \ gnunet_namestore_plugin.h \ gnunet_namestore_service.h \ gnunet_nat_lib.h \ gnunet_network_lib.h \ gnunet_nse_service.h \ gnunet_os_lib.h \ gnunet_peer_lib.h \ gnunet_peerinfo_service.h \ gnunet_plugin_lib.h \ gnunet_postgres_lib.h \ gnunet_psycstore_plugin.h \ gnunet_psycstore_service.h \ gnunet_psyc_service.h \ gnunet_program_lib.h \ gnunet_protocols.h \ gnunet_resolver_service.h \ gnunet_regex_service.h \ gnunet_revocation_service.h \ gnunet_scalarproduct_service.h \ gnunet_scheduler_lib.h \ gnunet_secretsharing_service.h \ gnunet_server_lib.h \ gnunet_service_lib.h \ gnunet_set_service.h \ gnunet_signal_lib.h \ gnunet_signatures.h \ gnunet_speaker_lib.h \ gnunet_statistics_service.h \ gnunet_strings_lib.h \ gnunet_testbed_service.h \ gnunet_testbed_logger_service.h \ gnunet_testing_lib.h \ gnunet_time_lib.h \ gnunet_transport_service.h \ gnunet_transport_plugin.h \ gnunet_tun_lib.h \ gnunet_util_lib.h \ gnunet_vpn_service.h gnunet-0.10.1/src/include/gnunet_mysql_lib.h0000644000175000017500000001442012225777503015763 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_mysql_lib.h * @brief library to help with access to a MySQL database * @author Christian Grothoff */ #ifndef GNUNET_MYSQL_LIB_H #define GNUNET_MYSQL_LIB_H #include "gnunet_util_lib.h" #include #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Mysql context. */ struct GNUNET_MYSQL_Context; /** * Handle for a prepared statement. */ struct GNUNET_MYSQL_StatementHandle; /** * Type of a callback that will be called for each * data set returned from MySQL. * * @param cls user-defined argument * @param num_values number of elements in values * @param values values returned by MySQL * @return GNUNET_OK to continue iterating, GNUNET_SYSERR to abort */ typedef int (*GNUNET_MYSQL_DataProcessor) (void *cls, unsigned int num_values, MYSQL_BIND * values); /** * Create a mysql context. * * @param cfg configuration * @param section configuration section to use to get MySQL configuration options * @return the mysql context */ struct GNUNET_MYSQL_Context * GNUNET_MYSQL_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section); /** * Destroy a mysql context. Also frees all associated prepared statements. * * @param mc context to destroy */ void GNUNET_MYSQL_context_destroy (struct GNUNET_MYSQL_Context *mc); /** * Close database connection and all prepared statements (we got a DB * error). The connection will automatically be re-opened and * statements will be re-prepared if they are needed again later. * * @param mc mysql context */ void GNUNET_MYSQL_statements_invalidate (struct GNUNET_MYSQL_Context *mc); /** * Get internal handle for a prepared statement. This function should rarely * be used, and if, with caution! On failures during the interaction with * the handle, you must call 'GNUNET_MYSQL_statements_invalidate'! * * @param mc mysql context * @param sh prepared statement to introspect * @return MySQL statement handle, NULL on error */ MYSQL_STMT * GNUNET_MYSQL_statement_get_stmt (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *sh); /** * Prepare a statement. Prepared statements are automatically discarded * when the MySQL context is destroyed. * * @param mc mysql context * @param query query text * @return prepared statement, NULL on error */ struct GNUNET_MYSQL_StatementHandle * GNUNET_MYSQL_statement_prepare (struct GNUNET_MYSQL_Context *mc, const char *query); /** * Run a SQL statement. * * @param mc mysql context * @param sql SQL statement to run * @return GNUNET_OK on success * GNUNET_SYSERR if there was a problem */ int GNUNET_MYSQL_statement_run (struct GNUNET_MYSQL_Context *mc, const char *sql); /** * Run a prepared SELECT statement. * * @param mc mysql context * @param sh handle to SELECT statment * @param result_size number of elements in results array * @param results pointer to already initialized MYSQL_BIND * array (of sufficient size) for passing results * @param processor function to call on each result * @param processor_cls extra argument to processor * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective * values (size + buffer-reference for pointers); terminated * with "-1" * @return GNUNET_SYSERR on error, otherwise * the number of successfully affected (or queried) rows */ int GNUNET_MYSQL_statement_run_prepared_select (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *sh, unsigned int result_size, MYSQL_BIND * results, GNUNET_MYSQL_DataProcessor processor, void *processor_cls, ...); /** * Run a prepared SELECT statement. * * @param mc mysql context * @param s statement to run * @param result_size number of elements in results array * @param results pointer to already initialized MYSQL_BIND * array (of sufficient size) for passing results * @param processor function to call on each result * @param processor_cls extra argument to processor * @param ap pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective * values (size + buffer-reference for pointers); terminated * with "-1" * @return GNUNET_SYSERR on error, otherwise * the number of successfully affected (or queried) rows */ int GNUNET_MYSQL_statement_run_prepared_select_va (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *s, unsigned int result_size, MYSQL_BIND * results, GNUNET_MYSQL_DataProcessor processor, void *processor_cls, va_list ap); /** * Run a prepared statement that does NOT produce results. * * @param mc mysql context * @param sh handle to statment * @param insert_id NULL or address where to store the row ID of whatever * was inserted (only for INSERT statements!) * @param ... pairs and triplets of "MYSQL_TYPE_XXX" keys and their respective * values (size + buffer-reference for pointers); terminated * with "-1" * @return GNUNET_SYSERR on error, otherwise * the number of successfully affected rows */ int GNUNET_MYSQL_statement_run_prepared (struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *sh, unsigned long long *insert_id, ...); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_mysql_lib.h */ #endif gnunet-0.10.1/src/include/gnunet_time_lib.h0000644000175000017500000003105112316473376015555 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_time_lib.h * @brief functions related to time * @author Christian Grothoff * @defgroup time Time and time calculations * @{ */ #ifndef GNUNET_TIME_LIB_H #define GNUNET_TIME_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_common.h" /** * Time for absolute times used by GNUnet, in microseconds. */ struct GNUNET_TIME_Absolute { /** * The actual value. */ uint64_t abs_value_us; }; /** * Time for relative time used by GNUnet, in microseconds. * Always positive, so we can only refer to future time. */ struct GNUNET_TIME_Relative { /** * The actual value. */ uint64_t rel_value_us; }; GNUNET_NETWORK_STRUCT_BEGIN /** * Time for relative time used by GNUnet, in microseconds and in network byte order. */ struct GNUNET_TIME_RelativeNBO { /** * The actual value (in network byte order). */ uint64_t rel_value_us__ GNUNET_PACKED; }; /** * Time for absolute time used by GNUnet, in microseconds and in network byte order. */ struct GNUNET_TIME_AbsoluteNBO { /** * The actual value (in network byte order). */ uint64_t abs_value_us__ GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /** * Relative time zero. */ #define GNUNET_TIME_UNIT_ZERO GNUNET_TIME_relative_get_zero_() /** * Absolute time zero. */ #define GNUNET_TIME_UNIT_ZERO_ABS GNUNET_TIME_absolute_get_zero_() /** * One microsecond, our basic time unit. */ #define GNUNET_TIME_UNIT_MICROSECONDS GNUNET_TIME_relative_get_unit_() /** * One millisecond. */ #define GNUNET_TIME_UNIT_MILLISECONDS GNUNET_TIME_relative_get_millisecond_() /** * One second. */ #define GNUNET_TIME_UNIT_SECONDS GNUNET_TIME_relative_get_second_() /** * One minute. */ #define GNUNET_TIME_UNIT_MINUTES GNUNET_TIME_relative_get_minute_() /** * One hour. */ #define GNUNET_TIME_UNIT_HOURS GNUNET_TIME_relative_get_hour_() /** * One day. */ #define GNUNET_TIME_UNIT_DAYS GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_HOURS, 24) /** * One week. */ #define GNUNET_TIME_UNIT_WEEKS GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_DAYS, 7) /** * One month (30 days). */ #define GNUNET_TIME_UNIT_MONTHS GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_DAYS, 30) /** * One year (365 days). */ #define GNUNET_TIME_UNIT_YEARS GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_DAYS, 365) /** * Constant used to specify "forever". This constant * will be treated specially in all time operations. */ #define GNUNET_TIME_UNIT_FOREVER_REL GNUNET_TIME_relative_get_forever_ () /** * Constant used to specify "forever". This constant * will be treated specially in all time operations. */ #define GNUNET_TIME_UNIT_FOREVER_ABS GNUNET_TIME_absolute_get_forever_ () /** * Threshold after which exponential backoff should not increase (15 m). */ #define GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) /** * Perform our standard exponential back-off calculation, starting at 1 ms * and then going by a factor of 2 up unto a maximum of 15 m. * * @param r current backoff time, initially zero */ #define GNUNET_TIME_STD_BACKOFF(r) GNUNET_TIME_relative_min (GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD, \ GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS, (r)), 2)); /** * Return relative time of 0ms. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_zero_ (void); /** * Return absolute time of 0ms. */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_zero_ (void); /** * Return relative time of 1 microsecond. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_unit_ (void); /** * Return relative time of 1ms. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_millisecond_ (void); /** * Return relative time of 1s. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_second_ (void); /** * Return relative time of 1 minute. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_minute_ (void); /** * Return relative time of 1 hour. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_hour_ (void); /** * Return "forever". */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_forever_ (void); /** * Return "forever". */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_forever_ (void); /** * Get the current time. * * @return the current time */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get (void); /** * Convert relative time to an absolute time in the * future. * * @param rel relative time to convert * @return timestamp that is "rel" in the future, or FOREVER if rel==FOREVER (or if we would overflow) */ struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel); /** * Return the minimum of two relative time values. * * @param t1 first timestamp * @param t2 other timestamp * @return timestamp that is smaller */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2); /** * Return the maximum of two relative time values. * * @param t1 first timestamp * @param t2 other timestamp * @return timestamp that is larger */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2); /** * Return the minimum of two absolute time values. * * @param t1 first timestamp * @param t2 other timestamp * @return timestamp that is smaller */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2); /** * Return the maximum of two absolute time values. * * @param t1 first timestamp * @param t2 other timestamp * @return timestamp that is smaller */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2); /** * Given a timestamp in the future, how much time * remains until then? * * @param future some absolute time, typically in the future * @return future - now, or 0 if now >= future, or FOREVER if future==FOREVER. */ struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future); /** * Calculate the estimate time of arrival/completion * for an operation. * * @param start when did the operation start? * @param finished how much has been done? * @param total how much must be done overall (same unit as for "finished") * @return remaining duration for the operation, * assuming it continues at the same speed */ struct GNUNET_TIME_Relative GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, uint64_t finished, uint64_t total); /** * Compute the time difference between the given start and end times. * Use this function instead of actual subtraction to ensure that * "FOREVER" and overflows are handeled correctly. * * @param start some absolute time * @param end some absolute time (typically larger or equal to start) * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start */ struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end); /** * Get the duration of an operation as the * difference of the current time and the given start time "hence". * * @param whence some absolute time, typically in the past * @return aborts if hence==FOREVER, 0 if hence > now, otherwise now-hence. */ struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence); /** * Add a given relative duration to the * given start time. * * @param start some absolute time * @param duration some relative time to add * @return FOREVER if either argument is FOREVER or on overflow; start+duration otherwise */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration); /** * Subtract a given relative duration from the * given start time. * * @param start some absolute time * @param duration some relative time to subtract * @return ZERO if start <= duration, or FOREVER if start time is FOREVER; start-duration otherwise */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration); /** * Multiply relative time by a given factor. * * @param rel some duration * @param factor integer to multiply with * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel, unsigned int factor); /** * Divide relative time by a given factor. * * @param rel some duration * @param factor integer to divide by * @return FOREVER if rel=FOREVER or factor==0; otherwise rel/factor */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel, unsigned int factor); /** * Add relative times together. * * @param a1 some relative time * @param a2 some other relative time * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2); /** * Subtract relative timestamp from the other. * * @param a1 first timestamp * @param a2 second timestamp * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2); /** * Convert relative time to network byte order. * * @param a time to convert * @return converted time value */ struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a); /** * Convert relative time from network byte order. * * @param a time to convert * @return converted time value */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a); /** * Convert absolute time to network byte order. * * @param a time to convert * @return converted time value */ struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a); /** * Convert absolute time from network byte order. * * @param a time to convert * @return converted time value */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a); /** * Set the timestamp offset for this instance. * * @param offset the offset to skew the locale time by */ void GNUNET_TIME_set_offset (long long offset); /** * Get the timestamp offset for this instance. * * @return the offset we currently skew the locale time by */ long long GNUNET_TIME_get_offset (void); /** * Return the current year (i.e. '2011'). */ unsigned int GNUNET_TIME_get_current_year (void); /** * Convert a year to an expiration time of January 1st of that year. * * @param year a year (after 1970, please ;-)). * @return absolute time for January 1st of that year. */ struct GNUNET_TIME_Absolute GNUNET_TIME_year_to_time (unsigned int year); /** * Convert an expiration time to the respective year (rounds) * * @param at absolute time * @return year a year (after 1970), 0 on error */ unsigned int GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group time */ /* ifndef GNUNET_TIME_LIB_H */ #endif /* end of gnunet_time_lib.h */ gnunet-0.10.1/src/include/gnunet_constants.h0000644000175000017500000001055412300637201015770 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_constants.h * @brief "global" constants for performance tuning * @author Christian Grothoff */ #ifndef GNUNET_CONSTANTS_H #define GNUNET_CONSTANTS_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Last resort choice for configuration file name. */ #define GNUNET_DEFAULT_USER_CONFIG_FILE "~/.config/gnunet.conf" /** * Bandwidth (in/out) to assume initially (before either peer has * communicated any particular preference). Should be rather low; set * so that at least one maximum-size message can be send roughly once * per minute. */ #define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT GNUNET_BANDWIDTH_value_init (1024) /** * After how long do we consider a connection to a peer dead * if we don't receive messages from the peer? */ #define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) /** * How long do we delay reading more from a peer after a quota violation? */ #define GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) /** * After how long do we consider a service unresponsive * even if we assume that the service commonly does not * respond instantly (DNS, Database, etc.). */ #define GNUNET_CONSTANTS_SERVICE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10) /** * How long do we delay messages to get larger packet sizes (CORKing)? */ #define GNUNET_CONSTANTS_MAX_CORK_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * Until which load do we consider the peer overly idle * (which means that we would like to use more resources).

* * Note that we use 70 to leave some room for applications * to consume resources "idly" (i.e. up to 85%) and then * still have some room for "paid for" resource consumption. */ #define GNUNET_CONSTANTS_IDLE_LOAD_THRESHOLD 70 /** * For how long do we allow unused bandwidth * from the past to carry over into the future? (in seconds) */ #define GNUNET_CONSTANTS_MAX_BANDWIDTH_CARRY_S 5 /** * After how long do we expire an address in a HELLO that we just * validated? This value is also used for our own addresses when we * create a HELLO. */ #define GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) /** * How long do we cache records at most in the DHT? */ #define GNUNET_CONSTANTS_DHT_MAX_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 24) /** * Size of the `struct EncryptedMessage` of the core (which * is the per-message overhead of the core). */ #define GNUNET_CONSTANTS_CORE_SIZE_ENCRYPTED_MESSAGE (24 + sizeof (struct GNUNET_HashCode)) /** * What is the maximum size for encrypted messages? Note that this * number imposes a clear limit on the maximum size of any message. * Set to a value close to 64k but not so close that transports will * have trouble with their headers. * * Could theoretically be 64k minus (#GNUNET_CONSTANTS_CORE_SIZE_ENCRYPTED_MESSAGE + * #GNUNET_CONSTANTS_TRANSPORT_SIZE_OUTBOUND_MESSAGE), but we're going * to be more conservative for now. */ #define GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE (63 * 1024) /** * Largest block that can be stored in the DHT. */ #define GNUNET_CONSTANTS_MAX_BLOCK_SIZE (62 * 1024) /** * K-value that must be used for the bloom filters in 'GET' * queries. */ #define GNUNET_CONSTANTS_BLOOMFILTER_K 16 #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_signatures.h0000644000175000017500000001001112262754601016137 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_signatures.h * @brief constants for network signatures * @author Christian Grothoff */ #ifndef GNUNET_SIGNATURES_H #define GNUNET_SIGNATURES_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Test signature, not valid for anything other than writing * a test. (Note that the signature verification code will * accept this value). */ #define GNUNET_SIGNATURE_PURPOSE_TEST 0 /** * Signature for confirming that this peer uses a particular address. */ #define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN 1 /** * Signature for confirming that this peer intends to disconnect. */ #define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DISCONNECT 2 /** * Signature for confirming a key revocation. */ #define GNUNET_SIGNATURE_PURPOSE_REVOCATION 3 /** * Signature for a namespace/pseudonym advertisement (by * the namespace owner). */ #define GNUNET_SIGNATURE_PURPOSE_NAMESPACE_ADVERTISEMENT 4 /** * Signature by which a peer affirms that it is * providing a certain bit of content (used * in LOCation URIs). */ #define GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT 5 /** * Obsolete, legacy value. */ #define GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK 6 /** * Obsolete, legacy value. */ #define GNUNET_SIGNATURE_PURPOSE_FS_SBLOCK 7 /** * Obsolete, legacy value. */ #define GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK 8 /** * Obsolete, legacy value. */ #define GNUNET_SIGNATURE_PURPOSE_FS_NBLOCK_KSIG 9 /** * */ #define GNUNET_SIGNATURE_PURPOSE_RESOLVER_RESPONSE 10 /** * Signature of an GNUNET_DNS_Advertisement */ #define GNUNET_SIGNATURE_PURPOSE_DNS_RECORD 11 /** * Signature of a chat message. */ #define GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE 12 /** * Signature of confirmation receipt for a chat message. */ #define GNUNET_SIGNATURE_PURPOSE_CHAT_RECEIPT 13 /** * Signature of a network size estimate message. */ #define GNUNET_SIGNATURE_PURPOSE_NSE_SEND 14 /** * Signature of a gnunet naming system record block */ #define GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN 15 /** * Purpose is to set a session key. */ #define GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY 16 /** * UBlock Signature, done using DSS, not ECC */ #define GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK 17 /** * Accept state in regex DFA. Peer affirms that * he offers the matching service. */ #define GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT 18 /** * Signature of a multicast message. */ #define GNUNET_SIGNATURE_PURPOSE_MULTICAST_MESSAGE 19 /** * Signature of a conversation ring. */ #define GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING 20 /** * Key exchange in MESH */ #define GNUNET_SIGNATURE_PURPOSE_MESH_KX 21 /** * Signature for the first round of distributed key generation. */ #define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1 22 /** * Signature for the second round of distributed key generation. */ #define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2 23 /** * Signature for cooperatice decryption. */ #define GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION 23 #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_SIGNATURES_H */ #endif /* end of gnunet_signatures.h */ gnunet-0.10.1/src/include/gnunet_connection_lib.h0000644000175000017500000002751612274162760016764 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_connection_lib.h * @brief basic, low-level TCP networking interface * @author Christian Grothoff */ #ifndef GNUNET_CONNECTION_LIB_H #define GNUNET_CONNECTION_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_network_lib.h" #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" /** * Timeout we use on TCP connect before trying another * result from the DNS resolver. Actual value used * is this value divided by the number of address families. * Default is 5s. */ #define GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * @brief handle for a network connection */ struct GNUNET_CONNECTION_Handle; /** * Credentials for UNIX domain sockets. */ struct GNUNET_CONNECTION_Credentials { /** * UID of the other end of the connection. */ uid_t uid; /** * GID of the other end of the connection. */ gid_t gid; }; /** * Function to call for access control checks. * * @param cls closure * @param ucred credentials, if available, otherwise NULL * @param addr address * @param addrlen length of address * @return GNUNET_YES to allow, GNUNET_NO to deny, GNUNET_SYSERR * for unknown address family (will be denied). */ typedef int (*GNUNET_CONNECTION_AccessCheck) (void *cls, const struct GNUNET_CONNECTION_Credentials * ucred, const struct sockaddr * addr, socklen_t addrlen); /** * Callback function for data received from the network. Note that * both "available" and "err" would be 0 if the read simply timed out. * * @param cls closure * @param buf pointer to received data * @param available number of bytes availabe in "buf", * possibly 0 (on errors) * @param addr address of the sender * @param addrlen size of addr * @param errCode value of errno (on errors receiving) */ typedef void (*GNUNET_CONNECTION_Receiver) (void *cls, const void *buf, size_t available, const struct sockaddr * addr, socklen_t addrlen, int errCode); /** * Set the persist option on this connection handle. Indicates * that the underlying socket or fd should never really be closed. * Used for indicating process death. * * @param connection the connection to set persistent */ void GNUNET_CONNECTION_persist_ (struct GNUNET_CONNECTION_Handle *connection); /** * Disable the "CORK" feature for communication with the given socket, * forcing the OS to immediately flush the buffer on transmission * instead of potentially buffering multiple messages. Essentially * reduces the OS send buffers to zero. * Used to make sure that the last messages sent through the connection * reach the other side before the process is terminated. * * @param connection the connection to make flushing and blocking * @return GNUNET_OK on success */ int GNUNET_CONNECTION_disable_corking (struct GNUNET_CONNECTION_Handle *connection); /** * Create a connection handle by boxing an existing OS socket. The OS * socket should henceforth be no longer used directly. * GNUNET_CONNECTION_destroy will close it. * * @param osSocket existing socket to box * @return the boxed socket handle */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_existing (struct GNUNET_NETWORK_Handle *osSocket); /** * Create a connection handle by accepting on a listen socket. This * function may block if the listen socket has no connection ready. * * @param access function to use to check if access is allowed * @param access_cls closure for access * @param lsock listen socket * @return the connection handle, NULL on error (for example, access refused) */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, void *access_cls, struct GNUNET_NETWORK_Handle *lsock); /** * Create a connection handle by (asynchronously) connecting to a host. * This function returns immediately, even if the connection has not * yet been established. This function only creates TCP connections. * * @param cfg configuration to use * @param hostname name of the host to connect to * @param port port to connect to * @return the connection handle */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *hostname, uint16_t port); /** * Create a connection handle by connecting to a UNIX domain service. * This function returns immediately, even if the connection has not * yet been established. This function only creates UNIX connections. * * @param cfg configuration to use * @param unixpath path to connect to) * @return the connection handle, NULL on systems without UNIX support */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *unixpath); /** * Create a connection handle by (asynchronously) connecting to a host. * This function returns immediately, even if the connection has not * yet been established. This function only creates TCP connections. * * @param af_family address family to use * @param serv_addr server address * @param addrlen length of server address * @return the connection handle */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_sockaddr (int af_family, const struct sockaddr *serv_addr, socklen_t addrlen); /** * Check if connection is valid (no fatal errors have happened so far). * Note that a connection that is still trying to connect is considered * valid. * * @param connection handle to check * @return GNUNET_YES if valid, GNUNET_NO otherwise */ int GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *connection); /** * Obtain the network address of the other party. * * @param connection the client to get the address for * @param addr where to store the address * @param addrlen where to store the length of the address * @return GNUNET_OK on success */ int GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection, void **addr, size_t * addrlen); /** * Close the connection and free associated resources. There must * not be any pending requests for reading or writing to the * connection at this time. * * @param connection connection to destroy */ void GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection); /** * Receive data from the given connection. Note that this function will * call "receiver" asynchronously using the scheduler. It will * "immediately" return. Note that there MUST only be one active * receive call per connection at any given point in time (so do not * call receive again until the receiver callback has been invoked). * * @param connection connection handle * @param max maximum number of bytes to read * @param timeout maximum amount of time to wait * @param receiver function to call with received data * @param receiver_cls closure for receiver */ void GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection, size_t max, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_Receiver receiver, void *receiver_cls); /** * Cancel receive job on the given connection. Note that the * receiver callback must not have been called yet in order * for the cancellation to be valid. * * @param connection connection handle * @return closure of the original receiver callback closure */ void * GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *connection); /** * Function called to notify a client about the connection begin ready * to queue more data. @a buf will be NULL and @a size zero if the * connection was closed for writing in the meantime. * * @param cls closure * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ typedef size_t (*GNUNET_CONNECTION_TransmitReadyNotify) (void *cls, size_t size, void *buf); /** * Opaque handle that can be used to cancel * a transmit-ready notification. */ struct GNUNET_CONNECTION_TransmitHandle; /** * Ask the connection to call us once the specified number of bytes * are free in the transmission buffer. May call the notify * method immediately if enough space is available. Note that * this function will abort if "size" is greater than * #GNUNET_SERVER_MAX_MESSAGE_SIZE. * * Note that "notify" will be called either when enough * buffer space is available OR when the connection is destroyed. * The size parameter given to notify is guaranteed to be * larger or equal to size if the buffer is ready, or zero * if the connection was destroyed (or at least closed for * writing). Finally, any time before 'notify' is called, a * client may call "notify_transmit_ready_cancel" to cancel * the transmission request. * * Only one transmission request can be scheduled at the same * time. Notify will be run with the same scheduler priority * as that of the caller. * * @param connection connection * @param size number of bytes to send * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param notify function to call when buffer space is available * @param notify_cls closure for notify * @return non-NULL if the notify callback was queued, * NULL if we are already going to notify someone else (busy) */ struct GNUNET_CONNECTION_TransmitHandle * GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connection, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls); /** * Cancel the specified transmission-ready * notification. * * @param th handle for notification to cancel */ void GNUNET_CONNECTION_notify_transmit_ready_cancel (struct GNUNET_CONNECTION_TransmitHandle *th); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_CONNECTION_LIB_H */ #endif /* end of gnunet_connection_lib.h */ gnunet-0.10.1/src/include/gnunet_plugin_lib.h0000644000175000017500000001016112236654562016113 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_plugin_lib.h * @brief plugin loading and unloading * @author Christian Grothoff */ #ifndef GNUNET_PLUGIN_LIB_H #define GNUNET_PLUGIN_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_common.h" #include "gnunet_configuration_lib.h" /** * Signature of any function exported by a plugin. * * @param arg argument to the function (context) * @return some pointer, NULL if the plugin was * shutdown or if there was an error, otherwise * the plugin's API on success */ typedef void *(*GNUNET_PLUGIN_Callback) (void *arg); /** * Test if a plugin exists. * * Note that the library must export a symbol called * "library_name_init" for the test to succeed. * * @param library_name name of the plugin to test if it is installed * @return #GNUNET_YES if the plugin exists, #GNUNET_NO if not */ int GNUNET_PLUGIN_test (const char *library_name); /** * Setup plugin (runs the "init" callback and returns whatever "init" * returned). If "init" returns NULL, the plugin is unloaded. * * Note that the library must export symbols called * "library_name_init" and "library_name_done". These will be called * when the library is loaded and unloaded respectively. * * @param library_name name of the plugin to load * @param arg argument to the plugin initialization function * @return whatever the initialization function returned, NULL on error */ void * GNUNET_PLUGIN_load (const char *library_name, void *arg); /** * Signature of a function called by 'GNUNET_PLUGIN_load_all'. * * @param cls closure * @param library_name full name of the library (to be used with * #GNUNET_PLUGIN_unload) * @param lib_ret return value from the initialization function * of the library (same as what #GNUNET_PLUGIN_load would * have returned for the given library name) */ typedef void (*GNUNET_PLUGIN_LoaderCallback) (void *cls, const char *library_name, void *lib_ret); /** * Load all compatible plugins with the given base name. * * Note that the library must export symbols called * "basename_ANYTHING_init" and "basename_ANYTHING__done". These will * be called when the library is loaded and unloaded respectively. * * @param basename basename of the plugins to load * @param arg argument to the plugin initialization function * @param cb function to call for each plugin found * @param cb_cls closure for @a cb */ void GNUNET_PLUGIN_load_all (const char *basename, void *arg, GNUNET_PLUGIN_LoaderCallback cb, void *cb_cls); /** * Unload plugin (runs the "done" callback and returns whatever "done" * returned). The plugin is then unloaded. * * @param library_name name of the plugin to unload * @param arg argument to the plugin shutdown function * @return whatever the shutdown function returned, typically NULL * or a "char *" representing the error message */ void * GNUNET_PLUGIN_unload (const char *library_name, void *arg); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_PLUGIN_LIB_H */ #endif /* end of gnunet_plugin_lib.h */ gnunet-0.10.1/src/include/gnunet_block_lib.h0000644000175000017500000001630012274707232015703 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_block_lib.h * @brief library for data block manipulation * @author Christian Grothoff */ #ifndef GNUNET_BLOCK_LIB_H #define GNUNET_BLOCK_LIB_H #include "gnunet_util_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Blocks in the datastore and the datacache must have a unique type. */ enum GNUNET_BLOCK_Type { /** * Any type of block, used as a wildcard when searching. Should * never be attached to a specific block. */ GNUNET_BLOCK_TYPE_ANY = 0, /** * Data block (leaf) in the CHK tree. */ GNUNET_BLOCK_TYPE_FS_DBLOCK = 1, /** * Inner block in the CHK tree. */ GNUNET_BLOCK_TYPE_FS_IBLOCK = 2, /** * Legacy type, no longer in use. */ GNUNET_BLOCK_TYPE_FS_KBLOCK = 3, /** * Legacy type, no longer in use. */ GNUNET_BLOCK_TYPE_FS_SBLOCK = 4, /** * Legacy type, no longer in use. */ GNUNET_BLOCK_TYPE_FS_NBLOCK = 5, /** * Type of a block representing a block to be encoded on demand from disk. * Should never appear on the network directly. */ GNUNET_BLOCK_TYPE_FS_ONDEMAND = 6, /** * Type of a block that contains a HELLO for a peer (for * DHT and MESH find-peer operations). */ GNUNET_BLOCK_TYPE_DHT_HELLO = 7, /** * Block for testing. */ GNUNET_BLOCK_TYPE_TEST = 8, /** * Type of a block representing any type of search result * (universal). Implemented in the context of #2564, replaces * SBLOCKS, KBLOCKS and NBLOCKS. */ GNUNET_BLOCK_TYPE_FS_UBLOCK = 9, /** * Block for storing DNS exit service advertisements. */ GNUNET_BLOCK_TYPE_DNS = 10, /** * Block for storing record data */ GNUNET_BLOCK_TYPE_GNS_NAMERECORD = 11, /** * Block to store a mesh regex state */ GNUNET_BLOCK_TYPE_REGEX = 22, /** * Block to store a mesh regex accepting state */ GNUNET_BLOCK_TYPE_REGEX_ACCEPT = 23 }; /** * Possible ways for how a block may relate to a query. */ enum GNUNET_BLOCK_EvaluationResult { /** * Valid result, and there may be more. */ GNUNET_BLOCK_EVALUATION_OK_MORE = 0, /** * Last possible valid result. */ GNUNET_BLOCK_EVALUATION_OK_LAST = 1, /** * Valid result, but suppressed because it is a duplicate. */ GNUNET_BLOCK_EVALUATION_OK_DUPLICATE = 2, /** * Block does not match query (invalid result) */ GNUNET_BLOCK_EVALUATION_RESULT_INVALID = 3, /** * Block does not match xquery (valid result, not relevant for the request) */ GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT = 4, /** * Query is valid, no reply given. */ GNUNET_BLOCK_EVALUATION_REQUEST_VALID = 10, /** * Query format does not match block type (invalid query). For * example, xquery not given or xquery_size not appropriate for * type. */ GNUNET_BLOCK_EVALUATION_REQUEST_INVALID = 11, /** * Specified block type not supported by this plugin. */ GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED = 20 }; /** * Handle to an initialized block library. */ struct GNUNET_BLOCK_Context; /** * Mingle hash with the mingle_number to produce different bits. * * @param in original hash code * @param mingle_number number for hash permutation * @param hc where to store the result. */ void GNUNET_BLOCK_mingle_hash (const struct GNUNET_HashCode * in, uint32_t mingle_number, struct GNUNET_HashCode * hc); /** * Create a block context. Loads the block plugins. * * @param cfg configuration to use * @return NULL on error */ struct GNUNET_BLOCK_Context * GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Destroy the block context. * * @param ctx context to destroy */ void GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx); /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would * be done with the "get_key" function. * * @param ctx block contxt * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for @a bf * @param xquery extrended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param reply_block response to validate * @param reply_block_size number of bytes in @a reply_block * @return characterization of result */ enum GNUNET_BLOCK_EvaluationResult GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size); /** * Function called to obtain the key for a block. * * @param ctx block context * @param type block type * @param block block to get the key for * @param block_size number of bytes in @a block * @param key set to the key (query) for the given block * @return #GNUNET_YES on success, * #GNUNET_NO if the block is malformed * #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ int GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode * key); /** * Construct a bloom filter that would filter out the given * results. * * @param bf_mutator mutation value to use * @param seen_results results already seen * @param seen_results_count number of entries in @a seen_results * @return NULL if seen_results_count is 0, otherwise a BF * that would match the given results. */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_BLOCK_construct_bloomfilter (int32_t bf_mutator, const struct GNUNET_HashCode * seen_results, unsigned int seen_results_count); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_BLOCK_LIB_H */ #endif /* end of gnunet_block_lib.h */ gnunet-0.10.1/src/include/gnunet_applications.h0000644000175000017500000000515112227011700016435 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_applications.h * @brief constants for network applications operating on top of the MESH service * @author Christian Grothoff */ #ifndef GNUNET_APPLICATIONS_H #define GNUNET_APPLICATIONS_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * End of list marker. */ #define GNUNET_APPLICATION_TYPE_END 0 /** * Test. */ #define GNUNET_APPLICATION_TYPE_TEST 1 /** * Internet DNS resolution (external DNS gateway). */ #define GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER 2 /** * Transfer of blocks for non-anonymmous file-sharing. */ #define GNUNET_APPLICATION_TYPE_FS_BLOCK_TRANSFER 3 /** * Internet IPv4 gateway (any TCP/UDP/ICMP). */ #define GNUNET_APPLICATION_TYPE_IPV4_GATEWAY 16 /** * Internet IPv6 gateway (any TCP/UDP/ICMP). */ #define GNUNET_APPLICATION_TYPE_IPV6_GATEWAY 17 /** * Internet exit regex prefix. Consisting of application ID, followed by version * and padding. */ #define GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX "GNUNET-VPN-VER-0001-" /** * Consensus. */ #define GNUNET_APPLICATION_TYPE_CONSENSUS 18 /** * Set. Used for two-peer set operations implemented using stream. */ #define GNUNET_APPLICATION_TYPE_SET 19 /** * Vectorproduct. Used for two-peer scalarproduct operations */ #define GNUNET_APPLICATION_TYPE_SCALARPRODUCT 20 /** * Conversation control data. */ #define GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL 21 /** * Conversation audio data. */ #define GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO 22 /** * MQTT publish-subscribe. */ #define GNUNET_APPLICATION_TYPE_MQTT 23 #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_APPLICATIONS_H */ #endif /* end of gnunet_applications.h */ gnunet-0.10.1/src/include/gnunet_regex_service.h0000644000175000017500000001051612225777503016624 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_regex_service.h * @brief access regex service to advertise capabilities via regex and discover * respective peers using matching strings * @author Maximilian Szengel * @author Christian Grothoff */ #ifndef GNUNET_REGEX_SERVICE_H #define GNUNET_REGEX_SERVICE_H #include "gnunet_util_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Constant for how many bytes the initial string regex should have. */ #define GNUNET_REGEX_INITIAL_BYTES 24 /** * Handle to store cached data about a regex announce. */ struct GNUNET_REGEX_Announcement; /** * Handle to store data about a regex search. */ struct GNUNET_REGEX_Search; /** * Announce this peer under the given regular expression. Does * not free resources, must call #GNUNET_REGEX_announce_cancel for * that. * * @param cfg configuration to use * @param regex Regular expression to announce. * @param refresh_delay after what delay should the announcement be repeated? * @param compression How many characters per edge can we squeeze? * @return Handle to reuse o free cached resources. * Must be freed by calling #GNUNET_REGEX_announce_cancel. */ struct GNUNET_REGEX_Announcement * GNUNET_REGEX_announce (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *regex, struct GNUNET_TIME_Relative refresh_delay, uint16_t compression); /** * Stop announcing the regex specified by the given handle. * * @param a handle returned by a previous #GNUNET_REGEX_announce call. */ void GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_Announcement *a); /** * Search callback function, invoked for every result that was found. * * @param cls Closure provided in #GNUNET_REGEX_search. * @param id Peer providing a regex that matches the string. * @param get_path Path of the get request. * @param get_path_length Lenght of @a get_path. * @param put_path Path of the put request. * @param put_path_length Length of the @a put_path. */ typedef void (*GNUNET_REGEX_Found)(void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length); /** * Search for a peer offering a regex matching certain string in the DHT. * The search runs until #GNUNET_REGEX_search_cancel is called, even if results * are returned. * * @param cfg configuration to use * @param string String to match against the regexes in the DHT. * @param callback Callback for found peers. * @param callback_cls Closure for @c callback. * @return Handle to stop search and free resources. * Must be freed by calling #GNUNET_REGEX_search_cancel. */ struct GNUNET_REGEX_Search * GNUNET_REGEX_search (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *string, GNUNET_REGEX_Found callback, void *callback_cls); /** * Stop search and free all data used by a #GNUNET_REGEX_search call. * * @param s Handle returned by a previous #GNUNET_REGEX_search call. */ void GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_regex_service.h */ #endif gnunet-0.10.1/src/include/gnunet_client_lib.h0000644000175000017500000001732712225777503016105 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_client_lib.h * @brief functions related to accessing services * @author Christian Grothoff * @defgroup client Generic client-side communication with services * @{ */ #ifndef GNUNET_CLIENT_LIB_H #define GNUNET_CLIENT_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Opaque handle for a connection to a service. */ struct GNUNET_CLIENT_Connection; /** * Get a connection with a service. * * @param service_name name of the service * @param cfg configuration to use * @return NULL on error (service unknown to configuration) */ struct GNUNET_CLIENT_Connection * GNUNET_CLIENT_connect (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Destroy connection with the service. This will automatically * cancel any pending "receive" request (however, the handler will * *NOT* be called, not even with a NULL message). Any pending * transmission request will also be cancelled UNLESS the callback for * the transmission request has already been called, in which case the * transmission 'finish_pending_write' argument determines whether or * not the write is guaranteed to complete before the socket is fully * destroyed (unless, of course, there is an error with the server in * which case the message may still be lost). * * @param client handle to the service connection */ void GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client); /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ typedef void (*GNUNET_CLIENT_MessageHandler) (void *cls, const struct GNUNET_MessageHeader *msg); /** * Read from the service. * * @param client connection to the service * @param handler function to call with the message * @param handler_cls closure for @a handler * @param timeout how long to wait until timing out */ void GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client, GNUNET_CLIENT_MessageHandler handler, void *handler_cls, struct GNUNET_TIME_Relative timeout); /** * Transmit handle for client connections. */ struct GNUNET_CLIENT_TransmitHandle; /** * Ask the client to call us once the specified number of bytes * are free in the transmission buffer. May call the notify * method immediately if enough space is available. * * @param client connection to the service * @param size number of bytes to send * @param timeout after how long should we give up (and call * @a notify with buf NULL and size 0)? * @param auto_retry if the connection to the service dies, should we * automatically re-connect and retry (within the timeout period) * or should we immediately fail in this case? Pass #GNUNET_YES * if the caller does not care about temporary connection errors, * for example because the protocol is stateless * @param notify function to call * @param notify_cls closure for @a notify * @return NULL if someone else is already waiting to be notified * non-NULL if the notify callback was queued (can be used to cancel * using #GNUNET_CONNECTION_notify_transmit_ready_cancel) */ struct GNUNET_CLIENT_TransmitHandle * GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, size_t size, struct GNUNET_TIME_Relative timeout, int auto_retry, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls); /** * Cancel a request for notification. * * @param th handle from the original request. */ void GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle *th); /** * Convenience API that combines sending a request * to the service and waiting for a response. * If either operation times out, the callback * will be called with a "NULL" response (in which * case the connection should probably be destroyed). * * @param client connection to use * @param hdr message to transmit * @param timeout when to give up (for both transmission * and for waiting for a response) * @param auto_retry if the connection to the service dies, should we * automatically re-connect and retry (within the timeout period) * or should we immediately fail in this case? Pass #GNUNET_YES * if the caller does not care about temporary connection errors, * for example because the protocol is stateless * @param rn function to call with the response * @param rn_cls closure for @a rn * @return #GNUNET_OK on success, #GNUNET_SYSERR if a request * is already pending */ int GNUNET_CLIENT_transmit_and_get_response (struct GNUNET_CLIENT_Connection *client, const struct GNUNET_MessageHeader *hdr, struct GNUNET_TIME_Relative timeout, int auto_retry, GNUNET_CLIENT_MessageHandler rn, void *rn_cls); /** * Handle for a test to check if a service is running. */ struct GNUNET_CLIENT_TestHandle; /** * Function called with the result on the service test. * * @param cls closure * @param result #GNUNET_YES if the service is running, * #GNUNET_NO if the service is not running * #GNUNET_SYSERR if the configuration is invalid */ typedef void (*GNUNET_CLIENT_TestResultCallback)(void *cls, int result); /** * Test if the service is running. If we are given a UNIXPATH or a * local address, we do this NOT by trying to connect to the service, * but by trying to BIND to the same port. If the BIND fails, we know * the service is running. * * @param service name of the service to wait for * @param cfg configuration to use * @param timeout how long to wait at most * @param cb function to call with the result * @param cb_cls closure for @a cb * @return handle to cancel the test */ struct GNUNET_CLIENT_TestHandle * GNUNET_CLIENT_service_test (const char *service, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TIME_Relative timeout, GNUNET_CLIENT_TestResultCallback cb, void *cb_cls); /** * Abort testing for service. * * @param th test handle */ void GNUNET_CLIENT_service_test_cancel (struct GNUNET_CLIENT_TestHandle *th); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group client */ /* ifndef GNUNET_CLIENT_LIB_H */ #endif /* end of gnunet_client_lib.h */ gnunet-0.10.1/src/include/block_fs.h0000644000175000017500000000436712225777503014203 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/block_fs.h * @brief fs block formats (shared between fs and block) * @author Christian Grothoff */ #ifndef BLOCK_FS_H #define BLOCK_FS_H #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" /** * Maximum legal size for a ublock. */ #define MAX_UBLOCK_SIZE (60 * 1024) GNUNET_NETWORK_STRUCT_BEGIN /** * @brief universal block for keyword and namespace search results */ struct UBlock { /** * Signature using pseudonym and search keyword / identifier. */ struct GNUNET_CRYPTO_EcdsaSignature signature; /** * What is being signed and why? */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Public key used to sign this block. */ struct GNUNET_CRYPTO_EcdsaPublicKey verification_key; /* rest of the data is encrypted */ /* 0-terminated update-identifier here (ignored for keyword results) */ /* 0-terminated URI here */ /* variable-size Meta-Data follows here */ }; /** * @brief index block (indexing a DBlock that * can be obtained directly from reading * the plaintext file) */ struct OnDemandBlock { /** * Hash code of the entire content of the * file that was indexed (used to uniquely * identify the plaintext file). */ struct GNUNET_HashCode file_id; /** * At which offset should we be able to find * this on-demand encoded block? (in NBO) */ uint64_t offset GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/include/gnunet_scalarproduct_service.h0000644000175000017500000001207112310570720020341 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_scalarproduct_service.h * @brief API to the scalarproduct service * @author Christian M. Fuchs * @author Gaurav Kukreja */ #ifndef GNUNET_SCALARPRODUCT_SERVICE_H #define GNUNET_SCALARPRODUCT_SERVICE_H #define GCRYPT_NO_DEPRECATED #include #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Version of the scalarproduct API. */ #define GNUNET_SCALARPRODUCT_VERSION 0x00000042 enum GNUNET_SCALARPRODUCT_ResponseStatus { GNUNET_SCALARPRODUCT_Status_Success = 0, GNUNET_SCALARPRODUCT_Status_Failure, GNUNET_SCALARPRODUCT_Status_InvalidResponse, GNUNET_SCALARPRODUCT_Status_ServiceDisconnected }; /** * Opaque declaration of the SP-Handle */ struct GNUNET_SCALARPRODUCT_Handle; /** * Continuation called to notify client about result of the * operation. * * @param cls closure * @param status Status of the request */ typedef void (*GNUNET_SCALARPRODUCT_ContinuationWithStatus) (void *cls, enum GNUNET_SCALARPRODUCT_ResponseStatus status); /** * Process a datum that was stored in the scalarproduct. * * @param cls closure * @param status Status of the request * @param result result of the computation */ typedef void (*GNUNET_SCALARPRODUCT_DatumProcessor) (void *cls, enum GNUNET_SCALARPRODUCT_ResponseStatus status, gcry_mpi_t result); /** * Entry in the request queue per client */ struct GNUNET_SCALARPRODUCT_ComputationHandle; /** * Request by Alice's client for computing a scalar product * * @param cfg the gnunet configuration handle * @param key Session key should be unique to the requesting client * @param peer PeerID of the other peer * @param elements Array of elements of the vector * @param element_count Number of elements in the vector * @param mask Array of the mask * @param mask_bytes number of bytes in the mask * @param cont Callback function * @param cont_cls Closure for @a cont * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * GNUNET_SCALARPRODUCT_request (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *peer, const int32_t *elements, uint32_t element_count, const unsigned char *mask, uint32_t mask_bytes, GNUNET_SCALARPRODUCT_DatumProcessor cont, void * cont_cls); /** * Used by Bob's client to cooperate with Alice, * * @param cfg the gnunet configuration handle * @param key Session key unique to the requesting client * @param elements Array of elements of the vector * @param element_count Number of elements in the vector * @param cont Callback function * @param cont_cls Closure for @a cont * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * GNUNET_SCALARPRODUCT_response (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HashCode *key, const int32_t *elements, uint32_t element_count, GNUNET_SCALARPRODUCT_ContinuationWithStatus cont, void *cont_cls); /** * Cancel an ongoing computation or revoke our collaboration offer. * Closes the connection to the service * * @param h computation handle to terminate */ void GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle *h); /** * Cancel ALL ongoing computation or revoke our collaboration offer. * Closes ALL connections to the service * * FIXME: this should take an argument, and we should * have an explicit 'connect' API which returns an opaque * connection handle. Avoid (globals) in the library! * @deprecated in this form */ void GNUNET_SCALARPRODUCT_disconnect (); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gauger.h0000644000175000017500000000623712225777503013671 00000000000000/** --------------------------------------------------------------------------- * This software is in the public domain, furnished "as is", without technical * support, and with no warranty, express or implied, as to its usefulness for * any purpose. * * gauger.h * Interface for C programs to log remotely to a gauger server * * Author: Bartlomiej Polot * -------------------------------------------------------------------------*/ #ifndef __GAUGER_H__ #define __GAUGER_H__ #ifndef WINDOWS #include #include #include #define GAUGER(category, counter, value, unit)\ {\ char* __gauger_v[10];\ char __gauger_s[32];\ pid_t __gauger_p;\ if(!(__gauger_p=fork())){\ close (1); \ close (2); \ if(!fork()){\ sprintf(__gauger_s,"%Lf", (long double) (value));\ __gauger_v[0] = "gauger";\ __gauger_v[1] = "-n";\ __gauger_v[2] = (char*) (counter); \ __gauger_v[3] = "-d";\ __gauger_v[4] = __gauger_s;\ __gauger_v[5] = "-u";\ __gauger_v[6] = (char*) (unit); \ __gauger_v[7] = "-c";\ __gauger_v[8] = (char*) (category); \ __gauger_v[9] = (char*) NULL;\ execvp("gauger",__gauger_v);\ _exit(1);\ }else{\ _exit(0);\ }\ }else{\ waitpid(__gauger_p,NULL,0);\ }\ } #define GAUGER_ID(category, counter, value, unit, id)\ {\ char* __gauger_v[12];\ char __gauger_s[32];\ pid_t __gauger_p;\ if(!(__gauger_p=fork())){\ close (1); \ close (2); \ if(!fork()){\ sprintf(__gauger_s,"%Lf", (long double) (value));\ __gauger_v[0] = "gauger";\ __gauger_v[1] = "-n";\ __gauger_v[2] = (char*) (counter); \ __gauger_v[3] = "-d";\ __gauger_v[4] = __gauger_s;\ __gauger_v[5] = "-u";\ __gauger_v[6] = (char*) (unit); \ __gauger_v[7] = "-i";\ __gauger_v[8] = id;\ __gauger_v[9] = "-c";\ __gauger_v[10] = (char *) (category); \ __gauger_v[11] = (char *) NULL;\ execvp("gauger",__gauger_v);\ _exit(1);\ }else{\ _exit(0);\ }\ }else{\ waitpid(__gauger_p, NULL, 0);\ }\ } #else /* WINDOWS */ #include #include #include #define GAUGER(category, counter, value, unit)\ {\ char __gauger_commandline[MAX_PATH];\ \ snprintf (__gauger_commandline, MAX_PATH, "gauger.py -n \"%s\" -d \"%Lf\" -u \"%s\" -c \"%s\"",\ (counter), (long double) (value), (unit), (category)); \ __gauger_commandline[MAX_PATH - 1] = '\0';\ system (__gauger_commandline);\ } #define GAUGER_ID(category, counter, value, unit, id)\ {\ char __gauger_commandline[MAX_PATH];\ \ snprintf (__gauger_commandline, MAX_PATH, "gauger.py -n \"%s\" -d \"%Lf\" -u \"%s\" -i \"%s\" -c \"%s\"",\ (counter), (long double) (value), (unit), (id), (category)); \ __gauger_commandline[MAX_PATH - 1] = '\0';\ system (__gauger_commandline);\ } #endif // WINDOWS #endif gnunet-0.10.1/src/include/gnunet_peerinfo_service.h0000644000175000017500000001561312225777503017324 00000000000000/* This file is part of GNUnet (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_peerinfo_service.h * @brief Code to maintain the list of currently known hosts * (in memory structure of data/hosts). * @author Christian Grothoff */ #ifndef GNUNET_PEERINFO_SERVICE_H #define GNUNET_PEERINFO_SERVICE_H #include "gnunet_common.h" #include "gnunet_configuration_lib.h" #include "gnunet_crypto_lib.h" #include "gnunet_hello_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Handle to the peerinfo service. */ struct GNUNET_PEERINFO_Handle; /** * Connect to the peerinfo service. * * @param cfg configuration to use * @return NULL on error (configuration related, actual connection * etablishment may happen asynchronously). */ struct GNUNET_PEERINFO_Handle * GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Disconnect from the peerinfo service. Note that all iterators must * have completed or have been cancelled by the time this function is * called (otherwise, calling this function is a serious error). * Furthermore, if 'GNUNET_PEERINFO_add_peer' operations are still * pending, they will be cancelled silently on disconnect. * * @param h handle to disconnect */ void GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h); /** * Continuation called with a status result. * * @param cls closure * @param emsg error message, NULL on success */ typedef void (*GNUNET_PEERINFO_Continuation)(void *cls, const char *emsg); /** * Opaque handle to cancel 'add' operation. */ struct GNUNET_PEERINFO_AddContext; /** * Add a host to the persistent list. This method operates in * semi-reliable mode: if the transmission is not completed by * the time 'GNUNET_PEERINFO_disconnect' is called, it will be * aborted. Furthermore, if a second HELLO is added for the * same peer before the first one was transmitted, PEERINFO may * merge the two HELLOs prior to transmission to the service. * * @param h handle to the peerinfo service * @param hello the verified (!) HELLO message * @param cont continuation to call when done, NULL is allowed * @param cont_cls closure for 'cont' * @return handle to cancel add operation; all pending * 'add' operations will be cancelled automatically * on disconnect, so it is not necessary to keep this * handle (unless 'cont' is NULL and at some point * calling 'cont' must be prevented) */ struct GNUNET_PEERINFO_AddContext * GNUNET_PEERINFO_add_peer (struct GNUNET_PEERINFO_Handle *h, const struct GNUNET_HELLO_Message *hello, GNUNET_PEERINFO_Continuation cont, void *cont_cls); /** * Cancel pending 'add' operation. Must only be called before * either 'cont' or 'GNUNET_PEERINFO_disconnect' are invoked. * * @param ac handle for the add operation to cancel */ void GNUNET_PEERINFO_add_peer_cancel (struct GNUNET_PEERINFO_AddContext *ac); /** * Type of an iterator over the hosts. Note that each * host will be called with each available protocol. * * @param cls closure * @param peer id of the peer, NULL for last call * @param hello hello message for the peer (can be NULL) * @param error message */ typedef void (*GNUNET_PEERINFO_Processor) (void *cls, const struct GNUNET_PeerIdentity * peer, const struct GNUNET_HELLO_Message * hello, const char *err_msg); /** * Handle for cancellation of iteration over peers. */ struct GNUNET_PEERINFO_IteratorContext; /** * Call a method for each known matching host. The callback method * will be invoked once for each matching host and then finally once * with a NULL pointer. After that final invocation, the iterator * context must no longer be used. * * Instead of calling this function with 'peer == NULL' it is often * better to use 'GNUNET_PEERINFO_notify'. * * @param h handle to the peerinfo service * @param include_friend_only include HELLO messages for friends only * @param peer restrict iteration to this peer only (can be NULL) * @param timeout how long to wait until timing out * @param callback the method to call for each peer * @param callback_cls closure for callback * @return iterator context */ struct GNUNET_PEERINFO_IteratorContext * GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h, int include_friend_only, const struct GNUNET_PeerIdentity *peer, struct GNUNET_TIME_Relative timeout, GNUNET_PEERINFO_Processor callback, void *callback_cls); /** * Cancel an iteration over peer information. * * @param ic context of the iterator to cancel */ void GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic); /** * Handle for notifications about changes to the set of known peers. */ struct GNUNET_PEERINFO_NotifyContext; /** * Call a method whenever our known information about peers * changes. Initially calls the given function for all known * peers and then only signals changes. * * If include_friend_only is set to GNUNET_YES peerinfo will include HELLO * messages which are intended for friend to friend mode and which do not * have to be gossiped. Otherwise these messages are skipped. * * @param cfg configuration to use * @param include_friend_only include HELLO messages for friends only * @param callback the method to call for each peer * @param callback_cls closure for callback * @return NULL on error */ struct GNUNET_PEERINFO_NotifyContext * GNUNET_PEERINFO_notify (const struct GNUNET_CONFIGURATION_Handle *cfg, int include_friend_only, GNUNET_PEERINFO_Processor callback, void *callback_cls); /** * Stop notifying about changes. * * @param nc context to stop notifying */ void GNUNET_PEERINFO_notify_cancel (struct GNUNET_PEERINFO_NotifyContext *nc); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_peerinfo_service.h */ #endif gnunet-0.10.1/src/include/gnunet_gns_service.h0000644000175000017500000000775312305564550016305 00000000000000/* This file is part of GNUnet (C) 2012-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_gns_service.h * @brief API to the GNS service * @author Martin Schanzenbach */ #ifndef GNUNET_GNS_SERVICE_H #define GNUNET_GNS_SERVICE_H #include "gnunet_util_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_namestore_service.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * String we use to indicate the local master zone or a * root entry in the current zone. */ #define GNUNET_GNS_MASTERZONE_STR "+" /** * Connection to the GNS service. */ struct GNUNET_GNS_Handle; /** * Handle to control a lookup operation. */ struct GNUNET_GNS_LookupRequest; /** * Initialize the connection with the GNS service. * * @param cfg configuration to use * @return handle to the GNS service, or NULL on error */ struct GNUNET_GNS_Handle * GNUNET_GNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Shutdown connection with the GNS service. * * @param handle connection to shut down */ void GNUNET_GNS_disconnect (struct GNUNET_GNS_Handle *handle); /** * Iterator called on obtained result for a GNS lookup. * * @param cls closure * @param rd_count number of records in @a rd * @param rd the records in reply */ typedef void (*GNUNET_GNS_LookupResultProcessor) (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd); /** * Options for the GNS lookup. */ enum GNUNET_GNS_LocalOptions { /** * Defaults, look in cache, then in DHT. */ GNUNET_GNS_LO_DEFAULT = 0, /** * Never look in the DHT, keep request to local cache. */ GNUNET_GNS_LO_NO_DHT = 1, /** * For the rightmost label, only look in the cache (it * is our master zone), for the others, the DHT is OK. */ GNUNET_GNS_LO_LOCAL_MASTER = 2 }; /** * Perform an asynchronous lookup operation on the GNS. * * @param handle handle to the GNS service * @param name the name to look up * @param zone zone to look in * @param type the GNS record type to look for * @param options local options for the lookup * @param shorten_zone_key the private key of the shorten zone (can be NULL); * specify to enable automatic shortening (given a PSEU * record, if a given pseudonym is not yet used in the * shorten zone, we automatically add the respective zone * under that name) * @param proc function to call on result * @param proc_cls closure for processor * @return handle to the queued request */ struct GNUNET_GNS_LookupRequest * GNUNET_GNS_lookup (struct GNUNET_GNS_Handle *handle, const char *name, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone, uint32_t type, enum GNUNET_GNS_LocalOptions options, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_zone_key, GNUNET_GNS_LookupResultProcessor proc, void *proc_cls); /** * Cancel pending lookup request * * @param lr the lookup request to cancel */ void GNUNET_GNS_lookup_cancel (struct GNUNET_GNS_LookupRequest *lr); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif /* gnunet_gns_service.h */ gnunet-0.10.1/src/include/gettext.h0000644000175000017500000000601712225777503014077 00000000000000/* Convenience header for conditional use of GNU . Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 /* NLS can be disabled through the configure --disable-nls option. */ #if ENABLE_NLS /* Get declarations of GNU message catalog functions. */ #include #else /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which chokes if dcgettext is defined as a macro. So include it now, to make later inclusions of a NOP. We don't include as well because people using "gettext.h" will not include , and also including would fail on SunOS 4, whereas is GNUNET_OK. */ #if defined(__sun) #include #endif /* Disabled NLS. The casts to 'const char *' serve the purpose of producing warnings for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ #define gettext(Msgid) ((const char *) (Msgid)) #define dgettext(Domainname, Msgid) ((const char *) (Msgid)) #define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) #define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) #define dngettext(Domainname, Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) #define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) /* slight modification here to avoid warnings: generate GNUNET_NO code, not even the cast... */ #define textdomain(Domainname) #define bindtextdomain(Domainname, Dirname) #define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) #endif /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time translation is done at a different place in the code. The argument, String, should be a literal string. Concatenated strings and other string expressions won't work. The macro's expansion is not parenthesized, so that it is suitable as initializer for static 'char[]' or 'const char[]' variables. */ #define gettext_noop(String) String #endif /* _LIBGETTEXT_H */ gnunet-0.10.1/src/include/gnunet_postgres_lib.h0000644000175000017500000001115312225777503016464 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_postgres_lib.h * @brief library to help with access to a Postgres database * @author Christian Grothoff */ #ifndef GNUNET_POSTGRES_LIB_H #define GNUNET_POSTGRES_LIB_H #include "gnunet_util_lib.h" #include #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Check if the result obtained from Postgres has * the desired status code. If not, log an error, clear the * result and return GNUNET_SYSERR. * * @param dbh database handle * @param ret return value from database operation to check * @param expected_status desired status * @param command description of the command that was run * @param args arguments given to the command * @param filename name of the source file where the command was run * @param line line number in the source file * @return GNUNET_OK if the result is acceptable */ int GNUNET_POSTGRES_check_result_ (PGconn *dbh, PGresult * ret, int expected_status, const char *command, const char *args, const char *filename, int line); /** * Check if the result obtained from Postgres has * the desired status code. If not, log an error, clear the * result and return GNUNET_SYSERR. * * @param dbh database handle * @param ret return value from database operation to check * @param expected_status desired status * @param command description of the command that was run * @param args arguments given to the command * @return GNUNET_OK if the result is acceptable */ #define GNUNET_POSTGRES_check_result(dbh,ret,expected_status,command,args) GNUNET_POSTGRES_check_result_(dbh,ret,expected_status,command,args,__FILE__,__LINE__) /** * Run simple SQL statement (without results). * * @param dbh database handle * @param sql statement to run * @param filename filename for error reporting * @param line code line for error reporting * @return GNUNET_OK on success */ int GNUNET_POSTGRES_exec_ (PGconn *dbh, const char *sql, const char *filename, int line); /** * Run simple SQL statement (without results). * * @param dbh database handle * @param sql statement to run * @return GNUNET_OK on success */ #define GNUNET_POSTGRES_exec(dbh,sql) GNUNET_POSTGRES_exec_(dbh,sql,__FILE__,__LINE__) /** * Prepare SQL statement. * * @param dbh database handle * @param name name for the prepared SQL statement * @param sql SQL code to prepare * @param nparams number of parameters in sql * @param filename filename for error reporting * @param line code line for error reporting * @return GNUNET_OK on success */ int GNUNET_POSTGRES_prepare_ (PGconn *dbh, const char *name, const char *sql, int nparams, const char *filename, int line); /** * Prepare SQL statement. * * @param dbh database handle * @param name name for the prepared SQL statement * @param sql SQL code to prepare * @param nparams number of parameters in sql * @return GNUNET_OK on success */ #define GNUNET_POSTGRES_prepare(dbh,name,sql,nparams) GNUNET_POSTGRES_prepare_(dbh,name,sql,nparams,__FILE__,__LINE__) /** * Connect to a postgres database * * @param cfg configuration * @param section configuration section to use to get Postgres configuration options * @return the postgres handle */ PGconn * GNUNET_POSTGRES_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section); /** * Delete the row identified by the given rowid (qid * in postgres). * * @param dbh database handle * @param stmt name of the prepared statement * @param rowid which row to delete * @return GNUNET_OK on success */ int GNUNET_POSTGRES_delete_by_rowid (PGconn *dbh, const char *stmt, uint32_t rowid); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_postgres_lib.h */ #endif gnunet-0.10.1/src/include/gnunet_namecache_service.h0000644000175000017500000001135312227705277017417 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_namecache_service.h * @brief API that can be used to store naming information on a GNUnet node; * Naming information can either be records for which this peer/user * is authoritative, or blocks which are cached, encrypted naming * data from other peers. * @author Christian Grothoff */ #ifndef GNUNET_NAMECACHE_SERVICE_H #define GNUNET_NAMECACHE_SERVICE_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_namestore_service.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Entry in the queue. */ struct GNUNET_NAMECACHE_QueueEntry; /** * Handle to the namecache service. */ struct GNUNET_NAMECACHE_Handle; /** * Maximum size of a value that can be stored in the namecache. */ #define GNUNET_NAMECACHE_MAX_VALUE_SIZE (63 * 1024) /** * Connect to the namecache service. * * @param cfg configuration to use * @return handle to use to access the service */ struct GNUNET_NAMECACHE_Handle * GNUNET_NAMECACHE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Disconnect from the namecache service (and free associated * resources). Must not be called from within operation callbacks of * the API. * * @param h handle to the namecache */ void GNUNET_NAMECACHE_disconnect (struct GNUNET_NAMECACHE_Handle *h); /** * Continuation called to notify client about result of the * operation. * * @param cls closure * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) * #GNUNET_NO if content was already there or not found * #GNUNET_YES (or other positive value) on success * @param emsg NULL on success, otherwise an error message */ typedef void (*GNUNET_NAMECACHE_ContinuationWithStatus) (void *cls, int32_t success, const char *emsg); /** * Store an item in the namecache. If the item is already present, * it is replaced with the new record. * * @param h handle to the namecache * @param block block to store * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return handle to abort the request */ struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_block_cache (struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_GNSRECORD_Block *block, GNUNET_NAMECACHE_ContinuationWithStatus cont, void *cont_cls); /** * Process a record that was stored in the namecache. * * @param cls closure * @param block block that was stored in the namecache */ typedef void (*GNUNET_NAMECACHE_BlockProcessor) (void *cls, const struct GNUNET_GNSRECORD_Block *block); /** * Get a result for a particular key from the namecache. The processor * will only be called once. * * @param h handle to the namecache * @param derived_hash hash of zone key combined with name to lookup * then at the end once with NULL * @param proc function to call on the matching block, or with * NULL if there is no matching block * @param proc_cls closure for @a proc * @return a handle that can be used to cancel */ struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_lookup_block (struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_HashCode *derived_hash, GNUNET_NAMECACHE_BlockProcessor proc, void *proc_cls); /** * Cancel a namecache operation. The final callback from the * operation must not have been done yet. Must be called on any * namecache operation that has not yet completed prior to calling * #GNUNET_NAMECACHE_disconnect. * * @param qe operation to cancel */ void GNUNET_NAMECACHE_cancel (struct GNUNET_NAMECACHE_QueueEntry *qe); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of gnunet_namecache_service.h */ #endif gnunet-0.10.1/src/include/gnunet_getopt_lib.h0000644000175000017500000002767612250322637016131 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_getopt_lib.h * @brief command line parsing and --help formatting * @author Christian Grothoff * @defgroup getopt command-line parsing * @{ */ #ifndef GNUNET_GETOPT_LIB_H #define GNUNET_GETOPT_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_configuration_lib.h" /** * @brief General context for command line processors. */ struct GNUNET_GETOPT_CommandLineProcessorContext { /** * Name of the application */ const char *binaryName; /** * Name of application with option summary */ const char *binaryOptions; /** * Array with all command line options. */ const struct GNUNET_GETOPT_CommandLineOption *allOptions; /** * Original command line */ char *const *argv; /** * Total number of argv's. */ unsigned int argc; /** * Current argument. */ unsigned int currentArgument; }; /** * @brief Process a command line option * * @param ctx context for all options * @param scls specific closure (for this processor) * @param option long name of the option (i.e. "config" for --config) * @param value argument, NULL if none was given * @return #GNUNET_OK to continue processing other options, #GNUNET_SYSERR to abort */ typedef int (*GNUNET_GETOPT_CommandLineOptionProcessor) (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * @brief Definition of a command line option. */ struct GNUNET_GETOPT_CommandLineOption { /** * Short name of the option. */ const char shortName; /** * Long name of the option (may not be NULL) */ const char *name; /** * Name of the argument for the user in help text */ const char *argumentHelp; /** * Help text for the option (description) */ const char *description; /** * Is an argument required? 0: #GNUNET_NO (includes optional), 1: #GNUNET_YES. */ int require_argument; /** * Handler for the option. */ GNUNET_GETOPT_CommandLineOptionProcessor processor; /** * Specific closure to pass to the processor. */ void *scls; }; /** * Macro defining the option to print the command line * help text (-h option). * * @param about string with brief description of the application */ #define GNUNET_GETOPT_OPTION_HELP(about) \ { 'h', "help", (const char *) NULL, gettext_noop("print this help"), 0, &GNUNET_GETOPT_format_help_, (void *) about } /** * Macro defining the option to print the version of * the application (-v option) * * @param version string with the version number */ #define GNUNET_GETOPT_OPTION_VERSION(version) \ { 'v', "version", (const char *) NULL, gettext_noop("print the version number"), 0, &GNUNET_GETOPT_print_version_, (void *) version } /** * Allow user to specify log file name (-l option) * * @param logfn set to the name of the logfile */ #define GNUNET_GETOPT_OPTION_LOGFILE(logfn) \ { 'l', "logfile", "LOGFILE", gettext_noop("configure logging to write logs to LOGFILE"), 1, &GNUNET_GETOPT_set_string, (void *) logfn } /** * Allow user to specify log level (-L option) * * @param loglev set to the log level */ #define GNUNET_GETOPT_OPTION_LOGLEVEL(loglev) \ { 'L', "log", "LOGLEVEL", gettext_noop("configure logging to use LOGLEVEL"), 1, &GNUNET_GETOPT_set_string, (void *) loglev } /** * Get number of verbose (-V) flags * * @param level where to store the verbosity level (should be an 'int') */ #define GNUNET_GETOPT_OPTION_VERBOSE(level) \ { 'V', "verbose", (const char *) NULL, gettext_noop("be verbose"), 0, &GNUNET_GETOPT_increment_value, (void *) level } /** * Get configuration file name (-c option) * * @param fn set to the configuration file name */ #define GNUNET_GETOPT_OPTION_CFG_FILE(fn) \ { 'c', "config", "FILENAME", gettext_noop("use configuration file FILENAME"), 1, &GNUNET_GETOPT_set_string, (void *) fn } /** * Marker for the end of the list of options. */ #define GNUNET_GETOPT_OPTION_END \ { '\0', NULL, NULL, NULL, 0, NULL, NULL } /** * Parse the command line. * * @param binaryOptions Name of application with option summary * @param allOptions defined options and handlers * @param argc number of arguments in @a argv * @param argv actual arguments * @return index into argv with first non-option * argument, or #GNUNET_SYSERR on error */ int GNUNET_GETOPT_run (const char *binaryOptions, const struct GNUNET_GETOPT_CommandLineOption *allOptions, unsigned int argc, char *const *argv); /** * Set an option of type 'unsigned long long' from the command line. * A pointer to this function should be passed as part of the * `struct GNUNET_GETOPT_CommandLineOption` array to initialize options * of this type. It should be followed by a pointer to a value of * type `unsigned long long`. * * @param ctx command line processing context * @param scls additional closure (will point to the 'unsigned long long') * @param option name of the option * @param value actual value of the option as a string. * @return #GNUNET_OK if parsing the value worked */ int GNUNET_GETOPT_set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * Set an option of type 'struct GNUNET_TIME_Relative' from the command line. * A pointer to this function should be passed as part of the * `struct GNUNET_GETOPT_CommandLineOption` array to initialize options * of this type. It should be followed by a pointer to a value of * type `struct GNUNET_TIME_Relative`. * * @param ctx command line processing context * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative') * @param option name of the option * @param value actual value of the option as a string. * @return #GNUNET_OK if parsing the value worked */ int GNUNET_GETOPT_set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * Set an option of type 'unsigned int' from the command line. * A pointer to this function should be passed as part of the * `struct GNUNET_GETOPT_CommandLineOption` array to initialize options * of this type. It should be followed by a pointer to a value of * type `unsigned int`. * * @param ctx command line processing context * @param scls additional closure (will point to the 'unsigned int') * @param option name of the option * @param value actual value of the option as a string. * @return #GNUNET_OK if parsing the value worked */ int GNUNET_GETOPT_set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * Set an option of type 'int' from the command line to 1 if the * given option is present. * A pointer to this function should be passed as part of the * `struct GNUNET_GETOPT_CommandLineOption` array to initialize options * of this type. It should be followed by a pointer to a value of * type `int`. * * @param ctx command line processing context * @param scls additional closure (will point to the `int`) * @param option name of the option * @param value not used (NULL) * @return #GNUNET_OK (always) */ int GNUNET_GETOPT_set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * Set an option of type 'char *' from the command line. * A pointer to this function should be passed as part of the * `struct GNUNET_GETOPT_CommandLineOption` array to initialize options * of this type. It should be followed by a pointer to a value of * type `char *`, which will be allocated with the requested string. * * @param ctx command line processing context * @param scls additional closure (will point to the `char *`, * which will be allocated) * @param option name of the option * @param value actual value of the option (a string) * @return #GNUNET_OK (always) */ int GNUNET_GETOPT_set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * Set an option of type 'char *' from the command line doing fs expansion. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'char *', which will be allocated with the requested string. * * @param ctx command line processing context * @param scls additional closure (will point to the 'char *', * which will be allocated) * @param option name of the option * @param value actual value of the option (a string) * @return #GNUNET_OK (always) */ int GNUNET_GETOPT_set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * Set an option of type 'unsigned int' from the command line. Each * time the option flag is given, the value is incremented by one. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'int'. * * @param ctx command line processing context * @param scls additional closure (will point to the 'int') * @param option name of the option * @param value not used (NULL) * @return #GNUNET_OK (always) */ int GNUNET_GETOPT_increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /* *************** internal prototypes - use macros above! ************* */ /** * Print out details on command line options (implements --help). * * @param ctx command line processing context * @param scls additional closure (points to about text) * @param option name of the option * @param value not used (NULL) * @return #GNUNET_NO (do not continue, not an error) */ int GNUNET_GETOPT_format_help_ (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * Print out program version (implements --version). * * @param ctx command line processing context * @param scls additional closure (points to version string) * @param option name of the option * @param value not used (NULL) * @return #GNUNET_NO (do not continue, not an error) */ int GNUNET_GETOPT_print_version_ (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group getopt */ /* ifndef GNUNET_GETOPT_LIB_H */ #endif /* end of gnunet_getopt_lib.h */ gnunet-0.10.1/src/include/gnunet_testbed_logger_service.h0000644000175000017500000000711012225777503020477 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_testbed_logger_service.h * @brief API for submitting data to the testbed logger service * @author Sree Harsha Totakura */ #ifndef GNUNET_TESTBED_LOGGER_SERVICE_H #define GNUNET_TESTBED_LOGGER_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_configuration_lib.h" /** * Opaque handle for the logging service */ struct GNUNET_TESTBED_LOGGER_Handle; /** * Connect to the testbed logger service * * @param cfg configuration to use * @return the handle which can be used for sending data to the service; NULL * upon any error */ struct GNUNET_TESTBED_LOGGER_Handle * GNUNET_TESTBED_LOGGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Disconnect from the logger service. Also cancels any pending send handles. * * @param h the logger handle */ void GNUNET_TESTBED_LOGGER_disconnect (struct GNUNET_TESTBED_LOGGER_Handle *h); /** * Functions of this type are called to notify a successful transmission of the * message to the logger service * * @param cls the closure given to GNUNET_TESTBED_LOGGER_send() * @param size the amount of data sent */ typedef void (*GNUNET_TESTBED_LOGGER_FlushCompletion) (void *cls, size_t size); /** * Send data to be logged to the logger service. The data will be buffered and * will be sent upon an explicit call to GNUNET_TESTBED_LOGGER_flush() or upon * exceeding a threshold size. * * @param h the logger handle * @param data the data to send; * @param size how many bytes of data to send */ void GNUNET_TESTBED_LOGGER_write (struct GNUNET_TESTBED_LOGGER_Handle *h, const void *data, size_t size); /** * Flush the buffered data to the logger service * * @param h the logger handle * @param timeout how long to wait before calling the flust completion callback * @param cb the callback to call after the data is flushed * @param cb_cls the closure for the above callback */ void GNUNET_TESTBED_LOGGER_flush (struct GNUNET_TESTBED_LOGGER_Handle *h, struct GNUNET_TIME_Relative timeout, GNUNET_TESTBED_LOGGER_FlushCompletion cb, void *cb_cls); /** * Cancel notification upon flush. Should only be used when the flush * completion callback given to GNUNET_TESTBED_LOGGER_flush() is not already * called. * * @param h the logger handle */ void GNUNET_TESTBED_LOGGER_flush_cancel (struct GNUNET_TESTBED_LOGGER_Handle *h); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif /* GNUNET_TESTBED_LOGGER_SERVICE_H */ /* End of gnunet_testbed_logger_service.h */ gnunet-0.10.1/src/include/gnunet_os_lib.h0000644000175000017500000004056412301361473015235 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_os_lib.h * @brief low level process routines * @author Christian Grothoff * @author Krista Bennett * @author Gerd Knorr * @author Ioana Patrascu * @author Tzvetan Horozov * @author Milan * * This code manages child processes. We can communicate with child * processes using signals. Because signals are not supported on W32 * and Java (at least not nicely), we can alternatively use a pipe * to send signals to the child processes (if the child process is * a full-blown GNUnet process that supports reading signals from * a pipe, of course). Naturally, this also only works for 'normal' * termination via signals, and not as a replacement for SIGKILL. * Thus using pipes to communicate signals should only be enabled if * the child is a Java process OR if we are on Windoze. */ #ifndef GNUNET_OS_LIB_H #define GNUNET_OS_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_common.h" #include "gnunet_configuration_lib.h" #include "gnunet_scheduler_lib.h" /** * Flags that determine which of the standard streams * should be inherited by the child process. */ enum GNUNET_OS_InheritStdioFlags { /** * No standard streams should be inherited. */ GNUNET_OS_INHERIT_STD_NONE = 0, /** * When this flag is set, the child process will * inherit stdin of the parent. */ GNUNET_OS_INHERIT_STD_IN = 1, /** * When this flag is set, the child process will * inherit stdout of the parent. */ GNUNET_OS_INHERIT_STD_OUT = 2, /** * When this flag is set, the child process will * inherit stderr of the parent. */ GNUNET_OS_INHERIT_STD_ERR = 4, /** * When these flags are set, the child process will * inherit stdout and stderr of the parent. */ GNUNET_OS_INHERIT_STD_OUT_AND_ERR = 6, /** * Use this option to have all of the standard streams * (stdin, stdout and stderror) be inherited. */ GNUNET_OS_INHERIT_STD_ALL = 7 }; /** * Process information (OS-dependent) */ struct GNUNET_OS_Process; /** * Possible installation paths to request */ enum GNUNET_OS_InstallationPathKind { /** * Return the "PREFIX" directory given to configure. */ GNUNET_OS_IPK_PREFIX, /** * Return the directory where the program binaries are installed. (bin/) */ GNUNET_OS_IPK_BINDIR, /** * Return the directory where libraries are installed. (lib/gnunet/) */ GNUNET_OS_IPK_LIBDIR, /** * Return the directory where data is installed (share/gnunet/) */ GNUNET_OS_IPK_DATADIR, /** * Return the directory where translations are installed (share/locale/) */ GNUNET_OS_IPK_LOCALEDIR, /** * Return the installation directory of this application, not * the one of the overall GNUnet installation (in case they * are different). */ GNUNET_OS_IPK_SELF_PREFIX, /** * Return the prefix of the path with application icons (share/icons/). */ GNUNET_OS_IPK_ICONDIR, /** * Return the prefix of the path with documentation files, including the * license (share/doc/gnunet/). */ GNUNET_OS_IPK_DOCDIR, /** * Return the directory where helper binaries are installed (lib/gnunet/libexec/) */ GNUNET_OS_IPK_LIBEXECDIR }; /** * Process status types */ enum GNUNET_OS_ProcessStatusType { /** * The process is not known to the OS (or at * least not one of our children). */ GNUNET_OS_PROCESS_UNKNOWN, /** * The process is still running. */ GNUNET_OS_PROCESS_RUNNING, /** * The process is paused (but could be resumed). */ GNUNET_OS_PROCESS_STOPPED, /** * The process exited with a return code. */ GNUNET_OS_PROCESS_EXITED, /** * The process was killed by a signal. */ GNUNET_OS_PROCESS_SIGNALED }; /** * Get the path to a specific GNUnet installation directory or, with * #GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation * directory. * * @param dirkind what kind of directory is desired? * @return a pointer to the dir path (to be freed by the caller) */ char * GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind); /** * Given the name of a gnunet-helper, gnunet-service or gnunet-daemon * binary, try to prefix it with the libexec/-directory to get the * full path. * * @param progname name of the binary * @return full path to the binary, if possible, otherwise copy of 'progname' */ char * GNUNET_OS_get_libexec_binary_path (const char *progname); /** * Callback function invoked for each interface found. * * @param cls closure * @param name name of the interface (can be NULL for unknown) * @param isDefault is this presumably the default interface * @param addr address of this interface (can be NULL for unknown or unassigned) * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) * @param netmask the network mask (can be NULL for unknown or unassigned) * @param addrlen length of the address * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort */ typedef int (*GNUNET_OS_NetworkInterfaceProcessor) (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen); /** * @brief Enumerate all network interfaces * * @param proc the callback function * @param proc_cls closure for @a proc */ void GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, void *proc_cls); /** * @brief Get maximum string length returned by gethostname() */ #if HAVE_SYSCONF && defined(_SC_HOST_NAME_MAX) #define GNUNET_OS_get_hostname_max_length() ({ int __sc_tmp = sysconf(_SC_HOST_NAME_MAX); __sc_tmp <= 0 ? 255 : __sc_tmp; }) #elif defined(HOST_NAME_MAX) #define GNUNET_OS_get_hostname_max_length() HOST_NAME_MAX #else #define GNUNET_OS_get_hostname_max_length() 255 #endif /** * Get process structure for current process * * The pointer it returns points to static memory location and must not be * deallocated/closed * * @return pointer to the process sturcutre for this process */ struct GNUNET_OS_Process * GNUNET_OS_process_current (void); /** * Sends a signal to the process * * @param proc pointer to process structure * @param sig signal * @return 0 on success, -1 on error */ int GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig); /** * Cleans up process structure contents (OS-dependent) and deallocates it * * @param proc pointer to process structure */ void GNUNET_OS_process_destroy (struct GNUNET_OS_Process *proc); /** * Get the pid of the process in question * * @param proc the process to get the pid of * * @return the current process id */ pid_t GNUNET_OS_process_get_pid (struct GNUNET_OS_Process *proc); /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param pipe_stdin pipe to use to send input to child process (or NULL) * @param pipe_stdout pipe to use to get output from child process (or NULL) * @param pipe_stderr pipe to use to get error output from child process (or NULL) * @param filename name of the binary * @param argv NULL-terminated array of arguments to the process * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process_vap (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename, char *const argv[]); /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param pipe_stdin pipe to use to send input to child process (or NULL) * @param pipe_stdout pipe to use to get output from child process (or NULL) * @param pipe_stderr pipe to use to get error output from child process (or NULL) * @param filename name of the binary * @param ... NULL-terminated list of arguments to the process * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename, ...); /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param pipe_stdin pipe to use to send input to child process (or NULL) * @param pipe_stdout pipe to use to get output from child process (or NULL) * @param pipe_stderr pipe to use to get error output from child process (or NULL) * @param filename name of the binary * @param va NULL-terminated list of arguments to the process * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process_va (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename, va_list va); /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param lsocks array of listen sockets to dup systemd-style (or NULL); * must be NULL on platforms where dup is not supported * @param filename name of the binary * @param argv NULL-terminated list of arguments to the process, * including the process name as the first argument * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process_v (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, const SOCKTYPE *lsocks, const char *filename, char *const argv[]); /** * Start a process. This function is similar to the GNUNET_OS_start_process_* * except that the filename and arguments can have whole strings which contain * the arguments. These arguments are to be separated by spaces and are parsed * in the order they appear. Arguments containing spaces can be used by * quoting them with @em ". * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param lsocks array of listen sockets to dup systemd-style (or NULL); * must be NULL on platforms where dup is not supported * @param filename name of the binary. It is valid to have the arguments * in this string when they are separated by spaces. * @param ... more arguments. Should be of type `char *`. It is valid * to have the arguments in these strings when they are separated by * spaces. The last argument MUST be NULL. * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process_s (int pipe_control, unsigned int std_inheritance, const SOCKTYPE * lsocks, const char *filename, ...); /** * Handle to a command action. */ struct GNUNET_OS_CommandHandle; /** * Type of a function to process a line of output. * * @param cls closure * @param line line of output from a command, NULL for the end */ typedef void (*GNUNET_OS_LineProcessor) (void *cls, const char *line); /** * Stop/kill a command. * * @param cmd handle to the process */ void GNUNET_OS_command_stop (struct GNUNET_OS_CommandHandle *cmd); /** * Run the given command line and call the given function * for each line of the output. * * @param proc function to call for each line of the output * @param proc_cls closure for proc * @param timeout when to time out * @param binary command to run * @param ... arguments to command * @return NULL on error */ struct GNUNET_OS_CommandHandle * GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls, struct GNUNET_TIME_Relative timeout, const char *binary, ...); /** * Retrieve the status of a process, waiting on him if dead. * Nonblocking version. * * @param proc pointer to process structure * @param type status type * @param code return code/signal number * @return #GNUNET_OK on success, #GNUNET_NO if the process is still running, #GNUNET_SYSERR otherwise */ int GNUNET_OS_process_status (struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code); /** * Wait for a process to terminate. The return code is discarded. * You must not use 'GNUNET_OS_process_status' on the same process * after calling this function! This function is blocking and should * thus only be used if the child process is known to have terminated * or to terminate very soon. * * @param proc pointer to process structure of the process to wait for * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc); /** * Connects this process to its parent via pipe; * essentially, the parent control handler will read signal numbers * from the 'GNUNET_OS_CONTROL_PIPE' (as given in an environment * variable) and raise those signals. * * @param cls closure (unused) * @param tc scheduler context (unused) */ void GNUNET_OS_install_parent_control_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Check whether an executable exists and possibly * if the suid bit is set on the file. * Attempts to find the file using the current * PATH environment variable as a search path. * * @param binary the name of the file to check. * W32: must not have an .exe suffix. * @param check_suid input true if the binary should be checked for SUID (*nix) * W32: checks if the program has sufficient privileges by executing this * binary with the -d flag. -d omits a programs main loop and only * executes all privileged operations in an binary. * @param params parameters used for w32 privilege checking (can be NULL for != w32, or when not checking for suid/permissions ) * @return #GNUNET_YES if the file is SUID (*nix) or can be executed with current privileges (W32), * #GNUNET_NO if not SUID (but binary exists), * #GNUNET_SYSERR on error (no such binary or not executable) */ int GNUNET_OS_check_helper_binary (const char *binary, int check_suid, const char * params); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_OS_LIB_H */ #endif /* end of gnunet_os_lib.h */ gnunet-0.10.1/src/include/block_regex.h0000644000175000017500000000353412225777503014700 00000000000000/* This file is part of GNUnet. (C) 2012,2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/block_regex.h * @brief regex block formats * @author Bartlomiej Polot */ #ifndef BLOCK_REGEX_H #define BLOCK_REGEX_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" #include GNUNET_NETWORK_STRUCT_BEGIN /** * @brief Block to announce a peer accepting a state. */ struct RegexAcceptBlock { /** * Accept blocks must be signed. Signature * goes over expiration time and key. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * When does the signature expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The key of the state. */ struct GNUNET_HashCode key; /** * Public key of the peer signing. */ struct GNUNET_PeerIdentity peer; /** * The signature. */ struct GNUNET_CRYPTO_EddsaSignature signature; }; GNUNET_NETWORK_STRUCT_END #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_fs_service.h0000644000175000017500000023202212230245272016105 00000000000000/* This file is part of GNUnet (C) 2004--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_fs_service.h * @brief API for file-sharing via GNUnet * @author Christian Grothoff */ #ifndef GNUNET_FS_LIB_H #define GNUNET_FS_LIB_H #include "gnunet_util_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Version number of the implementation. * History: * * 1.x.x: initial version with triple GNUNET_hash and merkle tree * 2.x.x: root node with mime-type, filename and version number * 2.1.x: combined GNUNET_EC_ContentHashKey/3HASH encoding with 25:1 super-nodes * 2.2.x: with directories * 3.0.x: with namespaces * 3.1.x: with namespace meta-data * 3.2.x: with collections * 4.0.x: with expiration, variable meta-data, kblocks * 4.1.x: with new error and configuration handling * 5.0.x: with location URIs * 6.0.0: with support for OR in KSKs * 6.1.x: with simplified namespace support * 9.0.0: CPS-style integrated API * 9.1.1: asynchronous directory scanning * 9.2.0: unified K-Block and S-block format (#2564) */ #define GNUNET_FS_VERSION 0x00090200 /* ******************** URI API *********************** */ #define GNUNET_FS_URI_PREFIX "gnunet://fs/" #define GNUNET_FS_URI_KSK_INFIX "ksk/" #define GNUNET_FS_URI_SKS_INFIX "sks/" #define GNUNET_FS_URI_CHK_INFIX "chk/" #define GNUNET_FS_URI_LOC_INFIX "loc/" /** * How often do we signal applications that a probe for a particular * search result is running? (used to visualize probes). */ #define GNUNET_FS_PROBE_UPDATE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) /** * A Universal Resource Identifier (URI), opaque. */ struct GNUNET_FS_Uri; /** * Iterator over keywords * * @param cls closure * @param keyword the keyword * @param is_mandatory is the keyword mandatory (in a search) * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to abort */ typedef int (*GNUNET_FS_KeywordIterator) (void *cls, const char *keyword, int is_mandatory); /** * Get a unique key from a URI. This is for putting URIs * into HashMaps. The key may change between FS implementations. * * @param uri uri to convert to a unique key * @param key wherer to store the unique key */ void GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri, struct GNUNET_HashCode *key); /** * Convert a URI to a UTF-8 String. * * @param uri uri to convert to a string * @return the UTF-8 string */ char * GNUNET_FS_uri_to_string (const struct GNUNET_FS_Uri *uri); /** * Convert keyword URI to a human readable format * (i.e. the search query that was used in the first place) * * @param uri ksk uri to convert to a string * @return string with the keywords */ char * GNUNET_FS_uri_ksk_to_string_fancy (const struct GNUNET_FS_Uri *uri); /** * Add the given keyword to the set of keywords represented by the URI. * Does nothing if the keyword is already present. * * @param uri ksk uri to modify * @param keyword keyword to add * @param is_mandatory is this keyword mandatory? */ void GNUNET_FS_uri_ksk_add_keyword (struct GNUNET_FS_Uri *uri, const char *keyword, int is_mandatory); /** * Remove the given keyword from the set of keywords represented by the URI. * Does nothing if the keyword is not present. * * @param uri ksk uri to modify * @param keyword keyword to add */ void GNUNET_FS_uri_ksk_remove_keyword (struct GNUNET_FS_Uri *uri, const char *keyword); /** * Convert a UTF-8 String to a URI. * * @param uri string to parse * @param emsg where to store the parser error message (if any) * @return NULL on error */ struct GNUNET_FS_Uri * GNUNET_FS_uri_parse (const char *uri, char **emsg); /** * Free URI. * * @param uri uri to free */ void GNUNET_FS_uri_destroy (struct GNUNET_FS_Uri *uri); /** * How many keywords are ANDed in this keyword URI? * * @param uri ksk uri to get the number of keywords from * @return 0 if this is not a keyword URI */ unsigned int GNUNET_FS_uri_ksk_get_keyword_count (const struct GNUNET_FS_Uri *uri); /** * Iterate over all keywords in this keyword URI. * * @param uri ksk uri to get the keywords from * @param iterator function to call on each keyword * @param iterator_cls closure for @a iterator * @return -1 if this is not a keyword URI, otherwise number of * keywords iterated over until iterator aborted */ int GNUNET_FS_uri_ksk_get_keywords (const struct GNUNET_FS_Uri *uri, GNUNET_FS_KeywordIterator iterator, void *iterator_cls); /** * Obtain the identity of the peer offering the data * * @param uri the location URI to inspect * @param peer where to store the identify of the peer (presumably) offering the content * @return #GNUNET_SYSERR if this is not a location URI, otherwise #GNUNET_OK */ int GNUNET_FS_uri_loc_get_peer_identity (const struct GNUNET_FS_Uri *uri, struct GNUNET_PeerIdentity *peer); /** * Obtain the URI of the content itself. * * @param uri location URI to get the content URI from * @return NULL if argument is not a location URI */ struct GNUNET_FS_Uri * GNUNET_FS_uri_loc_get_uri (const struct GNUNET_FS_Uri *uri); /** * Obtain the expiration of the LOC URI. * * @param uri location URI to get the expiration from * @return expiration time of the URI */ struct GNUNET_TIME_Absolute GNUNET_FS_uri_loc_get_expiration (const struct GNUNET_FS_Uri *uri); /** * Construct a location URI (this peer will be used for the location). * * @param baseUri content offered by the sender * @param cfg configuration information (used to find our hostkey) * @param expiration_time how long will the content be offered? * @return the location URI, NULL on error */ struct GNUNET_FS_Uri * GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TIME_Absolute expiration_time); /** * Merge the sets of keywords from two KSK URIs. * * @param u1 first uri * @param u2 second uri * @return merged URI, NULL on error */ struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_merge (const struct GNUNET_FS_Uri *u1, const struct GNUNET_FS_Uri *u2); /** * Duplicate URI. * * @param uri the URI to duplicate * @return copy of the URI */ struct GNUNET_FS_Uri * GNUNET_FS_uri_dup (const struct GNUNET_FS_Uri *uri); /** * Create an FS URI from a single user-supplied string of keywords. * The string is broken up at spaces into individual keywords. * Keywords that start with "+" are mandatory. Double-quotes can * be used to prevent breaking up strings at spaces (and also * to specify non-mandatory keywords starting with "+"). * * Keywords must contain a balanced number of double quotes and * double quotes can not be used in the actual keywords (for * example, the string '""foo bar""' will be turned into two * "OR"ed keywords 'foo' and 'bar', not into '"foo bar"'. * * @param keywords the keyword string * @param emsg where to store an error message * @return an FS URI for the given keywords, NULL * if keywords is not legal (i.e. empty). */ struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create (const char *keywords, char **emsg); /** * Create an FS URI from a user-supplied command line of keywords. * Arguments should start with "+" to indicate mandatory * keywords. * * @param argc number of keywords * @param argv keywords (double quotes are not required for * keywords containing spaces; however, double * quotes are required for keywords starting with * "+"); there is no mechanism for having double * quotes in the actual keywords (if the user * did specifically specify double quotes, the * caller should convert each double quote * into two single quotes). * @return an FS URI for the given keywords, NULL * if keywords is not legal (i.e. empty). */ struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create_from_args (unsigned int argc, const char **argv); /** * Test if two URIs are equal. * * @param u1 one of the URIs * @param u2 the other URI * @return #GNUNET_YES if the URIs are equal */ int GNUNET_FS_uri_test_equal (const struct GNUNET_FS_Uri *u1, const struct GNUNET_FS_Uri *u2); /** * Is this a namespace URI? * * @param uri the uri to check * @return #GNUNET_YES if this is an SKS uri */ int GNUNET_FS_uri_test_sks (const struct GNUNET_FS_Uri *uri); /** * Create an SKS URI from a namespace ID and an identifier. * * @param ns pseudonym to use * @param id identifier * @return an FS URI for the given namespace and identifier */ struct GNUNET_FS_Uri * GNUNET_FS_uri_sks_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *ns, const char *id); /** * Get the public key of a namespace from the given * namespace URI. * * @param uri the uri to get the namespace ID from * @param pseudonym where to store the public key of the namespace * @return #GNUNET_OK on success */ int GNUNET_FS_uri_sks_get_namespace (const struct GNUNET_FS_Uri *uri, struct GNUNET_CRYPTO_EcdsaPublicKey *pseudonym); /** * Get the content identifier of an SKS URI. * * @param uri the sks uri * @return NULL on error (not a valid SKS URI) */ char * GNUNET_FS_uri_sks_get_content_id (const struct GNUNET_FS_Uri *uri); /** * Is this a keyword URI? * * @param uri the uri * @return #GNUNET_YES if this is a KSK uri */ int GNUNET_FS_uri_test_ksk (const struct GNUNET_FS_Uri *uri); /** * Is this a file (or directory) URI? * * @param uri the uri to check * @return #GNUNET_YES if this is a CHK uri */ int GNUNET_FS_uri_test_chk (const struct GNUNET_FS_Uri *uri); /** * What is the size of the file that this URI * refers to? * * @param uri the CHK (or LOC) URI to inspect * @return size of the file as specified in the CHK URI */ uint64_t GNUNET_FS_uri_chk_get_file_size (const struct GNUNET_FS_Uri *uri); /** * Is this a location URI? * * @param uri the uri to check * @return #GNUNET_YES if this is a LOC uri */ int GNUNET_FS_uri_test_loc (const struct GNUNET_FS_Uri *uri); /** * Construct a keyword-URI from meta-data (take all entries * in the meta-data and construct one large keyword URI * that lists all keywords that can be found in the meta-data). * * @param md metadata to use * @return NULL on error, otherwise a KSK URI */ struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create_from_meta_data (const struct GNUNET_CONTAINER_MetaData *md); /* ******************** command-line option parsing API *********************** */ /** * Command-line option parser function that allows the user * to specify one or more '-k' options with keywords. Each * specified keyword will be added to the URI. A pointer to * the URI must be passed as the "scls" argument. * * @param ctx command line processor context * @param scls must be of type "struct GNUNET_FS_Uri **" * @param option name of the option (typically 'k') * @param value command line argument given * @return #GNUNET_OK on success */ int GNUNET_FS_getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /** * Command-line option parser function that allows the user to specify * one or more '-m' options with metadata. Each specified entry of * the form "type=value" will be added to the metadata. A pointer to * the metadata must be passed as the "scls" argument. * * @param ctx command line processor context * @param scls must be of type `struct GNUNET_CONTAINER_MetaData **` * @param option name of the option (typically 'k') * @param value command line argument given * @return #GNUNET_OK on success */ int GNUNET_FS_getopt_set_metadata (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value); /* ************************* sharing API ***************** */ /** * Possible status codes used in the callback for the * various file-sharing operations. On each file (or search), * the callback is guaranteed to be called once with "START" * and once with STOPPED; calls with PROGRESS, ERROR or COMPLETED * are optional and depend on the circumstances; parent operations * will be STARTED before child-operations and STOPPED after * their respective child-operations. START and STOP signals * are typically generated either due to explicit client requests * or because of suspend/resume operations. */ enum GNUNET_FS_Status { /** * Notification that we have started to publish a file structure. */ GNUNET_FS_STATUS_PUBLISH_START = 0, /** * Notification that we have resumed sharing a file structure. */ GNUNET_FS_STATUS_PUBLISH_RESUME = 1, /** * Notification that we have suspended sharing a file structure. */ GNUNET_FS_STATUS_PUBLISH_SUSPEND = 2, /** * Notification that we are making progress sharing a file structure. */ GNUNET_FS_STATUS_PUBLISH_PROGRESS = 3, /** * Notification that an error was encountered sharing a file structure. * The application will continue to receive resume/suspend events for * this structure until "GNUNET_FS_publish_stop" is called. */ GNUNET_FS_STATUS_PUBLISH_ERROR = 4, /** * Notification that we completed sharing a file structure. * The application will continue to receive resume/suspend events for * this structure until "GNUNET_FS_publish_stop" is called. */ GNUNET_FS_STATUS_PUBLISH_COMPLETED = 5, /** * Notification that we have stopped * the process of uploading a file structure; no * futher events will be generated for this action. */ GNUNET_FS_STATUS_PUBLISH_STOPPED = 6, /** * Notification that we have started this download. */ GNUNET_FS_STATUS_DOWNLOAD_START = 7, /** * Notification that this download is being resumed. */ GNUNET_FS_STATUS_DOWNLOAD_RESUME = 8, /** * Notification that this download was suspended. */ GNUNET_FS_STATUS_DOWNLOAD_SUSPEND = 9, /** * Notification about progress with this download. */ GNUNET_FS_STATUS_DOWNLOAD_PROGRESS = 10, /** * Notification that this download encountered an error. */ GNUNET_FS_STATUS_DOWNLOAD_ERROR = 11, /** * Notification that this download completed. Note that for * directories, completion does not imply completion of all files in * the directory. */ GNUNET_FS_STATUS_DOWNLOAD_COMPLETED = 12, /** * Notification that this download was stopped * (final event with respect to this action). */ GNUNET_FS_STATUS_DOWNLOAD_STOPPED = 13, /** * Notification that this download is now actively being * pursued (as opposed to waiting in the queue). */ GNUNET_FS_STATUS_DOWNLOAD_ACTIVE = 14, /** * Notification that this download is no longer actively * being pursued (back in the queue). */ GNUNET_FS_STATUS_DOWNLOAD_INACTIVE = 15, /** * Notification that this download is no longer part of a * recursive download or search but now a 'stand-alone' * download (and may thus need to be moved in the GUI * into a different category). */ GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT = 16, /** * First event generated when a client requests * a search to begin or when a namespace result * automatically triggers the search for updates. */ GNUNET_FS_STATUS_SEARCH_START = 17, /** * Last event when a search is being resumed; * note that "GNUNET_FS_SEARCH_START" will not * be generated in this case. */ GNUNET_FS_STATUS_SEARCH_RESUME = 18, /** * Event generated for each search result * when the respective search is resumed. */ GNUNET_FS_STATUS_SEARCH_RESUME_RESULT = 19, /** * Last event when a search is being suspended; * note that "GNUNET_FS_SEARCH_STOPPED" will not * be generated in this case. */ GNUNET_FS_STATUS_SEARCH_SUSPEND = 20, /** * This search has yielded a result. */ GNUNET_FS_STATUS_SEARCH_RESULT = 21, /** * We have discovered a new namespace. */ GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE = 22, /** * We have additional data about the quality * or availability of a search result. */ GNUNET_FS_STATUS_SEARCH_UPDATE = 23, /** * Signals a problem with this search. */ GNUNET_FS_STATUS_SEARCH_ERROR = 24, /** * Signals that this search was paused. */ GNUNET_FS_STATUS_SEARCH_PAUSED = 25, /** * Signals that this search was continued (unpaused). */ GNUNET_FS_STATUS_SEARCH_CONTINUED = 26, /** * Event generated for each search result * when the respective search is stopped. */ GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED = 27, /** * Event generated for each search result * when the respective search is suspended. */ GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND = 28, /** * Last message from a search; this signals * that there will be no further events associated * with this search. */ GNUNET_FS_STATUS_SEARCH_STOPPED = 29, /** * Notification that we started to unindex a file. */ GNUNET_FS_STATUS_UNINDEX_START = 30, /** * Notification that we resumed unindexing of a file. */ GNUNET_FS_STATUS_UNINDEX_RESUME = 31, /** * Notification that we suspended unindexing a file. */ GNUNET_FS_STATUS_UNINDEX_SUSPEND = 32, /** * Notification that we made progress unindexing a file. */ GNUNET_FS_STATUS_UNINDEX_PROGRESS = 33, /** * Notification that we encountered an error unindexing * a file. */ GNUNET_FS_STATUS_UNINDEX_ERROR = 34, /** * Notification that the unindexing of this file * was completed. */ GNUNET_FS_STATUS_UNINDEX_COMPLETED = 35, /** * Notification that the unindexing of this file * was stopped (final event for this action). */ GNUNET_FS_STATUS_UNINDEX_STOPPED = 36, /** * Notification that we are making progress sharing a directory. */ GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY = 37 }; /** * Handle for controlling an upload. */ struct GNUNET_FS_PublishContext; /** * Handle for controlling an unindexing operation. */ struct GNUNET_FS_UnindexContext; /** * Handle for controlling a search. */ struct GNUNET_FS_SearchContext; /** * Result from a search. Opaque handle to refer to the search * (typically used when starting a download associated with the search * result). */ struct GNUNET_FS_SearchResult; /** * Context for controlling a download. */ struct GNUNET_FS_DownloadContext; /** * Handle for detail information about a file that is being publishd. * Specifies metadata, keywords, how to get the contents of the file * (i.e. data-buffer in memory, filename on disk) and other options. */ struct GNUNET_FS_FileInformation; /** * Argument given to the progress callback with * information about what is going on. */ struct GNUNET_FS_ProgressInfo { /** * Values that depend on the event type. */ union { /** * Values for all "GNUNET_FS_STATUS_PUBLISH_*" events. */ struct { /** * Context for controlling the upload. */ struct GNUNET_FS_PublishContext *pc; /** * Information about the file that is being publishd. */ const struct GNUNET_FS_FileInformation *fi; /** * Client context pointer (set the last time by the client for * this operation; initially NULL on START/RESUME events). */ void *cctx; /** * Client context pointer for the parent operation * (if this is a file in a directory or a subdirectory). */ void *pctx; /** * Name of the file being published; can be NULL. */ const char *filename; /** * How large is the file overall? For directories, * this is only the size of the directory itself, * not of the other files contained within the * directory. */ uint64_t size; /** * At what time do we expect to finish the upload? * (will be a value in the past for completed * uploads). */ struct GNUNET_TIME_Relative eta; /** * How long has this upload been actively running * (excludes times where the upload was suspended). */ struct GNUNET_TIME_Relative duration; /** * How many bytes have we completed? */ uint64_t completed; /** * What anonymity level is used for this upload? */ uint32_t anonymity; /** * Additional values for specific events. */ union { /** * These values are only valid for * #GNUNET_FS_STATUS_PUBLISH_PROGRESS events. */ struct { /** * Data block we just published. */ const void *data; /** * At what offset in the file is "data"? */ uint64_t offset; /** * Length of the data block. */ uint64_t data_len; /** * Depth of the given block in the tree; * 0 would be the lowest level (DBLOCKs). */ unsigned int depth; } progress; /** * These values are only valid for * #GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY events. */ struct { /** * How far are we along in the overall directory? */ uint64_t completed; /** * How big do we estimate the entire directory to be? */ uint64_t total; /** * At what time do we expect to finish the upload of the * CONTENTS of the directory. (The direcory itself will take * extra time, indicated with the "eta" member at the * "publish"-level of this struct.) */ struct GNUNET_TIME_Relative eta; } progress_directory; /** * These values are only valid for * #GNUNET_FS_STATUS_PUBLISH_RESUME events. */ struct { /** * Error message, NULL if no error was encountered so far. */ const char *message; /** * URI of the file (if the download had been completed) */ const struct GNUNET_FS_Uri *chk_uri; } resume; /** * These values are only valid for * #GNUNET_FS_STATUS_PUBLISH_COMPLETED events. */ struct { /** * URI of the file. */ const struct GNUNET_FS_Uri *chk_uri; } completed; /** * These values are only valid for * #GNUNET_FS_STATUS_PUBLISH_ERROR events. */ struct { /** * Error message, never NULL. */ const char *message; } error; } specifics; } publish; /** * Values for all "GNUNET_FS_STATUS_DOWNLOAD_*" events. */ struct { /** * Context for controlling the download. */ struct GNUNET_FS_DownloadContext *dc; /** * Client context pointer (set the last time * by the client for this operation; initially * NULL on START/RESUME events). */ void *cctx; /** * Client context pointer for the parent operation * (if this is a file in a directory or a subdirectory). */ void *pctx; /** * Client context pointer for the associated search operation * (specifically, context pointer for the specific search * result, not the overall search); only set if this * download was started from a search result. */ void *sctx; /** * URI used for this download. */ const struct GNUNET_FS_Uri *uri; /** * Name of the file that we are downloading. */ const char *filename; /** * How large is the download overall? This * is NOT necessarily the size from the * URI since we may be doing a partial download. */ uint64_t size; /** * At what time do we expect to finish the download? * (will be a value in the past for completed * uploads). */ struct GNUNET_TIME_Relative eta; /** * How long has this download been active? */ struct GNUNET_TIME_Relative duration; /** * How many bytes have we completed? */ uint64_t completed; /** * What anonymity level is used for this download? */ uint32_t anonymity; /** * Is the download currently active. */ int is_active; /** * Additional values for specific events. */ union { /** * These values are only valid for * #GNUNET_FS_STATUS_DOWNLOAD_PROGRESS events. */ struct { /** * Data block we just obtained, can be NULL (even if * data_len > 0) if we found the entire block 'intact' on * disk. In this case, it is also possible for 'data_len' * to be larger than an individual (32k) block. */ const void *data; /** * At what offset in the file is "data"? */ uint64_t offset; /** * Length of the data block. */ uint64_t data_len; /** * How much time passed between us asking for this block and * actually getting it? #GNUNET_TIME_UNIT_FOREVER_REL if unknown. */ struct GNUNET_TIME_Relative block_download_duration; /** * Depth of the given block in the tree; * 0 would be the lowest level (DBLOCKS). */ unsigned int depth; /** * How much respect did we offer for downloading this block? (estimate, * because we might have the same request pending for multiple clients, * and of course because a transmission may have failed at a lower * layer). */ uint32_t respect_offered; /** * How often did we transmit the request? (estimate, * because we might have the same request pending for multiple clients, * and of course because a transmission may have failed at a lower * layer). */ uint32_t num_transmissions; } progress; /** * These values are only valid for * #GNUNET_FS_STATUS_DOWNLOAD_START events. */ struct { /** * Known metadata for the download. */ const struct GNUNET_CONTAINER_MetaData *meta; } start; /** * These values are only valid for * #GNUNET_FS_STATUS_DOWNLOAD_RESUME events. */ struct { /** * Known metadata for the download. */ const struct GNUNET_CONTAINER_MetaData *meta; /** * Error message, NULL if we have not encountered any error yet. */ const char *message; } resume; /** * These values are only valid for * #GNUNET_FS_STATUS_DOWNLOAD_ERROR events. */ struct { /** * Error message. */ const char *message; } error; } specifics; } download; /** * Values for all "GNUNET_FS_STATUS_SEARCH_*" events. */ struct { /** * Context for controlling the search, NULL for * searches that were not explicitly triggered * by the client (i.e., searches for updates in * namespaces). */ struct GNUNET_FS_SearchContext *sc; /** * Client context pointer (set the last time by the client for * this operation; initially NULL on START/RESUME events). Note * that this value can only be set on START/RESUME; returning * non-NULL on RESULT/RESUME_RESULT will actually update the * private context for "UPDATE" events. */ void *cctx; /** * Client parent-context pointer; NULL for top-level searches, * refers to the client context of the associated search result * for automatically triggered searches for updates in * namespaces. In this case, 'presult' refers to that search * result. */ void *pctx; /** * What query is used for this search * (list of keywords or SKS identifier). */ const struct GNUNET_FS_Uri *query; /** * How long has this search been actively running * (excludes times where the search was paused or * suspended). */ struct GNUNET_TIME_Relative duration; /** * What anonymity level is used for this search? */ uint32_t anonymity; /** * Additional values for specific events. */ union { /** * These values are only valid for * #GNUNET_FS_STATUS_SEARCH_RESULT events. */ struct { /** * Metadata for the search result. */ const struct GNUNET_CONTAINER_MetaData *meta; /** * URI for the search result. */ const struct GNUNET_FS_Uri *uri; /** * Handle to the result (for starting downloads). */ struct GNUNET_FS_SearchResult *result; /** * Applicability rank (the larger, the better the result * fits the search criteria). */ uint32_t applicability_rank; } result; /** * These values are only valid for * #GNUNET_FS_STATUS_SEARCH_RESUME_RESULT events. */ struct { /** * Metadata for the search result. */ const struct GNUNET_CONTAINER_MetaData *meta; /** * URI for the search result. */ const struct GNUNET_FS_Uri *uri; /** * Handle to the result (for starting downloads). */ struct GNUNET_FS_SearchResult *result; /** * Current availability rank (negative: * unavailable, positive: available) */ int32_t availability_rank; /** * On how many total queries is the given * availability_rank based? */ uint32_t availability_certainty; /** * Updated applicability rank (the larger, * the better the result fits the search * criteria). */ uint32_t applicability_rank; } resume_result; /** * These values are only valid for * #GNUNET_FS_STATUS_SEARCH_UPDATE events. */ struct { /** * Private context set for for this result * during the "RESULT" event. */ void *cctx; /** * Metadata for the search result. */ const struct GNUNET_CONTAINER_MetaData *meta; /** * URI for the search result. */ const struct GNUNET_FS_Uri *uri; /** * Current availability rank (negative: * unavailable, positive: available) */ int32_t availability_rank; /** * On how many total queries is the given * availability_rank based? */ uint32_t availability_certainty; /** * Updated applicability rank (the larger, * the better the result fits the search * criteria). */ uint32_t applicability_rank; /** * How long has the current probe been active? */ struct GNUNET_TIME_Relative current_probe_time; } update; /** * These values are only valid for * #GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND events. * These events are automatically triggered for * each search result before the * #GNUNET_FS_STATUS_SEARCH_SUSPEND event. This * happens primarily to give the client a chance * to clean up the "cctx" (if needed). */ struct { /** * Private context set for for this result * during the "RESULT" event. */ void *cctx; /** * Metadata for the search result. */ const struct GNUNET_CONTAINER_MetaData *meta; /** * URI for the search result. */ const struct GNUNET_FS_Uri *uri; } result_suspend; /** * These values are only valid for * #GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED events. * These events are automatically triggered for * each search result before the * #GNUNET_FS_STATUS_SEARCH_STOPPED event. This * happens primarily to give the client a chance * to clean up the "cctx" (if needed). */ struct { /** * Private context set for for this result * during the "RESULT" event. */ void *cctx; /** * Metadata for the search result. */ const struct GNUNET_CONTAINER_MetaData *meta; /** * URI for the search result. */ const struct GNUNET_FS_Uri *uri; } result_stopped; /** * These values are only valid for * #GNUNET_FS_STATUS_SEARCH_RESUME events. */ struct { /** * Error message, NULL if we have not encountered any error yet. */ const char *message; /** * Is this search currently paused? */ int is_paused; } resume; /** * These values are only valid for * #GNUNET_FS_STATUS_SEARCH_ERROR events. */ struct { /** * Error message. */ const char *message; } error; /** * Values for #GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE events. */ struct { /** * Short, human-readable name of the namespace. */ const char *name; /** * Root identifier for the namespace, can be NULL. */ const char *root; /** * Metadata for the namespace. */ const struct GNUNET_CONTAINER_MetaData *meta; /** * Public key of the namespace. */ struct GNUNET_CRYPTO_EcdsaPublicKey pseudonym; } ns; } specifics; } search; /** * Values for all "GNUNET_FS_STATUS_UNINDEX_*" events. */ struct { /** * Context for controlling the unindexing. */ struct GNUNET_FS_UnindexContext *uc; /** * Client context pointer (set the last time * by the client for this operation; initially * NULL on START/RESUME events). */ void *cctx; /** * Name of the file that is being unindexed. */ const char *filename; /** * How large is the file overall? */ uint64_t size; /** * At what time do we expect to finish unindexing? * (will be a value in the past for completed * unindexing opeations). */ struct GNUNET_TIME_Relative eta; /** * How long has this upload been actively running * (excludes times where the upload was suspended). */ struct GNUNET_TIME_Relative duration; /** * How many bytes have we completed? */ uint64_t completed; /** * Additional values for specific events. */ union { /** * These values are only valid for * #GNUNET_FS_STATUS_UNINDEX_PROGRESS events. */ struct { /** * Data block we just unindexed. */ const void *data; /** * At what offset in the file is "data"? */ uint64_t offset; /** * Length of the data block. */ uint64_t data_len; /** * Depth of the given block in the tree; * 0 would be the lowest level (DBLOCKS). */ unsigned int depth; } progress; /** * These values are only valid for * #GNUNET_FS_STATUS_UNINDEX_RESUME events. */ struct { /** * Error message, NULL if we have not encountered any error yet. */ const char *message; } resume; /** * These values are only valid for * #GNUNET_FS_STATUS_UNINDEX_ERROR events. */ struct { /** * Error message. */ const char *message; } error; } specifics; } unindex; } value; /** * Specific status code (determines the event type). */ enum GNUNET_FS_Status status; /** * File-sharing handle that generated the event. */ struct GNUNET_FS_Handle *fsh; }; /** * Notification of FS to a client about the progress of an * operation. Callbacks of this type will be used for uploads, * downloads and searches. Some of the arguments depend a bit * in their meaning on the context in which the callback is used. * * @param cls closure * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the `struct GNUNET_FS_ProgressInfo`. */ typedef void *(*GNUNET_FS_ProgressCallback) (void *cls, const struct GNUNET_FS_ProgressInfo *info); /** * General (global) option flags for file-sharing. */ enum GNUNET_FS_Flags { /** * No special flags set. */ GNUNET_FS_FLAGS_NONE = 0, /** * Is persistence of operations desired? * (will create SUSPEND/RESUME events). */ GNUNET_FS_FLAGS_PERSISTENCE = 1, /** * Should we automatically trigger probes for search results * to determine availability? * (will create #GNUNET_FS_STATUS_SEARCH_UPDATE events). */ GNUNET_FS_FLAGS_DO_PROBES = 2 }; /** * Options specified in the VARARGs portion of GNUNET_FS_start. */ enum GNUNET_FS_OPTIONS { /** * Last option in the VARARG list. */ GNUNET_FS_OPTIONS_END = 0, /** * Select the desired amount of parallelism (this option should be * followed by an "unsigned int" giving the desired maximum number * of parallel downloads). */ GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM = 1, /** * Maximum number of requests that should be pending at a given * point in time (invidivual downloads may go above this, but * if we are above this threshold, we should not activate any * additional downloads. */ GNUNET_FS_OPTIONS_REQUEST_PARALLELISM = 2 }; /** * Settings for publishing a block (which may of course also * apply to an entire directory or file). */ struct GNUNET_FS_BlockOptions { /** * At what time should the block expire? Data blocks (DBLOCKS and * IBLOCKS) may still be used even if they are expired (however, * they'd be removed quickly from the datastore if we are short on * space), all other types of blocks will no longer be returned * after they expire. */ struct GNUNET_TIME_Absolute expiration_time; /** * At which anonymity level should the block be shared? * (0: no anonymity, 1: normal GAP, >1: with cover traffic). */ uint32_t anonymity_level; /** * How important is it for us to store the block? If we run * out of space, the highest-priority, non-expired blocks will * be kept. */ uint32_t content_priority; /** * How often should we try to migrate the block to other peers? * Only used if "CONTENT_PUSHING" is set to YES, in which case we * first push each block to other peers according to their * replication levels. Once each block has been pushed that many * times to other peers, blocks are chosen for migration at random. * Naturally, there is no guarantee that the other peers will keep * these blocks for any period of time (since they won't have any * priority or might be too busy to even store the block in the * first place). */ uint32_t replication_level; }; /** * Handle to the file-sharing service. */ struct GNUNET_FS_Handle; /** * Setup a connection to the file-sharing service. * * @param cfg configuration to use * @param client_name unique identifier for this client * @param upcb function to call to notify about FS actions * @param upcb_cls closure for @a upcb * @param flags specific attributes for fs-operations * @param ... list of optional options, terminated with #GNUNET_FS_OPTIONS_END * @return NULL on error */ struct GNUNET_FS_Handle * GNUNET_FS_start (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *client_name, GNUNET_FS_ProgressCallback upcb, void *upcb_cls, enum GNUNET_FS_Flags flags, ...); /** * Close our connection with the file-sharing service. * The callback given to GNUNET_FS_start will no longer be * called after this function returns. * * @param h handle that was returned from GNUNET_FS_start */ void GNUNET_FS_stop (struct GNUNET_FS_Handle *h); /** * Function called on entries in a `struct GNUNET_FS_FileInformation` iteration. * * @param cls closure * @param fi the entry in the publish-structure * @param length length of the file or directory * @param meta metadata for the file or directory (can be modified) * @param uri pointer to the keywords that will be used for this entry (can be modified) * @param bo block options (can be modified) * @param do_index should we index (can be modified) * @param client_info pointer to client context set upon creation (can be modified) * @return #GNUNET_OK to continue, #GNUNET_NO to remove * this entry from the directory, #GNUNET_SYSERR * to abort the iteration */ typedef int (*GNUNET_FS_FileInformationProcessor) (void *cls, struct GNUNET_FS_FileInformation * fi, uint64_t length, struct GNUNET_CONTAINER_MetaData * meta, struct GNUNET_FS_Uri ** uri, struct GNUNET_FS_BlockOptions * bo, int *do_index, void **client_info); /** * Obtain the name under which this file information * structure is stored on disk. Only works for top-level * file information structures. * * @param s structure to get the filename for * @return NULL on error, otherwise filename that can be used * to read this fi-struct from disk. */ const char * GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s); /** * Obtain the filename from the file information structure. * * @param s structure to get the filename for * @return "filename" field of the structure (can be NULL) */ const char * GNUNET_FS_file_information_get_filename (struct GNUNET_FS_FileInformation *s); /** * Set the filename in the file information structure. * If filename was already set, frees it before setting the new one. * Makes a copy of the argument. * * @param s structure to get the filename for * @param filename filename to set */ void GNUNET_FS_file_information_set_filename (struct GNUNET_FS_FileInformation *s, const char *filename); /** * Create an entry for a file in a publish-structure. * * @param h handle to the file sharing subsystem * @param client_info initial client-info value for this entry * @param filename name of the file or directory to publish * @param keywords under which keywords should this file be available * directly; can be NULL * @param meta metadata for the file * @param do_index #GNUNET_YES for index, #GNUNET_NO for insertion, * #GNUNET_SYSERR for simulation * @param bo block options * @return publish structure entry for the file */ struct GNUNET_FS_FileInformation * GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h, void *client_info, const char *filename, const struct GNUNET_FS_Uri *keywords, const struct GNUNET_CONTAINER_MetaData *meta, int do_index, const struct GNUNET_FS_BlockOptions *bo); /** * Create an entry for a file in a publish-structure. * * @param h handle to the file sharing subsystem * @param client_info initial client-info value for this entry * @param length length of the file * @param data data for the file (should not be used afterwards by * the caller; callee will "free") * @param keywords under which keywords should this file be available * directly; can be NULL * @param meta metadata for the file * @param do_index #GNUNET_YES for index, #GNUNET_NO for insertion, * #GNUNET_SYSERR for simulation * @param bo block options * @return publish structure entry for the file */ struct GNUNET_FS_FileInformation * GNUNET_FS_file_information_create_from_data (struct GNUNET_FS_Handle *h, void *client_info, uint64_t length, void *data, const struct GNUNET_FS_Uri *keywords, const struct GNUNET_CONTAINER_MetaData *meta, int do_index, const struct GNUNET_FS_BlockOptions *bo); /** * Function that provides data. * * @param cls closure * @param offset offset to read from; it is possible * that the caller might need to go backwards * a bit at times; set to UINT64_MAX to tell * the reader that we won't be reading for a while * (used to close the file descriptor but NOT fully * clean up the reader's state); in this case, * a value of '0' for max should be ignored * @param max maximum number of bytes that should be * copied to buf; readers are not allowed * to provide less data unless there is an error; * a value of "0" will be used at the end to allow * the reader to clean up its internal state * @param buf where the reader should write the data * @param emsg location for the reader to store an error message * @return number of bytes written, usually @a max, 0 on error */ typedef size_t (*GNUNET_FS_DataReader) (void *cls, uint64_t offset, size_t max, void *buf, char **emsg); /** * Create an entry for a file in a publish-structure. * * @param h handle to the file sharing subsystem * @param client_info initial client-info value for this entry * @param length length of the file * @param reader function that can be used to obtain the data for the file * @param reader_cls closure for @a reader * @param keywords under which keywords should this file be available * directly; can be NULL * @param meta metadata for the file * @param do_index #GNUNET_YES for index, #GNUNET_NO for insertion, * #GNUNET_SYSERR for simulation * @param bo block options * @return publish structure entry for the file */ struct GNUNET_FS_FileInformation * GNUNET_FS_file_information_create_from_reader (struct GNUNET_FS_Handle *h, void *client_info, uint64_t length, GNUNET_FS_DataReader reader, void *reader_cls, const struct GNUNET_FS_Uri *keywords, const struct GNUNET_CONTAINER_MetaData *meta, int do_index, const struct GNUNET_FS_BlockOptions *bo); /** * Create an entry for an empty directory in a publish-structure. * * @param h handle to the file sharing subsystem * @param client_info initial client-info value for this entry * @param keywords under which keywords should this directory be available * directly; can be NULL * @param meta metadata for the directory * @param bo block options * @param filename name of the directory; can be NULL * @return publish structure entry for the directory , NULL on error */ struct GNUNET_FS_FileInformation * GNUNET_FS_file_information_create_empty_directory (struct GNUNET_FS_Handle *h, void *client_info, const struct GNUNET_FS_Uri *keywords, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_BlockOptions *bo, const char *filename); /** * Test if a given entry represents a directory. * * @param ent check if this FI represents a directory * @return #GNUNET_YES if so, #GNUNET_NO if not */ int GNUNET_FS_file_information_is_directory (const struct GNUNET_FS_FileInformation *ent); /** * Add an entry to a directory in a publish-structure. Clients * should never modify publish structures that were passed to * #GNUNET_FS_publish_start already. * * @param dir the directory * @param ent the entry to add; the entry must not have been * added to any other directory at this point and * must not include @a dir in its structure * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir, struct GNUNET_FS_FileInformation *ent); /** * Inspect a file or directory in a publish-structure. Clients * should never modify publish structures that were passed to * #GNUNET_FS_publish_start already. When called on a directory, * this function will FIRST call @a proc with information about * the directory itself and then for each of the files in the * directory (but not for files in subdirectories). When called * on a file, @a proc will be called exactly once (with information * about the specific file). * * @param dir the directory * @param proc function to call on each entry * @param proc_cls closure for @a proc */ void GNUNET_FS_file_information_inspect (struct GNUNET_FS_FileInformation *dir, GNUNET_FS_FileInformationProcessor proc, void *proc_cls); /** * Destroy publish-structure. Clients should never destroy publish * structures that were passed to #GNUNET_FS_publish_start already. * * @param fi structure to destroy * @param cleaner function to call on each entry in the structure * (useful to clean up client_info); can be NULL; return * values are ignored * @param cleaner_cls closure for @a cleaner */ void GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi, GNUNET_FS_FileInformationProcessor cleaner, void *cleaner_cls); /** * Options for publishing. Compatible options * can be OR'ed together. */ enum GNUNET_FS_PublishOptions { /** * No options (use defaults for everything). */ GNUNET_FS_PUBLISH_OPTION_NONE = 0, /** * Simulate publishing. With this option, no data will be stored * in the datastore. Useful for computing URIs from files. */ GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY = 1 }; /** * Publish a file or directory. * * @param h handle to the file sharing subsystem * @param fi information about the file or directory structure to publish * @param ns namespace to publish the file in, NULL for no namespace * @param nid identifier to use for the publishd content in the namespace * (can be NULL, must be NULL if namespace is NULL) * @param nuid update-identifier that will be used for future updates * (can be NULL, must be NULL if namespace or nid is NULL) * @param options options for the publication * @return context that can be used to control the publish operation */ struct GNUNET_FS_PublishContext * GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, struct GNUNET_FS_FileInformation *fi, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const char *nid, const char *nuid, enum GNUNET_FS_PublishOptions options); /** * Stop a publication. Will abort incomplete publications (but * not remove blocks that have already been published) or * simply clean up the state for completed publications. * Must NOT be called from within the event callback! * * @param pc context for the publication to stop */ void GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc); /** * Signature of a function called as the continuation of a KBlock or * SBlock publication. * * @param cls closure * @param uri URI under which the block is now available, NULL on error * @param emsg error message, NULL on success */ typedef void (*GNUNET_FS_PublishContinuation) (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg); /** * Handle to cancel publish KSK operation. */ struct GNUNET_FS_PublishKskContext; /** * Publish a KBlock on GNUnet. * * @param h handle to the file sharing subsystem * @param ksk_uri keywords to use * @param meta metadata to use * @param uri URI to refer to in the KBlock * @param bo block options * @param options publication options * @param cont continuation * @param cont_cls closure for @a cont * @return NULL on error (@a cont will still be called) */ struct GNUNET_FS_PublishKskContext * GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *ksk_uri, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_BlockOptions *bo, enum GNUNET_FS_PublishOptions options, GNUNET_FS_PublishContinuation cont, void *cont_cls); /** * Abort the KSK publishing operation. * * @param pkc context of the operation to abort. */ void GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc); /** * Handle to cancel publish SKS operation. */ struct GNUNET_FS_PublishSksContext; /** * Publish an SBlock on GNUnet. * * @param h handle to the file sharing subsystem * @param ns namespace to publish in * @param identifier identifier to use * @param update update identifier to use * @param meta metadata to use * @param uri URI to refer to in the SBlock * @param bo block options * @param options publication options * @param cont continuation * @param cont_cls closure for @a cont * @return NULL on error (@a cont will still be called) */ struct GNUNET_FS_PublishSksContext * GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const char *identifier, const char *update, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_BlockOptions *bo, enum GNUNET_FS_PublishOptions options, GNUNET_FS_PublishContinuation cont, void *cont_cls); /** * Abort the SKS publishing operation. * * @param psc context of the operation to abort. */ void GNUNET_FS_publish_sks_cancel (struct GNUNET_FS_PublishSksContext *psc); /** * Type of a function called by #GNUNET_FS_get_indexed_files. * * @param cls closure * @param filename the name of the file, NULL for end of list * @param file_id hash of the contents of the indexed file * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort */ typedef int (*GNUNET_FS_IndexedFileProcessor) (void *cls, const char *filename, const struct GNUNET_HashCode * file_id); /** * Handle to cancel 'GNUNET_FS_get_indexed_files'. */ struct GNUNET_FS_GetIndexedContext; /** * Iterate over all indexed files. * * @param h handle to the file sharing subsystem * @param iterator function to call on each indexed file * @param iterator_cls closure for @a iterator * @return NULL on error (@a iterator is not called) */ struct GNUNET_FS_GetIndexedContext * GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h, GNUNET_FS_IndexedFileProcessor iterator, void *iterator_cls); /** * Cancel iteration over all indexed files. * * @param gic operation to cancel */ void GNUNET_FS_get_indexed_files_cancel (struct GNUNET_FS_GetIndexedContext *gic); /** * Unindex a file. * * @param h handle to the file sharing subsystem * @param filename file to unindex * @param cctx initial value for the client context * @return NULL on error, otherwise handle */ struct GNUNET_FS_UnindexContext * GNUNET_FS_unindex_start (struct GNUNET_FS_Handle *h, const char *filename, void *cctx); /** * Clean up after completion of an unindex operation. * * @param uc handle */ void GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc); /** * Function called on updateable identifiers. * * @param cls closure * @param last_id last identifier * @param last_uri uri used for the content published under the @a last_id * @param last_meta metadata associated with @a last_uri * @param next_id identifier that should be used for updates */ typedef void (*GNUNET_FS_IdentifierProcessor) (void *cls, const char *last_id, const struct GNUNET_FS_Uri *last_uri, const struct GNUNET_CONTAINER_MetaData *last_meta, const char *next_id); /** * List all of the identifiers in the namespace for which we could * produce an update. Namespace updates form a graph where each node * has a name. Each node can have any number of URI/meta-data entries * which can each be linked to other nodes. Cycles are possible. * * Calling this function with @a next_id NULL will cause the library to * call @a ip with a root for each strongly connected component of the * graph (a root being a node from which all other nodes in the Scc * are reachable). * * Calling this function with @a next_id being the name of a node will * cause the library to call @a ip with all children of the node. Note * that cycles within an SCC are possible (including self-loops). * * @param h fs handle to use * @param ns namespace to inspect for updateable content * @param next_id ID to look for; use NULL to look for SCC roots * @param ip function to call on each updateable identifier * @param ip_cls closure for @a ip */ void GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const char *next_id, GNUNET_FS_IdentifierProcessor ip, void *ip_cls); /** * Options for searching. Compatible options * can be OR'ed together. */ enum GNUNET_FS_SearchOptions { /** * No options (use defaults for everything). */ GNUNET_FS_SEARCH_OPTION_NONE = 0, /** * Only search the local host, do not search remote systems (no P2P) */ GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY = 1 }; /** * Start search for content. * * @param h handle to the file sharing subsystem * @param uri specifies the search parameters; can be * a KSK URI or an SKS URI. * @param anonymity desired level of anonymity * @param options options for the search * @param cctx initial value for the client context * @return context that can be used to control the search */ struct GNUNET_FS_SearchContext * GNUNET_FS_search_start (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, uint32_t anonymity, enum GNUNET_FS_SearchOptions options, void *cctx); /** * Pause search. * * @param sc context for the search that should be paused */ void GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc); /** * Continue paused search. * * @param sc context for the search that should be resumed */ void GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc); /** * Stop search for content. * * @param sc context for the search that should be stopped */ void GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc); /** * Start download probes for the given search result. * * @param h file-sharing handle to use for the operation * @param uri URI to probe * @param meta meta data associated with the URI * @param client_info client info pointer to use for associated events * @param anonymity anonymity level to use for the probes * @return the search result handle to access the probe activity */ struct GNUNET_FS_SearchResult * GNUNET_FS_probe (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, void *client_info, uint32_t anonymity); /** * Stop probe activity. Must ONLY be used on values * returned from #GNUNET_FS_probe. * * @param sr search result to stop probing for (freed) * @return the value of the 'client_info' pointer */ void * GNUNET_FS_probe_stop (struct GNUNET_FS_SearchResult *sr); /** * Options for downloading. Compatible options * can be OR'ed together. */ enum GNUNET_FS_DownloadOptions { /** * No options (use defaults for everything). */ GNUNET_FS_DOWNLOAD_OPTION_NONE = 0, /** * Only download from the local host, do not access remote systems (no P2P) */ GNUNET_FS_DOWNLOAD_OPTION_LOOPBACK_ONLY = 1, /** * Do a recursive download (that is, automatically trigger the * download of files in directories). */ GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE = 2, /** * Do not append temporary data to * the target file (for the IBlocks). */ GNUNET_FS_DOWNLOAD_NO_TEMPORARIES = 4, /** * Internal option used to flag this download as a 'probe' for a * search result. Impacts the priority with which the download is * run and causes signalling callbacks to be done differently. * Also, probe downloads are not serialized on suspension. Normal * clients should not use this! */ GNUNET_FS_DOWNLOAD_IS_PROBE = (1 << 31) }; /** * Download parts of a file. Note that this will store * the blocks at the respective offset in the given file. Also, the * download is still using the blocking of the underlying FS * encoding. As a result, the download may *write* outside of the * given boundaries (if offset and length do not match the 32k FS * block boundaries). * * The given range can be used to focus a download towards a * particular portion of the file (optimization), not to strictly * limit the download to exactly those bytes. * * @param h handle to the file sharing subsystem * @param uri the URI of the file (determines what to download); CHK or LOC URI * @param meta known metadata for the file (can be NULL) * @param filename where to store the file, maybe NULL (then no file is * created on disk and data must be grabbed from the callbacks) * @param tempname where to store temporary file data, not used if filename is non-NULL; * can be NULL (in which case we will pick a name if needed); the temporary file * may already exist, in which case we will try to use the data that is there and * if it is not what is desired, will overwrite it * @param offset at what offset should we start the download (typically 0) * @param length how many bytes should be downloaded starting at offset * @param anonymity anonymity level to use for the download * @param options various download options * @param cctx initial value for the client context for this download * @param parent parent download to associate this download with (use NULL * for top-level downloads; useful for manually-triggered recursive downloads) * @return context that can be used to control this download */ struct GNUNET_FS_DownloadContext * GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx, struct GNUNET_FS_DownloadContext *parent); /** * Download parts of a file based on a search result. The download * will be associated with the search result (and the association * will be preserved when serializing/deserializing the state). * If the search is stopped, the download will not be aborted but * be 'promoted' to a stand-alone download. * * As with the other download function, this will store * the blocks at the respective offset in the given file. Also, the * download is still using the blocking of the underlying FS * encoding. As a result, the download may *write* outside of the * given boundaries (if offset and length do not match the 32k FS * block boundaries). * * The given range can be used to focus a download towards a * particular portion of the file (optimization), not to strictly * limit the download to exactly those bytes. * * @param h handle to the file sharing subsystem * @param sr the search result to use for the download (determines uri and * meta data and associations) * @param filename where to store the file, maybe NULL (then no file is * created on disk and data must be grabbed from the callbacks) * @param tempname where to store temporary file data, not used if filename is non-NULL; * can be NULL (in which case we will pick a name if needed); the temporary file * may already exist, in which case we will try to use the data that is there and * if it is not what is desired, will overwrite it * @param offset at what offset should we start the download (typically 0) * @param length how many bytes should be downloaded starting at offset * @param anonymity anonymity level to use for the download * @param options various download options * @param cctx initial value for the client context for this download * @return context that can be used to control this download */ struct GNUNET_FS_DownloadContext * GNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h, struct GNUNET_FS_SearchResult *sr, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx); /** * Stop a download (aborts if download is incomplete). * * @param dc handle for the download * @param do_delete delete files of incomplete downloads */ void GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, int do_delete); /* ******************** Directory API *********************** */ #define GNUNET_FS_DIRECTORY_MIME "application/gnunet-directory" #define GNUNET_FS_DIRECTORY_MAGIC "\211GND\r\n\032\n" #define GNUNET_FS_DIRECTORY_EXT ".gnd" /** * Does the meta-data claim that this is a directory? * Checks if the mime-type is that of a GNUnet directory. * * @return #GNUNET_YES if it is, #GNUNET_NO if it is not, #GNUNET_SYSERR if * we have no mime-type information (treat as #GNUNET_NO) */ int GNUNET_FS_meta_data_test_for_directory (const struct GNUNET_CONTAINER_MetaData *md); /** * Set the MIMETYPE information for the given * metadata to "application/gnunet-directory". * * @param md metadata to add mimetype to */ void GNUNET_FS_meta_data_make_directory (struct GNUNET_CONTAINER_MetaData *md); /** * Suggest a filename based on given metadata. * * @param md given meta data * @return NULL if meta data is useless for suggesting a filename */ char * GNUNET_FS_meta_data_suggest_filename (const struct GNUNET_CONTAINER_MetaData *md); /** * Function used to process entries in a directory. * * @param cls closure * @param filename name of the file in the directory * @param uri URI of the file * @param metadata metadata for the file; metadata for * the directory if everything else is NULL/zero * @param length length of the available data for the file * (of type size_t since data must certainly fit * into memory; if files are larger than size_t * permits, then they will certainly not be * embedded with the directory itself). * @param data data available for the file (length bytes) */ typedef void (*GNUNET_FS_DirectoryEntryProcessor) (void *cls, const char *filename, const struct GNUNET_FS_Uri * uri, const struct GNUNET_CONTAINER_MetaData * meta, size_t length, const void *data); /** * Iterate over all entries in a directory. Note that directories * are structured such that it is possible to iterate over the * individual blocks as well as over the entire directory. Thus * a client can call this function on the buffer in the * GNUNET_FS_ProgressCallback. Also, directories can optionally * include the contents of (small) files embedded in the directory * itself; for those files, the processor may be given the * contents of the file directly by this function. * * @param size number of bytes in data * @param data pointer to the beginning of the directory * @param offset offset of data in the directory * @param dep function to call on each entry * @param dep_cls closure for @a dep * @return #GNUNET_OK if this could be a block in a directory, * #GNUNET_NO if this could be part of a directory (but not 100% OK) * #GNUNET_SYSERR if 'data' does not represent a directory */ int GNUNET_FS_directory_list_contents (size_t size, const void *data, uint64_t offset, GNUNET_FS_DirectoryEntryProcessor dep, void *dep_cls); /** * Opaque handle to a directory builder. */ struct GNUNET_FS_DirectoryBuilder; /** * Create a directory builder. * * @param mdir metadata for the directory */ struct GNUNET_FS_DirectoryBuilder * GNUNET_FS_directory_builder_create (const struct GNUNET_CONTAINER_MetaData *mdir); /** * Add an entry to a directory. * * @param bld directory to extend * @param uri uri of the entry (must not be a KSK) * @param md metadata of the entry * @param data raw data of the entry, can be NULL, otherwise * data must point to exactly the number of bytes specified * by the uri */ void GNUNET_FS_directory_builder_add (struct GNUNET_FS_DirectoryBuilder *bld, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *md, const void *data); /** * Finish building the directory. Frees the * builder context and returns the directory * in-memory. * * @param bld directory to finish * @param rsize set to the number of bytes needed * @param rdata set to the encoded directory * @return #GNUNET_OK on success */ int GNUNET_FS_directory_builder_finish (struct GNUNET_FS_DirectoryBuilder *bld, size_t * rsize, void **rdata); /* ******************** DirScanner API *********************** */ /** * Progress reasons of the directory scanner. */ enum GNUNET_FS_DirScannerProgressUpdateReason { /** * We've started processing a file or directory. */ GNUNET_FS_DIRSCANNER_FILE_START = 0, /** * We're having trouble accessing a file (soft-error); it will * be ignored. */ GNUNET_FS_DIRSCANNER_FILE_IGNORED, /** * We've found all files (in the pre-pass). */ GNUNET_FS_DIRSCANNER_ALL_COUNTED, /** * We've finished extracting meta data from a file. */ GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED, /** * Last call to the progress function: we have finished scanning * the directory. */ GNUNET_FS_DIRSCANNER_FINISHED, /** * There was an internal error. Application should abort the scan. */ GNUNET_FS_DIRSCANNER_INTERNAL_ERROR }; /** * Function called over time as the directory scanner makes * progress on the job at hand. * * @param cls closure * @param filename which file we are making progress on * @param is_directory #GNUNET_YES if this is a directory, * #GNUNET_NO if this is a file * #GNUNET_SYSERR if it is neither (or unknown) * @param reason kind of progress we are making */ typedef void (*GNUNET_FS_DirScannerProgressCallback) (void *cls, const char *filename, int is_directory, enum GNUNET_FS_DirScannerProgressUpdateReason reason); /** * A node of a directory tree (produced by dirscanner) */ struct GNUNET_FS_ShareTreeItem { /** * This is a doubly-linked list */ struct GNUNET_FS_ShareTreeItem *prev; /** * This is a doubly-linked list */ struct GNUNET_FS_ShareTreeItem *next; /** * This is a doubly-linked tree * NULL for top-level entries. */ struct GNUNET_FS_ShareTreeItem *parent; /** * This is a doubly-linked tree * NULL for files and empty directories */ struct GNUNET_FS_ShareTreeItem *children_head; /** * This is a doubly-linked tree * NULL for files and empty directories */ struct GNUNET_FS_ShareTreeItem *children_tail; /** * Metadata for this file or directory */ struct GNUNET_CONTAINER_MetaData *meta; /** * Keywords for this file or directory (derived from metadata). */ struct GNUNET_FS_Uri *ksk_uri; /** * Name of the file/directory */ char *filename; /** * Base name of the file/directory. */ char *short_filename; /** * #GNUNET_YES if this is a directory */ int is_directory; }; /** * Opaqe handle to an asynchronous directory scanning activity. */ struct GNUNET_FS_DirScanner; /** * Start a directory scanner. * * @param filename name of the directory to scan * @param disable_extractor #GNUNET_YES to not to run libextractor on files (only build a tree) * @param ex if not NULL, must be a list of extra plugins for extractor * @param cb the callback to call when there are scanning progress messages * @param cb_cls closure for @a cb * @return directory scanner object to be used for controlling the scanner */ struct GNUNET_FS_DirScanner * GNUNET_FS_directory_scan_start (const char *filename, int disable_extractor, const char *ex, GNUNET_FS_DirScannerProgressCallback cb, void *cb_cls); /** * Abort the scan. Must not be called from within the progress_callback * function. * * @param ds directory scanner structure */ void GNUNET_FS_directory_scan_abort (struct GNUNET_FS_DirScanner *ds); /** * Obtain the result of the scan after the scan has signalled * completion. Must not be called prior to completion. The @a ds is * freed as part of this call. * * @param ds directory scanner structure * @return the results of the scan (a directory tree) */ struct GNUNET_FS_ShareTreeItem * GNUNET_FS_directory_scan_get_result (struct GNUNET_FS_DirScanner *ds); /** * Process a share item tree, moving frequent keywords up and * copying frequent metadata up. * * @param toplevel toplevel directory in the tree, returned by the scanner */ void GNUNET_FS_share_tree_trim (struct GNUNET_FS_ShareTreeItem *toplevel); /** * Release memory of a share item tree. * * @param toplevel toplevel of the tree to be freed */ void GNUNET_FS_share_tree_free (struct GNUNET_FS_ShareTreeItem *toplevel); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/include/gnunet_dnsparser_lib.h0000644000175000017500000005455212251306467016625 00000000000000/* This file is part of GNUnet (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_dnsparser_lib.h * @brief API for helper library to parse DNS packets. * @author Philipp Toelke * @author Christian Grothoff */ #ifndef GNUNET_DNSPARSER_LIB_H #define GNUNET_DNSPARSER_LIB_H #include "gnunet_util_lib.h" #include "gnunet_tun_lib.h" /** * Maximum length of a label in DNS. */ #define GNUNET_DNSPARSER_MAX_LABEL_LENGTH 63 /** * Maximum length of a name in DNS. */ #define GNUNET_DNSPARSER_MAX_NAME_LENGTH 253 /** * A few common DNS types. */ #define GNUNET_DNSPARSER_TYPE_A 1 #define GNUNET_DNSPARSER_TYPE_NS 2 #define GNUNET_DNSPARSER_TYPE_CNAME 5 #define GNUNET_DNSPARSER_TYPE_SOA 6 #define GNUNET_DNSPARSER_TYPE_PTR 12 #define GNUNET_DNSPARSER_TYPE_MX 15 #define GNUNET_DNSPARSER_TYPE_TXT 16 #define GNUNET_DNSPARSER_TYPE_AAAA 28 #define GNUNET_DNSPARSER_TYPE_SRV 33 #define GNUNET_DNSPARSER_TYPE_CERT 37 #define GNUNET_DNSPARSER_TYPE_TLSA 52 /** * A DNS query. */ struct GNUNET_DNSPARSER_Query { /** * Name of the record that the query is for (0-terminated). * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *name; /** * See GNUNET_DNSPARSER_TYPE_*. */ uint16_t type; /** * See GNUNET_TUN_DNS_CLASS_*. */ uint16_t dns_traffic_class; }; /** * Information from MX records (RFC 1035). */ struct GNUNET_DNSPARSER_MxRecord { /** * Preference for this entry (lower value is higher preference). */ uint16_t preference; /** * Name of the mail server. * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *mxhost; }; /** * Information from SRV records (RFC 2782). The 'service', 'proto' * and 'domain_name' fields together give the DNS-name which for SRV * records is of the form "_$SERVICE._$PROTO.$DOMAIN_NAME". The DNS * parser provides the full name in 'struct DNSPARSER_Record' and the * individual components in the respective fields of this struct. * When serializing, you CAN set the 'name' field of 'struct * GNUNET_DNSPARSER_Record' to NULL, in which case the DNSPARSER code * will populate 'name' from the 'service', 'proto' and 'domain_name' * fields in this struct. */ struct GNUNET_DNSPARSER_SrvRecord { /** * Service name without the underscore (!). Note that RFC 6335 clarifies the * set of legal characters for service names. * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *service; /** * Transport protocol (typcially "tcp" or "udp", but others might be allowed). * Without the underscore (!). */ char *proto; /** * Domain name for which the record is valid * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *domain_name; /** * Hostname offering the service. * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *target; /** * Preference for this entry (lower value is higher preference). Clients * will contact hosts from the lowest-priority group first and fall back * to higher priorities if the low-priority entries are unavailable. */ uint16_t priority; /** * Relative weight for records with the same priority. Clients will use * the hosts of the same (lowest) priority with a probability proportional * to the weight given. */ uint16_t weight; /** * TCP or UDP port of the service. */ uint16_t port; }; /** * DNS CERT types as defined in RFC 4398. */ enum GNUNET_DNSPARSER_CertType { /** * Reserved value */ GNUNET_DNSPARSER_CERTTYPE_RESERVED = 0, /** * An x509 PKIX certificate */ GNUNET_DNSPARSER_CERTTYPE_PKIX = 1, /** * A SKPI certificate */ GNUNET_DNSPARSER_CERTTYPE_SKPI = 2, /** * A PGP certificate */ GNUNET_DNSPARSER_CERTTYPE_PGP = 3, /** * An x509 PKIX cert URL */ GNUNET_DNSPARSER_CERTTYPE_IPKIX = 4, /** * A SKPI cert URL */ GNUNET_DNSPARSER_CERTTYPE_ISKPI = 5, /** * A PGP cert fingerprint and URL */ GNUNET_DNSPARSER_CERTTYPE_IPGP = 6, /** * An attribute Certificate */ GNUNET_DNSPARSER_CERTTYPE_ACPKIX = 7, /** * An attribute cert URL */ GNUNET_DNSPARSER_CERTTYPE_IACKPIX = 8 }; /** * DNSCERT algorithms as defined in http://www.iana.org/assignments/ * dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml, under dns-sec-alg-numbers-1 */ enum GNUNET_DNSPARSER_CertAlgorithm { /** * No defined */ GNUNET_DNSPARSER_CERTALGO_UNDEFINED = 0, /** * RSA/MD5 */ GNUNET_DNSPARSER_CERTALGO_RSAMD5 = 1, /** * Diffie-Hellman */ GNUNET_DNSPARSER_CERTALGO_DH = 2, /** * DSA/SHA1 */ GNUNET_DNSPARSER_CERTALGO_DSASHA = 3, /** * Reserved */ GNUNET_DNSPARSER_CERTALGO_RSRVD4 = 4, /** * RSA/SHA1 */ GNUNET_DNSPARSER_CERTALGO_RSASHA = 5, /** * DSA/NSEC3/SHA */ GNUNET_DNSPARSER_CERTALGO_DSANSEC3 = 6, /** * RSA/NSEC3/SHA */ GNUNET_DNSPARSER_CERTALGO_RSANSEC3 = 7, /** * RSA/SHA256 */ GNUNET_DNSPARSER_CERTALGO_RSASHA256 = 8, /** * Reserved */ GNUNET_DNSPARSER_CERTALGO_RSRVD9 = 9, /** * RSA/SHA512 */ GNUNET_DNSPARSER_CERTALGO_RSASHA512 = 10, /** * GOST R 34.10-2001 */ GNUNET_DNSPARSER_CERTALGO_GOST_R34 = 12, /** * ECDSA Curve P-256/SHA256 */ GNUNET_DNSPARSER_CERTALGO_ECDSA_P256SHA256 = 13, /** * ECDSA Curve P-384/SHA384 */ GNUNET_DNSPARSER_CERTALGO_ECDSA_P384SHA384 = 14 }; /** * Information from CERT records (RFC 4034). */ struct GNUNET_DNSPARSER_CertRecord { /** * Certificate type */ enum GNUNET_DNSPARSER_CertType cert_type; /** * Certificate KeyTag */ uint16_t cert_tag; /** * Algorithm */ enum GNUNET_DNSPARSER_CertAlgorithm algorithm; /** * Number of bytes in @e certificate_data */ size_t certificate_size; /** * Data of the certificate. */ char *certificate_data; }; /** * Information from SOA records (RFC 1035). */ struct GNUNET_DNSPARSER_SoaRecord { /** * The domainname of the name server that was the * original or primary source of data for this zone. * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use #GNUNET_DNSPARSER_check_label to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *mname; /** * A domainname which specifies the mailbox of the * person responsible for this zone. * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use 'GNUNET_DNSPARSER_check_label' to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *rname; /** * The version number of the original copy of the zone. */ uint32_t serial; /** * Time interval before the zone should be refreshed. */ uint32_t refresh; /** * Time interval that should elapse before a failed refresh should * be retried. */ uint32_t retry; /** * Time value that specifies the upper limit on the time interval * that can elapse before the zone is no longer authoritative. */ uint32_t expire; /** * The bit minimum TTL field that should be exported with any RR * from this zone. */ uint32_t minimum_ttl; }; /** * Binary record information (unparsed). */ struct GNUNET_DNSPARSER_RawRecord { /** * Binary record data. */ void *data; /** * Number of bytes in data. */ size_t data_len; }; /** * A DNS response record. */ struct GNUNET_DNSPARSER_Record { /** * Name of the record that the query is for (0-terminated). * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use #GNUNET_DNSPARSER_check_label to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *name; /** * Payload of the record (which one of these is valid depends on the 'type'). */ union { /** * For NS, CNAME and PTR records, this is the uncompressed 0-terminated hostname. * In UTF-8 format. The library will convert from and to DNS-IDNA * as necessary. Use #GNUNET_DNSPARSER_check_label to test if an * individual label is well-formed. If a given name is not well-formed, * creating the DNS packet will fail. */ char *hostname; /** * SOA data for SOA records. */ struct GNUNET_DNSPARSER_SoaRecord *soa; /** * CERT data for CERT records. */ struct GNUNET_DNSPARSER_CertRecord *cert; /** * MX data for MX records. */ struct GNUNET_DNSPARSER_MxRecord *mx; /** * SRV data for SRV records. */ struct GNUNET_DNSPARSER_SrvRecord *srv; /** * Raw data for all other types. */ struct GNUNET_DNSPARSER_RawRecord raw; } data; /** * When does the record expire? */ struct GNUNET_TIME_Absolute expiration_time; /** * See GNUNET_DNSPARSER_TYPE_*. */ uint16_t type; /** * See GNUNET_TUN_DNS_CLASS_*. */ uint16_t dns_traffic_class; }; /** * Easy-to-process, parsed version of a DNS packet. */ struct GNUNET_DNSPARSER_Packet { /** * Array of all queries in the packet, must contain "num_queries" entries. */ struct GNUNET_DNSPARSER_Query *queries; /** * Array of all answers in the packet, must contain "num_answers" entries. */ struct GNUNET_DNSPARSER_Record *answers; /** * Array of all authority records in the packet, must contain "num_authority_records" entries. */ struct GNUNET_DNSPARSER_Record *authority_records; /** * Array of all additional answers in the packet, must contain "num_additional_records" entries. */ struct GNUNET_DNSPARSER_Record *additional_records; /** * Number of queries in the packet. */ unsigned int num_queries; /** * Number of answers in the packet, should be 0 for queries. */ unsigned int num_answers; /** * Number of authoritative answers in the packet, should be 0 for queries. */ unsigned int num_authority_records; /** * Number of additional records in the packet, should be 0 for queries. */ unsigned int num_additional_records; /** * Bitfield of DNS flags. */ struct GNUNET_TUN_DnsFlags flags; /** * DNS ID (to match replies to requests). */ uint16_t id; }; /** * Check if a label in UTF-8 format can be coded into valid IDNA. * This can fail if the ASCII-conversion becomes longer than 63 characters. * * @param label label to check (UTF-8 string) * @return #GNUNET_OK if the label can be converted to IDNA, * #GNUNET_SYSERR if the label is not valid for DNS names */ int GNUNET_DNSPARSER_check_label (const char *label); /** * Check if a hostname in UTF-8 format can be coded into valid IDNA. * This can fail if a label becomes longer than 63 characters or if * the entire name exceeds 253 characters. * * @param name name to check (UTF-8 string) * @return #GNUNET_OK if the label can be converted to IDNA, * #GNUNET_SYSERR if the label is not valid for DNS names */ int GNUNET_DNSPARSER_check_name (const char *name); /** * Parse a UDP payload of a DNS packet in to a nice struct for further * processing and manipulation. * * @param udp_payload wire-format of the DNS packet * @param udp_payload_length number of bytes in @a udp_payload * @return NULL on error, otherwise the parsed packet */ struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse (const char *udp_payload, size_t udp_payload_length); /** * Free memory taken by a packet. * * @param p packet to free */ void GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p); /** * Given a DNS packet @a p, generate the corresponding UDP payload. * Note that we do not attempt to pack the strings with pointers * as this would complicate the code and this is about being * simple and secure, not fast, fancy and broken like bind. * * @param p packet to pack * @param max maximum allowed size for the resulting UDP payload * @param buf set to a buffer with the packed message * @param buf_length set to the length of @a buf * @return #GNUNET_SYSERR if @a p is invalid * #GNUNET_NO if @a p was truncated (but there is still a result in @a buf) * #GNUNET_OK if @a p was packed completely into @a buf */ int GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length); /* ***************** low-level packing API ******************** */ /** * Add a DNS name to the UDP packet at the given location, converting * the name to IDNA notation as necessary. * * @param dst where to write the name (UDP packet) * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the name (increment by bytes used) * must not be changed if there is an error * @param name name to write * @return #GNUNET_SYSERR if @a name is invalid * #GNUNET_NO if @a name did not fit * #GNUNET_OK if @a name was added to @a dst */ int GNUNET_DNSPARSER_builder_add_name (char *dst, size_t dst_len, size_t *off, const char *name); /** * Add a DNS query to the UDP packet at the given location. * * @param dst where to write the query * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the query (increment by bytes used) * must not be changed if there is an error * @param query query to write * @return #GNUNET_SYSERR if @a query is invalid * #GNUNET_NO if @a query did not fit * #GNUNET_OK if @a query was added to @a dst */ int GNUNET_DNSPARSER_builder_add_query (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_Query *query); /** * Add an MX record to the UDP packet at the given location. * * @param dst where to write the mx record * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the mx information (increment by bytes used); * can also change if there was an error * @param mx mx information to write * @return #GNUNET_SYSERR if @a mx is invalid * #GNUNET_NO if @a mx did not fit * #GNUNET_OK if @a mx was added to @a dst */ int GNUNET_DNSPARSER_builder_add_mx (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_MxRecord *mx); /** * Add an SOA record to the UDP packet at the given location. * * @param dst where to write the SOA record * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the SOA information (increment by bytes used) * can also change if there was an error * @param soa SOA information to write * @return #GNUNET_SYSERR if @a soa is invalid * #GNUNET_NO if @a soa did not fit * #GNUNET_OK if @a soa was added to @a dst */ int GNUNET_DNSPARSER_builder_add_soa (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa); /** * Add CERT record to the UDP packet at the given location. * * @param dst where to write the CERT record * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the CERT information (increment by bytes used) * can also change if there was an error * @param cert CERT information to write * @return #GNUNET_SYSERR if @a soa is invalid * #GNUNET_NO if @a soa did not fit * #GNUNET_OK if @a soa was added to @a dst */ int GNUNET_DNSPARSER_builder_add_cert (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_CertRecord *cert); /** * Add an SRV record to the UDP packet at the given location. * * @param dst where to write the SRV record * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the SRV information (increment by bytes used) * can also change if there was an error * @param srv SRV information to write * @return #GNUNET_SYSERR if @a srv is invalid * #GNUNET_NO if @a srv did not fit * #GNUNET_OK if @a srv was added to @a dst */ int GNUNET_DNSPARSER_builder_add_srv (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv); /* ***************** low-level parsing API ******************** */ /** * Parse a DNS record entry. * * @param udp_payload entire UDP payload * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the record to parse in the udp_payload (to be * incremented by the size of the record) * @param r where to write the record information * @return #GNUNET_OK on success, #GNUNET_SYSERR if the record is malformed */ int GNUNET_DNSPARSER_parse_record (const char *udp_payload, size_t udp_payload_length, size_t *off, struct GNUNET_DNSPARSER_Record *r); /** * Parse name inside of a DNS query or record. * * @param udp_payload entire UDP payload * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the name to parse in the udp_payload (to be * incremented by the size of the name) * @return name as 0-terminated C string on success, NULL if the payload is malformed */ char * GNUNET_DNSPARSER_parse_name (const char *udp_payload, size_t udp_payload_length, size_t *off); /** * Parse a DNS query entry. * * @param udp_payload entire UDP payload * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the udp_payload (to be * incremented by the size of the query) * @param q where to write the query information * @return #GNUNET_OK on success, #GNUNET_SYSERR if the query is malformed */ int GNUNET_DNSPARSER_parse_query (const char *udp_payload, size_t udp_payload_length, size_t *off, struct GNUNET_DNSPARSER_Query *q); /** * Parse a DNS SOA record. * * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the SOA record (to be * incremented by the size of the record), unchanged on error * @return the parsed SOA record, NULL on error */ struct GNUNET_DNSPARSER_SoaRecord * GNUNET_DNSPARSER_parse_soa (const char *udp_payload, size_t udp_payload_length, size_t *off); /** * Parse a DNS CERT record. * * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the CERT record (to be * incremented by the size of the record), unchanged on error * @return the parsed CERT record, NULL on error */ struct GNUNET_DNSPARSER_CertRecord * GNUNET_DNSPARSER_parse_cert (const char *udp_payload, size_t udp_payload_length, size_t *off); /** * Parse a DNS MX record. * * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the MX record (to be * incremented by the size of the record), unchanged on error * @return the parsed MX record, NULL on error */ struct GNUNET_DNSPARSER_MxRecord * GNUNET_DNSPARSER_parse_mx (const char *udp_payload, size_t udp_payload_length, size_t *off); /** * Parse a DNS SRV record. * * @param r_name name of the SRV record * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the SRV record (to be * incremented by the size of the record), unchanged on error * @return the parsed SRV record, NULL on error */ struct GNUNET_DNSPARSER_SrvRecord * GNUNET_DNSPARSER_parse_srv (const char *r_name, const char *udp_payload, size_t udp_payload_length, size_t *off); /* ***************** low-level deallocation API ******************** */ /** * Free the given DNS record. * * @param r record to free */ void GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r); /** * Free MX information record. * * @param mx record to free */ void GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx); /** * Free SRV information record. * * @param srv record to free */ void GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv); /** * Free SOA information record. * * @param soa record to free */ void GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa); /** * Free CERT information record. * * @param cert record to free */ void GNUNET_DNSPARSER_free_cert (struct GNUNET_DNSPARSER_CertRecord *cert); #endif gnunet-0.10.1/src/include/gnunet_server_lib.h0000644000175000017500000006656012251306467016134 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_server_lib.h * @brief library for building GNUnet network servers * @author Christian Grothoff * @defgroup server functions for a server that communicates with clients * @{ */ #ifndef GNUNET_SERVER_LIB_H #define GNUNET_SERVER_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_common.h" #include "gnunet_connection_lib.h" /** * Largest supported message (to be precise, one byte more * than the largest possible message, so tests involving * this value should check for messages being smaller than * this value). */ #define GNUNET_SERVER_MAX_MESSAGE_SIZE 65536 /** * Smallest supported message. */ #define GNUNET_SERVER_MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader) /** * @brief handle for a server */ struct GNUNET_SERVER_Handle; /** * @brief opaque handle for a client of the server */ struct GNUNET_SERVER_Client; /** * @brief opaque handle server returns for aborting transmission to a client. */ struct GNUNET_SERVER_TransmitHandle; /** * Functions with this signature are called whenever a message is * received. * * @param cls closure * @param client identification of the client * @param message the actual message */ typedef void (*GNUNET_SERVER_MessageCallback) (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Message handler. Each struct specifies how to handle on particular * type of message received. */ struct GNUNET_SERVER_MessageHandler { /** * Function to call for messages of "type". */ GNUNET_SERVER_MessageCallback callback; /** * Closure argument for @e callback. */ void *callback_cls; /** * Type of the message this handler covers. */ uint16_t type; /** * Expected size of messages of this type. Use 0 for * variable-size. If non-zero, messages of the given * type will be discarded (and the connection closed) * if they do not have the right size. */ uint16_t expected_size; }; /** * Create a new server. * * @param access function for access control * @param access_cls closure for @a access * @param lsocks NULL-terminated array of listen sockets * @param idle_timeout after how long should we timeout idle connections? * @param require_found if #GNUNET_YES, connections sending messages of unknown type * will be closed * @return handle for the new server, NULL on error * (typically, "port" already in use) */ struct GNUNET_SERVER_Handle * GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access, void *access_cls, struct GNUNET_NETWORK_Handle **lsocks, struct GNUNET_TIME_Relative idle_timeout, int require_found); /** * Create a new server. * * @param access function for access control * @param access_cls closure for @a access * @param server_addr address toes listen on (including port), NULL terminated array * @param socklen lengths of respective @a server_addr * @param idle_timeout after how long should we timeout idle connections? * @param require_found if #GNUNET_YES, connections sending messages of unknown type * will be closed * @return handle for the new server, NULL on error * (typically, "port" already in use) */ struct GNUNET_SERVER_Handle * GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access, void *access_cls, struct sockaddr *const *server_addr, const socklen_t * socklen, struct GNUNET_TIME_Relative idle_timeout, int require_found); /** * Suspend accepting connections from the listen socket temporarily. * Resume activity using #GNUNET_SERVER_resume. * * @param server server to stop accepting connections. */ void GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server); /** * Resume accepting connections from the listen socket. * * @param server server to resume accepting connections. */ void GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server); /** * Stop the listen socket and get ready to shutdown the server once * only clients marked using #GNUNET_SERVER_client_mark_monitor are * left. * * @param server server to stop listening on */ void GNUNET_SERVER_stop_listening (struct GNUNET_SERVER_Handle *server); /** * Free resources held by this server. * * @param server server to destroy */ void GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *server); /** * Add additional handlers to an existing server. * * @param server the server to add handlers to * @param handlers array of message handlers for * incoming messages; the last entry must * have "NULL" for the "callback"; multiple * entries for the same type are allowed, * they will be called in order of occurence. * These handlers can be removed later; * the handlers array must exist until removed * (or server is destroyed). */ void GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server, const struct GNUNET_SERVER_MessageHandler *handlers); /** * Notify us when the server has enough space to transmit * a message of the given size to the given client. * * @param client client to transmit message to * @param size requested amount of buffer space * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param callback function to call when space is available * @param callback_cls closure for @a callback * @return non-NULL if the notify callback was queued; can be used * to cancel the request using * #GNUNET_SERVER_notify_transmit_ready_cancel. * NULL if we are already going to notify someone else (busy) */ struct GNUNET_SERVER_TransmitHandle * GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify callback, void *callback_cls); /** * Abort transmission request. * * @param th request to abort */ void GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle *th); /** * Set the 'monitor' flag on this client. Clients which have been * marked as 'monitors' won't prevent the server from shutting down * once #GNUNET_SERVER_stop_listening has been invoked. The idea is * that for "normal" clients we likely want to allow them to process * their requests; however, monitor-clients are likely to 'never' * disconnect during shutdown and thus will not be considered when * determining if the server should continue to exist after * #GNUNET_SERVER_destroy has been called. * * @param client the client to set the 'monitor' flag on */ void GNUNET_SERVER_client_mark_monitor (struct GNUNET_SERVER_Client *client); /** * Set the persistent flag on this client, used to setup client * connection to only be killed when the process of the service it's * connected to is actually dead. This API is used during shutdown * signalling within ARM, and it is not expected that typical users * of the API would need this function. * * @param client the client to set the persistent flag on */ void GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client); /** * Resume receiving from this client, we are done processing the * current request. This function must be called from within each * #GNUNET_SERVER_MessageCallback (or its respective continuations). * * @param client client we were processing a message of * @param success #GNUNET_OK to keep the connection open and * continue to receive * #GNUNET_NO to close the connection (normal behavior) * #GNUNET_SYSERR to close the connection (signal * serious error) */ void GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success); /** * Change the timeout for a particular client. Decreasing the timeout * may not go into effect immediately (only after the previous timeout * times out or activity happens on the socket). * * @param client the client to update * @param timeout new timeout for activities on the socket */ void GNUNET_SERVER_client_set_timeout (struct GNUNET_SERVER_Client *client, struct GNUNET_TIME_Relative timeout); /** * Return user context associated with the given client. * Note: you should probably use the macro (call without the underscore). * * @param client client to query * @param size number of bytes in user context struct (for verification only) * @return pointer to user context */ void * GNUNET_SERVER_client_get_user_context_ (struct GNUNET_SERVER_Client *client, size_t size); /** * Set user context to be associated with the given client. * Note: you should probably use the macro (call without the underscore). * * @param client client to query * @param ptr pointer to user context * @param size number of bytes in user context struct (for verification only) */ void GNUNET_SERVER_client_set_user_context_ (struct GNUNET_SERVER_Client *client, void *ptr, size_t size); /** * Return user context associated with the given client. * * @param client client to query * @param type expected return type (i.e. 'struct Foo') * @return pointer to user context of type 'type *'. */ #define GNUNET_SERVER_client_get_user_context(client,type) \ (type *) GNUNET_SERVER_client_get_user_context_ (client, sizeof (type)) /** * Set user context to be associated with the given client. * * @param client client to query * @param value pointer to user context */ #define GNUNET_SERVER_client_set_user_context(client,value) \ GNUNET_SERVER_client_set_user_context_ (client, value, sizeof (*value)) /** * Disable the warning the server issues if a message is not acknowledged * in a timely fashion. Use this call if a client is intentionally delayed * for a while. Only applies to the current message. * * @param client client for which to disable the warning */ void GNUNET_SERVER_disable_receive_done_warning (struct GNUNET_SERVER_Client *client); /** * Inject a message into the server, pretend it came * from the specified client. Delivery of the message * will happen instantly (if a handler is installed; * otherwise the call does nothing). * * @param server the server receiving the message * @param sender the "pretended" sender of the message * can be NULL! * @param message message to transmit * @return #GNUNET_OK if the message was OK and the * connection can stay open * #GNUNET_SYSERR if the connection to the * client should be shut down */ int GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server, struct GNUNET_SERVER_Client *sender, const struct GNUNET_MessageHeader *message); /** * Add a TCP socket-based connection to the set of handles managed by * this server. Use this function for outgoing (P2P) connections that * we initiated (and where this server should process incoming * messages). * * @param server the server to use * @param connection the connection to manage (client must * stop using this connection from now on) * @return the client handle (client should call * #GNUNET_SERVER_client_drop on the return value eventually) */ struct GNUNET_SERVER_Client * GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server, struct GNUNET_CONNECTION_Handle *connection); /** * Notify the server that the given client handle should * be kept (keeps the connection up if possible, increments * the internal reference counter). * * @param client the client to keep */ void GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client); /** * Notify the server that the given client handle is no * longer required. Decrements the reference counter. If * that counter reaches zero an inactive connection maybe * closed. * * @param client the client to drop */ void GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client); /** * Obtain the network address of the other party. * * @param client the client to get the address for * @param addr where to store the address * @param addrlen where to store the length of @a addr * @return #GNUNET_OK on success */ int GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client, void **addr, size_t *addrlen); /** * Functions with this signature are called whenever a client * is disconnected on the network level. * * @param cls closure * @param client identification of the client; NULL * for the last call when the server is destroyed */ typedef void (*GNUNET_SERVER_DisconnectCallback) (void *cls, struct GNUNET_SERVER_Client *client); /** * Functions with this signature are called whenever a client * is connected on the network level. * * @param cls closure * @param client identification of the client */ typedef void (*GNUNET_SERVER_ConnectCallback) (void *cls, struct GNUNET_SERVER_Client *client); /** * Ask the server to notify us whenever a client disconnects. * This function is called whenever the actual network connection * is closed; the reference count may be zero or larger than zero * at this point. If the server is destroyed before this * notification is explicitly cancelled, the 'callback' will * once be called with a 'client' argument of NULL to indicate * that the server itself is now gone (and that the callback * won't be called anymore and also can no longer be cancelled). * * @param server the server manageing the clients * @param callback function to call on disconnect * @param callback_cls closure for @a callback */ void GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_DisconnectCallback callback, void *callback_cls); /** * Ask the server to notify us whenever a client connects. * This function is called whenever the actual network connection * is opened. If the server is destroyed before this * notification is explicitly cancelled, the @a callback will * once be called with a 'client' argument of NULL to indicate * that the server itself is now gone (and that the callback * won't be called anymore and also can no longer be cancelled). * * @param server the server manageing the clients * @param callback function to call on sconnect * @param callback_cls closure for @a callback */ void GNUNET_SERVER_connect_notify (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_ConnectCallback callback, void *callback_cls); /** * Ask the server to stop notifying us whenever a client disconnects. * Arguments must match exactly those given to * #GNUNET_SERVER_disconnect_notify. It is not necessary to call this * function during shutdown of the server; in fact, most applications * will never use this function. * * @param server the server manageing the clients * @param callback function to call on disconnect * @param callback_cls closure for @a callback */ void GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_DisconnectCallback callback, void *callback_cls); /** * Ask the server to stop notifying us whenever a client connects. * Arguments must match exactly those given to * #GNUNET_SERVER_connect_notify. It is not necessary to call this * function during shutdown of the server; in fact, most applications * will never use this function. * * @param server the server manageing the clients * @param callback function to call on connect * @param callback_cls closure for @a callback */ void GNUNET_SERVER_connect_notify_cancel (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_ConnectCallback callback, void *callback_cls); /** * Ask the server to disconnect from the given client. This is the * same as passing #GNUNET_SYSERR to #GNUNET_SERVER_receive_done, * except that it allows dropping of a client even when not handling a * message from that client. * * @param client the client to disconnect from */ void GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client); /** * Disable the "CORK" feature for communication with the given client, * forcing the OS to immediately flush the buffer on transmission * instead of potentially buffering multiple messages. * * @param client handle to the client * @return #GNUNET_OK on success */ int GNUNET_SERVER_client_disable_corking (struct GNUNET_SERVER_Client *client); /** * The tansmit context is the key datastructure for a conveniance API * used for transmission of complex results to the client followed * ONLY by signaling receive_done with success or error */ struct GNUNET_SERVER_TransmitContext; /** * Create a new transmission context for the given client. * * @param client client to create the context for. * @return NULL on error */ struct GNUNET_SERVER_TransmitContext * GNUNET_SERVER_transmit_context_create (struct GNUNET_SERVER_Client *client); /** * Append a message to the transmission context. * All messages in the context will be sent by * the #GNUNET_SERVER_transmit_context_run method. * * @param tc context to use * @param data what to append to the result message * @param length length of @a data * @param type type of the message */ void GNUNET_SERVER_transmit_context_append_data (struct GNUNET_SERVER_TransmitContext *tc, const void *data, size_t length, uint16_t type); /** * Append a message to the transmission context. * All messages in the context will be sent by * the transmit_context_run method. * * @param tc context to use * @param msg message to append */ void GNUNET_SERVER_transmit_context_append_message (struct GNUNET_SERVER_TransmitContext *tc, const struct GNUNET_MessageHeader *msg); /** * Execute a transmission context. If there is an error in the * transmission, the receive_done method will be called with an error * code (#GNUNET_SYSERR), otherwise with #GNUNET_OK. * * @param tc transmission context to use * @param timeout when to time out and abort the transmission */ void GNUNET_SERVER_transmit_context_run (struct GNUNET_SERVER_TransmitContext *tc, struct GNUNET_TIME_Relative timeout); /** * Destroy a transmission context. This function must not be called * after #GNUNET_SERVER_transmit_context_run. * * @param tc transmission context to destroy * @param success code to give to #GNUNET_SERVER_receive_done for * the client: #GNUNET_OK to keep the connection open and * continue to receive * #GNUNET_NO to close the connection (normal behavior) * #GNUNET_SYSERR to close the connection (signal * serious error) */ void GNUNET_SERVER_transmit_context_destroy (struct GNUNET_SERVER_TransmitContext *tc, int success); /** * The notification context is the key datastructure for a conveniance * API used for transmission of notifications to the client until the * client disconnects or is disconnected (or the notification context * is destroyed, in which case we disconnect these clients). * Essentially, all (notification) messages are queued up until the * client is able to read them. */ struct GNUNET_SERVER_NotificationContext; /** * Create a new notification context. * * @param server server for which this function creates the context * @param queue_length maximum number of messages to keep in * the notification queue; optional messages are dropped * if the queue gets longer than this number of messages * @return handle to the notification context */ struct GNUNET_SERVER_NotificationContext * GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server, unsigned int queue_length); /** * Destroy the context, force disconnect for all clients. * * @param nc context to destroy. */ void GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationContext *nc); /** * Add a client to the notification context. * * @param nc context to modify * @param client client to add */ void GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext *nc, struct GNUNET_SERVER_Client *client); /** * Send a message to a particular client; must have * already been added to the notification context. * * @param nc context to modify * @param client client to transmit to * @param msg message to send * @param can_drop can this message be dropped due to queue length limitations */ void GNUNET_SERVER_notification_context_unicast (struct GNUNET_SERVER_NotificationContext *nc, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg, int can_drop); /** * Send a message to all clients of this context. * * @param nc context to modify * @param msg message to send * @param can_drop can this message be dropped due to queue length limitations */ void GNUNET_SERVER_notification_context_broadcast (struct GNUNET_SERVER_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop); /** * Handle to a message stream tokenizer. */ struct GNUNET_SERVER_MessageStreamTokenizer; /** * Functions with this signature are called whenever a * complete message is received by the tokenizer. * * Do not call #GNUNET_SERVER_mst_destroy from within * the scope of this callback. * * @param cls closure * @param client identification of the client * @param message the actual message * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing */ typedef int (*GNUNET_SERVER_MessageTokenizerCallback) (void *cls, void *client, const struct GNUNET_MessageHeader *message); /** * Create a message stream tokenizer. * * @param cb function to call on completed messages * @param cb_cls closure for @a cb * @return handle to tokenizer */ struct GNUNET_SERVER_MessageStreamTokenizer * GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls); /** * Add incoming data to the receive buffer and call the * callback for all complete messages. * * @param mst tokenizer to use * @param client_identity ID of client for which this is a buffer, * can be NULL (will be passed back to 'cb') * @param buf input data to add * @param size number of bytes in @a buf * @param purge should any excess bytes in the buffer be discarded * (i.e. for packet-based services like UDP) * @param one_shot only call callback once, keep rest of message in buffer * @return #GNUNET_OK if we are done processing (need more data) * #GNUNET_NO if one_shot was set and we have another message ready * #GNUNET_SYSERR if the data stream is corrupt */ int GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst, void *client_identity, const char *buf, size_t size, int purge, int one_shot); /** * Destroys a tokenizer. * * @param mst tokenizer to destroy */ void GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst); /** * Signature of a function to create a custom tokenizer. * * @param cls closure from #GNUNET_SERVER_set_callbacks * @param client handle to client the tokenzier will be used for * @return handle to custom tokenizer ('mst') */ typedef void* (*GNUNET_SERVER_MstCreateCallback) (void *cls, struct GNUNET_SERVER_Client *client); /** * Signature of a function to destroy a custom tokenizer. * * @param cls closure from #GNUNET_SERVER_set_callbacks * @param mst custom tokenizer handle */ typedef void (*GNUNET_SERVER_MstDestroyCallback) (void *cls, void *mst); /** * Signature of a function to receive data for a custom tokenizer. * * @param cls closure from #GNUNET_SERVER_set_callbacks * @param mst custom tokenizer handle * @param client_identity ID of client for which this is a buffer, * can be NULL (will be passed back to 'cb') * @param buf input data to add * @param size number of bytes in @a buf * @param purge should any excess bytes in the buffer be discarded * (i.e. for packet-based services like UDP) * @param one_shot only call callback once, keep rest of message in buffer * @return #GNUNET_OK if we are done processing (need more data) * #GNUNET_NO if one_shot was set and we have another message ready * #GNUNET_SYSERR if the data stream is corrupt */ typedef int (*GNUNET_SERVER_MstReceiveCallback) (void *cls, void *mst, struct GNUNET_SERVER_Client *client, const char *buf, size_t size, int purge, int one_shot); /** * Change functions used by the server to tokenize the message stream. * (very rarely used). * * @param server server to modify * @param create new tokenizer initialization function * @param destroy new tokenizer destruction function * @param receive new tokenizer receive function * @param cls closure for @a create, @a receive and @a destroy */ void GNUNET_SERVER_set_callbacks (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_MstCreateCallback create, GNUNET_SERVER_MstDestroyCallback destroy, GNUNET_SERVER_MstReceiveCallback receive, void *cls); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group server */ /* ifndef GNUNET_SERVER_LIB_H */ #endif /* end of gnunet_server_lib.h */ gnunet-0.10.1/src/include/gnunet_service_lib.h0000644000175000017500000001243512225777503016262 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_service_lib.h * @brief functions related to starting services * @author Christian Grothoff * @defgroup service generic functions for implementing service processes * @{ */ #ifndef GNUNET_SERVICE_LIB_H #define GNUNET_SERVICE_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_configuration_lib.h" #include "gnunet_server_lib.h" /** * Get the list of addresses that a server for the given service * should bind to. * * @param service_name name of the service * @param cfg configuration (which specifies the addresses) * @param addrs set (call by reference) to an array of pointers to the * addresses the server should bind to and listen on; the * array will be NULL-terminated (on success) * @param addr_lens set (call by reference) to an array of the lengths * of the respective 'struct sockaddr' struct in the @a addrs * array (on success) * @return number of addresses found on success, * #GNUNET_SYSERR if the configuration * did not specify reasonable finding information or * if it specified a hostname that could not be resolved; * #GNUNET_NO if the number of addresses configured is * zero (in this case, '* @a addrs' and '* @a addr_lens' will be * set to NULL). */ int GNUNET_SERVICE_get_server_addresses (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, struct sockaddr ***addrs, socklen_t **addr_lens); /** * Function called by the service's run * method to run service-specific setup code. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ typedef void (*GNUNET_SERVICE_Main) (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Options for the service (bitmask). */ enum GNUNET_SERVICE_Options { /** * Use defaults. */ GNUNET_SERVICE_OPTION_NONE = 0, /** * Do not trigger server shutdown on signals, allow for the user * to terminate the server explicitly when needed. */ GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN = 1, /** * Trigger a SOFT server shutdown on signals, allowing active * non-monitor clients to complete their transactions. */ GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN = 2 }; /** * Run a standard GNUnet service startup sequence (initialize loggers * and configuration, parse options). * * @param argc number of command line arguments in @a argv * @param argv command line arguments * @param service_name our service name * @param options service options * @param task main task of the service * @param task_cls closure for @a task * @return #GNUNET_SYSERR on error, #GNUNET_OK * if we shutdown nicely */ int GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name, enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_Main task, void *task_cls); /** * Opaque handle for a service. */ struct GNUNET_SERVICE_Context; /** * Run a service startup sequence within an existing * initialized system. * * @param service_name our service name * @param cfg configuration to use * @param options service options * @return NULL on error, service handle */ struct GNUNET_SERVICE_Context * GNUNET_SERVICE_start (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SERVICE_Options options); /** * Obtain the server used by a service. Note that the server must NOT * be destroyed by the caller. * * @param ctx the service context returned from the start function * @return handle to the server for this service, NULL if there is none */ struct GNUNET_SERVER_Handle * GNUNET_SERVICE_get_server (struct GNUNET_SERVICE_Context *ctx); /** * Stop a service that was started with #GNUNET_SERVICE_start. * * @param sctx the service context returned from the start function */ void GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group service */ /* ifndef GNUNET_SERVICE_LIB_H */ #endif /* end of gnunet_service_lib.h */ gnunet-0.10.1/src/include/gnunet_vpn_service.h0000644000175000017500000001227712225777503016323 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_vpn_service.h * @brief API to access the VPN service. * @author Christian Grothoff */ #ifndef GNUNET_VPN_SERVICE_H #define GNUNET_VPN_SERVICE_H #include "gnunet_util_lib.h" /** * Opaque VPN handle */ struct GNUNET_VPN_Handle; /** * Opaque redirection request handle. */ struct GNUNET_VPN_RedirectionRequest; /** * Callback invoked from the VPN service once a redirection is * available. Provides the IP address that can now be used to * reach the requested destination. * * @param cls closure * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; * will match 'result_af' from the request * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') * that the VPN allocated for the redirection; * traffic to this IP will now be redirected to the * specified target peer; NULL on error */ typedef void (*GNUNET_VPN_AllocationCallback)(void *cls, int af, const void *address); /** * Cancel redirection request with the service. * * @param rr request to cancel */ void GNUNET_VPN_cancel_request (struct GNUNET_VPN_RedirectionRequest *rr); /** * Tell the VPN that a forwarding to a particular peer offering a * particular service is requested. The VPN is to reserve a * particular IP for the redirection and return it. The VPN will * begin the redirection as soon as possible and maintain it as long * as it is actively used and keeping it is feasible. Given resource * limitations, the longest inactive mappings will be destroyed. * * @param vh VPN handle * @param result_af desired address family for the returned allocation * can also be AF_UNSPEC * @param protocol protocol, IPPROTO_UDP or IPPROTO_TCP * @param peer target peer for the redirection * @param serv service descriptor to give to the peer * @param expiration_time at what time should the redirection expire? * (this should not impact connections that are active at that time) * @param cb function to call with the IP * @param cb_cls closure for cb * @return handle to cancel the request (means the callback won't be * invoked anymore; the mapping may or may not be established * anyway) */ struct GNUNET_VPN_RedirectionRequest * GNUNET_VPN_redirect_to_peer (struct GNUNET_VPN_Handle *vh, int result_af, uint8_t protocol, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HashCode *serv, struct GNUNET_TIME_Absolute expiration_time, GNUNET_VPN_AllocationCallback cb, void *cb_cls); /** * Tell the VPN that forwarding to the Internet via some exit node is * requested. Note that both UDP and TCP traffic will be forwarded, * but possibly to different exit nodes. The VPN is to reserve a * particular IP for the redirection and return it. The VPN will * begin the redirection as soon as possible and maintain it as long * as it is actively used and keeping it is feasible. Given resource * limitations, the longest inactive mappings will be destroyed. * * @param vh VPN handle * @param result_af desired address family for the returned allocation, * can also be AF_UNSPEC * @param addr_af address family for 'addr', AF_INET or AF_INET6 * @param addr destination IP address on the Internet; destination * port is to be taken from the VPN packet itself * @param expiration_time at what time should the redirection expire? * (this should not impact connections that are active at that time) * @param cb function to call with the IP * @param cb_cls closure for cb * @return handle to cancel the request (means the callback won't be * invoked anymore; the mapping may or may not be established * anyway) */ struct GNUNET_VPN_RedirectionRequest * GNUNET_VPN_redirect_to_ip (struct GNUNET_VPN_Handle *vh, int result_af, int addr_af, const void *addr, struct GNUNET_TIME_Absolute expiration_time, GNUNET_VPN_AllocationCallback cb, void *cb_cls); /** * Connect to the VPN service * * @param cfg configuration to use * @return VPN handle */ struct GNUNET_VPN_Handle * GNUNET_VPN_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Disconnect from the VPN service. * * @param vh VPN handle */ void GNUNET_VPN_disconnect (struct GNUNET_VPN_Handle *vh); #endif gnunet-0.10.1/src/include/gnunet_microphone_lib.h0000644000175000017500000000614412225777503016765 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_microphone_lib.h * @brief API to access an audio microphone; provides access to hardware microphones * @author Simon Dieterle * @author Andreas Fuchs * @author Christian Grothoff */ #ifndef GNUNET_MICROPHONE_SERVICE_H #define GNUNET_MICROPHONE_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Process recorded audio data. * * @param cls clsoure * @param data_size number of bytes in @a data * @param data audio data to play */ typedef void (*GNUNET_MICROPHONE_RecordedDataCallback)(void *cls, size_t data_size, const void *data); /** * Enable a microphone. * * @param cls clsoure * @param rdc function to call with recorded data * @param rdc_cls closure for @a dc * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ typedef int (*GNUNET_MICROPHONE_EnableCallback)(void *cls, GNUNET_MICROPHONE_RecordedDataCallback rdc, void *rdc_cls); /** * Function that disables a microphone. * * @param cls clsoure */ typedef void (*GNUNET_MICROPHONE_DisableCallback)(void *cls); /** * Function to destroy a microphone. * * @param cls clsoure */ typedef void (*GNUNET_MICROPHONE_DestroyCallback)(void *cls); /** * A microphone is a device that can capture or otherwise produce audio data. */ struct GNUNET_MICROPHONE_Handle { /** * Turn on the microphone. */ GNUNET_MICROPHONE_EnableCallback enable_microphone; /** * Turn the microphone off. */ GNUNET_MICROPHONE_DisableCallback disable_microphone; /** * Destroy the microphone. Called by #GNUNET_MICROPHONE_destroy. */ GNUNET_MICROPHONE_DestroyCallback destroy_microphone; /** * Closure for the callbacks. */ void *cls; }; /** * Create a microphone that corresponds to the microphone hardware * of our system. * * @param cfg configuration to use * @return NULL on error */ struct GNUNET_MICROPHONE_Handle * GNUNET_MICROPHONE_create_from_hardware (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Destroy a microphone. * * @param microphone microphone to destroy */ void GNUNET_MICROPHONE_destroy (struct GNUNET_MICROPHONE_Handle *microphone); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif /* end of gnunet_microphone_lib.h */ gnunet-0.10.1/src/include/gnunet_statistics_service.h0000644000175000017500000001567312255010512017674 00000000000000/* This file is part of GNUnet (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_statistics_service.h * @brief API to create, modify and access statistics about * the operation of GNUnet; all statistical values * must be of type `unsigned long long`. * @author Christian Grothoff * @defgroup statistics track statistics or provide access to statistics * @{ */ #ifndef GNUNET_STATISTICS_SERVICE_H #define GNUNET_STATISTICS_SERVICE_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * Version of the statistics API. */ #define GNUNET_STATISTICS_VERSION 0x00000000 /** * Opaque handle for the statistics service. */ struct GNUNET_STATISTICS_Handle; /** * Callback function to process statistic values. * * @param cls closure * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration */ typedef int (*GNUNET_STATISTICS_Iterator) (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent); /** * Get handle for the statistics service. * * @param subsystem name of subsystem using the service * @param cfg services configuration in use * @return handle to use */ struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create (const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Destroy a handle (free all state associated with * it). * * @param h statistics handle to destroy * @param sync_first set to #GNUNET_YES if pending SET requests should * be completed */ void GNUNET_STATISTICS_destroy (struct GNUNET_STATISTICS_Handle *h, int sync_first); /** * Watch statistics from the peer (be notified whenever they change). * * @param handle identification of the statistics service * @param subsystem limit to the specified subsystem, never NULL * @param name name of the statistic value, never NULL * @param proc function to call on each value * @param proc_cls closure for @a proc * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_STATISTICS_watch (struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Iterator proc, void *proc_cls); /** * Stop watching statistics from the peer. * * @param handle identification of the statistics service * @param subsystem limit to the specified subsystem, never NULL * @param name name of the statistic value, never NULL * @param proc function to call on each value * @param proc_cls closure for @a proc * @return #GNUNET_OK on success, #GNUNET_SYSERR on error (no such watch) */ int GNUNET_STATISTICS_watch_cancel (struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, GNUNET_STATISTICS_Iterator proc, void *proc_cls); /** * Continuation called by #GNUNET_STATISTICS_get functions. * * @param cls closure * @param success #GNUNET_OK if statistics were * successfully obtained, #GNUNET_SYSERR if not. */ typedef void (*GNUNET_STATISTICS_Callback) (void *cls, int success); /** * Handle that can be used to cancel a statistics 'get' operation. */ struct GNUNET_STATISTICS_GetHandle; /** * Get statistic from the peer. * * @param handle identification of the statistics service * @param subsystem limit to the specified subsystem, NULL for all subsystems * @param name name of the statistic value, NULL for all values * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param cont continuation to call when done (can be NULL) * This callback CANNOT destroy the statistics handle in the same call. * @param proc function to call on each value * @param cls closure for @a proc and @a cont * @return NULL on error */ struct GNUNET_STATISTICS_GetHandle * GNUNET_STATISTICS_get (struct GNUNET_STATISTICS_Handle *handle, const char *subsystem, const char *name, struct GNUNET_TIME_Relative timeout, GNUNET_STATISTICS_Callback cont, GNUNET_STATISTICS_Iterator proc, void *cls); /** * Cancel a #GNUNET_STATISTICS_get request. Must be called before the 'cont' * function is called. * * @param gh handle of the request to cancel */ void GNUNET_STATISTICS_get_cancel (struct GNUNET_STATISTICS_GetHandle *gh); /** * Set statistic value for the peer. Will always use our * subsystem (the argument used when @a handle was created). * * @param handle identification of the statistics service * @param name name of the statistic value * @param value new value to set * @param make_persistent should the value be kept across restarts? */ void GNUNET_STATISTICS_set (struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent); /** * Set statistic value for the peer. Will always use our * subsystem (the argument used when @a handle was created). * * @param handle identification of the statistics service * @param name name of the statistic value * @param delta change in value (added to existing value) * @param make_persistent should the value be kept across restarts? */ void GNUNET_STATISTICS_update (struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /** @} */ /* end of group statistics */ #endif gnunet-0.10.1/src/include/gnunet_peer_lib.h0000644000175000017500000000574112225777503015557 00000000000000/* This file is part of GNUnet. (C) 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file include/gnunet_peer_lib.h * @brief helper library for interning of peer identifiers * @author Christian Grothoff */ #ifndef GNUNET_PEER_LIB_H #define GNUNET_PEER_LIB_H #include "gnunet_util_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * A GNUNET_PEER_Id is simply a shorter * version of a "struct GNUNET_PeerIdentifier" * that can be used inside of a GNUnet peer * to save memory when the same identifier * needs to be used over and over again. */ typedef unsigned int GNUNET_PEER_Id; /** * Search for a peer identity. The reference counter is not changed. * * @param pid identity to find * @return the interned identity or 0. */ GNUNET_PEER_Id GNUNET_PEER_search (const struct GNUNET_PeerIdentity *pid); /** * Intern an peer identity. If the identity is already known, its * reference counter will be increased by one. * * @param pid identity to intern * @return the interned identity. */ GNUNET_PEER_Id GNUNET_PEER_intern (const struct GNUNET_PeerIdentity *pid); /** * Change the reference counter of an interned PID. * * @param id identity to change the RC of * @param delta how much to change the RC */ void GNUNET_PEER_change_rc (GNUNET_PEER_Id id, int delta); /** * Decrement multiple RCs of peer identities by one. * * @param ids array of PIDs to decrement the RCs of * @param count size of the ids array */ void GNUNET_PEER_decrement_rcs (const GNUNET_PEER_Id *ids, unsigned int count); /** * Convert an interned PID to a normal peer identity. * * @param id interned PID to convert * @param pid where to write the normal peer identity */ void GNUNET_PEER_resolve (GNUNET_PEER_Id id, struct GNUNET_PeerIdentity *pid); /** * Convert an interned PID to a normal peer identity. * * @param id interned PID to convert * @return pointer to peer identity, valid as long 'id' is valid */ const struct GNUNET_PeerIdentity * GNUNET_PEER_resolve2 (GNUNET_PEER_Id id); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_PEER_LIB_H */ #endif /* end of gnunet_peer_lib.h */ gnunet-0.10.1/src/regex/0000755000175000017500000000000012320755626012003 500000000000000gnunet-0.10.1/src/regex/plugin_block_regex.c0000644000175000017500000002526612255426423015741 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/plugin_block_regex.c * @brief blocks used for regex storage and search * @author Bartlomiej Polot */ #include "platform.h" #include "gnunet_block_plugin.h" #include "block_regex.h" #include "regex_block_lib.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" /** * Function called to validate a reply or a request of type * GNUNET_BLOCK_TYPE_REGEX. * For request evaluation, pass "NULL" for the reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would * be done with the "get_key" function. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for bf * @param xquery extrended query data (can be NULL, depending on type) * @param xquery_size number of bytes in xquery * @param reply_block response to validate * @param reply_block_size number of bytes in reply block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult evaluate_block_regex (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { if (NULL == reply_block) { if (0 != xquery_size) { const char *s; s = (const char *) xquery; if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */ { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } } return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; } if (0 != xquery_size) { const char *s; s = (const char *) xquery; if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */ { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } } else if (NULL != query) { /* xquery is required for regex GETs, at least an empty string */ GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "type %d, query %p, xquery %p\n", type, query, xquery); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } switch (REGEX_BLOCK_check (reply_block, reply_block_size, query, xquery)) { case GNUNET_SYSERR: GNUNET_break_op(0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; case GNUNET_NO: /* xquery missmatch, can happen */ return GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT; default: break; } if (NULL != bf) { struct GNUNET_HashCode chash; struct GNUNET_HashCode mhash; GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); if (NULL != *bf) { if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; } else { *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, GNUNET_CONSTANTS_BLOOMFILTER_K); } GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); } return GNUNET_BLOCK_EVALUATION_OK_MORE; } /** * Function called to validate a reply or a request of type * GNUNET_BLOCK_TYPE_REGEX_ACCEPT. * For request evaluation, pass "NULL" for the reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would * be done with the "get_key" function. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for bf * @param xquery extrended query data (can be NULL, depending on type) * @param xquery_size number of bytes in xquery * @param reply_block response to validate * @param reply_block_size number of bytes in reply block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult evaluate_block_regex_accept (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { const struct RegexAcceptBlock *rba; if (0 != xquery_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } if (NULL == reply_block) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; if (sizeof (struct RegexAcceptBlock) != reply_block_size) { GNUNET_break_op(0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } rba = reply_block; if (ntohl (rba->purpose.size) != sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_HashCode)) { GNUNET_break_op(0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (rba->expiration_time)).rel_value_us) { /* technically invalid, but can happen without an error, so we're nice by reporting it as a 'duplicate' */ return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT, &rba->purpose, &rba->signature, &rba->peer.public_key)) { GNUNET_break_op(0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (NULL != bf) { struct GNUNET_HashCode chash; struct GNUNET_HashCode mhash; GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); if (NULL != *bf) { if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; } else { *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, GNUNET_CONSTANTS_BLOOMFILTER_K); } GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); } return GNUNET_BLOCK_EVALUATION_OK_MORE; } /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would * be done with the "get_key" function. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for bf * @param xquery extrended query data (can be NULL, depending on type) * @param xquery_size number of bytes in xquery * @param reply_block response to validate * @param reply_block_size number of bytes in reply block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult block_plugin_regex_evaluate (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { enum GNUNET_BLOCK_EvaluationResult result; switch (type) { case GNUNET_BLOCK_TYPE_REGEX: result = evaluate_block_regex (cls, type, query, bf, bf_mutator, xquery, xquery_size, reply_block, reply_block_size); break; case GNUNET_BLOCK_TYPE_REGEX_ACCEPT: result = evaluate_block_regex_accept (cls, type, query, bf, bf_mutator, xquery, xquery_size, reply_block, reply_block_size); break; default: result = GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; } return result; } /** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param block block to get the key for * @param block_size number of bytes in @a block * @param key set to the key (query) for the given block * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int block_plugin_regex_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode * key) { switch (type) { case GNUNET_BLOCK_TYPE_REGEX: if (GNUNET_OK != REGEX_BLOCK_get_key (block, block_size, key)) { GNUNET_break_op (0); return GNUNET_NO; } return GNUNET_OK; case GNUNET_BLOCK_TYPE_REGEX_ACCEPT: if (sizeof (struct RegexAcceptBlock) != block_size) { GNUNET_break_op (0); return GNUNET_NO; } *key = ((struct RegexAcceptBlock *) block)->key; return GNUNET_OK; default: GNUNET_break (0); return GNUNET_SYSERR; } } /** * Entry point for the plugin. */ void * libgnunet_plugin_block_regex_init (void *cls) { static enum GNUNET_BLOCK_Type types[] = { GNUNET_BLOCK_TYPE_REGEX, GNUNET_BLOCK_TYPE_REGEX_ACCEPT, GNUNET_BLOCK_TYPE_ANY /* end of list */ }; struct GNUNET_BLOCK_PluginFunctions *api; api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_regex_evaluate; api->get_key = &block_plugin_regex_get_key; api->types = types; return api; } /** * Exit point from the plugin. */ void * libgnunet_plugin_block_regex_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_block_regex.c */ gnunet-0.10.1/src/regex/regex_ipc.h0000644000175000017500000000434112307322113014025 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/regex_ipc.h * @brief regex IPC messages (not called 'regex.h' due to conflict with * system headers) * @author Christian Grothoff */ #ifndef REGEX_IPC_H #define REGEX_IPC_H #include "gnunet_util_lib.h" /** * Request for regex service to announce capability. */ struct AnnounceMessage { /** * Type is GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE */ struct GNUNET_MessageHeader header; /** * How many characters can we squeeze per edge? */ uint16_t compression; /** * Always zero. */ uint16_t reserved; /** * Delay between repeated announcements. */ struct GNUNET_TIME_RelativeNBO refresh_delay; /* followed by 0-terminated regex as string */ }; /** * Message to initiate regex search. */ struct RegexSearchMessage { /** * Type is GNUNET_MESSAGE_TYPE_REGEX_SEARCH */ struct GNUNET_MessageHeader header; /* followed by 0-terminated search string */ }; /** * Result from regex search. */ struct ResultMessage { /** * Type is GNUNET_MESSAGE_TYPE_REGEX_RESULT */ struct GNUNET_MessageHeader header; /** * Number of entries in the GET path. */ uint16_t get_path_length; /** * Number of entries in the PUT path. */ uint16_t put_path_length; /** * Identity of the peer that was found. */ struct GNUNET_PeerIdentity id; /* followed by GET path and PUT path arrays */ }; /* end of regex_ipc.h */ #endif gnunet-0.10.1/src/regex/regex_simulation_profiler_test.conf0000644000175000017500000000016412225230043021073 00000000000000[regex-mysql] DATABASE = regex USER = gnunet PASSWORD = HOST = localhost PORT = 3306 REGEX_PREFIX = GNVPN-0001-PAD gnunet-0.10.1/src/regex/test_regex_eval_api.c0000644000175000017500000005237012225777501016107 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/test_regex_eval_api.c * @brief test for regex.c * @author Maximilian Szengel */ #include #include #include "platform.h" #include "regex_internal_lib.h" #include "regex_test_lib.h" #include "regex_internal.h" enum Match_Result { match = 0, nomatch = 1 }; struct Regex_String_Pair { char *regex; int string_count; char *strings[20]; enum Match_Result expected_results[20]; }; /** * Random regex test. Generate a random regex as well as 'str_count' strings to * match it against. Will match using GNUNET_REGEX implementation and compare * the result to glibc regex result. 'rx_length' has to be smaller then * 'max_str_len'. * * @param rx_length length of the regular expression. * @param max_str_len maximum length of the random strings. * @param str_count number of generated random strings. * * @return 0 on success, non 0 otherwise. */ int test_random (unsigned int rx_length, unsigned int max_str_len, unsigned int str_count) { unsigned int i; char *rand_rx; char *matching_str; int eval; int eval_check; int eval_canonical; int eval_canonical_check; struct REGEX_INTERNAL_Automaton *dfa; regex_t rx; regmatch_t matchptr[1]; char error[200]; int result; char *canonical_regex = NULL; /* At least one string is needed for matching */ GNUNET_assert (str_count > 0); /* The string should be at least as long as the regex itself */ GNUNET_assert (max_str_len >= rx_length); /* Generate random regex and a string that matches the regex */ matching_str = GNUNET_malloc (rx_length + 1); rand_rx = REGEX_TEST_generate_random_regex (rx_length, matching_str); /* Now match */ result = 0; for (i = 0; i < str_count; i++) { if (0 < i) { matching_str = REGEX_TEST_generate_random_string (max_str_len); } /* Match string using DFA */ dfa = REGEX_INTERNAL_construct_dfa (rand_rx, strlen (rand_rx), 0); if (NULL == dfa) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Constructing DFA failed\n"); goto error; } eval = REGEX_INTERNAL_eval (dfa, matching_str); /* save the canonical regex for later comparison */ canonical_regex = GNUNET_strdup (REGEX_INTERNAL_get_canonical_regex (dfa)); REGEX_INTERNAL_automaton_destroy (dfa); /* Match string using glibc regex */ if (0 != regcomp (&rx, rand_rx, REG_EXTENDED)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not compile regex using regcomp: %s\n", rand_rx); goto error; } eval_check = regexec (&rx, matching_str, 1, matchptr, 0); regfree (&rx); /* We only want to match the whole string, because that's what our DFA does, * too. */ if (eval_check == 0 && (matchptr[0].rm_so != 0 || matchptr[0].rm_eo != strlen (matching_str))) eval_check = 1; /* Match canonical regex */ dfa = REGEX_INTERNAL_construct_dfa (canonical_regex, strlen (canonical_regex), 0); if (NULL == dfa) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Constructing DFA failed\n"); goto error; } eval_canonical = REGEX_INTERNAL_eval (dfa, matching_str); REGEX_INTERNAL_automaton_destroy (dfa); if (0 != regcomp (&rx, canonical_regex, REG_EXTENDED)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not compile regex using regcomp: %s\n", canonical_regex); goto error; } eval_canonical_check = regexec (&rx, matching_str, 1, matchptr, 0); regfree (&rx); /* We only want to match the whole string, because that's what our DFA does, * too. */ if (eval_canonical_check == 0 && (matchptr[0].rm_so != 0 || matchptr[0].rm_eo != strlen (matching_str))) eval_canonical_check = 1; /* compare results */ if (eval_check != eval || eval_canonical != eval_canonical_check) { regerror (eval_check, &rx, error, sizeof error); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected result:\nregex: %s\ncanonical_regex: %s\n\ string: %s\ngnunet regex: %i\nglibc regex: %i\n\ canonical regex: %i\ncanonical regex glibc: %i\n\ glibc error: %s\n\n", rand_rx, canonical_regex, matching_str, eval, eval_check, eval_canonical, eval_canonical_check, error); result += 1; } GNUNET_free (canonical_regex); GNUNET_free (matching_str); canonical_regex = NULL; matching_str = NULL; } GNUNET_free (rand_rx); return result; error: GNUNET_free_non_null (matching_str); GNUNET_free_non_null (rand_rx); GNUNET_free_non_null (canonical_regex); return -1; } /** * Automaton test that compares the result of matching regular expression 'rx' * with the strings and expected results in 'rxstr' with the result of matching * the same strings with glibc regex. * * @param a automaton. * @param rx compiled glibc regex. * @param rxstr regular expression and strings with expected results to * match against. * * @return 0 on successfull, non 0 otherwise */ int test_automaton (struct REGEX_INTERNAL_Automaton *a, regex_t * rx, struct Regex_String_Pair *rxstr) { int result; int eval; int eval_check; char error[200]; regmatch_t matchptr[1]; int i; if (NULL == a) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Automaton was NULL\n"); return 1; } result = 0; for (i = 0; i < rxstr->string_count; i++) { eval = REGEX_INTERNAL_eval (a, rxstr->strings[i]); eval_check = regexec (rx, rxstr->strings[i], 1, matchptr, 0); /* We only want to match the whole string, because that's what our DFA does, * too. */ if (eval_check == 0 && (matchptr[0].rm_so != 0 || matchptr[0].rm_eo != strlen (rxstr->strings[i]))) eval_check = 1; if ((rxstr->expected_results[i] == match && (0 != eval || 0 != eval_check)) || (rxstr->expected_results[i] == nomatch && (0 == eval || 0 == eval_check))) { result = 1; regerror (eval_check, rx, error, sizeof error); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected result:\nregex: %s\ncanonical_regex: %s\n" "string: %s\nexpected result: %i\n" "gnunet regex: %i\nglibc regex: %i\nglibc error: %s\n" "rm_so: %i\nrm_eo: %i\n\n", rxstr->regex, REGEX_INTERNAL_get_canonical_regex (a), rxstr->strings[i], rxstr->expected_results[i], eval, eval_check, error, matchptr[0].rm_so, matchptr[0].rm_eo); } } return result; } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-regex", "WARNING", NULL); struct REGEX_INTERNAL_Automaton *a; regex_t rx; int i; int check_nfa; int check_dfa; int check_rand; char *check_proof; struct Regex_String_Pair rxstr[19] = { {"ab?(abcd)?", 5, {"ababcd", "abab", "aabcd", "a", "abb"}, {match, nomatch, match, match, nomatch}}, {"ab(c|d)+c*(a(b|c)d)+", 5, {"abcdcdcdcdddddabd", "abcd", "abcddddddccccccccccccccccccccccccabdacdabd", "abccccca", "abcdcdcdccdabdabd"}, {match, nomatch, match, nomatch, match}}, {"ab+c*(a(bx|c)d)+", 5, {"abcdcdcdcdddddabd", "abcd", "abcddddddccccccccccccccccccccccccabdacdabd", "abccccca", "abcdcdcdccdabdabd"}, {nomatch, nomatch, nomatch, nomatch, nomatch}}, {"a+X*y+c|p|R|Z*K*y*R+w|Y*6+n+h*k*w+V*F|W*B*e*", 1, {"kaXycQepRZKyRwY6nhkwVFWBegNVtLPj39XhJJ6bEifRSZRYZg"}, {nomatch}}, {"k|a+X*y+c|Q*e|p|R|Z*K*y*R+w|Y*6+n+h*k*w+V*F|W*B*e*g|N+V|t+L|P*j*3*9+X*h*J|J*6|b|E*i*f*R+S|Z|R|Y*Z|g*", 1, {"kaXycQepRZKyRwY6nhkwVFWBegNVtLPj39XhJJ6bEifRSZRYZg"}, {nomatch}}, {"F?W+m+2*6*c*s|P?U?a|B|y*i+t+A|V|6*C*7*e?Z*n*i|J?5+g?W*V?7*j?p?1|r?B?C+E+3+6*i+W*P?K?0|D+7?y*m+3?g?K?", 1, {"osfjsodfonONONOnosndfsdnfsd"}, {nomatch}}, {"V|M*o?x*p*d+h+b|E*m?h?Y*E*O?W*W*P+o?Z+H*M|I*q+C*a+5?5*9|b?z|G*y*k?R|p+u|8*h?B+l*H|e|L*O|1|F?v*0?5|C+", 1, {"VMoxpdhbEmhYEOWWPoZHMIqCa559bzGykRpu8hBlHeLO1Fv05C"}, {nomatch}}, {"(bla)*", 8, {"", "bla", "blabla", "bl", "la", "b", "l", "a"}, {match, match, match, nomatch, nomatch, nomatch, nomatch, nomatch}}, {"ab(c|d)+c*(a(b|c)+d)+(bla)(bla)*", 8, {"ab", "abcabdbla", "abdcccccccccccabcbccdblablabla", "bl", "la", "b", "l", "a"}, {nomatch, match, match, nomatch, nomatch, nomatch, nomatch, nomatch}}, {"a|aa*a", 6, {"", "a", "aa", "aaa", "aaaa", "aaaaa"}, {nomatch, match, match, match, match, match}}, {"ab(c|d)+c*(a(b|c)+d)+(bla)+", 1, {"abcabdblaacdbla"}, {nomatch}}, {"(ac|b)+", 8, {"b", "bb", "ac", "", "acb", "bacbacac", "acacac", "abc"}, {match, match, match, nomatch, match, match, match, nomatch}}, {"(ab|c)+", 7, {"", "ab", "c", "abc", "ababcc", "acc", "abac"}, {nomatch, match, match, match, match, nomatch, nomatch}}, {"((j|2j)K|(j|2j)AK|(j|2j)(D|e|(j|2j)A(D|e))D*K)", 1, {"", "2j2jADK", "j2jADK"}, {nomatch, match, match}}, {"((j|2j)K|(j|2j)(D|e|((j|2j)j|(j|2j)2j)A(D|e))D*K|(j|2j)AK)", 2, {"", "2j2jjADK", "j2jADK"}, {nomatch, match, match}}, {"ab(c|d)+c*(a(b|c)d)+", 1, {"abacd"}, {nomatch}}, {"d|5kl", 1, {"d5kl"}, {nomatch}}, {"a()b", 1, {"ab"}, {match}}, {"GNVPN-0001-PAD(001110101001001010(0|1)*|001110101001001010000(0|1)*|001110101001001010001(0|1)*|001110101001001010010(0|1)*|001110101001001010011(0|1)*|001110101001001010100(0|1)*|001110101001001010101(0|1)*|001110101001001010110(0|1)*|001110101001001010111(0|1)*|0011101010110110(0|1)*|001110101011011000000(0|1)*|001110101011011000001(0|1)*|001110101011011000010(0|1)*|001110101011011000011(0|1)*|001110101011011000100(0|1)*|001110101011011000101(0|1)*|001110101011011000110(0|1)*|001110101011011000111(0|1)*|001110101011011001000(0|1)*|001110101011011001001(0|1)*|001110101011011001010(0|1)*|001110101011011001011(0|1)*|001110101011011001100(0|1)*|001110101011011001101(0|1)*|001110101011011001110(0|1)*|001110101011011001111(0|1)*|001110101011011010000(0|1)*|001110101011011010001(0|1)*|001110101011011010010(0|1)*|001110101011011010011(0|1)*|001110101011011010100(0|1)*|001110101011011010101(0|1)*|001110101011011010110(0|1)*|001110101011011010111(0|1)*|001110101011011011000(0|1)*|001110101011011011001(0|1)*|001110101011011011010(0|1)*|001110101011011011011(0|1)*|001110101011011011100(0|1)*|001110101011011011101(0|1)*|001110101011011011110(0|1)*|001110101011011011111(0|1)*|0011101110111101(0|1)*|001110111011110100000(0|1)*|001110111011110100001(0|1)*|001110111011110100010(0|1)*|001110111011110100011(0|1)*|001110111011110100100(0|1)*|001110111011110100101(0|1)*|001110111011110100110(0|1)*|001110111011110100111(0|1)*|001110111011110101000(0|1)*|001110111011110101001(0|1)*|001110111011110101010(0|1)*|001110111011110101011(0|1)*|001110111011110101100(0|1)*|001110111011110101101(0|1)*|001110111011110101110(0|1)*|001110111011110101111(0|1)*|001110111011110110000(0|1)*|001110111011110110001(0|1)*|001110111011110110010(0|1)*|001110111011110110011(0|1)*|001110111011110110100(0|1)*|001110111011110110101(0|1)*|001110111011110110110(0|1)*|001110111011110110111(0|1)*|001110111011110111000(0|1)*|001110111011110111001(0|1)*|001110111011110111010(0|1)*|001110111011110111011(0|1)*|001110111011110111100(0|1)*|001110111011110111101(0|1)*|001110111011110111110(0|1)*|0111010001010110(0|1)*|011101000101011000000(0|1)*|011101000101011000001(0|1)*|011101000101011000010(0|1)*|011101000101011000011(0|1)*|011101000101011000100(0|1)*|011101000101011000101(0|1)*|011101000101011000110(0|1)*|011101000101011000111(0|1)*|011101000101011001000(0|1)*|011101000101011001001(0|1)*|011101000101011001010(0|1)*|011101000101011001011(0|1)*|011101000101011001100(0|1)*|011101000101011001101(0|1)*|011101000101011001110(0|1)*|011101000101011001111(0|1)*|011101000101011010000(0|1)*|011101000101011010001(0|1)*|011101000101011010010(0|1)*|011101000101011010011(0|1)*|011101000101011010100(0|1)*|011101000101011010101(0|1)*|011101000101011010110(0|1)*|011101000101011010111(0|1)*|011101000101011011000(0|1)*|011101000101011011001(0|1)*|011101000101011011010(0|1)*|011101000101011011011(0|1)*|011101000101011011100(0|1)*|011101000101011011101(0|1)*|011101000101011011110(0|1)*|011101000101011011111(0|1)*|0111010001010111(0|1)*|011101000101011100000(0|1)*|011101000101011100001(0|1)*|011101000101011100010(0|1)*|011101000101011100011(0|1)*|011101000101011100100(0|1)*|011101000101011100101(0|1)*|011101000101011100110(0|1)*|011101000101011100111(0|1)*|011101000101011101000(0|1)*|011101000101011101001(0|1)*|011101000101011101010(0|1)*|011101000101011101011(0|1)*|011101000101011101100(0|1)*|011101000101011101101(0|1)*|011101000101011101110(0|1)*|011101000101011101111(0|1)*|011101000101011110000(0|1)*|011101000101011110001(0|1)*|011101000101011110010(0|1)*|011101000101011110011(0|1)*|011101000101011110100(0|1)*|011101000101011110101(0|1)*|011101000101011110110(0|1)*|011101000101011110111(0|1)*|011101000101011111000(0|1)*|011101000101011111001(0|1)*|011101000101011111010(0|1)*|011101000101011111011(0|1)*|011101000101011111100(0|1)*|011101000101011111101(0|1)*|011101000101011111110(0|1)*|011101000101011111111(0|1)*|0111010001011000(0|1)*|011101000101100000000(0|1)*|011101000101100000001(0|1)*|011101000101100000010(0|1)*|011101000101100000011(0|1)*|011101000101100000100(0|1)*|011101000101100000101(0|1)*|011101000101100000110(0|1)*|011101000101100000111(0|1)*|011101000101100001000(0|1)*|011101000101100001001(0|1)*|011101000101100001010(0|1)*|011101000101100001011(0|1)*|011101000101100001100(0|1)*|011101000101100001101(0|1)*|011101000101100001110(0|1)*|011101000101100001111(0|1)*|011101000101100010000(0|1)*|011101000101100010001(0|1)*|011101000101100010010(0|1)*|011101000101100010011(0|1)*|011101000101100010100(0|1)*|011101000101100010101(0|1)*|011101000101100010110(0|1)*|011101000101100010111(0|1)*|011101000101100011000(0|1)*|011101000101100011001(0|1)*|011101000101100011010(0|1)*|011101000101100011011(0|1)*|011101000101100011100(0|1)*|011101000101100011101(0|1)*|011101000101100011110(0|1)*|011101000101100011111(0|1)*|01110100010110010(0|1)*|011101000101100100000(0|1)*|011101000101100100001(0|1)*|011101000101100100010(0|1)*|011101000101100100011(0|1)*|011101000101100100100(0|1)*|011101000101100100101(0|1)*|011101000101100100110(0|1)*|011101000101100100111(0|1)*|011101000101100101000(0|1)*|011101000101100101001(0|1)*|011101000101100101010(0|1)*|011101000101100101011(0|1)*|011101000101100101100(0|1)*|011101000101100101101(0|1)*|011101000101100101110(0|1)*|011101000101100101111(0|1)*|011101000101100101111000(0|1)*|1100101010011100(0|1)*|110010101001110000000(0|1)*|110010101001110000000001(0|1)*|110010101001110000000010(0|1)*|110010101001110000000110(0|1)*|110010101001110000001(0|1)*|110010101001110000001000(0|1)*|110010101001110000001001(0|1)*|110010101001110000001010(0|1)*|110010101001110000001011(0|1)*|110010101001110000001101(0|1)*|110010101001110000001110(0|1)*|110010101001110000010(0|1)*|110010101001110000011(0|1)*|110010101001110000100(0|1)*|110010101001110000101(0|1)*|110010101001110000110(0|1)*|110010101001110000111(0|1)*|110010101001110001000(0|1)*|110010101001110001001(0|1)*|110010101001110001010(0|1)*|110010101001110001011(0|1)*|110010101001110001100(0|1)*|110010101001110001101(0|1)*|110010101001110001110(0|1)*|110010101001110001111(0|1)*|110010101001110010000(0|1)*|110010101001110010001(0|1)*|110010101001110010010(0|1)*|110010101001110010011(0|1)*|110010101001110010100(0|1)*|110010101001110010101(0|1)*|110010101001110010110(0|1)*|110010101001110010111(0|1)*|110010101001110011000(0|1)*|110010101001110011001(0|1)*|110010101001110011010(0|1)*|110010101001110011011(0|1)*|110010101001110011100(0|1)*|110010101001110011101(0|1)*|110010101001110011110(0|1)*|110010101001110011111(0|1)*|1101101010111010(0|1)*|110110101011101000000(0|1)*|110110101011101000000001(0|1)*|110110101011101000001000(0|1)*|110110101011101000001001(0|1)*|110110101011101000001010(0|1)*|110110101011101000001011(0|1)*|110110101011101000001100(0|1)*|110110101011101000001110(0|1)*|110110101011101000001111(0|1)*|110110101011101000010(0|1)*|110110101011101000010000(0|1)*|110110101011101000010001(0|1)*|110110101011101000010010(0|1)*|110110101011101000010011(0|1)*|110110101011101000011(0|1)*|110110101011101000100(0|1)*|110110101011101000101(0|1)*|110110101011101000110(0|1)*|110110101011101000111(0|1)*|110110101011101001000(0|1)*|110110101011101001001(0|1)*|110110101011101001010(0|1)*|110110101011101001011(0|1)*|110110101011101001100(0|1)*|110110101011101001101(0|1)*|110110101011101001110(0|1)*|110110101011101001111(0|1)*|110110101011101010000(0|1)*|110110101011101010001(0|1)*|110110101011101010010(0|1)*|110110101011101010011(0|1)*|110110101011101010100(0|1)*|110110101011101010101(0|1)*|110110101011101010110(0|1)*|110110101011101010111(0|1)*|110110101011101011000(0|1)*|110110101011101011001(0|1)*|110110101011101011010(0|1)*|110110101011101011011(0|1)*|110110101011101011100(0|1)*|110110101011101011101(0|1)*|110110101011101011110(0|1)*|110110101011101011111(0|1)*|1101101011010100(0|1)*|110110101101010000000(0|1)*|110110101101010000001(0|1)*|110110101101010000010(0|1)*|110110101101010000011(0|1)*|110110101101010000100(0|1)*|110110101101010000101(0|1)*|110110101101010000110(0|1)*|110110101101010000111(0|1)*|110110101101010001000(0|1)*|110110101101010001001(0|1)*|110110101101010001010(0|1)*|110110101101010001011(0|1)*|110110101101010001100(0|1)*|110110101101010001101(0|1)*|110110101101010001110(0|1)*|110110101101010001111(0|1)*|110110101101010010000(0|1)*|110110101101010010001(0|1)*|110110101101010010010(0|1)*|110110101101010010011(0|1)*|110110101101010010100(0|1)*|1101101011010100101000(0|1)*|110110101101010010101(0|1)*|110110101101010010110(0|1)*|110110101101010010111(0|1)*|110110101101010011000(0|1)*|110110101101010011010(0|1)*|110110101101010011011(0|1)*|110110101101010011100(0|1)*|110110101101010011101(0|1)*|110110101101010011110(0|1)*|110110101101010011111(0|1)*|1101111010100100(0|1)*|110111101010010000000(0|1)*|110111101010010000001(0|1)*|110111101010010000010(0|1)*|110111101010010000011(0|1)*|110111101010010000100(0|1)*|110111101010010000101(0|1)*|110111101010010000110(0|1)*|110111101010010000111(0|1)*|110111101010010001000(0|1)*|110111101010010001001(0|1)*|110111101010010001010(0|1)*|110111101010010001011(0|1)*|110111101010010001100(0|1)*|110111101010010001101(0|1)*|110111101010010001110(0|1)*|110111101010010001111(0|1)*|110111101010010010000(0|1)*|110111101010010010001(0|1)*|110111101010010010010(0|1)*|110111101010010010011(0|1)*|110111101010010010100(0|1)*|110111101010010010101(0|1)*|110111101010010010110(0|1)*|110111101010010010111(0|1)*|110111101010010011000(0|1)*|110111101010010011001(0|1)*|110111101010010011010(0|1)*|110111101010010011011(0|1)*|110111101010010011100(0|1)*|110111101010010011101(0|1)*|110111101010010011110(0|1)*|110111101010010011111(0|1)*|11011110101001010(0|1)*|110111101010010100000(0|1)*|110111101010010100001(0|1)*|110111101010010100010(0|1)*|110111101010010100011(0|1)*|110111101010010100100(0|1)*|110111101010010100101(0|1)*|110111101010010100110(0|1)*|110111101010010100111(0|1)*|110111101010010101000(0|1)*|110111101010010101001(0|1)*|110111101010010101010(0|1)*|110111101010010101011(0|1)*|110111101010010101100(0|1)*|110111101010010101101(0|1)*|110111101010010101110(0|1)*|110111101010010101111(0|1)*)", 2, {"GNVPN-0001-PAD1101111010100101011101010101010101", "GNVPN-0001-PAD11001010100111000101101010101"}, {match, match}} }; check_nfa = 0; check_dfa = 0; check_rand = 0; for (i = 0; i < 19; i++) { if (0 != regcomp (&rx, rxstr[i].regex, REG_EXTENDED)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not compile regex using regcomp()\n"); return 1; } /* NFA test */ a = REGEX_INTERNAL_construct_nfa (rxstr[i].regex, strlen (rxstr[i].regex)); check_nfa += test_automaton (a, &rx, &rxstr[i]); REGEX_INTERNAL_automaton_destroy (a); /* DFA test */ a = REGEX_INTERNAL_construct_dfa (rxstr[i].regex, strlen (rxstr[i].regex), 0); check_dfa += test_automaton (a, &rx, &rxstr[i]); check_proof = GNUNET_strdup (REGEX_INTERNAL_get_canonical_regex (a)); REGEX_INTERNAL_automaton_destroy (a); a = REGEX_INTERNAL_construct_dfa (check_proof, strlen (check_proof), 0); check_dfa += test_automaton (a, &rx, &rxstr[i]); REGEX_INTERNAL_automaton_destroy (a); if (0 != check_dfa) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "check_proof: %s\n", check_proof); GNUNET_free_non_null (check_proof); regfree (&rx); } /* Random tests */ srand (time (NULL)); for (i = 0; i < 20; i++) check_rand += test_random (50, 60, 10); return check_nfa + check_dfa + check_rand; } gnunet-0.10.1/src/regex/regex.conf.in0000644000175000017500000000032012250373167014302 00000000000000[regex] AUTOSTART = @AUTOSTART@ @UNIXONLY@ PORT = 2107 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-regex.sock HOSTNAME = localhost BINARY = gnunet-service-regex ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; gnunet-0.10.1/src/regex/test_regex_iterate_api.c0000644000175000017500000001773512225777501016623 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/test_regex_iterate_api.c * @brief test for regex.c * @author Maximilian Szengel */ #include #include #include "platform.h" #include "regex_internal_lib.h" #include "regex_block_lib.h" #include "regex_internal.h" /** * Regex initial padding. */ #define INITIAL_PADDING "PADPADPADPADPADP" /** * Set to GNUNET_YES to save a debug graph. */ #define REGEX_INTERNAL_ITERATE_SAVE_DEBUG_GRAPH GNUNET_NO static unsigned int transition_counter; struct IteratorContext { int error; int should_save_graph; FILE *graph_filep; unsigned int string_count; char *const *strings; unsigned int match_count; }; struct RegexStringPair { char *regex; unsigned int string_count; char *strings[20]; }; static void key_iterator (void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges) { unsigned int i; struct IteratorContext *ctx = cls; char *out_str; char *state_id = GNUNET_strdup (GNUNET_h2s (key)); GNUNET_assert (NULL != proof); if (GNUNET_YES == ctx->should_save_graph) { if (GNUNET_YES == accepting) GNUNET_asprintf (&out_str, "\"%s\" [shape=doublecircle]\n", state_id); else GNUNET_asprintf (&out_str, "\"%s\" [shape=circle]\n", state_id); fwrite (out_str, strlen (out_str), 1, ctx->graph_filep); GNUNET_free (out_str); for (i = 0; i < num_edges; i++) { transition_counter++; GNUNET_asprintf (&out_str, "\"%s\" -> \"%s\" [label = \"%s (%s)\"]\n", state_id, GNUNET_h2s (&edges[i].destination), edges[i].label, proof); fwrite (out_str, strlen (out_str), 1, ctx->graph_filep); GNUNET_free (out_str); } } else { for (i = 0; i < num_edges; i++) transition_counter++; } for (i = 0; i < ctx->string_count; i++) { if (0 == strcmp (proof, ctx->strings[i])) ctx->match_count++; } if (GNUNET_OK != REGEX_BLOCK_check_proof (proof, strlen (proof), key)) { ctx->error++; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Proof check failed: proof: %s key: %s\n", proof, state_id); } GNUNET_free (state_id); } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-regex", "WARNING", NULL); int error; struct REGEX_INTERNAL_Automaton *dfa; unsigned int i; unsigned int num_transitions; char *filename = NULL; struct IteratorContext ctx = { 0, 0, NULL, 0, NULL, 0 }; error = 0; const struct RegexStringPair rxstr[13] = { {INITIAL_PADDING "ab(c|d)+c*(a(b|c)+d)+(bla)+", 2, {INITIAL_PADDING "abcdcdca", INITIAL_PADDING "abcabdbl"}}, {INITIAL_PADDING "abcdefghixxxxxxxxxxxxxjklmnop*qstoisdjfguisdfguihsdfgbdsuivggsd", 1, {INITIAL_PADDING "abcdefgh"}}, {INITIAL_PADDING "VPN-4-1(0|1)*", 2, {INITIAL_PADDING "VPN-4-10", INITIAL_PADDING "VPN-4-11"}}, {INITIAL_PADDING "(a+X*y+c|p|R|Z*K*y*R+w|Y*6+n+h*k*w+V*F|W*B*e*)", 2, {INITIAL_PADDING "aaaaaaaa", INITIAL_PADDING "aaXXyyyc"}}, {INITIAL_PADDING "a*", 1, {INITIAL_PADDING "aaaaaaaa"}}, {INITIAL_PADDING "xzxzxzxzxz", 1, {INITIAL_PADDING "xzxzxzxz"}}, {INITIAL_PADDING "xyz*", 1, {INITIAL_PADDING "xyzzzzzz"}}, {INITIAL_PADDING "abcd:(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1):(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)(0|1)", 2, {INITIAL_PADDING "abcd:000", INITIAL_PADDING "abcd:101"}}, {INITIAL_PADDING "(x*|(0|1|2)(a|b|c|d)+)", 2, {INITIAL_PADDING "xxxxxxxx", INITIAL_PADDING "0abcdbad"}}, {INITIAL_PADDING "(0|1)(0|1)23456789ABC", 1, {INITIAL_PADDING "11234567"}}, {INITIAL_PADDING "0*123456789ABC*", 3, {INITIAL_PADDING "00123456", INITIAL_PADDING "00000000", INITIAL_PADDING "12345678"}}, {INITIAL_PADDING "0123456789A*BC", 1, {INITIAL_PADDING "01234567"}}, {"GNUNETVPN000100000IPEX6-fc5a:4e1:c2ba::1", 1, {"GNUNETVPN000100000IPEX6-"}} }; const char *graph_start_str = "digraph G {\nrankdir=LR\n"; const char *graph_end_str = "\n}\n"; for (i = 0; i < 13; i++) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iterating DFA for regex %s\n", rxstr[i].regex); /* Create graph */ if (GNUNET_YES == REGEX_INTERNAL_ITERATE_SAVE_DEBUG_GRAPH) { GNUNET_asprintf (&filename, "iteration_graph_%u.dot", i); ctx.graph_filep = fopen (filename, "w"); if (NULL == ctx.graph_filep) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not open file %s for saving iteration graph.\n", filename); ctx.should_save_graph = GNUNET_NO; } else { ctx.should_save_graph = GNUNET_YES; fwrite (graph_start_str, strlen (graph_start_str), 1, ctx.graph_filep); } GNUNET_free (filename); } else { ctx.should_save_graph = GNUNET_NO; ctx.graph_filep = NULL; } /* Iterate over DFA edges */ transition_counter = 0; ctx.string_count = rxstr[i].string_count; ctx.strings = rxstr[i].strings; ctx.match_count = 0; dfa = REGEX_INTERNAL_construct_dfa (rxstr[i].regex, strlen (rxstr[i].regex), 0); REGEX_INTERNAL_iterate_all_edges (dfa, key_iterator, &ctx); num_transitions = REGEX_INTERNAL_get_transition_count (dfa) - dfa->start->transition_count; if (transition_counter < num_transitions) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Automaton has %d transitions, iterated over %d transitions\n", num_transitions, transition_counter); error += 1; } if (ctx.match_count < ctx.string_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing initial states for regex %s\n", rxstr[i].regex); error += (ctx.string_count - ctx.match_count); } else if (ctx.match_count > ctx.string_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Duplicate initial transitions for regex %s\n", rxstr[i].regex); error += (ctx.string_count - ctx.match_count); } REGEX_INTERNAL_automaton_destroy (dfa); /* Finish graph */ if (GNUNET_YES == ctx.should_save_graph) { fwrite (graph_end_str, strlen (graph_end_str), 1, ctx.graph_filep); fclose (ctx.graph_filep); ctx.graph_filep = NULL; ctx.should_save_graph = GNUNET_NO; } } for (i = 0; i < 13; i++) { ctx.string_count = rxstr[i].string_count; ctx.strings = rxstr[i].strings; ctx.match_count = 0; dfa = REGEX_INTERNAL_construct_dfa (rxstr[i].regex, strlen (rxstr[i].regex), 0); REGEX_INTERNAL_dfa_add_multi_strides (NULL, dfa, 2); REGEX_INTERNAL_iterate_all_edges (dfa, key_iterator, &ctx); if (ctx.match_count < ctx.string_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing initial states for regex %s\n", rxstr[i].regex); error += (ctx.string_count - ctx.match_count); } REGEX_INTERNAL_automaton_destroy (dfa); } error += ctx.error; return error; } gnunet-0.10.1/src/regex/regex_block_lib.h0000644000175000017500000001233212225777503015211 00000000000000/* This file is part of GNUnet. (C) 2012,2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Bartlomiej Polot * @file regex/regex_block_lib.h * @brief common function to manipulate blocks stored by regex in the DHT */ #ifndef REGEX_BLOCK_LIB_H_ #define REGEX_BLOCK_LIB_H_ #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "block_regex.h" /** * Representation of a Regex node (and edges) in the DHT. */ struct RegexBlock; /** * Edge representation. */ struct REGEX_BLOCK_Edge { /** * Label of the edge. FIXME: might want to not consume exactly multiples of 8 bits, need length! */ const char *label; /** * Destionation of the edge. */ struct GNUNET_HashCode destination; }; /** * Check if the given 'proof' matches the given 'key'. * * @param proof partial regex of a state * @param proof_len number of bytes in 'proof' * @param key hash of a state. * * @return GNUNET_OK if the proof is valid for the given key. */ int REGEX_BLOCK_check_proof (const char *proof, size_t proof_len, const struct GNUNET_HashCode *key); /** * Check if the regex block is well formed, including all edges. * * @param block The start of the block. * @param size The size of the block. * @param query the query for the block * @param xquery String describing the edge we are looking for. * Can be NULL in case this is a put block. * * @return GNUNET_OK in case it's fine. * GNUNET_NO in case the xquery exists and is not found (IRRELEVANT). * GNUNET_SYSERR if the block is invalid. */ int REGEX_BLOCK_check (const struct RegexBlock *block, size_t size, const struct GNUNET_HashCode *query, const char *xquery); /* FIXME: might want to use 'struct REGEX_BLOCK_Edge' here instead of 3 arguments! */ /** * Iterator over edges in a block. * * @param cls Closure. * @param token Token that follows to next state. * @param len Length of token. * @param key Hash of next state. * * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. */ typedef int (*REGEX_INTERNAL_EgdeIterator)(void *cls, const char *token, size_t len, const struct GNUNET_HashCode *key); /** * Iterate over all edges of a block of a regex state. * * @param block Block to iterate over. * @param size Size of block. * @param iterator Function to call on each edge in the block. * @param iter_cls Closure for the iterator. * * @return GNUNET_SYSERR if an error has been encountered. * GNUNET_OK if no error has been encountered. * Note that if the iterator stops the iteration by returning * GNUNET_NO, the block will no longer be checked for further errors. * The return value will be GNUNET_OK meaning that no errors were * found until the edge last notified to the iterator, but there might * be errors in further edges. */ int REGEX_BLOCK_iterate (const struct RegexBlock *block, size_t size, REGEX_INTERNAL_EgdeIterator iterator, void *iter_cls); /** * Obtain the key that a particular block is to be stored under. * * @param block block to get the key from * @param block_len number of bytes in block * @param key where to store the key * @return GNUNET_OK on success, GNUNET_SYSERR if the block is malformed */ int REGEX_BLOCK_get_key (const struct RegexBlock *block, size_t block_len, struct GNUNET_HashCode *key); /** * Test if this block is marked as being an accept state. * * @param block block to test * @param size number of bytes in block * @return GNUNET_YES if the block is accepting, GNUNET_NO if not */ int GNUNET_BLOCK_is_accepting (const struct RegexBlock *block, size_t block_len); /** * Construct a regex block to be stored in the DHT. * * @param proof proof string for the block * @param num_edges number of edges in the block * @param edges the edges of the block * @param accepting is this an accepting state * @param rsize set to the size of the returned block (OUT-only) * @return the regex block, NULL on error */ struct RegexBlock * REGEX_BLOCK_create (const char *proof, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges, int accepting, size_t *rsize); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef REGEX_BLOCK_LIB_H */ #endif /* end of regex_block_lib.h */ gnunet-0.10.1/src/regex/Makefile.in0000644000175000017500000016506512320755626014005 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-regex$(EXEEXT) \ gnunet-daemon-regexprofiler$(EXEEXT) @HAVE_TESTING_TRUE@noinst_PROGRAMS = $(am__EXEEXT_1) \ @HAVE_TESTING_TRUE@ perf-regex$(EXEEXT) \ @HAVE_TESTING_TRUE@ gnunet-regex-profiler$(EXEEXT) check_PROGRAMS = test_regex_eval_api$(EXEEXT) \ test_regex_iterate_api$(EXEEXT) test_regex_proofs$(EXEEXT) \ test_regex_graph_api$(EXEEXT) test_regex_api$(EXEEXT) subdir = src/regex DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/regex.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = regex.conf CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = libgnunetregex_internal_a_AR = $(AR) $(ARFLAGS) libgnunetregex_internal_a_LIBADD = am_libgnunetregex_internal_a_OBJECTS = regex_internal.$(OBJEXT) \ regex_internal_dht.$(OBJEXT) libgnunetregex_internal_a_OBJECTS = \ $(am_libgnunetregex_internal_a_OBJECTS) libgnunetregextest_a_AR = $(AR) $(ARFLAGS) am_libgnunetregextest_a_OBJECTS = regex_test_lib.$(OBJEXT) \ regex_test_graph.$(OBJEXT) regex_test_random.$(OBJEXT) libgnunetregextest_a_OBJECTS = $(am_libgnunetregextest_a_OBJECTS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am_libgnunet_plugin_block_regex_la_OBJECTS = plugin_block_regex.lo libgnunet_plugin_block_regex_la_OBJECTS = \ $(am_libgnunet_plugin_block_regex_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_block_regex_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_block_regex_la_LDFLAGS) $(LDFLAGS) -o $@ libgnunetregex_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetregex_la_OBJECTS = regex_api.lo libgnunetregex_la_OBJECTS = $(am_libgnunetregex_la_OBJECTS) libgnunetregex_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetregex_la_LDFLAGS) $(LDFLAGS) \ -o $@ am__DEPENDENCIES_1 = libgnunetregexblock_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetregexblock_la_OBJECTS = regex_block_lib.lo libgnunetregexblock_la_OBJECTS = $(am_libgnunetregexblock_la_OBJECTS) libgnunetregexblock_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetregexblock_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_MYSQL_TRUE@am__EXEEXT_1 = \ @HAVE_MYSQL_TRUE@ gnunet-regex-simulation-profiler$(EXEEXT) PROGRAMS = $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_daemon_regexprofiler_OBJECTS = \ gnunet-daemon-regexprofiler.$(OBJEXT) gnunet_daemon_regexprofiler_OBJECTS = \ $(am_gnunet_daemon_regexprofiler_OBJECTS) am_gnunet_regex_profiler_OBJECTS = gnunet-regex-profiler.$(OBJEXT) gnunet_regex_profiler_OBJECTS = $(am_gnunet_regex_profiler_OBJECTS) am__gnunet_regex_simulation_profiler_SOURCES_DIST = \ gnunet-regex-simulation-profiler.c @HAVE_MYSQL_TRUE@am_gnunet_regex_simulation_profiler_OBJECTS = \ @HAVE_MYSQL_TRUE@ gnunet-regex-simulation-profiler.$(OBJEXT) gnunet_regex_simulation_profiler_OBJECTS = \ $(am_gnunet_regex_simulation_profiler_OBJECTS) am_gnunet_service_regex_OBJECTS = gnunet-service-regex.$(OBJEXT) gnunet_service_regex_OBJECTS = $(am_gnunet_service_regex_OBJECTS) am_perf_regex_OBJECTS = perf-regex.$(OBJEXT) perf_regex_OBJECTS = $(am_perf_regex_OBJECTS) am_test_regex_api_OBJECTS = test_regex_api.$(OBJEXT) test_regex_api_OBJECTS = $(am_test_regex_api_OBJECTS) test_regex_api_DEPENDENCIES = \ $(top_builddir)/src/regex/libgnunetregex.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_regex_eval_api_OBJECTS = test_regex_eval_api.$(OBJEXT) test_regex_eval_api_OBJECTS = $(am_test_regex_eval_api_OBJECTS) test_regex_eval_api_DEPENDENCIES = \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_regex_graph_api_OBJECTS = test_regex_graph_api.$(OBJEXT) test_regex_graph_api_OBJECTS = $(am_test_regex_graph_api_OBJECTS) test_regex_graph_api_DEPENDENCIES = \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_regex_iterate_api_OBJECTS = test_regex_iterate_api.$(OBJEXT) test_regex_iterate_api_OBJECTS = $(am_test_regex_iterate_api_OBJECTS) test_regex_iterate_api_DEPENDENCIES = \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_regex_proofs_OBJECTS = test_regex_proofs.$(OBJEXT) test_regex_proofs_OBJECTS = $(am_test_regex_proofs_OBJECTS) test_regex_proofs_DEPENDENCIES = \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetregex_internal_a_SOURCES) \ $(libgnunetregextest_a_SOURCES) \ $(libgnunet_plugin_block_regex_la_SOURCES) \ $(libgnunetregex_la_SOURCES) $(libgnunetregexblock_la_SOURCES) \ $(gnunet_daemon_regexprofiler_SOURCES) \ $(gnunet_regex_profiler_SOURCES) \ $(gnunet_regex_simulation_profiler_SOURCES) \ $(gnunet_service_regex_SOURCES) $(perf_regex_SOURCES) \ $(test_regex_api_SOURCES) $(test_regex_eval_api_SOURCES) \ $(test_regex_graph_api_SOURCES) \ $(test_regex_iterate_api_SOURCES) $(test_regex_proofs_SOURCES) DIST_SOURCES = $(libgnunetregex_internal_a_SOURCES) \ $(libgnunetregextest_a_SOURCES) \ $(libgnunet_plugin_block_regex_la_SOURCES) \ $(libgnunetregex_la_SOURCES) $(libgnunetregexblock_la_SOURCES) \ $(gnunet_daemon_regexprofiler_SOURCES) \ $(gnunet_regex_profiler_SOURCES) \ $(am__gnunet_regex_simulation_profiler_SOURCES_DIST) \ $(gnunet_service_regex_SOURCES) $(perf_regex_SOURCES) \ $(test_regex_api_SOURCES) $(test_regex_eval_api_SOURCES) \ $(test_regex_graph_api_SOURCES) \ $(test_regex_iterate_api_SOURCES) $(test_regex_proofs_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage pkgcfgdir = $(pkgdatadir)/config.d/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ regex.conf gnunet_service_regex_SOURCES = \ gnunet-service-regex.c gnunet_service_regex_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_regex_DEPENDENCIES = \ libgnunetregex_internal.a noinst_LIBRARIES = \ libgnunetregex_internal.a \ libgnunetregextest.a lib_LTLIBRARIES = \ libgnunetregexblock.la \ libgnunetregex.la libgnunetregexblock_la_SOURCES = \ regex_block_lib.c regex_block_lib.h libgnunetregexblock_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) \ $(LTLIBINTL) libgnunetregexblock_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:0:0 libgnunetregex_internal_a_SOURCES = \ regex_internal_lib.h \ regex_internal.h regex_internal.c \ regex_internal_dht.c libgnunetregex_internal_a_DEPENDENCIES = \ libgnunetregexblock.la libgnunetregex_la_SOURCES = \ regex_api.c regex_ipc.h libgnunetregex_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetregex_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 3:1:0 plugin_LTLIBRARIES = \ libgnunet_plugin_block_regex.la libgnunet_plugin_block_regex_la_SOURCES = \ plugin_block_regex.c libgnunet_plugin_block_regex_la_LIBADD = \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_block_regex_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_regex_la_DEPENDENCIES = \ libgnunetregexblock.la @HAVE_MYSQL_TRUE@noinst_mysql_progs = \ @HAVE_MYSQL_TRUE@ gnunet-regex-simulation-profiler @HAVE_MYSQL_TRUE@gnunet_regex_simulation_profiler_SOURCES = \ @HAVE_MYSQL_TRUE@ gnunet-regex-simulation-profiler.c @HAVE_MYSQL_TRUE@gnunet_regex_simulation_profiler_LDADD = \ @HAVE_MYSQL_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_MYSQL_TRUE@ $(top_builddir)/src/regex/libgnunetregex_internal.a \ @HAVE_MYSQL_TRUE@ $(top_builddir)/src/dht/libgnunetdht.la \ @HAVE_MYSQL_TRUE@ $(top_builddir)/src/mysql/libgnunetmysql.la @HAVE_MYSQL_TRUE@gnunet_regex_simulation_profiler_DEPENDENCIES = \ @HAVE_MYSQL_TRUE@ libgnunetregex_internal.a libgnunetregextest_a_SOURCES = \ regex_test_lib.c regex_test_lib.h \ regex_test_graph.c \ regex_test_random.c libgnunetregextest_a_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/regex/libgnunetregex_internal.a libgnunetregextest_a_DEPENDENCIES = \ libgnunetregex_internal.a perf_regex_SOURCES = \ perf-regex.c perf_regex_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/util/libgnunetutil.la perf_regex_DEPENDENCIES = \ libgnunetregex_internal.a \ libgnunetregextest.a gnunet_regex_profiler_SOURCES = \ gnunet-regex-profiler.c gnunet_regex_profiler_LDADD = -lm \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_regex_profiler_DEPENDENCIES = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/dht/libgnunetdht.la \ libgnunetregex_internal.a \ libgnunetregextest.a gnunet_daemon_regexprofiler_SOURCES = \ gnunet-daemon-regexprofiler.c gnunet_daemon_regexprofiler_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_daemon_regexprofiler_DEPENDENCIES = \ $(top_builddir)/src/dht/libgnunetdht.la \ libgnunetregextest.a \ libgnunetregex_internal.a @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_regex_eval_api_SOURCES = \ test_regex_eval_api.c test_regex_eval_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la test_regex_api_SOURCES = \ test_regex_api.c test_regex_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_regex_iterate_api_SOURCES = \ test_regex_iterate_api.c test_regex_iterate_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/util/libgnunetutil.la test_regex_proofs_SOURCES = \ test_regex_proofs.c test_regex_proofs_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la test_regex_graph_api_SOURCES = \ test_regex_graph_api.c test_regex_graph_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ regex_simulation_profiler_test.conf \ test_regex_api_data.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/regex/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/regex/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): regex.conf: $(top_builddir)/config.status $(srcdir)/regex.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libgnunetregex_internal.a: $(libgnunetregex_internal_a_OBJECTS) $(libgnunetregex_internal_a_DEPENDENCIES) $(EXTRA_libgnunetregex_internal_a_DEPENDENCIES) $(AM_V_at)-rm -f libgnunetregex_internal.a $(AM_V_AR)$(libgnunetregex_internal_a_AR) libgnunetregex_internal.a $(libgnunetregex_internal_a_OBJECTS) $(libgnunetregex_internal_a_LIBADD) $(AM_V_at)$(RANLIB) libgnunetregex_internal.a libgnunetregextest.a: $(libgnunetregextest_a_OBJECTS) $(libgnunetregextest_a_DEPENDENCIES) $(EXTRA_libgnunetregextest_a_DEPENDENCIES) $(AM_V_at)-rm -f libgnunetregextest.a $(AM_V_AR)$(libgnunetregextest_a_AR) libgnunetregextest.a $(libgnunetregextest_a_OBJECTS) $(libgnunetregextest_a_LIBADD) $(AM_V_at)$(RANLIB) libgnunetregextest.a install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_block_regex.la: $(libgnunet_plugin_block_regex_la_OBJECTS) $(libgnunet_plugin_block_regex_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_block_regex_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_block_regex_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_regex_la_OBJECTS) $(libgnunet_plugin_block_regex_la_LIBADD) $(LIBS) libgnunetregex.la: $(libgnunetregex_la_OBJECTS) $(libgnunetregex_la_DEPENDENCIES) $(EXTRA_libgnunetregex_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetregex_la_LINK) -rpath $(libdir) $(libgnunetregex_la_OBJECTS) $(libgnunetregex_la_LIBADD) $(LIBS) libgnunetregexblock.la: $(libgnunetregexblock_la_OBJECTS) $(libgnunetregexblock_la_DEPENDENCIES) $(EXTRA_libgnunetregexblock_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetregexblock_la_LINK) -rpath $(libdir) $(libgnunetregexblock_la_OBJECTS) $(libgnunetregexblock_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-daemon-regexprofiler$(EXEEXT): $(gnunet_daemon_regexprofiler_OBJECTS) $(gnunet_daemon_regexprofiler_DEPENDENCIES) $(EXTRA_gnunet_daemon_regexprofiler_DEPENDENCIES) @rm -f gnunet-daemon-regexprofiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_regexprofiler_OBJECTS) $(gnunet_daemon_regexprofiler_LDADD) $(LIBS) gnunet-regex-profiler$(EXEEXT): $(gnunet_regex_profiler_OBJECTS) $(gnunet_regex_profiler_DEPENDENCIES) $(EXTRA_gnunet_regex_profiler_DEPENDENCIES) @rm -f gnunet-regex-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_regex_profiler_OBJECTS) $(gnunet_regex_profiler_LDADD) $(LIBS) gnunet-regex-simulation-profiler$(EXEEXT): $(gnunet_regex_simulation_profiler_OBJECTS) $(gnunet_regex_simulation_profiler_DEPENDENCIES) $(EXTRA_gnunet_regex_simulation_profiler_DEPENDENCIES) @rm -f gnunet-regex-simulation-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_regex_simulation_profiler_OBJECTS) $(gnunet_regex_simulation_profiler_LDADD) $(LIBS) gnunet-service-regex$(EXEEXT): $(gnunet_service_regex_OBJECTS) $(gnunet_service_regex_DEPENDENCIES) $(EXTRA_gnunet_service_regex_DEPENDENCIES) @rm -f gnunet-service-regex$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_regex_OBJECTS) $(gnunet_service_regex_LDADD) $(LIBS) perf-regex$(EXEEXT): $(perf_regex_OBJECTS) $(perf_regex_DEPENDENCIES) $(EXTRA_perf_regex_DEPENDENCIES) @rm -f perf-regex$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_regex_OBJECTS) $(perf_regex_LDADD) $(LIBS) test_regex_api$(EXEEXT): $(test_regex_api_OBJECTS) $(test_regex_api_DEPENDENCIES) $(EXTRA_test_regex_api_DEPENDENCIES) @rm -f test_regex_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_regex_api_OBJECTS) $(test_regex_api_LDADD) $(LIBS) test_regex_eval_api$(EXEEXT): $(test_regex_eval_api_OBJECTS) $(test_regex_eval_api_DEPENDENCIES) $(EXTRA_test_regex_eval_api_DEPENDENCIES) @rm -f test_regex_eval_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_regex_eval_api_OBJECTS) $(test_regex_eval_api_LDADD) $(LIBS) test_regex_graph_api$(EXEEXT): $(test_regex_graph_api_OBJECTS) $(test_regex_graph_api_DEPENDENCIES) $(EXTRA_test_regex_graph_api_DEPENDENCIES) @rm -f test_regex_graph_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_regex_graph_api_OBJECTS) $(test_regex_graph_api_LDADD) $(LIBS) test_regex_iterate_api$(EXEEXT): $(test_regex_iterate_api_OBJECTS) $(test_regex_iterate_api_DEPENDENCIES) $(EXTRA_test_regex_iterate_api_DEPENDENCIES) @rm -f test_regex_iterate_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_regex_iterate_api_OBJECTS) $(test_regex_iterate_api_LDADD) $(LIBS) test_regex_proofs$(EXEEXT): $(test_regex_proofs_OBJECTS) $(test_regex_proofs_DEPENDENCIES) $(EXTRA_test_regex_proofs_DEPENDENCIES) @rm -f test_regex_proofs$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_regex_proofs_OBJECTS) $(test_regex_proofs_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-regexprofiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-regex-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-regex-simulation-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-regex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf-regex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_regex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_block_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_internal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_internal_dht.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_test_graph.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_test_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_test_random.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_regex_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_regex_eval_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_regex_graph_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_regex_iterate_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_regex_proofs.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_regex_eval_api.log: test_regex_eval_api$(EXEEXT) @p='test_regex_eval_api$(EXEEXT)'; \ b='test_regex_eval_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_regex_iterate_api.log: test_regex_iterate_api$(EXEEXT) @p='test_regex_iterate_api$(EXEEXT)'; \ b='test_regex_iterate_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_regex_proofs.log: test_regex_proofs$(EXEEXT) @p='test_regex_proofs$(EXEEXT)'; \ b='test_regex_proofs'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_regex_graph_api.log: test_regex_graph_api$(EXEEXT) @p='test_regex_graph_api$(EXEEXT)'; \ b='test_regex_graph_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_regex_api.log: test_regex_api$(EXEEXT) @p='test_regex_api$(EXEEXT)'; \ b='test_regex_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-noinstLIBRARIES \ clean-noinstPROGRAMS clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-noinstLIBRARIES \ clean-noinstPROGRAMS clean-pluginLTLIBRARIES cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/regex/test_regex_api.c0000644000175000017500000000654312225777501015101 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/test_regex_api.c * @brief base test case for regex api (and DHT functions) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_regex_service.h" /** * How long until we really give up on a particular testcase portion? */ #define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) /** * How long until we give up on any particular operation (and retry)? */ #define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) static struct GNUNET_REGEX_Announcement *a; static struct GNUNET_REGEX_Search *s; static int ok = 1; static GNUNET_SCHEDULER_TaskIdentifier die_task; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_REGEX_announce_cancel (a); a = NULL; GNUNET_REGEX_search_cancel (s); s = NULL; ok = 0; } static void end_badly () { die_task = GNUNET_SCHEDULER_NO_TASK; FPRINTF (stderr, "%s", "Testcase failed (timeout).\n"); GNUNET_REGEX_announce_cancel (a); a = NULL; GNUNET_REGEX_search_cancel (s); s = NULL; ok = 1; } /** * Search callback function, invoked for every result that was found. * * @param cls Closure provided in GNUNET_REGEX_search. * @param id Peer providing a regex that matches the string. * @param get_path Path of the get request. * @param get_path_length Lenght of get_path. * @param put_path Path of the put request. * @param put_path_length Length of the put_path. */ static void found_cb (void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL); a = GNUNET_REGEX_announce (cfg, "my long prefix - hello world(0|1)*", GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), 1); s = GNUNET_REGEX_search (cfg, "my long prefix - hello world0101", &found_cb, NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-regex-api", "test_regex_api_data.conf", &run, NULL)) return 1; return ok; } /* end of test_regex_api.c */ gnunet-0.10.1/src/regex/test_regex_api_data.conf0000644000175000017500000000150212225230043016544 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-regex-api/ [fs] AUTOSTART = NO [resolver] AUTOSTART = NO [datastore] AUTOSTART = NO [dhtcache] QUOTA = 1 MB DATABASE = heap [topology] TARGET-CONNECTION-COUNT = 16 AUTOCONNECT = YES FRIENDS-ONLY = NO MINIMUM-FRIENDS = 0 [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [core] PORT = 2092 [dht] PORT = 12370 [transport] plugins = tcp NEIGHBOUR_LIMIT = 50 PORT = 2091 [peerinfo] PORT = 2090 [resolver] PORT = 2089 [statistics] PORT = 2088 [arm] DEFAULTSERVICES = PORT = 2087 [transport-tcp] TIMEOUT = 300 s PORT = 2094 [TESTING] WEAKRANDOM = NO [nat] DISABLEV6 = YES BINDTO = 127.0.0.1 ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 [dns] AUTOSTART = NO [namestore] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART=NO gnunet-0.10.1/src/regex/regex_test_graph.c0000644000175000017500000002071212225777501015423 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/regex/regex_test_graph.c * @brief functions for creating .dot graphs from regexes * @author Maximilian Szengel */ #include "platform.h" #include "regex_internal_lib.h" #include "regex_test_lib.h" #include "regex_internal.h" /** * Context for graph creation. Passed as the cls to * REGEX_TEST_automaton_save_graph_step. */ struct REGEX_TEST_Graph_Context { /** * File pointer to the dot file used for output. */ FILE *filep; /** * Verbose flag, if it's set to GNUNET_YES additional info will be printed in * the graph. */ int verbose; /** * Coloring flag, if set to GNUNET_YES SCCs will be colored. */ int coloring; }; /** * Recursive function doing DFS with 'v' as a start, detecting all SCCs inside * the subgraph reachable from 'v'. Used with scc_tarjan function to detect all * SCCs inside an automaton. * * @param scc_counter counter for numbering the sccs * @param v start vertex * @param index current index * @param stack stack for saving all SCCs * @param stack_size current size of the stack */ static void scc_tarjan_strongconnect (unsigned int *scc_counter, struct REGEX_INTERNAL_State *v, unsigned int *index, struct REGEX_INTERNAL_State **stack, unsigned int *stack_size) { struct REGEX_INTERNAL_State *w; struct REGEX_INTERNAL_Transition *t; v->index = *index; v->lowlink = *index; (*index)++; stack[(*stack_size)++] = v; v->contained = 1; for (t = v->transitions_head; NULL != t; t = t->next) { w = t->to_state; if (NULL == w) continue; if (w->index < 0) { scc_tarjan_strongconnect (scc_counter, w, index, stack, stack_size); v->lowlink = (v->lowlink > w->lowlink) ? w->lowlink : v->lowlink; } else if (1 == w->contained) v->lowlink = (v->lowlink > w->index) ? w->index : v->lowlink; } if (v->lowlink == v->index) { (*scc_counter)++; do { w = stack[--(*stack_size)]; w->contained = 0; w->scc_id = *scc_counter; } while (w != v); } } /** * Detect all SCCs (Strongly Connected Components) inside the given automaton. * SCCs will be marked using the scc_id on each state. * * @param a the automaton for which SCCs should be computed and assigned. */ static void scc_tarjan (struct REGEX_INTERNAL_Automaton *a) { unsigned int index; unsigned int scc_counter; struct REGEX_INTERNAL_State *v; struct REGEX_INTERNAL_State *stack[a->state_count]; unsigned int stack_size; for (v = a->states_head; NULL != v; v = v->next) { v->contained = 0; v->index = -1; v->lowlink = -1; } stack_size = 0; index = 0; scc_counter = 0; for (v = a->states_head; NULL != v; v = v->next) { if (v->index < 0) scc_tarjan_strongconnect (&scc_counter, v, &index, stack, &stack_size); } } /** * Save a state to an open file pointer. cls is expected to be a file pointer to * an open file. Used only in conjunction with * REGEX_TEST_automaton_save_graph. * * @param cls file pointer. * @param count current count of the state, not used. * @param s state. */ void REGEX_TEST_automaton_save_graph_step (void *cls, unsigned int count, struct REGEX_INTERNAL_State *s) { struct REGEX_TEST_Graph_Context *ctx = cls; struct REGEX_INTERNAL_Transition *ctran; char *s_acc = NULL; char *s_tran = NULL; char *name; char *to_name; if (GNUNET_YES == ctx->verbose) GNUNET_asprintf (&name, "%i (%s) (%s) (%s)", s->dfs_id, s->name, s->proof, GNUNET_h2s (&s->hash)); else GNUNET_asprintf (&name, "%i", s->dfs_id); if (s->accepting) { if (GNUNET_YES == ctx->coloring) { GNUNET_asprintf (&s_acc, "\"%s\" [shape=doublecircle, color=\"0.%i 0.8 0.95\"];\n", name, s->scc_id * s->scc_id); } else { GNUNET_asprintf (&s_acc, "\"%s\" [shape=doublecircle];\n", name, s->scc_id); } } else if (GNUNET_YES == ctx->coloring) { GNUNET_asprintf (&s_acc, "\"%s\" [shape=circle, color=\"0.%i 0.8 0.95\"];\n", name, s->scc_id * s->scc_id); } else { GNUNET_asprintf (&s_acc, "\"%s\" [shape=circle];\n", name, s->scc_id); } GNUNET_assert (NULL != s_acc); fwrite (s_acc, strlen (s_acc), 1, ctx->filep); GNUNET_free (s_acc); s_acc = NULL; for (ctran = s->transitions_head; NULL != ctran; ctran = ctran->next) { if (NULL == ctran->to_state) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Transition from State %i has no state for transitioning\n", s->id); continue; } if (GNUNET_YES == ctx->verbose) { GNUNET_asprintf (&to_name, "%i (%s) (%s) (%s)", ctran->to_state->dfs_id, ctran->to_state->name, ctran->to_state->proof, GNUNET_h2s (&ctran->to_state->hash)); } else GNUNET_asprintf (&to_name, "%i", ctran->to_state->dfs_id); if (NULL == ctran->label) { if (GNUNET_YES == ctx->coloring) { GNUNET_asprintf (&s_tran, "\"%s\" -> \"%s\" [label = \"ε\", color=\"0.%i 0.8 0.95\"];\n", name, to_name, s->scc_id * s->scc_id); } else { GNUNET_asprintf (&s_tran, "\"%s\" -> \"%s\" [label = \"ε\"];\n", name, to_name, s->scc_id); } } else { if (GNUNET_YES == ctx->coloring) { GNUNET_asprintf (&s_tran, "\"%s\" -> \"%s\" [label = \"%s\", color=\"0.%i 0.8 0.95\"];\n", name, to_name, ctran->label, s->scc_id * s->scc_id); } else { GNUNET_asprintf (&s_tran, "\"%s\" -> \"%s\" [label = \"%s\"];\n", name, to_name, ctran->label, s->scc_id); } } GNUNET_free (to_name); GNUNET_assert (NULL != s_tran); fwrite (s_tran, strlen (s_tran), 1, ctx->filep); GNUNET_free (s_tran); s_tran = NULL; } GNUNET_free (name); } /** * Save the given automaton as a GraphViz dot file. * * @param a the automaton to be saved. * @param filename where to save the file. * @param options options for graph generation that include coloring or verbose * mode */ void REGEX_TEST_automaton_save_graph (struct REGEX_INTERNAL_Automaton *a, const char *filename, enum REGEX_TEST_GraphSavingOptions options) { char *start; char *end; struct REGEX_TEST_Graph_Context ctx; if (NULL == a) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not print NFA, was NULL!"); return; } if (NULL == filename || strlen (filename) < 1) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No Filename given!"); return; } ctx.filep = fopen (filename, "w"); ctx.verbose = (0 == (options & REGEX_TEST_GRAPH_VERBOSE)) ? GNUNET_NO : GNUNET_YES; ctx.coloring = (0 == (options & REGEX_TEST_GRAPH_COLORING)) ? GNUNET_NO : GNUNET_YES; if (NULL == ctx.filep) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not open file for writing: %s", filename); return; } /* First add the SCCs to the automaton, so we can color them nicely */ if (GNUNET_YES == ctx.coloring) scc_tarjan (a); start = "digraph G {\nrankdir=LR\n"; fwrite (start, strlen (start), 1, ctx.filep); REGEX_INTERNAL_automaton_traverse (a, a->start, NULL, NULL, ®EX_TEST_automaton_save_graph_step, &ctx); end = "\n}\n"; fwrite (end, strlen (end), 1, ctx.filep); fclose (ctx.filep); } gnunet-0.10.1/src/regex/regex_test_random.c0000644000175000017500000001047512225777501015607 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/regex/regex_test_random.c * @brief functions for creating random regular expressions and strings * @author Maximilian Szengel */ #include "platform.h" #include "regex_test_lib.h" #include "gnunet_crypto_lib.h" #include "regex_internal.h" /** * Get a (pseudo) random valid literal for building a regular expression. * * @return random valid literal */ static char get_random_literal () { uint32_t ridx; ridx = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, (uint32_t) strlen (ALLOWED_LITERALS)); return ALLOWED_LITERALS[ridx]; } /** * Generate a (pseudo) random regular expression of length 'rx_length', as well * as a (optional) string that will be matched by the generated regex. The * returned regex needs to be freed. * * @param rx_length length of the random regex. * @param matching_str (optional) pointer to a string that will contain a string * that will be matched by the generated regex, if * 'matching_str' pointer was not NULL. Make sure you * allocated at least rx_length+1 bytes for this sting. * * @return NULL if 'rx_length' is 0, a random regex of length 'rx_length', which * needs to be freed, otherwise. */ char * REGEX_TEST_generate_random_regex (size_t rx_length, char *matching_str) { char *rx; char *rx_p; char *matching_strp; unsigned int i; unsigned int char_op_switch; unsigned int last_was_op; int rx_op; char current_char; if (0 == rx_length) return NULL; if (NULL != matching_str) matching_strp = matching_str; else matching_strp = NULL; rx = GNUNET_malloc (rx_length + 1); rx_p = rx; current_char = 0; last_was_op = 1; for (i = 0; i < rx_length; i++) { char_op_switch = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2); if (0 == char_op_switch && !last_was_op) { last_was_op = 1; rx_op = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4); switch (rx_op) { case 0: current_char = '+'; break; case 1: current_char = '*'; break; case 2: current_char = '?'; break; case 3: if (i < rx_length - 1) /* '|' cannot be at the end */ current_char = '|'; else current_char = get_random_literal (); break; } } else { current_char = get_random_literal (); last_was_op = 0; } if (NULL != matching_strp && (current_char != '+' && current_char != '*' && current_char != '?' && current_char != '|')) { *matching_strp = current_char; matching_strp++; } *rx_p = current_char; rx_p++; } *rx_p = '\0'; if (NULL != matching_strp) *matching_strp = '\0'; return rx; } /** * Generate a random string of maximum length 'max_len' that only contains literals allowed * in a regular expression. The string might be 0 chars long but is garantueed * to be shorter or equal to 'max_len'. * * @param max_len maximum length of the string that should be generated. * * @return random string that needs to be freed. */ char * REGEX_TEST_generate_random_string (size_t max_len) { unsigned int i; char *str; size_t len; if (1 > max_len) return GNUNET_strdup (""); len = (size_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max_len); str = GNUNET_malloc (len + 1); for (i = 0; i < len; i++) { str[i] = get_random_literal (); } str[i] = '\0'; return str; } gnunet-0.10.1/src/regex/test_regex_proofs.c0000644000175000017500000001070312225777501015631 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/test_regex_proofs.c * @brief test for regex.c * @author Maximilian Szengel */ #include "platform.h" #include "regex_internal_lib.h" #include "regex_test_lib.h" #include "regex_internal.h" /** * Test if the given regex's canonical regex is the same as this canonical * regex's canonical regex. Confused? Ok, then: 1. construct a dfa A from the * given 'regex' 2. get the canonical regex of dfa A 3. construct a dfa B from * this canonical regex 3. compare the canonical regex of dfa A with the * canonical regex of dfa B. * * @param regex regular expression used for this test (see above). * * @return 0 on success, 1 on failure */ static unsigned int test_proof (const char *regex) { unsigned int error; struct REGEX_INTERNAL_Automaton *dfa; char *c_rx1; const char *c_rx2; dfa = REGEX_INTERNAL_construct_dfa (regex, strlen (regex), 1); GNUNET_assert (NULL != dfa); c_rx1 = GNUNET_strdup (REGEX_INTERNAL_get_canonical_regex (dfa)); REGEX_INTERNAL_automaton_destroy (dfa); dfa = REGEX_INTERNAL_construct_dfa (c_rx1, strlen (c_rx1), 1); GNUNET_assert (NULL != dfa); c_rx2 = REGEX_INTERNAL_get_canonical_regex (dfa); error = (0 == strcmp (c_rx1, c_rx2)) ? 0 : 1; if (error > 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Comparing canonical regex of\n%s\nfailed:\n%s\nvs.\n%s\n", regex, c_rx1, c_rx2); } GNUNET_free (c_rx1); REGEX_INTERNAL_automaton_destroy (dfa); return error; } /** * Use 'test_proof' function to randomly test the canonical regexes of 'count' * random expressions of length 'rx_length'. * * @param count number of random regular expressions to test. * @param rx_length length of the random regular expressions. * * @return 0 on succes, number of failures otherwise. */ static unsigned int test_proofs_random (unsigned int count, size_t rx_length) { unsigned int i; char *rand_rx; unsigned int failures; failures = 0; for (i = 0; i < count; i++) { rand_rx = REGEX_TEST_generate_random_regex (rx_length, NULL); failures += test_proof (rand_rx); GNUNET_free (rand_rx); } return failures; } /** * Test a number of known examples of regexes for proper canonicalization. * * @return 0 on success, number of failures otherwise. */ static unsigned int test_proofs_static () { unsigned int i; unsigned int error; const char *regex[8] = { "a|aa*a", "a+", "a*", "a*a*", "(F*C|WfPf|y+F*C)", "y*F*C|WfPf", "((a|b)c|(a|b)(d|(a|b)e))", "((a|b)(c|d)|(a|b)(a|b)e)" }; const char *canon_rx1; const char *canon_rx2; struct REGEX_INTERNAL_Automaton *dfa1; struct REGEX_INTERNAL_Automaton *dfa2; error = 0; for (i = 0; i < 8; i += 2) { dfa1 = REGEX_INTERNAL_construct_dfa (regex[i], strlen (regex[i]), 1); dfa2 = REGEX_INTERNAL_construct_dfa (regex[i + 1], strlen (regex[i + 1]), 1); GNUNET_assert (NULL != dfa1); GNUNET_assert (NULL != dfa2); canon_rx1 = REGEX_INTERNAL_get_canonical_regex (dfa1); canon_rx2 = REGEX_INTERNAL_get_canonical_regex (dfa2); error += (0 == strcmp (canon_rx1, canon_rx2)) ? 0 : 1; if (error > 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Comparing canonical regex failed:\nrx1:\t%s\ncrx1:\t%s\nrx2:\t%s\ncrx2:\t%s\n", regex[i], canon_rx1, regex[i + 1], canon_rx2); } REGEX_INTERNAL_automaton_destroy (dfa1); REGEX_INTERNAL_automaton_destroy (dfa2); } return error; } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-regex", "WARNING", NULL); int error; error = 0; error += test_proofs_static (); error += test_proofs_random (100, 30); return error; } gnunet-0.10.1/src/regex/gnunet-regex-profiler.c0000644000175000017500000012255512225777501016331 00000000000000/* This file is part of GNUnet. (C) 2011 - 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/gnunet-regex-profiler.c * @brief Regex profiler for testing distributed regex use. * @author Bartlomiej Polot * @author Maximilian Szengel * */ #include #include "platform.h" #include "gnunet_applications.h" #include "gnunet_util_lib.h" #include "regex_internal_lib.h" #include "gnunet_arm_service.h" #include "gnunet_dht_service.h" #include "gnunet_testbed_service.h" #define FIND_TIMEOUT \ GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90) /** * DLL of operations */ struct DLLOperation { /** * The testbed operation handle */ struct GNUNET_TESTBED_Operation *op; /** * Closure */ void *cls; /** * The next pointer for DLL */ struct DLLOperation *next; /** * The prev pointer for DLL */ struct DLLOperation *prev; }; /** * Available states during profiling */ enum State { /** * Initial state */ STATE_INIT = 0, /** * Starting slaves */ STATE_SLAVES_STARTING, /** * Creating peers */ STATE_PEERS_CREATING, /** * Starting peers */ STATE_PEERS_STARTING, /** * Linking peers */ STATE_PEERS_LINKING, /** * Matching strings against announced regexes */ STATE_SEARCH_REGEX, /** * Destroying peers; we can do this as the controller takes care of stopping a * peer if it is running */ STATE_PEERS_DESTROYING }; /** * Peer handles. */ struct RegexPeer { /** * Peer id. */ unsigned int id; /** * Peer configuration handle. */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The actual testbed peer handle. */ struct GNUNET_TESTBED_Peer *peer_handle; /** * Peer's search string. */ const char *search_str; /** * Set to GNUNET_YES if the peer successfully matched the above * search string. GNUNET_NO if the string could not be matched * during the profiler run. GNUNET_SYSERR if the string matching * timed out. Undefined if search_str is NULL */ int search_str_matched; /** * Peer's DHT handle. */ struct GNUNET_DHT_Handle *dht_handle; /** * Handle to a running regex search. */ struct REGEX_INTERNAL_Search *search_handle; /** * Testbed operation handle for DHT. */ struct GNUNET_TESTBED_Operation *op_handle; /** * Peers's statistics handle. */ struct GNUNET_STATISTICS_Handle *stats_handle; /** * The starting time of a profiling step. */ struct GNUNET_TIME_Absolute prof_start_time; /** * Operation timeout */ GNUNET_SCHEDULER_TaskIdentifier timeout; /** * Deamon start */ struct GNUNET_TESTBED_Operation *daemon_op; }; /** * Set when shutting down to avoid making more queries. */ static int in_shutdown; /** * The array of peers; we fill this as the peers are given to us by the testbed */ static struct RegexPeer *peers; /** * Host registration handle */ static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; /** * Handle to the master controller process */ static struct GNUNET_TESTBED_ControllerProc *mc_proc; /** * Handle to the master controller */ static struct GNUNET_TESTBED_Controller *mc; /** * Handle to global configuration */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * Shutdown task identifier */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Host registration task identifier */ static GNUNET_SCHEDULER_TaskIdentifier register_hosts_task; /** * Global event mask for all testbed events */ static uint64_t event_mask; /** * The starting time of a profiling step */ static struct GNUNET_TIME_Absolute prof_start_time; /** * Duration profiling step has taken */ static struct GNUNET_TIME_Relative prof_time; /** * Number of peers to be started by the profiler */ static unsigned int num_peers; /** * Global testing status */ static int result; /** * current state of profiling */ enum State state; /** * Folder where policy files are stored. */ static char * policy_dir; /** * File with hostnames where to execute the test. */ static char *hosts_file; /** * File with the strings to look for. */ static char *strings_file; /** * Search strings (num_peers of them). */ static char **search_strings; /** * How many searches are we going to start in parallel */ static long long unsigned int init_parallel_searches; /** * How many searches are running in parallel */ static unsigned int parallel_searches; /** * Number of strings found in the published regexes. */ static unsigned int strings_found; /** * Index of peer to start next announce/search. */ static unsigned int next_search; /** * Search timeout task identifier. */ static GNUNET_SCHEDULER_TaskIdentifier search_timeout_task; /** * Search timeout in seconds. */ static struct GNUNET_TIME_Relative search_timeout_time = { 60000 }; /** * File to log statistics to. */ static struct GNUNET_DISK_FileHandle *data_file; /** * Filename to log statistics to. */ static char *data_filename; /** * Prefix used for regex announcing. We need to prefix the search * strings with it, in order to find something. */ static char * regex_prefix; /** * What's the maximum regex reannounce period. */ static struct GNUNET_TIME_Relative reannounce_period_max; /******************************************************************************/ /****************************** DECLARATIONS ********************************/ /******************************************************************************/ /** * DHT connect callback. * * @param cls internal peer id. * @param op operation handle. * @param ca_result connect adapter result. * @param emsg error message. */ static void dht_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg); /** * DHT connect adapter. * * @param cls not used. * @param cfg configuration handle. * * @return */ static void * dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Adapter function called to destroy a connection to * the DHT service * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void dht_da (void *cls, void *op_result); /** * Function called by testbed once we are connected to stats * service. Get the statistics for the services of interest. * * @param cls the 'struct RegexPeer' for which we connected to stats * @param op connect operation handle * @param ca_result handle to stats service * @param emsg error message on failure */ static void stats_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg); /** * Start announcing the next regex in the DHT. * * @param cls Index of the next peer in the peers array. * @param tc TaskContext. */ static void announce_next_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /******************************************************************************/ /******************************** SHUTDOWN **********************************/ /******************************************************************************/ /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RegexPeer *peer; unsigned int peer_cnt; unsigned int search_str_cnt; char output_buffer[512]; size_t size; shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); if (GNUNET_SCHEDULER_NO_TASK != register_hosts_task) GNUNET_SCHEDULER_cancel (register_hosts_task); for (peer_cnt = 0; peer_cnt < num_peers; peer_cnt++) { peer = &peers[peer_cnt]; if (GNUNET_YES != peer->search_str_matched && NULL != data_file) { prof_time = GNUNET_TIME_absolute_get_duration (peer->prof_start_time); size = GNUNET_snprintf (output_buffer, sizeof (output_buffer), "%p Search string not found: %s (%d)\n" "%p On peer: %u (%p)\n" "%p After: %s\n", peer, peer->search_str, peer->search_str_matched, peer, peer->id, peer, peer, GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO)); if (size != GNUNET_DISK_file_write (data_file, output_buffer, size)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); } if (NULL != peers[peer_cnt].op_handle) GNUNET_TESTBED_operation_done (peers[peer_cnt].op_handle); } if (NULL != data_file) GNUNET_DISK_file_close (data_file); for (search_str_cnt = 0; search_str_cnt < num_peers && NULL != search_strings; search_str_cnt++) { GNUNET_free_non_null (search_strings[search_str_cnt]); } GNUNET_free_non_null (search_strings); if (NULL != reg_handle) GNUNET_TESTBED_cancel_registration (reg_handle); if (NULL != mc) GNUNET_TESTBED_controller_disconnect (mc); if (NULL != mc_proc) GNUNET_TESTBED_controller_stop (mc_proc); if (NULL != cfg) GNUNET_CONFIGURATION_destroy (cfg); GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */ } /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned long i = (unsigned long) cls; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Aborting from line %lu...\n", i); abort_task = GNUNET_SCHEDULER_NO_TASK; result = GNUNET_SYSERR; if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } /******************************************************************************/ /********************* STATISTICS SERVICE CONNECTIONS ***********************/ /******************************************************************************/ /** * Adapter function called to establish a connection to * statistics service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * stats_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_STATISTICS_create ("", cfg); } /** * Adapter function called to destroy a connection to * statistics service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void stats_da (void *cls, void *op_result) { struct RegexPeer *peer = cls; GNUNET_assert (op_result == peer->stats_handle); GNUNET_STATISTICS_destroy (peer->stats_handle, GNUNET_NO); peer->stats_handle = NULL; } /** * Process statistic values. Write all values to global 'data_file', if present. * * @param cls closure * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int stats_iterator (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { struct RegexPeer *peer = cls; char output_buffer[512]; size_t size; if (NULL == data_file) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%p -> %s [%s]: %llu\n", peer, subsystem, name, value); return GNUNET_OK; } size = GNUNET_snprintf (output_buffer, sizeof (output_buffer), "%p [%s] %llu %s\n", peer, subsystem, value, name); if (size != GNUNET_DISK_file_write (data_file, output_buffer, size)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); return GNUNET_OK; } /** * Stats callback. Finish the stats testbed operation and when all stats have * been iterated, shutdown the profiler. * * @param cls closure * @param success GNUNET_OK if statistics were * successfully obtained, GNUNET_SYSERR if not. */ static void stats_cb (void *cls, int success) { static unsigned int peer_cnt; struct RegexPeer *peer = cls; if (GNUNET_OK != success) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Getting statistics for peer %u failed!\n", peer->id); return; } GNUNET_assert (NULL != peer->op_handle); GNUNET_TESTBED_operation_done (peer->op_handle); peer->op_handle = NULL; peer_cnt++; peer = &peers[peer_cnt]; fprintf (stderr, "s"); if (peer_cnt == num_peers) { struct GNUNET_TIME_Relative delay = { 100 }; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "\nCollecting stats finished. Shutting down.\n"); shutdown_task = GNUNET_SCHEDULER_add_delayed (delay, &do_shutdown, NULL); result = GNUNET_OK; } else { peer->op_handle = GNUNET_TESTBED_service_connect (NULL, peer->peer_handle, "statistics", &stats_connect_cb, peer, &stats_ca, &stats_da, peer); } } /** * Function called by testbed once we are connected to stats * service. Get the statistics for the services of interest. * * @param cls the 'struct RegexPeer' for which we connected to stats * @param op connect operation handle * @param ca_result handle to stats service * @param emsg error message on failure */ static void stats_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct RegexPeer *peer = cls; if (NULL == ca_result || NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to statistics service on peer %u: %s\n", peer->id, emsg); peer->stats_handle = NULL; return; } peer->stats_handle = ca_result; if (NULL == GNUNET_STATISTICS_get (peer->stats_handle, NULL, NULL, GNUNET_TIME_UNIT_FOREVER_REL, &stats_cb, &stats_iterator, peer)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not get statistics of peer %u!\n", peer->id); } } /** * Task to collect all statistics from all peers, will shutdown the * profiler, when done. * * @param cls NULL * @param tc the task context */ static void do_collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RegexPeer *peer = &peers[0]; GNUNET_assert (NULL != peer->peer_handle); peer->op_handle = GNUNET_TESTBED_service_connect (NULL, peer->peer_handle, "statistics", &stats_connect_cb, peer, &stats_ca, &stats_da, peer); } /******************************************************************************/ /************************ REGEX FIND CONNECTIONS **************************/ /******************************************************************************/ /** * Start searching for the next string in the DHT. * * @param cls Index of the next peer in the peers array. * @param tc TaskContext. */ static void find_string (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Method called when we've found a peer that announced a regex * that matches our search string. Now get the statistics. * * @param cls Closure provided in REGEX_INTERNAL_search. * @param id Peer providing a regex that matches the string. * @param get_path Path of the get request. * @param get_path_length Lenght of get_path. * @param put_path Path of the put request. * @param put_path_length Length of the put_path. */ static void regex_found_handler (void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length) { struct RegexPeer *peer = cls; char output_buffer[512]; size_t size; if (GNUNET_YES == peer->search_str_matched) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "String %s on peer %u already matched!\n", peer->search_str, peer->id); return; } strings_found++; parallel_searches--; if (GNUNET_SCHEDULER_NO_TASK != peer->timeout) { GNUNET_SCHEDULER_cancel (peer->timeout); peer->timeout = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_NO == in_shutdown) GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL); } if (NULL == id) { // FIXME not possible right now GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "String matching timed out for string %s on peer %u (%i/%i)\n", peer->search_str, peer->id, strings_found, num_peers); peer->search_str_matched = GNUNET_SYSERR; } else { prof_time = GNUNET_TIME_absolute_get_duration (peer->prof_start_time); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "String %s found on peer %u after %s (%i/%i) (%u||)\n", peer->search_str, peer->id, GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO), strings_found, num_peers, parallel_searches); peer->search_str_matched = GNUNET_YES; if (NULL != data_file) { size = GNUNET_snprintf (output_buffer, sizeof (output_buffer), "%p Peer: %u\n" "%p Search string: %s\n" "%p Search duration: %s\n\n", peer, peer->id, peer, peer->search_str, peer, GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO)); if (size != GNUNET_DISK_file_write (data_file, output_buffer, size)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); } } GNUNET_TESTBED_operation_done (peer->op_handle); peer->op_handle = NULL; if (strings_found == num_peers) { prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All strings successfully matched in %s\n", GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO)); if (GNUNET_SCHEDULER_NO_TASK != search_timeout_task) { GNUNET_SCHEDULER_cancel (search_timeout_task); search_timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Collecting stats.\n"); GNUNET_SCHEDULER_add_now (&do_collect_stats, NULL); } } /** * Connect by string timeout task. This will cancel the profiler after the * specified timeout 'search_timeout'. * * @param cls NULL * @param tc the task context */ static void search_timed_out (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) { unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finding matches to all strings did not succeed after %s.\n", GNUNET_STRINGS_relative_time_to_string (search_timeout_time, GNUNET_NO)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Found %i of %i strings\n", strings_found, num_peers); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Search timed out after %s." "Collecting stats and shutting down.\n", GNUNET_STRINGS_relative_time_to_string (search_timeout_time, GNUNET_NO)); in_shutdown = GNUNET_YES; for (i = 0; i < num_peers; i++) { if (NULL != peers[i].op_handle) { GNUNET_TESTBED_operation_done (peers[i].op_handle); peers[i].op_handle = NULL; } } GNUNET_SCHEDULER_add_now (&do_collect_stats, NULL); } /** * Search timed out. It might still complete in the future, * but we should start another one. * * @param cls Index of the next peer in the peers array. * @param tc TaskContext. */ static void find_timed_out (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RegexPeer *p = cls; p->timeout = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Searching for string \"%s\" on peer %d timed out.\n", p->search_str, p->id); if (GNUNET_NO == in_shutdown) GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL); } /** * Start searching for a string in the DHT. * * @param cls Index of the next peer in the peers array. * @param tc TaskContext. */ static void find_string (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int search_peer = (unsigned int) (long) cls; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) || search_peer >= num_peers || GNUNET_YES == in_shutdown) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Searching for string \"%s\" on peer %d (%u||)\n", peers[search_peer].search_str, search_peer, parallel_searches); peers[search_peer].op_handle = GNUNET_TESTBED_service_connect (NULL, peers[search_peer].peer_handle, "dht", &dht_connect_cb, &peers[search_peer], &dht_ca, &dht_da, &peers[search_peer]); GNUNET_assert (NULL != peers[search_peer].op_handle); peers[search_peer].timeout = GNUNET_SCHEDULER_add_delayed (FIND_TIMEOUT, &find_timed_out, &peers[search_peer]); } /** * Callback called when testbed has started the daemon we asked for. * * @param cls NULL * @param op the operation handle * @param emsg NULL on success; otherwise an error description */ static void daemon_started (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { struct RegexPeer *peer = (struct RegexPeer *) cls; unsigned long search_peer; unsigned int i; GNUNET_TESTBED_operation_done (peer->daemon_op); peer->daemon_op = NULL; if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to start/stop daemon at peer %u: %s\n", peer->id, emsg); GNUNET_abort (); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Deamon %u started successfully\n", peer->id); } /* Find a peer to look for a string matching the regex announced */ search_peer = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, num_peers); for (i = 0; peers[search_peer].search_str != NULL; i++) { search_peer = (search_peer + 1) % num_peers; if (i > num_peers) GNUNET_abort (); /* we ran out of peers, must be a bug */ } peers[search_peer].search_str = search_strings[peer->id]; peers[search_peer].search_str_matched = GNUNET_NO; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply( reannounce_period_max, 2), &find_string, (void *) search_peer); } /** * Task to start the daemons on each peer so that the regexes are announced * into the DHT. * * @param cls NULL * @param tc the task context */ static void do_announce (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting announce.\n"); for (i = 0; i < init_parallel_searches; i++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, " scheduling announce %u\n", i); (void) GNUNET_SCHEDULER_add_now (&announce_next_regex, NULL); } } /** * Start announcing the next regex in the DHT. * * @param cls Closure (unused). * @param tc TaskContext. */ static void announce_next_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RegexPeer *peer; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; if (next_search >= num_peers) { if (strings_found != num_peers) { struct GNUNET_TIME_Relative new_delay; if (GNUNET_SCHEDULER_NO_TASK != search_timeout_task) GNUNET_SCHEDULER_cancel (search_timeout_task); new_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15); search_timeout_task = GNUNET_SCHEDULER_add_delayed (new_delay, &search_timed_out, NULL); } return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting daemon %u\n", next_search); peer = &peers[next_search]; peer->daemon_op = GNUNET_TESTBED_peer_manage_service (NULL, peer->peer_handle, "regexprofiler", &daemon_started, peer, 1); next_search++; parallel_searches++; } /** * DHT connect callback. Called when we are connected to the dht service for * the peer in 'cls'. If successfull we connect to the stats service of this * peer and then try to match the search string of this peer. * * @param cls internal peer id. * @param op operation handle. * @param ca_result connect adapter result. * @param emsg error message. */ static void dht_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct RegexPeer *peer = (struct RegexPeer *) cls; if (NULL != emsg || NULL == op || NULL == ca_result) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "DHT connect failed: %s\n", emsg); GNUNET_abort (); } GNUNET_assert (NULL != peer->dht_handle); GNUNET_assert (peer->op_handle == op); GNUNET_assert (peer->dht_handle == ca_result); peer->search_str_matched = GNUNET_NO; peer->search_handle = REGEX_INTERNAL_search (peer->dht_handle, peer->search_str, ®ex_found_handler, peer, NULL); peer->prof_start_time = GNUNET_TIME_absolute_get (); } /** * DHT connect adapter. Opens a connection to the dht service. * * @param cls Closure (peer). * @param cfg Configuration handle. * * @return */ static void * dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct RegexPeer *peer = cls; peer->dht_handle = GNUNET_DHT_connect (cfg, 32); return peer->dht_handle; } /** * Adapter function called to destroy a connection to the dht service. * * @param cls Closure (peer). * @param op_result Service handle returned from the connect adapter. */ static void dht_da (void *cls, void *op_result) { struct RegexPeer *peer = (struct RegexPeer *) cls; GNUNET_assert (peer->dht_handle == op_result); if (NULL != peer->search_handle) { REGEX_INTERNAL_search_cancel (peer->search_handle); peer->search_handle = NULL; } if (NULL != peer->dht_handle) { GNUNET_DHT_disconnect (peer->dht_handle); peer->dht_handle = NULL; } } /** * Signature of a main function for a testcase. * * @param cls NULL * @param h the run handle * @param num_peers_ number of peers in 'peers' * @param testbed_peers handle to peers run in the testbed. NULL upon timeout (see * GNUNET_TESTBED_test_run()). * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers_, struct GNUNET_TESTBED_Peer **testbed_peers, unsigned int links_succeeded, unsigned int links_failed) { unsigned int i; GNUNET_assert (num_peers_ == num_peers); prof_time = GNUNET_TIME_absolute_get_duration (prof_start_time); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Testbed started in %s\n", GNUNET_STRINGS_relative_time_to_string (prof_time, GNUNET_NO)); if (GNUNET_SCHEDULER_NO_TASK != abort_task) { GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_NO_TASK; } for (i = 0; i < num_peers; i++) { peers[i].peer_handle = testbed_peers[i]; } if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno (cfg, "DHT", "DISABLE_TRY_CONNECT")) { struct GNUNET_TIME_Relative settle_time; settle_time = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10 * num_peers); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Waiting for DHT for %s to settle new connections.\n\n", GNUNET_STRINGS_relative_time_to_string(settle_time, GNUNET_NO)); GNUNET_SCHEDULER_add_delayed (settle_time, &do_announce, NULL); } else { GNUNET_SCHEDULER_add_now (&do_announce, NULL); } search_timeout_task = GNUNET_SCHEDULER_add_delayed (search_timeout_time, &search_timed_out, NULL); } /** * Function that will be called whenever something in the testbed changes. * * @param cls closure, NULL * @param event information on what is happening */ static void master_controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_CONNECT: printf("."); break; case GNUNET_TESTBED_ET_PEER_START: printf("#"); break; default: break; } fflush(stdout); } /******************************************************************************/ /*************************** TESTBED PEER SETUP *****************************/ /******************************************************************************/ /** * Load search strings from given filename. One search string per line. * * @param filename filename of the file containing the search strings. * @param strings set of strings loaded from file. Caller needs to free this * if number returned is greater than zero. * @param limit upper limit on the number of strings read from the file * @return number of strings found in the file. GNUNET_SYSERR on error. */ static int load_search_strings (const char *filename, char ***strings, unsigned int limit) { char *data; char *buf; uint64_t filesize; unsigned int offset; int str_cnt; unsigned int i; if (NULL == filename) { return GNUNET_SYSERR; } if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not find search strings file %s\n", filename); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_DISK_file_size (filename, &filesize, GNUNET_YES, GNUNET_YES)) filesize = 0; if (0 == filesize) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Search strings file %s is empty.\n", filename); return GNUNET_SYSERR; } data = GNUNET_malloc (filesize); if (filesize != GNUNET_DISK_fn_read (filename, data, filesize)) { GNUNET_free (data); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not read search strings file %s.\n", filename); return GNUNET_SYSERR; } buf = data; offset = 0; str_cnt = 0; while (offset < (filesize - 1) && str_cnt < limit) { offset++; if (((data[offset] == '\n')) && (buf != &data[offset])) { data[offset] = '\0'; str_cnt++; buf = &data[offset + 1]; } else if ((data[offset] == '\n') || (data[offset] == '\0')) buf = &data[offset + 1]; } *strings = GNUNET_malloc (sizeof (char *) * str_cnt); offset = 0; for (i = 0; i < str_cnt; i++) { GNUNET_asprintf (&(*strings)[i], "%s%s", regex_prefix, &data[offset]); offset += strlen (&data[offset]) + 1; } GNUNET_free (data); return str_cnt; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param config configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { unsigned int nsearchstrs; unsigned int i; struct GNUNET_TIME_Relative abort_time; in_shutdown = GNUNET_NO; /* Check config */ if (NULL == config) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No configuration file given. Exiting\n")); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); return; } cfg = GNUNET_CONFIGURATION_dup (config); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER", "REGEX_PREFIX", ®ex_prefix)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Configuration option \"regex_prefix\" missing. Exiting\n")); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "REGEXPROFILER", "PARALLEL_SEARCHES", &init_parallel_searches)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Configuration option \"PARALLEL_SEARCHES\" missing." " Using default (%d)\n", 10); init_parallel_searches = 10; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "REGEXPROFILER", "REANNOUNCE_PERIOD_MAX", &reannounce_period_max)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "reannounce_period_max not given. Using 10 minutes.\n"); reannounce_period_max = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10); } /* Check arguments */ if (NULL == policy_dir) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No policy directory specified on command line. Exiting.\n")); return; } if (GNUNET_YES != GNUNET_DISK_directory_test (policy_dir, GNUNET_YES)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Specified policies directory does not exist. Exiting.\n")); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); return; } if (0 >= (int) (num_peers = GNUNET_DISK_directory_scan (policy_dir, NULL, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No files found in `%s'\n"), policy_dir); return; } GNUNET_CONFIGURATION_set_value_string (cfg, "REGEXPROFILER", "POLICY_DIR", policy_dir); if (GNUNET_YES != GNUNET_DISK_file_test (strings_file)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No search strings file given. Exiting.\n")); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); return; } nsearchstrs = load_search_strings (strings_file, &search_strings, num_peers); if (num_peers != nsearchstrs) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error loading search strings.\n"); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "File (%s) does not contain enough strings (%u/%u).\n", strings_file, nsearchstrs, num_peers); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); return; } if ( (0 == num_peers) || (NULL == search_strings)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error loading search strings. Exiting.\n")); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); return; } for (i = 0; i < num_peers; i++) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "search string: %s\n", search_strings[i]); /* Check logfile */ if ( (NULL != data_filename) && (NULL == (data_file = GNUNET_DISK_file_open (data_filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))) ) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", data_filename); return; } /* Initialize peers */ peers = GNUNET_malloc (sizeof (struct RegexPeer) * num_peers); for (i = 0; i < num_peers; i++) peers[i].id = i; GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "OVERLAY_RANDOM_LINKS", num_peers * 20); GNUNET_CONFIGURATION_set_value_number (cfg, "DHT", "FORCE_NSE", (long long unsigned) (log (num_peers) / log (2.0))); event_mask = 0LL; /* For feedback about the start process activate these and pass master_cb */ event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); // event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP); event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); // event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT); prof_start_time = GNUNET_TIME_absolute_get (); GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, &master_controller_cb, NULL, /* master_controller_cb cls */ &test_master, NULL); /* test_master cls */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED", "SETUP_TIMEOUT", &abort_time)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "SETUP_TIMEOUT not given. Using 15 minutes.\n"); abort_time = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15); } abort_time = GNUNET_TIME_relative_add (abort_time, GNUNET_TIME_UNIT_MINUTES); abort_task = GNUNET_SCHEDULER_add_delayed (abort_time, &do_abort, (void*) __LINE__); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "setup_timeout: %s\n", GNUNET_STRINGS_relative_time_to_string (abort_time, GNUNET_YES)); } /** * Main function. * * @param argc argument count * @param argv argument values * @return 0 on success */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'o', "output-file", "FILENAME", gettext_noop ("name of the file for writing statistics"), GNUNET_YES, &GNUNET_GETOPT_set_string, &data_filename}, {'t', "matching-timeout", "TIMEOUT", gettext_noop ("wait TIMEOUT before ending the experiment"), GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &search_timeout_time}, {'p', "policy-dir", "DIRECTORY", gettext_noop ("directory with policy files"), GNUNET_YES, &GNUNET_GETOPT_set_filename, &policy_dir}, {'s', "strings-file", "FILENAME", gettext_noop ("name of file with input strings"), GNUNET_YES, &GNUNET_GETOPT_set_filename, &strings_file}, {'H', "hosts-file", "FILENAME", gettext_noop ("name of file with hosts' names"), GNUNET_YES, &GNUNET_GETOPT_set_filename, &hosts_file}, GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; result = GNUNET_SYSERR; ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-regex-profiler", _("Profiler for regex"), options, &run, NULL); if (GNUNET_OK != ret) return ret; if (GNUNET_OK != result) return 1; return 0; } gnunet-0.10.1/src/regex/regex_test_lib.h0000644000175000017500000001035112225777503015075 00000000000000/* * This file is part of GNUnet * (C) 2012 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file src/regex/regex_test_lib.h * @brief library to read regexes representing IP networks from a file. * and simplifying the into one big regex, in order to run * tests (regex performance, regex profiler). * @author Bertlomiej Polot */ #ifndef REGEX_INTERNAL_TEST_LIB_H #define REGEX_INTERNAL_TEST_LIB_H #include "regex_internal_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Combine an array of regexes into a single prefix-shared regex. * * @param regexes A NULL-terminated array of regexes. * * @return A string with a single regex that matches any of the original regexes */ char * REGEX_TEST_combine(char * const regexes[]); /** * Read a set of regexes from a file, one per line and return them in an array * suitable for REGEX_TEST_combine. * The array must be free'd using REGEX_TEST_free_from_file. * * @param filename Name of the file containing the regexes. * * @return A newly allocated, NULL terminated array of regexes. */ char ** REGEX_TEST_read_from_file (const char *filename); /** * Free all memory reserved for a set of regexes created by read_from_file. * * @param regexes NULL-terminated array of regexes. */ void REGEX_TEST_free_from_file (char **regexes); /** * Generate a (pseudo) random regular expression of length 'rx_length', as well * as a (optional) string that will be matched by the generated regex. The * returned regex needs to be freed. * * @param rx_length length of the random regex. * @param matching_str (optional) pointer to a string that will contain a string * that will be matched by the generated regex, if * 'matching_str' pointer was not NULL. * * @return NULL if 'rx_length' is 0, a random regex of length 'rx_length', which * needs to be freed, otherwise. */ char * REGEX_TEST_generate_random_regex (size_t rx_length, char *matching_str); /** * Generate a random string of maximum length 'max_len' that only contains literals allowed * in a regular expression. The string might be 0 chars long but is garantueed * to be shorter or equal to 'max_len'. * * @param max_len maximum length of the string that should be generated. * * @return random string that needs to be freed. */ char * REGEX_TEST_generate_random_string (size_t max_len); /** * Options for graph creation function * REGEX_TEST_automaton_save_graph. */ enum REGEX_TEST_GraphSavingOptions { /** * Default. Do nothing special. */ REGEX_TEST_GRAPH_DEFAULT = 0, /** * The generated graph will include extra information such as the NFA states * that were used to generate the DFA state. */ REGEX_TEST_GRAPH_VERBOSE = 1, /** * Enable graph coloring. Will color each SCC in a different color. */ REGEX_TEST_GRAPH_COLORING = 2 }; /** * Save the given automaton as a GraphViz dot file. * * @param a the automaton to be saved. * @param filename where to save the file. * @param options options for graph generation that include coloring or verbose * mode */ void REGEX_TEST_automaton_save_graph (struct REGEX_INTERNAL_Automaton *a, const char *filename, enum REGEX_TEST_GraphSavingOptions options); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of regex_internal_lib.h */ #endif gnunet-0.10.1/src/regex/regex_internal.h0000644000175000017500000002536312225777503015115 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/regex/regex_internal.h * @brief common internal definitions for regex library. * @author Maximilian Szengel */ #ifndef REGEX_INTERNAL_H #define REGEX_INTERNAL_H #include "regex_internal_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * char array of literals that are allowed inside a regex (apart from the * operators) */ #define ALLOWED_LITERALS "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" /** * Transition between two states. Transitions are stored at the states from * which they origin ('from_state'). Each state can have 0-n transitions. * If label is NULL, this is considered to be an epsilon transition. */ struct REGEX_INTERNAL_Transition { /** * This is a linked list. */ struct REGEX_INTERNAL_Transition *prev; /** * This is a linked list. */ struct REGEX_INTERNAL_Transition *next; /** * Unique id of this transition. */ unsigned int id; /** * Label for this transition. This is basically the edge label for the graph. */ char *label; /** * State to which this transition leads. */ struct REGEX_INTERNAL_State *to_state; /** * State from which this transition origins. */ struct REGEX_INTERNAL_State *from_state; }; /** * A state. Can be used in DFA and NFA automatons. */ struct REGEX_INTERNAL_State; /** * Set of states. */ struct REGEX_INTERNAL_StateSet { /** * Array of states. */ struct REGEX_INTERNAL_State **states; /** * Number of entries in *use* in the 'states' array. */ unsigned int off; /** * Length of the 'states' array. */ unsigned int size; }; /** * A state. Can be used in DFA and NFA automatons. */ struct REGEX_INTERNAL_State { /** * This is a linked list to keep states in an automaton. */ struct REGEX_INTERNAL_State *prev; /** * This is a linked list to keep states in an automaton. */ struct REGEX_INTERNAL_State *next; /** * This is a multi DLL for StateSet_MDLL. */ struct REGEX_INTERNAL_State *prev_SS; /** * This is a multi DLL for StateSet_MDLL. */ struct REGEX_INTERNAL_State *next_SS; /** * This is a multi DLL for StateSet_MDLL Stack. */ struct REGEX_INTERNAL_State *prev_ST; /** * This is a multi DLL for StateSet_MDLL Stack. */ struct REGEX_INTERNAL_State *next_ST; /** * Unique state id. */ unsigned int id; /** * Unique state id that is used for traversing the automaton. It is guaranteed * to be > 0 and < state_count. */ unsigned int traversal_id; /** * If this is an accepting state or not. */ int accepting; /** * Marking of the state. This is used for marking all visited states when * traversing all states of an automaton and for cases where the state id * cannot be used (dfa minimization). */ int marked; /** * Marking the state as contained. This is used for checking, if the state is * contained in a set in constant time. */ int contained; /** * Marking the state as part of an SCC (Strongly Connected Component). All * states with the same scc_id are part of the same SCC. scc_id is 0, if state * is not a part of any SCC. */ unsigned int scc_id; /** * Used for SCC detection. */ int index; /** * Used for SCC detection. */ int lowlink; /** * Human readable name of the state. Used for debugging and graph * creation. */ char *name; /** * Hash of the state. */ struct GNUNET_HashCode hash; /** * Linear state ID accquired by depth-first-search. This ID should be used for * storing information about the state in an array, because the 'id' of the * state is not guaranteed to be linear. The 'dfs_id' is guaranteed to be > 0 * and < 'state_count'. */ unsigned int dfs_id; /** * Proof for this state. */ char *proof; /** * Number of transitions from this state to other states. */ unsigned int transition_count; /** * DLL of transitions. */ struct REGEX_INTERNAL_Transition *transitions_head; /** * DLL of transitions. */ struct REGEX_INTERNAL_Transition *transitions_tail; /** * Number of incoming transitions. Used for compressing DFA paths. */ unsigned int incoming_transition_count; /** * Set of states on which this state is based on. Used when creating a DFA out * of several NFA states. */ struct REGEX_INTERNAL_StateSet nfa_set; }; /** * Type of an automaton. */ enum REGEX_INTERNAL_AutomatonType { NFA, DFA }; /** * Automaton representation. */ struct REGEX_INTERNAL_Automaton { /** * Linked list of NFAs used for partial NFA creation. */ struct REGEX_INTERNAL_Automaton *prev; /** * Linked list of NFAs used for partial NFA creation. */ struct REGEX_INTERNAL_Automaton *next; /** * First state of the automaton. This is mainly used for constructing an NFA, * where each NFA itself consists of one or more NFAs linked together. */ struct REGEX_INTERNAL_State *start; /** * End state of the partial NFA. This is undefined for DFAs */ struct REGEX_INTERNAL_State *end; /** * Number of states in the automaton. */ unsigned int state_count; /** * DLL of states. */ struct REGEX_INTERNAL_State *states_head; /** * DLL of states */ struct REGEX_INTERNAL_State *states_tail; /** * Type of the automaton. */ enum REGEX_INTERNAL_AutomatonType type; /** * Regex */ char *regex; /** * Canonical regex (result of RX->NFA->DFA->RX) */ char *canonical_regex; /** * GNUNET_YES, if multi strides have been added to the Automaton. */ int is_multistrided; }; /** * Construct an NFA by parsing the regex string of length 'len'. * * @param regex regular expression string. * @param len length of the string. * * @return NFA, needs to be freed using REGEX_INTERNAL_automaton_destroy. */ struct REGEX_INTERNAL_Automaton * REGEX_INTERNAL_construct_nfa (const char *regex, const size_t len); /** * Function that get's passed to automaton traversal and is called before each * next traversal from state 's' using transition 't' to check if traversal * should proceed. Return GNUNET_NO to stop traversal or GNUNET_YES to continue. * * @param cls closure for the check. * @param s current state in the traversal. * @param t current transition from state 's' that will be used for the next * step. * * @return GNUNET_YES to proceed traversal, GNUNET_NO to stop. */ typedef int (*REGEX_INTERNAL_traverse_check) (void *cls, struct REGEX_INTERNAL_State * s, struct REGEX_INTERNAL_Transition * t); /** * Function that is called with each state, when traversing an automaton. * * @param cls closure. * @param count current count of the state, from 0 to a->state_count -1. * @param s state. */ typedef void (*REGEX_INTERNAL_traverse_action) (void *cls, const unsigned int count, struct REGEX_INTERNAL_State * s); /** * Traverses the given automaton using depth-first-search (DFS) from it's start * state, visiting all reachable states and calling 'action' on each one of * them. * * @param a automaton to be traversed. * @param start start state, pass a->start or NULL to traverse the whole automaton. * @param check function that is checked before advancing on each transition * in the DFS. * @param check_cls closure for check. * @param action action to be performed on each state. * @param action_cls closure for action */ void REGEX_INTERNAL_automaton_traverse (const struct REGEX_INTERNAL_Automaton *a, struct REGEX_INTERNAL_State *start, REGEX_INTERNAL_traverse_check check, void *check_cls, REGEX_INTERNAL_traverse_action action, void *action_cls); /** * Get the canonical regex of the given automaton. * When constructing the automaton a proof is computed for each state, * consisting of the regular expression leading to this state. A complete * regex for the automaton can be computed by combining these proofs. * As of now this function is only useful for testing. * * @param a automaton for which the canonical regex should be returned. * * @return canonical regex string. */ const char * REGEX_INTERNAL_get_canonical_regex (struct REGEX_INTERNAL_Automaton *a); /** * Get the number of transitions that are contained in the given automaton. * * @param a automaton for which the number of transitions should be returned. * * @return number of transitions in the given automaton. */ unsigned int REGEX_INTERNAL_get_transition_count (struct REGEX_INTERNAL_Automaton *a); /** * Context that contains an id counter for states and transitions as well as a * DLL of automatons used as a stack for NFA construction. */ struct REGEX_INTERNAL_Context { /** * Unique state id. */ unsigned int state_id; /** * Unique transition id. */ unsigned int transition_id; /** * DLL of REGEX_INTERNAL_Automaton's used as a stack. */ struct REGEX_INTERNAL_Automaton *stack_head; /** * DLL of REGEX_INTERNAL_Automaton's used as a stack. */ struct REGEX_INTERNAL_Automaton *stack_tail; }; /** * Adds multi-strided transitions to the given 'dfa'. * * @param regex_ctx regex context needed to add transitions to the automaton. * @param dfa DFA to which the multi strided transitions should be added. * @param stride_len length of the strides. */ void REGEX_INTERNAL_dfa_add_multi_strides (struct REGEX_INTERNAL_Context *regex_ctx, struct REGEX_INTERNAL_Automaton *dfa, const unsigned int stride_len); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/regex/gnunet-service-regex.c0000644000175000017500000002404312307322113016122 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/gnunet-service-regex.c * @brief service to advertise capabilities described as regex and to * lookup capabilities by regex * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "regex_internal_lib.h" #include "regex_ipc.h" /** * Information about one of our clients. */ struct ClientEntry { /** * Kept in DLL. */ struct ClientEntry *next; /** * Kept in DLL. */ struct ClientEntry *prev; /** * Handle identifying the client. */ struct GNUNET_SERVER_Client *client; /** * Search handle (if this client is searching). */ struct REGEX_INTERNAL_Search *sh; /** * Announcement handle (if this client is announcing). */ struct REGEX_INTERNAL_Announcement *ah; /** * Refresh frequency for announcements. */ struct GNUNET_TIME_Relative frequency; /** * Task for re-announcing. */ GNUNET_SCHEDULER_TaskIdentifier refresh_task; }; /** * Connection to the DHT. */ static struct GNUNET_DHT_Handle *dht; /** * Handle for doing statistics. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Head of list of clients. */ static struct ClientEntry *client_head; /** * End of list of clients. */ static struct ClientEntry *client_tail; /** * Our notification context, used to send back results to the client. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Private key for this peer. */ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_DHT_disconnect (dht); dht = NULL; GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; GNUNET_free (my_private_key); my_private_key = NULL; } /** * A client disconnected. Remove all of its data structure entries. * * @param cls closure, NULL * @param client identification of the client */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ClientEntry *ce; struct ClientEntry *nx; nx = client_head; for (ce = nx; NULL != ce; ce = nx) { nx = ce->next; if (ce->client == client) { if (GNUNET_SCHEDULER_NO_TASK != ce->refresh_task) { GNUNET_SCHEDULER_cancel (ce->refresh_task); ce->refresh_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != ce->ah) { REGEX_INTERNAL_announce_cancel (ce->ah); ce->ah = NULL; } if (NULL != ce->sh) { REGEX_INTERNAL_search_cancel (ce->sh); ce->sh = NULL; } GNUNET_CONTAINER_DLL_remove (client_head, client_tail, ce); GNUNET_free (ce); } } } /** * Periodic task to refresh our announcement of the regex. * * @param cls the 'struct ClientEntry' of the client that triggered the * announcement * @param tc scheduler context */ static void reannounce (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ClientEntry *ce = cls; REGEX_INTERNAL_reannounce (ce->ah); ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency, &reannounce, ce); } /** * Handle ANNOUNCE message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_announce (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct AnnounceMessage *am; const char *regex; struct ClientEntry *ce; uint16_t size; size = ntohs (message->size); am = (const struct AnnounceMessage *) message; regex = (const char *) &am[1]; if ( (size <= sizeof (struct AnnounceMessage)) || ('\0' != regex[size - sizeof (struct AnnounceMessage) - 1]) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } ce = GNUNET_new (struct ClientEntry); ce->client = client; ce->frequency = GNUNET_TIME_relative_ntoh (am->refresh_delay); ce->refresh_task = GNUNET_SCHEDULER_add_delayed (ce->frequency, &reannounce, ce); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to announce regex `%s' every %s\n", regex, GNUNET_STRINGS_relative_time_to_string (ce->frequency, GNUNET_NO)); ce->ah = REGEX_INTERNAL_announce (dht, my_private_key, regex, ntohs (am->compression), stats); if (NULL == ce->ah) { GNUNET_break (0); GNUNET_SCHEDULER_cancel (ce->refresh_task); GNUNET_free (ce); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ce); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle result, pass it back to the client. * * @param cls the struct ClientEntry of the client searching * @param id Peer providing a regex that matches the string. * @param get_path Path of the get request. * @param get_path_length Lenght of get_path. * @param put_path Path of the put request. * @param put_path_length Length of the put_path. */ static void handle_search_result (void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length) { struct ClientEntry *ce = cls; struct ResultMessage *result; struct GNUNET_PeerIdentity *gp; uint16_t size; if ( (get_path_length >= 65536) || (put_path_length >= 65536) || ( (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity)) + sizeof (struct ResultMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } size = (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity) + sizeof (struct ResultMessage); result = GNUNET_malloc (size); result->header.size = htons (size); result->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_RESULT); result->get_path_length = htons ((uint16_t) get_path_length); result->put_path_length = htons ((uint16_t) put_path_length); result->id = *id; gp = &result->id; memcpy (&gp[1], get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); memcpy (&gp[1 + get_path_length], put_path, put_path_length * sizeof (struct GNUNET_PeerIdentity)); GNUNET_SERVER_notification_context_unicast (nc, ce->client, &result->header, GNUNET_NO); GNUNET_free (result); } /** * Handle SEARCH message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_search (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct RegexSearchMessage *sm; const char *string; struct ClientEntry *ce; uint16_t size; size = ntohs (message->size); sm = (const struct RegexSearchMessage *) message; string = (const char *) &sm[1]; if ( (size <= sizeof (struct RegexSearchMessage)) || ('\0' != string[size - sizeof (struct RegexSearchMessage) - 1]) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } ce = GNUNET_new (struct ClientEntry); ce->client = client; ce->sh = REGEX_INTERNAL_search (dht, string, &handle_search_result, ce, stats); if (NULL == ce->sh) { GNUNET_break (0); GNUNET_free (ce); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ce); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Process regex requests. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_announce, NULL, GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE, 0}, {&handle_search, NULL, GNUNET_MESSAGE_TYPE_REGEX_SEARCH, 0}, {NULL, NULL, 0, 0} }; my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); if (NULL == my_private_key) { GNUNET_SCHEDULER_shutdown (); return; } dht = GNUNET_DHT_connect (cfg, 1024); if (NULL == dht) { GNUNET_free (my_private_key); my_private_key = NULL; GNUNET_SCHEDULER_shutdown (); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, NULL); nc = GNUNET_SERVER_notification_context_create (server, 1); stats = GNUNET_STATISTICS_create ("regex", cfg); GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); } /** * The main function for the regex service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "regex", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-regex.c */ gnunet-0.10.1/src/regex/regex_internal.c0000644000175000017500000027670412255010511015075 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/regex/regex_internal.c * @brief library to create Deterministic Finite Automatons (DFAs) from regular * expressions (regexes). * @author Maximilian Szengel */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_regex_service.h" #include "regex_internal_lib.h" #include "regex_internal.h" /** * Set this to GNUNET_YES to enable state naming. Used to debug NFA->DFA * creation. Disabled by default for better performance. */ #define REGEX_DEBUG_DFA GNUNET_NO /** * Set of states using MDLL API. */ struct REGEX_INTERNAL_StateSet_MDLL { /** * MDLL of states. */ struct REGEX_INTERNAL_State *head; /** * MDLL of states. */ struct REGEX_INTERNAL_State *tail; /** * Length of the MDLL. */ unsigned int len; }; /** * Append state to the given StateSet ' * * @param set set to be modified * @param state state to be appended */ static void state_set_append (struct REGEX_INTERNAL_StateSet *set, struct REGEX_INTERNAL_State *state) { if (set->off == set->size) GNUNET_array_grow (set->states, set->size, set->size * 2 + 4); set->states[set->off++] = state; } /** * Compare two strings for equality. If either is NULL they are not equal. * * @param str1 first string for comparison. * @param str2 second string for comparison. * * @return 0 if the strings are the same or both NULL, 1 or -1 if not. */ static int nullstrcmp (const char *str1, const char *str2) { if ((NULL == str1) != (NULL == str2)) return -1; if ((NULL == str1) && (NULL == str2)) return 0; return strcmp (str1, str2); } /** * Adds a transition from one state to another on 'label'. Does not add * duplicate states. * * @param ctx context * @param from_state starting state for the transition * @param label transition label * @param to_state state to where the transition should point to */ static void state_add_transition (struct REGEX_INTERNAL_Context *ctx, struct REGEX_INTERNAL_State *from_state, const char *label, struct REGEX_INTERNAL_State *to_state) { struct REGEX_INTERNAL_Transition *t; struct REGEX_INTERNAL_Transition *oth; if (NULL == from_state) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create Transition.\n"); return; } /* Do not add duplicate state transitions */ for (t = from_state->transitions_head; NULL != t; t = t->next) { if (t->to_state == to_state && 0 == nullstrcmp (t->label, label) && t->from_state == from_state) return; } /* sort transitions by label */ for (oth = from_state->transitions_head; NULL != oth; oth = oth->next) { if (0 < nullstrcmp (oth->label, label)) break; } t = GNUNET_new (struct REGEX_INTERNAL_Transition); if (NULL != ctx) t->id = ctx->transition_id++; if (NULL != label) t->label = GNUNET_strdup (label); else t->label = NULL; t->to_state = to_state; t->from_state = from_state; /* Add outgoing transition to 'from_state' */ from_state->transition_count++; GNUNET_CONTAINER_DLL_insert_before (from_state->transitions_head, from_state->transitions_tail, oth, t); } /** * Remove a 'transition' from 'state'. * * @param state state from which the to-be-removed transition originates. * @param transition transition that should be removed from state 'state'. */ static void state_remove_transition (struct REGEX_INTERNAL_State *state, struct REGEX_INTERNAL_Transition *transition) { if (NULL == state || NULL == transition) return; if (transition->from_state != state) return; GNUNET_free_non_null (transition->label); state->transition_count--; GNUNET_CONTAINER_DLL_remove (state->transitions_head, state->transitions_tail, transition); GNUNET_free (transition); } /** * Compare two states. Used for sorting. * * @param a first state * @param b second state * * @return an integer less than, equal to, or greater than zero * if the first argument is considered to be respectively * less than, equal to, or greater than the second. */ static int state_compare (const void *a, const void *b) { struct REGEX_INTERNAL_State **s1 = (struct REGEX_INTERNAL_State **) a; struct REGEX_INTERNAL_State **s2 = (struct REGEX_INTERNAL_State **) b; return (*s1)->id - (*s2)->id; } /** * Get all edges leaving state 's'. * * @param s state. * @param edges all edges leaving 's', expected to be allocated and have enough * space for s->transitions_count elements. * * @return number of edges. */ static unsigned int state_get_edges (struct REGEX_INTERNAL_State *s, struct REGEX_BLOCK_Edge *edges) { struct REGEX_INTERNAL_Transition *t; unsigned int count; if (NULL == s) return 0; count = 0; for (t = s->transitions_head; NULL != t; t = t->next) { if (NULL != t->to_state) { edges[count].label = t->label; edges[count].destination = t->to_state->hash; count++; } } return count; } /** * Compare to state sets by comparing the id's of the states that are contained * in each set. Both sets are expected to be sorted by id! * * @param sset1 first state set * @param sset2 second state set * @return 0 if the sets are equal, otherwise non-zero */ static int state_set_compare (struct REGEX_INTERNAL_StateSet *sset1, struct REGEX_INTERNAL_StateSet *sset2) { int result; unsigned int i; if (NULL == sset1 || NULL == sset2) return 1; result = sset1->off - sset2->off; if (result < 0) return -1; if (result > 0) return 1; for (i = 0; i < sset1->off; i++) if (0 != (result = state_compare (&sset1->states[i], &sset2->states[i]))) break; return result; } /** * Clears the given StateSet 'set' * * @param set set to be cleared */ static void state_set_clear (struct REGEX_INTERNAL_StateSet *set) { GNUNET_array_grow (set->states, set->size, 0); set->off = 0; } /** * Clears an automaton fragment. Does not destroy the states inside the * automaton. * * @param a automaton to be cleared */ static void automaton_fragment_clear (struct REGEX_INTERNAL_Automaton *a) { if (NULL == a) return; a->start = NULL; a->end = NULL; a->states_head = NULL; a->states_tail = NULL; a->state_count = 0; GNUNET_free (a); } /** * Frees the memory used by State 's' * * @param s state that should be destroyed */ static void automaton_destroy_state (struct REGEX_INTERNAL_State *s) { struct REGEX_INTERNAL_Transition *t; struct REGEX_INTERNAL_Transition *next_t; if (NULL == s) return; GNUNET_free_non_null (s->name); GNUNET_free_non_null (s->proof); state_set_clear (&s->nfa_set); for (t = s->transitions_head; NULL != t; t = next_t) { next_t = t->next; state_remove_transition (s, t); } GNUNET_free (s); } /** * Remove a state from the given automaton 'a'. Always use this function when * altering the states of an automaton. Will also remove all transitions leading * to this state, before destroying it. * * @param a automaton * @param s state to remove */ static void automaton_remove_state (struct REGEX_INTERNAL_Automaton *a, struct REGEX_INTERNAL_State *s) { struct REGEX_INTERNAL_State *s_check; struct REGEX_INTERNAL_Transition *t_check; struct REGEX_INTERNAL_Transition *t_check_next; if (NULL == a || NULL == s) return; /* remove all transitions leading to this state */ for (s_check = a->states_head; NULL != s_check; s_check = s_check->next) { for (t_check = s_check->transitions_head; NULL != t_check; t_check = t_check_next) { t_check_next = t_check->next; if (t_check->to_state == s) state_remove_transition (s_check, t_check); } } /* remove state */ GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s); a->state_count--; automaton_destroy_state (s); } /** * Merge two states into one. Will merge 's1' and 's2' into 's1' and destroy * 's2'. 's1' will contain all (non-duplicate) outgoing transitions of 's2'. * * @param ctx context * @param a automaton * @param s1 first state * @param s2 second state, will be destroyed */ static void automaton_merge_states (struct REGEX_INTERNAL_Context *ctx, struct REGEX_INTERNAL_Automaton *a, struct REGEX_INTERNAL_State *s1, struct REGEX_INTERNAL_State *s2) { struct REGEX_INTERNAL_State *s_check; struct REGEX_INTERNAL_Transition *t_check; struct REGEX_INTERNAL_Transition *t; struct REGEX_INTERNAL_Transition *t_next; int is_dup; if (s1 == s2) return; /* 1. Make all transitions pointing to s2 point to s1, unless this transition * does not already exists, if it already exists remove transition. */ for (s_check = a->states_head; NULL != s_check; s_check = s_check->next) { for (t_check = s_check->transitions_head; NULL != t_check; t_check = t_next) { t_next = t_check->next; if (s2 == t_check->to_state) { is_dup = GNUNET_NO; for (t = t_check->from_state->transitions_head; NULL != t; t = t->next) { if (t->to_state == s1 && 0 == strcmp (t_check->label, t->label)) is_dup = GNUNET_YES; } if (GNUNET_NO == is_dup) t_check->to_state = s1; else state_remove_transition (t_check->from_state, t_check); } } } /* 2. Add all transitions from s2 to sX to s1 */ for (t_check = s2->transitions_head; NULL != t_check; t_check = t_check->next) { if (t_check->to_state != s1) state_add_transition (ctx, s1, t_check->label, t_check->to_state); } /* 3. Rename s1 to {s1,s2} */ #if REGEX_DEBUG_DFA char *new_name; new_name = s1->name; GNUNET_asprintf (&s1->name, "{%s,%s}", new_name, s2->name); GNUNET_free (new_name); #endif /* remove state */ GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s2); a->state_count--; automaton_destroy_state (s2); } /** * Add a state to the automaton 'a', always use this function to alter the * states DLL of the automaton. * * @param a automaton to add the state to * @param s state that should be added */ static void automaton_add_state (struct REGEX_INTERNAL_Automaton *a, struct REGEX_INTERNAL_State *s) { GNUNET_CONTAINER_DLL_insert (a->states_head, a->states_tail, s); a->state_count++; } /** * Depth-first traversal (DFS) of all states that are reachable from state * 's'. Performs 'action' on each visited state. * * @param s start state. * @param marks an array of size a->state_count to remember which state was * already visited. * @param count current count of the state. * @param check function that is checked before advancing on each transition * in the DFS. * @param check_cls closure for check. * @param action action to be performed on each state. * @param action_cls closure for action. */ static void automaton_state_traverse (struct REGEX_INTERNAL_State *s, int *marks, unsigned int *count, REGEX_INTERNAL_traverse_check check, void *check_cls, REGEX_INTERNAL_traverse_action action, void *action_cls) { struct REGEX_INTERNAL_Transition *t; if (GNUNET_YES == marks[s->traversal_id]) return; marks[s->traversal_id] = GNUNET_YES; if (NULL != action) action (action_cls, *count, s); (*count)++; for (t = s->transitions_head; NULL != t; t = t->next) { if (NULL == check || (NULL != check && GNUNET_YES == check (check_cls, s, t))) { automaton_state_traverse (t->to_state, marks, count, check, check_cls, action, action_cls); } } } /** * Traverses the given automaton using depth-first-search (DFS) from it's start * state, visiting all reachable states and calling 'action' on each one of * them. * * @param a automaton to be traversed. * @param start start state, pass a->start or NULL to traverse the whole automaton. * @param check function that is checked before advancing on each transition * in the DFS. * @param check_cls closure for check. * @param action action to be performed on each state. * @param action_cls closure for action */ void REGEX_INTERNAL_automaton_traverse (const struct REGEX_INTERNAL_Automaton *a, struct REGEX_INTERNAL_State *start, REGEX_INTERNAL_traverse_check check, void *check_cls, REGEX_INTERNAL_traverse_action action, void *action_cls) { unsigned int count; struct REGEX_INTERNAL_State *s; if (NULL == a || 0 == a->state_count) return; int marks[a->state_count]; for (count = 0, s = a->states_head; NULL != s && count < a->state_count; s = s->next, count++) { s->traversal_id = count; marks[s->traversal_id] = GNUNET_NO; } count = 0; if (NULL == start) s = a->start; else s = start; automaton_state_traverse (s, marks, &count, check, check_cls, action, action_cls); } /** * String container for faster string operations. */ struct StringBuffer { /** * Buffer holding the string (may start in the middle!); * NOT 0-terminated! */ char *sbuf; /** * Allocated buffer. */ char *abuf; /** * Length of the string in the buffer. */ size_t slen; /** * Number of bytes allocated for 'sbuf' */ unsigned int blen; /** * Buffer currently represents "NULL" (not the empty string!) */ int16_t null_flag; /** * If this entry is part of the last/current generation array, * this flag is GNUNET_YES if the last and current generation are * identical (and thus copying is unnecessary if the value didn't * change). This is used in an optimization that improves * performance by about 1% --- if we use int16_t here. With just * "int" for both flags, performance drops (on my system) significantly, * most likely due to increased cache misses. */ int16_t synced; }; /** * Compare two strings for equality. If either is NULL they are not equal. * * @param s1 first string for comparison. * @param s2 second string for comparison. * * @return 0 if the strings are the same or both NULL, 1 or -1 if not. */ static int sb_nullstrcmp (const struct StringBuffer *s1, const struct StringBuffer *s2) { if ( (GNUNET_YES == s1->null_flag) && (GNUNET_YES == s2->null_flag) ) return 0; if ( (GNUNET_YES == s1->null_flag) || (GNUNET_YES == s2->null_flag) ) return -1; if (s1->slen != s2->slen) return -1; return memcmp (s1->sbuf, s2->sbuf, s1->slen); } /** * Compare two strings for equality. * * @param s1 first string for comparison. * @param s2 second string for comparison. * * @return 0 if the strings are the same, 1 or -1 if not. */ static int sb_strcmp (const struct StringBuffer *s1, const struct StringBuffer *s2) { if (s1->slen != s2->slen) return -1; return memcmp (s1->sbuf, s2->sbuf, s1->slen); } /** * Reallocate the buffer of 'ret' to fit 'nlen' characters; * move the existing string to the beginning of the new buffer. * * @param ret current buffer, to be updated * @param nlen target length for the buffer, must be at least ret->slen */ static void sb_realloc (struct StringBuffer *ret, size_t nlen) { char *old; GNUNET_assert (nlen >= ret->slen); old = ret->abuf; ret->abuf = GNUNET_malloc (nlen); ret->blen = nlen; memcpy (ret->abuf, ret->sbuf, ret->slen); ret->sbuf = ret->abuf; GNUNET_free_non_null (old); } /** * Append a string. * * @param ret where to write the result * @param sarg string to append */ static void sb_append (struct StringBuffer *ret, const struct StringBuffer *sarg) { if (GNUNET_YES == ret->null_flag) ret->slen = 0; ret->null_flag = GNUNET_NO; if (ret->blen < sarg->slen + ret->slen) sb_realloc (ret, ret->blen + sarg->slen + 128); memcpy (&ret->sbuf[ret->slen], sarg->sbuf, sarg->slen); ret->slen += sarg->slen; } /** * Append a C string. * * @param ret where to write the result * @param cstr string to append */ static void sb_append_cstr (struct StringBuffer *ret, const char *cstr) { size_t cstr_len = strlen (cstr); if (GNUNET_YES == ret->null_flag) ret->slen = 0; ret->null_flag = GNUNET_NO; if (ret->blen < cstr_len + ret->slen) sb_realloc (ret, ret->blen + cstr_len + 128); memcpy (&ret->sbuf[ret->slen], cstr, cstr_len); ret->slen += cstr_len; } /** * Wrap a string buffer, that is, set ret to the format string * which contains an "%s" which is to be replaced with the original * content of 'ret'. Note that optimizing this function is not * really worth it, it is rarely called. * * @param ret where to write the result and take the input for %.*s from * @param format format string, fprintf-style, with exactly one "%.*s" * @param extra_chars how long will the result be, in addition to 'sarg' length */ static void sb_wrap (struct StringBuffer *ret, const char *format, size_t extra_chars) { char *temp; if (GNUNET_YES == ret->null_flag) ret->slen = 0; ret->null_flag = GNUNET_NO; temp = GNUNET_malloc (ret->slen + extra_chars + 1); GNUNET_snprintf (temp, ret->slen + extra_chars + 1, format, (int) ret->slen, ret->sbuf); GNUNET_free_non_null (ret->abuf); ret->abuf = temp; ret->sbuf = temp; ret->blen = ret->slen + extra_chars + 1; ret->slen = ret->slen + extra_chars; } /** * Format a string buffer. Note that optimizing this function is not * really worth it, it is rarely called. * * @param ret where to write the result * @param format format string, fprintf-style, with exactly one "%.*s" * @param extra_chars how long will the result be, in addition to 'sarg' length * @param sarg string to print into the format */ static void sb_printf1 (struct StringBuffer *ret, const char *format, size_t extra_chars, const struct StringBuffer *sarg) { if (ret->blen < sarg->slen + extra_chars + 1) sb_realloc (ret, sarg->slen + extra_chars + 1); ret->null_flag = GNUNET_NO; ret->sbuf = ret->abuf; ret->slen = sarg->slen + extra_chars; GNUNET_snprintf (ret->sbuf, ret->blen, format, (int) sarg->slen, sarg->sbuf); } /** * Format a string buffer. * * @param ret where to write the result * @param format format string, fprintf-style, with exactly two "%.*s" * @param extra_chars how long will the result be, in addition to 'sarg1/2' length * @param sarg1 first string to print into the format * @param sarg2 second string to print into the format */ static void sb_printf2 (struct StringBuffer *ret, const char *format, size_t extra_chars, const struct StringBuffer *sarg1, const struct StringBuffer *sarg2) { if (ret->blen < sarg1->slen + sarg2->slen + extra_chars + 1) sb_realloc (ret, sarg1->slen + sarg2->slen + extra_chars + 1); ret->null_flag = GNUNET_NO; ret->slen = sarg1->slen + sarg2->slen + extra_chars; ret->sbuf = ret->abuf; GNUNET_snprintf (ret->sbuf, ret->blen, format, (int) sarg1->slen, sarg1->sbuf, (int) sarg2->slen, sarg2->sbuf); } /** * Format a string buffer. Note that optimizing this function is not * really worth it, it is rarely called. * * @param ret where to write the result * @param format format string, fprintf-style, with exactly three "%.*s" * @param extra_chars how long will the result be, in addition to 'sarg1/2/3' length * @param sarg1 first string to print into the format * @param sarg2 second string to print into the format * @param sarg3 third string to print into the format */ static void sb_printf3 (struct StringBuffer *ret, const char *format, size_t extra_chars, const struct StringBuffer *sarg1, const struct StringBuffer *sarg2, const struct StringBuffer *sarg3) { if (ret->blen < sarg1->slen + sarg2->slen + sarg3->slen + extra_chars + 1) sb_realloc (ret, sarg1->slen + sarg2->slen + sarg3->slen + extra_chars + 1); ret->null_flag = GNUNET_NO; ret->slen = sarg1->slen + sarg2->slen + sarg3->slen + extra_chars; ret->sbuf = ret->abuf; GNUNET_snprintf (ret->sbuf, ret->blen, format, (int) sarg1->slen, sarg1->sbuf, (int) sarg2->slen, sarg2->sbuf, (int) sarg3->slen, sarg3->sbuf); } /** * Free resources of the given string buffer. * * @param sb buffer to free (actual pointer is not freed, as they * should not be individually allocated) */ static void sb_free (struct StringBuffer *sb) { GNUNET_array_grow (sb->abuf, sb->blen, 0); sb->slen = 0; sb->sbuf = NULL; sb->null_flag= GNUNET_YES; } /** * Copy the given string buffer from 'in' to 'out'. * * @param in input string * @param out output string */ static void sb_strdup (struct StringBuffer *out, const struct StringBuffer *in) { out->null_flag = in->null_flag; if (GNUNET_YES == out->null_flag) return; if (out->blen < in->slen) { GNUNET_array_grow (out->abuf, out->blen, in->slen); } out->sbuf = out->abuf; out->slen = in->slen; memcpy (out->sbuf, in->sbuf, out->slen); } /** * Copy the given string buffer from 'in' to 'out'. * * @param cstr input string * @param out output string */ static void sb_strdup_cstr (struct StringBuffer *out, const char *cstr) { if (NULL == cstr) { out->null_flag = GNUNET_YES; return; } out->null_flag = GNUNET_NO; out->slen = strlen (cstr); if (out->blen < out->slen) { GNUNET_array_grow (out->abuf, out->blen, out->slen); } out->sbuf = out->abuf; memcpy (out->sbuf, cstr, out->slen); } /** * Check if the given string 'str' needs parentheses around it when * using it to generate a regex. * * @param str string * * @return GNUNET_YES if parentheses are needed, GNUNET_NO otherwise */ static int needs_parentheses (const struct StringBuffer *str) { size_t slen; const char *op; const char *cl; const char *pos; const char *end; unsigned int cnt; if ((GNUNET_YES == str->null_flag) || ((slen = str->slen) < 2)) return GNUNET_NO; pos = str->sbuf; if ('(' != pos[0]) return GNUNET_YES; end = str->sbuf + slen; cnt = 1; pos++; while (cnt > 0) { cl = memchr (pos, ')', end - pos); if (NULL == cl) { GNUNET_break (0); return GNUNET_YES; } /* while '(' before ')', count opening parens */ while ( (NULL != (op = memchr (pos, '(', end - pos))) && (op < cl) ) { cnt++; pos = op + 1; } /* got ')' first */ cnt--; pos = cl + 1; } return (*pos == '\0') ? GNUNET_NO : GNUNET_YES; } /** * Remove parentheses surrounding string 'str'. * Example: "(a)" becomes "a", "(a|b)|(a|c)" stays the same. * You need to GNUNET_free the returned string. * * @param str string, modified to contain a * @return string without surrounding parentheses, string 'str' if no preceding * epsilon could be found, NULL if 'str' was NULL */ static void remove_parentheses (struct StringBuffer *str) { size_t slen; const char *pos; const char *end; const char *sbuf; const char *op; const char *cp; unsigned int cnt; if (0) return; sbuf = str->sbuf; if ( (GNUNET_YES == str->null_flag) || (1 >= (slen = str->slen)) || ('(' != str->sbuf[0]) || (')' != str->sbuf[slen - 1]) ) return; cnt = 0; pos = &sbuf[1]; end = &sbuf[slen - 1]; op = memchr (pos, '(', end - pos); cp = memchr (pos, ')', end - pos); while (NULL != cp) { while ( (NULL != op) && (op < cp) ) { cnt++; pos = op + 1; op = memchr (pos, '(', end - pos); } while ( (NULL != cp) && ( (NULL == op) || (cp < op) ) ) { if (0 == cnt) return; /* can't strip parens */ cnt--; pos = cp + 1; cp = memchr (pos, ')', end - pos); } } if (0 != cnt) { GNUNET_break (0); return; } str->sbuf++; str->slen -= 2; } /** * Check if the string 'str' starts with an epsilon (empty string). * Example: "(|a)" is starting with an epsilon. * * @param str string to test * * @return 0 if str has no epsilon, 1 if str starts with '(|' and ends with ')' */ static int has_epsilon (const struct StringBuffer *str) { return (GNUNET_YES != str->null_flag) && (0 < str->slen) && ('(' == str->sbuf[0]) && ('|' == str->sbuf[1]) && (')' == str->sbuf[str->slen - 1]); } /** * Remove an epsilon from the string str. Where epsilon is an empty string * Example: str = "(|a|b|c)", result: "a|b|c" * The returned string needs to be freed. * * @param str original string * @param ret where to return string without preceding epsilon, string 'str' if no preceding * epsilon could be found, NULL if 'str' was NULL */ static void remove_epsilon (const struct StringBuffer *str, struct StringBuffer *ret) { if (GNUNET_YES == str->null_flag) { ret->null_flag = GNUNET_YES; return; } if ( (str->slen > 1) && ('(' == str->sbuf[0]) && ('|' == str->sbuf[1]) && (')' == str->sbuf[str->slen - 1]) ) { /* remove epsilon */ if (ret->blen < str->slen - 3) { GNUNET_array_grow (ret->abuf, ret->blen, str->slen - 3); } ret->sbuf = ret->abuf; ret->slen = str->slen - 3; memcpy (ret->sbuf, &str->sbuf[2], ret->slen); return; } sb_strdup (ret, str); } /** * Compare n bytes of 'str1' and 'str2' * * @param str1 first string to compare * @param str2 second string for comparison * @param n number of bytes to compare * * @return -1 if any of the strings is NULL, 0 if equal, non 0 otherwise */ static int sb_strncmp (const struct StringBuffer *str1, const struct StringBuffer *str2, size_t n) { size_t max; if ( (str1->slen != str2->slen) && ( (str1->slen < n) || (str2->slen < n) ) ) return -1; max = GNUNET_MAX (str1->slen, str2->slen); if (max > n) max = n; return memcmp (str1->sbuf, str2->sbuf, max); } /** * Compare n bytes of 'str1' and 'str2' * * @param str1 first string to compare * @param str2 second C string for comparison * @param n number of bytes to compare (and length of str2) * * @return -1 if any of the strings is NULL, 0 if equal, non 0 otherwise */ static int sb_strncmp_cstr (const struct StringBuffer *str1, const char *str2, size_t n) { if (str1->slen < n) return -1; return memcmp (str1->sbuf, str2, n); } /** * Initialize string buffer for storing strings of up to n * characters. * * @param sb buffer to initialize * @param n desired target length */ static void sb_init (struct StringBuffer *sb, size_t n) { sb->null_flag = GNUNET_NO; sb->abuf = sb->sbuf = (0 == n) ? NULL : GNUNET_malloc (n); sb->blen = n; sb->slen = 0; } /** * Compare 'str1', starting from position 'k', with whole 'str2' * * @param str1 first string to compare, starting from position 'k' * @param str2 second string for comparison * @param k starting position in 'str1' * * @return -1 if any of the strings is NULL, 0 if equal, non 0 otherwise */ static int sb_strkcmp (const struct StringBuffer *str1, const struct StringBuffer *str2, size_t k) { if ( (GNUNET_YES == str1->null_flag) || (GNUNET_YES == str2->null_flag) || (k > str1->slen) || (str1->slen - k != str2->slen) ) return -1; return memcmp (&str1->sbuf[k], str2->sbuf, str2->slen); } /** * Helper function used as 'action' in 'REGEX_INTERNAL_automaton_traverse' * function to create the depth-first numbering of the states. * * @param cls states array. * @param count current state counter. * @param s current state. */ static void number_states (void *cls, const unsigned int count, struct REGEX_INTERNAL_State *s) { struct REGEX_INTERNAL_State **states = cls; s->dfs_id = count; if (NULL != states) states[count] = s; } #define PRIS(a) \ ((GNUNET_YES == a.null_flag) ? 6 : (int) a.slen), \ ((GNUNET_YES == a.null_flag) ? "(null)" : a.sbuf) /** * Construct the regular expression given the inductive step, * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* * R^{(k-1)}_{kj}, and simplify the resulting expression saved in R_cur_ij. * * @param R_last_ij value of $R^{(k-1)_{ij}. * @param R_last_ik value of $R^{(k-1)_{ik}. * @param R_last_kk value of $R^{(k-1)_{kk}. * @param R_last_kj value of $R^{(k-1)_{kj}. * @param R_cur_ij result for this inductive step is saved in R_cur_ij, R_cur_ij * is expected to be NULL when called! * @param R_cur_l optimization -- kept between iterations to avoid realloc * @param R_cur_r optimization -- kept between iterations to avoid realloc */ static void automaton_create_proofs_simplify (const struct StringBuffer *R_last_ij, const struct StringBuffer *R_last_ik, const struct StringBuffer *R_last_kk, const struct StringBuffer *R_last_kj, struct StringBuffer *R_cur_ij, struct StringBuffer *R_cur_l, struct StringBuffer *R_cur_r) { struct StringBuffer R_temp_ij; struct StringBuffer R_temp_ik; struct StringBuffer R_temp_kj; struct StringBuffer R_temp_kk; int eps_check; int ij_ik_cmp; int ij_kj_cmp; int ik_kk_cmp; int kk_kj_cmp; int clean_ik_kk_cmp; int clean_kk_kj_cmp; size_t length; size_t length_l; size_t length_r; /* * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj} * R_last == R^{(k-1)}, R_cur == R^{(k)} * R_cur_ij = R_cur_l | R_cur_r * R_cur_l == R^{(k-1)}_{ij} * R_cur_r == R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj} */ if ( (GNUNET_YES == R_last_ij->null_flag) && ( (GNUNET_YES == R_last_ik->null_flag) || (GNUNET_YES == R_last_kj->null_flag))) { /* R^{(k)}_{ij} = N | N */ R_cur_ij->null_flag = GNUNET_YES; R_cur_ij->synced = GNUNET_NO; return; } if ( (GNUNET_YES == R_last_ik->null_flag) || (GNUNET_YES == R_last_kj->null_flag) ) { /* R^{(k)}_{ij} = R^{(k-1)}_{ij} | N */ if (GNUNET_YES == R_last_ij->synced) { R_cur_ij->synced = GNUNET_YES; R_cur_ij->null_flag = GNUNET_NO; return; } R_cur_ij->synced = GNUNET_YES; sb_strdup (R_cur_ij, R_last_ij); return; } R_cur_ij->synced = GNUNET_NO; /* $R^{(k)}_{ij} = N | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj} OR * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj} */ R_cur_r->null_flag = GNUNET_YES; R_cur_r->slen = 0; R_cur_l->null_flag = GNUNET_YES; R_cur_l->slen = 0; /* cache results from strcmp, we might need these many times */ ij_kj_cmp = sb_nullstrcmp (R_last_ij, R_last_kj); ij_ik_cmp = sb_nullstrcmp (R_last_ij, R_last_ik); ik_kk_cmp = sb_nullstrcmp (R_last_ik, R_last_kk); kk_kj_cmp = sb_nullstrcmp (R_last_kk, R_last_kj); /* Assign R_temp_(ik|kk|kj) to R_last[][] and remove epsilon as well * as parentheses, so we can better compare the contents */ memset (&R_temp_ij, 0, sizeof (struct StringBuffer)); memset (&R_temp_ik, 0, sizeof (struct StringBuffer)); memset (&R_temp_kk, 0, sizeof (struct StringBuffer)); memset (&R_temp_kj, 0, sizeof (struct StringBuffer)); remove_epsilon (R_last_ik, &R_temp_ik); remove_epsilon (R_last_kk, &R_temp_kk); remove_epsilon (R_last_kj, &R_temp_kj); remove_parentheses (&R_temp_ik); remove_parentheses (&R_temp_kk); remove_parentheses (&R_temp_kj); clean_ik_kk_cmp = sb_nullstrcmp (R_last_ik, &R_temp_kk); clean_kk_kj_cmp = sb_nullstrcmp (&R_temp_kk, R_last_kj); /* construct R_cur_l (and, if necessary R_cur_r) */ if (GNUNET_YES != R_last_ij->null_flag) { /* Assign R_temp_ij to R_last_ij and remove epsilon as well * as parentheses, so we can better compare the contents */ remove_epsilon (R_last_ij, &R_temp_ij); remove_parentheses (&R_temp_ij); if ( (0 == sb_strcmp (&R_temp_ij, &R_temp_ik)) && (0 == sb_strcmp (&R_temp_ik, &R_temp_kk)) && (0 == sb_strcmp (&R_temp_kk, &R_temp_kj)) ) { if (0 == R_temp_ij.slen) { R_cur_r->null_flag = GNUNET_NO; } else if ((0 == sb_strncmp_cstr (R_last_ij, "(|", 2)) || (0 == sb_strncmp_cstr (R_last_ik, "(|", 2) && 0 == sb_strncmp_cstr (R_last_kj, "(|", 2))) { /* * a|(e|a)a*(e|a) = a* * a|(e|a)(e|a)*(e|a) = a* * (e|a)|aa*a = a* * (e|a)|aa*(e|a) = a* * (e|a)|(e|a)a*a = a* * (e|a)|(e|a)a*(e|a) = a* * (e|a)|(e|a)(e|a)*(e|a) = a* */ if (GNUNET_YES == needs_parentheses (&R_temp_ij)) sb_printf1 (R_cur_r, "(%.*s)*", 3, &R_temp_ij); else sb_printf1 (R_cur_r, "%.*s*", 1, &R_temp_ij); } else { /* * a|aa*a = a+ * a|(e|a)a*a = a+ * a|aa*(e|a) = a+ * a|(e|a)(e|a)*a = a+ * a|a(e|a)*(e|a) = a+ */ if (GNUNET_YES == needs_parentheses (&R_temp_ij)) sb_printf1 (R_cur_r, "(%.*s)+", 3, &R_temp_ij); else sb_printf1 (R_cur_r, "%.*s+", 1, &R_temp_ij); } } else if ( (0 == ij_ik_cmp) && (0 == clean_kk_kj_cmp) && (0 != clean_ik_kk_cmp) ) { /* a|ab*b = ab* */ if (0 == R_last_kk->slen) sb_strdup (R_cur_r, R_last_ij); else if (GNUNET_YES == needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "%.*s(%.*s)*", 3, R_last_ij, &R_temp_kk); else sb_printf2 (R_cur_r, "%.*s%.*s*", 1, R_last_ij, R_last_kk); R_cur_l->null_flag = GNUNET_YES; } else if ( (0 == ij_kj_cmp) && (0 == clean_ik_kk_cmp) && (0 != clean_kk_kj_cmp)) { /* a|bb*a = b*a */ if (R_last_kk->slen < 1) { sb_strdup (R_cur_r, R_last_kj); } else if (GNUNET_YES == needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "(%.*s)*%.*s", 3, &R_temp_kk, R_last_kj); else sb_printf2 (R_cur_r, "%.*s*%.*s", 1, &R_temp_kk, R_last_kj); R_cur_l->null_flag = GNUNET_YES; } else if ( (0 == ij_ik_cmp) && (0 == kk_kj_cmp) && (! has_epsilon (R_last_ij)) && has_epsilon (R_last_kk)) { /* a|a(e|b)*(e|b) = a|ab* = a|a|ab|abb|abbb|... = ab* */ if (needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "%.*s(%.*s)*", 3, R_last_ij, &R_temp_kk); else sb_printf2 (R_cur_r, "%.*s%.*s*", 1, R_last_ij, &R_temp_kk); R_cur_l->null_flag = GNUNET_YES; } else if ( (0 == ij_kj_cmp) && (0 == ik_kk_cmp) && (! has_epsilon (R_last_ij)) && has_epsilon (R_last_kk)) { /* a|(e|b)(e|b)*a = a|b*a = a|a|ba|bba|bbba|... = b*a */ if (needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "(%.*s)*%.*s", 3, &R_temp_kk, R_last_ij); else sb_printf2 (R_cur_r, "%.*s*%.*s", 1, &R_temp_kk, R_last_ij); R_cur_l->null_flag = GNUNET_YES; } else { sb_strdup (R_cur_l, R_last_ij); remove_parentheses (R_cur_l); } } else { /* we have no left side */ R_cur_l->null_flag = GNUNET_YES; } /* construct R_cur_r, if not already constructed */ if (GNUNET_YES == R_cur_r->null_flag) { length = R_temp_kk.slen - R_last_ik->slen; /* a(ba)*bx = (ab)+x */ if ( (length > 0) && (GNUNET_YES != R_last_kk->null_flag) && (0 < R_last_kk->slen) && (GNUNET_YES != R_last_kj->null_flag) && (0 < R_last_kj->slen) && (GNUNET_YES != R_last_ik->null_flag) && (0 < R_last_ik->slen) && (0 == sb_strkcmp (&R_temp_kk, R_last_ik, length)) && (0 == sb_strncmp (&R_temp_kk, R_last_kj, length)) ) { struct StringBuffer temp_a; struct StringBuffer temp_b; sb_init (&temp_a, length); sb_init (&temp_b, R_last_kj->slen - length); length_l = length; temp_a.sbuf = temp_a.abuf; memcpy (temp_a.sbuf, R_last_kj->sbuf, length_l); temp_a.slen = length_l; length_r = R_last_kj->slen - length; temp_b.sbuf = temp_b.abuf; memcpy (temp_b.sbuf, &R_last_kj->sbuf[length], length_r); temp_b.slen = length_r; /* e|(ab)+ = (ab)* */ if ( (GNUNET_YES != R_cur_l->null_flag) && (0 == R_cur_l->slen) && (0 == temp_b.slen) ) { sb_printf2 (R_cur_r, "(%.*s%.*s)*", 3, R_last_ik, &temp_a); sb_free (R_cur_l); R_cur_l->null_flag = GNUNET_YES; } else { sb_printf3 (R_cur_r, "(%.*s%.*s)+%.*s", 3, R_last_ik, &temp_a, &temp_b); } sb_free (&temp_a); sb_free (&temp_b); } else if (0 == sb_strcmp (&R_temp_ik, &R_temp_kk) && 0 == sb_strcmp (&R_temp_kk, &R_temp_kj)) { /* * (e|a)a*(e|a) = a* * (e|a)(e|a)*(e|a) = a* */ if (has_epsilon (R_last_ik) && has_epsilon (R_last_kj)) { if (needs_parentheses (&R_temp_kk)) sb_printf1 (R_cur_r, "(%.*s)*", 3, &R_temp_kk); else sb_printf1 (R_cur_r, "%.*s*", 1, &R_temp_kk); } /* aa*a = a+a */ else if ( (0 == clean_ik_kk_cmp) && (0 == clean_kk_kj_cmp) && (! has_epsilon (R_last_ik)) ) { if (needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "(%.*s)+%.*s", 3, &R_temp_kk, &R_temp_kk); else sb_printf2 (R_cur_r, "%.*s+%.*s", 1, &R_temp_kk, &R_temp_kk); } /* * (e|a)a*a = a+ * aa*(e|a) = a+ * a(e|a)*(e|a) = a+ * (e|a)a*a = a+ */ else { eps_check = (has_epsilon (R_last_ik) + has_epsilon (R_last_kk) + has_epsilon (R_last_kj)); if (1 == eps_check) { if (needs_parentheses (&R_temp_kk)) sb_printf1 (R_cur_r, "(%.*s)+", 3, &R_temp_kk); else sb_printf1 (R_cur_r, "%.*s+", 1, &R_temp_kk); } } } /* * aa*b = a+b * (e|a)(e|a)*b = a*b */ else if (0 == sb_strcmp (&R_temp_ik, &R_temp_kk)) { if (has_epsilon (R_last_ik)) { if (needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "(%.*s)*%.*s", 3, &R_temp_kk, R_last_kj); else sb_printf2 (R_cur_r, "%.*s*%.*s", 1, &R_temp_kk, R_last_kj); } else { if (needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "(%.*s)+%.*s", 3, &R_temp_kk, R_last_kj); else sb_printf2 (R_cur_r, "%.*s+%.*s", 1, &R_temp_kk, R_last_kj); } } /* * ba*a = ba+ * b(e|a)*(e|a) = ba* */ else if (0 == sb_strcmp (&R_temp_kk, &R_temp_kj)) { if (has_epsilon (R_last_kj)) { if (needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "%.*s(%.*s)*", 3, R_last_ik, &R_temp_kk); else sb_printf2 (R_cur_r, "%.*s%.*s*", 1, R_last_ik, &R_temp_kk); } else { if (needs_parentheses (&R_temp_kk)) sb_printf2 (R_cur_r, "(%.*s)+%.*s", 3, R_last_ik, &R_temp_kk); else sb_printf2 (R_cur_r, "%.*s+%.*s", 1, R_last_ik, &R_temp_kk); } } else { if (0 < R_temp_kk.slen) { if (needs_parentheses (&R_temp_kk)) { sb_printf3 (R_cur_r, "%.*s(%.*s)*%.*s", 3, R_last_ik, &R_temp_kk, R_last_kj); } else { sb_printf3 (R_cur_r, "%.*s%.*s*%.*s", 1, R_last_ik, &R_temp_kk, R_last_kj); } } else { sb_printf2 (R_cur_r, "%.*s%.*s", 0, R_last_ik, R_last_kj); } } } sb_free (&R_temp_ij); sb_free (&R_temp_ik); sb_free (&R_temp_kk); sb_free (&R_temp_kj); if ( (GNUNET_YES == R_cur_l->null_flag) && (GNUNET_YES == R_cur_r->null_flag) ) { R_cur_ij->null_flag = GNUNET_YES; return; } if ( (GNUNET_YES != R_cur_l->null_flag) && (GNUNET_YES == R_cur_r->null_flag) ) { struct StringBuffer tmp; tmp = *R_cur_ij; *R_cur_ij = *R_cur_l; *R_cur_l = tmp; return; } if ( (GNUNET_YES == R_cur_l->null_flag) && (GNUNET_YES != R_cur_r->null_flag) ) { struct StringBuffer tmp; tmp = *R_cur_ij; *R_cur_ij = *R_cur_r; *R_cur_r = tmp; return; } if (0 == sb_nullstrcmp (R_cur_l, R_cur_r)) { struct StringBuffer tmp; tmp = *R_cur_ij; *R_cur_ij = *R_cur_l; *R_cur_l = tmp; return; } sb_printf2 (R_cur_ij, "(%.*s|%.*s)", 3, R_cur_l, R_cur_r); } /** * Create proofs for all states in the given automaton. Implementation of the * algorithm descriped in chapter 3.2.1 of "Automata Theory, Languages, and * Computation 3rd Edition" by Hopcroft, Motwani and Ullman. * * Each state in the automaton gets assigned 'proof' and 'hash' (hash of the * proof) fields. The starting state will only have a valid proof/hash if it has * any incoming transitions. * * @param a automaton for which to assign proofs and hashes, must not be NULL */ static int automaton_create_proofs (struct REGEX_INTERNAL_Automaton *a) { unsigned int n = a->state_count; struct REGEX_INTERNAL_State *states[n]; struct StringBuffer *R_last; struct StringBuffer *R_cur; struct StringBuffer R_cur_r; struct StringBuffer R_cur_l; struct StringBuffer *R_swap; struct REGEX_INTERNAL_Transition *t; struct StringBuffer complete_regex; unsigned int i; unsigned int j; unsigned int k; R_last = GNUNET_malloc_large (sizeof (struct StringBuffer) * n * n); R_cur = GNUNET_malloc_large (sizeof (struct StringBuffer) * n * n); if ( (NULL == R_last) || (NULL == R_cur) ) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "malloc"); GNUNET_free_non_null (R_cur); GNUNET_free_non_null (R_last); return GNUNET_SYSERR; } /* create depth-first numbering of the states, initializes 'state' */ REGEX_INTERNAL_automaton_traverse (a, a->start, NULL, NULL, &number_states, states); for (i = 0; i < n; i++) GNUNET_assert (NULL != states[i]); for (i = 0; i < n; i++) for (j = 0; j < n; j++) R_last[i *n + j].null_flag = GNUNET_YES; /* Compute regular expressions of length "1" between each pair of states */ for (i = 0; i < n; i++) { for (t = states[i]->transitions_head; NULL != t; t = t->next) { j = t->to_state->dfs_id; if (GNUNET_YES == R_last[i * n + j].null_flag) { sb_strdup_cstr (&R_last[i * n + j], t->label); } else { sb_append_cstr (&R_last[i * n + j], "|"); sb_append_cstr (&R_last[i * n + j], t->label); } } /* add self-loop: i is reachable from i via epsilon-transition */ if (GNUNET_YES == R_last[i * n + i].null_flag) { R_last[i * n + i].slen = 0; R_last[i * n + i].null_flag = GNUNET_NO; } else { sb_wrap (&R_last[i * n + i], "(|%.*s)", 3); } } for (i = 0; i < n; i++) for (j = 0; j < n; j++) if (needs_parentheses (&R_last[i * n + j])) sb_wrap (&R_last[i * n + j], "(%.*s)", 2); /* Compute regular expressions of length "k" between each pair of states per * induction */ memset (&R_cur_l, 0, sizeof (struct StringBuffer)); memset (&R_cur_r, 0, sizeof (struct StringBuffer)); for (k = 0; k < n; k++) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { /* Basis for the recursion: * $R^{(k)}_{ij} = R^{(k-1)}_{ij} | R^{(k-1)}_{ik} ( R^{(k-1)}_{kk} )^* R^{(k-1)}_{kj} * R_last == R^{(k-1)}, R_cur == R^{(k)} */ /* Create R_cur[i][j] and simplify the expression */ automaton_create_proofs_simplify (&R_last[i * n + j], &R_last[i * n + k], &R_last[k * n + k], &R_last[k * n + j], &R_cur[i * n + j], &R_cur_l, &R_cur_r); } } /* set R_last = R_cur */ R_swap = R_last; R_last = R_cur; R_cur = R_swap; /* clear 'R_cur' for next iteration */ for (i = 0; i < n; i++) for (j = 0; j < n; j++) R_cur[i * n + j].null_flag = GNUNET_YES; } sb_free (&R_cur_l); sb_free (&R_cur_r); /* assign proofs and hashes */ for (i = 0; i < n; i++) { if (GNUNET_YES != R_last[a->start->dfs_id * n + i].null_flag) { states[i]->proof = GNUNET_strndup (R_last[a->start->dfs_id * n + i].sbuf, R_last[a->start->dfs_id * n + i].slen); GNUNET_CRYPTO_hash (states[i]->proof, strlen (states[i]->proof), &states[i]->hash); } } /* complete regex for whole DFA: union of all pairs (start state/accepting * state(s)). */ sb_init (&complete_regex, 16 * n); for (i = 0; i < n; i++) { if (states[i]->accepting) { if ( (0 == complete_regex.slen) && (0 < R_last[a->start->dfs_id * n + i].slen) ) { sb_append (&complete_regex, &R_last[a->start->dfs_id * n + i]); } else if ( (GNUNET_YES != R_last[a->start->dfs_id * n + i].null_flag) && (0 < R_last[a->start->dfs_id * n + i].slen) ) { sb_append_cstr (&complete_regex, "|"); sb_append (&complete_regex, &R_last[a->start->dfs_id * n + i]); } } } a->canonical_regex = GNUNET_strndup (complete_regex.sbuf, complete_regex.slen); /* cleanup */ sb_free (&complete_regex); for (i = 0; i < n; i++) for (j = 0; j < n; j++) { sb_free (&R_cur[i * n + j]); sb_free (&R_last[i * n + j]); } GNUNET_free (R_cur); GNUNET_free (R_last); return GNUNET_OK; } /** * Creates a new DFA state based on a set of NFA states. Needs to be freed using * automaton_destroy_state. * * @param ctx context * @param nfa_states set of NFA states on which the DFA should be based on * * @return new DFA state */ static struct REGEX_INTERNAL_State * dfa_state_create (struct REGEX_INTERNAL_Context *ctx, struct REGEX_INTERNAL_StateSet *nfa_states) { struct REGEX_INTERNAL_State *s; char *pos; size_t len; struct REGEX_INTERNAL_State *cstate; struct REGEX_INTERNAL_Transition *ctran; unsigned int i; s = GNUNET_new (struct REGEX_INTERNAL_State); s->id = ctx->state_id++; s->index = -1; s->lowlink = -1; if (NULL == nfa_states) { GNUNET_asprintf (&s->name, "s%i", s->id); return s; } s->nfa_set = *nfa_states; if (nfa_states->off < 1) return s; /* Create a name based on 'nfa_states' */ len = nfa_states->off * 14 + 4; s->name = GNUNET_malloc (len); strcat (s->name, "{"); pos = s->name + 1; for (i = 0; i < nfa_states->off; i++) { cstate = nfa_states->states[i]; GNUNET_snprintf (pos, pos - s->name + len, "%i,", cstate->id); pos += strlen (pos); /* Add a transition for each distinct label to NULL state */ for (ctran = cstate->transitions_head; NULL != ctran; ctran = ctran->next) if (NULL != ctran->label) state_add_transition (ctx, s, ctran->label, NULL); /* If the nfa_states contain an accepting state, the new dfa state is also * accepting. */ if (cstate->accepting) s->accepting = 1; } pos[-1] = '}'; s->name = GNUNET_realloc (s->name, strlen (s->name) + 1); memset (nfa_states, 0, sizeof (struct REGEX_INTERNAL_StateSet)); return s; } /** * Move from the given state 's' to the next state on transition 'str'. Consumes * as much of the given 'str' as possible (usefull for strided DFAs). On return * 's' will point to the next state, and the length of the substring used for * this transition will be returned. If no transition possible 0 is returned and * 's' points to NULL. * * @param s starting state, will point to the next state or NULL (if no * transition possible) * @param str edge label to follow (will match longest common prefix) * * @return length of the substring comsumed from 'str' */ static unsigned int dfa_move (struct REGEX_INTERNAL_State **s, const char *str) { struct REGEX_INTERNAL_Transition *t; struct REGEX_INTERNAL_State *new_s; unsigned int len; unsigned int max_len; if (NULL == s) return 0; new_s = NULL; max_len = 0; for (t = (*s)->transitions_head; NULL != t; t = t->next) { len = strlen (t->label); if (0 == strncmp (t->label, str, len)) { if (len >= max_len) { max_len = len; new_s = t->to_state; } } } *s = new_s; return max_len; } /** * Set the given state 'marked' to GNUNET_YES. Used by the * 'dfa_remove_unreachable_states' function to detect unreachable states in the * automaton. * * @param cls closure, not used. * @param count count, not used. * @param s state where the marked attribute will be set to GNUNET_YES. */ static void mark_states (void *cls, const unsigned int count, struct REGEX_INTERNAL_State *s) { s->marked = GNUNET_YES; } /** * Remove all unreachable states from DFA 'a'. Unreachable states are those * states that are not reachable from the starting state. * * @param a DFA automaton */ static void dfa_remove_unreachable_states (struct REGEX_INTERNAL_Automaton *a) { struct REGEX_INTERNAL_State *s; struct REGEX_INTERNAL_State *s_next; /* 1. unmark all states */ for (s = a->states_head; NULL != s; s = s->next) s->marked = GNUNET_NO; /* 2. traverse dfa from start state and mark all visited states */ REGEX_INTERNAL_automaton_traverse (a, a->start, NULL, NULL, &mark_states, NULL); /* 3. delete all states that were not visited */ for (s = a->states_head; NULL != s; s = s_next) { s_next = s->next; if (GNUNET_NO == s->marked) automaton_remove_state (a, s); } } /** * Remove all dead states from the DFA 'a'. Dead states are those states that do * not transition to any other state but themselves. * * @param a DFA automaton */ static void dfa_remove_dead_states (struct REGEX_INTERNAL_Automaton *a) { struct REGEX_INTERNAL_State *s; struct REGEX_INTERNAL_State *s_next; struct REGEX_INTERNAL_Transition *t; int dead; GNUNET_assert (DFA == a->type); for (s = a->states_head; NULL != s; s = s_next) { s_next = s->next; if (s->accepting) continue; dead = 1; for (t = s->transitions_head; NULL != t; t = t->next) { if (NULL != t->to_state && t->to_state != s) { dead = 0; break; } } if (0 == dead) continue; /* state s is dead, remove it */ automaton_remove_state (a, s); } } /** * Merge all non distinguishable states in the DFA 'a' * * @param ctx context * @param a DFA automaton * @return GNUNET_OK on success */ static int dfa_merge_nondistinguishable_states (struct REGEX_INTERNAL_Context *ctx, struct REGEX_INTERNAL_Automaton *a) { uint32_t *table; struct REGEX_INTERNAL_State *s1; struct REGEX_INTERNAL_State *s2; struct REGEX_INTERNAL_Transition *t1; struct REGEX_INTERNAL_Transition *t2; struct REGEX_INTERNAL_State *s1_next; struct REGEX_INTERNAL_State *s2_next; int change; unsigned int num_equal_edges; unsigned int i; unsigned int state_cnt; unsigned long long idx; unsigned long long idx1; if ( (NULL == a) || (0 == a->state_count) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not merge nondistinguishable states, automaton was NULL.\n"); return GNUNET_SYSERR; } state_cnt = a->state_count; table = GNUNET_malloc_large ((sizeof (uint32_t) * state_cnt * state_cnt / 32) + sizeof (uint32_t)); if (NULL == table) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "malloc"); return GNUNET_SYSERR; } for (i = 0, s1 = a->states_head; NULL != s1; s1 = s1->next) s1->marked = i++; /* Mark all pairs of accepting/!accepting states */ for (s1 = a->states_head; NULL != s1; s1 = s1->next) for (s2 = a->states_head; NULL != s2; s2 = s2->next) if ( (s1->accepting && !s2->accepting) || (!s1->accepting && s2->accepting) ) { idx = s1->marked * state_cnt + s2->marked; table[idx / 32] |= (1 << (idx % 32)); } /* Find all equal states */ change = 1; while (0 != change) { change = 0; for (s1 = a->states_head; NULL != s1; s1 = s1->next) { for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2->next) { idx = s1->marked * state_cnt + s2->marked; if (0 != (table[idx / 32] & (1 << (idx % 32)))) continue; num_equal_edges = 0; for (t1 = s1->transitions_head; NULL != t1; t1 = t1->next) { for (t2 = s2->transitions_head; NULL != t2; t2 = t2->next) { if (0 == strcmp (t1->label, t2->label)) { num_equal_edges++; /* same edge, but targets definitively different, so we're different as well */ if (t1->to_state->marked > t2->to_state->marked) idx1 = t1->to_state->marked * state_cnt + t2->to_state->marked; else idx1 = t2->to_state->marked * state_cnt + t1->to_state->marked; if (0 != (table[idx1 / 32] & (1 << (idx1 % 32)))) { table[idx / 32] |= (1 << (idx % 32)); change = 1; /* changed a marker, need to run again */ } } } } if ( (num_equal_edges != s1->transition_count) || (num_equal_edges != s2->transition_count) ) { /* Make sure ALL edges of possible equal states are the same */ table[idx / 32] |= (1 << (idx % 32)); change = 1; /* changed a marker, need to run again */ } } } } /* Merge states that are equal */ for (s1 = a->states_head; NULL != s1; s1 = s1_next) { s1_next = s1->next; for (s2 = a->states_head; NULL != s2 && s1 != s2; s2 = s2_next) { s2_next = s2->next; idx = s1->marked * state_cnt + s2->marked; if (0 == (table[idx / 32] & (1 << (idx % 32)))) automaton_merge_states (ctx, a, s1, s2); } } GNUNET_free (table); return GNUNET_OK; } /** * Minimize the given DFA 'a' by removing all unreachable states, removing all * dead states and merging all non distinguishable states * * @param ctx context * @param a DFA automaton * @return GNUNET_OK on success */ static int dfa_minimize (struct REGEX_INTERNAL_Context *ctx, struct REGEX_INTERNAL_Automaton *a) { if (NULL == a) return GNUNET_SYSERR; GNUNET_assert (DFA == a->type); /* 1. remove unreachable states */ dfa_remove_unreachable_states (a); /* 2. remove dead states */ dfa_remove_dead_states (a); /* 3. Merge nondistinguishable states */ if (GNUNET_OK != dfa_merge_nondistinguishable_states (ctx, a)) return GNUNET_SYSERR; return GNUNET_OK; } /** * Context for adding strided transitions to a DFA. */ struct REGEX_INTERNAL_Strided_Context { /** * Length of the strides. */ const unsigned int stride; /** * Strided transitions DLL. New strided transitions will be stored in this DLL * and afterwards added to the DFA. */ struct REGEX_INTERNAL_Transition *transitions_head; /** * Strided transitions DLL. */ struct REGEX_INTERNAL_Transition *transitions_tail; }; /** * Recursive helper function to add strides to a DFA. * * @param cls context, contains stride length and strided transitions DLL. * @param depth current depth of the depth-first traversal of the graph. * @param label current label, string that contains all labels on the path from * 'start' to 's'. * @param start start state for the depth-first traversal of the graph. * @param s current state in the depth-first traversal */ static void dfa_add_multi_strides_helper (void *cls, const unsigned int depth, char *label, struct REGEX_INTERNAL_State *start, struct REGEX_INTERNAL_State *s) { struct REGEX_INTERNAL_Strided_Context *ctx = cls; struct REGEX_INTERNAL_Transition *t; char *new_label; if (depth == ctx->stride) { t = GNUNET_new (struct REGEX_INTERNAL_Transition); t->label = GNUNET_strdup (label); t->to_state = s; t->from_state = start; GNUNET_CONTAINER_DLL_insert (ctx->transitions_head, ctx->transitions_tail, t); } else { for (t = s->transitions_head; NULL != t; t = t->next) { /* Do not consider self-loops, because it end's up in too many * transitions */ if (t->to_state == t->from_state) continue; if (NULL != label) { GNUNET_asprintf (&new_label, "%s%s", label, t->label); } else new_label = GNUNET_strdup (t->label); dfa_add_multi_strides_helper (cls, (depth + 1), new_label, start, t->to_state); } } GNUNET_free_non_null (label); } /** * Function called for each state in the DFA. Starts a traversal of depth set in * context starting from state 's'. * * @param cls context. * @param count not used. * @param s current state. */ static void dfa_add_multi_strides (void *cls, const unsigned int count, struct REGEX_INTERNAL_State *s) { dfa_add_multi_strides_helper (cls, 0, NULL, s, s); } /** * Adds multi-strided transitions to the given 'dfa'. * * @param regex_ctx regex context needed to add transitions to the automaton. * @param dfa DFA to which the multi strided transitions should be added. * @param stride_len length of the strides. */ void REGEX_INTERNAL_dfa_add_multi_strides (struct REGEX_INTERNAL_Context *regex_ctx, struct REGEX_INTERNAL_Automaton *dfa, const unsigned int stride_len) { struct REGEX_INTERNAL_Strided_Context ctx = { stride_len, NULL, NULL }; struct REGEX_INTERNAL_Transition *t; struct REGEX_INTERNAL_Transition *t_next; if (1 > stride_len || GNUNET_YES == dfa->is_multistrided) return; /* Compute the new transitions of given stride_len */ REGEX_INTERNAL_automaton_traverse (dfa, dfa->start, NULL, NULL, &dfa_add_multi_strides, &ctx); /* Add all the new transitions to the automaton. */ for (t = ctx.transitions_head; NULL != t; t = t_next) { t_next = t->next; state_add_transition (regex_ctx, t->from_state, t->label, t->to_state); GNUNET_CONTAINER_DLL_remove (ctx.transitions_head, ctx.transitions_tail, t); GNUNET_free_non_null (t->label); GNUNET_free (t); } /* Mark this automaton as multistrided */ dfa->is_multistrided = GNUNET_YES; } /** * Recursive Helper function for DFA path compression. Does DFS on the DFA graph * and adds new transitions to the given transitions DLL and marks states that * should be removed by setting state->contained to GNUNET_YES. * * @param dfa DFA for which the paths should be compressed. * @param start starting state for linear path search. * @param cur current state in the recursive DFS. * @param label current label (string of traversed labels). * @param max_len maximal path compression length. * @param transitions_head transitions DLL. * @param transitions_tail transitions DLL. */ void dfa_compress_paths_helper (struct REGEX_INTERNAL_Automaton *dfa, struct REGEX_INTERNAL_State *start, struct REGEX_INTERNAL_State *cur, char *label, unsigned int max_len, struct REGEX_INTERNAL_Transition **transitions_head, struct REGEX_INTERNAL_Transition **transitions_tail) { struct REGEX_INTERNAL_Transition *t; char *new_label; if (NULL != label && ((cur->incoming_transition_count > 1 || GNUNET_YES == cur->accepting || GNUNET_YES == cur->marked) || (start != dfa->start && max_len > 0 && max_len == strlen (label)) || (start == dfa->start && GNUNET_REGEX_INITIAL_BYTES == strlen (label)))) { t = GNUNET_new (struct REGEX_INTERNAL_Transition); t->label = GNUNET_strdup (label); t->to_state = cur; t->from_state = start; GNUNET_CONTAINER_DLL_insert (*transitions_head, *transitions_tail, t); if (GNUNET_NO == cur->marked) { dfa_compress_paths_helper (dfa, cur, cur, NULL, max_len, transitions_head, transitions_tail); } return; } else if (cur != start) cur->contained = GNUNET_YES; if (GNUNET_YES == cur->marked && cur != start) return; cur->marked = GNUNET_YES; for (t = cur->transitions_head; NULL != t; t = t->next) { if (NULL != label) GNUNET_asprintf (&new_label, "%s%s", label, t->label); else new_label = GNUNET_strdup (t->label); if (t->to_state != cur) { dfa_compress_paths_helper (dfa, start, t->to_state, new_label, max_len, transitions_head, transitions_tail); } GNUNET_free (new_label); } } /** * Compress paths in the given 'dfa'. Linear paths like 0->1->2->3 will be * compressed to 0->3 by combining transitions. * * @param regex_ctx context for adding new transitions. * @param dfa DFA representation, will directly modify the given DFA. * @param max_len maximal length of the compressed paths. */ static void dfa_compress_paths (struct REGEX_INTERNAL_Context *regex_ctx, struct REGEX_INTERNAL_Automaton *dfa, unsigned int max_len) { struct REGEX_INTERNAL_State *s; struct REGEX_INTERNAL_State *s_next; struct REGEX_INTERNAL_Transition *t; struct REGEX_INTERNAL_Transition *t_next; struct REGEX_INTERNAL_Transition *transitions_head = NULL; struct REGEX_INTERNAL_Transition *transitions_tail = NULL; if (NULL == dfa) return; /* Count the incoming transitions on each state. */ for (s = dfa->states_head; NULL != s; s = s->next) { for (t = s->transitions_head; NULL != t; t = t->next) { if (NULL != t->to_state) t->to_state->incoming_transition_count++; } } /* Unmark all states. */ for (s = dfa->states_head; NULL != s; s = s->next) { s->marked = GNUNET_NO; s->contained = GNUNET_NO; } /* Add strides and mark states that can be deleted. */ dfa_compress_paths_helper (dfa, dfa->start, dfa->start, NULL, max_len, &transitions_head, &transitions_tail); /* Add all the new transitions to the automaton. */ for (t = transitions_head; NULL != t; t = t_next) { t_next = t->next; state_add_transition (regex_ctx, t->from_state, t->label, t->to_state); GNUNET_CONTAINER_DLL_remove (transitions_head, transitions_tail, t); GNUNET_free_non_null (t->label); GNUNET_free (t); } /* Remove marked states (including their incoming and outgoing transitions). */ for (s = dfa->states_head; NULL != s; s = s_next) { s_next = s->next; if (GNUNET_YES == s->contained) automaton_remove_state (dfa, s); } } /** * Creates a new NFA fragment. Needs to be cleared using * automaton_fragment_clear. * * @param start starting state * @param end end state * * @return new NFA fragment */ static struct REGEX_INTERNAL_Automaton * nfa_fragment_create (struct REGEX_INTERNAL_State *start, struct REGEX_INTERNAL_State *end) { struct REGEX_INTERNAL_Automaton *n; n = GNUNET_new (struct REGEX_INTERNAL_Automaton); n->type = NFA; n->start = NULL; n->end = NULL; n->state_count = 0; if (NULL == start || NULL == end) return n; automaton_add_state (n, end); automaton_add_state (n, start); n->state_count = 2; n->start = start; n->end = end; return n; } /** * Adds a list of states to the given automaton 'n'. * * @param n automaton to which the states should be added * @param states_head head of the DLL of states * @param states_tail tail of the DLL of states */ static void nfa_add_states (struct REGEX_INTERNAL_Automaton *n, struct REGEX_INTERNAL_State *states_head, struct REGEX_INTERNAL_State *states_tail) { struct REGEX_INTERNAL_State *s; if (NULL == n || NULL == states_head) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not add states\n"); return; } if (NULL == n->states_head) { n->states_head = states_head; n->states_tail = states_tail; return; } if (NULL != states_head) { n->states_tail->next = states_head; n->states_tail = states_tail; } for (s = states_head; NULL != s; s = s->next) n->state_count++; } /** * Creates a new NFA state. Needs to be freed using automaton_destroy_state. * * @param ctx context * @param accepting is it an accepting state or not * * @return new NFA state */ static struct REGEX_INTERNAL_State * nfa_state_create (struct REGEX_INTERNAL_Context *ctx, int accepting) { struct REGEX_INTERNAL_State *s; s = GNUNET_new (struct REGEX_INTERNAL_State); s->id = ctx->state_id++; s->accepting = accepting; s->marked = GNUNET_NO; s->contained = 0; s->index = -1; s->lowlink = -1; s->scc_id = 0; s->name = NULL; GNUNET_asprintf (&s->name, "s%i", s->id); return s; } /** * Calculates the closure set for the given set of states. * * @param ret set to sorted nfa closure on 'label' (epsilon closure if 'label' is NULL) * @param nfa the NFA containing 's' * @param states list of states on which to base the closure on * @param label transitioning label for which to base the closure on, * pass NULL for epsilon transition */ static void nfa_closure_set_create (struct REGEX_INTERNAL_StateSet *ret, struct REGEX_INTERNAL_Automaton *nfa, struct REGEX_INTERNAL_StateSet *states, const char *label) { struct REGEX_INTERNAL_State *s; unsigned int i; struct REGEX_INTERNAL_StateSet_MDLL cls_stack; struct REGEX_INTERNAL_State *clsstate; struct REGEX_INTERNAL_State *currentstate; struct REGEX_INTERNAL_Transition *ctran; memset (ret, 0, sizeof (struct REGEX_INTERNAL_StateSet)); if (NULL == states) return; for (i = 0; i < states->off; i++) { s = states->states[i]; /* Add start state to closure only for epsilon closure */ if (NULL == label) state_set_append (ret, s); /* initialize work stack */ cls_stack.head = NULL; cls_stack.tail = NULL; GNUNET_CONTAINER_MDLL_insert (ST, cls_stack.head, cls_stack.tail, s); cls_stack.len = 1; while (NULL != (currentstate = cls_stack.tail)) { GNUNET_CONTAINER_MDLL_remove (ST, cls_stack.head, cls_stack.tail, currentstate); cls_stack.len--; for (ctran = currentstate->transitions_head; NULL != ctran; ctran = ctran->next) { if (NULL == (clsstate = ctran->to_state)) continue; if (0 != clsstate->contained) continue; if (0 != nullstrcmp (label, ctran->label)) continue; state_set_append (ret, clsstate); GNUNET_CONTAINER_MDLL_insert_tail (ST, cls_stack.head, cls_stack.tail, clsstate); cls_stack.len++; clsstate->contained = 1; } } } for (i = 0; i < ret->off; i++) ret->states[i]->contained = 0; if (ret->off > 1) qsort (ret->states, ret->off, sizeof (struct REGEX_INTERNAL_State *), &state_compare); } /** * Pops two NFA fragments (a, b) from the stack and concatenates them (ab) * * @param ctx context */ static void nfa_add_concatenation (struct REGEX_INTERNAL_Context *ctx) { struct REGEX_INTERNAL_Automaton *a; struct REGEX_INTERNAL_Automaton *b; struct REGEX_INTERNAL_Automaton *new_nfa; b = ctx->stack_tail; GNUNET_assert (NULL != b); GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b); a = ctx->stack_tail; GNUNET_assert (NULL != a); GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a); state_add_transition (ctx, a->end, NULL, b->start); a->end->accepting = 0; b->end->accepting = 1; new_nfa = nfa_fragment_create (NULL, NULL); nfa_add_states (new_nfa, a->states_head, a->states_tail); nfa_add_states (new_nfa, b->states_head, b->states_tail); new_nfa->start = a->start; new_nfa->end = b->end; new_nfa->state_count += a->state_count + b->state_count; automaton_fragment_clear (a); automaton_fragment_clear (b); GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa); } /** * Pops a NFA fragment from the stack (a) and adds a new fragment (a*) * * @param ctx context */ static void nfa_add_star_op (struct REGEX_INTERNAL_Context *ctx) { struct REGEX_INTERNAL_Automaton *a; struct REGEX_INTERNAL_Automaton *new_nfa; struct REGEX_INTERNAL_State *start; struct REGEX_INTERNAL_State *end; a = ctx->stack_tail; if (NULL == a) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "nfa_add_star_op failed, because there was no element on the stack"); return; } GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a); start = nfa_state_create (ctx, 0); end = nfa_state_create (ctx, 1); state_add_transition (ctx, start, NULL, a->start); state_add_transition (ctx, start, NULL, end); state_add_transition (ctx, a->end, NULL, a->start); state_add_transition (ctx, a->end, NULL, end); a->end->accepting = 0; end->accepting = 1; new_nfa = nfa_fragment_create (start, end); nfa_add_states (new_nfa, a->states_head, a->states_tail); automaton_fragment_clear (a); GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa); } /** * Pops an NFA fragment (a) from the stack and adds a new fragment (a+) * * @param ctx context */ static void nfa_add_plus_op (struct REGEX_INTERNAL_Context *ctx) { struct REGEX_INTERNAL_Automaton *a; a = ctx->stack_tail; if (NULL == a) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "nfa_add_plus_op failed, because there was no element on the stack"); return; } GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a); state_add_transition (ctx, a->end, NULL, a->start); GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, a); } /** * Pops an NFA fragment (a) from the stack and adds a new fragment (a?) * * @param ctx context */ static void nfa_add_question_op (struct REGEX_INTERNAL_Context *ctx) { struct REGEX_INTERNAL_Automaton *a; struct REGEX_INTERNAL_Automaton *new_nfa; struct REGEX_INTERNAL_State *start; struct REGEX_INTERNAL_State *end; a = ctx->stack_tail; if (NULL == a) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "nfa_add_question_op failed, because there was no element on the stack"); return; } GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a); start = nfa_state_create (ctx, 0); end = nfa_state_create (ctx, 1); state_add_transition (ctx, start, NULL, a->start); state_add_transition (ctx, start, NULL, end); state_add_transition (ctx, a->end, NULL, end); a->end->accepting = 0; new_nfa = nfa_fragment_create (start, end); nfa_add_states (new_nfa, a->states_head, a->states_tail); GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa); automaton_fragment_clear (a); } /** * Pops two NFA fragments (a, b) from the stack and adds a new NFA fragment that * alternates between a and b (a|b) * * @param ctx context */ static void nfa_add_alternation (struct REGEX_INTERNAL_Context *ctx) { struct REGEX_INTERNAL_Automaton *a; struct REGEX_INTERNAL_Automaton *b; struct REGEX_INTERNAL_Automaton *new_nfa; struct REGEX_INTERNAL_State *start; struct REGEX_INTERNAL_State *end; b = ctx->stack_tail; GNUNET_assert (NULL != b); GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, b); a = ctx->stack_tail; GNUNET_assert (NULL != a); GNUNET_CONTAINER_DLL_remove (ctx->stack_head, ctx->stack_tail, a); start = nfa_state_create (ctx, 0); end = nfa_state_create (ctx, 1); state_add_transition (ctx, start, NULL, a->start); state_add_transition (ctx, start, NULL, b->start); state_add_transition (ctx, a->end, NULL, end); state_add_transition (ctx, b->end, NULL, end); a->end->accepting = 0; b->end->accepting = 0; end->accepting = 1; new_nfa = nfa_fragment_create (start, end); nfa_add_states (new_nfa, a->states_head, a->states_tail); nfa_add_states (new_nfa, b->states_head, b->states_tail); automaton_fragment_clear (a); automaton_fragment_clear (b); GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, new_nfa); } /** * Adds a new nfa fragment to the stack * * @param ctx context * @param label label for nfa transition */ static void nfa_add_label (struct REGEX_INTERNAL_Context *ctx, const char *label) { struct REGEX_INTERNAL_Automaton *n; struct REGEX_INTERNAL_State *start; struct REGEX_INTERNAL_State *end; GNUNET_assert (NULL != ctx); start = nfa_state_create (ctx, 0); end = nfa_state_create (ctx, 1); state_add_transition (ctx, start, label, end); n = nfa_fragment_create (start, end); GNUNET_assert (NULL != n); GNUNET_CONTAINER_DLL_insert_tail (ctx->stack_head, ctx->stack_tail, n); } /** * Initialize a new context * * @param ctx context */ static void REGEX_INTERNAL_context_init (struct REGEX_INTERNAL_Context *ctx) { if (NULL == ctx) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Context was NULL!"); return; } ctx->state_id = 0; ctx->transition_id = 0; ctx->stack_head = NULL; ctx->stack_tail = NULL; } /** * Construct an NFA by parsing the regex string of length 'len'. * * @param regex regular expression string * @param len length of the string * * @return NFA, needs to be freed using REGEX_INTERNAL_destroy_automaton */ struct REGEX_INTERNAL_Automaton * REGEX_INTERNAL_construct_nfa (const char *regex, const size_t len) { struct REGEX_INTERNAL_Context ctx; struct REGEX_INTERNAL_Automaton *nfa; const char *regexp; char curlabel[2]; char *error_msg; unsigned int count; unsigned int altcount; unsigned int atomcount; unsigned int poff; unsigned int psize; struct { int altcount; int atomcount; } *p; if (NULL == regex || 0 == strlen (regex) || 0 == len) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse regex. Empty regex string provided.\n"); return NULL; } REGEX_INTERNAL_context_init (&ctx); regexp = regex; curlabel[1] = '\0'; p = NULL; error_msg = NULL; altcount = 0; atomcount = 0; poff = 0; psize = 0; for (count = 0; count < len && *regexp; count++, regexp++) { switch (*regexp) { case '(': if (atomcount > 1) { --atomcount; nfa_add_concatenation (&ctx); } if (poff == psize) GNUNET_array_grow (p, psize, psize * 2 + 4); /* FIXME why *2 +4? */ p[poff].altcount = altcount; p[poff].atomcount = atomcount; poff++; altcount = 0; atomcount = 0; break; case '|': if (0 == atomcount) { error_msg = "Cannot append '|' to nothing"; goto error; } while (--atomcount > 0) nfa_add_concatenation (&ctx); altcount++; break; case ')': if (0 == poff) { error_msg = "Missing opening '('"; goto error; } if (0 == atomcount) { /* Ignore this: "()" */ poff--; altcount = p[poff].altcount; atomcount = p[poff].atomcount; break; } while (--atomcount > 0) nfa_add_concatenation (&ctx); for (; altcount > 0; altcount--) nfa_add_alternation (&ctx); poff--; altcount = p[poff].altcount; atomcount = p[poff].atomcount; atomcount++; break; case '*': if (atomcount == 0) { error_msg = "Cannot append '*' to nothing"; goto error; } nfa_add_star_op (&ctx); break; case '+': if (atomcount == 0) { error_msg = "Cannot append '+' to nothing"; goto error; } nfa_add_plus_op (&ctx); break; case '?': if (atomcount == 0) { error_msg = "Cannot append '?' to nothing"; goto error; } nfa_add_question_op (&ctx); break; default: if (atomcount > 1) { --atomcount; nfa_add_concatenation (&ctx); } curlabel[0] = *regexp; nfa_add_label (&ctx, curlabel); atomcount++; break; } } if (0 != poff) { error_msg = "Unbalanced parenthesis"; goto error; } while (--atomcount > 0) nfa_add_concatenation (&ctx); for (; altcount > 0; altcount--) nfa_add_alternation (&ctx); GNUNET_array_grow (p, psize, 0); nfa = ctx.stack_tail; GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa); if (NULL != ctx.stack_head) { error_msg = "Creating the NFA failed. NFA stack was not empty!"; goto error; } /* Remember the regex that was used to generate this NFA */ nfa->regex = GNUNET_strdup (regex); /* create depth-first numbering of the states for pretty printing */ REGEX_INTERNAL_automaton_traverse (nfa, NULL, NULL, NULL, &number_states, NULL); /* No multistriding added so far */ nfa->is_multistrided = GNUNET_NO; return nfa; error: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not parse regex: `%s'\n", regex); if (NULL != error_msg) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", error_msg); GNUNET_free_non_null (p); while (NULL != (nfa = ctx.stack_head)) { GNUNET_CONTAINER_DLL_remove (ctx.stack_head, ctx.stack_tail, nfa); REGEX_INTERNAL_automaton_destroy (nfa); } return NULL; } /** * Create DFA states based on given 'nfa' and starting with 'dfa_state'. * * @param ctx context. * @param nfa NFA automaton. * @param dfa DFA automaton. * @param dfa_state current dfa state, pass epsilon closure of first nfa state * for starting. */ static void construct_dfa_states (struct REGEX_INTERNAL_Context *ctx, struct REGEX_INTERNAL_Automaton *nfa, struct REGEX_INTERNAL_Automaton *dfa, struct REGEX_INTERNAL_State *dfa_state) { struct REGEX_INTERNAL_Transition *ctran; struct REGEX_INTERNAL_State *new_dfa_state; struct REGEX_INTERNAL_State *state_contains; struct REGEX_INTERNAL_State *state_iter; struct REGEX_INTERNAL_StateSet tmp; struct REGEX_INTERNAL_StateSet nfa_set; for (ctran = dfa_state->transitions_head; NULL != ctran; ctran = ctran->next) { if (NULL == ctran->label || NULL != ctran->to_state) continue; nfa_closure_set_create (&tmp, nfa, &dfa_state->nfa_set, ctran->label); nfa_closure_set_create (&nfa_set, nfa, &tmp, NULL); state_set_clear (&tmp); state_contains = NULL; for (state_iter = dfa->states_head; NULL != state_iter; state_iter = state_iter->next) { if (0 == state_set_compare (&state_iter->nfa_set, &nfa_set)) { state_contains = state_iter; break; } } if (NULL == state_contains) { new_dfa_state = dfa_state_create (ctx, &nfa_set); automaton_add_state (dfa, new_dfa_state); ctran->to_state = new_dfa_state; construct_dfa_states (ctx, nfa, dfa, new_dfa_state); } else { ctran->to_state = state_contains; state_set_clear (&nfa_set); } } } /** * Construct DFA for the given 'regex' of length 'len'. * * Path compression means, that for example a DFA o -> a -> b -> c -> o will be * compressed to o -> abc -> o. Note that this parameter influences the * non-determinism of states of the resulting NFA in the DHT (number of outgoing * edges with the same label). For example for an application that stores IPv4 * addresses as bitstrings it could make sense to limit the path compression to * 4 or 8. * * @param regex regular expression string. * @param len length of the regular expression. * @param max_path_len limit the path compression length to the * given value. If set to 1, no path compression is applied. Set to 0 for * maximal possible path compression (generally not desireable). * @return DFA, needs to be freed using REGEX_INTERNAL_automaton_destroy. */ struct REGEX_INTERNAL_Automaton * REGEX_INTERNAL_construct_dfa (const char *regex, const size_t len, unsigned int max_path_len) { struct REGEX_INTERNAL_Context ctx; struct REGEX_INTERNAL_Automaton *dfa; struct REGEX_INTERNAL_Automaton *nfa; struct REGEX_INTERNAL_StateSet nfa_start_eps_cls; struct REGEX_INTERNAL_StateSet singleton_set; REGEX_INTERNAL_context_init (&ctx); /* Create NFA */ nfa = REGEX_INTERNAL_construct_nfa (regex, len); if (NULL == nfa) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create DFA, because NFA creation failed\n"); return NULL; } dfa = GNUNET_new (struct REGEX_INTERNAL_Automaton); dfa->type = DFA; dfa->regex = GNUNET_strdup (regex); /* Create DFA start state from epsilon closure */ memset (&singleton_set, 0, sizeof (struct REGEX_INTERNAL_StateSet)); state_set_append (&singleton_set, nfa->start); nfa_closure_set_create (&nfa_start_eps_cls, nfa, &singleton_set, NULL); state_set_clear (&singleton_set); dfa->start = dfa_state_create (&ctx, &nfa_start_eps_cls); automaton_add_state (dfa, dfa->start); construct_dfa_states (&ctx, nfa, dfa, dfa->start); REGEX_INTERNAL_automaton_destroy (nfa); /* Minimize DFA */ if (GNUNET_OK != dfa_minimize (&ctx, dfa)) { REGEX_INTERNAL_automaton_destroy (dfa); return NULL; } /* Create proofs and hashes for all states */ if (GNUNET_OK != automaton_create_proofs (dfa)) { REGEX_INTERNAL_automaton_destroy (dfa); return NULL; } /* Compress linear DFA paths */ if (1 != max_path_len) dfa_compress_paths (&ctx, dfa, max_path_len); return dfa; } /** * Free the memory allocated by constructing the REGEX_INTERNAL_Automaton data * structure. * * @param a automaton to be destroyed */ void REGEX_INTERNAL_automaton_destroy (struct REGEX_INTERNAL_Automaton *a) { struct REGEX_INTERNAL_State *s; struct REGEX_INTERNAL_State *next_state; if (NULL == a) return; GNUNET_free_non_null (a->regex); GNUNET_free_non_null (a->canonical_regex); for (s = a->states_head; NULL != s; s = next_state) { next_state = s->next; GNUNET_CONTAINER_DLL_remove (a->states_head, a->states_tail, s); automaton_destroy_state (s); } GNUNET_free (a); } /** * Evaluates the given string using the given DFA automaton * * @param a automaton, type must be DFA * @param string string that should be evaluated * * @return 0 if string matches, non 0 otherwise */ static int evaluate_dfa (struct REGEX_INTERNAL_Automaton *a, const char *string) { const char *strp; struct REGEX_INTERNAL_State *s; unsigned int step_len; if (DFA != a->type) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tried to evaluate DFA, but NFA automaton given"); return -1; } s = a->start; /* If the string is empty but the starting state is accepting, we accept. */ if ((NULL == string || 0 == strlen (string)) && s->accepting) return 0; for (strp = string; NULL != strp && *strp; strp += step_len) { step_len = dfa_move (&s, strp); if (NULL == s) break; } if (NULL != s && s->accepting) return 0; return 1; } /** * Evaluates the given string using the given NFA automaton * * @param a automaton, type must be NFA * @param string string that should be evaluated * * @return 0 if string matches, non 0 otherwise */ static int evaluate_nfa (struct REGEX_INTERNAL_Automaton *a, const char *string) { const char *strp; char str[2]; struct REGEX_INTERNAL_State *s; struct REGEX_INTERNAL_StateSet sset; struct REGEX_INTERNAL_StateSet new_sset; struct REGEX_INTERNAL_StateSet singleton_set; unsigned int i; int result; if (NFA != a->type) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tried to evaluate NFA, but DFA automaton given"); return -1; } /* If the string is empty but the starting state is accepting, we accept. */ if ((NULL == string || 0 == strlen (string)) && a->start->accepting) return 0; result = 1; memset (&singleton_set, 0, sizeof (struct REGEX_INTERNAL_StateSet)); state_set_append (&singleton_set, a->start); nfa_closure_set_create (&sset, a, &singleton_set, NULL); state_set_clear (&singleton_set); str[1] = '\0'; for (strp = string; NULL != strp && *strp; strp++) { str[0] = *strp; nfa_closure_set_create (&new_sset, a, &sset, str); state_set_clear (&sset); nfa_closure_set_create (&sset, a, &new_sset, 0); state_set_clear (&new_sset); } for (i = 0; i < sset.off; i++) { s = sset.states[i]; if ( (NULL != s) && (s->accepting) ) { result = 0; break; } } state_set_clear (&sset); return result; } /** * Evaluates the given 'string' against the given compiled regex * * @param a automaton * @param string string to check * * @return 0 if string matches, non 0 otherwise */ int REGEX_INTERNAL_eval (struct REGEX_INTERNAL_Automaton *a, const char *string) { int result; switch (a->type) { case DFA: result = evaluate_dfa (a, string); break; case NFA: result = evaluate_nfa (a, string); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Evaluating regex failed, automaton has no type!\n"); result = GNUNET_SYSERR; break; } return result; } /** * Get the canonical regex of the given automaton. * When constructing the automaton a proof is computed for each state, * consisting of the regular expression leading to this state. A complete * regex for the automaton can be computed by combining these proofs. * As of now this function is only useful for testing. * * @param a automaton for which the canonical regex should be returned. * * @return */ const char * REGEX_INTERNAL_get_canonical_regex (struct REGEX_INTERNAL_Automaton *a) { if (NULL == a) return NULL; return a->canonical_regex; } /** * Get the number of transitions that are contained in the given automaton. * * @param a automaton for which the number of transitions should be returned. * * @return number of transitions in the given automaton. */ unsigned int REGEX_INTERNAL_get_transition_count (struct REGEX_INTERNAL_Automaton *a) { unsigned int t_count; struct REGEX_INTERNAL_State *s; if (NULL == a) return 0; t_count = 0; for (s = a->states_head; NULL != s; s = s->next) t_count += s->transition_count; return t_count; } /** * Get the first key for the given 'input_string'. This hashes the first x bits * of the 'input_string'. * * @param input_string string. * @param string_len length of the 'input_string'. * @param key pointer to where to write the hash code. * * @return number of bits of 'input_string' that have been consumed * to construct the key */ size_t REGEX_INTERNAL_get_first_key (const char *input_string, size_t string_len, struct GNUNET_HashCode * key) { size_t size; size = string_len < GNUNET_REGEX_INITIAL_BYTES ? string_len : GNUNET_REGEX_INITIAL_BYTES; if (NULL == input_string) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Given input string was NULL!\n"); return 0; } GNUNET_CRYPTO_hash (input_string, size, key); return size; } /** * Recursive function that calls the iterator for each synthetic start state. * * @param min_len minimum length of the path in the graph. * @param max_len maximum length of the path in the graph. * @param consumed_string string consumed by traversing the graph till this state. * @param state current state of the automaton. * @param iterator iterator function called for each edge. * @param iterator_cls closure for the iterator function. */ static void iterate_initial_edge (const unsigned int min_len, const unsigned int max_len, char *consumed_string, struct REGEX_INTERNAL_State *state, REGEX_INTERNAL_KeyIterator iterator, void *iterator_cls) { char *temp; struct REGEX_INTERNAL_Transition *t; unsigned int num_edges = state->transition_count; struct REGEX_BLOCK_Edge edges[num_edges]; struct REGEX_BLOCK_Edge edge[1]; struct GNUNET_HashCode hash; struct GNUNET_HashCode hash_new; unsigned int cur_len; if (NULL != consumed_string) cur_len = strlen (consumed_string); else cur_len = 0; if ((cur_len >= min_len || GNUNET_YES == state->accepting) && cur_len > 0 && NULL != consumed_string) { if (cur_len <= max_len) { if (state->proof != NULL && 0 != strcmp (consumed_string, state->proof)) { (void) state_get_edges (state, edges); GNUNET_CRYPTO_hash (consumed_string, strlen (consumed_string), &hash); iterator (iterator_cls, &hash, consumed_string, state->accepting, num_edges, edges); } if (GNUNET_YES == state->accepting && cur_len > 1 && state->transition_count < 1 && cur_len < max_len) { /* Special case for regex consisting of just a string that is shorter than * max_len */ edge[0].label = &consumed_string[cur_len - 1]; edge[0].destination = state->hash; temp = GNUNET_strdup (consumed_string); temp[cur_len - 1] = '\0'; GNUNET_CRYPTO_hash (temp, cur_len - 1, &hash_new); iterator (iterator_cls, &hash_new, temp, GNUNET_NO, 1, edge); GNUNET_free (temp); } } else /* cur_len > max_len */ { /* Case where the concatenated labels are longer than max_len, then split. */ edge[0].label = &consumed_string[max_len]; edge[0].destination = state->hash; temp = GNUNET_strdup (consumed_string); temp[max_len] = '\0'; GNUNET_CRYPTO_hash (temp, max_len, &hash); iterator (iterator_cls, &hash, temp, GNUNET_NO, 1, edge); GNUNET_free (temp); } } if (cur_len < max_len) { for (t = state->transitions_head; NULL != t; t = t->next) { if (NULL != consumed_string) GNUNET_asprintf (&temp, "%s%s", consumed_string, t->label); else GNUNET_asprintf (&temp, "%s", t->label); iterate_initial_edge (min_len, max_len, temp, t->to_state, iterator, iterator_cls); GNUNET_free (temp); } } } /** * Iterate over all edges starting from start state of automaton 'a'. Calling * iterator for each edge. * * @param a automaton. * @param iterator iterator called for each edge. * @param iterator_cls closure. */ void REGEX_INTERNAL_iterate_all_edges (struct REGEX_INTERNAL_Automaton *a, REGEX_INTERNAL_KeyIterator iterator, void *iterator_cls) { struct REGEX_INTERNAL_State *s; for (s = a->states_head; NULL != s; s = s->next) { struct REGEX_BLOCK_Edge edges[s->transition_count]; unsigned int num_edges; num_edges = state_get_edges (s, edges); if ( ( (NULL != s->proof) && (0 < strlen (s->proof)) ) || s->accepting) iterator (iterator_cls, &s->hash, s->proof, s->accepting, num_edges, edges); s->marked = GNUNET_NO; } iterate_initial_edge (GNUNET_REGEX_INITIAL_BYTES, GNUNET_REGEX_INITIAL_BYTES, NULL, a->start, iterator, iterator_cls); } /** * Struct to hold all the relevant state information in the HashMap. * * Contains the same info as the Regex Iterator parametes except the key, * which comes directly from the HashMap iterator. */ struct temporal_state_store { int reachable; char *proof; int accepting; int num_edges; struct REGEX_BLOCK_Edge *edges; }; /** * Store regex iterator and cls in one place to pass to the hashmap iterator. */ struct client_iterator { REGEX_INTERNAL_KeyIterator iterator; void *iterator_cls; }; /** * Iterator over all edges of a dfa. Stores all of them in a HashMap * for later reachability marking. * * @param cls Closure (HashMap) * @param key hash for current state. * @param proof proof for current state * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. * @param num_edges number of edges leaving current state. * @param edges edges leaving current state. */ static void store_all_states (void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges) { struct GNUNET_CONTAINER_MultiHashMap *hm = cls; struct temporal_state_store *tmp; size_t edges_size; tmp = GNUNET_new (struct temporal_state_store); tmp->reachable = GNUNET_NO; tmp->proof = GNUNET_strdup (proof); tmp->accepting = accepting; tmp->num_edges = num_edges; edges_size = sizeof (struct REGEX_BLOCK_Edge) * num_edges; tmp->edges = GNUNET_malloc (edges_size); memcpy(tmp->edges, edges, edges_size); GNUNET_CONTAINER_multihashmap_put (hm, key, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); } /** * Mark state as reachable and call recursively on all its edges. * * If already marked as reachable, do nothing. * * @param state State to mark as reachable. * @param hm HashMap which stores all the states indexed by key. */ static void mark_as_reachable (struct temporal_state_store *state, struct GNUNET_CONTAINER_MultiHashMap *hm) { struct temporal_state_store *child; unsigned int i; if (GNUNET_YES == state->reachable) /* visited */ return; state->reachable = GNUNET_YES; for (i = 0; i < state->num_edges; i++) { child = GNUNET_CONTAINER_multihashmap_get (hm, &state->edges[i].destination); if (NULL == child) { GNUNET_break (0); continue; } mark_as_reachable (child, hm); } } /** * Iterator over hash map entries to mark the ones that are reachable. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to iterate, * #GNUNET_NO if not. */ static int reachability_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_CONTAINER_MultiHashMap *hm = cls; struct temporal_state_store *state = value; if (GNUNET_YES == state->reachable) /* already visited and marked */ return GNUNET_YES; if (GNUNET_REGEX_INITIAL_BYTES > strlen (state->proof) && GNUNET_NO == state->accepting) /* not directly reachable */ return GNUNET_YES; mark_as_reachable (state, hm); return GNUNET_YES; } /** * Iterator over hash map entries. * Calling the callback on the ones marked as reachables. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to iterate, * #GNUNET_NO if not. */ static int iterate_reachables (void *cls, const struct GNUNET_HashCode *key, void *value) { struct client_iterator *ci = cls; struct temporal_state_store *state = value; if (GNUNET_YES == state->reachable) { ci->iterator (ci->iterator_cls, key, state->proof, state->accepting, state->num_edges, state->edges); } GNUNET_free (state->edges); GNUNET_free (state->proof); GNUNET_free (state); return GNUNET_YES; } /** * Iterate over all edges of automaton 'a' that are reachable from a state with * a proof of at least GNUNET_REGEX_INITIAL_BYTES characters. * * Call the iterator for each such edge. * * @param a automaton. * @param iterator iterator called for each reachable edge. * @param iterator_cls closure. */ void REGEX_INTERNAL_iterate_reachable_edges (struct REGEX_INTERNAL_Automaton *a, REGEX_INTERNAL_KeyIterator iterator, void *iterator_cls) { struct GNUNET_CONTAINER_MultiHashMap *hm; struct client_iterator ci; hm = GNUNET_CONTAINER_multihashmap_create (a->state_count * 2, GNUNET_NO); ci.iterator = iterator; ci.iterator_cls = iterator_cls; REGEX_INTERNAL_iterate_all_edges (a, &store_all_states, hm); GNUNET_CONTAINER_multihashmap_iterate (hm, &reachability_iterator, hm); GNUNET_CONTAINER_multihashmap_iterate (hm, &iterate_reachables, &ci); GNUNET_CONTAINER_multihashmap_destroy (hm); } /* end of regex_internal.c */ gnunet-0.10.1/src/regex/Makefile.am0000644000175000017500000001457712320755240013765 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ regex.conf libexec_PROGRAMS = \ gnunet-service-regex \ gnunet-daemon-regexprofiler gnunet_service_regex_SOURCES = \ gnunet-service-regex.c gnunet_service_regex_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_regex_DEPENDENCIES = \ libgnunetregex_internal.a noinst_LIBRARIES = \ libgnunetregex_internal.a \ libgnunetregextest.a lib_LTLIBRARIES = \ libgnunetregexblock.la \ libgnunetregex.la libgnunetregexblock_la_SOURCES = \ regex_block_lib.c regex_block_lib.h libgnunetregexblock_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) \ $(LTLIBINTL) libgnunetregexblock_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:0:0 libgnunetregex_internal_a_SOURCES = \ regex_internal_lib.h \ regex_internal.h regex_internal.c \ regex_internal_dht.c libgnunetregex_internal_a_DEPENDENCIES = \ libgnunetregexblock.la libgnunetregex_la_SOURCES = \ regex_api.c regex_ipc.h libgnunetregex_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetregex_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 3:1:0 plugin_LTLIBRARIES = \ libgnunet_plugin_block_regex.la libgnunet_plugin_block_regex_la_SOURCES = \ plugin_block_regex.c libgnunet_plugin_block_regex_la_LIBADD = \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_block_regex_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_regex_la_DEPENDENCIES = \ libgnunetregexblock.la if HAVE_MYSQL noinst_mysql_progs = \ gnunet-regex-simulation-profiler gnunet_regex_simulation_profiler_SOURCES = \ gnunet-regex-simulation-profiler.c gnunet_regex_simulation_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/mysql/libgnunetmysql.la gnunet_regex_simulation_profiler_DEPENDENCIES = \ libgnunetregex_internal.a endif libgnunetregextest_a_SOURCES = \ regex_test_lib.c regex_test_lib.h \ regex_test_graph.c \ regex_test_random.c libgnunetregextest_a_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/regex/libgnunetregex_internal.a libgnunetregextest_a_DEPENDENCIES = \ libgnunetregex_internal.a if HAVE_TESTING noinst_PROGRAMS = $(noinst_mysql_progs) \ perf-regex \ gnunet-regex-profiler endif perf_regex_SOURCES = \ perf-regex.c perf_regex_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/util/libgnunetutil.la perf_regex_DEPENDENCIES = \ libgnunetregex_internal.a \ libgnunetregextest.a gnunet_regex_profiler_SOURCES = \ gnunet-regex-profiler.c gnunet_regex_profiler_LDADD = -lm \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_regex_profiler_DEPENDENCIES = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/dht/libgnunetdht.la \ libgnunetregex_internal.a \ libgnunetregextest.a gnunet_daemon_regexprofiler_SOURCES = \ gnunet-daemon-regexprofiler.c gnunet_daemon_regexprofiler_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_daemon_regexprofiler_DEPENDENCIES = \ $(top_builddir)/src/dht/libgnunetdht.la \ libgnunetregextest.a \ libgnunetregex_internal.a check_PROGRAMS = \ test_regex_eval_api \ test_regex_iterate_api \ test_regex_proofs \ test_regex_graph_api \ test_regex_api if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_regex_eval_api_SOURCES = \ test_regex_eval_api.c test_regex_eval_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la test_regex_api_SOURCES = \ test_regex_api.c test_regex_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_regex_iterate_api_SOURCES = \ test_regex_iterate_api.c test_regex_iterate_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/util/libgnunetutil.la test_regex_proofs_SOURCES = \ test_regex_proofs.c test_regex_proofs_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la test_regex_graph_api_SOURCES = \ test_regex_graph_api.c test_regex_graph_api_LDADD = -lm \ $(top_builddir)/src/regex/libgnunetregex_internal.a \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/regex/libgnunetregextest.a \ $(top_builddir)/src/regex/libgnunetregexblock.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ regex_simulation_profiler_test.conf \ test_regex_api_data.conf gnunet-0.10.1/src/regex/perf-regex.c0000644000175000017500000000655612225777501014147 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/regex/perf-regex.c * @brief Test how long it takes to create a automaton from a string regex. * @author Bartlomiej Polot */ #include #include #include "platform.h" #include "regex_internal_lib.h" #include "regex_test_lib.h" /** * Print information about the given node and its edges * to stdout. * * @param cls closure, unused. * @param key hash for current state. * @param proof proof for current state. * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. * @param num_edges number of edges leaving current state. * @param edges edges leaving current state. */ static void print_edge (void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges) { unsigned int i; printf ("%s: %s, proof: `%s'\n", GNUNET_h2s (key), accepting ? "ACCEPTING" : "", proof); for (i = 0; i < num_edges; i++) printf (" `%s': %s\n", edges[i].label, GNUNET_h2s (&edges[i].destination)); } /** * The main function of the regex performace test. * * Read a set of regex from a file, combine them and create a DFA from the * resulting combined regex. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { struct REGEX_INTERNAL_Automaton* dfa; char **regexes; char *buffer; char *regex; int compression; long size; GNUNET_log_setup ("perf-regex", "DEBUG", NULL); if (3 != argc) { fprintf (stderr, "Usage: %s REGEX_FILE COMPRESSION\n", argv[0]); return 1; } regexes = REGEX_TEST_read_from_file (argv[1]); if (NULL == regexes) { fprintf (stderr, "Failed to read regexes from `%s'\n", argv[1]); return 2; } compression = atoi (argv[2]); buffer = REGEX_TEST_combine (regexes); GNUNET_asprintf (®ex, "GNUNET_REGEX_PROFILER_(%s)(0|1)*", buffer); size = strlen (regex); fprintf (stderr, "Combined regex (%ld bytes):\n%s\n", size, regex); dfa = REGEX_INTERNAL_construct_dfa (regex, size, compression); printf ("********* ALL EDGES *********'\n"); REGEX_INTERNAL_iterate_all_edges (dfa, &print_edge, NULL); printf ("\n\n********* REACHABLE EDGES *********'\n"); REGEX_INTERNAL_iterate_reachable_edges (dfa, &print_edge, NULL); REGEX_INTERNAL_automaton_destroy (dfa); GNUNET_free (buffer); REGEX_TEST_free_from_file (regexes); GNUNET_free (regex); return 0; } /* end of prof-regex.c */ gnunet-0.10.1/src/regex/regex_internal_lib.h0000644000175000017500000002073412225777503015740 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/regex_internal_lib.h * @brief library to parse regular expressions into dfa * @author Maximilian Szengel */ #ifndef REGEX_INTERNAL_LIB_H #define REGEX_INTERNAL_LIB_H #include "gnunet_util_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" #include "regex_block_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Automaton (NFA/DFA) representation. */ struct REGEX_INTERNAL_Automaton; /** * Construct DFA for the given 'regex' of length 'len'. * * Path compression means, that for example a DFA o -> a -> b -> c -> o will be * compressed to o -> abc -> o. Note that this parameter influences the * non-determinism of states of the resulting NFA in the DHT (number of outgoing * edges with the same label). For example for an application that stores IPv4 * addresses as bitstrings it could make sense to limit the path compression to * 4 or 8. * * @param regex regular expression string. * @param len length of the regular expression. * @param max_path_len limit the path compression length to the * given value. If set to 1, no path compression is applied. Set to 0 for * maximal possible path compression (generally not desireable). * @return DFA, needs to be freed using REGEX_INTERNAL_automaton_destroy. */ struct REGEX_INTERNAL_Automaton * REGEX_INTERNAL_construct_dfa (const char *regex, const size_t len, unsigned int max_path_len); /** * Free the memory allocated by constructing the REGEX_INTERNAL_Automaton. * data structure. * * @param a automaton to be destroyed. */ void REGEX_INTERNAL_automaton_destroy (struct REGEX_INTERNAL_Automaton *a); /** * Evaluates the given 'string' against the given compiled regex. * * @param a automaton. * @param string string to check. * * @return 0 if string matches, non 0 otherwise. */ int REGEX_INTERNAL_eval (struct REGEX_INTERNAL_Automaton *a, const char *string); /** * Get the first key for the given 'input_string'. This hashes * the first x bits of the 'input_string'. * * @param input_string string. * @param string_len length of the 'input_string'. * @param key pointer to where to write the hash code. * * @return number of bits of 'input_string' that have been consumed * to construct the key */ size_t REGEX_INTERNAL_get_first_key (const char *input_string, size_t string_len, struct GNUNET_HashCode * key); /** * Iterator callback function. * * @param cls closure. * @param key hash for current state. * @param proof proof for current state * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. * @param num_edges number of edges leaving current state. * @param edges edges leaving current state. */ typedef void (*REGEX_INTERNAL_KeyIterator)(void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges); /** * Iterate over all edges starting from start state of automaton 'a'. Calling * iterator for each edge. * * @param a automaton. * @param iterator iterator called for each edge. * @param iterator_cls closure. */ void REGEX_INTERNAL_iterate_all_edges (struct REGEX_INTERNAL_Automaton *a, REGEX_INTERNAL_KeyIterator iterator, void *iterator_cls); /** * Iterate over all edges of automaton 'a' that are reachable from a state with * a proof of at least GNUNET_REGEX_INITIAL_BYTES characters. * * Call the iterator for each such edge. * * @param a automaton. * @param iterator iterator called for each reachable edge. * @param iterator_cls closure. */ void REGEX_INTERNAL_iterate_reachable_edges (struct REGEX_INTERNAL_Automaton *a, REGEX_INTERNAL_KeyIterator iterator, void *iterator_cls); /** * Handle to store cached data about a regex announce. */ struct REGEX_INTERNAL_Announcement; /** * Handle to store data about a regex search. */ struct REGEX_INTERNAL_Search; /** * Announce a regular expression: put all states of the automaton in the DHT. * Does not free resources, must call REGEX_INTERNAL_announce_cancel for that. * * @param dht An existing and valid DHT service handle. CANNOT be NULL. * @param priv our private key, must remain valid until the announcement is cancelled * @param regex Regular expression to announce. * @param compression How many characters per edge can we squeeze? * @param stats Optional statistics handle to report usage. Can be NULL. * * @return Handle to reuse o free cached resources. * Must be freed by calling REGEX_INTERNAL_announce_cancel. */ struct REGEX_INTERNAL_Announcement * REGEX_INTERNAL_announce (struct GNUNET_DHT_Handle *dht, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const char *regex, uint16_t compression, struct GNUNET_STATISTICS_Handle *stats); /** * Announce again a regular expression previously announced. * Does use caching to speed up process. * * @param h Handle returned by a previous REGEX_INTERNAL_announce call. */ void REGEX_INTERNAL_reannounce (struct REGEX_INTERNAL_Announcement *h); /** * Clear all cached data used by a regex announce. * Does not close DHT connection. * * @param h Handle returned by a previous REGEX_INTERNAL_announce call. */ void REGEX_INTERNAL_announce_cancel (struct REGEX_INTERNAL_Announcement *h); /** * Search callback function. * * @param cls Closure provided in REGEX_INTERNAL_search. * @param id Peer providing a regex that matches the string. * @param get_path Path of the get request. * @param get_path_length Lenght of get_path. * @param put_path Path of the put request. * @param put_path_length Length of the put_path. */ typedef void (*REGEX_INTERNAL_Found)(void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length); /** * Search for a peer offering a regex matching certain string in the DHT. * The search runs until REGEX_INTERNAL_search_cancel is called, even if results * are returned. * * @param dht An existing and valid DHT service handle. * @param string String to match against the regexes in the DHT. * @param callback Callback for found peers. * @param callback_cls Closure for @c callback. * @param stats Optional statistics handle to report usage. Can be NULL. * * @return Handle to stop search and free resources. * Must be freed by calling REGEX_INTERNAL_search_cancel. */ struct REGEX_INTERNAL_Search * REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht, const char *string, REGEX_INTERNAL_Found callback, void *callback_cls, struct GNUNET_STATISTICS_Handle *stats); /** * Stop search and free all data used by a REGEX_INTERNAL_search call. * Does not close DHT connection. * * @param h Handle returned by a previous REGEX_INTERNAL_search call. */ void REGEX_INTERNAL_search_cancel (struct REGEX_INTERNAL_Search *h); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* end of regex_internal_lib.h */ #endif gnunet-0.10.1/src/regex/regex_block_lib.c0000644000175000017500000003103312255426423015176 00000000000000/* This file is part of GNUnet. (C) 2012,2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Bartlomiej Polot * @file regex/regex_block_lib.c * @brief functions for manipulating non-accept blocks stored for * regex in the DHT */ #include "platform.h" #include "regex_block_lib.h" #include "gnunet_constants.h" #define LOG(kind,...) GNUNET_log_from (kind,"regex-bck",__VA_ARGS__) GNUNET_NETWORK_STRUCT_BEGIN /** * Information for each edge. */ struct EdgeInfo { /** * Index of the destination of this edge in the * unique destinations array. */ uint16_t destination_index GNUNET_PACKED; /** * Number of bytes the token for this edge takes in the * token area. */ uint16_t token_length GNUNET_PACKED; }; /** * @brief Block to announce a regex state. */ struct RegexBlock { /** * Length of the proof regex string. */ uint16_t proof_len GNUNET_PACKED; /** * Is this state an accepting state? */ int16_t is_accepting GNUNET_PACKED; /** * Number of edges parting from this state. */ uint16_t num_edges GNUNET_PACKED; /** * Nubmer of unique destinations reachable from this state. */ uint16_t num_destinations GNUNET_PACKED; /* followed by 'struct GNUNET_HashCode[num_destinations]' */ /* followed by 'struct EdgeInfo[edge_destination_indices]' */ /* followed by 'char proof[n_proof]', NOT 0-terminated */ /* followed by 'char tokens[num_edges][edge_info[k].token_length]'; essentially all of the tokens one after the other in the order of the edges; tokens are NOT 0-terminated */ }; GNUNET_NETWORK_STRUCT_END /** * Test if this block is marked as being an accept state. * * @param block block to test * @param size number of bytes in block * @return #GNUNET_YES if the block is accepting, #GNUNET_NO if not */ int GNUNET_BLOCK_is_accepting (const struct RegexBlock *block, size_t size) { if (size < sizeof (struct RegexBlock)) { GNUNET_break_op (0); return GNUNET_SYSERR; } return ntohs (block->is_accepting); } /** * Check if the given 'proof' matches the given 'key'. * * @param proof partial regex of a state * @param proof_len number of bytes in 'proof' * @param key hash of a state. * @return #GNUNET_OK if the proof is valid for the given key. */ int REGEX_BLOCK_check_proof (const char *proof, size_t proof_len, const struct GNUNET_HashCode *key) { struct GNUNET_HashCode key_check; if ( (NULL == proof) || (NULL == key)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Proof check failed, was NULL.\n"); return GNUNET_NO; } GNUNET_CRYPTO_hash (proof, proof_len, &key_check); return (0 == GNUNET_CRYPTO_hash_cmp (key, &key_check)) ? GNUNET_OK : GNUNET_NO; } /** * Struct to keep track of the xquery while iterating all the edges in a block. */ struct CheckEdgeContext { /** * Xquery: string we are looking for. */ const char *xquery; /** * Has any edge matched the xquery so far? (GNUNET_OK / GNUNET_NO) */ int found; }; /** * Iterator over all edges in a block, checking for a presence of a given query. * * @param cls Closure, (xquery context). * @param token Token that follows to next state. * @param len Lenght of token. * @param key Hash of next state. * * @return GNUNET_YES, to keep iterating */ static int check_edge (void *cls, const char *token, size_t len, const struct GNUNET_HashCode *key) { struct CheckEdgeContext *ctx = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "edge %.*s [%u]: %s->%s\n", (int) len, token, len, GNUNET_h2s(key)); if (NULL == ctx->xquery) return GNUNET_YES; if (strlen (ctx->xquery) < len) return GNUNET_YES; /* too long */ if (0 == strncmp (ctx->xquery, token, len)) ctx->found = GNUNET_OK; return GNUNET_YES; /* keep checking for malformed data! */ } /** * Check if the regex block is well formed, including all edges. * * @param block The start of the block. * @param size The size of the block. * @param query the query for the block * @param xquery String describing the edge we are looking for. * Can be NULL in case this is a put block. * @return #GNUNET_OK in case it's fine. * #GNUNET_NO in case the xquery exists and is not found (IRRELEVANT). * #GNUNET_SYSERR if the block is invalid. */ int REGEX_BLOCK_check (const struct RegexBlock *block, size_t size, const struct GNUNET_HashCode *query, const char *xquery) { struct GNUNET_HashCode key; struct CheckEdgeContext ctx; int res; LOG (GNUNET_ERROR_TYPE_DEBUG, "Block check\n"); if (GNUNET_OK != REGEX_BLOCK_get_key (block, size, &key)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (NULL != query && 0 != memcmp (&key, query, sizeof (struct GNUNET_HashCode))) { GNUNET_break_op (0); return GNUNET_SYSERR; } if ( (GNUNET_YES == ntohs (block->is_accepting)) && ( (NULL == xquery) || ('\0' == xquery[0]) ) ) { LOG (GNUNET_ERROR_TYPE_DEBUG, " out! Is accepting: %u, xquery %p\n", ntohs(block->is_accepting), xquery); return GNUNET_OK; } ctx.xquery = xquery; ctx.found = GNUNET_NO; res = REGEX_BLOCK_iterate (block, size, &check_edge, &ctx); if (GNUNET_SYSERR == res) return GNUNET_SYSERR; if (NULL == xquery) return GNUNET_YES; LOG (GNUNET_ERROR_TYPE_DEBUG, "Result %d\n", ctx.found); return ctx.found; } /** * Obtain the key that a particular block is to be stored under. * * @param block block to get the key from * @param block_len number of bytes in block * @param key where to store the key * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block is malformed */ int REGEX_BLOCK_get_key (const struct RegexBlock *block, size_t block_len, struct GNUNET_HashCode *key) { uint16_t len; const struct GNUNET_HashCode *destinations; const struct EdgeInfo *edges; uint16_t num_destinations; uint16_t num_edges; size_t total; if (block_len < sizeof (struct RegexBlock)) { GNUNET_break_op (0); return GNUNET_SYSERR; } num_destinations = ntohs (block->num_destinations); num_edges = ntohs (block->num_edges); len = ntohs (block->proof_len); destinations = (const struct GNUNET_HashCode *) &block[1]; edges = (const struct EdgeInfo *) &destinations[num_destinations]; total = sizeof (struct RegexBlock) + num_destinations * sizeof (struct GNUNET_HashCode) + num_edges * sizeof (struct EdgeInfo) + len; if (block_len < total) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_CRYPTO_hash (&edges[num_edges], len, key); return GNUNET_OK; } /** * Iterate over all edges of a block of a regex state. * * @param block Block to iterate over. * @param size Size of @a block. * @param iterator Function to call on each edge in the block. * @param iter_cls Closure for the @a iterator. * @return #GNUNET_SYSERR if an error has been encountered. * #GNUNET_OK if no error has been encountered. * Note that if the iterator stops the iteration by returning * #GNUNET_NO, the block will no longer be checked for further errors. * The return value will be GNUNET_OK meaning that no errors were * found until the edge last notified to the iterator, but there might * be errors in further edges. */ int REGEX_BLOCK_iterate (const struct RegexBlock *block, size_t size, REGEX_INTERNAL_EgdeIterator iterator, void *iter_cls) { uint16_t len; const struct GNUNET_HashCode *destinations; const struct EdgeInfo *edges; const char *aux; uint16_t num_destinations; uint16_t num_edges; size_t total; unsigned int n; size_t off; LOG (GNUNET_ERROR_TYPE_DEBUG, "Block iterate\n"); if (size < sizeof (struct RegexBlock)) { GNUNET_break_op (0); return GNUNET_SYSERR; } num_destinations = ntohs (block->num_destinations); num_edges = ntohs (block->num_edges); len = ntohs (block->proof_len); destinations = (const struct GNUNET_HashCode *) &block[1]; edges = (const struct EdgeInfo *) &destinations[num_destinations]; aux = (const char *) &edges[num_edges]; total = sizeof (struct RegexBlock) + num_destinations * sizeof (struct GNUNET_HashCode) + num_edges * sizeof (struct EdgeInfo) + len; if (size < total) { GNUNET_break_op (0); return GNUNET_SYSERR; } for (n=0;n UINT16_MAX) { GNUNET_break (0); return NULL; } unique_destinations = 0; total = sizeof (struct RegexBlock) + len; for (i=0;i UINT16_MAX) { GNUNET_break (0); return NULL; } total += slen; for (j=0;j= 1024) { GNUNET_break (0); return NULL; } destination_indices[i] = j; if (j == unique_destinations) destinations[unique_destinations++] = edges[i].destination; } total += num_edges * sizeof (struct EdgeInfo) + unique_destinations * sizeof (struct GNUNET_HashCode); if (total >= GNUNET_CONSTANTS_MAX_BLOCK_SIZE) { GNUNET_break (0); return NULL; } block = GNUNET_malloc (total); block->proof_len = htons (len); block->is_accepting = htons (accepting); block->num_edges = htons (num_edges); block->num_destinations = htons (unique_destinations); dests = (struct GNUNET_HashCode *) &block[1]; memcpy (dests, destinations, sizeof (struct GNUNET_HashCode) * unique_destinations); edgeinfos = (struct EdgeInfo *) &dests[unique_destinations]; aux = (char *) &edgeinfos[num_edges]; off = len; memcpy (aux, proof, len); for (i=0;is) printf ("'%s'\n", ctx->s); else printf ("NULL\n"); for (p = ctx->head; NULL != p; p = p->next) { debugctx (p, level + 1); } } */ /** * Extract a string from all prefix-combined regexes. * * @param ctx Context with 0 or more regexes. * * @return Regex that matches any of the added regexes. */ static char * regex_combine (struct RegexCombineCtx *ctx) { struct RegexCombineCtx *p; size_t len; char *regex; char *tmp; char *s; int opt; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new combine %s\n", ctx->s); regex = GNUNET_strdup (""); opt = GNUNET_NO; for (p = ctx->head; NULL != p; p = p->next) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding '%s' to innner %s\n", p->s, ctx->s); s = regex_combine (p); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " total '%s'\n", s); if (strlen(s) == 0) { opt = GNUNET_YES; } else { GNUNET_asprintf (&tmp, "%s%s|", regex, s); GNUNET_free_non_null (regex); regex = tmp; } GNUNET_free_non_null (s); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " so far '%s' for inner %s\n", regex, ctx->s); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "opt: %d, innner: '%s'\n", opt, regex); len = strlen (regex); if (0 == len) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "empty, returning ''\n"); GNUNET_free (regex); return NULL == ctx->s ? NULL : GNUNET_strdup (ctx->s); } if ('|' == regex[len - 1]) regex[len - 1] = '\0'; if (NULL != ctx->s) { if (opt) GNUNET_asprintf (&s, "%s(%s)?", ctx->s, regex); else GNUNET_asprintf (&s, "%s(%s)", ctx->s, regex); GNUNET_free (regex); regex = s; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "partial: %s\n", regex); return regex; } /** * Get the number of matching characters on the prefix of both strings. * * @param s1 String 1. * @param s2 String 2. * * @return Number of characters of matching prefix. */ static unsigned int get_prefix_length (const char *s1, const char *s2) { unsigned int l1; unsigned int l2; unsigned int limit; unsigned int i; l1 = strlen (s1); l2 = strlen (s2); limit = l1 > l2 ? l2 : l1; for (i = 1; i <= limit; i++) { if (0 != strncmp (s1, s2, i)) return i - 1; } return limit; } /** * Return the child context with the longest prefix match with the regex. * Usually only one child will match, search all just in case. * * @param ctx Context whose children to search. * @param regex String to match. * * @return Child with the longest prefix, NULL if no child matches. */ static struct RegexCombineCtx * get_longest_prefix (struct RegexCombineCtx *ctx, const char *regex) { struct RegexCombineCtx *p; struct RegexCombineCtx *best; unsigned int l; unsigned int best_l; best_l = 0; best = NULL; for (p = ctx->head; NULL != p; p = p->next) { l = get_prefix_length (p->s, regex); if (l > best_l) { GNUNET_break (0 == best_l); best = p; best_l = l; } } return best; } /** * Add a single regex to a context, combining with exisiting regex by-prefix. * * @param ctx Context with 0 or more regexes. * @param regex Regex to add. */ static void regex_add (struct RegexCombineCtx *ctx, const char *regex) { struct RegexCombineCtx *p; struct RegexCombineCtx *newctx; unsigned int prefix_l; const char *rest_r; const char *rest_s; size_t len; if (0 == strlen (regex)) return; p = get_longest_prefix (ctx, regex); if (NULL != p) /* There is some prefix match, reduce regex and try again */ { prefix_l = get_prefix_length (p->s, regex); rest_s = &p->s[prefix_l]; rest_r = ®ex[prefix_l]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "chosen '%s' [%u]\n", p->s, prefix_l); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "prefix r '%.*s'\n", prefix_l, p->s); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "rest r '%s'\n", rest_r); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "rest s '%s'\n", rest_s); len = strlen (p->s); if (prefix_l < len) /* only partial match, split existing state */ { newctx = GNUNET_new (struct RegexCombineCtx); newctx->head = p->head; newctx->tail = p->tail; newctx->s = GNUNET_malloc(len - prefix_l + 1); strncpy (newctx->s, rest_s, len - prefix_l + 1); p->head = newctx; p->tail = newctx; p->s[prefix_l] = '\0'; } regex_add (p, rest_r); return; } /* There is no prefix match, add new */ if (NULL == ctx->head && NULL != ctx->s) { /* this was the end before, add empty string */ newctx = GNUNET_new (struct RegexCombineCtx); newctx->s = GNUNET_strdup (""); GNUNET_CONTAINER_DLL_insert (ctx->head, ctx->tail, newctx); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " no match\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " new state %s\n", regex); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " under %s\n", ctx->s); newctx = GNUNET_new (struct RegexCombineCtx); newctx->s = GNUNET_strdup (regex); GNUNET_CONTAINER_DLL_insert (ctx->head, ctx->tail, newctx); } /** * Free all resources used by the context node and all its children. * * @param ctx Context to free. */ static void regex_ctx_destroy (struct RegexCombineCtx *ctx) { struct RegexCombineCtx *p; struct RegexCombineCtx *next; for (p = ctx->head; NULL != p; p = next) { next = p->next; regex_ctx_destroy (p); } GNUNET_free_non_null (ctx->s); /* 's' on root node is null */ GNUNET_free (ctx); } /** * Return a prefix-combine regex that matches the same strings as * any of the original regexes. * * WARNING: only useful for reading specific regexes for specific applications, * namely the gnunet-regex-profiler / gnunet-regex-daemon. * This function DOES NOT support arbitrary regex combining. */ char * REGEX_TEST_combine (char * const regexes[]) { unsigned int i; char *combined; const char *current; struct RegexCombineCtx *ctx; ctx = GNUNET_new (struct RegexCombineCtx); for (i = 0; regexes[i]; i++) { current = regexes[i]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Regex %u: %s\n", i, current); regex_add (ctx, current); /* debugctx (ctx, 0); */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\nCombining...\n"); /* debugctx (ctx, 0); */ combined = regex_combine (ctx); regex_ctx_destroy (ctx); return combined; } /** * Read a set of regexes from a file, one per line and return them in an array * suitable for REGEX_TEST_combine. * The array must be free'd using REGEX_TEST_free_from_file. * * @param filename Name of the file containing the regexes. * * @return A newly allocated, NULL terminated array of regexes. */ char ** REGEX_TEST_read_from_file (const char *filename) { struct GNUNET_DISK_FileHandle *f; unsigned int nr; unsigned int offset; off_t size; size_t len; char *buffer; char *regex; char **regexes; f = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == f) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't open file %s for reading\n", filename); return NULL; } if (GNUNET_OK != GNUNET_DISK_file_handle_size (f, &size)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Can't get size of file %s\n", filename); GNUNET_DISK_file_close (f); return NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "using file %s, size %llu\n", filename, (unsigned long long) size); buffer = GNUNET_malloc (size + 1); GNUNET_DISK_file_read (f, buffer, size); GNUNET_DISK_file_close (f); regexes = GNUNET_malloc (sizeof (char *)); nr = 1; offset = 0; regex = NULL; do { if (NULL == regex) regex = GNUNET_malloc (size + 1); len = (size_t) sscanf (&buffer[offset], "%s", regex); if (0 == len) break; len = strlen (regex); offset += len + 1; if (len < 1) continue; regex[len] = '\0'; regex = GNUNET_realloc (regex, len + 1); GNUNET_array_grow (regexes, nr, nr + 1); GNUNET_assert (NULL == regexes[nr - 2]); regexes[nr - 2] = regex; regexes[nr - 1] = NULL; regex = NULL; } while (offset < size); GNUNET_free_non_null (regex); GNUNET_free (buffer); return regexes; } /** * Free all memory reserved for a set of regexes created by read_from_file. * * @param regexes NULL-terminated array of regexes. */ void REGEX_TEST_free_from_file (char **regexes) { unsigned int i; for (i = 0; regexes[i]; i++) GNUNET_free (regexes[i]); GNUNET_free (regexes); } /* end of regex_test_lib.c */ gnunet-0.10.1/src/regex/regex_api.c0000644000175000017500000002147712307322113014027 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/regex_api.c * @brief access regex service to advertise capabilities via regex and discover * respective peers using matching strings * @author Maximilian Szengel * @author Christian Grothoff */ #include "platform.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" #include "gnunet_regex_service.h" #include "regex_ipc.h" /** * Handle to store cached data about a regex announce. */ struct GNUNET_REGEX_Announcement { /** * Connection to the regex service. */ struct GNUNET_CLIENT_Connection *client; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Message we're sending to the service. */ struct AnnounceMessage msg; }; /** * We got a response (!?) or disconnect after asking regex * to do the announcement. Retry. * * @param cls the 'struct GNUNET_REGEX_Announcement' to retry * @param msg NULL on disconnect */ static void handle_a_reconnect (void *cls, const struct GNUNET_MessageHeader *msg); /** * Try sending the announcement request to regex. On * errors (i.e. regex died), try again. * * @param a the announcement to retry */ static void retry_announcement (struct GNUNET_REGEX_Announcement *a) { GNUNET_assert (NULL != a->client); GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (a->client, &a->msg.header, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &handle_a_reconnect, a)); } /** * We got a response (!?) or disconnect after asking regex * to do the announcement. Retry. * * @param cls the 'struct GNUNET_REGEX_Announcement' to retry * @param msg NULL on disconnect */ static void handle_a_reconnect (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_REGEX_Announcement *a = cls; GNUNET_CLIENT_disconnect (a->client); a->client = GNUNET_CLIENT_connect ("regex", a->cfg); retry_announcement (a); } /** * Announce the given peer under the given regular expression. Does * not free resources, must call #GNUNET_REGEX_announce_cancel for * that. * * @param cfg configuration to use * @param regex Regular expression to announce. * @param refresh_delay after what delay should the announcement be repeated? * @param compression How many characters per edge can we squeeze? * @return Handle to reuse o free cached resources. * Must be freed by calling #GNUNET_REGEX_announce_cancel. */ struct GNUNET_REGEX_Announcement * GNUNET_REGEX_announce (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *regex, struct GNUNET_TIME_Relative refresh_delay, uint16_t compression) { struct GNUNET_REGEX_Announcement *a; size_t slen; slen = strlen (regex) + 1; if (slen + sizeof (struct AnnounceMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Regex `%s' is too long!\n"), regex); GNUNET_break (0); return NULL; } a = GNUNET_malloc (sizeof (struct GNUNET_REGEX_Announcement) + slen); a->cfg = cfg; a->client = GNUNET_CLIENT_connect ("regex", cfg); if (NULL == a->client) { GNUNET_free (a); return NULL; } a->msg.header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_ANNOUNCE); a->msg.header.size = htons (slen + sizeof (struct AnnounceMessage)); a->msg.compression = htons (compression); a->msg.reserved = htons (0); a->msg.refresh_delay = GNUNET_TIME_relative_hton (refresh_delay); memcpy (&a[1], regex, slen); retry_announcement (a); return a; } /** * Stop announcing the regex specified by the given handle. * * @param a handle returned by a previous GNUNET_REGEX_announce call. */ void GNUNET_REGEX_announce_cancel (struct GNUNET_REGEX_Announcement *a) { GNUNET_CLIENT_disconnect (a->client); GNUNET_free (a); } /** * Handle to store data about a regex search. */ struct GNUNET_REGEX_Search { /** * Connection to the regex service. */ struct GNUNET_CLIENT_Connection *client; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Function to call with results. */ GNUNET_REGEX_Found callback; /** * Closure for @e callback. */ void *callback_cls; /** * Search message to transmit to the service. */ struct RegexSearchMessage *msg; }; /** * We got a response or disconnect after asking regex * to do the search. Handle it. * * @param cls the `struct GNUNET_REGEX_Search` to retry * @param msg NULL on disconnect */ static void handle_search_response (void *cls, const struct GNUNET_MessageHeader *msg); /** * Try sending the search request to regex. On * errors (i.e. regex died), try again. * * @param s the search to retry */ static void retry_search (struct GNUNET_REGEX_Search *s) { GNUNET_assert (NULL != s->client); GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (s->client, &s->msg->header, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &handle_search_response, s)); } /** * We got a response or disconnect after asking regex * to do the search. Handle it. * * @param cls the 'struct GNUNET_REGEX_Search' to retry * @param msg NULL on disconnect, otherwise presumably a response */ static void handle_search_response (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_REGEX_Search *s = cls; const struct ResultMessage *result; uint16_t size; uint16_t gpl; uint16_t ppl; if (NULL == msg) { GNUNET_CLIENT_disconnect (s->client); s->client = GNUNET_CLIENT_connect ("regex", s->cfg); retry_search (s); return; } size = ntohs (msg->size); if ( (GNUNET_MESSAGE_TYPE_REGEX_RESULT == ntohs (msg->type)) && (size >= sizeof (struct ResultMessage)) ) { result = (const struct ResultMessage *) msg; gpl = ntohs (result->get_path_length); ppl = ntohs (result->put_path_length); if (size == (sizeof (struct ResultMessage) + (gpl + ppl) * sizeof (struct GNUNET_PeerIdentity))) { const struct GNUNET_PeerIdentity *pid; GNUNET_CLIENT_receive (s->client, &handle_search_response, s, GNUNET_TIME_UNIT_FOREVER_REL); pid = &result->id; s->callback (s->callback_cls, pid, &pid[1], gpl, &pid[1 + gpl], ppl); return; } } GNUNET_break (0); GNUNET_CLIENT_disconnect (s->client); s->client = GNUNET_CLIENT_connect ("regex", s->cfg); retry_search (s); } /** * Search for a peer offering a regex matching certain string in the DHT. * The search runs until GNUNET_REGEX_search_cancel is called, even if results * are returned. * * @param cfg configuration to use * @param string String to match against the regexes in the DHT. * @param callback Callback for found peers. * @param callback_cls Closure for @c callback. * @return Handle to stop search and free resources. * Must be freed by calling GNUNET_REGEX_search_cancel. */ struct GNUNET_REGEX_Search * GNUNET_REGEX_search (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *string, GNUNET_REGEX_Found callback, void *callback_cls) { struct GNUNET_REGEX_Search *s; size_t slen; slen = strlen (string) + 1; s = GNUNET_new (struct GNUNET_REGEX_Search); s->cfg = cfg; s->client = GNUNET_CLIENT_connect ("regex", cfg); if (NULL == s->client) { GNUNET_free (s); return NULL; } s->callback = callback; s->callback_cls = callback_cls; s->msg = GNUNET_malloc (sizeof (struct RegexSearchMessage) + slen); s->msg->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH); s->msg->header.size = htons (sizeof (struct RegexSearchMessage) + slen); memcpy (&s->msg[1], string, slen); retry_search (s); return s; } /** * Stop search and free all data used by a GNUNET_REGEX_search call. * * @param s Handle returned by a previous GNUNET_REGEX_search call. */ void GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s) { GNUNET_CLIENT_disconnect (s->client); GNUNET_free (s->msg); GNUNET_free (s); } /* end of regex_api.c */ gnunet-0.10.1/src/regex/gnunet-daemon-regexprofiler.c0000644000175000017500000002547112225777501017514 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/gnunet-daemon-regexprofiler.c * @brief daemon that uses mesh to announce a regular expression. Used in * conjunction with gnunet-regex-profiler to announce regexes on serveral peers * without the need to explicitly connect to the mesh service running on the * peer from within the profiler. * @author Maximilian Szengel * @author Bartlomiej Polot */ #include "platform.h" #include "gnunet_util_lib.h" #include "regex_internal_lib.h" #include "regex_test_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" /** * Return value from 'main'. */ static int global_ret; /** * Configuration we use. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the statistics service. */ static struct GNUNET_STATISTICS_Handle *stats_handle; /** * Peer's dht handle. */ static struct GNUNET_DHT_Handle *dht_handle; /** * Peer's regex announce handle. */ static struct REGEX_INTERNAL_Announcement *announce_handle; /** * Periodically reannounce regex. */ static GNUNET_SCHEDULER_TaskIdentifier reannounce_task; /** * What's the maximum reannounce period. */ static struct GNUNET_TIME_Relative reannounce_period_max; /** * Maximal path compression length for regex announcing. */ static unsigned long long max_path_compression; /** * Name of the file containing policies that this peer should announce. One * policy per line. */ static char * policy_filename; /** * Prefix to add before every regex we're announcing. */ static char * regex_prefix; /** * Regex with prefix. */ static char *rx_with_pfx; /** * How many put rounds should we do. */ static unsigned int rounds = 3; /** * Private key for this peer. */ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n"); if (NULL != announce_handle) { REGEX_INTERNAL_announce_cancel (announce_handle); announce_handle = NULL; } if (NULL != dht_handle) { GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; } GNUNET_free (my_private_key); my_private_key = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Daemon for %s shutting down\n", policy_filename); } /** * Announce a previously announced regex re-using cached data. * * @param cls Closure (regex to announce if needed). * @param tc TaskContext. */ static void reannounce_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Relative random_delay; char *regex = cls; reannounce_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { GNUNET_free (regex); return; } if (0 == rounds--) { global_ret = 0; GNUNET_SCHEDULER_shutdown (); GNUNET_free (regex); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Announcing regex: %s\n", regex); GNUNET_STATISTICS_update (stats_handle, "# regexes announced", 1, GNUNET_NO); if (NULL == announce_handle && NULL != regex) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First time, creating regex: %s\n", regex); announce_handle = REGEX_INTERNAL_announce (dht_handle, my_private_key, regex, (unsigned int) max_path_compression, stats_handle); } else { GNUNET_assert (NULL != announce_handle); REGEX_INTERNAL_reannounce (announce_handle); } random_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, GNUNET_CRYPTO_random_u32 ( GNUNET_CRYPTO_QUALITY_WEAK, reannounce_period_max.rel_value_us)); reannounce_task = GNUNET_SCHEDULER_add_delayed (random_delay, &reannounce_regex, cls); } /** * Announce the given regular expression using regex and the path compression * length read from config. * * @param regex regular expression to announce on this peer's mesh. */ static void announce_regex (const char * regex) { char *copy; if (NULL == regex || 0 == strlen (regex)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot announce empty regex\n"); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Daemon for %s starting\n", policy_filename); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == reannounce_task); copy = GNUNET_strdup (regex); reannounce_task = GNUNET_SCHEDULER_add_now (reannounce_regex, (void *) copy); } /** * Scan through the policy_dir looking for the n-th filename. * * @param cls Closure (target number n). * @param filename complete filename (absolute path). * @return GNUNET_OK to continue to iterate, * GNUNET_NO to stop when found */ static int scan (void *cls, const char *filename) { long n = (long) cls; static long c = 0; if (c == n) { policy_filename = GNUNET_strdup (filename); return GNUNET_NO; } c++; return GNUNET_OK; } /** * @brief Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg_ configuration */ static void run (void *cls, char *const *args GNUNET_UNUSED, const char *cfgfile GNUNET_UNUSED, const struct GNUNET_CONFIGURATION_Handle *cfg_) { char *regex = NULL; char **components; char *policy_dir; long long unsigned int peer_id; cfg = cfg_; my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); GNUNET_assert (NULL != my_private_key); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "REGEXPROFILER", "MAX_PATH_COMPRESSION", &max_path_compression)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("%s service is lacking key configuration settings (%s). Exiting.\n"), "regexprofiler", "max_path_compression"); global_ret = GNUNET_SYSERR; GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER", "POLICY_DIR", &policy_dir)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "REGEXPROFILER", "POLICY_DIR"); global_ret = GNUNET_SYSERR; GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED", "PEERID", &peer_id)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "TESTBED", "PEERID"); global_ret = GNUNET_SYSERR; GNUNET_free (policy_dir); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "REGEXPROFILER", "REGEX_PREFIX", ®ex_prefix)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "REGEXPROFILER", "REGEX_PREFIX"); global_ret = GNUNET_SYSERR; GNUNET_free (policy_dir); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "REGEXPROFILER", "REANNOUNCE_PERIOD_MAX", &reannounce_period_max)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "reannounce_period_max not given. Using 10 minutes.\n"); reannounce_period_max = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10); } stats_handle = GNUNET_STATISTICS_create ("regexprofiler", cfg); dht_handle = GNUNET_DHT_connect (cfg, 1); if (NULL == dht_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not acquire dht handle. Exiting.\n"); global_ret = GNUNET_SYSERR; GNUNET_free (policy_dir); GNUNET_SCHEDULER_shutdown (); return; } /* Read regexes from policy files */ GNUNET_assert (-1 != GNUNET_DISK_directory_scan (policy_dir, &scan, (void *) (long) peer_id)); if (NULL == (components = REGEX_TEST_read_from_file (policy_filename))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Policy file %s contains no policies. Exiting.\n", policy_filename); global_ret = GNUNET_SYSERR; GNUNET_free (policy_dir); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_free (policy_dir); regex = REGEX_TEST_combine (components); REGEX_TEST_free_from_file (components); /* Announcing regexes from policy_filename */ GNUNET_asprintf (&rx_with_pfx, "%s(%s)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*", regex_prefix, regex); announce_regex (rx_with_pfx); GNUNET_free (regex); GNUNET_free (rx_with_pfx); /* Scheduled the task to clean up when shutdown is called */ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function of the regexprofiler service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "regexprofiler", gettext_noop ("Daemon to announce regular expressions for the peer using mesh."), options, &run, NULL)) ? global_ret : 1; } #ifdef LINUX #include /** * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ void __attribute__ ((constructor)) GNUNET_ARM_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); malloc_trim (0); } #endif /* end of gnunet-daemon-regexprofiler.c */ gnunet-0.10.1/src/regex/test_regex_graph_api.c0000644000175000017500000001166312225777501016261 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/test_regex_graph_api.c * @brief test for regex_graph.c * @author Maximilian Szengel */ #include #include #include "platform.h" #include "regex_internal_lib.h" #include "regex_test_lib.h" #include "regex_internal.h" #define KEEP_FILES 1 /** * Check if 'filename' exists and is not empty. * * @param filename name of the file that should be checked * * @return 0 if ok, non 0 on error. */ static int filecheck (const char *filename) { int error = 0; FILE *fp; /* Check if file was created and delete it again */ if (NULL == (fp = fopen (filename, "r"))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not find graph %s\n", filename); return 1; } GNUNET_break (0 == fseek (fp, 0L, SEEK_END)); if (1 > ftell (fp)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Graph writing failed, got empty file (%s)!\n", filename); error = 2; } GNUNET_assert (0 == fclose (fp)); if (!KEEP_FILES) { if (0 != unlink (filename)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink", filename); } return error; } int main (int argc, char *argv[]) { int error; struct REGEX_INTERNAL_Automaton *a; unsigned int i; const char *filename = "test_graph.dot"; const char *regex[12] = { "ab(c|d)+c*(a(b|c)+d)+(bla)+", "(bla)*", "b(lab)*la", "(ab)*", "ab(c|d)+c*(a(b|c)+d)+(bla)(bla)*", "z(abc|def)?xyz", "1*0(0|1)*", "a*b*", "a+X*y+c|p|R|Z*K*y*R+w|Y*6+n+h*k*w+V*F|W*B*e*", "a", "a|b", "PADPADPADPADPADPabcdefghixxxxxxxxxxxxxjklmnop*qstoisdjfguisdfguihsdfgbdsuivggsd" }; GNUNET_log_setup ("test-regex", "WARNING", NULL); error = 0; for (i = 0; i < 12; i++) { /* Check NFA graph creation */ a = REGEX_INTERNAL_construct_nfa (regex[i], strlen (regex[i])); REGEX_TEST_automaton_save_graph (a, filename, REGEX_TEST_GRAPH_DEFAULT); REGEX_INTERNAL_automaton_destroy (a); error += filecheck (filename); a = REGEX_INTERNAL_construct_nfa (regex[i], strlen (regex[i])); REGEX_TEST_automaton_save_graph (a, filename, REGEX_TEST_GRAPH_DEFAULT | REGEX_TEST_GRAPH_VERBOSE); REGEX_INTERNAL_automaton_destroy (a); error += filecheck (filename); a = REGEX_INTERNAL_construct_nfa (regex[i], strlen (regex[i])); REGEX_TEST_automaton_save_graph (a, filename, REGEX_TEST_GRAPH_DEFAULT | REGEX_TEST_GRAPH_COLORING); REGEX_INTERNAL_automaton_destroy (a); error += filecheck (filename); a = REGEX_INTERNAL_construct_nfa (regex[i], strlen (regex[i])); REGEX_TEST_automaton_save_graph (a, filename, REGEX_TEST_GRAPH_DEFAULT | REGEX_TEST_GRAPH_VERBOSE | REGEX_TEST_GRAPH_COLORING); REGEX_INTERNAL_automaton_destroy (a); error += filecheck (filename); /* Check DFA graph creation */ a = REGEX_INTERNAL_construct_dfa (regex[i], strlen (regex[i]), 0); REGEX_TEST_automaton_save_graph (a, filename, REGEX_TEST_GRAPH_DEFAULT); REGEX_INTERNAL_automaton_destroy (a); error += filecheck (filename); a = REGEX_INTERNAL_construct_dfa (regex[i], strlen (regex[i]), 0); REGEX_TEST_automaton_save_graph (a, filename, REGEX_TEST_GRAPH_DEFAULT | REGEX_TEST_GRAPH_VERBOSE); REGEX_INTERNAL_automaton_destroy (a); error += filecheck (filename); a = REGEX_INTERNAL_construct_dfa (regex[i], strlen (regex[i]), 0); REGEX_TEST_automaton_save_graph (a, filename, REGEX_TEST_GRAPH_DEFAULT | REGEX_TEST_GRAPH_COLORING); REGEX_INTERNAL_automaton_destroy (a); error += filecheck (filename); a = REGEX_INTERNAL_construct_dfa (regex[i], strlen (regex[i]), 4); REGEX_TEST_automaton_save_graph (a, filename, REGEX_TEST_GRAPH_DEFAULT); REGEX_INTERNAL_automaton_destroy (a); error += filecheck (filename); } return error; } gnunet-0.10.1/src/regex/gnunet-regex-simulation-profiler.c0000644000175000017500000004523012255010511020465 00000000000000/* This file is part of GNUnet. (C) 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file regex/gnunet-regex-simulation-profiler.c * @brief Regex profiler that dumps all DFAs into a database instead of * using the DHT (with mesh). * @author Maximilian Szengel * */ #include "platform.h" #include "gnunet_util_lib.h" #include "regex_internal_lib.h" #include "gnunet_mysql_lib.h" #include /** * MySQL statement to insert an edge. */ #define INSERT_EDGE_STMT "INSERT IGNORE INTO `%s` "\ "(`key`, `label`, `to_key`, `accepting`) "\ "VALUES (?, ?, ?, ?);" /** * MySQL statement to select a key count. */ #define SELECT_KEY_STMT "SELECT COUNT(*) FROM `%s` "\ "WHERE `key` = ? AND `label` = ?;" /** * Simple struct to keep track of progress, and print a * nice little percentage meter for long running tasks. */ struct ProgressMeter { /** * Total number of elements. */ unsigned int total; /** * Intervall for printing percentage. */ unsigned int modnum; /** * Number of dots to print. */ unsigned int dotnum; /** * Completed number. */ unsigned int completed; /** * Should the meter be printed? */ int print; /** * String to print on startup. */ char *startup_string; }; /** * Handle for the progress meter */ static struct ProgressMeter *meter; /** * Abort task identifier. */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * Shutdown task identifier. */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Scan task identifier; */ static GNUNET_SCHEDULER_TaskIdentifier scan_task; /** * Global testing status. */ static int result; /** * MySQL context. */ static struct GNUNET_MYSQL_Context *mysql_ctx; /** * MySQL prepared statement handle. */ static struct GNUNET_MYSQL_StatementHandle *stmt_handle; /** * MySQL prepared statement handle for `key` select. */ static struct GNUNET_MYSQL_StatementHandle *select_stmt_handle; /** * MySQL table name. */ static char *table_name; /** * Policy dir containing files that contain policies. */ static char *policy_dir; /** * Number of policy files. */ static unsigned int num_policy_files; /** * Number of policies. */ static unsigned int num_policies; /** * Maximal path compression length. */ static unsigned int max_path_compression; /** * Number of merged transitions. */ static unsigned long long num_merged_transitions; /** * Number of merged states from different policies. */ static unsigned long long num_merged_states; /** * Prefix to add before every regex we're announcing. */ static char *regex_prefix; /** * Create a meter to keep track of the progress of some task. * * @param total the total number of items to complete * @param start_string a string to prefix the meter with (if printing) * @param print GNUNET_YES to print the meter, GNUNET_NO to count * internally only * * @return the progress meter */ static struct ProgressMeter * create_meter (unsigned int total, char *start_string, int print) { struct ProgressMeter *ret; ret = GNUNET_new (struct ProgressMeter); ret->print = print; ret->total = total; ret->modnum = total / 4; if (ret->modnum == 0) /* Divide by zero check */ ret->modnum = 1; ret->dotnum = (total / 50) + 1; if (start_string != NULL) ret->startup_string = GNUNET_strdup (start_string); else ret->startup_string = GNUNET_strdup (""); return ret; } /** * Update progress meter (increment by one). * * @param meter the meter to update and print info for * * @return GNUNET_YES if called the total requested, * GNUNET_NO if more items expected */ static int update_meter (struct ProgressMeter *meter) { if (meter->print == GNUNET_YES) { if (meter->completed % meter->modnum == 0) { if (meter->completed == 0) { FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string); } else FPRINTF (stdout, "%d%%", (int) (((float) meter->completed / meter->total) * 100)); } else if (meter->completed % meter->dotnum == 0) FPRINTF (stdout, "%s", "."); if (meter->completed + 1 == meter->total) FPRINTF (stdout, "%d%%]\n", 100); fflush (stdout); } meter->completed++; if (meter->completed == meter->total) return GNUNET_YES; if (meter->completed > meter->total) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Progress meter overflow!!\n"); return GNUNET_NO; } /** * Reset progress meter. * * @param meter the meter to reset * * @return GNUNET_YES if meter reset, * GNUNET_SYSERR on error */ static int reset_meter (struct ProgressMeter *meter) { if (meter == NULL) return GNUNET_SYSERR; meter->completed = 0; return GNUNET_YES; } /** * Release resources for meter * * @param meter the meter to free */ static void free_meter (struct ProgressMeter *meter) { GNUNET_free_non_null (meter->startup_string); GNUNET_free (meter); } /** * Shutdown task. * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); if (NULL != mysql_ctx) GNUNET_MYSQL_context_destroy (mysql_ctx); if (NULL != meter) free_meter (meter); GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */ } /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_SCHEDULER_cancel (scan_task); scan_task = GNUNET_SCHEDULER_NO_TASK; result = GNUNET_SYSERR; GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } /** * Dummy function for prepared select. Always return GNUNET_OK. * * @param cls closure * @param num_values number of values. * @param values returned values from select stmt. * * @return GNUNET_OK */ static int return_ok (void *cls, unsigned int num_values, MYSQL_BIND * values) { return GNUNET_OK; } /** * Iterator over all states that inserts each state into the MySQL db. * * @param cls closure. * @param key hash for current state. * @param proof proof for current state. * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. * @param num_edges number of edges leaving current state. * @param edges edges leaving current state. */ static void regex_iterator (void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges) { unsigned int i; int result; unsigned long k_length; unsigned long e_length; unsigned long d_length; MYSQL_BIND rbind[1]; unsigned long long total; GNUNET_assert (NULL != mysql_ctx); for (i = 0; i < num_edges; i++) { k_length = sizeof (struct GNUNET_HashCode); e_length = strlen (edges[i].label); d_length = sizeof (struct GNUNET_HashCode); memset (rbind, 0, sizeof (rbind)); total = -1; rbind[0].buffer_type = MYSQL_TYPE_LONGLONG; rbind[0].buffer = &total; rbind[0].is_unsigned = GNUNET_YES; result = GNUNET_MYSQL_statement_run_prepared_select (mysql_ctx, select_stmt_handle, 1, rbind, &return_ok, NULL, MYSQL_TYPE_BLOB, key, sizeof (struct GNUNET_HashCode), &k_length, MYSQL_TYPE_STRING, edges[i].label, strlen (edges[i].label), &e_length, -1); if (GNUNET_SYSERR == result) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error executing prepared mysql select statement\n"); GNUNET_SCHEDULER_add_now (&do_abort, NULL); return; } if (-1 != total && total > 0) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Total: %llu (%s, %s)\n", total, GNUNET_h2s (key), edges[i].label); } result = GNUNET_MYSQL_statement_run_prepared (mysql_ctx, stmt_handle, NULL, MYSQL_TYPE_BLOB, key, sizeof (struct GNUNET_HashCode), &k_length, MYSQL_TYPE_STRING, edges[i].label, strlen (edges[i].label), &e_length, MYSQL_TYPE_BLOB, &edges[i].destination, sizeof (struct GNUNET_HashCode), &d_length, MYSQL_TYPE_LONG, &accepting, GNUNET_YES, -1); if (0 == result) { char *key_str = GNUNET_strdup (GNUNET_h2s (key)); char *to_key_str = GNUNET_strdup (GNUNET_h2s (&edges[i].destination)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Merged (%s, %s, %s, %i)\n", key_str, edges[i].label, to_key_str, accepting); GNUNET_free (key_str); GNUNET_free (to_key_str); num_merged_transitions++; } else if (-1 != total) { num_merged_states++; } if (GNUNET_SYSERR == result || (1 != result && 0 != result)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error executing prepared mysql statement for edge: Affected rows: %i, expected 0 or 1!\n", result); GNUNET_SCHEDULER_add_now (&do_abort, NULL); } } if (0 == num_edges) { k_length = sizeof (struct GNUNET_HashCode); e_length = 0; d_length = 0; result = GNUNET_MYSQL_statement_run_prepared (mysql_ctx, stmt_handle, NULL, MYSQL_TYPE_BLOB, key, sizeof (struct GNUNET_HashCode), &k_length, MYSQL_TYPE_STRING, NULL, 0, &e_length, MYSQL_TYPE_BLOB, NULL, 0, &d_length, MYSQL_TYPE_LONG, &accepting, GNUNET_YES, -1); if (1 != result && 0 != result) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error executing prepared mysql statement for edge: Affected rows: %i, expected 0 or 1!\n", result); GNUNET_SCHEDULER_add_now (&do_abort, NULL); } } } /** * Announce a regex by creating the DFA and iterating over each state, inserting * each state into a MySQL database. * * @param regex regular expression. * @return GNUNET_OK on success, GNUNET_SYSERR on failure. */ static int announce_regex (const char *regex) { struct REGEX_INTERNAL_Automaton *dfa; dfa = REGEX_INTERNAL_construct_dfa (regex, strlen (regex), max_path_compression); if (NULL == dfa) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create DFA for regex %s\n", regex); abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); return GNUNET_SYSERR; } REGEX_INTERNAL_iterate_all_edges (dfa, ®ex_iterator, NULL); REGEX_INTERNAL_automaton_destroy (dfa); return GNUNET_OK; } /** * Function called with a filename. * * @param cls closure * @param filename complete filename (absolute path) * @return GNUNET_OK to continue to iterate, * GNUNET_SYSERR to abort iteration with error! */ static int policy_filename_cb (void *cls, const char *filename) { char *regex; char *data; char *buf; uint64_t filesize; unsigned int offset; GNUNET_assert (NULL != filename); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Announcing regexes from file %s\n", filename); if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not find policy file %s\n", filename); return GNUNET_OK; } if (GNUNET_OK != GNUNET_DISK_file_size (filename, &filesize, GNUNET_YES, GNUNET_YES)) filesize = 0; if (0 == filesize) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Policy file %s is empty.\n", filename); return GNUNET_OK; } data = GNUNET_malloc (filesize); if (filesize != GNUNET_DISK_fn_read (filename, data, filesize)) { GNUNET_free (data); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not read policy file %s.\n", filename); return GNUNET_OK; } update_meter (meter); buf = data; offset = 0; regex = NULL; while (offset < (filesize - 1)) { offset++; if (((data[offset] == '\n')) && (buf != &data[offset])) { data[offset] = '|'; num_policies++; buf = &data[offset + 1]; } else if ((data[offset] == '\n') || (data[offset] == '\0')) buf = &data[offset + 1]; } data[offset] = '\0'; GNUNET_asprintf (®ex, "%s(%s)", regex_prefix, data); GNUNET_assert (NULL != regex); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Announcing regex: %s\n", regex); if (GNUNET_OK != announce_regex (regex)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not announce regex %s\n", regex); } GNUNET_free (regex); GNUNET_free (data); return GNUNET_OK; } /** * Iterate over files contained in policy_dir. * * @param cls NULL * @param tc the task context */ static void do_directory_scan (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Absolute start_time; struct GNUNET_TIME_Relative duration; char *stmt; /* Create an MySQL prepared statement for the inserts */ GNUNET_asprintf (&stmt, INSERT_EDGE_STMT, table_name); stmt_handle = GNUNET_MYSQL_statement_prepare (mysql_ctx, stmt); GNUNET_free (stmt); GNUNET_asprintf (&stmt, SELECT_KEY_STMT, table_name); select_stmt_handle = GNUNET_MYSQL_statement_prepare (mysql_ctx, stmt); GNUNET_free (stmt); GNUNET_assert (NULL != stmt_handle); meter = create_meter (num_policy_files, "Announcing policy files\n", GNUNET_YES); start_time = GNUNET_TIME_absolute_get (); GNUNET_DISK_directory_scan (policy_dir, &policy_filename_cb, stmt_handle); duration = GNUNET_TIME_absolute_get_duration (start_time); reset_meter (meter); free_meter (meter); meter = NULL; printf ("Announced %u files containing %u policies in %s\n" "Duplicate transitions: %llu\nMerged states: %llu\n", num_policy_files, num_policies, GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_NO), num_merged_transitions, num_merged_states); result = GNUNET_OK; shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param config configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { if (NULL == args[0]) { fprintf (stderr, _("No policy directory specified on command line. Exiting.\n")); result = GNUNET_SYSERR; return; } if (GNUNET_YES != GNUNET_DISK_directory_test (args[0], GNUNET_YES)) { fprintf (stderr, _("Specified policies directory does not exist. Exiting.\n")); result = GNUNET_SYSERR; return; } policy_dir = args[0]; num_policy_files = GNUNET_DISK_directory_scan (policy_dir, NULL, NULL); meter = NULL; if (NULL == table_name) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "No table name specified, using default \"NFA\".\n"); table_name = "NFA"; } mysql_ctx = GNUNET_MYSQL_context_create (config, "regex-mysql"); if (NULL == mysql_ctx) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create mysql context\n"); result = GNUNET_SYSERR; return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (config, "regex-mysql", "REGEX_PREFIX", ®ex_prefix)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("%s service is lacking key configuration settings (%s). Exiting.\n"), "regexprofiler", "regex_prefix"); result = GNUNET_SYSERR; return; } result = GNUNET_OK; scan_task = GNUNET_SCHEDULER_add_now (&do_directory_scan, NULL); /* Scheduled the task to clean up when shutdown is called */ shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); } /** * Main function. * * @param argc argument count * @param argv argument values * @return 0 on success */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'t', "table", "TABLENAME", gettext_noop ("name of the table to write DFAs"), 1, &GNUNET_GETOPT_set_string, &table_name}, {'p', "max-path-compression", "MAX_PATH_COMPRESSION", gettext_noop ("maximum path compression length"), 1, &GNUNET_GETOPT_set_uint, &max_path_compression}, GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; result = GNUNET_SYSERR; ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-regex-simulationprofiler [OPTIONS] policy-dir", _("Profiler for regex library"), options, &run, NULL); if (GNUNET_OK != ret) return ret; if (GNUNET_OK != result) return 1; return 0; } gnunet-0.10.1/src/regex/regex_internal_dht.c0000644000175000017500000006142112255010511015720 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/regex/regex_internal_dht.c * @brief library to announce regexes in the network and match strings * against published regexes. * @author Bartlomiej Polot */ #include "platform.h" #include "regex_internal_lib.h" #include "regex_block_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #define LOG(kind,...) GNUNET_log_from (kind,"regex-dht",__VA_ARGS__) #define DHT_REPLICATION 5 #define DHT_TTL GNUNET_TIME_UNIT_HOURS #define DHT_OPT GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE /** * Handle to store cached data about a regex announce. */ struct REGEX_INTERNAL_Announcement { /** * DHT handle to use, must be initialized externally. */ struct GNUNET_DHT_Handle *dht; /** * Regular expression. */ const char *regex; /** * Automaton representation of the regex (expensive to build). */ struct REGEX_INTERNAL_Automaton* dfa; /** * Our private key. */ const struct GNUNET_CRYPTO_EddsaPrivateKey *priv; /** * Optional statistics handle to report usage. Can be NULL. */ struct GNUNET_STATISTICS_Handle *stats; }; /** * Regex callback iterator to store own service description in the DHT. * * @param cls closure. * @param key hash for current state. * @param proof proof for current state. * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not. * @param num_edges number of edges leaving current state. * @param edges edges leaving current state. */ static void regex_iterator (void *cls, const struct GNUNET_HashCode *key, const char *proof, int accepting, unsigned int num_edges, const struct REGEX_BLOCK_Edge *edges) { struct REGEX_INTERNAL_Announcement *h = cls; struct RegexBlock *block; size_t size; unsigned int i; LOG (GNUNET_ERROR_TYPE_INFO, "DHT PUT for state %s with proof `%s' and %u edges\n", GNUNET_h2s (key), proof, num_edges); for (i = 0; i < num_edges; i++) { LOG (GNUNET_ERROR_TYPE_INFO, " edge %s towards %s (%s)\n", edges[i].label, GNUNET_h2s (&edges[i].destination), proof); } if (GNUNET_YES == accepting) { struct RegexAcceptBlock ab; LOG (GNUNET_ERROR_TYPE_INFO, "State %s is accepting, putting own id\n", GNUNET_h2s (key)); size = sizeof (struct RegexAcceptBlock); ab.purpose.size = ntohl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_HashCode)); ab.purpose.purpose = ntohl (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT); ab.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_DHT_MAX_EXPIRATION)); ab.key = *key; GNUNET_CRYPTO_eddsa_key_get_public (h->priv, &ab.peer.public_key); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (h->priv, &ab.purpose, &ab.signature)); GNUNET_STATISTICS_update (h->stats, "# regex accepting blocks stored", 1, GNUNET_NO); GNUNET_STATISTICS_update (h->stats, "# regex accepting block bytes stored", sizeof (struct RegexAcceptBlock), GNUNET_NO); (void) GNUNET_DHT_put (h->dht, key, DHT_REPLICATION, DHT_OPT | GNUNET_DHT_RO_RECORD_ROUTE, GNUNET_BLOCK_TYPE_REGEX_ACCEPT, size, &ab, GNUNET_TIME_relative_to_absolute (DHT_TTL), DHT_TTL, NULL, NULL); } block = REGEX_BLOCK_create (proof, num_edges, edges, accepting, &size); (void) GNUNET_DHT_put (h->dht, key, DHT_REPLICATION, DHT_OPT, GNUNET_BLOCK_TYPE_REGEX, size, block, GNUNET_TIME_relative_to_absolute (DHT_TTL), DHT_TTL, NULL, NULL); GNUNET_STATISTICS_update (h->stats, "# regex blocks stored", 1, GNUNET_NO); GNUNET_STATISTICS_update (h->stats, "# regex block bytes stored", size, GNUNET_NO); GNUNET_free (block); } /** * Announce a regular expression: put all states of the automaton in the DHT. * Does not free resources, must call REGEX_INTERNAL_announce_cancel for that. * * @param dht An existing and valid DHT service handle. CANNOT be NULL. * @param priv our private key, must remain valid until the announcement is cancelled * @param regex Regular expression to announce. * @param compression How many characters per edge can we squeeze? * @param stats Optional statistics handle to report usage. Can be NULL. * * @return Handle to reuse o free cached resources. * Must be freed by calling REGEX_INTERNAL_announce_cancel. */ struct REGEX_INTERNAL_Announcement * REGEX_INTERNAL_announce (struct GNUNET_DHT_Handle *dht, const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const char *regex, uint16_t compression, struct GNUNET_STATISTICS_Handle *stats) { struct REGEX_INTERNAL_Announcement *h; GNUNET_assert (NULL != dht); h = GNUNET_new (struct REGEX_INTERNAL_Announcement); h->regex = regex; h->dht = dht; h->stats = stats; h->priv = priv; h->dfa = REGEX_INTERNAL_construct_dfa (regex, strlen (regex), compression); REGEX_INTERNAL_reannounce (h); return h; } /** * Announce again a regular expression previously announced. * Does use caching to speed up process. * * @param h Handle returned by a previous REGEX_INTERNAL_announce call. */ void REGEX_INTERNAL_reannounce (struct REGEX_INTERNAL_Announcement *h) { GNUNET_assert (NULL != h->dfa); /* make sure to call announce first */ LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_INTERNAL_reannounce: %s\n", h->regex); REGEX_INTERNAL_iterate_reachable_edges (h->dfa, ®ex_iterator, h); } /** * Clear all cached data used by a regex announce. * Does not close DHT connection. * * @param h Handle returned by a previous REGEX_INTERNAL_announce call. */ void REGEX_INTERNAL_announce_cancel (struct REGEX_INTERNAL_Announcement *h) { REGEX_INTERNAL_automaton_destroy (h->dfa); GNUNET_free (h); } /******************************************************************************/ /** * Struct to keep state of running searches that have consumed a part of * the inital string. */ struct RegexSearchContext { /** * Part of the description already consumed by * this particular search branch. */ size_t position; /** * Information about the search. */ struct REGEX_INTERNAL_Search *info; /** * We just want to look for one edge, the longer the better. * Keep its length. */ unsigned int longest_match; /** * Destination hash of the longest match. */ struct GNUNET_HashCode hash; }; /** * Type of values in 'dht_get_results'. */ struct Result { /** * Number of bytes in data. */ size_t size; /** * The raw result data. */ const void *data; }; /** * Struct to keep information of searches of services described by a regex * using a user-provided string service description. */ struct REGEX_INTERNAL_Search { /** * DHT handle to use, must be initialized externally. */ struct GNUNET_DHT_Handle *dht; /** * Optional statistics handle to report usage. Can be NULL. */ struct GNUNET_STATISTICS_Handle *stats; /** * User provided description of the searched service. */ char *description; /** * Running DHT GETs. */ struct GNUNET_CONTAINER_MultiHashMap *dht_get_handles; /** * Results from running DHT GETs, values are of type * 'struct Result'. */ struct GNUNET_CONTAINER_MultiHashMap *dht_get_results; /** * Contexts, for each running DHT GET. Free all on end of search. */ struct RegexSearchContext **contexts; /** * Number of contexts (branches/steps in search). */ unsigned int n_contexts; /** * @param callback Callback for found peers. */ REGEX_INTERNAL_Found callback; /** * @param callback_cls Closure for @c callback. */ void *callback_cls; }; /** * Jump to the next edge, with the longest matching token. * * @param block Block found in the DHT. * @param size Size of the block. * @param ctx Context of the search. */ static void regex_next_edge (const struct RegexBlock *block, size_t size, struct RegexSearchContext *ctx); /** * Function to process DHT string to regex matching. * Called on each result obtained for the DHT search. * * @param cls Closure (search context). * @param exp When will this value expire. * @param key Key of the result. * @param get_path Path of the get request. * @param get_path_length Lenght of get_path. * @param put_path Path of the put request. * @param put_path_length Length of the put_path. * @param type Type of the result. * @param size Number of bytes in data. * @param data Pointer to the result data. */ static void dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { const struct RegexAcceptBlock *block = data; struct RegexSearchContext *ctx = cls; struct REGEX_INTERNAL_Search *info = ctx->info; LOG (GNUNET_ERROR_TYPE_DEBUG, "Regex result accept for %s (key %s)\n", info->description, GNUNET_h2s(key)); GNUNET_STATISTICS_update (info->stats, "# regex accepting blocks found", 1, GNUNET_NO); GNUNET_STATISTICS_update (info->stats, "# regex accepting block bytes found", size, GNUNET_NO); info->callback (info->callback_cls, &block->peer, get_path, get_path_length, put_path, put_path_length); } /** * Find a path to a peer that offers a regex servcie compatible * with a given string. * * @param key The key of the accepting state. * @param ctx Context containing info about the string, tunnel, etc. */ static void regex_find_path (const struct GNUNET_HashCode *key, struct RegexSearchContext *ctx) { struct GNUNET_DHT_GetHandle *get_h; LOG (GNUNET_ERROR_TYPE_DEBUG, "regex finds path for %s\n", GNUNET_h2s (key)); get_h = GNUNET_DHT_get_start (ctx->info->dht, /* handle */ GNUNET_BLOCK_TYPE_REGEX_ACCEPT, /* type */ key, /* key to search */ DHT_REPLICATION, /* replication level */ DHT_OPT | GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* xquery */ // FIXME BLOOMFILTER 0, /* xquery bits */ // FIXME BLOOMFILTER SIZE &dht_get_string_accept_handler, ctx); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(ctx->info->dht_get_handles, key, get_h, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); } /** * Function to process DHT string to regex matching. * Called on each result obtained for the DHT search. * * @param cls closure (search context) * @param exp when will this value expire * @param key key of the result * @param get_path path of the get request (not used) * @param get_path_length lenght of get_path (not used) * @param put_path path of the put request (not used) * @param put_path_length length of the put_path (not used) * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data * * TODO: re-issue the request after certain time? cancel after X results? */ static void dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { const struct RegexBlock *block = data; struct RegexSearchContext *ctx = cls; struct REGEX_INTERNAL_Search *info = ctx->info; size_t len; struct Result *copy; LOG (GNUNET_ERROR_TYPE_INFO, "DHT GET result for %s (%s)\n", GNUNET_h2s (key), ctx->info->description); copy = GNUNET_malloc (sizeof (struct Result) + size); copy->size = size; copy->data = ©[1]; memcpy (©[1], block, size); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (info->dht_get_results, key, copy, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); len = strlen (info->description); if (len == ctx->position) // String processed { if (GNUNET_YES == GNUNET_BLOCK_is_accepting (block, size)) { regex_find_path (key, ctx); } else { LOG (GNUNET_ERROR_TYPE_INFO, "block not accepting!\n"); /* FIXME REGEX this block not successful, wait for more? start timeout? */ } return; } regex_next_edge (block, size, ctx); } /** * Iterator over found existing mesh regex blocks that match an ongoing search. * * @param cls Closure (current context)- * @param key Current key code (key for cached block). * @param value Value in the hash map (cached RegexBlock). * @return GNUNET_YES: we should always continue to iterate. */ static int regex_result_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) { struct Result *result = value; const struct RegexBlock *block = result->data; struct RegexSearchContext *ctx = cls; if ( (GNUNET_YES == GNUNET_BLOCK_is_accepting (block, result->size)) && (ctx->position == strlen (ctx->info->description)) ) { LOG (GNUNET_ERROR_TYPE_INFO, "Found accepting known block\n"); regex_find_path (key, ctx); return GNUNET_YES; // We found an accept state! } LOG (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n", ctx->position, strlen (ctx->info->description), GNUNET_BLOCK_is_accepting (block, result->size)); regex_next_edge (block, result->size, ctx); GNUNET_STATISTICS_update (ctx->info->stats, "# regex mesh blocks iterated", 1, GNUNET_NO); return GNUNET_YES; } /** * Iterator over edges in a regex block retrieved from the DHT. * * @param cls Closure (context of the search). * @param token Token that follows to next state. * @param len Lenght of token. * @param key Hash of next state. * * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise. */ static int regex_edge_iterator (void *cls, const char *token, size_t len, const struct GNUNET_HashCode *key) { struct RegexSearchContext *ctx = cls; struct REGEX_INTERNAL_Search *info = ctx->info; const char *current; size_t current_len; GNUNET_STATISTICS_update (info->stats, "# regex edges iterated", 1, GNUNET_NO); current = &info->description[ctx->position]; current_len = strlen (info->description) - ctx->position; if (len > current_len) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Token too long, END\n"); return GNUNET_YES; } if (0 != strncmp (current, token, len)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Token doesn't match, END\n"); return GNUNET_YES; } if (len > ctx->longest_match) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Token is longer, KEEP\n"); ctx->longest_match = len; ctx->hash = *key; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Token is not longer, IGNORE\n"); } LOG (GNUNET_ERROR_TYPE_DEBUG, "* End of regex edge iterator\n"); return GNUNET_YES; } /** * Jump to the next edge, with the longest matching token. * * @param block Block found in the DHT. * @param size Size of the block. * @param ctx Context of the search. */ static void regex_next_edge (const struct RegexBlock *block, size_t size, struct RegexSearchContext *ctx) { struct RegexSearchContext *new_ctx; struct REGEX_INTERNAL_Search *info = ctx->info; struct GNUNET_DHT_GetHandle *get_h; struct GNUNET_HashCode *hash; const char *rest; int result; LOG (GNUNET_ERROR_TYPE_DEBUG, "Next edge\n"); /* Find the longest match for the current string position, * among tokens in the given block */ ctx->longest_match = 0; result = REGEX_BLOCK_iterate (block, size, ®ex_edge_iterator, ctx); GNUNET_break (GNUNET_OK == result); /* Did anything match? */ if (0 == ctx->longest_match) { LOG (GNUNET_ERROR_TYPE_DEBUG, "no match in block\n"); return; } hash = &ctx->hash; new_ctx = GNUNET_new (struct RegexSearchContext); new_ctx->info = info; new_ctx->position = ctx->position + ctx->longest_match; GNUNET_array_append (info->contexts, info->n_contexts, new_ctx); /* Check whether we already have a DHT GET running for it */ if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (info->dht_get_handles, hash)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "GET for %s running, END\n", GNUNET_h2s (hash)); GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results, hash, ®ex_result_iterator, new_ctx); return; /* We are already looking for it */ } GNUNET_STATISTICS_update (info->stats, "# regex nodes traversed", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_INFO, "looking for %s\n", GNUNET_h2s (hash)); rest = &new_ctx->info->description[new_ctx->position]; get_h = GNUNET_DHT_get_start (info->dht, /* handle */ GNUNET_BLOCK_TYPE_REGEX, /* type */ hash, /* key to search */ DHT_REPLICATION, /* replication level */ DHT_OPT, rest, /* xquery */ strlen (rest) + 1, /* xquery bits */ &dht_get_string_handler, new_ctx); if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, hash, get_h, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { GNUNET_break (0); return; } } /** * Search for a peer offering a regex matching certain string in the DHT. * The search runs until REGEX_INTERNAL_search_cancel is called, even if results * are returned. * * @param dht An existing and valid DHT service handle. * @param string String to match against the regexes in the DHT. * @param callback Callback for found peers. * @param callback_cls Closure for @c callback. * @param stats Optional statistics handle to report usage. Can be NULL. * * @return Handle to stop search and free resources. * Must be freed by calling REGEX_INTERNAL_search_cancel. */ struct REGEX_INTERNAL_Search * REGEX_INTERNAL_search (struct GNUNET_DHT_Handle *dht, const char *string, REGEX_INTERNAL_Found callback, void *callback_cls, struct GNUNET_STATISTICS_Handle *stats) { struct REGEX_INTERNAL_Search *h; struct GNUNET_DHT_GetHandle *get_h; struct RegexSearchContext *ctx; struct GNUNET_HashCode key; size_t size; size_t len; /* Initialize handle */ LOG (GNUNET_ERROR_TYPE_INFO, "REGEX_INTERNAL_search: %s\n", string); GNUNET_assert (NULL != dht); GNUNET_assert (NULL != callback); h = GNUNET_new (struct REGEX_INTERNAL_Search); h->dht = dht; h->description = GNUNET_strdup (string); h->callback = callback; h->callback_cls = callback_cls; h->stats = stats; h->dht_get_handles = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); h->dht_get_results = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); /* Initialize context */ len = strlen (string); size = REGEX_INTERNAL_get_first_key (string, len, &key); LOG (GNUNET_ERROR_TYPE_INFO, " initial key for %s: %s (%.*s)\n", string, GNUNET_h2s (&key), size, string); ctx = GNUNET_new (struct RegexSearchContext); ctx->position = size; ctx->info = h; GNUNET_array_append (h->contexts, h->n_contexts, ctx); LOG (GNUNET_ERROR_TYPE_DEBUG, "consumed %u bits out of %u, now looking for %s\n", size, len, GNUNET_h2s (&key)); /* Start search in DHT */ get_h = GNUNET_DHT_get_start (h->dht, /* handle */ GNUNET_BLOCK_TYPE_REGEX, /* type */ &key, /* key to search */ DHT_REPLICATION, /* replication level */ DHT_OPT, &h->description[size], /* xquery */ // FIXME add BLOOMFILTER to exclude filtered peers len + 1 - size, /* xquery bits */ // FIXME add BLOOMFILTER SIZE &dht_get_string_handler, ctx); GNUNET_break ( GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (h->dht_get_handles, &key, get_h, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST) ); return h; } /** * Iterator over hash map entries to cancel DHT GET requests after a * successful connect_by_string. * * @param cls Closure (unused). * @param key Current key code (unused). * @param value Value in the hash map (get handle). * @return GNUNET_YES if we should continue to iterate, * GNUNET_NO if not. */ static int regex_cancel_dht_get (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GNUNET_DHT_GetHandle *h = value; GNUNET_DHT_get_stop (h); return GNUNET_YES; } /** * Iterator over hash map entries to free MeshRegexBlocks stored during the * search for connect_by_string. * * @param cls Closure (unused). * @param key Current key code (unused). * @param value MeshRegexBlock in the hash map. * @return GNUNET_YES if we should continue to iterate, * GNUNET_NO if not. */ static int regex_free_result (void *cls, const struct GNUNET_HashCode * key, void *value) { GNUNET_free (value); return GNUNET_YES; } /** * Cancel an ongoing regex search in the DHT and free all resources. * * @param h the search context. */ void REGEX_INTERNAL_search_cancel (struct REGEX_INTERNAL_Search *h) { unsigned int i; GNUNET_free (h->description); GNUNET_CONTAINER_multihashmap_iterate (h->dht_get_handles, ®ex_cancel_dht_get, NULL); GNUNET_CONTAINER_multihashmap_iterate (h->dht_get_results, ®ex_free_result, NULL); GNUNET_CONTAINER_multihashmap_destroy (h->dht_get_results); GNUNET_CONTAINER_multihashmap_destroy (h->dht_get_handles); if (0 < h->n_contexts) { for (i = 0; i < h->n_contexts; i++) GNUNET_free (h->contexts[i]); GNUNET_free (h->contexts); } GNUNET_free (h); } /* end of regex_internal_dht.c */ gnunet-0.10.1/src/util/0000755000175000017500000000000012320755622011642 500000000000000gnunet-0.10.1/src/util/gnunet-helper-w32-console.c0000644000175000017500000002022712320530515016547 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/util/gnunet-helper-w32-console.c * @brief Does blocking reads from the console, writes the results * into stdout, turning blocking console I/O into non-blocking * pipe I/O. For W32 only. * @author LRN */ #include "platform.h" #include "gnunet_crypto_lib.h" #include "gnunet_common.h" #include "gnunet-helper-w32-console.h" static unsigned long buffer_size; static int chars; static HANDLE parent_handle; /** * Write @a size bytes from @a buf into @a output. * * @param output the descriptor to write into * @param buf buffer with data to write * @param size number of bytes to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int write_all (int output, const void *buf, size_t size) { const char *cbuf = buf; size_t total; ssize_t wr; total = 0; do { wr = write (output, &cbuf[total], size - total); if (wr > 0) total += wr; } while ( (wr > 0) && (total < size) ); if (wr <= 0) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to write to stdout: %s\n", strerror (errno)); return (total == size) ? GNUNET_OK : GNUNET_SYSERR; } /** * Write message to the master process. * * @param output the descriptor to write into * @param message_type message type to use * @param data data to append, NULL for none * @param data_length number of bytes in @a data * @return #GNUNET_SYSERR to stop scanning (the pipe was broken somehow) */ static int write_message (int output, uint16_t message_type, const char *data, size_t data_length) { struct GNUNET_MessageHeader hdr; #if 0 fprintf (stderr, "Helper sends %u-byte message of type %u\n", (unsigned int) (sizeof (struct GNUNET_MessageHeader) + data_length), (unsigned int) message_type); #endif hdr.type = htons (message_type); hdr.size = htons (sizeof (struct GNUNET_MessageHeader) + data_length); if (GNUNET_OK != write_all (output, &hdr, sizeof (hdr))) return GNUNET_SYSERR; if (GNUNET_OK != write_all (output, data, data_length)) return GNUNET_SYSERR; return GNUNET_OK; } /** * Main function of the helper process. Reads input events from console, * writes messages, into stdout. * * @param console a handle to a console to read from * @param output_stream a stream to write messages to * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int read_events (HANDLE console, int output_stream) { DWORD rr; BOOL b; INPUT_RECORD *buf; DWORD i; int result; result = GNUNET_SYSERR; buf = malloc (sizeof (INPUT_RECORD) * buffer_size); if (NULL == buf) return result; b = TRUE; rr = 1; while (TRUE == b && 0 < rr) { rr = 0; b = ReadConsoleInput (console, buf, buffer_size, &rr); if (FALSE == b && ERROR_SUCCESS != GetLastError ()) break; for (i = 0; i < rr; i++) { int r; r = write_message (output_stream, GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT, (const char *) &buf[i], sizeof (INPUT_RECORD)); if (GNUNET_OK != r) break; } if (rr + 1 != i) break; } return result; } /** * Main function of the helper process. Reads chars from console, * writes messages, into stdout. * * @param console a handle to a console to read from * @param output_stream a stream to write messages to * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int read_chars (HANDLE console, int output_stream) { DWORD rr; BOOL b; wchar_t *buf; char *small_ubuf; char *large_ubuf; char *ubuf; int conv; int r; int result; result = GNUNET_SYSERR; buf = malloc (sizeof (wchar_t) * buffer_size); if (NULL == buf) return result; small_ubuf = malloc (sizeof (char) * buffer_size * 2); if (NULL == small_ubuf) { free (buf); return result; } b = TRUE; rr = 1; while (TRUE == b) { large_ubuf = NULL; rr = 0; b = ReadConsoleW (console, buf, buffer_size, &rr, NULL); if (FALSE == b && ERROR_SUCCESS != GetLastError ()) break; if (0 == rr) continue; /* Caveat: if the UTF-16-encoded string is longer than BUFFER_SIZE, * there's a possibility that we will read up to a word that constitutes * a part of a multi-byte UTF-16 codepoint. Converting that to UTF-8 * will either drop invalid word (flags == 0) or bail out because of it * (flags == WC_ERR_INVALID_CHARS). */ conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, small_ubuf, 0, NULL, FALSE); if (0 == conv || 0xFFFD == conv) continue; if (conv <= buffer_size * 2 - 1) { memset (small_ubuf, 0, buffer_size * 2); conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, small_ubuf, buffer_size * 2 - 1, NULL, FALSE); if (0 == conv || 0xFFFD == conv) continue; ubuf = small_ubuf; } else { large_ubuf = malloc (conv + 1); if (NULL == large_ubuf) continue; memset (large_ubuf, 0, conv + 1); conv = WideCharToMultiByte (CP_UTF8, 0, buf, rr, large_ubuf, conv, NULL, FALSE); if (0 == conv || 0xFFFD == conv) { free (large_ubuf); large_ubuf = NULL; continue; } ubuf = large_ubuf; } r = write_message (output_stream, GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS, ubuf, conv + 1); if (large_ubuf) free (large_ubuf); if (GNUNET_OK != r) break; } free (small_ubuf); free (buf); return result; } DWORD WINAPI watch_parent (LPVOID param) { WaitForSingleObject (parent_handle, INFINITE); ExitProcess (1); return 0; } /** * Main function of the helper process to extract meta data. * * @param argc should be 3 * @param argv [0] our binary name * [1] name of the file or directory to process * [2] "-" to disable extraction, NULL for defaults, * otherwise custom plugins to load from LE * @return 0 on success */ int main (int argc, char *const *argv) { HANDLE os_stdin; DWORD parent_pid; /* We're using stdout to communicate binary data back to the parent; use * binary mode. */ _setmode (1, _O_BINARY); if (argc != 4) { fprintf (stderr, "Usage: gnunet-helper-w32-console \n"); return 2; } if (0 == strcmp (argv[1], "chars")) chars = GNUNET_YES; else if (0 == strcmp (argv[1], "events")) chars = GNUNET_NO; else return 3; buffer_size = strtoul (argv[2], NULL, 10); if (buffer_size <= 0) return 4; parent_pid = (DWORD) strtoul (argv[3], NULL, 10); if (parent_pid == 0) return 5; parent_handle = OpenProcess (SYNCHRONIZE, FALSE, parent_pid); if (NULL == parent_handle) return 6; CreateThread (NULL, 0, watch_parent, NULL, 0, NULL); if (0 == AttachConsole (ATTACH_PARENT_PROCESS)) { if (ERROR_ACCESS_DENIED != GetLastError ()) return 5; } /* Helper API overrides stdin, so we just attach to the console that we * inherited. If we did. */ os_stdin = CreateFile ("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); if (INVALID_HANDLE_VALUE == os_stdin) return 1; if (GNUNET_NO == chars) return read_events (os_stdin, 1); else return read_chars (os_stdin, 1); } /* end of gnunet-helper-w32-console.c */ gnunet-0.10.1/src/util/container_slist.c0000644000175000017500000002275212255010512015123 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/container_slist.c * @brief Implementation of a singly-linked list * @author Nils Durner */ #include "platform.h" #include "gnunet_container_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Element in our linked list. */ struct GNUNET_CONTAINER_SList_Elem { /** * This is a linked list. */ struct GNUNET_CONTAINER_SList_Elem *next; /** * Application data stored at this element. */ void *elem; /** * Number of bytes stored in elem. */ size_t len; /** * Disposition of the element. */ enum GNUNET_CONTAINER_SListDisposition disp; }; /** * Handle to a singly linked list */ struct GNUNET_CONTAINER_SList { /** * Head of the linked list. */ struct GNUNET_CONTAINER_SList_Elem *head; /** * Tail of the linked list. */ struct GNUNET_CONTAINER_SList_Elem *tail; /** * Number of elements in the list. */ unsigned int length; }; /** * Create a new element that is to be inserted into the list * @internal * @param disp memory disposition * @param buf payload buffer * @param len length of the buffer * @return a new element */ static struct GNUNET_CONTAINER_SList_Elem * create_elem (enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, size_t len) { struct GNUNET_CONTAINER_SList_Elem *e; if (disp == GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT) { e = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_SList_Elem) + len); memcpy (&e[1], buf, len); e->elem = (void *) &e[1]; } else { e = GNUNET_new (struct GNUNET_CONTAINER_SList_Elem); e->elem = (void *) buf; } e->disp = disp; e->len = len; return e; } /** * Add a new element to the list * @param l list * @param disp memory disposition * @param buf payload buffer * @param len length of the buffer */ void GNUNET_CONTAINER_slist_add (struct GNUNET_CONTAINER_SList *l, enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, size_t len) { struct GNUNET_CONTAINER_SList_Elem *e; e = create_elem (disp, buf, len); e->next = l->head; l->head = e; if (l->tail == NULL) l->tail = e; l->length++; } /** * Add a new element to the end of the list * @param l list * @param disp memory disposition * @param buf payload buffer * @param len length of the buffer */ void GNUNET_CONTAINER_slist_add_end (struct GNUNET_CONTAINER_SList *l, enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, size_t len) { struct GNUNET_CONTAINER_SList_Elem *e; e = create_elem (disp, buf, len); if (l->tail != NULL) l->tail->next = e; if (l->head == NULL) l->head = e; l->tail = e; l->length++; } /** * Append a singly linked list to another * @param dst list to append to * @param src source */ void GNUNET_CONTAINER_slist_append (struct GNUNET_CONTAINER_SList *dst, struct GNUNET_CONTAINER_SList *src) { struct GNUNET_CONTAINER_SList_Iterator i; for (i = GNUNET_CONTAINER_slist_begin (src); GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&i)) { GNUNET_CONTAINER_slist_add (dst, (i.elem->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_STATIC) ? GNUNET_CONTAINER_SLIST_DISPOSITION_STATIC : GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, i.elem->elem, i.elem->len); } GNUNET_CONTAINER_slist_iter_destroy (&i); } /** * Create a new singly linked list * @return the new list */ struct GNUNET_CONTAINER_SList * GNUNET_CONTAINER_slist_create () { return GNUNET_new (struct GNUNET_CONTAINER_SList); } /** * Destroy a singly linked list * @param l the list to be destroyed */ void GNUNET_CONTAINER_slist_destroy (struct GNUNET_CONTAINER_SList *l) { GNUNET_CONTAINER_slist_clear (l); GNUNET_free (l); } /** * Return the beginning of a list * @param l list * @return iterator pointing to the beginning */ struct GNUNET_CONTAINER_SList_Iterator GNUNET_CONTAINER_slist_begin (struct GNUNET_CONTAINER_SList *l) { struct GNUNET_CONTAINER_SList_Iterator ret; memset (&ret, 0, sizeof (ret)); ret.elem = l->head; ret.list = l; return ret; } /** * Clear a list * @param l list */ void GNUNET_CONTAINER_slist_clear (struct GNUNET_CONTAINER_SList *l) { struct GNUNET_CONTAINER_SList_Elem *e; struct GNUNET_CONTAINER_SList_Elem *n; e = l->head; while (e != NULL) { n = e->next; if (e->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC) GNUNET_free (e->elem); GNUNET_free (e); e = n; } l->head = NULL; l->tail = NULL; l->length = 0; } /** * Check if a list contains a certain element * @param l list * @param buf payload buffer to find * @param len length of the payload (number of bytes in buf) * * @return GNUNET_YES if found, GNUNET_NO otherwise */ int GNUNET_CONTAINER_slist_contains (const struct GNUNET_CONTAINER_SList *l, const void *buf, size_t len) { struct GNUNET_CONTAINER_SList_Elem *e; for (e = l->head; e != NULL; e = e->next) if ((e->len == len) && (memcmp (buf, e->elem, len) == 0)) return GNUNET_YES; return GNUNET_NO; } typedef int (*Comparator)(const void *, size_t, const void *, size_t); /** * Check if a list contains a certain element * * @param l list * @param buf payload buffer to find * @param len length of the payload (number of bytes in buf) * @param compare comparison function, should return 0 if compared elements match * * @return NULL if the 'buf' could not be found, pointer to the * list element, if found */ void * GNUNET_CONTAINER_slist_contains2 (const struct GNUNET_CONTAINER_SList *l, const void *buf, size_t len, Comparator compare) { struct GNUNET_CONTAINER_SList_Elem *e; for (e = l->head; e != NULL; e = e->next) if ((e->len == len) && (*compare)(buf, len, e->elem, e->len) == 0) return e->elem; return NULL; } /** * Count the elements of a list * @param l list * @return number of elements in the list */ int GNUNET_CONTAINER_slist_count (const struct GNUNET_CONTAINER_SList *l) { return l->length; } /** * Remove an element from the list * * @param i iterator that points to the element to be removed */ void GNUNET_CONTAINER_slist_erase (struct GNUNET_CONTAINER_SList_Iterator *i) { struct GNUNET_CONTAINER_SList_Elem *next; next = i->elem->next; if (i->last != NULL) i->last->next = next; else i->list->head = next; if (next == NULL) i->list->tail = i->last; if (i->elem->disp == GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC) GNUNET_free (i->elem->elem); GNUNET_free (i->elem); i->list->length--; i->elem = next; } /** * Insert an element into a list at a specific position * @param before where to insert the new element * @param disp memory disposition * @param buf payload buffer * @param len length of the payload */ void GNUNET_CONTAINER_slist_insert (struct GNUNET_CONTAINER_SList_Iterator *before, enum GNUNET_CONTAINER_SListDisposition disp, const void *buf, size_t len) { struct GNUNET_CONTAINER_SList_Elem *e; e = create_elem (disp, buf, len); e->next = before->elem; if (before->last != NULL) before->last->next = e; else before->list->head = e; if (e->next == NULL) before->list->tail = e; before->list->length++; } /** * Advance an iterator to the next element * @param i iterator * @return GNUNET_YES on success, GNUNET_NO if the end has been reached */ int GNUNET_CONTAINER_slist_next (struct GNUNET_CONTAINER_SList_Iterator *i) { i->last = i->elem; i->elem = i->elem->next; return (i->elem != NULL) ? GNUNET_YES : GNUNET_NO; } /** * Check if an iterator points beyond the end of a list * * @param i iterator * @return GNUNET_YES if the end has been reached, GNUNET_NO if the iterator * points to a valid element */ int GNUNET_CONTAINER_slist_end (struct GNUNET_CONTAINER_SList_Iterator *i) { return (i->elem == NULL) ? GNUNET_YES : GNUNET_NO; } /** * Retrieve the element at a specific position in a list * @param i iterator * @param len payload length * @return payload */ void * GNUNET_CONTAINER_slist_get (const struct GNUNET_CONTAINER_SList_Iterator *i, size_t * len) { if (len) *len = i->elem->len; return i->elem->elem; } /** * Release an iterator * @param i iterator */ void GNUNET_CONTAINER_slist_iter_destroy (struct GNUNET_CONTAINER_SList_Iterator *i) { } /* end of container_slist.c */ gnunet-0.10.1/src/util/os_priority.c0000644000175000017500000014424312320724374014320 00000000000000/* This file is part of GNUnet (C) 2002, 2003, 2004, 2005, 2006, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/os_priority.c * @brief Methods to set process priority * @author Nils Durner */ #include "platform.h" #include "gnunet_util_lib.h" #include "disk.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE" struct GNUNET_OS_Process { /** * PID of the process. */ pid_t pid; #if WINDOWS /** * Process handle. */ HANDLE handle; #endif /** * Pipe we use to signal the process. * NULL if unused, or if process was deemed uncontrollable. */ struct GNUNET_DISK_FileHandle *control_pipe; }; /** * Handle for 'this' process. */ static struct GNUNET_OS_Process current_process; /** * This handler is called when there are control data to be read on the pipe * * @param cls the 'struct GNUNET_DISK_FileHandle' of the control pipe * @param tc scheduler context */ static void parent_control_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DISK_FileHandle *control_pipe = cls; char sig; char *pipe_fd; ssize_t ret; LOG (GNUNET_ERROR_TYPE_DEBUG, "`%s' invoked because of %d\n", __FUNCTION__, tc->reason); if (0 != (tc->reason & (GNUNET_SCHEDULER_REASON_SHUTDOWN | GNUNET_SCHEDULER_REASON_TIMEOUT))) { GNUNET_DISK_file_close (control_pipe); control_pipe = NULL; return; } ret = GNUNET_DISK_file_read (control_pipe, &sig, sizeof (sig)); if (sizeof (sig) != ret) { if (-1 == ret) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "GNUNET_DISK_file_read"); LOG (GNUNET_ERROR_TYPE_DEBUG, "Closing control pipe\n"); GNUNET_DISK_file_close (control_pipe); control_pipe = NULL; return; } pipe_fd = getenv (GNUNET_OS_CONTROL_PIPE); GNUNET_assert ( (NULL == pipe_fd) || (strlen (pipe_fd) <= 0) ); LOG (GNUNET_ERROR_TYPE_DEBUG, "Got control code %d from parent via pipe %s\n", sig, pipe_fd); GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, &parent_control_handler, control_pipe); GNUNET_SIGNAL_raise ((int) sig); } /** * Task that connects this process to its parent via pipe; * essentially, the parent control handler will read signal numbers * from the 'GNUNET_OS_CONTROL_PIPE' (as given in an environment * variable) and raise those signals. * * @param cls closure (unused) * @param tc scheduler context (unused) */ void GNUNET_OS_install_parent_control_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { const char *env_buf; char *env_buf_end; struct GNUNET_DISK_FileHandle *control_pipe; uint64_t pipe_fd; env_buf = getenv (GNUNET_OS_CONTROL_PIPE); if ( (NULL == env_buf) || (strlen (env_buf) <= 0) ) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Not installing a handler because $%s is empty\n", GNUNET_OS_CONTROL_PIPE); putenv (GNUNET_OS_CONTROL_PIPE "="); return; } errno = 0; pipe_fd = strtoull (env_buf, &env_buf_end, 16); if ((0 != errno) || (env_buf == env_buf_end)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "strtoull", env_buf); putenv (GNUNET_OS_CONTROL_PIPE "="); return; } #if !defined (WINDOWS) if (pipe_fd >= FD_SETSIZE) #else if ((FILE_TYPE_UNKNOWN == GetFileType ((HANDLE) (uintptr_t) pipe_fd)) && (0 != GetLastError ())) #endif { LOG (GNUNET_ERROR_TYPE_ERROR, "GNUNET_OS_CONTROL_PIPE `%s' contains garbage?\n", env_buf); putenv (GNUNET_OS_CONTROL_PIPE "="); return; } #if WINDOWS control_pipe = GNUNET_DISK_get_handle_from_w32_handle ((HANDLE) (uintptr_t) pipe_fd); #else control_pipe = GNUNET_DISK_get_handle_from_int_fd ((int) pipe_fd); #endif if (NULL == control_pipe) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "open", env_buf); putenv (GNUNET_OS_CONTROL_PIPE "="); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding parent control handler pipe `%s' to the scheduler\n", env_buf); GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, &parent_control_handler, control_pipe); putenv (GNUNET_OS_CONTROL_PIPE "="); } /** * Get process structure for current process * * The pointer it returns points to static memory location and must not be * deallocated/closed * * @return pointer to the process sturcutre for this process */ struct GNUNET_OS_Process * GNUNET_OS_process_current () { #if WINDOWS current_process.pid = GetCurrentProcessId (); current_process.handle = GetCurrentProcess (); #else current_process.pid = 0; #endif return ¤t_process; } /** * Sends a signal to the process * * @param proc pointer to process structure * @param sig signal * @return 0 on success, -1 on error */ int GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) { int ret; char csig; csig = (char) sig; if (NULL != proc->control_pipe) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via pipe\n", sig, proc->pid); ret = GNUNET_DISK_file_write (proc->control_pipe, &csig, sizeof (csig)); if (sizeof (csig) == ret) return 0; } /* pipe failed or non-existent, try other methods */ switch (sig) { #if !defined (WINDOWS) case SIGHUP: #endif case SIGINT: case SIGKILL: case SIGTERM: #if (SIGTERM != GNUNET_TERM_SIG) case GNUNET_TERM_SIG: #endif #if defined(WINDOWS) && !defined(__CYGWIN__) { DWORD exitcode; int must_kill = GNUNET_YES; if (0 != GetExitCodeProcess (proc->handle, &exitcode)) must_kill = (exitcode == STILL_ACTIVE) ? GNUNET_YES : GNUNET_NO; if (GNUNET_YES == must_kill) if (0 == SafeTerminateProcess (proc->handle, 0, 0)) { DWORD error_code = GetLastError (); if ((error_code != WAIT_TIMEOUT) && (error_code != ERROR_PROCESS_ABORTED)) { LOG ((error_code == ERROR_ACCESS_DENIED) ? GNUNET_ERROR_TYPE_INFO : GNUNET_ERROR_TYPE_WARNING, "SafeTermiateProcess failed with code %lu\n", error_code); /* The problem here is that a process that is already dying * might cause SafeTerminateProcess to fail with * ERROR_ACCESS_DENIED, but the process WILL die eventually. * If we really had a permissions problem, hanging up (which * is what will happen in process_wait() in that case) is * a valid option. */ if (ERROR_ACCESS_DENIED == error_code) { errno = 0; } else { SetErrnoFromWinError (error_code); return -1; } } } } return 0; #else LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via system call\n", sig, proc->pid); return PLIBC_KILL (proc->pid, sig); #endif default: #if defined (WINDOWS) errno = EINVAL; return -1; #else LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via system call\n", sig, proc->pid); return PLIBC_KILL (proc->pid, sig); #endif } } /** * Get the pid of the process in question * * @param proc the process to get the pid of * * @return the current process id */ pid_t GNUNET_OS_process_get_pid (struct GNUNET_OS_Process * proc) { return proc->pid; } /** * Cleans up process structure contents (OS-dependent) and deallocates it * * @param proc pointer to process structure */ void GNUNET_OS_process_destroy (struct GNUNET_OS_Process *proc) { if (NULL != proc->control_pipe) GNUNET_DISK_file_close (proc->control_pipe); #if defined (WINDOWS) if (proc->handle != NULL) CloseHandle (proc->handle); #endif GNUNET_free (proc); } #if WINDOWS #include "gnunet_signal_lib.h" extern GNUNET_SIGNAL_Handler w32_sigchld_handler; /** * Make seaspider happy. */ #define DWORD_WINAPI DWORD WINAPI /** * @brief Waits for a process to terminate and invokes the SIGCHLD handler * @param proc pointer to process structure */ static DWORD_WINAPI child_wait_thread (void *arg) { struct GNUNET_OS_Process *proc = (struct GNUNET_OS_Process *) arg; WaitForSingleObject (proc->handle, INFINITE); if (w32_sigchld_handler) w32_sigchld_handler (); return 0; } #endif #if MINGW static char * CreateCustomEnvTable (char **vars) { char *win32_env_table; char *ptr; char **var_ptr; char *result; char *result_ptr; size_t tablesize = 0; size_t items_count = 0; size_t n_found = 0; size_t n_var; char *index = NULL; size_t c; size_t var_len; char *var; char *val; win32_env_table = GetEnvironmentStringsA (); if (NULL == win32_env_table) return NULL; for (c = 0, var_ptr = vars; *var_ptr; var_ptr += 2, c++) ; n_var = c; index = GNUNET_malloc (sizeof (char *) * n_var); for (c = 0; c < n_var; c++) index[c] = 0; for (items_count = 0, ptr = win32_env_table; ptr[0] != 0; items_count++) { size_t len = strlen (ptr); int found = 0; for (var_ptr = vars; *var_ptr; var_ptr++) { var = *var_ptr++; val = *var_ptr; var_len = strlen (var); if (strncmp (var, ptr, var_len) == 0) { found = 1; index[c] = 1; tablesize += var_len + strlen (val) + 1; break; } } if (!found) tablesize += len + 1; ptr += len + 1; } for (n_found = 0, c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) { var = *var_ptr++; val = *var_ptr; if (index[c] != 1) n_found += strlen (var) + strlen (val) + 1; } result = GNUNET_malloc (tablesize + n_found + 1); for (result_ptr = result, ptr = win32_env_table; ptr[0] != 0;) { size_t len = strlen (ptr); int found = 0; for (c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) { var = *var_ptr++; val = *var_ptr; var_len = strlen (var); if (strncmp (var, ptr, var_len) == 0) { found = 1; break; } } if (!found) { strcpy (result_ptr, ptr); result_ptr += len + 1; } else { strcpy (result_ptr, var); result_ptr += var_len; strcpy (result_ptr, val); result_ptr += strlen (val) + 1; } ptr += len + 1; } for (c = 0, var_ptr = vars; *var_ptr; var_ptr++, c++) { var = *var_ptr++; val = *var_ptr; var_len = strlen (var); if (index[c] != 1) { strcpy (result_ptr, var); result_ptr += var_len; strcpy (result_ptr, val); result_ptr += strlen (val) + 1; } } FreeEnvironmentStrings (win32_env_table); GNUNET_free (index); *result_ptr = 0; return result; } #else /** * Open '/dev/null' and make the result the given * file descriptor. * * @param target_fd desired FD to point to /dev/null * @param flags open flags (O_RDONLY, O_WRONLY) */ static void open_dev_null (int target_fd, int flags) { int fd; fd = open ("/dev/null", flags); if (-1 == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", "/dev/null"); return; } if (fd == target_fd) return; if (-1 == dup2 (fd, target_fd)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup2"); (void) close (fd); return; } GNUNET_break (0 == close (fd)); } #endif /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags controlling which * std handles of the parent are inherited by the child. * pipe_stdin and pipe_stdout take priority over std_inheritance * (when they are non-NULL). * @param pipe_stdin pipe to use to send input to child process (or NULL) * @param pipe_stdout pipe to use to get output from child process (or NULL) * @param lsocks array of listen sockets to dup systemd-style (or NULL); * must be NULL on platforms where dup is not supported * @param filename name of the binary * @param argv NULL-terminated list of arguments to the process * @return process ID of the new process, -1 on error */ static struct GNUNET_OS_Process * start_process (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const SOCKTYPE *lsocks, const char *filename, char *const argv[]) { #ifndef MINGW pid_t ret; char fds[16]; struct GNUNET_OS_Process *gnunet_proc; struct GNUNET_DISK_FileHandle *childpipe_read; struct GNUNET_DISK_FileHandle *childpipe_write; int childpipe_read_fd; int i; int j; int k; int tgt; int flags; int *lscp; unsigned int ls; int fd_stdout_write; int fd_stdout_read; int fd_stderr_write; int fd_stderr_read; int fd_stdin_read; int fd_stdin_write; if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename, GNUNET_NO, NULL)) return NULL; /* not executable */ if (GNUNET_YES == pipe_control) { struct GNUNET_DISK_PipeHandle *childpipe; int dup_childpipe_read_fd = -1; childpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO); if (NULL == childpipe) return NULL; childpipe_read = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_READ); childpipe_write = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_WRITE); GNUNET_DISK_pipe_close (childpipe); if ((NULL == childpipe_read) || (NULL == childpipe_write) || (GNUNET_OK != GNUNET_DISK_internal_file_handle_ (childpipe_read, &childpipe_read_fd, sizeof (int))) || (-1 == (dup_childpipe_read_fd = dup (childpipe_read_fd)))) { if (NULL != childpipe_read) GNUNET_DISK_file_close (childpipe_read); if (NULL != childpipe_write) GNUNET_DISK_file_close (childpipe_write); if (0 <= dup_childpipe_read_fd) close (dup_childpipe_read_fd); return NULL; } childpipe_read_fd = dup_childpipe_read_fd; GNUNET_DISK_file_close (childpipe_read); } else { childpipe_write = NULL; childpipe_read_fd = -1; } if (NULL != pipe_stdin) { GNUNET_assert (GNUNET_OK == GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (pipe_stdin, GNUNET_DISK_PIPE_END_READ), &fd_stdin_read, sizeof (int))); GNUNET_assert (GNUNET_OK == GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE), &fd_stdin_write, sizeof (int))); } if (NULL != pipe_stdout) { GNUNET_assert (GNUNET_OK == GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (pipe_stdout, GNUNET_DISK_PIPE_END_WRITE), &fd_stdout_write, sizeof (int))); GNUNET_assert (GNUNET_OK == GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (pipe_stdout, GNUNET_DISK_PIPE_END_READ), &fd_stdout_read, sizeof (int))); } if (NULL != pipe_stderr) { GNUNET_assert (GNUNET_OK == GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (pipe_stderr, GNUNET_DISK_PIPE_END_READ), &fd_stderr_read, sizeof (int))); GNUNET_assert (GNUNET_OK == GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (pipe_stderr, GNUNET_DISK_PIPE_END_WRITE), &fd_stderr_write, sizeof (int))); } lscp = NULL; ls = 0; if (NULL != lsocks) { i = 0; while (-1 != (k = lsocks[i++])) GNUNET_array_append (lscp, ls, k); GNUNET_array_append (lscp, ls, -1); } #if DARWIN /* see https://gnunet.org/vfork */ ret = vfork (); #else ret = fork (); #endif if (-1 == ret) { int eno = errno; LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); GNUNET_array_grow (lscp, ls, 0); if (NULL != childpipe_write) GNUNET_DISK_file_close (childpipe_write); if (0 <= childpipe_read_fd) close (childpipe_read_fd); errno = eno; return NULL; } if (0 != ret) { unsetenv (GNUNET_OS_CONTROL_PIPE); gnunet_proc = GNUNET_new (struct GNUNET_OS_Process); gnunet_proc->pid = ret; gnunet_proc->control_pipe = childpipe_write; if (GNUNET_YES == pipe_control) { close (childpipe_read_fd); } GNUNET_array_grow (lscp, ls, 0); return gnunet_proc; } if (0 <= childpipe_read_fd) { char fdbuf[100]; #ifndef DARWIN /* due to vfork, we must NOT free memory on DARWIN! */ GNUNET_DISK_file_close (childpipe_write); #endif snprintf (fdbuf, 100, "%x", childpipe_read_fd); setenv (GNUNET_OS_CONTROL_PIPE, fdbuf, 1); } else unsetenv (GNUNET_OS_CONTROL_PIPE); if (NULL != pipe_stdin) { GNUNET_break (0 == close (fd_stdin_write)); if (-1 == dup2 (fd_stdin_read, 0)) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); GNUNET_break (0 == close (fd_stdin_read)); } else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_IN)) { GNUNET_break (0 == close (0)); open_dev_null (0, O_RDONLY); } if (NULL != pipe_stdout) { GNUNET_break (0 == close (fd_stdout_read)); if (-1 == dup2 (fd_stdout_write, 1)) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); GNUNET_break (0 == close (fd_stdout_write)); } else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_OUT)) { GNUNET_break (0 == close (1)); open_dev_null (1, O_WRONLY); } if (NULL != pipe_stderr) { GNUNET_break (0 == close (fd_stderr_read)); if (-1 == dup2 (fd_stderr_write, 2)) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); GNUNET_break (0 == close (fd_stderr_write)); } else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_ERR)) { GNUNET_break (0 == close (2)); open_dev_null (2, O_WRONLY); } if (NULL != lscp) { /* read systemd documentation... */ i = 0; tgt = 3; while (-1 != lscp[i]) { j = i + 1; while (-1 != lscp[j]) { if (lscp[j] == tgt) { /* dup away */ k = dup (lscp[j]); GNUNET_assert (-1 != k); GNUNET_assert (0 == close (lscp[j])); lscp[j] = k; break; } j++; } if (lscp[i] != tgt) { /* Bury any existing FD, no matter what; they should all be closed * on exec anyway and the important onces have been dup'ed away */ (void) close (tgt); GNUNET_assert (-1 != dup2 (lscp[i], tgt)); } /* unset close-on-exec flag */ flags = fcntl (tgt, F_GETFD); GNUNET_assert (flags >= 0); flags &= ~FD_CLOEXEC; fflush (stderr); (void) fcntl (tgt, F_SETFD, flags); tgt++; i++; } GNUNET_snprintf (fds, sizeof (fds), "%u", i); setenv ("LISTEN_FDS", fds, 1); } #ifndef DARWIN /* due to vfork, we must NOT free memory on DARWIN! */ GNUNET_array_grow (lscp, ls, 0); #endif execvp (filename, argv); LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); _exit (1); #else struct GNUNET_DISK_FileHandle *childpipe_read; struct GNUNET_DISK_FileHandle *childpipe_write; HANDLE childpipe_read_handle; char **arg; char **non_const_argv; unsigned int cmdlen; char *cmd; char *idx; STARTUPINFOW start; PROCESS_INFORMATION proc; int argcount = 0; struct GNUNET_OS_Process *gnunet_proc; char path[MAX_PATH + 1]; char *our_env[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; char *env_block = NULL; char *pathbuf; DWORD pathbuf_len; DWORD alloc_len; char *self_prefix; char *bindir; char *libdir; char *ptr; char *non_const_filename; char win_path[MAX_PATH + 1]; struct GNUNET_DISK_PipeHandle *lsocks_pipe; const struct GNUNET_DISK_FileHandle *lsocks_write_fd; HANDLE lsocks_read; HANDLE lsocks_write; wchar_t *wpath; wchar_t *wcmd; size_t wpath_len; size_t wcmd_len; int env_off; int fail; long lRet; HANDLE stdin_handle; HANDLE stdout_handle; HANDLE stdih, stdoh, stdeh; DWORD stdif, stdof, stdef; BOOL bresult; DWORD error_code; DWORD create_no_window; if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename, GNUNET_NO, NULL)) return NULL; /* not executable */ /* Search in prefix dir (hopefully - the directory from which * the current module was loaded), bindir and libdir, then in PATH */ self_prefix = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX); bindir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); libdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0); alloc_len = pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 + strlen (libdir); pathbuf = GNUNET_malloc (alloc_len * sizeof (char)); ptr = pathbuf; ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir); GNUNET_free (self_prefix); GNUNET_free (bindir); GNUNET_free (libdir); alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len); if (alloc_len != pathbuf_len - 1) { GNUNET_free (pathbuf); errno = ENOSYS; /* PATH changed on the fly. What kind of error is that? */ return NULL; } cmdlen = strlen (filename); if ( (cmdlen < 5) || (0 != strcmp (&filename[cmdlen - 4], ".exe")) ) GNUNET_asprintf (&non_const_filename, "%s.exe", filename); else GNUNET_asprintf (&non_const_filename, "%s", filename); /* It could be in POSIX form, convert it to a DOS path early on */ if (ERROR_SUCCESS != (lRet = plibc_conv_to_win_path (non_const_filename, win_path))) { SetErrnoFromWinError (lRet); LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "plibc_conv_to_win_path", non_const_filename); GNUNET_free (non_const_filename); GNUNET_free (pathbuf); return NULL; } GNUNET_free (non_const_filename); non_const_filename = GNUNET_strdup (win_path); /* Check that this is the full path. If it isn't, search. */ /* FIXME: convert it to wchar_t and use SearchPathW? * Remember: arguments to _start_process() are technically in UTF-8... */ if (non_const_filename[1] == ':') { snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename); LOG (GNUNET_ERROR_TYPE_DEBUG, "Using path `%s' as-is. PATH is %s\n", path, ptr); } else if (!SearchPathA (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char), path, NULL)) { SetErrnoFromWinError (GetLastError ()); LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "SearchPath", non_const_filename); GNUNET_free (non_const_filename); GNUNET_free (pathbuf); return NULL; } else LOG (GNUNET_ERROR_TYPE_DEBUG, "Found `%s' in PATH `%s'\n", path, pathbuf); GNUNET_free (pathbuf); GNUNET_free (non_const_filename); /* Count the number of arguments */ arg = (char **) argv; while (*arg) { arg++; argcount++; } /* Allocate a copy argv */ non_const_argv = GNUNET_malloc (sizeof (char *) * (argcount + 1)); /* Copy all argv strings */ argcount = 0; arg = (char **) argv; while (*arg) { if (arg == argv) non_const_argv[argcount] = GNUNET_strdup (path); else non_const_argv[argcount] = GNUNET_strdup (*arg); arg++; argcount++; } non_const_argv[argcount] = NULL; /* Count cmd len */ cmdlen = 1; arg = non_const_argv; while (*arg) { cmdlen = cmdlen + strlen (*arg) + 4; arg++; } /* Allocate and create cmd */ cmd = idx = GNUNET_malloc (sizeof (char) * cmdlen); arg = non_const_argv; while (*arg) { char arg_last_char = (*arg)[strlen (*arg) - 1]; idx += sprintf (idx, "\"%s%s\"%s", *arg, arg_last_char == '\\' ? "\\" : "", *(arg + 1) ? " " : ""); arg++; } while (argcount > 0) GNUNET_free (non_const_argv[--argcount]); GNUNET_free (non_const_argv); memset (&start, 0, sizeof (start)); start.cb = sizeof (start); if ((pipe_stdin != NULL) || (pipe_stdout != NULL) || (std_inheritance != 0)) start.dwFlags |= STARTF_USESTDHANDLES; stdih = GetStdHandle (STD_INPUT_HANDLE); GetHandleInformation (stdih, &stdif); if (pipe_stdin != NULL) { GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (pipe_stdin, GNUNET_DISK_PIPE_END_READ), &stdin_handle, sizeof (HANDLE)); start.hStdInput = stdin_handle; } else if (stdih) { if (std_inheritance & GNUNET_OS_INHERIT_STD_IN) { SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, 1); if (pipe_stdin == NULL) start.hStdInput = stdih; } else SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, 0); } stdoh = GetStdHandle (STD_OUTPUT_HANDLE); GetHandleInformation (stdoh, &stdof); if (NULL != pipe_stdout) { GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (pipe_stdout, GNUNET_DISK_PIPE_END_WRITE), &stdout_handle, sizeof (HANDLE)); start.hStdOutput = stdout_handle; } else if (stdoh) { if (std_inheritance & GNUNET_OS_INHERIT_STD_OUT) { SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, 1); if (pipe_stdout == NULL) start.hStdOutput = stdoh; } else SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, 0); } stdeh = GetStdHandle (STD_ERROR_HANDLE); GetHandleInformation (stdeh, &stdef); if (stdeh) { if (std_inheritance & GNUNET_OS_INHERIT_STD_ERR) { SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, 1); start.hStdError = stdeh; } else SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, 0); } if (GNUNET_YES == pipe_control) { struct GNUNET_DISK_PipeHandle *childpipe; childpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO); if (NULL == childpipe) return NULL; childpipe_read = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_READ); childpipe_write = GNUNET_DISK_pipe_detach_end (childpipe, GNUNET_DISK_PIPE_END_WRITE); GNUNET_DISK_pipe_close (childpipe); if ((NULL == childpipe_read) || (NULL == childpipe_write) || (GNUNET_OK != GNUNET_DISK_internal_file_handle_ (childpipe_read, &childpipe_read_handle, sizeof (HANDLE)))) { if (childpipe_read) GNUNET_DISK_file_close (childpipe_read); if (childpipe_write) GNUNET_DISK_file_close (childpipe_write); GNUNET_free (cmd); return NULL; } /* Unlike *nix variant, we don't dup the handle, so can't close * filehandle right now. */ SetHandleInformation (childpipe_read_handle, HANDLE_FLAG_INHERIT, 1); } else { childpipe_read = NULL; childpipe_write = NULL; } if (lsocks != NULL && lsocks[0] != INVALID_SOCKET) { lsocks_pipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); if (lsocks_pipe == NULL) { GNUNET_free (cmd); GNUNET_DISK_pipe_close (lsocks_pipe); if (GNUNET_YES == pipe_control) { GNUNET_DISK_file_close (childpipe_write); GNUNET_DISK_file_close (childpipe_read); } return NULL; } lsocks_write_fd = GNUNET_DISK_pipe_handle (lsocks_pipe, GNUNET_DISK_PIPE_END_WRITE); GNUNET_DISK_internal_file_handle_ (lsocks_write_fd, &lsocks_write, sizeof (HANDLE)); GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle (lsocks_pipe, GNUNET_DISK_PIPE_END_READ), &lsocks_read, sizeof (HANDLE)); } else lsocks_pipe = NULL; env_off = 0; if (GNUNET_YES == pipe_control) { GNUNET_asprintf (&our_env[env_off++], "%s=", GNUNET_OS_CONTROL_PIPE); GNUNET_asprintf (&our_env[env_off++], "%p", childpipe_read_handle); } if ( (lsocks != NULL) && (lsocks[0] != INVALID_SOCKET)) { /*This will tell the child that we're going to send lsocks over the pipe*/ GNUNET_asprintf (&our_env[env_off++], "%s=", "GNUNET_OS_READ_LSOCKS"); GNUNET_asprintf (&our_env[env_off++], "%lu", lsocks_read); } our_env[env_off++] = NULL; env_block = CreateCustomEnvTable (our_env); while (0 > env_off) GNUNET_free_non_null (our_env[--env_off]); wpath_len = 0; if (NULL == (wpath = u8_to_u16 ((uint8_t *) path, 1 + strlen (path), NULL, &wpath_len))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", path, errno); GNUNET_free (env_block); GNUNET_free (cmd); if (lsocks_pipe) GNUNET_DISK_pipe_close (lsocks_pipe); if (GNUNET_YES == pipe_control) { GNUNET_DISK_file_close (childpipe_write); GNUNET_DISK_file_close (childpipe_read); } return NULL; } wcmd_len = 0; if (NULL == (wcmd = u8_to_u16 ((uint8_t *) cmd, 1 + strlen (cmd), NULL, &wcmd_len))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", cmd, errno); GNUNET_free (env_block); GNUNET_free (cmd); free (wpath); if (lsocks_pipe) GNUNET_DISK_pipe_close (lsocks_pipe); if (GNUNET_YES == pipe_control) { GNUNET_DISK_file_close (childpipe_write); GNUNET_DISK_file_close (childpipe_read); } return NULL; } create_no_window = 0; { HANDLE console_input = CreateFile ("CONIN$", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == console_input) create_no_window = CREATE_NO_WINDOW; else CloseHandle (console_input); } bresult = CreateProcessW (wpath, wcmd, NULL, NULL, GNUNET_YES, create_no_window | CREATE_SUSPENDED, env_block, NULL, &start, &proc); error_code = GetLastError (); if ((NULL == pipe_stdin) && (stdih)) SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, stdif); if ((NULL == pipe_stdout) && (stdoh)) SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, stdof); if (stdeh) SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, stdef); if (!bresult) LOG (GNUNET_ERROR_TYPE_ERROR, "CreateProcess(%s, %s) failed: %lu\n", path, cmd, error_code); GNUNET_free (env_block); GNUNET_free (cmd); free (wpath); free (wcmd); if (GNUNET_YES == pipe_control) { GNUNET_DISK_file_close (childpipe_read); } if (!bresult) { if (GNUNET_YES == pipe_control) { GNUNET_DISK_file_close (childpipe_write); } if (NULL != lsocks) GNUNET_DISK_pipe_close (lsocks_pipe); SetErrnoFromWinError (error_code); return NULL; } gnunet_proc = GNUNET_new (struct GNUNET_OS_Process); gnunet_proc->pid = proc.dwProcessId; gnunet_proc->handle = proc.hProcess; gnunet_proc->control_pipe = childpipe_write; CreateThread (NULL, 64000, &child_wait_thread, (void *) gnunet_proc, 0, NULL); ResumeThread (proc.hThread); CloseHandle (proc.hThread); if ( (NULL == lsocks) || (INVALID_SOCKET == lsocks[0]) ) return gnunet_proc; GNUNET_DISK_pipe_close_end (lsocks_pipe, GNUNET_DISK_PIPE_END_READ); /* This is a replacement for "goto error" that doesn't use goto */ fail = 1; do { ssize_t wrote; uint64_t size; uint64_t count; unsigned int i; /* Tell the number of sockets */ for (count = 0; lsocks && lsocks[count] != INVALID_SOCKET; count++); wrote = GNUNET_DISK_file_write (lsocks_write_fd, &count, sizeof (count)); if (sizeof (count) != wrote) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u count bytes to the child: %u\n", sizeof (count), GetLastError ()); break; } for (i = 0; lsocks && lsocks[i] != INVALID_SOCKET; i++) { WSAPROTOCOL_INFOA pi; /* Get a socket duplication info */ if (SOCKET_ERROR == WSADuplicateSocketA (lsocks[i], gnunet_proc->pid, &pi)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to duplicate an socket[%llu]: %u\n", i, GetLastError ()); break; } /* Synchronous I/O is not nice, but we can't schedule this: * lsocks will be closed/freed by the caller soon, and until * the child creates a duplicate, closing a socket here will * close it for good. */ /* Send the size of the structure * (the child might be built with different headers...) */ size = sizeof (pi); wrote = GNUNET_DISK_file_write (lsocks_write_fd, &size, sizeof (size)); if (sizeof (size) != wrote) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u size[%llu] bytes to the child: %u\n", sizeof (size), i, GetLastError ()); break; } /* Finally! Send the data */ wrote = GNUNET_DISK_file_write (lsocks_write_fd, &pi, sizeof (pi)); if (sizeof (pi) != wrote) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u socket[%llu] bytes to the child: %u\n", sizeof (pi), i, GetLastError ()); break; } } /* This will block us until the child makes a final read or closes * the pipe (hence no 'wrote' check), since we have to wait for it * to duplicate the last socket, before we return and start closing * our own copies) */ wrote = GNUNET_DISK_file_write (lsocks_write_fd, &count, sizeof (count)); fail = 0; } while (fail); GNUNET_DISK_file_sync (lsocks_write_fd); GNUNET_DISK_pipe_close (lsocks_pipe); if (fail) { /* If we can't pass on the socket(s), the child will block forever, * better put it out of its misery. */ SafeTerminateProcess (gnunet_proc->handle, 0, 0); CloseHandle (gnunet_proc->handle); if (NULL != gnunet_proc->control_pipe) GNUNET_DISK_file_close (gnunet_proc->control_pipe); GNUNET_free (gnunet_proc); return NULL; } return gnunet_proc; #endif } /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param pipe_stdin pipe to use to send input to child process (or NULL) * @param pipe_stdout pipe to use to get output from child process (or NULL) * @param pipe_stderr pipe to use to get output from child process (or NULL) * @param filename name of the binary * @param argv NULL-terminated array of arguments to the process * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process_vap (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename, char *const argv[]) { return start_process (pipe_control, std_inheritance, pipe_stdin, pipe_stdout, pipe_stderr, NULL, filename, argv); } /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param pipe_stdin pipe to use to send input to child process (or NULL) * @param pipe_stdout pipe to use to get output from child process (or NULL) * @param pipe_stderr pipe to use to get output from child process (or NULL) * @param filename name of the binary * @param va NULL-terminated list of arguments to the process * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process_va (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename, va_list va) { struct GNUNET_OS_Process *ret; va_list ap; char **argv; int argc; argc = 0; va_copy (ap, va); while (NULL != va_arg (ap, char *)) argc++; va_end (ap); argv = GNUNET_malloc (sizeof (char *) * (argc + 1)); argc = 0; va_copy (ap, va); while (NULL != (argv[argc] = va_arg (ap, char *))) argc++; va_end (ap); ret = GNUNET_OS_start_process_vap (pipe_control, std_inheritance, pipe_stdin, pipe_stdout, pipe_stderr, filename, argv); GNUNET_free (argv); return ret; } /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param pipe_stdin pipe to use to send input to child process (or NULL) * @param pipe_stdout pipe to use to get output from child process (or NULL) * @param filename name of the binary * @param ... NULL-terminated list of arguments to the process * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, struct GNUNET_DISK_PipeHandle *pipe_stderr, const char *filename, ...) { struct GNUNET_OS_Process *ret; va_list ap; va_start (ap, filename); ret = GNUNET_OS_start_process_va (pipe_control, std_inheritance, pipe_stdin, pipe_stdout, pipe_stderr, filename, ap); va_end (ap); return ret; } /** * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags controlling which * std handles of the parent are inherited by the child. * pipe_stdin and pipe_stdout take priority over std_inheritance * (when they are non-NULL). * @param lsocks array of listen sockets to dup systemd-style (or NULL); * must be NULL on platforms where dup is not supported * @param filename name of the binary * @param argv NULL-terminated list of arguments to the process * @return process ID of the new process, -1 on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process_v (int pipe_control, enum GNUNET_OS_InheritStdioFlags std_inheritance, const SOCKTYPE *lsocks, const char *filename, char *const argv[]) { return start_process (pipe_control, std_inheritance, NULL, NULL, NULL, lsocks, filename, argv); } /** * Start a process. This function is similar to the GNUNET_OS_start_process_* * except that the filename and arguments can have whole strings which contain * the arguments. These arguments are to be separated by spaces and are parsed * in the order they appear. Arguments containing spaces can be used by * quoting them with @em ". * * @param pipe_control should a pipe be used to send signals to the child? * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags * @param lsocks array of listen sockets to dup systemd-style (or NULL); * must be NULL on platforms where dup is not supported * @param filename name of the binary. It is valid to have the arguments * in this string when they are separated by spaces. * @param ... more arguments. Should be of type `char *`. It is valid * to have the arguments in these strings when they are separated by * spaces. The last argument MUST be NULL. * @return pointer to process structure of the new process, NULL on error */ struct GNUNET_OS_Process * GNUNET_OS_start_process_s (int pipe_control, unsigned int std_inheritance, const SOCKTYPE * lsocks, const char *filename, ...) { va_list ap; char **argv; unsigned int argv_size; const char *arg; const char *rpos; char *pos; char *cp; const char *last; struct GNUNET_OS_Process *proc; char *binary_path; int quote_on; unsigned int i; size_t len; argv_size = 1; va_start (ap, filename); arg = filename; last = NULL; do { rpos = arg; quote_on = 0; while ('\0' != *rpos) { if ('"' == *rpos) { if (1 == quote_on) quote_on = 0; else quote_on = 1; } if ( (' ' == *rpos) && (0 == quote_on) ) { if (NULL != last) argv_size++; last = NULL; rpos++; while (' ' == *rpos) rpos++; } if ( (NULL == last) && ('\0' != *rpos) ) // FIXME: == or !=? last = rpos; if ('\0' != *rpos) rpos++; } if (NULL != last) argv_size++; } while (NULL != (arg = (va_arg (ap, const char*)))); va_end (ap); argv = GNUNET_malloc (argv_size * sizeof (char *)); argv_size = 0; va_start (ap, filename); arg = filename; last = NULL; do { cp = GNUNET_strdup (arg); quote_on = 0; pos = cp; while ('\0' != *pos) { if ('"' == *pos) { if (1 == quote_on) quote_on = 0; else quote_on = 1; } if ( (' ' == *pos) && (0 == quote_on) ) { *pos = '\0'; if (NULL != last) argv[argv_size++] = GNUNET_strdup (last); last = NULL; pos++; while (' ' == *pos) pos++; } if ( (NULL == last) && ('\0' != *pos)) // FIXME: == or !=? last = pos; if ('\0' != *pos) pos++; } if (NULL != last) argv[argv_size++] = GNUNET_strdup (last); last = NULL; GNUNET_free (cp); } while (NULL != (arg = (va_arg (ap, const char*)))); va_end (ap); argv[argv_size] = NULL; for(i = 0; i < argv_size; i++) { len = strlen (argv[i]); if ( (argv[i][0] == '"') && (argv[i][len-1] == '"')) { memmove (&argv[i][0], &argv[i][1], len - 2); argv[i][len-2] = '\0'; } } binary_path = argv[0]; proc = GNUNET_OS_start_process_v (pipe_control, std_inheritance, lsocks, binary_path, argv); while (argv_size > 0) GNUNET_free (argv[--argv_size]); GNUNET_free (argv); return proc; } /** * Retrieve the status of a process, waiting on him if dead. * Nonblocking version. * * @param proc process ID * @param type status type * @param code return code/signal number * @return GNUNET_OK on success, GNUNET_NO if the process is still running, GNUNET_SYSERR otherwise */ int GNUNET_OS_process_status (struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code) { #ifndef MINGW int status; int ret; GNUNET_assert (0 != proc); ret = waitpid (proc->pid, &status, WNOHANG); if (ret < 0) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "waitpid"); return GNUNET_SYSERR; } if (0 == ret) { *type = GNUNET_OS_PROCESS_RUNNING; *code = 0; return GNUNET_NO; } if (proc->pid != ret) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "waitpid"); return GNUNET_SYSERR; } if (WIFEXITED (status)) { *type = GNUNET_OS_PROCESS_EXITED; *code = WEXITSTATUS (status); } else if (WIFSIGNALED (status)) { *type = GNUNET_OS_PROCESS_SIGNALED; *code = WTERMSIG (status); } else if (WIFSTOPPED (status)) { *type = GNUNET_OS_PROCESS_SIGNALED; *code = WSTOPSIG (status); } #ifdef WIFCONTINUED else if (WIFCONTINUED (status)) { *type = GNUNET_OS_PROCESS_RUNNING; *code = 0; } #endif else { *type = GNUNET_OS_PROCESS_UNKNOWN; *code = 0; } #else HANDLE h; DWORD c, error_code, ret; h = proc->handle; ret = proc->pid; if (h == NULL || ret == 0) { LOG (GNUNET_ERROR_TYPE_WARNING, "Invalid process information {%d, %08X}\n", ret, h); return GNUNET_SYSERR; } if (h == NULL) h = GetCurrentProcess (); SetLastError (0); ret = GetExitCodeProcess (h, &c); error_code = GetLastError (); if (ret == 0 || error_code != NO_ERROR) { SetErrnoFromWinError (error_code); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "GetExitCodeProcess"); return GNUNET_SYSERR; } if (STILL_ACTIVE == c) { *type = GNUNET_OS_PROCESS_RUNNING; *code = 0; return GNUNET_NO; } *type = GNUNET_OS_PROCESS_EXITED; *code = c; #endif return GNUNET_OK; } /** * Wait for a process * * @param proc pointer to process structure * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc) { #ifndef MINGW pid_t pid = proc->pid; pid_t ret; while ( (pid != (ret = waitpid (pid, NULL, 0))) && (EINTR == errno) ) ; if (pid != ret) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "waitpid"); return GNUNET_SYSERR; } return GNUNET_OK; #else HANDLE h; h = proc->handle; if (NULL == h) { LOG (GNUNET_ERROR_TYPE_WARNING, "Invalid process information {%d, %08X}\n", proc->pid, h); return GNUNET_SYSERR; } if (NULL == h) h = GetCurrentProcess (); if (WAIT_OBJECT_0 != WaitForSingleObject (h, INFINITE)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } return GNUNET_OK; #endif } /** * Handle to a command. */ struct GNUNET_OS_CommandHandle { /** * Process handle. */ struct GNUNET_OS_Process *eip; /** * Handle to the output pipe. */ struct GNUNET_DISK_PipeHandle *opipe; /** * Read-end of output pipe. */ const struct GNUNET_DISK_FileHandle *r; /** * Function to call on each line of output. */ GNUNET_OS_LineProcessor proc; /** * Closure for 'proc'. */ void *proc_cls; /** * Buffer for the output. */ char buf[1024]; /** * Task reading from pipe. */ GNUNET_SCHEDULER_TaskIdentifier rtask; /** * When to time out. */ struct GNUNET_TIME_Absolute timeout; /** * Current read offset in buf. */ size_t off; }; /** * Stop/kill a command. Must ONLY be called either from * the callback after 'NULL' was passed for 'line' *OR* * from an independent task (not within the line processor). * * @param cmd handle to the process */ void GNUNET_OS_command_stop (struct GNUNET_OS_CommandHandle *cmd) { if (NULL != cmd->proc) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != cmd->rtask); GNUNET_SCHEDULER_cancel (cmd->rtask); } (void) GNUNET_OS_process_kill (cmd->eip, SIGKILL); GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (cmd->eip)); GNUNET_OS_process_destroy (cmd->eip); GNUNET_DISK_pipe_close (cmd->opipe); GNUNET_free (cmd); } /** * Read from the process and call the line processor. * * @param cls the 'struct GNUNET_OS_CommandHandle' * @param tc scheduler context */ static void cmd_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_OS_CommandHandle *cmd = cls; GNUNET_OS_LineProcessor proc; char *end; ssize_t ret; cmd->rtask = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_YES != GNUNET_NETWORK_fdset_handle_isset (tc->read_ready, cmd->r)) { /* timeout, shutdown, etc. */ proc = cmd->proc; cmd->proc = NULL; proc (cmd->proc_cls, NULL); return; } ret = GNUNET_DISK_file_read (cmd->r, &cmd->buf[cmd->off], sizeof (cmd->buf) - cmd->off); if (ret <= 0) { if ((cmd->off > 0) && (cmd->off < sizeof (cmd->buf))) { cmd->buf[cmd->off] = '\0'; cmd->proc (cmd->proc_cls, cmd->buf); } proc = cmd->proc; cmd->proc = NULL; proc (cmd->proc_cls, NULL); return; } end = memchr (&cmd->buf[cmd->off], '\n', ret); cmd->off += ret; while (NULL != end) { *end = '\0'; cmd->proc (cmd->proc_cls, cmd->buf); memmove (cmd->buf, end + 1, cmd->off - (end + 1 - cmd->buf)); cmd->off -= (end + 1 - cmd->buf); end = memchr (cmd->buf, '\n', cmd->off); } cmd->rtask = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining (cmd->timeout), cmd->r, &cmd_read, cmd); } /** * Run the given command line and call the given function * for each line of the output. * * @param proc function to call for each line of the output * @param proc_cls closure for proc * @param timeout when to time out * @param binary command to run * @param ... arguments to command * @return NULL on error */ struct GNUNET_OS_CommandHandle * GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls, struct GNUNET_TIME_Relative timeout, const char *binary, ...) { struct GNUNET_OS_CommandHandle *cmd; struct GNUNET_OS_Process *eip; struct GNUNET_DISK_PipeHandle *opipe; va_list ap; opipe = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if (NULL == opipe) return NULL; va_start (ap, binary); /* redirect stdout, don't inherit stderr/stdin */ eip = GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL, opipe, NULL, binary, ap); va_end (ap); if (NULL == eip) { GNUNET_DISK_pipe_close (opipe); return NULL; } GNUNET_DISK_pipe_close_end (opipe, GNUNET_DISK_PIPE_END_WRITE); cmd = GNUNET_new (struct GNUNET_OS_CommandHandle); cmd->timeout = GNUNET_TIME_relative_to_absolute (timeout); cmd->eip = eip; cmd->opipe = opipe; cmd->proc = proc; cmd->proc_cls = proc_cls; cmd->r = GNUNET_DISK_pipe_handle (opipe, GNUNET_DISK_PIPE_END_READ); cmd->rtask = GNUNET_SCHEDULER_add_read_file (timeout, cmd->r, &cmd_read, cmd); return cmd; } /* end of os_priority.c */ gnunet-0.10.1/src/util/test_container_meta_data.c0000644000175000017500000002627012225777501016761 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2006, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_container_meta_data.c * @brief Test for container_meta_data.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define ABORT(m) { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); if (m != NULL) GNUNET_CONTAINER_meta_data_destroy(m); return 1; } static int testMeta (int i) { struct GNUNET_CONTAINER_MetaData *m; char val[256]; char *sval; int j; unsigned int size; m = GNUNET_CONTAINER_meta_data_create (); if (GNUNET_OK != GNUNET_CONTAINER_meta_data_insert (m, "", EXTRACTOR_METATYPE_TITLE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "TestTitle", strlen ("TestTitle") + 1)) ABORT (m); if (GNUNET_OK != GNUNET_CONTAINER_meta_data_insert (m, "", EXTRACTOR_METATYPE_AUTHOR_NAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "TestTitle", strlen ("TestTitle") + 1)) ABORT (m); if (GNUNET_OK == GNUNET_CONTAINER_meta_data_insert (m, "", EXTRACTOR_METATYPE_TITLE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "TestTitle", strlen ("TestTitle") + 1)) /* dup! */ ABORT (m); if (GNUNET_OK == GNUNET_CONTAINER_meta_data_insert (m, "", EXTRACTOR_METATYPE_AUTHOR_NAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "TestTitle", strlen ("TestTitle") + 1)) /* dup! */ ABORT (m); if (2 != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL)) ABORT (m); if (GNUNET_OK != GNUNET_CONTAINER_meta_data_delete (m, EXTRACTOR_METATYPE_AUTHOR_NAME, "TestTitle", strlen ("TestTitle") + 1)) ABORT (m); if (GNUNET_OK == GNUNET_CONTAINER_meta_data_delete (m, EXTRACTOR_METATYPE_AUTHOR_NAME, "TestTitle", strlen ("TestTitle") + 1)) /* already gone */ ABORT (m); if (1 != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL)) ABORT (m); if (GNUNET_OK != GNUNET_CONTAINER_meta_data_delete (m, EXTRACTOR_METATYPE_TITLE, "TestTitle", strlen ("TestTitle") + 1)) ABORT (m); if (GNUNET_OK == GNUNET_CONTAINER_meta_data_delete (m, EXTRACTOR_METATYPE_TITLE, "TestTitle", strlen ("TestTitle") + 1)) /* already gone */ ABORT (m); if (0 != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL)) ABORT (m); for (j = 0; j < i; j++) { GNUNET_snprintf (val, sizeof (val), "%s.%d", "A teststring that should compress well.", j); if (GNUNET_OK != GNUNET_CONTAINER_meta_data_insert (m, "", EXTRACTOR_METATYPE_UNKNOWN, EXTRACTOR_METAFORMAT_UTF8, "text/plain", val, strlen (val) + 1)) ABORT (m); } if (i != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL)) ABORT (m); size = GNUNET_CONTAINER_meta_data_get_serialized_size (m); sval = NULL; if (size != GNUNET_CONTAINER_meta_data_serialize (m, &sval, size, GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL)) { GNUNET_free_non_null (sval); ABORT (m); } GNUNET_CONTAINER_meta_data_destroy (m); m = GNUNET_CONTAINER_meta_data_deserialize (sval, size); GNUNET_free (sval); if (m == NULL) ABORT (m); for (j = 0; j < i; j++) { GNUNET_snprintf (val, sizeof (val), "%s.%d", "A teststring that should compress well.", j); if (GNUNET_OK != GNUNET_CONTAINER_meta_data_delete (m, EXTRACTOR_METATYPE_UNKNOWN, val, strlen (val) + 1)) { ABORT (m); } } if (0 != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL)) ABORT (m); GNUNET_CONTAINER_meta_data_destroy (m); return 0; } int testMetaMore (int i) { struct GNUNET_CONTAINER_MetaData *meta; int q; char txt[128]; char *data; unsigned long long size; meta = GNUNET_CONTAINER_meta_data_create (); for (q = 0; q <= i; q++) { GNUNET_snprintf (txt, 128, "%u -- %u\n", i, q); GNUNET_CONTAINER_meta_data_insert (meta, "", q % EXTRACTOR_metatype_get_max (), EXTRACTOR_METAFORMAT_UTF8, "text/plain", txt, strlen (txt) + 1); } size = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); data = GNUNET_malloc (size * 4); if (size != GNUNET_CONTAINER_meta_data_serialize (meta, &data, size * 4, GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL)) { GNUNET_free (data); ABORT (meta); } GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_free (data); return 0; } static int testMetaLink () { struct GNUNET_CONTAINER_MetaData *m; char *val; unsigned int size; m = GNUNET_CONTAINER_meta_data_create (); if (GNUNET_OK != GNUNET_CONTAINER_meta_data_insert (m, "", EXTRACTOR_METATYPE_UNKNOWN, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "link", strlen ("link") + 1)) ABORT (m); if (GNUNET_OK != GNUNET_CONTAINER_meta_data_insert (m, "", EXTRACTOR_METATYPE_FILENAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "lib-link.m4", strlen ("lib-link.m4") + 1)) ABORT (m); val = NULL; size = GNUNET_CONTAINER_meta_data_serialize (m, &val, (size_t) - 1, GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); GNUNET_CONTAINER_meta_data_destroy (m); m = GNUNET_CONTAINER_meta_data_deserialize (val, size); GNUNET_free (val); if (m == NULL) ABORT (m); GNUNET_CONTAINER_meta_data_destroy (m); return 0; } int check () { struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_CONTAINER_MetaData *meta2; int q; int i = 100; char txt[128]; char *str; unsigned char *thumb; meta = GNUNET_CONTAINER_meta_data_create (); meta2 = GNUNET_CONTAINER_meta_data_create (); for (q = 0; q <= i; q++) { GNUNET_snprintf (txt, 128, "%u -- %u\n", i, q); GNUNET_CONTAINER_meta_data_insert (meta, "", EXTRACTOR_METATYPE_UNKNOWN, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "TestTitle", strlen ("TestTitle") + 1); GNUNET_CONTAINER_meta_data_insert (meta2, "", EXTRACTOR_METATYPE_UNKNOWN, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "TestTitle", strlen ("TestTitle") + 1); } //check meta_data_test_equal if (GNUNET_YES != GNUNET_CONTAINER_meta_data_test_equal (meta, meta2)) { GNUNET_CONTAINER_meta_data_destroy (meta2); ABORT (meta); } //check meta_data_clear GNUNET_CONTAINER_meta_data_clear (meta2); if (0 != GNUNET_CONTAINER_meta_data_iterate (meta2, NULL, NULL)) { GNUNET_CONTAINER_meta_data_destroy (meta2); ABORT (meta); } // check equal branch in meta_data_test_equal if (GNUNET_YES != GNUNET_CONTAINER_meta_data_test_equal (meta, meta)) { GNUNET_CONTAINER_meta_data_destroy (meta2); ABORT (meta); } // check "count" branch in meta_data_test_equal if (GNUNET_NO != GNUNET_CONTAINER_meta_data_test_equal (meta, meta2)) { GNUNET_CONTAINER_meta_data_destroy (meta2); ABORT (meta); } // check meta_data_add_publication_date GNUNET_CONTAINER_meta_data_add_publication_date (meta2); // check meta_data_merge GNUNET_CONTAINER_meta_data_clear (meta2); GNUNET_CONTAINER_meta_data_merge (meta2, meta); if (100 == GNUNET_CONTAINER_meta_data_iterate (meta2, NULL, NULL)) { GNUNET_CONTAINER_meta_data_destroy (meta2); ABORT (meta); } // check meta_data_get_by_type GNUNET_CONTAINER_meta_data_clear (meta2); if (NULL != (str = GNUNET_CONTAINER_meta_data_get_by_type (meta2, EXTRACTOR_METATYPE_UNKNOWN))) { GNUNET_CONTAINER_meta_data_destroy (meta2); GNUNET_free (str); ABORT (meta); } str = GNUNET_CONTAINER_meta_data_get_by_type (meta, EXTRACTOR_METATYPE_UNKNOWN); GNUNET_assert (NULL != str); if (str[0] != 'T') { GNUNET_CONTAINER_meta_data_destroy (meta2); GNUNET_free (str); ABORT (meta); } GNUNET_free (str); // check branch if (NULL != (str = GNUNET_CONTAINER_meta_data_get_by_type (meta, EXTRACTOR_METATYPE_PUBLICATION_DATE))) { GNUNET_free (str); GNUNET_CONTAINER_meta_data_destroy (meta2); ABORT (meta); } //check meta_data_get_first_by_types str = GNUNET_CONTAINER_meta_data_get_first_by_types (meta, EXTRACTOR_METATYPE_UNKNOWN, -1); GNUNET_assert (NULL != str); if (str[0] != 'T') { GNUNET_CONTAINER_meta_data_destroy (meta2); GNUNET_free (str); ABORT (meta); } GNUNET_free (str); //check meta_data_get_thumbnail if (GNUNET_CONTAINER_meta_data_get_thumbnail (meta, &thumb) != 0) { GNUNET_free (thumb); GNUNET_CONTAINER_meta_data_destroy (meta2); ABORT (meta); } GNUNET_CONTAINER_meta_data_destroy (meta2); //check meta_data_duplicate meta2 = GNUNET_CONTAINER_meta_data_duplicate (meta); if (200 == GNUNET_CONTAINER_meta_data_iterate (meta2, NULL, NULL)) { GNUNET_CONTAINER_meta_data_destroy (meta2); ABORT (meta); } GNUNET_CONTAINER_meta_data_destroy (meta2); GNUNET_CONTAINER_meta_data_destroy (meta); return 0; } int main (int argc, char *argv[]) { int failureCount = 0; int i; GNUNET_log_setup ("test-container-meta-data", "WARNING", NULL); for (i = 0; i < 255; i++) failureCount += testMeta (i); for (i = 1; i < 255; i++) failureCount += testMetaMore (i); failureCount += testMetaLink (); int ret = check (); if (ret == 1) return 1; if (failureCount != 0) return 1; return 0; } /* end of test_container_meta_data.c */ gnunet-0.10.1/src/util/crypto_ecc.c0000644000175000017500000013045212320724374014065 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/crypto_ecc.c * @brief public key cryptography (ECC) with libgcrypt * @author Christian Grothoff */ #include "platform.h" #include #include "gnunet_util_lib.h" #define EXTRA_CHECKS 0 /** * Name of the curve we are using. Note that we have hard-coded * structs that use 256 bits, so using a bigger curve will require * changes that break stuff badly. The name of the curve given here * must be agreed by all peers and be supported by libgcrypt. */ #define CURVE "Ed25519" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by gcry_strerror(rc). */ #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0) /** * Extract values from an S-expression. * * @param array where to store the result(s) * @param sexp S-expression to parse * @param topname top-level name in the S-expression that is of interest * @param elems names of the elements to extract * @return 0 on success */ static int key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, const char *elems) { gcry_sexp_t list; gcry_sexp_t l2; const char *s; unsigned int i; unsigned int idx; list = gcry_sexp_find_token (sexp, topname, 0); if (! list) return 1; l2 = gcry_sexp_cadr (list); gcry_sexp_release (list); list = l2; if (! list) return 2; idx = 0; for (s = elems; *s; s++, idx++) { l2 = gcry_sexp_find_token (list, s, 1); if (! l2) { for (i = 0; i < idx; i++) { gcry_free (array[i]); array[i] = NULL; } gcry_sexp_release (list); return 3; /* required parameter not found */ } array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l2); if (! array[idx]) { for (i = 0; i < idx; i++) { gcry_free (array[i]); array[i] = NULL; } gcry_sexp_release (list); return 4; /* required parameter is invalid */ } } gcry_sexp_release (list); return 0; } /** * Convert the given private key from the network format to the * S-expression that can be used by libgcrypt. * * @param priv private key to decode * @return NULL on error */ static gcry_sexp_t decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv) { gcry_sexp_t result; int rc; rc = gcry_sexp_build (&result, NULL, "(private-key(ecc(curve \"" CURVE "\")" "(d %b)))", (int)sizeof (priv->d), priv->d); if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); GNUNET_assert (0); } #if EXTRA_CHECKS if (0 != (rc = gcry_pk_testkey (result))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); GNUNET_assert (0); } #endif return result; } /** * Convert the given private key from the network format to the * S-expression that can be used by libgcrypt. * * @param priv private key to decode * @return NULL on error */ static gcry_sexp_t decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv) { gcry_sexp_t result; int rc; rc = gcry_sexp_build (&result, NULL, "(private-key(ecc(curve \"" CURVE "\")" "(flags eddsa)(d %b)))", (int)sizeof (priv->d), priv->d); if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); GNUNET_assert (0); } #if EXTRA_CHECKS if (0 != (rc = gcry_pk_testkey (result))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); GNUNET_assert (0); } #endif return result; } /** * Convert the given private key from the network format to the * S-expression that can be used by libgcrypt. * * @param priv private key to decode * @return NULL on error */ static gcry_sexp_t decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv) { gcry_sexp_t result; int rc; rc = gcry_sexp_build (&result, NULL, "(private-key(ecc(curve \"" CURVE "\")" "(d %b)))", (int)sizeof (priv->d), priv->d); if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); GNUNET_assert (0); } #if EXTRA_CHECKS if (0 != (rc = gcry_pk_testkey (result))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); GNUNET_assert (0); } #endif return result; } /** * Extract the public key for the given private key. * * @param priv the private key * @param pub where to write the public key */ void GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_EcdsaPublicKey *pub) { gcry_sexp_t sexp; gcry_ctx_t ctx; gcry_mpi_t q; sexp = decode_private_ecdsa_key (priv); GNUNET_assert (NULL != sexp); GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL)); gcry_sexp_release (sexp); q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); GNUNET_assert (q); GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q); gcry_mpi_release (q); gcry_ctx_release (ctx); } /** * Extract the public key for the given private key. * * @param priv the private key * @param pub where to write the public key */ void GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub) { gcry_sexp_t sexp; gcry_ctx_t ctx; gcry_mpi_t q; sexp = decode_private_eddsa_key (priv); GNUNET_assert (NULL != sexp); GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL)); gcry_sexp_release (sexp); q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); GNUNET_assert (q); GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q); gcry_mpi_release (q); gcry_ctx_release (ctx); } /** * Extract the public key for the given private key. * * @param priv the private key * @param pub where to write the public key */ void GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, struct GNUNET_CRYPTO_EcdhePublicKey *pub) { gcry_sexp_t sexp; gcry_ctx_t ctx; gcry_mpi_t q; sexp = decode_private_ecdhe_key (priv); GNUNET_assert (NULL != sexp); GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL)); gcry_sexp_release (sexp); q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); GNUNET_assert (q); GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q); gcry_mpi_release (q); gcry_ctx_release (ctx); } /** * Convert a public key to a string. * * @param pub key to convert * @return string representing @a pub */ char * GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) { char *pubkeybuf; size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8; char *end; if (keylen % 5 > 0) keylen += 5 - keylen % 5; keylen /= 5; pubkeybuf = GNUNET_malloc (keylen + 1); end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), pubkeybuf, keylen); if (NULL == end) { GNUNET_free (pubkeybuf); return NULL; } *end = '\0'; return pubkeybuf; } /** * Convert a public key to a string. * * @param pub key to convert * @return string representing @a pub */ char * GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub) { char *pubkeybuf; size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8; char *end; if (keylen % 5 > 0) keylen += 5 - keylen % 5; keylen /= 5; pubkeybuf = GNUNET_malloc (keylen + 1); end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), pubkeybuf, keylen); if (NULL == end) { GNUNET_free (pubkeybuf); return NULL; } *end = '\0'; return pubkeybuf; } /** * Convert a string representing a public key to a public key. * * @param enc encoded public key * @param enclen number of bytes in @a enc (without 0-terminator) * @param pub where to store the public key * @return #GNUNET_OK on success */ int GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc, size_t enclen, struct GNUNET_CRYPTO_EcdsaPublicKey *pub) { size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8; if (keylen % 5 > 0) keylen += 5 - keylen % 5; keylen /= 5; if (enclen != keylen) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen, pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) return GNUNET_SYSERR; return GNUNET_OK; } /** * Convert a string representing a public key to a public key. * * @param enc encoded public key * @param enclen number of bytes in @a enc (without 0-terminator) * @param pub where to store the public key * @return #GNUNET_OK on success */ int GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc, size_t enclen, struct GNUNET_CRYPTO_EddsaPublicKey *pub) { size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8; if (keylen % 5 > 0) keylen += 5 - keylen % 5; keylen /= 5; if (enclen != keylen) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen, pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) return GNUNET_SYSERR; return GNUNET_OK; } /** * @ingroup crypto * Clear memory that was used to store a private key. * * @param pk location of the key */ void GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk) { memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); } /** * @ingroup crypto * Clear memory that was used to store a private key. * * @param pk location of the key */ void GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk) { memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); } /** * @ingroup crypto * Clear memory that was used to store a private key. * * @param pk location of the key */ void GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk) { memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); } /** * Create a new private key. Caller must free return value. * * @return fresh private key */ struct GNUNET_CRYPTO_EcdhePrivateKey * GNUNET_CRYPTO_ecdhe_key_create () { struct GNUNET_CRYPTO_EcdhePrivateKey *priv; gcry_sexp_t priv_sexp; gcry_sexp_t s_keyparam; gcry_mpi_t d; int rc; if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")" "(flags)))"))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); return NULL; } if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc); gcry_sexp_release (s_keyparam); return NULL; } gcry_sexp_release (s_keyparam); #if EXTRA_CHECKS if (0 != (rc = gcry_pk_testkey (priv_sexp))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); gcry_sexp_release (priv_sexp); return NULL; } #endif if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d"))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc); gcry_sexp_release (priv_sexp); return NULL; } gcry_sexp_release (priv_sexp); priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey); GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d); gcry_mpi_release (d); return priv; } /** * Create a new private key. Caller must free return value. * * @return fresh private key */ struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_create () { struct GNUNET_CRYPTO_EcdsaPrivateKey *priv; gcry_sexp_t priv_sexp; gcry_sexp_t s_keyparam; gcry_mpi_t d; int rc; if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")" "(flags)))"))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); return NULL; } if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc); gcry_sexp_release (s_keyparam); return NULL; } gcry_sexp_release (s_keyparam); #if EXTRA_CHECKS if (0 != (rc = gcry_pk_testkey (priv_sexp))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); gcry_sexp_release (priv_sexp); return NULL; } #endif if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d"))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc); gcry_sexp_release (priv_sexp); return NULL; } gcry_sexp_release (priv_sexp); priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d); gcry_mpi_release (d); return priv; } /** * Create a new private key. Caller must free return value. * * @return fresh private key */ struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create () { struct GNUNET_CRYPTO_EddsaPrivateKey *priv; gcry_sexp_t priv_sexp; gcry_sexp_t s_keyparam; gcry_mpi_t d; int rc; if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")" "(flags eddsa)))"))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); return NULL; } if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc); gcry_sexp_release (s_keyparam); return NULL; } gcry_sexp_release (s_keyparam); #if EXTRA_CHECKS if (0 != (rc = gcry_pk_testkey (priv_sexp))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); gcry_sexp_release (priv_sexp); return NULL; } #endif if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d"))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc); gcry_sexp_release (priv_sexp); return NULL; } gcry_sexp_release (priv_sexp); priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey); GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d); gcry_mpi_release (d); return priv; } /** * Get the shared private key we use for anonymous users. * * @return "anonymous" private key */ const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_get_anonymous () { /** * 'anonymous' pseudonym (global static, d=1, public key = G * (generator). */ static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous; static int once; if (once) return &anonymous; GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d, sizeof (anonymous.d), GCRYMPI_CONST_ONE); once = 1; return &anonymous; } /** * Wait for a short time (we're trying to lock a file or want * to give another process a shot at finishing a disk write, etc.). * Sleeps for 100ms (as that should be long enough for virtually all * modern systems to context switch and allow another process to do * some 'real' work). */ static void short_wait () { struct GNUNET_TIME_Relative timeout; timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); } /** * Create a new private key by reading it from a file. If the * files does not exist, create a new key and write it to the * file. Caller must free return value. Note that this function * can not guarantee that another process might not be trying * the same operation on the same file at the same time. * If the contents of the file * are invalid the old file is deleted and a fresh key is * created. * * @param filename name of file to use to store the key * @return new private key, NULL on error (for example, * permission denied) */ struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename) { struct GNUNET_CRYPTO_EddsaPrivateKey *priv; struct GNUNET_DISK_FileHandle *fd; unsigned int cnt; int ec; uint64_t fs; if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename)) return NULL; while (GNUNET_YES != GNUNET_DISK_file_test (filename)) { fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == fd) { if (EEXIST == errno) { if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { /* must exist but not be accessible, fail for good! */ if (0 != ACCESS (filename, R_OK)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename); else GNUNET_break (0); /* what is going on!? */ return NULL; } continue; } LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); return NULL; } cnt = 0; while (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey), GNUNET_YES)) { short_wait (); if (0 == ++cnt % 10) { ec = errno; LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not acquire lock on file `%s': %s...\n"), filename, STRERROR (ec)); } } LOG (GNUNET_ERROR_TYPE_INFO, _("Creating a new private key. This may take a while.\n")); priv = GNUNET_CRYPTO_eddsa_key_create (); GNUNET_assert (NULL != priv); GNUNET_assert (sizeof (*priv) == GNUNET_DISK_file_write (fd, priv, sizeof (*priv))); GNUNET_DISK_file_sync (fd); if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); return priv; } /* key file exists already, read it! */ fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == fd) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); return NULL; } cnt = 0; while (1) { if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey), GNUNET_NO)) { if (0 == ++cnt % 60) { ec = errno; LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not acquire lock on file `%s': %s...\n"), filename, STRERROR (ec)); LOG (GNUNET_ERROR_TYPE_ERROR, _ ("This may be ok if someone is currently generating a private key.\n")); } short_wait (); continue; } if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { /* eh, what!? File we opened is now gone!? */ LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename); if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd)); return NULL; } if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) fs = 0; if (fs < sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) { /* maybe we got the read lock before the key generating * process had a chance to get the write lock; give it up! */ if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); if (0 == ++cnt % 10) { LOG (GNUNET_ERROR_TYPE_ERROR, _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"), filename, (unsigned int) fs, (unsigned int) sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); LOG (GNUNET_ERROR_TYPE_ERROR, _("This may be ok if someone is currently generating a key.\n")); } short_wait (); /* wait a bit longer! */ continue; } break; } fs = sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey); priv = GNUNET_malloc (fs); GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs)); if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); return priv; } /** * Create a new private key by reading it from a file. If the * files does not exist, create a new key and write it to the * file. Caller must free return value. Note that this function * can not guarantee that another process might not be trying * the same operation on the same file at the same time. * If the contents of the file * are invalid the old file is deleted and a fresh key is * created. * * @param filename name of file to use to store the key * @return new private key, NULL on error (for example, * permission denied) */ struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename) { struct GNUNET_CRYPTO_EcdsaPrivateKey *priv; struct GNUNET_DISK_FileHandle *fd; unsigned int cnt; int ec; uint64_t fs; if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename)) return NULL; while (GNUNET_YES != GNUNET_DISK_file_test (filename)) { fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == fd) { if (EEXIST == errno) { if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { /* must exist but not be accessible, fail for good! */ if (0 != ACCESS (filename, R_OK)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename); else GNUNET_break (0); /* what is going on!? */ return NULL; } continue; } LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); return NULL; } cnt = 0; while (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), GNUNET_YES)) { short_wait (); if (0 == ++cnt % 10) { ec = errno; LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not acquire lock on file `%s': %s...\n"), filename, STRERROR (ec)); } } LOG (GNUNET_ERROR_TYPE_INFO, _("Creating a new private key. This may take a while.\n")); priv = GNUNET_CRYPTO_ecdsa_key_create (); GNUNET_assert (NULL != priv); GNUNET_assert (sizeof (*priv) == GNUNET_DISK_file_write (fd, priv, sizeof (*priv))); GNUNET_DISK_file_sync (fd); if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); return priv; } /* key file exists already, read it! */ fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == fd) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); return NULL; } cnt = 0; while (1) { if (GNUNET_YES != GNUNET_DISK_file_lock (fd, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), GNUNET_NO)) { if (0 == ++cnt % 60) { ec = errno; LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not acquire lock on file `%s': %s...\n"), filename, STRERROR (ec)); LOG (GNUNET_ERROR_TYPE_ERROR, _ ("This may be ok if someone is currently generating a private key.\n")); } short_wait (); continue; } if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { /* eh, what!? File we opened is now gone!? */ LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename); if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd)); return NULL; } if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) fs = 0; if (fs < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) { /* maybe we got the read lock before the key generating * process had a chance to get the write lock; give it up! */ if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); if (0 == ++cnt % 10) { LOG (GNUNET_ERROR_TYPE_ERROR, _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"), filename, (unsigned int) fs, (unsigned int) sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); LOG (GNUNET_ERROR_TYPE_ERROR, _("This may be ok if someone is currently generating a key.\n")); } short_wait (); /* wait a bit longer! */ continue; } break; } fs = sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey); priv = GNUNET_malloc (fs); GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs)); if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); return priv; } /** * Create a new private key by reading our peer's key from * the file specified in the configuration. * * @param cfg the configuration to use * @return new private key, NULL on error (for example, * permission denied) */ struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_CRYPTO_EddsaPrivateKey *priv; char *fn; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn)) return NULL; priv = GNUNET_CRYPTO_eddsa_key_create_from_file (fn); GNUNET_free (fn); return priv; } /** * Setup a key file for a peer given the name of the * configuration file (!). This function is used so that * at a later point code can be certain that reading a * key is fast (for example in time-dependent testcases). * * @param cfg_name name of the configuration file to use */ void GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name) { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CRYPTO_EddsaPrivateKey *priv; cfg = GNUNET_CONFIGURATION_create (); (void) GNUNET_CONFIGURATION_load (cfg, cfg_name); priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); if (NULL != priv) GNUNET_free (priv); GNUNET_CONFIGURATION_destroy (cfg); } /** * Retrieve the identity of the host's peer. * * @param cfg configuration to use * @param dst pointer to where to write the peer identity * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity * could not be retrieved */ int GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst) { struct GNUNET_CRYPTO_EddsaPrivateKey *priv; if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load peer's private key\n")); return GNUNET_SYSERR; } GNUNET_CRYPTO_eddsa_key_get_public (priv, &dst->public_key); GNUNET_free (priv); return GNUNET_OK; } /** * Compare two Peer Identities. * * @param first first peer identity * @param second second peer identity * @return bigger than 0 if first > second, * 0 if they are the same * smaller than 0 if second > first */ int GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second) { return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity)); } /** * Convert the data specified in the given purpose argument to an * S-expression suitable for signature operations. * * @param purpose data to convert * @return converted s-expression */ static gcry_sexp_t data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) { struct GNUNET_HashCode hc; gcry_sexp_t data; int rc; GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc); if (0 != (rc = gcry_sexp_build (&data, NULL, "(data(flags eddsa)(hash-algo %s)(value %b))", "sha512", (int)sizeof (hc), &hc))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); return NULL; } return data; } /** * Convert the data specified in the given purpose argument to an * S-expression suitable for signature operations. * * @param purpose data to convert * @return converted s-expression */ static gcry_sexp_t data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) { struct GNUNET_HashCode hc; gcry_sexp_t data; int rc; GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc); if (0 != (rc = gcry_sexp_build (&data, NULL, "(data(flags rfc6979)(hash %s %b))", "sha512", (int)sizeof (hc), &hc))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); return NULL; } return data; } /** * Sign a given block. * * @param priv private key to use for the signing * @param purpose what to sign (size, purpose) * @param sig where to write the signature * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EcdsaSignature *sig) { gcry_sexp_t priv_sexp; gcry_sexp_t sig_sexp; gcry_sexp_t data; int rc; gcry_mpi_t rs[2]; priv_sexp = decode_private_ecdsa_key (priv); data = data_to_ecdsa_value (purpose); if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp))) { LOG (GNUNET_ERROR_TYPE_WARNING, _("ECC signing failed at %s:%d: %s\n"), __FILE__, __LINE__, gcry_strerror (rc)); gcry_sexp_release (data); gcry_sexp_release (priv_sexp); return GNUNET_SYSERR; } gcry_sexp_release (priv_sexp); gcry_sexp_release (data); /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in 'signature' */ if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs"))) { GNUNET_break (0); gcry_sexp_release (sig_sexp); return GNUNET_SYSERR; } gcry_sexp_release (sig_sexp); GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]); GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]); gcry_mpi_release (rs[0]); gcry_mpi_release (rs[1]); return GNUNET_OK; } /** * Sign a given block. * * @param priv private key to use for the signing * @param purpose what to sign (size, purpose) * @param sig where to write the signature * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig) { gcry_sexp_t priv_sexp; gcry_sexp_t sig_sexp; gcry_sexp_t data; int rc; gcry_mpi_t rs[2]; priv_sexp = decode_private_eddsa_key (priv); data = data_to_eddsa_value (purpose); if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp))) { LOG (GNUNET_ERROR_TYPE_WARNING, _("EdDSA signing failed at %s:%d: %s\n"), __FILE__, __LINE__, gcry_strerror (rc)); gcry_sexp_release (data); gcry_sexp_release (priv_sexp); return GNUNET_SYSERR; } gcry_sexp_release (priv_sexp); gcry_sexp_release (data); /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in 'signature' */ if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs"))) { GNUNET_break (0); gcry_sexp_release (sig_sexp); return GNUNET_SYSERR; } gcry_sexp_release (sig_sexp); GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]); GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]); gcry_mpi_release (rs[0]); gcry_mpi_release (rs[1]); return GNUNET_OK; } /** * Verify signature. * * @param purpose what is the purpose that the signature should have? * @param validate block to validate (size, purpose, data) * @param sig signature that is being validated * @param pub public key of the signer * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid */ int GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EcdsaSignature *sig, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) { gcry_sexp_t data; gcry_sexp_t sig_sexpr; gcry_sexp_t pub_sexpr; int rc; if (purpose != ntohl (validate->purpose)) return GNUNET_SYSERR; /* purpose mismatch */ /* build s-expression for signature */ if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL, "(sig-val(ecdsa(r %b)(s %b)))", (int)sizeof (sig->r), sig->r, (int)sizeof (sig->s), sig->s))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); return GNUNET_SYSERR; } data = data_to_ecdsa_value (validate); if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL, "(public-key(ecc(curve " CURVE ")(q %b)))", (int)sizeof (pub->q_y), pub->q_y))) { gcry_sexp_release (data); gcry_sexp_release (sig_sexpr); return GNUNET_SYSERR; } rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr); gcry_sexp_release (pub_sexpr); gcry_sexp_release (data); gcry_sexp_release (sig_sexpr); if (0 != rc) { LOG (GNUNET_ERROR_TYPE_INFO, _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__, __LINE__, gcry_strerror (rc)); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Verify signature. * * @param purpose what is the purpose that the signature should have? * @param validate block to validate (size, purpose, data) * @param sig signature that is being validated * @param pub public key of the signer * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid */ int GNUNET_CRYPTO_eddsa_verify (uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub) { gcry_sexp_t data; gcry_sexp_t sig_sexpr; gcry_sexp_t pub_sexpr; int rc; if (purpose != ntohl (validate->purpose)) return GNUNET_SYSERR; /* purpose mismatch */ /* build s-expression for signature */ if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL, "(sig-val(eddsa(r %b)(s %b)))", (int)sizeof (sig->r), sig->r, (int)sizeof (sig->s), sig->s))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); return GNUNET_SYSERR; } data = data_to_eddsa_value (validate); if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL, "(public-key(ecc(curve " CURVE ")(q %b)))", (int)sizeof (pub->q_y), pub->q_y))) { gcry_sexp_release (data); gcry_sexp_release (sig_sexpr); return GNUNET_SYSERR; } rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr); gcry_sexp_release (pub_sexpr); gcry_sexp_release (data); gcry_sexp_release (sig_sexpr); if (0 != rc) { LOG (GNUNET_ERROR_TYPE_INFO, _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__, __LINE__, gcry_strerror (rc)); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Derive key material from a public and a private ECDHE key. * * @param priv private key to use for the ECDH (x) * @param pub public key to use for the ECDH (yG) * @param key_material where to write the key material (xyG) * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_EcdhePublicKey *pub, struct GNUNET_HashCode *key_material) { gcry_mpi_point_t result; gcry_mpi_point_t q; gcry_mpi_t d; gcry_ctx_t ctx; gcry_sexp_t pub_sexpr; gcry_mpi_t result_x; unsigned char xbuf[256 / 8]; size_t rsize; /* first, extract the q = dP value from the public key */ if (0 != gcry_sexp_build (&pub_sexpr, NULL, "(public-key(ecc(curve " CURVE ")(q %b)))", (int)sizeof (pub->q_y), pub->q_y)) return GNUNET_SYSERR; GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL)); gcry_sexp_release (pub_sexpr); q = gcry_mpi_ec_get_point ("q", ctx, 0); /* second, extract the d value from our private key */ GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d)); /* then call the 'multiply' function, to compute the product */ result = gcry_mpi_point_new (0); gcry_mpi_ec_mul (result, d, q, ctx); gcry_mpi_point_release (q); gcry_mpi_release (d); /* finally, convert point to string for hashing */ result_x = gcry_mpi_new (256); if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx)) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0); gcry_mpi_point_release (result); gcry_ctx_release (ctx); return GNUNET_SYSERR; } gcry_mpi_point_release (result); gcry_ctx_release (ctx); rsize = sizeof (xbuf); GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE)); /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned' as that does not include the sign bit; x should be a 255-bit value, so with the sign it should fit snugly into the 256-bit xbuf */ GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, result_x)); GNUNET_CRYPTO_hash (xbuf, rsize, key_material); gcry_mpi_release (result_x); return GNUNET_OK; } /** * Derive the 'h' value for key derivation, where * 'h = H(l,P)'. * * @param pub public key for deriviation * @param label label for deriviation * @param context additional context to use for HKDF of 'h'; * typically the name of the subsystem/application * @return h value */ static gcry_mpi_t derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, const char *context) { gcry_mpi_t h; struct GNUNET_HashCode hc; GNUNET_CRYPTO_kdf (&hc, sizeof (hc), "key-derivation", strlen ("key-derivation"), pub, sizeof (*pub), label, strlen (label), context, strlen (context), NULL, 0); GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof (hc)); return h; } /** * Derive a private key from a given private key and a label. * Essentially calculates a private key 'd = H(l,P) * x mod n' * where n is the size of the ECC group and P is the public * key associated with the private key 'd'. * * @param priv original private key * @param label label to use for key deriviation * @param context additional context to use for HKDF of 'h'; * typically the name of the subsystem/application * @return derived private key */ struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const char *label, const char *context) { struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_CRYPTO_EcdsaPrivateKey *ret; gcry_mpi_t h; gcry_mpi_t x; gcry_mpi_t d; gcry_mpi_t n; gcry_ctx_t ctx; GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); n = gcry_mpi_ec_get_mpi ("n", ctx, 1); GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub); h = derive_h (&pub, label, context); GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof (priv->d)); d = gcry_mpi_new (256); gcry_mpi_mulm (d, h, x, n); gcry_mpi_release (h); gcry_mpi_release (x); gcry_mpi_release (n); gcry_ctx_release (ctx); ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d); gcry_mpi_release (d); return ret; } /** * Derive a public key from a given public key and a label. * Essentially calculates a public key 'V = H(l,P) * P'. * * @param pub original public key * @param label label to use for key derivation * @param context additional context to use for HKDF of 'h'; * typically the name of the subsystem/application * @param result where to write the derived public key */ void GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, const char *context, struct GNUNET_CRYPTO_EcdsaPublicKey *result) { gcry_ctx_t ctx; gcry_mpi_t q_y; gcry_mpi_t h; gcry_mpi_t n; gcry_mpi_t h_mod_n; gcry_mpi_point_t q; gcry_mpi_point_t v; GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); /* obtain point 'q' from original public key. The provided 'q' is compressed thus we first store it in the context and then get it back as a (decompresssed) point. */ q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y)); GNUNET_assert (q_y); GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx)); gcry_mpi_release (q_y); q = gcry_mpi_ec_get_point ("q", ctx, 0); GNUNET_assert (q); /* calculate h_mod_n = h % n */ h = derive_h (pub, label, context); n = gcry_mpi_ec_get_mpi ("n", ctx, 1); h_mod_n = gcry_mpi_new (256); gcry_mpi_mod (h_mod_n, h, n); /* calculate v = h_mod_n * q */ v = gcry_mpi_point_new (0); gcry_mpi_ec_mul (v, h_mod_n, q, ctx); gcry_mpi_release (h_mod_n); gcry_mpi_release (h); gcry_mpi_release (n); gcry_mpi_point_release (q); /* convert point 'v' to public key that we return */ GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx)); gcry_mpi_point_release (v); q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); GNUNET_assert (q_y); GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof result->q_y, q_y); gcry_mpi_release (q_y); gcry_ctx_release (ctx); } /* end of crypto_ecc.c */ gnunet-0.10.1/src/util/test_peer.c0000644000175000017500000000675712225777501013743 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_peer.c * @brief testcase for peer.c * @author Safey Mohammed */ #include "platform.h" #include "gnunet_util_lib.h" #include #define NUMBER_OF_PEERS 10 /** * A list of Peer ID's to play with */ static struct GNUNET_PeerIdentity pidArr[NUMBER_OF_PEERS]; static void generatePeerIdList () { int i; for (i = 0; i < NUMBER_OF_PEERS; i++) { gcry_randomize (&pidArr[i], sizeof (struct GNUNET_PeerIdentity), GCRY_STRONG_RANDOM); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %d: %s\n", i, GNUNET_i2s (&pidArr[i])); } } static int check () { int i; GNUNET_PEER_Id pid; struct GNUNET_PeerIdentity res; struct GNUNET_PeerIdentity zero; GNUNET_PEER_Id ids[] = { 1, 2, 3 }; GNUNET_assert (0 == GNUNET_PEER_intern (NULL)); /* Insert Peers into PeerEntry table and hashmap */ for (i = 0; i < NUMBER_OF_PEERS; i++) { pid = GNUNET_PEER_intern (&pidArr[i]); if (pid != (i + 1)) { FPRINTF (stderr, "%s", "Unexpected Peer ID returned by intern function\n"); return 1; } } /* Referencing the first 3 peers once again */ for (i = 0; i < 3; i++) { pid = GNUNET_PEER_intern (&pidArr[i]); if (pid != (i + 1)) { FPRINTF (stderr, "%s", "Unexpected Peer ID returned by intern function\n"); return 1; } } /* Dereferencing the first 3 peers once [decrementing their reference count] */ GNUNET_PEER_decrement_rcs (ids, 3); /* re-referencing the first 3 peers using the change_rc function */ for (i = 1; i <= 3; i++) GNUNET_PEER_change_rc (i, 1); /* Removing the second Peer from the PeerEntry hash map */ GNUNET_PEER_change_rc (2, -2); /* convert the pid of the first PeerEntry into that of the third */ GNUNET_PEER_resolve (1, &res); GNUNET_assert (0 == memcmp (&res, &pidArr[0], sizeof (res))); /* * Attempt to convert pid = 0 (which is reserved) * into a peer identity object, the peer identity memory * is expected to be set to zero */ memset (&zero, 0, sizeof (struct GNUNET_PeerIdentity)); GNUNET_log_skip (1, GNUNET_YES); GNUNET_PEER_resolve (0, &res); GNUNET_assert (0 == memcmp (&res, &zero, sizeof (res))); /* Removing peer entries 1 and 3 from table using the list decrement function */ /* If count = 0, nothing should be done whatsoever */ GNUNET_PEER_decrement_rcs (ids, 0); ids[1] = 3; GNUNET_PEER_decrement_rcs (ids, 2); GNUNET_PEER_decrement_rcs (ids, 2); return 0; } int main () { unsigned int i; GNUNET_log_setup ("test-peer", "ERROR", NULL); for (i = 0; i < 1; i++) { generatePeerIdList (); if (0 != check ()) return 1; } return 0; } /* end of test_peer.c */ gnunet-0.10.1/src/util/os_installation.c0000644000175000017500000005335212274162760015143 00000000000000/* This file is part of GNUnet. (C) 2006-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/util/os_installation.c * @brief get paths used by the program * @author Milan */ #include #include #include #include #include /* for u16_to_u8 */ #include "platform.h" #include "gnunet_util_lib.h" #if DARWIN #include #include #elif WINDOWS #include #endif #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) #if LINUX /** * Try to determine path by reading /proc/PID/exe * * @return NULL on error */ static char * get_path_from_proc_maps () { char fn[64]; char line[1024]; char dir[1024]; FILE *f; char *lgu; GNUNET_snprintf (fn, sizeof (fn), "/proc/%u/maps", getpid ()); if (NULL == (f = FOPEN (fn, "r"))) return NULL; while (NULL != fgets (line, sizeof (line), f)) { if ((1 == SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%1023s", dir)) && (NULL != (lgu = strstr (dir, "libgnunetutil")))) { lgu[0] = '\0'; FCLOSE (f); return GNUNET_strdup (dir); } } FCLOSE (f); return NULL; } /** * Try to determine path by reading /proc/PID/exe * * @return NULL on error */ static char * get_path_from_proc_exe () { char fn[64]; char lnk[1024]; ssize_t size; GNUNET_snprintf (fn, sizeof (fn), "/proc/%u/exe", getpid ()); size = readlink (fn, lnk, sizeof (lnk) - 1); if (size <= 0) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "readlink", fn); return NULL; } GNUNET_assert (size < sizeof (lnk)); lnk[size] = '\0'; while ((lnk[size] != '/') && (size > 0)) size--; /* test for being in lib/gnunet/libexec/ or lib/MULTIARCH/gnunet/libexec */ if ( (size > strlen ("/gnunet/libexec/")) && (0 == strcmp ("/gnunet/libexec/", &lnk[size - strlen ("/gnunet/libexec/")])) ) size -= strlen ("gnunet/libexec/"); if ((size < 4) || (lnk[size - 4] != '/')) { /* not installed in "/bin/" -- binary path probably useless */ return NULL; } lnk[size] = '\0'; return GNUNET_strdup (lnk); } #endif #if WINDOWS static HINSTANCE dll_instance; /** * GNUNET_util_cl_init() in common_logging.c is preferred. * This function is only for thread-local storage (not used in GNUnet) * and hInstance saving. */ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: dll_instance = hinstDLL; break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; } /** * Try to determine path with win32-specific function * * @return NULL on error */ static char * get_path_from_module_filename () { size_t pathlen = 512; DWORD real_pathlen; wchar_t *idx; wchar_t *modulepath = NULL; char *upath; uint8_t *u8_string; size_t u8_string_length; /* This braindead function won't tell us how much space it needs, so * we start at 1024 and double the space up if it doesn't fit, until * it fits, or we exceed the threshold. */ do { pathlen = pathlen * 2; modulepath = GNUNET_realloc (modulepath, pathlen * sizeof (wchar_t)); SetLastError (0); real_pathlen = GetModuleFileNameW (dll_instance, modulepath, pathlen * sizeof (wchar_t)); } while (real_pathlen >= pathlen && pathlen < 16*1024); if (real_pathlen >= pathlen) GNUNET_abort (); /* To be safe */ modulepath[real_pathlen] = '\0'; idx = modulepath + real_pathlen; while ((idx > modulepath) && (*idx != L'\\') && (*idx != L'/')) idx--; *idx = L'\0'; /* Now modulepath holds full path to the directory where libgnunetutil is. * This directory should look like /bin or . */ if (wcschr (modulepath, L'/') || wcschr (modulepath, L'\\')) { /* At least one directory component (i.e. we're not in a root directory) */ wchar_t *dirname = idx; while ((dirname > modulepath) && (*dirname != L'\\') && (*dirname != L'/')) dirname--; *dirname = L'\0'; if (dirname > modulepath) { dirname++; /* Now modulepath holds full path to the parent directory of the directory * where libgnunetutil is. * dirname holds the name of the directory where libgnunetutil is. */ if (wcsicmp (dirname, L"bin") == 0) { /* pass */ } else { /* Roll back our changes to modulepath */ dirname--; *dirname = L'/'; } } } /* modulepath is GNUNET_PREFIX */ u8_string = u16_to_u8 (modulepath, wcslen (modulepath), NULL, &u8_string_length); if (NULL == u8_string) GNUNET_abort (); upath = GNUNET_malloc (u8_string_length + 1); memcpy (upath, u8_string, u8_string_length); upath[u8_string_length] = '\0'; free (u8_string); GNUNET_free (modulepath); return upath; } #endif #if DARWIN /** * Signature of the '_NSGetExecutablePath" function. * * @param buf where to write the path * @param number of bytes available in 'buf' * @return 0 on success, otherwise desired number of bytes is stored in 'bufsize' */ typedef int (*MyNSGetExecutablePathProto) (char *buf, size_t * bufsize); /** * Try to obtain the path of our executable using '_NSGetExecutablePath'. * * @return NULL on error */ static char * get_path_from_NSGetExecutablePath () { static char zero = '\0'; char *path; size_t len; MyNSGetExecutablePathProto func; path = NULL; if (NULL == (func = (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, "_NSGetExecutablePath"))) return NULL; path = &zero; len = 0; /* get the path len, including the trailing \0 */ (void) func (path, &len); if (0 == len) return NULL; path = GNUNET_malloc (len); if (0 != func (path, &len)) { GNUNET_free (path); return NULL; } len = strlen (path); while ((path[len] != '/') && (len > 0)) len--; path[len] = '\0'; return path; } /** * Try to obtain the path of our executable using '_dyld_image' API. * * @return NULL on error */ static char * get_path_from_dyld_image () { const char *path; char *p; char *s; unsigned int i; int c; c = _dyld_image_count (); for (i = 0; i < c; i++) { if (((const void *) _dyld_get_image_header (i)) != (const void *)&_mh_dylib_header) continue; path = _dyld_get_image_name (i); if ( (NULL == path) || (0 == strlen (path)) ) continue; p = GNUNET_strdup (path); s = p + strlen (p); while ((s > p) && ('/' != *s)) s--; s++; *s = '\0'; return p; } return NULL; } #endif /** * Return the actual path to a file found in the current * PATH environment variable. * * @param binary the name of the file to find * @return path to binary, NULL if not found */ static char * get_path_from_PATH (const char *binary) { char *path; char *pos; char *end; char *buf; const char *p; if (NULL == (p = getenv ("PATH"))) return NULL; #if WINDOWS /* On W32 look in CWD first. */ GNUNET_asprintf (&path, ".%c%s", PATH_SEPARATOR, p); #else path = GNUNET_strdup (p); /* because we write on it */ #endif buf = GNUNET_malloc (strlen (path) + strlen (binary) + 1 + 1); pos = path; while (NULL != (end = strchr (pos, PATH_SEPARATOR))) { *end = '\0'; sprintf (buf, "%s/%s", pos, binary); if (GNUNET_DISK_file_test (buf) == GNUNET_YES) { pos = GNUNET_strdup (pos); GNUNET_free (buf); GNUNET_free (path); return pos; } pos = end + 1; } sprintf (buf, "%s/%s", pos, binary); if (GNUNET_YES == GNUNET_DISK_file_test (buf)) { pos = GNUNET_strdup (pos); GNUNET_free (buf); GNUNET_free (path); return pos; } GNUNET_free (buf); GNUNET_free (path); return NULL; } /** * Try to obtain the installation path using the "GNUNET_PREFIX" environment * variable. * * @return NULL on error (environment variable not set) */ static char * get_path_from_GNUNET_PREFIX () { const char *p; if (NULL != (p = getenv ("GNUNET_PREFIX"))) return GNUNET_strdup (p); return NULL; } /** * @brief get the path to GNUnet bin/ or lib/, prefering the lib/ path * @author Milan * * @return a pointer to the executable path, or NULL on error */ static char * os_get_gnunet_path () { char *ret; if (NULL != (ret = get_path_from_GNUNET_PREFIX ())) return ret; #if LINUX if (NULL != (ret = get_path_from_proc_maps ())) return ret; /* try path *first*, before /proc/exe, as /proc/exe can be wrong */ if (NULL != (ret = get_path_from_PATH ("gnunet-arm"))) return ret; if (NULL != (ret = get_path_from_proc_exe ())) return ret; #endif #if WINDOWS if (NULL != (ret = get_path_from_module_filename ())) return ret; #endif #if DARWIN if (NULL != (ret = get_path_from_dyld_image ())) return ret; if (NULL != (ret = get_path_from_NSGetExecutablePath ())) return ret; #endif if (NULL != (ret = get_path_from_PATH ("gnunet-arm"))) return ret; /* other attempts here */ LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not determine installation path for %s. Set `%s' environment variable.\n"), "GNUnet", "GNUNET_PREFIX"); return NULL; } /** * @brief get the path to current app's bin/ * @author Milan * * @return a pointer to the executable path, or NULL on error */ static char * os_get_exec_path () { char *ret = NULL; #if LINUX if (NULL != (ret = get_path_from_proc_exe ())) return ret; #endif #if WINDOWS if (NULL != (ret = get_path_from_module_filename ())) return ret; #endif #if DARWIN if (NULL != (ret = get_path_from_NSGetExecutablePath ())) return ret; #endif /* other attempts here */ return ret; } /** * @brief get the path to a specific GNUnet installation directory or, * with #GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation directory * @author Milan * @return a pointer to the dir path (to be freed by the caller) */ char * GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) { size_t n; const char *dirname; char *execpath = NULL; char *tmp; char *multiarch; char *libdir; int isbasedir; /* if wanted, try to get the current app's bin/ */ if (dirkind == GNUNET_OS_IPK_SELF_PREFIX) execpath = os_get_exec_path (); /* try to get GNUnet's bin/ or lib/, or if previous was unsuccessful some * guess for the current app */ if (NULL == execpath) execpath = os_get_gnunet_path (); if (NULL == execpath) return NULL; n = strlen (execpath); if (0 == n) { /* should never happen, but better safe than sorry */ GNUNET_free (execpath); return NULL; } /* remove filename itself */ while ((n > 1) && (DIR_SEPARATOR == execpath[n - 1])) execpath[--n] = '\0'; isbasedir = 1; if ((n > 6) && ((0 == strcasecmp (&execpath[n - 6], "/lib32")) || (0 == strcasecmp (&execpath[n - 6], "/lib64")))) { if ( (GNUNET_OS_IPK_LIBDIR != dirkind) && (GNUNET_OS_IPK_LIBEXECDIR != dirkind) ) { /* strip '/lib32' or '/lib64' */ execpath[n - 6] = '\0'; n -= 6; } else isbasedir = 0; } else if ((n > 4) && ((0 == strcasecmp (&execpath[n - 4], "/bin")) || (0 == strcasecmp (&execpath[n - 4], "/lib")))) { /* strip '/bin' or '/lib' */ execpath[n - 4] = '\0'; n -= 4; } multiarch = NULL; if (NULL != (libdir = strstr (execpath, "/lib/"))) { /* test for multi-arch path of the form "PREFIX/lib/MULTIARCH/"; here we need to re-add 'multiarch' to lib and libexec paths later! */ multiarch = &libdir[5]; if (NULL == strchr (multiarch, '/')) libdir[0] = '\0'; /* Debian multiarch format, cut of from 'execpath' but preserve in multicarch */ else multiarch = NULL; /* maybe not, multiarch still has a '/', which is not OK */ } /* in case this was a directory named foo-bin, remove "foo-" */ while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR)) execpath[--n] = '\0'; switch (dirkind) { case GNUNET_OS_IPK_PREFIX: case GNUNET_OS_IPK_SELF_PREFIX: dirname = DIR_SEPARATOR_STR; break; case GNUNET_OS_IPK_BINDIR: dirname = DIR_SEPARATOR_STR "bin" DIR_SEPARATOR_STR; break; case GNUNET_OS_IPK_LIBDIR: if (isbasedir) { GNUNET_asprintf (&tmp, "%s%s%s%s%s", execpath, DIR_SEPARATOR_STR "lib", (NULL != multiarch) ? DIR_SEPARATOR_STR : "", (NULL != multiarch) ? multiarch : "", DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR); if (GNUNET_YES == GNUNET_DISK_directory_test (tmp, GNUNET_YES)) { GNUNET_free (execpath); return tmp; } GNUNET_free (tmp); tmp = NULL; if (4 == sizeof (void *)) { dirname = DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; GNUNET_asprintf (&tmp, "%s%s", execpath, dirname); } if (8 == sizeof (void *)) { dirname = DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; GNUNET_asprintf (&tmp, "%s%s", execpath, dirname); } if ( (NULL != tmp) && (GNUNET_YES == GNUNET_DISK_directory_test (tmp, GNUNET_YES)) ) { GNUNET_free (execpath); return tmp; } GNUNET_free (tmp); } dirname = DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; break; case GNUNET_OS_IPK_DATADIR: dirname = DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; break; case GNUNET_OS_IPK_LOCALEDIR: dirname = DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "locale" DIR_SEPARATOR_STR; break; case GNUNET_OS_IPK_ICONDIR: dirname = DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "icons" DIR_SEPARATOR_STR; break; case GNUNET_OS_IPK_DOCDIR: dirname = DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "doc" DIR_SEPARATOR_STR \ "gnunet" DIR_SEPARATOR_STR; break; case GNUNET_OS_IPK_LIBEXECDIR: if (isbasedir) { dirname = DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR "libexec" DIR_SEPARATOR_STR; GNUNET_asprintf (&tmp, "%s%s%s%s", execpath, DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR, (NULL != multiarch) ? multiarch : "", dirname); if (GNUNET_YES == GNUNET_DISK_directory_test (tmp, GNUNET_YES)) { GNUNET_free (execpath); return tmp; } GNUNET_free (tmp); tmp = NULL; if (4 == sizeof (void *)) { dirname = DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ "libexec" DIR_SEPARATOR_STR; GNUNET_asprintf (&tmp, "%s%s", execpath, dirname); } if (8 == sizeof (void *)) { dirname = DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ "libexec" DIR_SEPARATOR_STR; GNUNET_asprintf (&tmp, "%s%s", execpath, dirname); } if ( (NULL != tmp) && (GNUNET_YES == GNUNET_DISK_directory_test (tmp, GNUNET_YES)) ) { GNUNET_free (execpath); return tmp; } GNUNET_free (tmp); } dirname = DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ "libexec" DIR_SEPARATOR_STR; break; default: GNUNET_free (execpath); return NULL; } GNUNET_asprintf (&tmp, "%s%s", execpath, dirname); GNUNET_free (execpath); return tmp; } /** * Given the name of a gnunet-helper, gnunet-service or gnunet-daemon * binary, try to prefix it with the libexec/-directory to get the * full path. * * @param progname name of the binary * @return full path to the binary, if possible, otherwise copy of 'progname' */ char * GNUNET_OS_get_libexec_binary_path (const char *progname) { static char *cache; char *libexecdir; char *binary; if ( (DIR_SEPARATOR == progname[0]) || (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (progname, GNUNET_NO, NULL, NULL)) ) return GNUNET_strdup (progname); if (NULL != cache) libexecdir = cache; else libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR); if (NULL == libexecdir) return GNUNET_strdup (progname); GNUNET_asprintf (&binary, "%s%s", libexecdir, progname); cache = libexecdir; return binary; } /** * Check whether an executable exists and possibly * if the suid bit is set on the file. * Attempts to find the file using the current * PATH environment variable as a search path. * * @param binary the name of the file to check. * W32: must not have an .exe suffix. * @param check_suid input true if the binary should be checked for SUID (*nix) * W32: checks if the program has sufficient privileges by executing this * binary with the -d flag. -d omits a programs main loop and only * executes all privileged operations in an binary. * @param params parameters used for w32 privilege checking (can be NULL for != w32 ) * @return #GNUNET_YES if the file is SUID (*nix) or can be executed with current privileges (W32), * #GNUNET_NO if not SUID (but binary exists), * #GNUNET_SYSERR on error (no such binary or not executable) */ int GNUNET_OS_check_helper_binary (const char *binary, int check_suid, const char *params) { struct stat statbuf; char *p; char *pf; #ifdef MINGW char *binaryexe; GNUNET_asprintf (&binaryexe, "%s.exe", binary); if ( (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (binaryexe, GNUNET_NO, NULL, NULL)) || (0 == strncmp (binary, "./", 2)) ) p = GNUNET_strdup (binaryexe); else { p = get_path_from_PATH (binaryexe); if (NULL != p) { GNUNET_asprintf (&pf, "%s/%s", p, binaryexe); GNUNET_free (p); p = pf; } } GNUNET_free (binaryexe); #else if ( (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (binary, GNUNET_NO, NULL, NULL)) || (0 == strncmp (binary, "./", 2)) ) p = GNUNET_strdup (binary); else { p = get_path_from_PATH (binary); if (NULL != p) { GNUNET_asprintf (&pf, "%s/%s", p, binary); GNUNET_free (p); p = pf; } } #endif if (NULL == p) { LOG (GNUNET_ERROR_TYPE_INFO, _("Could not find binary `%s' in PATH!\n"), binary); return GNUNET_SYSERR; } if (0 != ACCESS (p, X_OK)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", p); GNUNET_free (p); return GNUNET_SYSERR; } #ifndef MINGW if (0 == getuid ()) { /* as we run as root, we don't insist on SUID */ GNUNET_free (p); return GNUNET_OK; } #endif if (0 != STAT (p, &statbuf)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", p); GNUNET_free (p); return GNUNET_SYSERR; } if (check_suid){ #ifndef MINGW if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid)) { GNUNET_free (p); return GNUNET_YES; } /* binary exists, but not SUID */ #else STARTUPINFO start; char parameters[512]; PROCESS_INFORMATION proc; DWORD exit_value; GNUNET_snprintf (parameters, sizeof (parameters), "-d %s", params); memset (&start, 0, sizeof (start)); start.cb = sizeof (start); memset (&proc, 0, sizeof (proc)); // Start the child process. if ( ! (CreateProcess( p, // current windows (2k3 and up can handle / instead of \ in paths)) parameters, // execute dryrun/priviliege checking mode NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE CREATE_DEFAULT_ERROR_MODE, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &start, // Pointer to STARTUPINFO structure &proc ) // Pointer to PROCESS_INFORMATION structure )) { LOG (GNUNET_ERROR_TYPE_ERROR, _("CreateProcess failed for binary %s (%d).\n"), p, GetLastError()); return GNUNET_SYSERR; } // Wait until child process exits. WaitForSingleObject( proc.hProcess, INFINITE ); if ( ! GetExitCodeProcess (proc.hProcess, &exit_value)){ LOG (GNUNET_ERROR_TYPE_ERROR, _("GetExitCodeProcess failed for binary %s (%d).\n"), p, GetLastError() ); return GNUNET_SYSERR; } // Close process and thread handles. CloseHandle( proc.hProcess ); CloseHandle( proc.hThread ); if (!exit_value) return GNUNET_YES; #endif } GNUNET_free (p); return GNUNET_NO; } /* end of os_installation.c */ gnunet-0.10.1/src/util/test_common_allocation.c0000644000175000017500000000531712225777501016474 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2005, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_common_allocation.c * @brief testcase for common_allocation.c */ #include "platform.h" #include "gnunet_util_lib.h" static int check () { #define MAX_TESTVAL 1024 char *ptrs[MAX_TESTVAL]; int i; int j; int k; unsigned int ui; /* GNUNET_malloc/GNUNET_free test */ k = 352; /* random start value */ for (i = 1; i < MAX_TESTVAL; i++) { ptrs[i] = GNUNET_malloc (i); for (j = 0; j < i; j++) ptrs[i][j] = k++; } for (i = MAX_TESTVAL - 1; i >= 1; i--) { for (j = i - 1; j >= 0; j--) if (ptrs[i][j] != (char) --k) return 1; GNUNET_free (ptrs[i]); } /* GNUNET_free_non_null test */ GNUNET_free_non_null (NULL); GNUNET_free_non_null (GNUNET_malloc (4)); /* GNUNET_strdup tests */ ptrs[0] = GNUNET_strdup ("bar"); if (0 != strcmp (ptrs[0], "bar")) return 3; /* now realloc */ ptrs[0] = GNUNET_realloc (ptrs[0], 12); strcpy (ptrs[0], "Hello World"); GNUNET_free (ptrs[0]); GNUNET_asprintf (&ptrs[0], "%s %s", "Hello", "World"); GNUNET_assert (strlen (ptrs[0]) == 11); GNUNET_free (ptrs[0]); /* GNUNET_array_grow tests */ ptrs[0] = NULL; ui = 0; GNUNET_array_grow (ptrs[0], ui, 42); if (ui != 42) return 4; GNUNET_array_grow (ptrs[0], ui, 22); if (ui != 22) return 5; for (j = 0; j < 22; j++) ptrs[0][j] = j; GNUNET_array_grow (ptrs[0], ui, 32); for (j = 0; j < 22; j++) if (ptrs[0][j] != j) return 6; for (j = 22; j < 32; j++) if (ptrs[0][j] != 0) return 7; GNUNET_array_grow (ptrs[0], ui, 0); if (i != 0) return 8; if (ptrs[0] != NULL) return 9; return 0; } int main (int argc, char *argv[]) { int ret; GNUNET_log_setup ("test-common-allocation", "WARNING", NULL); ret = check (); if (ret != 0) FPRINTF (stderr, "ERROR %d.\n", ret); return ret; } /* end of test_common_allocation.c */ gnunet-0.10.1/src/util/container_heap.c0000644000175000017500000003210512255010512014673 00000000000000/* This file is part of GNUnet. (C) 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/container_heap.c * @brief Implementation of a heap * @author Nathan Evans * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define EXTRA_CHECKS 0 /** * Node in the heap. */ struct GNUNET_CONTAINER_HeapNode { /** * Heap this node belongs to. */ struct GNUNET_CONTAINER_Heap *heap; /** * Parent node. */ struct GNUNET_CONTAINER_HeapNode *parent; /** * Left child. */ struct GNUNET_CONTAINER_HeapNode *left_child; /** * Right child. */ struct GNUNET_CONTAINER_HeapNode *right_child; /** * Our element. */ void *element; /** * Cost for this element. */ GNUNET_CONTAINER_HeapCostType cost; /** * Number of elements below this node in the heap * (excluding this node itself). */ unsigned int tree_size; }; /** * Handle to a node in a heap. */ struct GNUNET_CONTAINER_Heap { /** * Root of the heap. */ struct GNUNET_CONTAINER_HeapNode *root; /** * Current position of our random walk. */ struct GNUNET_CONTAINER_HeapNode *walk_pos; /** * Number of elements in the heap. */ unsigned int size; /** * How is the heap sorted? */ enum GNUNET_CONTAINER_HeapOrder order; }; #if EXTRA_CHECKS /** * Check if internal invariants hold for the given node. * * @param node subtree to check */ static void check (const struct GNUNET_CONTAINER_HeapNode *node) { if (NULL == node) return; GNUNET_assert (node->tree_size == ((node->left_child == NULL) ? 0 : 1 + node->left_child->tree_size) + ((node->right_child == NULL) ? 0 : 1 + node->right_child->tree_size)); check (node->left_child); check (node->right_child); } #define CHECK(n) check(n) #else #define CHECK(n) do {} while (0) #endif /** * Create a new heap. * * @param order how should the heap be sorted? * @return handle to the heap */ struct GNUNET_CONTAINER_Heap * GNUNET_CONTAINER_heap_create (enum GNUNET_CONTAINER_HeapOrder order) { struct GNUNET_CONTAINER_Heap *heap; heap = GNUNET_new (struct GNUNET_CONTAINER_Heap); heap->order = order; return heap; } /** * Destroys the heap. Only call on a heap that * is already empty. * * @param heap heap to destroy */ void GNUNET_CONTAINER_heap_destroy (struct GNUNET_CONTAINER_Heap *heap) { GNUNET_break (heap->size == 0); GNUNET_free (heap); } /** * Get element stored at root of heap. * * @param heap heap to inspect * @return NULL if heap is empty */ void * GNUNET_CONTAINER_heap_peek (const struct GNUNET_CONTAINER_Heap *heap) { if (heap->root == NULL) return NULL; return heap->root->element; } /** * Get the current size of the heap * * @param heap the heap to get the size of * @return number of elements stored */ unsigned int GNUNET_CONTAINER_heap_get_size (const struct GNUNET_CONTAINER_Heap *heap) { return heap->size; } /** * Get the current cost of the node * * @param node the node to get the cost of * @return cost of the node */ GNUNET_CONTAINER_HeapCostType GNUNET_CONTAINER_heap_node_get_cost (const struct GNUNET_CONTAINER_HeapNode *node) { return node->cost; } /** * Iterate over the children of the given node. * * @param heap argument to give to iterator * @param node node to iterate over * @param iterator function to call on each node * @param iterator_cls closure for iterator * @return GNUNET_YES to continue to iterate */ static int node_iterator (const struct GNUNET_CONTAINER_Heap *heap, struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapIterator iterator, void *iterator_cls) { if (node == NULL) return GNUNET_YES; if (GNUNET_YES != node_iterator (heap, node->left_child, iterator, iterator_cls)) return GNUNET_NO; if (GNUNET_YES != node_iterator (heap, node->right_child, iterator, iterator_cls)) return GNUNET_NO; return iterator (iterator_cls, node, node->element, node->cost); } /** * Iterate over all entries in the heap. * * @param heap the heap * @param iterator function to call on each entry * @param iterator_cls closure for iterator */ void GNUNET_CONTAINER_heap_iterate (const struct GNUNET_CONTAINER_Heap *heap, GNUNET_CONTAINER_HeapIterator iterator, void *iterator_cls) { (void) node_iterator (heap, heap->root, iterator, iterator_cls); } /** * Perform a random walk of the tree. The walk is biased * towards elements closer to the root of the tree (since * each walk starts at the root and ends at a random leaf). * The heap internally tracks the current position of the * walk. * * @param heap heap to walk * @return data stored at the next random node in the walk; * NULL if the tree is empty. */ void * GNUNET_CONTAINER_heap_walk_get_next (struct GNUNET_CONTAINER_Heap *heap) { struct GNUNET_CONTAINER_HeapNode *pos; void *element; if (heap->root == NULL) return NULL; pos = heap->walk_pos; if (pos == NULL) pos = heap->root; element = pos->element; heap->walk_pos = (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2)) ? pos->right_child : pos->left_child; return element; } /** * Insert the given node 'node' into the subtree starting * at 'pos' (while keeping the tree somewhat balanced). * * @param heap heap to modify * @param pos existing tree * @param node node to insert (which may be a subtree itself) */ static void insert_node (struct GNUNET_CONTAINER_Heap *heap, struct GNUNET_CONTAINER_HeapNode *pos, struct GNUNET_CONTAINER_HeapNode *node) { struct GNUNET_CONTAINER_HeapNode *parent; GNUNET_assert (node->parent == NULL); while ((heap->order == GNUNET_CONTAINER_HEAP_ORDER_MAX) ? (pos->cost >= node->cost) : (pos->cost <= node->cost)) { /* node is descendent of pos */ pos->tree_size += (1 + node->tree_size); if (pos->left_child == NULL) { pos->left_child = node; node->parent = pos; return; } if (pos->right_child == NULL) { pos->right_child = node; node->parent = pos; return; } /* keep it balanced by descending into smaller subtree */ if (pos->left_child->tree_size < pos->right_child->tree_size) pos = pos->left_child; else pos = pos->right_child; } /* make 'node' parent of 'pos' */ parent = pos->parent; pos->parent = NULL; node->parent = parent; if (NULL == parent) { heap->root = node; } else { if (parent->left_child == pos) parent->left_child = node; else parent->right_child = node; } /* insert 'pos' below 'node' */ insert_node (heap, node, pos); CHECK (pos); } /** * Inserts a new element into the heap. * * @param heap heap to modify * @param element element to insert * @param cost cost for the element * @return node for the new element */ struct GNUNET_CONTAINER_HeapNode * GNUNET_CONTAINER_heap_insert (struct GNUNET_CONTAINER_Heap *heap, void *element, GNUNET_CONTAINER_HeapCostType cost) { struct GNUNET_CONTAINER_HeapNode *node; node = GNUNET_new (struct GNUNET_CONTAINER_HeapNode); node->heap = heap; node->element = element; node->cost = cost; heap->size++; if (NULL == heap->root) heap->root = node; else insert_node (heap, heap->root, node); GNUNET_assert (heap->size == heap->root->tree_size + 1); CHECK (heap->root); return node; } /** * Remove root of the heap. * * @param heap heap to modify * @return element data stored at the root node, NULL if heap is empty */ void * GNUNET_CONTAINER_heap_remove_root (struct GNUNET_CONTAINER_Heap *heap) { void *ret; struct GNUNET_CONTAINER_HeapNode *root; if (NULL == (root = heap->root)) return NULL; heap->size--; ret = root->element; if (root->left_child == NULL) { heap->root = root->right_child; if (root->right_child != NULL) root->right_child->parent = NULL; } else if (root->right_child == NULL) { heap->root = root->left_child; root->left_child->parent = NULL; } else { root->left_child->parent = NULL; root->right_child->parent = NULL; heap->root = root->left_child; insert_node (heap, heap->root, root->right_child); } if (heap->walk_pos == root) heap->walk_pos = heap->root; GNUNET_free (root); #if EXTRA_CHECKS GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) || (heap->size == heap->root->tree_size + 1)); CHECK (heap->root); #endif return ret; } /** * Remove the given node 'node' from the tree and update * the 'tree_size' fields accordingly. Preserves the * children of 'node' and does NOT change the overall * 'size' field of the tree. */ static void remove_node (struct GNUNET_CONTAINER_HeapNode *node) { struct GNUNET_CONTAINER_HeapNode *ancestor; struct GNUNET_CONTAINER_Heap *heap = node->heap; /* update 'size' of the ancestors */ ancestor = node; while (NULL != (ancestor = ancestor->parent)) ancestor->tree_size--; /* update 'size' of node itself */ if (node->left_child != NULL) node->tree_size -= (1 + node->left_child->tree_size); if (node->right_child != NULL) node->tree_size -= (1 + node->right_child->tree_size); /* unlink 'node' itself and insert children in its place */ if (node->parent == NULL) { if (node->left_child != NULL) { heap->root = node->left_child; node->left_child->parent = NULL; if (node->right_child != NULL) { node->right_child->parent = NULL; insert_node (heap, heap->root, node->right_child); } } else { heap->root = node->right_child; if (node->right_child != NULL) node->right_child->parent = NULL; } } else { if (node->parent->left_child == node) node->parent->left_child = NULL; else node->parent->right_child = NULL; if (node->left_child != NULL) { node->left_child->parent = NULL; node->parent->tree_size -= (1 + node->left_child->tree_size); insert_node (heap, node->parent, node->left_child); } if (node->right_child != NULL) { node->right_child->parent = NULL; node->parent->tree_size -= (1 + node->right_child->tree_size); insert_node (heap, node->parent, node->right_child); } } node->parent = NULL; node->left_child = NULL; node->right_child = NULL; GNUNET_assert (node->tree_size == 0); CHECK (heap->root); } /** * Removes a node from the heap. * * @param node node to remove * @return element data stored at the node */ void * GNUNET_CONTAINER_heap_remove_node (struct GNUNET_CONTAINER_HeapNode *node) { void *ret; struct GNUNET_CONTAINER_Heap *heap; heap = node->heap; CHECK (heap->root); if (heap->walk_pos == node) (void) GNUNET_CONTAINER_heap_walk_get_next (heap); remove_node (node); heap->size--; ret = node->element; if (heap->walk_pos == node) heap->walk_pos = NULL; GNUNET_free (node); #if EXTRA_CHECKS CHECK (heap->root); GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) || (heap->size == heap->root->tree_size + 1)); #endif return ret; } /** * Updates the cost of any node in the tree * * @param heap heap to modify * @param node node for which the cost is to be changed * @param new_cost new cost for the node */ void GNUNET_CONTAINER_heap_update_cost (struct GNUNET_CONTAINER_Heap *heap, struct GNUNET_CONTAINER_HeapNode *node, GNUNET_CONTAINER_HeapCostType new_cost) { #if EXTRA_CHECKS GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) || (heap->size == heap->root->tree_size + 1)); CHECK (heap->root); #endif remove_node (node); #if EXTRA_CHECKS CHECK (heap->root); GNUNET_assert (((heap->size == 1) && (heap->root == NULL)) || (heap->size == heap->root->tree_size + 2)); #endif node->cost = new_cost; if (heap->root == NULL) heap->root = node; else insert_node (heap, heap->root, node); #if EXTRA_CHECKS CHECK (heap->root); GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) || (heap->size == heap->root->tree_size + 1)); #endif } /* end of heap.c */ gnunet-0.10.1/src/util/speedup.c0000644000175000017500000000654612307557412013410 00000000000000/* This file is part of GNUnet. (C) 2011-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/speedup.c * @author Matthias Wachs * @brief functions to speedup peer execution by manipulation system time */ #include "platform.h" #include "gnunet_util_lib.h" #include "speedup.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) static struct GNUNET_TIME_Relative interval; static struct GNUNET_TIME_Relative delta; static GNUNET_SCHEDULER_TaskIdentifier speedup_task; static void do_speedup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static long long current_offset; speedup_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; current_offset += delta.rel_value_us; GNUNET_TIME_set_offset (current_offset); LOG (GNUNET_ERROR_TYPE_DEBUG, "Speeding up execution time by %s\n", GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_NO)); speedup_task = GNUNET_SCHEDULER_add_delayed (interval, &do_speedup, NULL); } /** * Start task that may speed up our system clock artificially * * @param cfg configuration to use * @return #GNUNET_OK on success, #GNUNET_SYSERR if the speedup was not configured */ int GNUNET_SPEEDUP_start_ (const struct GNUNET_CONFIGURATION_Handle *cfg) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SPEEDUP_INTERVAL", &interval)) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SPEEDUP_DELTA", &delta)) return GNUNET_SYSERR; if ((0 == interval.rel_value_us) || (0 == delta.rel_value_us)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Speed up disabled\n"); return GNUNET_OK; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Speed up execution by %s\n", GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_NO)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Speed up executed every %s\n", GNUNET_STRINGS_relative_time_to_string (interval, GNUNET_NO)); speedup_task = GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, &do_speedup, NULL); return GNUNET_OK; } /** * Stop tasks that modify clock behavior. */ void GNUNET_SPEEDUP_stop_ () { if (GNUNET_SCHEDULER_NO_TASK != speedup_task) { GNUNET_SCHEDULER_cancel (speedup_task); speedup_task = GNUNET_SCHEDULER_NO_TASK; } if ( (0 != interval.rel_value_us) && (0 != delta.rel_value_us) ) LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopped execution speed up\n"); } /* end of speedup.c */ gnunet-0.10.1/src/util/gnunet-helper-w32-console.h0000644000175000017500000000342012320530515016550 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author LRN * @file src/util/gnunet-helper-w32-console.h */ #ifndef GNUNET_HELPER_W32_CONSOLE_H #define GNUNET_HELPER_W32_CONSOLE_H #include "platform.h" #include "gnunet_crypto_lib.h" #include "gnunet_common.h" /** * Input event from the console */ #define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT 60000 /** * Chars from the console */ #define GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS 60001 GNUNET_NETWORK_STRUCT_BEGIN /** * This is just a dump of the INPUT_RECORD structure. */ struct GNUNET_W32_CONSOLE_input { /** * Type: GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_INPUT */ struct GNUNET_MessageHeader header; INPUT_RECORD input_record GNUNET_PACKED; }; /** * A header, followed by UTF8-encoded, 0-terminated string */ struct GNUNET_W32_CONSOLE_chars { /** * Type: GNUNET_MESSAGE_TYPE_W32_CONSOLE_HELPER_CHARS */ struct GNUNET_MessageHeader header; /* followed by a string */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/util/perf_malloc.c0000644000175000017500000000326112225777501014217 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file util/perf_malloc.c * @brief measure performance of allocation functions */ #include "platform.h" #include "gnunet_util_lib.h" #include static uint64_t perfMalloc () { size_t i; uint64_t ret; ret = 0; for (i=1;i<1024 * 1024;i+=1024) { ret += i; GNUNET_free (GNUNET_malloc (i)); } return ret; } int main (int argc, char *argv[]) { struct GNUNET_TIME_Absolute start; uint64_t kb; start = GNUNET_TIME_absolute_get (); kb = perfMalloc (); printf ("Malloc perf took %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GAUGER ("UTIL", "Allocation", kb / 1024 / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL), "kb/ms"); return 0; } /* end of perf_malloc.c */ gnunet-0.10.1/src/util/crypto_symmetric.c0000644000175000017500000002012612236175457015353 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/crypto_symmetric.c * @brief Symmetric encryption services; combined cipher AES+TWOFISH (256-bit each) * @author Christian Grothoff * @author Ioana Patrascu */ #include "platform.h" #include "gnunet_util_lib.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Create a new SessionKey (for symmetric encryption). * * @param key session key to initialize */ void GNUNET_CRYPTO_symmetric_create_session_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key) { gcry_randomize (key->aes_key, GNUNET_CRYPTO_AES_KEY_LENGTH, GCRY_STRONG_RANDOM); gcry_randomize (key->twofish_key, GNUNET_CRYPTO_AES_KEY_LENGTH, GCRY_STRONG_RANDOM); } /** * Initialize AES cipher. * * @param handle handle to initialize * @param sessionkey session key to use * @param iv initialization vector to use * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int setup_cipher_aes (gcry_cipher_hd_t *handle, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv) { int rc; GNUNET_assert (0 == gcry_cipher_open (handle, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CFB, 0)); rc = gcry_cipher_setkey (*handle, sessionkey->aes_key, sizeof (sessionkey->aes_key)); GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY)); rc = gcry_cipher_setiv (*handle, iv->aes_iv, sizeof (iv->aes_iv)); GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY)); return GNUNET_OK; } /** * Initialize TWOFISH cipher. * * @param handle handle to initialize * @param sessionkey session key to use * @param iv initialization vector to use * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int setup_cipher_twofish (gcry_cipher_hd_t *handle, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv) { int rc; GNUNET_assert (0 == gcry_cipher_open (handle, GCRY_CIPHER_TWOFISH, GCRY_CIPHER_MODE_CFB, 0)); rc = gcry_cipher_setkey (*handle, sessionkey->twofish_key, sizeof (sessionkey->twofish_key)); GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY)); rc = gcry_cipher_setiv (*handle, iv->twofish_iv, sizeof (iv->twofish_iv)); GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY)); return GNUNET_OK; } /** * Encrypt a block with a symmetric session key. * * @param block the block to encrypt * @param size the size of the @a block * @param sessionkey the key used to encrypt * @param iv the initialization vector to use, use INITVALUE for streams * @param result the output parameter in which to store the encrypted result * can be the same or overlap with @c block * @returns the size of the encrypted block, -1 for errors. * Due to the use of CFB and therefore an effective stream cipher, * this size should be the same as @c len. */ ssize_t GNUNET_CRYPTO_symmetric_encrypt (const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result) { gcry_cipher_hd_t handle; char tmp[size]; if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv)) return -1; GNUNET_assert (0 == gcry_cipher_encrypt (handle, tmp, size, block, size)); gcry_cipher_close (handle); if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv)) return -1; GNUNET_assert (0 == gcry_cipher_encrypt (handle, result, size, tmp, size)); gcry_cipher_close (handle); memset (tmp, 0, sizeof (tmp)); return size; } /** * Decrypt a given block with the session key. * * @param block the data to decrypt, encoded as returned by encrypt * @param size the size of the @a block to decrypt * @param sessionkey the key used to decrypt * @param iv the initialization vector to use, use INITVALUE for streams * @param result address to store the result at * can be the same or overlap with @c block * @return -1 on failure, size of decrypted block on success. * Due to the use of CFB and therefore an effective stream cipher, * this size should be the same as @c size. */ ssize_t GNUNET_CRYPTO_symmetric_decrypt (const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result) { gcry_cipher_hd_t handle; char tmp[size]; if (GNUNET_OK != setup_cipher_twofish (&handle, sessionkey, iv)) return -1; GNUNET_assert (0 == gcry_cipher_decrypt (handle, tmp, size, block, size)); gcry_cipher_close (handle); if (GNUNET_OK != setup_cipher_aes (&handle, sessionkey, iv)) return -1; GNUNET_assert (0 == gcry_cipher_decrypt (handle, result, size, tmp, size)); gcry_cipher_close (handle); memset (tmp, 0, sizeof (tmp)); return size; } /** * @brief Derive an IV * * @param iv initialization vector * @param skey session key * @param salt salt for the derivation * @param salt_len size of the @a salt * @param ... pairs of void * & size_t for context chunks, terminated by NULL */ void GNUNET_CRYPTO_symmetric_derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, const void *salt, size_t salt_len, ...) { va_list argp; va_start (argp, salt_len); GNUNET_CRYPTO_symmetric_derive_iv_v (iv, skey, salt, salt_len, argp); va_end (argp); } /** * @brief Derive an IV * * @param iv initialization vector * @param skey session key * @param salt salt for the derivation * @param salt_len size of the salt * @param argp pairs of void * & size_t for context chunks, terminated by NULL */ void GNUNET_CRYPTO_symmetric_derive_iv_v (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, const void *salt, size_t salt_len, va_list argp) { char aes_salt[salt_len + 4]; char twofish_salt[salt_len + 4]; memcpy (aes_salt, salt, salt_len); memcpy (&aes_salt[salt_len], "AES!", 4); memcpy (twofish_salt, salt, salt_len); memcpy (&twofish_salt[salt_len], "FISH", 4); GNUNET_CRYPTO_kdf_v (iv->aes_iv, sizeof (iv->aes_iv), aes_salt, salt_len + 4, skey->aes_key, sizeof (skey->aes_key), argp); GNUNET_CRYPTO_kdf_v (iv->twofish_iv, sizeof (iv->twofish_iv), twofish_salt, salt_len + 4, skey->twofish_key, sizeof (skey->twofish_key), argp); } /* end of crypto_aes.c */ gnunet-0.10.1/src/util/common_logging.c0000644000175000017500000007434212300637201014724 00000000000000/* This file is part of GNUnet. (C) 2006-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/common_logging.c * @brief error handling API * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include /** * After how many milliseconds do we always print * that "message X was repeated N times"? Use 12h. */ #define BULK_DELAY_THRESHOLD (12 * 60 * 60 * 1000LL * 1000LL) /** * After how many repetitions do we always print * that "message X was repeated N times"? (even if * we have not yet reached the delay threshold) */ #define BULK_REPEAT_THRESHOLD 1000 /** * How many characters do we use for matching of * bulk messages? */ #define BULK_TRACK_SIZE 256 /** * How many characters do we use for matching of * bulk components? */ #define COMP_TRACK_SIZE 32 /** * How many characters can a date/time string * be at most? */ #define DATE_STR_SIZE 64 /** * How many log files to keep? */ #define ROTATION_KEEP 3 #ifndef PATH_MAX /** * Assumed maximum path length (for the log file name). */ #define PATH_MAX 4096 #endif /** * Linked list of active loggers. */ struct CustomLogger { /** * This is a linked list. */ struct CustomLogger *next; /** * Log function. */ GNUNET_Logger logger; /** * Closure for logger. */ void *logger_cls; }; /** * The last "bulk" error message that we have been logging. * Note that this message maybe truncated to the first BULK_TRACK_SIZE * characters, in which case it is NOT 0-terminated! */ static char last_bulk[BULK_TRACK_SIZE]; /** * Type of the last bulk message. */ static enum GNUNET_ErrorType last_bulk_kind; /** * Time of the last bulk error message (0 for none) */ static struct GNUNET_TIME_Absolute last_bulk_time; /** * Number of times that bulk message has been repeated since. */ static unsigned int last_bulk_repeat; /** * Component when the last bulk was logged. Will be 0-terminated. */ static char last_bulk_comp[COMP_TRACK_SIZE + 1]; /** * Running component. */ static char *component; /** * Running component (without pid). */ static char *component_nopid; /** * Format string describing the name of the log file. */ static char *log_file_name; /** * Minimum log level. */ static enum GNUNET_ErrorType min_level; /** * Linked list of our custom loggres. */ static struct CustomLogger *loggers; /** * Number of log calls to ignore. */ int skip_log = 0; /** * File descriptor to use for "stderr", or NULL for none. */ static FILE *GNUNET_stderr; /** * Represents a single logging definition */ struct LogDef { /** * Component name regex */ regex_t component_regex; /** * File name regex */ regex_t file_regex; /** * Function name regex */ regex_t function_regex; /** * Lowest line at which this definition matches. * Defaults to 0. Must be <= to_line. */ int from_line; /** * Highest line at which this definition matches. * Defaults to INT_MAX. Must be >= from_line. */ int to_line; /** * Maximal log level allowed for calls that match this definition. * Calls with higher log level will be disabled. * Must be >= 0 */ int level; /** * 1 if this definition comes from GNUNET_FORCE_LOG, which means that it * overrides any configuration options. 0 otherwise. */ int force; }; /** * Dynamic array of logging definitions */ static struct LogDef *logdefs; /** * Allocated size of logdefs array (in units) */ static int logdefs_size; /** * The number of units used in logdefs array. */ static int logdefs_len; /** * GNUNET_YES if GNUNET_LOG environment variable is already parsed. */ static int gnunet_log_parsed; /** * GNUNET_YES if GNUNET_FORCE_LOG environment variable is already parsed. */ static int gnunet_force_log_parsed; /** * GNUNET_YES if at least one definition with forced == 1 is available. */ static int gnunet_force_log_present; #ifdef WINDOWS /** * Contains the number of performance counts per second. */ static LARGE_INTEGER performance_frequency; #endif /** * Convert a textual description of a loglevel * to the respective GNUNET_GE_KIND. * * @param log loglevel to parse * @return GNUNET_GE_INVALID if log does not parse */ static enum GNUNET_ErrorType get_type (const char *log) { if (NULL == log) return GNUNET_ERROR_TYPE_UNSPECIFIED; if (0 == strcasecmp (log, _("DEBUG"))) return GNUNET_ERROR_TYPE_DEBUG; if (0 == strcasecmp (log, _("INFO"))) return GNUNET_ERROR_TYPE_INFO; if (0 == strcasecmp (log, _("WARNING"))) return GNUNET_ERROR_TYPE_WARNING; if (0 == strcasecmp (log, _("ERROR"))) return GNUNET_ERROR_TYPE_ERROR; if (0 == strcasecmp (log, _("NONE"))) return GNUNET_ERROR_TYPE_NONE; return GNUNET_ERROR_TYPE_INVALID; } #if !defined(GNUNET_CULL_LOGGING) /** * Utility function - reallocates logdefs array to be twice as large. */ static void resize_logdefs () { logdefs_size = (logdefs_size + 1) * 2; logdefs = GNUNET_realloc (logdefs, logdefs_size * sizeof (struct LogDef)); } /** * Abort the process, generate a core dump if possible. */ void GNUNET_abort () { #if WINDOWS DebugBreak (); #endif abort (); } /** * Rotate logs, deleting the oldest log. * * @param new_name new name to add to the rotation */ static void log_rotate (const char *new_name) { static char *rotation[ROTATION_KEEP]; static unsigned int rotation_off; char *discard; if ('\0' == *new_name) return; /* not a real log file name */ discard = rotation[rotation_off % ROTATION_KEEP]; if (NULL != discard) { /* Note: can't log errors during logging (recursion!), so this operation MUST silently fail... */ (void) UNLINK (discard); GNUNET_free (discard); } rotation[rotation_off % ROTATION_KEEP] = GNUNET_strdup (new_name); rotation_off++; } /** * Setup the log file. * * @param tm timestamp for which we should setup logging * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int setup_log_file (const struct tm *tm) { static char last_fn[PATH_MAX + 1]; char fn[PATH_MAX + 1]; int dirwarn; int altlog_fd; int dup_return; FILE *altlog; char *leftsquare; if (NULL == log_file_name) return GNUNET_SYSERR; if (0 == strftime (fn, sizeof (fn), log_file_name, tm)) return GNUNET_SYSERR; leftsquare = strrchr (fn, '['); if ( (NULL != leftsquare) && (']' == leftsquare[1]) ) { char *logfile_copy = GNUNET_strdup (fn); logfile_copy[leftsquare - fn] = '\0'; logfile_copy[leftsquare - fn + 1] = '\0'; snprintf (fn, PATH_MAX, "%s%d%s", logfile_copy, getpid (), &logfile_copy[leftsquare - fn + 2]); GNUNET_free (logfile_copy); } if (0 == strcmp (fn, last_fn)) return GNUNET_OK; /* no change */ log_rotate (last_fn); strcpy (last_fn, fn); dirwarn = (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)); #if WINDOWS altlog_fd = OPEN (fn, O_APPEND | O_BINARY | O_WRONLY | O_CREAT, _S_IREAD | _S_IWRITE); #else altlog_fd = OPEN (fn, O_APPEND | O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); #endif if (-1 != altlog_fd) { if (NULL != GNUNET_stderr) fclose (GNUNET_stderr); dup_return = dup2 (altlog_fd, 2); (void) close (altlog_fd); if (-1 != dup_return) { altlog = fdopen (2, "ab"); if (NULL == altlog) { (void) close (2); altlog_fd = -1; } } else { altlog_fd = -1; } } if (-1 == altlog_fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); if (dirwarn) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to create or access directory for log file `%s'\n"), fn); return GNUNET_SYSERR; } GNUNET_stderr = altlog; return GNUNET_OK; } /** * Utility function - adds a parsed definition to logdefs array. * * @param component see struct LogDef, can't be NULL * @param file see struct LogDef, can't be NULL * @param function see struct LogDef, can't be NULL * @param from_line see struct LogDef * @param to_line see struct LogDef * @param level see struct LogDef, must be >= 0 * @param force see struct LogDef * @return 0 on success, regex-specific error otherwise */ static int add_definition (char *component, char *file, char *function, int from_line, int to_line, int level, int force) { struct LogDef n; int r; if (logdefs_size == logdefs_len) resize_logdefs (); memset (&n, 0, sizeof (n)); if (0 == strlen (component)) component = (char *) ".*"; r = regcomp (&n.component_regex, (const char *) component, REG_NOSUB); if (0 != r) { return r; } if (0 == strlen (file)) file = (char *) ".*"; r = regcomp (&n.file_regex, (const char *) file, REG_NOSUB); if (0 != r) { regfree (&n.component_regex); return r; } if ((NULL == function) || (0 == strlen (function))) function = (char *) ".*"; r = regcomp (&n.function_regex, (const char *) function, REG_NOSUB); if (0 != r) { regfree (&n.component_regex); regfree (&n.file_regex); return r; } n.from_line = from_line; n.to_line = to_line; n.level = level; n.force = force; logdefs[logdefs_len++] = n; return 0; } /** * Decides whether a particular logging call should or should not be allowed * to be made. Used internally by GNUNET_log*() * * @param caller_level loglevel the caller wants to use * @param comp component name the caller uses (NULL means that global * component name is used) * @param file file name containing the logging call, usually __FILE__ * @param function function which tries to make a logging call, * usually __FUNCTION__ * @param line line at which the call is made, usually __LINE__ * @return 0 to disallow the call, 1 to allow it */ int GNUNET_get_log_call_status (int caller_level, const char *comp, const char *file, const char *function, int line) { struct LogDef *ld; int i; int force_only; if (NULL == comp) /* Use default component */ comp = component_nopid; /* We have no definitions to override globally configured log level, * so just use it right away. */ if ( (min_level >= 0) && (GNUNET_NO == gnunet_force_log_present) ) return caller_level <= min_level; /* Only look for forced definitions? */ force_only = min_level >= 0; for (i = 0; i < logdefs_len; i++) { ld = &logdefs[i]; if (( (!force_only) || ld->force) && (line >= ld->from_line && line <= ld->to_line) && (0 == regexec (&ld->component_regex, comp, 0, NULL, 0)) && (0 == regexec (&ld->file_regex, file, 0, NULL, 0)) && (0 == regexec (&ld->function_regex, function, 0, NULL, 0))) { /* We're finished */ return caller_level <= ld->level; } } /* No matches - use global level, if defined */ if (min_level >= 0) return caller_level <= min_level; /* All programs/services previously defaulted to WARNING. * Now WE default to WARNING, and THEY default to NULL. */ return caller_level <= GNUNET_ERROR_TYPE_WARNING; } /** * Utility function - parses a definition * * Definition format: * component;file;function;from_line-to_line;level[/component...] * All entries are mandatory, but may be empty. * Empty entries for component, file and function are treated as * "matches anything". * Empty line entry is treated as "from 0 to INT_MAX" * Line entry with only one line is treated as "this line only" * Entry for level MUST NOT be empty. * Entries for component, file and function that consist of a * single character "*" are treated (at the moment) the same way * empty entries are treated (wildcard matching is not implemented (yet?)). * file entry is matched to the end of __FILE__. That is, it might be * a base name, or a base name with leading directory names (some compilers * define __FILE__ to absolute file path). * * @param constname name of the environment variable from which to get the * string to be parsed * @param force 1 if definitions found in constname are to be forced * @return number of added definitions */ static int parse_definitions (const char *constname, int force) { char *def; const char *tmp; char *comp = NULL; char *file = NULL; char *function = NULL; char *p; char *start; char *t; short state; int level; int from_line, to_line; int counter = 0; int keep_looking = 1; tmp = getenv (constname); if (NULL == tmp) return 0; def = GNUNET_strdup (tmp); from_line = 0; to_line = INT_MAX; for (p = def, state = 0, start = def; keep_looking; p++) { switch (p[0]) { case ';': /* found a field separator */ p[0] = '\0'; switch (state) { case 0: /* within a component name */ comp = start; break; case 1: /* within a file name */ file = start; break; case 2: /* within a function name */ /* after a file name there must be a function name */ function = start; break; case 3: /* within a from-to line range */ if (strlen (start) > 0) { errno = 0; from_line = strtol (start, &t, 10); if ( (0 != errno) || (from_line < 0) ) { GNUNET_free (def); return counter; } if ( (t < p) && ('-' == t[0]) ) { errno = 0; start = t + 1; to_line = strtol (start, &t, 10); if ( (0 != errno) || (to_line < 0) || (t != p) ) { GNUNET_free (def); return counter; } } else /* one number means "match this line only" */ to_line = from_line; } else /* default to 0-max */ { from_line = 0; to_line = INT_MAX; } break; } start = p + 1; state++; break; case '\0': /* found EOL */ keep_looking = 0; /* fall through to '/' */ case '/': /* found a definition separator */ switch (state) { case 4: /* within a log level */ p[0] = '\0'; state = 0; level = get_type ((const char *) start); if ( (GNUNET_ERROR_TYPE_INVALID == level) || (GNUNET_ERROR_TYPE_UNSPECIFIED == level) || (0 != add_definition (comp, file, function, from_line, to_line, level, force)) ) { GNUNET_free (def); return counter; } counter++; start = p + 1; break; default: break; } default: break; } } GNUNET_free (def); return counter; } /** * Utility function - parses GNUNET_LOG and GNUNET_FORCE_LOG. */ static void parse_all_definitions () { if (GNUNET_NO == gnunet_log_parsed) parse_definitions ("GNUNET_LOG", 0); gnunet_log_parsed = GNUNET_YES; if (GNUNET_NO == gnunet_force_log_parsed) gnunet_force_log_present = parse_definitions ("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO; gnunet_force_log_parsed = GNUNET_YES; } #endif /** * Setup logging. * * @param comp default component to use * @param loglevel what types of messages should be logged * @param logfile which file to write log messages to (can be NULL) * @return #GNUNET_OK on success */ int GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile) { const char *env_logfile; const struct tm *tm; time_t t; min_level = get_type (loglevel); #if !defined(GNUNET_CULL_LOGGING) parse_all_definitions (); #endif #ifdef WINDOWS QueryPerformanceFrequency (&performance_frequency); #endif GNUNET_free_non_null (component); GNUNET_asprintf (&component, "%s-%d", comp, getpid ()); GNUNET_free_non_null (component_nopid); component_nopid = GNUNET_strdup (comp); env_logfile = getenv ("GNUNET_FORCE_LOGFILE"); if ((NULL != env_logfile) && (strlen (env_logfile) > 0)) logfile = env_logfile; if (NULL == logfile) return GNUNET_OK; GNUNET_free_non_null (log_file_name); log_file_name = GNUNET_STRINGS_filename_expand (logfile); if (NULL == log_file_name) return GNUNET_SYSERR; t = time (NULL); tm = gmtime (&t); return setup_log_file (tm); } /** * Add a custom logger. * * @param logger log function * @param logger_cls closure for @a logger */ void GNUNET_logger_add (GNUNET_Logger logger, void *logger_cls) { struct CustomLogger *entry; entry = GNUNET_new (struct CustomLogger); entry->logger = logger; entry->logger_cls = logger_cls; entry->next = loggers; loggers = entry; } /** * Remove a custom logger. * * @param logger log function * @param logger_cls closure for @a logger */ void GNUNET_logger_remove (GNUNET_Logger logger, void *logger_cls) { struct CustomLogger *pos; struct CustomLogger *prev; prev = NULL; pos = loggers; while ((NULL != pos) && ((pos->logger != logger) || (pos->logger_cls != logger_cls))) { prev = pos; pos = pos->next; } GNUNET_assert (NULL != pos); if (NULL == prev) loggers = pos->next; else prev->next = pos->next; GNUNET_free (pos); } #if WINDOWS CRITICAL_SECTION output_message_cs; #endif /** * Actually output the log message. * * @param kind how severe was the issue * @param comp component responsible * @param datestr current date/time * @param msg the actual message */ static void output_message (enum GNUNET_ErrorType kind, const char *comp, const char *datestr, const char *msg) { struct CustomLogger *pos; #if WINDOWS EnterCriticalSection (&output_message_cs); #endif if (NULL != GNUNET_stderr) { FPRINTF (GNUNET_stderr, "%s %s %s %s", datestr, comp, GNUNET_error_type_to_string (kind), msg); fflush (GNUNET_stderr); } pos = loggers; while (pos != NULL) { pos->logger (pos->logger_cls, kind, comp, datestr, msg); pos = pos->next; } #if WINDOWS LeaveCriticalSection (&output_message_cs); #endif } /** * Flush an existing bulk report to the output. * * @param datestr our current timestamp */ static void flush_bulk (const char *datestr) { char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256]; int rev; char *last; const char *ft; if ((0 == last_bulk_time.abs_value_us) || (0 == last_bulk_repeat)) return; rev = 0; last = memchr (last_bulk, '\0', BULK_TRACK_SIZE); if (last == NULL) last = &last_bulk[BULK_TRACK_SIZE - 1]; else if (last != last_bulk) last--; if (last[0] == '\n') { rev = 1; last[0] = '\0'; } ft = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (last_bulk_time), GNUNET_YES); snprintf (msg, sizeof (msg), _("Message `%.*s' repeated %u times in the last %s\n"), BULK_TRACK_SIZE, last_bulk, last_bulk_repeat, ft); if (rev == 1) last[0] = '\n'; output_message (last_bulk_kind, last_bulk_comp, datestr, msg); last_bulk_time = GNUNET_TIME_absolute_get (); last_bulk_repeat = 0; } /** * Ignore the next n calls to the log function. * * @param n number of log calls to ignore (could be negative) * @param check_reset #GNUNET_YES to assert that the log skip counter is currently zero */ void GNUNET_log_skip (int n, int check_reset) { int ok; if (0 == n) { ok = (0 == skip_log); skip_log = 0; if (check_reset) GNUNET_break (ok); } else { skip_log += n; } } /** * Get the number of log calls that are going to be skipped * * @return number of log calls to be ignored */ int GNUNET_get_log_skip () { return skip_log; } /** * Output a log message using the default mechanism. * * @param kind how severe was the issue * @param comp component responsible * @param message the actual message * @param va arguments to the format string "message" */ static void mylog (enum GNUNET_ErrorType kind, const char *comp, const char *message, va_list va) { char date[DATE_STR_SIZE]; char date2[DATE_STR_SIZE]; struct tm *tmptr; size_t size; va_list vacp; va_copy (vacp, va); size = VSNPRINTF (NULL, 0, message, vacp) + 1; GNUNET_assert (0 != size); va_end (vacp); memset (date, 0, DATE_STR_SIZE); { char buf[size]; long long offset; #ifdef WINDOWS LARGE_INTEGER pc; time_t timetmp; offset = GNUNET_TIME_get_offset (); time (&timetmp); timetmp += offset / 1000; tmptr = localtime (&timetmp); pc.QuadPart = 0; QueryPerformanceCounter (&pc); if (NULL == tmptr) { strcpy (date, "localtime error"); } else { strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%020llu", tmptr); snprintf (date, sizeof (date), date2, (long long) (pc.QuadPart / (performance_frequency.QuadPart / 1000))); } #else struct timeval timeofday; gettimeofday (&timeofday, NULL); offset = GNUNET_TIME_get_offset (); if (offset > 0) { timeofday.tv_sec += offset / 1000LL; timeofday.tv_usec += (offset % 1000LL) * 1000LL; if (timeofday.tv_usec > 1000000LL) { timeofday.tv_usec -= 1000000LL; timeofday.tv_sec++; } } else { timeofday.tv_sec += offset / 1000LL; if (timeofday.tv_usec > - (offset % 1000LL) * 1000LL) { timeofday.tv_usec += (offset % 1000LL) * 1000LL; } else { timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL; timeofday.tv_sec--; } } tmptr = localtime (&timeofday.tv_sec); if (NULL == tmptr) { strcpy (date, "localtime error"); } else { strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%06u", tmptr); snprintf (date, sizeof (date), date2, timeofday.tv_usec); } #endif VSNPRINTF (buf, size, message, va); if (NULL != tmptr) (void) setup_log_file (tmptr); if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) && (0 != last_bulk_time.abs_value_us) && (0 == strncmp (buf, last_bulk, sizeof (last_bulk)))) { last_bulk_repeat++; if ( (GNUNET_TIME_absolute_get_duration (last_bulk_time).rel_value_us > BULK_DELAY_THRESHOLD) || (last_bulk_repeat > BULK_REPEAT_THRESHOLD) ) flush_bulk (date); return; } flush_bulk (date); strncpy (last_bulk, buf, sizeof (last_bulk)); last_bulk_repeat = 0; last_bulk_kind = kind; last_bulk_time = GNUNET_TIME_absolute_get (); strncpy (last_bulk_comp, comp, COMP_TRACK_SIZE); output_message (kind, comp, date, buf); } } /** * Main log function. * * @param kind how serious is the error? * @param message what is the message (format string) * @param ... arguments for format string */ void GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...) { va_list va; va_start (va, message); mylog (kind, component, message, va); va_end (va); } /** * Log function that specifies an alternative component. * This function should be used by plugins. * * @param kind how serious is the error? * @param comp component responsible for generating the message * @param message what is the message (format string) * @param ... arguments for format string */ void GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp, const char *message, ...) { va_list va; char comp_w_pid[128]; if (comp == NULL) comp = component_nopid; va_start (va, message); GNUNET_snprintf (comp_w_pid, sizeof (comp_w_pid), "%s-%d", comp, getpid ()); mylog (kind, comp_w_pid, message, va); va_end (va); } /** * Convert error type to string. * * @param kind type to convert * @return string corresponding to the type */ const char * GNUNET_error_type_to_string (enum GNUNET_ErrorType kind) { if ((kind & GNUNET_ERROR_TYPE_ERROR) > 0) return _("ERROR"); if ((kind & GNUNET_ERROR_TYPE_WARNING) > 0) return _("WARNING"); if ((kind & GNUNET_ERROR_TYPE_INFO) > 0) return _("INFO"); if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0) return _("DEBUG"); if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0) return _("NONE"); return _("INVALID"); } /** * Convert a hash to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param hc the hash code * @return string form; will be overwritten by next call to GNUNET_h2s. */ const char * GNUNET_h2s (const struct GNUNET_HashCode * hc) { static struct GNUNET_CRYPTO_HashAsciiEncoded ret; GNUNET_CRYPTO_hash_to_enc (hc, &ret); ret.encoding[8] = '\0'; return (const char *) ret.encoding; } /** * Convert a hash to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param hc the hash code * @return string form; will be overwritten by next call to GNUNET_h2s_full. */ const char * GNUNET_h2s_full (const struct GNUNET_HashCode * hc) { static struct GNUNET_CRYPTO_HashAsciiEncoded ret; GNUNET_CRYPTO_hash_to_enc (hc, &ret); ret.encoding[sizeof (ret) - 1] = '\0'; return (const char *) ret.encoding; } /** * Convert a peer identity to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param pid the peer identity * @return string form of the pid; will be overwritten by next * call to #GNUNET_i2s. */ const char * GNUNET_i2s (const struct GNUNET_PeerIdentity *pid) { static char buf[256]; char *ret; ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key); strcpy (buf, ret); GNUNET_free (ret); buf[4] = '\0'; return buf; } /** * Convert a peer identity to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param pid the peer identity * @return string form of the pid; will be overwritten by next * call to #GNUNET_i2s_full. */ const char * GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid) { static char buf[256]; char *ret; ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key); strcpy (buf, ret); GNUNET_free (ret); return buf; } /** * Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string * (for printing debug messages). This is one of the very few calls * in the entire API that is NOT reentrant! * * @param addr the address * @param addrlen the length of the address in @a addr * @return nicely formatted string for the address * will be overwritten by next call to #GNUNET_a2s. */ const char * GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen) { #ifndef WINDOWS #define LEN GNUNET_MAX ((INET6_ADDRSTRLEN + 8), \ (sizeof (struct sockaddr_un) - sizeof (sa_family_t))) #else #define LEN (INET6_ADDRSTRLEN + 8) #endif static char buf[LEN]; #undef LEN static char b2[6]; const struct sockaddr_in *v4; const struct sockaddr_un *un; const struct sockaddr_in6 *v6; unsigned int off; if (addr == NULL) return _("unknown address"); switch (addr->sa_family) { case AF_INET: if (addrlen != sizeof (struct sockaddr_in)) return ""; v4 = (const struct sockaddr_in *) addr; inet_ntop (AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN); if (0 == ntohs (v4->sin_port)) return buf; strcat (buf, ":"); GNUNET_snprintf (b2, sizeof (b2), "%u", ntohs (v4->sin_port)); strcat (buf, b2); return buf; case AF_INET6: if (addrlen != sizeof (struct sockaddr_in6)) return ""; v6 = (const struct sockaddr_in6 *) addr; buf[0] = '['; inet_ntop (AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN); if (0 == ntohs (v6->sin6_port)) return &buf[1]; strcat (buf, "]:"); GNUNET_snprintf (b2, sizeof (b2), "%u", ntohs (v6->sin6_port)); strcat (buf, b2); return buf; case AF_UNIX: if (addrlen <= sizeof (sa_family_t)) return ""; un = (const struct sockaddr_un *) addr; off = 0; if ('\0' == un->sun_path[0]) off++; memset (buf, 0, sizeof (buf)); snprintf (buf, sizeof (buf) - 1, "%s%.*s", (off == 1) ? "@" : "", (int) (addrlen - sizeof (sa_family_t) - 1 - off), &un->sun_path[off]); return buf; default: return _("invalid address"); } } /** * Log error message about missing configuration option. * * @param kind log level * @param section section with missing option * @param option name of missing option */ void GNUNET_log_config_missing (enum GNUNET_ErrorType kind, const char *section, const char *option) { GNUNET_log (kind, _("Configuration fails to specify option `%s' in section `%s'!\n"), option, section); } /** * Log error message about invalid configuration option value. * * @param kind log level * @param section section with invalid option * @param option name of invalid option * @param required what is required that is invalid about the option */ void GNUNET_log_config_invalid (enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required) { GNUNET_log (kind, _("Configuration specifies invalid value for option `%s' in section `%s': %s\n"), option, section, required); } /** * Initializer */ void __attribute__ ((constructor)) GNUNET_util_cl_init () { GNUNET_stderr = stderr; #ifdef MINGW GNInitWinEnv (NULL); #endif #if WINDOWS if (!InitializeCriticalSectionAndSpinCount (&output_message_cs, 0x00000400)) GNUNET_abort (); #endif } /** * Destructor */ void __attribute__ ((destructor)) GNUNET_util_cl_fini () { #if WINDOWS DeleteCriticalSection (&output_message_cs); #endif #ifdef MINGW GNShutdownWinEnv (); #endif } /* end of common_logging.c */ gnunet-0.10.1/src/util/test_crypto_hash.c0000644000175000017500000001017112225777501015314 00000000000000/* This file is part of GNUnet. (C) 2002, 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file util/test_crypto_hash.c * @brief Test for crypto_hash.c */ #include "platform.h" #include "gnunet_util_lib.h" static char block[65536]; #define FILENAME "testblock.dat" static int test (int number) { struct GNUNET_HashCode h1; struct GNUNET_HashCode h2; struct GNUNET_CRYPTO_HashAsciiEncoded enc; memset (&h1, number, sizeof (struct GNUNET_HashCode)); GNUNET_CRYPTO_hash_to_enc (&h1, &enc); if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &h2)) { printf ("enc2hash failed!\n"); return 1; } if (0 != memcmp (&h1, &h2, sizeof (struct GNUNET_HashCode))) return 1; return 0; } static int testEncoding () { int i; for (i = 0; i < 255; i++) if (0 != test (i)) return 1; return 0; } static int testArithmetic () { struct GNUNET_HashCode h1; struct GNUNET_HashCode h2; struct GNUNET_HashCode d; struct GNUNET_HashCode s; struct GNUNET_CRYPTO_SymmetricSessionKey skey; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &h1); GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &h2); if (GNUNET_CRYPTO_hash_distance_u32 (&h1, &h2) != GNUNET_CRYPTO_hash_distance_u32 (&h2, &h1)) return 1; GNUNET_CRYPTO_hash_difference (&h1, &h2, &d); GNUNET_CRYPTO_hash_sum (&h1, &d, &s); if (0 != GNUNET_CRYPTO_hash_cmp (&s, &h2)) return 1; GNUNET_CRYPTO_hash_xor (&h1, &h2, &d); GNUNET_CRYPTO_hash_xor (&h1, &d, &s); if (0 != GNUNET_CRYPTO_hash_cmp (&s, &h2)) return 1; if (0 != GNUNET_CRYPTO_hash_xorcmp (&s, &h2, &h1)) return 1; if (-1 != GNUNET_CRYPTO_hash_xorcmp (&h1, &h2, &h1)) return 1; if (1 != GNUNET_CRYPTO_hash_xorcmp (&h1, &h2, &h2)) return 1; memset (&d, 0xF0, sizeof (d)); if (0 != GNUNET_CRYPTO_hash_get_bit (&d, 3)) return 1; if (1 != GNUNET_CRYPTO_hash_get_bit (&d, 6)) return 1; memset (&d, 0, sizeof (d)); GNUNET_CRYPTO_hash_to_aes_key (&d, &skey, &iv); return 0; } static void finished_task (void *cls, const struct GNUNET_HashCode * res) { int *ret = cls; struct GNUNET_HashCode want; GNUNET_CRYPTO_hash (block, sizeof (block), &want); if (0 != memcmp (res, &want, sizeof (want))) *ret = 2; else *ret = 0; } static void file_hasher (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_assert (NULL != GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_DEFAULT, FILENAME, 1024, &finished_task, cls)); } static int testFileHash () { int ret; FILE *f; memset (block, 42, sizeof (block) / 2); memset (&block[sizeof (block) / 2], 43, sizeof (block) / 2); GNUNET_assert (NULL != (f = FOPEN (FILENAME, "w+"))); GNUNET_break (sizeof (block) == fwrite (block, 1, sizeof (block), f)); GNUNET_break (0 == FCLOSE (f)); ret = 1; GNUNET_SCHEDULER_run (&file_hasher, &ret); GNUNET_break (0 == UNLINK (FILENAME)); return ret; } int main (int argc, char *argv[]) { int failureCount = 0; int i; GNUNET_log_setup ("test-crypto-hash", "WARNING", NULL); for (i = 0; i < 10; i++) failureCount += testEncoding (); failureCount += testArithmetic (); failureCount += testFileHash (); if (failureCount != 0) return 1; return 0; } /* end of hashingtest.c */ gnunet-0.10.1/src/util/gnunet-ecc.c0000644000175000017500000002401312274162760013761 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/gnunet-ecc.c * @brief tool to manipulate EDDSA key files * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include /** * Flag for listing public key. */ static int list_keys; /** * Flag for listing public key. */ static int list_keys_count; /** * Flag for printing public key. */ static int print_public_key; /** * Flag for printing the output of random example operations. */ static int print_examples_flag; /** * Flag for printing hash of public key. */ static int print_peer_identity; /** * Option set to create a bunch of keys at once. */ static unsigned int make_keys; /** * Create a flat file with a large number of key pairs for testing. */ static void create_keys (const char *fn) { FILE *f; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; if (NULL == (f = fopen (fn, "w+"))) { fprintf (stderr, _("Failed to open `%s': %s\n"), fn, STRERROR (errno)); return; } fprintf (stderr, _("Generating %u keys, please wait"), make_keys); while (0 < make_keys--) { fprintf (stderr, "."); if (NULL == (pk = GNUNET_CRYPTO_eddsa_key_create ())) { GNUNET_break (0); break; } if (GNUNET_TESTING_HOSTKEYFILESIZE != fwrite (pk, 1, GNUNET_TESTING_HOSTKEYFILESIZE, f)) { fprintf (stderr, _("\nFailed to write to `%s': %s\n"), fn, STRERROR (errno)); GNUNET_free (pk); break; } GNUNET_free (pk); } if (UINT_MAX == make_keys) fprintf (stderr, _("\nFinished!\n")); else fprintf (stderr, _("\nError, %u keys not generated\n"), make_keys); fclose (f); } static void print_hex (char *msg, void *buf, size_t size) { size_t i; printf ("%s: ", msg); for (i = 0; i < size; i++) { printf ("%02hhx", ((char *)buf)[i]); } printf ("\n"); } static void print_examples_ecdh () { struct GNUNET_CRYPTO_EcdhePrivateKey *dh_priv1; struct GNUNET_CRYPTO_EcdhePublicKey *dh_pub1; struct GNUNET_CRYPTO_EcdhePrivateKey *dh_priv2; struct GNUNET_CRYPTO_EcdhePublicKey *dh_pub2; struct GNUNET_HashCode hash; char buf[128]; dh_pub1 = GNUNET_new (struct GNUNET_CRYPTO_EcdhePublicKey); dh_priv1 = GNUNET_CRYPTO_ecdhe_key_create (); dh_pub2 = GNUNET_new (struct GNUNET_CRYPTO_EcdhePublicKey); dh_priv2 = GNUNET_CRYPTO_ecdhe_key_create (); GNUNET_CRYPTO_ecdhe_key_get_public (dh_priv1, dh_pub1); GNUNET_CRYPTO_ecdhe_key_get_public (dh_priv2, dh_pub2); GNUNET_assert (NULL != GNUNET_STRINGS_data_to_string (dh_priv1, 32, buf, 128)); printf ("ECDHE key 1:\n"); printf ("private: %s\n", buf); print_hex ("private(hex)", dh_priv1, sizeof *dh_priv1); GNUNET_assert (NULL != GNUNET_STRINGS_data_to_string (dh_pub1, 32, buf, 128)); printf ("public: %s\n", buf); print_hex ("public(hex)", dh_pub1, sizeof *dh_pub1); GNUNET_assert (NULL != GNUNET_STRINGS_data_to_string (dh_priv2, 32, buf, 128)); printf ("ECDHE key 2:\n"); printf ("private: %s\n", buf); print_hex ("private(hex)", dh_priv2, sizeof *dh_priv2); GNUNET_assert (NULL != GNUNET_STRINGS_data_to_string (dh_pub2, 32, buf, 128)); printf ("public: %s\n", buf); print_hex ("public(hex)", dh_pub2, sizeof *dh_pub2); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecc_ecdh (dh_priv1, dh_pub2, &hash)); GNUNET_assert (NULL != GNUNET_STRINGS_data_to_string (&hash, 64, buf, 128)); printf ("ECDH shared secret: %s\n", buf); GNUNET_free (dh_priv1); GNUNET_free (dh_priv2); GNUNET_free (dh_pub1); GNUNET_free (dh_pub2); } /** * Print some random example operations to stdout. */ static void print_examples () { print_examples_ecdh (); // print_examples_ecdsa (); // print_examples_eddsa (); } static void print_key (const char *filename) { struct GNUNET_DISK_FileHandle *fd; struct GNUNET_CRYPTO_EddsaPrivateKey private_key; struct GNUNET_CRYPTO_EddsaPublicKey public_key; char *hostkeys_data; char *hostkey_str; uint64_t fs; unsigned int total_hostkeys; unsigned int c; if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { fprintf (stderr, _("Hostkeys file `%s' not found\n"), filename); return; } /* Check hostkey file size, read entire thing into memory */ if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) fs = 0; if (0 == fs) { fprintf (stderr, _("Hostkeys file `%s' is empty\n"), filename); return; /* File is empty */ } if (0 != (fs % GNUNET_TESTING_HOSTKEYFILESIZE)) { fprintf (stderr, _("Incorrect hostkey file format: %s\n"), filename); return; } fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", filename); return; } hostkeys_data = GNUNET_malloc (fs); if (fs != GNUNET_DISK_file_read (fd, hostkeys_data, fs)) { fprintf (stderr, _("Could not read hostkey file: %s\n"), filename); GNUNET_free (hostkeys_data); GNUNET_DISK_file_close (fd); return; } GNUNET_DISK_file_close (fd); if (NULL == hostkeys_data) return; total_hostkeys = fs / GNUNET_TESTING_HOSTKEYFILESIZE; for (c = 0; (c < total_hostkeys) && (c < list_keys_count); c++) { memcpy (&private_key, hostkeys_data + (c * GNUNET_TESTING_HOSTKEYFILESIZE), GNUNET_TESTING_HOSTKEYFILESIZE); GNUNET_CRYPTO_eddsa_key_get_public (&private_key, &public_key); hostkey_str = GNUNET_CRYPTO_eddsa_public_key_to_string (&public_key); if (NULL != hostkey_str) { fprintf (stderr, "%4u: %s\n", c, hostkey_str); GNUNET_free (hostkey_str); } else fprintf (stderr, "%4u: %s\n", c, "invalid"); } GNUNET_free (hostkeys_data); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { if (print_examples_flag) { print_examples (); return; } if (NULL == args[0]) { FPRINTF (stderr, "%s", _("No hostkey file specified on command line\n")); return; } if (list_keys) { print_key (args[0]); return; } if (make_keys > 0) { create_keys (args[0]); return; } if (print_public_key) { struct GNUNET_CRYPTO_EddsaPrivateKey *pk; struct GNUNET_CRYPTO_EddsaPublicKey pub; char *s; pk = GNUNET_CRYPTO_eddsa_key_create_from_file (args[0]); if (NULL == pk) return; GNUNET_CRYPTO_eddsa_key_get_public (pk, &pub); s = GNUNET_CRYPTO_eddsa_public_key_to_string (&pub); FPRINTF (stdout, "%s\n", s); GNUNET_free (s); GNUNET_free (pk); } if (print_peer_identity) { char *str; struct GNUNET_DISK_FileHandle *keyfile; struct GNUNET_CRYPTO_EddsaPrivateKey pk; struct GNUNET_CRYPTO_EddsaPublicKey pub; keyfile = GNUNET_DISK_file_open (args[0], GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == keyfile) return; while (sizeof (pk) == GNUNET_DISK_file_read (keyfile, &pk, sizeof (pk))) { GNUNET_CRYPTO_eddsa_key_get_public (&pk, &pub); str = GNUNET_CRYPTO_eddsa_public_key_to_string (&pub); FPRINTF (stdout, "%s\n", str); GNUNET_free (str); } } } /** * Program to manipulate ECC key files. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { list_keys_count = UINT32_MAX; static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'i', "iterate", "FILE", gettext_noop ("list keys included in a file (for testing)"), 0, &GNUNET_GETOPT_set_one, &list_keys }, { 'e', "end=", "COUNT", gettext_noop ("number of keys to list included in a file (for testing)"), 1, &GNUNET_GETOPT_set_uint, &list_keys_count }, { 'g', "generate-keys", "COUNT", gettext_noop ("create COUNT public-private key pairs (for testing)"), 1, &GNUNET_GETOPT_set_uint, &make_keys }, { 'p', "print-public-key", NULL, gettext_noop ("print the public key in ASCII format"), 0, &GNUNET_GETOPT_set_one, &print_public_key }, { 'P', "print-peer-identity", NULL, gettext_noop ("print the hash of the public key in ASCII format"), 0, &GNUNET_GETOPT_set_one, &print_peer_identity }, { 'E', "examples", NULL, gettext_noop ("print examples of ECC operations (used for compatibility testing)"), 0, &GNUNET_GETOPT_set_one, &print_examples_flag }, GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-ecc [OPTIONS] keyfile", gettext_noop ("Manipulate GNUnet private ECC key files"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-ecc.c */ gnunet-0.10.1/src/util/load.c0000644000175000017500000001473312225777501012661 00000000000000/* This file is part of GNUnet. (C) 2010, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/load.c * @brief functions related to load calculations * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Values we track for load calculations. */ struct GNUNET_LOAD_Value { /** * How fast should the load decline if no values are added? */ struct GNUNET_TIME_Relative autodecline; /** * Last time this load value was updated by an event. */ struct GNUNET_TIME_Absolute last_update; /** * Sum of all datastore delays ever observed (in ms). Note that * delays above 64k ms are excluded (to avoid overflow within * first 4 billion requests). */ uint64_t cummulative_delay; /** * Sum of squares of all datastore delays ever observed (in ms). Note that * delays above 64k ms are excluded (to avoid overflow within * first 4 billion requests). */ uint64_t cummulative_squared_delay; /** * Total number of requests included in the cummulative datastore delay values. */ uint64_t cummulative_request_count; /** * Current running average datastore delay. Its relation to the * average datastore delay and it std. dev. (as calcualted from the * cummulative values) tells us our current load. */ double runavg_delay; /** * How high is the load? 0 for below average, otherwise * the number of std. devs we are above average, or 100 if the * load is so high that we currently cannot calculate it. */ double load; }; static void internal_update (struct GNUNET_LOAD_Value *load) { struct GNUNET_TIME_Relative delta; unsigned int n; if (load->autodecline.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) return; delta = GNUNET_TIME_absolute_get_duration (load->last_update); if (delta.rel_value_us < load->autodecline.rel_value_us) return; if (0 == load->autodecline.rel_value_us) { load->runavg_delay = 0.0; load->load = 0; return; } n = delta.rel_value_us / load->autodecline.rel_value_us; if (n > 16) { load->runavg_delay = 0.0; load->load = 0; return; } while (n > 0) { n--; load->runavg_delay = (load->runavg_delay * 7.0) / 8.0; } } /** * Create a new load value. * * @param autodecline speed at which this value should automatically * decline in the absence of external events; at the given * frequency, 0-load values will be added to the load * @return the new load value */ struct GNUNET_LOAD_Value * GNUNET_LOAD_value_init (struct GNUNET_TIME_Relative autodecline) { struct GNUNET_LOAD_Value *ret; ret = GNUNET_new (struct GNUNET_LOAD_Value); ret->autodecline = autodecline; ret->last_update = GNUNET_TIME_absolute_get (); return ret; } /** * Change the value by which the load automatically declines. * * @param load load to update * @param autodecline frequency of load decline */ void GNUNET_LOAD_value_set_decline (struct GNUNET_LOAD_Value *load, struct GNUNET_TIME_Relative autodecline) { internal_update (load); load->autodecline = autodecline; } /** * Recalculate our load value. * * @param load load to update */ static void calculate_load (struct GNUNET_LOAD_Value *load) { double stddev; double avgdel; double sum_val_i; double n; double nm1; if (load->cummulative_request_count <= 1) return; /* calcuate std dev of latency; we have for n values of "i" that: * * avg = (sum val_i) / n * stddev = (sum (val_i - avg)^2) / (n-1) * = (sum (val_i^2 - 2 avg val_i + avg^2) / (n-1) * = (sum (val_i^2) - 2 avg sum (val_i) + n * avg^2) / (n-1) */ sum_val_i = (double) load->cummulative_delay; n = ((double) load->cummulative_request_count); nm1 = n - 1.0; avgdel = sum_val_i / n; stddev = (((double) load->cummulative_squared_delay) - 2.0 * avgdel * sum_val_i + n * avgdel * avgdel) / nm1; if (stddev <= 0) stddev = 0.01; /* must have been rounding error or zero; prevent division by zero */ /* now calculate load based on how far out we are from * std dev; or if we are below average, simply assume load zero */ if (load->runavg_delay < avgdel) load->load = 0.0; else load->load = (load->runavg_delay - avgdel) / stddev; } /** * Get the current load. * * @param load load handle * @return zero for below-average load, otherwise * number of std. devs we are above average; * 100 if the latest updates were so large * that we could not do proper calculations */ double GNUNET_LOAD_get_load (struct GNUNET_LOAD_Value *load) { internal_update (load); calculate_load (load); return load->load; } /** * Get the average value given to update so far. * * @param load load handle * @return zero if update was never called */ double GNUNET_LOAD_get_average (struct GNUNET_LOAD_Value *load) { double n; double sum_val_i; internal_update (load); if (load->cummulative_request_count == 0) return 0.0; n = ((double) load->cummulative_request_count); sum_val_i = (double) load->cummulative_delay; return sum_val_i / n; } /** * Update the current load. * * @param load to update * @param data latest measurement value (for example, delay) */ void GNUNET_LOAD_update (struct GNUNET_LOAD_Value *load, uint64_t data) { uint32_t dv; internal_update (load); load->last_update = GNUNET_TIME_absolute_get (); if (data > 64 * 1024) { /* very large */ load->load = 100.0; return; } dv = (uint32_t) data; load->cummulative_delay += dv; load->cummulative_squared_delay += dv * dv; load->cummulative_request_count++; load->runavg_delay = ((load->runavg_delay * 7.0) + dv) / 8.0; } /* end of load.c */ gnunet-0.10.1/src/util/test_crypto_ecdsa.c0000644000175000017500000001540512250373132015443 00000000000000/* This file is part of GNUnet. (C) 2002-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_crypto_ecdsa.c * @brief testcase for ECC ECDSA public key crypto * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_signatures.h" #include #define ITER 25 #define PERF GNUNET_YES static struct GNUNET_CRYPTO_EcdsaPrivateKey *key; static int testSignVerify () { struct GNUNET_CRYPTO_EcdsaSignature sig; struct GNUNET_CRYPTO_EccSignaturePurpose purp; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; int i; struct GNUNET_TIME_Absolute start; int ok = GNUNET_OK; FPRINTF (stderr, "%s", "W"); GNUNET_CRYPTO_ecdsa_key_get_public (key, &pkey); start = GNUNET_TIME_absolute_get (); purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); for (i = 0; i < ITER; i++) { FPRINTF (stderr, "%s", "."); fflush (stderr); if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (key, &purp, &sig)) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_ecdsa_sign returned SYSERR\n"); ok = GNUNET_SYSERR; continue; } if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig, &pkey)) { printf ("GNUNET_CRYPTO_ecdsa_verify failed!\n"); ok = GNUNET_SYSERR; continue; } if (GNUNET_SYSERR != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, &purp, &sig, &pkey)) { printf ("GNUNET_CRYPTO_ecdsa_verify failed to fail!\n"); ok = GNUNET_SYSERR; continue; } } printf ("%d ECDSA sign/verify operations %s\n", ITER, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); return ok; } static int testDeriveSignVerify () { struct GNUNET_CRYPTO_EcdsaSignature sig; struct GNUNET_CRYPTO_EccSignaturePurpose purp; struct GNUNET_CRYPTO_EcdsaPrivateKey *dpriv; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; struct GNUNET_CRYPTO_EcdsaPublicKey dpub; dpriv = GNUNET_CRYPTO_ecdsa_private_key_derive (key, "test-derive", "test-CTX"); GNUNET_CRYPTO_ecdsa_key_get_public (key, &pkey); GNUNET_CRYPTO_ecdsa_public_key_derive (&pkey, "test-derive", "test-CTX", &dpub); purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (dpriv, &purp, &sig)) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_ecdsa_sign returned SYSERR\n"); GNUNET_free (dpriv); return GNUNET_SYSERR; } if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig, &dpub)) { printf ("GNUNET_CRYPTO_ecdsa_verify failed!\n"); GNUNET_free (dpriv); return GNUNET_SYSERR; } if (GNUNET_SYSERR != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig, &pkey)) { printf ("GNUNET_CRYPTO_ecdsa_verify failed to fail!\n"); GNUNET_free (dpriv); return GNUNET_SYSERR; } if (GNUNET_SYSERR != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, &purp, &sig, &dpub)) { printf ("GNUNET_CRYPTO_ecdsa_verify failed to fail!\n"); GNUNET_free (dpriv); return GNUNET_SYSERR; } GNUNET_free (dpriv); return GNUNET_OK; } #if PERF static int testSignPerformance () { struct GNUNET_CRYPTO_EccSignaturePurpose purp; struct GNUNET_CRYPTO_EcdsaSignature sig; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; int i; struct GNUNET_TIME_Absolute start; int ok = GNUNET_OK; purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); FPRINTF (stderr, "%s", "W"); GNUNET_CRYPTO_ecdsa_key_get_public (key, &pkey); start = GNUNET_TIME_absolute_get (); for (i = 0; i < ITER; i++) { FPRINTF (stderr, "%s", "."); fflush (stderr); if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_sign (key, &purp, &sig)) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_ecdsa_sign returned SYSERR\n"); ok = GNUNET_SYSERR; continue; } } printf ("%d ECC sign operations %s\n", ITER, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); return ok; } #endif static void perf_keygen () { struct GNUNET_TIME_Absolute start; struct GNUNET_CRYPTO_EcdsaPrivateKey *pk; int i; FPRINTF (stderr, "%s", "W"); start = GNUNET_TIME_absolute_get (); for (i=0;i<10;i++) { fprintf (stderr, "."); fflush (stderr); pk = GNUNET_CRYPTO_ecdsa_key_create (); GNUNET_free (pk); } for (;i<25;i++) fprintf (stderr, "."); fflush (stderr); printf ("10 ECDSA keys created in %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); } int main (int argc, char *argv[]) { int failure_count = 0; if (! gcry_check_version ("1.6.0")) { FPRINTF (stderr, _ ("libgcrypt has not the expected version (version %s is required).\n"), "1.6.0"); return 0; } if (getenv ("GNUNET_GCRYPT_DEBUG")) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); GNUNET_log_setup ("test-crypto-ecc", "WARNING", NULL); key = GNUNET_CRYPTO_ecdsa_key_create (); if (GNUNET_OK != testDeriveSignVerify ()) { failure_count++; fprintf (stderr, "\n\n%d TESTS FAILED!\n\n", failure_count); return -1; } #if PERF if (GNUNET_OK != testSignPerformance ()) failure_count++; #endif if (GNUNET_OK != testSignVerify ()) failure_count++; GNUNET_free (key); perf_keygen (); if (0 != failure_count) { fprintf (stderr, "\n\n%d TESTS FAILED!\n\n", failure_count); return -1; } return 0; } /* end of test_crypto_ecdsa.c */ gnunet-0.10.1/src/util/test_common_endian.c0000644000175000017500000000251512225777501015602 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_common_endian.c * @brief testcase for common_endian.c */ #include "platform.h" #include "gnunet_util_lib.h" #define CHECK(n) if (n != GNUNET_htonll(GNUNET_ntohll(n))) return 1; int main (int argc, char *argv[]) { GNUNET_log_setup ("test-common-endian", "WARNING", NULL); CHECK (1); CHECK (0x12345678); CHECK (123456789012345LL); if ((0x1234567890ABCDEFLL != GNUNET_htonll (0xEFCDAB9078563412LL)) && 42 != htonl (42)) return 1; return 0; } /* end of test_common_endian.c */ gnunet-0.10.1/src/util/test_disk.c0000644000175000017500000001425312226035552013722 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2005, 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_disk.c * @brief testcase for the storage module * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define TESTSTRING "Hello World\0" static int testReadWrite () { char tmp[100 + 1]; int ret; if (strlen (TESTSTRING) != GNUNET_DISK_fn_write (".testfile", TESTSTRING, strlen (TESTSTRING), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) return 1; if (GNUNET_OK != GNUNET_DISK_file_test (".testfile")) return 1; ret = GNUNET_DISK_fn_read (".testfile", tmp, sizeof (tmp) - 1); if (ret < 0) { FPRINTF (stderr, "Error reading file `%s' in testReadWrite\n", ".testfile"); return 1; } tmp[ret] = '\0'; if (0 != memcmp (tmp, TESTSTRING, strlen (TESTSTRING) + 1)) { FPRINTF (stderr, "Error in testReadWrite: *%s* != *%s* for file %s\n", tmp, TESTSTRING, ".testfile"); return 1; } GNUNET_DISK_file_copy (".testfile", ".testfile2"); memset (tmp, 0, sizeof (tmp)); ret = GNUNET_DISK_fn_read (".testfile2", tmp, sizeof (tmp) - 1); if (ret < 0) { FPRINTF (stderr, "Error reading file `%s' in testReadWrite\n", ".testfile2"); return 1; } tmp[ret] = '\0'; if (0 != memcmp (tmp, TESTSTRING, strlen (TESTSTRING) + 1)) { FPRINTF (stderr, "Error in testReadWrite: *%s* != *%s* for file %s\n", tmp, TESTSTRING, ".testfile2"); return 1; } GNUNET_break (0 == UNLINK (".testfile")); GNUNET_break (0 == UNLINK (".testfile2")); if (GNUNET_NO != GNUNET_DISK_file_test (".testfile")) return 1; return 0; } static int testOpenClose () { struct GNUNET_DISK_FileHandle *fh; uint64_t size; fh = GNUNET_DISK_file_open (".testfile", GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); GNUNET_assert (GNUNET_NO == GNUNET_DISK_handle_invalid (fh)); GNUNET_break (5 == GNUNET_DISK_file_write (fh, "Hello", 5)); GNUNET_DISK_file_close (fh); GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (".testfile", &size, GNUNET_NO, GNUNET_YES)); if (size != 5) return 1; GNUNET_break (0 == UNLINK (".testfile")); return 0; } static int ok; static int scan_callback (void *want, const char *filename) { if (NULL != strstr (filename, want)) ok++; return GNUNET_OK; } static int testDirScan () { if (GNUNET_OK != GNUNET_DISK_directory_create ("test" DIR_SEPARATOR_STR "entry")) return 1; if (GNUNET_OK != GNUNET_DISK_directory_create ("test" DIR_SEPARATOR_STR "entry_more")) return 1; GNUNET_DISK_directory_scan ("test", &scan_callback, "test" DIR_SEPARATOR_STR "entry"); if (GNUNET_OK != GNUNET_DISK_directory_remove ("test")) return 1; if (ok < 2) return 1; return 0; } static void iter_callback (void *cls, struct GNUNET_DISK_DirectoryIterator *di, const char *filename, const char *dirname) { int *i = cls; (*i)++; GNUNET_DISK_directory_iterator_next (di, GNUNET_NO); } static void iter_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_DISK_directory_iterator_start (GNUNET_SCHEDULER_PRIORITY_DEFAULT, "test", &iter_callback, cls); } static int testDirIter () { int i; i = 0; if (GNUNET_OK != GNUNET_DISK_directory_create ("test/entry")) return 1; if (GNUNET_OK != GNUNET_DISK_directory_create ("test/entry_many")) return 1; if (GNUNET_OK != GNUNET_DISK_directory_create ("test/entry_more")) return 1; GNUNET_SCHEDULER_run (&iter_task, &i); if (GNUNET_OK != GNUNET_DISK_directory_remove ("test")) return 1; if (i < 3) return 1; return 0; } static int testCanonicalize () { char *fn = GNUNET_strdup ("ab?><|cd*ef:/g\""); GNUNET_DISK_filename_canonicalize (fn); if (0 != strcmp (fn, "ab____cd_ef__g_")) { GNUNET_free (fn); return 1; } GNUNET_free (fn); return 0; } static int testChangeOwner () { #ifndef WINDOWS GNUNET_log_skip (1, GNUNET_NO); if (GNUNET_OK == GNUNET_DISK_file_change_owner ("/dev/null", "unknownuser")) return 1; #endif return 0; } static int testDirMani () { if (GNUNET_OK != GNUNET_DISK_directory_create_for_file ("test/ing")) return 1; if (GNUNET_NO != GNUNET_DISK_file_test ("test")) return 1; if (GNUNET_NO != GNUNET_DISK_file_test ("test/ing")) return 1; if (GNUNET_OK != GNUNET_DISK_directory_remove ("test")) return 1; if (GNUNET_OK != GNUNET_DISK_directory_create ("test")) return 1; if (GNUNET_YES != GNUNET_DISK_directory_test ("test", GNUNET_YES)) return 1; if (GNUNET_OK != GNUNET_DISK_directory_remove ("test")) return 1; return 0; } int main (int argc, char *argv[]) { unsigned int failureCount = 0; GNUNET_log_setup ("test-disk", "WARNING", NULL); failureCount += testReadWrite (); failureCount += testOpenClose (); failureCount += testDirScan (); failureCount += testDirIter (); failureCount += testCanonicalize (); failureCount += testChangeOwner (); failureCount += testDirMani (); if (failureCount != 0) { FPRINTF (stderr, "\n%u TESTS FAILED!\n", failureCount); return -1; } return 0; } /* end of main */ gnunet-0.10.1/src/util/crypto_crc.c0000644000175000017500000001065612307322113014073 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. For the actual CRC-32 code: Copyright abandoned; this code is in the public domain. Provided to GNUnet by peter@horizon.com */ /** * @file util/crypto_crc.c * @brief implementation of CRC16 and CRC32 * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /* Avoid wasting space on 8-byte longs. */ #if UINT_MAX >= 0xffffffff typedef unsigned int GNUNET_uLong; #elif ULONG_MAX >= 0xffffffff typedef unsigned long GNUNET_uLong; #else #error This compiler is not ANSI-compliant! #endif #define Z_NULL 0 #define POLYNOMIAL (GNUNET_uLong)0xedb88320 static GNUNET_uLong crc_table[256]; /* * This routine writes each crc_table entry exactly once, * with the correct final value. Thus, it is safe to call * even on a table that someone else is using concurrently. */ static void crc_init () { static int once; unsigned int i, j; GNUNET_uLong h = 1; if (once) return; once = 1; crc_table[0] = 0; for (i = 128; i; i >>= 1) { h = (h >> 1) ^ ((h & 1) ? POLYNOMIAL : 0); /* h is now crc_table[i] */ for (j = 0; j < 256; j += 2 * i) crc_table[i + j] = crc_table[j] ^ h; } } /* * This computes the standard preset and inverted CRC, as used * by most networking standards. Start by passing in an initial * chaining value of 0, and then pass in the return value from the * previous crc32() call. The final return value is the CRC. * Note that this is a little-endian CRC, which is best used with * data transmitted lsbit-first, and it should, itself, be appended * to data in little-endian byte and bit order to preserve the * property of detecting all burst errors of length 32 bits or less. */ static GNUNET_uLong crc32 (GNUNET_uLong crc, const char *buf, size_t len) { crc_init (); GNUNET_assert (crc_table[255] != 0); crc ^= 0xffffffff; while (len--) crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff]; return crc ^ 0xffffffff; } /** * Compute the CRC32 checksum for the first len bytes of the buffer. * * @param buf the data over which we're taking the CRC * @param len the length of the buffer * @return the resulting CRC32 checksum */ int32_t GNUNET_CRYPTO_crc32_n (const void *buf, size_t len) { GNUNET_uLong crc; crc = crc32 (0L, Z_NULL, 0); crc = crc32 (crc, (char *) buf, len); return crc; } /** * Perform an incremental step in a CRC16 (for TCP/IP) calculation. * * @param sum current sum, initially 0 * @param buf buffer to calculate CRC over (must be 16-bit aligned) * @param len number of bytes in hdr, must be multiple of 2 * @return updated crc sum (must be subjected to GNUNET_CRYPTO_crc16_finish to get actual crc16) */ uint32_t GNUNET_CRYPTO_crc16_step (uint32_t sum, const void *buf, size_t len) { const uint16_t *hdr = buf; for (; len >= 2; len -= 2) sum += *(hdr++); if (len == 1) sum += (*hdr) & ntohs(0xFF00); return sum; } /** * Convert results from GNUNET_CRYPTO_crc16_step to final crc16. * * @param sum cummulative sum * @return crc16 value */ uint16_t GNUNET_CRYPTO_crc16_finish (uint32_t sum) { sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); return ~sum; } /** * Calculate the checksum of a buffer in one step. * * @param buf buffer to calculate CRC over (must be 16-bit aligned) * @param len number of bytes in hdr, must be multiple of 2 * @return crc16 value */ uint16_t GNUNET_CRYPTO_crc16_n (const void *buf, size_t len) { const uint16_t *hdr = buf; uint32_t sum = GNUNET_CRYPTO_crc16_step (0, hdr, len); return GNUNET_CRYPTO_crc16_finish (sum); } /* end of crypto_crc.c */ gnunet-0.10.1/src/util/test_crypto_symmetric.c0000644000175000017500000001206712225777501016413 00000000000000/* This file is part of GNUnet. (C) 2002, 2003, 2004, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file util/test_crypto_symmetric.c * @brief test for AES ciphers */ #include "platform.h" #include "gnunet_util_lib.h" #define TESTSTRING "Hello World!" #define INITVALUE "InitializationVectorValueinitializationvectorvalue" static int testSymcipher () { struct GNUNET_CRYPTO_SymmetricSessionKey key; char result[100]; int size; char res[100]; GNUNET_CRYPTO_symmetric_create_session_key (&key); size = GNUNET_CRYPTO_symmetric_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, &key, (const struct GNUNET_CRYPTO_SymmetricInitializationVector *) INITVALUE, result); if (size == -1) { printf ("symciphertest failed: encryptBlock returned %d\n", size); return 1; } size = GNUNET_CRYPTO_symmetric_decrypt (result, size, &key, (const struct GNUNET_CRYPTO_SymmetricInitializationVector *) INITVALUE, res); if (strlen (TESTSTRING) + 1 != size) { printf ("symciphertest failed: decryptBlock returned %d\n", size); return 1; } if (0 != strcmp (res, TESTSTRING)) { printf ("symciphertest failed: %s != %s\n", res, TESTSTRING); return 1; } else return 0; } static int verifyCrypto () { struct GNUNET_CRYPTO_SymmetricSessionKey key; char result[GNUNET_CRYPTO_AES_KEY_LENGTH]; char *res; int ret; unsigned char plain[] = { 29, 128, 192, 253, 74, 171, 38, 187, 84, 219, 76, 76, 209, 118, 33, 249, 172, 124, 96, 9, 157, 110, 8, 215, 200, 63, 69, 230, 157, 104, 247, 164 }; unsigned char raw_key_aes[] = { 106, 74, 209, 88, 145, 55, 189, 135, 125, 180, 225, 108, 183, 54, 25, 169, 129, 188, 131, 75, 227, 245, 105, 10, 225, 15, 115, 159, 148, 184, 34, 191 }; unsigned char raw_key_twofish[] = { 145, 55, 189, 135, 125, 180, 225, 108, 183, 54, 25, 169, 129, 188, 131, 75, 227, 245, 105, 10, 225, 15, 115, 159, 148, 184, 34, 191, 106, 74, 209, 88 }; unsigned char encrresult[] = { 155, 88, 106, 174, 124, 172, 47, 149, 85, 15, 208, 176, 65, 124, 155, 74, 215, 25, 177, 231, 162, 109, 165, 4, 133, 165, 93, 44, 213, 77, 206, 204, 1 }; res = NULL; ret = 0; memcpy (key.aes_key, raw_key_aes, GNUNET_CRYPTO_AES_KEY_LENGTH); memcpy (key.twofish_key, raw_key_twofish, GNUNET_CRYPTO_AES_KEY_LENGTH); if (GNUNET_CRYPTO_AES_KEY_LENGTH != GNUNET_CRYPTO_symmetric_encrypt (plain, GNUNET_CRYPTO_AES_KEY_LENGTH, &key, (const struct GNUNET_CRYPTO_SymmetricInitializationVector *) "testtesttesttesttesttesttesttest", result)) { printf ("Wrong return value from encrypt block.\n"); ret = 1; goto error; } if (0 != memcmp (encrresult, result, GNUNET_CRYPTO_AES_KEY_LENGTH)) { int i; printf ("Encrypted result wrong.\n"); for (i=0;i sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector)); failureCount += testSymcipher (); failureCount += verifyCrypto (); if (failureCount != 0) { printf ("%d TESTS FAILED!\n", failureCount); return -1; } return 0; } /* end of test_crypto_aes.c */ gnunet-0.10.1/src/util/test_strings.c0000644000175000017500000001177312263473436014475 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_strings.c * @brief testcase for strings.c */ #include "platform.h" #include "gnunet_util_lib.h" #define WANT(a,b) if (0 != strcmp(a,b)) { fprintf(stderr, "Got `%s', wanted `%s'\n", b, a); GNUNET_free(b); GNUNET_break(0); return 1;} else { GNUNET_free (b); } #define WANTNF(a,b) do { if (0 != strcmp(a,b)) { fprintf(stderr, "Got `%s', wanted `%s'\n", b, a); GNUNET_break(0); return 1;} } while (0) #define WANTB(a,b,l) if (0 != memcmp(a,b,l)) { GNUNET_break(0); return 1;} else { } int main (int argc, char *argv[]) { char buf[128]; char *r; char *b; const char *bc; struct GNUNET_TIME_Absolute at; struct GNUNET_TIME_Absolute atx; struct GNUNET_TIME_Relative rt; struct GNUNET_TIME_Relative rtx; const char *hdir; GNUNET_log_setup ("test_strings", "ERROR", NULL); sprintf (buf, "4 %s", _( /* size unit */ "b")); b = GNUNET_STRINGS_byte_size_fancy (4); WANT (buf, b); sprintf (buf, "10 %s", _( /* size unit */ "KiB")); b = GNUNET_STRINGS_byte_size_fancy (10240); WANT (buf, b); sprintf (buf, "10 %s", _( /* size unit */ "TiB")); b = GNUNET_STRINGS_byte_size_fancy (10240LL * 1024LL * 1024LL * 1024LL); WANT (buf, b); sprintf (buf, "4 %s", _( /* time unit */ "ms")); bc = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 4), GNUNET_YES); WANTNF (buf, bc); sprintf (buf, "7 %s", _( /* time unit */ "s")); bc = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 7 * 1000), GNUNET_YES); WANTNF (buf, bc); sprintf (buf, "7 %s", _( /* time unit */ "h")); bc = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 7 * 60 * 60 * 1000), GNUNET_YES); WANTNF (buf, bc); #ifndef MINGW hdir = getenv ("HOME"); #else hdir = getenv ("USERPROFILE"); #endif GNUNET_snprintf (buf, sizeof (buf), "%s%s", hdir, DIR_SEPARATOR_STR); b = GNUNET_STRINGS_filename_expand ("~"); GNUNET_assert (b != NULL); WANT (buf, b); GNUNET_STRINGS_buffer_fill (buf, sizeof (buf), 3, "a", "btx", "c"); WANTB ("a\0btx\0c", buf, 8); if (6 != GNUNET_STRINGS_buffer_tokenize (buf, sizeof (buf), 2, &r, &b)) return 1; r = GNUNET_strdup (r); WANT ("a", r); b = GNUNET_strdup (b); WANT ("btx", b); if (0 != GNUNET_STRINGS_buffer_tokenize (buf, 2, 2, &r, &b)) return 1; at.abs_value_us = 5000000; bc = GNUNET_STRINGS_absolute_time_to_string (at); /* bc should be something like "Wed Dec 31 17:00:05 1969" * where the details of the day and hour depend on the timezone; * however, the "0:05 19" should always be there; hence: */ if (NULL == strstr (bc, "0:05 19")) { FPRINTF (stderr, "Got %s\n", bc); GNUNET_break (0); return 1; } b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "ASCII"); WANT ("TEST", b); at = GNUNET_TIME_UNIT_FOREVER_ABS; bc = GNUNET_STRINGS_absolute_time_to_string (at); GNUNET_assert (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_absolute (bc, &atx)); GNUNET_assert (atx.abs_value_us == at.abs_value_us); at.abs_value_us = 50000000000; bc = GNUNET_STRINGS_absolute_time_to_string (at); GNUNET_assert (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_absolute (bc, &atx)); if (atx.abs_value_us != at.abs_value_us) { #ifdef WINDOWS DWORD tzv; TIME_ZONE_INFORMATION tzi; tzv = GetTimeZoneInformation (&tzi); if (TIME_ZONE_ID_INVALID != tzv) { atx.abs_value_us -= 1000LL * 1000LL * tzi.Bias * 60LL; } if (atx.abs_value_us == at.abs_value_us) fprintf (stderr, "WARNING: GNUNET_STRINGS_fancy_time_to_absolute() miscalculates timezone!\n"); #endif GNUNET_assert (0); } GNUNET_log_skip (2, GNUNET_NO); b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "unknown"); GNUNET_log_skip (0, GNUNET_YES); WANT ("TEST", b); GNUNET_assert (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative ("15m", &rt)); GNUNET_assert (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative ("15 m", &rtx)); GNUNET_assert (rt.rel_value_us == rtx.rel_value_us); return 0; } /* end of test_strings.c */ gnunet-0.10.1/src/util/test_connection_timeout_no_connect.c0000644000175000017500000000451212225777501021105 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_connection_timeout_no_connect.c * @brief tests for connection.c, doing timeout which connect failure */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 13425 static struct GNUNET_CONNECTION_Handle *csock; static struct GNUNET_CONFIGURATION_Handle *cfg; static size_t handle_timeout (void *cls, size_t size, void *buf) { int *ok = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received timeout signal.\n"); GNUNET_assert (size == 0); GNUNET_assert (buf == NULL); *ok = 0; return 0; } static void task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { csock = GNUNET_CONNECTION_create_from_connect (cfg, "localhost", PORT); GNUNET_assert (csock != NULL); GNUNET_assert (NULL != GNUNET_CONNECTION_notify_transmit_ready (csock, 1024, GNUNET_TIME_UNIT_SECONDS, &handle_timeout, cls)); } int main (int argc, char *argv[]) { int ok; GNUNET_log_setup ("test_connection_timeout_no_connect", "WARNING", NULL); ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); GNUNET_SCHEDULER_run (&task_timeout, &ok); GNUNET_CONFIGURATION_destroy (cfg); return ok; } /* end of test_connection_timeout_no_connect.c */ gnunet-0.10.1/src/util/connection.c0000644000175000017500000013364612276375236014113 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/connection.c * @brief TCP connection management * @author Christian Grothoff * * This code is rather complex. Only modify it if you * 1) Have a NEW testcase showing that the new code * is needed and correct * 2) All EXISTING testcases pass with the new code * These rules should apply in general, but for this * module they are VERY, VERY important. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) /** * Transmission handle. There can only be one for each connection. */ struct GNUNET_CONNECTION_TransmitHandle { /** * Function to call if the send buffer has notify_size * bytes available. */ GNUNET_CONNECTION_TransmitReadyNotify notify_ready; /** * Closure for notify_ready. */ void *notify_ready_cls; /** * Our connection handle. */ struct GNUNET_CONNECTION_Handle *connection; /** * Timeout for receiving (in absolute time). */ struct GNUNET_TIME_Absolute transmit_timeout; /** * Task called on timeout. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * At what number of bytes available in the * write buffer should the notify method be called? */ size_t notify_size; }; /** * During connect, we try multiple possible IP addresses * to find out which one might work. */ struct AddressProbe { /** * This is a linked list. */ struct AddressProbe *next; /** * This is a doubly-linked list. */ struct AddressProbe *prev; /** * The address; do not free (allocated at the end of this struct). */ const struct sockaddr *addr; /** * Underlying OS's socket. */ struct GNUNET_NETWORK_Handle *sock; /** * Connection for which we are probing. */ struct GNUNET_CONNECTION_Handle *connection; /** * Lenth of addr. */ socklen_t addrlen; /** * Task waiting for the connection to finish connecting. */ GNUNET_SCHEDULER_TaskIdentifier task; }; /** * @brief handle for a network connection */ struct GNUNET_CONNECTION_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Linked list of sockets we are currently trying out * (during connect). */ struct AddressProbe *ap_head; /** * Linked list of sockets we are currently trying out * (during connect). */ struct AddressProbe *ap_tail; /** * Network address of the other end-point, may be NULL. */ struct sockaddr *addr; /** * Pointer to the hostname if connection was * created using DNS lookup, otherwise NULL. */ char *hostname; /** * Underlying OS's socket, set to NULL after fatal errors. */ struct GNUNET_NETWORK_Handle *sock; /** * Function to call on data received, NULL if no receive is pending. */ GNUNET_CONNECTION_Receiver receiver; /** * Closure for receiver. */ void *receiver_cls; /** * Pointer to our write buffer. */ char *write_buffer; /** * Current size of our write buffer. */ size_t write_buffer_size; /** * Current write-offset in write buffer (where * would we write next). */ size_t write_buffer_off; /** * Current read-offset in write buffer (how many * bytes have already been sent). */ size_t write_buffer_pos; /** * Length of addr. */ socklen_t addrlen; /** * Read task that we may need to wait for. */ GNUNET_SCHEDULER_TaskIdentifier read_task; /** * Write task that we may need to wait for. */ GNUNET_SCHEDULER_TaskIdentifier write_task; /** * Handle to a pending DNS lookup request. */ struct GNUNET_RESOLVER_RequestHandle *dns_active; /** * The handle we return for GNUNET_CONNECTION_notify_transmit_ready. */ struct GNUNET_CONNECTION_TransmitHandle nth; /** * Timeout for receiving (in absolute time). */ struct GNUNET_TIME_Absolute receive_timeout; /** * Maximum number of bytes to read (for receiving). */ size_t max; /** * Port to connect to. */ uint16_t port; /** * When shutdown, do not ever actually close the socket, but * free resources. Only should ever be set if using program * termination as a signal (because only then will the leaked * socket be freed!) */ int8_t persist; /** * Usually 0. Set to 1 if this handle is in used and should * 'GNUNET_CONNECTION_destroy' be called right now, the action needs * to be deferred by setting it to -1. */ int8_t destroy_later; }; /** * Set the persist option on this connection handle. Indicates * that the underlying socket or fd should never really be closed. * Used for indicating process death. * * @param connection the connection to set persistent */ void GNUNET_CONNECTION_persist_ (struct GNUNET_CONNECTION_Handle *connection) { connection->persist = GNUNET_YES; } /** * Disable the "CORK" feature for communication with the given connection, * forcing the OS to immediately flush the buffer on transmission * instead of potentially buffering multiple messages. Essentially * reduces the OS send buffers to zero. * Used to make sure that the last messages sent through the connection * reach the other side before the process is terminated. * * @param connection the connection to make flushing and blocking * @return GNUNET_OK on success */ int GNUNET_CONNECTION_disable_corking (struct GNUNET_CONNECTION_Handle *connection) { return GNUNET_NETWORK_socket_disable_corking (connection->sock); } /** * Create a connection handle by boxing an existing OS socket. The OS * socket should henceforth be no longer used directly. * GNUNET_connection_destroy will close it. * * @param osSocket existing socket to box * @return the boxed connection handle */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_existing (struct GNUNET_NETWORK_Handle *osSocket) { struct GNUNET_CONNECTION_Handle *connection; connection = GNUNET_new (struct GNUNET_CONNECTION_Handle); connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE; connection->write_buffer = GNUNET_malloc (connection->write_buffer_size); connection->sock = osSocket; return connection; } /** * Create a connection handle by accepting on a listen socket. This * function may block if the listen socket has no connection ready. * * @param access function to use to check if access is allowed * @param access_cls closure for access * @param lsock listen socket * @return the connection handle, NULL on error */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access, void *access_cls, struct GNUNET_NETWORK_Handle *lsock) { struct GNUNET_CONNECTION_Handle *connection; char addr[128]; socklen_t addrlen; struct GNUNET_NETWORK_Handle *sock; int aret; struct sockaddr_in *v4; struct sockaddr_in6 *v6; struct sockaddr *sa; void *uaddr; struct GNUNET_CONNECTION_Credentials *gcp; struct GNUNET_CONNECTION_Credentials gc; #ifdef SO_PEERCRED struct ucred uc; socklen_t olen; #endif addrlen = sizeof (addr); sock = GNUNET_NETWORK_socket_accept (lsock, (struct sockaddr *) &addr, &addrlen); if (NULL == sock) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept"); return NULL; } if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t))) { GNUNET_break (0); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); return NULL; } sa = (struct sockaddr *) addr; v6 = (struct sockaddr_in6 *) addr; if ((AF_INET6 == sa->sa_family) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr))) { /* convert to V4 address */ v4 = GNUNET_new (struct sockaddr_in); memset (v4, 0, sizeof (struct sockaddr_in)); v4->sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4->sin_len = (u_char) sizeof (struct sockaddr_in); #endif memcpy (&v4->sin_addr, &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) - sizeof (struct in_addr)], sizeof (struct in_addr)); v4->sin_port = v6->sin6_port; uaddr = v4; addrlen = sizeof (struct sockaddr_in); } else { uaddr = GNUNET_malloc (addrlen); memcpy (uaddr, addr, addrlen); } gcp = NULL; gc.uid = 0; gc.gid = 0; if (AF_UNIX == sa->sa_family) { #if HAVE_GETPEEREID /* most BSDs */ if (0 == getpeereid (GNUNET_NETWORK_get_fd (sock), &gc.uid, &gc.gid)) gcp = &gc; #else #ifdef SO_PEERCRED /* largely traditional GNU/Linux */ olen = sizeof (uc); if ((0 == getsockopt (GNUNET_NETWORK_get_fd (sock), SOL_SOCKET, SO_PEERCRED, &uc, &olen)) && (olen == sizeof (uc))) { gc.uid = uc.uid; gc.gid = uc.gid; gcp = &gc; } #else #if HAVE_GETPEERUCRED /* this is for Solaris 10 */ ucred_t *uc; uc = NULL; if (0 == getpeerucred (GNUNET_NETWORK_get_fd (sock), &uc)) { gc.uid = ucred_geteuid (uc); gc.gid = ucred_getegid (uc); gcp = &gc; } ucred_free (uc); #endif #endif #endif } if ((NULL != access) && (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen)))) { if (GNUNET_NO == aret) LOG (GNUNET_ERROR_TYPE_INFO, _("Access denied to `%s'\n"), GNUNET_a2s (uaddr, addrlen)); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_shutdown (sock, SHUT_RDWR)); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); GNUNET_free (uaddr); return NULL; } connection = GNUNET_new (struct GNUNET_CONNECTION_Handle); connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE; connection->write_buffer = GNUNET_malloc (connection->write_buffer_size); connection->addr = uaddr; connection->addrlen = addrlen; connection->sock = sock; LOG (GNUNET_ERROR_TYPE_INFO, _("Accepting connection from `%s': %p\n"), GNUNET_a2s (uaddr, addrlen), connection); return connection; } /** * Obtain the network address of the other party. * * @param connection the client to get the address for * @param addr where to store the address * @param addrlen where to store the length of the address * @return GNUNET_OK on success */ int GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection, void **addr, size_t * addrlen) { if ((NULL == connection->addr) || (0 == connection->addrlen)) return GNUNET_NO; *addr = GNUNET_malloc (connection->addrlen); memcpy (*addr, connection->addr, connection->addrlen); *addrlen = connection->addrlen; return GNUNET_OK; } /** * Tell the receiver callback that we had an IO error. * * @param connection connection to signal error * @param errcode error code to send */ static void signal_receive_error (struct GNUNET_CONNECTION_Handle *connection, int errcode) { GNUNET_CONNECTION_Receiver receiver; LOG (GNUNET_ERROR_TYPE_DEBUG, "Receive encounters error (%s), connection closed (%p)\n", STRERROR (errcode), connection); GNUNET_assert (NULL != (receiver = connection->receiver)); connection->receiver = NULL; receiver (connection->receiver_cls, NULL, 0, connection->addr, connection->addrlen, errcode); } /** * Tell the receiver callback that a timeout was reached. * * @param connection connection to signal for */ static void signal_receive_timeout (struct GNUNET_CONNECTION_Handle *connection) { GNUNET_CONNECTION_Receiver receiver; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection signals timeout to receiver (%p)!\n", connection); GNUNET_assert (NULL != (receiver = connection->receiver)); connection->receiver = NULL; receiver (connection->receiver_cls, NULL, 0, NULL, 0, 0); } /** * We failed to transmit data to the service, signal the error. * * @param connection handle that had trouble * @param ecode error code (errno) */ static void signal_transmit_error (struct GNUNET_CONNECTION_Handle *connection, int ecode) { GNUNET_CONNECTION_TransmitReadyNotify notify; LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission encounterd error (%s), connection closed (%p)\n", STRERROR (ecode), connection); if (NULL != connection->sock) { GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); connection->sock = NULL; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); } if (GNUNET_SCHEDULER_NO_TASK != connection->read_task) { /* send errors trigger read errors... */ GNUNET_SCHEDULER_cancel (connection->read_task); connection->read_task = GNUNET_SCHEDULER_NO_TASK; signal_receive_timeout (connection); return; } if (NULL == connection->nth.notify_ready) return; /* nobody to tell about it */ notify = connection->nth.notify_ready; connection->nth.notify_ready = NULL; notify (connection->nth.notify_ready_cls, 0, NULL); } /** * We've failed for good to establish a connection (timeout or * no more addresses to try). * * @param connection the connection we tried to establish */ static void connect_fail_continuation (struct GNUNET_CONNECTION_Handle *connection) { LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to establish TCP connection to `%s:%u', no further addresses to try.\n"), connection->hostname, connection->port); GNUNET_break (NULL == connection->ap_head); GNUNET_break (NULL == connection->ap_tail); GNUNET_break (GNUNET_NO == connection->dns_active); GNUNET_break (NULL == connection->sock); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); /* signal errors for jobs that used to wait on the connection */ connection->destroy_later = 1; if (NULL != connection->receiver) signal_receive_error (connection, ECONNREFUSED); if (NULL != connection->nth.notify_ready) { GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; signal_transmit_error (connection, ECONNREFUSED); } if (-1 == connection->destroy_later) { /* do it now */ connection->destroy_later = 0; GNUNET_CONNECTION_destroy (connection); return; } connection->destroy_later = 0; } /** * We are ready to transmit (or got a timeout). * * @param cls our connection handle * @param tc task context describing why we are here */ static void transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * This function is called once we either timeout or have data ready * to read. * * @param cls connection to read from * @param tc scheduler context */ static void receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * We've succeeded in establishing a connection. * * @param connection the connection we tried to establish */ static void connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection to `%s' succeeded! (%p)\n", GNUNET_a2s (connection->addr, connection->addrlen), connection); /* trigger jobs that waited for the connection */ if (NULL != connection->receiver) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection succeeded, starting with receiving data (%p)\n", connection); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->read_task); connection->read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining (connection->receive_timeout), connection->sock, &receive_ready, connection); } if (NULL != connection->nth.notify_ready) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection succeeded, starting with sending data (%p)\n", connection); GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK); GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (connection->write_task == GNUNET_SCHEDULER_NO_TASK); connection->write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining (connection->nth.transmit_timeout), connection->sock, &transmit_ready, connection); } } /** * Scheduler let us know that we're either ready to write on the * socket OR connect timed out. Do the right thing. * * @param cls the "struct AddressProbe*" with the address that we are probing * @param tc success or failure info about the connect attempt. */ static void connect_probe_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct AddressProbe *ap = cls; struct GNUNET_CONNECTION_Handle *connection = ap->connection; struct AddressProbe *pos; int error; socklen_t len; GNUNET_assert (NULL != ap->sock); GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, ap); len = sizeof (error); errno = 0; error = 0; if ((0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) || (GNUNET_OK != GNUNET_NETWORK_socket_getsockopt (ap->sock, SOL_SOCKET, SO_ERROR, &error, &len)) || (0 != error)) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock)); GNUNET_free (ap); if ((NULL == connection->ap_head) && (GNUNET_NO == connection->dns_active)) connect_fail_continuation (connection); return; } GNUNET_assert (NULL == connection->sock); connection->sock = ap->sock; GNUNET_assert (NULL == connection->addr); connection->addr = GNUNET_malloc (ap->addrlen); memcpy (connection->addr, ap->addr, ap->addrlen); connection->addrlen = ap->addrlen; GNUNET_free (ap); /* cancel all other attempts */ while (NULL != (pos = connection->ap_head)) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock)); GNUNET_SCHEDULER_cancel (pos->task); GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos); GNUNET_free (pos); } connect_success_continuation (connection); } /** * Try to establish a connection given the specified address. * This function is called by the resolver once we have a DNS reply. * * @param cls our "struct GNUNET_CONNECTION_Handle *" * @param addr address to try, NULL for "last call" * @param addrlen length of addr */ static void try_connect_using_address (void *cls, const struct sockaddr *addr, socklen_t addrlen) { struct GNUNET_CONNECTION_Handle *connection = cls; struct AddressProbe *ap; struct GNUNET_TIME_Relative delay; if (NULL == addr) { connection->dns_active = NULL; if ((NULL == connection->ap_head) && (NULL == connection->sock)) connect_fail_continuation (connection); return; } if (NULL != connection->sock) return; /* already connected */ GNUNET_assert (NULL == connection->addr); /* try to connect */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to connect using address `%s:%u/%s:%u'\n", connection->hostname, connection->port, GNUNET_a2s (addr, addrlen), connection->port); ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen); ap->addr = (const struct sockaddr *) &ap[1]; memcpy (&ap[1], addr, addrlen); ap->addrlen = addrlen; ap->connection = connection; switch (ap->addr->sa_family) { case AF_INET: ((struct sockaddr_in *) ap->addr)->sin_port = htons (connection->port); break; case AF_INET6: ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (connection->port); break; default: GNUNET_break (0); GNUNET_free (ap); return; /* not supported by us */ } ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family, SOCK_STREAM, 0); if (NULL == ap->sock) { GNUNET_free (ap); return; /* not supported by OS */ } LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"), GNUNET_a2s (ap->addr, ap->addrlen), connection); if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (ap->sock, ap->addr, ap->addrlen)) && (EINPROGRESS != errno)) { /* maybe refused / unsupported address, try next */ LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock)); GNUNET_free (ap); return; } GNUNET_CONTAINER_DLL_insert (connection->ap_head, connection->ap_tail, ap); delay = GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT; if (NULL != connection->nth.notify_ready) delay = GNUNET_TIME_relative_min (delay, GNUNET_TIME_absolute_get_remaining (connection-> nth.transmit_timeout)); if (NULL != connection->receiver) delay = GNUNET_TIME_relative_min (delay, GNUNET_TIME_absolute_get_remaining (connection->receive_timeout)); ap->task = GNUNET_SCHEDULER_add_write_net (delay, ap->sock, &connect_probe_continuation, ap); } /** * Create a connection handle by (asynchronously) connecting to a host. * This function returns immediately, even if the connection has not * yet been established. This function only creates TCP connections. * * @param cfg configuration to use * @param hostname name of the host to connect to * @param port port to connect to * @return the connection handle */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *hostname, uint16_t port) { struct GNUNET_CONNECTION_Handle *connection; GNUNET_assert (0 < strlen (hostname)); /* sanity check */ connection = GNUNET_new (struct GNUNET_CONNECTION_Handle); connection->cfg = cfg; connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE; connection->write_buffer = GNUNET_malloc (connection->write_buffer_size); connection->port = port; connection->hostname = GNUNET_strdup (hostname); connection->dns_active = GNUNET_RESOLVER_ip_get (connection->hostname, AF_UNSPEC, GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT, &try_connect_using_address, connection); return connection; } /** * Create a connection handle by connecting to a UNIX domain service. * This function returns immediately, even if the connection has not * yet been established. This function only creates UNIX connections. * * @param cfg configuration to use * @param unixpath path to connect to * @return the connection handle, NULL on systems without UNIX support */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *unixpath) { #ifdef AF_UNIX struct GNUNET_CONNECTION_Handle *connection; struct sockaddr_un *un; GNUNET_assert (0 < strlen (unixpath)); /* sanity check */ un = GNUNET_new (struct sockaddr_un); un->sun_family = AF_UNIX; strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1); #ifdef LINUX { int abstract; abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg, "TESTING", "USE_ABSTRACT_SOCKETS"); if (GNUNET_YES == abstract) un->sun_path[0] = '\0'; } #endif #if HAVE_SOCKADDR_IN_SIN_LEN un->sun_len = (u_char) sizeof (struct sockaddr_un); #endif connection = GNUNET_new (struct GNUNET_CONNECTION_Handle); connection->cfg = cfg; connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE; connection->write_buffer = GNUNET_malloc (connection->write_buffer_size); connection->port = 0; connection->hostname = NULL; connection->addr = (struct sockaddr *) un; connection->addrlen = sizeof (struct sockaddr_un); connection->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); if (NULL == connection->sock) { GNUNET_free (connection->addr); GNUNET_free (connection->write_buffer); GNUNET_free (connection); return NULL; } if ( (GNUNET_OK != GNUNET_NETWORK_socket_connect (connection->sock, connection->addr, connection->addrlen)) && (EINPROGRESS != errno) ) { /* Just return; we expect everything to work eventually so don't fail HARD */ GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); connection->sock = NULL; return connection; } connect_success_continuation (connection); return connection; #else return NULL; #endif } /** * Create a connection handle by (asynchronously) connecting to a host. * This function returns immediately, even if the connection has not * yet been established. This function only creates TCP connections. * * @param af_family address family to use * @param serv_addr server address * @param addrlen length of server address * @return the connection handle */ struct GNUNET_CONNECTION_Handle * GNUNET_CONNECTION_create_from_sockaddr (int af_family, const struct sockaddr *serv_addr, socklen_t addrlen) { struct GNUNET_NETWORK_Handle *s; struct GNUNET_CONNECTION_Handle *connection; s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0); if (NULL == s) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "socket"); return NULL; } if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen)) && (EINPROGRESS != errno)) { /* maybe refused / unsupported address, try next */ LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); LOG (GNUNET_ERROR_TYPE_INFO, _("Attempt to connect to `%s' failed\n"), GNUNET_a2s (serv_addr, addrlen)); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s)); return NULL; } connection = GNUNET_CONNECTION_create_from_existing (s); connection->addr = GNUNET_malloc (addrlen); memcpy (connection->addr, serv_addr, addrlen); connection->addrlen = addrlen; LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"), GNUNET_a2s (serv_addr, addrlen), connection); return connection; } /** * Check if connection is valid (no fatal errors have happened so far). * Note that a connection that is still trying to connect is considered * valid. * * @param connection connection to check * @return GNUNET_YES if valid, GNUNET_NO otherwise */ int GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *connection) { if ((NULL != connection->ap_head) || (NULL != connection->dns_active)) return GNUNET_YES; /* still trying to connect */ return (NULL == connection->sock) ? GNUNET_NO : GNUNET_YES; } /** * Close the connection and free associated resources. There must * not be any pending requests for reading or writing to the * connection at this time. * * @param connection connection to destroy */ void GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) { struct AddressProbe *pos; if (0 != connection->destroy_later) { connection->destroy_later = -1; return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection); GNUNET_assert (NULL == connection->nth.notify_ready); GNUNET_assert (NULL == connection->receiver); if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) { GNUNET_SCHEDULER_cancel (connection->write_task); connection->write_task = GNUNET_SCHEDULER_NO_TASK; connection->write_buffer_off = 0; } if (GNUNET_SCHEDULER_NO_TASK != connection->read_task) { GNUNET_SCHEDULER_cancel (connection->read_task); connection->read_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != connection->nth.timeout_task) { GNUNET_SCHEDULER_cancel (connection->nth.timeout_task); connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; } connection->nth.notify_ready = NULL; if (NULL != connection->dns_active) { GNUNET_RESOLVER_request_cancel (connection->dns_active); connection->dns_active = NULL; } while (NULL != (pos = connection->ap_head)) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock)); GNUNET_SCHEDULER_cancel (pos->task); GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos); GNUNET_free (pos); } if ( (NULL != connection->sock) && (GNUNET_YES != connection->persist) ) { if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) && (ENOTCONN != errno) && (ECONNRESET != errno) ) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown"); } if (NULL != connection->sock) { if (GNUNET_YES != connection->persist) GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); else { GNUNET_NETWORK_socket_free_memory_only_ (connection->sock); /* at least no memory leak (we deliberately * leak the socket in this special case) ... */ } } GNUNET_free_non_null (connection->addr); GNUNET_free_non_null (connection->hostname); GNUNET_free (connection->write_buffer); GNUNET_free (connection); } /** * This function is called once we either timeout * or have data ready to read. * * @param cls connection to read from * @param tc scheduler context */ static void receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CONNECTION_Handle *connection = cls; char buffer[connection->max]; ssize_t ret; GNUNET_CONNECTION_Receiver receiver; connection->read_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* ignore shutdown request, go again immediately */ connection->read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining (connection->receive_timeout), connection->sock, &receive_ready, connection); return; } if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Receive from `%s' encounters error: timeout (%s, %p)\n", GNUNET_a2s (connection->addr, connection->addrlen), GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (connection->receive_timeout), GNUNET_YES), connection); signal_receive_timeout (connection); return; } if (NULL == connection->sock) { /* connect failed for good */ signal_receive_error (connection, ECONNREFUSED); return; } GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, connection->sock)); RETRY: ret = GNUNET_NETWORK_socket_recv (connection->sock, buffer, connection->max); if (-1 == ret) { if (EINTR == errno) goto RETRY; signal_receive_error (connection, errno); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "receive_ready read %u/%u bytes from `%s' (%p)!\n", (unsigned int) ret, connection->max, GNUNET_a2s (connection->addr, connection->addrlen), connection); GNUNET_assert (NULL != (receiver = connection->receiver)); connection->receiver = NULL; receiver (connection->receiver_cls, buffer, ret, connection->addr, connection->addrlen, 0); } /** * Receive data from the given connection. Note that this function will * call "receiver" asynchronously using the scheduler. It will * "immediately" return. Note that there MUST only be one active * receive call per connection at any given point in time (so do not * call receive again until the receiver callback has been invoked). * * @param connection connection handle * @param max maximum number of bytes to read * @param timeout maximum amount of time to wait * @param receiver function to call with received data * @param receiver_cls closure for receiver */ void GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection, size_t max, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_Receiver receiver, void *receiver_cls) { GNUNET_assert ((GNUNET_SCHEDULER_NO_TASK == connection->read_task) && (NULL == connection->receiver)); GNUNET_assert (NULL != receiver); connection->receiver = receiver; connection->receiver_cls = receiver_cls; connection->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); connection->max = max; if (NULL != connection->sock) { connection->read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining (connection->receive_timeout), connection->sock, &receive_ready, connection); return; } if ((NULL == connection->dns_active) && (NULL == connection->ap_head)) { connection->receiver = NULL; receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT); return; } } /** * Cancel receive job on the given connection. Note that the * receiver callback must not have been called yet in order * for the cancellation to be valid. * * @param connection connection handle * @return closure of the original receiver callback closure */ void * GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *connection) { if (GNUNET_SCHEDULER_NO_TASK != connection->read_task) { GNUNET_assert (connection == GNUNET_SCHEDULER_cancel (connection->read_task)); connection->read_task = GNUNET_SCHEDULER_NO_TASK; } connection->receiver = NULL; return connection->receiver_cls; } /** * Try to call the transmit notify method (check if we do * have enough space available first)! * * @param connection connection for which we should do this processing * @return GNUNET_YES if we were able to call notify */ static int process_notify (struct GNUNET_CONNECTION_Handle *connection) { size_t used; size_t avail; size_t size; GNUNET_CONNECTION_TransmitReadyNotify notify; LOG (GNUNET_ERROR_TYPE_DEBUG, "process_notify is running\n"); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); if (NULL == (notify = connection->nth.notify_ready)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Noone to notify\n"); return GNUNET_NO; } used = connection->write_buffer_off - connection->write_buffer_pos; avail = connection->write_buffer_size - used; size = connection->nth.notify_size; if (size > avail) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Not enough buffer\n"); return GNUNET_NO; } connection->nth.notify_ready = NULL; if (connection->write_buffer_size - connection->write_buffer_off < size) { /* need to compact */ memmove (connection->write_buffer, &connection->write_buffer[connection->write_buffer_pos], used); connection->write_buffer_off -= connection->write_buffer_pos; connection->write_buffer_pos = 0; } avail = connection->write_buffer_size - connection->write_buffer_off; GNUNET_assert (avail >= size); size = notify (connection->nth.notify_ready_cls, avail, &connection->write_buffer[connection->write_buffer_off]); GNUNET_assert (size <= avail); if (0 != size) connection->write_buffer_off += size; return GNUNET_YES; } /** * Task invoked by the scheduler when a call to transmit * is timing out (we never got enough buffer space to call * the callback function before the specified timeout * expired). * * This task notifies the client about the timeout. * * @param cls the 'struct GNUNET_CONNECTION_Handle' * @param tc scheduler context */ static void transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CONNECTION_Handle *connection = cls; GNUNET_CONNECTION_TransmitReadyNotify notify; connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmit to `%s:%u/%s' fails, time out reached (%p).\n", connection->hostname, connection->port, GNUNET_a2s (connection->addr, connection->addrlen), connection); notify = connection->nth.notify_ready; GNUNET_assert (NULL != notify); connection->nth.notify_ready = NULL; notify (connection->nth.notify_ready_cls, 0, NULL); } /** * Task invoked by the scheduler when we failed to connect * at the time of being asked to transmit. * * This task notifies the client about the error. * * @param cls the 'struct GNUNET_CONNECTION_Handle' * @param tc scheduler context */ static void connect_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CONNECTION_Handle *connection = cls; GNUNET_CONNECTION_TransmitReadyNotify notify; LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission request of size %u fails (%s/%u), connection failed (%p).\n", connection->nth.notify_size, connection->hostname, connection->port, connection); connection->write_task = GNUNET_SCHEDULER_NO_TASK; notify = connection->nth.notify_ready; connection->nth.notify_ready = NULL; notify (connection->nth.notify_ready_cls, 0, NULL); } /** * We are ready to transmit (or got a timeout). * * @param cls our connection handle * @param tc task context describing why we are here */ static void transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CONNECTION_Handle *connection = cls; GNUNET_CONNECTION_TransmitReadyNotify notify; ssize_t ret; size_t have; LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_ready running (%p).\n", connection); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != connection->write_task); connection->write_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task); if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { if (NULL != connection->sock) goto SCHEDULE_WRITE; /* ignore shutdown, go again immediately */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmit to `%s' fails, shutdown happened (%p).\n", GNUNET_a2s (connection->addr, connection->addrlen), connection); notify = connection->nth.notify_ready; if (NULL != notify) { connection->nth.notify_ready = NULL; notify (connection->nth.notify_ready_cls, 0, NULL); } return; } if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmit to `%s' fails, time out reached (%p).\n", GNUNET_a2s (connection->addr, connection->addrlen), connection); notify = connection->nth.notify_ready; GNUNET_assert (NULL != notify); connection->nth.notify_ready = NULL; notify (connection->nth.notify_ready_cls, 0, NULL); return; } GNUNET_assert (NULL != connection->sock); if (NULL == tc->write_ready) { /* special circumstances (in particular, PREREQ_DONE after * connect): not yet ready to write, but no "fatal" error either. * Hence retry. */ goto SCHEDULE_WRITE; } if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, connection->sock)) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); /* special circumstances (in particular, shutdown): not yet ready * to write, but no "fatal" error either. Hence retry. */ goto SCHEDULE_WRITE; } GNUNET_assert (connection->write_buffer_off >= connection->write_buffer_pos); if ((NULL != connection->nth.notify_ready) && (connection->write_buffer_size < connection->nth.notify_size)) { connection->write_buffer = GNUNET_realloc (connection->write_buffer, connection->nth.notify_size); connection->write_buffer_size = connection->nth.notify_size; } process_notify (connection); have = connection->write_buffer_off - connection->write_buffer_pos; if (0 == have) { /* no data ready for writing, terminate write loop */ return; } GNUNET_assert (have <= connection->write_buffer_size); GNUNET_assert (have + connection->write_buffer_pos <= connection->write_buffer_size); GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size); RETRY: ret = GNUNET_NETWORK_socket_send (connection->sock, &connection->write_buffer[connection->write_buffer_pos], have); if (-1 == ret) { if (EINTR == errno) goto RETRY; if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) { GNUNET_SCHEDULER_cancel (connection->write_task); connection->write_task = GNUNET_SCHEDULER_NO_TASK; } signal_transmit_error (connection, errno); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection transmitted %u/%u bytes to `%s' (%p)\n", (unsigned int) ret, have, GNUNET_a2s (connection->addr, connection->addrlen), connection); connection->write_buffer_pos += ret; if (connection->write_buffer_pos == connection->write_buffer_off) { /* transmitted all pending data */ connection->write_buffer_pos = 0; connection->write_buffer_off = 0; } if ((0 == connection->write_buffer_off) && (NULL == connection->nth.notify_ready)) return; /* all data sent! */ /* not done writing, schedule more */ SCHEDULE_WRITE: LOG (GNUNET_ERROR_TYPE_DEBUG, "Re-scheduling transmit_ready (more to do) (%p).\n", connection); have = connection->write_buffer_off - connection->write_buffer_pos; GNUNET_assert ((NULL != connection->nth.notify_ready) || (have > 0)); if (GNUNET_SCHEDULER_NO_TASK == connection->write_task) connection->write_task = GNUNET_SCHEDULER_add_write_net ((connection->nth.notify_ready == NULL) ? GNUNET_TIME_UNIT_FOREVER_REL : GNUNET_TIME_absolute_get_remaining (connection->nth.transmit_timeout), connection->sock, &transmit_ready, connection); } /** * Ask the connection to call us once the specified number of bytes * are free in the transmission buffer. May call the notify * method immediately if enough space is available. * * @param connection connection * @param size number of bytes to send * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param notify function to call * @param notify_cls closure for notify * @return non-NULL if the notify callback was queued, * NULL if we are already going to notify someone else (busy) */ struct GNUNET_CONNECTION_TransmitHandle * GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connection, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { if (NULL != connection->nth.notify_ready) { GNUNET_assert (0); return NULL; } GNUNET_assert (NULL != notify); GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); GNUNET_assert (connection->write_buffer_off <= connection->write_buffer_size); GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size); GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_off); connection->nth.notify_ready = notify; connection->nth.notify_ready_cls = notify_cls; connection->nth.connection = connection; connection->nth.notify_size = size; connection->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task); if ((NULL == connection->sock) && (NULL == connection->ap_head) && (NULL == connection->dns_active)) { if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) GNUNET_SCHEDULER_cancel (connection->write_task); connection->write_task = GNUNET_SCHEDULER_add_now (&connect_error, connection); return &connection->nth; } if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) return &connection->nth; /* previous transmission still in progress */ if (NULL != connection->sock) { /* connected, try to transmit now */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling transmission (%p).\n", connection); connection->write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining (connection->nth.transmit_timeout), connection->sock, &transmit_ready, connection); return &connection->nth; } /* not yet connected, wait for connection */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Need to wait to schedule transmission for connection, adding timeout task (%p).\n", connection); connection->nth.timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &transmit_timeout, connection); return &connection->nth; } /** * Cancel the specified transmission-ready notification. * * @param th notification to cancel */ void GNUNET_CONNECTION_notify_transmit_ready_cancel (struct GNUNET_CONNECTION_TransmitHandle *th) { GNUNET_assert (NULL != th->notify_ready); th->notify_ready = NULL; if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task) { GNUNET_SCHEDULER_cancel (th->timeout_task); th->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != th->connection->write_task) { GNUNET_SCHEDULER_cancel (th->connection->write_task); th->connection->write_task = GNUNET_SCHEDULER_NO_TASK; } } /* end of connection.c */ gnunet-0.10.1/src/util/gnunet-qr.py.in0000755000175000017500000000523112255055174014467 00000000000000#!@PYTHON@ import sys import getopt import subprocess from sys import argv try: import zbar except ImportError as e: print 'Cannot run gnunet-qr, please install zbar-python' sys.exit (1) def help (): print 'gnunet-qr\n\ Scan a QR code using a video device and import\n\ Arguments mandatory for long options are also mandatory for short options.\n\ -c, --config=FILENAME use configuration file FILENAME\n\ -d, --device=DEVICE use device DEVICE\n\ -s, --silent do not show preview windows\n\ -h, --help print this help\n\ -v, --verbose be verbose\n\ Report bugs to gnunet-developers@gnu.org.\n\ GNUnet home page: http://www.gnu.org/software/gnunet/\n\ General help using GNU software: http://www.gnu.org/gethelp/' if __name__ == '__main__': configuration = '' device = '/dev/video0' url = '' verbose = False silent = False # Parse arguments try: opts, args = getopt.gnu_getopt(sys.argv[1:], "c:hd:sv", ["config","help", "device","silent","verbose"]) except getopt.GetoptError as e: help () print str (e) exit (1) for o,a in opts: if o in ("-h", "--help"): help () sys.exit (0) elif o in ("-c", "--config"): configuration = a elif o in ("-d", "--device"): device = a elif o in ("-s", "--silent"): silent = True elif o in ("-v", "--verbose"): verbose = True if (True == verbose): print 'Initializing' # create a Processor proc = zbar.Processor() # configure the Processor proc.parse_config('enable') # initialize the Processor try: if (True == verbose): print 'Opening video device ' + device proc.init(device) except Exception as e: print 'Failed to open device ' + device exit (1) # enable the preview window #if (True == silent): # proc.visible = True #else: # proc.visible = False proc.visible = True # read at least one barcode (or until window closed) try: if (True == verbose): print 'Capturing' proc.process_one() except Exception as e: # Window was closed without finding code exit (1) # hide the preview window proc.visible = False # extract results for symbol in proc.results: # do something useful with results if (True == verbose): print 'Found ', symbol.type, ' symbol ', '"%s"' % symbol.data args = list() args.append("gnunet-uri") if (configuration != ''): args.append (str("-c " + str(configuration))) args.append (str(symbol.data)) cmd = '' for a in args: cmd += " " + str(a) if (verbose): print 'Running `' + cmd +'`' res=subprocess.call(args) if (0 != res): print 'Failed to add URI ' + str(symbol.data) else: print 'Added URI ' + str(symbol.data) exit (res) exit (1) gnunet-0.10.1/src/util/plugin.c0000644000175000017500000002147312252137227013232 00000000000000/* This file is part of GNUnet (C) 2002-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/plugin.c * @brief Methods to access plugins * @author Christian Grothoff */ #include "platform.h" #include #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Linked list of active plugins. */ struct PluginList { /** * This is a linked list. */ struct PluginList *next; /** * Name of the library. */ char *name; /** * System handle. */ void *handle; }; /** * Have we been initialized? */ static int initialized; /** * Libtool search path before we started. */ static char *old_dlsearchpath; /** * List of plugins we have loaded. */ static struct PluginList *plugins; /** * Setup libtool paths. */ static void plugin_init () { int err; const char *opath; char *path; char *cpath; err = lt_dlinit (); if (err > 0) { FPRINTF (stderr, _("Initialization of plugin mechanism failed: %s!\n"), lt_dlerror ()); return; } opath = lt_dlgetsearchpath (); if (opath != NULL) old_dlsearchpath = GNUNET_strdup (opath); path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); if (path != NULL) { if (opath != NULL) { GNUNET_asprintf (&cpath, "%s:%s", opath, path); lt_dlsetsearchpath (cpath); GNUNET_free (path); GNUNET_free (cpath); } else { lt_dlsetsearchpath (path); GNUNET_free (path); } } } /** * Shutdown libtool. */ static void plugin_fini () { lt_dlsetsearchpath (old_dlsearchpath); if (old_dlsearchpath != NULL) { GNUNET_free (old_dlsearchpath); old_dlsearchpath = NULL; } lt_dlexit (); } /** * Lookup a function in the plugin. * * @param plug the plugin to check * @param name name of the symbol to look for * @return NULL if the symbol was not found */ static GNUNET_PLUGIN_Callback resolve_function (struct PluginList *plug, const char *name) { char *initName; void *mptr; GNUNET_asprintf (&initName, "_%s_%s", plug->name, name); mptr = lt_dlsym (plug->handle, &initName[1]); if (NULL == mptr) mptr = lt_dlsym (plug->handle, initName); if (NULL == mptr) LOG (GNUNET_ERROR_TYPE_ERROR, _("`%s' failed to resolve method '%s' with error: %s\n"), "lt_dlsym", &initName[1], lt_dlerror ()); GNUNET_free (initName); return mptr; } /** * Test if a plugin exists. * * Note that the library must export a symbol called * `library_name_init` for the test to succeed. * * @param library_name name of the plugin to test if it is installed * @return #GNUNET_YES if the plugin exists, #GNUNET_NO if not */ int GNUNET_PLUGIN_test (const char *library_name) { void *libhandle; GNUNET_PLUGIN_Callback init; struct PluginList plug; if (! initialized) { initialized = GNUNET_YES; plugin_init (); } libhandle = lt_dlopenext (library_name); if (NULL == libhandle) return GNUNET_NO; plug.handle = libhandle; plug.name = (char *) library_name; init = resolve_function (&plug, "init"); if (NULL == init) { GNUNET_break (0); lt_dlclose (libhandle); return GNUNET_NO; } lt_dlclose (libhandle); return GNUNET_YES; } /** * Setup plugin (runs the `init` callback and returns whatever `init` * returned). If `init` returns NULL, the plugin is unloaded. * * Note that the library must export symbols called * `library_name_init` and `library_name_done`. These will be called * when the library is loaded and unloaded respectively. * * @param library_name name of the plugin to load * @param arg argument to the plugin initialization function * @return whatever the initialization function returned */ void * GNUNET_PLUGIN_load (const char *library_name, void *arg) { void *libhandle; struct PluginList *plug; GNUNET_PLUGIN_Callback init; void *ret; if (!initialized) { initialized = GNUNET_YES; plugin_init (); } libhandle = lt_dlopenext (library_name); if (libhandle == NULL) { LOG (GNUNET_ERROR_TYPE_ERROR, _("`%s' failed for library `%s' with error: %s\n"), "lt_dlopenext", library_name, lt_dlerror ()); return NULL; } plug = GNUNET_new (struct PluginList); plug->handle = libhandle; plug->name = GNUNET_strdup (library_name); plug->next = plugins; plugins = plug; init = resolve_function (plug, "init"); if ((init == NULL) || (NULL == (ret = init (arg)))) { lt_dlclose (libhandle); GNUNET_free (plug->name); plugins = plug->next; GNUNET_free (plug); return NULL; } return ret; } /** * Unload plugin (runs the `done` callback and returns whatever `done` * returned). The plugin is then unloaded. * * @param library_name name of the plugin to unload * @param arg argument to the plugin shutdown function * @return whatever the shutdown function returned */ void * GNUNET_PLUGIN_unload (const char *library_name, void *arg) { struct PluginList *pos; struct PluginList *prev; GNUNET_PLUGIN_Callback done; void *ret; prev = NULL; pos = plugins; while ((NULL != pos) && (0 != strcmp (pos->name, library_name))) { prev = pos; pos = pos->next; } if (NULL == pos) return NULL; done = resolve_function (pos, "done"); ret = NULL; if (NULL != done) ret = done (arg); if (NULL == prev) plugins = pos->next; else prev->next = pos->next; lt_dlclose (pos->handle); GNUNET_free (pos->name); GNUNET_free (pos); if (NULL == plugins) { plugin_fini (); initialized = GNUNET_NO; } return ret; } /** * Closure for #find_libraries(). */ struct LoadAllContext { /** * Prefix the plugin names we find have to match. */ const char *basename; /** * Argument to give to 'init' when loading the plugin. */ void *arg; /** * Function to call for each plugin. */ GNUNET_PLUGIN_LoaderCallback cb; /** * Closure for @e cb */ void *cb_cls; }; /** * Function called on each plugin in the directory. Loads * the plugins that match the given basename. * * @param cls the `struct LoadAllContext` describing which * plugins to load and what to do with them * @param filename name of a plugin library to check * @return #GNUNET_OK (continue loading) */ static int find_libraries (void *cls, const char *filename) { struct LoadAllContext *lac = cls; const char *slashpos; const char *libname; char *basename; char *dot; void *lib_ret; size_t n; libname = filename; while (NULL != (slashpos = strstr (libname, DIR_SEPARATOR_STR))) libname = slashpos + 1; n = strlen (libname); if (0 != strncmp (lac->basename, libname, strlen (lac->basename))) return GNUNET_OK; /* wrong name */ if ((n > 3) && (0 == strcmp (&libname[n - 3], ".la"))) return GNUNET_OK; /* .la file */ basename = GNUNET_strdup (libname); if (NULL != (dot = strstr (basename, "."))) *dot = '\0'; lib_ret = GNUNET_PLUGIN_load (basename, lac->arg); if (NULL != lib_ret) lac->cb (lac->cb_cls, basename, lib_ret); GNUNET_free (basename); return GNUNET_OK; } /** * Load all compatible plugins with the given base name. * * Note that the library must export symbols called * `basename_ANYTHING_init` and `basename_ANYTHING__done`. These will * be called when the library is loaded and unloaded respectively. * * @param basename basename of the plugins to load * @param arg argument to the plugin initialization function * @param cb function to call for each plugin found * @param cb_cls closure for @a cb */ void GNUNET_PLUGIN_load_all (const char *basename, void *arg, GNUNET_PLUGIN_LoaderCallback cb, void *cb_cls) { struct LoadAllContext lac; char *path; path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); if (NULL == path) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not determine plugin installation path.\n")); return; } lac.basename = basename; lac.arg = arg; lac.cb = cb; lac.cb_cls = cb_cls; GNUNET_DISK_directory_scan (path, &find_libraries, &lac); GNUNET_free (path); } /* end of plugin.c */ gnunet-0.10.1/src/util/test_container_multihashmap32.c0000644000175000017500000001032112225777501017671 00000000000000/* This file is part of GNUnet. (C) 2008 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_container_multihashmap32.c * @brief Test for container_multihashmap32.c * @author Christian Grothoff * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); if (m != NULL) GNUNET_CONTAINER_multihashmap32_destroy(m); return 1; } #define CHECK(c) { if (! (c)) ABORT(); } static int testMap (int i) { struct GNUNET_CONTAINER_MultiHashMap32 *m; uint32_t k1; uint32_t k2; const char *ret; int j; CHECK (NULL != (m = GNUNET_CONTAINER_multihashmap32_create (i))); k1 = 0; k2 = UINT32_MAX; CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap32_contains (m, k1)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap32_contains (m, k2)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap32_remove (m, k1, NULL)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap32_remove (m, k2, NULL)); CHECK (NULL == GNUNET_CONTAINER_multihashmap32_get (m, k1)); CHECK (NULL == GNUNET_CONTAINER_multihashmap32_get (m, k2)); CHECK (0 == GNUNET_CONTAINER_multihashmap32_remove_all (m, k1)); CHECK (0 == GNUNET_CONTAINER_multihashmap32_size (m)); CHECK (0 == GNUNET_CONTAINER_multihashmap32_iterate (m, NULL, NULL)); CHECK (0 == GNUNET_CONTAINER_multihashmap32_get_multiple (m, k1, NULL, NULL)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (m, k1, "v1", GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); CHECK (1 == GNUNET_CONTAINER_multihashmap32_size (m)); ret = GNUNET_CONTAINER_multihashmap32_get (m, k1); GNUNET_assert (ret != NULL); CHECK (0 == strcmp ("v1", ret)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap32_put (m, k1, "v1", GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); CHECK (1 == GNUNET_CONTAINER_multihashmap32_size (m)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (m, k1, "v2", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (m, k1, "v3", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); CHECK (3 == GNUNET_CONTAINER_multihashmap32_size (m)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_remove (m, k1, "v3")); CHECK (2 == GNUNET_CONTAINER_multihashmap32_size (m)); CHECK (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_contains (m, k1)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap32_contains (m, k2)); CHECK (2 == GNUNET_CONTAINER_multihashmap32_get_multiple (m, k1, NULL, NULL)); CHECK (0 == GNUNET_CONTAINER_multihashmap32_get_multiple (m, k2, NULL, NULL)); CHECK (2 == GNUNET_CONTAINER_multihashmap32_iterate (m, NULL, NULL)); CHECK (2 == GNUNET_CONTAINER_multihashmap32_remove_all (m, k1)); for (j = 0; j < 1024; j++) CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (m, k1, "v2", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); GNUNET_CONTAINER_multihashmap32_destroy (m); return 0; } int main (int argc, char *argv[]) { int failureCount = 0; int i; GNUNET_log_setup ("test-container-multihashmap", "WARNING", NULL); for (i = 1; i < 255; i++) failureCount += testMap (i); if (failureCount != 0) return 1; return 0; } /* end of test_container_multihashmap.c */ gnunet-0.10.1/src/util/test_scheduler_delay.c0000644000175000017500000000545712225777501016140 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_scheduler_delay.c * @brief testcase for delay of scheduler, measures how * precise the timers are. Expect values between 0.2 and 2 ms on * modern machines. */ #include "platform.h" #include "gnunet_util_lib.h" static struct GNUNET_TIME_Absolute target; static int i; static unsigned long long cumDelta; #define INCR 47 #define MAXV 5000 /** * Signature of the main function of a task. * * @param cls closure * @param tc context */ static void test_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Absolute now; now = GNUNET_TIME_absolute_get (); if (now.abs_value_us > target.abs_value_us) cumDelta += (now.abs_value_us - target.abs_value_us); else cumDelta += (target.abs_value_us - now.abs_value_us); target = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, i)); FPRINTF (stderr, "%s", "."); if (i > MAXV) { FPRINTF (stderr, "%s", "\n"); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, i), &test_task, NULL); i += INCR; } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-scheduler-delay", "WARNING", NULL); target = GNUNET_TIME_absolute_get (); GNUNET_SCHEDULER_run (&test_task, NULL); FPRINTF (stdout, "Sleep precision: %llu microseconds (average delta). ", cumDelta / (MAXV / INCR)); if (cumDelta <= 500 * MAXV / INCR) FPRINTF (stdout, "%s", "Timer precision is excellent.\n"); else if (cumDelta <= 5000 * MAXV / INCR) /* 5 ms average deviation */ FPRINTF (stdout, "%s", "Timer precision is good.\n"); else if (cumDelta > 25000 * MAXV / INCR) FPRINTF (stdout, "%s", "Timer precision is awful.\n"); else FPRINTF (stdout, "%s", "Timer precision is acceptable.\n"); return 0; } /* end of test_scheduler_delay.c */ gnunet-0.10.1/src/util/test_client.c0000644000175000017500000001363412255010512014237 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_client.c * @brief tests for client.c */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 14325 #define MYNAME "test_client" static struct GNUNET_CLIENT_Connection *client; static struct GNUNET_SERVER_Handle *server; static struct GNUNET_CONFIGURATION_Handle *cfg; #define MY_TYPE 130 struct CopyContext { struct GNUNET_SERVER_Client *client; struct GNUNET_MessageHeader *cpy; }; static size_t copy_msg (void *cls, size_t size, void *buf) { struct CopyContext *ctx = cls; struct GNUNET_MessageHeader *cpy = ctx->cpy; GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (cpy->size)); GNUNET_assert (size >= ntohs (cpy->size)); memcpy (buf, cpy, ntohs (cpy->size)); GNUNET_SERVER_receive_done (ctx->client, GNUNET_OK); GNUNET_free (cpy); GNUNET_free (ctx); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message bounced back to client\n"); return sizeof (struct GNUNET_MessageHeader); } /** * Callback that just bounces the message back to the sender. */ static void echo_cb (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct CopyContext *cc; struct GNUNET_MessageHeader *cpy; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message from client, bouncing back\n"); GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size)); cc = GNUNET_new (struct CopyContext); cc->client = client; cpy = GNUNET_malloc (ntohs (message->size)); memcpy (cpy, message, ntohs (message->size)); cc->cpy = cpy; GNUNET_assert (NULL != GNUNET_SERVER_notify_transmit_ready (client, ntohs (message->size), GNUNET_TIME_UNIT_SECONDS, ©_msg, cc)); } static struct GNUNET_SERVER_MessageHandler handlers[] = { {&echo_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; static void recv_bounce (void *cls, const struct GNUNET_MessageHeader *got) { int *ok = cls; struct GNUNET_MessageHeader msg; GNUNET_assert (got != NULL); /* timeout */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving bounce, checking content\n"); msg.type = htons (MY_TYPE); msg.size = htons (sizeof (struct GNUNET_MessageHeader)); GNUNET_assert (0 == memcmp (got, &msg, sizeof (struct GNUNET_MessageHeader))); GNUNET_CLIENT_disconnect (client); client = NULL; GNUNET_SERVER_destroy (server); server = NULL; *ok = 0; } static size_t make_msg (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg = buf; GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); msg->type = htons (MY_TYPE); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating message for transmission\n"); return sizeof (struct GNUNET_MessageHeader); } static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_in sa; struct sockaddr *sap[2]; socklen_t slens[2]; /* test that ill-configured client fails instantly */ GNUNET_assert (NULL == GNUNET_CLIENT_connect ("invalid-service", cfg)); /* test IPC between client and server */ sap[0] = (struct sockaddr *) &sa; slens[0] = sizeof (sa); sap[1] = NULL; slens[1] = 0; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); server = GNUNET_SERVER_create (NULL, NULL, sap, slens, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10000), GNUNET_NO); GNUNET_assert (server != NULL); handlers[0].callback_cls = cls; handlers[1].callback_cls = cls; GNUNET_SERVER_add_handlers (server, handlers); client = GNUNET_CLIENT_connect (MYNAME, cfg); GNUNET_assert (client != NULL); GNUNET_assert (NULL != GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_SECONDS, GNUNET_NO, &make_msg, NULL)); GNUNET_CLIENT_receive (client, &recv_bounce, cls, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10000)); } int main (int argc, char *argv[]) { int ok; GNUNET_log_setup ("test_client", "WARNING", NULL); cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_number (cfg, MYNAME, "PORT", PORT); GNUNET_CONFIGURATION_set_value_string (cfg, MYNAME, "HOSTNAME", "localhost"); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); ok = 1; GNUNET_SCHEDULER_run (&task, &ok); GNUNET_CONFIGURATION_destroy (cfg); return ok; } /* end of test_client.c */ gnunet-0.10.1/src/util/test_server_disconnect.c0000644000175000017500000001147612225777501016521 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_server_disconnect.c * @brief tests for server.c, specifically GNUNET_SERVER_client_disconnect */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 12435 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) #define MY_TYPE 128 static struct GNUNET_SERVER_Handle *server; static struct GNUNET_CLIENT_Connection *cc; static struct GNUNET_CONFIGURATION_Handle *cfg; static int ok; static void finish_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_assert (ok == 5); ok = 0; GNUNET_SERVER_destroy (server); GNUNET_CLIENT_disconnect (cc); GNUNET_CONFIGURATION_destroy (cfg); } static void notify_disconnect (void *cls, struct GNUNET_SERVER_Client *clientarg) { if (clientarg == NULL) return; GNUNET_assert (ok == 4); ok = 5; GNUNET_SCHEDULER_add_now (&finish_up, NULL); } static void server_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVER_Client *argclient = cls; GNUNET_assert (ok == 3); ok = 4; GNUNET_SERVER_client_disconnect (argclient); GNUNET_SERVER_client_drop (argclient); } static void recv_cb (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_assert (ok == 2); ok = 3; GNUNET_SERVER_client_keep (client); GNUNET_SCHEDULER_add_now (&server_disconnect, client); GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size)); GNUNET_assert (MY_TYPE == ntohs (message->type)); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static struct GNUNET_SERVER_MessageHandler handlers[] = { {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; static size_t transmit_initial_message (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader msg; GNUNET_assert (ok == 1); ok = 2; GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); msg.type = htons (MY_TYPE); msg.size = htons (sizeof (struct GNUNET_MessageHeader)); memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader)); return sizeof (struct GNUNET_MessageHeader); } static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_in sa; struct sockaddr *sap[2]; socklen_t slens[2]; sap[0] = (struct sockaddr *) &sa; slens[0] = sizeof (sa); sap[1] = NULL; slens[1] = 0; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); server = GNUNET_SERVER_create (NULL, NULL, sap, slens, TIMEOUT, GNUNET_NO); GNUNET_assert (server != NULL); GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, ¬ify_disconnect, NULL); cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_number (cfg, "test-server", "PORT", PORT); GNUNET_CONFIGURATION_set_value_string (cfg, "test-server", "HOSTNAME", "localhost"); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); cc = GNUNET_CLIENT_connect ("test-server", cfg); GNUNET_assert (cc != NULL); GNUNET_assert (NULL != GNUNET_CLIENT_notify_transmit_ready (cc, sizeof (struct GNUNET_MessageHeader), TIMEOUT, GNUNET_YES, &transmit_initial_message, NULL)); } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int check () { ok = 1; GNUNET_SCHEDULER_run (&task, &ok); return ok; } int main (int argc, char *argv[]) { int ret = 0; GNUNET_log_setup ("test_server_disconnect", "WARNING", NULL); ret += check (); return ret; } /* end of test_server_disconnect.c */ gnunet-0.10.1/src/util/crypto_mpi.c0000644000175000017500000000701112267431203014106 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/crypto_mpi.c * @brief Helper functions for libgcrypt MPIs * @author Christian Grothoff * @author Florian Dold */ #include "platform.h" #include #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by gcry_strerror(rc). */ #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0) /** * If target != size, move @a target bytes to the end of the size-sized * buffer and zero out the first @a target - @a size bytes. * * @param buf original buffer * @param size number of bytes in @a buf * @param target target size of the buffer */ static void adjust (void *buf, size_t size, size_t target) { char *p = buf; if (size < target) { memmove (&p[target - size], buf, size); memset (buf, 0, target - size); } } /** * Output the given MPI value to the given buffer in * network byte order. * The MPI @a val may not be negative. * * @param buf where to output to * @param size number of bytes in @a buf * @param val value to write to @a buf */ void GNUNET_CRYPTO_mpi_print_unsigned (void *buf, size_t size, gcry_mpi_t val) { size_t rsize; if (gcry_mpi_get_flag (val, GCRYMPI_FLAG_OPAQUE)) { /* Store opaque MPIs left aligned into the buffer. */ unsigned int nbits; const void *p; p = gcry_mpi_get_opaque (val, &nbits); GNUNET_assert (p); rsize = (nbits+7)/8; if (rsize > size) rsize = size; memcpy (buf, p, rsize); if (rsize < size) memset (buf+rsize, 0, size - rsize); } else { /* Store regular MPIs as unsigned integers right aligned into the buffer. */ rsize = size; GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG, buf, rsize, &rsize, val)); adjust (buf, rsize, size); } } /** * Convert data buffer into MPI value. * The buffer is interpreted as network * byte order, unsigned integer. * * @param result where to store MPI value (allocated) * @param data raw data (GCRYMPI_FMT_USG) * @param size number of bytes in @a data */ void GNUNET_CRYPTO_mpi_scan_unsigned (gcry_mpi_t *result, const void *data, size_t size) { int rc; if (0 != (rc = gcry_mpi_scan (result, GCRYMPI_FMT_USG, data, size, &size))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); GNUNET_assert (0); } } /* end of crypto_mpi.c */ gnunet-0.10.1/src/util/test_server_mst_interrupt.c0000644000175000017500000000364712225777501017310 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_server_mst_interrupt.c * @brief test for interrupt message processing in server_mst.c */ #include "platform.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" static struct GNUNET_SERVER_MessageStreamTokenizer * mst; /* Callback destroying mst with data in buffer */ static int mst_cb (void *cls, void *client, const struct GNUNET_MessageHeader * message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MST gave me message, destroying\n"); GNUNET_SERVER_mst_destroy (mst); return GNUNET_SYSERR; } int main (int argc, char *argv[]) { struct GNUNET_PeerIdentity id; struct GNUNET_MessageHeader msg[2]; GNUNET_log_setup ("test_server_mst_interrupt", "WARNING", NULL); memset (&id, 0, sizeof (id)); msg[0].size = htons (sizeof (msg)); msg[0].type = htons (sizeof (GNUNET_MESSAGE_TYPE_DUMMY)); mst = GNUNET_SERVER_mst_create(mst_cb, NULL); GNUNET_SERVER_mst_receive (mst, &id, (const char *) &msg, 2 * sizeof (msg), GNUNET_NO, GNUNET_NO); /* If we reach this line, it did not crash */ return 0; } /* end of test_server_mst_interrupt.c */ gnunet-0.10.1/src/util/server_nc.c0000644000175000017500000002753512251306467013732 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/server_nc.c * @brief convenience functions for transmission of * a notification stream * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util-server-nc", __VA_ARGS__) /** * Entry in list of messages pending to be transmitted. */ struct PendingMessageList { /** * This is a doubly-linked list. */ struct PendingMessageList *next; /** * This is a doubly-linked list. */ struct PendingMessageList *prev; /** * Message to transmit (allocated at the end of this * struct, do not free) */ const struct GNUNET_MessageHeader *msg; /** * Can this message be dropped? */ int can_drop; }; /** * Lists of clients we manage for notifications. */ struct ClientList { /** * This is a doubly linked list. */ struct ClientList *next; /** * This is a doubly linked list. */ struct ClientList *prev; /** * Overall context this client belongs to. */ struct GNUNET_SERVER_NotificationContext *nc; /** * Handle to the client. */ struct GNUNET_SERVER_Client *client; /** * Handle for pending transmission request to the client (or NULL). */ struct GNUNET_SERVER_TransmitHandle *th; /** * Head of linked list of requests queued for transmission. */ struct PendingMessageList *pending_head; /** * Tail of linked list of requests queued for transmission. */ struct PendingMessageList *pending_tail; /** * Number of messages currently in the list. */ unsigned int num_pending; }; /** * The notification context is the key datastructure for a convenience * API used for transmission of notifications to the client until the * client disconnects (or the notification context is destroyed, in * which case we disconnect these clients). Essentially, all * (notification) messages are queued up until the client is able to * read them. */ struct GNUNET_SERVER_NotificationContext { /** * Server we do notifications for. */ struct GNUNET_SERVER_Handle *server; /** * Head of list of clients receiving notifications. */ struct ClientList *clients_head; /** * Tail of list of clients receiving notifications. */ struct ClientList *clients_tail; /** * Maximum number of optional messages to queue per client. */ unsigned int queue_length; }; /** * Client has disconnected, clean up. * * @param cls our `struct GNUNET_SERVER_NotificationContext *` * @param client handle of client that disconnected */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct GNUNET_SERVER_NotificationContext *nc = cls; struct ClientList *pos; struct PendingMessageList *pml; if (NULL == client) { nc->server = NULL; return; } for (pos = nc->clients_head; NULL != pos; pos = pos->next) if (pos->client == client) break; if (NULL == pos) return; LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected, cleaning up %u messages in NC queue\n", pos->num_pending); GNUNET_CONTAINER_DLL_remove (nc->clients_head, nc->clients_tail, pos); while (NULL != (pml = pos->pending_head)) { GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, pml); GNUNET_free (pml); pos->num_pending--; } if (NULL != pos->th) { GNUNET_SERVER_notify_transmit_ready_cancel (pos->th); pos->th = NULL; } GNUNET_SERVER_client_drop (client); GNUNET_assert (0 == pos->num_pending); GNUNET_free (pos); } /** * Create a new notification context. * * @param server server for which this function creates the context * @param queue_length maximum number of messages to keep in * the notification queue; optional messages are dropped * if the queue gets longer than this number of messages * @return handle to the notification context */ struct GNUNET_SERVER_NotificationContext * GNUNET_SERVER_notification_context_create (struct GNUNET_SERVER_Handle *server, unsigned int queue_length) { struct GNUNET_SERVER_NotificationContext *ret; ret = GNUNET_new (struct GNUNET_SERVER_NotificationContext); ret->server = server; ret->queue_length = queue_length; GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, ret); return ret; } /** * Destroy the context, force disconnect for all clients. * * @param nc context to destroy. */ void GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationContext *nc) { struct ClientList *pos; struct PendingMessageList *pml; while (NULL != (pos = nc->clients_head)) { GNUNET_CONTAINER_DLL_remove (nc->clients_head, nc->clients_tail, pos); if (NULL != pos->th) { GNUNET_SERVER_notify_transmit_ready_cancel(pos->th); pos->th = NULL; } GNUNET_SERVER_client_drop (pos->client); while (NULL != (pml = pos->pending_head)) { GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, pml); GNUNET_free (pml); pos->num_pending--; } GNUNET_assert (0 == pos->num_pending); GNUNET_free (pos); } if (NULL != nc->server) GNUNET_SERVER_disconnect_notify_cancel (nc->server, &handle_client_disconnect, nc); GNUNET_free (nc); } /** * Add a client to the notification context. * * @param nc context to modify * @param client client to add */ void GNUNET_SERVER_notification_context_add (struct GNUNET_SERVER_NotificationContext *nc, struct GNUNET_SERVER_Client *client) { struct ClientList *cl; for (cl = nc->clients_head; NULL != cl; cl = cl->next) if (cl->client == client) return; /* already present */ cl = GNUNET_new (struct ClientList); GNUNET_CONTAINER_DLL_insert (nc->clients_head, nc->clients_tail, cl); cl->nc = nc; cl->client = client; GNUNET_SERVER_client_keep (client); } /** * Function called to notify a client about the socket begin ready to * queue more data. @a buf will be NULL and @a size zero if the socket * was closed for writing in the meantime. * * @param cls the `struct ClientList *` * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_message (void *cls, size_t size, void *buf) { struct ClientList *cl = cls; char *cbuf = buf; struct PendingMessageList *pml; uint16_t msize; size_t ret; cl->th = NULL; if (NULL == buf) { /* 'cl' should be freed via disconnect notification shortly */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit message from NC queue to client\n"); return 0; } ret = 0; while (NULL != (pml = cl->pending_head)) { msize = ntohs (pml->msg->size); if (size < msize) break; GNUNET_CONTAINER_DLL_remove (cl->pending_head, cl->pending_tail, pml); LOG (GNUNET_ERROR_TYPE_DEBUG, "Copying message of type %u and size %u from pending queue to transmission buffer\n", ntohs (pml->msg->type), msize); memcpy (&cbuf[ret], pml->msg, msize); ret += msize; size -= msize; GNUNET_free (pml); cl->num_pending--; } if (NULL != pml) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Have %u messages left in NC queue, will try transmission again\n", cl->num_pending); cl->th = GNUNET_SERVER_notify_transmit_ready (cl->client, ntohs (pml->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_message, cl); } else { GNUNET_assert (0 == cl->num_pending); } return ret; } /** * Send a message to a particular client. * * @param nc context to modify * @param client client to transmit to * @param msg message to send * @param can_drop can this message be dropped due to queue length limitations */ static void do_unicast (struct GNUNET_SERVER_NotificationContext *nc, struct ClientList *client, const struct GNUNET_MessageHeader *msg, int can_drop) { struct PendingMessageList *pml; uint16_t size; if ((client->num_pending > nc->queue_length) && (GNUNET_YES == can_drop)) { LOG (GNUNET_ERROR_TYPE_INFO, "Dropping message of type %u and size %u due to full queue (%u entries)\n", ntohs (msg->type), ntohs (msg->size), (unsigned int) nc->queue_length); return; /* drop! */ } if (client->num_pending > nc->queue_length) { /* FIXME: consider checking for other messages in the * queue that are 'droppable' */ } client->num_pending++; size = ntohs (msg->size); pml = GNUNET_malloc (sizeof (struct PendingMessageList) + size); pml->msg = (const struct GNUNET_MessageHeader *) &pml[1]; pml->can_drop = can_drop; LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding message of type %u and size %u to pending queue (which has %u entries)\n", ntohs (msg->type), ntohs (msg->size), (unsigned int) nc->queue_length); memcpy (&pml[1], msg, size); /* append */ GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, client->pending_tail, pml); if (NULL == client->th) client->th = GNUNET_SERVER_notify_transmit_ready (client->client, ntohs (client->pending_head-> msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_message, client); } /** * Send a message to a particular client; must have * already been added to the notification context. * * @param nc context to modify * @param client client to transmit to * @param msg message to send * @param can_drop can this message be dropped due to queue length limitations */ void GNUNET_SERVER_notification_context_unicast (struct GNUNET_SERVER_NotificationContext *nc, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg, int can_drop) { struct ClientList *pos; for (pos = nc->clients_head; NULL != pos; pos = pos->next) if (pos->client == client) break; GNUNET_assert (NULL != pos); do_unicast (nc, pos, msg, can_drop); } /** * Send a message to all clients of this context. * * @param nc context to modify * @param msg message to send * @param can_drop can this message be dropped due to queue length limitations */ void GNUNET_SERVER_notification_context_broadcast (struct GNUNET_SERVER_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop) { struct ClientList *pos; for (pos = nc->clients_head; NULL != pos; pos = pos->next) do_unicast (nc, pos, msg, can_drop); } /* end of server_nc.c */ gnunet-0.10.1/src/util/test_common_logging_runtime_loglevels.c0000644000175000017500000003034212301361473021600 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_common_logging_runtime_loglevels.c * @brief testcase for the logging module (runtime log level adjustment) * @author LRN */ #include "platform.h" #include "gnunet_util_lib.h" #define VERBOSE GNUNET_NO /** * How much time the child is allowed to waste on skipped log calls, at most. * Raspberry Pi takes 113 microseconds tops, this is 3x that value. */ #define MAX_SKIP_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, 400).rel_value_us /** * How much time non-skipped log call should take, at least. * Keep in sync with the value in the dummy! */ #define OUTPUT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, 1000).rel_value_us static int ok; static int phase = 0; static struct GNUNET_OS_Process *proc; /* Pipe to read from started processes stdout (on read end) */ static struct GNUNET_DISK_PipeHandle *pipe_stdout; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier read_task; static void runone (void); static void end_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending phase %d, ok is %d\n", phase, ok); if (NULL != proc) { if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = NULL; } if (GNUNET_SCHEDULER_NO_TASK != read_task) { GNUNET_SCHEDULER_cancel (read_task); read_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_DISK_pipe_close (pipe_stdout); if (ok == 1) { if (phase < 9) { phase += 1; runone (); } else ok = 0; } else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failing\n"); } static char * read_output_line (int phase_from1, int phase_to1, int phase_from2, int phase_to2, char c, const char *expect_level, long delay_morethan, long delay_lessthan, int phase, char *p, int *len, long *delay, char level[8]) { char *r = p; char t[7]; int i, j, stop = 0; int level_matches; int delay_is_sane; int delay_is_a_dummy; int delay_outside_of_range; j = 0; int stage = 0; if (!(phase >= phase_from1 && phase <= phase_to1) && !(phase >= phase_from2 && phase <= phase_to2)) return p; #if 0 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to match '%c%s \\d\\r\\n' on %s\n", c, expect_level, p); #endif for (i = 0; i < *len && !stop; i++) { switch (stage) { case 0: /* read first char */ if (r[i] != c) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected '%c', but got '%c'\n", c, r[i]); GNUNET_break (0); return NULL; } stage += 1; break; case 1: /* read at most 7 char-long error level string, finished by ' ' */ if (r[i] == ' ') { level[j] = '\0'; stage += 1; j = 0; } else if (i == 8) { GNUNET_break (0); ok = 2; return NULL; } else level[j++] = r[i]; break; case 2: /* read the delay, finished by '\n' */ t[j++] = r[i]; #if WINDOWS if (r[i] == '\r' && r[i + 1] == '\n') { i += 1; t[j - 1] = '\0'; *delay = strtol (t, NULL, 10); stop = 1; } #else if (r[i] == '\n') { t[j - 1] = '\0'; *delay = strtol (t, NULL, 10); stop = 1; } #endif break; } } level_matches = (strcmp (expect_level, level) == 0); delay_is_sane = (*delay >= 0) && (*delay <= 1000000); delay_is_a_dummy = (c == 'L'); /* Delay must be either less than 'lessthan' (log call is skipped) * or more than 'morethan' (log call is not skipped) */ delay_outside_of_range = ((*delay < delay_lessthan) || (*delay >= delay_morethan)); if (delay_is_a_dummy) delay_outside_of_range = 1; if (!stop) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong log format?\n"); if (!level_matches) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Wrong log level\n"); if (!delay_is_sane) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Delay %ld is insane\n", *delay); if (!delay_outside_of_range) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Delay %ld is not outside of range (%ld ; %ld)\n", *delay, delay_lessthan, delay_morethan, c); if (!stop || !level_matches || !delay_is_sane || !delay_outside_of_range) return NULL; *len = *len - i; return &r[i]; } /** * Up to 8 non-skipped GNUNET_log() calls * + extra line with delay for each one */ #define LOG_MAX_NUM_LINES (8 * 2) /** * Actual message is 17 chars at most */ #define LOG_MAX_LINE_LENGTH (17) #define LOG_BUFFER_SIZE LOG_MAX_NUM_LINES * LOG_MAX_LINE_LENGTH static char buf[LOG_BUFFER_SIZE]; static char *buf_ptr; static int bytes; static void read_call (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { const struct GNUNET_DISK_FileHandle *stdout_read_handle = cls; char level[8]; long delay; long delays[8]; int rd; read_task = GNUNET_SCHEDULER_NO_TASK; rd = GNUNET_DISK_file_read (stdout_read_handle, buf_ptr, sizeof (buf) - bytes); if (rd > 0) { buf_ptr += rd; bytes += rd; #if VERBOSE FPRINTF (stderr, "got %d bytes, reading more\n", rd); #endif read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdout_read_handle, &read_call, (void*) stdout_read_handle); return; } #if VERBOSE FPRINTF (stderr, "bytes is %d:%s\n", bytes, buf); #endif /* +------CHILD OUTPUT-- * | SOFT HARD * | E W I D E W I D * | 0E * * * * | 1W * * * * * P 2I * * * * * * H 3D * * * * * * * A * S 4E * * * E 5W * * * * * | 6I * * * * * * * | 7D * * * * * * * * * | 8 * * * * * | 9 * * * * */ char *p = buf; if (bytes == LOG_BUFFER_SIZE || !(p = read_output_line (0, 3, 4, 9, 'L', "ERROR", -1, 1, phase, p, &bytes, &delay, level)) || !(p = read_output_line (0, 3, 4, 9, '1', "ERROR", OUTPUT_DELAY, MAX_SKIP_DELAY, phase, p, &bytes, &delays[0], level)) || !(p = read_output_line (1, 3, 5, 9, 'L', "WARNING", -1, 1, phase, p, &bytes, &delay, level)) || !(p = read_output_line (0, 3, 4, 9, '1', "WARNING", OUTPUT_DELAY, MAX_SKIP_DELAY, phase, p, &bytes, &delays[1], level)) || !(p = read_output_line (2, 3, 6, 7, 'L', "INFO", -1, 1, phase, p, &bytes, &delay, level)) || !(p = read_output_line (0, 3, 4, 9, '1', "INFO", OUTPUT_DELAY, MAX_SKIP_DELAY, phase, p, &bytes, &delays[2], level)) || !(p = read_output_line (3, 3, 7, 7, 'L', "DEBUG", -1, 1, phase, p, &bytes, &delay, level)) || !(p = read_output_line (0, 3, 4, 9, '1', "DEBUG", OUTPUT_DELAY, MAX_SKIP_DELAY, phase, p, &bytes, &delays[3], level)) || !(p = read_output_line (0, 3, 4, 9, 'L', "ERROR", -1, 1, phase, p, &bytes, &delay, level)) || !(p = read_output_line (0, 3, 4, 9, '2', "ERROR", OUTPUT_DELAY, MAX_SKIP_DELAY, phase, p, &bytes, &delays[4], level)) || !(p = read_output_line (0, 3, 5, 9, 'L', "WARNING", -1, 1, phase, p, &bytes, &delay, level)) || !(p = read_output_line (0, 3, 4, 9, '2', "WARNING", OUTPUT_DELAY, MAX_SKIP_DELAY, phase, p, &bytes, &delays[5], level)) || !(p = read_output_line (-1, -1, 6, 7, 'L', "INFO", -1, 1, phase, p, &bytes, &delay, level)) || !(p = read_output_line (0, 3, 4, 9, '2', "INFO", OUTPUT_DELAY, MAX_SKIP_DELAY, phase, p, &bytes, &delays[6], level)) || !(p = read_output_line (-1, -1, 7, 7, 'L', "DEBUG", -1, 1, phase, p, &bytes, &delay, level)) || !(p = read_output_line (0, 3, 4, 9, '2', "DEBUG", OUTPUT_DELAY, MAX_SKIP_DELAY, phase, p, &bytes, &delays[7], level))) { if (bytes == LOG_BUFFER_SIZE) FPRINTF (stderr, "%s", "Ran out of buffer space!\n"); GNUNET_break (0); ok = 2; GNUNET_SCHEDULER_cancel (die_task); GNUNET_SCHEDULER_add_now (&end_task, NULL); return; } GNUNET_SCHEDULER_cancel (die_task); GNUNET_SCHEDULER_add_now (&end_task, NULL); } static void runone () { const struct GNUNET_DISK_FileHandle *stdout_read_handle; pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if (pipe_stdout == NULL) { GNUNET_break (0); ok = 2; return; } putenv ("GNUNET_LOG="); putenv ("GNUNET_FORCE_LOG="); putenv ("GNUNET_FORCE_LOGFILE="); switch (phase) { case 0: putenv ("GNUNET_LOG=;;;;ERROR"); break; case 1: putenv ("GNUNET_LOG=;;;;WARNING"); break; case 2: putenv ("GNUNET_LOG=;;;;INFO"); break; case 3: putenv ("GNUNET_LOG=;;;;DEBUG"); break; case 4: putenv ("GNUNET_FORCE_LOG=;;;;ERROR"); break; case 5: putenv ("GNUNET_FORCE_LOG=;;;;WARNING"); break; case 6: putenv ("GNUNET_FORCE_LOG=;;;;INFO"); break; case 7: putenv ("GNUNET_FORCE_LOG=;;;;DEBUG"); break; case 8: putenv ("GNUNET_LOG=blah;;;;ERROR"); break; case 9: putenv ("GNUNET_FORCE_LOG=blah;;;;ERROR"); break; } proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, pipe_stdout, NULL, #if MINGW "test_common_logging_dummy", #else "./test_common_logging_dummy", #endif "test_common_logging_dummy", NULL); GNUNET_assert (NULL != proc); putenv ("GNUNET_FORCE_LOG="); putenv ("GNUNET_LOG="); /* Close the write end of the read pipe */ GNUNET_DISK_pipe_close_end (pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); stdout_read_handle = GNUNET_DISK_pipe_handle (pipe_stdout, GNUNET_DISK_PIPE_END_READ); die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), &end_task, NULL); bytes = 0; buf_ptr = buf; memset (&buf, 0, sizeof (buf)); read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdout_read_handle, &read_call, (void*) stdout_read_handle); } static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { phase = 0; runone (); } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-common-logging-runtime-loglevels", "WARNING", NULL); ok = 1; GNUNET_SCHEDULER_run (&task, &ok); return ok; } /* end of test_common_logging_runtime_loglevels.c */ gnunet-0.10.1/src/util/bio.c0000644000175000017500000003327512225777501012515 00000000000000/* This file is part of GNUnet. (C) 2006, 2009, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/bio.c * @brief functions for buffering IO * @author Christian Grothoff */ #include "platform.h" #include "gnunet_bio_lib.h" #include "gnunet_disk_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__) /** * Size for I/O buffers. */ #define BIO_BUFFER_SIZE 65536 /** * Maximum size allowed for meta data written/read from disk. * File-sharing limits to 64k, so this should be rather generous. */ #define MAX_META_DATA (1024 * 1024) /** * Handle for buffered reading. */ struct GNUNET_BIO_ReadHandle { /** * Underlying file abstraction. */ struct GNUNET_DISK_FileHandle *fd; /** * Error message, NULL if there were no errors. */ char *emsg; /** * I/O buffer. Allocated at the end of the struct, do not free! */ char *buffer; /** * Number of bytes available in read @e buffer. */ size_t have; /** * Total size of @e buffer. */ size_t size; /** * Current read offset in @e buffer. */ off_t pos; }; /** * Open a file for reading. * * @param fn file name to be opened * @return IO handle on success, NULL on error */ struct GNUNET_BIO_ReadHandle * GNUNET_BIO_read_open (const char *fn) { struct GNUNET_DISK_FileHandle *fd; struct GNUNET_BIO_ReadHandle *h; fd = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == fd) return NULL; h = GNUNET_malloc (sizeof (struct GNUNET_BIO_ReadHandle) + BIO_BUFFER_SIZE); h->buffer = (char *) &h[1]; h->size = BIO_BUFFER_SIZE; h->fd = fd; return h; } /** * Close an open file. Reports if any errors reading * from the file were encountered. * * @param h file handle * @param emsg set to the error message * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, char **emsg) { int err; err = (NULL == h->emsg) ? GNUNET_OK : GNUNET_SYSERR; if (emsg != NULL) *emsg = h->emsg; else GNUNET_free_non_null (h->emsg); GNUNET_DISK_file_close (h->fd); GNUNET_free (h); return err; } /** * Read the contents of a binary file into a buffer. * * @param h handle to an open file * @param what describes what is being read (for error message creation) * @param result the buffer to write the result to * @param len the number of bytes to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, const char *what, void *result, size_t len) { char *dst = result; size_t min; size_t pos; ssize_t ret; if (NULL != h->emsg) return GNUNET_SYSERR; pos = 0; do { /* first, use buffer */ min = h->have - h->pos; if (min > 0) { if (min > len - pos) min = len - pos; memcpy (&dst[pos], &h->buffer[h->pos], min); h->pos += min; pos += min; } if (pos == len) return GNUNET_OK; /* done! */ GNUNET_assert (h->have == h->pos); /* fill buffer */ ret = GNUNET_DISK_file_read (h->fd, h->buffer, h->size); if (-1 == ret) { GNUNET_asprintf (&h->emsg, _("Error reading `%s': %s"), what, STRERROR (errno)); return GNUNET_SYSERR; } if (0 == ret) { GNUNET_asprintf (&h->emsg, _("Error reading `%s': %s"), what, _("End of file")); return GNUNET_SYSERR; } h->pos = 0; h->have = ret; } while (pos < len); /* should always be true */ return GNUNET_OK; } /** * Read the contents of a binary file into a buffer. * * @param h handle to an open file * @param file name of the source file * @param line line number in the source file * @param result the buffer to write the result to * @param len the number of bytes to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read_fn (struct GNUNET_BIO_ReadHandle *h, const char *file, int line, void *result, size_t len) { char what[1024]; GNUNET_snprintf (what, sizeof (what), "%s:%d", file, line); return GNUNET_BIO_read (h, what, result, len); } /** * Read 0-terminated string from a file. * * @param h handle to an open file * @param what describes what is being read (for error message creation) * @param result the buffer to store a pointer to the (allocated) string to * (note that *result could be set to NULL as well) * @param max_length maximum allowed length for the string * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, const char *what, char **result, size_t max_length) { char *buf; uint32_t big; if (GNUNET_OK != GNUNET_BIO_read_int32 (h, &big)) { GNUNET_free_non_null (h->emsg); GNUNET_asprintf (&h->emsg, _("Error reading length of string `%s'"), what); return GNUNET_SYSERR; } if (0 == big) { *result = NULL; return GNUNET_OK; } if (big > max_length) { GNUNET_asprintf (&h->emsg, _("String `%s' longer than allowed (%u > %u)"), what, big, max_length); return GNUNET_SYSERR; } buf = GNUNET_malloc (big); *result = buf; buf[--big] = '\0'; if (0 == big) return GNUNET_OK; if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, big)) { GNUNET_free (buf); *result = NULL; return GNUNET_SYSERR; } return GNUNET_OK; } /** * Read metadata container from a file. * * @param h handle to an open file * @param what describes what is being read (for error message creation) * @param result the buffer to store a pointer to the (allocated) metadata * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h, const char *what, struct GNUNET_CONTAINER_MetaData **result) { uint32_t size; char *buf; struct GNUNET_CONTAINER_MetaData *meta; if (GNUNET_BIO_read_int32 (h, (int32_t *) & size) != GNUNET_OK) return GNUNET_SYSERR; if (size == 0) { *result = NULL; return GNUNET_OK; } if (size > MAX_META_DATA) { GNUNET_asprintf (&h->emsg, _("Serialized metadata `%s' larger than allowed (%u>%u)"), what, size, MAX_META_DATA); return GNUNET_SYSERR; } buf = GNUNET_malloc (size); if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, size)) { GNUNET_free (buf); return GNUNET_SYSERR; } meta = GNUNET_CONTAINER_meta_data_deserialize (buf, size); if (meta == NULL) { GNUNET_free (buf); GNUNET_asprintf (&h->emsg, _("Metadata `%s' failed to deserialize"), what); return GNUNET_SYSERR; } GNUNET_free (buf); *result = meta; return GNUNET_OK; } /** * Read an (u)int32_t. * * @param h hande to open file * @param file name of the source file * @param line line number in the source file * @param i address of 32-bit integer to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h, const char *file, int line, int32_t * i) { int32_t big; if (GNUNET_OK != GNUNET_BIO_read_fn (h, file, line, &big, sizeof (int32_t))) return GNUNET_SYSERR; *i = ntohl (big); return GNUNET_OK; } /** * Read an (u)int64_t. * * @param h hande to open file * @param file name of the source file * @param line line number in the source file * @param i address of 64-bit integer to read * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h, const char *file, int line, int64_t *i) { int64_t big; if (GNUNET_OK != GNUNET_BIO_read_fn (h, file, line, &big, sizeof (int64_t))) return GNUNET_SYSERR; *i = GNUNET_ntohll (big); return GNUNET_OK; } /** * Handle for buffered writing. */ struct GNUNET_BIO_WriteHandle { /** * Underlying file handle. */ struct GNUNET_DISK_FileHandle *fd; /** * I/O buffer. Do not free, allocated at the end of the struct. */ char *buffer; /** * Number of bytes already in @e buffer. */ size_t have; /** * Total size of @e buffer. */ size_t size; }; /** * Open a file for writing. * * @param fn file name to be opened * @return IO handle on success, NULL on error */ struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open (const char *fn) { struct GNUNET_DISK_FileHandle *fd; struct GNUNET_BIO_WriteHandle *h; fd = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == fd) return NULL; h = GNUNET_malloc (sizeof (struct GNUNET_BIO_WriteHandle) + BIO_BUFFER_SIZE); h->buffer = (char *) &h[1]; h->size = BIO_BUFFER_SIZE; h->fd = fd; return h; } /** * Close an open file for writing. * * @param h file handle * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h) { int ret; ret = GNUNET_SYSERR; if ( (NULL != h->fd) && (GNUNET_OK == (ret = GNUNET_BIO_flush (h))) ) GNUNET_DISK_file_close (h->fd); GNUNET_free (h); return ret; } /** * Force a buffered writer to flush its buffer * * @param h the writer handle * @return #GNUNET_OK upon success. Upon failure #GNUNET_SYSERR is returned and * the file is closed */ int GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h) { ssize_t ret; ret = GNUNET_DISK_file_write (h->fd, h->buffer, h->have); if (ret != h->have) { GNUNET_DISK_file_close (h->fd); h->fd = NULL; return GNUNET_SYSERR; /* error */ } h->have = 0; return GNUNET_OK; } /** * Write a buffer to a file. * * @param h handle to open file * @param buffer the data to write * @param n number of bytes to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, const void *buffer, size_t n) { const char *src = buffer; size_t min; size_t pos; if (NULL == h->fd) return GNUNET_SYSERR; pos = 0; do { /* first, just use buffer */ min = h->size - h->have; if (min > n - pos) min = n - pos; memcpy (&h->buffer[h->have], &src[pos], min); pos += min; h->have += min; if (pos == n) return GNUNET_OK; /* done */ GNUNET_assert (h->have == h->size); if (GNUNET_OK != GNUNET_BIO_flush (h)) return GNUNET_SYSERR; /* error */ } while (pos < n); /* should always be true */ GNUNET_break (0); return GNUNET_OK; } /** * Write a string to a file. * * @param h handle to open file * @param s string to write (can be NULL) * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, const char *s) { uint32_t slen; slen = (uint32_t) ((s == NULL) ? 0 : strlen (s) + 1); if (GNUNET_OK != GNUNET_BIO_write_int32 (h, slen)) return GNUNET_SYSERR; if (0 != slen) return GNUNET_BIO_write (h, s, slen - 1); return GNUNET_OK; } /** * Write metadata container to a file. * * @param h handle to open file * @param m metadata to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, const struct GNUNET_CONTAINER_MetaData *m) { ssize_t size; char *buf; if (m == NULL) return GNUNET_BIO_write_int32 (h, 0); buf = NULL; size = GNUNET_CONTAINER_meta_data_serialize (m, &buf, MAX_META_DATA, GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); if (size == -1) { GNUNET_free (buf); return GNUNET_SYSERR; } if ((GNUNET_OK != GNUNET_BIO_write_int32 (h, (uint32_t) size)) || (GNUNET_OK != GNUNET_BIO_write (h, buf, size))) { GNUNET_free (buf); return GNUNET_SYSERR; } GNUNET_free (buf); return GNUNET_OK; } /** * Write an (u)int32_t. * * @param h hande to open file * @param i 32-bit integer to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h, int32_t i) { int32_t big; big = htonl (i); return GNUNET_BIO_write (h, &big, sizeof (int32_t)); } /** * Write an (u)int64_t. * * @param h hande to open file * @param i 64-bit integer to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h, int64_t i) { int64_t big; big = GNUNET_htonll (i); return GNUNET_BIO_write (h, &big, sizeof (int64_t)); } /* end of bio.c */ gnunet-0.10.1/src/util/test_mq.c0000644000175000017500000000363012225777501013410 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_mq.c * @brief simple tests for mq */ #include "platform.h" #include "gnunet_util_lib.h" GNUNET_NETWORK_STRUCT_BEGIN struct MyMessage { struct GNUNET_MessageHeader header; uint32_t x GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END static void test1 () { struct GNUNET_MQ_Envelope *mqm; struct MyMessage *mm; mm = NULL; mqm = NULL; mqm = GNUNET_MQ_msg (mm, 42); GNUNET_assert (NULL != mqm); GNUNET_assert (NULL != mm); GNUNET_assert (42 == ntohs (mm->header.type)); GNUNET_assert (sizeof (struct MyMessage) == ntohs (mm->header.size)); } static void test2 () { struct GNUNET_MQ_Envelope *mqm; struct GNUNET_MessageHeader *mh; mqm = GNUNET_MQ_msg_header (42); /* how could the above be checked? */ GNUNET_MQ_discard (mqm); mqm = GNUNET_MQ_msg_header_extra (mh, 20, 42); GNUNET_assert (42 == ntohs (mh->type)); GNUNET_assert (sizeof (struct GNUNET_MessageHeader) + 20 == ntohs (mh->size)); GNUNET_MQ_discard (mqm); } int main (int argc, char **argv) { GNUNET_log_setup ("test-mq", "INFO", NULL); test1 (); test2 (); return 0; } gnunet-0.10.1/src/util/Makefile.in0000644000175000017500000035741412320755133013642 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ noinst_PROGRAMS = gnunet-config-diff$(EXEEXT) $(am__EXEEXT_6) \ test_common_logging_dummy$(EXEEXT) libexec_PROGRAMS = gnunet-service-resolver$(EXEEXT) $(am__EXEEXT_5) bin_PROGRAMS = gnunet-resolver$(EXEEXT) gnunet-config$(EXEEXT) \ $(am__EXEEXT_1) $(am__EXEEXT_2) gnunet-uri$(EXEEXT) check_PROGRAMS = test_bio$(EXEEXT) test_client$(EXEEXT) \ test_common_allocation$(EXEEXT) test_common_endian$(EXEEXT) \ test_common_logging$(EXEEXT) test_configuration$(EXEEXT) \ test_container_bloomfilter$(EXEEXT) \ test_container_meta_data$(EXEEXT) \ test_container_multihashmap$(EXEEXT) \ test_container_multihashmap32$(EXEEXT) \ test_container_multipeermap$(EXEEXT) \ test_container_heap$(EXEEXT) test_container_slist$(EXEEXT) \ test_crypto_symmetric$(EXEEXT) test_crypto_crc$(EXEEXT) \ test_crypto_ecdsa$(EXEEXT) test_crypto_eddsa$(EXEEXT) \ test_crypto_ecdhe$(EXEEXT) test_crypto_hash$(EXEEXT) \ test_crypto_hkdf$(EXEEXT) test_crypto_paillier$(EXEEXT) \ test_crypto_random$(EXEEXT) test_disk$(EXEEXT) \ test_getopt$(EXEEXT) test_connection$(EXEEXT) \ test_connection_addressing$(EXEEXT) \ test_connection_receive_cancel$(EXEEXT) \ test_connection_timeout$(EXEEXT) \ test_connection_timeout_no_connect$(EXEEXT) \ test_connection_transmit_cancel$(EXEEXT) test_mq$(EXEEXT) \ test_mq_client$(EXEEXT) test_os_network$(EXEEXT) \ test_peer$(EXEEXT) test_plugin$(EXEEXT) test_program$(EXEEXT) \ test_resolver_api$(EXEEXT) test_scheduler$(EXEEXT) \ test_scheduler_delay$(EXEEXT) \ test_server_mst_interrupt$(EXEEXT) test_server$(EXEEXT) \ test_server_disconnect$(EXEEXT) \ test_server_with_client$(EXEEXT) $(am__EXEEXT_3) \ test_service$(EXEEXT) test_strings$(EXEEXT) \ test_strings_to_data$(EXEEXT) test_time$(EXEEXT) \ test_speedup$(EXEEXT) $(am__EXEEXT_4) \ test_os_start_process$(EXEEXT) \ test_common_logging_runtime_loglevels$(EXEEXT) subdir = src/util DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/resolver.conf.in $(top_srcdir)/depcomp \ $(dist_pkgcfg_DATA) $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = resolver.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) \ $(plugin_LTLIBRARIES) libgnunet_plugin_test_la_LIBADD = am_libgnunet_plugin_test_la_OBJECTS = test_plugin_plug.lo libgnunet_plugin_test_la_OBJECTS = \ $(am_libgnunet_plugin_test_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunet_plugin_test_la_LDFLAGS) \ $(LDFLAGS) -o $@ am__DEPENDENCIES_1 = libgnunetutil_la_DEPENDENCIES = $(WINLIB) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetutil_la_OBJECTS = bandwidth.lo bio.lo client.lo \ common_allocation.lo common_endian.lo common_logging.lo \ configuration.lo connection.lo container_bloomfilter.lo \ container_heap.lo container_meta_data.lo \ container_multihashmap.lo container_multipeermap.lo \ container_multihashmap32.lo container_slist.lo \ crypto_symmetric.lo crypto_crc.lo crypto_ecc.lo crypto_hash.lo \ crypto_hkdf.lo crypto_kdf.lo crypto_mpi.lo crypto_paillier.lo \ crypto_random.lo disk.lo getopt.lo getopt_helpers.lo helper.lo \ load.lo mq.lo network.lo os_installation.lo os_network.lo \ os_priority.lo peer.lo plugin.lo program.lo resolver_api.lo \ scheduler.lo server.lo server_mst.lo server_nc.lo server_tc.lo \ service.lo signal.lo strings.lo time.lo speedup.lo libgnunetutil_la_OBJECTS = $(am_libgnunetutil_la_OBJECTS) libgnunetutil_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetutil_la_LDFLAGS) $(LDFLAGS) \ -o $@ libgnunetutilwin_la_DEPENDENCIES = am__libgnunetutilwin_la_SOURCES_DIST = win.c winproc.c @MINGW_TRUE@am_libgnunetutilwin_la_OBJECTS = win.lo winproc.lo libgnunetutilwin_la_OBJECTS = $(am_libgnunetutilwin_la_OBJECTS) libgnunetutilwin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetutilwin_la_LDFLAGS) \ $(LDFLAGS) -o $@ @MINGW_TRUE@am_libgnunetutilwin_la_rpath = @HAVE_TESTING_TRUE@am__EXEEXT_1 = gnunet-ecc$(EXEEXT) @HAVE_TESTING_TRUE@am__EXEEXT_2 = gnunet-scrypt$(EXEEXT) @MINGW_FALSE@am__EXEEXT_3 = test_server_with_client_unix$(EXEEXT) @HAVE_BENCHMARKS_TRUE@am__EXEEXT_4 = perf_crypto_hash$(EXEEXT) \ @HAVE_BENCHMARKS_TRUE@ perf_crypto_symmetric$(EXEEXT) \ @HAVE_BENCHMARKS_TRUE@ perf_malloc$(EXEEXT) @MINGW_TRUE@am__EXEEXT_5 = gnunet-helper-w32-console$(EXEEXT) @MINGW_TRUE@am__EXEEXT_6 = w32cat$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_config_OBJECTS = gnunet-config.$(OBJEXT) gnunet_config_OBJECTS = $(am_gnunet_config_OBJECTS) am_gnunet_config_diff_OBJECTS = gnunet-config-diff.$(OBJEXT) gnunet_config_diff_OBJECTS = $(am_gnunet_config_diff_OBJECTS) am_gnunet_ecc_OBJECTS = gnunet-ecc.$(OBJEXT) gnunet_ecc_OBJECTS = $(am_gnunet_ecc_OBJECTS) am_gnunet_helper_w32_console_OBJECTS = \ gnunet-helper-w32-console.$(OBJEXT) gnunet_helper_w32_console_OBJECTS = \ $(am_gnunet_helper_w32_console_OBJECTS) am_gnunet_resolver_OBJECTS = gnunet-resolver.$(OBJEXT) gnunet_resolver_OBJECTS = $(am_gnunet_resolver_OBJECTS) am_gnunet_scrypt_OBJECTS = gnunet-scrypt.$(OBJEXT) gnunet_scrypt_OBJECTS = $(am_gnunet_scrypt_OBJECTS) am_gnunet_service_resolver_OBJECTS = \ gnunet-service-resolver.$(OBJEXT) gnunet_service_resolver_OBJECTS = \ $(am_gnunet_service_resolver_OBJECTS) am_gnunet_uri_OBJECTS = gnunet-uri.$(OBJEXT) gnunet_uri_OBJECTS = $(am_gnunet_uri_OBJECTS) am_perf_crypto_hash_OBJECTS = perf_crypto_hash.$(OBJEXT) perf_crypto_hash_OBJECTS = $(am_perf_crypto_hash_OBJECTS) perf_crypto_hash_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_perf_crypto_symmetric_OBJECTS = perf_crypto_symmetric.$(OBJEXT) perf_crypto_symmetric_OBJECTS = $(am_perf_crypto_symmetric_OBJECTS) perf_crypto_symmetric_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_perf_malloc_OBJECTS = perf_malloc.$(OBJEXT) perf_malloc_OBJECTS = $(am_perf_malloc_OBJECTS) perf_malloc_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_bio_OBJECTS = test_bio.$(OBJEXT) test_bio_OBJECTS = $(am_test_bio_OBJECTS) test_bio_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_client_OBJECTS = test_client.$(OBJEXT) test_client_OBJECTS = $(am_test_client_OBJECTS) test_client_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_common_allocation_OBJECTS = test_common_allocation.$(OBJEXT) test_common_allocation_OBJECTS = $(am_test_common_allocation_OBJECTS) test_common_allocation_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_common_endian_OBJECTS = test_common_endian.$(OBJEXT) test_common_endian_OBJECTS = $(am_test_common_endian_OBJECTS) test_common_endian_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_common_logging_OBJECTS = test_common_logging.$(OBJEXT) test_common_logging_OBJECTS = $(am_test_common_logging_OBJECTS) test_common_logging_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_common_logging_dummy_OBJECTS = \ test_common_logging_dummy.$(OBJEXT) test_common_logging_dummy_OBJECTS = \ $(am_test_common_logging_dummy_OBJECTS) am_test_common_logging_runtime_loglevels_OBJECTS = \ test_common_logging_runtime_loglevels.$(OBJEXT) test_common_logging_runtime_loglevels_OBJECTS = \ $(am_test_common_logging_runtime_loglevels_OBJECTS) test_common_logging_runtime_loglevels_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_configuration_OBJECTS = test_configuration.$(OBJEXT) test_configuration_OBJECTS = $(am_test_configuration_OBJECTS) test_configuration_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_connection_OBJECTS = test_connection.$(OBJEXT) test_connection_OBJECTS = $(am_test_connection_OBJECTS) test_connection_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_connection_addressing_OBJECTS = \ test_connection_addressing.$(OBJEXT) test_connection_addressing_OBJECTS = \ $(am_test_connection_addressing_OBJECTS) test_connection_addressing_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_connection_receive_cancel_OBJECTS = \ test_connection_receive_cancel.$(OBJEXT) test_connection_receive_cancel_OBJECTS = \ $(am_test_connection_receive_cancel_OBJECTS) test_connection_receive_cancel_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_connection_timeout_OBJECTS = \ test_connection_timeout.$(OBJEXT) test_connection_timeout_OBJECTS = \ $(am_test_connection_timeout_OBJECTS) test_connection_timeout_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_connection_timeout_no_connect_OBJECTS = \ test_connection_timeout_no_connect.$(OBJEXT) test_connection_timeout_no_connect_OBJECTS = \ $(am_test_connection_timeout_no_connect_OBJECTS) test_connection_timeout_no_connect_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_connection_transmit_cancel_OBJECTS = \ test_connection_transmit_cancel.$(OBJEXT) test_connection_transmit_cancel_OBJECTS = \ $(am_test_connection_transmit_cancel_OBJECTS) test_connection_transmit_cancel_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_container_bloomfilter_OBJECTS = \ test_container_bloomfilter.$(OBJEXT) test_container_bloomfilter_OBJECTS = \ $(am_test_container_bloomfilter_OBJECTS) test_container_bloomfilter_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_container_heap_OBJECTS = test_container_heap.$(OBJEXT) test_container_heap_OBJECTS = $(am_test_container_heap_OBJECTS) test_container_heap_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_container_meta_data_OBJECTS = \ test_container_meta_data.$(OBJEXT) test_container_meta_data_OBJECTS = \ $(am_test_container_meta_data_OBJECTS) test_container_meta_data_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_container_multihashmap_OBJECTS = \ test_container_multihashmap.$(OBJEXT) test_container_multihashmap_OBJECTS = \ $(am_test_container_multihashmap_OBJECTS) test_container_multihashmap_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_container_multihashmap32_OBJECTS = \ test_container_multihashmap32.$(OBJEXT) test_container_multihashmap32_OBJECTS = \ $(am_test_container_multihashmap32_OBJECTS) test_container_multihashmap32_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_container_multipeermap_OBJECTS = \ test_container_multipeermap.$(OBJEXT) test_container_multipeermap_OBJECTS = \ $(am_test_container_multipeermap_OBJECTS) test_container_multipeermap_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_container_slist_OBJECTS = test_container_slist.$(OBJEXT) test_container_slist_OBJECTS = $(am_test_container_slist_OBJECTS) test_container_slist_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_crypto_crc_OBJECTS = test_crypto_crc.$(OBJEXT) test_crypto_crc_OBJECTS = $(am_test_crypto_crc_OBJECTS) test_crypto_crc_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_crypto_ecdhe_OBJECTS = test_crypto_ecdhe.$(OBJEXT) test_crypto_ecdhe_OBJECTS = $(am_test_crypto_ecdhe_OBJECTS) test_crypto_ecdhe_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_crypto_ecdsa_OBJECTS = test_crypto_ecdsa.$(OBJEXT) test_crypto_ecdsa_OBJECTS = $(am_test_crypto_ecdsa_OBJECTS) test_crypto_ecdsa_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_crypto_eddsa_OBJECTS = test_crypto_eddsa.$(OBJEXT) test_crypto_eddsa_OBJECTS = $(am_test_crypto_eddsa_OBJECTS) test_crypto_eddsa_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_crypto_hash_OBJECTS = test_crypto_hash.$(OBJEXT) test_crypto_hash_OBJECTS = $(am_test_crypto_hash_OBJECTS) test_crypto_hash_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_crypto_hkdf_OBJECTS = test_crypto_hkdf.$(OBJEXT) test_crypto_hkdf_OBJECTS = $(am_test_crypto_hkdf_OBJECTS) test_crypto_hkdf_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_crypto_paillier_OBJECTS = test_crypto_paillier.$(OBJEXT) test_crypto_paillier_OBJECTS = $(am_test_crypto_paillier_OBJECTS) test_crypto_paillier_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_crypto_random_OBJECTS = test_crypto_random.$(OBJEXT) test_crypto_random_OBJECTS = $(am_test_crypto_random_OBJECTS) test_crypto_random_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_crypto_symmetric_OBJECTS = test_crypto_symmetric.$(OBJEXT) test_crypto_symmetric_OBJECTS = $(am_test_crypto_symmetric_OBJECTS) test_crypto_symmetric_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_disk_OBJECTS = test_disk.$(OBJEXT) test_disk_OBJECTS = $(am_test_disk_OBJECTS) test_disk_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_getopt_OBJECTS = test_getopt.$(OBJEXT) test_getopt_OBJECTS = $(am_test_getopt_OBJECTS) test_getopt_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_mq_OBJECTS = test_mq.$(OBJEXT) test_mq_OBJECTS = $(am_test_mq_OBJECTS) test_mq_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_mq_client_OBJECTS = test_mq_client.$(OBJEXT) test_mq_client_OBJECTS = $(am_test_mq_client_OBJECTS) test_mq_client_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_os_network_OBJECTS = test_os_network.$(OBJEXT) test_os_network_OBJECTS = $(am_test_os_network_OBJECTS) test_os_network_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_os_start_process_OBJECTS = test_os_start_process.$(OBJEXT) test_os_start_process_OBJECTS = $(am_test_os_start_process_OBJECTS) am_test_peer_OBJECTS = test_peer.$(OBJEXT) test_peer_OBJECTS = $(am_test_peer_OBJECTS) test_peer_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_OBJECTS = test_plugin.$(OBJEXT) test_plugin_OBJECTS = $(am_test_plugin_OBJECTS) test_plugin_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_program_OBJECTS = test_program.$(OBJEXT) test_program_OBJECTS = $(am_test_program_OBJECTS) test_program_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_resolver_api_OBJECTS = test_resolver_api.$(OBJEXT) test_resolver_api_OBJECTS = $(am_test_resolver_api_OBJECTS) test_resolver_api_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_scheduler_OBJECTS = test_scheduler.$(OBJEXT) test_scheduler_OBJECTS = $(am_test_scheduler_OBJECTS) test_scheduler_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_scheduler_delay_OBJECTS = test_scheduler_delay.$(OBJEXT) test_scheduler_delay_OBJECTS = $(am_test_scheduler_delay_OBJECTS) test_scheduler_delay_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_server_OBJECTS = test_server.$(OBJEXT) test_server_OBJECTS = $(am_test_server_OBJECTS) test_server_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_server_disconnect_OBJECTS = test_server_disconnect.$(OBJEXT) test_server_disconnect_OBJECTS = $(am_test_server_disconnect_OBJECTS) test_server_disconnect_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_server_mst_interrupt_OBJECTS = \ test_server_mst_interrupt.$(OBJEXT) test_server_mst_interrupt_OBJECTS = \ $(am_test_server_mst_interrupt_OBJECTS) test_server_mst_interrupt_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_server_with_client_OBJECTS = \ test_server_with_client.$(OBJEXT) test_server_with_client_OBJECTS = \ $(am_test_server_with_client_OBJECTS) test_server_with_client_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_server_with_client_unix_OBJECTS = \ test_server_with_client_unix.$(OBJEXT) test_server_with_client_unix_OBJECTS = \ $(am_test_server_with_client_unix_OBJECTS) test_server_with_client_unix_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_service_OBJECTS = test_service.$(OBJEXT) test_service_OBJECTS = $(am_test_service_OBJECTS) test_service_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_speedup_OBJECTS = test_speedup.$(OBJEXT) test_speedup_OBJECTS = $(am_test_speedup_OBJECTS) test_speedup_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_strings_OBJECTS = test_strings.$(OBJEXT) test_strings_OBJECTS = $(am_test_strings_OBJECTS) test_strings_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_strings_to_data_OBJECTS = test_strings_to_data.$(OBJEXT) test_strings_to_data_OBJECTS = $(am_test_strings_to_data_OBJECTS) test_strings_to_data_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_time_OBJECTS = test_time.$(OBJEXT) test_time_OBJECTS = $(am_test_time_OBJECTS) test_time_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_w32cat_OBJECTS = w32cat.$(OBJEXT) w32cat_OBJECTS = $(am_w32cat_OBJECTS) w32cat_LDADD = $(LDADD) SCRIPTS = $(bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_test_la_SOURCES) \ $(libgnunetutil_la_SOURCES) $(libgnunetutilwin_la_SOURCES) \ $(gnunet_config_SOURCES) $(gnunet_config_diff_SOURCES) \ $(gnunet_ecc_SOURCES) $(gnunet_helper_w32_console_SOURCES) \ $(gnunet_resolver_SOURCES) $(gnunet_scrypt_SOURCES) \ $(gnunet_service_resolver_SOURCES) $(gnunet_uri_SOURCES) \ $(perf_crypto_hash_SOURCES) $(perf_crypto_symmetric_SOURCES) \ $(perf_malloc_SOURCES) $(test_bio_SOURCES) \ $(test_client_SOURCES) $(test_common_allocation_SOURCES) \ $(test_common_endian_SOURCES) $(test_common_logging_SOURCES) \ $(test_common_logging_dummy_SOURCES) \ $(test_common_logging_runtime_loglevels_SOURCES) \ $(test_configuration_SOURCES) $(test_connection_SOURCES) \ $(test_connection_addressing_SOURCES) \ $(test_connection_receive_cancel_SOURCES) \ $(test_connection_timeout_SOURCES) \ $(test_connection_timeout_no_connect_SOURCES) \ $(test_connection_transmit_cancel_SOURCES) \ $(test_container_bloomfilter_SOURCES) \ $(test_container_heap_SOURCES) \ $(test_container_meta_data_SOURCES) \ $(test_container_multihashmap_SOURCES) \ $(test_container_multihashmap32_SOURCES) \ $(test_container_multipeermap_SOURCES) \ $(test_container_slist_SOURCES) $(test_crypto_crc_SOURCES) \ $(test_crypto_ecdhe_SOURCES) $(test_crypto_ecdsa_SOURCES) \ $(test_crypto_eddsa_SOURCES) $(test_crypto_hash_SOURCES) \ $(test_crypto_hkdf_SOURCES) $(test_crypto_paillier_SOURCES) \ $(test_crypto_random_SOURCES) $(test_crypto_symmetric_SOURCES) \ $(test_disk_SOURCES) $(test_getopt_SOURCES) $(test_mq_SOURCES) \ $(test_mq_client_SOURCES) $(test_os_network_SOURCES) \ $(test_os_start_process_SOURCES) $(test_peer_SOURCES) \ $(test_plugin_SOURCES) $(test_program_SOURCES) \ $(test_resolver_api_SOURCES) $(test_scheduler_SOURCES) \ $(test_scheduler_delay_SOURCES) $(test_server_SOURCES) \ $(test_server_disconnect_SOURCES) \ $(test_server_mst_interrupt_SOURCES) \ $(test_server_with_client_SOURCES) \ $(test_server_with_client_unix_SOURCES) \ $(test_service_SOURCES) $(test_speedup_SOURCES) \ $(test_strings_SOURCES) $(test_strings_to_data_SOURCES) \ $(test_time_SOURCES) $(w32cat_SOURCES) DIST_SOURCES = $(libgnunet_plugin_test_la_SOURCES) \ $(libgnunetutil_la_SOURCES) \ $(am__libgnunetutilwin_la_SOURCES_DIST) \ $(gnunet_config_SOURCES) $(gnunet_config_diff_SOURCES) \ $(gnunet_ecc_SOURCES) $(gnunet_helper_w32_console_SOURCES) \ $(gnunet_resolver_SOURCES) $(gnunet_scrypt_SOURCES) \ $(gnunet_service_resolver_SOURCES) $(gnunet_uri_SOURCES) \ $(perf_crypto_hash_SOURCES) $(perf_crypto_symmetric_SOURCES) \ $(perf_malloc_SOURCES) $(test_bio_SOURCES) \ $(test_client_SOURCES) $(test_common_allocation_SOURCES) \ $(test_common_endian_SOURCES) $(test_common_logging_SOURCES) \ $(test_common_logging_dummy_SOURCES) \ $(test_common_logging_runtime_loglevels_SOURCES) \ $(test_configuration_SOURCES) $(test_connection_SOURCES) \ $(test_connection_addressing_SOURCES) \ $(test_connection_receive_cancel_SOURCES) \ $(test_connection_timeout_SOURCES) \ $(test_connection_timeout_no_connect_SOURCES) \ $(test_connection_transmit_cancel_SOURCES) \ $(test_container_bloomfilter_SOURCES) \ $(test_container_heap_SOURCES) \ $(test_container_meta_data_SOURCES) \ $(test_container_multihashmap_SOURCES) \ $(test_container_multihashmap32_SOURCES) \ $(test_container_multipeermap_SOURCES) \ $(test_container_slist_SOURCES) $(test_crypto_crc_SOURCES) \ $(test_crypto_ecdhe_SOURCES) $(test_crypto_ecdsa_SOURCES) \ $(test_crypto_eddsa_SOURCES) $(test_crypto_hash_SOURCES) \ $(test_crypto_hkdf_SOURCES) $(test_crypto_paillier_SOURCES) \ $(test_crypto_random_SOURCES) $(test_crypto_symmetric_SOURCES) \ $(test_disk_SOURCES) $(test_getopt_SOURCES) $(test_mq_SOURCES) \ $(test_mq_client_SOURCES) $(test_os_network_SOURCES) \ $(test_os_start_process_SOURCES) $(test_peer_SOURCES) \ $(test_plugin_SOURCES) $(test_program_SOURCES) \ $(test_resolver_api_SOURCES) $(test_scheduler_SOURCES) \ $(test_scheduler_delay_SOURCES) $(test_server_SOURCES) \ $(test_server_disconnect_SOURCES) \ $(test_server_mst_interrupt_SOURCES) \ $(test_server_with_client_SOURCES) \ $(test_server_with_client_unix_SOURCES) \ $(test_service_SOURCES) $(test_speedup_SOURCES) \ $(test_strings_SOURCES) $(test_strings_to_data_SOURCES) \ $(test_time_SOURCES) $(w32cat_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_pkgcfg_DATA) $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ util.conf pkgcfg_DATA = \ resolver.conf @MINGW_TRUE@noinst_LTLIBRARIES = \ @MINGW_TRUE@ libgnunetutilwin.la @MINGW_TRUE@libgnunetutilwin_la_SOURCES = \ @MINGW_TRUE@ win.c \ @MINGW_TRUE@ winproc.c @MINGW_TRUE@libgnunetutilwin_la_LDFLAGS = \ @MINGW_TRUE@ -no-undefined -Wl,--export-all-symbols @MINGW_TRUE@libgnunetutilwin_la_LIBADD = \ @MINGW_TRUE@ -lshell32 -liconv -lstdc++ \ @MINGW_TRUE@ -lcomdlg32 -lgdi32 -liphlpapi @MINGW_TRUE@WINLIB = libgnunetutilwin.la @MINGW_TRUE@W32CAT = w32cat @MINGW_TRUE@W32CONSOLEHELPER = gnunet-helper-w32-console @MINGW_FALSE@SERVER_CLIENT_UNIX = test_server_with_client_unix @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov w32cat_SOURCES = w32cat.c gnunet_helper_w32_console_SOURCES = \ gnunet-helper-w32-console.c \ gnunet-helper-w32-console.h gnunet_helper_w32_console_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_helper_w32_console_DEPENDENCIES = \ libgnunetutil.la gnunet_config_diff_SOURCES = \ gnunet-config-diff.c gnunet_config_diff_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_config_diff_DEPENDENCIES = \ libgnunetutil.la test_common_logging_dummy_SOURCES = \ test_common_logging_dummy.c test_common_logging_dummy_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_logging_dummy_DEPENDENCIES = \ libgnunetutil.la lib_LTLIBRARIES = libgnunetutil.la libgnunetutil_la_SOURCES = \ bandwidth.c \ bio.c \ client.c \ common_allocation.c \ common_endian.c \ common_logging.c \ configuration.c \ connection.c \ container_bloomfilter.c \ container_heap.c \ container_meta_data.c \ container_multihashmap.c \ container_multipeermap.c \ container_multihashmap32.c \ container_slist.c \ crypto_symmetric.c \ crypto_crc.c \ crypto_ecc.c \ crypto_hash.c \ crypto_hkdf.c \ crypto_kdf.c \ crypto_mpi.c \ crypto_paillier.c \ crypto_random.c \ disk.c \ disk.h \ getopt.c \ getopt_helpers.c \ helper.c \ load.c \ mq.c \ network.c \ os_installation.c \ os_network.c \ os_priority.c \ peer.c \ plugin.c \ program.c \ resolver_api.c resolver.h \ scheduler.c \ server.c \ server_mst.c \ server_nc.c \ server_tc.c \ service.c \ signal.c \ strings.c \ time.c \ speedup.c speedup.h libgnunetutil_la_LIBADD = \ $(GCLIBADD) $(WINLIB) \ $(LIBGCRYPT_LIBS) \ $(LTLIBICONV) \ $(LTLIBINTL) \ -lltdl $(Z_LIBS) -lunistring $(XLIB) libgnunetutil_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 12:0:0 @HAVE_TESTING_TRUE@GNUNET_ECC = gnunet-ecc @HAVE_TESTING_TRUE@GNUNET_SCRYPT = gnunet-scrypt bin_SCRIPTS = \ gnunet-qr do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' gnunet_service_resolver_SOURCES = \ gnunet-service-resolver.c gnunet_service_resolver_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_resolver_DEPENDENCIES = \ libgnunetutil.la gnunet_resolver_SOURCES = \ gnunet-resolver.c gnunet_resolver_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_resolver_DEPENDENCIES = \ libgnunetutil.la gnunet_ecc_SOURCES = \ gnunet-ecc.c gnunet_ecc_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) -lgcrypt gnunet_ecc_DEPENDENCIES = \ libgnunetutil.la gnunet_scrypt_SOURCES = \ gnunet-scrypt.c gnunet_scrypt_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) -lgcrypt gnunet_scrypt_DEPENDENCIES = \ libgnunetutil.la gnunet_config_SOURCES = \ gnunet-config.c gnunet_config_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_config_DEPENDENCIES = \ libgnunetutil.la gnunet_uri_SOURCES = \ gnunet-uri.c gnunet_uri_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_uri_DEPENDENCIES = \ libgnunetutil.la plugin_LTLIBRARIES = \ libgnunet_plugin_test.la libgnunet_plugin_test_la_SOURCES = \ test_plugin_plug.c libgnunet_plugin_test_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) @HAVE_BENCHMARKS_TRUE@BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@ perf_crypto_hash \ @HAVE_BENCHMARKS_TRUE@ perf_crypto_symmetric \ @HAVE_BENCHMARKS_TRUE@ perf_malloc @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_bio_SOURCES = \ test_bio.c test_bio_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_os_start_process_SOURCES = \ test_os_start_process.c test_os_start_process_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_os_start_process_DEPENDENCIES = \ $(WINCAT) test_client_SOURCES = \ test_client.c test_client_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_allocation_SOURCES = \ test_common_allocation.c test_common_allocation_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_endian_SOURCES = \ test_common_endian.c test_common_endian_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_logging_SOURCES = \ test_common_logging.c test_common_logging_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_logging_runtime_loglevels_SOURCES = \ test_common_logging_runtime_loglevels.c test_common_logging_runtime_loglevels_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_configuration_SOURCES = \ test_configuration.c test_configuration_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_bloomfilter_SOURCES = \ test_container_bloomfilter.c test_container_bloomfilter_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_meta_data_SOURCES = \ test_container_meta_data.c test_container_meta_data_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la -lextractor test_container_multihashmap_SOURCES = \ test_container_multihashmap.c test_container_multihashmap_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_multihashmap32_SOURCES = \ test_container_multihashmap32.c test_container_multihashmap32_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_multipeermap_SOURCES = \ test_container_multipeermap.c test_container_multipeermap_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_heap_SOURCES = \ test_container_heap.c test_container_heap_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_slist_SOURCES = \ test_container_slist.c test_container_slist_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_symmetric_SOURCES = \ test_crypto_symmetric.c test_crypto_symmetric_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_crc_SOURCES = \ test_crypto_crc.c test_crypto_crc_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_ecdsa_SOURCES = \ test_crypto_ecdsa.c test_crypto_ecdsa_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) test_crypto_eddsa_SOURCES = \ test_crypto_eddsa.c test_crypto_eddsa_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) test_crypto_ecdhe_SOURCES = \ test_crypto_ecdhe.c test_crypto_ecdhe_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) test_crypto_hash_SOURCES = \ test_crypto_hash.c test_crypto_hash_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_hkdf_SOURCES = \ test_crypto_hkdf.c test_crypto_hkdf_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_paillier_SOURCES = \ test_crypto_paillier.c test_crypto_paillier_LDADD = \ -lgcrypt \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_random_SOURCES = \ test_crypto_random.c test_crypto_random_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_disk_SOURCES = \ test_disk.c test_disk_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_getopt_SOURCES = \ test_getopt.c test_getopt_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_SOURCES = \ test_connection.c test_connection_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_addressing_SOURCES = \ test_connection_addressing.c test_connection_addressing_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_receive_cancel_SOURCES = \ test_connection_receive_cancel.c test_connection_receive_cancel_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_timeout_SOURCES = \ test_connection_timeout.c test_connection_timeout_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_timeout_no_connect_SOURCES = \ test_connection_timeout_no_connect.c test_connection_timeout_no_connect_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_transmit_cancel_SOURCES = \ test_connection_transmit_cancel.c test_connection_transmit_cancel_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_mq_SOURCES = \ test_mq.c test_mq_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_mq_client_SOURCES = \ test_mq_client.c test_mq_client_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_os_network_SOURCES = \ test_os_network.c test_os_network_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_peer_SOURCES = \ test_peer.c test_peer_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la -lgcrypt test_plugin_SOURCES = \ test_plugin.c test_plugin_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_program_SOURCES = \ test_program.c test_program_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_resolver_api_SOURCES = \ test_resolver_api.c test_resolver_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_scheduler_SOURCES = \ test_scheduler.c test_scheduler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_scheduler_delay_SOURCES = \ test_scheduler_delay.c test_scheduler_delay_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_mst_interrupt_SOURCES = \ test_server_mst_interrupt.c test_server_mst_interrupt_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_SOURCES = \ test_server.c test_server_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_disconnect_SOURCES = \ test_server_disconnect.c test_server_disconnect_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_with_client_SOURCES = \ test_server_with_client.c test_server_with_client_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_with_client_unix_SOURCES = \ test_server_with_client_unix.c test_server_with_client_unix_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_service_SOURCES = \ test_service.c test_service_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_strings_SOURCES = \ test_strings.c test_strings_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_strings_to_data_SOURCES = \ test_strings_to_data.c test_strings_to_data_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_time_SOURCES = \ test_time.c test_time_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_speedup_SOURCES = \ test_speedup.c test_speedup_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la perf_crypto_hash_SOURCES = \ perf_crypto_hash.c perf_crypto_hash_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la perf_crypto_symmetric_SOURCES = \ perf_crypto_symmetric.c perf_crypto_symmetric_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la perf_malloc_SOURCES = \ perf_malloc.c perf_malloc_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_configuration_data.conf \ test_program_data.conf \ test_resolver_api_data.conf \ test_service_data.conf \ test_speedup_data.conf \ gnunet-qr.py.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/util/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/util/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): resolver.conf: $(top_builddir)/config.status $(srcdir)/resolver.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_test.la: $(libgnunet_plugin_test_la_OBJECTS) $(libgnunet_plugin_test_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_test_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_test_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_test_la_OBJECTS) $(libgnunet_plugin_test_la_LIBADD) $(LIBS) libgnunetutil.la: $(libgnunetutil_la_OBJECTS) $(libgnunetutil_la_DEPENDENCIES) $(EXTRA_libgnunetutil_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetutil_la_LINK) -rpath $(libdir) $(libgnunetutil_la_OBJECTS) $(libgnunetutil_la_LIBADD) $(LIBS) libgnunetutilwin.la: $(libgnunetutilwin_la_OBJECTS) $(libgnunetutilwin_la_DEPENDENCIES) $(EXTRA_libgnunetutilwin_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetutilwin_la_LINK) $(am_libgnunetutilwin_la_rpath) $(libgnunetutilwin_la_OBJECTS) $(libgnunetutilwin_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-config$(EXEEXT): $(gnunet_config_OBJECTS) $(gnunet_config_DEPENDENCIES) $(EXTRA_gnunet_config_DEPENDENCIES) @rm -f gnunet-config$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_config_OBJECTS) $(gnunet_config_LDADD) $(LIBS) gnunet-config-diff$(EXEEXT): $(gnunet_config_diff_OBJECTS) $(gnunet_config_diff_DEPENDENCIES) $(EXTRA_gnunet_config_diff_DEPENDENCIES) @rm -f gnunet-config-diff$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_config_diff_OBJECTS) $(gnunet_config_diff_LDADD) $(LIBS) gnunet-ecc$(EXEEXT): $(gnunet_ecc_OBJECTS) $(gnunet_ecc_DEPENDENCIES) $(EXTRA_gnunet_ecc_DEPENDENCIES) @rm -f gnunet-ecc$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_ecc_OBJECTS) $(gnunet_ecc_LDADD) $(LIBS) gnunet-helper-w32-console$(EXEEXT): $(gnunet_helper_w32_console_OBJECTS) $(gnunet_helper_w32_console_DEPENDENCIES) $(EXTRA_gnunet_helper_w32_console_DEPENDENCIES) @rm -f gnunet-helper-w32-console$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_helper_w32_console_OBJECTS) $(gnunet_helper_w32_console_LDADD) $(LIBS) gnunet-resolver$(EXEEXT): $(gnunet_resolver_OBJECTS) $(gnunet_resolver_DEPENDENCIES) $(EXTRA_gnunet_resolver_DEPENDENCIES) @rm -f gnunet-resolver$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_resolver_OBJECTS) $(gnunet_resolver_LDADD) $(LIBS) gnunet-scrypt$(EXEEXT): $(gnunet_scrypt_OBJECTS) $(gnunet_scrypt_DEPENDENCIES) $(EXTRA_gnunet_scrypt_DEPENDENCIES) @rm -f gnunet-scrypt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_scrypt_OBJECTS) $(gnunet_scrypt_LDADD) $(LIBS) gnunet-service-resolver$(EXEEXT): $(gnunet_service_resolver_OBJECTS) $(gnunet_service_resolver_DEPENDENCIES) $(EXTRA_gnunet_service_resolver_DEPENDENCIES) @rm -f gnunet-service-resolver$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_resolver_OBJECTS) $(gnunet_service_resolver_LDADD) $(LIBS) gnunet-uri$(EXEEXT): $(gnunet_uri_OBJECTS) $(gnunet_uri_DEPENDENCIES) $(EXTRA_gnunet_uri_DEPENDENCIES) @rm -f gnunet-uri$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_uri_OBJECTS) $(gnunet_uri_LDADD) $(LIBS) perf_crypto_hash$(EXEEXT): $(perf_crypto_hash_OBJECTS) $(perf_crypto_hash_DEPENDENCIES) $(EXTRA_perf_crypto_hash_DEPENDENCIES) @rm -f perf_crypto_hash$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_crypto_hash_OBJECTS) $(perf_crypto_hash_LDADD) $(LIBS) perf_crypto_symmetric$(EXEEXT): $(perf_crypto_symmetric_OBJECTS) $(perf_crypto_symmetric_DEPENDENCIES) $(EXTRA_perf_crypto_symmetric_DEPENDENCIES) @rm -f perf_crypto_symmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_crypto_symmetric_OBJECTS) $(perf_crypto_symmetric_LDADD) $(LIBS) perf_malloc$(EXEEXT): $(perf_malloc_OBJECTS) $(perf_malloc_DEPENDENCIES) $(EXTRA_perf_malloc_DEPENDENCIES) @rm -f perf_malloc$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_malloc_OBJECTS) $(perf_malloc_LDADD) $(LIBS) test_bio$(EXEEXT): $(test_bio_OBJECTS) $(test_bio_DEPENDENCIES) $(EXTRA_test_bio_DEPENDENCIES) @rm -f test_bio$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_bio_OBJECTS) $(test_bio_LDADD) $(LIBS) test_client$(EXEEXT): $(test_client_OBJECTS) $(test_client_DEPENDENCIES) $(EXTRA_test_client_DEPENDENCIES) @rm -f test_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_client_OBJECTS) $(test_client_LDADD) $(LIBS) test_common_allocation$(EXEEXT): $(test_common_allocation_OBJECTS) $(test_common_allocation_DEPENDENCIES) $(EXTRA_test_common_allocation_DEPENDENCIES) @rm -f test_common_allocation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_allocation_OBJECTS) $(test_common_allocation_LDADD) $(LIBS) test_common_endian$(EXEEXT): $(test_common_endian_OBJECTS) $(test_common_endian_DEPENDENCIES) $(EXTRA_test_common_endian_DEPENDENCIES) @rm -f test_common_endian$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_endian_OBJECTS) $(test_common_endian_LDADD) $(LIBS) test_common_logging$(EXEEXT): $(test_common_logging_OBJECTS) $(test_common_logging_DEPENDENCIES) $(EXTRA_test_common_logging_DEPENDENCIES) @rm -f test_common_logging$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_logging_OBJECTS) $(test_common_logging_LDADD) $(LIBS) test_common_logging_dummy$(EXEEXT): $(test_common_logging_dummy_OBJECTS) $(test_common_logging_dummy_DEPENDENCIES) $(EXTRA_test_common_logging_dummy_DEPENDENCIES) @rm -f test_common_logging_dummy$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_logging_dummy_OBJECTS) $(test_common_logging_dummy_LDADD) $(LIBS) test_common_logging_runtime_loglevels$(EXEEXT): $(test_common_logging_runtime_loglevels_OBJECTS) $(test_common_logging_runtime_loglevels_DEPENDENCIES) $(EXTRA_test_common_logging_runtime_loglevels_DEPENDENCIES) @rm -f test_common_logging_runtime_loglevels$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_logging_runtime_loglevels_OBJECTS) $(test_common_logging_runtime_loglevels_LDADD) $(LIBS) test_configuration$(EXEEXT): $(test_configuration_OBJECTS) $(test_configuration_DEPENDENCIES) $(EXTRA_test_configuration_DEPENDENCIES) @rm -f test_configuration$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_configuration_OBJECTS) $(test_configuration_LDADD) $(LIBS) test_connection$(EXEEXT): $(test_connection_OBJECTS) $(test_connection_DEPENDENCIES) $(EXTRA_test_connection_DEPENDENCIES) @rm -f test_connection$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_OBJECTS) $(test_connection_LDADD) $(LIBS) test_connection_addressing$(EXEEXT): $(test_connection_addressing_OBJECTS) $(test_connection_addressing_DEPENDENCIES) $(EXTRA_test_connection_addressing_DEPENDENCIES) @rm -f test_connection_addressing$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_addressing_OBJECTS) $(test_connection_addressing_LDADD) $(LIBS) test_connection_receive_cancel$(EXEEXT): $(test_connection_receive_cancel_OBJECTS) $(test_connection_receive_cancel_DEPENDENCIES) $(EXTRA_test_connection_receive_cancel_DEPENDENCIES) @rm -f test_connection_receive_cancel$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_receive_cancel_OBJECTS) $(test_connection_receive_cancel_LDADD) $(LIBS) test_connection_timeout$(EXEEXT): $(test_connection_timeout_OBJECTS) $(test_connection_timeout_DEPENDENCIES) $(EXTRA_test_connection_timeout_DEPENDENCIES) @rm -f test_connection_timeout$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_timeout_OBJECTS) $(test_connection_timeout_LDADD) $(LIBS) test_connection_timeout_no_connect$(EXEEXT): $(test_connection_timeout_no_connect_OBJECTS) $(test_connection_timeout_no_connect_DEPENDENCIES) $(EXTRA_test_connection_timeout_no_connect_DEPENDENCIES) @rm -f test_connection_timeout_no_connect$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_timeout_no_connect_OBJECTS) $(test_connection_timeout_no_connect_LDADD) $(LIBS) test_connection_transmit_cancel$(EXEEXT): $(test_connection_transmit_cancel_OBJECTS) $(test_connection_transmit_cancel_DEPENDENCIES) $(EXTRA_test_connection_transmit_cancel_DEPENDENCIES) @rm -f test_connection_transmit_cancel$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_transmit_cancel_OBJECTS) $(test_connection_transmit_cancel_LDADD) $(LIBS) test_container_bloomfilter$(EXEEXT): $(test_container_bloomfilter_OBJECTS) $(test_container_bloomfilter_DEPENDENCIES) $(EXTRA_test_container_bloomfilter_DEPENDENCIES) @rm -f test_container_bloomfilter$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_bloomfilter_OBJECTS) $(test_container_bloomfilter_LDADD) $(LIBS) test_container_heap$(EXEEXT): $(test_container_heap_OBJECTS) $(test_container_heap_DEPENDENCIES) $(EXTRA_test_container_heap_DEPENDENCIES) @rm -f test_container_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_heap_OBJECTS) $(test_container_heap_LDADD) $(LIBS) test_container_meta_data$(EXEEXT): $(test_container_meta_data_OBJECTS) $(test_container_meta_data_DEPENDENCIES) $(EXTRA_test_container_meta_data_DEPENDENCIES) @rm -f test_container_meta_data$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_meta_data_OBJECTS) $(test_container_meta_data_LDADD) $(LIBS) test_container_multihashmap$(EXEEXT): $(test_container_multihashmap_OBJECTS) $(test_container_multihashmap_DEPENDENCIES) $(EXTRA_test_container_multihashmap_DEPENDENCIES) @rm -f test_container_multihashmap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_multihashmap_OBJECTS) $(test_container_multihashmap_LDADD) $(LIBS) test_container_multihashmap32$(EXEEXT): $(test_container_multihashmap32_OBJECTS) $(test_container_multihashmap32_DEPENDENCIES) $(EXTRA_test_container_multihashmap32_DEPENDENCIES) @rm -f test_container_multihashmap32$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_multihashmap32_OBJECTS) $(test_container_multihashmap32_LDADD) $(LIBS) test_container_multipeermap$(EXEEXT): $(test_container_multipeermap_OBJECTS) $(test_container_multipeermap_DEPENDENCIES) $(EXTRA_test_container_multipeermap_DEPENDENCIES) @rm -f test_container_multipeermap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_multipeermap_OBJECTS) $(test_container_multipeermap_LDADD) $(LIBS) test_container_slist$(EXEEXT): $(test_container_slist_OBJECTS) $(test_container_slist_DEPENDENCIES) $(EXTRA_test_container_slist_DEPENDENCIES) @rm -f test_container_slist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_slist_OBJECTS) $(test_container_slist_LDADD) $(LIBS) test_crypto_crc$(EXEEXT): $(test_crypto_crc_OBJECTS) $(test_crypto_crc_DEPENDENCIES) $(EXTRA_test_crypto_crc_DEPENDENCIES) @rm -f test_crypto_crc$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_crc_OBJECTS) $(test_crypto_crc_LDADD) $(LIBS) test_crypto_ecdhe$(EXEEXT): $(test_crypto_ecdhe_OBJECTS) $(test_crypto_ecdhe_DEPENDENCIES) $(EXTRA_test_crypto_ecdhe_DEPENDENCIES) @rm -f test_crypto_ecdhe$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_ecdhe_OBJECTS) $(test_crypto_ecdhe_LDADD) $(LIBS) test_crypto_ecdsa$(EXEEXT): $(test_crypto_ecdsa_OBJECTS) $(test_crypto_ecdsa_DEPENDENCIES) $(EXTRA_test_crypto_ecdsa_DEPENDENCIES) @rm -f test_crypto_ecdsa$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_ecdsa_OBJECTS) $(test_crypto_ecdsa_LDADD) $(LIBS) test_crypto_eddsa$(EXEEXT): $(test_crypto_eddsa_OBJECTS) $(test_crypto_eddsa_DEPENDENCIES) $(EXTRA_test_crypto_eddsa_DEPENDENCIES) @rm -f test_crypto_eddsa$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_eddsa_OBJECTS) $(test_crypto_eddsa_LDADD) $(LIBS) test_crypto_hash$(EXEEXT): $(test_crypto_hash_OBJECTS) $(test_crypto_hash_DEPENDENCIES) $(EXTRA_test_crypto_hash_DEPENDENCIES) @rm -f test_crypto_hash$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_hash_OBJECTS) $(test_crypto_hash_LDADD) $(LIBS) test_crypto_hkdf$(EXEEXT): $(test_crypto_hkdf_OBJECTS) $(test_crypto_hkdf_DEPENDENCIES) $(EXTRA_test_crypto_hkdf_DEPENDENCIES) @rm -f test_crypto_hkdf$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_hkdf_OBJECTS) $(test_crypto_hkdf_LDADD) $(LIBS) test_crypto_paillier$(EXEEXT): $(test_crypto_paillier_OBJECTS) $(test_crypto_paillier_DEPENDENCIES) $(EXTRA_test_crypto_paillier_DEPENDENCIES) @rm -f test_crypto_paillier$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_paillier_OBJECTS) $(test_crypto_paillier_LDADD) $(LIBS) test_crypto_random$(EXEEXT): $(test_crypto_random_OBJECTS) $(test_crypto_random_DEPENDENCIES) $(EXTRA_test_crypto_random_DEPENDENCIES) @rm -f test_crypto_random$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_random_OBJECTS) $(test_crypto_random_LDADD) $(LIBS) test_crypto_symmetric$(EXEEXT): $(test_crypto_symmetric_OBJECTS) $(test_crypto_symmetric_DEPENDENCIES) $(EXTRA_test_crypto_symmetric_DEPENDENCIES) @rm -f test_crypto_symmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_symmetric_OBJECTS) $(test_crypto_symmetric_LDADD) $(LIBS) test_disk$(EXEEXT): $(test_disk_OBJECTS) $(test_disk_DEPENDENCIES) $(EXTRA_test_disk_DEPENDENCIES) @rm -f test_disk$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_disk_OBJECTS) $(test_disk_LDADD) $(LIBS) test_getopt$(EXEEXT): $(test_getopt_OBJECTS) $(test_getopt_DEPENDENCIES) $(EXTRA_test_getopt_DEPENDENCIES) @rm -f test_getopt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_getopt_OBJECTS) $(test_getopt_LDADD) $(LIBS) test_mq$(EXEEXT): $(test_mq_OBJECTS) $(test_mq_DEPENDENCIES) $(EXTRA_test_mq_DEPENDENCIES) @rm -f test_mq$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mq_OBJECTS) $(test_mq_LDADD) $(LIBS) test_mq_client$(EXEEXT): $(test_mq_client_OBJECTS) $(test_mq_client_DEPENDENCIES) $(EXTRA_test_mq_client_DEPENDENCIES) @rm -f test_mq_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mq_client_OBJECTS) $(test_mq_client_LDADD) $(LIBS) test_os_network$(EXEEXT): $(test_os_network_OBJECTS) $(test_os_network_DEPENDENCIES) $(EXTRA_test_os_network_DEPENDENCIES) @rm -f test_os_network$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_os_network_OBJECTS) $(test_os_network_LDADD) $(LIBS) test_os_start_process$(EXEEXT): $(test_os_start_process_OBJECTS) $(test_os_start_process_DEPENDENCIES) $(EXTRA_test_os_start_process_DEPENDENCIES) @rm -f test_os_start_process$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_os_start_process_OBJECTS) $(test_os_start_process_LDADD) $(LIBS) test_peer$(EXEEXT): $(test_peer_OBJECTS) $(test_peer_DEPENDENCIES) $(EXTRA_test_peer_DEPENDENCIES) @rm -f test_peer$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_peer_OBJECTS) $(test_peer_LDADD) $(LIBS) test_plugin$(EXEEXT): $(test_plugin_OBJECTS) $(test_plugin_DEPENDENCIES) $(EXTRA_test_plugin_DEPENDENCIES) @rm -f test_plugin$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_OBJECTS) $(test_plugin_LDADD) $(LIBS) test_program$(EXEEXT): $(test_program_OBJECTS) $(test_program_DEPENDENCIES) $(EXTRA_test_program_DEPENDENCIES) @rm -f test_program$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_program_OBJECTS) $(test_program_LDADD) $(LIBS) test_resolver_api$(EXEEXT): $(test_resolver_api_OBJECTS) $(test_resolver_api_DEPENDENCIES) $(EXTRA_test_resolver_api_DEPENDENCIES) @rm -f test_resolver_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_resolver_api_OBJECTS) $(test_resolver_api_LDADD) $(LIBS) test_scheduler$(EXEEXT): $(test_scheduler_OBJECTS) $(test_scheduler_DEPENDENCIES) $(EXTRA_test_scheduler_DEPENDENCIES) @rm -f test_scheduler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_scheduler_OBJECTS) $(test_scheduler_LDADD) $(LIBS) test_scheduler_delay$(EXEEXT): $(test_scheduler_delay_OBJECTS) $(test_scheduler_delay_DEPENDENCIES) $(EXTRA_test_scheduler_delay_DEPENDENCIES) @rm -f test_scheduler_delay$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_scheduler_delay_OBJECTS) $(test_scheduler_delay_LDADD) $(LIBS) test_server$(EXEEXT): $(test_server_OBJECTS) $(test_server_DEPENDENCIES) $(EXTRA_test_server_DEPENDENCIES) @rm -f test_server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_OBJECTS) $(test_server_LDADD) $(LIBS) test_server_disconnect$(EXEEXT): $(test_server_disconnect_OBJECTS) $(test_server_disconnect_DEPENDENCIES) $(EXTRA_test_server_disconnect_DEPENDENCIES) @rm -f test_server_disconnect$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_disconnect_OBJECTS) $(test_server_disconnect_LDADD) $(LIBS) test_server_mst_interrupt$(EXEEXT): $(test_server_mst_interrupt_OBJECTS) $(test_server_mst_interrupt_DEPENDENCIES) $(EXTRA_test_server_mst_interrupt_DEPENDENCIES) @rm -f test_server_mst_interrupt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_mst_interrupt_OBJECTS) $(test_server_mst_interrupt_LDADD) $(LIBS) test_server_with_client$(EXEEXT): $(test_server_with_client_OBJECTS) $(test_server_with_client_DEPENDENCIES) $(EXTRA_test_server_with_client_DEPENDENCIES) @rm -f test_server_with_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_with_client_OBJECTS) $(test_server_with_client_LDADD) $(LIBS) test_server_with_client_unix$(EXEEXT): $(test_server_with_client_unix_OBJECTS) $(test_server_with_client_unix_DEPENDENCIES) $(EXTRA_test_server_with_client_unix_DEPENDENCIES) @rm -f test_server_with_client_unix$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_with_client_unix_OBJECTS) $(test_server_with_client_unix_LDADD) $(LIBS) test_service$(EXEEXT): $(test_service_OBJECTS) $(test_service_DEPENDENCIES) $(EXTRA_test_service_DEPENDENCIES) @rm -f test_service$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_service_OBJECTS) $(test_service_LDADD) $(LIBS) test_speedup$(EXEEXT): $(test_speedup_OBJECTS) $(test_speedup_DEPENDENCIES) $(EXTRA_test_speedup_DEPENDENCIES) @rm -f test_speedup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_speedup_OBJECTS) $(test_speedup_LDADD) $(LIBS) test_strings$(EXEEXT): $(test_strings_OBJECTS) $(test_strings_DEPENDENCIES) $(EXTRA_test_strings_DEPENDENCIES) @rm -f test_strings$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_strings_OBJECTS) $(test_strings_LDADD) $(LIBS) test_strings_to_data$(EXEEXT): $(test_strings_to_data_OBJECTS) $(test_strings_to_data_DEPENDENCIES) $(EXTRA_test_strings_to_data_DEPENDENCIES) @rm -f test_strings_to_data$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_strings_to_data_OBJECTS) $(test_strings_to_data_LDADD) $(LIBS) test_time$(EXEEXT): $(test_time_OBJECTS) $(test_time_DEPENDENCIES) $(EXTRA_test_time_DEPENDENCIES) @rm -f test_time$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_time_OBJECTS) $(test_time_LDADD) $(LIBS) w32cat$(EXEEXT): $(w32cat_OBJECTS) $(w32cat_DEPENDENCIES) $(EXTRA_w32cat_DEPENDENCIES) @rm -f w32cat$(EXEEXT) $(AM_V_CCLD)$(LINK) $(w32cat_OBJECTS) $(w32cat_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bandwidth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_allocation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_endian.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/container_bloomfilter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/container_heap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/container_meta_data.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/container_multihashmap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/container_multihashmap32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/container_multipeermap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/container_slist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_crc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_ecc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_hkdf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_kdf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_mpi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_paillier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_random.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_symmetric.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt_helpers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-config-diff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-ecc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-w32-console.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-resolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-scrypt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-resolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-uri.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_installation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_network.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_priority.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_crypto_hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_crypto_symmetric.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_malloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/program.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolver_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheduler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_mst.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_nc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_tc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/service.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/speedup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strings.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_bio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_common_allocation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_common_endian.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_common_logging.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_common_logging_dummy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_common_logging_runtime_loglevels.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_configuration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_connection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_connection_addressing.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_connection_receive_cancel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_connection_timeout.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_connection_timeout_no_connect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_connection_transmit_cancel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_container_bloomfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_container_heap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_container_meta_data.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_container_multihashmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_container_multihashmap32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_container_multipeermap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_container_slist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_crc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_ecdhe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_ecdsa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_eddsa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_hkdf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_paillier.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_random.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_symmetric.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_disk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mq.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mq_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_os_network.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_os_start_process.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_peer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_plug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_program.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_resolver_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_scheduler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_scheduler_delay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_server_disconnect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_server_mst_interrupt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_server_with_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_server_with_client_unix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_service.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_speedup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_strings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_strings_to_data.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_time.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32cat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/winproc.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_bio.log: test_bio$(EXEEXT) @p='test_bio$(EXEEXT)'; \ b='test_bio'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_client.log: test_client$(EXEEXT) @p='test_client$(EXEEXT)'; \ b='test_client'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_common_allocation.log: test_common_allocation$(EXEEXT) @p='test_common_allocation$(EXEEXT)'; \ b='test_common_allocation'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_common_endian.log: test_common_endian$(EXEEXT) @p='test_common_endian$(EXEEXT)'; \ b='test_common_endian'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_common_logging.log: test_common_logging$(EXEEXT) @p='test_common_logging$(EXEEXT)'; \ b='test_common_logging'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_configuration.log: test_configuration$(EXEEXT) @p='test_configuration$(EXEEXT)'; \ b='test_configuration'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_container_bloomfilter.log: test_container_bloomfilter$(EXEEXT) @p='test_container_bloomfilter$(EXEEXT)'; \ b='test_container_bloomfilter'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_container_meta_data.log: test_container_meta_data$(EXEEXT) @p='test_container_meta_data$(EXEEXT)'; \ b='test_container_meta_data'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_container_multihashmap.log: test_container_multihashmap$(EXEEXT) @p='test_container_multihashmap$(EXEEXT)'; \ b='test_container_multihashmap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_container_multihashmap32.log: test_container_multihashmap32$(EXEEXT) @p='test_container_multihashmap32$(EXEEXT)'; \ b='test_container_multihashmap32'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_container_multipeermap.log: test_container_multipeermap$(EXEEXT) @p='test_container_multipeermap$(EXEEXT)'; \ b='test_container_multipeermap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_container_heap.log: test_container_heap$(EXEEXT) @p='test_container_heap$(EXEEXT)'; \ b='test_container_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_container_slist.log: test_container_slist$(EXEEXT) @p='test_container_slist$(EXEEXT)'; \ b='test_container_slist'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_symmetric.log: test_crypto_symmetric$(EXEEXT) @p='test_crypto_symmetric$(EXEEXT)'; \ b='test_crypto_symmetric'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_crc.log: test_crypto_crc$(EXEEXT) @p='test_crypto_crc$(EXEEXT)'; \ b='test_crypto_crc'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_ecdsa.log: test_crypto_ecdsa$(EXEEXT) @p='test_crypto_ecdsa$(EXEEXT)'; \ b='test_crypto_ecdsa'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_eddsa.log: test_crypto_eddsa$(EXEEXT) @p='test_crypto_eddsa$(EXEEXT)'; \ b='test_crypto_eddsa'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_ecdhe.log: test_crypto_ecdhe$(EXEEXT) @p='test_crypto_ecdhe$(EXEEXT)'; \ b='test_crypto_ecdhe'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_hash.log: test_crypto_hash$(EXEEXT) @p='test_crypto_hash$(EXEEXT)'; \ b='test_crypto_hash'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_hkdf.log: test_crypto_hkdf$(EXEEXT) @p='test_crypto_hkdf$(EXEEXT)'; \ b='test_crypto_hkdf'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_paillier.log: test_crypto_paillier$(EXEEXT) @p='test_crypto_paillier$(EXEEXT)'; \ b='test_crypto_paillier'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_crypto_random.log: test_crypto_random$(EXEEXT) @p='test_crypto_random$(EXEEXT)'; \ b='test_crypto_random'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_disk.log: test_disk$(EXEEXT) @p='test_disk$(EXEEXT)'; \ b='test_disk'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_getopt.log: test_getopt$(EXEEXT) @p='test_getopt$(EXEEXT)'; \ b='test_getopt'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_connection.log: test_connection$(EXEEXT) @p='test_connection$(EXEEXT)'; \ b='test_connection'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_connection_addressing.log: test_connection_addressing$(EXEEXT) @p='test_connection_addressing$(EXEEXT)'; \ b='test_connection_addressing'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_connection_receive_cancel.log: test_connection_receive_cancel$(EXEEXT) @p='test_connection_receive_cancel$(EXEEXT)'; \ b='test_connection_receive_cancel'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_connection_timeout.log: test_connection_timeout$(EXEEXT) @p='test_connection_timeout$(EXEEXT)'; \ b='test_connection_timeout'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_connection_timeout_no_connect.log: test_connection_timeout_no_connect$(EXEEXT) @p='test_connection_timeout_no_connect$(EXEEXT)'; \ b='test_connection_timeout_no_connect'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_connection_transmit_cancel.log: test_connection_transmit_cancel$(EXEEXT) @p='test_connection_transmit_cancel$(EXEEXT)'; \ b='test_connection_transmit_cancel'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mq.log: test_mq$(EXEEXT) @p='test_mq$(EXEEXT)'; \ b='test_mq'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mq_client.log: test_mq_client$(EXEEXT) @p='test_mq_client$(EXEEXT)'; \ b='test_mq_client'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_os_network.log: test_os_network$(EXEEXT) @p='test_os_network$(EXEEXT)'; \ b='test_os_network'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_peer.log: test_peer$(EXEEXT) @p='test_peer$(EXEEXT)'; \ b='test_peer'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin.log: test_plugin$(EXEEXT) @p='test_plugin$(EXEEXT)'; \ b='test_plugin'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_program.log: test_program$(EXEEXT) @p='test_program$(EXEEXT)'; \ b='test_program'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_resolver_api.log: test_resolver_api$(EXEEXT) @p='test_resolver_api$(EXEEXT)'; \ b='test_resolver_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_scheduler.log: test_scheduler$(EXEEXT) @p='test_scheduler$(EXEEXT)'; \ b='test_scheduler'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_scheduler_delay.log: test_scheduler_delay$(EXEEXT) @p='test_scheduler_delay$(EXEEXT)'; \ b='test_scheduler_delay'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_server_mst_interrupt.log: test_server_mst_interrupt$(EXEEXT) @p='test_server_mst_interrupt$(EXEEXT)'; \ b='test_server_mst_interrupt'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_server.log: test_server$(EXEEXT) @p='test_server$(EXEEXT)'; \ b='test_server'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_server_disconnect.log: test_server_disconnect$(EXEEXT) @p='test_server_disconnect$(EXEEXT)'; \ b='test_server_disconnect'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_server_with_client.log: test_server_with_client$(EXEEXT) @p='test_server_with_client$(EXEEXT)'; \ b='test_server_with_client'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_server_with_client_unix.log: test_server_with_client_unix$(EXEEXT) @p='test_server_with_client_unix$(EXEEXT)'; \ b='test_server_with_client_unix'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_service.log: test_service$(EXEEXT) @p='test_service$(EXEEXT)'; \ b='test_service'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_strings.log: test_strings$(EXEEXT) @p='test_strings$(EXEEXT)'; \ b='test_strings'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_strings_to_data.log: test_strings_to_data$(EXEEXT) @p='test_strings_to_data$(EXEEXT)'; \ b='test_strings_to_data'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_time.log: test_time$(EXEEXT) @p='test_time$(EXEEXT)'; \ b='test_time'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_speedup.log: test_speedup$(EXEEXT) @p='test_speedup$(EXEEXT)'; \ b='test_speedup'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_crypto_hash.log: perf_crypto_hash$(EXEEXT) @p='perf_crypto_hash$(EXEEXT)'; \ b='perf_crypto_hash'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_crypto_symmetric.log: perf_crypto_symmetric$(EXEEXT) @p='perf_crypto_symmetric$(EXEEXT)'; \ b='perf_crypto_symmetric'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_malloc.log: perf_malloc$(EXEEXT) @p='perf_malloc$(EXEEXT)'; \ b='perf_malloc'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_os_start_process.log: test_os_start_process$(EXEEXT) @p='test_os_start_process$(EXEEXT)'; \ b='test_os_start_process'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_common_logging_runtime_loglevels.log: test_common_logging_runtime_loglevels$(EXEEXT) @p='test_common_logging_runtime_loglevels$(EXEEXT)'; \ b='test_common_logging_runtime_loglevels'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-pkgcfgDATA \ install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS \ install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-dist_pkgcfgDATA uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-binSCRIPTS \ install-data install-data-am install-dist_pkgcfgDATA \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-dist_pkgcfgDATA uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES gnunet-qr: gnunet-qr.py.in Makefile $(do_subst) < gnunet-qr.py.in > gnunet-qr chmod +x gnunet-qr # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/util/test_connection_receive_cancel.c0000644000175000017500000001015712225777501020143 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_connection_receive_cancel.c * @brief tests for connection.c */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 12435 static struct GNUNET_CONNECTION_Handle *csock; static struct GNUNET_CONNECTION_Handle *asock; static struct GNUNET_CONNECTION_Handle *lsock; static struct GNUNET_NETWORK_Handle *ls; static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Create and initialize a listen socket for the server. * * @return NULL on error, otherwise the listen socket */ static struct GNUNET_NETWORK_Handle * open_listen_socket () { const static int on = 1; struct sockaddr_in sa; struct GNUNET_NETWORK_Handle *desc; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); desc = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); GNUNET_assert (desc != NULL); if (GNUNET_NETWORK_socket_setsockopt (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); GNUNET_assert (GNUNET_OK == GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa, sizeof (sa))); GNUNET_NETWORK_socket_listen (desc, 5); return desc; } static void dead_receive (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode) { GNUNET_assert (0); } static void run_accept_cancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { asock = GNUNET_CONNECTION_create_from_accept (NULL, NULL, ls); GNUNET_assert (asock != NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONNECTION_check (asock)); GNUNET_CONNECTION_destroy (lsock); GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &dead_receive, cls); } static void receive_cancel_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; GNUNET_CONNECTION_receive_cancel (asock); GNUNET_CONNECTION_destroy (csock); GNUNET_CONNECTION_destroy (asock); *ok = 0; } static void task_receive_cancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { ls = open_listen_socket (); lsock = GNUNET_CONNECTION_create_from_existing (ls); GNUNET_assert (lsock != NULL); csock = GNUNET_CONNECTION_create_from_connect (cfg, "localhost", PORT); GNUNET_assert (csock != NULL); GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, ls, &run_accept_cancel, cls); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &receive_cancel_task, cls); } /** * Main method, starts scheduler with task_timeout. */ static int check_receive_cancel () { int ok; ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); GNUNET_SCHEDULER_run (&task_receive_cancel, &ok); GNUNET_CONFIGURATION_destroy (cfg); return ok; } int main (int argc, char *argv[]) { int ret = 0; GNUNET_log_setup ("test_connection_receive_cancel", "WARNING", NULL); ret += check_receive_cancel (); return ret; } /* end of test_connection_receive_cancel.c */ gnunet-0.10.1/src/util/server_mst.c0000644000175000017500000002052312251306467014123 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/server_mst.c * @brief convenience functions for handling inbound message buffers * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #if HAVE_UNALIGNED_64_ACCESS #define ALIGN_FACTOR 4 #else #define ALIGN_FACTOR 8 #endif #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Handle to a message stream tokenizer. */ struct GNUNET_SERVER_MessageStreamTokenizer { /** * Function to call on completed messages. */ GNUNET_SERVER_MessageTokenizerCallback cb; /** * Closure for cb. */ void *cb_cls; /** * Size of the buffer (starting at 'hdr'). */ size_t curr_buf; /** * How many bytes in buffer have we already processed? */ size_t off; /** * How many bytes in buffer are valid right now? */ size_t pos; /** * Beginning of the buffer. Typed like this to force alignment. */ struct GNUNET_MessageHeader *hdr; }; /** * Create a message stream tokenizer. * * @param cb function to call on completed messages * @param cb_cls closure for @a cb * @return handle to tokenizer */ struct GNUNET_SERVER_MessageStreamTokenizer * GNUNET_SERVER_mst_create (GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls) { struct GNUNET_SERVER_MessageStreamTokenizer *ret; ret = GNUNET_new (struct GNUNET_SERVER_MessageStreamTokenizer); ret->hdr = GNUNET_malloc (GNUNET_SERVER_MIN_BUFFER_SIZE); ret->curr_buf = GNUNET_SERVER_MIN_BUFFER_SIZE; ret->cb = cb; ret->cb_cls = cb_cls; return ret; } /** * Add incoming data to the receive buffer and call the * callback for all complete messages. * * @param mst tokenizer to use * @param client_identity ID of client for which this is a buffer * @param buf input data to add * @param size number of bytes in @a buf * @param purge should any excess bytes in the buffer be discarded * (i.e. for packet-based services like UDP) * @param one_shot only call callback once, keep rest of message in buffer * @return #GNUNET_OK if we are done processing (need more data) * #GNUNET_NO if @a one_shot was set and we have another message ready * #GNUNET_SYSERR if the data stream is corrupt */ int GNUNET_SERVER_mst_receive (struct GNUNET_SERVER_MessageStreamTokenizer *mst, void *client_identity, const char *buf, size_t size, int purge, int one_shot) { const struct GNUNET_MessageHeader *hdr; size_t delta; uint16_t want; char *ibuf; int need_align; unsigned long offset; int ret; GNUNET_assert (mst->off <= mst->pos); GNUNET_assert (mst->pos <= mst->curr_buf); LOG (GNUNET_ERROR_TYPE_DEBUG, "Server-mst receives %u bytes with %u bytes already in private buffer\n", (unsigned int) size, (unsigned int) (mst->pos - mst->off)); ret = GNUNET_OK; ibuf = (char *) mst->hdr; while (mst->pos > 0) { do_align: GNUNET_assert (mst->pos >= mst->off); if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) || (0 != (mst->off % ALIGN_FACTOR))) { /* need to align or need more space */ mst->pos -= mst->off; memmove (ibuf, &ibuf[mst->off], mst->pos); mst->off = 0; } if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) { delta = GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) - (mst->pos - mst->off), size); memcpy (&ibuf[mst->pos], buf, delta); mst->pos += delta; buf += delta; size -= delta; } if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) { if (purge) { mst->off = 0; mst->pos = 0; } return GNUNET_OK; } hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; want = ntohs (hdr->size); if (want < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if ( (mst->curr_buf - mst->off < want) && (mst->off > 0) ) { /* can get more space by moving */ mst->pos -= mst->off; memmove (ibuf, &ibuf[mst->off], mst->pos); mst->off = 0; } if (mst->curr_buf < want) { /* need to get more space by growing buffer */ GNUNET_assert (0 == mst->off); mst->hdr = GNUNET_realloc (mst->hdr, want); ibuf = (char *) mst->hdr; mst->curr_buf = want; } hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; if (mst->pos - mst->off < want) { delta = GNUNET_MIN (want - (mst->pos - mst->off), size); GNUNET_assert (mst->pos + delta <= mst->curr_buf); memcpy (&ibuf[mst->pos], buf, delta); mst->pos += delta; buf += delta; size -= delta; } if (mst->pos - mst->off < want) { if (purge) { mst->off = 0; mst->pos = 0; } return GNUNET_OK; } if (one_shot == GNUNET_SYSERR) { /* cannot call callback again, but return value saying that * we have another full message in the buffer */ ret = GNUNET_NO; goto copy; } if (one_shot == GNUNET_YES) one_shot = GNUNET_SYSERR; mst->off += want; if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr)) return GNUNET_SYSERR; if (mst->off == mst->pos) { /* reset to beginning of buffer, it's free right now! */ mst->off = 0; mst->pos = 0; } } GNUNET_assert (0 == mst->pos); while (size > 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Server-mst has %u bytes left in inbound buffer\n", (unsigned int) size); if (size < sizeof (struct GNUNET_MessageHeader)) break; offset = (unsigned long) buf; need_align = (0 != (offset % ALIGN_FACTOR)) ? GNUNET_YES : GNUNET_NO; if (GNUNET_NO == need_align) { /* can try to do zero-copy and process directly from original buffer */ hdr = (const struct GNUNET_MessageHeader *) buf; want = ntohs (hdr->size); if (want < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); mst->off = 0; return GNUNET_SYSERR; } if (size < want) break; /* or not: buffer incomplete, so copy to private buffer... */ if (one_shot == GNUNET_SYSERR) { /* cannot call callback again, but return value saying that * we have another full message in the buffer */ ret = GNUNET_NO; goto copy; } if (one_shot == GNUNET_YES) one_shot = GNUNET_SYSERR; if (GNUNET_SYSERR == mst->cb (mst->cb_cls, client_identity, hdr)) return GNUNET_SYSERR; buf += want; size -= want; } else { /* need to copy to private buffer to align; * yes, we go a bit more spagetti than usual here */ goto do_align; } } copy: if ((size > 0) && (!purge)) { if (size + mst->pos > mst->curr_buf) { mst->hdr = GNUNET_realloc (mst->hdr, size + mst->pos); ibuf = (char *) mst->hdr; mst->curr_buf = size + mst->pos; } GNUNET_assert (size + mst->pos <= mst->curr_buf); memcpy (&ibuf[mst->pos], buf, size); mst->pos += size; } if (purge) { mst->off = 0; mst->pos = 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Server-mst leaves %u bytes in private buffer\n", (unsigned int) (mst->pos - mst->off)); return ret; } /** * Destroys a tokenizer. * * @param mst tokenizer to destroy */ void GNUNET_SERVER_mst_destroy (struct GNUNET_SERVER_MessageStreamTokenizer *mst) { GNUNET_free (mst->hdr); GNUNET_free (mst); } /* end of server_mst.c */ gnunet-0.10.1/src/util/container_multipeermap.c0000644000175000017500000005140112241134531016465 00000000000000/* This file is part of GNUnet. (C) 2008, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/container_multipeermap.c * @brief hash map where the same key may be present multiple times * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * An entry in the hash map with the full key. */ struct BigMapEntry { /** * Value of the entry. */ void *value; /** * If there is a hash collision, we create a linked list. */ struct BigMapEntry *next; /** * Key for the entry. */ struct GNUNET_PeerIdentity key; }; /** * An entry in the hash map with just a pointer to the key. */ struct SmallMapEntry { /** * Value of the entry. */ void *value; /** * If there is a hash collision, we create a linked list. */ struct SmallMapEntry *next; /** * Key for the entry. */ const struct GNUNET_PeerIdentity *key; }; /** * Entry in the map. */ union MapEntry { /** * Variant used if map entries only contain a pointer to the key. */ struct SmallMapEntry *sme; /** * Variant used if map entries contain the full key. */ struct BigMapEntry *bme; }; /** * Internal representation of the hash map. */ struct GNUNET_CONTAINER_MultiPeerMap { /** * All of our buckets. */ union MapEntry *map; /** * Number of entries in the map. */ unsigned int size; /** * Length of the "map" array. */ unsigned int map_length; /** * GNUNET_NO if the map entries are of type 'struct BigMapEntry', * GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. */ int use_small_entries; /** * Counts the destructive modifications (grow, remove) * to the map, so that iterators can check if they are still valid. */ unsigned int modification_counter; }; /** * Cursor into a multipeermap. * Allows to enumerate elements asynchronously. */ struct GNUNET_CONTAINER_MultiPeerMapIterator { /** * Position in the bucket 'idx' */ union MapEntry me; /** * Current bucket index. */ unsigned int idx; /** * Modification counter as observed on the map when the iterator * was created. */ unsigned int modification_counter; /** * Map that we are iterating over. */ const struct GNUNET_CONTAINER_MultiPeerMap *map; }; /** * Create a multi hash map. * * @param len initial size (map will grow as needed) * @param do_not_copy_keys GNUNET_NO is always safe and should be used by default; * GNUNET_YES means that on 'put', the 'key' does not have * to be copied as the destination of the pointer is * guaranteed to be life as long as the value is stored in * the hashmap. This can significantly reduce memory * consumption, but of course is also a recipie for * heap corruption if the assumption is not true. Only * use this if (1) memory use is important in this case and * (2) you have triple-checked that the invariant holds * @return NULL on error */ struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create (unsigned int len, int do_not_copy_keys) { struct GNUNET_CONTAINER_MultiPeerMap *map; GNUNET_assert (len > 0); map = GNUNET_new (struct GNUNET_CONTAINER_MultiPeerMap); map->map = GNUNET_malloc (len * sizeof (union MapEntry)); map->map_length = len; map->use_small_entries = do_not_copy_keys; return map; } /** * Destroy a hash map. Will not free any values * stored in the hash map! * * @param map the map */ void GNUNET_CONTAINER_multipeermap_destroy (struct GNUNET_CONTAINER_MultiPeerMap *map) { unsigned int i; union MapEntry me; for (i = 0; i < map->map_length; i++) { me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *nxt; nxt = me.sme; while (NULL != (sme = nxt)) { nxt = sme->next; GNUNET_free (sme); } me.sme = NULL; } else { struct BigMapEntry *bme; struct BigMapEntry *nxt; nxt = me.bme; while (NULL != (bme = nxt)) { nxt = bme->next; GNUNET_free (bme); } me.bme = NULL; } } GNUNET_free (map->map); GNUNET_free (map); } /** * Compute the index of the bucket for the given key. * * @param map hash map for which to compute the index * @param key what key should the index be computed for * @return offset into the "map" array of "map" */ static unsigned int idx_of (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key) { unsigned int kx; GNUNET_assert (NULL != map); memcpy (&kx, key, sizeof (kx)); return kx % map->map_length; } /** * Get the number of key-value pairs in the map. * * @param map the map * @return the number of key value pairs */ unsigned int GNUNET_CONTAINER_multipeermap_size (const struct GNUNET_CONTAINER_MultiPeerMap *map) { return map->size; } /** * Given a key find a value in the map matching the key. * * @param map the map * @param key what to look for * @return NULL if no value was found; note that * this is indistinguishable from values that just * happen to be NULL; use "contains" to test for * key-value pairs with value NULL */ void * GNUNET_CONTAINER_multipeermap_get (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key) { union MapEntry me; me = map->map[idx_of (map, key)]; if (map->use_small_entries) { struct SmallMapEntry *sme; for (sme = me.sme; NULL != sme; sme = sme->next) if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) return sme->value; } else { struct BigMapEntry *bme; for (bme = me.bme; NULL != bme; bme = bme->next) if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) return bme->value; } return NULL; } /** * Iterate over all entries in the map. * * @param map the map * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multipeermap_iterate (const struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls) { int count; unsigned int i; union MapEntry me; struct GNUNET_PeerIdentity kc; count = 0; GNUNET_assert (NULL != map); for (i = 0; i < map->map_length; i++) { me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *nxt; nxt = me.sme; while (NULL != (sme = nxt)) { nxt = sme->next; if (NULL != it) { if (GNUNET_OK != it (it_cls, sme->key, sme->value)) return GNUNET_SYSERR; } count++; } } else { struct BigMapEntry *bme; struct BigMapEntry *nxt; nxt = me.bme; while (NULL != (bme = nxt)) { nxt = bme->next; if (NULL != it) { kc = bme->key; if (GNUNET_OK != it (it_cls, &kc, bme->value)) return GNUNET_SYSERR; } count++; } } } return count; } /** * Remove the given key-value pair from the map. Note that if the * key-value pair is in the map multiple times, only one of the pairs * will be removed. * * @param map the map * @param key key of the key-value pair * @param value value of the key-value pair * @return GNUNET_YES on success, GNUNET_NO if the key-value pair * is not in the map */ int GNUNET_CONTAINER_multipeermap_remove (struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value) { union MapEntry me; unsigned int i; map->modification_counter++; i = idx_of (map, key); me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *p; p = NULL; for (sme = me.sme; NULL != sme; sme = sme->next) { if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) && (value == sme->value)) { if (NULL == p) map->map[i].sme = sme->next; else p->next = sme->next; GNUNET_free (sme); map->size--; return GNUNET_YES; } p = sme; } } else { struct BigMapEntry *bme; struct BigMapEntry *p; p = NULL; for (bme = me.bme; NULL != bme; bme = bme->next) { if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) && (value == bme->value)) { if (NULL == p) map->map[i].bme = bme->next; else p->next = bme->next; GNUNET_free (bme); map->size--; return GNUNET_YES; } p = bme; } } return GNUNET_NO; } /** * Remove all entries for the given key from the map. * Note that the values would not be "freed". * * @param map the map * @param key identifies values to be removed * @return number of values removed */ int GNUNET_CONTAINER_multipeermap_remove_all (struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key) { union MapEntry me; unsigned int i; int ret; map->modification_counter++; ret = 0; i = idx_of (map, key); me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *p; p = NULL; sme = me.sme; while (NULL != sme) { if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) { if (NULL == p) map->map[i].sme = sme->next; else p->next = sme->next; GNUNET_free (sme); map->size--; if (NULL == p) sme = map->map[i].sme; else sme = p->next; ret++; } else { p = sme; sme = sme->next; } } } else { struct BigMapEntry *bme; struct BigMapEntry *p; p = NULL; bme = me.bme; while (NULL != bme) { if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) { if (NULL == p) map->map[i].bme = bme->next; else p->next = bme->next; GNUNET_free (bme); map->size--; if (NULL == p) bme = map->map[i].bme; else bme = p->next; ret++; } else { p = bme; bme = bme->next; } } } return ret; } /** * Check if the map contains any value under the given * key (including values that are NULL). * * @param map the map * @param key the key to test if a value exists for it * @return GNUNET_YES if such a value exists, * GNUNET_NO if not */ int GNUNET_CONTAINER_multipeermap_contains (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key) { union MapEntry me; me = map->map[idx_of (map, key)]; if (map->use_small_entries) { struct SmallMapEntry *sme; for (sme = me.sme; NULL != sme; sme = sme->next) if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) return GNUNET_YES; } else { struct BigMapEntry *bme; for (bme = me.bme; NULL != bme; bme = bme->next) if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) return GNUNET_YES; } return GNUNET_NO; } /** * Check if the map contains the given value under the given * key. * * @param map the map * @param key the key to test if a value exists for it * @param value value to test for * @return GNUNET_YES if such a value exists, * GNUNET_NO if not */ int GNUNET_CONTAINER_multipeermap_contains_value (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value) { union MapEntry me; me = map->map[idx_of (map, key)]; if (map->use_small_entries) { struct SmallMapEntry *sme; for (sme = me.sme; NULL != sme; sme = sme->next) if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) && (sme->value == value) ) return GNUNET_YES; } else { struct BigMapEntry *bme; for (bme = me.bme; NULL != bme; bme = bme->next) if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) && (bme->value == value) ) return GNUNET_YES; } return GNUNET_NO; } /** * Grow the given map to a more appropriate size. * * @param map the hash map to grow */ static void grow (struct GNUNET_CONTAINER_MultiPeerMap *map) { union MapEntry *old_map; union MapEntry *new_map; unsigned int old_len; unsigned int new_len; unsigned int idx; unsigned int i; map->modification_counter++; old_map = map->map; old_len = map->map_length; new_len = old_len * 2; new_map = GNUNET_malloc (sizeof (union MapEntry) * new_len); map->map_length = new_len; map->map = new_map; for (i = 0; i < old_len; i++) { if (map->use_small_entries) { struct SmallMapEntry *sme; while (NULL != (sme = old_map[i].sme)) { old_map[i].sme = sme->next; idx = idx_of (map, sme->key); sme->next = new_map[idx].sme; new_map[idx].sme = sme; } } else { struct BigMapEntry *bme; while (NULL != (bme = old_map[i].bme)) { old_map[i].bme = bme->next; idx = idx_of (map, &bme->key); bme->next = new_map[idx].bme; new_map[idx].bme = bme; } } } GNUNET_free (old_map); } /** * Store a key-value pair in the map. * * @param map the map * @param key key to use * @param value value to use * @param opt options for put * @return #GNUNET_OK on success, * #GNUNET_NO if a value was replaced (with REPLACE) * #GNUNET_SYSERR if GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY was the option and the * value already exists */ int GNUNET_CONTAINER_multipeermap_put (struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt) { union MapEntry me; unsigned int i; i = idx_of (map, key); if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) && (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; for (sme = me.sme; NULL != sme; sme = sme->next) if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) { if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) return GNUNET_SYSERR; sme->value = value; return GNUNET_NO; } } else { struct BigMapEntry *bme; for (bme = me.bme; NULL != bme; bme = bme->next) if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) { if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) return GNUNET_SYSERR; bme->value = value; return GNUNET_NO; } } } if (map->size / 3 >= map->map_length / 4) { grow (map); i = idx_of (map, key); } if (map->use_small_entries) { struct SmallMapEntry *sme; sme = GNUNET_new (struct SmallMapEntry); sme->key = key; sme->value = value; sme->next = map->map[i].sme; map->map[i].sme = sme; } else { struct BigMapEntry *bme; bme = GNUNET_new (struct BigMapEntry); bme->key = *key; bme->value = value; bme->next = map->map[i].bme; map->map[i].bme = bme; } map->size++; return GNUNET_OK; } /** * Iterate over all entries in the map that match a particular key. * * @param map the map * @param key key that the entries must correspond to * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multipeermap_get_multiple (const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls) { int count; union MapEntry me; count = 0; me = map->map[idx_of (map, key)]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *nxt; nxt = me.sme; while (NULL != (sme = nxt)) { nxt = sme->next; if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_PeerIdentity))) continue; if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value))) return GNUNET_SYSERR; count++; } } else { struct BigMapEntry *bme; struct BigMapEntry *nxt; nxt = me.bme; while (NULL != (bme = nxt)) { nxt = bme->next; if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_PeerIdentity))) continue; if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value))) return GNUNET_SYSERR; count++; } } return count; } /** * Create an iterator for a multipeermap. * The iterator can be used to retrieve all the elements in the multipeermap * one by one, without having to handle all elements at once (in contrast to * #GNUNET_CONTAINER_multipeermap_iterate). Note that the iterator can not be * used anymore if elements have been removed from 'map' after the creation of * the iterator, or 'map' has been destroyed. Adding elements to 'map' may * result in skipped or repeated elements. * * @param map the map to create an iterator for * @return an iterator over the given multipeermap 'map' */ struct GNUNET_CONTAINER_MultiPeerMapIterator * GNUNET_CONTAINER_multipeermap_iterator_create (const struct GNUNET_CONTAINER_MultiPeerMap *map) { struct GNUNET_CONTAINER_MultiPeerMapIterator *iter; iter = GNUNET_new (struct GNUNET_CONTAINER_MultiPeerMapIterator); iter->map = map; iter->modification_counter = map->modification_counter; iter->me = map->map[0]; return iter; } /** * Retrieve the next element from the hash map at the iterator's position. * If there are no elements left, GNUNET_NO is returned, and 'key' and 'value' * are not modified. * This operation is only allowed if no elements have been removed from the * multipeermap since the creation of 'iter', and the map has not been destroyed. * Adding elements may result in repeating or skipping elements. * * @param iter the iterator to get the next element from * @param key pointer to store the key in, can be NULL * @param value pointer to store the value in, can be NULL * @return #GNUNET_YES we returned an element, * #GNUNET_NO if we are out of elements */ int GNUNET_CONTAINER_multipeermap_iterator_next (struct GNUNET_CONTAINER_MultiPeerMapIterator *iter, struct GNUNET_PeerIdentity *key, const void **value) { /* make sure the map has not been modified */ GNUNET_assert (iter->modification_counter == iter->map->modification_counter); /* look for the next entry, skipping empty buckets */ while (1) { if (iter->idx >= iter->map->map_length) return GNUNET_NO; if (GNUNET_YES == iter->map->use_small_entries) { if (NULL != iter->me.sme) { if (NULL != key) *key = *iter->me.sme->key; if (NULL != value) *value = iter->me.sme->value; iter->me.sme = iter->me.sme->next; return GNUNET_YES; } } else { if (NULL != iter->me.bme) { if (NULL != key) *key = iter->me.bme->key; if (NULL != value) *value = iter->me.bme->value; iter->me.bme = iter->me.bme->next; return GNUNET_YES; } } iter->idx += 1; if (iter->idx < iter->map->map_length) iter->me = iter->map->map[iter->idx]; } } /** * Destroy a multipeermap iterator. * * @param iter the iterator to destroy */ void GNUNET_CONTAINER_multipeermap_iterator_destroy (struct GNUNET_CONTAINER_MultiPeerMapIterator *iter) { GNUNET_free (iter); } /* end of container_multipeermap.c */ gnunet-0.10.1/src/util/test_server_with_client.c0000644000175000017500000001250412225777501016672 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_server_with_client.c * @brief tests for server.c and client.c, * specifically disconnect_notify, * client_get_address and receive_done (resume processing) */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 22335 #define MY_TYPE 128 static struct GNUNET_SERVER_Handle *server; static struct GNUNET_CLIENT_Connection *client; static struct GNUNET_CONFIGURATION_Handle *cfg; static int ok; static void send_done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVER_Client *argclient = cls; GNUNET_assert (ok == 3); ok++; GNUNET_SERVER_receive_done (argclient, GNUNET_OK); } static void recv_cb (void *cls, struct GNUNET_SERVER_Client *argclient, const struct GNUNET_MessageHeader *message) { void *addr; size_t addrlen; struct sockaddr_in sa; struct sockaddr_in *have; GNUNET_assert (GNUNET_OK == GNUNET_SERVER_client_get_address (argclient, &addr, &addrlen)); GNUNET_assert (addrlen == sizeof (struct sockaddr_in)); have = addr; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = have->sin_port; sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK); GNUNET_assert (0 == memcmp (&sa, addr, addrlen)); GNUNET_free (addr); switch (ok) { case 2: ok++; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 50), &send_done, argclient); break; case 4: ok++; GNUNET_CLIENT_disconnect (client); GNUNET_SERVER_receive_done (argclient, GNUNET_OK); break; default: GNUNET_assert (0); } } static void clean_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SERVER_destroy (server); server = NULL; GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; } /** * Functions with this signature are called whenever a client * is disconnected on the network level. * * @param cls closure * @param client identification of the client */ static void notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { if (client == NULL) return; GNUNET_assert (ok == 5); ok = 0; GNUNET_SCHEDULER_add_now (&clean_up, NULL); } static size_t notify_ready (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg; GNUNET_assert (size >= 256); GNUNET_assert (1 == ok); ok++; msg = buf; msg->type = htons (MY_TYPE); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); msg++; msg->type = htons (MY_TYPE); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); return 2 * sizeof (struct GNUNET_MessageHeader); } static struct GNUNET_SERVER_MessageHandler handlers[] = { {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_in sa; struct sockaddr *sap[2]; socklen_t slens[2]; sap[0] = (struct sockaddr *) &sa; slens[0] = sizeof (sa); sap[1] = NULL; slens[1] = 0; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); server = GNUNET_SERVER_create (NULL, NULL, sap, slens, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_NO); GNUNET_assert (server != NULL); handlers[0].callback_cls = cls; GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, ¬ify_disconnect, cls); cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_number (cfg, "test", "PORT", PORT); GNUNET_CONFIGURATION_set_value_string (cfg, "test", "HOSTNAME", "localhost"); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); client = GNUNET_CLIENT_connect ("test", cfg); GNUNET_assert (client != NULL); GNUNET_CLIENT_notify_transmit_ready (client, 256, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_NO, ¬ify_ready, NULL); } int main (int argc, char *argv[]) { GNUNET_log_setup ("test_server_with_client", "WARNING", NULL); ok = 1; GNUNET_SCHEDULER_run (&task, NULL); return ok; } /* end of test_server_with_client.c */ gnunet-0.10.1/src/util/server.c0000644000175000017500000014265212225777501013252 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/server.c * @brief library for building GNUnet network servers * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * List of arrays of message handlers. */ struct HandlerList { /** * This is a linked list. */ struct HandlerList *next; /** * NULL-terminated array of handlers. */ const struct GNUNET_SERVER_MessageHandler *handlers; }; /** * List of arrays of message handlers. */ struct NotifyList { /** * This is a doubly linked list. */ struct NotifyList *next; /** * This is a doubly linked list. */ struct NotifyList *prev; /** * Function to call. */ GNUNET_SERVER_DisconnectCallback callback; /** * Closure for callback. */ void *callback_cls; }; /** * @brief handle for a server */ struct GNUNET_SERVER_Handle { /** * List of handlers for incoming messages. */ struct HandlerList *handlers; /** * Head of list of our current clients. */ struct GNUNET_SERVER_Client *clients_head; /** * Head of list of our current clients. */ struct GNUNET_SERVER_Client *clients_tail; /** * Head of linked list of functions to call on disconnects by clients. */ struct NotifyList *disconnect_notify_list_head; /** * Tail of linked list of functions to call on disconnects by clients. */ struct NotifyList *disconnect_notify_list_tail; /** * Head of linked list of functions to call on connects by clients. */ struct NotifyList *connect_notify_list_head; /** * Tail of linked list of functions to call on connects by clients. */ struct NotifyList *connect_notify_list_tail; /** * Function to call for access control. */ GNUNET_CONNECTION_AccessCheck access; /** * Closure for access. */ void *access_cls; /** * NULL-terminated array of sockets used to listen for new * connections. */ struct GNUNET_NETWORK_Handle **listen_sockets; /** * After how long should an idle connection time * out (on write). */ struct GNUNET_TIME_Relative idle_timeout; /** * Task scheduled to do the listening. */ GNUNET_SCHEDULER_TaskIdentifier listen_task; /** * Alternative function to create a MST instance. */ GNUNET_SERVER_MstCreateCallback mst_create; /** * Alternative function to destroy a MST instance. */ GNUNET_SERVER_MstDestroyCallback mst_destroy; /** * Alternative function to give data to a MST instance. */ GNUNET_SERVER_MstReceiveCallback mst_receive; /** * Closure for 'mst_'-callbacks. */ void *mst_cls; /** * Do we ignore messages of types that we do not understand or do we * require that a handler is found (and if not kill the connection)? */ int require_found; /** * Set to #GNUNET_YES once we are in 'soft' shutdown where we wait for * all non-monitor clients to disconnect before we call * #GNUNET_SERVER_destroy. See 'test_monitor_clients'. Set to * #GNUNET_SYSERR once the final destroy task has been scheduled * (we cannot run it in the same task). */ int in_soft_shutdown; }; /** * Handle server returns for aborting transmission to a client. */ struct GNUNET_SERVER_TransmitHandle { /** * Function to call to get the message. */ GNUNET_CONNECTION_TransmitReadyNotify callback; /** * Closure for @e callback */ void *callback_cls; /** * Active connection transmission handle. */ struct GNUNET_CONNECTION_TransmitHandle *cth; }; /** * @brief handle for a client of the server */ struct GNUNET_SERVER_Client { /** * This is a doubly linked list. */ struct GNUNET_SERVER_Client *next; /** * This is a doubly linked list. */ struct GNUNET_SERVER_Client *prev; /** * Processing of incoming data. */ void *mst; /** * Server that this client belongs to. */ struct GNUNET_SERVER_Handle *server; /** * Client closure for callbacks. */ struct GNUNET_CONNECTION_Handle *connection; /** * User context value, manipulated using * 'GNUNET_SERVER_client_{get/set}_user_context' functions. */ void *user_context; /** * ID of task used to restart processing. */ GNUNET_SCHEDULER_TaskIdentifier restart_task; /** * Task that warns about missing calls to #GNUNET_SERVER_receive_done. */ GNUNET_SCHEDULER_TaskIdentifier warn_task; /** * Time when the warn task was started. */ struct GNUNET_TIME_Absolute warn_start; /** * Last activity on this socket (used to time it out * if reference_count == 0). */ struct GNUNET_TIME_Absolute last_activity; /** * Transmission handle we return for this client from * #GNUNET_SERVER_notify_transmit_ready. */ struct GNUNET_SERVER_TransmitHandle th; /** * After how long should an idle connection time * out (on write). */ struct GNUNET_TIME_Relative idle_timeout; /** * Number of external entities with a reference to * this client object. */ unsigned int reference_count; /** * Was processing if incoming messages suspended while * we were still processing data already received? * This is a counter saying how often processing was * suspended (once per handler invoked). */ unsigned int suspended; /** * Last size given when user context was initialized; used for * sanity check. */ size_t user_context_size; /** * Are we currently in the "process_client_buffer" function (and * will hence restart the receive job on exit if suspended == 0 once * we are done?). If this is set, then "receive_done" will * essentially only decrement suspended; if this is not set, then * "receive_done" may need to restart the receive process (either * from the side-buffer or via select/recv). */ int in_process_client_buffer; /** * We're about to close down this client. */ int shutdown_now; /** * Are we currently trying to receive? (#GNUNET_YES if we are, * #GNUNET_NO if we are not, #GNUNET_SYSERR if data is already * available in MST). */ int receive_pending; /** * Persist the file handle for this client no matter what happens, * force the OS to close once the process actually dies. Should only * be used in special cases! */ int persist; /** * Is this client a 'monitor' client that should not be counted * when deciding on destroying the server during soft shutdown? * (see also #GNUNET_SERVICE_start) */ int is_monitor; /** * Type of last message processed (for warn_no_receive_done). */ uint16_t warn_type; }; /** * Return user context associated with the given client. * Note: you should probably use the macro (call without the underscore). * * @param client client to query * @param size number of bytes in user context struct (for verification only) * @return pointer to user context */ void * GNUNET_SERVER_client_get_user_context_ (struct GNUNET_SERVER_Client *client, size_t size) { if ((0 == client->user_context_size) && (NULL == client->user_context)) return NULL; /* never set */ GNUNET_assert (size == client->user_context_size); return client->user_context; } /** * Set user context to be associated with the given client. * Note: you should probably use the macro (call without the underscore). * * @param client client to query * @param ptr pointer to user context * @param size number of bytes in user context struct (for verification only) */ void GNUNET_SERVER_client_set_user_context_ (struct GNUNET_SERVER_Client *client, void *ptr, size_t size) { if (NULL == ptr) { client->user_context_size = 0; client->user_context = ptr; return; } client->user_context_size = size; client->user_context = ptr; } /** * Scheduler says our listen socket is ready. Process it! * * @param cls handle to our server for which we are processing the listen * socket * @param tc reason why we are running right now */ static void process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVER_Handle *server = cls; struct GNUNET_CONNECTION_Handle *sock; struct GNUNET_SERVER_Client *client; unsigned int i; server->listen_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* ignore shutdown, someone else will take care of it! */ GNUNET_SERVER_resume (server); return; } i = 0; while (NULL != server->listen_sockets[i]) { if (GNUNET_NETWORK_fdset_isset (tc->read_ready, server->listen_sockets[i])) { sock = GNUNET_CONNECTION_create_from_accept (server->access, server->access_cls, server->listen_sockets[i]); if (NULL != sock) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Server accepted incoming connection.\n"); client = GNUNET_SERVER_connect_socket (server, sock); /* decrement reference count, we don't keep "client" alive */ GNUNET_SERVER_client_drop (client); } } i++; } /* listen for more! */ GNUNET_SERVER_resume (server); } /** * Create and initialize a listen socket for the server. * * @param server_addr address to listen on * @param socklen length of @a server_addr * @return NULL on error, otherwise the listen socket */ static struct GNUNET_NETWORK_Handle * open_listen_socket (const struct sockaddr *server_addr, socklen_t socklen) { struct GNUNET_NETWORK_Handle *sock; uint16_t port; int eno; switch (server_addr->sa_family) { case AF_INET: port = ntohs (((const struct sockaddr_in *) server_addr)->sin_port); break; case AF_INET6: port = ntohs (((const struct sockaddr_in6 *) server_addr)->sin6_port); break; case AF_UNIX: port = 0; break; default: GNUNET_break (0); port = 0; break; } sock = GNUNET_NETWORK_socket_create (server_addr->sa_family, SOCK_STREAM, 0); if (NULL == sock) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket"); errno = 0; return NULL; } /* bind the socket */ if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, server_addr, socklen)) { eno = errno; if (EADDRINUSE != errno) { /* we don't log 'EADDRINUSE' here since an IPv4 bind may * fail if we already took the port on IPv6; if both IPv4 and * IPv6 binds fail, then our caller will log using the * errno preserved in 'eno' */ LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "bind"); if (0 != port) LOG (GNUNET_ERROR_TYPE_ERROR, _("`%s' failed for port %d (%s).\n"), "bind", port, (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6"); eno = 0; } else { if (0 != port) LOG (GNUNET_ERROR_TYPE_WARNING, _("`%s' failed for port %d (%s): address already in use\n"), "bind", port, (AF_INET == server_addr->sa_family) ? "IPv4" : "IPv6"); else if (AF_UNIX == server_addr->sa_family) { LOG (GNUNET_ERROR_TYPE_WARNING, _("`%s' failed for `%s': address already in use\n"), "bind", GNUNET_a2s (server_addr, socklen)); } } GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); errno = eno; return NULL; } if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "listen"); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); errno = 0; return NULL; } if (0 != port) LOG (GNUNET_ERROR_TYPE_DEBUG, "Server starts to listen on port %u.\n", port); return sock; } /** * Create a new server. * * @param access function for access control * @param access_cls closure for access * @param lsocks NULL-terminated array of listen sockets * @param idle_timeout after how long should we timeout idle connections? * @param require_found if #GNUNET_YES, connections sending messages of unknown type * will be closed * @return handle for the new server, NULL on error * (typically, "port" already in use) */ struct GNUNET_SERVER_Handle * GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access, void *access_cls, struct GNUNET_NETWORK_Handle **lsocks, struct GNUNET_TIME_Relative idle_timeout, int require_found) { struct GNUNET_SERVER_Handle *server; server = GNUNET_new (struct GNUNET_SERVER_Handle); server->idle_timeout = idle_timeout; server->listen_sockets = lsocks; server->access = access; server->access_cls = access_cls; server->require_found = require_found; if (NULL != lsocks) GNUNET_SERVER_resume (server); return server; } /** * Create a new server. * * @param access function for access control * @param access_cls closure for access * @param server_addr address to listen on (including port), NULL terminated array * @param socklen length of server_addr * @param idle_timeout after how long should we timeout idle connections? * @param require_found if YES, connections sending messages of unknown type * will be closed * @return handle for the new server, NULL on error * (typically, "port" already in use) */ struct GNUNET_SERVER_Handle * GNUNET_SERVER_create (GNUNET_CONNECTION_AccessCheck access, void *access_cls, struct sockaddr *const *server_addr, const socklen_t * socklen, struct GNUNET_TIME_Relative idle_timeout, int require_found) { struct GNUNET_NETWORK_Handle **lsocks; unsigned int i; unsigned int j; unsigned int k; int seen; i = 0; while (NULL != server_addr[i]) i++; if (i > 0) { lsocks = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (i + 1)); i = 0; j = 0; while (NULL != server_addr[i]) { seen = 0; for (k=0;kis_monitor = GNUNET_YES; } /** * Helper function for 'test_monitor_clients' to trigger * 'GNUNET_SERVER_destroy' after the stack has unwound. * * @param cls the 'struct GNUNET_SERVER_Handle' to destroy * @param tc unused */ static void do_destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVER_Handle *server = cls; GNUNET_SERVER_destroy (server); } /** * Check if only 'monitor' clients are left. If so, destroy the * server completely. * * @param server server to test for full shutdown */ static void test_monitor_clients (struct GNUNET_SERVER_Handle *server) { struct GNUNET_SERVER_Client *client; if (GNUNET_YES != server->in_soft_shutdown) return; for (client = server->clients_head; NULL != client; client = client->next) if (GNUNET_NO == client->is_monitor) return; /* not done yet */ server->in_soft_shutdown = GNUNET_SYSERR; GNUNET_SCHEDULER_add_continuation (&do_destroy, server, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } /** * Suspend accepting connections from the listen socket temporarily. * * @param server server to stop accepting connections. */ void GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server) { if (GNUNET_SCHEDULER_NO_TASK != server->listen_task) { GNUNET_SCHEDULER_cancel (server->listen_task); server->listen_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Resume accepting connections from the listen socket. * * @param server server to stop accepting connections. */ void GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server) { struct GNUNET_NETWORK_FDSet *r; unsigned int i; if (NULL == server->listen_sockets) return; if (NULL == server->listen_sockets[0]) return; /* nothing to do, no listen sockets! */ if (NULL == server->listen_sockets[1]) { /* simplified method: no fd set needed; this is then much simpler and much more efficient */ server->listen_task = GNUNET_SCHEDULER_add_read_net_with_priority (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_SCHEDULER_PRIORITY_HIGH, server->listen_sockets[0], &process_listen_socket, server); return; } r = GNUNET_NETWORK_fdset_create (); i = 0; while (NULL != server->listen_sockets[i]) GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]); server->listen_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, GNUNET_TIME_UNIT_FOREVER_REL, r, NULL, &process_listen_socket, server); GNUNET_NETWORK_fdset_destroy (r); } /** * Stop the listen socket and get ready to shutdown the server * once only 'monitor' clients are left. * * @param server server to stop listening on */ void GNUNET_SERVER_stop_listening (struct GNUNET_SERVER_Handle *server) { unsigned int i; LOG (GNUNET_ERROR_TYPE_DEBUG, "Server in soft shutdown\n"); if (GNUNET_SCHEDULER_NO_TASK != server->listen_task) { GNUNET_SCHEDULER_cancel (server->listen_task); server->listen_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != server->listen_sockets) { i = 0; while (NULL != server->listen_sockets[i]) GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (server->listen_sockets[i++])); GNUNET_free (server->listen_sockets); server->listen_sockets = NULL; } if (GNUNET_NO == server->in_soft_shutdown) server->in_soft_shutdown = GNUNET_YES; test_monitor_clients (server); } /** * Free resources held by this server. * * @param server server to destroy */ void GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *server) { struct HandlerList *hpos; struct NotifyList *npos; unsigned int i; LOG (GNUNET_ERROR_TYPE_DEBUG, "Server shutting down.\n"); if (GNUNET_SCHEDULER_NO_TASK != server->listen_task) { GNUNET_SCHEDULER_cancel (server->listen_task); server->listen_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != server->listen_sockets) { i = 0; while (NULL != server->listen_sockets[i]) GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (server->listen_sockets[i++])); GNUNET_free (server->listen_sockets); server->listen_sockets = NULL; } while (NULL != server->clients_head) GNUNET_SERVER_client_disconnect (server->clients_head); while (NULL != (hpos = server->handlers)) { server->handlers = hpos->next; GNUNET_free (hpos); } while (NULL != (npos = server->disconnect_notify_list_head)) { npos->callback (npos->callback_cls, NULL); GNUNET_CONTAINER_DLL_remove (server->disconnect_notify_list_head, server->disconnect_notify_list_tail, npos); GNUNET_free (npos); } while (NULL != (npos = server->connect_notify_list_head)) { npos->callback (npos->callback_cls, NULL); GNUNET_CONTAINER_DLL_remove (server->connect_notify_list_head, server->connect_notify_list_tail, npos); GNUNET_free (npos); } GNUNET_free (server); } /** * Add additional handlers to an existing server. * * @param server the server to add handlers to * @param handlers array of message handlers for * incoming messages; the last entry must * have "NULL" for the "callback"; multiple * entries for the same type are allowed, * they will be called in order of occurence. * These handlers can be removed later; * the handlers array must exist until removed * (or server is destroyed). */ void GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server, const struct GNUNET_SERVER_MessageHandler *handlers) { struct HandlerList *p; p = GNUNET_new (struct HandlerList); p->handlers = handlers; p->next = server->handlers; server->handlers = p; } /** * Change functions used by the server to tokenize the message stream. * (very rarely used). * * @param server server to modify * @param create new tokenizer initialization function * @param destroy new tokenizer destruction function * @param receive new tokenizer receive function * @param cls closure for @a create, @a receive, @a destroy */ void GNUNET_SERVER_set_callbacks (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_MstCreateCallback create, GNUNET_SERVER_MstDestroyCallback destroy, GNUNET_SERVER_MstReceiveCallback receive, void *cls) { server->mst_create = create; server->mst_destroy = destroy; server->mst_receive = receive; server->mst_cls = cls; } /** * Task run to warn about missing calls to #GNUNET_SERVER_receive_done. * * @param cls our `struct GNUNET_SERVER_Client *` to process more requests from * @param tc scheduler context (unused) */ static void warn_no_receive_done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVER_Client *client = cls; GNUNET_break (0 != client->warn_type); /* type should never be 0 here, as we don't use 0 */ client->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &warn_no_receive_done, client); if (0 == (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) LOG (GNUNET_ERROR_TYPE_WARNING, _("Processing code for message of type %u did not call `GNUNET_SERVER_receive_done' after %s\n"), (unsigned int) client->warn_type, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (client->warn_start), GNUNET_YES)); } /** * Disable the warning the server issues if a message is not acknowledged * in a timely fashion. Use this call if a client is intentionally delayed * for a while. Only applies to the current message. * * @param client client for which to disable the warning */ void GNUNET_SERVER_disable_receive_done_warning (struct GNUNET_SERVER_Client *client) { if (GNUNET_SCHEDULER_NO_TASK != client->warn_task) { GNUNET_SCHEDULER_cancel (client->warn_task); client->warn_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Inject a message into the server, pretend it came * from the specified client. Delivery of the message * will happen instantly (if a handler is installed; * otherwise the call does nothing). * * @param server the server receiving the message * @param sender the "pretended" sender of the message * can be NULL! * @param message message to transmit * @return GNUNET_OK if the message was OK and the * connection can stay open * GNUNET_SYSERR if the connection to the * client should be shut down */ int GNUNET_SERVER_inject (struct GNUNET_SERVER_Handle *server, struct GNUNET_SERVER_Client *sender, const struct GNUNET_MessageHeader *message) { struct HandlerList *pos; const struct GNUNET_SERVER_MessageHandler *mh; unsigned int i; uint16_t type; uint16_t size; int found; type = ntohs (message->type); size = ntohs (message->size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Server schedules transmission of %u-byte message of type %u to client.\n", size, type); found = GNUNET_NO; for (pos = server->handlers; NULL != pos; pos = pos->next) { i = 0; while (pos->handlers[i].callback != NULL) { mh = &pos->handlers[i]; if ((mh->type == type) || (mh->type == GNUNET_MESSAGE_TYPE_ALL)) { if ((0 != mh->expected_size) && (mh->expected_size != size)) { #if GNUNET8_NETWORK_IS_DEAD LOG (GNUNET_ERROR_TYPE_WARNING, "Expected %u bytes for message of type %u, got %u\n", mh->expected_size, mh->type, size); GNUNET_break_op (0); #else LOG (GNUNET_ERROR_TYPE_DEBUG, "Expected %u bytes for message of type %u, got %u\n", mh->expected_size, mh->type, size); #endif return GNUNET_SYSERR; } if (NULL != sender) { if ( (0 == sender->suspended) && (GNUNET_SCHEDULER_NO_TASK == sender->warn_task) ) { GNUNET_break (0 != type); /* type should never be 0 here, as we don't use 0 */ sender->warn_start = GNUNET_TIME_absolute_get (); sender->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &warn_no_receive_done, sender); sender->warn_type = type; } sender->suspended++; } mh->callback (mh->callback_cls, sender, message); found = GNUNET_YES; } i++; } } if (GNUNET_NO == found) { LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Received message of unknown type %d\n", type); if (GNUNET_YES == server->require_found) return GNUNET_SYSERR; } return GNUNET_OK; } /** * We are receiving an incoming message. Process it. * * @param cls our closure (handle for the client) * @param buf buffer with data received from network * @param available number of bytes available in buf * @param addr address of the sender * @param addrlen length of addr * @param errCode code indicating errors receiving, 0 for success */ static void process_incoming (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode); /** * Process messages from the client's message tokenizer until either * the tokenizer is empty (and then schedule receiving more), or * until some handler is not immediately done (then wait for restart_processing) * or shutdown. * * @param client the client to process, RC must have already been increased * using #GNUNET_SERVER_client_keep and will be decreased by one in this * function * @param ret #GNUNET_NO to start processing from the buffer, * #GNUNET_OK if the mst buffer is drained and we should instantly go back to receiving * #GNUNET_SYSERR if we should instantly abort due to error in a previous step */ static void process_mst (struct GNUNET_SERVER_Client *client, int ret) { while ((GNUNET_SYSERR != ret) && (NULL != client->server) && (GNUNET_YES != client->shutdown_now) && (0 == client->suspended)) { if (GNUNET_OK == ret) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Server re-enters receive loop, timeout: %s.\n", GNUNET_STRINGS_relative_time_to_string (client->idle_timeout, GNUNET_YES)); client->receive_pending = GNUNET_YES; GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, client->idle_timeout, &process_incoming, client); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Server processes additional messages instantly.\n"); if (NULL != client->server->mst_receive) ret = client->server->mst_receive (client->server->mst_cls, client->mst, client, NULL, 0, GNUNET_NO, GNUNET_YES); else ret = GNUNET_SERVER_mst_receive (client->mst, client, NULL, 0, GNUNET_NO, GNUNET_YES); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Server leaves instant processing loop: ret = %d, server = %p, shutdown = %d, suspended = %u\n", ret, client->server, client->shutdown_now, client->suspended); if (GNUNET_NO == ret) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Server has more data pending but is suspended.\n"); client->receive_pending = GNUNET_SYSERR; /* data pending */ } if ( (GNUNET_SYSERR == ret) || (GNUNET_YES == client->shutdown_now) ) GNUNET_SERVER_client_disconnect (client); } /** * We are receiving an incoming message. Process it. * * @param cls our closure (handle for the client) * @param buf buffer with data received from network * @param available number of bytes available in buf * @param addr address of the sender * @param addrlen length of addr * @param errCode code indicating errors receiving, 0 for success */ static void process_incoming (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode) { struct GNUNET_SERVER_Client *client = cls; struct GNUNET_SERVER_Handle *server = client->server; struct GNUNET_TIME_Absolute end; struct GNUNET_TIME_Absolute now; int ret; GNUNET_assert (GNUNET_YES == client->receive_pending); client->receive_pending = GNUNET_NO; now = GNUNET_TIME_absolute_get (); end = GNUNET_TIME_absolute_add (client->last_activity, client->idle_timeout); if ((NULL == buf) && (0 == available) && (NULL == addr) && (0 == errCode) && (GNUNET_YES != client->shutdown_now) && (NULL != server) && (GNUNET_YES == GNUNET_CONNECTION_check (client->connection)) && (end.abs_value_us > now.abs_value_us)) { /* wait longer, timeout changed (i.e. due to us sending) */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Receive time out, but no disconnect due to sending (%p)\n", GNUNET_a2s (addr, addrlen)); client->receive_pending = GNUNET_YES; GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, GNUNET_TIME_absolute_get_remaining (end), &process_incoming, client); return; } if ((NULL == buf) || (0 == available) || (0 != errCode) || (NULL == server) || (GNUNET_YES == client->shutdown_now) || (GNUNET_YES != GNUNET_CONNECTION_check (client->connection))) { /* other side closed connection, error connecting, etc. */ GNUNET_SERVER_client_disconnect (client); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Server receives %u bytes from `%s'.\n", (unsigned int) available, GNUNET_a2s (addr, addrlen)); GNUNET_SERVER_client_keep (client); client->last_activity = now; if (NULL != server->mst_receive) ret = client->server->mst_receive (client->server->mst_cls, client->mst, client, buf, available, GNUNET_NO, GNUNET_YES); else if (NULL != client->mst) { ret = GNUNET_SERVER_mst_receive (client->mst, client, buf, available, GNUNET_NO, GNUNET_YES); } else { GNUNET_break (0); return; } process_mst (client, ret); GNUNET_SERVER_client_drop (client); } /** * Task run to start again receiving from the network * and process requests. * * @param cls our 'struct GNUNET_SERVER_Client*' to process more requests from * @param tc scheduler context (unused) */ static void restart_processing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVER_Client *client = cls; GNUNET_assert (GNUNET_YES != client->shutdown_now); client->restart_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_NO == client->receive_pending) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Server begins to read again from client.\n"); client->receive_pending = GNUNET_YES; GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, client->idle_timeout, &process_incoming, client); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Server continues processing messages still in the buffer.\n"); GNUNET_SERVER_client_keep (client); client->receive_pending = GNUNET_NO; process_mst (client, GNUNET_NO); GNUNET_SERVER_client_drop (client); } /** * This function is called whenever our inbound message tokenizer has * received a complete message. * * @param cls closure (struct GNUNET_SERVER_Handle) * @param client identification of the client (struct GNUNET_SERVER_Client*) * @param message the actual message * * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing */ static int client_message_tokenizer_callback (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_SERVER_Handle *server = cls; struct GNUNET_SERVER_Client *sender = client; int ret; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tokenizer gives server message of type %u from client\n", ntohs (message->type)); sender->in_process_client_buffer = GNUNET_YES; ret = GNUNET_SERVER_inject (server, sender, message); sender->in_process_client_buffer = GNUNET_NO; if ( (GNUNET_OK != ret) || (GNUNET_YES == sender->shutdown_now) ) { GNUNET_SERVER_client_disconnect (sender); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Add a TCP socket-based connection to the set of handles managed by * this server. Use this function for outgoing (P2P) connections that * we initiated (and where this server should process incoming * messages). * * @param server the server to use * @param connection the connection to manage (client must * stop using this connection from now on) * @return the client handle (client should call * "client_drop" on the return value eventually) */ struct GNUNET_SERVER_Client * GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server, struct GNUNET_CONNECTION_Handle *connection) { struct GNUNET_SERVER_Client *client; struct NotifyList *n; client = GNUNET_new (struct GNUNET_SERVER_Client); client->connection = connection; client->reference_count = 1; client->server = server; client->last_activity = GNUNET_TIME_absolute_get (); client->idle_timeout = server->idle_timeout; GNUNET_CONTAINER_DLL_insert (server->clients_head, server->clients_tail, client); if (NULL != server->mst_create) client->mst = server->mst_create (server->mst_cls, client); else client->mst = GNUNET_SERVER_mst_create (&client_message_tokenizer_callback, server); GNUNET_assert (NULL != client->mst); for (n = server->connect_notify_list_head; NULL != n; n = n->next) n->callback (n->callback_cls, client); client->receive_pending = GNUNET_YES; GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, client->idle_timeout, &process_incoming, client); return client; } /** * Change the timeout for a particular client. Decreasing the timeout * may not go into effect immediately (only after the previous timeout * times out or activity happens on the socket). * * @param client the client to update * @param timeout new timeout for activities on the socket */ void GNUNET_SERVER_client_set_timeout (struct GNUNET_SERVER_Client *client, struct GNUNET_TIME_Relative timeout) { client->idle_timeout = timeout; } /** * Notify the server that the given client handle should * be kept (keeps the connection up if possible, increments * the internal reference counter). * * @param client the client to keep */ void GNUNET_SERVER_client_keep (struct GNUNET_SERVER_Client *client) { client->reference_count++; } /** * Notify the server that the given client handle is no * longer required. Decrements the reference counter. If * that counter reaches zero an inactive connection maybe * closed. * * @param client the client to drop */ void GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client) { GNUNET_assert (client->reference_count > 0); client->reference_count--; if ((GNUNET_YES == client->shutdown_now) && (0 == client->reference_count)) GNUNET_SERVER_client_disconnect (client); } /** * Obtain the network address of the other party. * * @param client the client to get the address for * @param addr where to store the address * @param addrlen where to store the length of the address * @return GNUNET_OK on success */ int GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client, void **addr, size_t * addrlen) { return GNUNET_CONNECTION_get_address (client->connection, addr, addrlen); } /** * Ask the server to notify us whenever a client disconnects. * This function is called whenever the actual network connection * is closed; the reference count may be zero or larger than zero * at this point. * * @param server the server manageing the clients * @param callback function to call on disconnect * @param callback_cls closure for @a callback */ void GNUNET_SERVER_disconnect_notify (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_DisconnectCallback callback, void *callback_cls) { struct NotifyList *n; n = GNUNET_new (struct NotifyList); n->callback = callback; n->callback_cls = callback_cls; GNUNET_CONTAINER_DLL_insert (server->disconnect_notify_list_head, server->disconnect_notify_list_tail, n); } /** * Ask the server to notify us whenever a client connects. * This function is called whenever the actual network connection * is opened. If the server is destroyed before this * notification is explicitly cancelled, the 'callback' will * once be called with a 'client' argument of NULL to indicate * that the server itself is now gone (and that the callback * won't be called anymore and also can no longer be cancelled). * * @param server the server manageing the clients * @param callback function to call on sconnect * @param callback_cls closure for @a callback */ void GNUNET_SERVER_connect_notify (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_ConnectCallback callback, void *callback_cls) { struct NotifyList *n; n = GNUNET_new (struct NotifyList); n->callback = callback; n->callback_cls = callback_cls; GNUNET_CONTAINER_DLL_insert (server->connect_notify_list_head, server->connect_notify_list_tail, n); } /** * Ask the server to stop notifying us whenever a client connects. * * @param server the server manageing the clients * @param callback function to call on connect * @param callback_cls closure for @a callback */ void GNUNET_SERVER_disconnect_notify_cancel (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_DisconnectCallback callback, void *callback_cls) { struct NotifyList *pos; for (pos = server->disconnect_notify_list_head; NULL != pos; pos = pos->next) if ((pos->callback == callback) && (pos->callback_cls == callback_cls)) break; if (NULL == pos) { GNUNET_break (0); return; } GNUNET_CONTAINER_DLL_remove (server->disconnect_notify_list_head, server->disconnect_notify_list_tail, pos); GNUNET_free (pos); } /** * Ask the server to stop notifying us whenever a client disconnects. * * @param server the server manageing the clients * @param callback function to call on disconnect * @param callback_cls closure for @a callback */ void GNUNET_SERVER_connect_notify_cancel (struct GNUNET_SERVER_Handle *server, GNUNET_SERVER_ConnectCallback callback, void *callback_cls) { struct NotifyList *pos; for (pos = server->connect_notify_list_head; NULL != pos; pos = pos->next) if ((pos->callback == callback) && (pos->callback_cls == callback_cls)) break; if (NULL == pos) { GNUNET_break (0); return; } GNUNET_CONTAINER_DLL_remove (server->connect_notify_list_head, server->connect_notify_list_tail, pos); GNUNET_free (pos); } /** * Destroy the connection that is passed in via @a cls. Used * as calling #GNUNET_CONNECTION_destroy from within a function * that was itself called from within 'process_notify' of * 'connection.c' is not allowed (see #2329). * * @param cls connection to destroy * @param tc scheduler context (unused) */ static void destroy_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CONNECTION_Handle *connection = cls; GNUNET_CONNECTION_destroy (connection); } /** * Ask the server to disconnect from the given client. * This is the same as returning #GNUNET_SYSERR from a message * handler, except that it allows dropping of a client even * when not handling a message from that client. * * @param client the client to disconnect from */ void GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client) { struct GNUNET_SERVER_Handle *server = client->server; struct NotifyList *n; LOG (GNUNET_ERROR_TYPE_DEBUG, "Client is being disconnected from the server.\n"); if (GNUNET_SCHEDULER_NO_TASK != client->restart_task) { GNUNET_SCHEDULER_cancel (client->restart_task); client->restart_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != client->warn_task) { GNUNET_SCHEDULER_cancel (client->warn_task); client->warn_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_YES == client->receive_pending) { GNUNET_CONNECTION_receive_cancel (client->connection); client->receive_pending = GNUNET_NO; } client->shutdown_now = GNUNET_YES; client->reference_count++; /* make sure nobody else clean up client... */ if ( (NULL != client->mst) && (NULL != server) ) { GNUNET_CONTAINER_DLL_remove (server->clients_head, server->clients_tail, client); if (NULL != server->mst_destroy) server->mst_destroy (server->mst_cls, client->mst); else GNUNET_SERVER_mst_destroy (client->mst); client->mst = NULL; for (n = server->disconnect_notify_list_head; NULL != n; n = n->next) n->callback (n->callback_cls, client); } client->reference_count--; if (client->reference_count > 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "RC still positive, not destroying everything.\n"); client->server = NULL; return; } if (GNUNET_YES == client->in_process_client_buffer) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Still processing inputs, not destroying everything.\n"); return; } if (GNUNET_YES == client->persist) GNUNET_CONNECTION_persist_ (client->connection); if (NULL != client->th.cth) GNUNET_SERVER_notify_transmit_ready_cancel (&client->th); (void) GNUNET_SCHEDULER_add_now (&destroy_connection, client->connection); /* need to cancel again, as it might have been re-added in the meantime (i.e. during callbacks) */ if (GNUNET_SCHEDULER_NO_TASK != client->warn_task) { GNUNET_SCHEDULER_cancel (client->warn_task); client->warn_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_YES == client->receive_pending) { GNUNET_CONNECTION_receive_cancel (client->connection); client->receive_pending = GNUNET_NO; } GNUNET_free (client); /* we might be in soft-shutdown, test if we're done */ if (NULL != server) test_monitor_clients (server); } /** * Disable the "CORK" feature for communication with the given client, * forcing the OS to immediately flush the buffer on transmission * instead of potentially buffering multiple messages. * * @param client handle to the client * @return GNUNET_OK on success */ int GNUNET_SERVER_client_disable_corking (struct GNUNET_SERVER_Client *client) { return GNUNET_CONNECTION_disable_corking (client->connection); } /** * Wrapper for transmission notification that calls the original * callback and update the last activity time for our connection. * * @param cls the 'struct GNUNET_SERVER_Client' * @param size number of bytes we can transmit * @param buf where to copy the message * @return number of bytes actually transmitted */ static size_t transmit_ready_callback_wrapper (void *cls, size_t size, void *buf) { struct GNUNET_SERVER_Client *client = cls; GNUNET_CONNECTION_TransmitReadyNotify callback; client->th.cth = NULL; callback = client->th.callback; client->th.callback = NULL; client->last_activity = GNUNET_TIME_absolute_get (); return callback (client->th.callback_cls, size, buf); } /** * Notify us when the server has enough space to transmit * a message of the given size to the given client. * * @param client client to transmit message to * @param size requested amount of buffer space * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param callback function to call when space is available * @param callback_cls closure for @a callback * @return non-NULL if the notify callback was queued; can be used * to cancel the request using * #GNUNET_SERVER_notify_transmit_ready_cancel. * NULL if we are already going to notify someone else (busy) */ struct GNUNET_SERVER_TransmitHandle * GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_CONNECTION_TransmitReadyNotify callback, void *callback_cls) { if (NULL != client->th.callback) return NULL; client->th.callback_cls = callback_cls; client->th.callback = callback; client->th.cth = GNUNET_CONNECTION_notify_transmit_ready (client->connection, size, timeout, &transmit_ready_callback_wrapper, client); return &client->th; } /** * Abort transmission request. * * @param th request to abort */ void GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle *th) { GNUNET_CONNECTION_notify_transmit_ready_cancel (th->cth); th->cth = NULL; th->callback = NULL; } /** * Set the persistent flag on this client, used to setup client connection * to only be killed when the service it's connected to is actually dead. * * @param client the client to set the persistent flag on */ void GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client) { client->persist = GNUNET_YES; } /** * Resume receiving from this client, we are done processing the * current request. This function must be called from within each * GNUNET_SERVER_MessageCallback (or its respective continuations). * * @param client client we were processing a message of * @param success #GNUNET_OK to keep the connection open and * continue to receive * #GNUNET_NO to close the connection (normal behavior) * #GNUNET_SYSERR to close the connection (signal * serious error) */ void GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success) { if (NULL == client) return; GNUNET_assert (client->suspended > 0); client->suspended--; if (GNUNET_OK != success) { LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_SERVER_receive_done called with failure indication\n"); if ( (client->reference_count > 0) || (client->suspended > 0) ) client->shutdown_now = GNUNET_YES; else GNUNET_SERVER_client_disconnect (client); return; } if (client->suspended > 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_SERVER_receive_done called, but more clients pending\n"); return; } if (GNUNET_SCHEDULER_NO_TASK != client->warn_task) { GNUNET_SCHEDULER_cancel (client->warn_task); client->warn_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_YES == client->in_process_client_buffer) { LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_SERVER_receive_done called while still in processing loop\n"); return; } if ((NULL == client->server) || (GNUNET_YES == client->shutdown_now)) { GNUNET_SERVER_client_disconnect (client); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_SERVER_receive_done causes restart in reading from the socket\n"); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == client->restart_task); client->restart_task = GNUNET_SCHEDULER_add_now (&restart_processing, client); } /* end of server.c */ gnunet-0.10.1/src/util/network.c0000644000175000017500000015513012300637201013412 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/network.c * @brief basic, low-level networking interface * @author Nils Durner * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "disk.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING #ifndef INVALID_SOCKET #define INVALID_SOCKET -1 #endif struct GNUNET_NETWORK_Handle { #ifndef MINGW int fd; #else SOCKET fd; #endif /** * Address family / domain. */ int af; /** * Type of the socket */ int type; /** * Number of bytes in addr. */ socklen_t addrlen; /** * Address we were bound to, or NULL. */ struct sockaddr *addr; }; /** * Test if the given protocol family is supported by this system. * * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX) * @return #GNUNET_OK if the PF is supported */ int GNUNET_NETWORK_test_pf (int pf) { int s; s = socket (pf, SOCK_STREAM, 0); if (-1 == s) { if (EAFNOSUPPORT == errno) return GNUNET_NO; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to create test socket: %s\n", STRERROR (errno)); return GNUNET_SYSERR; } #if WINDOWS closesocket (s); #else close (s); #endif return GNUNET_OK; } /** * Given a unixpath that is too long (larger than UNIX_PATH_MAX), * shorten it to an acceptable length while keeping it unique * and making sure it remains a valid filename (if possible). * * @param unixpath long path, will be freed (or same pointer returned * with moved 0-termination). * @return shortened unixpath, NULL on error */ char * GNUNET_NETWORK_shorten_unixpath (char *unixpath) { struct sockaddr_un dummy; size_t slen; char *end; struct GNUNET_HashCode sh; struct GNUNET_CRYPTO_HashAsciiEncoded ae; size_t upm; upm = sizeof (dummy.sun_path); slen = strlen (unixpath); if (slen < upm) return unixpath; /* no shortening required */ GNUNET_CRYPTO_hash (unixpath, slen, &sh); while (16 + strlen (unixpath) >= upm) { if (NULL == (end = strrchr (unixpath, '/'))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to shorten unix path `%s' while keeping name unique\n"), unixpath); GNUNET_free (unixpath); return NULL; } *end = '\0'; } GNUNET_CRYPTO_hash_to_enc (&sh, &ae); strncat (unixpath, (char*) ae.encoding, 16); return unixpath; } #ifndef FD_COPY #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) #endif /** * Set if a socket should use blocking or non-blocking IO. * * @param fd socket * @param doBlock blocking mode * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock) { #if MINGW u_long mode; mode = !doBlock; if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR) { SetErrnoFromWinsockError (WSAGetLastError ()); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket"); return GNUNET_SYSERR; } return GNUNET_OK; #else /* not MINGW */ int flags = fcntl (fd->fd, F_GETFL); if (flags == -1) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl"); return GNUNET_SYSERR; } if (doBlock) flags &= ~O_NONBLOCK; else flags |= O_NONBLOCK; if (0 != fcntl (fd->fd, F_SETFL, flags)) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl"); return GNUNET_SYSERR; } return GNUNET_OK; #endif } /** * Make a socket non-inheritable to child processes * * @param h the socket to make non-inheritable * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise * @warning Not implemented on Windows */ static int socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h) { #ifndef MINGW int i; i = fcntl (h->fd, F_GETFD); if (i < 0) return GNUNET_SYSERR; if (i == (i | FD_CLOEXEC)) return GNUNET_OK; i |= FD_CLOEXEC; if (fcntl (h->fd, F_SETFD, i) < 0) return GNUNET_SYSERR; #else BOOL b; SetLastError (0); b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0); if (!b) { SetErrnoFromWinsockError (WSAGetLastError ()); return GNUNET_SYSERR; } #endif return GNUNET_OK; } #ifdef DARWIN /** * The MSG_NOSIGNAL equivalent on Mac OS X * * @param h the socket to make non-delaying */ static void socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h) { int abs_value = 1; if (0 != setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, (const void *) &abs_value, sizeof (abs_value))) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); } #endif /** * Disable delays when sending data via the socket. * (GNUnet makes sure that messages are as big as * possible already). * * @param h the socket to make non-delaying */ static void socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h) { #ifndef WINDOWS int value = 1; if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value))) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); #else const char *abs_value = "1"; if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, (const void *) abs_value, sizeof (abs_value))) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); #endif } /** * Perform proper canonical initialization for a network handle. * Set it to non-blocking, make it non-inheritable to child * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX * stream socket) and check that it is smaller than FD_SETSIZE. * * @param h socket to initialize * @param af address family of the socket * @param type socket type * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization * failed and the handle was destroyed */ static int initialize_network_handle (struct GNUNET_NETWORK_Handle *h, int af, int type) { h->af = af; h->type = type; if (h->fd == INVALID_SOCKET) { #ifdef MINGW SetErrnoFromWinsockError (WSAGetLastError ()); #endif GNUNET_free (h); return GNUNET_SYSERR; } #ifndef MINGW if (h->fd >= FD_SETSIZE) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h)); errno = EMFILE; return GNUNET_SYSERR; } #endif if (GNUNET_OK != socket_set_inheritable (h)) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "socket_set_inheritable"); if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO)) { GNUNET_break (0); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h)); return GNUNET_SYSERR; } #ifdef DARWIN socket_set_nosigpipe (h); #endif if ( (type == SOCK_STREAM) #ifdef AF_UNIX && (af != AF_UNIX) #endif ) socket_set_nodelay (h); return GNUNET_OK; } /** * accept a new connection on a socket * * @param desc bound socket * @param address address of the connecting peer, may be NULL * @param address_len length of @a address * @return client socket */ struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len) { struct GNUNET_NETWORK_Handle *ret; ret = GNUNET_new (struct GNUNET_NETWORK_Handle); #if DEBUG_NETWORK { struct sockaddr name; socklen_t namelen = sizeof (name); int gsn = getsockname (desc->fd, &name, &namelen); if (gsn == 0) LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n", GNUNET_a2s (&name, namelen)); } #endif ret->fd = accept (desc->fd, address, address_len); if (-1 == ret->fd) { GNUNET_free (ret); return NULL; } if (GNUNET_OK != initialize_network_handle (ret, (NULL != address) ? address->sa_family : desc->af, SOCK_STREAM)) return NULL; return ret; } /** * Bind a socket to a particular address. * * @param desc socket to bind * @param address address to be bound * @param address_len length of @a address * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len) { int ret; #ifdef IPV6_V6ONLY #ifdef IPPROTO_IPV6 { const int on = 1; if (AF_INET6 == desc->af) if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &on, sizeof (on))) LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt"); } #endif #endif #ifndef WINDOWS { const int on = 1; /* This is required here for TCP sockets, but only on UNIX */ if ((SOCK_STREAM == desc->type) && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))) LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt"); } #endif #ifndef WINDOWS { /* set permissions of newly created non-abstract UNIX domain socket to "user-only"; applications can choose to relax this later */ mode_t old_mask = 0; /* assigned to make compiler happy */ const struct sockaddr_un *un; int not_abstract = 0; if ((AF_UNIX == address->sa_family) && (NULL != (un = (const struct sockaddr_un *) address)->sun_path) && ('\0' != un->sun_path[0]) ) /* Not an abstract socket */ not_abstract = 1; if (not_abstract) old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH); #endif ret = bind (desc->fd, address, address_len); #ifndef WINDOWS if (not_abstract) (void) umask (old_mask); } #endif #ifdef MINGW if (SOCKET_ERROR == ret) SetErrnoFromWinsockError (WSAGetLastError ()); #endif if (ret != 0) return GNUNET_SYSERR; #ifndef MINGW desc->addr = GNUNET_malloc (address_len); memcpy (desc->addr, address, address_len); desc->addrlen = address_len; #endif return GNUNET_OK; } /** * Close a socket * * @param desc socket * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc) { int ret; #ifdef WINDOWS DWORD error = 0; SetLastError (0); ret = closesocket (desc->fd); error = WSAGetLastError (); SetErrnoFromWinsockError (error); LOG (GNUNET_ERROR_TYPE_DEBUG, "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret, error); #else ret = close (desc->fd); #endif #ifndef WINDOWS const struct sockaddr_un *un; /* Cleanup the UNIX domain socket and its parent directories in case of non abstract sockets */ if ((AF_UNIX == desc->af) && (NULL != desc->addr) && (NULL != (un = (const struct sockaddr_un *) desc->addr)->sun_path) && ('\0' != un->sun_path[0])) { char *dirname = GNUNET_strndup (un->sun_path, sizeof (un->sun_path)); if (0 != unlink (dirname)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", dirname); } else { size_t len; len = strlen (dirname); while ((len > 0) && (dirname[len] != DIR_SEPARATOR)) len--; dirname[len] = '\0'; if ((0 != len) && (0 != rmdir (dirname))) { switch (errno) { case EACCES: case ENOTEMPTY: case EPERM: /* these are normal and can just be ignored */ break; default: GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rmdir", dirname); break; } } } GNUNET_free (dirname); } #endif GNUNET_NETWORK_socket_free_memory_only_ (desc); return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR; } /** * Only free memory of a socket, keep the file descriptor untouched. * * @param desc socket */ void GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc) { GNUNET_free_non_null (desc->addr); GNUNET_free (desc); } /** * Box a native socket (and check that it is a socket). * * @param fd socket to box * @return NULL on error (including not supported on target platform) */ struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native (SOCKTYPE fd) { struct GNUNET_NETWORK_Handle *ret; #if MINGW unsigned long i; DWORD d; /* FIXME: Find a better call to check that FD is valid */ if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0) return NULL; /* invalid FD */ ret = GNUNET_new (struct GNUNET_NETWORK_Handle); ret->fd = fd; ret->af = AF_UNSPEC; return ret; #else if (fcntl (fd, F_GETFD) < 0) return NULL; /* invalid FD */ ret = GNUNET_new (struct GNUNET_NETWORK_Handle); ret->fd = fd; ret->af = AF_UNSPEC; return ret; #endif } /** * Connect a socket to some remote address. * * @param desc socket * @param address peer address * @param address_len length of @a address * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len) { int ret; ret = connect (desc->fd, address, address_len); #ifdef MINGW if (SOCKET_ERROR == ret) { SetErrnoFromWinsockError (WSAGetLastError ()); if (errno == EWOULDBLOCK) errno = EINPROGRESS; } #endif return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; } /** * Get socket options * * @param desc socket * @param level protocol level of the option * @param optname identifier of the option * @param optval options * @param optlen length of @a optval * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc, int level, int optname, void *optval, socklen_t *optlen) { int ret; ret = getsockopt (desc->fd, level, optname, optval, optlen); #ifdef MINGW if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR) *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval)); else if (SOCKET_ERROR == ret) SetErrnoFromWinsockError (WSAGetLastError ()); #endif return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; } /** * Listen on a socket * * @param desc socket * @param backlog length of the listen queue * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc, int backlog) { int ret; ret = listen (desc->fd, backlog); #ifdef MINGW if (SOCKET_ERROR == ret) SetErrnoFromWinsockError (WSAGetLastError ()); #endif return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; } /** * How much data is available to be read on this descriptor? * * @param desc socket * @returns #GNUNET_NO if no data is available, or on error! */ ssize_t GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle * desc) { int error; /* How much is there to be read? */ #ifndef WINDOWS int pending; error = ioctl (desc->fd, FIONREAD, &pending); if (error == 0) return (ssize_t) pending; return GNUNET_NO; #else u_long pending; error = ioctlsocket (desc->fd, FIONREAD, &pending); if (error != SOCKET_ERROR) return (ssize_t) pending; return GNUNET_NO; #endif } /** * Read data from a socket (always non-blocking). * * @param desc socket * @param buffer buffer * @param length length of @a buffer * @param src_addr either the source to recv from, or all zeroes * to be filled in by recvfrom * @param addrlen length of the @a src_addr */ ssize_t GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc, void *buffer, size_t length, struct sockaddr *src_addr, socklen_t *addrlen) { int ret; int flags; flags = 0; #ifdef MSG_DONTWAIT flags |= MSG_DONTWAIT; #endif ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen); #ifdef MINGW if (SOCKET_ERROR == ret) SetErrnoFromWinsockError (WSAGetLastError ()); #endif return ret; } /** * Read data from a connected socket (always non-blocking). * * @param desc socket * @param buffer buffer * @param length length of @a buffer */ ssize_t GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc, void *buffer, size_t length) { int ret; int flags; flags = 0; #ifdef MSG_DONTWAIT flags |= MSG_DONTWAIT; #endif ret = recv (desc->fd, buffer, length, flags); #ifdef MINGW if (SOCKET_ERROR == ret) SetErrnoFromWinsockError (WSAGetLastError ()); #endif return ret; } /** * Send data (always non-blocking). * * @param desc socket * @param buffer data to send * @param length size of the @a buffer * @return number of bytes sent, #GNUNET_SYSERR on error */ ssize_t GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc, const void *buffer, size_t length) { int ret; int flags; flags = 0; #ifdef MSG_DONTWAIT flags |= MSG_DONTWAIT; #endif #ifdef MSG_NOSIGNAL flags |= MSG_NOSIGNAL; #endif ret = send (desc->fd, buffer, length, flags); #ifdef MINGW if (SOCKET_ERROR == ret) SetErrnoFromWinsockError (WSAGetLastError ()); #endif return ret; } /** * Send data to a particular destination (always non-blocking). * This function only works for UDP sockets. * * @param desc socket * @param message data to send * @param length size of the data * @param dest_addr destination address * @param dest_len length of @a address * @return number of bytes sent, #GNUNET_SYSERR on error */ ssize_t GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc, const void *message, size_t length, const struct sockaddr * dest_addr, socklen_t dest_len) { int ret; int flags; flags = 0; #ifdef MSG_DONTWAIT flags |= MSG_DONTWAIT; #endif #ifdef MSG_NOSIGNAL flags |= MSG_NOSIGNAL; #endif ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len); #ifdef MINGW if (SOCKET_ERROR == ret) SetErrnoFromWinsockError (WSAGetLastError ()); #endif return ret; } /** * Set socket option * * @param fd socket * @param level protocol level of the option * @param option_name option identifier * @param option_value value to set * @param option_len size of option_value * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level, int option_name, const void *option_value, socklen_t option_len) { int ret; ret = setsockopt (fd->fd, level, option_name, option_value, option_len); #ifdef MINGW if (SOCKET_ERROR == ret) SetErrnoFromWinsockError (WSAGetLastError ()); #endif return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; } /** * Create a new socket. Configure it for non-blocking IO and * mark it as non-inheritable to child processes (set the * close-on-exec flag). * * @param domain domain of the socket * @param type socket type * @param protocol network protocol * @return new socket, NULL on error */ struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create (int domain, int type, int protocol) { struct GNUNET_NETWORK_Handle *ret; ret = GNUNET_new (struct GNUNET_NETWORK_Handle); ret->fd = socket (domain, type, protocol); if (-1 == ret->fd) { GNUNET_free (ret); return NULL; } if (GNUNET_OK != initialize_network_handle (ret, domain, type)) return NULL; return ret; } /** * Shut down socket operations * @param desc socket * @param how type of shutdown * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how) { int ret; ret = shutdown (desc->fd, how); #ifdef MINGW if (ret != 0) SetErrnoFromWinsockError (WSAGetLastError ()); #endif return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; } /** * Disable the "CORK" feature for communication with the given socket, * forcing the OS to immediately flush the buffer on transmission * instead of potentially buffering multiple messages. Essentially * reduces the OS send buffers to zero. * * @param desc socket * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc) { int ret = 0; #if WINDOWS int value = 0; if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value, sizeof (value)))) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value, sizeof (value)))) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); #elif LINUX int value = 0; if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value)))) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value)))) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt"); #endif return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; } /** * Reset FD set * * @param fds fd set */ void GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds) { FD_ZERO (&fds->sds); fds->nsds = 0; #ifdef MINGW GNUNET_CONTAINER_slist_clear (fds->handles); #endif } /** * Add a socket to the FD set * * @param fds fd set * @param desc socket to add */ void GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc) { FD_SET (desc->fd, &fds->sds); if (desc->fd + 1 > fds->nsds) fds->nsds = desc->fd + 1; } /** * Check whether a socket is part of the fd set * * @param fds fd set * @param desc socket * @return 0 if the FD is not set */ int GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc) { return FD_ISSET (desc->fd, &fds->sds); } /** * Add one fd set to another * * @param dst the fd set to add to * @param src the fd set to add from */ void GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, const struct GNUNET_NETWORK_FDSet *src) { #ifndef MINGW int nfds; for (nfds = src->nsds; nfds >= 0; nfds--) if (FD_ISSET (nfds, &src->sds)) { FD_SET (nfds, &dst->sds); if (nfds + 1 > dst->nsds) dst->nsds = nfds + 1; } #else /* This is MinGW32-specific implementation that relies on the code that * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking * that fd being added is not already in the set. * Also relies on us knowing what's inside fd_set (fd_count and fd_array). */ int i; for (i = 0; i < src->sds.fd_count; i++) FD_SET (src->sds.fd_array[i], &dst->sds); if (src->nsds > dst->nsds) dst->nsds = src->nsds; GNUNET_CONTAINER_slist_append (dst->handles, src->handles); #endif } /** * Copy one fd set to another * * @param to destination * @param from source */ void GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, const struct GNUNET_NETWORK_FDSet *from) { FD_COPY (&from->sds, &to->sds); to->nsds = from->nsds; #ifdef MINGW GNUNET_CONTAINER_slist_clear (to->handles); GNUNET_CONTAINER_slist_append (to->handles, from->handles); #endif } /** * Return file descriptor for this network handle * * @param desc wrapper to process * @return POSIX file descriptor */ int GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc) { return desc->fd; } /** * Return sockaddr for this network handle * * @param desc wrapper to process * @return sockaddr */ struct sockaddr* GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc) { return desc->addr; } /** * Return sockaddr length for this network handle * * @param desc wrapper to process * @return socklen_t for sockaddr */ socklen_t GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc) { return desc->addrlen; } /** * Copy a native fd set * * @param to destination * @param from native source set * @param nfds the biggest socket number in from + 1 */ void GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to, const fd_set * from, int nfds) { FD_COPY (from, &to->sds); to->nsds = nfds; } /** * Set a native fd in a set * * @param to destination * @param nfd native FD to set */ void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd) { GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE)); FD_SET (nfd, &to->sds); to->nsds = GNUNET_MAX (nfd + 1, to->nsds); } /** * Test native fd in a set * * @param to set to test, NULL for empty set * @param nfd native FD to test, or -1 for none * @return #GNUNET_YES if FD is set in the set */ int GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to, int nfd) { if ((nfd == -1) || (to == NULL)) return GNUNET_NO; return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO; } /** * Add a file handle to the fd set * @param fds fd set * @param h the file handle to add */ void GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_DISK_FileHandle *h) { #ifdef MINGW GNUNET_CONTAINER_slist_add (fds->handles, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h, sizeof (struct GNUNET_DISK_FileHandle)); #else int fd; GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int)); FD_SET (fd, &fds->sds); if (fd + 1 > fds->nsds) fds->nsds = fd + 1; #endif } /** * Check if a file handle is part of an fd set * @param fds fd set * @param h file handle * @return #GNUNET_YES if the file handle is part of the set */ int GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_DISK_FileHandle *h) { #ifdef MINGW return GNUNET_CONTAINER_slist_contains (fds->handles, h, sizeof (struct GNUNET_DISK_FileHandle)); #else return FD_ISSET (h->fd, &fds->sds); #endif } /** * Checks if two fd sets overlap * @param fds1 first fd set * @param fds2 second fd set * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise */ int GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, const struct GNUNET_NETWORK_FDSet *fds2) { #ifndef MINGW int nfds; nfds = fds1->nsds; if (nfds > fds2->nsds) nfds = fds2->nsds; while (nfds > 0) { nfds--; if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds)) return GNUNET_YES; } #else struct GNUNET_CONTAINER_SList_Iterator it; struct GNUNET_DISK_FileHandle *h; int i; int j; /*This code is somewhat hacky, we are not supposed to know what's * inside of fd_set; also the O(n^2) is really bad... */ for (i = 0; i < fds1->sds.fd_count; i++) { for (j = 0; j < fds2->sds.fd_count; j++) { if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j]) return GNUNET_YES; } } it = GNUNET_CONTAINER_slist_begin (fds1->handles); while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES) { #if DEBUG_NETWORK struct GNUNET_CONTAINER_SList_Iterator t; #endif h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it, NULL); #if DEBUG_NETWORK LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n", h->h); for (t = GNUNET_CONTAINER_slist_begin (fds2->handles); GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&t)) { struct GNUNET_DISK_FileHandle *fh; fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t, NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h); } #endif if (GNUNET_CONTAINER_slist_contains (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle))) { return GNUNET_YES; } GNUNET_CONTAINER_slist_next (&it); } #endif return GNUNET_NO; } /** * Creates an fd set * * @return a new fd set */ struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create () { struct GNUNET_NETWORK_FDSet *fds; fds = GNUNET_new (struct GNUNET_NETWORK_FDSet); #ifdef MINGW fds->handles = GNUNET_CONTAINER_slist_create (); #endif GNUNET_NETWORK_fdset_zero (fds); return fds; } /** * Releases the associated memory of an fd set * * @param fds fd set */ void GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds) { #ifdef MINGW GNUNET_CONTAINER_slist_destroy (fds->handles); #endif GNUNET_free (fds); } #if MINGW struct _select_params { fd_set *r; fd_set *w; fd_set *e; struct timeval *tv; HANDLE wakeup; HANDLE standby; SOCKET wakeup_socket; int status; }; static DWORD WINAPI _selector (LPVOID p) { struct _select_params *sp = p; while (1) { WaitForSingleObject (sp->standby, INFINITE); ResetEvent (sp->standby); sp->status = select (1, sp->r, sp->w, sp->e, sp->tv); if (FD_ISSET (sp->wakeup_socket, sp->r)) { FD_CLR (sp->wakeup_socket, sp->r); sp->status -= 1; } SetEvent (sp->wakeup); } return 0; } #endif #ifndef MINGW /** * Check if sockets or pipes meet certain conditions * * @param rfds set of sockets or pipes to be checked for readability * @param wfds set of sockets or pipes to be checked for writability * @param efds set of sockets or pipes to be checked for exceptions * @param timeout relative value when to return * @return number of selected sockets or pipes, #GNUNET_SYSERR on error */ int GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, const struct GNUNET_TIME_Relative timeout) { int nfds; struct timeval tv; if (NULL != rfds) nfds = rfds->nsds; else nfds = 0; if (NULL != wfds) nfds = GNUNET_MAX (nfds, wfds->nsds); if (NULL != efds) nfds = GNUNET_MAX (nfds, efds->nsds); if ((nfds == 0) && (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_ERROR, _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"), "select"); } tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us; tv.tv_usec = (timeout.rel_value_us - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us)); return select (nfds, (NULL != rfds) ? &rfds->sds : NULL, (NULL != wfds) ? &wfds->sds : NULL, (NULL != efds) ? &efds->sds : NULL, (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv); } #else /* MINGW */ /** * Check if sockets or pipes meet certain conditions, version for W32. * * @param rfds set of sockets or pipes to be checked for readability * @param wfds set of sockets or pipes to be checked for writability * @param efds set of sockets or pipes to be checked for exceptions * @param timeout relative value when to return * @return number of selected sockets or pipes, #GNUNET_SYSERR on error */ int GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, const struct GNUNET_TIME_Relative timeout) { int nfds = 0; int handles = 0; int ex_handles = 0; int read_handles = 0; int write_handles = 0; int i = 0; int retcode = 0; uint64_t mcs_total = 0; DWORD ms_rounded = 0; int nhandles = 0; static HANDLE hEventPipeWrite = 0; static HANDLE hEventReadReady = 0; static struct _select_params sp; static HANDLE select_thread = NULL; static HANDLE select_finished_event = NULL; static HANDLE select_standby_event = NULL; static SOCKET select_wakeup_socket = -1; static SOCKET select_send_socket = -1; static struct timeval select_timeout; int readPipes = 0; int writePipePos = 0; HANDLE handle_array[FD_SETSIZE + 2]; int returncode = -1; int returnedpos = 0; struct GNUNET_CONTAINER_SList *handles_read; struct GNUNET_CONTAINER_SList *handles_write; struct GNUNET_CONTAINER_SList *handles_except; int selectret = 0; fd_set aread; fd_set awrite; fd_set aexcept; #if DEBUG_NETWORK fd_set bread; fd_set bwrite; fd_set bexcept; #endif /* TODO: Make this growable */ struct GNUNET_DISK_FileHandle *readArray[50]; struct timeval tv; if (NULL != rfds) { nfds = rfds->nsds; handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles); #if DEBUG_NETWORK { struct GNUNET_CONTAINER_SList_Iterator t; for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&t)) { struct GNUNET_DISK_FileHandle *fh; fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t, NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h, fh); } } #endif } if (NULL != wfds) { nfds = GNUNET_MAX (nfds, wfds->nsds); handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles); } if (NULL != efds) { nfds = GNUNET_MAX (nfds, efds->nsds); handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles); } if ((nfds == 0) && (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) && (handles == 0) ) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_ERROR, _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"), "select"); } #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) /* calculate how long we need to wait in microseconds */ if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) { mcs_total = INFINITE; ms_rounded = INFINITE; } else { mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us; ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us); if (mcs_total > 0 && ms_rounded == 0) ms_rounded = 1; } /* select() may be used as a portable way to sleep */ if (!(rfds || wfds || efds)) { Sleep (ms_rounded); return 0; } if (NULL == select_thread) { SOCKET select_listening_socket = -1; struct sockaddr_in s_in; int alen; int res; unsigned long p; select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL); select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL); select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); p = 1; res = ioctlsocket (select_wakeup_socket, FIONBIO, &p); LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res); alen = sizeof (s_in); s_in.sin_family = AF_INET; s_in.sin_port = 0; s_in.sin_addr.S_un.S_un_b.s_b1 = 127; s_in.sin_addr.S_un.S_un_b.s_b2 = 0; s_in.sin_addr.S_un.S_un_b.s_b3 = 0; s_in.sin_addr.S_un.S_un_b.s_b4 = 1; res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res); res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen); LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res); res = listen (select_listening_socket, SOMAXCONN); LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res); res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res); select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen); closesocket (select_listening_socket); sp.wakeup = select_finished_event; sp.standby = select_standby_event; sp.wakeup_socket = select_wakeup_socket; select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL); } handles_read = GNUNET_CONTAINER_slist_create (); handles_write = GNUNET_CONTAINER_slist_create (); handles_except = GNUNET_CONTAINER_slist_create (); FD_ZERO (&aread); FD_ZERO (&awrite); FD_ZERO (&aexcept); #if DEBUG_NETWORK FD_ZERO (&bread); FD_ZERO (&bwrite); FD_ZERO (&bexcept); #endif if (rfds) { FD_COPY (&rfds->sds, &aread); #if DEBUG_NETWORK FD_COPY (&rfds->sds, &bread); #endif } if (wfds) { FD_COPY (&wfds->sds, &awrite); #if DEBUG_NETWORK FD_COPY (&wfds->sds, &bwrite); #endif } if (efds) { FD_COPY (&efds->sds, &aexcept); #if DEBUG_NETWORK FD_COPY (&efds->sds, &bexcept); #endif } /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time. By profiling we detected that to be true in 90% of the cases. */ /* Do the select now */ select_timeout.tv_sec = 0; select_timeout.tv_usec = 0; /* Copy all the writes to the except, so we can detect connect() errors */ for (i = 0; i < awrite.fd_count; i++) FD_SET (awrite.fd_array[i], &aexcept); if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0) selectret = select (1, (rfds != NULL) ? &aread : NULL, (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout); else selectret = 0; if (selectret == -1) { /* Throw an error early on, while we still have the context. */ LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n", rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ()); GNUNET_abort (); } /* Check aexcept, add its contents to awrite This is technically wrong (aexcept might have its own descriptors), we should have checked that descriptors were in awrite originally before re-adding them from aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */ for (i = 0; i < aexcept.fd_count; i++) FD_SET (aexcept.fd_array[i], &awrite); /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */ /* Sadly, it means code duplication :( */ if ((selectret > 0) || (mcs_total == 0)) { /* Read Pipes */ if (rfds && read_handles) { struct GNUNET_CONTAINER_SList_Iterator i; int c; for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles); GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&i), c++) { struct GNUNET_DISK_FileHandle *fh; fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL); if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { DWORD error; BOOL bret; SetLastError (0); DWORD waitstatus = 0; bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL); error = GetLastError (); LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", c, fh->h, bret, waitstatus, error); if (bret == 0) { /* TODO: either add more errors to this condition, or eliminate it * entirely (failed to peek -> pipe is in serious trouble, should * be selected as readable). */ if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE) continue; } else if (waitstatus <= 0) continue; GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, fh, sizeof (struct GNUNET_DISK_FileHandle)); retcode++; LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n", fh, fh->h); } else { GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, fh, sizeof (struct GNUNET_DISK_FileHandle)); retcode++; } } } if (wfds && write_handles) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding the write ready event to the array as %d\n", nhandles); GNUNET_CONTAINER_slist_append (handles_write, wfds->handles); retcode += write_handles; } if (efds && ex_handles) { struct GNUNET_CONTAINER_SList_Iterator i; for (i = GNUNET_CONTAINER_slist_begin (efds->handles); GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&i)) { struct GNUNET_DISK_FileHandle *fh; DWORD dwBytes; fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL); if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) continue; GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, fh, sizeof (struct GNUNET_DISK_FileHandle)); retcode++; } } } /* Add our select() result.*/ if (selectret >= 0) retcode += selectret; if (rfds) { GNUNET_NETWORK_fdset_zero (rfds); if (selectret != -1) GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret); GNUNET_CONTAINER_slist_append (rfds->handles, handles_read); } if (wfds) { GNUNET_NETWORK_fdset_zero (wfds); if (selectret != -1) GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret); GNUNET_CONTAINER_slist_append (wfds->handles, handles_write); } if (efds) { GNUNET_NETWORK_fdset_zero (efds); if (selectret != -1) GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret); GNUNET_CONTAINER_slist_append (efds->handles, handles_except); } GNUNET_CONTAINER_slist_destroy (handles_read); GNUNET_CONTAINER_slist_destroy (handles_write); GNUNET_CONTAINER_slist_destroy (handles_except); if (selectret == -1) return -1; return retcode; } /* If we got this far, use slower implementation that is able to do a waiting select on both sockets and pipes simultaneously */ /* Events for pipes */ if (!hEventReadReady) hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL); if (!hEventPipeWrite) hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL); readPipes = 0; writePipePos = -1; retcode = 0; FD_ZERO (&aread); FD_ZERO (&awrite); FD_ZERO (&aexcept); #if DEBUG_NETWORK FD_ZERO (&bread); FD_ZERO (&bwrite); FD_ZERO (&bexcept); #endif if (rfds) { FD_COPY (&rfds->sds, &aread); #if DEBUG_NETWORK FD_COPY (&rfds->sds, &bread); #endif } if (wfds) { FD_COPY (&wfds->sds, &awrite); #if DEBUG_NETWORK FD_COPY (&wfds->sds, &bwrite); #endif } if (efds) { FD_COPY (&efds->sds, &aexcept); #if DEBUG_NETWORK FD_COPY (&efds->sds, &bexcept); #endif } /* We will first Add the PIPES to the events */ /* Read Pipes */ if (rfds && read_handles) { struct GNUNET_CONTAINER_SList_Iterator i; for (i = GNUNET_CONTAINER_slist_begin (rfds->handles); GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&i)) { struct GNUNET_DISK_FileHandle *fh; fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL); if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { /* Read zero bytes to check the status of the pipe */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n", fh->h); if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead)) { DWORD error_code = GetLastError (); if (error_code == ERROR_IO_PENDING) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding the pipe's 0x%x overlapped event to the array as %d\n", fh->h, nhandles); handle_array[nhandles++] = fh->oOverlapRead->hEvent; readArray[readPipes++] = fh; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Read failed, adding the read ready event to the array as %d\n", nhandles); handle_array[nhandles++] = hEventReadReady; readArray[readPipes++] = fh; } } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding the read ready event to the array as %d\n", nhandles); handle_array[nhandles++] = hEventReadReady; readArray[readPipes++] = fh; } } else { GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, fh, sizeof (struct GNUNET_DISK_FileHandle)); } } } if (wfds && write_handles) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding the write ready event to the array as %d\n", nhandles); handle_array[nhandles++] = hEventPipeWrite; writePipePos = nhandles; } if (efds && ex_handles) { struct GNUNET_CONTAINER_SList_Iterator i; for (i = GNUNET_CONTAINER_slist_begin (efds->handles); GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&i)) { struct GNUNET_DISK_FileHandle *fh; DWORD dwBytes; fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL); if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) { GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, fh, sizeof (struct GNUNET_DISK_FileHandle)); } } } } sp.status = 0; if (nfds > 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding the socket event to the array as %d\n", nhandles); handle_array[nhandles++] = select_finished_event; if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) sp.tv = NULL; else { select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us; select_timeout.tv_usec =(timeout.rel_value_us - (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us)); sp.tv = &select_timeout; } FD_SET (select_wakeup_socket, &aread); do { i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0); } while (i == 1); sp.r = &aread; sp.w = &awrite; sp.e = &aexcept; /* Failed connections cause sockets to be set in errorfds on W32, * but on POSIX it should set them in writefds. * First copy all awrite sockets to aexcept, later we'll * check aexcept and set its contents in awrite as well * Sockets are also set in errorfds when OOB data is available, * but we don't use OOB data. */ for (i = 0; i < awrite.fd_count; i++) FD_SET (awrite.fd_array[i], &aexcept); ResetEvent (select_finished_event); SetEvent (select_standby_event); } handle_array[nhandles] = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n", nfds, nhandles, mcs_total); if (nhandles) { returncode = WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded); LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode); } else if (nfds > 0) { GNUNET_break (0); /* This branch shouldn't actually be executed...*/ i = (int) WaitForSingleObject (select_finished_event, INFINITE); returncode = WAIT_TIMEOUT; } else { /* Shouldn't come this far. If it does - investigate. */ GNUNET_assert (0); } if (nfds > 0) { /* Don't wake up select-thread when delay is 0, it should return immediately * and wake up by itself. */ if (mcs_total != 0) i = send (select_send_socket, (const char *) &returnedpos, 1, 0); i = (int) WaitForSingleObject (select_finished_event, INFINITE); LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status); if (mcs_total != 0) { do { i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0); } while (i == 1); } /* Check aexcept, add its contents to awrite */ for (i = 0; i < aexcept.fd_count; i++) FD_SET (aexcept.fd_array[i], &awrite); } returnedpos = returncode - WAIT_OBJECT_0; LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos); if (nhandles && (returnedpos < nhandles)) { DWORD waitstatus; if (sp.status > 0) retcode += sp.status; if ((writePipePos != -1) && (returnedpos < writePipePos)) { GNUNET_CONTAINER_slist_append (handles_write, wfds->handles); retcode += write_handles; LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n"); } LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes); /* We have some pipes ready for read. */ if (returnedpos < readPipes) { for (i = 0; i < readPipes; i++) { DWORD error; BOOL bret; SetLastError (0); waitstatus = 0; bret = PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL); error = GetLastError (); LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", i, readArray[i]->h, bret, waitstatus, error); if (bret == 0) { /* TODO: either add more errors to this condition, or eliminate it * entirely (failed to peek -> pipe is in serious trouble, should * be selected as readable). */ if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE) continue; } else if (waitstatus <= 0) continue; GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, readArray[i], sizeof (struct GNUNET_DISK_FileHandle)); retcode++; LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n", readArray[i], readArray[i]->h); } } } if (!nhandles || (returnedpos >= nhandles)) LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n"); if (rfds) { struct GNUNET_CONTAINER_SList_Iterator t; for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&t)) { struct GNUNET_DISK_FileHandle *fh; fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t, NULL); if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { CancelIo (fh->h); } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : ""); GNUNET_NETWORK_fdset_zero (rfds); if (retcode != -1 && nhandles && (returnedpos < nhandles)) GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode); GNUNET_CONTAINER_slist_append (rfds->handles, handles_read); } if (wfds) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : ""); GNUNET_NETWORK_fdset_zero (wfds); if (retcode != -1 && nhandles && (returnedpos < nhandles)) GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode); GNUNET_CONTAINER_slist_append (wfds->handles, handles_write); } if (efds) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : ""); GNUNET_NETWORK_fdset_zero (efds); if (retcode != -1 && nhandles && (returnedpos < nhandles)) GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode); GNUNET_CONTAINER_slist_append (efds->handles, handles_except); } GNUNET_CONTAINER_slist_destroy (handles_read); GNUNET_CONTAINER_slist_destroy (handles_write); GNUNET_CONTAINER_slist_destroy (handles_except); #if DEBUG_NETWORK if (rfds) { struct GNUNET_CONTAINER_SList_Iterator t; LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n"); for (i = 0; i < rfds->sds.fd_count; i++) { LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]); } for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&t)) { struct GNUNET_DISK_FileHandle *fh; fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t, NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h); } } if (wfds) { LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n"); for (i = 0; i < wfds->sds.fd_count; i++) { LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]); } } if (efds) { LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n"); for (i = 0; i < efds->sds.fd_count; i++) { LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]); } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode); #endif if (nhandles && (returnedpos < nhandles)) return retcode; else return 0; } /* MINGW */ #endif /* end of network.c */ gnunet-0.10.1/src/util/test_crypto_crc.c0000644000175000017500000003337612225777501015154 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. For the actual CRC code: Copyright abandoned; this code is in the public domain. Provided to GNUnet by peter@horizon.com */ /** * @file util/test_crypto_crc.c * @brief testcase for crypto_crc.c */ #include "platform.h" #include "gnunet_util_lib.h" static int expected[] = { -1223996378, 929797997, -1048047323, 1791081351, -425765913, 2138425902, 82584863, 1939615314, 1806463044, -1505003452, 1878277636, -997353517, 201238705, 1723258694, -1107452366, -344562561, -1102247383, 1973035265, 715213337, -1886586005, 2021214515, -1387332962, 593019378, -571088044, 1412577760, 412164558, -1626111170, 1556494863, -289796528, -850404775, 2066714587, -911838105, -1426027382, 499684507, -835420055, 1817119454, -1221795958, 1516966784, -1038806877, -2115880691, 532627620, 1984437415, -396341583, -1345366324, -590766745, -1801923449, 1752427988, -386896390, 453906317, 1552589433, -858925718, 1160445643, -740188079, -486609040, 1102529269, -515846212, -1614217202, 1572162207, 943558923, -467330358, -1870764193, 1477005328, -793029208, -888983175, -696956020, 842706021, 1642390067, -805889494, 1284862057, 1562545388, 2091626273, 1852404553, -2076508101, 370903003, 1186422975, 1936085227, 769358463, 180401058, 2032612572, -105461719, -1119935472, 617249831, 1169304728, 1771205256, -2042554284, 653270859, -918610713, 336081663, -913685370, 1962213744, -505406126, -838622649, -1141518710, 893143582, -1330296611, 122119483, 1111564496, 688811976, 1016241049, -1803438473, 359630107, 1034798954, -581359286, 1590946527, -389997034, 2020318460, 1695967527, -464069727, -862641495, -1405012109, -771244841, 738226150, -1035328134, -933945474, 1254965774, 1661863830, -884127998, 1800460481, 814702567, -1214068102, -541120421, 1898656429, -236825530, 1505866267, 1252462132, -981007520, 1502096471, -2134644056, 483221797, 1276403836, 541133290, -1234093967, 350748780, 257941070, 1030457090, 434988890, -1098135432, -1000556640, -577128022, 644806294, -787536281, -1288346343, 998079404, 1259353935, 955771631, -958377466, 1746756252, 451579658, 1913409243, -952026299, -1556035958, -830279881, 834744289, -1878491428, 700000962, -1027245802, 1393574384, -1260409147, -841420884, 892132797, 1494730226, -1649181766, 1651097838, -1041807403, -1916675721, -1324525963, 157405899, -655788033, -1943555237, -79747022, 339721623, -138341083, 1111902411, -435322914, -533294200, -190220608, -1718346014, -1631301894, 1706265243, 745533899, 1351941230, 1803009594, -1218191958, 1467751062, 84368433, -711251880, 1699423788, -768792716, 846639904, 2103267723, -2095288070, -440571408, -362144485, 2020468971, 352105963, -849211036, -1272592429, 1743440467, 2020667861, -1649992312, 172682343, 816705364, -1990206923, 902689869, -298510060, 164207498, 190378213, 242531543, 113383268, 304810777, -1081099373, 819221134, -1100982926, -855941239, 1091308887, -934548124, 520508733, -1381763773, -491593287, -2143492665, 700894653, -2049034808, -160942046, -2009323577, 1464245054, 1584746011, -768646852, -993282698, 1265838699, -1873820824, 575704373, -986682955, 1270688416, 88587481, -1723991633, -409928242, 866669946, -483811323, -181759253, -963525431, -1686612238, -1663460076, -1128449775, -1368922329, 122318131, 795862385, 528576131, -19927090, 1369299478, 1285665642, -738964611, 1328292127, 552041252, -1431494354, -1205275362, 42768297, -1329537238, -449177266, 943925221, 987016465, -945138414, -270064876, 1650366626, -369252552, 582030210, -1229235374, 147901387, -517510506, -1609742888, -1086838308, 1391998445, -313975512, -613392078, 855706229, 1475706341, -1112105406, 2032001400, 1565777625, 2030937777, 435522421, 1823527907, -691390605, -827253664, 1057171580, -314146639, -630099999, -1347514552, 478716232, -1533658804, -1425371979, 761987780, 1560243817, -1945893959, 1205759225, -959343783, -576742354, -154125407, -1158108776, 1183788580, 1354198127, -1534207721, -823991517, -170534462, -912524170, 1858513573, 467072185, 2091040157, -1765027018, -1659401643, -1173890143, -1912754057, -84568053, 2010781784, -921970156, 944508352, -922040609, 1055102010, 1018688871, -1186761311, -2012263648, 1311654161, 277659086, 2029602288, 1127061510, 1029452642, 285677123, -188521091, -641039012, 653836416, -805916340, -1644860596, 1352872213, 691634876, -1477113308, -748430369, 1030697363, -2007864449, -1196662616, 1313997192, 177342476, -566676450, -1118618118, 1697953104, 344671484, -1489783116, -889507873, 1259591310, -716567168, 2116447062, 324368527, 1789366816, 1558930442, 1950250221, -785460151, 1174714258, -430047304, -859487565, -580633932, 607732845, -1128150220, 1544355315, 1460298016, -1771194297, 1215703690, 277231808, -416020628, -418936577, -1724839216, 404731389, 1058730508, -1508366681, 229883053, -572310243, 1883189553, 931286849, 1659300867, -94236383, -241524462, 548020458, -302406981, 579986475, 73468197, -984957614, 1554382245, 2084807492, -1456802798, -1105192593, 629440327, -16313961, -2102585261, 1873675206, 161035128, 1497033351, 1990150811, -499405222, 304019482, 41935663, -805987182, -571699268, 1748462913, 2096239823, -116359807, -1871127553, -1074832534, -1558866192, 231353861, 2122854560, -2102323721, -281462361, -343403210, -673268171, 1776058383, 1581561150, 2059580579, 768848632, 1347190372, -1701705879, 245282007, -563267886, -592558289, 1662399958, 1390406821, -1522485580, -706446863, 2069516289, -301855859, -778346387, -1454093198, 1249083752, -1760506745, 262193320, 630751125, -1495939124, -29980580, -1989626563, 659039376, -329477132, -1003507166, -1322549020, 358606508, -2052572059, 1848014133, 1826958586, -1004948862, -1775370541, 2134177912, -1739214473, 1892700918, 926629675, -1042761322, 2020075900, 606370962, -1256609305, 117577265, -586848924, 191368285, 1653535275, -1329269701, -375879127, -1089901406, 1206489978, 534223924, -1042752982, -1178316881, -445594741, -1501682065, -1598136839, -467688289, 750784023, 1781080461, 1729380226, 16906088, 862168532, -2037752683, 1455274138, -1491220107, 1058323960, 1711530558, 1355062750, 227640096, 396568027, -173579098, -408975801, -993618329, -1470751562, 371076647, 209563718, 2015405719, -723460281, -1423934420, -2089643958, 353260489, 2084264341, -792676687, 701391030, -1440658244, 1479321011, 1907822880, 1232524257, -256712289, 401077577, 621808069, 868263613, 1244930119, 2020996902, 117483907, 1341376744, -1936988014, -445200547, -843751811, -435291191, 1041695743, 476132726, -1226874735, -1436046747, -297047422, 1739645396, 1948680937, -718144374, 1141983978, 1673650568, -197244350, 1604464002, 1424069853, -485626505, 1708710014, -849136541, 1573778103, 530360999, 1777767203, 1376958336, -1088364352, 1826167753, 742735448, -1386211659, -1991323164, -444115655, -443055378, -1586901006, -1741686587, 1925818034, -2118916824, 803890920, -1481793154, 992278937, 1302616410, 444517030, 1393144770, -2025632978, 1902300505, -1683582981, 800654133, 873850324, -619580878, -2002070410, -2024936385, 1978986634, 2012024264, 675768872, 389435615, -867217540, 231209167, -303917385, 1445676969, -1385982721, 1310476490, 580273453, -160600202, -1330895874, 487110497, 1124384798, 227637416, -1829783306, 1014818058, -1336870683, -1042199518, -468525587, -1186267363, -472843891, 1215617600, -2056648329, -873216891, 156780951, -1883246047, -842549253, -717684332, 760531638, 1074787431, 786267513, 814031289, -561255343, -110302255, -1837376592, 989669060, -81350614, 546038730, 222899882, 1298746805, 1791615733, 1565630269, 1516024174, 421691479, 1860326051, -1973359550, 1854393443, -1401468528, -158562295, 1509929255, -124024738, -462937489, 259890715, -1515121317, -289511197, -913738664, 698079062, -1631229382, -507275144, 1897739663, -1118192766, -1687033399, 61405556, -1913606579, -473308896, -259107170, -576944609, -1689355510, 322156799, 545090192, 127425176, -1815211748, -2070235628, -1172529316, 599259550, -910906653, 1797380363, -938649427, 142991392, 504559631, 1208867355, -807699247, -616021271, -254935281, -57151221, -1095534993, 1998380318, 1772459584, 713271407, -1197898266, 808881935, -308133481, -1314455137, 284321772, -743117625, -1622364240, -1667535152, 118713606, 1053615347, -2072876023, -178189072, -828319551, 2047304928, -1311435786, -1970672907, -747972100, 86806159, -436088421, 1464645587, 735840899, 32600466, -190473426, -735703440, 482872155, 475662392, -713681085, 1424078728, -150668609, -1137197868, -1682762563, -48035649, 1143959866, -1542015129, 284920371, -1587695586, -625236551, -753893357, -433976266, -1329796037, -1636712478, 1686783454, 27839146, 1748631474, -879528256, 2057796026, 773734654, 112269667, -2011541314, 1517797297, -1943171794, 268166111, -1037010413, -1945824504, -1672323792, 306260758, -692968628, -701704965, -462980996, 939188824, 553289792, 1790245000, 2093793129, -658085781, -186055037, -2130433650, -1013235433, 1190870089, -2126586963, -1509655742, -1291895256, -1427857845, 309538950, 388316741, 259659733, -1895092434, 110126220, -170175575, -419430224, -696234084, -832170948, -353431720, -797675726, -1644136054, 715163272, -1305904349, -145786463, -99586244, -695450446, -871327102, -725496060, 952863853, -688441983, -1729929460, -103732092, 1059054528, 568873585, -982665223, -128672783, 2099418320, 1508239336, -2089480835, -390935727, 664306522, -1607364342, -163246802, -1121295140, -128375779, -615694409, -2079391797, 760542037, 677761593, -750117849, -1060525080, 2128437080, 525250908, 1987657172, 2032530557, -2011247936, 1942775263, 1681562788, 688229491, -803856505, 684707948, 1308988965, 1455480037, 790659611, 1557968784, -383203149, -361510986, -742575828, 558837193, -1214977424, 1253274105, -119513513, -993964385, -33438767, -177452803, 1186928041, -2073533871, 1188528559, 1896514695, 1200128512, 1930588755, -1914141443, 1534656032, -1192989829, -1848274656, -220848455, 1001806509, 1298797392, 1533031884, -1912322446, 1705583815, 1568094347, -1397640627, 807828512, -1852996497, -1529733505, -1575634185, -1280270160, -1567624159, -1861904922, 1276738579, 1163432999, 626879833, 316942006, -1871138342, 1341039701, 1595907877, 1950911580, 1634717748, 1071476055, -809354290, -1161553341, -2081621710, -2085557943, 19360224, 322135580, -698485151, 1267663094, -233890834, -126361189, -1426257522, 1094007921, 500179855, -283548002, -1678987343, 1946999943, 1489410849, 2089571262, 1430799093, 1961848046, -99462663, -552833264, 1168700661, -1783882181, 2089196401, 1092839657, 914488673, 80263859, -2140947098, -726384741, -1022448237, 2113887675, 1485770846, -112922517, 1995461466, 774613726, 944068011, 1521975359, 289086919, -386920759, -1960513175, 358460021, -238698524, -1913640563, -1000324864, 1731755224, -1271586254, -1917469655, 2134162829, -828097534, -1089292503, -1514835999, 1682931514, -482307169, 2110243841, 115744834, -2038340170, 65889188, -539445712, -1713206408, -1842396726, -1659545588, -909558923, 860164922, 1328713040, 1044007120, -2103807103, -1073990344, -1312783785, -884980824, -705318011, -1263408788, -2032228692, -1732844111, -1813827156, 1462566279, 1179250845, 1732421772, 604429013, -92284336, -1192166516, 304654351, 1998552034, -1802461575, -1802704071, -1704833934, -976264396, 1005840702, 2108843914, 1363909309, 843040834, -1039625241, 1285007226, 91610001, 418426329, 678422358, -945360697, -440008081, -1053091357, 425719777, -1372778676, 591912153, 1229089037, -56663158, 2140251400, 830257037, 763914157, 175610373, -2105655963, -1040826150, 1174443038, 339290593, 346618443, -180504100, -1363190515, 210620018, 1028894425, 573529714, 698460117, 136999397, 1015621712, -1401813739, -297990684, -1820934845, -1299093313, 1299361369, -366522415, 91527707, 1113466178, -956229484, 22204763, -1394374195, -1912666711, -1453789804, 1613408399, -169509567, 1350520309, 540761213, -2086682848, 1095131491, -812787911, 1860108594, -1121378737, -1667252487, -486084366, 166519760, 1609891237, 728218405, 291075010, 646168382, 108462277, -1616661910, 1016600360, 2099958568, 27934736, 183821196, 13660496, -805589719, 936068730, -439037934, 1414622584, 215845485, -1352304469, -1817427526, -1318710977, -110207199, 228524335, 1704746590, 998293651, -1521016702, -641956531, -2089808167, 2094404052, -1446381065, -662186492, 1670154584, 9637833, 493925511, 660047318, 1197537103, 1696017374, -204994399, -1104145601, -852330465, -1936369658, -829716674, -1255255217, 1264013799, 1642611772, -652520861, 777247164, 2028895987, -1424241853, -54367829, -1940161761, -1802831079, -449405299, 838242661, -323055438, 794295411, -136989378, -446686673, -421252799, -16777216, }; int main (int argc, char *argv[]) { char buf[1024]; int i; GNUNET_log_setup ("test-crypto-crc", "WARNING", NULL); for (i = 0; i < 1024; i++) buf[i] = (char) i; for (i = 0; i < 1024; i++) if (expected[i] != GNUNET_CRYPTO_crc32_n (&buf[i], 1024 - i)) return 1; return 0; } gnunet-0.10.1/src/util/helper.c0000644000175000017500000004534412301361473013213 00000000000000/* This file is part of GNUnet. (C) 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/helper.c * @brief API for dealing with (SUID) helper processes that communicate via * GNUNET_MessageHeaders on stdin/stdout * @author Philipp Toelke * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" /** * Entry in the queue of messages we need to transmit to the helper. */ struct GNUNET_HELPER_SendHandle { /** * This is an entry in a DLL. */ struct GNUNET_HELPER_SendHandle *next; /** * This is an entry in a DLL. */ struct GNUNET_HELPER_SendHandle *prev; /** * Message to transmit (allocated at the end of this struct) */ const struct GNUNET_MessageHeader *msg; /** * The handle to a helper process. */ struct GNUNET_HELPER_Handle *h; /** * Function to call upon completion. */ GNUNET_HELPER_Continuation cont; /** * Closure to 'cont'. */ void *cont_cls; /** * Current write position. */ unsigned int wpos; }; /** * The handle to a helper process. */ struct GNUNET_HELPER_Handle { /** * PipeHandle to receive data from the helper */ struct GNUNET_DISK_PipeHandle *helper_in; /** * PipeHandle to send data to the helper */ struct GNUNET_DISK_PipeHandle *helper_out; /** * FileHandle to receive data from the helper */ const struct GNUNET_DISK_FileHandle *fh_from_helper; /** * FileHandle to send data to the helper */ const struct GNUNET_DISK_FileHandle *fh_to_helper; /** * The process id of the helper */ struct GNUNET_OS_Process *helper_proc; /** * The Message-Tokenizer that tokenizes the messages comming from the helper */ struct GNUNET_SERVER_MessageStreamTokenizer *mst; /** * The exception callback */ GNUNET_HELPER_ExceptionCallback exp_cb; /** * The closure for callbacks */ void *cb_cls; /** * First message queued for transmission to helper. */ struct GNUNET_HELPER_SendHandle *sh_head; /** * Last message queued for transmission to helper. */ struct GNUNET_HELPER_SendHandle *sh_tail; /** * Binary to run. */ char *binary_name; /** * NULL-terminated list of command-line arguments. */ char **binary_argv; /** * Task to read from the helper. */ GNUNET_SCHEDULER_TaskIdentifier read_task; /** * Task to read from the helper. */ GNUNET_SCHEDULER_TaskIdentifier write_task; /** * Restart task. */ GNUNET_SCHEDULER_TaskIdentifier restart_task; /** * Does the helper support the use of a control pipe for signalling? */ int with_control_pipe; }; /** * Sends termination signal to the helper process. The helper process is not * reaped; call GNUNET_HELPER_wait() for reaping the dead helper process. * * @param h the helper handle * @param soft_kill if GNUNET_YES, signals termination by closing the helper's * stdin; GNUNET_NO to signal termination by sending SIGTERM to helper * @return #GNUNET_OK on success; #GNUNET_SYSERR on error */ int GNUNET_HELPER_kill (struct GNUNET_HELPER_Handle *h, int soft_kill) { struct GNUNET_HELPER_SendHandle *sh; int ret; while (NULL != (sh = h->sh_head)) { GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh); if (NULL != sh->cont) sh->cont (sh->cont_cls, GNUNET_NO); GNUNET_free (sh); } if (GNUNET_SCHEDULER_NO_TASK != h->restart_task) { GNUNET_SCHEDULER_cancel (h->restart_task); h->restart_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != h->read_task) { GNUNET_SCHEDULER_cancel (h->read_task); h->read_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL == h->helper_proc) return GNUNET_SYSERR; if (GNUNET_YES == soft_kill) { /* soft-kill only possible with pipes */ GNUNET_assert (NULL != h->helper_in); ret = GNUNET_DISK_pipe_close (h->helper_in); h->helper_in = NULL; h->fh_to_helper = NULL; return ret; } if (0 != GNUNET_OS_process_kill (h->helper_proc, GNUNET_TERM_SIG)) return GNUNET_SYSERR; return GNUNET_OK; } /** * Reap the helper process. This call is blocking(!). The helper process * should either be sent a termination signal before or should be dead before * calling this function * * @param h the helper handle * @return #GNUNET_OK on success; #GNUNET_SYSERR on error */ int GNUNET_HELPER_wait (struct GNUNET_HELPER_Handle *h) { struct GNUNET_HELPER_SendHandle *sh; int ret; ret = GNUNET_SYSERR; if (NULL != h->helper_proc) { ret = GNUNET_OS_process_wait (h->helper_proc); GNUNET_OS_process_destroy (h->helper_proc); h->helper_proc = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->read_task) { GNUNET_SCHEDULER_cancel (h->read_task); h->read_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != h->write_task) { GNUNET_SCHEDULER_cancel (h->write_task); h->write_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != h->helper_in) { GNUNET_DISK_pipe_close (h->helper_in); h->helper_in = NULL; h->fh_to_helper = NULL; } if (NULL != h->helper_out) { GNUNET_DISK_pipe_close (h->helper_out); h->helper_out = NULL; h->fh_from_helper = NULL; } while (NULL != (sh = h->sh_head)) { GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh); if (NULL != sh->cont) sh->cont (sh->cont_cls, GNUNET_NO); GNUNET_free (sh); } /* purge MST buffer */ if (NULL != h->mst) (void) GNUNET_SERVER_mst_receive (h->mst, NULL, NULL, 0, GNUNET_YES, GNUNET_NO); return ret; } /** * Stop the helper process, we're closing down or had an error. * * @param h handle to the helper process * @param soft_kill if #GNUNET_YES, signals termination by closing the helper's * stdin; #GNUNET_NO to signal termination by sending SIGTERM to helper */ static void stop_helper (struct GNUNET_HELPER_Handle *h, int soft_kill) { if (GNUNET_SCHEDULER_NO_TASK != h->restart_task) { GNUNET_SCHEDULER_cancel (h->restart_task); h->restart_task = GNUNET_SCHEDULER_NO_TASK; } else { GNUNET_break (GNUNET_OK == GNUNET_HELPER_kill (h, soft_kill)); GNUNET_break (GNUNET_OK == GNUNET_HELPER_wait (h)); } } /** * Restart the helper process. * * @param cls handle to the helper process * @param tc scheduler context */ static void restart_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Read from the helper-process * * @param cls handle to the helper process * @param tc scheduler context */ static void helper_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_HELPER_Handle *h = cls; char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE] GNUNET_ALIGN; ssize_t t; h->read_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* try again */ h->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, h->fh_from_helper, &helper_read, h); return; } t = GNUNET_DISK_file_read (h->fh_from_helper, &buf, sizeof (buf)); if (t < 0) { /* On read-error, restart the helper */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Error reading from `%s': %s\n"), h->binary_name, STRERROR (errno)); if (NULL != h->exp_cb) { h->exp_cb (h->cb_cls); GNUNET_HELPER_stop (h, GNUNET_NO); return; } stop_helper (h, GNUNET_NO); /* Restart the helper */ h->restart_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &restart_task, h); return; } if (0 == t) { /* this happens if the helper is shut down via a signal, so it is not a "hard" error */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got 0 bytes from helper `%s' (EOF)\n", h->binary_name); if (NULL != h->exp_cb) { h->exp_cb (h->cb_cls); GNUNET_HELPER_stop (h, GNUNET_NO); return; } stop_helper (h, GNUNET_NO); /* Restart the helper */ h->restart_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &restart_task, h); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes from helper `%s'\n", (unsigned int) t, h->binary_name); h->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, h->fh_from_helper, &helper_read, h); if (GNUNET_SYSERR == GNUNET_SERVER_mst_receive (h->mst, NULL, buf, t, GNUNET_NO, GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to parse inbound message from helper `%s'\n"), h->binary_name); if (NULL != h->exp_cb) { h->exp_cb (h->cb_cls); GNUNET_HELPER_stop (h, GNUNET_NO); return; } stop_helper (h, GNUNET_NO); /* Restart the helper */ h->restart_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &restart_task, h); return; } } /** * Start the helper process. * * @param h handle to the helper process */ static void start_helper (struct GNUNET_HELPER_Handle *h) { h->helper_in = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); h->helper_out = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if ( (h->helper_in == NULL) || (h->helper_out == NULL)) { /* out of file descriptors? try again later... */ stop_helper (h, GNUNET_NO); h->restart_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &restart_task, h); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting HELPER process `%s'\n", h->binary_name); h->fh_from_helper = GNUNET_DISK_pipe_handle (h->helper_out, GNUNET_DISK_PIPE_END_READ); h->fh_to_helper = GNUNET_DISK_pipe_handle (h->helper_in, GNUNET_DISK_PIPE_END_WRITE); h->helper_proc = GNUNET_OS_start_process_vap (h->with_control_pipe, GNUNET_OS_INHERIT_STD_ERR, h->helper_in, h->helper_out, NULL, h->binary_name, h->binary_argv); if (NULL == h->helper_proc) { /* failed to start process? try again later... */ stop_helper (h, GNUNET_NO); h->restart_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &restart_task, h); return; } GNUNET_DISK_pipe_close_end (h->helper_out, GNUNET_DISK_PIPE_END_WRITE); GNUNET_DISK_pipe_close_end (h->helper_in, GNUNET_DISK_PIPE_END_READ); if (NULL != h->mst) h->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, h->fh_from_helper, &helper_read, h); } /** * Restart the helper process. * * @param cls handle to the helper process * @param tc scheduler context */ static void restart_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_HELPER_Handle*h = cls; h->restart_task = GNUNET_SCHEDULER_NO_TASK; start_helper (h); } /** * Starts a helper and begins reading from it. The helper process is * restarted when it dies except when it is stopped using GNUNET_HELPER_stop() * or when the exp_cb callback is not NULL. * * @param with_control_pipe does the helper support the use of a control pipe for signalling? * @param binary_name name of the binary to run * @param binary_argv NULL-terminated list of arguments to give when starting the binary (this * argument must not be modified by the client for * the lifetime of the helper handle) * @param cb function to call if we get messages from the helper * @param exp_cb the exception callback to call. Set this to NULL if the helper * process has to be restarted automatically when it dies/crashes * @param cb_cls closure for the above callback * @return the new Handle, NULL on error */ struct GNUNET_HELPER_Handle * GNUNET_HELPER_start (int with_control_pipe, const char *binary_name, char *const binary_argv[], GNUNET_SERVER_MessageTokenizerCallback cb, GNUNET_HELPER_ExceptionCallback exp_cb, void *cb_cls) { struct GNUNET_HELPER_Handle *h; unsigned int c; h = GNUNET_new (struct GNUNET_HELPER_Handle); h->with_control_pipe = with_control_pipe; /* Lookup in libexec path only if we are starting gnunet helpers */ if (NULL != strstr (binary_name, "gnunet")) h->binary_name = GNUNET_OS_get_libexec_binary_path (binary_name); else h->binary_name = strdup (binary_name); for (c = 0; NULL != binary_argv[c]; c++); h->binary_argv = GNUNET_malloc (sizeof (char *) * (c + 1)); for (c = 0; NULL != binary_argv[c]; c++) h->binary_argv[c] = GNUNET_strdup (binary_argv[c]); h->binary_argv[c] = NULL; h->cb_cls = cb_cls; if (NULL != cb) h->mst = GNUNET_SERVER_mst_create (cb, h->cb_cls); h->exp_cb = exp_cb; start_helper (h); return h; } /** * Free's the resources occupied by the helper handle * * @param h the helper handle to free */ void GNUNET_HELPER_destroy (struct GNUNET_HELPER_Handle *h) { unsigned int c; struct GNUNET_HELPER_SendHandle *sh; if (GNUNET_SCHEDULER_NO_TASK != h->write_task) { GNUNET_SCHEDULER_cancel (h->write_task); h->write_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->read_task); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->restart_task); while (NULL != (sh = h->sh_head)) { GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh); if (NULL != sh->cont) sh->cont (sh->cont_cls, GNUNET_SYSERR); GNUNET_free (sh); } if (NULL != h->mst) GNUNET_SERVER_mst_destroy (h->mst); GNUNET_free (h->binary_name); for (c = 0; h->binary_argv[c] != NULL; c++) GNUNET_free (h->binary_argv[c]); GNUNET_free (h->binary_argv); GNUNET_free (h); } /** * Kills the helper, closes the pipe and frees the handle * * @param h handle to helper to stop * @param soft_kill if #GNUNET_YES, signals termination by closing the helper's * stdin; #GNUNET_NO to signal termination by sending SIGTERM to helper */ void GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h, int soft_kill) { h->exp_cb = NULL; stop_helper (h, soft_kill); GNUNET_HELPER_destroy (h); } /** * Write to the helper-process * * @param cls handle to the helper process * @param tc scheduler context */ static void helper_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_HELPER_Handle *h = cls; struct GNUNET_HELPER_SendHandle *sh; const char *buf; ssize_t t; h->write_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* try again */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Helper write triggered during shutdown, retrying\n"); h->write_task = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, h->fh_to_helper, &helper_write, h); return; } if (NULL == (sh = h->sh_head)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Helper write had no work!\n"); return; /* how did this happen? */ } buf = (const char*) sh->msg; t = GNUNET_DISK_file_write (h->fh_to_helper, &buf[sh->wpos], ntohs (sh->msg->size) - sh->wpos); if (-1 == t) { /* On write-error, restart the helper */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Error writing to `%s': %s\n"), h->binary_name, STRERROR (errno)); if (NULL != h->exp_cb) { h->exp_cb (h->cb_cls); GNUNET_HELPER_stop (h, GNUNET_NO); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping and restarting helper task!\n"); stop_helper (h, GNUNET_NO); /* Restart the helper */ h->restart_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &restart_task, h); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %u bytes to %s\n", (unsigned int) t, h->binary_name); sh->wpos += t; if (sh->wpos == ntohs (sh->msg->size)) { GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh); if (NULL != sh->cont) sh->cont (sh->cont_cls, GNUNET_YES); GNUNET_free (sh); } if (NULL != h->sh_head) h->write_task = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, h->fh_to_helper, &helper_write, h); } /** * Send an message to the helper. * * @param h helper to send message to * @param msg message to send * @param can_drop can the message be dropped if there is already one in the queue? * @param cont continuation to run once the message is out (#GNUNET_OK on succees, #GNUNET_NO * if the helper process died, #GNUNET_SYSERR during #GNUNET_HELPER_destroy). * @param cont_cls closure for @a cont * @return NULL if the message was dropped, * otherwise handle to cancel *cont* (actual transmission may * not be abortable) */ struct GNUNET_HELPER_SendHandle * GNUNET_HELPER_send (struct GNUNET_HELPER_Handle *h, const struct GNUNET_MessageHeader *msg, int can_drop, GNUNET_HELPER_Continuation cont, void *cont_cls) { struct GNUNET_HELPER_SendHandle *sh; uint16_t mlen; if (NULL == h->fh_to_helper) return NULL; if ( (GNUNET_YES == can_drop) && (NULL != h->sh_head) ) return NULL; mlen = ntohs (msg->size); sh = GNUNET_malloc (sizeof (struct GNUNET_HELPER_SendHandle) + mlen); sh->msg = (const struct GNUNET_MessageHeader*) &sh[1]; memcpy (&sh[1], msg, mlen); sh->h = h; sh->cont = cont; sh->cont_cls = cont_cls; GNUNET_CONTAINER_DLL_insert_tail (h->sh_head, h->sh_tail, sh); if (GNUNET_SCHEDULER_NO_TASK == h->write_task) h->write_task = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, h->fh_to_helper, &helper_write, h); return sh; } /** * Cancel a #GNUNET_HELPER_send operation. If possible, transmitting the * message is also aborted, but at least 'cont' won't be * called. * * @param sh operation to cancel */ void GNUNET_HELPER_send_cancel (struct GNUNET_HELPER_SendHandle *sh) { struct GNUNET_HELPER_Handle *h = sh->h; sh->cont = NULL; sh->cont_cls = NULL; if (0 == sh->wpos) { GNUNET_CONTAINER_DLL_remove (h->sh_head, h->sh_tail, sh); GNUNET_free (sh); if (NULL == h->sh_head) { GNUNET_SCHEDULER_cancel (h->write_task); h->write_task = GNUNET_SCHEDULER_NO_TASK; } } } /* end of helper.c */ gnunet-0.10.1/src/util/bandwidth.c0000644000175000017500000003562512316473376013715 00000000000000/* This file is part of GNUnet. (C) 2010, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/bandwidth.c * @brief functions related to bandwidth (unit) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util-bandwidth", __VA_ARGS__) /** * Create a new bandwidth value. * * @param bytes_per_second value to create * @return the new bandwidth value */ struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_init (uint32_t bytes_per_second) { struct GNUNET_BANDWIDTH_Value32NBO ret; LOG (GNUNET_ERROR_TYPE_DEBUG, "Initializing bandwidth of %u Bps\n", (unsigned int) bytes_per_second); ret.value__ = htonl (bytes_per_second); return ret; } /** * Compute the MIN of two bandwidth values. * * @param b1 first value * @param b2 second value * @return the min of b1 and b2 */ struct GNUNET_BANDWIDTH_Value32NBO GNUNET_BANDWIDTH_value_min (struct GNUNET_BANDWIDTH_Value32NBO b1, struct GNUNET_BANDWIDTH_Value32NBO b2) { return GNUNET_BANDWIDTH_value_init (GNUNET_MIN (ntohl (b1.value__), ntohl (b2.value__))); } /** * At the given bandwidth, calculate how much traffic will be * available until the given deadline. * * @param bps bandwidth * @param deadline when is the deadline * @return number of bytes available at bps until deadline */ uint64_t GNUNET_BANDWIDTH_value_get_available_until (struct GNUNET_BANDWIDTH_Value32NBO bps, struct GNUNET_TIME_Relative deadline) { uint64_t b; b = ntohl (bps.value__); LOG (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth has %llu bytes available until deadline in %s\n", (unsigned long long) ((b * deadline.rel_value_us + 500000LL) / 1000000LL), GNUNET_STRINGS_relative_time_to_string (deadline, GNUNET_YES)); return (b * deadline.rel_value_us + 500000LL) / 1000000LL; } /** * At the given bandwidth, calculate how long it would take for * @a size bytes to be transmitted. * * @param bps bandwidth * @param size number of bytes we want to have available * @return how long it would take */ struct GNUNET_TIME_Relative GNUNET_BANDWIDTH_value_get_delay_for (struct GNUNET_BANDWIDTH_Value32NBO bps, uint64_t size) { uint64_t b; struct GNUNET_TIME_Relative ret; b = ntohl (bps.value__); if (0 == b) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth suggests delay of infinity (zero bandwidth)\n"); return GNUNET_TIME_UNIT_FOREVER_REL; } ret.rel_value_us = size * 1000LL * 1000LL / b; LOG (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth suggests delay of %s for %llu bytes of traffic\n", GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES), (unsigned long long) size); return ret; } /** * Task run whenever we hit the bandwidth limit for a tracker. * * @param cls the `struct GNUNET_BANDWIDTH_Tracker` * @param tc scheduler context */ static void excess_trigger (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_BANDWIDTH_Tracker *av = cls; av->excess_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != av->excess_cb) av->excess_cb (av->excess_cb_cls); } /** * Recalculate when we might need to call the excess callback. */ static void update_excess (struct GNUNET_BANDWIDTH_Tracker *av) { struct GNUNET_TIME_Relative delay; struct GNUNET_TIME_Absolute now; uint64_t delta_time; uint64_t delta_avail; int64_t left_bytes; uint64_t max_carry; int64_t current_consumption; if (NULL == av->excess_cb) return; /* nothing to do */ now = GNUNET_TIME_absolute_get (); delta_time = now.abs_value_us - av->last_update__.abs_value_us; delta_avail = (delta_time * ((unsigned long long) av->available_bytes_per_s__) + 500000LL) / 1000000LL; current_consumption = av->consumption_since_last_update__ - delta_avail; /* negative current_consumption means that we have savings */ max_carry = av->available_bytes_per_s__ * av->max_carry_s__; if (max_carry < GNUNET_SERVER_MAX_MESSAGE_SIZE) max_carry = GNUNET_SERVER_MAX_MESSAGE_SIZE; left_bytes = max_carry + current_consumption; /* left_bytes now contains the number of bytes needed until we have more savings than allowed */ if (left_bytes < 0) { /* having excess already */ delay = GNUNET_TIME_UNIT_ZERO; } else { delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, left_bytes); delay = GNUNET_TIME_relative_divide (delay, av->available_bytes_per_s__); } if (GNUNET_SCHEDULER_NO_TASK != av->excess_task) GNUNET_SCHEDULER_cancel (av->excess_task); av->excess_task = GNUNET_SCHEDULER_add_delayed (delay, &excess_trigger, av); } /** * Initialize bandwidth tracker. Note that in addition to the * 'max_carry_s' limit, we also always allow at least * #GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the * bytes-per-second limit is so small that within 'max_carry_s' not * even #GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is * ignored and replaced by #GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in * bytes). * * To stop notifications about updates and excess callbacks use * #GNUNET_BANDWIDTH_tracker_notification_stop * * @param av tracker to initialize * @param update_cb callback to notify a client about the tracker being updated * @param update_cb_cls cls for the callback * @param bytes_per_second_limit initial limit to assume * @param max_carry_s maximum number of seconds unused bandwidth * may accumulate before it expires * @param excess_cb callback to notify if we have excess bandwidth * @param excess_cb_cls closure for @a excess_cb */ void GNUNET_BANDWIDTH_tracker_init2 (struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s, GNUNET_BANDWIDTH_ExcessNotificationCallback excess_cb, void *excess_cb_cls) { av->update_cb = update_cb; av->update_cb_cls = update_cb_cls; av->consumption_since_last_update__ = 0; av->last_update__ = GNUNET_TIME_absolute_get (); av->available_bytes_per_s__ = ntohl (bytes_per_second_limit.value__); av->max_carry_s__ = max_carry_s; av->excess_cb = excess_cb; av->excess_cb_cls = excess_cb_cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p initialized with %u Bps and max carry %u\n", av, (unsigned int) av->available_bytes_per_s__, (unsigned int) max_carry_s); update_excess (av); } /** * Initialize bandwidth tracker. Note that in addition to the * 'max_carry_s' limit, we also always allow at least * GNUNET_SERVER_MAX_MESSAGE_SIZE to accumulate. So if the * bytes-per-second limit is so small that within 'max_carry_s' not * even GNUNET_SERVER_MAX_MESSAGE_SIZE is allowed to accumulate, it is * ignored and replaced by GNUNET_SERVER_MAX_MESSAGE_SIZE (which is in * bytes). * * @param av tracker to initialize * @param update_cb callback to notify a client about the tracker being updated * @param update_cb_cls cls for the callback * @param bytes_per_second_limit initial limit to assume * @param max_carry_s maximum number of seconds unused bandwidth * may accumulate before it expires */ void GNUNET_BANDWIDTH_tracker_init (struct GNUNET_BANDWIDTH_Tracker *av, GNUNET_BANDWIDTH_TrackerUpdateCallback update_cb, void *update_cb_cls, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit, uint32_t max_carry_s) { GNUNET_BANDWIDTH_tracker_init2 (av, update_cb, update_cb_cls, bytes_per_second_limit, max_carry_s, NULL, NULL); } /** * Stop notifying about tracker updates and excess notifications * * @param av the respective trackers */ void GNUNET_BANDWIDTH_tracker_notification_stop (struct GNUNET_BANDWIDTH_Tracker *av) { if (GNUNET_SCHEDULER_NO_TASK != av->excess_task) GNUNET_SCHEDULER_cancel (av->excess_task); av->excess_task = GNUNET_SCHEDULER_NO_TASK; av->excess_cb = NULL; av->excess_cb_cls = NULL; av->update_cb = NULL; av->update_cb_cls = NULL; } /** * Update the tracker, looking at the current time and * bandwidth consumption data. * * @param av tracker to update */ static void update_tracker (struct GNUNET_BANDWIDTH_Tracker *av) { struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Relative delta; uint64_t delta_time; uint64_t delta_avail; uint64_t left_bytes; uint64_t max_carry; now = GNUNET_TIME_absolute_get (); delta_time = now.abs_value_us - av->last_update__.abs_value_us; delta_avail = (delta_time * ((unsigned long long) av->available_bytes_per_s__) + 500000LL) / 1000000LL; av->consumption_since_last_update__ -= delta_avail; av->last_update__ = now; if (av->consumption_since_last_update__ < 0) { left_bytes = -av->consumption_since_last_update__; max_carry = av->available_bytes_per_s__ * av->max_carry_s__; if (max_carry < GNUNET_SERVER_MAX_MESSAGE_SIZE) max_carry = GNUNET_SERVER_MAX_MESSAGE_SIZE; if (max_carry > left_bytes) av->consumption_since_last_update__ = -left_bytes; else av->consumption_since_last_update__ = -max_carry; } delta.rel_value_us = delta_time; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p updated, have %u Bps, last update was %s ago\n", av, (unsigned int) av->available_bytes_per_s__, GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); } /** * Notify the tracker that a certain number of bytes of bandwidth have * been consumed. Note that it is legal to consume bytes even if not * enough bandwidth is available (in that case, * #GNUNET_BANDWIDTH_tracker_get_delay may return non-zero delay values * even for a size of zero for a while). * * @param av tracker to update * @param size number of bytes consumed * @return #GNUNET_YES if this consumption is above the limit */ int GNUNET_BANDWIDTH_tracker_consume (struct GNUNET_BANDWIDTH_Tracker *av, ssize_t size) { int64_t nc; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p consumes %d bytes\n", av, (int) size); if (size > 0) { nc = av->consumption_since_last_update__ + size; if (nc < av->consumption_since_last_update__) { GNUNET_break (0); return GNUNET_SYSERR; } av->consumption_since_last_update__ = nc; update_tracker (av); update_excess (av); if (av->consumption_since_last_update__ > 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p consumption %llu bytes above limit\n", av, (unsigned long long) av->consumption_since_last_update__); return GNUNET_YES; } } else { av->consumption_since_last_update__ += size; update_excess (av); } return GNUNET_NO; } /** * Compute how long we should wait until consuming 'size' * bytes of bandwidth in order to stay within the given * quota. * * @param av tracker to query * @param size number of bytes we would like to consume * @return time in ms to wait for consumption to be OK */ struct GNUNET_TIME_Relative GNUNET_BANDWIDTH_tracker_get_delay (struct GNUNET_BANDWIDTH_Tracker *av, size_t size) { struct GNUNET_TIME_Relative ret; int64_t bytes_needed; if (0 == av->available_bytes_per_s__) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p delay is infinity\n", av); return GNUNET_TIME_UNIT_FOREVER_REL; } update_tracker (av); bytes_needed = size + av->consumption_since_last_update__; if (bytes_needed <= 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p delay for %u bytes is zero\n", av, (unsigned int) size); return GNUNET_TIME_UNIT_ZERO; } ret.rel_value_us = (1000LL * 1000LL * bytes_needed) / (unsigned long long) av->available_bytes_per_s__; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p delay for %u bytes is %s\n", av, (unsigned int) size, GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); return ret; } /** * Compute how many bytes are available for consumption right now. * quota. * * @param av tracker to query * @return number of bytes available for consumption right now */ int64_t GNUNET_BANDWIDTH_tracker_get_available (struct GNUNET_BANDWIDTH_Tracker *av) { struct GNUNET_BANDWIDTH_Value32NBO bps; uint64_t avail; int64_t used; update_tracker (av); bps = GNUNET_BANDWIDTH_value_init (av->available_bytes_per_s__); avail = GNUNET_BANDWIDTH_value_get_available_until (bps, GNUNET_TIME_absolute_get_duration (av->last_update__)); used = av->consumption_since_last_update__; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p available bandwidth is %lld bytes\n", av, (long long) (int64_t) (avail - used)); return (int64_t) (avail - used); } /** * Update quota of bandwidth tracker. * * @param av tracker to initialize * @param bytes_per_second_limit new limit to assume */ void GNUNET_BANDWIDTH_tracker_update_quota (struct GNUNET_BANDWIDTH_Tracker *av, struct GNUNET_BANDWIDTH_Value32NBO bytes_per_second_limit) { uint32_t old_limit; uint32_t new_limit; new_limit = ntohl (bytes_per_second_limit.value__); LOG (GNUNET_ERROR_TYPE_DEBUG, "Tracker %p bandwidth changed to %u Bps\n", av, (unsigned int) new_limit); update_tracker (av); old_limit = av->available_bytes_per_s__; av->available_bytes_per_s__ = new_limit; if (NULL != av->update_cb) av->update_cb (av->update_cb_cls); if (old_limit > new_limit) update_tracker (av); /* maximum excess might be less now */ update_excess (av); } /* end of bandwidth.c */ gnunet-0.10.1/src/util/test_server_with_client_unix.c0000644000175000017500000001145012225777501017734 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_server_with_client_unix.c * @brief tests for server.c and client.c, * specifically disconnect_notify, * client_get_address and receive_done (resume processing) */ #include "platform.h" #include "gnunet_util_lib.h" #define MY_TYPE 128 static struct GNUNET_SERVER_Handle *server; static struct GNUNET_CLIENT_Connection *client; static struct GNUNET_CONFIGURATION_Handle *cfg; static int ok; static void send_done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVER_Client *argclient = cls; GNUNET_assert (ok == 3); ok++; GNUNET_SERVER_receive_done (argclient, GNUNET_OK); } static void recv_cb (void *cls, struct GNUNET_SERVER_Client *argclient, const struct GNUNET_MessageHeader *message) { switch (ok) { case 2: ok++; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 50), &send_done, argclient); break; case 4: ok++; GNUNET_CLIENT_disconnect (client); GNUNET_SERVER_receive_done (argclient, GNUNET_OK); break; default: GNUNET_assert (0); } } static void clean_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SERVER_destroy (server); server = NULL; GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; } /** * Functions with this signature are called whenever a client * is disconnected on the network level. * * @param cls closure * @param client identification of the client */ static void notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { if (client == NULL) return; GNUNET_assert (ok == 5); ok = 0; GNUNET_SCHEDULER_add_now (&clean_up, NULL); } static size_t notify_ready (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg; GNUNET_assert (size >= 256); GNUNET_assert (1 == ok); ok++; msg = buf; msg->type = htons (MY_TYPE); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); msg++; msg->type = htons (MY_TYPE); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); return 2 * sizeof (struct GNUNET_MessageHeader); } static struct GNUNET_SERVER_MessageHandler handlers[] = { {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_un un; const char *unixpath = "/tmp/testsock"; struct sockaddr *sap[2]; socklen_t slens[2]; memset (&un, 0, sizeof (un)); un.sun_family = AF_UNIX; strncpy(un.sun_path, unixpath, sizeof (un.sun_path) - 1); #if HAVE_SOCKADDR_IN_SIN_LEN un.sun_len = (u_char) sizeof (un); #endif sap[0] = (struct sockaddr *) &un; slens[0] = sizeof (un); sap[1] = NULL; slens[1] = 0; server = GNUNET_SERVER_create (NULL, NULL, sap, slens, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_NO); GNUNET_assert (server != NULL); handlers[0].callback_cls = cls; GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, ¬ify_disconnect, cls); cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "test", "UNIXPATH", unixpath); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); client = GNUNET_CLIENT_connect ("test", cfg); GNUNET_assert (client != NULL); GNUNET_CLIENT_notify_transmit_ready (client, 256, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_NO, ¬ify_ready, NULL); } int main (int argc, char *argv[]) { GNUNET_log_setup ("test_server_with_client_unix", "WARNING", NULL); ok = 1; GNUNET_SCHEDULER_run (&task, NULL); return ok; } /* end of test_server_with_client_unix.c */ gnunet-0.10.1/src/util/crypto_random.c0000644000175000017500000001715512305616352014616 00000000000000/* This file is part of GNUnet. (C) 2001-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/crypto_random.c * @brief functions to gather random numbers * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) /* TODO: ndurner, move this to plibc? */ /* The code is derived from glibc, obviously */ #if !HAVE_RANDOM || !HAVE_SRANDOM #ifdef RANDOM #undef RANDOM #endif #ifdef SRANDOM #undef SRANDOM #endif #define RANDOM() glibc_weak_rand32() #define SRANDOM(s) glibc_weak_srand32(s) #if defined(RAND_MAX) #undef RAND_MAX #endif #define RAND_MAX 0x7fffffff /* Hopefully this is correct */ static int32_t glibc_weak_rand32_state = 1; void glibc_weak_srand32 (int32_t s) { glibc_weak_rand32_state = s; } int32_t glibc_weak_rand32 () { int32_t val = glibc_weak_rand32_state; val = ((glibc_weak_rand32_state * 1103515245) + 12345) & 0x7fffffff; glibc_weak_rand32_state = val; return val; } #endif /** * Create a cryptographically weak pseudo-random number in the interval of 0 to 1. * * @return number between 0 and 1. */ static double get_weak_random () { return ((double) RANDOM () / RAND_MAX); } /** * Seed a weak random generator. Only #GNUNET_CRYPTO_QUALITY_WEAK-mode generator * can be seeded. * * @param seed the seed to use */ void GNUNET_CRYPTO_seed_weak_random (int32_t seed) { SRANDOM (seed); } /** * @ingroup crypto * Fill block with a random values. * * @param mode desired quality of the random number * @param buffer the buffer to fill * @param length buffer length */ void GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length) { #ifdef gcry_fast_random_poll static unsigned int invokeCount; #endif switch (mode) { case GNUNET_CRYPTO_QUALITY_STRONG: /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ #ifdef gcry_fast_random_poll if ((invokeCount++ % 256) == 0) gcry_fast_random_poll (); #endif gcry_randomize (buffer, length, GCRY_STRONG_RANDOM); return; case GNUNET_CRYPTO_QUALITY_NONCE: gcry_create_nonce (buffer, length); return; case GNUNET_CRYPTO_QUALITY_WEAK: /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ #ifdef gcry_fast_random_poll if ((invokeCount++ % 256) == 0) gcry_fast_random_poll (); #endif gcry_randomize (buffer, length, GCRY_WEAK_RANDOM); return; default: GNUNET_assert (0); } } /** * Produce a random unsigned 32-bit number modulo @a i. * * @param mode desired quality of the random number * @param i the upper limit (exclusive) for the random number * @return a random value in the interval [0,i[. */ uint32_t GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i) { #ifdef gcry_fast_random_poll static unsigned int invokeCount; #endif uint32_t ret; uint32_t ul; GNUNET_assert (i > 0); switch (mode) { case GNUNET_CRYPTO_QUALITY_STRONG: /* see http://lists.gnupg.org/pipermail/gcrypt-devel/2004-May/000613.html */ #ifdef gcry_fast_random_poll if ((invokeCount++ % 256) == 0) gcry_fast_random_poll (); #endif ul = UINT32_MAX - (UINT32_MAX % i); do { gcry_randomize ((unsigned char *) &ret, sizeof (uint32_t), GCRY_STRONG_RANDOM); } while (ret >= ul); return ret % i; case GNUNET_CRYPTO_QUALITY_NONCE: ul = UINT32_MAX - (UINT32_MAX % i); do { gcry_create_nonce (&ret, sizeof (ret)); } while (ret >= ul); return ret % i; case GNUNET_CRYPTO_QUALITY_WEAK: ret = i * get_weak_random (); if (ret >= i) ret = i - 1; return ret; default: GNUNET_assert (0); } return 0; } /** * Get an array with a random permutation of the * numbers 0...n-1. * @param mode #GNUNET_RANDOM_QUALITY_STRONG if the strong (but expensive) * PRNG should be used, #GNUNET_RANDOM_QUALITY_WEAK otherwise * @param n the size of the array * @return the permutation array (allocated from heap) */ unsigned int * GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, unsigned int n) { unsigned int *ret; unsigned int i; unsigned int tmp; uint32_t x; GNUNET_assert (n > 0); ret = GNUNET_malloc (n * sizeof (unsigned int)); for (i = 0; i < n; i++) ret[i] = i; for (i = n - 1; i > 0; i--) { x = GNUNET_CRYPTO_random_u32 (mode, i + 1); tmp = ret[x]; ret[x] = ret[i]; ret[i] = tmp; } return ret; } /** * Generate random unsigned 64-bit value. * * @param mode desired quality of the random number * @param max value returned will be in range [0,max) (exclusive) * @return random 64-bit number */ uint64_t GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) { uint64_t ret; uint64_t ul; GNUNET_assert (max > 0); switch (mode) { case GNUNET_CRYPTO_QUALITY_STRONG: ul = UINT64_MAX - (UINT64_MAX % max); do { gcry_randomize ((unsigned char *) &ret, sizeof (uint64_t), GCRY_STRONG_RANDOM); } while (ret >= ul); return ret % max; case GNUNET_CRYPTO_QUALITY_NONCE: ul = UINT64_MAX - (UINT64_MAX % max); do { gcry_create_nonce (&ret, sizeof (ret)); } while (ret >= ul); return ret % max; case GNUNET_CRYPTO_QUALITY_WEAK: ret = max * get_weak_random (); if (ret >= max) ret = max - 1; return ret; default: GNUNET_assert (0); } return 0; } /** * Initialize libgcrypt. */ void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init () { gcry_error_t rc; if (! gcry_check_version (NEED_LIBGCRYPT_VERSION)) { FPRINTF (stderr, _("libgcrypt has not the expected version (version %s is required).\n"), NEED_LIBGCRYPT_VERSION); GNUNET_abort (); } if ((rc = gcry_control (GCRYCTL_DISABLE_SECMEM, 0))) FPRINTF (stderr, "Failed to set libgcrypt option %s: %s\n", "DISABLE_SECMEM", gcry_strerror (rc)); /* Otherwise gnunet-ecc takes forever to complete, besides we are fine with "just" using GCRY_STRONG_RANDOM */ if ((rc = gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0))) FPRINTF (stderr, "Failed to set libgcrypt option %s: %s\n", "ENABLE_QUICK_RANDOM", gcry_strerror (rc)); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); gcry_fast_random_poll (); GNUNET_CRYPTO_seed_weak_random (time (NULL) ^ GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); } /** * Nicely shut down libgcrypt. */ void __attribute__ ((destructor)) GNUNET_CRYPTO_random_fini () { gcry_set_progress_handler (NULL, NULL); #ifdef GCRYCTL_CLOSE_RANDOM_DEVICE (void) gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0); #endif } /* end of crypto_random.c */ gnunet-0.10.1/src/util/time.c0000644000175000017500000003607112241142576012673 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/time.c * @author Christian Grothoff * @brief functions for handling time and time arithmetic */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Variable used to simulate clock skew. Used for testing, never in production. */ static long long timestamp_offset; /** * Set the timestamp offset for this instance. * * @param offset the offset to skew the locale time by */ void GNUNET_TIME_set_offset (long long offset) { timestamp_offset = offset; } /** * Get the timestamp offset for this instance. * * @return the offset we currently skew the locale time by */ long long GNUNET_TIME_get_offset () { return timestamp_offset; } /** * Get the current time (works just as "time", just that we use the * unit of time that the cron-jobs use (and is 64 bit)). * * @return the current time */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get () { struct GNUNET_TIME_Absolute ret; struct timeval tv; GETTIMEOFDAY (&tv, NULL); ret.abs_value_us = (uint64_t) (((uint64_t) tv.tv_sec * 1000LL * 1000LL) + ((uint64_t) tv.tv_usec)) + timestamp_offset; return ret; } /** * Return relative time of 0ms. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_zero_ () { static struct GNUNET_TIME_Relative zero; return zero; } /** * Return absolute time of 0ms. */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_zero_ () { static struct GNUNET_TIME_Absolute zero; return zero; } /** * Return relative time of 1us. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_unit_ () { static struct GNUNET_TIME_Relative one = { 1 }; return one; } /** * Return relative time of 1ms. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_millisecond_ () { static struct GNUNET_TIME_Relative one = { 1000 }; return one; } /** * Return relative time of 1s. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_second_ () { static struct GNUNET_TIME_Relative one = { 1000 * 1000LL }; return one; } /** * Return relative time of 1 minute. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_minute_ () { static struct GNUNET_TIME_Relative one = { 60 * 1000 * 1000LL }; return one; } /** * Return relative time of 1 hour. */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_hour_ () { static struct GNUNET_TIME_Relative one = { 60 * 60 * 1000 * 1000LL }; return one; } /** * Return "forever". */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_forever_ () { static struct GNUNET_TIME_Relative forever = { UINT64_MAX }; return forever; } /** * Return "forever". */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_forever_ () { static struct GNUNET_TIME_Absolute forever = { UINT64_MAX }; return forever; } /** * Convert relative time to an absolute time in the * future. * * @return timestamp that is "rel" in the future, or FOREVER if rel==FOREVER (or if we would overflow) */ struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel) { struct GNUNET_TIME_Absolute ret; if (rel.rel_value_us == UINT64_MAX) return GNUNET_TIME_UNIT_FOREVER_ABS; struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); if (rel.rel_value_us + now.abs_value_us < rel.rel_value_us) { GNUNET_break (0); /* overflow... */ return GNUNET_TIME_UNIT_FOREVER_ABS; } ret.abs_value_us = rel.rel_value_us + now.abs_value_us; return ret; } /** * Return the minimum of two relative time values. * * @param t1 first timestamp * @param t2 other timestamp * @return timestamp that is smaller */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2) { return (t1.rel_value_us < t2.rel_value_us) ? t1 : t2; } /** * Return the maximum of two relative time values. * * @param t1 first timestamp * @param t2 other timestamp * @return timestamp that is larger */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2) { return (t1.rel_value_us > t2.rel_value_us) ? t1 : t2; } /** * Return the minimum of two relative time values. * * @param t1 first timestamp * @param t2 other timestamp * @return timestamp that is smaller */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2) { return (t1.abs_value_us < t2.abs_value_us) ? t1 : t2; } /** * Return the maximum of two relative time values. * * @param t1 first timestamp * @param t2 other timestamp * @return timestamp that is bigger */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2) { return (t1.abs_value_us > t2.abs_value_us) ? t1 : t2; } /** * Given a timestamp in the future, how much time * remains until then? * * @return future - now, or 0 if now >= future, or FOREVER if future==FOREVER. */ struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future) { struct GNUNET_TIME_Relative ret; if (future.abs_value_us == UINT64_MAX) return GNUNET_TIME_UNIT_FOREVER_REL; struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); if (now.abs_value_us > future.abs_value_us) return GNUNET_TIME_UNIT_ZERO; ret.rel_value_us = future.abs_value_us - now.abs_value_us; return ret; } /** * Compute the time difference between the given start and end times. * Use this function instead of actual subtraction to ensure that * "FOREVER" and overflows are handled correctly. * * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start */ struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end) { struct GNUNET_TIME_Relative ret; if (end.abs_value_us == UINT64_MAX) return GNUNET_TIME_UNIT_FOREVER_REL; if (end.abs_value_us < start.abs_value_us) return GNUNET_TIME_UNIT_ZERO; ret.rel_value_us = end.abs_value_us - start.abs_value_us; return ret; } /** * Get the duration of an operation as the * difference of the current time and the given start time "whence". * * @return aborts if whence==FOREVER, 0 if whence > now, otherwise now-whence. */ struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence) { struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Relative ret; now = GNUNET_TIME_absolute_get (); GNUNET_assert (whence.abs_value_us != UINT64_MAX); if (whence.abs_value_us > now.abs_value_us) return GNUNET_TIME_UNIT_ZERO; ret.rel_value_us = now.abs_value_us - whence.abs_value_us; return ret; } /** * Add a given relative duration to the * given start time. * * @return FOREVER if either argument is FOREVER or on overflow; start+duration otherwise */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration) { struct GNUNET_TIME_Absolute ret; if ((start.abs_value_us == UINT64_MAX) || (duration.rel_value_us == UINT64_MAX)) return GNUNET_TIME_UNIT_FOREVER_ABS; if (start.abs_value_us + duration.rel_value_us < start.abs_value_us) { GNUNET_break (0); return GNUNET_TIME_UNIT_FOREVER_ABS; } ret.abs_value_us = start.abs_value_us + duration.rel_value_us; return ret; } /** * Subtract a given relative duration from the * given start time. * * @param start some absolute time * @param duration some relative time to subtract * @return ZERO if start <= duration, or FOREVER if start time is FOREVER; start-duration otherwise */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration) { struct GNUNET_TIME_Absolute ret; if (start.abs_value_us <= duration.rel_value_us) return GNUNET_TIME_UNIT_ZERO_ABS; if (start.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) return GNUNET_TIME_UNIT_FOREVER_ABS; ret.abs_value_us = start.abs_value_us - duration.rel_value_us; return ret; } /** * Multiply relative time by a given factor. * * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel, unsigned int factor) { struct GNUNET_TIME_Relative ret; if (0 == factor) return GNUNET_TIME_UNIT_ZERO; if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) return GNUNET_TIME_UNIT_FOREVER_REL; ret.rel_value_us = rel.rel_value_us * (unsigned long long) factor; if (ret.rel_value_us / factor != rel.rel_value_us) { GNUNET_break (0); return GNUNET_TIME_UNIT_FOREVER_REL; } return ret; } /** * Divide relative time by a given factor. * * @param rel some duration * @param factor integer to divide by * @return FOREVER if rel=FOREVER or factor==0; otherwise rel/factor */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel, unsigned int factor) { struct GNUNET_TIME_Relative ret; if ((0 == factor) || (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)) return GNUNET_TIME_UNIT_FOREVER_REL; ret.rel_value_us = rel.rel_value_us / (unsigned long long) factor; return ret; } /** * Calculate the estimate time of arrival/completion * for an operation. * * @param start when did the operation start? * @param finished how much has been done? * @param total how much must be done overall (same unit as for "finished") * @return remaining duration for the operation, * assuming it continues at the same speed */ struct GNUNET_TIME_Relative GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, uint64_t finished, uint64_t total) { struct GNUNET_TIME_Relative dur; double exp; struct GNUNET_TIME_Relative ret; GNUNET_break (finished <= total); if (finished >= total) return GNUNET_TIME_UNIT_ZERO; if (0 == finished) return GNUNET_TIME_UNIT_FOREVER_REL; dur = GNUNET_TIME_absolute_get_duration (start); exp = ((double) dur.rel_value_us) * ((double) total) / ((double) finished); ret.rel_value_us = ((uint64_t) exp) - dur.rel_value_us; return ret; } /** * Add relative times together. * * @param a1 first timestamp * @param a2 second timestamp * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2) { struct GNUNET_TIME_Relative ret; if ((a1.rel_value_us == UINT64_MAX) || (a2.rel_value_us == UINT64_MAX)) return GNUNET_TIME_UNIT_FOREVER_REL; if (a1.rel_value_us + a2.rel_value_us < a1.rel_value_us) { GNUNET_break (0); return GNUNET_TIME_UNIT_FOREVER_REL; } ret.rel_value_us = a1.rel_value_us + a2.rel_value_us; return ret; } /** * Subtract relative timestamp from the other. * * @param a1 first timestamp * @param a2 second timestamp * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2) { struct GNUNET_TIME_Relative ret; if (a2.rel_value_us >= a1.rel_value_us) return GNUNET_TIME_UNIT_ZERO; if (a1.rel_value_us == UINT64_MAX) return GNUNET_TIME_UNIT_FOREVER_REL; ret.rel_value_us = a1.rel_value_us - a2.rel_value_us; return ret; } /** * Convert relative time to network byte order. * * @param a time to convert * @return time in network byte order */ struct GNUNET_TIME_RelativeNBO GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) { struct GNUNET_TIME_RelativeNBO ret; ret.rel_value_us__ = GNUNET_htonll (a.rel_value_us); return ret; } /** * Convert relative time from network byte order. * * @param a time to convert * @return time in host byte order */ struct GNUNET_TIME_Relative GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) { struct GNUNET_TIME_Relative ret; ret.rel_value_us = GNUNET_ntohll (a.rel_value_us__); return ret; } /** * Convert absolute time to network byte order. * * @param a time to convert * @return time in network byte order */ struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) { struct GNUNET_TIME_AbsoluteNBO ret; ret.abs_value_us__ = GNUNET_htonll (a.abs_value_us); return ret; } /** * Convert absolute time from network byte order. * * @param a time to convert * @return time in host byte order */ struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) { struct GNUNET_TIME_Absolute ret; ret.abs_value_us = GNUNET_ntohll (a.abs_value_us__); return ret; } /** * Return the current year (i.e. '2011'). */ unsigned int GNUNET_TIME_get_current_year () { time_t tp; struct tm *t; tp = time (NULL); t = gmtime (&tp); if (t == NULL) return 0; return t->tm_year + 1900; } /** * Convert an expiration time to the respective year (rounds) * * @param at absolute time * @return year a year (after 1970), 0 on error */ unsigned int GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at) { struct tm *t; time_t tp; tp = at.abs_value_us / 1000LL / 1000LL; /* microseconds to seconds */ t = gmtime (&tp); if (t == NULL) return 0; return t->tm_year + 1900; } /** * Convert a year to an expiration time of January 1st of that year. * * @param year a year (after 1970, please ;-)). * @return absolute time for January 1st of that year. */ struct GNUNET_TIME_Absolute GNUNET_TIME_year_to_time (unsigned int year) { struct GNUNET_TIME_Absolute ret; time_t tp; struct tm t; memset (&t, 0, sizeof (t)); if (year < 1900) { GNUNET_break (0); return GNUNET_TIME_absolute_get (); /* now */ } t.tm_year = year - 1900; t.tm_mday = 1; t.tm_mon = 1; t.tm_wday = 1; t.tm_yday = 1; tp = mktime (&t); GNUNET_break (tp != (time_t) - 1); ret.abs_value_us = tp * 1000LL * 1000LL; /* seconds to microseconds */ return ret; } /* end of time.c */ gnunet-0.10.1/src/util/common_endian.c0000644000175000017500000000422312225777501014541 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2006, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/common_endian.c * @brief endian conversion helpers * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__) uint64_t GNUNET_ntohll (uint64_t n) { #if __BYTE_ORDER == __BIG_ENDIAN return n; #elif __BYTE_ORDER == __LITTLE_ENDIAN return (((uint64_t) ntohl (n)) << 32) + ntohl (n >> 32); #else #error byteorder undefined #endif } uint64_t GNUNET_htonll (uint64_t n) { #if __BYTE_ORDER == __BIG_ENDIAN return n; #elif __BYTE_ORDER == __LITTLE_ENDIAN return (((uint64_t) htonl (n)) << 32) + htonl (n >> 32); #else #error byteorder undefined #endif } /** * Convert double to network-byte-order. * @param d the value in network byte order * @return the same value in host byte order */ double GNUNET_hton_double (double d) { double res; uint64_t *in = (uint64_t *) &d; uint64_t *out = (uint64_t *) &res; out[0] = GNUNET_htonll(in[0]); return res; } /** * Convert double to host-byte-order * @param d the value in network byte order * @return the same value in host byte order */ double GNUNET_ntoh_double (double d) { double res; uint64_t *in = (uint64_t *) &d; uint64_t *out = (uint64_t *) &res; out[0] = GNUNET_ntohll(in[0]); return res; } /* end of common_endian.c */ gnunet-0.10.1/src/util/test_resolver_api.c0000644000175000017500000002545212301361473015463 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file resolver/test_resolver_api.c * @brief testcase for resolver_api.c */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #include "resolver.h" /** * Using DNS root servers to check gnunet's resolver service * a.root-servers.net <-> 198.41.0.4 is a fix 1:1 mapping that should not change over years * For more information have a look at IANA's website http://www.root-servers.org/ */ #define ROOTSERVER_NAME "a.root-servers.net" #define ROOTSERVER_IP "198.41.0.4" static void check_hostname (void *cls, const struct sockaddr *sa, socklen_t salen) { int *ok = cls; if (0 == salen) { (*ok) &= ~8; return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Got IP address `%s' for our host.\n"), GNUNET_a2s (sa, salen)); } static void check_localhost_num (void *cls, const char *hostname) { int *ok = cls; if (hostname == NULL) return; if (0 == strcmp (hostname, "127.0.0.1")) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct hostname `%s'.\n", hostname); (*ok) &= ~4; } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid hostname `%s'.\n", hostname); GNUNET_break (0); } } static void check_localhost (void *cls, const char *hostname) { int *ok = cls; if (NULL == hostname) return; if (0 == strcmp (hostname, "localhost")) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct hostname `%s'.\n", hostname); (*ok) &= ~2; } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received unexpected hostname `%s', expected `localhost' (this could be OK).\n", hostname); } } static void check_127 (void *cls, const struct sockaddr *sa, socklen_t salen) { int *ok = cls; const struct sockaddr_in *sai = (const struct sockaddr_in *) sa; if (NULL == sa) return; GNUNET_assert (sizeof (struct sockaddr_in) == salen); if (sai->sin_addr.s_addr == htonl (INADDR_LOOPBACK)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct address.\n"); (*ok) &= ~1; } else { char buf[INET_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received incorrect address`%s'.\n", inet_ntop (AF_INET, &sai->sin_addr, buf, sizeof (buf))); GNUNET_break (0); } } static void check_local_fqdn (void *cls, const char *gnunet_fqdn) { int result = 0; struct hostent *host; char hostname[GNUNET_OS_get_hostname_max_length () + 1]; if (0 != gethostname (hostname, sizeof (hostname) - 1)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "gethostname"); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Resolving our FQDN `%s'\n"), hostname); host = gethostbyname (hostname); if (NULL == host) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not resolve our FQDN: %s %u\n"), hstrerror (h_errno), h_errno); return; } GNUNET_assert (0 != host); result = strcmp (host->h_name, gnunet_fqdn); if (0 != result) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Local resolved and resolver resolved fqdns are not equal\n"); } GNUNET_assert (0 == result); } static void check_rootserver_ip (void *cls, const struct sockaddr *sa, socklen_t salen) { int *ok = cls; const struct sockaddr_in *sai = (const struct sockaddr_in *) sa; if (NULL == sa) return; GNUNET_assert (sizeof (struct sockaddr_in) == salen); if (0 == strcmp (inet_ntoa (sai->sin_addr), ROOTSERVER_IP)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct rootserver ip address.\n"); (*ok) &= ~1; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received incorrect rootserver ip address.\n"); GNUNET_break (0); } } static void check_rootserver_name (void *cls, const char *hostname) { int *ok = cls; if (NULL == hostname) return; if (0 == strcmp (hostname, ROOTSERVER_NAME)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received correct rootserver hostname `%s'.\n", hostname); (*ok) &= ~2; } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid rootserver hostname `%s', expected `%s'\n", hostname, ROOTSERVER_NAME); GNUNET_break (0); } } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { int *ok = cls; struct sockaddr_in sa; struct GNUNET_TIME_Relative timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); int count_ips = 0; char *own_fqdn; memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = (u_char) sizeof (sa); #endif sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK); /* * Looking up our own fqdn */ own_fqdn = GNUNET_RESOLVER_local_fqdn_get (); check_local_fqdn (NULL, own_fqdn); GNUNET_free_non_null (own_fqdn); /* * Testing non-local DNS resolution * DNS rootserver to test: a.root-servers.net - 198.41.0.4 */ const char *rootserver_name = ROOTSERVER_NAME; struct hostent *rootserver; rootserver = gethostbyname (rootserver_name); if (rootserver == NULL) { /* Error: resolving ip addresses does not work */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("gethostbyname() could not lookup IP address: %s\n"), hstrerror (h_errno)); FPRINTF (stderr, "%s", "System seems to be off-line, will not run all DNS tests\n"); *ok = 0; /* mark test as passing anyway */ return; } /* Counting returned IP addresses */ while (rootserver->h_addr_list[count_ips] != NULL) count_ips++; if (count_ips > 1) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "IP received range for root name server, but a root name server has only 1 IP\n"); GNUNET_break (0); } /* Comparing to resolved address to the address the root name server should have */ if (strcmp (inet_ntoa (*(struct in_addr *) rootserver->h_addr_list[0]), ROOTSERVER_IP) != 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "IP received and IP for root name server differ\n"); GNUNET_break (0); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "System's own forward name resolution is working\n"); /* Resolve the same using GNUNET */ GNUNET_RESOLVER_ip_get (ROOTSERVER_NAME, AF_INET, timeout, &check_rootserver_ip, cls); /* * Success: forward lookups work as expected * Next step: reverse lookups */ struct in_addr rootserver_addr; rootserver->h_name = ""; if (1 != inet_pton (AF_INET, ROOTSERVER_IP, &rootserver_addr)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not transform root name server IP address\n"); GNUNET_break (0); } rootserver = gethostbyaddr (&rootserver_addr, sizeof (rootserver_addr), AF_INET); if (NULL == rootserver) { /* Error: resolving IP addresses does not work */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "gethostbyaddr() could not lookup hostname: %s\n", hstrerror (h_errno)); GNUNET_break (0); } else { if (0 != strcmp (rootserver->h_name, ROOTSERVER_NAME)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received hostname and hostname for root name server differ\n"); GNUNET_break (0); } } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "System's own reverse name resolution is working\n"); /* Resolve the same using GNUNET */ memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = (u_char) sizeof (sa); #endif #ifndef MINGW inet_aton (ROOTSERVER_IP, &sa.sin_addr); #else sa.sin_addr.S_un.S_addr = inet_addr (ROOTSERVER_IP); #endif GNUNET_RESOLVER_hostname_get ((const struct sockaddr *) &sa, sizeof (struct sockaddr), GNUNET_YES, timeout, &check_rootserver_name, cls); memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = (u_char) sizeof (sa); #endif sa.sin_addr.s_addr = htonl (INADDR_LOOPBACK); GNUNET_RESOLVER_ip_get ("localhost", AF_INET, timeout, &check_127, cls); GNUNET_RESOLVER_hostname_get ((const struct sockaddr *) &sa, sizeof (struct sockaddr), GNUNET_YES, timeout, &check_localhost, cls); GNUNET_RESOLVER_hostname_get ((const struct sockaddr *) &sa, sizeof (struct sockaddr), GNUNET_NO, timeout, &check_localhost_num, cls); GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, timeout, &check_hostname, cls); } int main (int argc, char *argv[]) { int ok = 1 + 2 + 4 + 8; char *fn; struct GNUNET_OS_Process *proc; char *const argvx[] = { "test-resolver-api", "-c", "test_resolver_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_log_setup ("test-resolver-api", "WARNING", NULL); fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver"); proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, fn, "gnunet-service-resolver", "-c", "test_resolver_api_data.conf", NULL); GNUNET_assert (NULL != proc); GNUNET_free (fn); GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-resolver-api", "nohelp", options, &run, &ok)); if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); ok = 1; } GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = NULL; if (0 != ok) FPRINTF (stderr, "Missed some resolutions: %u\n", ok); return ok; } /* end of test_resolver_api.c */ gnunet-0.10.1/src/util/speedup.h0000644000175000017500000000255612307557412013412 00000000000000/* This file is part of GNUnet. (C) 2009 -- 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/speedup.c * @brief Interface for speedup routinues * @author Sree Harsha Totakura */ #ifndef SPEEDUP_H_ #define SPEEDUP_H_ /** * Start task that may speed up our system clock artificially * * @param cfg configuration to use * @return GNUNET_OK on success, GNUNET_SYSERR if the speedup was not configured */ int GNUNET_SPEEDUP_start_ (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Stop tasks that modify clock behavior. */ void GNUNET_SPEEDUP_stop_ (void); #endif /* SPEEDUP_H_ */ gnunet-0.10.1/src/util/server_tc.c0000644000175000017500000001530512255010512013713 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/server_tc.c * @brief convenience functions for transmission of * complex responses as a server * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * How much buffer space do we want to have at least * before transmitting another increment? */ #define MIN_BLOCK_SIZE 128 struct GNUNET_SERVER_TransmitContext { /** * Which client are we transmitting to? */ struct GNUNET_SERVER_Client *client; /** * Transmission buffer. (current offset for writing). */ char *buf; /** * Number of bytes in buf. */ size_t total; /** * Offset for writing in buf. */ size_t off; /** * Timeout for this request. */ struct GNUNET_TIME_Absolute timeout; }; /** * Helper function for incremental transmission of the response. */ static size_t transmit_response (void *cls, size_t size, void *buf) { struct GNUNET_SERVER_TransmitContext *tc = cls; size_t msize; if (NULL == buf) { GNUNET_SERVER_transmit_context_destroy (tc, GNUNET_SYSERR); return 0; } if (tc->total - tc->off > size) msize = size; else msize = tc->total - tc->off; memcpy (buf, &tc->buf[tc->off], msize); tc->off += msize; if (tc->total == tc->off) { GNUNET_SERVER_receive_done (tc->client, GNUNET_OK); GNUNET_SERVER_client_drop (tc->client); GNUNET_free_non_null (tc->buf); GNUNET_free (tc); } else { if (NULL == GNUNET_SERVER_notify_transmit_ready (tc->client, GNUNET_MIN (MIN_BLOCK_SIZE, tc->total - tc->off), GNUNET_TIME_absolute_get_remaining (tc->timeout), &transmit_response, tc)) { GNUNET_break (0); GNUNET_SERVER_transmit_context_destroy (tc, GNUNET_SYSERR); } } return msize; } /** * Create a new transmission context for the * given client. * * @param client client to create the context for. * @return NULL on error */ struct GNUNET_SERVER_TransmitContext * GNUNET_SERVER_transmit_context_create (struct GNUNET_SERVER_Client *client) { struct GNUNET_SERVER_TransmitContext *tc; GNUNET_assert (NULL != client); tc = GNUNET_new (struct GNUNET_SERVER_TransmitContext); GNUNET_SERVER_client_keep (client); tc->client = client; return tc; } /** * Append a message to the transmission context. * All messages in the context will be sent by * the transmit_context_run method. * * @param tc context to use * @param data what to append to the result message * @param length length of data * @param type type of the message */ void GNUNET_SERVER_transmit_context_append_data (struct GNUNET_SERVER_TransmitContext *tc, const void *data, size_t length, uint16_t type) { struct GNUNET_MessageHeader *msg; size_t size; GNUNET_assert (length < GNUNET_SERVER_MAX_MESSAGE_SIZE); size = length + sizeof (struct GNUNET_MessageHeader); GNUNET_assert (size > length); tc->buf = GNUNET_realloc (tc->buf, tc->total + size); msg = (struct GNUNET_MessageHeader *) &tc->buf[tc->total]; tc->total += size; msg->size = htons (size); msg->type = htons (type); memcpy (&msg[1], data, length); } /** * Append a message to the transmission context. * All messages in the context will be sent by * the transmit_context_run method. * * @param tc context to use * @param msg message to append */ void GNUNET_SERVER_transmit_context_append_message (struct GNUNET_SERVER_TransmitContext *tc, const struct GNUNET_MessageHeader *msg) { struct GNUNET_MessageHeader *m; uint16_t size; size = ntohs (msg->size); tc->buf = GNUNET_realloc (tc->buf, tc->total + size); m = (struct GNUNET_MessageHeader *) &tc->buf[tc->total]; tc->total += size; memcpy (m, msg, size); } /** * Execute a transmission context. If there is * an error in the transmission, the receive_done * method will be called with an error code (GNUNET_SYSERR), * otherwise with GNUNET_OK. * * @param tc transmission context to use * @param timeout when to time out and abort the transmission */ void GNUNET_SERVER_transmit_context_run (struct GNUNET_SERVER_TransmitContext *tc, struct GNUNET_TIME_Relative timeout) { tc->timeout = GNUNET_TIME_relative_to_absolute (timeout); if (NULL == GNUNET_SERVER_notify_transmit_ready (tc->client, GNUNET_MIN (MIN_BLOCK_SIZE, tc->total), timeout, &transmit_response, tc)) { GNUNET_break (0); GNUNET_SERVER_transmit_context_destroy (tc, GNUNET_SYSERR); } } /** * Destroy a transmission context. This function must not be called * after 'GNUNET_SERVER_transmit_context_run'. * * @param tc transmission context to destroy * @param success code to give to 'GNUNET_SERVER_receive_done' for * the client: GNUNET_OK to keep the connection open and * continue to receive * GNUNET_NO to close the connection (normal behavior) * GNUNET_SYSERR to close the connection (signal * serious error) */ void GNUNET_SERVER_transmit_context_destroy (struct GNUNET_SERVER_TransmitContext *tc, int success) { GNUNET_SERVER_receive_done (tc->client, success); GNUNET_SERVER_client_drop (tc->client); GNUNET_free_non_null (tc->buf); GNUNET_free (tc); } /* end of server_tc.c */ gnunet-0.10.1/src/util/test_crypto_hkdf.c0000644000175000017500000003437512225777501015321 00000000000000/* Copyright (c) 2010 Nils Durner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * @file src/util/test_crypt_hkdf.c * @brief Testcases for HKDF * @todo: test for out_len < hash_len * @author Nils Durner */ #include #include "platform.h" #include "gnunet_crypto_lib.h" void tc1 () { unsigned char ikm[22] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; unsigned char salt[13] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c }; unsigned char info[10] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 }; unsigned char okm[42] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65 }; unsigned char result[44]; int l = 42; memset (result, 0, sizeof (result)); GNUNET_assert (GNUNET_CRYPTO_hkdf (result, l, GCRY_MD_SHA256, GCRY_MD_SHA256, salt, sizeof (salt), ikm, sizeof (ikm), info, sizeof (info), NULL) == GNUNET_YES); GNUNET_assert (memcmp (result, okm, l) == 0); GNUNET_assert (memcmp (result + l, "\0", 2) == 0); } void tc2 () { unsigned char ikm[80] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; unsigned char salt[80] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf }; unsigned char info[80] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; unsigned char okm[82] = { 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87 }; char result[84]; int l = 82; memset (result, 0, sizeof (result)); GNUNET_assert (GNUNET_CRYPTO_hkdf (result, l, GCRY_MD_SHA256, GCRY_MD_SHA256, salt, sizeof (salt), ikm, sizeof (ikm), info, sizeof (info), NULL) == GNUNET_YES); GNUNET_assert (memcmp (result, okm, l) == 0); GNUNET_assert (memcmp (result + l, "\0", 2) == 0); } void tc3 () { unsigned char ikm[22] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; unsigned char okm[42] = { 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8 }; unsigned char result[44]; int l = 42; memset (result, 0, sizeof (result)); GNUNET_assert (GNUNET_CRYPTO_hkdf (result, l, GCRY_MD_SHA256, GCRY_MD_SHA256, NULL, 0, ikm, sizeof (ikm), NULL, 0, NULL) == GNUNET_YES); GNUNET_assert (memcmp (result, okm, l) == 0); GNUNET_assert (memcmp (result + l, "\0", 2) == 0); } void tc4 () { unsigned char ikm[11] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; unsigned char salt[13] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c }; unsigned char info[10] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 }; unsigned char okm[42] = { 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96 }; char result[84]; int l = 42; memset (result, 0, sizeof (result)); GNUNET_assert (GNUNET_CRYPTO_hkdf (result, l, GCRY_MD_SHA1, GCRY_MD_SHA1, salt, sizeof (salt), ikm, sizeof (ikm), info, sizeof (info), NULL) == GNUNET_YES); GNUNET_assert (memcmp (result, okm, l) == 0); GNUNET_assert (memcmp (result + l, "\0", 2) == 0); } void tc5 () { unsigned char ikm[80] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; unsigned char salt[80] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf }; unsigned char info[80] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; unsigned char okm[82] = { 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4 }; char result[84]; int l = 82; memset (result, 0, sizeof (result)); GNUNET_assert (GNUNET_CRYPTO_hkdf (result, l, GCRY_MD_SHA1, GCRY_MD_SHA1, salt, sizeof (salt), ikm, sizeof (ikm), info, sizeof (info), NULL) == GNUNET_YES); GNUNET_assert (memcmp (result, okm, l) == 0); GNUNET_assert (memcmp (result + l, "\0", 2) == 0); } void tc6 () { unsigned char ikm[22] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; unsigned char okm[42] = { 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18 }; char result[44]; int l = 42; memset (result, 0, sizeof (result)); GNUNET_assert (GNUNET_CRYPTO_hkdf (result, l, GCRY_MD_SHA1, GCRY_MD_SHA1, NULL, 0, ikm, sizeof (ikm), NULL, 0, NULL) == GNUNET_YES); GNUNET_assert (memcmp (result, okm, l) == 0); GNUNET_assert (memcmp (result + l, "\0", 2) == 0); } void tc7 () { unsigned char ikm[80] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; unsigned char salt[80] = { 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf }; unsigned char info1[34] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1 }; unsigned char info2[46] = { 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; unsigned char okm[82] = { 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4 }; char result[84]; int l = 82; memset (result, 0, sizeof (result)); GNUNET_assert (GNUNET_CRYPTO_hkdf (result, l, GCRY_MD_SHA1, GCRY_MD_SHA1, salt, sizeof (salt), ikm, sizeof (ikm), info1, sizeof (info1), info2, sizeof (info2), NULL) == GNUNET_YES); GNUNET_assert (memcmp (result, okm, l) == 0); GNUNET_assert (memcmp (result + l, "\0", 2) == 0); } void tc8 () { unsigned char ikm[32] = { 0xbf, 0x16, 0x6e, 0x46, 0x3a, 0x6c, 0xf3, 0x93, 0xa7, 0x72, 0x11, 0xa1, 0xdc, 0x0b, 0x07, 0xdb, 0x1a, 0x5e, 0xd9, 0xb9, 0x81, 0xbe, 0xea, 0xe4, 0x31, 0x5f, 0x24, 0xff, 0xfe, 0x50, 0x8a, 0xde }; unsigned char salt[4] = { 0xfc, 0x62, 0x76, 0x35 }; unsigned char info[86] = { 0x8c, 0x0d, 0xcf, 0xb3, 0x25, 0x6e, 0x88, 0x0d, 0xc1, 0x0b, 0x1d, 0x33, 0x15, 0x3e, 0x52, 0x0b, 0xb0, 0x77, 0xff, 0x7d, 0xc3, 0xc7, 0xef, 0xe5, 0x8e, 0x3c, 0xc4, 0x4e, 0x8b, 0x41, 0x46, 0x1f, 0x02, 0x94, 0x82, 0x35, 0xc5, 0xa6, 0x5e, 0x91, 0xd8, 0xa2, 0x90, 0xfd, 0x6f, 0xb4, 0x07, 0xc9, 0xed, 0x6b, 0x18, 0x90, 0x31, 0xab, 0x0f, 0xb5, 0x6b, 0xec, 0x9e, 0x45, 0xa2, 0x83, 0x65, 0x41, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x00 }; unsigned char okm[16] = { 0xd6, 0x90, 0xec, 0x9e, 0x62, 0xdf, 0xb9, 0x41, 0xff, 0x92, 0x4f, 0xd2, 0xf6, 0x1d, 0x67, 0xe0 }; char result[18]; int l = 16; memset (result, 0, sizeof (result)); GNUNET_assert (GNUNET_CRYPTO_hkdf (result, l, GCRY_MD_SHA512, GCRY_MD_SHA256, salt, sizeof (salt), ikm, sizeof (ikm), info, sizeof (info), NULL) == GNUNET_YES); GNUNET_assert (memcmp (result, okm, l) == 0); GNUNET_assert (memcmp (result + l, "\0", 2) == 0); } int main () { GNUNET_log_setup ("test-crypto-hkdf", "WARNING", NULL); /* Official test vectors */ tc1 (); tc2 (); tc3 (); tc4 (); tc5 (); tc6 (); /* Additional tests */ tc7 (); tc8 (); return 0; } gnunet-0.10.1/src/util/container_multihashmap.c0000644000175000017500000005126312234446163016474 00000000000000/* This file is part of GNUnet. (C) 2008, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/container_multihashmap.c * @brief hash map where the same key may be present multiple times * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * An entry in the hash map with the full key. */ struct BigMapEntry { /** * Value of the entry. */ void *value; /** * If there is a hash collision, we create a linked list. */ struct BigMapEntry *next; /** * Key for the entry. */ struct GNUNET_HashCode key; }; /** * An entry in the hash map with just a pointer to the key. */ struct SmallMapEntry { /** * Value of the entry. */ void *value; /** * If there is a hash collision, we create a linked list. */ struct SmallMapEntry *next; /** * Key for the entry. */ const struct GNUNET_HashCode *key; }; /** * Entry in the map. */ union MapEntry { /** * Variant used if map entries only contain a pointer to the key. */ struct SmallMapEntry *sme; /** * Variant used if map entries contain the full key. */ struct BigMapEntry *bme; }; /** * Internal representation of the hash map. */ struct GNUNET_CONTAINER_MultiHashMap { /** * All of our buckets. */ union MapEntry *map; /** * Number of entries in the map. */ unsigned int size; /** * Length of the "map" array. */ unsigned int map_length; /** * #GNUNET_NO if the map entries are of type 'struct BigMapEntry', * #GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. */ int use_small_entries; /** * Counts the destructive modifications (grow, remove) * to the map, so that iterators can check if they are still valid. */ unsigned int modification_counter; }; /** * Cursor into a multihashmap. * Allows to enumerate elements asynchronously. */ struct GNUNET_CONTAINER_MultiHashMapIterator { /** * Position in the bucket 'idx' */ union MapEntry me; /** * Current bucket index. */ unsigned int idx; /** * Modification counter as observed on the map when the iterator * was created. */ unsigned int modification_counter; /** * Map that we are iterating over. */ const struct GNUNET_CONTAINER_MultiHashMap *map; }; /** * Create a multi hash map. * * @param len initial size (map will grow as needed) * @param do_not_copy_keys #GNUNET_NO is always safe and should be used by default; * #GNUNET_YES means that on 'put', the 'key' does not have * to be copied as the destination of the pointer is * guaranteed to be life as long as the value is stored in * the hashmap. This can significantly reduce memory * consumption, but of course is also a recipie for * heap corruption if the assumption is not true. Only * use this if (1) memory use is important in this case and * (2) you have triple-checked that the invariant holds * @return NULL on error */ struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create (unsigned int len, int do_not_copy_keys) { struct GNUNET_CONTAINER_MultiHashMap *map; GNUNET_assert (len > 0); map = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMap); map->map = GNUNET_malloc (len * sizeof (union MapEntry)); map->map_length = len; map->use_small_entries = do_not_copy_keys; return map; } /** * Destroy a hash map. Will not free any values * stored in the hash map! * * @param map the map */ void GNUNET_CONTAINER_multihashmap_destroy (struct GNUNET_CONTAINER_MultiHashMap *map) { unsigned int i; union MapEntry me; for (i = 0; i < map->map_length; i++) { me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *nxt; nxt = me.sme; while (NULL != (sme = nxt)) { nxt = sme->next; GNUNET_free (sme); } me.sme = NULL; } else { struct BigMapEntry *bme; struct BigMapEntry *nxt; nxt = me.bme; while (NULL != (bme = nxt)) { nxt = bme->next; GNUNET_free (bme); } me.bme = NULL; } } GNUNET_free (map->map); GNUNET_free (map); } /** * Compute the index of the bucket for the given key. * * @param map hash map for which to compute the index * @param key what key should the index be computed for * @return offset into the "map" array of "map" */ static unsigned int idx_of (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key) { GNUNET_assert (map != NULL); return (*(unsigned int *) key) % map->map_length; } /** * Get the number of key-value pairs in the map. * * @param map the map * @return the number of key value pairs */ unsigned int GNUNET_CONTAINER_multihashmap_size (const struct GNUNET_CONTAINER_MultiHashMap *map) { return map->size; } /** * Given a key find a value in the map matching the key. * * @param map the map * @param key what to look for * @return NULL if no value was found; note that * this is indistinguishable from values that just * happen to be NULL; use "contains" to test for * key-value pairs with value NULL */ void * GNUNET_CONTAINER_multihashmap_get (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key) { union MapEntry me; me = map->map[idx_of (map, key)]; if (map->use_small_entries) { struct SmallMapEntry *sme; for (sme = me.sme; NULL != sme; sme = sme->next) if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) return sme->value; } else { struct BigMapEntry *bme; for (bme = me.bme; NULL != bme; bme = bme->next) if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) return bme->value; } return NULL; } /** * Iterate over all entries in the map. * * @param map the map * @param it function to call on each entry * @param it_cls extra argument to @a it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap_iterate (const struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_HashMapIterator it, void *it_cls) { int count; unsigned int i; union MapEntry me; struct GNUNET_HashCode kc; count = 0; GNUNET_assert (NULL != map); for (i = 0; i < map->map_length; i++) { me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *nxt; nxt = me.sme; while (NULL != (sme = nxt)) { nxt = sme->next; if (NULL != it) { if (GNUNET_OK != it (it_cls, sme->key, sme->value)) return GNUNET_SYSERR; } count++; } } else { struct BigMapEntry *bme; struct BigMapEntry *nxt; nxt = me.bme; while (NULL != (bme = nxt)) { nxt = bme->next; if (NULL != it) { kc = bme->key; if (GNUNET_OK != it (it_cls, &kc, bme->value)) return GNUNET_SYSERR; } count++; } } } return count; } /** * Remove the given key-value pair from the map. Note that if the * key-value pair is in the map multiple times, only one of the pairs * will be removed. * * @param map the map * @param key key of the key-value pair * @param value value of the key-value pair * @return #GNUNET_YES on success, #GNUNET_NO if the key-value pair * is not in the map */ int GNUNET_CONTAINER_multihashmap_remove (struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value) { union MapEntry me; unsigned int i; map->modification_counter++; i = idx_of (map, key); me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *p; p = NULL; for (sme = me.sme; NULL != sme; sme = sme->next) { if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) && (value == sme->value)) { if (NULL == p) map->map[i].sme = sme->next; else p->next = sme->next; GNUNET_free (sme); map->size--; return GNUNET_YES; } p = sme; } } else { struct BigMapEntry *bme; struct BigMapEntry *p; p = NULL; for (bme = me.bme; NULL != bme; bme = bme->next) { if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) && (value == bme->value)) { if (NULL == p) map->map[i].bme = bme->next; else p->next = bme->next; GNUNET_free (bme); map->size--; return GNUNET_YES; } p = bme; } } return GNUNET_NO; } /** * Remove all entries for the given key from the map. * Note that the values would not be "freed". * * @param map the map * @param key identifies values to be removed * @return number of values removed */ int GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key) { union MapEntry me; unsigned int i; int ret; map->modification_counter++; ret = 0; i = idx_of (map, key); me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *p; p = NULL; sme = me.sme; while (NULL != sme) { if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) { if (NULL == p) map->map[i].sme = sme->next; else p->next = sme->next; GNUNET_free (sme); map->size--; if (NULL == p) sme = map->map[i].sme; else sme = p->next; ret++; } else { p = sme; sme = sme->next; } } } else { struct BigMapEntry *bme; struct BigMapEntry *p; p = NULL; bme = me.bme; while (NULL != bme) { if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) { if (NULL == p) map->map[i].bme = bme->next; else p->next = bme->next; GNUNET_free (bme); map->size--; if (NULL == p) bme = map->map[i].bme; else bme = p->next; ret++; } else { p = bme; bme = bme->next; } } } return ret; } /** * Check if the map contains any value under the given * key (including values that are NULL). * * @param map the map * @param key the key to test if a value exists for it * @return #GNUNET_YES if such a value exists, * #GNUNET_NO if not */ int GNUNET_CONTAINER_multihashmap_contains (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key) { union MapEntry me; me = map->map[idx_of (map, key)]; if (map->use_small_entries) { struct SmallMapEntry *sme; for (sme = me.sme; NULL != sme; sme = sme->next) if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) return GNUNET_YES; } else { struct BigMapEntry *bme; for (bme = me.bme; NULL != bme; bme = bme->next) if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) return GNUNET_YES; } return GNUNET_NO; } /** * Check if the map contains the given value under the given * key. * * @param map the map * @param key the key to test if a value exists for it * @param value value to test for * @return #GNUNET_YES if such a value exists, * #GNUNET_NO if not */ int GNUNET_CONTAINER_multihashmap_contains_value (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value) { union MapEntry me; me = map->map[idx_of (map, key)]; if (map->use_small_entries) { struct SmallMapEntry *sme; for (sme = me.sme; NULL != sme; sme = sme->next) if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) && (sme->value == value) ) return GNUNET_YES; } else { struct BigMapEntry *bme; for (bme = me.bme; NULL != bme; bme = bme->next) if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) && (bme->value == value) ) return GNUNET_YES; } return GNUNET_NO; } /** * Grow the given map to a more appropriate size. * * @param map the hash map to grow */ static void grow (struct GNUNET_CONTAINER_MultiHashMap *map) { union MapEntry *old_map; union MapEntry *new_map; unsigned int old_len; unsigned int new_len; unsigned int idx; unsigned int i; map->modification_counter++; old_map = map->map; old_len = map->map_length; new_len = old_len * 2; new_map = GNUNET_malloc (sizeof (union MapEntry) * new_len); map->map_length = new_len; map->map = new_map; for (i = 0; i < old_len; i++) { if (map->use_small_entries) { struct SmallMapEntry *sme; while (NULL != (sme = old_map[i].sme)) { old_map[i].sme = sme->next; idx = idx_of (map, sme->key); sme->next = new_map[idx].sme; new_map[idx].sme = sme; } } else { struct BigMapEntry *bme; while (NULL != (bme = old_map[i].bme)) { old_map[i].bme = bme->next; idx = idx_of (map, &bme->key); bme->next = new_map[idx].bme; new_map[idx].bme = bme; } } } GNUNET_free (old_map); } /** * Store a key-value pair in the map. * * @param map the map * @param key key to use * @param value value to use * @param opt options for put * @return #GNUNET_OK on success, * #GNUNET_NO if a value was replaced (with REPLACE) * #GNUNET_SYSERR if UNIQUE_ONLY was the option and the * value already exists */ int GNUNET_CONTAINER_multihashmap_put (struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt) { union MapEntry me; unsigned int i; i = idx_of (map, key); if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) && (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { me = map->map[i]; if (map->use_small_entries) { struct SmallMapEntry *sme; for (sme = me.sme; NULL != sme; sme = sme->next) if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) { if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) return GNUNET_SYSERR; sme->value = value; return GNUNET_NO; } } else { struct BigMapEntry *bme; for (bme = me.bme; NULL != bme; bme = bme->next) if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) { if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) return GNUNET_SYSERR; bme->value = value; return GNUNET_NO; } } } if (map->size / 3 >= map->map_length / 4) { grow (map); i = idx_of (map, key); } if (map->use_small_entries) { struct SmallMapEntry *sme; sme = GNUNET_new (struct SmallMapEntry); sme->key = key; sme->value = value; sme->next = map->map[i].sme; map->map[i].sme = sme; } else { struct BigMapEntry *bme; bme = GNUNET_new (struct BigMapEntry); bme->key = *key; bme->value = value; bme->next = map->map[i].bme; map->map[i].bme = bme; } map->size++; return GNUNET_OK; } /** * Iterate over all entries in the map that match a particular key. * * @param map the map * @param key key that the entries must correspond to * @param it function to call on each entry * @param it_cls extra argument to it * @return the number of key value pairs processed, * #GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_HashMapIterator it, void *it_cls) { int count; union MapEntry me; count = 0; me = map->map[idx_of (map, key)]; if (map->use_small_entries) { struct SmallMapEntry *sme; struct SmallMapEntry *nxt; nxt = me.sme; while (NULL != (sme = nxt)) { nxt = sme->next; if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) continue; if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value))) return GNUNET_SYSERR; count++; } } else { struct BigMapEntry *bme; struct BigMapEntry *nxt; nxt = me.bme; while (NULL != (bme = nxt)) { nxt = bme->next; if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) continue; if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value))) return GNUNET_SYSERR; count++; } } return count; } /** * Create an iterator for a multihashmap. * The iterator can be used to retrieve all the elements in the multihashmap * one by one, without having to handle all elements at once (in contrast to * GNUNET_CONTAINER_multihashmap_iterate()). Note that the iterator can not be * used anymore if elements have been removed from 'map' after the creation of * the iterator, or 'map' has been destroyed. Adding elements to 'map' may * result in skipped or repeated elements. * * @param map the map to create an iterator for * @return an iterator over the given multihashmap 'map' */ struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create (const struct GNUNET_CONTAINER_MultiHashMap *map) { struct GNUNET_CONTAINER_MultiHashMapIterator *iter; iter = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMapIterator); iter->map = map; iter->modification_counter = map->modification_counter; iter->me = map->map[0]; return iter; } /** * Retrieve the next element from the hash map at the iterator's position. * If there are no elements left, GNUNET_NO is returned, and 'key' and 'value' * are not modified. * This operation is only allowed if no elements have been removed from the * multihashmap since the creation of 'iter', and the map has not been destroyed. * Adding elements may result in repeating or skipping elements. * * @param iter the iterator to get the next element from * @param key pointer to store the key in, can be NULL * @param value pointer to store the value in, can be NULL * @return #GNUNET_YES we returned an element, * #GNUNET_NO if we are out of elements */ int GNUNET_CONTAINER_multihashmap_iterator_next (struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value) { /* make sure the map has not been modified */ GNUNET_assert (iter->modification_counter == iter->map->modification_counter); /* look for the next entry, skipping empty buckets */ while (1) { if (iter->idx >= iter->map->map_length) return GNUNET_NO; if (GNUNET_YES == iter->map->use_small_entries) { if (NULL != iter->me.sme) { if (NULL != key) *key = *iter->me.sme->key; if (NULL != value) *value = iter->me.sme->value; iter->me.sme = iter->me.sme->next; return GNUNET_YES; } } else { if (NULL != iter->me.bme) { if (NULL != key) *key = iter->me.bme->key; if (NULL != value) *value = iter->me.bme->value; iter->me.bme = iter->me.bme->next; return GNUNET_YES; } } iter->idx += 1; if (iter->idx < iter->map->map_length) iter->me = iter->map->map[iter->idx]; } } /** * Destroy a multihashmap iterator. * * @param iter the iterator to destroy */ void GNUNET_CONTAINER_multihashmap_iterator_destroy (struct GNUNET_CONTAINER_MultiHashMapIterator *iter) { GNUNET_free (iter); } /* end of container_multihashmap.c */ gnunet-0.10.1/src/util/gnunet-config.c0000644000175000017500000001060612225777501014500 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/gnunet-config.c * @brief tool to access and manipulate GNUnet configuration files * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" /** * Name of the section */ static char *section; /** * Name of the option */ static char *option; /** * Value to set */ static char *value; /** * Treat option as a filename. */ static int is_filename; /** * Return value from 'main'. */ static int ret; /** * Print each option in a given section. * * @param cls closure * @param section name of the section * @param option name of the option * @param value value of the option */ static void print_option (void *cls, const char *section, const char *option, const char *value) { fprintf (stdout, "%s = %s\n", option, value); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_CONFIGURATION_Handle *out; if (NULL == section) { fprintf (stderr, _("--section argument is required\n")); ret = 1; return; } if (NULL == value) { if (NULL == option) { GNUNET_CONFIGURATION_iterate_section_values (cfg, section, &print_option, NULL); } else { if (is_filename) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, section, option, &value)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, option); ret = 3; return; } } else { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &value)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, section, option); ret = 3; return; } } fprintf (stdout, "%s\n", value); } } else { if (NULL == option) { fprintf (stderr, _("--option argument required to set value\n")); ret = 1; return; } out = GNUNET_CONFIGURATION_dup (cfg); GNUNET_CONFIGURATION_set_value_string (out, section, option, value); if (GNUNET_OK != GNUNET_CONFIGURATION_write (out, cfgfile)) ret = 2; GNUNET_CONFIGURATION_destroy (out); return; } } /** * Program to manipulate configuration files. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'f', "filename", NULL, gettext_noop ("obtain option of value as a filename (with $-expansion)"), 0, &GNUNET_GETOPT_set_one, &is_filename }, { 's', "section", "SECTION", gettext_noop ("name of the section to access"), 1, &GNUNET_GETOPT_set_string, §ion }, { 'o', "option", "OPTION", gettext_noop ("name of the option to access"), 1, &GNUNET_GETOPT_set_string, &option }, { 'V', "value", "VALUE", gettext_noop ("value to set"), 1, &GNUNET_GETOPT_set_string, &value }, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-config [OPTIONS]", gettext_noop ("Manipulate GNUnet configuration files"), options, &run, NULL)) ? 0 : ret; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-config.c */ gnunet-0.10.1/src/util/test_container_slist.c0000644000175000017500000001174512255010512016162 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_container_slist.c * @brief Testcases for singly linked lists * @author Nils Durner */ #include "platform.h" #include "gnunet_util_lib.h" int main (int argc, char *argv[]) { struct GNUNET_CONTAINER_SList *l; struct GNUNET_CONTAINER_SList_Iterator it; unsigned int i; int *ip; unsigned int j; size_t s; const void *p; GNUNET_log_setup ("test-container-slist", "WARNING", NULL); l = GNUNET_CONTAINER_slist_create (); GNUNET_assert (l != NULL); GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 0); for (i = 0; i < 100; i++) GNUNET_CONTAINER_slist_add (l, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &i, sizeof (i)); GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 100); for (it = GNUNET_CONTAINER_slist_begin (l), i = 99; GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&it), i--) { p = GNUNET_CONTAINER_slist_get (&it, &s); if ((p == NULL) || (i != (j = *(int *) p)) || (s != sizeof (i))) { GNUNET_CONTAINER_slist_iter_destroy (&it); GNUNET_assert (0); } j *= 2; GNUNET_CONTAINER_slist_insert (&it, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &j, sizeof (j)); } GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 200); i = 198; GNUNET_assert (GNUNET_CONTAINER_slist_contains (l, &i, sizeof (i))); for (it = GNUNET_CONTAINER_slist_begin (l); GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES;) { p = GNUNET_CONTAINER_slist_get (&it, &s); GNUNET_assert (p != NULL); GNUNET_assert (s == sizeof (i)); i = *(int *) p; GNUNET_assert (GNUNET_CONTAINER_slist_next (&it) == GNUNET_YES); GNUNET_assert (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES); p = GNUNET_CONTAINER_slist_get (&it, &s); GNUNET_assert (p != NULL); GNUNET_assert (s == sizeof (j)); j = *(int *) p; GNUNET_assert (j * 2 == i); GNUNET_CONTAINER_slist_erase (&it); } GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 100); i = 99; GNUNET_assert (GNUNET_CONTAINER_slist_contains (l, &i, sizeof (i)) == GNUNET_NO); i = 198; GNUNET_assert (GNUNET_CONTAINER_slist_contains (l, &i, sizeof (i)) == GNUNET_YES); GNUNET_CONTAINER_slist_clear (l); GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 0); for (i = 0; i < 100; i++) GNUNET_CONTAINER_slist_add (l, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &i, sizeof (i)); /*check slist_append */ GNUNET_CONTAINER_slist_append (l, l); GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 200); GNUNET_CONTAINER_slist_destroy (l); /*check slist_add_end */ l = GNUNET_CONTAINER_slist_create (); for (i = 0; i < 100; i++) GNUNET_CONTAINER_slist_add_end (l, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &i, sizeof (i)); GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 100); for (it = GNUNET_CONTAINER_slist_begin (l), i = 0; GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&it), i++) { p = GNUNET_CONTAINER_slist_get (&it, &s); if ((p == NULL) || (i != *(int *) p) || (s != sizeof (i))) { GNUNET_assert (0); } } GNUNET_CONTAINER_slist_destroy (l); /*check if disp = GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC */ l = GNUNET_CONTAINER_slist_create (); for (i = 0; i < 100; i++) { ip = GNUNET_new (int); *ip = i; GNUNET_CONTAINER_slist_add (l, GNUNET_CONTAINER_SLIST_DISPOSITION_DYNAMIC, ip, sizeof (int)); } //creat_add it = GNUNET_CONTAINER_slist_begin (l); p = GNUNET_CONTAINER_slist_get (&it, &s); GNUNET_assert (p != NULL); //slist_erase GNUNET_assert (GNUNET_CONTAINER_slist_next (&it) == GNUNET_YES); GNUNET_CONTAINER_slist_erase (&it); GNUNET_CONTAINER_slist_iter_destroy (&it); GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 99); //slist_clear GNUNET_CONTAINER_slist_clear (l); GNUNET_assert (GNUNET_CONTAINER_slist_count (l) == 0); GNUNET_CONTAINER_slist_destroy (l); return 0; } gnunet-0.10.1/src/util/test_getopt.c0000644000175000017500000001071012225777501014272 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_getopt.c * @brief testcase for util/getopt.c */ #include "platform.h" #include "gnunet_util_lib.h" static int testMinimal () { char *const emptyargv[] = { "test", NULL }; const struct GNUNET_GETOPT_CommandLineOption emptyoptionlist[] = { GNUNET_GETOPT_OPTION_END }; if (1 != GNUNET_GETOPT_run ("test", emptyoptionlist, 1, emptyargv)) return 1; return 0; } static int testVerbose () { char *const myargv[] = { "test", "-V", "-V", "more", NULL }; unsigned int vflags = 0; const struct GNUNET_GETOPT_CommandLineOption verboseoptionlist[] = { GNUNET_GETOPT_OPTION_VERBOSE (&vflags), GNUNET_GETOPT_OPTION_END }; if (3 != GNUNET_GETOPT_run ("test", verboseoptionlist, 4, myargv)) { GNUNET_break (0); return 1; } if (vflags != 2) { GNUNET_break (0); return 1; } return 0; } static int testVersion () { char *const myargv[] = { "test_getopt", "-v", NULL }; const struct GNUNET_GETOPT_CommandLineOption versionoptionlist[] = { GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION), GNUNET_GETOPT_OPTION_END }; if (0 != GNUNET_GETOPT_run ("test_getopt", versionoptionlist, 2, myargv)) { GNUNET_break (0); return 1; } return 0; } static int testAbout () { char *const myargv[] = { "test_getopt", "-h", NULL }; const struct GNUNET_GETOPT_CommandLineOption aboutoptionlist[] = { GNUNET_GETOPT_OPTION_HELP ("Testing"), GNUNET_GETOPT_OPTION_END }; if (0 != GNUNET_GETOPT_run ("test_getopt", aboutoptionlist, 2, myargv)) { GNUNET_break (0); return 1; } return 0; } static int testLogOpts () { char *const myargv[] = { "test_getopt", "-l", "filename", "-L", "WARNING", NULL }; char *level = GNUNET_strdup ("stuff"); char *fn = NULL; const struct GNUNET_GETOPT_CommandLineOption logoptionlist[] = { GNUNET_GETOPT_OPTION_LOGFILE (&fn), GNUNET_GETOPT_OPTION_LOGLEVEL (&level), GNUNET_GETOPT_OPTION_END }; if (5 != GNUNET_GETOPT_run ("test_getopt", logoptionlist, 5, myargv)) { GNUNET_break (0); return 1; } GNUNET_assert (fn != NULL); if ((0 != strcmp (level, "WARNING")) || (0 != strcmp (fn, "filename"))) { GNUNET_break (0); GNUNET_free (level); GNUNET_free (fn); return 1; } GNUNET_free (level); GNUNET_free (fn); return 0; } static int testFlagNum () { char *const myargv[] = { "test_getopt", "-f", "-n", "42", "-N", "42", NULL }; int flag = 0; unsigned int num = 0; unsigned long long lnum = 0; const struct GNUNET_GETOPT_CommandLineOption logoptionlist[] = { {'f', "--flag", NULL, "helptext", 0, &GNUNET_GETOPT_set_one, (void *) &flag}, {'n', "--num", "ARG", "helptext", 1, &GNUNET_GETOPT_set_uint, (void *) &num}, {'N', "--lnum", "ARG", "helptext", 1, &GNUNET_GETOPT_set_ulong, (void *) &lnum}, GNUNET_GETOPT_OPTION_END }; if (6 != GNUNET_GETOPT_run ("test_getopt", logoptionlist, 6, myargv)) { GNUNET_break (0); return 1; } if ((1 != flag) || (42 != num) || (42 != lnum)) { GNUNET_break (0); return 1; } return 0; } int main (int argc, char *argv[]) { int errCnt = 0; GNUNET_log_setup ("test_getopt", "WARNING", NULL); /* suppress output from -h, -v options */ #ifndef MINGW GNUNET_break (0 == CLOSE (1)); #endif if (0 != testMinimal ()) errCnt++; if (0 != testVerbose ()) errCnt++; if (0 != testVersion ()) errCnt++; if (0 != testAbout ()) errCnt++; if (0 != testLogOpts ()) errCnt++; if (0 != testFlagNum ()) errCnt++; return errCnt; } gnunet-0.10.1/src/util/crypto_hkdf.c0000644000175000017500000001704612263515227014253 00000000000000/* Copyright (c) 2010 Nils Durner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * @file src/util/crypto_hkdf.c * @brief Hash-based KDF as defined in RFC 5869 * @see http://www.rfc-editor.org/rfc/rfc5869.txt * @todo remove GNUNET references * @author Nils Durner * * The following list of people have reviewed this code and considered * it correct on the date given (if you reviewed it, please * have your name added to the list): * * - Christian Grothoff (08.10.2010) * - Nathan Evans (08.10.2010) * - Matthias Wachs (08.10.2010) */ #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Set this to 0 if you compile this code outside of GNUnet. */ #define GNUNET_BUILD 1 /** * Enable debugging. */ #define DEBUG_HKDF 0 #if GNUNET_BUILD #include "platform.h" #include "gnunet_crypto_lib.h" #else #define GNUNET_NO 0 #define GNUNET_YES 1 #define GNUNET_SYSERR -1 #include #endif #include /** * @brief Compute the HMAC * @todo use chunked buffers * @param mac gcrypt MAC handle * @param key HMAC key * @param key_len length of key * @param buf message to be processed * @param buf_len length of buf * @return HMAC, freed by caller via gcry_md_close/_reset */ static const void * doHMAC (gcry_md_hd_t mac, const void *key, size_t key_len, const void *buf, size_t buf_len) { gcry_md_setkey (mac, key, key_len); gcry_md_write (mac, buf, buf_len); return (const void *) gcry_md_read (mac, 0); } /** * @brief Generate pseudo-random key * @param mac gcrypt HMAC handle * @param xts salt * @param xts_len length of the @a xts salt * @param skm source key material * @param skm_len length of @a skm * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes) * @return #GNUNET_YES on success */ static int getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm, size_t skm_len, void *prk) { const void *ret; ret = doHMAC (mac, xts, xts_len, skm, skm_len); if (ret == NULL) return GNUNET_SYSERR; memcpy (prk, ret, gcry_md_get_algo_dlen (gcry_md_get_algo (mac))); return GNUNET_YES; } #if DEBUG_HKDF static void dump (const char *src, const void *p, unsigned int l) { unsigned int i; printf ("\n%s: ", src); for (i = 0; i < l; i++) { printf ("%2x", (int) ((const unsigned char *) p)[i]); } printf ("\n"); } #endif /** * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... * @param xts salt * @param xts_len length of @a xts * @param skm source key material * @param skm_len length of @a skm * @param argp va_list of void * & size_t pairs for context chunks * @return #GNUNET_YES on success */ int GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, const void *xts, size_t xts_len, const void *skm, size_t skm_len, va_list argp) { gcry_md_hd_t xtr; gcry_md_hd_t prf; const void *hc; unsigned long i; unsigned long t; unsigned long d; unsigned int k = gcry_md_get_algo_dlen (prf_algo); unsigned int xtr_len = gcry_md_get_algo_dlen (xtr_algo); char prk[xtr_len]; int ret; size_t ctx_len; va_list args; if (0 == k) return GNUNET_SYSERR; if (GPG_ERR_NO_ERROR != gcry_md_open (&xtr, xtr_algo, GCRY_MD_FLAG_HMAC)) return GNUNET_SYSERR; if (GPG_ERR_NO_ERROR != gcry_md_open (&prf, prf_algo, GCRY_MD_FLAG_HMAC)) { gcry_md_close (xtr); return GNUNET_SYSERR; } va_copy (args, argp); ctx_len = 0; while (NULL != va_arg (args, void *)) ctx_len += va_arg (args, size_t); va_end (args); memset (result, 0, out_len); if (getPRK (xtr, xts, xts_len, skm, skm_len, prk) != GNUNET_YES) goto hkdf_error; #if DEBUG_HKDF dump ("PRK", prk, xtr_len); #endif t = out_len / k; d = out_len % k; /* K(1) */ { size_t plain_len = k + ctx_len + 1; char plain[plain_len]; const void *ctx; char *dst; dst = plain + k; va_copy (args, argp); while ((ctx = va_arg (args, void *))) { size_t len; len = va_arg (args, size_t); memcpy (dst, ctx, len); dst += len; } va_end (args); if (t > 0) { memset (plain + k + ctx_len, 1, 1); #if DEBUG_HKDF dump ("K(1)", plain, plain_len); #endif hc = doHMAC (prf, prk, xtr_len, &plain[k], ctx_len + 1); if (hc == NULL) goto hkdf_error; memcpy (result, hc, k); result += k; } /* K(i+1) */ for (i = 1; i < t; i++) { memcpy (plain, result - k, k); memset (plain + k + ctx_len, i + 1, 1); gcry_md_reset (prf); #if DEBUG_HKDF dump ("K(i+1)", plain, plain_len); #endif hc = doHMAC (prf, prk, xtr_len, plain, plain_len); if (hc == NULL) goto hkdf_error; memcpy (result, hc, k); result += k; } /* K(t):d */ if (d > 0) { if (t > 0) { memcpy (plain, result - k, k); i++; } memset (plain + k + ctx_len, i, 1); gcry_md_reset (prf); #if DEBUG_HKDF dump ("K(t):d", plain, plain_len); #endif if (t > 0) hc = doHMAC (prf, prk, xtr_len, plain, plain_len); else hc = doHMAC (prf, prk, xtr_len, plain + k, plain_len - k); if (hc == NULL) goto hkdf_error; memcpy (result, hc, d); } #if DEBUG_HKDF dump ("result", result - k, out_len); #endif ret = GNUNET_YES; goto hkdf_ok; } hkdf_error: ret = GNUNET_SYSERR; hkdf_ok: gcry_md_close (xtr); gcry_md_close (prf); return ret; } /** * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... * @param xts salt * @param xts_len length of @a xts * @param skm source key material * @param skm_len length of @a skm * @return #GNUNET_YES on success */ int GNUNET_CRYPTO_hkdf (void *result, size_t out_len, int xtr_algo, int prf_algo, const void *xts, size_t xts_len, const void *skm, size_t skm_len, ...) { va_list argp; int ret; va_start (argp, skm_len); ret = GNUNET_CRYPTO_hkdf_v (result, out_len, xtr_algo, prf_algo, xts, xts_len, skm, skm_len, argp); va_end (argp); return ret; } /* end of crypto_hkdf.c */ gnunet-0.10.1/src/util/configuration.c0000644000175000017500000012516712272454041014606 00000000000000/* This file is part of GNUnet. (C) 2006, 2007, 2008, 2009, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/util/configuration.c * @brief configuration management * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * @brief configuration entry */ struct ConfigEntry { /** * This is a linked list. */ struct ConfigEntry *next; /** * key for this entry */ char *key; /** * current, commited value */ char *val; }; /** * @brief configuration section */ struct ConfigSection { /** * This is a linked list. */ struct ConfigSection *next; /** * entries in the section */ struct ConfigEntry *entries; /** * name of the section */ char *name; }; /** * @brief configuration data */ struct GNUNET_CONFIGURATION_Handle { /** * Configuration sections. */ struct ConfigSection *sections; /** * Modification indication since last save * #GNUNET_NO if clean, #GNUNET_YES if dirty, * #GNUNET_SYSERR on error (i.e. last save failed) */ int dirty; }; /** * Used for diffing a configuration object against * the default one */ struct DiffHandle { const struct GNUNET_CONFIGURATION_Handle *cfg_default; struct GNUNET_CONFIGURATION_Handle *cfgDiff; }; /** * Create a GNUNET_CONFIGURATION_Handle. * * @return fresh configuration object */ struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create () { return GNUNET_new (struct GNUNET_CONFIGURATION_Handle); } /** * Destroy configuration object. * * @param cfg configuration to destroy */ void GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg) { struct ConfigSection *sec; while (NULL != (sec = cfg->sections)) GNUNET_CONFIGURATION_remove_section (cfg, sec->name); GNUNET_free (cfg); } /** * De-serializes configuration * * @param cfg configuration to update * @param mem the memory block of serialized configuration * @param size the size of the memory block * @param allow_inline set to #GNUNET_YES if we recursively load configuration * from inlined configurations; #GNUNET_NO if not and raise warnings * when we come across them * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, const char *mem, const size_t size, int allow_inline) { char *line; char *line_orig; size_t line_size; char *pos; unsigned int nr; size_t r_bytes; size_t to_read; size_t i; int emptyline; int ret; char *section; char *eq; char *tag; char *value; LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing config file\n"); ret = GNUNET_OK; section = GNUNET_strdup (""); nr = 0; r_bytes = 0; line_orig = NULL; while (r_bytes < size) { GNUNET_free_non_null (line_orig); /* fgets-like behaviour on buffer */ to_read = size - r_bytes; pos = memchr (&mem[r_bytes], '\n', to_read); if (NULL == pos) { line_orig = GNUNET_strndup (&mem[r_bytes], line_size = to_read); r_bytes += line_size; } else { line_orig = GNUNET_strndup (&mem[r_bytes], line_size = (pos - &mem[r_bytes])); r_bytes += line_size + 1; } line = line_orig; /* increment line number */ nr++; /* tabs and '\r' are whitespace */ emptyline = GNUNET_YES; for (i = 0; i < line_size; i++) { if (line[i] == '\t') line[i] = ' '; if (line[i] == '\r') line[i] = ' '; if (' ' != line[i]) emptyline = GNUNET_NO; } /* ignore empty lines */ if (GNUNET_YES == emptyline) continue; /* remove tailing whitespace */ for (i = line_size - 1; (i >= 1) && (isspace ((unsigned char) line[i]));i--) line[i] = '\0'; /* remove leading whitespace */ for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++); /* ignore comments */ if ( ('#' == line[0]) || ('%' == line[0]) ) continue; /* handle special "@INLINE@" directive */ if (0 == strncasecmp (line, "@INLINE@ ", strlen ("@INLINE@ "))) { /* @INLINE@ value */ value = &line[strlen ("@INLINE@ ")]; if (GNUNET_YES == allow_inline) { if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, value)) { ret = GNUNET_SYSERR; /* failed to parse included config */ break; } } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Ignoring parsing @INLINE@ configurations, not allowed!\n"); ret = GNUNET_SYSERR; break; } continue; } if ( ('[' == line[0]) && (']' == line[line_size - 1]) ) { /* [value] */ line[line_size - 1] = '\0'; value = &line[1]; GNUNET_free (section); section = GNUNET_strdup (value); LOG (GNUNET_ERROR_TYPE_DEBUG, "Config section `%s'\n", section); continue; } if (NULL != (eq = strchr (line, '='))) { /* tag = value */ tag = GNUNET_strndup (line, eq - line); /* remove tailing whitespace */ for (i = strlen (tag) - 1; (i >= 1) && (isspace ((unsigned char) tag[i]));i--) tag[i] = '\0'; /* Strip whitespace */ value = eq + 1; while (isspace ((unsigned char) value[0])) value++; for (i = strlen (value) - 1; (i >= 1) && (isspace ((unsigned char) value[i]));i--) value[i] = '\0'; /* remove quotes */ i = 0; if ( ('"' == value[0]) && ('"' == value[strlen (value) - 1]) ) { value[strlen (value) - 1] = '\0'; value++; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Config value %s=\"%s\"\n", tag, value); GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]); GNUNET_free (tag); continue; } /* parse error */ LOG (GNUNET_ERROR_TYPE_WARNING, _("Syntax error while deserializing in line %u\n"), nr); ret = GNUNET_SYSERR; break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished deserializing config\n"); GNUNET_free_non_null (line_orig); GNUNET_free (section); GNUNET_assert ( (GNUNET_OK != ret) || (r_bytes == size) ); return ret; } /** * Parse a configuration file, add all of the options in the * file to the configuration environment. * * @param cfg configuration to update * @param filename name of the configuration file * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename) { uint64_t fs64; size_t fs; char *fn; char *mem; int dirty; int ret; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", filename); fn = GNUNET_STRINGS_filename_expand (filename); LOG (GNUNET_ERROR_TYPE_DEBUG, "Config file name expanded to `%s'\n", fn); if (fn == NULL) return GNUNET_SYSERR; dirty = cfg->dirty; /* back up value! */ if (GNUNET_SYSERR == GNUNET_DISK_file_size (fn, &fs64, GNUNET_YES, GNUNET_YES)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Error while determining the file size of %s\n", fn); GNUNET_free (fn); return GNUNET_SYSERR; } if (fs64 > SIZE_MAX) { GNUNET_break (0); /* File size is more than the heap size */ GNUNET_free (fn); return GNUNET_SYSERR; } fs = fs64; mem = GNUNET_malloc (fs); if (fs != GNUNET_DISK_fn_read (fn, mem, fs)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Error while reading file %s\n", fn); GNUNET_free (fn); GNUNET_free (mem); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing contents of file `%s'\n", fn); GNUNET_free (fn); ret = GNUNET_CONFIGURATION_deserialize (cfg, mem, fs, GNUNET_YES); GNUNET_free (mem); /* restore dirty flag - anything we set in the meantime * came from disk */ cfg->dirty = dirty; return ret; } /** * Test if there are configuration options that were * changed since the last save. * * @param cfg configuration to inspect * @return #GNUNET_NO if clean, #GNUNET_YES if dirty, #GNUNET_SYSERR on error (i.e. last save failed) */ int GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg) { return cfg->dirty; } /** * Serializes the given configuration. * * @param cfg configuration to serialize * @param size will be set to the size of the serialized memory block * @return the memory block where the serialized configuration is * present. This memory should be freed by the caller */ char * GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size) { struct ConfigSection *sec; struct ConfigEntry *ent; char *mem; char *cbuf; char *val; char *pos; int len; size_t m_size; size_t c_size; /* Pass1 : calculate the buffer size required */ m_size = 0; for (sec = cfg->sections; NULL != sec; sec = sec->next) { /* For each section we need to add 3 charaters: {'[',']','\n'} */ m_size += strlen (sec->name) + 3; for (ent = sec->entries; NULL != ent; ent = ent->next) { if (NULL != ent->val) { /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */ pos = ent->val; while (NULL != (pos = strstr (pos, "\n"))) { m_size++; pos++; } /* For each key = value pair we need to add 4 characters (2 spaces and 1 equal-to character and 1 new line) */ m_size += strlen (ent->key) + strlen (ent->val) + 4; } } /* A new line after section end */ m_size++; } /* Pass2: Allocate memory and write the configuration to it */ mem = GNUNET_malloc (m_size); sec = cfg->sections; c_size = 0; *size = c_size; while (NULL != sec) { len = GNUNET_asprintf (&cbuf, "[%s]\n", sec->name); GNUNET_assert (0 < len); memcpy (mem + c_size, cbuf, len); c_size += len; GNUNET_free (cbuf); for (ent = sec->entries; NULL != ent; ent = ent->next) { if (NULL != ent->val) { val = GNUNET_malloc (strlen (ent->val) * 2 + 1); strcpy (val, ent->val); while (NULL != (pos = strstr (val, "\n"))) { memmove (&pos[2], &pos[1], strlen (&pos[1])); pos[0] = '\\'; pos[1] = 'n'; } len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val); GNUNET_free (val); memcpy (mem + c_size, cbuf, len); c_size += len; GNUNET_free (cbuf); } } memcpy (mem + c_size, "\n", 1); c_size ++; sec = sec->next; } GNUNET_assert (c_size == m_size); *size = c_size; return mem; } /** * Write configuration file. * * @param cfg configuration to write * @param filename where to write the configuration * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename) { char *fn; char *cfg_buf; size_t size; fn = GNUNET_STRINGS_filename_expand (filename); if (fn == NULL) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)) { GNUNET_free (fn); return GNUNET_SYSERR; } cfg_buf = GNUNET_CONFIGURATION_serialize (cfg, &size); if (size != GNUNET_DISK_fn_write (fn, cfg_buf, size, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_GROUP_WRITE)) { GNUNET_free (fn); GNUNET_free (cfg_buf); LOG (GNUNET_ERROR_TYPE_WARNING, "Writing configration to file: %s failed\n", filename); cfg->dirty = GNUNET_SYSERR; /* last write failed */ return GNUNET_SYSERR; } GNUNET_free (fn); GNUNET_free (cfg_buf); cfg->dirty = GNUNET_NO; /* last write succeeded */ return GNUNET_OK; } /** * Iterate over all options in the configuration. * * @param cfg configuration to inspect * @param iter function to call on each option * @param iter_cls closure for @a iter */ void GNUNET_CONFIGURATION_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls) { struct ConfigSection *spos; struct ConfigEntry *epos; for (spos = cfg->sections; NULL != spos; spos = spos->next) for (epos = spos->entries; NULL != epos; epos = epos->next) if (NULL != epos->val) iter (iter_cls, spos->name, epos->key, epos->val); } /** * Iterate over values of a section in the configuration. * * @param cfg configuration to inspect * @param section the section * @param iter function to call on each option * @param iter_cls closure for @a iter */ void GNUNET_CONFIGURATION_iterate_section_values (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, GNUNET_CONFIGURATION_Iterator iter, void *iter_cls) { struct ConfigSection *spos; struct ConfigEntry *epos; spos = cfg->sections; while ((spos != NULL) && (0 != strcasecmp (spos->name, section))) spos = spos->next; if (NULL == spos) return; for (epos = spos->entries; NULL != epos; epos = epos->next) if (NULL != epos->val) iter (iter_cls, spos->name, epos->key, epos->val); } /** * Iterate over all sections in the configuration. * * @param cfg configuration to inspect * @param iter function to call on each section * @param iter_cls closure for @a iter */ void GNUNET_CONFIGURATION_iterate_sections (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Section_Iterator iter, void *iter_cls) { struct ConfigSection *spos; struct ConfigSection *next; next = cfg->sections; while (next != NULL) { spos = next; next = spos->next; iter (iter_cls, spos->name); } } /** * Remove the given section and all options in it. * * @param cfg configuration to inspect * @param section name of the section to remove */ void GNUNET_CONFIGURATION_remove_section (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section) { struct ConfigSection *spos; struct ConfigSection *prev; struct ConfigEntry *ent; prev = NULL; spos = cfg->sections; while (NULL != spos) { if (0 == strcasecmp (section, spos->name)) { if (NULL == prev) cfg->sections = spos->next; else prev->next = spos->next; while (NULL != (ent = spos->entries)) { spos->entries = ent->next; GNUNET_free (ent->key); GNUNET_free_non_null (ent->val); GNUNET_free (ent); cfg->dirty = GNUNET_YES; } GNUNET_free (spos->name); GNUNET_free (spos); return; } prev = spos; spos = spos->next; } } /** * Copy a configuration value to the given target configuration. * Overwrites existing entries. * * @param cls the destination configuration (`struct GNUNET_CONFIGURATION_Handle *`) * @param section section for the value * @param option option name of the value * @param value value to copy */ static void copy_entry (void *cls, const char *section, const char *option, const char *value) { struct GNUNET_CONFIGURATION_Handle *dst = cls; GNUNET_CONFIGURATION_set_value_string (dst, section, option, value); } /** * Duplicate an existing configuration object. * * @param cfg configuration to duplicate * @return duplicate configuration */ struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_dup (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_CONFIGURATION_Handle *ret; ret = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_iterate (cfg, ©_entry, ret); return ret; } /** * Find a section entry from a configuration. * * @param cfg configuration to search in * @param section name of the section to look for * @return matching entry, NULL if not found */ static struct ConfigSection * find_section (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section) { struct ConfigSection *pos; pos = cfg->sections; while ((pos != NULL) && (0 != strcasecmp (section, pos->name))) pos = pos->next; return pos; } /** * Find an entry from a configuration. * * @param cfg handle to the configuration * @param section section the option is in * @param key the option * @return matching entry, NULL if not found */ static struct ConfigEntry * find_entry (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *key) { struct ConfigSection *sec; struct ConfigEntry *pos; if (NULL == (sec = find_section (cfg, section))) return NULL; pos = sec->entries; while ((pos != NULL) && (0 != strcasecmp (key, pos->key))) pos = pos->next; return pos; } /** * A callback function, compares entries from two configurations * (default against a new configuration) and write the diffs in a * diff-configuration object (the callback object). * * @param cls the diff configuration (`struct DiffHandle *`) * @param section section for the value (of the default conf.) * @param option option name of the value (of the default conf.) * @param value value to copy (of the default conf.) */ static void compare_entries (void *cls, const char *section, const char *option, const char *value) { struct DiffHandle *dh = cls; struct ConfigEntry *entNew; entNew = find_entry (dh->cfg_default, section, option); if ( (NULL != entNew) && (NULL != entNew->val) && (0 == strcmp (entNew->val, value)) ) return; GNUNET_CONFIGURATION_set_value_string (dh->cfgDiff, section, option, value); } /** * Compute configuration with only entries that have been changed * * @param cfg_default original configuration * @param cfg_new new configuration * @return configuration with only the differences, never NULL */ struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new) { struct DiffHandle diffHandle; diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (); diffHandle.cfg_default = cfg_default; GNUNET_CONFIGURATION_iterate (cfg_new, &compare_entries, &diffHandle); return diffHandle.cfgDiff; } /** * Write only configuration entries that have been changed to configuration file * * @param cfg_default default configuration * @param cfg_new new configuration * @param filename where to write the configuration diff between default and new * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle *cfg_default, const struct GNUNET_CONFIGURATION_Handle *cfg_new, const char *filename) { int ret; struct GNUNET_CONFIGURATION_Handle *diff; diff = GNUNET_CONFIGURATION_get_diff (cfg_default, cfg_new); ret = GNUNET_CONFIGURATION_write (diff, filename); GNUNET_CONFIGURATION_destroy (diff); return ret; } /** * Set a configuration value that should be a string. * * @param cfg configuration to update * @param section section of interest * @param option option of interest * @param value value to set */ void GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value) { struct ConfigSection *sec; struct ConfigEntry *e; char *nv; e = find_entry (cfg, section, option); if (NULL != e) { if (NULL == value) { GNUNET_free_non_null (e->val); e->val = NULL; } else { nv = GNUNET_strdup (value); GNUNET_free_non_null (e->val); e->val = nv; } return; } sec = find_section (cfg, section); if (sec == NULL) { sec = GNUNET_new (struct ConfigSection); sec->name = GNUNET_strdup (section); sec->next = cfg->sections; cfg->sections = sec; } e = GNUNET_new (struct ConfigEntry); e->key = GNUNET_strdup (option); e->val = GNUNET_strdup (value); e->next = sec->entries; sec->entries = e; } /** * Set a configuration value that should be a number. * * @param cfg configuration to update * @param section section of interest * @param option option of interest * @param number value to set */ void GNUNET_CONFIGURATION_set_value_number (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long number) { char s[64]; GNUNET_snprintf (s, 64, "%llu", number); GNUNET_CONFIGURATION_set_value_string (cfg, section, option, s); } /** * Get a configuration value that should be a number. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param number where to store the numeric value of the option * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_number (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number) { struct ConfigEntry *e; if (NULL == (e = find_entry (cfg, section, option))) return GNUNET_SYSERR; if (NULL == e->val) return GNUNET_SYSERR; if (1 != SSCANF (e->val, "%llu", number)) return GNUNET_SYSERR; return GNUNET_OK; } /** * Get a configuration value that should be a relative time. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param time set to the time value stored in the configuration * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_time (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time) { struct ConfigEntry *e; if (NULL == (e = find_entry (cfg, section, option))) return GNUNET_SYSERR; if (NULL == e->val) return GNUNET_SYSERR; return GNUNET_STRINGS_fancy_time_to_relative (e->val, time); } /** * Get a configuration value that should be a size in bytes. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param size set to the size in bytes as stored in the configuration * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_size (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size) { struct ConfigEntry *e; if (NULL == (e = find_entry (cfg, section, option))) return GNUNET_SYSERR; if (NULL == e->val) return GNUNET_SYSERR; return GNUNET_STRINGS_fancy_size_to_bytes (e->val, size); } /** * Get a configuration value that should be a string. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param value will be set to a freshly allocated configuration * value, or NULL if option is not specified * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value) { struct ConfigEntry *e; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to retrieve string `%s' in section `%s'\n", option, section); if ( (NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val) ) { *value = NULL; return GNUNET_SYSERR; } *value = GNUNET_strdup (e->val); return GNUNET_OK; } /** * Get a configuration value that should be in a set of * predefined strings * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param choices NULL-terminated list of legal values * @param value will be set to an entry in the legal list, * or NULL if option is not specified and no default given * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_choice (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value) { struct ConfigEntry *e; unsigned int i; if (NULL == (e = find_entry (cfg, section, option))) return GNUNET_SYSERR; for (i = 0; NULL != choices[i]; i++) if (0 == strcasecmp (choices[i], e->val)) break; if (NULL == choices[i]) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Configuration value '%s' for '%s'" " in section '%s' is not in set of legal choices\n"), e->val, option, section); return GNUNET_SYSERR; } *value = choices[i]; return GNUNET_OK; } /** * Test if we have a value for a particular option * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @return #GNUNET_YES if so, #GNUNET_NO if not. */ int GNUNET_CONFIGURATION_have_value (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option) { struct ConfigEntry *e; if ((NULL == (e = find_entry (cfg, section, option))) || (NULL == e->val)) return GNUNET_NO; return GNUNET_YES; } /** * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" * where either in the "PATHS" section or the environtment "FOO" is * set to "DIRECTORY". We also support default expansion, * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is * set in PATHS or the environment, and otherwise to "default". Note * that "default" itself can also be a $-expression, thus * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined * to VAR2. * * @param cfg configuration to use for path expansion * @param orig string to $-expand (will be freed!) * @param depth recursion depth, used to detect recursive expansions * @return $-expanded string */ static char * expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig, unsigned int depth) { int i; char *prefix; char *result; char *start; const char *post; const char *env; char *def; char *end; unsigned int lopen; char erased_char; char *erased_pos; size_t len; if (NULL == orig) return NULL; if (depth > 128) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Recursive expansion suspected, aborting $-expansion for term `%s'\n"), orig); return orig; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to $-expand %s\n", orig); if ('$' != orig[0]) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Doesn't start with $ - not expanding\n"); return orig; } erased_char = 0; erased_pos = NULL; if ('{' == orig[1]) { start = &orig[2]; lopen = 1; end = &orig[1]; while (lopen > 0) { end++; switch (*end) { case '}': lopen--; break; case '{': lopen++; break; case '\0': LOG (GNUNET_ERROR_TYPE_WARNING, _("Missing closing `%s' in option `%s'\n"), "}", orig); return orig; default: break; } } erased_char = *end; erased_pos = end; *end = '\0'; post = end + 1; def = strchr (orig, ':'); if (NULL != def) { *def = '\0'; def++; if ( ('-' == *def) || ('=' == *def) ) def++; def = GNUNET_strdup (def); } } else { start = &orig[1]; def = NULL; i = 0; while ( (orig[i] != '/') && (orig[i] != '\\') && (orig[i] != '\0') && (orig[i] != ' ') ) i++; if (orig[i] == '\0') { post = ""; } else { erased_char = orig[i]; erased_pos = &orig[i]; orig[i] = '\0'; post = &orig[i + 1]; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Split into `%s' and `%s' with default %s\n", start, post, def); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", start, &prefix)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Filename for `%s' is not in PATHS config section\n", start); if (NULL == (env = getenv (start))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "`%s' is not an environment variable\n", start); /* try default */ def = expand_dollar (cfg, def, depth + 1); env = def; } if (NULL == env) { start = GNUNET_strdup (start); if (erased_pos) *erased_pos = erased_char; LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to expand `%s' in `%s' as it is neither found in [PATHS] nor defined as an environmental variable\n"), start, orig); GNUNET_free (start); return orig; } prefix = GNUNET_strdup (env); } prefix = GNUNET_CONFIGURATION_expand_dollar (cfg, prefix); LOG (GNUNET_ERROR_TYPE_DEBUG, "Prefix is `%s'\n", prefix); if ( (erased_pos) && ('}' != erased_char) ) { len = strlen (prefix) + 1; prefix = GNUNET_realloc (prefix, len + 1); prefix[len - 1] = erased_char; prefix[len] = '\0'; } result = GNUNET_malloc (strlen (prefix) + strlen (post) + 1); strcpy (result, prefix); strcat (result, post); GNUNET_free_non_null (def); GNUNET_free (prefix); GNUNET_free (orig); LOG (GNUNET_ERROR_TYPE_DEBUG, "Expanded to `%s'\n", result); return result; } /** * Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" * where either in the "PATHS" section or the environtment "FOO" is * set to "DIRECTORY". We also support default expansion, * i.e. ${VARIABLE:-default} will expand to $VARIABLE if VARIABLE is * set in PATHS or the environment, and otherwise to "default". Note * that "default" itself can also be a $-expression, thus * "${VAR1:-{$VAR2}}" will expand to VAR1 and if that is not defined * to VAR2. * * @param cfg configuration to use for path expansion * @param orig string to $-expand (will be freed!). Note that multiple * $-expressions can be present in this string. They will all be * $-expanded. * @return $-expanded string */ char * GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig) { char *dup; size_t i; size_t len; for (i = 0; '\0' != orig[i]; i++) { if ('$' != orig[i]) continue; dup = GNUNET_strdup (orig + i); dup = expand_dollar (cfg, dup, 0); len = strlen (dup) + 1; orig = GNUNET_realloc (orig, i + len); memcpy (orig + i, dup, len); GNUNET_free (dup); } return orig; } /** * Get a configuration value that should be a string. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param value will be set to a freshly allocated configuration * value, or NULL if option is not specified * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_get_value_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value) { char *tmp; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to retrieve filename `%s' in section `%s'\n", option, section); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to retrieve filename\n"); *value = NULL; return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Retrieved filename `%s', $-expanding\n", tmp); tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp); LOG (GNUNET_ERROR_TYPE_DEBUG, "Expanded to filename `%s', *nix-expanding\n", tmp); *value = GNUNET_STRINGS_filename_expand (tmp); GNUNET_free (tmp); LOG (GNUNET_ERROR_TYPE_DEBUG, "Filename result is `%s'\n", *value); if (*value == NULL) return GNUNET_SYSERR; return GNUNET_OK; } /** * Get a configuration value that should be in a set of * "YES" or "NO". * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @return #GNUNET_YES, #GNUNET_NO or #GNUNET_SYSERR */ int GNUNET_CONFIGURATION_get_value_yesno (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option) { static const char *yesno[] = { "YES", "NO", NULL }; const char *val; int ret; ret = GNUNET_CONFIGURATION_get_value_choice (cfg, section, option, yesno, &val); if (ret == GNUNET_SYSERR) return ret; if (val == yesno[0]) return GNUNET_YES; return GNUNET_NO; } /** * Iterate over the set of filenames stored in a configuration value. * * @param cfg configuration to inspect * @param section section of interest * @param option option of interest * @param cb function to call on each filename * @param cb_cls closure for @a cb * @return number of filenames iterated over, -1 on error */ int GNUNET_CONFIGURATION_iterate_value_filenames (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, GNUNET_FileNameCallback cb, void *cb_cls) { char *list; char *pos; char *end; char old; int ret; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list)) return 0; GNUNET_assert (list != NULL); ret = 0; pos = list; while (1) { while (pos[0] == ' ') pos++; if (strlen (pos) == 0) break; end = pos + 1; while ((end[0] != ' ') && (end[0] != '\0')) { if (end[0] == '\\') { switch (end[1]) { case '\\': case ' ': memmove (end, &end[1], strlen (&end[1]) + 1); case '\0': /* illegal, but just keep it */ break; default: /* illegal, but just ignore that there was a '/' */ break; } } end++; } old = end[0]; end[0] = '\0'; if (strlen (pos) > 0) { ret++; if ((cb != NULL) && (GNUNET_OK != cb (cb_cls, pos))) { ret = GNUNET_SYSERR; break; } } if (old == '\0') break; pos = end + 1; } GNUNET_free (list); return ret; } /** * FIXME. * * @param value FIXME * @return FIXME */ static char * escape_name (const char *value) { char *escaped; const char *rpos; char *wpos; escaped = GNUNET_malloc (strlen (value) * 2 + 1); memset (escaped, 0, strlen (value) * 2 + 1); rpos = value; wpos = escaped; while (rpos[0] != '\0') { switch (rpos[0]) { case '\\': case ' ': wpos[0] = '\\'; wpos[1] = rpos[0]; wpos += 2; break; default: wpos[0] = rpos[0]; wpos++; } rpos++; } return escaped; } /** * FIXME. * * @param cls string we compare with (const char*) * @param fn filename we are currently looking at * @return #GNUNET_OK if the names do not match, #GNUNET_SYSERR if they do */ static int test_match (void *cls, const char *fn) { const char *of = cls; return (0 == strcmp (of, fn)) ? GNUNET_SYSERR : GNUNET_OK; } /** * Append a filename to a configuration value that * represents a list of filenames * * @param cfg configuration to update * @param section section of interest * @param option option of interest * @param value filename to append * @return #GNUNET_OK on success, * #GNUNET_NO if the filename already in the list * #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_append_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value) { char *escaped; char *old; char *nw; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_iterate_value_filenames (cfg, section, option, &test_match, (void *) value)) return GNUNET_NO; /* already exists */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &old)) old = GNUNET_strdup (""); escaped = escape_name (value); nw = GNUNET_malloc (strlen (old) + strlen (escaped) + 2); strcpy (nw, old); if (strlen (old) > 0) strcat (nw, " "); strcat (nw, escaped); GNUNET_CONFIGURATION_set_value_string (cfg, section, option, nw); GNUNET_free (old); GNUNET_free (nw); GNUNET_free (escaped); return GNUNET_OK; } /** * Remove a filename from a configuration value that * represents a list of filenames * * @param cfg configuration to update * @param section section of interest * @param option option of interest * @param value filename to remove * @return #GNUNET_OK on success, * #GNUNET_NO if the filename is not in the list, * #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_remove_value_filename (struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value) { char *list; char *pos; char *end; char *match; char old; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &list)) return GNUNET_NO; match = escape_name (value); pos = list; while (1) { while (pos[0] == ' ') pos++; if (strlen (pos) == 0) break; end = pos + 1; while ((end[0] != ' ') && (end[0] != '\0')) { if (end[0] == '\\') { switch (end[1]) { case '\\': case ' ': end++; break; case '\0': /* illegal, but just keep it */ break; default: /* illegal, but just ignore that there was a '/' */ break; } } end++; } old = end[0]; end[0] = '\0'; if (0 == strcmp (pos, match)) { if (old != '\0') memmove (pos, &end[1], strlen (&end[1]) + 1); else { if (pos != list) pos[-1] = '\0'; else pos[0] = '\0'; } GNUNET_CONFIGURATION_set_value_string (cfg, section, option, list); GNUNET_free (list); GNUNET_free (match); return GNUNET_OK; } if (old == '\0') break; end[0] = old; pos = end + 1; } GNUNET_free (list); GNUNET_free (match); return GNUNET_NO; } /** * Wrapper around #GNUNET_CONFIGURATION_parse. Called on each * file in a directory, we trigger parsing on those files that * end with ".conf". * * @param cls the cfg * @param filename file to parse * @return #GNUNET_OK on success */ static int parse_configuration_file (void *cls, const char *filename) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; char * ext; int ret; /* Examine file extension */ ext = strrchr (filename, '.'); if ((NULL == ext) || (0 != strcmp (ext, ".conf"))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Skipping file `%s'\n", filename); return GNUNET_OK; } ret = GNUNET_CONFIGURATION_parse (cfg, filename); return ret; } /** * Load default configuration. This function will parse the * defaults from the given defaults_d directory. * * @param cfg configuration to update * @param defaults_d directory with the defaults * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_load_from (struct GNUNET_CONFIGURATION_Handle *cfg, const char *defaults_d) { if (GNUNET_SYSERR == GNUNET_DISK_directory_scan (defaults_d, &parse_configuration_file, cfg)) return GNUNET_SYSERR; /* no configuration at all found */ return GNUNET_OK; } /** * Load configuration (starts with defaults, then loads * system-specific configuration). * * @param cfg configuration to update * @param filename name of the configuration file, NULL to load defaults * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_CONFIGURATION_load (struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename) { char *baseconfig; char *ipath; ipath = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); if (NULL == ipath) return GNUNET_SYSERR; baseconfig = NULL; GNUNET_asprintf (&baseconfig, "%s%s", ipath, "config.d"); GNUNET_free (ipath); if (GNUNET_SYSERR == GNUNET_DISK_directory_scan (baseconfig, &parse_configuration_file, cfg)) { GNUNET_free (baseconfig); return GNUNET_SYSERR; /* no configuration at all found */ } GNUNET_free (baseconfig); if ((NULL != filename) && (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, filename))) { /* specified configuration not found */ return GNUNET_SYSERR; } if (((GNUNET_YES != GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "DEFAULTCONFIG"))) && (filename != NULL)) GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG", filename); return GNUNET_OK; } /* end of configuration.c */ gnunet-0.10.1/src/util/test_mq_client.c0000644000175000017500000001042112242423447014736 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_mq_client.c * @brief tests for mq with connection client */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 23336 #define MY_TYPE 128 static struct GNUNET_SERVER_Handle *server; static struct GNUNET_CLIENT_Connection *client; static struct GNUNET_CONFIGURATION_Handle *cfg; static int ok; static int notify = GNUNET_NO; static int received = 0; static void recv_cb (void *cls, struct GNUNET_SERVER_Client *argclient, const struct GNUNET_MessageHeader *message) { received++; if (received == 2) { GNUNET_SERVER_receive_done (argclient, GNUNET_NO); return; } /* can happen if notify does not work */ GNUNET_assert (received < 2); GNUNET_SERVER_receive_done (argclient, GNUNET_YES); } static void clean_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SERVER_destroy (server); server = NULL; GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; } /** * Functions with this signature are called whenever a client * is disconnected on the network level. * * @param cls closure * @param client identification of the client */ static void notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { if (client == NULL) return; ok = 0; GNUNET_SCHEDULER_add_now (&clean_up, NULL); } static struct GNUNET_SERVER_MessageHandler handlers[] = { {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; static void send_cb (void *cls) { /* the notify should only be called once */ GNUNET_assert (GNUNET_NO == notify); notify = GNUNET_YES; } static void test_mq (struct GNUNET_CLIENT_Connection *client) { struct GNUNET_MQ_Handle *mq; struct GNUNET_MQ_Envelope *mqm; /* FIXME: test handling responses */ mq = GNUNET_MQ_queue_for_connection_client (client, NULL, NULL, NULL); mqm = GNUNET_MQ_msg_header (MY_TYPE); GNUNET_MQ_send (mq, mqm); mqm = GNUNET_MQ_msg_header (MY_TYPE); GNUNET_MQ_notify_sent (mqm, send_cb, NULL); GNUNET_MQ_send (mq, mqm); /* FIXME: add a message that will be canceled */ } static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_in sa; struct sockaddr *sap[2]; socklen_t slens[2]; sap[0] = (struct sockaddr *) &sa; slens[0] = sizeof (sa); sap[1] = NULL; slens[1] = 0; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); server = GNUNET_SERVER_create (NULL, NULL, sap, slens, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_NO); GNUNET_assert (server != NULL); handlers[0].callback_cls = cls; GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, ¬ify_disconnect, cls); cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_number (cfg, "test", "PORT", PORT); GNUNET_CONFIGURATION_set_value_string (cfg, "test", "HOSTNAME", "localhost"); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); client = GNUNET_CLIENT_connect ("test", cfg); GNUNET_assert (client != NULL); test_mq (client); } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-mq-client", "INFO", NULL); ok = 1; GNUNET_SCHEDULER_run (&task, NULL); GNUNET_assert (GNUNET_YES == notify); return ok; } gnunet-0.10.1/src/util/gnunet-resolver.c0000644000175000017500000001000412225777501015064 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/gnunet-resolver.c * @brief tool to test resolver * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * Flag for reverse lookup. */ static int reverse; /** * Prints each hostname obtained from DNS. * * @param cls closure (unused) * @param hostname one of the names for the host, NULL * on the last call to the callback */ static void print_hostname (void *cls, const char *hostname) { if (NULL == hostname) return; FPRINTF (stdout, "%s\n", hostname); } /** * Callback function to display address. * * @param cls closure (unused) * @param addr one of the addresses of the host, NULL for the last address * @param addrlen length of the address */ static void print_sockaddr (void *cls, const struct sockaddr *addr, socklen_t addrlen) { if (NULL == addr) return; FPRINTF (stdout, "%s\n", GNUNET_a2s (addr, addrlen)); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { const struct sockaddr *sa; socklen_t salen; struct sockaddr_in v4; struct sockaddr_in6 v6; if (args[0] == NULL) return; if (! reverse) { GNUNET_RESOLVER_ip_get (args[0], AF_UNSPEC, GET_TIMEOUT, &print_sockaddr, NULL); return; } sa = NULL; memset (&v4, 0, sizeof (v4)); v4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif if (1 == inet_pton (AF_INET, args[0], &v4.sin_addr)) { sa = (struct sockaddr *) &v4; salen = sizeof (v4); } memset (&v6, 0, sizeof (v6)); v6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (v6); #endif if (1 == inet_pton (AF_INET6, args[0], &v6.sin6_addr)) { sa = (struct sockaddr *) &v6; salen = sizeof (v6); } if (NULL == sa) { fprintf (stderr, "`%s' is not a valid IP: %s\n", args[0], strerror (errno)); return; } GNUNET_RESOLVER_hostname_get (sa, salen, GNUNET_YES, GET_TIMEOUT, &print_hostname, NULL); } /** * The main function to access GNUnet's DNS resolver. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'r', "reverse", NULL, gettext_noop ("perform a reverse lookup"), 0, &GNUNET_GETOPT_set_one, &reverse }, GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-resolver [hostname]", gettext_noop ("Use build-in GNUnet stub resolver"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-resolver.c */ gnunet-0.10.1/src/util/resolver.conf.in0000644000175000017500000000061412250373167014702 00000000000000[resolver] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2089 HOSTNAME = localhost BINARY = gnunet-service-resolver ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = NO # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = gnunet-0.10.1/src/util/test_crypto_random.c0000644000175000017500000000354312225777501015656 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_crypto_random.c * @brief testcase for crypto_random.c */ #include "platform.h" #include "gnunet_util_lib.h" static int test (enum GNUNET_CRYPTO_Quality mode) { int buf[1024]; unsigned int *b2; int i; unsigned long long n; for (i = 0; i < 1024; i++) GNUNET_break (1024 > (buf[i] = GNUNET_CRYPTO_random_u32 (mode, 1024))); for (i = 0; i < 10; i++) { b2 = GNUNET_CRYPTO_random_permute (mode, 1024); if (0 == memcmp (b2, buf, sizeof (buf))) { FPRINTF (stderr, "%s", "!"); GNUNET_free (b2); continue; } GNUNET_free (b2); break; } if (i == 10) return 1; /* virtually impossible... */ for (n = 10; n < 1024LL * 1024LL * 1024LL; n *= 10) GNUNET_break (n > GNUNET_CRYPTO_random_u64 (mode, n)); return 0; } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-crypto-random", "WARNING", NULL); if (0 != test (GNUNET_CRYPTO_QUALITY_WEAK)) return 1; if (0 != test (GNUNET_CRYPTO_QUALITY_STRONG)) return 1; return 0; } gnunet-0.10.1/src/util/container_bloomfilter.c0000644000175000017500000005444612255010512016310 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2006, 2008, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/container_bloomfilter.c * @brief data structure used to reduce disk accesses. * * The idea basically: Create a signature for each element in the * database. Add those signatures to a bit array. When doing a lookup, * check if the bit array matches the signature of the requested * element. If yes, address the disk, otherwise return 'not found'. * * A property of the bloom filter is that sometimes we will have * a match even if the element is not on the disk (then we do * an unnecessary disk access), but what's most important is that * we never get a single "false negative". * * To be able to delete entries from the bloom filter, we maintain * a 4 bit counter in the file on the drive (we still use only one * bit in memory). * * @author Igor Wronsky * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) struct GNUNET_CONTAINER_BloomFilter { /** * The actual bloomfilter bit array */ char *bitArray; /** * Filename of the filter */ char *filename; /** * The bit counter file on disk */ struct GNUNET_DISK_FileHandle *fh; /** * How many bits we set for each stored element */ unsigned int addressesPerElement; /** * Size of bitArray in bytes */ size_t bitArraySize; }; /** * Get the number of the addresses set per element in the bloom filter. * * @param bf the filter * @return addresses set per element in the bf */ size_t GNUNET_CONTAINER_bloomfilter_get_element_addresses (const struct GNUNET_CONTAINER_BloomFilter *bf) { if (bf == NULL) return 0; return bf->addressesPerElement; } /** * Get size of the bloom filter. * * @param bf the filter * @return number of bytes used for the data of the bloom filter */ size_t GNUNET_CONTAINER_bloomfilter_get_size (const struct GNUNET_CONTAINER_BloomFilter *bf) { if (bf == NULL) return 0; return bf->bitArraySize; } /** * Copy an existing memory. Any association with a file * on-disk will be lost in the process. * @param bf the filter to copy * @return copy of the bf */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_copy (const struct GNUNET_CONTAINER_BloomFilter *bf) { return GNUNET_CONTAINER_bloomfilter_init (bf->bitArray, bf->bitArraySize, bf->addressesPerElement); } /** * Sets a bit active in the bitArray. Increment bit-specific * usage counter on disk only if below 4bit max (==15). * * @param bitArray memory area to set the bit in * @param bitIdx which bit to set */ static void setBit (char *bitArray, unsigned int bitIdx) { size_t arraySlot; unsigned int targetBit; arraySlot = bitIdx / 8; targetBit = (1L << (bitIdx % 8)); bitArray[arraySlot] |= targetBit; } /** * Clears a bit from bitArray. Bit is cleared from the array * only if the respective usage counter on the disk hits/is zero. * * @param bitArray memory area to set the bit in * @param bitIdx which bit to unset */ static void clearBit (char *bitArray, unsigned int bitIdx) { size_t slot; unsigned int targetBit; slot = bitIdx / 8; targetBit = (1L << (bitIdx % 8)); bitArray[slot] = bitArray[slot] & (~targetBit); } /** * Checks if a bit is active in the bitArray * * @param bitArray memory area to set the bit in * @param bitIdx which bit to test * @return GNUNET_YES if the bit is set, GNUNET_NO if not. */ static int testBit (char *bitArray, unsigned int bitIdx) { size_t slot; unsigned int targetBit; slot = bitIdx / 8; targetBit = (1L << (bitIdx % 8)); if (bitArray[slot] & targetBit) return GNUNET_YES; else return GNUNET_NO; } /** * Sets a bit active in the bitArray and increments * bit-specific usage counter on disk (but only if * the counter was below 4 bit max (==15)). * * @param bitArray memory area to set the bit in * @param bitIdx which bit to test * @param fh A file to keep the 4 bit address usage counters in */ static void incrementBit (char *bitArray, unsigned int bitIdx, const struct GNUNET_DISK_FileHandle *fh) { off_t fileSlot; unsigned char value; unsigned int high; unsigned int low; unsigned int targetLoc; setBit (bitArray, bitIdx); if (GNUNET_DISK_handle_invalid (fh)) return; /* Update the counter file on disk */ fileSlot = bitIdx / 2; targetLoc = bitIdx % 2; GNUNET_assert (fileSlot == GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET)); if (1 != GNUNET_DISK_file_read (fh, &value, 1)) value = 0; low = value & 0xF; high = (value & (~0xF)) >> 4; if (targetLoc == 0) { if (low < 0xF) low++; } else { if (high < 0xF) high++; } value = ((high << 4) | low); GNUNET_assert (fileSlot == GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET)); GNUNET_assert (1 == GNUNET_DISK_file_write (fh, &value, 1)); } /** * Clears a bit from bitArray if the respective usage * counter on the disk hits/is zero. * * @param bitArray memory area to set the bit in * @param bitIdx which bit to test * @param fh A file to keep the 4bit address usage counters in */ static void decrementBit (char *bitArray, unsigned int bitIdx, const struct GNUNET_DISK_FileHandle *fh) { off_t fileslot; unsigned char value; unsigned int high; unsigned int low; unsigned int targetLoc; if (GNUNET_DISK_handle_invalid (fh)) return; /* cannot decrement! */ /* Each char slot in the counter file holds two 4 bit counters */ fileslot = bitIdx / 2; targetLoc = bitIdx % 2; if (GNUNET_SYSERR == GNUNET_DISK_file_seek (fh, fileslot, GNUNET_DISK_SEEK_SET)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "seek"); return; } if (1 != GNUNET_DISK_file_read (fh, &value, 1)) value = 0; low = value & 0xF; high = (value & 0xF0) >> 4; /* decrement, but once we have reached the max, never go back! */ if (targetLoc == 0) { if ((low > 0) && (low < 0xF)) low--; if (low == 0) { clearBit (bitArray, bitIdx); } } else { if ((high > 0) && (high < 0xF)) high--; if (high == 0) { clearBit (bitArray, bitIdx); } } value = ((high << 4) | low); if (GNUNET_SYSERR == GNUNET_DISK_file_seek (fh, fileslot, GNUNET_DISK_SEEK_SET)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "seek"); return; } GNUNET_assert (1 == GNUNET_DISK_file_write (fh, &value, 1)); } #define BUFFSIZE 65536 /** * Creates a file filled with zeroes * * @param fh the file handle * @param size the size of the file * @return GNUNET_OK if created ok, GNUNET_SYSERR otherwise */ static int make_empty_file (const struct GNUNET_DISK_FileHandle *fh, size_t size) { char buffer[BUFFSIZE]; size_t bytesleft = size; int res = 0; if (GNUNET_DISK_handle_invalid (fh)) return GNUNET_SYSERR; memset (buffer, 0, sizeof (buffer)); GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_SET); while (bytesleft > 0) { if (bytesleft > sizeof (buffer)) { res = GNUNET_DISK_file_write (fh, buffer, sizeof (buffer)); if (res >= 0) bytesleft -= res; } else { res = GNUNET_DISK_file_write (fh, buffer, bytesleft); if (res >= 0) bytesleft -= res; } if (GNUNET_SYSERR == res) return GNUNET_SYSERR; } return GNUNET_OK; } /* ************** GNUNET_CONTAINER_BloomFilter iterator ********* */ /** * Iterator (callback) method to be called by the * bloomfilter iterator on each bit that is to be * set or tested for the key. * * @param cls closure * @param bf the filter to manipulate * @param bit the current bit * @return GNUNET_YES to continue, GNUNET_NO to stop early */ typedef int (*BitIterator) (void *cls, const struct GNUNET_CONTAINER_BloomFilter * bf, unsigned int bit); /** * Call an iterator for each bit that the bloomfilter * must test or set for this element. * * @param bf the filter * @param callback the method to call * @param arg extra argument to callback * @param key the key for which we iterate over the BF bits */ static void iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, BitIterator callback, void *arg, const struct GNUNET_HashCode *key) { struct GNUNET_HashCode tmp[2]; int bitCount; unsigned int round; unsigned int slot = 0; bitCount = bf->addressesPerElement; tmp[0] = *key; round = 0; GNUNET_assert (bf->bitArraySize > 0); GNUNET_assert (bf->bitArraySize * 8LL > bf->bitArraySize); while (bitCount > 0) { while (slot < (sizeof (struct GNUNET_HashCode) / sizeof (uint32_t))) { if (GNUNET_YES != callback (arg, bf, ntohl ((((uint32_t *) & tmp[round & 1])[slot])) % ((bf->bitArraySize * 8LL)))) return; slot++; bitCount--; if (bitCount == 0) break; } if (bitCount > 0) { GNUNET_CRYPTO_hash (&tmp[round & 1], sizeof (struct GNUNET_HashCode), &tmp[(round + 1) & 1]); round++; slot = 0; } } } /** * Callback: increment bit * * @param cls pointer to writeable form of bf * @param bf the filter to manipulate * @param bit the bit to increment * @return GNUNET_YES */ static int incrementBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit) { struct GNUNET_CONTAINER_BloomFilter *b = cls; incrementBit (b->bitArray, bit, bf->fh); return GNUNET_YES; } /** * Callback: decrement bit * * @param cls pointer to writeable form of bf * @param bf the filter to manipulate * @param bit the bit to decrement * @return GNUNET_YES */ static int decrementBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit) { struct GNUNET_CONTAINER_BloomFilter *b = cls; decrementBit (b->bitArray, bit, bf->fh); return GNUNET_YES; } /** * Callback: test if all bits are set * * @param cls pointer set to GNUNET_NO if bit is not set * @param bf the filter * @param bit the bit to test * @return YES if the bit is set, NO if not */ static int testBitCallback (void *cls, const struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit) { int *arg = cls; if (GNUNET_NO == testBit (bf->bitArray, bit)) { *arg = GNUNET_NO; return GNUNET_NO; } return GNUNET_YES; } /* *********************** INTERFACE **************** */ /** * Load a bloom-filter from a file. * * @param filename the name of the file (or the prefix) * @param size the size of the bloom-filter (number of * bytes of storage space to use); will be rounded up * to next power of 2 * @param k the number of GNUNET_CRYPTO_hash-functions to apply per * element (number of bits set per element in the set) * @return the bloomfilter */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_load (const char *filename, size_t size, unsigned int k) { struct GNUNET_CONTAINER_BloomFilter *bf; char *rbuff; off_t pos; int i; size_t ui; off_t fsize; int must_read; GNUNET_assert (NULL != filename); if ((k == 0) || (size == 0)) return NULL; if (size < BUFFSIZE) size = BUFFSIZE; ui = 1; while ( (ui < size) && (ui * 2 > ui) ) ui *= 2; size = ui; /* make sure it's a power of 2 */ bf = GNUNET_new (struct GNUNET_CONTAINER_BloomFilter); /* Try to open a bloomfilter file */ if (GNUNET_YES == GNUNET_DISK_file_test (filename)) bf->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL != bf->fh) { /* file existed, try to read it! */ must_read = GNUNET_YES; if (GNUNET_OK != GNUNET_DISK_file_handle_size (bf->fh, &fsize)) { GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } if (fsize == 0) { /* found existing empty file, just overwrite */ if (GNUNET_OK != make_empty_file (bf->fh, size * 4LL)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write"); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } } else if (fsize != size * 4LL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Size of file on disk is incorrect for this Bloom filter (want %llu, have %llu)\n"), (unsigned long long) (size * 4LL), (unsigned long long) fsize); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } } else { /* file did not exist, don't read, just create */ must_read = GNUNET_NO; bf->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_READWRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == bf->fh) { GNUNET_free (bf); return NULL; } if (GNUNET_OK != make_empty_file (bf->fh, size * 4LL)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write"); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } } bf->filename = GNUNET_strdup (filename); /* Alloc block */ bf->bitArray = GNUNET_malloc_large (size); if (bf->bitArray == NULL) { if (bf->fh != NULL) GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf->filename); GNUNET_free (bf); return NULL; } bf->bitArraySize = size; bf->addressesPerElement = k; if (GNUNET_YES != must_read) return bf; /* already done! */ /* Read from the file what bits we can */ rbuff = GNUNET_malloc (BUFFSIZE); pos = 0; while (pos < size * 8LL) { int res; res = GNUNET_DISK_file_read (bf->fh, rbuff, BUFFSIZE); if (res == -1) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "read", bf->filename); GNUNET_free (rbuff); GNUNET_free (bf->filename); GNUNET_DISK_file_close (bf->fh); GNUNET_free (bf); return NULL; } if (res == 0) break; /* is ok! we just did not use that many bits yet */ for (i = 0; i < res; i++) { if ((rbuff[i] & 0x0F) != 0) setBit (bf->bitArray, pos + i * 2); if ((rbuff[i] & 0xF0) != 0) setBit (bf->bitArray, pos + i * 2 + 1); } if (res < BUFFSIZE) break; pos += BUFFSIZE * 2; /* 2 bits per byte in the buffer */ } GNUNET_free (rbuff); return bf; } /** * Create a bloom filter from raw bits. * * @param data the raw bits in memory (maybe NULL, * in which case all bits should be considered * to be zero). * @param size the size of the bloom-filter (number of * bytes of storage space to use); also size of data * -- unless data is NULL * @param k the number of GNUNET_CRYPTO_hash-functions to apply per * element (number of bits set per element in the set) * @return the bloomfilter */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_CONTAINER_bloomfilter_init (const char *data, size_t size, unsigned int k) { struct GNUNET_CONTAINER_BloomFilter *bf; if ((0 == k) || (0 == size)) return NULL; bf = GNUNET_new (struct GNUNET_CONTAINER_BloomFilter); bf->filename = NULL; bf->fh = NULL; bf->bitArray = GNUNET_malloc_large (size); if (NULL == bf->bitArray) { GNUNET_free (bf); return NULL; } bf->bitArraySize = size; bf->addressesPerElement = k; if (NULL != data) memcpy (bf->bitArray, data, size); return bf; } /** * Copy the raw data of this bloomfilter into * the given data array. * * @param bf bloomfilter to take the raw data from * @param data where to write the data * @param size the size of the given data array * @return GNUNET_SYSERR if the data array is not big enough */ int GNUNET_CONTAINER_bloomfilter_get_raw_data (const struct GNUNET_CONTAINER_BloomFilter *bf, char *data, size_t size) { if (NULL == bf) return GNUNET_SYSERR; if (bf->bitArraySize != size) return GNUNET_SYSERR; memcpy (data, bf->bitArray, size); return GNUNET_OK; } /** * Free the space associated with a filter * in memory, flush to drive if needed (do not * free the space on the drive) * * @param bf the filter */ void GNUNET_CONTAINER_bloomfilter_free (struct GNUNET_CONTAINER_BloomFilter *bf) { if (NULL == bf) return; if (bf->fh != NULL) GNUNET_DISK_file_close (bf->fh); GNUNET_free_non_null (bf->filename); GNUNET_free (bf->bitArray); GNUNET_free (bf); } /** * Reset a bloom filter to empty. Clears the file on disk. * * @param bf the filter */ void GNUNET_CONTAINER_bloomfilter_clear (struct GNUNET_CONTAINER_BloomFilter *bf) { if (NULL == bf) return; memset (bf->bitArray, 0, bf->bitArraySize); if (bf->filename != NULL) make_empty_file (bf->fh, bf->bitArraySize * 4LL); } /** * Test if an element is in the filter. * * @param e the element * @param bf the filter * @return GNUNET_YES if the element is in the filter, GNUNET_NO if not */ int GNUNET_CONTAINER_bloomfilter_test (const struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode * e) { int res; if (NULL == bf) return GNUNET_YES; res = GNUNET_YES; iterateBits (bf, &testBitCallback, &res, e); return res; } /** * Add an element to the filter * * @param bf the filter * @param e the element */ void GNUNET_CONTAINER_bloomfilter_add (struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode * e) { if (NULL == bf) return; iterateBits (bf, &incrementBitCallback, bf, e); } /** * Or the entries of the given raw data array with the * data of the given bloom filter. Assumes that * the size of the data array and the current filter * match. * * @param bf the filter * @param data the data to or-in * @param size number of bytes in data */ int GNUNET_CONTAINER_bloomfilter_or (struct GNUNET_CONTAINER_BloomFilter *bf, const char *data, size_t size) { unsigned int i; unsigned int n; unsigned long long *fc; const unsigned long long *dc; if (NULL == bf) return GNUNET_YES; if (bf->bitArraySize != size) return GNUNET_SYSERR; fc = (unsigned long long *) bf->bitArray; dc = (const unsigned long long *) data; n = size / sizeof (unsigned long long); for (i = 0; i < n; i++) fc[i] |= dc[i]; for (i = n * sizeof (unsigned long long); i < size; i++) bf->bitArray[i] |= data[i]; return GNUNET_OK; } /** * Or the entries of the given raw data array with the * data of the given bloom filter. Assumes that * the size of the data array and the current filter * match. * * @param bf the filter * @param to_or the bloomfilter to or-in * @return #GNUNET_OK on success */ int GNUNET_CONTAINER_bloomfilter_or2 (struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_CONTAINER_BloomFilter *to_or) { unsigned int i; unsigned int n; unsigned long long *fc; const unsigned long long *dc; size_t size; if (NULL == bf) return GNUNET_OK; if (bf->bitArraySize != to_or->bitArraySize) { GNUNET_break (0); return GNUNET_SYSERR; } size = bf->bitArraySize; fc = (unsigned long long *) bf->bitArray; dc = (const unsigned long long *) to_or->bitArray; n = size / sizeof (unsigned long long); for (i = 0; i < n; i++) fc[i] |= dc[i]; for (i = n * sizeof (unsigned long long); i < size; i++) bf->bitArray[i] |= to_or->bitArray[i]; return GNUNET_OK; } /** * Remove an element from the filter. * * @param bf the filter * @param e the element to remove */ void GNUNET_CONTAINER_bloomfilter_remove (struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode * e) { if (NULL == bf) return; if (bf->filename == NULL) return; iterateBits (bf, &decrementBitCallback, bf, e); } /** * Resize a bloom filter. Note that this operation * is pretty costly. Essentially, the bloom filter * needs to be completely re-build. * * @param bf the filter * @param iterator an iterator over all elements stored in the BF * @param iterator_cls argument to the iterator function * @param size the new size for the filter * @param k the new number of GNUNET_CRYPTO_hash-function to apply per element */ void GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf, GNUNET_HashCodeIterator iterator, void *iterator_cls, size_t size, unsigned int k) { struct GNUNET_HashCode hc; unsigned int i; GNUNET_free (bf->bitArray); i = 1; while (i < size) i *= 2; size = i; /* make sure it's a power of 2 */ bf->bitArraySize = size; bf->bitArray = GNUNET_malloc (size); if (bf->filename != NULL) make_empty_file (bf->fh, bf->bitArraySize * 4LL); while (GNUNET_YES == iterator (iterator_cls, &hc)) GNUNET_CONTAINER_bloomfilter_add (bf, &hc); } /* end of container_bloomfilter.c */ gnunet-0.10.1/src/util/Makefile.am0000644000175000017500000003142412320754700013616 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include plugindir = $(libdir)/gnunet libexecdir= $(pkglibdir)/libexec/ pkgcfgdir= $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ util.conf pkgcfg_DATA = \ resolver.conf if MINGW noinst_LTLIBRARIES = \ libgnunetutilwin.la libgnunetutilwin_la_SOURCES = \ win.c \ winproc.c libgnunetutilwin_la_LDFLAGS = \ -no-undefined -Wl,--export-all-symbols libgnunetutilwin_la_LIBADD = \ -lshell32 -liconv -lstdc++ \ -lcomdlg32 -lgdi32 -liphlpapi WINLIB = libgnunetutilwin.la W32CAT = w32cat W32CONSOLEHELPER = gnunet-helper-w32-console endif if !MINGW SERVER_CLIENT_UNIX = test_server_with_client_unix endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif w32cat_SOURCES = w32cat.c gnunet_helper_w32_console_SOURCES = \ gnunet-helper-w32-console.c \ gnunet-helper-w32-console.h gnunet_helper_w32_console_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_helper_w32_console_DEPENDENCIES = \ libgnunetutil.la noinst_PROGRAMS = \ gnunet-config-diff \ $(W32CAT) \ test_common_logging_dummy gnunet_config_diff_SOURCES = \ gnunet-config-diff.c gnunet_config_diff_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_config_diff_DEPENDENCIES = \ libgnunetutil.la test_common_logging_dummy_SOURCES = \ test_common_logging_dummy.c test_common_logging_dummy_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_logging_dummy_DEPENDENCIES = \ libgnunetutil.la lib_LTLIBRARIES = libgnunetutil.la libgnunetutil_la_SOURCES = \ bandwidth.c \ bio.c \ client.c \ common_allocation.c \ common_endian.c \ common_logging.c \ configuration.c \ connection.c \ container_bloomfilter.c \ container_heap.c \ container_meta_data.c \ container_multihashmap.c \ container_multipeermap.c \ container_multihashmap32.c \ container_slist.c \ crypto_symmetric.c \ crypto_crc.c \ crypto_ecc.c \ crypto_hash.c \ crypto_hkdf.c \ crypto_kdf.c \ crypto_mpi.c \ crypto_paillier.c \ crypto_random.c \ disk.c \ disk.h \ getopt.c \ getopt_helpers.c \ helper.c \ load.c \ mq.c \ network.c \ os_installation.c \ os_network.c \ os_priority.c \ peer.c \ plugin.c \ program.c \ resolver_api.c resolver.h \ scheduler.c \ server.c \ server_mst.c \ server_nc.c \ server_tc.c \ service.c \ signal.c \ strings.c \ time.c \ speedup.c speedup.h libgnunetutil_la_LIBADD = \ $(GCLIBADD) $(WINLIB) \ $(LIBGCRYPT_LIBS) \ $(LTLIBICONV) \ $(LTLIBINTL) \ -lltdl $(Z_LIBS) -lunistring $(XLIB) libgnunetutil_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 12:0:0 if HAVE_TESTING GNUNET_ECC = gnunet-ecc GNUNET_SCRYPT = gnunet-scrypt endif libexec_PROGRAMS = \ gnunet-service-resolver \ $(W32CONSOLEHELPER) bin_SCRIPTS =\ gnunet-qr bin_PROGRAMS = \ gnunet-resolver \ gnunet-config \ $(GNUNET_ECC) \ $(GNUNET_SCRYPT) \ gnunet-uri do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' gnunet-qr: gnunet-qr.py.in Makefile $(do_subst) < gnunet-qr.py.in > gnunet-qr chmod +x gnunet-qr gnunet_service_resolver_SOURCES = \ gnunet-service-resolver.c gnunet_service_resolver_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_resolver_DEPENDENCIES = \ libgnunetutil.la gnunet_resolver_SOURCES = \ gnunet-resolver.c gnunet_resolver_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_resolver_DEPENDENCIES = \ libgnunetutil.la gnunet_ecc_SOURCES = \ gnunet-ecc.c gnunet_ecc_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) -lgcrypt gnunet_ecc_DEPENDENCIES = \ libgnunetutil.la gnunet_scrypt_SOURCES = \ gnunet-scrypt.c gnunet_scrypt_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) -lgcrypt gnunet_scrypt_DEPENDENCIES = \ libgnunetutil.la gnunet_config_SOURCES = \ gnunet-config.c gnunet_config_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_config_DEPENDENCIES = \ libgnunetutil.la gnunet_uri_SOURCES = \ gnunet-uri.c gnunet_uri_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_uri_DEPENDENCIES = \ libgnunetutil.la plugin_LTLIBRARIES = \ libgnunet_plugin_test.la libgnunet_plugin_test_la_SOURCES = \ test_plugin_plug.c libgnunet_plugin_test_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) if HAVE_BENCHMARKS BENCHMARKS = \ perf_crypto_hash \ perf_crypto_symmetric \ perf_malloc endif check_PROGRAMS = \ test_bio \ test_client \ test_common_allocation \ test_common_endian \ test_common_logging \ test_configuration \ test_container_bloomfilter \ test_container_meta_data \ test_container_multihashmap \ test_container_multihashmap32 \ test_container_multipeermap \ test_container_heap \ test_container_slist \ test_crypto_symmetric \ test_crypto_crc \ test_crypto_ecdsa \ test_crypto_eddsa \ test_crypto_ecdhe \ test_crypto_hash \ test_crypto_hkdf \ test_crypto_paillier \ test_crypto_random \ test_disk \ test_getopt \ test_connection \ test_connection_addressing \ test_connection_receive_cancel \ test_connection_timeout \ test_connection_timeout_no_connect \ test_connection_transmit_cancel \ test_mq \ test_mq_client \ test_os_network \ test_peer \ test_plugin \ test_program \ test_resolver_api \ test_scheduler \ test_scheduler_delay \ test_server_mst_interrupt \ test_server \ test_server_disconnect \ test_server_with_client \ $(SERVER_CLIENT_UNIX) \ test_service \ test_strings \ test_strings_to_data \ test_time \ test_speedup \ $(BENCHMARKS) \ test_os_start_process \ test_common_logging_runtime_loglevels if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_bio_SOURCES = \ test_bio.c test_bio_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_os_start_process_SOURCES = \ test_os_start_process.c test_os_start_process_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_os_start_process_DEPENDENCIES = \ $(WINCAT) test_client_SOURCES = \ test_client.c test_client_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_allocation_SOURCES = \ test_common_allocation.c test_common_allocation_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_endian_SOURCES = \ test_common_endian.c test_common_endian_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_logging_SOURCES = \ test_common_logging.c test_common_logging_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_common_logging_runtime_loglevels_SOURCES = \ test_common_logging_runtime_loglevels.c test_common_logging_runtime_loglevels_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_configuration_SOURCES = \ test_configuration.c test_configuration_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_bloomfilter_SOURCES = \ test_container_bloomfilter.c test_container_bloomfilter_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_meta_data_SOURCES = \ test_container_meta_data.c test_container_meta_data_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la -lextractor test_container_multihashmap_SOURCES = \ test_container_multihashmap.c test_container_multihashmap_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_multihashmap32_SOURCES = \ test_container_multihashmap32.c test_container_multihashmap32_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_multipeermap_SOURCES = \ test_container_multipeermap.c test_container_multipeermap_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_heap_SOURCES = \ test_container_heap.c test_container_heap_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_container_slist_SOURCES = \ test_container_slist.c test_container_slist_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_symmetric_SOURCES = \ test_crypto_symmetric.c test_crypto_symmetric_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_crc_SOURCES = \ test_crypto_crc.c test_crypto_crc_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_ecdsa_SOURCES = \ test_crypto_ecdsa.c test_crypto_ecdsa_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) test_crypto_eddsa_SOURCES = \ test_crypto_eddsa.c test_crypto_eddsa_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) test_crypto_ecdhe_SOURCES = \ test_crypto_ecdhe.c test_crypto_ecdhe_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) test_crypto_hash_SOURCES = \ test_crypto_hash.c test_crypto_hash_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_hkdf_SOURCES = \ test_crypto_hkdf.c test_crypto_hkdf_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_paillier_SOURCES = \ test_crypto_paillier.c test_crypto_paillier_LDADD = \ -lgcrypt \ $(top_builddir)/src/util/libgnunetutil.la test_crypto_random_SOURCES = \ test_crypto_random.c test_crypto_random_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_disk_SOURCES = \ test_disk.c test_disk_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_getopt_SOURCES = \ test_getopt.c test_getopt_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_SOURCES = \ test_connection.c test_connection_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_addressing_SOURCES = \ test_connection_addressing.c test_connection_addressing_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_receive_cancel_SOURCES = \ test_connection_receive_cancel.c test_connection_receive_cancel_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_timeout_SOURCES = \ test_connection_timeout.c test_connection_timeout_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_timeout_no_connect_SOURCES = \ test_connection_timeout_no_connect.c test_connection_timeout_no_connect_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_connection_transmit_cancel_SOURCES = \ test_connection_transmit_cancel.c test_connection_transmit_cancel_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_mq_SOURCES = \ test_mq.c test_mq_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_mq_client_SOURCES = \ test_mq_client.c test_mq_client_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_os_network_SOURCES = \ test_os_network.c test_os_network_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_peer_SOURCES = \ test_peer.c test_peer_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la -lgcrypt test_plugin_SOURCES = \ test_plugin.c test_plugin_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_program_SOURCES = \ test_program.c test_program_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_resolver_api_SOURCES = \ test_resolver_api.c test_resolver_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_scheduler_SOURCES = \ test_scheduler.c test_scheduler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_scheduler_delay_SOURCES = \ test_scheduler_delay.c test_scheduler_delay_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_mst_interrupt_SOURCES = \ test_server_mst_interrupt.c test_server_mst_interrupt_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_SOURCES = \ test_server.c test_server_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_disconnect_SOURCES = \ test_server_disconnect.c test_server_disconnect_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_with_client_SOURCES = \ test_server_with_client.c test_server_with_client_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_server_with_client_unix_SOURCES = \ test_server_with_client_unix.c test_server_with_client_unix_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_service_SOURCES = \ test_service.c test_service_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_strings_SOURCES = \ test_strings.c test_strings_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_strings_to_data_SOURCES = \ test_strings_to_data.c test_strings_to_data_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_time_SOURCES = \ test_time.c test_time_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la test_speedup_SOURCES = \ test_speedup.c test_speedup_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la perf_crypto_hash_SOURCES = \ perf_crypto_hash.c perf_crypto_hash_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la perf_crypto_symmetric_SOURCES = \ perf_crypto_symmetric.c perf_crypto_symmetric_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la perf_malloc_SOURCES = \ perf_malloc.c perf_malloc_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_configuration_data.conf \ test_program_data.conf \ test_resolver_api_data.conf \ test_service_data.conf \ test_speedup_data.conf \ gnunet-qr.py.in gnunet-0.10.1/src/util/container_multihashmap32.c0000644000175000017500000003523112236140650016630 00000000000000/* This file is part of GNUnet. (C) 2008 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/container_multihashmap32.c * @brief a version of hash map implemented in container_multihashmap.c but with * uint32_t as keys * @author Christian Grothoff * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * An entry in the hash map. */ struct MapEntry { /** * Key for the entry. */ uint32_t key; /** * Value of the entry. */ void *value; /** * If there is a hash collision, we create a linked list. */ struct MapEntry *next; }; /** * Internal representation of the hash map. */ struct GNUNET_CONTAINER_MultiHashMap32 { /** * All of our buckets. */ struct MapEntry **map; /** * Number of entries in the map. */ unsigned int size; /** * Length of the "map" array. */ unsigned int map_length; /** * Counts the destructive modifications (grow, remove) * to the map, so that iterators can check if they are still valid. */ unsigned int modification_counter; }; /** * Cursor into a multihashmap. * Allows to enumerate elements asynchronously. */ struct GNUNET_CONTAINER_MultiHashMap32Iterator { /** * Position in the bucket 'idx' */ struct MapEntry *me; /** * Current bucket index. */ unsigned int idx; /** * Modification counter as observed on the map when the iterator * was created. */ unsigned int modification_counter; /** * Map that we are iterating over. */ const struct GNUNET_CONTAINER_MultiHashMap32 *map; }; /** * Create a multi hash map. * * @param len initial size (map will grow as needed) * @return NULL on error */ struct GNUNET_CONTAINER_MultiHashMap32 * GNUNET_CONTAINER_multihashmap32_create (unsigned int len) { struct GNUNET_CONTAINER_MultiHashMap32 *ret; GNUNET_assert (len > 0); ret = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMap32); ret->map = GNUNET_malloc (len * sizeof (struct MapEntry *)); ret->map_length = len; return ret; } /** * Destroy a hash map. Will not free any values * stored in the hash map! * * @param map the map */ void GNUNET_CONTAINER_multihashmap32_destroy (struct GNUNET_CONTAINER_MultiHashMap32 *map) { unsigned int i; struct MapEntry *e; for (i = 0; i < map->map_length; i++) { while (NULL != (e = map->map[i])) { map->map[i] = e->next; GNUNET_free (e); } } GNUNET_free (map->map); GNUNET_free (map); } /** * Compute the index of the bucket for the given key. * * @param m hash map for which to compute the index * @param key what key should the index be computed for * @return offset into the "map" array of "m" */ static unsigned int idx_of (const struct GNUNET_CONTAINER_MultiHashMap32 *m, const uint32_t key) { GNUNET_assert (m != NULL); return ((unsigned int) key) % m->map_length; } /** * Get the number of key-value pairs in the map. * * @param map the map * @return the number of key value pairs */ unsigned int GNUNET_CONTAINER_multihashmap32_size (const struct GNUNET_CONTAINER_MultiHashMap32 *map) { return map->size; } /** * Given a key find a value in the map matching the key. * * @param map the map * @param key what to look for * @return NULL if no value was found; note that * this is indistinguishable from values that just * happen to be NULL; use "contains" to test for * key-value pairs with value NULL */ void * GNUNET_CONTAINER_multihashmap32_get (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key) { struct MapEntry *e; e = map->map[idx_of (map, key)]; while (e != NULL) { if (key == e->key) return e->value; e = e->next; } return NULL; } /** * Iterate over all entries in the map. * * @param map the map * @param it function to call on each entry * @param it_cls extra argument to it * @return the number of key value pairs processed, * GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap32_iterate (const struct GNUNET_CONTAINER_MultiHashMap32 *map, GNUNET_CONTAINER_HashMapIterator32 it, void *it_cls) { int count; unsigned int i; struct MapEntry *e; struct MapEntry *n; count = 0; GNUNET_assert (map != NULL); for (i = 0; i < map->map_length; i++) { n = map->map[i]; while (NULL != (e = n)) { n = e->next; if (NULL != it) { if (GNUNET_OK != it (it_cls, e->key, e->value)) return GNUNET_SYSERR; } count++; } } return count; } /** * Remove the given key-value pair from the map. Note that if the * key-value pair is in the map multiple times, only one of the pairs * will be removed. * * @param map the map * @param key key of the key-value pair * @param value value of the key-value pair * @return GNUNET_YES on success, GNUNET_NO if the key-value pair * is not in the map */ int GNUNET_CONTAINER_multihashmap32_remove (struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value) { struct MapEntry *e; struct MapEntry *p; unsigned int i; map->modification_counter++; i = idx_of (map, key); p = NULL; e = map->map[i]; while (e != NULL) { if ( (key == e->key) && (value == e->value) ) { if (p == NULL) map->map[i] = e->next; else p->next = e->next; GNUNET_free (e); map->size--; return GNUNET_YES; } p = e; e = e->next; } return GNUNET_NO; } /** * Remove all entries for the given key from the map. * Note that the values would not be "freed". * * @param map the map * @param key identifies values to be removed * @return number of values removed */ int GNUNET_CONTAINER_multihashmap32_remove_all (struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key) { struct MapEntry *e; struct MapEntry *p; unsigned int i; int ret; map->modification_counter++; ret = 0; i = idx_of (map, key); p = NULL; e = map->map[i]; while (e != NULL) { if (key == e->key) { if (p == NULL) map->map[i] = e->next; else p->next = e->next; GNUNET_free (e); map->size--; if (p == NULL) e = map->map[i]; else e = p->next; ret++; } else { p = e; e = e->next; } } return ret; } /** * Check if the map contains any value under the given * key (including values that are NULL). * * @param map the map * @param key the key to test if a value exists for it * @return GNUNET_YES if such a value exists, * GNUNET_NO if not */ int GNUNET_CONTAINER_multihashmap32_contains (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key) { struct MapEntry *e; e = map->map[idx_of (map, key)]; while (e != NULL) { if (key == e->key) return GNUNET_YES; e = e->next; } return GNUNET_NO; } /** * Check if the map contains the given value under the given * key. * * @param map the map * @param key the key to test if a value exists for it * @param value value to test for * @return GNUNET_YES if such a value exists, * GNUNET_NO if not */ int GNUNET_CONTAINER_multihashmap32_contains_value (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, const void *value) { struct MapEntry *e; e = map->map[idx_of (map, key)]; while (e != NULL) { if ( (key == e->key) && (e->value == value) ) return GNUNET_YES; e = e->next; } return GNUNET_NO; } /** * Grow the given map to a more appropriate size. * * @param map the hash map to grow */ static void grow (struct GNUNET_CONTAINER_MultiHashMap32 *map) { struct MapEntry **old_map; struct MapEntry **new_map; struct MapEntry *e; unsigned int old_len; unsigned int new_len; unsigned int idx; unsigned int i; map->modification_counter++; old_map = map->map; old_len = map->map_length; new_len = old_len * 2; new_map = GNUNET_malloc (sizeof (struct MapEntry *) * new_len); map->map_length = new_len; map->map = new_map; for (i = 0; i < old_len; i++) { while (NULL != (e = old_map[i])) { old_map[i] = e->next; idx = idx_of (map, e->key); e->next = new_map[idx]; new_map[idx] = e; } } GNUNET_free (old_map); } /** * Store a key-value pair in the map. * * @param map the map * @param key key to use * @param value value to use * @param opt options for put * @return GNUNET_OK on success, * GNUNET_NO if a value was replaced (with REPLACE) * GNUNET_SYSERR if UNIQUE_ONLY was the option and the * value already exists */ int GNUNET_CONTAINER_multihashmap32_put (struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt) { struct MapEntry *e; unsigned int i; i = idx_of (map, key); if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) && (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { e = map->map[i]; while (e != NULL) { if (key == e->key) { if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) return GNUNET_SYSERR; e->value = value; return GNUNET_NO; } e = e->next; } } if (map->size / 3 >= map->map_length / 4) { grow (map); i = idx_of (map, key); } e = GNUNET_new (struct MapEntry); e->key = key; e->value = value; e->next = map->map[i]; map->map[i] = e; map->size++; return GNUNET_OK; } /** * Iterate over all entries in the map that match a particular key. * * @param map the map * @param key key that the entries must correspond to * @param it function to call on each entry * @param it_cls extra argument to it * @return the number of key value pairs processed, * GNUNET_SYSERR if it aborted iteration */ int GNUNET_CONTAINER_multihashmap32_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap32 *map, uint32_t key, GNUNET_CONTAINER_HashMapIterator32 it, void *it_cls) { int count; struct MapEntry *e; struct MapEntry *n; count = 0; n = map->map[idx_of (map, key)]; while (NULL != (e = n)) { n = e->next; if (key != e->key) continue; if ((it != NULL) && (GNUNET_OK != it (it_cls, key, e->value))) return GNUNET_SYSERR; count++; } return count; } /** * Create an iterator for a multihashmap. * The iterator can be used to retrieve all the elements in the multihashmap * one by one, without having to handle all elements at once (in contrast to * GNUNET_CONTAINER_multihashmap_iterate()). Note that the iterator can not be * used anymore if elements have been removed from 'map' after the creation of * the iterator, or 'map' has been destroyed. Adding elements to 'map' may * result in skipped or repeated elements. * * @param map the map to create an iterator for * @return an iterator over the given multihashmap 'map' */ struct GNUNET_CONTAINER_MultiHashMap32Iterator * GNUNET_CONTAINER_multihashmap32_iterator_create (const struct GNUNET_CONTAINER_MultiHashMap32 *map) { struct GNUNET_CONTAINER_MultiHashMap32Iterator *iter; iter = GNUNET_new (struct GNUNET_CONTAINER_MultiHashMap32Iterator); iter->map = map; iter->modification_counter = map->modification_counter; iter->me = map->map[0]; return iter; } /** * Retrieve the next element from the hash map at the iterator's position. * If there are no elements left, GNUNET_NO is returned, and 'key' and 'value' * are not modified. * This operation is only allowed if no elements have been removed from the * multihashmap since the creation of 'iter', and the map has not been destroyed. * Adding elements may result in repeating or skipping elements. * * @param iter the iterator to get the next element from * @param key pointer to store the key in, can be NULL * @param value pointer to store the value in, can be NULL * @return #GNUNET_YES we returned an element, * #GNUNET_NO if we are out of elements */ int GNUNET_CONTAINER_multihashmap32_iterator_next (struct GNUNET_CONTAINER_MultiHashMap32Iterator *iter, uint32_t *key, const void **value) { /* make sure the map has not been modified */ GNUNET_assert (iter->modification_counter == iter->map->modification_counter); /* look for the next entry, skipping empty buckets */ while (1) { if (iter->idx >= iter->map->map_length) return GNUNET_NO; if (NULL != iter->me) { if (NULL != key) *key = iter->me->key; if (NULL != value) *value = iter->me->value; iter->me = iter->me->next; return GNUNET_YES; } iter->idx += 1; if (iter->idx < iter->map->map_length) iter->me = iter->map->map[iter->idx]; } } /** * Destroy a multihashmap iterator. * * @param iter the iterator to destroy */ void GNUNET_CONTAINER_multihashmap32_iterator_destroy (struct GNUNET_CONTAINER_MultiHashMapIterator *iter) { GNUNET_free (iter); } /* end of container_multihashmap.c */ gnunet-0.10.1/src/util/test_container_bloomfilter.c0000644000175000017500000001430612225777501017355 00000000000000/* This file is part of GNUnet. (C) 2004, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_container_bloomfilter.c * @brief Testcase for the bloomfilter. * @author Christian Grothoff * @author Igor Wronsky */ #include "platform.h" #include "gnunet_util_lib.h" #define K 4 #define SIZE 65536 #define TESTFILE "/tmp/bloomtest.dat" /** * Generate a random hashcode. */ static void nextHC (struct GNUNET_HashCode * hc) { GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, hc); } static int add_iterator (void *cls, struct GNUNET_HashCode * next) { int *ret = cls; struct GNUNET_HashCode pos; if (0 == (*ret)--) return GNUNET_NO; nextHC (&pos); *next = pos; return GNUNET_YES; } int main (int argc, char *argv[]) { struct GNUNET_CONTAINER_BloomFilter *bf; struct GNUNET_CONTAINER_BloomFilter *bfi; struct GNUNET_HashCode tmp; int i; int ok1; int ok2; int falseok; char buf[SIZE]; struct stat sbuf; GNUNET_log_setup ("test-container-bloomfilter", "WARNING", NULL); GNUNET_CRYPTO_seed_weak_random (1); if (0 == STAT (TESTFILE, &sbuf)) if (0 != UNLINK (TESTFILE)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink", TESTFILE); bf = GNUNET_CONTAINER_bloomfilter_load (TESTFILE, SIZE, K); for (i = 0; i < 200; i++) { nextHC (&tmp); GNUNET_CONTAINER_bloomfilter_add (bf, &tmp); } GNUNET_CRYPTO_seed_weak_random (1); ok1 = 0; for (i = 0; i < 200; i++) { nextHC (&tmp); if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES) ok1++; } if (ok1 != 200) { printf ("Got %d elements out of" "200 expected after insertion.\n", ok1); GNUNET_CONTAINER_bloomfilter_free (bf); return -1; } if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_get_raw_data (bf, buf, SIZE)) { GNUNET_CONTAINER_bloomfilter_free (bf); return -1; } GNUNET_CONTAINER_bloomfilter_free (bf); bf = GNUNET_CONTAINER_bloomfilter_load (TESTFILE, SIZE, K); GNUNET_assert (bf != NULL); bfi = GNUNET_CONTAINER_bloomfilter_init (buf, SIZE, K); GNUNET_assert (bfi != NULL); GNUNET_CRYPTO_seed_weak_random (1); ok1 = 0; ok2 = 0; for (i = 0; i < 200; i++) { nextHC (&tmp); if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES) ok1++; if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES) ok2++; } if (ok1 != 200) { printf ("Got %d elements out of 200 " "expected after reloading.\n", ok1); GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); return -1; } if (ok2 != 200) { printf ("Got %d elements out of 200 " "expected after initialization.\n", ok2); GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); return -1; } GNUNET_CRYPTO_seed_weak_random (1); for (i = 0; i < 100; i++) { nextHC (&tmp); GNUNET_CONTAINER_bloomfilter_remove (bf, &tmp); GNUNET_CONTAINER_bloomfilter_remove (bfi, &tmp); } GNUNET_CRYPTO_seed_weak_random (1); ok1 = 0; ok2 = 0; for (i = 0; i < 200; i++) { nextHC (&tmp); if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES) ok1++; if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES) ok2++; } if (ok1 != 100) { printf ("Expected 100 elements in loaded filter" " after adding 200 and deleting 100, got %d\n", ok1); GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); return -1; } if (ok2 != 200) { printf ("Expected 200 elements in initialized filter" " after adding 200 and deleting 100 " "(which should do nothing for a filter not backed by a file), got %d\n", ok2); GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); return -1; } GNUNET_CRYPTO_seed_weak_random (3); GNUNET_CONTAINER_bloomfilter_clear (bf); falseok = 0; for (i = 0; i < 1000; i++) { nextHC (&tmp); if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES) falseok++; } if (falseok > 0) { GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); return -1; } if (GNUNET_OK != GNUNET_CONTAINER_bloomfilter_or (bf, buf, SIZE)) { GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); return -1; } GNUNET_CRYPTO_seed_weak_random (2); i = 20; GNUNET_CONTAINER_bloomfilter_resize (bfi, &add_iterator, &i, SIZE * 2, K); GNUNET_CRYPTO_seed_weak_random (2); i = 20; GNUNET_CONTAINER_bloomfilter_resize (bf, &add_iterator, &i, SIZE * 2, K); GNUNET_CRYPTO_seed_weak_random (2); ok1 = 0; ok2 = 0; for (i = 0; i < 20; i++) { nextHC (&tmp); if (GNUNET_CONTAINER_bloomfilter_test (bf, &tmp) == GNUNET_YES) ok1++; if (GNUNET_CONTAINER_bloomfilter_test (bfi, &tmp) == GNUNET_YES) ok2++; } if (ok1 != 20) { printf ("Expected 20 elements in resized file-backed filter" " after adding 20, got %d\n", ok1); GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); return -1; } if (ok2 != 20) { printf ("Expected 20 elements in resized filter" " after adding 20, got %d\n", ok2); GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); return -1; } GNUNET_CONTAINER_bloomfilter_free (bf); GNUNET_CONTAINER_bloomfilter_free (bfi); GNUNET_break (0 == UNLINK (TESTFILE)); return 0; } gnunet-0.10.1/src/util/test_scheduler.c0000644000175000017500000001255212226712730014746 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_scheduler.c * @brief tests for the scheduler */ #include "platform.h" #include "gnunet_util_lib.h" struct GNUNET_DISK_PipeHandle *p; static const struct GNUNET_DISK_FileHandle *fds[2]; static void task2 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; /* t3 should be ready (albeit with lower priority) */ GNUNET_assert (1 == GNUNET_SCHEDULER_get_load (GNUNET_SCHEDULER_PRIORITY_COUNT)); GNUNET_assert (2 == *ok); (*ok) = 3; } static void task3 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; GNUNET_assert (3 == *ok); (*ok) = 4; } static void taskWrt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static char c; int *ok = cls; GNUNET_assert (6 == *ok); GNUNET_assert (GNUNET_NETWORK_fdset_handle_isset (tc->write_ready, fds[1])); (*ok) = 7; GNUNET_assert (1 == GNUNET_DISK_file_write (fds[1], &c, 1)); } static void taskNeverRun (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_assert (0); } static void taskLast (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; /* t4 should be ready (albeit with lower priority) */ GNUNET_assert (8 == *ok); (*ok) = 0; } static void taskRd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static char c; int *ok = cls; GNUNET_assert (7 == *ok); GNUNET_assert (GNUNET_NETWORK_fdset_handle_isset (tc->read_ready, fds[0])); GNUNET_assert (1 == GNUNET_DISK_file_read (fds[0], &c, 1)); (*ok) = 8; GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &taskLast, cls); GNUNET_SCHEDULER_shutdown (); } static void task4 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; GNUNET_assert (4 == *ok); (*ok) = 6; p = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); GNUNET_assert (NULL != p); fds[0] = GNUNET_DISK_pipe_handle (p, GNUNET_DISK_PIPE_END_READ); fds[1] = GNUNET_DISK_pipe_handle (p, GNUNET_DISK_PIPE_END_WRITE); GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, fds[0], &taskRd, cls); GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, fds[1], &taskWrt, cls); } static void task1 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; GNUNET_assert (1 == *ok); (*ok) = 2; GNUNET_SCHEDULER_add_now (&task3, cls); GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_UI, &task2, cls); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &task4, cls); } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int check () { int ok; ok = 1; GNUNET_SCHEDULER_run (&task1, &ok); return ok; } static void taskShutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; GNUNET_assert (1 == *ok); *ok = 8; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &taskLast, cls); GNUNET_SCHEDULER_shutdown (); } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int checkShutdown () { int ok; ok = 1; GNUNET_SCHEDULER_run (&taskShutdown, &ok); return ok; } #ifndef MINGW static void taskSig (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; GNUNET_assert (1 == *ok); *ok = 8; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &taskLast, cls); GNUNET_break (0 == PLIBC_KILL (getpid (), GNUNET_TERM_SIG)); } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int checkSignal () { int ok; ok = 1; GNUNET_SCHEDULER_run (&taskSig, &ok); return ok; } #endif static void taskCancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; GNUNET_assert (1 == *ok); *ok = 0; GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_add_now (&taskNeverRun, NULL)); } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int checkCancel () { int ok; ok = 1; GNUNET_SCHEDULER_run (&taskCancel, &ok); return ok; } int main (int argc, char *argv[]) { int ret = 0; GNUNET_log_setup ("test_scheduler", "WARNING", NULL); ret += check (); #ifndef MINGW ret += checkSignal (); #endif ret += checkShutdown (); ret += checkCancel (); GNUNET_DISK_pipe_close (p); return ret; } /* end of test_scheduler.c */ gnunet-0.10.1/src/util/gnunet-config-diff.c0000644000175000017500000000113012225777501015376 00000000000000#include "platform.h" #include int main (int argc, char **argv) { struct GNUNET_CONFIGURATION_Handle *i1; struct GNUNET_CONFIGURATION_Handle *i2; if (argc != 3) { fprintf (stderr, "Invoke using `%s DEFAULTS-IN DIFFS'\n", argv[0]); return 1; } i1 = GNUNET_CONFIGURATION_create (); i2 = GNUNET_CONFIGURATION_create (); if ((GNUNET_OK != GNUNET_CONFIGURATION_load (i1, argv[1])) || (GNUNET_OK != GNUNET_CONFIGURATION_load (i2, argv[2]))) return 1; if (GNUNET_OK != GNUNET_CONFIGURATION_write_diffs (i1, i2, argv[2])) return 2; return 0; } gnunet-0.10.1/src/util/test_time.c0000644000175000017500000002175712225777501013743 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_time.c * @brief testcase for time.c */ #include "platform.h" #include "gnunet_util_lib.h" int main (int argc, char *argv[]) { struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_AbsoluteNBO nown; struct GNUNET_TIME_Absolute future; struct GNUNET_TIME_Absolute past; struct GNUNET_TIME_Absolute last; struct GNUNET_TIME_Absolute forever; struct GNUNET_TIME_Absolute zero; struct GNUNET_TIME_Relative rel; struct GNUNET_TIME_Relative relForever; struct GNUNET_TIME_Relative relUnit; struct GNUNET_TIME_RelativeNBO reln; unsigned int i; GNUNET_log_setup ("test-time", "WARNING", NULL); forever = GNUNET_TIME_UNIT_FOREVER_ABS; relForever = GNUNET_TIME_UNIT_FOREVER_REL; relUnit = GNUNET_TIME_UNIT_MILLISECONDS; zero.abs_value_us = 0; last = now = GNUNET_TIME_absolute_get (); while (now.abs_value_us == last.abs_value_us) now = GNUNET_TIME_absolute_get (); GNUNET_assert (now.abs_value_us > last.abs_value_us); /* test overflow checking in multiply */ rel = GNUNET_TIME_UNIT_MILLISECONDS; GNUNET_log_skip (1, GNUNET_NO); for (i = 0; i < 55; i++) rel = GNUNET_TIME_relative_multiply (rel, 2); GNUNET_log_skip (0, GNUNET_NO); GNUNET_assert (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us); /*check zero */ rel.rel_value_us = (UINT64_MAX) - 1024; GNUNET_assert (GNUNET_TIME_UNIT_ZERO.rel_value_us == GNUNET_TIME_relative_multiply (rel, 0).rel_value_us); /* test infinity-check for relative to absolute */ GNUNET_log_skip (1, GNUNET_NO); last = GNUNET_TIME_relative_to_absolute (rel); GNUNET_assert (last.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us); GNUNET_log_skip (0, GNUNET_YES); /* check relative to absolute */ rel.rel_value_us = 1000000; GNUNET_assert (GNUNET_TIME_absolute_get ().abs_value_us < GNUNET_TIME_relative_to_absolute (rel).abs_value_us); /*check forever */ rel.rel_value_us = UINT64_MAX; GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == GNUNET_TIME_relative_to_absolute (rel).abs_value_us); /* check overflow for r2a */ rel.rel_value_us = (UINT64_MAX) - 1024; GNUNET_log_skip (1, GNUNET_NO); last = GNUNET_TIME_relative_to_absolute (rel); GNUNET_log_skip (0, GNUNET_NO); GNUNET_assert (last.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us); /* check overflow for relative add */ GNUNET_log_skip (1, GNUNET_NO); rel = GNUNET_TIME_relative_add (rel, rel); GNUNET_log_skip (0, GNUNET_NO); GNUNET_assert (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us); GNUNET_log_skip (1, GNUNET_NO); rel = GNUNET_TIME_relative_add (relForever, relForever); GNUNET_log_skip (0, GNUNET_NO); GNUNET_assert (rel.rel_value_us == relForever.rel_value_us); GNUNET_log_skip (1, GNUNET_NO); rel = GNUNET_TIME_relative_add (relUnit, relUnit); GNUNET_assert (rel.rel_value_us == 2 * relUnit.rel_value_us); /* check relation check in get_duration */ future.abs_value_us = now.abs_value_us + 1000000; GNUNET_assert (GNUNET_TIME_absolute_get_difference (now, future).rel_value_us == 1000000); GNUNET_assert (GNUNET_TIME_absolute_get_difference (future, now).rel_value_us == 0); GNUNET_assert (GNUNET_TIME_absolute_get_difference (zero, forever).rel_value_us == forever.abs_value_us); past.abs_value_us = now.abs_value_us - 1000000; rel = GNUNET_TIME_absolute_get_duration (future); GNUNET_assert (rel.rel_value_us == 0); rel = GNUNET_TIME_absolute_get_duration (past); GNUNET_assert (rel.rel_value_us >= 1000000); /* check get remaining */ rel = GNUNET_TIME_absolute_get_remaining (now); GNUNET_assert (rel.rel_value_us == 0); rel = GNUNET_TIME_absolute_get_remaining (past); GNUNET_assert (rel.rel_value_us == 0); rel = GNUNET_TIME_absolute_get_remaining (future); GNUNET_assert (rel.rel_value_us > 0); GNUNET_assert (rel.rel_value_us <= 1000000); forever = GNUNET_TIME_UNIT_FOREVER_ABS; GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == GNUNET_TIME_absolute_get_remaining (forever).rel_value_us); /* check endianess */ reln = GNUNET_TIME_relative_hton (rel); GNUNET_assert (rel.rel_value_us == GNUNET_TIME_relative_ntoh (reln).rel_value_us); nown = GNUNET_TIME_absolute_hton (now); GNUNET_assert (now.abs_value_us == GNUNET_TIME_absolute_ntoh (nown).abs_value_us); /* check absolute addition */ future = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_SECONDS); GNUNET_assert (future.abs_value_us == now.abs_value_us + 1000 * 1000LL); future = GNUNET_TIME_absolute_add (forever, GNUNET_TIME_UNIT_ZERO); GNUNET_assert (future.abs_value_us == forever.abs_value_us); rel.rel_value_us = (UINT64_MAX) - 1024; now.abs_value_us = rel.rel_value_us; future = GNUNET_TIME_absolute_add (now, rel); GNUNET_assert (future.abs_value_us == forever.abs_value_us); /* check zero */ future = GNUNET_TIME_absolute_add (now, GNUNET_TIME_UNIT_ZERO); GNUNET_assert (future.abs_value_us == now.abs_value_us); GNUNET_assert (forever.abs_value_us == GNUNET_TIME_absolute_subtract (forever, GNUNET_TIME_UNIT_MINUTES).abs_value_us); /*check absolute subtract */ now.abs_value_us = 50000; rel.rel_value_us = 100000; GNUNET_assert (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == (GNUNET_TIME_absolute_subtract (now, rel)).abs_value_us); rel.rel_value_us = 10000; GNUNET_assert (40000 == (GNUNET_TIME_absolute_subtract (now, rel)).abs_value_us); /*check relative divide */ GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == (GNUNET_TIME_relative_divide (rel, 0)).rel_value_us); rel = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == (GNUNET_TIME_relative_divide (rel, 2)).rel_value_us); rel = GNUNET_TIME_relative_divide (relUnit, 2); GNUNET_assert (rel.rel_value_us == relUnit.rel_value_us / 2); /* check Return absolute time of 0ms */ zero = GNUNET_TIME_UNIT_ZERO_ABS; /* check GNUNET_TIME_calculate_eta */ last.abs_value_us = GNUNET_TIME_absolute_get ().abs_value_us - 1024; forever = GNUNET_TIME_UNIT_FOREVER_ABS; forever.abs_value_us = forever.abs_value_us - 1024; GNUNET_assert (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == GNUNET_TIME_calculate_eta (forever, 50000, 100000).rel_value_us); /* check zero */ GNUNET_log_skip (1, GNUNET_NO); GNUNET_assert (GNUNET_TIME_UNIT_ZERO.rel_value_us == (GNUNET_TIME_calculate_eta (last, 60000, 50000)).rel_value_us); GNUNET_log_skip (0, GNUNET_YES); /*check forever */ GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == (GNUNET_TIME_calculate_eta (last, 0, 50000)).rel_value_us); /*check relative subtract */ now = GNUNET_TIME_absolute_get (); rel.rel_value_us = now.abs_value_us; relForever.rel_value_us = rel.rel_value_us + 1024; GNUNET_assert (1024 == GNUNET_TIME_relative_subtract (relForever, rel).rel_value_us); /*check zero */ GNUNET_assert (GNUNET_TIME_UNIT_ZERO.rel_value_us == GNUNET_TIME_relative_subtract (rel, relForever).rel_value_us); /*check forever */ rel.rel_value_us = UINT64_MAX; GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == GNUNET_TIME_relative_subtract (rel, relForever).rel_value_us); /*check GNUNET_TIME_relative_min */ now = GNUNET_TIME_absolute_get (); rel.rel_value_us = now.abs_value_us; relForever.rel_value_us = rel.rel_value_us - 1024; GNUNET_assert (relForever.rel_value_us == GNUNET_TIME_relative_min (rel, relForever).rel_value_us); /*check GNUNET_TIME_relative_max */ GNUNET_assert (rel.rel_value_us == GNUNET_TIME_relative_max (rel, relForever).rel_value_us); /*check GNUNET_TIME_absolute_min */ now = GNUNET_TIME_absolute_get (); last.abs_value_us = now.abs_value_us - 1024; GNUNET_assert (last.abs_value_us == GNUNET_TIME_absolute_min (now, last).abs_value_us); /*check GNUNET_TIME_absolute_max */ GNUNET_assert (now.abs_value_us == GNUNET_TIME_absolute_max (now, last).abs_value_us); return 0; } /* end of test_time.c */ gnunet-0.10.1/src/util/test_speedup_data.conf0000644000175000017500000000007312225230043016113 00000000000000[testing] SPEEDUP_INTERVAL = 100 ms SPEEDUP_DELTA = 100 ms gnunet-0.10.1/src/util/program.c0000644000175000017500000002263412307557412013406 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPROSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/program.c * @brief standard code for GNUnet startup and shutdown * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #include "gnunet_constants.h" #include "speedup.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * Context for the command. */ struct CommandContext { /** * Argv argument. */ char *const *args; /** * Name of the configuration file used, can be NULL! */ char *cfgfile; /** * Main function to run. */ GNUNET_PROGRAM_Main task; /** * Closure for @e task. */ void *task_cls; /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; }; /** * Initial task called by the scheduler for each * program. Runs the program-specific main task. */ static void program_main (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CommandContext *cc = cls; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; GNUNET_SPEEDUP_start_(cc->cfg); GNUNET_RESOLVER_connect (cc->cfg); cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg); } /** * Compare function for 'qsort' to sort command-line arguments by the * short option. * * @param a1 first command line option * @param a2 second command line option */ static int cmd_sorter (const void *a1, const void *a2) { const struct GNUNET_GETOPT_CommandLineOption *c1 = a1; const struct GNUNET_GETOPT_CommandLineOption *c2 = a2; if (toupper ((unsigned char) c1->shortName) > toupper ((unsigned char) c2->shortName)) return 1; if (toupper ((unsigned char) c1->shortName) < toupper ((unsigned char) c2->shortName)) return -1; if (c1->shortName > c2->shortName) return 1; if (c1->shortName < c2->shortName) return -1; return 0; } /** * Run a standard GNUnet command startup sequence (initialize loggers * and configuration, parse options). * * @param argc number of command line arguments in @a argv * @param argv command line arguments * @param binaryName our expected name * @param binaryHelp help text for the program * @param options command line options * @param task main function to run * @param task_cls closure for @a task * @param run_without_scheduler #GNUNET_NO start the scheduler, #GNUNET_YES do not * start the scheduler just run the main task * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_PROGRAM_run2 (int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls, int run_without_scheduler) { struct CommandContext cc; #if ENABLE_NLS char *path; #endif char *loglev; char *logfile; char *cfg_fn; const char *xdg; int ret; unsigned int cnt; unsigned long long skew_offset; unsigned long long skew_variance; long long clock_offset; struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_GETOPT_CommandLineOption defoptions[] = { GNUNET_GETOPT_OPTION_CFG_FILE (&cc.cfgfile), GNUNET_GETOPT_OPTION_HELP (binaryHelp), GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev), GNUNET_GETOPT_OPTION_LOGFILE (&logfile), GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION) }; struct GNUNET_GETOPT_CommandLineOption *allopts; const char *gargs; char *lpfx; char *spc; logfile = NULL; gargs = getenv ("GNUNET_ARGS"); if (NULL != gargs) { char **gargv; unsigned int gargc; int i; char *tok; char *cargs; gargv = NULL; gargc = 0; for (i = 0; i < argc; i++) GNUNET_array_append (gargv, gargc, GNUNET_strdup (argv[i])); cargs = GNUNET_strdup (gargs); for (tok = strtok (cargs, " "); NULL != tok; tok = strtok (NULL, " ")) GNUNET_array_append (gargv, gargc, GNUNET_strdup (tok)); GNUNET_free (cargs); GNUNET_array_append (gargv, gargc, NULL); argv = (char *const *) gargv; argc = gargc - 1; } memset (&cc, 0, sizeof (cc)); loglev = NULL; cc.task = task; cc.task_cls = task_cls; cc.cfg = cfg = GNUNET_CONFIGURATION_create (); /* prepare */ #if ENABLE_NLS setlocale (LC_ALL, ""); path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LOCALEDIR); if (NULL != path) { BINDTEXTDOMAIN ("GNUnet", path); GNUNET_free (path); } textdomain ("GNUnet"); #endif cnt = 0; while (NULL != options[cnt].name) cnt++; allopts = GNUNET_malloc ((cnt + 1) * sizeof (struct GNUNET_GETOPT_CommandLineOption) + sizeof (defoptions)); memcpy (allopts, defoptions, sizeof (defoptions)); memcpy (&allopts [sizeof (defoptions) / sizeof (struct GNUNET_GETOPT_CommandLineOption)], options, (cnt + 1) * sizeof (struct GNUNET_GETOPT_CommandLineOption)); cnt += sizeof (defoptions) / sizeof (struct GNUNET_GETOPT_CommandLineOption); qsort (allopts, cnt, sizeof (struct GNUNET_GETOPT_CommandLineOption), &cmd_sorter); loglev = NULL; xdg = getenv ("XDG_CONFIG_HOME"); if (NULL != xdg) GNUNET_asprintf (&cfg_fn, "%s%s%s", xdg, DIR_SEPARATOR_STR, "gnunet.conf"); else cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE); lpfx = GNUNET_strdup (binaryName); if (NULL != (spc = strstr (lpfx, " "))) *spc = '\0'; ret = GNUNET_GETOPT_run (binaryName, allopts, (unsigned int) argc, argv); if ((GNUNET_OK > ret) || (GNUNET_OK != GNUNET_log_setup (lpfx, loglev, logfile))) { GNUNET_free (allopts); GNUNET_free (lpfx); goto cleanup; } if (NULL == cc.cfgfile) cc.cfgfile = GNUNET_strdup (cfg_fn); if (GNUNET_YES == GNUNET_DISK_file_test (cc.cfgfile)) { if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, cc.cfgfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Malformed configuration file `%s', exit ...\n"), cc.cfgfile); ret = GNUNET_SYSERR; GNUNET_free (allopts); GNUNET_free (lpfx); goto cleanup; } } else { if (0 != strcmp (cc.cfgfile, cfg_fn)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not access configuration file `%s'\n"), cc.cfgfile); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Malformed configuration, exit ...\n")); ret = GNUNET_SYSERR; GNUNET_free (allopts); GNUNET_free (lpfx); goto cleanup; } } GNUNET_free (allopts); GNUNET_free (lpfx); if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cc.cfg, "testing", "skew_offset", &skew_offset) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cc.cfg, "testing", "skew_variance", &skew_variance))) { clock_offset = skew_offset - skew_variance; GNUNET_TIME_set_offset (clock_offset); } /* run */ cc.args = &argv[ret]; if (GNUNET_NO == run_without_scheduler) { GNUNET_SCHEDULER_run (&program_main, &cc); } else { GNUNET_RESOLVER_connect (cc.cfg); cc.task (cc.task_cls, cc.args, cc.cfgfile, cc.cfg); } ret = GNUNET_OK; cleanup: GNUNET_SPEEDUP_stop_ (); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_free_non_null (cc.cfgfile); GNUNET_free (cfg_fn); GNUNET_free_non_null (loglev); GNUNET_free_non_null (logfile); return ret; } /** * Run a standard GNUnet command startup sequence (initialize loggers * and configuration, parse options). * * @param argc number of command line arguments * @param argv command line arguments * @param binaryName our expected name * @param binaryHelp help text for the program * @param options command line options * @param task main function to run * @param task_cls closure for @a task * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_PROGRAM_run (int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls) { return GNUNET_PROGRAM_run2 (argc, argv, binaryName, binaryHelp, options, task, task_cls, GNUNET_NO); } /* end of program.c */ gnunet-0.10.1/src/util/client.c0000644000175000017500000011613212276375236013221 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/client.c * @brief code for access to services * @author Christian Grothoff * * Generic TCP code for reliable, record-oriented TCP * connections between clients and service providers. */ #include "platform.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" /** * How often do we re-try tranmsitting requests before giving up? * Note that if we succeeded transmitting a request but failed to read * a response, we do NOT re-try. */ #define MAX_ATTEMPTS 50 #define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__) /** * Handle for a transmission request. */ struct GNUNET_CLIENT_TransmitHandle { /** * Connection state. */ struct GNUNET_CLIENT_Connection *client; /** * Function to call to get the data for transmission. */ GNUNET_CONNECTION_TransmitReadyNotify notify; /** * Closure for @e notify. */ void *notify_cls; /** * Handle to the transmission with the underlying * connection. */ struct GNUNET_CONNECTION_TransmitHandle *th; /** * If we are re-trying and are delaying to do so, * handle to the scheduled task managing the delay. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Timeout for the operation overall. */ struct GNUNET_TIME_Absolute timeout; /** * Number of bytes requested. */ size_t size; /** * Are we allowed to re-try to connect without telling * the user (of this API) about the connection troubles? */ int auto_retry; /** * Number of attempts left for transmitting the request. We may * fail the first time (say because the service is not yet up), in * which case (if auto_retry is set) we wait a bit and re-try * (timeout permitting). */ unsigned int attempts_left; }; /** * Context for processing * "GNUNET_CLIENT_transmit_and_get_response" requests. */ struct TransmitGetResponseContext { /** * Client handle. */ struct GNUNET_CLIENT_Connection *client; /** * Message to transmit; do not free, allocated * right after this struct. */ const struct GNUNET_MessageHeader *hdr; /** * Timeout to use. */ struct GNUNET_TIME_Absolute timeout; /** * Function to call when done. */ GNUNET_CLIENT_MessageHandler rn; /** * Closure for @e rn. */ void *rn_cls; }; /** * Struct to refer to a GNUnet TCP connection. * This is more than just a socket because if the server * drops the connection, the client automatically tries * to reconnect (and for that needs connection information). */ struct GNUNET_CLIENT_Connection { /** * The connection handle, NULL if not live */ struct GNUNET_CONNECTION_Handle *connection; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Name of the service we interact with. */ char *service_name; /** * Context of a transmit_and_get_response operation, NULL * if no such operation is pending. */ struct TransmitGetResponseContext *tag; /** * Handler for current receiver task. */ GNUNET_CLIENT_MessageHandler receiver_handler; /** * Closure for @e receiver_handler. */ void *receiver_handler_cls; /** * Handle for a pending transmission request, NULL if there is * none pending. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * If we are re-trying and are delaying to do so, * handle to the scheduled task managing the delay. */ GNUNET_SCHEDULER_TaskIdentifier receive_task; /** * Buffer for received message. */ char *received_buf; /** * Timeout for receiving a response (absolute time). */ struct GNUNET_TIME_Absolute receive_timeout; /** * Current value for our incremental back-off (for * connect re-tries). */ struct GNUNET_TIME_Relative back_off; /** * Number of bytes in received_buf that are valid. */ size_t received_pos; /** * Size of received_buf. */ unsigned int received_size; /** * Do we have a complete response in received_buf? */ int msg_complete; /** * Are we currently busy doing receive-processing? * GNUNET_YES if so, GNUNET_NO if not. */ int in_receive; /** * Is this the first message we are sending to the service? */ int first_message; /** * How often have we tried to connect? */ unsigned int attempts; }; /** * Try connecting to the server using UNIX domain sockets. * * @param service_name name of service to connect to * @param cfg configuration to use * @return NULL on error, connection to UNIX otherwise */ static struct GNUNET_CONNECTION_Handle * try_unixpath (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { #if AF_UNIX struct GNUNET_CONNECTION_Handle *connection; char *unixpath; struct sockaddr_un s_un; unixpath = NULL; if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath))) { /* We have a non-NULL unixpath, need to validate it */ if (strlen (unixpath) >= sizeof (s_un.sun_path)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, (unsigned long long) sizeof (s_un.sun_path)); unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); LOG (GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath); if (NULL == unixpath) return NULL; } connection = GNUNET_CONNECTION_create_from_connect_to_unixpath (cfg, unixpath); if (NULL != connection) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Connected to unixpath `%s'!\n", unixpath); GNUNET_free (unixpath); return connection; } } GNUNET_free_non_null (unixpath); #endif return NULL; } /** * Test whether the configuration has proper values for connection * (UNIXPATH || (PORT && HOSTNAME)). * * @param service_name name of service to connect to * @param cfg configuration to use * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not */ static int test_service_configuration (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { int ret = GNUNET_SYSERR; char *hostname = NULL; unsigned long long port; #if AF_UNIX char *unixpath = NULL; if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath))) ret = GNUNET_OK; GNUNET_free_non_null (unixpath); #endif if ( (GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port)) && (port <= 65535) && (0 != port) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME", &hostname)) && (0 != strlen (hostname)) ) ret = GNUNET_OK; GNUNET_free_non_null (hostname); return ret; } /** * Try to connect to the service. * * @param service_name name of service to connect to * @param cfg configuration to use * @param attempt counter used to alternate between IP and UNIX domain sockets * @return NULL on error */ static struct GNUNET_CONNECTION_Handle * do_connect (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int attempt) { struct GNUNET_CONNECTION_Handle *connection; char *hostname; unsigned long long port; connection = NULL; if (0 == (attempt % 2)) { /* on even rounds, try UNIX first */ connection = try_unixpath (service_name, cfg); if (NULL != connection) return connection; } if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) { if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port)) || (port > 65535) || (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME", &hostname))) { LOG (GNUNET_ERROR_TYPE_WARNING, _ ("Could not determine valid hostname and port for service `%s' from configuration.\n"), service_name); return NULL; } if (0 == strlen (hostname)) { GNUNET_free (hostname); LOG (GNUNET_ERROR_TYPE_WARNING, _("Need a non-empty hostname for service `%s'.\n"), service_name); return NULL; } } else { /* unspecified means 0 (disabled) */ port = 0; hostname = NULL; } if (0 == port) { /* if port is 0, try UNIX */ connection = try_unixpath (service_name, cfg); if (NULL != connection) { GNUNET_free_non_null (hostname); return connection; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Port is 0 for service `%s', UNIXPATH did not work, returning NULL!\n", service_name); GNUNET_free_non_null (hostname); return NULL; } connection = GNUNET_CONNECTION_create_from_connect (cfg, hostname, port); GNUNET_free (hostname); return connection; } /** * Get a connection with a service. * * @param service_name name of the service * @param cfg configuration to use * @return NULL on error (service unknown to configuration) */ struct GNUNET_CLIENT_Connection * GNUNET_CLIENT_connect (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_CLIENT_Connection *client; struct GNUNET_CONNECTION_Handle *connection; if (GNUNET_OK != test_service_configuration (service_name, cfg)) return NULL; connection = do_connect (service_name, cfg, 0); client = GNUNET_new (struct GNUNET_CLIENT_Connection); client->first_message = GNUNET_YES; client->attempts = 1; client->connection = connection; client->service_name = GNUNET_strdup (service_name); client->cfg = cfg; client->back_off = GNUNET_TIME_UNIT_MILLISECONDS; return client; } /** * Destroy connection with the service. This will automatically * cancel any pending "receive" request (however, the handler will * *NOT* be called, not even with a NULL message). Any pending * transmission request will also be cancelled UNLESS the callback for * the transmission request has already been called, in which case the * transmission 'finish_pending_write' argument determines whether or * not the write is guaranteed to complete before the socket is fully * destroyed (unless, of course, there is an error with the server in * which case the message may still be lost). * * @param client handle to the service connection */ void GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client) { if (GNUNET_YES == client->in_receive) { GNUNET_CONNECTION_receive_cancel (client->connection); client->in_receive = GNUNET_NO; } if (NULL != client->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (client->th); client->th = NULL; } if (NULL != client->connection) { GNUNET_CONNECTION_destroy (client->connection); client->connection = NULL; } if (GNUNET_SCHEDULER_NO_TASK != client->receive_task) { GNUNET_SCHEDULER_cancel (client->receive_task); client->receive_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != client->tag) { GNUNET_free (client->tag); client->tag = NULL; } client->receiver_handler = NULL; GNUNET_array_grow (client->received_buf, client->received_size, 0); GNUNET_free (client->service_name); GNUNET_free (client); } /** * Check if message is complete. Sets the "msg_complete" member * in the client struct. * * @param client connection with the buffer to check */ static void check_complete (struct GNUNET_CLIENT_Connection *client) { if ((client->received_pos >= sizeof (struct GNUNET_MessageHeader)) && (client->received_pos >= ntohs (((const struct GNUNET_MessageHeader *) client->received_buf)-> size))) client->msg_complete = GNUNET_YES; } /** * Callback function for data received from the network. Note that * both @a available and @a errCode would be 0 if the read simply timed out. * * @param cls closure * @param buf pointer to received data * @param available number of bytes availabe in @a buf, * possibly 0 (on errors) * @param addr address of the sender * @param addrlen size of @a addr * @param errCode value of errno (on errors receiving) */ static void receive_helper (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode) { struct GNUNET_CLIENT_Connection *client = cls; struct GNUNET_TIME_Relative remaining; GNUNET_CLIENT_MessageHandler receive_handler; void *receive_handler_cls; GNUNET_assert (GNUNET_NO == client->msg_complete); GNUNET_assert (GNUNET_YES == client->in_receive); client->in_receive = GNUNET_NO; if ((0 == available) || (NULL == client->connection) || (0 != errCode)) { /* signal timeout! */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n", (unsigned int) available, NULL == client->connection ? "NULL" : "non-NULL", STRERROR (errCode)); if (NULL != (receive_handler = client->receiver_handler)) { receive_handler_cls = client->receiver_handler_cls; client->receiver_handler = NULL; receive_handler (receive_handler_cls, NULL); } return; } /* FIXME: optimize for common fast case where buf contains the * entire message and we need no copying... */ /* slow path: append to array */ if (client->received_size < client->received_pos + available) GNUNET_array_grow (client->received_buf, client->received_size, client->received_pos + available); memcpy (&client->received_buf[client->received_pos], buf, available); client->received_pos += available; check_complete (client); /* check for timeout */ remaining = GNUNET_TIME_absolute_get_remaining (client->receive_timeout); if (0 == remaining.rel_value_us) { /* signal timeout! */ if (NULL != (receive_handler = client->receiver_handler)) { client->receiver_handler = NULL; receive_handler (client->receiver_handler_cls, NULL); } return; } /* back to receive -- either for more data or to call callback! */ GNUNET_CLIENT_receive (client, client->receiver_handler, client->receiver_handler_cls, remaining); } /** * Continuation to call the receive callback. * * @param cls our handle to the client connection * @param tc scheduler context */ static void receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CLIENT_Connection *client = cls; GNUNET_CLIENT_MessageHandler handler = client->receiver_handler; const struct GNUNET_MessageHeader *cmsg = (const struct GNUNET_MessageHeader *) client->received_buf; void *handler_cls = client->receiver_handler_cls; uint16_t msize = ntohs (cmsg->size); char mbuf[msize] GNUNET_ALIGN; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u and size %u from %s service.\n", ntohs (cmsg->type), msize, client->service_name); client->receive_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_YES == client->msg_complete); GNUNET_assert (client->received_pos >= msize); memcpy (msg, cmsg, msize); memmove (client->received_buf, &client->received_buf[msize], client->received_pos - msize); client->received_pos -= msize; client->msg_complete = GNUNET_NO; client->receiver_handler = NULL; check_complete (client); if (NULL != handler) handler (handler_cls, msg); } /** * Read from the service. * * @param client the service * @param handler function to call with the message * @param handler_cls closure for @a handler * @param timeout how long to wait until timing out */ void GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client, GNUNET_CLIENT_MessageHandler handler, void *handler_cls, struct GNUNET_TIME_Relative timeout) { if (NULL == client->connection) { /* already disconnected, fail instantly! */ GNUNET_break (0); /* this should not happen in well-written code! */ if (NULL != handler) handler (handler_cls, NULL); return; } client->receiver_handler = handler; client->receiver_handler_cls = handler_cls; client->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout); if (GNUNET_YES == client->msg_complete) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == client->receive_task); client->receive_task = GNUNET_SCHEDULER_add_now (&receive_task, client); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "calling GNUNET_CONNECTION_receive\n"); GNUNET_assert (GNUNET_NO == client->in_receive); client->in_receive = GNUNET_YES; GNUNET_CONNECTION_receive (client->connection, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1, timeout, &receive_helper, client); } } /** * Handle for a test to check if a service is running. */ struct GNUNET_CLIENT_TestHandle { /** * Function to call with the result of the test. */ GNUNET_CLIENT_TestResultCallback cb; /** * Closure for @e cb. */ void *cb_cls; /** * Client connection we are using for the test, if any. */ struct GNUNET_CLIENT_Connection *client; /** * Handle for the transmission request, if any. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Deadline for calling @e cb. */ struct GNUNET_TIME_Absolute test_deadline; /** * ID of task used for asynchronous operations. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Final result to report back (once known). */ int result; }; /** * Abort testing for service. * * @param th test handle */ void GNUNET_CLIENT_service_test_cancel (struct GNUNET_CLIENT_TestHandle *th) { if (NULL != th->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (th->th); th->th = NULL; } if (NULL != th->client) { GNUNET_CLIENT_disconnect (th->client); th->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != th->task) { GNUNET_SCHEDULER_cancel (th->task); th->task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (th); } /** * Task that reports back the result by calling the callback * and then cleans up. * * @param cls the `struct GNUNET_CLIENT_TestHandle` * @param tc scheduler context */ static void report_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CLIENT_TestHandle *th = cls; th->task = GNUNET_SCHEDULER_NO_TASK; th->cb (th->cb_cls, th->result); GNUNET_CLIENT_service_test_cancel (th); } /** * Report service test result asynchronously back to callback. * * @param th test handle with the result and the callback * @param result result to report */ static void service_test_report (struct GNUNET_CLIENT_TestHandle *th, int result) { th->result = result; th->task = GNUNET_SCHEDULER_add_now (&report_result, th); } /** * Receive confirmation from test, service is up. * * @param cls closure with the `struct GNUNET_CLIENT_TestHandle` * @param msg message received, NULL on timeout or fatal error */ static void confirm_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CLIENT_TestHandle *th = cls; /* We may want to consider looking at the reply in more * detail in the future, for example, is this the * correct service? FIXME! */ if (NULL != msg) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Received confirmation that service is running.\n"); service_test_report (th, GNUNET_YES); } else { service_test_report (th, GNUNET_NO); } } /** * Send the 'TEST' message to the service. If successful, prepare to * receive the reply. * * @param cls the `struct GNUNET_CLIENT_TestHandle` of the test * @param size number of bytes available in @a buf * @param buf where to write the message * @return number of bytes written to @a buf */ static size_t write_test (void *cls, size_t size, void *buf) { struct GNUNET_CLIENT_TestHandle *th = cls; struct GNUNET_MessageHeader *msg; th->th = NULL; if (size < sizeof (struct GNUNET_MessageHeader)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit TEST request.\n"); service_test_report (th, GNUNET_NO); return 0; /* client disconnected */ } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "TEST"); msg = (struct GNUNET_MessageHeader *) buf; msg->type = htons (GNUNET_MESSAGE_TYPE_TEST); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); GNUNET_CLIENT_receive (th->client, &confirm_handler, th, GNUNET_TIME_absolute_get_remaining (th->test_deadline)); return sizeof (struct GNUNET_MessageHeader); } /** * Test if the service is running. If we are given a UNIXPATH or a * local address, we do this NOT by trying to connect to the service, * but by trying to BIND to the same port. If the BIND fails, we know * the service is running. * * @param service name of the service to wait for * @param cfg configuration to use * @param timeout how long to wait at most * @param cb function to call with the result * @param cb_cls closure for @a cb * @return handle to cancel the test */ struct GNUNET_CLIENT_TestHandle * GNUNET_CLIENT_service_test (const char *service, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TIME_Relative timeout, GNUNET_CLIENT_TestResultCallback cb, void *cb_cls) { struct GNUNET_CLIENT_TestHandle *th; char *hostname; unsigned long long port; struct GNUNET_NETWORK_Handle *sock; th = GNUNET_new (struct GNUNET_CLIENT_TestHandle); th->cb = cb; th->cb_cls = cb_cls; th->test_deadline = GNUNET_TIME_relative_to_absolute (timeout); LOG (GNUNET_ERROR_TYPE_DEBUG, "Testing if service `%s' is running.\n", service); #ifdef AF_UNIX { /* probe UNIX support */ struct sockaddr_un s_un; char *unixpath; int abstract; unixpath = NULL; if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath))) /* We have a non-NULL unixpath, does that mean it's valid? */ { if (strlen (unixpath) >= sizeof (s_un.sun_path)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, (unsigned long long) sizeof (s_un.sun_path)); unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); LOG (GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath); } } #ifdef LINUX abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg, "TESTING", "USE_ABSTRACT_SOCKETS"); #else abstract = GNUNET_NO; #endif if ((NULL != unixpath) && (GNUNET_YES != abstract)) { if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (unixpath)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "mkdir", unixpath); } if (NULL != unixpath) { sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); if (NULL != sock) { memset (&s_un, 0, sizeof (s_un)); s_un.sun_family = AF_UNIX; strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1); if (GNUNET_YES == abstract) s_un.sun_path[0] = '\0'; #if HAVE_SOCKADDR_IN_SIN_LEN s_un.sun_len = (u_char) sizeof (struct sockaddr_un); #endif if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un, sizeof (struct sockaddr_un))) { /* failed to bind => service must be running */ GNUNET_free (unixpath); (void) GNUNET_NETWORK_socket_close (sock); service_test_report (th, GNUNET_YES); return th; } (void) GNUNET_NETWORK_socket_close (sock); /* let's try IP */ } } GNUNET_free_non_null (unixpath); } #endif hostname = NULL; if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, service, "PORT", &port)) || (port > 65535) || (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, service, "HOSTNAME", &hostname))) { /* UNIXPATH failed (if possible) AND IP failed => error */ service_test_report (th, GNUNET_SYSERR); return th; } if (0 == strcmp ("localhost", hostname) #if !LINUX && 0 #endif ) { /* can test using 'bind' */ struct sockaddr_in s_in; memset (&s_in, 0, sizeof (s_in)); #if HAVE_SOCKADDR_IN_SIN_LEN s_in.sin_len = sizeof (struct sockaddr_in); #endif s_in.sin_family = AF_INET; s_in.sin_port = htons (port); sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); if (NULL != sock) { if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in, sizeof (s_in))) { /* failed to bind => service must be running */ GNUNET_free (hostname); (void) GNUNET_NETWORK_socket_close (sock); service_test_report (th, GNUNET_YES); return th; } (void) GNUNET_NETWORK_socket_close (sock); } } if (0 == strcmp ("ip6-localhost", hostname) #if !LINUX && 0 #endif ) { /* can test using 'bind' */ struct sockaddr_in6 s_in6; memset (&s_in6, 0, sizeof (s_in6)); #if HAVE_SOCKADDR_IN_SIN_LEN s_in6.sin6_len = sizeof (struct sockaddr_in6); #endif s_in6.sin6_family = AF_INET6; s_in6.sin6_port = htons (port); sock = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0); if (NULL != sock) { if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6, sizeof (s_in6))) { /* failed to bind => service must be running */ GNUNET_free (hostname); (void) GNUNET_NETWORK_socket_close (sock); service_test_report (th, GNUNET_YES); return th; } (void) GNUNET_NETWORK_socket_close (sock); } } if (((0 == strcmp ("localhost", hostname)) || (0 == strcmp ("ip6-localhost", hostname))) #if !LINUX && 0 #endif ) { /* all binds succeeded => claim service not running right now */ GNUNET_free_non_null (hostname); service_test_report (th, GNUNET_NO); return th; } GNUNET_free_non_null (hostname); /* non-localhost, try 'connect' method */ th->client = GNUNET_CLIENT_connect (service, cfg); if (NULL == th->client) { LOG (GNUNET_ERROR_TYPE_INFO, _("Could not connect to service `%s', configuration broken.\n"), service); service_test_report (th, GNUNET_SYSERR); return th; } th->th = GNUNET_CLIENT_notify_transmit_ready (th->client, sizeof (struct GNUNET_MessageHeader), timeout, GNUNET_YES, &write_test, th); if (NULL == th->th) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Failure to transmit request to service `%s'\n"), service); service_test_report (th, GNUNET_SYSERR); return th; } return th; } /** * Connection notifies us about failure or success of * a transmission request. Either pass it on to our * user or, if possible, retry. * * @param cls our `struct GNUNET_CLIENT_TransmissionHandle` * @param size number of bytes available for transmission * @param buf where to write them * @return number of bytes written to buf */ static size_t client_notify (void *cls, size_t size, void *buf); /** * This task is run if we should re-try connection to the * service after a while. * * @param cls our `struct GNUNET_CLIENT_TransmitHandle` of the request * @param tc unused */ static void client_delayed_retry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CLIENT_TransmitHandle *th = cls; struct GNUNET_TIME_Relative delay; th->reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* give up, was shutdown */ th->client->th = NULL; th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); return; } th->client->connection = do_connect (th->client->service_name, th->client->cfg, th->client->attempts++); th->client->first_message = GNUNET_YES; if (NULL == th->client->connection) { /* could happen if we're out of sockets */ delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (th->timeout), th->client->back_off); th->client->back_off = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (th->client->back_off, 2), GNUNET_TIME_UNIT_SECONDS); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, trying again in %s.\n", MAX_ATTEMPTS - th->attempts_left, GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == th->reconnect_task); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); return; } th->th = GNUNET_CONNECTION_notify_transmit_ready (th->client->connection, th->size, GNUNET_TIME_absolute_get_remaining (th->timeout), &client_notify, th); if (NULL == th->th) { GNUNET_break (0); th->client->th = NULL; th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); return; } } /** * Connection notifies us about failure or success of a transmission * request. Either pass it on to our user or, if possible, retry. * * @param cls our `struct GNUNET_CLIENT_TransmissionHandle` * @param size number of bytes available for transmission * @param buf where to write them * @return number of bytes written to @a buf */ static size_t client_notify (void *cls, size_t size, void *buf) { struct GNUNET_CLIENT_TransmitHandle *th = cls; struct GNUNET_CLIENT_Connection *client = th->client; size_t ret; struct GNUNET_TIME_Relative delay; LOG (GNUNET_ERROR_TYPE_DEBUG, "client_notify is running\n"); th->th = NULL; client->th = NULL; if (NULL == buf) { delay = GNUNET_TIME_absolute_get_remaining (th->timeout); delay.rel_value_us /= 2; if ((GNUNET_YES != th->auto_retry) || (0 == --th->attempts_left) || (delay.rel_value_us < 1)|| (0 != (GNUNET_SCHEDULER_get_reason() & GNUNET_SCHEDULER_REASON_SHUTDOWN))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, giving up.\n", MAX_ATTEMPTS - th->attempts_left); GNUNET_break (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); return 0; } /* auto-retry */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect to `%s', automatically trying again.\n", client->service_name); if (GNUNET_YES == client->in_receive) { GNUNET_CONNECTION_receive_cancel (client->connection); client->in_receive = GNUNET_NO; } GNUNET_CONNECTION_destroy (client->connection); client->connection = NULL; delay = GNUNET_TIME_relative_min (delay, client->back_off); client->back_off = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (client->back_off, 2), GNUNET_TIME_UNIT_SECONDS); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, trying again in %s.\n", MAX_ATTEMPTS - th->attempts_left, GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); client->th = th; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == th->reconnect_task); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); return 0; } GNUNET_assert (size >= th->size); ret = th->notify (th->notify_cls, size, buf); GNUNET_free (th); if (sizeof (struct GNUNET_MessageHeader) <= ret) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting message of type %u and size %u to %s service.\n", ntohs (((struct GNUNET_MessageHeader *) buf)->type), ntohs (((struct GNUNET_MessageHeader *) buf)->size), client->service_name); } return ret; } /** * Ask the client to call us once the specified number of bytes * are free in the transmission buffer. May call the notify * method immediately if enough space is available. * * @param client connection to the service * @param size number of bytes to send * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param auto_retry if the connection to the service dies, should we * automatically re-connect and retry (within the timeout period) * or should we immediately fail in this case? Pass GNUNET_YES * if the caller does not care about temporary connection errors, * for example because the protocol is stateless * @param notify function to call * @param notify_cls closure for @a notify * @return NULL if our buffer will never hold size bytes, * a handle if the notify callback was queued (can be used to cancel) */ struct GNUNET_CLIENT_TransmitHandle * GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, size_t size, struct GNUNET_TIME_Relative timeout, int auto_retry, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { struct GNUNET_CLIENT_TransmitHandle *th; if (NULL != client->th) { /* If this breaks, you most likley called this function twice without waiting * for completion or canceling the request */ GNUNET_break (0); return NULL; } th = GNUNET_new (struct GNUNET_CLIENT_TransmitHandle); th->client = client; th->size = size; th->timeout = GNUNET_TIME_relative_to_absolute (timeout); /* always auto-retry on first message to service */ th->auto_retry = (GNUNET_YES == client->first_message) ? GNUNET_YES : auto_retry; client->first_message = GNUNET_NO; th->notify = notify; th->notify_cls = notify_cls; th->attempts_left = MAX_ATTEMPTS; client->th = th; if (NULL == client->connection) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == th->reconnect_task); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (client->back_off, &client_delayed_retry, th); } else { th->th = GNUNET_CONNECTION_notify_transmit_ready (client->connection, size, timeout, &client_notify, th); if (NULL == th->th) { GNUNET_break (0); GNUNET_free (th); client->th = NULL; return NULL; } } return th; } /** * Cancel a request for notification. * * @param th handle from the original request. */ void GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle *th) { if (GNUNET_SCHEDULER_NO_TASK != th->reconnect_task) { GNUNET_assert (NULL == th->th); GNUNET_SCHEDULER_cancel (th->reconnect_task); th->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } else { GNUNET_assert (NULL != th->th); GNUNET_CONNECTION_notify_transmit_ready_cancel (th->th); } th->client->th = NULL; GNUNET_free (th); } /** * Function called to notify a client about the socket * begin ready to queue the message. @a buf will be * NULL and @a size zero if the socket was closed for * writing in the meantime. * * @param cls closure of type "struct TransmitGetResponseContext*" * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ static size_t transmit_for_response (void *cls, size_t size, void *buf) { struct TransmitGetResponseContext *tc = cls; uint16_t msize; tc->client->tag = NULL; msize = ntohs (tc->hdr->size); if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, _("Could not submit request, not expecting to receive a response.\n")); if (NULL != tc->rn) tc->rn (tc->rn_cls, NULL); GNUNET_free (tc); return 0; } GNUNET_assert (size >= msize); memcpy (buf, tc->hdr, msize); GNUNET_CLIENT_receive (tc->client, tc->rn, tc->rn_cls, GNUNET_TIME_absolute_get_remaining (tc->timeout)); GNUNET_free (tc); return msize; } /** * Convenience API that combines sending a request * to the service and waiting for a response. * If either operation times out, the callback * will be called with a "NULL" response (in which * case the connection should probably be destroyed). * * @param client connection to use * @param hdr message to transmit * @param timeout when to give up (for both transmission * and for waiting for a response) * @param auto_retry if the connection to the service dies, should we * automatically re-connect and retry (within the timeout period) * or should we immediately fail in this case? Pass GNUNET_YES * if the caller does not care about temporary connection errors, * for example because the protocol is stateless * @param rn function to call with the response * @param rn_cls closure for @a rn * @return #GNUNET_OK on success, #GNUNET_SYSERR if a request * is already pending */ int GNUNET_CLIENT_transmit_and_get_response (struct GNUNET_CLIENT_Connection *client, const struct GNUNET_MessageHeader *hdr, struct GNUNET_TIME_Relative timeout, int auto_retry, GNUNET_CLIENT_MessageHandler rn, void *rn_cls) { struct TransmitGetResponseContext *tc; uint16_t msize; if (NULL != client->th) return GNUNET_SYSERR; GNUNET_assert (NULL == client->tag); msize = ntohs (hdr->size); tc = GNUNET_malloc (sizeof (struct TransmitGetResponseContext) + msize); tc->client = client; tc->hdr = (const struct GNUNET_MessageHeader *) &tc[1]; memcpy (&tc[1], hdr, msize); tc->timeout = GNUNET_TIME_relative_to_absolute (timeout); tc->rn = rn; tc->rn_cls = rn_cls; if (NULL == GNUNET_CLIENT_notify_transmit_ready (client, msize, timeout, auto_retry, &transmit_for_response, tc)) { GNUNET_break (0); GNUNET_free (tc); return GNUNET_SYSERR; } client->tag = tc; return GNUNET_OK; } /* end of client.c */ gnunet-0.10.1/src/util/crypto_kdf.c0000644000175000017500000000601312263515426014074 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/util/crypto_kdf.c * @brief Key derivation * @author Nils Durner */ #include #include "platform.h" #include "gnunet_crypto_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xts salt * @param xts_len length of @a xts * @param skm source key material * @param skm_len length of @a skm * @param argp va_list of void * & size_t pairs for context chunks * @return #GNUNET_YES on success */ int GNUNET_CRYPTO_kdf_v (void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len, va_list argp) { /* * "Finally, we point out to a particularly advantageous instantiation using * HMAC-SHA512 as XTR and HMAC-SHA256 in PRF* (in which case the output from SHA-512 is * truncated to 256 bits). This makes sense in two ways: First, the extraction part is where we need a * stronger hash function due to the unconventional demand from the hash function in the extraction * setting. Second, as shown in Section 6, using HMAC with a truncated output as an extractor * allows to prove the security of HKDF under considerably weaker assumptions on the underlying * hash function." * * http://eprint.iacr.org/2010/264 */ return GNUNET_CRYPTO_hkdf_v (result, out_len, GCRY_MD_SHA512, GCRY_MD_SHA256, xts, xts_len, skm, skm_len, argp); } /** * @brief Derive key * @param result buffer for the derived key, allocated by caller * @param out_len desired length of the derived key * @param xts salt * @param xts_len length of @a xts * @param skm source key material * @param skm_len length of @a skm * @param ... void * & size_t pairs for context chunks * @return #GNUNET_YES on success */ int GNUNET_CRYPTO_kdf (void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len, ...) { va_list argp; int ret; va_start (argp, skm_len); ret = GNUNET_CRYPTO_kdf_v (result, out_len, xts, xts_len, skm, skm_len, argp); va_end (argp); return ret; } gnunet-0.10.1/src/util/w32cat.c0000644000175000017500000001006412225777501013036 00000000000000/* W32 version of 'cat' program (C) 2012 LRN cat is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. cat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with cat; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include DWORD WINAPI parent_control_thread (LPVOID lpParameter) { HANDLE h = (HANDLE) lpParameter; while (TRUE) { DWORD dw; BOOL b; unsigned char c; b = ReadFile (h, &c, 1, &dw, NULL); if (!b) { ExitProcess (0); } raise ((int) c); } } void install_parent_control_handler () { const char *env_buf; char *env_buf_end; uint64_t pipe_fd; HANDLE pipe_handle; env_buf = getenv ("GNUNET_OS_CONTROL_PIPE"); if ( (NULL == env_buf) || (strlen (env_buf) <= 0) ) return; errno = 0; pipe_fd = strtoull (env_buf, &env_buf_end, 16); if ((0 != errno) || (env_buf == env_buf_end)) return; /* Gcc will issue a warning here. What to do with it? */ pipe_handle = (HANDLE) (uintptr_t) pipe_fd; CreateThread (NULL, 0, parent_control_thread, (LPVOID) pipe_handle, 0, NULL); } int main (int argc, char **argv) { HANDLE stdi, stdo; BOOL b; wchar_t *commandlinew, **argvw; int argcw; int i; stdo = GetStdHandle (STD_OUTPUT_HANDLE); if (stdo == INVALID_HANDLE_VALUE || stdo == NULL) return 1; commandlinew = GetCommandLineW (); argvw = CommandLineToArgvW (commandlinew, &argcw); if (argvw == NULL) return 1; install_parent_control_handler (); for (i = 1; i < argcw || argcw == 1; i++) { DWORD r, w; int is_dash = wcscmp (NULL == argvw[i] ? L"-" : argvw[i], L"-") == 0; if (argcw == 1 || is_dash) { stdi = GetStdHandle (STD_INPUT_HANDLE); if (stdi == INVALID_HANDLE_VALUE) { fprintf (stderr, "cat: Failed to obtain stdin handle.\n"); return 4; } if (stdi == NULL) { fprintf (stderr, "cat: Have no stdin.\n"); return 5; } } else { stdi = CreateFileW (argvw[i], GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (stdi == INVALID_HANDLE_VALUE) { wchar_t *msgbuf; DWORD le = GetLastError (); if (0 < FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, le, 0, (wchar_t *) &msgbuf, 0, NULL)) { fprintf (stderr, "cat: Failed to open file `%S'. Error %lu.\n", argvw[i], le); return 3; } fprintf (stderr, "cat: Failed to open file `%S'. Error %lu: %S\n", argvw[i], le, msgbuf); if (msgbuf != NULL) LocalFree (msgbuf); return 2; } } do { unsigned char c; b = ReadFile (stdi, &c, 1, &r, NULL); if (b && r > 0) { b = WriteFile (stdo, &c, 1, &w, NULL); if (b == 0) { wchar_t *msgbuf; DWORD le = GetLastError (); if (0 < FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, le, 0, (wchar_t *) &msgbuf, 0, NULL)) { fprintf (stderr, "cat: Failed to write into stdout. Error %lu.\n", le); return 3; } fprintf (stderr, "cat: Failed to write into stdout. Error %lu: %S\n", le, msgbuf); if (msgbuf != NULL) LocalFree (msgbuf); return 6; } } } while (b && r > 0); if (argcw == 1) break; if (!is_dash) CloseHandle (stdi); } LocalFree (argvw); return 0; } gnunet-0.10.1/src/util/test_service_data.conf0000644000175000017500000000104212225230043016103 00000000000000[test_service] PORT=12435 BINDTO=localhost PIDFILE=/tmp/test-service.pid TIMEOUT=30 s MAXBUF=1024 DISABLEV6=NO ACCEPT_FROM=127.0.0.1; REJECT_FROM=1.2.3.0/15;4.5.0.0/8;6.7.8.9/255.255.255.0; ACCEPT_FROM6=::1; REJECT_FROM6=AB:CD:EF::00;AB:CD::00/40; HOSTNAME=localhost [test_service6] PORT=12435 PIDFILE=/tmp/test-service.pid TIMEOUT=30 s MAXBUF=1024 DISABLEV6=NO ACCEPT_FROM=127.0.0.1; REJECT_FROM=1.2.3.0/15;4.5.0.0/8;6.7.8.9/255.255.255.0; ACCEPT_FROM6=::1; REJECT_FROM6=AB:CD:EF::00;AB:CD::00/40; HOSTNAME=::1 [resolver] HOSTNAME=localhost gnunet-0.10.1/src/util/perf_crypto_hash.c0000644000175000017500000000502712263525233015270 00000000000000/* This file is part of GNUnet. (C) 2002, 2003, 2004, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file util/perf_crypto_hash.c * @brief measure performance of hash function */ #include "platform.h" #include "gnunet_util_lib.h" #include #include static void perfHash () { struct GNUNET_HashCode hc; unsigned int i; char buf[64 * 1024]; memset (buf, 1, sizeof (buf)); for (i = 0; i < 1024; i++) GNUNET_CRYPTO_hash (buf, sizeof (buf), &hc); } static void perfHKDF () { unsigned int i; char res[128]; char buf[128]; char skm[64]; memset (buf, 1, sizeof (buf)); memset (skm, 2, sizeof (skm)); for (i = 0; i < 1024; i++) GNUNET_CRYPTO_hkdf (res, sizeof (res), GCRY_MD_SHA512, GCRY_MD_SHA256, buf, sizeof (buf), skm, sizeof (skm), "test", (size_t) 4, NULL, 0); } int main (int argc, char *argv[]) { struct GNUNET_TIME_Absolute start; start = GNUNET_TIME_absolute_get (); perfHash (); printf ("Hash perf took %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GAUGER ("UTIL", "Cryptographic hashing", 64 * 1024 / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL), "kb/ms"); start = GNUNET_TIME_absolute_get (); perfHKDF (); printf ("HKDF perf took %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GAUGER ("UTIL", "Cryptographic HKDF", 64 * 1024 / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL), "kb/ms"); return 0; } /* end of perf_crypto_hash.c */ gnunet-0.10.1/src/util/test_plugin.c0000644000175000017500000000365612225777501014301 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_plugin.c * @brief testcase for plugin.c */ #include "platform.h" #include "gnunet_util_lib.h" static void test_cb (void *cls, const char *libname, void *lib_ret) { void *ret; GNUNET_assert (0 == strcmp (cls, "test")); GNUNET_assert (0 == strcmp (lib_ret, "Hello")); ret = GNUNET_PLUGIN_unload (libname, "out"); GNUNET_assert (NULL != ret); GNUNET_assert (0 == strcmp (ret, "World")); GNUNET_free (ret); } int main (int argc, char *argv[]) { void *ret; GNUNET_log_setup ("test-plugin", "WARNING", NULL); GNUNET_log_skip (1, GNUNET_NO); ret = GNUNET_PLUGIN_load ("libgnunet_plugin_missing", NULL); GNUNET_log_skip (0, GNUNET_NO); if (ret != NULL) return 1; ret = GNUNET_PLUGIN_load ("libgnunet_plugin_test", "in"); if (ret == NULL) return 1; if (0 != strcmp (ret, "Hello")) return 2; ret = GNUNET_PLUGIN_unload ("libgnunet_plugin_test", "out"); if (ret == NULL) return 3; if (0 != strcmp (ret, "World")) return 4; free (ret); GNUNET_PLUGIN_load_all ("libgnunet_plugin_tes", "in", &test_cb, "test"); return 0; } /* end of test_plugin.c */ gnunet-0.10.1/src/util/perf_crypto_symmetric.c0000644000175000017500000000434512225777501016370 00000000000000/* This file is part of GNUnet. (C) 2002, 2003, 2004, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file util/perf_crypto_symmetric.c * @brief measure performance of encryption function */ #include "platform.h" #include "gnunet_util_lib.h" #include static void perfEncrypt () { unsigned int i; char buf[64 * 1024]; char rbuf[64 * 1024]; struct GNUNET_CRYPTO_SymmetricSessionKey sk; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; GNUNET_CRYPTO_symmetric_create_session_key (&sk); memset (buf, 1, sizeof (buf)); for (i = 0; i < 1024; i++) { memset (&iv, (int8_t) i, sizeof (iv)); GNUNET_CRYPTO_symmetric_encrypt (buf, sizeof (buf), &sk, &iv, rbuf); GNUNET_CRYPTO_symmetric_decrypt (rbuf, sizeof (buf), &sk, &iv, buf); } memset (rbuf, 1, sizeof (rbuf)); GNUNET_assert (0 == memcmp (rbuf, buf, sizeof (buf))); } int main (int argc, char *argv[]) { struct GNUNET_TIME_Absolute start; start = GNUNET_TIME_absolute_get (); perfEncrypt (); printf ("Encrypt perf took %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GAUGER ("UTIL", "Symmetric encryption", 64 * 1024 / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL), "kb/ms"); return 0; } /* end of perf_crypto_aes.c */ gnunet-0.10.1/src/util/scheduler.c0000644000175000017500000014152712306322024013704 00000000000000/* This file is part of GNUnet (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/scheduler.c * @brief schedule computations using continuation passing style * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "disk.h" #define LOG(kind,...) GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-scheduler", syscall) #if HAVE_EXECINFO_H #include "execinfo.h" /** * Use lsof to generate file descriptor reports on select error? * (turn off for stable releases). */ #define USE_LSOF GNUNET_NO /** * Obtain trace information for all scheduler calls that schedule tasks. */ #define EXECINFO GNUNET_NO /** * Check each file descriptor before adding */ #define DEBUG_FDS GNUNET_NO /** * Depth of the traces collected via EXECINFO. */ #define MAX_TRACE_DEPTH 50 #endif /** * Should we figure out which tasks are delayed for a while * before they are run? (Consider using in combination with EXECINFO). */ #define PROFILE_DELAYS GNUNET_NO /** * Task that were in the queue for longer than this are reported if * PROFILE_DELAYS is active. */ #define DELAY_THRESHOLD GNUNET_TIME_UNIT_SECONDS /** * Linked list of pending tasks. */ struct Task { /** * This is a linked list. */ struct Task *next; /** * Function to run when ready. */ GNUNET_SCHEDULER_Task callback; /** * Closure for the @e callback. */ void *callback_cls; /** * Set of file descriptors this task is waiting * for for reading. Once ready, this is updated * to reflect the set of file descriptors ready * for operation. */ struct GNUNET_NETWORK_FDSet *read_set; /** * Set of file descriptors this task is waiting for for writing. * Once ready, this is updated to reflect the set of file * descriptors ready for operation. */ struct GNUNET_NETWORK_FDSet *write_set; /** * Unique task identifier. */ GNUNET_SCHEDULER_TaskIdentifier id; /** * Absolute timeout value for the task, or * GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout". */ struct GNUNET_TIME_Absolute timeout; #if PROFILE_DELAYS /** * When was the task scheduled? */ struct GNUNET_TIME_Absolute start_time; #endif /** * Why is the task ready? Set after task is added to ready queue. * Initially set to zero. All reasons that have already been * satisfied (i.e. read or write ready) will be set over time. */ enum GNUNET_SCHEDULER_Reason reason; /** * Task priority. */ enum GNUNET_SCHEDULER_Priority priority; /** * Set if we only wait for reading from a single FD, otherwise -1. */ int read_fd; /** * Set if we only wait for writing to a single FD, otherwise -1. */ int write_fd; /** * Should the existence of this task in the queue be counted as * reason to not shutdown the scheduler? */ int lifeness; #if EXECINFO /** * Array of strings which make up a backtrace from the point when this * task was scheduled (essentially, who scheduled the task?) */ char **backtrace_strings; /** * Size of the backtrace_strings array */ int num_backtrace_strings; #endif }; /** * List of tasks waiting for an event. */ static struct Task *pending; /** * List of tasks waiting ONLY for a timeout event. * Sorted by timeout (earliest first). Used so that * we do not traverse the list of these tasks when * building select sets (we just look at the head * to determine the respective timeout ONCE). */ static struct Task *pending_timeout; /** * Last inserted task waiting ONLY for a timeout event. * Used to (heuristically) speed up insertion. */ static struct Task *pending_timeout_last; /** * ID of the task that is running right now. */ static struct Task *active_task; /** * List of tasks ready to run right now, * grouped by importance. */ static struct Task *ready[GNUNET_SCHEDULER_PRIORITY_COUNT]; /** * Identity of the last task queued. Incremented for each task to * generate a unique task ID (it is virtually impossible to start * more than 2^64 tasks during the lifetime of a process). */ static GNUNET_SCHEDULER_TaskIdentifier last_id; /** * Number of tasks on the ready list. */ static unsigned int ready_count; /** * How many tasks have we run so far? */ static unsigned long long tasks_run; /** * Priority of the task running right now. Only * valid while a task is running. */ static enum GNUNET_SCHEDULER_Priority current_priority; /** * Priority of the highest task added in the current select * iteration. */ static enum GNUNET_SCHEDULER_Priority max_priority_added; /** * Value of the 'lifeness' flag for the current task. */ static int current_lifeness; /** * Function to use as a select() in the scheduler. * If NULL, we use GNUNET_NETWORK_socket_select(). */ static GNUNET_SCHEDULER_select scheduler_select; /** * Closure for 'scheduler_select'. */ static void *scheduler_select_cls; /** * Sets the select function to use in the scheduler (scheduler_select). * * @param new_select new select function to use * @param new_select_cls closure for @a new_select * @return previously used select function, NULL for default */ void GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select, void *new_select_cls) { scheduler_select = new_select; scheduler_select_cls = new_select_cls; } /** * Check that the given priority is legal (and return it). * * @param p priority value to check * @return p on success, 0 on error */ static enum GNUNET_SCHEDULER_Priority check_priority (enum GNUNET_SCHEDULER_Priority p) { if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT)) return p; GNUNET_assert (0); return 0; /* make compiler happy */ } /** * Update all sets and timeout for select. * * @param rs read-set, set to all FDs we would like to read (updated) * @param ws write-set, set to all FDs we would like to write (updated) * @param timeout next timeout (updated) */ static void update_sets (struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws, struct GNUNET_TIME_Relative *timeout) { struct Task *pos; struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Relative to; now = GNUNET_TIME_absolute_get (); pos = pending_timeout; if (NULL != pos) { to = GNUNET_TIME_absolute_get_difference (now, pos->timeout); if (timeout->rel_value_us > to.rel_value_us) *timeout = to; if (pos->reason != 0) *timeout = GNUNET_TIME_UNIT_ZERO; } pos = pending; while (NULL != pos) { if (pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) { to = GNUNET_TIME_absolute_get_difference (now, pos->timeout); if (timeout->rel_value_us > to.rel_value_us) *timeout = to; } if (-1 != pos->read_fd) GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd); if (-1 != pos->write_fd) GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd); if (NULL != pos->read_set) GNUNET_NETWORK_fdset_add (rs, pos->read_set); if (NULL != pos->write_set) GNUNET_NETWORK_fdset_add (ws, pos->write_set); if (0 != pos->reason) *timeout = GNUNET_TIME_UNIT_ZERO; pos = pos->next; } } /** * Check if the ready set overlaps with the set we want to have ready. * If so, update the want set (set all FDs that are ready). If not, * return GNUNET_NO. * * @param ready set that is ready * @param want set that we want to be ready * @return GNUNET_YES if there was some overlap */ static int set_overlaps (const struct GNUNET_NETWORK_FDSet *ready, struct GNUNET_NETWORK_FDSet *want) { if ((NULL == want) || (NULL == ready)) return GNUNET_NO; if (GNUNET_NETWORK_fdset_overlap (ready, want)) { /* copy all over (yes, there maybe unrelated bits, * but this should not hurt well-written clients) */ GNUNET_NETWORK_fdset_copy (want, ready); return GNUNET_YES; } return GNUNET_NO; } /** * Check if the given task is eligible to run now. * Also set the reason why it is eligible. * * @param task task to check if it is ready * @param now the current time * @param rs set of FDs ready for reading * @param ws set of FDs ready for writing * @return #GNUNET_YES if we can run it, #GNUNET_NO if not. */ static int is_ready (struct Task *task, struct GNUNET_TIME_Absolute now, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws) { enum GNUNET_SCHEDULER_Reason reason; reason = task->reason; if (now.abs_value_us >= task->timeout.abs_value_us) reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) && (((task->read_fd != -1) && (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, task->read_fd))) || (set_overlaps (rs, task->read_set)))) reason |= GNUNET_SCHEDULER_REASON_READ_READY; if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && (((task->write_fd != -1) && (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, task->write_fd))) || (set_overlaps (ws, task->write_set)))) reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; if (0 == reason) return GNUNET_NO; /* not ready */ reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; task->reason = reason; return GNUNET_YES; } /** * Put a task that is ready for execution into the ready queue. * * @param task task ready for execution */ static void queue_ready_task (struct Task *task) { enum GNUNET_SCHEDULER_Priority p = task->priority; if (0 != (task->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) p = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN; task->next = ready[check_priority (p)]; ready[check_priority (p)] = task; ready_count++; } /** * Check which tasks are ready and move them * to the respective ready queue. * * @param rs FDs ready for reading * @param ws FDs ready for writing */ static void check_ready (const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws) { struct Task *pos; struct Task *prev; struct Task *next; struct GNUNET_TIME_Absolute now; now = GNUNET_TIME_absolute_get (); prev = NULL; pos = pending_timeout; while (NULL != pos) { next = pos->next; if (now.abs_value_us >= pos->timeout.abs_value_us) pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; if (0 == pos->reason) break; pending_timeout = next; if (pending_timeout_last == pos) pending_timeout_last = NULL; queue_ready_task (pos); pos = next; } pos = pending; while (NULL != pos) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking readiness of task: %llu / %p\n", pos->id, pos->callback_cls); next = pos->next; if (GNUNET_YES == is_ready (pos, now, rs, ws)) { if (NULL == prev) pending = next; else prev->next = next; queue_ready_task (pos); pos = next; continue; } prev = pos; pos = next; } } /** * Request the shutdown of a scheduler. Marks all currently * pending tasks as ready because of shutdown. This will * cause all tasks to run (as soon as possible, respecting * priorities and prerequisite tasks). Note that tasks * scheduled AFTER this call may still be delayed arbitrarily. */ void GNUNET_SCHEDULER_shutdown () { struct Task *pos; int i; pos = pending_timeout; while (NULL != pos) { pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; /* we don't move the task into the ready queue yet; check_ready * will do that later, possibly adding additional * readiness-factors */ pos = pos->next; } pos = pending; while (NULL != pos) { pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; /* we don't move the task into the ready queue yet; check_ready * will do that later, possibly adding additional * readiness-factors */ pos = pos->next; } for (i = 0; i < GNUNET_SCHEDULER_PRIORITY_COUNT; i++) { pos = ready[i]; while (NULL != pos) { pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; /* we don't move the task into the ready queue yet; check_ready * will do that later, possibly adding additional * readiness-factors */ pos = pos->next; } } } /** * Destroy a task (release associated resources) * * @param t task to destroy */ static void destroy_task (struct Task *t) { if (NULL != t->read_set) GNUNET_NETWORK_fdset_destroy (t->read_set); if (NULL != t->write_set) GNUNET_NETWORK_fdset_destroy (t->write_set); #if EXECINFO GNUNET_free (t->backtrace_strings); #endif GNUNET_free (t); } /** * Run at least one task in the highest-priority queue that is not * empty. Keep running tasks until we are either no longer running * "URGENT" tasks or until we have at least one "pending" task (which * may become ready, hence we should select on it). Naturally, if * there are no more ready tasks, we also return. * * @param rs FDs ready for reading * @param ws FDs ready for writing */ static void run_ready (struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws) { enum GNUNET_SCHEDULER_Priority p; struct Task *pos; struct GNUNET_SCHEDULER_TaskContext tc; max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; do { if (0 == ready_count) return; GNUNET_assert (ready[GNUNET_SCHEDULER_PRIORITY_KEEP] == NULL); /* yes, p>0 is correct, 0 is "KEEP" which should * always be an empty queue (see assertion)! */ for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--) { pos = ready[p]; if (NULL != pos) break; } GNUNET_assert (NULL != pos); /* ready_count wrong? */ ready[p] = pos->next; ready_count--; current_priority = pos->priority; current_lifeness = pos->lifeness; active_task = pos; #if PROFILE_DELAYS if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > DELAY_THRESHOLD.rel_value_us) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Task %llu took %s to be scheduled\n", (unsigned long long) pos->id, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), GNUNET_YES)); } #endif tc.reason = pos->reason; tc.read_ready = (pos->read_set == NULL) ? rs : pos->read_set; if ((pos->read_fd != -1) && (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY))) GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd); tc.write_ready = (pos->write_set == NULL) ? ws : pos->write_set; if ((pos->write_fd != -1) && (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd); if (((tc.reason & GNUNET_SCHEDULER_REASON_WRITE_READY) != 0) && (pos->write_fd != -1) && (!GNUNET_NETWORK_fdset_test_native (ws, pos->write_fd))) GNUNET_abort (); // added to ready in previous select loop! LOG (GNUNET_ERROR_TYPE_DEBUG, "Running task: %llu / %p\n", pos->id, pos->callback_cls); pos->callback (pos->callback_cls, &tc); #if EXECINFO int i; for (i = 0; i < pos->num_backtrace_strings; i++) LOG (GNUNET_ERROR_TYPE_ERROR, "Task %llu trace %d: %s\n", pos->id, i, pos->backtrace_strings[i]); #endif active_task = NULL; destroy_task (pos); tasks_run++; } while ((NULL == pending) || (p >= max_priority_added)); } /** * Pipe used to communicate shutdown via signal. */ static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle; /** * Process ID of this process at the time we installed the various * signal handlers. */ static pid_t my_pid; /** * Signal handler called for SIGPIPE. */ #ifndef MINGW static void sighandler_pipe () { return; } #endif /** * Wait for a short time. * Sleeps for @a ms ms (as that should be long enough for virtually all * modern systems to context switch and allow another process to do * some 'real' work). * * @param ms how many ms to wait */ static void short_wait (unsigned int ms) { struct GNUNET_TIME_Relative timeout; timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms); (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); } /** * Signal handler called for signals that should cause us to shutdown. */ static void sighandler_shutdown () { static char c; int old_errno = errno; /* backup errno */ if (getpid () != my_pid) exit (1); /* we have fork'ed since the signal handler was created, * ignore the signal, see https://gnunet.org/vfork discussion */ GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE), &c, sizeof (c)); errno = old_errno; } /** * Check if the system is still life. Trigger shutdown if we * have tasks, but none of them give us lifeness. * * @return #GNUNET_OK to continue the main loop, * #GNUNET_NO to exit */ static int check_lifeness () { struct Task *t; if (ready_count > 0) return GNUNET_OK; for (t = pending; NULL != t; t = t->next) if (t->lifeness == GNUNET_YES) return GNUNET_OK; for (t = pending_timeout; NULL != t; t = t->next) if (t->lifeness == GNUNET_YES) return GNUNET_OK; if ((NULL != pending) || (NULL != pending_timeout)) { GNUNET_SCHEDULER_shutdown (); return GNUNET_OK; } return GNUNET_NO; } /** * Initialize and run scheduler. This function will return when all * tasks have completed. On systems with signals, receiving a SIGTERM * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown() * to be run after the active task is complete. As a result, SIGTERM * causes all active tasks to be scheduled with reason * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added * afterwards will execute normally!). Note that any particular signal * will only shut down one scheduler; applications should always only * create a single scheduler. * * @param task task to run immediately * @param task_cls closure of @a task */ void GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) { struct GNUNET_NETWORK_FDSet *rs; struct GNUNET_NETWORK_FDSet *ws; struct GNUNET_TIME_Relative timeout; int ret; struct GNUNET_SIGNAL_Context *shc_int; struct GNUNET_SIGNAL_Context *shc_term; #if (SIGTERM != GNUNET_TERM_SIG) struct GNUNET_SIGNAL_Context *shc_gterm; #endif #ifndef MINGW struct GNUNET_SIGNAL_Context *shc_quit; struct GNUNET_SIGNAL_Context *shc_hup; struct GNUNET_SIGNAL_Context *shc_pipe; #endif unsigned long long last_tr; unsigned int busy_wait_warning; const struct GNUNET_DISK_FileHandle *pr; char c; GNUNET_assert (NULL == active_task); rs = GNUNET_NETWORK_fdset_create (); ws = GNUNET_NETWORK_fdset_create (); GNUNET_assert (NULL == shutdown_pipe_handle); shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); GNUNET_assert (NULL != shutdown_pipe_handle); pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_READ); GNUNET_assert (pr != NULL); my_pid = getpid (); LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering signal handlers\n"); shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown); #if (SIGTERM != GNUNET_TERM_SIG) shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, &sighandler_shutdown); #endif #ifndef MINGW shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, &sighandler_pipe); shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, &sighandler_shutdown); shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown); #endif current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; current_lifeness = GNUNET_YES; GNUNET_SCHEDULER_add_continuation (task, task_cls, GNUNET_SCHEDULER_REASON_STARTUP); active_task = (void *) (long) -1; /* force passing of sanity check */ GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, &GNUNET_OS_install_parent_control_handler, NULL); active_task = NULL; last_tr = 0; busy_wait_warning = 0; while (GNUNET_OK == check_lifeness ()) { GNUNET_NETWORK_fdset_zero (rs); GNUNET_NETWORK_fdset_zero (ws); timeout = GNUNET_TIME_UNIT_FOREVER_REL; update_sets (rs, ws, &timeout); GNUNET_NETWORK_fdset_handle_set (rs, pr); if (ready_count > 0) { /* no blocking, more work already ready! */ timeout = GNUNET_TIME_UNIT_ZERO; } if (NULL == scheduler_select) ret = GNUNET_NETWORK_socket_select (rs, ws, NULL, timeout); else ret = scheduler_select (scheduler_select_cls, rs, ws, NULL, timeout); if (ret == GNUNET_SYSERR) { if (errno == EINTR) continue; LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "select"); #ifndef MINGW #if USE_LSOF char lsof[512]; snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid ()); (void) close (1); (void) dup2 (2, 1); if (0 != system (lsof)) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "system"); #endif #endif GNUNET_abort (); break; } if ( (0 == ret) && (0 == timeout.rel_value_us) && (busy_wait_warning > 16) ) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Looks like we're busy waiting...\n")); short_wait (100); /* mitigate */ } check_ready (rs, ws); run_ready (rs, ws); if (GNUNET_NETWORK_fdset_handle_isset (rs, pr)) { /* consume the signal */ GNUNET_DISK_file_read (pr, &c, sizeof (c)); /* mark all active tasks as ready due to shutdown */ GNUNET_SCHEDULER_shutdown (); } if (last_tr == tasks_run) { short_wait (1); busy_wait_warning++; } else { last_tr = tasks_run; busy_wait_warning = 0; } } GNUNET_SIGNAL_handler_uninstall (shc_int); GNUNET_SIGNAL_handler_uninstall (shc_term); #if (SIGTERM != GNUNET_TERM_SIG) GNUNET_SIGNAL_handler_uninstall (shc_gterm); #endif #ifndef MINGW GNUNET_SIGNAL_handler_uninstall (shc_pipe); GNUNET_SIGNAL_handler_uninstall (shc_quit); GNUNET_SIGNAL_handler_uninstall (shc_hup); #endif GNUNET_DISK_pipe_close (shutdown_pipe_handle); shutdown_pipe_handle = NULL; GNUNET_NETWORK_fdset_destroy (rs); GNUNET_NETWORK_fdset_destroy (ws); } /** * Obtain the reason code for why the current task was * started. Will return the same value as * the `struct GNUNET_SCHEDULER_TaskContext`'s reason field. * * @return reason(s) why the current task is run */ enum GNUNET_SCHEDULER_Reason GNUNET_SCHEDULER_get_reason () { GNUNET_assert (active_task != NULL); return active_task->reason; } /** * Get information about the current load of this scheduler. Use this * function to determine if an elective task should be added or simply * dropped (if the decision should be made based on the number of * tasks ready to run). * * @param p priority level to look at * @return number of tasks pending right now */ unsigned int GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) { struct Task *pos; unsigned int ret; GNUNET_assert (active_task != NULL); if (p == GNUNET_SCHEDULER_PRIORITY_COUNT) return ready_count; if (p == GNUNET_SCHEDULER_PRIORITY_KEEP) p = current_priority; ret = 0; pos = ready[check_priority (p)]; while (NULL != pos) { pos = pos->next; ret++; } return ret; } /** * Cancel the task with the specified identifier. * The task must not yet have run. * * @param task id of the task to cancel * @return original closure of the task */ void * GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task) { struct Task *t; struct Task *prev; enum GNUNET_SCHEDULER_Priority p; int to; void *ret; GNUNET_assert (NULL != active_task); to = 0; prev = NULL; t = pending; while (NULL != t) { if (t->id == task) break; prev = t; t = t->next; } if (NULL == t) { prev = NULL; to = 1; t = pending_timeout; while (t != NULL) { if (t->id == task) break; prev = t; t = t->next; } if (pending_timeout_last == t) pending_timeout_last = NULL; } p = 0; while (NULL == t) { p++; if (p >= GNUNET_SCHEDULER_PRIORITY_COUNT) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Attempt to cancel dead task %llu!\n"), (unsigned long long) task); GNUNET_assert (0); } prev = NULL; t = ready[p]; while (NULL != t) { if (t->id == task) { ready_count--; break; } prev = t; t = t->next; } } if (NULL == prev) { if (0 == p) { if (0 == to) { pending = t->next; } else { pending_timeout = t->next; } } else { ready[p] = t->next; } } else { prev->next = t->next; } ret = t->callback_cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Canceling task: %llu / %p\n", task, t->callback_cls); destroy_task (t); return ret; } /** * Continue the current execution with the given function. This is * similar to the other "add" functions except that there is no delay * and the reason code can be specified. * * @param task main function of the task * @param task_cls closure for @a task * @param reason reason for task invocation * @param priority priority to use for the task */ void GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, void *task_cls, enum GNUNET_SCHEDULER_Reason reason, enum GNUNET_SCHEDULER_Priority priority) { struct Task *t; #if EXECINFO void *backtrace_array[50]; #endif GNUNET_assert (NULL != task); GNUNET_assert ((NULL != active_task) || (GNUNET_SCHEDULER_REASON_STARTUP == reason)); t = GNUNET_new (struct Task); #if EXECINFO t->num_backtrace_strings = backtrace (backtrace_array, 50); t->backtrace_strings = backtrace_symbols (backtrace_array, t->num_backtrace_strings); #endif t->read_fd = -1; t->write_fd = -1; t->callback = task; t->callback_cls = task_cls; t->id = ++last_id; #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); #endif t->reason = reason; t->priority = priority; t->lifeness = current_lifeness; LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding continuation task: %llu / %p\n", t->id, t->callback_cls); queue_ready_task (t); } /** * Continue the current execution with the given function. This is * similar to the other "add" functions except that there is no delay * and the reason code can be specified. * * @param task main function of the task * @param task_cls closure for @a task * @param reason reason for task invocation */ void GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, void *task_cls, enum GNUNET_SCHEDULER_Reason reason) { GNUNET_SCHEDULER_add_continuation_with_priority (task, task_cls, reason, GNUNET_SCHEDULER_PRIORITY_DEFAULT); } /** * Schedule a new task to be run with a specified priority. * * @param prio how important is the new task? * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_Task task, void *task_cls) { return GNUNET_SCHEDULER_add_select (prio, GNUNET_TIME_UNIT_ZERO, NULL, NULL, task, task_cls); } /** * Schedule a new task to be run with a specified delay. The task * will be scheduled for execution once the delay has expired. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param priority priority to use for the task * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_Task task, void *task_cls) { struct Task *t; struct Task *pos; struct Task *prev; #if EXECINFO void *backtrace_array[MAX_TRACE_DEPTH]; #endif GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); t = GNUNET_new (struct Task); t->callback = task; t->callback_cls = task_cls; #if EXECINFO t->num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH); t->backtrace_strings = backtrace_symbols (backtrace_array, t->num_backtrace_strings); #endif t->read_fd = -1; t->write_fd = -1; t->id = ++last_id; #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); #endif t->timeout = GNUNET_TIME_relative_to_absolute (delay); t->priority = priority; t->lifeness = current_lifeness; /* try tail first (optimization in case we are * appending to a long list of tasks with timeouts) */ prev = pending_timeout_last; if (prev != NULL) { if (prev->timeout.abs_value_us > t->timeout.abs_value_us) prev = NULL; else pos = prev->next; /* heuristic success! */ } if (prev == NULL) { /* heuristic failed, do traversal of timeout list */ pos = pending_timeout; } while ((pos != NULL) && ((pos->timeout.abs_value_us <= t->timeout.abs_value_us) || (0 != pos->reason))) { prev = pos; pos = pos->next; } if (prev == NULL) pending_timeout = t; else prev->next = t; t->next = pos; /* hyper-optimization... */ pending_timeout_last = t; LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding task: %llu / %p\n", t->id, t->callback_cls); #if EXECINFO int i; for (i = 0; i < t->num_backtrace_strings; i++) LOG (GNUNET_ERROR_TYPE_DEBUG, "Task %llu trace %d: %s\n", t->id, i, t->backtrace_strings[i]); #endif return t->id; } /** * Schedule a new task to be run with a specified delay. The task * will be scheduled for execution once the delay has expired. It * will be run with the DEFAULT priority. * * @param delay when should this operation time out? Use * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param task main function of the task * @param task_cls closure of task * @return unique task identifier for the job * only valid until "task" is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_Task task, void *task_cls) { return GNUNET_SCHEDULER_add_delayed_with_priority (delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, task, task_cls); } /** * Schedule a new task to be run as soon as possible. Note that this * does not guarantee that this will be the next task that is being * run, as other tasks with higher priority (or that are already ready * to run) might get to run first. Just as with delays, clients must * not rely on any particular order of execution between tasks * scheduled concurrently. * * The task will be run with the DEFAULT priority. * * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until "task" is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, void *task_cls) { return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, task, task_cls); } /** * Schedule a new task to be run as soon as possible with the * (transitive) ignore-shutdown flag either explicitly set or * explicitly enabled. This task (and all tasks created from it, * other than by another call to this function) will either count or * not count for the "lifeness" of the process. This API is only * useful in a few special cases. * * @param lifeness #GNUNET_YES if the task counts for lifeness, #GNUNET_NO if not. * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, GNUNET_SCHEDULER_Task task, void *task_cls) { GNUNET_SCHEDULER_TaskIdentifier ret; ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_UNIT_ZERO, NULL, NULL, task, task_cls); GNUNET_assert (pending->id == ret); pending->lifeness = lifeness; return ret; } /** * Schedule a new task to be run with a specified delay or when any of * the specified file descriptor sets is ready. The delay can be used * as a timeout on the socket(s) being ready. The task will be * scheduled for execution once either the delay has expired or any of * the socket operations is ready. This is the most general * function of the "add" family. Note that the "prerequisite_task" * must be satisfied in addition to any of the other conditions. In * other words, the task will be started when * * (prerequisite-run) * && (delay-ready * || any-rs-ready * || any-ws-ready * || shutdown-active ) * * * @param delay how long should we wait? Use #GNUNET_TIME_UNIT_FOREVER_REL for "forever", * which means that the task will only be run after we receive SIGTERM * @param priority priority to use * @param rfd file descriptor we want to read (can be -1) * @param wfd file descriptors we want to write (can be -1) * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until "task" is started! */ #ifndef MINGW static GNUNET_SCHEDULER_TaskIdentifier add_without_sets (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, int rfd, int wfd, GNUNET_SCHEDULER_Task task, void *task_cls) { struct Task *t; #if EXECINFO void *backtrace_array[MAX_TRACE_DEPTH]; #endif GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); t = GNUNET_new (struct Task); t->callback = task; t->callback_cls = task_cls; #if EXECINFO t->num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH); t->backtrace_strings = backtrace_symbols (backtrace_array, t->num_backtrace_strings); #endif #if DEBUG_FDS if (-1 != rfd) { int flags = fcntl (rfd, F_GETFD); if ((flags == -1) && (errno == EBADF)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Got invalid file descriptor %d!\n", rfd); #if EXECINFO int i; for (i = 0; i < t->num_backtrace_strings; i++) LOG (GNUNET_ERROR_TYPE_DEBUG, "Trace: %s\n", t->backtrace_strings[i]); #endif GNUNET_assert (0); } } if (-1 != wfd) { int flags = fcntl (wfd, F_GETFD); if (flags == -1 && errno == EBADF) { LOG (GNUNET_ERROR_TYPE_ERROR, "Got invalid file descriptor %d!\n", wfd); #if EXECINFO int i; for (i = 0; i < t->num_backtrace_strings; i++) LOG (GNUNET_ERROR_TYPE_DEBUG, "Trace: %s\n", t->backtrace_strings[i]); #endif GNUNET_assert (0); } } #endif t->read_fd = rfd; GNUNET_assert (wfd >= -1); t->write_fd = wfd; t->id = ++last_id; #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); #endif t->timeout = GNUNET_TIME_relative_to_absolute (delay); t->priority = check_priority ((priority == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : priority); t->lifeness = current_lifeness; t->next = pending; pending = t; max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding task: %llu / %p\n", t->id, t->callback_cls); #if EXECINFO int i; for (i = 0; i < t->num_backtrace_strings; i++) LOG (GNUNET_ERROR_TYPE_DEBUG, "Task %llu trace %d: %s\n", t->id, i, t->backtrace_strings[i]); #endif return t->id; } #endif /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready for reading. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param rfd read file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_Task task, void *task_cls) { return GNUNET_SCHEDULER_add_read_net_with_priority (delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, rfd, task, task_cls); } /** * Schedule a new task to be run with a specified priority and to be * run after the specified delay or when the specified file descriptor * is ready for reading. The delay can be used as a timeout on the * socket being ready. The task will be scheduled for execution once * either the delay has expired or the socket operation is ready. It * will be run with the DEFAULT priority. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param priority priority to use for the task * @param rfd read file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_Task task, void *task_cls) { return GNUNET_SCHEDULER_add_net_with_priority ( delay, priority, rfd, GNUNET_YES, GNUNET_NO, task, task_cls); } /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready for writing. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the priority of * the calling task. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param wfd write file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_Task task, void *task_cls) { return GNUNET_SCHEDULER_add_net_with_priority ( delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, wfd, GNUNET_NO, GNUNET_YES, task, task_cls); } /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. * * @param delay when should this operation time out? Use * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param priority priority of the task * @param fd file-descriptor * @param on_read whether to poll the file-descriptor for readability * @param on_write whether to poll the file-descriptor for writability * @param task main function of the task * @param task_cls closure of task * @return unique task identifier for the job * only valid until "task" is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *fd, int on_read, int on_write, GNUNET_SCHEDULER_Task task, void *task_cls) { #if MINGW struct GNUNET_NETWORK_FDSet *s; GNUNET_SCHEDULER_TaskIdentifier ret; GNUNET_assert (fd != NULL); s = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_set (s, fd); ret = GNUNET_SCHEDULER_add_select ( priority, delay, on_read ? s : NULL, on_write ? s : NULL, task, task_cls); GNUNET_NETWORK_fdset_destroy (s); return ret; #else GNUNET_assert (GNUNET_NETWORK_get_fd (fd) >= 0); return add_without_sets ( delay, priority, on_read ? GNUNET_NETWORK_get_fd (fd) : -1, on_write ? GNUNET_NETWORK_get_fd (fd) : -1, task, task_cls); #endif } /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready for reading. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param rfd read file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_Task task, void *task_cls) { return GNUNET_SCHEDULER_add_file_with_priority ( delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, rfd, GNUNET_YES, GNUNET_NO, task, task_cls); } /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready for writing. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. It will be run with the DEFAULT priority. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param wfd write file-descriptor * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *wfd, GNUNET_SCHEDULER_Task task, void *task_cls) { return GNUNET_SCHEDULER_add_file_with_priority ( delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, wfd, GNUNET_NO, GNUNET_YES, task, task_cls); } /** * Schedule a new task to be run with a specified delay or when the * specified file descriptor is ready. The delay can be * used as a timeout on the socket being ready. The task will be * scheduled for execution once either the delay has expired or the * socket operation is ready. * * @param delay when should this operation time out? Use * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" * @param priority priority of the task * @param fd file-descriptor * @param on_read whether to poll the file-descriptor for readability * @param on_write whether to poll the file-descriptor for writability * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_DISK_FileHandle *fd, int on_read, int on_write, GNUNET_SCHEDULER_Task task, void *task_cls) { #if MINGW struct GNUNET_NETWORK_FDSet *s; GNUNET_SCHEDULER_TaskIdentifier ret; GNUNET_assert (fd != NULL); s = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_handle_set (s, fd); ret = GNUNET_SCHEDULER_add_select ( priority, delay, on_read ? s : NULL, on_write ? s : NULL, task, task_cls); GNUNET_NETWORK_fdset_destroy (s); return ret; #else int real_fd; GNUNET_DISK_internal_file_handle_ (fd, &real_fd, sizeof (int)); GNUNET_assert (real_fd >= 0); return add_without_sets ( delay, priority, on_read ? real_fd : -1, on_write ? real_fd : -1, task, task_cls); #endif } /** * Schedule a new task to be run with a specified delay or when any of * the specified file descriptor sets is ready. The delay can be used * as a timeout on the socket(s) being ready. The task will be * scheduled for execution once either the delay has expired or any of * the socket operations is ready. This is the most general * function of the "add" family. Note that the "prerequisite_task" * must be satisfied in addition to any of the other conditions. In * other words, the task will be started when * * (prerequisite-run) * && (delay-ready * || any-rs-ready * || any-ws-ready * || (shutdown-active && run-on-shutdown) ) * * * @param prio how important is this task? * @param delay how long should we wait? Use #GNUNET_TIME_UNIT_FOREVER_REL for "forever", * which means that the task will only be run after we receive SIGTERM * @param rs set of file descriptors we want to read (can be NULL) * @param ws set of file descriptors we want to write (can be NULL) * @param task main function of the task * @param task_cls closure of @a task * @return unique task identifier for the job * only valid until @a task is started! */ GNUNET_SCHEDULER_TaskIdentifier GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_Task task, void *task_cls) { struct Task *t; #if EXECINFO void *backtrace_array[MAX_TRACE_DEPTH]; #endif GNUNET_assert (NULL != active_task); GNUNET_assert (NULL != task); t = GNUNET_new (struct Task); t->callback = task; t->callback_cls = task_cls; #if EXECINFO t->num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH); t->backtrace_strings = backtrace_symbols (backtrace_array, t->num_backtrace_strings); #endif t->read_fd = -1; t->write_fd = -1; if (NULL != rs) { t->read_set = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_copy (t->read_set, rs); } if (NULL != ws) { t->write_set = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_copy (t->write_set, ws); } t->id = ++last_id; #if PROFILE_DELAYS t->start_time = GNUNET_TIME_absolute_get (); #endif t->timeout = GNUNET_TIME_relative_to_absolute (delay); t->priority = check_priority ((prio == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : prio); t->lifeness = current_lifeness; t->next = pending; pending = t; max_priority_added = GNUNET_MAX (max_priority_added, t->priority); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding task: %llu / %p\n", t->id, t->callback_cls); #if EXECINFO int i; for (i = 0; i < t->num_backtrace_strings; i++) LOG (GNUNET_ERROR_TYPE_DEBUG, "Task %llu trace %d: %s\n", t->id, i, t->backtrace_strings[i]); #endif return t->id; } /* end of scheduler.c */ gnunet-0.10.1/src/util/test_common_logging_dummy.c0000644000175000017500000000633512254265741017211 00000000000000/* This file is part of GNUnet. (C) 2008-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_common_logging_dummy.c * @brief dummy labrat for the testcase for the logging module (runtime * log level adjustment) * @author LRN */ #include "platform.h" #undef GNUNET_EXTRA_LOGGING #define GNUNET_EXTRA_LOGGING GNUNET_YES #include "gnunet_util_lib.h" /** * Artificial delay attached to each log call that is not skipped out. * This must be long enough for us to not to mistake skipped log call * on a slow machine for a non-skipped one. */ #define OUTPUT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, 1000) static void my_log (void *ctx, enum GNUNET_ErrorType kind, const char *component, const char *date, const char *msg) { if (strncmp ("test-common-logging-dummy", component, 25) != 0) return; FPRINTF (stdout, "%s", msg); fflush (stdout); } static int expensive_func () { return GNUNET_NETWORK_socket_select (NULL, NULL, NULL, OUTPUT_DELAY); } #define pr(kind,lvl) {\ struct GNUNET_TIME_Absolute t1, t2;\ t1 = GNUNET_TIME_absolute_get ();\ GNUNET_log (kind, "L%s %d\n", lvl, expensive_func());\ t2 = GNUNET_TIME_absolute_get ();\ printf ("1%s %llu\n", lvl,\ (unsigned long long) GNUNET_TIME_absolute_get_difference (t1, t2).rel_value_us); \ } #define pr2(kind,lvl) {\ struct GNUNET_TIME_Absolute t1, t2;\ t1 = GNUNET_TIME_absolute_get ();\ GNUNET_log (kind, "L%s %d\n", lvl, expensive_func());\ t2 = GNUNET_TIME_absolute_get ();\ printf ("2%s %llu\n", lvl,\ (unsigned long long) GNUNET_TIME_absolute_get_difference (t1, t2).rel_value_us); \ } int main (int argc, char *argv[]) { /* We set up logging with NULL level - will be overrided by * GNUNET_LOG or GNUNET_FORCE_LOG at runtime. */ GNUNET_log_setup ("test-common-logging-dummy", NULL, "/dev/null"); GNUNET_logger_add (&my_log, NULL); pr (GNUNET_ERROR_TYPE_ERROR, "ERROR"); pr (GNUNET_ERROR_TYPE_WARNING, "WARNING"); pr (GNUNET_ERROR_TYPE_INFO, "INFO"); pr (GNUNET_ERROR_TYPE_DEBUG, "DEBUG"); /* We set up logging with WARNING level - will onle be overrided by * GNUNET_FORCE_LOG at runtime. */ GNUNET_log_setup ("test-common-logging-dummy", "WARNING", "/dev/null"); pr2 (GNUNET_ERROR_TYPE_ERROR, "ERROR"); pr2 (GNUNET_ERROR_TYPE_WARNING, "WARNING"); pr2 (GNUNET_ERROR_TYPE_INFO, "INFO"); pr2 (GNUNET_ERROR_TYPE_DEBUG, "DEBUG"); return 0; } /* end of main */ /* end of test_common_logging_dummy.c */ gnunet-0.10.1/src/util/test_connection_transmit_cancel.c0000644000175000017500000000434112225777501020360 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_connection_transmit_cancel.c * @brief tests for connection.c */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 12435 static struct GNUNET_CONFIGURATION_Handle *cfg; static size_t not_run (void *cls, size_t size, void *buf) { GNUNET_assert (0); return 0; } static void task_transmit_cancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int *ok = cls; struct GNUNET_CONNECTION_TransmitHandle *th; struct GNUNET_CONNECTION_Handle *csock; csock = GNUNET_CONNECTION_create_from_connect (cfg, "localhost", PORT); GNUNET_assert (csock != NULL); th = GNUNET_CONNECTION_notify_transmit_ready (csock, 12, GNUNET_TIME_UNIT_MINUTES, ¬_run, cls); GNUNET_assert (NULL != th); GNUNET_CONNECTION_notify_transmit_ready_cancel (th); GNUNET_CONNECTION_destroy (csock); *ok = 0; } int main (int argc, char *argv[]) { int ok; GNUNET_log_setup ("test_connection_transmit_cancel", "WARNING", NULL); ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); GNUNET_SCHEDULER_run (&task_transmit_cancel, &ok); GNUNET_CONFIGURATION_destroy (cfg); return ok; } /* end of test_connection_transmit_cancel.c */ gnunet-0.10.1/src/util/test_crypto_eddsa.c0000644000175000017500000001342012236654562015454 00000000000000/* This file is part of GNUnet. (C) 2002-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_crypto_eddsa.c * @brief testcase for ECC public key crypto * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_signatures.h" #include #define ITER 25 #define KEYFILE "/tmp/test-gnunet-crypto-eddsa.key" #define PERF GNUNET_YES static struct GNUNET_CRYPTO_EddsaPrivateKey *key; static int testSignVerify () { struct GNUNET_CRYPTO_EddsaSignature sig; struct GNUNET_CRYPTO_EccSignaturePurpose purp; struct GNUNET_CRYPTO_EddsaPublicKey pkey; int i; struct GNUNET_TIME_Absolute start; int ok = GNUNET_OK; FPRINTF (stderr, "%s", "W"); GNUNET_CRYPTO_eddsa_key_get_public (key, &pkey); start = GNUNET_TIME_absolute_get (); purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); for (i = 0; i < ITER; i++) { FPRINTF (stderr, "%s", "."); fflush (stderr); if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_sign (key, &purp, &sig)) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_eddsa_sign returned SYSERR\n"); ok = GNUNET_SYSERR; continue; } if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig, &pkey)) { printf ("GNUNET_CRYPTO_eddsa_verify failed!\n"); ok = GNUNET_SYSERR; continue; } if (GNUNET_SYSERR != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, &purp, &sig, &pkey)) { printf ("GNUNET_CRYPTO_eddsa_verify failed to fail!\n"); ok = GNUNET_SYSERR; continue; } } printf ("%d EdDSA sign/verify operations %s\n", ITER, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); return ok; } #if PERF static int testSignPerformance () { struct GNUNET_CRYPTO_EccSignaturePurpose purp; struct GNUNET_CRYPTO_EddsaSignature sig; struct GNUNET_CRYPTO_EddsaPublicKey pkey; int i; struct GNUNET_TIME_Absolute start; int ok = GNUNET_OK; purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); FPRINTF (stderr, "%s", "W"); GNUNET_CRYPTO_eddsa_key_get_public (key, &pkey); start = GNUNET_TIME_absolute_get (); for (i = 0; i < ITER; i++) { FPRINTF (stderr, "%s", "."); fflush (stderr); if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_sign (key, &purp, &sig)) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_eddsa_sign returned SYSERR\n"); ok = GNUNET_SYSERR; continue; } } printf ("%d EdDSA sign operations %s\n", ITER, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); return ok; } #endif static int testCreateFromFile () { struct GNUNET_CRYPTO_EddsaPublicKey p1; struct GNUNET_CRYPTO_EddsaPublicKey p2; key = GNUNET_CRYPTO_eddsa_key_create_from_file (KEYFILE); GNUNET_assert (NULL != key); GNUNET_CRYPTO_eddsa_key_get_public (key, &p1); GNUNET_free (key); key = GNUNET_CRYPTO_eddsa_key_create_from_file (KEYFILE); GNUNET_assert (NULL != key); GNUNET_CRYPTO_eddsa_key_get_public (key, &p2); GNUNET_assert (0 == memcmp (&p1, &p2, sizeof (p1))); GNUNET_free (key); GNUNET_assert (0 == UNLINK (KEYFILE)); key = GNUNET_CRYPTO_eddsa_key_create_from_file (KEYFILE); GNUNET_assert (NULL != key); GNUNET_CRYPTO_eddsa_key_get_public (key, &p2); GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1))); GNUNET_free (key); return GNUNET_OK; } static void perf_keygen () { struct GNUNET_TIME_Absolute start; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; int i; FPRINTF (stderr, "%s", "W"); start = GNUNET_TIME_absolute_get (); for (i=0;i<10;i++) { fprintf (stderr, "."); fflush (stderr); pk = GNUNET_CRYPTO_eddsa_key_create (); GNUNET_free (pk); } for (;i<25;i++) fprintf (stderr, "."); fflush (stderr); printf ("10 EdDSA keys created in %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); } int main (int argc, char *argv[]) { int failure_count = 0; if (! gcry_check_version ("1.6.0")) { FPRINTF (stderr, _("libgcrypt has not the expected version (version %s is required).\n"), "1.6.0"); return 0; } if (getenv ("GNUNET_GCRYPT_DEBUG")) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); GNUNET_log_setup ("test-crypto-eddsa", "WARNING", NULL); key = GNUNET_CRYPTO_eddsa_key_create (); #if PERF if (GNUNET_OK != testSignPerformance ()) failure_count++; #endif if (GNUNET_OK != testSignVerify ()) failure_count++; GNUNET_free (key); if (GNUNET_OK != testCreateFromFile ()) failure_count++; GNUNET_assert (0 == UNLINK (KEYFILE)); perf_keygen (); if (0 != failure_count) { fprintf (stderr, "\n\n%d TESTS FAILED!\n\n", failure_count); return -1; } return 0; } /* end of test_crypto_eddsa.c */ gnunet-0.10.1/src/util/strings.c0000644000175000017500000014236012263473436013433 00000000000000/* This file is part of GNUnet. (C) 2005-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/strings.c * @brief string functions * @author Nils Durner * @author Christian Grothoff */ #include "platform.h" #if HAVE_ICONV #include #endif #include "gnunet_util_lib.h" #include #include #include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) /** * Fill a buffer of the given size with * count 0-terminated strings (given as varargs). * If "buffer" is NULL, only compute the amount of * space required (sum of "strlen(arg)+1"). * * Unlike using "snprintf" with "%s", this function * will add 0-terminators after each string. The * "GNUNET_string_buffer_tokenize" function can be * used to parse the buffer back into individual * strings. * * @param buffer the buffer to fill with strings, can * be NULL in which case only the necessary * amount of space will be calculated * @param size number of bytes available in buffer * @param count number of strings that follow * @param ... count 0-terminated strings to copy to buffer * @return number of bytes written to the buffer * (or number of bytes that would have been written) */ size_t GNUNET_STRINGS_buffer_fill (char *buffer, size_t size, unsigned int count, ...) { size_t needed; size_t slen; const char *s; va_list ap; needed = 0; va_start (ap, count); while (count > 0) { s = va_arg (ap, const char *); slen = strlen (s) + 1; if (buffer != NULL) { GNUNET_assert (needed + slen <= size); memcpy (&buffer[needed], s, slen); } needed += slen; count--; } va_end (ap); return needed; } /** * Given a buffer of a given size, find "count" * 0-terminated strings in the buffer and assign * the count (varargs) of type "const char**" to the * locations of the respective strings in the * buffer. * * @param buffer the buffer to parse * @param size size of the buffer * @param count number of strings to locate * @return offset of the character after the last 0-termination * in the buffer, or 0 on error. */ unsigned int GNUNET_STRINGS_buffer_tokenize (const char *buffer, size_t size, unsigned int count, ...) { unsigned int start; unsigned int needed; const char **r; va_list ap; needed = 0; va_start (ap, count); while (count > 0) { r = va_arg (ap, const char **); start = needed; while ((needed < size) && (buffer[needed] != '\0')) needed++; if (needed == size) { va_end (ap); return 0; /* error */ } *r = &buffer[start]; needed++; /* skip 0-termination */ count--; } va_end (ap); return needed; } /** * Convert a given filesize into a fancy human-readable format. * * @param size number of bytes * @return fancy representation of the size (possibly rounded) for humans */ char * GNUNET_STRINGS_byte_size_fancy (unsigned long long size) { const char *unit = _( /* size unit */ "b"); char *ret; if (size > 5 * 1024) { size = size / 1024; unit = "KiB"; if (size > 5 * 1024) { size = size / 1024; unit = "MiB"; if (size > 5 * 1024) { size = size / 1024; unit = "GiB"; if (size > 5 * 1024) { size = size / 1024; unit = "TiB"; } } } } ret = GNUNET_malloc (32); GNUNET_snprintf (ret, 32, "%llu %s", size, unit); return ret; } /** * Unit conversion table entry for 'convert_with_table'. */ struct ConversionTable { /** * Name of the unit (or NULL for end of table). */ const char *name; /** * Factor to apply for this unit. */ unsigned long long value; }; /** * Convert a string of the form "4 X 5 Y" into a numeric value * by interpreting "X" and "Y" as units and then multiplying * the numbers with the values associated with the respective * unit from the conversion table. * * @param input input string to parse * @param table table with the conversion of unit names to numbers * @param output where to store the result * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int convert_with_table (const char *input, const struct ConversionTable *table, unsigned long long *output) { unsigned long long ret; char *in; const char *tok; unsigned long long last; unsigned int i; ret = 0; last = 0; in = GNUNET_strdup (input); for (tok = strtok (in, " "); tok != NULL; tok = strtok (NULL, " ")) { do { i = 0; while ((table[i].name != NULL) && (0 != strcasecmp (table[i].name, tok))) i++; if (table[i].name != NULL) { last *= table[i].value; break; /* next tok */ } else { char *endptr; ret += last; errno = 0; last = strtoull (tok, &endptr, 10); if ((0 != errno) || (endptr == tok)) { GNUNET_free (in); return GNUNET_SYSERR; /* expected number */ } if ('\0' == endptr[0]) break; /* next tok */ else tok = endptr; /* and re-check (handles times like "10s") */ } } while (GNUNET_YES); } ret += last; *output = ret; GNUNET_free (in); return GNUNET_OK; } /** * Convert a given fancy human-readable size to bytes. * * @param fancy_size human readable string (i.e. 1 MB) * @param size set to the size in bytes * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_STRINGS_fancy_size_to_bytes (const char *fancy_size, unsigned long long *size) { static const struct ConversionTable table[] = { { "B", 1}, { "KiB", 1024}, { "kB", 1000}, { "MiB", 1024 * 1024}, { "MB", 1000 * 1000}, { "GiB", 1024 * 1024 * 1024}, { "GB", 1000 * 1000 * 1000}, { "TiB", 1024LL * 1024LL * 1024LL * 1024LL}, { "TB", 1000LL * 1000LL * 1000LL * 1024LL}, { "PiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL}, { "PB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL}, { "EiB", 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL}, { "EB", 1000LL * 1000LL * 1000LL * 1024LL * 1000LL * 1000LL}, { NULL, 0} }; return convert_with_table (fancy_size, table, size); } /** * Convert a given fancy human-readable time to our internal * representation. * * @param fancy_time human readable string (i.e. 1 minute) * @param rtime set to the relative time * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time, struct GNUNET_TIME_Relative *rtime) { static const struct ConversionTable table[] = { { "us", 1}, { "ms", 1000 }, { "s", 1000 * 1000LL }, { "\"", 1000 * 1000LL }, { "m", 60 * 1000 * 1000LL}, { "min", 60 * 1000 * 1000LL}, { "minutes", 60 * 1000 * 1000LL}, { "'", 60 * 1000 * 1000LL}, { "h", 60 * 60 * 1000 * 1000LL}, { "d", 24 * 60 * 60 * 1000LL * 1000LL}, { "day", 24 * 60 * 60 * 1000LL * 1000LL}, { "days", 24 * 60 * 60 * 1000LL * 1000LL}, { "week", 7 * 24 * 60 * 60 * 1000LL * 1000LL}, { "weeks", 7 * 24 * 60 * 60 * 1000LL * 1000LL}, { "a", 31536000000000LL /* year */ }, { NULL, 0} }; int ret; unsigned long long val; if (0 == strcasecmp ("forever", fancy_time)) { *rtime = GNUNET_TIME_UNIT_FOREVER_REL; return GNUNET_OK; } ret = convert_with_table (fancy_time, table, &val); rtime->rel_value_us = (uint64_t) val; return ret; } /** * Convert a given fancy human-readable time to our internal * representation. The human-readable time is expected to be * in local time, whereas the returned value will be in UTC. * * @param fancy_time human readable string (i.e. %Y-%m-%d %H:%M:%S) * @param atime set to the absolute time * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time, struct GNUNET_TIME_Absolute *atime) { struct tm tv; time_t t; if (0 == strcasecmp ("end of time", fancy_time)) { *atime = GNUNET_TIME_UNIT_FOREVER_ABS; return GNUNET_OK; } memset (&tv, 0, sizeof (tv)); if ( (NULL == strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) && (NULL == strptime (fancy_time, "%c", &tv)) && (NULL == strptime (fancy_time, "%Ec", &tv)) && (NULL == strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) && (NULL == strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) && (NULL == strptime (fancy_time, "%x", &tv)) && (NULL == strptime (fancy_time, "%Ex", &tv)) && (NULL == strptime (fancy_time, "%Y-%m-%d", &tv)) && (NULL == strptime (fancy_time, "%Y-%m", &tv)) && (NULL == strptime (fancy_time, "%Y", &tv)) ) return GNUNET_SYSERR; t = mktime (&tv); atime->abs_value_us = (uint64_t) ((uint64_t) t * 1000LL * 1000LL); return GNUNET_OK; } /** * Convert the len characters long character sequence * given in input that is in the given input charset * to a string in given output charset. * * @param input input string * @param len number of bytes in @a input * @param input_charset character set used for @a input * @param output_charset desired character set for the return value * @return the converted string (0-terminated), * if conversion fails, a copy of the orignal * string is returned. */ char * GNUNET_STRINGS_conv (const char *input, size_t len, const char *input_charset, const char *output_charset) { char *ret; uint8_t *u8_string; char *encoded_string; size_t u8_string_length; size_t encoded_string_length; u8_string = u8_conv_from_encoding (input_charset, iconveh_error, input, len, NULL, NULL, &u8_string_length); if (NULL == u8_string) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_from_encoding"); goto fail; } if (0 == strcmp (output_charset, "UTF-8")) { ret = GNUNET_malloc (u8_string_length + 1); memcpy (ret, u8_string, u8_string_length); ret[u8_string_length] = '\0'; free (u8_string); return ret; } encoded_string = u8_conv_to_encoding (output_charset, iconveh_error, u8_string, u8_string_length, NULL, NULL, &encoded_string_length); free (u8_string); if (NULL == encoded_string) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_to_encoding"); goto fail; } ret = GNUNET_malloc (encoded_string_length + 1); memcpy (ret, encoded_string, encoded_string_length); ret[encoded_string_length] = '\0'; free (encoded_string); return ret; fail: LOG (GNUNET_ERROR_TYPE_WARNING, _("Character sets requested were `%s'->`%s'\n"), "UTF-8", output_charset); ret = GNUNET_malloc (len + 1); memcpy (ret, input, len); ret[len] = '\0'; return ret; } /** * Convert the len characters long character sequence * given in input that is in the given charset * to UTF-8. * * @param input the input string (not necessarily 0-terminated) * @param len the number of bytes in the @a input * @param charset character set to convert from * @return the converted string (0-terminated), * if conversion fails, a copy of the orignal * string is returned. */ char * GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset) { return GNUNET_STRINGS_conv (input, len, charset, "UTF-8"); } /** * Convert the len bytes-long UTF-8 string * given in input to the given charset. * * @param input the input string (not necessarily 0-terminated) * @param len the number of bytes in the @a input * @param charset character set to convert to * @return the converted string (0-terminated), * if conversion fails, a copy of the orignal * string is returned. */ char * GNUNET_STRINGS_from_utf8 (const char *input, size_t len, const char *charset) { return GNUNET_STRINGS_conv (input, len, "UTF-8", charset); } /** * Convert the utf-8 input string to lowercase. * Output needs to be allocated appropriately. * * @param input input string * @param output output buffer */ void GNUNET_STRINGS_utf8_tolower (const char *input, char *output) { uint8_t *tmp_in; size_t len; tmp_in = u8_tolower ((uint8_t*)input, strlen ((char *) input), NULL, UNINORM_NFD, NULL, &len); memcpy(output, tmp_in, len); output[len] = '\0'; free(tmp_in); } /** * Convert the utf-8 input string to uppercase. * Output needs to be allocated appropriately. * * @param input input string * @param output output buffer */ void GNUNET_STRINGS_utf8_toupper(const char *input, char *output) { uint8_t *tmp_in; size_t len; tmp_in = u8_toupper ((uint8_t*)input, strlen ((char *) input), NULL, UNINORM_NFD, NULL, &len); memcpy (output, tmp_in, len); output[len] = '\0'; free (tmp_in); } /** * Complete filename (a la shell) from abbrevition. * @param fil the name of the file, may contain ~/ or * be relative to the current directory * @returns the full file name, * NULL is returned on error */ char * GNUNET_STRINGS_filename_expand (const char *fil) { char *buffer; #ifndef MINGW size_t len; size_t n; char *fm; const char *fil_ptr; #else char *fn; long lRet; #endif if (fil == NULL) return NULL; #ifndef MINGW if (fil[0] == DIR_SEPARATOR) /* absolute path, just copy */ return GNUNET_strdup (fil); if (fil[0] == '~') { fm = getenv ("HOME"); if (fm == NULL) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to expand `$HOME': environment variable `HOME' not set")); return NULL; } fm = GNUNET_strdup (fm); /* do not copy '~' */ fil_ptr = fil + 1; /* skip over dir seperator to be consistent */ if (fil_ptr[0] == DIR_SEPARATOR) fil_ptr++; } else { /* relative path */ fil_ptr = fil; len = 512; fm = NULL; while (1) { buffer = GNUNET_malloc (len); if (getcwd (buffer, len) != NULL) { fm = buffer; break; } if ((errno == ERANGE) && (len < 1024 * 1024 * 4)) { len *= 2; GNUNET_free (buffer); continue; } GNUNET_free (buffer); break; } if (fm == NULL) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "getcwd"); buffer = getenv ("PWD"); /* alternative */ if (buffer != NULL) fm = GNUNET_strdup (buffer); } if (fm == NULL) fm = GNUNET_strdup ("./"); /* give up */ } n = strlen (fm) + 1 + strlen (fil_ptr) + 1; buffer = GNUNET_malloc (n); GNUNET_snprintf (buffer, n, "%s%s%s", fm, (fm[strlen (fm) - 1] == DIR_SEPARATOR) ? "" : DIR_SEPARATOR_STR, fil_ptr); GNUNET_free (fm); return buffer; #else fn = GNUNET_malloc (MAX_PATH + 1); if ((lRet = plibc_conv_to_win_path (fil, fn)) != ERROR_SUCCESS) { SetErrnoFromWinError (lRet); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "plibc_conv_to_win_path"); return NULL; } /* is the path relative? */ if ((strncmp (fn + 1, ":\\", 2) != 0) && (strncmp (fn, "\\\\", 2) != 0)) { char szCurDir[MAX_PATH + 1]; lRet = GetCurrentDirectory (MAX_PATH + 1, szCurDir); if (lRet + strlen (fn) + 1 > (MAX_PATH + 1)) { SetErrnoFromWinError (ERROR_BUFFER_OVERFLOW); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "GetCurrentDirectory"); return NULL; } buffer = GNUNET_malloc (MAX_PATH + 1); GNUNET_snprintf (buffer, MAX_PATH + 1, "%s\\%s", szCurDir, fn); GNUNET_free (fn); fn = buffer; } return fn; #endif } /** * Give relative time in human-readable fancy format. * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param delta time in milli seconds * @param do_round are we allowed to round a bit? * @return time as human-readable string */ const char * GNUNET_STRINGS_relative_time_to_string (struct GNUNET_TIME_Relative delta, int do_round) { static char buf[128]; const char *unit = _( /* time unit */ "µs"); uint64_t dval = delta.rel_value_us; if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == delta.rel_value_us) return _("forever"); if (0 == delta.rel_value_us) return _("0 ms"); if ( ( (GNUNET_YES == do_round) && (dval > 5 * 1000) ) || (0 == (dval % 1000) )) { dval = dval / 1000; unit = _( /* time unit */ "ms"); if ( ( (GNUNET_YES == do_round) && (dval > 5 * 1000) ) || (0 == (dval % 1000) )) { dval = dval / 1000; unit = _( /* time unit */ "s"); if ( ( (GNUNET_YES == do_round) && (dval > 5 * 60) ) || (0 == (dval % 60) ) ) { dval = dval / 60; unit = _( /* time unit */ "m"); if ( ( (GNUNET_YES == do_round) && (dval > 5 * 60) ) || (0 == (dval % 60) )) { dval = dval / 60; unit = _( /* time unit */ "h"); if ( ( (GNUNET_YES == do_round) && (dval > 5 * 24) ) || (0 == (dval % 24)) ) { dval = dval / 24; if (1 == dval) unit = _( /* time unit */ "day"); else unit = _( /* time unit */ "days"); } } } } } GNUNET_snprintf (buf, sizeof (buf), "%llu %s", dval, unit); return buf; } /** * "asctime", except for GNUnet time. Converts a GNUnet internal * absolute time (which is in UTC) to a string in local time. * Note that the returned value will be overwritten if this function * is called again. * * @param t the absolute time to convert * @return timestamp in human-readable form in local time */ const char * GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t) { static char buf[255]; time_t tt; struct tm *tp; if (t.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) return _("end of time"); tt = t.abs_value_us / 1000LL / 1000LL; tp = localtime (&tt); /* This is hacky, but i don't know a way to detect libc character encoding. * Just expect utf8 from glibc these days. * As for msvcrt, use the wide variant, which always returns utf16 * (otherwise we'd have to detect current codepage or use W32API character * set conversion routines to convert to UTF8). */ #ifndef WINDOWS strftime (buf, sizeof (buf), "%a %b %d %H:%M:%S %Y", tp); #else { static wchar_t wbuf[255]; uint8_t *conved; size_t ssize; wcsftime (wbuf, sizeof (wbuf) / sizeof (wchar_t), L"%a %b %d %H:%M:%S %Y", tp); ssize = sizeof (buf); conved = u16_to_u8 (wbuf, sizeof (wbuf) / sizeof (wchar_t), (uint8_t *) buf, &ssize); if (conved != (uint8_t *) buf) { strncpy (buf, (char *) conved, sizeof (buf)); buf[255 - 1] = '\0'; free (conved); } } #endif return buf; } /** * "man basename" * Returns a pointer to a part of filename (allocates nothing)! * * @param filename filename to extract basename from * @return short (base) name of the file (that is, everything following the * last directory separator in filename. If filename ends with a * directory separator, the result will be a zero-length string. * If filename has no directory separators, the result is filename * itself. */ const char * GNUNET_STRINGS_get_short_name (const char *filename) { const char *short_fn = filename; const char *ss; while (NULL != (ss = strstr (short_fn, DIR_SEPARATOR_STR)) && (ss[1] != '\0')) short_fn = 1 + ss; return short_fn; } /** * Get the numeric value corresponding to a character. * * @param a a character * @return corresponding numeric value */ static unsigned int getValue__ (unsigned char a) { if ((a >= '0') && (a <= '9')) return a - '0'; if ((a >= 'A') && (a <= 'V')) return (a - 'A' + 10); if ((a >= 'a') && (a <= 'v')) return (a - 'a' + 10); return -1; } /** * Convert binary data to ASCII encoding. The ASCII encoding is rather * GNUnet specific. It was chosen such that it only uses characters * in [0-9A-V], can be produced without complex arithmetics and uses a * small number of characters. * Does not append 0-terminator, but returns a pointer to the place where * it should be placed, if needed. * * @param data data to encode * @param size size of data (in bytes) * @param out buffer to fill * @param out_size size of the buffer. Must be large enough to hold * ((size*8) + (((size*8) % 5) > 0 ? 5 - ((size*8) % 5) : 0)) / 5 bytes * @return pointer to the next byte in 'out' or NULL on error. */ char * GNUNET_STRINGS_data_to_string (const void *data, size_t size, char *out, size_t out_size) { /** * 32 characters for encoding */ static char *encTable__ = "0123456789ABCDEFGHIJKLMNOPQRSTUV"; unsigned int wpos; unsigned int rpos; unsigned int bits; unsigned int vbit; const unsigned char *udata; GNUNET_assert (data != NULL); GNUNET_assert (out != NULL); udata = data; if (out_size < (((size*8) + ((size*8) % 5)) % 5)) { GNUNET_break (0); return NULL; } vbit = 0; wpos = 0; rpos = 0; bits = 0; while ((rpos < size) || (vbit > 0)) { if ((rpos < size) && (vbit < 5)) { bits = (bits << 8) | udata[rpos++]; /* eat 8 more bits */ vbit += 8; } if (vbit < 5) { bits <<= (5 - vbit); /* zero-padding */ GNUNET_assert (vbit == ((size * 8) % 5)); vbit = 5; } if (wpos >= out_size) { GNUNET_break (0); return NULL; } out[wpos++] = encTable__[(bits >> (vbit - 5)) & 31]; vbit -= 5; } GNUNET_assert (vbit == 0); if (wpos < out_size) out[wpos] = '\0'; return &out[wpos]; } /** * Convert ASCII encoding back to data * out_size must match exactly the size of the data before it was encoded. * * @param enc the encoding * @param enclen number of characters in @a enc (without 0-terminator, which can be missing) * @param out location where to store the decoded data * @param out_size size of the output buffer @a out * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding */ int GNUNET_STRINGS_string_to_data (const char *enc, size_t enclen, void *out, size_t out_size) { unsigned int rpos; unsigned int wpos; unsigned int bits; unsigned int vbit; int ret; int shift; unsigned char *uout; unsigned int encoded_len = out_size * 8; if (0 == enclen) { if (0 == out_size) return GNUNET_OK; return GNUNET_SYSERR; } uout = out; wpos = out_size; rpos = enclen; if ((encoded_len % 5) > 0) { vbit = encoded_len % 5; /* padding! */ shift = 5 - vbit; bits = (ret = getValue__ (enc[--rpos])) >> (5 - (encoded_len % 5)); } else { vbit = 5; shift = 0; bits = (ret = getValue__ (enc[--rpos])); } if ((encoded_len + shift) / 5 != enclen) return GNUNET_SYSERR; if (-1 == ret) return GNUNET_SYSERR; while (wpos > 0) { if (0 == rpos) { GNUNET_break (0); return GNUNET_SYSERR; } bits = ((ret = getValue__ (enc[--rpos])) << vbit) | bits; if (-1 == ret) return GNUNET_SYSERR; vbit += 5; if (vbit >= 8) { uout[--wpos] = (unsigned char) bits; bits >>= 8; vbit -= 8; } } if ( (0 != rpos) || (0 != vbit) ) return GNUNET_SYSERR; return GNUNET_OK; } /** * Parse a path that might be an URI. * * @param path path to parse. Must be NULL-terminated. * @param scheme_part a pointer to 'char *' where a pointer to a string that * represents the URI scheme will be stored. Can be NULL. The string is * allocated by the function, and should be freed by GNUNET_free() when * it is no longer needed. * @param path_part a pointer to 'const char *' where a pointer to the path * part of the URI will be stored. Can be NULL. Points to the same block * of memory as 'path', and thus must not be freed. Might point to '\0', * if path part is zero-length. * @return GNUNET_YES if it's an URI, GNUNET_NO otherwise. If 'path' is not * an URI, '* scheme_part' and '*path_part' will remain unchanged * (if they weren't NULL). */ int GNUNET_STRINGS_parse_uri (const char *path, char **scheme_part, const char **path_part) { size_t len; int i, end; int pp_state = 0; const char *post_scheme_part = NULL; len = strlen (path); for (end = 0, i = 0; !end && i < len; i++) { switch (pp_state) { case 0: if (path[i] == ':' && i > 0) { pp_state += 1; continue; } if (!((path[i] >= 'A' && path[i] <= 'Z') || (path[i] >= 'a' && path[i] <= 'z') || (path[i] >= '0' && path[i] <= '9') || path[i] == '+' || path[i] == '-' || (path[i] == '.'))) end = 1; break; case 1: case 2: if (path[i] == '/') { pp_state += 1; continue; } end = 1; break; case 3: post_scheme_part = &path[i]; end = 1; break; default: end = 1; } } if (post_scheme_part == NULL) return GNUNET_NO; if (scheme_part) { *scheme_part = GNUNET_malloc (post_scheme_part - path + 1); memcpy (*scheme_part, path, post_scheme_part - path); (*scheme_part)[post_scheme_part - path] = '\0'; } if (path_part) *path_part = post_scheme_part; return GNUNET_YES; } /** * Check whether @a filename is absolute or not, and if it's an URI * * @param filename filename to check * @param can_be_uri #GNUNET_YES to check for being URI, #GNUNET_NO - to * assume it's not URI * @param r_is_uri a pointer to an int that is set to #GNUNET_YES if @a filename * is URI and to #GNUNET_NO otherwise. Can be NULL. If @a can_be_uri is * not #GNUNET_YES, `* r_is_uri` is set to #GNUNET_NO. * @param r_uri_scheme a pointer to a char * that is set to a pointer to URI scheme. * The string is allocated by the function, and should be freed with * GNUNET_free(). Can be NULL. * @return #GNUNET_YES if @a filename is absolute, #GNUNET_NO otherwise. */ int GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri, int *r_is_uri, char **r_uri_scheme) { #if WINDOWS size_t len; #endif const char *post_scheme_path; int is_uri; char * uri; /* consider POSIX paths to be absolute too, even on W32, * as plibc expansion will fix them for us. */ if (filename[0] == '/') return GNUNET_YES; if (can_be_uri) { is_uri = GNUNET_STRINGS_parse_uri (filename, &uri, &post_scheme_path); if (r_is_uri) *r_is_uri = is_uri; if (is_uri) { if (r_uri_scheme) *r_uri_scheme = uri; else GNUNET_free_non_null (uri); #if WINDOWS len = strlen(post_scheme_path); /* Special check for file:///c:/blah * We want to parse 'c:/', not '/c:/' */ if (post_scheme_path[0] == '/' && len >= 3 && post_scheme_path[2] == ':') post_scheme_path = &post_scheme_path[1]; #endif return GNUNET_STRINGS_path_is_absolute (post_scheme_path, GNUNET_NO, NULL, NULL); } } else { if (r_is_uri) *r_is_uri = GNUNET_NO; } #if WINDOWS len = strlen (filename); if (len >= 3 && ((filename[0] >= 'A' && filename[0] <= 'Z') || (filename[0] >= 'a' && filename[0] <= 'z')) && filename[1] == ':' && (filename[2] == '/' || filename[2] == '\\')) return GNUNET_YES; #endif return GNUNET_NO; } #if MINGW #define _IFMT 0170000 /* type of file */ #define _IFLNK 0120000 /* symbolic link */ #define S_ISLNK(m) (((m)&_IFMT) == _IFLNK) #endif /** * Perform @a checks on @a filename. * * @param filename file to check * @param checks checks to perform * @return #GNUNET_YES if all checks pass, #GNUNET_NO if at least one of them * fails, #GNUNET_SYSERR when a check can't be performed */ int GNUNET_STRINGS_check_filename (const char *filename, enum GNUNET_STRINGS_FilenameCheck checks) { struct stat st; if ( (NULL == filename) || (filename[0] == '\0') ) return GNUNET_SYSERR; if (0 != (checks & GNUNET_STRINGS_CHECK_IS_ABSOLUTE)) if (!GNUNET_STRINGS_path_is_absolute (filename, GNUNET_NO, NULL, NULL)) return GNUNET_NO; if (0 != (checks & (GNUNET_STRINGS_CHECK_EXISTS | GNUNET_STRINGS_CHECK_IS_DIRECTORY | GNUNET_STRINGS_CHECK_IS_LINK))) { if (0 != STAT (filename, &st)) { if (0 != (checks & GNUNET_STRINGS_CHECK_EXISTS)) return GNUNET_NO; else return GNUNET_SYSERR; } } if (0 != (checks & GNUNET_STRINGS_CHECK_IS_DIRECTORY)) if (!S_ISDIR (st.st_mode)) return GNUNET_NO; if (0 != (checks & GNUNET_STRINGS_CHECK_IS_LINK)) if (!S_ISLNK (st.st_mode)) return GNUNET_NO; return GNUNET_YES; } /** * Tries to convert 'zt_addr' string to an IPv6 address. * The string is expected to have the format "[ABCD::01]:80". * * @param zt_addr 0-terminated string. May be mangled by the function. * @param addrlen length of @a zt_addr (not counting 0-terminator). * @param r_buf a buffer to fill. Initially gets filled with zeroes, * then its sin6_port, sin6_family and sin6_addr are set appropriately. * @return #GNUNET_OK if conversion succeded. * #GNUNET_SYSERR otherwise, in which * case the contents of @a r_buf are undefined. */ int GNUNET_STRINGS_to_address_ipv6 (const char *zt_addr, uint16_t addrlen, struct sockaddr_in6 *r_buf) { char zbuf[addrlen + 1]; int ret; char *port_colon; unsigned int port; if (addrlen < 6) return GNUNET_SYSERR; memcpy (zbuf, zt_addr, addrlen); if ('[' != zbuf[0]) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("IPv6 address did not start with `['\n")); return GNUNET_SYSERR; } zbuf[addrlen] = '\0'; port_colon = strrchr (zbuf, ':'); if (NULL == port_colon) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("IPv6 address did contain ':' to separate port number\n")); return GNUNET_SYSERR; } if (']' != *(port_colon - 1)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("IPv6 address did contain ']' before ':' to separate port number\n")); return GNUNET_SYSERR; } ret = SSCANF (port_colon, ":%u", &port); if ( (1 != ret) || (port > 65535) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("IPv6 address did contain a valid port number after the last ':'\n")); return GNUNET_SYSERR; } *(port_colon-1) = '\0'; memset (r_buf, 0, sizeof (struct sockaddr_in6)); ret = inet_pton (AF_INET6, &zbuf[1], &r_buf->sin6_addr); if (ret <= 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Invalid IPv6 address `%s': %s\n"), &zbuf[1], STRERROR (errno)); return GNUNET_SYSERR; } r_buf->sin6_port = htons (port); r_buf->sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN r_buf->sin6_len = (u_char) sizeof (struct sockaddr_in6); #endif return GNUNET_OK; } /** * Tries to convert 'zt_addr' string to an IPv4 address. * The string is expected to have the format "1.2.3.4:80". * * @param zt_addr 0-terminated string. May be mangled by the function. * @param addrlen length of @a zt_addr (not counting 0-terminator). * @param r_buf a buffer to fill. * @return #GNUNET_OK if conversion succeded. * #GNUNET_SYSERR otherwise, in which case * the contents of @a r_buf are undefined. */ int GNUNET_STRINGS_to_address_ipv4 (const char *zt_addr, uint16_t addrlen, struct sockaddr_in *r_buf) { unsigned int temps[4]; unsigned int port; unsigned int cnt; if (addrlen < 9) return GNUNET_SYSERR; cnt = SSCANF (zt_addr, "%u.%u.%u.%u:%u", &temps[0], &temps[1], &temps[2], &temps[3], &port); if (5 != cnt) return GNUNET_SYSERR; for (cnt = 0; cnt < 4; cnt++) if (temps[cnt] > 0xFF) return GNUNET_SYSERR; if (port > 65535) return GNUNET_SYSERR; r_buf->sin_family = AF_INET; r_buf->sin_port = htons (port); r_buf->sin_addr.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]); #if HAVE_SOCKADDR_IN_SIN_LEN r_buf->sin_len = (u_char) sizeof (struct sockaddr_in); #endif return GNUNET_OK; } /** * Tries to convert @a addr string to an IP (v4 or v6) address. * Will automatically decide whether to treat 'addr' as v4 or v6 address. * * @param addr a string, may not be 0-terminated. * @param addrlen number of bytes in @a addr (if addr is 0-terminated, * 0-terminator should not be counted towards addrlen). * @param r_buf a buffer to fill. * @return #GNUNET_OK if conversion succeded. GNUNET_SYSERR otherwise, in which * case the contents of r_buf are undefined. */ int GNUNET_STRINGS_to_address_ip (const char *addr, uint16_t addrlen, struct sockaddr_storage *r_buf) { if (addr[0] == '[') return GNUNET_STRINGS_to_address_ipv6 (addr, addrlen, (struct sockaddr_in6 *) r_buf); return GNUNET_STRINGS_to_address_ipv4 (addr, addrlen, (struct sockaddr_in *) r_buf); } /** * Makes a copy of argv that consists of a single memory chunk that can be * freed with a single call to GNUNET_free(); */ static char *const * _make_continuous_arg_copy (int argc, char *const *argv) { size_t argvsize = 0; int i; char **new_argv; char *p; for (i = 0; i < argc; i++) argvsize += strlen (argv[i]) + 1 + sizeof (char *); new_argv = GNUNET_malloc (argvsize + sizeof (char *)); p = (char *) &new_argv[argc + 1]; for (i = 0; i < argc; i++) { new_argv[i] = p; strcpy (p, argv[i]); p += strlen (argv[i]) + 1; } new_argv[argc] = NULL; return (char *const *) new_argv; } /** * Returns utf-8 encoded arguments. * Does nothing (returns a copy of argc and argv) on any platform * other than W32. * Returned argv has u8argv[u8argc] == NULL. * Returned argv is a single memory block, and can be freed with a single * GNUNET_free() call. * * @param argc argc (as given by main()) * @param argv argv (as given by main()) * @param u8argc a location to store new argc in (though it's th same as argc) * @param u8argv a location to store new argv in * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv) { #if WINDOWS wchar_t *wcmd; wchar_t **wargv; int wargc; int i; char **split_u8argv; wcmd = GetCommandLineW (); if (NULL == wcmd) return GNUNET_SYSERR; wargv = CommandLineToArgvW (wcmd, &wargc); if (NULL == wargv) return GNUNET_SYSERR; split_u8argv = GNUNET_malloc (argc * sizeof (char *)); for (i = 0; i < wargc; i++) { size_t strl; /* Hopefully it will allocate us NUL-terminated strings... */ split_u8argv[i] = (char *) u16_to_u8 (wargv[i], wcslen (wargv[i]) + 1, NULL, &strl); if (NULL == split_u8argv[i]) { int j; for (j = 0; j < i; j++) free (split_u8argv[j]); GNUNET_free (split_u8argv); LocalFree (wargv); return GNUNET_SYSERR; } } *u8argv = _make_continuous_arg_copy (wargc, split_u8argv); *u8argc = wargc; for (i = 0; i < wargc; i++) free (split_u8argv[i]); free (split_u8argv); return GNUNET_OK; #else char *const *new_argv = (char *const *) _make_continuous_arg_copy (argc, argv); *u8argv = new_argv; *u8argc = argc; return GNUNET_OK; #endif } /** * Parse the given port policy. The format is * "[!]SPORT[-DPORT]". * * @param port_policy string to parse * @param pp policy to fill in * @return #GNUNET_OK on success, #GNUNET_SYSERR if the * @a port_policy is malformed */ static int parse_port_policy (const char *port_policy, struct GNUNET_STRINGS_PortPolicy *pp) { const char *pos; int s; int e; char eol[2]; pos = port_policy; if ('!' == *pos) { pp->negate_portrange = GNUNET_YES; pos++; } if (2 == sscanf (pos, "%u-%u%1s", &s, &e, eol)) { if ( (0 == s) || (s > 0xFFFF) || (e < s) || (e > 0xFFFF) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Port not in range\n")); return GNUNET_SYSERR; } pp->start_port = (uint16_t) s; pp->end_port = (uint16_t) e; return GNUNET_OK; } if (1 == sscanf (pos, "%u%1s", &s, eol)) { if ( (0 == s) || (s > 0xFFFF) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Port not in range\n")); return GNUNET_SYSERR; } pp->start_port = (uint16_t) s; pp->end_port = (uint16_t) s; return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Malformed port policy `%s'\n"), port_policy); return GNUNET_SYSERR; } /** * Parse an IPv4 network policy. The argument specifies a list of * subnets. The format is * (network[/netmask][:SPORT[-DPORT]];)* (no whitespace, must * be terminated with a semicolon). The network must be given in * dotted-decimal notation. The netmask can be given in CIDR notation * (/16) or in dotted-decimal (/255.255.0.0). * * @param routeListX a string specifying the IPv4 subnets * @return the converted list, terminated with all zeros; * NULL if the synatx is flawed */ struct GNUNET_STRINGS_IPv4NetworkPolicy * GNUNET_STRINGS_parse_ipv4_policy (const char *routeListX) { unsigned int count; unsigned int i; unsigned int j; unsigned int len; int cnt; unsigned int pos; unsigned int temps[8]; int slash; struct GNUNET_STRINGS_IPv4NetworkPolicy *result; int colon; int end; char *routeList; if (NULL == routeListX) return NULL; len = strlen (routeListX); if (0 == len) return NULL; routeList = GNUNET_strdup (routeListX); count = 0; for (i = 0; i < len; i++) if (routeList[i] == ';') count++; result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv4NetworkPolicy) * (count + 1)); i = 0; pos = 0; while (i < count) { for (colon = pos; ':' != routeList[colon]; colon++) if ( (';' == routeList[colon]) || ('\0' == routeList[colon]) ) break; for (end = colon; ';' != routeList[end]; end++) if ('\0' == routeList[end]) break; if ('\0' == routeList[end]) break; routeList[end] = '\0'; if (':' == routeList[colon]) { routeList[colon] = '\0'; if (GNUNET_OK != parse_port_policy (&routeList[colon + 1], &result[i].pp)) break; } cnt = SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u", &temps[0], &temps[1], &temps[2], &temps[3], &temps[4], &temps[5], &temps[6], &temps[7]); if (8 == cnt) { for (j = 0; j < 8; j++) if (temps[j] > 0xFF) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Invalid format for IP: `%s'\n"), &routeList[pos]); GNUNET_free (result); GNUNET_free (routeList); return NULL; } result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]); result[i].netmask.s_addr = htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) + temps[7]); pos = end + 1; i++; continue; } /* try second notation */ cnt = SSCANF (&routeList[pos], "%u.%u.%u.%u/%u", &temps[0], &temps[1], &temps[2], &temps[3], &slash); if (5 == cnt) { for (j = 0; j < 4; j++) if (temps[j] > 0xFF) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Invalid format for IP: `%s'\n"), &routeList[pos]); GNUNET_free (result); GNUNET_free (routeList); return NULL; } result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]); if ((slash <= 32) && (slash >= 0)) { result[i].netmask.s_addr = 0; while (slash > 0) { result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000; slash--; } result[i].netmask.s_addr = htonl (result[i].netmask.s_addr); pos = end + 1; i++; continue; } else { LOG (GNUNET_ERROR_TYPE_WARNING, _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."), slash); GNUNET_free (result); GNUNET_free (routeList); return NULL; /* error */ } } /* try third notation */ slash = 32; cnt = SSCANF (&routeList[pos], "%u.%u.%u.%u", &temps[0], &temps[1], &temps[2], &temps[3]); if (4 == cnt) { for (j = 0; j < 4; j++) if (temps[j] > 0xFF) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Invalid format for IP: `%s'\n"), &routeList[pos]); GNUNET_free (result); GNUNET_free (routeList); return NULL; } result[i].network.s_addr = htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + temps[3]); result[i].netmask.s_addr = 0; while (slash > 0) { result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000; slash--; } result[i].netmask.s_addr = htonl (result[i].netmask.s_addr); pos = end + 1; i++; continue; } LOG (GNUNET_ERROR_TYPE_WARNING, _("Invalid format for IP: `%s'\n"), &routeList[pos]); GNUNET_free (result); GNUNET_free (routeList); return NULL; /* error */ } if (pos < strlen (routeList)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Invalid format: `%s'\n"), &routeListX[pos]); GNUNET_free (result); GNUNET_free (routeList); return NULL; /* oops */ } GNUNET_free (routeList); return result; /* ok */ } /** * Parse an IPv6 network policy. The argument specifies a list of * subnets. The format is (network[/netmask[:SPORT[-DPORT]]];)* * (no whitespace, must be terminated with a semicolon). The network * must be given in colon-hex notation. The netmask must be given in * CIDR notation (/16) or can be omitted to specify a single host. * Note that the netmask is mandatory if ports are specified. * * @param routeListX a string specifying the policy * @return the converted list, 0-terminated, NULL if the synatx is flawed */ struct GNUNET_STRINGS_IPv6NetworkPolicy * GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX) { unsigned int count; unsigned int i; unsigned int len; unsigned int pos; int start; int slash; int ret; char *routeList; struct GNUNET_STRINGS_IPv6NetworkPolicy *result; unsigned int bits; unsigned int off; int save; int colon; if (NULL == routeListX) return NULL; len = strlen (routeListX); if (0 == len) return NULL; routeList = GNUNET_strdup (routeListX); count = 0; for (i = 0; i < len; i++) if (';' == routeList[i]) count++; if (';' != routeList[len - 1]) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Invalid network notation (does not end with ';': `%s')\n"), routeList); GNUNET_free (routeList); return NULL; } result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv6NetworkPolicy) * (count + 1)); i = 0; pos = 0; while (i < count) { start = pos; while (';' != routeList[pos]) pos++; slash = pos; while ((slash >= start) && (routeList[slash] != '/')) slash--; if (slash < start) { memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr)); slash = pos; } else { routeList[pos] = '\0'; for (colon = pos; ':' != routeList[colon]; colon--) if ('/' == routeList[colon]) break; if (':' == routeList[colon]) { routeList[colon] = '\0'; if (GNUNET_OK != parse_port_policy (&routeList[colon + 1], &result[i].pp)) { GNUNET_free (result); GNUNET_free (routeList); return NULL; } } ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask); if (ret <= 0) { save = errno; if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits > 128)) { if (0 == ret) LOG (GNUNET_ERROR_TYPE_WARNING, _("Wrong format `%s' for netmask\n"), &routeList[slash + 1]); else { errno = save; LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_pton"); } GNUNET_free (result); GNUNET_free (routeList); return NULL; } off = 0; while (bits > 8) { result[i].netmask.s6_addr[off++] = 0xFF; bits -= 8; } while (bits > 0) { result[i].netmask.s6_addr[off] = (result[i].netmask.s6_addr[off] >> 1) + 0x80; bits--; } } } routeList[slash] = '\0'; ret = inet_pton (AF_INET6, &routeList[start], &result[i].network); if (ret <= 0) { if (0 == ret) LOG (GNUNET_ERROR_TYPE_WARNING, _("Wrong format `%s' for network\n"), &routeList[slash + 1]); else LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton"); GNUNET_free (result); GNUNET_free (routeList); return NULL; } pos++; i++; } GNUNET_free (routeList); return result; } /** ******************** Base64 encoding ***********/ #define FILLCHAR '=' static char *cvt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; /** * Encode into Base64. * * @param data the data to encode * @param len the length of the input * @param output where to write the output (*output should be NULL, * is allocated) * @return the size of the output */ size_t GNUNET_STRINGS_base64_encode (const char *data, size_t len, char **output) { size_t i; char c; size_t ret; char *opt; ret = 0; opt = GNUNET_malloc (2 + (len * 4 / 3) + 8); *output = opt; for (i = 0; i < len; ++i) { c = (data[i] >> 2) & 0x3f; opt[ret++] = cvt[(int) c]; c = (data[i] << 4) & 0x3f; if (++i < len) c |= (data[i] >> 4) & 0x0f; opt[ret++] = cvt[(int) c]; if (i < len) { c = (data[i] << 2) & 0x3f; if (++i < len) c |= (data[i] >> 6) & 0x03; opt[ret++] = cvt[(int) c]; } else { ++i; opt[ret++] = FILLCHAR; } if (i < len) { c = data[i] & 0x3f; opt[ret++] = cvt[(int) c]; } else { opt[ret++] = FILLCHAR; } } opt[ret++] = FILLCHAR; return ret; } #define cvtfind(a)( (((a) >= 'A')&&((a) <= 'Z'))? (a)-'A'\ :(((a)>='a')&&((a)<='z')) ? (a)-'a'+26\ :(((a)>='0')&&((a)<='9')) ? (a)-'0'+52\ :((a) == '+') ? 62\ :((a) == '/') ? 63 : -1) /** * Decode from Base64. * * @param data the data to encode * @param len the length of the input * @param output where to write the output (*output should be NULL, * is allocated) * @return the size of the output */ size_t GNUNET_STRINGS_base64_decode (const char *data, size_t len, char **output) { size_t i; char c; char c1; size_t ret = 0; #define CHECK_CRLF while (data[i] == '\r' || data[i] == '\n') {\ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "ignoring CR/LF\n"); \ i++; \ if (i >= len) goto END; \ } *output = GNUNET_malloc ((len * 3 / 4) + 8); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "base64_decode decoding len=%d\n", (int) len); for (i = 0; i < len; ++i) { CHECK_CRLF; if (FILLCHAR == data[i]) break; c = (char) cvtfind (data[i]); ++i; CHECK_CRLF; c1 = (char) cvtfind (data[i]); c = (c << 2) | ((c1 >> 4) & 0x3); (*output)[ret++] = c; if (++i < len) { CHECK_CRLF; c = data[i]; if (FILLCHAR == c) break; c = (char) cvtfind (c); c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); (*output)[ret++] = c1; } if (++i < len) { CHECK_CRLF; c1 = data[i]; if (FILLCHAR == c1) break; c1 = (char) cvtfind (c1); c = ((c << 6) & 0xc0) | c1; (*output)[ret++] = c; } } END: return ret; } /* end of strings.c */ gnunet-0.10.1/src/util/crypto_hash.c0000644000175000017500000003735112263515316014262 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/crypto_hash.c * @brief SHA-512 GNUNET_CRYPTO_hash related functions * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * Hash block of given size. * * @param block the data to #GNUNET_CRYPTO_hash, length is given as a second argument * @param size the length of the data to #GNUNET_CRYPTO_hash in @a block * @param ret pointer to where to write the hashcode */ void GNUNET_CRYPTO_hash (const void *block, size_t size, struct GNUNET_HashCode *ret) { gcry_md_hash_buffer (GCRY_MD_SHA512, ret, block, size); } /** * Context used when hashing a file. */ struct GNUNET_CRYPTO_FileHashContext { /** * Function to call upon completion. */ GNUNET_CRYPTO_HashCompletedCallback callback; /** * Closure for callback. */ void *callback_cls; /** * IO buffer. */ unsigned char *buffer; /** * Name of the file we are hashing. */ char *filename; /** * File descriptor. */ struct GNUNET_DISK_FileHandle *fh; /** * Cummulated hash. */ gcry_md_hd_t md; /** * Size of the file. */ uint64_t fsize; /** * Current offset. */ uint64_t offset; /** * Current task for hashing. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Priority we use. */ enum GNUNET_SCHEDULER_Priority priority; /** * Blocksize. */ size_t bsize; }; /** * Report result of hash computation to callback * and free associated resources. */ static void file_hash_finish (struct GNUNET_CRYPTO_FileHashContext *fhc, const struct GNUNET_HashCode * res) { fhc->callback (fhc->callback_cls, res); GNUNET_free (fhc->filename); if (!GNUNET_DISK_handle_invalid (fhc->fh)) GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh)); gcry_md_close (fhc->md); GNUNET_free (fhc); /* also frees fhc->buffer */ } /** * File hashing task. * * @param cls closure * @param tc context */ static void file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CRYPTO_FileHashContext *fhc = cls; struct GNUNET_HashCode *res; size_t delta; fhc->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (fhc->offset <= fhc->fsize); delta = fhc->bsize; if (fhc->fsize - fhc->offset < delta) delta = fhc->fsize - fhc->offset; if (delta != GNUNET_DISK_file_read (fhc->fh, fhc->buffer, delta)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "read", fhc->filename); file_hash_finish (fhc, NULL); return; } gcry_md_write (fhc->md, fhc->buffer, delta); fhc->offset += delta; if (fhc->offset == fhc->fsize) { res = (struct GNUNET_HashCode *) gcry_md_read (fhc->md, GCRY_MD_SHA512); file_hash_finish (fhc, res); return; } fhc->task = GNUNET_SCHEDULER_add_with_priority (fhc->priority, &file_hash_task, fhc); } /** * Compute the hash of an entire file. * * @param priority scheduling priority to use * @param filename name of file to hash * @param blocksize number of bytes to process in one task * @param callback function to call upon completion * @param callback_cls closure for callback * @return NULL on (immediate) errror */ struct GNUNET_CRYPTO_FileHashContext * GNUNET_CRYPTO_hash_file (enum GNUNET_SCHEDULER_Priority priority, const char *filename, size_t blocksize, GNUNET_CRYPTO_HashCompletedCallback callback, void *callback_cls) { struct GNUNET_CRYPTO_FileHashContext *fhc; GNUNET_assert (blocksize > 0); fhc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_FileHashContext) + blocksize); fhc->callback = callback; fhc->callback_cls = callback_cls; fhc->buffer = (unsigned char *) &fhc[1]; fhc->filename = GNUNET_strdup (filename); if (GPG_ERR_NO_ERROR != gcry_md_open (&fhc->md, GCRY_MD_SHA512, 0)) { GNUNET_break (0); GNUNET_free (fhc); return NULL; } fhc->bsize = blocksize; if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fhc->fsize, GNUNET_NO, GNUNET_YES)) { GNUNET_free (fhc->filename); GNUNET_free (fhc); return NULL; } fhc->fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (!fhc->fh) { GNUNET_free (fhc->filename); GNUNET_free (fhc); return NULL; } fhc->priority = priority; fhc->task = GNUNET_SCHEDULER_add_with_priority (priority, &file_hash_task, fhc); return fhc; } /** * Cancel a file hashing operation. * * @param fhc operation to cancel (callback must not yet have been invoked) */ void GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc) { GNUNET_SCHEDULER_cancel (fhc->task); GNUNET_free (fhc->filename); GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fhc->fh)); GNUNET_free (fhc); } /* ***************** binary-ASCII encoding *************** */ /** * Convert GNUNET_CRYPTO_hash to ASCII encoding. The ASCII encoding is rather * GNUnet specific. It was chosen such that it only uses characters * in [0-9A-V], can be produced without complex arithmetics and uses a * small number of characters. The GNUnet encoding uses 103 * characters plus a null terminator. * * @param block the hash code * @param result where to store the encoding (struct GNUNET_CRYPTO_HashAsciiEncoded can be * safely cast to char*, a '\\0' termination is set). */ void GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode *block, struct GNUNET_CRYPTO_HashAsciiEncoded *result) { char *np; np = GNUNET_STRINGS_data_to_string ((const unsigned char *) block, sizeof (struct GNUNET_HashCode), (char*) result, sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1); GNUNET_assert (NULL != np); *np = '\0'; } /** * Convert ASCII encoding back to hash code. * * @param enc the encoding * @param enclen number of characters in @a enc (without 0-terminator, which can be missing) * @param result where to store the hash code * @return #GNUNET_OK on success, #GNUNET_SYSERR if result has the wrong encoding */ int GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, struct GNUNET_HashCode *result) { char upper_enc[enclen]; char *up_ptr = upper_enc; GNUNET_STRINGS_utf8_toupper (enc, up_ptr); return GNUNET_STRINGS_string_to_data (upper_enc, enclen, (unsigned char*) result, sizeof (struct GNUNET_HashCode)); } /** * @ingroup hash * * Compute the distance between 2 hashcodes. The computation must be * fast, not involve bits[0] or bits[4] (they're used elsewhere), and be * somewhat consistent. And of course, the result should be a positive * number. * * @param a some hash code * @param b some hash code * @return a positive number which is a measure for * hashcode proximity. */ unsigned int GNUNET_CRYPTO_hash_distance_u32 (const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b) { unsigned int x1 = (a->bits[1] - b->bits[1]) >> 16; unsigned int x2 = (b->bits[1] - a->bits[1]) >> 16; return (x1 * x2); } /** * Create a random hash code. * * @param mode desired quality level * @param result hash code that is randomized */ void GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode, struct GNUNET_HashCode *result) { int i; for (i = (sizeof (struct GNUNET_HashCode) / sizeof (uint32_t)) - 1; i >= 0; i--) result->bits[i] = GNUNET_CRYPTO_random_u32 (mode, UINT32_MAX); } /** * compute result(delta) = b - a * * @param a some hash code * @param b some hash code * @param result set to b - a */ void GNUNET_CRYPTO_hash_difference (const struct GNUNET_HashCode *a, const struct GNUNET_HashCode *b, struct GNUNET_HashCode *result) { int i; for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) result->bits[i] = b->bits[i] - a->bits[i]; } /** * compute result(b) = a + delta * * @param a some hash code * @param delta some hash code * @param result set to a + delta */ void GNUNET_CRYPTO_hash_sum (const struct GNUNET_HashCode * a, const struct GNUNET_HashCode * delta, struct GNUNET_HashCode * result) { int i; for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) result->bits[i] = delta->bits[i] + a->bits[i]; } /** * compute result = a ^ b * * @param a some hash code * @param b some hash code * @param result set to a ^ b */ void GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode * a, const struct GNUNET_HashCode * b, struct GNUNET_HashCode * result) { int i; for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) result->bits[i] = a->bits[i] ^ b->bits[i]; } /** * Convert a hashcode into a key. * * @param hc hash code that serves to generate the key * @param skey set to a valid session key * @param iv set to a valid initialization vector */ void GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode *hc, struct GNUNET_CRYPTO_SymmetricSessionKey *skey, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv) { GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), "Hash key derivation", strlen ("Hash key derivation"), hc, sizeof (struct GNUNET_HashCode), NULL, 0)); GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), "Initialization vector derivation", strlen ("Initialization vector derivation"), hc, sizeof (struct GNUNET_HashCode), NULL, 0)); } /** * Obtain a bit from a hashcode. * @param code the GNUNET_CRYPTO_hash to index bit-wise * @param bit index into the hashcode, [0...511] * @return Bit \a bit from hashcode \a code, -1 for invalid index */ int GNUNET_CRYPTO_hash_get_bit (const struct GNUNET_HashCode * code, unsigned int bit) { GNUNET_assert (bit < 8 * sizeof (struct GNUNET_HashCode)); return (((unsigned char *) code)[bit >> 3] & (1 << (bit & 7))) > 0; } /** * Determine how many low order bits match in two * `struct GNUNET_HashCode`s. i.e. - 010011 and 011111 share * the first two lowest order bits, and therefore the * return value is two (NOT XOR distance, nor how many * bits match absolutely!). * * @param first the first hashcode * @param second the hashcode to compare first to * * @return the number of bits that match */ unsigned int GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode * first, const struct GNUNET_HashCode * second) { unsigned int i; for (i = 0; i < sizeof (struct GNUNET_HashCode) * 8; i++) if (GNUNET_CRYPTO_hash_get_bit (first, i) != GNUNET_CRYPTO_hash_get_bit (second, i)) return i; return sizeof (struct GNUNET_HashCode) * 8; } /** * Compare function for HashCodes, producing a total ordering * of all hashcodes. * * @param h1 some hash code * @param h2 some hash code * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2. */ int GNUNET_CRYPTO_hash_cmp (const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2) { unsigned int *i1; unsigned int *i2; int i; i1 = (unsigned int *) h1; i2 = (unsigned int *) h2; for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) { if (i1[i] > i2[i]) return 1; if (i1[i] < i2[i]) return -1; } return 0; } /** * Find out which of the two `struct GNUNET_HashCode`s is closer to target * in the XOR metric (Kademlia). * * @param h1 some hash code * @param h2 some hash code * @param target some hash code * @return -1 if h1 is closer, 1 if h2 is closer and 0 if h1==h2. */ int GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2, const struct GNUNET_HashCode *target) { int i; unsigned int d1; unsigned int d2; for (i = sizeof (struct GNUNET_HashCode) / sizeof (unsigned int) - 1; i >= 0; i--) { d1 = ((unsigned int *) h1)[i] ^ ((unsigned int *) target)[i]; d2 = ((unsigned int *) h2)[i] ^ ((unsigned int *) target)[i]; if (d1 > d2) return 1; else if (d1 < d2) return -1; } return 0; } /** * @brief Derive an authentication key * @param key authentication key * @param rkey root key * @param salt salt * @param salt_len size of the @a salt * @param ... pair of void * & size_t for context chunks, terminated by NULL */ void GNUNET_CRYPTO_hmac_derive_key (struct GNUNET_CRYPTO_AuthKey *key, const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, const void *salt, size_t salt_len, ...) { va_list argp; va_start (argp, salt_len); GNUNET_CRYPTO_hmac_derive_key_v (key, rkey, salt, salt_len, argp); va_end (argp); } /** * @brief Derive an authentication key * @param key authentication key * @param rkey root key * @param salt salt * @param salt_len size of the @a salt * @param argp pair of void * & size_t for context chunks, terminated by NULL */ void GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, const struct GNUNET_CRYPTO_SymmetricSessionKey *rkey, const void *salt, size_t salt_len, va_list argp) { GNUNET_CRYPTO_kdf_v (key->key, sizeof (key->key), salt, salt_len, rkey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), argp); } /** * Calculate HMAC of a message (RFC 2104) * * @param key secret key * @param plaintext input plaintext * @param plaintext_len length of @a plaintext * @param hmac where to store the hmac */ void GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac) { static int once; static gcry_md_hd_t md; const unsigned char *mc; if (! once) { once = 1; GNUNET_assert (GPG_ERR_NO_ERROR == gcry_md_open (&md, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC)); } else { gcry_md_reset (md); } gcry_md_setkey (md, key->key, sizeof (key->key)); gcry_md_write (md, plaintext, plaintext_len); mc = gcry_md_read (md, GCRY_MD_SHA512); GNUNET_assert (NULL != mc); memcpy (hmac->bits, mc, sizeof (hmac->bits)); } /* end of crypto_hash.c */ gnunet-0.10.1/src/util/test_container_heap.c0000644000175000017500000002514112225777501015753 00000000000000/* This file is part of GNUnet. (C) 2008 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Nathan Evans * @file util/test_container_heap.c * @brief Test of heap operations */ #include "platform.h" #include "gnunet_util_lib.h" static int iterator_callback (void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost) { return GNUNET_OK; } static int nstrcmp (const char *a, const char *b) { GNUNET_assert (a != NULL); GNUNET_assert (b != NULL); return strcmp (a, b); } static int check () { struct GNUNET_CONTAINER_Heap *myHeap; struct GNUNET_CONTAINER_HeapNode *n1; struct GNUNET_CONTAINER_HeapNode *n2; struct GNUNET_CONTAINER_HeapNode *n3; struct GNUNET_CONTAINER_HeapNode *n4; struct GNUNET_CONTAINER_HeapNode *n5; struct GNUNET_CONTAINER_HeapNode *n6; struct GNUNET_CONTAINER_HeapNode *n7; struct GNUNET_CONTAINER_HeapNode *n8; const char *r; myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); // GNUNET_CONTAINER_heap_remove_root heap empty, taking if-branch n1 = GNUNET_CONTAINER_heap_remove_root (myHeap); GNUNET_assert (NULL == n1); // GNUNET_CONTAINER_heap_peek heap empty, taking if-branch n1 = GNUNET_CONTAINER_heap_peek (myHeap); GNUNET_assert (NULL == n1); // GNUNET_CONTAINER_heap_walk_get_next: heap empty, taking if-branch n1 = GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (NULL == n1); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "11", 11); GNUNET_assert (NULL != n1); // GNUNET_CONTAINER_heap_peek not empty, taking if-branch n2 = NULL; n2 = GNUNET_CONTAINER_heap_peek (myHeap); GNUNET_assert (NULL != n2); // GNUNET_CONTAINER_heap_walk_get_next: 1 element n1 = NULL; n1 = GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (NULL != n1); GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); GNUNET_assert (1 == GNUNET_CONTAINER_heap_get_size (myHeap)); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "78", 78); GNUNET_assert (2 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_assert (0 == strcmp ("78", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (1 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "15", 5); GNUNET_CONTAINER_heap_update_cost (myHeap, n3, 15); GNUNET_assert (2 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); n4 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50); GNUNET_CONTAINER_heap_update_cost (myHeap, n4, 50); GNUNET_assert (3 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_iterate (myHeap, &iterator_callback, NULL); n5 = GNUNET_CONTAINER_heap_insert (myHeap, "100", 100); n6 = GNUNET_CONTAINER_heap_insert (myHeap, "30/200", 30); GNUNET_assert (5 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_remove_node (n5); r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n1 */ GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("11", r)); GNUNET_CONTAINER_heap_update_cost (myHeap, n6, 200); GNUNET_CONTAINER_heap_remove_node (n3); r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n4 */ GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("50", r)); r = GNUNET_CONTAINER_heap_remove_root (myHeap); /* n6 */ GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("30/200", r)); GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (myHeap)); GNUNET_CONTAINER_heap_destroy (myHeap); // My additions to a complete testcase // Testing a GNUNET_CONTAINER_HEAP_ORDER_MIN // Testing remove_node myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); GNUNET_CONTAINER_heap_update_cost (myHeap, n1, 15); r = GNUNET_CONTAINER_heap_remove_node (n1); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("10", r)); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); GNUNET_CONTAINER_heap_walk_get_next (myHeap); r = GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("20", r)); r = GNUNET_CONTAINER_heap_remove_node (n1); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("10", r)); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 10); GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_CONTAINER_heap_remove_node (n1); r = GNUNET_CONTAINER_heap_remove_root (myHeap); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("30", r)); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 10); GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_CONTAINER_heap_remove_node (n1); r = GNUNET_CONTAINER_heap_remove_node (n3); GNUNET_assert (NULL != r); GNUNET_assert (0 == strcmp ("30", r)); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 20); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 30); GNUNET_assert (0 == nstrcmp ("20", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_root (myHeap))); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_root (myHeap))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 20); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 30); n4 = GNUNET_CONTAINER_heap_insert (myHeap, "40", 40); n5 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50); n6 = GNUNET_CONTAINER_heap_insert (myHeap, "60", 60); // Inserting nodes deeper in the tree with lower costs n7 = GNUNET_CONTAINER_heap_insert (myHeap, "70", 10); n8 = GNUNET_CONTAINER_heap_insert (myHeap, "80", 10); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_node (n3))); // Cleaning up... GNUNET_assert (0 == nstrcmp ("60", GNUNET_CONTAINER_heap_remove_node (n6))); GNUNET_assert (0 == nstrcmp ("50", GNUNET_CONTAINER_heap_remove_node (n5))); // Testing heap_walk_get_next GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap);; GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); GNUNET_assert (0 == nstrcmp ("20", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (0 == nstrcmp ("40", GNUNET_CONTAINER_heap_remove_node (n4))); GNUNET_assert (0 == nstrcmp ("70", GNUNET_CONTAINER_heap_remove_node (n7))); GNUNET_assert (0 == nstrcmp ("80", GNUNET_CONTAINER_heap_remove_node (n8))); // End Testing remove_node // Testing a GNUNET_CONTAINER_HEAP_ORDER_MAX GNUNET_CONTAINER_heap_destroy (myHeap); myHeap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); GNUNET_CONTAINER_heap_update_cost (myHeap, n1, 15); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (0 == nstrcmp ("20", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 10); GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_CONTAINER_heap_remove_node (n1); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_root (myHeap))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 10); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 10); GNUNET_CONTAINER_heap_remove_node (n2); GNUNET_CONTAINER_heap_remove_node (n1); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_node (n3))); n1 = GNUNET_CONTAINER_heap_insert (myHeap, "10", 10); n2 = GNUNET_CONTAINER_heap_insert (myHeap, "20", 20); n3 = GNUNET_CONTAINER_heap_insert (myHeap, "30", 30); n4 = GNUNET_CONTAINER_heap_insert (myHeap, "40", 40); n5 = GNUNET_CONTAINER_heap_insert (myHeap, "50", 50); n6 = GNUNET_CONTAINER_heap_insert (myHeap, "60", 60); // Inserting nodes deeper in the tree with lower costs n7 = GNUNET_CONTAINER_heap_insert (myHeap, "70", 10); n8 = GNUNET_CONTAINER_heap_insert (myHeap, "80", 10); GNUNET_assert (0 == nstrcmp ("30", GNUNET_CONTAINER_heap_remove_node (n3))); // Cleaning up... GNUNET_assert (0 == nstrcmp ("60", GNUNET_CONTAINER_heap_remove_node (n6))); GNUNET_assert (0 == nstrcmp ("50", GNUNET_CONTAINER_heap_remove_node (n5))); // Testing heap_walk_get_next GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap);; GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_CONTAINER_heap_walk_get_next (myHeap); GNUNET_assert (0 == nstrcmp ("10", GNUNET_CONTAINER_heap_remove_node (n1))); GNUNET_assert (0 == nstrcmp ("20", GNUNET_CONTAINER_heap_remove_node (n2))); GNUNET_assert (0 == nstrcmp ("40", GNUNET_CONTAINER_heap_remove_node (n4))); GNUNET_assert (0 == nstrcmp ("70", GNUNET_CONTAINER_heap_remove_node (n7))); GNUNET_assert (0 == nstrcmp ("80", GNUNET_CONTAINER_heap_remove_node (n8))); // End Testing remove_node GNUNET_CONTAINER_heap_destroy (myHeap); return 0; } int main (int argc, char **argv) { GNUNET_log_setup ("test-container-heap", "WARNING", NULL); return check (); } /* end of test_container_heap.c */ gnunet-0.10.1/src/util/test_connection_timeout.c0000644000175000017500000000737612225777501016713 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_connection_timeout.c * @brief tests for connection.c */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 12435 static struct GNUNET_CONNECTION_Handle *csock; static struct GNUNET_CONNECTION_Handle *lsock; static struct GNUNET_NETWORK_Handle *ls; static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Create and initialize a listen socket for the server. * * @return NULL on error, otherwise the listen socket */ static struct GNUNET_NETWORK_Handle * open_listen_socket () { const static int on = 1; struct sockaddr_in sa; struct GNUNET_NETWORK_Handle *desc; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); desc = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); GNUNET_assert (desc != NULL); if (GNUNET_NETWORK_socket_setsockopt (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); GNUNET_assert (GNUNET_OK == GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa, sizeof (sa))); GNUNET_NETWORK_socket_listen (desc, 5); return desc; } static size_t send_kilo (void *cls, size_t size, void *buf) { int *ok = cls; if (size == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got the desired timeout!\n"); GNUNET_assert (buf == NULL); *ok = 0; GNUNET_CONNECTION_destroy (lsock); GNUNET_CONNECTION_destroy (csock); return 0; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending kilo to fill buffer.\n"); GNUNET_assert (size >= 1024); memset (buf, 42, 1024); GNUNET_assert (NULL != GNUNET_CONNECTION_notify_transmit_ready (csock, 1024, GNUNET_TIME_UNIT_SECONDS, &send_kilo, cls)); return 1024; } static void task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { ls = open_listen_socket (); lsock = GNUNET_CONNECTION_create_from_existing (ls); GNUNET_assert (lsock != NULL); csock = GNUNET_CONNECTION_create_from_connect (cfg, "localhost", PORT); GNUNET_assert (csock != NULL); GNUNET_assert (NULL != GNUNET_CONNECTION_notify_transmit_ready (csock, 1024, GNUNET_TIME_UNIT_SECONDS, &send_kilo, cls)); } int main (int argc, char *argv[]) { int ok; GNUNET_log_setup ("test_connection_timeout", "WARNING", NULL); ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); GNUNET_SCHEDULER_run (&task_timeout, &ok); GNUNET_CONFIGURATION_destroy (cfg); return ok; } /* end of test_connection_timeout.c */ gnunet-0.10.1/src/util/test_container_multihashmap.c0000644000175000017500000001212612225777501017531 00000000000000/* This file is part of GNUnet. (C) 2008 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_container_multihashmap.c * @brief Test for container_multihashmap.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); if (m != NULL) GNUNET_CONTAINER_multihashmap_destroy(m); return 1; } #define CHECK(c) { if (! (c)) ABORT(); } static int testMap (int i) { struct GNUNET_CONTAINER_MultiHashMap *m; struct GNUNET_HashCode k1; struct GNUNET_HashCode k2; struct GNUNET_CONTAINER_MultiHashMapIterator *iter; struct GNUNET_HashCode key_ret; const char *ret; int j; CHECK (NULL != (m = GNUNET_CONTAINER_multihashmap_create (i, GNUNET_NO))); memset (&k1, 0, sizeof (k1)); memset (&k2, 1, sizeof (k2)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (m, &k1)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (m, &k2)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (m, &k1, NULL)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (m, &k2, NULL)); CHECK (NULL == GNUNET_CONTAINER_multihashmap_get (m, &k1)); CHECK (NULL == GNUNET_CONTAINER_multihashmap_get (m, &k2)); CHECK (0 == GNUNET_CONTAINER_multihashmap_remove_all (m, &k1)); CHECK (0 == GNUNET_CONTAINER_multihashmap_size (m)); CHECK (0 == GNUNET_CONTAINER_multihashmap_iterate (m, NULL, NULL)); CHECK (0 == GNUNET_CONTAINER_multihashmap_get_multiple (m, &k1, NULL, NULL)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (m, &k1, "v1", GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); CHECK (1 == GNUNET_CONTAINER_multihashmap_size (m)); ret = GNUNET_CONTAINER_multihashmap_get (m, &k1); GNUNET_assert (ret != NULL); CHECK (0 == strcmp ("v1", ret)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_put (m, &k1, "v1", GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); CHECK (1 == GNUNET_CONTAINER_multihashmap_size (m)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (m, &k1, "v2", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (m, &k1, "v3", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); CHECK (3 == GNUNET_CONTAINER_multihashmap_size (m)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (m, &k1, "v3")); CHECK (2 == GNUNET_CONTAINER_multihashmap_size (m)); CHECK (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (m, &k1)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (m, &k2)); CHECK (2 == GNUNET_CONTAINER_multihashmap_get_multiple (m, &k1, NULL, NULL)); CHECK (0 == GNUNET_CONTAINER_multihashmap_get_multiple (m, &k2, NULL, NULL)); CHECK (2 == GNUNET_CONTAINER_multihashmap_iterate (m, NULL, NULL)); iter = GNUNET_CONTAINER_multihashmap_iterator_create (m); CHECK (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter, &key_ret, (const void **)&ret)); CHECK (0 == memcmp (&key_ret, &k1, sizeof (key_ret))); CHECK (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter, &key_ret, (const void **)&ret)); CHECK (0 == memcmp (&key_ret, &k1, sizeof (key_ret))); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL, NULL)); GNUNET_free (iter); CHECK (2 == GNUNET_CONTAINER_multihashmap_remove_all (m, &k1)); for (j = 0; j < 1024; j++) CHECK (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (m, &k1, "v2", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); iter = GNUNET_CONTAINER_multihashmap_iterator_create (m); for (j = 0; j < GNUNET_CONTAINER_multihashmap_size (m); j++) CHECK (GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL, NULL)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL, NULL)); GNUNET_free (iter); GNUNET_CONTAINER_multihashmap_destroy (m); return 0; } int main (int argc, char *argv[]) { int failureCount = 0; int i; GNUNET_log_setup ("test-container-multihashmap", "WARNING", NULL); for (i = 1; i < 255; i++) failureCount += testMap (i); if (failureCount != 0) return 1; return 0; } /* end of test_container_multihashmap.c */ gnunet-0.10.1/src/util/disk.c0000644000175000017500000020307012303035353012653 00000000000000/* This file is part of GNUnet. (C) 2001--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/disk.c * @brief disk IO convenience methods * @author Christian Grothoff * @author Nils Durner */ #include "platform.h" #include "gnunet_util_lib.h" #include "disk.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * Block size for IO for copying files. */ #define COPY_BLK_SIZE 65536 #include #if HAVE_SYS_VFS_H #include #endif #if HAVE_SYS_PARAM_H #include #endif #if HAVE_SYS_MOUNT_H #include #endif #if HAVE_SYS_STATVFS_H #include #endif #ifndef S_ISLNK #define _IFMT 0170000 /* type of file */ #define _IFLNK 0120000 /* symbolic link */ #define S_ISLNK(m) (((m)&_IFMT) == _IFLNK) #endif /** * Handle used to manage a pipe. */ struct GNUNET_DISK_PipeHandle { /** * File descriptors for the pipe. * One or both of them could be NULL. */ struct GNUNET_DISK_FileHandle *fd[2]; }; /** * Closure for the recursion to determine the file size * of a directory. */ struct GetFileSizeData { /** * Set to the total file size. */ uint64_t total; /** * GNUNET_YES if symbolic links should be included. */ int include_sym_links; /** * GNUNET_YES if mode is file-only (return total == -1 for directories). */ int single_file_mode; }; #ifndef MINGW /** * Translate GNUnet-internal permission bitmap to UNIX file * access permission bitmap. * * @param perm file permissions, GNUnet style * @return file permissions, UNIX style */ static int translate_unix_perms (enum GNUNET_DISK_AccessPermissions perm) { int mode; mode = 0; if (perm & GNUNET_DISK_PERM_USER_READ) mode |= S_IRUSR; if (perm & GNUNET_DISK_PERM_USER_WRITE) mode |= S_IWUSR; if (perm & GNUNET_DISK_PERM_USER_EXEC) mode |= S_IXUSR; if (perm & GNUNET_DISK_PERM_GROUP_READ) mode |= S_IRGRP; if (perm & GNUNET_DISK_PERM_GROUP_WRITE) mode |= S_IWGRP; if (perm & GNUNET_DISK_PERM_GROUP_EXEC) mode |= S_IXGRP; if (perm & GNUNET_DISK_PERM_OTHER_READ) mode |= S_IROTH; if (perm & GNUNET_DISK_PERM_OTHER_WRITE) mode |= S_IWOTH; if (perm & GNUNET_DISK_PERM_OTHER_EXEC) mode |= S_IXOTH; return mode; } #endif /** * Iterate over all files in the given directory and * accumulate their size. * * @param cls closure of type `struct GetFileSizeData` * @param fn current filename we are looking at * @return #GNUNET_SYSERR on serious errors, otherwise #GNUNET_OK */ static int getSizeRec (void *cls, const char *fn) { struct GetFileSizeData *gfsd = cls; #if defined (HAVE_STAT64) && !(defined (_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64) STRUCT_STAT64 buf; if (0 != STAT64 (fn, &buf)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "stat64", fn); return GNUNET_SYSERR; } #else struct stat buf; if (0 != STAT (fn, &buf)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "stat", fn); return GNUNET_SYSERR; } #endif if ((S_ISDIR (buf.st_mode)) && (gfsd->single_file_mode == GNUNET_YES)) { errno = EISDIR; return GNUNET_SYSERR; } if ((!S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES)) gfsd->total += buf.st_size; if ((S_ISDIR (buf.st_mode)) && (0 == ACCESS (fn, X_OK)) && ((!S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES))) { if (GNUNET_SYSERR == GNUNET_DISK_directory_scan (fn, &getSizeRec, gfsd)) return GNUNET_SYSERR; } return GNUNET_OK; } /** * Checks whether a handle is invalid * * @param h handle to check * @return #GNUNET_YES if invalid, #GNUNET_NO if valid */ int GNUNET_DISK_handle_invalid (const struct GNUNET_DISK_FileHandle *h) { #ifdef MINGW return ((!h) || (h->h == INVALID_HANDLE_VALUE)) ? GNUNET_YES : GNUNET_NO; #else return ((!h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO; #endif } /** * Get the size of an open file. * * @param fh open file handle * @param size where to write size of the file * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_file_handle_size (struct GNUNET_DISK_FileHandle *fh, off_t *size) { #if WINDOWS BOOL b; LARGE_INTEGER li; b = GetFileSizeEx (fh->h, &li); if (!b) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } *size = (off_t) li.QuadPart; #else struct stat sbuf; if (0 != FSTAT (fh->fd, &sbuf)) return GNUNET_SYSERR; *size = sbuf.st_size; #endif return GNUNET_OK; } /** * Move the read/write pointer in a file * * @param h handle of an open file * @param offset position to move to * @param whence specification to which position the offset parameter relates to * @return the new position on success, #GNUNET_SYSERR otherwise */ off_t GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, off_t offset, enum GNUNET_DISK_Seek whence) { if (h == NULL) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW LARGE_INTEGER li; LARGE_INTEGER new_pos; BOOL b; static DWORD t[] = { FILE_BEGIN, FILE_CURRENT, FILE_END }; li.QuadPart = offset; b = SetFilePointerEx (h->h, li, &new_pos, t[whence]); if (b == 0) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } return (off_t) new_pos.QuadPart; #else static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END }; return lseek (h->fd, offset, t[whence]); #endif } /** * Get the size of the file (or directory) of the given file (in * bytes). * * @param filename name of the file or directory * @param size set to the size of the file (or, * in the case of directories, the sum * of all sizes of files in the directory) * @param include_symbolic_links should symbolic links be * included? * @param single_file_mode #GNUNET_YES to only get size of one file * and return #GNUNET_SYSERR for directories. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success */ int GNUNET_DISK_file_size (const char *filename, uint64_t * size, int include_symbolic_links, int single_file_mode) { struct GetFileSizeData gfsd; int ret; GNUNET_assert (size != NULL); gfsd.total = 0; gfsd.include_sym_links = include_symbolic_links; gfsd.single_file_mode = single_file_mode; ret = getSizeRec (&gfsd, filename); *size = gfsd.total; return ret; } /** * Obtain some unique identifiers for the given file * that can be used to identify it in the local system. * This function is used between GNUnet processes to * quickly check if two files with the same absolute path * are actually identical. The two processes represent * the same peer but may communicate over the network * (and the file may be on an NFS volume). This function * may not be supported on all operating systems. * * @param filename name of the file * @param dev set to the device ID * @param ino set to the inode ID * @return #GNUNET_OK on success */ int GNUNET_DISK_file_get_identifiers (const char *filename, uint64_t * dev, uint64_t * ino) { #if WINDOWS { // FIXME NILS: test this struct GNUNET_DISK_FileHandle *fh; BY_HANDLE_FILE_INFORMATION info; int succ; fh = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, 0); if (fh == NULL) return GNUNET_SYSERR; succ = GetFileInformationByHandle (fh->h, &info); GNUNET_DISK_file_close (fh); if (!succ) { return GNUNET_SYSERR; } *dev = info.dwVolumeSerialNumber; *ino = ((((uint64_t) info.nFileIndexHigh) << (sizeof (DWORD) * 8)) | info.nFileIndexLow); } #else /* !WINDOWS */ #if HAVE_STAT { struct stat sbuf; if (0 != stat (filename, &sbuf)) { return GNUNET_SYSERR; } *ino = (uint64_t) sbuf.st_ino; } #else *ino = 0; #endif #if HAVE_STATVFS { struct statvfs fbuf; if (0 != statvfs (filename, &fbuf)) { return GNUNET_SYSERR; } *dev = (uint64_t) fbuf.f_fsid; } #elif HAVE_STATFS { struct statfs fbuf; if (0 != statfs (filename, &fbuf)) { return GNUNET_SYSERR; } *dev = ((uint64_t) fbuf.f_fsid.val[0]) << 32 || ((uint64_t) fbuf.f_fsid.val[1]); } #else *dev = 0; #endif #endif /* !WINDOWS */ return GNUNET_OK; } /** * Create the name for a temporary file or directory from a template. * * @param t template (without XXXXX or "/tmp/") * @return name ready for passing to 'mktemp' or 'mkdtemp', NULL on error */ static char * mktemp_name (const char *t) { const char *tmpdir; char *tmpl; char *fn; if ((t[0] != '/') && (t[0] != '\\') #if WINDOWS && !(isalpha ((int) t[0]) && (t[0] != '\0') && (t[1] == ':')) #endif ) { /* FIXME: This uses system codepage on W32, not UTF-8 */ tmpdir = getenv ("TMPDIR"); if (NULL == tmpdir) tmpdir = getenv ("TMP"); if (NULL == tmpdir) tmpdir = getenv ("TEMP"); if (NULL == tmpdir) tmpdir = "/tmp"; GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX"); } else { GNUNET_asprintf (&tmpl, "%s%s", t, "XXXXXX"); } #ifdef MINGW fn = (char *) GNUNET_malloc (MAX_PATH + 1); if (ERROR_SUCCESS != plibc_conv_to_win_path (tmpl, fn)) { GNUNET_free (fn); GNUNET_free (tmpl); return NULL; } GNUNET_free (tmpl); #else fn = tmpl; #endif return fn; } #if WINDOWS static char * mkdtemp (char *fn) { char *random_fn; char *tfn; while (1) { tfn = GNUNET_strdup (fn); random_fn = _mktemp (tfn); if (NULL == random_fn) { GNUNET_free (tfn); return NULL; } /* FIXME: assume fn to be UTF-8-encoded and do the right thing */ if (0 == CreateDirectoryA (tfn, NULL)) { DWORD error = GetLastError (); GNUNET_free (tfn); if (ERROR_ALREADY_EXISTS == error) continue; return NULL; } break; } strcpy (fn, tfn); return fn; } #else /** * Update POSIX permissions mask of a file on disk. If both argumets * are #GNUNET_NO, the file is made world-read-write-executable (777). * * @param fn name of the file to update * @param require_uid_match #GNUNET_YES means 700 * @param require_gid_match #GNUNET_YES means 770 unless @a require_uid_match is set */ void GNUNET_DISK_fix_permissions (const char *fn, int require_uid_match, int require_gid_match) { mode_t mode; if (GNUNET_YES == require_uid_match) mode = S_IRUSR | S_IWUSR | S_IXUSR; else if (GNUNET_YES == require_gid_match) mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP; else mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH; if (0 != chmod (fn, mode)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "chmod", fn); } #endif /** * Create an (empty) temporary directory on disk. If the given name is not * an absolute path, the current 'TMPDIR' will be prepended. In any case, * 6 random characters will be appended to the name to create a unique * filename. * * @param t component to use for the name; * does NOT contain "XXXXXX" or "/tmp/". * @return NULL on error, otherwise name of fresh * file on disk in directory for temporary files */ char * GNUNET_DISK_mkdtemp (const char *t) { char *fn; fn = mktemp_name (t); if (fn != mkdtemp (fn)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "mkstemp", fn); GNUNET_free (fn); return NULL; } return fn; } /** * Move a file out of the way (create a backup) by * renaming it to "orig.NUM~" where NUM is the smallest * number that is not used yet. * * @param fil name of the file to back up */ void GNUNET_DISK_file_backup (const char *fil) { size_t slen; char *target; unsigned int num; slen = strlen (fil) + 20; target = GNUNET_malloc (slen); num = 0; do { GNUNET_snprintf (target, slen, "%s.%u~", fil, num++); } while (0 == access (target, F_OK)); if (0 != rename (fil, target)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "rename", fil); GNUNET_free (target); } /** * Create an (empty) temporary file on disk. If the given name is not * an absolute path, the current 'TMPDIR' will be prepended. In any case, * 6 random characters will be appended to the name to create a unique * filename. * * @param t component to use for the name; * does NOT contain "XXXXXX" or "/tmp/". * @return NULL on error, otherwise name of fresh * file on disk in directory for temporary files */ char * GNUNET_DISK_mktemp (const char *t) { int fd; char *fn; fn = mktemp_name (t); if (-1 == (fd = mkstemp (fn))) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "mkstemp", fn); GNUNET_free (fn); return NULL; } if (0 != CLOSE (fd)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "close", fn); return fn; } /** * Test if @a fil is a directory and listable. Optionally, also check if the * directory is readable. Will not print an error message if the directory does * not exist. Will log errors if #GNUNET_SYSERR is returned (i.e., a file exists * with the same name). * * @param fil filename to test * @param is_readable GNUNET_YES to additionally check if @a fil is readable; * #GNUNET_NO to disable this check * @return #GNUNET_YES if yes, #GNUNET_NO if not; #GNUNET_SYSERR if it * does not exist or stat'ed */ int GNUNET_DISK_directory_test (const char *fil, int is_readable) { struct stat filestat; int ret; ret = STAT (fil, &filestat); if (ret != 0) { if (errno != ENOENT) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", fil); return GNUNET_SYSERR; } if (!S_ISDIR (filestat.st_mode)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "A file already exits with the same name %s\n", fil); return GNUNET_NO; } if (GNUNET_YES == is_readable) ret = ACCESS (fil, R_OK | X_OK); else ret = ACCESS (fil, X_OK); if (ret < 0) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", fil); return GNUNET_NO; } return GNUNET_YES; } /** * Check that fil corresponds to a filename * (of a file that exists and that is not a directory). * * @param fil filename to check * @return #GNUNET_YES if yes, #GNUNET_NO if not a file, #GNUNET_SYSERR if something * else (will print an error message in that case, too). */ int GNUNET_DISK_file_test (const char *fil) { struct stat filestat; int ret; char *rdir; rdir = GNUNET_STRINGS_filename_expand (fil); if (rdir == NULL) return GNUNET_SYSERR; ret = STAT (rdir, &filestat); if (ret != 0) { if (errno != ENOENT) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", rdir); GNUNET_free (rdir); return GNUNET_SYSERR; } GNUNET_free (rdir); return GNUNET_NO; } if (!S_ISREG (filestat.st_mode)) { GNUNET_free (rdir); return GNUNET_NO; } if (ACCESS (rdir, F_OK) < 0) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", rdir); GNUNET_free (rdir); return GNUNET_SYSERR; } GNUNET_free (rdir); return GNUNET_YES; } /** * Implementation of "mkdir -p" * * @param dir the directory to create * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GNUNET_DISK_directory_create (const char *dir) { char *rdir; unsigned int len; unsigned int pos; unsigned int pos2; int ret = GNUNET_OK; rdir = GNUNET_STRINGS_filename_expand (dir); if (rdir == NULL) return GNUNET_SYSERR; len = strlen (rdir); #ifndef MINGW pos = 1; /* skip heading '/' */ #else /* Local or Network path? */ if (strncmp (rdir, "\\\\", 2) == 0) { pos = 2; while (rdir[pos]) { if (rdir[pos] == '\\') { pos++; break; } pos++; } } else { pos = 3; /* strlen("C:\\") */ } #endif /* Check which low level directories already exist */ pos2 = len; rdir[len] = DIR_SEPARATOR; while (pos <= pos2) { if (DIR_SEPARATOR == rdir[pos2]) { rdir[pos2] = '\0'; ret = GNUNET_DISK_directory_test (rdir, GNUNET_NO); if (GNUNET_NO == ret) { GNUNET_free (rdir); return GNUNET_SYSERR; } rdir[pos2] = DIR_SEPARATOR; if (GNUNET_YES == ret) { pos2++; break; } } pos2--; } rdir[len] = '\0'; if (pos < pos2) pos = pos2; /* Start creating directories */ while (pos <= len) { if ((rdir[pos] == DIR_SEPARATOR) || (pos == len)) { rdir[pos] = '\0'; ret = GNUNET_DISK_directory_test (rdir, GNUNET_NO); if (GNUNET_NO == ret) { GNUNET_free (rdir); return GNUNET_SYSERR; } if (GNUNET_SYSERR == ret) { #ifndef MINGW ret = mkdir (rdir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); /* 755 */ #else wchar_t wrdir[MAX_PATH + 1]; if (ERROR_SUCCESS == plibc_conv_to_win_pathwconv(rdir, wrdir)) ret = !CreateDirectoryW (wrdir, NULL); else ret = 1; #endif if ((ret != 0) && (errno != EEXIST)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "mkdir", rdir); GNUNET_free (rdir); return GNUNET_SYSERR; } } rdir[pos] = DIR_SEPARATOR; } pos++; } GNUNET_free (rdir); return GNUNET_OK; } /** * Create the directory structure for storing * a file. * * @param filename name of a file in the directory * @returns #GNUNET_OK on success, * #GNUNET_SYSERR on failure, * #GNUNET_NO if the directory * exists but is not writeable for us */ int GNUNET_DISK_directory_create_for_file (const char *filename) { char *rdir; size_t len; int ret; rdir = GNUNET_STRINGS_filename_expand (filename); if (rdir == NULL) return GNUNET_SYSERR; len = strlen (rdir); while ((len > 0) && (rdir[len] != DIR_SEPARATOR)) len--; rdir[len] = '\0'; ret = GNUNET_DISK_directory_create (rdir); if ((ret == GNUNET_OK) && (0 != ACCESS (rdir, W_OK))) ret = GNUNET_NO; GNUNET_free (rdir); return ret; } /** * Read the contents of a binary file into a buffer. * * @param h handle to an open file * @param result the buffer to write the result to * @param len the maximum number of bytes to read * @return the number of bytes read on success, #GNUNET_SYSERR on failure */ ssize_t GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle *h, void *result, size_t len) { if (NULL == h) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW DWORD bytes_read; if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) { if (!ReadFile (h->h, result, len, &bytes_read, NULL)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } } else { if (!ReadFile (h->h, result, len, &bytes_read, h->oOverlapRead)) { if (GetLastError () != ERROR_IO_PENDING) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Error reading from pipe: %u\n", GetLastError ()); SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Will get overlapped result\n"); GetOverlappedResult (h->h, h->oOverlapRead, &bytes_read, TRUE); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %u bytes from pipe\n", bytes_read); } return bytes_read; #else return read (h->fd, result, len); #endif } /** * Read the contents of a binary file into a buffer. * Guarantees not to block (returns GNUNET_SYSERR and sets errno to EAGAIN * when no data can be read). * * @param h handle to an open file * @param result the buffer to write the result to * @param len the maximum number of bytes to read * @return the number of bytes read on success, #GNUNET_SYSERR on failure */ ssize_t GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle *h, void *result, size_t len) { if (NULL == h) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW DWORD bytes_read; if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) { if (!ReadFile (h->h, result, len, &bytes_read, NULL)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } } else { if (!ReadFile (h->h, result, len, &bytes_read, h->oOverlapRead)) { if (GetLastError () != ERROR_IO_PENDING) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Error reading from pipe: %u\n", GetLastError ()); SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadFile() queued a read, cancelling\n"); CancelIo (h->h); errno = EAGAIN; return GNUNET_SYSERR; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %u bytes\n", bytes_read); } return bytes_read; #else int flags; ssize_t ret; /* set to non-blocking, read, then set back */ flags = fcntl (h->fd, F_GETFL); if (0 == (flags & O_NONBLOCK)) (void) fcntl (h->fd, F_SETFL, flags | O_NONBLOCK); ret = read (h->fd, result, len); if (0 == (flags & O_NONBLOCK)) { int eno = errno; (void) fcntl (h->fd, F_SETFL, flags); errno = eno; } return ret; #endif } /** * Read the contents of a binary file into a buffer. * * @param fn file name * @param result the buffer to write the result to * @param len the maximum number of bytes to read * @return number of bytes read, #GNUNET_SYSERR on failure */ ssize_t GNUNET_DISK_fn_read (const char *fn, void *result, size_t len) { struct GNUNET_DISK_FileHandle *fh; ssize_t ret; fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (!fh) return GNUNET_SYSERR; ret = GNUNET_DISK_file_read (fh, result, len); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); return ret; } /** * Write a buffer to a file. * * @param h handle to open file * @param buffer the data to write * @param n number of bytes to write * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h, const void *buffer, size_t n) { if (NULL == h) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW DWORD bytes_written; if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) { if (!WriteFile (h->h, buffer, n, &bytes_written, NULL)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "It is a pipe trying to write %u bytes\n", n); if (!WriteFile (h->h, buffer, n, &bytes_written, h->oOverlapWrite)) { if (GetLastError () != ERROR_IO_PENDING) { SetErrnoFromWinError (GetLastError ()); LOG (GNUNET_ERROR_TYPE_DEBUG, "Error writing to pipe: %u\n", GetLastError ()); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Will get overlapped result\n"); if (!GetOverlappedResult (h->h, h->oOverlapWrite, &bytes_written, TRUE)) { SetErrnoFromWinError (GetLastError ()); LOG (GNUNET_ERROR_TYPE_DEBUG, "Error getting overlapped result while writing to pipe: %u\n", GetLastError ()); return GNUNET_SYSERR; } } else { DWORD ovr; if (!GetOverlappedResult (h->h, h->oOverlapWrite, &ovr, TRUE)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Error getting control overlapped result while writing to pipe: %u\n", GetLastError ()); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes (ovr says %u), picking the greatest\n", bytes_written, ovr); } } if (bytes_written == 0) { if (n > 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes, returning -1 with EAGAIN\n", bytes_written); errno = EAGAIN; return GNUNET_SYSERR; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes\n", bytes_written); } return bytes_written; #else return write (h->fd, buffer, n); #endif } /** * Write a buffer to a file, blocking, if necessary. * * @param h handle to open file * @param buffer the data to write * @param n number of bytes to write * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t GNUNET_DISK_file_write_blocking (const struct GNUNET_DISK_FileHandle * h, const void *buffer, size_t n) { if (NULL == h) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW DWORD bytes_written; /* We do a non-overlapped write, which is as blocking as it gets */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Writing %u bytes\n", n); if (!WriteFile (h->h, buffer, n, &bytes_written, NULL)) { SetErrnoFromWinError (GetLastError ()); LOG (GNUNET_ERROR_TYPE_DEBUG, "Error writing to pipe: %u\n", GetLastError ()); return GNUNET_SYSERR; } if (bytes_written == 0 && n > 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for pipe to clean\n"); WaitForSingleObject (h->h, INFINITE); if (!WriteFile (h->h, buffer, n, &bytes_written, NULL)) { SetErrnoFromWinError (GetLastError ()); LOG (GNUNET_ERROR_TYPE_DEBUG, "Error writing to pipe: %u\n", GetLastError ()); return GNUNET_SYSERR; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Wrote %u bytes\n", bytes_written); return bytes_written; #else int flags; ssize_t ret; /* set to blocking, write, then set back */ flags = fcntl (h->fd, F_GETFL); if (0 != (flags & O_NONBLOCK)) (void) fcntl (h->fd, F_SETFL, flags - O_NONBLOCK); ret = write (h->fd, buffer, n); if (0 == (flags & O_NONBLOCK)) (void) fcntl (h->fd, F_SETFL, flags); return ret; #endif } /** * Write a buffer to a file. If the file is longer than the * number of bytes that will be written, it will be truncated. * * @param fn file name * @param buffer the data to write * @param n number of bytes to write * @param mode file permissions * @return number of bytes written on success, #GNUNET_SYSERR on error */ ssize_t GNUNET_DISK_fn_write (const char *fn, const void *buffer, size_t n, enum GNUNET_DISK_AccessPermissions mode) { struct GNUNET_DISK_FileHandle *fh; ssize_t ret; fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE, mode); if (!fh) return GNUNET_SYSERR; ret = GNUNET_DISK_file_write (fh, buffer, n); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); return ret; } /** * Scan a directory for files. * * @param dir_name the name of the directory * @param callback the method to call for each file, * can be NULL, in that case, we only count * @param callback_cls closure for @a callback * @return the number of files found, #GNUNET_SYSERR on error or * ieration aborted by callback returning #GNUNET_SYSERR */ int GNUNET_DISK_directory_scan (const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls) { DIR *dinfo; struct dirent *finfo; struct stat istat; int count = 0; int ret; char *name; char *dname; unsigned int name_len; unsigned int n_size; GNUNET_assert (dir_name != NULL); dname = GNUNET_STRINGS_filename_expand (dir_name); if (dname == NULL) return GNUNET_SYSERR; while ((strlen (dname) > 0) && (dname[strlen (dname) - 1] == DIR_SEPARATOR)) dname[strlen (dname) - 1] = '\0'; if (0 != STAT (dname, &istat)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", dname); GNUNET_free (dname); return GNUNET_SYSERR; } if (!S_ISDIR (istat.st_mode)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Expected `%s' to be a directory!\n"), dir_name); GNUNET_free (dname); return GNUNET_SYSERR; } errno = 0; dinfo = OPENDIR (dname); if ((errno == EACCES) || (dinfo == NULL)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "opendir", dname); if (dinfo != NULL) CLOSEDIR (dinfo); GNUNET_free (dname); return GNUNET_SYSERR; } name_len = 256; n_size = strlen (dname) + name_len + 2; name = GNUNET_malloc (n_size); while ((finfo = READDIR (dinfo)) != NULL) { if ((0 == strcmp (finfo->d_name, ".")) || (0 == strcmp (finfo->d_name, ".."))) continue; if (callback != NULL) { if (name_len < strlen (finfo->d_name)) { GNUNET_free (name); name_len = strlen (finfo->d_name); n_size = strlen (dname) + name_len + 2; name = GNUNET_malloc (n_size); } /* dname can end in "/" only if dname == "/"; * if dname does not end in "/", we need to add * a "/" (otherwise, we must not!) */ GNUNET_snprintf (name, n_size, "%s%s%s", dname, (strcmp (dname, DIR_SEPARATOR_STR) == 0) ? "" : DIR_SEPARATOR_STR, finfo->d_name); ret = callback (callback_cls, name); if (GNUNET_OK != ret) { CLOSEDIR (dinfo); GNUNET_free (name); GNUNET_free (dname); if (GNUNET_NO == ret) return count; return GNUNET_SYSERR; } } count++; } CLOSEDIR (dinfo); GNUNET_free (name); GNUNET_free (dname); return count; } /** * Opaque handle used for iterating over a directory. */ struct GNUNET_DISK_DirectoryIterator { /** * Function to call on directory entries. */ GNUNET_DISK_DirectoryIteratorCallback callback; /** * Closure for callback. */ void *callback_cls; /** * Reference to directory. */ DIR *directory; /** * Directory name. */ char *dirname; /** * Next filename to process. */ char *next_name; /** * Our priority. */ enum GNUNET_SCHEDULER_Priority priority; }; /** * Task used by the directory iterator. */ static void directory_iterator_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DISK_DirectoryIterator *iter = cls; char *name; name = iter->next_name; GNUNET_assert (name != NULL); iter->next_name = NULL; iter->callback (iter->callback_cls, iter, name, iter->dirname); GNUNET_free (name); } /** * This function must be called during the DiskIteratorCallback * (exactly once) to schedule the task to process the next * filename in the directory (if there is one). * * @param iter opaque handle for the iterator * @param can set to GNUNET_YES to terminate the iteration early * @return GNUNET_YES if iteration will continue, * GNUNET_NO if this was the last entry (and iteration is complete), * GNUNET_SYSERR if abort was YES */ int GNUNET_DISK_directory_iterator_next (struct GNUNET_DISK_DirectoryIterator *iter, int can) { struct dirent *finfo; GNUNET_assert (iter->next_name == NULL); if (can == GNUNET_YES) { CLOSEDIR (iter->directory); GNUNET_free (iter->dirname); GNUNET_free (iter); return GNUNET_SYSERR; } while (NULL != (finfo = READDIR (iter->directory))) { if ((0 == strcmp (finfo->d_name, ".")) || (0 == strcmp (finfo->d_name, ".."))) continue; GNUNET_asprintf (&iter->next_name, "%s%s%s", iter->dirname, DIR_SEPARATOR_STR, finfo->d_name); break; } if (finfo == NULL) { GNUNET_DISK_directory_iterator_next (iter, GNUNET_YES); return GNUNET_NO; } GNUNET_SCHEDULER_add_with_priority (iter->priority, &directory_iterator_task, iter); return GNUNET_YES; } /** * Scan a directory for files using the scheduler to run a task for * each entry. The name of the directory must be expanded first (!). * If a scheduler does not need to be used, GNUNET_DISK_directory_scan * may provide a simpler API. * * @param prio priority to use * @param dir_name the name of the directory * @param callback the method to call for each file * @param callback_cls closure for callback * @return GNUNET_YES if directory is not empty and 'callback' * will be called later, GNUNET_NO otherwise, GNUNET_SYSERR on error. */ int GNUNET_DISK_directory_iterator_start (enum GNUNET_SCHEDULER_Priority prio, const char *dir_name, GNUNET_DISK_DirectoryIteratorCallback callback, void *callback_cls) { struct GNUNET_DISK_DirectoryIterator *di; di = GNUNET_new (struct GNUNET_DISK_DirectoryIterator); di->callback = callback; di->callback_cls = callback_cls; di->directory = OPENDIR (dir_name); if (di->directory == NULL) { GNUNET_free (di); callback (callback_cls, NULL, NULL, NULL); return GNUNET_SYSERR; } di->dirname = GNUNET_strdup (dir_name); di->priority = prio; return GNUNET_DISK_directory_iterator_next (di, GNUNET_NO); } /** * Function that removes the given directory by calling * "GNUNET_DISK_directory_remove". * * @param unused not used * @param fn directory to remove * @return #GNUNET_OK */ static int remove_helper (void *unused, const char *fn) { (void) GNUNET_DISK_directory_remove (fn); return GNUNET_OK; } /** * Remove all files in a directory (rm -rf). Call with * caution. * * @param filename the file to remove * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_directory_remove (const char *filename) { struct stat istat; if (NULL == filename) { GNUNET_break (0); return GNUNET_SYSERR; } if (0 != LSTAT (filename, &istat)) return GNUNET_NO; /* file may not exist... */ (void) CHMOD (filename, S_IWUSR | S_IRUSR | S_IXUSR); if (UNLINK (filename) == 0) return GNUNET_OK; if ((errno != EISDIR) && /* EISDIR is not sufficient in all cases, e.g. * sticky /tmp directory may result in EPERM on BSD. * So we also explicitly check "isDirectory" */ (GNUNET_YES != GNUNET_DISK_directory_test (filename, GNUNET_YES))) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", filename); return GNUNET_SYSERR; } if (GNUNET_SYSERR == GNUNET_DISK_directory_scan (filename, &remove_helper, NULL)) return GNUNET_SYSERR; if (0 != RMDIR (filename)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", filename); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Copy a file. * * @param src file to copy * @param dst destination file name * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_file_copy (const char *src, const char *dst) { char *buf; uint64_t pos; uint64_t size; size_t len; struct GNUNET_DISK_FileHandle *in; struct GNUNET_DISK_FileHandle *out; if (GNUNET_OK != GNUNET_DISK_file_size (src, &size, GNUNET_YES, GNUNET_YES)) return GNUNET_SYSERR; pos = 0; in = GNUNET_DISK_file_open (src, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (!in) return GNUNET_SYSERR; out = GNUNET_DISK_file_open (dst, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_FAILIFEXISTS, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_GROUP_WRITE); if (!out) { GNUNET_DISK_file_close (in); return GNUNET_SYSERR; } buf = GNUNET_malloc (COPY_BLK_SIZE); while (pos < size) { len = COPY_BLK_SIZE; if (len > size - pos) len = size - pos; if (len != GNUNET_DISK_file_read (in, buf, len)) goto FAIL; if (len != GNUNET_DISK_file_write (out, buf, len)) goto FAIL; pos += len; } GNUNET_free (buf); GNUNET_DISK_file_close (in); GNUNET_DISK_file_close (out); return GNUNET_OK; FAIL: GNUNET_free (buf); GNUNET_DISK_file_close (in); GNUNET_DISK_file_close (out); return GNUNET_SYSERR; } /** * @brief Removes special characters as ':' from a filename. * @param fn the filename to canonicalize */ void GNUNET_DISK_filename_canonicalize (char *fn) { char *idx; char c; idx = fn; while (*idx) { c = *idx; if (c == '/' || c == '\\' || c == ':' || c == '*' || c == '?' || c == '"' || c == '<' || c == '>' || c == '|') { *idx = '_'; } idx++; } } /** * @brief Change owner of a file * * @param filename name of file to change the owner of * @param user name of the new owner * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ int GNUNET_DISK_file_change_owner (const char *filename, const char *user) { #ifndef MINGW struct passwd *pws; pws = getpwnam (user); if (pws == NULL) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot obtain information about user `%s': %s\n"), user, STRERROR (errno)); return GNUNET_SYSERR; } if (0 != chown (filename, pws->pw_uid, pws->pw_gid)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "chown", filename); #endif return GNUNET_OK; } /** * Lock a part of a file * @param fh file handle * @param lock_start absolute position from where to lock * @param lock_end absolute position until where to lock * @param excl GNUNET_YES for an exclusive lock * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GNUNET_DISK_file_lock (struct GNUNET_DISK_FileHandle *fh, off_t lock_start, off_t lock_end, int excl) { if (fh == NULL) { errno = EINVAL; return GNUNET_SYSERR; } #ifndef MINGW struct flock fl; memset (&fl, 0, sizeof (struct flock)); fl.l_type = excl ? F_WRLCK : F_RDLCK; fl.l_whence = SEEK_SET; fl.l_start = lock_start; fl.l_len = lock_end; return fcntl (fh->fd, F_SETLK, &fl) != 0 ? GNUNET_SYSERR : GNUNET_OK; #else OVERLAPPED o; off_t diff = lock_end - lock_start; DWORD diff_low, diff_high; diff_low = (DWORD) (diff & 0xFFFFFFFF); diff_high = (DWORD) ((diff >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); memset (&o, 0, sizeof (OVERLAPPED)); o.Offset = (DWORD) (lock_start & 0xFFFFFFFF);; o.OffsetHigh = (DWORD) (((lock_start & ~0xFFFFFFFF) >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); if (!LockFileEx (fh->h, (excl ? LOCKFILE_EXCLUSIVE_LOCK : 0) | LOCKFILE_FAIL_IMMEDIATELY, 0, diff_low, diff_high, &o)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } return GNUNET_OK; #endif } /** * Unlock a part of a file * @param fh file handle * @param unlock_start absolute position from where to unlock * @param unlock_end absolute position until where to unlock * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_DISK_file_unlock (struct GNUNET_DISK_FileHandle *fh, off_t unlock_start, off_t unlock_end) { if (fh == NULL) { errno = EINVAL; return GNUNET_SYSERR; } #ifndef MINGW struct flock fl; memset (&fl, 0, sizeof (struct flock)); fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = unlock_start; fl.l_len = unlock_end; return fcntl (fh->fd, F_SETLK, &fl) != 0 ? GNUNET_SYSERR : GNUNET_OK; #else OVERLAPPED o; off_t diff = unlock_end - unlock_start; DWORD diff_low, diff_high; diff_low = (DWORD) (diff & 0xFFFFFFFF); diff_high = (DWORD) ((diff >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); memset (&o, 0, sizeof (OVERLAPPED)); o.Offset = (DWORD) (unlock_start & 0xFFFFFFFF);; o.OffsetHigh = (DWORD) (((unlock_start & ~0xFFFFFFFF) >> (sizeof (DWORD) * 8)) & 0xFFFFFFFF); if (!UnlockFileEx (fh->h, 0, diff_low, diff_high, &o)) { SetErrnoFromWinError (GetLastError ()); return GNUNET_SYSERR; } return GNUNET_OK; #endif } /** * Open a file. Note that the access permissions will only be * used if a new file is created and if the underlying operating * system supports the given permissions. * * @param fn file name to be opened * @param flags opening flags, a combination of GNUNET_DISK_OPEN_xxx bit flags * @param perm permissions for the newly created file, use * #GNUNET_DISK_PERM_NONE if a file could not be created by this * call (because of flags) * @return IO handle on success, NULL on error */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm) { char *expfn; struct GNUNET_DISK_FileHandle *ret; #ifdef MINGW DWORD access; DWORD disp; HANDLE h; wchar_t wexpfn[MAX_PATH + 1]; #else int oflags; int mode; int fd; #endif expfn = GNUNET_STRINGS_filename_expand (fn); if (NULL == expfn) return NULL; #ifndef MINGW mode = 0; if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE)) oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */ else if (flags & GNUNET_DISK_OPEN_READ) oflags = O_RDONLY; else if (flags & GNUNET_DISK_OPEN_WRITE) oflags = O_WRONLY; else { GNUNET_break (0); GNUNET_free (expfn); return NULL; } if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) oflags |= (O_CREAT | O_EXCL); if (flags & GNUNET_DISK_OPEN_TRUNCATE) oflags |= O_TRUNC; if (flags & GNUNET_DISK_OPEN_APPEND) oflags |= O_APPEND; if (flags & GNUNET_DISK_OPEN_CREATE) { (void) GNUNET_DISK_directory_create_for_file (expfn); oflags |= O_CREAT; mode = translate_unix_perms (perm); } fd = open (expfn, oflags #if O_CLOEXEC | O_CLOEXEC #endif | O_LARGEFILE, mode); if (fd == -1) { if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "open", expfn); else LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "open", expfn); GNUNET_free (expfn); return NULL; } #else access = 0; disp = OPEN_ALWAYS; if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE)) access = FILE_READ_DATA | FILE_WRITE_DATA; else if (flags & GNUNET_DISK_OPEN_READ) access = FILE_READ_DATA; else if (flags & GNUNET_DISK_OPEN_WRITE) access = FILE_WRITE_DATA; if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) { disp = CREATE_NEW; } else if (flags & GNUNET_DISK_OPEN_CREATE) { (void) GNUNET_DISK_directory_create_for_file (expfn); if (flags & GNUNET_DISK_OPEN_TRUNCATE) disp = CREATE_ALWAYS; else disp = OPEN_ALWAYS; } else if (flags & GNUNET_DISK_OPEN_TRUNCATE) { disp = TRUNCATE_EXISTING; } else { disp = OPEN_EXISTING; } if (ERROR_SUCCESS == plibc_conv_to_win_pathwconv(expfn, wexpfn)) h = CreateFileW (wexpfn, access, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, disp, FILE_ATTRIBUTE_NORMAL, NULL); else h = INVALID_HANDLE_VALUE; if (h == INVALID_HANDLE_VALUE) { int err; SetErrnoFromWinError (GetLastError ()); err = errno; LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_INFO, "open", expfn); GNUNET_free (expfn); errno = err; return NULL; } if (flags & GNUNET_DISK_OPEN_APPEND) if (SetFilePointer (h, 0, 0, FILE_END) == INVALID_SET_FILE_POINTER) { SetErrnoFromWinError (GetLastError ()); LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "SetFilePointer", expfn); CloseHandle (h); GNUNET_free (expfn); return NULL; } #endif ret = GNUNET_new (struct GNUNET_DISK_FileHandle); #ifdef MINGW ret->h = h; ret->type = GNUNET_DISK_HANLDE_TYPE_FILE; #else ret->fd = fd; #endif GNUNET_free (expfn); return ret; } /** * Close an open file * @param h file handle * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ int GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h) { int ret; if (h == NULL) { errno = EINVAL; return GNUNET_SYSERR; } ret = GNUNET_OK; #if MINGW if (!CloseHandle (h->h)) { SetErrnoFromWinError (GetLastError ()); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close"); ret = GNUNET_SYSERR; } if (h->oOverlapRead) { if (!CloseHandle (h->oOverlapRead->hEvent)) { SetErrnoFromWinError (GetLastError ()); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close"); ret = GNUNET_SYSERR; } GNUNET_free (h->oOverlapRead); } if (h->oOverlapWrite) { if (!CloseHandle (h->oOverlapWrite->hEvent)) { SetErrnoFromWinError (GetLastError ()); LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close"); ret = GNUNET_SYSERR; } GNUNET_free (h->oOverlapWrite); } #else if (close (h->fd) != 0) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "close"); ret = GNUNET_SYSERR; } #endif GNUNET_free (h); return ret; } #ifdef WINDOWS /** * Get a GNUnet file handle from a W32 handle. * * @param handle native handle * @return GNUnet file handle corresponding to the W32 handle */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_w32_handle (HANDLE osfh) { struct GNUNET_DISK_FileHandle *fh; DWORD dwret; enum GNUNET_FILE_Type ftype; dwret = GetFileType (osfh); switch (dwret) { case FILE_TYPE_DISK: ftype = GNUNET_DISK_HANLDE_TYPE_FILE; break; case FILE_TYPE_PIPE: ftype = GNUNET_DISK_HANLDE_TYPE_PIPE; break; default: return NULL; } fh = GNUNET_new (struct GNUNET_DISK_FileHandle); fh->h = osfh; fh->type = ftype; if (ftype == GNUNET_DISK_HANLDE_TYPE_PIPE) { /** * Note that we can't make it overlapped if it isn't already. * (ReOpenFile() is only available in 2003/Vista). * The process that opened this file in the first place (usually a parent * process, if this is stdin/stdout/stderr) must make it overlapped, * otherwise we're screwed, as selecting on non-overlapped handle * will block. */ fh->oOverlapRead = GNUNET_new (OVERLAPPED); fh->oOverlapWrite = GNUNET_new (OVERLAPPED); fh->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); fh->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); } return fh; } #endif /** * Get a handle from a native integer FD. * * @param fno native integer file descriptor * @return file handle corresponding to the descriptor, NULL on error */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd (int fno) { struct GNUNET_DISK_FileHandle *fh; if ( (((off_t) -1) == lseek (fno, 0, SEEK_CUR)) && (EBADF == errno) ) return NULL; /* invalid FD */ #ifndef WINDOWS fh = GNUNET_new (struct GNUNET_DISK_FileHandle); fh->fd = fno; #else intptr_t osfh; osfh = _get_osfhandle (fno); if (INVALID_HANDLE_VALUE == (HANDLE) osfh) return NULL; fh = GNUNET_DISK_get_handle_from_w32_handle ((HANDLE) osfh); #endif return fh; } /** * Get a handle from a native streaming FD. * * @param fd native streaming file descriptor * @return file handle corresponding to the descriptor */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_native (FILE *fd) { int fno; fno = fileno (fd); if (-1 == fno) return NULL; return GNUNET_DISK_get_handle_from_int_fd (fno); } /** * Handle for a memory-mapping operation. */ struct GNUNET_DISK_MapHandle { /** * Address where the map is in memory. */ void *addr; #ifdef MINGW /** * Underlying OS handle. */ HANDLE h; #else /** * Number of bytes mapped. */ size_t len; #endif }; #ifndef MAP_FAILED #define MAP_FAILED ((void *) -1) #endif /** * Map a file into memory * * @param h open file handle * @param m handle to the new mapping * @param access access specification, GNUNET_DISK_MAP_TYPE_xxx * @param len size of the mapping * @return pointer to the mapped memory region, NULL on failure */ void * GNUNET_DISK_file_map (const struct GNUNET_DISK_FileHandle *h, struct GNUNET_DISK_MapHandle **m, enum GNUNET_DISK_MapType access, size_t len) { if (h == NULL) { errno = EINVAL; return NULL; } #ifdef MINGW DWORD mapAccess, protect; if ((access & GNUNET_DISK_MAP_TYPE_READ) && (access & GNUNET_DISK_MAP_TYPE_WRITE)) { protect = PAGE_READWRITE; mapAccess = FILE_MAP_ALL_ACCESS; } else if (access & GNUNET_DISK_MAP_TYPE_READ) { protect = PAGE_READONLY; mapAccess = FILE_MAP_READ; } else if (access & GNUNET_DISK_MAP_TYPE_WRITE) { protect = PAGE_READWRITE; mapAccess = FILE_MAP_WRITE; } else { GNUNET_break (0); return NULL; } *m = GNUNET_new (struct GNUNET_DISK_MapHandle); (*m)->h = CreateFileMapping (h->h, NULL, protect, 0, 0, NULL); if ((*m)->h == INVALID_HANDLE_VALUE) { SetErrnoFromWinError (GetLastError ()); GNUNET_free (*m); return NULL; } (*m)->addr = MapViewOfFile ((*m)->h, mapAccess, 0, 0, len); if (!(*m)->addr) { SetErrnoFromWinError (GetLastError ()); CloseHandle ((*m)->h); GNUNET_free (*m); } return (*m)->addr; #else int prot; prot = 0; if (access & GNUNET_DISK_MAP_TYPE_READ) prot = PROT_READ; if (access & GNUNET_DISK_MAP_TYPE_WRITE) prot |= PROT_WRITE; *m = GNUNET_new (struct GNUNET_DISK_MapHandle); (*m)->addr = mmap (NULL, len, prot, MAP_SHARED, h->fd, 0); GNUNET_assert (NULL != (*m)->addr); if (MAP_FAILED == (*m)->addr) { GNUNET_free (*m); return NULL; } (*m)->len = len; return (*m)->addr; #endif } /** * Unmap a file * @param h mapping handle * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ int GNUNET_DISK_file_unmap (struct GNUNET_DISK_MapHandle *h) { int ret; if (h == NULL) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW ret = UnmapViewOfFile (h->addr) ? GNUNET_OK : GNUNET_SYSERR; if (ret != GNUNET_OK) SetErrnoFromWinError (GetLastError ()); if (!CloseHandle (h->h) && (ret == GNUNET_OK)) { ret = GNUNET_SYSERR; SetErrnoFromWinError (GetLastError ()); } #else ret = munmap (h->addr, h->len) != -1 ? GNUNET_OK : GNUNET_SYSERR; #endif GNUNET_free (h); return ret; } /** * Write file changes to disk * @param h handle to an open file * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ int GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h) { if (h == NULL) { errno = EINVAL; return GNUNET_SYSERR; } #ifdef MINGW int ret; ret = FlushFileBuffers (h->h) ? GNUNET_OK : GNUNET_SYSERR; if (ret != GNUNET_OK) SetErrnoFromWinError (GetLastError ()); return ret; #elif defined(FREEBSD) || defined(OPENBSD) || defined(DARWIN) return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK; #else return fdatasync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK; #endif } #if WINDOWS #ifndef PIPE_BUF #define PIPE_BUF 512 #endif /* Copyright Bob Byrnes curl.com> http://permalink.gmane.org/gmane.os.cygwin.patches/2121 */ /* Create a pipe, and return handles to the read and write ends, just like CreatePipe, but ensure that the write end permits FILE_READ_ATTRIBUTES access, on later versions of win32 where this is supported. This access is needed by NtQueryInformationFile, which is used to implement select and nonblocking writes. Note that the return value is either NO_ERROR or GetLastError, unlike CreatePipe, which returns a bool for success or failure. */ static int create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr, LPSECURITY_ATTRIBUTES sa_ptr, DWORD psize, DWORD dwReadMode, DWORD dwWriteMode) { /* Default to error. */ *read_pipe_ptr = *write_pipe_ptr = INVALID_HANDLE_VALUE; HANDLE read_pipe; HANDLE write_pipe; /* Ensure that there is enough pipe buffer space for atomic writes. */ if (psize < PIPE_BUF) psize = PIPE_BUF; char pipename[MAX_PATH]; /* Retry CreateNamedPipe as long as the pipe name is in use. * Retrying will probably never be necessary, but we want * to be as robust as possible. */ while (1) { static volatile LONG pipe_unique_id; snprintf (pipename, sizeof pipename, "\\\\.\\pipe\\gnunet-%d-%ld", getpid (), InterlockedIncrement ((LONG *) & pipe_unique_id)); LOG (GNUNET_ERROR_TYPE_DEBUG, "CreateNamedPipe: name = %s, size = %lu\n", pipename, psize); /* Use CreateNamedPipe instead of CreatePipe, because the latter * returns a write handle that does not permit FILE_READ_ATTRIBUTES * access, on versions of win32 earlier than WinXP SP2. * CreatePipe also stupidly creates a full duplex pipe, which is * a waste, since only a single direction is actually used. * It's important to only allow a single instance, to ensure that * the pipe was not created earlier by some other process, even if * the pid has been reused. */ read_pipe = CreateNamedPipeA (pipename, PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | dwReadMode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, /* max instances */ psize, /* output buffer size */ psize, /* input buffer size */ NMPWAIT_USE_DEFAULT_WAIT, sa_ptr); if (read_pipe != INVALID_HANDLE_VALUE) { LOG (GNUNET_ERROR_TYPE_DEBUG, "pipe read handle = %p\n", read_pipe); break; } DWORD err = GetLastError (); switch (err) { case ERROR_PIPE_BUSY: /* The pipe is already open with compatible parameters. * Pick a new name and retry. */ LOG (GNUNET_ERROR_TYPE_DEBUG, "pipe busy, retrying\n"); continue; case ERROR_ACCESS_DENIED: /* The pipe is already open with incompatible parameters. * Pick a new name and retry. */ LOG (GNUNET_ERROR_TYPE_DEBUG, "pipe access denied, retrying\n"); continue; case ERROR_CALL_NOT_IMPLEMENTED: /* We are on an older Win9x platform without named pipes. * Return an anonymous pipe as the best approximation. */ LOG (GNUNET_ERROR_TYPE_DEBUG, "CreateNamedPipe not implemented, resorting to " "CreatePipe: size = %lu\n", psize); if (CreatePipe (read_pipe_ptr, write_pipe_ptr, sa_ptr, psize)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "pipe read handle = %p, write handle = %p\n", *read_pipe_ptr, *write_pipe_ptr); return GNUNET_OK; } err = GetLastError (); LOG (GNUNET_ERROR_TYPE_ERROR, "CreatePipe failed: %d\n", err); return err; default: LOG (GNUNET_ERROR_TYPE_ERROR, "CreateNamedPipe failed: %d\n", err); return err; } /* NOTREACHED */ } LOG (GNUNET_ERROR_TYPE_DEBUG, "CreateFile: name = %s\n", pipename); /* Open the named pipe for writing. * Be sure to permit FILE_READ_ATTRIBUTES access. */ write_pipe = CreateFileA (pipename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0, /* share mode */ sa_ptr, OPEN_EXISTING, dwWriteMode, /* flags and attributes */ 0); /* handle to template file */ if (write_pipe == INVALID_HANDLE_VALUE) { /* Failure. */ DWORD err = GetLastError (); LOG (GNUNET_ERROR_TYPE_DEBUG, "CreateFile failed: %d\n", err); CloseHandle (read_pipe); return err; } LOG (GNUNET_ERROR_TYPE_DEBUG, "pipe write handle = %p\n", write_pipe); /* Success. */ *read_pipe_ptr = read_pipe; *write_pipe_ptr = write_pipe; return GNUNET_OK; } #endif /** * Creates an interprocess channel * * @param blocking_read creates an asynchronous pipe for reading if set to GNUNET_NO * @param blocking_write creates an asynchronous pipe for writing if set to GNUNET_NO * @param inherit_read inherit the parent processes stdin (only for windows) * @param inherit_write inherit the parent processes stdout (only for windows) * @return handle to the new pipe, NULL on error */ struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int inherit_write) { #ifndef MINGW int fd[2]; int ret; int eno; ret = pipe (fd); if (ret == -1) { eno = errno; LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe"); errno = eno; return NULL; } return GNUNET_DISK_pipe_from_fd (blocking_read, blocking_write, fd); #else struct GNUNET_DISK_PipeHandle *p; BOOL ret; HANDLE tmp_handle; int save_errno; p = GNUNET_new (struct GNUNET_DISK_PipeHandle); p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle); /* All pipes are overlapped. If you want them to block - just * call WriteFile() and ReadFile() with NULL overlapped pointer. * NOTE: calling with NULL overlapped pointer works only * for pipes, and doesn't seem to be a documented feature. * It will NOT work for files, because overlapped files need * to read offsets from the overlapped structure, regardless. * Pipes are not seekable, and need no offsets, which is * probably why it works for them. */ ret = create_selectable_pipe (&p->fd[0]->h, &p->fd[1]->h, NULL, 0, FILE_FLAG_OVERLAPPED, FILE_FLAG_OVERLAPPED); if (!ret) { SetErrnoFromWinError (GetLastError ()); save_errno = errno; GNUNET_free (p->fd[0]); GNUNET_free (p->fd[1]); GNUNET_free (p); errno = save_errno; return NULL; } if (!DuplicateHandle (GetCurrentProcess (), p->fd[0]->h, GetCurrentProcess (), &tmp_handle, 0, inherit_read == GNUNET_YES ? TRUE : FALSE, DUPLICATE_SAME_ACCESS)) { SetErrnoFromWinError (GetLastError ()); save_errno = errno; CloseHandle (p->fd[0]->h); CloseHandle (p->fd[1]->h); GNUNET_free (p->fd[0]); GNUNET_free (p->fd[1]); GNUNET_free (p); errno = save_errno; return NULL; } CloseHandle (p->fd[0]->h); p->fd[0]->h = tmp_handle; if (!DuplicateHandle (GetCurrentProcess (), p->fd[1]->h, GetCurrentProcess (), &tmp_handle, 0, inherit_write == GNUNET_YES ? TRUE : FALSE, DUPLICATE_SAME_ACCESS)) { SetErrnoFromWinError (GetLastError ()); save_errno = errno; CloseHandle (p->fd[0]->h); CloseHandle (p->fd[1]->h); GNUNET_free (p->fd[0]); GNUNET_free (p->fd[1]); GNUNET_free (p); errno = save_errno; return NULL; } CloseHandle (p->fd[1]->h); p->fd[1]->h = tmp_handle; p->fd[0]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; p->fd[1]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; p->fd[0]->oOverlapRead = GNUNET_new (OVERLAPPED); p->fd[0]->oOverlapWrite = GNUNET_new (OVERLAPPED); p->fd[1]->oOverlapRead = GNUNET_new (OVERLAPPED); p->fd[1]->oOverlapWrite = GNUNET_new (OVERLAPPED); p->fd[0]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); p->fd[0]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); p->fd[1]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); p->fd[1]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); return p; #endif } /** * Creates a pipe object from a couple of file descriptors. * Useful for wrapping existing pipe FDs. * * @param blocking_read creates an asynchronous pipe for reading if set to GNUNET_NO * @param blocking_write creates an asynchronous pipe for writing if set to GNUNET_NO * @param fd an array of two fd values. One of them may be -1 for read-only or write-only pipes * * @return handle to the new pipe, NULL on error */ struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]) { struct GNUNET_DISK_PipeHandle *p; p = GNUNET_new (struct GNUNET_DISK_PipeHandle); #ifndef MINGW int ret; int flags; int eno = 0; /* make gcc happy */ ret = 0; if (fd[0] >= 0) { p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[0]->fd = fd[0]; if (!blocking_read) { flags = fcntl (fd[0], F_GETFL); flags |= O_NONBLOCK; if (0 > fcntl (fd[0], F_SETFL, flags)) { ret = -1; eno = errno; } } flags = fcntl (fd[0], F_GETFD); flags |= FD_CLOEXEC; if (0 > fcntl (fd[0], F_SETFD, flags)) { ret = -1; eno = errno; } } if (fd[1] >= 0) { p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[1]->fd = fd[1]; if (!blocking_write) { flags = fcntl (fd[1], F_GETFL); flags |= O_NONBLOCK; if (0 > fcntl (fd[1], F_SETFL, flags)) { ret = -1; eno = errno; } } flags = fcntl (fd[1], F_GETFD); flags |= FD_CLOEXEC; if (0 > fcntl (fd[1], F_SETFD, flags)) { ret = -1; eno = errno; } } if (ret == -1) { errno = eno; LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fcntl"); if (p->fd[0]->fd >= 0) GNUNET_break (0 == close (p->fd[0]->fd)); if (p->fd[1]->fd >= 0) GNUNET_break (0 == close (p->fd[1]->fd)); GNUNET_free_non_null (p->fd[0]); GNUNET_free_non_null (p->fd[1]); GNUNET_free (p); errno = eno; return NULL; } #else if (fd[0] >= 0) { p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[0]->h = (HANDLE) _get_osfhandle (fd[0]); if (p->fd[0]->h != INVALID_HANDLE_VALUE) { p->fd[0]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; p->fd[0]->oOverlapRead = GNUNET_new (OVERLAPPED); p->fd[0]->oOverlapWrite = GNUNET_new (OVERLAPPED); p->fd[0]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); p->fd[0]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); } else { GNUNET_free (p->fd[0]); p->fd[0] = NULL; } } if (fd[1] >= 0) { p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle); p->fd[1]->h = (HANDLE) _get_osfhandle (fd[1]); if (p->fd[1]->h != INVALID_HANDLE_VALUE) { p->fd[1]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; p->fd[1]->oOverlapRead = GNUNET_new (OVERLAPPED); p->fd[1]->oOverlapWrite = GNUNET_new (OVERLAPPED); p->fd[1]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); p->fd[1]->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); } else { GNUNET_free (p->fd[1]); p->fd[1] = NULL; } } #endif return p; } /** * Closes an interprocess channel * * @param p pipe to close * @param end which end of the pipe to close * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ int GNUNET_DISK_pipe_close_end (struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end) { int ret = GNUNET_OK; if (end == GNUNET_DISK_PIPE_END_READ) { if (p->fd[0]) { ret = GNUNET_DISK_file_close (p->fd[0]); p->fd[0] = NULL; } } else if (end == GNUNET_DISK_PIPE_END_WRITE) { if (p->fd[1]) { ret = GNUNET_DISK_file_close (p->fd[1]); p->fd[1] = NULL; } } return ret; } /** * Detaches one of the ends from the pipe. * Detached end is a fully-functional FileHandle, it will * not be affected by anything you do with the pipe afterwards. * Each end of a pipe can only be detched from it once (i.e. * it is not duplicated). * * @param p pipe to detach an end from * @param end which end of the pipe to detach * @return Detached end on success, NULL on failure * (or if that end is not present or is closed). */ struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_detach_end (struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end) { struct GNUNET_DISK_FileHandle *ret = NULL; if (end == GNUNET_DISK_PIPE_END_READ) { if (p->fd[0]) { ret = p->fd[0]; p->fd[0] = NULL; } } else if (end == GNUNET_DISK_PIPE_END_WRITE) { if (p->fd[1]) { ret = p->fd[1]; p->fd[1] = NULL; } } return ret; } /** * Closes an interprocess channel * * @param p pipe to close * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ int GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p) { int ret = GNUNET_OK; int read_end_close; int write_end_close; int read_end_close_errno; int write_end_close_errno; read_end_close = GNUNET_DISK_pipe_close_end (p, GNUNET_DISK_PIPE_END_READ); read_end_close_errno = errno; write_end_close = GNUNET_DISK_pipe_close_end (p, GNUNET_DISK_PIPE_END_WRITE); write_end_close_errno = errno; GNUNET_free (p); if (GNUNET_OK != read_end_close) { errno = read_end_close_errno; ret = read_end_close; } else if (GNUNET_OK != write_end_close) { errno = write_end_close_errno; ret = write_end_close; } return ret; } /** * Get the handle to a particular pipe end * * @param p pipe * @param n end to access * @return handle for the respective end */ const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle (const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n) { switch (n) { case GNUNET_DISK_PIPE_END_READ: case GNUNET_DISK_PIPE_END_WRITE: return p->fd[n]; default: GNUNET_break (0); return NULL; } } /** * Retrieve OS file handle * @internal * @param fh GNUnet file descriptor * @param dst destination buffer * @param dst_len length of dst * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_internal_file_handle_ (const struct GNUNET_DISK_FileHandle *fh, void *dst, size_t dst_len) { if (NULL == fh) return GNUNET_SYSERR; #ifdef MINGW if (dst_len < sizeof (HANDLE)) return GNUNET_SYSERR; *((HANDLE *) dst) = fh->h; #else if (dst_len < sizeof (int)) return GNUNET_SYSERR; *((int *) dst) = fh->fd; #endif return GNUNET_OK; } /* end of disk.c */ gnunet-0.10.1/src/util/test_crypto_paillier.c0000644000175000017500000001007612274162760016175 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_crypto_paillier.c * @brief testcase paillier crypto * @author Christian Fuchs * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include int test_crypto () { gcry_mpi_t plaintext; gcry_mpi_t plaintext_result; struct GNUNET_CRYPTO_PaillierCiphertext ciphertext; struct GNUNET_CRYPTO_PaillierPublicKey public_key; struct GNUNET_CRYPTO_PaillierPrivateKey private_key; GNUNET_CRYPTO_paillier_create (&public_key, &private_key); GNUNET_assert (NULL != (plaintext = gcry_mpi_new (0))); GNUNET_assert (NULL != (plaintext_result = gcry_mpi_new (0))); gcry_mpi_randomize (plaintext, GNUNET_CRYPTO_PAILLIER_BITS / 2, GCRY_WEAK_RANDOM); GNUNET_CRYPTO_paillier_encrypt (&public_key, plaintext, 0, &ciphertext); GNUNET_CRYPTO_paillier_decrypt (&private_key, &public_key, &ciphertext, plaintext_result); if (0 != gcry_mpi_cmp (plaintext, plaintext_result)) { printf ("paillier failed with plaintext of size %u\n", gcry_mpi_get_nbits (plaintext)); gcry_log_debugmpi("\n", plaintext); gcry_log_debugmpi("\n", plaintext_result); return 1; } return 0; } int test_hom() { int ret; gcry_mpi_t m1; gcry_mpi_t m2; gcry_mpi_t result; gcry_mpi_t hom_result; struct GNUNET_CRYPTO_PaillierCiphertext c1; struct GNUNET_CRYPTO_PaillierCiphertext c2; struct GNUNET_CRYPTO_PaillierCiphertext c_result; struct GNUNET_CRYPTO_PaillierPublicKey public_key; struct GNUNET_CRYPTO_PaillierPrivateKey private_key; GNUNET_CRYPTO_paillier_create (&public_key, &private_key); GNUNET_assert (NULL != (m1 = gcry_mpi_new (0))); GNUNET_assert (NULL != (m2 = gcry_mpi_new (0))); GNUNET_assert (NULL != (result = gcry_mpi_new (0))); GNUNET_assert (NULL != (hom_result = gcry_mpi_new (0))); //gcry_mpi_randomize (m1, GNUNET_CRYPTO_PAILLIER_BITS-2, GCRY_WEAK_RANDOM); m1 = gcry_mpi_set_ui(m1,1); gcry_mpi_mul_2exp(m1,m1,GNUNET_CRYPTO_PAILLIER_BITS-3); //gcry_mpi_randomize (m2, GNUNET_CRYPTO_PAILLIER_BITS-2, GCRY_WEAK_RANDOM); m2 = gcry_mpi_set_ui(m2,1); gcry_mpi_mul_2exp(m2,m2,GNUNET_CRYPTO_PAILLIER_BITS-3); gcry_mpi_add(result,m1,m2); if (1 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key, m1, 2, &c1))){ printf ("GNUNET_CRYPTO_paillier_encrypt 1 failed, should return 1 allowed operation, got %d!\n", ret); return 1; } if (1 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key, m2, 2, &c2))){ printf ("GNUNET_CRYPTO_paillier_encrypt 2 failed, should return 1 allowed operation, got %d!\n", ret); return 1; } if (0 != (ret = GNUNET_CRYPTO_paillier_hom_add (&public_key, &c1,&c2, &c_result))){ printf ("GNUNET_CRYPTO_paillier_hom_add failed, expected 0 remaining operations, got %d!\n", ret); return 1; } GNUNET_CRYPTO_paillier_decrypt (&private_key, &public_key, &c_result, hom_result); gcry_log_debugmpi("\n", hom_result); gcry_log_debugmpi("\n", result); if (0 != gcry_mpi_cmp(result, hom_result)){ printf ("GNUNET_CRYPTO_paillier miscalculated!\n"); return 1; } return 0; } int main (int argc, char *argv[]) { int ret; ret = test_crypto (); if (0 != ret) return ret; ret = test_hom (); return ret; } /* end of test_crypto_paillier.c */ gnunet-0.10.1/src/util/util.conf0000644000175000017500000000450512316522431013405 00000000000000[PATHS] # The PATHS section is special, as filenames including $-expression are # expanded using the values from PATHS or the system environment (PATHS # is checked first). GNUnet also supports expanding $-expressions using # defaults with the syntax "${VAR:-default}". Here, "default" can again # be a $-expression. # # We usually want $HOME for $GNUNET_HOME, but we allow testcases to # easily override this by setting $GNUNET_TEST_HOME. # GNUNET_HOME = ${GNUNET_TEST_HOME:-${HOME:-${USERPROFILE}}} # see XDG Base Directory Specification at # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html # for how these should be used. # Persistant data storage GNUNET_DATA_HOME = ${XDG_DATA_HOME:-$GNUNET_HOME/.local/share}/gnunet/ # Configuration files GNUNET_CONFIG_HOME = ${XDG_CONFIG_HOME:-$GNUNET_HOME/.config}/gnunet/ # Cached data, no big deal if lost GNUNET_CACHE_HOME = ${XDG_CACHE_HOME:-$GNUNET_HOME/.cache}/gnunet/ # Runtime data (i.e UNIX domain sockets, locks, always lost on system boot) # This is the variable for system-wide services; use GNUNET_USER_RUNTIME_DIR # for per-user services (where USER_SERVICE=YES is set) # Note that the 'gnunet'/system user must have $TMPDIR/$TMP set to # exactly the same values as 'normal' users, otherwise this will fail. # If $TMPDIR or $TMP are set to different directories for different # users, this option should be changed to point to the same directory # for all users (i.e. by simply using "/tmp/gnunet-system-runtime/"). GNUNET_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/gnunet-system-runtime/ # Runtime data for per-user services GNUNET_USER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/gnunet-${USERHOME:-${USER:-user}}-runtime/ # Legacy option... # GNUNET_TEST_HOME = ~/.gnunet/ # GNUNET_TEST_HOME = /var/lib/gnunet/ # DEFAULTCONFIG = /etc/gnunet.conf # If 'DEFAULTCONFIG' is not defined, the current # configuration file is assumed to be the default, # which is what we want by default... [PEER] PRIVATE_KEY = $GNUNET_DATA_HOME/private_key.ecc [TESTING] SPEEDUP_INTERVAL = 0 ms SPEEDUP_DELTA = 0 ms # This following option is applicable to LINUX. Enabling this option causes all # UNIX domain sockets to be opened as abstract sockets. Note that the # filesystem level restrictions no longer apply for abstract sockets. An # end-user should not modify this option. USE_ABSTRACT_SOCKETS = NO gnunet-0.10.1/src/util/crypto_paillier.c0000644000175000017500000002212212274162760015131 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/crypto_paillier.c * @brief implementation of the paillier crypto system with libgcrypt * @author Florian Dold * @author Christian Fuchs */ #include "platform.h" #include #include "gnunet_util_lib.h" /** * Create a freshly generated paillier public key. * * @param[out] public_key Where to store the public key? * @param[out] private_key Where to store the private key? */ void GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_key, struct GNUNET_CRYPTO_PaillierPrivateKey *private_key) { gcry_mpi_t p; gcry_mpi_t q; gcry_mpi_t phi; gcry_mpi_t n; GNUNET_assert (NULL != (phi = gcry_mpi_new (0))); GNUNET_assert (NULL != (n = gcry_mpi_new (0))); p = q = NULL; // Generate two distinct primes. // The probability that the loop body // is executed more than once is very low. do { if (NULL != p) gcry_mpi_release (p); if (NULL != q) gcry_mpi_release (q); // generate rsa modulus GNUNET_assert (0 == gcry_prime_generate (&p, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL, GCRY_WEAK_RANDOM, 0)); GNUNET_assert (0 == gcry_prime_generate (&q, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL, GCRY_WEAK_RANDOM, 0)); } while (0 == gcry_mpi_cmp (p, q)); gcry_mpi_mul (n, p, q); GNUNET_CRYPTO_mpi_print_unsigned (public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey), n); // compute phi(n) = (p-1)(q-1) gcry_mpi_sub_ui (p, p, 1); gcry_mpi_sub_ui (q, q, 1); gcry_mpi_mul (phi, p, q); // lambda equals phi(n) in the simplified key generation GNUNET_CRYPTO_mpi_print_unsigned (private_key->lambda, GNUNET_CRYPTO_PAILLIER_BITS / 8, phi); // invert phi and abuse the phi mpi to store the result ... GNUNET_assert (0 != gcry_mpi_invm (phi, phi, n)); GNUNET_CRYPTO_mpi_print_unsigned (private_key->mu, GNUNET_CRYPTO_PAILLIER_BITS / 8, phi); gcry_mpi_release (p); gcry_mpi_release (q); gcry_mpi_release (phi); gcry_mpi_release (n); } /** * Encrypt a plaintext with a paillier public key. * * @param public_key Public key to use. * @param m Plaintext to encrypt. * @param desired_ops How many homomorphic ops the caller intends to use * @param[out] ciphertext Encrytion of @a plaintext with @a public_key. * @return guaranteed number of supported homomorphic operations >= 1, * or desired_ops, in case that is lower, * or -1 if less than one homomorphic operation is possible */ int GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const gcry_mpi_t m, int desired_ops, struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext) { int possible_opts; gcry_mpi_t n_square; gcry_mpi_t r; gcry_mpi_t g; gcry_mpi_t c; gcry_mpi_t n; gcry_mpi_t tmp1; gcry_mpi_t tmp2; // determine how many operations we could allow, if the other number // has the same length. GNUNET_assert (NULL != (tmp1 = gcry_mpi_set_ui (NULL, 1))); GNUNET_assert (NULL != (tmp2 = gcry_mpi_set_ui (NULL, 2))); gcry_mpi_mul_2exp (tmp1, tmp1, GNUNET_CRYPTO_PAILLIER_BITS); // count number of possible operations // this would be nicer with gcry_mpi_get_nbits, however it does not return // the BITLENGTH of the given MPI's value, but the bits required // to represent the number as MPI. for (possible_opts = -2; gcry_mpi_cmp (tmp1, m) > 0; possible_opts++) { gcry_mpi_div (tmp1, NULL, tmp1, tmp2, 0); } gcry_mpi_release (tmp1); gcry_mpi_release (tmp2); if (possible_opts < 1) possible_opts = 0; //soft-cap by caller possible_opts = (desired_ops < possible_opts)? desired_ops : possible_opts; ciphertext->remaining_ops = htonl (possible_opts); GNUNET_assert (0 != (n_square = gcry_mpi_new (0))); GNUNET_assert (0 != (r = gcry_mpi_new (0))); GNUNET_assert (0 != (g = gcry_mpi_new (0))); GNUNET_assert (0 != (c = gcry_mpi_new (0))); GNUNET_CRYPTO_mpi_scan_unsigned (&n, public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey)); gcry_mpi_mul (n_square, n, n); // generate r < n do { gcry_mpi_randomize (r, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM); } while (gcry_mpi_cmp (r, n) >= 0); // c = (n+1)^m mod n^2 gcry_mpi_add_ui (c, n, 1); gcry_mpi_powm (c, c, m, n_square); // r <- r^n mod n^2 gcry_mpi_powm (r, r, n, n_square); // c <- r*c mod n^2 gcry_mpi_mulm (c, r, c, n_square); GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits, sizeof ciphertext->bits, c); gcry_mpi_release (n_square); gcry_mpi_release (r); gcry_mpi_release (c); return possible_opts; } /** * Decrypt a paillier ciphertext with a private key. * * @param private_key Private key to use for decryption. * @param public_key Public key to use for encryption. * @param ciphertext Ciphertext to decrypt. * @param[out] m Decryption of @a ciphertext with @private_key. */ void GNUNET_CRYPTO_paillier_decrypt (const struct GNUNET_CRYPTO_PaillierPrivateKey *private_key, const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext, gcry_mpi_t m) { gcry_mpi_t mu; gcry_mpi_t lambda; gcry_mpi_t n; gcry_mpi_t n_square; gcry_mpi_t c; GNUNET_assert (0 != (n_square = gcry_mpi_new (0))); GNUNET_CRYPTO_mpi_scan_unsigned (&lambda, private_key->lambda, sizeof private_key->lambda); GNUNET_CRYPTO_mpi_scan_unsigned (&mu, private_key->mu, sizeof private_key->mu); GNUNET_CRYPTO_mpi_scan_unsigned (&n, public_key, sizeof *public_key); GNUNET_CRYPTO_mpi_scan_unsigned (&c, ciphertext->bits, sizeof ciphertext->bits); gcry_mpi_mul (n_square, n, n); // m = c^lambda mod n^2 gcry_mpi_powm (m, c, lambda, n_square); // m = m - 1 gcry_mpi_sub_ui (m, m, 1); // m <- m/n gcry_mpi_div (m, NULL, m, n, 0); gcry_mpi_mulm (m, m, mu, n); gcry_mpi_release (mu); gcry_mpi_release (lambda); gcry_mpi_release (n); gcry_mpi_release (n_square); gcry_mpi_release (c); } /** * Compute a ciphertext that represents the sum of the plaintext in @a x1 and @a x2 * * Note that this operation can only be done a finite number of times * before an overflow occurs. * * @param public_key Public key to use for encryption. * @param c1 Paillier cipher text. * @param c2 Paillier cipher text. * @param[out] result Result of the homomorphic operation. * @return #GNUNET_OK if the result could be computed, * #GNUNET_SYSERR if no more homomorphic operations are remaining. */ int GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, const struct GNUNET_CRYPTO_PaillierCiphertext *c1, const struct GNUNET_CRYPTO_PaillierCiphertext *c2, struct GNUNET_CRYPTO_PaillierCiphertext *result) { gcry_mpi_t a; gcry_mpi_t b; gcry_mpi_t c; gcry_mpi_t n_square; int32_t o1; int32_t o2; o1 = ntohl (c1->remaining_ops); o2 = ntohl (c2->remaining_ops); if (0 >= o1 || 0 >= o2) return GNUNET_SYSERR; GNUNET_assert (0 != (c = gcry_mpi_new (0))); GNUNET_CRYPTO_mpi_scan_unsigned (&a, c1->bits, sizeof c1->bits); GNUNET_CRYPTO_mpi_scan_unsigned (&b, c1->bits, sizeof c2->bits); GNUNET_CRYPTO_mpi_scan_unsigned (&n_square, public_key, sizeof *public_key); gcry_mpi_mul (n_square, n_square, n_square); gcry_mpi_mulm (c, a, b, n_square); result->remaining_ops = htonl (((o2 > o1) ? o1 : o2) - 1); GNUNET_CRYPTO_mpi_print_unsigned (result->bits, sizeof result->bits, c); gcry_mpi_release (a); gcry_mpi_release (b); gcry_mpi_release (c); gcry_mpi_release (n_square); return ntohl (result->remaining_ops); } /** * Get the number of remaining supported homomorphic operations. * * @param c Paillier cipher text. * @return the number of remaining homomorphic operations */ int GNUNET_CRYPTO_paillier_hom_get_remaining (const struct GNUNET_CRYPTO_PaillierCiphertext *c) { GNUNET_assert (NULL != c); return ntohl (c->remaining_ops); } /* end of crypto_paillier.c */ gnunet-0.10.1/src/util/test_service.c0000644000175000017500000001632112225777501014434 00000000000000/* This file is part of GNUnet. (C) 2009, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_service.c * @brief tests for service.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 12435 /** * Message type we use for testing. */ #define MY_TYPE 256 static struct GNUNET_SERVICE_Context *sctx; static int ok = 1; static struct GNUNET_CLIENT_Connection *client; static void do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != client) { GNUNET_CLIENT_disconnect (client); client = NULL; } if (NULL != sctx) { GNUNET_SERVICE_stop (sctx); sctx = NULL; } else { GNUNET_SCHEDULER_shutdown (); } } static size_t build_msg (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg = buf; if (size < sizeof (struct GNUNET_MessageHeader)) { /* timeout */ GNUNET_break (0); GNUNET_SCHEDULER_add_now (&do_stop, NULL); ok = 1; return 0; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected, transmitting\n"); GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); msg->type = htons (MY_TYPE); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); return sizeof (struct GNUNET_MessageHeader); } static void ready (void *cls, int result) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_assert (GNUNET_YES == result); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service confirmed running\n"); client = GNUNET_CLIENT_connect ("test_service", cfg); GNUNET_assert (client != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connecting, waiting to transmit\n"); GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_SECONDS, GNUNET_NO, &build_msg, NULL); } static void recv_cb (void *cls, struct GNUNET_SERVER_Client *sc, const struct GNUNET_MessageHeader *message) { GNUNET_assert (NULL != message); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving client message...\n"); GNUNET_SERVER_receive_done (sc, GNUNET_OK); GNUNET_SCHEDULER_add_now (&do_stop, NULL); ok = 0; } static struct GNUNET_SERVER_MessageHandler myhandlers[] = { {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; static void runner (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service initializing\n"); GNUNET_SERVER_add_handlers (server, myhandlers); GNUNET_CLIENT_service_test ("test_service", cfg, GNUNET_TIME_UNIT_SECONDS, &ready, (void *) cfg); } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int check () { ok = 1; char *const argv[] = { "test_service", "-c", "test_service_data.conf", NULL }; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting service\n"); GNUNET_assert (GNUNET_OK == GNUNET_SERVICE_run (3, argv, "test_service", GNUNET_SERVICE_OPTION_NONE, &runner, &ok)); GNUNET_assert (0 == ok); return ok; } static void ready6 (void *cls, int result) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "V6 ready\n"); GNUNET_assert (GNUNET_YES == result); client = GNUNET_CLIENT_connect ("test_service6", cfg); GNUNET_assert (client != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "V6 client connected\n"); GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_SECONDS, GNUNET_NO, &build_msg, NULL); } static void runner6 (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initializing v6 service\n"); GNUNET_SERVER_add_handlers (server, myhandlers); GNUNET_CLIENT_service_test ("test_service6", cfg, GNUNET_TIME_UNIT_SECONDS, &ready6, (void *) cfg); } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int check6 () { char *const argv[] = { "test_service6", "-c", "test_service_data.conf", NULL }; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting v6 service\n"); GNUNET_assert (GNUNET_OK == GNUNET_SERVICE_run (3, argv, "test_service6", GNUNET_SERVICE_OPTION_NONE, &runner6, &ok)); GNUNET_assert (0 == ok); return ok; } static void start_stop_main (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { int *ret = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting service using start method\n"); sctx = GNUNET_SERVICE_start ("test_service", cfg, GNUNET_SERVICE_OPTION_NONE); GNUNET_assert (NULL != sctx); runner (cls, GNUNET_SERVICE_get_server (sctx), cfg); *ret = 0; } static int check_start_stop () { char *const argv[] = { "test-service-program", "-c", "test_service_data.conf", NULL }; const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret = 1; GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run (3, argv, "test-service-program", "no help", options, &start_stop_main, &ret)); GNUNET_break (0 == ret); return ret; } int main (int argc, char *argv[]) { int ret = 0; struct GNUNET_NETWORK_Handle *s = NULL; GNUNET_log_setup ("test-service", "WARNING", NULL); ret += check (); ret += check (); // FIXME #ifndef MINGW s = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); #endif if (NULL == s) { if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) || (errno == EACCES)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); return 1; } FPRINTF (stderr, "IPv6 support seems to not be available (%s), not testing it!\n", strerror (errno)); } else { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s)); ret += check6 (); } ret += check_start_stop (); return ret; } /* end of test_service.c */ gnunet-0.10.1/src/util/test_program.c0000644000175000017500000000647712225777501014456 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_program.c * @brief tests for program.c */ #include "platform.h" #include "gnunet_util_lib.h" static int setme1, setme2; static struct GNUNET_GETOPT_CommandLineOption options1[] = { {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, GNUNET_GETOPT_OPTION_END }; static struct GNUNET_GETOPT_CommandLineOption options2[] = { {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, {'N', "number", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme2}, GNUNET_GETOPT_OPTION_END }; static struct GNUNET_GETOPT_CommandLineOption options3[] = { {'N', "number", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme2}, GNUNET_GETOPT_OPTION_END }; static struct GNUNET_GETOPT_CommandLineOption options4[] = { {'n', "name", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme1}, {'n', "number", NULL, "description", 0, &GNUNET_GETOPT_set_one, &setme2}, GNUNET_GETOPT_OPTION_END }; /** * Main function that will be run. */ static void runner (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { int *ok = cls; GNUNET_assert (setme1 == 1); GNUNET_assert (0 == strcmp (args[0], "extra")); GNUNET_assert (args[1] == NULL); GNUNET_assert (0 == strcmp (cfgfile, "test_program_data.conf")); *ok = 0; } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int check () { int ok = 1; char *const argv[] = { "test_program", "-c", "test_program_data.conf", "-L", "WARNING", "-n", "extra", NULL }; GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run (7, argv, "test_program", "A test", options1, &runner, &ok)); GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run (7, argv, "test_program", "A test", options2, &runner, &ok)); GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run (7, argv, "test_program", "A test", options3, &runner, &ok)); GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run (7, argv, "test_program", "A test", options4, &runner, &ok)); return ok; } int main (int argc, char *argv[]) { int ret = 0; GNUNET_log_setup ("test_program", "WARNING", NULL); ret += check (); return ret; } /* end of test_program.c */ gnunet-0.10.1/src/util/test_os_start_process.c0000644000175000017500000001705512301361473016365 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_os_start_process.c * @brief testcase for os start process code * * This testcase simply calls the os start process code * giving a file descriptor to write stdout to. If the * correct data "HELLO" is read then all is well. */ #include "platform.h" #include "gnunet_util_lib.h" #include "disk.h" static const char *test_phrase = "HELLO WORLD"; static int ok; static struct GNUNET_OS_Process *proc; /** * Pipe to write to started processes stdin (on write end) */ static struct GNUNET_DISK_PipeHandle *hello_pipe_stdin; /** * Pipe to read from started processes stdout (on read end) */ static struct GNUNET_DISK_PipeHandle *hello_pipe_stdout; static GNUNET_SCHEDULER_TaskIdentifier die_task; struct read_context { char buf[16]; int buf_offset; const struct GNUNET_DISK_FileHandle *stdout_read_handle; }; struct read_context rc; static void end_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); } GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc)); GNUNET_OS_process_destroy (proc); proc = NULL; GNUNET_DISK_pipe_close (hello_pipe_stdout); GNUNET_DISK_pipe_close (hello_pipe_stdin); } static void read_call (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int bytes; bytes = GNUNET_DISK_file_read (rc.stdout_read_handle, &rc.buf[rc.buf_offset], \ sizeof (rc.buf) - rc.buf_offset); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "bytes is %d\n", bytes); if (bytes < 1) { GNUNET_break (0); ok = 1; GNUNET_SCHEDULER_cancel (die_task); GNUNET_SCHEDULER_add_now (&end_task, NULL); return; } ok = strncmp (rc.buf, test_phrase, strlen (test_phrase)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "read %s\n", &rc.buf[rc.buf_offset]); rc.buf_offset += bytes; if (0 == ok) { GNUNET_SCHEDULER_cancel (die_task); GNUNET_SCHEDULER_add_now (&end_task, NULL); return; } GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, rc.stdout_read_handle, &read_call, NULL); } static void run_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { char *fn; const struct GNUNET_DISK_FileHandle *stdout_read_handle; const struct GNUNET_DISK_FileHandle *wh; #if !WINDOWS GNUNET_asprintf (&fn, "cat"); #else GNUNET_asprintf (&fn, "w32cat"); #endif hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) { GNUNET_break (0); ok = 1; GNUNET_free (fn); return; } proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, hello_pipe_stdin, hello_pipe_stdout, NULL, fn, "test_gnunet_echo_hello", "-", NULL); GNUNET_free (fn); /* Close the write end of the read pipe */ GNUNET_DISK_pipe_close_end (hello_pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); /* Close the read end of the write pipe */ GNUNET_DISK_pipe_close_end (hello_pipe_stdin, GNUNET_DISK_PIPE_END_READ); wh = GNUNET_DISK_pipe_handle (hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE); /* Write the test_phrase to the cat process */ if (GNUNET_DISK_file_write (wh, test_phrase, strlen (test_phrase) + 1) != strlen (test_phrase) + 1) { GNUNET_break (0); ok = 1; return; } /* Close the write end to end the cycle! */ GNUNET_DISK_pipe_close_end (hello_pipe_stdin, GNUNET_DISK_PIPE_END_WRITE); stdout_read_handle = GNUNET_DISK_pipe_handle (hello_pipe_stdout, GNUNET_DISK_PIPE_END_READ); die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1), &end_task, NULL); memset (&rc, 0, sizeof (rc)); rc.stdout_read_handle = stdout_read_handle; GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdout_read_handle, &read_call, NULL); } /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. */ static int check_run () { ok = 1; GNUNET_SCHEDULER_run (&run_task, &ok); return ok; } /** * Test killing via pipe. */ static int check_kill () { char *fn; hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) { return 1; } fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver"); proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR, hello_pipe_stdin, hello_pipe_stdout, NULL, fn, "gnunet-service-resolver", "-", NULL); sleep (1); /* give process time to start, so we actually use the pipe-kill mechanism! */ GNUNET_free (fn); if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc)); GNUNET_OS_process_destroy (proc); proc = NULL; GNUNET_DISK_pipe_close (hello_pipe_stdout); GNUNET_DISK_pipe_close (hello_pipe_stdin); return 0; } /** * Test killing via pipe. */ static int check_instant_kill () { char *fn; hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) { return 1; } fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver"); proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR, hello_pipe_stdin, hello_pipe_stdout, NULL, fn, "gnunet-service-resolver", "-", NULL); if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); } GNUNET_free (fn); GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc)); GNUNET_OS_process_destroy (proc); proc = NULL; GNUNET_DISK_pipe_close (hello_pipe_stdout); GNUNET_DISK_pipe_close (hello_pipe_stdin); return 0; } int main (int argc, char *argv[]) { int ret; GNUNET_log_setup ("test-os-start-process", "WARNING", NULL); ret = 0; ret |= check_run (); ret |= check_kill (); ret |= check_instant_kill (); return ret; } /* end of test_os_start_process.c */ gnunet-0.10.1/src/util/test_resolver_api_data.conf0000644000175000017500000000015012225230043017134 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunetd-statistics/ [resolver] PORT = 22354 HOSTNAME = localhost gnunet-0.10.1/src/util/test_common_logging.c0000644000175000017500000000636312225777501015777 00000000000000/* This file is part of GNUnet. (C) 2008 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_common_logging.c * @brief testcase for the logging module * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" static void my_log (void *ctx, enum GNUNET_ErrorType kind, const char *component, const char *date, const char *msg) { unsigned int *c = ctx; (*c)++; } int main (int argc, char *argv[]) { unsigned int failureCount = 0; unsigned int logs = 0; if (0 != putenv ("GNUNET_FORCE_LOG=")) FPRINTF (stderr, "Failed to putenv: %s\n", strerror (errno)); GNUNET_log_setup ("test-common-logging", "DEBUG", "/dev/null"); GNUNET_logger_add (&my_log, &logs); GNUNET_logger_add (&my_log, &logs); GNUNET_log (GNUNET_ERROR_TYPE_BULK, "Testing...\n"); GNUNET_log (GNUNET_ERROR_TYPE_BULK, "Testing...\n"); GNUNET_log (GNUNET_ERROR_TYPE_BULK, "Testing...\n"); GNUNET_log (GNUNET_ERROR_TYPE_BULK, "Testing...\n"); GNUNET_log (GNUNET_ERROR_TYPE_BULK, "Testing...\n"); GNUNET_log (GNUNET_ERROR_TYPE_BULK, "Testing...\n"); GNUNET_logger_remove (&my_log, &logs); GNUNET_log (GNUNET_ERROR_TYPE_BULK, "Flusher...\n"); /* the last 6 calls should be merged (repated bulk messages!) */ GNUNET_logger_remove (&my_log, &logs); if (logs != 4) { FPRINTF (stdout, "Expected 4 log calls, got %u\n", logs); failureCount++; } GNUNET_break (0 == strcmp (_("ERROR"), GNUNET_error_type_to_string (GNUNET_ERROR_TYPE_ERROR))); GNUNET_break (0 == strcmp (_("WARNING"), GNUNET_error_type_to_string (GNUNET_ERROR_TYPE_WARNING))); GNUNET_break (0 == strcmp (_("INFO"), GNUNET_error_type_to_string (GNUNET_ERROR_TYPE_INFO))); GNUNET_break (0 == strcmp (_("DEBUG"), GNUNET_error_type_to_string (GNUNET_ERROR_TYPE_DEBUG))); GNUNET_log_setup ("test_common_logging", "WARNING", "/dev/null"); logs = 0; GNUNET_logger_add (&my_log, &logs); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Checker...\n"); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Drop me...\n"); GNUNET_logger_remove (&my_log, &logs); if (logs != 1) { FPRINTF (stdout, "Expected 1 log call, got %u\n", logs); failureCount++; } if (failureCount != 0) { FPRINTF (stdout, "%u TESTS FAILED!\n", failureCount); return -1; } return 0; } /* end of main */ /* end of test_common_logging.c */ gnunet-0.10.1/src/util/mq.c0000644000175000017500000004711412251551532012347 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Florian Dold * @file util/mq.c * @brief general purpose request queue */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "mq",__VA_ARGS__) struct GNUNET_MQ_Envelope { /** * Messages are stored in a linked list. * Each queue has its own list of envelopes. */ struct GNUNET_MQ_Envelope *next; /** * Messages are stored in a linked list * Each queue has its own list of envelopes. */ struct GNUNET_MQ_Envelope *prev; /** * Actual allocated message header, * usually points to the end of the containing GNUNET_MQ_Envelope */ struct GNUNET_MessageHeader *mh; /** * Queue the message is queued in, NULL if message is not queued. */ struct GNUNET_MQ_Handle *parent_queue; /** * Called after the message was sent irrevocably. */ GNUNET_MQ_NotifyCallback sent_cb; /** * Closure for send_cb */ void *sent_cls; }; /** * Handle to a message queue. */ struct GNUNET_MQ_Handle { /** * Handlers array, or NULL if the queue should not receive messages */ const struct GNUNET_MQ_MessageHandler *handlers; /** * Closure for the handler callbacks, * as well as for the error handler. */ void *handlers_cls; /** * Actual implementation of message sending, * called when a message is added */ GNUNET_MQ_SendImpl send_impl; /** * Implementation-dependent queue destruction function */ GNUNET_MQ_DestroyImpl destroy_impl; /** * Implementation-specific state */ void *impl_state; /** * Callback will be called when an error occurs. */ GNUNET_MQ_ErrorHandler error_handler; /** * Linked list of messages pending to be sent */ struct GNUNET_MQ_Envelope *envelope_head; /** * Linked list of messages pending to be sent */ struct GNUNET_MQ_Envelope *envelope_tail; /** * Message that is currently scheduled to be * sent. Not the head of the message queue, as the implementation * needs to know if sending has been already scheduled or not. */ struct GNUNET_MQ_Envelope *current_envelope; /** * Map of associations, lazily allocated */ struct GNUNET_CONTAINER_MultiHashMap32 *assoc_map; /** * Task scheduled during #GNUNET_MQ_impl_send_continue. */ GNUNET_SCHEDULER_TaskIdentifier continue_task; /** * Next id that should be used for the assoc_map, * initialized lazily to a random value together with * assoc_map */ uint32_t assoc_id; }; struct ServerClientSocketState { struct GNUNET_SERVER_Client *client; struct GNUNET_SERVER_TransmitHandle* th; }; struct ClientConnectionState { /** * Did we call receive alread alreadyy? */ int receive_active; /** * Do we also want to receive? */ int receive_requested; struct GNUNET_CLIENT_Connection *connection; struct GNUNET_CLIENT_TransmitHandle *th; }; /** * Call the message message handler that was registered * for the type of the given message in the given message queue. * * This function is indended to be used for the implementation * of message queues. * * @param mq message queue with the handlers * @param mh message to dispatch */ void GNUNET_MQ_inject_message (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *mh) { const struct GNUNET_MQ_MessageHandler *handler; int handled = GNUNET_NO; handler = mq->handlers; if (NULL == handler) return; for (; NULL != handler->cb; handler++) { if (handler->type == ntohs (mh->type)) { handler->cb (mq->handlers_cls, mh); handled = GNUNET_YES; } } if (GNUNET_NO == handled) LOG (GNUNET_ERROR_TYPE_WARNING, "no handler for message of type %d\n", ntohs (mh->type)); } /** * Call the error handler of a message queue with the given * error code. If there is no error handler, log a warning. * * This function is intended to be used by the implementation * of message queues. * * @param mq message queue * @param error the error type */ void GNUNET_MQ_inject_error (struct GNUNET_MQ_Handle *mq, enum GNUNET_MQ_Error error) { if (NULL == mq->error_handler) { /* FIXME: log what kind of error occured */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "mq: got error, but no handler installed\n"); return; } mq->error_handler (mq->handlers_cls, error); } void GNUNET_MQ_discard (struct GNUNET_MQ_Envelope *mqm) { GNUNET_assert (NULL == mqm->parent_queue); GNUNET_free (mqm); } /** * Send a message with the give message queue. * May only be called once per message. * * @param mq message queue * @param ev the envelope with the message to send. */ void GNUNET_MQ_send (struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev) { GNUNET_assert (NULL != mq); GNUNET_assert (NULL == ev->parent_queue); /* is the implementation busy? queue it! */ if (NULL != mq->current_envelope) { GNUNET_CONTAINER_DLL_insert_tail (mq->envelope_head, mq->envelope_tail, ev); return; } mq->current_envelope = ev; mq->send_impl (mq, ev->mh, mq->impl_state); } /** * Task run to call the send implementation for the next queued * message, if any. Only useful for implementing message queues, * results in undefined behavior if not used carefully. * * @param cls message queue to send the next message with * @param tc scheduler context */ static void impl_send_continue (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_MQ_Handle *mq = cls; struct GNUNET_MQ_Envelope *current_envelope; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; mq->continue_task = GNUNET_SCHEDULER_NO_TASK; /* call is only valid if we're actually currently sending * a message */ current_envelope = mq->current_envelope; GNUNET_assert (NULL != current_envelope); if (NULL == mq->envelope_head) { mq->current_envelope = NULL; } else { mq->current_envelope = mq->envelope_head; GNUNET_CONTAINER_DLL_remove (mq->envelope_head, mq->envelope_tail, mq->current_envelope); mq->send_impl (mq, mq->current_envelope->mh, mq->impl_state); } if (NULL != current_envelope->sent_cb) current_envelope->sent_cb (current_envelope->sent_cls); GNUNET_free (current_envelope); } /** * Call the send implementation for the next queued message, * if any. * Only useful for implementing message queues, * results in undefined behavior if not used carefully. * * @param mq message queue to send the next message with */ void GNUNET_MQ_impl_send_continue (struct GNUNET_MQ_Handle *mq) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == mq->continue_task); mq->continue_task = GNUNET_SCHEDULER_add_now (&impl_send_continue, mq); } /** * Create a message queue for the specified handlers. * * @param send function the implements sending messages * @param destroy function that implements destroying the queue * @param cancel function that implements canceling a message * @param impl_state for the queue, passed to 'send' and 'destroy' * @param handlers array of message handlers * @param error_handler handler for read and write errors * @param cls closure for message handlers and error handler * @return a new message queue */ struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks (GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls) { struct GNUNET_MQ_Handle *mq; mq = GNUNET_new (struct GNUNET_MQ_Handle); mq->send_impl = send; mq->destroy_impl = destroy; mq->handlers = handlers; mq->handlers_cls = cls; mq->impl_state = impl_state; return mq; } /** * Get the message that should currently be sent. * Fails if there is no current message. * Only useful for implementing message queues, * results in undefined behavior if not used carefully. * * @param mq message queue with the current message * @return message to send, never NULL */ const struct GNUNET_MessageHeader * GNUNET_MQ_impl_current (struct GNUNET_MQ_Handle *mq) { if (NULL == mq->current_envelope) GNUNET_abort (); if (NULL == mq->current_envelope->mh) GNUNET_abort (); return mq->current_envelope->mh; } /** * Get the implementation state associated with the * message queue. * * While the GNUNET_MQ_Impl* callbacks receive the * implementation state, continuations that are scheduled * by the implementation function often only have one closure * argument, with this function it is possible to get at the * implementation state when only passing the GNUNET_MQ_Handle * as closure. * * @param mq message queue with the current message * @return message to send, never NULL */ void * GNUNET_MQ_impl_state (struct GNUNET_MQ_Handle *mq) { return mq->impl_state; } struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_ (struct GNUNET_MessageHeader **mhp, uint16_t size, uint16_t type) { struct GNUNET_MQ_Envelope *mqm; mqm = GNUNET_malloc (sizeof *mqm + size); mqm->mh = (struct GNUNET_MessageHeader *) &mqm[1]; mqm->mh->size = htons (size); mqm->mh->type = htons (type); if (NULL != mhp) *mhp = mqm->mh; return mqm; } /** * Implementation of the GNUNET_MQ_msg_nested_mh macro. * * @param mhp pointer to the message header pointer that will be changed to allocate at * the newly allocated space for the message. * @param base_size size of the data before the nested message * @param type type of the message in the envelope * @param nested_mh the message to append to the message after base_size */ struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_nested_mh_ (struct GNUNET_MessageHeader **mhp, uint16_t base_size, uint16_t type, const struct GNUNET_MessageHeader *nested_mh) { struct GNUNET_MQ_Envelope *mqm; uint16_t size; if (NULL == nested_mh) return GNUNET_MQ_msg_ (mhp, base_size, type); size = base_size + ntohs (nested_mh->size); /* check for uint16_t overflow */ if (size < base_size) return NULL; mqm = GNUNET_MQ_msg_ (mhp, size, type); memcpy ((char *) mqm->mh + base_size, nested_mh, ntohs (nested_mh->size)); return mqm; } /** * Transmit a queued message to the session's client. * * @param cls consensus session * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_queued (void *cls, size_t size, void *buf) { struct GNUNET_MQ_Handle *mq = cls; struct ServerClientSocketState *state = GNUNET_MQ_impl_state (mq); const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq); size_t msg_size; GNUNET_assert (NULL != buf); msg_size = ntohs (msg->size); GNUNET_assert (size >= msg_size); memcpy (buf, msg, msg_size); state->th = NULL; GNUNET_MQ_impl_send_continue (mq); return msg_size; } static void server_client_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) { struct ServerClientSocketState *state = impl_state; if (NULL != state->th) { GNUNET_SERVER_notify_transmit_ready_cancel (state->th); state->th = NULL; } GNUNET_assert (NULL != mq); GNUNET_assert (NULL != state); GNUNET_SERVER_client_drop (state->client); GNUNET_free (state); } static void server_client_send_impl (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state) { struct ServerClientSocketState *state = impl_state; GNUNET_assert (NULL != mq); GNUNET_assert (NULL != state); state->th = GNUNET_SERVER_notify_transmit_ready (state->client, ntohs (msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_queued, mq); } struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_server_client (struct GNUNET_SERVER_Client *client) { struct GNUNET_MQ_Handle *mq; struct ServerClientSocketState *scss; mq = GNUNET_new (struct GNUNET_MQ_Handle); scss = GNUNET_new (struct ServerClientSocketState); mq->impl_state = scss; scss->client = client; GNUNET_SERVER_client_keep (client); mq->send_impl = server_client_send_impl; mq->destroy_impl = server_client_destroy_impl; return mq; } /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void handle_client_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_MQ_Handle *mq = cls; struct ClientConnectionState *state; state = mq->impl_state; if (NULL == msg) { GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_READ); return; } GNUNET_CLIENT_receive (state->connection, handle_client_message, mq, GNUNET_TIME_UNIT_FOREVER_REL); GNUNET_MQ_inject_message (mq, msg); } /** * Transmit a queued message to the session's client. * * @param cls consensus session * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t connection_client_transmit_queued (void *cls, size_t size, void *buf) { struct GNUNET_MQ_Handle *mq = cls; const struct GNUNET_MessageHeader *msg; struct ClientConnectionState *state = mq->impl_state; size_t msg_size; GNUNET_assert (NULL != mq); msg = GNUNET_MQ_impl_current (mq); if (NULL == buf) { GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_READ); return 0; } if ( (GNUNET_YES == state->receive_requested) && (GNUNET_NO == state->receive_active) ) { state->receive_active = GNUNET_YES; GNUNET_CLIENT_receive (state->connection, handle_client_message, mq, GNUNET_TIME_UNIT_FOREVER_REL); } msg_size = ntohs (msg->size); GNUNET_assert (size >= msg_size); memcpy (buf, msg, msg_size); state->th = NULL; GNUNET_MQ_impl_send_continue (mq); return msg_size; } static void connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) { GNUNET_free (impl_state); } static void connection_client_send_impl (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state) { struct ClientConnectionState *state = impl_state; GNUNET_assert (NULL != state); GNUNET_assert (NULL == state->th); state->th = GNUNET_CLIENT_notify_transmit_ready (state->connection, ntohs (msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &connection_client_transmit_queued, mq); GNUNET_assert (NULL != state->th); } struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_connection_client (struct GNUNET_CLIENT_Connection *connection, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls) { struct GNUNET_MQ_Handle *mq; struct ClientConnectionState *state; GNUNET_assert (NULL != connection); mq = GNUNET_new (struct GNUNET_MQ_Handle); mq->handlers = handlers; mq->error_handler = error_handler; mq->handlers_cls = cls; state = GNUNET_new (struct ClientConnectionState); state->connection = connection; mq->impl_state = state; mq->send_impl = connection_client_send_impl; mq->destroy_impl = connection_client_destroy_impl; if (NULL != handlers) state->receive_requested = GNUNET_YES; return mq; } void GNUNET_MQ_replace_handlers (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MQ_MessageHandler *new_handlers, void *cls) { /* FIXME: notify implementation? */ /* FIXME: what about NULL handlers? abort receive? */ mq->handlers = new_handlers; mq->handlers_cls = cls; } /** * Associate the assoc_data in mq with a unique request id. * * @param mq message queue, id will be unique for the queue * @param assoc_data to associate */ uint32_t GNUNET_MQ_assoc_add (struct GNUNET_MQ_Handle *mq, void *assoc_data) { uint32_t id; if (NULL == mq->assoc_map) { mq->assoc_map = GNUNET_CONTAINER_multihashmap32_create (8); mq->assoc_id = 1; } id = mq->assoc_id++; GNUNET_CONTAINER_multihashmap32_put (mq->assoc_map, id, assoc_data, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); return id; } void * GNUNET_MQ_assoc_get (struct GNUNET_MQ_Handle *mq, uint32_t request_id) { if (NULL == mq->assoc_map) return NULL; return GNUNET_CONTAINER_multihashmap32_get (mq->assoc_map, request_id); } void * GNUNET_MQ_assoc_remove (struct GNUNET_MQ_Handle *mq, uint32_t request_id) { void *val; if (NULL == mq->assoc_map) return NULL; val = GNUNET_CONTAINER_multihashmap32_get (mq->assoc_map, request_id); GNUNET_CONTAINER_multihashmap32_remove_all (mq->assoc_map, request_id); return val; } void GNUNET_MQ_notify_sent (struct GNUNET_MQ_Envelope *mqm, GNUNET_MQ_NotifyCallback cb, void *cls) { mqm->sent_cb = cb; mqm->sent_cls = cls; } void GNUNET_MQ_destroy (struct GNUNET_MQ_Handle *mq) { if (NULL != mq->destroy_impl) { mq->destroy_impl (mq, mq->impl_state); } if (GNUNET_SCHEDULER_NO_TASK != mq->continue_task) { GNUNET_SCHEDULER_cancel (mq->continue_task); mq->continue_task = GNUNET_SCHEDULER_NO_TASK; } while (NULL != mq->envelope_head) { struct GNUNET_MQ_Envelope *ev; ev = mq->envelope_head; GNUNET_CONTAINER_DLL_remove (mq->envelope_head, mq->envelope_tail, ev); GNUNET_MQ_discard (ev); } if (NULL != mq->current_envelope) { GNUNET_MQ_discard (mq->current_envelope); mq->current_envelope = NULL; } if (NULL != mq->assoc_map) { GNUNET_CONTAINER_multihashmap32_destroy (mq->assoc_map); mq->assoc_map = NULL; } GNUNET_free (mq); } struct GNUNET_MessageHeader * GNUNET_MQ_extract_nested_mh_ (const struct GNUNET_MessageHeader *mh, uint16_t base_size) { uint16_t whole_size; uint16_t nested_size; struct GNUNET_MessageHeader *nested_msg; whole_size = ntohs (mh->size); GNUNET_assert (whole_size >= base_size); nested_size = whole_size - base_size; if (0 == nested_size) return NULL; if (nested_size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return NULL; } nested_msg = (struct GNUNET_MessageHeader *) ((char *) mh + base_size); if (ntohs (nested_msg->size) != nested_size) { GNUNET_break_op (0); nested_msg->size = htons (nested_size); } return nested_msg; } gnunet-0.10.1/src/util/resolver_api.c0000644000175000017500000006217412261236531014427 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/resolver_api.c * @brief resolver for writing a tool * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_resolver_service.h" #include "resolver.h" #define LOG(kind,...) GNUNET_log_from (kind, "resolver-api", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "resolver-api", syscall) /** * Maximum supported length for a hostname */ #define MAX_HOSTNAME 1024 /** * Possible hostnames for "loopback". */ static const char *loopback[] = { "localhost", "ip6-localnet", NULL }; /** * Configuration. */ static const struct GNUNET_CONFIGURATION_Handle *resolver_cfg; /** * Our connection to the resolver service, created on-demand, but then * persists until error or shutdown. */ static struct GNUNET_CLIENT_Connection *client; /** * Head of DLL of requests. */ static struct GNUNET_RESOLVER_RequestHandle *req_head; /** * Tail of DLL of requests. */ static struct GNUNET_RESOLVER_RequestHandle *req_tail; /** * How long should we wait to reconnect? */ static struct GNUNET_TIME_Relative backoff; /** * Task for reconnecting. */ static GNUNET_SCHEDULER_TaskIdentifier r_task; /** * Task ID of shutdown task; only present while we have a * connection to the resolver service. */ static GNUNET_SCHEDULER_TaskIdentifier s_task; /** * Handle to a request given to the resolver. Can be used to cancel * the request prior to the timeout or successful execution. Also * used to track our internal state for the request. */ struct GNUNET_RESOLVER_RequestHandle { /** * Next entry in DLL of requests. */ struct GNUNET_RESOLVER_RequestHandle *next; /** * Previous entry in DLL of requests. */ struct GNUNET_RESOLVER_RequestHandle *prev; /** * Callback if this is an name resolution request, * otherwise NULL. */ GNUNET_RESOLVER_AddressCallback addr_callback; /** * Callback if this is a reverse lookup request, * otherwise NULL. */ GNUNET_RESOLVER_HostnameCallback name_callback; /** * Closure for the respective "callback". */ void *cls; /** * When should this request time out? */ struct GNUNET_TIME_Absolute timeout; /** * Task handle for numeric lookups. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Desired address family. */ int af; /** * Has this request been transmitted to the service? * #GNUNET_YES if transmitted * #GNUNET_YES if not transmitted * #GNUNET_SYSERR when request was canceled */ int was_transmitted; /** * Did we add this request to the queue? */ int was_queued; /** * Desired direction (IP to name or name to IP) */ int direction; /** * #GNUNET_YES if a response was received */ int received_response; /** * Length of the data that follows this struct. */ size_t data_len; }; /** * Check that the resolver service runs on localhost * (or equivalent). */ static void check_config () { char *hostname; unsigned int i; struct sockaddr_in v4; struct sockaddr_in6 v6; memset (&v4, 0, sizeof (v4)); v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK); v4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif memset (&v6, 0, sizeof (v6)); v6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (v6); #endif if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (resolver_cfg, "resolver", "HOSTNAME", &hostname)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Must specify `%s' for `%s' in configuration!\n"), "HOSTNAME", "resolver"); GNUNET_assert (0); } if ((1 != inet_pton (AF_INET, hostname, &v4)) || (1 != inet_pton (AF_INET6, hostname, &v6))) { GNUNET_free (hostname); return; } i = 0; while (NULL != loopback[i]) if (0 == strcasecmp (loopback[i++], hostname)) { GNUNET_free (hostname); return; } LOG (GNUNET_ERROR_TYPE_ERROR, _("Must specify `%s' or numeric IP address for `%s' of `%s' in configuration!\n"), "localhost", "HOSTNAME", "resolver"); GNUNET_free (hostname); GNUNET_assert (0); } /** * Create the connection to the resolver service. * * @param cfg configuration to use */ void GNUNET_RESOLVER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_assert (NULL != cfg); backoff = GNUNET_TIME_UNIT_MILLISECONDS; resolver_cfg = cfg; check_config (); } /** * Destroy the connection to the resolver service. */ void GNUNET_RESOLVER_disconnect () { GNUNET_assert (NULL == req_head); GNUNET_assert (NULL == req_tail); if (NULL != client) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from DNS service\n"); GNUNET_CLIENT_disconnect (client); client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != r_task) { GNUNET_SCHEDULER_cancel (r_task); r_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != s_task) { GNUNET_SCHEDULER_cancel (s_task); s_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Convert IP address to string without DNS resolution. * * @param af address family * @param ip the address * @param ip_len number of bytes in ip * @return address as a string, NULL on error */ static char * no_resolve (int af, const void *ip, socklen_t ip_len) { char buf[INET6_ADDRSTRLEN]; switch (af) { case AF_INET: if (ip_len != sizeof (struct in_addr)) return NULL; if (NULL == inet_ntop (AF_INET, ip, buf, sizeof (buf))) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_ntop"); return NULL; } break; case AF_INET6: if (ip_len != sizeof (struct in6_addr)) return NULL; if (NULL == inet_ntop (AF_INET6, ip, buf, sizeof (buf))) { LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "inet_ntop"); return NULL; } break; default: GNUNET_break (0); return NULL; } return GNUNET_strdup (buf); } /** * Adjust exponential back-off and reconnect to the service. */ static void reconnect (); /** * Process pending requests to the resolver. */ static void process_requests (); /** * Process response with a hostname for a DNS lookup. * * @param cls our `struct GNUNET_RESOLVER_RequestHandle` context * @param msg message with the hostname, NULL on error */ static void handle_response (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_RESOLVER_RequestHandle *rh = cls; uint16_t size; char *nret; LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving response from DNS service\n"); if (NULL == msg) { char buf[INET6_ADDRSTRLEN]; if (NULL != rh->name_callback) LOG (GNUNET_ERROR_TYPE_INFO, _("Timeout trying to resolve IP address `%s'.\n"), inet_ntop (rh->af, (const void *) &rh[1], buf, sizeof(buf))); else LOG (GNUNET_ERROR_TYPE_INFO, _("Timeout trying to resolve hostname `%s'.\n"), (const char *) &rh[1]); /* check if request was canceled */ if (GNUNET_SYSERR != rh->was_transmitted) { if (NULL != rh->name_callback) { /* no reverse lookup was successful, return ip as string */ if (rh->received_response == GNUNET_NO) { nret = no_resolve (rh->af, &rh[1], rh->data_len); rh->name_callback (rh->cls, nret); GNUNET_free (nret); rh->name_callback (rh->cls, NULL); } /* at least one reverse lookup was successful */ else rh->name_callback (rh->cls, NULL); } if (NULL != rh->addr_callback) rh->addr_callback (rh->cls, NULL, 0); } GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh); GNUNET_free (rh); GNUNET_CLIENT_disconnect (client); client = NULL; reconnect (); return; } if (GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE != ntohs (msg->type)) { GNUNET_break (0); GNUNET_CLIENT_disconnect (client); client = NULL; reconnect (); return; } size = ntohs (msg->size); /* message contains not data, just header */ if (size == sizeof (struct GNUNET_MessageHeader)) { /* check if request was canceled */ if (GNUNET_SYSERR != rh->was_transmitted) { if (NULL != rh->name_callback) rh->name_callback (rh->cls, NULL); if (NULL != rh->addr_callback) rh->addr_callback (rh->cls, NULL, 0); } GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh); GNUNET_free (rh); process_requests (); return; } /* return reverse lookup results to caller */ if (NULL != rh->name_callback) { const char *hostname; hostname = (const char *) &msg[1]; if (hostname[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0') { GNUNET_break (0); if (rh->was_transmitted != GNUNET_SYSERR) rh->name_callback (rh->cls, NULL); GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh); GNUNET_free (rh); GNUNET_CLIENT_disconnect (client); client = NULL; reconnect (); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Resolver returns `%s' for IP `%s'.\n", hostname, GNUNET_a2s ((const void *) &rh[1], rh->data_len)); if (rh->was_transmitted != GNUNET_SYSERR) rh->name_callback (rh->cls, hostname); rh->received_response = GNUNET_YES; GNUNET_CLIENT_receive (client, &handle_response, rh, GNUNET_TIME_absolute_get_remaining (rh->timeout)); } /* return lookup results to caller */ if (NULL != rh->addr_callback) { struct sockaddr_in v4; struct sockaddr_in6 v6; const struct sockaddr *sa; socklen_t salen; const void *ip; size_t ip_len; ip = &msg[1]; ip_len = size - sizeof (struct GNUNET_MessageHeader); if (ip_len == sizeof (struct in_addr)) { memset (&v4, 0, sizeof (v4)); v4.sin_family = AF_INET; v4.sin_addr = *(struct in_addr*) ip; #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif salen = sizeof (v4); sa = (const struct sockaddr *) &v4; } else if (ip_len == sizeof (struct in6_addr)) { memset (&v6, 0, sizeof (v6)); v6.sin6_family = AF_INET6; v6.sin6_addr = *(struct in6_addr*) ip; #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (v6); #endif salen = sizeof (v6); sa = (const struct sockaddr *) &v6; } else { GNUNET_break (0); if (rh->was_transmitted != GNUNET_SYSERR) rh->addr_callback (rh->cls, NULL, 0); GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh); GNUNET_free (rh); GNUNET_CLIENT_disconnect (client); client = NULL; reconnect (); return; } rh->addr_callback (rh->cls, sa, salen); GNUNET_CLIENT_receive (client, &handle_response, rh, GNUNET_TIME_absolute_get_remaining (rh->timeout)); } } /** * We've been asked to lookup the address for a hostname and were * given a valid numeric string. Perform the callbacks for the * numeric addresses. * * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request * @param tc unused scheduler context */ static void numeric_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_RESOLVER_RequestHandle *rh = cls; struct sockaddr_in v4; struct sockaddr_in6 v6; const char *hostname; memset (&v4, 0, sizeof (v4)); v4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif memset (&v6, 0, sizeof (v6)); v6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (v6); #endif hostname = (const char *) &rh[1]; if (((rh->af == AF_UNSPEC) || (rh->af == AF_INET)) && (1 == inet_pton (AF_INET, hostname, &v4.sin_addr))) { rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); if ((rh->af == AF_UNSPEC) && (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr))) { /* this can happen on some systems IF "hostname" is "localhost" */ rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); } rh->addr_callback (rh->cls, NULL, 0); GNUNET_free (rh); return; } if (((rh->af == AF_UNSPEC) || (rh->af == AF_INET6)) && (1 == inet_pton (AF_INET6, hostname, &v6.sin6_addr))) { rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); rh->addr_callback (rh->cls, NULL, 0); GNUNET_free (rh); return; } /* why are we here? this task should not have been scheduled! */ GNUNET_assert (0); GNUNET_free (rh); } /** * We've been asked to lookup the address for a hostname and were * given a variant of "loopback". Perform the callbacks for the * respective loopback numeric addresses. * * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request * @param tc unused scheduler context */ static void loopback_resolution (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_RESOLVER_RequestHandle *rh = cls; struct sockaddr_in v4; struct sockaddr_in6 v6; memset (&v4, 0, sizeof (v4)); v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK); v4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif memset (&v6, 0, sizeof (v6)); v6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (v6); #endif v6.sin6_addr = in6addr_loopback; switch (rh->af) { case AF_INET: rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); break; case AF_INET6: rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); break; case AF_UNSPEC: rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6)); rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4)); break; default: GNUNET_break (0); break; } rh->addr_callback (rh->cls, NULL, 0); GNUNET_free (rh); } /** * Task executed on system shutdown. */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { s_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_RESOLVER_disconnect (); backoff = GNUNET_TIME_UNIT_MILLISECONDS; } /** * Process pending requests to the resolver. */ static void process_requests () { struct GNUNET_RESOLVER_GetMessage *msg; char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; struct GNUNET_RESOLVER_RequestHandle *rh; if (NULL == client) { reconnect (); return; } rh = req_head; if (NULL == rh) { /* nothing to do, release socket really soon if there is nothing * else happening... */ s_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &shutdown_task, NULL); return; } if (GNUNET_YES == rh->was_transmitted) return; /* waiting for reply */ msg = (struct GNUNET_RESOLVER_GetMessage *) buf; msg->header.size = htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + rh->data_len); msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST); msg->direction = htonl (rh->direction); msg->af = htonl (rh->af); memcpy (&msg[1], &rh[1], rh->data_len); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting DNS resolution request to DNS service\n"); if (GNUNET_OK != GNUNET_CLIENT_transmit_and_get_response (client, &msg->header, GNUNET_TIME_absolute_get_remaining (rh->timeout), GNUNET_YES, &handle_response, rh)) { GNUNET_CLIENT_disconnect (client); client = NULL; GNUNET_break (0); reconnect (); return; } rh->was_transmitted = GNUNET_YES; } /** * Now try to reconnect to the resolver service. * * @param cls NULL * @param tc scheduler context */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { r_task = GNUNET_SCHEDULER_NO_TASK; if (NULL == req_head) return; /* no work pending */ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to connect to DNS service\n"); client = GNUNET_CLIENT_connect ("resolver", resolver_cfg); if (NULL == client) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect, will try again later\n"); reconnect (); return; } process_requests (); } /** * Adjust exponential back-off and reconnect to the service. */ static void reconnect () { struct GNUNET_RESOLVER_RequestHandle *rh; if (GNUNET_SCHEDULER_NO_TASK != r_task) return; GNUNET_assert (NULL == client); if (NULL != (rh = req_head)) { switch (rh->was_transmitted) { case GNUNET_NO: /* nothing more to do */ break; case GNUNET_YES: /* disconnected, transmit again! */ rh->was_transmitted = GNUNET_NO; break; case GNUNET_SYSERR: /* request was cancelled, remove entirely */ GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh); GNUNET_free (rh); break; default: GNUNET_assert (0); break; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Will try to connect to DNS service in %s\n", GNUNET_STRINGS_relative_time_to_string (backoff, GNUNET_YES)); GNUNET_assert (NULL != resolver_cfg); r_task = GNUNET_SCHEDULER_add_delayed (backoff, &reconnect_task, NULL); backoff = GNUNET_TIME_STD_BACKOFF (backoff); } /** * Convert a string to one or more IP addresses. * * @param hostname the hostname to resolve * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" * @param callback function to call with addresses * @param callback_cls closure for @a callback * @param timeout how long to try resolving * @return handle that can be used to cancel the request, NULL on error */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get (const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls) { struct GNUNET_RESOLVER_RequestHandle *rh; size_t slen; unsigned int i; struct in_addr v4; struct in6_addr v6; slen = strlen (hostname) + 1; if (slen + sizeof (struct GNUNET_RESOLVER_GetMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + slen); rh->af = af; rh->addr_callback = callback; rh->cls = callback_cls; memcpy (&rh[1], hostname, slen); rh->data_len = slen; rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); rh->direction = GNUNET_NO; /* first, check if this is a numeric address */ if (((1 == inet_pton (AF_INET, hostname, &v4)) && ((af == AF_INET) || (af == AF_UNSPEC))) || ((1 == inet_pton (AF_INET6, hostname, &v6)) && ((af == AF_INET6) || (af == AF_UNSPEC)))) { rh->task = GNUNET_SCHEDULER_add_now (&numeric_resolution, rh); return rh; } /* then, check if this is a loopback address */ i = 0; while (NULL != loopback[i]) if (0 == strcasecmp (loopback[i++], hostname)) { rh->task = GNUNET_SCHEDULER_add_now (&loopback_resolution, rh); return rh; } GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh); rh->was_queued = GNUNET_YES; if (s_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (s_task); s_task = GNUNET_SCHEDULER_NO_TASK; } process_requests (); return rh; } /** * We've been asked to convert an address to a string without * a reverse lookup. Do it. * * @param cls `struct GNUNET_RESOLVER_RequestHandle` for the request * @param tc unused scheduler context */ static void numeric_reverse (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_RESOLVER_RequestHandle *rh = cls; char *result; result = no_resolve (rh->af, &rh[1], rh->data_len); LOG (GNUNET_ERROR_TYPE_DEBUG, "Resolver returns `%s'.\n", result); if (NULL != result) { rh->name_callback (rh->cls, result); GNUNET_free (result); } rh->name_callback (rh->cls, NULL); GNUNET_free (rh); } /** * Get an IP address as a string. * * @param sa host address * @param salen length of host address in @a sa * @param do_resolve use #GNUNET_NO to return numeric hostname * @param timeout how long to try resolving * @param callback function to call with hostnames * last callback is NULL when finished * @param cls closure for @a callback * @return handle that can be used to cancel the request */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_get (const struct sockaddr *sa, socklen_t salen, int do_resolve, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_HostnameCallback callback, void *cls) { struct GNUNET_RESOLVER_RequestHandle *rh; size_t ip_len; const void *ip; check_config (); switch (sa->sa_family) { case AF_INET: ip_len = sizeof (struct in_addr); ip = &((const struct sockaddr_in*)sa)->sin_addr; break; case AF_INET6: ip_len = sizeof (struct in6_addr); ip = &((const struct sockaddr_in6*)sa)->sin6_addr; break; default: GNUNET_break (0); return NULL; } rh = GNUNET_malloc (sizeof (struct GNUNET_RESOLVER_RequestHandle) + salen); rh->name_callback = callback; rh->cls = cls; rh->af = sa->sa_family; rh->timeout = GNUNET_TIME_relative_to_absolute (timeout); memcpy (&rh[1], ip, ip_len); rh->data_len = ip_len; rh->direction = GNUNET_YES; rh->received_response = GNUNET_NO; if (GNUNET_NO == do_resolve) { rh->task = GNUNET_SCHEDULER_add_now (&numeric_reverse, rh); return rh; } GNUNET_CONTAINER_DLL_insert_tail (req_head, req_tail, rh); rh->was_queued = GNUNET_YES; if (s_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (s_task); s_task = GNUNET_SCHEDULER_NO_TASK; } process_requests (); return rh; } /** * Get local fully qualified af name * * @return fqdn */ char * GNUNET_RESOLVER_local_fqdn_get () { struct hostent *host; char hostname[GNUNET_OS_get_hostname_max_length () + 1]; if (0 != gethostname (hostname, sizeof (hostname) - 1)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "gethostname"); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Resolving our FQDN `%s'\n", hostname); host = gethostbyname (hostname); if (NULL == host) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not resolve our FQDN : %s\n"), hstrerror (h_errno)); return NULL; } return GNUNET_strdup (host->h_name); } /** * Looking our own hostname. * * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" * @param callback function to call with addresses * @param cls closure for @a callback * @param timeout how long to try resolving * @return handle that can be used to cancel the request, NULL on error */ struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_hostname_resolve (int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *cls) { char hostname[GNUNET_OS_get_hostname_max_length () + 1]; if (0 != gethostname (hostname, sizeof (hostname) - 1)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "gethostname"); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Resolving our hostname `%s'\n", hostname); return GNUNET_RESOLVER_ip_get (hostname, af, timeout, callback, cls); } /** * Cancel a request that is still pending with the resolver. * Note that a client MUST NOT cancel a request that has * been completed (i.e, the callback has been called to * signal timeout or the final result). * * @param rh handle of request to cancel */ void GNUNET_RESOLVER_request_cancel (struct GNUNET_RESOLVER_RequestHandle *rh) { if (rh->task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (rh->task); rh->task = GNUNET_SCHEDULER_NO_TASK; } if (rh->was_transmitted == GNUNET_NO) { if (rh->was_queued == GNUNET_YES) GNUNET_CONTAINER_DLL_remove (req_head, req_tail, rh); GNUNET_free (rh); return; } GNUNET_assert (rh->was_transmitted == GNUNET_YES); rh->was_transmitted = GNUNET_SYSERR; /* mark as cancelled */ } /* end of resolver_api.c */ gnunet-0.10.1/src/util/test_configuration_data.conf0000644000175000017500000000042612225230043017317 00000000000000[PATHS] SUBST=/hello [GNUNET] SUBST=hello GNUNET_HOME=/tmp [test] a=a b=b five=5 [more] c=c five=42 [last] test = $SUBST/world boom = "1 2 3 testing" trailing = YES size = 512 KiB [FILENAMES] test = "/Hello /File\ Name /World" [TESTING] WEAKRANDOM = YES gnunet-0.10.1/src/util/test_os_network.c0000644000175000017500000000467412225777501015176 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_os_network.c * @brief testcase for util/os_network.c */ #include "platform.h" #include "gnunet_util_lib.h" /** * Check if the address we got is IPv4 or IPv6 loopback (which should * be present on all systems at all times); if so, set ok to 0 * (success). */ static int proc (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen) { int *ok = cls; char buf[INET6_ADDRSTRLEN]; const char * protocol; if (NULL == addr) return GNUNET_OK; if (addrlen == sizeof (struct sockaddr_in)) protocol = "IPv4"; else protocol = "IPv6"; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s Address `%s'\n", protocol, GNUNET_a2s ((const struct sockaddr *) addr,addrlen) ); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Netmask `%s'\n", GNUNET_a2s ((const struct sockaddr *) netmask, addrlen) ); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s'\n", GNUNET_a2s ((const struct sockaddr *) broadcast_addr,addrlen) ); inet_ntop (addr->sa_family, (addr->sa_family == AF_INET) ? (void *) &((struct sockaddr_in *) addr)->sin_addr : (void *) &((struct sockaddr_in6 *) addr)->sin6_addr, buf, sizeof (buf)); if ((0 == strcmp ("::1", buf)) || (0 == strcmp ("127.0.0.1", buf))) *ok = 0; return GNUNET_OK; } int main (int argc, char *argv[]) { int ret; GNUNET_log_setup ("test-os-network", "WARNING", NULL); ret = 1; GNUNET_OS_network_interfaces_list (&proc, &ret); return ret; } /* end of test_os_network.c */ gnunet-0.10.1/src/util/container_meta_data.c0000644000175000017500000007451512225777501015727 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/container_meta_data.c * @brief Storing of meta data * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include #include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Meta data item. */ struct MetaItem { /** * This is a doubly linked list. */ struct MetaItem *next; /** * This is a doubly linked list. */ struct MetaItem *prev; /** * Name of the extracting plugin. */ char *plugin_name; /** * Mime-type of data. */ char *mime_type; /** * The actual meta data. */ char *data; /** * Number of bytes in 'data'. */ size_t data_size; /** * Type of the meta data. */ enum EXTRACTOR_MetaType type; /** * Format of the meta data. */ enum EXTRACTOR_MetaFormat format; }; /** * Meta data to associate with a file, directory or namespace. */ struct GNUNET_CONTAINER_MetaData { /** * Head of linked list of the meta data items. */ struct MetaItem *items_head; /** * Tail of linked list of the meta data items. */ struct MetaItem *items_tail; /** * Complete serialized and compressed buffer of the items. * NULL if we have not computed that buffer yet. */ char *sbuf; /** * Number of bytes in 'sbuf'. 0 if the buffer is stale. */ size_t sbuf_size; /** * Number of items in the linked list. */ unsigned int item_count; }; /** * Create a fresh struct CONTAINER_MetaData token. * * @return empty meta-data container */ struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_create () { return GNUNET_new (struct GNUNET_CONTAINER_MetaData); } /** * Free meta data item. * * @param mi item to free */ static void meta_item_free (struct MetaItem *mi) { GNUNET_free_non_null (mi->plugin_name); GNUNET_free_non_null (mi->mime_type); GNUNET_free_non_null (mi->data); GNUNET_free (mi); } /** * The meta data has changed, invalidate its serialization * buffer. * * @param md meta data that changed */ static void invalidate_sbuf (struct GNUNET_CONTAINER_MetaData *md) { if (NULL == md->sbuf) return; GNUNET_free (md->sbuf); md->sbuf = NULL; md->sbuf_size = 0; } /** * Free meta data. * * @param md what to free */ void GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md) { struct MetaItem *pos; if (NULL == md) return; while (NULL != (pos = md->items_head)) { GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, pos); meta_item_free (pos); } GNUNET_free_non_null (md->sbuf); GNUNET_free (md); } /** * Remove all items in the container. * * @param md metadata to manipulate */ void GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md) { struct MetaItem *mi; if (NULL == md) return; while (NULL != (mi = md->items_head)) { GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, mi); meta_item_free (mi); } GNUNET_free_non_null (md->sbuf); memset (md, 0, sizeof (struct GNUNET_CONTAINER_MetaData)); } /** * Test if two MDs are equal. We consider them equal if * the meta types, formats and content match (we do not * include the mime types and plugins names in this * consideration). * * @param md1 first value to check * @param md2 other value to check * @return #GNUNET_YES if they are equal */ int GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData *md1, const struct GNUNET_CONTAINER_MetaData *md2) { struct MetaItem *i; struct MetaItem *j; int found; if (md1 == md2) return GNUNET_YES; if (md1->item_count != md2->item_count) return GNUNET_NO; for (i = md1->items_head; NULL != i; i = i->next) { found = GNUNET_NO; for (j = md2->items_head; NULL != j; j = j->next) { if ((i->type == j->type) && (i->format == j->format) && (i->data_size == j->data_size) && (0 == memcmp (i->data, j->data, i->data_size))) { found = GNUNET_YES; break; } if (j->data_size < i->data_size) break; /* elements are sorted by (decreasing) size... */ } if (GNUNET_NO == found) return GNUNET_NO; } return GNUNET_YES; } /** * Extend metadata. Note that the list of meta data items is * sorted by size (largest first). * * @param md metadata to extend * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_size number of bytes in @a data * @return #GNUNET_OK on success, #GNUNET_SYSERR if this entry already exists * data_mime_type and plugin_name are not considered for "exists" checks */ int GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size) { struct MetaItem *pos; struct MetaItem *mi; char *p; if ((EXTRACTOR_METAFORMAT_UTF8 == format) || (EXTRACTOR_METAFORMAT_C_STRING == format)) GNUNET_break ('\0' == data[data_size - 1]); for (pos = md->items_head; NULL != pos; pos = pos->next) { if (pos->data_size < data_size) break; /* elements are sorted by size in the list */ if ((pos->type == type) && (pos->data_size == data_size) && (0 == memcmp (pos->data, data, data_size))) { if ((NULL == pos->mime_type) && (NULL != data_mime_type)) { pos->mime_type = GNUNET_strdup (data_mime_type); invalidate_sbuf (md); } if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) && (EXTRACTOR_METAFORMAT_UTF8 == format)) { pos->format = EXTRACTOR_METAFORMAT_UTF8; invalidate_sbuf (md); } return GNUNET_SYSERR; } } md->item_count++; mi = GNUNET_new (struct MetaItem); mi->type = type; mi->format = format; mi->data_size = data_size; if (NULL == pos) GNUNET_CONTAINER_DLL_insert_tail (md->items_head, md->items_tail, mi); else GNUNET_CONTAINER_DLL_insert_after (md->items_head, md->items_tail, pos->prev, mi); mi->mime_type = (NULL == data_mime_type) ? NULL : GNUNET_strdup (data_mime_type); mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup (plugin_name); mi->data = GNUNET_malloc (data_size); memcpy (mi->data, data, data_size); /* change all dir separators to POSIX style ('/') */ if ( (EXTRACTOR_METATYPE_FILENAME == type) || (EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME == type) ) { p = mi->data; while (('\0' != *p) && (p < mi->data + data_size)) { if ('\\' == *p) *p = '/'; p++; } } invalidate_sbuf (md); return GNUNET_OK; } /** * Merge given meta data. * * @param cls the `struct GNUNET_CONTAINER_MetaData` to merge into * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_size number of bytes in @a data * @return 0 (to continue) */ static int merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size) { struct GNUNET_CONTAINER_MetaData *md = cls; (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format, data_mime_type, data, data_size); return 0; } /** * Extend metadata. Merges the meta data from the second argument * into the first, discarding duplicate key-value pairs. * * @param md metadata to extend * @param in metadata to merge */ void GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md, const struct GNUNET_CONTAINER_MetaData *in) { GNUNET_CONTAINER_meta_data_iterate (in, &merge_helper, md); } /** * Remove an item. * * @param md metadata to manipulate * @param type type of the item to remove * @param data specific value to remove, NULL to remove all * entries of the given type * @param data_size number of bytes in @a data * @return #GNUNET_OK on success, #GNUNET_SYSERR if the item does not exist in md */ int GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type, const char *data, size_t data_size) { struct MetaItem *pos; for (pos = md->items_head; NULL != pos; pos = pos->next) { if (pos->data_size < data_size) break; /* items are sorted by (decreasing) size */ if ((pos->type == type) && ((NULL == data) || ((pos->data_size == data_size) && (0 == memcmp (pos->data, data, data_size))))) { GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, pos); meta_item_free (pos); md->item_count--; invalidate_sbuf (md); return GNUNET_OK; } } return GNUNET_SYSERR; } /** * Add the current time as the publication date * to the meta-data. * * @param md metadata to modify */ void GNUNET_CONTAINER_meta_data_add_publication_date (struct GNUNET_CONTAINER_MetaData *md) { const char *dat; struct GNUNET_TIME_Absolute t; t = GNUNET_TIME_absolute_get (); GNUNET_CONTAINER_meta_data_delete (md, EXTRACTOR_METATYPE_PUBLICATION_DATE, NULL, 0); dat = GNUNET_STRINGS_absolute_time_to_string (t); GNUNET_CONTAINER_meta_data_insert (md, "", EXTRACTOR_METATYPE_PUBLICATION_DATE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", dat, strlen (dat) + 1); } /** * Iterate over MD entries. * * @param md metadata to inspect * @param iter function to call on each entry * @param iter_cls closure for iterator * @return number of entries */ int GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md, EXTRACTOR_MetaDataProcessor iter, void *iter_cls) { struct MetaItem *pos; if (NULL == md) return 0; if (NULL == iter) return md->item_count; for (pos = md->items_head; NULL != pos; pos = pos->next) if (0 != iter (iter_cls, pos->plugin_name, pos->type, pos->format, pos->mime_type, pos->data, pos->data_size)) return md->item_count; return md->item_count; } /** * Get the first MD entry of the given type. Caller * is responsible for freeing the return value. * Also, only meta data items that are strings (0-terminated) * are returned by this function. * * @param md metadata to inspect * @param type type to look for * @return NULL if no entry was found */ char * GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type) { struct MetaItem *pos; if (NULL == md) return NULL; for (pos = md->items_head; NULL != pos; pos = pos->next) if ((type == pos->type) && ((pos->format == EXTRACTOR_METAFORMAT_UTF8) || (pos->format == EXTRACTOR_METAFORMAT_C_STRING))) return GNUNET_strdup (pos->data); return NULL; } /** * Get the first matching MD entry of the given types. Caller is * responsible for freeing the return value. Also, only meta data * items that are strings (0-terminated) are returned by this * function. * * @param md metadata to inspect * @param ... -1-terminated list of types * @return NULL if we do not have any such entry, * otherwise client is responsible for freeing the value! */ char * GNUNET_CONTAINER_meta_data_get_first_by_types (const struct GNUNET_CONTAINER_MetaData *md, ...) { char *ret; va_list args; enum EXTRACTOR_MetaType type; if (NULL == md) return NULL; ret = NULL; va_start (args, md); while (1) { type = va_arg (args, enum EXTRACTOR_MetaType); if (-1 == type) break; if (NULL != (ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type))) break; } va_end (args); return ret; } /** * Get a thumbnail from the meta-data (if present). * * @param md metadata to get the thumbnail from * @param thumb will be set to the thumbnail data. Must be * freed by the caller! * @return number of bytes in thumbnail, 0 if not available */ size_t GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData * md, unsigned char **thumb) { struct MetaItem *pos; struct MetaItem *match; if (NULL == md) return 0; match = NULL; for (pos = md->items_head; NULL != pos; pos = pos->next) { if ((NULL != pos->mime_type) && (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) && (EXTRACTOR_METAFORMAT_BINARY == pos->format)) { if (NULL == match) match = pos; else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) && (pos->type == EXTRACTOR_METATYPE_THUMBNAIL)) match = pos; } } if ((NULL == match) || (0 == match->data_size)) return 0; *thumb = GNUNET_malloc (match->data_size); memcpy (*thumb, match->data, match->data_size); return match->data_size; } /** * Duplicate a `struct GNUNET_CONTAINER_MetaData`. * * @param md what to duplicate * @return duplicate meta-data container */ struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData *md) { struct GNUNET_CONTAINER_MetaData *ret; struct MetaItem *pos; if (NULL == md) return NULL; ret = GNUNET_CONTAINER_meta_data_create (); for (pos = md->items_tail; NULL != pos; pos = pos->prev) GNUNET_CONTAINER_meta_data_insert (ret, pos->plugin_name, pos->type, pos->format, pos->mime_type, pos->data, pos->data_size); return ret; } /** * Try to compress the given block of data. * * @param data block to compress; if compression * resulted in a smaller block, the first * bytes of data are updated to the compressed * data * @param oldSize number of bytes in data * @param result set to the compressed data * @param newSize set to size of result * @return #GNUNET_YES if compression reduce the size, * #GNUNET_NO if compression did not help */ static int try_compression (const char *data, size_t oldSize, char **result, size_t * newSize) { char *tmp; uLongf dlen; #ifdef compressBound dlen = compressBound (oldSize); #else dlen = oldSize + (oldSize / 100) + 20; /* documentation says 100.1% oldSize + 12 bytes, but we * should be able to overshoot by more to be safe */ #endif tmp = GNUNET_malloc (dlen); if (Z_OK == compress2 ((Bytef *) tmp, &dlen, (const Bytef *) data, oldSize, 9)) { if (dlen < oldSize) { *result = tmp; *newSize = dlen; return GNUNET_YES; } } GNUNET_free (tmp); return GNUNET_NO; } /** * Flag in 'version' that indicates compressed meta-data. */ #define HEADER_COMPRESSED 0x80000000 /** * Bits in 'version' that give the version number. */ #define HEADER_VERSION_MASK 0x7FFFFFFF /** * Header for serialized meta data. */ struct MetaDataHeader { /** * The version of the MD serialization. The highest bit is used to * indicate compression. * * Version 0 is traditional (pre-0.9) meta data (unsupported) * Version is 1 for a NULL pointer * Version 2 is for 0.9.x (and possibly higher) * Other version numbers are not yet defined. */ uint32_t version; /** * How many MD entries are there? */ uint32_t entries; /** * Size of the decompressed meta data. */ uint32_t size; /** * This is followed by 'entries' values of type 'struct MetaDataEntry' * and then by 'entry' plugin names, mime-types and data blocks * as specified in those meta data entries. */ }; /** * Entry of serialized meta data. */ struct MetaDataEntry { /** * Meta data type. Corresponds to an 'enum EXTRACTOR_MetaType' */ uint32_t type; /** * Meta data format. Corresponds to an 'enum EXTRACTOR_MetaFormat' */ uint32_t format; /** * Number of bytes of meta data. */ uint32_t data_size; /** * Number of bytes in the plugin name including 0-terminator. 0 for NULL. */ uint32_t plugin_name_len; /** * Number of bytes in the mime type including 0-terminator. 0 for NULL. */ uint32_t mime_type_len; }; /** * Serialize meta-data to target. * * @param md metadata to serialize * @param target where to write the serialized metadata; * *target can be NULL, in which case memory is allocated * @param max maximum number of bytes available in target * @param opt is it ok to just write SOME of the * meta-data to match the size constraint, * possibly discarding some data? * @return number of bytes written on success, * #GNUNET_SYSERR on error (typically: not enough * space) */ ssize_t GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData *md, char **target, size_t max, enum GNUNET_CONTAINER_MetaDataSerializationOptions opt) { struct GNUNET_CONTAINER_MetaData *vmd; struct MetaItem *pos; struct MetaDataHeader ihdr; struct MetaDataHeader *hdr; struct MetaDataEntry *ent; char *dst; unsigned int i; uint64_t msize; size_t off; char *mdata; char *cdata; size_t mlen; size_t plen; size_t size; size_t left; size_t clen; size_t rlen; int comp; if (max < sizeof (struct MetaDataHeader)) return GNUNET_SYSERR; /* far too small */ if (NULL == md) return 0; if (NULL != md->sbuf) { /* try to use serialization cache */ if (md->sbuf_size <= max) { if (NULL == *target) *target = GNUNET_malloc (md->sbuf_size); memcpy (*target, md->sbuf, md->sbuf_size); return md->sbuf_size; } if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART)) return GNUNET_SYSERR; /* can say that this will fail */ /* need to compute a partial serialization, sbuf useless ... */ } dst = NULL; msize = 0; for (pos = md->items_tail; NULL != pos; pos = pos->prev) { msize += sizeof (struct MetaDataEntry); msize += pos->data_size; if (NULL != pos->plugin_name) msize += strlen (pos->plugin_name) + 1; if (NULL != pos->mime_type) msize += strlen (pos->mime_type) + 1; } size = (size_t) msize; if (size != msize) { GNUNET_break (0); /* integer overflow */ return GNUNET_SYSERR; } if (size >= GNUNET_MAX_MALLOC_CHECKED) { /* too large to be processed */ return GNUNET_SYSERR; } ent = GNUNET_malloc (size); mdata = (char *) &ent[md->item_count]; off = size - (md->item_count * sizeof (struct MetaDataEntry)); i = 0; for (pos = md->items_head; NULL != pos; pos = pos->next) { ent[i].type = htonl ((uint32_t) pos->type); ent[i].format = htonl ((uint32_t) pos->format); ent[i].data_size = htonl ((uint32_t) pos->data_size); if (NULL == pos->plugin_name) plen = 0; else plen = strlen (pos->plugin_name) + 1; ent[i].plugin_name_len = htonl ((uint32_t) plen); if (NULL == pos->mime_type) mlen = 0; else mlen = strlen (pos->mime_type) + 1; ent[i].mime_type_len = htonl ((uint32_t) mlen); off -= pos->data_size; if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) || (EXTRACTOR_METAFORMAT_C_STRING == pos->format)) GNUNET_break ('\0' == pos->data[pos->data_size - 1]); memcpy (&mdata[off], pos->data, pos->data_size); off -= plen; if (NULL != pos->plugin_name) memcpy (&mdata[off], pos->plugin_name, plen); off -= mlen; if (NULL != pos->mime_type) memcpy (&mdata[off], pos->mime_type, mlen); i++; } GNUNET_assert (0 == off); clen = 0; cdata = NULL; left = size; i = 0; for (pos = md->items_head; NULL != pos; pos = pos->next) { comp = GNUNET_NO; if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS)) comp = try_compression ((const char *) &ent[i], left, &cdata, &clen); if ((NULL == md->sbuf) && (0 == i)) { /* fill 'sbuf'; this "modifies" md, but since this is only * an internal cache we will cast away the 'const' instead * of making the API look strange. */ vmd = (struct GNUNET_CONTAINER_MetaData *) md; hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader)); hdr->size = htonl (left); hdr->entries = htonl (md->item_count); if (GNUNET_YES == comp) { GNUNET_assert (clen < left); hdr->version = htonl (2 | HEADER_COMPRESSED); memcpy (&hdr[1], cdata, clen); vmd->sbuf_size = clen + sizeof (struct MetaDataHeader); } else { hdr->version = htonl (2); memcpy (&hdr[1], &ent[0], left); vmd->sbuf_size = left + sizeof (struct MetaDataHeader); } vmd->sbuf = (char *) hdr; } if (((left + sizeof (struct MetaDataHeader)) <= max) || ((GNUNET_YES == comp) && (clen <= max))) { /* success, this now fits! */ if (GNUNET_YES == comp) { if (NULL == dst) dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader)); hdr = (struct MetaDataHeader *) dst; hdr->version = htonl (2 | HEADER_COMPRESSED); hdr->size = htonl (left); hdr->entries = htonl (md->item_count - i); memcpy (&dst[sizeof (struct MetaDataHeader)], cdata, clen); GNUNET_free (cdata); cdata = NULL; GNUNET_free (ent); rlen = clen + sizeof (struct MetaDataHeader); } else { if (NULL == dst) dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader)); hdr = (struct MetaDataHeader *) dst; hdr->version = htonl (2); hdr->entries = htonl (md->item_count - i); hdr->size = htonl (left); memcpy (&dst[sizeof (struct MetaDataHeader)], &ent[i], left); GNUNET_free (ent); rlen = left + sizeof (struct MetaDataHeader); } if (NULL != *target) { if (GNUNET_YES == comp) memcpy (*target, dst, clen + sizeof (struct MetaDataHeader)); else memcpy (*target, dst, left + sizeof (struct MetaDataHeader)); GNUNET_free (dst); } else { *target = dst; } return rlen; } if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART)) { /* does not fit! */ GNUNET_free (ent); return GNUNET_SYSERR; } /* next iteration: ignore the corresponding meta data at the * end and try again without it */ left -= sizeof (struct MetaDataEntry); left -= pos->data_size; if (NULL != pos->plugin_name) left -= strlen (pos->plugin_name) + 1; if (NULL != pos->mime_type) left -= strlen (pos->mime_type) + 1; GNUNET_free_non_null (cdata); cdata = NULL; i++; } GNUNET_free (ent); /* nothing fit, only write header! */ ihdr.version = htonl (2); ihdr.entries = htonl (0); ihdr.size = htonl (0); if (NULL == *target) *target = (char *) GNUNET_new (struct MetaDataHeader); memcpy (*target, &ihdr, sizeof (struct MetaDataHeader)); return sizeof (struct MetaDataHeader); } /** * Get the size of the full meta-data in serialized form. * * @param md metadata to inspect * @return number of bytes needed for serialization, -1 on error */ ssize_t GNUNET_CONTAINER_meta_data_get_serialized_size (const struct GNUNET_CONTAINER_MetaData *md) { ssize_t ret; char *ptr; if (NULL != md->sbuf) return md->sbuf_size; ptr = NULL; ret = GNUNET_CONTAINER_meta_data_serialize (md, &ptr, GNUNET_MAX_MALLOC_CHECKED, GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); if (-1 != ret) GNUNET_free (ptr); return ret; } /** * Decompress input, return the decompressed data * as output, set outputSize to the number of bytes * that were found. * * @param input compressed data * @param inputSize number of bytes in input * @param outputSize expected size of the output * @return NULL on error */ static char * decompress (const char *input, size_t inputSize, size_t outputSize) { char *output; uLongf olen; olen = outputSize; output = GNUNET_malloc (olen); if (Z_OK == uncompress ((Bytef *) output, &olen, (const Bytef *) input, inputSize)) return output; GNUNET_free (output); return NULL; } /** * Deserialize meta-data. Initializes md. * * @param input buffer with the serialized metadata * @param size number of bytes available in input * @return MD on success, NULL on error (i.e. * bad format) */ struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) { struct GNUNET_CONTAINER_MetaData *md; struct MetaDataHeader hdr; struct MetaDataEntry ent; uint32_t ic; uint32_t i; char *data; const char *cdata; uint32_t version; uint32_t dataSize; int compressed; size_t left; uint32_t mlen; uint32_t plen; uint32_t dlen; const char *mdata; const char *meta_data; const char *plugin_name; const char *mime_type; enum EXTRACTOR_MetaFormat format; if (size < sizeof (struct MetaDataHeader)) return NULL; memcpy (&hdr, input, sizeof (struct MetaDataHeader)); version = ntohl (hdr.version) & HEADER_VERSION_MASK; compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0; if (1 == version) return NULL; /* null pointer */ if (2 != version) { GNUNET_break_op (0); /* unsupported version */ return NULL; } ic = ntohl (hdr.entries); dataSize = ntohl (hdr.size); if ((sizeof (struct MetaDataEntry) * ic) > dataSize) { GNUNET_break_op (0); return NULL; } if (compressed) { if (dataSize >= GNUNET_MAX_MALLOC_CHECKED) { /* make sure we don't blow our memory limit because of a mal-formed * message... */ GNUNET_break_op (0); return NULL; } data = decompress ((const char *) &input[sizeof (struct MetaDataHeader)], size - sizeof (struct MetaDataHeader), dataSize); if (NULL == data) { GNUNET_break_op (0); return NULL; } cdata = data; } else { data = NULL; cdata = (const char *) &input[sizeof (struct MetaDataHeader)]; if (dataSize != size - sizeof (struct MetaDataHeader)) { GNUNET_break_op (0); return NULL; } } md = GNUNET_CONTAINER_meta_data_create (); left = dataSize - ic * sizeof (struct MetaDataEntry); mdata = &cdata[ic * sizeof (struct MetaDataEntry)]; for (i = 0; i < ic; i++) { memcpy (&ent, &cdata[i * sizeof (struct MetaDataEntry)], sizeof (struct MetaDataEntry)); format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format); if ((EXTRACTOR_METAFORMAT_UTF8 != format) && (EXTRACTOR_METAFORMAT_C_STRING != format) && (EXTRACTOR_METAFORMAT_BINARY != format)) { GNUNET_break_op (0); break; } dlen = ntohl (ent.data_size); plen = ntohl (ent.plugin_name_len); mlen = ntohl (ent.mime_type_len); if (dlen > left) { GNUNET_break_op (0); break; } left -= dlen; meta_data = &mdata[left]; if ((EXTRACTOR_METAFORMAT_UTF8 == format) || (EXTRACTOR_METAFORMAT_C_STRING == format)) { if (0 == dlen) { GNUNET_break_op (0); break; } if ('\0' != meta_data[dlen - 1]) { GNUNET_break_op (0); break; } } if (plen > left) { GNUNET_break_op (0); break; } left -= plen; if ((plen > 0) && ('\0' != mdata[left + plen - 1])) { GNUNET_break_op (0); break; } if (0 == plen) plugin_name = NULL; else plugin_name = &mdata[left]; if (mlen > left) { GNUNET_break_op (0); break; } left -= mlen; if ((mlen > 0) && ('\0' != mdata[left + mlen - 1])) { GNUNET_break_op (0); break; } if (0 == mlen) mime_type = NULL; else mime_type = &mdata[left]; GNUNET_CONTAINER_meta_data_insert (md, plugin_name, (enum EXTRACTOR_MetaType) ntohl (ent.type), format, mime_type, meta_data, dlen); } GNUNET_free_non_null (data); return md; } /* end of container_meta_data.c */ gnunet-0.10.1/src/util/common_allocation.c0000644000175000017500000002502412251306467015430 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2005, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/common_allocation.c * @brief wrapper around malloc/free * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #if HAVE_MALLOC_H #include #endif #if HAVE_MALLOC_MALLOC_H #include #endif #define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #ifndef INT_MAX #define INT_MAX 0x7FFFFFFF #endif #if 0 #define W32_MEM_LIMIT 200000000 #endif #ifdef W32_MEM_LIMIT static LONG mem_used = 0; #endif /** * Allocate memory. Checks the return value, aborts if no more * memory is available. * * @param size how many bytes of memory to allocate, do NOT use * this function (or GNUNET_malloc) to allocate more than several MB * of memory, if you are possibly needing a very large chunk use * GNUNET_xmalloc_unchecked_ instead. * @param filename where in the code was the call to GNUNET_malloc * @param linenumber where in the code was the call to GNUNET_malloc * @return pointer to size bytes of memory */ void * GNUNET_xmalloc_ (size_t size, const char *filename, int linenumber) { void *ret; /* As a security precaution, we generally do not allow very large * allocations using the default 'GNUNET_malloc' macro */ GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber); ret = GNUNET_xmalloc_unchecked_ (size, filename, linenumber); if (ret == NULL) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc"); GNUNET_abort (); } return ret; } /** * Allocate and initialize memory. Checks the return value, aborts if no more * memory is available. Don't use GNUNET_xmemdup_ directly. Use the * GNUNET_memdup macro. * * @param buf buffer to initialize from (must contain size bytes) * @param size number of bytes to allocate * @param filename where is this call being made (for debugging) * @param linenumber line where this call is being made (for debugging) * @return allocated memory, never NULL */ void * GNUNET_xmemdup_ (const void *buf, size_t size, const char *filename, int linenumber) { void *ret; /* As a security precaution, we generally do not allow very large * allocations here */ GNUNET_assert_at (size <= GNUNET_MAX_MALLOC_CHECKED, filename, linenumber); #ifdef W32_MEM_LIMIT size += sizeof (size_t); if (mem_used + size > W32_MEM_LIMIT) return NULL; #endif GNUNET_assert_at (size < INT_MAX, filename, linenumber); ret = malloc (size); if (ret == NULL) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "malloc"); GNUNET_abort (); } #ifdef W32_MEM_LIMIT *((size_t *) ret) = size; ret = &((size_t *) ret)[1]; mem_used += size; #endif memcpy (ret, buf, size); return ret; } /** * Wrapper around malloc. Allocates size bytes of memory. * The memory will be zero'ed out. * * @param size the number of bytes to allocate * @param filename where in the code was the call to GNUNET_malloc_large * @param linenumber where in the code was the call to GNUNET_malloc_large * @return pointer to size bytes of memory, NULL if we do not have enough memory */ void * GNUNET_xmalloc_unchecked_ (size_t size, const char *filename, int linenumber) { void *result; #ifdef W32_MEM_LIMIT size += sizeof (size_t); if (mem_used + size > W32_MEM_LIMIT) return NULL; #endif result = malloc (size); if (result == NULL) return NULL; memset (result, 0, size); #ifdef W32_MEM_LIMIT *((size_t *) result) = size; result = &((size_t *) result)[1]; mem_used += size; #endif return result; } /** * Reallocate memory. Checks the return value, aborts if no more * memory is available. * * @param ptr the pointer to reallocate * @param n how many bytes of memory to allocate * @param filename where in the code was the call to GNUNET_realloc * @param linenumber where in the code was the call to GNUNET_realloc * @return pointer to size bytes of memory */ void * GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber) { #ifdef W32_MEM_LIMIT n += sizeof (size_t); ptr = &((size_t *) ptr)[-1]; mem_used = mem_used - *((size_t *) ptr) + n; #endif ptr = realloc (ptr, n); if ((NULL == ptr) && (n > 0)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "realloc"); GNUNET_abort (); } #ifdef W32_MEM_LIMIT ptr = &((size_t *) ptr)[1]; #endif return ptr; } # if __BYTE_ORDER == __LITTLE_ENDIAN #define BAADFOOD_STR "\x0D\xF0\xAD\xBA" #endif # if __BYTE_ORDER == __BIG_ENDIAN #define BAADFOOD_STR "\xBA\xAD\xF0\x0D" #endif #if WINDOWS #define M_SIZE(p) _msize (p) #endif #ifdef FREEBSD #include #endif #if HAVE_MALLOC_USABLE_SIZE #define M_SIZE(p) malloc_usable_size (p) #elif HAVE_MALLOC_SIZE #define M_SIZE(p) malloc_size (p) #endif /** * Free memory. Merely a wrapper for the case that we * want to keep track of allocations. * * @param ptr the pointer to free * @param filename where in the code was the call to GNUNET_array_grow * @param linenumber where in the code was the call to GNUNET_array_grow */ void GNUNET_xfree_ (void *ptr, const char *filename, int linenumber) { GNUNET_assert_at (ptr != NULL, filename, linenumber); #ifdef W32_MEM_LIMIT ptr = &((size_t *) ptr)[-1]; mem_used -= *((size_t *) ptr); #endif #if defined(M_SIZE) #if ENABLE_POISONING { const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL); uint64_t *base = ptr; size_t s = M_SIZE (ptr); size_t i; for (i=0;i newCount, filename, linenumber); size = newCount * elementSize; if (size == 0) { tmp = NULL; } else { tmp = GNUNET_xmalloc_ (size, filename, linenumber); memset (tmp, 0, size); /* client code should not rely on this, though... */ if (*oldCount > newCount) *oldCount = newCount; /* shrink is also allowed! */ memcpy (tmp, *old, elementSize * (*oldCount)); } if (*old != NULL) { GNUNET_xfree_ (*old, filename, linenumber); } *old = tmp; *oldCount = newCount; } /** * Like asprintf, just portable. * * @param buf set to a buffer of sufficient size (allocated, caller must free) * @param format format string (see printf, fprintf, etc.) * @param ... data for format string * @return number of bytes in "*buf" excluding 0-termination */ int GNUNET_asprintf (char **buf, const char *format, ...) { int ret; va_list args; va_start (args, format); ret = VSNPRINTF (NULL, 0, format, args); va_end (args); *buf = GNUNET_malloc (ret + 1); va_start (args, format); ret = VSPRINTF (*buf, format, args); va_end (args); return ret; } /** * Like snprintf, just aborts if the buffer is of insufficient size. * * @param buf pointer to buffer that is written to * @param size number of bytes in buf * @param format format strings * @param ... data for format string * @return number of bytes written to buf or negative value on error */ int GNUNET_snprintf (char *buf, size_t size, const char *format, ...) { int ret; va_list args; va_start (args, format); ret = VSNPRINTF (buf, size, format, args); va_end (args); GNUNET_assert (ret <= size); return ret; } /** * Create a copy of the given message. * * @param msg message to copy * @return duplicate of the message */ struct GNUNET_MessageHeader * GNUNET_copy_message (const struct GNUNET_MessageHeader *msg) { struct GNUNET_MessageHeader *ret; uint16_t msize; msize = ntohs (msg->size); GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader)); ret = GNUNET_malloc (msize); memcpy (ret, msg, msize); return ret; } /* end of common_allocation.c */ gnunet-0.10.1/src/util/test_container_multipeermap.c0000644000175000017500000001215012225777501017536 00000000000000/* This file is part of GNUnet. (C) 2008, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_container_multipeermap.c * @brief Test for container_multipeermap.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); if (NULL != m) GNUNET_CONTAINER_multipeermap_destroy(m); return 1; } #define CHECK(c) { if (! (c)) ABORT(); } static int testMap (int i) { struct GNUNET_CONTAINER_MultiPeerMap *m; struct GNUNET_PeerIdentity k1; struct GNUNET_PeerIdentity k2; struct GNUNET_CONTAINER_MultiPeerMapIterator *iter; struct GNUNET_PeerIdentity key_ret; const char *ret; int j; CHECK (NULL != (m = GNUNET_CONTAINER_multipeermap_create (i, GNUNET_NO))); memset (&k1, 0, sizeof (k1)); memset (&k2, 1, sizeof (k2)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k1)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k2)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_remove (m, &k1, NULL)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_remove (m, &k2, NULL)); CHECK (NULL == GNUNET_CONTAINER_multipeermap_get (m, &k1)); CHECK (NULL == GNUNET_CONTAINER_multipeermap_get (m, &k2)); CHECK (0 == GNUNET_CONTAINER_multipeermap_remove_all (m, &k1)); CHECK (0 == GNUNET_CONTAINER_multipeermap_size (m)); CHECK (0 == GNUNET_CONTAINER_multipeermap_iterate (m, NULL, NULL)); CHECK (0 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k1, NULL, NULL)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v1", GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); CHECK (1 == GNUNET_CONTAINER_multipeermap_size (m)); ret = GNUNET_CONTAINER_multipeermap_get (m, &k1); GNUNET_assert (ret != NULL); CHECK (0 == strcmp ("v1", ret)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v1", GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); CHECK (1 == GNUNET_CONTAINER_multipeermap_size (m)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v2", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v3", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); CHECK (3 == GNUNET_CONTAINER_multipeermap_size (m)); CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (m, &k1, "v3")); CHECK (2 == GNUNET_CONTAINER_multipeermap_size (m)); CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (m, &k1)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (m, &k2)); CHECK (2 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k1, NULL, NULL)); CHECK (0 == GNUNET_CONTAINER_multipeermap_get_multiple (m, &k2, NULL, NULL)); CHECK (2 == GNUNET_CONTAINER_multipeermap_iterate (m, NULL, NULL)); iter = GNUNET_CONTAINER_multipeermap_iterator_create (m); CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, &key_ret, (const void **)&ret)); CHECK (0 == memcmp (&key_ret, &k1, sizeof (key_ret))); CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, &key_ret, (const void **)&ret)); CHECK (0 == memcmp (&key_ret, &k1, sizeof (key_ret))); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL)); GNUNET_free (iter); CHECK (2 == GNUNET_CONTAINER_multipeermap_remove_all (m, &k1)); for (j = 0; j < 1024; j++) CHECK (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (m, &k1, "v2", GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); iter = GNUNET_CONTAINER_multipeermap_iterator_create (m); for (j = 0; j < GNUNET_CONTAINER_multipeermap_size (m); j++) CHECK (GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multipeermap_iterator_next (iter, NULL, NULL)); GNUNET_free (iter); GNUNET_CONTAINER_multipeermap_destroy (m); return 0; } int main (int argc, char *argv[]) { int failureCount = 0; int i; GNUNET_log_setup ("test-container-multipeermap", "WARNING", NULL); for (i = 1; i < 255; i++) failureCount += testMap (i); if (failureCount != 0) return 1; return 0; } /* end of test_container_multipeermap.c */ gnunet-0.10.1/src/util/gnunet-service-resolver.c0000644000175000017500000003561512267431203016531 00000000000000/* This file is part of GNUnet. (C) 2007-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/gnunet-service-resolver.c * @brief code to do DNS resolution * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "resolver.h" /** * A cached DNS lookup result. */ struct IPCache { /** * This is a doubly linked list. */ struct IPCache *next; /** * This is a doubly linked list. */ struct IPCache *prev; /** * Hostname in human-readable form. */ char *addr; /** * Binary IP address, allocated at the end of this struct. */ const void *ip; /** * Last time this entry was updated. */ struct GNUNET_TIME_Absolute last_refresh; /** * Last time this entry was requested. */ struct GNUNET_TIME_Absolute last_request; /** * Number of bytes in ip. */ size_t ip_len; /** * Address family of the IP. */ int af; }; /** * Start of the linked list of cached DNS lookup results. */ static struct IPCache *cache_head; /** * Tail of the linked list of cached DNS lookup results. */ static struct IPCache *cache_tail; #if HAVE_GETNAMEINFO /** * Resolve the given request using getnameinfo * * @param cache the request to resolve (and where to store the result) */ static void getnameinfo_resolve (struct IPCache *cache) { char hostname[256]; const struct sockaddr *sa; struct sockaddr_in v4; struct sockaddr_in6 v6; size_t salen; switch (cache->af) { case AF_INET: GNUNET_assert (cache->ip_len == sizeof (struct in_addr)); sa = (const struct sockaddr*) &v4; memset (&v4, 0, sizeof (v4)); v4.sin_addr = * (const struct in_addr*) cache->ip; v4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif salen = sizeof (v4); break; case AF_INET6: GNUNET_assert (cache->ip_len == sizeof (struct in6_addr)); sa = (const struct sockaddr*) &v6; memset (&v6, 0, sizeof (v6)); v6.sin6_addr = * (const struct in6_addr*) cache->ip; v6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (v6); #endif salen = sizeof (v6); break; default: GNUNET_assert (0); } if (0 == getnameinfo (sa, salen, hostname, sizeof (hostname), NULL, 0, 0)) cache->addr = GNUNET_strdup (hostname); } #endif #if HAVE_GETHOSTBYADDR /** * Resolve the given request using gethostbyaddr * * @param cache the request to resolve (and where to store the result) */ static void gethostbyaddr_resolve (struct IPCache *cache) { struct hostent *ent; ent = gethostbyaddr (cache->ip, cache->ip_len, cache->af); if (ent != NULL) cache->addr = GNUNET_strdup (ent->h_name); } #endif /** * Resolve the given request using the available methods. * * @param cache the request to resolve (and where to store the result) */ static void cache_resolve (struct IPCache *cache) { #if HAVE_GETNAMEINFO if (cache->addr == NULL) getnameinfo_resolve (cache); #endif #if HAVE_GETHOSTBYADDR if (cache->addr == NULL) gethostbyaddr_resolve (cache); #endif } /** * Get an IP address as a string (works for both IPv4 and IPv6). Note * that the resolution happens asynchronously and that the first call * may not immediately result in the FQN (but instead in a * human-readable IP address). * * @param client handle to the client making the request (for sending the reply) * @param af AF_INET or AF_INET6 * @param ip 'struct in_addr' or 'struct in6_addr' */ static void get_ip_as_string (struct GNUNET_SERVER_Client *client, int af, const void *ip) { struct IPCache *pos; struct IPCache *next; struct GNUNET_TIME_Absolute now; struct GNUNET_SERVER_TransmitContext *tc; size_t ip_len; switch (af) { case AF_INET: ip_len = sizeof (struct in_addr); break; case AF_INET6: ip_len = sizeof (struct in6_addr); break; default: GNUNET_assert (0); } now = GNUNET_TIME_absolute_get (); next = cache_head; while ( (NULL != (pos = next)) && ( (pos->af != af) || (pos->ip_len != ip_len) || (0 != memcmp (pos->ip, ip, ip_len))) ) { next = pos->next; if (GNUNET_TIME_absolute_get_duration (pos->last_request).rel_value_us < 60 * 60 * 1000 * 1000LL) { GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, pos); GNUNET_free_non_null (pos->addr); GNUNET_free (pos); continue; } } if (pos != NULL) { pos->last_request = now; if (GNUNET_TIME_absolute_get_duration (pos->last_request).rel_value_us < 60 * 60 * 1000 * 1000LL) { GNUNET_free_non_null (pos->addr); pos->addr = NULL; cache_resolve (pos); } } else { pos = GNUNET_malloc (sizeof (struct IPCache) + ip_len); pos->ip = &pos[1]; memcpy (&pos[1], ip, ip_len); pos->last_request = now; pos->last_refresh = now; pos->ip_len = ip_len; pos->af = af; GNUNET_CONTAINER_DLL_insert (cache_head, cache_tail, pos); cache_resolve (pos); } tc = GNUNET_SERVER_transmit_context_create (client); if (pos->addr != NULL) GNUNET_SERVER_transmit_context_append_data (tc, pos->addr, strlen (pos->addr) + 1, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); } #if HAVE_GETADDRINFO static int getaddrinfo_resolve (struct GNUNET_SERVER_TransmitContext *tc, const char *hostname, int af) { int s; struct addrinfo hints; struct addrinfo *result; struct addrinfo *pos; #ifdef WINDOWS /* Due to a bug, getaddrinfo will not return a mix of different families */ if (AF_UNSPEC == af) { int ret1; int ret2; ret1 = getaddrinfo_resolve (tc, hostname, AF_INET); ret2 = getaddrinfo_resolve (tc, hostname, AF_INET6); if ((ret1 == GNUNET_OK) || (ret2 == GNUNET_OK)) return GNUNET_OK; if ((ret1 == GNUNET_SYSERR) || (ret2 == GNUNET_SYSERR)) return GNUNET_SYSERR; return GNUNET_NO; } #endif memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; /* go for TCP */ if (0 != (s = getaddrinfo (hostname, NULL, &hints, &result))) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Could not resolve `%s' (%s): %s\n"), hostname, (af == AF_INET) ? "IPv4" : ((af == AF_INET6) ? "IPv6" : "any"), gai_strerror (s)); if ((s == EAI_BADFLAGS) || (s == EAI_MEMORY) #ifndef WINDOWS || (s == EAI_SYSTEM) #else || 1 #endif ) return GNUNET_NO; /* other function may still succeed */ return GNUNET_SYSERR; } if (result == NULL) return GNUNET_SYSERR; for (pos = result; pos != NULL; pos = pos->ai_next) { switch (pos->ai_family) { case AF_INET: GNUNET_SERVER_transmit_context_append_data (tc, &((struct sockaddr_in*) pos->ai_addr)->sin_addr, sizeof (struct in_addr), GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); break; case AF_INET6: GNUNET_SERVER_transmit_context_append_data (tc, &((struct sockaddr_in6*) pos->ai_addr)->sin6_addr, sizeof (struct in6_addr), GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); break; default: /* unsupported, skip */ break; } } freeaddrinfo (result); return GNUNET_OK; } #endif #if HAVE_GETHOSTBYNAME2 static int gethostbyname2_resolve (struct GNUNET_SERVER_TransmitContext *tc, const char *hostname, int af) { struct hostent *hp; int ret1; int ret2; #ifdef WINDOWS /* gethostbyname2() in plibc is a compat dummy that calls gethostbyname(). */ return GNUNET_NO; #endif if (af == AF_UNSPEC) { ret1 = gethostbyname2_resolve (tc, hostname, AF_INET); ret2 = gethostbyname2_resolve (tc, hostname, AF_INET6); if ((ret1 == GNUNET_OK) || (ret2 == GNUNET_OK)) return GNUNET_OK; if ((ret1 == GNUNET_SYSERR) || (ret2 == GNUNET_SYSERR)) return GNUNET_SYSERR; return GNUNET_NO; } hp = gethostbyname2 (hostname, af); if (hp == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Could not find IP of host `%s': %s\n"), hostname, hstrerror (h_errno)); return GNUNET_SYSERR; } GNUNET_assert (hp->h_addrtype == af); switch (af) { case AF_INET: GNUNET_assert (hp->h_length == sizeof (struct in_addr)); GNUNET_SERVER_transmit_context_append_data (tc, hp->h_addr_list[0], hp->h_length, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); break; case AF_INET6: GNUNET_assert (hp->h_length == sizeof (struct in6_addr)); GNUNET_SERVER_transmit_context_append_data (tc, hp->h_addr_list[0], hp->h_length, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); break; default: GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; } #endif #if HAVE_GETHOSTBYNAME static int gethostbyname_resolve (struct GNUNET_SERVER_TransmitContext *tc, const char *hostname) { struct hostent *hp; hp = GETHOSTBYNAME (hostname); if (hp == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Could not find IP of host `%s': %s\n"), hostname, hstrerror (h_errno)); return GNUNET_SYSERR; } if (hp->h_addrtype != AF_INET) { GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_assert (hp->h_length == sizeof (struct in_addr)); GNUNET_SERVER_transmit_context_append_data (tc, hp->h_addr_list[0], hp->h_length, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); return GNUNET_OK; } #endif /** * Convert a string to an IP address. * * @param client where to send the IP address * @param hostname the hostname to resolve * @param af AF_INET or AF_INET6; use AF_UNSPEC for "any" */ static void get_ip_from_hostname (struct GNUNET_SERVER_Client *client, const char *hostname, int af) { int ret; struct GNUNET_SERVER_TransmitContext *tc; tc = GNUNET_SERVER_transmit_context_create (client); ret = GNUNET_NO; #if HAVE_GETADDRINFO if (ret == GNUNET_NO) ret = getaddrinfo_resolve (tc, hostname, af); #endif #if HAVE_GETHOSTBYNAME2 if (ret == GNUNET_NO) ret = gethostbyname2_resolve (tc, hostname, af); #endif #if HAVE_GETHOSTBYNAME if ((ret == GNUNET_NO) && ((af == AF_UNSPEC) || (af == PF_INET))) gethostbyname_resolve (tc, hostname); #endif GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_RESOLVER_RESPONSE); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Handle GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { uint16_t msize; const struct GNUNET_RESOLVER_GetMessage *msg; const void *ip; uint16_t size; int direction; int af; msize = ntohs (message->size); if (msize < sizeof (struct GNUNET_RESOLVER_GetMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_RESOLVER_GetMessage *) message; size = msize - sizeof (struct GNUNET_RESOLVER_GetMessage); direction = ntohl (msg->direction); af = ntohl (msg->af); if (direction == GNUNET_NO) { /* IP from hostname */ const char *hostname; hostname = (const char *) &msg[1]; if (hostname[size - 1] != '\0') { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resolver asked to look up `%s'.\n", hostname); get_ip_from_hostname (client, hostname, af); return; } ip = &msg[1]; switch (af) { case AF_INET: if (size != sizeof (struct in_addr)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } break; case AF_INET6: if (size != sizeof (struct in6_addr)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } break; default: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } { char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resolver asked to look up IP address `%s'.\n", inet_ntop (af, ip, buf, sizeof (buf))); } get_ip_as_string (client, af, ip); } /** * Process resolver requests. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_get, NULL, GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, 0}, {NULL, NULL, 0, 0} }; GNUNET_SERVER_add_handlers (server, handlers); } /** * The main function for the resolver service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { struct IPCache *pos; int ret; ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "resolver", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; while (NULL != (pos = cache_head)) { GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, pos); GNUNET_free_non_null (pos->addr); GNUNET_free (pos); } return ret; } #ifdef LINUX #include /** * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ void __attribute__ ((constructor)) GNUNET_ARM_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); malloc_trim (0); } #endif /* end of gnunet-service-resolver.c */ gnunet-0.10.1/src/util/getopt.c0000644000175000017500000007221112225777501013237 00000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. NOTE: The canonical source of this file is maintained with the GNU C Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. This code was heavily modified for GNUnet. Copyright (C) 2006 Christian Grothoff */ /** * @file util/getopt.c * @brief GNU style option parsing * * TODO: get rid of statics (make reentrant) and * replace main GNU getopt parser with one that * actually fits our API. */ #include "platform.h" #include "gnunet_util_lib.h" #ifdef VMS #include #if HAVE_STRING_H - 0 #include #endif #endif #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #if defined (WIN32) && !defined (__CYGWIN32__) /* It's not Unix, really. See? Capital letters. */ #include #define getpid() GetCurrentProcessId() #endif #ifndef _ /* This is for other GNU distributions with internationalized messages. When compiling libc, the _ macro is predefined. */ #ifdef HAVE_LIBINTL_H #include #define _(msgid) gettext (msgid) #else #define _(msgid) (msgid) #endif #endif /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct GNoption' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `GNoptarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct GNoption { const char *name; /* has_arg can't be an enum because some compilers complain about * type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ static char *GNoptarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns -1, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `GNoptind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* 1003.2 says this must be 1 before any call. */ static int GNoptind = 1; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We GNUNET_CRYPTO_random_permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect GNoptions and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `GNoptind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ char * getenv (); static char * my_index (const char *str, int chr) { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ #if !defined (__STDC__) || !__STDC__ /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); #endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; #define SWAP_FLAGS(ch1, ch2) /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,GNoptind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ #if defined (__STDC__) && __STDC__ static void exchange (char **); #endif static void exchange (char **argv) { int bottom = first_nonopt; int middle = last_nonopt; int top = GNoptind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. * That puts the shorter segment into the right place. * It leaves the longer segment in the right place overall, * but it consists of two parts that need to be swapped next. */ while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; SWAP_FLAGS (bottom + i, middle + i); } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (GNoptind - last_nonopt); last_nonopt = GNoptind; } /* Initialize the internal data when the first call is made. */ #if defined (__STDC__) && __STDC__ static const char * _getopt_initialize (int, char *const *, const char *); #endif static const char * _getopt_initialize (int argc, char *const *argv, const char *optstring) { /* Start processing options with ARGV-element 1 (since ARGV-element 0 * is the program name); the sequence of previously skipped * non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = GNoptind; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `GNoptind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns -1. Then `GNoptind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `GNopterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `GNoptarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `GNoptarg', otherwise `GNoptarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we GNUNET_CRYPTO_random_permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct GNoption' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ static int GN_getopt_internal (int argc, char *const *argv, const char *optstring, const struct GNoption *longopts, int *longind, int long_only) { static int __getopt_initialized = 0; static int GNopterr = 1; GNoptarg = NULL; if (GNoptind == 0 || !__getopt_initialized) { if (GNoptind == 0) GNoptind = 1; /* Don't scan ARGV[0], the program name. */ optstring = _getopt_initialize (argc, argv, optstring); __getopt_initialized = 1; } /* Test whether ARGV[GNoptind] points to a non-option argument. * Either it does not have option syntax, or there is an environment flag * from the shell indicating it is not an option. The later information * is only used when the used in the GNU libc. */ #define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0') if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ /* Give FIRST_NONOPT & LAST_NONOPT rational values if GNoptind has been * moved back by the user (who may also have changed the arguments). */ if (last_nonopt > GNoptind) last_nonopt = GNoptind; if (first_nonopt > GNoptind) first_nonopt = GNoptind; if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, * exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != GNoptind) exchange ((char **) argv); else if (last_nonopt != GNoptind) first_nonopt = GNoptind; /* Skip any additional non-options * and extend the range of non-options previously skipped. */ while (GNoptind < argc && NONOPTION_P) GNoptind++; last_nonopt = GNoptind; } /* The special ARGV-element `--' means premature end of options. * Skip it like a null option, * then exchange with previous non-options as if it were an option, * then skip everything else like a non-option. */ if (GNoptind != argc && !strcmp (argv[GNoptind], "--")) { GNoptind++; if (first_nonopt != last_nonopt && last_nonopt != GNoptind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = GNoptind; last_nonopt = argc; GNoptind = argc; } /* If we have done all the ARGV-elements, stop the scan * and back over any non-options that we skipped and permuted. */ if (GNoptind == argc) { /* Set the next-arg-index to point at the non-options * that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) GNoptind = first_nonopt; return -1; } /* If we have come to a non-option and did not permute it, * either stop the scan or describe it to the caller and pass it by. */ if (NONOPTION_P) { if (ordering == REQUIRE_ORDER) return -1; GNoptarg = argv[GNoptind++]; return 1; } /* We have found another option-ARGV-element. * Skip the initial punctuation. */ nextchar = (argv[GNoptind] + 1 + (longopts != NULL && argv[GNoptind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. * * If long_only and the ARGV-element has the form "-f", where f is * a valid short option, don't consider it an abbreviated form of * a long option that starts with f. Otherwise there would be no * way to give the -f short option. * * On the other hand, if there's a long option "fubar" and * the ARGV-element is "-fu", do consider that an abbreviation of * the long option, just like "--fu", and not "-f" with arg "u". * * This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[GNoptind][1] == '-' || (long_only && (argv[GNoptind][2] || !my_index (optstring, argv[GNoptind][1]))))) { char *nameend; const struct GNoption *p; const struct GNoption *pfound = NULL; int exact = 0; int ambig = 0; int indfound = -1; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match * or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == (unsigned int) strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (GNopterr) FPRINTF (stderr, _("%s: option `%s' is ambiguous\n"), argv[0], argv[GNoptind]); nextchar += strlen (nextchar); GNoptind++; return '?'; } if (pfound != NULL) { option_index = indfound; GNoptind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't * allow it to be used on enums. */ if (pfound->has_arg) GNoptarg = nameend + 1; else { if (GNopterr) { if (argv[GNoptind - 1][1] == '-') /* --option */ FPRINTF (stderr, _("%s: option `--%s' does not allow an argument\n"), argv[0], pfound->name); else /* +option or -option */ FPRINTF (stderr, _("%s: option `%c%s' does not allow an argument\n"), argv[0], argv[GNoptind - 1][0], pfound->name); } nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (GNoptind < argc) { GNoptarg = argv[GNoptind++]; } else { if (GNopterr) { FPRINTF (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[GNoptind - 1]); } nextchar += strlen (nextchar); return (optstring[0] == ':') ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, * or the option starts with '--' or is not a valid short * option, then it's an error. * Otherwise interpret it as a short option. */ if (!long_only || argv[GNoptind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (GNopterr) { if (argv[GNoptind][1] == '-') /* --option */ FPRINTF (stderr, _("%s: unrecognized option `--%s'\n"), argv[0], nextchar); else /* +option or -option */ FPRINTF (stderr, _("%s: unrecognized option `%c%s'\n"), argv[0], argv[GNoptind][0], nextchar); } nextchar = (char *) ""; GNoptind++; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `GNoptind' when we start to process its last character. */ if (*nextchar == '\0') ++GNoptind; if (temp == NULL || c == ':') { if (GNopterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ FPRINTF (stderr, _("%s: illegal option -- %c\n"), argv[0], c); else FPRINTF (stderr, _("%s: invalid option -- %c\n"), argv[0], c); } return '?'; } /* Convenience. Treat POSIX -W foo same as long option --foo */ if (temp[0] == 'W' && temp[1] == ';') { char *nameend; const struct GNoption *p; const struct GNoption *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; /* This is an option that requires an argument. */ if (*nextchar != '\0') { GNoptarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, * we must advance to the next element now. */ GNoptind++; } else if (GNoptind == argc) { if (GNopterr) { /* 1003.2 specifies the format of this message. */ FPRINTF (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } if (optstring[0] == ':') c = ':'; else c = '?'; return c; } else /* We already incremented `GNoptind' once; * increment it again when taking next ARGV-elt as argument. */ GNoptarg = argv[GNoptind++]; /* GNoptarg is now the argument, see if it's in the * table of longopts. */ for (nextchar = nameend = GNoptarg; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match * or abbreviated matches. */ if (longopts != NULL) for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if ((unsigned int) (nameend - nextchar) == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (GNopterr) FPRINTF (stderr, _("%s: option `-W %s' is ambiguous\n"), argv[0], argv[GNoptind]); nextchar += strlen (nextchar); GNoptind++; return '?'; } if (pfound != NULL) { option_index = indfound; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't * allow it to be used on enums. */ if (pfound->has_arg) GNoptarg = nameend + 1; else { if (GNopterr) FPRINTF (stderr, _("%s: option `-W %s' does not allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (GNoptind < argc) GNoptarg = argv[GNoptind++]; else { if (GNopterr) FPRINTF (stderr, _("%s: option `%s' requires an argument\n"), argv[0], argv[GNoptind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } nextchar = NULL; return 'W'; /* Let the application handle it. */ } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { GNoptarg = nextchar; GNoptind++; } else GNoptarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { GNoptarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, * we must advance to the next element now. */ GNoptind++; } else if (GNoptind == argc) { if (GNopterr) { /* 1003.2 specifies the format of this message. */ FPRINTF (stderr, _("%s: option requires an argument -- %c\n"), argv[0], c); } if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `GNoptind' once; * increment it again when taking next ARGV-elt as argument. */ GNoptarg = argv[GNoptind++]; nextchar = NULL; } } return c; } } static int GNgetopt_long (int argc, char *const *argv, const char *options, const struct GNoption *long_options, int *opt_index) { return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* ******************** now the GNUnet specific modifications... ********************* */ /** * Parse the command line. * * @param binaryOptions Name of application with option summary * @param allOptions defined options and handlers * @param argc number of arguments * @param argv actual arguments * @return index into argv with first non-option * argument, or -1 on error */ int GNUNET_GETOPT_run (const char *binaryOptions, const struct GNUNET_GETOPT_CommandLineOption *allOptions, unsigned int argc, char *const *argv) { struct GNoption *long_options; struct GNUNET_GETOPT_CommandLineProcessorContext clpc; int count; int i; char *shorts; int spos; int cont; int c; GNUNET_assert (argc > 0); GNoptind = 0; clpc.binaryName = argv[0]; clpc.binaryOptions = binaryOptions; clpc.allOptions = allOptions; clpc.argv = argv; clpc.argc = argc; count = 0; while (allOptions[count].name != NULL) count++; long_options = GNUNET_malloc (sizeof (struct GNoption) * (count + 1)); shorts = GNUNET_malloc (count * 2 + 1); spos = 0; for (i = 0; i < count; i++) { long_options[i].name = allOptions[i].name; long_options[i].has_arg = allOptions[i].require_argument; long_options[i].flag = NULL; long_options[i].val = allOptions[i].shortName; shorts[spos++] = allOptions[i].shortName; if (allOptions[i].require_argument != 0) shorts[spos++] = ':'; } long_options[count].name = NULL; long_options[count].has_arg = 0; long_options[count].flag = NULL; long_options[count].val = '\0'; shorts[spos] = '\0'; cont = GNUNET_OK; /* main getopt loop */ while (cont == GNUNET_OK) { int option_index = 0; c = GNgetopt_long (argc, argv, shorts, long_options, &option_index); if (c == GNUNET_SYSERR) break; /* No more flags to process */ for (i = 0; i < count; i++) { clpc.currentArgument = GNoptind - 1; if ((char) c == allOptions[i].shortName) { cont = allOptions[i].processor (&clpc, allOptions[i].scls, allOptions[i].name, GNoptarg); break; } } if (i == count) { FPRINTF (stderr, _("Use %s to get a list of options.\n"), "--help"); cont = GNUNET_SYSERR; } } GNUNET_free (shorts); GNUNET_free (long_options); if (cont != GNUNET_OK) { return cont; } return GNoptind; } /* end of getopt.c */ gnunet-0.10.1/src/util/signal.c0000644000175000017500000000615312261236531013205 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/signal.c * @brief code for installing and uninstalling signal handlers * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) struct GNUNET_SIGNAL_Context { struct GNUNET_SIGNAL_Context *next; struct GNUNET_SIGNAL_Context *prev; int sig; GNUNET_SIGNAL_Handler method; #ifndef MINGW struct sigaction oldsig; #endif }; static struct GNUNET_SIGNAL_Context *sc_head; static struct GNUNET_SIGNAL_Context *sc_tail; #ifdef WINDOWS GNUNET_SIGNAL_Handler w32_sigchld_handler = NULL; #endif struct GNUNET_SIGNAL_Context * GNUNET_SIGNAL_handler_install (int signum, GNUNET_SIGNAL_Handler handler) { struct GNUNET_SIGNAL_Context *ret; #ifndef MINGW struct sigaction sig; #endif ret = GNUNET_new (struct GNUNET_SIGNAL_Context); ret->sig = signum; ret->method = handler; #ifndef MINGW memset (&sig, 0, sizeof (sig)); sig.sa_handler = (void *) handler; sigemptyset (&sig.sa_mask); #ifdef SA_INTERRUPT sig.sa_flags = SA_INTERRUPT; /* SunOS */ #else sig.sa_flags = SA_RESTART; #endif sigaction (signum, &sig, &ret->oldsig); #else if (signum == GNUNET_SIGCHLD) w32_sigchld_handler = handler; else { __p_sig_fn_t sigret = signal (signum, (__p_sig_fn_t) handler); if (sigret == SIG_ERR) { LOG (GNUNET_ERROR_TYPE_WARNING, _("signal (%d, %p) returned %d.\n"), signum, handler, sigret); } } #endif GNUNET_CONTAINER_DLL_insert_tail (sc_head, sc_tail, ret); return ret; } void GNUNET_SIGNAL_handler_uninstall (struct GNUNET_SIGNAL_Context *ctx) { #ifndef MINGW struct sigaction sig; sigemptyset (&sig.sa_mask); sigaction (ctx->sig, &ctx->oldsig, &sig); #endif GNUNET_CONTAINER_DLL_remove (sc_head, sc_tail, ctx); GNUNET_free (ctx); } /** * Raise the given signal by calling the installed signal handlers. This will * not use the @em raise() system call but only calls the handlers registered * through GNUNET_SIGNAL_handler_install(). * * @param sig the signal to raise */ void GNUNET_SIGNAL_raise (const int sig) { struct GNUNET_SIGNAL_Context *ctx; for (ctx = sc_head; NULL != ctx; ctx = ctx->next) { if (sig != ctx->sig) continue; if (NULL == ctx->method) continue; ctx->method (); } } gnunet-0.10.1/src/util/test_connection_addressing.c0000644000175000017500000001240712225777501017337 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_connection_addressing.c * @brief tests for connection.c */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 12435 static struct GNUNET_CONNECTION_Handle *csock; static struct GNUNET_CONNECTION_Handle *asock; static struct GNUNET_CONNECTION_Handle *lsock; static size_t sofar; static struct GNUNET_NETWORK_Handle *ls; /** * Create and initialize a listen socket for the server. * * @return NULL on error, otherwise the listen socket */ static struct GNUNET_NETWORK_Handle * open_listen_socket () { const static int on = 1; struct sockaddr_in sa; struct GNUNET_NETWORK_Handle *desc; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); desc = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); GNUNET_assert (desc != 0); if (GNUNET_NETWORK_socket_setsockopt (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); if (GNUNET_OK != GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa, sizeof (sa))) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "bind"); GNUNET_assert (0); } GNUNET_NETWORK_socket_listen (desc, 5); return desc; } static void receive_check (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode) { int *ok = cls; GNUNET_assert (buf != NULL); /* no timeout */ if (0 == memcmp (&"Hello World"[sofar], buf, available)) sofar += available; if (sofar < 12) { GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); } else { *ok = 0; GNUNET_CONNECTION_destroy (csock); GNUNET_CONNECTION_destroy (asock); } } static void run_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { void *addr; size_t alen; struct sockaddr_in *v4; struct sockaddr_in expect; asock = GNUNET_CONNECTION_create_from_accept (NULL, NULL, ls); GNUNET_assert (asock != NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONNECTION_check (asock)); GNUNET_assert (GNUNET_OK == GNUNET_CONNECTION_get_address (asock, &addr, &alen)); GNUNET_assert (alen == sizeof (struct sockaddr_in)); v4 = addr; memset (&expect, 0, sizeof (expect)); #if HAVE_SOCKADDR_IN_SIN_LEN expect.sin_len = sizeof (expect); #endif expect.sin_family = AF_INET; expect.sin_port = v4->sin_port; expect.sin_addr.s_addr = htonl (INADDR_LOOPBACK); GNUNET_assert (0 == memcmp (&expect, v4, alen)); GNUNET_free (addr); GNUNET_CONNECTION_destroy (lsock); GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); } static size_t make_hello (void *cls, size_t size, void *buf) { GNUNET_assert (size >= 12); strcpy ((char *) buf, "Hello World"); return 12; } static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_in v4; ls = open_listen_socket (); lsock = GNUNET_CONNECTION_create_from_existing (ls); GNUNET_assert (lsock != NULL); #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (v4); #endif v4.sin_family = AF_INET; v4.sin_port = htons (PORT); v4.sin_addr.s_addr = htonl (INADDR_LOOPBACK); csock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, (const struct sockaddr *) &v4, sizeof (v4)); GNUNET_assert (csock != NULL); GNUNET_assert (NULL != GNUNET_CONNECTION_notify_transmit_ready (csock, 12, GNUNET_TIME_UNIT_SECONDS, &make_hello, NULL)); GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, ls, &run_accept, cls); } int main (int argc, char *argv[]) { int ok; GNUNET_log_setup ("test_connection_addressing", "WARNING", NULL); ok = 1; GNUNET_SCHEDULER_run (&task, &ok); return ok; } /* end of test_connection_addressing.c */ gnunet-0.10.1/src/util/peer.c0000644000175000017500000001362512255010512012655 00000000000000/* This file is part of GNUnet (C) 2006, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** * @file util/peer.c * @brief peer-ID table that assigns integer IDs to peer-IDs to save memory * @author Christian Grothoff */ #include "platform.h" #include "gnunet_peer_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) struct PeerEntry { /** * The identifier itself */ struct GNUNET_PeerIdentity id; /** * Short version of the identifier; if the RC==0, then index of next * free slot in table, otherwise equal to this slot in the table. */ GNUNET_PEER_Id pid; /** * Reference counter, 0 if this slot is not used. */ unsigned int rc; }; /** * Table with our interned peer IDs. */ static struct PeerEntry **table; /** * Peermap of PeerIdentities to "struct PeerEntry" * (for fast lookup). NULL until the library * is actually being used. */ static struct GNUNET_CONTAINER_MultiPeerMap *map; /** * Size of the "table". */ static unsigned int size; /** * Index of the beginning of the free list in the table; set to "size" * if no slots are free in the table. */ static unsigned int free_list_start; /** * Search for a peer identity. The reference counter is not changed. * * @param pid identity to find * @return the interned identity or 0. */ GNUNET_PEER_Id GNUNET_PEER_search (const struct GNUNET_PeerIdentity *pid) { struct PeerEntry *e; if (NULL == pid) return 0; if (NULL == map) return 0; e = GNUNET_CONTAINER_multipeermap_get (map, pid); if (NULL == e) return 0; GNUNET_assert (e->rc > 0); return e->pid; } /** * Intern an peer identity. If the identity is already known, its * reference counter will be increased by one. * * @param pid identity to intern * @return the interned identity. */ GNUNET_PEER_Id GNUNET_PEER_intern (const struct GNUNET_PeerIdentity *pid) { GNUNET_PEER_Id ret; struct PeerEntry *e; unsigned int i; if (NULL == pid) return 0; if (NULL == map) map = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_YES); e = GNUNET_CONTAINER_multipeermap_get (map, pid); if (NULL != e) { GNUNET_assert (e->rc > 0); e->rc++; return e->pid; } ret = free_list_start; if (ret == size) { GNUNET_array_grow (table, size, size + 16); for (i = ret; i < size; i++) { table[i] = GNUNET_new (struct PeerEntry); table[i]->pid = i + 1; } } if (0 == ret) { table[0]->pid = 0; table[0]->rc = 1; ret = 1; } GNUNET_assert (ret < size); GNUNET_assert (0 == table[ret]->rc); free_list_start = table[ret]->pid; table[ret]->id = *pid; table[ret]->rc = 1; table[ret]->pid = ret; GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (map, &table[ret]->id, table[ret], GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return ret; } /** * Decrement multiple RCs of peer identities by one. * * @param ids array of PIDs to decrement the RCs of * @param count size of the ids array */ void GNUNET_PEER_decrement_rcs (const GNUNET_PEER_Id *ids, unsigned int count) { int i; GNUNET_PEER_Id id; if (0 == count) return; for (i = count - 1; i >= 0; i--) { id = ids[i]; if (0 == id) continue; GNUNET_assert (id < size); GNUNET_assert (table[id]->rc > 0); table[id]->rc--; if (0 == table[id]->rc) { GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (map, &table[id]->id, table[id])); table[id]->pid = free_list_start; free_list_start = id; } } } /** * Change the reference counter of an interned PID. * * @param id identity to change the RC of * @param delta how much to change the RC */ void GNUNET_PEER_change_rc (GNUNET_PEER_Id id, int delta) { if (0 == id) return; GNUNET_assert (id < size); GNUNET_assert (table[id]->rc > 0); GNUNET_assert ((delta >= 0) || (table[id]->rc >= -delta)); table[id]->rc += delta; if (0 == table[id]->rc) { GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (map, &table[id]->id, table[id])); table[id]->pid = free_list_start; free_list_start = id; } } /** * Convert an interned PID to a normal peer identity. * * @param id interned PID to convert * @param pid where to write the normal peer identity */ void GNUNET_PEER_resolve (GNUNET_PEER_Id id, struct GNUNET_PeerIdentity *pid) { if (0 == id) { memset (pid, 0, sizeof (struct GNUNET_PeerIdentity)); return; } GNUNET_assert (id < size); GNUNET_assert (table[id]->rc > 0); *pid = table[id]->id; } /** * Convert an interned PID to a normal peer identity. * * @param id interned PID to convert * @return pointer to peer identity, valid as long 'id' is valid */ const struct GNUNET_PeerIdentity * GNUNET_PEER_resolve2 (GNUNET_PEER_Id id) { return &table[id]->id; } /* end of peer.c */ gnunet-0.10.1/src/util/test_connection.c0000644000175000017500000001235412225777501015135 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_connection.c * @brief tests for connection.c */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 12435 static struct GNUNET_CONNECTION_Handle *csock; static struct GNUNET_CONNECTION_Handle *asock; static struct GNUNET_CONNECTION_Handle *lsock; static size_t sofar; static struct GNUNET_NETWORK_Handle *ls; static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Create and initialize a listen socket for the server. * * @return -1 on error, otherwise the listen socket */ static struct GNUNET_NETWORK_Handle * open_listen_socket () { const static int on = 1; struct sockaddr_in sa; struct GNUNET_NETWORK_Handle *desc; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_port = htons (PORT); sa.sin_family = AF_INET; desc = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0); GNUNET_assert (desc != NULL); if (GNUNET_NETWORK_socket_setsockopt (desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); GNUNET_assert (GNUNET_OK == GNUNET_NETWORK_socket_bind (desc, (const struct sockaddr *) &sa, sizeof (sa))); GNUNET_NETWORK_socket_listen (desc, 5); return desc; } static void receive_check (void *cls, const void *buf, size_t available, const struct sockaddr *addr, socklen_t addrlen, int errCode) { int *ok = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive validates incoming data\n"); GNUNET_assert (buf != NULL); /* no timeout */ if (0 == memcmp (&"Hello World"[sofar], buf, available)) sofar += available; if (sofar < 12) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive needs more data\n"); GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive closes accepted socket\n"); *ok = 0; GNUNET_CONNECTION_destroy (asock); GNUNET_CONNECTION_destroy (csock); } } static void run_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test accepts connection\n"); asock = GNUNET_CONNECTION_create_from_accept (NULL, NULL, ls); GNUNET_assert (asock != NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONNECTION_check (asock)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test destroys listen socket\n"); GNUNET_CONNECTION_destroy (lsock); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test asks to receive on accepted socket\n"); GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); } static size_t make_hello (void *cls, size_t size, void *buf) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test prepares to transmit on connect socket\n"); GNUNET_assert (size >= 12); strcpy ((char *) buf, "Hello World"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test destroys client socket\n"); return 12; } static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { ls = open_listen_socket (); lsock = GNUNET_CONNECTION_create_from_existing (ls); GNUNET_assert (lsock != NULL); csock = GNUNET_CONNECTION_create_from_connect (cfg, "localhost", PORT); GNUNET_assert (csock != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test asks for write notification\n"); GNUNET_assert (NULL != GNUNET_CONNECTION_notify_transmit_ready (csock, 12, GNUNET_TIME_UNIT_SECONDS, &make_hello, NULL)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test prepares to accept\n"); GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, ls, &run_accept, cls); } int main (int argc, char *argv[]) { int ok; GNUNET_log_setup ("test_connection", "WARNING", NULL); ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); GNUNET_SCHEDULER_run (&task, &ok); GNUNET_CONFIGURATION_destroy (cfg); return ok; } /* end of test_connection.c */ gnunet-0.10.1/src/util/test_speedup.c0000644000175000017500000000626712225777501014451 00000000000000/* This file is part of GNUnet. (C) 2011-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_speedup.c * @brief testcase for speedup.c */ #include "platform.h" #include "gnunet_util_lib.h" /** * Start time of the testcase */ static struct GNUNET_TIME_Absolute start; /** * End-time of the testcase (affected by speed-up) */ static struct GNUNET_TIME_Absolute end; /** * Number of cycles we have spent in 'run'. */ static unsigned int cycles; /** * Main task that is scheduled with the speed-up. * * @param cls NULL * @param tc scheduler context, unused */ static void run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cycles++; fprintf (stderr, "..%u", cycles); if (cycles <= 5) { GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &run, NULL); return; } end = GNUNET_TIME_absolute_get(); fprintf (stderr, "\n"); fflush(stdout); } /** * */ static void check (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle * cfg) { fprintf (stderr, "0"); fflush(stdout); GNUNET_SCHEDULER_add_now(&run, NULL); } int main (int argc, char *argv[]) { static char *const argvn[] = { "test-speedup", "-c", "test_speedup_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; time_t start_real; time_t end_real; struct GNUNET_TIME_Relative delta; start_real = time (NULL); start = GNUNET_TIME_absolute_get(); GNUNET_PROGRAM_run ((sizeof (argvn) / sizeof (char *)) - 1, argvn, "test-speedup", "nohelp", options, &check, NULL); end_real = time (NULL); delta = GNUNET_TIME_absolute_get_difference (start, end); if (delta.rel_value_us > ((end_real - start_real) * 1500LL * 1000LL)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Execution time in GNUnet time: %s\n", GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Execution time in system time: %llu ms\n", (unsigned long long) ((end_real - start_real) * 1000LL)); return 0; } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Execution time in GNUnet time: %s\n", GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Execution time in system time: %llu ms\n", (unsigned long long) ((end_real - start_real) * 1000LL)); return 1; } /* end of test_speedup.c */ gnunet-0.10.1/src/util/test_server.c0000644000175000017500000001421612225777501014303 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_server.c * @brief tests for server.c */ #include "platform.h" #include "gnunet_util_lib.h" #define PORT 12435 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) #define MY_TYPE 128 #define MY_TYPE2 129 static struct GNUNET_SERVER_Handle *server; static struct GNUNET_CLIENT_Connection *cc; static struct GNUNET_SERVER_Client *argclient; static struct GNUNET_CONFIGURATION_Handle *cfg; static int ok; static void finish_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_assert (ok == 6); ok = 0; GNUNET_SERVER_destroy (server); GNUNET_CLIENT_disconnect (cc); GNUNET_CONFIGURATION_destroy (cfg); } static void recv_fin_cb (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_assert (ok == 5); ok = 6; GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_SCHEDULER_add_now (&finish_up, NULL); } static void first_reply_handler (void *cls, const struct GNUNET_MessageHeader *msg) { GNUNET_assert (ok == 4); ok = 5; GNUNET_SERVER_receive_done (argclient, GNUNET_OK); GNUNET_SERVER_client_drop (argclient); argclient = NULL; } static size_t reply_msg (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader msg; GNUNET_assert (ok == 3); ok = 4; GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); msg.type = htons (MY_TYPE); msg.size = htons (sizeof (struct GNUNET_MessageHeader)); memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader)); return sizeof (struct GNUNET_MessageHeader); } static void recv_cb (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_assert (ok == 2); ok = 3; argclient = client; GNUNET_SERVER_client_keep (argclient); GNUNET_assert (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size)); GNUNET_assert (MY_TYPE == ntohs (message->type)); GNUNET_assert (NULL != GNUNET_SERVER_notify_transmit_ready (client, ntohs (message->size), TIMEOUT, &reply_msg, NULL)); } static struct GNUNET_SERVER_MessageHandler handlers[] = { {&recv_cb, NULL, MY_TYPE, sizeof (struct GNUNET_MessageHeader)}, {&recv_fin_cb, NULL, MY_TYPE2, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; static size_t transmit_second_message (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader msg; GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); msg.type = htons (MY_TYPE2); msg.size = htons (sizeof (struct GNUNET_MessageHeader)); memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader)); return sizeof (struct GNUNET_MessageHeader); } static size_t transmit_initial_message (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader msg; GNUNET_assert (ok == 1); ok = 2; GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); msg.type = htons (MY_TYPE); msg.size = htons (sizeof (struct GNUNET_MessageHeader)); memcpy (buf, &msg, sizeof (struct GNUNET_MessageHeader)); GNUNET_assert (NULL != GNUNET_CLIENT_notify_transmit_ready (cc, sizeof (struct GNUNET_MessageHeader), TIMEOUT, GNUNET_YES, &transmit_second_message, NULL)); GNUNET_CLIENT_receive (cc, &first_reply_handler, NULL, TIMEOUT); return sizeof (struct GNUNET_MessageHeader); } static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct sockaddr_in sa; struct sockaddr *sap[2]; socklen_t slens[2]; sap[0] = (struct sockaddr *) &sa; slens[0] = sizeof (sa); sap[1] = NULL; slens[1] = 0; memset (&sa, 0, sizeof (sa)); #if HAVE_SOCKADDR_IN_SIN_LEN sa.sin_len = sizeof (sa); #endif sa.sin_family = AF_INET; sa.sin_port = htons (PORT); server = GNUNET_SERVER_create (NULL, NULL, sap, slens, TIMEOUT, GNUNET_NO); GNUNET_assert (server != NULL); GNUNET_SERVER_add_handlers (server, handlers); cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_number (cfg, "test-server", "PORT", PORT); GNUNET_CONFIGURATION_set_value_string (cfg, "test-server", "HOSTNAME", "localhost"); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", "localhost"); cc = GNUNET_CLIENT_connect ("test-server", cfg); GNUNET_assert (cc != NULL); GNUNET_assert (NULL != GNUNET_CLIENT_notify_transmit_ready (cc, sizeof (struct GNUNET_MessageHeader), TIMEOUT, GNUNET_YES, &transmit_initial_message, NULL)); } int main (int argc, char *argv[]) { GNUNET_log_setup ("test_server", "WARNING", NULL); ok = 1; GNUNET_SCHEDULER_run (&task, &ok); return ok; } /* end of test_server.c */ gnunet-0.10.1/src/util/resolver.h0000644000175000017500000000367512225777503013615 00000000000000/* This file is part of GNUnet. (C) 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file util/resolver.h */ #ifndef RESOLVER_H #define RESOLVER_H #include "gnunet_common.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Request for the resolver. Followed by either the "struct sockaddr" * or the 0-terminated hostname. * * The response will be one or more messages of type * RESOLVER_RESPONSE, each with the message header immediately * followed by the requested data (0-terminated hostname or struct * in[6]_addr, depending on direction). The last RESOLVER_RESPONSE * will just be a header without any data (used to indicate the end of * the list). */ struct GNUNET_RESOLVER_GetMessage { /** * Type: GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST */ struct GNUNET_MessageHeader header; /** * GNUNET_YES to get hostname from IP, * GNUNET_NO to get IP from hostname. */ int32_t direction GNUNET_PACKED; /** * Address family to use (AF_INET, AF_INET6 or AF_UNSPEC). */ int32_t af GNUNET_PACKED; /* followed by 0-terminated string for A/AAAA-lookup or by 'struct in_addr' / 'struct in6_addr' for reverse lookup */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/util/gnunet-scrypt.c0000644000175000017500000002234512263724143014556 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/gnunet-scrypt.c * @brief tool to manipulate SCRYPT proofs of work. * largely stolen from gnunet-peerinfo.c and gnunet-service-nse.c * @author Bart Polot */ #include "platform.h" #include "gnunet_util_lib.h" #include /** * Amount of work required (W-bit collisions) for NSE proofs, in collision-bits. */ static unsigned long long nse_work_required; /** * Interval between proof find runs. */ static struct GNUNET_TIME_Relative proof_find_delay; static struct GNUNET_CRYPTO_EddsaPublicKey pub; uint64_t proof; GNUNET_SCHEDULER_TaskIdentifier proof_task; const struct GNUNET_CONFIGURATION_Handle *cfg; char *pkfn; char *pwfn; /** * Write our current proof to disk. */ static void write_proof () { if (sizeof (proof) != GNUNET_DISK_fn_write (pwfn, &proof, sizeof (proof), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", proof); } /** * Calculate the 'proof-of-work' hash (an expensive hash). * * @param buf data to hash * @param buf_len number of bytes in @a buf * @param result where to write the resulting hash */ static void pow_hash (const void *buf, size_t buf_len, struct GNUNET_HashCode *result) { GNUNET_break (0 == gcry_kdf_derive (buf, buf_len, GCRY_KDF_SCRYPT, 1 /* subalgo */, "gnunet-proof-of-work", strlen ("gnunet-proof-of-work"), 2 /* iterations; keep cost of individual op small */, sizeof (struct GNUNET_HashCode), result)); } /** * Count the leading zeroes in hash. * * @param hash to count leading zeros in * @return the number of leading zero bits. */ static unsigned int count_leading_zeroes (const struct GNUNET_HashCode *hash) { unsigned int hash_count; hash_count = 0; while (0 == GNUNET_CRYPTO_hash_get_bit (hash, hash_count)) hash_count++; return hash_count; } /** * Find our proof of work. * * @param cls closure (unused) * @param tc task context */ static void find_proof (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { #define ROUND_SIZE 10 uint64_t counter; char buf[sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) + sizeof (uint64_t)] GNUNET_ALIGN; struct GNUNET_HashCode result; unsigned int i; struct GNUNET_TIME_Absolute timestamp; struct GNUNET_TIME_Relative elapsed; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) { write_proof (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got Proof of Work %llu\n", proof); proof_task = GNUNET_SCHEDULER_NO_TASK; memcpy (&buf[sizeof (uint64_t)], &pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); i = 0; counter = proof; timestamp = GNUNET_TIME_absolute_get (); while ((counter != UINT64_MAX) && (i < ROUND_SIZE)) { memcpy (buf, &counter, sizeof (uint64_t)); pow_hash (buf, sizeof (buf), &result); if (nse_work_required <= count_leading_zeroes (&result)) { proof = counter; FPRINTF (stdout, "Proof of work found: %llu!\n", (unsigned long long) proof); write_proof (); return; } counter++; i++; } elapsed = GNUNET_TIME_absolute_get_duration (timestamp); elapsed = GNUNET_TIME_relative_divide (elapsed, ROUND_SIZE); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current: %llu [%s/proof]\n", (unsigned long long) counter, GNUNET_STRINGS_relative_time_to_string (elapsed, 0)); if (proof / (100 * ROUND_SIZE) < counter / (100 * ROUND_SIZE)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing proofs currently at %llu\n", (unsigned long long) counter); /* remember progress every 100 rounds */ proof = counter; write_proof (); } else { proof = counter; } proof_task = GNUNET_SCHEDULER_add_delayed_with_priority (proof_find_delay, GNUNET_SCHEDULER_PRIORITY_IDLE, &find_proof, NULL); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { struct GNUNET_CRYPTO_EddsaPrivateKey *pk; cfg = config; /* load proof of work */ if (NULL == pwfn) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "PROOFFILE", &pwfn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "PROOFFILE"); GNUNET_SCHEDULER_shutdown (); return; } } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Proof of Work file: %s\n", pwfn); if (GNUNET_YES != GNUNET_DISK_file_test (pwfn) || sizeof (proof) != GNUNET_DISK_fn_read (pwfn, &proof, sizeof (proof))) proof = 0; /* load private key */ if (NULL == pkfn) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &pkfn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "PEER", "PRIVATE_KEY"); return; } } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Private Key file: %s\n", pkfn); if (NULL == (pk = GNUNET_CRYPTO_eddsa_key_create_from_file (pkfn))) { FPRINTF (stderr, _("Loading hostkey from `%s' failed.\n"), pkfn); GNUNET_free (pkfn); return; } GNUNET_free (pkfn); GNUNET_CRYPTO_eddsa_key_get_public (pk, &pub); GNUNET_free (pk); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer ID: %s\n", GNUNET_CRYPTO_eddsa_public_key_to_string (&pub)); /* get target bit amount */ if (0 == nse_work_required) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "NSE", "WORKBITS", &nse_work_required)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKBITS"); GNUNET_SCHEDULER_shutdown (); return; } if (nse_work_required >= sizeof (struct GNUNET_HashCode) * 8) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKBITS", _("Value is too large.\n")); GNUNET_SCHEDULER_shutdown (); return; } else if (0 == nse_work_required) { write_proof (); GNUNET_SCHEDULER_shutdown (); return; } } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Bits: %llu\n", nse_work_required); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delay between tries: %s\n", GNUNET_STRINGS_relative_time_to_string (proof_find_delay, 1)); GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &find_proof, NULL); } /** * Program to manipulate ECC key files. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'b', "bits", "BITS", gettext_noop ("number of bits to require for the proof of work"), 1, &GNUNET_GETOPT_set_ulong, &nse_work_required }, { 'k', "keyfile", "FILE", gettext_noop ("file with private key, otherwise default is used"), 1, &GNUNET_GETOPT_set_filename, &pkfn }, { 'o', "outfile", "FILE", gettext_noop ("file with proof of work, otherwise default is used"), 1, &GNUNET_GETOPT_set_filename, &pwfn }, { 't', "timeout", "TIME", gettext_noop ("time to wait between calculations"), 1, &GNUNET_GETOPT_set_relative_time, &proof_find_delay }, GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-scrypt [OPTIONS] prooffile", gettext_noop ("Manipulate GNUnet proof of work files"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); GNUNET_free_non_null (pwfn); return ret; } /* end of gnunet-ecc.c */ gnunet-0.10.1/src/util/getopt_helpers.c0000644000175000017500000002357012225777501014765 00000000000000/* This file is part of GNUnet (C) 2006, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/util/getopt_helpers.c * @brief implements command line that sets option * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** * Print out program version (implements --version). * * @param ctx command line processing context * @param scls additional closure (points to version string) * @param option name of the option * @param value not used (NULL) * @return GNUNET_NO (do not continue, not an error) */ int GNUNET_GETOPT_print_version_ (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { const char *version = scls; printf ("%s v%s\n", ctx->binaryName, version); return GNUNET_NO; } #define BORDER 29 /** * Print out details on command line options (implements --help). * * @param ctx command line processing context * @param scls additional closure (points to about text) * @param option name of the option * @param value not used (NULL) * @return GNUNET_NO (do not continue, not an error) */ int GNUNET_GETOPT_format_help_ (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { const char *about = scls; size_t slen; unsigned int i; int j; size_t ml; size_t p; char *scp; const char *trans; const struct GNUNET_GETOPT_CommandLineOption *opt; if (NULL != about) { printf ("%s\n%s\n", ctx->binaryOptions, gettext (about)); printf (_ ("Arguments mandatory for long options are also mandatory for short options.\n")); } i = 0; opt = ctx->allOptions; while (opt[i].description != NULL) { if (opt[i].shortName == '\0') printf (" "); else printf (" -%c, ", opt[i].shortName); printf ("--%s", opt[i].name); slen = 8 + strlen (opt[i].name); if (opt[i].argumentHelp != NULL) { printf ("=%s", opt[i].argumentHelp); slen += 1 + strlen (opt[i].argumentHelp); } if (slen > BORDER) { printf ("\n%*s", BORDER, ""); slen = BORDER; } if (slen < BORDER) { printf ("%*s", (int) (BORDER - slen), ""); slen = BORDER; } if (0 < strlen (opt[i].description)) trans = gettext (opt[i].description); else trans = ""; ml = strlen (trans); p = 0; OUTER: while (ml - p > 78 - slen) { for (j = p + 78 - slen; j > p; j--) { if (isspace ((unsigned char) trans[j])) { scp = GNUNET_malloc (j - p + 1); memcpy (scp, &trans[p], j - p); scp[j - p] = '\0'; printf ("%s\n%*s", scp, BORDER + 2, ""); GNUNET_free (scp); p = j + 1; slen = BORDER + 2; goto OUTER; } } /* could not find space to break line */ scp = GNUNET_malloc (78 - slen + 1); memcpy (scp, &trans[p], 78 - slen); scp[78 - slen] = '\0'; printf ("%s\n%*s", scp, BORDER + 2, ""); GNUNET_free (scp); slen = BORDER + 2; p = p + 78 - slen; } /* print rest */ if (p < ml) printf ("%s\n", &trans[p]); if (strlen (trans) == 0) printf ("\n"); i++; } printf ("Report bugs to gnunet-developers@gnu.org.\n" "GNUnet home page: http://www.gnu.org/software/gnunet/\n" "General help using GNU software: http://www.gnu.org/gethelp/\n"); return GNUNET_NO; } /** * Set an option of type 'unsigned int' from the command line. Each * time the option flag is given, the value is incremented by one. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'int'. * * @param ctx command line processing context * @param scls additional closure (will point to the 'int') * @param option name of the option * @param value not used (NULL) * @return GNUNET_OK */ int GNUNET_GETOPT_increment_value (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { int *val = scls; (*val)++; return GNUNET_OK; } /** * Set an option of type 'int' from the command line to 1 if the * given option is present. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'int'. * * @param ctx command line processing context * @param scls additional closure (will point to the 'int') * @param option name of the option * @param value not used (NULL) * @return GNUNET_OK */ int GNUNET_GETOPT_set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { int *val = scls; *val = 1; return GNUNET_OK; } /** * Set an option of type 'char *' from the command line. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'char *', which will be allocated with the requested string. * * @param ctx command line processing context * @param scls additional closure (will point to the 'char *', * which will be allocated) * @param option name of the option * @param value actual value of the option (a string) * @return GNUNET_OK */ int GNUNET_GETOPT_set_string (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { char **val = scls; GNUNET_assert (value != NULL); GNUNET_free_non_null (*val); *val = GNUNET_strdup (value); return GNUNET_OK; } int GNUNET_GETOPT_set_filename (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { char **val = scls; GNUNET_assert (value != NULL); GNUNET_free_non_null (*val); *val = GNUNET_STRINGS_filename_expand (value); return GNUNET_OK; } /** * Set an option of type 'unsigned long long' from the command line. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'unsigned long long'. * * @param ctx command line processing context * @param scls additional closure (will point to the 'unsigned long long') * @param option name of the option * @param value actual value of the option as a string. * @return GNUNET_OK if parsing the value worked */ int GNUNET_GETOPT_set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { unsigned long long *val = scls; if (1 != SSCANF (value, "%llu", val)) { FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), option); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Set an option of type 'struct GNUNET_TIME_Relative' from the command line. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'struct GNUNET_TIME_Relative'. * * @param ctx command line processing context * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative') * @param option name of the option * @param value actual value of the option as a string. * @return GNUNET_OK if parsing the value worked */ int GNUNET_GETOPT_set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { struct GNUNET_TIME_Relative *val = scls; if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (value, val)) { FPRINTF (stderr, _("You must pass relative time to the `%s' option.\n"), option); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Set an option of type 'unsigned int' from the command line. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of * type 'unsigned int'. * * @param ctx command line processing context * @param scls additional closure (will point to the 'unsigned int') * @param option name of the option * @param value actual value of the option as a string. * @return GNUNET_OK if parsing the value worked */ int GNUNET_GETOPT_set_uint (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { unsigned int *val = scls; if (1 != SSCANF (value, "%u", val)) { FPRINTF (stderr, _("You must pass a number to the `%s' option.\n"), option); return GNUNET_SYSERR; } return GNUNET_OK; } /* end of getopt_helpers.c */ gnunet-0.10.1/src/util/win.c0000644000175000017500000011443412225777501012536 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/win.c * @brief Helper functions for MS Windows in C++ * @author Nils Durner */ #ifndef _WIN_C #define _WIN_C #include "winproc.h" #include "platform.h" #include "gnunet_crypto_lib.h" #include "gnunet_common.h" #include "gnunet_connection_lib.h" #include #ifndef INHERITED_ACE #define INHERITED_ACE 0x10 #endif int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows); #define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \ union { \ struct { \ ULONG Length; \ DWORD Flags; \ }; \ }; #define _IP_ADAPTER_UNICAST_ADDRESS_BASE \ SOCKET_ADDRESS Address; \ IP_PREFIX_ORIGIN PrefixOrigin; \ IP_SUFFIX_ORIGIN SuffixOrigin; \ IP_DAD_STATE DadState; \ ULONG ValidLifetime; \ ULONG PreferredLifetime; \ ULONG LeaseLifetime; #define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \ UINT8 OnLinkPrefixLength; #define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \ typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \ _IP_ADAPTER_UNICAST_ADDRESS_HEAD \ struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \ _IP_ADAPTER_UNICAST_ADDRESS_BASE \ addition \ } IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix; /* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */ _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA) #ifndef __MINGW64_VERSION_MAJOR typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS { union { ULONGLONG Alignment; struct { ULONG Length; DWORD Reserved; }; }; struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next; SOCKET_ADDRESS Address; } IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH; typedef struct _IP_ADAPTER_GATEWAY_ADDRESS { union { ULONGLONG Alignment; struct { ULONG Length; DWORD Reserved; }; }; struct _IP_ADAPTER_GATEWAY_ADDRESS *Next; SOCKET_ADDRESS Address; } IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH; #endif typedef UINT32 NET_IF_COMPARTMENT_ID; typedef GUID NET_IF_NETWORK_GUID; #ifndef __MINGW64_VERSION_MAJOR typedef enum _NET_IF_CONNECTION_TYPE { NET_IF_CONNECTION_DEDICATED = 1, NET_IF_CONNECTION_PASSIVE, NET_IF_CONNECTION_DEMAND, NET_IF_CONNECTION_MAXIMUM } NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE; typedef enum { TUNNEL_TYPE_NONE = 0, TUNNEL_TYPE_OTHER, TUNNEL_TYPE_DIRECT, TUNNEL_TYPE_6TO4, TUNNEL_TYPE_ISATAP, TUNNEL_TYPE_TEREDO, TUNNEL_TYPE_IPHTTPS } TUNNEL_TYPE, *PTUNNEL_TYPE; #endif /* A DUID consists of a two-octet type code represented in network byte order, followed by a variable number of octets that make up the actual identifier. A DUID can be no more than 128 octets long (not including the type code). */ #define MAX_DHCPV6_DUID_LENGTH 130 #ifndef __MINGW64_VERSION_MAJOR typedef union _NET_LUID { ULONG64 Value; struct { ULONG64 Reserved :24; ULONG64 NetLuidIndex :24; ULONG64 IfType :16; } Info; } NET_LUID, *PNET_LUID, IF_LUID; #define MAX_DNS_SUFFIX_STRING_LENGTH 246 typedef struct _IP_ADAPTER_DNS_SUFFIX { struct _IP_ADAPTER_DNS_SUFFIX *Next; WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH]; } IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX; #endif #define _IP_ADAPTER_ADDRESSES_HEAD \ union { \ ULONGLONG Alignment; \ struct { \ ULONG Length; \ DWORD IfIndex; \ }; \ }; #define _IP_ADAPTER_ADDRESSES_BASE \ PCHAR AdapterName; \ PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; \ PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; \ PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; \ PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; \ PWCHAR DnsSuffix; \ PWCHAR Description; \ PWCHAR FriendlyName; \ BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \ DWORD PhysicalAddressLength; \ DWORD Flags; \ DWORD Mtu; \ DWORD IfType; \ IF_OPER_STATUS OperStatus; #define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \ DWORD Ipv6IfIndex; \ DWORD ZoneIndices[16]; \ PIP_ADAPTER_PREFIX FirstPrefix; \ #define _IP_ADAPTER_ADDRESSES_ADD_VISTA \ _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \ ULONG64 TransmitLinkSpeed; \ ULONG64 ReceiveLinkSpeed; \ PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \ PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \ ULONG Ipv4Metric; \ ULONG Ipv6Metric; \ IF_LUID Luid; \ SOCKET_ADDRESS Dhcpv4Server; \ NET_IF_COMPARTMENT_ID CompartmentId; \ NET_IF_NETWORK_GUID NetworkGuid; \ NET_IF_CONNECTION_TYPE ConnectionType; \ TUNNEL_TYPE TunnelType; \ SOCKET_ADDRESS Dhcpv6Server; \ BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \ ULONG Dhcpv6ClientDuidLength; \ ULONG Dhcpv6Iaid; #define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \ _IP_ADAPTER_ADDRESSES_ADD_VISTA \ PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix; #define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \ typedef struct _IP_ADAPTER_ADDRESSES##suffix { \ _IP_ADAPTER_ADDRESSES_HEAD \ struct _IP_ADAPTER_ADDRESSES##suffix *Next; \ _IP_ADAPTER_ADDRESSES_BASE \ addition \ } IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix; /* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */ _IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1) _IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA) _IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1) static int EnumNICs_IPv6_get_ifs_count (SOCKET s) { DWORD dwret = 0, err; int iret; iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0, &dwret, NULL, NULL); err = GetLastError (); if (iret == SOCKET_ERROR && err == WSAEFAULT) return dwret; else if (iret == 0) return 0; return GNUNET_SYSERR; } static int EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size) { int iret; DWORD dwret = 0; iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size, &dwret, NULL, NULL); if (iret != 0 || dwret != size) { /* It's supposed to succeed! And size should be the same */ return GNUNET_SYSERR; } return GNUNET_OK; } #undef GNUNET_malloc #define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \ HEAP_GENERATE_EXCEPTIONS, a) #undef GNUNET_free #define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a) #undef GNUNET_free_non_null #define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while (0) static int EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size) { int iret; DWORD dwret = 0; DWORD error; INTERFACE_INFO *ii = NULL; DWORD ii_size = sizeof (INTERFACE_INFO) * 15; while (TRUE) { if (ii_size >= sizeof (INTERFACE_INFO) * 1000) return GNUNET_SYSERR; ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size); dwret = 0; iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size, &dwret, NULL, NULL); error = GetLastError (); if (iret == SOCKET_ERROR) { if (error == WSAEFAULT) { GNUNET_free (ii); ii_size *= 2; continue; } GNUNET_free (ii); return GNUNET_SYSERR; } else { *inf = ii; *size = dwret; return GNUNET_OK; } } return GNUNET_SYSERR; } int EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6) { int result = 0; SOCKET s4 = INVALID_SOCKET, s6 = INVALID_SOCKET; DWORD dwret1 = 0, dwret2; DWORD err1, err2; int ifs4len = 0, ifs6len = 0; INTERFACE_INFO *interfaces4 = NULL; SOCKET_ADDRESS_LIST *interfaces6 = NULL; SetLastError (0); s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); err1 = GetLastError (); SetLastError (0); s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP); err2 = GetLastError (); if (s6 != INVALID_SOCKET) { ifs6len = EnumNICs_IPv6_get_ifs_count (s6); if (ifs6len > 0) { interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len); result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result; } closesocket (s6); s6 = INVALID_SOCKET; } if (s4 != INVALID_SOCKET) { result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result; closesocket (s4); s4 = INVALID_SOCKET; } if (ifs6len + ifs4len == 0) goto error; if (!result) { *ifs4 = interfaces4; *ifs4_len = ifs4len; *ifs6 = interfaces6; return GNUNET_OK; } error: if (interfaces4 != NULL) GNUNET_free (interfaces4); if (interfaces6 != NULL) GNUNET_free (interfaces6); if (s4 != INVALID_SOCKET) closesocket (s4); if (s6 != INVALID_SOCKET) closesocket (s6); return GNUNET_SYSERR; } /** * Returns GNUNET_OK on OK, GNUNET_SYSERR on error */ int EnumNICs3 (struct EnumNICs3_results **results, int *results_count) { DWORD dwRetVal = 0; int count = 0; ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; struct sockaddr_in6 examplecom6; IPAddr examplecom; DWORD best_interface = 0; DWORD best_interface6 = 0; int use_enum2 = 0; INTERFACE_INFO *interfaces4 = NULL; int interfaces4_len = 0; SOCKET_ADDRESS_LIST *interfaces6 = NULL; unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES); IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL; IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen); if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) { GNUNET_free (pAddresses); pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen); } dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen); if (dwRetVal != NO_ERROR) { GNUNET_free (pAddresses); return GNUNET_SYSERR; } if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA)) { use_enum2 = 1; /* Enumerate NICs using WSAIoctl() */ if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6)) { GNUNET_free (pAddresses); return GNUNET_SYSERR; } } examplecom = inet_addr("192.0.34.166"); /* www.example.com */ if (GetBestInterface (examplecom, &best_interface) != NO_ERROR) best_interface = 0; if (GNGetBestInterfaceEx != NULL) { examplecom6.sin6_family = AF_INET6; examplecom6.sin6_port = 0; examplecom6.sin6_flowinfo = 0; examplecom6.sin6_scope_id = 0; inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10", (struct sockaddr *) &examplecom6.sin6_addr); dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6, &best_interface6); if (dwRetVal != NO_ERROR) best_interface6 = 0; } /* Give IPv6 a priority */ if (best_interface6 != 0) best_interface = best_interface6; count = 0; for (pCurrentAddress = pAddresses; pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next) { if (pCurrentAddress->OperStatus == IfOperStatusUp) { IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL; for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL; unicast = unicast->Next) { if ((unicast->Address.lpSockaddr->sa_family == AF_INET || unicast->Address.lpSockaddr->sa_family == AF_INET6) && (unicast->DadState == IpDadStateDeprecated || unicast->DadState == IpDadStatePreferred)) count += 1; } } } if (count == 0) { *results = NULL; *results_count = 0; GNUNET_free (pAddresses); GNUNET_free_non_null (interfaces4); GNUNET_free_non_null (interfaces6); return GNUNET_OK; } *results = (struct EnumNICs3_results *) GNUNET_malloc ( sizeof (struct EnumNICs3_results) * count); *results_count = count; count = 0; for (pCurrentAddress = pAddresses; pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next) { struct EnumNICs3_results *r; IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL; if (pCurrentAddress->OperStatus != IfOperStatusUp) continue; for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL; unicast = unicast->Next) { int i, j; int mask_length = -1; char dst[INET6_ADDRSTRLEN + 1]; if ((unicast->Address.lpSockaddr->sa_family != AF_INET && unicast->Address.lpSockaddr->sa_family != AF_INET6) || (unicast->DadState != IpDadStateDeprecated && unicast->DadState != IpDadStatePreferred)) continue; r = &(*results)[count]; r->flags = 0; if (pCurrentAddress->IfIndex > 0 && pCurrentAddress->IfIndex == best_interface && unicast->Address.lpSockaddr->sa_family == AF_INET) r->is_default = 1; else if (pCurrentAddress->Ipv6IfIndex > 0 && pCurrentAddress->Ipv6IfIndex == best_interface6 && unicast->Address.lpSockaddr->sa_family == AF_INET6) r->is_default = 1; else r->is_default = 0; /* Don't choose default interface twice */ if (r->is_default) best_interface = best_interface6 = 0; if (!use_enum2) { memcpy (&r->address, unicast->Address.lpSockaddr, unicast->Address.iSockaddrLength); memset (&r->mask, 0, sizeof (struct sockaddr)); mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)-> OnLinkPrefixLength; /* OnLinkPrefixLength is the number of leading 1s in the mask. * OnLinkPrefixLength is available on Vista and later (hence use_enum2). */ if (unicast->Address.lpSockaddr->sa_family == AF_INET) { struct sockaddr_in *m = (struct sockaddr_in *) &r->mask; for (i = 0; i < mask_length; i++) ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8); } else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) { struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask; struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast; for (i = 0; i < mask_length; i++) ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8); memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength); for (i = mask_length; i < 128; i++) ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8); } r->flags |= ENUMNICS3_MASK_OK; } else { int found = 0; if (unicast->Address.lpSockaddr->sa_family == AF_INET) { for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); i++) { struct sockaddr_in *m = (struct sockaddr_in *) &r->mask; if (memcpy (&interfaces4[i].iiAddress.Address, unicast->Address.lpSockaddr, unicast->Address.iSockaddrLength) != 0) continue; found = 1; memcpy (&r->address, &interfaces4[i].iiAddress.Address, sizeof (struct sockaddr_in)); memcpy (&r->mask, &interfaces4[i].iiNetmask.Address, sizeof (struct sockaddr_in)); for (mask_length = 0; ((unsigned char *) &m->sin_addr)[mask_length / 8] & 0x80 >> (mask_length % 8); mask_length++) { } r->flags |= ENUMNICS3_MASK_OK; } } else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) { for (i = 0; interfaces6 != NULL && !found && i < interfaces6->iAddressCount; i++) { if (memcpy (interfaces6->Address[i].lpSockaddr, unicast->Address.lpSockaddr, unicast->Address.iSockaddrLength) != 0) continue; found = 1; memcpy (&r->address, interfaces6->Address[i].lpSockaddr, sizeof (struct sockaddr_in6)); /* TODO: Find a way to reliably get network mask for IPv6 on XP */ memset (&r->mask, 0, sizeof (struct sockaddr)); r->flags &= ~ENUMNICS3_MASK_OK; } } if (!found) { DebugBreak (); } } if (unicast->Address.lpSockaddr->sa_family == AF_INET) { struct sockaddr_in *m = (struct sockaddr_in *) &r->mask; struct sockaddr_in *a = (struct sockaddr_in *) &r->address; /* copy address to broadcast, then flip all the trailing bits not * falling under netmask to 1, * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24. */ memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength); for (i = mask_length; i < 32; i++) ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8); r->flags |= ENUMNICS3_BCAST_OK; r->addr_size = sizeof (struct sockaddr_in); inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN); } else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) { struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address; /* for IPv6 broadcast is not defined, zero it down */ memset (&r->broadcast, 0, sizeof (struct sockaddr)); r->flags &= ~ENUMNICS3_BCAST_OK; r->addr_size = sizeof (struct sockaddr_in6); inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN); } i = 0; i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, "%S (%s", pCurrentAddress->FriendlyName, dst); for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++) i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]); i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")"); r->pretty_name[1000] = '\0'; count += 1; } } if (use_enum2) { GNUNET_free_non_null (interfaces4); GNUNET_free_non_null (interfaces6); } GNUNET_free (pAddresses); return GNUNET_OK; } void EnumNICs3_free (struct EnumNICs3_results *r) { GNUNET_free_non_null (r); } /** * Lists all network interfaces in a combo box * Used by the basic GTK configurator * * @param callback function to call for each NIC * @param callback_cls closure for callback */ int ListNICs (void (*callback) (void *, const char *, int), void * callback_cls) { int r; int i; struct EnumNICs3_results *results = NULL; int results_count; r = EnumNICs3 (&results, &results_count); if (r != GNUNET_OK) return GNUNET_NO; for (i = 0; i < results_count; i++) callback (callback_cls, results[i].pretty_name, results[i].is_default); GNUNET_free_non_null (results); return GNUNET_YES; } /** * @brief Installs the Windows service * @param servicename name of the service as diplayed by the SCM * @param application path to the application binary * @param username the name of the service's user account * @returns 0 on success * 1 if the Windows version doesn't support services * 2 if the SCM could not be opened * 3 if the service could not be created */ int InstallAsService(char *servicename, char *application, char *username) { SC_HANDLE hManager, hService; char szEXE[_MAX_PATH + 17] = "\""; char *user = NULL; if (! GNOpenSCManager) return 1; plibc_conv_to_win_path(application, szEXE + 1); strcat(szEXE, "\" --win-service"); hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (! hManager) return 2; if (username) { user = (char *) malloc(strlen(username) + 3); sprintf(user, ".\\%s", username); } hService = GNCreateService(hManager, (LPCTSTR) servicename, (LPCTSTR) servicename, 0, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, (LPCTSTR) szEXE, NULL, NULL, NULL, (LPCTSTR) user, (LPCTSTR) username); if (user) free(user); if (! hService) return 3; GNCloseServiceHandle(hService); return 0; } /** * @brief Uninstall Windows service * @param servicename name of the service to delete * @returns 0 on success * 1 if the Windows version doesn't support services * 2 if the SCM could not be openend * 3 if the service cannot be accessed * 4 if the service cannot be deleted */ int UninstallService(char *servicename) { SC_HANDLE hManager, hService; if (! GNOpenSCManager) return 1; hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (! hManager) return 2; if (! (hService = GNOpenService(hManager, (LPCTSTR) servicename, DELETE))) { if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) return 3; else goto closeSCM; } if (! GNDeleteService(hService)) if (GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE) return 4; closeSCM: GNCloseServiceHandle(hService); return 0; } /** * @author Scott Field, Microsoft * @see http://support.microsoft.com/?scid=kb;en-us;132958 * @date 12-Jul-95 */ void _InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String) { DWORD StringLength; if(String == NULL) { LsaString->Buffer = NULL; LsaString->Length = 0; LsaString->MaximumLength = 0; return; } StringLength = wcslen(String); LsaString->Buffer = String; LsaString->Length = (USHORT) StringLength *sizeof(WCHAR); LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR); } /** * @author Scott Field, Microsoft * @see http://support.microsoft.com/?scid=kb;en-us;132958 * @date 12-Jul-95 */ NTSTATUS _OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle) { LSA_OBJECT_ATTRIBUTES ObjectAttributes; LSA_UNICODE_STRING ServerString; PLSA_UNICODE_STRING Server = NULL; /* Always initialize the object attributes to all zeroes. */ ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); if(ServerName != NULL) { /* Make a LSA_UNICODE_STRING out of the LPWSTR passed in */ _InitLsaString(&ServerString, ServerName); Server = &ServerString; } /* Attempt to open the policy. */ return GNLsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess, PolicyHandle); } /** * @brief Obtain a SID representing the supplied account on the supplied system * @return TRUE on success, FALSE on failure * @author Scott Field, Microsoft * @date 12-Jul-95 * @remarks A buffer is allocated which contains the SID representing the * supplied account. This buffer should be freed when it is no longer * needed by calling\n * HeapFree(GetProcessHeap(), 0, buffer) * @remarks Call GetLastError() to obtain extended error information. * @see http://support.microsoft.com/?scid=kb;en-us;132958 */ BOOL _GetAccountSid(LPCTSTR SystemName, LPCTSTR AccountName, PSID * Sid) { LPTSTR ReferencedDomain = NULL; DWORD cbSid = 128; /* initial allocation attempt */ DWORD cchReferencedDomain = 16; /* initial allocation size */ SID_NAME_USE peUse; BOOL bSuccess = FALSE; /* assume this function will fail */ /* initial memory allocations */ if ((*Sid = HeapAlloc (GetProcessHeap (), 0, cbSid)) == NULL) return FALSE; if ((ReferencedDomain = (LPTSTR) HeapAlloc (GetProcessHeap (), 0, cchReferencedDomain * sizeof (TCHAR))) == NULL) return FALSE; /* Obtain the SID of the specified account on the specified system. */ while (!GNLookupAccountName(SystemName, /* machine to lookup account on */ AccountName, /* account to lookup */ *Sid, /* SID of interest */ &cbSid, /* size of SID */ ReferencedDomain, /* domain account was found on */ &cchReferencedDomain, &peUse)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { /* reallocate memory */ if ((*Sid = HeapReAlloc (GetProcessHeap (), 0, *Sid, cbSid)) == NULL) return FALSE; if ((ReferencedDomain = (LPTSTR) HeapReAlloc (GetProcessHeap (), 0, ReferencedDomain, cchReferencedDomain * sizeof (TCHAR))) == NULL) return FALSE; } else goto end; } /* Indicate success. */ bSuccess = TRUE; end: /* Cleanup and indicate failure, if appropriate. */ HeapFree (GetProcessHeap (), 0, ReferencedDomain); if (!bSuccess) { if (*Sid != NULL) { HeapFree (GetProcessHeap (), 0, *Sid); *Sid = NULL; } } return bSuccess; } /** * @author Scott Field, Microsoft * @see http://support.microsoft.com/?scid=kb;en-us;132958 * @date 12-Jul-95 */ NTSTATUS _SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle,/* open policy handle */ PSID AccountSid, /* SID to grant privilege to */ LPWSTR PrivilegeName, /* privilege to grant (Unicode) */ BOOL bEnable /* enable or disable */ ) { LSA_UNICODE_STRING PrivilegeString; /* Create a LSA_UNICODE_STRING for the privilege name. */ _InitLsaString(&PrivilegeString, PrivilegeName); /* grant or revoke the privilege, accordingly */ if(bEnable) { NTSTATUS i; i = GNLsaAddAccountRights(PolicyHandle, /* open policy handle */ AccountSid, /* target SID */ &PrivilegeString, /* privileges */ 1 /* privilege count */ ); return i; } else { return GNLsaRemoveAccountRights(PolicyHandle, /* open policy handle */ AccountSid, /* target SID */ FALSE, /* do not disable all rights */ &PrivilegeString, /* privileges */ 1 /* privilege count */ ); } } /** * @brief Create a Windows service account * @return 0 on success, > 0 otherwise * @param pszName the name of the account * @param pszDesc description of the account */ int CreateServiceAccount(const char *pszName, const char *pszDesc) { USER_INFO_1 ui; USER_INFO_1008 ui2; NET_API_STATUS nStatus; wchar_t wszName[MAX_NAME_LENGTH], wszDesc[MAX_NAME_LENGTH]; DWORD dwErr; LSA_HANDLE hPolicy; PSID pSID; if (! GNNetUserAdd) return 1; mbstowcs(wszName, pszName, strlen(pszName) + 1); mbstowcs(wszDesc, pszDesc, strlen(pszDesc) + 1); memset(&ui, 0, sizeof(ui)); ui.usri1_name = wszName; ui.usri1_password = wszName; /* account is locked anyway */ ui.usri1_priv = USER_PRIV_USER; ui.usri1_comment = wszDesc; ui.usri1_flags = UF_SCRIPT; nStatus = GNNetUserAdd(NULL, 1, (LPBYTE)&ui, NULL); if (nStatus != NERR_Success && nStatus != NERR_UserExists) return 2; ui2.usri1008_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD; GNNetUserSetInfo(NULL, wszName, 1008, (LPBYTE)&ui2, NULL); if (!NT_SUCCESS(_OpenPolicy(NULL, POLICY_ALL_ACCESS, &hPolicy))) return 3; _GetAccountSid(NULL, (LPCTSTR) pszName, &pSID); if (!NT_SUCCESS(_SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeServiceLogonRight", TRUE))) return 4; _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyInteractiveLogonRight", TRUE); _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyBatchLogonRight", TRUE); _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyNetworkLogonRight", TRUE); GNLsaClose(hPolicy); return 0; } /** * @brief Grant permission to a file * @param lpszFileName the name of the file or directory * @param lpszAccountName the user account * @param dwAccessMask the desired access (e.g. GENERIC_ALL) * @return TRUE on success * @remark based on http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q102102& */ BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName, DWORD dwAccessMask) { /* SID variables. */ SID_NAME_USE snuType; TCHAR * szDomain = NULL; DWORD cbDomain = 0; LPVOID pUserSID = NULL; DWORD cbUserSID = 0; /* File SD variables. */ PSECURITY_DESCRIPTOR pFileSD = NULL; DWORD cbFileSD = 0; /* New SD variables. */ SECURITY_DESCRIPTOR newSD; /* ACL variables. */ PACL pACL = NULL; BOOL fDaclPresent; BOOL fDaclDefaulted; ACL_SIZE_INFORMATION AclInfo; /* New ACL variables. */ PACL pNewACL = NULL; DWORD cbNewACL = 0; /* Temporary ACE. */ LPVOID pTempAce = NULL; UINT CurrentAceIndex = 0; UINT newAceIndex = 0; /* Assume function will fail. */ BOOL fResult = FALSE; BOOL fAPISuccess; SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; /** * STEP 1: Get SID of the account name specified. */ fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName, pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType); /* API should have failed with insufficient buffer. */ if (fAPISuccess) goto end; else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto end; } pUserSID = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbUserSID); if (!pUserSID) { goto end; } szDomain = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDomain * sizeof(TCHAR)); if (!szDomain) { goto end; } fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName, pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType); if (!fAPISuccess) { goto end; } /** * STEP 2: Get security descriptor (SD) of the file specified. */ fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName, secInfo, pFileSD, 0, &cbFileSD); /* API should have failed with insufficient buffer. */ if (fAPISuccess) goto end; else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto end; } pFileSD = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbFileSD); if (!pFileSD) { goto end; } fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName, secInfo, pFileSD, cbFileSD, &cbFileSD); if (!fAPISuccess) { goto end; } /** * STEP 3: Initialize new SD. */ if (!GNInitializeSecurityDescriptor(&newSD, SECURITY_DESCRIPTOR_REVISION)) { goto end; } /** * STEP 4: Get DACL from the old SD. */ if (!GNGetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL, &fDaclDefaulted)) { goto end; } /** * STEP 5: Get size information for DACL. */ AclInfo.AceCount = 0; // Assume NULL DACL. AclInfo.AclBytesFree = 0; AclInfo.AclBytesInUse = sizeof(ACL); if (pACL == NULL) fDaclPresent = FALSE; /* If not NULL DACL, gather size information from DACL. */ if (fDaclPresent) { if (!GNGetAclInformation(pACL, &AclInfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) { goto end; } } /** * STEP 6: Compute size needed for the new ACL. */ cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pUserSID) - sizeof(DWORD); /** * STEP 7: Allocate memory for new ACL. */ pNewACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL); if (!pNewACL) { goto end; } /** * STEP 8: Initialize the new ACL. */ if (!GNInitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) { goto end; } /** * STEP 9 If DACL is present, copy all the ACEs from the old DACL * to the new DACL. * * The following code assumes that the old DACL is * already in Windows 2000 preferred order. To conform * to the new Windows 2000 preferred order, first we will * copy all non-inherited ACEs from the old DACL to the * new DACL, irrespective of the ACE type. */ newAceIndex = 0; if (fDaclPresent && AclInfo.AceCount) { for (CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { /** * TEP 10: Get an ACE. */ if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) { goto end; } /** * STEP 11: Check if it is a non-inherited ACE. * If it is an inherited ACE, break from the loop so * that the new access allowed non-inherited ACE can * be added in the correct position, immediately after * all non-inherited ACEs. */ if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags & INHERITED_ACE) break; /** * STEP 12: Skip adding the ACE, if the SID matches * with the account specified, as we are going to * add an access allowed ACE with a different access * mask. */ if (GNEqualSid(pUserSID, &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) continue; /** * STEP 13: Add the ACE to the new ACL. */ if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) { goto end; } newAceIndex++; } } /** * STEP 14: Add the access-allowed ACE to the new DACL. * The new ACE added here will be in the correct position, * immediately after all existing non-inherited ACEs. */ if (!GNAddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask, pUserSID)) { goto end; } /** * STEP 14.5: Make new ACE inheritable */ if (!GetAce(pNewACL, newAceIndex, &pTempAce)) goto end; ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags |= (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE); /** * STEP 15: To conform to the new Windows 2000 preferred order, * we will now copy the rest of inherited ACEs from the * old DACL to the new DACL. */ if (fDaclPresent && AclInfo.AceCount) { for (; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++) { /** * STEP 16: Get an ACE. */ if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) { goto end; } /** * STEP 17: Add the ACE to the new ACL. */ if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ((PACE_HEADER) pTempAce)->AceSize)) { goto end; } } } /** * STEP 18: Set permissions */ if (GNSetNamedSecurityInfo((LPTSTR) lpszFileName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS) { goto end; } fResult = TRUE; end: /** * STEP 19: Free allocated memory */ if (pUserSID) HeapFree(GetProcessHeap(), 0, pUserSID); if (szDomain) HeapFree(GetProcessHeap(), 0, szDomain); if (pFileSD) HeapFree(GetProcessHeap(), 0, pFileSD); if (pNewACL) HeapFree(GetProcessHeap(), 0, pNewACL); return fResult; } char *winErrorStr(const char *prefix, int dwErr) { char *err, *ret; int mem; if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD) dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &err, 0, NULL )) { err = (char *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, 1); } mem = strlen(err) + strlen(prefix) + 20; ret = (char *) malloc(mem); snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr); LocalFree(err); return ret; } /** * Terminate a process by creating a remote thread within it, * which proceeds to call ExitProcess() inside that process. * Safer than TerminateProcess (). * * Code is from From http://private-storm.de/2009/08/11/case-terminateprocess/ * * @param hProcess handle of a process to terminate * @param uExitCode exit code to use for ExitProcess() * @param dwTimeout number of ms to wait for the process to terminate * @return TRUE on success, FALSE on failure (check last error for the code) */ BOOL SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout) { DWORD dwTID, dwCode, dwErr = 0; HANDLE hProcessDup = INVALID_HANDLE_VALUE; HANDLE hRT = NULL; HINSTANCE hKernel = GetModuleHandle ("Kernel32"); BOOL bSuccess = FALSE; BOOL bDup = DuplicateHandle (GetCurrentProcess (), hProcess, GetCurrentProcess (), &hProcessDup, PROCESS_ALL_ACCESS, FALSE, 0); /* Detect the special case where the process is * already dead... */ if (GetExitCodeProcess (bDup ? hProcessDup : hProcess, &dwCode) && (STILL_ACTIVE == dwCode)) { FARPROC pfnExitProc; pfnExitProc = GetProcAddress (hKernel, "ExitProcess"); hRT = CreateRemoteThread ((bDup) ? hProcessDup : hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pfnExitProc, (PVOID) uExitCode, 0, &dwTID); dwErr = GetLastError (); } else { dwErr = ERROR_PROCESS_ABORTED; } if (hRT) { /* Must wait process to terminate to * guarantee that it has exited... */ DWORD dwWaitResult = WaitForSingleObject ((bDup) ? hProcessDup : hProcess, dwTimeout); if (dwWaitResult == WAIT_TIMEOUT) dwErr = WAIT_TIMEOUT; else dwErr = GetLastError (); CloseHandle (hRT); bSuccess = dwErr == NO_ERROR; } if (bDup) CloseHandle (hProcessDup); SetLastError (dwErr); return bSuccess; } #endif gnunet-0.10.1/src/util/disk.h0000644000175000017500000000256712225777503012705 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/disk.h * @brief Internal DISK related helper functions * @author Nils Durner */ #ifndef GNUNET_DISK_H_ #define GNUNET_DISK_H_ #include "gnunet_util_lib.h" /** * Retrieve OS file handle * * @internal * @param fh GNUnet file descriptor * @param dst destination buffer * @param dst_len length of @a dst * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ int GNUNET_DISK_internal_file_handle_ (const struct GNUNET_DISK_FileHandle *fh, void *dst, size_t dst_len); #endif /* GNUNET_DISK_H_ */ gnunet-0.10.1/src/util/test_crypto_ecdhe.c0000644000175000017500000000414712236654562015452 00000000000000/* This file is part of GNUnet. (C) 2002-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_crypto_ecdhe.c * @brief testcase for ECC ECDHE public key crypto * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include int main (int argc, char *argv[]) { struct GNUNET_CRYPTO_EcdhePrivateKey *priv1; struct GNUNET_CRYPTO_EcdhePrivateKey *priv2; struct GNUNET_CRYPTO_EcdhePublicKey pub1; struct GNUNET_CRYPTO_EcdhePublicKey pub2; struct GNUNET_HashCode ecdh1; struct GNUNET_HashCode ecdh2; if (! gcry_check_version ("1.6.0")) { FPRINTF (stderr, _ ("libgcrypt has not the expected version (version %s is required).\n"), "1.6.0"); return 0; } if (getenv ("GNUNET_GCRYPT_DEBUG")) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); GNUNET_log_setup ("test-crypto-ecdhe", "WARNING", NULL); priv1 = GNUNET_CRYPTO_ecdhe_key_create (); priv2 = GNUNET_CRYPTO_ecdhe_key_create (); GNUNET_CRYPTO_ecdhe_key_get_public (priv1, &pub1); GNUNET_CRYPTO_ecdhe_key_get_public (priv2, &pub2); GNUNET_CRYPTO_ecc_ecdh (priv1, &pub2, &ecdh1); GNUNET_CRYPTO_ecc_ecdh (priv2, &pub1, &ecdh2); GNUNET_assert (0 == memcmp (&ecdh1, &ecdh2, sizeof (struct GNUNET_HashCode))); GNUNET_free (priv1); GNUNET_free (priv2); return 0; } /* end of test_crypto_ecdhe.c */ gnunet-0.10.1/src/util/test_configuration.c0000644000175000017500000003223412225777501015644 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2005, 2006, 2007 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_configuration.c * @brief Test that the configuration module works. * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" /* Test Configuration Diffs Options */ enum { EDIT_NOTHING, EDIT_SECTION, EDIT_ALL, ADD_NEW_SECTION, ADD_NEW_ENTRY, REMOVE_SECTION, REMOVE_ENTRY, COMPARE, PRINT }; static struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_CONFIGURATION_Handle *cfg_default; struct DiffsCBData { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CONFIGURATION_Handle *cfgDiffs; const char *section; int callBackOption; int status; }; static void initDiffsCBData (struct DiffsCBData *cbData) { cbData->section = NULL; cbData->cfg = NULL; cbData->cfgDiffs = NULL; cbData->callBackOption = -1; cbData->status = 0; } /** * callback function for modifying * and comparing configuration */ static void diffsCallBack (void *cls, const char *section, const char *option, const char *value) { struct DiffsCBData *cbData = cls; int cbOption = cbData->callBackOption; switch (cbOption) { case EDIT_SECTION: if (NULL == cbData->section) cbData->section = section; if (strcmp (cbData->section, section) == 0) { GNUNET_CONFIGURATION_set_value_string (cbData->cfg, section, option, "new-value"); GNUNET_CONFIGURATION_set_value_string (cbData->cfgDiffs, section, option, "new-value"); } break; case EDIT_ALL: GNUNET_CONFIGURATION_set_value_string (cbData->cfg, section, option, "new-value"); GNUNET_CONFIGURATION_set_value_string (cbData->cfgDiffs, section, option, "new-value"); break; case ADD_NEW_ENTRY: { static int hit = 0; if (hit == 0) { hit = 1; GNUNET_CONFIGURATION_set_value_string (cbData->cfg, section, "new-key", "new-value"); GNUNET_CONFIGURATION_set_value_string (cbData->cfgDiffs, section, "new-key", "new-value"); } break; } case COMPARE: { int ret; char *diffValue; diffValue = NULL; ret = GNUNET_CONFIGURATION_get_value_string (cbData->cfgDiffs, section, option, &diffValue); if (NULL != diffValue) { if (ret == GNUNET_SYSERR || strcmp (diffValue, value) != 0) cbData->status = 1; } else cbData->status = 1; GNUNET_free_non_null (diffValue); break; } #if 0 case PRINT: if (NULL == cbData->section) { cbData->section = section; printf ("\nSection: %s\n", section); } else if (strcmp (cbData->section, section) != 0) { cbData->section = section; printf ("\nSection: %s\n", section); } printf ("%s = %s\n", option, value); #endif default: break; } } static struct GNUNET_CONFIGURATION_Handle * editConfiguration (struct GNUNET_CONFIGURATION_Handle *cfg, int option) { struct DiffsCBData diffsCB; initDiffsCBData (&diffsCB); diffsCB.cfgDiffs = GNUNET_CONFIGURATION_create (); switch (option) { case EDIT_SECTION: case EDIT_ALL: case ADD_NEW_ENTRY: diffsCB.callBackOption = option; diffsCB.cfg = cfg; GNUNET_CONFIGURATION_iterate (cfg, diffsCallBack, &diffsCB); break; case EDIT_NOTHING: /* Do nothing */ break; case ADD_NEW_SECTION: { int i; char *key; for (i = 0; i < 5; i++) { GNUNET_asprintf (&key, "key%d", i); GNUNET_CONFIGURATION_set_value_string (cfg, "new-section", key, "new-value"); GNUNET_CONFIGURATION_set_value_string (diffsCB.cfgDiffs, "new-section", key, "new-value"); GNUNET_free (key); } break; } case REMOVE_SECTION: break; case REMOVE_ENTRY: break; default: break; } return diffsCB.cfgDiffs; } /** * Checking configuration diffs */ static int checkDiffs (struct GNUNET_CONFIGURATION_Handle *cfg_default, int option) { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CONFIGURATION_Handle *cfgDiffs; struct DiffsCBData cbData; int ret; char *diffsFileName; initDiffsCBData (&cbData); cfg = GNUNET_CONFIGURATION_create (); /* load defaults */ GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (cfg, NULL)); /* Modify configuration and save it */ cfgDiffs = editConfiguration (cfg, option); diffsFileName = GNUNET_DISK_mktemp ("gnunet-test-configurations-diffs.conf"); if (diffsFileName == NULL) { GNUNET_break (0); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_CONFIGURATION_destroy (cfgDiffs); return 1; } GNUNET_CONFIGURATION_write_diffs (cfg_default, cfg, diffsFileName); GNUNET_CONFIGURATION_destroy (cfg); /* Compare the dumped configuration with modifications done */ cfg = GNUNET_CONFIGURATION_create (); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, diffsFileName)); if (0 != remove (diffsFileName)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "remove", diffsFileName); cbData.callBackOption = COMPARE; cbData.cfgDiffs = cfgDiffs; GNUNET_CONFIGURATION_iterate (cfg, diffsCallBack, &cbData); if (1 == (ret = cbData.status)) { FPRINTF (stderr, "%s", "Incorrect Configuration Diffs: Diffs may contain data not actually edited\n"); goto housekeeping; } cbData.cfgDiffs = cfg; GNUNET_CONFIGURATION_iterate (cfgDiffs, diffsCallBack, &cbData); if ((ret = cbData.status) == 1) FPRINTF (stderr, "%s", "Incorrect Configuration Diffs: Data may be missing in diffs\n"); housekeeping: #if 0 cbData.section = NULL; cbData.callBackOption = PRINT; printf ("\nExpected Diffs:\n"); GNUNET_CONFIGURATION_iterate (cfgDiffs, diffsCallBack, &cbData); cbData.section = NULL; printf ("\nActual Diffs:\n"); GNUNET_CONFIGURATION_iterate (cfg, diffsCallBack, &cbData); #endif GNUNET_CONFIGURATION_destroy (cfg); GNUNET_CONFIGURATION_destroy (cfgDiffs); GNUNET_free (diffsFileName); return ret; } static int testConfig () { char *c; unsigned long long l; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "test", "b", &c)) return 1; if (0 != strcmp ("b", c)) { FPRINTF (stderr, "Got `%s'\n", c); GNUNET_free (c); return 2; } GNUNET_free (c); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "test", "five", &l)) { GNUNET_break (0); return 3; } if (5 != l) { GNUNET_break (0); return 4; } GNUNET_CONFIGURATION_set_value_string (cfg, "more", "c", "YES"); if (GNUNET_NO == GNUNET_CONFIGURATION_get_value_yesno (cfg, "more", "c")) { GNUNET_break (0); return 5; } GNUNET_CONFIGURATION_set_value_number (cfg, "NUMBERS", "TEN", 10); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "NUMBERS", "TEN", &c)) { GNUNET_break (0); return 6; } if (0 != strcmp (c, "10")) { GNUNET_free (c); GNUNET_break (0); return 7; } GNUNET_free (c); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "last", "test", &c)) { GNUNET_break (0); return 8; } #ifndef MINGW if (0 != strcmp (c, "/hello/world")) #else #define HI "\\hello\\world" if (strstr (c, HI) != c + strlen (c) - strlen (HI)) #endif { GNUNET_break (0); GNUNET_free (c); return 9; } GNUNET_free (c); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size (cfg, "last", "size", &l)) { GNUNET_break (0); return 10; } if (l != 512 * 1024) { GNUNET_break (0); return 11; } return 0; } static const char *want[] = { "/Hello", "/File Name", "/World", NULL, NULL, }; static int check (void *data, const char *fn) { int *idx = data; if (0 == strcmp (want[*idx], fn)) { (*idx)++; return GNUNET_OK; } GNUNET_break (0); return GNUNET_SYSERR; } static int testConfigFilenames () { int idx; idx = 0; if (3 != GNUNET_CONFIGURATION_iterate_value_filenames (cfg, "FILENAMES", "test", &check, &idx)) { GNUNET_break (0); return 8; } if (idx != 3) return 16; if (GNUNET_OK != GNUNET_CONFIGURATION_remove_value_filename (cfg, "FILENAMES", "test", "/File Name")) { GNUNET_break (0); return 24; } if (GNUNET_NO != GNUNET_CONFIGURATION_remove_value_filename (cfg, "FILENAMES", "test", "/File Name")) { GNUNET_break (0); return 32; } if (GNUNET_NO != GNUNET_CONFIGURATION_remove_value_filename (cfg, "FILENAMES", "test", "Stuff")) { GNUNET_break (0); return 40; } if (GNUNET_NO != GNUNET_CONFIGURATION_append_value_filename (cfg, "FILENAMES", "test", "/Hello")) { GNUNET_break (0); return 48; } if (GNUNET_NO != GNUNET_CONFIGURATION_append_value_filename (cfg, "FILENAMES", "test", "/World")) { GNUNET_break (0); return 56; } if (GNUNET_YES != GNUNET_CONFIGURATION_append_value_filename (cfg, "FILENAMES", "test", "/File 1")) { GNUNET_break (0); return 64; } if (GNUNET_YES != GNUNET_CONFIGURATION_append_value_filename (cfg, "FILENAMES", "test", "/File 2")) { GNUNET_break (0); return 72; } idx = 0; want[1] = "/World"; want[2] = "/File 1"; want[3] = "/File 2"; if (4 != GNUNET_CONFIGURATION_iterate_value_filenames (cfg, "FILENAMES", "test", &check, &idx)) { GNUNET_break (0); return 80; } if (idx != 4) { GNUNET_break (0); return 88; } return 0; } int main (int argc, char *argv[]) { int failureCount = 0; char *c; GNUNET_log_setup ("test_configuration", "WARNING", NULL); cfg = GNUNET_CONFIGURATION_create (); GNUNET_assert (cfg != NULL); if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, "test_configuration_data.conf")) { FPRINTF (stderr, "%s", "Failed to parse configuration file\n"); GNUNET_CONFIGURATION_destroy (cfg); return 1; } failureCount += testConfig (); if (failureCount > 0) goto error; failureCount = testConfigFilenames (); if (failureCount > 0) goto error; if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, "/tmp/gnunet-test.conf")) { FPRINTF (stderr, "%s", "Failed to write configuration file\n"); GNUNET_CONFIGURATION_destroy (cfg); return 1; } GNUNET_CONFIGURATION_destroy (cfg); GNUNET_assert (0 == UNLINK ("/tmp/gnunet-test.conf")); cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, "test_configuration_data.conf")) { GNUNET_break (0); GNUNET_CONFIGURATION_destroy (cfg); return 1; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING", "WEAKRANDOM", &c)) { GNUNET_break (0); GNUNET_CONFIGURATION_destroy (cfg); return 1; } if (0 != strcmp (c, "YES")) { GNUNET_break (0); GNUNET_free (c); GNUNET_CONFIGURATION_destroy (cfg); return 1; } GNUNET_free (c); GNUNET_CONFIGURATION_destroy (cfg); /* Testing configuration diffs */ cfg_default = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg_default, NULL)) { GNUNET_break (0); GNUNET_CONFIGURATION_destroy (cfg_default); return 1; } /* Nothing changed in the new configuration */ failureCount += checkDiffs (cfg_default, EDIT_NOTHING); /* Modify all entries of the last section */ failureCount += checkDiffs (cfg_default, EDIT_SECTION); /* Add a new section */ failureCount += checkDiffs (cfg_default, ADD_NEW_SECTION); /* Add a new entry to the last section */ failureCount += checkDiffs (cfg_default, ADD_NEW_ENTRY); /* Modify all entries in the configuration */ failureCount += checkDiffs (cfg_default, EDIT_ALL); GNUNET_CONFIGURATION_destroy (cfg_default); error: if (failureCount != 0) { FPRINTF (stderr, "Test failed: %u\n", failureCount); return 1; } return 0; } gnunet-0.10.1/src/util/os_network.c0000644000175000017500000001727512225777501014140 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/os_network.c * @brief function to determine available network interfaces * @author Nils Durner * @author Heikki Lindholm * @author Jake Dust * @author LRN */ #include "platform.h" #include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * @brief Enumerate all network interfaces * * @param proc the callback function * @param proc_cls closure for proc */ void GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, void *proc_cls) { #ifdef MINGW int r; int i; struct EnumNICs3_results *results = NULL; int results_count; r = EnumNICs3 (&results, &results_count); if (r != GNUNET_OK) return; for (i = 0; i < results_count; i++) { if (GNUNET_OK != proc (proc_cls, results[i].pretty_name, results[i].is_default, (const struct sockaddr *) &results[i].address, results[i]. flags & ENUMNICS3_BCAST_OK ? (const struct sockaddr *) &results[i].broadcast : NULL, results[i].flags & ENUMNICS3_MASK_OK ? (const struct sockaddr *) &results[i].mask : NULL, results[i].addr_size)) break; } EnumNICs3_free (results); return; #elif HAVE_GETIFADDRS && HAVE_FREEIFADDRS struct ifaddrs *ifa_first; struct ifaddrs *ifa_ptr; socklen_t alen; if (getifaddrs (&ifa_first) == 0) { for (ifa_ptr = ifa_first; ifa_ptr != NULL; ifa_ptr = ifa_ptr->ifa_next) { if (ifa_ptr->ifa_name != NULL && ifa_ptr->ifa_addr != NULL && (ifa_ptr->ifa_flags & IFF_UP) != 0) { if ((ifa_ptr->ifa_addr->sa_family != AF_INET) && (ifa_ptr->ifa_addr->sa_family != AF_INET6)) continue; if (ifa_ptr->ifa_addr->sa_family == AF_INET) alen = sizeof (struct sockaddr_in); else alen = sizeof (struct sockaddr_in6); if (GNUNET_OK != proc (proc_cls, ifa_ptr->ifa_name, 0 == strcmp (ifa_ptr->ifa_name, GNUNET_DEFAULT_INTERFACE), ifa_ptr->ifa_addr, ifa_ptr->ifa_broadaddr, ifa_ptr->ifa_netmask, alen)) break; } } freeifaddrs (ifa_first); } #else int i; char line[1024]; char *replace; const char *start; char ifc[12]; char addrstr[128]; char bcstr[128]; char netmaskstr[128]; FILE *f; int have_ifc; struct sockaddr_in a4; struct sockaddr_in6 a6; struct in_addr v4; struct in6_addr v6; struct sockaddr_in bcaddr; struct sockaddr_in netmask; struct sockaddr_in6 netmask6; struct sockaddr *pass_bcaddr; struct sockaddr *pass_netmask; int prefixlen; if (system ("ifconfig -a > /dev/null 2> /dev/null")) if (system ("/sbin/ifconfig -a > /dev/null 2> /dev/null") == 0) f = popen ("/sbin/ifconfig -a 2> /dev/null", "r"); else f = NULL; else f = popen ("ifconfig -a 2> /dev/null", "r"); if (!f) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "popen", "ifconfig"); return; } have_ifc = GNUNET_NO; ifc[11] = '\0'; while (NULL != fgets (line, sizeof (line), f)) { if (strlen (line) == 0) { have_ifc = GNUNET_NO; continue; } if (!isspace (line[0])) { have_ifc = (1 == SSCANF (line, "%11s", ifc)) ? GNUNET_YES : GNUNET_NO; /* would end with ':' on OSX, fix it! */ if (ifc[strlen (ifc) - 1] == ':') ifc[strlen (ifc) - 1] = '\0'; continue; } if (!have_ifc) continue; /* strange input, hope for the best */ /* make parsing of ipv6 addresses easier */ for (replace = line; *replace != '\0'; replace++) { if (*replace == '/') *replace = ' '; } prefixlen = -1; start = line; while (('\0' != *start) && (isspace (*start))) start++; /* Zero-out stack allocated values */ memset (addrstr, 0, 128); memset (netmaskstr, 0, 128); memset (bcstr, 0, 128); prefixlen = 0; if ( /* Linux */ (3 == SSCANF (start, "inet addr:%127s Bcast:%127s Mask:%127s", addrstr, bcstr, netmaskstr)) || (2 == SSCANF (start, "inet addr:%127s Mask:%127s", addrstr, netmaskstr)) || (2 == SSCANF (start, "inet6 addr:%127s %d", addrstr, &prefixlen)) || /* Solaris, OS X */ (1 == SSCANF (start, "inet %127s", addrstr)) || (1 == SSCANF (start, "inet6 %127s", addrstr))) { /* IPv4 */ if (1 == inet_pton (AF_INET, addrstr, &v4)) { memset (&a4, 0, sizeof (a4)); a4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN a4.sin_len = (u_char) sizeof (struct sockaddr_in); #endif a4.sin_addr = v4; pass_bcaddr = NULL; pass_netmask = NULL; if (1 == inet_pton (AF_INET, bcstr, &v4)) { memset (&bcaddr, 0, sizeof (bcaddr)); bcaddr.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN bcaddr.sin_len = (u_char) sizeof (struct sockaddr_in); #endif bcaddr.sin_addr = v4; pass_bcaddr = (struct sockaddr *) &bcaddr; } if (1 == inet_pton (AF_INET, netmaskstr, &v4)) { memset (&netmask, 0, sizeof (netmask)); netmask.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN netmask.sin_len = (u_char) sizeof (struct sockaddr_in); #endif netmask.sin_addr = v4; pass_netmask = (struct sockaddr *) &netmask; } if (GNUNET_OK != proc (proc_cls, ifc, 0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE), (const struct sockaddr *) &a4, pass_bcaddr, pass_netmask, sizeof (a4))) break; continue; } /* IPv6 */ if (1 == inet_pton (AF_INET6, addrstr, &v6)) { memset (&a6, 0, sizeof (a6)); a6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN a6.sin6_len = (u_char) sizeof (struct sockaddr_in6); #endif a6.sin6_addr = v6; pass_netmask = NULL; if (prefixlen != -1) { memset (v6.s6_addr, 0, sizeof (v6.s6_addr)); for (i = 0; i < prefixlen; i++) { v6.s6_addr[i >> 3] |= 1 << (i & 7); } memset (&netmask6, 0, sizeof (netmask6)); netmask6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN netmask6.sin6_len = (u_char) sizeof (struct sockaddr_in6); #endif netmask6.sin6_addr = v6; pass_netmask = (struct sockaddr *) &netmask6; } if (GNUNET_OK != proc (proc_cls, ifc, 0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE), (const struct sockaddr *) &a6, NULL, pass_netmask, sizeof (a6))) break; continue; } } } pclose (f); #endif } /* end of os_network.c */ gnunet-0.10.1/src/util/test_plugin_plug.c0000644000175000017500000000226312225777501015321 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_plugin_plug.c * @brief plugin for testing */ #include "platform.h" void * libgnunet_plugin_test_init (void *arg) { if (0 == strcmp (arg, "in")) return "Hello"; return NULL; } void * libgnunet_plugin_test_done (void *arg) { if (0 == strcmp (arg, "out")) return strdup ("World"); return NULL; } /* end of test_plugin_plug.c */ gnunet-0.10.1/src/util/gnunet-uri.c0000644000175000017500000001151012301361473014015 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/gnunet-uri.c * @brief tool to dispatch URIs to the appropriate GNUnet helper process * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" /** * Handler exit code */ static long unsigned int exit_code = 1; /** * Helper process we started. */ static struct GNUNET_OS_Process *p; /** * Pipe used to communicate shutdown via signal. */ static struct GNUNET_DISK_PipeHandle *sigpipe; /** * Task triggered whenever we receive a SIGCHLD (child * process died) or when user presses CTRL-C. * * @param cls closure, NULL * @param tc scheduler context */ static void maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { enum GNUNET_OS_ProcessStatusType type; if ( (GNUNET_OK != GNUNET_OS_process_status (p, &type, &exit_code)) || (type != GNUNET_OS_PROCESS_EXITED) ) GNUNET_break (0 == GNUNET_OS_process_kill (p, GNUNET_TERM_SIG)); GNUNET_OS_process_destroy (p); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { const char *uri; const char *slash; char *subsystem; char *program; GNUNET_SCHEDULER_TaskIdentifier rt; if (NULL == (uri = args[0])) { fprintf (stderr, _("No URI specified on command line\n")); return; } if (0 != strncasecmp ("gnunet://", uri, strlen ("gnunet://"))) { fprintf (stderr, _("Invalid URI: does not start with `%s'\n"), "gnunet://"); return; } uri += strlen ("gnunet://"); if (NULL == (slash = strchr (uri, '/'))) { fprintf (stderr, _("Invalid URI: fails to specify subsystem\n")); return; } subsystem = GNUNET_strndup (uri, slash - uri); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "uri", subsystem, &program)) { fprintf (stderr, _("No handler known for subsystem `%s'\n"), subsystem); GNUNET_free (subsystem); return; } GNUNET_free (subsystem); rt = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), &maint_child_death, NULL); p = GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL, program, program, args[0], NULL); GNUNET_free (program); if (NULL == p) GNUNET_SCHEDULER_cancel (rt); } /** * Signal handler called for SIGCHLD. Triggers the * respective handler by writing to the trigger pipe. */ static void sighandler_child_death () { static char c; int old_errno = errno; /* back-up errno */ GNUNET_break (1 == GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_WRITE), &c, sizeof (c))); errno = old_errno; /* restore errno */ } /** * The main function to handle gnunet://-URIs. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; struct GNUNET_SIGNAL_Context *shc_chld; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); GNUNET_assert (sigpipe != NULL); shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-uri URI", gettext_noop ("Perform default-actions for GNUnet URIs"), options, &run, NULL); GNUNET_SIGNAL_handler_uninstall (shc_chld); shc_chld = NULL; GNUNET_DISK_pipe_close (sigpipe); sigpipe = NULL; GNUNET_free ((void *) argv); return ((GNUNET_OK == ret) && (0 == exit_code)) ? 0 : 1; } /* end of gnunet-uri.c */ gnunet-0.10.1/src/util/test_program_data.conf0000644000175000017500000000004012274162760016125 00000000000000[resolver] HOSTNAME = localhost gnunet-0.10.1/src/util/test_bio.c0000644000175000017500000003162412225777501013550 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_bio.c * @brief testcase for the buffered IO module * @author Ji Lu */ #include "platform.h" #include "gnunet_util_lib.h" #define TESTSTRING "testString" #define TESTNUMBER64 ((int64_t)100000L) static int test_normal_rw () { char *msg; int64_t testNum; char *readResultString; char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; struct GNUNET_CONTAINER_MetaData *metaDataW; struct GNUNET_CONTAINER_MetaData *metaDataR; metaDataW = GNUNET_CONTAINER_meta_data_create (); metaDataR = NULL; GNUNET_CONTAINER_meta_data_add_publication_date (metaDataW); fileW = GNUNET_BIO_write_open (fileName); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, TESTSTRING)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_meta_data (fileW, metaDataW)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int64 (fileW, TESTNUMBER64)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open (fileName); GNUNET_assert (NULL != fileR); readResultString = NULL; GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_string (fileR, "Read string error", &readResultString, 200)); GNUNET_assert (NULL != readResultString); GNUNET_assert (0 == strcmp (TESTSTRING, readResultString)); GNUNET_free (readResultString); GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_meta_data (fileR, "Read meta error", &metaDataR)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (metaDataR, metaDataW)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_int64 (fileR, &testNum)); GNUNET_BIO_read_close (fileR, &msg); GNUNET_CONTAINER_meta_data_destroy (metaDataW); GNUNET_CONTAINER_meta_data_destroy (metaDataR); GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); GNUNET_free (fileName); return 0; } static int test_nullstring_rw () { char *msg; char *readResultString = (char *) "not null"; struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); fileW = GNUNET_BIO_write_open (fileName); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, NULL)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open (fileName); GNUNET_assert (NULL != fileR); GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_string (fileR, "Read string error", &readResultString, 200)); GNUNET_assert (NULL == readResultString); GNUNET_BIO_read_close (fileR, &msg); GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); GNUNET_free (fileName); return 0; } static int test_emptystring_rw () { char *msg; char *readResultString; struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); fileW = GNUNET_BIO_write_open (fileName); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, "")); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open (fileName); GNUNET_assert (NULL != fileR); readResultString = NULL; GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_string (fileR, "Read string error", &readResultString, 200)); GNUNET_free (readResultString); GNUNET_BIO_read_close (fileR, &msg); GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); GNUNET_free (fileName); return 0; } static int test_bigstring_rw () { char *msg; char *readResultString; struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); fileW = GNUNET_BIO_write_open (fileName); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, TESTSTRING)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open (fileName); GNUNET_assert (NULL != fileR); readResultString = NULL; GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_string (fileR, "Read string error", &readResultString, 1)); GNUNET_assert (NULL == readResultString); msg = NULL; GNUNET_BIO_read_close (fileR, &msg); GNUNET_free (msg); GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); GNUNET_free (fileName); return 0; } static int test_bigmeta_rw () { char *msg; static char meta[1024 * 1024 * 10]; struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); struct GNUNET_CONTAINER_MetaData *metaDataR; memset (meta, 'b', sizeof (meta)); meta[sizeof (meta) - 1] = '\0'; fileW = GNUNET_BIO_write_open (fileName); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, sizeof (meta))); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write (fileW, meta, sizeof (meta))); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open (fileName); GNUNET_assert (NULL != fileR); metaDataR = NULL; GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_meta_data (fileR, "Read meta error", &metaDataR)); msg = NULL; GNUNET_BIO_read_close (fileR, &msg); GNUNET_free (msg); GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); GNUNET_assert (NULL == metaDataR); GNUNET_free (fileName); return 0; } static int test_directory_r () { #if LINUX char *msg; char readResult[200]; struct GNUNET_BIO_ReadHandle *fileR; fileR = GNUNET_BIO_read_open ("/dev"); GNUNET_assert (NULL != fileR); GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read (fileR, "Read error", readResult, sizeof (readResult))); msg = NULL; GNUNET_BIO_read_close (fileR, &msg); GNUNET_free (msg); #endif return 0; } static int test_nullfile_rw () { static char fileNameNO[102401]; struct GNUNET_BIO_WriteHandle *fileWNO; struct GNUNET_BIO_ReadHandle *fileRNO; memset (fileNameNO, 'a', sizeof (fileNameNO)); fileNameNO[sizeof (fileNameNO) - 1] = '\0'; GNUNET_log_skip (1, GNUNET_NO); fileWNO = GNUNET_BIO_write_open (fileNameNO); GNUNET_log_skip (0, GNUNET_YES); GNUNET_assert (NULL == fileWNO); GNUNET_log_skip (1, GNUNET_NO); fileRNO = GNUNET_BIO_read_open (fileNameNO); GNUNET_log_skip (0, GNUNET_YES); GNUNET_assert (NULL == fileRNO); return 0; } static int test_fullfile_rw () { #ifdef LINUX /* /dev/full only seems to exist on Linux */ char *msg; int64_t testNum; char *readResultString; char readResult[200]; struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; struct GNUNET_CONTAINER_MetaData *metaDataW; struct GNUNET_CONTAINER_MetaData *metaDataR; metaDataW = GNUNET_CONTAINER_meta_data_create (); GNUNET_CONTAINER_meta_data_add_publication_date (metaDataW); fileW = GNUNET_BIO_write_open ("/dev/full"); GNUNET_assert (NULL != fileW); (void) GNUNET_BIO_write (fileW, TESTSTRING, strlen (TESTSTRING)); (void) GNUNET_BIO_write_string (fileW, TESTSTRING); (void) GNUNET_BIO_write_meta_data (fileW, metaDataW); GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_close (fileW)); GNUNET_CONTAINER_meta_data_destroy (metaDataW); fileW = GNUNET_BIO_write_open ("/dev/full"); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open ("/dev/null"); GNUNET_assert (NULL != fileR); GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read (fileR, "Read error", readResult, sizeof (readResult))); readResultString = NULL; GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_string (fileR, "Read string error", &readResultString, 200)); GNUNET_assert (NULL == readResultString); GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_int64 (fileR, &testNum)); metaDataR = NULL; GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_meta_data (fileR, "Read meta error", &metaDataR)); msg = NULL; GNUNET_BIO_read_close (fileR, &msg); GNUNET_free (msg); GNUNET_assert (NULL == metaDataR); #endif return 0; } static int test_fakestring_rw () { char *msg; int32_t tmpInt = 2; char *readResult; struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); fileW = GNUNET_BIO_write_open (fileName); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open (fileName); GNUNET_assert (NULL != fileR); GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_string (fileR, "Read string error", &readResult, 200)); msg = NULL; GNUNET_BIO_read_close (fileR, &msg); GNUNET_free (msg); GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); GNUNET_free (fileName); return 0; } static int test_fakemeta_rw () { char *msg; int32_t tmpInt = 2; struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); struct GNUNET_CONTAINER_MetaData *metaDataR; fileW = GNUNET_BIO_write_open (fileName); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open (fileName); GNUNET_assert (NULL != fileR); metaDataR = NULL; GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_meta_data (fileR, "Read meta error", &metaDataR)); GNUNET_assert (NULL == metaDataR); msg = NULL; GNUNET_BIO_read_close (fileR, &msg); GNUNET_free (msg); GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); GNUNET_free (fileName); return 0; } static int test_fakebigmeta_rw () { char *msg; int32_t tmpInt = 1024 * 1024 * 10; struct GNUNET_BIO_WriteHandle *fileW; struct GNUNET_BIO_ReadHandle *fileR; char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); struct GNUNET_CONTAINER_MetaData *metaDataR; fileW = GNUNET_BIO_write_open (fileName); GNUNET_assert (NULL != fileW); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt)); GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); fileR = GNUNET_BIO_read_open (fileName); GNUNET_assert (NULL != fileR); metaDataR = NULL; GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_meta_data (fileR, "Read meta error", &metaDataR)); msg = NULL; GNUNET_BIO_read_close (fileR, &msg); GNUNET_free (msg); GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); GNUNET_assert (NULL == metaDataR); GNUNET_free (fileName); return 0; } static int check_string_rw () { GNUNET_assert (0 == test_nullstring_rw ()); GNUNET_assert (0 == test_emptystring_rw ()); GNUNET_assert (0 == test_bigstring_rw ()); GNUNET_assert (0 == test_fakestring_rw ()); return 0; } static int check_metadata_rw () { GNUNET_assert (0 == test_fakebigmeta_rw ()); GNUNET_assert (0 == test_fakemeta_rw ()); GNUNET_assert (0 == test_bigmeta_rw ()); return 0; } static int check_file_rw () { GNUNET_assert (0 == test_normal_rw ()); GNUNET_assert (0 == test_nullfile_rw ()); GNUNET_assert (0 == test_fullfile_rw ()); GNUNET_assert (0 == test_directory_r ()); return 0; } int main (int argc, char *argv[]) { GNUNET_log_setup ("test-bio", "WARNING", NULL); GNUNET_assert (0 == check_file_rw ()); GNUNET_assert (0 == check_metadata_rw ()); GNUNET_assert (0 == check_string_rw ()); return 0; } /* end of test_bio.c */ gnunet-0.10.1/src/util/winproc.c0000644000175000017500000002442612256040736013420 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/winproc.c * @brief Functions for MS Windows * @author Nils Durner */ #include "platform.h" #include "gnunet_crypto_lib.h" #include "gnunet_common.h" #ifdef MINGW static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi; #ifdef W32_VEH static void *GNWinVEH_handle = NULL; #endif TNtQuerySystemInformation GNNtQuerySystemInformation; TGetIfEntry GNGetIfEntry; TGetIpAddrTable GNGetIpAddrTable; TGetIfTable GNGetIfTable; TOpenSCManager GNOpenSCManager; TCreateService GNCreateService; TCloseServiceHandle GNCloseServiceHandle; TDeleteService GNDeleteService; TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler; TSetServiceStatus GNSetServiceStatus; TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher; TControlService GNControlService; TOpenService GNOpenService; TGetBestInterfaceEx GNGetBestInterfaceEx; TGetAdaptersInfo GNGetAdaptersInfo; TNetUserAdd GNNetUserAdd; TNetUserSetInfo GNNetUserSetInfo; TLsaOpenPolicy GNLsaOpenPolicy; TLsaAddAccountRights GNLsaAddAccountRights; TLsaRemoveAccountRights GNLsaRemoveAccountRights; TLsaClose GNLsaClose; TLookupAccountName GNLookupAccountName; TGetFileSecurity GNGetFileSecurity; TInitializeSecurityDescriptor GNInitializeSecurityDescriptor; TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl; TGetAclInformation GNGetAclInformation; TInitializeAcl GNInitializeAcl; TGetAce GNGetAce; TEqualSid GNEqualSid; TAddAce GNAddAce; TAddAccessAllowedAce GNAddAccessAllowedAce; TSetNamedSecurityInfo GNSetNamedSecurityInfo; #define LOG(kind,...) GNUNET_log_from (kind, "winproc", __VA_ARGS__) /** * Log (panic) messages from PlibC */ void plibc_panic (int err, char *msg) { LOG (((err == INT_MAX) ? GNUNET_ERROR_TYPE_DEBUG : GNUNET_ERROR_TYPE_ERROR), "%s", msg); } #ifdef W32_VEH /** * Handles exceptions (useful for debugging). * Issues a DebugBreak() call if the process is being debugged (not really * useful - if the process is being debugged, this handler won't be invoked * anyway). If it is not, runs a debugger from GNUNET_DEBUGGER env var, * substituting first %u in it for PID, and the second one for the event, * that should be set once the debugger attaches itself (otherwise the * only way out of WaitForSingleObject() is to time out after 1 minute). */ LONG __stdcall GNWinVEH (PEXCEPTION_POINTERS ExceptionInfo) { char debugger[MAX_PATH + 1]; char *debugger_env = NULL; if (IsDebuggerPresent ()) { DebugBreak (); return EXCEPTION_CONTINUE_EXECUTION; } debugger_env = getenv ("GNUNET_DEBUGGER"); if (debugger_env != NULL) { STARTUPINFO si; PROCESS_INFORMATION pi; HANDLE event; SECURITY_ATTRIBUTES sa; memset (&si, 0, sizeof (si)); si.cb = sizeof (si); memset (&pi, 0, sizeof (pi)); memset (&sa, 0, sizeof (sa)); sa.nLength = sizeof (sa); sa.bInheritHandle = TRUE; event = CreateEvent (&sa, FALSE, FALSE, NULL); snprintf (debugger, MAX_PATH + 1, debugger_env, GetCurrentProcessId (), (uintptr_t) event); debugger[MAX_PATH] = '\0'; if (0 != CreateProcessA (NULL, debugger, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { CloseHandle (pi.hProcess); CloseHandle (pi.hThread); WaitForSingleObject (event, 60000); CloseHandle (event); if (IsDebuggerPresent ()) { return EXCEPTION_CONTINUE_EXECUTION; } } else CloseHandle (event); } return EXCEPTION_CONTINUE_SEARCH; } #endif /** * @brief Initialize PlibC and set up Windows environment * @param logging context, NULL means stderr * @return Error code from winerror.h, ERROR_SUCCESS on success */ int GNInitWinEnv () { int ret; plibc_initialized (); plibc_set_panic_proc (plibc_panic); ret = plibc_init_utf8 ("GNU", PACKAGE, 1); plibc_set_stat_size_size (sizeof (((struct stat *) 0)->st_size)); plibc_set_stat_time_size (sizeof (((struct stat *) 0)->st_mtime)); /* don't load other DLLs twice */ if (hNTDLL) return ret; #ifdef W32_VEH if (GNWinVEH_handle == NULL) { GNWinVEH_handle = AddVectoredExceptionHandler (1, &GNWinVEH); if (GNWinVEH_handle == NULL) { /* This is bad, but what can we do? */ printf ("Failed to set up an exception handler!\n"); } } #endif hNTDLL = LoadLibrary ("ntdll.dll"); /* Function to get CPU usage under Win NT */ if (hNTDLL) { GNNtQuerySystemInformation = (TNtQuerySystemInformation) GetProcAddress (hNTDLL, "NtQuerySystemInformation"); } else { GNNtQuerySystemInformation = NULL; } /* Functions to get information about a network adapter */ hIphlpapi = LoadLibrary ("iphlpapi.dll"); if (hIphlpapi) { GNGetIfEntry = (TGetIfEntry) GetProcAddress (hIphlpapi, "GetIfEntry"); GNGetIpAddrTable = (TGetIpAddrTable) GetProcAddress (hIphlpapi, "GetIpAddrTable"); GNGetIfTable = (TGetIfTable) GetProcAddress (hIphlpapi, "GetIfTable"); GNGetBestInterfaceEx = (TGetBestInterfaceEx) GetProcAddress (hIphlpapi, "GetBestInterfaceEx"); GNGetAdaptersInfo = (TGetAdaptersInfo) GetProcAddress (hIphlpapi, "GetAdaptersInfo"); } else { GNGetIfEntry = NULL; GNGetIpAddrTable = NULL; GNGetIfTable = NULL; GNGetBestInterfaceEx = NULL; GNGetAdaptersInfo = NULL; } /* Service & Account functions */ hAdvapi = LoadLibrary ("advapi32.dll"); if (hAdvapi) { GNOpenSCManager = (TOpenSCManager) GetProcAddress (hAdvapi, "OpenSCManagerA"); GNCreateService = (TCreateService) GetProcAddress (hAdvapi, "CreateServiceA"); GNCloseServiceHandle = (TCloseServiceHandle) GetProcAddress (hAdvapi, "CloseServiceHandle"); GNDeleteService = (TDeleteService) GetProcAddress (hAdvapi, "DeleteService"); GNRegisterServiceCtrlHandler = (TRegisterServiceCtrlHandler) GetProcAddress (hAdvapi, "RegisterServiceCtrlHandlerA"); GNSetServiceStatus = (TSetServiceStatus) GetProcAddress (hAdvapi, "SetServiceStatus"); GNStartServiceCtrlDispatcher = (TStartServiceCtrlDispatcher) GetProcAddress (hAdvapi, "StartServiceCtrlDispatcherA"); GNControlService = (TControlService) GetProcAddress (hAdvapi, "ControlService"); GNOpenService = (TOpenService) GetProcAddress (hAdvapi, "OpenServiceA"); GNLsaOpenPolicy = (TLsaOpenPolicy) GetProcAddress (hAdvapi, "LsaOpenPolicy"); GNLsaAddAccountRights = (TLsaAddAccountRights) GetProcAddress (hAdvapi, "LsaAddAccountRights"); GNLsaRemoveAccountRights = (TLsaRemoveAccountRights) GetProcAddress (hAdvapi, "LsaRemoveAccountRights"); GNLsaClose = (TLsaClose) GetProcAddress (hAdvapi, "LsaClose"); GNLookupAccountName = (TLookupAccountName) GetProcAddress (hAdvapi, "LookupAccountNameA"); GNGetFileSecurity = (TGetFileSecurity) GetProcAddress (hAdvapi, "GetFileSecurityA"); GNInitializeSecurityDescriptor = (TInitializeSecurityDescriptor) GetProcAddress (hAdvapi, "InitializeSecurityDescriptor"); GNGetSecurityDescriptorDacl = (TGetSecurityDescriptorDacl) GetProcAddress (hAdvapi, "GetSecurityDescriptorDacl"); GNGetAclInformation = (TGetAclInformation) GetProcAddress (hAdvapi, "GetAclInformation"); GNInitializeAcl = (TInitializeAcl) GetProcAddress (hAdvapi, "InitializeAcl"); GNGetAce = (TGetAce) GetProcAddress (hAdvapi, "GetAce"); GNEqualSid = (TEqualSid) GetProcAddress (hAdvapi, "EqualSid"); GNAddAce = (TAddAce) GetProcAddress (hAdvapi, "AddAce"); GNAddAccessAllowedAce = (TAddAccessAllowedAce) GetProcAddress (hAdvapi, "AddAccessAllowedAce"); GNSetNamedSecurityInfo = (TSetNamedSecurityInfo) GetProcAddress (hAdvapi, "SetNamedSecurityInfoA"); } else { GNOpenSCManager = NULL; GNCreateService = NULL; GNCloseServiceHandle = NULL; GNDeleteService = NULL; GNRegisterServiceCtrlHandler = NULL; GNSetServiceStatus = NULL; GNStartServiceCtrlDispatcher = NULL; GNControlService = NULL; GNOpenService = NULL; GNLsaOpenPolicy = NULL; GNLsaAddAccountRights = NULL; GNLsaRemoveAccountRights = NULL; GNLsaClose = NULL; GNLookupAccountName = NULL; GNGetFileSecurity = NULL; GNInitializeSecurityDescriptor = NULL; GNGetSecurityDescriptorDacl = NULL; GNGetAclInformation = NULL; GNInitializeAcl = NULL; GNGetAce = NULL; GNEqualSid = NULL; GNAddAce = NULL; GNAddAccessAllowedAce = NULL; GNSetNamedSecurityInfo = NULL; } /* Account function */ hNetapi = LoadLibrary ("netapi32.dll"); if (hNetapi) { GNNetUserAdd = (TNetUserAdd) GetProcAddress (hNetapi, "NetUserAdd"); GNNetUserSetInfo = (TNetUserSetInfo) GetProcAddress (hNetapi, "NetUserSetInfo"); } else { GNNetUserAdd = NULL; GNNetUserSetInfo = NULL; } return ret; } /** * Clean up Windows environment */ void GNShutdownWinEnv () { plibc_shutdown (); #ifdef W32_VEH if (GNWinVEH_handle != NULL) { RemoveVectoredExceptionHandler (GNWinVEH_handle); GNWinVEH_handle = NULL; } #endif FreeLibrary (hNTDLL); FreeLibrary (hIphlpapi); FreeLibrary (hAdvapi); FreeLibrary (hNetapi); CoUninitialize (); } #endif /* MINGW */ #if !HAVE_ATOLL long long atoll (const char *nptr) { return atol (nptr); } #endif gnunet-0.10.1/src/util/service.c0000644000175000017500000013731212307557412013377 00000000000000/* This file is part of GNUnet. (C) 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/service.c * @brief functions related to starting services * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_constants.h" #include "gnunet_resolver_service.h" #include "speedup.h" #if HAVE_MALLINFO #include #include "gauger.h" #endif #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /* ******************* access control ******************** */ /** * Check if the given IP address is in the list of IP addresses. * * @param list a list of networks * @param add the IP to check (in network byte order) * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is */ static int check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add) { unsigned int i; if (NULL == list) return GNUNET_NO; i = 0; while ((list[i].network.s_addr != 0) || (list[i].netmask.s_addr != 0)) { if ((add->s_addr & list[i].netmask.s_addr) == (list[i].network.s_addr & list[i].netmask.s_addr)) return GNUNET_YES; i++; } return GNUNET_NO; } /** * Check if the given IP address is in the list of IP addresses. * * @param list a list of networks * @param ip the IP to check (in network byte order) * @return #GNUNET_NO if the IP is not in the list, #GNUNET_YES if it it is */ static int check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip) { unsigned int i; unsigned int j; struct in6_addr zero; if (NULL == list) return GNUNET_NO; memset (&zero, 0, sizeof (struct in6_addr)); i = 0; NEXT: while (0 != memcmp (&zero, &list[i].network, sizeof (struct in6_addr))) { for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++) if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) != (((int *) &list[i].network)[j] & ((int *) &list[i].netmask)[j])) { i++; goto NEXT; } return GNUNET_YES; } return GNUNET_NO; } /* ****************** service struct ****************** */ /** * Context for "service_task". */ struct GNUNET_SERVICE_Context { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for the server. */ struct GNUNET_SERVER_Handle *server; /** * NULL-terminated array of addresses to bind to, NULL if we got pre-bound * listen sockets. */ struct sockaddr **addrs; /** * Name of our service. */ const char *service_name; /** * Main service-specific task to run. */ GNUNET_SERVICE_Main task; /** * Closure for task. */ void *task_cls; /** * IPv4 addresses that are not allowed to connect. */ struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied; /** * IPv6 addresses that are not allowed to connect. */ struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied; /** * IPv4 addresses that are allowed to connect (if not * set, all are allowed). */ struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed; /** * IPv6 addresses that are allowed to connect (if not * set, all are allowed). */ struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed; /** * My (default) message handlers. Adjusted copy * of "defhandlers". */ struct GNUNET_SERVER_MessageHandler *my_handlers; /** * Array of the lengths of the entries in addrs. */ socklen_t *addrlens; /** * NULL-terminated array of listen sockets we should take over. */ struct GNUNET_NETWORK_Handle **lsocks; /** * Task ID of the shutdown task. */ GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Idle timeout for server. */ struct GNUNET_TIME_Relative timeout; /** * Overall success/failure of the service start. */ int ret; /** * If we are daemonizing, this FD is set to the * pipe to the parent. Send '.' if we started * ok, '!' if not. -1 if we are not daemonizing. */ int ready_confirm_fd; /** * Do we close connections if we receive messages * for which we have no handler? */ int require_found; /** * Do we require a matching UID for UNIX domain socket connections? * #GNUNET_NO means that the UID does not have to match (however, * @e match_gid may still impose other access control checks). */ int match_uid; /** * Do we require a matching GID for UNIX domain socket connections? * Ignored if @e match_uid is #GNUNET_YES. Note that this is about * checking that the client's UID is in our group OR that the * client's GID is our GID. If both "match_gid" and @e match_uid are * #GNUNET_NO, all users on the local system have access. */ int match_gid; /** * Our options. */ enum GNUNET_SERVICE_Options options; }; /* ****************** message handlers ****************** */ /** * Send a 'TEST' message back to the client. * * @param cls the 'struct GNUNET_SERVER_Client' to send TEST to * @param size number of bytes available in 'buf' * @param buf where to copy the message * @return number of bytes written to 'buf' */ static size_t write_test (void *cls, size_t size, void *buf) { struct GNUNET_SERVER_Client *client = cls; struct GNUNET_MessageHeader *msg; if (size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return 0; /* client disconnected */ } msg = (struct GNUNET_MessageHeader *) buf; msg->type = htons (GNUNET_MESSAGE_TYPE_TEST); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); GNUNET_SERVER_receive_done (client, GNUNET_OK); return sizeof (struct GNUNET_MessageHeader); } /** * Handler for TEST message. * * @param cls closure (refers to service) * @param client identification of the client * @param message the actual message */ static void handle_test (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { /* simply bounce message back to acknowledge */ if (NULL == GNUNET_SERVER_notify_transmit_ready (client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, &write_test, client)) GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); } /** * Default handlers for all services. Will be copied and the * "callback_cls" fields will be replaced with the specific service * struct. */ static const struct GNUNET_SERVER_MessageHandler defhandlers[] = { {&handle_test, NULL, GNUNET_MESSAGE_TYPE_TEST, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; /* ****************** service core routines ************** */ /** * Check if access to the service is allowed from the given address. * * @param cls closure * @param uc credentials, if available, otherwise NULL * @param addr address * @param addrlen length of address * @return #GNUNET_YES to allow, #GNUNET_NO to deny, #GNUNET_SYSERR * for unknown address family (will be denied). */ static int check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc, const struct sockaddr *addr, socklen_t addrlen) { struct GNUNET_SERVICE_Context *sctx = cls; const struct sockaddr_in *i4; const struct sockaddr_in6 *i6; int ret; switch (addr->sa_family) { case AF_INET: GNUNET_assert (addrlen == sizeof (struct sockaddr_in)); i4 = (const struct sockaddr_in *) addr; ret = ((NULL == sctx->v4_allowed) || (check_ipv4_listed (sctx->v4_allowed, &i4->sin_addr))) && ((NULL == sctx->v4_denied) || (!check_ipv4_listed (sctx->v4_denied, &i4->sin_addr))); break; case AF_INET6: GNUNET_assert (addrlen == sizeof (struct sockaddr_in6)); i6 = (const struct sockaddr_in6 *) addr; ret = ((NULL == sctx->v6_allowed) || (check_ipv6_listed (sctx->v6_allowed, &i6->sin6_addr))) && ((NULL == sctx->v6_denied) || (!check_ipv6_listed (sctx->v6_denied, &i6->sin6_addr))); break; #ifndef WINDOWS case AF_UNIX: ret = GNUNET_OK; /* controlled using file-system ACL now */ break; #endif default: LOG (GNUNET_ERROR_TYPE_WARNING, _("Unknown address family %d\n"), addr->sa_family); return GNUNET_SYSERR; } if (GNUNET_OK != ret) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Access from `%s' denied to service `%s'\n"), GNUNET_a2s (addr, addrlen), sctx->service_name); } return ret; } /** * Get the name of the file where we will * write the PID of the service. * * @param sctx service context * @return name of the file for the process ID */ static char * get_pid_file_name (struct GNUNET_SERVICE_Context *sctx) { char *pif; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->service_name, "PIDFILE", &pif)) return NULL; return pif; } /** * Parse an IPv4 access control list. * * @param ret location where to write the ACL (set) * @param sctx service context to use to get the configuration * @param option name of the ACL option to parse * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including * no ACL configured) */ static int process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Context *sctx, const char *option) { char *opt; if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option)) { *ret = NULL; return GNUNET_OK; } GNUNET_break (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (sctx->cfg, sctx->service_name, option, &opt)); if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt))) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"), opt, sctx->service_name, option); GNUNET_free (opt); return GNUNET_SYSERR; } GNUNET_free (opt); return GNUNET_OK; } /** * Parse an IPv6 access control list. * * @param ret location where to write the ACL (set) * @param sctx service context to use to get the configuration * @param option name of the ACL option to parse * @return #GNUNET_SYSERR on parse error, #GNUNET_OK on success (including * no ACL configured) */ static int process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Context *sctx, const char *option) { char *opt; if (!GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, option)) { *ret = NULL; return GNUNET_OK; } GNUNET_break (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (sctx->cfg, sctx->service_name, option, &opt)); if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt))) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"), opt, sctx->service_name, option); GNUNET_free (opt); return GNUNET_SYSERR; } GNUNET_free (opt); return GNUNET_OK; } /** * Add the given UNIX domain path as an address to the * list (as the first entry). * * @param saddrs array to update * @param saddrlens where to store the address length * @param unixpath path to add * @param abstract GNUNET_YES to add an abstract UNIX domain socket. This * parameter is ignore on systems other than LINUX */ static void add_unixpath (struct sockaddr **saddrs, socklen_t * saddrlens, const char *unixpath, int abstract) { #ifdef AF_UNIX struct sockaddr_un *un; un = GNUNET_new (struct sockaddr_un); un->sun_family = AF_UNIX; strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1); #ifdef LINUX if (GNUNET_YES == abstract) un->sun_path[0] = '\0'; #endif #if HAVE_SOCKADDR_IN_SIN_LEN un->sun_len = (u_char) sizeof (struct sockaddr_un); #endif *saddrs = (struct sockaddr *) un; *saddrlens = sizeof (struct sockaddr_un); #else /* this function should never be called * unless AF_UNIX is defined! */ GNUNET_assert (0); #endif } /** * Get the list of addresses that a server for the given service * should bind to. * * @param service_name name of the service * @param cfg configuration (which specifies the addresses) * @param addrs set (call by reference) to an array of pointers to the * addresses the server should bind to and listen on; the * array will be NULL-terminated (on success) * @param addr_lens set (call by reference) to an array of the lengths * of the respective 'struct sockaddr' struct in the 'addrs' * array (on success) * @return number of addresses found on success, * #GNUNET_SYSERR if the configuration * did not specify reasonable finding information or * if it specified a hostname that could not be resolved; * #GNUNET_NO if the number of addresses configured is * zero (in this case, `*addrs` and `*addr_lens` will be * set to NULL). */ int GNUNET_SERVICE_get_server_addresses (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, struct sockaddr ***addrs, socklen_t ** addr_lens) { int disablev6; struct GNUNET_NETWORK_Handle *desc; unsigned long long port; char *unixpath; struct addrinfo hints; struct addrinfo *res; struct addrinfo *pos; struct addrinfo *next; unsigned int i; int resi; int ret; int abstract; struct sockaddr **saddrs; socklen_t *saddrlens; char *hostname; *addrs = NULL; *addr_lens = NULL; desc = NULL; if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6")) { if (GNUNET_SYSERR == (disablev6 = GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6"))) return GNUNET_SYSERR; } else disablev6 = GNUNET_NO; if (!disablev6) { /* probe IPv6 support */ desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); if (NULL == desc) { if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) || (EACCES == errno)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket"); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_INFO, _ ("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"), service_name, STRERROR (errno)); disablev6 = GNUNET_YES; } else { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); desc = NULL; } } port = 0; if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Require valid port number for service `%s' in configuration!\n"), service_name); } if (port > 65535) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Require valid port number for service `%s' in configuration!\n"), service_name); return GNUNET_SYSERR; } } if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO")) { GNUNET_break (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "BINDTO", &hostname)); } else hostname = NULL; unixpath = NULL; abstract = GNUNET_NO; #ifdef AF_UNIX if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath))) { /* probe UNIX support */ struct sockaddr_un s_un; if (strlen (unixpath) >= sizeof (s_un.sun_path)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, (unsigned long long) sizeof (s_un.sun_path)); unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); LOG (GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath); } #ifdef LINUX abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg, "TESTING", "USE_ABSTRACT_SOCKETS"); if (GNUNET_SYSERR == abstract) abstract = GNUNET_NO; #endif if ((GNUNET_YES != abstract) && (GNUNET_OK != GNUNET_DISK_directory_create_for_file (unixpath))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "mkdir", unixpath); } if (NULL != unixpath) { desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); if (NULL == desc) { if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) || (EACCES == errno)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket"); GNUNET_free_non_null (hostname); GNUNET_free (unixpath); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_INFO, _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"), service_name, STRERROR (errno)); GNUNET_free (unixpath); unixpath = NULL; } else { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); desc = NULL; } } #endif if ((0 == port) && (NULL == unixpath)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"), service_name); GNUNET_free_non_null (hostname); return GNUNET_SYSERR; } if (0 == port) { saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *)); saddrlens = GNUNET_malloc (2 * sizeof (socklen_t)); add_unixpath (saddrs, saddrlens, unixpath, abstract); GNUNET_free_non_null (unixpath); GNUNET_free_non_null (hostname); *addrs = saddrs; *addr_lens = saddrlens; return 1; } if (NULL != hostname) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Resolving `%s' since that is where `%s' will bind to.\n", hostname, service_name); memset (&hints, 0, sizeof (struct addrinfo)); if (disablev6) hints.ai_family = AF_INET; hints.ai_protocol = IPPROTO_TCP; if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) || (res == NULL)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to resolve `%s': %s\n"), hostname, gai_strerror (ret)); GNUNET_free (hostname); GNUNET_free_non_null (unixpath); return GNUNET_SYSERR; } next = res; i = 0; while (NULL != (pos = next)) { next = pos->ai_next; if ((disablev6) && (pos->ai_family == AF_INET6)) continue; i++; } if (0 == i) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to find %saddress for `%s'.\n"), disablev6 ? "IPv4 " : "", hostname); freeaddrinfo (res); GNUNET_free (hostname); GNUNET_free_non_null (unixpath); return GNUNET_SYSERR; } resi = i; if (NULL != unixpath) resi++; saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); i = 0; if (NULL != unixpath) { add_unixpath (saddrs, saddrlens, unixpath, abstract); i++; } next = res; while (NULL != (pos = next)) { next = pos->ai_next; if ((disablev6) && (AF_INET6 == pos->ai_family)) continue; if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol)) continue; /* not TCP */ if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype)) continue; /* huh? */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n", service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen)); if (AF_INET == pos->ai_family) { GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen); saddrlens[i] = pos->ai_addrlen; saddrs[i] = GNUNET_malloc (saddrlens[i]); memcpy (saddrs[i], pos->ai_addr, saddrlens[i]); ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); } else { GNUNET_assert (AF_INET6 == pos->ai_family); GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen); saddrlens[i] = pos->ai_addrlen; saddrs[i] = GNUNET_malloc (saddrlens[i]); memcpy (saddrs[i], pos->ai_addr, saddrlens[i]); ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); } i++; } GNUNET_free (hostname); freeaddrinfo (res); resi = i; } else { /* will bind against everything, just set port */ if (disablev6) { /* V4-only */ resi = 1; if (NULL != unixpath) resi++; i = 0; saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); if (NULL != unixpath) { add_unixpath (saddrs, saddrlens, unixpath, abstract); i++; } saddrlens[i] = sizeof (struct sockaddr_in); saddrs[i] = GNUNET_malloc (saddrlens[i]); #if HAVE_SOCKADDR_IN_SIN_LEN ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i]; #endif ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); } else { /* dual stack */ resi = 2; if (NULL != unixpath) resi++; saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); i = 0; if (NULL != unixpath) { add_unixpath (saddrs, saddrlens, unixpath, abstract); i++; } saddrlens[i] = sizeof (struct sockaddr_in6); saddrs[i] = GNUNET_malloc (saddrlens[i]); #if HAVE_SOCKADDR_IN_SIN_LEN ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0]; #endif ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6; ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); i++; saddrlens[i] = sizeof (struct sockaddr_in); saddrs[i] = GNUNET_malloc (saddrlens[i]); #if HAVE_SOCKADDR_IN_SIN_LEN ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1]; #endif ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); } } GNUNET_free_non_null (unixpath); *addrs = saddrs; *addr_lens = saddrlens; return resi; } #ifdef MINGW /** * Read listen sockets from the parent process (ARM). * * @param sctx service context to initialize * @return #GNUNET_YES if ok, #GNUNET_NO if not ok (must bind yourself), * and #GNUNET_SYSERR on error. */ static int receive_sockets_from_parent (struct GNUNET_SERVICE_Context *sctx) { const char *env_buf; int fail; uint64_t count; uint64_t i; HANDLE lsocks_pipe; env_buf = getenv ("GNUNET_OS_READ_LSOCKS"); if ((NULL == env_buf) || (strlen (env_buf) <= 0)) return GNUNET_NO; /* Using W32 API directly here, because this pipe will * never be used outside of this function, and it's just too much of a bother * to create a GNUnet API that boxes a HANDLE (the way it is done with socks) */ lsocks_pipe = (HANDLE) strtoul (env_buf, NULL, 10); if ( (0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe)) return GNUNET_NO; fail = 1; do { int ret; int fail2; DWORD rd; ret = ReadFile (lsocks_pipe, &count, sizeof (count), &rd, NULL); if ((0 == ret) || (sizeof (count) != rd) || (0 == count)) break; sctx->lsocks = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (count + 1)); fail2 = 1; for (i = 0; i < count; i++) { WSAPROTOCOL_INFOA pi; uint64_t size; SOCKET s; ret = ReadFile (lsocks_pipe, &size, sizeof (size), &rd, NULL); if ( (0 == ret) || (sizeof (size) != rd) || (sizeof (pi) != size) ) break; ret = ReadFile (lsocks_pipe, &pi, sizeof (pi), &rd, NULL); if ( (0 == ret) || (sizeof (pi) != rd)) break; s = WSASocketA (pi.iAddressFamily, pi.iSocketType, pi.iProtocol, &pi, 0, WSA_FLAG_OVERLAPPED); sctx->lsocks[i] = GNUNET_NETWORK_socket_box_native (s); if (NULL == sctx->lsocks[i]) break; else if (i == count - 1) fail2 = 0; } if (fail2) break; sctx->lsocks[count] = NULL; fail = 0; } while (fail); CloseHandle (lsocks_pipe); if (fail) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Could not access a pre-bound socket, will try to bind myself\n")); for (i = 0; (i < count) && (NULL != sctx->lsocks[i]); i++) GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[i])); GNUNET_free_non_null (sctx->lsocks); sctx->lsocks = NULL; return GNUNET_NO; } return GNUNET_YES; } #endif /** * Setup addr, addrlen, idle_timeout * based on configuration! * * Configuration may specify: * - PORT (where to bind to for TCP) * - UNIXPATH (where to bind to for UNIX domain sockets) * - TIMEOUT (after how many ms does an inactive service timeout); * - DISABLEV6 (disable support for IPv6, otherwise we use dual-stack) * - BINDTO (hostname or IP address to bind to, otherwise we take everything) * - ACCEPT_FROM (only allow connections from specified IPv4 subnets) * - ACCEPT_FROM6 (only allow connections from specified IPv6 subnets) * - REJECT_FROM (disallow allow connections from specified IPv4 subnets) * - REJECT_FROM6 (disallow allow connections from specified IPv6 subnets) * * @param sctx service context to initialize * @return #GNUNET_OK if configuration succeeded */ static int setup_service (struct GNUNET_SERVICE_Context *sctx) { struct GNUNET_TIME_Relative idleout; int tolerant; #ifndef MINGW const char *nfds; unsigned int cnt; int flags; #endif if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, "TIMEOUT")) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (sctx->cfg, sctx->service_name, "TIMEOUT", &idleout)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Specified value for `%s' of service `%s' is invalid\n"), "TIMEOUT", sctx->service_name); return GNUNET_SYSERR; } sctx->timeout = idleout; } else sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL; if (GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, "TOLERANT")) { if (GNUNET_SYSERR == (tolerant = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name, "TOLERANT"))) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Specified value for `%s' of service `%s' is invalid\n"), "TOLERANT", sctx->service_name); return GNUNET_SYSERR; } } else tolerant = GNUNET_NO; #ifndef MINGW errno = 0; if ((NULL != (nfds = getenv ("LISTEN_FDS"))) && (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE)) { sctx->lsocks = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle *) * (cnt + 1)); while (0 < cnt--) { flags = fcntl (3 + cnt, F_GETFD); if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) || (NULL == (sctx->lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt)))) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Could not access pre-bound socket %u, will try to bind myself\n"), (unsigned int) 3 + cnt); cnt++; while (sctx->lsocks[cnt] != NULL) GNUNET_break (0 == GNUNET_NETWORK_socket_close (sctx->lsocks[cnt++])); GNUNET_free (sctx->lsocks); sctx->lsocks = NULL; break; } } unsetenv ("LISTEN_FDS"); } #else if (getenv ("GNUNET_OS_READ_LSOCKS") != NULL) { receive_sockets_from_parent (sctx); putenv ("GNUNET_OS_READ_LSOCKS="); } #endif if ((NULL == sctx->lsocks) && (GNUNET_SYSERR == GNUNET_SERVICE_get_server_addresses (sctx->service_name, sctx->cfg, &sctx->addrs, &sctx->addrlens))) return GNUNET_SYSERR; sctx->require_found = tolerant ? GNUNET_NO : GNUNET_YES; sctx->match_uid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name, "UNIX_MATCH_UID"); sctx->match_gid = GNUNET_CONFIGURATION_get_value_yesno (sctx->cfg, sctx->service_name, "UNIX_MATCH_GID"); process_acl4 (&sctx->v4_denied, sctx, "REJECT_FROM"); process_acl4 (&sctx->v4_allowed, sctx, "ACCEPT_FROM"); process_acl6 (&sctx->v6_denied, sctx, "REJECT_FROM6"); process_acl6 (&sctx->v6_allowed, sctx, "ACCEPT_FROM6"); return GNUNET_OK; } /** * Get the name of the user that'll be used * to provide the service. * * @param sctx service context * @return value of the 'USERNAME' option */ static char * get_user_name (struct GNUNET_SERVICE_Context *sctx) { char *un; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (sctx->cfg, sctx->service_name, "USERNAME", &un)) return NULL; return un; } /** * Write PID file. * * @param sctx service context * @param pid PID to write (should be equal to 'getpid()' * @return #GNUNET_OK on success (including no work to be done) */ static int write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid) { FILE *pidfd; char *pif; char *user; char *rdir; int len; if (NULL == (pif = get_pid_file_name (sctx))) return GNUNET_OK; /* no file desired */ user = get_user_name (sctx); rdir = GNUNET_strdup (pif); len = strlen (rdir); while ((len > 0) && (rdir[len] != DIR_SEPARATOR)) len--; rdir[len] = '\0'; if (0 != ACCESS (rdir, F_OK)) { /* we get to create a directory -- and claim it * as ours! */ (void) GNUNET_DISK_directory_create (rdir); if ((NULL != user) && (0 < strlen (user))) GNUNET_DISK_file_change_owner (rdir, user); } if (0 != ACCESS (rdir, W_OK | X_OK)) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", rdir); GNUNET_free (rdir); GNUNET_free_non_null (user); GNUNET_free (pif); return GNUNET_SYSERR; } GNUNET_free (rdir); pidfd = FOPEN (pif, "w"); if (NULL == pidfd) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "fopen", pif); GNUNET_free (pif); GNUNET_free_non_null (user); return GNUNET_SYSERR; } if (0 > FPRINTF (pidfd, "%u", pid)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fprintf", pif); GNUNET_break (0 == FCLOSE (pidfd)); if ((NULL != user) && (0 < strlen (user))) GNUNET_DISK_file_change_owner (pif, user); GNUNET_free_non_null (user); GNUNET_free (pif); return GNUNET_OK; } /** * Task run during shutdown. Stops the server/service. * * @param cls the `struct GNUNET_SERVICE_Context` * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVICE_Context *service = cls; struct GNUNET_SERVER_Handle *server = service->server; service->shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (service->options & GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN)) GNUNET_SERVER_stop_listening (server); else GNUNET_SERVER_destroy (server); } /** * Initial task for the service. * * @param cls service context * @param tc unused */ static void service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_SERVICE_Context *sctx = cls; unsigned int i; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; (void) GNUNET_SPEEDUP_start_ (sctx->cfg); GNUNET_RESOLVER_connect (sctx->cfg); if (NULL != sctx->lsocks) sctx->server = GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks, sctx->timeout, sctx->require_found); else sctx->server = GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens, sctx->timeout, sctx->require_found); if (NULL == sctx->server) { if (NULL != sctx->addrs) for (i = 0; NULL != sctx->addrs[i]; i++) LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to start `%s' at `%s'\n"), sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i])); sctx->ret = GNUNET_SYSERR; return; } #ifndef WINDOWS if (NULL != sctx->addrs) for (i = 0; NULL != sctx->addrs[i]; i++) if ((AF_UNIX == sctx->addrs[i]->sa_family) && ('\0' != ((const struct sockaddr_un *)sctx->addrs[i])->sun_path[0])) GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path, sctx->match_uid, sctx->match_gid); #endif if (0 == (sctx->options & GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN)) { /* install a task that will kill the server * process if the scheduler ever gets a shutdown signal */ sctx->shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, sctx); } sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers)); memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers)); i = 0; while (NULL != sctx->my_handlers[i].callback) sctx->my_handlers[i++].callback_cls = sctx; GNUNET_SERVER_add_handlers (sctx->server, sctx->my_handlers); if (-1 != sctx->ready_confirm_fd) { GNUNET_break (1 == WRITE (sctx->ready_confirm_fd, ".", 1)); GNUNET_break (0 == CLOSE (sctx->ready_confirm_fd)); sctx->ready_confirm_fd = -1; write_pid_file (sctx, getpid ()); } if (NULL != sctx->addrs) { i = 0; while (NULL != sctx->addrs[i]) { LOG (GNUNET_ERROR_TYPE_INFO, _("Service `%s' runs at %s\n"), sctx->service_name, GNUNET_a2s (sctx->addrs[i], sctx->addrlens[i])); i++; } } sctx->task (sctx->task_cls, sctx->server, sctx->cfg); } /** * Detach from terminal. * * @param sctx service context * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int detach_terminal (struct GNUNET_SERVICE_Context *sctx) { #ifndef MINGW pid_t pid; int nullfd; int filedes[2]; if (0 != PIPE (filedes)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe"); return GNUNET_SYSERR; } pid = fork (); if (pid < 0) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); return GNUNET_SYSERR; } if (0 != pid) { /* Parent */ char c; GNUNET_break (0 == CLOSE (filedes[1])); c = 'X'; if (1 != READ (filedes[0], &c, sizeof (char))) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "read"); fflush (stdout); switch (c) { case '.': exit (0); case 'I': LOG (GNUNET_ERROR_TYPE_INFO, _("Service process failed to initialize\n")); break; case 'S': LOG (GNUNET_ERROR_TYPE_INFO, _("Service process could not initialize server function\n")); break; case 'X': LOG (GNUNET_ERROR_TYPE_INFO, _("Service process failed to report status\n")); break; } exit (1); /* child reported error */ } GNUNET_break (0 == CLOSE (0)); GNUNET_break (0 == CLOSE (1)); GNUNET_break (0 == CLOSE (filedes[0])); nullfd = OPEN ("/dev/null", O_RDWR | O_APPEND); if (nullfd < 0) return GNUNET_SYSERR; /* set stdin/stdout to /dev/null */ if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0)) { LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); (void) CLOSE (nullfd); return GNUNET_SYSERR; } (void) CLOSE (nullfd); /* Detach from controlling terminal */ pid = setsid (); if (-1 == pid) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "setsid"); sctx->ready_confirm_fd = filedes[1]; #else /* FIXME: we probably need to do something else * elsewhere in order to fork the process itself... */ FreeConsole (); #endif return GNUNET_OK; } /** * Set user ID. * * @param sctx service context * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int set_user_id (struct GNUNET_SERVICE_Context *sctx) { char *user; if (NULL == (user = get_user_name (sctx))) return GNUNET_OK; /* keep */ #ifndef MINGW struct passwd *pws; errno = 0; pws = getpwnam (user); if (NULL == pws) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot obtain information about user `%s': %s\n"), user, errno == 0 ? _("No such user") : STRERROR (errno)); GNUNET_free (user); return GNUNET_SYSERR; } if ((0 != setgid (pws->pw_gid)) || (0 != setegid (pws->pw_gid)) || #if HAVE_INITGROUPS (0 != initgroups (user, pws->pw_gid)) || #endif (0 != setuid (pws->pw_uid)) || (0 != seteuid (pws->pw_uid))) { if ((0 != setregid (pws->pw_gid, pws->pw_gid)) || (0 != setreuid (pws->pw_uid, pws->pw_uid))) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot change user/group to `%s': %s\n"), user, STRERROR (errno)); GNUNET_free (user); return GNUNET_SYSERR; } } #endif GNUNET_free (user); return GNUNET_OK; } /** * Delete the PID file that was created by our parent. * * @param sctx service context */ static void pid_file_delete (struct GNUNET_SERVICE_Context *sctx) { char *pif = get_pid_file_name (sctx); if (NULL == pif) return; /* no PID file */ if (0 != UNLINK (pif)) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", pif); GNUNET_free (pif); } /** * Run a standard GNUnet service startup sequence (initialize loggers * and configuration, parse options). * * @param argc number of command line arguments * @param argv command line arguments * @param service_name our service name * @param options service options * @param task main task of the service * @param task_cls closure for @a task * @return #GNUNET_SYSERR on error, #GNUNET_OK * if we shutdown nicely */ int GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name, enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_Main task, void *task_cls) { #define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0) int err; int ret; char *cfg_fn; char *opt_cfg_fn; char *loglev; char *logfile; int do_daemonize; unsigned int i; unsigned long long skew_offset; unsigned long long skew_variance; long long clock_offset; struct GNUNET_SERVICE_Context sctx; struct GNUNET_CONFIGURATION_Handle *cfg; const char *xdg; struct GNUNET_GETOPT_CommandLineOption service_options[] = { GNUNET_GETOPT_OPTION_CFG_FILE (&opt_cfg_fn), {'d', "daemonize", NULL, gettext_noop ("do daemonize (detach from terminal)"), 0, GNUNET_GETOPT_set_one, &do_daemonize}, GNUNET_GETOPT_OPTION_HELP (NULL), GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev), GNUNET_GETOPT_OPTION_LOGFILE (&logfile), GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION), GNUNET_GETOPT_OPTION_END }; err = 1; do_daemonize = 0; logfile = NULL; loglev = NULL; opt_cfg_fn = NULL; xdg = getenv ("XDG_CONFIG_HOME"); if (NULL != xdg) GNUNET_asprintf (&cfg_fn, "%s%s%s", xdg, DIR_SEPARATOR_STR, "gnunet.conf"); else cfg_fn = GNUNET_strdup (GNUNET_DEFAULT_USER_CONFIG_FILE); memset (&sctx, 0, sizeof (sctx)); sctx.options = options; sctx.ready_confirm_fd = -1; sctx.ret = GNUNET_OK; sctx.timeout = GNUNET_TIME_UNIT_FOREVER_REL; sctx.task = task; sctx.task_cls = task_cls; sctx.service_name = service_name; sctx.cfg = cfg = GNUNET_CONFIGURATION_create (); /* setup subsystems */ ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv); if (GNUNET_SYSERR == ret) goto shutdown; if (GNUNET_NO == ret) { err = 0; goto shutdown; } if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile)) HANDLE_ERROR; if (NULL == opt_cfg_fn) opt_cfg_fn = GNUNET_strdup (cfg_fn); if (GNUNET_YES == GNUNET_DISK_file_test (opt_cfg_fn)) { if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, opt_cfg_fn)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Malformed configuration file `%s', exit ...\n"), opt_cfg_fn); goto shutdown; } } else { if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Malformed configuration, exit ...\n")); goto shutdown; } if (0 != strcmp (opt_cfg_fn, cfg_fn)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not access configuration file `%s'\n"), opt_cfg_fn); } if (GNUNET_OK != setup_service (&sctx)) goto shutdown; if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sctx))) HANDLE_ERROR; if (GNUNET_OK != set_user_id (&sctx)) goto shutdown; LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' runs with configuration from `%s'\n", service_name, opt_cfg_fn); if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING", "SKEW_OFFSET", &skew_offset)) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (sctx.cfg, "TESTING", "SKEW_VARIANCE", &skew_variance))) { clock_offset = skew_offset - skew_variance; GNUNET_TIME_set_offset (clock_offset); LOG (GNUNET_ERROR_TYPE_DEBUG, "Skewing clock by %dll ms\n", clock_offset); } /* actually run service */ err = 0; GNUNET_SCHEDULER_run (&service_task, &sctx); /* shutdown */ if ((1 == do_daemonize) && (NULL != sctx.server)) pid_file_delete (&sctx); GNUNET_free_non_null (sctx.my_handlers); shutdown: if (-1 != sctx.ready_confirm_fd) { if (1 != WRITE (sctx.ready_confirm_fd, err ? "I" : "S", 1)) LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write"); GNUNET_break (0 == CLOSE (sctx.ready_confirm_fd)); } #if HAVE_MALLINFO { char *counter; if ( (GNUNET_YES == GNUNET_CONFIGURATION_have_value (sctx.cfg, service_name, "GAUGER_HEAP")) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (sctx.cfg, service_name, "GAUGER_HEAP", &counter)) ) { struct mallinfo mi; mi = mallinfo (); GAUGER (service_name, counter, mi.usmblks, "blocks"); GNUNET_free (counter); } } #endif GNUNET_SPEEDUP_stop_ (); GNUNET_CONFIGURATION_destroy (cfg); i = 0; if (NULL != sctx.addrs) while (NULL != sctx.addrs[i]) GNUNET_free (sctx.addrs[i++]); GNUNET_free_non_null (sctx.addrs); GNUNET_free_non_null (sctx.addrlens); GNUNET_free_non_null (logfile); GNUNET_free_non_null (loglev); GNUNET_free (cfg_fn); GNUNET_free_non_null (opt_cfg_fn); GNUNET_free_non_null (sctx.v4_denied); GNUNET_free_non_null (sctx.v6_denied); GNUNET_free_non_null (sctx.v4_allowed); GNUNET_free_non_null (sctx.v6_allowed); return err ? GNUNET_SYSERR : sctx.ret; } /** * Run a service startup sequence within an existing * initialized system. * * @param service_name our service name * @param cfg configuration to use * @param options service options * @return NULL on error, service handle */ struct GNUNET_SERVICE_Context * GNUNET_SERVICE_start (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SERVICE_Options options) { int i; struct GNUNET_SERVICE_Context *sctx; sctx = GNUNET_new (struct GNUNET_SERVICE_Context); sctx->ready_confirm_fd = -1; /* no daemonizing */ sctx->ret = GNUNET_OK; sctx->timeout = GNUNET_TIME_UNIT_FOREVER_REL; sctx->service_name = service_name; sctx->cfg = cfg; sctx->options = options; /* setup subsystems */ if (GNUNET_OK != setup_service (sctx)) { GNUNET_SERVICE_stop (sctx); return NULL; } if (NULL != sctx->lsocks) sctx->server = GNUNET_SERVER_create_with_sockets (&check_access, sctx, sctx->lsocks, sctx->timeout, sctx->require_found); else sctx->server = GNUNET_SERVER_create (&check_access, sctx, sctx->addrs, sctx->addrlens, sctx->timeout, sctx->require_found); if (NULL == sctx->server) { GNUNET_SERVICE_stop (sctx); return NULL; } #ifndef WINDOWS if (NULL != sctx->addrs) for (i = 0; NULL != sctx->addrs[i]; i++) if ((AF_UNIX == sctx->addrs[i]->sa_family) && ('\0' != ((const struct sockaddr_un *)sctx->addrs[i])->sun_path[0])) GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sctx->addrs[i])->sun_path, sctx->match_uid, sctx->match_gid); #endif sctx->my_handlers = GNUNET_malloc (sizeof (defhandlers)); memcpy (sctx->my_handlers, defhandlers, sizeof (defhandlers)); i = 0; while ((sctx->my_handlers[i].callback != NULL)) sctx->my_handlers[i++].callback_cls = sctx; GNUNET_SERVER_add_handlers (sctx->server, sctx->my_handlers); return sctx; } /** * Obtain the server used by a service. Note that the server must NOT * be destroyed by the caller. * * @param ctx the service context returned from the start function * @return handle to the server for this service, NULL if there is none */ struct GNUNET_SERVER_Handle * GNUNET_SERVICE_get_server (struct GNUNET_SERVICE_Context *ctx) { return ctx->server; } /** * Stop a service that was started with "GNUNET_SERVICE_start". * * @param sctx the service context returned from the start function */ void GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx) { unsigned int i; #if HAVE_MALLINFO { char *counter; if ( (GNUNET_YES == GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, "GAUGER_HEAP")) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (sctx->cfg, sctx->service_name, "GAUGER_HEAP", &counter)) ) { struct mallinfo mi; mi = mallinfo (); GAUGER (sctx->service_name, counter, mi.usmblks, "blocks"); GNUNET_free (counter); } } #endif if (GNUNET_SCHEDULER_NO_TASK != sctx->shutdown_task) { GNUNET_SCHEDULER_cancel (sctx->shutdown_task); sctx->shutdown_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sctx->server) GNUNET_SERVER_destroy (sctx->server); GNUNET_free_non_null (sctx->my_handlers); if (NULL != sctx->addrs) { i = 0; while (NULL != sctx->addrs[i]) GNUNET_free (sctx->addrs[i++]); GNUNET_free (sctx->addrs); } GNUNET_free_non_null (sctx->addrlens); GNUNET_free_non_null (sctx->v4_denied); GNUNET_free_non_null (sctx->v6_denied); GNUNET_free_non_null (sctx->v4_allowed); GNUNET_free_non_null (sctx->v6_allowed); GNUNET_free (sctx); } /* end of service.c */ gnunet-0.10.1/src/util/test_strings_to_data.c0000644000175000017500000000336312225777501016162 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file util/test_strings_to_data.c * @brief testcase for strings.c */ #include "platform.h" #include "gnunet_util_lib.h" int main (int argc, char *argv[]) { char buf[1024]; char *end; char src[128]; char dst[128]; unsigned int i; int ret = 0; GNUNET_log_setup ("util", "DEBUG", NULL); for (i=0;itype) { case GNUNET_TESTBED_ET_OPERATION_FINISHED: /* Will be reached when we destroy peers */ FAIL_TEST (PEERS_STOPPED == result); FAIL_TEST (NULL == event->op_cls); FAIL_TEST (NULL == event->details.operation_finished.emsg); FAIL_TEST (NULL == event->details.operation_finished.generic); if (event->op == peer1.operation) { GNUNET_TESTBED_operation_done (peer1.operation); peer1.operation = NULL; peer1.peer = NULL; } else if (event->op == peer2.operation) { GNUNET_TESTBED_operation_done (peer2.operation); peer2.operation = NULL; peer2.peer = NULL; } else FAIL_TEST (0); if ((NULL == peer1.peer) && (NULL == peer2.peer)) { result = SUCCESS; GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } break; case GNUNET_TESTBED_ET_PEER_START: FAIL_TEST (INIT == result); FAIL_TEST (event->details.peer_start.host == host); if (event->details.peer_start.peer == peer1.peer) { peer1.is_running = GNUNET_YES; GNUNET_TESTBED_operation_done (peer1.operation); peer1.operation = NULL; } else if (event->details.peer_start.peer == peer2.peer) { peer2.is_running = GNUNET_YES; GNUNET_TESTBED_operation_done (peer2.operation); peer2.operation = NULL; } else FAIL_TEST (0); if ((GNUNET_YES == peer1.is_running) && (GNUNET_YES == peer2.is_running)) { result = PEERS_STARTED; common_operation = GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer, peer2.peer); } break; case GNUNET_TESTBED_ET_PEER_STOP: FAIL_TEST (PEERS_CONNECTED_2 == result); if (event->details.peer_stop.peer == peer1.peer) { peer1.is_running = GNUNET_NO; GNUNET_TESTBED_operation_done (peer1.operation); peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer); } else if (event->details.peer_stop.peer == peer2.peer) { peer2.is_running = GNUNET_NO; GNUNET_TESTBED_operation_done (peer2.operation); peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer); } else FAIL_TEST (0); if ((GNUNET_NO == peer1.is_running) && (GNUNET_NO == peer2.is_running)) result = PEERS_STOPPED; break; case GNUNET_TESTBED_ET_CONNECT: switch (result) { case PEERS_STARTED: FAIL_TEST (NULL == peer1.operation); FAIL_TEST (NULL == peer2.operation); FAIL_TEST (NULL != common_operation); FAIL_TEST ((event->details.peer_connect.peer1 == peer1.peer) && (event->details.peer_connect.peer2 == peer2.peer)); GNUNET_TESTBED_operation_done (common_operation); common_operation = NULL; result = PEERS_CONNECTED; LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n"); delayed_connect_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), &do_delayed_connect, NULL); break; case PEERS_CONNECTED: FAIL_TEST (NULL == peer1.operation); FAIL_TEST (NULL == peer2.operation); FAIL_TEST (NULL != common_operation); GNUNET_TESTBED_operation_done (common_operation); common_operation = NULL; result = PEERS_CONNECTED_2; LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n"); peer1.operation = GNUNET_TESTBED_peer_stop (NULL, peer1.peer, NULL, NULL); peer2.operation = GNUNET_TESTBED_peer_stop (NULL, peer2.peer, NULL, NULL); break; default: FAIL_TEST (0); } break; default: FAIL_TEST (0); }; } /** * Functions of this signature are called when a peer has been successfully * created * * @param cls the closure from GNUNET_TESTBED_peer_create() * @param peer the handle for the created peer; NULL on any error during * creation * @param emsg NULL if peer is not NULL; else MAY contain the error description */ static void peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) { struct PeerContext *pc = cls; FAIL_TEST (NULL != pc->operation); FAIL_TEST (NULL != peer); FAIL_TEST (NULL == pc->peer); pc->peer = peer; GNUNET_TESTBED_operation_done (pc->operation); pc->operation = GNUNET_TESTBED_peer_start (NULL, pc->peer, NULL, NULL); } /** * Callback which will be called to after a host registration succeeded or failed * * @param cls the host which has been registered * @param emsg the error message; NULL if host registration is successful */ static void registration_comp (void *cls, const char *emsg) { FAIL_TEST (cls == neighbour); reg_handle = NULL; peer1.operation = GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb, &peer1); peer2.operation = GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb, &peer2); FAIL_TEST (NULL != peer1.operation); FAIL_TEST (NULL != peer2.operation); } /** * Callback to signal successfull startup of the controller process * * @param cls the closure from GNUNET_TESTBED_controller_start() * @param cfg the configuration with which the controller has been started; * NULL if status is not GNUNET_OK * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ static void status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int status) { uint64_t event_mask; if (GNUNET_OK != status) { cp = NULL; FAIL_TEST (0); } event_mask = 0; event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); controller = GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb, NULL); FAIL_TEST (NULL != controller); neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); FAIL_TEST (NULL != neighbour); reg_handle = GNUNET_TESTBED_register_host (controller, neighbour, ®istration_comp, neighbour); FAIL_TEST (NULL != reg_handle); } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { cfg = GNUNET_CONFIGURATION_dup (config); host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); FAIL_TEST (NULL != host); cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { int ret; char *const argv2[] = { "test_testbed_api_2peers_1controller", "-c", "test_testbed_api.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; result = INIT; ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testbed_api_2peers_1controller", "nohelp", options, &run, NULL); if ((GNUNET_OK != ret) || (SUCCESS != result)) return 1; return 0; } /* end of test_testbed_api_2peers_1controller.c */ gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf0000644000175000017500000000021012233724131024617 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = SCALE_FREE SCALE_FREE_TOPOLOGY_CAP = 70 SCALE_FREE_TOPOLOGY_M = 5 gnunet-0.10.1/src/testbed/testbed_api_sd.c0000644000175000017500000001064112255010512015343 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_sd.c * @brief functions to calculate standard deviation * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "testbed_api_sd.h" /** * An entry to hold data which will be used to calculate SD */ struct SDEntry { /** * DLL next pointer */ struct SDEntry *next; /** * DLL prev pointer */ struct SDEntry *prev; /** * The value to store */ unsigned int amount; }; /** * Opaque handle for calculating SD */ struct SDHandle { /** * DLL head for storing entries */ struct SDEntry *head; /** * DLL tail for storing entries */ struct SDEntry *tail; /** * Squared sum of data values */ unsigned long long sqsum; /** * Sum of the data values */ unsigned long sum; /** * The average of data amounts */ float avg; /** * The variance */ double vr; /** * Number of data values; also the length of DLL containing SDEntries */ unsigned int cnt; /** * max number of entries we can have in the DLL */ unsigned int max_cnt; }; /** * Initialize standard deviation calculation handle * * @param max_cnt the maximum number of readings to keep * @return the initialized handle */ struct SDHandle * GNUNET_TESTBED_SD_init_ (unsigned int max_cnt) { struct SDHandle *h; GNUNET_assert (1 < max_cnt); h = GNUNET_new (struct SDHandle); h->max_cnt = max_cnt; return h; } /** * Frees the memory allocated to the SD handle * * @param h the SD handle */ void GNUNET_TESTBED_SD_destroy_ (struct SDHandle *h) { struct SDEntry *entry; while (NULL != (entry = h->head)) { GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry); GNUNET_free (entry); } GNUNET_free (h); } /** * Add a reading to SD * * @param h the SD handle * @param amount the reading value */ void GNUNET_TESTBED_SD_add_data_ (struct SDHandle *h, unsigned int amount) { struct SDEntry *entry; double sqavg; double sqsum_avg; entry = NULL; if (h->cnt == h->max_cnt) { entry = h->head; GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry); h->sum -= entry->amount; h->sqsum -= ((unsigned long) entry->amount) * ((unsigned long) entry->amount); h->cnt--; } GNUNET_assert (h->cnt < h->max_cnt); if (NULL == entry) entry = GNUNET_new (struct SDEntry); entry->amount = amount; GNUNET_CONTAINER_DLL_insert_tail (h->head, h->tail, entry); h->sum += amount; h->cnt++; h->avg = ((float) h->sum) / ((float) h->cnt); h->sqsum += ((unsigned long) amount) * ((unsigned long) amount); sqsum_avg = ((double) h->sqsum) / ((double) h->cnt); sqavg = ((double) h->avg) * ((double) h->avg); h->vr = sqsum_avg - sqavg; } /** * Calculates the factor by which the given amount differs * * @param h the SDhandle * @param amount the value for which the deviation is returned * @param factor the factor by which the given amont differs * @return GNUNET_SYSERR if the deviation cannot * be calculated; GNUNET_OK if the deviation is returned through factor */ int GNUNET_TESTBED_SD_deviation_factor_ (struct SDHandle *h, unsigned int amount, int *factor) { double diff; int f; int n; if (h->cnt < 2) return GNUNET_SYSERR; if (((float) amount) > h->avg) { diff = ((float) amount) - h->avg; f = 1; } else { diff = h->avg - ((float) amount); f = -1; } diff *= diff; for (n = 1; n < 4; n++) if (diff < (((double) (n * n)) * h->vr)) break; *factor = f * n; return GNUNET_OK; } /* end of testbed_api_sd.c */ gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topologyline.conf0000644000175000017500000000011312233724131023617 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = LINE gnunet-0.10.1/src/testbed/testbed_api_peers.h0000644000175000017500000001362312252137227016075 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_peers.h * @brief internal API to access the 'peers' subsystem * @author Christian Grothoff * @author Sree Harsha Totakura */ #ifndef NEW_TESTING_API_PEERS_H #define NEW_TESTING_API_PEERS_H #include "gnunet_testbed_service.h" #include "gnunet_helper_lib.h" /** * Enumeration of possible states a peer could be in */ enum PeerState { /** * State to signify that this peer is invalid */ TESTBED_PS_INVALID, /** * The peer has been created */ TESTBED_PS_CREATED, /** * The peer is running */ TESTBED_PS_STARTED, /** * The peer is stopped */ TESTBED_PS_STOPPED, }; /** * A peer controlled by the testing framework. A peer runs * at a particular host. */ struct GNUNET_TESTBED_Peer { /** * peer list DLL */ struct GNUNET_TESTBED_Peer *next; /** * peer list DLL */ struct GNUNET_TESTBED_Peer *prev; /** * Our controller context (not necessarily the controller * that is responsible for starting/running the peer!). */ struct GNUNET_TESTBED_Controller *controller; /** * Which host does this peer run on? */ struct GNUNET_TESTBED_Host *host; /** * Globally unique ID of the peer. */ uint32_t unique_id; /** * Peer's state */ enum PeerState state; /** * Has an underlay model already set for this peer? */ uint8_t underlay_model_exists; }; /** * Data for the OperationType OP_PEER_CREATE */ struct PeerCreateData { /** * The host where the peer has to be created */ struct GNUNET_TESTBED_Host *host; /** * The template configuration of the peer */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * The call back to call when we receive peer create success message */ GNUNET_TESTBED_PeerCreateCallback cb; /** * The closure for the above callback */ void *cls; /** * The peer structure to return when we get success message */ struct GNUNET_TESTBED_Peer *peer; }; /** * Data for OperationType OP_PEER_START and OP_PEER_STOP */ struct PeerEventData { /** * The handle of the peer to start */ struct GNUNET_TESTBED_Peer *peer; /** * The Peer churn callback to call when this operation is completed */ GNUNET_TESTBED_PeerChurnCallback pcc; /** * Closure for the above callback */ void *pcc_cls; }; /** * Data for the OperationType OP_PEER_DESTROY; */ struct PeerDestroyData { /** * The peer structure */ struct GNUNET_TESTBED_Peer *peer; //PEERDESTROYDATA }; /** * Data for the OperationType OP_PEER_INFO */ struct PeerInfoData { /** * The peer whose information has been requested */ struct GNUNET_TESTBED_Peer *peer; /** * The Peer info callback to call when this operation has completed */ GNUNET_TESTBED_PeerInfoCallback cb; /** * The closure for peer info callback */ void *cb_cls; /** * The type of peer information requested */ enum GNUNET_TESTBED_PeerInformationType pit; }; /** * Data for the operations of type OP_PEER_RECONFIGURE */ struct PeerReconfigureData { /** * The peer whose information has been requested */ struct GNUNET_TESTBED_Peer *peer; /** * The serialized new configuration template */ char *config; /** * the size of the serialized configuration */ uint16_t cfg_size; }; /** * Data structure for OperationType OP_OVERLAY_CONNECT */ struct OverlayConnectData { /** * Peer A to connect to peer B */ struct GNUNET_TESTBED_Peer *p1; /** * Peer B */ struct GNUNET_TESTBED_Peer *p2; /** * The operation completion callback to call once this operation is done */ GNUNET_TESTBED_OperationCompletionCallback cb; /** * The closure for the above callback */ void *cb_cls; /** * OperationContext for forwarded operations generated when peer1's controller doesn't have the * configuration of peer2's controller for linking laterally to attemp an * overlay connection between peer 1 and peer 2. */ struct OperationContext *sub_opc; }; struct ManageServiceData { GNUNET_TESTBED_OperationCompletionCallback cb; void *cb_cls; struct GNUNET_TESTBED_Peer *peer; char *service_name; unsigned int start; uint16_t msize; }; /** * Generate PeerGetConfigurationMessage * * @param peer_id the id of the peer whose information we have to get * @param operation_id the ip of the operation that should be represented in * the message * @return the PeerGetConfigurationMessage */ struct GNUNET_TESTBED_PeerGetConfigurationMessage * GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id, uint64_t operation_id); /** * Adds a peer to the peer list * * @param peer the peer to add to the peer list */ void GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer); /** * Removes a peer from the peer list * * @param peer the peer to remove */ void GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer); /** * Frees all peers */ void GNUNET_TESTBED_cleanup_peers_ (void); #endif /* end of testbed_api_peers.h */ gnunet-0.10.1/src/testbed/gnunet-helper-testbed.c0000644000175000017500000004337112301361474016615 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-helper-testbed.c * @brief Helper binary that is started from a remote controller to start * gnunet-service-testbed. This binary also receives configuration * from the remove controller which is put in a temporary location * with ports and paths fixed so that gnunet-service-testbed runs * without any hurdles. * * This helper monitors for three termination events. They are: (1)The * stdin of the helper is closed for reading; (2)the helper received * SIGTERM/SIGINT; (3)the testbed crashed. In case of events 1 and 2 * the helper kills the testbed service. When testbed crashed (event * 3), the helper should send a SIGTERM to its own process group; this * behaviour will help terminate any child processes (peers) testbed * has started and prevents them from leaking and running forever. * * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_testbed_service.h" #include "testbed_helper.h" #include "testbed_api.h" #include /** * Generic logging shortcut */ #define LOG(kind, ...) \ GNUNET_log (kind, __VA_ARGS__) /** * Debug logging shorthand */ #define LOG_DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * We need pipe control only on WINDOWS */ #if WINDOWS #define PIPE_CONTROL GNUNET_YES #else #define PIPE_CONTROL GNUNET_NO #endif /** * Context for a single write on a chunk of memory */ struct WriteContext { /** * The data to write */ void *data; /** * The length of the data */ size_t length; /** * The current position from where the write operation should begin */ size_t pos; }; /** * Handle to the testing system */ static struct GNUNET_TESTING_System *test_system; /** * Our message stream tokenizer */ struct GNUNET_SERVER_MessageStreamTokenizer *tokenizer; /** * Disk handle from stdin */ static struct GNUNET_DISK_FileHandle *stdin_fd; /** * Disk handle for stdout */ static struct GNUNET_DISK_FileHandle *stdout_fd; /** * The process handle to the testbed service */ static struct GNUNET_OS_Process *testbed; /** * Pipe used to communicate shutdown via signal. */ static struct GNUNET_DISK_PipeHandle *sigpipe; /** * Task identifier for the read task */ static GNUNET_SCHEDULER_TaskIdentifier read_task_id; /** * Task identifier for the write task */ static GNUNET_SCHEDULER_TaskIdentifier write_task_id; /** * Task to kill the child */ static GNUNET_SCHEDULER_TaskIdentifier child_death_task_id; /** * shutdown task id */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id; /** * Are we done reading messages from stdin? */ static int done_reading; /** * Result to return in case we fail */ static int status; /** * Task to shut down cleanly * * @param cls NULL * @param tc the task context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG_DEBUG ("Shutting down\n"); shutdown_task_id = GNUNET_SCHEDULER_NO_TASK; if (NULL != testbed) { LOG_DEBUG ("Killing testbed\n"); GNUNET_break (0 == GNUNET_OS_process_kill (testbed, GNUNET_TERM_SIG)); } if (GNUNET_SCHEDULER_NO_TASK != read_task_id) { GNUNET_SCHEDULER_cancel (read_task_id); read_task_id = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != write_task_id) { GNUNET_SCHEDULER_cancel (write_task_id); write_task_id = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != child_death_task_id) { GNUNET_SCHEDULER_cancel (child_death_task_id); child_death_task_id = GNUNET_SCHEDULER_NO_TASK; } if (NULL != stdin_fd) (void) GNUNET_DISK_file_close (stdin_fd); if (NULL != stdout_fd) (void) GNUNET_DISK_file_close (stdout_fd); GNUNET_SERVER_mst_destroy (tokenizer); tokenizer = NULL; if (NULL != testbed) { GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (testbed)); GNUNET_OS_process_destroy (testbed); testbed = NULL; } if (NULL != test_system) { GNUNET_TESTING_system_destroy (test_system, GNUNET_YES); test_system = NULL; } } /** * Scheduler shutdown task to be run now. */ static void shutdown_now (void) { if (GNUNET_SCHEDULER_NO_TASK != shutdown_task_id) GNUNET_SCHEDULER_cancel (shutdown_task_id); shutdown_task_id = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } /** * Task to write to the standard out * * @param cls the WriteContext * @param tc the TaskContext */ static void write_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct WriteContext *wc = cls; ssize_t bytes_wrote; GNUNET_assert (NULL != wc); write_task_id = GNUNET_SCHEDULER_NO_TASK; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) { GNUNET_free (wc->data); GNUNET_free (wc); return; } bytes_wrote = GNUNET_DISK_file_write (stdout_fd, wc->data + wc->pos, wc->length - wc->pos); if (GNUNET_SYSERR == bytes_wrote) { LOG (GNUNET_ERROR_TYPE_WARNING, "Cannot reply back configuration\n"); GNUNET_free (wc->data); GNUNET_free (wc); return; } wc->pos += bytes_wrote; if (wc->pos == wc->length) { GNUNET_free (wc->data); GNUNET_free (wc); return; } write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, stdout_fd, &write_task, wc); } /** * Task triggered whenever we receive a SIGCHLD (child * process died). * * @param cls closure, NULL if we need to self-restart * @param tc context */ static void child_death_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { const struct GNUNET_DISK_FileHandle *pr; char c[16]; enum GNUNET_OS_ProcessStatusType type; unsigned long code; int ret; pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); child_death_task_id = GNUNET_SCHEDULER_NO_TASK; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) { child_death_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, &child_death_task, NULL); return; } /* consume the signal */ GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); LOG_DEBUG ("Got SIGCHLD\n"); if (NULL == testbed) { GNUNET_break (0); return; } GNUNET_break (GNUNET_SYSERR != (ret = GNUNET_OS_process_status (testbed, &type, &code))); if (GNUNET_NO != ret) { GNUNET_OS_process_destroy (testbed); testbed = NULL; /* Send SIGTERM to our process group */ if (0 != PLIBC_KILL (0, GNUNET_TERM_SIG)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "signal"); shutdown_now (); /* Couldn't send the signal, we shutdown frowning */ } return; } LOG_DEBUG ("Child hasn't died. Resuming to monitor its status\n"); child_death_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, &child_death_task, NULL); } /** * Functions with this signature are called whenever a * complete message is received by the tokenizer. * * Do not call GNUNET_SERVER_mst_destroy in callback * * @param cls closure * @param client identification of the client * @param message the actual message * * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing */ static int tokenizer_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_HelperInit *msg; struct GNUNET_TESTBED_HelperReply *reply; struct GNUNET_CONFIGURATION_Handle *cfg; struct WriteContext *wc; char *binary; char *trusted_ip; char *hostname; char *config; char *xconfig; char *evstr; //char *str; size_t config_size; uLongf ul_config_size; size_t xconfig_size; uint16_t trusted_ip_size; uint16_t hostname_size; uint16_t msize; msize = ntohs (message->size); if ((sizeof (struct GNUNET_TESTBED_HelperInit) >= msize) || (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT != ntohs (message->type))) { LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n"); goto error; } msg = (const struct GNUNET_TESTBED_HelperInit *) message; trusted_ip_size = ntohs (msg->trusted_ip_size); trusted_ip = (char *) &msg[1]; if ('\0' != trusted_ip[trusted_ip_size]) { LOG (GNUNET_ERROR_TYPE_WARNING, "Trusted IP cannot be empty -- exiting\n"); goto error; } hostname_size = ntohs (msg->hostname_size); if ((sizeof (struct GNUNET_TESTBED_HelperInit) + trusted_ip_size + 1 + hostname_size) >= msize) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, "Received unexpected message -- exiting\n"); goto error; } ul_config_size = (uLongf) ntohs (msg->config_size); config = GNUNET_malloc (ul_config_size); xconfig_size = ntohs (message->size) - (trusted_ip_size + 1 + sizeof (struct GNUNET_TESTBED_HelperInit)); if (Z_OK != uncompress ((Bytef *) config, &ul_config_size, (const Bytef *) (trusted_ip + trusted_ip_size + 1 + hostname_size), (uLongf) xconfig_size)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Error while uncompressing config -- exiting\n"); GNUNET_free (config); goto error; } cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, ul_config_size, GNUNET_NO)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Unable to deserialize config -- exiting\n"); GNUNET_free (config); goto error; } GNUNET_free (config); hostname = NULL; if (0 != hostname_size) { hostname = GNUNET_malloc (hostname_size + 1); (void) strncpy (hostname, ((char *) &msg[1]) + trusted_ip_size + 1, hostname_size); hostname[hostname_size] = '\0'; } /* unset GNUNET_TESTING_PREFIX if present as it is more relevant for testbed */ evstr = getenv (GNUNET_TESTING_PREFIX); if (NULL != evstr) { /* unsetting the variable will invalidate the pointer! */ evstr = GNUNET_strdup (evstr); #ifdef WINDOWS GNUNET_break (0 != SetEnvironmentVariable (GNUNET_TESTING_PREFIX, NULL)); #else GNUNET_break (0 == unsetenv (GNUNET_TESTING_PREFIX)); #endif } test_system = GNUNET_TESTING_system_create ("testbed-helper", trusted_ip, hostname, NULL); if (NULL != evstr) { #ifdef WINDOWS GNUNET_assert (0 != SetEnvironmentVariable (GNUNET_TESTING_PREFIX, evstr)); #else static char evar[2* PATH_MAX]; GNUNET_assert (0 < GNUNET_snprintf (evar, sizeof (evar), GNUNET_TESTING_PREFIX "=%s", evstr)); putenv (evar); #endif GNUNET_free (evstr); evstr = NULL; } GNUNET_free_non_null (hostname); hostname = NULL; GNUNET_assert (NULL != test_system); GNUNET_assert (GNUNET_OK == GNUNET_TESTING_configuration_create (test_system, cfg)); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", "DEFAULTCONFIG", &config)); if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, config)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Unable to write config file: %s -- exiting\n", config); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_free (config); goto error; } LOG_DEBUG ("Staring testbed with config: %s\n", config); binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-testbed"); { static char evar[2 * PATH_MAX]; /* expose testbed configuration through env variable */ GNUNET_assert (0 < GNUNET_snprintf (evar, sizeof (evar), "%s=%s", ENV_TESTBED_CONFIG, config)); GNUNET_assert (0 == putenv (evar)); evstr = NULL; } testbed = GNUNET_OS_start_process (PIPE_CONTROL, GNUNET_OS_INHERIT_STD_ERR /*verbose? */ , NULL, NULL, NULL, binary, "gnunet-service-testbed", "-c", config, NULL); GNUNET_free (binary); GNUNET_free (config); if (NULL == testbed) { LOG (GNUNET_ERROR_TYPE_WARNING, "Error starting gnunet-service-testbed -- exiting\n"); GNUNET_CONFIGURATION_destroy (cfg); goto error; } done_reading = GNUNET_YES; config = GNUNET_CONFIGURATION_serialize (cfg, &config_size); GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; xconfig_size = GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig); GNUNET_free (config); wc = GNUNET_new (struct WriteContext); wc->length = xconfig_size + sizeof (struct GNUNET_TESTBED_HelperReply); reply = GNUNET_realloc (xconfig, wc->length); memmove (&reply[1], reply, xconfig_size); reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY); reply->header.size = htons ((uint16_t) wc->length); reply->config_size = htons ((uint16_t) config_size); wc->data = reply; write_task_id = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, stdout_fd, &write_task, wc); child_death_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), &child_death_task, NULL); return GNUNET_OK; error: status = GNUNET_SYSERR; shutdown_now (); return GNUNET_SYSERR; } /** * Task to read from stdin * * @param cls NULL * @param tc the task context */ static void read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE]; ssize_t sread; read_task_id = GNUNET_SCHEDULER_NO_TASK; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof (buf)); if ((GNUNET_SYSERR == sread) || (0 == sread)) { LOG_DEBUG ("STDIN closed\n"); shutdown_now (); return; } if (GNUNET_YES == done_reading) { /* didn't expect any more data! */ GNUNET_break_op (0); shutdown_now (); return; } LOG_DEBUG ("Read %u bytes\n", sread); if (GNUNET_OK != GNUNET_SERVER_mst_receive (tokenizer, NULL, buf, sread, GNUNET_NO, GNUNET_NO)) { GNUNET_break (0); shutdown_now (); return; } read_task_id = /* No timeout while reading */ GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdin_fd, &read_task, NULL); } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { LOG_DEBUG ("Starting testbed helper...\n"); tokenizer = GNUNET_SERVER_mst_create (&tokenizer_cb, NULL); stdin_fd = GNUNET_DISK_get_handle_from_native (stdin); stdout_fd = GNUNET_DISK_get_handle_from_native (stdout); read_task_id = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdin_fd, &read_task, NULL); shutdown_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * Signal handler called for SIGCHLD. */ static void sighandler_child_death () { static char c; int old_errno; /* back-up errno */ old_errno = errno; GNUNET_break (1 == GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_WRITE), &c, sizeof (c))); errno = old_errno; } /** * Main function * * @param argc the number of command line arguments * @param argv command line arg array * @return return code */ int main (int argc, char **argv) { struct GNUNET_SIGNAL_Context *shc_chld; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; status = GNUNET_OK; if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO))) { GNUNET_break (0); return 1; } shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-helper-testbed", "Helper for starting gnunet-service-testbed", options, &run, NULL); GNUNET_SIGNAL_handler_uninstall (shc_chld); shc_chld = NULL; GNUNET_DISK_pipe_close (sigpipe); if (GNUNET_OK != ret) return 1; return (GNUNET_OK == status) ? 0 : 1; } /* end of gnunet-helper-testbed.c */ gnunet-0.10.1/src/testbed/testbed_api_services.c0000644000175000017500000001761212255010512016565 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_services.c * @brief convenience functions for accessing services * @author Christian Grothoff */ #include "platform.h" #include "testbed_api.h" #include "testbed_api_peers.h" #include "testbed_api_operations.h" /** * States for Service connect operations */ enum State { /** * Initial state */ INIT, /** * The configuration request has been sent */ CFG_REQUEST_QUEUED, /** * connected to service */ SERVICE_CONNECTED }; /** * Data accessed during service connections */ struct ServiceConnectData { /** * helper function callback to establish the connection */ GNUNET_TESTBED_ConnectAdapter ca; /** * helper function callback to close the connection */ GNUNET_TESTBED_DisconnectAdapter da; /** * Closure to the above callbacks */ void *cada_cls; /** * Service name */ char *service_name; /** * Closure for operation event */ void *op_cls; /** * The operation which created this structure */ struct GNUNET_TESTBED_Operation *operation; /** * The operation context from GNUNET_TESTBED_forward_operation_msg_() */ struct OperationContext *opc; /** * The peer handle */ struct GNUNET_TESTBED_Peer *peer; /** * The acquired configuration of the peer */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The op_result pointer from ConnectAdapter */ void *op_result; /** * The operation completion callback */ GNUNET_TESTBED_ServiceConnectCompletionCallback cb; /** * The closure for operation completion callback */ void *cb_cls; /** * State information */ enum State state; }; /** * Type of a function to call when we receive a message * from the service. * * @param cls ServiceConnectData * @param msg message received, NULL on timeout or fatal error */ static void configuration_receiver (void *cls, const struct GNUNET_MessageHeader *msg) { struct ServiceConnectData *data = cls; struct GNUNET_TESTBED_Controller *c; const char *emsg; struct GNUNET_TESTBED_EventInformation info; uint16_t mtype; c = data->peer->controller; mtype = ntohs (msg->type); emsg = NULL; info.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; info.op = data->operation; info.op_cls = data->op_cls; if (GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT == mtype) { emsg = GNUNET_TESTBED_parse_error_string_ ((const struct GNUNET_TESTBED_OperationFailureEventMessage *) msg); if (NULL == emsg) emsg = "Unknown error"; info.details.operation_finished.emsg = emsg; info.details.operation_finished.generic = NULL; goto call_cb; } data->cfg = GNUNET_TESTBED_extract_config_ (msg); GNUNET_assert (NULL == data->op_result); data->op_result = data->ca (data->cada_cls, data->cfg); info.details.operation_finished.emsg = NULL; info.details.operation_finished.generic = data->op_result; data->state = SERVICE_CONNECTED; call_cb: if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) && (NULL != c->cc)) c->cc (c->cc_cls, &info); if (NULL != data->cb) data->cb (data->cb_cls, data->operation, data->op_result, emsg); } /** * Function called when a service connect operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_service_connect (void *cls) { struct ServiceConnectData *data = cls; struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; struct GNUNET_TESTBED_Controller *c; uint64_t op_id; GNUNET_assert (NULL != data); GNUNET_assert (NULL != data->peer); c = data->peer->controller; op_id = GNUNET_TESTBED_get_next_op_id (c); msg = GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id, op_id); data->opc = GNUNET_TESTBED_forward_operation_msg_ (c, op_id, &msg->header, &configuration_receiver, data); GNUNET_free (msg); data->state = CFG_REQUEST_QUEUED; } /** * Callback which will be called when service connect type operation is * released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_service_connect (void *cls) { struct ServiceConnectData *data = cls; switch (data->state) { case INIT: break; case CFG_REQUEST_QUEUED: GNUNET_assert (NULL != data->opc); GNUNET_TESTBED_forward_operation_msg_cancel_ (data->opc); break; case SERVICE_CONNECTED: GNUNET_assert (NULL != data->cfg); GNUNET_CONFIGURATION_destroy (data->cfg); if (NULL != data->da) data->da (data->cada_cls, data->op_result); break; } GNUNET_free (data); } /** * Connect to a service offered by the given peer. Will ensure that * the request is queued to not overwhelm our ability to create and * maintain connections with other systems. The actual service * handle is then returned via the 'op_result' member in the event * callback. The 'ca' callback is used to create the connection * when the time is right; the 'da' callback will be used to * destroy the connection (upon 'GNUNET_TESTBED_operation_done'). * 'GNUNET_TESTBED_operation_done' can be used to abort this * operation until the event callback has been called. * * @param op_cls closure to pass in operation event * @param peer peer that runs the service * @param service_name name of the service to connect to * @param cb the callback to call when this operation finishes * @param cb_cls closure for the above callback * @param ca helper function to establish the connection * @param da helper function to close the connection * @param cada_cls closure for ca and da * @return handle for the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_service_connect (void *op_cls, struct GNUNET_TESTBED_Peer *peer, const char *service_name, GNUNET_TESTBED_ServiceConnectCompletionCallback cb, void *cb_cls, GNUNET_TESTBED_ConnectAdapter ca, GNUNET_TESTBED_DisconnectAdapter da, void *cada_cls) { struct ServiceConnectData *data; data = GNUNET_new (struct ServiceConnectData); data->ca = ca; data->da = da; data->cada_cls = cada_cls; data->op_cls = op_cls; data->peer = peer; data->state = INIT; data->cb = cb; data->cb_cls = cb_cls; data->operation = GNUNET_TESTBED_operation_create_ (data, &opstart_service_connect, &oprelease_service_connect); GNUNET_TESTBED_operation_queue_insert_ (peer-> controller->opq_parallel_service_connections, data->operation); GNUNET_TESTBED_operation_queue_insert_ (peer-> controller->opq_parallel_operations, data->operation); GNUNET_TESTBED_operation_begin_wait_ (data->operation); return data->operation; } /* end of testbed_api_services.c */ gnunet-0.10.1/src/testbed/test_testbed_api_test_timeout.c0000644000175000017500000000653412225777501020546 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/testbed/test_testbed_api_test.c * @brief testing cases for testing notications via test master callback upon * timeout while setting up testbed using functions * GNUNET_TESTBED_test_run() * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Generic logging shortcut */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Number of peers we want to start */ #define NUM_PEERS 25 /** * Testing result */ static int result; /** * shortcut to exit during failure */ #define FAIL_TEST(cond) do { \ if (!(cond)) { \ GNUNET_break(0); \ GNUNET_SCHEDULER_shutdown (); \ return; \ } \ } while (0) /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { FAIL_TEST (0); } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers- handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { FAIL_TEST (NULL == cls); FAIL_TEST (0 == num_peers); FAIL_TEST (NULL == peers_); result = GNUNET_OK; GNUNET_SCHEDULER_shutdown (); } /** * Main function */ int main (int argc, char **argv) { uint64_t event_mask; result = GNUNET_SYSERR; event_mask = 0; (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", "test_testbed_api_test_timeout.conf", NUM_PEERS, event_mask, &controller_event_cb, NULL, &test_master, NULL); if (GNUNET_OK != result) return 1; return 0; } /* end of test_testbed_api_test.c */ gnunet-0.10.1/src/testbed/test_testbed_api_3peers_3controllers.c0000644000175000017500000005551112225777502021733 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_3peers_3controllers.c * @brief testcases for the testbed api: 3 peers are configured, started and * connected together. Each peer resides on its own controller. * @author Sree Harsha Totakura */ /** * The testing architecture is: * A * / \ * / \ * B === C * A is the master controller and B, C are slave controllers. B links to C * laterally. * Peers are mapped to controllers in the following relations: * Peer Controller * 1 A * 2 B * 3 C * */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_testbed_service.h" /** * Generic logging shortcut */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Relative time seconds shorthand */ #define TIME_REL_SECS(sec) \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) /** * Peer context */ struct PeerContext { /** * The peer handle */ struct GNUNET_TESTBED_Peer *peer; /** * Operations involving this peer */ struct GNUNET_TESTBED_Operation *operation; /** * set to GNUNET_YES when peer is started */ int is_running; }; /** * Our localhost */ static struct GNUNET_TESTBED_Host *host; /** * The controller process of one controller */ static struct GNUNET_TESTBED_ControllerProc *cp1; /** * A neighbouring host */ static struct GNUNET_TESTBED_Host *neighbour1; /** * Another neighbouring host */ static struct GNUNET_TESTBED_Host *neighbour2; /** * Handle for neighbour registration */ static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; /** * The controller handle of one controller */ static struct GNUNET_TESTBED_Controller *controller1; /** * peer 1 */ static struct PeerContext peer1; /** * peer2 */ static struct PeerContext peer2; /** * peer3 */ static struct PeerContext peer3; /** * Handle to starting configuration */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to slave controller C's configuration, used to establish lateral link from * master controller */ static struct GNUNET_CONFIGURATION_Handle *cfg2; /** * Handle to operations involving both peers */ static struct GNUNET_TESTBED_Operation *common_operation; /** * The handle for whether a host is habitable or not */ struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * Delayed connect job identifier */ static GNUNET_SCHEDULER_TaskIdentifier delayed_connect_task; /** * Different stages in testing */ enum Stage { /** * Initial stage */ INIT, /** * Controller 1 has started */ CONTROLLER1_UP, /** * peer1 is created */ PEER1_CREATED, /** * peer1 is started */ PEER1_STARTED, /** * Controller 2 has started */ CONTROLLER2_UP, /** * peer2 is created */ PEER2_CREATED, /** * peer2 is started */ PEER2_STARTED, /** * Controller 3 has started */ CONTROLLER3_UP, /** * Peer3 is created */ PEER3_CREATED, /** * Peer3 started */ PEER3_STARTED, /** * peer1 and peer2 are connected */ PEERS_1_2_CONNECTED, /** * peer2 and peer3 are connected */ PEERS_2_3_CONNECTED, /** * Peers are connected once again (this should not fail as they are already connected) */ PEERS_CONNECTED_2, /** * peers are stopped */ PEERS_STOPPED, /** * Final success stage */ SUCCESS, /** * Optional stage for marking test to be skipped */ SKIP }; /** * The testing result */ static enum Stage result; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); if (NULL != hc_handle) GNUNET_TESTBED_is_host_habitable_cancel (hc_handle); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == delayed_connect_task); if (NULL != common_operation) GNUNET_TESTBED_operation_done (common_operation); if (NULL != reg_handle) GNUNET_TESTBED_cancel_registration (reg_handle); if (NULL != controller1) GNUNET_TESTBED_controller_disconnect (controller1); GNUNET_CONFIGURATION_destroy (cfg); if (NULL != cfg2) GNUNET_CONFIGURATION_destroy (cfg2); if (NULL != cp1) GNUNET_TESTBED_controller_stop (cp1); if (NULL != host) GNUNET_TESTBED_host_destroy (host); if (NULL != neighbour1) GNUNET_TESTBED_host_destroy (neighbour1); if (NULL != neighbour2) GNUNET_TESTBED_host_destroy (neighbour2); } /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != delayed_connect_task) { GNUNET_SCHEDULER_cancel (delayed_connect_task); delayed_connect_task = GNUNET_SCHEDULER_NO_TASK; } do_shutdown (cls, tc); } static void abort_test () { if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); } /** * Callback to be called when an operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg); /** * task for delaying a connect * * @param cls NULL * @param tc the task context */ static void do_delayed_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { delayed_connect_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != common_operation) { GNUNET_break (0); abort_test (); return; } common_operation = GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer1.peer, peer2.peer); } /** * Callback to be called when an operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { if (common_operation != op) { GNUNET_break (0); abort_test (); return; } switch (result) { case PEER3_STARTED: case PEERS_2_3_CONNECTED: case PEERS_1_2_CONNECTED: break; default: GNUNET_break (0); abort_test (); return; } if ((NULL != peer1.operation) || (NULL != peer2.operation) || (NULL != peer3.operation)) { GNUNET_break (0); abort_test (); return; } } /** * Functions of this signature are called when a peer has been successfully * created * * @param cls NULL * @param peer the handle for the created peer; NULL on any error during * creation * @param emsg NULL if peer is not NULL; else MAY contain the error description */ static void peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) { switch (result) { case CONTROLLER1_UP: if ((NULL == peer1.operation) || (NULL == peer) || (NULL != peer1.peer)) { GNUNET_break (0); abort_test (); return; } peer1.peer = peer; GNUNET_TESTBED_operation_done (peer1.operation); result = PEER1_CREATED; peer1.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); break; case CONTROLLER2_UP: if ((NULL == peer2.operation) || (NULL == peer) || (NULL != peer2.peer)) { GNUNET_break (0); abort_test (); return; } peer2.peer = peer; GNUNET_TESTBED_operation_done (peer2.operation); result = PEER2_CREATED; peer2.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); break; case CONTROLLER3_UP: if ((NULL == peer3.operation) || (NULL == peer) || (NULL != peer3.peer)) { GNUNET_break (0); abort_test (); return; } peer3.peer = peer; GNUNET_TESTBED_operation_done (peer3.operation); result = PEER3_CREATED; peer3.operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); break; default: GNUNET_break (0); abort_test (); return; } } /** * Signature of the event handler function called by the * respective event controller. * * @param cls closure * @param event information about the event */ static void controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_OPERATION_FINISHED: if ((NULL != event->op_cls) || (NULL != event->details.operation_finished.emsg)) { GNUNET_break (0); abort_test (); return; } switch (result) { case PEERS_STOPPED: if (NULL != event->details.operation_finished.generic) { GNUNET_break (0); abort_test (); return; } if (event->op == peer1.operation) { GNUNET_TESTBED_operation_done (peer1.operation); peer1.operation = NULL; peer1.peer = NULL; } else if (event->op == peer2.operation) { GNUNET_TESTBED_operation_done (peer2.operation); peer2.operation = NULL; peer2.peer = NULL; } else if (event->op == peer3.operation) { GNUNET_TESTBED_operation_done (peer3.operation); peer3.operation = NULL; peer3.peer = NULL; } else { GNUNET_break (0); abort_test (); return; } if ((NULL == peer1.peer) && (NULL == peer2.peer) && (NULL == peer3.peer)) { result = SUCCESS; GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } break; case PEER1_STARTED: if ((NULL != event->details.operation_finished.generic) || (NULL == common_operation)) { GNUNET_break (0); abort_test (); return; } GNUNET_TESTBED_operation_done (common_operation); common_operation = NULL; result = CONTROLLER2_UP; peer2.operation = GNUNET_TESTBED_peer_create (controller1, neighbour1, cfg, &peer_create_cb, NULL); if (NULL == peer2.operation) { GNUNET_break (0); abort_test (); return; } break; case PEER2_STARTED: if ((NULL != event->details.operation_finished.generic) || (NULL == common_operation)) { GNUNET_break (0); abort_test (); return; } GNUNET_TESTBED_operation_done (common_operation); common_operation = NULL; result = CONTROLLER3_UP; peer3.operation = GNUNET_TESTBED_peer_create (controller1, neighbour2, cfg, &peer_create_cb, NULL); if (NULL == peer3.operation) { GNUNET_break (0); abort_test (); return; } break; default: GNUNET_break (0); abort_test (); return; } break; case GNUNET_TESTBED_ET_PEER_START: switch (result) { case PEER1_CREATED: if (event->details.peer_start.host != host) { GNUNET_break (0); abort_test (); return; } peer1.is_running = GNUNET_YES; GNUNET_TESTBED_operation_done (peer1.operation); peer1.operation = NULL; result = PEER1_STARTED; common_operation = GNUNET_TESTBED_controller_link (NULL, controller1, neighbour1, NULL, GNUNET_YES); break; case PEER2_CREATED: if (event->details.peer_start.host != neighbour1) { GNUNET_break (0); abort_test (); return; } peer2.is_running = GNUNET_YES; GNUNET_TESTBED_operation_done (peer2.operation); peer2.operation = NULL; result = PEER2_STARTED; if (NULL != common_operation) { GNUNET_break (0); abort_test (); return; } common_operation = GNUNET_TESTBED_controller_link (NULL, controller1, neighbour2, NULL, GNUNET_YES); if (NULL == common_operation) { GNUNET_break (0); abort_test (); return; } break; case PEER3_CREATED: if (event->details.peer_start.host != neighbour2) { GNUNET_break (0); abort_test (); return; } peer3.is_running = GNUNET_YES; GNUNET_TESTBED_operation_done (peer3.operation); peer3.operation = NULL; result = PEER3_STARTED; common_operation = GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer2.peer, peer1.peer); break; default: GNUNET_break (0); abort_test (); return; } break; case GNUNET_TESTBED_ET_PEER_STOP: if (PEERS_CONNECTED_2 != result) { GNUNET_break (0); abort_test (); return; } if (event->details.peer_stop.peer == peer1.peer) { peer1.is_running = GNUNET_NO; GNUNET_TESTBED_operation_done (peer1.operation); } else if (event->details.peer_stop.peer == peer2.peer) { peer2.is_running = GNUNET_NO; GNUNET_TESTBED_operation_done (peer2.operation); } else if (event->details.peer_stop.peer == peer3.peer) { peer3.is_running = GNUNET_NO; GNUNET_TESTBED_operation_done (peer3.operation); } else { GNUNET_break (0); abort_test (); return; } if ((GNUNET_NO == peer1.is_running) && (GNUNET_NO == peer2.is_running) && (GNUNET_NO == peer3.is_running)) { result = PEERS_STOPPED; peer1.operation = GNUNET_TESTBED_peer_destroy (peer1.peer); peer2.operation = GNUNET_TESTBED_peer_destroy (peer2.peer); peer3.operation = GNUNET_TESTBED_peer_destroy (peer3.peer); } break; case GNUNET_TESTBED_ET_CONNECT: if ((NULL != peer1.operation) || (NULL != peer2.operation) || (NULL != peer3.operation) || (NULL == common_operation)) { GNUNET_break (0); abort_test (); return; } switch (result) { case PEER3_STARTED: if ((event->details.peer_connect.peer1 != peer2.peer) || (event->details.peer_connect.peer2 != peer1.peer)) { GNUNET_break (0); abort_test (); return; } GNUNET_TESTBED_operation_done (common_operation); common_operation = NULL; result = PEERS_1_2_CONNECTED; LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected\n"); common_operation = GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peer2.peer, peer3.peer); break; case PEERS_1_2_CONNECTED: if ((event->details.peer_connect.peer1 != peer2.peer) || (event->details.peer_connect.peer2 != peer3.peer)) { GNUNET_break (0); abort_test (); return; } GNUNET_TESTBED_operation_done (common_operation); common_operation = NULL; result = PEERS_2_3_CONNECTED; delayed_connect_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (3), &do_delayed_connect, NULL); break; case PEERS_2_3_CONNECTED: if ((event->details.peer_connect.peer1 != peer1.peer) || (event->details.peer_connect.peer2 != peer2.peer)) { GNUNET_break (0); abort_test (); return; } GNUNET_TESTBED_operation_done (common_operation); common_operation = NULL; result = PEERS_CONNECTED_2; LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers connected again\n"); peer1.operation = GNUNET_TESTBED_peer_stop (NULL, peer1.peer, NULL, NULL); peer2.operation = GNUNET_TESTBED_peer_stop (NULL, peer2.peer, NULL, NULL); peer3.operation = GNUNET_TESTBED_peer_stop (NULL, peer3.peer, NULL, NULL); break; default: GNUNET_break (0); abort_test (); return; } break; default: GNUNET_break (0); abort_test (); return; } } /** * Callback which will be called to after a host registration succeeded or failed * * @param cls the host which has been registered * @param emsg the error message; NULL if host registration is successful */ static void registration_comp (void *cls, const char *emsg) { reg_handle = NULL; if (cls == neighbour1) { neighbour2 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0); if (NULL == neighbour2) { GNUNET_break (0); abort_test (); return; } reg_handle = GNUNET_TESTBED_register_host (controller1, neighbour2, ®istration_comp, neighbour2); if (NULL == reg_handle) { GNUNET_break (0); abort_test (); return; } return; } if (cls != neighbour2) { GNUNET_break (0); abort_test (); return; } peer1.operation = GNUNET_TESTBED_peer_create (controller1, host, cfg, &peer_create_cb, &peer1); if (NULL == peer1.operation) { GNUNET_break (0); abort_test (); return; } } /** * Callback to signal successfull startup of the controller process * * @param cls the closure from GNUNET_TESTBED_controller_start() * @param cfg the configuration with which the controller has been started; * NULL if status is not GNUNET_OK * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ static void status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, int status) { uint64_t event_mask; if (GNUNET_OK != status) { GNUNET_break (0); cp1 = NULL; abort_test (); return; } event_mask = 0; event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); switch (result) { case INIT: controller1 = GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb, NULL); if (NULL == controller1) { GNUNET_break (0); abort_test (); return; } result = CONTROLLER1_UP; neighbour1 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0); if (NULL == neighbour1) { GNUNET_break (0); abort_test (); return; } reg_handle = GNUNET_TESTBED_register_host (controller1, neighbour1, ®istration_comp, neighbour1); if (NULL == reg_handle) { GNUNET_break (0); abort_test (); return; } break; default: GNUNET_break (0); abort_test (); return; } } /** * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to * inform whether the given host is habitable or not. The Handle returned by * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called * * @param cls NULL * @param host the host whose status is being reported; will be NULL if the host * given to GNUNET_TESTBED_is_host_habitable() is NULL * @param status GNUNET_YES if it is habitable; GNUNET_NO if not */ static void host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *_host, int status) { hc_handle = NULL; if (GNUNET_NO == status) { (void) PRINTF ("%s", "Unable to run the test as this system is not configured " "to use password less SSH logins to localhost.\n" "Skipping test\n"); GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_NO_TASK; (void) GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); result = SKIP; return; } cp1 = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL); } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { cfg = GNUNET_CONFIGURATION_dup (config); host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); if (NULL == host) { GNUNET_break (0); abort_test (); return; } if (NULL == (hc_handle = GNUNET_TESTBED_is_host_habitable (host, config, &host_habitable_cb, NULL))) { GNUNET_TESTBED_host_destroy (host); host = NULL; (void) PRINTF ("%s", "Unable to run the test as this system is not configured " "to use password less SSH logins to localhost.\n" "Skipping test\n"); result = SKIP; return; } abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { char *const argv2[] = { "test_testbed_api_3peers_3controllers", "-c", "test_testbed_api.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; result = INIT; ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testbed_api_3peers_3controllers", "nohelp", options, &run, NULL); if (GNUNET_OK != ret) return 1; switch (result) { case SUCCESS: return 0; case SKIP: return 77; /* Mark test as skipped */ default: return 1; } } /* end of test_testbed_api_3peers_3controllers.c */ gnunet-0.10.1/src/testbed/overlay_topology.txt0000644000175000017500000000004512053661740016414 00000000000000 1:2|3 3:4| 0| 1 2: 3|1|0 0: 2 gnunet-0.10.1/src/testbed/testbed_helper.h0000644000175000017500000000472712225777503015421 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_helper.h * @brief Message formats for communication between testbed api and * gnunet-helper-testbed process * @author Sree Harsha Totakura */ #ifndef TESTBED_HELPER_H #define TESTBED_HELPER_H GNUNET_NETWORK_STRUCT_BEGIN /** * Initialization message for gnunet-helper-testbed to start testbed service */ struct GNUNET_TESTBED_HelperInit { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT */ struct GNUNET_MessageHeader header; /** * The controller hostname size excluding the NULL termination character - * strlen (hostname); cannot be zero */ uint16_t trusted_ip_size GNUNET_PACKED; /** * The hostname size excluding the NULL termination character - strlen * (hostname); cannot be zero */ uint16_t hostname_size GNUNET_PACKED; /** * The size of the uncompressed configuration */ uint16_t config_size GNUNET_PACKED; /* Followed by NULL terminated trusted ip */ /* Followed by hostname of the machine on which helper runs. This is not NULL * terminated */ /* Followed by serialized and compressed configuration which should be * config_size long when un-compressed */ }; /** * Reply message from helper process */ struct GNUNET_TESTBED_HelperReply { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY */ struct GNUNET_MessageHeader header; /** * Size of the uncompressed configuration */ uint16_t config_size GNUNET_PACKED; /* Followed by compressed configuration which should be config_size long when * un-compressed */ }; GNUNET_NETWORK_STRUCT_END #endif /* end of testbed_helper.h */ gnunet-0.10.1/src/testbed/gnunet-service-testbed_barriers.h0000644000175000017500000000606112225777503020700 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_barriers.h * @brief Interface for the barrier initialisation handler routine * @author Sree Harsha Totakura */ #ifndef GNUNET_SERVER_TESTBED_BARRIERS_H_ #define GNUNET_SERVER_TESTBED_BARRIERS_H_ /** * Function to initialise barrriers component * * @param cfg the configuration to use for initialisation */ void GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg); /** * Function to stop the barrier service */ void GST_barriers_destroy (); /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This * message should always come from a parent controller or the testbed API if we * are the root controller. * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This * message should always come from a parent controller or the testbed API if we * are the root controller. * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_barrier_status (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); #endif /* GNUNET_SERVER_TESTBED_BARRIERS_H_ */ /* end of gnunet-service-testbed_barriers.h */ gnunet-0.10.1/src/testbed/gnunet-service-testbed.c0000644000175000017500000007333412255010512016770 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed.c * @brief implementation of the TESTBED service * @author Sree Harsha Totakura */ #include "gnunet-service-testbed.h" #include "gnunet-service-testbed_barriers.h" #include "gnunet-service-testbed_connectionpool.h" /***********/ /* Globals */ /***********/ /** * Our configuration */ struct GNUNET_CONFIGURATION_Handle *GST_config; /** * The master context; generated with the first INIT message */ struct Context *GST_context; /** * Array of hosts */ struct GNUNET_TESTBED_Host **GST_host_list; /** * DLL head for forwarded operation contexts */ struct ForwardedOperationContext *fopcq_head; /** * DLL tail for forwarded operation contexts */ struct ForwardedOperationContext *fopcq_tail; /** * Operation queue for open file descriptors */ struct OperationQueue *GST_opq_openfds; /** * Timeout for operations which may take some time */ const struct GNUNET_TIME_Relative GST_timeout; /** * The size of the host list */ unsigned int GST_host_list_size; /** * The size of the peer list */ unsigned int GST_peer_list_size; /***********************************/ /* Local definitions and variables */ /***********************************/ /** * The message queue for sending messages to clients */ struct MessageQueue { /** * The message to be sent */ struct GNUNET_MessageHeader *msg; /** * The client to send the message to */ struct GNUNET_SERVER_Client *client; /** * next pointer for DLL */ struct MessageQueue *next; /** * prev pointer for DLL */ struct MessageQueue *prev; }; /** * Our hostname; we give this to all the peers we start */ static char *hostname; /** * Current Transmit Handle; NULL if no notify transmit exists currently */ static struct GNUNET_SERVER_TransmitHandle *transmit_handle; /** * The message queue head */ static struct MessageQueue *mq_head; /** * The message queue tail */ static struct MessageQueue *mq_tail; /** * The shutdown task handle */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id; /** * Function called to notify a client about the connection begin ready to queue * more data. "buf" will be NULL and "size" zero if the connection was closed * for writing in the meantime. * * @param cls NULL * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_ready_notify (void *cls, size_t size, void *buf) { struct MessageQueue *mq_entry; transmit_handle = NULL; mq_entry = mq_head; GNUNET_assert (NULL != mq_entry); if (0 == size) return 0; GNUNET_assert (ntohs (mq_entry->msg->size) <= size); size = ntohs (mq_entry->msg->size); memcpy (buf, mq_entry->msg, size); GNUNET_free (mq_entry->msg); GNUNET_SERVER_client_drop (mq_entry->client); GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry); GNUNET_free (mq_entry); mq_entry = mq_head; if (NULL != mq_entry) transmit_handle = GNUNET_SERVER_notify_transmit_ready (mq_entry->client, ntohs (mq_entry->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_ready_notify, NULL); return size; } /** * Queues a message in send queue for sending to the service * * @param client the client to whom the queued message has to be sent * @param msg the message to queue */ void GST_queue_message (struct GNUNET_SERVER_Client *client, struct GNUNET_MessageHeader *msg) { struct MessageQueue *mq_entry; uint16_t type; uint16_t size; type = ntohs (msg->type); size = ntohs (msg->size); GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) && (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type)); mq_entry = GNUNET_new (struct MessageQueue); mq_entry->msg = msg; mq_entry->client = client; GNUNET_SERVER_client_keep (client); LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type, ntohs (msg->size)); GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry); if (NULL == transmit_handle) transmit_handle = GNUNET_SERVER_notify_transmit_ready (client, size, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_ready_notify, NULL); } /** * Function to add a host to the current list of known hosts * * @param host the host to add * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id * already in use */ static int host_list_add (struct GNUNET_TESTBED_Host *host) { uint32_t host_id; host_id = GNUNET_TESTBED_host_get_id_ (host); if (GST_host_list_size <= host_id) GST_array_grow_large_enough (GST_host_list, GST_host_list_size, host_id); if (NULL != GST_host_list[host_id]) { LOG_DEBUG ("A host with id: %u already exists\n", host_id); return GNUNET_SYSERR; } GST_host_list[host_id] = host; return GNUNET_OK; } /** * Send operation failure message to client * * @param client the client to which the failure message has to be sent to * @param operation_id the id of the failed operation * @param emsg the error message; can be NULL */ void GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, uint64_t operation_id, const char *emsg) { struct GNUNET_TESTBED_OperationFailureEventMessage *msg; uint16_t msize; uint16_t emsg_len; msize = sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage); emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1; msize += emsg_len; msg = GNUNET_malloc (msize); msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT); msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); msg->operation_id = GNUNET_htonll (operation_id); if (0 != emsg_len) memcpy (&msg[1], emsg, emsg_len); GST_queue_message (client, &msg->header); } /** * Function to send generic operation success message to given client * * @param client the client to send the message to * @param operation_id the id of the operation which was successful */ void GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client, uint64_t operation_id) { struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg; uint16_t msize; msize = sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage); msg = GNUNET_malloc (msize); msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS); msg->operation_id = GNUNET_htonll (operation_id); msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED); GST_queue_message (client, &msg->header); } /** * Callback which will be called after a host registration succeeded or failed * * @param cls the handle to the slave at which the registration is completed * @param emsg the error message; NULL if host registration is successful */ static void hr_completion (void *cls, const char *emsg); /** * Attempts to register the next host in the host registration queue * * @param slave the slave controller whose host registration queue is checked * for host registrations */ static void register_next_host (struct Slave *slave) { struct HostRegistration *hr; hr = slave->hr_dll_head; GNUNET_assert (NULL != hr); GNUNET_assert (NULL == slave->rhandle); LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u\n", GNUNET_TESTBED_host_get_id_ (hr->host), GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); slave->rhandle = GNUNET_TESTBED_register_host (slave->controller, hr->host, hr_completion, slave); } /** * Callback which will be called to after a host registration succeeded or failed * * @param cls the handle to the slave at which the registration is completed * @param emsg the error message; NULL if host registration is successful */ static void hr_completion (void *cls, const char *emsg) { struct Slave *slave = cls; struct HostRegistration *hr; slave->rhandle = NULL; hr = slave->hr_dll_head; GNUNET_assert (NULL != hr); LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering host %u at %u successful\n", GNUNET_TESTBED_host_get_id_ (hr->host), GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail, hr); if (NULL != hr->cb) hr->cb (hr->cb_cls, emsg); GNUNET_free (hr); if (NULL != slave->hr_dll_head) register_next_host (slave); } /** * Adds a host registration's request to a slave's registration queue * * @param slave the slave controller at which the given host has to be * registered * @param cb the host registration completion callback * @param cb_cls the closure for the host registration completion callback * @param host the host which has to be registered */ void GST_queue_host_registration (struct Slave *slave, GNUNET_TESTBED_HostRegistrationCompletion cb, void *cb_cls, struct GNUNET_TESTBED_Host *host) { struct HostRegistration *hr; int call_register; LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing host registration for host %u at %u\n", GNUNET_TESTBED_host_get_id_ (host), GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id])); hr = GNUNET_new (struct HostRegistration); hr->cb = cb; hr->cb_cls = cb_cls; hr->host = host; call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO; GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head, slave->hr_dll_tail, hr); if (GNUNET_YES == call_register) register_next_host (slave); } /** * Callback to relay the reply msg of a forwarded operation back to the client * * @param cls ForwardedOperationContext * @param msg the message to relay */ void GST_forwarded_operation_reply_relay (void *cls, const struct GNUNET_MessageHeader *msg) { struct ForwardedOperationContext *fopc = cls; struct GNUNET_MessageHeader *dup_msg; uint16_t msize; msize = ntohs (msg->size); LOG_DEBUG ("Relaying message with type: %u, size: %u\n", ntohs (msg->type), msize); dup_msg = GNUNET_copy_message (msg); GST_queue_message (fopc->client, dup_msg); GNUNET_SERVER_client_drop (fopc->client); GNUNET_SCHEDULER_cancel (fopc->timeout_task); GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); GNUNET_free (fopc); } /** * Task to free resources when forwarded operation has been timedout * * @param cls the ForwardedOperationContext * @param tc the task context from scheduler */ void GST_forwarded_operation_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ForwardedOperationContext *fopc = cls; GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); LOG (GNUNET_ERROR_TYPE_DEBUG, "A forwarded operation has timed out\n"); GST_send_operation_fail_msg (fopc->client, fopc->operation_id, "A forwarded operation has timed out"); GNUNET_SERVER_client_drop (fopc->client); GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); GNUNET_free (fopc); } /** * Parse service sharing specification line. * Format is "[] [] ..." * * @param ss_str the spec string to be parsed * @param cfg the configuration to use for shared services * @return an array suitable to pass to GNUNET_TESTING_system_create(). NULL * upon empty service sharing specification. */ static struct GNUNET_TESTING_SharedService * parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_TESTING_SharedService ss; struct GNUNET_TESTING_SharedService *slist; char service[256]; char *arg; unsigned int n; #define GROW_SS \ do { \ GNUNET_array_grow (slist, n, n+1); \ (void) memcpy (&slist[n - 1], &ss, \ sizeof (struct GNUNET_TESTING_SharedService)); \ } while (0) slist = NULL; n = 0; ss.cfg = cfg; for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL) { ss.service = NULL; ss.share = 0; if (2 != sscanf (arg, "%255[^:]:%u", service, &ss.share)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring shared service spec: %s", arg); continue; } LOG_DEBUG ("Will be sharing %s service among %u peers\n", service, ss.share); ss.service = GNUNET_strdup (service); GROW_SS; } if (NULL != slist) { /* Add trailing NULL block */ (void) memset (&ss, 0, sizeof (struct GNUNET_TESTING_SharedService)); GROW_SS; } return slist; #undef GROW_SS } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ static void handle_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_InitMessage *msg; struct GNUNET_TESTBED_Host *host; const char *controller_hostname; char *ss_str; struct GNUNET_TESTING_SharedService *ss; unsigned int cnt; uint16_t msize; if (NULL != GST_context) { LOG_DEBUG ("We are being connected to laterally\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } msg = (const struct GNUNET_TESTBED_InitMessage *) message; msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msize -= sizeof (struct GNUNET_TESTBED_InitMessage); controller_hostname = (const char *) &msg[1]; if ('\0' != controller_hostname[msize - 1]) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } ss_str = NULL; ss = NULL; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (GST_config, "TESTBED", "SHARED_SERVICES", &ss_str)) { ss = parse_shared_services (ss_str, GST_config); GNUNET_free (ss_str); ss_str = NULL; } GST_context = GNUNET_new (struct Context); GNUNET_SERVER_client_keep (client); GST_context->client = client; GST_context->host_id = ntohl (msg->host_id); GST_context->master_ip = GNUNET_strdup (controller_hostname); LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip); GST_context->system = GNUNET_TESTING_system_create ("testbed", GST_context->master_ip, hostname, ss); if (NULL != ss) { for (cnt = 0; NULL != ss[cnt].service; cnt++) { ss_str = (char *) ss[cnt].service; GNUNET_free (ss_str); } GNUNET_free (ss); ss = NULL; } host = GNUNET_TESTBED_host_create_with_id (GST_context->host_id, GST_context->master_ip, NULL, GST_config, 0); host_list_add (host); LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ static void handle_add_host (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_TESTBED_Host *host; const struct GNUNET_TESTBED_AddHostMessage *msg; struct GNUNET_TESTBED_HostConfirmedMessage *reply; struct GNUNET_CONFIGURATION_Handle *host_cfg; char *username; char *hostname; char *emsg; const void *ptr; uint32_t host_id; uint16_t username_length; uint16_t hostname_length; uint16_t reply_size; uint16_t msize; msg = (const struct GNUNET_TESTBED_AddHostMessage *) message; msize = ntohs (msg->header.size); if (msize <= sizeof (struct GNUNET_TESTBED_AddHostMessage)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } username_length = ntohs (msg->username_length); hostname_length = ntohs (msg->hostname_length); /* msg must contain hostname */ if ((msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length)) || (0 == hostname_length)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* msg must contain configuration */ if (msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length + hostname_length)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } username = NULL; hostname = NULL; ptr = &msg[1]; if (0 != username_length) { username = GNUNET_malloc (username_length + 1); strncpy (username, ptr, username_length); ptr += username_length; } hostname = GNUNET_malloc (hostname_length + 1); strncpy (hostname, ptr, hostname_length); if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (message))) { GNUNET_free_non_null (username); GNUNET_free_non_null (hostname); GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } host_id = ntohl (msg->host_id); LOG_DEBUG ("Received ADDHOST %u message\n", host_id); LOG_DEBUG ("-------host id: %u\n", host_id); LOG_DEBUG ("-------hostname: %s\n", hostname); if (NULL != username) LOG_DEBUG ("-------username: %s\n", username); else LOG_DEBUG ("-------username: \n"); LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port)); host = GNUNET_TESTBED_host_create_with_id (host_id, hostname, username, host_cfg, ntohs (msg->ssh_port)); GNUNET_free_non_null (username); GNUNET_free (hostname); GNUNET_CONFIGURATION_destroy (host_cfg); if (NULL == host) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage); if (GNUNET_OK != host_list_add (host)) { /* We are unable to add a host */ emsg = "A host exists with given host-id"; LOG_DEBUG ("%s: %u", emsg, host_id); GNUNET_TESTBED_host_destroy (host); reply_size += strlen (emsg) + 1; reply = GNUNET_malloc (reply_size); memcpy (&reply[1], emsg, strlen (emsg) + 1); } else { LOG_DEBUG ("Added host %u at %u\n", host_id, GST_context->host_id); reply = GNUNET_malloc (reply_size); } reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS); reply->header.size = htons (reply_size); reply->host_id = htonl (host_id); GST_queue_message (client, &reply->header); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ static void handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; struct Slave *slave; struct GNUNET_TESTBED_SlaveConfiguration *reply; const struct GNUNET_CONFIGURATION_Handle *cfg; char *config; char *xconfig; size_t config_size; size_t xconfig_size; size_t reply_size; uint64_t op_id; uint32_t slave_id; msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message; slave_id = ntohl (msg->slave_id); op_id = GNUNET_ntohll (msg->operation_id); if ((GST_slave_list_size <= slave_id) || (NULL == GST_slave_list[slave_id])) { /* FIXME: Add forwardings for this type of message here.. */ GST_send_operation_fail_msg (client, op_id, "Slave not found"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } slave = GST_slave_list[slave_id]; GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (GST_host_list[slave->host_id]))); config = GNUNET_CONFIGURATION_serialize (cfg, &config_size); xconfig_size = GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig); GNUNET_free (config); reply_size = xconfig_size + sizeof (struct GNUNET_TESTBED_SlaveConfiguration); GNUNET_break (reply_size <= UINT16_MAX); GNUNET_break (config_size <= UINT16_MAX); reply = GNUNET_realloc (xconfig, reply_size); (void) memmove (&reply[1], reply, xconfig_size); reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION); reply->header.size = htons ((uint16_t) reply_size); reply->slave_id = msg->slave_id; reply->operation_id = msg->operation_id; reply->config_size = htons ((uint16_t) config_size); GST_queue_message (client, &reply->header); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Clears the forwarded operations queue */ void GST_clear_fopcq () { struct ForwardedOperationContext *fopc; while (NULL != (fopc = fopcq_head)) { GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc); GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc); if (GNUNET_SCHEDULER_NO_TASK != fopc->timeout_task) GNUNET_SCHEDULER_cancel (fopc->timeout_task); GNUNET_SERVER_client_drop (fopc->client); switch (fopc->type) { case OP_PEER_CREATE: GNUNET_free (fopc->cls); break; case OP_SHUTDOWN_PEERS: { struct HandlerContext_ShutdownPeers *hc = fopc->cls; GNUNET_assert (0 < hc->nslaves); hc->nslaves--; if (0 == hc->nslaves) GNUNET_free (hc); } break; case OP_PEER_START: case OP_PEER_STOP: case OP_PEER_DESTROY: case OP_PEER_INFO: case OP_OVERLAY_CONNECT: case OP_LINK_CONTROLLERS: case OP_GET_SLAVE_CONFIG: case OP_MANAGE_SERVICE: case OP_PEER_RECONFIGURE: break; case OP_FORWARDED: GNUNET_assert (0); }; GNUNET_free (fopc); } } /** * Task to clean up and shutdown nicely * * @param cls NULL * @param tc the TaskContext from scheduler */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MessageQueue *mq_entry; uint32_t id; shutdown_task_id = GNUNET_SCHEDULER_NO_TASK; LOG_DEBUG ("Shutting down testbed service\n"); /* cleanup any remaining forwarded operations */ GST_clear_fopcq (); GST_free_lcfq (); GST_free_mctxq (); GST_free_occq (); GST_free_roccq (); GST_free_nccq (); GST_neighbour_list_clean(); GST_free_prcq (); /* Clear peer list */ GST_destroy_peers (); /* Clear route list */ GST_route_list_clear (); /* Clear GST_slave_list */ GST_slave_list_clear (); /* Clear host list */ for (id = 0; id < GST_host_list_size; id++) if (NULL != GST_host_list[id]) GNUNET_TESTBED_host_destroy (GST_host_list[id]); GNUNET_free_non_null (GST_host_list); if (NULL != GST_context) { GNUNET_free_non_null (GST_context->master_ip); if (NULL != GST_context->system) GNUNET_TESTING_system_destroy (GST_context->system, GNUNET_YES); GNUNET_SERVER_client_drop (GST_context->client); GNUNET_free (GST_context); GST_context = NULL; } if (NULL != transmit_handle) GNUNET_SERVER_notify_transmit_ready_cancel (transmit_handle); while (NULL != (mq_entry = mq_head)) { GNUNET_free (mq_entry->msg); GNUNET_SERVER_client_drop (mq_entry->client); GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry); GNUNET_free (mq_entry); } GNUNET_free_non_null (hostname); /* Free hello cache */ GST_cache_clear (); GST_connection_pool_destroy (); GNUNET_TESTBED_operation_queue_destroy_ (GST_opq_openfds); GST_opq_openfds = NULL; GST_stats_destroy (); GST_barriers_destroy (); GNUNET_CONFIGURATION_destroy (GST_config); } /** * Callback for client disconnect * * @param cls NULL * @param client the client which has disconnected */ static void client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) { if (NULL == GST_context) return; if (client == GST_context->client) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n"); /* should not be needed as we're terminated by failure to read * from stdin, but if stdin fails for some reason, this shouldn't * hurt for now --- might need to revise this later if we ever * decide that master connections might be temporarily down * for some reason */ //GNUNET_SCHEDULER_shutdown (); } } /** * Testbed setup * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler message_handlers[] = { {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0}, {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0}, {&GST_handle_link_controllers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)}, {&GST_handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0}, {&GST_handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)}, {&GST_handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, sizeof (struct GNUNET_TESTBED_PeerStartMessage)}, {&GST_handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, sizeof (struct GNUNET_TESTBED_PeerStopMessage)}, {&GST_handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION, sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)}, {&GST_handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT, sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)}, {&GST_handle_remote_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0}, {&GST_handle_manage_peer_service, NULL, GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, 0}, {&handle_slave_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION, sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)}, {&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)}, {&GST_handle_peer_reconfigure, NULL, GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, 0}, {&GST_handle_barrier_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, 0}, {&GST_handle_barrier_cancel, NULL, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, 0}, {&GST_handle_barrier_status, NULL, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, 0}, {NULL, NULL, 0, 0} }; char *logfile; unsigned long long num; LOG_DEBUG ("Starting testbed\n"); if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE", &logfile)) { GNUNET_break (GNUNET_OK == GNUNET_log_setup ("testbed", "DEBUG", logfile)); GNUNET_free (logfile); } GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED", "CACHE_SIZE", &num)); GST_cache_init ((unsigned int) num); GST_connection_pool_init ((unsigned int) num); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED", "MAX_OPEN_FDS", &num)); GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, (unsigned int) num); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED", "OPERATION_TIMEOUT", (struct GNUNET_TIME_Relative *) &GST_timeout)); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", "HOSTNAME", &hostname)); GST_config = GNUNET_CONFIGURATION_dup (cfg); GNUNET_SERVER_add_handlers (server, message_handlers); GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL); shutdown_task_id = GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_SCHEDULER_PRIORITY_IDLE, &shutdown_task, NULL); LOG_DEBUG ("Testbed startup complete\n"); GST_stats_init (GST_config); GST_barriers_init (GST_config); } /** * The starting point of execution */ int main (int argc, char *const *argv) { //sleep (15); /* Debugging */ return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE, &testbed_run, NULL)) ? 0 : 1; } /* end of gnunet-service-testbed.c */ gnunet-0.10.1/src/testbed/test_testbed_underlay.c0000644000175000017500000001153012263473436017005 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_underlay.c * @brief testcase binary for testing testbed underlay restrictions * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we start in this test case */ #define NUM_PEERS 3 /** * Result of this test case */ static int result; static struct GNUNET_TESTBED_Operation *op; /** * Shutdown testcase * * @param cls NULL * @param tc scheduler task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != op) GNUNET_TESTBED_operation_done (op); op = NULL; } /** * Callback to be called when an operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void overlay_connect_status (void *cls, struct GNUNET_TESTBED_Operation *op_, const char *emsg) { GNUNET_assert (op_ == op); GNUNET_TESTBED_operation_done (op); op = NULL; if (NULL == emsg) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peers 0 and 2 should not get connected\n"); else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers 0 and 2 not connected: %s. Success!\n", emsg); result = GNUNET_OK; } GNUNET_SCHEDULER_shutdown (); } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { GNUNET_assert (NULL == cls); if (NULL == peers_) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_assert (NUM_PEERS == num_peers); op = GNUNET_TESTBED_overlay_connect (NULL, &overlay_connect_status, NULL, peers_[0], peers_[2]); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60), &do_shutdown, NULL); } /** * Main function */ int main (int argc, char **argv) { struct GNUNET_CONFIGURATION_Handle *cfg; char pwd[PATH_MAX]; char *dbfile; uint64_t event_mask; result = GNUNET_SYSERR; event_mask = 0; cfg = GNUNET_CONFIGURATION_create (); GNUNET_assert (GNUNET_YES == GNUNET_CONFIGURATION_parse (cfg, "test_testbed_underlay.conf.in")); if (NULL == getcwd (pwd, PATH_MAX)) return 1; GNUNET_assert (0 < GNUNET_asprintf (&dbfile, "%s/%s", pwd, "test-underlay.sqlite")); GNUNET_CONFIGURATION_set_value_string (cfg, "TESTBED-UNDERLAY","DBFILE", dbfile); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_write (cfg, "test_testbed_underlay.conf")); GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; GNUNET_free (dbfile); dbfile = NULL; (void) GNUNET_TESTBED_test_run ("test_testbed_underlay", "test_testbed_underlay.conf", NUM_PEERS, event_mask, NULL, NULL, &test_master, NULL); (void) unlink ("test_testbed_underlay.conf"); if (GNUNET_OK != result) return 1; return 0; } gnunet-0.10.1/src/testbed/gnunet-service-testbed_peers.c0000644000175000017500000012563512250315331020172 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_peers.c * @brief implementation of TESTBED service that deals with peer management * @author Sree Harsha Totakura */ #include "gnunet-service-testbed.h" #include "gnunet_arm_service.h" #include /** * A list of peers we know about */ struct Peer **GST_peer_list; /** * The current number of peers running locally under this controller */ unsigned int GST_num_local_peers; /** * Context information to manage peers' services */ struct ManageServiceContext { /** * DLL next ptr */ struct ManageServiceContext *next; /** * DLL prev ptr */ struct ManageServiceContext *prev; /** * The ARM handle of the peer */ struct GNUNET_ARM_Handle *ah; /** * peer whose service has to be managed */ struct Peer *peer; /** * The client which requested to manage the peer's service */ struct GNUNET_SERVER_Client *client; /** * The operation id of the associated request */ uint64_t op_id; /** * 1 if the service at the peer has to be started; 0 if it has to be stopped */ uint8_t start; /** * Is this context expired? Do not work on this context if it is set to * GNUNET_YES */ uint8_t expired; }; /** * Context information for peer re-configure operations */ struct PeerReconfigureContext { /** * DLL next for inclusoin in peer reconfigure operations list */ struct PeerReconfigureContext *next; /** * DLL prev */ struct PeerReconfigureContext *prev; /** * The client which gave this operation to us */ struct GNUNET_SERVER_Client *client; /** * The configuration handle to use as the new template */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The id of the operation */ uint64_t op_id; /** * The id of the peer which has to be reconfigured */ uint32_t peer_id; /** * The the peer stopped? Used while cleaning up this context to decide * whether the asynchronous stop request through Testing/ARM API has to be * cancelled */ uint8_t stopped; }; /** * The DLL head for the peer reconfigure list */ static struct PeerReconfigureContext *prc_head; /** * The DLL tail for the peer reconfigure list */ static struct PeerReconfigureContext *prc_tail; /** * DLL head for queue of manage service requests */ static struct ManageServiceContext *mctx_head; /** * DLL tail for queue of manage service requests */ static struct ManageServiceContext *mctx_tail; /** * Adds a peer to the peer array * * @param peer the peer to add */ static void peer_list_add (struct Peer *peer) { if (peer->id >= GST_peer_list_size) GST_array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id); GNUNET_assert (NULL == GST_peer_list[peer->id]); GST_peer_list[peer->id] = peer; if (GNUNET_NO == peer->is_remote) GST_num_local_peers++; } /** * Removes a the give peer from the peer array * * @param peer the peer to be removed */ static void peer_list_remove (struct Peer *peer) { unsigned int orig_size; uint32_t id; if (GNUNET_NO == peer->is_remote) GST_num_local_peers--; GST_peer_list[peer->id] = NULL; orig_size = GST_peer_list_size; while (GST_peer_list_size >= LIST_GROW_STEP) { for (id = GST_peer_list_size - 1; (id >= GST_peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); id--) if (NULL != GST_peer_list[id]) break; if (id != ((GST_peer_list_size - LIST_GROW_STEP) - 1)) break; GST_peer_list_size -= LIST_GROW_STEP; } if (orig_size == GST_peer_list_size) return; GST_peer_list = GNUNET_realloc (GST_peer_list, sizeof (struct Peer *) * GST_peer_list_size); } /** * The task to be executed if the forwarded peer create operation has been * timed out * * @param cls the FowardedOperationContext * @param tc the TaskContext from the scheduler */ static void peer_create_forward_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ForwardedOperationContext *fopc = cls; GNUNET_free (fopc->cls); GST_forwarded_operation_timeout (fopc, tc); } /** * Callback to be called when forwarded peer create operation is successfull. We * have to relay the reply msg back to the client * * @param cls ForwardedOperationContext * @param msg the peer create success message */ static void peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) { struct ForwardedOperationContext *fopc = cls; struct Peer *remote_peer; if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS) { GNUNET_assert (NULL != fopc->cls); remote_peer = fopc->cls; peer_list_add (remote_peer); } GST_forwarded_operation_reply_relay (fopc, msg); } /** * Function to destroy a peer * * @param peer the peer structure to destroy */ void GST_destroy_peer (struct Peer *peer) { GNUNET_break (0 == peer->reference_cnt); if (GNUNET_YES == peer->is_remote) { peer_list_remove (peer); GNUNET_free (peer); return; } if (GNUNET_YES == peer->details.local.is_running) { GNUNET_TESTING_peer_stop (peer->details.local.peer); peer->details.local.is_running = GNUNET_NO; } GNUNET_TESTING_peer_destroy (peer->details.local.peer); GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); peer_list_remove (peer); GNUNET_free (peer); } /** * Callback to be called when forwarded peer destroy operation is successfull. We * have to relay the reply msg back to the client * * @param cls ForwardedOperationContext * @param msg the peer create success message */ static void peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) { struct ForwardedOperationContext *fopc = cls; struct Peer *remote_peer; if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS == ntohs (msg->type)) { remote_peer = fopc->cls; GNUNET_assert (NULL != remote_peer); remote_peer->destroy_flag = GNUNET_YES; if (0 == remote_peer->reference_cnt) GST_destroy_peer (remote_peer); } GST_forwarded_operation_reply_relay (fopc, msg); } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_PeerCreateMessage *msg; struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply; struct GNUNET_CONFIGURATION_Handle *cfg; struct ForwardedOperationContext *fo_ctxt; struct Route *route; struct Peer *peer; char *emsg; uint32_t host_id; uint32_t peer_id; uint16_t msize; msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage)) { GNUNET_break (0); /* We need configuration */ GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message; host_id = ntohl (msg->host_id); peer_id = ntohl (msg->peer_id); if (VALID_PEER_ID (peer_id)) { (void) GNUNET_asprintf (&emsg, "Peer with ID %u already exists", peer_id); GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), emsg); GNUNET_free (emsg); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (UINT32_MAX == peer_id) { GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Cannot create peer with given ID"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (host_id == GST_context->host_id) { /* We are responsible for this peer */ cfg = GNUNET_TESTBED_extract_config_ (message); if (NULL == cfg) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID", (unsigned long long) peer_id); GNUNET_CONFIGURATION_set_value_number (cfg, "PATHS", "PEERID", (unsigned long long) peer_id); peer = GNUNET_new (struct Peer); peer->is_remote = GNUNET_NO; peer->details.local.cfg = cfg; peer->id = peer_id; LOG_DEBUG ("Creating peer with id: %u\n", (unsigned int) peer->id); peer->details.local.peer = GNUNET_TESTING_peer_configure (GST_context->system, peer->details.local.cfg, peer->id, NULL /* Peer id */ , &emsg); if (NULL == peer->details.local.peer) { LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg); GNUNET_free (emsg); GNUNET_free (peer); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } peer->details.local.is_running = GNUNET_NO; peer_list_add (peer); reply = GNUNET_new (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage); reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS); reply->peer_id = msg->peer_id; reply->operation_id = msg->operation_id; GST_queue_message (client, &reply->header); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } /* Forward peer create request */ route = GST_find_dest_route (host_id); if (NULL == route) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } peer = GNUNET_new (struct Peer); peer->is_remote = GNUNET_YES; peer->id = peer_id; peer->details.remote.slave = GST_slave_list[route->dest]; peer->details.remote.remote_host_id = host_id; fo_ctxt = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fo_ctxt->client = client; fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id); fo_ctxt->cls = peer; fo_ctxt->type = OP_PEER_CREATE; fo_ctxt->opc = GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list [route->dest]->controller, fo_ctxt->operation_id, &msg->header, peer_create_success_cb, fo_ctxt); fo_ctxt->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &peer_create_forward_timeout, fo_ctxt); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_PeerDestroyMessage *msg; struct ForwardedOperationContext *fopc; struct Peer *peer; uint32_t peer_id; msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message; peer_id = ntohl (msg->peer_id); LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n", peer_id, GNUNET_ntohll (msg->operation_id)); if (!VALID_PEER_ID (peer_id)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Asked to destroy a non existent peer with id: %u\n", peer_id); GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Peer doesn't exist"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } peer = GST_peer_list[peer_id]; if (GNUNET_YES == peer->is_remote) { /* Forward the destory message to sub controller */ fopc = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->cls = peer; fopc->type = OP_PEER_DESTROY; fopc->operation_id = GNUNET_ntohll (msg->operation_id); fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. slave->controller, fopc->operation_id, &msg->header, &peer_destroy_success_cb, fopc); fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } peer->destroy_flag = GNUNET_YES; if (0 == peer->reference_cnt) GST_destroy_peer (peer); else LOG (GNUNET_ERROR_TYPE_DEBUG, "Delaying peer destroy as peer is currently in use\n"); GST_send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id)); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Stats a peer * * @param peer the peer to start * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure */ static int start_peer (struct Peer *peer) { GNUNET_assert (GNUNET_NO == peer->is_remote); if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer)) return GNUNET_SYSERR; peer->details.local.is_running = GNUNET_YES; return GNUNET_OK; } /** * Stops a peer * * @param peer the peer to stop * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure */ static int stop_peer (struct Peer *peer) { GNUNET_assert (GNUNET_NO == peer->is_remote); if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) return GNUNET_SYSERR; peer->details.local.is_running = GNUNET_NO; return GNUNET_OK; } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_PeerStartMessage *msg; struct GNUNET_TESTBED_PeerEventMessage *reply; struct ForwardedOperationContext *fopc; struct Peer *peer; uint32_t peer_id; msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message; peer_id = ntohl (msg->peer_id); if (!VALID_PEER_ID (peer_id)) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_ERROR, "Asked to start a non existent peer with id: %u\n", peer_id); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } peer = GST_peer_list[peer_id]; if (GNUNET_YES == peer->is_remote) { fopc = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = GNUNET_ntohll (msg->operation_id); fopc->type = OP_PEER_START; fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. slave->controller, fopc->operation_id, &msg->header, &GST_forwarded_operation_reply_relay, fopc); fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_OK != start_peer (peer)) { GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Failed to start"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } reply = GNUNET_new (struct GNUNET_TESTBED_PeerEventMessage); reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START); reply->host_id = htonl (GST_context->host_id); reply->peer_id = msg->peer_id; reply->operation_id = msg->operation_id; GST_queue_message (client, &reply->header); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_PeerStopMessage *msg; struct GNUNET_TESTBED_PeerEventMessage *reply; struct ForwardedOperationContext *fopc; struct Peer *peer; uint32_t peer_id; msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message; peer_id = ntohl (msg->peer_id); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id); if (!VALID_PEER_ID (peer_id)) { GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Peer not found"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } peer = GST_peer_list[peer_id]; if (GNUNET_YES == peer->is_remote) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Forwarding PEER_STOP for peer %u\n", peer_id); fopc = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = GNUNET_ntohll (msg->operation_id); fopc->type = OP_PEER_STOP; fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. slave->controller, fopc->operation_id, &msg->header, &GST_forwarded_operation_reply_relay, fopc); fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_OK != stop_peer (peer)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id); GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Peer not running"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id); reply = GNUNET_new (struct GNUNET_TESTBED_PeerEventMessage); reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP); reply->host_id = htonl (GST_context->host_id); reply->peer_id = msg->peer_id; reply->operation_id = msg->operation_id; GST_queue_message (client, &reply->header); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_TESTING_peer_wait (peer->details.local.peer); } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply; struct ForwardedOperationContext *fopc; struct Peer *peer; char *config; char *xconfig; size_t c_size; size_t xc_size; uint32_t peer_id; uint16_t msize; msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message; peer_id = ntohl (msg->peer_id); LOG_DEBUG ("Received GET_CONFIG for peer %u\n", peer_id); if (!VALID_PEER_ID (peer_id)) { GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), "Peer not found"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } peer = GST_peer_list[peer_id]; if (GNUNET_YES == peer->is_remote) { LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id); fopc = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = GNUNET_ntohll (msg->operation_id); fopc->type = OP_PEER_INFO; fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. slave->controller, fopc->operation_id, &msg->header, &GST_forwarded_operation_reply_relay, fopc); fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", peer_id); config = GNUNET_CONFIGURATION_serialize (GST_peer_list[peer_id]->details.local.cfg, &c_size); xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig); GNUNET_free (config); msize = xc_size + sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage); reply = GNUNET_realloc (xconfig, msize); (void) memmove (&reply[1], reply, xc_size); reply->header.size = htons (msize); reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION); reply->peer_id = msg->peer_id; reply->operation_id = msg->operation_id; GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer, &reply->peer_identity); reply->config_size = htons ((uint16_t) c_size); GST_queue_message (client, &reply->header); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Cleans up the given PeerReconfigureContext * * @param prc the PeerReconfigureContext */ static void cleanup_prc (struct PeerReconfigureContext *prc) { struct Peer *peer; if (VALID_PEER_ID (prc->peer_id)) { peer = GST_peer_list [prc->peer_id]; if (1 != prc->stopped) { GNUNET_TESTING_peer_stop_async_cancel (peer->details.local.peer); stop_peer (peer); /* Stop the peer synchronously */ } } if (NULL != prc->cfg) GNUNET_CONFIGURATION_destroy (prc->cfg); GNUNET_SERVER_client_drop (prc->client); GNUNET_CONTAINER_DLL_remove (prc_head, prc_tail, prc); GNUNET_free (prc); } /** * Cleans up the Peer reconfigure context list */ void GST_free_prcq () { while (NULL != prc_head) cleanup_prc (prc_head); } /** * Update peer configuration * * @param peer the peer to update * @param cfg the new configuration * @return error message (freshly allocated); NULL upon success */ static char * update_peer_config (struct Peer *peer, struct GNUNET_CONFIGURATION_Handle *cfg) { char *emsg; GNUNET_TESTING_peer_destroy (peer->details.local.peer); GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); peer->details.local.cfg = cfg; emsg = NULL; peer->details.local.peer = GNUNET_TESTING_peer_configure (GST_context->system, peer->details.local.cfg, peer->id, NULL /* Peer id */ , &emsg); return emsg; } /** * Callback to inform whether the peer is running or stopped. * * @param cls the closure given to GNUNET_TESTING_peer_stop_async() * @param p the respective peer whose status is being reported * @param success GNUNET_YES if the peer is stopped; GNUNET_SYSERR upon any * error */ static void prc_stop_cb (void *cls, struct GNUNET_TESTING_Peer *p, int success) { struct PeerReconfigureContext *prc = cls; struct Peer *peer; char *emsg; GNUNET_assert (VALID_PEER_ID (prc->peer_id)); peer = GST_peer_list [prc->peer_id]; GNUNET_assert (GNUNET_NO == peer->is_remote); emsg = update_peer_config (peer, prc->cfg); prc->cfg = NULL; prc->stopped = 1; if (NULL != emsg) { GST_send_operation_fail_msg (prc->client, prc->op_id, emsg); goto cleanup; } if (GNUNET_OK != start_peer (peer)) { GST_send_operation_fail_msg (prc->client, prc->op_id, "Failed to start reconfigured peer"); goto cleanup; } GST_send_operation_success_msg (prc->client, prc->op_id); cleanup: cleanup_prc (prc); return; } /** * Handler for GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. * Should stop the peer asyncronously, destroy it and create it again with the * new configuration. * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_PeerReconfigureMessage *msg; struct Peer *peer; struct GNUNET_CONFIGURATION_Handle *cfg; struct ForwardedOperationContext *fopc; struct PeerReconfigureContext *prc; char *emsg; uint64_t op_id; uint32_t peer_id; uint16_t msize; msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) message; peer_id = ntohl (msg->peer_id); op_id = GNUNET_ntohll (msg->operation_id); if (!VALID_PEER_ID (peer_id)) { GNUNET_break (0); GST_send_operation_fail_msg (client, op_id, "Peer not found"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } peer = GST_peer_list[peer_id]; if (GNUNET_YES == peer->is_remote) { LOG_DEBUG ("Forwarding PEER_RECONFIGURE for peer: %u\n", peer_id); fopc = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = op_id; fopc->type = OP_PEER_RECONFIGURE; fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. slave->controller, fopc->operation_id, &msg->header, &GST_forwarded_operation_reply_relay, fopc); fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } LOG_DEBUG ("Received PEER_RECONFIGURE for peer %u\n", peer_id); if (0 < peer->reference_cnt) { GNUNET_break (0); GST_send_operation_fail_msg (client, op_id, "Peer in use"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_YES == peer->destroy_flag) { GNUNET_break (0); GST_send_operation_fail_msg (client, op_id, "Peer is being destroyed"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } cfg = GNUNET_TESTBED_extract_config_ (message); if (NULL == cfg) { GNUNET_break (0); GST_send_operation_fail_msg (client, op_id, "Compression error"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_NO == peer->details.local.is_running) { emsg = update_peer_config (peer, cfg); if (NULL != emsg) GST_send_operation_fail_msg (client, op_id, emsg); GST_send_operation_success_msg (client, op_id); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_free_non_null (emsg); return; } prc = GNUNET_new (struct PeerReconfigureContext); if (GNUNET_OK != GNUNET_TESTING_peer_stop_async (peer->details.local.peer, &prc_stop_cb, prc)) { GNUNET_assert (0 < GNUNET_asprintf (&emsg, "Error trying to stop peer %u asynchronously\n", peer_id)); LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); GST_send_operation_fail_msg (client, op_id, emsg); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_free (prc); GNUNET_free (emsg); return; } prc->cfg = cfg; prc->peer_id = peer_id; prc->op_id = op_id; prc->client = client; GNUNET_SERVER_client_keep (client); GNUNET_CONTAINER_DLL_insert_tail (prc_head, prc_tail, prc); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Cleanup the context information created for managing a peer's service * * @param mctx the ManageServiceContext */ static void cleanup_mctx (struct ManageServiceContext *mctx) { mctx->expired = GNUNET_YES; GNUNET_CONTAINER_DLL_remove (mctx_head, mctx_tail, mctx); GNUNET_SERVER_client_drop (mctx->client); GNUNET_ARM_disconnect_and_free (mctx->ah); GNUNET_assert (0 < mctx->peer->reference_cnt); mctx->peer->reference_cnt--; if ( (GNUNET_YES == mctx->peer->destroy_flag) && (0 == mctx->peer->reference_cnt) ) GST_destroy_peer (mctx->peer); GNUNET_free (mctx); } /** * Frees the ManageServiceContext queue */ void GST_free_mctxq () { while (NULL != mctx_head) cleanup_mctx (mctx_head); } /** * Returns a string interpretation of 'rs' * * @param rs the request status from ARM * @return a string interpretation of the request status */ static const char * arm_req_string (enum GNUNET_ARM_RequestStatus rs) { switch (rs) { case GNUNET_ARM_REQUEST_SENT_OK: return _("Message was sent successfully"); case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR: return _("Misconfiguration (can't connect to the ARM service)"); case GNUNET_ARM_REQUEST_DISCONNECTED: return _("We disconnected from ARM before we could send a request"); case GNUNET_ARM_REQUEST_BUSY: return _("ARM API is busy"); case GNUNET_ARM_REQUEST_TOO_LONG: return _("Request doesn't fit into a message"); case GNUNET_ARM_REQUEST_TIMEOUT: return _("Request timed out"); } return _("Unknown request status"); } /** * Returns a string interpretation of the 'result' * * @param result the arm result * @return a string interpretation */ static const char * arm_ret_string (enum GNUNET_ARM_Result result) { switch (result) { case GNUNET_ARM_RESULT_STOPPED: return _("%s is stopped"); case GNUNET_ARM_RESULT_STARTING: return _("%s is starting"); case GNUNET_ARM_RESULT_STOPPING: return _("%s is stopping"); case GNUNET_ARM_RESULT_IS_STARTING_ALREADY: return _("%s is starting already"); case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY: return _("%s is stopping already"); case GNUNET_ARM_RESULT_IS_STARTED_ALREADY: return _("%s is started already"); case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY: return _("%s is stopped already"); case GNUNET_ARM_RESULT_IS_NOT_KNOWN: return _("%s service is not known to ARM"); case GNUNET_ARM_RESULT_START_FAILED: return _("%s service failed to start"); case GNUNET_ARM_RESULT_IN_SHUTDOWN: return _("%s service can't be started because ARM is shutting down"); } return _("%.s Unknown result code."); } /** * Function called in response to a start/stop request. * Will be called when request was not sent successfully, * or when a reply comes. If the request was not sent successfully, * 'rs' will indicate that, and 'service' and 'result' will be undefined. * * @param cls ManageServiceContext * @param rs status of the request * @param service service name * @param result result of the operation */ static void service_manage_result_cb (void *cls, enum GNUNET_ARM_RequestStatus rs, const char *service, enum GNUNET_ARM_Result result) { struct ManageServiceContext *mctx = cls; char *emsg; emsg = NULL; if (GNUNET_YES == mctx->expired) return; if (GNUNET_ARM_REQUEST_SENT_OK != rs) { GNUNET_asprintf (&emsg, "Error communicating with Peer %u's ARM: %s", mctx->peer->id, arm_req_string (rs)); goto ret; } if (1 == mctx->start) goto service_start_check; if (! ((GNUNET_ARM_RESULT_STOPPED == result) || (GNUNET_ARM_RESULT_STOPPING == result) || (GNUNET_ARM_RESULT_IS_STOPPING_ALREADY == result) || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) ) { /* stopping a service failed */ GNUNET_asprintf (&emsg, arm_ret_string (result), service); goto ret; } /* service stopped successfully */ goto ret; service_start_check: if (! ((GNUNET_ARM_RESULT_STARTING == result) || (GNUNET_ARM_RESULT_IS_STARTING_ALREADY == result) || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) ) { /* starting a service failed */ GNUNET_asprintf (&emsg, arm_ret_string (result), service); goto ret; } /* service started successfully */ ret: if (NULL != emsg) { LOG_DEBUG ("%s\n", emsg); GST_send_operation_fail_msg (mctx->client, mctx->op_id, emsg); } else GST_send_operation_success_msg (mctx->client, mctx->op_id); GNUNET_free_non_null (emsg); cleanup_mctx (mctx); } /** * Handler for GNUNET_TESTBED_ManagePeerServiceMessage message * * @param cls NULL * @param client identification of client * @param message the actual message */ void GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg; const char* service; struct Peer *peer; char *emsg; struct GNUNET_ARM_Handle *ah; struct ManageServiceContext *mctx; struct ForwardedOperationContext *fopc; uint64_t op_id; uint32_t peer_id; uint16_t msize; msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_ManagePeerServiceMessage *) message; service = (const char *) &msg[1]; if ('\0' != service[msize - sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1]) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (1 < msg->start) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } peer_id = ntohl (msg->peer_id); op_id = GNUNET_ntohll (msg->operation_id); LOG_DEBUG ("Received request to manage service %s on peer %u\n", service, (unsigned int) peer_id); if ((GST_peer_list_size <= peer_id) || (NULL == (peer = GST_peer_list[peer_id]))) { GNUNET_asprintf (&emsg, "Asked to manage service of a non existent peer " "with id: %u", peer_id); goto err_ret; } if (0 == strcasecmp ("arm", service)) { emsg = GNUNET_strdup ("Cannot start/stop peer's ARM service. " "Use peer start/stop for that"); goto err_ret; } if (GNUNET_YES == peer->is_remote) { /* Forward the destory message to sub controller */ fopc = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->cls = peer; fopc->type = OP_MANAGE_SERVICE; fopc->operation_id = op_id; fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. slave->controller, fopc->operation_id, &msg->header, &GST_forwarded_operation_reply_relay, fopc); fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_NO == peer->details.local.is_running) { emsg = GNUNET_strdup ("Peer not running\n"); goto err_ret; } if ((0 != peer->reference_cnt) && ( (0 == strcasecmp ("core", service)) || (0 == strcasecmp ("transport", service)) ) ) { GNUNET_asprintf (&emsg, "Cannot stop %s service of peer with id: %u " "since it is required by existing operations", service, peer_id); goto err_ret; } ah = GNUNET_ARM_connect (peer->details.local.cfg, NULL, NULL); if (NULL == ah) { GNUNET_asprintf (&emsg, "Cannot connect to ARM service of peer with id: %u", peer_id); goto err_ret; } mctx = GNUNET_new (struct ManageServiceContext); mctx->peer = peer; peer->reference_cnt++; mctx->op_id = op_id; mctx->ah = ah; GNUNET_SERVER_client_keep (client); mctx->client = client; mctx->start = msg->start; GNUNET_CONTAINER_DLL_insert_tail (mctx_head, mctx_tail, mctx); if (1 == mctx->start) GNUNET_ARM_request_service_start (mctx->ah, service, GNUNET_OS_INHERIT_STD_ERR, GST_timeout, service_manage_result_cb, mctx); else GNUNET_ARM_request_service_stop (mctx->ah, service, GST_timeout, service_manage_result_cb, mctx); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; err_ret: LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); GST_send_operation_fail_msg (client, op_id, emsg); GNUNET_free (emsg); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Stops and destroys all peers */ void GST_destroy_peers () { struct Peer *peer; unsigned int id; if (NULL == GST_peer_list) return; for (id = 0; id < GST_peer_list_size; id++) { peer = GST_peer_list[id]; if (NULL == peer) continue; /* If destroy flag is set it means that this peer should have been * destroyed by a context which we destroy before */ GNUNET_break (GNUNET_NO == peer->destroy_flag); /* counter should be zero as we free all contexts before */ GNUNET_break (0 == peer->reference_cnt); if ((GNUNET_NO == peer->is_remote) && (GNUNET_YES == peer->details.local.is_running)) GNUNET_TESTING_peer_kill (peer->details.local.peer); } for (id = 0; id < GST_peer_list_size; id++) { peer = GST_peer_list[id]; if (NULL == peer) continue; if (GNUNET_NO == peer->is_remote) { if (GNUNET_YES == peer->details.local.is_running) GNUNET_TESTING_peer_wait (peer->details.local.peer); GNUNET_TESTING_peer_destroy (peer->details.local.peer); GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); } GNUNET_free (peer); } GNUNET_free_non_null (GST_peer_list); GST_peer_list = NULL; GST_peer_list_size = 0; } /** * The reply msg handler forwarded SHUTDOWN_PEERS operation. Checks if a * success reply is received from all clients and then sends the success message * to the client * * @param cls ForwardedOperationContext * @param msg the message to relay */ static void shutdown_peers_reply_cb (void *cls, const struct GNUNET_MessageHeader *msg) { struct ForwardedOperationContext *fo_ctxt = cls; struct HandlerContext_ShutdownPeers *hc; hc = fo_ctxt->cls; GNUNET_assert (0 < hc->nslaves); hc->nslaves--; if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS != ntohs (msg->type)) hc->timeout = GNUNET_YES; if (0 == hc->nslaves) { if (GNUNET_YES == hc->timeout) GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, "Timeout at a slave controller"); else GST_send_operation_success_msg (fo_ctxt->client, fo_ctxt->operation_id); GNUNET_free (hc); hc = NULL; } GNUNET_SERVER_client_drop (fo_ctxt->client); GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt); GNUNET_free (fo_ctxt); } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_ShutdownPeersMessage *msg; struct HandlerContext_ShutdownPeers *hc; struct Slave *slave; struct ForwardedOperationContext *fo_ctxt; uint64_t op_id; unsigned int cnt; msg = (const struct GNUNET_TESTBED_ShutdownPeersMessage *) message; LOG_DEBUG ("Received SHUTDOWN_PEERS\n"); /* Stop and destroy all peers */ GST_free_mctxq (); GST_free_occq (); GST_free_roccq (); GST_clear_fopcq (); /* Forward to all slaves which we have started */ op_id = GNUNET_ntohll (msg->operation_id); hc = GNUNET_new (struct HandlerContext_ShutdownPeers); /* FIXME: have a better implementation where we track which slaves are started by this controller */ for (cnt = 0; cnt < GST_slave_list_size; cnt++) { slave = GST_slave_list[cnt]; if (NULL == slave) continue; if (NULL == slave->controller_proc) /* We didn't start the slave */ continue; LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n"); hc->nslaves++; fo_ctxt = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fo_ctxt->client = client; fo_ctxt->operation_id = op_id; fo_ctxt->cls = hc; fo_ctxt->type = OP_SHUTDOWN_PEERS; fo_ctxt->opc = GNUNET_TESTBED_forward_operation_msg_ (slave->controller, fo_ctxt->operation_id, &msg->header, shutdown_peers_reply_cb, fo_ctxt); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); } LOG_DEBUG ("Shutting down peers\n"); GST_destroy_peers (); if (0 == hc->nslaves) { GST_send_operation_success_msg (client, op_id); GNUNET_free (hc); } GNUNET_SERVER_receive_done (client, GNUNET_OK); } gnunet-0.10.1/src/testbed/testbed_api_barriers.h0000644000175000017500000000402312225777503016571 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_barriers.h * @brief interface for barriers API function that are used internally (not * exposed as user API) * @author Sree Harsha Totakura */ #include "gnunet_testbed_service.h" /** * Initialise a barrier and call the given callback when the required percentage * of peers (quorum) reach the barrier OR upon error. * * @param controller the handle to the controller * @param name identification name of the barrier * @param quorum the percentage of peers that is required to reach the barrier. * Peers signal reaching a barrier by calling * GNUNET_TESTBED_barrier_reached(). * @param cb the callback to call when the barrier is reached or upon error. * Cannot be NULL. * @param cls closure for the above callback * @param echo GNUNET_YES to echo the barrier crossed status message back to the * controller * @return barrier handle; NULL upon error */ struct GNUNET_TESTBED_Barrier * GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller, const char *name, unsigned int quorum, GNUNET_TESTBED_barrier_status_cb cb, void *cls, int echo); gnunet-0.10.1/src/testbed/testbed_api_hosts.c0000644000175000017500000013501612301361474016111 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_hosts.c * @brief API for manipulating 'hosts' controlled by the GNUnet testing service; * allows parsing hosts files, starting, stopping and communicating (via * SSH/stdin/stdout) with the remote (or local) processes * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_core_service.h" #include "gnunet_transport_service.h" #include "testbed_api.h" #include "testbed_api_hosts.h" #include "testbed_helper.h" #include "testbed_api_operations.h" #include #include /** * Generic logging shorthand */ #define LOG(kind, ...) \ GNUNET_log_from (kind, "testbed-api-hosts", __VA_ARGS__); /** * Debug logging shorthand */ #define LOG_DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__); /** * Prints API violation message */ #define API_VIOLATION(cond,errstr) \ do { \ if (cond) \ break; \ LOG (GNUNET_ERROR_TYPE_ERROR, "API violation detected: %s\n", errstr); \ GNUNET_assert (0); \ } while (0) /** * Log an error message at log-level 'level' that indicates a failure of the * command 'cmd' with the message given by gai_strerror(rc). */ #define LOG_GAI(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gai_strerror(rc)); } while(0) /** * Number of extra elements we create space for when we grow host list */ #define HOST_LIST_GROW_STEP 10 /** * A list entry for registered controllers list */ struct RegisteredController { /** * The controller at which this host is registered */ const struct GNUNET_TESTBED_Controller *controller; /** * The next ptr for DLL */ struct RegisteredController *next; /** * The prev ptr for DLL */ struct RegisteredController *prev; }; /** * Opaque handle to a host running experiments managed by the testing framework. * The master process must be able to SSH to this host without password (via * ssh-agent). */ struct GNUNET_TESTBED_Host { /** * The hostname of the host; NULL for localhost */ const char *hostname; /** * The username to be used for SSH login */ const char *username; /** * the configuration to use as a template while starting a controller on this * host. Operation queue size specific to a host are also read from this * configuration handle. After starting the controller, it points to the actual * configuration with which the controller is running */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The head for the list of controllers where this host is registered */ struct RegisteredController *rc_head; /** * The tail for the list of controllers where this host is registered */ struct RegisteredController *rc_tail; /** * Operation queue for simultaneous overlay connect operations target at this * host */ struct OperationQueue *opq_parallel_overlay_connect_operations; /** * Is a controller started on this host? FIXME: Is this needed? */ int controller_started; /** * Is this host locked by GNUNET_TESTBED_controller_start()? */ int locked; /** * Global ID we use to refer to a host on the network */ uint32_t id; /** * The port which is to be used for SSH */ uint16_t port; }; /** * Array of available hosts */ static struct GNUNET_TESTBED_Host **host_list; /** * The size of the available hosts list */ static unsigned int host_list_size; /** * Lookup a host by ID. * * @param id global host ID assigned to the host; 0 is * reserved to always mean 'localhost' * @return handle to the host, NULL if host not found */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id) { if (host_list_size <= id) return NULL; return host_list[id]; } /** * Create a host by ID; given this host handle, we could not * run peers at the host, but we can talk about the host * internally. * * @param id global host ID assigned to the host; 0 is * reserved to always mean 'localhost' * @param cfg the configuration to use as a template while starting a controller * on this host. Operation queue sizes specific to a host are also * read from this configuration handle * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_create_by_id_ (uint32_t id, const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_TESTBED_host_create_with_id (id, NULL, NULL, cfg, 0); } /** * Obtain the host's unique global ID. * * @param host handle to the host, NULL means 'localhost' * @return id global host ID assigned to the host (0 is * 'localhost', but then obviously not globally unique) */ uint32_t GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host * host) { return host->id; } /** * Obtain the host's hostname. * * @param host handle to the host, NULL means 'localhost' * @return hostname of the host */ const char * GNUNET_TESTBED_host_get_hostname (const struct GNUNET_TESTBED_Host *host) { return host->hostname; } /** * Obtain the host's username * * @param host handle to the host, NULL means 'localhost' * @return username to login to the host */ const char * GNUNET_TESTBED_host_get_username_ (const struct GNUNET_TESTBED_Host *host) { return host->username; } /** * Obtain the host's ssh port * * @param host handle to the host, NULL means 'localhost' * @return username to login to the host */ uint16_t GNUNET_TESTBED_host_get_ssh_port_ (const struct GNUNET_TESTBED_Host * host) { return host->port; } /** * Check whether a controller is already started on the given host * * @param host the handle to the host * @return GNUNET_YES if the controller is already started; GNUNET_NO if not */ int GNUNET_TESTBED_host_controller_started (const struct GNUNET_TESTBED_Host *host) { return host->controller_started; } /** * Obtain the host's configuration template * * @param host handle to the host * @return the host's configuration template */ const struct GNUNET_CONFIGURATION_Handle * GNUNET_TESTBED_host_get_cfg_ (const struct GNUNET_TESTBED_Host *host) { return host->cfg; } /** * Function to replace host's configuration * * @param host the host handle * @param new_cfg the new configuration to replace the old one */ void GNUNET_TESTBED_host_replace_cfg_ (struct GNUNET_TESTBED_Host *host, const struct GNUNET_CONFIGURATION_Handle *new_cfg) { GNUNET_CONFIGURATION_destroy (host->cfg); host->cfg = GNUNET_CONFIGURATION_dup (new_cfg); } /** * Create a host to run peers and controllers on. * * @param id global host ID assigned to the host; 0 is * reserved to always mean 'localhost' * @param hostname name of the host, use "NULL" for localhost * @param username username to use for the login; may be NULL * @param cfg the configuration to use as a template while starting a controller * on this host. Operation queue sizes specific to a host are also * read from this configuration handle * @param port port number to use for ssh; use 0 to let ssh decide * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname, const char *username, const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t port) { struct GNUNET_TESTBED_Host *host; unsigned int new_size; if ((id < host_list_size) && (NULL != host_list[id])) { LOG (GNUNET_ERROR_TYPE_WARNING, "Host with id: %u already created\n", id); return NULL; } host = GNUNET_new (struct GNUNET_TESTBED_Host); host->hostname = (NULL != hostname) ? GNUNET_strdup (hostname) : NULL; host->username = (NULL != username) ? GNUNET_strdup (username) : NULL; host->id = id; host->port = (0 == port) ? 22 : port; host->cfg = GNUNET_CONFIGURATION_dup (cfg); host->opq_parallel_overlay_connect_operations = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_ADAPTIVE, UINT_MAX); new_size = host_list_size; while (id >= new_size) new_size += HOST_LIST_GROW_STEP; if (new_size != host_list_size) GNUNET_array_grow (host_list, host_list_size, new_size); GNUNET_assert (id < host_list_size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding host with id: %u\n", host->id); host_list[id] = host; return host; } /** * Create a host to run peers and controllers on. * * @param hostname name of the host, use "NULL" for localhost * @param username username to use for the login; may be NULL * @param cfg the configuration to use as a template while starting a controller * on this host. Operation queue sizes specific to a host are also * read from this configuration handle * @param port port number to use for ssh; use 0 to let ssh decide * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_create (const char *hostname, const char *username, const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t port) { static uint32_t uid_generator; if (NULL == hostname) return GNUNET_TESTBED_host_create_with_id (0, hostname, username, cfg, port); return GNUNET_TESTBED_host_create_with_id (++uid_generator, hostname, username, cfg, port); } /** * Load a set of hosts from a configuration file. * * @param filename file with the host specification * @param cfg the configuration to use as a template while starting a controller * on any of the loaded hosts. Operation queue sizes specific to a host * are also read from this configuration handle * @param hosts set to the hosts found in the file; caller must free this if * number of hosts returned is greater than 0 * @return number of hosts returned in 'hosts', 0 on error */ unsigned int GNUNET_TESTBED_hosts_load_from_file (const char *filename, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTBED_Host ***hosts) { //struct GNUNET_TESTBED_Host **host_array; struct GNUNET_TESTBED_Host *starting_host; char *data; char *buf; char *username; char *hostname; regex_t rex; regmatch_t pmatch[6]; uint64_t fs; short int port; unsigned int offset; unsigned int count; GNUNET_assert (NULL != filename); if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Hosts file %s not found\n"), filename); return 0; } if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) fs = 0; if (0 == fs) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Hosts file %s has no data\n"), filename); return 0; } data = GNUNET_malloc (fs); if (fs != GNUNET_DISK_fn_read (filename, data, fs)) { GNUNET_free (data); LOG (GNUNET_ERROR_TYPE_WARNING, _("Hosts file %s cannot be read\n"), filename); return 0; } buf = data; offset = 0; starting_host = NULL; count = 0; /* refer RFC 952 and RFC 1123 for valid hostnames */ GNUNET_assert (0 == regcomp (&rex, "^(([[:alnum:]]+)@)?" /* username */ "([[:alnum:]]+[-[:alnum:]_\\.]+)" /* hostname */ "(:([[:digit:]]{1,5}))?", /* port */ REG_EXTENDED | REG_ICASE)); while (offset < (fs - 1)) { offset++; if (((data[offset] == '\n')) && (buf != &data[offset])) { unsigned int size; data[offset] = '\0'; username = NULL; hostname = NULL; port = 0; if ((REG_NOMATCH == regexec (&rex, buf, 6, pmatch, 0)) || (-1 == pmatch[3].rm_so)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Error reading line `%s' in hostfile\n", buf); buf = &data[offset + 1]; continue; } if (-1 != pmatch[2].rm_so) { size = pmatch[2].rm_eo - pmatch[2].rm_so; username = GNUNET_malloc (size + 1); username[size] = '\0'; GNUNET_assert (NULL != strncpy (username, buf + pmatch[2].rm_so, size)); } if (-1 != pmatch[5].rm_so) { (void) SSCANF (buf + pmatch[5].rm_so, "%5hd", &port); } size = pmatch[3].rm_eo - pmatch[3].rm_so; hostname = GNUNET_malloc (size + 1); hostname[size] = '\0'; GNUNET_assert (NULL != strncpy (hostname, buf + pmatch[3].rm_so, size)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Successfully read host %s, port %d and user %s from file\n", (NULL == hostname) ? "NULL" : hostname, port, (NULL == username) ? "NULL" : username); /* We store hosts in a static list; hence we only require the starting * host pointer in that list to access the newly created list of hosts */ if (NULL == starting_host) starting_host = GNUNET_TESTBED_host_create (hostname, username, cfg, port); else (void) GNUNET_TESTBED_host_create (hostname, username, cfg, port); count++; GNUNET_free_non_null (username); GNUNET_free (hostname); buf = &data[offset + 1]; } else if ((data[offset] == '\n') || (data[offset] == '\0')) buf = &data[offset + 1]; } regfree (&rex); GNUNET_free (data); if (NULL == starting_host) return 0; *hosts = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host *) * count); memcpy (*hosts, &host_list[GNUNET_TESTBED_host_get_id_ (starting_host)], sizeof (struct GNUNET_TESTBED_Host *) * count); return count; } /** * Resolves a hostname using getaddrinfo * * @param host the hostname * @return the string representing the IPv4 address of the given host; NULL upon error */ const char * simple_resolve (const char *host) { struct addrinfo *res; const struct sockaddr_in *in_addr; char *hostip; struct addrinfo hint; unsigned int rc; hint.ai_family = AF_INET; /* IPv4 */ hint.ai_socktype = 0; hint.ai_protocol = 0; hint.ai_addrlen = 0; hint.ai_addr = NULL; hint.ai_canonname = NULL; hint.ai_next = NULL; hint.ai_flags = AI_NUMERICSERV; res = NULL; LOG_DEBUG ("Resolving [%s]\n", host); if (0 != (rc = getaddrinfo (host, "22", &hint, &res))) { LOG_GAI (GNUNET_ERROR_TYPE_ERROR, "getaddrinfo", rc); return NULL; } GNUNET_assert (NULL != res); GNUNET_assert (NULL != res->ai_addr); GNUNET_assert (sizeof (struct sockaddr_in) == res->ai_addrlen); in_addr = (const struct sockaddr_in *) res->ai_addr; hostip = inet_ntoa (in_addr->sin_addr); GNUNET_assert (NULL != hostip); freeaddrinfo (res); LOG_DEBUG ("Resolved [%s] to [%s]\n", host, hostip); return hostip; } /** * Loads the set of host allocated by the LoadLeveler Job Scheduler. This * function is only available when compiled with support for LoadLeveler and is * used for running on the SuperMUC * * @param cfg the configuration to use as a template while starting a controller * on any of the loaded hosts. Operation queue sizes specific to a host * are also read from this configuration handle * @param hosts set to the hosts found in the file; caller must free this if * number of hosts returned is greater than 0 * @return number of hosts returned in 'hosts', 0 on error */ unsigned int GNUNET_TESTBED_hosts_load_from_loadleveler (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTBED_Host ***hosts) { #if !ENABLE_SUPERMUC LOG (GNUNET_ERROR_TYPE_ERROR, _("The function %s is only available when compiled with (--with-ll)\n"), __func__); GNUNET_assert (0); #else const char *hostfile; if (NULL == (hostfile = getenv ("MP_SAVEHOSTFILE"))) { GNUNET_break (0); return 0; } return GNUNET_TESTBED_hosts_load_from_file (hostfile, cfg, hosts); #endif } /** * Destroy a host handle. Must only be called once everything * running on that host has been stopped. * * @param host handle to destroy */ void GNUNET_TESTBED_host_destroy (struct GNUNET_TESTBED_Host *host) { struct RegisteredController *rc; uint32_t id; GNUNET_assert (host->id < host_list_size); GNUNET_assert (host_list[host->id] == host); host_list[host->id] = NULL; /* clear registered controllers list */ for (rc = host->rc_head; NULL != rc; rc = host->rc_head) { GNUNET_CONTAINER_DLL_remove (host->rc_head, host->rc_tail, rc); GNUNET_free (rc); } GNUNET_free_non_null ((char *) host->username); GNUNET_free_non_null ((char *) host->hostname); GNUNET_TESTBED_operation_queue_destroy_ (host->opq_parallel_overlay_connect_operations); GNUNET_CONFIGURATION_destroy (host->cfg); GNUNET_free (host); while (host_list_size >= HOST_LIST_GROW_STEP) { for (id = host_list_size - 1; id > host_list_size - HOST_LIST_GROW_STEP; id--) if (NULL != host_list[id]) break; if (id != host_list_size - HOST_LIST_GROW_STEP) break; if (NULL != host_list[id]) break; host_list_size -= HOST_LIST_GROW_STEP; } host_list = GNUNET_realloc (host_list, sizeof (struct GNUNET_TESTBED_Host *) * host_list_size); } /** * Marks a host as registered with a controller * * @param host the host to mark * @param controller the controller at which this host is registered */ void GNUNET_TESTBED_mark_host_registered_at_ (struct GNUNET_TESTBED_Host *host, const struct GNUNET_TESTBED_Controller *const controller) { struct RegisteredController *rc; for (rc = host->rc_head; NULL != rc; rc = rc->next) { if (controller == rc->controller) /* already registered at controller */ { GNUNET_break (0); return; } } rc = GNUNET_new (struct RegisteredController); rc->controller = controller; GNUNET_CONTAINER_DLL_insert_tail (host->rc_head, host->rc_tail, rc); } /** * Unmarks a host registered at a controller * * @param host the host to unmark * @param controller the controller at which this host has to be unmarked */ void GNUNET_TESTBED_deregister_host_at_ (struct GNUNET_TESTBED_Host *host, const struct GNUNET_TESTBED_Controller *const controller) { struct RegisteredController *rc; for (rc = host->rc_head; NULL != rc; rc=rc->next) if (controller == rc->controller) break; if (NULL == rc) { GNUNET_break (0); return; } GNUNET_CONTAINER_DLL_remove (host->rc_head, host->rc_tail, rc); GNUNET_free (rc); } /** * Checks whether a host has been registered * * @param host the host to check * @param controller the controller at which host's registration is checked * @return GNUNET_YES if registered; GNUNET_NO if not */ int GNUNET_TESTBED_is_host_registered_ (const struct GNUNET_TESTBED_Host *host, const struct GNUNET_TESTBED_Controller *const controller) { struct RegisteredController *rc; for (rc = host->rc_head; NULL != rc; rc = rc->next) { if (controller == rc->controller) /* already registered at controller */ { return GNUNET_YES; } } return GNUNET_NO; } /** * Handle for controller process */ struct GNUNET_TESTBED_ControllerProc { /** * The process handle */ struct GNUNET_HELPER_Handle *helper; /** * The arguments used to start the helper */ char **helper_argv; /** * The host where the helper is run */ struct GNUNET_TESTBED_Host *host; /** * The controller error callback */ GNUNET_TESTBED_ControllerStatusCallback cb; /** * The closure for the above callback */ void *cls; /** * The send handle for the helper */ struct GNUNET_HELPER_SendHandle *shandle; /** * The message corresponding to send handle */ struct GNUNET_MessageHeader *msg; }; /** * Function to copy NULL terminated list of arguments * * @param argv the NULL terminated list of arguments. Cannot be NULL. * @return the copied NULL terminated arguments */ static char ** copy_argv (const char *const *argv) { char **argv_dup; unsigned int argp; GNUNET_assert (NULL != argv); for (argp = 0; NULL != argv[argp]; argp++) ; argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1)); for (argp = 0; NULL != argv[argp]; argp++) argv_dup[argp] = strdup (argv[argp]); return argv_dup; } /** * Function to join NULL terminated list of arguments * * @param argv1 the NULL terminated list of arguments. Cannot be NULL. * @param argv2 the NULL terminated list of arguments. Cannot be NULL. * @return the joined NULL terminated arguments */ static char ** join_argv (const char *const *argv1, const char *const *argv2) { char **argvj; char *argv; unsigned int carg; unsigned int cnt; carg = 0; argvj = NULL; for (cnt = 0; NULL != argv1[cnt]; cnt++) { argv = GNUNET_strdup (argv1[cnt]); GNUNET_array_append (argvj, carg, argv); } for (cnt = 0; NULL != argv2[cnt]; cnt++) { argv = GNUNET_strdup (argv2[cnt]); GNUNET_array_append (argvj, carg, argv); } GNUNET_array_append (argvj, carg, NULL); return argvj; } /** * Frees the given NULL terminated arguments * * @param argv the NULL terminated list of arguments */ static void free_argv (char **argv) { unsigned int argp; for (argp = 0; NULL != argv[argp]; argp++) GNUNET_free (argv[argp]); GNUNET_free (argv); } /** * Generates arguments for opening a remote shell. Builds up the arguments * from the environment variable GNUNET_TESTBED_RSH_CMD. The variable * should not mention `-p' (port) option and destination address as these will * be set locally in the function from its parameteres. If the environmental * variable is not found then it defaults to `ssh -o BatchMode=yes -o * NoHostAuthenticationForLocalhost=yes' * * @param port the destination port number * @param hostname the hostname of the target host * @param username the username to use while connecting to target host * @return NULL terminated list of arguments */ static char ** gen_rsh_args (const char *port, const char *hostname, const char *username) { static const char *default_ssh_args[] = { "ssh", "-o", "BatchMode=yes", "-o", "NoHostAuthenticationForLocalhost=yes", "%h", NULL }; char **ssh_args; char *ssh_cmd; char *ssh_cmd_cp; char *arg; const char *new_arg; unsigned int size; unsigned int cnt; ssh_args = NULL; if (NULL != (ssh_cmd = getenv ("GNUNET_TESTBED_RSH_CMD"))) { ssh_cmd = GNUNET_strdup (ssh_cmd); ssh_cmd_cp = ssh_cmd; for (size = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL) GNUNET_array_append (ssh_args, size, GNUNET_strdup (arg)); GNUNET_free (ssh_cmd_cp); } else { ssh_args = copy_argv (default_ssh_args); size = (sizeof (default_ssh_args)) / (sizeof (const char *)); GNUNET_array_grow (ssh_args, size, size - 1); } for (cnt = 0; cnt < size; cnt++) { arg = ssh_args[cnt]; if ('%' != arg[0]) continue; switch (arg[1]) { case 'p': new_arg = port; break; case 'u': new_arg = username; break; case 'h': new_arg = hostname; break; default: continue; } if (NULL == new_arg) continue; GNUNET_free (arg); ssh_args[cnt] = GNUNET_strdup (new_arg); } GNUNET_array_append (ssh_args, size, NULL); return ssh_args; } /** * Generates the arguments needed for executing the given binary in a remote * shell. Builds the arguments from the environmental variable * GNUNET_TETSBED_RSH_CMD_SUFFIX. If the environmental variable is not found, * only the given binary name will be present in the returned arguments * * @param append_args the arguments to append after generating the suffix * arguments. Can be NULL; if not must be NULL terminated 'char *' array * @return NULL-terminated args */ static char ** gen_rsh_suffix_args (const char * const *append_args) { char **rshell_args; char *rshell_cmd; char *rshell_cmd_cp; char *arg; unsigned int cnt; unsigned int append_cnt; rshell_args = NULL; cnt = 0; if (NULL != (rshell_cmd = getenv ("GNUNET_TESTBED_RSH_CMD_SUFFIX"))) { rshell_cmd = GNUNET_strdup (rshell_cmd); rshell_cmd_cp = rshell_cmd; for (; NULL != (arg = strtok (rshell_cmd, " ")); rshell_cmd = NULL) GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (arg)); GNUNET_free (rshell_cmd_cp); } if (NULL != append_args) { for (append_cnt = 0; NULL != append_args[append_cnt]; append_cnt++) GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (append_args[append_cnt])); } GNUNET_array_append (rshell_args, cnt, NULL); return rshell_args; } /** * Functions with this signature are called whenever a * complete message is received by the tokenizer. * * Do not call GNUNET_SERVER_mst_destroy in callback * * @param cls closure * @param client identification of the client * @param message the actual message * * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing */ static int helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_TESTBED_ControllerProc *cp = cls; const struct GNUNET_TESTBED_HelperReply *msg; const char *hostname; char *config; uLongf config_size; uLongf xconfig_size; msg = (const struct GNUNET_TESTBED_HelperReply *) message; GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) < ntohs (msg->header.size)); GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY == ntohs (msg->header.type)); config_size = (uLongf) ntohs (msg->config_size); xconfig_size = (uLongf) (ntohs (msg->header.size) - sizeof (struct GNUNET_TESTBED_HelperReply)); config = GNUNET_malloc (config_size); GNUNET_assert (Z_OK == uncompress ((Bytef *) config, &config_size, (const Bytef *) &msg[1], xconfig_size)); /* Replace the configuration template present in the host with the controller's running configuration */ GNUNET_CONFIGURATION_destroy (cp->host->cfg); cp->host->cfg = GNUNET_CONFIGURATION_create (); GNUNET_assert (GNUNET_CONFIGURATION_deserialize (cp->host->cfg, config, config_size, GNUNET_NO)); GNUNET_free (config); if (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))) hostname = "localhost"; /* Change the hostname so that we can connect to it */ GNUNET_CONFIGURATION_set_value_string (cp->host->cfg, "testbed", "hostname", hostname); cp->host->locked = GNUNET_NO; cp->host->controller_started = GNUNET_YES; cp->cb (cp->cls, cp->host->cfg, GNUNET_OK); return GNUNET_OK; } /** * Continuation function from GNUNET_HELPER_send() * * @param cls closure * @param result GNUNET_OK on success, * GNUNET_NO if helper process died * GNUNET_SYSERR during GNUNET_HELPER_stop */ static void clear_msg (void *cls, int result) { struct GNUNET_TESTBED_ControllerProc *cp = cls; GNUNET_assert (NULL != cp->shandle); cp->shandle = NULL; GNUNET_free (cp->msg); cp->msg = NULL; } /** * Callback that will be called when the helper process dies. This is not called * when the helper process is stoped using GNUNET_HELPER_stop() * * @param cls the closure from GNUNET_HELPER_start() */ static void helper_exp_cb (void *cls) { struct GNUNET_TESTBED_ControllerProc *cp = cls; GNUNET_TESTBED_ControllerStatusCallback cb; void *cb_cls; cb = cp->cb; cb_cls = cp->cls; cp->helper = NULL; GNUNET_TESTBED_controller_stop (cp); if (NULL != cb) cb (cb_cls, NULL, GNUNET_SYSERR); } /** * Starts a controller process at the given host. The given host's configration * is used as a Template configuration to use for the remote controller; the * remote controller will be started with a slightly modified configuration * (port numbers, unix domain sockets and service home values are changed as per * TESTING library on the remote host). The modified configuration replaces the * host's existing configuration before signalling success through the * GNUNET_TESTBED_ControllerStatusCallback() * * @param trusted_ip the ip address of the controller which will be set as TRUSTED * HOST(all connections form this ip are permitted by the testbed) when * starting testbed controller at host. This can either be a single ip * address or a network address in CIDR notation. * @param host the host where the controller has to be started. CANNOT be NULL. * @param cb function called when the controller is successfully started or * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be * called if cb is called with GNUNET_SYSERR as status. Will never be * called in the same task as 'GNUNET_TESTBED_controller_start' * (synchronous errors will be signalled by returning NULL). This * parameter cannot be NULL. * @param cls closure for above callbacks * @return the controller process handle, NULL on errors */ struct GNUNET_TESTBED_ControllerProc * GNUNET_TESTBED_controller_start (const char *trusted_ip, struct GNUNET_TESTBED_Host *host, GNUNET_TESTBED_ControllerStatusCallback cb, void *cls) { struct GNUNET_TESTBED_ControllerProc *cp; struct GNUNET_TESTBED_HelperInit *msg; const struct GNUNET_CONFIGURATION_Handle *cfg; const char *hostname; static char *const binary_argv[] = { HELPER_TESTBED_BINARY, NULL }; GNUNET_assert (NULL != host); GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host))); hostname = NULL; API_VIOLATION (GNUNET_NO == host->locked, "Host is already locked by a previous call to GNUNET_TESTBED_controller_start()"); host->locked = GNUNET_YES; API_VIOLATION (GNUNET_NO == host->controller_started, "Attempting to start a controller on a host which is already started a controller"); cp = GNUNET_new (struct GNUNET_TESTBED_ControllerProc); if (0 == GNUNET_TESTBED_host_get_id_ (host)) { cp->helper = GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv, &helper_mst, &helper_exp_cb, cp); } else { char *helper_binary_path_args[2]; char **rsh_args; char **rsh_suffix_args; const char *username; char *port; char *argstr; char *aux; unsigned int cnt; username = host->username; hostname = host->hostname; GNUNET_asprintf (&port, "%u", host->port); LOG_DEBUG ("Starting remote connection to destination %s\n", hostname); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "testbed", "HELPER_BINARY_PATH", &helper_binary_path_args[0])) helper_binary_path_args[0] = GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY); helper_binary_path_args[1] = NULL; rsh_args = gen_rsh_args (port, hostname, username); rsh_suffix_args = gen_rsh_suffix_args ((const char **) helper_binary_path_args); cp->helper_argv = join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args); free_argv (rsh_args); free_argv (rsh_suffix_args); GNUNET_free (port); argstr = GNUNET_strdup (""); for (cnt = 0; NULL != cp->helper_argv[cnt]; cnt++) { aux = argstr; GNUNET_assert (0 < GNUNET_asprintf (&argstr, "%s %s", aux, cp->helper_argv[cnt])); GNUNET_free (aux); } LOG_DEBUG ("Helper cmd str: %s\n", argstr); GNUNET_free (argstr); cp->helper = GNUNET_HELPER_start (GNUNET_NO, cp->helper_argv[0], cp->helper_argv, &helper_mst, &helper_exp_cb, cp); GNUNET_free (helper_binary_path_args[0]); } if (NULL == cp->helper) { if (NULL != cp->helper_argv) free_argv (cp->helper_argv); GNUNET_free (cp); return NULL; } cp->host = host; cp->cb = cb; cp->cls = cls; msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg); cp->msg = &msg->header; cp->shandle = GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp); if (NULL == cp->shandle) { GNUNET_free (msg); GNUNET_TESTBED_controller_stop (cp); return NULL; } return cp; } /** * Sends termination signal to the controller's helper process * * @param cproc the handle to the controller's helper process */ void GNUNET_TESTBED_controller_kill_ (struct GNUNET_TESTBED_ControllerProc *cproc) { if (NULL != cproc->shandle) GNUNET_HELPER_send_cancel (cproc->shandle); if (NULL != cproc->helper) GNUNET_HELPER_kill (cproc->helper, GNUNET_YES); } /** * Cleans-up the controller's helper process handle * * @param cproc the handle to the controller's helper process */ void GNUNET_TESTBED_controller_destroy_ (struct GNUNET_TESTBED_ControllerProc *cproc) { if (NULL != cproc->helper) { GNUNET_break (GNUNET_OK == GNUNET_HELPER_wait (cproc->helper)); GNUNET_HELPER_destroy (cproc->helper); } if (NULL != cproc->helper_argv) free_argv (cproc->helper_argv); cproc->host->controller_started = GNUNET_NO; cproc->host->locked = GNUNET_NO; GNUNET_free_non_null (cproc->msg); GNUNET_free (cproc); } /** * Stop the controller process (also will terminate all peers and controllers * dependent on this controller). This function blocks until the testbed has * been fully terminated (!). The controller status cb from * GNUNET_TESTBED_controller_start() will not be called. * * @param cproc the controller process handle */ void GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc) { GNUNET_TESTBED_controller_kill_ (cproc); GNUNET_TESTBED_controller_destroy_ (cproc); } /** * The handle for whether a host is habitable or not */ struct GNUNET_TESTBED_HostHabitableCheckHandle { /** * The host to check */ const struct GNUNET_TESTBED_Host *host; /** * The callback to call once we have the status */ GNUNET_TESTBED_HostHabitableCallback cb; /** * The callback closure */ void *cb_cls; /** * The process handle for the SSH process */ struct GNUNET_OS_Process *auxp; /** * The arguments used to start the helper */ char **helper_argv; /** * Task id for the habitability check task */ GNUNET_SCHEDULER_TaskIdentifier habitability_check_task; /** * How long we wait before checking the process status. Should grow * exponentially */ struct GNUNET_TIME_Relative wait_time; }; /** * Task for checking whether a host is habitable or not * * @param cls GNUNET_TESTBED_HostHabitableCheckHandle * @param tc the scheduler task context */ static void habitability_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_HostHabitableCheckHandle *h = cls; void *cb_cls; GNUNET_TESTBED_HostHabitableCallback cb; const struct GNUNET_TESTBED_Host *host; unsigned long code; enum GNUNET_OS_ProcessStatusType type; int ret; h->habitability_check_task = GNUNET_SCHEDULER_NO_TASK; ret = GNUNET_OS_process_status (h->auxp, &type, &code); if (GNUNET_SYSERR == ret) { GNUNET_break (0); ret = GNUNET_NO; goto call_cb; } if (GNUNET_NO == ret) { h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time); h->habitability_check_task = GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h); return; } GNUNET_OS_process_destroy (h->auxp); h->auxp = NULL; ret = (0 != code) ? GNUNET_NO : GNUNET_YES; call_cb: if (NULL != h->auxp) GNUNET_OS_process_destroy (h->auxp); cb = h->cb; cb_cls = h->cb_cls; host = h->host; free_argv (h->helper_argv); GNUNET_free (h); if (NULL != cb) cb (cb_cls, host, ret); } /** * Checks whether a host can be used to start testbed service * * @param host the host to check * @param config the configuration handle to lookup the path of the testbed * helper * @param cb the callback to call to inform about habitability of the given host * @param cb_cls the closure for the callback * @return NULL upon any error or a handle which can be passed to * GNUNET_TESTBED_is_host_habitable_cancel() */ struct GNUNET_TESTBED_HostHabitableCheckHandle * GNUNET_TESTBED_is_host_habitable (const struct GNUNET_TESTBED_Host *host, const struct GNUNET_CONFIGURATION_Handle *config, GNUNET_TESTBED_HostHabitableCallback cb, void *cb_cls) { struct GNUNET_TESTBED_HostHabitableCheckHandle *h; char **rsh_args; char **rsh_suffix_args; char *stat_args[3]; const char *hostname; char *port; h = GNUNET_new (struct GNUNET_TESTBED_HostHabitableCheckHandle); h->cb = cb; h->cb_cls = cb_cls; h->host = host; hostname = (NULL == host->hostname) ? "127.0.0.1" : host->hostname; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (config, "testbed", "HELPER_BINARY_PATH", &stat_args[1])) stat_args[1] = GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY); GNUNET_asprintf (&port, "%u", host->port); rsh_args = gen_rsh_args (port, hostname, host->username); GNUNET_free (port); port = NULL; stat_args[0] = "stat"; stat_args[2] = NULL; rsh_suffix_args = gen_rsh_suffix_args ((const char **) stat_args); GNUNET_free (stat_args[1]); h->helper_argv = join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args); free_argv (rsh_suffix_args); free_argv (rsh_args); h->auxp = GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, NULL, NULL, NULL, h->helper_argv[0], h->helper_argv); if (NULL == h->auxp) { GNUNET_break (0); /* Cannot exec SSH? */ GNUNET_free (h); return NULL; } h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time); h->habitability_check_task = GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h); return h; } /** * Function to cancel a request started using GNUNET_TESTBED_is_host_habitable() * * @param handle the habitability check handle */ void GNUNET_TESTBED_is_host_habitable_cancel (struct GNUNET_TESTBED_HostHabitableCheckHandle *handle) { GNUNET_SCHEDULER_cancel (handle->habitability_check_task); (void) GNUNET_OS_process_kill (handle->auxp, GNUNET_TERM_SIG); (void) GNUNET_OS_process_wait (handle->auxp); GNUNET_OS_process_destroy (handle->auxp); free_argv (handle->helper_argv); GNUNET_free (handle); } /** * handle for host registration */ struct GNUNET_TESTBED_HostRegistrationHandle { /** * The host being registered */ struct GNUNET_TESTBED_Host *host; /** * The controller at which this host is being registered */ struct GNUNET_TESTBED_Controller *c; /** * The Registartion completion callback */ GNUNET_TESTBED_HostRegistrationCompletion cc; /** * The closure for above callback */ void *cc_cls; }; /** * Register a host with the controller * * @param controller the controller handle * @param host the host to register * @param cc the completion callback to call to inform the status of * registration. After calling this callback the registration handle * will be invalid. Cannot be NULL. * @param cc_cls the closure for the cc * @return handle to the host registration which can be used to cancel the * registration */ struct GNUNET_TESTBED_HostRegistrationHandle * GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller, struct GNUNET_TESTBED_Host *host, GNUNET_TESTBED_HostRegistrationCompletion cc, void *cc_cls) { struct GNUNET_TESTBED_HostRegistrationHandle *rh; struct GNUNET_TESTBED_AddHostMessage *msg; const char *username; const char *hostname; char *config; char *cconfig; void *ptr; size_t cc_size; size_t config_size; uint16_t msg_size; uint16_t username_length; uint16_t hostname_length; if (NULL != controller->rh) return NULL; hostname = GNUNET_TESTBED_host_get_hostname (host); if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Host hostname: %s already registered\n", (NULL == hostname) ? "localhost" : hostname); return NULL; } rh = GNUNET_new (struct GNUNET_TESTBED_HostRegistrationHandle); rh->host = host; rh->c = controller; GNUNET_assert (NULL != cc); rh->cc = cc; rh->cc_cls = cc_cls; controller->rh = rh; username = GNUNET_TESTBED_host_get_username_ (host); username_length = 0; if (NULL != username) username_length = strlen (username); GNUNET_assert (NULL != hostname); /* Hostname must be present */ hostname_length = strlen (hostname); GNUNET_assert (NULL != host->cfg); config = GNUNET_CONFIGURATION_serialize (host->cfg, &config_size); cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig); GNUNET_free (config); msg_size = (sizeof (struct GNUNET_TESTBED_AddHostMessage)); msg_size += username_length; msg_size += hostname_length; msg_size += cc_size; msg = GNUNET_malloc (msg_size); msg->header.size = htons (msg_size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST); msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host)); msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host)); ptr = &msg[1]; if (NULL != username) { msg->username_length = htons (username_length); ptr = memcpy (ptr, username, username_length); ptr += username_length; } msg->hostname_length = htons (hostname_length); ptr = memcpy (ptr, hostname, hostname_length); ptr += hostname_length; msg->config_size = htons (config_size); ptr = memcpy (ptr, cconfig, cc_size); ptr += cc_size; GNUNET_assert ((ptr - (void *) msg) == msg_size); GNUNET_free (cconfig); GNUNET_TESTBED_queue_message_ (controller, (struct GNUNET_MessageHeader *) msg); return rh; } /** * Cancel the pending registration. Note that if the registration message is * already sent to the service the cancellation has only the effect that the * registration completion callback for the registration is never called. * * @param handle the registration handle to cancel */ void GNUNET_TESTBED_cancel_registration (struct GNUNET_TESTBED_HostRegistrationHandle *handle) { if (handle != handle->c->rh) { GNUNET_break (0); return; } handle->c->rh = NULL; GNUNET_free (handle); } /** * Queues the given operation in the queue for parallel overlay connects of the * given host * * @param h the host handle * @param op the operation to queue in the given host's parally overlay connect * queue */ void GNUNET_TESTBED_host_queue_oc_ (struct GNUNET_TESTBED_Host *h, struct GNUNET_TESTBED_Operation *op) { GNUNET_TESTBED_operation_queue_insert_ (h->opq_parallel_overlay_connect_operations, op); } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from * controller (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ int GNUNET_TESTBED_host_handle_addhostconfirm_ (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_HostConfirmedMessage *msg) { struct GNUNET_TESTBED_HostRegistrationHandle *rh; char *emsg; uint16_t msg_size; rh = c->rh; if (NULL == rh) { return GNUNET_OK; } if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id)) { LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n", GNUNET_TESTBED_host_get_id_ (rh->host), ntohl (msg->host_id)); return GNUNET_OK; } c->rh = NULL; msg_size = ntohs (msg->header.size); if (sizeof (struct GNUNET_TESTBED_HostConfirmedMessage) == msg_size) { LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id)); GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c); rh->cc (rh->cc_cls, NULL); GNUNET_free (rh); return GNUNET_OK; } /* We have an error message */ emsg = (char *) &msg[1]; if ('\0' != emsg[msg_size - sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)]) { GNUNET_break (0); GNUNET_free (rh); return GNUNET_NO; } LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding host %u failed with error: %s\n"), ntohl (msg->host_id), emsg); rh->cc (rh->cc_cls, emsg); GNUNET_free (rh); return GNUNET_OK; } /** * Resolves the hostname of the host to an ip address * * @param host the host whose hostname is to be resolved */ void GNUNET_TESTBED_host_resolve_ (struct GNUNET_TESTBED_Host *host) { char *hostname; hostname = (char *) host->hostname; host->hostname = simple_resolve (hostname); if (NULL == host->hostname) { GNUNET_break (0); host->hostname = hostname; return; } GNUNET_free (hostname); host->hostname = GNUNET_strdup (host->hostname); } /* end of testbed_api_hosts.c */ gnunet-0.10.1/src/testbed/test_testbed_underlay.conf.in0000644000175000017500000000037612263473436020123 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = LINE OPERATION_TIMEOUT = 5 s [testbed-underlay] AUTOSTART = NO DBFILE = /will/be/overwritten/by/testcase [dv] AUTOSTART = NO [arm] DEFAULTSERVICES = core transport testbed-underlay gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf0000644000175000017500000000015312233724131025054 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = SMALL_WORLD OVERLAY_RANDOM_LINKS = 3 gnunet-0.10.1/src/testbed/test_gnunet_helper_testbed.c0000644000175000017500000001477612225777502020037 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_gnunet_helper_testbed.c * @brief Testcase for testing gnunet-helper-testbed.c * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include #include "testbed_api.h" #include "testbed_helper.h" #include "testbed_api_hosts.h" /** * Generic logging shortcut */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Handle to the helper process */ static struct GNUNET_HELPER_Handle *helper; /** * Message to helper */ static struct GNUNET_TESTBED_HelperInit *msg; /** * Message send handle */ static struct GNUNET_HELPER_SendHandle *shandle; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * Shutdown task identifier */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Configuratin handler */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Global testing status */ static int result; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); if (NULL != helper) GNUNET_HELPER_stop (helper, GNUNET_NO); GNUNET_free_non_null (msg); if (NULL != cfg) GNUNET_CONFIGURATION_destroy (cfg); } /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { abort_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); result = GNUNET_SYSERR; if (NULL != shandle) GNUNET_HELPER_send_cancel (shandle); if (GNUNET_SCHEDULER_NO_TASK == shutdown_task) shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } /** * Continuation function. * * @param cls closure * @param result GNUNET_OK on success, * GNUNET_NO if helper process died * GNUNET_SYSERR during GNUNET_HELPER_stop */ static void cont_cb (void *cls, int result) { shandle = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "Message sent\n"); GNUNET_assert (GNUNET_OK == result); } /** * Functions with this signature are called whenever a * complete message is received by the tokenizer. * * Do not call GNUNET_SERVER_mst_destroy in callback * * @param cls closure * @param client identification of the client * @param message the actual message * * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing */ static int mst_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_HelperReply *msg; char *config; uLongf config_size; uLongf xconfig_size; msg = (const struct GNUNET_TESTBED_HelperReply *) message; config_size = 0; xconfig_size = 0; GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) < ntohs (msg->header.size)); GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY == ntohs (msg->header.type)); config_size = (uLongf) ntohs (msg->config_size); xconfig_size = (uLongf) (ntohs (msg->header.size) - sizeof (struct GNUNET_TESTBED_HelperReply)); config = GNUNET_malloc (config_size); GNUNET_assert (Z_OK == uncompress ((Bytef *) config, &config_size, (const Bytef *) &msg[1], xconfig_size)); GNUNET_free (config); if (GNUNET_SCHEDULER_NO_TASK == shutdown_task) shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), &do_shutdown, NULL); return GNUNET_OK; } /** * Callback that will be called when the helper process dies. This is not called * when the helper process is stoped using GNUNET_HELPER_stop() * * @param cls the closure from GNUNET_HELPER_start() */ static void exp_cb (void *cls) { helper = NULL; result = GNUNET_SYSERR; } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg2) { static char *const binary_argv[] = { "gnunet-helper-testbed", NULL }; const char *trusted_ip = "127.0.0.1"; helper = GNUNET_HELPER_start (GNUNET_YES, "gnunet-helper-testbed", binary_argv, &mst_cb, &exp_cb, NULL); GNUNET_assert (NULL != helper); cfg = GNUNET_CONFIGURATION_dup (cfg2); msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, NULL, cfg); shandle = GNUNET_HELPER_send (helper, &msg->header, GNUNET_NO, &cont_cb, NULL); GNUNET_assert (NULL != shandle); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1), &do_abort, NULL); } /** * Main function * * @param argc the number of command line arguments * @param argv command line arg array * @return return code */ int main (int argc, char **argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; result = GNUNET_OK; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test_gnunet_helper_testbed", "Testcase for testing gnunet-helper-testbed.c", options, &run, NULL)) return 1; return (GNUNET_OK == result) ? 0 : 1; } /* end of test_gnunet_helper_testbed.c */ gnunet-0.10.1/src/testbed/gnunet-service-testbed_cache.c0000644000175000017500000001521112277162077020123 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_cache.c * @brief testbed cache implementation * @author Sree Harsha Totakura */ #include "gnunet-service-testbed.h" /** * Redefine LOG with a changed log component string */ #ifdef LOG #undef LOG #endif #define LOG(kind,...) \ GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__) /** * Cache entry */ struct CacheEntry { /** * DLL next ptr for least recently used cache entries */ struct CacheEntry *next; /** * DLL prev ptr for least recently used cache entries */ struct CacheEntry *prev; /** * The HELLO message */ struct GNUNET_MessageHeader *hello; /** * The id of the peer this entry corresponds to */ unsigned int peer_id; }; /** * Hashmap to maintain cache */ static struct GNUNET_CONTAINER_MultiHashMap32 *cache; /** * DLL head for least recently used cache entries; least recently used * cache items are at the head. The cache enties are added to this queue when * their demand becomes zero. They are removed from the queue when they are * needed by any operation. */ static struct CacheEntry *cache_head; /** * DLL tail for least recently used cache entries; recently used cache * items are at the tail.The cache enties are added to this queue when * their demand becomes zero. They are removed from the queue when they are * needed by any operation. */ static struct CacheEntry *cache_tail; /** * Maximum number of elements to cache */ static unsigned int cache_size; /** * Looks up in the cache and returns the entry * * @param peer_id the peer identity of the peer whose corresponding entry has to * be looked up * @return the HELLO message; NULL if not found */ static struct CacheEntry * cache_lookup (unsigned int peer_id) { struct CacheEntry *entry; GNUNET_assert (NULL != cache); entry = GNUNET_CONTAINER_multihashmap32_get (cache, peer_id); if (NULL == entry) return NULL; GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, entry); GNUNET_CONTAINER_DLL_insert_tail (cache_head, cache_tail, entry); return entry; } /** * Free the resources occupied by a cache entry * * @param entry the cache entry to free */ static void free_entry (struct CacheEntry *entry) { GNUNET_CONTAINER_DLL_remove (cache_head, cache_tail, entry); GNUNET_free_non_null (entry->hello); GNUNET_free (entry); } /** * Creates a new cache entry and then puts it into the cache's hashtable. * * @param peer_id the index of the peer to tag the newly created entry * @return the newly created entry */ static struct CacheEntry * add_entry (unsigned int peer_id) { struct CacheEntry *entry; GNUNET_assert (NULL != cache); if (cache_size == GNUNET_CONTAINER_multihashmap32_size (cache)) { /* remove the LRU head */ entry = cache_head; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_remove (cache, (uint32_t) entry->peer_id, entry)); free_entry (entry); } entry = GNUNET_new (struct CacheEntry); entry->peer_id = peer_id; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (cache, (uint32_t) peer_id, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); GNUNET_CONTAINER_DLL_insert_tail (cache_head, cache_tail, entry); return entry; } /** * Iterator over hash map entries. * * @param cls closure * @param key current key * @param value value in the hash map * @return GNUNET_YES if we should continue to * iterate, * GNUNET_NO if not. */ static int cache_clear_iterator (void *cls, uint32_t key, void *value) { struct CacheEntry *entry = value; GNUNET_assert (NULL != entry); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_remove (cache, key, value)); free_entry (entry); return GNUNET_YES; } /** * Clear cache */ void GST_cache_clear () { if (NULL != cache) { GNUNET_CONTAINER_multihashmap32_iterate (cache, &cache_clear_iterator, NULL); GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (cache)); GNUNET_CONTAINER_multihashmap32_destroy (cache); cache = NULL; } cache_size = 0; cache_head = NULL; cache_tail = NULL; } /** * Initializes the cache * * @param size the size of the cache */ void GST_cache_init (unsigned int size) { if (0 == size) return; cache_size = size; cache = GNUNET_CONTAINER_multihashmap32_create (cache_size); } /** * Looks up in the hello cache and returns the HELLO of the given peer * * @param peer_id the index of the peer whose HELLO has to be looked up * @return the HELLO message; NULL if not found */ const struct GNUNET_MessageHeader * GST_cache_lookup_hello (const unsigned int peer_id) { struct CacheEntry *entry; LOG_DEBUG ("Looking up HELLO for peer %u\n", peer_id); if (NULL == cache) { LOG_DEBUG ("Caching disabled\n"); return NULL; } entry = cache_lookup (peer_id); if (NULL == entry) return NULL; if (NULL != entry->hello) LOG_DEBUG ("HELLO found for peer %u\n", peer_id); return entry->hello; } /** * Caches the HELLO of the given peer. Updates the HELLO if it was already * cached before * * @param peer_id the peer identity of the peer whose HELLO has to be cached * @param hello the HELLO message */ void GST_cache_add_hello (const unsigned int peer_id, const struct GNUNET_MessageHeader *hello) { struct CacheEntry *entry; if (NULL == cache) return; entry = cache_lookup (peer_id); if (NULL == entry) entry = add_entry (peer_id); GNUNET_free_non_null (entry->hello); entry->hello = GNUNET_copy_message (hello); } /* end of gnunet-service-testbed_hc.c */ gnunet-0.10.1/src/testbed/testbed_logger_api.c0000644000175000017500000003102412307312000016205 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_logger_api.c * @brief Client-side routines for communicating with the tesbted logger service * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_logger_service.h" /** * Generic logging shorthand */ #define LOG(kind, ...) \ GNUNET_log_from (kind, "testbed-logger-api", __VA_ARGS__) /** * Debug logging */ #define LOG_DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) #ifdef GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD #undef GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD #endif /** * Threshold after which exponential backoff should not increase (15 s). */ #define GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) /** * The size of the buffer we fill before sending out the message */ #define BUFFER_SIZE GNUNET_SERVER_MAX_MESSAGE_SIZE /** * The message queue for sending messages to the controller service */ struct MessageQueue { /** * next pointer for DLL */ struct MessageQueue *next; /** * prev pointer for DLL */ struct MessageQueue *prev; /** * The message to be sent */ struct GNUNET_MessageHeader *msg; /** * Completion callback */ GNUNET_TESTBED_LOGGER_FlushCompletion cb; /** * callback closure */ void *cb_cls; }; /** * Connection handle for the logger service */ struct GNUNET_TESTBED_LOGGER_Handle { /** * Client connection */ struct GNUNET_CLIENT_Connection *client; /** * The transport handle */ struct GNUNET_CLIENT_TransmitHandle *th; /** * DLL head for the message queue */ struct MessageQueue *mq_head; /** * DLL tail for the message queue */ struct MessageQueue *mq_tail; /** * Flush completion callback */ GNUNET_TESTBED_LOGGER_FlushCompletion cb; /** * Closure for the above callback */ void *cb_cls; /** * Local buffer for data to be transmitted */ void *buf; /** * The size of the local buffer */ size_t bs; /** * Number of bytes wrote since last flush */ size_t bwrote; /** * How long after should we retry sending a message to the service? */ struct GNUNET_TIME_Relative retry_backoff; /** * Task to call the flush completion callback */ GNUNET_SCHEDULER_TaskIdentifier flush_completion_task; /** * Task to be executed when flushing takes too long */ GNUNET_SCHEDULER_TaskIdentifier timeout_flush_task; }; /** * Cancels the flush timeout task * * @param h handle to the logger */ static void cancel_timeout_flush (struct GNUNET_TESTBED_LOGGER_Handle *h) { GNUNET_SCHEDULER_cancel (h->timeout_flush_task); h->timeout_flush_task = GNUNET_SCHEDULER_NO_TASK; } /** * Task to call the flush completion notification * * @param cls the logger handle * @param tc the scheduler task context */ static void call_flush_completion (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_LOGGER_Handle *h = cls; GNUNET_TESTBED_LOGGER_FlushCompletion cb; void *cb_cls; size_t bw; h->flush_completion_task = GNUNET_SCHEDULER_NO_TASK; bw = h->bwrote; h->bwrote = 0; cb = h->cb; h->cb = NULL; cb_cls = h->cb_cls; h->cb_cls = NULL; if (GNUNET_SCHEDULER_NO_TASK != h->timeout_flush_task) cancel_timeout_flush (h); if (NULL != cb) cb (cb_cls, bw); } /** * Schedule the flush completion notification task * * @param h logger handle */ static void trigger_flush_notification (struct GNUNET_TESTBED_LOGGER_Handle *h) { if (GNUNET_SCHEDULER_NO_TASK != h->flush_completion_task) GNUNET_SCHEDULER_cancel (h->flush_completion_task); h->flush_completion_task = GNUNET_SCHEDULER_add_now (&call_flush_completion, h); } /** * Function called to notify a client about the connection begin ready to queue * more data. "buf" will be NULL and "size" zero if the connection was closed * for writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_ready_notify (void *cls, size_t size, void *buf) { struct GNUNET_TESTBED_LOGGER_Handle *h = cls; struct MessageQueue *mq; h->th = NULL; mq = h->mq_head; GNUNET_assert (NULL != mq); if ((0 == size) && (NULL == buf)) /* Timeout */ { LOG_DEBUG ("Message sending timed out -- retrying\n"); h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ntohs (mq->msg->size), h->retry_backoff, GNUNET_YES, &transmit_ready_notify, h); return 0; } h->retry_backoff = GNUNET_TIME_UNIT_ZERO; GNUNET_assert (ntohs (mq->msg->size) <= size); size = ntohs (mq->msg->size); memcpy (buf, mq->msg, size); LOG_DEBUG ("Message of type: %u and size: %u sent\n", ntohs (mq->msg->type), size); GNUNET_free (mq->msg); GNUNET_CONTAINER_DLL_remove (h->mq_head, h->mq_tail, mq); GNUNET_free (mq); h->bwrote += (size - sizeof (struct GNUNET_MessageHeader)); mq = h->mq_head; if (NULL != mq) { h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ntohs (mq->msg->size), h->retry_backoff, GNUNET_YES, &transmit_ready_notify, h); return size; } if (NULL != h->cb) trigger_flush_notification (h); /* Call the flush completion callback */ return size; } /** * Queues a message in send queue of the logger handle * * @param h the logger handle * @param msg the message to queue */ static void queue_message (struct GNUNET_TESTBED_LOGGER_Handle *h, struct GNUNET_MessageHeader *msg) { struct MessageQueue *mq; uint16_t type; uint16_t size; type = ntohs (msg->type); size = ntohs (msg->size); mq = GNUNET_new (struct MessageQueue); mq->msg = msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing message of type %u, size %u for sending\n", type, ntohs (msg->size)); GNUNET_CONTAINER_DLL_insert_tail (h->mq_head, h->mq_tail, mq); if (NULL == h->th) { h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, h->retry_backoff, GNUNET_YES, &transmit_ready_notify, h); } } /** * Send the buffered data to the service * * @param h the logger handle */ static void dispatch_buffer (struct GNUNET_TESTBED_LOGGER_Handle *h) { struct GNUNET_MessageHeader *msg; size_t msize; msize = sizeof (struct GNUNET_MessageHeader) + h->bs; msg = GNUNET_realloc (h->buf, msize); h->buf = NULL; memmove (&msg[1], msg, h->bs); h->bs = 0; msg->type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG); msg->size = htons (msize); queue_message (h, msg); } /** * Connect to the testbed logger service * * @param cfg configuration to use * @return the handle which can be used for sending data to the service; NULL * upon any error */ struct GNUNET_TESTBED_LOGGER_Handle * GNUNET_TESTBED_LOGGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_TESTBED_LOGGER_Handle *h; struct GNUNET_CLIENT_Connection *client; client = GNUNET_CLIENT_connect ("testbed-logger", cfg); if (NULL == client) return NULL; h = GNUNET_new (struct GNUNET_TESTBED_LOGGER_Handle); h->client = client; return h; } /** * Disconnect from the logger service. * * @param h the logger handle */ void GNUNET_TESTBED_LOGGER_disconnect (struct GNUNET_TESTBED_LOGGER_Handle *h) { struct MessageQueue *mq; unsigned int lost; if (GNUNET_SCHEDULER_NO_TASK != h->flush_completion_task) GNUNET_SCHEDULER_cancel (h->flush_completion_task); lost = 0; while (NULL != (mq = h->mq_head)) { GNUNET_CONTAINER_DLL_remove (h->mq_head, h->mq_tail, mq); GNUNET_free (mq->msg); GNUNET_free (mq); lost++; } if (0 != lost) LOG (GNUNET_ERROR_TYPE_WARNING, "Cleaning up %u unsent logger message[s]\n", lost); GNUNET_CLIENT_disconnect (h->client); GNUNET_free (h); } /** * Send data to be logged to the logger service. The data will be buffered and * will be sent upon an explicit call to GNUNET_TESTBED_LOGGER_flush() or upon * exceeding a threshold size. * * @param h the logger handle * @param data the data to send; * @param size how many bytes of data to send */ void GNUNET_TESTBED_LOGGER_write (struct GNUNET_TESTBED_LOGGER_Handle *h, const void *data, size_t size) { size_t fit_size; GNUNET_assert (0 != size); GNUNET_assert (NULL != data); GNUNET_assert (size <= (BUFFER_SIZE - sizeof (struct GNUNET_MessageHeader))); fit_size = sizeof (struct GNUNET_MessageHeader) + h->bs + size; if ( BUFFER_SIZE < fit_size ) dispatch_buffer (h); if (NULL == h->buf) { h->buf = GNUNET_malloc (size); h->bs = size; memcpy (h->buf, data, size); goto dispatch_ready; } h->buf = GNUNET_realloc (h->buf, h->bs + size); memcpy (h->buf + h->bs, data, size); h->bs += size; dispatch_ready: if (BUFFER_SIZE == fit_size) dispatch_buffer (h); } /** * Task to be executed when flushing our local buffer takes longer than timeout * given to GNUNET_TESTBED_LOGGER_flush(). The flush completion callback will * be called with 0 as the amount of data sent. * * @param cls the logger handle * @param tc scheduler task context */ static void timeout_flush (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_LOGGER_Handle *h = cls; GNUNET_TESTBED_LOGGER_FlushCompletion cb; void *cb_cls; h->timeout_flush_task = GNUNET_SCHEDULER_NO_TASK; cb = h->cb; h->cb = NULL; cb_cls = h->cb_cls; h->cb_cls = NULL; if (GNUNET_SCHEDULER_NO_TASK != h->flush_completion_task) { GNUNET_SCHEDULER_cancel (h->flush_completion_task); h->flush_completion_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != cb) cb (cb_cls, 0); } /** * Flush the buffered data to the logger service * * @param h the logger handle * @param timeout how long to wait before calling the flust completion callback * @param cb the callback to call after the data is flushed * @param cb_cls the closure for the above callback */ void GNUNET_TESTBED_LOGGER_flush (struct GNUNET_TESTBED_LOGGER_Handle *h, struct GNUNET_TIME_Relative timeout, GNUNET_TESTBED_LOGGER_FlushCompletion cb, void *cb_cls) { h->cb = cb; h->cb_cls = cb_cls; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->timeout_flush_task); h->timeout_flush_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_flush, h); if (NULL == h->buf) { trigger_flush_notification (h); return; } dispatch_buffer (h); } /** * Cancel notification upon flush. Should only be used when the flush * completion callback given to GNUNET_TESTBED_LOGGER_flush() is not already * called. * * @param h the logger handle */ void GNUNET_TESTBED_LOGGER_flush_cancel (struct GNUNET_TESTBED_LOGGER_Handle *h) { if (GNUNET_SCHEDULER_NO_TASK != h->flush_completion_task) { GNUNET_SCHEDULER_cancel (h->flush_completion_task); h->flush_completion_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != h->timeout_flush_task) cancel_timeout_flush (h); h->cb = NULL; h->cb_cls = NULL; } /* End of testbed_logger_api.c */ gnunet-0.10.1/src/testbed/test_testbed_api_controllerlink.c0000644000175000017500000005532612225777502021066 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_controllerlink.c * @brief testcase for testing controller to subcontroller linking * @author Sree Harsha Totakura */ /** * The controller architecture we try to achieve in this test case: * * Master Controller * // \\ * // \\ * Slave Controller 1---------Slave Controller 3 * || * || * Slave Controller 2 */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_testbed_service.h" /** * Generic logging shortcut */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Debug logging shorthand */ #define LOG_DEBUG(...) \ LOG(GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * Different stages in testing */ enum Stage { /** * Initial stage */ INIT, /** * Master controller has started */ MASTER_STARTED, /** * A peer has been created on master */ MASTER_PEER_CREATE_SUCCESS, /** * Peer on master controller has been started successfully. */ MASTER_PEER_START_SUCCESS, /** * The first slave has been registered at master controller */ SLAVE1_REGISTERED, /** * The second slave has been registered at the master controller */ SLAVE2_REGISTERED, /** * Link from master to slave 1 has been successfully created */ SLAVE1_LINK_SUCCESS, /** * Peer create on slave 1 successful */ SLAVE1_PEER_CREATE_SUCCESS, /** * Peer startup on slave 1 successful */ SLAVE1_PEER_START_SUCCESS, /** * Link from slave 1 to slave 2 has been successfully created. */ SLAVE2_LINK_SUCCESS, /** * Peer create on slave 2 successful */ SLAVE2_PEER_CREATE_SUCCESS, /** * Peer on slave 1 successfully stopped */ SLAVE1_PEER_STOP_SUCCESS, /** * Peer startup on slave 2 successful */ SLAVE2_PEER_START_SUCCESS, /** * Try to connect peers on master and slave 2. */ MASTER_SLAVE2_PEERS_CONNECTED, /** * Slave 3 has successfully registered */ SLAVE3_REGISTERED, /** * Slave 3 has successfully started */ SLAVE3_STARTED, /** * Peer created on slave 3 */ SLAVE3_PEER_CREATE_SUCCESS, /** * Peer started at slave 3 */ SLAVE3_PEER_START_SUCCESS, /** * Try to connect peers on slave2 and slave3 */ SLAVE2_SLAVE3_PEERS_CONNECTED, /** * Peer on slave 2 successfully stopped */ SLAVE2_PEER_STOP_SUCCESS, /** * Peer destroy on slave 1 successful */ SLAVE1_PEER_DESTROY_SUCCESS, /** * Peer destory on slave 2 successful */ SLAVE2_PEER_DESTROY_SUCCESS, /** * The configuration of slave 3 is acquired */ SLAVE3_GET_CONFIG_SUCCESS, /** * Slave 1 has linked to slave 3; */ SLAVE3_LINK_SUCCESS, /** * Master peer destoryed. Destory slave 3 peer */ MASTER_PEER_DESTROY_SUCCESS, /** * Slave 3 peer destroyed. Mark test as success */ SUCCESS, /** * Marks test as skipped */ SKIP }; /** * Host for running master controller */ static struct GNUNET_TESTBED_Host *host; /** * The master controller process */ static struct GNUNET_TESTBED_ControllerProc *cp; /** * Handle to master controller */ static struct GNUNET_TESTBED_Controller *mc; /** * Slave host for running slave controller */ static struct GNUNET_TESTBED_Host *slave; /** * Another slave host for running another slave controller */ static struct GNUNET_TESTBED_Host *slave2; /** * Host for slave 3 */ static struct GNUNET_TESTBED_Host *slave3; /** * Slave host registration handle */ static struct GNUNET_TESTBED_HostRegistrationHandle *rh; /** * Handle to global configuration */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Configuration of slave 3 controller */ static struct GNUNET_CONFIGURATION_Handle *cfg3; /** * Abort task */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * Operation handle for linking controllers */ static struct GNUNET_TESTBED_Operation *op; /** * Handle to peer started at slave 1 */ static struct GNUNET_TESTBED_Peer *slave1_peer; /** * Handle to peer started at slave 2 */ static struct GNUNET_TESTBED_Peer *slave2_peer; /** * Handle to peer started at slave 2 */ static struct GNUNET_TESTBED_Peer *slave3_peer; /** * Handle to a peer started at master controller */ static struct GNUNET_TESTBED_Peer *master_peer; /** * The handle for whether a host is habitable or not */ struct GNUNET_TESTBED_HostHabitableCheckHandle *hc_handle; /** * The task handle for the delay task */ GNUNET_SCHEDULER_TaskIdentifier delay_task_id; /** * Event mask */ uint64_t event_mask; /** * Global testing status */ static enum Stage result; /** * shortcut to exit during failure */ #define FAIL_TEST(cond) do { \ if (!(cond)) { \ GNUNET_break(0); \ if (GNUNET_SCHEDULER_NO_TASK != abort_task) \ GNUNET_SCHEDULER_cancel (abort_task); \ abort_task = GNUNET_SCHEDULER_NO_TASK; \ GNUNET_SCHEDULER_add_now (do_shutdown, NULL); \ return; \ } \ } while (0) /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); if (GNUNET_SCHEDULER_NO_TASK != delay_task_id) { GNUNET_SCHEDULER_cancel (delay_task_id); delay_task_id = GNUNET_SCHEDULER_NO_TASK; } if (NULL != hc_handle) GNUNET_TESTBED_is_host_habitable_cancel (hc_handle); if (NULL != mc) GNUNET_TESTBED_controller_disconnect (mc); if (NULL != cp) GNUNET_TESTBED_controller_stop (cp); if (NULL != slave3) GNUNET_TESTBED_host_destroy (slave3); if (NULL != slave2) GNUNET_TESTBED_host_destroy (slave2); if (NULL != slave) GNUNET_TESTBED_host_destroy (slave); if (NULL != host) GNUNET_TESTBED_host_destroy (host); if (NULL != cfg) GNUNET_CONFIGURATION_destroy (cfg); if (NULL != cfg3) GNUNET_CONFIGURATION_destroy (cfg3); if (NULL != rh) GNUNET_TESTBED_cancel_registration (rh); } /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_WARNING, "Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; do_shutdown (cls, tc); } /** * Calls abort now * * @param * @return */ static void do_abort_now (void *cls) { if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); } /** * Callback which will be called to after a host registration succeeded or failed * * @param cls the host which has been registered * @param emsg the error message; NULL if host registration is successful */ static void registration_cont (void *cls, const char *emsg); /** * Task for inserting delay between tests * * @param * @return */ static void delay_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { delay_task_id = GNUNET_SCHEDULER_NO_TASK; switch (result) { case SLAVE2_PEER_CREATE_SUCCESS: op = GNUNET_TESTBED_peer_stop (NULL, slave1_peer, NULL, NULL); FAIL_TEST (NULL != op); break; case MASTER_SLAVE2_PEERS_CONNECTED: slave3 = GNUNET_TESTBED_host_create_with_id (3, "127.0.0.1", NULL, cfg, 0); rh = GNUNET_TESTBED_register_host (mc, slave3, ®istration_cont, NULL); break; case SLAVE2_SLAVE3_PEERS_CONNECTED: op = GNUNET_TESTBED_peer_stop (NULL, slave2_peer, NULL, NULL); FAIL_TEST (NULL != op); break; default: FAIL_TEST (0); } } /** * Functions of this signature are called when a peer has been successfully * created * * @param cls the closure from GNUNET_TESTBED_peer_create() * @param peer the handle for the created peer; NULL on any error during * creation * @param emsg NULL if peer is not NULL; else MAY contain the error description */ static void peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) { FAIL_TEST (NULL != peer); FAIL_TEST (NULL == emsg); switch (result) { case MASTER_STARTED: result = MASTER_PEER_CREATE_SUCCESS; master_peer = peer; GNUNET_TESTBED_operation_done (op); op = GNUNET_TESTBED_peer_start (NULL, master_peer, NULL, NULL); break; case SLAVE1_LINK_SUCCESS: result = SLAVE1_PEER_CREATE_SUCCESS; slave1_peer = peer; GNUNET_TESTBED_operation_done (op); op = GNUNET_TESTBED_peer_start (NULL, slave1_peer, NULL, NULL); break; case SLAVE2_LINK_SUCCESS: result = SLAVE2_PEER_CREATE_SUCCESS; slave2_peer = peer; GNUNET_TESTBED_operation_done (op); delay_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), &delay_task, NULL); break; case SLAVE3_STARTED: result = SLAVE3_PEER_CREATE_SUCCESS; slave3_peer = peer; GNUNET_TESTBED_operation_done (op); op = GNUNET_TESTBED_peer_start (NULL, slave3_peer, NULL, NULL); break; default: FAIL_TEST (0); } FAIL_TEST (NULL != op); } /** * Checks the event if it is an operation finished event and if indicates a * successfull completion of operation * * @param event the event information to check */ static void check_operation_success (const struct GNUNET_TESTBED_EventInformation *event) { FAIL_TEST (NULL != event); FAIL_TEST (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); FAIL_TEST (event->op == op); FAIL_TEST (NULL == event->op_cls); FAIL_TEST (NULL == event->details.operation_finished.emsg); FAIL_TEST (NULL == event->details.operation_finished.generic); } /** * Signature of the event handler function called by the * respective event controller. * * @param cls closure * @param event information about the event */ static void controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (result) { case SLAVE2_REGISTERED: check_operation_success (event); GNUNET_TESTBED_operation_done (op); op = NULL; result = SLAVE1_LINK_SUCCESS; FAIL_TEST (NULL != slave2); FAIL_TEST (NULL != slave); op = GNUNET_TESTBED_peer_create (mc, slave, cfg, peer_create_cb, NULL); FAIL_TEST (NULL != op); break; case SLAVE1_PEER_START_SUCCESS: check_operation_success (event); GNUNET_TESTBED_operation_done (op); result = SLAVE2_LINK_SUCCESS; op = GNUNET_TESTBED_peer_create (mc, slave2, cfg, peer_create_cb, NULL); FAIL_TEST (NULL != op); break; case MASTER_PEER_CREATE_SUCCESS: FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); FAIL_TEST (event->details.peer_start.host == host); FAIL_TEST (event->details.peer_start.peer == master_peer); GNUNET_TESTBED_operation_done (op); result = MASTER_PEER_START_SUCCESS; slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, cfg, 0); FAIL_TEST (NULL != slave); rh = GNUNET_TESTBED_register_host (mc, slave, ®istration_cont, NULL); FAIL_TEST (NULL != rh); break; case SLAVE1_PEER_CREATE_SUCCESS: FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); FAIL_TEST (event->details.peer_start.host == slave); FAIL_TEST (event->details.peer_start.peer == slave1_peer); GNUNET_TESTBED_operation_done (op); result = SLAVE1_PEER_START_SUCCESS; op = GNUNET_TESTBED_controller_link (NULL, mc, slave2, slave, GNUNET_YES); break; case SLAVE2_PEER_CREATE_SUCCESS: FAIL_TEST (GNUNET_TESTBED_ET_PEER_STOP == event->type); FAIL_TEST (event->details.peer_stop.peer == slave1_peer); GNUNET_TESTBED_operation_done (op); result = SLAVE1_PEER_STOP_SUCCESS; op = GNUNET_TESTBED_peer_start (NULL, slave2_peer, NULL, NULL); FAIL_TEST (NULL != op); break; case SLAVE3_PEER_CREATE_SUCCESS: FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); FAIL_TEST (event->details.peer_start.host == slave3); FAIL_TEST (event->details.peer_start.peer == slave3_peer); GNUNET_TESTBED_operation_done (op); result = SLAVE3_PEER_START_SUCCESS; sleep (1); LOG_DEBUG ("**************************************\n"); op = GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, slave2_peer, slave3_peer); FAIL_TEST (NULL != op); break; case SLAVE3_PEER_START_SUCCESS: FAIL_TEST (NULL != event); FAIL_TEST (GNUNET_TESTBED_ET_CONNECT == event->type); FAIL_TEST (event->details.peer_connect.peer1 == slave2_peer); FAIL_TEST (event->details.peer_connect.peer2 == slave3_peer); result = SLAVE2_SLAVE3_PEERS_CONNECTED; GNUNET_TESTBED_operation_done (op); op = NULL; delay_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), &delay_task, NULL); break; case SLAVE1_PEER_STOP_SUCCESS: FAIL_TEST (GNUNET_TESTBED_ET_PEER_START == event->type); FAIL_TEST (event->details.peer_start.host == slave2); FAIL_TEST (event->details.peer_start.peer == slave2_peer); GNUNET_TESTBED_operation_done (op); result = SLAVE2_PEER_START_SUCCESS; op = GNUNET_TESTBED_overlay_connect (mc, NULL, NULL, master_peer, slave2_peer); break; case SLAVE2_PEER_START_SUCCESS: FAIL_TEST (NULL != event); FAIL_TEST (GNUNET_TESTBED_ET_CONNECT == event->type); FAIL_TEST (event->details.peer_connect.peer1 == master_peer); FAIL_TEST (event->details.peer_connect.peer2 == slave2_peer); result = MASTER_SLAVE2_PEERS_CONNECTED; GNUNET_TESTBED_operation_done (op); op = NULL; delay_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), &delay_task, NULL); break; case SLAVE2_SLAVE3_PEERS_CONNECTED: FAIL_TEST (GNUNET_TESTBED_ET_PEER_STOP == event->type); FAIL_TEST (event->details.peer_stop.peer == slave2_peer); GNUNET_TESTBED_operation_done (op); result = SLAVE2_PEER_STOP_SUCCESS; op = GNUNET_TESTBED_peer_destroy (slave1_peer); FAIL_TEST (NULL != op); break; case SLAVE2_PEER_STOP_SUCCESS: check_operation_success (event); GNUNET_TESTBED_operation_done (op); result = SLAVE1_PEER_DESTROY_SUCCESS; op = GNUNET_TESTBED_peer_destroy (slave2_peer); FAIL_TEST (NULL != op); break; case SLAVE1_PEER_DESTROY_SUCCESS: check_operation_success (event); GNUNET_TESTBED_operation_done (op); op = NULL; result = SLAVE2_PEER_DESTROY_SUCCESS; op = GNUNET_TESTBED_get_slave_config (NULL, mc, slave3); FAIL_TEST (NULL != op); break; case SLAVE2_PEER_DESTROY_SUCCESS: FAIL_TEST (NULL != event); FAIL_TEST (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); FAIL_TEST (event->op == op); FAIL_TEST (NULL == event->op_cls); FAIL_TEST (NULL == event->details.operation_finished.emsg); cfg3 = GNUNET_CONFIGURATION_dup (event->details.operation_finished.generic); GNUNET_TESTBED_operation_done (op); result = SLAVE3_GET_CONFIG_SUCCESS; op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, slave, GNUNET_NO); break; case SLAVE3_REGISTERED: check_operation_success (event); GNUNET_TESTBED_operation_done (op); op = NULL; result = SLAVE3_STARTED; op = GNUNET_TESTBED_peer_create (mc, slave3, cfg, peer_create_cb, NULL); FAIL_TEST (NULL != op); break; case SLAVE3_GET_CONFIG_SUCCESS: result = SLAVE3_LINK_SUCCESS; GNUNET_TESTBED_operation_done (op); op = GNUNET_TESTBED_peer_destroy (master_peer); break; case SLAVE3_LINK_SUCCESS: check_operation_success (event); result = MASTER_PEER_DESTROY_SUCCESS; GNUNET_TESTBED_operation_done (op); op = GNUNET_TESTBED_peer_destroy (slave3_peer); break; case MASTER_PEER_DESTROY_SUCCESS: result = SUCCESS; GNUNET_TESTBED_operation_done (op); op = NULL; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), &do_shutdown, NULL); break; default: FAIL_TEST (0); } } /** * Callback which will be called to after a host registration succeeded or failed * * @param cls the host which has been registered * @param emsg the error message; NULL if host registration is successful */ static void registration_cont (void *cls, const char *emsg) { rh = NULL; switch (result) { case MASTER_PEER_START_SUCCESS: FAIL_TEST (NULL == emsg); FAIL_TEST (NULL != mc); result = SLAVE1_REGISTERED; slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, cfg, 0); FAIL_TEST (NULL != slave2); rh = GNUNET_TESTBED_register_host (mc, slave2, ®istration_cont, NULL); FAIL_TEST (NULL != rh); break; case SLAVE1_REGISTERED: FAIL_TEST (NULL == emsg); FAIL_TEST (NULL != mc); result = SLAVE2_REGISTERED; FAIL_TEST (NULL != cfg); op = GNUNET_TESTBED_controller_link (NULL, mc, slave, NULL, GNUNET_YES); FAIL_TEST (NULL != op); break; case MASTER_SLAVE2_PEERS_CONNECTED: FAIL_TEST (NULL == emsg); FAIL_TEST (NULL != mc); FAIL_TEST (NULL == op); result = SLAVE3_REGISTERED; op = GNUNET_TESTBED_controller_link (NULL, mc, slave3, NULL, GNUNET_YES); FAIL_TEST (NULL != op); break; default: GNUNET_break (0); do_abort_now (NULL); } } /** * Callback to signal successfull startup of the controller process * * @param cls the closure from GNUNET_TESTBED_controller_start() * @param cfg the configuration with which the controller has been started; * NULL if status is not GNUNET_OK * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ static void status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, int status) { switch (result) { case INIT: FAIL_TEST (GNUNET_OK == status); event_mask = 0; event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); mc = GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb, NULL); FAIL_TEST (NULL != mc); result = MASTER_STARTED; op = GNUNET_TESTBED_peer_create (mc, host, cfg, peer_create_cb, NULL); FAIL_TEST (NULL != op); break; default: GNUNET_break (0); cp = NULL; do_abort_now (NULL); } } /** * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to * inform whether the given host is habitable or not. The Handle returned by * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called * * @param cls NULL * @param host the host whose status is being reported; will be NULL if the host * given to GNUNET_TESTBED_is_host_habitable() is NULL * @param status GNUNET_YES if it is habitable; GNUNET_NO if not */ static void host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *_host, int status) { hc_handle = NULL; if (GNUNET_NO == status) { (void) PRINTF ("%s", "Unable to run the test as this system is not configured " "to use password less SSH logins to localhost.\n" "Skipping test\n"); GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_NO_TASK; (void) GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); result = SKIP; return; } cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL); } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { cfg = GNUNET_CONFIGURATION_dup (config); host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); FAIL_TEST (NULL != host); if (NULL == (hc_handle = GNUNET_TESTBED_is_host_habitable (host, config, &host_habitable_cb, NULL))) { GNUNET_TESTBED_host_destroy (host); GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; host = NULL; (void) PRINTF ("%s", "Unable to run the test as this system is not configured " "to use password less SSH logins to localhost.\n" "Marking test as successful\n"); result = SKIP; return; } abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { char *const argv2[] = { "test_testbed_api_controllerlink", "-c", "test_testbed_api.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; result = INIT; ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testbed_api_controllerlink", "nohelp", options, &run, NULL); if (GNUNET_OK != ret) return 1; switch (result) { case SUCCESS: return 0; case SKIP: return 77; /* Mark test as skipped */ default: return 1; } } /* end of test_testbed_api_controllerlink.c */ gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run.c0000644000175000017500000001455512225777502020342 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_testbed_run.c * @brief Test cases for testing high-level testbed management * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we want to start */ #define NUM_PEERS 5 /** * The array of peers; we fill this as the peers are given to us by the testbed */ static struct GNUNET_TESTBED_Peer *peers[NUM_PEERS]; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * Current peer id */ static unsigned int peer_id; /** * Testing result */ static int result; /** * Should we wait forever after testbed is initialized? */ static int wait_forever; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */ } /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; (void) GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { result = GNUNET_OK; if (GNUNET_YES == wait_forever) { if (GNUNET_SCHEDULER_NO_TASK == abort_task) return; /* abort already scheduled */ GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_NO_TASK; (void) GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); return; } GNUNET_assert (NULL != peers[0]); op = GNUNET_TESTBED_peer_stop (NULL, peers[0], NULL, NULL); GNUNET_assert (NULL != op); } /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_PEER_START: GNUNET_assert (NULL == peers[peer_id]); GNUNET_assert (NULL != event->details.peer_start.peer); peers[peer_id++] = event->details.peer_start.peer; break; case GNUNET_TESTBED_ET_PEER_STOP: GNUNET_assert (NULL != op); GNUNET_TESTBED_operation_done (op); GNUNET_assert (peers[0] == event->details.peer_stop.peer); GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); break; default: GNUNET_assert (0); } } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { uint64_t event_mask; event_mask = 0; event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP); GNUNET_TESTBED_run (NULL, config, NUM_PEERS, event_mask, &controller_event_cb, NULL, &test_master, NULL); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { char *argv2[] = { "test_testbed_api_testbed_run", "-c", NULL, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; char *testname; char *config_filename; int ret; if (NULL == (testname = strrchr (argv[0], (int) '_'))) { GNUNET_break (0); return 1; } testname++; testname = GNUNET_strdup (testname); #ifdef MINGW { char *period; /* check and remove .exe extension */ period = strrchr (testname, (int) '.'); if (NULL != period) *period = '\0'; else GNUNET_break (0); /* Windows with no .exe? */ } #endif if (0 == strcmp ("waitforever", testname)) wait_forever = GNUNET_YES; if ( (GNUNET_YES != wait_forever) && (0 != strcmp ("run", testname)) ) { GNUNET_asprintf (&config_filename, "test_testbed_api_testbed_run_%s.conf", testname); } else config_filename = GNUNET_strdup ("test_testbed_api.conf"); GNUNET_free (testname); argv2[2] = config_filename; result = GNUNET_SYSERR; ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testbed_api_testbed_run", "nohelp", options, &run, NULL); GNUNET_free (config_filename); if ((GNUNET_OK != ret) || (GNUNET_OK != result)) return 1; return 0; } /* end of test_testbed_api_testbed_run.c */ gnunet-0.10.1/src/testbed/test_testbed_api_statistics.conf0000644000175000017500000000023412233724131020673 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = 2D_TORUS MAX_PARALLEL_SERVICE_CONNECTIONS = 2 [statistics] AUTOSTART = YES PORT = 30 gnunet-0.10.1/src/testbed/test_testbed_api_operations.c0000644000175000017500000003461712225777502020210 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_operations.c * @brief tests cases for testbed_api_operations.c * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "testbed_api_operations.h" /** * Generic logging shortcut */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Delay to start step task */ #define STEP_DELAY \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) /** * Queue A. Initially the max active is set to 2 and then reduced to 0 - this * should block op2 even after op1 has finished. Later the max active is set to * 2 and this should start op2 */ struct OperationQueue *q1; /** * Queue B. Max active set to 2 is not changed throughout the test */ struct OperationQueue *q2; /** * This operation should go into both queues and block op2 until it is done */ struct GNUNET_TESTBED_Operation *op1; /** * This operation should go into q1 and q2 */ struct GNUNET_TESTBED_Operation *op2; /** * This operation should go into both queues and should consume 2 units of * resources on both queues. Since op2 needs a resource from both queues and is * queues before this operation, it will be blocked until op2 is released even * though q1 has enough free resources */ struct GNUNET_TESTBED_Operation *op3; /** * Just like op3, this operation also consumes 2 units of resources on both * queues. Since this is queued after op3 and both queues are at max active * 2. This will be blocked until op3 is done. */ struct GNUNET_TESTBED_Operation *op4; /** * This operation is started after op4 is released and should consume only 1 * resource on queue q1. It should be started along with op6 and op7 */ struct GNUNET_TESTBED_Operation *op5; /** * This operation is started after op4 is released and should consume only 1 * resource on q2. It should be started along with op5 and op7 */ struct GNUNET_TESTBED_Operation *op6; /** * This operation is started after op4 is released and should consume 1 resource * on both queues q1 and q1. It should be started along with op5 and op6. It is * then inactivated when op6 is released. op8's start should release this * operation implicitly. */ struct GNUNET_TESTBED_Operation *op7; /** * This operation is started after op6 is finished in step task. It consumes 2 * resources on both queues q1 and q2. This operation should evict op7. After * starting, it should be made inactive, active and inactive again in the step task. */ struct GNUNET_TESTBED_Operation *op8; /** * This opration is started after activating op8. It should consume a resource * on queues q1 and q2. It should not be started until op8 is again made * inactive at which point it should be released. It can be released as soon as * it begins. */ struct GNUNET_TESTBED_Operation *op9; /** * The delay task identifier */ GNUNET_SCHEDULER_TaskIdentifier step_task; /** * Enumeration of test stages */ enum Test { /** * Initial stage */ TEST_INIT, /** * op1 has been started */ TEST_OP1_STARTED, /** * op1 has been released */ TEST_OP1_RELEASED, /** * Temporary pause where no operations should start as we set max active in q1 * to 0 in stage TEST_OP1_STARTED */ TEST_PAUSE, /** * op2 has started */ TEST_OP2_STARTED, /** * op2 released */ TEST_OP2_RELEASED, /** * op3 has started */ TEST_OP3_STARTED, /** * op3 has finished */ TEST_OP3_RELEASED, /** * op4 has started */ TEST_OP4_STARTED, /** * op4 has released */ TEST_OP4_RELEASED, /** * op5, op6, op7 started */ TEST_OP5_6_7_STARTED, /** * op5 has released */ TEST_OP5_RELEASED, /** * op6 has released */ TEST_OP6_RELEASED, /** * op8 has began waiting */ TEST_OP8_WAITING, /** * op7 has released */ TEST_OP7_RELEASED, /** * op8 has started */ TEST_OP8_STARTED, /** * op8 is inactive */ TEST_OP8_INACTIVE_1, /** * op8 is active */ TEST_OP8_ACTIVE, /** * op8 has been released */ TEST_OP8_RELEASED, /** * op9 has started */ TEST_OP9_STARTED, /** * op9 has been released */ TEST_OP9_RELEASED }; /** * The test result */ enum Test result; /** * Function to call to start an operation once all * queues the operation is part of declare that the * operation can be activated. */ static void start_cb (void *cls); /** * Function to cancel an operation (release all associated resources). This can * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the * operation generated an event) or AFTER the operation generated an event due * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that * a callback to the 'OperationStart' preceeds the call to 'OperationRelease'. * Implementations of this function are expected to clean up whatever state is * in 'cls' and release all resources associated with the operation. */ static void release_cb (void *cls); /** * Task to simulate artificial delay and change the test stage * * @param cls NULL * @param tc the task context */ static void step (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != step_task); step_task = GNUNET_SCHEDULER_NO_TASK; switch (result) { case TEST_OP1_STARTED: GNUNET_TESTBED_operation_release_ (op1); GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 0); op3 = GNUNET_TESTBED_operation_create_ (&op3, &start_cb, &release_cb); GNUNET_TESTBED_operation_queue_insert2_ (q1, op3, 2); GNUNET_TESTBED_operation_queue_insert2_ (q2, op3, 2); GNUNET_TESTBED_operation_begin_wait_ (op3); op4 = GNUNET_TESTBED_operation_create_ (&op4, &start_cb, &release_cb); GNUNET_TESTBED_operation_queue_insert2_ (q1, op4, 2); GNUNET_TESTBED_operation_queue_insert2_ (q2, op4, 2); GNUNET_TESTBED_operation_begin_wait_ (op4); break; case TEST_OP1_RELEASED: result = TEST_PAUSE; GNUNET_TESTBED_operation_queue_reset_max_active_ (q1, 2); break; case TEST_OP2_STARTED: GNUNET_TESTBED_operation_release_ (op2); break; case TEST_OP3_STARTED: GNUNET_TESTBED_operation_release_ (op3); break; case TEST_OP4_STARTED: GNUNET_TESTBED_operation_release_ (op4); break; case TEST_OP6_RELEASED: op8 = GNUNET_TESTBED_operation_create_ (&op8, &start_cb, &release_cb); GNUNET_TESTBED_operation_queue_insert2_ (q1, op8, 2); GNUNET_TESTBED_operation_queue_insert2_ (q2, op8, 2); result = TEST_OP8_WAITING; GNUNET_TESTBED_operation_begin_wait_ (op8); break; case TEST_OP8_STARTED: GNUNET_TESTBED_operation_inactivate_ (op8); result = TEST_OP8_INACTIVE_1; step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; case TEST_OP8_INACTIVE_1: GNUNET_TESTBED_operation_activate_ (op8); result = TEST_OP8_ACTIVE; op9 = GNUNET_TESTBED_operation_create_ (&op9, &start_cb, &release_cb); GNUNET_TESTBED_operation_queue_insert2_ (q1, op9, 1); GNUNET_TESTBED_operation_queue_insert2_ (q2, op9, 1); GNUNET_TESTBED_operation_begin_wait_ (op9); step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; case TEST_OP8_ACTIVE: GNUNET_TESTBED_operation_inactivate_ (op8); /* op8 should be released by now due to above call */ GNUNET_assert (TEST_OP8_RELEASED == result); break; case TEST_OP9_STARTED: GNUNET_TESTBED_operation_release_ (op9); break; default: GNUNET_assert (0); } } /** * Function to call to start an operation once all * queues the operation is part of declare that the * operation can be activated. */ static void start_cb (void *cls) { switch (result) { case TEST_INIT: GNUNET_assert (&op1 == cls); result = TEST_OP1_STARTED; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task); step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; case TEST_PAUSE: GNUNET_assert (&op2 == cls); result = TEST_OP2_STARTED; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task); step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; case TEST_OP2_RELEASED: GNUNET_assert (&op3 == cls); result = TEST_OP3_STARTED; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task); step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; case TEST_OP3_RELEASED: GNUNET_assert (&op4 == cls); result = TEST_OP4_STARTED; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task); step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; case TEST_OP4_RELEASED: { static int nops; nops++; if (nops == 3) { result = TEST_OP5_6_7_STARTED; GNUNET_TESTBED_operation_release_ (op5); op5 = NULL; } } break; case TEST_OP7_RELEASED: GNUNET_assert (&op8 == cls); result = TEST_OP8_STARTED; step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; case TEST_OP8_RELEASED: GNUNET_assert (&op9 == cls); result = TEST_OP9_STARTED; step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; default: GNUNET_assert (0); } } /** * Function to cancel an operation (release all associated resources). This can * be because of a call to "GNUNET_TESTBED_operation_cancel" (before the * operation generated an event) or AFTER the operation generated an event due * to a call to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that * a callback to the 'OperationStart' preceeds the call to 'OperationRelease'. * Implementations of this function are expected to clean up whatever state is * in 'cls' and release all resources associated with the operation. */ static void release_cb (void *cls) { switch (result) { case TEST_OP1_STARTED: GNUNET_assert (&op1 == cls); result = TEST_OP1_RELEASED; op1 = NULL; step_task = GNUNET_SCHEDULER_add_delayed (STEP_DELAY, &step, NULL); break; case TEST_OP2_STARTED: GNUNET_assert (&op2 == cls); result = TEST_OP2_RELEASED; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task); break; case TEST_OP3_STARTED: GNUNET_assert (&op3 == cls); result = TEST_OP3_RELEASED; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task); break; case TEST_OP4_STARTED: GNUNET_assert (&op4 == cls); result = TEST_OP4_RELEASED; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == step_task); op5 = GNUNET_TESTBED_operation_create_ (&op5, &start_cb, &release_cb); GNUNET_TESTBED_operation_queue_insert2_ (q1, op5, 1); GNUNET_TESTBED_operation_begin_wait_ (op5); op6 = GNUNET_TESTBED_operation_create_ (&op6, &start_cb, &release_cb); GNUNET_TESTBED_operation_queue_insert2_ (q2, op6, 1); GNUNET_TESTBED_operation_begin_wait_ (op6); op7 = GNUNET_TESTBED_operation_create_ (&op7, &start_cb, &release_cb); GNUNET_TESTBED_operation_queue_insert2_ (q1, op7, 1); GNUNET_TESTBED_operation_queue_insert2_ (q2, op7, 1); GNUNET_TESTBED_operation_begin_wait_ (op7); break; case TEST_OP5_6_7_STARTED: result = TEST_OP5_RELEASED; op5 = NULL; GNUNET_TESTBED_operation_release_ (op6); break; case TEST_OP5_RELEASED: op6 = NULL; result = TEST_OP6_RELEASED; GNUNET_TESTBED_operation_inactivate_ (op7); step_task = GNUNET_SCHEDULER_add_now (&step, NULL); break; case TEST_OP8_WAITING: GNUNET_assert (&op7 == cls); op7 = NULL; result = TEST_OP7_RELEASED; break; case TEST_OP8_ACTIVE: result = TEST_OP8_RELEASED; op8 = NULL; break; case TEST_OP9_STARTED: GNUNET_assert (&op9 == cls); result = TEST_OP9_RELEASED; GNUNET_TESTBED_operation_queue_destroy_ (q1); GNUNET_TESTBED_operation_queue_destroy_ (q2); q1 = NULL; q2 = NULL; break; default: GNUNET_assert (0); } } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { q1 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 1); GNUNET_assert (NULL != q1); q2 = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, 2); GNUNET_assert (NULL != q2); op1 = GNUNET_TESTBED_operation_create_ (&op1, start_cb, release_cb); GNUNET_assert (NULL != op1); op2 = GNUNET_TESTBED_operation_create_ (&op2, start_cb, release_cb); GNUNET_TESTBED_operation_queue_insert_ (q1, op1); GNUNET_TESTBED_operation_queue_insert_ (q2, op1); GNUNET_TESTBED_operation_begin_wait_ (op1); GNUNET_TESTBED_operation_queue_insert_ (q1, op2); GNUNET_TESTBED_operation_queue_insert_ (q2, op2); GNUNET_TESTBED_operation_begin_wait_ (op2); result = TEST_INIT; } /** * Main function */ int main (int argc, char **argv) { int ret; char *const argv2[] = { "test_testbed_api_operations", "-c", "test_testbed_api.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testbed_api_operations", "nohelp", options, &run, NULL); if ((GNUNET_OK != ret) || (TEST_OP9_RELEASED != result)) return 1; op1 = NULL; op2 = NULL; op3 = NULL; op4 = NULL; op5 = NULL; op6 = NULL; op7 = NULL; op8 = NULL; op9 = NULL; q1 = NULL; q2 = NULL; return 0; } /* end of test_testbed_api_operations.c */ gnunet-0.10.1/src/testbed/test-underlay.sqlite0000644000175000017500000000600012263473436016264 00000000000000SQLite format 3@ -â% üùùÉM‚itablewhitelistwhitelistCREATE TABLE whitelist (id INTEGER,oid INTEGER,bandwidth INTEGER DEFAULT NULL,latency INTEGER DEFAULT NULL,loss INTEGER DEFAULT NULL, UNIQUE ( id, oid ) ON CONFLICT IGNORE)1Eindexsqlite_autoindex_whitelist_1whitelist ÞøðçÞ     çûõîç    gnunet-0.10.1/src/testbed/test_testbed_api_test.c0000644000175000017500000001574612225777502017006 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/testbed/test_testbed_api_test.c * @brief testing cases for testing high level testbed api helper functions * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Generic logging shortcut */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Number of peers we want to start */ #define NUM_PEERS 25 /** * Array of peers */ static struct GNUNET_TESTBED_Peer **peers; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * shutdown task identifier */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Testing result */ static int result; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); if (NULL != op) GNUNET_TESTBED_operation_done (op); GNUNET_SCHEDULER_shutdown (); } /** * shortcut to exit during failure */ #define FAIL_TEST(cond) do { \ if (!(cond)) { \ GNUNET_break(0); \ if (GNUNET_SCHEDULER_NO_TASK != abort_task) \ GNUNET_SCHEDULER_cancel (abort_task); \ abort_task = GNUNET_SCHEDULER_NO_TASK; \ if (GNUNET_SCHEDULER_NO_TASK == shutdown_task) \ shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL); \ return; \ } \ } while (0) /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) GNUNET_SCHEDULER_cancel (shutdown_task); do_shutdown (cls, tc); } /** * Callback to be called when the requested peer information is available * * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() * @param op the operation this callback corresponds to * @param pinfo the result; will be NULL if the operation has failed * @param emsg error message if the operation has failed; will be NULL if the * operation is successfull */ static void peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) { FAIL_TEST (op == op_); FAIL_TEST (NULL == cb_cls); FAIL_TEST (NULL == emsg); FAIL_TEST (GNUNET_TESTBED_PIT_IDENTITY == pinfo->pit); FAIL_TEST (NULL != pinfo->result.id); GNUNET_TESTBED_operation_done (op); op = NULL; result = GNUNET_OK; shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } /** * Callback to be called when an operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op_, const char *emsg) { FAIL_TEST (NULL == cls); FAIL_TEST (op == op_); if (NULL != emsg) { LOG (GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg); FAIL_TEST (0); } GNUNET_TESTBED_operation_done (op); op = GNUNET_TESTBED_peer_get_information (peers[0], GNUNET_TESTBED_PIT_IDENTITY, &peerinfo_cb, NULL); } /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_CONNECT: FAIL_TEST (event->details.peer_connect.peer1 == peers[0]); FAIL_TEST (event->details.peer_connect.peer2 == peers[1]); break; default: FAIL_TEST (0); } } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers- handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { unsigned int peer; FAIL_TEST (NULL == cls); FAIL_TEST (NUM_PEERS == num_peers); FAIL_TEST (NULL != peers_); for (peer = 0; peer < num_peers; peer++) FAIL_TEST (NULL != peers_[peer]); peers = peers_; op = GNUNET_TESTBED_overlay_connect (NULL, &op_comp_cb, NULL, peers[0], peers[1]); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { uint64_t event_mask; result = GNUNET_SYSERR; event_mask = 0; event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", "test_testbed_api.conf", NUM_PEERS, event_mask, &controller_event_cb, NULL, &test_master, NULL); if (GNUNET_OK != result) return 1; return 0; } /* end of test_testbed_api_test.c */ gnunet-0.10.1/src/testbed/gnunet-service-testbed-logger.c0000644000175000017500000001473112307312000020234 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed-logger.c * @brief service for collecting messages and writing to a file * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" /** * Generic logging shorthand */ #define LOG(type, ...) \ GNUNET_log (type, __VA_ARGS__) /** * Debug logging shorthand */ #define LOG_DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * The message queue for sending messages to clients */ struct MessageQueue { /** * The message to be sent */ struct GNUNET_MessageHeader *msg; /** * The client to send the message to */ struct GNUNET_SERVER_Client *client; /** * next pointer for DLL */ struct MessageQueue *next; /** * prev pointer for DLL */ struct MessageQueue *prev; }; /** * The message queue head */ static struct MessageQueue *mq_head; /** * The message queue tail */ static struct MessageQueue *mq_tail; /** * Handle for buffered writing. */ struct GNUNET_BIO_WriteHandle *bio; /** * The shutdown task handle */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id; /** * The number of connections we have */ static unsigned int nconn; /** * Are we shutting down? */ static int in_shutdown; /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages * * @param cls NULL * @param client identification of the client * @param msg the actual message */ static void handle_log_msg (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { uint16_t ms; ms = ntohs (msg->size); ms -= sizeof (struct GNUNET_MessageHeader); GNUNET_BIO_write (bio, &msg[1], ms); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Task to clean up and shutdown nicely * * @param cls NULL * @param tc the TaskContext from scheduler */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MessageQueue *mq_entry; shutdown_task_id = GNUNET_SCHEDULER_NO_TASK; in_shutdown = GNUNET_YES; if (0 != nconn) { /* Delay shutdown if there are active connections */ shutdown_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); return; } while (NULL != (mq_entry = mq_head)) { GNUNET_free (mq_entry->msg); GNUNET_SERVER_client_drop (mq_entry->client); GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry); GNUNET_free (mq_entry); } GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bio)); } /** * Functions with this signature are called whenever a client * is disconnected on the network level. * * @param cls closure * @param client identification of the client; NULL * for the last call when the server is destroyed */ static void client_disconnected (void *cls, struct GNUNET_SERVER_Client *client) { if (NULL == client) { GNUNET_break (0 == nconn); return; } nconn--; if (GNUNET_YES != in_shutdown) return; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != shutdown_task_id); GNUNET_SCHEDULER_cancel (shutdown_task_id); shutdown_task_id = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } /** * Functions with this signature are called whenever a client * is connected on the network level. * * @param cls closure * @param client identification of the client */ static void client_connected (void *cls, struct GNUNET_SERVER_Client *client) { if (NULL == client) { GNUNET_break (0 == nconn); return; } GNUNET_SERVER_client_persist_ (client); nconn++; } /** * Testbed setup * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void logger_run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler message_handlers[] = { {&handle_log_msg, NULL, GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG, 0}, {NULL, NULL, 0, 0} }; char *dir; char *fn; char *hname; size_t hname_len; pid_t pid; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED-LOGGER", "DIR", &dir)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Not logging directory definied. Exiting\n"); GNUNET_SCHEDULER_shutdown (); return; } pid = getpid (); hname_len = GNUNET_OS_get_hostname_max_length (); hname = GNUNET_malloc (hname_len); if (0 != gethostname (hname, hname_len)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot get hostname. Exiting\n"); GNUNET_free (hname); GNUNET_free (dir); GNUNET_SCHEDULER_shutdown (); return; } (void) GNUNET_asprintf (&fn, "%s/%.*s_%jd.dat", dir, hname_len, hname, (intmax_t) pid); GNUNET_free (hname); GNUNET_free (dir); if (NULL == (bio = GNUNET_BIO_write_open (fn))) { GNUNET_free (fn); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_free (fn); GNUNET_SERVER_add_handlers (server, message_handlers); GNUNET_SERVER_connect_notify (server, &client_connected, NULL); GNUNET_SERVER_disconnect_notify (server, &client_disconnected, NULL); shutdown_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); LOG_DEBUG ("TESTBED-LOGGER startup complete\n"); } /** * The starting point of execution */ int main (int argc, char *const *argv) { //sleep (15); /* Debugging */ return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "testbed-logger", GNUNET_SERVICE_OPTION_NONE, &logger_run, NULL)) ? 0 : 1; } /* end of gnunet-service-testbed.c */ gnunet-0.10.1/src/testbed/testbed_api.c0000644000175000017500000020443412310570720014666 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api.c * @brief API for accessing the GNUnet testing service. * This library is supposed to make it easier to write * testcases and script large-scale benchmarks. * @author Christian Grothoff * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_testbed_service.h" #include "gnunet_core_service.h" #include "gnunet_constants.h" #include "gnunet_transport_service.h" #include "gnunet_hello_lib.h" #include #include "testbed.h" #include "testbed_api.h" #include "testbed_api_hosts.h" #include "testbed_api_peers.h" #include "testbed_api_operations.h" #include "testbed_api_sd.h" /** * Generic logging shorthand */ #define LOG(kind, ...) \ GNUNET_log_from (kind, "testbed-api", __VA_ARGS__) /** * Debug logging */ #define LOG_DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * Relative time seconds shorthand */ #define TIME_REL_SECS(sec) \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) /** * Default server message sending retry timeout */ #define TIMEOUT_REL TIME_REL_SECS(1) /** * The message queue for sending messages to the controller service */ struct MessageQueue { /** * The message to be sent */ struct GNUNET_MessageHeader *msg; /** * next pointer for DLL */ struct MessageQueue *next; /** * prev pointer for DLL */ struct MessageQueue *prev; }; /** * Context data for forwarded Operation */ struct ForwardedOperationData { /** * The callback to call when reply is available */ GNUNET_CLIENT_MessageHandler cc; /** * The closure for the above callback */ void *cc_cls; }; /** * Context data for get slave config operations */ struct GetSlaveConfigData { /** * The id of the slave controller */ uint32_t slave_id; }; /** * Context data for controller link operations */ struct ControllerLinkData { /** * The controller link message */ struct GNUNET_TESTBED_ControllerLinkRequest *msg; /** * The id of the host which is hosting the controller to be linked */ uint32_t host_id; }; /** * Date context for OP_SHUTDOWN_PEERS operations */ struct ShutdownPeersData { /** * The operation completion callback to call */ GNUNET_TESTBED_OperationCompletionCallback cb; /** * The closure for the above callback */ void *cb_cls; }; /** * An entry in the stack for keeping operations which are about to expire */ struct ExpireOperationEntry { /** * DLL head; new entries are to be inserted here */ struct ExpireOperationEntry *next; /** * DLL tail; entries are deleted from here */ struct ExpireOperationEntry *prev; /** * The operation. This will be a dangling pointer when the operation is freed */ const struct GNUNET_TESTBED_Operation *op; }; /** * DLL head for list of operations marked for expiry */ static struct ExpireOperationEntry *exop_head; /** * DLL tail for list of operation marked for expiry */ static struct ExpireOperationEntry *exop_tail; /** * Inserts an operation into the list of operations marked for expiry * * @param op the operation to insert */ static void exop_insert (struct GNUNET_TESTBED_Operation *op) { struct ExpireOperationEntry *entry; entry = GNUNET_new (struct ExpireOperationEntry); entry->op = op; GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry); } /** * Checks if an operation is present in the list of operations marked for * expiry. If the operation is found, it and the tail of operations after it * are removed from the list. * * @param op the operation to check * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if * the operation is found in the list (the operation is then removed * from the list -- calling this function again with the same * paramenter will return GNUNET_NO) */ static int exop_check (const struct GNUNET_TESTBED_Operation *const op) { struct ExpireOperationEntry *entry; struct ExpireOperationEntry *entry2; int found; found = GNUNET_NO; entry = exop_head; while (NULL != entry) { if (op == entry->op) { found = GNUNET_YES; break; } entry = entry->next; } if (GNUNET_NO == found) return GNUNET_NO; /* Truncate the tail */ while (NULL != entry) { entry2 = entry->next; GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry); GNUNET_free (entry); entry = entry2; } return GNUNET_YES; } /** * Context information to be used while searching for operation contexts */ struct SearchContext { /** * The result of the search */ struct OperationContext *opc; /** * The id of the operation context we are searching for */ uint64_t id; }; /** * Search iterator for searching an operation context * * @param cls the serach context * @param key current key code * @param value value in the hash map * @return GNUNET_YES if we should continue to * iterate, * GNUNET_NO if not. */ static int opc_search_iterator (void *cls, uint32_t key, void *value) { struct SearchContext *sc = cls; struct OperationContext *opc = value; GNUNET_assert (NULL != opc); GNUNET_assert (NULL == sc->opc); if (opc->id != sc->id) return GNUNET_YES; sc->opc = opc; return GNUNET_NO; } /** * Returns the operation context with the given id if found in the Operation * context queues of the controller * * @param c the controller whose operation context map is searched * @param id the id which has to be checked * @return the matching operation context; NULL if no match found */ static struct OperationContext * find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id) { struct SearchContext sc; sc.id = id; sc.opc = NULL; GNUNET_assert (NULL != c->opc_map); if (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, (uint32_t) id, &opc_search_iterator, &sc)) return NULL; return sc.opc; } /** * Inserts the given operation context into the operation context map of the * given controller. Creates the operation context map if one does not exist * for the controller * * @param c the controller * @param opc the operation context to be inserted */ void GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c, struct OperationContext *opc) { if (NULL == c->opc_map) c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (c->opc_map, (uint32_t) opc->id, opc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); } /** * Removes the given operation context from the operation context map of the * given controller * * @param c the controller * @param opc the operation context to remove */ void GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c, struct OperationContext *opc) { GNUNET_assert (NULL != c->opc_map); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_remove (c->opc_map, (uint32_t) opc->id, opc)); if ( (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map)) && (NULL != c->opcq_empty_cb) ) c->opcq_empty_cb (c->opcq_empty_cls); } /** * Handler for forwarded operations * * @param c the controller handle * @param opc the opearation context * @param msg the message */ static void handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c, struct OperationContext *opc, const struct GNUNET_MessageHeader *msg) { struct ForwardedOperationData *fo_data; fo_data = opc->data; if (NULL != fo_data->cc) fo_data->cc (fo_data->cc_cls, msg); GNUNET_TESTBED_remove_opc_ (c, opc); GNUNET_free (fo_data); GNUNET_free (opc); } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from * controller (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ static int handle_opsuccess (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg) { struct OperationContext *opc; GNUNET_TESTBED_OperationCompletionCallback op_comp_cb; void *op_comp_cb_cls; struct GNUNET_TESTBED_EventInformation event; uint64_t op_id; op_id = GNUNET_ntohll (msg->operation_id); LOG_DEBUG ("Operation %lu successful\n", op_id); if (NULL == (opc = find_opc (c, op_id))) { LOG_DEBUG ("Operation not found\n"); return GNUNET_YES; } event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; event.op = opc->op; event.op_cls = opc->op_cls; event.details.operation_finished.emsg = NULL; event.details.operation_finished.generic = NULL; op_comp_cb = NULL; op_comp_cb_cls = NULL; switch (opc->type) { case OP_FORWARDED: { handle_forwarded_operation_msg (c, opc, (const struct GNUNET_MessageHeader *) msg); return GNUNET_YES; } break; case OP_PEER_DESTROY: { struct GNUNET_TESTBED_Peer *peer; peer = opc->data; GNUNET_TESTBED_peer_deregister_ (peer); GNUNET_free (peer); opc->data = NULL; //PEERDESTROYDATA } break; case OP_SHUTDOWN_PEERS: { struct ShutdownPeersData *data; data = opc->data; op_comp_cb = data->cb; op_comp_cb_cls = data->cb_cls; GNUNET_free (data); opc->data = NULL; GNUNET_TESTBED_cleanup_peers_ (); } break; case OP_MANAGE_SERVICE: { struct ManageServiceData *data; GNUNET_assert (NULL != (data = opc->data)); op_comp_cb = data->cb; op_comp_cb_cls = data->cb_cls; GNUNET_free (data); opc->data = NULL; } break; case OP_PEER_RECONFIGURE: break; default: GNUNET_assert (0); } GNUNET_TESTBED_remove_opc_ (opc->c, opc); opc->state = OPC_STATE_FINISHED; exop_insert (event.op); if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) { if (NULL != c->cc) c->cc (c->cc_cls, &event); if (GNUNET_NO == exop_check (event.op)) return GNUNET_YES; } else LOG_DEBUG ("Not calling callback\n"); if (NULL != op_comp_cb) op_comp_cb (op_comp_cb_cls, event.op, NULL); /* You could have marked the operation as done by now */ GNUNET_break (GNUNET_NO == exop_check (event.op)); return GNUNET_YES; } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from * controller (testbed service) * * @param c the controller handle * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ static int handle_peer_create_success (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg) { struct OperationContext *opc; struct PeerCreateData *data; struct GNUNET_TESTBED_Peer *peer; struct GNUNET_TESTBED_Operation *op; GNUNET_TESTBED_PeerCreateCallback cb; void *cls; uint64_t op_id; GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) == ntohs (msg->header.size)); op_id = GNUNET_ntohll (msg->operation_id); if (NULL == (opc = find_opc (c, op_id))) { LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n"); return GNUNET_YES; } if (OP_FORWARDED == opc->type) { handle_forwarded_operation_msg (c, opc, (const struct GNUNET_MessageHeader *) msg); return GNUNET_YES; } GNUNET_assert (OP_PEER_CREATE == opc->type); GNUNET_assert (NULL != opc->data); data = opc->data; GNUNET_assert (NULL != data->peer); peer = data->peer; GNUNET_assert (peer->unique_id == ntohl (msg->peer_id)); peer->state = TESTBED_PS_CREATED; GNUNET_TESTBED_peer_register_ (peer); cb = data->cb; cls = data->cls; op = opc->op; GNUNET_free (opc->data); GNUNET_TESTBED_remove_opc_ (opc->c, opc); opc->state = OPC_STATE_FINISHED; exop_insert (op); if (NULL != cb) cb (cls, peer, NULL); /* You could have marked the operation as done by now */ GNUNET_break (GNUNET_NO == exop_check (op)); return GNUNET_YES; } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from * controller (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ static int handle_peer_event (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_PeerEventMessage *msg) { struct OperationContext *opc; struct GNUNET_TESTBED_Peer *peer; struct PeerEventData *data; GNUNET_TESTBED_PeerChurnCallback pcc; void *pcc_cls; struct GNUNET_TESTBED_EventInformation event; uint64_t op_id; uint64_t mask; GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) == ntohs (msg->header.size)); op_id = GNUNET_ntohll (msg->operation_id); if (NULL == (opc = find_opc (c, op_id))) { LOG_DEBUG ("Operation not found\n"); return GNUNET_YES; } if (OP_FORWARDED == opc->type) { handle_forwarded_operation_msg (c, opc, (const struct GNUNET_MessageHeader *) msg); return GNUNET_YES; } GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type)); data = opc->data; GNUNET_assert (NULL != data); peer = data->peer; GNUNET_assert (NULL != peer); event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type); event.op = opc->op; event.op_cls = opc->op_cls; switch (event.type) { case GNUNET_TESTBED_ET_PEER_START: peer->state = TESTBED_PS_STARTED; event.details.peer_start.host = peer->host; event.details.peer_start.peer = peer; break; case GNUNET_TESTBED_ET_PEER_STOP: peer->state = TESTBED_PS_STOPPED; event.details.peer_stop.peer = peer; break; default: GNUNET_assert (0); /* We should never reach this state */ } pcc = data->pcc; pcc_cls = data->pcc_cls; GNUNET_free (data); GNUNET_TESTBED_remove_opc_ (opc->c, opc); opc->state = OPC_STATE_FINISHED; exop_insert (event.op); mask = 1LL << GNUNET_TESTBED_ET_PEER_START; mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP; if (0 != (mask & c->event_mask)) { if (NULL != c->cc) c->cc (c->cc_cls, &event); if (GNUNET_NO == exop_check (event.op)) return GNUNET_YES; } if (NULL != pcc) pcc (pcc_cls, NULL); /* You could have marked the operation as done by now */ GNUNET_break (GNUNET_NO == exop_check (event.op)); return GNUNET_YES; } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from * controller (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ static int handle_peer_conevent (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_ConnectionEventMessage *msg) { struct OperationContext *opc; struct OverlayConnectData *data; GNUNET_TESTBED_OperationCompletionCallback cb; void *cb_cls; struct GNUNET_TESTBED_EventInformation event; uint64_t op_id; uint64_t mask; op_id = GNUNET_ntohll (msg->operation_id); if (NULL == (opc = find_opc (c, op_id))) { LOG_DEBUG ("Operation not found\n"); return GNUNET_YES; } if (OP_FORWARDED == opc->type) { handle_forwarded_operation_msg (c, opc, (const struct GNUNET_MessageHeader *) msg); return GNUNET_YES; } GNUNET_assert (OP_OVERLAY_CONNECT == opc->type); GNUNET_assert (NULL != (data = opc->data)); GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) && (ntohl (msg->peer2) == data->p2->unique_id)); event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type); event.op = opc->op; event.op_cls = opc->op_cls; switch (event.type) { case GNUNET_TESTBED_ET_CONNECT: event.details.peer_connect.peer1 = data->p1; event.details.peer_connect.peer2 = data->p2; break; case GNUNET_TESTBED_ET_DISCONNECT: GNUNET_assert (0); /* FIXME: implement */ break; default: GNUNET_assert (0); /* Should never reach here */ break; } cb = data->cb; cb_cls = data->cb_cls; GNUNET_TESTBED_remove_opc_ (opc->c, opc); opc->state = OPC_STATE_FINISHED; exop_insert (event.op); mask = 1LL << GNUNET_TESTBED_ET_CONNECT; mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT; if (0 != (mask & c->event_mask)) { if (NULL != c->cc) c->cc (c->cc_cls, &event); if (GNUNET_NO == exop_check (event.op)) return GNUNET_YES; } if (NULL != cb) cb (cb_cls, opc->op, NULL); /* You could have marked the operation as done by now */ GNUNET_break (GNUNET_NO == exop_check (event.op)); return GNUNET_YES; } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from * controller (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ static int handle_peer_config (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg) { struct OperationContext *opc; struct GNUNET_TESTBED_Peer *peer; struct PeerInfoData *data; struct GNUNET_TESTBED_PeerInformation *pinfo; GNUNET_TESTBED_PeerInfoCallback cb; void *cb_cls; uint64_t op_id; op_id = GNUNET_ntohll (msg->operation_id); if (NULL == (opc = find_opc (c, op_id))) { LOG_DEBUG ("Operation not found\n"); return GNUNET_YES; } if (OP_FORWARDED == opc->type) { handle_forwarded_operation_msg (c, opc, (const struct GNUNET_MessageHeader *) msg); return GNUNET_YES; } data = opc->data; GNUNET_assert (NULL != data); peer = data->peer; GNUNET_assert (NULL != peer); GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id); pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation); pinfo->pit = data->pit; cb = data->cb; cb_cls = data->cb_cls; GNUNET_assert (NULL != cb); GNUNET_free (data); opc->data = NULL; switch (pinfo->pit) { case GNUNET_TESTBED_PIT_IDENTITY: pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity); (void) memcpy (pinfo->result.id, &msg->peer_identity, sizeof (struct GNUNET_PeerIdentity)); break; case GNUNET_TESTBED_PIT_CONFIGURATION: pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */ GNUNET_TESTBED_extract_config_ (&msg->header); break; case GNUNET_TESTBED_PIT_GENERIC: GNUNET_assert (0); /* never reach here */ break; } opc->data = pinfo; GNUNET_TESTBED_remove_opc_ (opc->c, opc); opc->state = OPC_STATE_FINISHED; cb (cb_cls, opc->op, pinfo, NULL); /* We dont check whether the operation is marked as done here as the operation contains data (cfg/identify) which will be freed at a later point */ return GNUNET_YES; } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from * controller (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ static int handle_op_fail_event (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_OperationFailureEventMessage *msg) { struct OperationContext *opc; const char *emsg; uint64_t op_id; uint64_t mask; struct GNUNET_TESTBED_EventInformation event; op_id = GNUNET_ntohll (msg->operation_id); if (NULL == (opc = find_opc (c, op_id))) { LOG_DEBUG ("Operation not found\n"); return GNUNET_YES; } if (OP_FORWARDED == opc->type) { handle_forwarded_operation_msg (c, opc, (const struct GNUNET_MessageHeader *) msg); return GNUNET_YES; } GNUNET_TESTBED_remove_opc_ (opc->c, opc); opc->state = OPC_STATE_FINISHED; emsg = GNUNET_TESTBED_parse_error_string_ (msg); if (NULL == emsg) emsg = "Unknown error"; if (OP_PEER_INFO == opc->type) { struct PeerInfoData *data; data = opc->data; if (NULL != data->cb) data->cb (data->cb_cls, opc->op, NULL, emsg); GNUNET_free (data); return GNUNET_YES; /* We do not call controller callback for peer info */ } event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; event.op = opc->op; event.op_cls = opc->op_cls; event.details.operation_finished.emsg = emsg; event.details.operation_finished.generic = NULL; mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); if ((0 != (mask & c->event_mask)) && (NULL != c->cc)) { exop_insert (event.op); c->cc (c->cc_cls, &event); if (GNUNET_NO == exop_check (event.op)) return GNUNET_YES; } switch (opc->type) { case OP_PEER_CREATE: { struct PeerCreateData *data; data = opc->data; GNUNET_free (data->peer); if (NULL != data->cb) data->cb (data->cls, NULL, emsg); GNUNET_free (data); } break; case OP_PEER_START: case OP_PEER_STOP: { struct PeerEventData *data; data = opc->data; if (NULL != data->pcc) data->pcc (data->pcc_cls, emsg); GNUNET_free (data); } break; case OP_PEER_DESTROY: break; case OP_PEER_INFO: GNUNET_assert (0); case OP_OVERLAY_CONNECT: { struct OverlayConnectData *data; data = opc->data; GNUNET_TESTBED_operation_mark_failed (opc->op); if (NULL != data->cb) data->cb (data->cb_cls, opc->op, emsg); } break; case OP_FORWARDED: GNUNET_assert (0); case OP_LINK_CONTROLLERS: /* No secondary callback */ break; case OP_SHUTDOWN_PEERS: { struct ShutdownPeersData *data; data = opc->data; GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */ opc->data = NULL; } break; case OP_MANAGE_SERVICE: { struct ManageServiceData *data = opc->data; GNUNET_TESTBED_OperationCompletionCallback cb; void *cb_cls; GNUNET_assert (NULL != data); cb = data->cb; cb_cls = data->cb_cls; GNUNET_free (data); opc->data = NULL; exop_insert (event.op); if (NULL != cb) cb (cb_cls, opc->op, emsg); /* You could have marked the operation as done by now */ GNUNET_break (GNUNET_NO == exop_check (event.op)); } break; default: GNUNET_break (0); } return GNUNET_YES; } /** * Function to build GET_SLAVE_CONFIG message * * @param op_id the id this message should contain in its operation id field * @param slave_id the id this message should contain in its slave id field * @return newly allocated SlaveGetConfigurationMessage */ static struct GNUNET_TESTBED_SlaveGetConfigurationMessage * GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id) { struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; uint16_t msize; msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage); msg = GNUNET_malloc (msize); msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION); msg->operation_id = GNUNET_htonll (op_id); msg->slave_id = htonl (slave_id); return msg; } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller * (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ static int handle_slave_config (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_SlaveConfiguration *msg) { struct OperationContext *opc; uint64_t op_id; uint64_t mask; struct GNUNET_TESTBED_EventInformation event; op_id = GNUNET_ntohll (msg->operation_id); if (NULL == (opc = find_opc (c, op_id))) { LOG_DEBUG ("Operation not found\n"); return GNUNET_YES; } if (OP_GET_SLAVE_CONFIG != opc->type) { GNUNET_break (0); return GNUNET_YES; } opc->state = OPC_STATE_FINISHED; GNUNET_TESTBED_remove_opc_ (opc->c, opc); mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED; if ((0 != (mask & c->event_mask)) && (NULL != c->cc)) { opc->data = GNUNET_TESTBED_extract_config_ (&msg->header); event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; event.op = opc->op; event.op_cls = opc->op_cls; event.details.operation_finished.generic = opc->data; event.details.operation_finished.emsg = NULL; c->cc (c->cc_cls, &event); } return GNUNET_YES; } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller * (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ static int handle_link_controllers_result (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_ControllerLinkResponse *msg) { struct OperationContext *opc; struct ControllerLinkData *data; struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_TESTBED_Host *host; char *emsg; uint64_t op_id; struct GNUNET_TESTBED_EventInformation event; op_id = GNUNET_ntohll (msg->operation_id); if (NULL == (opc = find_opc (c, op_id))) { LOG_DEBUG ("Operation not found\n"); return GNUNET_YES; } if (OP_FORWARDED == opc->type) { handle_forwarded_operation_msg (c, opc, (const struct GNUNET_MessageHeader *) msg); return GNUNET_YES; } if (OP_LINK_CONTROLLERS != opc->type) { GNUNET_break (0); return GNUNET_YES; } GNUNET_assert (NULL != (data = opc->data)); host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id); GNUNET_assert (NULL != host); GNUNET_free (data); opc->data = NULL; opc->state = OPC_STATE_FINISHED; GNUNET_TESTBED_remove_opc_ (opc->c, opc); event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED; event.op = opc->op; event.op_cls = opc->op_cls; event.details.operation_finished.emsg = NULL; event.details.operation_finished.generic = NULL; emsg = NULL; cfg = NULL; if (GNUNET_NO == ntohs (msg->success)) { emsg = GNUNET_malloc (ntohs (msg->header.size) - sizeof (struct GNUNET_TESTBED_ControllerLinkResponse) + 1); memcpy (emsg, &msg[1], ntohs (msg->header.size) - sizeof (struct GNUNET_TESTBED_ControllerLinkResponse)); event.details.operation_finished.emsg = emsg; } else { if (0 != ntohs (msg->config_size)) { cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg); GNUNET_assert (NULL != cfg); GNUNET_TESTBED_host_replace_cfg_ (host, cfg); } } if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED))) { if (NULL != c->cc) c->cc (c->cc_cls, &event); } else LOG_DEBUG ("Not calling callback\n"); if (NULL != cfg) GNUNET_CONFIGURATION_destroy (cfg); GNUNET_free_non_null (emsg); return GNUNET_YES; } /** * Handler for messages from controller (testbed service) * * @param cls the controller handler * @param msg message received, NULL on timeout or fatal error */ static void message_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_TESTBED_Controller *c = cls; int status; uint16_t msize; c->in_receive = GNUNET_NO; /* FIXME: Add checks for message integrity */ if (NULL == msg) { LOG_DEBUG ("Receive timed out or connection to service dropped\n"); return; } msize = ntohs (msg->size); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS: GNUNET_assert (msize >= sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)); status = GNUNET_TESTBED_host_handle_addhostconfirm_ (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS: GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage)); status = handle_opsuccess (c, (const struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT: GNUNET_assert (msize >= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage)); status = handle_op_fail_event (c, (const struct GNUNET_TESTBED_OperationFailureEventMessage *) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS: GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); status = handle_peer_create_success (c, (const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT: GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage)); status = handle_peer_event (c, (const struct GNUNET_TESTBED_PeerEventMessage *) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION: GNUNET_assert (msize >= sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage)); status = handle_peer_config (c, (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT: GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_ConnectionEventMessage)); status = handle_peer_conevent (c, (const struct GNUNET_TESTBED_ConnectionEventMessage *) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION: GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration)); status = handle_slave_config (c, (const struct GNUNET_TESTBED_SlaveConfiguration *) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT: status = handle_link_controllers_result (c, (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg); break; case GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS: status = GNUNET_TESTBED_handle_barrier_status_ (c, (const struct GNUNET_TESTBED_BarrierStatusMsg *) msg); break; default: GNUNET_assert (0); } if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive)) { c->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (c->client, &message_handler, c, GNUNET_TIME_UNIT_FOREVER_REL); } } /** * Function called to notify a client about the connection begin ready to queue * more data. "buf" will be NULL and "size" zero if the connection was closed * for writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_ready_notify (void *cls, size_t size, void *buf) { struct GNUNET_TESTBED_Controller *c = cls; struct MessageQueue *mq_entry; c->th = NULL; mq_entry = c->mq_head; GNUNET_assert (NULL != mq_entry); if ((0 == size) && (NULL == buf)) /* Timeout */ { LOG_DEBUG ("Message sending timed out -- retrying\n"); c->th = GNUNET_CLIENT_notify_transmit_ready (c->client, ntohs (mq_entry->msg->size), TIMEOUT_REL, GNUNET_YES, &transmit_ready_notify, c); return 0; } GNUNET_assert (ntohs (mq_entry->msg->size) <= size); size = ntohs (mq_entry->msg->size); memcpy (buf, mq_entry->msg, size); LOG_DEBUG ("Message of type: %u and size: %u sent\n", ntohs (mq_entry->msg->type), size); GNUNET_free (mq_entry->msg); GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry); GNUNET_free (mq_entry); mq_entry = c->mq_head; if (NULL != mq_entry) c->th = GNUNET_CLIENT_notify_transmit_ready (c->client, ntohs (mq_entry->msg->size), TIMEOUT_REL, GNUNET_YES, &transmit_ready_notify, c); if (GNUNET_NO == c->in_receive) { c->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (c->client, &message_handler, c, GNUNET_TIME_UNIT_FOREVER_REL); } return size; } /** * Queues a message in send queue for sending to the service * * @param controller the handle to the controller * @param msg the message to queue */ void GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller, struct GNUNET_MessageHeader *msg) { struct MessageQueue *mq_entry; uint16_t type; uint16_t size; type = ntohs (msg->type); size = ntohs (msg->size); GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) && (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type)); mq_entry = GNUNET_new (struct MessageQueue); mq_entry->msg = msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing message of type %u, size %u for sending\n", type, ntohs (msg->size)); GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail, mq_entry); if (NULL == controller->th) controller->th = GNUNET_CLIENT_notify_transmit_ready (controller->client, size, TIMEOUT_REL, GNUNET_YES, &transmit_ready_notify, controller); } /** * Sends the given message as an operation. The given callback is called when a * reply for the operation is available. Call * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned * operation context if the cc hasn't been called * * @param controller the controller to which the message has to be sent * @param operation_id the operation id of the message * @param msg the message to send * @param cc the callback to call when reply is available * @param cc_cls the closure for the above callback * @return the operation context which can be used to cancel the forwarded * operation */ struct OperationContext * GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller *controller, uint64_t operation_id, const struct GNUNET_MessageHeader *msg, GNUNET_CLIENT_MessageHandler cc, void *cc_cls) { struct OperationContext *opc; struct ForwardedOperationData *data; struct GNUNET_MessageHeader *dup_msg; uint16_t msize; data = GNUNET_new (struct ForwardedOperationData); data->cc = cc; data->cc_cls = cc_cls; opc = GNUNET_new (struct OperationContext); opc->c = controller; opc->type = OP_FORWARDED; opc->data = data; opc->id = operation_id; msize = ntohs (msg->size); dup_msg = GNUNET_malloc (msize); (void) memcpy (dup_msg, msg, msize); GNUNET_TESTBED_queue_message_ (opc->c, dup_msg); GNUNET_TESTBED_insert_opc_ (controller, opc); return opc; } /** * Function to cancel an operation created by simply forwarding an operation * message. * * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_() */ void GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc) { GNUNET_TESTBED_remove_opc_ (opc->c, opc); GNUNET_free (opc->data); GNUNET_free (opc); } /** * Function to call to start a link-controllers type operation once all queues * the operation is part of declare that the operation can be activated. * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_link_controllers (void *cls) { struct OperationContext *opc = cls; struct ControllerLinkData *data; struct GNUNET_TESTBED_ControllerLinkRequest *msg; GNUNET_assert (NULL != opc->data); data = opc->data; msg = data->msg; data->msg = NULL; opc->state = OPC_STATE_STARTED; GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); } /** * Callback which will be called when link-controllers type operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_link_controllers (void *cls) { struct OperationContext *opc = cls; struct ControllerLinkData *data; data = opc->data; switch (opc->state) { case OPC_STATE_INIT: GNUNET_free (data->msg); break; case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); break; case OPC_STATE_FINISHED: break; } GNUNET_free_non_null (data); GNUNET_free (opc); } /** * Function to be called when get slave config operation is ready * * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG */ static void opstart_get_slave_config (void *cls) { struct OperationContext *opc = cls; struct GetSlaveConfigData *data = opc->data; struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg; GNUNET_assert (NULL != data); msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id); GNUNET_free (opc->data); data = NULL; opc->data = NULL; GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); opc->state = OPC_STATE_STARTED; } /** * Function to be called when get slave config operation is cancelled or finished * * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG */ static void oprelease_get_slave_config (void *cls) { struct OperationContext *opc = cls; switch (opc->state) { case OPC_STATE_INIT: GNUNET_free (opc->data); break; case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); break; case OPC_STATE_FINISHED: if (NULL != opc->data) GNUNET_CONFIGURATION_destroy (opc->data); break; } GNUNET_free (opc); } /** * Start a controller process using the given configuration at the * given host. * * @param host host to run the controller on; This should be the same host if * the controller was previously started with * GNUNET_TESTBED_controller_start() * @param event_mask bit mask with set of events to call 'cc' for; * or-ed values of "1LL" shifted by the * respective 'enum GNUNET_TESTBED_EventType' * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...") * @param cc controller callback to invoke on events * @param cc_cls closure for cc * @return handle to the controller */ struct GNUNET_TESTBED_Controller * GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host, uint64_t event_mask, GNUNET_TESTBED_ControllerCallback cc, void *cc_cls) { struct GNUNET_TESTBED_Controller *controller; struct GNUNET_TESTBED_InitMessage *msg; const struct GNUNET_CONFIGURATION_Handle *cfg; const char *controller_hostname; unsigned long long max_parallel_operations; unsigned long long max_parallel_service_connections; unsigned long long max_parallel_topology_config_operations; GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host))); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "testbed", "MAX_PARALLEL_OPERATIONS", &max_parallel_operations)) { GNUNET_break (0); return NULL; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "testbed", "MAX_PARALLEL_SERVICE_CONNECTIONS", &max_parallel_service_connections)) { GNUNET_break (0); return NULL; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "testbed", "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS", &max_parallel_topology_config_operations)) { GNUNET_break (0); return NULL; } controller = GNUNET_new (struct GNUNET_TESTBED_Controller); controller->cc = cc; controller->cc_cls = cc_cls; controller->event_mask = event_mask; controller->cfg = GNUNET_CONFIGURATION_dup (cfg); controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg); if (NULL == controller->client) { GNUNET_TESTBED_controller_disconnect (controller); return NULL; } GNUNET_TESTBED_mark_host_registered_at_ (host, controller); controller->host = host; controller->opq_parallel_operations = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, (unsigned int) max_parallel_operations); controller->opq_parallel_service_connections = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, (unsigned int) max_parallel_service_connections); controller->opq_parallel_topology_config_operations = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, (unsigned int) max_parallel_topology_config_operations); controller_hostname = GNUNET_TESTBED_host_get_hostname (host); if (NULL == controller_hostname) controller_hostname = "127.0.0.1"; msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) + strlen (controller_hostname) + 1); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT); msg->header.size = htons (sizeof (struct GNUNET_TESTBED_InitMessage) + strlen (controller_hostname) + 1); msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host)); msg->event_mask = GNUNET_htonll (controller->event_mask); strcpy ((char *) &msg[1], controller_hostname); GNUNET_TESTBED_queue_message_ (controller, (struct GNUNET_MessageHeader *) msg); return controller; } /** * Iterator to free opc map entries * * @param cls closure * @param key current key code * @param value value in the hash map * @return GNUNET_YES if we should continue to * iterate, * GNUNET_NO if not. */ static int opc_free_iterator (void *cls, uint32_t key, void *value) { struct GNUNET_CONTAINER_MultiHashMap32 *map = cls; struct OperationContext *opc = value; GNUNET_assert (NULL != opc); GNUNET_break (0); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_remove (map, key, value)); GNUNET_free (opc); return GNUNET_YES; } /** * Stop the given controller (also will terminate all peers and * controllers dependent on this controller). This function * blocks until the testbed has been fully terminated (!). * * @param c handle to controller to stop */ void GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *c) { struct MessageQueue *mq_entry; if (NULL != c->th) GNUNET_CLIENT_notify_transmit_ready_cancel (c->th); /* Clear the message queue */ while (NULL != (mq_entry = c->mq_head)) { GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry); GNUNET_free (mq_entry->msg); GNUNET_free (mq_entry); } if (NULL != c->client) GNUNET_CLIENT_disconnect (c->client); if (NULL != c->host) GNUNET_TESTBED_deregister_host_at_ (c->host, c); GNUNET_CONFIGURATION_destroy (c->cfg); GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations); GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_service_connections); GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_topology_config_operations); if (NULL != c->opc_map) { GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map, &opc_free_iterator, c->opc_map)); GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map)); GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map); } GNUNET_free (c); } /** * Compresses given configuration using zlib compress * * @param config the serialized configuration * @param size the size of config * @param xconfig will be set to the compressed configuration (memory is fresly * allocated) * @return the size of the xconfig */ size_t GNUNET_TESTBED_compress_config_ (const char *config, size_t size, char **xconfig) { size_t xsize; xsize = compressBound ((uLong) size); *xconfig = GNUNET_malloc (xsize); GNUNET_assert (Z_OK == compress2 ((Bytef *) * xconfig, (uLongf *) & xsize, (const Bytef *) config, (uLongf) size, Z_BEST_SPEED)); return xsize; } /** * Function to serialize and compress using zlib a configuration through a * configuration handle * * @param cfg the configuration * @param size the size of configuration when serialize. Will be set on success. * @param xsize the sizeo of the compressed configuration. Will be set on success. * @return the serialized and compressed configuration */ char * GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size, size_t *xsize) { char *config; char *xconfig; size_t size_; size_t xsize_; config = GNUNET_CONFIGURATION_serialize (cfg, &size_); xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig); GNUNET_free (config); *size = size_; *xsize = xsize_; return xconfig; } /** * Create a link from slave controller to delegated controller. Whenever the * master controller is asked to start a peer at the delegated controller the * request will be routed towards slave controller (if a route exists). The * slave controller will then route it to the delegated controller. The * configuration of the delegated controller is given and is used to either * create the delegated controller or to connect to an existing controller. Note * that while starting the delegated controller the configuration will be * modified to accommodate available free ports. the 'is_subordinate' specifies * if the given delegated controller should be started and managed by the slave * controller, or if the delegated controller already has a master and the slave * controller connects to it as a non master controller. The success or failure * of this operation will be signalled through the * GNUNET_TESTBED_ControllerCallback() with an event of type * GNUNET_TESTBED_ET_OPERATION_FINISHED * * @param op_cls the operation closure for the event which is generated to * signal success or failure of this operation * @param master handle to the master controller who creates the association * @param delegated_host requests to which host should be delegated; cannot be NULL * @param slave_host which host is used to run the slave controller; use NULL to * make the master controller connect to the delegated host * @param is_subordinate GNUNET_YES if the controller at delegated_host should * be started by the slave controller; GNUNET_NO if the slave * controller has to connect to the already started delegated * controller via TCP/IP * @return the operation handle */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_controller_link (void *op_cls, struct GNUNET_TESTBED_Controller *master, struct GNUNET_TESTBED_Host *delegated_host, struct GNUNET_TESTBED_Host *slave_host, int is_subordinate) { struct OperationContext *opc; struct GNUNET_TESTBED_ControllerLinkRequest *msg; struct ControllerLinkData *data; uint32_t slave_host_id; uint32_t delegated_host_id; uint16_t msg_size; GNUNET_assert (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (delegated_host, master)); slave_host_id = GNUNET_TESTBED_host_get_id_ ((NULL != slave_host) ? slave_host : master->host); delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host); if ((NULL != slave_host) && (0 != slave_host_id)) GNUNET_assert (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (slave_host, master)); msg_size = sizeof (struct GNUNET_TESTBED_ControllerLinkRequest); msg = GNUNET_malloc (msg_size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS); msg->header.size = htons (msg_size); msg->delegated_host_id = htonl (delegated_host_id); msg->slave_host_id = htonl (slave_host_id); msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0; data = GNUNET_new (struct ControllerLinkData); data->msg = msg; data->host_id = delegated_host_id; opc = GNUNET_new (struct OperationContext); opc->c = master; opc->data = data; opc->type = OP_LINK_CONTROLLERS; opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); opc->state = OPC_STATE_INIT; opc->op_cls = op_cls; msg->operation_id = GNUNET_htonll (opc->id); opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers, &oprelease_link_controllers); GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Like GNUNET_TESTBED_get_slave_config(), however without the host registration * check. Another difference is that this function takes the id of the slave * host. * * @param op_cls the closure for the operation * @param master the handle to master controller * @param slave_host_id id of the host where the slave controller is running to * the slave_host should remain valid until this operation is cancelled * or marked as finished * @return the operation handle; */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_get_slave_config_ (void *op_cls, struct GNUNET_TESTBED_Controller *master, uint32_t slave_host_id) { struct OperationContext *opc; struct GetSlaveConfigData *data; data = GNUNET_new (struct GetSlaveConfigData); data->slave_id = slave_host_id; opc = GNUNET_new (struct OperationContext); opc->state = OPC_STATE_INIT; opc->c = master; opc->id = GNUNET_TESTBED_get_next_op_id (master); opc->type = OP_GET_SLAVE_CONFIG; opc->data = data; opc->op_cls = op_cls; opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config, &oprelease_get_slave_config); GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Function to acquire the configuration of a running slave controller. The * completion of the operation is signalled through the controller_cb from * GNUNET_TESTBED_controller_connect(). If the operation is successful the * handle to the configuration is available in the generic pointer of * operation_finished field of struct GNUNET_TESTBED_EventInformation. * * @param op_cls the closure for the operation * @param master the handle to master controller * @param slave_host the host where the slave controller is running; the handle * to the slave_host should remain valid until this operation is * cancelled or marked as finished * @return the operation handle; NULL if the slave_host is not registered at * master */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_get_slave_config (void *op_cls, struct GNUNET_TESTBED_Controller *master, struct GNUNET_TESTBED_Host *slave_host) { if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master)) return NULL; return GNUNET_TESTBED_get_slave_config_ (op_cls, master, GNUNET_TESTBED_host_get_id_ (slave_host)); } /** * Ask the testbed controller to write the current overlay topology to * a file. Naturally, the file will only contain a snapshot as the * topology may evolve all the time. * * @param controller overlay controller to inspect * @param filename name of the file the topology should * be written to. */ void GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller *controller, const char *filename) { GNUNET_break (0); } /** * Creates a helper initialization message. This function is here because we * want to use this in testing * * @param trusted_ip the ip address of the controller which will be set as TRUSTED * HOST(all connections form this ip are permitted by the testbed) when * starting testbed controller at host. This can either be a single ip * address or a network address in CIDR notation. * @param hostname the hostname of the destination this message is intended for * @param cfg the configuration that has to used to start the testbed service * thru helper * @return the initialization message */ struct GNUNET_TESTBED_HelperInit * GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip, const char *hostname, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_TESTBED_HelperInit *msg; char *config; char *xconfig; size_t config_size; size_t xconfig_size; uint16_t trusted_ip_len; uint16_t hostname_len; uint16_t msg_size; config = GNUNET_CONFIGURATION_serialize (cfg, &config_size); GNUNET_assert (NULL != config); xconfig_size = GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig); GNUNET_free (config); trusted_ip_len = strlen (trusted_ip); hostname_len = (NULL == hostname) ? 0 : strlen (hostname); msg_size = xconfig_size + trusted_ip_len + 1 + sizeof (struct GNUNET_TESTBED_HelperInit); msg_size += hostname_len; msg = GNUNET_realloc (xconfig, msg_size); (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg, xconfig_size); msg->header.size = htons (msg_size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT); msg->trusted_ip_size = htons (trusted_ip_len); msg->hostname_size = htons (hostname_len); msg->config_size = htons (config_size); (void) strcpy ((char *) &msg[1], trusted_ip); if (0 != hostname_len) (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname, hostname_len); return msg; } /** * This function is used to signal that the event information (struct * GNUNET_TESTBED_EventInformation) from an operation has been fully processed * i.e. if the event callback is ever called for this operation. If the event * callback for this operation has not yet been called, calling this function * cancels the operation, frees its resources and ensures the no event is * generated with respect to this operation. Note that however cancelling an * operation does NOT guarantee that the operation will be fully undone (or that * nothing ever happened). * * This function MUST be called for every operation to fully remove the * operation from the operation queue. After calling this function, if * operation is completed and its event information is of type * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!). * If the operation is generated from GNUNET_TESTBED_service_connect() then * calling this function on such as operation calls the disconnect adapter if * the connect adapter was ever called. * * @param operation operation to signal completion or cancellation */ void GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation) { (void) exop_check (operation); GNUNET_TESTBED_operation_release_ (operation); } /** * Generates configuration by uncompressing configuration in given message. The * given message should be of the following types: * GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION, * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION, * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT, * * @param msg the message containing compressed configuration * @return handle to the parsed configuration; NULL upon error while parsing the message */ struct GNUNET_CONFIGURATION_Handle * GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONFIGURATION_Handle *cfg; Bytef *data; const Bytef *xdata; uLong data_len; uLong xdata_len; int ret; switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION: { const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg; imsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg; data_len = (uLong) ntohs (imsg->config_size); xdata_len = ntohs (imsg->header.size) - sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage); xdata = (const Bytef *) &imsg[1]; } break; case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION: { const struct GNUNET_TESTBED_SlaveConfiguration *imsg; imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg; data_len = (uLong) ntohs (imsg->config_size); xdata_len = ntohs (imsg->header.size) - sizeof (struct GNUNET_TESTBED_SlaveConfiguration); xdata = (const Bytef *) &imsg[1]; } break; case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST: { const struct GNUNET_TESTBED_AddHostMessage *imsg; uint16_t osize; imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg; data_len = (uLong) ntohs (imsg->config_size); osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) + ntohs (imsg->username_length) + ntohs (imsg->hostname_length); xdata_len = ntohs (imsg->header.size) - osize; xdata = (const Bytef *) ((const void *) imsg + osize); } break; case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT: { const struct GNUNET_TESTBED_ControllerLinkResponse *imsg; imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg; data_len = ntohs (imsg->config_size); xdata_len = ntohs (imsg->header.size) - sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse); xdata = (const Bytef *) &imsg[1]; } break; case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER: { const struct GNUNET_TESTBED_PeerCreateMessage *imsg; imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg; data_len = ntohs (imsg->config_size); xdata_len = ntohs (imsg->header.size) - sizeof (struct GNUNET_TESTBED_PeerCreateMessage); xdata = (const Bytef *) &imsg[1]; } break; case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER: { const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg; imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg; data_len = ntohs (imsg->config_size); xdata_len = ntohs (imsg->header.size) - sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage); xdata = (const Bytef *) &imsg[1]; } break; default: GNUNET_assert (0); } data = GNUNET_malloc (data_len); if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len))) { GNUNET_free (data); GNUNET_break_op (0); /* Un-compression failure */ return NULL; } cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data, (size_t) data_len, GNUNET_NO)) { GNUNET_free (data); GNUNET_break_op (0); /* De-serialization failure */ return NULL; } GNUNET_free (data); return cfg; } /** * Checks the integrity of the OperationFailureEventMessage and if good returns * the error message it contains. * * @param msg the OperationFailureEventMessage * @return the error message */ const char * GNUNET_TESTBED_parse_error_string_ (const struct GNUNET_TESTBED_OperationFailureEventMessage *msg) { uint16_t msize; const char *emsg; msize = ntohs (msg->header.size); if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize) return NULL; msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage); emsg = (const char *) &msg[1]; if ('\0' != emsg[msize - 1]) { GNUNET_break (0); return NULL; } return emsg; } /** * Function to return the operation id for a controller. The operation id is * created from the controllers host id and its internal operation counter. * * @param controller the handle to the controller whose operation id has to be incremented * @return the incremented operation id. */ uint64_t GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller) { uint64_t op_id; op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host); op_id = op_id << 32; op_id |= (uint64_t) controller->operation_counter++; return op_id; } /** * Function called when a shutdown peers operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_shutdown_peers (void *cls) { struct OperationContext *opc = cls; struct GNUNET_TESTBED_ShutdownPeersMessage *msg; opc->state = OPC_STATE_STARTED; msg = GNUNET_new (struct GNUNET_TESTBED_ShutdownPeersMessage); msg->header.size = htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS); msg->operation_id = GNUNET_htonll (opc->id); GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); } /** * Callback which will be called when shutdown peers operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_shutdown_peers (void *cls) { struct OperationContext *opc = cls; switch (opc->state) { case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); /* no break; continue */ case OPC_STATE_INIT: GNUNET_free (opc->data); break; case OPC_STATE_FINISHED: break; } GNUNET_free (opc); } /** * Stops and destroys all peers. Is equivalent of calling * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers, * except that the peer stop event and operation finished event corresponding to * the respective functions are not generated. This function should be called * when there are no other pending operations. If there are pending operations, * it will return NULL * * @param c the controller to send this message to * @param op_cls closure for the operation * @param cb the callback to call when all peers are stopped and destroyed * @param cb_cls the closure for the callback * @return operation handle on success; NULL if any pending operations are * present */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c, void *op_cls, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls) { struct OperationContext *opc; struct ShutdownPeersData *data; if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map)) return NULL; data = GNUNET_new (struct ShutdownPeersData); data->cb = cb; data->cb_cls = cb_cls; opc = GNUNET_new (struct OperationContext); opc->c = c; opc->op_cls = op_cls; opc->data = data; opc->id = GNUNET_TESTBED_get_next_op_id (c); opc->type = OP_SHUTDOWN_PEERS; opc->state = OPC_STATE_INIT; opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers, &oprelease_shutdown_peers); GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Return the index of the peer inside of the total peer array, * aka. the peer's "unique ID". * * @param peer Peer handle. * * @return The peer's unique ID. */ uint32_t GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer) { return peer->unique_id; } /* end of testbed_api.c */ gnunet-0.10.1/src/testbed/sample_hosts.txt0000644000175000017500000000020212207341476015475 00000000000000totakura@192.168.0.1:22 totakura@192.168.0.2:22 totakura@opt01:22 totakura@i19-n015:2022 totakura@asgard.realm rivendal rohan:561 gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf0000644000175000017500000000016012233724131025732 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = SMALL_WORLD_RING OVERLAY_RANDOM_LINKS = 3 gnunet-0.10.1/src/testbed/gnunet-service-testbed_connectionpool.h0000644000175000017500000001423512251306467022116 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_connectionpool.h * @brief Interface for connection pooling subroutines * @author Sree Harsha Totakura */ /** * The request handle for obtaining a pooled connection */ struct GST_ConnectionPool_GetHandle; /** * The type of service */ enum GST_ConnectionPool_Service { /** * Transport service */ GST_CONNECTIONPOOL_SERVICE_TRANSPORT = 1, /** * Core service */ GST_CONNECTIONPOOL_SERVICE_CORE }; /** * Initialise the connection pool. * * @param size the size of the connection pool. Each entry in the connection * pool can handle a connection to each of the services enumerated in * #GST_ConnectionPool_Service */ void GST_connection_pool_init (unsigned int size); /** * Cleanup the connection pool */ void GST_connection_pool_destroy (); /** * Functions of this type are called when the needed handle is available for * usage. These functions are to be registered with the function * GST_connection_pool_get_handle(). The corresponding handles will be set upon * success. If they are not set, then it signals an error while opening the * handles. * * @param cls the closure passed to GST_connection_pool_get_handle() * @param ch the handle to CORE. Can be NULL if it is not requested * @param th the handle to TRANSPORT. Can be NULL if it is not requested * @param peer_id the identity of the peer. Will be NULL if ch is NULL. In other * cases, its value being NULL means that CORE connection has failed. */ typedef void (*GST_connection_pool_connection_ready_cb) (void *cls, struct GNUNET_CORE_Handle * ch, struct GNUNET_TRANSPORT_Handle * th, const struct GNUNET_PeerIdentity * peer_id); /** * Callback to notify when the target peer given to * GST_connection_pool_get_handle() is connected. * * @param cls the closure given to GST_connection_pool_get_handle() for this * callback * @param target the peer identity of the target peer */ typedef void (*GST_connection_pool_peer_connect_notify) (void *cls, const struct GNUNET_PeerIdentity *target); /** * Get a connection handle to @a service. If the connection is opened before * and the connection handle is present in the connection pool, it is returned * through @a cb. @a peer_id is used for the lookup in the connection pool. If * the connection handle is not present in the connection pool, a new connection * handle is opened for the @a service using @a cfg. Additionally, @a target, * @a connect_notify_cb can be specified to get notified when @a target is * connected at @a service. * * @note @a connect_notify_cb will not be called if @a target is * already connected @a service level. Use * GNUNET_TRANSPORT_check_peer_connected() or a similar function from the * respective @a service's API to check if the target peer is already connected or * not. @a connect_notify_cb will be called only once or never (in case @a target * cannot be connected or is already connected). * * @param peer_id the index of the peer * @param cfg the configuration with which the transport handle has to be * created if it was not present in the cache * @param service the service of interest * @param cb the callback to notify when the transport handle is available * @param cb_cls the closure for @a cb * @param target the peer identify of the peer whose connection to our TRANSPORT * subsystem will be notified through the @a connect_notify_cb. Can be NULL * @param connect_notify_cb the callback to call when the @a target peer is * connected. This callback will only be called once or never again (in * case the target peer cannot be connected). Can be NULL * @param connect_notify_cb_cls the closure for @a connect_notify_cb * @return the handle which can be used cancel or mark that the handle is no * longer being used */ struct GST_ConnectionPool_GetHandle * GST_connection_pool_get_handle (unsigned int peer_id, const struct GNUNET_CONFIGURATION_Handle *cfg, enum GST_ConnectionPool_Service service, GST_connection_pool_connection_ready_cb cb, void *cb_cls, const struct GNUNET_PeerIdentity *target, GST_connection_pool_peer_connect_notify connect_notify_cb, void *connect_notify_cb_cls); /** * Relinquish a #GST_ConnectionPool_GetHandle object. If the connection * associated with the object is currently being used by other * #GST_ConnectionPool_GetHandle objects, it is left in the connection pool. If * no other objects are using the connection and the connection pool is not full * then it is placed in a LRU queue. If the connection pool is full, then * connections from the LRU queue are evicted and closed to create place for this * connection. If the connection pool if full and the LRU queue is empty, then * the connection is closed. * * @param gh the handle */ void GST_connection_pool_get_handle_done (struct GST_ConnectionPool_GetHandle *gh); /* End of gnunet-service-testbed_connectionpool.h */ gnunet-0.10.1/src/testbed/testbed.conf.in0000644000175000017500000001004512265232753015150 00000000000000[testbed] AUTOSTART = NO @JAVAPORT@ PORT = 2101 HOSTNAME = localhost BINARY = gnunet-service-testbed # How long should operations wait? OPERATION_TIMEOUT = 30 s # Set this to the path where the testbed helper is installed. By default the # helper binary is searched in @prefix@/lib/gnunet/libexec/ # HELPER_BINARY_PATH = @prefix@/lib/gnunet/libexec/gnunet-helper-testbed # Add your local network address here. For example, if you want to running # testbed on a group of hosts connected to network 192.168.1.0/24, then set # ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24; # Multiple network addresses can be given. They should be separated by `;' ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # How many maximum number of operations can be run in parallel. This number # should be decreased if the system is getting overloaded and to keep reduce the # load of testbed. MAX_PARALLEL_OPERATIONS = 1000 MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 1 # What topology should be generated by the helper functions GNUNET_TESTBED_run() # and GNUNET_TESTBED_test_run(). This option has no effect if testbed is # initialized with other functions. Valid values can be found at: # https://gnunet.org/content/supported-topologies OVERLAY_TOPOLOGY = NONE # Number of random links to be included to the generate the above topology. # Note that not all topologies require this option and ignore it. Topologies # requiring this option are RANDOM, SMALL_WORLD and SMALL_WORLD ring. # OVERLAY_RANDOM_LINKS = # If the OVERLAY_TOPOLOGY is set to FROM_FILE. This option is ignored for all # other topology values. This option should contain the path to the file # containing the topology information. The format of the file is presented at: # https://gnunet.org/content/topology-file-format # OVERLAY_TOPOLOGY_FILE = /path/to/topology-file # How many maximum number of handles to peers' services should be kept open at # any time. This number also keeps a check on the number of open descriptors as # opening a service connection results in opening a file descriptor. MAX_PARALLEL_SERVICE_CONNECTIONS = 256 # Size of the internal testbed cache. It is used to cache handles to peers # while trying to connect them. CACHE_SIZE = 30 # Maximum number of file descriptors a testbed controller is permitted to keep # open. MAX_OPEN_FDS = 512 # How long should we wait for testbed to setup while using helper functions # GNUNET_TESTBED_test_run() and GNUNET_TESTBED_run() SETUP_TIMEOUT = 5 m # Where should testbed write load statistics data # STATS_DIR = /tmp/load # What services should be shared among peers. # Format is "[] [] ...". The shared services are # started standalone without any other peer services or a hostkey. For this # reason, only services which doesn't depend on other services can only be # shared. Example: To share peerinfo among every 10 peers. The following spec # will start 5 peerinfo services when 50 peers are started: # # SHARED_SERVICES = peerinfo:10 # # To share multiple services # # SHARED_SERVICES = service1:n_share1 service2:n_share2 ... # # Default is to share no services SHARED_SERVICES = [testbed-logger] AUTOSTART = NO @UNIXONLY@ PORT = 2102 HOSTNAME = localhost BINARY = gnunet-service-testbed-logger UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-gnunet-testbed-logger.sock DIR = /tmp UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES [testbed-barrier] AUTOSTART = NO @UNIXONLY@ PORT = 2103 HOSTNAME = localhost UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-testbed-barrier.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # This section is related to configuring underlay restrictions to simulate # connectivity restrictions of NAT boxes [testbed-underlay] AUTOSTART = NO BINARY = gnunet-daemon-testbed-underlay # The sqlite3 database file containing information about what underlay # restrictions to apply # DBFILE = [latency-logger] AUTOSTART = NO BINARY = gnunet-daemon-latency-logger # The sqlite3 database file where the latency values are to be stored # DBFILE = gnunet-0.10.1/src/testbed/test_testbed_api_sd.c0000644000175000017500000000530512225777502016423 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_sd.c * @brief test cases for calculating standard deviation * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "testbed_api_sd.h" /** * Global return value */ static int ret; /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { struct SDHandle *h = GNUNET_TESTBED_SD_init_ (20); int sd; ret = 0; GNUNET_TESTBED_SD_add_data_ (h, 40); if (GNUNET_SYSERR != GNUNET_TESTBED_SD_deviation_factor_ (h, 10, &sd)) { GNUNET_break (0); ret = 1; goto err; } GNUNET_TESTBED_SD_add_data_ (h, 30); if (GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 80, &sd)) { GNUNET_break (0); ret = 1; goto err; } GNUNET_TESTBED_SD_add_data_ (h, 40); if ((GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 30, &sd)) || (-2 != sd)) { GNUNET_break (0); ret = 1; goto err; } GNUNET_TESTBED_SD_add_data_ (h, 10); GNUNET_TESTBED_SD_add_data_ (h, 30); if ((GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (h, 60, &sd)) || (3 != sd)) { GNUNET_break (0); ret = 1; goto err; } err: GNUNET_TESTBED_SD_destroy_ (h); } /** * Main function */ int main (int argc, char **argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int result; result = GNUNET_SYSERR; result = GNUNET_PROGRAM_run (argc, argv, "test_testbed_api_sd", "nohelp", options, &run, NULL); if ((GNUNET_OK != result)) return 1; return ret; } /* end of test_testbed_api_sd.c */ gnunet-0.10.1/src/testbed/Makefile.in0000644000175000017500000030647212320752064014315 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-testbed$(EXEEXT) \ gnunet-helper-testbed$(EXEEXT) \ gnunet-service-testbed-logger$(EXEEXT) \ gnunet-daemon-testbed-blacklist$(EXEEXT) $(am__EXEEXT_2) \ $(am__EXEEXT_3) bin_PROGRAMS = gnunet-testbed-profiler$(EXEEXT) noinst_PROGRAMS = $(am__EXEEXT_4) check_PROGRAMS = test_testbed_api_hosts$(EXEEXT) \ test_testbed_logger_api$(EXEEXT) \ test_gnunet_helper_testbed$(EXEEXT) \ test_testbed_api_controllerlink$(EXEEXT) \ test_testbed_api_2peers_1controller$(EXEEXT) \ test_testbed_api_3peers_3controllers$(EXEEXT) \ test_testbed_api$(EXEEXT) test_testbed_api_sd$(EXEEXT) \ test_testbed_api_operations$(EXEEXT) \ test_testbed_api_testbed_run$(EXEEXT) \ test_testbed_api_test$(EXEEXT) \ test_testbed_api_test_timeout$(EXEEXT) \ test_testbed_api_peer_reconfiguration$(EXEEXT) \ test_testbed_api_peers_manage_services$(EXEEXT) \ test_testbed_api_topology$(EXEEXT) \ test_testbed_api_topology_clique$(EXEEXT) \ test_testbed_api_testbed_run_topologyrandom$(EXEEXT) \ test_testbed_api_testbed_run_topologyline$(EXEEXT) \ test_testbed_api_testbed_run_topologyclique$(EXEEXT) \ test_testbed_api_testbed_run_topologyring$(EXEEXT) \ test_testbed_api_testbed_run_topologysmallworldring$(EXEEXT) \ test_testbed_api_testbed_run_topology2dtorus$(EXEEXT) \ test_testbed_api_testbed_run_topologysmallworld$(EXEEXT) \ test_testbed_api_testbed_run_topologyfromfile$(EXEEXT) \ test_testbed_api_testbed_run_topologyscalefree$(EXEEXT) \ test_testbed_api_testbed_run_waitforever$(EXEEXT) \ test_testbed_api_statistics$(EXEEXT) \ gnunet-service-test-barriers$(EXEEXT) \ test_testbed_api_barriers$(EXEEXT) $(am__EXEEXT_1) @ENABLE_TEST_RUN_TRUE@TESTS = test_testbed_api$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_logger_api$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_sd$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_operations$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_hosts$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_gnunet_helper_testbed$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_2peers_1controller$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_controllerlink$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_3peers_3controllers$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_test$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_test_timeout$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_statistics$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_peer_reconfiguration$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_peers_manage_services$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_topology$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_topology_clique$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topologyrandom$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topologyline$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topologyclique$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topologyring$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topology2dtorus$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topologysmallworld$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topologysmallworldring$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topologyfromfile$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_testbed_run_topologyscalefree$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_testbed_api_barriers$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_1) subdir = src/testbed DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/testbed.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = testbed.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunettestbed_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(am__DEPENDENCIES_1) am_libgnunettestbed_la_OBJECTS = testbed_api.lo testbed_api_hosts.lo \ testbed_api_operations.lo testbed_api_peers.lo \ testbed_api_services.lo testbed_api_statistics.lo \ testbed_api_testbed.lo testbed_api_test.lo \ testbed_api_topology.lo testbed_api_sd.lo \ testbed_api_barriers.lo libgnunettestbed_la_OBJECTS = $(am_libgnunettestbed_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunettestbed_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunettestbed_la_LDFLAGS) \ $(LDFLAGS) -o $@ libgnunettestbedlogger_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunettestbedlogger_la_OBJECTS = testbed_logger_api.lo libgnunettestbedlogger_la_OBJECTS = \ $(am_libgnunettestbedlogger_la_OBJECTS) libgnunettestbedlogger_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunettestbedlogger_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_SQLITE_TRUE@am__EXEEXT_1 = test_testbed_underlay$(EXEEXT) @HAVE_SQLITE_TRUE@am__EXEEXT_2 = \ @HAVE_SQLITE_TRUE@ gnunet-daemon-testbed-underlay$(EXEEXT) @HAVE_SQLITE_TRUE@am__EXEEXT_3 = \ @HAVE_SQLITE_TRUE@ gnunet-daemon-latency-logger$(EXEEXT) @HAVE_SQLITE_TRUE@am__EXEEXT_4 = generate-underlay-topology$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_generate_underlay_topology_OBJECTS = \ generate-underlay-topology.$(OBJEXT) generate_underlay_topology_OBJECTS = \ $(am_generate_underlay_topology_OBJECTS) am_gnunet_daemon_latency_logger_OBJECTS = \ gnunet-daemon-latency-logger.$(OBJEXT) gnunet_daemon_latency_logger_OBJECTS = \ $(am_gnunet_daemon_latency_logger_OBJECTS) am_gnunet_daemon_testbed_blacklist_OBJECTS = \ gnunet-daemon-testbed-blacklist.$(OBJEXT) gnunet_daemon_testbed_blacklist_OBJECTS = \ $(am_gnunet_daemon_testbed_blacklist_OBJECTS) am_gnunet_daemon_testbed_underlay_OBJECTS = \ gnunet-daemon-testbed-underlay.$(OBJEXT) gnunet_daemon_testbed_underlay_OBJECTS = \ $(am_gnunet_daemon_testbed_underlay_OBJECTS) am_gnunet_helper_testbed_OBJECTS = gnunet-helper-testbed.$(OBJEXT) gnunet_helper_testbed_OBJECTS = $(am_gnunet_helper_testbed_OBJECTS) am_gnunet_service_test_barriers_OBJECTS = \ gnunet-service-test-barriers.$(OBJEXT) gnunet_service_test_barriers_OBJECTS = \ $(am_gnunet_service_test_barriers_OBJECTS) gnunet_service_test_barriers_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_gnunet_service_testbed_OBJECTS = gnunet-service-testbed.$(OBJEXT) \ gnunet-service-testbed_links.$(OBJEXT) \ gnunet-service-testbed_peers.$(OBJEXT) \ gnunet-service-testbed_cache.$(OBJEXT) \ gnunet-service-testbed_oc.$(OBJEXT) \ gnunet-service-testbed_cpustatus.$(OBJEXT) \ gnunet-service-testbed_meminfo.$(OBJEXT) \ gnunet-service-testbed_barriers.$(OBJEXT) \ gnunet-service-testbed_connectionpool.$(OBJEXT) gnunet_service_testbed_OBJECTS = $(am_gnunet_service_testbed_OBJECTS) am_gnunet_service_testbed_logger_OBJECTS = \ gnunet-service-testbed-logger.$(OBJEXT) gnunet_service_testbed_logger_OBJECTS = \ $(am_gnunet_service_testbed_logger_OBJECTS) am_gnunet_testbed_profiler_OBJECTS = \ gnunet-testbed-profiler.$(OBJEXT) gnunet_testbed_profiler_OBJECTS = \ $(am_gnunet_testbed_profiler_OBJECTS) am_test_gnunet_helper_testbed_OBJECTS = \ test_gnunet_helper_testbed.$(OBJEXT) test_gnunet_helper_testbed_OBJECTS = \ $(am_test_gnunet_helper_testbed_OBJECTS) test_gnunet_helper_testbed_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la \ $(am__DEPENDENCIES_1) am_test_testbed_api_OBJECTS = test_testbed_api.$(OBJEXT) test_testbed_api_OBJECTS = $(am_test_testbed_api_OBJECTS) test_testbed_api_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/arm/libgnunetarm.la libgnunettestbed.la am_test_testbed_api_2peers_1controller_OBJECTS = \ test_testbed_api_2peers_1controller.$(OBJEXT) test_testbed_api_2peers_1controller_OBJECTS = \ $(am_test_testbed_api_2peers_1controller_OBJECTS) test_testbed_api_2peers_1controller_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la am_test_testbed_api_3peers_3controllers_OBJECTS = \ test_testbed_api_3peers_3controllers.$(OBJEXT) test_testbed_api_3peers_3controllers_OBJECTS = \ $(am_test_testbed_api_3peers_3controllers_OBJECTS) test_testbed_api_3peers_3controllers_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la am_test_testbed_api_barriers_OBJECTS = \ test_testbed_api_barriers.$(OBJEXT) test_testbed_api_barriers_OBJECTS = \ $(am_test_testbed_api_barriers_OBJECTS) am_test_testbed_api_controllerlink_OBJECTS = \ test_testbed_api_controllerlink.$(OBJEXT) test_testbed_api_controllerlink_OBJECTS = \ $(am_test_testbed_api_controllerlink_OBJECTS) test_testbed_api_controllerlink_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_hosts_OBJECTS = test_testbed_api_hosts.$(OBJEXT) test_testbed_api_hosts_OBJECTS = $(am_test_testbed_api_hosts_OBJECTS) test_testbed_api_hosts_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_operations_OBJECTS = \ test_testbed_api_operations.$(OBJEXT) test_testbed_api_operations_OBJECTS = \ $(am_test_testbed_api_operations_OBJECTS) test_testbed_api_operations_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_peer_reconfiguration_OBJECTS = \ test_testbed_api_peer_reconfiguration.$(OBJEXT) test_testbed_api_peer_reconfiguration_OBJECTS = \ $(am_test_testbed_api_peer_reconfiguration_OBJECTS) test_testbed_api_peer_reconfiguration_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_peers_manage_services_OBJECTS = \ test_testbed_api_peers_manage_services.$(OBJEXT) test_testbed_api_peers_manage_services_OBJECTS = \ $(am_test_testbed_api_peers_manage_services_OBJECTS) test_testbed_api_peers_manage_services_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_sd_OBJECTS = test_testbed_api_sd.$(OBJEXT) test_testbed_api_sd_OBJECTS = $(am_test_testbed_api_sd_OBJECTS) test_testbed_api_sd_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_statistics_OBJECTS = \ test_testbed_api_statistics.$(OBJEXT) test_testbed_api_statistics_OBJECTS = \ $(am_test_testbed_api_statistics_OBJECTS) test_testbed_api_statistics_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_test_OBJECTS = test_testbed_api_test.$(OBJEXT) test_testbed_api_test_OBJECTS = $(am_test_testbed_api_test_OBJECTS) test_testbed_api_test_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_test_timeout_OBJECTS = \ test_testbed_api_test_timeout.$(OBJEXT) test_testbed_api_test_timeout_OBJECTS = \ $(am_test_testbed_api_test_timeout_OBJECTS) test_testbed_api_test_timeout_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_OBJECTS = \ $(am_test_testbed_api_testbed_run_OBJECTS) test_testbed_api_testbed_run_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topology2dtorus_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topology2dtorus_OBJECTS = \ $(am_test_testbed_api_testbed_run_topology2dtorus_OBJECTS) test_testbed_api_testbed_run_topology2dtorus_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topologyclique_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topologyclique_OBJECTS = \ $(am_test_testbed_api_testbed_run_topologyclique_OBJECTS) test_testbed_api_testbed_run_topologyclique_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topologyfromfile_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topologyfromfile_OBJECTS = \ $(am_test_testbed_api_testbed_run_topologyfromfile_OBJECTS) test_testbed_api_testbed_run_topologyfromfile_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topologyline_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topologyline_OBJECTS = \ $(am_test_testbed_api_testbed_run_topologyline_OBJECTS) test_testbed_api_testbed_run_topologyline_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topologyrandom_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topologyrandom_OBJECTS = \ $(am_test_testbed_api_testbed_run_topologyrandom_OBJECTS) test_testbed_api_testbed_run_topologyrandom_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topologyring_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topologyring_OBJECTS = \ $(am_test_testbed_api_testbed_run_topologyring_OBJECTS) test_testbed_api_testbed_run_topologyring_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topologyscalefree_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topologyscalefree_OBJECTS = \ $(am_test_testbed_api_testbed_run_topologyscalefree_OBJECTS) test_testbed_api_testbed_run_topologyscalefree_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topologysmallworld_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topologysmallworld_OBJECTS = \ $(am_test_testbed_api_testbed_run_topologysmallworld_OBJECTS) test_testbed_api_testbed_run_topologysmallworld_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_topologysmallworldring_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_topologysmallworldring_OBJECTS = $(am_test_testbed_api_testbed_run_topologysmallworldring_OBJECTS) test_testbed_api_testbed_run_topologysmallworldring_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_testbed_run_waitforever_OBJECTS = \ test_testbed_api_testbed_run.$(OBJEXT) test_testbed_api_testbed_run_waitforever_OBJECTS = \ $(am_test_testbed_api_testbed_run_waitforever_OBJECTS) test_testbed_api_testbed_run_waitforever_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_topology_OBJECTS = \ test_testbed_api_topology.$(OBJEXT) test_testbed_api_topology_OBJECTS = \ $(am_test_testbed_api_topology_OBJECTS) test_testbed_api_topology_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_api_topology_clique_OBJECTS = \ test_testbed_api_topology_clique.$(OBJEXT) test_testbed_api_topology_clique_OBJECTS = \ $(am_test_testbed_api_topology_clique_OBJECTS) test_testbed_api_topology_clique_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la am_test_testbed_logger_api_OBJECTS = \ test_testbed_logger_api.$(OBJEXT) test_testbed_logger_api_OBJECTS = \ $(am_test_testbed_logger_api_OBJECTS) test_testbed_logger_api_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbedlogger.la am_test_testbed_underlay_OBJECTS = test_testbed_underlay.$(OBJEXT) test_testbed_underlay_OBJECTS = $(am_test_testbed_underlay_OBJECTS) test_testbed_underlay_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunettestbed.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunettestbed_la_SOURCES) \ $(libgnunettestbedlogger_la_SOURCES) \ $(generate_underlay_topology_SOURCES) \ $(gnunet_daemon_latency_logger_SOURCES) \ $(gnunet_daemon_testbed_blacklist_SOURCES) \ $(gnunet_daemon_testbed_underlay_SOURCES) \ $(gnunet_helper_testbed_SOURCES) \ $(gnunet_service_test_barriers_SOURCES) \ $(gnunet_service_testbed_SOURCES) \ $(gnunet_service_testbed_logger_SOURCES) \ $(gnunet_testbed_profiler_SOURCES) \ $(test_gnunet_helper_testbed_SOURCES) \ $(test_testbed_api_SOURCES) \ $(test_testbed_api_2peers_1controller_SOURCES) \ $(test_testbed_api_3peers_3controllers_SOURCES) \ $(test_testbed_api_barriers_SOURCES) \ $(test_testbed_api_controllerlink_SOURCES) \ $(test_testbed_api_hosts_SOURCES) \ $(test_testbed_api_operations_SOURCES) \ $(test_testbed_api_peer_reconfiguration_SOURCES) \ $(test_testbed_api_peers_manage_services_SOURCES) \ $(test_testbed_api_sd_SOURCES) \ $(test_testbed_api_statistics_SOURCES) \ $(test_testbed_api_test_SOURCES) \ $(test_testbed_api_test_timeout_SOURCES) \ $(test_testbed_api_testbed_run_SOURCES) \ $(test_testbed_api_testbed_run_topology2dtorus_SOURCES) \ $(test_testbed_api_testbed_run_topologyclique_SOURCES) \ $(test_testbed_api_testbed_run_topologyfromfile_SOURCES) \ $(test_testbed_api_testbed_run_topologyline_SOURCES) \ $(test_testbed_api_testbed_run_topologyrandom_SOURCES) \ $(test_testbed_api_testbed_run_topologyring_SOURCES) \ $(test_testbed_api_testbed_run_topologyscalefree_SOURCES) \ $(test_testbed_api_testbed_run_topologysmallworld_SOURCES) \ $(test_testbed_api_testbed_run_topologysmallworldring_SOURCES) \ $(test_testbed_api_testbed_run_waitforever_SOURCES) \ $(test_testbed_api_topology_SOURCES) \ $(test_testbed_api_topology_clique_SOURCES) \ $(test_testbed_logger_api_SOURCES) \ $(test_testbed_underlay_SOURCES) DIST_SOURCES = $(libgnunettestbed_la_SOURCES) \ $(libgnunettestbedlogger_la_SOURCES) \ $(generate_underlay_topology_SOURCES) \ $(gnunet_daemon_latency_logger_SOURCES) \ $(gnunet_daemon_testbed_blacklist_SOURCES) \ $(gnunet_daemon_testbed_underlay_SOURCES) \ $(gnunet_helper_testbed_SOURCES) \ $(gnunet_service_test_barriers_SOURCES) \ $(gnunet_service_testbed_SOURCES) \ $(gnunet_service_testbed_logger_SOURCES) \ $(gnunet_testbed_profiler_SOURCES) \ $(test_gnunet_helper_testbed_SOURCES) \ $(test_testbed_api_SOURCES) \ $(test_testbed_api_2peers_1controller_SOURCES) \ $(test_testbed_api_3peers_3controllers_SOURCES) \ $(test_testbed_api_barriers_SOURCES) \ $(test_testbed_api_controllerlink_SOURCES) \ $(test_testbed_api_hosts_SOURCES) \ $(test_testbed_api_operations_SOURCES) \ $(test_testbed_api_peer_reconfiguration_SOURCES) \ $(test_testbed_api_peers_manage_services_SOURCES) \ $(test_testbed_api_sd_SOURCES) \ $(test_testbed_api_statistics_SOURCES) \ $(test_testbed_api_test_SOURCES) \ $(test_testbed_api_test_timeout_SOURCES) \ $(test_testbed_api_testbed_run_SOURCES) \ $(test_testbed_api_testbed_run_topology2dtorus_SOURCES) \ $(test_testbed_api_testbed_run_topologyclique_SOURCES) \ $(test_testbed_api_testbed_run_topologyfromfile_SOURCES) \ $(test_testbed_api_testbed_run_topologyline_SOURCES) \ $(test_testbed_api_testbed_run_topologyrandom_SOURCES) \ $(test_testbed_api_testbed_run_topologyring_SOURCES) \ $(test_testbed_api_testbed_run_topologyscalefree_SOURCES) \ $(test_testbed_api_testbed_run_topologysmallworld_SOURCES) \ $(test_testbed_api_testbed_run_topologysmallworldring_SOURCES) \ $(test_testbed_api_testbed_run_waitforever_SOURCES) \ $(test_testbed_api_topology_SOURCES) \ $(test_testbed_api_topology_clique_SOURCES) \ $(test_testbed_logger_api_SOURCES) \ $(test_testbed_underlay_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ testbed.conf @HAVE_SQLITE_TRUE@underlay_daemon = gnunet-daemon-testbed-underlay @HAVE_SQLITE_TRUE@latency_logger = gnunet-daemon-latency-logger @HAVE_SQLITE_TRUE@generate_underlay = generate-underlay-topology @HAVE_SQLITE_TRUE@underlay_testcases = test_testbed_underlay gnunet_service_testbed_SOURCES = \ gnunet-service-testbed.c gnunet-service-testbed.h \ gnunet-service-testbed_links.c gnunet-service-testbed_links.h \ gnunet-service-testbed_peers.c \ gnunet-service-testbed_cache.c \ gnunet-service-testbed_oc.c \ gnunet-service-testbed_cpustatus.c \ gnunet-service-testbed_meminfo.c gnunet-service-testbed_meminfo.h \ gnunet-service-testbed_barriers.c gnunet-service-testbed_barriers.h \ gnunet-service-testbed_connectionpool.c gnunet-service-testbed_connectionpool.h gnunet_service_testbed_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/arm/libgnunetarm.la \ $(LTLIBINTL) $(Z_LIBS) gnunet_service_testbed_DEPENDENCIES = \ libgnunettestbed.la gnunet_service_testbed_logger_SOURCES = \ gnunet-service-testbed-logger.c gnunet_service_testbed_logger_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_service_testbed_logger_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_testbed_profiler_SOURCES = \ gnunet-testbed-profiler.c gnunet_testbed_profiler_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la gnunet_testbed_profiler_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la gnunet_helper_testbed_SOURCES = \ gnunet-helper-testbed.c gnunet_helper_testbed_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la \ $(LTLIBINTL) $(Z_LIBS) gnunet_helper_testbed_DEPENDENCIES = \ gnunet-service-testbed.$(OBJEXT) \ libgnunettestbed.la gnunet_daemon_testbed_blacklist_SOURCES = gnunet-daemon-testbed-blacklist.c gnunet_daemon_testbed_blacklist_LDADD = $(XLIB) \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) gnunet_daemon_testbed_blacklist_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_daemon_testbed_underlay_SOURCES = gnunet-daemon-testbed-underlay.c gnunet_daemon_testbed_underlay_LDADD = $(XLIB) \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) -lsqlite3 gnunet_daemon_testbed_underlay_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_daemon_latency_logger_SOURCES = gnunet-daemon-latency-logger.c gnunet_daemon_latency_logger_LDADD = $(XLIB) \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) -lsqlite3 gnunet_daemon_latency_logger_DEPENDENCIES = \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/util/libgnunetutil.la lib_LTLIBRARIES = \ libgnunettestbed.la \ libgnunettestbedlogger.la libgnunettestbed_la_SOURCES = \ testbed_api.c testbed_api.h testbed.h \ testbed_api_hosts.c testbed_api_hosts.h testbed_helper.h \ testbed_api_operations.c testbed_api_operations.h \ testbed_api_peers.c testbed_api_peers.h \ testbed_api_services.c \ testbed_api_statistics.c \ testbed_api_testbed.c \ testbed_api_test.c \ testbed_api_topology.c testbed_api_topology.h \ testbed_api_sd.c testbed_api_sd.h \ testbed_api_barriers.c testbed_api_barriers.h libgnunettestbed_la_LIBADD = $(XLIB) \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ -lm \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(LTLIBINTL) libgnunettestbed_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 libgnunettestbedlogger_la_SOURCES = \ testbed_logger_api.c libgnunettestbedlogger_la_LIBADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunettestbedlogger_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 generate_underlay_topology_SOURCES = generate-underlay-topology.c generate_underlay_topology_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(LTLIBINTL) -lsqlite3 generate_underlay_topology_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; test_testbed_api_hosts_SOURCES = \ test_testbed_api_hosts.c test_testbed_api_hosts_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_SOURCES = \ test_testbed_api.c test_testbed_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/arm/libgnunetarm.la \ libgnunettestbed.la test_testbed_logger_api_SOURCES = \ test_testbed_logger_api.c test_testbed_logger_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbedlogger.la test_testbed_api_sd_SOURCES = \ test_testbed_api_sd.c test_testbed_api_sd_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_2peers_1controller_SOURCES = \ test_testbed_api_2peers_1controller.c test_testbed_api_2peers_1controller_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la test_testbed_api_3peers_3controllers_SOURCES = \ test_testbed_api_3peers_3controllers.c test_testbed_api_3peers_3controllers_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la test_testbed_api_operations_SOURCES = \ test_testbed_api_operations.c test_testbed_api_operations_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_controllerlink_SOURCES = \ test_testbed_api_controllerlink.c test_testbed_api_controllerlink_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_test_SOURCES = \ test_testbed_api_test.c test_testbed_api_test_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_test_timeout_SOURCES = \ test_testbed_api_test_timeout.c test_testbed_api_test_timeout_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_topology_SOURCES = \ test_testbed_api_topology.c test_testbed_api_topology_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_topology_clique_SOURCES = \ test_testbed_api_topology_clique.c test_testbed_api_topology_clique_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_gnunet_helper_testbed_SOURCES = \ test_gnunet_helper_testbed.c test_gnunet_helper_testbed_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la \ $(Z_LIBS) test_testbed_api_testbed_run_topologyrandom_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyrandom_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyline_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyline_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyclique_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyclique_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyring_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyring_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologysmallworldring_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologysmallworldring_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topology2dtorus_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topology2dtorus_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologysmallworld_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologysmallworld_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyfromfile_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyfromfile_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyscalefree_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyscalefree_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_waitforever_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_waitforever_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_statistics_SOURCES = \ test_testbed_api_statistics.c test_testbed_api_statistics_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_peers_manage_services_SOURCES = \ test_testbed_api_peers_manage_services.c test_testbed_api_peers_manage_services_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_peer_reconfiguration_SOURCES = \ test_testbed_api_peer_reconfiguration.c test_testbed_api_peer_reconfiguration_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_barriers_SOURCES = \ test_testbed_api_barriers.c \ test_testbed_api_barriers.h test_testbed_api_barriers_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_barriers_DEPENDENCIES = \ gnunet-service-test-barriers$(EXEEXT) gnunet_service_test_barriers_SOURCES = \ gnunet-service-test-barriers.c \ test_testbed_api_barriers.h gnunet_service_test_barriers_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_underlay_SOURCES = \ test_testbed_underlay.c test_testbed_underlay_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la EXTRA_DIST = \ test_testbed_api.conf \ test_testbed_api_statistics.conf \ test_testbed_api_test_timeout.conf \ test_testbed_api_template.conf \ test_testbed_logger_api.conf \ test_testbed_api_testbed_run_topologyring.conf \ test_testbed_api_testbed_run_topologyclique.conf \ test_testbed_api_testbed_run_topologyline.conf \ test_testbed_api_testbed_run_topologyrandom.conf \ test_testbed_api_testbed_run_topologysmallworldring.conf \ test_testbed_api_testbed_run_topology2dtorus.conf \ test_testbed_api_testbed_run_topologysmallworld.conf \ test_testbed_api_testbed_run_topologyfromfile.conf \ test_testbed_api_testbed_run_topologyscalefree.conf \ test_testbed_api_barriers.conf.in \ overlay_topology.txt \ sample_hosts.txt \ sample.job \ test_testbed_underlay.conf.in \ test-underlay.sqlite all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/testbed/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/testbed/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): testbed.conf: $(top_builddir)/config.status $(srcdir)/testbed.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunettestbed.la: $(libgnunettestbed_la_OBJECTS) $(libgnunettestbed_la_DEPENDENCIES) $(EXTRA_libgnunettestbed_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunettestbed_la_LINK) -rpath $(libdir) $(libgnunettestbed_la_OBJECTS) $(libgnunettestbed_la_LIBADD) $(LIBS) libgnunettestbedlogger.la: $(libgnunettestbedlogger_la_OBJECTS) $(libgnunettestbedlogger_la_DEPENDENCIES) $(EXTRA_libgnunettestbedlogger_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunettestbedlogger_la_LINK) -rpath $(libdir) $(libgnunettestbedlogger_la_OBJECTS) $(libgnunettestbedlogger_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list generate-underlay-topology$(EXEEXT): $(generate_underlay_topology_OBJECTS) $(generate_underlay_topology_DEPENDENCIES) $(EXTRA_generate_underlay_topology_DEPENDENCIES) @rm -f generate-underlay-topology$(EXEEXT) $(AM_V_CCLD)$(LINK) $(generate_underlay_topology_OBJECTS) $(generate_underlay_topology_LDADD) $(LIBS) gnunet-daemon-latency-logger$(EXEEXT): $(gnunet_daemon_latency_logger_OBJECTS) $(gnunet_daemon_latency_logger_DEPENDENCIES) $(EXTRA_gnunet_daemon_latency_logger_DEPENDENCIES) @rm -f gnunet-daemon-latency-logger$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_latency_logger_OBJECTS) $(gnunet_daemon_latency_logger_LDADD) $(LIBS) gnunet-daemon-testbed-blacklist$(EXEEXT): $(gnunet_daemon_testbed_blacklist_OBJECTS) $(gnunet_daemon_testbed_blacklist_DEPENDENCIES) $(EXTRA_gnunet_daemon_testbed_blacklist_DEPENDENCIES) @rm -f gnunet-daemon-testbed-blacklist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_testbed_blacklist_OBJECTS) $(gnunet_daemon_testbed_blacklist_LDADD) $(LIBS) gnunet-daemon-testbed-underlay$(EXEEXT): $(gnunet_daemon_testbed_underlay_OBJECTS) $(gnunet_daemon_testbed_underlay_DEPENDENCIES) $(EXTRA_gnunet_daemon_testbed_underlay_DEPENDENCIES) @rm -f gnunet-daemon-testbed-underlay$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_testbed_underlay_OBJECTS) $(gnunet_daemon_testbed_underlay_LDADD) $(LIBS) gnunet-helper-testbed$(EXEEXT): $(gnunet_helper_testbed_OBJECTS) $(gnunet_helper_testbed_DEPENDENCIES) $(EXTRA_gnunet_helper_testbed_DEPENDENCIES) @rm -f gnunet-helper-testbed$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_helper_testbed_OBJECTS) $(gnunet_helper_testbed_LDADD) $(LIBS) gnunet-service-test-barriers$(EXEEXT): $(gnunet_service_test_barriers_OBJECTS) $(gnunet_service_test_barriers_DEPENDENCIES) $(EXTRA_gnunet_service_test_barriers_DEPENDENCIES) @rm -f gnunet-service-test-barriers$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_test_barriers_OBJECTS) $(gnunet_service_test_barriers_LDADD) $(LIBS) gnunet-service-testbed$(EXEEXT): $(gnunet_service_testbed_OBJECTS) $(gnunet_service_testbed_DEPENDENCIES) $(EXTRA_gnunet_service_testbed_DEPENDENCIES) @rm -f gnunet-service-testbed$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_testbed_OBJECTS) $(gnunet_service_testbed_LDADD) $(LIBS) gnunet-service-testbed-logger$(EXEEXT): $(gnunet_service_testbed_logger_OBJECTS) $(gnunet_service_testbed_logger_DEPENDENCIES) $(EXTRA_gnunet_service_testbed_logger_DEPENDENCIES) @rm -f gnunet-service-testbed-logger$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_testbed_logger_OBJECTS) $(gnunet_service_testbed_logger_LDADD) $(LIBS) gnunet-testbed-profiler$(EXEEXT): $(gnunet_testbed_profiler_OBJECTS) $(gnunet_testbed_profiler_DEPENDENCIES) $(EXTRA_gnunet_testbed_profiler_DEPENDENCIES) @rm -f gnunet-testbed-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_testbed_profiler_OBJECTS) $(gnunet_testbed_profiler_LDADD) $(LIBS) test_gnunet_helper_testbed$(EXEEXT): $(test_gnunet_helper_testbed_OBJECTS) $(test_gnunet_helper_testbed_DEPENDENCIES) $(EXTRA_test_gnunet_helper_testbed_DEPENDENCIES) @rm -f test_gnunet_helper_testbed$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_helper_testbed_OBJECTS) $(test_gnunet_helper_testbed_LDADD) $(LIBS) test_testbed_api$(EXEEXT): $(test_testbed_api_OBJECTS) $(test_testbed_api_DEPENDENCIES) $(EXTRA_test_testbed_api_DEPENDENCIES) @rm -f test_testbed_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_OBJECTS) $(test_testbed_api_LDADD) $(LIBS) test_testbed_api_2peers_1controller$(EXEEXT): $(test_testbed_api_2peers_1controller_OBJECTS) $(test_testbed_api_2peers_1controller_DEPENDENCIES) $(EXTRA_test_testbed_api_2peers_1controller_DEPENDENCIES) @rm -f test_testbed_api_2peers_1controller$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_2peers_1controller_OBJECTS) $(test_testbed_api_2peers_1controller_LDADD) $(LIBS) test_testbed_api_3peers_3controllers$(EXEEXT): $(test_testbed_api_3peers_3controllers_OBJECTS) $(test_testbed_api_3peers_3controllers_DEPENDENCIES) $(EXTRA_test_testbed_api_3peers_3controllers_DEPENDENCIES) @rm -f test_testbed_api_3peers_3controllers$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_3peers_3controllers_OBJECTS) $(test_testbed_api_3peers_3controllers_LDADD) $(LIBS) test_testbed_api_barriers$(EXEEXT): $(test_testbed_api_barriers_OBJECTS) $(test_testbed_api_barriers_DEPENDENCIES) $(EXTRA_test_testbed_api_barriers_DEPENDENCIES) @rm -f test_testbed_api_barriers$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_barriers_OBJECTS) $(test_testbed_api_barriers_LDADD) $(LIBS) test_testbed_api_controllerlink$(EXEEXT): $(test_testbed_api_controllerlink_OBJECTS) $(test_testbed_api_controllerlink_DEPENDENCIES) $(EXTRA_test_testbed_api_controllerlink_DEPENDENCIES) @rm -f test_testbed_api_controllerlink$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_controllerlink_OBJECTS) $(test_testbed_api_controllerlink_LDADD) $(LIBS) test_testbed_api_hosts$(EXEEXT): $(test_testbed_api_hosts_OBJECTS) $(test_testbed_api_hosts_DEPENDENCIES) $(EXTRA_test_testbed_api_hosts_DEPENDENCIES) @rm -f test_testbed_api_hosts$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_hosts_OBJECTS) $(test_testbed_api_hosts_LDADD) $(LIBS) test_testbed_api_operations$(EXEEXT): $(test_testbed_api_operations_OBJECTS) $(test_testbed_api_operations_DEPENDENCIES) $(EXTRA_test_testbed_api_operations_DEPENDENCIES) @rm -f test_testbed_api_operations$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_operations_OBJECTS) $(test_testbed_api_operations_LDADD) $(LIBS) test_testbed_api_peer_reconfiguration$(EXEEXT): $(test_testbed_api_peer_reconfiguration_OBJECTS) $(test_testbed_api_peer_reconfiguration_DEPENDENCIES) $(EXTRA_test_testbed_api_peer_reconfiguration_DEPENDENCIES) @rm -f test_testbed_api_peer_reconfiguration$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_peer_reconfiguration_OBJECTS) $(test_testbed_api_peer_reconfiguration_LDADD) $(LIBS) test_testbed_api_peers_manage_services$(EXEEXT): $(test_testbed_api_peers_manage_services_OBJECTS) $(test_testbed_api_peers_manage_services_DEPENDENCIES) $(EXTRA_test_testbed_api_peers_manage_services_DEPENDENCIES) @rm -f test_testbed_api_peers_manage_services$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_peers_manage_services_OBJECTS) $(test_testbed_api_peers_manage_services_LDADD) $(LIBS) test_testbed_api_sd$(EXEEXT): $(test_testbed_api_sd_OBJECTS) $(test_testbed_api_sd_DEPENDENCIES) $(EXTRA_test_testbed_api_sd_DEPENDENCIES) @rm -f test_testbed_api_sd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_sd_OBJECTS) $(test_testbed_api_sd_LDADD) $(LIBS) test_testbed_api_statistics$(EXEEXT): $(test_testbed_api_statistics_OBJECTS) $(test_testbed_api_statistics_DEPENDENCIES) $(EXTRA_test_testbed_api_statistics_DEPENDENCIES) @rm -f test_testbed_api_statistics$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_statistics_OBJECTS) $(test_testbed_api_statistics_LDADD) $(LIBS) test_testbed_api_test$(EXEEXT): $(test_testbed_api_test_OBJECTS) $(test_testbed_api_test_DEPENDENCIES) $(EXTRA_test_testbed_api_test_DEPENDENCIES) @rm -f test_testbed_api_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_test_OBJECTS) $(test_testbed_api_test_LDADD) $(LIBS) test_testbed_api_test_timeout$(EXEEXT): $(test_testbed_api_test_timeout_OBJECTS) $(test_testbed_api_test_timeout_DEPENDENCIES) $(EXTRA_test_testbed_api_test_timeout_DEPENDENCIES) @rm -f test_testbed_api_test_timeout$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_test_timeout_OBJECTS) $(test_testbed_api_test_timeout_LDADD) $(LIBS) test_testbed_api_testbed_run$(EXEEXT): $(test_testbed_api_testbed_run_OBJECTS) $(test_testbed_api_testbed_run_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_DEPENDENCIES) @rm -f test_testbed_api_testbed_run$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_OBJECTS) $(test_testbed_api_testbed_run_LDADD) $(LIBS) test_testbed_api_testbed_run_topology2dtorus$(EXEEXT): $(test_testbed_api_testbed_run_topology2dtorus_OBJECTS) $(test_testbed_api_testbed_run_topology2dtorus_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topology2dtorus_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topology2dtorus$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topology2dtorus_OBJECTS) $(test_testbed_api_testbed_run_topology2dtorus_LDADD) $(LIBS) test_testbed_api_testbed_run_topologyclique$(EXEEXT): $(test_testbed_api_testbed_run_topologyclique_OBJECTS) $(test_testbed_api_testbed_run_topologyclique_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topologyclique_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topologyclique$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topologyclique_OBJECTS) $(test_testbed_api_testbed_run_topologyclique_LDADD) $(LIBS) test_testbed_api_testbed_run_topologyfromfile$(EXEEXT): $(test_testbed_api_testbed_run_topologyfromfile_OBJECTS) $(test_testbed_api_testbed_run_topologyfromfile_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topologyfromfile_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topologyfromfile$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topologyfromfile_OBJECTS) $(test_testbed_api_testbed_run_topologyfromfile_LDADD) $(LIBS) test_testbed_api_testbed_run_topologyline$(EXEEXT): $(test_testbed_api_testbed_run_topologyline_OBJECTS) $(test_testbed_api_testbed_run_topologyline_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topologyline_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topologyline$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topologyline_OBJECTS) $(test_testbed_api_testbed_run_topologyline_LDADD) $(LIBS) test_testbed_api_testbed_run_topologyrandom$(EXEEXT): $(test_testbed_api_testbed_run_topologyrandom_OBJECTS) $(test_testbed_api_testbed_run_topologyrandom_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topologyrandom_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topologyrandom$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topologyrandom_OBJECTS) $(test_testbed_api_testbed_run_topologyrandom_LDADD) $(LIBS) test_testbed_api_testbed_run_topologyring$(EXEEXT): $(test_testbed_api_testbed_run_topologyring_OBJECTS) $(test_testbed_api_testbed_run_topologyring_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topologyring_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topologyring$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topologyring_OBJECTS) $(test_testbed_api_testbed_run_topologyring_LDADD) $(LIBS) test_testbed_api_testbed_run_topologyscalefree$(EXEEXT): $(test_testbed_api_testbed_run_topologyscalefree_OBJECTS) $(test_testbed_api_testbed_run_topologyscalefree_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topologyscalefree_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topologyscalefree$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topologyscalefree_OBJECTS) $(test_testbed_api_testbed_run_topologyscalefree_LDADD) $(LIBS) test_testbed_api_testbed_run_topologysmallworld$(EXEEXT): $(test_testbed_api_testbed_run_topologysmallworld_OBJECTS) $(test_testbed_api_testbed_run_topologysmallworld_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topologysmallworld_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topologysmallworld$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topologysmallworld_OBJECTS) $(test_testbed_api_testbed_run_topologysmallworld_LDADD) $(LIBS) test_testbed_api_testbed_run_topologysmallworldring$(EXEEXT): $(test_testbed_api_testbed_run_topologysmallworldring_OBJECTS) $(test_testbed_api_testbed_run_topologysmallworldring_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_topologysmallworldring_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_topologysmallworldring$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_topologysmallworldring_OBJECTS) $(test_testbed_api_testbed_run_topologysmallworldring_LDADD) $(LIBS) test_testbed_api_testbed_run_waitforever$(EXEEXT): $(test_testbed_api_testbed_run_waitforever_OBJECTS) $(test_testbed_api_testbed_run_waitforever_DEPENDENCIES) $(EXTRA_test_testbed_api_testbed_run_waitforever_DEPENDENCIES) @rm -f test_testbed_api_testbed_run_waitforever$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_testbed_run_waitforever_OBJECTS) $(test_testbed_api_testbed_run_waitforever_LDADD) $(LIBS) test_testbed_api_topology$(EXEEXT): $(test_testbed_api_topology_OBJECTS) $(test_testbed_api_topology_DEPENDENCIES) $(EXTRA_test_testbed_api_topology_DEPENDENCIES) @rm -f test_testbed_api_topology$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_topology_OBJECTS) $(test_testbed_api_topology_LDADD) $(LIBS) test_testbed_api_topology_clique$(EXEEXT): $(test_testbed_api_topology_clique_OBJECTS) $(test_testbed_api_topology_clique_DEPENDENCIES) $(EXTRA_test_testbed_api_topology_clique_DEPENDENCIES) @rm -f test_testbed_api_topology_clique$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_api_topology_clique_OBJECTS) $(test_testbed_api_topology_clique_LDADD) $(LIBS) test_testbed_logger_api$(EXEEXT): $(test_testbed_logger_api_OBJECTS) $(test_testbed_logger_api_DEPENDENCIES) $(EXTRA_test_testbed_logger_api_DEPENDENCIES) @rm -f test_testbed_logger_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_logger_api_OBJECTS) $(test_testbed_logger_api_LDADD) $(LIBS) test_testbed_underlay$(EXEEXT): $(test_testbed_underlay_OBJECTS) $(test_testbed_underlay_DEPENDENCIES) $(EXTRA_test_testbed_underlay_DEPENDENCIES) @rm -f test_testbed_underlay$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_testbed_underlay_OBJECTS) $(test_testbed_underlay_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-underlay-topology.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-latency-logger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-testbed-blacklist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-testbed-underlay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-testbed.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-test-barriers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed-logger.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed_barriers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed_cache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed_connectionpool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed_cpustatus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed_links.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed_meminfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed_oc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-testbed_peers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-testbed-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_helper_testbed.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_2peers_1controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_3peers_3controllers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_barriers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_controllerlink.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_hosts.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_operations.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_peer_reconfiguration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_peers_manage_services.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_sd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_statistics.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_test_timeout.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_testbed_run.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_topology.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_api_topology_clique.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_logger_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_testbed_underlay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_barriers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_hosts.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_operations.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_peers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_sd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_services.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_statistics.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_test.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_testbed.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_api_topology.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testbed_logger_api.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_testbed_api.log: test_testbed_api$(EXEEXT) @p='test_testbed_api$(EXEEXT)'; \ b='test_testbed_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_logger_api.log: test_testbed_logger_api$(EXEEXT) @p='test_testbed_logger_api$(EXEEXT)'; \ b='test_testbed_logger_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_sd.log: test_testbed_api_sd$(EXEEXT) @p='test_testbed_api_sd$(EXEEXT)'; \ b='test_testbed_api_sd'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_operations.log: test_testbed_api_operations$(EXEEXT) @p='test_testbed_api_operations$(EXEEXT)'; \ b='test_testbed_api_operations'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_hosts.log: test_testbed_api_hosts$(EXEEXT) @p='test_testbed_api_hosts$(EXEEXT)'; \ b='test_testbed_api_hosts'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_helper_testbed.log: test_gnunet_helper_testbed$(EXEEXT) @p='test_gnunet_helper_testbed$(EXEEXT)'; \ b='test_gnunet_helper_testbed'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_2peers_1controller.log: test_testbed_api_2peers_1controller$(EXEEXT) @p='test_testbed_api_2peers_1controller$(EXEEXT)'; \ b='test_testbed_api_2peers_1controller'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_controllerlink.log: test_testbed_api_controllerlink$(EXEEXT) @p='test_testbed_api_controllerlink$(EXEEXT)'; \ b='test_testbed_api_controllerlink'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_3peers_3controllers.log: test_testbed_api_3peers_3controllers$(EXEEXT) @p='test_testbed_api_3peers_3controllers$(EXEEXT)'; \ b='test_testbed_api_3peers_3controllers'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run.log: test_testbed_api_testbed_run$(EXEEXT) @p='test_testbed_api_testbed_run$(EXEEXT)'; \ b='test_testbed_api_testbed_run'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_test.log: test_testbed_api_test$(EXEEXT) @p='test_testbed_api_test$(EXEEXT)'; \ b='test_testbed_api_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_test_timeout.log: test_testbed_api_test_timeout$(EXEEXT) @p='test_testbed_api_test_timeout$(EXEEXT)'; \ b='test_testbed_api_test_timeout'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_statistics.log: test_testbed_api_statistics$(EXEEXT) @p='test_testbed_api_statistics$(EXEEXT)'; \ b='test_testbed_api_statistics'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_peer_reconfiguration.log: test_testbed_api_peer_reconfiguration$(EXEEXT) @p='test_testbed_api_peer_reconfiguration$(EXEEXT)'; \ b='test_testbed_api_peer_reconfiguration'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_peers_manage_services.log: test_testbed_api_peers_manage_services$(EXEEXT) @p='test_testbed_api_peers_manage_services$(EXEEXT)'; \ b='test_testbed_api_peers_manage_services'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_topology.log: test_testbed_api_topology$(EXEEXT) @p='test_testbed_api_topology$(EXEEXT)'; \ b='test_testbed_api_topology'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_topology_clique.log: test_testbed_api_topology_clique$(EXEEXT) @p='test_testbed_api_topology_clique$(EXEEXT)'; \ b='test_testbed_api_topology_clique'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topologyrandom.log: test_testbed_api_testbed_run_topologyrandom$(EXEEXT) @p='test_testbed_api_testbed_run_topologyrandom$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topologyrandom'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topologyline.log: test_testbed_api_testbed_run_topologyline$(EXEEXT) @p='test_testbed_api_testbed_run_topologyline$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topologyline'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topologyclique.log: test_testbed_api_testbed_run_topologyclique$(EXEEXT) @p='test_testbed_api_testbed_run_topologyclique$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topologyclique'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topologyring.log: test_testbed_api_testbed_run_topologyring$(EXEEXT) @p='test_testbed_api_testbed_run_topologyring$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topologyring'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topology2dtorus.log: test_testbed_api_testbed_run_topology2dtorus$(EXEEXT) @p='test_testbed_api_testbed_run_topology2dtorus$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topology2dtorus'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topologysmallworld.log: test_testbed_api_testbed_run_topologysmallworld$(EXEEXT) @p='test_testbed_api_testbed_run_topologysmallworld$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topologysmallworld'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topologysmallworldring.log: test_testbed_api_testbed_run_topologysmallworldring$(EXEEXT) @p='test_testbed_api_testbed_run_topologysmallworldring$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topologysmallworldring'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topologyfromfile.log: test_testbed_api_testbed_run_topologyfromfile$(EXEEXT) @p='test_testbed_api_testbed_run_topologyfromfile$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topologyfromfile'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_testbed_run_topologyscalefree.log: test_testbed_api_testbed_run_topologyscalefree$(EXEEXT) @p='test_testbed_api_testbed_run_topologyscalefree$(EXEEXT)'; \ b='test_testbed_api_testbed_run_topologyscalefree'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_api_barriers.log: test_testbed_api_barriers$(EXEEXT) @p='test_testbed_api_barriers$(EXEEXT)'; \ b='test_testbed_api_barriers'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_testbed_underlay.log: test_testbed_underlay$(EXEEXT) @p='test_testbed_underlay$(EXEEXT)'; \ b='test_testbed_underlay'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/testbed/gnunet-testbed-profiler.c0000644000175000017500000002061012261236531017147 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-testbed-profiler.c * @brief Profiling driver for the testbed. * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "testbed_api_hosts.h" /** * Generic loggins shorthand */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Handle to global configuration */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * Peer linking - topology operation */ struct GNUNET_TESTBED_Operation *topology_op; /** * Name of the file with the hosts to run the test over (configuration option). * It will be NULL if ENABLE_LL is set */ static char *hosts_file; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * Shutdown task identifier */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Global event mask for all testbed events */ uint64_t event_mask; /** * Number of peers to be started by the profiler */ static unsigned int num_peers; /** * Number of timeout failures to tolerate */ static unsigned int num_cont_fails; /** * Continuous failures during overlay connect operations */ static unsigned int cont_fails; /** * Links which are successfully established */ static unsigned int established_links; /** * Links which are not successfully established */ static unsigned int failed_links; /** * Global testing status */ static int result; /** * Are we running non interactively */ static int noninteractive; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != abort_task) { GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != cfg) { GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; } GNUNET_SCHEDULER_shutdown (); /* Stop scheduler to shutdown testbed run */ } /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_WARNING, "Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; result = GNUNET_SYSERR; if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } /** * Function to print summary about how many overlay links we have made and how * many failed */ static void print_overlay_links_summary () { static int printed_already; if (GNUNET_YES == printed_already) return; printed_already = GNUNET_YES; printf ("%u links succeeded\n", established_links); printf ("%u links failed due to timeouts\n", failed_links); } /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_OPERATION_FINISHED: /* Control reaches here when a peer linking operation fails */ if (NULL != event->details.operation_finished.emsg) { printf ("F"); fflush (stdout); failed_links++; if (++cont_fails > num_cont_fails) { printf ("\nAborting due to very high failure rate\n"); print_overlay_links_summary (); if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); return; } } break; case GNUNET_TESTBED_ET_CONNECT: { if (0 != cont_fails) cont_fails--; if (0 == established_links) printf ("Establishing links. Please wait\n"); printf ("."); fflush (stdout); established_links++; } break; default: GNUNET_break (0); } } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link */ static void test_run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { result = GNUNET_OK; fprintf (stdout, "\n"); print_overlay_links_summary (); if (noninteractive) { GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_NO_TASK; shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); return; } #if (!ENABLE_SUPERMUC) fprintf (stdout, "Testbed running, waiting for keystroke to shut down\n"); fflush (stdout); (void) getc (stdin); #endif fprintf (stdout, "Shutting down. Please wait\n"); fflush (stdout); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); return; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param config configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { if (0 == num_peers) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Exiting as the number of peers is %u\n"), num_peers); return; } cfg = GNUNET_CONFIGURATION_dup (config); event_mask = 0; event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, controller_event_cb, NULL, &test_run, NULL); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_abort, NULL); } /** * Main function. * * @return 0 on success */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'p', "num-peers", "COUNT", gettext_noop ("create COUNT number of peers"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers}, {'e', "num-errors", "COUNT", gettext_noop ("tolerate COUNT number of continious timeout failures"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_cont_fails}, {'n', "non-interactive", NULL, gettext_noop ("run profiler in non-interactive mode where upon " "testbed setup the profiler does not wait for a " "keystroke but continues to run until a termination " "signal is received"), GNUNET_NO, &GNUNET_GETOPT_set_one, &noninteractive}, #if !ENABLE_SUPERMUC {'H', "hosts", "FILENAME", gettext_noop ("name of the file with the login information for the testbed"), GNUNET_YES, &GNUNET_GETOPT_set_string, &hosts_file}, #endif GNUNET_GETOPT_OPTION_END }; const char *binaryHelp = "gnunet-testbed-profiler [OPTIONS]"; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; result = GNUNET_SYSERR; ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-testbed-profiler", binaryHelp, options, &run, NULL); GNUNET_free ((void *) argv); if (GNUNET_OK != ret) return ret; if (GNUNET_OK != result) return 1; return 0; } gnunet-0.10.1/src/testbed/test_testbed_logger_api.conf0000644000175000017500000000017412233724131017763 00000000000000[testbed-logger] UNIXPATH=/tmp/testbed-logger.sock DIR=$GNUNET_TEST_HOME/data [PATHS] GNUNET_TEST_HOME = /tmp/test-testbed/gnunet-0.10.1/src/testbed/testbed_api_sd.h0000644000175000017500000000440212225777503015367 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_sd.h * @brief functions to calculate standard deviation * @author Sree Harsha Totakura */ #ifndef TESTBED_API_SD_H #define TESTBED_API_SD_H /** * Opaque handle for calculating SD */ struct SDHandle; /** * Initialize standard deviation calculation handle * * @param max_cnt the maximum number of readings to keep * @return the initialized handle */ struct SDHandle * GNUNET_TESTBED_SD_init_ (unsigned int max_cnt); /** * Frees the memory allocated to the SD handle * * @param h the SD handle */ void GNUNET_TESTBED_SD_destroy_ (struct SDHandle *h); /** * Add a reading to SD * * @param h the SD handle * @param amount the reading value */ void GNUNET_TESTBED_SD_add_data_ (struct SDHandle *h, unsigned int amount); /** * Returns the factor by which the given amount differs from the standard deviation * * @param h the SDhandle * @param amount the value for which the deviation is returned * @param factor the factor by which the given amont differs * @return the deviation from the average; GNUNET_SYSERR if the deviation cannot * be calculated OR 0 if the deviation is less than the average; a * maximum of 4 is returned for deviations equal to or larger than 4 */ int GNUNET_TESTBED_SD_deviation_factor_ (struct SDHandle *h, unsigned int amount, int *factor); #endif /* end of testbed_api.h */ gnunet-0.10.1/src/testbed/test_testbed_api_topology_clique.c0000644000175000017500000001163112225777502021232 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/testbed/test_testbed_api_topology.c * @brief testing cases for testing high level testbed api helper functions * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we want to start */ #define NUM_PEERS 10 /** * Array of peers */ static struct GNUNET_TESTBED_Peer **peers; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * Shutdown task */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Testing result */ static int result; /** * Counter for counting overlay connections */ static unsigned int overlay_connects; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != op) { GNUNET_TESTBED_operation_done (op); op = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_CONNECT: overlay_connects++; if ((NUM_PEERS * (NUM_PEERS - 1)) == overlay_connects) { result = GNUNET_OK; GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } break; case GNUNET_TESTBED_ET_OPERATION_FINISHED: GNUNET_assert (NULL != event->details.operation_finished.emsg); break; default: GNUNET_break (0); result = GNUNET_SYSERR; GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { unsigned int peer; GNUNET_assert (NULL == cls); if (NULL == peers_) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); return; } GNUNET_assert (NUM_PEERS == num_peers); for (peer = 0; peer < num_peers; peer++) GNUNET_assert (NULL != peers_[peer]); peers = peers_; overlay_connects = 0; op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, NULL, NULL, GNUNET_TESTBED_TOPOLOGY_CLIQUE, /* GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, */ /* NUM_PEERS, */ GNUNET_TESTBED_TOPOLOGY_OPTION_END); GNUNET_assert (NULL != op); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300), do_shutdown, NULL); } /** * Main function */ int main (int argc, char **argv) { uint64_t event_mask; result = GNUNET_SYSERR; event_mask = 0; event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", "test_testbed_api.conf", NUM_PEERS, event_mask, &controller_event_cb, NULL, &test_master, NULL); if (GNUNET_OK != result) return 1; return 0; } /* end of test_testbed_api_topology.c */ gnunet-0.10.1/src/testbed/testbed_api_topology.c0000644000175000017500000012030312262754601016622 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_topology.c * @brief topology-generation functions * @author Christian Grothoff */ #include "platform.h" #include "gnunet_testbed_service.h" #include "testbed_api.h" #include "testbed_api_peers.h" #include "testbed_api_operations.h" #include "testbed_api_topology.h" /** * Generic loggins shorthand */ #define LOG(kind,...) \ GNUNET_log_from (kind, "testbed-api-topology", __VA_ARGS__) /** * Default number of retires */ #define DEFAULT_RETRY_CNT 3 /** * Context information for topology operations */ struct TopologyContext; /** * Representation of an overlay link */ struct OverlayLink { /** * An operation corresponding to this link */ struct GNUNET_TESTBED_Operation *op; /** * The topology context this link is a part of */ struct TopologyContext *tc; /** * position of peer A's handle in peers array */ uint32_t A; /** * position of peer B's handle in peers array */ uint32_t B; }; /** * Representation of an underlay link */ struct UnderlayLink { /** * position of peer A's handle in peers array */ uint32_t A; /** * position of peer B's handle in peers array */ uint32_t B; /** * Bandwidth of the link in bytes per second */ uint32_t bandwidth; /** * Latency of the link in milliseconds */ uint32_t latency; /** * Loss in the link in percentage of message dropped */ uint32_t loss; }; struct RetryListEntry { /** * the next pointer for the DLL */ struct RetryListEntry *next; /** * the prev pointer for the DLL */ struct RetryListEntry *prev; /** * The link to be retired */ struct OverlayLink *link; }; /** * Context information for overlay topologies */ struct TopologyContextOverlay { /** * The array of peers */ struct GNUNET_TESTBED_Peer **peers; /** * An array of links; this array is of size link_array_size */ struct OverlayLink *link_array; /** * The operation closure */ void *op_cls; /** * topology generation completion callback */ GNUNET_TESTBED_TopologyCompletionCallback comp_cb; /** * The closure for the above callback */ void *comp_cb_cls; /** * DLL head for retry list */ struct RetryListEntry *rl_head; /** * DLL tail for retry list */ struct RetryListEntry *rl_tail; /** * How many retries to do before we give up */ unsigned int retry_cnt; /** * Number of links to try */ unsigned int nlinks; /** * How many links have been completed */ unsigned int ncompleted; /** * Total successfully established overlay connections */ unsigned int nsuccess; /** * Total failed overlay connections */ unsigned int nfailures; }; /** * Topology context information for underlay topologies */ struct TopologyContextUnderlay { /** * The link array */ struct UnderlayLink *link_array; }; /** * Context information for topology operations */ struct TopologyContext { /** * The type of this context */ enum { /** * Type for underlay topology */ TOPOLOGYCONTEXT_TYPE_UNDERLAY = 0, /** * Type for overlay topology */ TOPOLOGYCONTEXT_TYPE_OVERLAY } type; union { /** * Topology context information for overlay topology */ struct TopologyContextOverlay overlay; /** * Topology context information for underlay topology */ struct TopologyContextUnderlay underlay; } u; /** * The number of peers */ unsigned int num_peers; /** * The size of the link array */ unsigned int link_array_size; }; /** * A array of names representing topologies. Should be in sync with enum * GNUNET_TESTBED_TopologyOption */ const char *topology_strings[] = { /** * A clique (everyone connected to everyone else). No options. If there are N * peers this topology results in (N * (N -1)) connections. */ "CLIQUE", /** * Small-world network (2d torus plus random links). Followed * by the number of random links to add (unsigned int). */ "SMALL_WORLD", /** * Small-world network (ring plus random links). Followed * by the number of random links to add (unsigned int). */ "SMALL_WORLD_RING", /** * Ring topology. No options. */ "RING", /** * 2-d torus. No options. */ "2D_TORUS", /** * Random graph. Followed by the number of random links to be established * (unsigned int) */ "RANDOM", // GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI /** * Certain percentage of peers are unable to communicate directly * replicating NAT conditions. Followed by the fraction of * NAT'ed peers (float). */ "INTERNAT", /** * Scale free topology. Followed by the maximum number of links a node can * have (unsigned int); and the number of links a new node should have when * it is added to the network (unsigned int) */ "SCALE_FREE", /** * Straight line topology. No options. */ "LINE", /** * Read a topology from a given file. Followed by the name of the file (const char *). */ "FROM_FILE", /** * All peers are disconnected. No options. */ "NONE", /** * End of strings */ NULL }; /** * Callback to be called when an overlay_link operation complete * * @param cls element of the link_op array which points to the corresponding operation * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void overlay_link_completed (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { struct OverlayLink *link = cls; struct TopologyContext *tc; struct TopologyContextOverlay *overlay; struct RetryListEntry *retry_entry; GNUNET_assert (op == link->op); GNUNET_TESTBED_operation_done (op); link->op = NULL; tc = link->tc; GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); overlay = &tc->u.overlay; if (NULL != emsg) { overlay->nfailures++; if (0 != overlay->retry_cnt) { LOG (GNUNET_ERROR_TYPE_WARNING, "Error while establishing a link: %s -- Retrying\n", emsg); retry_entry = GNUNET_new (struct RetryListEntry); retry_entry->link = link; GNUNET_CONTAINER_DLL_insert_tail (overlay->rl_head, overlay->rl_tail, retry_entry); } } else overlay->nsuccess++; overlay->ncompleted++; if (overlay->ncompleted < overlay->nlinks) return; if ((0 != overlay->retry_cnt) && (NULL != overlay->rl_head)) { overlay->retry_cnt--; overlay->ncompleted = 0; overlay->nlinks = 0; while (NULL != (retry_entry = overlay->rl_head)) { link = retry_entry->link; link->op = GNUNET_TESTBED_overlay_connect (overlay->op_cls, &overlay_link_completed, link, overlay->peers[link->A], overlay->peers[link->B]); overlay->nlinks++; GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, retry_entry); GNUNET_free (retry_entry); } return; } if (NULL != overlay->comp_cb) { overlay->comp_cb (overlay->comp_cb_cls, overlay->nsuccess, overlay->nfailures); } } /** * Function called when a overlay connect operation is ready * * @param cls the Topology context */ static void opstart_overlay_configure_topology (void *cls) { struct TopologyContext *tc = cls; struct TopologyContextOverlay *overlay; unsigned int p; GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); overlay = &tc->u.overlay; overlay->nlinks = tc->link_array_size; for (p = 0; p < tc->link_array_size; p++) { overlay->link_array[p].op = GNUNET_TESTBED_overlay_connect (overlay->op_cls, &overlay_link_completed, &overlay->link_array[p], overlay->peers[overlay->link_array[p].A], overlay->peers[overlay->link_array[p].B]); } } /** * Callback which will be called when overlay connect operation is released * * @param cls the Topology context */ static void oprelease_overlay_configure_topology (void *cls) { struct TopologyContext *tc = cls; struct TopologyContextOverlay *overlay; struct RetryListEntry *retry_entry; unsigned int p; GNUNET_assert (TOPOLOGYCONTEXT_TYPE_OVERLAY == tc->type); overlay = &tc->u.overlay; while (NULL != (retry_entry = overlay->rl_head)) { GNUNET_CONTAINER_DLL_remove (overlay->rl_head, overlay->rl_tail, retry_entry); GNUNET_free (retry_entry); } if (NULL != overlay->link_array) { for (p = 0; p < tc->link_array_size; p++) if (NULL != overlay->link_array[p].op) GNUNET_TESTBED_operation_done (overlay->link_array[p].op); GNUNET_free (overlay->link_array); } GNUNET_free (tc); } /** * Populates the OverlayLink structure. * * @param offset the offset of the link array to use * @param A the peer A. Should be different from B * @param B the peer B. Should be different from A * @param tc the TopologyContext * @return */ static void make_link (unsigned int offset, uint32_t A, uint32_t B, struct TopologyContext *tc) { GNUNET_assert (A != B); switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; struct OverlayLink *olink; overlay = &tc->u.overlay; GNUNET_assert (offset < tc->link_array_size); olink = &overlay->link_array[offset]; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %u to %u\n", B, A); olink->A = A; olink->B = B; olink->op = NULL; olink->tc = tc; } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; struct UnderlayLink *ulink; underlay = &tc->u.underlay; GNUNET_assert (offset < tc->link_array_size); ulink = &underlay->link_array[offset]; ulink->A = A; ulink->B = B; } break; } } /** * Generates line topology * * @param tc the topology context */ static void gen_topo_line (struct TopologyContext *tc) { unsigned int cnt; tc->link_array_size = tc->num_peers - 1; switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; overlay->link_array = GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; underlay->link_array = GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size); } break; } for (cnt = 0; cnt < (tc->link_array_size); cnt++) make_link (cnt, cnt, cnt + 1, tc); } /** * Generates ring topology * * @param tc the topology context */ static void gen_topo_ring (struct TopologyContext *tc) { gen_topo_line (tc); tc->link_array_size++; switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; overlay->link_array = GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * tc->link_array_size); } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; underlay->link_array = GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * tc->link_array_size); } break; } make_link (tc->link_array_size - 1, tc->num_peers - 1, 0, tc); } /** * Returns the number of links that are required to generate a 2d torus for the * given number of peers. Also returns the arrangment (number of rows and the * length of each row) * * @param num_peers number of peers * @param rows number of rows in the 2d torus. Can be NULL * @param rows_len the length of each row. This array will be allocated * fresh. The caller should free it. Can be NULL * @return the number of links that are required to generate a 2d torus for the * given number of peers */ unsigned int GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows, unsigned int **rows_len) { double sq; unsigned int sq_floor; unsigned int _rows; unsigned int *_rows_len; unsigned int x; unsigned int y; unsigned int _num_peers; unsigned int cnt; sq = sqrt (num_peers); sq = floor (sq); sq_floor = (unsigned int) sq; _rows = (sq_floor + 1); _rows_len = GNUNET_malloc (sizeof (unsigned int) * _rows); for (y = 0; y < _rows - 1; y++) _rows_len[y] = sq_floor; _num_peers = sq_floor * sq_floor; cnt = (_num_peers < 2) ? _num_peers : 2 * _num_peers; x = 0; y = 0; while (_num_peers < num_peers) { if (x < y) _rows_len[_rows - 1] = ++x; else _rows_len[y++]++; _num_peers++; } cnt += (x < 2) ? x : 2 * x; cnt += (y < 2) ? y : 2 * y; if (0 == _rows_len[_rows - 1]) _rows--; if (NULL != rows) *rows = _rows; if (NULL != rows_len) *rows_len = _rows_len; else GNUNET_free (_rows_len); return cnt; } /** * Generates ring topology * * @param tc the topology context */ static void gen_topo_2dtorus (struct TopologyContext *tc) { unsigned int rows; unsigned int *rows_len; unsigned int x; unsigned int y; unsigned int cnt; unsigned int offset; tc->link_array_size = GNUNET_TESTBED_2dtorus_calc_links (tc->num_peers, &rows, &rows_len); switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; overlay->link_array = GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; underlay->link_array = GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size); break; } } cnt = 0; offset = 0; for (y = 0; y < rows; y++) { for (x = 0; x < rows_len[y] - 1; x++) { make_link (cnt, offset + x, offset + x + 1, tc); cnt++; } if (0 == x) break; make_link (cnt, offset + x, offset, tc); cnt++; offset += rows_len[y]; } for (x = 0; x < rows_len[0]; x++) { offset = 0; for (y = 0; y < rows - 1; y++) { if (x >= rows_len[y + 1]) break; GNUNET_assert (x < rows_len[y + 1]); make_link (cnt, offset + x, offset + rows_len[y] + x, tc); offset += rows_len[y]; cnt++; } if (0 == offset) break; make_link (cnt, offset + x, x, tc); cnt++; } GNUNET_assert (cnt == tc->link_array_size); GNUNET_free (rows_len); } /** * Generates ring topology * * @param tc the topology context * @param links the number of random links to establish * @param append GNUNET_YES to add links to existing link array; GNUNET_NO to * create a new link array */ static void gen_topo_random (struct TopologyContext *tc, unsigned int links, int append) { unsigned int cnt; unsigned int index; uint32_t A_rand; uint32_t B_rand; if (1 == tc->num_peers) return; if (GNUNET_YES == append) { index = tc->link_array_size; tc->link_array_size += links; } else { index = 0; tc->link_array_size = links; } switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; if (GNUNET_YES != append) { GNUNET_assert (NULL == overlay->link_array); overlay->link_array = GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); break; } GNUNET_assert ((0 < tc->link_array_size) && (NULL != overlay->link_array)); overlay->link_array = GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * tc->link_array_size); break; } case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; if (GNUNET_YES != append) { GNUNET_assert (NULL == underlay->link_array); underlay->link_array = GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size); break; } GNUNET_assert ((0 < tc->link_array_size) && (NULL != underlay->link_array)); underlay->link_array = GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * tc->link_array_size); break; } } for (cnt = 0; cnt < links; cnt++) { do { A_rand = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers); B_rand = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tc->num_peers); } while (A_rand == B_rand); make_link (index+cnt, A_rand, B_rand, tc); } } /** * Generates scale free network. Its construction is described in: * * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999. * * @param tc the topology context * @param cap maximum allowed node degree * @param m number of edges to establish for a new node when it is added to the * network */ static void gen_topo_scale_free (struct TopologyContext *tc, uint16_t cap, uint8_t m) { unsigned int *deg; unsigned int *etab; unsigned int *used; unsigned int etaboff; unsigned int cnt; unsigned int cnt2; unsigned int peer; unsigned int random_peer; unsigned int links; unsigned int off; unsigned int redo_threshold; etaboff = 0; tc->link_array_size = tc->num_peers * m; switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; overlay->link_array = GNUNET_malloc_large (sizeof (struct OverlayLink) * tc->link_array_size); } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; underlay->link_array = GNUNET_malloc_large (sizeof (struct UnderlayLink) * tc->link_array_size); } break; } etab = GNUNET_malloc_large (sizeof (unsigned int) * 2 * tc->link_array_size); deg = GNUNET_malloc (sizeof (unsigned int) * tc->num_peers); used = GNUNET_malloc (sizeof (unsigned int) * m); /* start by connecting peer 1 to peer 0 */ make_link (0, 0, 1, tc); deg[0]++; deg[1]++; etab[etaboff++] = 0; etab[etaboff++] = 1; links = 1; for (peer = 2; peer < tc->num_peers; peer++) { if (cap < deg[peer]) continue; for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++) { redo_threshold = 0; redo: off = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, etaboff); random_peer = etab[off]; if (cap < deg[random_peer]) { if (++redo_threshold > GNUNET_MAX (1, cap / 2)) { redo_threshold = 0; off = 0; for (cnt2 = 0; cnt2 < etaboff; cnt2++) { if (random_peer == etab[cnt2]) { off++; continue; } etab[cnt2 - off] = etab[cnt2]; } etaboff -= off; } goto redo; } for (cnt2 = 0; cnt2 < cnt; cnt2++) if (random_peer == used[cnt2]) goto redo; make_link (links + cnt, random_peer, peer, tc); deg[random_peer]++; deg[peer]++; used[cnt] = random_peer; } for (cnt = 0; cnt < GNUNET_MIN (peer, m); cnt++) { etab[etaboff++] = used[cnt]; etab[etaboff++] = peer; } links += GNUNET_MIN (peer, m); } GNUNET_free (etab); GNUNET_free (used); GNUNET_free (deg); GNUNET_assert (links <= tc->link_array_size); tc->link_array_size = links; switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; overlay->link_array = GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * tc->link_array_size); } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; underlay->link_array = GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * tc->link_array_size); } break; } } /** * Generates topology from the given file * * @param tc the topology context * @param filename the filename of the file containing topology data */ static void gen_topo_from_file (struct TopologyContext *tc, const char *filename) { char *data; char *end; char *buf; uint64_t fs; uint64_t offset; unsigned long int peer_id; unsigned long int other_peer_id; enum ParseState { /** * We read the peer index */ PEER_INDEX, /** * We read the other peer indices */ OTHER_PEER_INDEX, } state; int status; status = GNUNET_SYSERR; if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Topology file %s not found\n"), filename); return; } if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Topology file %s has no data\n"), filename); return; } data = GNUNET_malloc (fs); if (fs != GNUNET_DISK_fn_read (filename, data, fs)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Topology file %s cannot be read\n"), filename); goto _exit; } offset = 0; peer_id = 0; state = PEER_INDEX; while (offset < fs) { if (0 != isspace (data[offset])) { offset++; continue; } switch (state) { case PEER_INDEX: buf = strchr (&data[offset], ':'); if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to read peer index from toology file: %s"), filename); goto _exit; } *buf = '\0'; errno = 0; peer_id = (unsigned int) strtoul (&data[offset], &end, 10); if (0 != errno) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Value in given topology file: %s out of range\n"), filename); goto _exit; } if (&data[offset] == end) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to read peer index from topology file: %s"), filename); goto _exit; } if (tc->num_peers <= peer_id) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Topology file needs more peers than given ones\n"), filename); goto _exit; } state = OTHER_PEER_INDEX; offset += ((unsigned int) (buf - &data[offset])) + 1; break; case OTHER_PEER_INDEX: errno = 0; other_peer_id = (unsigned int) strtoul (&data[offset], &end, 10); if (0 != errno) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Value in given topology file: %s out of range\n"), filename); goto _exit; } if (&data[offset] == end) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to read peer index from topology file: %s"), filename); goto _exit; } if (tc->num_peers <= other_peer_id) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Topology file needs more peers than given ones\n"), filename); goto _exit; } if (peer_id != other_peer_id) { tc->link_array_size++; switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; overlay->link_array = GNUNET_realloc (overlay->link_array, sizeof (struct OverlayLink) * tc->link_array_size); } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; underlay->link_array = GNUNET_realloc (underlay->link_array, sizeof (struct UnderlayLink) * tc->link_array_size); } break; } offset += end - &data[offset]; make_link (tc->link_array_size - 1, peer_id, other_peer_id, tc); } else LOG (GNUNET_ERROR_TYPE_WARNING, _("Ignoring to connect peer %u to peer %u\n"), peer_id, other_peer_id); while (('\n' != data[offset]) && ('|' != data[offset]) && (offset < fs)) offset++; if ('\n' == data[offset]) state = PEER_INDEX; else if ('|' == data[offset]) { state = OTHER_PEER_INDEX; offset++; } break; } } status = GNUNET_OK; _exit: GNUNET_free (data); if (GNUNET_OK != status) { LOG (GNUNET_ERROR_TYPE_WARNING, "Removing link data read from the file\n"); tc->link_array_size = 0; switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; GNUNET_free_non_null (overlay->link_array); overlay->link_array = NULL; } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; GNUNET_free_non_null (underlay->link_array); underlay->link_array = NULL; } break; } } } /** * Generates clique topology * * @param tc the topology context */ static void gen_topo_clique (struct TopologyContext *tc) { unsigned int cnt; unsigned int offset; unsigned int neighbour; tc->link_array_size = tc->num_peers * (tc->num_peers - 1); switch (tc->type) { case TOPOLOGYCONTEXT_TYPE_OVERLAY: { struct TopologyContextOverlay *overlay; overlay = &tc->u.overlay; overlay->link_array = GNUNET_malloc (sizeof (struct OverlayLink) * tc->link_array_size); } break; case TOPOLOGYCONTEXT_TYPE_UNDERLAY: { struct TopologyContextUnderlay *underlay; underlay = &tc->u.underlay; underlay->link_array = GNUNET_malloc (sizeof (struct UnderlayLink) * tc->link_array_size); } } offset = 0; for (cnt = 0; cnt < tc->num_peers; cnt++) { for (neighbour = 0; neighbour < tc->num_peers; neighbour++) { if (neighbour == cnt) continue; make_link (offset, cnt, neighbour, tc); offset++; } } } /** * Configure overall network topology to have a particular shape. * * @param op_cls closure argument to give with the operation event * @param num_peers number of peers in 'peers' * @param peers array of 'num_peers' with the peers to configure * @param topo desired underlay topology to use * @param ap topology-specific options * @return handle to the operation, NULL if configuring the topology * is not allowed at this time */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_topology_va (void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, enum GNUNET_TESTBED_TopologyOption topo, va_list ap) { GNUNET_break (0); return NULL; } /** * Configure overall network topology to have a particular shape. * * @param op_cls closure argument to give with the operation event * @param num_peers number of peers in 'peers' * @param peers array of 'num_peers' with the peers to configure * @param topo desired underlay topology to use * @param ... topology-specific options * @return handle to the operation, NULL if configuring the topology * is not allowed at this time */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_topology (void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, enum GNUNET_TESTBED_TopologyOption topo, ...) { GNUNET_break (0); return NULL; } /** * All peers must have been started before calling this function. * This function then connects the given peers in the P2P overlay * using the given topology. * * @param op_cls closure argument to give with the peer connect operation events * generated through this function * @param num_peers number of peers in 'peers' * @param peers array of 'num_peers' with the peers to configure * @param max_connections the maximums number of overlay connections that will * be made to achieve the given topology * @param comp_cb the completion callback to call when the topology generation * is completed * @param comp_cb_cls closure for the above completion callback * @param topo desired underlay topology to use * @param va topology-specific options * @return handle to the operation, NULL if connecting these * peers is fundamentally not possible at this time (peers * not running or underlay disallows) or if num_peers is less than 2 */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_configure_topology_va (void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int *max_connections, GNUNET_TESTBED_TopologyCompletionCallback comp_cb, void *comp_cb_cls, enum GNUNET_TESTBED_TopologyOption topo, va_list va) { struct TopologyContext *tc; struct TopologyContextOverlay *overlay; struct GNUNET_TESTBED_Operation *op; struct GNUNET_TESTBED_Controller *c; enum GNUNET_TESTBED_TopologyOption secondary_option; if (num_peers < 2) return NULL; c = peers[0]->controller; tc = GNUNET_new (struct TopologyContext); tc->type = TOPOLOGYCONTEXT_TYPE_OVERLAY; overlay = &tc->u.overlay; overlay->peers = peers; tc->num_peers = num_peers; overlay->op_cls = op_cls; overlay->retry_cnt = DEFAULT_RETRY_CNT; overlay->comp_cb = comp_cb; overlay->comp_cb_cls = comp_cb_cls; switch (topo) { case GNUNET_TESTBED_TOPOLOGY_LINE: gen_topo_line (tc); break; case GNUNET_TESTBED_TOPOLOGY_RING: gen_topo_ring (tc); break; case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_NO); break; case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: gen_topo_ring (tc); gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES); break; case GNUNET_TESTBED_TOPOLOGY_CLIQUE: gen_topo_clique (tc); break; case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: gen_topo_2dtorus (tc); break; case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: gen_topo_2dtorus (tc); gen_topo_random (tc, va_arg (va, unsigned int), GNUNET_YES); break; case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: { uint16_t cap; uint8_t m; cap = (uint16_t) va_arg (va, unsigned int); m = (uint8_t) va_arg (va, unsigned int); gen_topo_scale_free (tc, cap, m); } break; case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: { const char *filename; filename = va_arg (va, const char *); GNUNET_assert (NULL != filename); gen_topo_from_file (tc, filename); } break; default: GNUNET_break (0); GNUNET_free (tc); return NULL; } do { secondary_option = va_arg (va, enum GNUNET_TESTBED_TopologyOption); switch (secondary_option) { case GNUNET_TESTBED_TOPOLOGY_RETRY_CNT: overlay->retry_cnt = va_arg (va, unsigned int); break; case GNUNET_TESTBED_TOPOLOGY_OPTION_END: break; default: GNUNET_break (0); /* Should not use any other option apart from * the ones handled here */ GNUNET_free_non_null (overlay->link_array); GNUNET_free (tc); return NULL; } } while (GNUNET_TESTBED_TOPOLOGY_OPTION_END != secondary_option); op = GNUNET_TESTBED_operation_create_ (tc, &opstart_overlay_configure_topology, &oprelease_overlay_configure_topology); GNUNET_TESTBED_operation_queue_insert_ (c->opq_parallel_topology_config_operations, op); GNUNET_TESTBED_operation_begin_wait_ (op); LOG (GNUNET_ERROR_TYPE_DEBUG, "Generated %u connections\n", tc->link_array_size); if (NULL != max_connections) *max_connections = tc->link_array_size; return op; } /** * All peers must have been started before calling this function. * This function then connects the given peers in the P2P overlay * using the given topology. * * @param op_cls closure argument to give with the peer connect operation events * generated through this function * @param num_peers number of peers in 'peers' * @param peers array of 'num_peers' with the peers to configure * @param max_connections the maximums number of overlay connections that will * be made to achieve the given topology * @param comp_cb the completion callback to call when the topology generation * is completed * @param comp_cb_cls closure for the above completion callback * @param topo desired underlay topology to use * @param ... topology-specific options * @return handle to the operation, NULL if connecting these * peers is fundamentally not possible at this time (peers * not running or underlay disallows) or if num_peers is less than 2 */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_configure_topology (void *op_cls, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int *max_connections, GNUNET_TESTBED_TopologyCompletionCallback comp_cb, void *comp_cb_cls, enum GNUNET_TESTBED_TopologyOption topo, ...) { struct GNUNET_TESTBED_Operation *op; va_list vargs; GNUNET_assert (topo < GNUNET_TESTBED_TOPOLOGY_OPTION_END); va_start (vargs, topo); op = GNUNET_TESTBED_overlay_configure_topology_va (op_cls, num_peers, peers, max_connections, comp_cb, comp_cb_cls, topo, vargs); va_end (vargs); return op; } /** * Get a topology from a string input. * * @param topology where to write the retrieved topology * @param topology_string The string to attempt to * get a configuration value from * @return GNUNET_YES if topology string matched a * known topology, GNUNET_NO if not */ int GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology, const char *topology_string) { unsigned int cnt; for (cnt = 0; NULL != topology_strings[cnt]; cnt++) { if (0 == strcasecmp (topology_string, topology_strings[cnt])) { if (NULL != topology) *topology = (enum GNUNET_TESTBED_TopologyOption) cnt; return GNUNET_YES; } } return GNUNET_NO; } /** * Returns the string corresponding to the given topology * * @param topology the topology * @return the string (freshly allocated) of given topology; NULL if topology cannot be * expressed as a string */ char * GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology) { if (GNUNET_TESTBED_TOPOLOGY_OPTION_END <= topology) return NULL; return GNUNET_strdup (topology_strings[topology]); } /** * Function to construct an underlay topology * * @param num_peers the number of peers for which the topology should be * generated * @param proc the underlay link processor callback. Will be called for each * underlay link generated unless a previous call to this callback * returned GNUNET_SYSERR. Cannot be NULL. * @param cls closure for proc * @param ... variable arguments denoting the topology and its parameters. They * should start with the type of topology to generate followed by their * options. * @return GNUNET_OK if underlay link generation is successful; GNUNET_SYSERR * upon error in generating the underlay or if any calls to the * underlay link processor returned GNUNET_SYSERR */ int GNUNET_TESTBED_underlay_construct_ (int num_peers, underlay_link_processor proc, void *cls, ...) { struct TopologyContext tc; struct TopologyContextUnderlay *underlay; struct UnderlayLink *ulink; va_list vargs; enum GNUNET_TESTBED_TopologyOption topology; unsigned int cnt; int ret; GNUNET_assert (NULL != proc); ret = GNUNET_OK; memset (&tc, 0, sizeof (tc)); tc.num_peers = num_peers; tc.type = TOPOLOGYCONTEXT_TYPE_UNDERLAY; underlay = &tc.u.underlay; va_start (vargs, cls); topology = va_arg (vargs, enum GNUNET_TESTBED_TopologyOption); switch (topology) { case GNUNET_TESTBED_TOPOLOGY_LINE: gen_topo_line (&tc); break; case GNUNET_TESTBED_TOPOLOGY_RING: gen_topo_ring (&tc); break; case GNUNET_TESTBED_TOPOLOGY_CLIQUE: gen_topo_clique (&tc); break; case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: gen_topo_2dtorus (&tc); break; case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_NO); break; case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: gen_topo_ring (&tc); gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES); break; case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: gen_topo_2dtorus (&tc); gen_topo_random (&tc, va_arg (vargs, unsigned int), GNUNET_YES); break; case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: { const char *filename; filename = va_arg (vargs, char *); GNUNET_assert (NULL != filename); gen_topo_from_file (&tc, filename); } break; case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: { uint16_t cap; uint8_t m; cap = (uint16_t) va_arg (vargs, unsigned int); m = (uint8_t) va_arg (vargs, unsigned int); gen_topo_scale_free (&tc, cap, m); } break; default: GNUNET_assert (0); } va_end (vargs); for (cnt = 0; cnt < tc.link_array_size; cnt++) { ulink = &underlay->link_array[cnt]; if (GNUNET_SYSERR == proc (cls, ulink->A, ulink->B, ulink->bandwidth, ulink->latency, ulink->loss)) { ret = GNUNET_SYSERR; break; } } GNUNET_free_non_null (underlay->link_array); return ret; } /* end of testbed_api_topology.c */ gnunet-0.10.1/src/testbed/gnunet-daemon-latency-logger.c0000644000175000017500000002200112267431203020045 00000000000000/* This file is part of GNUnet (C) 2008--2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-daemon-latency-logger.c * @brief log latency values from neighbour connections into an SQLite database * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_ats_service.h" #include /** * Logging shorthand */ #define LOG(type,...) \ GNUNET_log (type, __VA_ARGS__) /** * Debug logging shorthand */ #define DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_SQLITE(db, msg, level, cmd) \ do { \ GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), \ cmd, __FILE__,__LINE__, sqlite3_errmsg(db)); \ if (msg != NULL) \ GNUNET_asprintf(msg, _("`%s' failed at %s:%u with error: %s"), cmd, \ __FILE__, __LINE__, sqlite3_errmsg(db)); \ } while(0) /** * Entry type to be used in the map to store old latency values */ struct Entry { /** * The peer's identity */ struct GNUNET_PeerIdentity id; /** * The last known value for latency */ unsigned int latency; }; /** * Handle to the map used to store old latency values for peers */ static struct GNUNET_CONTAINER_MultiPeerMap *map; /** * The SQLite database handle */ static struct sqlite3 *db; /** * Handle to the ATS performance subsystem */ struct GNUNET_ATS_PerformanceHandle *ats; /** * Prepared statement for inserting values into the database table */ struct sqlite3_stmt *stmt_insert; /** * Shutdown task identifier */ GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * @ingroup hashmap * Iterator over hash map entries. * * @param cls closure * @param key current public key * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int free_iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct Entry *e = cls; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key, e)); GNUNET_free (e); return GNUNET_YES; } /** * Shutdown * * @param cls NULL * @param tc task context from scheduler * @return */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_ATS_performance_done (ats); ats = NULL; if (NULL != stmt_insert) { sqlite3_finalize (stmt_insert); stmt_insert = NULL; } GNUNET_break (SQLITE_OK == sqlite3_close (db)); db = NULL; if (NULL != map) { GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_iterate (map, free_iterator, NULL)); GNUNET_CONTAINER_multipeermap_destroy (map); map = NULL; } } /** * Signature of a function that is called with QoS information about an address. * * @param cls closure * @param address the address * @param address_active is this address actively used to maintain a connection * to a peer * @param bandwidth_out assigned outbound bandwidth for the connection * @param bandwidth_in assigned inbound bandwidth for the connection * @param ats performance data for the address (as far as known) * @param ats_count number of performance records in 'ats' */ static void addr_info_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { static const char *query_insert = "INSERT INTO ats_info(" " id," " val," " timestamp" ") VALUES (" " ?1," " ?2," " datetime('now')" ");"; struct Entry *entry; int latency; unsigned int cnt; GNUNET_assert (NULL != db); if (GNUNET_NO == address_active) return; for (cnt = 0; cnt < ats_count; cnt++) { if (GNUNET_ATS_QUALITY_NET_DELAY == ntohl (ats[cnt].type)) goto insert; } return; insert: latency = (int) ntohl (ats[cnt].value); entry = NULL; if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (map, &address->peer)) { entry = GNUNET_CONTAINER_multipeermap_get (map, &address->peer); GNUNET_assert (NULL != entry); if (latency == entry->latency) return; } if (NULL == stmt_insert) { if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert, NULL)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); goto err_shutdown; } } if ( (SQLITE_OK != sqlite3_bind_text (stmt_insert, 1, GNUNET_i2s (&address->peer), -1, SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, latency)) ) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_text"); goto err_shutdown; } if (SQLITE_DONE != sqlite3_step (stmt_insert)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); goto err_shutdown; } if (SQLITE_OK != sqlite3_reset (stmt_insert)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_insert"); goto err_shutdown; } if (NULL == entry) { entry = GNUNET_new (struct Entry); entry->id = address->peer; GNUNET_CONTAINER_multipeermap_put (map, &entry->id, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); } entry->latency = latency; return; err_shutdown: GNUNET_SCHEDULER_shutdown (); } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { const char *query_create = "CREATE TABLE ats_info (" "id TEXT," "val INTEGER," "timestamp NUMERIC" ");"; char *dbfile; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "LATENCY-LOGGER", "DBFILE", &dbfile)) { GNUNET_break (0); return; } if (SQLITE_OK != sqlite3_open (dbfile, &db)) { if (NULL != db) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2"); sqlite3_close (db); } else LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile); GNUNET_free (dbfile); return; } if (0 != sqlite3_exec (db, query_create, NULL, NULL, NULL)) DEBUG ("SQLite Error: %d. Perhaps the database `%s' already exits.\n", sqlite3_errcode (db), dbfile); DEBUG ("Opened database %s\n", dbfile); GNUNET_free (dbfile); dbfile = NULL; ats = GNUNET_ATS_performance_init (c, addr_info_cb, NULL); map = GNUNET_CONTAINER_multipeermap_create (30, GNUNET_YES); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); } /** * Execution entry point */ int main (int argc, char * const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-latency-logger", _("Daemon to log latency values of connections to neighbours"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } gnunet-0.10.1/src/testbed/testbed_api_testbed.c0000644000175000017500000012270112263473436016411 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_testbed.c * @brief high-level testbed management * @author Christian Grothoff * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "testbed_api.h" #include "testbed_api_peers.h" #include "testbed_api_hosts.h" #include "testbed_api_topology.h" /** * Generic loggins shorthand */ #define LOG(kind,...) \ GNUNET_log_from (kind, "testbed-api-testbed", __VA_ARGS__) /** * Debug logging shortcut */ #define DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * The default setup timeout in seconds */ #define DEFAULT_SETUP_TIMEOUT 300 /** * Configuration section for testbed */ #define TESTBED_CONFIG_SECTION "testbed" /** * Option string for the maximum number of edges a peer is permitted to have * while generating scale free topology */ #define SCALE_FREE_CAP "SCALE_FREE_TOPOLOGY_CAP" /** * Option string for the number of edges to be established when adding a new * node to the scale free network */ #define SCALE_FREE_M "SCALE_FREE_TOPOLOGY_M" /** * Context information for the operation we start */ struct RunContextOperation { /** * The testbed operation handle */ struct GNUNET_TESTBED_Operation *op; /** * Context information for GNUNET_TESTBED_run() */ struct GNUNET_TESTBED_RunHandle *rc; /** * Closure */ void *cls; }; /** * States of RunContext */ enum State { /** * Initial state */ RC_INIT = 0, /** * Controllers on given hosts started and linked */ RC_LINKED, /** * Peers are created */ RC_PEERS_CREATED, /** * The testbed run is ready and the master callback can be called now. At this * time the peers are all started and if a topology is provided in the * configuration the topology would have been attempted */ RC_READY, /* /\** */ /* * Peers are stopped */ /* *\/ */ /* RC_PEERS_STOPPED, */ /* /\** */ /* * Peers are destroyed */ /* *\/ */ /* RC_PEERS_DESTROYED */ /** * All peers shutdown (stopped and destroyed) */ RC_PEERS_SHUTDOWN }; /** * Context for host compability checks */ struct CompatibilityCheckContext { /** * The run context */ struct GNUNET_TESTBED_RunHandle *rc; /** * Handle for the compability check */ struct GNUNET_TESTBED_HostHabitableCheckHandle *h; /** * Index of the host in the run context's hosts array */ unsigned int index; }; /** * Testbed Run Handle */ struct GNUNET_TESTBED_RunHandle { /** * The controller handle */ struct GNUNET_TESTBED_Controller *c; /** * The configuration of the controller. This is based on the cfg given to the * function GNUNET_TESTBED_run(). We also use this config as a template while * for peers */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the host on which the controller runs */ struct GNUNET_TESTBED_Host *h; /** * The handle to the controller process */ struct GNUNET_TESTBED_ControllerProc *cproc; /** * The callback to use as controller callback */ GNUNET_TESTBED_ControllerCallback cc; /** * The pointer to the controller callback */ void *cc_cls; /** * The trusted IP string */ char *trusted_ip; /** * TestMaster callback to call when testbed initialization is done */ GNUNET_TESTBED_TestMaster test_master; /** * The closure for the TestMaster callback */ void *test_master_cls; /** * A hashmap for operations started by us */ struct GNUNET_CONTAINER_MultiHashMap32 *rcop_map; /** * An array of hosts loaded from the hostkeys file */ struct GNUNET_TESTBED_Host **hosts; /** * Array of compatibility check contexts */ struct CompatibilityCheckContext *hclist; /** * Array of peers which we create */ struct GNUNET_TESTBED_Peer **peers; /** * The topology generation operation. Will be null if no topology is set in * the configuration */ struct GNUNET_TESTBED_Operation *topology_operation; /** * The file containing topology data. Only used if the topology is set to 'FROM_FILE' */ char *topo_file; /** * Host registration handle */ struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; /** * Profiling start time */ struct GNUNET_TIME_Absolute pstart_time; /** * Host registration task */ GNUNET_SCHEDULER_TaskIdentifier register_hosts_task; /** * Task to be run of a timeout */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Task run upon shutdown interrupts */ GNUNET_SCHEDULER_TaskIdentifier interrupt_task; /** * The event mask for the controller */ uint64_t event_mask; /** * State of this context */ enum State state; /** * The topology which has to be achieved with the peers started in this context */ enum GNUNET_TESTBED_TopologyOption topology; /** * Have we already shutdown */ int shutdown; /** * Number of hosts in the given host file */ unsigned int num_hosts; /** * Number of registered hosts. Also used as a counter while checking * habitabillity of hosts */ unsigned int reg_hosts; /** * Current peer count for an operation; Set this to 0 and increment for each * successful operation on a peer */ unsigned int peer_count; /** * number of peers to start */ unsigned int num_peers; /** * Expected overlay connects. Should be zero if no topology is relavant */ unsigned int num_oc; /** * Number of random links to established */ unsigned int random_links; /** * the number of overlay link connection attempts that succeeded */ unsigned int links_succeeded; /** * the number of overlay link connection attempts that failed */ unsigned int links_failed; }; /** * Return a 32-bit key from a pointer * * @param rcop the pointer * @return 32-bit key */ static uint32_t rcop_key (void *rcop) { return * ((uint32_t *) &rcop); } /** * Context information used for finding a pointer in the rcop_map */ struct SearchContext { /** * The operation pointer to look for */ struct GNUNET_TESTBED_Operation *query; /** * The Run context operation which has the operation being queried */ struct RunContextOperation *result; }; /** * Iterator for searching over the elements matching a given query * * @param cls the SearchContext * @param key the 32-bit key * @param value the RunContextOperation element * @return GNUNET_YES to continue iteration; GNUNET_NO to cancel it */ static int search_iterator (void *cls, uint32_t key, void *value) { struct RunContextOperation *rcop = value; struct SearchContext *sc = cls; GNUNET_assert (NULL != rcop); if (sc->query == rcop->op) { GNUNET_assert (NULL == sc->result); sc->result = rcop; return GNUNET_NO; } return GNUNET_YES; } /** * Initiate a search for the given operation in the rcop_map * * @param rc the RunContext whose rcop_map will be searched for the given * operation * @param op the given operation to search for * @return the matching RunContextOperation if found; NULL if not */ static struct RunContextOperation * search_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct GNUNET_TESTBED_Operation *op) { struct SearchContext sc; sc.query = op; sc.result = NULL; if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap32_get_multiple (rc->rcop_map, rcop_key (op), &search_iterator, &sc)) { GNUNET_assert (NULL != sc.result); return sc.result; } return NULL; } /** * Insert an RunContextOperation into the rcop_map of the given RunContext * * @param rc the RunContext into whose map is to be used for insertion * @param rcop the RunContextOperation to insert */ static void insert_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct RunContextOperation *rcop) { GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (rc->rcop_map, rcop_key (rcop->op), rcop, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); } /** * Remove a RunContextOperation from the rcop_map of the given RunContext * * @param rc the RunContext from whose map the given RunContextOperaton has to * be removed * @param rcop the RunContextOperation */ static void remove_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct RunContextOperation *rcop) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_remove (rc->rcop_map, rcop_key (rcop->op), rcop)); } /** * Assuming all peers have been destroyed cleanup run handle * * @param rc the run context */ static void cleanup (struct GNUNET_TESTBED_RunHandle *rc) { unsigned int hid; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rc->register_hosts_task); GNUNET_assert (NULL == rc->reg_handle); GNUNET_assert (NULL == rc->peers); GNUNET_assert (NULL == rc->hclist); GNUNET_assert (RC_PEERS_SHUTDOWN == rc->state); GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (rc->rcop_map)); GNUNET_CONTAINER_multihashmap32_destroy (rc->rcop_map); if (NULL != rc->c) GNUNET_TESTBED_controller_disconnect (rc->c); if (NULL != rc->cproc) GNUNET_TESTBED_controller_stop (rc->cproc); if (NULL != rc->h) GNUNET_TESTBED_host_destroy (rc->h); for (hid = 0; hid < rc->num_hosts; hid++) GNUNET_TESTBED_host_destroy (rc->hosts[hid]); GNUNET_free_non_null (rc->hosts); if (NULL != rc->cfg) GNUNET_CONFIGURATION_destroy (rc->cfg); GNUNET_free_non_null (rc->topo_file); GNUNET_free_non_null (rc->trusted_ip); GNUNET_free (rc); } /** * Iterator for cleaning up elements from rcop_map * * @param cls the RunContext * @param key the 32-bit key * @param value the RunContextOperation element * @return always GNUNET_YES */ static int rcop_cleanup_iterator (void *cls, uint32_t key, void *value) { struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop = value; GNUNET_assert (rc == rcop->rc); remove_rcop (rc, rcop); GNUNET_TESTBED_operation_done (rcop->op); GNUNET_free (rcop); return GNUNET_YES; } /** * Cancels operations and tasks which are assigned to the given run context * * @param rc the RunContext */ static void rc_cleanup_operations (struct GNUNET_TESTBED_RunHandle *rc) { struct CompatibilityCheckContext *hc; unsigned int nhost; if (NULL != rc->hclist) { for (nhost = 0; nhost < rc->num_hosts; nhost++) { hc = &rc->hclist[nhost]; if (NULL != hc->h) GNUNET_TESTBED_is_host_habitable_cancel (hc->h); } GNUNET_free (rc->hclist); rc->hclist = NULL; } /* Stop register hosts task if it is running */ if (GNUNET_SCHEDULER_NO_TASK != rc->register_hosts_task) { GNUNET_SCHEDULER_cancel (rc->register_hosts_task); rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != rc->timeout_task) { GNUNET_SCHEDULER_cancel (rc->timeout_task); rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != rc->reg_handle) { GNUNET_TESTBED_cancel_registration (rc->reg_handle); rc->reg_handle = NULL; } if (NULL != rc->topology_operation) { GNUNET_TESTBED_operation_done (rc->topology_operation); rc->topology_operation = NULL; } /* cancel any exiting operations */ GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map, &rcop_cleanup_iterator, rc)); } /** * Cancels the scheduled interrupt task * * @param rc the run context */ static void cancel_interrupt_task (struct GNUNET_TESTBED_RunHandle *rc) { GNUNET_SCHEDULER_cancel (rc->interrupt_task); rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK; } /** * This callback will be called when all the operations are completed * (done/cancelled) * * @param cls run context */ static void wait_op_completion (void *cls) { struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop; if ( (NULL == rc->cproc) || (NULL == rc->c) || (GNUNET_YES == rc->shutdown) ) { if (NULL != rc->peers) { GNUNET_free (rc->peers); rc->peers = NULL; } goto cleanup_; } if (NULL == rc->peers) goto cleanup_; rc->shutdown = GNUNET_YES; rcop = GNUNET_new (struct RunContextOperation); rcop->rc = rc; rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL); GNUNET_assert (NULL != rcop->op); DEBUG ("Shutting down peers\n"); rc->pstart_time = GNUNET_TIME_absolute_get (); insert_rcop (rc, rcop); return; cleanup_: rc->state = RC_PEERS_SHUTDOWN; cancel_interrupt_task (rc); cleanup (rc); } /** * Task run upon interrupts (SIGINT, SIGTERM) and upon scheduler shutdown. * * @param cls the RunContext which has to be acted upon * @param tc the scheduler task context */ static void interrupt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_RunHandle *rc = cls; struct GNUNET_TESTBED_Controller *c = rc->c; unsigned int size; /* reschedule */ rc->interrupt_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &interrupt, rc); rc_cleanup_operations (rc); if ( (GNUNET_NO == rc->shutdown) && (NULL != c) && (0 != (size = GNUNET_CONTAINER_multihashmap32_size (c->opc_map)))) { LOG (GNUNET_ERROR_TYPE_WARNING, "Shutdown postponed as there are " "%u operations currently active\n", size); c->opcq_empty_cb = &wait_op_completion; c->opcq_empty_cls = rc; return; } wait_op_completion (rc); } /** * Function to return the string representation of the duration between current * time and `pstart_time' in `RunContext' * * @param rc the RunContext * @return the representation string; this is NOT reentrant */ static const char * prof_time (struct GNUNET_TESTBED_RunHandle *rc) { struct GNUNET_TIME_Relative ptime; ptime = GNUNET_TIME_absolute_get_duration (rc->pstart_time); return GNUNET_STRINGS_relative_time_to_string (ptime, GNUNET_YES); } /** * Task for starting peers * * @param cls the RunHandle * @param tc the task context from scheduler */ static void start_peers_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop; unsigned int peer; DEBUG ("Starting Peers\n"); rc->pstart_time = GNUNET_TIME_absolute_get (); for (peer = 0; peer < rc->num_peers; peer++) { rcop = GNUNET_new (struct RunContextOperation); rcop->rc = rc; rcop->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL); GNUNET_assert (NULL != rcop->op); rcop->cls = rc->peers[peer]; insert_rcop (rc, rcop); } rc->peer_count = 0; } /** * Functions of this signature are called when a peer has been successfully * created * * @param cls the closure from GNUNET_TESTBED_peer_create() * @param peer the handle for the created peer; NULL on any error during * creation * @param emsg NULL if peer is not NULL; else MAY contain the error description */ static void peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) { struct RunContextOperation *rcop = cls; struct GNUNET_TESTBED_RunHandle *rc; GNUNET_assert (NULL != rcop); GNUNET_assert (NULL != (rc = rcop->rc)); remove_rcop (rc, rcop); GNUNET_TESTBED_operation_done (rcop->op); GNUNET_free (rcop); if (NULL == peer) { if (NULL != emsg) LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n", emsg); GNUNET_SCHEDULER_shutdown (); return; } rc->peers[rc->peer_count] = peer; rc->peer_count++; if (rc->peer_count < rc->num_peers) return; DEBUG ("%u peers created in %s\n", rc->num_peers, prof_time (rc)); rc->state = RC_PEERS_CREATED; GNUNET_SCHEDULER_add_now (&start_peers_task, rc); } /** * call test master callback * * @param rc the RunContext */ static void call_master (struct GNUNET_TESTBED_RunHandle *rc) { GNUNET_SCHEDULER_cancel (rc->timeout_task); rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != rc->test_master) rc->test_master (rc->test_master_cls, rc, rc->num_peers, rc->peers, rc->links_succeeded, rc->links_failed); } /** * Callbacks of this type are called when topology configuration is completed * * @param cls the operation closure given to * GNUNET_TESTBED_overlay_configure_topology_va() and * GNUNET_TESTBED_overlay_configure() calls * @param nsuccess the number of successful overlay connects * @param nfailures the number of overlay connects which failed */ static void topology_completion_callback (void *cls, unsigned int nsuccess, unsigned int nfailures) { struct GNUNET_TESTBED_RunHandle *rc = cls; DEBUG ("Overlay topology generated in %s\n", prof_time (rc)); GNUNET_TESTBED_operation_done (rc->topology_operation); rc->topology_operation = NULL; rc->links_succeeded = nsuccess; rc->links_failed = nfailures; rc->state = RC_READY; call_master (rc); } /** * Function to create peers * * @param rc the RunContext */ static void create_peers (struct GNUNET_TESTBED_RunHandle *rc) { struct RunContextOperation *rcop; unsigned int peer; DEBUG ("Creating peers\n"); rc->pstart_time = GNUNET_TIME_absolute_get (); rc->peers = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * rc->num_peers); GNUNET_assert (NULL != rc->c); rc->peer_count = 0; for (peer = 0; peer < rc->num_peers; peer++) { rcop = GNUNET_new (struct RunContextOperation); rcop->rc = rc; rcop->op = GNUNET_TESTBED_peer_create (rc->c, (0 == rc->num_hosts) ? rc->h : rc->hosts[peer % rc->num_hosts], rc->cfg, &peer_create_cb, rcop); GNUNET_assert (NULL != rcop->op); insert_rcop (rc, rcop); } } /** * Signature of the event handler function called by the * respective event controller. * * @param cls closure * @param event information about the event */ static void event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop; if (RC_INIT == rc->state) { switch (event->type) { case GNUNET_TESTBED_ET_OPERATION_FINISHED: rcop = event->op_cls; if (NULL != event->details.operation_finished.emsg) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Linking controllers failed. Exiting")); GNUNET_SCHEDULER_shutdown (); } else rc->reg_hosts++; GNUNET_assert (event->op == rcop->op); remove_rcop (rc, rcop); GNUNET_TESTBED_operation_done (rcop->op); GNUNET_free (rcop); if (rc->reg_hosts == rc->num_hosts) { rc->state = RC_LINKED; create_peers (rc); } return; default: GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } } if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type) goto call_cc; if (NULL == (rcop = search_rcop (rc, event->op))) goto call_cc; remove_rcop (rc, rcop); GNUNET_TESTBED_operation_done (rcop->op); GNUNET_free (rcop); if ( (GNUNET_NO == rc->shutdown) && (NULL != event->details.operation_finished.emsg) ) { LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n", event->details.operation_finished.emsg); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_assert (GNUNET_YES == rc->shutdown); switch (rc->state) { case RC_LINKED: case RC_PEERS_CREATED: case RC_READY: rc->state = RC_PEERS_SHUTDOWN; GNUNET_free_non_null (rc->peers); rc->peers = NULL; DEBUG ("Peers shut down in %s\n", prof_time (rc)); GNUNET_SCHEDULER_shutdown (); break; default: GNUNET_assert (0); } return; call_cc: if ((0 != (rc->event_mask & (1LL << event->type))) && (NULL != rc->cc)) rc->cc (rc->cc_cls, event); if (GNUNET_TESTBED_ET_PEER_START != event->type) return; if (NULL == (rcop = search_rcop (rc, event->op))) /* Not our operation */ return; remove_rcop (rc, rcop); GNUNET_TESTBED_operation_done (rcop->op); GNUNET_free (rcop); rc->peer_count++; if (rc->peer_count < rc->num_peers) return; DEBUG ("%u peers started in %s\n", rc->num_peers, prof_time (rc)); if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology) { switch (rc->topology) { case GNUNET_TESTBED_TOPOLOGY_NONE: GNUNET_assert (0); case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: rc->topology_operation = GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, rc->peers, &rc->num_oc, &topology_completion_callback, rc, rc->topology, rc->random_links, GNUNET_TESTBED_TOPOLOGY_OPTION_END); break; case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: GNUNET_assert (NULL != rc->topo_file); rc->topology_operation = GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, rc->peers, &rc->num_oc, &topology_completion_callback, rc, rc->topology, rc->topo_file, GNUNET_TESTBED_TOPOLOGY_OPTION_END); break; case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: { unsigned long long number; unsigned int cap; GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, SCALE_FREE_CAP, &number)); cap = (unsigned int) number; GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, SCALE_FREE_M, &number)); rc->topology_operation = GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, rc->peers, &rc->num_oc, &topology_completion_callback, rc, rc->topology, cap, /* uint16_t */ (unsigned int) number, /* uint8_t */ GNUNET_TESTBED_TOPOLOGY_OPTION_END); } break; default: rc->topology_operation = GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers, rc->peers, &rc->num_oc, &topology_completion_callback, rc, rc->topology, GNUNET_TESTBED_TOPOLOGY_OPTION_END); } if (NULL == rc->topology_operation) LOG (GNUNET_ERROR_TYPE_WARNING, "Not generating a topology. Check number of peers\n"); else { DEBUG ("Creating overlay topology\n"); rc->pstart_time = GNUNET_TIME_absolute_get (); return; } } rc->state = RC_READY; call_master (rc); } /** * Task to register all hosts available in the global host list * * @param cls the RunContext * @param tc the scheduler task context */ static void register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Callback which will be called to after a host registration succeeded or failed * * @param cls the closure * @param emsg the error message; NULL if host registration is successful */ static void host_registration_completion (void *cls, const char *emsg) { struct GNUNET_TESTBED_RunHandle *rc = cls; rc->reg_handle = NULL; if (NULL != emsg) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Host registration failed for a host. Error: %s\n"), emsg); GNUNET_SCHEDULER_shutdown (); return; } rc->register_hosts_task = GNUNET_SCHEDULER_add_now (®ister_hosts, rc); } /** * Task to register all hosts available in the global host list * * @param cls RunContext * @param tc the scheduler task context */ static void register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_RunHandle *rc = cls; struct RunContextOperation *rcop; unsigned int slave; rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK; if (rc->reg_hosts == rc->num_hosts) { DEBUG ("All hosts successfully registered\n"); /* Start slaves */ for (slave = 0; slave < rc->num_hosts; slave++) { rcop = GNUNET_new (struct RunContextOperation); rcop->rc = rc; rcop->op = GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[slave], rc->h, GNUNET_YES); GNUNET_assert (NULL != rcop->op); insert_rcop (rc, rcop); } rc->reg_hosts = 0; return; } rc->reg_handle = GNUNET_TESTBED_register_host (rc->c, rc->hosts[rc->reg_hosts], host_registration_completion, rc); rc->reg_hosts++; } /** * Callback to signal successfull startup of the controller process * * @param cls the closure from GNUNET_TESTBED_controller_start() * @param cfg the configuration with which the controller has been started; * NULL if status is not GNUNET_OK * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ static void controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, int status) { struct GNUNET_TESTBED_RunHandle *rc = cls; uint64_t event_mask; if (status != GNUNET_OK) { rc->cproc = NULL; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Controller crash detected. Shutting down.\n")); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_CONFIGURATION_destroy (rc->cfg); rc->cfg = GNUNET_CONFIGURATION_dup (cfg); event_mask = rc->event_mask; event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE) event_mask |= GNUNET_TESTBED_ET_CONNECT; rc->c = GNUNET_TESTBED_controller_connect (rc->h, event_mask, &event_cb, rc); if (0 < rc->num_hosts) { rc->reg_hosts = 0; rc->register_hosts_task = GNUNET_SCHEDULER_add_now (®ister_hosts, rc); return; } rc->state = RC_LINKED; create_peers (rc); } /** * Callback function invoked for each interface found. * * @param cls closure * @param name name of the interface (can be NULL for unknown) * @param isDefault is this presumably the default interface * @param addr address of this interface (can be NULL for unknown or unassigned) * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) * @param netmask the network mask (can be NULL for unknown or unassigned)) * @param addrlen length of the address * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort */ static int netint_proc (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen) { struct GNUNET_TESTBED_RunHandle *rc = cls; char hostip[NI_MAXHOST]; char *buf; if (sizeof (struct sockaddr_in) != addrlen) return GNUNET_OK; /* Only consider IPv4 for now */ if (0 != getnameinfo (addr, addrlen, hostip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getnameinfo"); if (NULL == rc->trusted_ip) { rc->trusted_ip = GNUNET_strdup (hostip); return GNUNET_YES; } (void) GNUNET_asprintf (&buf, "%s; %s", rc->trusted_ip, hostip); GNUNET_free (rc->trusted_ip); rc->trusted_ip = buf; return GNUNET_YES; } /** * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to * inform whether the given host is habitable or not. The Handle returned by * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called * * @param cls NULL * @param host the host whose status is being reported; will be NULL if the host * given to GNUNET_TESTBED_is_host_habitable() is NULL * @param status GNUNET_YES if it is habitable; GNUNET_NO if not */ static void host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, int status) { struct CompatibilityCheckContext *hc = cls; struct GNUNET_TESTBED_RunHandle *rc; struct GNUNET_TESTBED_Host **old_hosts; unsigned int nhost; GNUNET_assert (NULL != (rc = hc->rc)); nhost = hc->index; GNUNET_assert (nhost <= rc->num_hosts); GNUNET_assert (host == rc->hosts[nhost]); hc->h = NULL; if (GNUNET_NO == status) { if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host))) LOG (GNUNET_ERROR_TYPE_ERROR, _("Host %s cannot start testbed\n"), GNUNET_TESTBED_host_get_hostname (host)); else LOG (GNUNET_ERROR_TYPE_ERROR, _("Testbed cannot be started on localhost\n")); GNUNET_SCHEDULER_shutdown (); return; } rc->reg_hosts++; if (rc->reg_hosts < rc->num_hosts) return; GNUNET_free (rc->hclist); rc->hclist = NULL; rc->h = rc->hosts[0]; rc->num_hosts--; if (0 < rc->num_hosts) { old_hosts = rc->hosts; rc->hosts = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host *) * rc->num_hosts); memcpy (rc->hosts, &old_hosts[1], (sizeof (struct GNUNET_TESTBED_Host *) * rc->num_hosts)); GNUNET_free (old_hosts); } else { GNUNET_free (rc->hosts); rc->hosts = NULL; } GNUNET_TESTBED_host_resolve_ (rc->h); for (nhost = 0; nhost < rc->num_hosts; nhost++) GNUNET_TESTBED_host_resolve_ (rc->hosts[nhost]); GNUNET_OS_network_interfaces_list (netint_proc, rc); if (NULL == rc->trusted_ip) rc->trusted_ip = GNUNET_strdup ("127.0.0.1"); rc->cproc = GNUNET_TESTBED_controller_start (rc->trusted_ip, rc->h, &controller_status_cb, rc); GNUNET_free (rc->trusted_ip); rc->trusted_ip = NULL; if (NULL == rc->cproc) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot start the master controller")); GNUNET_SCHEDULER_shutdown (); } } /** * Task run upon timeout while setting up the testbed * * @param cls the RunContext * @param tc the task context */ static void timeout_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_RunHandle *rc = cls; rc->timeout_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_ERROR, _("Shutting down testbed due to timeout while setup.\n")); GNUNET_SCHEDULER_shutdown (); if (NULL != rc->test_master) rc->test_master (rc->test_master_cls, rc, 0, NULL, 0, 0); rc->test_master = NULL; } /** * Convenience method for running a testbed with * a single call. Underlay and overlay topology * are configured using the "UNDERLAY" and "OVERLAY" * options in the "[testbed]" section of the configuration\ * (with possible options given in "UNDERLAY_XXX" and/or * "OVERLAY_XXX"). * * The testbed is to be terminated using a call to * "GNUNET_SCHEDULER_shutdown". * * @param host_filename name of the file with the 'hosts', NULL * to run everything on 'localhost' * @param cfg configuration to use (for testbed, controller and peers) * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg? * @param event_mask bit mask with set of events to call 'cc' for; * or-ed values of "1LL" shifted by the * respective 'enum GNUNET_TESTBED_EventType' * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...") * @param cc controller callback to invoke on events; This callback is called * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't * set in the event_mask as this is the only way get access to the * handle of each peer * @param cc_cls closure for cc * @param test_master this callback will be called once the test is ready * @param test_master_cls closure for 'test_master'. */ void GNUNET_TESTBED_run (const char *host_filename, const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, uint64_t event_mask, GNUNET_TESTBED_ControllerCallback cc, void *cc_cls, GNUNET_TESTBED_TestMaster test_master, void *test_master_cls) { struct GNUNET_TESTBED_RunHandle *rc; char *topology; struct CompatibilityCheckContext *hc; struct GNUNET_TIME_Relative timeout; unsigned long long number; unsigned int hid; unsigned int nhost; GNUNET_assert (num_peers > 0); rc = GNUNET_new (struct GNUNET_TESTBED_RunHandle); rc->cfg = GNUNET_CONFIGURATION_dup (cfg); #if ENABLE_SUPERMUC rc->num_hosts = GNUNET_TESTBED_hosts_load_from_loadleveler (rc->cfg, &rc->hosts); if (0 == rc->num_hosts) { LOG (GNUNET_ERROR_TYPE_WARNING, _("No hosts loaded from LoadLeveler. Need at least one host\n")); goto error_cleanup; } #else if (NULL != host_filename) { rc->num_hosts = GNUNET_TESTBED_hosts_load_from_file (host_filename, rc->cfg, &rc->hosts); if (0 == rc->num_hosts) { LOG (GNUNET_ERROR_TYPE_WARNING, _("No hosts loaded. Need at least one host\n")); goto error_cleanup; } } else rc->h = GNUNET_TESTBED_host_create (NULL, NULL, rc->cfg, 0); #endif rc->num_peers = num_peers; rc->event_mask = event_mask; rc->cc = cc; rc->cc_cls = cc_cls; rc->test_master = test_master; rc->test_master_cls = test_master_cls; rc->state = RC_INIT; rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (rc->cfg, TESTBED_CONFIG_SECTION, "OVERLAY_TOPOLOGY", &topology)) { if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology, topology)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, "OVERLAY_TOPLOGY", _ ("Specified topology must be supported by testbed")); } GNUNET_free (topology); } switch (rc->topology) { case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, "OVERLAY_RANDOM_LINKS", &number)) { /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS * option to be set to the number of random links to be established */ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, "OVERLAY_RANDOM_LINKS"); goto error_cleanup; } if (number > UINT32_MAX) { GNUNET_break (0); /* Too big number */ goto error_cleanup; } rc->random_links = (unsigned int) number; break; case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (rc->cfg, TESTBED_CONFIG_SECTION, "OVERLAY_TOPOLOGY_FILE", &rc->topo_file)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, "OVERLAY_TOPOLOGY_FILE"); goto error_cleanup; } goto warn_ignore; case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, SCALE_FREE_CAP, &number)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, SCALE_FREE_CAP); goto error_cleanup; } if (UINT16_MAX < number) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Maximum number of edges a peer can have in a scale free topology" " cannot be more than %u. Given `%s = %llu'"), UINT16_MAX, SCALE_FREE_CAP, number); goto error_cleanup; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION, SCALE_FREE_M, &number)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION, SCALE_FREE_M); goto error_cleanup; } if (UINT8_MAX < number) { LOG (GNUNET_ERROR_TYPE_ERROR, _("The number of edges that can established when adding a new node" " to scale free topology cannot be more than %u. Given `%s = %llu'"), UINT8_MAX, SCALE_FREE_M, number); goto error_cleanup; } goto warn_ignore; default: warn_ignore: /* Warn if OVERLAY_RANDOM_LINKS is present that it will be ignored */ if (GNUNET_YES == GNUNET_CONFIGURATION_have_value (rc->cfg, TESTBED_CONFIG_SECTION, "OVERLAY_RANDOM_LINKS")) LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring value of `OVERLAY_RANDOM_LINKS' in given configuration\n"); break; } if (0 != rc->num_hosts) { rc->hclist = GNUNET_malloc (sizeof (struct CompatibilityCheckContext) * rc->num_hosts); for (nhost = 0; nhost < rc->num_hosts; nhost++) { hc = &rc->hclist[nhost]; hc->index = nhost; hc->rc = rc; hc->h = GNUNET_TESTBED_is_host_habitable (rc->hosts[nhost], rc->cfg, &host_habitable_cb, hc); if (NULL == hc->h) { GNUNET_break (0); for (nhost = 0; nhost < rc->num_hosts; nhost++) { hc = &rc->hclist[nhost]; if (NULL != hc->h) GNUNET_TESTBED_is_host_habitable_cancel (hc->h); } GNUNET_free (rc->hclist); rc->hclist = NULL; goto error_cleanup; } } } else rc->cproc = GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, &controller_status_cb, rc); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, TESTBED_CONFIG_SECTION, "SETUP_TIMEOUT", &timeout)) { timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, DEFAULT_SETUP_TIMEOUT); } rc->rcop_map = GNUNET_CONTAINER_multihashmap32_create (256); rc->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc); rc->interrupt_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &interrupt, rc); return; error_cleanup: if (NULL != rc->h) GNUNET_TESTBED_host_destroy (rc->h); if (NULL != rc->hosts) { for (hid = 0; hid < rc->num_hosts; hid++) if (NULL != rc->hosts[hid]) GNUNET_TESTBED_host_destroy (rc->hosts[hid]); GNUNET_free (rc->hosts); } if (NULL != rc->cfg) GNUNET_CONFIGURATION_destroy (rc->cfg); GNUNET_free (rc); } /** * Obtain handle to the master controller from a testbed run. The handle * returned should not be disconnected. * * @param h the testbed run handle * @return handle to the master controller */ struct GNUNET_TESTBED_Controller * GNUNET_TESTBED_run_get_controller_handle (struct GNUNET_TESTBED_RunHandle *h) { return h->c; } /* end of testbed_api_testbed.c */ gnunet-0.10.1/src/testbed/testbed_api_barriers.c0000644000175000017500000003523512255010512016554 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_barriers.c * @brief API implementation for testbed barriers * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_testbed_service.h" #include "testbed_api.h" #include "testbed_api_barriers.h" /** * Logging shorthand */ #define LOG(type, ...) \ GNUNET_log_from (type, "testbed-api-barriers", __VA_ARGS__); /** * Debug logging shorthand */ #define LOG_DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__); /** * Handle for barrier */ struct GNUNET_TESTBED_Barrier { /** * hashcode identifying this barrier in the hashmap */ struct GNUNET_HashCode key; /** * The controller handle given while initiliasing this barrier */ struct GNUNET_TESTBED_Controller *c; /** * The name of the barrier */ char *name; /** * The continuation callback to call when we have a status update on this */ GNUNET_TESTBED_barrier_status_cb cb; /** * the closure for the above callback */ void *cls; /** * Should the barrier crossed status message be echoed back to the controller? */ int echo; }; /** * handle for hashtable of barrier handles */ static struct GNUNET_CONTAINER_MultiHashMap *barrier_map; /** * Remove a barrier and it was the last one in the barrier hash map, destroy the * hash map * * @param barrier the barrier to remove */ static void barrier_remove (struct GNUNET_TESTBED_Barrier *barrier) { GNUNET_assert (NULL != barrier_map); /* No barriers present */ GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (barrier_map, &barrier->key, barrier)); GNUNET_free (barrier->name); GNUNET_free (barrier); if (0 == GNUNET_CONTAINER_multihashmap_size (barrier_map)) { GNUNET_CONTAINER_multihashmap_destroy (barrier_map); barrier_map = NULL; } } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages * * @param c the controller handle to determine the connection this message * belongs to * @param msg the barrier status message * @return GNUNET_OK to keep the connection active; GNUNET_SYSERR to tear it * down signalling an error */ int GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_BarrierStatusMsg *msg) { struct GNUNET_TESTBED_Barrier *barrier; char *emsg; const char *name; struct GNUNET_HashCode key; size_t emsg_len; int status; uint16_t msize; uint16_t name_len; emsg = NULL; barrier = NULL; msize = ntohs (msg->header.size); name = msg->data; name_len = ntohs (msg->name_len); LOG_DEBUG ("Received BARRIER_STATUS msg\n"); if (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1 > msize) { GNUNET_break_op (0); return GNUNET_SYSERR; } if ('\0' != name[name_len]) { GNUNET_break_op (0); return GNUNET_SYSERR; } status = ntohs (msg->status); if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status) { status = -1; emsg_len = msize - (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1); if (0 == emsg_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } emsg_len++; emsg = GNUNET_malloc (emsg_len); emsg_len--; emsg[emsg_len] = '\0'; (void) memcpy (emsg, msg->data + name_len + 1, emsg_len); } if (NULL == barrier_map) { GNUNET_break_op (0); goto cleanup; } GNUNET_CRYPTO_hash (name, name_len, &key); barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key); if (NULL == barrier) { GNUNET_break_op (0); goto cleanup; } GNUNET_assert (NULL != barrier->cb); if ((GNUNET_YES == barrier->echo) && (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status)) GNUNET_TESTBED_queue_message_ (c, GNUNET_copy_message (&msg->header)); barrier->cb (barrier->cls, name, barrier, status, emsg); if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED == status) return GNUNET_OK; /* just initialised; skip cleanup */ cleanup: GNUNET_free_non_null (emsg); if (NULL != barrier) barrier_remove (barrier); return GNUNET_OK; } /** * Initialise a barrier and call the given callback when the required percentage * of peers (quorum) reach the barrier OR upon error. * * @param controller the handle to the controller * @param name identification name of the barrier * @param quorum the percentage of peers that is required to reach the barrier. * Peers signal reaching a barrier by calling * GNUNET_TESTBED_barrier_reached(). * @param cb the callback to call when the barrier is reached or upon error. * Cannot be NULL. * @param cls closure for the above callback * @param echo GNUNET_YES to echo the barrier crossed status message back to the * controller * @return barrier handle; NULL upon error */ struct GNUNET_TESTBED_Barrier * GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller, const char *name, unsigned int quorum, GNUNET_TESTBED_barrier_status_cb cb, void *cls, int echo) { struct GNUNET_TESTBED_BarrierInit *msg; struct GNUNET_TESTBED_Barrier *barrier; struct GNUNET_HashCode key; size_t name_len; uint16_t msize; GNUNET_assert (quorum <= 100); GNUNET_assert (NULL != cb); name_len = strlen (name); GNUNET_assert (0 < name_len); GNUNET_CRYPTO_hash (name, name_len, &key); if (NULL == barrier_map) barrier_map = GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (barrier_map, &key)) { GNUNET_break (0); return NULL; } LOG_DEBUG ("Initialising barrier `%s'\n", name); barrier = GNUNET_new (struct GNUNET_TESTBED_Barrier); barrier->c = controller; barrier->name = GNUNET_strdup (name); barrier->cb = cb; barrier->cls = cls; barrier->echo = echo; (void) memcpy (&barrier->key, &key, sizeof (struct GNUNET_HashCode)); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (barrier_map, &barrier->key, barrier, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); msize = name_len + sizeof (struct GNUNET_TESTBED_BarrierInit); msg = GNUNET_malloc (msize); msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT); msg->quorum = (uint8_t) quorum; (void) memcpy (msg->name, barrier->name, name_len); GNUNET_TESTBED_queue_message_ (barrier->c, &msg->header); return barrier; } /** * Initialise a barrier and call the given callback when the required percentage * of peers (quorum) reach the barrier OR upon error. * * @param controller the handle to the controller * @param name identification name of the barrier * @param quorum the percentage of peers that is required to reach the barrier. * Peers signal reaching a barrier by calling * GNUNET_TESTBED_barrier_reached(). * @param cb the callback to call when the barrier is reached or upon error. * Cannot be NULL. * @param cls closure for the above callback * @return barrier handle; NULL upon error */ struct GNUNET_TESTBED_Barrier * GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, const char *name, unsigned int quorum, GNUNET_TESTBED_barrier_status_cb cb, void *cls) { return GNUNET_TESTBED_barrier_init_ (controller, name, quorum, cb, cls, GNUNET_YES); } /** * Cancel a barrier. * * @param barrier the barrier handle */ void GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier) { struct GNUNET_TESTBED_BarrierCancel *msg; uint16_t msize; msize = sizeof (struct GNUNET_TESTBED_BarrierCancel) + strlen (barrier->name); msg = GNUNET_malloc (msize); msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL); (void) memcpy (msg->name, barrier->name, strlen (barrier->name)); GNUNET_TESTBED_queue_message_ (barrier->c, &msg->header); barrier_remove (barrier); } /** * Barrier wait handle */ struct GNUNET_TESTBED_BarrierWaitHandle { /** * The name of the barrier */ char *name; /** * Then configuration used for the client connection */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The client connection */ struct GNUNET_CLIENT_Connection *conn; /** * Transmit handle */ struct GNUNET_CLIENT_TransmitHandle *tx; /** * The message to transmit with tx */ struct GNUNET_MessageHeader *msg; /** * The barrier wait callback */ GNUNET_TESTBED_barrier_wait_cb cb; /** * The closure for the above callback */ void *cls; }; /** * Function to destroy barrier wait handle * * @param h the handle to destroy */ static void destroy_handle (struct GNUNET_TESTBED_BarrierWaitHandle *h) { GNUNET_free (h->name); if (NULL != h->tx) GNUNET_CLIENT_notify_transmit_ready_cancel (h->tx); if (NULL != h->conn) GNUNET_CLIENT_disconnect (h->conn); if (NULL != h->msg) GNUNET_free (h->msg); GNUNET_CONFIGURATION_destroy (h->cfg); GNUNET_free (h); } /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param message received message; NULL on timeout or fatal error */ static void receive_handler (void *cls, const struct GNUNET_MessageHeader *message) { struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; const struct GNUNET_TESTBED_BarrierStatusMsg *msg; uint16_t msize; if (NULL == message) { GNUNET_break_op (0); goto fail; } if (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS != ntohs (message->type)) { GNUNET_break_op (0); goto fail; } msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg)) { GNUNET_break_op (0); goto fail; } msg = (const struct GNUNET_TESTBED_BarrierStatusMsg *) message; switch (ntohs (msg->status)) { case GNUNET_TESTBED_BARRIERSTATUS_ERROR: goto fail; case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: GNUNET_break (0); /* FIXME */ goto destroy; case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: h->cb (h->cls, h->name, GNUNET_OK); goto destroy; default: GNUNET_break_op (0); } fail: h->cb (h->cls, h->name, GNUNET_SYSERR); destroy: destroy_handle (h); } /** * Function called to notify a client about the connection * begin ready to queue more data. "buf" will be * NULL and "size" zero if the connection was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_notify (void *cls, size_t size, void *buf) { struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; uint16_t msize; h->tx = NULL; if ((0 == size) || (NULL == buf)) { destroy_handle (h); return 0; } msize = htons (h->msg->size); GNUNET_assert (msize <= size); (void) memcpy (buf, h->msg, msize); GNUNET_free (h->msg); h->msg = NULL; GNUNET_CLIENT_receive (h->conn, &receive_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); return msize; } /** * Wait for a barrier to be crossed. This function should be called by the * peers which have been started by the testbed. If the peer is not started by * testbed this function may return error * * @param name the name of the barrier * @param cb the barrier wait callback * @param cls the closure for the above callback * @return barrier wait handle which can be used to cancel the waiting at * anytime before the callback is called. NULL upon error. */ struct GNUNET_TESTBED_BarrierWaitHandle * GNUNET_TESTBED_barrier_wait (const char *name, GNUNET_TESTBED_barrier_wait_cb cb, void *cls) { struct GNUNET_TESTBED_BarrierWait *msg; struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_TESTBED_BarrierWaitHandle *h; char *cfg_filename; size_t name_len; uint16_t msize; GNUNET_assert (NULL != cb); GNUNET_assert (NULL != name); cfg_filename = getenv (ENV_TESTBED_CONFIG); if (NULL == cfg_filename) { LOG (GNUNET_ERROR_TYPE_ERROR, "Are you running under testbed?\n"); return NULL; } cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_filename)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Unable to load configuration from file `%s'\n", cfg_filename); GNUNET_CONFIGURATION_destroy (cfg); return NULL; } h = GNUNET_new (struct GNUNET_TESTBED_BarrierWaitHandle); h->name = GNUNET_strdup (name); h->cfg = cfg; h->conn = GNUNET_CLIENT_connect ("testbed-barrier", h->cfg); h->cb = cb; h->cls = cls; if (NULL == h->conn) { LOG (GNUNET_ERROR_TYPE_ERROR, "Unable to connect to local testbed-barrier service\n"); destroy_handle (h); return NULL; } name_len = strlen (name); msize = sizeof (struct GNUNET_TESTBED_BarrierWait) + name_len; msg = GNUNET_malloc (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT); msg->header.size = htons (msize); (void) memcpy (msg->name, name, name_len); h->msg = &msg->header; h->tx = GNUNET_CLIENT_notify_transmit_ready (h->conn, msize, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_notify, h); return h; } /** * Cancel a barrier wait handle * * @param h the barrier wait handle */ void GNUNET_TESTBED_barrier_wait_cancel (struct GNUNET_TESTBED_BarrierWaitHandle *h) { destroy_handle (h); } /* end of testbed_api_barriers.c */ gnunet-0.10.1/src/testbed/gnunet-service-testbed_cpustatus.c0000644000175000017500000005407012276375236021123 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_cpustatus.c * @brief calls to determine current CPU load * @author Tzvetan Horozov * @author Christian Grothoff * @author Igor Wronsky * @author Alex Harper (OS X portion) * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet-service-testbed_meminfo.h" #if SOLARIS #if HAVE_KSTAT_H #include #endif #if HAVE_SYS_SYSINFO_H #include #endif #if HAVE_KVM_H #include #endif #endif #if SOMEBSD #if HAVE_KVM_H #include #endif #endif #ifdef OSX #include static processor_cpu_load_info_t prev_cpu_load; #endif #ifdef WINDOWS #include #endif #define DEBUG_STATUSCALLS GNUNET_NO #ifdef LINUX static FILE *proc_stat; #endif /** * Current CPU load, as percentage of CPU cycles not idle or * blocked on IO. */ static int currentCPULoad; static double agedCPULoad = -1; /** * Current IO load, as percentage of CPU cycles blocked on IO. */ static int currentIOLoad; static double agedIOLoad = -1; /** * hanlde to the file to write the load statistics to */ struct GNUNET_BIO_WriteHandle *bw; GNUNET_SCHEDULER_TaskIdentifier sample_load_task_id; #ifdef OSX static int initMachCpuStats () { unsigned int cpu_count; processor_cpu_load_info_t cpu_load; mach_msg_type_number_t cpu_msg_count; kern_return_t kret; int i, j; kret = host_processor_info (mach_host_self (), PROCESSOR_CPU_LOAD_INFO, &cpu_count, (processor_info_array_t *) & cpu_load, &cpu_msg_count); if (kret != KERN_SUCCESS) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "host_processor_info failed."); return GNUNET_SYSERR; } prev_cpu_load = GNUNET_malloc (cpu_count * sizeof (*prev_cpu_load)); for (i = 0; i < cpu_count; i++) { for (j = 0; j < CPU_STATE_MAX; j++) { prev_cpu_load[i].cpu_ticks[j] = cpu_load[i].cpu_ticks[j]; } } vm_deallocate (mach_task_self (), (vm_address_t) cpu_load, (vm_size_t) (cpu_msg_count * sizeof (*cpu_load))); return GNUNET_OK; } #endif /** * Update the currentCPU and currentIO load (and on Linux, memory) values. * * Before its first invocation the method initStatusCalls() must be called. * If there is an error the method returns -1. */ static int updateUsage () { currentIOLoad = -1; currentCPULoad = -1; #ifdef LINUX /* under linux, first try %idle/usage using /proc/stat; if that does not work, disable /proc/stat for the future by closing the file and use the next-best method. */ if (proc_stat != NULL) { static unsigned long long last_cpu_results[5] = { 0, 0, 0, 0, 0 }; static int have_last_cpu = GNUNET_NO; int ret; char line[256]; unsigned long long user_read, system_read, nice_read, idle_read, iowait_read; unsigned long long user, system, nice, idle, iowait; unsigned long long usage_time = 0, total_time = 1; /* Get the first line with the data */ rewind (proc_stat); fflush (proc_stat); if (NULL == fgets (line, 256, proc_stat)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fgets", "/proc/stat"); proc_stat = NULL; /* don't try again */ } else { iowait_read = 0; ret = sscanf (line, "%*s %llu %llu %llu %llu %llu", &user_read, &system_read, &nice_read, &idle_read, &iowait_read); if (ret < 4) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fgets-sscanf", "/proc/stat"); fclose (proc_stat); proc_stat = NULL; /* don't try again */ have_last_cpu = GNUNET_NO; } else { /* Store the current usage */ user = user_read - last_cpu_results[0]; system = system_read - last_cpu_results[1]; nice = nice_read - last_cpu_results[2]; idle = idle_read - last_cpu_results[3]; iowait = iowait_read - last_cpu_results[4]; /* Calculate the % usage */ usage_time = user + system + nice; total_time = usage_time + idle + iowait; if ((total_time > 0) && (have_last_cpu == GNUNET_YES)) { currentCPULoad = (int) (100L * usage_time / total_time); if (ret > 4) currentIOLoad = (int) (100L * iowait / total_time); else currentIOLoad = -1; /* 2.4 kernel */ } /* Store the values for the next calculation */ last_cpu_results[0] = user_read; last_cpu_results[1] = system_read; last_cpu_results[2] = nice_read; last_cpu_results[3] = idle_read; last_cpu_results[4] = iowait_read; have_last_cpu = GNUNET_YES; return GNUNET_OK; } } } #endif #ifdef OSX { unsigned int cpu_count; processor_cpu_load_info_t cpu_load; mach_msg_type_number_t cpu_msg_count; unsigned long long t_sys, t_user, t_nice, t_idle, t_total; unsigned long long t_idle_all, t_total_all; kern_return_t kret; int i, j; t_idle_all = t_total_all = 0; kret = host_processor_info (mach_host_self (), PROCESSOR_CPU_LOAD_INFO, &cpu_count, (processor_info_array_t *) & cpu_load, &cpu_msg_count); if (kret == KERN_SUCCESS) { for (i = 0; i < cpu_count; i++) { if (cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] >= prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM]) { t_sys = cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] - prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM]; } else { t_sys = cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_SYSTEM] + 1); } if (cpu_load[i].cpu_ticks[CPU_STATE_USER] >= prev_cpu_load[i].cpu_ticks[CPU_STATE_USER]) { t_user = cpu_load[i].cpu_ticks[CPU_STATE_USER] - prev_cpu_load[i].cpu_ticks[CPU_STATE_USER]; } else { t_user = cpu_load[i].cpu_ticks[CPU_STATE_USER] + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_USER] + 1); } if (cpu_load[i].cpu_ticks[CPU_STATE_NICE] >= prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE]) { t_nice = cpu_load[i].cpu_ticks[CPU_STATE_NICE] - prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE]; } else { t_nice = cpu_load[i].cpu_ticks[CPU_STATE_NICE] + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_NICE] + 1); } if (cpu_load[i].cpu_ticks[CPU_STATE_IDLE] >= prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE]) { t_idle = cpu_load[i].cpu_ticks[CPU_STATE_IDLE] - prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE]; } else { t_idle = cpu_load[i].cpu_ticks[CPU_STATE_IDLE] + (ULONG_MAX - prev_cpu_load[i].cpu_ticks[CPU_STATE_IDLE] + 1); } t_total = t_sys + t_user + t_nice + t_idle; t_idle_all += t_idle; t_total_all += t_total; } for (i = 0; i < cpu_count; i++) { for (j = 0; j < CPU_STATE_MAX; j++) { prev_cpu_load[i].cpu_ticks[j] = cpu_load[i].cpu_ticks[j]; } } if (t_total_all > 0) currentCPULoad = 100 - (100 * t_idle_all) / t_total_all; else currentCPULoad = -1; vm_deallocate (mach_task_self (), (vm_address_t) cpu_load, (vm_size_t) (cpu_msg_count * sizeof (*cpu_load))); currentIOLoad = -1; /* FIXME-OSX! */ return GNUNET_OK; } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "host_processor_info failed."); return GNUNET_SYSERR; } } #endif /* try kstat (Solaris only) */ #if SOLARIS && HAVE_KSTAT_H && HAVE_SYS_SYSINFO_H { static long long last_idlecount; static long long last_totalcount; static int kstat_once; /* if open fails, don't keep trying */ kstat_ctl_t *kc; kstat_t *khelper; long long idlecount; long long totalcount; long long deltaidle; long long deltatotal; if (kstat_once == 1) goto ABORT_KSTAT; kc = kstat_open (); if (kc == NULL) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kstat_close"); goto ABORT_KSTAT; } idlecount = 0; totalcount = 0; for (khelper = kc->kc_chain; khelper != NULL; khelper = khelper->ks_next) { cpu_stat_t stats; if (0 != strncmp (khelper->ks_name, "cpu_stat", strlen ("cpu_stat"))) continue; if (khelper->ks_data_size > sizeof (cpu_stat_t)) continue; /* better save then sorry! */ if (-1 != kstat_read (kc, khelper, &stats)) { idlecount += stats.cpu_sysinfo.cpu[CPU_IDLE]; totalcount += stats.cpu_sysinfo.cpu[CPU_IDLE] + stats.cpu_sysinfo.cpu[CPU_USER] + stats.cpu_sysinfo.cpu[CPU_KERNEL] + stats.cpu_sysinfo.cpu[CPU_WAIT]; } } if (0 != kstat_close (kc)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kstat_close"); if ((idlecount == 0) && (totalcount == 0)) goto ABORT_KSTAT; /* no stats found => abort */ deltaidle = idlecount - last_idlecount; deltatotal = totalcount - last_totalcount; if ((deltatotal > 0) && (last_totalcount > 0)) { currentCPULoad = (unsigned int) (100.0 * deltaidle / deltatotal); if (currentCPULoad > 100) currentCPULoad = 100; /* odd */ if (currentCPULoad < 0) currentCPULoad = 0; /* odd */ currentCPULoad = 100 - currentCPULoad; /* computed idle-load before! */ } else currentCPULoad = -1; currentIOLoad = -1; /* FIXME-SOLARIS! */ last_idlecount = idlecount; last_totalcount = totalcount; return GNUNET_OK; ABORT_KSTAT: kstat_once = 1; /* failed, don't try again */ return GNUNET_SYSERR; } #endif /* insert methods better than getloadavg for other platforms HERE! */ /* ok, maybe we have getloadavg on this platform */ #if HAVE_GETLOADAVG { static int warnOnce = 0; double loadavg; if (1 != getloadavg (&loadavg, 1)) { /* only warn once, if there is a problem with getloadavg, we're going to hit it frequently... */ if (warnOnce == 0) { warnOnce = 1; GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getloadavg"); } return GNUNET_SYSERR; } else { /* success with getloadavg */ currentCPULoad = (int) (100 * loadavg); currentIOLoad = -1; /* FIXME */ return GNUNET_OK; } } #endif #if MINGW /* Win NT? */ if (GNNtQuerySystemInformation) { static double dLastKernel; static double dLastIdle; static double dLastUser; double dKernel; double dIdle; double dUser; double dDiffKernel; double dDiffIdle; double dDiffUser; SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION theInfo; if (GNNtQuerySystemInformation (SystemProcessorPerformanceInformation, &theInfo, sizeof (theInfo), NULL) == NO_ERROR) { /* PORT-ME MINGW: Multi-processor? */ dKernel = Li2Double (theInfo.KernelTime); dIdle = Li2Double (theInfo.IdleTime); dUser = Li2Double (theInfo.UserTime); dDiffKernel = dKernel - dLastKernel; dDiffIdle = dIdle - dLastIdle; dDiffUser = dUser - dLastUser; if (((dDiffKernel + dDiffUser) > 0) && (dLastIdle + dLastKernel + dLastUser > 0)) currentCPULoad = 100.0 - (dDiffIdle / (dDiffKernel + dDiffUser)) * 100.0; else currentCPULoad = -1; /* don't know (yet) */ dLastKernel = dKernel; dLastIdle = dIdle; dLastUser = dUser; currentIOLoad = -1; /* FIXME-MINGW */ return GNUNET_OK; } else { /* only warn once, if there is a problem with NtQuery..., we're going to hit it frequently... */ static int once; if (once == 0) { once = 1; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Cannot query the CPU usage (Windows NT).\n"); } return GNUNET_SYSERR; } } else { /* Win 9x */ HKEY hKey; DWORD dwDataSize, dwType, dwDummy; /* Start query */ if (RegOpenKeyEx (HKEY_DYN_DATA, "PerfStats\\StartSrv", 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS) { /* only warn once */ static int once = 0; if (once == 0) { once = 1; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Cannot query the CPU usage (Win 9x)\n"); } } RegOpenKeyEx (HKEY_DYN_DATA, "PerfStats\\StartStat", 0, KEY_ALL_ACCESS, &hKey); dwDataSize = sizeof (dwDummy); RegQueryValueEx (hKey, "KERNEL\\CPUUsage", NULL, &dwType, (LPBYTE) & dwDummy, &dwDataSize); RegCloseKey (hKey); /* Get CPU usage */ RegOpenKeyEx (HKEY_DYN_DATA, "PerfStats\\StatData", 0, KEY_ALL_ACCESS, &hKey); dwDataSize = sizeof (currentCPULoad); RegQueryValueEx (hKey, "KERNEL\\CPUUsage", NULL, &dwType, (LPBYTE) & currentCPULoad, &dwDataSize); RegCloseKey (hKey); currentIOLoad = -1; /* FIXME-MINGW! */ /* Stop query */ RegOpenKeyEx (HKEY_DYN_DATA, "PerfStats\\StopStat", 0, KEY_ALL_ACCESS, &hKey); RegOpenKeyEx (HKEY_DYN_DATA, "PerfStats\\StopSrv", 0, KEY_ALL_ACCESS, &hKey); dwDataSize = sizeof (dwDummy); RegQueryValueEx (hKey, "KERNEL\\CPUUsage", NULL, &dwType, (LPBYTE) & dwDummy, &dwDataSize); RegCloseKey (hKey); return GNUNET_OK; } #endif /* loadaverage not defined and no platform specific alternative defined => default: error */ return GNUNET_SYSERR; } /** * Update load values (if enough time has expired), * including computation of averages. Code assumes * that lock has already been obtained. */ static void updateAgedLoad () { static struct GNUNET_TIME_Absolute lastCall; struct GNUNET_TIME_Relative age; age = GNUNET_TIME_absolute_get_duration (lastCall); if ( (agedCPULoad == -1) || (age.rel_value_us > 500000) ) { /* use smoothing, but do NOT update lastRet at frequencies higher than 500ms; this makes the smoothing (mostly) independent from the frequency at which getCPULoad is called (and we don't spend more time measuring CPU than actually computing something). */ lastCall = GNUNET_TIME_absolute_get (); updateUsage (); if (currentCPULoad == -1) { agedCPULoad = -1; } else { if (agedCPULoad == -1) { agedCPULoad = currentCPULoad; } else { /* for CPU, we don't do the 'fast increase' since CPU is much more jitterish to begin with */ agedCPULoad = (agedCPULoad * 31 + currentCPULoad) / 32; } } if (currentIOLoad == -1) { agedIOLoad = -1; } else { if (agedIOLoad == -1) { agedIOLoad = currentIOLoad; } else { /* for IO, we don't do the 'fast increase' since IO is much more jitterish to begin with */ agedIOLoad = (agedIOLoad * 31 + currentIOLoad) / 32; } } } } /** * Get the load of the CPU relative to what is allowed. * @return the CPU load as a percentage of allowed * (100 is equivalent to full load) */ static int cpu_get_load () { updateAgedLoad (); return (int) agedCPULoad; } /** * Get the load of the CPU relative to what is allowed. * @return the CPU load as a percentage of allowed * (100 is equivalent to full load) */ static int disk_get_load () { updateAgedLoad (); return (int) agedIOLoad; } /** * Get the percentage of memory used * * @return the percentage of memory used */ static unsigned int mem_get_usage () { double percentage; meminfo (); percentage = ( ((double) kb_main_used) / ((double) kb_main_total) * 100.0 ); return (unsigned int) percentage; } #ifdef LINUX #include /** * Returns the number of processes * * @return the number of processes */ static unsigned int get_nproc () { DIR *dir; struct dirent *ent; unsigned int nproc; dir = opendir ("/proc"); if (NULL == dir) return 0; nproc = 0; while (NULL != (ent = readdir (dir))) { if((*ent->d_name > '0') && (*ent->d_name <= '9')) nproc++; } closedir (dir); return nproc; } #endif static void sample_load_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Absolute now; char *str; int nbs; int ld_cpu; int ld_disk; unsigned int mem_usage; unsigned int nproc; sample_load_task_id = GNUNET_SCHEDULER_NO_TASK; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; ld_cpu = cpu_get_load (); ld_disk = disk_get_load (); if ( (-1 == ld_cpu) || (-1 == ld_disk) ) goto reschedule; mem_usage = mem_get_usage (); #ifdef LINUX nproc = get_nproc (); #else nproc = 0; #endif now = GNUNET_TIME_absolute_get (); nbs = GNUNET_asprintf (&str, "%llu %d %d %u %u\n", now.abs_value_us / 1000LL / 1000LL, ld_cpu, ld_disk, mem_usage, nproc); if (0 < nbs) { GNUNET_BIO_write (bw, str, nbs); } else GNUNET_break (0); GNUNET_free (str); reschedule: sample_load_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &sample_load_task, NULL); } /** * Initialize logging CPU and IO statisticfs. Checks the configuration for * "STATS_DIR" and logs to a file in that directory. The file is name is * generated from the hostname and the process's PID. */ void GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg) { char *hostname; char *stats_dir; char *fn; size_t len; #if MINGW GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Load statistics logging now available for windows\n"); return; /* No logging on windows for now :( */ #endif if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "testbed", "STATS_DIR", &stats_dir)) return; len = GNUNET_OS_get_hostname_max_length (); hostname = GNUNET_malloc (len); if (0 != gethostname (hostname, len)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "gethostname"); GNUNET_free (stats_dir); GNUNET_free (hostname); return; } fn = NULL; (void) GNUNET_asprintf (&fn, "%s/%.*s-%jd.dat", stats_dir, len, hostname, (intmax_t) getpid()); GNUNET_free (stats_dir); GNUNET_free (hostname); if (NULL == (bw = GNUNET_BIO_write_open (fn))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Cannot open %s for writing load statistics. " "Not logging load statistics\n"), fn); GNUNET_free (fn); return; } GNUNET_free (fn); sample_load_task_id = GNUNET_SCHEDULER_add_now (&sample_load_task, NULL); #ifdef LINUX proc_stat = fopen ("/proc/stat", "r"); if (NULL == proc_stat) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fopen", "/proc/stat"); #elif OSX initMachCpuStats (); #endif updateUsage (); /* initialize */ } /** * Shutdown the status calls module. */ void GST_stats_destroy () { #if MINGW return; #endif if (NULL == bw) return; #ifdef LINUX if (proc_stat != NULL) { fclose (proc_stat); proc_stat = NULL; } #elif OSX GNUNET_free_non_null (prev_cpu_load); #endif if (GNUNET_SCHEDULER_NO_TASK != sample_load_task_id) { GNUNET_SCHEDULER_cancel (sample_load_task_id); sample_load_task_id = GNUNET_SCHEDULER_NO_TASK; } GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bw)); bw = NULL; } /* end of cpustatus.c */ gnunet-0.10.1/src/testbed/test_testbed_api_barriers.h0000644000175000017500000000014712225777503017633 00000000000000 /** * The name to use for the barrier in the test cases */ #define TEST_BARRIER_NAME "test_barrier" gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf0000644000175000017500000000017512233724131024503 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = FROM_FILE OVERLAY_TOPOLOGY_FILE = overlay_topology.txt gnunet-0.10.1/src/testbed/test_testbed_logger_api.c0000644000175000017500000001503212230201042017243 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_logger_api.c * @brief testcases for the testbed logger api * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_testbed_logger_service.h" /** * Generic logging shortcut */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Relative time seconds shorthand */ #define TIME_REL_SECS(sec) \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) /** * Opaque handle for the logging service */ static struct GNUNET_TESTBED_LOGGER_Handle *h; static struct GNUNET_TESTING_Peer *peer; static char *search_dir; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; static GNUNET_SCHEDULER_TaskIdentifier write_task; static int result; #define CANCEL_TASK(task) do { \ if (GNUNET_SCHEDULER_NO_TASK != task) \ { \ GNUNET_SCHEDULER_cancel (task); \ task = GNUNET_SCHEDULER_NO_TASK; \ } \ } while (0) /** * shortcut to exit during failure */ #define FAIL_TEST(cond, ret) do { \ if (!(cond)) { \ GNUNET_break(0); \ CANCEL_TASK (abort_task); \ abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ ret; \ } \ } while (0) /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void shutdown_now () { CANCEL_TASK (abort_task); CANCEL_TASK (write_task); GNUNET_free_non_null (search_dir); if (NULL != h) GNUNET_TESTBED_LOGGER_disconnect (h); GNUNET_SCHEDULER_shutdown (); } static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_WARNING, "Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; shutdown_now (); } #define BSIZE 1024 /** * Function called to iterate over a directory. * * @param cls closure * @param di argument to pass to "GNUNET_DISK_directory_iterator_next" to * get called on the next entry (or finish cleanly); * NULL on error (will be the last call in that case) * @param filename complete filename (absolute path) * @param dirname directory name (absolute path) */ static void iterator_cb (void *cls, struct GNUNET_DISK_DirectoryIterator *di, const char *filename, const char *dirname) { const char *fn; size_t len; uint64_t fs; int cancel; cancel = GNUNET_NO; if (NULL == filename) goto iteration_cont; len = strlen (filename); if (len < 5) /* log file: `pid'.dat */ goto iteration_cont; fn = filename + len; if (0 != strcasecmp (".dat", fn - 4)) goto iteration_cont; if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_NO, GNUNET_YES)) goto iteration_cont; if ((BSIZE * 2) != fs) /* The file size should be equal to what we have written */ goto iteration_cont; cancel = GNUNET_YES; result = GNUNET_OK; iteration_cont: if ( (NULL != di) && (GNUNET_YES == GNUNET_DISK_directory_iterator_next (di, cancel)) ) return; shutdown_now (); } /** * Functions of this type are called to notify a successful transmission of the * message to the logger service * * @param cls the closure given to GNUNET_TESTBED_LOGGER_send() * @param size the amount of data sent */ static void flush_comp (void *cls, size_t size) { FAIL_TEST (&write_task == cls, return); FAIL_TEST ((BSIZE * 2) == size, return); FAIL_TEST (GNUNET_OK == GNUNET_TESTING_peer_stop (peer), return); FAIL_TEST (GNUNET_YES == GNUNET_DISK_directory_iterator_start (GNUNET_SCHEDULER_PRIORITY_DEFAULT, search_dir, &iterator_cb, NULL), return); } static void do_write (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static int i; char buf[BSIZE]; write_task = GNUNET_SCHEDULER_NO_TASK; if (0 == i) write_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS(1), &do_write, NULL); (void) memset (buf, i, BSIZE); GNUNET_TESTBED_LOGGER_write (h, buf, BSIZE); if (0 == i++) return; GNUNET_TESTBED_LOGGER_flush (h, GNUNET_TIME_UNIT_FOREVER_REL, &flush_comp, &write_task); } /** * Signature of the 'main' function for a (single-peer) testcase that * is run using 'GNUNET_TESTING_peer_run'. * * @param cls closure * @param cfg configuration of the peer that was started * @param peer identity of the peer that was created */ static void test_main (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *p) { FAIL_TEST (NULL != (h = GNUNET_TESTBED_LOGGER_connect (cfg)), return); FAIL_TEST (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "testbed-logger", "dir", &search_dir), return); peer = p; write_task = GNUNET_SCHEDULER_add_now (&do_write, NULL); abort_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (10), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { int ret; result = GNUNET_SYSERR; ret = GNUNET_TESTING_service_run ("test-testbed-logger", "testbed-logger", "test_testbed_logger_api.conf", &test_main, NULL); if (0 != ret) return 1; if (GNUNET_OK != result) return 2; return 0; } gnunet-0.10.1/src/testbed/test_testbed_api_topology.c0000644000175000017500000001210412225777502017664 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/testbed/test_testbed_api_topology.c * @brief testing cases for testing high level testbed api helper functions * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we want to start */ #define NUM_PEERS 10 /** * Array of peers */ static struct GNUNET_TESTBED_Peer **peers; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * Shutdown task */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Testing result */ static int result; /** * Counter for counting overlay connections */ static unsigned int overlay_connects; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != op) { GNUNET_TESTBED_operation_done (op); op = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_CONNECT: overlay_connects++; if ((NUM_PEERS) == overlay_connects) { result = GNUNET_OK; GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } break; case GNUNET_TESTBED_ET_OPERATION_FINISHED: GNUNET_assert (NULL != event->details.operation_finished.emsg); break; default: GNUNET_break (0); if ((GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type) && (NULL != event->details.operation_finished.emsg)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "An operation failed with error: %s\n", event->details.operation_finished.emsg); result = GNUNET_SYSERR; GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); } } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { unsigned int peer; GNUNET_assert (NULL == cls); if (NULL == peers_) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); return; } GNUNET_assert (NUM_PEERS == num_peers); for (peer = 0; peer < num_peers; peer++) GNUNET_assert (NULL != peers_[peer]); peers = peers_; overlay_connects = 0; op = GNUNET_TESTBED_overlay_configure_topology (NULL, NUM_PEERS, peers, NULL, NULL, NULL, GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI, NUM_PEERS, GNUNET_TESTBED_TOPOLOGY_OPTION_END); GNUNET_assert (NULL != op); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300), do_shutdown, NULL); } /** * Main function */ int main (int argc, char **argv) { uint64_t event_mask; result = GNUNET_SYSERR; event_mask = 0; event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); (void) GNUNET_TESTBED_test_run ("test_testbed_api_test", "test_testbed_api.conf", NUM_PEERS, event_mask, &controller_event_cb, NULL, &test_master, NULL); if (GNUNET_OK != result) return 1; return 0; } /* end of test_testbed_api_topology.c */ gnunet-0.10.1/src/testbed/testbed_api_test.c0000644000175000017500000001157412225777502015742 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_test.c * @brief high-level test function * @author Christian Grothoff * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_testbed_service.h" /** * Context information for test run */ struct TestRunContext { /** * Test master callback */ GNUNET_TESTBED_TestMaster test_master; /** * Closure for test master */ void *test_master_cls; /** * The controller event callback */ GNUNET_TESTBED_ControllerCallback cc; /** * Closure for the above callback */ void *cc_cls; /** * event mask for the controller callback */ uint64_t event_mask; /** * Number of peers to start */ unsigned int num_peers; }; /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param config the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { struct TestRunContext *rc = cls; GNUNET_TESTBED_run (NULL, config, rc->num_peers, rc->event_mask, rc->cc, rc->cc_cls, rc->test_master, rc->test_master_cls); } /** * Convenience method for running a "simple" test on the local system * with a single call from 'main'. Underlay and overlay topology are * configured using the "UNDERLAY" and "OVERLAY" options in the * "[testbed]" section of the configuration (with possible options * given in "UNDERLAY_XXX" and/or "OVERLAY_XXX"). * * The test is to be terminated using a call to * "GNUNET_SCHEDULER_shutdown". If starting the test fails, * the program is stopped without 'master' ever being run. * * NOTE: this function should be called from 'main', NOT from * within a GNUNET_SCHEDULER-loop. This function will initialze * the scheduler loop, the testbed and then pass control to * 'master'. * * @param testname name of the testcase (to configure logging, etc.) * @param cfg_filename configuration filename to use * (for testbed, controller and peers) * @param num_peers number of peers to start * @param event_mask bit mask with set of events to call 'cc' for; * or-ed values of "1LL" shifted by the * respective 'enum GNUNET_TESTBED_EventType' * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...") * @param cc controller callback to invoke on events; This callback is called * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't * set in the event_mask as this is the only way get access to the * handle of each peer * @param cc_cls closure for cc * @param test_master task to run once the test is ready * @param test_master_cls closure for 'task'. * @return GNUNET_SYSERR on error, GNUNET_OK on success */ int GNUNET_TESTBED_test_run (const char *testname, const char *cfg_filename, unsigned int num_peers, uint64_t event_mask, GNUNET_TESTBED_ControllerCallback cc, void *cc_cls, GNUNET_TESTBED_TestMaster test_master, void *test_master_cls) { char *argv2[] = { NULL, "-c", NULL, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; struct TestRunContext *rc; int ret; argv2[0] = GNUNET_strdup (testname); argv2[2] = GNUNET_strdup (cfg_filename); GNUNET_assert (NULL != test_master); GNUNET_assert (num_peers > 0); rc = GNUNET_malloc (sizeof (struct TestRunContext) + (num_peers * sizeof (struct GNUNET_TESTBED_Peer *))); rc->test_master = test_master; rc->test_master_cls = test_master_cls; rc->num_peers = num_peers; rc->event_mask = event_mask; rc->cc = cc; rc->cc_cls = cc_cls; ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, testname, "nohelp", options, &run, rc); GNUNET_free (rc); GNUNET_free (argv2[0]); GNUNET_free (argv2[2]); return ret; } /* end of testbed_api_test.c */ gnunet-0.10.1/src/testbed/test_testbed_api_barriers.conf.in0000644000175000017500000000205312225230043020713 00000000000000[testbed] AUTOSTART = NO PORT = 12113 ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost TOPOLOGY = RANDOM #PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args [arm] DEFAULTSERVICES = core transport test-barriers PORT = 12366 [test-barriers] AUTOSTART = NO PORT = 12114 BINARY = /will/be/overwriten/in/test_testbed_api_barriers/ [fs] AUTOSTART = NO [resolver] HOSTNAME = localhost AUTOSTART = NO [mesh] AUTOSTART = NO [dht] AUTOSTART = NO [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = udp ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 PORT = 12365 [ats] WAN_QUOTA_OUT = 3932160 WAN_QUOTA_IN = 3932160 [core] PORT = 12092 AUTOSTART = YES USE_EPHEMERAL_KEYS = NO [transport-udp] TIMEOUT = 300 s PORT = 12368 [PATHS] GNUNET_TEST_HOME = /tmp/test-testbed/ [dns] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART = NO [nat] RETURN_LOCAL_ADDRESSES = YES [gns-helper-service-w32] AUTOSTART = NO [consensus] AUTOSTART = NO [gns] AUTOSTART = NO [statistics] AUTOSTART = NO [peerinfo] NO_IO = YES gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topology2dtorus.conf0000644000175000017500000000012012233724131024270 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = 2D_TORUS gnunet-0.10.1/src/testbed/gnunet-service-testbed_barriers.c0000644000175000017500000006261012255010512020654 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_barriers.c * @brief barrier handling at the testbed controller * @author Sree Harsha Totakura */ #include "gnunet-service-testbed.h" #include "gnunet-service-testbed_barriers.h" #include "testbed_api_barriers.h" /** * timeout for outgoing message transmissions in seconds */ #define MESSAGE_SEND_TIMEOUT(s) \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, s) /** * Test to see if local peers have reached the required quorum of a barrier */ #define LOCAL_QUORUM_REACHED(barrier) \ ((barrier->quorum * GST_num_local_peers) <= (barrier->nreached * 100)) #ifdef LOG #undef LOG #endif /** * Logging shorthand */ #define LOG(kind,...) \ GNUNET_log_from (kind, "testbed-barriers", __VA_ARGS__) /** * Barrier */ struct Barrier; /** * Message queue for transmitting messages */ struct MessageQueue { /** * next pointer for DLL */ struct MessageQueue *next; /** * prev pointer for DLL */ struct MessageQueue *prev; /** * The message to be sent */ struct GNUNET_MessageHeader *msg; }; /** * Context to be associated with each client */ struct ClientCtx { /** * The barrier this client is waiting for */ struct Barrier *barrier; /** * DLL next ptr */ struct ClientCtx *next; /** * DLL prev ptr */ struct ClientCtx *prev; /** * The client handle */ struct GNUNET_SERVER_Client *client; /** * the transmission handle */ struct GNUNET_SERVER_TransmitHandle *tx; /** * message queue head */ struct MessageQueue *mq_head; /** * message queue tail */ struct MessageQueue *mq_tail; }; /** * Wrapper around Barrier handle */ struct WBarrier { /** * DLL next pointer */ struct WBarrier *next; /** * DLL prev pointer */ struct WBarrier *prev; /** * The local barrier associated with the creation of this wrapper */ struct Barrier *barrier; /** * The barrier handle from API */ struct GNUNET_TESTBED_Barrier *hbarrier; /** * Has this barrier been crossed? */ uint8_t reached; }; /** * Barrier */ struct Barrier { /** * The hashcode of the barrier name */ struct GNUNET_HashCode hash; /** * The client handle to the master controller */ struct GNUNET_SERVER_Client *mc; /** * The name of the barrier */ char *name; /** * DLL head for the list of clients waiting for this barrier */ struct ClientCtx *head; /** * DLL tail for the list of clients waiting for this barrier */ struct ClientCtx *tail; /** * DLL head for the list of barrier handles */ struct WBarrier *whead; /** * DLL tail for the list of barrier handles */ struct WBarrier *wtail; /** * Identifier for the timeout task */ GNUNET_SCHEDULER_TaskIdentifier tout_task; /** * The status of this barrier */ enum GNUNET_TESTBED_BarrierStatus status; /** * Number of barriers wrapped in the above DLL */ unsigned int num_wbarriers; /** * Number of wrapped barriers reached so far */ unsigned int num_wbarriers_reached; /** * Number of wrapped barrier initialised so far */ unsigned int num_wbarriers_inited; /** * Number of peers which have reached this barrier */ unsigned int nreached; /** * Number of slaves we have initialised this barrier */ unsigned int nslaves; /** * Quorum percentage to be reached */ uint8_t quorum; }; /** * Hashtable handle for storing initialised barriers */ static struct GNUNET_CONTAINER_MultiHashMap *barrier_map; /** * Service context */ static struct GNUNET_SERVICE_Context *ctx; /** * Function called to notify a client about the connection * begin ready to queue more data. "buf" will be * NULL and "size" zero if the connection was closed for * writing in the meantime. * * @param cls client context * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_ready_cb (void *cls, size_t size, void *buf) { struct ClientCtx *ctx = cls; struct GNUNET_SERVER_Client *client = ctx->client; struct MessageQueue *mq; struct GNUNET_MessageHeader *msg; size_t wrote; ctx->tx = NULL; if ((0 == size) || (NULL == buf)) { GNUNET_assert (NULL != ctx->client); GNUNET_SERVER_client_drop (ctx->client); ctx->client = NULL; return 0; } mq = ctx->mq_head; msg = mq->msg; wrote = ntohs (msg->size); GNUNET_assert (size >= wrote); (void) memcpy (buf, msg, wrote); GNUNET_CONTAINER_DLL_remove (ctx->mq_head, ctx->mq_tail, mq); GNUNET_free (mq->msg); GNUNET_free (mq); if (NULL != (mq = ctx->mq_head)) ctx->tx = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size), MESSAGE_SEND_TIMEOUT (30), &transmit_ready_cb, ctx); return wrote; } /** * Queue a message into a clients message queue * * @param ctx the context associated with the client * @param msg the message to queue. Will be consumed */ static void queue_message (struct ClientCtx *ctx, struct GNUNET_MessageHeader *msg) { struct MessageQueue *mq; struct GNUNET_SERVER_Client *client = ctx->client; mq = GNUNET_new (struct MessageQueue); mq->msg = msg; LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", ntohs (msg->type), ntohs (msg->size)); GNUNET_CONTAINER_DLL_insert_tail (ctx->mq_head, ctx->mq_tail, mq); if (NULL == ctx->tx) ctx->tx = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size), MESSAGE_SEND_TIMEOUT (30), &transmit_ready_cb, ctx); } /** * Function to cleanup client context data structure * * @param ctx the client context data structure */ static void cleanup_clientctx (struct ClientCtx *ctx) { struct MessageQueue *mq; if (NULL != ctx->client) { GNUNET_SERVER_client_set_user_context_ (ctx->client, NULL, 0); GNUNET_SERVER_client_drop (ctx->client); } if (NULL != ctx->tx) GNUNET_SERVER_notify_transmit_ready_cancel (ctx->tx); if (NULL != (mq = ctx->mq_head)) { GNUNET_CONTAINER_DLL_remove (ctx->mq_head, ctx->mq_tail, mq); GNUNET_free (mq->msg); GNUNET_free (mq); } GNUNET_free (ctx); } /** * Function to remove a barrier from the barrier map and cleanup resources * occupied by a barrier * * @param barrier the barrier handle */ static void remove_barrier (struct Barrier *barrier) { struct ClientCtx *ctx; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (barrier_map, &barrier->hash, barrier)); while (NULL != (ctx = barrier->head)) { GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, ctx); cleanup_clientctx (ctx); } GNUNET_free (barrier->name); GNUNET_SERVER_client_drop (barrier->mc); GNUNET_free (barrier); } /** * Cancels all subcontroller barrier handles * * @param barrier the local barrier */ static void cancel_wrappers (struct Barrier *barrier) { struct WBarrier *wrapper; while (NULL != (wrapper = barrier->whead)) { GNUNET_TESTBED_barrier_cancel (wrapper->hbarrier); GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); GNUNET_free (wrapper); } } /** * Send a status message about a barrier to the given client * * @param client the client to send the message to * @param name the barrier name * @param status the status of the barrier * @param emsg the error message; should be non-NULL for * status=GNUNET_TESTBED_BARRIERSTATUS_ERROR */ static void send_client_status_msg (struct GNUNET_SERVER_Client *client, const char *name, enum GNUNET_TESTBED_BarrierStatus status, const char *emsg) { struct GNUNET_TESTBED_BarrierStatusMsg *msg; size_t name_len; uint16_t msize; GNUNET_assert ((NULL == emsg) || (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)); name_len = strlen (name); msize = sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + (name_len + 1) + ((NULL == emsg) ? 0 : (strlen (emsg) + 1)); msg = GNUNET_malloc (msize); msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS); msg->status = htons (status); msg->name_len = htons ((uint16_t) name_len); (void) memcpy (msg->data, name, name_len); if (NULL != emsg) (void) memcpy (msg->data + name_len + 1, emsg, strlen (emsg)); GST_queue_message (client, &msg->header); } /** * Sends a barrier failed message * * @param barrier the corresponding barrier * @param emsg the error message; should be non-NULL for * status=GNUNET_TESTBED_BARRIERSTATUS_ERROR */ static void send_barrier_status_msg (struct Barrier *barrier, const char *emsg) { GNUNET_assert (0 != barrier->status); send_client_status_msg (barrier->mc, barrier->name, barrier->status, emsg); } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT messages. This * message should come from peers or a shared helper service using the * testbed-barrier client API (@see gnunet_testbed_barrier_service.h) * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * * @param cls NULL * @param client identification of the client * @param message the actual message */ static void handle_barrier_wait (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_BarrierWait *msg; struct Barrier *barrier; char *name; struct ClientCtx *client_ctx; struct GNUNET_HashCode key; size_t name_len; uint16_t msize; msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_BarrierWait)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (NULL == barrier_map) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_BarrierWait *) message; name_len = msize - sizeof (struct GNUNET_TESTBED_BarrierWait); name = GNUNET_malloc (name_len + 1); name[name_len] = '\0'; (void) memcpy (name, msg->name, name_len); LOG_DEBUG ("Received BARRIER_WAIT for barrier `%s'\n", name); GNUNET_CRYPTO_hash (name, name_len, &key); GNUNET_free (name); if (NULL == (barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } client_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx); if (NULL == client_ctx) { client_ctx = GNUNET_new (struct ClientCtx); client_ctx->client = client; GNUNET_SERVER_client_keep (client); client_ctx->barrier = barrier; GNUNET_CONTAINER_DLL_insert_tail (barrier->head, barrier->tail, client_ctx); GNUNET_SERVER_client_set_user_context (client, client_ctx); } barrier->nreached++; if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) && (LOCAL_QUORUM_REACHED (barrier))) { barrier->status = GNUNET_TESTBED_BARRIERSTATUS_CROSSED; send_barrier_status_msg (barrier, NULL); } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Functions with this signature are called whenever a client * is disconnected on the network level. * * @param cls closure * @param client identification of the client; NULL * for the last call when the server is destroyed */ static void disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) { struct ClientCtx *client_ctx; if (NULL == client) return; client_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx); if (NULL == client_ctx) return; cleanup_clientctx (client_ctx); } /** * Function to initialise barrriers component * * @param cfg the configuration to use for initialisation */ void GST_barriers_init (struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler message_handlers[] = { {&handle_barrier_wait, NULL, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT, 0}, {NULL, NULL, 0, 0} }; struct GNUNET_SERVER_Handle *srv; barrier_map = GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES); ctx = GNUNET_SERVICE_start ("testbed-barrier", cfg, GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN); srv = GNUNET_SERVICE_get_server (ctx); GNUNET_SERVER_add_handlers (srv, message_handlers); GNUNET_SERVER_disconnect_notify (srv, &disconnect_cb, NULL); } /** * Iterator over hash map entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int barrier_destroy_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct Barrier *barrier = value; GNUNET_assert (NULL != barrier); cancel_wrappers (barrier); remove_barrier (barrier); return GNUNET_YES; } /** * Function to stop the barrier service */ void GST_barriers_destroy () { GNUNET_assert (NULL != barrier_map); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_iterate (barrier_map, &barrier_destroy_iterator, NULL)); GNUNET_CONTAINER_multihashmap_destroy (barrier_map); GNUNET_assert (NULL != ctx); GNUNET_SERVICE_stop (ctx); } /** * Functions of this type are to be given as callback argument to * GNUNET_TESTBED_barrier_init(). The callback will be called when status * information is available for the barrier. * * @param cls the closure given to GNUNET_TESTBED_barrier_init() * @param name the name of the barrier * @param b_ the barrier handle * @param status status of the barrier; GNUNET_OK if the barrier is crossed; * GNUNET_SYSERR upon error * @param emsg if the status were to be GNUNET_SYSERR, this parameter has the * error messsage */ static void wbarrier_status_cb (void *cls, const char *name, struct GNUNET_TESTBED_Barrier *b_, enum GNUNET_TESTBED_BarrierStatus status, const char *emsg) { struct WBarrier *wrapper = cls; struct Barrier *barrier = wrapper->barrier; GNUNET_assert (b_ == wrapper->hbarrier); wrapper->hbarrier = NULL; GNUNET_CONTAINER_DLL_remove (barrier->whead, barrier->wtail, wrapper); GNUNET_free (wrapper); switch (status) { case GNUNET_TESTBED_BARRIERSTATUS_ERROR: LOG (GNUNET_ERROR_TYPE_ERROR, "Initialising barrier `%s' failed at a sub-controller: %s\n", barrier->name, (NULL != emsg) ? emsg : "NULL"); cancel_wrappers (barrier); if (NULL == emsg) emsg = "Initialisation failed at a sub-controller"; barrier->status = GNUNET_TESTBED_BARRIERSTATUS_ERROR; send_barrier_status_msg (barrier, emsg); return; case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED != barrier->status) { GNUNET_break_op (0); return; } barrier->num_wbarriers_reached++; if ((barrier->num_wbarriers_reached == barrier->num_wbarriers) && (LOCAL_QUORUM_REACHED (barrier))) { barrier->status = GNUNET_TESTBED_BARRIERSTATUS_CROSSED; send_barrier_status_msg (barrier, NULL); } return; case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: if (0 != barrier->status) { GNUNET_break_op (0); return; } barrier->num_wbarriers_inited++; if (barrier->num_wbarriers_inited == barrier->num_wbarriers) { barrier->status = GNUNET_TESTBED_BARRIERSTATUS_INITIALISED; send_barrier_status_msg (barrier, NULL); } return; } } /** * Function called upon timeout while waiting for a response from the * subcontrollers to barrier init message * * @param cls barrier * @param tc scheduler task context */ static void fwd_tout_barrier_init (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Barrier *barrier = cls; cancel_wrappers (barrier); barrier->status = GNUNET_TESTBED_BARRIERSTATUS_ERROR; send_barrier_status_msg (barrier, "Timedout while propagating barrier initialisation\n"); remove_barrier (barrier); } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT messages. This * message should always come from a parent controller or the testbed API if we * are the root controller. * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_barrier_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_BarrierInit *msg; char *name; struct Barrier *barrier; struct Slave *slave; struct WBarrier *wrapper; struct GNUNET_HashCode hash; size_t name_len; unsigned int cnt; uint16_t msize; if (NULL == GST_context) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (client != GST_context->client) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_BarrierInit)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_BarrierInit *) message; name_len = (size_t) msize - sizeof (struct GNUNET_TESTBED_BarrierInit); name = GNUNET_malloc (name_len + 1); (void) memcpy (name, msg->name, name_len); GNUNET_CRYPTO_hash (name, name_len, &hash); LOG_DEBUG ("Received BARRIER_INIT for barrier `%s'\n", name); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (barrier_map, &hash)) { send_client_status_msg (client, name, GNUNET_TESTBED_BARRIERSTATUS_ERROR, "A barrier with the same name already exists"); GNUNET_free (name); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } barrier = GNUNET_new (struct Barrier); (void) memcpy (&barrier->hash, &hash, sizeof (struct GNUNET_HashCode)); barrier->quorum = msg->quorum; barrier->name = name; barrier->mc = client; GNUNET_SERVER_client_keep (client); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (barrier_map, &barrier->hash, barrier, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); GNUNET_SERVER_receive_done (client, GNUNET_OK); /* Propagate barrier init to subcontrollers */ for (cnt = 0; cnt < GST_slave_list_size; cnt++) { if (NULL == (slave = GST_slave_list[cnt])) continue; if (NULL == slave->controller) { GNUNET_break (0);/* May happen when we are connecting to the controller */ continue; } wrapper = GNUNET_new (struct WBarrier); wrapper->barrier = barrier; GNUNET_CONTAINER_DLL_insert_tail (barrier->whead, barrier->wtail, wrapper); wrapper->hbarrier = GNUNET_TESTBED_barrier_init_ (slave->controller, barrier->name, barrier->quorum, &wbarrier_status_cb, wrapper, GNUNET_NO); } if (NULL == barrier->whead) /* No further propagation */ { barrier->status = GNUNET_TESTBED_BARRIERSTATUS_INITIALISED; LOG_DEBUG ("Sending GNUNET_TESTBED_BARRIERSTATUS_INITIALISED for barrier `%s'\n", barrier->name); send_barrier_status_msg (barrier, NULL); }else barrier->tout_task = GNUNET_SCHEDULER_add_delayed (MESSAGE_SEND_TIMEOUT (30), &fwd_tout_barrier_init, barrier); } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL messages. This * message should always come from a parent controller or the testbed API if we * are the root controller. * * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_barrier_cancel (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_BarrierCancel *msg; char *name; struct Barrier *barrier; struct GNUNET_HashCode hash; size_t name_len; uint16_t msize; if (NULL == GST_context) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (client != GST_context->client) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_BarrierCancel)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_BarrierCancel *) message; name_len = msize - sizeof (struct GNUNET_TESTBED_BarrierCancel); name = GNUNET_malloc (name_len + 1); (void) memcpy (name, msg->name, name_len); GNUNET_CRYPTO_hash (name, name_len, &hash); if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (barrier_map, &hash)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &hash); GNUNET_assert (NULL != barrier); cancel_wrappers (barrier); remove_barrier (barrier); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. * This handler is queued in the main service and will handle the messages sent * either from the testbed driver or from a high level controller * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_barrier_status (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_BarrierStatusMsg *msg; struct Barrier *barrier; struct ClientCtx *client_ctx; const char *name; struct GNUNET_HashCode key; enum GNUNET_TESTBED_BarrierStatus status; uint16_t msize; uint16_t name_len; if (NULL == GST_context) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (client != GST_context->client) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msize = ntohs (message->size); if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_BarrierStatusMsg *) message; status = ntohs (msg->status); if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED != status) { GNUNET_break_op (0); /* current we only expect BARRIER_CROSSED status message this way */ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } name = msg->data; name_len = ntohs (msg->name_len); if ((sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1) != msize) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if ('\0' != name[name_len]) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_CRYPTO_hash (name, name_len, &key); barrier = GNUNET_CONTAINER_multihashmap_get (barrier_map, &key); if (NULL == barrier) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); while (NULL != (client_ctx = barrier->head)) /* Notify peers */ { queue_message (client_ctx, GNUNET_copy_message (message)); GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, client_ctx); } } /* end of gnunet-service-testbed_barriers.c */ gnunet-0.10.1/src/testbed/Makefile.am0000644000175000017500000003446212320751517014303 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif libexecdir= $(pkglibdir)/libexec/ pkgcfgdir= $(pkgdatadir)/config.d/ pkgcfg_DATA = \ testbed.conf if HAVE_SQLITE underlay_daemon = gnunet-daemon-testbed-underlay latency_logger = gnunet-daemon-latency-logger generate_underlay = generate-underlay-topology underlay_testcases = test_testbed_underlay endif libexec_PROGRAMS = \ gnunet-service-testbed \ gnunet-helper-testbed \ gnunet-service-testbed-logger \ gnunet-daemon-testbed-blacklist \ $(underlay_daemon) \ $(latency_logger) bin_PROGRAMS = \ gnunet-testbed-profiler noinst_PROGRAMS = \ $(generate_underlay) gnunet_service_testbed_SOURCES = \ gnunet-service-testbed.c gnunet-service-testbed.h \ gnunet-service-testbed_links.c gnunet-service-testbed_links.h \ gnunet-service-testbed_peers.c \ gnunet-service-testbed_cache.c \ gnunet-service-testbed_oc.c \ gnunet-service-testbed_cpustatus.c \ gnunet-service-testbed_meminfo.c gnunet-service-testbed_meminfo.h \ gnunet-service-testbed_barriers.c gnunet-service-testbed_barriers.h \ gnunet-service-testbed_connectionpool.c gnunet-service-testbed_connectionpool.h gnunet_service_testbed_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/arm/libgnunetarm.la \ $(LTLIBINTL) $(Z_LIBS) gnunet_service_testbed_DEPENDENCIES = \ libgnunettestbed.la gnunet_service_testbed_logger_SOURCES = \ gnunet-service-testbed-logger.c gnunet_service_testbed_logger_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_service_testbed_logger_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_testbed_profiler_SOURCES = \ gnunet-testbed-profiler.c gnunet_testbed_profiler_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la gnunet_testbed_profiler_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la gnunet_helper_testbed_SOURCES = \ gnunet-helper-testbed.c gnunet_helper_testbed_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la \ $(LTLIBINTL) $(Z_LIBS) gnunet_helper_testbed_DEPENDENCIES = \ gnunet-service-testbed.$(OBJEXT) \ libgnunettestbed.la gnunet_daemon_testbed_blacklist_SOURCES = gnunet-daemon-testbed-blacklist.c gnunet_daemon_testbed_blacklist_LDADD = $(XLIB) \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) gnunet_daemon_testbed_blacklist_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_daemon_testbed_underlay_SOURCES = gnunet-daemon-testbed-underlay.c gnunet_daemon_testbed_underlay_LDADD = $(XLIB) \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) -lsqlite3 gnunet_daemon_testbed_underlay_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_daemon_latency_logger_SOURCES = gnunet-daemon-latency-logger.c gnunet_daemon_latency_logger_LDADD = $(XLIB) \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) -lsqlite3 gnunet_daemon_latency_logger_DEPENDENCIES = \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/util/libgnunetutil.la lib_LTLIBRARIES = \ libgnunettestbed.la \ libgnunettestbedlogger.la libgnunettestbed_la_SOURCES = \ testbed_api.c testbed_api.h testbed.h \ testbed_api_hosts.c testbed_api_hosts.h testbed_helper.h \ testbed_api_operations.c testbed_api_operations.h \ testbed_api_peers.c testbed_api_peers.h \ testbed_api_services.c \ testbed_api_statistics.c \ testbed_api_testbed.c \ testbed_api_test.c \ testbed_api_topology.c testbed_api_topology.h \ testbed_api_sd.c testbed_api_sd.h \ testbed_api_barriers.c testbed_api_barriers.h libgnunettestbed_la_LIBADD = $(XLIB) \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ -lm \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(LTLIBINTL) libgnunettestbed_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 libgnunettestbedlogger_la_SOURCES = \ testbed_logger_api.c libgnunettestbedlogger_la_LIBADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunettestbedlogger_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 generate_underlay_topology_SOURCES = generate-underlay-topology.c generate_underlay_topology_LDADD = $(XLIB) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(LTLIBINTL) -lsqlite3 generate_underlay_topology_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la check_PROGRAMS = \ test_testbed_api_hosts \ test_testbed_logger_api \ test_gnunet_helper_testbed \ test_testbed_api_controllerlink \ test_testbed_api_2peers_1controller \ test_testbed_api_3peers_3controllers \ test_testbed_api \ test_testbed_api_sd \ test_testbed_api_operations \ test_testbed_api_testbed_run \ test_testbed_api_test \ test_testbed_api_test_timeout \ test_testbed_api_peer_reconfiguration \ test_testbed_api_peers_manage_services \ test_testbed_api_topology \ test_testbed_api_topology_clique \ test_testbed_api_testbed_run_topologyrandom \ test_testbed_api_testbed_run_topologyline \ test_testbed_api_testbed_run_topologyclique \ test_testbed_api_testbed_run_topologyring \ test_testbed_api_testbed_run_topologysmallworldring \ test_testbed_api_testbed_run_topology2dtorus \ test_testbed_api_testbed_run_topologysmallworld \ test_testbed_api_testbed_run_topologyfromfile \ test_testbed_api_testbed_run_topologyscalefree \ test_testbed_api_testbed_run_waitforever \ test_testbed_api_statistics \ gnunet-service-test-barriers \ test_testbed_api_barriers \ $(underlay_testcases) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ test_testbed_api \ test_testbed_logger_api \ test_testbed_api_sd \ test_testbed_api_operations \ test_testbed_api_hosts \ test_gnunet_helper_testbed \ test_testbed_api_2peers_1controller \ test_testbed_api_controllerlink \ test_testbed_api_3peers_3controllers \ test_testbed_api_testbed_run \ test_testbed_api_test \ test_testbed_api_test_timeout \ test_testbed_api_statistics \ test_testbed_api_peer_reconfiguration \ test_testbed_api_peers_manage_services \ test_testbed_api_topology \ test_testbed_api_topology_clique \ test_testbed_api_testbed_run_topologyrandom \ test_testbed_api_testbed_run_topologyline \ test_testbed_api_testbed_run_topologyclique \ test_testbed_api_testbed_run_topologyring \ test_testbed_api_testbed_run_topology2dtorus \ test_testbed_api_testbed_run_topologysmallworld \ test_testbed_api_testbed_run_topologysmallworldring \ test_testbed_api_testbed_run_topologyfromfile \ test_testbed_api_testbed_run_topologyscalefree \ test_testbed_api_barriers \ $(underlay_testcases) endif test_testbed_api_hosts_SOURCES = \ test_testbed_api_hosts.c test_testbed_api_hosts_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_SOURCES = \ test_testbed_api.c test_testbed_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/arm/libgnunetarm.la \ libgnunettestbed.la test_testbed_logger_api_SOURCES = \ test_testbed_logger_api.c test_testbed_logger_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbedlogger.la test_testbed_api_sd_SOURCES = \ test_testbed_api_sd.c test_testbed_api_sd_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_2peers_1controller_SOURCES = \ test_testbed_api_2peers_1controller.c test_testbed_api_2peers_1controller_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la test_testbed_api_3peers_3controllers_SOURCES = \ test_testbed_api_3peers_3controllers.c test_testbed_api_3peers_3controllers_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ libgnunettestbed.la test_testbed_api_operations_SOURCES = \ test_testbed_api_operations.c test_testbed_api_operations_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_controllerlink_SOURCES = \ test_testbed_api_controllerlink.c test_testbed_api_controllerlink_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_test_SOURCES = \ test_testbed_api_test.c test_testbed_api_test_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_test_timeout_SOURCES = \ test_testbed_api_test_timeout.c test_testbed_api_test_timeout_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_topology_SOURCES = \ test_testbed_api_topology.c test_testbed_api_topology_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_topology_clique_SOURCES = \ test_testbed_api_topology_clique.c test_testbed_api_topology_clique_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_gnunet_helper_testbed_SOURCES = \ test_gnunet_helper_testbed.c test_gnunet_helper_testbed_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la \ $(Z_LIBS) test_testbed_api_testbed_run_topologyrandom_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyrandom_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyline_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyline_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyclique_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyclique_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyring_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyring_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologysmallworldring_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologysmallworldring_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topology2dtorus_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topology2dtorus_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologysmallworld_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologysmallworld_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyfromfile_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyfromfile_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_topologyscalefree_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_topologyscalefree_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_testbed_run_waitforever_SOURCES = \ test_testbed_api_testbed_run.c test_testbed_api_testbed_run_waitforever_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_statistics_SOURCES = \ test_testbed_api_statistics.c test_testbed_api_statistics_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_peers_manage_services_SOURCES = \ test_testbed_api_peers_manage_services.c test_testbed_api_peers_manage_services_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_peer_reconfiguration_SOURCES = \ test_testbed_api_peer_reconfiguration.c test_testbed_api_peer_reconfiguration_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_barriers_SOURCES = \ test_testbed_api_barriers.c \ test_testbed_api_barriers.h test_testbed_api_barriers_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_api_barriers_DEPENDENCIES = \ gnunet-service-test-barriers$(EXEEXT) gnunet_service_test_barriers_SOURCES = \ gnunet-service-test-barriers.c \ test_testbed_api_barriers.h gnunet_service_test_barriers_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la test_testbed_underlay_SOURCES = \ test_testbed_underlay.c test_testbed_underlay_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunettestbed.la EXTRA_DIST = \ test_testbed_api.conf \ test_testbed_api_statistics.conf \ test_testbed_api_test_timeout.conf \ test_testbed_api_template.conf \ test_testbed_logger_api.conf \ test_testbed_api_testbed_run_topologyring.conf \ test_testbed_api_testbed_run_topologyclique.conf \ test_testbed_api_testbed_run_topologyline.conf \ test_testbed_api_testbed_run_topologyrandom.conf \ test_testbed_api_testbed_run_topologysmallworldring.conf \ test_testbed_api_testbed_run_topology2dtorus.conf \ test_testbed_api_testbed_run_topologysmallworld.conf \ test_testbed_api_testbed_run_topologyfromfile.conf \ test_testbed_api_testbed_run_topologyscalefree.conf \ test_testbed_api_barriers.conf.in \ overlay_topology.txt \ sample_hosts.txt \ sample.job \ test_testbed_underlay.conf.in \ test-underlay.sqlite gnunet-0.10.1/src/testbed/test_testbed_api_test_timeout.conf0000644000175000017500000000014112233724131021223 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = CLIQUE SETUP_TIMEOUT = 2 s gnunet-0.10.1/src/testbed/test_testbed_api.c0000644000175000017500000003331112225777502015733 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api.c * @brief testcases for the testbed api * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_testing_lib.h" #include "gnunet_testbed_service.h" /** * Generic logging shortcut */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Relative time seconds shorthand */ #define TIME_REL_SECS(sec) \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) /** * Our localhost */ static struct GNUNET_TESTBED_Host *host; /** * The controller process */ static struct GNUNET_TESTBED_ControllerProc *cp; /** * The controller handle */ static struct GNUNET_TESTBED_Controller *controller; /** * A neighbouring host */ static struct GNUNET_TESTBED_Host *neighbour; /** * Handle for neighbour registration */ static struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle; /** * Handle for a peer */ static struct GNUNET_TESTBED_Peer *peer; /** * Handle to configuration */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to operation */ static struct GNUNET_TESTBED_Operation *operation; /** * Handle to peer's ARM service */ static struct GNUNET_ARM_Handle *arm_handle; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * The testing result */ static int result; /** * Enumeration of sub testcases */ enum Test { /** * Test cases which are not covered by the below ones */ OTHER, /** * Test where we get a peer config from controller */ PEER_GETCONFIG, /** * Test where we connect to a service running on the peer */ PEER_SERVICE_CONNECT, /** * Test where we get a peer's identity from controller */ PEER_DESTROY, }; /** * Testing status */ static enum Test sub_test; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down...\n"); if (GNUNET_SCHEDULER_NO_TASK != abort_task) GNUNET_SCHEDULER_cancel (abort_task); if (NULL != reg_handle) GNUNET_TESTBED_cancel_registration (reg_handle); if (NULL != controller) GNUNET_TESTBED_controller_disconnect (controller); if (NULL != cfg) GNUNET_CONFIGURATION_destroy (cfg); if (NULL != cp) GNUNET_TESTBED_controller_stop (cp); if (NULL != neighbour) GNUNET_TESTBED_host_destroy (neighbour); if (NULL != host) GNUNET_TESTBED_host_destroy (host); } /** * shortcut to exit during failure */ #define FAIL_TEST(cond, ret) do { \ if (!(cond)) { \ GNUNET_break(0); \ if (GNUNET_SCHEDULER_NO_TASK != abort_task) \ GNUNET_SCHEDULER_cancel (abort_task); \ abort_task = GNUNET_SCHEDULER_NO_TASK; \ GNUNET_SCHEDULER_add_now (do_shutdown, NULL); \ ret; \ } \ } while (0) /** * abort task to run on test timed out * * @param cls NULL * @param tc the task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { LOG (GNUNET_ERROR_TYPE_WARNING, "Test timedout -- Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; do_shutdown (cls, tc); } /** * Adapter function called to establish a connection to * a service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * arm_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { FAIL_TEST (NULL == cls, return NULL); FAIL_TEST (OTHER == sub_test, return NULL); sub_test = PEER_SERVICE_CONNECT; arm_handle = GNUNET_ARM_connect (cfg, NULL, NULL); return arm_handle; } /** * Adapter function called to destroy a connection to * a service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void arm_disconnect_adapter (void *cls, void *op_result) { FAIL_TEST (NULL != op_result, return); FAIL_TEST (op_result == arm_handle, return); GNUNET_ARM_disconnect_and_free (arm_handle); arm_handle = NULL; FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return); FAIL_TEST (NULL != operation, return); operation = GNUNET_TESTBED_peer_stop (NULL, peer, NULL, NULL); FAIL_TEST (NULL != operation, return); } /** * Callback to be called when a service connect operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void service_connect_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { switch (sub_test) { case PEER_SERVICE_CONNECT: FAIL_TEST (operation == op, return); FAIL_TEST (NULL == emsg, return); FAIL_TEST (NULL == cls, return); FAIL_TEST (ca_result == arm_handle, return); GNUNET_TESTBED_operation_done (operation); /* This results in call to * disconnect adapter */ break; default: FAIL_TEST (0, return); } } /** * Callback to be called when the requested peer information is available * * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() * @param op the operation this callback corresponds to * @param pinfo the result; will be NULL if the operation has failed * @param emsg error message if the operation has failed; will be NULL if the * operation is successfull */ static void peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) { switch (sub_test) { case PEER_GETCONFIG: FAIL_TEST (NULL != pinfo, return); FAIL_TEST (NULL == emsg, return); FAIL_TEST (NULL == cb_cls, return); FAIL_TEST (operation == op, return); FAIL_TEST (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit, return); FAIL_TEST (NULL != pinfo->result.cfg, return); sub_test = PEER_DESTROY; GNUNET_TESTBED_operation_done (operation); operation = GNUNET_TESTBED_peer_destroy (peer); break; default: FAIL_TEST (0, return); } } /** * Signature of the event handler function called by the * respective event controller. * * @param cls closure * @param event information about the event */ static void controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_OPERATION_FINISHED: switch (sub_test) { case PEER_DESTROY: FAIL_TEST (event->op == operation, return); FAIL_TEST (NULL == event->op_cls, return); FAIL_TEST (NULL == event->details.operation_finished.emsg, return); FAIL_TEST (NULL == event->details.operation_finished.generic, return); GNUNET_TESTBED_operation_done (operation); GNUNET_SCHEDULER_add_now (&do_shutdown, NULL); break; case PEER_SERVICE_CONNECT: FAIL_TEST (event->op == operation, return); FAIL_TEST (NULL == event->op_cls, return); FAIL_TEST (NULL == event->details.operation_finished.emsg, return); FAIL_TEST (NULL != arm_handle, return); FAIL_TEST (event->details.operation_finished.generic == arm_handle, return); break; default: FAIL_TEST (0, return); break; } break; case GNUNET_TESTBED_ET_PEER_START: FAIL_TEST (event->details.peer_start.host == host, return); FAIL_TEST (event->details.peer_start.peer == peer, return); FAIL_TEST (OTHER == sub_test, return); GNUNET_TESTBED_operation_done (operation); operation = GNUNET_TESTBED_service_connect (NULL, peer, "dht", &service_connect_comp_cb, NULL, &arm_connect_adapter, &arm_disconnect_adapter, NULL); FAIL_TEST (NULL != operation, return); break; case GNUNET_TESTBED_ET_PEER_STOP: FAIL_TEST (event->details.peer_stop.peer == peer, return); FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return); result = GNUNET_YES; sub_test = PEER_GETCONFIG; GNUNET_TESTBED_operation_done (operation); operation = GNUNET_TESTBED_peer_get_information (peer, GNUNET_TESTBED_PIT_CONFIGURATION, &peerinfo_cb, NULL); break; default: FAIL_TEST (0, return); /* We should never reach this state */ } } /** * Functions of this signature are called when a peer has been successfully * created * * @param cls the closure from GNUNET_TESTBED_peer_create() * @param peer the handle for the created peer; NULL on any error during * creation * @param emsg NULL if peer is not NULL; else MAY contain the error description */ static void peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) { struct GNUNET_TESTBED_Peer **peer_ptr; peer_ptr = cls; FAIL_TEST (NULL != peer, return); FAIL_TEST (NULL != peer_ptr, return); *peer_ptr = peer; GNUNET_TESTBED_operation_done (operation); operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); FAIL_TEST (NULL != operation, return); } /** * Callback which will be called to after a host registration succeeded or failed * * @param cls the host which has been registered * @param emsg the error message; NULL if host registration is successful */ static void registration_comp (void *cls, const char *emsg) { FAIL_TEST (cls == neighbour, return); reg_handle = NULL; operation = GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb, &peer); FAIL_TEST (NULL != operation, return); } /** * Callback to signal successfull startup of the controller process * * @param cls the closure from GNUNET_TESTBED_controller_start() * @param cfg the configuration with which the controller has been started; * NULL if status is not GNUNET_OK * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ static void status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int status) { uint64_t event_mask; if (GNUNET_OK != status) { cp = NULL; FAIL_TEST (0, return); return; } event_mask = 0; event_mask |= (1L << GNUNET_TESTBED_ET_PEER_START); event_mask |= (1L << GNUNET_TESTBED_ET_PEER_STOP); event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); controller = GNUNET_TESTBED_controller_connect (host, event_mask, &controller_cb, NULL); FAIL_TEST (NULL != controller, return); neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); FAIL_TEST (NULL != neighbour, return); reg_handle = GNUNET_TESTBED_register_host (controller, neighbour, ®istration_comp, neighbour); FAIL_TEST (NULL != reg_handle, return); } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { cfg = GNUNET_CONFIGURATION_dup (config); host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); FAIL_TEST (NULL != host, return); cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb, NULL); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { int ret; char *const argv2[] = { "test_testbed_api", "-c", "test_testbed_api.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; result = GNUNET_SYSERR; ret = GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testbed_api", "nohelp", options, &run, NULL); if ((GNUNET_OK != ret) || (GNUNET_OK != result)) return 1; return 0; } /* end of test_testbed_api.c */ gnunet-0.10.1/src/testbed/test_testbed_api_peers_manage_services.c0000644000175000017500000001340012250315331022323 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_peers_manage_services.c * @brief testcase for testing GNUNET_TESTBED_peer_manage_service() * implementation * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we want to start */ #define NUM_PEERS 2 /** * The array of peers; we get them from the testbed */ static struct GNUNET_TESTBED_Peer **peers; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * dummy pointer */ static void *dummy_cls = (void *) 0xDEAD0001; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * States in this test */ enum { /** * Test has just been initialized */ STATE_INIT, /** * Peers have been started */ STATE_PEERS_STARTED, /** * statistics service went down */ STATE_SERVICE_DOWN, /** * statistics service went up */ STATE_SERVICE_UP, /** * Testing completed successfully */ STATE_OK } state; /** * Fail testcase */ #define FAIL_TEST(cond, ret) do { \ if (!(cond)) { \ GNUNET_break(0); \ if (GNUNET_SCHEDULER_NO_TASK != abort_task) \ GNUNET_SCHEDULER_cancel (abort_task); \ abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ ret; \ } \ } while (0) /** * Abort task * * @param cls NULL * @param tc scheduler task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != op) { GNUNET_TESTBED_operation_done (op); op = NULL; } GNUNET_SCHEDULER_shutdown(); } /** * Callback to be called when an operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { FAIL_TEST (cls == dummy_cls, return); FAIL_TEST (NULL == emsg, return); GNUNET_TESTBED_operation_done (op); op = NULL; switch (state) { case STATE_PEERS_STARTED: state = STATE_SERVICE_DOWN; op = GNUNET_TESTBED_peer_manage_service (dummy_cls, peers[1], "topology", op_comp_cb, dummy_cls, 0); GNUNET_assert (NULL != op); break; case STATE_SERVICE_DOWN: state = STATE_SERVICE_UP; GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_NO_TASK; state = STATE_OK; GNUNET_SCHEDULER_shutdown (); break; default: FAIL_TEST (0, return); } } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { FAIL_TEST (NUM_PEERS == num_peers, return); state = STATE_PEERS_STARTED; peers = peers_; op = GNUNET_TESTBED_peer_manage_service (dummy_cls, peers[1], "topology", op_comp_cb, dummy_cls, 1); FAIL_TEST (NULL != op, return); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { state = STATE_INIT; (void) GNUNET_TESTBED_test_run ("test_testbed_api_peers_manage_services", "test_testbed_api.conf", NUM_PEERS, 1LL, NULL, NULL, &test_master, NULL); if (STATE_OK != state) return 1; return 0; } gnunet-0.10.1/src/testbed/gnunet-service-testbed_links.h0000644000175000017500000001222212225777503020203 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_links.h * @brief TESTBED service components that deals with starting slave controllers * and establishing lateral links between controllers * @author Sree Harsha Totakura */ /** * A connected controller which is not our child */ struct Neighbour; /** * Structure representing a connected(directly-linked) controller */ struct Slave { /** * The controller process handle if we had started the controller */ struct GNUNET_TESTBED_ControllerProc *controller_proc; /** * The controller handle */ struct GNUNET_TESTBED_Controller *controller; /** * handle to lcc which is associated with this slave startup. Should be set to * NULL when the slave has successfully started up */ struct LinkControllersContext *lcc; /** * Head of the host registration DLL */ struct HostRegistration *hr_dll_head; /** * Tail of the host registration DLL */ struct HostRegistration *hr_dll_tail; /** * The current host registration handle */ struct GNUNET_TESTBED_HostRegistrationHandle *rhandle; /** * Hashmap to hold Registered host contexts */ struct GNUNET_CONTAINER_MultiHashMap *reghost_map; /** * The id of the host this controller is running on */ uint32_t host_id; }; /** * A list of directly linked neighbours */ extern struct Slave **GST_slave_list; /** * The size of directly linked neighbours list */ extern unsigned int GST_slave_list_size; /** * Cleans up the neighbour list */ void GST_neighbour_list_clean(); /** * Get a neighbour from the neighbour list * * @param id the index of the neighbour in the neighbour list * @return the Neighbour; NULL if the given index in invalid (index greater than * the list size or neighbour at that index is NULL) */ struct Neighbour * GST_get_neighbour (uint32_t id); /** * Function to cleanup the neighbour connect contexts */ void GST_free_nccq (); /** * Notification context to be used to notify when connection to the neighbour's * controller is opened */ struct NeighbourConnectNotification; /** * The notification callback to call when we are connect to neighbour * * @param cls the closure given to GST_neighbour_get_connection() * @param controller the controller handle to the neighbour */ typedef void (*GST_NeigbourConnectNotifyCallback) (void *cls, struct GNUNET_TESTBED_Controller *controller); /** * Try to open a connection to the given neigbour. If the connection is open * already, then it is re-used. If not, the request is queued in the operation * queues responsible for bounding the total number of file descriptors. The * actual connection will happen when the operation queue marks the * corresponding operation as active. * * @param n the neighbour to open a connection to * @param cb the notification callback to call when the connection is opened * @param cb_cls the closure for the above callback */ struct NeighbourConnectNotification * GST_neighbour_get_connection (struct Neighbour *n, GST_NeigbourConnectNotifyCallback cb, void *cb_cls); /** * Cancel the request for opening a connection to the neighbour * * @param h the notification handle */ void GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h); /** * Release the connection to the neighbour. The actual connection will be * closed if connections to other neighbour are waiting (to maintain a bound on * the total number of connections that are open). * * @param n the neighbour whose connection can be closed */ void GST_neighbour_release_connection (struct Neighbour *n); /** * Function to create a neigbour and add it into the neighbour list * * @param host the host of the neighbour */ struct Neighbour * GST_create_neighbour (struct GNUNET_TESTBED_Host *host); /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Cleans up the slave list */ void GST_slave_list_clear (); gnunet-0.10.1/src/testbed/gnunet-service-testbed_meminfo.h0000644000175000017500000000371712225777503020526 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* obsolete */ extern unsigned long kb_main_shared; /* old but still kicking -- the important stuff */ extern unsigned long kb_main_buffers; extern unsigned long kb_main_cached; extern unsigned long kb_main_free; extern unsigned long kb_main_total; extern unsigned long kb_swap_free; extern unsigned long kb_swap_total; /* recently introduced */ extern unsigned long kb_high_free; extern unsigned long kb_high_total; extern unsigned long kb_low_free; extern unsigned long kb_low_total; /* 2.4.xx era */ extern unsigned long kb_active; extern unsigned long kb_inact_laundry; // grrr... extern unsigned long kb_inact_dirty; extern unsigned long kb_inact_clean; extern unsigned long kb_inact_target; extern unsigned long kb_swap_cached; /* late 2.4+ */ /* derived values */ extern unsigned long kb_swap_used; extern unsigned long kb_main_used; /* 2.5.41+ */ extern unsigned long kb_writeback; extern unsigned long kb_slab; extern unsigned long nr_reversemaps; extern unsigned long kb_committed_as; extern unsigned long kb_dirty; extern unsigned long kb_inactive; extern unsigned long kb_mapped; extern unsigned long kb_pagetables; extern void meminfo(void); gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topologyring.conf0000644000175000017500000000011312233724131023627 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = RING gnunet-0.10.1/src/testbed/test_testbed_api_peer_reconfiguration.c0000644000175000017500000001250112225777502022222 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_peer_reconfiguration.c * @brief testcase for testing GNUNET_TESTBED_peer_manage_service() * implementation * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we want to start */ #define NUM_PEERS 1 /** * The array of peers; we get them from the testbed */ static struct GNUNET_TESTBED_Peer **peers; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * States in this test */ enum { /** * Test has just been initialized */ STATE_INIT, /** * Peers have been started */ STATE_PEER_STARTED, /** * Peer has been reconfigured. Test completed successfully */ STATE_PEER_RECONFIGURED } state; /** * Fail testcase */ #define FAIL_TEST(cond, ret) do { \ if (!(cond)) { \ GNUNET_break(0); \ if (GNUNET_SCHEDULER_NO_TASK != abort_task) \ GNUNET_SCHEDULER_cancel (abort_task); \ abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ ret; \ } \ } while (0) /** * Abort task * * @param cls NULL * @param tc scheduler task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != op) { GNUNET_TESTBED_operation_done (op); op = NULL; } GNUNET_SCHEDULER_shutdown(); } /** * Signature of the event handler function called by the * respective event controller. * * @param cls closure * @param event information about the event */ static void controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { if (STATE_PEER_STARTED != state) return; if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type) { GNUNET_TESTBED_operation_done (op); op = NULL; FAIL_TEST (0, return); } if (NULL != event->details.operation_finished.emsg) { fprintf (stderr, "Operation failed: %s\n", event->details.operation_finished.emsg); GNUNET_TESTBED_operation_done (op); op = NULL; FAIL_TEST (0, return); } GNUNET_TESTBED_operation_done (op); state = STATE_PEER_RECONFIGURED; GNUNET_SCHEDULER_cancel (abort_task); abort_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_SCHEDULER_shutdown (); } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { struct GNUNET_CONFIGURATION_Handle *cfg; FAIL_TEST (NUM_PEERS == num_peers, return); state = STATE_PEER_STARTED; peers = peers_; cfg = GNUNET_CONFIGURATION_create (); FAIL_TEST (GNUNET_OK == GNUNET_CONFIGURATION_load (cfg, "test_testbed_api_testbed_run_topologyrandom.conf"), return); op = GNUNET_TESTBED_peer_update_configuration (peers[0], cfg); GNUNET_CONFIGURATION_destroy (cfg); FAIL_TEST (NULL != op, return); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { state = STATE_INIT; (void) GNUNET_TESTBED_test_run ("test_testbed_api_peer_reconfiguration", "test_testbed_api.conf", NUM_PEERS, 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED, &controller_cb, NULL, &test_master, NULL); if (STATE_PEER_RECONFIGURED != state) return 1; return 0; } gnunet-0.10.1/src/testbed/test_testbed_api.conf0000644000175000017500000000005012233724131016415 00000000000000@INLINE@ test_testbed_api_template.conf gnunet-0.10.1/src/testbed/test_testbed_api_barriers.c0000644000175000017500000001367212225777502017634 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_barriers.c * @brief testcase binary for testing testbed barriers API * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "test_testbed_api_barriers.h" /** * logging short hand */ #define LOG(type,...) \ GNUNET_log (type, __VA_ARGS__); /** * Number of peers we start in this test case */ #define NUM_PEERS 3 /** * Our barrier */ struct GNUNET_TESTBED_Barrier *barrier; /** * Identifier for the shutdown task */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Result of this test case */ static int result; /** * Shutdown this test case when it takes too long * * @param cls NULL * @param tc scheduler task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != barrier) { GNUNET_TESTBED_barrier_cancel (barrier); barrier = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Functions of this type are to be given as callback argument to * GNUNET_TESTBED_barrier_init(). The callback will be called when status * information is available for the barrier. * * @param cls the closure given to GNUNET_TESTBED_barrier_init() * @param name the name of the barrier * @param barrier the barrier handle * @param status status of the barrier; GNUNET_OK if the barrier is crossed; * GNUNET_SYSERR upon error * @param emsg if the status were to be GNUNET_SYSERR, this parameter has the * error messsage */ static void barrier_cb (void *cls, const char *name, struct GNUNET_TESTBED_Barrier *_barrier, enum GNUNET_TESTBED_BarrierStatus status, const char *emsg) { static enum GNUNET_TESTBED_BarrierStatus old_status; GNUNET_assert (NULL == cls); GNUNET_assert (_barrier == barrier); switch (status) { case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: LOG (GNUNET_ERROR_TYPE_INFO, "Barrier initialised\n"); old_status = status; return; case GNUNET_TESTBED_BARRIERSTATUS_ERROR: LOG (GNUNET_ERROR_TYPE_ERROR, "Barrier initialisation failed: %s", (NULL == emsg) ? "unknown reason" : emsg); barrier = NULL; GNUNET_SCHEDULER_shutdown (); return; case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: LOG (GNUNET_ERROR_TYPE_INFO, "Barrier crossed\n"); if (old_status == GNUNET_TESTBED_BARRIERSTATUS_INITIALISED) result = GNUNET_OK; barrier = NULL; GNUNET_SCHEDULER_shutdown (); return; default: GNUNET_assert (0); } } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { struct GNUNET_TESTBED_Controller *c; GNUNET_assert (NULL == cls); if (NULL == peers_) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failing test due to timeout\n"); return; } GNUNET_assert (NUM_PEERS == num_peers); c = GNUNET_TESTBED_run_get_controller_handle (h); barrier = GNUNET_TESTBED_barrier_init (c, TEST_BARRIER_NAME, 100, &barrier_cb, NULL); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10 * (NUM_PEERS + 1)), &do_shutdown, NULL); } /** * Main function */ int main (int argc, char **argv) { struct GNUNET_CONFIGURATION_Handle *cfg; char pwd[PATH_MAX]; char *binary; uint64_t event_mask; result = GNUNET_SYSERR; event_mask = 0; cfg = GNUNET_CONFIGURATION_create (); GNUNET_assert (GNUNET_YES == GNUNET_CONFIGURATION_parse (cfg, "test_testbed_api_barriers.conf.in")); if (NULL == getcwd (pwd, PATH_MAX)) return 1; GNUNET_assert (0 < GNUNET_asprintf (&binary, "%s/%s", pwd, "gnunet-service-test-barriers")); GNUNET_CONFIGURATION_set_value_string (cfg, "test-barriers","BINARY", binary); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_write (cfg, "test_testbed_api_barriers.conf")); GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; GNUNET_free (binary); binary = NULL; (void) GNUNET_TESTBED_test_run ("test_testbed_api_barriers", "test_testbed_api_barriers.conf", NUM_PEERS, event_mask, NULL, NULL, &test_master, NULL); (void) unlink ("test_testbed_api_barriers.conf"); if (GNUNET_OK != result) return 1; return 0; } gnunet-0.10.1/src/testbed/testbed_api.h0000644000175000017500000003035612225777503014710 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api.h * @brief Interface for functions internally exported from testbed_api.c * @author Sree Harsha Totakura */ #ifndef TESTBED_API_H #define TESTBED_API_H #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "testbed.h" #include "testbed_helper.h" /** * Testbed Helper binary name */ #define HELPER_TESTBED_BINARY "gnunet-helper-testbed" /** * Enumeration of operations */ enum OperationType { /** * Peer create operation */ OP_PEER_CREATE, /** * Peer start operation */ OP_PEER_START, /** * Peer stop operation */ OP_PEER_STOP, /** * Peer destroy operation */ OP_PEER_DESTROY, /** * Get peer information operation */ OP_PEER_INFO, /** * Reconfigure a peer */ OP_PEER_RECONFIGURE, /** * Overlay connection operation */ OP_OVERLAY_CONNECT, /** * Forwarded operation */ OP_FORWARDED, /** * Link controllers operation */ OP_LINK_CONTROLLERS, /** * Get slave config operation */ OP_GET_SLAVE_CONFIG, /** * Stop and destroy all peers */ OP_SHUTDOWN_PEERS, /** * Start/stop service at a peer */ OP_MANAGE_SERVICE }; /** * The message queue for sending messages to the controller service */ struct MessageQueue; /** * Enumeration of states of OperationContext */ enum OperationContextState { /** * The initial state where the associated operation has just been created * and is waiting in the operation queues to be started */ OPC_STATE_INIT = 0, /** * The operation has been started. It may occupy some resources which are to * be freed if cancelled. */ OPC_STATE_STARTED, /** * The operation has finished. The end results of this operation may occupy * some resources which are to be freed by operation_done */ OPC_STATE_FINISHED }; /** * Context information for GNUNET_TESTBED_Operation */ struct OperationContext { /** * The controller to which this operation context belongs to */ struct GNUNET_TESTBED_Controller *c; /** * The operation */ struct GNUNET_TESTBED_Operation *op; /** * The operation closure */ void *op_cls; /** * Data relevant to the operation */ void *data; /** * The id of the opearation */ uint64_t id; /** * The type of operation */ enum OperationType type; /** * The state of the operation */ enum OperationContextState state; }; /** * Operation empty callback * * @param cls closure */ typedef void (*TESTBED_opcq_empty_cb) (void *cls); /** * Handle to interact with a GNUnet testbed controller. Each * controller has at least one master handle which is created when the * controller is created; this master handle interacts with the * controller process, destroying it destroys the controller (by * closing stdin of the controller process). Additionally, * controllers can interact with each other (in a P2P fashion); those * links are established via TCP/IP on the controller's service port. */ struct GNUNET_TESTBED_Controller { /** * The host where the controller is running */ struct GNUNET_TESTBED_Host *host; /** * The controller callback */ GNUNET_TESTBED_ControllerCallback cc; /** * The closure for controller callback */ void *cc_cls; /** * The configuration to use while connecting to controller */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * The client connection handle to the controller service */ struct GNUNET_CLIENT_Connection *client; /** * The head of the message queue */ struct MessageQueue *mq_head; /** * The tail of the message queue */ struct MessageQueue *mq_tail; /** * The client transmit handle */ struct GNUNET_CLIENT_TransmitHandle *th; /** * The host registration handle; NULL if no current registration requests are * present */ struct GNUNET_TESTBED_HostRegistrationHandle *rh; /** * The map of active operation contexts */ struct GNUNET_CONTAINER_MultiHashMap32 *opc_map; /** * If this callback is not NULL, schedule it as a task when opc_map gets empty */ TESTBED_opcq_empty_cb opcq_empty_cb; /** * Closure for the above task */ void *opcq_empty_cls; /** * Operation queue for simultaneous operations */ struct OperationQueue *opq_parallel_operations; /** * Operation queue for simultaneous service connections */ struct OperationQueue *opq_parallel_service_connections; /** * Operation queue for simultaneous topology configuration operations */ struct OperationQueue *opq_parallel_topology_config_operations; /** * The controller event mask */ uint64_t event_mask; /** * Did we start the receive loop yet? */ int in_receive; /** * The operation id counter. use current value and increment */ uint32_t operation_counter; }; /** * Queues a message in send queue for sending to the service * * @param controller the handle to the controller * @param msg the message to queue */ void GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller, struct GNUNET_MessageHeader *msg); /** * Inserts the given operation context into the operation context map of the * given controller. Creates the operation context map if one does not exist * for the controller * * @param c the controller * @param opc the operation context to be inserted */ void GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c, struct OperationContext *opc); /** * Removes the given operation context from the operation context map of the * given controller * * @param c the controller * @param opc the operation context to remove */ void GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c, struct OperationContext *opc); /** * Compresses given configuration using zlib compress * * @param config the serialized configuration * @param size the size of config * @param xconfig will be set to the compressed configuration (memory is fresly * allocated) * @return the size of the xconfig */ size_t GNUNET_TESTBED_compress_config_ (const char *config, size_t size, char **xconfig); /** * Function to serialize and compress using zlib a configuration through a * configuration handle * * @param cfg the configuration * @param size the size of configuration when serialize. Will be set on success. * @param xsize the sizeo of the compressed configuration. Will be set on success. * @return the serialized and compressed configuration */ char * GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg, size_t *size, size_t *xsize); /** * Creates a helper initialization message. This function is here because we * want to use this in testing * * @param trusted_ip the ip address of the controller which will be set as TRUSTED * HOST(all connections form this ip are permitted by the testbed) when * starting testbed controller at host. This can either be a single ip * address or a network address in CIDR notation. * @param hostname the hostname of the destination this message is intended for * @param cfg the configuration that has to used to start the testbed service * thru helper * @return the initialization message */ struct GNUNET_TESTBED_HelperInit * GNUNET_TESTBED_create_helper_init_msg_ (const char *cname, const char *hostname, const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Sends the given message as an operation. The given callback is called when a * reply for the operation is available. Call * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned * operation context if the cc hasn't been called * * @param controller the controller to which the message has to be sent * @param operation_id the operation id of the message * @param msg the message to send * @param cc the callback to call when reply is available * @param cc_cls the closure for the above callback * @return the operation context which can be used to cancel the forwarded * operation */ struct OperationContext * GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller *controller, uint64_t operation_id, const struct GNUNET_MessageHeader *msg, GNUNET_CLIENT_MessageHandler cc, void *cc_cls); /** * Function to cancel an operation created by simply forwarding an operation * message. * * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_() */ void GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc); /** * Generates configuration by uncompressing configuration in given message. The * given message should be of the following types: * GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG, * GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG * * @param msg the message containing compressed configuration * @return handle to the parsed configuration */ struct GNUNET_CONFIGURATION_Handle * GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg); /** * Checks the integrity of the OpeationFailureEventMessage and if good returns * the error message it contains. * * @param msg the OperationFailureEventMessage * @return the error message */ const char * GNUNET_TESTBED_parse_error_string_ (const struct GNUNET_TESTBED_OperationFailureEventMessage *msg); /** * Function to return the operation id for a controller. The operation id is * created from the controllers host id and its internal operation counter. * * @param controller the handle to the controller whose operation id has to be incremented * @return the incremented operation id. */ uint64_t GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller); /** * Like GNUNET_TESTBED_get_slave_config(), however without the host registration * check. Another difference is that this function takes the id of the slave * host. * * @param op_cls the closure for the operation * @param master the handle to master controller * @param slave_host_id id of the host where the slave controller is running to * the slave_host should remain valid until this operation is cancelled * or marked as finished * @return the operation handle; */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_get_slave_config_ (void *op_cls, struct GNUNET_TESTBED_Controller *master, uint32_t slave_host_id); /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages. This * function is defined in @file testbed_api_barriers.c * * @param c the controller handle to determine the connection this message * belongs to * @param msg the barrier status message * @return GNUNET_OK to keep the connection active; GNUNET_SYSERR to tear it * down signalling an error */ int GNUNET_TESTBED_handle_barrier_status_ (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_BarrierStatusMsg *msg); #endif /* end of testbed_api.h */ gnunet-0.10.1/src/testbed/testbed_api_topology.h0000644000175000017500000001031112262754601016624 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_topology.h * @brief header for intra library exported functions * @author Sree Harsha Totakura */ #ifndef TESTBED_API_TOPOLOGY_H #define TESTBED_API_TOPOLOGY_H /** * Returns the number of links that are required to generate a 2d torus for the * given number of peers. Also returns the arrangment (number of rows and the * length of each row) * * @param num_peers number of peers * @param rows number of rows in the 2d torus. Can be NULL. * @param rows_len the length of each row. This array will be allocated * fresh. The caller should free it. Can be NULL. */ unsigned int GNUNET_TESTBED_2dtorus_calc_links (unsigned int num_peers, unsigned int *rows, unsigned int **rows_len); /** * Get a topology from a string input. * * @param topology where to write the retrieved topology * @param topology_string The string to attempt to * get a configuration value from * @return GNUNET_YES if topology string matched a * known topology, GNUNET_NO if not */ int GNUNET_TESTBED_topology_get_ (enum GNUNET_TESTBED_TopologyOption *topology, const char *topology_string); /** * Returns the string corresponding to the given topology * * @param topology the topology * @return the string (freshly allocated) of given topology; NULL if topology cannot be * expressed as a string */ char * GNUNET_TESTBED_topology_to_str_ (enum GNUNET_TESTBED_TopologyOption topology); /** * Functions of this type are called to process underlay link * * @param cls closure * @param A offset of first peer * @param B offset of second peer * @param bandwidth the bandwidth of the link in bytes per second * @param latency the latency of link in milliseconds * @param loss the percentage of messages dropped on the link * @return GNUNET_OK to continue processing; GNUNET_SYSERR to abort */ typedef int (*underlay_link_processor) (void *cls, unsigned int A, unsigned int B, unsigned int bandwidth, unsigned int latency, unsigned int loss); /** * Function to construct an underlay topology * * @param num_peers the number of peers for which the topology should be * generated * @param proc the underlay link processor callback. Will be called for each * underlay link generated unless a previous call to this callback * returned GNUNET_SYSERR. Cannot be NULL. * @param cls closure for proc * @param ... variable arguments denoting the topology and its parameters. They * should start with the type of topology to generate followed by their * options. These arguments should *always* end with * GNUNET_TESTBED_TOPOLOGY_OPTION_END option * @return GNUNET_OK if underlay link generation is successful; GNUNET_SYSERR * upon error in generating the underlay or if any calls to the * underlay link processor returned GNUNET_SYSERR */ int GNUNET_TESTBED_underlay_construct_ (int num_peers, underlay_link_processor proc, void *cls, ...); #endif /* end of testbed_api_topology.h */ gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topologyclique.conf0000644000175000017500000000011512233724131024154 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = CLIQUE gnunet-0.10.1/src/testbed/test_testbed_api_hosts.c0000644000175000017500000001303112225777502017150 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_hosts.c * @brief tests cases for testbed_api_hosts.c * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "testbed_api_hosts.h" #define TIME_REL_SECS(sec) \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) /** * configuration handle to use as template configuration while creating hosts */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Host we are creating and using */ static struct GNUNET_TESTBED_Host *host; /** * An array of hosts which are loaded from a file */ static struct GNUNET_TESTBED_Host **hosts; /** * Number of hosts in the above list */ static unsigned int num_hosts; /** * Global test status */ static int status; /** * Shutdown task identifier */ GNUNET_SCHEDULER_TaskIdentifier shutdown_id; /** * The shutdown task * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_TESTBED_host_destroy (host); while (0 != num_hosts) { GNUNET_TESTBED_host_destroy (hosts[num_hosts - 1]); num_hosts--; } GNUNET_free (hosts); if (NULL != cfg) { GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; } } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { unsigned int cnt; cfg = GNUNET_CONFIGURATION_dup (config); host = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0); GNUNET_assert (NULL != host); GNUNET_assert (0 != GNUNET_TESTBED_host_get_id_ (host)); GNUNET_TESTBED_host_destroy (host); host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0); GNUNET_assert (NULL != host); GNUNET_assert (0 == GNUNET_TESTBED_host_get_id_ (host)); GNUNET_assert (host == GNUNET_TESTBED_host_lookup_by_id_ (0)); hosts = NULL; num_hosts = GNUNET_TESTBED_hosts_load_from_file ("sample_hosts.txt", cfg, &hosts); GNUNET_assert (7 == num_hosts); GNUNET_assert (NULL != hosts); for (cnt = 0; cnt < num_hosts; cnt++) { if (cnt < 3) { GNUNET_assert (0 == strcmp ("totakura", GNUNET_TESTBED_host_get_username_ (hosts[cnt]))); GNUNET_assert (NULL != GNUNET_TESTBED_host_get_hostname (hosts[cnt])); GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); } if (3 == cnt) { GNUNET_assert (0 == strcmp ("totakura", GNUNET_TESTBED_host_get_username_ (hosts[cnt]))); GNUNET_assert (NULL != GNUNET_TESTBED_host_get_hostname (hosts[cnt])); GNUNET_assert (2022 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); } if (4 == cnt) { GNUNET_assert (0 == strcmp ("totakura", GNUNET_TESTBED_host_get_username_ (hosts[cnt]))); GNUNET_assert (0 == strcmp ("asgard.realm", GNUNET_TESTBED_host_get_hostname (hosts[cnt]))); GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); } if (5 == cnt) { GNUNET_assert (NULL == GNUNET_TESTBED_host_get_username_ (hosts[cnt])); GNUNET_assert (0 == strcmp ("rivendal", GNUNET_TESTBED_host_get_hostname (hosts[cnt]))); GNUNET_assert (22 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); } if (6 == cnt) { GNUNET_assert (NULL == GNUNET_TESTBED_host_get_username_ (hosts[cnt])); GNUNET_assert (0 == strcmp ("rohan", GNUNET_TESTBED_host_get_hostname (hosts[cnt]))); GNUNET_assert (561 == GNUNET_TESTBED_host_get_ssh_port_ (hosts[cnt])); } } status = GNUNET_YES; shutdown_id = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (0), &do_shutdown, NULL); } int main (int argc, char **argv) { char *const argv2[] = { "test_testbed_api_hosts", "-c", "test_testbed_api.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; status = GNUNET_SYSERR; if (GNUNET_OK != GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2, "test_testbed_api_hosts", "nohelp", options, &run, NULL)) return 1; return (GNUNET_OK == status) ? 0 : 1; } /* end of test_testbed_api_hosts.c */ gnunet-0.10.1/src/testbed/test_testbed_api_testbed_run_topologyrandom.conf0000644000175000017500000000014612233724131024156 00000000000000@INLINE@ test_testbed_api_template.conf [testbed] OVERLAY_TOPOLOGY = RANDOM OVERLAY_RANDOM_LINKS = 5 gnunet-0.10.1/src/testbed/test_testbed_api_statistics.c0000644000175000017500000001365412225777502020215 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/test_testbed_api_statistics.c * @brief testcase for testing GNUNET_TESTBED_get_statistics() implementation * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Number of peers we want to start */ #define NUM_PEERS 5 /** * The array of peers; we get them from the testbed */ static struct GNUNET_TESTBED_Peer **peers; /** * Operation handle */ static struct GNUNET_TESTBED_Operation *op; /** * dummy pointer */ static void *dummy_cls = (void *) 0xDEAD0001; /** * Abort task identifier */ static GNUNET_SCHEDULER_TaskIdentifier abort_task; /** * Global testing result */ static int result; /** * The peers we have seen in the statistics iterator */ static struct GNUNET_TESTBED_Peer **seen_peers; /** * Number of peers in the above array */ static unsigned int num_seen_peers; /** * Fail testcase */ #define FAIL_TEST(cond, ret) do { \ if (!(cond)) { \ GNUNET_break(0); \ if (GNUNET_SCHEDULER_NO_TASK != abort_task) \ GNUNET_SCHEDULER_cancel (abort_task); \ abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \ ret; \ } \ } while (0) /** * Abort task * * @param cls NULL * @param tc scheduler task context */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test timed out -- Aborting\n"); abort_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != op) { GNUNET_TESTBED_operation_done (op); op = NULL; } result = GNUNET_SYSERR; } /** * Callback function to process statistic values from all peers. * * @param cls closure * @param peer the peer the statistic belong to * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, const char *subsystem, const char *name, uint64_t value, int is_persistent) { unsigned int cnt; FAIL_TEST (cls == dummy_cls, return GNUNET_SYSERR); for (cnt = 0; cnt < num_seen_peers; cnt++) FAIL_TEST (peer != seen_peers[cnt], return GNUNET_SYSERR); FAIL_TEST (NULL != subsystem, return GNUNET_SYSERR); FAIL_TEST (NULL != name, return GNUNET_SYSERR); GNUNET_array_append (seen_peers, num_seen_peers, (struct GNUNET_TESTBED_Peer *) peer); return GNUNET_SYSERR; } /** * Callback to be called when an operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void op_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { FAIL_TEST (cls == dummy_cls, return); result = GNUNET_OK; GNUNET_TESTBED_operation_done (op); op = NULL; GNUNET_SCHEDULER_cancel (abort_task); GNUNET_SCHEDULER_shutdown (); } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { FAIL_TEST (NUM_PEERS == num_peers, return); peers = peers_; op = GNUNET_TESTBED_get_statistics (num_peers, peers, NULL, NULL, &stats_iterator, &op_comp_cb, dummy_cls); abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1), &do_abort, NULL); } /** * Main function */ int main (int argc, char **argv) { (void) GNUNET_TESTBED_test_run ("test_testbed_api_statistics", "test_testbed_api_statistics.conf", NUM_PEERS, 1LL, NULL, NULL, &test_master, NULL); GNUNET_free_non_null (seen_peers); if (GNUNET_OK != result) return 1; return 0; } gnunet-0.10.1/src/testbed/testbed.h0000644000175000017500000004400412261236531014041 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed.h * @brief IPC messages between testing API and service ("controller") * @author Christian Grothoff */ #ifndef TESTBED_H #define TESTBED_H #include "gnunet_util_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Initial message from a client to a testing control service. */ struct GNUNET_TESTBED_InitMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_INIT */ struct GNUNET_MessageHeader header; /** * Host ID that the controller is either given (if this is the * dominating client) or assumed to have (for peer-connections * between controllers). A controller must check that all * connections make consistent claims... */ uint32_t host_id GNUNET_PACKED; /** * Event mask that specifies which events this client * is interested in. In NBO. */ uint64_t event_mask GNUNET_PACKED; /* Followed by 0-terminated hostname of the controller */ }; /** * Notify the service about a host that we intend to use. */ struct GNUNET_TESTBED_AddHostMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST */ struct GNUNET_MessageHeader header; /** * Unique ID for the host (in NBO). */ uint32_t host_id GNUNET_PACKED; /** * SSH port to use, 0 for default (in NBO). */ uint16_t ssh_port GNUNET_PACKED; /** * Number of bytes in the user name that follows; * 0 to use no user name; otherwise 'strlen (username)', * excluding 0-termination! */ uint16_t username_length GNUNET_PACKED; /** * Number of bytes in the host name (excluding 0-termination) that follows the * user name; cannot be 0 */ uint16_t hostname_length GNUNET_PACKED; /** * The length of the uncompressed configuration */ uint16_t config_size GNUNET_PACKED; /* followed by non 0-terminated user name */ /* followed by non 0-terminated host name */ /* followed by gzip compressed configuration to start or connect to a controller on this host. While starting the controller this configration is used as a template */ }; /** * Confirmation from the service that adding a host * worked (or failed). * FIXME: Where is this required? */ struct GNUNET_TESTBED_HostConfirmedMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS */ struct GNUNET_MessageHeader header; /** * Unique ID for the host (in NBO). */ uint32_t host_id GNUNET_PACKED; /* followed by the 0-terminated error message (on failure) * (typical errors include host-id already in use) */ }; /** * Client notifies controller that it should delegate * requests for a particular client to a particular * sub-controller. */ struct GNUNET_TESTBED_ControllerLinkRequest { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS */ struct GNUNET_MessageHeader header; /** * For which host should requests be delegated? NBO. */ uint32_t delegated_host_id GNUNET_PACKED; /** * The id of the operation which created this message */ uint64_t operation_id GNUNET_PACKED; /** * Which host is responsible for managing the delegation? NBO */ uint32_t slave_host_id GNUNET_PACKED; /** * Set to 1 if the receiving controller is the master controller for * the slave host (and thus responsible for starting it?). 0 if not */ uint8_t is_subordinate; }; /** * Response message for ControllerLinkRequest message */ struct GNUNET_TESTBED_ControllerLinkResponse { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT */ struct GNUNET_MessageHeader header; /** * The size of the compressed configuration. Can be ZERO if the controller is * not started (depends on the ControllerLinkRequest). NBO. */ uint16_t config_size GNUNET_PACKED; /** * Set to GNUNET_YES to signify SUCCESS; GNUNET_NO to signify failure */ uint16_t success GNUNET_PACKED; /** * The id of the operation which created this message. NBO */ uint64_t operation_id GNUNET_PACKED; /* If controller linking is successful and configuration is present, then here * comes the serialized gzip configuration with which the controller is * running at the delegate host */ /* In case of failure, here comes the error message (without \0 termination)*/ }; /** * Message sent from client to testing service to * create (configure, but not start) a peer. */ struct GNUNET_TESTBED_PeerCreateMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER */ struct GNUNET_MessageHeader header; /** * On which host should the peer be started? */ uint32_t host_id GNUNET_PACKED; /** * Unique operation id */ uint64_t operation_id GNUNET_PACKED; /** * Unique ID for the peer. */ uint32_t peer_id GNUNET_PACKED; /** * Size of the uncompressed configuration */ uint16_t config_size GNUNET_PACKED; /* followed by serialized peer configuration; * gzip'ed configuration file in INI format */ }; /** * Message sent from client to testing service to * reconfigure a (stopped) a peer. */ struct GNUNET_TESTBED_PeerReconfigureMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER */ struct GNUNET_MessageHeader header; /** * Unique ID for the peer. */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; /** * The length of the serialized configuration when uncompressed */ uint16_t config_size GNUNET_PACKED; /* followed by serialized peer configuration; * gzip'ed configuration file in INI format */ }; /** * Message sent from client to testing service to * start a peer. */ struct GNUNET_TESTBED_PeerStartMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_START_PEER */ struct GNUNET_MessageHeader header; /** * Unique ID for the peer. */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; }; /** * Message sent from client to testing service to * stop a peer. */ struct GNUNET_TESTBED_PeerStopMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER */ struct GNUNET_MessageHeader header; /** * Unique ID for the peer. */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; }; /** * Message sent from client to testing service to * destroy a (stopped) peer. */ struct GNUNET_TESTBED_PeerDestroyMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER */ struct GNUNET_MessageHeader header; /** * Unique ID for the peer. */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; }; /** * Message sent from client to testing service to * (re)configure a "physical" link between two peers. */ struct GNUNET_TESTBED_ConfigureUnderlayLinkMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_CONFIGURE_UNDERLAY_LINK */ struct GNUNET_MessageHeader header; /** * 'enum GNUNET_TESTBED_ConnectOption' of the option to change */ int32_t connect_option GNUNET_PACKED; /** * Unique ID for the first peer. */ uint32_t peer1 GNUNET_PACKED; /** * Unique ID for the second peer. */ uint32_t peer2 GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; /* followed by option-dependent variable-size values */ }; /** * Message sent from client to testing service to * connect two peers. */ struct GNUNET_TESTBED_OverlayConnectMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT */ struct GNUNET_MessageHeader header; /** * Unique ID for the first peer. */ uint32_t peer1 GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; /** * Unique ID for the second peer. */ uint32_t peer2 GNUNET_PACKED; /** * The ID of the host which runs peer2 */ uint32_t peer2_host_id GNUNET_PACKED; }; /** * Message sent from host controller of a peer(A) to the host controller of * another peer(B) to request B to connect to A */ struct GNUNET_TESTBED_RemoteOverlayConnectMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT */ struct GNUNET_MessageHeader header; /** * The Unique ID of B */ uint32_t peer GNUNET_PACKED; /** * The Operation ID that is used to identify this operation */ uint64_t operation_id GNUNET_PACKED; /** * Identity of A */ struct GNUNET_PeerIdentity peer_identity; /** * To be followed by the HELLO message of A */ struct GNUNET_MessageHeader hello[0]; // FIXME: we usually do not use this gcc-hack as some // compilers / tools really get messed up by it... }; /** * Event notification from a controller to a client. */ struct GNUNET_TESTBED_PeerEventMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT */ struct GNUNET_MessageHeader header; /** * `enum GNUNET_TESTBED_EventType` (in NBO); * either #GNUNET_TESTBED_ET_PEER_START or #GNUNET_TESTBED_ET_PEER_STOP. */ int32_t event_type GNUNET_PACKED; /** * Host where the peer is running. */ uint32_t host_id GNUNET_PACKED; /** * Peer that was started or stopped. */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; }; /** * Event notification from a controller to a client. */ struct GNUNET_TESTBED_ConnectionEventMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT */ struct GNUNET_MessageHeader header; /** * 'enum GNUNET_TESTBED_EventType' (in NBO); * either GNUNET_TESTBED_ET_CONNECT or GNUNET_TESTBED_ET_DISCONNECT. */ int32_t event_type GNUNET_PACKED; /** * First peer. */ uint32_t peer1 GNUNET_PACKED; /** * Second peer. */ uint32_t peer2 GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; }; /** * Event notification from a controller to a client. */ struct GNUNET_TESTBED_OperationFailureEventMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT */ struct GNUNET_MessageHeader header; /** * 'enum GNUNET_TESTBED_EventType' (in NBO); * GNUNET_TESTBED_ET_OPERATION_FINISHED. */ int32_t event_type GNUNET_PACKED; /** * Operation ID of the operation that created this event. */ uint64_t operation_id GNUNET_PACKED; /* followed by 0-terminated error message */ }; /** * Event notification from a controller to a client. */ struct GNUNET_TESTBED_PeerCreateSuccessEventMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS */ struct GNUNET_MessageHeader header; /** * Peer identity of the peer that was created. */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID of the operation that created this event. */ uint64_t operation_id GNUNET_PACKED; }; /** * Event notification from a controller to a client for * a generic operational success where the operation does * not return any data. */ struct GNUNET_TESTBED_GenericOperationSuccessEventMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS */ struct GNUNET_MessageHeader header; /** * 'enum GNUNET_TESTBED_EventType' (in NBO); * GNUNET_TESTBED_ET_OPERATION_FINISHED. */ int32_t event_type GNUNET_PACKED; /** * Operation ID of the operation that created this event. */ uint64_t operation_id GNUNET_PACKED; }; /** * Message sent from client to testing service to * obtain the configuration of a peer. */ struct GNUNET_TESTBED_PeerGetConfigurationMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION */ struct GNUNET_MessageHeader header; /** * Unique ID for the peer. */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID that is used to identify this operation. */ uint64_t operation_id GNUNET_PACKED; }; /** * Peer configuration and identity reply from controller to a client. */ struct GNUNET_TESTBED_PeerConfigurationInformationMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION */ struct GNUNET_MessageHeader header; /** * The id of the peer relevant to this information */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID of the operation that created this event. */ uint64_t operation_id GNUNET_PACKED; /** * Identity of the peer. */ struct GNUNET_PeerIdentity peer_identity; /** * The size of configuration when uncompressed */ uint16_t config_size GNUNET_PACKED; /* followed by gzip-compressed configuration of the peer */ }; /** * Message to request configuration of a slave controller */ struct GNUNET_TESTBED_SlaveGetConfigurationMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION */ struct GNUNET_MessageHeader header; /** * The id of the slave host */ uint32_t slave_id GNUNET_PACKED; /** * Operation ID */ uint64_t operation_id GNUNET_PACKED; }; /** * Reply to #GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION message */ struct GNUNET_TESTBED_SlaveConfiguration { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION */ struct GNUNET_MessageHeader header; /** * The id of the host where the slave is running */ uint32_t slave_id GNUNET_PACKED; /** * Operation ID */ uint64_t operation_id GNUNET_PACKED; /** * The size of the configuration when uncompressed */ uint16_t config_size GNUNET_PACKED; /* followed by gzip-compressed configuration of the peer */ }; /** * Shutdown peers message */ struct GNUNET_TESTBED_ShutdownPeersMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS */ struct GNUNET_MessageHeader header; /** * Operation ID */ uint64_t operation_id GNUNET_PACKED; }; /** * Message to start/stop services of a peer */ struct GNUNET_TESTBED_ManagePeerServiceMessage { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS */ struct GNUNET_MessageHeader header; /** * Unique ID of the peer whose service has to be managed. */ uint32_t peer_id GNUNET_PACKED; /** * Operation ID */ uint64_t operation_id GNUNET_PACKED; /** * set this to 1 to start the service; 0 to stop the service */ uint8_t start; /** * The NULL-terminated name of the service to start/stop follows here */ }; /** * Message to send underlay link model of a peer. This message will be * forwarded to the controller running the peer. */ struct GNUNET_TESTBED_UnderlayLinkModelMsg { /** * Type is GNUNET_MESSAGE_TYPE_UNDERLAYLINKMODELMSG */ struct GNUNET_MessageHeader header; /** * The number of peer entries contained in this message */ uint32_t nentries GNUNET_PACKED; /** * The number of link properties contained in this message */ uint32_t nprops GNUNET_PACKED; /** * Array of ids of peers to be in the blacklist/whitelist. Each id is of type * uint32_t. Number of ids should be equal to nentries. */ /** * Array of link properties. Each link property is to be arraged in a * sequence of four integers of type uint32_t: peer_id, latency, loss and * bandwidth. */ }; /**************************************/ /* Barriers IPC messages and protocol */ /**************************************/ /** * The environmental variable which when available refers to the configuration * file the local testbed controller is using */ #define ENV_TESTBED_CONFIG "GNUNET_TESTBED_CONTROLLER_CONFIG" /** * Message to initialise a barrier */ struct GNUNET_TESTBED_BarrierInit { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT */ struct GNUNET_MessageHeader header; /** * The quorum percentage needed for crossing the barrier */ uint8_t quorum; /** * name of the barrier. Non NULL-terminated. */ char name[0]; }; /** * Message to cancel a barrier */ struct GNUNET_TESTBED_BarrierCancel { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL */ struct GNUNET_MessageHeader header; /** * The barrier name. Non NULL terminated */ char name[0]; }; /** * Message for signalling status changes of a barrier */ struct GNUNET_TESTBED_BarrierStatusMsg { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS */ struct GNUNET_MessageHeader header; /** * status. Use enumerated values of enum BarrierStatus */ uint16_t status GNUNET_PACKED; /** * strlen of the barrier name */ uint16_t name_len GNUNET_PACKED; /** * the barrier name (NULL terminated) concatenated with an error message (NULL * terminated) if the status were to indicate an error */ char data[0]; }; /** * Message sent from peers to the testbed-barrier service to indicate that they * have reached a barrier and are waiting for it to be crossed */ struct GNUNET_TESTBED_BarrierWait { /** * Type is GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT */ struct GNUNET_MessageHeader header; /** * The name of the barrier they have reached. Non-NULL terminated. */ char name[0]; }; GNUNET_NETWORK_STRUCT_END #endif /* end of testbed.h */ gnunet-0.10.1/src/testbed/generate-underlay-topology.c0000644000175000017500000002651012265232753017677 00000000000000/* This file is part of GNUnet (C) 2008--2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/generate-underlay-topology.c * @brief Program to generate a database file containing given underlay topology * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "testbed_api_topology.h" #include "sqlite3.h" #define LOG(type, ...) \ GNUNET_log (type, __VA_ARGS__) #define LOG_ERROR(...) \ LOG (GNUNET_ERROR_TYPE_ERROR, __VA_ARGS__) /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_SQLITE(db, msg, level, cmd) \ do { \ GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), \ cmd, __FILE__,__LINE__, sqlite3_errmsg(db)); \ if (msg != NULL) \ GNUNET_asprintf(msg, _("`%s' failed at %s:%u with error: %s"), cmd, \ __FILE__, __LINE__, sqlite3_errmsg(db)); \ } while(0) /** * Handle to the sqlite3 database */ static struct sqlite3 *db; /** * Prepared statement for inserting link values into db */ struct sqlite3_stmt *stmt_insert; /** * The topology to generate */ enum GNUNET_TESTBED_TopologyOption topology; /** * The number of peers to include in the topology */ static int num_peers; /** * program result */ static int exit_result; /** * Functions of this type are called to process underlay link * * @param cls closure * @param A offset of first peer * @param B offset of second peer * @param bandwidth the bandwidth of the link in bytes per second * @param latency the latency of link in milliseconds * @param loss the percentage of messages dropped on the link * @return GNUNET_OK to continue processing; GNUNET_SYSERR to abort */ static int link_processor (void *cls, unsigned int A, unsigned int B, unsigned int bandwidth, unsigned int latency, unsigned int loss) { if ( (SQLITE_OK != sqlite3_bind_int (stmt_insert, 1, A)) || (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, B)) || (SQLITE_OK != sqlite3_bind_int (stmt_insert, 3, bandwidth)) || (SQLITE_OK != sqlite3_bind_int (stmt_insert, 4, latency)) || (SQLITE_OK != sqlite3_bind_int (stmt_insert, 5, loss)) ) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); return GNUNET_SYSERR; } if (SQLITE_DONE != sqlite3_step (stmt_insert)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); return GNUNET_SYSERR; } FPRINTF (stdout, "%u -> %u\n", A, B); GNUNET_break (SQLITE_OK == sqlite3_reset (stmt_insert)); //GNUNET_break (SQLITE_OK == sqlite3_clear_bindings (stmt_insert)); if ( (SQLITE_OK != sqlite3_bind_int (stmt_insert, 1, B)) || (SQLITE_OK != sqlite3_bind_int (stmt_insert, 2, A)) ) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); return GNUNET_SYSERR; } if (SQLITE_DONE != sqlite3_step (stmt_insert)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_step"); return GNUNET_SYSERR; } FPRINTF (stdout, "%u -> %u\n", B, A); GNUNET_break (SQLITE_OK == sqlite3_reset (stmt_insert)); return GNUNET_OK; } /** * Open the database file, creating a new database if not existing and setup the * whitelist table * * @param dbfile the database filename * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure (error message has * to be printed) */ static int setup_db (const char *dbfile) { const char *query_create = "CREATE TABLE whitelist (" "id INTEGER," "oid INTEGER," "bandwidth INTEGER DEFAULT NULL," "latency INTEGER DEFAULT NULL," "loss INTEGER DEFAULT NULL," " UNIQUE (" " id," " oid" " ) ON CONFLICT IGNORE" ");"; const char *query_insert = "INSERT INTO whitelist(" " id," " oid," " bandwidth," " latency," " loss" ") VALUES (" " ?1," " ?2," " ?3," " ?4," " ?5);"; int ret; ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_open (dbfile, &db)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_open"); goto err_ret; } if (0 != sqlite3_exec (db, query_create, NULL, NULL, NULL)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); FPRINTF (stderr, "Error: %d. Perhaps the database `%s' already exits.\n", sqlite3_errcode (db), dbfile); goto err_ret; } GNUNET_break (0 == sqlite3_exec (db, "PRAGMA synchronous = 0;", NULL, NULL, NULL)); if (SQLITE_OK != sqlite3_prepare_v2 (db, query_insert, -1, &stmt_insert, NULL)) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); goto err_ret; } ret = GNUNET_OK; err_ret: return ret; } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { const char *dbfile; const char *topology_string; unsigned int arg_uint1; unsigned int arg_uint2; const char *arg_str1; const char *value; unsigned int argc; argc = 0; if (NULL == args) { LOG_ERROR (_("Need atleast 2 arguments\n")); return; } if (NULL == (dbfile = args[argc++])) { LOG_ERROR (_("Database filename missing\n")); return; } if (GNUNET_OK != setup_db (dbfile)) return; if (NULL == (topology_string = args[argc++])) { LOG_ERROR (_("Topology string missing\n")); return; } if (GNUNET_YES != GNUNET_TESTBED_topology_get_ (&topology, topology_string)) { LOG_ERROR (_("Invalid topology: %s\n"), topology_string); return; } /* parse for first TOPOOPT. This can either be arg_uint1 or arg_str1 */ switch (topology) { case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: if (NULL == (value = args[argc++])) { LOG_ERROR (_("An argument is missing for given topology `%s'\n"), topology_string); return; } if (-1 == SSCANF (value, "%u", &arg_uint1)) { LOG_ERROR (_("Invalid argument `%s' given as topology argument\n"), value); return; } break; case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: if (NULL == (arg_str1 = args[argc++])) { LOG_ERROR (_("Filename argument missing for topology `%s'\n"), topology_string); return; } break; default: break; } /* parse for second TOPOOPT. Only required for SCALE_FREE topology */ switch (topology) { case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: if (NULL == (value = args[argc++])) { LOG_ERROR (_("Second argument for topology `%s' is missing\n"), topology_string); return; } if (-1 == SSCANF (value, "%u", &arg_uint2)) { LOG_ERROR (_("Invalid argument `%s'; expecting unsigned int\n"), value); return; } break; default: break; } /* contruct topologies */ switch (topology) { case GNUNET_TESTBED_TOPOLOGY_LINE: case GNUNET_TESTBED_TOPOLOGY_RING: case GNUNET_TESTBED_TOPOLOGY_CLIQUE: case GNUNET_TESTBED_TOPOLOGY_2D_TORUS: GNUNET_TESTBED_underlay_construct_ (num_peers, link_processor, NULL, topology); break; case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING: case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD: GNUNET_TESTBED_underlay_construct_ (num_peers, link_processor, NULL, topology, arg_uint1); break; case GNUNET_TESTBED_TOPOLOGY_FROM_FILE: GNUNET_TESTBED_underlay_construct_ (num_peers, link_processor, NULL, topology, arg_str1); break; case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE: GNUNET_TESTBED_underlay_construct_ (num_peers, link_processor, NULL, topology, arg_uint1, arg_uint2); break; default: GNUNET_assert (0); } } /** * Main */ int main (int argc, char *const argv[]) { struct GNUNET_GETOPT_CommandLineOption option[] = { {'p', "num-peers", "COUNT", gettext_noop ("create COUNT number of peers"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers}, GNUNET_GETOPT_OPTION_END }; int ret; exit_result = GNUNET_SYSERR; ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-underlay-topology", _("Generates SQLite3 database representing a given underlay topology.\n" "Usage: gnunet-underlay-topology [OPTIONS] db-filename TOPO [TOPOOPTS]\n" "The following options are available for TOPO followed by TOPOOPTS if applicable:\n" "\t LINE\n" "\t RING\n" "\t RANDOM \n" "\t SMALL_WORLD \n" "\t SMALL_WORLD_RING \n" "\t CLIQUE\n" "\t 2D_TORUS\n" "\t SCALE_FREE \n" "\t FROM_FILE \n" "TOPOOPTS:\n" "\t num_rnd_links: The number of random links\n" "\t cap: the maximum number of links a node can have\n" "\t m: the number of links a node should have while joining the network\n" "\t filename: the path of the file which contains topology information\n" "NOTE: the format of the above file is descibed here: https://www.gnunet.org/content/topology-file-format\n"), option, &run, NULL); if (NULL != stmt_insert) sqlite3_finalize (stmt_insert); if (NULL != db) sqlite3_close (db); if ((GNUNET_OK != ret) || (GNUNET_OK != exit_result)) return 1; return 0; } gnunet-0.10.1/src/testbed/testbed_api_operations.h0000644000175000017500000001643312225777503017153 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_operations.h * @brief internal API to access the 'operations' subsystem * @author Christian Grothoff */ #ifndef NEW_TESTING_API_OPERATIONS_H #define NEW_TESTING_API_OPERATIONS_H #include "gnunet_testbed_service.h" #include "gnunet_helper_lib.h" /** * Queue of operations where we can only support a certain * number of concurrent operations of a particular type. */ struct OperationQueue; /** * The type of operation queue */ enum OperationQueueType { /** * Operation queue which permits a fixed maximum number of operations to be * active at any time */ OPERATION_QUEUE_TYPE_FIXED, /** * Operation queue which adapts the number of operations to be active based on * the operation completion times of previously executed operation in it */ OPERATION_QUEUE_TYPE_ADAPTIVE }; /** * Create an operation queue. * * @param type the type of operation queue * @param max_active maximum number of operations in this queue that can be * active in parallel at the same time. * @return handle to the queue */ struct OperationQueue * GNUNET_TESTBED_operation_queue_create_ (enum OperationQueueType type, unsigned int max_active); /** * Destroy an operation queue. The queue MUST be empty * at this time. * * @param queue queue to destroy */ void GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue); /** * Destroys the operation queue if it is empty. If not empty return GNUNET_NO. * * @param queue the queue to destroy if empty * @return GNUNET_YES if the queue is destroyed. GNUNET_NO if not (because it * is not empty) */ int GNUNET_TESTBED_operation_queue_destroy_empty_ (struct OperationQueue *queue); /** * Function to reset the maximum number of operations in the given queue. If * max_active is lesser than the number of currently active operations, the * active operations are not stopped immediately. * * @param queue the operation queue which has to be modified * @param max_active the new maximum number of active operations */ void GNUNET_TESTBED_operation_queue_reset_max_active_ (struct OperationQueue *queue, unsigned int max_active); /** * Add an operation to a queue. An operation can be in multiple queues at * once. Once the operation is inserted into all the queues * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start * waiting for the operation to become active. * * @param queue queue to add the operation to * @param op operation to add to the queue * @param nres the number of units of the resources of queue needed by the * operation. Should be greater than 0. */ void GNUNET_TESTBED_operation_queue_insert2_ (struct OperationQueue *queue, struct GNUNET_TESTBED_Operation *op, unsigned int nres); /** * Add an operation to a queue. An operation can be in multiple queues at * once. Once the operation is inserted into all the queues * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start * waiting for the operation to become active. * * @param queue queue to add the operation to * @param op operation to add to the queue */ void GNUNET_TESTBED_operation_queue_insert_ (struct OperationQueue *queue, struct GNUNET_TESTBED_Operation *op); /** * Marks the given operation as waiting on the queues. Once all queues permit * the operation to become active, the operation will be activated. The actual * activation will occur in a separate task (thus allowing multiple queue * insertions to be made without having the first one instantly trigger the * operation if the first queue has sufficient resources). * * @param op the operation to marks as waiting */ void GNUNET_TESTBED_operation_begin_wait_ (struct GNUNET_TESTBED_Operation *op); /** * Function to call to start an operation once all * queues the operation is part of declare that the * operation can be activated. * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ typedef void (*OperationStart) (void *cls); /** * Function to call to cancel an operation (release all associated * resources). This can be because of a call to * "GNUNET_TESTBED_operation_cancel" (before the operation generated * an event) or AFTER the operation generated an event due to a call * to "GNUNET_TESTBED_operation_done". Thus it is not guaranteed that * a callback to the 'OperationStart' preceeds the call to * 'OperationRelease'. Implementations of this function are expected * to clean up whatever state is in 'cls' and release all resources * associated with the operation. * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ typedef void (*OperationRelease) (void *cls); /** * Create an 'operation' to be performed. * * @param cls closure for the callbacks * @param start function to call to start the operation * @param release function to call to close down the operation * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_operation_create_ (void *cls, OperationStart start, OperationRelease release); /** * An operation is 'done' (was cancelled or finished); remove * it from the queues and release associated resources. * * @param op operation that finished */ void GNUNET_TESTBED_operation_release_ (struct GNUNET_TESTBED_Operation *op); /** * Marks an active operation as inactive - the operation will be kept in a * ready-to-be-released state and continues to hold resources until another * operation contents for them. * * @param op the operation to be marked as inactive. The operation start * callback should have been called before for this operation to mark * it as inactive. */ void GNUNET_TESTBED_operation_inactivate_ (struct GNUNET_TESTBED_Operation *op); /** * Marks and inactive operation as active. This fuction should be called to * ensure that the oprelease callback will not be called until it is either * marked as inactive or released. * * @param op the operation to be marked as active */ void GNUNET_TESTBED_operation_activate_ (struct GNUNET_TESTBED_Operation *op); /** * Marks an operation as failed * * @param op the operation to be marked as failed */ void GNUNET_TESTBED_operation_mark_failed (struct GNUNET_TESTBED_Operation *op); #endif /* end of testbed_api_operations.h */ gnunet-0.10.1/src/testbed/gnunet-service-testbed_links.c0000644000175000017500000011073612255010512020166 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_links.c * @brief TESTBED service components that deals with starting slave controllers * and establishing lateral links between controllers * @author Sree Harsha Totakura */ #include "gnunet-service-testbed.h" /** * Redefine LOG with a changed log component string */ #ifdef LOG #undef LOG #endif #define LOG(kind,...) \ GNUNET_log_from (kind, "testbed-links", __VA_ARGS__) /** * The event mask for the events we listen from sub-controllers */ #define EVENT_MASK (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED) /** * States of LCFContext */ enum LCFContextState { /** * The Context has been initialized; Nothing has been done on it */ INIT, /** * Delegated host has been registered at the forwarding controller */ DELEGATED_HOST_REGISTERED, /** * The slave host has been registred at the forwarding controller */ SLAVE_HOST_REGISTERED, /** * The context has been finished (may have error) */ FINISHED }; /** * Link controllers request forwarding context */ struct LCFContext { /** * The gateway which will pass the link message to delegated host */ struct Slave *gateway; /** * The client which has asked to perform this operation */ struct GNUNET_SERVER_Client *client; /** * Handle for operations which are forwarded while linking controllers */ struct GNUNET_TESTBED_Operation *op; /** * The timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * The id of the operation which created this context */ uint64_t operation_id; /** * should the slave controller start the delegated controller? */ int is_subordinate; /** * The state of this context */ enum LCFContextState state; /** * The delegated host */ uint32_t delegated_host_id; /** * The slave host */ uint32_t slave_host_id; }; /** * Structure of a queue entry in LCFContext request queue */ struct LCFContextQueue { /** * The LCFContext */ struct LCFContext *lcf; /** * Head prt for DLL */ struct LCFContextQueue *next; /** * Tail ptr for DLL */ struct LCFContextQueue *prev; }; /** * Notification context to be used to notify when connection to the neighbour's * controller is opened */ struct NeighbourConnectNotification { /** * DLL next for inclusion in neighbour's list of notification requests */ struct NeighbourConnectNotification *next; /** * DLL prev */ struct NeighbourConnectNotification *prev; /** * The neighbour */ struct Neighbour *n; /** * The notification callback to call when we are connect to neighbour */ GST_NeigbourConnectNotifyCallback cb; /** * The closure for the above callback */ void *cb_cls; }; /** * A connected controller which is not our child */ struct Neighbour { /** * The controller handle */ struct GNUNET_TESTBED_Controller *controller; /** * Operation handle for opening a lateral connection to another controller. * Will be NULL if the slave controller is started by this controller */ struct GNUNET_TESTBED_Operation *conn_op; /** * DLL head for the list of notification requests */ struct NeighbourConnectNotification *nl_head; /** * DLL tail for the list of notification requests */ struct NeighbourConnectNotification *nl_tail; /** * Task id for the task to call notifications from the notification list */ GNUNET_SCHEDULER_TaskIdentifier notify_task; /** * How many references are present currently to this neighbour's connection */ unsigned int reference_cnt; /** * Is the conn_op inactivated? */ unsigned int inactive; /** * The id of the host this controller is running on */ uint32_t host_id; }; /** * The neighbour list */ static struct Neighbour **neighbour_list; /** * The size of the neighbour list */ static unsigned int neighbour_list_size; /** * Context information for establishing a link to neighbour (Used is * GST_handle_link_controllers() */ struct NeighbourConnectCtxt { /** * DLL next for inclusion in the corresponding context list */ struct NeighbourConnectCtxt *next; /** * DLL tail */ struct NeighbourConnectCtxt *prev; /** * The neighbour to whom connection should be made */ struct Neighbour *n; /** * The client requesting the connection */ struct GNUNET_SERVER_Client *client; /** * Task to be run upon timeout */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * The notification handle associated with the neighbour's connection request */ struct NeighbourConnectNotification *nh; /** * The id of the link-controllers operation responsible for creating this * context */ uint64_t op_id; }; /** * DLL head for the list of neighbour connect contexts */ struct NeighbourConnectCtxt *ncc_head; /** * DLL tail for the list of neighbour connect contexts */ struct NeighbourConnectCtxt *ncc_tail; /** * A list of directly linked neighbours */ struct Slave **GST_slave_list; /** * The size of directly linked neighbours list */ unsigned int GST_slave_list_size; /** * A list of routes */ static struct Route **route_list; /** * The head for the LCF queue */ static struct LCFContextQueue *lcfq_head; /** * The tail for the LCF queue */ static struct LCFContextQueue *lcfq_tail; /** * The lcf_task handle */ static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id; /** * The size of the route list */ static unsigned int route_list_size; /** * Adds a slave to the slave array * * @param slave the slave controller to add */ static void slave_list_add (struct Slave *slave) { if (slave->host_id >= GST_slave_list_size) GST_array_grow_large_enough (GST_slave_list, GST_slave_list_size, slave->host_id); GNUNET_assert (NULL == GST_slave_list[slave->host_id]); GST_slave_list[slave->host_id] = slave; } /** * Adds a route to the route list * * @param route the route to add */ static void route_list_add (struct Route *route) { if (route->dest >= route_list_size) GST_array_grow_large_enough (route_list, route_list_size, route->dest); GNUNET_assert (NULL == route_list[route->dest]); route_list[route->dest] = route; } /** * Add a neighbour to the neighbour list. Grows the neighbour list * automatically. * * @param n the neighbour to add */ static void neighbour_list_add (struct Neighbour *n) { if (n->host_id >= neighbour_list_size) GST_array_grow_large_enough (neighbour_list, neighbour_list_size, n->host_id); GNUNET_assert (NULL == neighbour_list[n->host_id]); neighbour_list[n->host_id] = n; } /** * Cleans up the route list */ void GST_route_list_clear () { unsigned int id; for (id = 0; id < route_list_size; id++) if (NULL != route_list[id]) GNUNET_free (route_list[id]); GNUNET_free_non_null (route_list); route_list = NULL; } /** * Iterator for freeing hash map entries in a slave's reghost_map * * @param cls handle to the slave * @param key current key code * @param value value in the hash map * @return GNUNET_YES if we should continue to * iterate, * GNUNET_NO if not. */ static int reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct Slave *slave = cls; struct RegisteredHostContext *rhc = value; struct ForwardedOverlayConnectContext *focc; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key, value)); while (NULL != (focc = rhc->focc_dll_head)) { GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc); GST_cleanup_focc (focc); } GNUNET_free (value); return GNUNET_YES; } /** * Kill a #Slave object * * @param slave the #Slave object */ static void kill_slave (struct Slave *slave) { struct HostRegistration *hr_entry; while (NULL != (hr_entry = slave->hr_dll_head)) { GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail, hr_entry); GNUNET_free (hr_entry); } if (NULL != slave->rhandle) GNUNET_TESTBED_cancel_registration (slave->rhandle); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map, reghost_free_iterator, slave)); GNUNET_CONTAINER_multihashmap_destroy (slave->reghost_map); if (NULL != slave->controller) GNUNET_TESTBED_controller_disconnect (slave->controller); if (NULL != slave->controller_proc) { LOG_DEBUG ("Stopping a slave\n"); GNUNET_TESTBED_controller_kill_ (slave->controller_proc); } } /** * Destroy a #Slave object * * @param slave the #Slave object */ static void destroy_slave (struct Slave *slave) { if (NULL != slave->controller_proc) { GNUNET_TESTBED_controller_destroy_ (slave->controller_proc); LOG_DEBUG ("Slave stopped\n"); } GST_slave_list[slave->host_id] = NULL; GNUNET_free (slave); } /** * Cleans up the slave list */ void GST_slave_list_clear () { struct Slave *slave; unsigned int id; for (id = 0; id < GST_slave_list_size; id++) { slave = GST_slave_list[id]; if (NULL == slave) continue; kill_slave (slave); } for (id = 0; id < GST_slave_list_size; id++) { slave = GST_slave_list[id]; if (NULL == slave) continue; destroy_slave (slave); } GNUNET_free_non_null (GST_slave_list); GST_slave_list = NULL; } /** * Finds the route with directly connected host as destination through which * the destination host can be reached * * @param host_id the id of the destination host * @return the route with directly connected destination host; NULL if no route * is found */ struct Route * GST_find_dest_route (uint32_t host_id) { struct Route *route; if (route_list_size <= host_id) return NULL; while (NULL != (route = route_list[host_id])) { if (route->thru == GST_context->host_id) break; host_id = route->thru; } return route; } /** * Function to send a failure reponse for controller link operation * * @param client the client to send the message to * @param operation_id the operation ID of the controller link request * @param cfg the configuration with which the delegated controller is started. * Can be NULL if the delegated controller is not started but just * linked to. * @param emsg set to an error message explaining why the controller link * failed. Setting this to NULL signifies success. !This should be * NULL if cfg is set! */ static void send_controller_link_response (struct GNUNET_SERVER_Client *client, uint64_t operation_id, const struct GNUNET_CONFIGURATION_Handle *cfg, const char *emsg) { struct GNUNET_TESTBED_ControllerLinkResponse *msg; char *xconfig; size_t config_size; size_t xconfig_size; uint16_t msize; GNUNET_assert ((NULL == cfg) || (NULL == emsg)); xconfig = NULL; xconfig_size = 0; config_size = 0; msize = sizeof (struct GNUNET_TESTBED_ControllerLinkResponse); if (NULL != cfg) { xconfig = GNUNET_TESTBED_compress_cfg_ (cfg, &config_size, &xconfig_size); msize += xconfig_size; } if (NULL != emsg) msize += strlen (emsg); msg = GNUNET_malloc (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT); msg->header.size = htons (msize); if (NULL == emsg) msg->success = htons (GNUNET_YES); msg->operation_id = GNUNET_htonll (operation_id); msg->config_size = htons ((uint16_t) config_size); if (NULL != xconfig) { memcpy (&msg[1], xconfig, xconfig_size); GNUNET_free (xconfig); } if (NULL != emsg) memcpy (&msg[1], emsg, strlen (emsg)); GST_queue_message (client, &msg->header); } /** * The Link Controller forwarding task * * @param cls the LCFContext * @param tc the Task context from scheduler */ static void lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Completion callback for host registrations while forwarding Link Controller messages * * @param cls the LCFContext * @param emsg the error message; NULL if host registration is successful */ static void lcf_proc_cc (void *cls, const char *emsg) { struct LCFContext *lcf = cls; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); switch (lcf->state) { case INIT: if (NULL != emsg) goto registration_error; lcf->state = DELEGATED_HOST_REGISTERED; lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); break; case DELEGATED_HOST_REGISTERED: if (NULL != emsg) goto registration_error; lcf->state = SLAVE_HOST_REGISTERED; lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); break; default: GNUNET_assert (0); /* Shouldn't reach here */ } return; registration_error: LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n", emsg); lcf->state = FINISHED; lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); } /** * The Link Controller forwarding task * * @param cls the LCFContext * @param tc the Task context from scheduler */ static void lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Task to free resources when forwarded link controllers has been timedout * * @param cls the LCFContext * @param tc the task context from scheduler */ static void lcf_forwarded_operation_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct LCFContext *lcf = cls; lcf->timeout_task = GNUNET_SCHEDULER_NO_TASK; // GST_forwarded_operation_timeout (lcf->fopc, tc); LOG (GNUNET_ERROR_TYPE_WARNING, "A forwarded controller link operation has timed out\n"); send_controller_link_response (lcf->client, lcf->operation_id, NULL, "A forwarded controller link operation has " "timed out\n"); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); } /** * The Link Controller forwarding task * * @param cls the LCFContext * @param tc the Task context from scheduler */ static void lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct LCFContext *lcf = cls; struct LCFContextQueue *lcfq; lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK; switch (lcf->state) { case INIT: if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (GST_host_list [lcf->delegated_host_id], lcf->gateway->controller)) { GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf, GST_host_list[lcf->delegated_host_id]); } else { lcf->state = DELEGATED_HOST_REGISTERED; lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); } break; case DELEGATED_HOST_REGISTERED: if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (GST_host_list[lcf->slave_host_id], lcf->gateway->controller)) { GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf, GST_host_list[lcf->slave_host_id]); } else { lcf->state = SLAVE_HOST_REGISTERED; lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); } break; case SLAVE_HOST_REGISTERED: lcf->op = GNUNET_TESTBED_controller_link (lcf, lcf->gateway->controller, GST_host_list[lcf->delegated_host_id], GST_host_list[lcf->slave_host_id], lcf->is_subordinate); lcf->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &lcf_forwarded_operation_timeout, lcf); lcf->state = FINISHED; break; case FINISHED: lcfq = lcfq_head; GNUNET_assert (lcfq->lcf == lcf); GNUNET_SERVER_client_drop (lcf->client); if (NULL != lcf->op) GNUNET_TESTBED_operation_done (lcf->op); GNUNET_free (lcf); GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq); GNUNET_free (lcfq); if (NULL != lcfq_head) lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf); } } /** * Callback for event from slave controllers * * @param cls NULL * @param event information about the event */ static void slave_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { struct LCFContext *lcf; /* We currently only get here when working on LCFContexts */ GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type); lcf = event->op_cls; GNUNET_assert (lcf->op == event->op); GNUNET_TESTBED_operation_done (lcf->op); lcf->op = NULL; GNUNET_assert (FINISHED == lcf->state); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != lcf->timeout_task); GNUNET_SCHEDULER_cancel (lcf->timeout_task); if (NULL == event->details.operation_finished.emsg) send_controller_link_response (lcf->client, lcf->operation_id, GNUNET_TESTBED_host_get_cfg_ (GST_host_list[lcf->delegated_host_id]), NULL); else send_controller_link_response (lcf->client, lcf->operation_id, NULL, event->details.operation_finished.emsg); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf); return; } /** * Callback to signal successfull startup of the controller process * * @param cls the handle to the slave whose status is to be found here * @param cfg the configuration with which the controller has been started; * NULL if status is not GNUNET_OK * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ static void slave_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, int status) { struct Slave *slave = cls; struct LinkControllersContext *lcc; lcc = slave->lcc; if (GNUNET_SYSERR == status) { slave->controller_proc = NULL; /* Stop all link controller forwarding tasks since we shutdown here anyway and as these tasks they depend on the operation queues which are created through GNUNET_TESTBED_controller_connect() and in kill_slave() we call the destructor function GNUNET_TESTBED_controller_disconnect() */ GST_free_lcfq (); kill_slave (slave); destroy_slave (slave); slave = NULL; LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n"); GNUNET_SCHEDULER_shutdown (); /* We too shutdown */ goto clean_lcc; } slave->controller = GNUNET_TESTBED_controller_connect (GST_host_list[slave->host_id], EVENT_MASK, &slave_event_cb, slave); if (NULL != slave->controller) { send_controller_link_response (lcc->client, lcc->operation_id, cfg, NULL); } else { send_controller_link_response (lcc->client, lcc->operation_id, NULL, "Could not connect to delegated controller"); kill_slave (slave); destroy_slave (slave); slave = NULL; } clean_lcc: if (NULL != lcc) { if (NULL != lcc->client) { GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK); GNUNET_SERVER_client_drop (lcc->client); lcc->client = NULL; } GNUNET_free (lcc); } if (NULL != slave) slave->lcc = NULL; } /** * Trigger notification task if there are notification requests currently * waiting in the given neighbour. Also activates the neighbour connect operation * if it was previously inactivated so that the connection to the neighbour can * be re-used * * @param n the neighbour */ static void trigger_notifications (struct Neighbour *n); /** * Task to call the notification queued in the notifications list of the given * neighbour * * @param cls the neighbour * @param tc scheduler task context */ static void neighbour_connect_notify_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Neighbour *n = cls; struct NeighbourConnectNotification *h; GNUNET_assert (NULL != (h = n->nl_head)); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->notify_task); n->notify_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (NULL != n->controller); GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h); trigger_notifications (n); h->cb (h->cb_cls, n->controller); GNUNET_free (h); } /** * Trigger notification task if there are notification requests currently * waiting in the given neighbour. Also activates the neighbour connect operation * if it was previously inactivated so that the connection to the neighbour can * be re-used * * @param n the neighbour */ static void trigger_notifications (struct Neighbour *n) { GNUNET_assert (NULL != n->conn_op); if (NULL == n->nl_head) return; if (NULL == n->controller) return; if (GNUNET_SCHEDULER_NO_TASK != n->notify_task) return; if (1 == n->inactive) { GNUNET_assert (0 == n->reference_cnt); GNUNET_TESTBED_operation_activate_ (n->conn_op); n->inactive = 0; } n->reference_cnt++; n->notify_task = GNUNET_SCHEDULER_add_now (&neighbour_connect_notify_task, n); } /** * Callback to be called when the neighbour connect operation is started. The * connection to the neigbour is opened here and any pending notifications are * trigger. * * @param cls the neighbour */ static void opstart_neighbour_conn (void *cls) { struct Neighbour *n = cls; GNUNET_assert (NULL != n->conn_op); GNUNET_assert (NULL == n->controller); LOG_DEBUG ("Opening connection to controller on host %u\n", n->host_id); n->controller = GNUNET_TESTBED_controller_connect (GST_host_list[n->host_id], EVENT_MASK, &slave_event_cb, NULL); trigger_notifications (n); } /** * Callback to be called when the neighbour connect operation is released * * @param cls the neighbour */ static void oprelease_neighbour_conn (void *cls) { struct Neighbour *n = cls; GNUNET_assert (0 == n->reference_cnt); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == n->notify_task); GNUNET_assert (NULL == n->nl_head); if (NULL != n->controller) { LOG_DEBUG ("Closing connection to controller on host %u\n", n->host_id); GNUNET_TESTBED_controller_disconnect (n->controller); n->controller = NULL; } n->conn_op = NULL; n->inactive = 0; } /** * Try to open a connection to the given neigbour. If the connection is open * already, then it is re-used. If not, the request is queued in the operation * queues responsible for bounding the total number of file descriptors. The * actual connection will happen when the operation queue marks the * corresponding operation as active. * * @param n the neighbour to open a connection to * @param cb the notification callback to call when the connection is opened * @param cb_cls the closure for the above callback */ struct NeighbourConnectNotification * GST_neighbour_get_connection (struct Neighbour *n, GST_NeigbourConnectNotifyCallback cb, void *cb_cls) { struct NeighbourConnectNotification *h; GNUNET_assert (NULL != cb); LOG_DEBUG ("Attempting to get connection to controller on host %u\n", n->host_id); h = GNUNET_new (struct NeighbourConnectNotification); h->n = n; h->cb = cb; h->cb_cls = cb_cls; GNUNET_CONTAINER_DLL_insert_tail (n->nl_head, n->nl_tail, h); if (NULL == n->conn_op) { GNUNET_assert (NULL == n->controller); n->conn_op = GNUNET_TESTBED_operation_create_ (n, &opstart_neighbour_conn, &oprelease_neighbour_conn); GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, n->conn_op); GNUNET_TESTBED_operation_begin_wait_ (n->conn_op); return h; } trigger_notifications (n); return h; } /** * Cancel the request for opening a connection to the neighbour * * @param h the notification handle */ void GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h) { struct Neighbour *n; int cleanup_task; n = h->n; cleanup_task = (h == n->nl_head) ? GNUNET_YES : GNUNET_NO; GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h); GNUNET_free (h); if (GNUNET_NO == cleanup_task) return; if (GNUNET_SCHEDULER_NO_TASK == n->notify_task) return; GNUNET_assert (0 < n->reference_cnt); n->reference_cnt--; GNUNET_SCHEDULER_cancel (n->notify_task); n->notify_task = GNUNET_SCHEDULER_NO_TASK; if (NULL == n->nl_head) { if ( (0 == n->reference_cnt) && (0 == n->inactive) ) { n->inactive = 1; GNUNET_TESTBED_operation_inactivate_ (n->conn_op); } return; } trigger_notifications (n); } /** * Release the connection to the neighbour. The actual connection will be * closed if connections to other neighbour are waiting (to maintain a bound on * the total number of connections that are open). * * @param n the neighbour whose connection can be closed */ void GST_neighbour_release_connection (struct Neighbour *n) { GNUNET_assert (0 == n->inactive); GNUNET_assert (0 < n->reference_cnt); n->reference_cnt--; if (0 == n->reference_cnt) { n->inactive = 1; GNUNET_TESTBED_operation_inactivate_ (n->conn_op); } } /** * Cleanup neighbour connect contexts * * @param ncc the neighbour connect context to cleanup */ static void cleanup_ncc (struct NeighbourConnectCtxt *ncc) { if (NULL != ncc->nh) GST_neighbour_get_connection_cancel (ncc->nh); if (GNUNET_SCHEDULER_NO_TASK != ncc->timeout_task) GNUNET_SCHEDULER_cancel (ncc->timeout_task); GNUNET_SERVER_client_drop (ncc->client); GNUNET_CONTAINER_DLL_remove (ncc_head, ncc_tail, ncc); GNUNET_free (ncc); } /** * Cleans up the neighbour list */ void GST_neighbour_list_clean() { struct Neighbour *n; unsigned int id; for (id = 0; id < neighbour_list_size; id++) { if (NULL == (n = neighbour_list[id])) continue; if (NULL != n->conn_op) GNUNET_TESTBED_operation_release_ (n->conn_op); GNUNET_free (n); neighbour_list[id] = NULL; } GNUNET_free_non_null (neighbour_list); } /** * Get a neighbour from the neighbour list * * @param id the index of the neighbour in the neighbour list * @return the Neighbour; NULL if the given index in invalid (index greater than * the list size or neighbour at that index is NULL) */ struct Neighbour * GST_get_neighbour (uint32_t id) { if (neighbour_list_size <= id) return NULL; else return neighbour_list[id]; } /** * Function to cleanup the neighbour connect contexts */ void GST_free_nccq () { while (NULL != ncc_head) cleanup_ncc (ncc_head); } /** * Task to be run upon timeout while attempting to connect to the neighbour * * @param cls the NeighbourConnectCtxt created in GST_handle_link_controllers() * @param tc the scheduler task context */ static void timeout_neighbour_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct NeighbourConnectCtxt *ncc = cls; ncc->timeout_task = GNUNET_SCHEDULER_NO_TASK; send_controller_link_response (ncc->client, ncc->op_id, NULL, "Could not connect to delegated controller"); cleanup_ncc (ncc); } /** * Callback called when a connection to the neighbour is made * * @param cls the NeighbourConnectCtxt created in GST_handle_link_controllers() * @param c the handle the neighbour's controller */ static void neighbour_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c) { struct NeighbourConnectCtxt *ncc = cls; GNUNET_SCHEDULER_cancel (ncc->timeout_task); ncc->timeout_task = GNUNET_SCHEDULER_NO_TASK; ncc->nh = NULL; GST_neighbour_release_connection (ncc->n); send_controller_link_response (ncc->client, ncc->op_id, NULL, NULL); cleanup_ncc (ncc); } /** * Function to create a neigbour and add it into the neighbour list * * @param host the host of the neighbour */ struct Neighbour * GST_create_neighbour (struct GNUNET_TESTBED_Host *host) { struct Neighbour *n; n = GNUNET_new (struct Neighbour); n->host_id = GNUNET_TESTBED_host_get_id_ (host); neighbour_list_add (n); /* just add; connect on-demand */ return n; } /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_ControllerLinkRequest *msg; struct LCFContextQueue *lcfq; struct Route *route; struct Route *new_route; uint64_t op_id; uint32_t delegated_host_id; uint32_t slave_host_id; if (NULL == GST_context) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) message; delegated_host_id = ntohl (msg->delegated_host_id); if (delegated_host_id == GST_context->host_id) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n"); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if ((delegated_host_id >= GST_host_list_size) || (NULL == GST_host_list[delegated_host_id])) { LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host %u not registered with us\n", delegated_host_id); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } slave_host_id = ntohl (msg->slave_host_id); if ((slave_host_id >= GST_host_list_size) || (NULL == GST_host_list[slave_host_id])) { LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n", slave_host_id); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (slave_host_id == delegated_host_id) { LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n"); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } op_id = GNUNET_ntohll (msg->operation_id); if (slave_host_id == GST_context->host_id) /* Link from us */ { struct Slave *slave; struct LinkControllersContext *lcc; if (1 != msg->is_subordinate) { struct Neighbour *n; struct NeighbourConnectCtxt *ncc; if ((delegated_host_id < neighbour_list_size) && (NULL != neighbour_list[delegated_host_id])) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG_DEBUG ("Received request to establish a link to host %u\n", delegated_host_id); n = GST_create_neighbour (GST_host_list[delegated_host_id]); ncc = GNUNET_new (struct NeighbourConnectCtxt); ncc->n = n; ncc->op_id = op_id; ncc->client = client; GNUNET_SERVER_client_keep (client); ncc->nh = GST_neighbour_get_connection (n, neighbour_connect_cb, ncc); ncc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_neighbour_connect, ncc); GNUNET_CONTAINER_DLL_insert_tail (ncc_head, ncc_tail, ncc); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if ((delegated_host_id < GST_slave_list_size) && (NULL != GST_slave_list[delegated_host_id])) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG_DEBUG ("Received request to start and establish a link to host %u\n", delegated_host_id); slave = GNUNET_new (struct Slave); slave->host_id = delegated_host_id; slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO); slave_list_add (slave); lcc = GNUNET_new (struct LinkControllersContext); lcc->operation_id = op_id; GNUNET_SERVER_client_keep (client); lcc->client = client; slave->lcc = lcc; slave->controller_proc = GNUNET_TESTBED_controller_start (GST_context->master_ip, GST_host_list[slave->host_id], &slave_status_cb, slave); new_route = GNUNET_new (struct Route); new_route->dest = delegated_host_id; new_route->thru = GST_context->host_id; route_list_add (new_route); return; } /* Route the request */ if (slave_host_id >= route_list_size) { LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host"); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } lcfq = GNUNET_new (struct LCFContextQueue); lcfq->lcf = GNUNET_new (struct LCFContext); lcfq->lcf->delegated_host_id = delegated_host_id; lcfq->lcf->slave_host_id = slave_host_id; route = GST_find_dest_route (slave_host_id); GNUNET_assert (NULL != route); /* because we add routes carefully */ GNUNET_assert (route->dest < GST_slave_list_size); GNUNET_assert (NULL != GST_slave_list[route->dest]); lcfq->lcf->is_subordinate = msg->is_subordinate; lcfq->lcf->state = INIT; lcfq->lcf->operation_id = op_id; lcfq->lcf->gateway = GST_slave_list[route->dest]; GNUNET_SERVER_client_keep (client); lcfq->lcf->client = client; if (NULL == lcfq_head) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq); lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf); } else GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq); /* FIXME: Adding a new route should happen after the controllers are linked * successfully */ if (1 != msg->is_subordinate) { GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if ((delegated_host_id < route_list_size) && (NULL != route_list[delegated_host_id])) { GNUNET_break_op (0); /* Are you trying to link delegated host twice * with is subordinate flag set to GNUNET_YES? */ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } new_route = GNUNET_new (struct Route); new_route->dest = delegated_host_id; new_route->thru = route->dest; route_list_add (new_route); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Cleans up the queue used for forwarding link controllers requests */ void GST_free_lcfq () { struct LCFContextQueue *lcfq; struct LCFContext *lcf; if (NULL != lcfq_head) { if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id) { GNUNET_SCHEDULER_cancel (lcf_proc_task_id); lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK; } } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id); for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head) { lcf = lcfq->lcf; GNUNET_SERVER_client_drop (lcf->client); if (NULL != lcf->op) GNUNET_TESTBED_operation_done (lcf->op); if (GNUNET_SCHEDULER_NO_TASK != lcf->timeout_task) GNUNET_SCHEDULER_cancel (lcf->timeout_task); GNUNET_free (lcf); GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq); GNUNET_free (lcfq); } } gnunet-0.10.1/src/testbed/gnunet-service-testbed_meminfo.c0000644000175000017500000002246612225777502020522 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" /* * File for parsing top-level /proc entities. * Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com * Copyright 1998-2003 Albert Cahalan * June 2003, Fabian Frederick, disk and slab info * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define BAD_OPEN_MESSAGE \ "Error: /proc must be mounted\n" \ " To mount /proc at boot you need an /etc/fstab line like:\n" \ " proc /proc proc defaults\n" \ " In the meantime, run \"mount proc /proc -t proc\"\n" #define STAT_FILE "/proc/stat" //static int stat_fd = -1; #define UPTIME_FILE "/proc/uptime" //static int uptime_fd = -1; #define LOADAVG_FILE "/proc/loadavg" //static int loadavg_fd = -1; #define MEMINFO_FILE "/proc/meminfo" static int meminfo_fd = -1; #define VMINFO_FILE "/proc/vmstat" //static int vminfo_fd = -1; // As of 2.6.24 /proc/meminfo seems to need 888 on 64-bit, // and would need 1258 if the obsolete fields were there. static char buf[2048]; /* This macro opens filename only if necessary and seeks to 0 so * that successive calls to the functions are more efficient. * It also reads the current contents of the file into the global buf. */ #define FILE_TO_BUF(filename, fd) do{ \ static int local_n; \ if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) { \ fputs(BAD_OPEN_MESSAGE, stderr); \ fflush(NULL); \ _exit(102); \ } \ lseek(fd, 0L, SEEK_SET); \ if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \ perror(filename); \ fflush(NULL); \ _exit(103); \ } \ buf[local_n] = '\0'; \ }while(0) /***********************************************************************/ /* * Copyright 1999 by Albert Cahalan; all rights reserved. * This file may be used subject to the terms and conditions of the * GNU Library General Public License Version 2, or any later version * at your option, as published by the Free Software Foundation. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. */ typedef struct mem_table_struct { const char *name; /* memory type name */ unsigned long *slot; /* slot in return struct */ } mem_table_struct; static int compare_mem_table_structs(const void *a, const void *b){ return strcmp(((const mem_table_struct*)a)->name,((const mem_table_struct*)b)->name); } /* example data, following junk, with comments added: * * MemTotal: 61768 kB old * MemFree: 1436 kB old * MemShared: 0 kB old (now always zero; not calculated) * Buffers: 1312 kB old * Cached: 20932 kB old * Active: 12464 kB new * Inact_dirty: 7772 kB new * Inact_clean: 2008 kB new * Inact_target: 0 kB new * Inact_laundry: 0 kB new, and might be missing too * HighTotal: 0 kB * HighFree: 0 kB * LowTotal: 61768 kB * LowFree: 1436 kB * SwapTotal: 122580 kB old * SwapFree: 60352 kB old * Inactive: 20420 kB 2.5.41+ * Dirty: 0 kB 2.5.41+ * Writeback: 0 kB 2.5.41+ * Mapped: 9792 kB 2.5.41+ * Slab: 4564 kB 2.5.41+ * Committed_AS: 8440 kB 2.5.41+ * PageTables: 304 kB 2.5.41+ * ReverseMaps: 5738 2.5.41+ * SwapCached: 0 kB 2.5.??+ * HugePages_Total: 220 2.5.??+ * HugePages_Free: 138 2.5.??+ * Hugepagesize: 4096 kB 2.5.??+ */ /* obsolete */ unsigned long kb_main_shared; /* old but still kicking -- the important stuff */ unsigned long kb_main_buffers; unsigned long kb_main_cached; unsigned long kb_main_free; unsigned long kb_main_total; unsigned long kb_swap_free; unsigned long kb_swap_total; /* recently introduced */ unsigned long kb_high_free; unsigned long kb_high_total; unsigned long kb_low_free; unsigned long kb_low_total; /* 2.4.xx era */ unsigned long kb_active; unsigned long kb_inact_laundry; unsigned long kb_inact_dirty; unsigned long kb_inact_clean; unsigned long kb_inact_target; unsigned long kb_swap_cached; /* late 2.4 and 2.6+ only */ /* derived values */ unsigned long kb_swap_used; unsigned long kb_main_used; /* 2.5.41+ */ unsigned long kb_writeback; unsigned long kb_slab; unsigned long nr_reversemaps; unsigned long kb_committed_as; unsigned long kb_dirty; unsigned long kb_inactive; unsigned long kb_mapped; unsigned long kb_pagetables; // seen on a 2.6.x kernel: static unsigned long kb_vmalloc_chunk; static unsigned long kb_vmalloc_total; static unsigned long kb_vmalloc_used; // seen on 2.6.24-rc6-git12 static unsigned long kb_anon_pages; static unsigned long kb_bounce; static unsigned long kb_commit_limit; static unsigned long kb_nfs_unstable; static unsigned long kb_swap_reclaimable; static unsigned long kb_swap_unreclaimable; void meminfo(void){ char namebuf[16]; /* big enough to hold any row name */ mem_table_struct findme = { namebuf, NULL}; mem_table_struct *found; char *head; char *tail; static const mem_table_struct mem_table[] = { {"Active", &kb_active}, // important {"AnonPages", &kb_anon_pages}, {"Bounce", &kb_bounce}, {"Buffers", &kb_main_buffers}, // important {"Cached", &kb_main_cached}, // important {"CommitLimit", &kb_commit_limit}, {"Committed_AS", &kb_committed_as}, {"Dirty", &kb_dirty}, // kB version of vmstat nr_dirty {"HighFree", &kb_high_free}, {"HighTotal", &kb_high_total}, {"Inact_clean", &kb_inact_clean}, {"Inact_dirty", &kb_inact_dirty}, {"Inact_laundry",&kb_inact_laundry}, {"Inact_target", &kb_inact_target}, {"Inactive", &kb_inactive}, // important {"LowFree", &kb_low_free}, {"LowTotal", &kb_low_total}, {"Mapped", &kb_mapped}, // kB version of vmstat nr_mapped {"MemFree", &kb_main_free}, // important {"MemShared", &kb_main_shared}, // important, but now gone! {"MemTotal", &kb_main_total}, // important {"NFS_Unstable", &kb_nfs_unstable}, {"PageTables", &kb_pagetables}, // kB version of vmstat nr_page_table_pages {"ReverseMaps", &nr_reversemaps}, // same as vmstat nr_page_table_pages {"SReclaimable", &kb_swap_reclaimable}, // "swap reclaimable" (dentry and inode structures) {"SUnreclaim", &kb_swap_unreclaimable}, {"Slab", &kb_slab}, // kB version of vmstat nr_slab {"SwapCached", &kb_swap_cached}, {"SwapFree", &kb_swap_free}, // important {"SwapTotal", &kb_swap_total}, // important {"VmallocChunk", &kb_vmalloc_chunk}, {"VmallocTotal", &kb_vmalloc_total}, {"VmallocUsed", &kb_vmalloc_used}, {"Writeback", &kb_writeback}, // kB version of vmstat nr_writeback }; const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct); FILE_TO_BUF(MEMINFO_FILE,meminfo_fd); kb_inactive = ~0UL; head = buf; for(;;){ tail = strchr(head, ':'); if(!tail) break; *tail = '\0'; if(strlen(head) >= sizeof(namebuf)){ head = tail+1; goto nextline; } strcpy(namebuf,head); found = bsearch(&findme, mem_table, mem_table_count, sizeof(mem_table_struct), compare_mem_table_structs ); head = tail+1; if(!found) goto nextline; *(found->slot) = (unsigned long)strtoull(head,&tail,10); nextline: tail = strchr(head, '\n'); if(!tail) break; head = tail+1; } if(!kb_low_total){ /* low==main except with large-memory support */ kb_low_total = kb_main_total; kb_low_free = kb_main_free; } if(kb_inactive==~0UL){ kb_inactive = kb_inact_dirty + kb_inact_clean + kb_inact_laundry; } kb_swap_used = kb_swap_total - kb_swap_free; kb_main_used = kb_main_total - kb_main_free; } gnunet-0.10.1/src/testbed/testbed_api_statistics.c0000644000175000017500000003076412255010512017137 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_statistics.c * @brief high-level statistics function * @author Christian Grothoff * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "testbed_api_operations.h" /** * Generic logging shorthand */ #define LOG(kind,...) \ GNUNET_log_from (kind, "testbed-api-statistics", __VA_ARGS__) /** * Debug logging shorthand */ #define LOG_DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * Context information for use in GNUNET_TESTBED_get_statistics() */ struct GetStatsContext { /** * The main operation we generate while creating this context */ struct GNUNET_TESTBED_Operation *main_op; /** * The service connect operations we create to open connection to the * statistics service of each given peer */ struct GNUNET_TESTBED_Operation **ops; /** * The array of peers whose statistics services are to be accessed */ struct GNUNET_TESTBED_Peer **peers; /** * The subsystem of peers for which statistics are requested */ char *subsystem; /** * The particular statistics value of interest */ char *name; /** * The iterator to call with statistics information */ GNUNET_TESTBED_StatisticsIterator proc; /** * The callback to call when we are done iterating through all peers' * statistics services */ GNUNET_TESTBED_OperationCompletionCallback cont; /** * The closure for the above callbacks */ void *cb_cls; /** * The task for calling the continuation callback */ GNUNET_SCHEDULER_TaskIdentifier call_completion_task_id; /** * The number of peers present in the peers array. This number also * represents the number of service connect operations in the ops array */ unsigned int num_peers; /** * How many peers' statistics have we iterated through */ unsigned int num_completed; }; /** * Context information with respect to a particular peer */ struct PeerGetStatsContext { /** * The GetStatsContext which is associated with this context */ struct GetStatsContext *sc; /** * The handle from GNUNET_STATISTICS_get() */ struct GNUNET_STATISTICS_GetHandle *get_handle; /** * Task to mark the statistics service connect operation as done */ GNUNET_SCHEDULER_TaskIdentifier op_done_task_id; /** * The index of this peer in the peers array of GetStatsContext */ unsigned int peer_index; }; /** * A no-wait operation queue */ static struct OperationQueue *no_wait_queue; /** * Call statistics operation completion. We call it in a separate task because * the iteration_completion_cb() cannot destroy statistics handle which will be * the case if the user calles GNUNET_TESTBED_operation_done() on the * get_statistics operation. * * @param cls the GetStatsContext * @param tc the scheduler task context */ static void call_completion_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GetStatsContext *sc = cls; GNUNET_assert (sc->call_completion_task_id != GNUNET_SCHEDULER_NO_TASK); sc->call_completion_task_id = GNUNET_SCHEDULER_NO_TASK; LOG_DEBUG ("Calling get_statistics() continuation callback\n"); sc->cont (sc->cb_cls, sc->main_op, NULL); } /** * Task to mark statistics service connect operation as done. We call it here * as we cannot destroy the statistics handle in iteration_completion_cb() * * @param cls the PeerGetStatsContext * @param tc the scheduler task context */ static void op_done_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerGetStatsContext *peer_sc = cls; struct GetStatsContext *sc; struct GNUNET_TESTBED_Operation **op; sc = peer_sc->sc; peer_sc->op_done_task_id = GNUNET_SCHEDULER_NO_TASK; op = &sc->ops[peer_sc->peer_index]; GNUNET_assert (NULL != *op); GNUNET_TESTBED_operation_done (*op); *op = NULL; } /** * Continuation called by the "get_all" and "get" functions. * * @param cls the PeerGetStatsContext * @param success GNUNET_OK if statistics were * successfully obtained, GNUNET_SYSERR if not. */ static void iteration_completion_cb (void *cls, int success) { struct PeerGetStatsContext *peer_sc = cls; struct GetStatsContext *sc; GNUNET_break (GNUNET_OK == success); sc = peer_sc->sc; peer_sc->get_handle = NULL; sc->num_completed++; peer_sc->op_done_task_id = GNUNET_SCHEDULER_add_now (&op_done_task, peer_sc); if (sc->num_completed == sc->num_peers) { LOG_DEBUG ("Scheduling to call iteration completion callback\n"); sc->call_completion_task_id = GNUNET_SCHEDULER_add_now (&call_completion_task, sc); } } /** * Callback function to process statistic values. * * @param cls the PeerGetStatsContext * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int iterator_cb (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { struct PeerGetStatsContext *peer_sc = cls; struct GetStatsContext *sc; struct GNUNET_TESTBED_Peer *peer; int ret; sc = peer_sc->sc; peer = sc->peers[peer_sc->peer_index]; LOG_DEBUG ("Peer %u: [%s,%s] -> %lu\n", peer_sc->peer_index, subsystem, name, (unsigned long) value); ret = sc->proc (sc->cb_cls, peer, subsystem, name, value, is_persistent); if (GNUNET_SYSERR == ret) LOG_DEBUG ("Aborting iteration for peer %u\n", peer_sc->peer_index); return ret; } /** * Called after opening a connection to the statistics service of a peer * * @param cls the PeerGetStatsContext * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void service_connect_comp (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct PeerGetStatsContext *peer_sc = cls; struct GNUNET_STATISTICS_Handle *h = ca_result; LOG_DEBUG ("Retrieving statistics of peer %u\n", peer_sc->peer_index); peer_sc->get_handle = GNUNET_STATISTICS_get (h, peer_sc->sc->subsystem, peer_sc->sc->name, GNUNET_TIME_UNIT_FOREVER_REL, &iteration_completion_cb, iterator_cb, peer_sc); } /** * Adapter function called to establish a connection to the statistics service * of a peer. * * @param cls the PeerGetStatsContext * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * statistics_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct PeerGetStatsContext *peer_sc = cls; LOG_DEBUG ("Connecting to statistics service of peer %u\n", peer_sc->peer_index); return GNUNET_STATISTICS_create ("", cfg); } /** * Adapter function called to destroy statistics connection * * @param cls the PeerGetStatsContext * @param op_result service handle returned from the connect adapter */ static void statistics_da (void *cls, void *op_result) { struct PeerGetStatsContext *peer_sc = cls; struct GNUNET_STATISTICS_Handle *sh = op_result; if (NULL != peer_sc->get_handle) { GNUNET_STATISTICS_get_cancel (peer_sc->get_handle); peer_sc->get_handle = NULL; } GNUNET_STATISTICS_destroy (sh, GNUNET_NO); if (GNUNET_SCHEDULER_NO_TASK != peer_sc->op_done_task_id) GNUNET_SCHEDULER_cancel (peer_sc->op_done_task_id); GNUNET_free (peer_sc); } /** * Function called when get_statistics operation is ready * * @param cls the GetStatsContext */ static void opstart_get_stats (void *cls) { struct GetStatsContext *sc = cls; struct PeerGetStatsContext *peer_sc; unsigned int peer; LOG_DEBUG ("Starting get_statistics operation\n"); sc->ops = GNUNET_malloc (sc->num_peers * sizeof (struct GNUNET_TESTBED_Operation *)); for (peer = 0; peer < sc->num_peers; peer++) { if (NULL == sc->peers[peer]) { GNUNET_break (0); continue; } peer_sc = GNUNET_new (struct PeerGetStatsContext); peer_sc->sc = sc; peer_sc->peer_index = peer; sc->ops[peer] = GNUNET_TESTBED_service_connect (sc, sc->peers[peer], "statistics", &service_connect_comp, peer_sc, &statistics_ca, &statistics_da, peer_sc); } } /** * Function called when get_statistics operation is cancelled or marked as done * * @param cls the GetStatsContext */ static void oprelease_get_stats (void *cls) { struct GetStatsContext *sc = cls; unsigned int peer; LOG_DEBUG ("Cleaning up get_statistics operation\n"); if (GNUNET_SCHEDULER_NO_TASK != sc->call_completion_task_id) GNUNET_SCHEDULER_cancel (sc->call_completion_task_id); if (NULL != sc->ops) { for (peer = 0; peer < sc->num_peers; peer++) { if (NULL != sc->ops[peer]) { GNUNET_TESTBED_operation_done (sc->ops[peer]); sc->ops[peer] = NULL; } } GNUNET_free (sc->ops); } GNUNET_free_non_null (sc->subsystem); GNUNET_free_non_null (sc->name); GNUNET_free (sc); if (GNUNET_YES == GNUNET_TESTBED_operation_queue_destroy_empty_ (no_wait_queue)) no_wait_queue = NULL; } /** * Convenience method that iterates over all (running) peers * and retrieves all statistics from each peer. * * @param num_peers number of peers to iterate over * @param peers array of peers to iterate over * @param subsystem limit to the specified subsystem, NULL for all subsystems * @param name name of the statistic value, NULL for all values * @param proc processing function for each statistic retrieved * @param cont continuation to call once call is completed(?) * @param cls closure to pass to proc and cont * @return operation handle to cancel the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_get_statistics (unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, const char *subsystem, const char *name, GNUNET_TESTBED_StatisticsIterator proc, GNUNET_TESTBED_OperationCompletionCallback cont, void *cls) { struct GetStatsContext *sc; GNUNET_assert (NULL != proc); GNUNET_assert (NULL != cont); if (NULL == no_wait_queue) no_wait_queue = GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED, UINT_MAX); sc = GNUNET_new (struct GetStatsContext); sc->peers = peers; sc->subsystem = (NULL == subsystem) ? NULL : GNUNET_strdup (subsystem); sc->name = (NULL == name) ? NULL : GNUNET_strdup (name); sc->proc = proc; sc->cont = cont; sc->cb_cls = cls; sc->num_peers = num_peers; sc->main_op = GNUNET_TESTBED_operation_create_ (sc, &opstart_get_stats, &oprelease_get_stats); GNUNET_TESTBED_operation_queue_insert_ (no_wait_queue, sc->main_op); GNUNET_TESTBED_operation_begin_wait_ (sc->main_op); return sc->main_op; } /* end of testbed_api_statistics.c */ gnunet-0.10.1/src/testbed/gnunet-service-testbed.h0000644000175000017500000004472512233724131017004 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed.h * @brief data structures shared amongst components of TESTBED service * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_transport_service.h" #include "gnunet_core_service.h" #include "testbed.h" #include "testbed_api.h" #include "testbed_api_operations.h" #include "testbed_api_hosts.h" #include "gnunet_testing_lib.h" #include "gnunet-service-testbed_links.h" /** * Generic logging */ #define LOG(kind,...) \ GNUNET_log (kind, __VA_ARGS__) /** * Debug logging */ #define LOG_DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * By how much should the arrays lists grow */ #define LIST_GROW_STEP 10 /** * A routing entry */ struct Route { /** * destination host */ uint32_t dest; /** * The destination host is reachable thru */ uint32_t thru; }; /** * Context information for operations forwarded to subcontrollers */ struct ForwardedOperationContext { /** * The next pointer for DLL */ struct ForwardedOperationContext *next; /** * The prev pointer for DLL */ struct ForwardedOperationContext *prev; /** * The generated operation context */ struct OperationContext *opc; /** * The client to which we have to reply */ struct GNUNET_SERVER_Client *client; /** * Closure pointer */ void *cls; /** * Task ID for the timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * The id of the operation that has been forwarded */ uint64_t operation_id; /** * The type of the operation which is forwarded */ enum OperationType type; }; /** * A DLL of host registrations to be made */ struct HostRegistration { /** * next registration in the DLL */ struct HostRegistration *next; /** * previous registration in the DLL */ struct HostRegistration *prev; /** * The callback to call after this registration's status is available */ GNUNET_TESTBED_HostRegistrationCompletion cb; /** * The closure for the above callback */ void *cb_cls; /** * The host that has to be registered */ struct GNUNET_TESTBED_Host *host; }; /** * Context information used while linking controllers */ struct LinkControllersContext { /** * The client which initiated the link controller operation */ struct GNUNET_SERVER_Client *client; /** * The ID of the operation */ uint64_t operation_id; }; /** * A peer */ struct Peer { union { struct { /** * The peer handle from testing API */ struct GNUNET_TESTING_Peer *peer; /** * The modified (by GNUNET_TESTING_peer_configure) configuration this * peer is configured with */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * Is the peer running */ int is_running; } local; struct { /** * The slave this peer is started through */ struct Slave *slave; /** * The id of the remote host this peer is running on */ uint32_t remote_host_id; } remote; } details; /** * Is this peer locally created? */ int is_remote; /** * Our local reference id for this peer */ uint32_t id; /** * References to peers are using in forwarded overlay contexts and remote * overlay connect contexts. A peer can only be destroyed after all such * contexts are destroyed. For this, we maintain a reference counter. When we * use a peer in any such context, we increment this counter. We decrement it * when we are destroying these contexts */ uint32_t reference_cnt; /** * While destroying a peer, due to the fact that there could be references to * this peer, we delay the peer destroy to a further time. We do this by using * this flag to destroy the peer while destroying a context in which this peer * has been used. When the flag is set to 1 and reference_cnt = 0 we destroy * the peer */ uint32_t destroy_flag; }; /** * The main context information associated with the client which started us */ struct Context { /** * The client handle associated with this context */ struct GNUNET_SERVER_Client *client; /** * The network address of the master controller */ char *master_ip; /** * The TESTING system handle for starting peers locally */ struct GNUNET_TESTING_System *system; /** * Our host id according to this context */ uint32_t host_id; }; /** * The structure for identifying a shared service */ struct SharedService { /** * The name of the shared service */ char *name; /** * Number of shared peers per instance of the shared service */ uint32_t num_shared; /** * Number of peers currently sharing the service */ uint32_t num_sharing; }; /** * Context information to used during operations which forward the overlay * connect message */ struct ForwardedOverlayConnectContext { /** * next ForwardedOverlayConnectContext in the DLL */ struct ForwardedOverlayConnectContext *next; /** * previous ForwardedOverlayConnectContext in the DLL */ struct ForwardedOverlayConnectContext *prev; /** * A copy of the original overlay connect message */ struct GNUNET_MessageHeader *orig_msg; /** * The client handle */ struct GNUNET_SERVER_Client *client; /** * The id of the operation which created this context information */ uint64_t operation_id; /** * the id of peer 1 */ uint32_t peer1; /** * The id of peer 2 */ uint32_t peer2; /** * Id of the host where peer2 is running */ uint32_t peer2_host_id; }; /** * This context information will be created for each host that is registered at * slave controllers during overlay connects. */ struct RegisteredHostContext { /** * The host which is being registered */ struct GNUNET_TESTBED_Host *reg_host; /** * The host of the controller which has to connect to the above rhost */ struct GNUNET_TESTBED_Host *host; /** * Head of the ForwardedOverlayConnectContext DLL */ struct ForwardedOverlayConnectContext *focc_dll_head; /** * Tail of the ForwardedOverlayConnectContext DLL */ struct ForwardedOverlayConnectContext *focc_dll_tail; /** * Enumeration of states for this context */ enum RHCState { /** * The initial state */ RHC_INIT = 0, /** * State where we attempt to do the overlay connection again */ RHC_DONE } state; }; /** * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler */ struct HandlerContext_ShutdownPeers { /** * The number of slave we expect to hear from since we forwarded the * GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them */ unsigned int nslaves; /** * Did we observe a timeout with respect to this operation at any of the * slaves */ int timeout; }; /** * Our configuration */ extern struct GNUNET_CONFIGURATION_Handle *GST_config; /** * The master context; generated with the first INIT message */ extern struct Context *GST_context; /** * DLL head for forwarded operation contexts */ extern struct ForwardedOperationContext *fopcq_head; /** * DLL tail for forwarded operation contexts */ extern struct ForwardedOperationContext *fopcq_tail; /** * A list of peers we know about */ extern struct Peer **GST_peer_list; /** * Array of hosts */ extern struct GNUNET_TESTBED_Host **GST_host_list; /** * Operation queue for open file descriptors */ extern struct OperationQueue *GST_opq_openfds; /** * Timeout for operations which may take some time */ const extern struct GNUNET_TIME_Relative GST_timeout; /** * The size of the peer list */ extern unsigned int GST_peer_list_size; /** * The current number of peers running locally under this controller */ extern unsigned int GST_num_local_peers; /** * The size of the host list */ extern unsigned int GST_host_list_size; /** * The directory where to store load statistics data */ extern char *GST_stats_dir; /** * Condition to check if host id is valid */ #define VALID_HOST_ID(id) \ ( ((id) < GST_host_list_size) && (NULL != GST_host_list[id]) ) /** * Condition to check if peer id is valid */ #define VALID_PEER_ID(id) \ ( ((id) < GST_peer_list_size) && (NULL != GST_peer_list[id]) ) /** * Similar to GNUNET_array_grow(); however instead of calling GNUNET_array_grow() * several times we call it only once. The array is also made to grow in steps * of LIST_GROW_STEP. * * @param ptr the array pointer to grow * @param size the size of array * @param accommodate_size the size which the array has to accommdate; after * this call the array will be big enough to accommdate sizes upto * accommodate_size */ #define GST_array_grow_large_enough(ptr, size, accommodate_size) \ do \ { \ unsigned int growth_size; \ GNUNET_assert (size <= accommodate_size); \ growth_size = size; \ while (growth_size <= accommodate_size) \ growth_size += LIST_GROW_STEP; \ GNUNET_array_grow (ptr, size, growth_size); \ GNUNET_assert (size > accommodate_size); \ } while (0) /** * Queues a message in send queue for sending to the service * * @param client the client to whom the queued message has to be sent * @param msg the message to queue */ void GST_queue_message (struct GNUNET_SERVER_Client *client, struct GNUNET_MessageHeader *msg); /** * Function to destroy a peer * * @param peer the peer structure to destroy */ void GST_destroy_peer (struct Peer *peer); /** * Stops and destroys all peers */ void GST_destroy_peers (); /** * Finds the route with directly connected host as destination through which * the destination host can be reached * * @param host_id the id of the destination host * @return the route with directly connected destination host; NULL if no route * is found */ struct Route * GST_find_dest_route (uint32_t host_id); /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Adds a host registration's request to a slave's registration queue * * @param slave the slave controller at which the given host has to be * registered * @param cb the host registration completion callback * @param cb_cls the closure for the host registration completion callback * @param host the host which has to be registered */ void GST_queue_host_registration (struct Slave *slave, GNUNET_TESTBED_HostRegistrationCompletion cb, void *cb_cls, struct GNUNET_TESTBED_Host *host); /** * Callback to relay the reply msg of a forwarded operation back to the client * * @param cls ForwardedOperationContext * @param msg the message to relay */ void GST_forwarded_operation_reply_relay (void *cls, const struct GNUNET_MessageHeader *msg); /** * Task to free resources when forwarded operation has been timedout * * @param cls the ForwardedOperationContext * @param tc the task context from scheduler */ void GST_forwarded_operation_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Clears the forwarded operations queue */ void GST_clear_fopcq (); /** * Send operation failure message to client * * @param client the client to which the failure message has to be sent to * @param operation_id the id of the failed operation * @param emsg the error message; can be NULL */ void GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, uint64_t operation_id, const char *emsg); /** * Function to send generic operation success message to given client * * @param client the client to send the message to * @param operation_id the id of the operation which was successful */ void GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client, uint64_t operation_id); /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_remote_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handler for GNUNET_TESTBED_ManagePeerServiceMessage message * * @param cls NULL * @param client identification of client * @param message the actual message */ void GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handler for GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages. * Should stop the peer asyncronously, destroy it and create it again with the * new configuration. * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Frees the ManageServiceContext queue */ void GST_free_mctxq (); /** * Cleans up the queue used for forwarding link controllers requests */ void GST_free_lcfq (); /** * Cleans up the route list */ void GST_route_list_clear (); /** * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext * * @param rhc the RegisteredHostContext */ void GST_process_next_focc (struct RegisteredHostContext *rhc); /** * Cleans up ForwardedOverlayConnectContext * * @param focc the ForwardedOverlayConnectContext to cleanup */ void GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc); /** * Clears all pending overlay connect contexts in queue */ void GST_free_occq (); /** * Clears all pending remote overlay connect contexts in queue */ void GST_free_roccq (); /** * Cleans up the Peer reconfigure context list */ void GST_free_prcq (); /** * Initializes the cache * * @param size the size of the cache */ void GST_cache_init (unsigned int size); /** * Clear cache */ void GST_cache_clear (); /** * Looks up in the hello cache and returns the HELLO of the given peer * * @param peer_id the index of the peer whose HELLO has to be looked up * @return the HELLO message; NULL if not found */ const struct GNUNET_MessageHeader * GST_cache_lookup_hello (const unsigned int peer_id); /** * Caches the HELLO of the given peer. Updates the HELLO if it was already * cached before * * @param peer_id the peer identity of the peer whose HELLO has to be cached * @param hello the HELLO message */ void GST_cache_add_hello (const unsigned int peer_id, const struct GNUNET_MessageHeader *hello); /** * Initialize logging CPU and IO statisticfs. Checks the configuration for * "STATS_DIR" and logs to a file in that directory. The file is name is * generated from the hostname and the process's PID. */ void GST_stats_init (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Shutdown the status calls module. */ void GST_stats_destroy (); /* End of gnunet-service-testbed.h */ gnunet-0.10.1/src/testbed/gnunet-service-testbed_connectionpool.c0000644000175000017500000006673212261236531022115 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_connectionpool.c * @brief connection pooling for connections to peers' services * @author Sree Harsha Totakura */ #include "gnunet-service-testbed.h" #include "gnunet-service-testbed_connectionpool.h" #include "testbed_api_operations.h" /** * Redefine LOG with a changed log component string */ #ifdef LOG #undef LOG #endif #define LOG(kind,...) \ GNUNET_log_from (kind, "testbed-connectionpool", __VA_ARGS__) /** * Time to expire a cache entry */ #define CACHE_EXPIRY \ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) /** * The request handle for obtaining a pooled connection */ struct GST_ConnectionPool_GetHandle; /** * A pooled connection */ struct PooledConnection { /** * Next ptr for placing this object in the DLL of least recently used pooled * connections */ struct PooledConnection *next; /** * Prev ptr for placing this object in the DLL of the least recently used * pooled connections */ struct PooledConnection *prev; /** * The transport handle to the peer corresponding to this entry; can be NULL */ struct GNUNET_TRANSPORT_Handle *handle_transport; /** * The core handle to the peer corresponding to this entry; can be NULL */ struct GNUNET_CORE_Handle *handle_core; /** * The operation handle for transport handle */ struct GNUNET_TESTBED_Operation *op_transport; /** * The operation handle for core handle */ struct GNUNET_TESTBED_Operation *op_core; /** * The peer identity of this peer. Will be set upon opening a connection to * the peers CORE service. Will be NULL until then and after the CORE * connection is closed */ struct GNUNET_PeerIdentity *peer_identity; /** * The configuration of the peer. Should be not NULL as long as the core_handle * or transport_handle are valid */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * DLL head for the queue to serve notifications when a peer is connected */ struct GST_ConnectionPool_GetHandle *head_notify; /** * DLL tail for the queue to serve notifications when a peer is connected */ struct GST_ConnectionPool_GetHandle *tail_notify; /** * DLL head for the queue of #GST_ConnectionPool_GetHandle requests that are * waiting for this connection to be opened */ struct GST_ConnectionPool_GetHandle *head_waiting; /** * DLL tail for the queue of #GST_ConnectionPool_GetHandle requests that are * waiting for this connection to be opened */ struct GST_ConnectionPool_GetHandle *tail_waiting; /** * The task to expire this connection from the connection pool */ GNUNET_SCHEDULER_TaskIdentifier expire_task; /** * The task to notify a waiting #GST_ConnectionPool_GetHandle object */ GNUNET_SCHEDULER_TaskIdentifier notify_task; /** * Number of active requests using this pooled connection */ unsigned int demand; /** * Is this entry in LRU */ int in_lru; /** * Is this entry present in the connection pool */ int in_pool; /** * The index of this peer */ uint32_t index; }; /** * The request handle for obtaining a pooled connection */ struct GST_ConnectionPool_GetHandle { /** * The next ptr for inclusion in the notification DLLs. At first the object * is placed in the waiting DLL of the corresponding #PooledConnection * object. After the handle is opened it is moved to the notification DLL if * @p connect_notify_cb and @p target are not NULL */ struct GST_ConnectionPool_GetHandle *next; /** * The prev ptr for inclusion in the notification DLLs */ struct GST_ConnectionPool_GetHandle *prev; /** * The pooled connection object this handle corresponds to */ struct PooledConnection *entry; /** * The cache callback to call when a handle is available */ GST_connection_pool_connection_ready_cb cb; /** * The closure for the above callback */ void *cb_cls; /** * The peer identity of the target peer. When this target peer is connected, * call the notify callback */ const struct GNUNET_PeerIdentity *target; /** * The callback to be called for serving notification that the target peer is * connected */ GST_connection_pool_peer_connect_notify connect_notify_cb; /** * The closure for the notify callback */ void *connect_notify_cb_cls; /** * The service we want to connect to */ enum GST_ConnectionPool_Service service; /** * Did we call the pool_connection_ready_cb already? */ int connection_ready_called; /** * Are we waiting for any peer connect notifications? */ int notify_waiting; }; /** * A hashmap for quickly finding connections in the connection pool */ static struct GNUNET_CONTAINER_MultiHashMap32 *map; /** * DLL head for maitaining the least recently used #PooledConnection objects. * The head is the least recently used object. */ static struct PooledConnection *head_lru; /** * DLL tail for maitaining the least recently used #PooledConnection objects */ static struct PooledConnection *tail_lru; /** * DLL head for maintaining #PooledConnection objects that are not added into * the connection pool as it was full at the time the object's creation * FIXME */ static struct PooledConnection *head_not_pooled; /** * DLL tail for maintaining #PooledConnection objects that are not added into * the connection pool as it was full at the time the object's creation */ static struct PooledConnection *tail_not_pooled; /** * The maximum number of entries that can be present in the connection pool */ static unsigned int max_size; /** * Cancel the expiration task of the give #PooledConnection object * * @param entry the #PooledConnection object */ static void expire_task_cancel (struct PooledConnection *entry); /** * Destroy a #PooledConnection object * * @param entry the #PooledConnection object */ static void destroy_pooled_connection (struct PooledConnection *entry) { GNUNET_assert ((NULL == entry->head_notify) && (NULL == entry->tail_notify)); GNUNET_assert ((NULL == entry->head_waiting) && (NULL == entry->tail_waiting)); GNUNET_assert (0 == entry->demand); expire_task_cancel (entry); if (entry->in_lru) GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); if (entry->in_pool) GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_remove (map, entry->index, entry)); if (GNUNET_SCHEDULER_NO_TASK != entry->notify_task) { GNUNET_SCHEDULER_cancel (entry->notify_task); entry->notify_task = GNUNET_SCHEDULER_NO_TASK; } LOG_DEBUG ("Cleaning up handles of a pooled connection\n"); if (NULL != entry->handle_transport) GNUNET_assert (NULL != entry->op_transport); if (NULL != entry->op_transport) { GNUNET_TESTBED_operation_done (entry->op_transport); entry->op_transport = NULL; } if (NULL != entry->op_core) { GNUNET_TESTBED_operation_done (entry->op_core); entry->op_core = NULL; } GNUNET_assert (NULL == entry->handle_core); GNUNET_assert (NULL == entry->handle_transport); GNUNET_CONFIGURATION_destroy (entry->cfg); GNUNET_free (entry); } /** * Expire a #PooledConnection object * * @param cls the #PooledConnection object * @param tc scheduler task context */ static void expire (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PooledConnection *entry = cls; entry->expire_task = GNUNET_SCHEDULER_NO_TASK; destroy_pooled_connection (entry); } /** * Cancel the expiration task of the give #PooledConnection object * * @param entry the #PooledConnection object */ static void expire_task_cancel (struct PooledConnection *entry) { if (GNUNET_SCHEDULER_NO_TASK != entry->expire_task) { GNUNET_SCHEDULER_cancel (entry->expire_task); entry->expire_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Function to add a #PooledConnection object into LRU and begin the expiry task * * @param entry the #PooledConnection object */ static void add_to_lru (struct PooledConnection *entry) { GNUNET_assert (0 == entry->demand); GNUNET_assert (!entry->in_lru); GNUNET_CONTAINER_DLL_insert_tail (head_lru, tail_lru, entry); entry->in_lru = GNUNET_YES; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == entry->expire_task); entry->expire_task = GNUNET_SCHEDULER_add_delayed (CACHE_EXPIRY, &expire, entry); } /** * Function to find a #GST_ConnectionPool_GetHandle which is waiting for one of * the handles in given entry which are now available. * * @param entry the pooled connection whose active list has to be searched * @param head the starting list element in the GSTCacheGetHandle where the * search has to be begin * @return a suitable GSTCacheGetHandle whose handle ready notify callback * hasn't been called yet. NULL if no such suitable GSTCacheGetHandle * is found */ static struct GST_ConnectionPool_GetHandle * search_waiting (const struct PooledConnection *entry, struct GST_ConnectionPool_GetHandle *head) { struct GST_ConnectionPool_GetHandle *gh; for (gh = head; NULL != gh; gh = gh->next) { switch (gh->service) { case GST_CONNECTIONPOOL_SERVICE_CORE: if (NULL == entry->handle_core) continue; if (NULL == entry->peer_identity) continue; /* CORE connection isn't ready yet */ break; case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: if (NULL == entry->handle_transport) continue; break; } break; } return gh; } /** * A handle in the #PooledConnection object pointed by @a cls is ready and there * is a #GST_ConnectionPool_GetHandle object waiting in the waiting list. This * function retrieves that object and calls the handle ready callback. It * further schedules itself if there are similar waiting objects which can be notified. * * @param cls the #PooledConnection object * @param tc the task context from scheduler */ static void connection_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PooledConnection *entry = cls; struct GST_ConnectionPool_GetHandle *gh; struct GST_ConnectionPool_GetHandle *gh_next; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != entry->notify_task); entry->notify_task = GNUNET_SCHEDULER_NO_TASK; gh = search_waiting (entry, entry->head_waiting); GNUNET_assert (NULL != gh); gh_next = NULL; if (NULL != gh->next) gh_next = search_waiting (entry, gh->next); GNUNET_CONTAINER_DLL_remove (entry->head_waiting, entry->tail_waiting, gh); gh->connection_ready_called = 1; if (NULL != gh_next) entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); if ( (NULL != gh->target) && (NULL != gh->connect_notify_cb) ) { GNUNET_CONTAINER_DLL_insert_tail (entry->head_notify, entry->tail_notify, gh); gh->notify_waiting = 1; } LOG_DEBUG ("Connection ready for handle type %u\n", gh->service); gh->cb (gh->cb_cls, entry->handle_core, entry->handle_transport, entry->peer_identity); } /** * Function called from peer connect notify callbacks from CORE and TRANSPORT * connections. This function calls the pending peer connect notify callbacks * which are queued in an entry. * * @param cls the #PooledConnection object * @param peer the peer that connected * @param service the service where this notification has originated */ static void peer_connect_notify_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const enum GST_ConnectionPool_Service service) { struct PooledConnection *entry = cls; struct GST_ConnectionPool_GetHandle *gh; struct GST_ConnectionPool_GetHandle *gh_next; GST_connection_pool_peer_connect_notify cb; void *cb_cls; for (gh = entry->head_notify; NULL != gh;) { GNUNET_assert (NULL != gh->target); GNUNET_assert (NULL != gh->connect_notify_cb); GNUNET_assert (gh->connection_ready_called); if (service != gh->service) { gh = gh->next; continue; } if (0 != memcmp (gh->target, peer, sizeof (struct GNUNET_PeerIdentity))) { gh = gh->next; continue; } cb = gh->connect_notify_cb; cb_cls = gh->connect_notify_cb_cls; gh_next = gh->next; GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh); gh->notify_waiting = 0; LOG_DEBUG ("Peer connected to peer %u at service %u\n", entry->index, gh->service); gh = gh_next; cb (cb_cls, peer); } } /** * Function called to notify transport users that another * peer connected to us. * * @param cls the #PooledConnection object * @param peer the peer that connected */ static void transport_peer_connect_notify_cb (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PooledConnection *entry = cls; peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_TRANSPORT); } /** * Function called when resources for opening a connection to TRANSPORT are * available. * * @param cls the #PooledConnection object */ static void opstart_get_handle_transport (void *cls) { struct PooledConnection *entry = cls; GNUNET_assert (NULL != entry); LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->index); entry->handle_transport = GNUNET_TRANSPORT_connect (entry->cfg, NULL, entry, NULL, &transport_peer_connect_notify_cb, NULL); if (NULL == entry->handle_transport) { GNUNET_break (0); return; } if (0 == entry->demand) return; if (GNUNET_SCHEDULER_NO_TASK != entry->notify_task) return; if (NULL != search_waiting (entry, entry->head_waiting)) { entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); return; } } /** * Function called when the operation responsible for opening a TRANSPORT * connection is marked as done. * * @param cls the cache entry */ static void oprelease_get_handle_transport (void *cls) { struct PooledConnection *entry = cls; if (NULL == entry->handle_transport) return; GNUNET_TRANSPORT_disconnect (entry->handle_transport); entry->handle_transport = NULL; } /** * Method called whenever a given peer connects at CORE level * * @param cls the #PooledConnection object * @param peer peer identity this notification is about */ static void core_peer_connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PooledConnection *entry = cls; peer_connect_notify_cb (entry, peer, GST_CONNECTIONPOOL_SERVICE_CORE); } /** * Function called after GNUNET_CORE_connect has succeeded (or failed * for good). Note that the private key of the peer is intentionally * not exposed here; if you need it, your process should try to read * the private key file directly (which should work if you are * authorized...). Implementations of this function must not call * GNUNET_CORE_disconnect (other than by scheduling a new task to * do this later). * * @param cls the #PooledConnection object * @param my_identity ID of this peer, NULL if we failed */ static void core_startup_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) { struct PooledConnection *entry = cls; if (NULL == my_identity) { GNUNET_break (0); return; } GNUNET_assert (NULL == entry->peer_identity); entry->peer_identity = GNUNET_new (struct GNUNET_PeerIdentity); memcpy (entry->peer_identity, my_identity, sizeof (struct GNUNET_PeerIdentity)); if (0 == entry->demand) return; if (GNUNET_SCHEDULER_NO_TASK != entry->notify_task) return; if (NULL != search_waiting (entry, entry->head_waiting)) { entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); return; } } /** * Function called when resources for opening a connection to CORE are * available. * * @param cls the #PooledConnection object */ static void opstart_get_handle_core (void *cls) { struct PooledConnection *entry = cls; const struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} }; GNUNET_assert (NULL != entry); LOG_DEBUG ("Opening a CORE connection to peer %u\n", entry->index); entry->handle_core = GNUNET_CORE_connect (entry->cfg, entry, /* closure */ &core_startup_cb, /* core startup notify */ &core_peer_connect_cb, /* peer connect notify */ NULL, /* peer disconnect notify */ NULL, /* inbound notify */ GNUNET_NO, /* inbound header only? */ NULL, /* outbound notify */ GNUNET_NO, /* outbound header only? */ no_handlers); } /** * Function called when the operation responsible for opening a TRANSPORT * connection is marked as done. * * @param cls the #PooledConnection object */ static void oprelease_get_handle_core (void *cls) { struct PooledConnection *entry = cls; if (NULL == entry->handle_core) return; GNUNET_CORE_disconnect (entry->handle_core); entry->handle_core = NULL; GNUNET_free_non_null (entry->peer_identity); entry->peer_identity = NULL; } /** * This function will be called for every #PooledConnection object in @p map * * @param cls NULL * @param key current key code * @param value the #PooledConnection object * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int cleanup_iterator (void *cls, uint32_t key, void *value) { struct PooledConnection *entry = value; GNUNET_assert (NULL != entry); destroy_pooled_connection (entry); return GNUNET_YES; } /** * Initialise the connection pool. * * @param size the size of the connection pool. Each entry in the connection * pool can handle a connection to each of the services enumerated in * #GST_ConnectionPool_Service */ void GST_connection_pool_init (unsigned int size) { max_size = size; if (0 == max_size) return; GNUNET_assert (NULL == map); map = GNUNET_CONTAINER_multihashmap32_create (((size * 3) / 4) + 1); } /** * Cleanup the connection pool */ void GST_connection_pool_destroy () { struct PooledConnection *entry; if (NULL != map) { GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap32_iterate (map, &cleanup_iterator, NULL)); GNUNET_CONTAINER_multihashmap32_destroy (map); map = NULL; } while (NULL != (entry = head_lru)) { GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); destroy_pooled_connection (entry); } GNUNET_assert (NULL == head_not_pooled); } /** * Get a connection handle to @a service. If the connection is opened before * and the connection handle is present in the connection pool, it is returned * through @a cb. @a peer_id is used for the lookup in the connection pool. If * the connection handle is not present in the connection pool, a new connection * handle is opened for the @a service using @a cfg. Additionally, @a target, * @a connect_notify_cb can be specified to get notified when @a target is * connected at @a service. * * @note @a connect_notify_cb will not be called if @a target is * already connected @a service level. Use * GNUNET_TRANSPORT_check_peer_connected() or a similar function from the * respective @a service's API to check if the target peer is already connected or * not. @a connect_notify_cb will be called only once or never (in case @a target * cannot be connected or is already connected). * * @param peer_id the index of the peer * @param cfg the configuration with which the transport handle has to be * created if it was not present in the cache * @param service the service of interest * @param cb the callback to notify when the transport handle is available * @param cb_cls the closure for @a cb * @param target the peer identify of the peer whose connection to our TRANSPORT * subsystem will be notified through the @a connect_notify_cb. Can be NULL * @param connect_notify_cb the callback to call when the @a target peer is * connected. This callback will only be called once or never again (in * case the target peer cannot be connected). Can be NULL * @param connect_notify_cb_cls the closure for @a connect_notify_cb * @return the handle which can be used cancel or mark that the handle is no * longer being used */ struct GST_ConnectionPool_GetHandle * GST_connection_pool_get_handle (unsigned int peer_id, const struct GNUNET_CONFIGURATION_Handle *cfg, enum GST_ConnectionPool_Service service, GST_connection_pool_connection_ready_cb cb, void *cb_cls, const struct GNUNET_PeerIdentity *target, GST_connection_pool_peer_connect_notify connect_notify_cb, void *connect_notify_cb_cls) { struct GST_ConnectionPool_GetHandle *gh; struct PooledConnection *entry; struct GNUNET_TESTBED_Operation *op; void *handle; uint32_t peer_id32; peer_id32 = (uint32_t) peer_id; handle = NULL; entry = NULL; if (NULL != map) entry = GNUNET_CONTAINER_multihashmap32_get (map, peer_id32); if (NULL != entry) { if (entry->in_lru) { GNUNET_assert (0 == entry->demand); expire_task_cancel (entry); GNUNET_CONTAINER_DLL_remove (head_lru, tail_lru, entry); entry->in_lru = GNUNET_NO; } switch (service) { case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: handle = entry->handle_transport; if (NULL != handle) LOG_DEBUG ("Found TRANSPORT handle for peer %u\n", entry->index); break; case GST_CONNECTIONPOOL_SERVICE_CORE: handle = entry->handle_core; if (NULL != handle) LOG_DEBUG ("Found CORE handle for peer %u\n", entry->index); break; } } else { entry = GNUNET_new (struct PooledConnection); entry->index = peer_id32; if ((NULL != map) && (GNUNET_CONTAINER_multihashmap32_size (map) < max_size)) { GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (map, entry->index, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); entry->in_pool = GNUNET_YES; } else { GNUNET_CONTAINER_DLL_insert_tail (head_not_pooled, tail_not_pooled, entry); } entry->cfg = GNUNET_CONFIGURATION_dup (cfg); } entry->demand++; gh = GNUNET_new (struct GST_ConnectionPool_GetHandle); gh->entry = entry; gh->cb = cb; gh->cb_cls = cb_cls; gh->target = target; gh->connect_notify_cb = connect_notify_cb; gh->connect_notify_cb_cls = connect_notify_cb_cls; gh->service = service; GNUNET_CONTAINER_DLL_insert (entry->head_waiting, entry->tail_waiting, gh); if (NULL != handle) { if (GNUNET_SCHEDULER_NO_TASK == entry->notify_task) { if (NULL != search_waiting (entry, entry->head_waiting)) entry->notify_task = GNUNET_SCHEDULER_add_now (&connection_ready, entry); } return gh; } op = NULL; switch (gh->service) { case GST_CONNECTIONPOOL_SERVICE_TRANSPORT: if (NULL != entry->op_transport) return gh; /* Operation pending */ op = GNUNET_TESTBED_operation_create_ (entry, &opstart_get_handle_transport, &oprelease_get_handle_transport); entry->op_transport = op; break; case GST_CONNECTIONPOOL_SERVICE_CORE: if (NULL != entry->op_core) return gh; /* Operation pending */ op = GNUNET_TESTBED_operation_create_ (entry, &opstart_get_handle_core, &oprelease_get_handle_core); entry->op_core = op; break; } GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, op); GNUNET_TESTBED_operation_begin_wait_ (op); return gh; } /** * Relinquish a #GST_ConnectionPool_GetHandle object. If the connection * associated with the object is currently being used by other * #GST_ConnectionPool_GetHandle objects, it is left in the connection pool. If * no other objects are using the connection and the connection pool is not full * then it is placed in a LRU queue. If the connection pool is full, then * connections from the LRU queue are evicted and closed to create place for this * connection. If the connection pool if full and the LRU queue is empty, then * the connection is closed. * * @param gh the handle */ void GST_connection_pool_get_handle_done (struct GST_ConnectionPool_GetHandle *gh) { struct PooledConnection *entry; entry = gh->entry; LOG_DEBUG ("Cleaning up get handle %p for service %u, peer %u\n", gh, gh->service, entry->index); if (!gh->connection_ready_called) { GNUNET_CONTAINER_DLL_remove (entry->head_waiting, entry->tail_waiting, gh); if ( (NULL == search_waiting (entry, entry->head_waiting)) && (GNUNET_SCHEDULER_NO_TASK != entry->notify_task) ) { GNUNET_SCHEDULER_cancel (entry->notify_task); entry->notify_task = GNUNET_SCHEDULER_NO_TASK; } } if (gh->notify_waiting) { GNUNET_CONTAINER_DLL_remove (entry->head_notify, entry->tail_notify, gh); gh->notify_waiting = 0; } GNUNET_free (gh); gh = NULL; GNUNET_assert (!entry->in_lru); if (!entry->in_pool) GNUNET_CONTAINER_DLL_remove (head_not_pooled, tail_not_pooled, entry); if (NULL != map) { if (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_contains (map, entry->index)) goto unallocate; if (GNUNET_CONTAINER_multihashmap32_size (map) == max_size) { if (NULL == head_lru) goto unallocate; destroy_pooled_connection (head_lru); } GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (map, entry->index, entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); entry->in_pool = GNUNET_YES; } unallocate: GNUNET_assert (0 < entry->demand); entry->demand--; if (0 != entry->demand) return; if (entry->in_pool) { add_to_lru (entry); return; } destroy_pooled_connection (entry); } gnunet-0.10.1/src/testbed/gnunet-service-test-barriers.c0000644000175000017500000000706612225777502020143 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-test-barriers.c * @brief Daemon acting as a service for testing testbed barriers. It is * started as a peer service and waits for a barrier to be crossed. * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "test_testbed_api_barriers.h" /** * logging short hand */ #define LOG(type,...) \ GNUNET_log (type, __VA_ARGS__); /** * Our barrier wait handle */ struct GNUNET_TESTBED_BarrierWaitHandle *wh; /** * Dummy task callback to keep us running forever * * @param cls NULL * @param tc scheduler task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != wh) GNUNET_TESTBED_barrier_wait_cancel (wh); wh = NULL; } /** * Functions of this type are to be given as acallback argumetn to * GNUNET_TESTBED_barrier_wait(). The callback will be called when the barrier * corresponding given in GNUNET_TESTBED_barrier_wait() is crossed or cancelled. * * @param cls NULL * @param name the barrier name * @param status GNUNET_SYSERR in case of error while waiting for the barrier; * GNUNET_OK if the barrier is crossed */ static void barrier_wait_cb (void *cls, const char *name, int status) { GNUNET_break (NULL == cls); wh = NULL; GNUNET_break (GNUNET_OK == status); } /** * Task to wait for the barrier * * @param cls NULL * @param tc scheduler task context * @return */ static void do_wait (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; wh = GNUNET_TESTBED_barrier_wait (TEST_BARRIER_NAME, &barrier_wait_cb, NULL); GNUNET_break (NULL != wh); } /** * Main run function. * * @param cls NULL * @param args arguments passed to GNUNET_PROGRAM_run * @param cfgfile the path to configuration file * @param config the configuration file handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { unsigned int rsec; rsec = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 10); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, rsec), &do_wait, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); } /** * Main */ int main (int argc, char **argv) { struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; ret = GNUNET_PROGRAM_run (argc, argv, "test-barriers", "nohelp", options, &run, NULL); return ret; } gnunet-0.10.1/src/testbed/testbed_api_operations.c0000644000175000017500000010206212305564550017133 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_operations.c * @brief functions to manage operation queues * @author Christian Grothoff * @author Sree Harsha Totakura */ #include "platform.h" #include "testbed_api_operations.h" #include "testbed_api_sd.h" /** * The number of readings containing past operation's timing information that we * keep track of for adaptive queues */ #define ADAPTIVE_QUEUE_DEFAULT_HISTORY 40 /** * The number of parallel opeartions we start with by default for adaptive * queues */ #define ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE 4 /** * An entry in the operation queue */ struct QueueEntry { /** * The next DLL pointer */ struct QueueEntry *next; /** * The prev DLL pointer */ struct QueueEntry *prev; /** * The operation this entry holds */ struct GNUNET_TESTBED_Operation *op; /** * How many units of resources does the operation need */ unsigned int nres; }; /** * Queue of operations where we can only support a certain * number of concurrent operations of a particular type. */ struct OperationQueue; /** * A slot to record time taken by an operation */ struct TimeSlot { /** * DLL next pointer */ struct TimeSlot *next; /** * DLL prev pointer */ struct TimeSlot *prev; /** * This operation queue to which this time slot belongs to */ struct OperationQueue *queue; /** * The operation to which this timeslot is currently allocated to */ struct GNUNET_TESTBED_Operation *op; /** * Accumulated time */ struct GNUNET_TIME_Relative tsum; /** * Number of timing values accumulated */ unsigned int nvals; }; /** * Context for operation queues of type OPERATION_QUEUE_TYPE_ADAPTIVE */ struct FeedbackCtx { /** * Handle for calculating standard deviation */ struct SDHandle *sd; /** * Head for DLL of time slots which are free to be allocated to operations */ struct TimeSlot *alloc_head; /** * Tail for DLL of time slots which are free to be allocated to operations */ struct TimeSlot *alloc_tail; /** * Pointer to the chunk of time slots. Free all time slots at a time using * this pointer. */ struct TimeSlot *tslots_freeptr; /** * Number of time slots filled so far */ unsigned int tslots_filled; /** * Bound on the maximum number of operations which can be active */ unsigned int max_active_bound; /** * Number of operations that have failed */ unsigned int nfailed; }; /** * Queue of operations where we can only support a certain * number of concurrent operations of a particular type. */ struct OperationQueue { /** * DLL head for the wait queue. Operations which are waiting for this * operation queue are put here */ struct QueueEntry *wq_head; /** * DLL tail for the wait queue. */ struct QueueEntry *wq_tail; /** * DLL head for the ready queue. Operations which are in this operation queue * and are in ready state are put here */ struct QueueEntry *rq_head; /** * DLL tail for the ready queue */ struct QueueEntry *rq_tail; /** * DLL head for the active queue. Operations which are in this operation * queue and are currently active are put here */ struct QueueEntry *aq_head; /** * DLL tail for the active queue. */ struct QueueEntry *aq_tail; /** * DLL head for the inactive queue. Operations which are inactive and can be * evicted if the queues it holds are maxed out and another operation begins * to wait on them. */ struct QueueEntry *nq_head; /** * DLL tail for the inactive queue. */ struct QueueEntry *nq_tail; /** * Feedback context; only relevant for adaptive operation queues. NULL for * fixed operation queues */ struct FeedbackCtx *fctx; /** * The type of this opeartion queue */ enum OperationQueueType type; /** * Number of operations that are currently active in this queue. */ unsigned int active; /** * Max number of operations which can be active at any time in this queue. * This value can be changed either by calling * GNUNET_TESTBED_operation_queue_reset_max_active_() or by the adaptive * algorithm if this operation queue is of type #OPERATION_QUEUE_TYPE_ADAPTIVE */ unsigned int max_active; /** * The number of resources occupied by failed operations in the current shot. * This is only relavant if the operation queue is of type * #OPERATION_QUEUE_TYPE_ADAPTIVE */ unsigned int overload; }; /** * Operation state */ enum OperationState { /** * The operation is just created and is in initial state */ OP_STATE_INIT, /** * The operation is currently waiting for resources */ OP_STATE_WAITING, /** * The operation is ready to be started */ OP_STATE_READY, /** * The operation has started and is active */ OP_STATE_ACTIVE, /** * The operation is inactive. It still holds resources on the operation * queues. However, this operation will be evicted when another operation * requires resources from the maxed out queues this operation is holding * resources from. */ OP_STATE_INACTIVE }; /** * An entry in the ready queue (implemented as DLL) */ struct ReadyQueueEntry { /** * next ptr for DLL */ struct ReadyQueueEntry *next; /** * prev ptr for DLL */ struct ReadyQueueEntry *prev; /** * The operation associated with this entry */ struct GNUNET_TESTBED_Operation *op; }; /** * Opaque handle to an abstract operation to be executed by the testing framework. */ struct GNUNET_TESTBED_Operation { /** * Function to call when we have the resources to begin the operation. */ OperationStart start; /** * Function to call to clean up after the operation (which may or may * not have been started yet). */ OperationRelease release; /** * Closure for callbacks. */ void *cb_cls; /** * Array of operation queues this Operation belongs to. */ struct OperationQueue **queues; /** * Array of operation queue entries corresponding to this operation in * operation queues for this operation */ struct QueueEntry **qentries; /** * Array of number of resources an operation need from each queue. The numbers * in this array should correspond to the queues array */ unsigned int *nres; /** * Entry corresponding to this operation in ready queue. Will be NULL if the * operation is not marked as READY */ struct ReadyQueueEntry *rq_entry; /** * Head pointer for DLL of tslots allocated to this operation */ struct TimeSlot *tslots_head; /** * Tail pointer for DLL of tslots allocated to this operation */ struct TimeSlot *tslots_tail; /** * The time at which the operation is started */ struct GNUNET_TIME_Absolute tstart; /** * Number of queues in the operation queues array */ unsigned int nqueues; /** * The state of the operation */ enum OperationState state; /** * Is this a failed operation? */ int failed; }; /** * DLL head for the ready queue */ struct ReadyQueueEntry *rq_head; /** * DLL tail for the ready queue */ struct ReadyQueueEntry *rq_tail; /** * The id of the task to process the ready queue */ GNUNET_SCHEDULER_TaskIdentifier process_rq_task_id; /** * Assigns the given operation a time slot from the given operation queue * * @param op the operation * @param queue the operation queue * @return the timeslot */ static void assign_timeslot (struct GNUNET_TESTBED_Operation *op, struct OperationQueue *queue) { struct FeedbackCtx *fctx = queue->fctx; struct TimeSlot *tslot; GNUNET_assert (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type); tslot = fctx->alloc_head; GNUNET_assert (NULL != tslot); GNUNET_CONTAINER_DLL_remove (fctx->alloc_head, fctx->alloc_tail, tslot); GNUNET_CONTAINER_DLL_insert_tail (op->tslots_head, op->tslots_tail, tslot); tslot->op = op; } /** * Removes a queue entry of an operation from one of the operation queues' lists * depending on the state of the operation * * @param op the operation whose entry has to be removed * @param index the index of the entry in the operation's array of queue entries */ static void remove_queue_entry (struct GNUNET_TESTBED_Operation *op, unsigned int index) { struct OperationQueue *opq; struct QueueEntry *entry; opq = op->queues[index]; entry = op->qentries[index]; switch (op->state) { case OP_STATE_INIT: GNUNET_assert (0); break; case OP_STATE_WAITING: GNUNET_CONTAINER_DLL_remove (opq->wq_head, opq->wq_tail, entry); break; case OP_STATE_READY: GNUNET_CONTAINER_DLL_remove (opq->rq_head, opq->rq_tail, entry); break; case OP_STATE_ACTIVE: GNUNET_CONTAINER_DLL_remove (opq->aq_head, opq->aq_tail, entry); break; case OP_STATE_INACTIVE: GNUNET_CONTAINER_DLL_remove (opq->nq_head, opq->nq_tail, entry); break; } } /** * Changes the state of the operation while moving its associated queue entries * in the operation's operation queues * * @param op the operation whose state has to be changed * @param state the state the operation should have. It cannot be OP_STATE_INIT */ static void change_state (struct GNUNET_TESTBED_Operation *op, enum OperationState state) { struct QueueEntry *entry; struct OperationQueue *opq; unsigned int cnt; unsigned int s; GNUNET_assert (OP_STATE_INIT != state); GNUNET_assert (NULL != op->queues); GNUNET_assert (NULL != op->nres); GNUNET_assert ((OP_STATE_INIT == op->state) || (NULL != op->qentries)); GNUNET_assert (op->state != state); for (cnt = 0; cnt < op->nqueues; cnt++) { if (OP_STATE_INIT == op->state) { entry = GNUNET_new (struct QueueEntry); entry->op = op; entry->nres = op->nres[cnt]; s = cnt; GNUNET_array_append (op->qentries, s, entry); } else { entry = op->qentries[cnt]; remove_queue_entry (op, cnt); } opq = op->queues[cnt]; switch (state) { case OP_STATE_INIT: GNUNET_assert (0); break; case OP_STATE_WAITING: GNUNET_CONTAINER_DLL_insert_tail (opq->wq_head, opq->wq_tail, entry); break; case OP_STATE_READY: GNUNET_CONTAINER_DLL_insert_tail (opq->rq_head, opq->rq_tail, entry); break; case OP_STATE_ACTIVE: GNUNET_CONTAINER_DLL_insert_tail (opq->aq_head, opq->aq_tail, entry); break; case OP_STATE_INACTIVE: GNUNET_CONTAINER_DLL_insert_tail (opq->nq_head, opq->nq_tail, entry); break; } } op->state = state; } /** * Removes an operation from the ready queue. Also stops the 'process_rq_task' * if the given operation is the last one in the queue. * * @param op the operation to be removed */ static void rq_remove (struct GNUNET_TESTBED_Operation *op) { GNUNET_assert (NULL != op->rq_entry); GNUNET_CONTAINER_DLL_remove (rq_head, rq_tail, op->rq_entry); GNUNET_free (op->rq_entry); op->rq_entry = NULL; if ( (NULL == rq_head) && (GNUNET_SCHEDULER_NO_TASK != process_rq_task_id) ) { GNUNET_SCHEDULER_cancel (process_rq_task_id); process_rq_task_id = GNUNET_SCHEDULER_NO_TASK; } } /** * Processes the ready queue by calling the operation start callback of the * operation at the head. The operation is then removed from the queue. The * task is scheduled to run again immediately until no more operations are in * the ready queue. * * @param cls NULL * @param tc scheduler task context. Not used. */ static void process_rq_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TESTBED_Operation *op; struct OperationQueue *queue; unsigned int cnt; process_rq_task_id = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (NULL != rq_head); GNUNET_assert (NULL != (op = rq_head->op)); rq_remove (op); if (NULL != rq_head) process_rq_task_id = GNUNET_SCHEDULER_add_now (&process_rq_task, NULL); change_state (op, OP_STATE_ACTIVE); for (cnt = 0; cnt < op->nqueues; cnt++) { queue = op->queues[cnt]; if (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type) assign_timeslot (op, queue); } op->tstart = GNUNET_TIME_absolute_get (); if (NULL != op->start) op->start (op->cb_cls); } /** * Adds the operation to the ready queue and starts the 'process_rq_task' * * @param op the operation to be queued */ static void rq_add (struct GNUNET_TESTBED_Operation *op) { struct ReadyQueueEntry *rq_entry; GNUNET_assert (NULL == op->rq_entry); rq_entry = GNUNET_new (struct ReadyQueueEntry); rq_entry->op = op; GNUNET_CONTAINER_DLL_insert_tail (rq_head, rq_tail, rq_entry); op->rq_entry = rq_entry; if (GNUNET_SCHEDULER_NO_TASK == process_rq_task_id) process_rq_task_id = GNUNET_SCHEDULER_add_now (&process_rq_task, NULL); } /** * Checks if the given operation queue is empty or not * * @param opq the operation queue * @return GNUNET_YES if the given operation queue has no operations; GNUNET_NO * otherwise */ static int is_queue_empty (struct OperationQueue *opq) { if ( (NULL != opq->wq_head) || (NULL != opq->rq_head) || (NULL != opq->aq_head) || (NULL != opq->nq_head) ) return GNUNET_NO; return GNUNET_YES; } /** * Checks if the given operation queue has enough resources to provide for the * operation of the given queue entry. It also checks if any inactive * operations are to be released in order to accommodate the needed resources * and returns them as an array. * * @param opq the operation queue to check for resource accommodation * @param entry the operation queue entry whose operation's resources are to be * accommodated * @param ops_ pointer to return the array of operations which are to be released * in order to accommodate the new operation. Can be NULL * @param n_ops_ the number of operations in ops_ * @return GNUNET_YES if the given entry's operation can be accommodated in this * queue. GNUNET_NO if it cannot be accommodated; ops_ and n_ops_ will * be set to NULL and 0 respectively. */ static int decide_capacity (struct OperationQueue *opq, struct QueueEntry *entry, struct GNUNET_TESTBED_Operation ***ops_, unsigned int *n_ops_) { struct QueueEntry **evict_entries; struct GNUNET_TESTBED_Operation **ops; struct GNUNET_TESTBED_Operation *op; unsigned int n_ops; unsigned int n_evict_entries; unsigned int need; unsigned int max; int deficit; int rval; GNUNET_assert (NULL != (op = entry->op)); GNUNET_assert (0 < (need = entry->nres)); ops = NULL; n_ops = 0; evict_entries = NULL; n_evict_entries = 0; rval = GNUNET_YES; if (OPERATION_QUEUE_TYPE_ADAPTIVE == opq->type) { GNUNET_assert (NULL != opq->fctx); GNUNET_assert (opq->max_active >= opq->overload); max = opq->max_active - opq->overload; } else max = opq->max_active; if (opq->active > max) { rval = GNUNET_NO; goto ret; } if ((opq->active + need) <= max) goto ret; deficit = need - (max - opq->active); for (entry = opq->nq_head; (0 < deficit) && (NULL != entry); entry = entry->next) { GNUNET_array_append (evict_entries, n_evict_entries, entry); deficit -= entry->nres; } if (0 < deficit) { rval = GNUNET_NO; goto ret; } for (n_ops = 0; n_ops < n_evict_entries;) { op = evict_entries[n_ops]->op; GNUNET_array_append (ops, n_ops, op); /* increments n-ops */ } ret: GNUNET_free_non_null (evict_entries); if (NULL != ops_) *ops_ = ops; else GNUNET_free (ops); if (NULL != n_ops_) *n_ops_ = n_ops; return rval; } /** * Merges an array of operations into another, eliminating duplicates. No * ordering is guaranteed. * * @param old the array into which the merging is done. * @param n_old the number of operations in old array * @param new the array from which operations are to be merged * @param n_new the number of operations in new array */ static void merge_ops (struct GNUNET_TESTBED_Operation ***old, unsigned int *n_old, struct GNUNET_TESTBED_Operation **new, unsigned int n_new) { struct GNUNET_TESTBED_Operation **cur; unsigned int i; unsigned int j; unsigned int n_cur; GNUNET_assert (NULL != old); n_cur = *n_old; cur = *old; for (i = 0; i < n_new; i++) { for (j = 0; j < *n_old; j++) { if (new[i] == cur[j]) break; } if (j < *n_old) continue; GNUNET_array_append (cur, n_cur, new[j]); } *old = cur; *n_old = n_cur; } /** * Checks for the readiness of an operation and schedules a operation start task * * @param op the operation */ static int check_readiness (struct GNUNET_TESTBED_Operation *op) { struct GNUNET_TESTBED_Operation **evict_ops; struct GNUNET_TESTBED_Operation **ops; unsigned int n_ops; unsigned int n_evict_ops; unsigned int i; GNUNET_assert (NULL == op->rq_entry); GNUNET_assert (OP_STATE_WAITING == op->state); evict_ops = NULL; n_evict_ops = 0; for (i = 0; i < op->nqueues; i++) { ops = NULL; n_ops = 0; if (GNUNET_NO == decide_capacity (op->queues[i], op->qentries[i], &ops, &n_ops)) { GNUNET_free_non_null (evict_ops); return GNUNET_NO; } if (NULL == ops) continue; merge_ops (&evict_ops, &n_evict_ops, ops, n_ops); GNUNET_free (ops); } if (NULL != evict_ops) { for (i = 0; i < n_evict_ops; i++) GNUNET_TESTBED_operation_release_ (evict_ops[i]); GNUNET_free (evict_ops); evict_ops = NULL; /* Evicting the operations should schedule this operation */ GNUNET_assert (OP_STATE_READY == op->state); return GNUNET_YES; } for (i = 0; i < op->nqueues; i++) op->queues[i]->active += op->nres[i]; change_state (op, OP_STATE_READY); rq_add (op); return GNUNET_YES; } /** * Defers a ready to be executed operation back to waiting * * @param op the operation to defer */ static void defer (struct GNUNET_TESTBED_Operation *op) { unsigned int i; GNUNET_assert (OP_STATE_READY == op->state); rq_remove (op); for (i = 0; i < op->nqueues; i++) { GNUNET_assert (op->queues[i]->active >= op->nres[i]); op->queues[i]->active -= op->nres[i]; } change_state (op, OP_STATE_WAITING); } /** * Cleanups the array of timeslots of an operation queue. For each time slot in * the array, if it is allocated to an operation, it will be deallocated from * the operation * * @param queue the operation queue */ static void cleanup_tslots (struct OperationQueue *queue) { struct FeedbackCtx *fctx = queue->fctx; struct TimeSlot *tslot; struct GNUNET_TESTBED_Operation *op; unsigned int cnt; GNUNET_assert (NULL != fctx); for (cnt = 0; cnt < queue->max_active; cnt++) { tslot = &fctx->tslots_freeptr[cnt]; op = tslot->op; if (NULL == op) continue; GNUNET_CONTAINER_DLL_remove (op->tslots_head, op->tslots_tail, tslot); } GNUNET_free_non_null (fctx->tslots_freeptr); fctx->tslots_freeptr = NULL; fctx->alloc_head = NULL; fctx->alloc_tail = NULL; fctx->tslots_filled = 0; } /** * Cleansup the existing timing slots and sets new timing slots in the given * queue to accommodate given number of max active operations. * * @param queue the queue * @param n the number of maximum active operations. If n is greater than the * maximum limit set while creating the queue, then the minimum of these two * will be selected as n */ static void adaptive_queue_set_max_active (struct OperationQueue *queue, unsigned int n) { struct FeedbackCtx *fctx = queue->fctx; struct TimeSlot *tslot; unsigned int cnt; cleanup_tslots (queue); n = GNUNET_MIN (n ,fctx->max_active_bound); fctx->tslots_freeptr = GNUNET_malloc (n * sizeof (struct TimeSlot)); fctx->nfailed = 0; FPRINTF (stderr, "Parallelism: %u\n", n); for (cnt = 0; cnt < n; cnt++) { tslot = &fctx->tslots_freeptr[cnt]; tslot->queue = queue; GNUNET_CONTAINER_DLL_insert_tail (fctx->alloc_head, fctx->alloc_tail, tslot); } GNUNET_TESTBED_operation_queue_reset_max_active_ (queue, n); } /** * Adapts parallelism in an adaptive queue by using the statistical data from * the feedback context. * * @param queue the queue */ static void adapt_parallelism (struct OperationQueue *queue) { struct GNUNET_TIME_Relative avg; struct FeedbackCtx *fctx; struct TimeSlot *tslot; int sd; unsigned int nvals; unsigned int cnt; unsigned int parallelism; avg = GNUNET_TIME_UNIT_ZERO; nvals = 0; fctx = queue->fctx; for (cnt = 0; cnt < queue->max_active; cnt++) { tslot = &fctx->tslots_freeptr[cnt]; avg = GNUNET_TIME_relative_add (avg, tslot->tsum); nvals += tslot->nvals; } GNUNET_assert (nvals >= queue->max_active); GNUNET_assert (fctx->nfailed <= nvals); nvals -= fctx->nfailed; if (0 == nvals) { if (1 == queue->max_active) adaptive_queue_set_max_active (queue, 1); else adaptive_queue_set_max_active (queue, queue->max_active / 2); return; } avg = GNUNET_TIME_relative_divide (avg, nvals); GNUNET_TESTBED_SD_add_data_ (fctx->sd, (unsigned int) avg.rel_value_us); if (GNUNET_SYSERR == GNUNET_TESTBED_SD_deviation_factor_ (fctx->sd, (unsigned int) avg.rel_value_us, &sd)) { adaptive_queue_set_max_active (queue, queue->max_active); /* no change */ return; } parallelism = 0; if (-1 == sd) parallelism = queue->max_active + 1; if (sd <= -2) parallelism = queue->max_active * 2; if (1 == sd) parallelism = queue->max_active - 1; if (2 <= sd) parallelism = queue->max_active / 2; parallelism = GNUNET_MAX (parallelism, ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE); adaptive_queue_set_max_active (queue, parallelism); #if 0 /* old algorithm */ if (sd < 0) sd = 0; GNUNET_assert (0 <= sd); //GNUNET_TESTBED_SD_add_data_ (fctx->sd, (unsigned int) avg.rel_value_us); if (0 == sd) { adaptive_queue_set_max_active (queue, queue->max_active * 2); return; } if (1 == sd) { adaptive_queue_set_max_active (queue, queue->max_active + 1); return; } if (1 == queue->max_active) { adaptive_queue_set_max_active (queue, 1); return; } if (2 == sd) { adaptive_queue_set_max_active (queue, queue->max_active - 1); return; } adaptive_queue_set_max_active (queue, queue->max_active / 2); #endif } /** * update tslots with the operation's completion time. Additionally, if * updating a timeslot makes all timeslots filled in an adaptive operation * queue, call adapt_parallelism() for that queue. * * @param op the operation */ static void update_tslots (struct GNUNET_TESTBED_Operation *op) { struct OperationQueue *queue; struct GNUNET_TIME_Relative t; struct TimeSlot *tslot; struct FeedbackCtx *fctx; unsigned int i; t = GNUNET_TIME_absolute_get_duration (op->tstart); while (NULL != (tslot = op->tslots_head)) /* update time slots */ { queue = tslot->queue; fctx = queue->fctx; GNUNET_CONTAINER_DLL_remove (op->tslots_head, op->tslots_tail, tslot); tslot->op = NULL; GNUNET_CONTAINER_DLL_insert_tail (fctx->alloc_head, fctx->alloc_tail, tslot); if (op->failed) { fctx->nfailed++; for (i = 0; i < op->nqueues; i++) if (queue == op->queues[i]) break; GNUNET_assert (i != op->nqueues); op->queues[i]->overload += op->nres[i]; } tslot->tsum = GNUNET_TIME_relative_add (tslot->tsum, t); if (0 != tslot->nvals++) continue; fctx->tslots_filled++; if (queue->max_active == fctx->tslots_filled) adapt_parallelism (queue); } } /** * Create an 'operation' to be performed. * * @param cls closure for the callbacks * @param start function to call to start the operation * @param release function to call to close down the operation * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_operation_create_ (void *cls, OperationStart start, OperationRelease release) { struct GNUNET_TESTBED_Operation *op; op = GNUNET_new (struct GNUNET_TESTBED_Operation); op->start = start; op->state = OP_STATE_INIT; op->release = release; op->cb_cls = cls; return op; } /** * Create an operation queue. * * @param type the type of operation queue * @param max_active maximum number of operations in this * queue that can be active in parallel at the same time * @return handle to the queue */ struct OperationQueue * GNUNET_TESTBED_operation_queue_create_ (enum OperationQueueType type, unsigned int max_active) { struct OperationQueue *queue; struct FeedbackCtx *fctx; queue = GNUNET_new (struct OperationQueue); queue->type = type; if (OPERATION_QUEUE_TYPE_FIXED == type) { queue->max_active = max_active; } else { fctx = GNUNET_new (struct FeedbackCtx); fctx->max_active_bound = max_active; fctx->sd = GNUNET_TESTBED_SD_init_ (ADAPTIVE_QUEUE_DEFAULT_HISTORY); queue->fctx = fctx; adaptive_queue_set_max_active (queue, ADAPTIVE_QUEUE_DEFAULT_MAX_ACTIVE); } return queue; } /** * Destroy an operation queue. The queue MUST be empty * at this time. * * @param queue queue to destroy */ void GNUNET_TESTBED_operation_queue_destroy_ (struct OperationQueue *queue) { struct FeedbackCtx *fctx; GNUNET_break (GNUNET_YES == is_queue_empty (queue)); if (OPERATION_QUEUE_TYPE_ADAPTIVE == queue->type) { cleanup_tslots (queue); fctx = queue->fctx; GNUNET_TESTBED_SD_destroy_ (fctx->sd); GNUNET_free (fctx); } GNUNET_free (queue); } /** * Destroys the operation queue if it is empty. If not empty return GNUNET_NO. * * @param queue the queue to destroy if empty * @return GNUNET_YES if the queue is destroyed. GNUNET_NO if not (because it * is not empty) */ int GNUNET_TESTBED_operation_queue_destroy_empty_ (struct OperationQueue *queue) { if (GNUNET_NO == is_queue_empty (queue)) return GNUNET_NO; GNUNET_TESTBED_operation_queue_destroy_ (queue); return GNUNET_YES; } /** * Rechecks if any of the operations in the given operation queue's waiting list * can be made active * * @param opq the operation queue */ static void recheck_waiting (struct OperationQueue *opq) { struct QueueEntry *entry; struct QueueEntry *entry2; entry = opq->wq_head; while (NULL != entry) { entry2 = entry->next; if (GNUNET_NO == check_readiness (entry->op)) break; entry = entry2; } } /** * Function to reset the maximum number of operations in the given queue. If * max_active is lesser than the number of currently active operations, the * active operations are not stopped immediately. * * @param queue the operation queue which has to be modified * @param max_active the new maximum number of active operations */ void GNUNET_TESTBED_operation_queue_reset_max_active_ (struct OperationQueue *queue, unsigned int max_active) { struct QueueEntry *entry; queue->max_active = max_active; queue->overload = 0; while ( (queue->active > queue->max_active) && (NULL != (entry = queue->rq_head)) ) defer (entry->op); recheck_waiting (queue); } /** * Add an operation to a queue. An operation can be in multiple queues at * once. Once the operation is inserted into all the queues * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start * waiting for the operation to become active. * * @param queue queue to add the operation to * @param op operation to add to the queue * @param nres the number of units of the resources of queue needed by the * operation. Should be greater than 0. */ void GNUNET_TESTBED_operation_queue_insert2_ (struct OperationQueue *queue, struct GNUNET_TESTBED_Operation *op, unsigned int nres) { unsigned int qsize; GNUNET_assert (0 < nres); qsize = op->nqueues; GNUNET_array_append (op->queues, op->nqueues, queue); GNUNET_array_append (op->nres, qsize, nres); GNUNET_assert (qsize == op->nqueues); } /** * Add an operation to a queue. An operation can be in multiple queues at * once. Once the operation is inserted into all the queues * GNUNET_TESTBED_operation_begin_wait_() has to be called to actually start * waiting for the operation to become active. The operation is assumed to take * 1 queue resource. Use GNUNET_TESTBED_operation_queue_insert2_() if it * requires more than 1 * * @param queue queue to add the operation to * @param op operation to add to the queue */ void GNUNET_TESTBED_operation_queue_insert_ (struct OperationQueue *queue, struct GNUNET_TESTBED_Operation *op) { return GNUNET_TESTBED_operation_queue_insert2_ (queue, op, 1); } /** * Marks the given operation as waiting on the queues. Once all queues permit * the operation to become active, the operation will be activated. The actual * activation will occur in a separate task (thus allowing multiple queue * insertions to be made without having the first one instantly trigger the * operation if the first queue has sufficient resources). * * @param op the operation to marks as waiting */ void GNUNET_TESTBED_operation_begin_wait_ (struct GNUNET_TESTBED_Operation *op) { GNUNET_assert (NULL == op->rq_entry); change_state (op, OP_STATE_WAITING); (void) check_readiness (op); } /** * Marks an active operation as inactive - the operation will be kept in a * ready-to-be-released state and continues to hold resources until another * operation contents for them. * * @param op the operation to be marked as inactive. The operation start * callback should have been called before for this operation to mark * it as inactive. */ void GNUNET_TESTBED_operation_inactivate_ (struct GNUNET_TESTBED_Operation *op) { struct OperationQueue **queues; size_t ms; unsigned int nqueues; unsigned int i; GNUNET_assert (OP_STATE_ACTIVE == op->state); change_state (op, OP_STATE_INACTIVE); nqueues = op->nqueues; ms = sizeof (struct OperationQueue *) * nqueues; queues = GNUNET_malloc (ms); /* Cloning is needed as the operation be released by waiting operations and hence its nqueues memory ptr will be freed */ GNUNET_assert (NULL != (queues = memcpy (queues, op->queues, ms))); for (i = 0; i < nqueues; i++) recheck_waiting (queues[i]); GNUNET_free (queues); } /** * Marks and inactive operation as active. This fuction should be called to * ensure that the oprelease callback will not be called until it is either * marked as inactive or released. * * @param op the operation to be marked as active */ void GNUNET_TESTBED_operation_activate_ (struct GNUNET_TESTBED_Operation *op) { GNUNET_assert (OP_STATE_INACTIVE == op->state); change_state (op, OP_STATE_ACTIVE); } /** * An operation is 'done' (was cancelled or finished); remove * it from the queues and release associated resources. * * @param op operation that finished */ void GNUNET_TESTBED_operation_release_ (struct GNUNET_TESTBED_Operation *op) { struct QueueEntry *entry; struct OperationQueue *opq; unsigned int i; if (OP_STATE_INIT == op->state) { GNUNET_free (op); return; } if (OP_STATE_READY == op->state) rq_remove (op); if (OP_STATE_INACTIVE == op->state) /* Activate the operation if inactive */ GNUNET_TESTBED_operation_activate_ (op); if (OP_STATE_ACTIVE == op->state) update_tslots (op); GNUNET_assert (NULL != op->queues); GNUNET_assert (NULL != op->qentries); for (i = 0; i < op->nqueues; i++) { entry = op->qentries[i]; remove_queue_entry (op, i); opq = op->queues[i]; switch (op->state) { case OP_STATE_INIT: case OP_STATE_INACTIVE: GNUNET_assert (0); break; case OP_STATE_WAITING: break; case OP_STATE_ACTIVE: case OP_STATE_READY: GNUNET_assert (0 != opq->active); GNUNET_assert (opq->active >= entry->nres); opq->active -= entry->nres; recheck_waiting (opq); break; } GNUNET_free (entry); } GNUNET_free_non_null (op->qentries); GNUNET_free (op->queues); GNUNET_free (op->nres); if (NULL != op->release) op->release (op->cb_cls); GNUNET_free (op); } /** * Marks an operation as failed * * @param op the operation to be marked as failed */ void GNUNET_TESTBED_operation_mark_failed (struct GNUNET_TESTBED_Operation *op) { op->failed = GNUNET_YES; } /* end of testbed_api_operations.c */ gnunet-0.10.1/src/testbed/gnunet-daemon-testbed-blacklist.c0000644000175000017500000001622512230201042020526 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-daemon-testbed-blacklist.c * @brief daemon to restrict incoming connections from other peers at the * transport layer of a peer * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" /** * Logging shorthand */ #define LOG(type,...) \ GNUNET_log (type, __VA_ARGS__) /** * Debug logging shorthand */ #define DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * Allow access from the peers read from the whitelist */ #define ACCESS_ALLOW 1 /** * Deny access from the peers read from the blacklist */ #define ACCESS_DENY 0 /** * The map to store the peer identities to allow/deny */ static struct GNUNET_CONTAINER_MultiPeerMap *map; /** * The array of peer identities we read from whitelist/blacklist */ static struct GNUNET_PeerIdentity *ilist; /** * The blacklist handle we obtain from transport when we register ourselves for * access control */ struct GNUNET_TRANSPORT_Blacklist *bh; /** * Task for shutdown */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Are we allowing or denying access from peers */ static int mode; /** * @ingroup hashmap * Iterator over hash map entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key, value)); return GNUNET_YES; } /** * Cleaup and destroy the map */ static void cleanup_map () { if (NULL != map) { GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_iterate (map, &iterator, NULL)); GNUNET_CONTAINER_multipeermap_destroy (map); map = NULL; } } /** * Shutdown task to cleanup our resources and exit. * * @param cls NULL * @param tc scheduler task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup_map (); if (NULL != bh) GNUNET_TRANSPORT_blacklist_cancel (bh); } /** * Function that decides if a connection is acceptable or not. * * @param cls closure * @param pid peer to approve or disapproave * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not */ static int check_access (void *cls, const struct GNUNET_PeerIdentity * pid) { int contains; if (NULL != map) contains = GNUNET_CONTAINER_multipeermap_contains (map, pid); else contains = GNUNET_NO; if (ACCESS_DENY == mode) return (contains) ? GNUNET_SYSERR : GNUNET_OK; return (contains) ? GNUNET_OK : GNUNET_SYSERR; } /** * Setup the access control by reading the given file containing peer identities * and then establishing blacklist handler with the peer's transport service * * @param fname the filename to read the list of peer identities * @param cfg the configuration for connecting to the peer's transport service */ static void setup_ac (const char *fname, const struct GNUNET_CONFIGURATION_Handle *cfg) { uint64_t fsize; unsigned int npeers; unsigned int cnt; GNUNET_assert (GNUNET_OK != GNUNET_DISK_file_size (fname, &fsize, GNUNET_NO, GNUNET_YES)); if (0 != (fsize % sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); return; } npeers = fsize / sizeof (struct GNUNET_PeerIdentity); if (0 != npeers) { map = GNUNET_CONTAINER_multipeermap_create (npeers, GNUNET_YES); ilist = GNUNET_malloc_large (fsize); GNUNET_assert (fsize == GNUNET_DISK_fn_read (fname, ilist, fsize)); } for (cnt = 0; cnt < npeers; cnt++) { if (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_put (map, &ilist[cnt], &ilist[cnt], GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { cleanup_map (); GNUNET_free (ilist); return; } } shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); bh = GNUNET_TRANSPORT_blacklist (cfg, &check_access, NULL); } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char *shome; char fname[PATH_MAX]; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "PATHS", "GNUNET_HOME", &shome)) { GNUNET_break (0); return; } GNUNET_assert (0 < GNUNET_snprintf (fname, PATH_MAX, "%s/whitelist", shome)); if (GNUNET_YES == GNUNET_DISK_file_test (fname)) { mode = ACCESS_ALLOW; setup_ac (fname, c); GNUNET_free (shome); return; } GNUNET_assert (0 < GNUNET_snprintf (fname, PATH_MAX, "%s/blacklist", shome)); if (GNUNET_YES == GNUNET_DISK_file_test (fname)) { mode = ACCESS_DENY; setup_ac (shome, c); } GNUNET_free (shome); return; } /** * The main function. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-testbed-blacklist", _ ("Daemon to restrict incoming transport layer connections during testbed deployments"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } gnunet-0.10.1/src/testbed/testbed_api_peers.c0000644000175000017500000007257212255010512016066 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_peers.c * @brief management of the knowledge about peers in this library * (we know the peer ID, its host, pending operations, etc.) * @author Christian Grothoff * @author Sree Harsha Totakura */ #include "platform.h" #include "testbed_api_peers.h" #include "testbed_api.h" #include "testbed.h" #include "testbed_api_hosts.h" #include "testbed_api_operations.h" /** * Peer list DLL head */ static struct GNUNET_TESTBED_Peer *peer_list_head; /** * Peer list DLL tail */ static struct GNUNET_TESTBED_Peer *peer_list_tail; /** * Adds a peer to the peer list * * @param peer the peer to add to the peer list */ void GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer) { GNUNET_CONTAINER_DLL_insert_tail (peer_list_head, peer_list_tail, peer); } /** * Removes a peer from the peer list * * @param peer the peer to remove */ void GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer) { GNUNET_CONTAINER_DLL_remove (peer_list_head, peer_list_tail, peer); } /** * Frees all peers */ void GNUNET_TESTBED_cleanup_peers_ (void) { struct GNUNET_TESTBED_Peer *peer; while (NULL != (peer = peer_list_head)) { GNUNET_TESTBED_peer_deregister_ (peer); GNUNET_free (peer); } } /** * Function to call to start a peer_create type operation once all * queues the operation is part of declare that the * operation can be activated. * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_peer_create (void *cls) { struct OperationContext *opc = cls; struct PeerCreateData *data = opc->data; struct GNUNET_TESTBED_PeerCreateMessage *msg; char *config; char *xconfig; size_t c_size; size_t xc_size; uint16_t msize; GNUNET_assert (OP_PEER_CREATE == opc->type); GNUNET_assert (NULL != data); GNUNET_assert (NULL != data->peer); opc->state = OPC_STATE_STARTED; config = GNUNET_CONFIGURATION_serialize (data->cfg, &c_size); xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig); GNUNET_free (config); msize = xc_size + sizeof (struct GNUNET_TESTBED_PeerCreateMessage); msg = GNUNET_realloc (xconfig, msize); memmove (&msg[1], msg, xc_size); msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER); msg->operation_id = GNUNET_htonll (opc->id); msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host)); msg->peer_id = htonl (data->peer->unique_id); msg->config_size = htons ((uint16_t) c_size); GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); } /** * Callback which will be called when peer_create type operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_peer_create (void *cls) { struct OperationContext *opc = cls; switch (opc->state) { case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); /* No break we continue flow */ case OPC_STATE_INIT: GNUNET_free (((struct PeerCreateData *) opc->data)->peer); GNUNET_free (opc->data); break; case OPC_STATE_FINISHED: break; } GNUNET_free (opc); } /** * Function called when a peer destroy operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_peer_destroy (void *cls) { struct OperationContext *opc = cls; struct GNUNET_TESTBED_Peer *peer = opc->data; struct GNUNET_TESTBED_PeerDestroyMessage *msg; GNUNET_assert (OP_PEER_DESTROY == opc->type); GNUNET_assert (NULL != peer); opc->state = OPC_STATE_STARTED; msg = GNUNET_new (struct GNUNET_TESTBED_PeerDestroyMessage); msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER); msg->peer_id = htonl (peer->unique_id); msg->operation_id = GNUNET_htonll (opc->id); GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header); } /** * Callback which will be called when peer_create type operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_peer_destroy (void *cls) { struct OperationContext *opc = cls; switch (opc->state) { case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); /* no break; continue */ case OPC_STATE_INIT: break; case OPC_STATE_FINISHED: break; } GNUNET_free (opc); } /** * Function called when a peer start operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_peer_start (void *cls) { struct OperationContext *opc = cls; struct GNUNET_TESTBED_PeerStartMessage *msg; struct PeerEventData *data; struct GNUNET_TESTBED_Peer *peer; GNUNET_assert (OP_PEER_START == opc->type); GNUNET_assert (NULL != (data = opc->data)); GNUNET_assert (NULL != (peer = data->peer)); GNUNET_assert ((TESTBED_PS_CREATED == peer->state) || (TESTBED_PS_STOPPED == peer->state)); opc->state = OPC_STATE_STARTED; msg = GNUNET_new (struct GNUNET_TESTBED_PeerStartMessage); msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStartMessage)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_START_PEER); msg->peer_id = htonl (peer->unique_id); msg->operation_id = GNUNET_htonll (opc->id); GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header); } /** * Callback which will be called when peer start type operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_peer_start (void *cls) { struct OperationContext *opc = cls; switch (opc->state) { case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); /* no break; continue */ case OPC_STATE_INIT: GNUNET_free (opc->data); break; case OPC_STATE_FINISHED: break; } GNUNET_free (opc); } /** * Function called when a peer stop operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_peer_stop (void *cls) { struct OperationContext *opc = cls; struct GNUNET_TESTBED_PeerStopMessage *msg; struct PeerEventData *data; struct GNUNET_TESTBED_Peer *peer; GNUNET_assert (NULL != (data = opc->data)); GNUNET_assert (NULL != (peer = data->peer)); GNUNET_assert (TESTBED_PS_STARTED == peer->state); opc->state = OPC_STATE_STARTED; msg = GNUNET_new (struct GNUNET_TESTBED_PeerStopMessage); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER); msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStopMessage)); msg->peer_id = htonl (peer->unique_id); msg->operation_id = GNUNET_htonll (opc->id); GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header); } /** * Callback which will be called when peer stop type operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_peer_stop (void *cls) { struct OperationContext *opc = cls; switch (opc->state) { case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); /* no break; continue */ case OPC_STATE_INIT: GNUNET_free (opc->data); break; case OPC_STATE_FINISHED: break; } GNUNET_free (opc); } /** * Generate PeerGetConfigurationMessage * * @param peer_id the id of the peer whose information we have to get * @param operation_id the ip of the operation that should be represented in the * message * @return the PeerGetConfigurationMessage */ struct GNUNET_TESTBED_PeerGetConfigurationMessage * GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id, uint64_t operation_id) { struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)); msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION); msg->peer_id = htonl (peer_id); msg->operation_id = GNUNET_htonll (operation_id); return msg; } /** * Function called when a peer get information operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_peer_getinfo (void *cls) { struct OperationContext *opc = cls; struct PeerInfoData *data = opc->data; struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; GNUNET_assert (NULL != data); opc->state = OPC_STATE_STARTED; msg = GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id, opc->id); GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); } /** * Callback which will be called when peer stop type operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_peer_getinfo (void *cls) { struct OperationContext *opc = cls; struct GNUNET_TESTBED_PeerInformation *data; switch (opc->state) { case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); /* no break; continue */ case OPC_STATE_INIT: GNUNET_free (opc->data); break; case OPC_STATE_FINISHED: data = opc->data; GNUNET_assert (NULL != data); switch (data->pit) { case GNUNET_TESTBED_PIT_CONFIGURATION: if (NULL != data->result.cfg) GNUNET_CONFIGURATION_destroy (data->result.cfg); break; case GNUNET_TESTBED_PIT_IDENTITY: GNUNET_free (data->result.id); break; default: GNUNET_assert (0); /* We should never reach here */ } GNUNET_free (data); break; } GNUNET_free (opc); } /** * Function called when a overlay connect operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_overlay_connect (void *cls) { struct OperationContext *opc = cls; struct GNUNET_TESTBED_OverlayConnectMessage *msg; struct OverlayConnectData *data; opc->state = OPC_STATE_STARTED; data = opc->data; GNUNET_assert (NULL != data); msg = GNUNET_new (struct GNUNET_TESTBED_OverlayConnectMessage); msg->header.size = htons (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT); msg->peer1 = htonl (data->p1->unique_id); msg->peer2 = htonl (data->p2->unique_id); msg->operation_id = GNUNET_htonll (opc->id); msg->peer2_host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->p2->host)); GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); } /** * Callback which will be called when overlay connect operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_overlay_connect (void *cls) { struct OperationContext *opc = cls; struct OverlayConnectData *data; data = opc->data; switch (opc->state) { case OPC_STATE_INIT: break; case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); break; case OPC_STATE_FINISHED: break; } GNUNET_free (data); GNUNET_free (opc); } /** * Function called when a peer reconfigure operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_peer_reconfigure (void *cls) { struct OperationContext *opc = cls; struct PeerReconfigureData *data = opc->data; struct GNUNET_TESTBED_PeerReconfigureMessage *msg; char *xconfig; size_t xc_size; uint16_t msize; opc->state = OPC_STATE_STARTED; GNUNET_assert (NULL != data); xc_size = GNUNET_TESTBED_compress_config_ (data->config, data->cfg_size, &xconfig); GNUNET_free (data->config); data->config = NULL; GNUNET_assert (xc_size <= UINT16_MAX); msize = (uint16_t) xc_size + sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage); msg = GNUNET_realloc (xconfig, msize); (void) memmove (&msg[1], msg, xc_size); msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER); msg->peer_id = htonl (data->peer->unique_id); msg->operation_id = GNUNET_htonll (opc->id); msg->config_size = htons (data->cfg_size); GNUNET_free (data); opc->data = NULL; GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); } /** * Callback which will be called when a peer reconfigure operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_peer_reconfigure (void *cls) { struct OperationContext *opc = cls; struct PeerReconfigureData *data = opc->data; switch (opc->state) { case OPC_STATE_INIT: GNUNET_free (data->config); GNUNET_free (data); break; case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); break; case OPC_STATE_FINISHED: break; } GNUNET_free (opc); } /** * Lookup a peer by ID. * * @param id global peer ID assigned to the peer * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Peer * GNUNET_TESTBED_peer_lookup_by_id_ (uint32_t id) { GNUNET_break (0); return NULL; } /** * Create the given peer at the specified host using the given * controller. If the given controller is not running on the target * host, it should find or create a controller at the target host and * delegate creating the peer. Explicit delegation paths can be setup * using 'GNUNET_TESTBED_controller_link'. If no explicit delegation * path exists, a direct link with a subordinate controller is setup * for the first delegated peer to a particular host; the subordinate * controller is then destroyed once the last peer that was delegated * to the remote host is stopped. * * Creating the peer only creates the handle to manipulate and further * configure the peer; use "GNUNET_TESTBED_peer_start" and * "GNUNET_TESTBED_peer_stop" to actually start/stop the peer's * processes. * * Note that the given configuration will be adjusted by the * controller to avoid port/path conflicts with other peers. * The "final" configuration can be obtained using * 'GNUNET_TESTBED_peer_get_information'. * * @param controller controller process to use * @param host host to run the peer on; cannot be NULL * @param cfg Template configuration to use for the peer. Should exist until * operation is cancelled or GNUNET_TESTBED_operation_done() is called * @param cb the callback to call when the peer has been created * @param cls the closure to the above callback * @return the operation handle */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_create (struct GNUNET_TESTBED_Controller *controller, struct GNUNET_TESTBED_Host *host, const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_TESTBED_PeerCreateCallback cb, void *cls) { struct GNUNET_TESTBED_Peer *peer; struct PeerCreateData *data; struct OperationContext *opc; static uint32_t id_gen; peer = GNUNET_new (struct GNUNET_TESTBED_Peer); peer->controller = controller; peer->host = host; peer->unique_id = id_gen++; peer->state = TESTBED_PS_INVALID; data = GNUNET_new (struct PeerCreateData); data->host = host; data->cfg = cfg; data->cb = cb; data->cls = cls; data->peer = peer; opc = GNUNET_new (struct OperationContext); opc->c = controller; opc->data = data; opc->id = GNUNET_TESTBED_get_next_op_id (controller); opc->type = OP_PEER_CREATE; opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_create, &oprelease_peer_create); GNUNET_TESTBED_operation_queue_insert_ (controller->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Start the given peer. * * @param op_cls the closure for this operation; will be set in * event->details.operation_finished.op_cls when this operation fails. * @param peer peer to start * @param pcc function to call upon completion * @param pcc_cls closure for 'pcc' * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_start (void *op_cls, struct GNUNET_TESTBED_Peer *peer, GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls) { struct OperationContext *opc; struct PeerEventData *data; data = GNUNET_new (struct PeerEventData); data->peer = peer; data->pcc = pcc; data->pcc_cls = pcc_cls; opc = GNUNET_new (struct OperationContext); opc->c = peer->controller; opc->data = data; opc->op_cls = op_cls; opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); opc->type = OP_PEER_START; opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_start, &oprelease_peer_start); GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Stop the given peer. The handle remains valid (use * "GNUNET_TESTBED_peer_destroy" to fully clean up the * state of the peer). * * @param op_cls the closure for this operation; will be set in the event * information * @param peer peer to stop * @param pcc function to call upon completion * @param pcc_cls closure for 'pcc' * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_stop (void *op_cls, struct GNUNET_TESTBED_Peer *peer, GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls) { struct OperationContext *opc; struct PeerEventData *data; data = GNUNET_new (struct PeerEventData); data->peer = peer; data->pcc = pcc; data->pcc_cls = pcc_cls; opc = GNUNET_new (struct OperationContext); opc->c = peer->controller; opc->data = data; opc->op_cls = op_cls; opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); opc->type = OP_PEER_STOP; opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_stop, &oprelease_peer_stop); GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Request information about a peer. The controller callback will not be called * with event type GNUNET_TESTBED_ET_OPERATION_FINISHED when result for this * operation is available. Instead, the GNUNET_TESTBED_PeerInfoCallback() will * be called. * The peer information in the callback is valid until the operation is canceled. * * @param peer peer to request information about * @param pit desired information * @param cb the convenience callback to be called when results for this * operation are available * @param cb_cls the closure for the above callback * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer, enum GNUNET_TESTBED_PeerInformationType pit, GNUNET_TESTBED_PeerInfoCallback cb, void *cb_cls) { struct OperationContext *opc; struct PeerInfoData *data; GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit); GNUNET_assert (NULL != cb); data = GNUNET_new (struct PeerInfoData); data->peer = peer; data->pit = pit; data->cb = cb; data->cb_cls = cb_cls; opc = GNUNET_new (struct OperationContext); opc->c = peer->controller; opc->data = data; opc->type = OP_PEER_INFO; opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_getinfo, &oprelease_peer_getinfo); GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Change peer configuration. Must only be called while the * peer is stopped. Ports and paths cannot be changed this * way. * * @param peer peer to change configuration for * @param cfg new configuration (differences to existing * configuration only) * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct OperationContext *opc; struct PeerReconfigureData *data; size_t csize; data = GNUNET_new (struct PeerReconfigureData); data->peer = peer; data->config = GNUNET_CONFIGURATION_serialize (cfg, &csize); if (NULL == data->config) { GNUNET_free (data); return NULL; } if (csize > UINT16_MAX) { GNUNET_break (0); GNUNET_free (data->config); GNUNET_free (data); return NULL; } data->cfg_size = (uint16_t) csize; opc = GNUNET_new (struct OperationContext); opc->c = peer->controller; opc->data = data; opc->type = OP_PEER_RECONFIGURE; opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_reconfigure, &oprelease_peer_reconfigure); GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Destroy the given peer; the peer should have been * stopped first (if it was started). * * @param peer peer to stop * @return handle to the operation */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer) { struct OperationContext *opc; opc = GNUNET_new (struct OperationContext); opc->data = peer; opc->c = peer->controller; opc->id = GNUNET_TESTBED_get_next_op_id (peer->controller); opc->type = OP_PEER_DESTROY; opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_destroy, &oprelease_peer_destroy); GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Manipulate the P2P underlay topology by configuring a link * between two peers. * * @param op_cls closure argument to give with the operation event * @param p1 first peer * @param p2 second peer * @param co option to change * @param ... option-specific values * @return handle to the operation, NULL if configuring the link at this * time is not allowed */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_underlay_configure_link (void *op_cls, struct GNUNET_TESTBED_Peer *p1, struct GNUNET_TESTBED_Peer *p2, enum GNUNET_TESTBED_ConnectOption co, ...) { GNUNET_break (0); return NULL; } /** * Both peers must have been started before calling this function. * This function then obtains a HELLO from 'p1', gives it to 'p2' * and asks 'p2' to connect to 'p1'. * * @param op_cls closure argument to give with the operation event * @param cb the callback to call when this operation has finished * @param cb_cls the closure for the above callback * @param p1 first peer * @param p2 second peer * @return handle to the operation, NULL if connecting these two * peers is fundamentally not possible at this time (peers * not running or underlay disallows) */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_overlay_connect (void *op_cls, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls, struct GNUNET_TESTBED_Peer *p1, struct GNUNET_TESTBED_Peer *p2) { struct OperationContext *opc; struct OverlayConnectData *data; GNUNET_assert ((TESTBED_PS_STARTED == p1->state) && (TESTBED_PS_STARTED == p2->state)); data = GNUNET_new (struct OverlayConnectData); data->p1 = p1; data->p2 = p2; data->cb = cb; data->cb_cls = cb_cls; opc = GNUNET_new (struct OperationContext); opc->data = data; opc->c = p1->controller; opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); opc->type = OP_OVERLAY_CONNECT; opc->op_cls = op_cls; opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_overlay_connect, &oprelease_overlay_connect); GNUNET_TESTBED_host_queue_oc_ (p1->host, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /** * Function called when a peer manage service operation is ready * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void opstart_manage_service (void *cls) { struct OperationContext *opc = cls; struct ManageServiceData *data = opc->data; struct GNUNET_TESTBED_ManagePeerServiceMessage *msg; GNUNET_assert (NULL != data); msg = GNUNET_malloc (data->msize); msg->header.size = htons (data->msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE); msg->peer_id = htonl (data->peer->unique_id); msg->operation_id = GNUNET_htonll (opc->id); msg->start = (uint8_t) data->start; (void) memcpy (&msg[1], data->service_name, data->msize - sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage)); GNUNET_free (data->service_name); data->service_name = NULL; opc->state = OPC_STATE_STARTED; GNUNET_TESTBED_insert_opc_ (opc->c, opc); GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); } /** * Callback which will be called when peer manage server operation is released * * @param cls the closure from GNUNET_TESTBED_operation_create_() */ static void oprelease_manage_service (void *cls) { struct OperationContext *opc = cls; struct ManageServiceData *data; data = opc->data; switch (opc->state) { case OPC_STATE_STARTED: GNUNET_TESTBED_remove_opc_ (opc->c, opc); break; case OPC_STATE_INIT: GNUNET_assert (NULL != data); GNUNET_free (data->service_name); break; case OPC_STATE_FINISHED: break; } GNUNET_free_non_null (data); GNUNET_free (opc); } /** * Start or stop given service at a peer. This should not be called to * start/stop the peer's ARM service. Use GNUNET_TESTBED_peer_start(), * GNUNET_TESTBED_peer_stop() for starting/stopping peer's ARM service. Success * or failure of the generated operation is signalled through the controller * event callback and/or operation completion callback. * * @param op_cls the closure for the operation * @param peer the peer whose service is to be started/stopped * @param service_name the name of the service * @param cb the operation completion callback * @param cb_cls the closure for the operation completion callback * @param start 1 to start the service; 0 to stop the service * @return an operation handle; NULL upon error (peer not running) */ struct GNUNET_TESTBED_Operation * GNUNET_TESTBED_peer_manage_service (void *op_cls, struct GNUNET_TESTBED_Peer *peer, const char *service_name, GNUNET_TESTBED_OperationCompletionCallback cb, void *cb_cls, unsigned int start) { struct ManageServiceData *data; struct OperationContext *opc; size_t msize; GNUNET_assert (TESTBED_PS_STARTED == peer->state); /* peer is not running? */ msize = strlen (service_name) + 1; msize += sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage); if (GNUNET_SERVER_MAX_MESSAGE_SIZE < msize) return NULL; data = GNUNET_new (struct ManageServiceData); data->cb = cb; data->cb_cls = cb_cls; data->peer = peer; data->service_name = GNUNET_strdup (service_name); data->start = start; data->msize = (uint16_t) msize; opc = GNUNET_new (struct OperationContext); opc->data = data; opc->c = peer->controller; opc->id = GNUNET_TESTBED_get_next_op_id (opc->c); opc->type = OP_MANAGE_SERVICE; opc->op_cls = op_cls; opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_manage_service, &oprelease_manage_service); GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations, opc->op); GNUNET_TESTBED_operation_begin_wait_ (opc->op); return opc->op; } /* end of testbed_api_peers.c */ gnunet-0.10.1/src/testbed/testbed_api_hosts.h0000644000175000017500000001414712225777503016130 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/testbed_api_hosts.h * @brief internal API to access the 'hosts' subsystem * @author Christian Grothoff */ #ifndef NEW_TESTING_API_HOSTS_H #define NEW_TESTING_API_HOSTS_H //#include "gnunet_testbed_service.h" //#include "testbed_helper.h" #include "testbed.h" /** * Lookup a host by ID. * * @param id global host ID assigned to the host; 0 is * reserved to always mean 'localhost' * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id); /** * Create a host by ID; given this host handle, we could not * run peers at the host, but we can talk about the host * internally. * * @param id global host ID assigned to the host; 0 is * reserved to always mean 'localhost' * @param cfg the configuration to use as a template while starting a controller * on this host. Operation queue sizes specific to a host are also * read from this configuration handle * @return handle to the host, NULL on error */ struct GNUNET_TESTBED_Host * GNUNET_TESTBED_host_create_by_id_ (uint32_t id, const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Obtain a host's unique global ID. * * @param host handle to the host, NULL means 'localhost' * @return id global host ID assigned to the host (0 is * 'localhost', but then obviously not globally unique) */ uint32_t GNUNET_TESTBED_host_get_id_ (const struct GNUNET_TESTBED_Host *host); /** * Obtain the host's username * * @param host handle to the host, NULL means 'localhost' * @return username to login to the host */ const char * GNUNET_TESTBED_host_get_username_ (const struct GNUNET_TESTBED_Host *host); /** * Obtain the host's ssh port * * @param host handle to the host, NULL means 'localhost' * @return username to login to the host */ uint16_t GNUNET_TESTBED_host_get_ssh_port_ (const struct GNUNET_TESTBED_Host *host); /** * Obtain the host's configuration template * * @param host handle to the host * @return the host's configuration template */ const struct GNUNET_CONFIGURATION_Handle * GNUNET_TESTBED_host_get_cfg_ (const struct GNUNET_TESTBED_Host *host); /** * Function to replace host's configuration * * @param host the host handle * @param new_cfg the new configuration to replace the old one */ void GNUNET_TESTBED_host_replace_cfg_ (struct GNUNET_TESTBED_Host *host, const struct GNUNET_CONFIGURATION_Handle *new_cfg); /** * Marks a host as registered with a controller * * @param host the host to mark * @param controller the controller at which this host is registered */ void GNUNET_TESTBED_mark_host_registered_at_ (struct GNUNET_TESTBED_Host *host, const struct GNUNET_TESTBED_Controller *controller); /** * Unmarks a host registered at a controller * * @param host the host to unmark * @param controller the controller at which this host has to be unmarked */ void GNUNET_TESTBED_deregister_host_at_ (struct GNUNET_TESTBED_Host *host, const struct GNUNET_TESTBED_Controller *const controller); /** * Checks whether a host has been registered with the given controller * * @param host the host to check * @param controller the controller at which host's registration is checked * @return GNUNET_YES if registered; GNUNET_NO if not */ int GNUNET_TESTBED_is_host_registered_ (const struct GNUNET_TESTBED_Host *host, const struct GNUNET_TESTBED_Controller *controller); /** * Queues the given operation in the queue for parallel overlay connects of the * given host * * @param h the host handle * @param op the operation to queue in the given host's parally overlay connect * queue */ void GNUNET_TESTBED_host_queue_oc_ (struct GNUNET_TESTBED_Host *h, struct GNUNET_TESTBED_Operation *op); /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from * controller (testbed service) * * @param c the controller handler * @param msg message received * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if * not */ int GNUNET_TESTBED_host_handle_addhostconfirm_ (struct GNUNET_TESTBED_Controller *c, const struct GNUNET_TESTBED_HostConfirmedMessage *msg); /** * Sends termination signal to the controller's helper process * * @param cproc the handle to the controller's helper process */ void GNUNET_TESTBED_controller_kill_ (struct GNUNET_TESTBED_ControllerProc *cproc); /** * Cleans-up the controller's helper process handle * * @param cproc the handle to the controller's helper process */ void GNUNET_TESTBED_controller_destroy_ (struct GNUNET_TESTBED_ControllerProc *cproc); /** * Resolves the hostname of the host to an ip address * * @param host the host whose hostname is to be resolved */ void GNUNET_TESTBED_host_resolve_ (struct GNUNET_TESTBED_Host *host); #endif /* end of testbed_api_hosts.h */ gnunet-0.10.1/src/testbed/sample.job0000755000175000017500000000060712060057341014214 00000000000000#!/bin/bash # This job command file is called job.cmd #@ job_type = parallel #@ class = general #@ node = 1 #@ output = job$(jobid).out #@ error = job$(jobid).err #@ total_tasks=16 #@ wall_clock_limit = 0:0:1 #@ network.MPI = sn_all,not_shared,us ##@ ... other LoadLeveler keywords (see below) #@ notification = always #@ notify_user = totakura@in.tum.de #@ queue #@ executable = /bin/bash gnunet-0.10.1/src/testbed/gnunet-service-testbed_oc.c0000644000175000017500000015712112255010512017446 00000000000000/* This file is part of GNUnet. (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-service-testbed_oc.c * @brief code for handling overlay connect operations * @author Sree Harsha Totakura */ #include "gnunet-service-testbed.h" #include "gnunet-service-testbed_connectionpool.h" /** * Redefine LOG with a changed log component string */ #ifdef LOG #undef LOG #endif #define LOG(kind,...) \ GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__) /** * Context information for requesting TRANSPORT to connect to a peer */ struct TryConnectContext { /** * The identity of the peer to which the transport has to attempt a connection */ struct GNUNET_PeerIdentity *pid; /** * The transport handle obtained from cache. Do NOT close/disconnect. */ struct GNUNET_TRANSPORT_Handle *th_; /** * The GetCacheHandle for the p1th transport handle */ struct GST_ConnectionPool_GetHandle *cgh_th; /** * the try connect handle */ struct GNUNET_TRANSPORT_TryConnectHandle *tch; /** * The task handle */ GNUNET_SCHEDULER_TaskIdentifier task; /** * The id of the operation which is resposible for this context */ uint64_t op_id; /** * The number of times we attempted to connect */ unsigned int retries; }; /** * Types for context information we create for overlay connect requests */ enum OverlayConnectContextType { /** * This type is used if the overlay connection is local i.e. the connection * has to be made between local peers */ OCC_TYPE_LOCAL, /** * Type to be used when the first peer is local and the other peer is on a slave * controller started by us */ OCC_TYPE_REMOTE_SLAVE, /** * Type to be used when the first peer is local and the other peer is on a * controller which is not started by us. */ OCC_TYPE_REMOTE_LATERAL }; /** * Context data for operations on second peer in local overlay connection * contexts */ struct LocalPeer2Context { /** * The handle for offering the HELLO of the first peer to the second * peer. */ struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; /** * The transport TryConnectContext */ struct TryConnectContext tcc; }; /** * Context data for operations on second peer in remote overlay connection * contexts */ struct RemotePeer2Context { /** * Controller of peer 2; If OCC_TYPE_REMOTE_LATERAL is the type of overlay * connection then this can be NULL until the connection to the controller is * established */ struct GNUNET_TESTBED_Controller *p2c; /** * Operation context for the suboperation we start to get the identity of the * second peer */ struct OperationContext *opc; /** * Notification handle acquire to connect to a remote controller. Only used * if the type of overlay connection is OCC_TYPE_REMOTE_LATERAL. */ struct NeighbourConnectNotification *ncn; /** * The neighbour handle. Only used if the type of overlay connection is * OCC_TYPE_REMOTE_LATERAL. */ struct Neighbour *p2n; }; /** * Context information for connecting 2 peers in overlay. */ struct OverlayConnectContext { /** * The next pointer for maintaining a DLL of all OverlayConnectContexts */ struct OverlayConnectContext *next; /** * The prev pointer for maintaining a DLL of all OverlayConnectContexts */ struct OverlayConnectContext *prev; /** * The client which has requested for overlay connection. This is used to send * either a success of failure message */ struct GNUNET_SERVER_Client *client; /** * the first peer which is to expect an overlay connection from the second peer. */ struct Peer *peer; /** * Transport handle of the first peer obtained from cache to get its HELLO. Do * NOT close/disconnect. */ struct GNUNET_TRANSPORT_Handle *p1th_; /** * The #GST_ConnectionPool_GetHandle for the peer1's transport handle */ struct GST_ConnectionPool_GetHandle *cgh_p1th; /** * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE * level peer connects and to get our identity. */ struct GST_ConnectionPool_GetHandle *cgh_ch; /** * HELLO of the first peer. This should be sent to the second peer. */ struct GNUNET_MessageHeader *hello; /** * Get GetHelloHandle to acquire a HELLO of the first peer */ struct GNUNET_TRANSPORT_GetHelloHandle *ghh; /** * The error message we send if this overlay connect operation has timed out */ char *emsg; /** * Context information for operations on the second peer */ union { /** * Context information to be used if the second peer is local */ struct LocalPeer2Context local; /** * Context information to be used if the second peer is remote */ struct RemotePeer2Context remote; } p2ctx; /** * The peer identity of the first peer */ struct GNUNET_PeerIdentity peer_identity; /** * The peer identity of the other peer */ struct GNUNET_PeerIdentity other_peer_identity; /** * The id of the operation responsible for creating this context */ uint64_t op_id; /** * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to * connect to peer 2 */ GNUNET_SCHEDULER_TaskIdentifier send_hello_task; /** * The id of the overlay connect timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * The id of the cleanup task */ GNUNET_SCHEDULER_TaskIdentifier cleanup_task; /** * The type of this context information */ enum OverlayConnectContextType type; /** * The id of the second peer which is has to connect to the first peer */ uint32_t other_peer_id; }; /** * Context information for remote overlay connect operations. Remote overlay * connections are used when peers A and B reside on different hosts. In these * operations the host controller for peer B is asked by the host controller of * peer A to make peer B connect to peer A by sending the controller of peer B * the HELLO of peer A. */ struct RemoteOverlayConnectCtx { /** * the next pointer for DLL */ struct RemoteOverlayConnectCtx *next; /** * the prev pointer for DLL */ struct RemoteOverlayConnectCtx *prev; /** * The peer handle of peer B */ struct Peer *peer; /** * Peer A's HELLO */ struct GNUNET_MessageHeader *hello; /** * The handle for offering HELLO */ struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; /** * The transport try connect context */ struct TryConnectContext tcc; /** * The peer identity of peer A */ struct GNUNET_PeerIdentity a_id; /** * Task for offering HELLO of A to B and doing try_connect */ GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id; /** * Task to timeout RequestOverlayConnect */ GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id; /** * The id of the operation responsible for creating this context */ uint64_t op_id; }; /** * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown */ static struct OverlayConnectContext *occq_head; /** * DLL tail for OverlayConnectContext DLL */ static struct OverlayConnectContext *occq_tail; /** * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during * shutdown */ static struct RemoteOverlayConnectCtx *roccq_head; /** * DLL tail for RequectOverlayConnectContext DLL */ static struct RemoteOverlayConnectCtx *roccq_tail; /** * Cleans up ForwardedOverlayConnectContext * * @param focc the ForwardedOverlayConnectContext to cleanup */ void GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc) { GNUNET_SERVER_client_drop (focc->client); GNUNET_free_non_null (focc->orig_msg); GNUNET_free (focc); } /** * Timeout task for cancelling a forwarded overlay connect connect * * @param cls the ForwardedOverlayConnectContext * @param tc the task context from the scheduler */ static void forwarded_overlay_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ForwardedOperationContext *fopc = cls; struct RegisteredHostContext *rhc; struct ForwardedOverlayConnectContext *focc; rhc = fopc->cls; focc = rhc->focc_dll_head; GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc); LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1, focc->peer2); GST_cleanup_focc (focc); GST_forwarded_operation_timeout (fopc, tc); if (NULL != rhc->focc_dll_head) GST_process_next_focc (rhc); } /** * Callback to be called when forwarded overlay connection operation has a reply * from the sub-controller successfull. We have to relay the reply msg back to * the client * * @param cls ForwardedOperationContext * @param msg the peer create success message */ static void forwarded_overlay_connect_listener (void *cls, const struct GNUNET_MessageHeader *msg) { struct ForwardedOperationContext *fopc = cls; struct RegisteredHostContext *rhc; struct ForwardedOverlayConnectContext *focc; rhc = fopc->cls; GST_forwarded_operation_reply_relay (cls, msg); focc = rhc->focc_dll_head; GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc); GST_cleanup_focc (focc); if (NULL != rhc->focc_dll_head) GST_process_next_focc (rhc); } /** * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext * * @param rhc the RegisteredHostContext */ void GST_process_next_focc (struct RegisteredHostContext *rhc) { struct ForwardedOperationContext *fopc; struct ForwardedOverlayConnectContext *focc; struct Peer *peer; struct Slave *slave; focc = rhc->focc_dll_head; GNUNET_assert (NULL != focc); GNUNET_assert (RHC_DONE == rhc->state); GNUNET_assert (VALID_PEER_ID (focc->peer1)); peer = GST_peer_list[focc->peer1]; GNUNET_assert (GNUNET_YES == peer->is_remote); GNUNET_assert (NULL != (slave = peer->details.remote.slave)); fopc = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (focc->client); fopc->client = focc->client; fopc->operation_id = focc->operation_id; fopc->cls = rhc; fopc->type = OP_OVERLAY_CONNECT; fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (slave->controller, focc->operation_id, focc->orig_msg, &forwarded_overlay_connect_listener, fopc); GNUNET_free (focc->orig_msg); focc->orig_msg = NULL; fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout, fopc); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); } /** * Cleans up any used handles in local peer2 context * * @param lp2c the local peer2 context information */ static void cleanup_occ_lp2c (struct LocalPeer2Context *lp2c) { if (NULL != lp2c->ohh) GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh); if (NULL != lp2c->tcc.cgh_th) GST_connection_pool_get_handle_done (lp2c->tcc.cgh_th); if (NULL != lp2c->tcc.tch) GNUNET_TRANSPORT_try_connect_cancel (lp2c->tcc.tch); if (GNUNET_SCHEDULER_NO_TASK != lp2c->tcc.task) GNUNET_SCHEDULER_cancel (lp2c->tcc.task); } /** * Cleans up any used handles in remote peer2 context. Relinquishes the * remote controller connection if it has been established on-demand. * * @param rp2c the remote peer2 context information */ static void cleanup_occ_rp2c (struct RemotePeer2Context *rp2c) { if (NULL != rp2c->opc) GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc); if (NULL != rp2c->ncn) GST_neighbour_get_connection_cancel (rp2c->ncn); if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) ) GST_neighbour_release_connection (rp2c->p2n); } /** * Condition for checking if given peer is ready to be destroyed * * @param peer the peer to check */ #define PEER_EXPIRED(peer) \ ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) ) /** * Cleanup overlay connect context structure * * @param occ the overlay connect context */ static void cleanup_occ (struct OverlayConnectContext *occ) { struct Peer *peer2; LOG_DEBUG ("0x%llx: Cleaning up occ\n", occ->op_id); GNUNET_free_non_null (occ->emsg); GNUNET_free_non_null (occ->hello); GNUNET_SERVER_client_drop (occ->client); if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task) GNUNET_SCHEDULER_cancel (occ->send_hello_task); if (GNUNET_SCHEDULER_NO_TASK != occ->cleanup_task) GNUNET_SCHEDULER_cancel (occ->cleanup_task); if (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task) GNUNET_SCHEDULER_cancel (occ->timeout_task); if (NULL != occ->cgh_ch) GST_connection_pool_get_handle_done (occ->cgh_ch); if (NULL != occ->ghh) GNUNET_TRANSPORT_get_hello_cancel (occ->ghh); if (NULL != occ->cgh_p1th) GST_connection_pool_get_handle_done (occ->cgh_p1th); GNUNET_assert (NULL != GST_peer_list); GNUNET_assert (occ->peer->reference_cnt > 0); occ->peer->reference_cnt--; if (PEER_EXPIRED (occ->peer)) GST_destroy_peer (occ->peer); switch (occ->type) { case OCC_TYPE_LOCAL: peer2 = GST_peer_list[occ->other_peer_id]; GNUNET_assert (peer2->reference_cnt > 0); peer2->reference_cnt--; if (PEER_EXPIRED (peer2)) GST_destroy_peer (peer2); cleanup_occ_lp2c (&occ->p2ctx.local); break; case OCC_TYPE_REMOTE_SLAVE: case OCC_TYPE_REMOTE_LATERAL: cleanup_occ_rp2c (&occ->p2ctx.remote); break; } GNUNET_CONTAINER_DLL_remove (occq_head, occq_tail, occ); GNUNET_free (occ); } /** * Task for cleaing up overlay connect context structure * * @param cls the overlay connect context * @param tc the task context */ static void do_cleanup_occ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct OverlayConnectContext *occ = cls; occ->cleanup_task = GNUNET_SCHEDULER_NO_TASK; cleanup_occ (occ); } /** * Task which will be run when overlay connect request has been timed out * * @param cls the OverlayConnectContext * @param tc the TaskContext */ static void timeout_overlay_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct OverlayConnectContext *occ = cls; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task); occ->timeout_task = GNUNET_SCHEDULER_NO_TASK; /* LOG (GNUNET_ERROR_TYPE_WARNING, */ /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */ /* occ->peer->id, occ->other_peer_id, occ->emsg); */ GST_send_operation_fail_msg (occ->client, occ->op_id, occ->emsg); cleanup_occ (occ); } static void send_overlay_connect_success_msg (struct OverlayConnectContext *occ) { struct GNUNET_TESTBED_ConnectionEventMessage *msg; LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n", occ->op_id); msg = GNUNET_new (struct GNUNET_TESTBED_ConnectionEventMessage); msg->header.size = htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT); msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT); msg->peer1 = htonl (occ->peer->id); msg->peer2 = htonl (occ->other_peer_id); msg->operation_id = GNUNET_htonll (occ->op_id); GST_queue_message (occ->client, &msg->header); } /** * Function called to notify transport users that another * peer connected to us. * * @param cls closure * @param new_peer the peer that connected */ static void overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer) { struct OverlayConnectContext *occ = cls; struct LocalPeer2Context *lp2c; char *new_peer_str; char *other_peer_str; LOG_DEBUG ("Overlay connect notify\n"); if (0 == memcmp (new_peer, &occ->peer_identity, sizeof (struct GNUNET_PeerIdentity))) return; new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer)); other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); if (0 != memcmp (new_peer, &occ->other_peer_identity, sizeof (struct GNUNET_PeerIdentity))) { LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n", new_peer_str, other_peer_str); GNUNET_free (new_peer_str); GNUNET_free (other_peer_str); return; } GNUNET_free (new_peer_str); LOG_DEBUG ("0x%llx: Peer %4s connected to peer %4s\n", occ->op_id, other_peer_str, GNUNET_i2s (&occ->peer_identity)); GNUNET_free (other_peer_str); if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task) { GNUNET_SCHEDULER_cancel (occ->send_hello_task); occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task); GNUNET_SCHEDULER_cancel (occ->timeout_task); occ->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (OCC_TYPE_LOCAL == occ->type) { lp2c = &occ->p2ctx.local; if (GNUNET_SCHEDULER_NO_TASK != lp2c->tcc.task) { GNUNET_SCHEDULER_cancel (lp2c->tcc.task); lp2c->tcc.task = GNUNET_SCHEDULER_NO_TASK; } } GNUNET_free_non_null (occ->emsg); occ->emsg = NULL; send_overlay_connect_success_msg (occ); occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ); } /** * Task to ask transport of a peer to connect to another peer * * @param cls the TryConnectContext * @param tc the scheduler task context */ static void try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Callback to be called with result of the try connect request. * * @param cls the overlay connect context * @param result GNUNET_OK if message was transmitted to transport service * GNUNET_SYSERR if message was not transmitted to transport service */ static void try_connect_cb (void *cls, const int result) { struct TryConnectContext *tcc = cls; tcc->tch = NULL; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tcc->task); tcc->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500 + pow (2, ++tcc->retries)), &try_connect_task, tcc); } /** * Task to ask transport of a peer to connect to another peer * * @param cls the TryConnectContext * @param tc the scheduler task context */ static void try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TryConnectContext *tcc = cls; tcc->task = GNUNET_SCHEDULER_NO_TASK; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; GNUNET_assert (NULL == tcc->tch); GNUNET_assert (NULL != tcc->pid); GNUNET_assert (NULL != tcc->th_); GNUNET_assert (NULL != tcc->cgh_th); LOG_DEBUG ("0x%llx: Trail %u to connect to peer %4s\n", tcc->op_id, tcc->retries, GNUNET_i2s (tcc->pid)); tcc->tch = GNUNET_TRANSPORT_try_connect (tcc->th_, tcc->pid, &try_connect_cb, tcc); } /** * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to * peer 1. * * @param cls the OverlayConnectContext * @param tc the TaskContext from scheduler */ static void send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Task that is run when hello has been sent * * @param cls the overlay connect context * @param tc the scheduler task context; if tc->reason = * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if * GNUNET_SCHEDULER_REASON_READ_READY is succeeded */ static void occ_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct OverlayConnectContext *occ = cls; struct LocalPeer2Context *lp2c; GNUNET_assert (OCC_TYPE_LOCAL == occ->type); lp2c = &occ->p2ctx.local; lp2c->ohh = NULL; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->send_hello_task); if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason) { GNUNET_free_non_null (occ->emsg); GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to other peer", occ->op_id); occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); return; } if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason) return; GNUNET_free_non_null (occ->emsg); GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout during TRANSPORT_try_connect() " "at peer %4s", occ->op_id, GNUNET_i2s(&occ->other_peer_identity)); lp2c->tcc.pid = &occ->peer_identity; lp2c->tcc.op_id = occ->op_id; lp2c->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &lp2c->tcc); } /** * Sends the HELLO of peer1 to peer2's controller through remote overlay connect * request. * * @param occ the overlay connect context. Its type must be either * OCC_TYPE_REMOTE_SLAVE or OCC_TYPE_REMOTE_LATERAL */ void send_hello_thru_rocc (struct OverlayConnectContext *occ) { struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg; char *other_peer_str; uint16_t msize; uint16_t hello_size; GNUNET_assert (OCC_TYPE_LOCAL != occ->type); GNUNET_assert (NULL != occ->hello); other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote " "Overlay Request\n", occ->op_id, GNUNET_i2s (&occ->peer_identity), ntohs (occ->hello->size), other_peer_str); GNUNET_free (other_peer_str); hello_size = ntohs (occ->hello->size); msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size; msg = GNUNET_malloc (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT); msg->header.size = htons (msize); msg->peer = htonl (occ->other_peer_id); msg->operation_id = GNUNET_htonll (occ->op_id); (void) memcpy (&msg->peer_identity, &occ->peer_identity, sizeof (struct GNUNET_PeerIdentity)); memcpy (msg->hello, occ->hello, hello_size); GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c, &msg->header); } /** * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered * using its TRANSPORT connection; if remote the HELLO is sent remotely by using * send_hello_thru_rocc() * * @param cls the OverlayConnectContext * @param tc the TaskContext from scheduler */ static void send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct OverlayConnectContext *occ = cls; struct LocalPeer2Context *lp2c; char *other_peer_str; occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_assert (NULL != occ->hello); if (OCC_TYPE_LOCAL != occ->type) { send_hello_thru_rocc (occ); return; } lp2c = &occ->p2ctx.local; other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity)); LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", occ->op_id, GNUNET_i2s (&occ->peer_identity), other_peer_str); GNUNET_free (other_peer_str); lp2c->ohh = GNUNET_TRANSPORT_offer_hello (lp2c->tcc.th_, occ->hello, occ_hello_sent_cb, occ); if (NULL == lp2c->ohh) { GNUNET_break (0); occ->send_hello_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 500)), &send_hello, occ); } } /** * Callback from cache with needed handles set * * @param cls the closure passed to GST_cache_get_handle_transport() * @param ch the handle to CORE. Can be NULL if it is not requested * @param th the handle to TRANSPORT. Can be NULL if it is not requested * @param ignore_ peer identity which is ignored in this callback */ static void p2_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch, struct GNUNET_TRANSPORT_Handle *th, const struct GNUNET_PeerIdentity *ignore_) { struct OverlayConnectContext *occ = cls; GNUNET_assert (OCC_TYPE_LOCAL == occ->type); if (NULL == th) { GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s", occ->op_id, GNUNET_i2s (&occ->other_peer_identity)); GNUNET_SCHEDULER_cancel (occ->timeout_task); occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); return; } occ->p2ctx.local.tcc.th_ = th; GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s", occ->op_id, GNUNET_i2s (&occ->other_peer_identity)); occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); } /** * Connects to the transport of the other peer if it is a local peer and * schedules the send hello task * * @param occ the overlay connect context */ static void p2_transport_connect (struct OverlayConnectContext *occ) { struct Peer *peer2; GNUNET_assert (NULL == occ->emsg); GNUNET_assert (NULL != occ->hello); GNUNET_assert (NULL == occ->ghh); GNUNET_assert (NULL == occ->p1th_); GNUNET_assert (NULL == occ->cgh_p1th); if (OCC_TYPE_LOCAL == occ->type) { GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id])); occ->p2ctx.local.tcc.cgh_th = GST_connection_pool_get_handle (occ->other_peer_id, peer2->details.local.cfg, GST_CONNECTIONPOOL_SERVICE_TRANSPORT, &p2_transport_connect_cache_callback, occ, NULL, NULL, NULL); return; } GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s", occ->op_id, GNUNET_i2s (&occ->other_peer_identity)); occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ); } /** * Test for checking whether HELLO message is empty * * @param cls empty flag to set * @param address the HELLO * @param expiration expiration of the HELLO * @return */ static int test_address (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { int *empty = cls; *empty = GNUNET_NO; return GNUNET_OK; } /** * Function called whenever there is an update to the HELLO of peers in the * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1 * * @param cls closure * @param hello our updated HELLO */ static void hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello) { struct OverlayConnectContext *occ = cls; int empty; uint16_t msize; msize = ntohs (hello->size); empty = GNUNET_YES; (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) hello, GNUNET_NO, &test_address, &empty); if (GNUNET_YES == empty) { LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", occ->op_id, GNUNET_i2s (&occ->peer_identity)); return; } LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id, GNUNET_i2s (&occ->peer_identity)); occ->hello = GNUNET_malloc (msize); GST_cache_add_hello (occ->peer->id, hello); memcpy (occ->hello, hello, msize); GNUNET_TRANSPORT_get_hello_cancel (occ->ghh); occ->ghh = NULL; GST_connection_pool_get_handle_done (occ->cgh_p1th); occ->cgh_p1th = NULL; occ->p1th_ = NULL; GNUNET_free_non_null (occ->emsg); occ->emsg = NULL; p2_transport_connect (occ); } /** * Callback from cache with needed handles set * * @param cls the closure passed to GST_cache_get_handle_transport() * @param ch the handle to CORE. Can be NULL if it is not requested * @param th the handle to TRANSPORT. Can be NULL if it is not requested * @param ignore_ peer identity which is ignored in this callback */ static void p1_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch, struct GNUNET_TRANSPORT_Handle *th, const struct GNUNET_PeerIdentity *ignore_) { struct OverlayConnectContext *occ = cls; GNUNET_free_non_null (occ->emsg); occ->emsg = NULL; if (NULL == th) { GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s", occ->op_id, GNUNET_i2s (&occ->peer_identity)); GNUNET_SCHEDULER_cancel (occ->timeout_task); occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); return; } GNUNET_assert (NULL == occ->p1th_); GNUNET_assert (NULL != occ->cgh_p1th); occ->p1th_ = th; GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while acquiring HELLO of peer %4s", occ->op_id, GNUNET_i2s (&occ->peer_identity)); occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th_, &hello_update_cb, occ); } /** * Callback from cache with needed handles set * * @param cls the closure passed to GST_cache_get_handle_transport() * @param ch the handle to CORE. Can be NULL if it is not requested * @param th the handle to TRANSPORT. Can be NULL if it is not requested * @param my_identity the identity of our peer */ static void occ_cache_get_handle_core_cb (void *cls, struct GNUNET_CORE_Handle *ch, struct GNUNET_TRANSPORT_Handle *th, const struct GNUNET_PeerIdentity *my_identity) { struct OverlayConnectContext *occ = cls; const struct GNUNET_MessageHeader *hello; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task); GNUNET_free_non_null (occ->emsg); if ((NULL == ch) || (NULL == my_identity)) { GNUNET_asprintf (&occ->emsg, "0x%llx: Failed to connect to CORE of peer with " "id: %u", occ->op_id, occ->peer->id); GNUNET_SCHEDULER_cancel (occ->timeout_task); occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); return; } occ->emsg = NULL; if (GNUNET_YES == GNUNET_CORE_is_peer_connected_sync (ch, &occ->other_peer_identity)) { LOG_DEBUG ("0x%llx: Target peer already connected\n", occ->op_id); GNUNET_SCHEDULER_cancel (occ->timeout_task); occ->timeout_task = GNUNET_SCHEDULER_NO_TASK; send_overlay_connect_success_msg (occ); occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ); return; } memcpy (&occ->peer_identity, my_identity, sizeof (struct GNUNET_PeerIdentity)); LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id, GNUNET_i2s (&occ->peer_identity)); /* Lookup for HELLO in hello cache */ if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id))) { LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id, GNUNET_i2s (&occ->peer_identity)); occ->hello = GNUNET_copy_message (hello); p2_transport_connect (occ); return; } GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while acquiring TRANSPORT of %s from cache", occ->op_id, GNUNET_i2s (&occ->peer_identity)); occ->cgh_p1th = GST_connection_pool_get_handle (occ->peer->id, occ->peer->details.local.cfg, GST_CONNECTIONPOOL_SERVICE_TRANSPORT, p1_transport_connect_cache_callback, occ, NULL, NULL, NULL); } /** * Callback to be called when forwarded get peer config operation as part of * overlay connect is successfull. Connection to Peer 1's core is made and is * checked for new connection from peer 2 * * @param cls ForwardedOperationContext * @param msg the peer create success message */ static void overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg) { struct OverlayConnectContext *occ = cls; struct RemotePeer2Context *rp2c; const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg; GNUNET_assert (OCC_TYPE_LOCAL != occ->type); rp2c = &occ->p2ctx.remote; rp2c->opc = NULL; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task); if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type)) { GNUNET_SCHEDULER_cancel (occ->timeout_task); occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ); } cmsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg; memcpy (&occ->other_peer_identity, &cmsg->peer_identity, sizeof (struct GNUNET_PeerIdentity)); GNUNET_free_non_null (occ->emsg); GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while connecting to CORE of peer with " "id: %u", occ->op_id, occ->peer->id); occ->cgh_ch = GST_connection_pool_get_handle (occ->peer->id, occ->peer->details.local.cfg, GST_CONNECTIONPOOL_SERVICE_CORE, occ_cache_get_handle_core_cb, occ, &occ->other_peer_identity, &overlay_connect_notify, occ); return; } /** * Callback which will be called after a host registration succeeded or failed * * @param cls the RegisteredHostContext * @param emsg the error message; NULL if host registration is successful */ static void host_registration_comp (void *cls, const char *emsg) { struct RegisteredHostContext *rhc = cls; rhc->state = RHC_DONE; GST_process_next_focc (rhc); } /** * Iterator to match a registered host context * * @param cls pointer 2 pointer of RegisteredHostContext * @param key current key code * @param value value in the hash map * @return GNUNET_YES if we should continue to * iterate, * GNUNET_NO if not. */ static int reghost_match_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct RegisteredHostContext **rh = cls; struct RegisteredHostContext *rh_val = value; if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host)) { GNUNET_free (*rh); *rh = rh_val; return GNUNET_NO; } return GNUNET_YES; } /** * Function to generate the hashcode corresponding to a RegisteredHostContext * * @param reg_host the host which is being registered in RegisteredHostContext * @param host the host of the controller which has to connect to the above rhost * @return the hashcode */ static struct GNUNET_HashCode hash_hosts (struct GNUNET_TESTBED_Host *reg_host, struct GNUNET_TESTBED_Host *host) { struct GNUNET_HashCode hash; uint32_t host_ids[2]; host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host); host_ids[1] = GNUNET_TESTBED_host_get_id_ (host); GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash); return hash; } /** * Checks if the given host is registered at the given slave. * * @param slave the slave where registration has to be checked. The check is * actually done through a locally maintained hashmap. No * communication with the slave is involved. * @param host the host to register * @return If the given host is not registered already or the registration is * pending, it returns the registration context. Any overlay connects * to be forwarded should be queued in the context so that they can be * executed when the registration is completed. If the given host is * already registered, NULL is returned. */ static struct RegisteredHostContext * register_host (struct Slave *slave, struct GNUNET_TESTBED_Host *host) { struct GNUNET_HashCode hash; struct RegisteredHostContext *rhc; rhc = GNUNET_new (struct RegisteredHostContext); rhc->reg_host = host; rhc->host = GST_host_list[slave->host_id]; GNUNET_assert (NULL != rhc->reg_host); GNUNET_assert (NULL != rhc->host); rhc->state = RHC_INIT; hash = hash_hosts (rhc->reg_host, rhc->host); if ((GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, &hash)) || (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map, &hash, reghost_match_iterator, &rhc))) { /* create and add a new registerd host context */ /* add the focc to its queue */ GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, &hash, rhc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GST_queue_host_registration (slave, host_registration_comp, rhc, rhc->reg_host); } else { /* rhc is now set to the existing one from the hash map by * reghost_match_iterator() */ /* if queue is empty then ignore creating focc and proceed with normal * forwarding */ if (RHC_DONE == rhc->state) return NULL; } return rhc; } /** * Forwards the overlay connect request to a slave controller. Before * forwarding, any hosts which are needed to be known by the slave controller to * execute the overlay connect request are registered at slave. * * @param msg the overlay connect request message to be forwarded * @param client the client to which the status of the forwarded request has to * be notified */ static void forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg, struct GNUNET_SERVER_Client *client) { struct ForwardedOperationContext *fopc; struct Route *route_to_peer2_host; struct Route *route_to_peer1_host; struct Peer *peer; struct RegisteredHostContext *rhc; struct ForwardedOverlayConnectContext *focc; uint64_t op_id; uint32_t peer2_host_id; uint32_t p1; uint32_t p2; p1 = ntohl (msg->peer1); p2 = ntohl (msg->peer2); op_id = GNUNET_ntohll (msg->operation_id); peer2_host_id = ntohl (msg->peer2_host_id); GNUNET_assert (VALID_PEER_ID (p1)); GNUNET_assert (VALID_HOST_ID (peer2_host_id)); peer = GST_peer_list[p1]; GNUNET_assert (GNUNET_YES == peer->is_remote); LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id); route_to_peer2_host = GST_find_dest_route (peer2_host_id); route_to_peer1_host = GST_find_dest_route (peer->details.remote.remote_host_id); GNUNET_assert (NULL != route_to_peer1_host); if ((NULL != route_to_peer2_host) && (route_to_peer1_host->dest == route_to_peer2_host->dest)) goto forward; /* Peer2 is either with us OR peer1 and peer2 can be reached through different subtrees OR peer2 is on a subtree unknown to us */ if (NULL != (rhc = register_host (peer->details.remote.slave, GST_host_list[peer2_host_id]))) { LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2); focc = GNUNET_new (struct ForwardedOverlayConnectContext); focc->peer1 = p1; focc->peer2 = p2; focc->peer2_host_id = peer2_host_id; focc->orig_msg = GNUNET_copy_message (&msg->header); focc->operation_id = op_id; focc->client = client; GNUNET_SERVER_client_keep (client); GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, rhc->focc_dll_tail, focc); return; } forward: LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2); fopc = GNUNET_new (struct ForwardedOperationContext); GNUNET_SERVER_client_keep (client); fopc->client = client; fopc->operation_id = op_id; fopc->type = OP_OVERLAY_CONNECT; fopc->opc = GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. slave->controller, op_id, &msg->header, &GST_forwarded_operation_reply_relay, fopc); fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, fopc); GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); } /** * Callback called when a connection to the controller of peer2 has been * established * * @param cls the overlay connect contexts * @param c handle to the controller connection */ static void p2_controller_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c) { struct OverlayConnectContext *occ = cls; struct RemotePeer2Context *rp2c; struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg; GNUNET_assert (OCC_TYPE_LOCAL != occ->type); rp2c = &occ->p2ctx.remote; rp2c->ncn = NULL; rp2c->p2c = c; cmsg.header.size = htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)); cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION); cmsg.peer_id = htonl (occ->other_peer_id); cmsg.operation_id = GNUNET_htonll (occ->op_id); rp2c->opc = GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c, occ->op_id, &cmsg.header, &overlay_connect_get_config, occ); GNUNET_free_non_null (occ->emsg); GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while getting peer identity of peer " "with id: %u", occ->op_id, occ->other_peer_id); } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_OverlayConnectMessage *msg; struct Peer *peer; struct Peer *peer2; struct OverlayConnectContext *occ; struct Neighbour *p2n; uint64_t operation_id; uint32_t p1; uint32_t p2; uint32_t peer2_host_id; if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) != ntohs (message->size)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message; p1 = ntohl (msg->peer1); p2 = ntohl (msg->peer2); if (!VALID_PEER_ID (p1)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } peer = GST_peer_list[p1]; operation_id = GNUNET_ntohll (msg->operation_id); LOG_DEBUG ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", p1, p2, operation_id); peer2_host_id = ntohl (msg->peer2_host_id); if (GNUNET_YES == peer->is_remote) { if (!VALID_HOST_ID (peer2_host_id)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } forward_overlay_connect (msg, client); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } p2n = NULL; occ = GNUNET_new (struct OverlayConnectContext); occ->type = OCC_TYPE_LOCAL; if (!VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */ { if (NULL == (p2n = GST_get_neighbour (peer2_host_id))) { if (!VALID_HOST_ID (peer2_host_id)) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, "0x%llx: Peer %u's host not in our neighbours list\n", operation_id, p2); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_free (occ); return; } p2n = GST_create_neighbour (GST_host_list[peer2_host_id]); } occ->type = OCC_TYPE_REMOTE_LATERAL; occ->p2ctx.remote.p2n = p2n; } else if (GNUNET_YES == GST_peer_list[p2]->is_remote) { occ->type = OCC_TYPE_REMOTE_SLAVE; occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller; } GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ); GNUNET_SERVER_client_keep (client); occ->client = client; occ->other_peer_id = p2; GST_peer_list[p1]->reference_cnt++; occ->peer = GST_peer_list[p1]; occ->op_id = operation_id; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task); occ->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_overlay_connect, occ); switch (occ->type) { case OCC_TYPE_REMOTE_LATERAL: GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while acquiring connection to peer %u's " "host: %u\n", occ->op_id, occ->other_peer_id, peer2_host_id); occ->p2ctx.remote.ncn = GST_neighbour_get_connection (p2n, &p2_controller_connect_cb, occ); break; case OCC_TYPE_REMOTE_SLAVE: p2_controller_connect_cb (occ, occ->p2ctx.remote.p2c); break; case OCC_TYPE_LOCAL: peer2 = GST_peer_list[occ->other_peer_id]; peer2->reference_cnt++; GNUNET_TESTING_peer_get_identity (peer2->details.local.peer, &occ->other_peer_identity); GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while connecting to CORE of peer with " "id: %u", occ->op_id, occ->peer->id); occ->cgh_ch = GST_connection_pool_get_handle (occ->peer->id, occ->peer->details.local.cfg, GST_CONNECTIONPOOL_SERVICE_CORE, occ_cache_get_handle_core_cb, occ, &occ->other_peer_identity, &overlay_connect_notify, occ); break; } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Function to cleanup RemoteOverlayConnectCtx and any associated tasks * with it * * @param rocc the RemoteOverlayConnectCtx */ static void cleanup_rocc (struct RemoteOverlayConnectCtx *rocc) { LOG_DEBUG ("0x%llx: Cleaning up rocc\n", rocc->op_id); if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id) GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id); if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id) GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id); if (NULL != rocc->ohh) GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh); if (NULL != rocc->tcc.tch) GNUNET_TRANSPORT_try_connect_cancel (rocc->tcc.tch); if (GNUNET_SCHEDULER_NO_TASK != rocc->tcc.task) GNUNET_SCHEDULER_cancel (rocc->tcc.task); GST_connection_pool_get_handle_done (rocc->tcc.cgh_th); GNUNET_assert (rocc->peer->reference_cnt > 0); rocc->peer->reference_cnt--; if ((GNUNET_YES == rocc->peer->destroy_flag) && (0 == rocc->peer->reference_cnt)) GST_destroy_peer (rocc->peer); GNUNET_free_non_null (rocc->hello); GNUNET_CONTAINER_DLL_remove (roccq_head, roccq_tail, rocc); GNUNET_free (rocc); } /** * Task to timeout rocc and cleanit up * * @param cls the RemoteOverlayConnectCtx * @param tc the TaskContext from scheduler */ static void timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RemoteOverlayConnectCtx *rocc = cls; GNUNET_assert (rocc->timeout_rocc_task_id != GNUNET_SCHEDULER_NO_TASK); rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK; LOG_DEBUG ("0x%llx: rocc timed out\n", rocc->op_id); cleanup_rocc (rocc); } /** * Function called to notify transport users that another * peer connected to us. * * @param cls the RemoteOverlayConnectContext * @param new_peer the peer that connected */ static void cache_transport_peer_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer) { struct RemoteOverlayConnectCtx *rocc = cls; LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", rocc->op_id); GNUNET_assert (0 == memcmp (new_peer, &rocc->a_id, sizeof (struct GNUNET_PeerIdentity))); LOG_DEBUG ("0x%llx: Peer %4s connected\n", rocc->op_id, GNUNET_i2s (&rocc->a_id)); cleanup_rocc (rocc); } /** * Task to offer the HELLO message to the peer and ask it to connect to the peer * whose identity is in RemoteOverlayConnectCtx * * @param cls the RemoteOverlayConnectCtx * @param tc the TaskContext from scheduler */ static void attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Task that is run when hello has been sent * * @param cls the overlay connect context * @param tc the scheduler task context; if tc->reason = * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if * GNUNET_SCHEDULER_REASON_READ_READY is succeeded */ static void rocc_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RemoteOverlayConnectCtx *rocc = cls; rocc->ohh = NULL; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rocc->attempt_connect_task_id); LOG_DEBUG ("0x%llx: HELLO of peer %4s sent to local peer with id: %u\n", rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id); if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason) { GNUNET_break (0); rocc->attempt_connect_task_id = GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc); return; } if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason) { GNUNET_break (0); return; } rocc->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &rocc->tcc); } /** * Task to offer the HELLO message to the peer and ask it to connect to the peer * whose identity is in RemoteOverlayConnectCtx * * @param cls the RemoteOverlayConnectCtx * @param tc the TaskContext from scheduler */ static void attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RemoteOverlayConnectCtx *rocc = cls; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id); rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK; LOG_DEBUG ("0x%llx: Offering HELLO of peer %4s to local peer with id: %u\n", rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id); rocc->ohh = GNUNET_TRANSPORT_offer_hello (rocc->tcc.th_, rocc->hello, rocc_hello_sent_cb, rocc); if (NULL == rocc->ohh) rocc->attempt_connect_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 500)), &attempt_connect_task, rocc); } /** * Callback from cache with needed handles set * * @param cls the closure passed to GST_cache_get_handle_transport() * @param ch the handle to CORE. Can be NULL if it is not requested * @param th the handle to TRANSPORT. Can be NULL if it is not requested * @param ignore_ peer identity which is ignored in this callback */ static void rocc_cache_get_handle_transport_cb (void *cls, struct GNUNET_CORE_Handle *ch, struct GNUNET_TRANSPORT_Handle *th, const struct GNUNET_PeerIdentity *ignore_) { struct RemoteOverlayConnectCtx *rocc = cls; if (NULL == th) { rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc); return; } rocc->tcc.th_ = th; rocc->tcc.pid = &rocc->a_id; if (GNUNET_YES == GNUNET_TRANSPORT_check_peer_connected (rocc->tcc.th_, rocc->tcc.pid)) { LOG_DEBUG ("0x%llx: Target peer %4s already connected to local peer: %u\n", rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id); cleanup_rocc (rocc); return; } rocc->attempt_connect_task_id = GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc); } /** * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages * * @param cls NULL * @param client identification of the client * @param message the actual message */ void GST_handle_remote_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg; struct RemoteOverlayConnectCtx *rocc; struct Peer *peer; struct GNUNET_PeerIdentity pid; static char pid_str[16]; uint32_t peer_id; uint16_t msize; uint16_t hsize; msize = ntohs (message->size); if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message; if ((NULL == msg->hello) || ((GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } hsize = ntohs (msg->hello->size); if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != msize) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } peer_id = ntohl (msg->peer); if ((peer_id >= GST_peer_list_size) || (NULL == (peer = GST_peer_list[peer_id]))) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (GNUNET_YES == peer->is_remote) { struct GNUNET_MessageHeader *msg2; msg2 = GNUNET_copy_message (message); GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, msg2); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } rocc = GNUNET_new (struct RemoteOverlayConnectCtx); rocc->op_id = GNUNET_ntohll (msg->operation_id); GNUNET_CONTAINER_DLL_insert_tail (roccq_head, roccq_tail, rocc); memcpy (&rocc->a_id, &msg->peer_identity, sizeof (struct GNUNET_PeerIdentity)); GNUNET_TESTING_peer_get_identity (peer->details.local.peer, &pid); (void) strncpy (pid_str, GNUNET_i2s (&pid), 15); LOG_DEBUG ("0x%llx: Remote overlay connect %4s to peer %4s with hello size: %u\n", rocc->op_id, pid_str, GNUNET_i2s (&rocc->a_id), hsize); rocc->peer = peer; rocc->peer->reference_cnt++; rocc->hello = GNUNET_malloc (hsize); memcpy (rocc->hello, msg->hello, hsize); rocc->tcc.op_id = rocc->op_id; rocc->tcc.cgh_th = GST_connection_pool_get_handle (peer_id, rocc->peer->details.local.cfg, GST_CONNECTIONPOOL_SERVICE_TRANSPORT, &rocc_cache_get_handle_transport_cb, rocc, &rocc->a_id, &cache_transport_peer_connect_notify, rocc); rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_rocc_task, rocc); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Clears all pending overlay connect contexts in queue */ void GST_free_occq () { struct OverlayConnectContext *occ; while (NULL != (occ = occq_head)) cleanup_occ (occ); } /** * Clears all pending remote overlay connect contexts in queue */ void GST_free_roccq () { struct RemoteOverlayConnectCtx *rocc; while (NULL != (rocc = roccq_head)) cleanup_rocc (rocc); } gnunet-0.10.1/src/testbed/test_testbed_api_template.conf0000644000175000017500000000172612233724131020323 00000000000000[testbed] AUTOSTART = NO PORT = 12113 ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost OVERLAY_TOPOLOGY = NONE #PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args [fs] AUTOSTART = NO [resolver] AUTOSTART = NO [mesh] AUTOSTART = NO [dht] AUTOSTART = NO [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = udp ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 PORT = 12365 [ats] WAN_QUOTA_OUT = 3932160 WAN_QUOTA_IN = 3932160 [core] PORT = 12092 AUTOSTART = YES USE_EPHEMERAL_KEYS = NO [arm] DEFAULTSERVICES = core transport PORT = 12366 [transport-udp] TIMEOUT = 300 s PORT = 12368 [gnunetd] HOSTKEY = $GNUNET_TEST_HOME/.hostkey [PATHS] GNUNET_TEST_HOME = /tmp/test-testbed/ [dns] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART = NO [nat] RETURN_LOCAL_ADDRESSES = YES [gns-helper-service-w32] AUTOSTART = NO [consensus] AUTOSTART = NO [gns] AUTOSTART = NO [statistics] AUTOSTART = NO [peerinfo] NO_IO = YES gnunet-0.10.1/src/testbed/gnunet-daemon-testbed-underlay.c0000644000175000017500000003100412263473436020421 00000000000000/* This file is part of GNUnet (C) 2008--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file testbed/gnunet-daemon-testbed-blacklist.c * @brief daemon to restrict incoming connections from other peers at the * transport layer of a peer * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include /** * Logging shorthand */ #define LOG(type,...) \ GNUNET_log (type, __VA_ARGS__) /** * Debug logging shorthand */ #define DEBUG(...) \ LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_SQLITE(db, msg, level, cmd) \ do { \ GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), \ cmd, __FILE__,__LINE__, sqlite3_errmsg(db)); \ if (msg != NULL) \ GNUNET_asprintf(msg, _("`%s' failed at %s:%u with error: %s"), cmd, \ __FILE__, __LINE__, sqlite3_errmsg(db)); \ } while(0) /** * The map to store the peer identities to allow/deny */ static struct GNUNET_CONTAINER_MultiPeerMap *map; /** * The database connection */ static struct sqlite3 *db; /** * The blacklist handle we obtain from transport when we register ourselves for * access control */ struct GNUNET_TRANSPORT_Blacklist *bh; /** * The hostkeys file */ struct GNUNET_DISK_FileHandle *hostkeys_fd; /** * The hostkeys map */ static struct GNUNET_DISK_MapHandle *hostkeys_map; /** * The hostkeys data */ static void *hostkeys_data; /** * Handle to the transport service. This is used for setting link metrics */ static struct GNUNET_TRANSPORT_Handle *transport; /** * The number of hostkeys in the hostkeys array */ static unsigned int num_hostkeys; /** * Task for shutdown */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * @ingroup hashmap * Iterator over hash map entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (map, key, value)); return GNUNET_YES; } /** * Cleaup and destroy the map */ static void cleanup_map () { if (NULL != map) { GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_iterate (map, &iterator, NULL)); GNUNET_CONTAINER_multipeermap_destroy (map); map = NULL; } } /** * Function that decides if a connection is acceptable or not. * * @param cls closure * @param pid peer to approve or disapproave * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not */ static int check_access (void *cls, const struct GNUNET_PeerIdentity * pid) { int contains; GNUNET_assert (NULL != map); contains = GNUNET_CONTAINER_multipeermap_contains (map, pid); if (GNUNET_YES == contains) { DEBUG ("Permitting `%s'\n", GNUNET_i2s (pid)); return GNUNET_OK; } DEBUG ("Not permitting `%s'\n", GNUNET_i2s (pid)); return GNUNET_SYSERR; } static int get_identity (unsigned int offset, struct GNUNET_PeerIdentity *id) { struct GNUNET_CRYPTO_EddsaPrivateKey private_key; if (offset >= num_hostkeys) return GNUNET_SYSERR; (void) memcpy (&private_key, hostkeys_data + (offset * GNUNET_TESTING_HOSTKEYFILESIZE), GNUNET_TESTING_HOSTKEYFILESIZE); GNUNET_CRYPTO_eddsa_key_get_public (&private_key, &id->public_key); return GNUNET_OK; } /** * Whilelist entry */ struct WhiteListRow { /** * Next ptr */ struct WhiteListRow *next; /** * The offset where to find the hostkey for the peer */ unsigned int id; /** * Latency to be assigned to the link */ int latency; }; /** * Function to load keys */ static int load_keys (const struct GNUNET_CONFIGURATION_Handle *c) { char *data_dir; char *idfile; uint64_t fsize; data_dir = NULL; idfile = NULL; fsize = 0; data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); GNUNET_asprintf (&idfile, "%s/testing_hostkeys.ecc", data_dir); GNUNET_free (data_dir); data_dir = NULL; if (GNUNET_OK != GNUNET_DISK_file_size (idfile, &fsize, GNUNET_YES, GNUNET_YES)) { GNUNET_free (idfile); return GNUNET_SYSERR; } if (0 != (fsize % GNUNET_TESTING_HOSTKEYFILESIZE)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Incorrect hostkey file format: %s\n"), idfile); GNUNET_free (idfile); return GNUNET_SYSERR; } hostkeys_fd = GNUNET_DISK_file_open (idfile, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == hostkeys_fd) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", idfile); GNUNET_free (idfile); return GNUNET_SYSERR; } GNUNET_free (idfile); idfile = NULL; hostkeys_data = GNUNET_DISK_file_map (hostkeys_fd, &hostkeys_map, GNUNET_DISK_MAP_TYPE_READ, fsize); if (NULL == hostkeys_data) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "mmap"); return GNUNET_SYSERR; } num_hostkeys = fsize / GNUNET_TESTING_HOSTKEYFILESIZE; return GNUNET_OK; } /** * Function to unload keys */ static void unload_keys () { if (NULL != hostkeys_map) { GNUNET_assert (NULL != hostkeys_data); GNUNET_DISK_file_unmap (hostkeys_map); hostkeys_map = NULL; hostkeys_data = NULL; } if (NULL != hostkeys_fd) { GNUNET_DISK_file_close (hostkeys_fd); hostkeys_fd = NULL; } } /** * Shutdown task to cleanup our resources and exit. * * @param cls NULL * @param tc scheduler task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != transport) { GNUNET_TRANSPORT_disconnect (transport); transport = NULL; } cleanup_map (); unload_keys (); if (NULL != bh) GNUNET_TRANSPORT_blacklist_cancel (bh); } /** * Function to read whitelist rows from the database * * @param db the database connection * @param pid the identity of this peer * @param wl_rows where to store the retrieved whitelist rows * @return GNUNET_SYSERR upon error OR the number of rows retrieved */ static int db_read_whitelist (struct sqlite3 *db, int pid, struct WhiteListRow **wl_rows) { static const char *query_wl = "SELECT oid, latency FROM whitelist WHERE (id == ?);"; struct sqlite3_stmt *stmt_wl; struct WhiteListRow *lr; int nrows; int ret; if (SQLITE_OK != (ret = sqlite3_prepare_v2 (db, query_wl, -1, &stmt_wl, NULL))) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_prepare_v2"); return GNUNET_SYSERR; } if (SQLITE_OK != (ret = sqlite3_bind_int (stmt_wl, 1, pid))) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_bind_int"); sqlite3_finalize (stmt_wl); return GNUNET_SYSERR; } nrows = 0; do { ret = sqlite3_step (stmt_wl); if (SQLITE_ROW != ret) break; nrows++; lr = GNUNET_new (struct WhiteListRow); lr->id = sqlite3_column_int (stmt_wl, 0); lr->latency = sqlite3_column_int (stmt_wl, 1); lr->next = *wl_rows; *wl_rows = lr; } while (1); sqlite3_finalize (stmt_wl); return nrows; } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char *dbfile; struct WhiteListRow *wl_head; struct WhiteListRow *wl_entry; struct GNUNET_PeerIdentity identity; struct GNUNET_ATS_Information params[1]; unsigned long long pid; unsigned int nrows; int ret; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "TESTBED", "PEERID", &pid)) { GNUNET_break (0); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "TESTBED-UNDERLAY", "DBFILE", &dbfile)) { GNUNET_break (0); return; } if (SQLITE_OK != (ret = sqlite3_open_v2 (dbfile, &db, SQLITE_OPEN_READONLY, NULL))) { if (NULL != db) { LOG_SQLITE (db, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_open_v2"); sqlite3_close (db); } else LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot open sqlite file %s\n", dbfile); GNUNET_free (dbfile); return; } DEBUG ("Opened database %s\n", dbfile); GNUNET_free (dbfile); dbfile = NULL; wl_head = NULL; if (GNUNET_OK != load_keys (c)) goto close_db; transport = GNUNET_TRANSPORT_connect (c, NULL, NULL, NULL, NULL, NULL); if (NULL == transport) { GNUNET_break (0); return; } /* read and process whitelist */ nrows = 0; wl_head = NULL; nrows = db_read_whitelist (db, pid, &wl_head); if ((GNUNET_SYSERR == nrows) || (0 == nrows)) { GNUNET_TRANSPORT_disconnect (transport); goto close_db; } map = GNUNET_CONTAINER_multipeermap_create (nrows, GNUNET_NO); params[0].type = GNUNET_ATS_QUALITY_NET_DELAY; while (NULL != (wl_entry = wl_head)) { wl_head = wl_entry->next; params[0].value = wl_entry->latency; GNUNET_assert (GNUNET_OK == get_identity (wl_entry->id, &identity)); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (map, &identity, &identity, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); DEBUG ("Setting %u ms latency to peer `%s'\n", wl_entry->latency, GNUNET_i2s (&identity)); GNUNET_TRANSPORT_set_traffic_metric (transport, &identity, GNUNET_YES, GNUNET_YES, /* FIXME: Separate inbound, outboud metrics */ params, 1); GNUNET_free (wl_entry); } bh = GNUNET_TRANSPORT_blacklist (c, &check_access, NULL); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); close_db: GNUNET_break (SQLITE_OK == sqlite3_close (db)); return; } /** * The main function. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; #ifdef SQLITE_CONFIG_MMAP_SIZE (void) sqlite3_config (SQLITE_CONFIG_MMAP_SIZE, 512000, 256000000); #endif ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "testbed-underlay", _ ("Daemon to restrict underlay network in testbed deployments"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } gnunet-0.10.1/src/revocation/0000755000175000017500000000000012320755626013042 500000000000000gnunet-0.10.1/src/revocation/test_revocation.conf0000644000175000017500000000107212303035353017026 00000000000000[paths] GNUNET_HOME=/tmp/test-revocation-service SERVICEHOME=/tmp/test-revocation-service [revocation] WORKBITS = 3 [arm] DEFAULTSERVICES = core identity revocation [identity] # Directory where we store information about our egos EGODIR = $GNUNET_HOME/identity/egos/ SUBSYSTEM_CFG = $SERVICEHOME/s.conf [hostlist] AUTOSTART = NO SERVERS = dummy [transport-udp] BROADCAST = NO [nat] RETURN_LOCAL_ADDRESSES = YES [peerinfo] USE_INCLUDED_HELLOS = NO [testbed] OVERLAY_TOPOLOGY = CLIQUE SETUP_TIMEOUT = 1 m OPERATION_TIMEOUT = 5 s CACHE_SIZE = 0 [nse] WORKBITS = 1 gnunet-0.10.1/src/revocation/test_local_revocation.py.in0000644000175000017500000000724212250055470020320 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Testcase for ego revocation from __future__ import print_function import sys import os import subprocess import re import shutil if os.name == 'posix': config = 'gnunet-config' gnunetarm = 'gnunet-arm' ident = 'gnunet-identity' revoc = './gnunet-revocation' elif os.name == 'nt': config = 'gnunet-config.exe' gnunetarm = 'gnunet-arm.exe' ident = 'gnunet-identity.exe' revoc = './gnunet-revocation.exe' TEST_CONFIGURATION = "test_revocation.conf" TEST_REVOCATION_EGO = "revoc_test" get_clean = subprocess.Popen ([config, '-c', TEST_CONFIGURATION, '-s', 'PATHS', '-o', 'GNUNET_HOME', '-f'], stdout=subprocess.PIPE) cleandir, x = get_clean.communicate () cleandir = cleandir.rstrip ('\n').rstrip ('\r') if os.path.isdir (cleandir): shutil.rmtree (cleandir, True) res = 0 arm = subprocess.Popen ([gnunetarm, '-s', '-c', TEST_CONFIGURATION]) arm.communicate () try: print ("Creating an ego " + TEST_REVOCATION_EGO) sys.stdout.flush () sys.stderr.flush () idc = subprocess.Popen ([ident, '-C', TEST_REVOCATION_EGO, '-c', TEST_CONFIGURATION]) idc.communicate () if idc.returncode != 0: raise Exception ("gnunet-identity failed to create an ego `" + TEST_REVOCATION_EGO + "'") sys.stdout.flush () sys.stderr.flush () idd = subprocess.Popen ([ident, '-d'], stdout=subprocess.PIPE) rev_key, x = idd.communicate () if len (rev_key.split ()) < 3: raise Exception ("can't get revocation key out of `" + rev_key + "'") rev_key = rev_key.split ()[2] print ("Testing key " + rev_key) sys.stdout.flush () sys.stderr.flush () tst = subprocess.Popen ([revoc, '-t', rev_key, '-c', TEST_CONFIGURATION], stdout=subprocess.PIPE) output_not_revoked, x = tst.communicate () if tst.returncode != 0: raise Exception ("gnunet-revocation failed to test a key - " + str (tst.returncode) + ": " + output_not_revoked) if 'valid' not in output_not_revoked: res = 1 print ("Key was not valid") else: print ("Key was valid") print ("Revoking key " + rev_key) sys.stdout.flush () sys.stderr.flush () rev = subprocess.Popen ([revoc, '-R', TEST_REVOCATION_EGO, '-p', '-c', TEST_CONFIGURATION]) rev.communicate () if rev.returncode != 0: raise Exception ("gnunet-revocation failed to revoke a key") print ("Testing revoked key " + rev_key) sys.stdout.flush () sys.stderr.flush () tst = subprocess.Popen ([revoc, '-t', rev_key, '-c', TEST_CONFIGURATION], stdout=subprocess.PIPE) output_revoked, x = tst.communicate () if tst.returncode != 0: raise Exception ("gnunet-revocation failed to test a revoked key") if 'revoked' not in output_revoked: res = 1 print ("Key was not revoked") else: print ("Key was revoked") finally: arm = subprocess.Popen ([gnunetarm, '-e', '-c', TEST_CONFIGURATION]) arm.communicate () if os.path.isdir (cleandir): shutil.rmtree (cleandir, True) sys.exit (res) gnunet-0.10.1/src/revocation/revocation.h0000644000175000017500000000556012225777503015314 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file revocation/revocation.h * @brief messages for key revocation */ #ifndef REVOCATION_H #define REVOCATION_H #include "gnunet_util_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Query key revocation status. */ struct QueryMessage { /** * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_QUERY */ struct GNUNET_MessageHeader header; /** * For alignment. */ uint32_t reserved GNUNET_PACKED; /** * Key to check. */ struct GNUNET_CRYPTO_EcdsaPublicKey key; }; /** * Key revocation response. */ struct QueryResponseMessage { /** * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE */ struct GNUNET_MessageHeader header; /** * #GNUNET_NO if revoked, #GNUNET_YES if valid. */ uint32_t is_valid GNUNET_PACKED; }; /** * Revoke key. These messages are exchanged between peers (during * flooding) but also sent by the client to the service. When the * client sends it to the service, the message is answered by a * #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE (which is just * in a `struct GNUNET_MessageHeader`. */ struct RevokeMessage { /** * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE */ struct GNUNET_MessageHeader header; /** * For alignment. */ uint32_t reserved GNUNET_PACKED; /** * Number that causes a hash collision with the @e public_key. */ uint64_t proof_of_work GNUNET_PACKED; /** * Signature confirming revocation. */ struct GNUNET_CRYPTO_EcdsaSignature signature; /** * Must have purpose #GNUNET_SIGNATURE_PURPOSE_REVOCATION, * size expands over the public key. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Key to revoke. */ struct GNUNET_CRYPTO_EcdsaPublicKey public_key; }; /** * Key revocation response. */ struct RevocationResponseMessage { /** * Type: #GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE */ struct GNUNET_MessageHeader header; /** * #GNUNET_NO if revoked, #GNUNET_YES if valid. */ uint32_t is_valid GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/revocation/gnunet-revocation.c0000644000175000017500000003300412261236531016566 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file revocation/gnunet-revocation.c * @brief tool for revoking public keys * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_revocation_service.h" #include "gnunet_identity_service.h" /** * Final status code. */ static int ret; /** * Was "-p" specified? */ static int perform; /** * -f option. */ static char *filename; /** * -R option */ static char *revoke_ego; /** * -t option. */ static char *test_ego; /** * Handle for revocation query. */ static struct GNUNET_REVOCATION_Query *q; /** * Handle for revocation. */ static struct GNUNET_REVOCATION_Handle *h; /** * Handle for our ego lookup. */ static struct GNUNET_IDENTITY_EgoLookup *el; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Number of matching bits required for revocation. */ static unsigned long long matching_bits; /** * Function run if the user aborts with CTRL-C. * * @param cls closure * @param tc scheduler context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != el) { GNUNET_IDENTITY_ego_lookup_cancel (el); el = NULL; } if (NULL != q) { GNUNET_REVOCATION_query_cancel (q); q = NULL; } if (NULL != h) { GNUNET_REVOCATION_revoke_cancel (h); h = NULL; } } /** * Print the result from a revocation query. * * @param cls NULL * @param is_valid #GNUNET_YES if the key is still valid, #GNUNET_NO if not, #GNUNET_SYSERR on error */ static void print_query_result (void *cls, int is_valid) { q = NULL; switch (is_valid) { case GNUNET_YES: FPRINTF (stdout, _("Key `%s' is valid\n"), test_ego); break; case GNUNET_NO: FPRINTF (stdout, _("Key `%s' has been revoked\n"), test_ego); break; case GNUNET_SYSERR: FPRINTF (stdout, "%s", _("Internal error\n")); break; default: GNUNET_break (0); break; } GNUNET_SCHEDULER_shutdown (); } /** * Print the result from a revocation request. * * @param cls NULL * @param is_valid #GNUNET_YES if the key is still valid, #GNUNET_NO if not, #GNUNET_SYSERR on error */ static void print_revocation_result (void *cls, int is_valid) { h = NULL; switch (is_valid) { case GNUNET_YES: if (NULL != revoke_ego) FPRINTF (stdout, _("Key for ego `%s' is still valid, revocation failed (!)\n"), revoke_ego); else FPRINTF (stdout, "%s", _("Revocation failed (!)\n")); break; case GNUNET_NO: if (NULL != revoke_ego) FPRINTF (stdout, _("Key for ego `%s' has been successfully revoked\n"), revoke_ego); else FPRINTF (stdout, "%s", _("Revocation successful.\n")); break; case GNUNET_SYSERR: FPRINTF (stdout, "%s", _("Internal error, key revocation might have failed\n")); break; default: GNUNET_break (0); break; } GNUNET_SCHEDULER_shutdown (); } /** * Data needed to perform a revocation. */ struct RevocationData { /** * Public key. */ struct GNUNET_CRYPTO_EcdsaPublicKey key; /** * Revocation signature data. */ struct GNUNET_CRYPTO_EcdsaSignature sig; /** * Proof of work (in NBO). */ uint64_t pow GNUNET_PACKED; }; /** * Perform the revocation. */ static void perform_revocation (const struct RevocationData *rd) { h = GNUNET_REVOCATION_revoke (cfg, &rd->key, &rd->sig, rd->pow, &print_revocation_result, NULL); } /** * Perform the proof-of-work calculation. * * @param cls the `struct RevocationData` * @param tc scheduler context */ static void calculate_pow (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RevocationData *rd = cls; /* store temporary results */ if ( (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) || (0 == (rd->pow % 128) ) ) { if ( (NULL != filename) && (sizeof (struct RevocationData) == GNUNET_DISK_fn_write (filename, &rd, sizeof (rd), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename); } /* display progress estimate */ if ( (0 == ((1 << matching_bits) / 100 / 50)) || (0 == (rd->pow % ((1 << matching_bits) / 100 / 50))) ) FPRINTF (stderr, "%s", "."); if ( (0 != rd->pow) && ( (0 == ((1 << matching_bits) / 100)) || (0 == (rd->pow % ((1 << matching_bits) / 100))) ) ) FPRINTF (stderr, " - @ %3u%% (estimate)\n", (unsigned int) (rd->pow * 100) / (1 << matching_bits)); if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) { GNUNET_free (rd); return; } /* actually do POW calculation */ rd->pow++; if (GNUNET_OK == GNUNET_REVOCATION_check_pow (&rd->key, rd->pow, (unsigned int) matching_bits)) { if ( (NULL != filename) && (sizeof (struct RevocationData) != GNUNET_DISK_fn_write (filename, rd, sizeof (struct RevocationData), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", filename); if (perform) perform_revocation (rd); else { FPRINTF (stderr, "%s", "\n"); FPRINTF (stderr, _("Revocation certificate for `%s' stored in `%s'\n"), revoke_ego, filename); GNUNET_SCHEDULER_shutdown (); } GNUNET_free (rd); return; } GNUNET_SCHEDULER_add_now (&calculate_pow, rd); } /** * Function called with the result from the ego lookup. * * @param cls closure * @param ego the ego, NULL if not found */ static void ego_callback (void *cls, const struct GNUNET_IDENTITY_Ego *ego) { struct RevocationData *rd; struct GNUNET_CRYPTO_EcdsaPublicKey key; el = NULL; if (NULL == ego) { FPRINTF (stdout, _("Ego `%s' not found.\n"), revoke_ego); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_IDENTITY_ego_get_public_key (ego, &key); rd = GNUNET_new (struct RevocationData); if ( (NULL != filename) && (GNUNET_YES == GNUNET_DISK_file_test (filename)) && (sizeof (struct RevocationData) == GNUNET_DISK_fn_read (filename, rd, sizeof (struct RevocationData))) ) { if (0 != memcmp (&rd->key, &key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) { fprintf (stderr, _("Error: revocation certificate in `%s' is not for `%s'\n"), filename, revoke_ego); GNUNET_free (rd); return; } } else { GNUNET_REVOCATION_sign_revocation (GNUNET_IDENTITY_ego_get_private_key (ego), &rd->sig); rd->key = key; } if (GNUNET_YES == GNUNET_REVOCATION_check_pow (&key, rd->pow, (unsigned int) matching_bits)) { FPRINTF (stderr, "%s", _("Revocation certificate ready\n")); if (perform) perform_revocation (rd); else GNUNET_SCHEDULER_shutdown (); GNUNET_free (rd); return; } FPRINTF (stderr, "%s", _("Revocation certificate not ready, calculating proof of work\n")); GNUNET_SCHEDULER_add_now (&calculate_pow, rd); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_CRYPTO_EcdsaPublicKey pk; struct RevocationData rd; cfg = c; if (NULL != test_ego) { if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (test_ego, strlen (test_ego), &pk)) { FPRINTF (stderr, _("Public key `%s' malformed\n"), test_ego); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); q = GNUNET_REVOCATION_query (cfg, &pk, &print_query_result, NULL); if (NULL != revoke_ego) FPRINTF (stderr, "%s", _("Testing and revoking at the same time is not allowed, only executing test.\n")); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "REVOCATION", "WORKBITS", &matching_bits)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "REVOCATION", "WORKBITS"); return; } if (NULL != revoke_ego) { if ( !perform && (NULL == filename) ) { FPRINTF (stderr, "%s", _("No filename to store revocation certificate given.\n")); return; } /* main code here */ el = GNUNET_IDENTITY_ego_lookup (cfg, revoke_ego, &ego_callback, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); return; } if ( (NULL != filename) && (perform) ) { if (sizeof (rd) != GNUNET_DISK_fn_read (filename, &rd, sizeof (rd))) { fprintf (stderr, _("Failed to read revocation certificate from `%s'\n"), filename); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); if (GNUNET_YES != GNUNET_REVOCATION_check_pow (&rd.key, rd.pow, (unsigned int) matching_bits)) { struct RevocationData *cp = GNUNET_new (struct RevocationData); *cp = rd; GNUNET_SCHEDULER_add_now (&calculate_pow, cp); return; } perform_revocation (&rd); return; } FPRINTF (stderr, "%s", _("No action specified. Nothing to do.\n")); } /** * The main function of gnunet-revocation. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'f', "filename", "NAME", gettext_noop ("use NAME for the name of the revocation file"), 1, &GNUNET_GETOPT_set_string, &filename}, {'R', "revoke", "NAME", gettext_noop ("revoke the private key associated for the the private key associated with the ego NAME "), 1, &GNUNET_GETOPT_set_string, &revoke_ego}, {'p', "perform", NULL, gettext_noop ("actually perform revocation, otherwise we just do the precomputation"), 0, &GNUNET_GETOPT_set_one, &perform}, {'t', "test", "KEY", gettext_noop ("test if the public key KEY has been revoked"), 1, &GNUNET_GETOPT_set_string, &test_ego}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-revocation", gettext_noop ("help text"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-revocation.c */ gnunet-0.10.1/src/revocation/Makefile.in0000644000175000017500000013212312320752063015021 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-revocation$(EXEEXT) libexec_PROGRAMS = gnunet-service-revocation$(EXEEXT) check_PROGRAMS = test_revocation$(EXEEXT) subdir = src/revocation DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/revocation.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = revocation.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetrevocation_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libgnunetrevocation_la_OBJECTS = revocation_api.lo libgnunetrevocation_la_OBJECTS = $(am_libgnunetrevocation_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetrevocation_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetrevocation_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_revocation_OBJECTS = gnunet-revocation.$(OBJEXT) gnunet_revocation_OBJECTS = $(am_gnunet_revocation_OBJECTS) gnunet_revocation_DEPENDENCIES = libgnunetrevocation.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_gnunet_service_revocation_OBJECTS = \ gnunet-service-revocation.$(OBJEXT) gnunet_service_revocation_OBJECTS = \ $(am_gnunet_service_revocation_OBJECTS) am_test_revocation_OBJECTS = test_revocation.$(OBJEXT) test_revocation_OBJECTS = $(am_test_revocation_OBJECTS) test_revocation_DEPENDENCIES = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src//core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetrevocation_la_SOURCES) \ $(gnunet_revocation_SOURCES) \ $(gnunet_service_revocation_SOURCES) \ $(test_revocation_SOURCES) DIST_SOURCES = $(libgnunetrevocation_la_SOURCES) \ $(gnunet_revocation_SOURCES) \ $(gnunet_service_revocation_SOURCES) \ $(test_revocation_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ revocation.conf gnunet_revocation_SOURCES = \ gnunet-revocation.c gnunet_revocation_LDADD = \ libgnunetrevocation.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) lib_LTLIBRARIES = libgnunetrevocation.la libgnunetrevocation_la_SOURCES = \ revocation_api.c revocation.h libgnunetrevocation_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) \ $(GN_LIBINTL) $(XLIB) -lgcrypt libgnunetrevocation_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 gnunet_service_revocation_SOURCES = \ gnunet-service-revocation.c gnunet_service_revocation_LDADD = \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/set/libgnunetset.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lm \ $(GN_LIBINTL) gnunet_service_revocation_DEPENDENCIES = \ libgnunetrevocation.la test_revocation_SOURCES = \ test_revocation.c test_revocation_LDADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src//core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la check_SCRIPTS = \ test_local_revocation.py @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = \ @ENABLE_TEST_RUN_TRUE@ $(check_SCRIPTS) \ @ENABLE_TEST_RUN_TRUE@ $(check_PROGRAMS) do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' EXTRA_DIST = test_revocation.conf \ test_local_revocation.py.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/revocation/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/revocation/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): revocation.conf: $(top_builddir)/config.status $(srcdir)/revocation.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetrevocation.la: $(libgnunetrevocation_la_OBJECTS) $(libgnunetrevocation_la_DEPENDENCIES) $(EXTRA_libgnunetrevocation_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetrevocation_la_LINK) -rpath $(libdir) $(libgnunetrevocation_la_OBJECTS) $(libgnunetrevocation_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-revocation$(EXEEXT): $(gnunet_revocation_OBJECTS) $(gnunet_revocation_DEPENDENCIES) $(EXTRA_gnunet_revocation_DEPENDENCIES) @rm -f gnunet-revocation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_revocation_OBJECTS) $(gnunet_revocation_LDADD) $(LIBS) gnunet-service-revocation$(EXEEXT): $(gnunet_service_revocation_OBJECTS) $(gnunet_service_revocation_DEPENDENCIES) $(EXTRA_gnunet_service_revocation_DEPENDENCIES) @rm -f gnunet-service-revocation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_revocation_OBJECTS) $(gnunet_service_revocation_LDADD) $(LIBS) test_revocation$(EXEEXT): $(test_revocation_OBJECTS) $(test_revocation_DEPENDENCIES) $(EXTRA_test_revocation_DEPENDENCIES) @rm -f test_revocation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_revocation_OBJECTS) $(test_revocation_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-revocation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-revocation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revocation_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_revocation.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_local_revocation.py.log: test_local_revocation.py @p='test_local_revocation.py'; \ b='test_local_revocation.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_revocation.log: test_revocation$(EXEEXT) @p='test_revocation$(EXEEXT)'; \ b='test_revocation'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA test_local_revocation.py: test_local_revocation.py.in Makefile $(do_subst) < $(srcdir)/test_local_revocation.py.in > test_local_revocation.py chmod +x test_local_revocation.py # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/revocation/Makefile.am0000644000175000017500000000435712320751520015014 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ revocation.conf bin_PROGRAMS = \ gnunet-revocation gnunet_revocation_SOURCES = \ gnunet-revocation.c gnunet_revocation_LDADD = \ libgnunetrevocation.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) lib_LTLIBRARIES = libgnunetrevocation.la libgnunetrevocation_la_SOURCES = \ revocation_api.c revocation.h libgnunetrevocation_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) \ $(GN_LIBINTL) $(XLIB) -lgcrypt libgnunetrevocation_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libexec_PROGRAMS = \ gnunet-service-revocation gnunet_service_revocation_SOURCES = \ gnunet-service-revocation.c gnunet_service_revocation_LDADD = \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/set/libgnunetset.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lm \ $(GN_LIBINTL) gnunet_service_revocation_DEPENDENCIES = \ libgnunetrevocation.la test_revocation_SOURCES = \ test_revocation.c test_revocation_LDADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/revocation/libgnunetrevocation.la \ $(top_builddir)/src//core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la check_PROGRAMS = \ test_revocation check_SCRIPTS = \ test_local_revocation.py if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ $(check_SCRIPTS) \ $(check_PROGRAMS) endif do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' test_local_revocation.py: test_local_revocation.py.in Makefile $(do_subst) < $(srcdir)/test_local_revocation.py.in > test_local_revocation.py chmod +x test_local_revocation.py EXTRA_DIST = test_revocation.conf \ test_local_revocation.py.in gnunet-0.10.1/src/revocation/revocation_api.c0000644000175000017500000003156712225777502016145 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public Licerevocation as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licerevocation for more details. You should have received a copy of the GNU General Public Licerevocation along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file revocation/revocation_api.c * @brief API to perform and access key revocations * @author Christian Grothoff */ #include "platform.h" #include "gnunet_revocation_service.h" #include "gnunet_signatures.h" #include "gnunet_protocols.h" #include "revocation.h" #include /** * Handle for the key revocation query. */ struct GNUNET_REVOCATION_Query { /** * Connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Key to check. */ struct GNUNET_CRYPTO_EcdsaPublicKey key; /** * Function to call with the result. */ GNUNET_REVOCATION_Callback func; /** * Closure for @e func. */ void *func_cls; /** * Transmission handle to the service. */ struct GNUNET_CLIENT_TransmitHandle *th; }; /** * Handle response to our revocation query. * * @param cls our `struct GNUNET_REVOCATION_Query` handle * @param msg response we got, NULL on disconnect */ static void handle_revocation_query_response (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_REVOCATION_Query *q = cls; const struct QueryResponseMessage *qrm; if ( (NULL == msg) || (sizeof (struct QueryResponseMessage) != ntohs (msg->size)) || (GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE != ntohs (msg->type)) ) { GNUNET_break (NULL == msg); q->func (q->func_cls, GNUNET_SYSERR); GNUNET_REVOCATION_query_cancel (q); return; } qrm = (const struct QueryResponseMessage *) msg; q->func (q->func_cls, ntohl (qrm->is_valid)); GNUNET_REVOCATION_query_cancel (q); } /** * Transmit our revocation query to the service. * * @param cls our `struct GNUNET_REVOCATION_Query` handle * @param size number of bytes available in @a buf * @param buf where to copy the query * @return number of bytes copied to @a buf */ static size_t send_revocation_query (void *cls, size_t size, void *buf) { struct GNUNET_REVOCATION_Query *q = cls; struct QueryMessage qm; q->th = NULL; if ( (NULL == buf) || (sizeof (struct QueryMessage) > size) ) { GNUNET_break (0); q->func (q->func_cls, GNUNET_SYSERR); GNUNET_REVOCATION_query_cancel (q); return 0; } qm.header.size = htons (sizeof (struct QueryMessage)); qm.header.type = htons (GNUNET_MESSAGE_TYPE_REVOCATION_QUERY); qm.reserved = htonl (0); qm.key = q->key; memcpy (buf, &qm, sizeof (struct QueryMessage)); GNUNET_CLIENT_receive (q->client, &handle_revocation_query_response, q, GNUNET_TIME_UNIT_FOREVER_REL); return sizeof (struct QueryMessage); } /** * Check if a key was revoked. * * @param cfg the configuration to use * @param key key to check for revocation * @param func funtion to call with the result of the check * @param func_cls closure to pass to @a func * @return handle to use in #GNUNET_REVOCATION_query_cancel to stop REVOCATION from invoking the callback */ struct GNUNET_REVOCATION_Query * GNUNET_REVOCATION_query (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPublicKey *key, GNUNET_REVOCATION_Callback func, void *func_cls) { struct GNUNET_REVOCATION_Query *q; q = GNUNET_new (struct GNUNET_REVOCATION_Query); q->client = GNUNET_CLIENT_connect ("revocation", cfg); if (NULL == q->client) { GNUNET_break (0); GNUNET_free (q); return NULL; } q->cfg = cfg; q->key = *key; q->func = func; q->func_cls = func_cls; q->th = GNUNET_CLIENT_notify_transmit_ready (q->client, sizeof (struct QueryMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_revocation_query, q); return q; } /** * Cancel key revocation check. * * @param q query to cancel */ void GNUNET_REVOCATION_query_cancel (struct GNUNET_REVOCATION_Query *q) { if (NULL != q->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (q->th); q->th = NULL; } GNUNET_CLIENT_disconnect (q->client); GNUNET_free (q); } /** * Handle for the key revocation operation. */ struct GNUNET_REVOCATION_Handle { /** * Connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Key to revoke. */ struct GNUNET_CRYPTO_EcdsaPublicKey key; /** * Signature showing that we have the right to revoke. */ struct GNUNET_CRYPTO_EcdsaSignature sig; /** * Proof of work showing that we spent enough resources to broadcast revocation. */ uint64_t pow; /** * Function to call once we are done. */ GNUNET_REVOCATION_Callback func; /** * Closure for @e func. */ void *func_cls; /** * Transmission handle to the service. */ struct GNUNET_CLIENT_TransmitHandle *th; }; /** * Handle response to our revocation query. * * @param cls our `struct GNUNET_REVOCATION_Handle` handle * @param msg response we got, NULL on disconnect */ static void handle_revocation_response (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_REVOCATION_Handle *h = cls; const struct RevocationResponseMessage *rrm; if ( (NULL == msg) || (sizeof (struct RevocationResponseMessage) != ntohs (msg->size)) || (GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE != ntohs (msg->type)) ) { GNUNET_break (NULL == msg); h->func (h->func_cls, GNUNET_SYSERR); GNUNET_REVOCATION_revoke_cancel (h); return; } rrm = (const struct RevocationResponseMessage *) msg; h->func (h->func_cls, ntohl (rrm->is_valid)); GNUNET_REVOCATION_revoke_cancel (h); } /** * Transmit our revocation to the service. * * @param cls our `struct GNUNET_REVOCATION_Handle` handle * @param size number of bytes available in @a buf * @param buf where to copy the query * @return number of bytes copied to @a buf */ static size_t send_revoke (void *cls, size_t size, void *buf) { struct GNUNET_REVOCATION_Handle *h = cls; struct RevokeMessage rm; h->th = NULL; if ( (NULL == buf) || (sizeof (struct RevokeMessage) > size) ) { GNUNET_break (0); h->func (h->func_cls, GNUNET_SYSERR); GNUNET_REVOCATION_revoke_cancel (h); return 0; } rm.header.size = htons (sizeof (struct RevokeMessage)); rm.header.type = htons (GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE); rm.reserved = htonl (0); rm.proof_of_work = h->pow; rm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); rm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); rm.public_key = h->key; rm.signature = h->sig; memcpy (buf, &rm, sizeof (struct RevokeMessage)); GNUNET_CLIENT_receive (h->client, &handle_revocation_response, h, GNUNET_TIME_UNIT_FOREVER_REL); return sizeof (struct RevokeMessage); } /** * Perform key revocation. * * @param cfg the configuration to use * @param key public key of the key to revoke * @param sig signature to use on the revocation (should have been * created using #GNUNET_REVOCATION_sign_revocation). * @param pow proof of work to use (should have been created by * iteratively calling #GNUNET_REVOCATION_check_pow) * @param func funtion to call with the result of the check * (called with `is_valid` being #GNUNET_NO if * the revocation worked). * @param func_cls closure to pass to @a func * @return handle to use in #GNUNET_REVOCATION_revoke_cancel to stop REVOCATION from invoking the callback */ struct GNUNET_REVOCATION_Handle * GNUNET_REVOCATION_revoke (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPublicKey *key, const struct GNUNET_CRYPTO_EcdsaSignature *sig, uint64_t pow, GNUNET_REVOCATION_Callback func, void *func_cls) { struct GNUNET_REVOCATION_Handle *h; unsigned long long matching_bits; if ( (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "REVOCATION", "WORKBITS", &matching_bits)) && (GNUNET_YES != GNUNET_REVOCATION_check_pow (key, pow, (unsigned int) matching_bits)) ) { GNUNET_break (0); return NULL; } h = GNUNET_new (struct GNUNET_REVOCATION_Handle); h->client = GNUNET_CLIENT_connect ("revocation", cfg); h->cfg = cfg; h->key = *key; h->sig = *sig; h->pow = pow; h->func = func; h->func_cls = func_cls; h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof (struct RevokeMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_revoke, h); return h; } /** * Cancel key revocation. * * @param h operation to cancel */ void GNUNET_REVOCATION_revoke_cancel (struct GNUNET_REVOCATION_Handle *h) { if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } GNUNET_CLIENT_disconnect (h->client); GNUNET_free (h); } /** * Calculate the 'proof-of-work' hash (an expensive hash). * * @param buf data to hash * @param buf_len number of bytes in @a buf * @param result where to write the resulting hash */ static void pow_hash (const void *buf, size_t buf_len, struct GNUNET_HashCode *result) { GNUNET_break (0 == gcry_kdf_derive (buf, buf_len, GCRY_KDF_SCRYPT, 1 /* subalgo */, "gnunet-revocation-proof-of-work", strlen ("gnunet-revocation-proof-of-work"), 2 /* iterations; keep cost of individual op small */, sizeof (struct GNUNET_HashCode), result)); } /** * Count the leading zeroes in hash. * * @param hash to count leading zeros in * @return the number of leading zero bits. */ static unsigned int count_leading_zeroes (const struct GNUNET_HashCode *hash) { unsigned int hash_count; hash_count = 0; while ((0 == GNUNET_CRYPTO_hash_get_bit (hash, hash_count))) hash_count++; return hash_count; } /** * Check if the given proof-of-work value * would be acceptable for revoking the given key. * * @param key key to check for * @param pow proof of work value * @param matching_bits how many bits must match (configuration) * @return #GNUNET_YES if the @a pow is acceptable, #GNUNET_NO if not */ int GNUNET_REVOCATION_check_pow (const struct GNUNET_CRYPTO_EcdsaPublicKey *key, uint64_t pow, unsigned int matching_bits) { char buf[sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (pow)] GNUNET_ALIGN; struct GNUNET_HashCode result; memcpy (buf, &pow, sizeof (pow)); memcpy (&buf[sizeof (pow)], key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); pow_hash (buf, sizeof (buf), &result); return (count_leading_zeroes (&result) >= matching_bits) ? GNUNET_YES : GNUNET_NO; } /** * Create a revocation signature. * * @param key private key of the key to revoke * @param sig where to write the revocation signature */ void GNUNET_REVOCATION_sign_revocation (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, struct GNUNET_CRYPTO_EcdsaSignature *sig) { struct RevokeMessage rm; rm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_REVOCATION); rm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); GNUNET_CRYPTO_ecdsa_key_get_public (key, &rm.public_key); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (key, &rm.purpose, sig)); } /* end of revocation_api.c */ gnunet-0.10.1/src/revocation/revocation.conf.in0000644000175000017500000000074312250373167016411 00000000000000[revocation] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2112 HOSTNAME = localhost BINARY = gnunet-service-revocation ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-revocation.unix UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES # 2^25 hash operations take about 16-24h on a modern i7 # (using only a single-core) with SCRYPT. # DO NOT CHANGE THIS VALUE, doing so will break the protocol! WORKBITS = 25 DATABASE = $GNUNET_DATA_HOME/revocation.dat gnunet-0.10.1/src/revocation/test_revocation.c0000644000175000017500000002322712245626213016337 00000000000000/* This file is part of GNUnet. (C) 2009, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file revocation/test_revocation.c * @brief base testcase for revocation exchange */ #include "platform.h" #include "gnunet_core_service.h" #include "gnunet_identity_service.h" #include "gnunet_revocation_service.h" #include "gnunet_testbed_service.h" #define NUM_TEST_PEERS 2 struct TestPeer { struct GNUNET_TESTBED_Peer *p; struct GNUNET_TESTBED_Operation *identity_op; struct GNUNET_TESTBED_Operation *core_op; struct GNUNET_IDENTITY_Handle *idh; const struct GNUNET_CONFIGURATION_Handle *cfg; const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; struct GNUNET_CRYPTO_EcdsaSignature sig; struct GNUNET_IDENTITY_Operation *create_id_op; struct GNUNET_IDENTITY_EgoLookup *ego_lookup; struct GNUNET_REVOCATION_Handle *revok_handle; struct GNUNET_CORE_Handle *ch; uint64_t pow; }; static struct TestPeer testpeers[2]; static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Return value from main, set to 0 on success. */ static int ok; static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int c; if (GNUNET_SCHEDULER_NO_TASK != die_task) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } for (c = 0; c < NUM_TEST_PEERS; c++) { if (NULL != testpeers[c].create_id_op) { GNUNET_IDENTITY_cancel (testpeers[c].create_id_op); testpeers[c].create_id_op = NULL; } if (NULL != testpeers[c].ego_lookup) { GNUNET_IDENTITY_ego_lookup_cancel (testpeers[c].ego_lookup); testpeers[c].ego_lookup = NULL; } if (NULL != testpeers[c].revok_handle) { GNUNET_REVOCATION_revoke_cancel (testpeers[c].revok_handle); testpeers[c].revok_handle = NULL; } if (NULL != testpeers[c].identity_op) { GNUNET_TESTBED_operation_done (testpeers[c].identity_op); testpeers[c].identity_op = NULL; } if (NULL != testpeers[c].core_op) { GNUNET_TESTBED_operation_done (testpeers[c].core_op); testpeers[c].core_op = NULL; } } GNUNET_SCHEDULER_shutdown (); ok = 0; } static void do_shutdown_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != die_task) die_task = GNUNET_SCHEDULER_NO_TASK; do_shutdown (NULL, NULL ); ok = 1; } static void * identity_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TestPeer *me = cls; me->cfg = cfg; me->idh = GNUNET_IDENTITY_connect (cfg, NULL, NULL ); if (NULL == me->idh) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create IDENTITY handle \n"); return me->idh; } static void identity_disconnect_adapter (void *cls, void *op_result) { struct TestPeer *me = cls; GNUNET_IDENTITY_disconnect (me->idh); me->idh = NULL; } static void check_revocation (); static void revocation_remote_cb (void *cls, int is_valid) { static int repeat = 0; if (GNUNET_NO == is_valid) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Local revocation successful\n"); GNUNET_SCHEDULER_add_now (&do_shutdown, NULL ); } else if (repeat < 10) { GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &check_revocation, NULL ); } else { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Flooding of revocation failed\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_now (&do_shutdown_badly, NULL ); } repeat++; } static void check_revocation () { GNUNET_REVOCATION_query (testpeers[0].cfg, &testpeers[1].pubkey, &revocation_remote_cb, NULL ); } static void revocation_cb (void *cls, int is_valid) { testpeers[1].revok_handle = NULL; if (GNUNET_NO == is_valid) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Revocation successful\n"); check_revocation (); } } static void ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) { static int completed = 0; if ((NULL != ego) && (cls == &testpeers[0])) { testpeers[0].ego_lookup = NULL; testpeers[0].privkey = GNUNET_IDENTITY_ego_get_private_key (ego); GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[0].pubkey); completed++; } if ((NULL != ego) && (cls == &testpeers[1])) { testpeers[1].ego_lookup = NULL; testpeers[1].privkey = GNUNET_IDENTITY_ego_get_private_key (ego); GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[1].pubkey); GNUNET_REVOCATION_sign_revocation (testpeers[1].privkey, &testpeers[1].sig); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Calculating proof of work...\n"); testpeers[1].pow = 0; int res = GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey, testpeers[1].pow, 5); while (GNUNET_OK != res) { testpeers[1].pow++; res = GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey, testpeers[1].pow, 5); } GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Done calculating proof of work\n"); completed++; } if (2 == completed) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Egos retrieved\n"); testpeers[1].revok_handle = GNUNET_REVOCATION_revoke (testpeers[1].cfg, &testpeers[1].pubkey, &testpeers[1].sig, testpeers[1].pow, revocation_cb, NULL ); } } void identity_create_cb (void *cls, const char *emsg) { static int completed = 0; if ((NULL == emsg) && (cls == &testpeers[0])) { testpeers[0].create_id_op = NULL; completed++; } if ((NULL == emsg) && (cls == &testpeers[1])) { testpeers[1].create_id_op = NULL; completed++; } if (2 == completed) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Identities created\n"); testpeers[0].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[0].cfg, "client", ego_cb, &testpeers[0]); testpeers[1].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[1].cfg, "toberevoked", ego_cb, &testpeers[1]); } } static void identity_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { static int completed = 0; completed++; if (NUM_TEST_PEERS == completed) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to identity\n"); testpeers[0].create_id_op = GNUNET_IDENTITY_create (testpeers[0].idh, "client", identity_create_cb, &testpeers[0]); testpeers[1].create_id_op = GNUNET_IDENTITY_create (testpeers[1].idh, "toberevoked", identity_create_cb, &testpeers[1]); } } void static connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer) { static int connects = 0; connects++; if (4 == connects) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "All peers connected ...\n"); /* Connect to identity service */ testpeers[0].identity_op = GNUNET_TESTBED_service_connect (NULL, testpeers[0].p, "identity", identity_completion_cb, NULL, &identity_connect_adapter, &identity_disconnect_adapter, &testpeers[0]); testpeers[1].identity_op = GNUNET_TESTBED_service_connect (NULL, testpeers[1].p, "identity", identity_completion_cb, NULL, &identity_connect_adapter, &identity_disconnect_adapter, &testpeers[1]); } } static void core_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { static int completed = 0; completed++; if (NUM_TEST_PEERS == completed) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to CORE\n"); } } static void * core_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TestPeer *me = cls; me->cfg = cfg; me->ch = GNUNET_CORE_connect (cfg, me, NULL, &connect_cb, NULL, NULL, GNUNET_NO, NULL, GNUNET_NO, NULL); if (NULL == me->ch) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create CORE handle \n"); return me->ch; } static void core_disconnect_adapter (void *cls, void *op_result) { struct TestPeer *me = cls; GNUNET_CORE_disconnect (me->ch); me->ch = NULL; } static void test_connection (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { int c; die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown_badly, NULL ); if (NUM_TEST_PEERS != num_peers) { ok = 1; fprintf (stderr, "Only %u out of 2 peers were started ...\n", num_peers); } if (0 == links_failed) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Testbed connected peers\n"); for (c = 0; c < num_peers; c++) { testpeers[c].p = peers[c]; testpeers[c].core_op = GNUNET_TESTBED_service_connect (NULL, testpeers[c].p, "core", &core_completion_cb, NULL, &core_connect_adapter, &core_disconnect_adapter, &testpeers[c]); } } } int main (int argc, char *argv[]) { ok = 1; /* Connecting initial topology */ (void) GNUNET_TESTBED_test_run ("test-revocation", "test_revocation.conf", NUM_TEST_PEERS, 0, NULL, NULL, &test_connection, NULL ); return ok; } /* end of test_revocation.c */ gnunet-0.10.1/src/revocation/gnunet-service-revocation.c0000644000175000017500000006635612245626213020246 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public Licerevocation as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licerevocation for more details. You should have received a copy of the GNU General Public Licerevocation along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file revocation/gnunet-service-revocation.c * @brief key revocation service * @author Christian Grothoff * * The purpose of this service is to allow users to permanently revoke * (compromised) keys. This is done by flooding the network with the * revocation requests. To reduce the attack potential offered by such * flooding, revocations must include a proof of work. We use the * set service for efficiently computing the union of revocations of * peers that connect. * * TODO: * - optimization: avoid sending revocation back to peer that we got it from; * - optimization: have randomized delay in sending revocations to other peers * to make it rare to traverse each link twice (NSE-style) */ #include "platform.h" #include #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_signatures.h" #include "gnunet_statistics_service.h" #include "gnunet_core_service.h" #include "gnunet_revocation_service.h" #include "gnunet_set_service.h" #include "revocation.h" #include /** * Per-peer information. */ struct PeerEntry { /** * Queue for sending messages to this peer. */ struct GNUNET_MQ_Handle *mq; /** * What is the identity of the peer? */ struct GNUNET_PeerIdentity id; /** * Tasked used to trigger the set union operation. */ GNUNET_SCHEDULER_TaskIdentifier transmit_task; /** * Handle to active set union operation (over revocation sets). */ struct GNUNET_SET_OperationHandle *so; }; /** * Set from all revocations known to us. */ static struct GNUNET_SET_Handle *revocation_set; /** * Hash map with all revoked keys, maps the hash of the public key * to the respective `struct RevokeMessage`. */ static struct GNUNET_CONTAINER_MultiHashMap *revocation_map; /** * Handle to our current configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the statistics service. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Handle to the core service (for flooding) */ static struct GNUNET_CORE_Handle *core_api; /** * Map of all connected peers. */ static struct GNUNET_CONTAINER_MultiPeerMap *peers; /** * The peer identity of this peer. */ static struct GNUNET_PeerIdentity my_identity; /** * Handle to this serivce's server. */ static struct GNUNET_SERVER_Handle *srv; /** * Notification context for convenient sending of replies to the clients. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * File handle for the revocation database. */ static struct GNUNET_DISK_FileHandle *revocation_db; /** * Handle for us listening to incoming revocation set union requests. */ static struct GNUNET_SET_ListenHandle *revocation_union_listen_handle; /** * Amount of work required (W-bit collisions) for REVOCATION proofs, in collision-bits. */ static unsigned long long revocation_work_required; /** * Our application ID for set union operations. Must be the * same for all (compatible) peers. */ static struct GNUNET_HashCode revocation_set_union_app_id; /** * An revoke message has been received, check that it is well-formed. * * @param rm the message to verify * @return #GNUNET_YES if the message is verified * #GNUNET_NO if the key/signature don't verify */ static int verify_revoke_message (const struct RevokeMessage *rm) { if (GNUNET_YES != GNUNET_REVOCATION_check_pow (&rm->public_key, rm->proof_of_work, (unsigned int) revocation_work_required)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Proof of work invalid!\n"); GNUNET_break_op (0); return GNUNET_NO; } if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_REVOCATION, &rm->purpose, &rm->signature, &rm->public_key)) { GNUNET_break_op (0); return GNUNET_NO; } return GNUNET_YES; } /** * Handle QUERY message from client. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_query_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct QueryMessage *qm = (const struct QueryMessage *) message; struct QueryResponseMessage qrm; struct GNUNET_HashCode hc; int res; GNUNET_CRYPTO_hash (&qm->key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &hc); res = GNUNET_CONTAINER_multihashmap_contains (revocation_map, &hc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, (GNUNET_NO == res) ? "Received revocation check for valid key `%s' from client\n" : "Received revocation check for revoked key `%s' from client\n", GNUNET_h2s (&hc)); qrm.header.size = htons (sizeof (struct QueryResponseMessage)); qrm.header.type = htons (GNUNET_MESSAGE_TYPE_REVOCATION_QUERY_RESPONSE); qrm.is_valid = htonl ((GNUNET_YES == res) ? GNUNET_NO : GNUNET_YES); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_notification_context_unicast (nc, client, &qrm.header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Flood the given revocation message to all neighbours. * * @param cls the `struct RevokeMessage` to flood * @param target a neighbour * @param value our `struct PeerEntry` for the neighbour * @return #GNUNET_OK (continue to iterate) */ static int do_flood (void *cls, const struct GNUNET_PeerIdentity *target, void *value) { const struct RevokeMessage *rm = cls; struct PeerEntry *pe = value; struct GNUNET_MQ_Envelope *e; struct RevokeMessage *cp; e = GNUNET_MQ_msg (cp, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE); *cp = *rm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Flooding revocation to `%s'\n", GNUNET_i2s (target)); GNUNET_MQ_send (pe->mq, e); return GNUNET_OK; } /** * Publicize revocation message. Stores the message locally in the * database and passes it to all connected neighbours (and adds it to * the set for future connections). * * @param rm message to publicize * @return #GNUNET_OK on success, #GNUNET_NO if we encountered an error, * #GNUNET_SYSERR if the message was malformed */ static int publicize_rm (const struct RevokeMessage *rm) { struct RevokeMessage *cp; struct GNUNET_HashCode hc; struct GNUNET_SET_Element e; GNUNET_CRYPTO_hash (&rm->public_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &hc); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (revocation_map, &hc)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Duplicate revocation received from peer. Ignored.\n")); return GNUNET_OK; } if (GNUNET_OK != verify_revoke_message (rm)) { GNUNET_break_op (0); return GNUNET_SYSERR; } /* write to disk */ if (sizeof (struct RevokeMessage) != GNUNET_DISK_file_write (revocation_db, rm, sizeof (struct RevokeMessage))) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "write"); return GNUNET_NO; } if (GNUNET_OK != GNUNET_DISK_file_sync (revocation_db)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sync"); return GNUNET_NO; } /* keep copy in memory */ cp = (struct RevokeMessage *) GNUNET_copy_message (&rm->header); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (revocation_map, &hc, cp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); /* add to set for future connections */ e.size = htons (rm->header.size); e.type = 0; e.data = rm; if (GNUNET_OK != GNUNET_SET_add_element (revocation_set, &e, NULL, NULL)) { GNUNET_break (0); return GNUNET_OK; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added revocation info to SET\n"); } /* flood to neighbours */ GNUNET_CONTAINER_multipeermap_iterate (peers, &do_flood, cp); return GNUNET_OK; } /** * Handle REVOKE message from client. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_revoke_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct RevokeMessage *rm; struct RevocationResponseMessage rrm; int ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE message from client\n"); rm = (const struct RevokeMessage *) message; if (GNUNET_SYSERR == (ret = publicize_rm (rm))) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } rrm.header.size = htons (sizeof (struct RevocationResponseMessage)); rrm.header.type = htons (GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE_RESPONSE); rrm.is_valid = htonl ((GNUNET_OK == ret) ? GNUNET_NO : GNUNET_YES); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_notification_context_unicast (nc, client, &rrm.header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Core handler for flooded revocation messages. * * @param cls closure unused * @param message message * @param peer peer identity this message is from (ignored) */ static int handle_p2p_revoke_message (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { const struct RevokeMessage *rm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received REVOKE message from peer\n"); rm = (const struct RevokeMessage *) message; GNUNET_break_op (GNUNET_SYSERR != publicize_rm (rm)); return GNUNET_OK; } /** * Callback for set operation results. Called for each element in the * result set. Each element contains a revocation, which we should * validate and then add to our revocation list (and set). * * @param cls closure * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK * @param status see `enum GNUNET_SET_Status` */ static void add_revocation (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { struct PeerEntry *peer_entry = cls; const struct RevokeMessage *rm; switch (status) { case GNUNET_SET_STATUS_OK: if (element->size != sizeof (struct RevokeMessage)) { GNUNET_break_op (0); return; } if (0 != element->type) { GNUNET_STATISTICS_update (stats, "# unsupported revocations received via set union", 1, GNUNET_NO); return; } rm = element->data; (void) handle_p2p_revoke_message (NULL, &peer_entry->id, &rm->header); GNUNET_STATISTICS_update (stats, "# revocation messages received via set union", 1, GNUNET_NO); break; case GNUNET_SET_STATUS_TIMEOUT: case GNUNET_SET_STATUS_FAILURE: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Error computing revocation set union with %s\n"), GNUNET_i2s (&peer_entry->id)); peer_entry->so = NULL; GNUNET_STATISTICS_update (stats, "# revocation set unions failed", 1, GNUNET_NO); break; case GNUNET_SET_STATUS_HALF_DONE: break; case GNUNET_SET_STATUS_DONE: peer_entry->so = NULL; GNUNET_STATISTICS_update (stats, "# revocation set unions completed", 1, GNUNET_NO); break; default: GNUNET_break (0); break; } } /** * The timeout for performing the set union has expired, * run the set operation on the revocation certificates. * * @param cls NULL * @param tc scheduler context (unused) */ static void transmit_task_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerEntry *peer_entry = cls; uint16_t salt; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting set exchange with peer `%s'\n", GNUNET_i2s (&peer_entry->id)); salt = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT16_MAX); peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK; peer_entry->so = GNUNET_SET_prepare (&peer_entry->id, &revocation_set_union_app_id, NULL, salt, GNUNET_SET_RESULT_ADDED, &add_revocation, peer_entry); if (GNUNET_OK != GNUNET_SET_commit (peer_entry->so, revocation_set)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("SET service crashed, terminating revocation service\n")); GNUNET_SCHEDULER_shutdown (); return; } } /** * Method called whenever a peer connects. Sets up the PeerEntry and * schedules the initial revocation set exchange with this peer. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerEntry *peer_entry; struct GNUNET_HashCode my_hash; struct GNUNET_HashCode peer_hash; if (0 == memcmp(peer, &my_identity, sizeof (my_identity))) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected to us\n", GNUNET_i2s (peer)); peer_entry = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == peer_entry) { peer_entry = GNUNET_new (struct PeerEntry); peer_entry->id = *peer; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (peers, peer, peer_entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } else { GNUNET_assert (NULL == peer_entry->mq); } peer_entry->mq = GNUNET_CORE_mq_create (core_api, peer); GNUNET_CRYPTO_hash (&my_identity, sizeof (my_identity), &my_hash); GNUNET_CRYPTO_hash (peer, sizeof (*peer), &peer_hash); if (0 < GNUNET_CRYPTO_hash_cmp (&my_hash, &peer_hash)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting SET operation with peer `%s'\n", GNUNET_i2s (peer)); peer_entry->transmit_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &transmit_task_cb, peer_entry); } GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO); } /** * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels * any pending transmission requests to that peer. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerEntry *pos; if (0 == memcmp(peer, &my_identity, sizeof (my_identity))) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' disconnected from us\n", GNUNET_i2s (peer)); pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == pos) { GNUNET_break (0); return; } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (peers, peer, pos)); GNUNET_MQ_destroy (pos->mq); if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (pos->transmit_task); pos->transmit_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != pos->so) { GNUNET_SET_operation_cancel (pos->so); pos->so = NULL; } GNUNET_free (pos); GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO); } /** * Free all values in a hash map. * * @param cls NULL * @param key the key * @param value value to free * @return #GNUNET_OK (continue to iterate) */ static int free_entry (void *cls, const struct GNUNET_HashCode *key, void *value) { GNUNET_free (value); return GNUNET_OK; } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != revocation_set) { GNUNET_SET_destroy (revocation_set); revocation_set = NULL; } if (NULL != revocation_union_listen_handle) { GNUNET_SET_listen_cancel (revocation_union_listen_handle); revocation_union_listen_handle = NULL; } if (NULL != core_api) { GNUNET_CORE_disconnect (core_api); core_api = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } if (NULL != peers) { GNUNET_CONTAINER_multipeermap_destroy (peers); peers = NULL; } if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } if (NULL != revocation_db) { GNUNET_DISK_file_close (revocation_db); revocation_db = NULL; } GNUNET_CONTAINER_multihashmap_iterate (revocation_map, &free_entry, NULL); GNUNET_CONTAINER_multihashmap_destroy (revocation_map); } /** * Called on core init/fail. * * @param cls service closure * @param identity the public identity of this peer */ static void core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { if (NULL == identity) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to core FAILED!\n"); GNUNET_SCHEDULER_shutdown (); return; } my_identity = *identity; } /** * Called when another peer wants to do a set operation with the * local peer. If a listen error occurs, the 'request' is NULL. * * @param cls closure * @param other_peer the other peer * @param context_msg message with application specific information from * the other peer * @param request request from the other peer (never NULL), use GNUNET_SET_accept() * to accept it, otherwise the request will be refused * Note that we can't just return value from the listen callback, * as it is also necessary to specify the set we want to do the * operation with, whith sometimes can be derived from the context * message. It's necessary to specify the timeout. */ static void handle_revocation_union_request (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request) { struct PeerEntry *peer_entry; if (NULL == request) { GNUNET_break (0); return; } peer_entry = GNUNET_CONTAINER_multipeermap_get (peers, other_peer); if (NULL == peer_entry) { peer_entry = GNUNET_new (struct PeerEntry); peer_entry->id = *other_peer; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (peers, other_peer, peer_entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } peer_entry->so = GNUNET_SET_accept (request, GNUNET_SET_RESULT_ADDED, &add_revocation, peer_entry); } /** * Handle network size estimate clients. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_query_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_QUERY, sizeof (struct QueryMessage)}, {&handle_revoke_message, NULL, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE, sizeof (struct RevokeMessage)}, {NULL, NULL, 0, 0} }; static const struct GNUNET_CORE_MessageHandler core_handlers[] = { {&handle_p2p_revoke_message, GNUNET_MESSAGE_TYPE_REVOCATION_REVOKE, sizeof (struct RevokeMessage)}, {NULL, 0, 0} }; char *fn; uint64_t left; struct RevokeMessage *rm; struct GNUNET_HashCode hc; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "REVOCATION", "DATABASE", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "REVOCATION", "DATABASE"); GNUNET_SCHEDULER_shutdown (); return; } cfg = c; srv = server; revocation_map = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO); nc = GNUNET_SERVER_notification_context_create (server, 1); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "REVOCATION", "WORKBITS", &revocation_work_required)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "REVOCATION", "WORKBITS"); GNUNET_SCHEDULER_shutdown (); GNUNET_free (fn); return; } if (revocation_work_required >= sizeof (struct GNUNET_HashCode) * 8) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "REVOCATION", "WORKBITS", _("Value is too large.\n")); GNUNET_SCHEDULER_shutdown (); GNUNET_free (fn); return; } revocation_set = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); revocation_union_listen_handle = GNUNET_SET_listen (cfg, GNUNET_SET_OPERATION_UNION, &revocation_set_union_app_id, &handle_revocation_union_request, NULL); revocation_db = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ); if (NULL == revocation_db) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "REVOCATION", "DATABASE", _("Could not open revocation database file!")); GNUNET_SCHEDULER_shutdown (); GNUNET_free (fn); return; } if (GNUNET_OK != GNUNET_DISK_file_size (fn, &left, GNUNET_YES, GNUNET_YES)) left = 0; while (left > sizeof (struct RevokeMessage)) { rm = GNUNET_new (struct RevokeMessage); if (sizeof (struct RevokeMessage) != GNUNET_DISK_file_read (revocation_db, rm, sizeof (struct RevokeMessage))) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "read", fn); GNUNET_free (rm); GNUNET_SCHEDULER_shutdown (); GNUNET_free (fn); return; } GNUNET_break (0 == ntohl (rm->reserved)); GNUNET_CRYPTO_hash (&rm->public_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &hc); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (revocation_map, &hc, rm, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } GNUNET_free (fn); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); GNUNET_SERVER_add_handlers (srv, handlers); /* Connect to core service and register core handlers */ core_api = GNUNET_CORE_connect (cfg, /* Main configuration */ NULL, /* Closure passed to functions */ &core_init, /* Call core_init once connected */ &handle_core_connect, /* Handle connects */ &handle_core_disconnect, /* Handle disconnects */ NULL, /* Don't want notified about all incoming messages */ GNUNET_NO, /* For header only inbound notification */ NULL, /* Don't want notified about all outbound messages */ GNUNET_NO, /* For header only outbound notification */ core_handlers); /* Register these handlers */ if (NULL == core_api) { GNUNET_SCHEDULER_shutdown (); return; } stats = GNUNET_STATISTICS_create ("revocation", cfg); } /** * The main function for the network size estimation service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { GNUNET_CRYPTO_hash ("revocation-set-union-application-id", strlen ("revocation-set-union-application-id"), &revocation_set_union_app_id); return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "revocation", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } #ifdef LINUX #include /** * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ void __attribute__ ((constructor)) GNUNET_ARM_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); malloc_trim (0); } #endif /* end of gnunet-service-revocation.c */ gnunet-0.10.1/src/namecache/0000755000175000017500000000000012320755627012576 500000000000000gnunet-0.10.1/src/namecache/gnunet-service-namecache.c0000644000175000017500000002777212241134531017524 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namecache/gnunet-service-namecache.c * @brief namecache for the GNUnet naming system * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_namecache_service.h" #include "gnunet_namecache_plugin.h" #include "gnunet_signatures.h" #include "namecache.h" #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * A namecache client */ struct NamecacheClient; /** * A namecache client */ struct NamecacheClient { /** * Next element in the DLL */ struct NamecacheClient *next; /** * Previous element in the DLL */ struct NamecacheClient *prev; /** * The client */ struct GNUNET_SERVER_Client *client; }; /** * Configuration handle. */ static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; /** * Database handle */ static struct GNUNET_NAMECACHE_PluginFunctions *GSN_database; /** * Name of the database plugin */ static char *db_lib_name; /** * Our notification context. */ static struct GNUNET_SERVER_NotificationContext *snc; /** * Head of the Client DLL */ static struct NamecacheClient *client_head; /** * Tail of the Client DLL */ static struct NamecacheClient *client_tail; /** * Notification context shared by all monitors. */ static struct GNUNET_SERVER_NotificationContext *monitor_nc; /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct NamecacheClient *nc; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namecache service\n"); if (NULL != snc) { GNUNET_SERVER_notification_context_destroy (snc); snc = NULL; } while (NULL != (nc = client_head)) { GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); GNUNET_SERVER_client_set_user_context (nc->client, (void *)NULL); GNUNET_free (nc); } GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); GNUNET_free (db_lib_name); db_lib_name = NULL; if (NULL != monitor_nc) { GNUNET_SERVER_notification_context_destroy (monitor_nc); monitor_nc = NULL; } } /** * Called whenever a client is disconnected. * Frees our resources associated with that client. * * @param cls closure * @param client identification of the client */ static void client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) { struct NamecacheClient *nc; if (NULL == client) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); if (NULL == (nc = GNUNET_SERVER_client_get_user_context (client, struct NamecacheClient))) return; GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); GNUNET_free (nc); } /** * Add a client to our list of active clients, if it is not yet * in there. * * @param client client to add * @return internal namecache client structure for this client */ static struct NamecacheClient * client_lookup (struct GNUNET_SERVER_Client *client) { struct NamecacheClient *nc; nc = GNUNET_SERVER_client_get_user_context (client, struct NamecacheClient); if (NULL != nc) return nc; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); nc = GNUNET_new (struct NamecacheClient); nc->client = client; GNUNET_SERVER_notification_context_add (snc, client); GNUNET_CONTAINER_DLL_insert (client_head, client_tail, nc); GNUNET_SERVER_client_set_user_context (client, nc); return nc; } /** * Context for name lookups passed from #handle_lookup_block to * #handle_lookup_block_it as closure */ struct LookupBlockContext { /** * The client to send the response to */ struct NamecacheClient *nc; /** * Operation id for the name lookup */ uint32_t request_id; }; /** * A #GNUNET_NAMECACHE_BlockCallback for name lookups in #handle_lookup_block * * @param cls a `struct LookupNameContext *` with information about the request * @param block the block */ static void handle_lookup_block_it (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct LookupBlockContext *lnc = cls; struct LookupBlockResponseMessage *r; size_t esize; esize = ntohl (block->purpose.size) - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) - sizeof (struct GNUNET_TIME_AbsoluteNBO); r = GNUNET_malloc (sizeof (struct LookupBlockResponseMessage) + esize); r->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE); r->gns_header.header.size = htons (sizeof (struct LookupBlockResponseMessage) + esize); r->gns_header.r_id = htonl (lnc->request_id); r->expire = block->expiration_time; r->signature = block->signature; r->derived_key = block->derived_key; memcpy (&r[1], &block[1], esize); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with expiration time %s\n", "NAMECACHE_LOOKUP_BLOCK_RESPONSE", GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (r->expire))); GNUNET_SERVER_notification_context_unicast (snc, lnc->nc->client, &r->gns_header.header, GNUNET_NO); GNUNET_free (r); } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK message * * @param cls unused * @param client client sending the message * @param message message of type 'struct LookupNameMessage' */ static void handle_lookup_block (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct LookupBlockMessage *ln_msg; struct LookupBlockContext lnc; struct NamecacheClient *nc; struct LookupBlockResponseMessage zir_end; int ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMECACHE_LOOKUP_BLOCK"); nc = client_lookup(client); ln_msg = (const struct LookupBlockMessage *) message; lnc.request_id = ntohl (ln_msg->gns_header.r_id); lnc.nc = nc; if (GNUNET_SYSERR == (ret = GSN_database->lookup_block (GSN_database->cls, &ln_msg->query, &handle_lookup_block_it, &lnc))) { /* internal error (in database plugin); might be best to just hang up on plugin rather than to signal that there are 'no' results, which might also be false... */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (0 == ret) { /* no records match at all, generate empty response */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending empty `%s' message\n", "NAMECACHE_LOOKUP_BLOCK_RESPONSE"); memset (&zir_end, 0, sizeof (zir_end)); zir_end.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE); zir_end.gns_header.header.size = htons (sizeof (struct LookupBlockResponseMessage)); zir_end.gns_header.r_id = ln_msg->gns_header.r_id; GNUNET_SERVER_notification_context_unicast (snc, client, &zir_end.gns_header.header, GNUNET_NO); } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE message * * @param cls unused * @param client client sending the message * @param message message of type 'struct BlockCacheMessage' */ static void handle_block_cache (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct NamecacheClient *nc; const struct BlockCacheMessage *rp_msg; struct BlockCacheResponseMessage rpr_msg; struct GNUNET_GNSRECORD_Block *block; size_t esize; int res; nc = client_lookup (client); if (ntohs (message->size) < sizeof (struct BlockCacheMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } rp_msg = (const struct BlockCacheMessage *) message; esize = ntohs (rp_msg->gns_header.header.size) - sizeof (struct BlockCacheMessage); block = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Block) + esize); block->signature = rp_msg->signature; block->derived_key = rp_msg->derived_key; block->purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + esize); block->expiration_time = rp_msg->expire; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message with expiration time %s\n", "NAMECACHE_BLOCK_CACHE", GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (block->expiration_time))); memcpy (&block[1], &rp_msg[1], esize); res = GSN_database->cache_block (GSN_database->cls, block); GNUNET_free (block); rpr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE); rpr_msg.gns_header.header.size = htons (sizeof (struct BlockCacheResponseMessage)); rpr_msg.gns_header.r_id = rp_msg->gns_header.r_id; rpr_msg.op_result = htonl (res); GNUNET_SERVER_notification_context_unicast (snc, nc->client, &rpr_msg.gns_header.header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Process namecache requests. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_lookup_block, NULL, GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK, sizeof (struct LookupBlockMessage)}, {&handle_block_cache, NULL, GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE, 0}, {NULL, NULL, 0, 0} }; char *database; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namecache service\n"); GSN_cfg = cfg; monitor_nc = GNUNET_SERVER_notification_context_create (server, 1); /* Loading database plugin */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "namecache", "database", &database)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namecache_%s", database); GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); GNUNET_free (database); if (NULL == GSN_database) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n", db_lib_name); GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); return; } /* Configuring server handles */ GNUNET_SERVER_add_handlers (server, handlers); snc = GNUNET_SERVER_notification_context_create (server, 16); GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, NULL); } /** * The main function for the template service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "namecache", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-namecache.c */ gnunet-0.10.1/src/namecache/plugin_namecache_postgres.c0000644000175000017500000003033312230201041020044 00000000000000 /* * This file is part of GNUnet * (C) 2009-2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file namecache/plugin_namecache_postgres.c * @brief postgres-based namecache backend * @author Christian Grothoff */ #include "platform.h" #include "gnunet_namecache_plugin.h" #include "gnunet_namecache_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_postgres_lib.h" #include "namecache.h" /** * After how many ms "busy" should a DB operation fail for good? * A low value makes sure that we are more responsive to requests * (especially PUTs). A high value guarantees a higher success * rate (SELECTs in iterate can take several seconds despite LIMIT=1). * * The default value of 1s should ensure that users do not experience * huge latencies while at the same time allowing operations to succeed * with reasonable probability. */ #define BUSY_TIMEOUT_MS 1000 /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_POSTGRES(db, level, cmd) do { GNUNET_log_from (level, "namecache-postgres", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) #define LOG(kind,...) GNUNET_log_from (kind, "namecache-postgres", __VA_ARGS__) /** * Context for all functions in this plugin. */ struct Plugin { const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Native Postgres database handle. */ PGconn *dbh; }; /** * Create our database indices. * * @param dbh handle to the database */ static void create_indices (PGconn * dbh) { /* create indices */ if ( (GNUNET_OK != GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)")) ) LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to create indices\n")); } /** * Initialize the database connections and associated * data structures (create tables and indices * as needed as well). * * @param plugin the plugin context (state for this module) * @return GNUNET_OK on success */ static int database_setup (struct Plugin *plugin) { PGresult *res; plugin->dbh = GNUNET_POSTGRES_connect (plugin->cfg, "namecache-postgres"); if (NULL == plugin->dbh) return GNUNET_SYSERR; if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, "namecache-postgres", "TEMPORARY_TABLE")) { res = PQexec (plugin->dbh, "CREATE TEMPORARY TABLE ns096blocks (" " query BYTEA NOT NULL DEFAULT ''," " block BYTEA NOT NULL DEFAULT ''," " expiration_time BIGINT NOT NULL DEFAULT 0" ")" "WITH OIDS"); } else { res = PQexec (plugin->dbh, "CREATE TABLE ns096blocks (" " query BYTEA NOT NULL DEFAULT ''," " block BYTEA NOT NULL DEFAULT ''," " expiration_time BIGINT NOT NULL DEFAULT 0" ")" "WITH OIDS"); } if ( (NULL == res) || ((PQresultStatus (res) != PGRES_COMMAND_OK) && (0 != strcmp ("42P07", /* duplicate table */ PQresultErrorField (res, PG_DIAG_SQLSTATE))))) { (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_COMMAND_OK, "CREATE TABLE", "ns096blocks"); PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } if (PQresultStatus (res) == PGRES_COMMAND_OK) create_indices (plugin->dbh); PQclear (res); if ((GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "cache_block", "INSERT INTO ns096blocks (query, block, expiration_time) VALUES " "($1, $2, $3)", 3)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "expire_blocks", "DELETE FROM ns096blocks WHERE expiration_time<$1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "delete_block", "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2", 2)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "lookup_block", "SELECT block FROM ns096blocks WHERE query=$1" " ORDER BY expiration_time DESC LIMIT 1", 1))) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } return GNUNET_OK; } /** * Removes any expired block. * * @param plugin the plugin */ static void namecache_postgres_expire_blocks (struct Plugin *plugin) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct GNUNET_TIME_AbsoluteNBO now_be = GNUNET_TIME_absolute_hton (now); const char *paramValues[] = { (const char *) &now_be }; int paramLengths[] = { sizeof (now_be) }; const int paramFormats[] = { 1 }; PGresult *res; res = PQexecPrepared (plugin->dbh, "expire_blocks", 1, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_COMMAND_OK, "PQexecPrepared", "expire_blocks")) return; PQclear (res); } /** * Delete older block in the datastore. * * @param plugin the plugin * @param query query for the block * @param expiration_time how old does the block have to be for deletion */ static void delete_old_block (struct Plugin *plugin, const struct GNUNET_HashCode *query, struct GNUNET_TIME_AbsoluteNBO expiration_time) { const char *paramValues[] = { (const char *) query, (const char *) &expiration_time }; int paramLengths[] = { sizeof (*query), sizeof (expiration_time) }; const int paramFormats[] = { 1, 1 }; PGresult *res; res = PQexecPrepared (plugin->dbh, "delete_block", 2, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_COMMAND_OK, "PQexecPrepared", "delete_block")) return; PQclear (res); } /** * Cache a block in the datastore. * * @param cls closure (internal context for the plugin) * @param block block to cache * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int namecache_postgres_cache_block (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct Plugin *plugin = cls; struct GNUNET_HashCode query; size_t block_size = ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature); const char *paramValues[] = { (const char *) &query, (const char *) block, (const char *) &block->expiration_time }; int paramLengths[] = { sizeof (query), (int) block_size, sizeof (block->expiration_time) }; const int paramFormats[] = { 1, 1, 1 }; PGresult *res; namecache_postgres_expire_blocks (plugin); GNUNET_CRYPTO_hash (&block->derived_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &query); if (block_size > 64 * 65536) { GNUNET_break (0); return GNUNET_SYSERR; } delete_old_block (plugin, &query, block->expiration_time); res = PQexecPrepared (plugin->dbh, "cache_block", 3, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_COMMAND_OK, "PQexecPrepared", "cache_block")) return GNUNET_SYSERR; PQclear (res); return GNUNET_OK; } /** * Get the block for a particular zone and label in the * datastore. Will return at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param query hash of public key derived from the zone and the label * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int namecache_postgres_lookup_block (void *cls, const struct GNUNET_HashCode *query, GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls) { struct Plugin *plugin = cls; const char *paramValues[] = { (const char *) query }; int paramLengths[] = { sizeof (*query) }; const int paramFormats[] = { 1 }; PGresult *res; unsigned int cnt; size_t bsize; const struct GNUNET_GNSRECORD_Block *block; res = PQexecPrepared (plugin->dbh, "lookup_block", 1, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", "lookup_block")) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failing lookup (postgres error)\n"); return GNUNET_SYSERR; } if (0 == (cnt = PQntuples (res))) { /* no result */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (no more results)\n"); PQclear (res); return GNUNET_NO; } GNUNET_assert (1 == cnt); GNUNET_assert (1 != PQnfields (res)); bsize = PQgetlength (res, 0, 0); block = (const struct GNUNET_GNSRECORD_Block *) PQgetvalue (res, 0, 0); if ( (bsize < sizeof (*block)) || (bsize != ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)) ) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Failing lookup (corrupt block)\n"); PQclear (res); return GNUNET_SYSERR; } iter (iter_cls, block); PQclear (res); return GNUNET_OK; } /** * Shutdown database connection and associate data * structures. * * @param plugin the plugin context (state for this module) */ static void database_shutdown (struct Plugin *plugin) { PQfinish (plugin->dbh); plugin->dbh = NULL; } /** * Entry point for the plugin. * * @param cls the "struct GNUNET_NAMECACHE_PluginEnvironment*" * @return NULL on error, othrewise the plugin context */ void * libgnunet_plugin_namecache_postgres_init (void *cls) { static struct Plugin plugin; const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_NAMECACHE_PluginFunctions *api; if (NULL != plugin.cfg) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); plugin.cfg = cfg; if (GNUNET_OK != database_setup (&plugin)) { database_shutdown (&plugin); return NULL; } api = GNUNET_new (struct GNUNET_NAMECACHE_PluginFunctions); api->cls = &plugin; api->cache_block = &namecache_postgres_cache_block; api->lookup_block = &namecache_postgres_lookup_block; LOG (GNUNET_ERROR_TYPE_INFO, _("Postgres database running\n")); return api; } /** * Exit point from the plugin. * * @param cls the plugin context (as returned by "init") * @return always NULL */ void * libgnunet_plugin_namecache_postgres_done (void *cls) { struct GNUNET_NAMECACHE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; database_shutdown (plugin); plugin->cfg = NULL; GNUNET_free (api); LOG (GNUNET_ERROR_TYPE_DEBUG, "postgres plugin is finished\n"); return NULL; } /* end of plugin_namecache_postgres.c */ gnunet-0.10.1/src/namecache/namecache.h0000644000175000017500000000575712227705277014613 00000000000000/* This file is part of GNUnet. (C) 2011-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namecache/namecache.h * @brief common internal definitions for namecache service * @author Matthias Wachs * @author Christian Grothoff */ #ifndef NAMECACHE_H #define NAMECACHE_H /** * Maximum length of any name, including 0-termination. */ #define MAX_NAME_LEN 256 GNUNET_NETWORK_STRUCT_BEGIN /** * Generic namecache message with op id */ struct GNUNET_NAMECACHE_Header { /** * header.type will be GNUNET_MESSAGE_TYPE_NAMECACHE_* * header.size will be message size */ struct GNUNET_MessageHeader header; /** * Request ID in NBO */ uint32_t r_id GNUNET_PACKED; }; /** * Lookup a block in the namecache */ struct LookupBlockMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK */ struct GNUNET_NAMECACHE_Header gns_header; /** * The query. */ struct GNUNET_HashCode query GNUNET_PACKED; }; /** * Lookup response */ struct LookupBlockResponseMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE */ struct GNUNET_NAMECACHE_Header gns_header; /** * Expiration time */ struct GNUNET_TIME_AbsoluteNBO expire; /** * Signature. */ struct GNUNET_CRYPTO_EcdsaSignature signature; /** * Derived public key. */ struct GNUNET_CRYPTO_EcdsaPublicKey derived_key; /* follwed by encrypted block data */ }; /** * Cache a record in the namecache. */ struct BlockCacheMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE */ struct GNUNET_NAMECACHE_Header gns_header; /** * Expiration time */ struct GNUNET_TIME_AbsoluteNBO expire; /** * Signature. */ struct GNUNET_CRYPTO_EcdsaSignature signature; /** * Derived public key. */ struct GNUNET_CRYPTO_EcdsaPublicKey derived_key; /* follwed by encrypted block data */ }; /** * Response to a request to cache a block. */ struct BlockCacheResponseMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE */ struct GNUNET_NAMECACHE_Header gns_header; /** * #GNUNET_OK on success, #GNUNET_SYSERR error */ int32_t op_result GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /* end of namecache.h */ #endif gnunet-0.10.1/src/namecache/gnunet-namecache.c0000644000175000017500000001376112241146166016066 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnunet-namecache.c * @brief command line tool to inspect the name cache * @author Christian Grothoff * * TODO: * - test */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_identity_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_namecache_service.h" /** * Handle to the namecache. */ static struct GNUNET_NAMECACHE_Handle *ns; /** * Queue entry for the 'query' operation. */ static struct GNUNET_NAMECACHE_QueueEntry *qe; /** * Name (label) of the records to list. */ static char *name; /** * Public key of the zone to look in. */ static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; /** * Public key of the zone to look in, in ASCII. */ static char *pkey; /** * Global return value */ static int ret; /** * Task run on shutdown. Cleans up everything. * * @param cls unused * @param tc scheduler context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != qe) { GNUNET_NAMECACHE_cancel (qe); qe = NULL; } if (NULL != ns) { GNUNET_NAMECACHE_disconnect (ns); ns = NULL; } } /** * Process a record that was stored in the namecache in a block. * * @param cls closure, NULL * @param rd_len number of entries in @a rd array * @param rd array of records with data to store */ static void display_records_from_block (void *cls, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { const char *typestring; char *s; unsigned int i; if (0 == rd_len) { FPRINTF (stdout, _("No records found for `%s'"), name); return; } FPRINTF (stdout, "%s:\n", name); for (i=0;i&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @HAVE_SQLITE_TRUE@check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) \ @HAVE_SQLITE_TRUE@ $(am__EXEEXT_3) libexec_PROGRAMS = gnunet-service-namecache$(EXEEXT) bin_PROGRAMS = gnunet-namecache$(EXEEXT) subdir = src/namecache DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/namecache.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = namecache.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunet_plugin_namecache_postgres_la_OBJECTS = \ plugin_namecache_postgres.lo libgnunet_plugin_namecache_postgres_la_OBJECTS = \ $(am_libgnunet_plugin_namecache_postgres_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_namecache_postgres_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_namecache_postgres_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_POSTGRES_TRUE@am_libgnunet_plugin_namecache_postgres_la_rpath = \ @HAVE_POSTGRES_TRUE@ -rpath $(plugindir) am_libgnunet_plugin_namecache_sqlite_la_OBJECTS = \ plugin_namecache_sqlite.lo libgnunet_plugin_namecache_sqlite_la_OBJECTS = \ $(am_libgnunet_plugin_namecache_sqlite_la_OBJECTS) libgnunet_plugin_namecache_sqlite_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_namecache_sqlite_la_LDFLAGS) $(LDFLAGS) -o \ $@ @HAVE_SQLITE_TRUE@am_libgnunet_plugin_namecache_sqlite_la_rpath = \ @HAVE_SQLITE_TRUE@ -rpath $(plugindir) libgnunetnamecache_la_DEPENDENCIES = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetnamecache_la_OBJECTS = namecache_api.lo libgnunetnamecache_la_OBJECTS = $(am_libgnunetnamecache_la_OBJECTS) libgnunetnamecache_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetnamecache_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_1 = test_plugin_namecache_sqlite$(EXEEXT) @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_2 = test_plugin_namecache_postgres$(EXEEXT) @HAVE_TESTING_TRUE@am__EXEEXT_3 = \ @HAVE_TESTING_TRUE@ test_namecache_api_cache_block$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_namecache_OBJECTS = gnunet-namecache.$(OBJEXT) gnunet_namecache_OBJECTS = $(am_gnunet_namecache_OBJECTS) am_gnunet_service_namecache_OBJECTS = \ gnunet-service-namecache.$(OBJEXT) gnunet_service_namecache_OBJECTS = \ $(am_gnunet_service_namecache_OBJECTS) am_test_namecache_api_cache_block_OBJECTS = \ test_namecache_api_cache_block.$(OBJEXT) test_namecache_api_cache_block_OBJECTS = \ $(am_test_namecache_api_cache_block_OBJECTS) test_namecache_api_cache_block_DEPENDENCIES = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_namecache_postgres_OBJECTS = \ test_plugin_namecache.$(OBJEXT) test_plugin_namecache_postgres_OBJECTS = \ $(am_test_plugin_namecache_postgres_OBJECTS) test_plugin_namecache_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_namecache_sqlite_OBJECTS = \ test_plugin_namecache.$(OBJEXT) test_plugin_namecache_sqlite_OBJECTS = \ $(am_test_plugin_namecache_sqlite_OBJECTS) test_plugin_namecache_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_namecache_postgres_la_SOURCES) \ $(libgnunet_plugin_namecache_sqlite_la_SOURCES) \ $(libgnunetnamecache_la_SOURCES) $(gnunet_namecache_SOURCES) \ $(gnunet_service_namecache_SOURCES) \ $(test_namecache_api_cache_block_SOURCES) \ $(test_plugin_namecache_postgres_SOURCES) \ $(test_plugin_namecache_sqlite_SOURCES) DIST_SOURCES = $(libgnunet_plugin_namecache_postgres_la_SOURCES) \ $(libgnunet_plugin_namecache_sqlite_la_SOURCES) \ $(libgnunetnamecache_la_SOURCES) $(gnunet_namecache_SOURCES) \ $(gnunet_service_namecache_SOURCES) \ $(test_namecache_api_cache_block_SOURCES) \ $(test_plugin_namecache_postgres_SOURCES) \ $(test_plugin_namecache_sqlite_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ namecache.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIBS = -lgcov @HAVE_SQLITE_TRUE@SQLITE_PLUGIN = libgnunet_plugin_namecache_sqlite.la @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@SQLITE_TESTS = test_plugin_namecache_sqlite @HAVE_POSTGRES_TRUE@POSTGRES_PLUGIN = libgnunet_plugin_namecache_postgres.la @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@POSTGRES_TESTS = test_plugin_namecache_postgres # testcases do not even build yet; thus: experimental! @HAVE_TESTING_TRUE@TESTING_TESTS = \ @HAVE_TESTING_TRUE@ test_namecache_api_cache_block @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = \ @ENABLE_TEST_RUN_TRUE@ $(check_PROGRAMS) lib_LTLIBRARIES = \ libgnunetnamecache.la libgnunetnamecache_la_SOURCES = \ namecache_api.c \ namecache.h libgnunetnamecache_la_LIBADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetnamecache_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 gnunet_namecache_SOURCES = \ gnunet-namecache.c gnunet_namecache_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la \ $(GN_LIBINTL) gnunet_namecache_DEPENDENCIES = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la gnunet_service_namecache_SOURCES = \ gnunet-service-namecache.c gnunet_service_namecache_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la \ $(GN_LIBINTL) gnunet_service_namecache_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ $(POSTGRES_PLUGIN) libgnunet_plugin_namecache_sqlite_la_SOURCES = \ plugin_namecache_sqlite.c libgnunet_plugin_namecache_sqlite_la_LIBADD = \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_namecache_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_namecache_sqlite_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la libgnunet_plugin_namecache_postgres_la_SOURCES = \ plugin_namecache_postgres.c libgnunet_plugin_namecache_postgres_la_LIBADD = \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ $(LTLIBINTL) libgnunet_plugin_namecache_postgres_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_namecache_postgres_la_DEPENDENCIES = \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la test_namecache_api_cache_block_SOURCES = \ test_namecache_api_cache_block.c test_namecache_api_cache_block_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_namecache_sqlite_SOURCES = \ test_plugin_namecache.c test_plugin_namecache_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_namecache_postgres_SOURCES = \ test_plugin_namecache.c test_plugin_namecache_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_namecache_api.conf \ test_plugin_namecache_sqlite.conf \ test_plugin_namecache_postgres.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/namecache/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/namecache/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): namecache.conf: $(top_builddir)/config.status $(srcdir)/namecache.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_namecache_postgres.la: $(libgnunet_plugin_namecache_postgres_la_OBJECTS) $(libgnunet_plugin_namecache_postgres_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_namecache_postgres_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_namecache_postgres_la_LINK) $(am_libgnunet_plugin_namecache_postgres_la_rpath) $(libgnunet_plugin_namecache_postgres_la_OBJECTS) $(libgnunet_plugin_namecache_postgres_la_LIBADD) $(LIBS) libgnunet_plugin_namecache_sqlite.la: $(libgnunet_plugin_namecache_sqlite_la_OBJECTS) $(libgnunet_plugin_namecache_sqlite_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_namecache_sqlite_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_namecache_sqlite_la_LINK) $(am_libgnunet_plugin_namecache_sqlite_la_rpath) $(libgnunet_plugin_namecache_sqlite_la_OBJECTS) $(libgnunet_plugin_namecache_sqlite_la_LIBADD) $(LIBS) libgnunetnamecache.la: $(libgnunetnamecache_la_OBJECTS) $(libgnunetnamecache_la_DEPENDENCIES) $(EXTRA_libgnunetnamecache_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetnamecache_la_LINK) -rpath $(libdir) $(libgnunetnamecache_la_OBJECTS) $(libgnunetnamecache_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-namecache$(EXEEXT): $(gnunet_namecache_OBJECTS) $(gnunet_namecache_DEPENDENCIES) $(EXTRA_gnunet_namecache_DEPENDENCIES) @rm -f gnunet-namecache$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_namecache_OBJECTS) $(gnunet_namecache_LDADD) $(LIBS) gnunet-service-namecache$(EXEEXT): $(gnunet_service_namecache_OBJECTS) $(gnunet_service_namecache_DEPENDENCIES) $(EXTRA_gnunet_service_namecache_DEPENDENCIES) @rm -f gnunet-service-namecache$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_namecache_OBJECTS) $(gnunet_service_namecache_LDADD) $(LIBS) test_namecache_api_cache_block$(EXEEXT): $(test_namecache_api_cache_block_OBJECTS) $(test_namecache_api_cache_block_DEPENDENCIES) $(EXTRA_test_namecache_api_cache_block_DEPENDENCIES) @rm -f test_namecache_api_cache_block$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namecache_api_cache_block_OBJECTS) $(test_namecache_api_cache_block_LDADD) $(LIBS) test_plugin_namecache_postgres$(EXEEXT): $(test_plugin_namecache_postgres_OBJECTS) $(test_plugin_namecache_postgres_DEPENDENCIES) $(EXTRA_test_plugin_namecache_postgres_DEPENDENCIES) @rm -f test_plugin_namecache_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_namecache_postgres_OBJECTS) $(test_plugin_namecache_postgres_LDADD) $(LIBS) test_plugin_namecache_sqlite$(EXEEXT): $(test_plugin_namecache_sqlite_OBJECTS) $(test_plugin_namecache_sqlite_DEPENDENCIES) $(EXTRA_test_plugin_namecache_sqlite_DEPENDENCIES) @rm -f test_plugin_namecache_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_namecache_sqlite_OBJECTS) $(test_plugin_namecache_sqlite_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-namecache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-namecache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namecache_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_namecache_postgres.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_namecache_sqlite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namecache_api_cache_block.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_namecache.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_plugin_namecache_sqlite.log: test_plugin_namecache_sqlite$(EXEEXT) @p='test_plugin_namecache_sqlite$(EXEEXT)'; \ b='test_plugin_namecache_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_namecache_postgres.log: test_plugin_namecache_postgres$(EXEEXT) @p='test_plugin_namecache_postgres$(EXEEXT)'; \ b='test_plugin_namecache_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namecache_api_cache_block.log: test_namecache_api_cache_block$(EXEEXT) @p='test_namecache_api_cache_block$(EXEEXT)'; \ b='test_namecache_api_cache_block'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/namecache/namecache_api.c0000644000175000017500000004434212300637201015407 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namecache/namecache_api.c * @brief API to access the NAMECACHE service * @author Martin Schanzenbach * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_crypto_lib.h" #include "gnunet_constants.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_signatures.h" #include "gnunet_namecache_service.h" #include "namecache.h" #define LOG(kind,...) GNUNET_log_from (kind, "namecache-api",__VA_ARGS__) /** * An QueueEntry used to store information for a pending * NAMECACHE record operation */ struct GNUNET_NAMECACHE_QueueEntry { /** * Kept in a DLL. */ struct GNUNET_NAMECACHE_QueueEntry *next; /** * Kept in a DLL. */ struct GNUNET_NAMECACHE_QueueEntry *prev; /** * Main handle to access the namecache. */ struct GNUNET_NAMECACHE_Handle *nsh; /** * Continuation to call */ GNUNET_NAMECACHE_ContinuationWithStatus cont; /** * Closure for @e cont. */ void *cont_cls; /** * Function to call with the blocks we get back; or NULL. */ GNUNET_NAMECACHE_BlockProcessor block_proc; /** * Closure for @e block_proc. */ void *block_proc_cls; /** * The operation id this zone iteration operation has */ uint32_t op_id; }; /** * Message in linked list we should send to the service. The * actual binary message follows this struct. */ struct PendingMessage { /** * Kept in a DLL. */ struct PendingMessage *next; /** * Kept in a DLL. */ struct PendingMessage *prev; /** * Size of the message. */ size_t size; }; /** * Connection to the NAMECACHE service. */ struct GNUNET_NAMECACHE_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Currently pending transmission request (or NULL). */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of linked list of pending messages to send to the service */ struct PendingMessage *pending_head; /** * Tail of linked list of pending messages to send to the service */ struct PendingMessage *pending_tail; /** * Head of pending namecache queue entries */ struct GNUNET_NAMECACHE_QueueEntry *op_head; /** * Tail of pending namecache queue entries */ struct GNUNET_NAMECACHE_QueueEntry *op_tail; /** * Reconnect task */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Delay introduced before we reconnect. */ struct GNUNET_TIME_Relative reconnect_delay; /** * Should we reconnect to service due to some serious error? */ int reconnect; /** * Did we start to receive yet? */ int is_receiving; /** * The last operation id used for a NAMECACHE operation */ uint32_t last_op_id_used; }; /** * Disconnect from service and then reconnect. * * @param h our handle */ static void force_reconnect (struct GNUNET_NAMECACHE_Handle *h); /** * Handle an incoming message of type * #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE. * * @param qe the respective entry in the message queue * @param msg the message we received * @param size the message size * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and we did NOT notify the client */ static int handle_lookup_block_response (struct GNUNET_NAMECACHE_QueueEntry *qe, const struct LookupBlockResponseMessage *msg, size_t size) { struct GNUNET_GNSRECORD_Block *block; char buf[size + sizeof (struct GNUNET_GNSRECORD_Block) - sizeof (struct LookupBlockResponseMessage)]; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n", "LOOKUP_BLOCK_RESPONSE"); if (0 == GNUNET_TIME_absolute_ntoh (msg->expire).abs_value_us) { /* no match found */ if (NULL != qe->block_proc) qe->block_proc (qe->block_proc_cls, NULL); return GNUNET_OK; } block = (struct GNUNET_GNSRECORD_Block *) buf; block->signature = msg->signature; block->derived_key = msg->derived_key; block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); block->purpose.size = htonl (size - sizeof (struct LookupBlockResponseMessage) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); block->expiration_time = msg->expire; memcpy (&block[1], &msg[1], size - sizeof (struct LookupBlockResponseMessage)); if (GNUNET_OK != GNUNET_GNSRECORD_block_verify (block)) { GNUNET_break (0); return GNUNET_SYSERR; } if (NULL != qe->block_proc) qe->block_proc (qe->block_proc_cls, block); else GNUNET_break (0); return GNUNET_OK; } /** * Handle an incoming message of type * #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE * * @param qe the respective entry in the message queue * @param msg the message we received * @param size the message size * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and we did NOT notify the client */ static int handle_block_cache_response (struct GNUNET_NAMECACHE_QueueEntry *qe, const struct BlockCacheResponseMessage *msg, size_t size) { int res; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n", "BLOCK_CACHE_RESPONSE"); res = ntohl (msg->op_result); /* TODO: add actual error message from namecache to response... */ if (NULL != qe->cont) qe->cont (qe->cont_cls, res, (GNUNET_OK == res) ? NULL : _("Namecache failed to cache block")); return GNUNET_OK; } /** * Handle incoming messages for record operations * * @param qe the respective zone iteration handle * @param msg the message we received * @param type the message type in host byte order * @param size the message size * @return #GNUNET_OK on success, #GNUNET_NO if we notified the client about * the error, #GNUNET_SYSERR on error and we did NOT notify the client */ static int manage_record_operations (struct GNUNET_NAMECACHE_QueueEntry *qe, const struct GNUNET_MessageHeader *msg, uint16_t type, size_t size) { /* handle different message type */ switch (type) { case GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE: if (size < sizeof (struct LookupBlockResponseMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } return handle_lookup_block_response (qe, (const struct LookupBlockResponseMessage *) msg, size); case GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE: if (size != sizeof (struct BlockCacheResponseMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } return handle_block_cache_response (qe, (const struct BlockCacheResponseMessage *) msg, size); default: GNUNET_break (0); return GNUNET_SYSERR; } } /** * Type of a function to call when we receive a message * from the service. * * @param cls the `struct GNUNET_NAMECACHE_SchedulingHandle` * @param msg message received, NULL on timeout or fatal error */ static void process_namecache_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_NAMECACHE_Handle *h = cls; const struct GNUNET_NAMECACHE_Header *gm; struct GNUNET_NAMECACHE_QueueEntry *qe; uint16_t size; uint16_t type; uint32_t r_id; int ret; if (NULL == msg) { force_reconnect (h); return; } size = ntohs (msg->size); type = ntohs (msg->type); if (size < sizeof (struct GNUNET_NAMECACHE_Header)) { GNUNET_break_op (0); GNUNET_CLIENT_receive (h->client, &process_namecache_message, h, GNUNET_TIME_UNIT_FOREVER_REL); return; } gm = (const struct GNUNET_NAMECACHE_Header *) msg; r_id = ntohl (gm->r_id); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message type %u size %u op %u\n", (unsigned int) type, (unsigned int) size, (unsigned int) r_id); /* Is it a record related operation ? */ for (qe = h->op_head; qe != NULL; qe = qe->next) if (qe->op_id == r_id) break; if (NULL != qe) { ret = manage_record_operations (qe, msg, type, size); if (GNUNET_SYSERR == ret) { /* protocol error, need to reconnect */ h->reconnect = GNUNET_YES; } else { /* client was notified about success or failure, clean up 'qe' */ GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe); GNUNET_free (qe); } } if (GNUNET_YES == h->reconnect) { force_reconnect (h); return; } GNUNET_CLIENT_receive (h->client, &process_namecache_message, h, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Transmit messages from the message queue to the service * (if there are any, and if we are not already trying). * * @param h handle to use */ static void do_transmit (struct GNUNET_NAMECACHE_Handle *h); /** * We can now transmit a message to NAMECACHE. Do it. * * @param cls the `struct GNUNET_NAMECACHE_Handle` * @param size number of bytes we can transmit * @param buf where to copy the messages * @return number of bytes copied into @a buf */ static size_t transmit_message_to_namecache (void *cls, size_t size, void *buf) { struct GNUNET_NAMECACHE_Handle *h = cls; struct PendingMessage *p; size_t ret; char *cbuf; h->th = NULL; if ((0 == size) || (NULL == buf)) { force_reconnect (h); return 0; } ret = 0; cbuf = buf; while ( (NULL != (p = h->pending_head)) && (p->size <= size) ) { memcpy (&cbuf[ret], &p[1], p->size); ret += p->size; size -= p->size; GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); if (GNUNET_NO == h->is_receiving) { h->is_receiving = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &process_namecache_message, h, GNUNET_TIME_UNIT_FOREVER_REL); } GNUNET_free (p); } do_transmit (h); return ret; } /** * Transmit messages from the message queue to the service * (if there are any, and if we are not already trying). * * @param h handle to use */ static void do_transmit (struct GNUNET_NAMECACHE_Handle *h) { struct PendingMessage *p; if (NULL != h->th) return; /* transmission request already pending */ if (NULL == (p = h->pending_head)) return; /* transmission queue empty */ if (NULL == h->client) return; /* currently reconnecting */ h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_message_to_namecache, h); GNUNET_break (NULL != h->th); } /** * Reconnect to namecache service. * * @param h the handle to the NAMECACHE service */ static void reconnect (struct GNUNET_NAMECACHE_Handle *h) { GNUNET_assert (NULL == h->client); h->client = GNUNET_CLIENT_connect ("namecache", h->cfg); GNUNET_assert (NULL != h->client); do_transmit (h); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAMECACHE_Handle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; reconnect (h); } /** * Disconnect from service and then reconnect. * * @param h our handle */ static void force_reconnect (struct GNUNET_NAMECACHE_Handle *h) { if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } h->reconnect = GNUNET_NO; GNUNET_CLIENT_disconnect (h->client); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting to namecache\n"); h->is_receiving = GNUNET_NO; h->client = NULL; h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect_task, h); } /** * Get a fresh operation id to distinguish between namecache requests * * @param h the namecache handle * @return next operation id to use */ static uint32_t get_op_id (struct GNUNET_NAMECACHE_Handle *h) { return h->last_op_id_used++; } /** * Initialize the connection with the NAMECACHE service. * * @param cfg configuration to use * @return handle to the GNS service, or NULL on error */ struct GNUNET_NAMECACHE_Handle * GNUNET_NAMECACHE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAMECACHE_Handle *h; h = GNUNET_new (struct GNUNET_NAMECACHE_Handle); h->cfg = cfg; h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h); h->last_op_id_used = 0; return h; } /** * Disconnect from the namecache service (and free associated * resources). * * @param h handle to the namecache */ void GNUNET_NAMECACHE_disconnect (struct GNUNET_NAMECACHE_Handle *h) { struct PendingMessage *p; struct GNUNET_NAMECACHE_QueueEntry *q; LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); GNUNET_assert (NULL != h); if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } while (NULL != (p = h->pending_head)) { GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); GNUNET_free (p); } GNUNET_break (NULL == h->op_head); while (NULL != (q = h->op_head)) { GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q); GNUNET_free (q); } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (h); } /** * Store an item in the namecache. If the item is already present, * it is replaced with the new record. * * @param h handle to the namecache * @param block block to store * @param cont continuation to call when done * @param cont_cls closure for cont * @return handle to abort the request */ struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_block_cache (struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_GNSRECORD_Block *block, GNUNET_NAMECACHE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_NAMECACHE_QueueEntry *qe; struct PendingMessage *pe; struct BlockCacheMessage *msg; uint32_t rid; size_t blen; size_t msg_size; GNUNET_assert (NULL != h); blen = ntohl (block->purpose.size) - sizeof (struct GNUNET_TIME_AbsoluteNBO) - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose); rid = get_op_id (h); qe = GNUNET_new (struct GNUNET_NAMECACHE_QueueEntry); qe->nsh = h; qe->cont = cont; qe->cont_cls = cont_cls; qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); /* setup msg */ msg_size = sizeof (struct BlockCacheMessage) + blen; pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; msg = (struct BlockCacheMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); msg->expire = block->expiration_time; msg->signature = block->signature; msg->derived_key = block->derived_key; memcpy (&msg[1], &block[1], blen); LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with size %u and expiration %s\n", "NAMECACHE_BLOCK_CACHE", (unsigned int) msg_size, GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (msg->expire))); GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit (h); return qe; } /** * Get a result for a particular key from the namecache. The processor * will only be called once. * * @param h handle to the namecache * @param derived_hash hash of zone key combined with name to lookup * @param proc function to call on the matching block, or with * NULL if there is no matching block * @param proc_cls closure for proc * @return a handle that can be used to cancel */ struct GNUNET_NAMECACHE_QueueEntry * GNUNET_NAMECACHE_lookup_block (struct GNUNET_NAMECACHE_Handle *h, const struct GNUNET_HashCode *derived_hash, GNUNET_NAMECACHE_BlockProcessor proc, void *proc_cls) { struct GNUNET_NAMECACHE_QueueEntry *qe; struct PendingMessage *pe; struct LookupBlockMessage *msg; size_t msg_size; uint32_t rid; LOG (GNUNET_ERROR_TYPE_DEBUG, "Looking for block under %s\n", GNUNET_h2s (derived_hash)); rid = get_op_id(h); qe = GNUNET_new (struct GNUNET_NAMECACHE_QueueEntry); qe->nsh = h; qe->block_proc = proc; qe->block_proc_cls = proc_cls; qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); msg_size = sizeof (struct LookupBlockMessage); pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; msg = (struct LookupBlockMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); msg->query = *derived_hash; GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit (h); return qe; } /** * Cancel a namecache operation. The final callback from the * operation must not have been done yet. * * @param qe operation to cancel */ void GNUNET_NAMECACHE_cancel (struct GNUNET_NAMECACHE_QueueEntry *qe) { struct GNUNET_NAMECACHE_Handle *h = qe->nsh; GNUNET_assert (NULL != qe); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe); GNUNET_free(qe); } /* end of namecache_api.c */ gnunet-0.10.1/src/namecache/test_plugin_namecache_sqlite.conf0000644000175000017500000000012112227705277021263 00000000000000[namestore-sqlite] FILENAME = /tmp/gnunet-test-plugin-namestore-sqlite/sqlite.db gnunet-0.10.1/src/namecache/test_plugin_namecache.c0000644000175000017500000000700712227705277017211 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file namecache/test_plugin_namecache.c * @brief Test for the namecache plugins * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_namecache_plugin.h" #include "gnunet_testing_lib.h" static int ok; /** * Name of plugin under test. */ static const char *plugin_name; /** * Function called when the service shuts down. Unloads our namecache * plugin. * * @param api api to unload */ static void unload_plugin (struct GNUNET_NAMECACHE_PluginFunctions *api) { char *libname; GNUNET_asprintf (&libname, "libgnunet_plugin_namecache_%s", plugin_name); GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api)); GNUNET_free (libname); } /** * Load the namecache plugin. * * @param cfg configuration to pass * @return NULL on error */ static struct GNUNET_NAMECACHE_PluginFunctions * load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAMECACHE_PluginFunctions *ret; char *libname; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' namecache plugin\n"), plugin_name); GNUNET_asprintf (&libname, "libgnunet_plugin_namecache_%s", plugin_name); if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void*) cfg))) { FPRINTF (stderr, "Failed to load plugin `%s'!\n", plugin_name); GNUNET_free (libname); return NULL; } GNUNET_free (libname); return ret; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAMECACHE_PluginFunctions *nsp; ok = 0; nsp = load_plugin (cfg); if (NULL == nsp) { FPRINTF (stderr, "%s", "Failed to initialize namecache. Database likely not setup, skipping test.\n"); return; } unload_plugin (nsp); } int main (int argc, char *argv[]) { char cfg_name[128]; char *const xargv[] = { "test-plugin-namecache", "-c", cfg_name, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namecache-sqlite"); GNUNET_log_setup ("test-plugin-namecache", "WARNING", NULL); plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_plugin_namecache_%s.conf", plugin_name); GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "test-plugin-namecache", "nohelp", options, &run, NULL); if (ok != 0) FPRINTF (stderr, "Missed some testcases: %d\n", ok); GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namecache-sqlite"); return ok; } /* end of test_plugin_namecache.c */ gnunet-0.10.1/src/namecache/test_plugin_namecache_postgres.conf0000644000175000017500000000013312227705277021633 00000000000000[namestore-postgres] CONFIG = connect_timeout=10; dbname=gnunetcheck TEMPORARY_TABLE = YES gnunet-0.10.1/src/namecache/plugin_namecache_sqlite.c0000644000175000017500000004246512227705277017542 00000000000000 /* * This file is part of GNUnet * (C) 2009-2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file namecache/plugin_namecache_sqlite.c * @brief sqlite-based namecache backend * @author Christian Grothoff */ #include "platform.h" #include "gnunet_namecache_plugin.h" #include "gnunet_namecache_service.h" #include "gnunet_gnsrecord_lib.h" #include "namecache.h" #include /** * After how many ms "busy" should a DB operation fail for good? A * low value makes sure that we are more responsive to requests * (especially PUTs). A high value guarantees a higher success rate * (SELECTs in iterate can take several seconds despite LIMIT=1). * * The default value of 1s should ensure that users do not experience * huge latencies while at the same time allowing operations to * succeed with reasonable probability. */ #define BUSY_TIMEOUT_MS 1000 /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "namecache-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) #define LOG(kind,...) GNUNET_log_from (kind, "namecache-sqlite", __VA_ARGS__) /** * Context for all functions in this plugin. */ struct Plugin { const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Database filename. */ char *fn; /** * Native SQLite database handle. */ sqlite3 *dbh; /** * Precompiled SQL for caching a block */ sqlite3_stmt *cache_block; /** * Precompiled SQL for deleting an older block */ sqlite3_stmt *delete_block; /** * Precompiled SQL for looking up a block */ sqlite3_stmt *lookup_block; /** * Precompiled SQL for removing expired blocks */ sqlite3_stmt *expire_blocks; }; /** * @brief Prepare a SQL statement * * @param dbh handle to the database * @param zSql SQL statement, UTF-8 encoded * @param ppStmt set to the prepared statement * @return 0 on success */ static int sq_prepare (sqlite3 * dbh, const char *zSql, sqlite3_stmt ** ppStmt) { char *dummy; int result; result = sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt, (const char **) &dummy); LOG (GNUNET_ERROR_TYPE_DEBUG, "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result); return result; } /** * Create our database indices. * * @param dbh handle to the database */ static void create_indices (sqlite3 * dbh) { /* create indices */ if ( (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_query_hash ON ns096blocks (query,expiration_time)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_block_expiration ON ns096blocks (expiration_time)", NULL, NULL, NULL)) ) LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to create indices: %s\n", sqlite3_errmsg (dbh)); } #if 0 #define CHECK(a) GNUNET_break(a) #define ENULL NULL #else #define ENULL &e #define ENULL_DEFINED 1 #define CHECK(a) if (! a) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); } #endif /** * Initialize the database connections and associated * data structures (create tables and indices * as needed as well). * * @param plugin the plugin context (state for this module) * @return #GNUNET_OK on success */ static int database_setup (struct Plugin *plugin) { sqlite3_stmt *stmt; char *afsdir; #if ENULL_DEFINED char *e; #endif if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "namecache-sqlite", "FILENAME", &afsdir)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "namecache-sqlite", "FILENAME"); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_DISK_file_test (afsdir)) { if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir)) { GNUNET_break (0); GNUNET_free (afsdir); return GNUNET_SYSERR; } } /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ plugin->fn = afsdir; /* Open database and precompile statements */ if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Unable to initialize SQLite: %s.\n"), sqlite3_errmsg (plugin->dbh)); return GNUNET_SYSERR; } CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA synchronous=NORMAL", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\"", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA count_changes=OFF", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA page_size=4092", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS)); /* Create tables */ CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "SELECT 1 FROM sqlite_master WHERE tbl_name = 'ns096blocks'", &stmt)); if ((sqlite3_step (stmt) == SQLITE_DONE) && (sqlite3_exec (plugin->dbh, "CREATE TABLE ns096blocks (" " query BLOB NOT NULL DEFAULT ''," " block BLOB NOT NULL DEFAULT ''," " expiration_time INT8 NOT NULL DEFAULT 0" ")", NULL, NULL, NULL) != SQLITE_OK)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); sqlite3_finalize (stmt); return GNUNET_SYSERR; } sqlite3_finalize (stmt); create_indices (plugin->dbh); if ((sq_prepare (plugin->dbh, "INSERT INTO ns096blocks (query,block,expiration_time) VALUES (?, ?, ?)", &plugin->cache_block) != SQLITE_OK) || (sq_prepare (plugin->dbh, "DELETE FROM ns096blocks WHERE expiration_timeexpire_blocks) != SQLITE_OK) || (sq_prepare (plugin->dbh, "DELETE FROM ns096blocks WHERE query=? AND expiration_time<=?", &plugin->delete_block) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT block FROM ns096blocks WHERE query=? ORDER BY expiration_time DESC LIMIT 1", &plugin->lookup_block) != SQLITE_OK) ) { LOG_SQLITE (plugin,GNUNET_ERROR_TYPE_ERROR, "precompiling"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Shutdown database connection and associate data * structures. * @param plugin the plugin context (state for this module) */ static void database_shutdown (struct Plugin *plugin) { int result; sqlite3_stmt *stmt; if (NULL != plugin->cache_block) sqlite3_finalize (plugin->cache_block); if (NULL != plugin->lookup_block) sqlite3_finalize (plugin->lookup_block); if (NULL != plugin->expire_blocks) sqlite3_finalize (plugin->expire_blocks); if (NULL != plugin->delete_block) sqlite3_finalize (plugin->delete_block); result = sqlite3_close (plugin->dbh); if (result == SQLITE_BUSY) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Tried to close sqlite without finalizing all prepared statements.\n")); stmt = sqlite3_next_stmt (plugin->dbh, NULL); while (stmt != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Closing statement %p\n", stmt); result = sqlite3_finalize (stmt); if (result != SQLITE_OK) GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", "Failed to close statement %p: %d\n", stmt, result); stmt = sqlite3_next_stmt (plugin->dbh, NULL); } result = sqlite3_close (plugin->dbh); } if (SQLITE_OK != result) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); GNUNET_free_non_null (plugin->fn); } /** * Removes any expired block. * * @param plugin the plugin */ static void namecache_sqlite_expire_blocks (struct Plugin *plugin) { struct GNUNET_TIME_Absolute now; int n; now = GNUNET_TIME_absolute_get (); if (SQLITE_OK != sqlite3_bind_int64 (plugin->expire_blocks, 1, now.abs_value_us)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->expire_blocks)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return; } n = sqlite3_step (plugin->expire_blocks); if (SQLITE_OK != sqlite3_reset (plugin->expire_blocks)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); switch (n) { case SQLITE_DONE: GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Records expired\n"); return; case SQLITE_BUSY: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return; } } /** * Cache a block in the datastore. * * @param cls closure (internal context for the plugin) * @param block block to cache * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int namecache_sqlite_cache_block (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct Plugin *plugin = cls; struct GNUNET_HashCode query; struct GNUNET_TIME_Absolute expiration; int64_t dval; size_t block_size; int n; namecache_sqlite_expire_blocks (plugin); GNUNET_CRYPTO_hash (&block->derived_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &query); expiration = GNUNET_TIME_absolute_ntoh (block->expiration_time); dval = (int64_t) expiration.abs_value_us; if (dval < 0) dval = INT64_MAX; block_size = ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature); if (block_size > 64 * 65536) { GNUNET_break (0); return GNUNET_SYSERR; } /* delete old version of the block */ if ( (SQLITE_OK != sqlite3_bind_blob (plugin->delete_block, 1, &query, sizeof (struct GNUNET_HashCode), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int64 (plugin->delete_block, 2, dval)) ) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->delete_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } n = sqlite3_step (plugin->delete_block); switch (n) { case SQLITE_DONE: GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Old block deleted\n"); break; case SQLITE_BUSY: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); break; } if (SQLITE_OK != sqlite3_reset (plugin->delete_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); /* insert new version of the block */ if ((SQLITE_OK != sqlite3_bind_blob (plugin->cache_block, 1, &query, sizeof (struct GNUNET_HashCode), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_blob (plugin->cache_block, 2, block, block_size, SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int64 (plugin->cache_block, 3, dval))) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->cache_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Caching block under derived key `%s'\n", GNUNET_h2s_full (&query)); n = sqlite3_step (plugin->cache_block); if (SQLITE_OK != sqlite3_reset (plugin->cache_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); switch (n) { case SQLITE_DONE: LOG (GNUNET_ERROR_TYPE_DEBUG, "Record stored\n"); return GNUNET_OK; case SQLITE_BUSY: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return GNUNET_NO; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return GNUNET_SYSERR; } } /** * Get the block for a particular zone and label in the * datastore. Will return at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param query hash of public key derived from the zone and the label * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int namecache_sqlite_lookup_block (void *cls, const struct GNUNET_HashCode *query, GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls) { struct Plugin *plugin = cls; int ret; int sret; size_t block_size; const struct GNUNET_GNSRECORD_Block *block; if (SQLITE_OK != sqlite3_bind_blob (plugin->lookup_block, 1, query, sizeof (struct GNUNET_HashCode), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->lookup_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } ret = GNUNET_NO; if (SQLITE_ROW == (sret = sqlite3_step (plugin->lookup_block))) { block = sqlite3_column_blob (plugin->lookup_block, 0); block_size = sqlite3_column_bytes (plugin->lookup_block, 0); if ( (block_size < sizeof (struct GNUNET_GNSRECORD_Block)) || (ntohl (block->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature) != block_size) ) { GNUNET_break (0); ret = GNUNET_SYSERR; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found block under derived key `%s'\n", GNUNET_h2s_full (query)); iter (iter_cls, block); ret = GNUNET_YES; } } else { if (SQLITE_DONE != sret) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); ret = GNUNET_SYSERR; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No block found under derived key `%s'\n", GNUNET_h2s_full (query)); } } if (SQLITE_OK != sqlite3_reset (plugin->lookup_block)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return ret; } /** * Entry point for the plugin. * * @param cls the "struct GNUNET_NAMECACHE_PluginEnvironment*" * @return NULL on error, otherwise the plugin context */ void * libgnunet_plugin_namecache_sqlite_init (void *cls) { static struct Plugin plugin; const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_NAMECACHE_PluginFunctions *api; if (NULL != plugin.cfg) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); plugin.cfg = cfg; if (GNUNET_OK != database_setup (&plugin)) { database_shutdown (&plugin); return NULL; } api = GNUNET_new (struct GNUNET_NAMECACHE_PluginFunctions); api->cls = &plugin; api->cache_block = &namecache_sqlite_cache_block; api->lookup_block = &namecache_sqlite_lookup_block; LOG (GNUNET_ERROR_TYPE_INFO, _("Sqlite database running\n")); return api; } /** * Exit point from the plugin. * * @param cls the plugin context (as returned by "init") * @return always NULL */ void * libgnunet_plugin_namecache_sqlite_done (void *cls) { struct GNUNET_NAMECACHE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; database_shutdown (plugin); plugin->cfg = NULL; GNUNET_free (api); LOG (GNUNET_ERROR_TYPE_DEBUG, "sqlite plugin is finished\n"); return NULL; } /* end of plugin_namecache_sqlite.c */ gnunet-0.10.1/src/namecache/Makefile.am0000644000175000017500000001062112320751517014544 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ namecache.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIBS = -lgcov endif if HAVE_SQLITE SQLITE_PLUGIN = libgnunet_plugin_namecache_sqlite.la if HAVE_TESTING SQLITE_TESTS = test_plugin_namecache_sqlite endif endif if HAVE_POSTGRES POSTGRES_PLUGIN = libgnunet_plugin_namecache_postgres.la if HAVE_TESTING POSTGRES_TESTS = test_plugin_namecache_postgres endif endif # testcases do not even build yet; thus: experimental! if HAVE_TESTING TESTING_TESTS = \ test_namecache_api_cache_block endif if HAVE_SQLITE check_PROGRAMS = \ $(SQLITE_TESTS) \ $(POSTGRES_TESTS) \ $(TESTING_TESTS) endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ $(check_PROGRAMS) endif lib_LTLIBRARIES = \ libgnunetnamecache.la libgnunetnamecache_la_SOURCES = \ namecache_api.c \ namecache.h libgnunetnamecache_la_LIBADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetnamecache_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libexec_PROGRAMS = \ gnunet-service-namecache bin_PROGRAMS = \ gnunet-namecache gnunet_namecache_SOURCES = \ gnunet-namecache.c gnunet_namecache_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la \ $(GN_LIBINTL) gnunet_namecache_DEPENDENCIES = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la gnunet_service_namecache_SOURCES = \ gnunet-service-namecache.c gnunet_service_namecache_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la \ $(GN_LIBINTL) gnunet_service_namecache_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ $(POSTGRES_PLUGIN) libgnunet_plugin_namecache_sqlite_la_SOURCES = \ plugin_namecache_sqlite.c libgnunet_plugin_namecache_sqlite_la_LIBADD = \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_namecache_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_namecache_sqlite_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la libgnunet_plugin_namecache_postgres_la_SOURCES = \ plugin_namecache_postgres.c libgnunet_plugin_namecache_postgres_la_LIBADD = \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ $(LTLIBINTL) libgnunet_plugin_namecache_postgres_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_namecache_postgres_la_DEPENDENCIES = \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamecache.la test_namecache_api_cache_block_SOURCES = \ test_namecache_api_cache_block.c test_namecache_api_cache_block_LDADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_namecache_sqlite_SOURCES = \ test_plugin_namecache.c test_plugin_namecache_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_namecache_postgres_SOURCES = \ test_plugin_namecache.c test_plugin_namecache_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_namecache_api.conf \ test_plugin_namecache_sqlite.conf \ test_plugin_namecache_postgres.conf gnunet-0.10.1/src/namecache/test_namecache_api_cache_block.c0000644000175000017500000001403412236654562020757 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namecache/test_namecache_api.c * @brief testcase for namecache_api.c: store a record and perform a lookup */ #include "platform.h" #include "gnunet_namecache_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMECACHE_Handle *nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static struct GNUNET_NAMECACHE_QueueEntry *nsqe; static void cleanup () { if (NULL != nsh) { GNUNET_NAMECACHE_disconnect (nsh); nsh = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMECACHE_cancel (nsqe); nsqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } static void rd_decrypt_cb (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { char rd_cmp_data[TEST_RECORD_DATALEN]; GNUNET_assert (1 == rd_count); GNUNET_assert (NULL != rd); memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN); GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type); GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size); GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Block was decrypted successfully \n"); GNUNET_SCHEDULER_add_now (&end, NULL); } static void name_lookup_proc (void *cls, const struct GNUNET_GNSRECORD_Block *block) { const char *name = cls; nsqe = NULL; GNUNET_assert (NULL != cls); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL == block) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namecache returned no block\n")); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namecache returned block, decrypting \n"); GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt(block, &pubkey, name, &rd_decrypt_cb, (void *) name)); } static void cache_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; struct GNUNET_HashCode derived_hash; GNUNET_assert (NULL != cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store cached record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); /* Create derived hash */ GNUNET_GNSRECORD_query_from_public_key (&pubkey, name, &derived_hash); nsqe = GNUNET_NAMECACHE_lookup_block (nsh, &derived_hash, &name_lookup_proc, (void *) name); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_GNSRECORD_Data rd; struct GNUNET_GNSRECORD_Block *block; char *hostkey_file; const char * name = "dummy.dummy.gnunet"; endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); rd.expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 10000000000; rd.record_type = TEST_RECORD_TYPE; rd.data_size = TEST_RECORD_DATALEN; rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); rd.flags = 0; memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); block = GNUNET_GNSRECORD_block_create (privkey, GNUNET_TIME_UNIT_FOREVER_ABS, name, &rd, 1 ); if (NULL == block) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namecache cannot cache no block\n")); } nsh = GNUNET_NAMECACHE_connect (cfg); if (NULL == nsh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namecache cannot connect to namecache\n")); } GNUNET_break (NULL != nsh); nsqe = GNUNET_NAMECACHE_block_cache (nsh, block , &cache_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namecache cannot cache no block\n")); } GNUNET_free ((void *)rd.data); } int main (int argc, char *argv[]) { GNUNET_DISK_directory_remove ("/tmp/test-gnunet-namecache/"); res = 1; if (0 != GNUNET_TESTING_service_run ("test-namecache-api", "namecache", "test_namecache_api.conf", &run, NULL)) return 1; return res; } /* end of test_namecache_api_cache_block.c */ gnunet-0.10.1/src/namecache/test_namecache_api.conf0000644000175000017500000000052012227705277017160 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-namecache/ [arm] PORT = 12000 DEFAULTSERVICES = namecache [namecache] #PREFIX = valgrind AUTOSTART = YES DATABASE = sqlite [namecache-sqlite] FILENAME = $GNUNET_TEST_HOME/namecache/sqlite_test.db [namecache-postgres] CONFIG = connect_timeout=10; dbname=gnunetcheck TEMPORARY_TABLE = YES gnunet-0.10.1/src/namecache/namecache.conf.in0000644000175000017500000000070712250373167015677 00000000000000[namecache] AUTOSTART = @AUTOSTART@ USER_SERVICE = NO UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-namecache.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES @UNIXONLY@ PORT = 2113 HOSTNAME = localhost BINARY = gnunet-service-namecache ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; DATABASE = sqlite [namecache-sqlite] FILENAME = $GNUNET_DATA_HOME/namecache/sqlite.db [namecache-postgres] CONFIG = connect_timeout=10; dbname=gnunet TEMPORARY_TABLE = NO gnunet-0.10.1/src/Makefile.in0000644000175000017500000005432012320752057012655 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ #if WANT_FRAMEWORK # INTLEMU_SUBDIRS = intlemu #endif VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = include util hello tun block statistics arm testing \ peerinfo mysql postgres datacache datastore template ats nat \ fragmentation transport ats-tool peerinfo-tool core testbed \ ats-tests nse dht hostlist topology regex mesh dns identity \ set revocation gnsrecord namecache namestore vpn gns \ conversation fs exit pt integration-tests dv multicast env \ psycstore psyc consensus secretsharing scalarproduct \ experimentation DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @HAVE_TESTING_TRUE@TESTING = testing @HAVE_TESTING_TRUE@TESTBED = testbed @HAVE_TESTING_TRUE@CONSENSUS = consensus @HAVE_TESTING_TRUE@SECRETSHARING = secretsharing @HAVE_TESTING_TRUE@EXPERIMENTATION = experimentation @HAVE_TESTING_TRUE@SCALARPRODUCT = scalarproduct @HAVE_EXPERIMENTAL_TRUE@EXP_DIR = \ @HAVE_EXPERIMENTAL_TRUE@ dv \ @HAVE_EXPERIMENTAL_TRUE@ multicast \ @HAVE_EXPERIMENTAL_TRUE@ env \ @HAVE_EXPERIMENTAL_TRUE@ psycstore \ @HAVE_EXPERIMENTAL_TRUE@ psyc \ @HAVE_EXPERIMENTAL_TRUE@ $(CONSENSUS) \ @HAVE_EXPERIMENTAL_TRUE@ $(SECRETSHARING) \ @HAVE_EXPERIMENTAL_TRUE@ $(SCALARPRODUCT) \ @HAVE_EXPERIMENTAL_TRUE@ $(EXPERIMENTATION) @BUILD_GST_HELPERS_TRUE@@BUILD_PULSE_HELPERS_FALSE@CONVERSATION_DIR = conversation @BUILD_PULSE_HELPERS_TRUE@CONVERSATION_DIR = conversation @HAVE_MYSQL_TRUE@MYSQL_DIR = mysql @HAVE_POSTGRES_TRUE@POSTGRES_DIR = postgres SUBDIRS = \ include $(INTLEMU_SUBDIRS) \ util \ hello \ tun \ block \ statistics \ arm \ $(TESTING) \ peerinfo \ $(MYSQL_DIR) \ $(POSTGRES_DIR) \ datacache \ datastore \ template \ ats \ nat \ fragmentation \ transport \ ats-tool \ peerinfo-tool \ core \ $(TESTBED) \ ats-tests \ nse \ dht \ hostlist \ topology \ regex \ mesh \ dns \ identity \ set \ revocation \ gnsrecord \ namecache \ namestore \ vpn \ gns \ $(CONVERSATION_DIR) \ fs \ exit \ pt \ integration-tests \ $(EXP_DIR) all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/secretsharing/0000755000175000017500000000000012320755627013533 500000000000000gnunet-0.10.1/src/secretsharing/test_secretsharing_api.c0000644000175000017500000000612712300637202020340 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file secretsharing/test_secretsharing_api.c * @brief testcase for the secretsharing api */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_secretsharing_service.h" static int success; static struct GNUNET_SECRETSHARING_Session *keygen; static void secret_ready_cb (void *cls, struct GNUNET_SECRETSHARING_Share *my_share, struct GNUNET_SECRETSHARING_PublicKey *public_key, unsigned int num_ready_peers, struct GNUNET_PeerIdentity *ready_peers) { keygen = NULL; if (num_ready_peers == 1) success = 1; // FIXME: check that our share is valid, which we can do as there's only // one peer. GNUNET_SCHEDULER_shutdown (); } static void handle_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) { if (NULL != keygen) { GNUNET_SECRETSHARING_session_destroy (keygen); keygen = NULL; } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_HashCode session_id; struct GNUNET_TIME_Absolute start; struct GNUNET_TIME_Absolute deadline; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, handle_shutdown, NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "testing secretsharing api\n"); GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &session_id); start = GNUNET_TIME_absolute_get (); deadline = GNUNET_TIME_absolute_add (start, GNUNET_TIME_UNIT_SECONDS); keygen = GNUNET_SECRETSHARING_create_session (cfg, 0, NULL, /* only the local peer */ &session_id, start, deadline, 1, secret_ready_cb, NULL); } int main (int argc, char **argv) { int ret; ret = GNUNET_TESTING_peer_run ("test_secretsharing_api", "test_secretsharing.conf", &run, NULL); if (0 != ret) return ret; return (GNUNET_YES == success) ? 0 : 1; } gnunet-0.10.1/src/secretsharing/secretsharing_common.c0000644000175000017500000000775412300637202020027 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "secretsharing.h" /** * Read a share from its binary representation. * * @param data Binary representation of the share. * @param len Length of @a data. * @param[out] readlen Number of bytes read, * ignored if NULL. * @return The share, or NULL on error. */ struct GNUNET_SECRETSHARING_Share * GNUNET_SECRETSHARING_share_read (const void *data, size_t len, size_t *readlen) { struct GNUNET_SECRETSHARING_Share *share; const struct GNUNET_SECRETSHARING_ShareHeaderNBO *sh = data; char *p; size_t n; uint16_t payload_size; payload_size = ntohs (sh->num_peers) * (sizeof (uint16_t) + sizeof (struct GNUNET_SECRETSHARING_FieldElement) + sizeof (struct GNUNET_PeerIdentity)); if (NULL != readlen) *readlen = payload_size + sizeof *sh; share = GNUNET_malloc (sizeof *share); share->threshold = ntohs (sh->threshold); share->num_peers = ntohs (sh->num_peers); share->my_peer = ntohs (sh->my_peer); share->my_share = sh->my_share; share->public_key = sh->public_key; p = (void *) &sh[1]; n = share->num_peers * sizeof (struct GNUNET_PeerIdentity); share->peers = GNUNET_malloc (n); memcpy (share->peers, p, n); p += n; n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement); share->sigmas = GNUNET_malloc (n); memcpy (share->sigmas, p, n); p += n; n = share->num_peers * sizeof (uint16_t); share->original_indices = GNUNET_malloc (n); memcpy (share->original_indices, p, n); return share; } /** * Convert a share to its binary representation. * Can be called with a NULL @a buf to get the size of the share. * * @param share Share to write. * @param buf Buffer to write to. * @param buflen Number of writable bytes in @a buf. * @param[out] writelen Pointer to store number of bytes written, * ignored if NULL. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure. */ int GNUNET_SECRETSHARING_share_write (const struct GNUNET_SECRETSHARING_Share *share, void *buf, size_t buflen, size_t *writelen) { uint16_t payload_size; struct GNUNET_SECRETSHARING_ShareHeaderNBO *sh; char *p; int n; payload_size = share->num_peers * (sizeof (uint16_t) + sizeof (struct GNUNET_SECRETSHARING_FieldElement) + sizeof (struct GNUNET_PeerIdentity)); if (NULL != writelen) *writelen = payload_size + sizeof (struct GNUNET_SECRETSHARING_ShareHeaderNBO); /* just a query for the writelen */ if (buf == NULL) return GNUNET_OK; /* wrong buffer size */ if (buflen < payload_size + sizeof (struct GNUNET_SECRETSHARING_ShareHeaderNBO)) return GNUNET_SYSERR; sh = buf; sh->threshold = htons (share->threshold); sh->num_peers = htons (share->num_peers); sh->my_peer = htons (share->my_peer); sh->my_share = share->my_share; sh->public_key = share->public_key; p = (void *) &sh[1]; n = share->num_peers * sizeof (struct GNUNET_PeerIdentity); memcpy (p, share->peers, n); p += n; n = share->num_peers * sizeof (struct GNUNET_SECRETSHARING_FieldElement); memcpy (p, share->sigmas, n); p += n; n = share->num_peers * sizeof (uint16_t); memcpy (p, share->original_indices, n); return GNUNET_OK; } gnunet-0.10.1/src/secretsharing/secretsharing_protocol.h0000644000175000017500000000657712267465702020427 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file secretsharing/secretsharing_protocol.h * @brief p2p message definitions for secretsharing * @author Florian Dold */ #ifndef GNUNET_SECRETSHARING_PROTOCOL_H #define GNUNET_SECRETSHARING_PROTOCOL_H #include "platform.h" #include "gnunet_common.h" #include "gnunet_protocols.h" #include "secretsharing.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Consensus element data used in the first round of key generation. */ struct GNUNET_SECRETSHARING_KeygenCommitData { /** * Signature over the rest of the message. */ struct GNUNET_CRYPTO_EddsaSignature signature; /** * Signature purpose for signing the keygen commit data. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Peer that inserts this element. */ struct GNUNET_PeerIdentity peer; /** * Ephemeral paillier public key used by 'peer' for * this session. */ struct GNUNET_CRYPTO_PaillierPublicKey pubkey; /** * Commitment of 'peer' to his presecret. */ struct GNUNET_HashCode commitment GNUNET_PACKED; }; struct GNUNET_SECRETSHARING_KeygenRevealData { /** * Signature over rest of the message. */ struct GNUNET_CRYPTO_EddsaSignature signature; /* * Signature purpose for signing the keygen commit data. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Peer that inserts this element. */ struct GNUNET_PeerIdentity peer; /* values follow */ }; /** * Data of then element put in consensus * for decrypting a value. */ struct GNUNET_SECRETSHARING_DecryptData { /* * Signature over rest of the message. */ struct GNUNET_CRYPTO_EddsaSignature signature; /* * Signature purpose for signing the keygen commit data. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Ciphertext we want to decrypt. */ struct GNUNET_SECRETSHARING_Ciphertext ciphertext; /** * Peer that inserts this element. */ struct GNUNET_PeerIdentity peer; /** * Partial decryption, computed as c_1^{s_i} */ struct GNUNET_SECRETSHARING_FieldElement partial_decryption; /** * Commitment for the non-interactive zero knowledge proof. * g^\beta, with \beta < q */ struct GNUNET_SECRETSHARING_FieldElement nizk_commit1; /** * Commitment for the non-interactive zero knowledge proof. * c_1^\beta, with \beta < q */ struct GNUNET_SECRETSHARING_FieldElement nizk_commit2; /** * Reponse to the challenge computed from the protocol transcript. * r = \beta + challenge \cdot share_i */ struct GNUNET_SECRETSHARING_FieldElement nizk_response; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/secretsharing/Makefile.in0000644000175000017500000014457312320752064015526 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-secretsharing-profiler$(EXEEXT) libexec_PROGRAMS = gnunet-service-secretsharing$(EXEEXT) check_PROGRAMS = test_secretsharing_api$(EXEEXT) subdir = src/secretsharing DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/secretsharing.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = secretsharing.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetsecretsharing_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetsecretsharing_la_OBJECTS = secretsharing_api.lo \ secretsharing_common.lo libgnunetsecretsharing_la_OBJECTS = \ $(am_libgnunetsecretsharing_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetsecretsharing_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetsecretsharing_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_secretsharing_profiler_OBJECTS = \ gnunet-secretsharing-profiler.$(OBJEXT) gnunet_secretsharing_profiler_OBJECTS = \ $(am_gnunet_secretsharing_profiler_OBJECTS) am_gnunet_service_secretsharing_OBJECTS = gnunet_service_secretsharing-gnunet-service-secretsharing.$(OBJEXT) \ gnunet_service_secretsharing-secretsharing_common.$(OBJEXT) gnunet_service_secretsharing_OBJECTS = \ $(am_gnunet_service_secretsharing_OBJECTS) gnunet_service_secretsharing_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_test_secretsharing_api_OBJECTS = test_secretsharing_api.$(OBJEXT) test_secretsharing_api_OBJECTS = $(am_test_secretsharing_api_OBJECTS) test_secretsharing_api_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/secretsharing/libgnunetsecretsharing.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetsecretsharing_la_SOURCES) \ $(gnunet_secretsharing_profiler_SOURCES) \ $(gnunet_service_secretsharing_SOURCES) \ $(test_secretsharing_api_SOURCES) DIST_SOURCES = $(libgnunetsecretsharing_la_SOURCES) \ $(gnunet_secretsharing_profiler_SOURCES) \ $(gnunet_service_secretsharing_SOURCES) \ $(test_secretsharing_api_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ secretsharing.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage lib_LTLIBRARIES = \ libgnunetsecretsharing.la gnunet_secretsharing_profiler_SOURCES = \ gnunet-secretsharing-profiler.c gnunet_secretsharing_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/secretsharing/libgnunetsecretsharing.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(GN_LIBINTL) gnunet_secretsharing_profiler_DEPENDENCIES = \ libgnunetsecretsharing.la gnunet_service_secretsharing_SOURCES = \ gnunet-service-secretsharing.c \ secretsharing_common.c \ secretsharing_protocol.h gnunet_service_secretsharing_CFLAGS = $(AM_CFLAGS) gnunet_service_secretsharing_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/consensus/libgnunetconsensus.la \ $(LIBGCRYPT_LIBS) \ $(GN_LIBINTL) gnunet_service_secretsharing_DEPENDENCIES = \ $(top_builddir)/src/set/libgnunetset.la libgnunetsecretsharing_la_SOURCES = \ secretsharing_api.c \ secretsharing_common.c \ secretsharing.h libgnunetsecretsharing_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetsecretsharing_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_secretsharing_api_SOURCES = \ test_secretsharing_api.c test_secretsharing_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/secretsharing/libgnunetsecretsharing.la EXTRA_DIST = \ test_secretsharing.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/secretsharing/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/secretsharing/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): secretsharing.conf: $(top_builddir)/config.status $(srcdir)/secretsharing.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetsecretsharing.la: $(libgnunetsecretsharing_la_OBJECTS) $(libgnunetsecretsharing_la_DEPENDENCIES) $(EXTRA_libgnunetsecretsharing_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetsecretsharing_la_LINK) -rpath $(libdir) $(libgnunetsecretsharing_la_OBJECTS) $(libgnunetsecretsharing_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-secretsharing-profiler$(EXEEXT): $(gnunet_secretsharing_profiler_OBJECTS) $(gnunet_secretsharing_profiler_DEPENDENCIES) $(EXTRA_gnunet_secretsharing_profiler_DEPENDENCIES) @rm -f gnunet-secretsharing-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_secretsharing_profiler_OBJECTS) $(gnunet_secretsharing_profiler_LDADD) $(LIBS) gnunet-service-secretsharing$(EXEEXT): $(gnunet_service_secretsharing_OBJECTS) $(gnunet_service_secretsharing_DEPENDENCIES) $(EXTRA_gnunet_service_secretsharing_DEPENDENCIES) @rm -f gnunet-service-secretsharing$(EXEEXT) $(AM_V_CCLD)$(gnunet_service_secretsharing_LINK) $(gnunet_service_secretsharing_OBJECTS) $(gnunet_service_secretsharing_LDADD) $(LIBS) test_secretsharing_api$(EXEEXT): $(test_secretsharing_api_OBJECTS) $(test_secretsharing_api_DEPENDENCIES) $(EXTRA_test_secretsharing_api_DEPENDENCIES) @rm -f test_secretsharing_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_secretsharing_api_OBJECTS) $(test_secretsharing_api_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-secretsharing-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_secretsharing-gnunet-service-secretsharing.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_secretsharing-secretsharing_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/secretsharing_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/secretsharing_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_secretsharing_api.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< gnunet_service_secretsharing-gnunet-service-secretsharing.o: gnunet-service-secretsharing.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) -MT gnunet_service_secretsharing-gnunet-service-secretsharing.o -MD -MP -MF $(DEPDIR)/gnunet_service_secretsharing-gnunet-service-secretsharing.Tpo -c -o gnunet_service_secretsharing-gnunet-service-secretsharing.o `test -f 'gnunet-service-secretsharing.c' || echo '$(srcdir)/'`gnunet-service-secretsharing.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_secretsharing-gnunet-service-secretsharing.Tpo $(DEPDIR)/gnunet_service_secretsharing-gnunet-service-secretsharing.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-secretsharing.c' object='gnunet_service_secretsharing-gnunet-service-secretsharing.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) -c -o gnunet_service_secretsharing-gnunet-service-secretsharing.o `test -f 'gnunet-service-secretsharing.c' || echo '$(srcdir)/'`gnunet-service-secretsharing.c gnunet_service_secretsharing-gnunet-service-secretsharing.obj: gnunet-service-secretsharing.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) -MT gnunet_service_secretsharing-gnunet-service-secretsharing.obj -MD -MP -MF $(DEPDIR)/gnunet_service_secretsharing-gnunet-service-secretsharing.Tpo -c -o gnunet_service_secretsharing-gnunet-service-secretsharing.obj `if test -f 'gnunet-service-secretsharing.c'; then $(CYGPATH_W) 'gnunet-service-secretsharing.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-secretsharing.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_secretsharing-gnunet-service-secretsharing.Tpo $(DEPDIR)/gnunet_service_secretsharing-gnunet-service-secretsharing.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-secretsharing.c' object='gnunet_service_secretsharing-gnunet-service-secretsharing.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) -c -o gnunet_service_secretsharing-gnunet-service-secretsharing.obj `if test -f 'gnunet-service-secretsharing.c'; then $(CYGPATH_W) 'gnunet-service-secretsharing.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-secretsharing.c'; fi` gnunet_service_secretsharing-secretsharing_common.o: secretsharing_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) -MT gnunet_service_secretsharing-secretsharing_common.o -MD -MP -MF $(DEPDIR)/gnunet_service_secretsharing-secretsharing_common.Tpo -c -o gnunet_service_secretsharing-secretsharing_common.o `test -f 'secretsharing_common.c' || echo '$(srcdir)/'`secretsharing_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_secretsharing-secretsharing_common.Tpo $(DEPDIR)/gnunet_service_secretsharing-secretsharing_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='secretsharing_common.c' object='gnunet_service_secretsharing-secretsharing_common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) -c -o gnunet_service_secretsharing-secretsharing_common.o `test -f 'secretsharing_common.c' || echo '$(srcdir)/'`secretsharing_common.c gnunet_service_secretsharing-secretsharing_common.obj: secretsharing_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) -MT gnunet_service_secretsharing-secretsharing_common.obj -MD -MP -MF $(DEPDIR)/gnunet_service_secretsharing-secretsharing_common.Tpo -c -o gnunet_service_secretsharing-secretsharing_common.obj `if test -f 'secretsharing_common.c'; then $(CYGPATH_W) 'secretsharing_common.c'; else $(CYGPATH_W) '$(srcdir)/secretsharing_common.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_secretsharing-secretsharing_common.Tpo $(DEPDIR)/gnunet_service_secretsharing-secretsharing_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='secretsharing_common.c' object='gnunet_service_secretsharing-secretsharing_common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_secretsharing_CFLAGS) $(CFLAGS) -c -o gnunet_service_secretsharing-secretsharing_common.obj `if test -f 'secretsharing_common.c'; then $(CYGPATH_W) 'secretsharing_common.c'; else $(CYGPATH_W) '$(srcdir)/secretsharing_common.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_secretsharing_api.log: test_secretsharing_api$(EXEEXT) @p='test_secretsharing_api$(EXEEXT)'; \ b='test_secretsharing_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/secretsharing/gnunet-service-secretsharing.c0000644000175000017500000015020712300637202021403 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file secretsharing/gnunet-service-secretsharing.c * @brief secret sharing service * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_time_lib.h" #include "gnunet_signatures.h" #include "gnunet_consensus_service.h" #include "secretsharing.h" #include "secretsharing_protocol.h" #include #define EXTRA_CHECKS 1 /** * Info about a peer in a key generation session. */ struct KeygenPeerInfo { /** * Peer identity of the peer. */ struct GNUNET_PeerIdentity peer; /** * The peer's paillier public key. * Freshly generated for each keygen session. */ struct GNUNET_CRYPTO_PaillierPublicKey paillier_public_key; /** * The peer's commitment to his presecret. */ gcry_mpi_t presecret_commitment; /** * Commitment to the preshare that is * intended for our peer. */ gcry_mpi_t preshare_commitment; /** * Sigma (exponentiated share) for this peer. */ gcry_mpi_t sigma; /** * Did we successfully receive the round1 element * of the peer? */ int round1_valid; /** * Did we successfully receive the round2 element * of the peer? */ int round2_valid; }; /** * Information about a peer in a decrypt session. */ struct DecryptPeerInfo { /** * Identity of the peer. */ struct GNUNET_PeerIdentity peer; /** * Original index in the key generation round. * Necessary for computing the lagrange coefficients. */ unsigned int original_index; /** * Set to the partial decryption of * this peer, or NULL if we did not * receive a partial decryption from this * peer or the zero knowledge proof failed. */ gcry_mpi_t partial_decryption; }; /** * Session to establish a threshold-shared secret. */ struct KeygenSession { /** * Keygen sessions are held in a linked list. */ struct KeygenSession *next; /** * Keygen sessions are held in a linked list. */ struct KeygenSession *prev; /** * Current consensus, used for both DKG rounds. */ struct GNUNET_CONSENSUS_Handle *consensus; /** * Client that is interested in the result * of this key generation session. */ struct GNUNET_SERVER_Client *client; /** * Message queue for 'client' */ struct GNUNET_MQ_Handle *client_mq; /** * Randomly generated coefficients of the polynomial for sharing our * pre-secret, where 'preshares[0]' is our pre-secret. Contains 'threshold' * elements, thus represents a polynomial of degree 'threshold-1', which can * be interpolated with 'threshold' data points. * * The pre-secret-shares 'i=1,...,num_peers' are given by evaluating this * polyomial at 'i' for share i. */ gcry_mpi_t *presecret_polynomial; /** * Minimum number of shares required to restore the secret. * Also the number of coefficients for the polynomial representing * the sharing. Obviously, the polynomial then has degree threshold-1. */ unsigned int threshold; /** * Total number of peers. */ unsigned int num_peers; /** * Index of the local peer. */ unsigned int local_peer; /** * Information about all participating peers. * Array of size 'num_peers'. */ struct KeygenPeerInfo *info; /** * List of all peers involved in the secret sharing session. */ struct GNUNET_PeerIdentity *peers; /** * Identifier for this session. */ struct GNUNET_HashCode session_id; /** * Paillier private key of our peer. */ struct GNUNET_CRYPTO_PaillierPrivateKey paillier_private_key; /** * When would we like the key to be established? */ struct GNUNET_TIME_Absolute deadline; /** * When does the DKG start? Necessary to compute fractions of the * operation's desired time interval. */ struct GNUNET_TIME_Absolute start_time; /** * Index of the local peer in the ordered list * of peers in the session. */ unsigned int local_peer_idx; /** * Share of our peer. Once preshares from other peers are received, they * will be added to 'my'share. */ gcry_mpi_t my_share; /** * Public key, will be updated when a round2 element arrives. */ gcry_mpi_t public_key; }; /** * Session to cooperatively decrypt a value. */ struct DecryptSession { /** * Decrypt sessions are stored in a linked list. */ struct DecryptSession *next; /** * Decrypt sessions are stored in a linked list. */ struct DecryptSession *prev; /** * Handle to the consensus over partial decryptions. */ struct GNUNET_CONSENSUS_Handle *consensus; /** * Client connected to us. */ struct GNUNET_SERVER_Client *client; /** * Message queue for 'client'. */ struct GNUNET_MQ_Handle *client_mq; /** * When should we start communicating for decryption? */ struct GNUNET_TIME_Absolute start; /** * When would we like the ciphertext to be * decrypted? */ struct GNUNET_TIME_Absolute deadline; /** * Ciphertext we want to decrypt. */ struct GNUNET_SECRETSHARING_Ciphertext ciphertext; /** * Share of the local peer. * Containts other important information, such as * the list of other peers. */ struct GNUNET_SECRETSHARING_Share *share; /** * State information about other peers. */ struct DecryptPeerInfo *info; }; /** * Decrypt sessions are held in a linked list. */ static struct DecryptSession *decrypt_sessions_head; /** * Decrypt sessions are held in a linked list. */ static struct DecryptSession *decrypt_sessions_tail; /** * Decrypt sessions are held in a linked list. */ static struct KeygenSession *keygen_sessions_head; /** * Decrypt sessions are held in a linked list. */ static struct KeygenSession *keygen_sessions_tail; /** * The ElGamal prime field order as libgcrypt mpi. * Initialized in #init_crypto_constants. */ static gcry_mpi_t elgamal_q; /** * Modulus of the prime field used for ElGamal. * Initialized in #init_crypto_constants. */ static gcry_mpi_t elgamal_p; /** * Generator for prime field of order 'elgamal_q'. * Initialized in #init_crypto_constants. */ static gcry_mpi_t elgamal_g; /** * Peer that runs this service. */ static struct GNUNET_PeerIdentity my_peer; /** * Peer that runs this service. */ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_peer_private_key; /** * Configuration of this service. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Server for this service. */ static struct GNUNET_SERVER_Handle *srv; /** * Get the peer info belonging to a peer identity in a keygen session. * * @param ks The keygen session. * @param peer The peer identity. * @return The Keygen peer info, or NULL if the peer could not be found. */ static struct KeygenPeerInfo * get_keygen_peer_info (const struct KeygenSession *ks, const struct GNUNET_PeerIdentity *peer) { unsigned int i; for (i = 0; i < ks->num_peers; i++) if (0 == memcmp (peer, &ks->info[i].peer, sizeof (struct GNUNET_PeerIdentity))) return &ks->info[i]; return NULL; } /** * Get the peer info belonging to a peer identity in a decrypt session. * * @param ds The decrypt session. * @param peer The peer identity. * @return The decrypt peer info, or NULL if the peer could not be found. */ static struct DecryptPeerInfo * get_decrypt_peer_info (const struct DecryptSession *ds, const struct GNUNET_PeerIdentity *peer) { unsigned int i; for (i = 0; i < ds->share->num_peers; i++) if (0 == memcmp (peer, &ds->info[i].peer, sizeof (struct GNUNET_PeerIdentity))) return &ds->info[i]; return NULL; } /** * Interpolate between two points in time. * * @param start start time * @param end end time * @param num numerator of the scale factor * @param denum denumerator of the scale factor */ static struct GNUNET_TIME_Absolute time_between (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end, int num, int denum) { struct GNUNET_TIME_Absolute result; uint64_t diff; GNUNET_assert (start.abs_value_us <= end.abs_value_us); diff = end.abs_value_us - start.abs_value_us; result.abs_value_us = start.abs_value_us + ((diff * num) / denum); return result; } /** * Compare two peer identities. Indended to be used with qsort or bsearch. * * @param p1 Some peer identity. * @param p2 Some peer identity. * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2. */ static int peer_id_cmp (const void *p1, const void *p2) { return memcmp (p1, p2, sizeof (struct GNUNET_PeerIdentity)); } /** * Get the index of a peer in an array of peers * * @param haystack Array of peers. * @param n Size of @a haystack. * @param needle Peer to find * @return Index of @a needle in @a haystack, or -1 if peer * is not in the list. */ static int peer_find (const struct GNUNET_PeerIdentity *haystack, unsigned int n, const struct GNUNET_PeerIdentity *needle) { unsigned int i; for (i = 0; i < n; i++) if (0 == memcmp (&haystack[i], needle, sizeof (struct GNUNET_PeerIdentity))) return i; return -1; } /** * Normalize the given list of peers, by including the local peer * (if it is missing) and sorting the peers by their identity. * * @param listed Peers in the unnormalized list. * @param num_listed Peers in the un-normalized list. * @param[out] num_normalized Number of peers in the normalized list. * @param[out] my_peer_idx Index of the local peer in the normalized list. * @return Normalized list, must be free'd by the caller. */ static struct GNUNET_PeerIdentity * normalize_peers (struct GNUNET_PeerIdentity *listed, unsigned int num_listed, unsigned int *num_normalized, unsigned int *my_peer_idx) { unsigned int local_peer_in_list; /* number of peers in the normalized list */ unsigned int n; struct GNUNET_PeerIdentity *normalized; local_peer_in_list = GNUNET_YES; n = num_listed; if (peer_find (listed, num_listed, &my_peer) < 0) { local_peer_in_list = GNUNET_NO; n += 1; } normalized = GNUNET_new_array (n, struct GNUNET_PeerIdentity); if (GNUNET_NO == local_peer_in_list) normalized[n - 1] = my_peer; memcpy (normalized, listed, num_listed * sizeof (struct GNUNET_PeerIdentity)); qsort (normalized, n, sizeof (struct GNUNET_PeerIdentity), &peer_id_cmp); if (NULL != my_peer_idx) *my_peer_idx = peer_find (normalized, n, &my_peer); if (NULL != num_normalized) *num_normalized = n; return normalized; } /** * Get a the j-th lagrange coefficient for a set of indices. * * @param[out] coeff the lagrange coefficient * @param j lagrange coefficient we want to compute * @param indices indices * @param num number of indices in @a indices */ static void compute_lagrange_coefficient (gcry_mpi_t coeff, unsigned int j, unsigned int *indices, unsigned int num) { unsigned int i; /* numerator */ gcry_mpi_t n; /* denominator */ gcry_mpi_t d; /* temp value for l-j */ gcry_mpi_t tmp; GNUNET_assert (0 != coeff); GNUNET_assert (0 != (n = gcry_mpi_new (0))); GNUNET_assert (0 != (d = gcry_mpi_new (0))); GNUNET_assert (0 != (tmp = gcry_mpi_new (0))); gcry_mpi_set_ui (n, 1); gcry_mpi_set_ui (d, 1); for (i = 0; i < num; i++) { unsigned int l = indices[i]; if (l == j) continue; gcry_mpi_mul_ui (n, n, l + 1); // d <- d * (l-j) gcry_mpi_set_ui (tmp, l + 1); gcry_mpi_sub_ui (tmp, tmp, j + 1); gcry_mpi_mul (d, d, tmp); } // gcry_mpi_invm does not like negative numbers ... gcry_mpi_mod (d, d, elgamal_q); GNUNET_assert (gcry_mpi_cmp_ui (d, 0) > 0); // now we do the actual division, with everything mod q, as we // are not operating on elements from , but on exponents GNUNET_assert (0 != gcry_mpi_invm (d, d, elgamal_q)); gcry_mpi_mulm (coeff, n, d, elgamal_q); gcry_mpi_release (n); gcry_mpi_release (d); gcry_mpi_release (tmp); } static void decrypt_session_destroy (struct DecryptSession *ds) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying decrypt session\n"); GNUNET_CONTAINER_DLL_remove (decrypt_sessions_head, decrypt_sessions_tail, ds); if (NULL != ds->client_mq) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying decrypt MQ\n"); GNUNET_MQ_destroy (ds->client_mq); ds->client_mq = NULL; } if (NULL != ds->client) { GNUNET_SERVER_client_disconnect (ds->client); ds->client = NULL; } GNUNET_free (ds); } static void keygen_session_destroy (struct KeygenSession *ks) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying keygen session\n"); GNUNET_CONTAINER_DLL_remove (keygen_sessions_head, keygen_sessions_tail, ks); if (NULL != ks->client_mq) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying keygen MQ\n"); GNUNET_MQ_destroy (ks->client_mq); ks->client_mq = NULL; } if (NULL != ks->client) { GNUNET_SERVER_client_disconnect (ks->client); ks->client = NULL; } GNUNET_free (ks); } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { while (NULL != decrypt_sessions_head) decrypt_session_destroy (decrypt_sessions_head); while (NULL != keygen_sessions_head) keygen_session_destroy (keygen_sessions_head); } /** * Generate the random coefficients of our pre-secret polynomial * * @param ks the session */ static void generate_presecret_polynomial (struct KeygenSession *ks) { int i; gcry_mpi_t v; GNUNET_assert (NULL == ks->presecret_polynomial); ks->presecret_polynomial = GNUNET_new_array (ks->threshold, gcry_mpi_t); for (i = 0; i < ks->threshold; i++) { v = ks->presecret_polynomial[i] = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS); GNUNET_assert (NULL != v); // Randomize v such that 0 < v < elgamal_q. // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1. do { gcry_mpi_randomize (v, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM); } while ((gcry_mpi_cmp_ui (v, 0) == 0) || (gcry_mpi_cmp (v, elgamal_q) >= 0)); } } /** * Consensus element handler for round one. * We should get one ephemeral key for each peer. * * @param cls Closure (keygen session). * @param element The element from consensus, or * NULL if consensus failed. */ static void keygen_round1_new_element (void *cls, const struct GNUNET_SET_Element *element) { const struct GNUNET_SECRETSHARING_KeygenCommitData *d; struct KeygenSession *ks = cls; struct KeygenPeerInfo *info; if (NULL == element) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round1 consensus failed\n"); return; } /* elements have fixed size */ if (element->size != sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong size (%u) in consensus, " " %u expected\n", element->size, sizeof (struct GNUNET_SECRETSHARING_KeygenCommitData)); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round1 element\n"); d = element->data; info = get_keygen_peer_info (ks, &d->peer); if (NULL == info) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n", GNUNET_i2s (&d->peer)); return; } /* Check that the right amount of data has been signed. */ if (d->purpose.size != htonl (element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong signature purpose size in consensus\n"); return; } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1, &d->purpose, &d->signature, &d->peer.public_key)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with invalid signature in consensus\n"); return; } info->paillier_public_key = d->pubkey; GNUNET_CRYPTO_mpi_scan_unsigned (&info->presecret_commitment, &d->commitment, 512 / 8); info->round1_valid = GNUNET_YES; } /** * Evaluate the polynomial with coefficients @a coeff at @a x. * The i-th element in @a coeff corresponds to the coefficient of x^i. * * @param[out] z result of the evaluation * @param coeff array of coefficients * @param num_coeff number of coefficients * @param x where to evaluate the polynomial * @param m what group are we operating in? */ static void horner_eval (gcry_mpi_t z, gcry_mpi_t *coeff, unsigned int num_coeff, gcry_mpi_t x, gcry_mpi_t m) { unsigned int i; gcry_mpi_set_ui (z, 0); for (i = 0; i < num_coeff; i++) { // z <- zx + c gcry_mpi_mul (z, z, x); gcry_mpi_addm (z, z, coeff[num_coeff - i - 1], m); } } static void keygen_round2_conclude (void *cls) { struct KeygenSession *ks = cls; struct GNUNET_SECRETSHARING_SecretReadyMessage *m; struct GNUNET_MQ_Envelope *ev; size_t share_size; unsigned int i; unsigned int j; struct GNUNET_SECRETSHARING_Share *share; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "round2 conclude\n"); share = GNUNET_new (struct GNUNET_SECRETSHARING_Share); share->num_peers = 0; for (i = 0; i < ks->num_peers; i++) if (GNUNET_YES == ks->info[i].round2_valid) share->num_peers++; share->peers = GNUNET_new_array (share->num_peers, struct GNUNET_PeerIdentity); share->sigmas = GNUNET_new_array (share->num_peers, struct GNUNET_SECRETSHARING_FieldElement); share->original_indices = GNUNET_new_array (share->num_peers, uint16_t); /* maybe we're not even in the list of peers? */ share->my_peer = share->num_peers; j = 0; /* running index of valid peers */ for (i = 0; i < ks->num_peers; i++) { if (GNUNET_YES == ks->info[i].round2_valid) { share->peers[j] = ks->info[i].peer; GNUNET_CRYPTO_mpi_print_unsigned (&share->sigmas[j], GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, ks->info[i].sigma); share->original_indices[i] = j; if (0 == memcmp (&share->peers[i], &my_peer, sizeof (struct GNUNET_PeerIdentity))) share->my_peer = j; j += 1; } } if (share->my_peer == share->num_peers) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: peer identity not in share\n", ks->local_peer_idx); } GNUNET_CRYPTO_mpi_print_unsigned (&share->my_share, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, ks->my_share); GNUNET_CRYPTO_mpi_print_unsigned (&share->public_key, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, ks->public_key); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "keygen completed with %u peers\n", share->num_peers); /* Write the share. If 0 peers completed the dkg, an empty * share will be sent. */ m = GNUNET_malloc (sizeof (struct GNUNET_SECRETSHARING_SecretReadyMessage) + ks->num_peers * sizeof (struct GNUNET_PeerIdentity)); GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "writing share of size %u\n", (unsigned int) share_size); ev = GNUNET_MQ_msg_extra (m, share_size, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY); GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &m[1], share_size, NULL)); GNUNET_MQ_send (ks->client_mq, ev); } /** * Insert round 2 element in the consensus, consisting of * (1) The exponentiated pre-share polynomial coefficients A_{i,l}=g^{a_{i,l}} * (2) The exponentiated pre-shares y_{i,j}=g^{s_{i,j}} * (3) The encrypted pre-shares Y_{i,j} * (4) The zero knowledge proof for fairness of * the encryption * * @param ks session to use */ static void insert_round2_element (struct KeygenSession *ks) { struct GNUNET_SET_Element *element; struct GNUNET_SECRETSHARING_KeygenRevealData *d; unsigned char *pos; unsigned char *last_pos; size_t element_size; unsigned int i; gcry_mpi_t idx; gcry_mpi_t v; gcry_mpi_t c; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting round2 element\n", ks->local_peer_idx); GNUNET_assert (NULL != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS))); GNUNET_assert (NULL != (idx = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS))); GNUNET_assert (NULL != (c = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS))); element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) + GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers + sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * ks->num_peers + GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold); element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size); element->size = element_size; element->data = (void *) &element[1]; d = (void *) element->data; d->peer = my_peer; // start inserting vector elements // after the fixed part of the element's data pos = (void *) &d[1]; last_pos = pos + element_size; // exponentiated pre-shares for (i = 0; i < ks->num_peers; i++) { ptrdiff_t remaining = last_pos - pos; GNUNET_assert (remaining > 0); gcry_mpi_set_ui (idx, i + 1); // evaluate the polynomial horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q); // take g to the result gcry_mpi_powm (v, elgamal_g, v, elgamal_p); GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v); pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp preshares\n", ks->local_peer_idx); // encrypted pre-shares for (i = 0; i < ks->num_peers; i++) { ptrdiff_t remaining = last_pos - pos; struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext; GNUNET_assert (remaining > 0); ciphertext = (void *) pos; memset (ciphertext, 0, sizeof *ciphertext); if (GNUNET_YES == ks->info[i].round1_valid) { gcry_mpi_set_ui (idx, i + 1); // evaluate the polynomial horner_eval (v, ks->presecret_polynomial, ks->threshold, idx, elgamal_q); // encrypt the result GNUNET_CRYPTO_paillier_encrypt (&ks->info[i].paillier_public_key, v, 0, ciphertext); } pos += sizeof *ciphertext; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed enc preshares\n", ks->local_peer_idx); // exponentiated coefficients for (i = 0; i < ks->threshold; i++) { ptrdiff_t remaining = last_pos - pos; GNUNET_assert (remaining > 0); gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[i], elgamal_p); GNUNET_CRYPTO_mpi_print_unsigned (pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v); pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: computed exp coefficients\n", ks->local_peer_idx); d->purpose.size = htonl (element_size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose)); d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2); GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature); GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL); GNUNET_free (element); /* FIXME: maybe stack-allocate instead? */ gcry_mpi_release (v); gcry_mpi_release (idx); } static gcry_mpi_t keygen_reveal_get_exp_preshare (struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx) { unsigned char *pos; gcry_mpi_t exp_preshare; GNUNET_assert (idx < ks->num_peers); GNUNET_assert (NULL != (exp_preshare = gcry_mpi_new (0))); pos = (void *) &d[1]; // skip exponentiated pre-shares we don't want pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * idx; GNUNET_CRYPTO_mpi_scan_unsigned (&exp_preshare, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); return exp_preshare; } static gcry_mpi_t keygen_reveal_get_exp_coeff (struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx) { unsigned char *pos; gcry_mpi_t exp_coeff; GNUNET_assert (idx < ks->threshold); GNUNET_assert (NULL != (exp_coeff = gcry_mpi_new (0))); pos = (void *) &d[1]; // skip exponentiated pre-shares pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers; // skip encrypted pre-shares pos += sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * ks->num_peers; // skip exp. coeffs we are not interested in pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * idx; // the first exponentiated coefficient is the public key share GNUNET_CRYPTO_mpi_scan_unsigned (&exp_coeff, pos, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); return exp_coeff; } static struct GNUNET_CRYPTO_PaillierCiphertext * keygen_reveal_get_enc_preshare (struct KeygenSession *ks, const struct GNUNET_SECRETSHARING_KeygenRevealData *d, unsigned int idx) { unsigned char *pos; GNUNET_assert (idx < ks->num_peers); pos = (void *) &d[1]; // skip exponentiated pre-shares pos += GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers; // skip encrypted pre-shares we're not interested in pos += sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * idx; return (struct GNUNET_CRYPTO_PaillierCiphertext *) pos; } static void keygen_round2_new_element (void *cls, const struct GNUNET_SET_Element *element) { struct KeygenSession *ks = cls; const struct GNUNET_SECRETSHARING_KeygenRevealData *d; struct KeygenPeerInfo *info; size_t expected_element_size; unsigned int j; gcry_mpi_t tmp; gcry_mpi_t public_key_share; gcry_mpi_t preshare; if (NULL == element) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "round2 consensus failed\n"); return; } expected_element_size = (sizeof (struct GNUNET_SECRETSHARING_KeygenRevealData) + GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->num_peers + sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * ks->num_peers + GNUNET_SECRETSHARING_ELGAMAL_BITS / 8 * ks->threshold); if (element->size != expected_element_size) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen round2 data with wrong size (%u) in consensus, " " %u expected\n", element->size, expected_element_size); return; } d = (const void *) element->data; info = get_keygen_peer_info (ks, &d->peer); if (NULL == info) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen commit data with wrong peer identity (%s) in consensus\n", GNUNET_i2s (&d->peer)); return; } if (GNUNET_NO == info->round1_valid) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ignoring round2 element from peer with invalid round1 element (%s)\n", GNUNET_i2s (&d->peer)); return; } if (GNUNET_YES == info->round2_valid) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ignoring duplicate round2 element (%s)\n", GNUNET_i2s (&d->peer)); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "got round2 element\n"); if (ntohl (d->purpose.size) != element->size - offsetof (struct GNUNET_SECRETSHARING_KeygenRevealData, purpose)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with wrong signature purpose size in consensus\n"); return; } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG2, &d->purpose, &d->signature, &d->peer.public_key)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "keygen reveal data with invalid signature in consensus\n"); return; } public_key_share = keygen_reveal_get_exp_coeff (ks, d, 0); info->preshare_commitment = keygen_reveal_get_exp_preshare (ks, d, ks->local_peer_idx); if (NULL == ks->public_key) { GNUNET_assert (NULL != (ks->public_key = gcry_mpi_new (0))); gcry_mpi_set_ui (ks->public_key, 1); } gcry_mpi_mulm (ks->public_key, ks->public_key, public_key_share, elgamal_p); GNUNET_assert (NULL != (preshare = gcry_mpi_new (0))); GNUNET_CRYPTO_paillier_decrypt (&ks->paillier_private_key, &ks->info[ks->local_peer_idx].paillier_public_key, keygen_reveal_get_enc_preshare (ks, d, ks->local_peer_idx), preshare); GNUNET_assert (NULL != (tmp = gcry_mpi_new (0))); gcry_mpi_powm (tmp, elgamal_g, preshare, elgamal_p); // TODO: restore a valid secret from the decryption (the hard part, solving SVP with gauss) if (0 != gcry_mpi_cmp (tmp, info->preshare_commitment)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: Got invalid presecret from P%u\n", (unsigned int) ks->local_peer_idx, (unsigned int) (info - ks->info)); return; } if (NULL == ks->my_share) { GNUNET_assert (NULL != (ks->my_share = gcry_mpi_new (0))); } gcry_mpi_addm (ks->my_share, ks->my_share, preshare, elgamal_q); for (j = 0; j < ks->num_peers; j++) { gcry_mpi_t presigma; if (NULL == ks->info[j].sigma) { GNUNET_assert (NULL != (ks->info[j].sigma = gcry_mpi_new (0))); gcry_mpi_set_ui (ks->info[j].sigma, 1); } presigma = keygen_reveal_get_exp_preshare (ks, d, j); gcry_mpi_mulm (ks->info[j].sigma, ks->info[j].sigma, presigma, elgamal_p); } gcry_mpi_t prod; GNUNET_assert (NULL != (prod = gcry_mpi_new (0))); gcry_mpi_t j_to_k; GNUNET_assert (NULL != (j_to_k = gcry_mpi_new (0))); // validate that the polynomial sharing matches the additive sharing for (j = 0; j < ks->num_peers; j++) { unsigned int k; gcry_mpi_t tmp; gcry_mpi_t exp_preshare; gcry_mpi_set_ui (prod, 1); for (k = 0; k < ks->threshold; k++) { // Using pow(double,double) is a bit sketchy. // We count players from 1, but shares from 0. gcry_mpi_set_ui (j_to_k, (unsigned int) pow(j+1, k)); tmp = keygen_reveal_get_exp_coeff (ks, d, k); gcry_mpi_powm (tmp, tmp, j_to_k, elgamal_p); gcry_mpi_mulm (prod, prod, tmp, elgamal_p); } exp_preshare = keygen_reveal_get_exp_preshare (ks, d, j); gcry_mpi_mod (exp_preshare, exp_preshare, elgamal_p); if (0 != gcry_mpi_cmp (prod, exp_preshare)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: reveal data from P%u incorrect\n", ks->local_peer_idx, j); /* no need for further verification, round2 stays invalid ... */ return; } } // TODO: verify proof of fair encryption (once implemented) info->round2_valid = GNUNET_YES; } /** * Called when the first consensus round has concluded. * Will initiate the second round. * * @param cls closure */ static void keygen_round1_conclude (void *cls) { struct KeygenSession *ks = cls; GNUNET_CONSENSUS_destroy (ks->consensus); ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &ks->session_id, time_between (ks->start_time, ks->deadline, 1, 2), ks->deadline, keygen_round2_new_element, ks); insert_round2_element (ks); GNUNET_CONSENSUS_conclude (ks->consensus, keygen_round2_conclude, ks); } /** * Insert the ephemeral key and the presecret commitment * of this peer in the consensus of the given session. * * @param ks session to use */ static void insert_round1_element (struct KeygenSession *ks) { struct GNUNET_SET_Element *element; struct GNUNET_SECRETSHARING_KeygenCommitData *d; // g^a_{i,0} gcry_mpi_t v; // big-endian representation of 'v' unsigned char v_data[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8]; element = GNUNET_malloc (sizeof *element + sizeof *d); d = (void *) &element[1]; element->data = d; element->size = sizeof *d; d->peer = my_peer; GNUNET_assert (0 != (v = gcry_mpi_new (GNUNET_SECRETSHARING_ELGAMAL_BITS))); gcry_mpi_powm (v, elgamal_g, ks->presecret_polynomial[0], elgamal_p); GNUNET_CRYPTO_mpi_print_unsigned (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, v); GNUNET_CRYPTO_hash (v_data, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, &d->commitment); d->pubkey = ks->info[ks->local_peer_idx].paillier_public_key; d->purpose.size = htonl ((sizeof *d) - offsetof (struct GNUNET_SECRETSHARING_KeygenCommitData, purpose)); d->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DKG1); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d->purpose, &d->signature)); GNUNET_CONSENSUS_insert (ks->consensus, element, NULL, NULL); gcry_mpi_release (v); GNUNET_free (element); } /** * Functions with this signature are called whenever a message is * received. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_client_keygen (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_SECRETSHARING_CreateMessage *msg = (const struct GNUNET_SECRETSHARING_CreateMessage *) message; struct KeygenSession *ks; unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "client requested key generation\n"); ks = GNUNET_new (struct KeygenSession); /* FIXME: check if client already has some session */ GNUNET_CONTAINER_DLL_insert (keygen_sessions_head, keygen_sessions_tail, ks); ks->client = client; ks->client_mq = GNUNET_MQ_queue_for_server_client (client); ks->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline); ks->threshold = ntohs (msg->threshold); ks->num_peers = ntohs (msg->num_peers); ks->peers = normalize_peers ((struct GNUNET_PeerIdentity *) &msg[1], ks->num_peers, &ks->num_peers, &ks->local_peer_idx); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "first round of consensus with %u peers\n", ks->num_peers); ks->consensus = GNUNET_CONSENSUS_create (cfg, ks->num_peers, ks->peers, &msg->session_id, GNUNET_TIME_absolute_ntoh (msg->start), GNUNET_TIME_absolute_ntoh (msg->deadline), keygen_round1_new_element, ks); ks->info = GNUNET_new_array (ks->num_peers, struct KeygenPeerInfo); for (i = 0; i < ks->num_peers; i++) ks->info[i].peer = ks->peers[i]; GNUNET_CRYPTO_paillier_create (&ks->info[ks->local_peer_idx].paillier_public_key, &ks->paillier_private_key); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Generated paillier key pair\n", ks->local_peer_idx); generate_presecret_polynomial (ks); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Generated presecret polynomial\n", ks->local_peer_idx); insert_round1_element (ks); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Concluding for round 1\n", ks->local_peer_idx); GNUNET_CONSENSUS_conclude (ks->consensus, keygen_round1_conclude, ks); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Waiting for round 1 elements ...\n", ks->local_peer_idx); } /** * Called when the partial decryption consensus concludes. */ static void decrypt_conclude (void *cls) { struct DecryptSession *ds = cls; struct GNUNET_SECRETSHARING_DecryptResponseMessage *msg; struct GNUNET_MQ_Envelope *ev; gcry_mpi_t lagrange; gcry_mpi_t m; gcry_mpi_t tmp; gcry_mpi_t c_2; gcry_mpi_t prod; unsigned int *indices; unsigned int num; unsigned int i; unsigned int j; GNUNET_assert (0 != (lagrange = gcry_mpi_new (0))); GNUNET_assert (0 != (m = gcry_mpi_new (0))); GNUNET_assert (0 != (tmp = gcry_mpi_new (0))); GNUNET_assert (0 != (prod = gcry_mpi_new (0))); num = 0; for (i = 0; i < ds->share->num_peers; i++) if (NULL != ds->info[i].partial_decryption) num++; indices = GNUNET_malloc (num * sizeof (unsigned int)); j = 0; for (i = 0; i < ds->share->num_peers; i++) if (NULL != ds->info[i].partial_decryption) indices[j++] = ds->info[i].original_index; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: decrypt conclude, with %u peers\n", ds->share->my_peer, num); gcry_mpi_set_ui (prod, 1); for (i = 0; i < num; i++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "P%u: index of %u: %u\n", ds->share->my_peer, i, indices[i]); compute_lagrange_coefficient (lagrange, indices[i], indices, num); // w_i^{\lambda_i} gcry_mpi_powm (tmp, ds->info[indices[i]].partial_decryption, lagrange, elgamal_p); // product of all exponentiated partiel decryptions ... gcry_mpi_mulm (prod, prod, tmp, elgamal_p); } GNUNET_CRYPTO_mpi_scan_unsigned (&c_2, ds->ciphertext.c2_bits, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); GNUNET_assert (0 != gcry_mpi_invm (prod, prod, elgamal_p)); gcry_mpi_mulm (m, c_2, prod, elgamal_p); ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE); GNUNET_CRYPTO_mpi_print_unsigned (&msg->plaintext, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, m); msg->success = htonl (1); GNUNET_MQ_send (ds->client_mq, ev); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "sent decrypt done to client\n"); // FIXME: what if not enough peers participated? } /** * Get a string representation of an MPI. * The caller must free the returned string. * * @param mpi mpi to convert to a string * @return string representation of @a mpi, must be free'd by the caller */ static char * mpi_to_str (gcry_mpi_t mpi) { unsigned char *buf; GNUNET_assert (0 == gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, mpi)); return (char *) buf; } /** * Called when a new partial decryption arrives. */ static void decrypt_new_element (void *cls, const struct GNUNET_SET_Element *element) { struct DecryptSession *session = cls; const struct GNUNET_SECRETSHARING_DecryptData *d; struct DecryptPeerInfo *info; struct GNUNET_HashCode challenge_hash; /* nizk response */ gcry_mpi_t r; /* nizk challenge */ gcry_mpi_t challenge; /* nizk commit1, g^\beta */ gcry_mpi_t commit1; /* nizk commit2, c_1^\beta */ gcry_mpi_t commit2; /* homomorphic commitment to the peer's share, * public key share */ gcry_mpi_t sigma; /* partial decryption we received */ gcry_mpi_t w; /* ciphertext component #1 */ gcry_mpi_t c1; /* temporary variable (for comparision) #1 */ gcry_mpi_t tmp1; /* temporary variable (for comparision) #2 */ gcry_mpi_t tmp2; if (NULL == element) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decryption failed\n"); /* FIXME: destroy */ return; } if (element->size != sizeof *d) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "element of wrong size in decrypt consensus\n"); return; } d = element->data; info = get_decrypt_peer_info (session, &d->peer); if (NULL == info) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element from invalid peer (%s)\n", GNUNET_i2s (&d->peer)); return; } if (NULL != info->partial_decryption) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt element duplicate\n", GNUNET_i2s (&d->peer)); return; } if (0 != memcmp (&d->ciphertext, &session->ciphertext, sizeof (struct GNUNET_SECRETSHARING_Ciphertext))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: got decrypt element with non-matching ciphertext from P%u\n", (unsigned int) session->share->my_peer, (unsigned int) (info - session->info)); return; } GNUNET_CRYPTO_hash (offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext) + (char *) d, offsetof (struct GNUNET_SECRETSHARING_DecryptData, nizk_response) - offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext), &challenge_hash); GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash, sizeof (struct GNUNET_HashCode)); GNUNET_CRYPTO_mpi_scan_unsigned (&sigma, &session->share->sigmas[info - session->info], sizeof (struct GNUNET_SECRETSHARING_FieldElement)); GNUNET_CRYPTO_mpi_scan_unsigned (&c1, session->ciphertext.c1_bits, sizeof (struct GNUNET_SECRETSHARING_FieldElement)); GNUNET_CRYPTO_mpi_scan_unsigned (&commit1, &d->nizk_commit1, sizeof (struct GNUNET_SECRETSHARING_FieldElement)); GNUNET_CRYPTO_mpi_scan_unsigned (&commit2, &d->nizk_commit2, sizeof (struct GNUNET_SECRETSHARING_FieldElement)); GNUNET_CRYPTO_mpi_scan_unsigned (&r, &d->nizk_response, sizeof (struct GNUNET_SECRETSHARING_FieldElement)); GNUNET_CRYPTO_mpi_scan_unsigned (&w, &d->partial_decryption, sizeof (struct GNUNET_SECRETSHARING_FieldElement)); GNUNET_assert (NULL != (tmp1 = gcry_mpi_new (0))); GNUNET_assert (NULL != (tmp2 = gcry_mpi_new (0))); // tmp1 = g^r gcry_mpi_powm (tmp1, elgamal_g, r, elgamal_p); // tmp2 = g^\beta * \sigma^challenge gcry_mpi_powm (tmp2, sigma, challenge, elgamal_p); gcry_mpi_mulm (tmp2, tmp2, commit1, elgamal_p); if (0 != gcry_mpi_cmp (tmp1, tmp2)) { char *tmp1_str; char *tmp2_str; tmp1_str = mpi_to_str (tmp1); tmp2_str = mpi_to_str (tmp2); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: Received invalid partial decryption from P%u (eqn 1), expected %s got %s\n", session->share->my_peer, info - session->info, tmp1_str, tmp2_str); GNUNET_free (tmp1_str); GNUNET_free (tmp2_str); // return; } gcry_mpi_powm (tmp1, c1, r, elgamal_p); gcry_mpi_powm (tmp2, w, challenge, elgamal_p); gcry_mpi_mulm (tmp2, tmp2, commit2, elgamal_p); if (0 != gcry_mpi_cmp (tmp1, tmp2)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: Received invalid partial decryption from P%u (eqn 2)\n", session->share->my_peer, info - session->info); // return; } GNUNET_CRYPTO_mpi_scan_unsigned (&info->partial_decryption, &d->partial_decryption, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); } static void insert_decrypt_element (struct DecryptSession *ds) { struct GNUNET_SECRETSHARING_DecryptData d; struct GNUNET_SET_Element element; /* our share */ gcry_mpi_t s; /* partial decryption with our share */ gcry_mpi_t w; /* first component of the elgamal ciphertext */ gcry_mpi_t c1; /* nonce for dlog zkp */ gcry_mpi_t beta; gcry_mpi_t tmp; gcry_mpi_t challenge; gcry_mpi_t sigma; struct GNUNET_HashCode challenge_hash; /* make vagrind happy until we implement the real deal ... */ memset (&d, 0, sizeof d); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element\n", ds->share->my_peer); GNUNET_assert (ds->share->my_peer < ds->share->num_peers); GNUNET_CRYPTO_mpi_scan_unsigned (&c1, &ds->ciphertext.c1_bits, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); GNUNET_CRYPTO_mpi_scan_unsigned (&s, &ds->share->my_share, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); GNUNET_CRYPTO_mpi_scan_unsigned (&sigma, &ds->share->sigmas[ds->share->my_peer], GNUNET_SECRETSHARING_ELGAMAL_BITS / 8); GNUNET_assert (NULL != (w = gcry_mpi_new (0))); GNUNET_assert (NULL != (beta = gcry_mpi_new (0))); GNUNET_assert (NULL != (tmp = gcry_mpi_new (0))); // FIXME: unnecessary, remove once crypto works gcry_mpi_powm (tmp, elgamal_g, s, elgamal_p); if (0 != gcry_mpi_cmp (tmp, sigma)) { char *sigma_str = mpi_to_str (sigma); char *tmp_str = mpi_to_str (tmp); char *s_str = mpi_to_str (s); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Share of P%u is invalid, ref sigma %s, " "computed sigma %s, s %s\n", ds->share->my_peer, sigma_str, tmp_str, s_str); GNUNET_free (sigma_str); GNUNET_free (tmp_str); GNUNET_free (s_str); } gcry_mpi_powm (w, c1, s, elgamal_p); element.data = (void *) &d; element.size = sizeof (struct GNUNET_SECRETSHARING_DecryptData); element.type = 0; d.ciphertext = ds->ciphertext; d.peer = my_peer; GNUNET_CRYPTO_mpi_print_unsigned (&d.partial_decryption, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, w); // create the zero knowledge proof // randomly choose beta such that 0 < beta < q do { gcry_mpi_randomize (beta, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM); } while ((gcry_mpi_cmp_ui (beta, 0) == 0) || (gcry_mpi_cmp (beta, elgamal_q) >= 0)); // tmp = g^beta gcry_mpi_powm (tmp, elgamal_g, beta, elgamal_p); GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_commit1, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp); // tmp = (c_1)^beta gcry_mpi_powm (tmp, c1, beta, elgamal_p); GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_commit2, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp); // the challenge is the hash of everything up to the response GNUNET_CRYPTO_hash (offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext) + (char *) &d, offsetof (struct GNUNET_SECRETSHARING_DecryptData, nizk_response) - offsetof (struct GNUNET_SECRETSHARING_DecryptData, ciphertext), &challenge_hash); GNUNET_CRYPTO_mpi_scan_unsigned (&challenge, &challenge_hash, sizeof (struct GNUNET_HashCode)); // compute the response in tmp, // tmp = (c * s + beta) mod q gcry_mpi_mulm (tmp, challenge, s, elgamal_q); gcry_mpi_addm (tmp, tmp, beta, elgamal_q); GNUNET_CRYPTO_mpi_print_unsigned (&d.nizk_response, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp); d.purpose.size = htonl (element.size - offsetof (struct GNUNET_SECRETSHARING_DecryptData, purpose)); d.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SECRETSHARING_DECRYPTION); GNUNET_CRYPTO_eddsa_sign (my_peer_private_key, &d.purpose, &d.signature); GNUNET_CONSENSUS_insert (ds->consensus, &element, NULL, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: Inserting decrypt element done!\n", ds->share->my_peer); } /** * Functions with this signature are called whenever a message is * received. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_client_decrypt (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg = (const void *) message; struct DecryptSession *ds; struct GNUNET_HashCode session_id; unsigned int i; ds = GNUNET_new (struct DecryptSession); // FIXME: check if session already exists GNUNET_CONTAINER_DLL_insert (decrypt_sessions_head, decrypt_sessions_tail, ds); ds->client = client; ds->client_mq = GNUNET_MQ_queue_for_server_client (client); ds->start = GNUNET_TIME_absolute_ntoh (msg->start); ds->deadline = GNUNET_TIME_absolute_ntoh (msg->deadline); ds->ciphertext = msg->ciphertext; ds->share = GNUNET_SECRETSHARING_share_read (&msg[1], ntohs (msg->header.size) - sizeof *msg, NULL); // FIXME: probably should be break rather than assert GNUNET_assert (NULL != ds->share); // FIXME: this is probably sufficient, but kdf/hash with all values would be nicer ... GNUNET_CRYPTO_hash (&msg->ciphertext, sizeof (struct GNUNET_SECRETSHARING_Ciphertext), &session_id); ds->consensus = GNUNET_CONSENSUS_create (cfg, ds->share->num_peers, ds->share->peers, &session_id, ds->start, ds->deadline, &decrypt_new_element, ds); ds->info = GNUNET_new_array (ds->share->num_peers, struct DecryptPeerInfo); for (i = 0; i < ds->share->num_peers; i++) { ds->info[i].peer = ds->share->peers[i]; ds->info[i].original_index = ds->share->original_indices[i]; } insert_decrypt_element (ds); GNUNET_CONSENSUS_conclude (ds->consensus, decrypt_conclude, ds); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypting with %u peers\n", ds->share->num_peers); } static void init_crypto_constants (void) { GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX, GNUNET_SECRETSHARING_ELGAMAL_Q_HEX, 0, NULL)); GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX, GNUNET_SECRETSHARING_ELGAMAL_P_HEX, 0, NULL)); GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX, GNUNET_SECRETSHARING_ELGAMAL_G_HEX, 0, NULL)); } static struct KeygenSession * keygen_session_get (struct GNUNET_SERVER_Client *client) { struct KeygenSession *ks; for (ks = keygen_sessions_head; NULL != ks; ks = ks->next) if (ks->client == client) return ks; return NULL; } static struct DecryptSession * decrypt_session_get (struct GNUNET_SERVER_Client *client) { struct DecryptSession *ds; for (ds = decrypt_sessions_head; NULL != ds; ds = ds->next) if (ds->client == client) return ds; return NULL; } /** * Clean up after a client has disconnected * * @param cls closure, unused * @param client the client to clean up after */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct KeygenSession *ks; struct DecryptSession *ds; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handling client disconnect\n"); ks = keygen_session_get (client); if (NULL != ks) keygen_session_destroy (ks); ds = decrypt_session_get (client); if (NULL != ds) decrypt_session_destroy (ds); } /** * Process template requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {handle_client_keygen, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE, 0}, {handle_client_decrypt, NULL, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT, 0}, {NULL, NULL, 0, 0} }; cfg = c; srv = server; my_peer_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); if (NULL == my_peer_private_key) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not access host private key\n"); GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } init_crypto_constants (); if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n"); GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, NULL); } /** * The main function for the template service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "secretsharing", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } gnunet-0.10.1/src/secretsharing/gnunet-secretsharing-profiler.c0000644000175000017500000004024212276375236021604 00000000000000/* This file is part of GNUnet (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file secretsharing/gnunet-secretsharing-profiler.c * @brief profiling tool for distributed key generation and decryption * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_secretsharing_service.h" #include "gnunet_testbed_service.h" /** * How many peers should participate in the key generation? */ static unsigned int num_peers = 3; /** * What should the threshold for then key be? */ static unsigned int threshold = 2; /** * Should we try to decrypt a value after the key generation? */ static unsigned int decrypt = GNUNET_NO; /** * When would we like to see the operation finished? */ static struct GNUNET_TIME_Relative timeout; /** * When should dkg communication start? */ static struct GNUNET_TIME_Relative delay; /** * Handles for secretsharing sessions. */ static struct GNUNET_SECRETSHARING_Session **session_handles; static struct GNUNET_SECRETSHARING_DecryptionHandle **decrypt_handles; /** * Shares we got from the distributed key generation. */ static struct GNUNET_SECRETSHARING_Share **shares; static struct GNUNET_SECRETSHARING_PublicKey common_pubkey; /** * ??? */ static struct GNUNET_TESTBED_Operation **testbed_operations; static unsigned int num_connected_sessions; static unsigned int num_connected_decrypt; static struct GNUNET_TESTBED_Peer **peers; static struct GNUNET_PeerIdentity *peer_ids; static unsigned int num_retrieved_peer_ids; static unsigned int num_generated; static unsigned int num_decrypted; static struct GNUNET_HashCode session_id; static int verbose; static struct GNUNET_SECRETSHARING_Plaintext reference_plaintext; static struct GNUNET_SECRETSHARING_Ciphertext ciphertext; static struct GNUNET_TIME_Absolute dkg_start; static struct GNUNET_TIME_Absolute dkg_deadline; static struct GNUNET_TIME_Absolute decrypt_start; static struct GNUNET_TIME_Absolute decrypt_deadline; /** * Signature of the event handler function called by the * respective event controller. * * @param cls closure * @param event information about the event */ static void controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { GNUNET_assert (0); } /** * Callback to be called when a service connect operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void session_connect_complete (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "testbed connect emsg: %s\n", emsg); GNUNET_assert (0); } num_connected_sessions++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "dkg: session connect complete\n"); if (num_connected_sessions == num_peers) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "dkg: all peers connected\n"); } } /** * Callback to be called when a service connect operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void decrypt_connect_complete (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "testbed connect emsg: %s\n", emsg); GNUNET_assert (0); } num_connected_decrypt++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypt: session connect complete\n"); if (num_connected_decrypt == num_peers) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypt: all peers connected\n"); } } /** * Called when a decryption has succeeded. * * @param cls Plaintext * @param plaintext Plaintext */ static void decrypt_cb (void *cls, const struct GNUNET_SECRETSHARING_Plaintext *plaintext) { struct GNUNET_SECRETSHARING_DecryptionHandle **dhp = cls; unsigned int n = dhp - decrypt_handles; num_decrypted++; *dhp = NULL; if (NULL == plaintext) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt failed for peer %u\n", n); return; } else if (0 == memcmp (&reference_plaintext, plaintext, sizeof (struct GNUNET_SECRETSHARING_Plaintext))) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypt got correct result for peer %u\n", n); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "decrypt got wrong result for peer %u\n", n); if (num_decrypted == num_peers) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "every peer decrypted\n"); GNUNET_SCHEDULER_shutdown (); } *dhp = NULL; } /** * Adapter function called to establish a connection to * a service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * decrypt_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_SECRETSHARING_DecryptionHandle **hp = cls; unsigned int n = hp - decrypt_handles; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "decrypt connect adapter, %d peers\n", num_peers); *hp = GNUNET_SECRETSHARING_decrypt (cfg, shares[n], &ciphertext, decrypt_start, decrypt_deadline, decrypt_cb, hp); return *hp; } /** * Adapter function called to destroy a connection to * a service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void decrypt_disconnect_adapter(void *cls, void *op_result) { struct GNUNET_SECRETSHARING_DecryptionHandle **dh = cls; if (NULL != *dh) { GNUNET_SECRETSHARING_decrypt_cancel (*dh); *dh = NULL; } } static void secret_ready_cb (void *cls, struct GNUNET_SECRETSHARING_Share *my_share, struct GNUNET_SECRETSHARING_PublicKey *public_key, unsigned int num_ready_peers, struct GNUNET_PeerIdentity *ready_peers) { struct GNUNET_SECRETSHARING_Session **sp = cls; unsigned int n = sp - session_handles; char pubkey_str[1024]; char *ret; num_generated++; *sp = NULL; shares[n] = my_share; if (NULL == my_share) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "key generation failed for peer #%u\n", n); } else { ret = GNUNET_STRINGS_data_to_string (public_key, sizeof *public_key, pubkey_str, 1024); GNUNET_assert (NULL != ret); *ret = '\0'; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "key generation successful for peer #%u, pubkey %s\n", n, pubkey_str); /* we're the first to get the key -> store it */ if (num_generated == 1) { common_pubkey = *public_key; } else if (0 != memcmp (public_key, &common_pubkey, sizeof (struct GNUNET_SECRETSHARING_PublicKey))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "generated public keys do not match\n"); GNUNET_SCHEDULER_shutdown (); return; } } // FIXME: destroy testbed operation if (num_generated == num_peers) { int i; if (GNUNET_NO == decrypt) { GNUNET_SCHEDULER_shutdown (); return; } decrypt_start = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay); decrypt_deadline = GNUNET_TIME_absolute_add (decrypt_start, timeout); // compute g^42 GNUNET_SECRETSHARING_plaintext_generate_i (&reference_plaintext, 42); GNUNET_SECRETSHARING_encrypt (&common_pubkey, &reference_plaintext, &ciphertext); // FIXME: store the ops somewhere! for (i = 0; i < num_peers; i++) GNUNET_TESTBED_service_connect (NULL, peers[i], "secretsharing", &decrypt_connect_complete, NULL, &decrypt_connect_adapter, &decrypt_disconnect_adapter, &decrypt_handles[i]); } } /** * Adapter function called to establish a connection to * a service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * session_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_SECRETSHARING_Session **sp = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "connect adapter, %d peers\n", num_peers); *sp = GNUNET_SECRETSHARING_create_session (cfg, num_peers, peer_ids, &session_id, dkg_start, dkg_deadline, threshold, &secret_ready_cb, sp); return *sp; } /** * Adapter function called to destroy a connection to * a service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void session_disconnect_adapter (void *cls, void *op_result) { struct GNUNET_SECRETSHARING_Session **sp = cls; if (NULL != *sp) { GNUNET_SECRETSHARING_session_destroy (*sp); *sp = NULL; } } /** * Callback to be called when the requested peer information is available * * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() * @param op the operation this callback corresponds to * @param pinfo the result; will be NULL if the operation has failed * @param emsg error message if the operation has failed; will be NULL if the * operation is successfull */ static void peer_info_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) { struct GNUNET_PeerIdentity *p; int i; GNUNET_assert (NULL == emsg); p = (struct GNUNET_PeerIdentity *) cb_cls; if (pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY) { *p = *pinfo->result.id; num_retrieved_peer_ids++; if (num_retrieved_peer_ids == num_peers) for (i = 0; i < num_peers; i++) testbed_operations[i] = GNUNET_TESTBED_service_connect (NULL, peers[i], "secretsharing", session_connect_complete, NULL, session_connect_adapter, session_disconnect_adapter, &session_handles[i]); } else { GNUNET_assert (0); } GNUNET_TESTBED_operation_done (op); } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param started_peers handle to peers run in the testbed. NULL upon timeout (see * GNUNET_TESTBED_test_run()). * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **started_peers, unsigned int links_succeeded, unsigned int links_failed) { int i; GNUNET_log_setup ("gnunet-secretsharing-profiler", "INFO", NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test master\n"); peers = started_peers; peer_ids = GNUNET_malloc (num_peers * sizeof (struct GNUNET_PeerIdentity)); session_handles = GNUNET_new_array (num_peers, struct GNUNET_SECRETSHARING_Session *); decrypt_handles = GNUNET_new_array (num_peers, struct GNUNET_SECRETSHARING_DecryptionHandle *); testbed_operations = GNUNET_new_array (num_peers, struct GNUNET_TESTBED_Operation *); shares = GNUNET_new_array (num_peers, struct GNUNET_SECRETSHARING_Share *); for (i = 0; i < num_peers; i++) GNUNET_TESTBED_peer_get_information (peers[i], GNUNET_TESTBED_PIT_IDENTITY, peer_info_cb, &peer_ids[i]); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { static char *session_str = "gnunet-secretsharing/test"; char *topology; int topology_cmp_result; dkg_start = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay); dkg_deadline = GNUNET_TIME_absolute_add (dkg_start, timeout); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", "OVERLAY_TOPOLOGY", &topology)) { fprintf (stderr, "'OVERLAY_TOPOLOGY' not found in 'testbed' config section, " "seems like you passed the wrong configuration file\n"); return; } topology_cmp_result = strcasecmp (topology, "NONE"); GNUNET_free (topology); if (0 == topology_cmp_result) { fprintf (stderr, "'OVERLAY_TOPOLOGY' set to 'NONE', " "seems like you passed the wrong configuration file\n"); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "running gnunet-secretsharing-profiler\n"); GNUNET_CRYPTO_hash (session_str, strlen (session_str), &session_id); (void) GNUNET_TESTBED_test_run ("gnunet-secretsharing-profiler", cfgfile, num_peers, 0, controller_cb, NULL, test_master, NULL); } int main (int argc, char **argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'n', "num-peers", NULL, gettext_noop ("number of peers in consensus"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers }, { 'D', "delay", NULL, gettext_noop ("dkg start delay"), GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &delay }, { 't', "timeout", NULL, gettext_noop ("dkg timeout"), GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &timeout }, { 'k', "threshold", NULL, gettext_noop ("threshold"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &threshold }, { 'd', "decrypt", NULL, gettext_noop ("also profile decryption"), GNUNET_NO, &GNUNET_GETOPT_set_one, &decrypt }, { 'V', "verbose", NULL, gettext_noop ("be more verbose (print received values)"), GNUNET_NO, &GNUNET_GETOPT_set_one, &verbose }, GNUNET_GETOPT_OPTION_END }; delay = GNUNET_TIME_UNIT_ZERO; timeout = GNUNET_TIME_UNIT_MINUTES; GNUNET_PROGRAM_run2 (argc, argv, "gnunet-secretsharing-profiler", "help", options, &run, NULL, GNUNET_YES); return 0; } gnunet-0.10.1/src/secretsharing/secretsharing.h0000644000175000017500000001117612320724313016457 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Florian Dold * @file secretsharing/secretsharing.h * @brief messages used for the secretsharing api */ #ifndef SECRETSHARING_H #define SECRETSHARING_H #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_time_lib.h" #include "gnunet_common.h" #include "gnunet_secretsharing_service.h" GNUNET_NETWORK_STRUCT_BEGIN struct GNUNET_SECRETSHARING_FieldElement { /** * Value of an element in <elgamal_g>. */ unsigned char bits[GNUNET_SECRETSHARING_ELGAMAL_BITS / 8]; }; struct GNUNET_SECRETSHARING_CreateMessage { /** * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE */ struct GNUNET_MessageHeader header; /** * Session ID, will be used for consensus. */ struct GNUNET_HashCode session_id GNUNET_PACKED; /** * Start time for communication with the other peers. */ struct GNUNET_TIME_AbsoluteNBO start; /** * Deadline for the establishment of the crypto system. */ struct GNUNET_TIME_AbsoluteNBO deadline; /** * Mininum number of cooperating peers to decrypt a * value. */ uint16_t threshold GNUNET_PACKED; /** * Number of peers at the end of this message. */ uint16_t num_peers GNUNET_PACKED; /* struct GNUNET_PeerIdentity[num_peers]; */ }; struct GNUNET_SECRETSHARING_ShareHeaderNBO { /** * Threshold for the key this share belongs to. */ uint16_t threshold; /** * Peers that have the share. */ uint16_t num_peers; /** * Index of our peer in the list. */ uint16_t my_peer; /** * Public key. Must correspond to the product of * the homomorphic share commitments. */ struct GNUNET_SECRETSHARING_PublicKey public_key; /** * Share of 'my_peer' */ struct GNUNET_SECRETSHARING_FieldElement my_share; }; /** * Notify the client that then threshold secret has been * established. */ struct GNUNET_SECRETSHARING_SecretReadyMessage { /** * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY */ struct GNUNET_MessageHeader header; /* rest: the serialized share */ }; struct GNUNET_SECRETSHARING_DecryptRequestMessage { /** * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_REQUEST */ struct GNUNET_MessageHeader header; /** * Until when should the decryption start? */ struct GNUNET_TIME_AbsoluteNBO start; /** * Until when should the decryption be finished? */ struct GNUNET_TIME_AbsoluteNBO deadline; /** * Ciphertext we want to decrypt. */ struct GNUNET_SECRETSHARING_Ciphertext ciphertext; /* the share with payload */ }; struct GNUNET_SECRETSHARING_DecryptResponseMessage { /** * Type: GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE */ struct GNUNET_MessageHeader header; /** * Zero if decryption failed, non-zero if decryption succeeded. * If the decryption failed, plaintext is also zero. */ uint32_t success; /** * Decrypted plaintext. */ struct GNUNET_SECRETSHARING_FieldElement plaintext; }; GNUNET_NETWORK_STRUCT_END /** * A share, with all values in in host byte order. */ struct GNUNET_SECRETSHARING_Share { /** * Threshold for the key this share belongs to. */ uint16_t threshold; /** * Peers that have the share. */ uint16_t num_peers; /** * Index of our peer in the list. */ uint16_t my_peer; /** * Public key. Computed from the * exponentiated coefficients. */ struct GNUNET_SECRETSHARING_PublicKey public_key; /** * Share of 'my_peer' */ struct GNUNET_SECRETSHARING_FieldElement my_share; /** * Peer identities (includes 'my_peer') */ struct GNUNET_PeerIdentity *peers; /* * For each peer, store elgamal_g to the peer's * share. */ struct GNUNET_SECRETSHARING_FieldElement *sigmas; /* * Original indices of peers from the DKG round. */ uint16_t *original_indices; }; #endif gnunet-0.10.1/src/secretsharing/Makefile.am0000644000175000017500000000376612320751517015515 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ secretsharing.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif bin_PROGRAMS = \ gnunet-secretsharing-profiler libexec_PROGRAMS = \ gnunet-service-secretsharing lib_LTLIBRARIES = \ libgnunetsecretsharing.la gnunet_secretsharing_profiler_SOURCES = \ gnunet-secretsharing-profiler.c gnunet_secretsharing_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/secretsharing/libgnunetsecretsharing.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(GN_LIBINTL) gnunet_secretsharing_profiler_DEPENDENCIES = \ libgnunetsecretsharing.la gnunet_service_secretsharing_SOURCES = \ gnunet-service-secretsharing.c \ secretsharing_common.c \ secretsharing_protocol.h gnunet_service_secretsharing_CFLAGS = $(AM_CFLAGS) gnunet_service_secretsharing_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/consensus/libgnunetconsensus.la \ $(LIBGCRYPT_LIBS) \ $(GN_LIBINTL) gnunet_service_secretsharing_DEPENDENCIES = \ $(top_builddir)/src/set/libgnunetset.la libgnunetsecretsharing_la_SOURCES = \ secretsharing_api.c \ secretsharing_common.c \ secretsharing.h libgnunetsecretsharing_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetsecretsharing_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) check_PROGRAMS = \ test_secretsharing_api if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_secretsharing_api_SOURCES = \ test_secretsharing_api.c test_secretsharing_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/secretsharing/libgnunetsecretsharing.la EXTRA_DIST = \ test_secretsharing.conf gnunet-0.10.1/src/secretsharing/secretsharing.conf.in0000644000175000017500000000062312236140650017557 00000000000000[secretsharing] AUTOSTART = NO @JAVAPORT@PORT = 2114 HOSTNAME = localhost BINARY = gnunet-service-secretsharing ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-secretsharing.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = gnunet-0.10.1/src/secretsharing/secretsharing_api.c0000644000175000017500000003056112300637202017300 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file secretsharing/secretsharing_api.c * @brief * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_secretsharing_service.h" #include "secretsharing.h" #include #define LOG(kind,...) GNUNET_log_from (kind, "secretsharing-api",__VA_ARGS__) /** * Session that will eventually establish a shared secred between * the involved peers and allow encryption and cooperative decryption. */ struct GNUNET_SECRETSHARING_Session { /** * Client connected to the secretsharing service. */ struct GNUNET_CLIENT_Connection *client; /** * Message queue for 'client'. */ struct GNUNET_MQ_Handle *mq; /** * Called when the secret sharing is done. */ GNUNET_SECRETSHARING_SecretReadyCallback secret_ready_cb; /** * Closure for 'secret_ready_cb'. */ void *secret_ready_cls; }; struct GNUNET_SECRETSHARING_DecryptionHandle { /** * Client connected to the secretsharing service. */ struct GNUNET_CLIENT_Connection *client; /** * Message queue for 'client'. */ struct GNUNET_MQ_Handle *mq; /** * Called when the secret sharing is done. */ GNUNET_SECRETSHARING_DecryptCallback decrypt_cb; /** * Closure for 'decrypt_cb'. */ void *decrypt_cls; }; /** * The ElGamal prime field order as libgcrypt mpi. * Initialized in #init_crypto_constants. */ static gcry_mpi_t elgamal_q; /** * Modulus of the prime field used for ElGamal. * Initialized in #init_crypto_constants. */ static gcry_mpi_t elgamal_p; /** * Generator for prime field of order 'elgamal_q'. * Initialized in #init_crypto_constants. */ static gcry_mpi_t elgamal_g; static void ensure_elgamal_initialized (void) { if (NULL != elgamal_q) return; /* looks like crypto is already initialized */ GNUNET_assert (0 == gcry_mpi_scan (&elgamal_q, GCRYMPI_FMT_HEX, GNUNET_SECRETSHARING_ELGAMAL_Q_HEX, 0, NULL)); GNUNET_assert (0 == gcry_mpi_scan (&elgamal_p, GCRYMPI_FMT_HEX, GNUNET_SECRETSHARING_ELGAMAL_P_HEX, 0, NULL)); GNUNET_assert (0 == gcry_mpi_scan (&elgamal_g, GCRYMPI_FMT_HEX, GNUNET_SECRETSHARING_ELGAMAL_G_HEX, 0, NULL)); } static void handle_session_client_error (void *cls, enum GNUNET_MQ_Error error) { struct GNUNET_SECRETSHARING_Session *s = cls; s->secret_ready_cb (s->secret_ready_cls, NULL, NULL, 0, NULL); } static void handle_decrypt_client_error (void *cls, enum GNUNET_MQ_Error error) { struct GNUNET_SECRETSHARING_DecryptionHandle *dh = cls; dh->decrypt_cb (dh->decrypt_cls, NULL); } static void handle_secret_ready (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_SECRETSHARING_Session *session = cls; struct GNUNET_SECRETSHARING_Share *share; const struct GNUNET_SECRETSHARING_SecretReadyMessage *m = (const void *) msg; size_t share_size; LOG (GNUNET_ERROR_TYPE_DEBUG, "got secret ready message of size %u\n", ntohs (m->header.size)); share_size = ntohs (m->header.size) - sizeof *m; share = GNUNET_SECRETSHARING_share_read (&m[1], share_size, NULL); session->secret_ready_cb (session->secret_ready_cls, share, /* FIXME */ &share->public_key, share->num_peers, (struct GNUNET_PeerIdentity *) &m[1]); GNUNET_SECRETSHARING_session_destroy (session); } void GNUNET_SECRETSHARING_session_destroy (struct GNUNET_SECRETSHARING_Session *session) { GNUNET_MQ_destroy (session->mq); session->mq = NULL; GNUNET_CLIENT_disconnect (session->client); session->client = NULL; GNUNET_free (session); } struct GNUNET_SECRETSHARING_Session * GNUNET_SECRETSHARING_create_session (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, const struct GNUNET_PeerIdentity *peers, const struct GNUNET_HashCode *session_id, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, unsigned int threshold, GNUNET_SECRETSHARING_SecretReadyCallback cb, void *cls) { struct GNUNET_SECRETSHARING_Session *s; struct GNUNET_MQ_Envelope *ev; struct GNUNET_SECRETSHARING_CreateMessage *msg; static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { {handle_secret_ready, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_SECRET_READY, 0}, GNUNET_MQ_HANDLERS_END }; s = GNUNET_new (struct GNUNET_SECRETSHARING_Session); s->client = GNUNET_CLIENT_connect ("secretsharing", cfg); s->secret_ready_cb = cb; s->secret_ready_cls = cls; GNUNET_assert (NULL != s->client); s->mq = GNUNET_MQ_queue_for_connection_client (s->client, mq_handlers, handle_session_client_error, s); GNUNET_assert (NULL != s->mq); ev = GNUNET_MQ_msg_extra (msg, num_peers * sizeof (struct GNUNET_PeerIdentity), GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_GENERATE); msg->threshold = htons (threshold); msg->num_peers = htons (num_peers); msg->session_id = *session_id; msg->start = GNUNET_TIME_absolute_hton (start); msg->deadline = GNUNET_TIME_absolute_hton (deadline); memcpy (&msg[1], peers, num_peers * sizeof (struct GNUNET_PeerIdentity)); GNUNET_MQ_send (s->mq, ev); LOG (GNUNET_ERROR_TYPE_DEBUG, "secretsharing session created with %u peers\n", num_peers); return s; } static void handle_decrypt_done (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_SECRETSHARING_DecryptionHandle *dh = cls; const struct GNUNET_SECRETSHARING_DecryptResponseMessage *m = (const void *) msg; const struct GNUNET_SECRETSHARING_Plaintext *plaintext; if (m->success == 0) plaintext = NULL; else plaintext = (void *) &m->plaintext; dh->decrypt_cb (dh->decrypt_cls, plaintext); GNUNET_SECRETSHARING_decrypt_cancel (dh); } /** * Publish the given ciphertext for decryption. Once a sufficient (>=k) number of peers has * published the same value, it will be decrypted. * * When the operation is canceled, the decrypt_cb is not called anymore, but the calling * peer may already have irrevocably contributed his share for the decryption of the value. * * @param share our secret share to use for decryption * @param ciphertext ciphertext to publish in order to decrypt it (if enough peers agree) * @param decrypt_cb callback called once the decryption succeeded * @param decrypt_cb_cls closure for @a decrypt_cb * @return handle to cancel the operation */ struct GNUNET_SECRETSHARING_DecryptionHandle * GNUNET_SECRETSHARING_decrypt (const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_SECRETSHARING_Share *share, const struct GNUNET_SECRETSHARING_Ciphertext *ciphertext, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, GNUNET_SECRETSHARING_DecryptCallback decrypt_cb, void *decrypt_cb_cls) { struct GNUNET_SECRETSHARING_DecryptionHandle *s; struct GNUNET_MQ_Envelope *ev; struct GNUNET_SECRETSHARING_DecryptRequestMessage *msg; static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { {handle_decrypt_done, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT_DONE, 0}, GNUNET_MQ_HANDLERS_END }; size_t share_size; s = GNUNET_new (struct GNUNET_SECRETSHARING_DecryptionHandle); s->client = GNUNET_CLIENT_connect ("secretsharing", cfg); s->decrypt_cb = decrypt_cb; s->decrypt_cls = decrypt_cb_cls; GNUNET_assert (NULL != s->client); s->mq = GNUNET_MQ_queue_for_connection_client (s->client, mq_handlers, handle_decrypt_client_error, s); GNUNET_assert (NULL != s->mq); GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, NULL, 0, &share_size)); ev = GNUNET_MQ_msg_extra (msg, share_size, GNUNET_MESSAGE_TYPE_SECRETSHARING_CLIENT_DECRYPT); GNUNET_assert (GNUNET_OK == GNUNET_SECRETSHARING_share_write (share, &msg[1], share_size, NULL)); msg->start = GNUNET_TIME_absolute_hton (start); msg->deadline = GNUNET_TIME_absolute_hton (deadline); msg->ciphertext = *ciphertext; GNUNET_MQ_send (s->mq, ev); LOG (GNUNET_ERROR_TYPE_DEBUG, "decrypt session created\n"); return s; } int GNUNET_SECRETSHARING_plaintext_generate_i (struct GNUNET_SECRETSHARING_Plaintext *plaintext, int64_t exponent) { int negative; gcry_mpi_t x; ensure_elgamal_initialized (); GNUNET_assert (NULL != (x = gcry_mpi_new (0))); negative = GNUNET_NO; if (exponent < 0) { negative = GNUNET_YES; exponent = -exponent; } gcry_mpi_set_ui (x, exponent); gcry_mpi_powm (x, elgamal_g, x, elgamal_p); if (GNUNET_YES == negative) { int res; res = gcry_mpi_invm (x, x, elgamal_p); if (0 == res) return GNUNET_SYSERR; } GNUNET_CRYPTO_mpi_print_unsigned (plaintext, sizeof (struct GNUNET_SECRETSHARING_Plaintext), x); return GNUNET_OK; } /** * Encrypt a value. This operation is executed locally, no communication is * necessary. * * This is a helper function, encryption can be done soley with a session's public key * and the crypto system parameters. * * @param public_key public key to use for decryption * @param message message to encrypt * @param message_size number of bytes in @a message * @param result_ciphertext pointer to store the resulting ciphertext * @return #GNUNET_YES on succes, #GNUNET_SYSERR if the message is invalid (invalid range) */ int GNUNET_SECRETSHARING_encrypt (const struct GNUNET_SECRETSHARING_PublicKey *public_key, const struct GNUNET_SECRETSHARING_Plaintext *plaintext, struct GNUNET_SECRETSHARING_Ciphertext *result_ciphertext) { /* pubkey */ gcry_mpi_t h; /* nonce */ gcry_mpi_t y; /* plaintext message */ gcry_mpi_t m; /* temp value */ gcry_mpi_t tmp; ensure_elgamal_initialized (); GNUNET_assert (NULL != (h = gcry_mpi_new (0))); GNUNET_assert (NULL != (y = gcry_mpi_new (0))); GNUNET_assert (NULL != (tmp = gcry_mpi_new (0))); GNUNET_CRYPTO_mpi_scan_unsigned (&h, public_key, sizeof *public_key); GNUNET_CRYPTO_mpi_scan_unsigned (&m, plaintext, sizeof *plaintext); // Randomize y such that 0 < y < elgamal_q. // The '- 1' is necessary as bitlength(q) = bitlength(p) - 1. do { gcry_mpi_randomize (y, GNUNET_SECRETSHARING_ELGAMAL_BITS - 1, GCRY_WEAK_RANDOM); } while ((gcry_mpi_cmp_ui (y, 0) == 0) || (gcry_mpi_cmp (y, elgamal_q) >= 0)); // tmp <- g^y gcry_mpi_powm (tmp, elgamal_g, y, elgamal_p); // write tmp to c1 GNUNET_CRYPTO_mpi_print_unsigned (&result_ciphertext->c1_bits, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp); // tmp <- h^y gcry_mpi_powm (tmp, h, y, elgamal_p); // tmp <- tmp * m gcry_mpi_mulm (tmp, tmp, m, elgamal_p); // write tmp to c2 GNUNET_CRYPTO_mpi_print_unsigned (&result_ciphertext->c2_bits, GNUNET_SECRETSHARING_ELGAMAL_BITS / 8, tmp); return GNUNET_OK; } void GNUNET_SECRETSHARING_decrypt_cancel (struct GNUNET_SECRETSHARING_DecryptionHandle *h) { GNUNET_MQ_destroy (h->mq); h->mq = NULL; GNUNET_CLIENT_disconnect (h->client); h->client = NULL; GNUNET_free (h); } gnunet-0.10.1/src/secretsharing/test_secretsharing.conf0000644000175000017500000000113212306316411020203 00000000000000[secretsharing] AUTOSTART = YES #PREFIX = valgrind OPTIONS = -LINFO [consensus] AUTOSTART = YES [transport] OPTIONS = -LERROR [arm] DEFAULTSERVICES = core consensus set secretsharing [set] OPTIONS = -L INFO AUTOSTART = YES #PREFIX = valgrind --leak-check=full [testbed] OVERLAY_TOPOLOGY = CLIQUE [hostlist] SERVERS = [nat] # Use addresses from the local network interfaces (inluding loopback, but also others) USE_LOCALADDR = YES # Disable IPv6 support DISABLEV6 = NO # Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8) RETURN_LOCAL_ADDRESSES = YES [nse] AUTOSTART = NO gnunet-0.10.1/src/fs/0000755000175000017500000000000012320755627011302 500000000000000gnunet-0.10.1/src/fs/test_gnunet_service_fs_p2p_mesh.conf0000644000175000017500000000105512225230043020416 00000000000000@INLINE@ fs_test_lib_data.conf [fs] # FIXME: this option needs to be set for the # testcase to truly work; however, as the code # is not finished, not setting the option should # allow the test to at least pass for now... DISABLE_ANON_TRANSFER = YES # Do we cache content from other nodes? (may improve anonymity) CONTENT_CACHING = NO # Do we send unsolicited data to other nodes if we have excess bandwidth? # (may improve anonymity, probably not a good idea if content_caching is NO) CONTENT_PUSHING = NO #PREFIX = valgrind [mesh] #PREFIX = valgrind gnunet-0.10.1/src/fs/test_fs_download_mesh.conf0000644000175000017500000000032612225230043016424 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-download/ [download-test] # set to 'YES' to test non-anonymous download USE_STREAM = NO # set to 'YES' to use indexing USE_INDEX = NO gnunet-0.10.1/src/fs/gnunet-service-fs_indexing.h0000644000175000017500000000735412225777503016636 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_indexing.h * @brief indexing for the file-sharing service * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_FS_INDEXING_H #define GNUNET_SERVICE_FS_INDEXING_H #include "gnunet_block_lib.h" #include "gnunet_core_service.h" #include "gnunet_datastore_service.h" #include "gnunet_peer_lib.h" #include "gnunet_protocols.h" #include "gnunet_signatures.h" #include "gnunet_util_lib.h" /** * We've received an on-demand encoded block from the datastore. * Attempt to do on-demand encoding and (if successful), call the * continuation with the resulting block. On error, clean up and ask * the datastore for more results. * * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * @param cont function to call with the actual block (at most once, on success) * @param cont_cls closure for cont * @return GNUNET_OK on success */ int GNUNET_FS_handle_on_demand_block (const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid, GNUNET_DATASTORE_DatumProcessor cont, void *cont_cls); /** * Handle INDEX_START-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ void GNUNET_FS_handle_index_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle INDEX_LIST_GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ void GNUNET_FS_handle_index_list_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle UNINDEX-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ void GNUNET_FS_handle_unindex (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Initialize the indexing submodule. * * @param c configuration to use * @param d datastore to use * @return GNUNET_OK on success */ int GNUNET_FS_indexing_init (const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_DATASTORE_Handle *d); /** * Shutdown the module. */ void GNUNET_FS_indexing_done (void); #endif gnunet-0.10.1/src/fs/fs_uri.c0000644000175000017500000015322312267431203012652 00000000000000/* This file is part of GNUnet. (C) 2003--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_uri.c * @brief Parses and produces uri strings. * @author Igor Wronsky, Christian Grothoff * * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER". * The specific structure of "IDENTIFIER" depends on the module and * maybe differenciated into additional subcategories if applicable. * This module only deals with fs identifiers (MODULE = "fs"). *

* * This module only parses URIs for the AFS module. The FS URIs fall * into four categories, "chk", "sks", "ksk" and "loc". The first three * categories were named in analogy (!) to Freenet, but they do NOT * work in exactly the same way. They are very similar from the user's * point of view (unique file identifier, subspace, keyword), but the * implementation is rather different in pretty much every detail. * The concrete URI formats are: * *

  • * * First, there are URIs that identify a file. They have the format * "gnunet://fs/chk/HEX1.HEX2.SIZE". These URIs can be used to * download the file. The description, filename, mime-type and other * meta-data is NOT part of the file-URI since a URI uniquely * identifies a resource (and the contents of the file would be the * same even if it had a different description). * *
  • * * The second category identifies entries in a namespace. The format * is "gnunet://fs/sks/NAMESPACE/IDENTIFIER" where the namespace * should be given in HEX. Applications may allow using a nickname * for the namespace if the nickname is not ambiguous. The identifier * can be either an ASCII sequence or a HEX-encoding. If the * identifier is in ASCII but the format is ambiguous and could denote * a HEX-string a "/" is appended to indicate ASCII encoding. * *
  • * * The third category identifies ordinary searches. The format is * "gnunet://fs/ksk/KEYWORD[+KEYWORD]*". Using the "+" syntax * it is possible to encode searches with the boolean "AND" operator. * "+" is used since it indicates a commutative 'and' operation and * is unlikely to be used in a keyword by itself. * *
  • * * The last category identifies a datum on a specific machine. The * format is "gnunet://fs/loc/HEX1.HEX2.SIZE.PEER.SIG.EXPTIME". PEER is * the BinName of the public key of the peer storing the datum. The * signature (SIG) certifies that this peer has this content. * HEX1, HEX2 and SIZE correspond to a 'chk' URI. * *
* * The encoding for hexadecimal values is defined in the hashing.c * module in the gnunetutil library and discussed there. *

*/ #include "platform.h" #include "gnunet_fs_service.h" #include "gnunet_signatures.h" #include "fs_api.h" #include #include #include #include #include /** * Get a unique key from a URI. This is for putting URIs * into HashMaps. The key may change between FS implementations. * * @param uri uri to convert to a unique key * @param key where to store the unique key */ void GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri, struct GNUNET_HashCode *key) { switch (uri->type) { case GNUNET_FS_URI_CHK: *key = uri->data.chk.chk.query; return; case GNUNET_FS_URI_SKS: GNUNET_CRYPTO_hash (uri->data.sks.identifier, strlen (uri->data.sks.identifier), key); break; case GNUNET_FS_URI_KSK: if (uri->data.ksk.keywordCount > 0) GNUNET_CRYPTO_hash (uri->data.ksk.keywords[0], strlen (uri->data.ksk.keywords[0]), key); break; case GNUNET_FS_URI_LOC: GNUNET_CRYPTO_hash (&uri->data.loc.fi, sizeof (struct FileIdentifier) + sizeof (struct GNUNET_PeerIdentity), key); break; default: memset (key, 0, sizeof (struct GNUNET_HashCode)); break; } } /** * Convert keyword URI to a human readable format * (i.e. the search query that was used in the first place) * * @param uri ksk uri to convert to a string * @return string with the keywords */ char * GNUNET_FS_uri_ksk_to_string_fancy (const struct GNUNET_FS_Uri *uri) { size_t n; char *ret; unsigned int i; const char *keyword; char **keywords; unsigned int keywordCount; if ((NULL == uri) || (GNUNET_FS_URI_KSK != uri->type)) { GNUNET_break (0); return NULL; } keywords = uri->data.ksk.keywords; keywordCount = uri->data.ksk.keywordCount; n = keywordCount + 1; for (i = 0; i < keywordCount; i++) { keyword = keywords[i]; n += strlen (keyword) - 1; if (NULL != strstr (&keyword[1], " ")) n += 2; if (keyword[0] == '+') n++; } ret = GNUNET_malloc (n); strcpy (ret, ""); for (i = 0; i < keywordCount; i++) { keyword = keywords[i]; if (NULL != strstr (&keyword[1], " ")) { strcat (ret, "\""); if (keyword[0] == '+') strcat (ret, keyword); else strcat (ret, &keyword[1]); strcat (ret, "\""); } else { if (keyword[0] == '+') strcat (ret, keyword); else strcat (ret, &keyword[1]); } strcat (ret, " "); } return ret; } /** * Given a keyword with %-encoding (and possibly quotes to protect * spaces), return a copy of the keyword without %-encoding and * without double-quotes (%22). Also, add a space at the beginning * if there is not a '+'. * * @param in string with %-encoding * @param emsg where to store the parser error message (if any) * @return decodded string with leading space (or preserved plus) */ static char * percent_decode_keyword (const char *in, char **emsg) { char *out; char *ret; unsigned int rpos; unsigned int wpos; unsigned int hx; out = GNUNET_strdup (in); rpos = 0; wpos = 0; while (out[rpos] != '\0') { if (out[rpos] == '%') { if (1 != SSCANF (&out[rpos + 1], "%2X", &hx)) { GNUNET_free (out); *emsg = GNUNET_strdup (_(/* xgettext:no-c-format */ "`%' must be followed by HEX number")); return NULL; } rpos += 3; if (hx == '"') continue; /* skip double quote */ out[wpos++] = (char) hx; } else { out[wpos++] = out[rpos++]; } } out[wpos] = '\0'; if (out[0] == '+') { ret = GNUNET_strdup (out); } else { /* need to prefix with space */ ret = GNUNET_malloc (strlen (out) + 2); strcpy (ret, " "); strcat (ret, out); } GNUNET_free (out); return ret; } #define GNUNET_FS_URI_KSK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_KSK_INFIX /** * Parse a KSK URI. * * @param s an uri string * @param emsg where to store the parser error message (if any) * @return NULL on error, otherwise the KSK URI */ static struct GNUNET_FS_Uri * uri_ksk_parse (const char *s, char **emsg) { struct GNUNET_FS_Uri *ret; char **keywords; unsigned int pos; int max; int iret; int i; size_t slen; char *dup; int saw_quote; GNUNET_assert (NULL != s); slen = strlen (s); pos = strlen (GNUNET_FS_URI_KSK_PREFIX); if ((slen <= pos) || (0 != strncmp (s, GNUNET_FS_URI_KSK_PREFIX, pos))) return NULL; /* not KSK URI */ if ((s[slen - 1] == '+') || (s[pos] == '+')) { *emsg = GNUNET_strdup (_("Malformed KSK URI (must not begin or end with `+')")); return NULL; } max = 1; saw_quote = 0; for (i = pos; i < slen; i++) { if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22"))) { saw_quote = (saw_quote + 1) % 2; i += 3; continue; } if ((s[i] == '+') && (saw_quote == 0)) { max++; if (s[i - 1] == '+') { *emsg = GNUNET_strdup (_("`++' not allowed in KSK URI")); return NULL; } } } if (saw_quote == 1) { *emsg = GNUNET_strdup (_("Quotes not balanced in KSK URI")); return NULL; } iret = max; dup = GNUNET_strdup (s); keywords = GNUNET_malloc (max * sizeof (char *)); for (i = slen - 1; i >= (int) pos; i--) { if ((s[i] == '%') && (&s[i] == strstr (&s[i], "%22"))) { saw_quote = (saw_quote + 1) % 2; i += 3; continue; } if ((dup[i] == '+') && (saw_quote == 0)) { keywords[--max] = percent_decode_keyword (&dup[i + 1], emsg); if (NULL == keywords[max]) goto CLEANUP; dup[i] = '\0'; } } keywords[--max] = percent_decode_keyword (&dup[pos], emsg); if (NULL == keywords[max]) goto CLEANUP; GNUNET_assert (max == 0); GNUNET_free (dup); ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_KSK; ret->data.ksk.keywordCount = iret; ret->data.ksk.keywords = keywords; return ret; CLEANUP: for (i = 0; i < max; i++) GNUNET_free_non_null (keywords[i]); GNUNET_free (keywords); GNUNET_free (dup); return NULL; } #define GNUNET_FS_URI_SKS_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_SKS_INFIX /** * Parse an SKS URI. * * @param s an uri string * @param emsg where to store the parser error message (if any) * @return NULL on error, SKS URI otherwise */ static struct GNUNET_FS_Uri * uri_sks_parse (const char *s, char **emsg) { struct GNUNET_FS_Uri *ret; struct GNUNET_CRYPTO_EcdsaPublicKey ns; size_t pos; char *end; GNUNET_assert (s != NULL); pos = strlen (GNUNET_FS_URI_SKS_PREFIX); if ((strlen (s) <= pos) || (0 != strncmp (s, GNUNET_FS_URI_SKS_PREFIX, pos))) return NULL; /* not an SKS URI */ end = strchr (&s[pos], '/'); if ( (NULL == end) || (GNUNET_OK != GNUNET_STRINGS_string_to_data (&s[pos], end - &s[pos], &ns, sizeof (ns))) ) { *emsg = GNUNET_strdup (_("Malformed SKS URI")); return NULL; /* malformed */ } end++; /* skip over '/' */ ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_SKS; ret->data.sks.ns = ns; ret->data.sks.identifier = GNUNET_strdup (end); return ret; } #define GNUNET_FS_URI_CHK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX /** * Parse a CHK URI. * * @param s an uri string * @param emsg where to store the parser error message (if any) * @return NULL on error, CHK URI otherwise */ static struct GNUNET_FS_Uri * uri_chk_parse (const char *s, char **emsg) { struct GNUNET_FS_Uri *ret; struct FileIdentifier fi; unsigned int pos; unsigned long long flen; size_t slen; char h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]; char h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]; if (NULL == s) return NULL; GNUNET_assert (s != NULL); slen = strlen (s); pos = strlen (GNUNET_FS_URI_CHK_PREFIX); if ((slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || (0 != strncmp (s, GNUNET_FS_URI_CHK_PREFIX, pos))) return NULL; /* not a CHK URI */ if ((s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') || (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.')) { *emsg = GNUNET_strdup (_("Malformed CHK URI")); return NULL; } memcpy (h1, &s[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0'; memcpy (h2, &s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0'; if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1, &fi.chk.key)) || (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h2, &fi.chk.query)) || (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2], "%llu", &flen))) { *emsg = GNUNET_strdup (_("Malformed CHK URI")); return NULL; } fi.file_length = GNUNET_htonll (flen); ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_CHK; ret->data.chk = fi; return ret; } GNUNET_NETWORK_STRUCT_BEGIN /** * Structure that defines how the contents of a location URI must be * assembled in memory to create or verify the signature of a location * URI. */ struct LocUriAssembly { /** * What is being signed (rest of this struct). */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Expiration time of the offer. */ struct GNUNET_TIME_AbsoluteNBO exptime; /** * File being offered. */ struct FileIdentifier fi; /** * Peer offering the file. */ struct GNUNET_PeerIdentity peer; }; GNUNET_NETWORK_STRUCT_END #define GNUNET_FS_URI_LOC_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX #define SIGNATURE_ASCII_LENGTH 103 /** * Parse a LOC URI. * Also verifies validity of the location URI. * * @param s an uri string * @param emsg where to store the parser error message (if any) * @return NULL on error, valid LOC URI otherwise */ static struct GNUNET_FS_Uri * uri_loc_parse (const char *s, char **emsg) { struct GNUNET_FS_Uri *uri; char h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]; char h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)]; unsigned int pos; unsigned int npos; unsigned long long exptime; unsigned long long flen; struct GNUNET_TIME_Absolute et; struct GNUNET_CRYPTO_EddsaSignature sig; struct LocUriAssembly ass; size_t slen; slen = strlen (s); pos = strlen (GNUNET_FS_URI_LOC_PREFIX); if ((slen < pos + 2 * sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1) || (0 != strncmp (s, GNUNET_FS_URI_LOC_PREFIX, pos))) return NULL; /* not an SKS URI */ if ((s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] != '.') || (s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2 - 1] != '.')) { *emsg = GNUNET_strdup (_("SKS URI malformed")); return NULL; } memcpy (h1, &s[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); h1[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0'; memcpy (h2, &s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); h2[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0'; if ((GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h1, &ass.fi.chk.key)) || (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (h2, &ass.fi.chk.query)) || (1 != SSCANF (&s[pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2], "%llu", &flen))) { *emsg = GNUNET_strdup (_("LOC URI malformed")); return NULL; } ass.fi.file_length = GNUNET_htonll (flen); npos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) * 2; while ((s[npos] != '\0') && (s[npos] != '.')) npos++; if (s[npos] == '\0') { *emsg = GNUNET_strdup (_("LOC URI malformed")); goto ERR; } npos++; if ( (strlen (&s[npos]) <= GNUNET_CRYPTO_PKEY_ASCII_LENGTH + 1) || ('.' != s[npos+GNUNET_CRYPTO_PKEY_ASCII_LENGTH]) ) { *emsg = GNUNET_strdup (_("LOC URI malformed (could not decode public key)")); } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (&s[npos], GNUNET_CRYPTO_PKEY_ASCII_LENGTH, &ass.peer.public_key)) { *emsg = GNUNET_strdup (_("LOC URI malformed (could not decode public key)")); goto ERR; } npos += GNUNET_CRYPTO_PKEY_ASCII_LENGTH; if (s[npos++] != '.') { *emsg = GNUNET_strdup (_("SKS URI malformed (could not find signature)")); goto ERR; } if ( (strlen (&s[npos]) <= SIGNATURE_ASCII_LENGTH + 1) || ('.' != s[npos + SIGNATURE_ASCII_LENGTH]) ) { *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode signature)")); goto ERR; } if (GNUNET_OK != GNUNET_STRINGS_string_to_data (&s[npos], SIGNATURE_ASCII_LENGTH, &sig, sizeof (struct GNUNET_CRYPTO_EddsaSignature))) { *emsg = GNUNET_strdup (_("SKS URI malformed (could not decode signature)")); goto ERR; } npos += SIGNATURE_ASCII_LENGTH; if (s[npos++] != '.') { *emsg = GNUNET_strdup (_("SKS URI malformed")); goto ERR; } if (1 != SSCANF (&s[npos], "%llu", &exptime)) { *emsg = GNUNET_strdup (_("SKS URI malformed (could not parse expiration time)")); goto ERR; } ass.purpose.size = htonl (sizeof (struct LocUriAssembly)); ass.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT); et.abs_value_us = exptime * 1000LL * 1000LL; ass.exptime = GNUNET_TIME_absolute_hton (et); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT, &ass.purpose, &sig, &ass.peer.public_key)) { *emsg = GNUNET_strdup (_("SKS URI malformed (signature failed validation)")); goto ERR; } uri = GNUNET_new (struct GNUNET_FS_Uri); uri->type = GNUNET_FS_URI_LOC; uri->data.loc.fi = ass.fi; uri->data.loc.peer = ass.peer; uri->data.loc.expirationTime = et; uri->data.loc.contentSignature = sig; return uri; ERR: return NULL; } /** * Convert a UTF-8 String to a URI. * * @param uri string to parse * @param emsg where to store the parser error message (if any) * @return NULL on error */ struct GNUNET_FS_Uri * GNUNET_FS_uri_parse (const char *uri, char **emsg) { struct GNUNET_FS_Uri *ret; char *msg; if (NULL == emsg) emsg = &msg; *emsg = NULL; if ((NULL != (ret = uri_chk_parse (uri, emsg))) || (NULL != (ret = uri_ksk_parse (uri, emsg))) || (NULL != (ret = uri_sks_parse (uri, emsg))) || (NULL != (ret = uri_loc_parse (uri, emsg)))) return ret; if (NULL == *emsg) *emsg = GNUNET_strdup (_("Unrecognized URI type")); if (emsg == &msg) GNUNET_free (msg); return NULL; } /** * Free URI. * * @param uri uri to free */ void GNUNET_FS_uri_destroy (struct GNUNET_FS_Uri *uri) { unsigned int i; switch (uri->type) { case GNUNET_FS_URI_KSK: for (i = 0; i < uri->data.ksk.keywordCount; i++) GNUNET_free (uri->data.ksk.keywords[i]); GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount, 0); break; case GNUNET_FS_URI_SKS: GNUNET_free (uri->data.sks.identifier); break; case GNUNET_FS_URI_LOC: break; default: /* do nothing */ break; } GNUNET_free (uri); } /** * How many keywords are ANDed in this keyword URI? * * @param uri ksk uri to get the number of keywords from * @return 0 if this is not a keyword URI */ unsigned int GNUNET_FS_uri_ksk_get_keyword_count (const struct GNUNET_FS_Uri *uri) { if (uri->type != GNUNET_FS_URI_KSK) return 0; return uri->data.ksk.keywordCount; } /** * Iterate over all keywords in this keyword URI. * * @param uri ksk uri to get the keywords from * @param iterator function to call on each keyword * @param iterator_cls closure for iterator * @return -1 if this is not a keyword URI, otherwise number of * keywords iterated over until iterator aborted */ int GNUNET_FS_uri_ksk_get_keywords (const struct GNUNET_FS_Uri *uri, GNUNET_FS_KeywordIterator iterator, void *iterator_cls) { unsigned int i; char *keyword; if (uri->type != GNUNET_FS_URI_KSK) return -1; if (NULL == iterator) return uri->data.ksk.keywordCount; for (i = 0; i < uri->data.ksk.keywordCount; i++) { keyword = uri->data.ksk.keywords[i]; /* first character of keyword indicates * if it is mandatory or not */ if (GNUNET_OK != iterator (iterator_cls, &keyword[1], keyword[0] == '+')) return i; } return i; } /** * Add the given keyword to the set of keywords represented by the URI. * Does nothing if the keyword is already present. * * @param uri ksk uri to modify * @param keyword keyword to add * @param is_mandatory is this keyword mandatory? */ void GNUNET_FS_uri_ksk_add_keyword (struct GNUNET_FS_Uri *uri, const char *keyword, int is_mandatory) { unsigned int i; const char *old; char *n; GNUNET_assert (uri->type == GNUNET_FS_URI_KSK); for (i = 0; i < uri->data.ksk.keywordCount; i++) { old = uri->data.ksk.keywords[i]; if (0 == strcmp (&old[1], keyword)) return; } GNUNET_asprintf (&n, is_mandatory ? "+%s" : " %s", keyword); GNUNET_array_append (uri->data.ksk.keywords, uri->data.ksk.keywordCount, n); } /** * Remove the given keyword from the set of keywords represented by the URI. * Does nothing if the keyword is not present. * * @param uri ksk uri to modify * @param keyword keyword to add */ void GNUNET_FS_uri_ksk_remove_keyword (struct GNUNET_FS_Uri *uri, const char *keyword) { unsigned int i; char *old; GNUNET_assert (uri->type == GNUNET_FS_URI_KSK); for (i = 0; i < uri->data.ksk.keywordCount; i++) { old = uri->data.ksk.keywords[i]; if (0 == strcmp (&old[1], keyword)) { uri->data.ksk.keywords[i] = uri->data.ksk.keywords[uri->data.ksk.keywordCount - 1]; GNUNET_array_grow (uri->data.ksk.keywords, uri->data.ksk.keywordCount, uri->data.ksk.keywordCount - 1); GNUNET_free (old); return; } } } /** * Obtain the identity of the peer offering the data * * @param uri the location URI to inspect * @param peer where to store the identify of the peer (presumably) offering the content * @return #GNUNET_SYSERR if this is not a location URI, otherwise #GNUNET_OK */ int GNUNET_FS_uri_loc_get_peer_identity (const struct GNUNET_FS_Uri *uri, struct GNUNET_PeerIdentity *peer) { if (uri->type != GNUNET_FS_URI_LOC) return GNUNET_SYSERR; *peer = uri->data.loc.peer; return GNUNET_OK; } /** * Obtain the expiration of the LOC URI. * * @param uri location URI to get the expiration from * @return expiration time of the URI */ struct GNUNET_TIME_Absolute GNUNET_FS_uri_loc_get_expiration (const struct GNUNET_FS_Uri *uri) { GNUNET_assert (uri->type == GNUNET_FS_URI_LOC); return uri->data.loc.expirationTime; } /** * Obtain the URI of the content itself. * * @param uri location URI to get the content URI from * @return NULL if argument is not a location URI */ struct GNUNET_FS_Uri * GNUNET_FS_uri_loc_get_uri (const struct GNUNET_FS_Uri *uri) { struct GNUNET_FS_Uri *ret; if (uri->type != GNUNET_FS_URI_LOC) return NULL; ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_CHK; ret->data.chk = uri->data.loc.fi; return ret; } /** * Construct a location URI (this peer will be used for the location). * * @param baseUri content offered by the sender * @param cfg configuration information (used to find our hostkey) * @param expiration_time how long will the content be offered? * @return the location URI, NULL on error */ struct GNUNET_FS_Uri * GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TIME_Absolute expiration_time) { struct GNUNET_FS_Uri *uri; struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; struct GNUNET_CRYPTO_EddsaPublicKey my_public_key; char *keyfile; struct LocUriAssembly ass; struct GNUNET_TIME_Absolute et; if (baseUri->type != GNUNET_FS_URI_CHK) return NULL; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &keyfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Lacking key configuration settings.\n")); return NULL; } if (NULL == (my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not access hostkey file `%s'.\n"), keyfile); GNUNET_free (keyfile); return NULL; } GNUNET_free (keyfile); /* we round expiration time to full seconds for SKS URIs */ et.abs_value_us = (expiration_time.abs_value_us / 1000000LL) * 1000000LL; GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_public_key); ass.purpose.size = htonl (sizeof (struct LocUriAssembly)); ass.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT); ass.exptime = GNUNET_TIME_absolute_hton (et); ass.fi = baseUri->data.chk; ass.peer.public_key = my_public_key; uri = GNUNET_new (struct GNUNET_FS_Uri); uri->type = GNUNET_FS_URI_LOC; uri->data.loc.fi = baseUri->data.chk; uri->data.loc.expirationTime = et; uri->data.loc.peer.public_key = my_public_key; GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_private_key, &ass.purpose, &uri->data.loc.contentSignature)); GNUNET_free (my_private_key); return uri; } /** * Create an SKS URI from a namespace ID and an identifier. * * @param ns namespace ID * @param id identifier * @return an FS URI for the given namespace and identifier */ struct GNUNET_FS_Uri * GNUNET_FS_uri_sks_create (const struct GNUNET_CRYPTO_EcdsaPublicKey *ns, const char *id) { struct GNUNET_FS_Uri *ns_uri; ns_uri = GNUNET_new (struct GNUNET_FS_Uri); ns_uri->type = GNUNET_FS_URI_SKS; ns_uri->data.sks.ns = *ns; ns_uri->data.sks.identifier = GNUNET_strdup (id); return ns_uri; } /** * Merge the sets of keywords from two KSK URIs. * (useful for merging the canonicalized keywords with * the original keywords for sharing). * * @param u1 first uri * @param u2 second uri * @return merged URI, NULL on error */ struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_merge (const struct GNUNET_FS_Uri *u1, const struct GNUNET_FS_Uri *u2) { struct GNUNET_FS_Uri *ret; unsigned int kc; unsigned int i; unsigned int j; int found; const char *kp; char **kl; if ((u1 == NULL) && (u2 == NULL)) return NULL; if (u1 == NULL) return GNUNET_FS_uri_dup (u2); if (u2 == NULL) return GNUNET_FS_uri_dup (u1); if ((u1->type != GNUNET_FS_URI_KSK) || (u2->type != GNUNET_FS_URI_KSK)) { GNUNET_break (0); return NULL; } kc = u1->data.ksk.keywordCount; kl = GNUNET_malloc ((kc + u2->data.ksk.keywordCount) * sizeof (char *)); for (i = 0; i < u1->data.ksk.keywordCount; i++) kl[i] = GNUNET_strdup (u1->data.ksk.keywords[i]); for (i = 0; i < u2->data.ksk.keywordCount; i++) { kp = u2->data.ksk.keywords[i]; found = 0; for (j = 0; j < u1->data.ksk.keywordCount; j++) if (0 == strcmp (kp + 1, kl[j] + 1)) { found = 1; if (kp[0] == '+') kl[j][0] = '+'; break; } if (0 == found) kl[kc++] = GNUNET_strdup (kp); } ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_KSK; ret->data.ksk.keywordCount = kc; ret->data.ksk.keywords = kl; return ret; } /** * Duplicate URI. * * @param uri the URI to duplicate * @return copy of the URI */ struct GNUNET_FS_Uri * GNUNET_FS_uri_dup (const struct GNUNET_FS_Uri *uri) { struct GNUNET_FS_Uri *ret; unsigned int i; if (uri == NULL) return NULL; ret = GNUNET_new (struct GNUNET_FS_Uri); memcpy (ret, uri, sizeof (struct GNUNET_FS_Uri)); switch (ret->type) { case GNUNET_FS_URI_KSK: if (ret->data.ksk.keywordCount >= GNUNET_MAX_MALLOC_CHECKED / sizeof (char *)) { GNUNET_break (0); GNUNET_free (ret); return NULL; } if (ret->data.ksk.keywordCount > 0) { ret->data.ksk.keywords = GNUNET_malloc (ret->data.ksk.keywordCount * sizeof (char *)); for (i = 0; i < ret->data.ksk.keywordCount; i++) ret->data.ksk.keywords[i] = GNUNET_strdup (uri->data.ksk.keywords[i]); } else ret->data.ksk.keywords = NULL; /* just to be sure */ break; case GNUNET_FS_URI_SKS: ret->data.sks.identifier = GNUNET_strdup (uri->data.sks.identifier); break; case GNUNET_FS_URI_LOC: break; default: break; } return ret; } /** * Create an FS URI from a single user-supplied string of keywords. * The string is broken up at spaces into individual keywords. * Keywords that start with "+" are mandatory. Double-quotes can * be used to prevent breaking up strings at spaces (and also * to specify non-mandatory keywords starting with "+"). * * Keywords must contain a balanced number of double quotes and * double quotes can not be used in the actual keywords (for * example, the string '""foo bar""' will be turned into two * "OR"ed keywords 'foo' and 'bar', not into '"foo bar"'. * * @param keywords the keyword string * @param emsg where to store an error message * @return an FS URI for the given keywords, NULL * if keywords is not legal (i.e. empty). */ struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create (const char *keywords, char **emsg) { char **keywordarr; unsigned int num_Words; int inWord; char *pos; struct GNUNET_FS_Uri *uri; char *searchString; int saw_quote; if (keywords == NULL) { *emsg = GNUNET_strdup (_("No keywords specified!\n")); GNUNET_break (0); return NULL; } searchString = GNUNET_strdup (keywords); num_Words = 0; inWord = 0; saw_quote = 0; pos = searchString; while ('\0' != *pos) { if ((saw_quote == 0) && (isspace ((unsigned char) *pos))) { inWord = 0; } else if (0 == inWord) { inWord = 1; ++num_Words; } if ('"' == *pos) saw_quote = (saw_quote + 1) % 2; pos++; } if (num_Words == 0) { GNUNET_free (searchString); *emsg = GNUNET_strdup (_("No keywords specified!\n")); return NULL; } if (saw_quote != 0) { GNUNET_free (searchString); *emsg = GNUNET_strdup (_("Number of double-quotes not balanced!\n")); return NULL; } keywordarr = GNUNET_malloc (num_Words * sizeof (char *)); num_Words = 0; inWord = 0; pos = searchString; while ('\0' != *pos) { if ((saw_quote == 0) && (isspace ((unsigned char) *pos))) { inWord = 0; *pos = '\0'; } else if (0 == inWord) { keywordarr[num_Words] = pos; inWord = 1; ++num_Words; } if ('"' == *pos) saw_quote = (saw_quote + 1) % 2; pos++; } uri = GNUNET_FS_uri_ksk_create_from_args (num_Words, (const char **) keywordarr); GNUNET_free (keywordarr); GNUNET_free (searchString); return uri; } /** * Create an FS URI from a user-supplied command line of keywords. * Arguments should start with "+" to indicate mandatory * keywords. * * @param argc number of keywords * @param argv keywords (double quotes are not required for * keywords containing spaces; however, double * quotes are required for keywords starting with * "+"); there is no mechanism for having double * quotes in the actual keywords (if the user * did specifically specify double quotes, the * caller should convert each double quote * into two single quotes). * @return an FS URI for the given keywords, NULL * if keywords is not legal (i.e. empty). */ struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create_from_args (unsigned int argc, const char **argv) { unsigned int i; struct GNUNET_FS_Uri *uri; const char *keyword; char *val; const char *r; char *w; char *emsg; if (argc == 0) return NULL; /* allow URI to be given as one and only keyword and * handle accordingly */ emsg = NULL; if ((argc == 1) && (strlen (argv[0]) > strlen (GNUNET_FS_URI_PREFIX)) && (0 == strncmp (argv[0], GNUNET_FS_URI_PREFIX, strlen (GNUNET_FS_URI_PREFIX))) && (NULL != (uri = GNUNET_FS_uri_parse (argv[0], &emsg)))) return uri; GNUNET_free_non_null (emsg); uri = GNUNET_new (struct GNUNET_FS_Uri); uri->type = GNUNET_FS_URI_KSK; uri->data.ksk.keywordCount = argc; uri->data.ksk.keywords = GNUNET_malloc (argc * sizeof (char *)); for (i = 0; i < argc; i++) { keyword = argv[i]; if (keyword[0] == '+') val = GNUNET_strdup (keyword); else GNUNET_asprintf (&val, " %s", keyword); r = val; w = val; while ('\0' != *r) { if ('"' == *r) r++; else *(w++) = *(r++); } *w = '\0'; uri->data.ksk.keywords[i] = val; } return uri; } /** * Test if two URIs are equal. * * @param u1 one of the URIs * @param u2 the other URI * @return GNUNET_YES if the URIs are equal */ int GNUNET_FS_uri_test_equal (const struct GNUNET_FS_Uri *u1, const struct GNUNET_FS_Uri *u2) { int ret; unsigned int i; unsigned int j; GNUNET_assert (u1 != NULL); GNUNET_assert (u2 != NULL); if (u1->type != u2->type) return GNUNET_NO; switch (u1->type) { case GNUNET_FS_URI_CHK: if (0 == memcmp (&u1->data.chk, &u2->data.chk, sizeof (struct FileIdentifier))) return GNUNET_YES; return GNUNET_NO; case GNUNET_FS_URI_SKS: if ((0 == memcmp (&u1->data.sks.ns, &u2->data.sks.ns, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) && (0 == strcmp (u1->data.sks.identifier, u2->data.sks.identifier))) return GNUNET_YES; return GNUNET_NO; case GNUNET_FS_URI_KSK: if (u1->data.ksk.keywordCount != u2->data.ksk.keywordCount) return GNUNET_NO; for (i = 0; i < u1->data.ksk.keywordCount; i++) { ret = GNUNET_NO; for (j = 0; j < u2->data.ksk.keywordCount; j++) { if (0 == strcmp (u1->data.ksk.keywords[i], u2->data.ksk.keywords[j])) { ret = GNUNET_YES; break; } } if (ret == GNUNET_NO) return GNUNET_NO; } return GNUNET_YES; case GNUNET_FS_URI_LOC: if (memcmp (&u1->data.loc, &u2->data.loc, sizeof (struct FileIdentifier) + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) + sizeof (struct GNUNET_TIME_Absolute) + sizeof (unsigned short) + sizeof (unsigned short)) != 0) return GNUNET_NO; return GNUNET_YES; default: return GNUNET_NO; } } /** * Is this a namespace URI? * * @param uri the uri to check * @return GNUNET_YES if this is an SKS uri */ int GNUNET_FS_uri_test_sks (const struct GNUNET_FS_Uri *uri) { return uri->type == GNUNET_FS_URI_SKS; } /** * Get the ID of a namespace from the given * namespace URI. * * @param uri the uri to get the namespace ID from * @param pseudonym where to store the ID of the namespace * @return GNUNET_OK on success */ int GNUNET_FS_uri_sks_get_namespace (const struct GNUNET_FS_Uri *uri, struct GNUNET_CRYPTO_EcdsaPublicKey *pseudonym) { if (!GNUNET_FS_uri_test_sks (uri)) { GNUNET_break (0); return GNUNET_SYSERR; } *pseudonym = uri->data.sks.ns; return GNUNET_OK; } /** * Get the content identifier of an SKS URI. * * @param uri the sks uri * @return NULL on error (not a valid SKS URI) */ char * GNUNET_FS_uri_sks_get_content_id (const struct GNUNET_FS_Uri *uri) { if (!GNUNET_FS_uri_test_sks (uri)) { GNUNET_break (0); return NULL; } return GNUNET_strdup (uri->data.sks.identifier); } /** * Is this a keyword URI? * * @param uri the uri * @return #GNUNET_YES if this is a KSK uri */ int GNUNET_FS_uri_test_ksk (const struct GNUNET_FS_Uri *uri) { #if EXTRA_CHECKS unsigned int i; if (uri->type == GNUNET_FS_URI_KSK) { for (i=0;i < uri->data.ksk.keywordCount; i++) GNUNET_assert (uri->data.ksk.keywords[i] != NULL); } #endif return uri->type == GNUNET_FS_URI_KSK; } /** * Is this a file (or directory) URI? * * @param uri the uri to check * @return GNUNET_YES if this is a CHK uri */ int GNUNET_FS_uri_test_chk (const struct GNUNET_FS_Uri *uri) { return uri->type == GNUNET_FS_URI_CHK; } /** * What is the size of the file that this URI * refers to? * * @param uri the CHK URI to inspect * @return size of the file as specified in the CHK URI */ uint64_t GNUNET_FS_uri_chk_get_file_size (const struct GNUNET_FS_Uri * uri) { switch (uri->type) { case GNUNET_FS_URI_CHK: return GNUNET_ntohll (uri->data.chk.file_length); case GNUNET_FS_URI_LOC: return GNUNET_ntohll (uri->data.loc.fi.file_length); default: GNUNET_assert (0); } return 0; /* unreachable */ } /** * Is this a location URI? * * @param uri the uri to check * @return GNUNET_YES if this is a LOC uri */ int GNUNET_FS_uri_test_loc (const struct GNUNET_FS_Uri *uri) { return uri->type == GNUNET_FS_URI_LOC; } /** * Add a keyword as non-mandatory (with ' '-prefix) to the * given keyword list at offset 'index'. The array is * guaranteed to be long enough. * * @param s keyword to add * @param array array to add the keyword to * @param index offset where to add the keyword */ static void insert_non_mandatory_keyword (const char *s, char **array, int index) { char *nkword; GNUNET_asprintf (&nkword, " %s", /* space to mark as 'non mandatory' */ s); array[index] = nkword; } /** * Test if the given keyword @a s is already present in the * given array, ignoring the '+'-mandatory prefix in the array. * * @param s keyword to test * @param array keywords to test against, with ' ' or '+' prefix to ignore * @param array_length length of the @a array * @return #GNUNET_YES if the keyword exists, #GNUNET_NO if not */ static int find_duplicate (const char *s, const char **array, int array_length) { int j; for (j = array_length - 1; j >= 0; j--) if (0 == strcmp (&array[j][1], s)) return GNUNET_YES; return GNUNET_NO; } /** * FIXME: comment */ static char * normalize_metadata (enum EXTRACTOR_MetaFormat format, const char *data, size_t data_len) { uint8_t *free_str = NULL; uint8_t *str_to_normalize = (uint8_t *) data; uint8_t *normalized; size_t r_len; if (str_to_normalize == NULL) return NULL; /* Don't trust libextractor */ if (format == EXTRACTOR_METAFORMAT_UTF8) { free_str = (uint8_t *) u8_check ((const uint8_t *) data, data_len); if (free_str == NULL) free_str = NULL; else format = EXTRACTOR_METAFORMAT_C_STRING; } if (format == EXTRACTOR_METAFORMAT_C_STRING) { free_str = u8_strconv_from_encoding (data, locale_charset (), iconveh_escape_sequence); if (free_str == NULL) return NULL; } normalized = u8_tolower (str_to_normalize, strlen ((char *) str_to_normalize), NULL, UNINORM_NFD, NULL, &r_len); /* free_str is allocated by libunistring internally, use free() */ if (free_str != NULL) free (free_str); if (normalized != NULL) { /* u8_tolower allocates a non-NULL-terminated string! */ free_str = GNUNET_malloc (r_len + 1); memcpy (free_str, normalized, r_len); free_str[r_len] = '\0'; free (normalized); normalized = free_str; } return (char *) normalized; } /** * Counts the number of UTF-8 characters (not bytes) in the string, * returns that count. */ static size_t u8_strcount (const uint8_t *s) { size_t count; ucs4_t c; GNUNET_assert (s != NULL); if (s[0] == 0) return 0; for (count = 0; s != NULL; count++) s = u8_next (&c, s); return count - 1; } /** * Break the filename up by matching [], () and {} pairs to make * keywords. In case of nesting parentheses only the inner pair counts. * You can't escape parentheses to scan something like "[blah\{foo]" to * make a "blah{foo" keyword, this function is only a heuristic! * * @param s string to break down. * @param array array to fill with enclosed tokens. If NULL, then tokens * are only counted. * @param index index at which to start filling the array (entries prior * to it are used to check for duplicates). ignored if array == NULL. * @return number of tokens counted (including duplicates), or number of * tokens extracted (excluding duplicates). 0 if there are no * matching parens in the string (when counting), or when all tokens * were duplicates (when extracting). */ static int get_keywords_from_parens (const char *s, char **array, int index) { int count = 0; char *open_paren; char *close_paren; char *ss; char tmp; if (NULL == s) return 0; ss = GNUNET_strdup (s); open_paren = ss - 1; while (NULL != (open_paren = strpbrk (open_paren + 1, "[{("))) { int match = 0; close_paren = strpbrk (open_paren + 1, "]})"); if (NULL == close_paren) continue; switch (open_paren[0]) { case '[': if (']' == close_paren[0]) match = 1; break; case '{': if ('}' == close_paren[0]) match = 1; break; case '(': if (')' == close_paren[0]) match = 1; break; default: break; } if (match && (close_paren - open_paren > 1)) { tmp = close_paren[0]; close_paren[0] = '\0'; /* Keywords must be at least 3 characters long */ if (u8_strcount ((const uint8_t *) &open_paren[1]) <= 2) { close_paren[0] = tmp; continue; } if (NULL != array) { char *normalized; if (GNUNET_NO == find_duplicate ((const char *) &open_paren[1], (const char **) array, index + count)) { insert_non_mandatory_keyword ((const char *) &open_paren[1], array, index + count); count++; } normalized = normalize_metadata (EXTRACTOR_METAFORMAT_UTF8, &open_paren[1], close_paren - &open_paren[1]); if (normalized != NULL) { if (GNUNET_NO == find_duplicate ((const char *) normalized, (const char **) array, index + count)) { insert_non_mandatory_keyword ((const char *) normalized, array, index + count); count++; } GNUNET_free (normalized); } } else count++; close_paren[0] = tmp; } } GNUNET_free (ss); return count; } /** * Where to break up keywords */ #define TOKENS "_. /-!?#&+@\"\'\\;:,()[]{}$<>|" /** * Break the filename up by TOKENS to make * keywords. * * @param s string to break down. * @param array array to fill with tokens. If NULL, then tokens are only * counted. * @param index index at which to start filling the array (entries prior * to it are used to check for duplicates). ignored if array == NULL. * @return number of tokens (>1) counted (including duplicates), or number of * tokens extracted (excluding duplicates). 0 if there are no * separators in the string (when counting), or when all tokens were * duplicates (when extracting). */ static int get_keywords_from_tokens (const char *s, char **array, int index) { char *p; char *ss; int seps = 0; ss = GNUNET_strdup (s); for (p = strtok (ss, TOKENS); p != NULL; p = strtok (NULL, TOKENS)) { /* Keywords must be at least 3 characters long */ if (u8_strcount ((const uint8_t *) p) <= 2) continue; if (NULL != array) { char *normalized; if (GNUNET_NO == find_duplicate (p, (const char **) array, index + seps)) { insert_non_mandatory_keyword (p, array, index + seps); seps++; } normalized = normalize_metadata (EXTRACTOR_METAFORMAT_UTF8, p, strlen (p)); if (normalized != NULL) { if (GNUNET_NO == find_duplicate ((const char *) normalized, (const char **) array, index + seps)) { insert_non_mandatory_keyword ((const char *) normalized, array, index + seps); seps++; } GNUNET_free (normalized); } } else seps++; } GNUNET_free (ss); return seps; } #undef TOKENS /** * Function called on each value in the meta data. * Adds it to the URI. * * @param cls URI to update * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_len number of bytes in @a data * @return 0 (always) */ static int gather_uri_data (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len) { struct GNUNET_FS_Uri *uri = cls; char *normalized_data; const char *sep; if ((format != EXTRACTOR_METAFORMAT_UTF8) && (format != EXTRACTOR_METAFORMAT_C_STRING)) return 0; /* Keywords must be at least 3 characters long * If given non-utf8 string it will, most likely, find it to be invalid, * and will return the length of its valid part, skipping the keyword. * If it does - fix the extractor, not this check! */ if (u8_strcount ((const uint8_t *) data) <= 2) return 0; if ( (EXTRACTOR_METATYPE_MIMETYPE == type) && (NULL != (sep = memchr (data, '/', data_len))) && (sep != data) ) { char *xtra; GNUNET_asprintf (&xtra, "mimetype:%.*s", (int) (sep - data), data); if (! find_duplicate (xtra, (const char **) uri->data.ksk.keywords, uri->data.ksk.keywordCount)) { insert_non_mandatory_keyword (xtra, uri->data.ksk.keywords, uri->data.ksk.keywordCount); uri->data.ksk.keywordCount++; } GNUNET_free (xtra); } normalized_data = normalize_metadata (format, data, data_len); if (! find_duplicate (data, (const char **) uri->data.ksk.keywords, uri->data.ksk.keywordCount)) { insert_non_mandatory_keyword (data, uri->data.ksk.keywords, uri->data.ksk.keywordCount); uri->data.ksk.keywordCount++; } if (NULL != normalized_data) { if (! find_duplicate (normalized_data, (const char **) uri->data.ksk.keywords, uri->data.ksk.keywordCount)) { insert_non_mandatory_keyword (normalized_data, uri->data.ksk.keywords, uri->data.ksk.keywordCount); uri->data.ksk.keywordCount++; } GNUNET_free (normalized_data); } return 0; } /** * Construct a keyword-URI from meta-data (take all entries * in the meta-data and construct one large keyword URI * that lists all keywords that can be found in the meta-data). * * @param md metadata to use * @return NULL on error, otherwise a KSK URI */ struct GNUNET_FS_Uri * GNUNET_FS_uri_ksk_create_from_meta_data (const struct GNUNET_CONTAINER_MetaData *md) { struct GNUNET_FS_Uri *ret; char *filename; char *full_name = NULL; char *ss; int ent; int tok_keywords = 0; int paren_keywords = 0; if (NULL == md) return NULL; ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_KSK; ent = GNUNET_CONTAINER_meta_data_iterate (md, NULL, NULL); if (ent > 0) { full_name = GNUNET_CONTAINER_meta_data_get_first_by_types (md, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, -1); if (NULL != full_name) { filename = full_name; while (NULL != (ss = strstr (filename, DIR_SEPARATOR_STR))) filename = ss + 1; tok_keywords = get_keywords_from_tokens (filename, NULL, 0); paren_keywords = get_keywords_from_parens (filename, NULL, 0); } /* x3 because there might be a normalized variant of every keyword, plus theoretically one more for mime... */ ret->data.ksk.keywords = GNUNET_malloc (sizeof (char *) * (ent + tok_keywords + paren_keywords) * 3); GNUNET_CONTAINER_meta_data_iterate (md, &gather_uri_data, ret); } if (tok_keywords > 0) ret->data.ksk.keywordCount += get_keywords_from_tokens (filename, ret->data.ksk.keywords, ret->data.ksk.keywordCount); if (paren_keywords > 0) ret->data.ksk.keywordCount += get_keywords_from_parens (filename, ret->data.ksk.keywords, ret->data.ksk.keywordCount); if (ent > 0) GNUNET_free_non_null (full_name); return ret; } /** * In URI-encoding, does the given character * need to be encoded using %-encoding? */ static int needs_percent (char c) { return (! ((isalnum ((unsigned char) c)) || (c == '-') || (c == '_') || (c == '.') || (c == '~'))); } /** * Convert a KSK URI to a string. * * @param uri the URI to convert * @return NULL on error (i.e. keywordCount == 0) */ static char * uri_ksk_to_string (const struct GNUNET_FS_Uri *uri) { char **keywords; unsigned int keywordCount; size_t n; char *ret; unsigned int i; unsigned int j; unsigned int wpos; size_t slen; const char *keyword; if (uri->type != GNUNET_FS_URI_KSK) return NULL; keywords = uri->data.ksk.keywords; keywordCount = uri->data.ksk.keywordCount; n = keywordCount + strlen (GNUNET_FS_URI_PREFIX) + strlen (GNUNET_FS_URI_KSK_INFIX) + 1; for (i = 0; i < keywordCount; i++) { keyword = keywords[i]; slen = strlen (keyword); n += slen; for (j = 0; j < slen; j++) { if ((j == 0) && (keyword[j] == ' ')) { n--; continue; /* skip leading space */ } if (needs_percent (keyword[j])) n += 2; /* will use %-encoding */ } } ret = GNUNET_malloc (n); strcpy (ret, GNUNET_FS_URI_PREFIX); strcat (ret, GNUNET_FS_URI_KSK_INFIX); wpos = strlen (ret); for (i = 0; i < keywordCount; i++) { keyword = keywords[i]; slen = strlen (keyword); for (j = 0; j < slen; j++) { if ((j == 0) && (keyword[j] == ' ')) continue; /* skip leading space */ if (needs_percent (keyword[j])) { sprintf (&ret[wpos], "%%%02X", (unsigned char) keyword[j]); wpos += 3; } else { ret[wpos++] = keyword[j]; } } if (i != keywordCount - 1) ret[wpos++] = '+'; } return ret; } /** * Convert SKS URI to a string. * * @param uri sks uri to convert * @return NULL on error */ static char * uri_sks_to_string (const struct GNUNET_FS_Uri *uri) { char *ret; char buf[1024]; if (GNUNET_FS_URI_SKS != uri->type) return NULL; ret = GNUNET_STRINGS_data_to_string (&uri->data.sks.ns, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), buf, sizeof (buf)); GNUNET_assert (NULL != ret); ret[0] = '\0'; GNUNET_asprintf (&ret, "%s%s%s/%s", GNUNET_FS_URI_PREFIX, GNUNET_FS_URI_SKS_INFIX, buf, uri->data.sks.identifier); return ret; } /** * Convert a CHK URI to a string. * * @param uri chk uri to convert * @return NULL on error */ static char * uri_chk_to_string (const struct GNUNET_FS_Uri *uri) { const struct FileIdentifier *fi; char *ret; struct GNUNET_CRYPTO_HashAsciiEncoded keyhash; struct GNUNET_CRYPTO_HashAsciiEncoded queryhash; if (uri->type != GNUNET_FS_URI_CHK) return NULL; fi = &uri->data.chk; GNUNET_CRYPTO_hash_to_enc (&fi->chk.key, &keyhash); GNUNET_CRYPTO_hash_to_enc (&fi->chk.query, &queryhash); GNUNET_asprintf (&ret, "%s%s%s.%s.%llu", GNUNET_FS_URI_PREFIX, GNUNET_FS_URI_CHK_INFIX, (const char *) &keyhash, (const char *) &queryhash, GNUNET_ntohll (fi->file_length)); return ret; } /** * Convert a LOC URI to a string. * * @param uri loc uri to convert * @return NULL on error */ static char * uri_loc_to_string (const struct GNUNET_FS_Uri *uri) { char *ret; struct GNUNET_CRYPTO_HashAsciiEncoded keyhash; struct GNUNET_CRYPTO_HashAsciiEncoded queryhash; char *peer_id; char peer_sig[SIGNATURE_ASCII_LENGTH + 1]; GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.key, &keyhash); GNUNET_CRYPTO_hash_to_enc (&uri->data.loc.fi.chk.query, &queryhash); peer_id = GNUNET_CRYPTO_eddsa_public_key_to_string (&uri->data.loc.peer.public_key); GNUNET_assert (NULL != GNUNET_STRINGS_data_to_string (&uri->data.loc.contentSignature, sizeof (struct GNUNET_CRYPTO_EddsaSignature), peer_sig, sizeof (peer_sig))); GNUNET_asprintf (&ret, "%s%s%s.%s.%llu.%s.%s.%llu", GNUNET_FS_URI_PREFIX, GNUNET_FS_URI_LOC_INFIX, (const char *) &keyhash, (const char *) &queryhash, (unsigned long long) GNUNET_ntohll (uri->data.loc. fi.file_length), peer_id, peer_sig, (unsigned long long) uri->data.loc.expirationTime.abs_value_us / 1000000LL); GNUNET_free (peer_id); return ret; } /** * Convert a URI to a UTF-8 String. * * @param uri uri to convert to a string * @return the UTF-8 string */ char * GNUNET_FS_uri_to_string (const struct GNUNET_FS_Uri *uri) { if (uri == NULL) { GNUNET_break (0); return NULL; } switch (uri->type) { case GNUNET_FS_URI_KSK: return uri_ksk_to_string (uri); case GNUNET_FS_URI_SKS: return uri_sks_to_string (uri); case GNUNET_FS_URI_CHK: return uri_chk_to_string (uri); case GNUNET_FS_URI_LOC: return uri_loc_to_string (uri); default: GNUNET_break (0); return NULL; } } /* end of fs_uri.c */ gnunet-0.10.1/src/fs/gnunet-service-fs_pe.h0000644000175000017500000000454312225777503015432 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_pe.h * @brief API to manage query plan * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_FS_PE_H #define GNUNET_SERVICE_FS_PE_H #include "gnunet-service-fs.h" /** * Create a new query plan entry. * * @param cp peer with the entry * @param pr request with the entry */ void GSF_plan_add_ (struct GSF_ConnectedPeer *cp, struct GSF_PendingRequest *pr); /** * Notify the plan about a peer being no longer available; * destroy all entries associated with this peer. * * @param cp connected peer */ void GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp); /** * Notify the plan about a request being done; * destroy all entries associated with this request. * * @param pr request that is done */ void GSF_plan_notify_request_done_ (struct GSF_PendingRequest *pr); /** * Get the last transmission attempt time for the request plan list * referenced by 'rpr_head', that was sent to 'sender' * * @param pr_head request plan reference list to check. * @param sender the peer that we've sent the request to. * @param result the timestamp to fill. * @return GNUNET_YES if 'result' was changed, GNUNET_NO otherwise. */ int GSF_request_plan_reference_get_last_transmission_ (struct GSF_PendingRequestPlanBijection *pr_head, struct GSF_ConnectedPeer *sender, struct GNUNET_TIME_Absolute *result); /** * Initialize plan subsystem. */ void GSF_plan_init (void); /** * Shutdown plan subsystem. */ void GSF_plan_done (void); #endif /* end of gnunet-service-fs_pe.h */ gnunet-0.10.1/src/fs/gnunet-download-manager.scm0000755000175000017500000003203211704771274016447 00000000000000#!/bin/sh exec guile -e main -s "$0" "$@" !# ;;; gnunet-download-manager -- Manage GNUnet downloads. ;;; Copyright (C) 2004 Ludovic Courtès ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License ;;; as published by the Free Software Foundation; either version 2 ;;; of the License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;;; Remember ongoing GNUnet downloads so as to be able to resume them ;;; later. Typical usage is to define the following alias in your ;;; favorite shell: ;;; ;;; alias gnunet-download='gnunet-download-manager.scm download' ;;; ;;; You may have a ~/.gnunet-download-manager.scm Scheme configuration ;;; file. In particular, if you would like to be notified of ;;; completed downloads, you may want to add the following line to ;;; your configuration file: ;;; ;;; (add-hook! *completed-download-hook* ;;; completed-download-notification-hook) ;;; ;;; This script works fine with GNU Guile 1.6.4, and doesn't run with ;;; Guile 1.4.x. ;;; ;;; Enjoy! ;;; Ludovic Courtès (use-modules (ice-9 format) (ice-9 optargs) (ice-9 regex) (ice-9 and-let-star) (ice-9 pretty-print) (ice-9 documentation)) ;; Overall user settings (define *debug?* #f) (define *rc-file* (string-append (getenv "HOME") "/.gnunet-download-manager.scm")) (define *status-directory* (string-append (getenv "HOME") "/" ".gnunet-download-manager")) (define *gnunet-download* "gnunet-download") ;; Helper macros (define-macro (gnunet-info fmt . args) `(format #t (string-append *program-name* ": " ,fmt "~%") ,@args)) (define-macro (gnunet-debug fmt . args) (if *debug?* (cons 'gnunet-info (cons fmt args)) #t)) (define-macro (gnunet-error fmt . args) `(and ,(cons 'gnunet-info (cons fmt args)) (exit 1))) (define (exception-string key args) "Describe an error, using the format from @var{args}, if available." (if (< (length args) 4) (format #f "Scheme exception: ~S" key) (string-append (if (string? (car args)) (string-append "In " (car args)) "Scheme exception") ": " (apply format `(#f ,(cadr args) ,@(caddr args)))))) ;; Regexps matching GNUnet URIs (define *uri-base* "([[:alnum:]]+)\.([[:alnum:]]+)\.([[:alnum:]]+)\.([0-9]+)") (define *uri-re* (make-regexp (string-append "^gnunet://afs/" *uri-base* "$") regexp/extended)) (define *uri-status-file-re* (make-regexp (string-append "^" *uri-base* "$") regexp/extended)) (define (uri-status-file-name directory uri) "Return the name of the status file for URI @var{uri}." (let ((match (regexp-exec *uri-re* uri))) (if (not match) (and (gnunet-info "~a: Invalid URI" uri) #f) (let ((start (match:start match 1)) (end (match:end match 4))) (string-append directory "/" (substring uri start end)))))) (define (uri-status directory uri) "Load the current status alist for URI @var{uri} from @var{directory}." (gnunet-debug "uri-status") (let ((filename (uri-status-file-name directory uri))) (catch 'system-error (lambda () (let* ((file (open-input-file filename)) (status (read file))) (begin (close-port file) status))) (lambda (key . args) (and (gnunet-debug (exception-string key args)) '()))))) (define (process-exists? pid) (false-if-exception (begin (kill pid 0) #t))) (define (fork-and-exec directory program . args) "Launch @var{program} and return its PID." (gnunet-debug "fork-and-exec: ~a ~a" program args) (let ((pid (primitive-fork))) (if (= 0 pid) (begin (if directory (chdir directory)) (apply execlp (cons program (cons program args)))) pid))) (define* (start-downloader downloader uri options #:key (directory #f)) "Start the GNUnet downloader for URI @var{uri} with options @var{options}. Return an alist describing the download status." (catch 'system-error (lambda () (let* ((pid (apply fork-and-exec `(,(if directory directory (getcwd)) ,downloader ,@options)))) (gnunet-info "Launched process ~a" pid) `((uri . ,uri) (working-directory . ,(if directory directory (getcwd))) (options . ,options) (pid . ,(getpid)) (downloader-pid . ,pid)))) (lambda (key . args) (gnunet-error (exception-string key args))))) (define (download-process-alive? uri-status) "Return true if the download whose status is that described by @var{uri-status} is still alive." (let ((pid (assoc-ref uri-status 'pid)) (downloader-pid (assoc-ref uri-status 'downloader-pid))) (and (process-exists? pid) (process-exists? downloader-pid)))) (define (start-file-download downloader status-dir uri options) "Dowload the file located at @var{uri}, with options @var{options} and return an updated status alist." (gnunet-debug "start-file-download") (let ((uri-status (uri-status status-dir uri))) (if (null? uri-status) (acons 'start-date (current-time) (start-downloader downloader uri options)) (if (download-process-alive? uri-status) (and (gnunet-info "~a already being downloaded by process ~a" uri (assoc-ref uri-status 'pid)) #f) (and (gnunet-info "Resuming download") (let ((start-date (assoc-ref uri-status 'start-date)) (dir (assoc-ref uri-status 'working-directory)) (options (assoc-ref uri-status 'options))) (acons 'start-date start-date (start-downloader downloader uri options #:directory dir)))))))) (define *completed-download-hook* (make-hook 1)) (define (download-file downloader status-dir uri options) "Start downloading file located at URI @var{uri}, with options @var{options}, resuming it if it's already started." (catch 'system-error (lambda () (and-let* ((status (start-file-download downloader status-dir uri options)) (pid (assoc-ref status 'downloader-pid)) (filename (uri-status-file-name status-dir uri)) (file (open-file filename "w"))) ;; Write down the status (pretty-print status file) (close-port file) ;; Wait for `gnunet-download' (gnunet-info "Waiting for process ~a" pid) (let* ((process-status (waitpid pid)) (exit-val (status:exit-val (cdr process-status))) (term-sig (status:term-sig (cdr process-status)))) ;; Terminate (delete-file filename) (gnunet-info "Download completed (PID ~a, exit code ~a)" pid exit-val) (let ((ret `((end-date . ,(current-time)) (exit-code . ,exit-val) (terminating-signal . ,term-sig) ,@status))) (run-hook *completed-download-hook* ret) ret)))) (lambda (key . args) (gnunet-error (exception-string key args))))) (define (uri-status-files directory) "Return the list of URI status files in @var{directory}." (catch 'system-error (lambda () (let ((dir (opendir directory))) (let loop ((filename (readdir dir)) (file-list '())) (if (eof-object? filename) file-list (if (regexp-exec *uri-status-file-re* filename) (loop (readdir dir) (cons filename file-list)) (loop (readdir dir) file-list)))))) (lambda (key . args) (gnunet-error (exception-string key args))))) (define (output-file-option option-list) "Return the output file specified in @var{option-list}, false if anavailable." (if (null? option-list) #f (let ((rest (cdr option-list)) (opt (car option-list))) (if (null? rest) #f (if (or (string=? opt "-o") (string=? opt "--output")) (car rest) (output-file-option rest)))))) (define (download-command . args) "Start downloading a file using the given `gnunet-download' arguments." (gnunet-debug "download-command") (let* ((argc (length args)) ;; FIXME: We're assuming the URI is the last argument (uri (car (list-tail args (- argc 1)))) (options args)) (download-file *gnunet-download* *status-directory* uri options))) (define (status-command . args) "Print status info about files being downloaded." (for-each (lambda (status) (format #t "~a: ~a~% ~a~% ~a~% ~a~%" (assoc-ref status 'uri) (if (download-process-alive? status) (string-append "running (PID " (number->string (assoc-ref status 'pid)) ")") "not running") (string-append "Started on " (strftime "%c" (localtime (assoc-ref status 'start-date)))) (string-append "Directory: " (assoc-ref status 'working-directory)) (string-append "Output file: " (or (output-file-option (assoc-ref status 'options)) "")))) (map (lambda (file) (uri-status *status-directory* (string-append "gnunet://afs/" file))) (uri-status-files *status-directory*)))) (define (resume-command . args) "Resume stopped downloads." (for-each (lambda (status) (if (not (download-process-alive? status)) (if (= 0 (primitive-fork)) (let* ((ret (download-file *gnunet-download* *status-directory* (assoc-ref status 'uri) (assoc-ref status 'options))) (code (assoc-ref ret 'exit-code))) (exit code))))) (map (lambda (file) (uri-status *status-directory* (string-append "gnunet://afs/" file))) (uri-status-files *status-directory*)))) (define (killall-command . args) "Stop all running downloads." (for-each (lambda (status) (if (download-process-alive? status) (let ((pid (assoc-ref status 'pid)) (dl-pid (assoc-ref status 'downloader-pid))) (and (gnunet-info "Stopping processes ~a and ~a" pid dl-pid) (kill pid 15) (kill dl-pid 15))))) (map (lambda (file) (uri-status *status-directory* (string-append "gnunet://afs/" file))) (uri-status-files *status-directory*)))) (define (help-command . args) "Show this help message." (format #t "Usage: ~a [options]~%" *program-name*) (format #t "Where may be one of the following:~%~%") (for-each (lambda (command) (if (not (eq? (cdr command) help-command)) (format #t (string-append " " (car command) ": " (object-documentation (cdr command)) "~%")))) *commands*) (format #t "~%")) (define (settings-command . args) "Dump the current settings." (format #t "Current settings:~%~%") (module-for-each (lambda (symbol variable) (if (string-match "^\\*.*\\*$" (symbol->string symbol)) (format #t " ~a: ~a~%" symbol (variable-ref variable)))) (current-module)) (format #t "~%")) (define (version-command . args) "Show version information." (format #t "~a ~a.~a (~a)~%" *program-name* *version-major* *version-minor* *version-date*)) ;; This hook may be added to *completed-download-hook*. (define (completed-download-notification-hook status) "Notifies of the completion of a file download." (let ((msg (string-append "GNUnet download of " (output-file-option (assoc-ref status 'options)) " in " (assoc-ref status 'working-directory) " complete!"))) (if (getenv "DISPLAY") (waitpid (fork-and-exec #f "xmessage" msg)) (waitpid (fork-and-exec #f "write" (cuserid) msg))))) ;; Available user commands (define *commands* `(("download" . ,download-command) ("status" . ,status-command) ("resume" . ,resume-command) ("killall" . ,killall-command) ("settings" . ,settings-command) ("version" . ,version-command) ("help" . ,help-command) ("--help" . ,help-command) ("-h" . ,help-command))) (define *program-name* "gnunet-download-manager") (define *version-major* 0) (define *version-minor* 1) (define *version-date* "april 2004") (define (main args) (set! *program-name* (basename (car args))) ;; Load the user's configuration file (if (file-exists? *rc-file*) (load *rc-file*)) ;; Check whether the status directory already exists (if (not (file-exists? *status-directory*)) (begin (gnunet-info "Creating status directory ~a..." *status-directory*) (catch 'system-error (lambda () (mkdir *status-directory*)) (lambda (key . args) (and (gnunet-error (exception-string key args)) (exit 1)))))) ;; Go ahead (if (< (length args) 2) (and (format #t "Usage: ~a [options]~%" *program-name*) (exit 1)) (let* ((command-name (cadr args)) (command (assoc-ref *commands* command-name))) (if command (apply command (cddr args)) (and (gnunet-info "~a command not found" command-name) (exit 1))))))gnunet-0.10.1/src/fs/test_pseudonym_data.conf0000644000175000017500000000006512225230043016125 00000000000000# General settings [fs] [TESTING] WEAKRANDOM = YES gnunet-0.10.1/src/fs/gnunet-auto-share.c0000644000175000017500000004715112301361474014734 00000000000000/* This file is part of GNUnet. (C) 2001--2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-auto-share.c * @brief automatically publish files on GNUnet * @author Christian Grothoff * * TODO: * - support loading meta data / keywords from resource file * - add stability timer (a la buildbot) */ #include "platform.h" #include "gnunet_util_lib.h" #define MIN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4) #define MAX_FREQUENCY GNUNET_TIME_UNIT_MINUTES /** * Item in our work queue (or in the set of files/directories * we have successfully published). */ struct WorkItem { /** * PENDING Work is kept in a linked list. */ struct WorkItem *prev; /** * PENDING Work is kept in a linked list. */ struct WorkItem *next; /** * Filename of the work item. */ char *filename; /** * Unique identity for this work item (used to detect * if we need to do the work again). */ struct GNUNET_HashCode id; }; /** * Global return value from 'main'. */ static int ret; /** * Are we running 'verbosely'? */ static int verbose; /** * Configuration to use. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Name of the configuration file. */ static char *cfg_filename; /** * Disable extractor option to use for publishing. */ static int disable_extractor; /** * Disable creation time option to use for publishing. */ static int do_disable_creation_time; /** * Handle for the 'shutdown' task. */ static GNUNET_SCHEDULER_TaskIdentifier kill_task; /** * Handle for the main task that does scanning and working. */ static GNUNET_SCHEDULER_TaskIdentifier run_task; /** * Anonymity level option to use for publishing. */ static unsigned int anonymity_level = 1; /** * Content priority option to use for publishing. */ static unsigned int content_priority = 365; /** * Replication level option to use for publishing. */ static unsigned int replication_level = 1; /** * Top-level directory we monitor to auto-publish. */ static const char *dir_name; /** * Head of linked list of files still to publish. */ static struct WorkItem *work_head; /** * Tail of linked list of files still to publish. */ static struct WorkItem *work_tail; /** * Map from the hash of the filename (!) to a 'struct WorkItem' * that was finished. */ static struct GNUNET_CONTAINER_MultiHashMap *work_finished; /** * Set to GNUNET_YES if we are shutting down. */ static int do_shutdown; /** * Start time of the current round; used to determine how long * one iteration takes (which influences how fast we schedule * the next one). */ static struct GNUNET_TIME_Absolute start_time; /** * Pipe used to communicate 'gnunet-publish' completion (SIGCHLD) via signal. */ static struct GNUNET_DISK_PipeHandle *sigpipe; /** * Handle to the 'gnunet-publish' process that we executed. */ static struct GNUNET_OS_Process *publish_proc; /** * Compute the name of the state database file we will use. */ static char * get_state_file () { char *ret; GNUNET_asprintf (&ret, "%s%s.auto-share", dir_name, (DIR_SEPARATOR == dir_name[strlen(dir_name)-1]) ? "" : DIR_SEPARATOR_STR); return ret; } /** * Load the set of 'work_finished' items from disk. */ static void load_state () { char *fn; struct GNUNET_BIO_ReadHandle *rh; uint32_t n; struct GNUNET_HashCode id; struct WorkItem *wi; char *emsg; emsg = NULL; fn = get_state_file (); rh = GNUNET_BIO_read_open (fn); GNUNET_free (fn); if (NULL == rh) return; fn = NULL; if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &n)) goto error; while (n-- > 0) { if ( (GNUNET_OK != GNUNET_BIO_read_string (rh, "filename", &fn, 1024)) || (GNUNET_OK != GNUNET_BIO_read (rh, "id", &id, sizeof (struct GNUNET_HashCode))) ) goto error; wi = GNUNET_new (struct WorkItem); wi->id = id; wi->filename = fn; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded serialization ID for `%s' is `%s'\n", wi->filename, GNUNET_h2s (&id)); fn = NULL; GNUNET_CRYPTO_hash (wi->filename, strlen (wi->filename), &id); GNUNET_CONTAINER_multihashmap_put (work_finished, &id, wi, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); } if (GNUNET_OK == GNUNET_BIO_read_close (rh, &emsg)) return; rh = NULL; error: GNUNET_free_non_null (fn); if (NULL != rh) (void) GNUNET_BIO_read_close (rh, &emsg); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to load state: %s\n"), emsg); GNUNET_free_non_null (emsg); } /** * Write work item from the work_finished map to the given write handle. * * @param cls the 'struct GNUNET_BIO_WriteHandle*' * @param key key of the item in the map (unused) * @param value the 'struct WorkItem' to write * @return GNUNET_OK to continue to iterate (if write worked) */ static int write_item (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_BIO_WriteHandle *wh = cls; struct WorkItem *wi = value; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Saving serialization ID of file `%s' with value `%s'\n", wi->filename, GNUNET_h2s (&wi->id)); if ( (GNUNET_OK != GNUNET_BIO_write_string (wh, wi->filename)) || (GNUNET_OK != GNUNET_BIO_write (wh, &wi->id, sizeof (struct GNUNET_HashCode))) ) return GNUNET_SYSERR; /* write error, abort iteration */ return GNUNET_OK; } /** * Save the set of 'work_finished' items on disk. */ static void save_state () { uint32_t n; struct GNUNET_BIO_WriteHandle *wh; char *fn; n = GNUNET_CONTAINER_multihashmap_size (work_finished); fn = get_state_file (); wh = GNUNET_BIO_write_open (fn); if (NULL == wh) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to save state to file %s\n"), fn); GNUNET_free (fn); return; } if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, n)) { (void) GNUNET_BIO_write_close (wh); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to save state to file %s\n"), fn); GNUNET_free (fn); return; } (void) GNUNET_CONTAINER_multihashmap_iterate (work_finished, &write_item, wh); if (GNUNET_OK != GNUNET_BIO_write_close (wh)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to save state to file %s\n"), fn); GNUNET_free (fn); } /** * Task run on shutdown. Serializes our current state to disk. * * @param cls closure, unused * @param tc scheduler context, unused */ static void do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { kill_task = GNUNET_SCHEDULER_NO_TASK; do_shutdown = GNUNET_YES; if (NULL != publish_proc) { GNUNET_OS_process_kill (publish_proc, SIGKILL); return; } if (GNUNET_SCHEDULER_NO_TASK != run_task) { GNUNET_SCHEDULER_cancel (run_task); run_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Decide what the next task is (working or scanning) and schedule it. */ static void schedule_next_task (void); /** * Task triggered whenever we receive a SIGCHLD (child * process died). * * @param cls the 'struct WorkItem' we were working on * @param tc context */ static void maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct WorkItem *wi = cls; struct GNUNET_HashCode key; enum GNUNET_OS_ProcessStatusType type; unsigned long code; int ret; char c; const struct GNUNET_DISK_FileHandle *pr; run_task = GNUNET_SCHEDULER_NO_TASK; pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) { /* shutdown scheduled us, ignore! */ run_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, &maint_child_death, wi); return; } ret = GNUNET_OS_process_status (publish_proc, &type, &code); GNUNET_assert (GNUNET_SYSERR != ret); if (GNUNET_NO == ret) { GNUNET_break (0); GNUNET_OS_process_kill (publish_proc, SIGKILL); type = GNUNET_OS_PROCESS_SIGNALED; } GNUNET_OS_process_destroy (publish_proc); publish_proc = NULL; /* consume the signal */ GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); if (GNUNET_YES == do_shutdown) { GNUNET_free (wi->filename); GNUNET_free (wi); return; } if ( (GNUNET_OS_PROCESS_EXITED == type) && (0 == code) ) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Publication of `%s' done\n"), wi->filename); GNUNET_CRYPTO_hash (wi->filename, strlen (wi->filename), &key); GNUNET_CONTAINER_multihashmap_put (work_finished, &key, wi, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); } else { GNUNET_CONTAINER_DLL_insert_tail (work_head, work_tail, wi); } save_state (); schedule_next_task (); } /** * Signal handler called for SIGCHLD. Triggers the * respective handler by writing to the trigger pipe. */ static void sighandler_child_death () { static char c; int old_errno = errno; /* back-up errno */ GNUNET_break (1 == GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_WRITE), &c, sizeof (c))); errno = old_errno; /* restore errno */ } /** * Function called to process work items. * * @param cls closure, NULL * @param tc scheduler context (unused) */ static void work (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static char *argv[14]; static char anon_level[20]; static char content_prio[20]; static char repl_level[20]; struct WorkItem *wi; const struct GNUNET_DISK_FileHandle *pr; int argc; run_task = GNUNET_SCHEDULER_NO_TASK; wi = work_head; GNUNET_CONTAINER_DLL_remove (work_head, work_tail, wi); argc = 0; argv[argc++] = "gnunet-publish"; if (verbose) argv[argc++] = "-V"; if (disable_extractor) argv[argc++] = "-D"; if (do_disable_creation_time) argv[argc++] = "-d"; argv[argc++] = "-c"; argv[argc++] = cfg_filename; GNUNET_snprintf (anon_level, sizeof (anon_level), "%u", anonymity_level); argv[argc++] = "-a"; argv[argc++] = anon_level; GNUNET_snprintf (content_prio, sizeof (content_prio), "%u", content_priority); argv[argc++] = "-p"; argv[argc++] = content_prio; GNUNET_snprintf (repl_level, sizeof (repl_level), "%u", replication_level); argv[argc++] = "-r"; argv[argc++] = repl_level; argv[argc++] = wi->filename; argv[argc] = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Publishing `%s'\n"), wi->filename); publish_proc = GNUNET_OS_start_process_vap (GNUNET_YES, 0, NULL, NULL, NULL, "gnunet-publish", argv); if (NULL == publish_proc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to run `%s'\n"), "gnunet-publish"); GNUNET_CONTAINER_DLL_insert (work_head, work_tail, wi); run_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &work, NULL); return; } pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); run_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, &maint_child_death, wi); } /** * Recursively scan the given file/directory structure to determine * a unique ID that represents the current state of the hierarchy. * * @param cls where to store the unique ID we are computing * @param filename file to scan * @return GNUNET_OK (always) */ static int determine_id (void *cls, const char *filename) { struct GNUNET_HashCode *id = cls; struct stat sbuf; struct GNUNET_HashCode fx[2]; struct GNUNET_HashCode ft; if (0 != STAT (filename, &sbuf)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename); return GNUNET_OK; } GNUNET_CRYPTO_hash (filename, strlen (filename), &fx[0]); if (!S_ISDIR (sbuf.st_mode)) { uint64_t fattr[2]; fattr[0] = GNUNET_htonll (sbuf.st_size); fattr[0] = GNUNET_htonll (sbuf.st_mtime); GNUNET_CRYPTO_hash (fattr, sizeof (fattr), &fx[1]); } else { memset (&fx[1], 1, sizeof (struct GNUNET_HashCode)); GNUNET_DISK_directory_scan (filename, &determine_id, &fx[1]); } /* use hash here to make hierarchical structure distinct from all files on the same level */ GNUNET_CRYPTO_hash (fx, sizeof (fx), &ft); /* use XOR here so that order of the files in the directory does not matter! */ GNUNET_CRYPTO_hash_xor (&ft, id, id); return GNUNET_OK; } /** * Function called with a filename (or directory name) to publish * (if it has changed since the last time we published it). This function * is called for the top-level files only. * * @param cls closure, NULL * @param filename complete filename (absolute path) * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR during shutdown */ static int add_file (void *cls, const char *filename) { struct WorkItem *wi; struct GNUNET_HashCode key; struct GNUNET_HashCode id; if (GNUNET_YES == do_shutdown) return GNUNET_SYSERR; if ( (NULL != strstr (filename, "/.auto-share")) || (NULL != strstr (filename, "\\.auto-share")) ) return GNUNET_OK; /* skip internal file */ GNUNET_CRYPTO_hash (filename, strlen (filename), &key); wi = GNUNET_CONTAINER_multihashmap_get (work_finished, &key); memset (&id, 0, sizeof (struct GNUNET_HashCode)); determine_id (&id, filename); if (NULL != wi) { if (0 == memcmp (&id, &wi->id, sizeof (struct GNUNET_HashCode))) return GNUNET_OK; /* skip: we did this one already */ /* contents changed, need to re-do the directory... */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (work_finished, &key, wi)); } else { wi = GNUNET_new (struct WorkItem); wi->filename = GNUNET_strdup (filename); } wi->id = id; GNUNET_CONTAINER_DLL_insert (work_head, work_tail, wi); if (GNUNET_YES == do_shutdown) return GNUNET_SYSERR; return GNUNET_OK; } /** * Periodically run task to update our view of the directory to share. * * @param cls NULL * @param tc scheduler context, unused */ static void scan (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { run_task = GNUNET_SCHEDULER_NO_TASK; start_time = GNUNET_TIME_absolute_get (); (void) GNUNET_DISK_directory_scan (dir_name, &add_file, NULL); schedule_next_task (); } /** * Decide what the next task is (working or scanning) and schedule it. */ static void schedule_next_task () { struct GNUNET_TIME_Relative delay; if (GNUNET_YES == do_shutdown) return; if (NULL == work_head) { /* delay by at most 4h, at least 1s, and otherwise in between depending on how long it took to scan */ delay = GNUNET_TIME_absolute_get_duration (start_time); delay = GNUNET_TIME_relative_min (MIN_FREQUENCY, GNUNET_TIME_relative_multiply (delay, 100)); delay = GNUNET_TIME_relative_max (delay, MAX_FREQUENCY); run_task = GNUNET_SCHEDULER_add_delayed (delay, &scan, NULL); } else { run_task = GNUNET_SCHEDULER_add_now (&work, NULL); } } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { /* check arguments */ if ((args[0] == NULL) || (args[1] != NULL) || (GNUNET_YES != GNUNET_DISK_directory_test (args[0], GNUNET_YES))) { printf (_("You must specify one and only one directory name for automatic publication.\n")); ret = -1; return; } cfg_filename = GNUNET_strdup (cfgfile); cfg = c; dir_name = args[0]; work_finished = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); load_state (); run_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &scan, NULL); kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task, NULL); } /** * Free memory associated with the work item from the work_finished map. * * @param cls NULL (unused) * @param key key of the item in the map (unused) * @param value the 'struct WorkItem' to free * @return GNUNET_OK to continue to iterate */ static int free_item (void *cls, const struct GNUNET_HashCode *key, void *value) { struct WorkItem *wi = value; GNUNET_free (wi->filename); GNUNET_free (wi); return GNUNET_OK; } /** * The main function to automatically publish content to GNUnet. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'a', "anonymity", "LEVEL", gettext_noop ("set the desired LEVEL of sender-anonymity"), 1, &GNUNET_GETOPT_set_uint, &anonymity_level}, {'d', "disable-creation-time", NULL, gettext_noop ("disable adding the creation time to the metadata of the uploaded file"), 0, &GNUNET_GETOPT_set_one, &do_disable_creation_time}, {'D', "disable-extractor", NULL, gettext_noop ("do not use libextractor to add keywords or metadata"), 0, &GNUNET_GETOPT_set_one, &disable_extractor}, {'p', "priority", "PRIORITY", gettext_noop ("specify the priority of the content"), 1, &GNUNET_GETOPT_set_uint, &content_priority}, {'r', "replication", "LEVEL", gettext_noop ("set the desired replication LEVEL"), 1, &GNUNET_GETOPT_set_uint, &replication_level}, {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_set_one, &verbose}, GNUNET_GETOPT_OPTION_END }; struct WorkItem *wi; int ok; struct GNUNET_SIGNAL_Context *shc_chld; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); GNUNET_assert (sigpipe != NULL); shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); ok = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-auto-share [OPTIONS] FILENAME", gettext_noop ("Automatically publish files from a directory on GNUnet"), options, &run, NULL)) ? ret : 1; if (NULL != work_finished) { (void) GNUNET_CONTAINER_multihashmap_iterate (work_finished, &free_item, NULL); GNUNET_CONTAINER_multihashmap_destroy (work_finished); } while (NULL != (wi = work_head)) { GNUNET_CONTAINER_DLL_remove (work_head, work_tail, wi); GNUNET_free (wi->filename); GNUNET_free (wi); } GNUNET_SIGNAL_handler_uninstall (shc_chld); shc_chld = NULL; GNUNET_DISK_pipe_close (sigpipe); sigpipe = NULL; GNUNET_free (cfg_filename); cfg_filename = NULL; GNUNET_free ((void*) argv); return ok; } /* end of gnunet-auto-share.c */ gnunet-0.10.1/src/fs/test_gnunet_fs_psd.py.in0000755000175000017500000000753312222260266016100 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Testcase for file-sharing command-line tools (publish, search, download) import sys import os import subprocess import re import shutil srcdir = "../.." gnunet_pyexpect_dir = os.path.join (srcdir, "contrib") if gnunet_pyexpect_dir not in sys.path: sys.path.append (gnunet_pyexpect_dir) from gnunet_pyexpect import pexpect if os.name == 'posix': download = './gnunet-download' gnunetarm = 'gnunet-arm' publish = './gnunet-publish' unindex = './gnunet-unindex' search = './gnunet-search' elif os.name == 'nt': download = './gnunet-download.exe' gnunetarm = 'gnunet-arm.exe' publish = './gnunet-publish.exe' unindex = './gnunet-unindex.exe' search = './gnunet-search.exe' if os.name == "nt": shutil.rmtree (os.path.join (os.getenv ("TEMP"), "gnunet-test-fs-py-psd"), True) else: shutil.rmtree ("/tmp/gnunet-test-fs-py-psd", True) arm = subprocess.Popen ([gnunetarm, '-sq', '-c', 'test_gnunet_fs_psd_data.conf']) arm.communicate () # first, basic publish-search-download run try: pub = pexpect () pub.spawn (None, [publish, '-c', 'test_gnunet_fs_psd_data.conf', '-n', '-m', "description:Test archive", '-k', 'tst', 'test_gnunet_fs_rec_data.tgz'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pub.expect ("stdout", re.compile (r"Publishing `.+test_gnunet_fs_rec_data.tgz' done\.\r?\n")) pub.expect ("stdout", re.compile (r"URI is `gnunet://fs/chk/2VKHJMR74CB6GB1GFJNOO95BTINA2PEO25FL48GAS7SPBMA0GDEK5U74R1VIHK0LA6919QRS376BHQFDOE3OUP0JOU92K1NIRJMHFCO\.49BQ3R5C10JA1695IF71FCQ8VVG4IKIPH04BD9CQ22O6JEK915A7CEPQ17OD0NUQHTR5K4HHEGIKEVPFODB7IAUC0EKIAL2R781E9DG\.17822'\.\r?\n")) s = pexpect () s.spawn (None, [search, '-V', '-t', '1000 ms', '-N', '1', '-c', 'test_gnunet_fs_psd_data.conf', 'tst'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) s.expect ("stdout", re.compile (r'#0:\r?\n')) s.expect ("stdout", re.compile (r'gnunet-download -o "test_gnunet_fs_rec_data.tgz" gnunet://fs/chk/2VKHJMR74CB6GB1GFJNOO95BTINA2PEO25FL48GAS7SPBMA0GDEK5U74R1VIHK0LA6919QRS376BHQFDOE3OUP0JOU92K1NIRJMHFCO\.49BQ3R5C10JA1695IF71FCQ8VVG4IKIPH04BD9CQ22O6JEK915A7CEPQ17OD0NUQHTR5K4HHEGIKEVPFODB7IAUC0EKIAL2R781E9DG\.17822\r?\n')) s.expect ("stdout", re.compile (r"\s*description: Test archive\r?\n")) down = pexpect () down.spawn (None, [download, '-c', 'test_gnunet_fs_psd_data.conf', '-o', 'test_gnunet_fs_rec_data.tar.gz', 'gnunet://fs/chk/2VKHJMR74CB6GB1GFJNOO95BTINA2PEO25FL48GAS7SPBMA0GDEK5U74R1VIHK0LA6919QRS376BHQFDOE3OUP0JOU92K1NIRJMHFCO.49BQ3R5C10JA1695IF71FCQ8VVG4IKIPH04BD9CQ22O6JEK915A7CEPQ17OD0NUQHTR5K4HHEGIKEVPFODB7IAUC0EKIAL2R781E9DG.17822'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) down.expect ("stdout", re.compile (r"Downloading `test_gnunet_fs_rec_data.tar.gz' done (.*).\r?\n")) os.remove ("test_gnunet_fs_rec_data.tar.gz") finally: arm = subprocess.Popen ([gnunetarm, '-eq', '-c', 'test_gnunet_fs_psd_data.conf']) arm.communicate () if os.name == "nt": shutil.rmtree (os.path.join (os.getenv ("TEMP"), "gnunet-test-fs-py-psd"), True) else: shutil.rmtree ("/tmp/gnunet-test-fs-py-psd", True) gnunet-0.10.1/src/fs/gnunet-service-fs_mesh_server.c0000644000175000017500000003564712251306467017350 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_mesh_server.c * @brief non-anonymous file-transfer * @author Christian Grothoff * * TODO: * - PORT is set to old application type, unsure if we should keep * it that way (fine for now) */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_util_lib.h" #include "gnunet_mesh_service.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet-service-fs.h" #include "gnunet-service-fs_indexing.h" #include "gnunet-service-fs_mesh.h" /** * After how long do we termiante idle connections? */ #define IDLE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) /** * A message in the queue to be written to the mesh. */ struct WriteQueueItem { /** * Kept in a DLL. */ struct WriteQueueItem *next; /** * Kept in a DLL. */ struct WriteQueueItem *prev; /** * Number of bytes of payload, allocated at the end of this struct. */ size_t msize; }; /** * Information we keep around for each active meshing client. */ struct MeshClient { /** * DLL */ struct MeshClient *next; /** * DLL */ struct MeshClient *prev; /** * Channel for communication. */ struct GNUNET_MESH_Channel *channel; /** * Handle for active write operation, or NULL. */ struct GNUNET_MESH_TransmitHandle *wh; /** * Head of write queue. */ struct WriteQueueItem *wqi_head; /** * Tail of write queue. */ struct WriteQueueItem *wqi_tail; /** * Current active request to the datastore, if we have one pending. */ struct GNUNET_DATASTORE_QueueEntry *qe; /** * Task that is scheduled to asynchronously terminate the connection. */ GNUNET_SCHEDULER_TaskIdentifier terminate_task; /** * Task that is scheduled to terminate idle connections. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Size of the last write that was initiated. */ size_t reply_size; }; /** * Listen channel for incoming requests. */ static struct GNUNET_MESH_Handle *listen_channel; /** * Head of DLL of mesh clients. */ static struct MeshClient *sc_head; /** * Tail of DLL of mesh clients. */ static struct MeshClient *sc_tail; /** * Number of active mesh clients in the 'sc_*'-DLL. */ static unsigned int sc_count; /** * Maximum allowed number of mesh clients. */ static unsigned long long sc_count_max; /** * Task run to asynchronously terminate the mesh due to timeout. * * @param cls the 'struct MeshClient' * @param tc scheduler context */ static void timeout_mesh_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshClient *sc = cls; struct GNUNET_MESH_Channel *tun; sc->timeout_task = GNUNET_SCHEDULER_NO_TASK; tun = sc->channel; sc->channel = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for inactive mesh client %p\n", sc); GNUNET_MESH_channel_destroy (tun); } /** * Reset the timeout for the mesh client (due to activity). * * @param sc client handle to reset timeout for */ static void refresh_timeout_task (struct MeshClient *sc) { if (GNUNET_SCHEDULER_NO_TASK != sc->timeout_task) GNUNET_SCHEDULER_cancel (sc->timeout_task); sc->timeout_task = GNUNET_SCHEDULER_add_delayed (IDLE_TIMEOUT, &timeout_mesh_task, sc); } /** * We're done handling a request from a client, read the next one. * * @param sc client to continue reading requests from */ static void continue_reading (struct MeshClient *sc) { refresh_timeout_task (sc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished processing mesh request from client %p, ready to receive the next one\n", sc); GNUNET_MESH_receive_done (sc->channel); } /** * Transmit the next entry from the write queue. * * @param sc where to process the write queue */ static void continue_writing (struct MeshClient *sc); /** * Send a reply now, mesh is ready. * * @param cls closure with the `struct MeshClient` which sent the query * @param size number of bytes available in @a buf * @param buf where to write the message * @return number of bytes written to @a buf */ static size_t write_continuation (void *cls, size_t size, void *buf) { struct MeshClient *sc = cls; struct GNUNET_MESH_Channel *tun; struct WriteQueueItem *wqi; size_t ret; sc->wh = NULL; if (NULL == (wqi = sc->wqi_head)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Write queue empty, reading more requests\n"); return 0; } if ( (0 == size) || (size < wqi->msize) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission of reply failed, terminating mesh\n"); tun = sc->channel; sc->channel = NULL; GNUNET_MESH_channel_destroy (tun); return 0; } GNUNET_CONTAINER_DLL_remove (sc->wqi_head, sc->wqi_tail, wqi); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %u byte reply via mesh to %p\n", (unsigned int) size, sc); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Blocks transferred via mesh"), 1, GNUNET_NO); memcpy (buf, &wqi[1], ret = wqi->msize); GNUNET_free (wqi); continue_writing (sc); return ret; } /** * Transmit the next entry from the write queue. * * @param sc where to process the write queue */ static void continue_writing (struct MeshClient *sc) { struct WriteQueueItem *wqi; struct GNUNET_MESH_Channel *tun; if (NULL != sc->wh) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Write pending, waiting for it to complete\n"); return; /* write already pending */ } if (NULL == (wqi = sc->wqi_head)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Write queue empty, reading more requests\n"); continue_reading (sc); return; } sc->wh = GNUNET_MESH_notify_transmit_ready (sc->channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, wqi->msize, &write_continuation, sc); if (NULL == sc->wh) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Write failed; terminating mesh\n"); tun = sc->channel; sc->channel = NULL; GNUNET_MESH_channel_destroy (tun); return; } } /** * Process a datum that was stored in the datastore. * * @param cls closure with the `struct MeshClient` which sent the query * @param key key for the content * @param size number of bytes in @a data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ static void handle_datastore_reply (void *cls, const struct GNUNET_HashCode *key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct MeshClient *sc = cls; size_t msize = size + sizeof (struct MeshReplyMessage); struct WriteQueueItem *wqi; struct MeshReplyMessage *srm; sc->qe = NULL; if (NULL == data) { /* no result, this should not really happen, as for non-anonymous routing only peers that HAVE the answers should be queried; OTOH, this is not a hard error as we might have had the answer in the past and the user might have unindexed it. Hence we log at level "INFO" for now. */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Have no answer for query `%s'\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# queries received via mesh not answered"), 1, GNUNET_NO); continue_writing (sc); return; } if (GNUNET_BLOCK_TYPE_FS_ONDEMAND == type) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Performing on-demand encoding for query %s\n", GNUNET_h2s (key)); if (GNUNET_OK != GNUNET_FS_handle_on_demand_block (key, size, data, type, priority, anonymity, expiration, uid, &handle_datastore_reply, sc)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "On-demand encoding request failed\n"); continue_writing (sc); } return; } if (msize > GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); continue_writing (sc); return; } GNUNET_break (GNUNET_BLOCK_TYPE_ANY != type); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting transmission of %u byte reply of type %d for query `%s' via mesh to %p\n", (unsigned int) size, (unsigned int) type, GNUNET_h2s (key), sc); wqi = GNUNET_malloc (sizeof (struct WriteQueueItem) + msize); wqi->msize = msize; srm = (struct MeshReplyMessage *) &wqi[1]; srm->header.size = htons ((uint16_t) msize); srm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_MESH_REPLY); srm->type = htonl (type); srm->expiration = GNUNET_TIME_absolute_hton (expiration); memcpy (&srm[1], data, size); sc->reply_size = msize; GNUNET_CONTAINER_DLL_insert (sc->wqi_head, sc->wqi_tail, wqi); continue_writing (sc); } /** * Functions with this signature are called whenever a * complete query message is received. * * Do not call #GNUNET_SERVER_mst_destroy in callback * * @param cls closure with the 'struct MeshClient' * @param channel channel handle * @param channel_ctx channel context * @param message the actual message * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing */ static int request_cb (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct MeshClient *sc = *channel_ctx; const struct MeshQueryMessage *sqm; sqm = (const struct MeshQueryMessage *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received query for `%s' via mesh from client %p\n", GNUNET_h2s (&sqm->query), sc); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# queries received via mesh"), 1, GNUNET_NO); refresh_timeout_task (sc); sc->qe = GNUNET_DATASTORE_get_key (GSF_dsh, 0, &sqm->query, ntohl (sqm->type), 0 /* priority */, GSF_datastore_queue_size, GNUNET_TIME_UNIT_FOREVER_REL, &handle_datastore_reply, sc); if (NULL == sc->qe) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing request with datastore failed (queue full?)\n"); continue_writing (sc); } return GNUNET_OK; } /** * Functions of this type are called upon new mesh connection from other peers. * * @param cls the closure from GNUNET_MESH_connect * @param channel the channel representing the mesh * @param initiator the identity of the peer who wants to establish a mesh * with us; NULL on binding error * @param port mesh port used for the incoming connection * @param options channel option flags * @return initial channel context (our 'struct MeshClient') */ static void * accept_cb (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { struct MeshClient *sc; GNUNET_assert (NULL != channel); if (sc_count >= sc_count_max) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# mesh client connections rejected"), 1, GNUNET_NO); GNUNET_MESH_channel_destroy (channel); return NULL; } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# mesh connections active"), 1, GNUNET_NO); sc = GNUNET_new (struct MeshClient); sc->channel = channel; GNUNET_CONTAINER_DLL_insert (sc_head, sc_tail, sc); sc_count++; refresh_timeout_task (sc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Accepting inbound mesh connection from `%s' as client %p\n", GNUNET_i2s (initiator), sc); return sc; } /** * Function called by mesh when a client disconnects. * Cleans up our 'struct MeshClient' of that channel. * * @param cls NULL * @param channel channel of the disconnecting client * @param channel_ctx our 'struct MeshClient' */ static void cleaner_cb (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { struct MeshClient *sc = channel_ctx; struct WriteQueueItem *wqi; if (NULL == sc) return; sc->channel = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Terminating mesh connection with client %p\n", sc); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# mesh connections active"), -1, GNUNET_NO); if (GNUNET_SCHEDULER_NO_TASK != sc->terminate_task) GNUNET_SCHEDULER_cancel (sc->terminate_task); if (GNUNET_SCHEDULER_NO_TASK != sc->timeout_task) GNUNET_SCHEDULER_cancel (sc->timeout_task); if (NULL != sc->wh) GNUNET_MESH_notify_transmit_ready_cancel (sc->wh); if (NULL != sc->qe) GNUNET_DATASTORE_cancel (sc->qe); while (NULL != (wqi = sc->wqi_head)) { GNUNET_CONTAINER_DLL_remove (sc->wqi_head, sc->wqi_tail, wqi); GNUNET_free (wqi); } GNUNET_CONTAINER_DLL_remove (sc_head, sc_tail, sc); sc_count--; GNUNET_free (sc); } /** * Initialize subsystem for non-anonymous file-sharing. */ void GSF_mesh_start_server () { static const struct GNUNET_MESH_MessageHandler handlers[] = { { &request_cb, GNUNET_MESSAGE_TYPE_FS_MESH_QUERY, sizeof (struct MeshQueryMessage)}, { NULL, 0, 0 } }; static const uint32_t ports[] = { GNUNET_APPLICATION_TYPE_FS_BLOCK_TRANSFER, 0 }; if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_number (GSF_cfg, "fs", "MAX_MESH_CLIENTS", &sc_count_max)) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initializing mesh FS server with a limit of %llu connections\n", sc_count_max); listen_channel = GNUNET_MESH_connect (GSF_cfg, NULL, &accept_cb, &cleaner_cb, handlers, ports); } /** * Shutdown subsystem for non-anonymous file-sharing. */ void GSF_mesh_stop_server () { if (NULL != listen_channel) { GNUNET_MESH_disconnect (listen_channel); listen_channel = NULL; } GNUNET_assert (NULL == sc_head); GNUNET_assert (0 == sc_count); } /* end of gnunet-service-fs_mesh.c */ gnunet-0.10.1/src/fs/fs_list_indexed.c0000644000175000017500000001235212255010511014513 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_list_indexed.c * @author Christian Grothoff * @brief provide a list of all indexed files */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_fs_service.h" #include "gnunet_protocols.h" #include "fs_api.h" /** * Context for "GNUNET_FS_get_indexed_files". */ struct GNUNET_FS_GetIndexedContext { /** * Handle to global FS context. */ struct GNUNET_FS_Handle *h; /** * Connection to the FS service. */ struct GNUNET_CLIENT_Connection *client; /** * Function to call for each indexed file. */ GNUNET_FS_IndexedFileProcessor iterator; /** * Closure for iterator. */ void *iterator_cls; /** * Continuation to trigger at the end. */ GNUNET_SCHEDULER_Task cont; /** * Closure for cont. */ void *cont_cls; }; /** * Function called on each response from the FS * service with information about indexed files. * * @param cls closure (of type "struct GNUNET_FS_GetIndexedContext*") * @param msg message with indexing information */ static void handle_index_info (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_FS_GetIndexedContext *gic = cls; const struct IndexInfoMessage *iim; uint16_t msize; const char *filename; if (NULL == msg) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Failed to receive response for `%s' request from `%s' service.\n"), "GET_INDEXED", "fs"); (void) gic->iterator (gic->iterator_cls, NULL, NULL); GNUNET_FS_get_indexed_files_cancel (gic); return; } if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END) { /* normal end-of-list */ (void) gic->iterator (gic->iterator_cls, NULL, NULL); GNUNET_FS_get_indexed_files_cancel (gic); return; } msize = ntohs (msg->size); iim = (const struct IndexInfoMessage *) msg; filename = (const char *) &iim[1]; if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY) || (msize <= sizeof (struct IndexInfoMessage)) || (filename[msize - sizeof (struct IndexInfoMessage) - 1] != '\0')) { /* bogus reply */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Failed to receive valid response for `%s' request from `%s' service.\n"), "GET_INDEXED", "fs"); (void) gic->iterator (gic->iterator_cls, NULL, NULL); GNUNET_FS_get_indexed_files_cancel (gic); return; } if (GNUNET_OK != gic->iterator (gic->iterator_cls, filename, &iim->file_id)) { GNUNET_FS_get_indexed_files_cancel (gic); return; } /* get more */ GNUNET_CLIENT_receive (gic->client, &handle_index_info, gic, GNUNET_CONSTANTS_SERVICE_TIMEOUT); } /** * Iterate over all indexed files. * * @param h handle to the file sharing subsystem * @param iterator function to call on each indexed file * @param iterator_cls closure for iterator * @return NULL on error ('iter' is not called) */ struct GNUNET_FS_GetIndexedContext * GNUNET_FS_get_indexed_files (struct GNUNET_FS_Handle *h, GNUNET_FS_IndexedFileProcessor iterator, void *iterator_cls) { struct GNUNET_CLIENT_Connection *client; struct GNUNET_FS_GetIndexedContext *gic; struct GNUNET_MessageHeader msg; client = GNUNET_CLIENT_connect ("fs", h->cfg); if (NULL == client) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to not connect to `%s' service.\n"), "fs"); return NULL; } gic = GNUNET_new (struct GNUNET_FS_GetIndexedContext); gic->h = h; gic->client = client; gic->iterator = iterator; gic->iterator_cls = iterator_cls; msg.size = htons (sizeof (struct GNUNET_MessageHeader)); msg.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET); GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (client, &msg, GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_YES, &handle_index_info, gic)); return gic; } /** * Cancel iteration over all indexed files. * * @param gic operation to cancel */ void GNUNET_FS_get_indexed_files_cancel (struct GNUNET_FS_GetIndexedContext *gic) { GNUNET_CLIENT_disconnect (gic->client); GNUNET_free (gic); } /* end of fs_list_indexed.c */ gnunet-0.10.1/src/fs/fs.h0000644000175000017500000002043112225777503012004 00000000000000/* This file is part of GNUnet. (C) 2003--2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs.h * @brief definitions for the entire fs module * @author Igor Wronsky, Christian Grothoff */ #ifndef FS_H #define FS_H #include "gnunet_constants.h" #include "gnunet_datastore_service.h" #include "gnunet_dht_service.h" #include "gnunet_fs_service.h" #include "gnunet_block_lib.h" #include "block_fs.h" /** * Size of the individual blocks used for file-sharing. */ #define DBLOCK_SIZE (32 * 1024) /** * Blocksize to use when hashing files for indexing (blocksize for IO, * not for the DBlocks). Larger blocksizes can be more efficient but * will be more disruptive as far as the scheduler is concerned. */ #define HASHING_BLOCKSIZE (1024 * 128) /** * @brief content hash key */ struct ContentHashKey { /** * Hash of the original content, used for encryption. */ struct GNUNET_HashCode key; /** * Hash of the encrypted content, used for querying. */ struct GNUNET_HashCode query; }; GNUNET_NETWORK_STRUCT_BEGIN /** * Message sent from a GNUnet (fs) publishing activity to the * gnunet-fs-service to initiate indexing of a file. The service is * supposed to check if the specified file is available and has the * same cryptographic hash. It should then respond with either a * confirmation or a denial. * * On OSes where this works, it is considered acceptable if the * service only checks that the path, device and inode match (it can * then be assumed that the hash will also match without actually * computing it; this is an optimization that should be safe given * that the client is not our adversary). */ struct IndexStartMessage { /** * Message type will be #GNUNET_MESSAGE_TYPE_FS_INDEX_START. */ struct GNUNET_MessageHeader header; /** * For alignment. */ uint32_t reserved GNUNET_PACKED; /** * ID of device containing the file, as seen by the client. This * device ID is obtained using a call like "statvfs" (and converting * the "f_fsid" field to a 32-bit big-endian number). Use 0 if the * OS does not support this, in which case the service must do a * full hash recomputation. */ uint64_t device GNUNET_PACKED; /** * Inode of the file on the given device, as seen by the client * ("st_ino" field from "struct stat"). Use 0 if the OS does not * support this, in which case the service must do a full hash * recomputation. */ uint64_t inode GNUNET_PACKED; /** * Hash of the file that we would like to index. */ struct GNUNET_HashCode file_id; /* this is followed by a 0-terminated * filename of a file with the hash * "file_id" as seen by the client */ }; /** * Message send by FS service in response to a request * asking for a list of all indexed files. */ struct IndexInfoMessage { /** * Message type will be * #GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY. */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Hash of the indexed file. */ struct GNUNET_HashCode file_id; /* this is followed by a 0-terminated * filename of a file with the hash * "file_id" as seen by the client */ }; /** * Message sent from a GNUnet (fs) unindexing activity to the * gnunet-service-fs to indicate that a file will be unindexed. The * service is supposed to remove the file from the list of indexed * files and response with a confirmation message (even if the file * was already not on the list). */ struct UnindexMessage { /** * Message type will be #GNUNET_MESSAGE_TYPE_FS_UNINDEX. */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Hash of the file that we will unindex. */ struct GNUNET_HashCode file_id; }; /** * No options. */ #define SEARCH_MESSAGE_OPTION_NONE 0 /** * Only search the local datastore (no network) */ #define SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY 1 /** * Request is too large to fit in 64k format. The list of * already-known search results will be continued in another message * for the same type/query/target and additional already-known results * following this one). */ #define SEARCH_MESSAGE_OPTION_CONTINUED 2 /** * Message sent from a GNUnet (fs) search activity to the * gnunet-service-fs to start a search. */ struct SearchMessage { /** * Message type will be #GNUNET_MESSAGE_TYPE_FS_START_SEARCH. */ struct GNUNET_MessageHeader header; /** * Bitmask with options. Zero for no options, one for * loopback-only, two for 'to be continued' (with a second search * message for the same type/query/target and additional * already-known results following this one). See * SEARCH_MESSAGE_OPTION_ defines. * * Other bits are currently not defined. */ uint32_t options GNUNET_PACKED; /** * Type of the content that we're looking for. */ uint32_t type GNUNET_PACKED; /** * Desired anonymity level, big-endian. */ uint32_t anonymity_level GNUNET_PACKED; /** * If the request is for a DBLOCK or IBLOCK, this is the identity of * the peer that is known to have a response. Set to all-zeros if * such a target is not known (note that even if OUR anonymity * level is >0 we may happen to know the responder's identity; * nevertheless, we should probably not use it for a DHT-lookup * or similar blunt actions in order to avoid exposing ourselves). *

* Otherwise, "target" must be all zeros. */ struct GNUNET_PeerIdentity target; /** * Hash of the public key for UBLOCKs; Hash of * the CHK-encoded block for DBLOCKS and IBLOCKS. */ struct GNUNET_HashCode query; /* this is followed by the hash codes of already-known * results (which should hence be excluded from what * the service returns); naturally, this only applies * to queries that can have multiple results (UBLOCKS). */ }; /** * Response from FS service with a result for a previous FS search. * Note that queries for DBLOCKS and IBLOCKS that have received a * single response are considered done. This message is transmitted * between peers. */ struct PutMessage { /** * Message type will be #GNUNET_MESSAGE_TYPE_FS_PUT. */ struct GNUNET_MessageHeader header; /** * Type of the block (in big endian). Should never be zero. */ uint32_t type GNUNET_PACKED; /** * When does this result expire? */ struct GNUNET_TIME_AbsoluteNBO expiration; /* this is followed by the actual encrypted content */ }; /** * Response from FS service with a result for a previous FS search. * Note that queries for DBLOCKS and IBLOCKS that have received a * single response are considered done. This message is transmitted * between the service and a client. */ struct ClientPutMessage { /** * Message type will be #GNUNET_MESSAGE_TYPE_FS_PUT. */ struct GNUNET_MessageHeader header; /** * Type of the block (in big endian). Should never be zero. */ uint32_t type GNUNET_PACKED; /** * When does this result expire? */ struct GNUNET_TIME_AbsoluteNBO expiration; /** * When was the last time we've tried to download this block? * (FOREVER if unknown/not relevant) */ struct GNUNET_TIME_AbsoluteNBO last_transmission; /** * How often did we transmit this query before getting an * answer (estimate). */ uint32_t num_transmissions; /** * How much respect did we offer (in total) before getting an * answer (estimate). */ uint32_t respect_offered; /* this is followed by the actual encrypted content */ }; GNUNET_NETWORK_STRUCT_END #endif /* end of fs.h */ gnunet-0.10.1/src/fs/test_fs_directory.c0000644000175000017500000001274412225777502015131 00000000000000/* This file is part of GNUnet. (C) 2005, 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_directory.c * @brief Test for fs_directory.c * @author Christian Grothoff */ #include "platform.h" #include #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "fs_api.h" #define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); return 1; } struct PCLS { struct GNUNET_FS_Uri **uri; struct GNUNET_CONTAINER_MetaData **md; unsigned int pos; unsigned int max; }; static void processor (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *md, size_t length, const void *data) { struct PCLS *p = cls; int i; if (NULL == uri) return; /* ignore directory's meta data */ for (i = 0; i < p->max; i++) { if (GNUNET_CONTAINER_meta_data_test_equal (p->md[i], md) && GNUNET_FS_uri_test_equal (p->uri[i], uri)) { p->pos++; return; } } FPRINTF (stderr, "Error at %s:%d\n", __FILE__, __LINE__); } static int testDirectory (unsigned int i) { struct GNUNET_FS_DirectoryBuilder *db; char *data; size_t dlen; struct GNUNET_FS_Uri **uris; struct GNUNET_CONTAINER_MetaData **mds; struct GNUNET_CONTAINER_MetaData *meta; struct PCLS cls; char *emsg; int p; int q; char uri[512]; char txt[128]; int ret = 0; struct GNUNET_TIME_Absolute start; const char *s; cls.max = i; uris = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri *) * i); mds = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_MetaData *) * i); meta = GNUNET_CONTAINER_meta_data_create (); GNUNET_CONTAINER_meta_data_insert (meta, "", EXTRACTOR_METATYPE_TITLE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "A title", strlen ("A title") + 1); GNUNET_CONTAINER_meta_data_insert (meta, "", EXTRACTOR_METATYPE_AUTHOR_NAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", "An author", strlen ("An author") + 1); for (p = 0; p < i; p++) { mds[p] = GNUNET_CONTAINER_meta_data_create (); for (q = 0; q <= p; q++) { GNUNET_snprintf (txt, sizeof (txt), "%u -- %u\n", p, q); GNUNET_CONTAINER_meta_data_insert (mds[p], "", q % EXTRACTOR_metatype_get_max (), EXTRACTOR_METAFORMAT_UTF8, "text/plain", txt, strlen (txt) + 1); } GNUNET_snprintf (uri, sizeof (uri), "gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.%u", p); emsg = NULL; uris[p] = GNUNET_FS_uri_parse (uri, &emsg); if (uris[p] == NULL) { GNUNET_CONTAINER_meta_data_destroy (mds[p]); while (--p > 0) { GNUNET_CONTAINER_meta_data_destroy (mds[p]); GNUNET_FS_uri_destroy (uris[p]); } GNUNET_free (mds); GNUNET_free (uris); GNUNET_free (emsg); GNUNET_CONTAINER_meta_data_destroy (meta); ABORT (); /* error in testcase */ } GNUNET_assert (emsg == NULL); } start = GNUNET_TIME_absolute_get (); db = GNUNET_FS_directory_builder_create (meta); for (p = 0; p < i; p++) GNUNET_FS_directory_builder_add (db, uris[p], mds[p], NULL); GNUNET_FS_directory_builder_finish (db, &dlen, (void **) &data); s = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES); FPRINTF (stdout, "Creating directory with %u entires and total size %llu took %s\n", i, (unsigned long long) dlen, s); if (i < 100) { cls.pos = 0; cls.uri = uris; cls.md = mds; GNUNET_FS_directory_list_contents (dlen, data, 0, &processor, &cls); GNUNET_assert (cls.pos == i); } GNUNET_free (data); GNUNET_CONTAINER_meta_data_destroy (meta); for (p = 0; p < i; p++) { GNUNET_CONTAINER_meta_data_destroy (mds[p]); GNUNET_FS_uri_destroy (uris[p]); } GNUNET_free (uris); GNUNET_free (mds); return ret; } int main (int argc, char *argv[]) { int failureCount = 0; int i; GNUNET_log_setup ("test_fs_directory", #if VERBOSE "DEBUG", #else "WARNING", #endif NULL); for (i = 17; i < 1000; i *= 2) failureCount += testDirectory (i); if (failureCount != 0) return 1; return 0; } /* end of test_fs_directory.c */ gnunet-0.10.1/src/fs/test_fs_search.c0000644000175000017500000001641212226006637014361 00000000000000/* This file is part of GNUnet. (C) 2004-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_search.c * @brief simple testcase for simple publish + search operation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_fs_service.h" /** * File-size we use for testing. */ #define FILESIZE 1024 /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static struct GNUNET_TIME_Absolute start; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_SearchContext *search; static struct GNUNET_FS_PublishContext *publish; static GNUNET_SCHEDULER_TaskIdentifier timeout_task; static int err; static void abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != publish) { GNUNET_FS_publish_stop (publish); publish = NULL; } if (GNUNET_SCHEDULER_NO_TASK != timeout_task) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } } static void abort_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { fprintf (stderr, "Timeout\n"); timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != search) { GNUNET_FS_search_stop (search); search = NULL; } if (NULL != publish) { GNUNET_FS_publish_stop (publish); publish = NULL; } err = 1; } static void abort_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != search) { GNUNET_FS_search_stop (search); search = NULL; } } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { const char *keywords[] = { "down_foo" }; struct GNUNET_FS_Uri *kuri; switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_PROGRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: kuri = GNUNET_FS_uri_ksk_create_from_args (1, keywords); start = GNUNET_TIME_absolute_get (); search = GNUNET_FS_search_start (fs, kuri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "search"); GNUNET_FS_uri_destroy (kuri); GNUNET_assert (search != NULL); break; case GNUNET_FS_STATUS_SEARCH_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Search complete.\n"); GNUNET_SCHEDULER_add_continuation (&abort_search_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); GNUNET_break (0); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_SEARCH_ERROR: FPRINTF (stderr, "Error searching file: %s\n", event->value.search.specifics.error.message); GNUNET_SCHEDULER_add_continuation (&abort_search_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_START: GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); GNUNET_assert (NULL == event->value.publish.pctx); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_assert (publish == event->value.publish.pc); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (1 == event->value.publish.anonymity); GNUNET_FS_stop (fs); fs = NULL; break; case GNUNET_FS_STATUS_SEARCH_START: GNUNET_assert (search == NULL); GNUNET_assert (0 == strcmp ("search", event->value.search.cctx)); GNUNET_assert (1 == event->value.search.anonymity); break; case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: break; case GNUNET_FS_STATUS_SEARCH_STOPPED: GNUNET_assert (search == event->value.search.sc); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; default: FPRINTF (stderr, "Unexpected event: %d\n", event->status); break; } return NULL; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar" }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_BlockOptions bo; struct GNUNET_FS_FileInformation *fi; size_t i; fs = GNUNET_FS_start (cfg, "test-fs-search", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi = GNUNET_FS_file_information_create_from_data (fs, "publish-context", FILESIZE, buf, kuri, meta, GNUNET_NO, &bo); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fi); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); timeout_task = GNUNET_SCHEDULER_add_delayed (LIFETIME, &abort_error, NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-search", "test_fs_search_data.conf", &run, NULL)) return 1; return err; } /* end of test_fs_search.c */ gnunet-0.10.1/src/fs/fs_api.h0000644000175000017500000012717612226005245012637 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_api.h * @brief shared definitions for the FS library * @author Igor Wronsky, Christian Grothoff */ #ifndef FS_API_H #define FS_API_H #include "gnunet_constants.h" #include "gnunet_datastore_service.h" #include "gnunet_dht_service.h" #include "gnunet_fs_service.h" #include "gnunet_block_lib.h" #include "block_fs.h" #include "fs.h" /** * Pick a multiple of 2 here to achive 8-byte alignment! We also * probably want DBlocks to have (roughly) the same size as IBlocks. * With SHA-512, the optimal value is 32768 byte / 128 byte = 256 (128 * byte = 2 * 512 bits). DO NOT CHANGE! */ #define CHK_PER_INODE 256 /** * Maximum size for a file to be considered for inlining in a * directory. */ #define MAX_INLINE_SIZE 65536 /** * Name of the directory with top-level searches. */ #define GNUNET_FS_SYNC_PATH_MASTER_SEARCH "search" /** * Name of the directory with sub-searches (namespace-updates). */ #define GNUNET_FS_SYNC_PATH_CHILD_SEARCH "search-child" /** * Name of the directory with master downloads (not associated * with search or part of another download). */ #define GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD "download" /** * Name of the directory with downloads that are part of another * download or a search. */ #define GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD "download-child" /** * Name of the directory with publishing operations. */ #define GNUNET_FS_SYNC_PATH_MASTER_PUBLISH "publish" /** * Name of the directory with files that are being published */ #define GNUNET_FS_SYNC_PATH_FILE_INFO "publish-file" /** * Name of the directory with unindex operations. */ #define GNUNET_FS_SYNC_PATH_MASTER_UNINDEX "unindex" /** * @brief complete information needed * to download a file. */ struct FileIdentifier { /** * Total size of the file in bytes. (network byte order (!)) */ uint64_t file_length; /** * Query and key of the top GNUNET_EC_IBlock. */ struct ContentHashKey chk; }; /** * Information about a file and its location * (peer claiming to share the file). */ struct Location { /** * Information about the shared file. */ struct FileIdentifier fi; /** * Identity of the peer sharing the file. */ struct GNUNET_PeerIdentity peer; /** * Time when this location URI expires. */ struct GNUNET_TIME_Absolute expirationTime; /** * Signature over the GNUNET_EC_FileIdentifier, * peer identity and expiration time. */ struct GNUNET_CRYPTO_EddsaSignature contentSignature; }; /** * Types of URIs. */ enum GNUNET_FS_UriType { /** * Content-hash-key (simple file). */ GNUNET_FS_URI_CHK, /** * Signed key space (file in namespace). */ GNUNET_FS_URI_SKS, /** * Keyword search key (query with keywords). */ GNUNET_FS_URI_KSK, /** * Location (chk with identity of hosting peer). */ GNUNET_FS_URI_LOC }; /** * A Universal Resource Identifier (URI), opaque. */ struct GNUNET_FS_Uri { /** * Type of the URI. */ enum GNUNET_FS_UriType type; union { struct { /** * Keywords start with a '+' if they are mandatory (in which * case the '+' is NOT part of the keyword) and with a simple * space if they are optional (in which case the space is ALSO * not part of the actual keyword). * * Double-quotes to protect spaces and %-encoding are NOT used * internally (only in URI-strings). */ char **keywords; /** * Size of the keywords array. */ unsigned int keywordCount; } ksk; struct { /** * Identifier of the namespace. */ struct GNUNET_CRYPTO_EcdsaPublicKey ns; /** * Human-readable identifier chosen for this entry in the * namespace. */ char *identifier; } sks; /** * Information needed to retrieve a file (content-hash-key * plus file size). */ struct FileIdentifier chk; /** * Information needed to retrieve a file including signed * location (identity of a peer) of the content. */ struct Location loc; } data; }; /** * Information for a file or directory that is * about to be published. */ struct GNUNET_FS_FileInformation { /** * Files in a directory are kept as a linked list. */ struct GNUNET_FS_FileInformation *next; /** * If this is a file in a directory, "dir" refers to * the directory; otherwise NULL. */ struct GNUNET_FS_FileInformation *dir; /** * Handle to the master context. */ struct GNUNET_FS_Handle *h; /** * Pointer kept for the client. */ void *client_info; /** * Metadata to use for the file. */ struct GNUNET_CONTAINER_MetaData *meta; /** * Keywords to use for KBlocks. */ struct GNUNET_FS_Uri *keywords; /** * CHK for this file or directory. NULL if * we have not yet computed it. */ struct GNUNET_FS_Uri *chk_uri; /** * Block options for the file. */ struct GNUNET_FS_BlockOptions bo; /** * At what time did we start this upload? */ struct GNUNET_TIME_Absolute start_time; /** * Under what filename is this struct serialized * (for operational persistence). Should be determined * using 'mktemp'. */ char *serialization; /** * Encoder being used to publish this file. */ struct GNUNET_FS_TreeEncoder *te; /** * Error message (non-NULL if this operation failed). */ char *emsg; /** * Name of the file or directory (must be an absolute path). */ char *filename; /** * Data describing either the file or the directory. */ union { /** * Data for a file. */ struct { /** * Function that can be used to read the data for the file. */ GNUNET_FS_DataReader reader; /** * Closure for reader. */ void *reader_cls; /** * If this file is being indexed, this value is set to the hash * over the entire file (when the indexing process is started). * Otherwise this field is not used. */ struct GNUNET_HashCode file_id; /** * Size of the file (in bytes). */ uint64_t file_size; /** * Should the file be indexed or inserted? */ int do_index; /** * Is "file_id" already valid? Set to #GNUNET_YES once the hash * has been calculated. */ int have_hash; /** * Has the service confirmed our INDEX_START request? * #GNUNET_YES if this step has been completed. */ int index_start_confirmed; } file; /** * Data for a directory. */ struct { /** * Linked list of entries in the directory. */ struct GNUNET_FS_FileInformation *entries; /** * Size of the directory itself (in bytes); 0 if the * size has not yet been calculated. */ size_t dir_size; /** * Pointer to the data for the directory (or NULL if not * available). */ void *dir_data; /** * How much of the directory have we published (relative to @e contents_size). */ uint64_t contents_completed; /** * Sum of all of the sizes of all of the files in the directory. */ uint64_t contents_size; } dir; } data; /** * Is this struct for a file or directory? */ int is_directory; /** * Are we done publishing this file? */ int is_published; }; /** * The job is now ready to run and should use the given client * handle to communicate with the FS service. * * @param cls closure * @param client handle to use for FS communication */ typedef void (*GNUNET_FS_QueueStart) (void *cls, struct GNUNET_CLIENT_Connection * client); /** * The job must now stop to run and should destry the client handle as * soon as possible (ideally prior to returning). */ typedef void (*GNUNET_FS_QueueStop) (void *cls); /** * Priorities for the queue. */ enum GNUNET_FS_QueuePriority { /** * This is a probe (low priority). */ GNUNET_FS_QUEUE_PRIORITY_PROBE, /** * Default priority. */ GNUNET_FS_QUEUE_PRIORITY_NORMAL }; /** * Entry in the job queue. */ struct GNUNET_FS_QueueEntry { /** * This is a linked list. */ struct GNUNET_FS_QueueEntry *next; /** * This is a linked list. */ struct GNUNET_FS_QueueEntry *prev; /** * Function to call when the job is started. */ GNUNET_FS_QueueStart start; /** * Function to call when the job needs to stop (or is done / dequeued). */ GNUNET_FS_QueueStop stop; /** * Closure for start and stop. */ void *cls; /** * Handle to FS primary context. */ struct GNUNET_FS_Handle *h; /** * Client handle, or NULL if job is not running. */ struct GNUNET_CLIENT_Connection *client; /** * Time the job was originally queued. */ struct GNUNET_TIME_Absolute queue_time; /** * Time the job was started last. */ struct GNUNET_TIME_Absolute start_time; /** * Total amount of time the job has been running (except for the * current run). */ struct GNUNET_TIME_Relative run_time; /** * How many blocks do the active downloads have? */ unsigned int blocks; /** * How important is this download? */ enum GNUNET_FS_QueuePriority priority; /** * How often have we (re)started this download? */ unsigned int start_times; }; /** * Information we store for each search result. */ struct GNUNET_FS_SearchResult { /** * File-sharing context this result belongs to. */ struct GNUNET_FS_Handle *h; /** * Search context this result belongs to; can be NULL * for probes that come from a directory result. */ struct GNUNET_FS_SearchContext *sc; /** * URI to which this search result refers to. */ struct GNUNET_FS_Uri *uri; /** * Metadata for the search result. */ struct GNUNET_CONTAINER_MetaData *meta; /** * Client info for this search result. */ void *client_info; /** * ID of a job that is currently probing this results' availability * (NULL if we are not currently probing). */ struct GNUNET_FS_DownloadContext *probe_ctx; /** * ID of an associated download based on this search result (or * NULL for none). */ struct GNUNET_FS_DownloadContext *download; /** * If this search result triggered an update search, this field * links to the update search. */ struct GNUNET_FS_SearchContext *update_search; /** * Name under which this search result is stored on disk. */ char *serialization; /** * Bitmap that specifies precisely which keywords have been matched already. */ uint8_t *keyword_bitmap; /** * Key for the search result */ struct GNUNET_HashCode key; /** * ID of the task that will clean up the probe_ctx should it not * complete on time (and that will need to be cancelled if we clean * up the search result before then). */ GNUNET_SCHEDULER_TaskIdentifier probe_cancel_task; /** * Task we use to report periodically to the application that the * probe is still running. */ GNUNET_SCHEDULER_TaskIdentifier probe_ping_task; /** * When did the current probe become active? */ struct GNUNET_TIME_Absolute probe_active_time; /** * How much longer should we run the current probe before giving up? */ struct GNUNET_TIME_Relative remaining_probe_time; /** * Anonymity level to use for probes using this search result. */ uint32_t anonymity; /** * Number of mandatory keywords for which we have NOT yet found the * search result; when this value hits zero, the search result is * given to the callback. */ uint32_t mandatory_missing; /** * Number of optional keywords under which this result was also * found. */ uint32_t optional_support; /** * Number of availability tests that have succeeded for this result. */ uint32_t availability_success; /** * Number of availability trials that we have performed for this * search result. */ uint32_t availability_trials; }; /** * Add a job to the queue. * * @param h handle to the overall FS state * @param start function to call to begin the job * @param stop function to call to pause the job, or on dequeue (if the job was running) * @param cls closure for start and stop * @param blocks number of blocks this download has * @param priority how important is this download * @return queue handle */ struct GNUNET_FS_QueueEntry * GNUNET_FS_queue_ (struct GNUNET_FS_Handle *h, GNUNET_FS_QueueStart start, GNUNET_FS_QueueStop stop, void *cls, unsigned int blocks, enum GNUNET_FS_QueuePriority priority); /** * Dequeue a job from the queue. * * @param qe handle for the job */ void GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qe); /** * Function that provides data by reading from a file. * * @param cls closure (points to the file information) * @param offset offset to read from; it is possible * that the caller might need to go backwards * a bit at times * @param max maximum number of bytes that should be * copied to buf; readers are not allowed * to provide less data unless there is an error; * a value of "0" will be used at the end to allow * the reader to clean up its internal state * @param buf where the reader should write the data * @param emsg location for the reader to store an error message * @return number of bytes written, usually "max", 0 on error */ size_t GNUNET_FS_data_reader_file_ (void *cls, uint64_t offset, size_t max, void *buf, char **emsg); /** * Create the closure for the 'GNUNET_FS_data_reader_file_' callback. * * @param filename file to read * @return closure to use */ void * GNUNET_FS_make_file_reader_context_ (const char *filename); /** * Function that provides data by copying from a buffer. * * @param cls closure (points to the buffer) * @param offset offset to read from; it is possible * that the caller might need to go backwards * a bit at times * @param max maximum number of bytes that should be * copied to buf; readers are not allowed * to provide less data unless there is an error; * a value of "0" will be used at the end to allow * the reader to clean up its internal state * @param buf where the reader should write the data * @param emsg location for the reader to store an error message * @return number of bytes written, usually "max", 0 on error */ size_t GNUNET_FS_data_reader_copy_ (void *cls, uint64_t offset, size_t max, void *buf, char **emsg); /** * Notification of FS that a search probe has made progress. * This function is used INSTEAD of the client's event handler * for downloads where the GNUNET_FS_DOWNLOAD_IS_PROBE flag is set. * * @param cls closure, always NULL (!), actual closure * is in the client-context of the info struct * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the GNUNET_FS_ProgressInfo struct. */ void * GNUNET_FS_search_probe_progress_ (void *cls, const struct GNUNET_FS_ProgressInfo *info); /** * Main function that performs the upload. * * @param cls "struct GNUNET_FS_PublishContext" identifies the upload * @param tc task context */ void GNUNET_FS_publish_main_ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Function called once the hash of the file * that is being unindexed has been computed. * * @param cls closure, unindex context * @param file_id computed hash, NULL on error */ void GNUNET_FS_unindex_process_hash_ (void *cls, const struct GNUNET_HashCode * file_id); /** * Extract the keywords for KBlock removal * * @param uc context for the unindex operation. */ void GNUNET_FS_unindex_do_extract_keywords_ (struct GNUNET_FS_UnindexContext *uc); /** * If necessary, connect to the datastore and remove the KBlocks. * * @param uc context for the unindex operation. */ void GNUNET_FS_unindex_do_remove_kblocks_ (struct GNUNET_FS_UnindexContext *uc); /** * Fill in all of the generic fields for a publish event and call the * callback. * * @param pi structure to fill in * @param pc overall publishing context * @param p file information for the file being published * @param offset where in the file are we so far * @return value returned from callback */ void * GNUNET_FS_publish_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_PublishContext *pc, const struct GNUNET_FS_FileInformation *p, uint64_t offset); /** * Fill in all of the generic fields for a download event and call the * callback. * * @param pi structure to fill in * @param dc overall download context */ void GNUNET_FS_download_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_DownloadContext *dc); /** * Task that creates the initial (top-level) download * request for the file. * * @param cls the 'struct GNUNET_FS_DownloadContext' * @param tc scheduler context */ void GNUNET_FS_download_start_task_ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Fill in all of the generic fields for * an unindex event and call the callback. * * @param pi structure to fill in * @param uc overall unindex context * @param offset where we are in the file (for progress) */ void GNUNET_FS_unindex_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_UnindexContext *uc, uint64_t offset); /** * Fill in all of the generic fields for a search event and * call the callback. * * @param pi structure to fill in * @param h file-sharing handle * @param sc overall search context * @return value returned by the callback */ void * GNUNET_FS_search_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_Handle *h, struct GNUNET_FS_SearchContext *sc); /** * Connect to the datastore and remove the blocks. * * @param uc context for the unindex operation. */ void GNUNET_FS_unindex_do_remove_ (struct GNUNET_FS_UnindexContext *uc); /** * Build the request and actually initiate the search using the * GNUnet FS service. * * @param sc search context * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc); /** * Start the downloading process (by entering the queue). * * @param dc our download context */ void GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc); /** * Start download probes for the given search result. * * @param sr the search result */ void GNUNET_FS_search_start_probe_ (struct GNUNET_FS_SearchResult *sr); /** * Remove serialization/deserialization file from disk. * * @param h master context * @param ext component of the path * @param ent entity identifier */ void GNUNET_FS_remove_sync_file_ (struct GNUNET_FS_Handle *h, const char *ext, const char *ent); /** * Remove serialization/deserialization directory from disk. * * @param h master context * @param ext component of the path * @param uni unique name of parent */ void GNUNET_FS_remove_sync_dir_ (struct GNUNET_FS_Handle *h, const char *ext, const char *uni); /** * Synchronize this file-information struct with its mirror * on disk. Note that all internal FS-operations that change * file information data should already call "sync" internally, * so this function is likely not useful for clients. * * @param fi the struct to sync */ void GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation *f); /** * Synchronize this publishing struct with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param pc the struct to sync */ void GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext *pc); /** * Synchronize this unindex struct with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param uc the struct to sync */ void GNUNET_FS_unindex_sync_ (struct GNUNET_FS_UnindexContext *uc); /** * Synchronize this search struct with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param sc the struct to sync */ void GNUNET_FS_search_sync_ (struct GNUNET_FS_SearchContext *sc); /** * Synchronize this search result with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param sr the struct to sync */ void GNUNET_FS_search_result_sync_ (struct GNUNET_FS_SearchResult *sr); /** * Synchronize this download struct with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param dc the struct to sync */ void GNUNET_FS_download_sync_ (struct GNUNET_FS_DownloadContext *dc); /** * Create SUSPEND event for the given publish operation * and then clean up our state (without stop signal). * * @param cls the 'struct GNUNET_FS_PublishContext' to signal for */ void GNUNET_FS_publish_signal_suspend_ (void *cls); /** * Create SUSPEND event for the given search operation * and then clean up our state (without stop signal). * * @param cls the 'struct GNUNET_FS_SearchContext' to signal for */ void GNUNET_FS_search_signal_suspend_ (void *cls); /** * Create SUSPEND event for the given download operation * and then clean up our state (without stop signal). * * @param cls the 'struct GNUNET_FS_DownloadContext' to signal for */ void GNUNET_FS_download_signal_suspend_ (void *cls); /** * Create SUSPEND event for the given unindex operation * and then clean up our state (without stop signal). * * @param cls the 'struct GNUNET_FS_UnindexContext' to signal for */ void GNUNET_FS_unindex_signal_suspend_ (void *cls); /** * Function signature of the functions that can be called * to trigger suspend signals and clean-up for top-level * activities. * * @param cls closure */ typedef void (*SuspendSignalFunction) (void *cls); /** * We track all of the top-level activities of FS * so that we can signal 'suspend' on shutdown. */ struct TopLevelActivity { /** * This is a doubly-linked list. */ struct TopLevelActivity *next; /** * This is a doubly-linked list. */ struct TopLevelActivity *prev; /** * Function to call for suspend-signalling and clean up. */ SuspendSignalFunction ssf; /** * Closure for 'ssf' (some struct GNUNET_FS_XXXHandle*) */ void *ssf_cls; }; /** * Create a top-level activity entry. * * @param h global fs handle * @param ssf suspend signal function to use * @param ssf_cls closure for @a ssf * @return fresh top-level activity handle */ struct TopLevelActivity * GNUNET_FS_make_top (struct GNUNET_FS_Handle *h, SuspendSignalFunction ssf, void *ssf_cls); /** * Destroy a top-level activity entry. * * @param h global fs handle * @param top top level activity entry */ void GNUNET_FS_end_top (struct GNUNET_FS_Handle *h, struct TopLevelActivity *top); /** * Master context for most FS operations. */ struct GNUNET_FS_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Name of our client. */ char *client_name; /** * Function to call with updates on our progress. */ GNUNET_FS_ProgressCallback upcb; /** * Closure for upcb. */ void *upcb_cls; /** * Head of DLL of top-level activities. */ struct TopLevelActivity *top_head; /** * Tail of DLL of top-level activities. */ struct TopLevelActivity *top_tail; /** * Head of DLL of running jobs. */ struct GNUNET_FS_QueueEntry *running_head; /** * Tail of DLL of running jobs. */ struct GNUNET_FS_QueueEntry *running_tail; /** * Head of DLL of pending jobs. */ struct GNUNET_FS_QueueEntry *pending_head; /** * Tail of DLL of pending jobs. */ struct GNUNET_FS_QueueEntry *pending_tail; /** * Task that processes the jobs in the running and pending queues * (and moves jobs around as needed). */ GNUNET_SCHEDULER_TaskIdentifier queue_job; /** * Average time we take for a single request to be satisfied. * FIXME: not yet calcualted properly... */ struct GNUNET_TIME_Relative avg_block_latency; /** * How many actual downloads do we have running right now? */ unsigned int active_downloads; /** * How many blocks do the active downloads have? */ unsigned int active_blocks; /** * General flags. */ enum GNUNET_FS_Flags flags; /** * Maximum number of parallel downloads. */ unsigned int max_parallel_downloads; /** * Maximum number of parallel requests. */ unsigned int max_parallel_requests; }; /** * Handle for controlling a publication process. */ struct GNUNET_FS_PublishContext { /** * Handle to the global fs context. */ struct GNUNET_FS_Handle *h; /** * Our top-level activity entry (if we are top-level, otherwise NULL). */ struct TopLevelActivity *top; /** * File-structure that is being shared. */ struct GNUNET_FS_FileInformation *fi; /** * Namespace that we are publishing in, NULL if we have no namespace. */ struct GNUNET_CRYPTO_EcdsaPrivateKey *ns; /** * ID of the content in the namespace, NULL if we have no namespace. */ char *nid; /** * ID for future updates, NULL if we have no namespace or no updates. */ char *nuid; /** * Filename used for serializing information about this operation * (should be determined using 'mktemp'). */ char *serialization; /** * Our own client handle for the FS service; only briefly used when * we start to index a file, otherwise NULL. */ struct GNUNET_CLIENT_Connection *client; /** * Current position in the file-tree for the upload. */ struct GNUNET_FS_FileInformation *fi_pos; /** * Non-null if we are currently hashing a file. */ struct GNUNET_CRYPTO_FileHashContext *fhc; /** * Connection to the datastore service. */ struct GNUNET_DATASTORE_Handle *dsh; /** * Queue entry for reservation/unreservation. */ struct GNUNET_DATASTORE_QueueEntry *qre; /** * Context for SKS publishing operation that is part of this publishing operation * (NULL if not active). */ struct GNUNET_FS_PublishSksContext *sks_pc; /** * Context for KSK publishing operation that is part of this publishing operation * (NULL if not active). */ struct GNUNET_FS_PublishKskContext *ksk_pc; /** * ID of the task performing the upload. NO_TASK if the upload has * completed. */ GNUNET_SCHEDULER_TaskIdentifier upload_task; /** * Storage space to reserve for the operation. */ uint64_t reserve_space; /** * Overall number of entries to reserve for the * publish operation. */ uint32_t reserve_entries; /** * Options for publishing. */ enum GNUNET_FS_PublishOptions options; /** * Space reservation ID with datastore service * for this upload. */ int rid; /** * Set to #GNUNET_YES if all processing has completed. */ int all_done; /** * Flag set to #GNUNET_YES if the next callback from * #GNUNET_FS_file_information_inspect should be skipped because it * is for the directory which was already processed with the parent. */ int skip_next_fi_callback; }; /** * Phases of unindex processing (state machine). */ enum UnindexState { /** * We're currently hashing the file. */ UNINDEX_STATE_HASHING = 0, /** * We're telling the datastore to delete * the respective DBlocks and IBlocks. */ UNINDEX_STATE_DS_REMOVE = 1, /** * Find out which keywords apply. */ UNINDEX_STATE_EXTRACT_KEYWORDS = 2, /** * We're telling the datastore to remove KBlocks. */ UNINDEX_STATE_DS_REMOVE_KBLOCKS = 3, /** * We're notifying the FS service about * the unindexing. */ UNINDEX_STATE_FS_NOTIFY = 4, /** * We're done. */ UNINDEX_STATE_COMPLETE = 5, /** * We've encountered a fatal error. */ UNINDEX_STATE_ERROR = 6 }; /** * Handle for controlling an unindexing operation. */ struct GNUNET_FS_UnindexContext { /** * The content hash key of the last block we processed, will in the * end be set to the CHK from the URI. Used to remove the KBlocks. */ struct ContentHashKey chk; /** * Global FS context. */ struct GNUNET_FS_Handle *h; /** * Our top-level activity entry. */ struct TopLevelActivity *top; /** * Directory scanner to find keywords (KBlock removal). */ struct GNUNET_FS_DirScanner *dscan; /** * Keywords found (telling us which KBlocks to remove). */ struct GNUNET_FS_Uri *ksk_uri; /** * Current offset in KSK removal. */ uint32_t ksk_offset; /** * Name of the file that we are unindexing. */ char *filename; /** * Short name under which we are serializing the state of this operation. */ char *serialization; /** * Connection to the FS service, only valid during the * #UNINDEX_STATE_FS_NOTIFY phase. */ struct GNUNET_CLIENT_Connection *client; /** * Connection to the datastore service, only valid during the * UNINDEX_STATE_DS_NOTIFY phase. */ struct GNUNET_DATASTORE_Handle *dsh; /** * Pointer kept for the client. */ void *client_info; /** * Merkle-ish tree encoder context. */ struct GNUNET_FS_TreeEncoder *tc; /** * Handle used to read the file. */ struct GNUNET_DISK_FileHandle *fh; /** * Handle to datastore 'get_key' operation issued for * obtaining KBlocks. */ struct GNUNET_DATASTORE_QueueEntry *dqe; /** * Current key for decrypting UBLocks from 'get_key' operation. */ struct GNUNET_HashCode ukey; /** * Current query of 'get_key' operation. */ struct GNUNET_HashCode uquery; /** * First content UID, 0 for none. */ uint64_t first_uid; /** * Error message, NULL on success. */ char *emsg; /** * Context for hashing of the file. */ struct GNUNET_CRYPTO_FileHashContext *fhc; /** * Overall size of the file. */ uint64_t file_size; /** * Random offset given to #GNUNET_DATASTORE_get_key. */ uint64_t roff; /** * When did we start? */ struct GNUNET_TIME_Absolute start_time; /** * Hash of the file's contents (once computed). */ struct GNUNET_HashCode file_id; /** * Current operatinonal phase. */ enum UnindexState state; }; /** * Information we keep for each keyword in * a keyword search. */ struct SearchRequestEntry { /** * Hash of the public key, also known as the query. */ struct GNUNET_HashCode uquery; /** * Derived public key, hashes to 'uquery'. */ struct GNUNET_CRYPTO_EcdsaPublicKey dpub; /** * The original keyword, used to derive the * key (for decrypting the UBlock). */ char *keyword; /** * Map that contains a "struct GNUNET_FS_SearchResult" for each result that * was found under this keyword. Note that the entries will point * to the same locations as those in the master result map (in * "struct GNUNET_FS_SearchContext"), so they should not be freed. * The key for each entry is the XOR of the key and query in the CHK * URI (as a unique identifier for the search result). */ struct GNUNET_CONTAINER_MultiHashMap *results; /** * Is this keyword a mandatory keyword * (started with '+')? */ int mandatory; }; /** * Handle for controlling a search. */ struct GNUNET_FS_SearchContext { /** * Handle to the global FS context. */ struct GNUNET_FS_Handle *h; /** * Our top-level activity entry (if we are top-level, otherwise NULL). */ struct TopLevelActivity *top; /** * List of keywords that we're looking for. */ struct GNUNET_FS_Uri *uri; /** * For update-searches, link to the search result that triggered * the update search; otherwise NULL. */ struct GNUNET_FS_SearchResult *psearch_result; /** * Connection to the FS service. */ struct GNUNET_CLIENT_Connection *client; /** * Pointer we keep for the client. */ void *client_info; /** * Name of the file on disk we use for persistence. */ char *serialization; /** * Error message (non-NULL if this operation failed). */ char *emsg; /** * Map that contains a "struct GNUNET_FS_SearchResult" for each result that * was found in the search. The key for each entry is the XOR of * the key and query in the CHK URI (as a unique identifier for the * search result). */ struct GNUNET_CONTAINER_MultiHashMap *master_result_map; /** * Per-keyword information for a keyword search. This array will * have exactly as many entries as there were keywords. */ struct SearchRequestEntry *requests; /** * When did we start? */ struct GNUNET_TIME_Absolute start_time; /** * How long to wait before we try to reconnect to FS service? */ struct GNUNET_TIME_Relative reconnect_backoff; /** * ID of a task that is using this struct and that must be cancelled * when the search is being stopped (if not * #GNUNET_SCHEDULER_NO_TASK). Used for the task that adds some * artificial delay when trying to reconnect to the FS service. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * How many of the entries in the search request * map have been passed to the service so far? */ unsigned int search_request_map_offset; /** * How many of the keywords in the KSK * map have been passed to the service so far? */ unsigned int keyword_offset; /** * Anonymity level for the search. */ uint32_t anonymity; /** * Number of mandatory keywords in this query. */ uint32_t mandatory_count; /** * Options for the search. */ enum GNUNET_FS_SearchOptions options; }; /** * FSM for possible states a block can go through. The typical * order of progression is linear through the states, alternatives * are documented in the comments. */ enum BlockRequestState { /** * Initial state, block has only been allocated (since it is * relevant to the overall download request). */ BRS_INIT = 0, /** * We've checked the block on the path down the tree, and the * content on disk did match the desired CHK, but not all * the way down, so at the bottom some blocks will still * need to be reconstructed). */ BRS_RECONSTRUCT_DOWN = 1, /** * We've calculated the CHK bottom-up based on the meta data. * This may work, but if it did we have to write the meta data to * disk at the end (and we still need to check against the * CHK set on top). */ BRS_RECONSTRUCT_META_UP = 2, /** * We've calculated the CHK bottom-up based on what we have on * disk, which may not be what the desired CHK is. If the * reconstructed CHKs match whatever comes from above, we're * done with the respective subtree. */ BRS_RECONSTRUCT_UP = 3, /** * We've determined the real, desired CHK for this block * (full tree reconstruction failed), request is now pending. * If the CHK that bubbled up through reconstruction did match * the top-level request, the state machine for the subtree * would have moved to BRS_DOWNLOAD_UP. */ BRS_CHK_SET = 4, /** * We've successfully downloaded this block, but the children * still need to be either downloaded or verified (download * request propagates down). If the download fails, the * state machine for this block may move to * BRS_DOWNLOAD_ERROR instead. */ BRS_DOWNLOAD_DOWN = 5, /** * This block and all of its children have been downloaded * successfully (full completion propagates up). */ BRS_DOWNLOAD_UP = 6, /** * We got a block back that matched the query but did not hash to * the key (malicious publisher or hash collision); this block * can never be downloaded (error propagates up). */ BRS_ERROR = 7 }; /** * Information about an active download request. */ struct DownloadRequest { /** * While pending, we keep all download requests in a doubly-linked list. */ struct DownloadRequest *next; /** * While pending, we keep all download requests in a doubly-linked list. */ struct DownloadRequest *prev; /** * Parent in the CHK-tree. */ struct DownloadRequest *parent; /** * Array (!) of child-requests, or NULL for the bottom of the tree. */ struct DownloadRequest **children; /** * CHK for the request for this block (set during reconstruction * to what we have on disk, later to what we want to have). */ struct ContentHashKey chk; /** * Offset of the corresponding block. Specifically, first (!) byte of * the first DBLOCK in the subtree induced by block represented by * this request. */ uint64_t offset; /** * Number of entries in 'children' array. */ unsigned int num_children; /** * Depth of the corresponding block in the tree. 0==DBLOCKs. */ unsigned int depth; /** * Offset of the CHK for this block in the parent block */ unsigned int chk_idx; /** * State in the FSM. */ enum BlockRequestState state; /** * #GNUNET_YES if this entry is in the pending list. */ int is_pending; }; /** * (recursively) free download request structure * * @param dr request to free */ void GNUNET_FS_free_download_request_ (struct DownloadRequest *dr); /** * Context for controlling a download. */ struct GNUNET_FS_DownloadContext { /** * Global FS context. */ struct GNUNET_FS_Handle *h; /** * Our top-level activity entry (if we are top-level, otherwise NULL). */ struct TopLevelActivity *top; /** * Connection to the FS service. */ struct GNUNET_CLIENT_Connection *client; /** * Parent download (used when downloading files * in directories). */ struct GNUNET_FS_DownloadContext *parent; /** * Associated search (used when downloading files * based on search results), or NULL for none. */ struct GNUNET_FS_SearchResult *search; /** * Head of list of child downloads. */ struct GNUNET_FS_DownloadContext *child_head; /** * Tail of list of child downloads. */ struct GNUNET_FS_DownloadContext *child_tail; /** * Previous download belonging to the same parent. */ struct GNUNET_FS_DownloadContext *prev; /** * Next download belonging to the same parent. */ struct GNUNET_FS_DownloadContext *next; /** * Context kept for the client. */ void *client_info; /** * URI that identifies the file that we are downloading. */ struct GNUNET_FS_Uri *uri; /** * Known meta-data for the file (can be NULL). */ struct GNUNET_CONTAINER_MetaData *meta; /** * Error message, NULL if we're doing OK. */ char *emsg; /** * Random portion of filename we use for syncing state of this * download. */ char *serialization; /** * Where are we writing the data (name of the * file, can be NULL!). */ char *filename; /** * Where are we writing the data temporarily (name of the * file, can be NULL!); used if we do not have a permanent * name and we are a directory and we do a recursive download. */ char *temp_filename; /** * Our entry in the job queue. */ struct GNUNET_FS_QueueEntry *job_queue; /** * Non-NULL if we are currently having a request for * transmission pending with the client handle. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Tree encoder used for the reconstruction. */ struct GNUNET_FS_TreeEncoder *te; /** * File handle for reading data from an existing file * (to pass to tree encoder). */ struct GNUNET_DISK_FileHandle *rfh; /** * Map of active requests (those waiting for a response). The key * is the hash of the encryped block (aka query). */ struct GNUNET_CONTAINER_MultiHashMap *active; /** * Head of linked list of pending requests. */ struct DownloadRequest *pending_head; /** * Head of linked list of pending requests. */ struct DownloadRequest *pending_tail; /** * Top-level download request. */ struct DownloadRequest *top_request; /** * Identity of the peer having the content, or all-zeros * if we don't know of such a peer. */ struct GNUNET_PeerIdentity target; /** * ID of a task that is using this struct and that must be cancelled * when the download is being stopped (if not * GNUNET_SCHEDULER_NO_TASK). Used for the task that adds some * artificial delay when trying to reconnect to the FS service or * the task processing incrementally the data on disk, or the * task requesting blocks, etc. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * What is the first offset that we're interested * in? */ uint64_t offset; /** * How many bytes starting from offset are desired? * This is NOT the overall length of the file! */ uint64_t length; /** * How many bytes have we already received within * the specified range (DBlocks only). */ uint64_t completed; /** * What was the size of the file on disk that we're downloading * before we started? Used to detect if there is a point in * checking an existing block on disk for matching the desired * content. 0 if the file did not exist already. */ uint64_t old_file_size; /** * Time download was started. */ struct GNUNET_TIME_Absolute start_time; /** * How long to wait before we try to reconnect to FS service? */ struct GNUNET_TIME_Relative reconnect_backoff; /** * Desired level of anonymity. */ uint32_t anonymity; /** * The depth of the file-tree. */ unsigned int treedepth; /** * Options for the download. */ enum GNUNET_FS_DownloadOptions options; /** * Flag set upon transitive completion (includes child downloads). * This flag is only set to #GNUNET_YES for directories where all * child-downloads have also completed (and signalled completion). */ int has_finished; /** * Have we started the receive continuation yet? */ int in_receive; /** * Are we ready to issue requests (reconstructions are finished)? */ int issue_requests; }; #endif /* end of fs_api.h */ gnunet-0.10.1/src/fs/perf_gnunet_service_fs_p2p_respect.c0000644000175000017500000003070512255010511020404 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/perf_gnunet_service_fs_p2p_respect.c * @brief profile P2P routing respect mechanism. Creates * a clique of NUM_DAEMONS (i.e. 3) where two * peers share (seed) different files and download * them from each other while all the other peers * just "leach" those files. Ideally, the seeders * "learn" that they contribute (to each other), * and give the other seeder higher priority; * naturally, this only happens nicely for larger * files; finally, once the seeders are done, the * leachers should see fast download rates as well. * @author Christian Grothoff * * Sample output: * - 10 MB, 3 peers, with delays: * Download speed of type `seeder 1' was 757 KiB/s * Download speed of type `seeder 2' was 613 KiB/s * Download speed of type `leach` was 539 KiB/s * * - 10 MB, 3 peers, without delays: * Download speed of type `seeder 1' was 1784 KiB/s * Download speed of type `seeder 2' was 1604 KiB/s * Download speed of type `leach` was 1384 KiB/s */ #include "platform.h" #include "fs_test_lib.h" #include "gnunet_testbed_service.h" #define VERBOSE GNUNET_NO /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 1) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) /** * Number of daemons in clique, must be at least 3 (!). */ #define NUM_DAEMONS 3 /** * Seed for first file on offer. */ #define SEED1 42 /** * Seed for second file on offer. */ #define SEED2 43 static struct GNUNET_TESTBED_Peer *daemons[NUM_DAEMONS]; static int ok; static struct GNUNET_TIME_Absolute start_time; static const char *progname; static struct GNUNET_FS_Uri *uri1; static struct GNUNET_FS_Uri *uri2; static char *fn1; static char *fn2; /** * Master context for 'stat_run'. */ struct StatMaster { struct GNUNET_STATISTICS_Handle *stat; struct GNUNET_TESTBED_Operation *op; unsigned int daemon; unsigned int value; }; struct StatValues { const char *subsystem; const char *name; }; /** * Statistics we print out. */ static struct StatValues stats[] = { {"fs", "# artificial delays introduced (ms)"}, {"fs", "# queries forwarded"}, {"fs", "# replies received and matched"}, {"fs", "# results found locally"}, {"fs", "# requests forwarded due to high load"}, {"fs", "# requests done for free (low load)"}, {"fs", "# requests dropped, priority insufficient"}, {"fs", "# requests done for a price (normal load)"}, {"fs", "# requests dropped by datastore (queue length limit)"}, {"fs", "# P2P searches received"}, {"fs", "# P2P searches discarded (queue length bound)"}, {"fs", "# replies received for local clients"}, {"fs", "# queries retransmitted to same target"}, {"core", "# bytes decrypted"}, {"core", "# bytes encrypted"}, {"core", "# discarded CORE_SEND requests"}, {"core", "# discarded lower priority CORE_SEND requests"}, {"transport", "# bytes received via TCP"}, {"transport", "# bytes transmitted via TCP"}, {"datacache", "# bytes stored"}, {NULL, NULL} }; static void cleanup () { GNUNET_SCHEDULER_shutdown (); if (NULL != fn1) { GNUNET_DISK_directory_remove (fn1); GNUNET_free (fn1); } if (NULL != fn2) { GNUNET_DISK_directory_remove (fn2); GNUNET_free (fn2); } } /** * Callback function to process statistic values. * * @param cls closure * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int print_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { struct StatMaster *sm = cls; FPRINTF (stderr, "Peer %2u: %12s/%50s = %12llu\n", sm->daemon, subsystem, name, (unsigned long long) value); return GNUNET_OK; } /** * Function that gathers stats from all daemons. */ static void stat_run (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg); /** * Function called when GET operation on stats is done. */ static void get_done (void *cls, int success) { struct StatMaster *sm = cls; GNUNET_break (GNUNET_OK == success); sm->value++; stat_run (sm, sm->op, sm->stat, NULL); } /** * Adapter function called to establish a connection to * statistics service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * statistics_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_STATISTICS_create ("", cfg); } /** * Adapter function called to destroy a connection to * statistics service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void statistics_disconnect_adapter (void *cls, void *op_result) { GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); } /** * Function that gathers stats from all daemons. */ static void stat_run (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct StatMaster *sm = cls; sm->stat = ca_result; GNUNET_assert (NULL != sm->stat); if (NULL != stats[sm->value].name) { GNUNET_STATISTICS_get (sm->stat, #if 0 NULL, NULL, #else stats[sm->value].subsystem, stats[sm->value].name, #endif GNUNET_TIME_UNIT_FOREVER_REL, &get_done, &print_stat, sm); return; } GNUNET_TESTBED_operation_done (sm->op); sm->value = 0; sm->daemon++; if (NUM_DAEMONS == sm->daemon) { GNUNET_free (sm); cleanup (); return; } sm->op = GNUNET_TESTBED_service_connect (NULL, daemons[sm->daemon], "statistics", &stat_run, sm, &statistics_connect_adapter, &statistics_disconnect_adapter, NULL); } static void do_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static int download_counter; const char *type = cls; struct GNUNET_TIME_Relative del; char *fancy; struct StatMaster *sm; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout during download for type `%s', shutting down with error\n", type); ok = 1; cleanup (); return; } del = GNUNET_TIME_absolute_get_duration (start_time); if (del.rel_value_us == 0) del.rel_value_us = 1; fancy = GNUNET_STRINGS_byte_size_fancy (((unsigned long long) FILESIZE) * 1000000LL / del.rel_value_us); FPRINTF (stderr, "Download speed of type `%s' was %s/s\n", type, fancy); GNUNET_free (fancy); if (NUM_DAEMONS != ++download_counter) return; /* more downloads to come */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished all downloads, getting statistics\n"); sm = GNUNET_new (struct StatMaster); sm->op = GNUNET_TESTBED_service_connect (NULL, daemons[sm->daemon], "statistics", &stat_run, sm, &statistics_connect_adapter, &statistics_disconnect_adapter, NULL); } static void do_downloads (void *cls, const struct GNUNET_FS_Uri *u2, const char *fn) { int anonymity; unsigned int i; if (NULL == u2) { cleanup (); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout during upload attempt, shutting down with error\n"); ok = 1; return; } if (NULL != fn) fn2 = GNUNET_strdup (fn); uri2 = GNUNET_FS_uri_dup (u2); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Downloading %llu bytes\n", (unsigned long long) FILESIZE); start_time = GNUNET_TIME_absolute_get (); if (NULL != strstr (progname, "dht")) anonymity = 0; else anonymity = 1; /* (semi) leach-download(s); not true leaches since * these peers do participate in sharing, they just * don't have to offer anything *initially*. */ for (i = 0; i < NUM_DAEMONS - 2; i++) GNUNET_FS_TEST_download (daemons[i], TIMEOUT, anonymity, 0 == (i % 2) ? SEED1 : SEED2, 0 == (i % 2) ? uri1 : uri2, VERBOSE, &do_report, "leach"); /* mutual downloads of (primary) sharing peers */ GNUNET_FS_TEST_download (daemons[NUM_DAEMONS - 2], TIMEOUT, anonymity, SEED1, uri1, VERBOSE, &do_report, "seeder 2"); GNUNET_FS_TEST_download (daemons[NUM_DAEMONS - 1], TIMEOUT, anonymity, SEED2, uri2, VERBOSE, &do_report, "seeder 1"); } static void do_publish2 (void *cls, const struct GNUNET_FS_Uri *u1, const char *fn) { int do_index; int anonymity; if (NULL == u1) { cleanup (); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout during upload attempt, shutting down with error\n"); ok = 1; return; } if (NULL != fn) fn1 = GNUNET_strdup (fn); uri1 = GNUNET_FS_uri_dup (u1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing %llu bytes\n", (unsigned long long) FILESIZE); if (NULL != strstr (progname, "index")) do_index = GNUNET_YES; else do_index = GNUNET_NO; if (NULL != strstr (progname, "dht")) anonymity = 0; else anonymity = 1; GNUNET_FS_TEST_publish (daemons[NUM_DAEMONS - 2], TIMEOUT, anonymity, do_index, FILESIZE, SEED2, VERBOSE, &do_downloads, NULL); } static void do_publish1 (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { unsigned int *coco = cls; int do_index; int anonymity; GNUNET_TESTBED_operation_done (op); if (NULL != emsg) { cleanup (); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error trying to connect: %s\n", emsg); ok = 1; return; } if (0 != (--(*coco))) return; /* more connections to be created */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing %llu bytes\n", (unsigned long long) FILESIZE); if (NULL != strstr (progname, "index")) do_index = GNUNET_YES; else do_index = GNUNET_NO; if (NULL != strstr (progname, "dht")) anonymity = 0; else anonymity = 1; GNUNET_FS_TEST_publish (daemons[NUM_DAEMONS - 1], TIMEOUT, anonymity, do_index, FILESIZE, SEED1, VERBOSE, &do_publish2, NULL); } static void do_connect (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { static unsigned int coco; unsigned int i; unsigned int j; GNUNET_assert (NUM_DAEMONS == num_peers); for (i=0;iclient != client)) pos = pos->next; if (NULL != pos) return pos; pos = GNUNET_new (struct GSF_LocalClient); pos->client = client; GNUNET_CONTAINER_DLL_insert (client_head, client_tail, pos); return pos; } /** * Free the given client request. * * @param cls the client request to free * @param tc task context */ static void client_request_destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ClientRequest *cr = cls; struct GSF_LocalClient *lc; cr->kill_task = GNUNET_SCHEDULER_NO_TASK; lc = cr->lc; GNUNET_CONTAINER_DLL_remove (lc->cr_head, lc->cr_tail, cr); GSF_pending_request_cancel_ (cr->pr, GNUNET_YES); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# client searches active"), -1, GNUNET_NO); GNUNET_free (cr); } /** * Handle a reply to a pending request. Also called if a request * expires (then with data == NULL). The handler may be called * many times (depending on the request type), but will not be * called during or after a call to GSF_pending_request_cancel * and will also not be called anymore after a call signalling * expiration. * * @param cls user-specified closure * @param eval evaluation of the result * @param pr handle to the original pending request * @param reply_anonymity_level anonymity level for the reply, UINT32_MAX for "unknown" * @param expiration when does 'data' expire? * @param last_transmission when was the last time we've tried to download this block? (FOREVER if unknown) * @param type type of the block * @param data response data, NULL on request expiration * @param data_len number of bytes in data */ static void client_response_handler (void *cls, enum GNUNET_BLOCK_EvaluationResult eval, struct GSF_PendingRequest *pr, uint32_t reply_anonymity_level, struct GNUNET_TIME_Absolute expiration, struct GNUNET_TIME_Absolute last_transmission, enum GNUNET_BLOCK_Type type, const void *data, size_t data_len) { struct ClientRequest *cr = cls; struct GSF_LocalClient *lc; struct ClientPutMessage *pm; const struct GSF_PendingRequestData *prd; size_t msize; if (NULL == data) { /* ugh, request 'timed out' -- how can this be? */ GNUNET_break (0); return; } prd = GSF_pending_request_get_data_ (pr); GNUNET_break (type != GNUNET_BLOCK_TYPE_ANY); if ((prd->type != type) && (prd->type != GNUNET_BLOCK_TYPE_ANY)) { GNUNET_break (0); return; } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies received for local clients"), 1, GNUNET_NO); GNUNET_assert (pr == cr->pr); lc = cr->lc; msize = sizeof (struct ClientPutMessage) + data_len; { char buf[msize] GNUNET_ALIGN; pm = (struct ClientPutMessage *) buf; pm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT); pm->header.size = htons (msize); pm->type = htonl (type); pm->expiration = GNUNET_TIME_absolute_hton (expiration); pm->last_transmission = GNUNET_TIME_absolute_hton (last_transmission); pm->num_transmissions = htonl (prd->num_transmissions); pm->respect_offered = htonl (prd->respect_offered); memcpy (&pm[1], data, data_len); GSF_local_client_transmit_ (lc, &pm->header); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queued reply to query `%s' for local client\n", GNUNET_h2s (&prd->query), (unsigned int) prd->type); if (GNUNET_BLOCK_EVALUATION_OK_LAST != eval) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Evaluation %d - keeping query alive\n", (int) eval); return; } if (GNUNET_SCHEDULER_NO_TASK == cr->kill_task) cr->kill_task = GNUNET_SCHEDULER_add_now (&client_request_destroy, cr); } /** * Handle START_SEARCH-message (search request from local client). * Only responsible for creating the request entry itself and setting * up reply callback and cancellation on client disconnect. Does NOT * execute the actual request strategy (planning). * * @param client identification of the client * @param message the actual message * @param prptr where to store the pending request handle for the request * @return #GNUNET_YES to start local processing, * #GNUNET_NO to not (yet) start local processing, * #GNUNET_SYSERR on error */ int GSF_local_client_start_search_handler_ (struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message, struct GSF_PendingRequest **prptr) { static struct GNUNET_PeerIdentity all_zeros; const struct SearchMessage *sm; struct GSF_LocalClient *lc; struct ClientRequest *cr; struct GSF_PendingRequestData *prd; uint16_t msize; unsigned int sc; enum GNUNET_BLOCK_Type type; enum GSF_PendingRequestOptions options; msize = ntohs (message->size); if ((msize < sizeof (struct SearchMessage)) || (0 != (msize - sizeof (struct SearchMessage)) % sizeof (struct GNUNET_HashCode))) { GNUNET_break (0); *prptr = NULL; return GNUNET_SYSERR; } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# client searches received"), 1, GNUNET_NO); sc = (msize - sizeof (struct SearchMessage)) / sizeof (struct GNUNET_HashCode); sm = (const struct SearchMessage *) message; type = ntohl (sm->type); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request for `%s' of type %u from local client\n", GNUNET_h2s (&sm->query), (unsigned int) type); lc = GSF_local_client_lookup_ (client); cr = NULL; /* detect duplicate UBLOCK requests */ if ((type == GNUNET_BLOCK_TYPE_FS_UBLOCK) || (type == GNUNET_BLOCK_TYPE_ANY)) { cr = lc->cr_head; while (NULL != cr) { prd = GSF_pending_request_get_data_ (cr->pr); /* only unify with queries that hae not yet started local processing (SEARCH_MESSAGE_OPTION_CONTINUED was always set) and that have a matching query and type */ if ((GNUNET_YES != prd->has_started) && (0 != memcmp (&prd->query, &sm->query, sizeof (struct GNUNET_HashCode))) && (prd->type == type)) break; cr = cr->next; } } if (NULL != cr) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have existing request, merging content-seen lists.\n"); GSF_pending_request_update_ (cr->pr, (const struct GNUNET_HashCode *) &sm[1], sc); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# client searches updated (merged content seen list)"), 1, GNUNET_NO); } else { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# client searches active"), 1, GNUNET_NO); cr = GNUNET_new (struct ClientRequest); cr->lc = lc; GNUNET_CONTAINER_DLL_insert (lc->cr_head, lc->cr_tail, cr); options = GSF_PRO_LOCAL_REQUEST; if (0 != (SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY & ntohl (sm->options))) options |= GSF_PRO_LOCAL_ONLY; cr->pr = GSF_pending_request_create_ (options, type, &sm->query, (0 != memcmp (&sm->target, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) ? &sm->target : NULL, NULL, 0, 0 /* bf */ , ntohl (sm->anonymity_level), 0 /* priority */ , 0 /* ttl */ , 0 /* sender PID */ , 0 /* origin PID */ , (const struct GNUNET_HashCode *) &sm[1], sc, &client_response_handler, cr); } *prptr = cr->pr; return (0 != (SEARCH_MESSAGE_OPTION_CONTINUED & ntohl (sm->options))) ? GNUNET_NO : GNUNET_YES; } /** * Transmit the given message by copying it to the target buffer * "buf". "buf" will be NULL and "size" zero if the socket was closed * for writing in the meantime. In that case, do nothing * (the disconnect or shutdown handler will take care of the rest). * If we were able to transmit messages and there are still more * pending, ask core again for further calls to this function. * * @param cls closure, pointer to the 'struct GSF_LocalClient' * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_to_client (void *cls, size_t size, void *buf) { struct GSF_LocalClient *lc = cls; char *cbuf = buf; struct ClientResponse *res; size_t msize; lc->th = NULL; if (NULL == buf) return 0; msize = 0; while ((NULL != (res = lc->res_head)) && (res->msize <= size)) { memcpy (&cbuf[msize], &res[1], res->msize); msize += res->msize; size -= res->msize; GNUNET_CONTAINER_DLL_remove (lc->res_head, lc->res_tail, res); GNUNET_free (res); } if (NULL != res) lc->th = GNUNET_SERVER_notify_transmit_ready (lc->client, res->msize, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_to_client, lc); return msize; } /** * Transmit a message to the given local client as soon as possible. * If the client disconnects before transmission, the message is * simply discarded. * * @param lc recipient * @param msg message to transmit to client */ void GSF_local_client_transmit_ (struct GSF_LocalClient *lc, const struct GNUNET_MessageHeader *msg) { struct ClientResponse *res; size_t msize; msize = ntohs (msg->size); res = GNUNET_malloc (sizeof (struct ClientResponse) + msize); res->lc = lc; res->msize = msize; memcpy (&res[1], msg, msize); GNUNET_CONTAINER_DLL_insert_tail (lc->res_head, lc->res_tail, res); if (NULL == lc->th) lc->th = GNUNET_SERVER_notify_transmit_ready (lc->client, msize, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_to_client, lc); } /** * A client disconnected from us. Tear down the local client * record. * * @param cls unused * @param client handle of the client */ void GSF_client_disconnect_handler_ (void *cls, struct GNUNET_SERVER_Client *client) { struct GSF_LocalClient *pos; struct ClientRequest *cr; struct ClientResponse *res; pos = client_head; while ((pos != NULL) && (pos->client != client)) pos = pos->next; if (NULL == pos) return; while (NULL != (cr = pos->cr_head)) { if (GNUNET_SCHEDULER_NO_TASK != cr->kill_task) GNUNET_SCHEDULER_cancel (cr->kill_task); client_request_destroy (cr, NULL); } while (NULL != (res = pos->res_head)) { GNUNET_CONTAINER_DLL_remove (pos->res_head, pos->res_tail, res); GNUNET_free (res); } if (NULL != pos->th) { GNUNET_SERVER_notify_transmit_ready_cancel (pos->th); pos->th = NULL; } GSF_handle_local_client_disconnect_ (pos); GNUNET_CONTAINER_DLL_remove (client_head, client_tail, pos); GNUNET_free (pos); } /* end of gnunet-service-fs_lc.c */ gnunet-0.10.1/src/fs/gnunet-service-fs_put.h0000644000175000017500000000224012225777503015626 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_put.h * @brief support for putting content into the DHT * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_FS_PUT_H #define GNUNET_SERVICE_FS_PUT_H #include "gnunet-service-fs.h" /** * Setup the module. */ void GSF_put_init_ (void); /** * Shutdown the module. */ void GSF_put_done_ (void); #endif gnunet-0.10.1/src/fs/test_fs_unindex_persistence.c0000644000175000017500000002251412226006662017170 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2008, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_unindex_persistence.c * @brief simple testcase for simple publish + unindex operation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_fs_service.h" /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 2) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static struct GNUNET_TIME_Absolute start; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_UnindexContext *unindex; static struct GNUNET_FS_PublishContext *publish; static char *fn; static const struct GNUNET_CONFIGURATION_Handle *cfg; static void abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_publish_stop (publish); publish = NULL; } static void abort_unindex_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (unindex != NULL) { GNUNET_FS_unindex_stop (unindex); unindex = NULL; } if (fn != NULL) { GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); fn = NULL; } } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event); static void restart_fs_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_stop (fs); fs = GNUNET_FS_start (cfg, "test-fs-unindex-persistence", &progress_cb, NULL, GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END); } /** * Consider scheduling the restart-task. * Only runs the restart task once per event * category. * * @param ev type of the event to consider */ static void consider_restart (int ev) { static int prev[32]; static int off; int i; for (i = 0; i < off; i++) if (prev[i] == ev) return; prev[off++] = ev; GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_URGENT, &restart_fs_task, NULL); } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_PROGRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: printf ("Publishing complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); start = GNUNET_TIME_absolute_get (); unindex = GNUNET_FS_unindex_start (fs, fn, "unindex"); GNUNET_assert (unindex != NULL); break; case GNUNET_FS_STATUS_UNINDEX_COMPLETED: printf ("Unindex complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); GNUNET_SCHEDULER_add_continuation (&abort_unindex_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_UNINDEX_PROGRESS: consider_restart (event->status); GNUNET_assert (unindex == event->value.unindex.uc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unindex is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.unindex.completed, (unsigned long long) event->value.unindex.size, event->value.unindex.specifics.progress.depth, (unsigned long long) event->value.unindex.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_SUSPEND: if (event->value.publish.pc == publish) publish = NULL; break; case GNUNET_FS_STATUS_PUBLISH_RESUME: if (NULL == publish) { publish = event->value.publish.pc; return "publish-context"; } break; case GNUNET_FS_STATUS_UNINDEX_SUSPEND: GNUNET_assert (event->value.unindex.uc == unindex); unindex = NULL; break; case GNUNET_FS_STATUS_UNINDEX_RESUME: GNUNET_assert (NULL == unindex); unindex = event->value.unindex.uc; return "unindex"; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); GNUNET_break (0); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_UNINDEX_ERROR: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error unindexing file: %s\n", event->value.unindex.specifics.error.message); GNUNET_SCHEDULER_add_continuation (&abort_unindex_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_START: GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); GNUNET_assert (NULL == event->value.publish.pctx); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_assert (publish == event->value.publish.pc); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (1 == event->value.publish.anonymity); GNUNET_FS_stop (fs); fs = NULL; break; case GNUNET_FS_STATUS_UNINDEX_START: consider_restart (event->status); GNUNET_assert (unindex == NULL); GNUNET_assert (0 == strcmp ("unindex", event->value.unindex.cctx)); GNUNET_assert (0 == strcmp (fn, event->value.unindex.filename)); GNUNET_assert (FILESIZE == event->value.unindex.size); GNUNET_assert (0 == event->value.unindex.completed); break; case GNUNET_FS_STATUS_UNINDEX_STOPPED: GNUNET_assert (unindex == event->value.unindex.uc); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; default: printf ("Unexpected event: %d\n", event->status); break; } return NULL; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar", }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi; size_t i; struct GNUNET_FS_BlockOptions bo; cfg = c; fn = GNUNET_DISK_mktemp ("gnunet-unindex-test-dst"); fs = GNUNET_FS_start (cfg, "test-fs-unindex-persistence", &progress_cb, NULL, GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi = GNUNET_FS_file_information_create_from_file (fs, "publish-context", fn, kuri, meta, GNUNET_YES, &bo); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fi); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-unindex-persistence", "test_fs_unindex_data.conf", &run, NULL)) return 1; return 0; } /* end of test_fs_unindex_persistence.c */ gnunet-0.10.1/src/fs/fs_dirmetascan.c0000644000175000017500000003107612255010511014336 00000000000000/* This file is part of GNUnet (C) 2005-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_dirmetascan.c * @brief code to asynchronously build a 'struct GNUNET_FS_ShareTreeItem' * from an on-disk directory for publishing; use the 'gnunet-helper-fs-publish'. * @author LRN * @author Christian Grothoff */ #include "platform.h" #include "gnunet_fs_service.h" #include "gnunet_scheduler_lib.h" #include /** * An opaque structure a pointer to which is returned to the * caller to be used to control the scanner. */ struct GNUNET_FS_DirScanner { /** * Helper process. */ struct GNUNET_HELPER_Handle *helper; /** * Expanded filename (as given by the scan initiator). * The scanner thread stores a copy here, and frees it when it finishes. */ char *filename_expanded; /** * Second argument to helper process. */ char *ex_arg; /** * The function that will be called every time there's a progress * message. */ GNUNET_FS_DirScannerProgressCallback progress_callback; /** * A closure for progress_callback. */ void *progress_callback_cls; /** * After the scan is finished, it will contain a pointer to the * top-level directory entry in the directory tree built by the * scanner. */ struct GNUNET_FS_ShareTreeItem *toplevel; /** * Current position during processing. */ struct GNUNET_FS_ShareTreeItem *pos; /** * Task scheduled when we are done. */ GNUNET_SCHEDULER_TaskIdentifier stop_task; /** * Arguments for helper. */ char *args[4]; }; /** * Abort the scan. Must not be called from within the progress_callback * function. * * @param ds directory scanner structure */ void GNUNET_FS_directory_scan_abort (struct GNUNET_FS_DirScanner *ds) { /* terminate helper */ if (NULL != ds->helper) GNUNET_HELPER_stop (ds->helper, GNUNET_NO); /* free resources */ if (NULL != ds->toplevel) GNUNET_FS_share_tree_free (ds->toplevel); if (GNUNET_SCHEDULER_NO_TASK != ds->stop_task) GNUNET_SCHEDULER_cancel (ds->stop_task); GNUNET_free_non_null (ds->ex_arg); GNUNET_free (ds->filename_expanded); GNUNET_free (ds); } /** * Obtain the result of the scan after the scan has signalled * completion. Must not be called prior to completion. The 'ds' is * freed as part of this call. * * @param ds directory scanner structure * @return the results of the scan (a directory tree) */ struct GNUNET_FS_ShareTreeItem * GNUNET_FS_directory_scan_get_result (struct GNUNET_FS_DirScanner *ds) { struct GNUNET_FS_ShareTreeItem *result; /* check that we're actually done */ GNUNET_assert (NULL == ds->helper); /* preserve result */ result = ds->toplevel; ds->toplevel = NULL; GNUNET_FS_directory_scan_abort (ds); return result; } /** * Move in the directory from the given position to the next file * in DFS traversal. * * @param pos current position * @return next file, NULL for none */ static struct GNUNET_FS_ShareTreeItem * advance (struct GNUNET_FS_ShareTreeItem *pos) { int moved; GNUNET_assert (NULL != pos); moved = 0; /* must not terminate, even on file, otherwise "normal" */ while ( (pos->is_directory == GNUNET_YES) || (0 == moved) ) { if ( (moved != -1) && (NULL != pos->children_head) ) { pos = pos->children_head; moved = 1; /* can terminate if file */ continue; } if (NULL != pos->next) { pos = pos->next; moved = 1; /* can terminate if file */ continue; } if (NULL != pos->parent) { pos = pos->parent; moved = -1; /* force move to 'next' or 'parent' */ continue; } /* no more options, end of traversal */ return NULL; } return pos; } /** * Add another child node to the tree. * * @param parent parent of the child, NULL for top level * @param filename name of the file or directory * @param is_directory GNUNET_YES for directories * @return new entry that was just created */ static struct GNUNET_FS_ShareTreeItem * expand_tree (struct GNUNET_FS_ShareTreeItem *parent, const char *filename, int is_directory) { struct GNUNET_FS_ShareTreeItem *chld; size_t slen; chld = GNUNET_new (struct GNUNET_FS_ShareTreeItem); chld->parent = parent; chld->filename = GNUNET_strdup (filename); GNUNET_asprintf (&chld->short_filename, "%s%s", GNUNET_STRINGS_get_short_name (filename), is_directory == GNUNET_YES ? "/" : ""); /* make sure we do not end with '//' */ slen = strlen (chld->short_filename); if ( (slen >= 2) && (chld->short_filename[slen-1] == '/') && (chld->short_filename[slen-2] == '/') ) chld->short_filename[slen-1] = '\0'; chld->is_directory = is_directory; if (NULL != parent) GNUNET_CONTAINER_DLL_insert (parent->children_head, parent->children_tail, chld); return chld; } /** * Task run last to shut everything down. * * @param cls the 'struct GNUNET_FS_DirScanner' * @param tc unused */ static void finish_scan (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_DirScanner *ds = cls; ds->stop_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != ds->helper) { GNUNET_HELPER_stop (ds->helper, GNUNET_NO); ds->helper = NULL; } ds->progress_callback (ds->progress_callback_cls, NULL, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_FINISHED); } /** * Called every time there is data to read from the scanner. * Calls the scanner progress handler. * * @param cls the closure (directory scanner object) * @param client always NULL * @param msg message from the helper process */ static int process_helper_msgs (void *cls, void *client, const struct GNUNET_MessageHeader *msg) { struct GNUNET_FS_DirScanner *ds = cls; const char *filename; size_t left; #if 0 fprintf (stderr, "DMS parses %u-byte message of type %u\n", (unsigned int) ntohs (msg->size), (unsigned int) ntohs (msg->type)); #endif left = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader); filename = (const char*) &msg[1]; switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE: if (filename[left-1] != '\0') { GNUNET_break (0); break; } ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_NO, GNUNET_FS_DIRSCANNER_FILE_START); if (NULL == ds->toplevel) ds->toplevel = expand_tree (ds->pos, filename, GNUNET_NO); else (void) expand_tree (ds->pos, filename, GNUNET_NO); return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY: if (filename[left-1] != '\0') { GNUNET_break (0); break; } if (0 == strcmp ("..", filename)) { if (NULL == ds->pos) { GNUNET_break (0); break; } ds->pos = ds->pos->parent; return GNUNET_OK; } ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_YES, GNUNET_FS_DIRSCANNER_FILE_START); ds->pos = expand_tree (ds->pos, filename, GNUNET_YES); if (NULL == ds->toplevel) ds->toplevel = ds->pos; return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR: break; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE: if ('\0' != filename[left-1]) break; ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_FILE_IGNORED); return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE: if (0 != left) { GNUNET_break (0); break; } if (NULL == ds->toplevel) { GNUNET_break (0); break; } ds->progress_callback (ds->progress_callback_cls, NULL, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_ALL_COUNTED); ds->pos = ds->toplevel; if (GNUNET_YES == ds->pos->is_directory) ds->pos = advance (ds->pos); return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA: { size_t nlen; const char *end; if (NULL == ds->pos) { GNUNET_break (0); break; } end = memchr (filename, 0, left); if (NULL == end) { GNUNET_break (0); break; } end++; nlen = end - filename; left -= nlen; if (0 != strcmp (filename, ds->pos->filename)) { GNUNET_break (0); break; } ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_YES, GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED); if (0 < left) { ds->pos->meta = GNUNET_CONTAINER_meta_data_deserialize (end, left); if (NULL == ds->pos->meta) { GNUNET_break (0); break; } /* having full filenames is too dangerous; always make sure we clean them up */ GNUNET_CONTAINER_meta_data_delete (ds->pos->meta, EXTRACTOR_METATYPE_FILENAME, NULL, 0); /* instead, put in our 'safer' original filename */ GNUNET_CONTAINER_meta_data_insert (ds->pos->meta, "", EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", ds->pos->short_filename, strlen (ds->pos->short_filename) + 1); } ds->pos->ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (ds->pos->meta); ds->pos = advance (ds->pos); return GNUNET_OK; } case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED: if (NULL != ds->pos) { GNUNET_break (0); break; } if (0 != left) { GNUNET_break (0); break; } if (NULL == ds->toplevel) { GNUNET_break (0); break; } ds->stop_task = GNUNET_SCHEDULER_add_now (&finish_scan, ds); return GNUNET_OK; default: GNUNET_break (0); break; } ds->progress_callback (ds->progress_callback_cls, NULL, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); return GNUNET_OK; } /** * Function called if our helper process died. * * @param cls the 'struct GNUNET_FS_DirScanner' callback. */ static void helper_died_cb (void *cls) { struct GNUNET_FS_DirScanner *ds = cls; ds->helper = NULL; if (GNUNET_SCHEDULER_NO_TASK != ds->stop_task) return; /* normal death, was finished */ ds->progress_callback (ds->progress_callback_cls, NULL, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); } /** * Start a directory scanner thread. * * @param filename name of the directory to scan * @param disable_extractor #GNUNET_YES to not to run libextractor on files (only build a tree) * @param ex if not NULL, must be a list of extra plugins for extractor * @param cb the callback to call when there are scanning progress messages * @param cb_cls closure for 'cb' * @return directory scanner object to be used for controlling the scanner */ struct GNUNET_FS_DirScanner * GNUNET_FS_directory_scan_start (const char *filename, int disable_extractor, const char *ex, GNUNET_FS_DirScannerProgressCallback cb, void *cb_cls) { struct stat sbuf; char *filename_expanded; struct GNUNET_FS_DirScanner *ds; if (0 != STAT (filename, &sbuf)) return NULL; filename_expanded = GNUNET_STRINGS_filename_expand (filename); if (NULL == filename_expanded) return NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to scan directory `%s'\n", filename_expanded); ds = GNUNET_new (struct GNUNET_FS_DirScanner); ds->progress_callback = cb; ds->progress_callback_cls = cb_cls; ds->filename_expanded = filename_expanded; if (disable_extractor) ds->ex_arg = GNUNET_strdup ("-"); else ds->ex_arg = (NULL != ex) ? GNUNET_strdup (ex) : NULL; ds->args[0] = "gnunet-helper-fs-publish"; ds->args[1] = ds->filename_expanded; ds->args[2] = ds->ex_arg; ds->args[3] = NULL; ds->helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-fs-publish", ds->args, &process_helper_msgs, &helper_died_cb, ds); if (NULL == ds->helper) { GNUNET_free (filename_expanded); GNUNET_free (ds); return NULL; } return ds; } /* end of fs_dirmetascan.c */ gnunet-0.10.1/src/fs/gnunet-service-fs_cp.h0000644000175000017500000003011612225777503015423 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_cp.h * @brief API to handle 'connected peers' * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_FS_CP_H #define GNUNET_SERVICE_FS_CP_H #include "fs.h" #include "gnunet-service-fs.h" /** * Maximum number of outgoing messages we queue per peer. * * Performance measurements for 2 peer setup for 50 MB file * (with MAX_DATASTORE_QUEUE = 1 and RETRY_PROBABILITY_INV = 1): * * 2: 1700 kb/s, 1372 kb/s * 8: 2117 kb/s, 1284 kb/s, 1112 kb/s * 16: 3500 kb/s, 3200 kb/s, 3388 kb/s * 32: 3441 kb/s, 3163 kb/s, 3277 kb/s * 128: 1700 kb/s; 2010 kb/s, 3383 kb/s, 1156 kb/s * * Conclusion: 16 seems to be a pretty good value (stable * and high performance, no excessive memory use). */ #define MAX_QUEUE_PER_PEER 16 /** * Length of the P2P success tracker. Note that having a very long * list can also hurt performance. */ #define P2P_SUCCESS_LIST_SIZE 8 /** * Length of the CS-2-P success tracker. Note that * having a very long list can also hurt performance. */ #define CS2P_SUCCESS_LIST_SIZE 8 /** * Performance data kept for a peer. */ struct GSF_PeerPerformanceData { /** * Transport performance data. */ struct GNUNET_ATS_Information *atsi; /** * List of the last clients for which this peer successfully * answered a query. */ struct GSF_LocalClient *last_client_replies[CS2P_SUCCESS_LIST_SIZE]; /** * List of the last PIDs for which * this peer successfully answered a query; * We use 0 to indicate no successful reply. */ GNUNET_PEER_Id last_p2p_replies[P2P_SUCCESS_LIST_SIZE]; /** * Average delay between sending the peer a request and * getting a reply (only calculated over the requests for * which we actually got a reply). Calculated * as a moving average: new_delay = ((n-1)*last_delay+curr_delay) / n */ struct GNUNET_TIME_Relative avg_reply_delay; /** * If we get content we already have from this peer, for how * long do we block him? Adjusted based on the fraction of * redundant data we receive, between 1s and 1h. */ struct GNUNET_TIME_Relative migration_delay; /** * Point in time until which this peer does not want us to migrate content * to it. */ struct GNUNET_TIME_Absolute migration_blocked_until; /** * Transmission times for the last MAX_QUEUE_PER_PEER * requests for this peer. Used as a ring buffer, current * offset is stored in 'last_request_times_off'. If the * oldest entry is more recent than the 'avg_delay', we should * not send any more requests right now. */ struct GNUNET_TIME_Absolute last_request_times[MAX_QUEUE_PER_PEER]; /** * How long does it typically take for us to transmit a message * to this peer? (delay between the request being issued and * the callback being invoked). */ struct GNUNET_LOAD_Value *transmission_delay; /** * Average priority of successful replies. Calculated * as a moving average: new_avg = ((n-1)*last_avg+curr_prio) / n */ double avg_priority; /** * The peer's identity. */ GNUNET_PEER_Id pid; /** * Respect rating for this peer */ uint32_t respect; /** * Number of pending queries (replies are not counted) */ unsigned int pending_queries; /** * Number of pending replies (queries are not counted) */ unsigned int pending_replies; }; /** * Signature of function called on a connected peer. * * @param cls closure * @param peer identity of the peer * @param cp handle to the connected peer record * @param perf peer performance data */ typedef void (*GSF_ConnectedPeerIterator) (void *cls, const struct GNUNET_PeerIdentity * peer, struct GSF_ConnectedPeer * cp, const struct GSF_PeerPerformanceData * ppd); /** * Function called to get a message for transmission. * * @param cls closure * @param buf_size number of bytes available in buf * @param buf where to copy the message, NULL on error (peer disconnect) * @return number of bytes copied to 'buf', can be 0 (without indicating an error) */ typedef size_t (*GSF_GetMessageCallback) (void *cls, size_t buf_size, void *buf); /** * Signature of function called on a reservation success or failure. * * @param cls closure * @param cp handle to the connected peer record * @param success GNUNET_YES on success, GNUNET_NO on failure */ typedef void (*GSF_PeerReserveCallback) (void *cls, struct GSF_ConnectedPeer * cp, int success); /** * Handle to cancel a transmission request. */ struct GSF_PeerTransmitHandle; /** * A peer connected to us. Setup the connected peer * records. * * @param peer identity of peer that connected * @return handle to connected peer entry */ struct GSF_ConnectedPeer * GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer); /** * Get a handle for a connected peer. * * @param peer peer's identity * @return NULL if this peer is not currently connected */ struct GSF_ConnectedPeer * GSF_peer_get_ (const struct GNUNET_PeerIdentity *peer); /** * Update the latency information kept for the given peer. * * @param id peer record to update * @param latency current latency value */ void GSF_update_peer_latency_ (const struct GNUNET_PeerIdentity *id, struct GNUNET_TIME_Relative latency); /** * Transmit a message to the given peer as soon as possible. * If the peer disconnects before the transmission can happen, * the callback is invoked with a 'NULL' buffer. * * @param cp target peer * @param is_query is this a query (GNUNET_YES) or content (GNUNET_NO) * @param priority how important is this request? * @param timeout when does this request timeout (call gmc with error) * @param size number of bytes we would like to send to the peer * @param gmc function to call to get the message * @param gmc_cls closure for gmc * @return handle to cancel request */ struct GSF_PeerTransmitHandle * GSF_peer_transmit_ (struct GSF_ConnectedPeer *cp, int is_query, uint32_t priority, struct GNUNET_TIME_Relative timeout, size_t size, GSF_GetMessageCallback gmc, void *gmc_cls); /** * Cancel an earlier request for transmission. * * @param pth request to cancel */ void GSF_peer_transmit_cancel_ (struct GSF_PeerTransmitHandle *pth); /** * Report on receiving a reply; update the performance record of the given peer. * * @param cp responding peer (will be updated) * @param request_time time at which the original query was transmitted * @param request_priority priority of the original request */ void GSF_peer_update_performance_ (struct GSF_ConnectedPeer *cp, struct GNUNET_TIME_Absolute request_time, uint32_t request_priority); /** * Report on receiving a reply in response to an initiating client. * Remember that this peer is good for this client. * * @param cp responding peer (will be updated) * @param initiator_client local client on responsible for query */ void GSF_peer_update_responder_client_ (struct GSF_ConnectedPeer *cp, struct GSF_LocalClient *initiator_client); /** * Report on receiving a reply in response to an initiating peer. * Remember that this peer is good for this initiating peer. * * @param cp responding peer (will be updated) * @param initiator_peer other peer responsible for query */ void GSF_peer_update_responder_peer_ (struct GSF_ConnectedPeer *cp, const struct GSF_ConnectedPeer *initiator_peer); /** * Handle P2P "MIGRATION_STOP" message. * * @param cls closure, always NULL * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GSF_handle_p2p_migration_stop_ (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message); /** * Handle P2P "QUERY" message. Only responsible for creating the * request entry itself and setting up reply callback and cancellation * on peer disconnect. Does NOT execute the actual request strategy * (planning) or local database operations. * * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message * @return pending request handle, NULL on error */ struct GSF_PendingRequest * GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message); /** * Return the performance data record for the given peer * * @param cp peer to query * @return performance data record for the peer */ struct GSF_PeerPerformanceData * GSF_get_peer_performance_data_ (struct GSF_ConnectedPeer *cp); /** * Ask a peer to stop migrating data to us until the given point * in time. * * @param cp peer to ask * @param block_time until when to block */ void GSF_block_peer_migration_ (struct GSF_ConnectedPeer *cp, struct GNUNET_TIME_Absolute block_time); /** * A peer disconnected from us. Tear down the connected peer * record. * * @param cls unused * @param peer identity of peer that connected */ void GSF_peer_disconnect_handler_ (void *cls, const struct GNUNET_PeerIdentity *peer); /** * Notification that a local client disconnected. Clean up all of our * references to the given handle. * * @param lc handle to the local client (henceforth invalid) */ void GSF_handle_local_client_disconnect_ (const struct GSF_LocalClient *lc); /** * Notify core about a preference we have for the given peer * (to allocate more resources towards it). The change will * be communicated the next time we reserve bandwidth with * core (not instantly). * * @param cp peer to reserve bandwidth from * @param pref preference change */ void GSF_connected_peer_change_preference_ (struct GSF_ConnectedPeer *cp, uint64_t pref); /** * Obtain the identity of a connected peer. * * @param cp peer to get identity of * @param id identity to set (written to) */ void GSF_connected_peer_get_identity_ (const struct GSF_ConnectedPeer *cp, struct GNUNET_PeerIdentity *id); /** * Obtain the identity of a connected peer. * * @param cp peer to get identity of * @return reference to peer identity, valid until peer disconnects (!) */ const struct GNUNET_PeerIdentity * GSF_connected_peer_get_identity2_ (const struct GSF_ConnectedPeer *cp); /** * Iterate over all connected peers. * * @param it function to call for each peer * @param it_cls closure for it */ void GSF_iterate_connected_peers_ (GSF_ConnectedPeerIterator it, void *it_cls); /** * Initialize peer management subsystem. */ void GSF_connected_peer_init_ (void); /** * Shutdown peer management subsystem. */ void GSF_connected_peer_done_ (void); #endif /* end of gnunet-service-fs_cp.h */ gnunet-0.10.1/src/fs/fs_publish.c0000644000175000017500000012551112226006456013523 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_publish.c * @brief publish a file or directory in GNUnet * @see https://gnunet.org/encoding * @author Krista Bennett * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "fs_api.h" #include "fs_tree.h" /** * Fill in all of the generic fields for * a publish event and call the callback. * * @param pi structure to fill in * @param pc overall publishing context * @param p file information for the file being published * @param offset where in the file are we so far * @return value returned from callback */ void * GNUNET_FS_publish_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_PublishContext *pc, const struct GNUNET_FS_FileInformation *p, uint64_t offset) { pi->value.publish.pc = pc; pi->value.publish.fi = p; pi->value.publish.cctx = p->client_info; pi->value.publish.pctx = (NULL == p->dir) ? NULL : p->dir->client_info; pi->value.publish.filename = p->filename; pi->value.publish.size = (p->is_directory == GNUNET_YES) ? p->data.dir.dir_size : p->data.file.file_size; pi->value.publish.eta = GNUNET_TIME_calculate_eta (p->start_time, offset, pi->value.publish.size); pi->value.publish.completed = offset; pi->value.publish.duration = GNUNET_TIME_absolute_get_duration (p->start_time); pi->value.publish.anonymity = p->bo.anonymity_level; pi->fsh = pc->h; return pc->h->upcb (pc->h->upcb_cls, pi); } /** * Cleanup the publish context, we're done with it. * * @param pc struct to clean up */ static void publish_cleanup (struct GNUNET_FS_PublishContext *pc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up publish context (done!)\n"); if (pc->fhc != NULL) { GNUNET_CRYPTO_hash_file_cancel (pc->fhc); pc->fhc = NULL; } GNUNET_FS_file_information_destroy (pc->fi, NULL, NULL); GNUNET_free_non_null (pc->nid); GNUNET_free_non_null (pc->nuid); GNUNET_free_non_null (pc->serialization); if (pc->dsh != NULL) { GNUNET_DATASTORE_disconnect (pc->dsh, GNUNET_NO); pc->dsh = NULL; } if (pc->client != NULL) { GNUNET_CLIENT_disconnect (pc->client); pc->client = NULL; } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); GNUNET_free (pc); } /** * Function called by the datastore API with * the result from the PUT request. * * @param cls the `struct GNUNET_FS_PublishContext *` * @param success #GNUNET_OK on success * @param min_expiration minimum expiration time required for content to be stored * @param msg error message (or NULL) */ static void ds_put_cont (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_ProgressInfo pi; pc->qre = NULL; if (GNUNET_SYSERR == success) { GNUNET_asprintf (&pc->fi_pos->emsg, _("Publishing failed: %s"), msg); pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; pi.value.publish.specifics.error.message = pc->fi_pos->emsg; pc->fi_pos->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi_pos, 0); if ((pc->fi_pos->is_directory != GNUNET_YES) && (pc->fi_pos->filename != NULL) && (pc->fi_pos->data.file.do_index == GNUNET_YES)) { /* run unindex to clean up */ GNUNET_FS_unindex_start (pc->h, pc->fi_pos->filename, NULL); } } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); } /** * Generate the callback that signals clients * that a file (or directory) has been completely * published. * * @param p the completed upload * @param pc context of the publication */ static void signal_publish_completion (struct GNUNET_FS_FileInformation *p, struct GNUNET_FS_PublishContext *pc) { struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_PUBLISH_COMPLETED; pi.value.publish.eta = GNUNET_TIME_UNIT_ZERO; pi.value.publish.specifics.completed.chk_uri = p->chk_uri; p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, GNUNET_ntohll (p->chk_uri->data. chk.file_length)); } /** * Generate the callback that signals clients * that a file (or directory) has encountered * a problem during publication. * * @param p the upload that had trouble * @param pc context of the publication * @param emsg error message */ static void signal_publish_error (struct GNUNET_FS_FileInformation *p, struct GNUNET_FS_PublishContext *pc, const char *emsg) { struct GNUNET_FS_ProgressInfo pi; p->emsg = GNUNET_strdup (emsg); pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; pi.value.publish.specifics.error.message = emsg; p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); if ((p->is_directory != GNUNET_YES) && (p->filename != NULL) && (p->data.file.do_index == GNUNET_YES)) { /* run unindex to clean up */ GNUNET_FS_unindex_start (pc->h, p->filename, NULL); } } /** * Datastore returns from reservation cancel request. * * @param cls the `struct GNUNET_FS_PublishContext *` * @param success success code (not used) * @param min_expiration minimum expiration time required for content to be stored * @param msg error message (typically NULL, not used) */ static void finish_release_reserve (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct GNUNET_FS_PublishContext *pc = cls; pc->qre = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Releasing reserve done!\n"); signal_publish_completion (pc->fi, pc); pc->all_done = GNUNET_YES; GNUNET_FS_publish_sync_ (pc); } /** * We've finished publishing the SBlock as part of a larger upload. * Check the result and complete the larger upload. * * @param cls the "struct GNUNET_FS_PublishContext*" of the larger upload * @param uri URI of the published SBlock * @param emsg NULL on success, otherwise error message */ static void publish_sblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { struct GNUNET_FS_PublishContext *pc = cls; pc->sks_pc = NULL; if (NULL != emsg) { signal_publish_error (pc->fi, pc, emsg); GNUNET_FS_publish_sync_ (pc); return; } GNUNET_assert (pc->qre == NULL); if ((pc->dsh != NULL) && (pc->rid != 0)) { pc->qre = GNUNET_DATASTORE_release_reserve (pc->dsh, pc->rid, UINT_MAX, UINT_MAX, GNUNET_TIME_UNIT_FOREVER_REL, &finish_release_reserve, pc); } else { finish_release_reserve (pc, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL); } } /** * We are almost done publishing the structure, * add SBlocks (if needed). * * @param pc overall upload data */ static void publish_sblock (struct GNUNET_FS_PublishContext *pc) { if (NULL != pc->ns) pc->sks_pc = GNUNET_FS_publish_sks (pc->h, pc->ns, pc->nid, pc->nuid, pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo, pc->options, &publish_sblocks_cont, pc); else publish_sblocks_cont (pc, NULL, NULL); } /** * We've finished publishing a KBlock as part of a larger upload. * Check the result and continue the larger upload. * * @param cls the `struct GNUNET_FS_PublishContext *` * of the larger upload * @param uri URI of the published blocks * @param emsg NULL on success, otherwise error message */ static void publish_kblocks_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_FileInformation *p = pc->fi_pos; pc->ksk_pc = NULL; if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading KSK blocks: %s\n", emsg); signal_publish_error (p, pc, emsg); GNUNET_FS_file_information_sync_ (p); GNUNET_FS_publish_sync_ (pc); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK blocks published, moving on to next file\n"); if (NULL != p->dir) signal_publish_completion (p, pc); /* move on to next file */ if (NULL != p->next) pc->fi_pos = p->next; else pc->fi_pos = p->dir; GNUNET_FS_publish_sync_ (pc); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); } /** * Function called by the tree encoder to obtain * a block of plaintext data (for the lowest level * of the tree). * * @param cls our publishing context * @param offset identifies which block to get * @param max (maximum) number of bytes to get; returning * fewer will also cause errors * @param buf where to copy the plaintext buffer * @param emsg location to store an error message (on error) * @return number of bytes copied to buf, 0 on error */ static size_t block_reader (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_FileInformation *p; const char *dd; size_t pt_size; p = pc->fi_pos; if (GNUNET_YES == p->is_directory) { pt_size = GNUNET_MIN (max, p->data.dir.dir_size - offset); dd = p->data.dir.dir_data; memcpy (buf, &dd[offset], pt_size); } else { if (UINT64_MAX == offset) { if (&GNUNET_FS_data_reader_file_ == p->data.file.reader) { /* force closing the file to avoid keeping too many files open */ p->data.file.reader (p->data.file.reader_cls, offset, 0, NULL, NULL); } return 0; } pt_size = GNUNET_MIN (max, p->data.file.file_size - offset); if (0 == pt_size) return 0; /* calling reader with pt_size==0 * might free buf, so don't! */ if (pt_size != p->data.file.reader (p->data.file.reader_cls, offset, pt_size, buf, emsg)) return 0; } return pt_size; } /** * The tree encoder has finished processing a * file. Call it's finish method and deal with * the final result. * * @param cls our publishing context * @param tc scheduler's task context (not used) */ static void encode_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_FileInformation *p; struct GNUNET_FS_ProgressInfo pi; char *emsg; uint64_t flen; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished with tree encoder\n"); p = pc->fi_pos; p->chk_uri = GNUNET_FS_tree_encoder_get_uri (p->te); GNUNET_FS_file_information_sync_ (p); GNUNET_FS_tree_encoder_finish (p->te, &emsg); p->te = NULL; if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error during tree walk: %s\n", emsg); GNUNET_asprintf (&p->emsg, _("Publishing failed: %s"), emsg); GNUNET_free (emsg); pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; pi.value.publish.specifics.error.message = p->emsg; p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); } else { /* final progress event */ GNUNET_assert (NULL != p->chk_uri); flen = GNUNET_FS_uri_chk_get_file_size (p->chk_uri); pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; pi.value.publish.specifics.progress.data = NULL; pi.value.publish.specifics.progress.offset = flen; pi.value.publish.specifics.progress.data_len = 0; pi.value.publish.specifics.progress.depth = GNUNET_FS_compute_depth (flen); p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, flen); } /* continue with main */ /* continue with main */ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); } /** * Function called asking for the current (encoded) * block to be processed. After processing the * client should either call #GNUNET_FS_tree_encoder_next * or (on error) #GNUNET_FS_tree_encoder_finish. * * @param cls closure * @param chk content hash key for the block * @param offset offset of the block in the file * @param depth depth of the block in the file, 0 for DBLOCK * @param type type of the block (IBLOCK or DBLOCK) * @param block the (encrypted) block * @param block_size size of @a block (in bytes) */ static void block_proc (void *cls, const struct ContentHashKey *chk, uint64_t offset, unsigned int depth, enum GNUNET_BLOCK_Type type, const void *block, uint16_t block_size) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_FileInformation *p; struct OnDemandBlock odb; p = pc->fi_pos; if (NULL == pc->dsh) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for datastore connection\n"); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); return; } if ( (GNUNET_YES != p->is_directory) && (GNUNET_YES == p->data.file.do_index) && (GNUNET_BLOCK_TYPE_FS_DBLOCK == type) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Indexing block `%s' for offset %llu with index size %u\n", GNUNET_h2s (&chk->query), (unsigned long long) offset, sizeof (struct OnDemandBlock)); odb.offset = GNUNET_htonll (offset); odb.file_id = p->data.file.file_id; GNUNET_assert (pc->qre == NULL); pc->qre = GNUNET_DATASTORE_put (pc->dsh, (p->is_directory == GNUNET_YES) ? 0 : pc->rid, &chk->query, sizeof (struct OnDemandBlock), &odb, GNUNET_BLOCK_TYPE_FS_ONDEMAND, p->bo.content_priority, p->bo.anonymity_level, p->bo.replication_level, p->bo.expiration_time, -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &ds_put_cont, pc); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing block `%s' for offset %llu with size %u\n", GNUNET_h2s (&chk->query), (unsigned long long) offset, (unsigned int) block_size); GNUNET_assert (pc->qre == NULL); pc->qre = GNUNET_DATASTORE_put (pc->dsh, (p->is_directory == GNUNET_YES) ? 0 : pc->rid, &chk->query, block_size, block, type, p->bo.content_priority, p->bo.anonymity_level, p->bo.replication_level, p->bo.expiration_time, -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &ds_put_cont, pc); } /** * Function called with information about our * progress in computing the tree encoding. * * @param cls closure * @param offset where are we in the file * @param pt_block plaintext of the currently processed block * @param pt_size size of @a pt_block * @param depth depth of the block in the tree, 0 for DBLOCK */ static void progress_proc (void *cls, uint64_t offset, const void *pt_block, size_t pt_size, unsigned int depth) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_FileInformation *p; struct GNUNET_FS_FileInformation *par; struct GNUNET_FS_ProgressInfo pi; p = pc->fi_pos; pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS; pi.value.publish.specifics.progress.data = pt_block; pi.value.publish.specifics.progress.offset = offset; pi.value.publish.specifics.progress.data_len = pt_size; pi.value.publish.specifics.progress.depth = depth; p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, offset); if ( (0 != depth) || (GNUNET_YES == p->is_directory) ) return; while (NULL != (par = p->dir)) { p = par; GNUNET_assert (GNUNET_YES == par->is_directory); p->data.dir.contents_completed += pt_size; pi.status = GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY; pi.value.publish.specifics.progress_directory.completed = p->data.dir.contents_completed; pi.value.publish.specifics.progress_directory.total = p->data.dir.contents_size; pi.value.publish.specifics.progress_directory.eta = GNUNET_TIME_calculate_eta (p->start_time, p->data.dir.contents_completed, p->data.dir.contents_size); p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); } } /** * We are uploading a file or directory; load (if necessary) the next * block into memory, encrypt it and send it to the FS service. Then * continue with the main task. * * @param pc overall upload data */ static void publish_content (struct GNUNET_FS_PublishContext *pc) { struct GNUNET_FS_FileInformation *p; char *emsg; struct GNUNET_FS_DirectoryBuilder *db; struct GNUNET_FS_FileInformation *dirpos; void *raw_data; uint64_t size; p = pc->fi_pos; GNUNET_assert (NULL != p); if (NULL == p->te) { if (GNUNET_YES == p->is_directory) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating directory\n"); db = GNUNET_FS_directory_builder_create (p->meta); dirpos = p->data.dir.entries; while (NULL != dirpos) { if (GNUNET_YES == dirpos->is_directory) { raw_data = dirpos->data.dir.dir_data; dirpos->data.dir.dir_data = NULL; } else { raw_data = NULL; if ((dirpos->data.file.file_size < MAX_INLINE_SIZE) && (dirpos->data.file.file_size > 0)) { raw_data = GNUNET_malloc (dirpos->data.file.file_size); emsg = NULL; if (dirpos->data.file.file_size != dirpos->data.file.reader (dirpos->data.file.reader_cls, 0, dirpos->data.file.file_size, raw_data, &emsg)) { GNUNET_free_non_null (emsg); GNUNET_free (raw_data); raw_data = NULL; } dirpos->data.file.reader (dirpos->data.file.reader_cls, UINT64_MAX, 0, 0, NULL); } } GNUNET_FS_directory_builder_add (db, dirpos->chk_uri, dirpos->meta, raw_data); GNUNET_free_non_null (raw_data); dirpos = dirpos->next; } GNUNET_free_non_null (p->data.dir.dir_data); p->data.dir.dir_data = NULL; p->data.dir.dir_size = 0; GNUNET_FS_directory_builder_finish (db, &p->data.dir.dir_size, &p->data.dir.dir_data); GNUNET_FS_file_information_sync_ (p); } size = (GNUNET_YES == p->is_directory) ? p->data.dir.dir_size : p->data.file.file_size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating tree encoder\n"); p->te = GNUNET_FS_tree_encoder_create (pc->h, size, pc, &block_reader, &block_proc, &progress_proc, &encode_cont); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing next block from tree\n"); GNUNET_FS_tree_encoder_next (p->te); } /** * Process the response (or lack thereof) from * the "fs" service to our 'start index' request. * * @param cls closure (of type `struct GNUNET_FS_PublishContext *`) * @param msg the response we got */ static void process_index_start_response (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_FileInformation *p; const char *emsg; uint16_t msize; GNUNET_CLIENT_disconnect (pc->client); pc->client = NULL; p = pc->fi_pos; if (NULL == msg) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Can not index file `%s': %s. Will try to insert instead.\n"), p->filename, _("timeout on index-start request to `fs' service")); p->data.file.do_index = GNUNET_NO; GNUNET_FS_file_information_sync_ (p); publish_content (pc); return; } if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK) { msize = ntohs (msg->size); emsg = (const char *) &msg[1]; if ((msize <= sizeof (struct GNUNET_MessageHeader)) || (emsg[msize - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')) emsg = gettext_noop ("unknown error"); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Can not index file `%s': %s. Will try to insert instead.\n"), p->filename, gettext (emsg)); p->data.file.do_index = GNUNET_NO; GNUNET_FS_file_information_sync_ (p); publish_content (pc); return; } p->data.file.index_start_confirmed = GNUNET_YES; /* success! continue with indexing */ GNUNET_FS_file_information_sync_ (p); publish_content (pc); } /** * Function called once the hash computation over an * indexed file has completed. * * @param cls closure, our publishing context * @param res resulting hash, NULL on error */ static void hash_for_index_cb (void *cls, const struct GNUNET_HashCode *res) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_FileInformation *p; struct IndexStartMessage *ism; size_t slen; struct GNUNET_CLIENT_Connection *client; uint64_t dev; uint64_t ino; char *fn; pc->fhc = NULL; p = pc->fi_pos; if (NULL == res) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Can not index file `%s': %s. Will try to insert instead.\n"), p->filename, _("failed to compute hash")); p->data.file.do_index = GNUNET_NO; GNUNET_FS_file_information_sync_ (p); publish_content (pc); return; } if (GNUNET_YES == p->data.file.index_start_confirmed) { publish_content (pc); return; } fn = GNUNET_STRINGS_filename_expand (p->filename); GNUNET_assert (fn != NULL); slen = strlen (fn) + 1; if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct IndexStartMessage)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Can not index file `%s': %s. Will try to insert instead.\n"), fn, _("filename too long")); GNUNET_free (fn); p->data.file.do_index = GNUNET_NO; GNUNET_FS_file_information_sync_ (p); publish_content (pc); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hash of indexed file `%s' is `%s'\n", p->filename, GNUNET_h2s (res)); if (0 != (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) { p->data.file.file_id = *res; p->data.file.have_hash = GNUNET_YES; p->data.file.index_start_confirmed = GNUNET_YES; GNUNET_FS_file_information_sync_ (p); publish_content (pc); GNUNET_free (fn); return; } client = GNUNET_CLIENT_connect ("fs", pc->h->cfg); if (NULL == client) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Can not index file `%s': %s. Will try to insert instead.\n"), p->filename, _("could not connect to `fs' service")); p->data.file.do_index = GNUNET_NO; publish_content (pc); GNUNET_free (fn); return; } if (p->data.file.have_hash != GNUNET_YES) { p->data.file.file_id = *res; p->data.file.have_hash = GNUNET_YES; GNUNET_FS_file_information_sync_ (p); } ism = GNUNET_malloc (sizeof (struct IndexStartMessage) + slen); ism->header.size = htons (sizeof (struct IndexStartMessage) + slen); ism->header.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_START); if (GNUNET_OK == GNUNET_DISK_file_get_identifiers (p->filename, &dev, &ino)) { ism->device = GNUNET_htonll (dev); ism->inode = GNUNET_htonll (ino); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Failed to get file identifiers for `%s'\n"), p->filename); } ism->file_id = *res; memcpy (&ism[1], fn, slen); GNUNET_free (fn); pc->client = client; GNUNET_break (GNUNET_YES == GNUNET_CLIENT_transmit_and_get_response (client, &ism->header, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &process_index_start_response, pc)); GNUNET_free (ism); } /** * Main function that performs the upload. * * @param cls `struct GNUNET_FS_PublishContext *` identifies the upload * @param tc task context */ void GNUNET_FS_publish_main_ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_ProgressInfo pi; struct GNUNET_FS_FileInformation *p; struct GNUNET_FS_Uri *loc; char *fn; pc->upload_task = GNUNET_SCHEDULER_NO_TASK; p = pc->fi_pos; if (NULL == p) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing complete, now publishing SKS and KSK blocks.\n"); /* upload of entire hierarchy complete, * publish namespace entries */ GNUNET_FS_publish_sync_ (pc); publish_sblock (pc); return; } /* find starting position */ while ( (GNUNET_YES == p->is_directory) && (NULL != p->data.dir.entries) && (NULL == p->emsg) && (NULL == p->data.dir.entries->chk_uri) ) { p = p->data.dir.entries; pc->fi_pos = p; GNUNET_FS_publish_sync_ (pc); } /* abort on error */ if (NULL != p->emsg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error uploading: %s\n", p->emsg); /* error with current file, abort all * related files as well! */ while (NULL != p->dir) { fn = GNUNET_CONTAINER_meta_data_get_by_type (p->meta, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); p = p->dir; if (fn != NULL) { GNUNET_asprintf (&p->emsg, _("Recursive upload failed at `%s': %s"), fn, p->emsg); GNUNET_free (fn); } else { GNUNET_asprintf (&p->emsg, _("Recursive upload failed: %s"), p->emsg); } pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; pi.value.publish.specifics.error.message = p->emsg; p->client_info = GNUNET_FS_publish_make_status_ (&pi, pc, p, 0); } pc->all_done = GNUNET_YES; GNUNET_FS_publish_sync_ (pc); return; } /* handle completion */ if (NULL != p->chk_uri) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File upload complete, now publishing KSK blocks.\n"); if (0 == p->bo.anonymity_level) { /* zero anonymity, box CHK URI in LOC URI */ loc = GNUNET_FS_uri_loc_create (p->chk_uri, pc->h->cfg, p->bo.expiration_time); GNUNET_FS_uri_destroy (p->chk_uri); p->chk_uri = loc; GNUNET_FS_file_information_sync_ (p); } GNUNET_FS_publish_sync_ (pc); /* upload of "p" complete, publish KBlocks! */ if (NULL != p->keywords) { pc->ksk_pc = GNUNET_FS_publish_ksk (pc->h, p->keywords, p->meta, p->chk_uri, &p->bo, pc->options, &publish_kblocks_cont, pc); } else { publish_kblocks_cont (pc, p->chk_uri, NULL); } return; } if ((GNUNET_YES != p->is_directory) && (p->data.file.do_index)) { if (NULL == p->filename) { p->data.file.do_index = GNUNET_NO; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Can not index file `%s': %s. Will try to insert instead.\n"), "", _("needs to be an actual file")); GNUNET_FS_file_information_sync_ (p); publish_content (pc); return; } if (p->data.file.have_hash) { hash_for_index_cb (pc, &p->data.file.file_id); } else { p->start_time = GNUNET_TIME_absolute_get (); pc->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE, p->filename, HASHING_BLOCKSIZE, &hash_for_index_cb, pc); } return; } publish_content (pc); } /** * Signal the FS's progress function that we are starting * an upload. * * @param cls closure (of type `struct GNUNET_FS_PublishContext *`) * @param fi the entry in the publish-structure * @param length length of the file or directory * @param meta metadata for the file or directory (can be modified) * @param uri pointer to the keywords that will be used for this entry (can be modified) * @param bo block options * @param do_index should we index? * @param client_info pointer to client context set upon creation (can be modified) * @return #GNUNET_OK to continue (always) */ static int fip_signal_start (void *cls, struct GNUNET_FS_FileInformation *fi, uint64_t length, struct GNUNET_CONTAINER_MetaData *meta, struct GNUNET_FS_Uri **uri, struct GNUNET_FS_BlockOptions *bo, int *do_index, void **client_info) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_ProgressInfo pi; unsigned int kc; uint64_t left; if (GNUNET_YES == pc->skip_next_fi_callback) { pc->skip_next_fi_callback = GNUNET_NO; return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting publish operation\n"); if (*do_index) { /* space for on-demand blocks */ pc->reserve_space += ((length + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * sizeof (struct OnDemandBlock); } else { /* space for DBlocks */ pc->reserve_space += length; } /* entries for IBlocks and DBlocks, space for IBlocks */ left = length; while (1) { left = (left + DBLOCK_SIZE - 1) / DBLOCK_SIZE; pc->reserve_entries += left; if (left <= 1) break; left = left * sizeof (struct ContentHashKey); pc->reserve_space += left; } pc->reserve_entries++; /* entries and space for keywords */ if (NULL != *uri) { kc = GNUNET_FS_uri_ksk_get_keyword_count (*uri); pc->reserve_entries += kc; pc->reserve_space += GNUNET_SERVER_MAX_MESSAGE_SIZE * kc; } pi.status = GNUNET_FS_STATUS_PUBLISH_START; *client_info = GNUNET_FS_publish_make_status_ (&pi, pc, fi, 0); GNUNET_FS_file_information_sync_ (fi); if ((fi->is_directory) && (fi->dir != NULL)) { /* We are a directory, and we are not top-level; process entries in directory */ pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (fi, &fip_signal_start, pc); } return GNUNET_OK; } /** * Actually signal the FS's progress function that we are suspending * an upload. * * @param fi the entry in the publish-structure * @param pc the publish context of which a file is being suspended */ static void suspend_operation (struct GNUNET_FS_FileInformation *fi, struct GNUNET_FS_PublishContext *pc) { struct GNUNET_FS_ProgressInfo pi; uint64_t off; if (NULL != pc->ksk_pc) { GNUNET_FS_publish_ksk_cancel (pc->ksk_pc); pc->ksk_pc = NULL; } if (NULL != pc->sks_pc) { GNUNET_FS_publish_sks_cancel (pc->sks_pc); pc->sks_pc = NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Suspending publish operation\n"); GNUNET_free_non_null (fi->serialization); fi->serialization = NULL; off = (NULL == fi->chk_uri) ? 0 : (GNUNET_YES == fi->is_directory) ? fi->data.dir.dir_size : fi->data.file.file_size; pi.status = GNUNET_FS_STATUS_PUBLISH_SUSPEND; GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, fi, off)); if (NULL != pc->qre) { GNUNET_DATASTORE_cancel (pc->qre); pc->qre = NULL; } if (NULL != pc->dsh) { GNUNET_DATASTORE_disconnect (pc->dsh, GNUNET_NO); pc->dsh = NULL; } pc->rid = 0; } /** * Signal the FS's progress function that we are suspending * an upload. Performs the recursion. * * @param cls closure (of type `struct GNUNET_FS_PublishContext *`) * @param fi the entry in the publish-structure * @param length length of the file or directory * @param meta metadata for the file or directory (can be modified) * @param uri pointer to the keywords that will be used for this entry (can be modified) * @param bo block options * @param do_index should we index? * @param client_info pointer to client context set upon creation (can be modified) * @return #GNUNET_OK to continue (always) */ static int fip_signal_suspend (void *cls, struct GNUNET_FS_FileInformation *fi, uint64_t length, struct GNUNET_CONTAINER_MetaData *meta, struct GNUNET_FS_Uri **uri, struct GNUNET_FS_BlockOptions *bo, int *do_index, void **client_info) { struct GNUNET_FS_PublishContext *pc = cls; if (GNUNET_YES == pc->skip_next_fi_callback) { pc->skip_next_fi_callback = GNUNET_NO; return GNUNET_OK; } if (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (meta)) { /* process entries in directory */ pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (fi, &fip_signal_suspend, pc); } suspend_operation (fi, pc); *client_info = NULL; return GNUNET_OK; } /** * Create SUSPEND event for the given publish operation * and then clean up our state (without stop signal). * * @param cls the `struct GNUNET_FS_PublishContext` to signal for */ void GNUNET_FS_publish_signal_suspend_ (void *cls) { struct GNUNET_FS_PublishContext *pc = cls; if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) { GNUNET_SCHEDULER_cancel (pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_NO_TASK; } pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_suspend, pc); suspend_operation (pc->fi, pc); GNUNET_FS_end_top (pc->h, pc->top); pc->top = NULL; publish_cleanup (pc); } /** * We have gotten a reply for our space reservation request. * Either fail (insufficient space) or start publishing for good. * * @param cls the `struct GNUNET_FS_PublishContext *` * @param success positive reservation ID on success * @param min_expiration minimum expiration time required for content to be stored * @param msg error message on error, otherwise NULL */ static void finish_reserve (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct GNUNET_FS_PublishContext *pc = cls; pc->qre = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reservation complete (%d)!\n", success); if ((msg != NULL) || (success <= 0)) { GNUNET_asprintf (&pc->fi->emsg, _("Insufficient space for publishing: %s"), msg); signal_publish_error (pc->fi, pc, pc->fi->emsg); return; } pc->rid = success; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); } /** * Calculate the total size of all of the files in the directory structure. * * @param fi file structure to traverse */ static uint64_t compute_contents_size (struct GNUNET_FS_FileInformation *fi) { struct GNUNET_FS_FileInformation *ent; if (GNUNET_YES != fi->is_directory) return fi->data.file.file_size; fi->data.dir.contents_size = 0; for (ent = fi->data.dir.entries; NULL != ent; ent = ent->next) fi->data.dir.contents_size += compute_contents_size (ent); return fi->data.dir.contents_size; } /** * Publish a file or directory. * * @param h handle to the file sharing subsystem * @param fi information about the file or directory structure to publish * @param ns namespace to publish the file in, NULL for no namespace * @param nid identifier to use for the publishd content in the namespace * (can be NULL, must be NULL if namespace is NULL) * @param nuid update-identifier that will be used for future updates * (can be NULL, must be NULL if namespace or nid is NULL) * @param options options for the publication * @return context that can be used to control the publish operation */ struct GNUNET_FS_PublishContext * GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, struct GNUNET_FS_FileInformation *fi, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const char *nid, const char *nuid, enum GNUNET_FS_PublishOptions options) { struct GNUNET_FS_PublishContext *ret; struct GNUNET_DATASTORE_Handle *dsh; GNUNET_assert (NULL != h); compute_contents_size (fi); if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) { dsh = GNUNET_DATASTORE_connect (h->cfg); if (NULL == dsh) return NULL; } else { dsh = NULL; } ret = GNUNET_new (struct GNUNET_FS_PublishContext); ret->dsh = dsh; ret->h = h; ret->fi = fi; if (NULL != ns) { ret->ns = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); *ret->ns = *ns; GNUNET_assert (NULL != nid); ret->nid = GNUNET_strdup (nid); if (NULL != nuid) ret->nuid = GNUNET_strdup (nuid); } ret->options = options; /* signal start */ GNUNET_FS_file_information_inspect (ret->fi, &fip_signal_start, ret); ret->fi_pos = ret->fi; ret->top = GNUNET_FS_make_top (h, &GNUNET_FS_publish_signal_suspend_, ret); GNUNET_FS_publish_sync_ (ret); if (NULL != ret->dsh) { GNUNET_assert (NULL == ret->qre); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Reserving space for %u entries and %llu bytes for publication\n"), (unsigned int) ret->reserve_entries, (unsigned long long) ret->reserve_space); ret->qre = GNUNET_DATASTORE_reserve (ret->dsh, ret->reserve_space, ret->reserve_entries, UINT_MAX, UINT_MAX, GNUNET_TIME_UNIT_FOREVER_REL, &finish_reserve, ret); } else { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ret->upload_task); ret->upload_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, ret); } return ret; } /** * Signal the FS's progress function that we are stopping * an upload. * * @param cls closure (of type `struct GNUNET_FS_PublishContext *`) * @param fi the entry in the publish-structure * @param length length of the file or directory * @param meta metadata for the file or directory (can be modified) * @param uri pointer to the keywords that will be used for this entry (can be modified) * @param bo block options (can be modified) * @param do_index should we index? * @param client_info pointer to client context set upon creation (can be modified) * @return #GNUNET_OK to continue (always) */ static int fip_signal_stop (void *cls, struct GNUNET_FS_FileInformation *fi, uint64_t length, struct GNUNET_CONTAINER_MetaData *meta, struct GNUNET_FS_Uri **uri, struct GNUNET_FS_BlockOptions *bo, int *do_index, void **client_info) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_ProgressInfo pi; uint64_t off; if (GNUNET_YES == pc->skip_next_fi_callback) { pc->skip_next_fi_callback = GNUNET_NO; return GNUNET_OK; } if (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (meta)) { /* process entries in directory first */ pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (fi, &fip_signal_stop, pc); } if (fi->serialization != NULL) { GNUNET_FS_remove_sync_file_ (pc->h, GNUNET_FS_SYNC_PATH_FILE_INFO, fi->serialization); GNUNET_free (fi->serialization); fi->serialization = NULL; } off = (fi->chk_uri == NULL) ? 0 : length; pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, fi, off)); *client_info = NULL; return GNUNET_OK; } /** * Stop an upload. Will abort incomplete uploads (but * not remove blocks that have already been publishd) or * simply clean up the state for completed uploads. * Must NOT be called from within the event callback! * * @param pc context for the upload to stop */ void GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc) { struct GNUNET_FS_ProgressInfo pi; uint64_t off; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish stop called\n"); GNUNET_FS_end_top (pc->h, pc->top); if (NULL != pc->ksk_pc) { GNUNET_FS_publish_ksk_cancel (pc->ksk_pc); pc->ksk_pc = NULL; } if (NULL != pc->sks_pc) { GNUNET_FS_publish_sks_cancel (pc->sks_pc); pc->sks_pc = NULL; } if (GNUNET_SCHEDULER_NO_TASK != pc->upload_task) { GNUNET_SCHEDULER_cancel (pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_NO_TASK; } pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_stop, pc); if (pc->fi->serialization != NULL) { GNUNET_FS_remove_sync_file_ (pc->h, GNUNET_FS_SYNC_PATH_FILE_INFO, pc->fi->serialization); GNUNET_free (pc->fi->serialization); pc->fi->serialization = NULL; } off = (pc->fi->chk_uri == NULL) ? 0 : GNUNET_ntohll (pc->fi->chk_uri->data.chk.file_length); if (pc->serialization != NULL) { GNUNET_FS_remove_sync_file_ (pc->h, GNUNET_FS_SYNC_PATH_MASTER_PUBLISH, pc->serialization); GNUNET_free (pc->serialization); pc->serialization = NULL; } if (NULL != pc->qre) { GNUNET_DATASTORE_cancel (pc->qre); pc->qre = NULL; } pi.status = GNUNET_FS_STATUS_PUBLISH_STOPPED; GNUNET_break (NULL == GNUNET_FS_publish_make_status_ (&pi, pc, pc->fi, off)); publish_cleanup (pc); } /* end of fs_publish.c */ gnunet-0.10.1/src/fs/gnunet-download.c0000644000175000017500000002434012225777502014476 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-download.c * @brief downloading for files on GNUnet * @author Christian Grothoff * @author Krista Bennett * @author James Blackwell * @author Igor Wronsky */ #include "platform.h" #include "gnunet_fs_service.h" static int ret; static int verbose; static int delete_incomplete; static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_FS_Handle *ctx; static struct GNUNET_FS_DownloadContext *dc; static unsigned int anonymity = 1; static unsigned int parallelism = 16; static unsigned int request_parallelism = 4092; static int do_recursive; static char *filename; static int local_only; static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_stop (ctx); ctx = NULL; } static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != dc) { GNUNET_FS_download_stop (dc, delete_incomplete); dc = NULL; } } /** * Display progress bar (if tty). * * @param x current position in the download * @param n total size of the download * @param w desired number of steps in the progress bar */ static void display_bar (unsigned long long x, unsigned long long n, unsigned int w) { char buf[w + 20]; unsigned int p; unsigned int endeq; float ratio_complete; #if !WINDOWS if (0 == isatty (1)) return; #else if (FILE_TYPE_CHAR != GetFileType (GetStdHandle (STD_OUTPUT_HANDLE))) return; #endif ratio_complete = x/(float)n; endeq = ratio_complete * w; GNUNET_snprintf (buf, sizeof (buf), "%3d%% [", (int)(ratio_complete*100) ); for (p=0; pstatus) { case GNUNET_FS_STATUS_DOWNLOAD_START: if (verbose > 1) FPRINTF (stderr, _("Starting download `%s'.\n"), info->value.download.filename); break; case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: if (verbose) { s = GNUNET_strdup (GNUNET_STRINGS_relative_time_to_string (info->value.download.eta, GNUNET_YES)); if (info->value.download.specifics.progress.block_download_duration.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) s2 = _(""); else s2 = GNUNET_STRINGS_relative_time_to_string ( info->value.download.specifics.progress.block_download_duration, GNUNET_YES); t = GNUNET_STRINGS_byte_size_fancy (info->value.download.completed * 1000LL / (info->value.download. duration.rel_value_us + 1)); FPRINTF (stdout, _("Downloading `%s' at %llu/%llu (%s remaining, %s/s). Block took %s to download\n"), info->value.download.filename, (unsigned long long) info->value.download.completed, (unsigned long long) info->value.download.size, s, t, s2); GNUNET_free (s); GNUNET_free (t); } else { display_bar (info->value.download.completed, info->value.download.size, 60); } break; case GNUNET_FS_STATUS_DOWNLOAD_ERROR: #if !WINDOWS if (0 != isatty (1)) fprintf (stdout, "\n"); #else if (FILE_TYPE_CHAR == GetFileType (GetStdHandle (STD_OUTPUT_HANDLE))) fprintf (stdout, "\n"); #endif FPRINTF (stderr, _("Error downloading: %s.\n"), info->value.download.specifics.error.message); GNUNET_SCHEDULER_shutdown (); break; case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: s = GNUNET_STRINGS_byte_size_fancy (info->value.download.completed * 1000 / (info->value.download. duration.rel_value_us + 1)); #if !WINDOWS if (0 != isatty (1)) fprintf (stdout, "\n"); #else if (FILE_TYPE_CHAR == GetFileType (GetStdHandle (STD_OUTPUT_HANDLE))) fprintf (stdout, "\n"); #endif FPRINTF (stdout, _("Downloading `%s' done (%s/s).\n"), info->value.download.filename, s); GNUNET_free (s); if (info->value.download.dc == dc) GNUNET_SCHEDULER_shutdown (); break; case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: if (info->value.download.dc == dc) GNUNET_SCHEDULER_add_continuation (&cleanup_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: break; default: FPRINTF (stderr, _("Unexpected status: %d\n"), info->status); break; } return NULL; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_FS_Uri *uri; char *emsg; enum GNUNET_FS_DownloadOptions options; if (NULL == args[0]) { FPRINTF (stderr, "%s", _("You need to specify a URI argument.\n")); return; } uri = GNUNET_FS_uri_parse (args[0], &emsg); if (NULL == uri) { FPRINTF (stderr, _("Failed to parse URI: %s\n"), emsg); GNUNET_free (emsg); ret = 1; return; } if ((!GNUNET_FS_uri_test_chk (uri)) && (!GNUNET_FS_uri_test_loc (uri))) { FPRINTF (stderr, "%s", _("Only CHK or LOC URIs supported.\n")); ret = 1; GNUNET_FS_uri_destroy (uri); return; } if (NULL == filename) { FPRINTF (stderr, "%s", _("Target filename must be specified.\n")); ret = 1; GNUNET_FS_uri_destroy (uri); return; } cfg = c; ctx = GNUNET_FS_start (cfg, "gnunet-download", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM, parallelism, GNUNET_FS_OPTIONS_REQUEST_PARALLELISM, request_parallelism, GNUNET_FS_OPTIONS_END); if (NULL == ctx) { FPRINTF (stderr, _("Could not initialize `%s' subsystem.\n"), "FS"); GNUNET_FS_uri_destroy (uri); ret = 1; return; } options = GNUNET_FS_DOWNLOAD_OPTION_NONE; if (do_recursive) options |= GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE; if (local_only) options |= GNUNET_FS_DOWNLOAD_OPTION_LOOPBACK_ONLY; dc = GNUNET_FS_download_start (ctx, uri, NULL, filename, NULL, 0, GNUNET_FS_uri_chk_get_file_size (uri), anonymity, options, NULL, NULL); GNUNET_FS_uri_destroy (uri); if (dc == NULL) { GNUNET_FS_stop (ctx); ctx = NULL; return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function to download GNUnet. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'a', "anonymity", "LEVEL", gettext_noop ("set the desired LEVEL of receiver-anonymity"), 1, &GNUNET_GETOPT_set_uint, &anonymity}, {'D', "delete-incomplete", NULL, gettext_noop ("delete incomplete downloads (when aborted with CTRL-C)"), 0, &GNUNET_GETOPT_set_one, &delete_incomplete}, {'n', "no-network", NULL, gettext_noop ("only search the local peer (no P2P network search)"), 0, &GNUNET_GETOPT_set_uint, &local_only}, {'o', "output", "FILENAME", gettext_noop ("write the file to FILENAME"), 1, &GNUNET_GETOPT_set_string, &filename}, {'p', "parallelism", "DOWNLOADS", gettext_noop ("set the maximum number of parallel downloads that is allowed"), 1, &GNUNET_GETOPT_set_uint, ¶llelism}, {'r', "request-parallelism", "REQUESTS", gettext_noop ("set the maximum number of parallel requests for blocks that is allowed"), 1, &GNUNET_GETOPT_set_uint, &request_parallelism}, {'R', "recursive", NULL, gettext_noop ("download a GNUnet directory recursively"), 0, &GNUNET_GETOPT_set_one, &do_recursive}, {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_increment_value, &verbose}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-download [OPTIONS] URI", gettext_noop ("Download files from GNUnet using a GNUnet CHK or LOC URI (gnunet://fs/chk/...)"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-download.c */ gnunet-0.10.1/src/fs/gnunet-fs.c0000644000175000017500000000646712225777502013311 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-fs.c * @brief special file-sharing functions * @author Christian Grothoff */ #include "platform.h" #include "gnunet_fs_service.h" /** * Return value. */ static int ret; /** * Handle to FS service. */ static struct GNUNET_FS_Handle *fs; /** * Option -i given? */ static int list_indexed_files; /** * Option -v given? */ static int verbose; /** * Print indexed filenames to stdout. * * @param cls closure * @param filename the name of the file * @param file_id hash of the contents of the indexed file * @return GNUNET_OK to continue iteration */ static int print_indexed (void *cls, const char *filename, const struct GNUNET_HashCode * file_id) { if (NULL == filename) { GNUNET_FS_stop (fs); fs = NULL; return GNUNET_OK; } if (verbose) FPRINTF (stdout, "%s: %s\n", GNUNET_h2s (file_id), filename); else FPRINTF (stdout, "%s\n", filename); return GNUNET_OK; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { if (list_indexed_files) { fs = GNUNET_FS_start (cfg, "gnunet-fs", NULL, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); if (NULL == fs) { ret = 1; return; } if (NULL == GNUNET_FS_get_indexed_files (fs, &print_indexed, NULL)) { ret = 2; GNUNET_FS_stop (fs); fs = NULL; return; } } } /** * The main function to access special file-sharing functions. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static struct GNUNET_GETOPT_CommandLineOption options[] = { {'i', "list-indexed", NULL, gettext_noop ("print a list of all indexed files"), 0, &GNUNET_GETOPT_set_one, &list_indexed_files}, GNUNET_GETOPT_OPTION_VERBOSE (&verbose), GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-fs [OPTIONS]", gettext_noop ("Special file-sharing operations"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-fs.c */ gnunet-0.10.1/src/fs/fs_sharetree.c0000644000175000017500000002754712225777502014057 00000000000000/* This file is part of GNUnet (C) 2005-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_sharetree.c * @brief code to manipulate the 'struct GNUNET_FS_ShareTreeItem' tree * @author LRN * @author Christian Grothoff */ #include "platform.h" #include "gnunet_fs_service.h" #include "gnunet_scheduler_lib.h" #include /** * Entry for each unique keyword to track how often * it occured. Contains the keyword and the counter. */ struct KeywordCounter { /** * This is a doubly-linked list */ struct KeywordCounter *prev; /** * This is a doubly-linked list */ struct KeywordCounter *next; /** * Keyword that was found. */ const char *value; /** * How many files have this keyword? */ unsigned int count; }; /** * Aggregate information we keep for meta data in each directory. */ struct MetaCounter { /** * This is a doubly-linked list */ struct MetaCounter *prev; /** * This is a doubly-linked list */ struct MetaCounter *next; /** * Name of the plugin that provided that piece of metadata */ const char *plugin_name; /** * MIME-type of the metadata itself */ const char *data_mime_type; /** * The actual meta data. */ const char *data; /** * Number of bytes in 'data'. */ size_t data_size; /** * Type of the data */ enum EXTRACTOR_MetaType type; /** * Format of the data */ enum EXTRACTOR_MetaFormat format; /** * How many files have meta entries matching this value? * (type and format do not have to match). */ unsigned int count; }; /** * A structure that forms a singly-linked list that serves as a stack * for metadata-processing function. */ struct TrimContext { /** * Map from the hash over the keyword to an 'struct KeywordCounter *' * counter that says how often this keyword was * encountered in the current directory. */ struct GNUNET_CONTAINER_MultiHashMap *keywordcounter; /** * Map from the hash over the metadata to an 'struct MetaCounter *' * counter that says how often this metadata was * encountered in the current directory. */ struct GNUNET_CONTAINER_MultiHashMap *metacounter; /** * Position we are currently manipulating. */ struct GNUNET_FS_ShareTreeItem *pos; /** * Number of times an item has to be found to be moved to the parent. */ unsigned int move_threshold; }; /** * Add the given keyword to the keyword statistics tracker. * * @param cls the multihashmap we store the keyword counters in * @param keyword the keyword to count * @param is_mandatory ignored * @return always GNUNET_OK */ static int add_to_keyword_counter (void *cls, const char *keyword, int is_mandatory) { struct GNUNET_CONTAINER_MultiHashMap *mcm = cls; struct KeywordCounter *cnt; struct GNUNET_HashCode hc; size_t klen; klen = strlen (keyword) + 1; GNUNET_CRYPTO_hash (keyword, klen - 1, &hc); cnt = GNUNET_CONTAINER_multihashmap_get (mcm, &hc); if (cnt == NULL) { cnt = GNUNET_malloc (sizeof (struct KeywordCounter) + klen); cnt->value = (const char *) &cnt[1]; memcpy (&cnt[1], keyword, klen); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (mcm, &hc, cnt, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } cnt->count++; return GNUNET_OK; } /** * Function called on each meta data item. Increments the * respective counter. * * @param cls the container multihashmap to update * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_len number of bytes in data * @return 0 to continue extracting / iterating */ static int add_to_meta_counter (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len) { struct GNUNET_CONTAINER_MultiHashMap *map = cls; struct GNUNET_HashCode key; struct MetaCounter *cnt; GNUNET_CRYPTO_hash (data, data_len, &key); cnt = GNUNET_CONTAINER_multihashmap_get (map, &key); if (NULL == cnt) { cnt = GNUNET_new (struct MetaCounter); cnt->data = data; cnt->data_size = data_len; cnt->plugin_name = plugin_name; cnt->type = type; cnt->format = format; cnt->data_mime_type = data_mime_type; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, &key, cnt, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } cnt->count++; return 0; } /** * Remove keywords above the threshold. * * @param cls the 'struct TrimContext' with the pos to remove the keywords from * @param keyword the keyword to check * @param is_mandatory ignored * @return always GNUNET_OK */ static int remove_high_frequency_keywords (void *cls, const char *keyword, int is_mandatory) { struct TrimContext *tc = cls; struct KeywordCounter *counter; struct GNUNET_HashCode hc; size_t klen; klen = strlen (keyword) + 1; GNUNET_CRYPTO_hash (keyword, klen - 1, &hc); counter = GNUNET_CONTAINER_multihashmap_get (tc->keywordcounter, &hc); GNUNET_assert (NULL != counter); if (counter->count < tc->move_threshold) return GNUNET_OK; GNUNET_FS_uri_ksk_remove_keyword (tc->pos->ksk_uri, counter->value); return GNUNET_OK; } /** * Move "frequent" keywords over to the target ksk uri, free the * counters. * * @param cls the 'struct TrimContext' * @param key key of the entry * @param value the 'struct KeywordCounter' * @return GNUNET_YES (always) */ static int migrate_and_drop_keywords (void *cls, const struct GNUNET_HashCode * key, void *value) { struct TrimContext *tc = cls; struct KeywordCounter *counter = value; if (counter->count >= tc->move_threshold) { if (NULL == tc->pos->ksk_uri) tc->pos->ksk_uri = GNUNET_FS_uri_ksk_create_from_args (1, &counter->value); else GNUNET_FS_uri_ksk_add_keyword (tc->pos->ksk_uri, counter->value, GNUNET_NO); } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (tc->keywordcounter, key, counter)); GNUNET_free (counter); return GNUNET_YES; } /** * Copy "frequent" metadata items over to the * target metadata container, free the counters. * * @param cls the 'struct TrimContext' * @param key key of the entry * @param value the 'struct KeywordCounter' * @return GNUNET_YES (always) */ static int migrate_and_drop_metadata (void *cls, const struct GNUNET_HashCode * key, void *value) { struct TrimContext *tc = cls; struct MetaCounter *counter = value; if (counter->count >= tc->move_threshold) { if (NULL == tc->pos->meta) tc->pos->meta = GNUNET_CONTAINER_meta_data_create (); GNUNET_CONTAINER_meta_data_insert (tc->pos->meta, counter->plugin_name, counter->type, counter->format, counter->data_mime_type, counter->data, counter->data_size); } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (tc->metacounter, key, counter)); GNUNET_free (counter); return GNUNET_YES; } /** * Process a share item tree, moving frequent keywords up and * copying frequent metadata up. * * @param tc trim context with hash maps to use * @param tree tree to trim */ static void share_tree_trim (struct TrimContext *tc, struct GNUNET_FS_ShareTreeItem *tree) { struct GNUNET_FS_ShareTreeItem *pos; unsigned int num_children; /* first, trim all children */ num_children = 0; for (pos = tree->children_head; NULL != pos; pos = pos->next) { share_tree_trim (tc, pos); num_children++; } /* consider adding filename to directory meta data */ if (tree->is_directory == GNUNET_YES) { const char *user = getenv ("USER"); if ( (user == NULL) || (0 != strncasecmp (user, tree->short_filename, strlen(user)))) { /* only use filename if it doesn't match $USER */ if (NULL == tree->meta) tree->meta = GNUNET_CONTAINER_meta_data_create (); GNUNET_CONTAINER_meta_data_insert (tree->meta, "", EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", tree->short_filename, strlen (tree->short_filename) + 1); } } if (1 >= num_children) return; /* nothing to trim */ /* now, count keywords and meta data in children */ for (pos = tree->children_head; NULL != pos; pos = pos->next) { if (NULL != pos->meta) GNUNET_CONTAINER_meta_data_iterate (pos->meta, &add_to_meta_counter, tc->metacounter); if (NULL != pos->ksk_uri) GNUNET_FS_uri_ksk_get_keywords (pos->ksk_uri, &add_to_keyword_counter, tc->keywordcounter); } /* calculate threshold for moving keywords / meta data */ tc->move_threshold = 1 + (num_children / 2); /* remove high-frequency keywords from children */ for (pos = tree->children_head; NULL != pos; pos = pos->next) { tc->pos = pos; if (NULL != pos->ksk_uri) { struct GNUNET_FS_Uri *ksk_uri_copy = GNUNET_FS_uri_dup (pos->ksk_uri); GNUNET_FS_uri_ksk_get_keywords (ksk_uri_copy, &remove_high_frequency_keywords, tc); GNUNET_FS_uri_destroy (ksk_uri_copy); } } /* add high-frequency meta data and keywords to parent */ tc->pos = tree; GNUNET_CONTAINER_multihashmap_iterate (tc->keywordcounter, &migrate_and_drop_keywords, tc); GNUNET_CONTAINER_multihashmap_iterate (tc->metacounter, &migrate_and_drop_metadata, tc); } /** * Process a share item tree, moving frequent keywords up and * copying frequent metadata up. * * @param toplevel toplevel directory in the tree, returned by the scanner */ void GNUNET_FS_share_tree_trim (struct GNUNET_FS_ShareTreeItem *toplevel) { struct TrimContext tc; if (toplevel == NULL) return; tc.keywordcounter = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); tc.metacounter = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); share_tree_trim (&tc, toplevel); GNUNET_CONTAINER_multihashmap_destroy (tc.keywordcounter); GNUNET_CONTAINER_multihashmap_destroy (tc.metacounter); } /** * Release memory of a share item tree. * * @param toplevel toplevel of the tree to be freed */ void GNUNET_FS_share_tree_free (struct GNUNET_FS_ShareTreeItem *toplevel) { struct GNUNET_FS_ShareTreeItem *pos; while (NULL != (pos = toplevel->children_head)) GNUNET_FS_share_tree_free (pos); if (NULL != toplevel->parent) GNUNET_CONTAINER_DLL_remove (toplevel->parent->children_head, toplevel->parent->children_tail, toplevel); if (NULL != toplevel->meta) GNUNET_CONTAINER_meta_data_destroy (toplevel->meta); if (NULL != toplevel->ksk_uri) GNUNET_FS_uri_destroy (toplevel->ksk_uri); GNUNET_free_non_null (toplevel->filename); GNUNET_free_non_null (toplevel->short_filename); GNUNET_free (toplevel); } /* end fs_sharetree.c */ gnunet-0.10.1/src/fs/gnunet-unindex.c0000644000175000017500000001230612225777502014340 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-unindex.c * @brief unindex files published on GNUnet * @author Christian Grothoff * @author Krista Bennett * @author James Blackwell * @author Igor Wronsky */ #include "platform.h" #include "gnunet_fs_service.h" static int ret; static int verbose; static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_FS_Handle *ctx; static struct GNUNET_FS_UnindexContext *uc; static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_stop (ctx); ctx = NULL; } static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_UnindexContext *u; if (uc != NULL) { u = uc; uc = NULL; GNUNET_FS_unindex_stop (u); } } /** * Called by FS client to give information about the progress of an * operation. * * @param cls closure * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the GNUNET_FS_ProgressInfo struct. */ static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { const char *s; switch (info->status) { case GNUNET_FS_STATUS_UNINDEX_START: break; case GNUNET_FS_STATUS_UNINDEX_PROGRESS: if (verbose) { s = GNUNET_STRINGS_relative_time_to_string (info->value.unindex.eta, GNUNET_YES); FPRINTF (stdout, _("Unindexing at %llu/%llu (%s remaining)\n"), (unsigned long long) info->value.unindex.completed, (unsigned long long) info->value.unindex.size, s); } break; case GNUNET_FS_STATUS_UNINDEX_ERROR: FPRINTF (stderr, _("Error unindexing: %s.\n"), info->value.unindex.specifics.error.message); GNUNET_SCHEDULER_shutdown (); break; case GNUNET_FS_STATUS_UNINDEX_COMPLETED: FPRINTF (stdout, "%s", _("Unindexing done.\n")); GNUNET_SCHEDULER_shutdown (); break; case GNUNET_FS_STATUS_UNINDEX_STOPPED: GNUNET_SCHEDULER_add_continuation (&cleanup_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; default: FPRINTF (stderr, _("Unexpected status: %d\n"), info->status); break; } return NULL; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { /* check arguments */ if ((args[0] == NULL) || (args[1] != NULL)) { printf (_("You must specify one and only one filename for unindexing.\n")); ret = -1; return; } cfg = c; ctx = GNUNET_FS_start (cfg, "gnunet-unindex", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); if (NULL == ctx) { FPRINTF (stderr, _("Could not initialize `%s' subsystem.\n"), "FS"); ret = 1; return; } uc = GNUNET_FS_unindex_start (ctx, args[0], NULL); if (NULL == uc) { FPRINTF (stderr, "%s", _("Could not start unindex operation.\n")); GNUNET_FS_stop (ctx); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function to unindex content. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_set_one, &verbose}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-unindex [OPTIONS] FILENAME", gettext_noop ("Unindex a file that was previously indexed with gnunet-publish."), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-unindex.c */ gnunet-0.10.1/src/fs/fs_tree.c0000644000175000017500000003204012255010511012773 00000000000000/* This file is part of GNUnet. (C) 2009-2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_tree.c * @brief Merkle-tree-ish-CHK file encoding for GNUnet * @see http://gnunet.org/encoding.php3 * @author Krista Bennett * @author Christian Grothoff */ #include "platform.h" #include "fs_tree.h" /** * Context for an ECRS-based file encoder that computes * the Merkle-ish-CHK tree. */ struct GNUNET_FS_TreeEncoder { /** * Global FS context. */ struct GNUNET_FS_Handle *h; /** * Closure for all callbacks. */ void *cls; /** * Function to call on encrypted blocks. */ GNUNET_FS_TreeBlockProcessor proc; /** * Function to call with progress information. */ GNUNET_FS_TreeProgressCallback progress; /** * Function to call to receive input data. */ GNUNET_FS_DataReader reader; /** * Function to call once we're done with processing. */ GNUNET_SCHEDULER_Task cont; /** * Set to an error message (if we had an error). */ char *emsg; /** * Set to the URI (upon successful completion) */ struct GNUNET_FS_Uri *uri; /** * Overall file size. */ uint64_t size; /** * How far are we? */ uint64_t publish_offset; /** * How deep are we? Depth 0 is for the DBLOCKs. */ unsigned int current_depth; /** * How deep is the tree? Always > 0. */ unsigned int chk_tree_depth; /** * In-memory cache of the current CHK tree. * This struct will contain the CHK values * from the root to the currently processed * node in the tree as identified by * "current_depth" and "publish_offset". * The "chktree" will be initially NULL, * then allocated to a sufficient number of * entries for the size of the file and * finally freed once the upload is complete. */ struct ContentHashKey *chk_tree; /** * Are we currently in 'GNUNET_FS_tree_encoder_next'? * Flag used to prevent recursion. */ int in_next; }; /** * Compute the depth of the CHK tree. * * @param flen file length for which to compute the depth * @return depth of the tree, always > 0. A depth of 1 means only a DBLOCK. */ unsigned int GNUNET_FS_compute_depth (uint64_t flen) { unsigned int treeDepth; uint64_t fl; treeDepth = 1; fl = DBLOCK_SIZE; while (fl < flen) { treeDepth++; if (fl * CHK_PER_INODE < fl) { /* integer overflow, this is a HUGE file... */ return treeDepth; } fl = fl * CHK_PER_INODE; } return treeDepth; } /** * Calculate how many bytes of payload a block tree of the given * depth MAY correspond to at most (this function ignores the fact that * some blocks will only be present partially due to the total file * size cutting some blocks off at the end). * * @param depth depth of the block. depth==0 is a DBLOCK. * @return number of bytes of payload a subtree of this depth may correspond to */ uint64_t GNUNET_FS_tree_compute_tree_size (unsigned int depth) { uint64_t rsize; unsigned int i; rsize = DBLOCK_SIZE; for (i = 0; i < depth; i++) rsize *= CHK_PER_INODE; return rsize; } /** * Compute the size of the current IBLOCK. The encoder is * triggering the calculation of the size of an IBLOCK at the * *end* (hence end_offset) of its construction. The IBLOCK * maybe a full or a partial IBLOCK, and this function is to * calculate how long it should be. * * @param depth depth of the IBlock in the tree, 0 would be a DBLOCK, * must be > 0 (this function is for IBLOCKs only!) * @param end_offset current offset in the payload (!) of the overall file, * must be > 0 (since this function is called at the * end of a block). * @return size of the corresponding IBlock */ static uint16_t GNUNET_FS_tree_compute_iblock_size (unsigned int depth, uint64_t end_offset) { unsigned int ret; uint64_t mod; uint64_t bds; GNUNET_assert (depth > 0); GNUNET_assert (end_offset > 0); bds = GNUNET_FS_tree_compute_tree_size (depth); mod = end_offset % bds; if (0 == mod) { /* we were triggered at the end of a full block */ ret = CHK_PER_INODE; } else { /* we were triggered at the end of the file */ bds /= CHK_PER_INODE; ret = mod / bds; if (0 != mod % bds) ret++; } return (uint16_t) (ret * sizeof (struct ContentHashKey)); } /** * Compute how many bytes of data should be stored in * the specified block. * * @param fsize overall file size, must be > 0. * @param offset offset in the original data corresponding * to the beginning of the tree induced by the block; * must be <= fsize * @param depth depth of the node in the tree, 0 for DBLOCK * @return number of bytes stored in this node */ size_t GNUNET_FS_tree_calculate_block_size (uint64_t fsize, uint64_t offset, unsigned int depth) { size_t ret; uint64_t rsize; uint64_t epos; unsigned int chks; GNUNET_assert (fsize > 0); GNUNET_assert (offset <= fsize); if (depth == 0) { ret = DBLOCK_SIZE; if ((offset + ret > fsize) || (offset + ret < offset)) ret = (size_t) (fsize - offset); return ret; } rsize = GNUNET_FS_tree_compute_tree_size (depth - 1); epos = offset + rsize * CHK_PER_INODE; if ((epos < offset) || (epos > fsize)) epos = fsize; /* round up when computing #CHKs in our IBlock */ chks = (epos - offset + rsize - 1) / rsize; GNUNET_assert (chks <= CHK_PER_INODE); return chks * sizeof (struct ContentHashKey); } /** * Initialize a tree encoder. This function will call @a proc and * "progress" on each block in the tree. Once all blocks have been * processed, "cont" will be scheduled. The @a reader will be called * to obtain the (plaintext) blocks for the file. Note that this * function will not actually call @a proc. The client must * call #GNUNET_FS_tree_encoder_next to trigger encryption (and * calling of @a proc) for the each block. * * @param h the global FS context * @param size overall size of the file to encode * @param cls closure for reader, proc, progress and cont * @param reader function to call to read plaintext data * @param proc function to call on each encrypted block * @param progress function to call with progress information * @param cont function to call when done */ struct GNUNET_FS_TreeEncoder * GNUNET_FS_tree_encoder_create (struct GNUNET_FS_Handle *h, uint64_t size, void *cls, GNUNET_FS_DataReader reader, GNUNET_FS_TreeBlockProcessor proc, GNUNET_FS_TreeProgressCallback progress, GNUNET_SCHEDULER_Task cont) { struct GNUNET_FS_TreeEncoder *te; te = GNUNET_new (struct GNUNET_FS_TreeEncoder); te->h = h; te->size = size; te->cls = cls; te->reader = reader; te->proc = proc; te->progress = progress; te->cont = cont; te->chk_tree_depth = GNUNET_FS_compute_depth (size); te->chk_tree = GNUNET_malloc (te->chk_tree_depth * CHK_PER_INODE * sizeof (struct ContentHashKey)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created tree encoder for file with %llu bytes and depth %u\n", (unsigned long long) size, te->chk_tree_depth); return te; } /** * Compute the offset of the CHK for the * current block in the IBlock above. * * @param depth depth of the IBlock in the tree (aka overall * number of tree levels minus depth); 0 == DBlock * @param end_offset current offset in the overall file, * at the *beginning* of the block for DBLOCKs (depth==0), * otherwise at the *end* of the block (exclusive) * @return (array of CHKs') offset in the above IBlock */ static unsigned int compute_chk_offset (unsigned int depth, uint64_t end_offset) { uint64_t bds; unsigned int ret; bds = GNUNET_FS_tree_compute_tree_size (depth); if (depth > 0) end_offset--; /* round down since for depth > 0 offset is at the END of the block */ ret = end_offset / bds; return ret % CHK_PER_INODE; } /** * Encrypt the next block of the file (and call proc and progress * accordingly; or of course "cont" if we have already completed * encoding of the entire file). * * @param te tree encoder to use */ void GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder *te) { struct ContentHashKey *mychk; const void *pt_block; uint16_t pt_size; char iob[DBLOCK_SIZE]; char enc[DBLOCK_SIZE]; struct GNUNET_CRYPTO_SymmetricSessionKey sk; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; unsigned int off; GNUNET_assert (GNUNET_NO == te->in_next); te->in_next = GNUNET_YES; if (te->chk_tree_depth == te->current_depth) { off = CHK_PER_INODE * (te->chk_tree_depth - 1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TE done, reading CHK `%s' from %u\n", GNUNET_h2s (&te->chk_tree[off].query), off); te->uri = GNUNET_new (struct GNUNET_FS_Uri); te->uri->type = GNUNET_FS_URI_CHK; te->uri->data.chk.chk = te->chk_tree[off]; te->uri->data.chk.file_length = GNUNET_htonll (te->size); te->in_next = GNUNET_NO; te->cont (te->cls, NULL); return; } if (0 == te->current_depth) { /* read DBLOCK */ pt_size = GNUNET_MIN (DBLOCK_SIZE, te->size - te->publish_offset); if (pt_size != te->reader (te->cls, te->publish_offset, pt_size, iob, &te->emsg)) { te->in_next = GNUNET_NO; te->cont (te->cls, NULL); return; } pt_block = iob; } else { pt_size = GNUNET_FS_tree_compute_iblock_size (te->current_depth, te->publish_offset); pt_block = &te->chk_tree[(te->current_depth - 1) * CHK_PER_INODE]; } off = compute_chk_offset (te->current_depth, te->publish_offset); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TE is at offset %llu and depth %u with block size %u and target-CHK-offset %u\n", (unsigned long long) te->publish_offset, te->current_depth, (unsigned int) pt_size, (unsigned int) off); mychk = &te->chk_tree[te->current_depth * CHK_PER_INODE + off]; GNUNET_CRYPTO_hash (pt_block, pt_size, &mychk->key); GNUNET_CRYPTO_hash_to_aes_key (&mychk->key, &sk, &iv); GNUNET_CRYPTO_symmetric_encrypt (pt_block, pt_size, &sk, &iv, enc); GNUNET_CRYPTO_hash (enc, pt_size, &mychk->query); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TE calculates query to be `%s', stored at %u\n", GNUNET_h2s (&mychk->query), te->current_depth * CHK_PER_INODE + off); if (NULL != te->proc) te->proc (te->cls, mychk, te->publish_offset, te->current_depth, (0 == te->current_depth) ? GNUNET_BLOCK_TYPE_FS_DBLOCK : GNUNET_BLOCK_TYPE_FS_IBLOCK, enc, pt_size); if (NULL != te->progress) te->progress (te->cls, te->publish_offset, pt_block, pt_size, te->current_depth); if (0 == te->current_depth) { te->publish_offset += pt_size; if ((te->publish_offset == te->size) || (0 == te->publish_offset % (CHK_PER_INODE * DBLOCK_SIZE))) te->current_depth++; } else { if ((off == CHK_PER_INODE) || (te->publish_offset == te->size)) te->current_depth++; else te->current_depth = 0; } te->in_next = GNUNET_NO; } /** * Get the resulting URI from the encoding. * * @param te the tree encoder to clean up * @return uri set to the resulting URI (if encoding finished), NULL otherwise */ struct GNUNET_FS_Uri * GNUNET_FS_tree_encoder_get_uri (struct GNUNET_FS_TreeEncoder *te) { if (NULL != te->uri) return GNUNET_FS_uri_dup (te->uri); return NULL; } /** * Clean up a tree encoder and return information * about possible errors. * * @param te the tree encoder to clean up * @param emsg set to an error message (if an error occured * within the tree encoder; if this function is called * prior to completion and prior to an internal error, * both "*emsg" will be set to NULL). */ void GNUNET_FS_tree_encoder_finish (struct GNUNET_FS_TreeEncoder *te, char **emsg) { if (NULL != te->reader) { (void) te->reader (te->cls, UINT64_MAX, 0, 0, NULL); te->reader = NULL; } GNUNET_assert (GNUNET_NO == te->in_next); if (NULL != te->uri) GNUNET_FS_uri_destroy (te->uri); if (emsg != NULL) *emsg = te->emsg; else GNUNET_free_non_null (te->emsg); GNUNET_free (te->chk_tree); GNUNET_free (te); } /* end of fs_tree.c */ gnunet-0.10.1/src/fs/fs_namespace.c0000644000175000017500000005143112225777502014016 00000000000000/* This file is part of GNUnet (C) 2003-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_namespace.c * @brief publishing to namespaces, and tracking updateable entries * for our namespaces * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "fs_api.h" #include "fs_publish_ublock.h" /** * Information about an (updateable) node in the * namespace. */ struct NamespaceUpdateNode { /** * Identifier for this node. */ char *id; /** * Identifier of children of this node. */ char *update; /** * Metadata for this entry. */ struct GNUNET_CONTAINER_MetaData *md; /** * URI of this entry in the namespace. */ struct GNUNET_FS_Uri *uri; /** * Namespace update generation ID. Used to ensure * freshness of the tree_id. */ unsigned int nug; /** * TREE this entry belongs to (if nug is current). */ unsigned int tree_id; }; /** * Handle to update information for a namespace. */ struct GNUNET_FS_UpdateInformationGraph { /** * Handle to the FS service context. */ struct GNUNET_FS_Handle *h; /** * Array with information about nodes in the namespace. */ struct NamespaceUpdateNode **update_nodes; /** * Private key for the namespace. */ struct GNUNET_CRYPTO_EcdsaPrivateKey ns; /** * Hash map mapping identifiers of update nodes * to the update nodes (initialized on-demand). */ struct GNUNET_CONTAINER_MultiHashMap *update_map; /** * Size of the update nodes array. */ unsigned int update_node_count; /** * Reference counter. */ unsigned int rc; /** * Generator for unique nug numbers. */ unsigned int nug_gen; }; /** * Return the name of the directory in which we store * the update information graph for the given local namespace. * * @param h file-sharing handle * @param ns namespace handle * @return NULL on error, otherwise the name of the directory */ static char * get_update_information_directory (struct GNUNET_FS_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns) { char *dn; char *ret; struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_HashCode hc; struct GNUNET_CRYPTO_HashAsciiEncoded enc; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (h->cfg, "FS", "UPDATE_DIR", &dn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "fs", "UPDATE_DIR"); return NULL; } GNUNET_CRYPTO_ecdsa_key_get_public (ns, &pub); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &hc); GNUNET_CRYPTO_hash_to_enc (&hc, &enc); GNUNET_asprintf (&ret, "%s%s%s", dn, DIR_SEPARATOR_STR, (const char *) enc.encoding); GNUNET_free (dn); return ret; } /** * Release memory occupied by UIG datastructure. * * @param uig data structure to free */ static void free_update_information_graph (struct GNUNET_FS_UpdateInformationGraph *uig) { unsigned int i; struct NamespaceUpdateNode *nsn; for (i = 0; i < uig->update_node_count; i++) { nsn = uig->update_nodes[i]; GNUNET_CONTAINER_meta_data_destroy (nsn->md); GNUNET_FS_uri_destroy (nsn->uri); GNUNET_free (nsn->id); GNUNET_free (nsn->update); GNUNET_free (nsn); } GNUNET_array_grow (uig->update_nodes, uig->update_node_count, 0); if (NULL != uig->update_map) GNUNET_CONTAINER_multihashmap_destroy (uig->update_map); GNUNET_free (uig); } /** * Write a namespace's update node graph to a file. * * @param uig update information graph to dump */ static void write_update_information_graph (struct GNUNET_FS_UpdateInformationGraph *uig) { char *fn; struct GNUNET_BIO_WriteHandle *wh; unsigned int i; struct NamespaceUpdateNode *n; char *uris; fn = get_update_information_directory (uig->h, &uig->ns); wh = GNUNET_BIO_write_open (fn); if (NULL == wh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to open `%s' for writing: %s\n"), STRERROR (errno)); GNUNET_free (fn); return; } if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, uig->update_node_count)) goto END; for (i = 0; i < uig->update_node_count; i++) { n = uig->update_nodes[i]; uris = GNUNET_FS_uri_to_string (n->uri); if ((GNUNET_OK != GNUNET_BIO_write_string (wh, n->id)) || (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, n->md)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, n->update)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, uris))) { GNUNET_free (uris); break; } GNUNET_free (uris); } END: if (GNUNET_OK != GNUNET_BIO_write_close (wh)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to write `%s': %s\n"), STRERROR (errno)); GNUNET_free (fn); } /** * Read the namespace update node graph from a file. * * @param h FS handle to use * @param ns namespace to read * @return update graph, never NULL */ static struct GNUNET_FS_UpdateInformationGraph * read_update_information_graph (struct GNUNET_FS_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns) { struct GNUNET_FS_UpdateInformationGraph *uig; char *fn; struct GNUNET_BIO_ReadHandle *rh; unsigned int i; struct NamespaceUpdateNode *n; char *uris; uint32_t count; char *emsg; uig = GNUNET_new (struct GNUNET_FS_UpdateInformationGraph); uig->h = h; uig->ns = *ns; fn = get_update_information_directory (h, ns); if (GNUNET_YES != GNUNET_DISK_file_test (fn)) { GNUNET_free (fn); return uig; } rh = GNUNET_BIO_read_open (fn); if (NULL == rh) { GNUNET_free (fn); return uig; } if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &count)) { GNUNET_break (0); goto END; } if (count > 1024 * 1024) { GNUNET_break (0); goto END; } if (0 == count) goto END; uig->update_nodes = GNUNET_malloc (count * sizeof (struct NamespaceUpdateNode *)); for (i = 0; i < count; i++) { n = GNUNET_new (struct NamespaceUpdateNode); if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "identifier", &n->id, 1024)) || (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "meta", &n->md)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "update-id", &n->update, 1024)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "uri", &uris, 1024 * 2))) { GNUNET_break (0); GNUNET_free_non_null (n->id); GNUNET_free_non_null (n->update); if (n->md != NULL) GNUNET_CONTAINER_meta_data_destroy (n->md); GNUNET_free (n); break; } n->uri = GNUNET_FS_uri_parse (uris, &emsg); GNUNET_free (uris); if (n->uri == NULL) { GNUNET_break (0); GNUNET_free (emsg); GNUNET_free (n->id); GNUNET_free_non_null (n->update); GNUNET_CONTAINER_meta_data_destroy (n->md); GNUNET_free (n); break; } uig->update_nodes[i] = n; } uig->update_node_count = i; END: if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read `%s': %s\n"), fn, emsg); GNUNET_free (emsg); } GNUNET_free (fn); return uig; } /** * Context for the SKS publication. */ struct GNUNET_FS_PublishSksContext { /** * URI of the new entry in the namespace. */ struct GNUNET_FS_Uri *uri; /** * Namespace update node to add to namespace on success (or to be * deleted if publishing failed). */ struct NamespaceUpdateNode *nsn; /** * Namespace we're publishing to. */ struct GNUNET_CRYPTO_EcdsaPrivateKey ns; /** * Handle to the datastore. */ struct GNUNET_DATASTORE_Handle *dsh; /** * Handle to FS. */ struct GNUNET_FS_Handle *h; /** * Function to call once we're done. */ GNUNET_FS_PublishContinuation cont; /** * Closure for cont. */ void *cont_cls; /** * Handle for our UBlock operation request. */ struct GNUNET_FS_PublishUblockContext *uc; }; /** * Function called by the UBlock construction with * the result from the PUT (UBlock) request. * * @param cls closure of type "struct GNUNET_FS_PublishSksContext*" * @param msg error message (or NULL) */ static void sks_publish_cont (void *cls, const char *msg) { struct GNUNET_FS_PublishSksContext *psc = cls; struct GNUNET_FS_UpdateInformationGraph *uig; psc->uc = NULL; if (NULL != msg) { if (NULL != psc->cont) psc->cont (psc->cont_cls, NULL, msg); GNUNET_FS_publish_sks_cancel (psc); return; } if (NULL != psc->nsn) { /* FIXME: this can be done much more * efficiently by simply appending to the * file and overwriting the 4-byte header */ uig = read_update_information_graph (psc->h, &psc->ns); GNUNET_array_append (uig->update_nodes, uig->update_node_count, psc->nsn); psc->nsn = NULL; write_update_information_graph (uig); free_update_information_graph (uig); } if (NULL != psc->cont) psc->cont (psc->cont_cls, psc->uri, NULL); GNUNET_FS_publish_sks_cancel (psc); } /** * Publish an SBlock on GNUnet. * * @param h handle to the file sharing subsystem * @param ns namespace to publish in * @param identifier identifier to use * @param update update identifier to use * @param meta metadata to use * @param uri URI to refer to in the SBlock * @param bo block options * @param options publication options * @param cont continuation * @param cont_cls closure for cont * @return NULL on error ('cont' will still be called) */ struct GNUNET_FS_PublishSksContext * GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const char *identifier, const char *update, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_BlockOptions *bo, enum GNUNET_FS_PublishOptions options, GNUNET_FS_PublishContinuation cont, void *cont_cls) { struct GNUNET_FS_PublishSksContext *psc; struct GNUNET_FS_Uri *sks_uri; sks_uri = GNUNET_new (struct GNUNET_FS_Uri); sks_uri->type = GNUNET_FS_URI_SKS; sks_uri->data.sks.identifier = GNUNET_strdup (identifier); GNUNET_CRYPTO_ecdsa_key_get_public (ns, &sks_uri->data.sks.ns); psc = GNUNET_new (struct GNUNET_FS_PublishSksContext); psc->h = h; psc->uri = sks_uri; psc->cont = cont; psc->cont_cls = cont_cls; psc->ns = *ns; if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) { psc->dsh = GNUNET_DATASTORE_connect (h->cfg); if (NULL == psc->dsh) { sks_publish_cont (psc, _("Failed to connect to datastore.")); return NULL; } } if (NULL != update) { psc->nsn = GNUNET_new (struct NamespaceUpdateNode); psc->nsn->id = GNUNET_strdup (identifier); psc->nsn->update = GNUNET_strdup (update); psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta); psc->nsn->uri = GNUNET_FS_uri_dup (uri); } psc->uc = GNUNET_FS_publish_ublock_ (h, psc->dsh, identifier, update, ns, meta, uri, bo, options, &sks_publish_cont, psc); return psc; } /** * Abort the SKS publishing operation. * * @param psc context of the operation to abort. */ void GNUNET_FS_publish_sks_cancel (struct GNUNET_FS_PublishSksContext *psc) { if (NULL != psc->uc) { GNUNET_FS_publish_ublock_cancel_ (psc->uc); psc->uc = NULL; } if (NULL != psc->dsh) { GNUNET_DATASTORE_disconnect (psc->dsh, GNUNET_NO); psc->dsh = NULL; } GNUNET_FS_uri_destroy (psc->uri); if (NULL != psc->nsn) { GNUNET_CONTAINER_meta_data_destroy (psc->nsn->md); GNUNET_FS_uri_destroy (psc->nsn->uri); GNUNET_free (psc->nsn->id); GNUNET_free (psc->nsn->update); GNUNET_free (psc->nsn); } GNUNET_free (psc); } /** * Closure for 'process_update_node'. */ struct ProcessUpdateClosure { /** * Function to call for each node. */ GNUNET_FS_IdentifierProcessor ip; /** * Closure for 'ip'. */ void *ip_cls; }; /** * Call the iterator in the closure for each node. * * @param cls closure (of type 'struct ProcessUpdateClosure *') * @param key current key code * @param value value in the hash map (of type 'struct NamespaceUpdateNode *') * @return GNUNET_YES if we should continue to * iterate, * GNUNET_NO if not. */ static int process_update_node (void *cls, const struct GNUNET_HashCode *key, void *value) { struct ProcessUpdateClosure *pc = cls; struct NamespaceUpdateNode *nsn = value; pc->ip (pc->ip_cls, nsn->id, nsn->uri, nsn->md, nsn->update); return GNUNET_YES; } /** * Closure for 'find_trees'. */ struct FindTreeClosure { /** * UIG we are operating on. */ struct GNUNET_FS_UpdateInformationGraph *uig; /** * Array with 'head's of TREEs. */ struct NamespaceUpdateNode **tree_array; /** * Size of 'tree_array' */ unsigned int tree_array_size; /** * Current generational ID used. */ unsigned int nug; /** * Identifier for the current TREE, or UINT_MAX for none yet. */ unsigned int id; }; /** * Find all nodes reachable from the current node (including the * current node itself). If they are in no tree, add them to the * current one. If they are the head of another tree, merge the * trees. If they are in the middle of another tree, let them be. * We can tell that a node is already in an tree by checking if * its 'nug' field is set to the current 'nug' value. It is the * head of an tree if it is in the 'tree_array' under its respective * 'tree_id'. * * In short, we're trying to find the smallest number of tree to * cover a directed graph. * * @param cls closure (of type 'struct FindTreeClosure') * @param key current key code * @param value value in the hash map * @return GNUNET_YES if we should continue to * iterate, * GNUNET_NO if not. */ static int find_trees (void *cls, const struct GNUNET_HashCode *key, void *value) { struct FindTreeClosure *fc = cls; struct NamespaceUpdateNode *nsn = value; struct GNUNET_HashCode hc; if (nsn->nug == fc->nug) { if (UINT_MAX == nsn->tree_id) return GNUNET_YES; /* circular */ GNUNET_assert (nsn->tree_id < fc->tree_array_size); if (fc->tree_array[nsn->tree_id] != nsn) return GNUNET_YES; /* part of "another" (directed) TREE, * and not root of it, end trace */ if (nsn->tree_id == fc->id) return GNUNET_YES; /* that's our own root (can this be?) */ /* merge existing TREE, we have a root for both */ fc->tree_array[nsn->tree_id] = NULL; if (UINT_MAX == fc->id) fc->id = nsn->tree_id; /* take over ID */ } else { nsn->nug = fc->nug; nsn->tree_id = UINT_MAX; /* mark as undef */ /* trace */ GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc); GNUNET_CONTAINER_multihashmap_get_multiple (fc->uig->update_map, &hc, &find_trees, fc); } return GNUNET_YES; } /** * List all of the identifiers in the namespace for which we could * produce an update. Namespace updates form a graph where each node * has a name. Each node can have any number of URI/meta-data entries * which can each be linked to other nodes. Cycles are possible. * * Calling this function with "next_id" NULL will cause the library to * call "ip" with a root for each strongly connected component of the * graph (a root being a node from which all other nodes in the Tree * are reachable). * * Calling this function with "next_id" being the name of a node will * cause the library to call "ip" with all children of the node. Note * that cycles within the final tree are possible (including self-loops). * I know, odd definition of a tree, but the GUI will display an actual * tree (GtkTreeView), so that's what counts for the term here. * * @param h fs handle to use * @param ns namespace to inspect for updateable content * @param next_id ID to look for; use NULL to look for tree roots * @param ip function to call on each updateable identifier * @param ip_cls closure for ip */ void GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const char *next_id, GNUNET_FS_IdentifierProcessor ip, void *ip_cls) { unsigned int i; unsigned int nug; struct GNUNET_HashCode hc; struct NamespaceUpdateNode *nsn; struct ProcessUpdateClosure pc; struct FindTreeClosure fc; struct GNUNET_FS_UpdateInformationGraph *uig; uig = read_update_information_graph (h, ns); if (NULL == uig->update_nodes) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No updateable nodes found for ID `%s'\n", next_id); free_update_information_graph (uig); return; /* no nodes */ } uig->update_map = GNUNET_CONTAINER_multihashmap_create (2 + 3 * uig->update_node_count / 4, GNUNET_NO); for (i = 0; i < uig->update_node_count; i++) { nsn = uig->update_nodes[i]; GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); GNUNET_CONTAINER_multihashmap_put (uig->update_map, &hc, nsn, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } if (NULL != next_id) { GNUNET_CRYPTO_hash (next_id, strlen (next_id), &hc); pc.ip = ip; pc.ip_cls = ip_cls; GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, &process_update_node, &pc); free_update_information_graph (uig); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calculating TREEs to find roots of update trees\n"); /* Find heads of TREEs in update graph */ nug = ++uig->nug_gen; fc.tree_array = NULL; fc.tree_array_size = 0; for (i = 0; i < uig->update_node_count; i++) { nsn = uig->update_nodes[i]; if (nsn->nug == nug) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, nsn->nug); continue; /* already placed in TREE */ } GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc); nsn->nug = nug; nsn->tree_id = UINT_MAX; fc.id = UINT_MAX; fc.nug = nug; fc.uig = uig; GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, &find_trees, &fc); if (UINT_MAX == fc.id) { /* start new TREE */ for (fc.id = 0; fc.id < fc.tree_array_size; fc.id++) { if (NULL == fc.tree_array[fc.id]) { fc.tree_array[fc.id] = nsn; nsn->tree_id = fc.id; break; } } if (fc.id == fc.tree_array_size) { GNUNET_array_append (fc.tree_array, fc.tree_array_size, nsn); nsn->tree_id = fc.id; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting new TREE %u with node `%s'\n", nsn->tree_id, nsn->id); /* put all nodes with same identifier into this TREE */ GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); fc.id = nsn->tree_id; fc.nug = nug; fc.uig = uig; GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, &find_trees, &fc); } else { /* make head of TREE "id" */ fc.tree_array[fc.id] = nsn; nsn->tree_id = fc.id; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, fc.id); } for (i = 0; i < fc.tree_array_size; i++) { nsn = fc.tree_array[i]; if (NULL != nsn) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Root of TREE %u is node `%s'\n", i, nsn->id); ip (ip_cls, nsn->id, nsn->uri, nsn->md, nsn->update); } } GNUNET_array_grow (fc.tree_array, fc.tree_array_size, 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done processing TREEs\n"); free_update_information_graph (uig); } /* end of fs_namespace.c */ gnunet-0.10.1/src/fs/fs_publish_ublock.c0000644000175000017500000002030512241134531015046 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_publish_ublock.c * @brief publish a UBLOCK in GNUnet * @see https://gnunet.org/encoding and #2564 * @author Krista Bennett * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "fs_publish_ublock.h" #include "fs_api.h" #include "fs_tree.h" /** * Derive the key for symmetric encryption/decryption from * the public key and the label. * * @param skey where to store symmetric key * @param iv where to store the IV * @param label label to use for key derivation * @param pub public key to use for key derivation */ static void derive_ublock_encryption_key (struct GNUNET_CRYPTO_SymmetricSessionKey *skey, struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const char *label, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) { struct GNUNET_HashCode key; /* derive key from 'label' and public key of the namespace */ GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_kdf (&key, sizeof (key), "UBLOCK-ENC", strlen ("UBLOCK-ENC"), label, strlen (label), pub, sizeof (*pub), NULL, 0)); GNUNET_CRYPTO_hash_to_aes_key (&key, skey, iv); } /** * Decrypt the given UBlock, storing the result in output. * * @param input input data * @param input_len number of bytes in @a input * @param ns public key under which the UBlock was stored * @param label label under which the UBlock was stored * @param output where to write the result, has input_len bytes */ void GNUNET_FS_ublock_decrypt_ (const void *input, size_t input_len, const struct GNUNET_CRYPTO_EcdsaPublicKey *ns, const char *label, void *output) { struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_SymmetricSessionKey skey; derive_ublock_encryption_key (&skey, &iv, label, ns); GNUNET_CRYPTO_symmetric_decrypt (input, input_len, &skey, &iv, output); } /** * Context for 'ublock_put_cont'. */ struct GNUNET_FS_PublishUblockContext { /** * Function to call when done. */ GNUNET_FS_UBlockContinuation cont; /** * Closure of 'cont'. */ void *cont_cls; /** * Handle for active datastore operation. */ struct GNUNET_DATASTORE_QueueEntry *qre; }; /** * Continuation of "GNUNET_FS_publish_ublock_". * * @param cls closure of type "struct GNUNET_FS_PublishUblockContext*" * @param success GNUNET_SYSERR on failure (including timeout/queue drop) * GNUNET_NO if content was already there * GNUNET_YES (or other positive value) on success * @param min_expiration minimum expiration time required for 0-priority content to be stored * by the datacache at this time, zero for unknown, forever if we have no * space for 0-priority content * @param msg NULL on success, otherwise an error message */ static void ublock_put_cont (void *cls, int32_t success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct GNUNET_FS_PublishUblockContext *uc = cls; uc->qre = NULL; uc->cont (uc->cont_cls, msg); GNUNET_free (uc); } /** * Publish a UBlock. * * @param h handle to the file sharing subsystem * @param dsh datastore handle to use for storage operation * @param label identifier to use * @param ulabel update label to use, may be an empty string for none * @param ns namespace to publish in * @param meta metadata to use * @param uri URI to refer to in the UBlock * @param bo per-block options * @param options publication options * @param cont continuation * @param cont_cls closure for @a cont * @return NULL on error (@a cont will still be called) */ struct GNUNET_FS_PublishUblockContext * GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h, struct GNUNET_DATASTORE_Handle *dsh, const char *label, const char *ulabel, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_BlockOptions *bo, enum GNUNET_FS_PublishOptions options, GNUNET_FS_UBlockContinuation cont, void *cont_cls) { struct GNUNET_FS_PublishUblockContext *uc; struct GNUNET_HashCode query; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_SymmetricSessionKey skey; struct GNUNET_CRYPTO_EcdsaPrivateKey *nsd; struct GNUNET_CRYPTO_EcdsaPublicKey pub; char *uris; size_t size; char *kbe; char *sptr; ssize_t mdsize; size_t slen; size_t ulen; struct UBlock *ub_plain; struct UBlock *ub_enc; /* compute ublock to publish */ if (NULL == meta) mdsize = 0; else mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); GNUNET_assert (mdsize >= 0); uris = GNUNET_FS_uri_to_string (uri); slen = strlen (uris) + 1; if (NULL == ulabel) ulen = 1; else ulen = strlen (ulabel) + 1; size = mdsize + sizeof (struct UBlock) + slen + ulen; if (size > MAX_UBLOCK_SIZE) { size = MAX_UBLOCK_SIZE; mdsize = size - sizeof (struct UBlock) - (slen + ulen); } ub_plain = GNUNET_malloc (size); kbe = (char *) &ub_plain[1]; if (NULL != ulabel) memcpy (kbe, ulabel, ulen); kbe += ulen; memcpy (kbe, uris, slen); kbe += slen; GNUNET_free (uris); sptr = kbe; if (NULL != meta) mdsize = GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, mdsize, GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); if (-1 == mdsize) { GNUNET_break (0); GNUNET_free (ub_plain); cont (cont_cls, _("Internal error.")); return NULL; } size = sizeof (struct UBlock) + slen + mdsize + ulen; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under identifier `%s'\n", label); /* get public key of the namespace */ GNUNET_CRYPTO_ecdsa_key_get_public (ns, &pub); derive_ublock_encryption_key (&skey, &iv, label, &pub); /* encrypt ublock */ ub_enc = GNUNET_malloc (size); GNUNET_CRYPTO_symmetric_encrypt (&ub_plain[1], ulen + slen + mdsize, &skey, &iv, &ub_enc[1]); GNUNET_free (ub_plain); ub_enc->purpose.size = htonl (ulen + slen + mdsize + sizeof (struct UBlock) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK); /* derive signing-key from 'label' and public key of the namespace */ nsd = GNUNET_CRYPTO_ecdsa_private_key_derive (ns, label, "fs-ublock"); GNUNET_CRYPTO_ecdsa_key_get_public (nsd, &ub_enc->verification_key); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (nsd, &ub_enc->purpose, &ub_enc->signature)); GNUNET_CRYPTO_hash (&ub_enc->verification_key, sizeof (ub_enc->verification_key), &query); GNUNET_free (nsd); uc = GNUNET_new (struct GNUNET_FS_PublishUblockContext); uc->cont = cont; uc->cont_cls = cont_cls; uc->qre = GNUNET_DATASTORE_put (dsh, 0, &query, ulen + slen + mdsize + sizeof (struct UBlock), ub_enc, GNUNET_BLOCK_TYPE_FS_UBLOCK, bo->content_priority, bo->anonymity_level, bo->replication_level, bo->expiration_time, -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &ublock_put_cont, uc); return uc; } /** * Abort UBlock publishing operation. * * @param uc operation to abort. */ void GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc) { GNUNET_DATASTORE_cancel (uc->qre); GNUNET_free (uc); } gnunet-0.10.1/src/fs/test_fs_list_indexed.c0000644000175000017500000002107312226007731015562 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_list_indexed.c * @brief simple testcase for list_indexed operation (indexing, listing * indexed) * @author Christian Grothoff * * TODO: * - actually call list_indexed API! */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_fs_service.h" /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 2) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static struct GNUNET_TIME_Absolute start; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_PublishContext *publish; static char *fn1; static char *fn2; static int err; static void abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_publish_stop (publish); publish = NULL; GNUNET_DISK_directory_remove (fn1); GNUNET_free (fn1); fn1 = NULL; GNUNET_DISK_directory_remove (fn2); GNUNET_free (fn2); fn2 = NULL; } static void list_indexed_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { void *ret; ret = NULL; switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_COMPLETED: ret = event->value.publish.cctx; printf ("Publish complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); if (0 == strcmp ("list_indexed-context-dir", event->value.publish.cctx)) GNUNET_SCHEDULER_add_continuation (&list_indexed_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS: ret = event->value.publish.cctx; GNUNET_assert (publish == event->value.publish.pc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: ret = event->value.publish.cctx; break; case GNUNET_FS_STATUS_PUBLISH_ERROR: ret = event->value.publish.cctx; FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); err = 1; if (0 == strcmp ("list_indexed-context-dir", event->value.publish.cctx)) GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_START: ret = event->value.publish.cctx; if (0 == strcmp ("list_indexed-context1", event->value.publish.cctx)) { GNUNET_assert (0 == strcmp ("list_indexed-context-dir", event->value.publish.pctx)); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); } else if (0 == strcmp ("list_indexed-context2", event->value.publish.cctx)) { GNUNET_assert (0 == strcmp ("list_indexed-context-dir", event->value.publish.pctx)); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (2 == event->value.publish.anonymity); } else if (0 == strcmp ("list_indexed-context-dir", event->value.publish.cctx)) { GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (3 == event->value.publish.anonymity); } else GNUNET_assert (0); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: if (0 == strcmp ("list_indexed-context-dir", event->value.publish.cctx)) { GNUNET_assert (publish == event->value.publish.pc); publish = NULL; } break; default: printf ("Unexpected event: %d\n", event->status); break; } return ret; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar", }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi1; struct GNUNET_FS_FileInformation *fi2; struct GNUNET_FS_FileInformation *fidir; size_t i; struct GNUNET_FS_BlockOptions bo; fs = GNUNET_FS_start (cfg, "test-fs-list_indexed", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); fn1 = GNUNET_DISK_mktemp ("gnunet-list_indexed-test-dst"); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn1, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); fn2 = GNUNET_DISK_mktemp ("gnunet-list_indexed-test-dst"); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn2, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi1 = GNUNET_FS_file_information_create_from_file (fs, "list_indexed-context1", fn1, kuri, meta, GNUNET_YES, &bo); GNUNET_assert (NULL != fi1); bo.anonymity_level = 2; fi2 = GNUNET_FS_file_information_create_from_file (fs, "list_indexed-context2", fn2, kuri, meta, GNUNET_YES, &bo); GNUNET_assert (NULL != fi2); bo.anonymity_level = 3; fidir = GNUNET_FS_file_information_create_empty_directory (fs, "list_indexed-context-dir", kuri, meta, &bo, NULL); GNUNET_assert (GNUNET_OK == GNUNET_FS_file_information_add (fidir, fi1)); GNUNET_assert (GNUNET_OK == GNUNET_FS_file_information_add (fidir, fi2)); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fidir); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fidir, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-list-indexed", "test_fs_list_indexed_data.conf", &run, NULL)) return 1; return 0; } /* end of test_fs_list_indexed.c */ gnunet-0.10.1/src/fs/test_fs_download_data.conf0000644000175000017500000000032512225230043016400 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-download/ [download-test] # set to 'YES' to test non-anonymous download USE_STREAM = NO # set to 'YES' to use indexing USE_INDEX = NOgnunet-0.10.1/src/fs/gnunet-search.c0000644000175000017500000002363412255773025014140 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-search.c * @brief searching for files on GNUnet * @author Christian Grothoff * @author Krista Bennett * @author James Blackwell * @author Igor Wronsky */ #include "platform.h" #include "gnunet_fs_service.h" static int ret; static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_FS_Handle *ctx; static struct GNUNET_FS_SearchContext *sc; static char *output_filename; static struct GNUNET_FS_DirectoryBuilder *db; static unsigned int anonymity = 1; /** * Timeout for the search, 0 means to wait for CTRL-C. */ static struct GNUNET_TIME_Relative timeout; static unsigned int results_limit; static unsigned int results; static int verbose; static int local_only; /** * Type of a function that libextractor calls for each * meta data item found. * * @param cls closure (user-defined, unused) * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_size number of bytes in data * @return 0 to continue extracting, 1 to abort */ static int item_printer (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size) { if ((format != EXTRACTOR_METAFORMAT_UTF8) && (format != EXTRACTOR_METAFORMAT_C_STRING)) return 0; if (type == EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME) return 0; printf ("\t%20s: %s\n", dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN, EXTRACTOR_metatype_to_string (type)), data); return 0; } static void clean_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { size_t dsize; void *ddata; GNUNET_FS_stop (ctx); ctx = NULL; if (output_filename == NULL) return; if (GNUNET_OK != GNUNET_FS_directory_builder_finish (db, &dsize, &ddata)) { GNUNET_break (0); GNUNET_free (output_filename); return; } if (dsize != GNUNET_DISK_fn_write (output_filename, ddata, dsize, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) { FPRINTF (stderr, _("Failed to write directory with search results to `%s'\n"), output_filename); } GNUNET_free_non_null (ddata); GNUNET_free (output_filename); } /** * Called by FS client to give information about the progress of an * operation. * * @param cls closure * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the GNUNET_FS_ProgressInfo struct. */ static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { static unsigned int cnt; int is_directory; char *uri; char *filename; switch (info->status) { case GNUNET_FS_STATUS_SEARCH_START: break; case GNUNET_FS_STATUS_SEARCH_RESULT: if (db != NULL) GNUNET_FS_directory_builder_add (db, info->value.search.specifics.result.uri, info->value.search.specifics.result.meta, NULL); uri = GNUNET_FS_uri_to_string (info->value.search.specifics.result.uri); printf ("#%u:\n", cnt++); filename = GNUNET_CONTAINER_meta_data_get_by_type (info->value.search. specifics.result.meta, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); is_directory = GNUNET_FS_meta_data_test_for_directory (info->value.search. specifics.result.meta); if (filename != NULL) { GNUNET_DISK_filename_canonicalize (filename); if (GNUNET_YES == is_directory) printf ("gnunet-download -o \"%s%s\" -R %s\n", filename, GNUNET_FS_DIRECTORY_EXT, uri); else printf ("gnunet-download -o \"%s\" %s\n", filename, uri); } else if (GNUNET_YES == is_directory) printf ("gnunet-download -o \"collection%s\" -R %s\n", GNUNET_FS_DIRECTORY_EXT, uri); else printf ("gnunet-download %s\n", uri); if (verbose) GNUNET_CONTAINER_meta_data_iterate (info->value.search.specifics. result.meta, &item_printer, NULL); printf ("\n"); fflush (stdout); GNUNET_free_non_null (filename); GNUNET_free (uri); results++; if ((results_limit > 0) && (results >= results_limit)) GNUNET_SCHEDULER_shutdown (); break; case GNUNET_FS_STATUS_SEARCH_UPDATE: break; case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: /* ignore */ break; case GNUNET_FS_STATUS_SEARCH_ERROR: FPRINTF (stderr, _("Error searching: %s.\n"), info->value.search.specifics.error.message); GNUNET_SCHEDULER_shutdown (); break; case GNUNET_FS_STATUS_SEARCH_STOPPED: GNUNET_SCHEDULER_add_continuation (&clean_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; default: FPRINTF (stderr, _("Unexpected status: %d\n"), info->status); break; } return NULL; } static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (sc != NULL) { GNUNET_FS_search_stop (sc); sc = NULL; } } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_FS_Uri *uri; unsigned int argc; enum GNUNET_FS_SearchOptions options; argc = 0; while (NULL != args[argc]) argc++; uri = GNUNET_FS_uri_ksk_create_from_args (argc, (const char **) args); if (NULL == uri) { FPRINTF (stderr, "%s", _("Could not create keyword URI from arguments.\n")); ret = 1; return; } cfg = c; ctx = GNUNET_FS_start (cfg, "gnunet-search", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); if (NULL == ctx) { FPRINTF (stderr, _("Could not initialize `%s' subsystem.\n"), "FS"); GNUNET_FS_uri_destroy (uri); ret = 1; return; } if (output_filename != NULL) db = GNUNET_FS_directory_builder_create (NULL); options = GNUNET_FS_SEARCH_OPTION_NONE; if (local_only) options |= GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY; sc = GNUNET_FS_search_start (ctx, uri, anonymity, options, NULL); GNUNET_FS_uri_destroy (uri); if (NULL == sc) { FPRINTF (stderr, "%s", _("Could not start searching.\n")); GNUNET_FS_stop (ctx); ret = 1; return; } if (0 != timeout.rel_value_us) GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_task, NULL); else GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function to search GNUnet. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'a', "anonymity", "LEVEL", gettext_noop ("set the desired LEVEL of receiver-anonymity"), 1, &GNUNET_GETOPT_set_uint, &anonymity}, {'n', "no-network", NULL, gettext_noop ("only search the local peer (no P2P network search)"), 0, &GNUNET_GETOPT_set_one, &local_only}, {'o', "output", "PREFIX", gettext_noop ("write search results to file starting with PREFIX"), 1, &GNUNET_GETOPT_set_string, &output_filename}, {'t', "timeout", "DELAY", gettext_noop ("automatically terminate search after DELAY"), 1, &GNUNET_GETOPT_set_relative_time, &timeout}, {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_set_one, &verbose}, {'N', "results", "VALUE", gettext_noop ("automatically terminate search after VALUE results are found"), 1, &GNUNET_GETOPT_set_uint, &results_limit}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-search [OPTIONS] KEYWORD", gettext_noop ("Search GNUnet for files that were published on GNUnet"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-search.c */ gnunet-0.10.1/src/fs/perf_gnunet_service_fs_p2p.conf0000644000175000017500000000022712225230043017357 00000000000000@INLINE@ fs_test_lib_data.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-fs-test-lib/ [fs] GAUGER_HEAP = "2-peer 10 MB P2P download" # PREFIX = valgrind gnunet-0.10.1/src/fs/test_fs_download.c0000644000175000017500000002526412226006743014726 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2008, 2009, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_download.c * @brief simple testcase for simple publish + download operation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "gnunet_testing_lib.h" #include /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 2) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static unsigned int anonymity_level; static int indexed; static struct GNUNET_TIME_Absolute start; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_DownloadContext *download; static struct GNUNET_FS_PublishContext *publish; static GNUNET_SCHEDULER_TaskIdentifier timeout_kill; static char *fn; static char *fn1; static int err; static void timeout_kill_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != download) { GNUNET_FS_download_stop (download, GNUNET_YES); download = NULL; } else if (NULL != publish) { GNUNET_FS_publish_stop (publish); publish = NULL; } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout downloading file\n"); timeout_kill = GNUNET_SCHEDULER_NO_TASK; err = 1; } static void abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != publish) { GNUNET_FS_publish_stop (publish); publish = NULL; } } static void stop_fs_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_stop (fs); fs = NULL; } static void abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { uint64_t size; if (NULL != download) { GNUNET_FS_download_stop (download, GNUNET_YES); download = NULL; } GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES, GNUNET_NO)); GNUNET_assert (size == FILESIZE); GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); fn = NULL; GNUNET_SCHEDULER_cancel (timeout_kill); timeout_kill = GNUNET_SCHEDULER_NO_TASK; } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_PROGRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: fprintf (stdout, "Publishing complete, %llu kb/s.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024LL)); GAUGER ("FS", (GNUNET_YES == indexed) ? "Publishing speed (indexing)" : "Publishing speed (insertion)", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024LL), "kb/s"); fn = GNUNET_DISK_mktemp ("gnunet-download-test-dst"); start = GNUNET_TIME_absolute_get (); download = GNUNET_FS_download_start (fs, event->value.publish.specifics. completed.chk_uri, NULL, fn, NULL, 0, FILESIZE, anonymity_level, GNUNET_FS_DOWNLOAD_OPTION_NONE, "download", NULL); GNUNET_assert (download != NULL); break; case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: fprintf (stdout, "Download complete, %llu kb/s.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024LL)); GAUGER ("FS", (GNUNET_YES == indexed) ? "Local download speed (indexed)" : "Local download speed (inserted)", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024LL), "kb/s"); GNUNET_SCHEDULER_add_now (&abort_download_task, NULL); break; case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: GNUNET_assert (download == event->value.download.dc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.download.completed, (unsigned long long) event->value.download.size, event->value.download.specifics.progress.depth, (unsigned long long) event->value.download.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); GNUNET_break (0); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_DOWNLOAD_ERROR: FPRINTF (stderr, "Error downloading file: %s\n", event->value.download.specifics.error.message); GNUNET_SCHEDULER_add_now (&abort_download_task, NULL); break; case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: break; case GNUNET_FS_STATUS_PUBLISH_START: GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); GNUNET_assert (NULL == event->value.publish.pctx); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_assert (publish == event->value.publish.pc); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (1 == event->value.publish.anonymity); GNUNET_SCHEDULER_add_now (&stop_fs_task, NULL); break; case GNUNET_FS_STATUS_DOWNLOAD_START: GNUNET_assert (0 == strcmp ("download", event->value.download.cctx)); GNUNET_assert (NULL == event->value.download.pctx); GNUNET_assert (NULL != event->value.download.uri); GNUNET_assert (0 == strcmp (fn, event->value.download.filename)); GNUNET_assert (FILESIZE == event->value.download.size); GNUNET_assert (0 == event->value.download.completed); GNUNET_assert (1 == event->value.download.anonymity); break; case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: GNUNET_assert (download == event->value.download.dc); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; default: printf ("Unexpected event: %d\n", event->status); break; } return NULL; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { const char *binary_name = cls; const char *keywords[] = { "down_foo", "down_bar", }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi; size_t i; struct GNUNET_FS_BlockOptions bo; if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg, "download-test", "USE_STREAM")) anonymity_level = 0; else anonymity_level = 1; fs = GNUNET_FS_start (cfg, binary_name, &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = anonymity_level; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg, "download-test", "USE_INDEX")) { fn1 = GNUNET_DISK_mktemp ("gnunet-download-indexed-test"); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn1, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); fi = GNUNET_FS_file_information_create_from_file (fs, "publish-context", fn1, kuri, meta, GNUNET_YES, &bo); indexed = GNUNET_YES; } else { fi = GNUNET_FS_file_information_create_from_data (fs, "publish-context", FILESIZE, buf, kuri, meta, GNUNET_NO, &bo); /* note: buf will be free'd as part of 'fi' now */ indexed = GNUNET_NO; } GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fi); timeout_kill = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_kill_task, NULL); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); } int main (int argc, char *argv[]) { const char *binary_name; const char *config_name; binary_name = "test-fs-download"; config_name = "test_fs_download_data.conf"; if (NULL != strstr (argv[0], "indexed")) { binary_name = "test-fs-download-indexed"; config_name = "test_fs_download_indexed.conf"; } if (NULL != strstr (argv[0], "mesh")) { binary_name = "test-fs-download-mesh"; config_name = "test_fs_download_mesh.conf"; } if (0 != GNUNET_TESTING_peer_run (binary_name, config_name, &run, (void *) binary_name)) return 1; if (NULL != fn1) { UNLINK (fn1); GNUNET_free (fn1); } return err; } /* end of test_fs_download.c */ gnunet-0.10.1/src/fs/gnunet-fs-profiler.c0000644000175000017500000001343312225777502015120 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-fs-profiler.c * @brief tool to benchmark/profile file-sharing * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" /** * Final status code. */ static int ret; /** * Data file with the hosts for the testbed. */ static char *host_filename; /** * Number of peers to run in the experiment. */ static unsigned int num_peers; /** * After how long do we abort the test? */ static struct GNUNET_TIME_Relative timeout; /** * Handle to the task run during termination. */ static GNUNET_SCHEDULER_TaskIdentifier terminate_taskid; /** * Function called after we've collected the statistics. * * @param cls NULL * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void shutdown_task (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { if (NULL != emsg) fprintf (stderr, "Error collecting statistics: %s\n", emsg); GNUNET_SCHEDULER_shutdown (); } /** * Callback function to process statistic values from all peers. * Prints them out. * * @param cls closure * @param peer the peer the statistic belong to * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int process_stats (void *cls, const struct GNUNET_TESTBED_Peer *peer, const char *subsystem, const char *name, uint64_t value, int is_persistent) { fprintf (stdout, "%p-%s: %s = %llu\n", peer, subsystem, name, (unsigned long long) value); return GNUNET_OK; } /** * Task run on timeout to terminate. Triggers printing out * all statistics. * * @param cls NULL * @param tc unused */ static void terminate_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { terminate_taskid = GNUNET_SCHEDULER_NO_TASK; GNUNET_TESTBED_get_statistics (0, NULL, NULL, NULL, &process_stats, &shutdown_task, NULL); } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { // const struct GNUNET_CONFIGURATION_Handle *cfg = cls; // FIXME: enable clients to signal 'completion' before timeout; // in that case, run the 'terminate_task' "immediately" if (0 != timeout.rel_value_us) terminate_taskid = GNUNET_SCHEDULER_add_delayed (timeout, &terminate_task, NULL); else terminate_taskid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &terminate_task, NULL); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_TESTBED_run (host_filename, cfg, num_peers, 0, NULL, NULL, &test_master, (void *) cfg); } /** * Program to run a file-sharing testbed. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'n', "num-peers", "COUNT", gettext_noop ("run the experiment with COUNT peers"), 1, &GNUNET_GETOPT_set_uint, &num_peers}, {'H', "hosts", "HOSTFILE", gettext_noop ("specifies name of a file with the HOSTS the testbed should use"), 1, &GNUNET_GETOPT_set_string, &host_filename}, {'t', "timeout", "DELAY", gettext_noop ("automatically terminate experiment after DELAY"), 1, &GNUNET_GETOPT_set_relative_time, &timeout}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-fs-profiler", gettext_noop ("run a testbed to measure file-sharing performance"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-fs-profiler.c */ gnunet-0.10.1/src/fs/plugin_block_fs.c0000644000175000017500000001441312225777502014531 00000000000000/* This file is part of GNUnet (C) 2010, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/plugin_block_fs.c * @brief blocks used for file-sharing * @author Christian Grothoff */ #include "platform.h" #include "gnunet_block_plugin.h" #include "gnunet_fs_service.h" #include "block_fs.h" #include "gnunet_signatures.h" /** * Number of bits we set per entry in the bloomfilter. * Do not change! */ #define BLOOMFILTER_K 16 /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would * be done with the "get_key" function. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for bf * @param xquery extrended query data (can be NULL, depending on type) * @param xquery_size number of bytes in xquery * @param reply_block response to validate * @param reply_block_size number of bytes in reply block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult block_plugin_fs_evaluate (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { const struct UBlock *ub; struct GNUNET_HashCode hc; struct GNUNET_HashCode chash; struct GNUNET_HashCode mhash; switch (type) { case GNUNET_BLOCK_TYPE_FS_DBLOCK: case GNUNET_BLOCK_TYPE_FS_IBLOCK: if (0 != xquery_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } if (NULL == reply_block) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; return GNUNET_BLOCK_EVALUATION_OK_LAST; case GNUNET_BLOCK_TYPE_FS_UBLOCK: if (0 != xquery_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } if (NULL == reply_block) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; if (reply_block_size < sizeof (struct UBlock)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } ub = reply_block; GNUNET_CRYPTO_hash (&ub->verification_key, sizeof (ub->verification_key), &hc); if (0 != memcmp (&hc, query, sizeof (struct GNUNET_HashCode))) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (reply_block_size != ntohl (ub->purpose.size) + sizeof (struct GNUNET_CRYPTO_EcdsaSignature)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK, &ub->purpose, &ub->signature, &ub->verification_key)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (NULL != bf) { GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); if (NULL != *bf) { if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; } else { *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K); } GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); } return GNUNET_BLOCK_EVALUATION_OK_MORE; default: return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; } } /** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param block block to get the key for * @param block_size number of bytes in block * @param key set to the key (query) for the given block * @return GNUNET_OK on success, GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int block_plugin_fs_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode *key) { const struct UBlock *ub; switch (type) { case GNUNET_BLOCK_TYPE_FS_DBLOCK: case GNUNET_BLOCK_TYPE_FS_IBLOCK: GNUNET_CRYPTO_hash (block, block_size, key); return GNUNET_OK; case GNUNET_BLOCK_TYPE_FS_UBLOCK: if (block_size < sizeof (struct UBlock)) { GNUNET_break (0); return GNUNET_SYSERR; } ub = block; GNUNET_CRYPTO_hash (&ub->verification_key, sizeof (ub->verification_key), key); return GNUNET_OK; default: GNUNET_break (0); return GNUNET_SYSERR; } } /** * Entry point for the plugin. */ void * libgnunet_plugin_block_fs_init (void *cls) { static enum GNUNET_BLOCK_Type types[] = { GNUNET_BLOCK_TYPE_FS_DBLOCK, GNUNET_BLOCK_TYPE_FS_IBLOCK, GNUNET_BLOCK_TYPE_FS_UBLOCK, GNUNET_BLOCK_TYPE_ANY /* end of list */ }; struct GNUNET_BLOCK_PluginFunctions *api; api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_fs_evaluate; api->get_key = &block_plugin_fs_get_key; api->types = types; return api; } /** * Exit point from the plugin. */ void * libgnunet_plugin_block_fs_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_block_fs.c */ gnunet-0.10.1/src/fs/fs_unindex.c0000644000175000017500000006055512255010511013522 00000000000000/* This file is part of GNUnet. (C) 2003--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_unindex.c * @author Krista Grothoff * @author Christian Grothoff * @brief Unindex file. */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_fs_service.h" #include "gnunet_protocols.h" #include "fs_api.h" #include "fs_tree.h" #include "block_fs.h" #include "fs_publish_ublock.h" /** * Function called by the tree encoder to obtain * a block of plaintext data (for the lowest level * of the tree). * * @param cls our publishing context * @param offset identifies which block to get * @param max (maximum) number of bytes to get; returning * fewer will also cause errors * @param buf where to copy the plaintext buffer * @param emsg location to store an error message (on error) * @return number of bytes copied to buf, 0 on error */ static size_t unindex_reader (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) { struct GNUNET_FS_UnindexContext *uc = cls; size_t pt_size; pt_size = GNUNET_MIN (max, uc->file_size - offset); if (offset != GNUNET_DISK_file_seek (uc->fh, offset, GNUNET_DISK_SEEK_SET)) { *emsg = GNUNET_strdup (_("Failed to find given position in file")); return 0; } if (pt_size != GNUNET_DISK_file_read (uc->fh, buf, pt_size)) { *emsg = GNUNET_strdup (_("Failed to read file")); return 0; } return pt_size; } /** * Fill in all of the generic fields for * an unindex event and call the callback. * * @param pi structure to fill in * @param uc overall unindex context * @param offset where we are in the file (for progress) */ void GNUNET_FS_unindex_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_UnindexContext *uc, uint64_t offset) { pi->value.unindex.uc = uc; pi->value.unindex.cctx = uc->client_info; pi->value.unindex.filename = uc->filename; pi->value.unindex.size = uc->file_size; pi->value.unindex.eta = GNUNET_TIME_calculate_eta (uc->start_time, offset, uc->file_size); pi->value.unindex.duration = GNUNET_TIME_absolute_get_duration (uc->start_time); pi->value.unindex.completed = offset; pi->fsh = uc->h; uc->client_info = uc->h->upcb (uc->h->upcb_cls, pi); } /** * Function called with information about our * progress in computing the tree encoding. * * @param cls closure * @param offset where are we in the file * @param pt_block plaintext of the currently processed block * @param pt_size size of pt_block * @param depth depth of the block in the tree, 0 for DBLOCK */ static void unindex_progress (void *cls, uint64_t offset, const void *pt_block, size_t pt_size, unsigned int depth) { struct GNUNET_FS_UnindexContext *uc = cls; struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_UNINDEX_PROGRESS; pi.value.unindex.specifics.progress.data = pt_block; pi.value.unindex.specifics.progress.offset = offset; pi.value.unindex.specifics.progress.data_len = pt_size; pi.value.unindex.specifics.progress.depth = depth; GNUNET_FS_unindex_make_status_ (&pi, uc, offset); } /** * We've encountered an error during * unindexing. Signal the client. * * @param uc context for the failed unindexing operation */ static void signal_unindex_error (struct GNUNET_FS_UnindexContext *uc) { struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_UNINDEX_ERROR; pi.value.unindex.eta = GNUNET_TIME_UNIT_FOREVER_REL; pi.value.unindex.specifics.error.message = uc->emsg; GNUNET_FS_unindex_make_status_ (&pi, uc, 0); } /** * Continuation called to notify client about result of the * datastore removal operation. * * @param cls closure * @param success GNUNET_SYSERR on failure * @param min_expiration minimum expiration time required for content to be stored * @param msg NULL on success, otherwise an error message */ static void process_cont (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct GNUNET_FS_UnindexContext *uc = cls; if (success == GNUNET_SYSERR) { uc->emsg = GNUNET_strdup (msg); signal_unindex_error (uc); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Datastore REMOVE operation succeeded\n"); GNUNET_FS_tree_encoder_next (uc->tc); } /** * Function called asking for the current (encoded) * block to be processed. After processing the * client should either call "GNUNET_FS_tree_encode_next" * or (on error) "GNUNET_FS_tree_encode_finish". * * @param cls closure * @param chk content hash key for the block (key for lookup in the datastore) * @param offset offset of the block * @param depth depth of the block, 0 for DBLOCK * @param type type of the block (IBLOCK or DBLOCK) * @param block the (encrypted) block * @param block_size size of block (in bytes) */ static void unindex_process (void *cls, const struct ContentHashKey *chk, uint64_t offset, unsigned int depth, enum GNUNET_BLOCK_Type type, const void *block, uint16_t block_size) { struct GNUNET_FS_UnindexContext *uc = cls; uint32_t size; const void *data; struct OnDemandBlock odb; if (type != GNUNET_BLOCK_TYPE_FS_DBLOCK) { size = block_size; data = block; } else /* on-demand encoded DBLOCK */ { size = sizeof (struct OnDemandBlock); odb.offset = GNUNET_htonll (offset); odb.file_id = uc->file_id; data = &odb; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending REMOVE request to DATASTORE service\n"); GNUNET_DATASTORE_remove (uc->dsh, &chk->query, size, data, -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &process_cont, uc); uc->chk = *chk; } /** * Function called with the response from the * FS service to our unindexing request. * * @param cls closure, unindex context * @param msg NULL on timeout, otherwise the response */ static void process_fs_response (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_FS_UnindexContext *uc = cls; struct GNUNET_FS_ProgressInfo pi; if (uc->client != NULL) { GNUNET_CLIENT_disconnect (uc->client); uc->client = NULL; } if (uc->state != UNINDEX_STATE_FS_NOTIFY) { uc->state = UNINDEX_STATE_ERROR; uc->emsg = GNUNET_strdup (_("Unexpected time for a response from `fs' service.")); GNUNET_FS_unindex_sync_ (uc); signal_unindex_error (uc); return; } if (NULL == msg) { uc->state = UNINDEX_STATE_ERROR; uc->emsg = GNUNET_strdup (_("Timeout waiting for `fs' service.")); GNUNET_FS_unindex_sync_ (uc); signal_unindex_error (uc); return; } if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK) { uc->state = UNINDEX_STATE_ERROR; uc->emsg = GNUNET_strdup (_("Invalid response from `fs' service.")); GNUNET_FS_unindex_sync_ (uc); signal_unindex_error (uc); return; } uc->state = UNINDEX_STATE_COMPLETE; pi.status = GNUNET_FS_STATUS_UNINDEX_COMPLETED; pi.value.unindex.eta = GNUNET_TIME_UNIT_ZERO; GNUNET_FS_unindex_sync_ (uc); GNUNET_FS_unindex_make_status_ (&pi, uc, uc->file_size); } /** * Function called when we are done with removing UBlocks. * Disconnect from datastore and notify FS service about * the unindex event. * * @param uc our unindexing context */ static void unindex_finish (struct GNUNET_FS_UnindexContext *uc) { char *emsg; struct UnindexMessage req; /* generate final progress message */ unindex_progress (uc, uc->file_size, NULL, 0, 0); GNUNET_FS_tree_encoder_finish (uc->tc, &emsg); uc->tc = NULL; GNUNET_DISK_file_close (uc->fh); uc->fh = NULL; GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO); uc->dsh = NULL; uc->state = UNINDEX_STATE_FS_NOTIFY; GNUNET_FS_unindex_sync_ (uc); uc->client = GNUNET_CLIENT_connect ("fs", uc->h->cfg); if (uc->client == NULL) { uc->state = UNINDEX_STATE_ERROR; uc->emsg = GNUNET_strdup (_("Failed to connect to FS service for unindexing.")); GNUNET_FS_unindex_sync_ (uc); signal_unindex_error (uc); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending UNINDEX message to FS service\n"); req.header.size = htons (sizeof (struct UnindexMessage)); req.header.type = htons (GNUNET_MESSAGE_TYPE_FS_UNINDEX); req.reserved = 0; req.file_id = uc->file_id; GNUNET_break (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (uc->client, &req.header, GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_YES, &process_fs_response, uc)); } /** * Function called by the directory scanner as we extract keywords * that we will need to remove UBlocks. * * @param cls the 'struct GNUNET_FS_UnindexContext *' * @param filename which file we are making progress on * @param is_directory GNUNET_YES if this is a directory, * GNUNET_NO if this is a file * GNUNET_SYSERR if it is neither (or unknown) * @param reason kind of progress we are making */ static void unindex_directory_scan_cb (void *cls, const char *filename, int is_directory, enum GNUNET_FS_DirScannerProgressUpdateReason reason) { struct GNUNET_FS_UnindexContext *uc = cls; static struct GNUNET_FS_ShareTreeItem * directory_scan_result; switch (reason) { case GNUNET_FS_DIRSCANNER_FINISHED: directory_scan_result = GNUNET_FS_directory_scan_get_result (uc->dscan); uc->dscan = NULL; if (NULL != directory_scan_result->ksk_uri) { uc->ksk_uri = GNUNET_FS_uri_dup (directory_scan_result->ksk_uri); uc->state = UNINDEX_STATE_DS_REMOVE_KBLOCKS; GNUNET_FS_unindex_sync_ (uc); GNUNET_FS_unindex_do_remove_kblocks_ (uc); } else { uc->emsg = GNUNET_strdup (_("Failed to get KSKs from directory scan.")); GNUNET_FS_unindex_sync_ (uc); unindex_finish (uc); } GNUNET_FS_share_tree_free (directory_scan_result); break; case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Internal error scanning `%s'.\n"), uc->filename); GNUNET_FS_directory_scan_abort (uc->dscan); uc->dscan = NULL; uc->emsg = GNUNET_strdup (_("Failed to get KSKs from directory scan.")); GNUNET_FS_unindex_sync_ (uc); unindex_finish (uc); break; default: break; } } /** * If necessary, connect to the datastore and remove the UBlocks. * * @param uc context for the unindex operation. */ void GNUNET_FS_unindex_do_extract_keywords_ (struct GNUNET_FS_UnindexContext *uc) { char *ex; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (uc->h->cfg, "FS", "EXTRACTORS", &ex)) ex = NULL; uc->dscan = GNUNET_FS_directory_scan_start (uc->filename, GNUNET_NO, ex, &unindex_directory_scan_cb, uc); GNUNET_free_non_null (ex); } /** * Continuation called to notify client about result of the remove * operation for the UBlock. * * @param cls the 'struct GNUNET_FS_UnindexContext *' * @param success GNUNET_SYSERR on failure (including timeout/queue drop) * GNUNET_NO if content was already there * GNUNET_YES (or other positive value) on success * @param min_expiration minimum expiration time required for 0-priority content to be stored * by the datacache at this time, zero for unknown, forever if we have no * space for 0-priority content * @param msg NULL on success, otherwise an error message */ static void continue_after_remove (void *cls, int32_t success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct GNUNET_FS_UnindexContext *uc = cls; uc->dqe = NULL; if (success != GNUNET_YES) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to remove UBlock: %s\n"), msg); uc->ksk_offset++; GNUNET_FS_unindex_do_remove_kblocks_ (uc); } /** * Function called from datastore with result from us looking for * a UBlock. There are four cases: * 1) no result, means we move on to the next keyword * 2) UID is the same as the first UID, means we move on to next keyword * 3) UBlock for a different CHK, means we keep looking for more * 4) UBlock is for our CHK, means we remove the block and then move * on to the next keyword * * @param cls the 'struct GNUNET_FS_UnindexContext *' * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ static void process_kblock_for_unindex (void *cls, const struct GNUNET_HashCode *key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct GNUNET_FS_UnindexContext *uc = cls; const struct UBlock *ub; struct GNUNET_FS_Uri *chk_uri; struct GNUNET_HashCode query; uc->dqe = NULL; if (NULL == data) { /* no result */ uc->ksk_offset++; GNUNET_FS_unindex_do_remove_kblocks_ (uc); return; } if (0 == uc->first_uid) { /* remember UID of first result to detect cycles */ uc->first_uid = uid; } else if (uid == uc->first_uid) { /* no more additional results */ uc->ksk_offset++; GNUNET_FS_unindex_do_remove_kblocks_ (uc); return; } GNUNET_assert (GNUNET_BLOCK_TYPE_FS_UBLOCK == type); if (size < sizeof (struct UBlock)) { GNUNET_break (0); goto get_next; } ub = data; GNUNET_CRYPTO_hash (&ub->verification_key, sizeof (ub->verification_key), &query); if (0 != memcmp (&query, key, sizeof (struct GNUNET_HashCode))) { /* result does not match our keyword, skip */ goto get_next; } { char pt[size - sizeof (struct UBlock)]; struct GNUNET_CRYPTO_EcdsaPublicKey anon_pub; const char *keyword; GNUNET_CRYPTO_ecdsa_key_get_public (GNUNET_CRYPTO_ecdsa_key_get_anonymous (), &anon_pub); keyword = &uc->ksk_uri->data.ksk.keywords[uc->ksk_offset][1]; GNUNET_FS_ublock_decrypt_ (&ub[1], size - sizeof (struct UBlock), &anon_pub, keyword, pt); if (NULL == memchr (&pt[1], 0, sizeof (pt) - 1)) { GNUNET_break_op (0); /* malformed UBlock */ goto get_next; } chk_uri = GNUNET_FS_uri_parse (&pt[1], NULL); if (NULL == chk_uri) { GNUNET_break_op (0); /* malformed UBlock */ goto get_next; } } if (0 != memcmp (&uc->chk, &chk_uri->data.chk.chk, sizeof (struct ContentHashKey))) { /* different CHK, ignore */ GNUNET_FS_uri_destroy (chk_uri); goto get_next; } GNUNET_FS_uri_destroy (chk_uri); /* matches! */ uc->dqe = GNUNET_DATASTORE_remove (uc->dsh, key, size, data, 0 /* priority */, 1 /* queue size */, GNUNET_TIME_UNIT_FOREVER_REL, &continue_after_remove, uc); return; get_next: uc->dqe = GNUNET_DATASTORE_get_key (uc->dsh, uc->roff++, &uc->uquery, GNUNET_BLOCK_TYPE_FS_UBLOCK, 0 /* priority */, 1 /* queue size */, GNUNET_TIME_UNIT_FOREVER_REL, &process_kblock_for_unindex, uc); } /** * If necessary, connect to the datastore and remove the KBlocks. * * @param uc context for the unindex operation. */ void GNUNET_FS_unindex_do_remove_kblocks_ (struct GNUNET_FS_UnindexContext *uc) { const char *keyword; const struct GNUNET_CRYPTO_EcdsaPrivateKey *anon; struct GNUNET_CRYPTO_EcdsaPublicKey anon_pub; struct GNUNET_CRYPTO_EcdsaPublicKey dpub; if (NULL == uc->dsh) uc->dsh = GNUNET_DATASTORE_connect (uc->h->cfg); if (NULL == uc->dsh) { uc->state = UNINDEX_STATE_ERROR; uc->emsg = GNUNET_strdup (_("Failed to connect to `datastore' service.")); GNUNET_FS_unindex_sync_ (uc); signal_unindex_error (uc); return; } if ( (NULL == uc->ksk_uri) || (uc->ksk_offset >= uc->ksk_uri->data.ksk.keywordCount) ) { unindex_finish (uc); return; } anon = GNUNET_CRYPTO_ecdsa_key_get_anonymous (); GNUNET_CRYPTO_ecdsa_key_get_public (anon, &anon_pub); keyword = &uc->ksk_uri->data.ksk.keywords[uc->ksk_offset][1]; GNUNET_CRYPTO_ecdsa_public_key_derive (&anon_pub, keyword, "fs-ublock", &dpub); GNUNET_CRYPTO_hash (&dpub, sizeof (dpub), &uc->uquery); uc->first_uid = 0; uc->dqe = GNUNET_DATASTORE_get_key (uc->dsh, uc->roff++, &uc->uquery, GNUNET_BLOCK_TYPE_FS_UBLOCK, 0 /* priority */, 1 /* queue size */, GNUNET_TIME_UNIT_FOREVER_REL, &process_kblock_for_unindex, uc); } /** * Function called when the tree encoder has * processed all blocks. Clean up. * * @param cls our unindexing context * @param tc not used */ static void unindex_extract_keywords (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_UnindexContext *uc = cls; uc->state = UNINDEX_STATE_EXTRACT_KEYWORDS; GNUNET_FS_unindex_sync_ (uc); GNUNET_FS_unindex_do_extract_keywords_ (uc); } /** * Connect to the datastore and remove the blocks. * * @param uc context for the unindex operation. */ void GNUNET_FS_unindex_do_remove_ (struct GNUNET_FS_UnindexContext *uc) { if (NULL == uc->dsh) uc->dsh = GNUNET_DATASTORE_connect (uc->h->cfg); if (NULL == uc->dsh) { uc->state = UNINDEX_STATE_ERROR; uc->emsg = GNUNET_strdup (_("Failed to connect to `datastore' service.")); GNUNET_FS_unindex_sync_ (uc); signal_unindex_error (uc); return; } uc->fh = GNUNET_DISK_file_open (uc->filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == uc->fh) { GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO); uc->dsh = NULL; uc->state = UNINDEX_STATE_ERROR; uc->emsg = GNUNET_strdup (_("Failed to open file for unindexing.")); GNUNET_FS_unindex_sync_ (uc); signal_unindex_error (uc); return; } uc->tc = GNUNET_FS_tree_encoder_create (uc->h, uc->file_size, uc, &unindex_reader, &unindex_process, &unindex_progress, &unindex_extract_keywords); GNUNET_FS_tree_encoder_next (uc->tc); } /** * Function called once the hash of the file * that is being unindexed has been computed. * * @param cls closure, unindex context * @param file_id computed hash, NULL on error */ void GNUNET_FS_unindex_process_hash_ (void *cls, const struct GNUNET_HashCode * file_id) { struct GNUNET_FS_UnindexContext *uc = cls; uc->fhc = NULL; if (uc->state != UNINDEX_STATE_HASHING) { GNUNET_FS_unindex_stop (uc); return; } if (file_id == NULL) { uc->state = UNINDEX_STATE_ERROR; uc->emsg = GNUNET_strdup (_("Failed to compute hash of file.")); GNUNET_FS_unindex_sync_ (uc); signal_unindex_error (uc); return; } uc->file_id = *file_id; uc->state = UNINDEX_STATE_DS_REMOVE; GNUNET_FS_unindex_sync_ (uc); GNUNET_FS_unindex_do_remove_ (uc); } /** * Create SUSPEND event for the given unindex operation * and then clean up our state (without stop signal). * * @param cls the `struct GNUNET_FS_UnindexContext` to signal for */ void GNUNET_FS_unindex_signal_suspend_ (void *cls) { struct GNUNET_FS_UnindexContext *uc = cls; struct GNUNET_FS_ProgressInfo pi; /* FIXME: lots of duplication with unindex_stop here! */ if (uc->dscan != NULL) { GNUNET_FS_directory_scan_abort (uc->dscan); uc->dscan = NULL; } if (NULL != uc->dqe) { GNUNET_DATASTORE_cancel (uc->dqe); uc->dqe = NULL; } if (uc->fhc != NULL) { GNUNET_CRYPTO_hash_file_cancel (uc->fhc); uc->fhc = NULL; } if (NULL != uc->ksk_uri) { GNUNET_FS_uri_destroy (uc->ksk_uri); uc->ksk_uri = NULL; } if (uc->client != NULL) { GNUNET_CLIENT_disconnect (uc->client); uc->client = NULL; } if (NULL != uc->dsh) { GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO); uc->dsh = NULL; } if (NULL != uc->tc) { GNUNET_FS_tree_encoder_finish (uc->tc, NULL); uc->tc = NULL; } if (uc->fh != NULL) { GNUNET_DISK_file_close (uc->fh); uc->fh = NULL; } GNUNET_FS_end_top (uc->h, uc->top); pi.status = GNUNET_FS_STATUS_UNINDEX_SUSPEND; GNUNET_FS_unindex_make_status_ (&pi, uc, (uc->state == UNINDEX_STATE_COMPLETE) ? uc->file_size : 0); GNUNET_break (NULL == uc->client_info); GNUNET_free (uc->filename); GNUNET_free_non_null (uc->serialization); GNUNET_free_non_null (uc->emsg); GNUNET_free (uc); } /** * Unindex a file. * * @param h handle to the file sharing subsystem * @param filename file to unindex * @param cctx initial value for the client context * @return NULL on error, otherwise handle */ struct GNUNET_FS_UnindexContext * GNUNET_FS_unindex_start (struct GNUNET_FS_Handle *h, const char *filename, void *cctx) { struct GNUNET_FS_UnindexContext *ret; struct GNUNET_FS_ProgressInfo pi; uint64_t size; if (GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, GNUNET_YES)) return NULL; ret = GNUNET_new (struct GNUNET_FS_UnindexContext); ret->h = h; ret->filename = GNUNET_strdup (filename); ret->start_time = GNUNET_TIME_absolute_get (); ret->file_size = size; ret->client_info = cctx; GNUNET_FS_unindex_sync_ (ret); pi.status = GNUNET_FS_STATUS_UNINDEX_START; pi.value.unindex.eta = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_FS_unindex_make_status_ (&pi, ret, 0); ret->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE, filename, HASHING_BLOCKSIZE, &GNUNET_FS_unindex_process_hash_, ret); ret->top = GNUNET_FS_make_top (h, &GNUNET_FS_unindex_signal_suspend_, ret); return ret; } /** * Clean up after completion of an unindex operation. * * @param uc handle */ void GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc) { struct GNUNET_FS_ProgressInfo pi; if (uc->dscan != NULL) { GNUNET_FS_directory_scan_abort (uc->dscan); uc->dscan = NULL; } if (NULL != uc->dqe) { GNUNET_DATASTORE_cancel (uc->dqe); uc->dqe = NULL; } if (uc->fhc != NULL) { GNUNET_CRYPTO_hash_file_cancel (uc->fhc); uc->fhc = NULL; } if (uc->client != NULL) { GNUNET_CLIENT_disconnect (uc->client); uc->client = NULL; } if (NULL != uc->dsh) { GNUNET_DATASTORE_disconnect (uc->dsh, GNUNET_NO); uc->dsh = NULL; } if (NULL != uc->ksk_uri) { GNUNET_FS_uri_destroy (uc->ksk_uri); uc->ksk_uri = NULL; } if (NULL != uc->tc) { GNUNET_FS_tree_encoder_finish (uc->tc, NULL); uc->tc = NULL; } if (uc->fh != NULL) { GNUNET_DISK_file_close (uc->fh); uc->fh = NULL; } GNUNET_FS_end_top (uc->h, uc->top); if (uc->serialization != NULL) { GNUNET_FS_remove_sync_file_ (uc->h, GNUNET_FS_SYNC_PATH_MASTER_UNINDEX, uc->serialization); GNUNET_free (uc->serialization); uc->serialization = NULL; } pi.status = GNUNET_FS_STATUS_UNINDEX_STOPPED; pi.value.unindex.eta = GNUNET_TIME_UNIT_ZERO; GNUNET_FS_unindex_make_status_ (&pi, uc, (uc->state == UNINDEX_STATE_COMPLETE) ? uc->file_size : 0); GNUNET_break (NULL == uc->client_info); GNUNET_free_non_null (uc->emsg); GNUNET_free (uc->filename); GNUNET_free (uc); } /* end of fs_unindex.c */ gnunet-0.10.1/src/fs/gnunet-directory.c0000644000175000017500000001333312225777502014673 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-directory.c * @brief display content of GNUnet directories * @author Christian Grothoff */ #include "platform.h" #include "gnunet_fs_service.h" static int ret; /** * Print a meta data entry. * * @param cls closure (unused) * @param plugin_name name of the plugin that generated the meta data * @param type type of the keyword * @param format format of data * @param data_mime_type mime type of data * @param data value of the meta data * @param data_size number of bytes in data * @return always 0 (to continue iterating) */ static int item_printer (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size) { if (type == EXTRACTOR_METATYPE_GNUNET_FULL_DATA) { printf (_("\t\n"), (unsigned int) data_size); return 0; } if ((format != EXTRACTOR_METAFORMAT_UTF8) && (format != EXTRACTOR_METAFORMAT_C_STRING)) return 0; if (type == EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME) return 0; printf ("\t%20s: %s\n", dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN, EXTRACTOR_metatype_to_string (type)), data); return 0; } /** * Print an entry in a directory. * * @param cls closure (not used) * @param filename name of the file in the directory * @param uri URI of the file * @param meta metadata for the file; metadata for * the directory if everything else is NULL/zero * @param length length of the available data for the file * (of type size_t since data must certainly fit * into memory; if files are larger than size_t * permits, then they will certainly not be * embedded with the directory itself). * @param data data available for the file (length bytes) */ static void print_entry (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, size_t length, const void *data) { char *string; char *name; name = GNUNET_CONTAINER_meta_data_get_by_type (meta, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); if (uri == NULL) { printf (_("Directory `%s' meta data:\n"), name); GNUNET_CONTAINER_meta_data_iterate (meta, &item_printer, NULL); printf ("\n"); printf (_("Directory `%s' contents:\n"), name); GNUNET_free (name); return; } string = GNUNET_FS_uri_to_string (uri); printf ("%s (%s):\n", name, string); GNUNET_free (string); GNUNET_CONTAINER_meta_data_iterate (meta, &item_printer, NULL); printf ("\n"); GNUNET_free (name); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_DISK_MapHandle *map; struct GNUNET_DISK_FileHandle *h; void *data; size_t len; uint64_t size; const char *filename; int i; if (NULL == args[0]) { FPRINTF (stderr, "%s", _("You must specify a filename to inspect.\n")); ret = 1; return; } i = 0; while (NULL != (filename = args[i++])) { if ((GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, GNUNET_YES)) || (NULL == (h = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE)))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read directory `%s'\n"), filename); ret = 1; continue; } len = (size_t) size; data = GNUNET_DISK_file_map (h, &map, GNUNET_DISK_MAP_TYPE_READ, len); GNUNET_assert (NULL != data); if (GNUNET_OK != GNUNET_FS_directory_list_contents (len, data, 0, &print_entry, NULL)) fprintf (stdout, _("`%s' is not a GNUnet directory\n"), filename); else printf ("\n"); GNUNET_DISK_file_unmap (map); GNUNET_DISK_file_close (h); } } /** * The main function to inspect GNUnet directories. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-directory [OPTIONS] FILENAME", gettext_noop ("Display contents of a GNUnet directory"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-directory.c */ gnunet-0.10.1/src/fs/test_fs_defaults.conf0000644000175000017500000000205512225230043015411 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-lib/ [resolver] PORT = 4364 HOSTNAME = localhost [transport] PORT = 4365 PLUGINS = tcp [nat] DISABLEV6 = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 USE_LOCALADDR = YES RETURN_LOCAL_ADDRESSES = YES [arm] PORT = 4366 HOSTNAME = localhost DEFAULTSERVICES = fs [datastore] QUOTA = 100 MB [statistics] PORT = 4367 HOSTNAME = localhost [transport-tcp] BINDTO = 127.0.0.1 PORT = 4368 [peerinfo] PORT = 4369 HOSTNAME = localhost NO_IO = YES [ats] WAN_QUOTA_IN = 65536 WAN_QUOTA_OUT = 65536 [core] PORT = 4370 HOSTNAME = localhost [fs] PORT = 4371 HOSTNAME = localhost CONTENT_CACHING = YES CONTENT_PUSHING = YES DELAY = YES # PREFIX = valgrind --leak-check=full [testing] WEAKRANDOM = YES [dhtcache] QUOTA=65536 DATABASE=heap [dns] AUTOSTART = NO [nse] AUTOSTART = NO [dv] AUTOSTART = NO [chat] AUTOSTART = NO [gns] AUTOSTART = NO [vpn] AUTOSTART = NO [namestore] AUTOSTART = NO [consensus] AUTOSTART = NO [mesh] REFRESH_PATH_TIME = 30 min gnunet-0.10.1/src/fs/fs.conf.in0000644000175000017500000000424412250373167013107 00000000000000[fs] AUTOSTART = @AUTOSTART@ INDEXDB = $GNUNET_DATA_HOME/fs/idxinfo.lst RESPECT = $GNUNET_DATA_HOME/fs/credit/ STATE_DIR = $GNUNET_DATA_HOME/fs/persistence/ UPDATE_DIR = $GNUNET_DATA_HOME/fs/updates/ @UNIXONLY@ PORT = 2094 HOSTNAME = localhost BINARY = gnunet-service-fs ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; # Do we introduce artificial delays? (may improve anonymity) DELAY = YES # Do we cache content from other nodes? (may improve anonymity) CONTENT_CACHING = YES # Do we send unsolicited data to other nodes if we have excess bandwidth? # (may improve anonymity, probably not a good idea if content_caching is NO) CONTENT_PUSHING = YES UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-fs.sock # Do we require users that want to access file-sharing to run this process # (usually not a good idea) UNIX_MATCH_UID = NO # Do we require users that want to access file-sharing to be in the 'gnunet' group? UNIX_MATCH_GID = YES # Maximum number of requests this peer tracks (important for # memory consumption; 2k RAM/request is not unusual) MAX_PENDING_REQUESTS = 65536 # How many requests do we have at most waiting in the queue towards # the datastore? (important for memory consumption) DATASTORE_QUEUE_SIZE = 1024 # Maximum frequency we're allowed to poll the datastore # for content for migration (can be used to reduce # GNUnet's disk-IO rate) MIN_MIGRATION_DELAY = 100 ms # For how many neighbouring peers should we allocate hash maps? EXPECTED_NEIGHBOUR_COUNT = 128 # Disable anonymous file-sharing (but keep non-anonymous transfers)? # This option is mostly for testing. DISABLE_ANON_TRANSFER = NO # Maximum number of non-anonymous transfers this peer will support # at the same time. Excessive values mostly have the problem that # the service might use more memory, so we need to bound this at # some reasonable level. And if we have a very, very large # number, we probably won't have enough bandwidth to suppor them # well anyway, so better have a moderate cap. MAX_MESH_CLIENTS = 128 [gnunet-auto-share] BINARY = gnunet-auto-share # Note: MUST specify path to auto-share directory and CAN specify other options # to gnunet-auto-share here! OPTIONS = $GNUNET_DATA_HOME/fs/share/ gnunet-0.10.1/src/fs/test_gnunet_fs_rec_data.conf0000644000175000017500000000015712225230043016725 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-py-rec/ [transport] PLUGINS = gnunet-0.10.1/src/fs/Makefile.in0000644000175000017500000031242512320755252013270 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-helper-fs-publish$(EXEEXT) \ gnunet-service-fs$(EXEEXT) @HAVE_TESTING_TRUE@noinst_PROGRAMS = gnunet-fs-profiler$(EXEEXT) \ @HAVE_TESTING_TRUE@ gnunet-daemon-fsprofiler$(EXEEXT) bin_PROGRAMS = gnunet-auto-share$(EXEEXT) gnunet-directory$(EXEEXT) \ gnunet-download$(EXEEXT) gnunet-publish$(EXEEXT) \ gnunet-search$(EXEEXT) gnunet-fs$(EXEEXT) \ gnunet-unindex$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = test_plugin_block_fs$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_directory$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_download$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_download_mesh$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_download_indexed$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_download_persistence$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_file_information$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_getopt$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_list_indexed$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_namespace$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_namespace_list_updateable$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_publish$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_publish_persistence$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_search$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_search_probes$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_search_persistence$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_start_stop$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_test_lib$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_unindex$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_unindex_persistence$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_fs_uri$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_gnunet_service_fs_migration$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_gnunet_service_fs_p2p$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_gnunet_service_fs_p2p_mesh$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_1) @ENABLE_TEST_RUN_TRUE@TESTS = test_fs_directory$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_download$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_download_indexed$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_download_persistence$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_file_information$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_list_indexed$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_namespace$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_namespace_list_updateable$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_publish$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_publish_persistence$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_search$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_search_probes$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_search_persistence$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_start_stop$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_unindex$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_unindex_persistence$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_uri$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_fs_test_lib$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_gnunet_service_fs_migration$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_gnunet_service_fs_p2p$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_gnunet_service_fs_p2p_mesh$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ perf_gnunet_service_fs_p2p$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ perf_gnunet_service_fs_p2p_index$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ perf_gnunet_service_fs_p2p_respect$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ $(check_SCRIPTS) subdir = src/fs DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/fs.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = fs.conf CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = libgnunetfstest_a_AR = $(AR) $(ARFLAGS) libgnunetfstest_a_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la am_libgnunetfstest_a_OBJECTS = fs_test_lib.$(OBJEXT) libgnunetfstest_a_OBJECTS = $(am_libgnunetfstest_a_OBJECTS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunet_plugin_block_fs_la_OBJECTS = plugin_block_fs.lo libgnunet_plugin_block_fs_la_OBJECTS = \ $(am_libgnunet_plugin_block_fs_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_block_fs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunet_plugin_block_fs_la_LDFLAGS) \ $(LDFLAGS) -o $@ libgnunetfs_la_DEPENDENCIES = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libgnunetfs_la_OBJECTS = fs_api.lo fs_directory.lo \ fs_dirmetascan.lo fs_download.lo fs_file_information.lo \ fs_getopt.lo fs_list_indexed.lo fs_publish.lo \ fs_publish_ksk.lo fs_publish_ublock.lo fs_misc.lo \ fs_namespace.lo fs_search.lo fs_sharetree.lo fs_tree.lo \ fs_unindex.lo fs_uri.lo libgnunetfs_la_OBJECTS = $(am_libgnunetfs_la_OBJECTS) libgnunetfs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetfs_la_LDFLAGS) $(LDFLAGS) -o \ $@ @HAVE_BENCHMARKS_TRUE@am__EXEEXT_1 = \ @HAVE_BENCHMARKS_TRUE@ perf_gnunet_service_fs_p2p$(EXEEXT) \ @HAVE_BENCHMARKS_TRUE@ perf_gnunet_service_fs_p2p_dht$(EXEEXT) \ @HAVE_BENCHMARKS_TRUE@ perf_gnunet_service_fs_p2p_index$(EXEEXT) \ @HAVE_BENCHMARKS_TRUE@ perf_gnunet_service_fs_p2p_respect$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_auto_share_OBJECTS = gnunet-auto-share.$(OBJEXT) gnunet_auto_share_OBJECTS = $(am_gnunet_auto_share_OBJECTS) am_gnunet_daemon_fsprofiler_OBJECTS = \ gnunet-daemon-fsprofiler.$(OBJEXT) gnunet_daemon_fsprofiler_OBJECTS = \ $(am_gnunet_daemon_fsprofiler_OBJECTS) am_gnunet_directory_OBJECTS = gnunet-directory.$(OBJEXT) gnunet_directory_OBJECTS = $(am_gnunet_directory_OBJECTS) am_gnunet_download_OBJECTS = gnunet-download.$(OBJEXT) gnunet_download_OBJECTS = $(am_gnunet_download_OBJECTS) am_gnunet_fs_OBJECTS = gnunet-fs.$(OBJEXT) gnunet_fs_OBJECTS = $(am_gnunet_fs_OBJECTS) am_gnunet_fs_profiler_OBJECTS = gnunet-fs-profiler.$(OBJEXT) gnunet_fs_profiler_OBJECTS = $(am_gnunet_fs_profiler_OBJECTS) gnunet_fs_profiler_DEPENDENCIES = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_gnunet_helper_fs_publish_OBJECTS = \ gnunet-helper-fs-publish.$(OBJEXT) gnunet_helper_fs_publish_OBJECTS = \ $(am_gnunet_helper_fs_publish_OBJECTS) am_gnunet_publish_OBJECTS = gnunet-publish.$(OBJEXT) gnunet_publish_OBJECTS = $(am_gnunet_publish_OBJECTS) am_gnunet_search_OBJECTS = gnunet-search.$(OBJEXT) gnunet_search_OBJECTS = $(am_gnunet_search_OBJECTS) am_gnunet_service_fs_OBJECTS = gnunet-service-fs.$(OBJEXT) \ gnunet-service-fs_cp.$(OBJEXT) \ gnunet-service-fs_indexing.$(OBJEXT) \ gnunet-service-fs_lc.$(OBJEXT) gnunet-service-fs_pe.$(OBJEXT) \ gnunet-service-fs_pr.$(OBJEXT) \ gnunet-service-fs_push.$(OBJEXT) \ gnunet-service-fs_put.$(OBJEXT) \ gnunet-service-fs_mesh_client.$(OBJEXT) \ gnunet-service-fs_mesh_server.$(OBJEXT) gnunet_service_fs_OBJECTS = $(am_gnunet_service_fs_OBJECTS) am_gnunet_unindex_OBJECTS = gnunet-unindex.$(OBJEXT) gnunet_unindex_OBJECTS = $(am_gnunet_unindex_OBJECTS) am_perf_gnunet_service_fs_p2p_OBJECTS = \ perf_gnunet_service_fs_p2p.$(OBJEXT) perf_gnunet_service_fs_p2p_OBJECTS = \ $(am_perf_gnunet_service_fs_p2p_OBJECTS) perf_gnunet_service_fs_p2p_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_gnunet_service_fs_p2p_dht_OBJECTS = \ perf_gnunet_service_fs_p2p.$(OBJEXT) perf_gnunet_service_fs_p2p_dht_OBJECTS = \ $(am_perf_gnunet_service_fs_p2p_dht_OBJECTS) perf_gnunet_service_fs_p2p_dht_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_gnunet_service_fs_p2p_index_OBJECTS = \ perf_gnunet_service_fs_p2p.$(OBJEXT) perf_gnunet_service_fs_p2p_index_OBJECTS = \ $(am_perf_gnunet_service_fs_p2p_index_OBJECTS) perf_gnunet_service_fs_p2p_index_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_gnunet_service_fs_p2p_respect_OBJECTS = \ perf_gnunet_service_fs_p2p_respect.$(OBJEXT) perf_gnunet_service_fs_p2p_respect_OBJECTS = \ $(am_perf_gnunet_service_fs_p2p_respect_OBJECTS) perf_gnunet_service_fs_p2p_respect_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_directory_OBJECTS = test_fs_directory.$(OBJEXT) test_fs_directory_OBJECTS = $(am_test_fs_directory_OBJECTS) test_fs_directory_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_download_OBJECTS = test_fs_download.$(OBJEXT) test_fs_download_OBJECTS = $(am_test_fs_download_OBJECTS) test_fs_download_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_download_indexed_OBJECTS = test_fs_download.$(OBJEXT) test_fs_download_indexed_OBJECTS = \ $(am_test_fs_download_indexed_OBJECTS) test_fs_download_indexed_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_download_mesh_OBJECTS = test_fs_download.$(OBJEXT) test_fs_download_mesh_OBJECTS = $(am_test_fs_download_mesh_OBJECTS) test_fs_download_mesh_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_download_persistence_OBJECTS = \ test_fs_download_persistence.$(OBJEXT) test_fs_download_persistence_OBJECTS = \ $(am_test_fs_download_persistence_OBJECTS) test_fs_download_persistence_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_file_information_OBJECTS = \ test_fs_file_information.$(OBJEXT) test_fs_file_information_OBJECTS = \ $(am_test_fs_file_information_OBJECTS) test_fs_file_information_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_getopt_OBJECTS = test_fs_getopt.$(OBJEXT) test_fs_getopt_OBJECTS = $(am_test_fs_getopt_OBJECTS) test_fs_getopt_DEPENDENCIES = $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_list_indexed_OBJECTS = test_fs_list_indexed.$(OBJEXT) test_fs_list_indexed_OBJECTS = $(am_test_fs_list_indexed_OBJECTS) test_fs_list_indexed_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_namespace_OBJECTS = test_fs_namespace.$(OBJEXT) test_fs_namespace_OBJECTS = $(am_test_fs_namespace_OBJECTS) test_fs_namespace_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_namespace_list_updateable_OBJECTS = \ test_fs_namespace_list_updateable.$(OBJEXT) test_fs_namespace_list_updateable_OBJECTS = \ $(am_test_fs_namespace_list_updateable_OBJECTS) test_fs_namespace_list_updateable_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_publish_OBJECTS = test_fs_publish.$(OBJEXT) test_fs_publish_OBJECTS = $(am_test_fs_publish_OBJECTS) test_fs_publish_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_publish_persistence_OBJECTS = \ test_fs_publish_persistence.$(OBJEXT) test_fs_publish_persistence_OBJECTS = \ $(am_test_fs_publish_persistence_OBJECTS) test_fs_publish_persistence_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_search_OBJECTS = test_fs_search.$(OBJEXT) test_fs_search_OBJECTS = $(am_test_fs_search_OBJECTS) test_fs_search_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_search_persistence_OBJECTS = \ test_fs_search_persistence.$(OBJEXT) test_fs_search_persistence_OBJECTS = \ $(am_test_fs_search_persistence_OBJECTS) test_fs_search_persistence_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_search_probes_OBJECTS = test_fs_search_probes.$(OBJEXT) test_fs_search_probes_OBJECTS = $(am_test_fs_search_probes_OBJECTS) test_fs_search_probes_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_start_stop_OBJECTS = test_fs_start_stop.$(OBJEXT) test_fs_start_stop_OBJECTS = $(am_test_fs_start_stop_OBJECTS) test_fs_start_stop_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_test_lib_OBJECTS = test_fs_test_lib.$(OBJEXT) test_fs_test_lib_OBJECTS = $(am_test_fs_test_lib_OBJECTS) test_fs_test_lib_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_unindex_OBJECTS = test_fs_unindex.$(OBJEXT) test_fs_unindex_OBJECTS = $(am_test_fs_unindex_OBJECTS) test_fs_unindex_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_unindex_persistence_OBJECTS = \ test_fs_unindex_persistence.$(OBJEXT) test_fs_unindex_persistence_OBJECTS = \ $(am_test_fs_unindex_persistence_OBJECTS) test_fs_unindex_persistence_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_fs_uri_OBJECTS = test_fs_uri.$(OBJEXT) test_fs_uri_OBJECTS = $(am_test_fs_uri_OBJECTS) test_fs_uri_DEPENDENCIES = $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_service_fs_migration_OBJECTS = \ test_gnunet_service_fs_migration.$(OBJEXT) test_gnunet_service_fs_migration_OBJECTS = \ $(am_test_gnunet_service_fs_migration_OBJECTS) test_gnunet_service_fs_migration_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_service_fs_p2p_OBJECTS = \ test_gnunet_service_fs_p2p.$(OBJEXT) test_gnunet_service_fs_p2p_OBJECTS = \ $(am_test_gnunet_service_fs_p2p_OBJECTS) test_gnunet_service_fs_p2p_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_service_fs_p2p_mesh_OBJECTS = \ test_gnunet_service_fs_p2p.$(OBJEXT) test_gnunet_service_fs_p2p_mesh_OBJECTS = \ $(am_test_gnunet_service_fs_p2p_mesh_OBJECTS) test_gnunet_service_fs_p2p_mesh_DEPENDENCIES = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_block_fs_OBJECTS = test_plugin_block_fs.$(OBJEXT) test_plugin_block_fs_OBJECTS = $(am_test_plugin_block_fs_OBJECTS) test_plugin_block_fs_DEPENDENCIES = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la SCRIPTS = $(bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetfstest_a_SOURCES) \ $(libgnunet_plugin_block_fs_la_SOURCES) \ $(libgnunetfs_la_SOURCES) $(gnunet_auto_share_SOURCES) \ $(gnunet_daemon_fsprofiler_SOURCES) \ $(gnunet_directory_SOURCES) $(gnunet_download_SOURCES) \ $(gnunet_fs_SOURCES) $(gnunet_fs_profiler_SOURCES) \ $(gnunet_helper_fs_publish_SOURCES) $(gnunet_publish_SOURCES) \ $(gnunet_search_SOURCES) $(gnunet_service_fs_SOURCES) \ $(gnunet_unindex_SOURCES) \ $(perf_gnunet_service_fs_p2p_SOURCES) \ $(perf_gnunet_service_fs_p2p_dht_SOURCES) \ $(perf_gnunet_service_fs_p2p_index_SOURCES) \ $(perf_gnunet_service_fs_p2p_respect_SOURCES) \ $(test_fs_directory_SOURCES) $(test_fs_download_SOURCES) \ $(test_fs_download_indexed_SOURCES) \ $(test_fs_download_mesh_SOURCES) \ $(test_fs_download_persistence_SOURCES) \ $(test_fs_file_information_SOURCES) $(test_fs_getopt_SOURCES) \ $(test_fs_list_indexed_SOURCES) $(test_fs_namespace_SOURCES) \ $(test_fs_namespace_list_updateable_SOURCES) \ $(test_fs_publish_SOURCES) \ $(test_fs_publish_persistence_SOURCES) \ $(test_fs_search_SOURCES) \ $(test_fs_search_persistence_SOURCES) \ $(test_fs_search_probes_SOURCES) $(test_fs_start_stop_SOURCES) \ $(test_fs_test_lib_SOURCES) $(test_fs_unindex_SOURCES) \ $(test_fs_unindex_persistence_SOURCES) $(test_fs_uri_SOURCES) \ $(test_gnunet_service_fs_migration_SOURCES) \ $(test_gnunet_service_fs_p2p_SOURCES) \ $(test_gnunet_service_fs_p2p_mesh_SOURCES) \ $(test_plugin_block_fs_SOURCES) DIST_SOURCES = $(libgnunetfstest_a_SOURCES) \ $(libgnunet_plugin_block_fs_la_SOURCES) \ $(libgnunetfs_la_SOURCES) $(gnunet_auto_share_SOURCES) \ $(gnunet_daemon_fsprofiler_SOURCES) \ $(gnunet_directory_SOURCES) $(gnunet_download_SOURCES) \ $(gnunet_fs_SOURCES) $(gnunet_fs_profiler_SOURCES) \ $(gnunet_helper_fs_publish_SOURCES) $(gnunet_publish_SOURCES) \ $(gnunet_search_SOURCES) $(gnunet_service_fs_SOURCES) \ $(gnunet_unindex_SOURCES) \ $(perf_gnunet_service_fs_p2p_SOURCES) \ $(perf_gnunet_service_fs_p2p_dht_SOURCES) \ $(perf_gnunet_service_fs_p2p_index_SOURCES) \ $(perf_gnunet_service_fs_p2p_respect_SOURCES) \ $(test_fs_directory_SOURCES) $(test_fs_download_SOURCES) \ $(test_fs_download_indexed_SOURCES) \ $(test_fs_download_mesh_SOURCES) \ $(test_fs_download_persistence_SOURCES) \ $(test_fs_file_information_SOURCES) $(test_fs_getopt_SOURCES) \ $(test_fs_list_indexed_SOURCES) $(test_fs_namespace_SOURCES) \ $(test_fs_namespace_list_updateable_SOURCES) \ $(test_fs_publish_SOURCES) \ $(test_fs_publish_persistence_SOURCES) \ $(test_fs_search_SOURCES) \ $(test_fs_search_persistence_SOURCES) \ $(test_fs_search_probes_SOURCES) $(test_fs_start_stop_SOURCES) \ $(test_fs_test_lib_SOURCES) $(test_fs_unindex_SOURCES) \ $(test_fs_unindex_persistence_SOURCES) $(test_fs_uri_SOURCES) \ $(test_gnunet_service_fs_migration_SOURCES) \ $(test_gnunet_service_fs_p2p_SOURCES) \ $(test_gnunet_service_fs_p2p_mesh_SOURCES) \ $(test_plugin_block_fs_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ fs.conf plugindir = $(libdir)/gnunet lib_LTLIBRARIES = libgnunetfs.la plugin_LTLIBRARIES = \ libgnunet_plugin_block_fs.la @HAVE_TESTING_TRUE@noinst_LIBRARIES = libgnunetfstest.a libgnunetfs_la_SOURCES = \ fs_api.c fs_api.h fs.h \ fs_directory.c \ fs_dirmetascan.c \ fs_download.c \ fs_file_information.c \ fs_getopt.c \ fs_list_indexed.c \ fs_publish.c \ fs_publish_ksk.c \ fs_publish_ublock.c fs_publish_ublock.h \ fs_misc.c \ fs_namespace.c \ fs_search.c \ fs_sharetree.c \ fs_tree.c fs_tree.h \ fs_unindex.c \ fs_uri.c libgnunetfs_la_LIBADD = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) $(LIBGCRYPT_LIBS) -lunistring -lextractor libgnunetfs_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 3:1:1 libgnunetfstest_a_SOURCES = \ fs_test_lib.c fs_test_lib.h libgnunetfstest_a_LIBADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la bin_SCRIPTS = \ gnunet-download-manager.scm gnunet_directory_SOURCES = \ gnunet-directory.c gnunet_directory_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_directory_DEPENDENCIES = \ libgnunetfs.la gnunet_fs_profiler_SOURCES = \ gnunet-fs-profiler.c gnunet_fs_profiler_LDADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_fs_SOURCES = \ gnunet-fs.c gnunet_fs_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_fs_DEPENDENCIES = \ libgnunetfs.la gnunet_download_SOURCES = \ gnunet-download.c gnunet_download_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_download_DEPENDENCIES = \ libgnunetfs.la gnunet_publish_SOURCES = \ gnunet-publish.c gnunet_publish_LDADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_publish_DEPENDENCIES = \ libgnunetfs.la gnunet_auto_share_SOURCES = \ gnunet-auto-share.c gnunet_auto_share_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_auto_share_DEPENDENCIES = \ libgnunetfs.la gnunet_helper_fs_publish_SOURCES = \ gnunet-helper-fs-publish.c gnunet_helper_fs_publish_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_helper_fs_publish_DEPENDENCIES = \ libgnunetfs.la gnunet_search_SOURCES = \ gnunet-search.c gnunet_search_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_search_DEPENDENCIES = \ libgnunetfs.la gnunet_daemon_fsprofiler_SOURCES = \ gnunet-daemon-fsprofiler.c gnunet_daemon_fsprofiler_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_daemon_fsprofiler_DEPENDENCIES = \ libgnunetfs.la gnunet_service_fs_SOURCES = \ gnunet-service-fs.c gnunet-service-fs.h \ gnunet-service-fs_cp.c gnunet-service-fs_cp.h \ gnunet-service-fs_indexing.c gnunet-service-fs_indexing.h \ gnunet-service-fs_lc.c gnunet-service-fs_lc.h \ gnunet-service-fs_pe.c gnunet-service-fs_pe.h \ gnunet-service-fs_pr.c gnunet-service-fs_pr.h \ gnunet-service-fs_push.c gnunet-service-fs_push.h \ gnunet-service-fs_put.c gnunet-service-fs_put.h \ gnunet-service-fs_mesh_client.c gnunet-service-fs_mesh.h \ gnunet-service-fs_mesh_server.c gnunet_service_fs_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) -lm gnunet_service_fs_DEPENDENCIES = \ libgnunetfs.la gnunet_unindex_SOURCES = \ gnunet-unindex.c gnunet_unindex_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_unindex_DEPENDENCIES = \ libgnunetfs.la libgnunet_plugin_block_fs_la_SOURCES = \ plugin_block_fs.c libgnunet_plugin_block_fs_la_LIBADD = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_fs_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_fs_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/block/libgnunetblock.la \ libgnunetfs.la @HAVE_BENCHMARKS_TRUE@FS_BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@ perf_gnunet_service_fs_p2p \ @HAVE_BENCHMARKS_TRUE@ perf_gnunet_service_fs_p2p_dht \ @HAVE_BENCHMARKS_TRUE@ perf_gnunet_service_fs_p2p_index \ @HAVE_BENCHMARKS_TRUE@ perf_gnunet_service_fs_p2p_respect test_plugin_block_fs_SOURCES = \ test_plugin_block_fs.c test_plugin_block_fs_LDADD = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la @HAVE_PYTHON_TRUE@check_SCRIPTS = \ @HAVE_PYTHON_TRUE@ test_gnunet_fs_psd.py \ @HAVE_PYTHON_TRUE@ test_gnunet_fs_rec.py \ @HAVE_PYTHON_TRUE@ test_gnunet_fs_idx.py @ENABLE_MONKEY_TRUE@MONKEY = @MONKEYPREFIX@ @ENABLE_MONKEY_TRUE@AM_LDFLAGS = -no-install @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; $(MONKEY) test_fs_directory_SOURCES = \ test_fs_directory.c test_fs_directory_LDADD = \ -lextractor \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_download_SOURCES = \ test_fs_download.c test_fs_download_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_download_indexed_SOURCES = \ test_fs_download.c test_fs_download_indexed_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_download_mesh_SOURCES = \ test_fs_download.c test_fs_download_mesh_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_download_persistence_SOURCES = \ test_fs_download_persistence.c test_fs_download_persistence_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_file_information_SOURCES = \ test_fs_file_information.c test_fs_file_information_LDADD = \ -lextractor \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_getopt_SOURCES = \ test_fs_getopt.c test_fs_getopt_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_list_indexed_SOURCES = \ test_fs_list_indexed.c test_fs_list_indexed_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_namespace_SOURCES = \ test_fs_namespace.c test_fs_namespace_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_namespace_list_updateable_SOURCES = \ test_fs_namespace_list_updateable.c test_fs_namespace_list_updateable_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_publish_SOURCES = \ test_fs_publish.c test_fs_publish_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_publish_persistence_SOURCES = \ test_fs_publish_persistence.c test_fs_publish_persistence_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_search_SOURCES = \ test_fs_search.c test_fs_search_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_search_probes_SOURCES = \ test_fs_search_probes.c test_fs_search_probes_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_search_persistence_SOURCES = \ test_fs_search_persistence.c test_fs_search_persistence_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_start_stop_SOURCES = \ test_fs_start_stop.c test_fs_start_stop_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_unindex_SOURCES = \ test_fs_unindex.c test_fs_unindex_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_unindex_persistence_SOURCES = \ test_fs_unindex_persistence.c test_fs_unindex_persistence_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_uri_SOURCES = \ test_fs_uri.c test_fs_uri_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_test_lib_SOURCES = \ test_fs_test_lib.c test_fs_test_lib_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_service_fs_p2p_SOURCES = \ test_gnunet_service_fs_p2p.c test_gnunet_service_fs_p2p_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_service_fs_p2p_mesh_SOURCES = \ test_gnunet_service_fs_p2p.c test_gnunet_service_fs_p2p_mesh_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_service_fs_migration_SOURCES = \ test_gnunet_service_fs_migration.c test_gnunet_service_fs_migration_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la perf_gnunet_service_fs_p2p_SOURCES = \ perf_gnunet_service_fs_p2p.c perf_gnunet_service_fs_p2p_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la perf_gnunet_service_fs_p2p_index_SOURCES = \ perf_gnunet_service_fs_p2p.c perf_gnunet_service_fs_p2p_index_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la perf_gnunet_service_fs_p2p_dht_SOURCES = \ perf_gnunet_service_fs_p2p.c perf_gnunet_service_fs_p2p_dht_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la perf_gnunet_service_fs_p2p_respect_SOURCES = \ perf_gnunet_service_fs_p2p_respect.c perf_gnunet_service_fs_p2p_respect_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' EXTRA_DIST = \ test_fs_defaults.conf \ fs_test_lib_data.conf \ test_fs_data.conf \ test_fs_download_data.conf \ test_fs_download_indexed.conf \ test_fs_download_mesh.conf \ test_fs_file_information_data.conf \ fs_test_lib_data.conf \ test_fs_list_indexed_data.conf \ test_fs_namespace_data.conf \ test_fs_publish_data.conf \ test_fs_search_data.conf \ test_fs_unindex_data.conf \ test_fs_uri_data.conf \ test_gnunet_service_fs_migration_data.conf \ test_gnunet_service_fs_p2p_mesh.conf \ test_gnunet_fs_idx_data.conf \ test_gnunet_fs_psd_data.conf \ test_gnunet_fs_rec_data.conf \ perf_gnunet_service_fs_p2p.conf \ test_gnunet_fs_rec_data.tgz \ test_gnunet_fs_psd.py.in \ test_gnunet_fs_rec.py.in \ test_gnunet_fs_idx.py.in \ test_pseudonym_data.conf \ $(bin_SCRIPTS) CLEANFILES = $(check_SCRIPTS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/fs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/fs/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): fs.conf: $(top_builddir)/config.status $(srcdir)/fs.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libgnunetfstest.a: $(libgnunetfstest_a_OBJECTS) $(libgnunetfstest_a_DEPENDENCIES) $(EXTRA_libgnunetfstest_a_DEPENDENCIES) $(AM_V_at)-rm -f libgnunetfstest.a $(AM_V_AR)$(libgnunetfstest_a_AR) libgnunetfstest.a $(libgnunetfstest_a_OBJECTS) $(libgnunetfstest_a_LIBADD) $(AM_V_at)$(RANLIB) libgnunetfstest.a install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_block_fs.la: $(libgnunet_plugin_block_fs_la_OBJECTS) $(libgnunet_plugin_block_fs_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_block_fs_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_block_fs_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_fs_la_OBJECTS) $(libgnunet_plugin_block_fs_la_LIBADD) $(LIBS) libgnunetfs.la: $(libgnunetfs_la_OBJECTS) $(libgnunetfs_la_DEPENDENCIES) $(EXTRA_libgnunetfs_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetfs_la_LINK) -rpath $(libdir) $(libgnunetfs_la_OBJECTS) $(libgnunetfs_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-auto-share$(EXEEXT): $(gnunet_auto_share_OBJECTS) $(gnunet_auto_share_DEPENDENCIES) $(EXTRA_gnunet_auto_share_DEPENDENCIES) @rm -f gnunet-auto-share$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_auto_share_OBJECTS) $(gnunet_auto_share_LDADD) $(LIBS) gnunet-daemon-fsprofiler$(EXEEXT): $(gnunet_daemon_fsprofiler_OBJECTS) $(gnunet_daemon_fsprofiler_DEPENDENCIES) $(EXTRA_gnunet_daemon_fsprofiler_DEPENDENCIES) @rm -f gnunet-daemon-fsprofiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_fsprofiler_OBJECTS) $(gnunet_daemon_fsprofiler_LDADD) $(LIBS) gnunet-directory$(EXEEXT): $(gnunet_directory_OBJECTS) $(gnunet_directory_DEPENDENCIES) $(EXTRA_gnunet_directory_DEPENDENCIES) @rm -f gnunet-directory$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_directory_OBJECTS) $(gnunet_directory_LDADD) $(LIBS) gnunet-download$(EXEEXT): $(gnunet_download_OBJECTS) $(gnunet_download_DEPENDENCIES) $(EXTRA_gnunet_download_DEPENDENCIES) @rm -f gnunet-download$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_download_OBJECTS) $(gnunet_download_LDADD) $(LIBS) gnunet-fs$(EXEEXT): $(gnunet_fs_OBJECTS) $(gnunet_fs_DEPENDENCIES) $(EXTRA_gnunet_fs_DEPENDENCIES) @rm -f gnunet-fs$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_fs_OBJECTS) $(gnunet_fs_LDADD) $(LIBS) gnunet-fs-profiler$(EXEEXT): $(gnunet_fs_profiler_OBJECTS) $(gnunet_fs_profiler_DEPENDENCIES) $(EXTRA_gnunet_fs_profiler_DEPENDENCIES) @rm -f gnunet-fs-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_fs_profiler_OBJECTS) $(gnunet_fs_profiler_LDADD) $(LIBS) gnunet-helper-fs-publish$(EXEEXT): $(gnunet_helper_fs_publish_OBJECTS) $(gnunet_helper_fs_publish_DEPENDENCIES) $(EXTRA_gnunet_helper_fs_publish_DEPENDENCIES) @rm -f gnunet-helper-fs-publish$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_helper_fs_publish_OBJECTS) $(gnunet_helper_fs_publish_LDADD) $(LIBS) gnunet-publish$(EXEEXT): $(gnunet_publish_OBJECTS) $(gnunet_publish_DEPENDENCIES) $(EXTRA_gnunet_publish_DEPENDENCIES) @rm -f gnunet-publish$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_publish_OBJECTS) $(gnunet_publish_LDADD) $(LIBS) gnunet-search$(EXEEXT): $(gnunet_search_OBJECTS) $(gnunet_search_DEPENDENCIES) $(EXTRA_gnunet_search_DEPENDENCIES) @rm -f gnunet-search$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_search_OBJECTS) $(gnunet_search_LDADD) $(LIBS) gnunet-service-fs$(EXEEXT): $(gnunet_service_fs_OBJECTS) $(gnunet_service_fs_DEPENDENCIES) $(EXTRA_gnunet_service_fs_DEPENDENCIES) @rm -f gnunet-service-fs$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_fs_OBJECTS) $(gnunet_service_fs_LDADD) $(LIBS) gnunet-unindex$(EXEEXT): $(gnunet_unindex_OBJECTS) $(gnunet_unindex_DEPENDENCIES) $(EXTRA_gnunet_unindex_DEPENDENCIES) @rm -f gnunet-unindex$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_unindex_OBJECTS) $(gnunet_unindex_LDADD) $(LIBS) perf_gnunet_service_fs_p2p$(EXEEXT): $(perf_gnunet_service_fs_p2p_OBJECTS) $(perf_gnunet_service_fs_p2p_DEPENDENCIES) $(EXTRA_perf_gnunet_service_fs_p2p_DEPENDENCIES) @rm -f perf_gnunet_service_fs_p2p$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_gnunet_service_fs_p2p_OBJECTS) $(perf_gnunet_service_fs_p2p_LDADD) $(LIBS) perf_gnunet_service_fs_p2p_dht$(EXEEXT): $(perf_gnunet_service_fs_p2p_dht_OBJECTS) $(perf_gnunet_service_fs_p2p_dht_DEPENDENCIES) $(EXTRA_perf_gnunet_service_fs_p2p_dht_DEPENDENCIES) @rm -f perf_gnunet_service_fs_p2p_dht$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_gnunet_service_fs_p2p_dht_OBJECTS) $(perf_gnunet_service_fs_p2p_dht_LDADD) $(LIBS) perf_gnunet_service_fs_p2p_index$(EXEEXT): $(perf_gnunet_service_fs_p2p_index_OBJECTS) $(perf_gnunet_service_fs_p2p_index_DEPENDENCIES) $(EXTRA_perf_gnunet_service_fs_p2p_index_DEPENDENCIES) @rm -f perf_gnunet_service_fs_p2p_index$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_gnunet_service_fs_p2p_index_OBJECTS) $(perf_gnunet_service_fs_p2p_index_LDADD) $(LIBS) perf_gnunet_service_fs_p2p_respect$(EXEEXT): $(perf_gnunet_service_fs_p2p_respect_OBJECTS) $(perf_gnunet_service_fs_p2p_respect_DEPENDENCIES) $(EXTRA_perf_gnunet_service_fs_p2p_respect_DEPENDENCIES) @rm -f perf_gnunet_service_fs_p2p_respect$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_gnunet_service_fs_p2p_respect_OBJECTS) $(perf_gnunet_service_fs_p2p_respect_LDADD) $(LIBS) test_fs_directory$(EXEEXT): $(test_fs_directory_OBJECTS) $(test_fs_directory_DEPENDENCIES) $(EXTRA_test_fs_directory_DEPENDENCIES) @rm -f test_fs_directory$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_directory_OBJECTS) $(test_fs_directory_LDADD) $(LIBS) test_fs_download$(EXEEXT): $(test_fs_download_OBJECTS) $(test_fs_download_DEPENDENCIES) $(EXTRA_test_fs_download_DEPENDENCIES) @rm -f test_fs_download$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_download_OBJECTS) $(test_fs_download_LDADD) $(LIBS) test_fs_download_indexed$(EXEEXT): $(test_fs_download_indexed_OBJECTS) $(test_fs_download_indexed_DEPENDENCIES) $(EXTRA_test_fs_download_indexed_DEPENDENCIES) @rm -f test_fs_download_indexed$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_download_indexed_OBJECTS) $(test_fs_download_indexed_LDADD) $(LIBS) test_fs_download_mesh$(EXEEXT): $(test_fs_download_mesh_OBJECTS) $(test_fs_download_mesh_DEPENDENCIES) $(EXTRA_test_fs_download_mesh_DEPENDENCIES) @rm -f test_fs_download_mesh$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_download_mesh_OBJECTS) $(test_fs_download_mesh_LDADD) $(LIBS) test_fs_download_persistence$(EXEEXT): $(test_fs_download_persistence_OBJECTS) $(test_fs_download_persistence_DEPENDENCIES) $(EXTRA_test_fs_download_persistence_DEPENDENCIES) @rm -f test_fs_download_persistence$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_download_persistence_OBJECTS) $(test_fs_download_persistence_LDADD) $(LIBS) test_fs_file_information$(EXEEXT): $(test_fs_file_information_OBJECTS) $(test_fs_file_information_DEPENDENCIES) $(EXTRA_test_fs_file_information_DEPENDENCIES) @rm -f test_fs_file_information$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_file_information_OBJECTS) $(test_fs_file_information_LDADD) $(LIBS) test_fs_getopt$(EXEEXT): $(test_fs_getopt_OBJECTS) $(test_fs_getopt_DEPENDENCIES) $(EXTRA_test_fs_getopt_DEPENDENCIES) @rm -f test_fs_getopt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_getopt_OBJECTS) $(test_fs_getopt_LDADD) $(LIBS) test_fs_list_indexed$(EXEEXT): $(test_fs_list_indexed_OBJECTS) $(test_fs_list_indexed_DEPENDENCIES) $(EXTRA_test_fs_list_indexed_DEPENDENCIES) @rm -f test_fs_list_indexed$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_list_indexed_OBJECTS) $(test_fs_list_indexed_LDADD) $(LIBS) test_fs_namespace$(EXEEXT): $(test_fs_namespace_OBJECTS) $(test_fs_namespace_DEPENDENCIES) $(EXTRA_test_fs_namespace_DEPENDENCIES) @rm -f test_fs_namespace$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_namespace_OBJECTS) $(test_fs_namespace_LDADD) $(LIBS) test_fs_namespace_list_updateable$(EXEEXT): $(test_fs_namespace_list_updateable_OBJECTS) $(test_fs_namespace_list_updateable_DEPENDENCIES) $(EXTRA_test_fs_namespace_list_updateable_DEPENDENCIES) @rm -f test_fs_namespace_list_updateable$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_namespace_list_updateable_OBJECTS) $(test_fs_namespace_list_updateable_LDADD) $(LIBS) test_fs_publish$(EXEEXT): $(test_fs_publish_OBJECTS) $(test_fs_publish_DEPENDENCIES) $(EXTRA_test_fs_publish_DEPENDENCIES) @rm -f test_fs_publish$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_publish_OBJECTS) $(test_fs_publish_LDADD) $(LIBS) test_fs_publish_persistence$(EXEEXT): $(test_fs_publish_persistence_OBJECTS) $(test_fs_publish_persistence_DEPENDENCIES) $(EXTRA_test_fs_publish_persistence_DEPENDENCIES) @rm -f test_fs_publish_persistence$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_publish_persistence_OBJECTS) $(test_fs_publish_persistence_LDADD) $(LIBS) test_fs_search$(EXEEXT): $(test_fs_search_OBJECTS) $(test_fs_search_DEPENDENCIES) $(EXTRA_test_fs_search_DEPENDENCIES) @rm -f test_fs_search$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_search_OBJECTS) $(test_fs_search_LDADD) $(LIBS) test_fs_search_persistence$(EXEEXT): $(test_fs_search_persistence_OBJECTS) $(test_fs_search_persistence_DEPENDENCIES) $(EXTRA_test_fs_search_persistence_DEPENDENCIES) @rm -f test_fs_search_persistence$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_search_persistence_OBJECTS) $(test_fs_search_persistence_LDADD) $(LIBS) test_fs_search_probes$(EXEEXT): $(test_fs_search_probes_OBJECTS) $(test_fs_search_probes_DEPENDENCIES) $(EXTRA_test_fs_search_probes_DEPENDENCIES) @rm -f test_fs_search_probes$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_search_probes_OBJECTS) $(test_fs_search_probes_LDADD) $(LIBS) test_fs_start_stop$(EXEEXT): $(test_fs_start_stop_OBJECTS) $(test_fs_start_stop_DEPENDENCIES) $(EXTRA_test_fs_start_stop_DEPENDENCIES) @rm -f test_fs_start_stop$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_start_stop_OBJECTS) $(test_fs_start_stop_LDADD) $(LIBS) test_fs_test_lib$(EXEEXT): $(test_fs_test_lib_OBJECTS) $(test_fs_test_lib_DEPENDENCIES) $(EXTRA_test_fs_test_lib_DEPENDENCIES) @rm -f test_fs_test_lib$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_test_lib_OBJECTS) $(test_fs_test_lib_LDADD) $(LIBS) test_fs_unindex$(EXEEXT): $(test_fs_unindex_OBJECTS) $(test_fs_unindex_DEPENDENCIES) $(EXTRA_test_fs_unindex_DEPENDENCIES) @rm -f test_fs_unindex$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_unindex_OBJECTS) $(test_fs_unindex_LDADD) $(LIBS) test_fs_unindex_persistence$(EXEEXT): $(test_fs_unindex_persistence_OBJECTS) $(test_fs_unindex_persistence_DEPENDENCIES) $(EXTRA_test_fs_unindex_persistence_DEPENDENCIES) @rm -f test_fs_unindex_persistence$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_unindex_persistence_OBJECTS) $(test_fs_unindex_persistence_LDADD) $(LIBS) test_fs_uri$(EXEEXT): $(test_fs_uri_OBJECTS) $(test_fs_uri_DEPENDENCIES) $(EXTRA_test_fs_uri_DEPENDENCIES) @rm -f test_fs_uri$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fs_uri_OBJECTS) $(test_fs_uri_LDADD) $(LIBS) test_gnunet_service_fs_migration$(EXEEXT): $(test_gnunet_service_fs_migration_OBJECTS) $(test_gnunet_service_fs_migration_DEPENDENCIES) $(EXTRA_test_gnunet_service_fs_migration_DEPENDENCIES) @rm -f test_gnunet_service_fs_migration$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_service_fs_migration_OBJECTS) $(test_gnunet_service_fs_migration_LDADD) $(LIBS) test_gnunet_service_fs_p2p$(EXEEXT): $(test_gnunet_service_fs_p2p_OBJECTS) $(test_gnunet_service_fs_p2p_DEPENDENCIES) $(EXTRA_test_gnunet_service_fs_p2p_DEPENDENCIES) @rm -f test_gnunet_service_fs_p2p$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_service_fs_p2p_OBJECTS) $(test_gnunet_service_fs_p2p_LDADD) $(LIBS) test_gnunet_service_fs_p2p_mesh$(EXEEXT): $(test_gnunet_service_fs_p2p_mesh_OBJECTS) $(test_gnunet_service_fs_p2p_mesh_DEPENDENCIES) $(EXTRA_test_gnunet_service_fs_p2p_mesh_DEPENDENCIES) @rm -f test_gnunet_service_fs_p2p_mesh$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_service_fs_p2p_mesh_OBJECTS) $(test_gnunet_service_fs_p2p_mesh_LDADD) $(LIBS) test_plugin_block_fs$(EXEEXT): $(test_plugin_block_fs_OBJECTS) $(test_plugin_block_fs_DEPENDENCIES) $(EXTRA_test_plugin_block_fs_DEPENDENCIES) @rm -f test_plugin_block_fs$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_block_fs_OBJECTS) $(test_plugin_block_fs_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_directory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_dirmetascan.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_download.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_file_information.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_getopt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_list_indexed.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_misc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_namespace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_publish.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_publish_ksk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_publish_ublock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_search.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_sharetree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_test_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_tree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_unindex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs_uri.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-auto-share.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-fsprofiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-directory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-download.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-fs-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-fs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-fs-publish.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-publish.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-search.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_cp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_indexing.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_lc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_mesh_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_mesh_server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_pe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_pr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_push.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-fs_put.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-unindex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_gnunet_service_fs_p2p.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_gnunet_service_fs_p2p_respect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_fs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_directory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_download.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_download_persistence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_file_information.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_list_indexed.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_namespace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_namespace_list_updateable.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_publish.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_publish_persistence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_search.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_search_persistence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_search_probes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_start_stop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_test_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_unindex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_unindex_persistence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_fs_uri.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_service_fs_migration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_service_fs_p2p.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_block_fs.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_fs_directory.log: test_fs_directory$(EXEEXT) @p='test_fs_directory$(EXEEXT)'; \ b='test_fs_directory'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_download.log: test_fs_download$(EXEEXT) @p='test_fs_download$(EXEEXT)'; \ b='test_fs_download'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_download_indexed.log: test_fs_download_indexed$(EXEEXT) @p='test_fs_download_indexed$(EXEEXT)'; \ b='test_fs_download_indexed'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_download_persistence.log: test_fs_download_persistence$(EXEEXT) @p='test_fs_download_persistence$(EXEEXT)'; \ b='test_fs_download_persistence'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_file_information.log: test_fs_file_information$(EXEEXT) @p='test_fs_file_information$(EXEEXT)'; \ b='test_fs_file_information'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_list_indexed.log: test_fs_list_indexed$(EXEEXT) @p='test_fs_list_indexed$(EXEEXT)'; \ b='test_fs_list_indexed'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_namespace.log: test_fs_namespace$(EXEEXT) @p='test_fs_namespace$(EXEEXT)'; \ b='test_fs_namespace'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_namespace_list_updateable.log: test_fs_namespace_list_updateable$(EXEEXT) @p='test_fs_namespace_list_updateable$(EXEEXT)'; \ b='test_fs_namespace_list_updateable'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_publish.log: test_fs_publish$(EXEEXT) @p='test_fs_publish$(EXEEXT)'; \ b='test_fs_publish'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_publish_persistence.log: test_fs_publish_persistence$(EXEEXT) @p='test_fs_publish_persistence$(EXEEXT)'; \ b='test_fs_publish_persistence'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_search.log: test_fs_search$(EXEEXT) @p='test_fs_search$(EXEEXT)'; \ b='test_fs_search'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_search_probes.log: test_fs_search_probes$(EXEEXT) @p='test_fs_search_probes$(EXEEXT)'; \ b='test_fs_search_probes'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_search_persistence.log: test_fs_search_persistence$(EXEEXT) @p='test_fs_search_persistence$(EXEEXT)'; \ b='test_fs_search_persistence'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_start_stop.log: test_fs_start_stop$(EXEEXT) @p='test_fs_start_stop$(EXEEXT)'; \ b='test_fs_start_stop'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_unindex.log: test_fs_unindex$(EXEEXT) @p='test_fs_unindex$(EXEEXT)'; \ b='test_fs_unindex'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_unindex_persistence.log: test_fs_unindex_persistence$(EXEEXT) @p='test_fs_unindex_persistence$(EXEEXT)'; \ b='test_fs_unindex_persistence'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_uri.log: test_fs_uri$(EXEEXT) @p='test_fs_uri$(EXEEXT)'; \ b='test_fs_uri'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_fs_test_lib.log: test_fs_test_lib$(EXEEXT) @p='test_fs_test_lib$(EXEEXT)'; \ b='test_fs_test_lib'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_service_fs_migration.log: test_gnunet_service_fs_migration$(EXEEXT) @p='test_gnunet_service_fs_migration$(EXEEXT)'; \ b='test_gnunet_service_fs_migration'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_service_fs_p2p.log: test_gnunet_service_fs_p2p$(EXEEXT) @p='test_gnunet_service_fs_p2p$(EXEEXT)'; \ b='test_gnunet_service_fs_p2p'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_service_fs_p2p_mesh.log: test_gnunet_service_fs_p2p_mesh$(EXEEXT) @p='test_gnunet_service_fs_p2p_mesh$(EXEEXT)'; \ b='test_gnunet_service_fs_p2p_mesh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_gnunet_service_fs_p2p.log: perf_gnunet_service_fs_p2p$(EXEEXT) @p='perf_gnunet_service_fs_p2p$(EXEEXT)'; \ b='perf_gnunet_service_fs_p2p'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_gnunet_service_fs_p2p_index.log: perf_gnunet_service_fs_p2p_index$(EXEEXT) @p='perf_gnunet_service_fs_p2p_index$(EXEEXT)'; \ b='perf_gnunet_service_fs_p2p_index'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_gnunet_service_fs_p2p_respect.log: perf_gnunet_service_fs_p2p_respect$(EXEEXT) @p='perf_gnunet_service_fs_p2p_respect$(EXEEXT)'; \ b='perf_gnunet_service_fs_p2p_respect'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_fs_psd.py.log: test_gnunet_fs_psd.py @p='test_gnunet_fs_psd.py'; \ b='test_gnunet_fs_psd.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_fs_rec.py.log: test_gnunet_fs_rec.py @p='test_gnunet_fs_rec.py'; \ b='test_gnunet_fs_rec.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_fs_idx.py.log: test_gnunet_fs_idx.py @p='test_gnunet_fs_idx.py'; \ b='test_gnunet_fs_idx.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) \ $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstLIBRARIES clean-noinstPROGRAMS \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS \ install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstLIBRARIES clean-noinstPROGRAMS \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-binSCRIPTS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libexecPROGRAMS install-man install-pdf install-pdf-am \ install-pkgcfgDATA install-pluginLTLIBRARIES install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-binSCRIPTS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES test_gnunet_fs_psd.py: test_gnunet_fs_psd.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_fs_psd.py.in > test_gnunet_fs_psd.py chmod +x test_gnunet_fs_psd.py test_gnunet_fs_rec.py: test_gnunet_fs_rec.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_fs_rec.py.in > test_gnunet_fs_rec.py chmod +x test_gnunet_fs_rec.py test_gnunet_fs_ns.py: test_gnunet_fs_ns.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_fs_ns.py.in > test_gnunet_fs_ns.py chmod +x test_gnunet_fs_ns.py test_gnunet_fs_idx.py: test_gnunet_fs_idx.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_fs_idx.py.in > test_gnunet_fs_idx.py chmod +x test_gnunet_fs_idx.py # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/fs/perf_gnunet_service_fs_p2p.c0000644000175000017500000002204612255010511016656 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/perf_gnunet_service_fs_p2p.c * @brief profile P2P routing using simple publish + download operation * @author Christian Grothoff */ #include "platform.h" #include "fs_test_lib.h" #include "gnunet_testbed_service.h" #define VERBOSE GNUNET_NO /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 10) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) #define NUM_DAEMONS 2 #define SEED 42 static struct GNUNET_TESTBED_Peer *daemons[NUM_DAEMONS]; static int ok; static struct GNUNET_TIME_Absolute start_time; static const char *progname; /** * Master context for 'stat_run'. */ struct StatMaster { struct GNUNET_STATISTICS_Handle *stat; struct GNUNET_TESTBED_Operation *op; unsigned int daemon; unsigned int value; }; struct StatValues { const char *subsystem; const char *name; }; /** * Statistics we print out. */ static struct StatValues stats[] = { {"fs", "# queries forwarded"}, {"fs", "# replies received and matched"}, {"fs", "# results found locally"}, {"fs", "# requests forwarded due to high load"}, {"fs", "# requests done for free (low load)"}, {"fs", "# requests dropped, priority insufficient"}, {"fs", "# requests done for a price (normal load)"}, {"fs", "# requests dropped by datastore (queue length limit)"}, {"fs", "# P2P searches received"}, {"fs", "# P2P searches discarded (queue length bound)"}, {"fs", "# replies received for local clients"}, {"fs", "# queries retransmitted to same target"}, {"core", "# bytes decrypted"}, {"core", "# bytes encrypted"}, {"core", "# discarded CORE_SEND requests"}, {"core", "# discarded CORE_SEND request bytes"}, {"core", "# discarded lower priority CORE_SEND requests"}, {"core", "# discarded lower priority CORE_SEND request bytes"}, {"transport", "# bytes received via TCP"}, {"transport", "# bytes transmitted via TCP"}, {"datacache", "# bytes stored"}, {NULL, NULL} }; /** * Callback function to process statistic values. * * @param cls closure * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int print_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { struct StatMaster *sm = cls; FPRINTF (stderr, "Peer %2u: %12s/%50s = %12llu\n", sm->daemon, subsystem, name, (unsigned long long) value); return GNUNET_OK; } /** * Function that gathers stats from all daemons. */ static void stat_run (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg); /** * Function called when GET operation on stats is done. */ static void get_done (void *cls, int success) { struct StatMaster *sm = cls; GNUNET_break (GNUNET_OK == success); sm->value++; stat_run (sm, sm->op, sm->stat, NULL); } /** * Adapter function called to establish a connection to * statistics service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * statistics_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_STATISTICS_create ("", cfg); } /** * Adapter function called to destroy a connection to * statistics service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void statistics_disconnect_adapter (void *cls, void *op_result) { GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); } /** * Function that gathers stats from all daemons. */ static void stat_run (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct StatMaster *sm = cls; if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to statistics service: %s\n", emsg); GNUNET_SCHEDULER_shutdown (); return; } sm->stat = ca_result; if (stats[sm->value].name != NULL) { GNUNET_STATISTICS_get (sm->stat, #if 0 NULL, NULL, #else stats[sm->value].subsystem, stats[sm->value].name, #endif GNUNET_TIME_UNIT_FOREVER_REL, &get_done, &print_stat, sm); return; } GNUNET_TESTBED_operation_done (sm->op); sm->value = 0; sm->daemon++; if (NUM_DAEMONS == sm->daemon) { GNUNET_free (sm); GNUNET_SCHEDULER_shutdown (); return; } sm->op = GNUNET_TESTBED_service_connect (NULL, daemons[sm->daemon], "statistics", &stat_run, sm, &statistics_connect_adapter, &statistics_disconnect_adapter, NULL); } static void do_report (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { char *fn = cls; struct GNUNET_TIME_Relative del; char *fancy; struct StatMaster *sm; if (NULL != fn) { GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); } if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout during download, shutting down with error\n"); ok = 1; GNUNET_SCHEDULER_shutdown (); return; } del = GNUNET_TIME_absolute_get_duration (start_time); if (del.rel_value_us == 0) del.rel_value_us = 1; fancy = GNUNET_STRINGS_byte_size_fancy (((unsigned long long) FILESIZE) * 1000000LL / del.rel_value_us); FPRINTF (stdout, "Download speed was %s/s\n", fancy); GNUNET_free (fancy); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished download, shutting down\n", (unsigned long long) FILESIZE); sm = GNUNET_new (struct StatMaster); sm->op = GNUNET_TESTBED_service_connect (NULL, daemons[sm->daemon], "statistics", &stat_run, sm, &statistics_connect_adapter, &statistics_disconnect_adapter, NULL); } static void do_download (void *cls, const struct GNUNET_FS_Uri *uri, const char *fn) { int anonymity; if (NULL == uri) { GNUNET_SCHEDULER_shutdown (); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout during upload attempt, shutting down with error\n"); ok = 1; return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Downloading %llu bytes\n", (unsigned long long) FILESIZE); start_time = GNUNET_TIME_absolute_get (); if (NULL != strstr (progname, "dht")) anonymity = 0; else anonymity = 1; GNUNET_FS_TEST_download (daemons[0], TIMEOUT, anonymity, SEED, uri, VERBOSE, &do_report, (NULL == fn) ? NULL : GNUNET_strdup (fn)); } static void do_publish (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { unsigned int i; int do_index; int anonymity; GNUNET_assert (NUM_DAEMONS == num_peers); for (i=0;istatus) { case GNUNET_FS_STATUS_PUBLISH_COMPLETED: ret = event->value.publish.cctx; printf ("Publish complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); if (0 == strcmp ("publish-context-dir", event->value.publish.cctx)) GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS: ret = event->value.publish.cctx; GNUNET_assert (publish == event->value.publish.pc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: ret = event->value.publish.cctx; break; case GNUNET_FS_STATUS_PUBLISH_ERROR: ret = event->value.publish.cctx; FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); err = 1; if (0 == strcmp ("publish-context-dir", event->value.publish.cctx)) { FPRINTF (stderr, "Scheduling abort task for error on `%s'\n", (const char *) event->value.publish.cctx); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } break; case GNUNET_FS_STATUS_PUBLISH_START: ret = event->value.publish.cctx; if (0 == strcmp ("publish-context1", event->value.publish.cctx)) { GNUNET_assert (0 == strcmp ("publish-context-dir", event->value.publish.pctx)); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); } else if (0 == strcmp ("publish-context2", event->value.publish.cctx)) { GNUNET_assert (0 == strcmp ("publish-context-dir", event->value.publish.pctx)); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (2 == event->value.publish.anonymity); } else if (0 == strcmp ("publish-context-dir", event->value.publish.cctx)) { GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (3 == event->value.publish.anonymity); } else GNUNET_assert (0); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: if (0 == strcmp ("publish-context-dir", event->value.publish.cctx)) GNUNET_assert (publish == event->value.publish.pc); break; default: printf ("Unexpected event: %d\n", event->status); break; } return ret; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar", }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi1; struct GNUNET_FS_FileInformation *fi2; struct GNUNET_FS_FileInformation *fidir; size_t i; struct GNUNET_FS_BlockOptions bo; fs = GNUNET_FS_start (cfg, "test-fs-publish", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); fn1 = GNUNET_DISK_mktemp ("gnunet-publish-test-dst"); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn1, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); fn2 = GNUNET_DISK_mktemp ("gnunet-publish-test-dst"); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn2, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi1 = GNUNET_FS_file_information_create_from_file (fs, "publish-context1", fn1, kuri, meta, GNUNET_YES, &bo); GNUNET_assert (NULL != fi1); bo.anonymity_level = 2; fi2 = GNUNET_FS_file_information_create_from_file (fs, "publish-context2", fn2, kuri, meta, GNUNET_YES, &bo); GNUNET_assert (NULL != fi2); bo.anonymity_level = 3; fidir = GNUNET_FS_file_information_create_empty_directory (fs, "publish-context-dir", kuri, meta, &bo, NULL); GNUNET_assert (GNUNET_OK == GNUNET_FS_file_information_add (fidir, fi1)); GNUNET_assert (GNUNET_OK == GNUNET_FS_file_information_add (fidir, fi2)); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fidir); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fidir, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-publish", "test_fs_publish_data.conf", &run, NULL)) return 1; return err; } /* end of test_fs_publish.c */ gnunet-0.10.1/src/fs/test_fs_download_indexed.conf0000644000175000017500000000032712225230043017111 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-download/ [download-test] # set to 'YES' to test non-anonymous download USE_STREAM = NO # set to 'YES' to use indexing USE_INDEX = YES gnunet-0.10.1/src/fs/gnunet-service-fs.c0000644000175000017500000005060112225777502014734 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs.c * @brief gnunet anonymity protocol implementation * @author Christian Grothoff */ #include "platform.h" #include #include "gnunet_constants.h" #include "gnunet_core_service.h" #include "gnunet_dht_service.h" #include "gnunet_datastore_service.h" #include "gnunet_load_lib.h" #include "gnunet_peer_lib.h" #include "gnunet_protocols.h" #include "gnunet_signatures.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_util_lib.h" #include "gnunet-service-fs_cp.h" #include "gnunet-service-fs_indexing.h" #include "gnunet-service-fs_lc.h" #include "gnunet-service-fs_pe.h" #include "gnunet-service-fs_pr.h" #include "gnunet-service-fs_push.h" #include "gnunet-service-fs_put.h" #include "gnunet-service-fs_mesh.h" #include "fs.h" /** * Size for the hash map for DHT requests from the FS * service. Should be about the number of concurrent * DHT requests we plan to make. */ #define FS_DHT_HT_SIZE 1024 /** * How quickly do we age cover traffic? At the given * time interval, remaining cover traffic counters are * decremented by 1/16th. */ #define COVER_AGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Collect an instane number of statistics? May cause excessive IPC. */ #define INSANE_STATISTICS GNUNET_NO /* ****************************** globals ****************************** */ /** * Our connection to the datastore. */ struct GNUNET_DATASTORE_Handle *GSF_dsh; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *GSF_cfg; /** * Handle for reporting statistics. */ struct GNUNET_STATISTICS_Handle *GSF_stats; /** * Handle for DHT operations. */ struct GNUNET_DHT_Handle *GSF_dht; /** * How long do requests typically stay in the routing table? */ struct GNUNET_LOAD_Value *GSF_rt_entry_lifetime; /** * Running average of the observed latency to other peers (round trip). * Initialized to 5s as the initial default. */ struct GNUNET_TIME_Relative GSF_avg_latency = { 500 }; /** * Handle to ATS service. */ struct GNUNET_ATS_PerformanceHandle *GSF_ats; /** * Typical priorities we're seeing from other peers right now. Since * most priorities will be zero, this value is the weighted average of * non-zero priorities seen "recently". In order to ensure that new * values do not dramatically change the ratio, values are first * "capped" to a reasonable range (+N of the current value) and then * averaged into the existing value by a ratio of 1:N. Hence * receiving the largest possible priority can still only raise our * "current_priorities" by at most 1. */ double GSF_current_priorities; /** * Size of the datastore queue we assume for common requests. */ unsigned int GSF_datastore_queue_size; /** * How many query messages have we received 'recently' that * have not yet been claimed as cover traffic? */ unsigned int GSF_cover_query_count; /** * How many content messages have we received 'recently' that * have not yet been claimed as cover traffic? */ unsigned int GSF_cover_content_count; /** * Our block context. */ struct GNUNET_BLOCK_Context *GSF_block_ctx; /** * Pointer to handle to the core service (points to NULL until we've * connected to it). */ struct GNUNET_CORE_Handle *GSF_core; /** * Are we introducing randomized delays for better anonymity? */ int GSF_enable_randomized_delays; /* ***************************** locals ******************************* */ /** * Configuration for block library. */ static struct GNUNET_CONFIGURATION_Handle *block_cfg; /** * ID of our task that we use to age the cover counters. */ static GNUNET_SCHEDULER_TaskIdentifier cover_age_task; /** * Datastore 'GET' load tracking. */ static struct GNUNET_LOAD_Value *datastore_get_load; /** * Identity of this peer. */ static struct GNUNET_PeerIdentity my_id; /** * Task that periodically ages our cover traffic statistics. * * @param cls unused closure * @param tc task context */ static void age_cover_counters (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GSF_cover_content_count = (GSF_cover_content_count * 15) / 16; GSF_cover_query_count = (GSF_cover_query_count * 15) / 16; cover_age_task = GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY, &age_cover_counters, NULL); } /** * We've just now completed a datastore request. Update our * datastore load calculations. * * @param start time when the datastore request was issued */ void GSF_update_datastore_delay_ (struct GNUNET_TIME_Absolute start) { struct GNUNET_TIME_Relative delay; delay = GNUNET_TIME_absolute_get_duration (start); GNUNET_LOAD_update (datastore_get_load, delay.rel_value_us); } /** * Test if the DATABASE (GET) load on this peer is too high * to even consider processing the query at * all. * * @param priority priority of the request (used as a reference point to compare with the load) * @return GNUNET_YES if the load is too high to do anything (load high) * GNUNET_NO to process normally (load normal) * GNUNET_SYSERR to process for free (load low) */ int GSF_test_get_load_too_high_ (uint32_t priority) { double ld; ld = GNUNET_LOAD_get_load (datastore_get_load); if (ld < 1) return GNUNET_SYSERR; if (ld <= priority) return GNUNET_NO; return GNUNET_YES; } /** * We've received peer performance information. Update * our running average for the P2P latency. * * @param cls closure * @param address the address * @param active is this address in active use * @param bandwidth_out assigned outbound bandwidth for the connection * @param bandwidth_in assigned inbound bandwidth for the connection * @param ats performance data for the address (as far as known) * @param ats_count number of performance records in 'ats' */ static void update_latencies (void *cls, const struct GNUNET_HELLO_Address *address, int active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { unsigned int i; struct GNUNET_TIME_Relative latency; if (GNUNET_YES != active) return; for (i = 0; i < ats_count; i++) { if (GNUNET_ATS_QUALITY_NET_DELAY != ntohl (ats[i].type)) continue; latency.rel_value_us = ntohl (ats[i].value); GSF_update_peer_latency_ (&address->peer, latency); GSF_avg_latency.rel_value_us = (GSF_avg_latency.rel_value_us * 31 + GNUNET_MIN (5000, ntohl (ats[i].value))) / 32; GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# running average P2P latency (ms)"), GSF_avg_latency.rel_value_us / 1000LL, GNUNET_NO); break; } } /** * Handle P2P "PUT" message. * * @param cls closure, always NULL * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_p2p_put (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { struct GSF_ConnectedPeer *cp; cp = GSF_peer_get_ (other); if (NULL == cp) { GNUNET_break (0); return GNUNET_OK; } GSF_cover_content_count++; return GSF_handle_p2p_content_ (cp, message); } /** * We have a new request, consider forwarding it to the given * peer. * * @param cls the 'struct GSF_PendingRequest' * @param peer identity of the peer * @param cp handle to the connected peer record * @param ppd peer performance data */ static void consider_request_for_forwarding (void *cls, const struct GNUNET_PeerIdentity *peer, struct GSF_ConnectedPeer *cp, const struct GSF_PeerPerformanceData *ppd) { struct GSF_PendingRequest *pr = cls; if (GNUNET_YES != GSF_pending_request_test_target_ (pr, peer)) { #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Loopback routes suppressed"), 1, GNUNET_NO); #endif return; } GSF_plan_add_ (cp, pr); } /** * Function to be called after we're done processing * replies from the local lookup. If the result status * code indicates that there may be more replies, plan * forwarding the request. * * @param cls closure (NULL) * @param pr the pending request we were processing * @param result final datastore lookup result */ static void consider_forwarding (void *cls, struct GSF_PendingRequest *pr, enum GNUNET_BLOCK_EvaluationResult result) { if (GNUNET_BLOCK_EVALUATION_OK_LAST == result) return; /* we're done... */ GSF_iterate_connected_peers_ (&consider_request_for_forwarding, pr); } /** * Handle P2P "GET" request. * * @param cls closure, always NULL * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_p2p_get (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { struct GSF_PendingRequest *pr; pr = GSF_handle_p2p_query_ (other, message); if (NULL == pr) return GNUNET_SYSERR; GSF_pending_request_get_data_ (pr)->has_started = GNUNET_YES; GSF_local_lookup_ (pr, &consider_forwarding, NULL); return GNUNET_OK; } /** * We're done with the local lookup, now consider * P2P processing (depending on request options and * result status). Also signal that we can now * receive more request information from the client. * * @param cls the client doing the request ('struct GNUNET_SERVER_Client') * @param pr the pending request we were processing * @param result final datastore lookup result */ static void start_p2p_processing (void *cls, struct GSF_PendingRequest *pr, enum GNUNET_BLOCK_EvaluationResult result) { struct GNUNET_SERVER_Client *client = cls; struct GSF_PendingRequestData *prd; prd = GSF_pending_request_get_data_ (pr); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished database lookup for local request `%s' with result %d\n", GNUNET_h2s (&prd->query), result); GNUNET_SERVER_receive_done (client, GNUNET_OK); if (GNUNET_BLOCK_EVALUATION_OK_LAST == result) return; /* we're done, 'pr' was already destroyed... */ if (0 != (GSF_PRO_LOCAL_ONLY & prd->options)) { GSF_pending_request_cancel_ (pr, GNUNET_YES); return; } if (0 == prd->anonymity_level) { switch (prd->type) { case GNUNET_BLOCK_TYPE_FS_DBLOCK: case GNUNET_BLOCK_TYPE_FS_IBLOCK: /* the above block types MAY be available via 'mesh' */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Considering mesh-based download for block\n"); GSF_mesh_lookup_ (pr); break; case GNUNET_BLOCK_TYPE_FS_UBLOCK: /* the above block types are in the DHT */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Considering DHT-based search for block\n"); GSF_dht_lookup_ (pr); break; default: GNUNET_break (0); break; } } consider_forwarding (NULL, pr, result); } /** * Handle START_SEARCH-message (search request from client). * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_start_search (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GSF_PendingRequest *pr; int ret; pr = NULL; ret = GSF_local_client_start_search_handler_ (client, message, &pr); switch (ret) { case GNUNET_SYSERR: GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); break; case GNUNET_NO: GNUNET_SERVER_receive_done (client, GNUNET_OK); break; case GNUNET_YES: GSF_pending_request_get_data_ (pr)->has_started = GNUNET_YES; GSF_local_lookup_ (pr, &start_p2p_processing, client); break; default: GNUNET_assert (0); } } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GSF_mesh_stop_client (); GSF_mesh_stop_server (); if (NULL != GSF_core) { GNUNET_CORE_disconnect (GSF_core); GSF_core = NULL; } if (NULL != GSF_ats) { GNUNET_ATS_performance_done (GSF_ats); GSF_ats = NULL; } GSF_put_done_ (); GSF_push_done_ (); GSF_pending_request_done_ (); GSF_plan_done (); GSF_connected_peer_done_ (); GNUNET_DATASTORE_disconnect (GSF_dsh, GNUNET_NO); GSF_dsh = NULL; GNUNET_DHT_disconnect (GSF_dht); GSF_dht = NULL; GNUNET_BLOCK_context_destroy (GSF_block_ctx); GSF_block_ctx = NULL; GNUNET_CONFIGURATION_destroy (block_cfg); block_cfg = NULL; GNUNET_STATISTICS_destroy (GSF_stats, GNUNET_NO); GSF_stats = NULL; if (GNUNET_SCHEDULER_NO_TASK != cover_age_task) { GNUNET_SCHEDULER_cancel (cover_age_task); cover_age_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_FS_indexing_done (); GNUNET_LOAD_value_free (datastore_get_load); datastore_get_load = NULL; GNUNET_LOAD_value_free (GSF_rt_entry_lifetime); GSF_rt_entry_lifetime = NULL; } /** * Function called for each pending request whenever a new * peer connects, giving us a chance to decide about submitting * the existing request to the new peer. * * @param cls the 'struct GSF_ConnectedPeer' of the new peer * @param key query for the request * @param pr handle to the pending request * @return GNUNET_YES to continue to iterate */ static int consider_peer_for_forwarding (void *cls, const struct GNUNET_HashCode * key, struct GSF_PendingRequest *pr) { struct GSF_ConnectedPeer *cp = cls; struct GNUNET_PeerIdentity pid; GSF_connected_peer_get_identity_ (cp, &pid); if (GNUNET_YES != GSF_pending_request_test_target_ (pr, &pid)) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Loopback routes suppressed"), 1, GNUNET_NO); return GNUNET_YES; } GSF_plan_add_ (cp, pr); return GNUNET_YES; } /** * Method called whenever a given peer connects. * * @param cls closure, not used * @param peer peer identity this notification is about */ static void peer_connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer) { struct GSF_ConnectedPeer *cp; if (0 == memcmp (&my_id, peer, sizeof (struct GNUNET_PeerIdentity))) return; cp = GSF_peer_connect_handler_ (peer); if (NULL == cp) return; GSF_iterate_pending_requests_ (&consider_peer_for_forwarding, cp); } /** * Function called after GNUNET_CORE_connect has succeeded * (or failed for good). Note that the private key of the * peer is intentionally not exposed here; if you need it, * your process should try to read the private key file * directly (which should work if you are authorized...). * * @param cls closure * @param my_identity ID of this peer, NULL if we failed */ static void peer_init_handler (void *cls, const struct GNUNET_PeerIdentity *my_identity) { my_id = *my_identity; } /** * Process fs requests. * * @param server the initialized server * @param c configuration to use */ static int main_init (struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_CORE_MessageHandler no_p2p_handlers[] = { {NULL, 0, 0} }; static const struct GNUNET_CORE_MessageHandler p2p_handlers[] = { {&handle_p2p_get, GNUNET_MESSAGE_TYPE_FS_GET, 0}, {&handle_p2p_put, GNUNET_MESSAGE_TYPE_FS_PUT, 0}, {&GSF_handle_p2p_migration_stop_, GNUNET_MESSAGE_TYPE_FS_MIGRATION_STOP, sizeof (struct MigrationStopMessage)}, {NULL, 0, 0} }; static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&GNUNET_FS_handle_index_start, NULL, GNUNET_MESSAGE_TYPE_FS_INDEX_START, 0}, {&GNUNET_FS_handle_index_list_get, NULL, GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_GET, sizeof (struct GNUNET_MessageHeader)}, {&GNUNET_FS_handle_unindex, NULL, GNUNET_MESSAGE_TYPE_FS_UNINDEX, sizeof (struct UnindexMessage)}, {&handle_start_search, NULL, GNUNET_MESSAGE_TYPE_FS_START_SEARCH, 0}, {NULL, NULL, 0, 0} }; int anon_p2p_off; /* this option is really only for testcases that need to disable _anonymous_ file-sharing for some reason */ anon_p2p_off = (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (GSF_cfg, "fs", "DISABLE_ANON_TRANSFER")); GSF_core = GNUNET_CORE_connect (GSF_cfg, NULL, &peer_init_handler, &peer_connect_handler, &GSF_peer_disconnect_handler_, NULL, GNUNET_NO, NULL, GNUNET_NO, (GNUNET_YES == anon_p2p_off) ? no_p2p_handlers : p2p_handlers); if (NULL == GSF_core) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to `%s' service.\n"), "core"); return GNUNET_SYSERR; } GNUNET_SERVER_disconnect_notify (server, &GSF_client_disconnect_handler_, NULL); GNUNET_SERVER_add_handlers (server, handlers); cover_age_task = GNUNET_SCHEDULER_add_delayed (COVER_AGE_FREQUENCY, &age_cover_counters, NULL); datastore_get_load = GNUNET_LOAD_value_init (DATASTORE_LOAD_AUTODECLINE); GSF_mesh_start_server (); GSF_mesh_start_client (); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); return GNUNET_OK; } /** * Process fs requests. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { unsigned long long dqs; GSF_cfg = cfg; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size (GSF_cfg, "fs", "DATASTORE_QUEUE_SIZE", &dqs)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, "fs", "DATASTORE_QUEUE_SIZE"); dqs = 1024; } GSF_datastore_queue_size = (unsigned int) dqs; GSF_enable_randomized_delays = GNUNET_CONFIGURATION_get_value_yesno (cfg, "fs", "DELAY"); GSF_dsh = GNUNET_DATASTORE_connect (cfg); if (NULL == GSF_dsh) { GNUNET_SCHEDULER_shutdown (); return; } GSF_rt_entry_lifetime = GNUNET_LOAD_value_init (GNUNET_TIME_UNIT_FOREVER_REL); GSF_stats = GNUNET_STATISTICS_create ("fs", cfg); block_cfg = GNUNET_CONFIGURATION_create (); GSF_block_ctx = GNUNET_BLOCK_context_create (block_cfg); GNUNET_assert (NULL != GSF_block_ctx); GSF_dht = GNUNET_DHT_connect (cfg, FS_DHT_HT_SIZE); GSF_plan_init (); GSF_pending_request_init_ (); GSF_connected_peer_init_ (); GSF_ats = GNUNET_ATS_performance_init (GSF_cfg, &update_latencies, NULL); GSF_push_init_ (); GSF_put_init_ (); if ((GNUNET_OK != GNUNET_FS_indexing_init (cfg, GSF_dsh)) || (GNUNET_OK != main_init (server, cfg))) { GNUNET_SCHEDULER_shutdown (); shutdown_task (NULL, NULL); return; } } /** * The main function for the fs service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "fs", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-fs.c */ gnunet-0.10.1/src/fs/test_fs_unindex.c0000644000175000017500000001733412226006757014575 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_unindex.c * @brief simple testcase for simple publish + unindex operation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "gnunet_testing_lib.h" /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 2) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static struct GNUNET_TIME_Absolute start; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_UnindexContext *unindex; static struct GNUNET_FS_PublishContext *publish; static char *fn; static void abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_publish_stop (publish); publish = NULL; } static void abort_unindex_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_unindex_stop (unindex); unindex = NULL; GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); fn = NULL; } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_PROGRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: printf ("Publishing complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); start = GNUNET_TIME_absolute_get (); unindex = GNUNET_FS_unindex_start (fs, fn, "unindex"); GNUNET_assert (unindex != NULL); break; case GNUNET_FS_STATUS_UNINDEX_COMPLETED: printf ("Unindex complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); GNUNET_SCHEDULER_add_continuation (&abort_unindex_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_UNINDEX_PROGRESS: GNUNET_assert (unindex == event->value.unindex.uc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unindex is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.unindex.completed, (unsigned long long) event->value.unindex.size, event->value.unindex.specifics.progress.depth, (unsigned long long) event->value.unindex.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); GNUNET_break (0); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_UNINDEX_ERROR: FPRINTF (stderr, "Error unindexing file: %s\n", event->value.unindex.specifics.error.message); GNUNET_SCHEDULER_add_continuation (&abort_unindex_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_START: GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); GNUNET_assert (NULL == event->value.publish.pctx); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_assert (publish == event->value.publish.pc); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (1 == event->value.publish.anonymity); GNUNET_FS_stop (fs); fs = NULL; break; case GNUNET_FS_STATUS_UNINDEX_START: GNUNET_assert (unindex == NULL); GNUNET_assert (0 == strcmp ("unindex", event->value.unindex.cctx)); GNUNET_assert (0 == strcmp (fn, event->value.unindex.filename)); GNUNET_assert (FILESIZE == event->value.unindex.size); GNUNET_assert (0 == event->value.unindex.completed); break; case GNUNET_FS_STATUS_UNINDEX_STOPPED: GNUNET_assert (unindex == event->value.unindex.uc); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; default: printf ("Unexpected event: %d\n", event->status); break; } return NULL; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar", }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi; size_t i; struct GNUNET_FS_BlockOptions bo; fn = GNUNET_DISK_mktemp ("gnunet-unindex-test-dst"); fs = GNUNET_FS_start (cfg, "test-fs-unindex", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi = GNUNET_FS_file_information_create_from_file (fs, "publish-context", fn, kuri, meta, GNUNET_YES, &bo); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fi); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-unindex", "test_fs_unindex_data.conf", &run, NULL)) return 1; return 0; } /* end of test_fs_unindex.c */ gnunet-0.10.1/src/fs/test_gnunet_fs_rec.py.in0000644000175000017500000001144012221077151016046 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Testcase for file-sharing command-line tools (recursive publishing & download) import sys import os import subprocess import re import shutil import tarfile import filecmp srcdir = "../.." gnunet_pyexpect_dir = os.path.join (srcdir, "contrib") if gnunet_pyexpect_dir not in sys.path: sys.path.append (gnunet_pyexpect_dir) from gnunet_pyexpect import pexpect from pydiffer import dcdiff if os.name == 'posix': download = './gnunet-download' gnunetarm = 'gnunet-arm' publish = './gnunet-publish' unindex = './gnunet-unindex' search = './gnunet-search' directory = './gnunet-directory' elif os.name == 'nt': download = './gnunet-download.exe' gnunetarm = 'gnunet-arm.exe' publish = './gnunet-publish.exe' unindex = './gnunet-unindex.exe' search = './gnunet-search.exe' directory = './gnunet-directory.exe' if os.name == "nt": shutil.rmtree (os.path.join (os.getenv ("TEMP"), "gnunet-test-fs-py-rec"), True) else: shutil.rmtree ("/tmp/gnunet-test-fs-py-rec", True) arm = subprocess.Popen ([gnunetarm, '-sq', '-c', 'test_gnunet_fs_rec_data.conf']) arm.communicate () # pray that `tar' is in PATH tar = tarfile.open ('test_gnunet_fs_rec_data.tgz') tar.extractall () # first, basic publish-search-download run try: pub = pexpect () pub.spawn (None, [publish, '-c', 'test_gnunet_fs_rec_data.conf', '-d', '-k', 'testdir', 'dir/'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # Can't say much for publishing, except that the last one is the toplevel directory pub.expect ("stdout", re.compile (r"Publishing `.+' done\.\r?\n")) pub.expect ("stdout", re.compile (r"URI is `gnunet://fs/chk/[A-Z0-9]{103}\.[A-Z0-9]{103}\.\d+'\.\r?\n")) pub.expect ("stdout", re.compile (r"Publishing `.+' done\.\r?\n")) pub.expect ("stdout", re.compile (r"URI is `gnunet://fs/chk/[A-Z0-9]{103}\.[A-Z0-9]{103}\.\d+'\.\r?\n")) pub.expect ("stdout", re.compile (r"Publishing `.+' done\.\r?\n")) pub.expect ("stdout", re.compile (r"URI is `gnunet://fs/chk/[A-Z0-9]{103}\.[A-Z0-9]{103}\.\d+'\.\r?\n")) pub.expect ("stdout", re.compile (r"Publishing `.+' done\.\r?\n")) pub.expect ("stdout", re.compile (r"URI is `gnunet://fs/chk/[A-Z0-9]{103}\.[A-Z0-9]{103}\.\d+'\.\r?\n")) pub.expect ("stdout", re.compile (r"Publishing `.+' done\.\r?\n")) pub.expect ("stdout", re.compile (r"URI is `gnunet://fs/chk/[A-Z0-9]{103}\.[A-Z0-9]{103}\.\d+'\.\r?\n")) pub.expect ("stdout", re.compile (r"Publishing `.+' done\.\r?\n")) pub.expect ("stdout", re.compile (r"URI is `gnunet://fs/chk/[A-Z0-9]{103}\.[A-Z0-9]{103}\.\d+'\.\r?\n")) pub.expect ("stdout", re.compile (r"Publishing `.+[\\/]dir[\\/]' done\.\r?\n")) m = pub.expect ("stdout", re.compile (r".+\r?\n")) if not m: sys.exit (3) output = m.string url = output[output.find ("`")+1:output.find("'")] down = pexpect () down.spawn (None, [download, '-c', 'test_gnunet_fs_rec_data.conf', '-R', '-o', 'rdir.gnd', url], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) down.expect ("stdout", re.compile (r"Downloading `rdir.gnd' done (.*).\r?\n")) d = pexpect () d.spawn (None, [directory, '-c', 'test_gnunet_fs_rec_data.conf', 'rdir/a.gnd'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) d.expect ("stdout", re.compile (r"Directory `a/' meta data:\r?\n")) d.expect ("stdout", re.compile (r"Directory `a/' contents:\r?\n")) d.expect ("stdout", re.compile (r"COPYING (.*)\r?\n")) d.expect ("stdout", re.compile (r"INSTALL (.*)\r?\n")) os.remove ("rdir/b.gnd") os.remove ("rdir/a.gnd") diff = dcdiff ('dir', 'rdir') if len (diff) != 0: raise Exception ("Unexpected difference between source directory and downloaded result:\n{}".format (diff)) finally: arm = subprocess.Popen ([gnunetarm, '-eq', '-c', 'test_gnunet_fs_rec_data.conf']) arm.communicate () if os.name == "nt": shutil.rmtree (os.path.join (os.getenv ("TEMP"), "gnunet-test-fs-py-rec"), True) else: shutil.rmtree ("/tmp/gnunet-test-fs-py-rec", True) shutil.rmtree ("dir", True) shutil.rmtree ("rdir", True) shutil.rmtree ("rdir.gnd", True) gnunet-0.10.1/src/fs/fs_file_information.c0000644000175000017500000003772712255010511015401 00000000000000/* This file is part of GNUnet. (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_file_information.c * @brief Manage information for publishing directory hierarchies * @author Christian Grothoff */ #include "platform.h" #include #include "gnunet_fs_service.h" #include "fs_api.h" #include "fs_tree.h" /** * Obtain the name under which this file information * structure is stored on disk. Only works for top-level * file information structures. * * @param s structure to get the filename for * @return NULL on error, otherwise filename that * can be used to read this fi-struct from disk. */ const char * GNUNET_FS_file_information_get_id (struct GNUNET_FS_FileInformation *s) { if (NULL != s->dir) return NULL; return s->serialization; } /** * Obtain the filename from the file information structure. * * @param s structure to get the filename for * @return "filename" field of the structure (can be NULL) */ const char * GNUNET_FS_file_information_get_filename (struct GNUNET_FS_FileInformation *s) { return s->filename; } /** * Set the filename in the file information structure. * If filename was already set, frees it before setting the new one. * Makes a copy of the argument. * * @param s structure to get the filename for * @param filename filename to set */ void GNUNET_FS_file_information_set_filename (struct GNUNET_FS_FileInformation *s, const char *filename) { GNUNET_free_non_null (s->filename); if (filename) s->filename = GNUNET_strdup (filename); else s->filename = NULL; } /** * Create an entry for a file in a publish-structure. * * @param h handle to the file sharing subsystem * @param client_info initial value for the client-info value for this entry * @param filename name of the file or directory to publish * @param keywords under which keywords should this file be available * directly; can be NULL * @param meta metadata for the file * @param do_index #GNUNET_YES for index, #GNUNET_NO for insertion, * #GNUNET_SYSERR for simulation * @param bo block options * @return publish structure entry for the file */ struct GNUNET_FS_FileInformation * GNUNET_FS_file_information_create_from_file (struct GNUNET_FS_Handle *h, void *client_info, const char *filename, const struct GNUNET_FS_Uri *keywords, const struct GNUNET_CONTAINER_MetaData *meta, int do_index, const struct GNUNET_FS_BlockOptions *bo) { struct FileInfo *fi; uint64_t fsize; struct GNUNET_FS_FileInformation *ret; const char *fn; const char *ss; #if WINDOWS char fn_conv[MAX_PATH]; #endif /* FIXME: should include_symbolic_links be GNUNET_NO or GNUNET_YES here? */ if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fsize, GNUNET_NO, GNUNET_YES)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename); return NULL; } fi = GNUNET_FS_make_file_reader_context_ (filename); if (NULL == fi) { GNUNET_break (0); return NULL; } ret = GNUNET_FS_file_information_create_from_reader (h, client_info, fsize, &GNUNET_FS_data_reader_file_, fi, keywords, meta, do_index, bo); if (ret == NULL) return NULL; ret->h = h; ret->filename = GNUNET_strdup (filename); #if !WINDOWS fn = filename; #else plibc_conv_to_win_path (filename, fn_conv); fn = fn_conv; #endif while (NULL != (ss = strstr (fn, DIR_SEPARATOR_STR))) fn = ss + 1; /* FIXME: If we assume that on other platforms CRT is UTF-8-aware, then * this should be changed to EXTRACTOR_METAFORMAT_UTF8 */ #if !WINDOWS GNUNET_CONTAINER_meta_data_insert (ret->meta, "", EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, EXTRACTOR_METAFORMAT_C_STRING, "text/plain", fn, strlen (fn) + 1); #else GNUNET_CONTAINER_meta_data_insert (ret->meta, "", EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", fn, strlen (fn) + 1); #endif return ret; } /** * Create an entry for a file in a publish-structure. * * @param h handle to the file sharing subsystem * @param client_info initial value for the client-info value for this entry * @param length length of the file * @param data data for the file (should not be used afterwards by * the caller; callee will "free") * @param keywords under which keywords should this file be available * directly; can be NULL * @param meta metadata for the file * @param do_index GNUNET_YES for index, GNUNET_NO for insertion, * GNUNET_SYSERR for simulation * @param bo block options * @return publish structure entry for the file */ struct GNUNET_FS_FileInformation * GNUNET_FS_file_information_create_from_data (struct GNUNET_FS_Handle *h, void *client_info, uint64_t length, void *data, const struct GNUNET_FS_Uri *keywords, const struct GNUNET_CONTAINER_MetaData *meta, int do_index, const struct GNUNET_FS_BlockOptions *bo) { if (GNUNET_YES == do_index) { GNUNET_break (0); return NULL; } return GNUNET_FS_file_information_create_from_reader (h, client_info, length, &GNUNET_FS_data_reader_copy_, data, keywords, meta, do_index, bo); } /** * Create an entry for a file in a publish-structure. * * @param h handle to the file sharing subsystem * @param client_info initial value for the client-info value for this entry * @param length length of the file * @param reader function that can be used to obtain the data for the file * @param reader_cls closure for "reader" * @param keywords under which keywords should this file be available * directly; can be NULL * @param meta metadata for the file * @param do_index #GNUNET_YES for index, #GNUNET_NO for insertion, * #GNUNET_SYSERR for simulation * @param bo block options * @return publish structure entry for the file */ struct GNUNET_FS_FileInformation * GNUNET_FS_file_information_create_from_reader (struct GNUNET_FS_Handle *h, void *client_info, uint64_t length, GNUNET_FS_DataReader reader, void *reader_cls, const struct GNUNET_FS_Uri *keywords, const struct GNUNET_CONTAINER_MetaData *meta, int do_index, const struct GNUNET_FS_BlockOptions *bo) { struct GNUNET_FS_FileInformation *ret; if ((GNUNET_YES == do_index) && (reader != &GNUNET_FS_data_reader_file_)) { GNUNET_break (0); return NULL; } ret = GNUNET_new (struct GNUNET_FS_FileInformation); ret->h = h; ret->client_info = client_info; ret->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); if (ret->meta == NULL) ret->meta = GNUNET_CONTAINER_meta_data_create (); ret->keywords = (keywords == NULL) ? NULL : GNUNET_FS_uri_dup (keywords); ret->data.file.reader = reader; ret->data.file.reader_cls = reader_cls; ret->data.file.do_index = do_index; ret->data.file.file_size = length; ret->bo = *bo; return ret; } /** * Test if a given entry represents a directory. * * @param ent check if this FI represents a directory * @return #GNUNET_YES if so, #GNUNET_NO if not */ int GNUNET_FS_file_information_is_directory (const struct GNUNET_FS_FileInformation *ent) { return ent->is_directory; } /** * Create an entry for an empty directory in a publish-structure. * * @param h handle to the file sharing subsystem * @param client_info initial value for the client-info value for this entry * @param meta metadata for the directory * @param keywords under which keywords should this directory be available * directly; can be NULL * @param bo block options * @param filename name of the directory; can be NULL * @return publish structure entry for the directory , NULL on error */ struct GNUNET_FS_FileInformation * GNUNET_FS_file_information_create_empty_directory (struct GNUNET_FS_Handle *h, void *client_info, const struct GNUNET_FS_Uri *keywords, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_BlockOptions *bo, const char *filename) { struct GNUNET_FS_FileInformation *ret; ret = GNUNET_new (struct GNUNET_FS_FileInformation); ret->h = h; ret->client_info = client_info; ret->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); ret->keywords = GNUNET_FS_uri_dup (keywords); ret->bo = *bo; ret->is_directory = GNUNET_YES; if (filename != NULL) ret->filename = GNUNET_strdup (filename); return ret; } /** * Add an entry to a directory in a publish-structure. Clients * should never modify publish structures that were passed to * #GNUNET_FS_publish_start already. * * @param dir the directory * @param ent the entry to add; the entry must not have been * added to any other directory at this point and * must not include @a dir in its structure * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_FS_file_information_add (struct GNUNET_FS_FileInformation *dir, struct GNUNET_FS_FileInformation *ent) { if ((ent->dir != NULL) || (ent->next != NULL) || (dir->is_directory != GNUNET_YES)) { GNUNET_break (0); return GNUNET_SYSERR; } ent->dir = dir; ent->next = dir->data.dir.entries; dir->data.dir.entries = ent; dir->data.dir.dir_size = 0; return GNUNET_OK; } /** * Inspect a file or directory in a publish-structure. Clients * should never modify publish structures that were passed to * #GNUNET_FS_publish_start already. When called on a directory, * this function will FIRST call @a proc with information about * the directory itself and then for each of the files in the * directory (but not for files in subdirectories). When called * on a file, @a proc will be called exactly once (with information * about the specific file). * * @param dir the directory * @param proc function to call on each entry * @param proc_cls closure for @a proc */ void GNUNET_FS_file_information_inspect (struct GNUNET_FS_FileInformation *dir, GNUNET_FS_FileInformationProcessor proc, void *proc_cls) { struct GNUNET_FS_FileInformation *pos; int no; no = GNUNET_NO; if (GNUNET_OK != proc (proc_cls, dir, (dir->is_directory == GNUNET_YES) ? dir->data.dir.dir_size : dir->data. file.file_size, dir->meta, &dir->keywords, &dir->bo, (dir->is_directory == GNUNET_YES) ? &no : &dir->data.file.do_index, &dir->client_info)) return; if (dir->is_directory != GNUNET_YES) return; pos = dir->data.dir.entries; while (pos != NULL) { no = GNUNET_NO; if (GNUNET_OK != proc (proc_cls, pos, (pos->is_directory == GNUNET_YES) ? pos->data.dir.dir_size : pos->data. file.file_size, pos->meta, &pos->keywords, &pos->bo, (pos->is_directory == GNUNET_YES) ? &no : &pos->data.file.do_index, &pos->client_info)) break; pos = pos->next; } } /** * Destroy publish-structure. Clients should never destroy publish * structures that were passed to #GNUNET_FS_publish_start already. * * @param fi structure to destroy * @param cleaner function to call on each entry in the structure * (useful to clean up client_info); can be NULL; return * values are ignored * @param cleaner_cls closure for @a cleaner */ void GNUNET_FS_file_information_destroy (struct GNUNET_FS_FileInformation *fi, GNUNET_FS_FileInformationProcessor cleaner, void *cleaner_cls) { struct GNUNET_FS_FileInformation *pos; int no; no = GNUNET_NO; if (GNUNET_YES == fi->is_directory) { /* clean up directory */ while (NULL != (pos = fi->data.dir.entries)) { fi->data.dir.entries = pos->next; GNUNET_FS_file_information_destroy (pos, cleaner, cleaner_cls); } /* clean up client-info */ if (NULL != cleaner) cleaner (cleaner_cls, fi, fi->data.dir.dir_size, fi->meta, &fi->keywords, &fi->bo, &no, &fi->client_info); GNUNET_free_non_null (fi->data.dir.dir_data); } else { /* call clean-up function of the reader */ if (NULL != fi->data.file.reader) { (void) fi->data.file.reader (fi->data.file.reader_cls, 0, 0, NULL, NULL); fi->data.file.reader = NULL; } /* clean up client-info */ if (NULL != cleaner) cleaner (cleaner_cls, fi, fi->data.file.file_size, fi->meta, &fi->keywords, &fi->bo, &fi->data.file.do_index, &fi->client_info); } GNUNET_free_non_null (fi->filename); GNUNET_free_non_null (fi->emsg); GNUNET_free_non_null (fi->chk_uri); /* clean up serialization */ if ((NULL != fi->serialization) && (0 != UNLINK (fi->serialization))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fi->serialization); if (NULL != fi->keywords) GNUNET_FS_uri_destroy (fi->keywords); if (NULL != fi->meta) GNUNET_CONTAINER_meta_data_destroy (fi->meta); GNUNET_free_non_null (fi->serialization); if (NULL != fi->te) { GNUNET_FS_tree_encoder_finish (fi->te, NULL); fi->te = NULL; } GNUNET_free (fi); } /* end of fs_file_information.c */ gnunet-0.10.1/src/fs/test_fs_data.conf0000644000175000017500000000016012225230043014506 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-data/ [fs] ACTIVEMIGRATION = NO gnunet-0.10.1/src/fs/fs_test_lib.c0000644000175000017500000004437612255010511013660 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_test_lib.c * @brief library routines for testing FS publishing and downloading; * this code is limited to flat files * and no keywords (those functions can be tested with * single-peer setups; this is for testing routing). * @author Christian Grothoff */ #include "platform.h" #include "fs_api.h" #include "fs_test_lib.h" #define CONTENT_LIFETIME GNUNET_TIME_UNIT_HOURS /** * Handle for a publishing operation started for testing FS. */ struct TestPublishOperation { /** * Handle for the operation to connect to the peer's 'fs' service. */ struct GNUNET_TESTBED_Operation *fs_op; /** * Handle to the file sharing context using this daemon. */ struct GNUNET_FS_Handle *fs; /** * Function to call when upload is done. */ GNUNET_FS_TEST_UriContinuation publish_cont; /** * Closure for publish_cont. */ void *publish_cont_cls; /** * Task to abort publishing (timeout). */ GNUNET_SCHEDULER_TaskIdentifier publish_timeout_task; /** * Seed for file generation. */ uint32_t publish_seed; /** * Context for current publishing operation. */ struct GNUNET_FS_PublishContext *publish_context; /** * Result URI. */ struct GNUNET_FS_Uri *publish_uri; /** * Name of the temporary file used, or NULL for none. */ char *publish_tmp_file; /** * Size of the file. */ uint64_t size; /** * Anonymity level used. */ uint32_t anonymity; /** * Verbosity level of the current operation. */ unsigned int verbose; /** * Are we testing indexing? (YES: index, NO: insert, SYSERR: simulate) */ int do_index; }; /** * Handle for a download operation started for testing FS. */ struct TestDownloadOperation { /** * Handle for the operation to connect to the peer's 'fs' service. */ struct GNUNET_TESTBED_Operation *fs_op; /** * Handle to the file sharing context using this daemon. */ struct GNUNET_FS_Handle *fs; /** * Handle to the daemon via testing. */ struct GNUNET_TESTING_Daemon *daemon; /** * Function to call when download is done. */ GNUNET_SCHEDULER_Task download_cont; /** * Closure for download_cont. */ void *download_cont_cls; /** * URI to download. */ struct GNUNET_FS_Uri *uri; /** * Task to abort downloading (timeout). */ GNUNET_SCHEDULER_TaskIdentifier download_timeout_task; /** * Context for current download operation. */ struct GNUNET_FS_DownloadContext *download_context; /** * Size of the file. */ uint64_t size; /** * Anonymity level used. */ uint32_t anonymity; /** * Seed for download verification. */ uint32_t download_seed; /** * Verbosity level of the current operation. */ unsigned int verbose; }; /** * Task scheduled to report on the completion of our publish operation. * * @param cls the publish operation context * @param tc scheduler context (unused) */ static void report_uri (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestPublishOperation *po = cls; GNUNET_FS_publish_stop (po->publish_context); GNUNET_TESTBED_operation_done (po->fs_op); po->publish_cont (po->publish_cont_cls, po->publish_uri, (GNUNET_YES == po->do_index) ? po->publish_tmp_file : NULL); GNUNET_FS_uri_destroy (po->publish_uri); if ( (GNUNET_YES != po->do_index) && (NULL != po->publish_tmp_file) ) (void) GNUNET_DISK_directory_remove (po->publish_tmp_file); GNUNET_free_non_null (po->publish_tmp_file); GNUNET_free (po); } /** * Task scheduled to run when publish operation times out. * * @param cls the publish operation context * @param tc scheduler context (unused) */ static void publish_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestPublishOperation *po = cls; po->publish_timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout while trying to publish data\n"); GNUNET_TESTBED_operation_done (po->fs_op); GNUNET_FS_publish_stop (po->publish_context); po->publish_cont (po->publish_cont_cls, NULL, NULL); (void) GNUNET_DISK_directory_remove (po->publish_tmp_file); GNUNET_free_non_null (po->publish_tmp_file); GNUNET_free (po); } /** * Progress callback for file-sharing events while publishing. * * @param cls the publish operation context * @param info information about the event */ static void * publish_progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { struct TestPublishOperation *po = cls; switch (info->status) { case GNUNET_FS_STATUS_PUBLISH_COMPLETED: GNUNET_SCHEDULER_cancel (po->publish_timeout_task); po->publish_timeout_task = GNUNET_SCHEDULER_NO_TASK; po->publish_uri = GNUNET_FS_uri_dup (info->value.publish.specifics.completed.chk_uri); GNUNET_SCHEDULER_add_continuation (&report_uri, po, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS: if (po->verbose) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Publishing at %llu/%llu bytes\n", (unsigned long long) info->value.publish.completed, (unsigned long long) info->value.publish.size); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: if (po->verbose) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Download at %llu/%llu bytes\n", (unsigned long long) info->value.download.completed, (unsigned long long) info->value.download.size); break; default: break; } return NULL; } /** * Generate test data for publishing test. * * @param cls pointer to uint32_t with publishing seed * @param offset offset to generate data for * @param max maximum number of bytes to generate * @param buf where to write generated data * @param emsg where to store error message (unused) * @return number of bytes written to buf */ static size_t file_generator (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) { uint32_t *publish_seed = cls; uint64_t pos; uint8_t *cbuf = buf; int mod; if (emsg != NULL) *emsg = NULL; if (buf == NULL) return 0; for (pos = 0; pos < 8; pos++) cbuf[pos] = (uint8_t) (offset >> pos * 8); for (pos = 8; pos < max; pos++) { mod = (255 - (offset / 1024 / 32)); if (mod == 0) mod = 1; cbuf[pos] = (uint8_t) ((offset * (*publish_seed)) % mod); } return max; } /** * Connect adapter for publishing operation. * * @param cls the 'struct TestPublishOperation' * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * publish_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TestPublishOperation *po = cls; return GNUNET_FS_start (cfg, "fs-test-publish", &publish_progress_cb, po, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); } /** * Adapter function called to destroy connection to file-sharing service. * * @param cls the 'struct GNUNET_FS_Handle' * @param op_result unused (different for publish/download!) */ static void fs_disconnect_adapter (void *cls, void *op_result) { struct GNUNET_FS_Handle *fs = op_result; GNUNET_FS_stop (fs); } /** * Callback to be called when testbed has connected to the fs service * * @param cls the 'struct TestPublishOperation' * @param op the operation that has been finished * @param ca_result the 'struct GNUNET_FS_Handle ' (NULL on error) * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void publish_fs_connect_complete_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct TestPublishOperation *po = cls; struct GNUNET_FS_FileInformation *fi; struct GNUNET_DISK_FileHandle *fh; char *em; uint64_t off; char buf[DBLOCK_SIZE]; size_t bsize; struct GNUNET_FS_BlockOptions bo; if (NULL == ca_result) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to FS for publishing: %s\n", emsg); po->publish_cont (po->publish_cont_cls, NULL, NULL); GNUNET_TESTBED_operation_done (po->fs_op); GNUNET_free (po); return; } po->fs = ca_result; bo.expiration_time = GNUNET_TIME_relative_to_absolute (CONTENT_LIFETIME); bo.anonymity_level = po->anonymity; bo.content_priority = 42; bo.replication_level = 1; if (GNUNET_YES == po->do_index) { po->publish_tmp_file = GNUNET_DISK_mktemp ("fs-test-publish-index"); GNUNET_assert (po->publish_tmp_file != NULL); fh = GNUNET_DISK_file_open (po->publish_tmp_file, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); GNUNET_assert (NULL != fh); off = 0; while (off < po->size) { bsize = GNUNET_MIN (sizeof (buf), po->size - off); emsg = NULL; GNUNET_assert (bsize == file_generator (&po->publish_seed, off, bsize, buf, &em)); GNUNET_assert (em == NULL); GNUNET_assert (bsize == GNUNET_DISK_file_write (fh, buf, bsize)); off += bsize; } GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); fi = GNUNET_FS_file_information_create_from_file (po->fs, po, po->publish_tmp_file, NULL, NULL, po->do_index, &bo); GNUNET_assert (NULL != fi); } else { fi = GNUNET_FS_file_information_create_from_reader (po->fs, po, po->size, &file_generator, &po->publish_seed, NULL, NULL, po->do_index, &bo); GNUNET_assert (NULL != fi); } po->publish_context = GNUNET_FS_publish_start (po->fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); } /** * Publish a file at the given peer. * * @param peer where to publish * @param timeout if this operation cannot be completed within the * given period, call the continuation with an error code * @param anonymity option for publication * @param do_index GNUNET_YES for index, GNUNET_NO for insertion, * GNUNET_SYSERR for simulation * @param size size of the file to publish * @param seed seed to use for file generation * @param verbose how verbose to be in reporting * @param cont function to call when done * @param cont_cls closure for cont */ void GNUNET_FS_TEST_publish (struct GNUNET_TESTBED_Peer *peer, struct GNUNET_TIME_Relative timeout, uint32_t anonymity, int do_index, uint64_t size, uint32_t seed, unsigned int verbose, GNUNET_FS_TEST_UriContinuation cont, void *cont_cls) { struct TestPublishOperation *po; po = GNUNET_new (struct TestPublishOperation); po->publish_cont = cont; po->publish_cont_cls = cont_cls; po->publish_seed = seed; po->anonymity = anonymity; po->size = size; po->verbose = verbose; po->do_index = do_index; po->fs_op = GNUNET_TESTBED_service_connect (po, peer, "fs", &publish_fs_connect_complete_cb, po, &publish_connect_adapter, &fs_disconnect_adapter, po); po->publish_timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &publish_timeout, po); } /* ************************** download ************************ */ /** * Task scheduled to run when download operation times out. * * @param cls the download operation context * @param tc scheduler context (unused) */ static void download_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestDownloadOperation *dop = cls; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout while trying to download file\n"); dop->download_timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_FS_download_stop (dop->download_context, GNUNET_YES); GNUNET_SCHEDULER_add_continuation (dop->download_cont, dop->download_cont_cls, GNUNET_SCHEDULER_REASON_TIMEOUT); GNUNET_TESTBED_operation_done (dop->fs_op); GNUNET_FS_uri_destroy (dop->uri); GNUNET_free (dop); } /** * Task scheduled to report on the completion of our download operation. * * @param cls the download operation context * @param tc scheduler context (unused) */ static void report_success (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestDownloadOperation *dop = cls; GNUNET_FS_download_stop (dop->download_context, GNUNET_YES); GNUNET_SCHEDULER_add_continuation (dop->download_cont, dop->download_cont_cls, GNUNET_SCHEDULER_REASON_PREREQ_DONE); GNUNET_TESTBED_operation_done (dop->fs_op); GNUNET_FS_uri_destroy (dop->uri); GNUNET_free (dop); } /** * Progress callback for file-sharing events while downloading. * * @param cls the download operation context * @param info information about the event */ static void * download_progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { struct TestDownloadOperation *dop = cls; switch (info->status) { case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: if (dop->verbose) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Download at %llu/%llu bytes\n", (unsigned long long) info->value.download.completed, (unsigned long long) info->value.download.size); break; case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: GNUNET_SCHEDULER_cancel (dop->download_timeout_task); dop->download_timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_SCHEDULER_add_continuation (&report_success, dop, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: break; /* FIXME: monitor data correctness during download progress */ /* FIXME: do performance reports given sufficient verbosity */ /* FIXME: advance timeout task to "immediate" on error */ default: break; } return NULL; } /** * Connect adapter for download operation. * * @param cls the 'struct TestDownloadOperation' * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * download_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TestPublishOperation *po = cls; return GNUNET_FS_start (cfg, "fs-test-download", &download_progress_cb, po, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); } /** * Callback to be called when testbed has connected to the fs service * * @param cls the 'struct TestPublishOperation' * @param op the operation that has been finished * @param ca_result the 'struct GNUNET_FS_Handle ' (NULL on error) * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void download_fs_connect_complete_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct TestDownloadOperation *dop = cls; dop->fs = ca_result; GNUNET_assert (NULL != dop->fs); dop->download_context = GNUNET_FS_download_start (dop->fs, dop->uri, NULL, NULL, NULL, 0, dop->size, dop->anonymity, GNUNET_FS_DOWNLOAD_OPTION_NONE, NULL, NULL); } /** * Perform test download. * * @param peer which peer to download from * @param timeout if this operation cannot be completed within the * given period, call the continuation with an error code * @param anonymity option for download * @param seed used for file validation * @param uri URI of file to download (CHK/LOC only) * @param verbose how verbose to be in reporting * @param cont function to call when done * @param cont_cls closure for cont */ void GNUNET_FS_TEST_download (struct GNUNET_TESTBED_Peer *peer, struct GNUNET_TIME_Relative timeout, uint32_t anonymity, uint32_t seed, const struct GNUNET_FS_Uri *uri, unsigned int verbose, GNUNET_SCHEDULER_Task cont, void *cont_cls) { struct TestDownloadOperation *dop; dop = GNUNET_new (struct TestDownloadOperation); dop->uri = GNUNET_FS_uri_dup (uri); dop->size = GNUNET_FS_uri_chk_get_file_size (uri); dop->verbose = verbose; dop->anonymity = anonymity; dop->download_cont = cont; dop->download_cont_cls = cont_cls; dop->download_seed = seed; dop->fs_op = GNUNET_TESTBED_service_connect (dop, peer, "fs", &download_fs_connect_complete_cb, dop, &download_connect_adapter, &fs_disconnect_adapter, dop); dop->download_timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &download_timeout, dop); } /* end of fs_test_lib.c */ gnunet-0.10.1/src/fs/test_fs_namespace.c0000644000175000017500000002206312225777502015054 00000000000000/* This file is part of GNUnet. (C) 2005-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_namespace.c * @brief Test for fs_namespace.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_fs_service.h" static struct GNUNET_CRYPTO_EcdsaPublicKey nsid; static struct GNUNET_FS_Uri *sks_expect_uri; static struct GNUNET_FS_Uri *ksk_expect_uri; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_SearchContext *sks_search; static struct GNUNET_FS_SearchContext *ksk_search; static GNUNET_SCHEDULER_TaskIdentifier kill_task; static int update_started; static int err; static void abort_ksk_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (ksk_search != NULL) { GNUNET_FS_search_stop (ksk_search); ksk_search = NULL; if (sks_search == NULL) { GNUNET_FS_stop (fs); if (GNUNET_SCHEDULER_NO_TASK != kill_task) GNUNET_SCHEDULER_cancel (kill_task); } } } static void abort_sks_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (sks_search == NULL) return; GNUNET_FS_search_stop (sks_search); sks_search = NULL; if (ksk_search == NULL) { GNUNET_FS_stop (fs); if (GNUNET_SCHEDULER_NO_TASK != kill_task) GNUNET_SCHEDULER_cancel (kill_task); } } static void do_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { err = 1; FPRINTF (stderr, "%s", "Operation timed out\n"); kill_task = GNUNET_SCHEDULER_NO_TASK; abort_sks_search_task (NULL, tc); abort_ksk_search_task (NULL, tc); } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { switch (event->status) { case GNUNET_FS_STATUS_SEARCH_RESULT: if (sks_search == event->value.search.sc) { if (!GNUNET_FS_uri_test_equal (sks_expect_uri, event->value.search.specifics.result.uri)) { FPRINTF (stderr, "%s", "Wrong result for sks search!\n"); err = 1; } /* give system 1ms to initiate update search! */ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &abort_sks_search_task, NULL); } else if (ksk_search == event->value.search.sc) { if (!GNUNET_FS_uri_test_equal (ksk_expect_uri, event->value.search.specifics.result.uri)) { FPRINTF (stderr, "%s", "Wrong result for ksk search!\n"); err = 1; } GNUNET_SCHEDULER_add_continuation (&abort_ksk_search_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } else { FPRINTF (stderr, "%s", "Unexpected search result received!\n"); GNUNET_break (0); } break; case GNUNET_FS_STATUS_SEARCH_ERROR: FPRINTF (stderr, "Error searching file: %s\n", event->value.search.specifics.error.message); if (sks_search == event->value.search.sc) GNUNET_SCHEDULER_add_continuation (&abort_sks_search_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); else if (ksk_search == event->value.search.sc) GNUNET_SCHEDULER_add_continuation (&abort_ksk_search_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); else GNUNET_break (0); break; case GNUNET_FS_STATUS_SEARCH_START: GNUNET_assert ((NULL == event->value.search.cctx) || (0 == strcmp ("sks_search", event->value.search.cctx)) || (0 == strcmp ("ksk_search", event->value.search.cctx))); if (NULL == event->value.search.cctx) { GNUNET_assert (0 == strcmp ("sks_search", event->value.search.pctx)); update_started = GNUNET_YES; } GNUNET_assert (1 == event->value.search.anonymity); break; case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: return NULL; case GNUNET_FS_STATUS_SEARCH_STOPPED: return NULL; default: FPRINTF (stderr, "Unexpected event: %d\n", event->status); break; } return event->value.search.cctx; } static void publish_cont (void *cls, const struct GNUNET_FS_Uri *ksk_uri, const char *emsg) { char *msg; struct GNUNET_FS_Uri *sks_uri; char sbuf[1024]; char buf[1024]; char *ret; if (NULL != emsg) { FPRINTF (stderr, "Error publishing: %s\n", emsg); err = 1; GNUNET_FS_stop (fs); return; } ret = GNUNET_STRINGS_data_to_string (&nsid, sizeof (nsid), buf, sizeof (buf)); GNUNET_assert (NULL != ret); ret[0] = '\0'; GNUNET_snprintf (sbuf, sizeof (sbuf), "gnunet://fs/sks/%s/this", buf); sks_uri = GNUNET_FS_uri_parse (sbuf, &msg); if (NULL == sks_uri) { FPRINTF (stderr, "failed to parse URI `%s': %s\n", sbuf, msg); err = 1; GNUNET_FS_stop (fs); GNUNET_free_non_null (msg); return; } ksk_search = GNUNET_FS_search_start (fs, ksk_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "ksk_search"); sks_search = GNUNET_FS_search_start (fs, sks_uri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "sks_search"); GNUNET_FS_uri_destroy (sks_uri); } static void sks_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *ksk_uri; char *msg; struct GNUNET_FS_BlockOptions bo; if (NULL == uri) { fprintf (stderr, "Error publishing: %s\n", emsg); err = 1; GNUNET_FS_stop (fs); return; } meta = GNUNET_CONTAINER_meta_data_create (); msg = NULL; ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/ns-search", &msg); GNUNET_assert (NULL == msg); ksk_expect_uri = GNUNET_FS_uri_dup (uri); bo.content_priority = 1; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); GNUNET_FS_publish_ksk (fs, ksk_uri, meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &publish_cont, NULL); GNUNET_FS_uri_destroy (ksk_uri); GNUNET_CONTAINER_meta_data_destroy (meta); } static void adv_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_CRYPTO_EcdsaPrivateKey *ns; struct GNUNET_FS_BlockOptions bo; if (NULL != emsg) { FPRINTF (stderr, "Error publishing: %s\n", emsg); err = 1; GNUNET_FS_stop (fs); return; } ns = GNUNET_CRYPTO_ecdsa_key_create (); meta = GNUNET_CONTAINER_meta_data_create (); sks_expect_uri = GNUNET_FS_uri_dup (uri); bo.content_priority = 1; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); GNUNET_CRYPTO_ecdsa_key_get_public (ns, &nsid); GNUNET_FS_publish_sks (fs, ns, "this", "next", meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &sks_cont, NULL); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_free (ns); } static void testNamespace () { struct GNUNET_CRYPTO_EcdsaPrivateKey *ns; struct GNUNET_FS_BlockOptions bo; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *ksk_uri; struct GNUNET_FS_Uri *sks_uri; ns = GNUNET_CRYPTO_ecdsa_key_create (); meta = GNUNET_CONTAINER_meta_data_create (); ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/testnsa", NULL); bo.content_priority = 1; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); sks_uri = GNUNET_FS_uri_sks_create (&nsid, "root"); GNUNET_FS_publish_ksk (fs, ksk_uri, meta, sks_uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &adv_cont, NULL); GNUNET_FS_uri_destroy (sks_uri); kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &do_timeout, NULL); GNUNET_FS_uri_destroy (ksk_uri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_free (ns); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { fs = GNUNET_FS_start (cfg, "test-fs-namespace", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); testNamespace (); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-namespace", "test_fs_namespace_data.conf", &run, NULL)) return 1; return err; } /* end of test_fs_namespace.c */ gnunet-0.10.1/src/fs/gnunet-helper-fs-publish.c0000644000175000017500000003505212255010511016201 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/fs/gnunet-helper-fs-publish.c * @brief Tool to help extract meta data asynchronously * @author Christian Grothoff * * This program will scan a directory for files with meta data * and report the results to stdout. */ #include "platform.h" #include "gnunet_fs_service.h" /** * A node of a directory tree. */ struct ScanTreeNode { /** * This is a doubly-linked list */ struct ScanTreeNode *next; /** * This is a doubly-linked list */ struct ScanTreeNode *prev; /** * Parent of this node, NULL for top-level entries. */ struct ScanTreeNode *parent; /** * This is a doubly-linked tree * NULL for files and empty directories */ struct ScanTreeNode *children_head; /** * This is a doubly-linked tree * NULL for files and empty directories */ struct ScanTreeNode *children_tail; /** * Name of the file/directory */ char *filename; /** * Size of the file (if it is a file), in bytes. * At the moment it is set to 0 for directories. */ uint64_t file_size; /** * #GNUNET_YES if this is a directory */ int is_directory; }; /** * List of libextractor plugins to use for extracting. */ static struct EXTRACTOR_PluginList *plugins; /** * File descriptor we use for IPC with the parent. */ static int output_stream; /** * Add meta data that libextractor finds to our meta data * container. * * @param cls closure, our meta data container * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_len number of bytes in @a data * @return always 0 to continue extracting */ static int add_to_md (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len) { struct GNUNET_CONTAINER_MetaData *md = cls; if ( ((EXTRACTOR_METAFORMAT_UTF8 == format) || (EXTRACTOR_METAFORMAT_C_STRING == format)) && ('\0' != data[data_len - 1]) ) { char zdata[data_len + 1]; memcpy (zdata, data, data_len); zdata[data_len] = '\0'; (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format, data_mime_type, zdata, data_len + 1); } else { (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format, data_mime_type, data, data_len); } return 0; } /** * Free memory of the @a tree structure * * @param tree tree to free */ static void free_tree (struct ScanTreeNode *tree) { struct ScanTreeNode *pos; while (NULL != (pos = tree->children_head)) free_tree (pos); if (NULL != tree->parent) GNUNET_CONTAINER_DLL_remove (tree->parent->children_head, tree->parent->children_tail, tree); GNUNET_free (tree->filename); GNUNET_free (tree); } /** * Write @a size bytes from @a buf into the #output_stream. * * @param buf buffer with data to write * @param size number of bytes to write * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int write_all (const void *buf, size_t size) { const char *cbuf = buf; size_t total; ssize_t wr; total = 0; do { wr = write (output_stream, &cbuf[total], size - total); if (wr > 0) total += wr; } while ( (wr > 0) && (total < size) ); if (wr <= 0) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to write to stdout: %s\n", strerror (errno)); return (total == size) ? GNUNET_OK : GNUNET_SYSERR; } /** * Write message to the master process. * * @param message_type message type to use * @param data data to append, NULL for none * @param data_length number of bytes in @a data * @return #GNUNET_SYSERR to stop scanning (the pipe was broken somehow) */ static int write_message (uint16_t message_type, const char *data, size_t data_length) { struct GNUNET_MessageHeader hdr; #if 0 fprintf (stderr, "Helper sends %u-byte message of type %u\n", (unsigned int) (sizeof (struct GNUNET_MessageHeader) + data_length), (unsigned int) message_type); #endif hdr.type = htons (message_type); hdr.size = htons (sizeof (struct GNUNET_MessageHeader) + data_length); if ( (GNUNET_OK != write_all (&hdr, sizeof (hdr))) || (GNUNET_OK != write_all (data, data_length)) ) return GNUNET_SYSERR; return GNUNET_OK; } /** * Function called to (recursively) add all of the files in the * directory to the tree. Called by the directory scanner to initiate * the scan. Does NOT yet add any metadata. * * @param filename file or directory to scan * @param dst where to store the resulting share tree item; * NULL is stored in @a dst upon recoverable errors (#GNUNET_OK is returned) * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int preprocess_file (const char *filename, struct ScanTreeNode **dst); /** * Closure for the 'scan_callback' */ struct RecursionContext { /** * Parent to add the files to. */ struct ScanTreeNode *parent; /** * Flag to set to GNUNET_YES on serious errors. */ int stop; }; /** * Function called by the directory iterator to (recursively) add all * of the files in the directory to the tree. Called by the directory * scanner to initiate the scan. Does NOT yet add any metadata. * * @param cls the `struct RecursionContext` * @param filename file or directory to scan * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int scan_callback (void *cls, const char *filename) { struct RecursionContext *rc = cls; struct ScanTreeNode *chld; if (GNUNET_OK != preprocess_file (filename, &chld)) { rc->stop = GNUNET_YES; return GNUNET_SYSERR; } if (NULL == chld) return GNUNET_OK; chld->parent = rc->parent; GNUNET_CONTAINER_DLL_insert (rc->parent->children_head, rc->parent->children_tail, chld); return GNUNET_OK; } /** * Function called to (recursively) add all of the files in the * directory to the tree. Called by the directory scanner to initiate * the scan. Does NOT yet add any metadata. * * @param filename file or directory to scan * @param dst where to store the resulting share tree item; * NULL is stored in @a dst upon recoverable errors (#GNUNET_OK is returned) * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int preprocess_file (const char *filename, struct ScanTreeNode **dst) { struct ScanTreeNode *item; struct stat sbuf; uint64_t fsize = 0; if ((0 != STAT (filename, &sbuf)) || ((!S_ISDIR (sbuf.st_mode)) && (GNUNET_OK != GNUNET_DISK_file_size ( filename, &fsize, GNUNET_NO, GNUNET_YES)))) { /* If the file doesn't exist (or is not stat-able for any other reason) skip it (but report it), but do continue. */ if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE, filename, strlen (filename) + 1)) return GNUNET_SYSERR; /* recoverable error, store 'NULL' in *dst */ *dst = NULL; return GNUNET_OK; } /* Report the progress */ if (GNUNET_OK != write_message (S_ISDIR (sbuf.st_mode) ? GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY : GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_FILE, filename, strlen (filename) + 1)) return GNUNET_SYSERR; item = GNUNET_new (struct ScanTreeNode); item->filename = GNUNET_strdup (filename); item->is_directory = (S_ISDIR (sbuf.st_mode)) ? GNUNET_YES : GNUNET_NO; item->file_size = fsize; if (GNUNET_YES == item->is_directory) { struct RecursionContext rc; rc.parent = item; rc.stop = GNUNET_NO; GNUNET_DISK_directory_scan (filename, &scan_callback, &rc); if ( (GNUNET_YES == rc.stop) || (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY, "..", 3)) ) { free_tree (item); return GNUNET_SYSERR; } } *dst = item; return GNUNET_OK; } /** * Extract metadata from files. * * @param item entry we are processing * @return #GNUNET_OK on success, #GNUNET_SYSERR on fatal errors */ static int extract_files (struct ScanTreeNode *item) { struct GNUNET_CONTAINER_MetaData *meta; ssize_t size; size_t slen; if (GNUNET_YES == item->is_directory) { /* for directories, we simply only descent, no extraction, no progress reporting */ struct ScanTreeNode *pos; for (pos = item->children_head; NULL != pos; pos = pos->next) if (GNUNET_OK != extract_files (pos)) return GNUNET_SYSERR; return GNUNET_OK; } /* this is the expensive operation, *afterwards* we'll check for aborts */ meta = GNUNET_CONTAINER_meta_data_create (); EXTRACTOR_extract (plugins, item->filename, NULL, 0, &add_to_md, meta); slen = strlen (item->filename) + 1; size = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); if (-1 == size) { /* no meta data */ GNUNET_CONTAINER_meta_data_destroy (meta); if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA, item->filename, slen)) return GNUNET_SYSERR; return GNUNET_OK; } else if (size > (UINT16_MAX - sizeof (struct GNUNET_MessageHeader) - slen)) { /* We can't transfer more than 64k bytes in one message. */ size = UINT16_MAX - sizeof (struct GNUNET_MessageHeader) - slen; } { char buf[size + slen]; char *dst = &buf[slen]; memcpy (buf, item->filename, slen); size = GNUNET_CONTAINER_meta_data_serialize (meta, &dst, size, GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); if (size < 0) { GNUNET_break (0); size = 0; } GNUNET_CONTAINER_meta_data_destroy (meta); if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA, buf, slen + size)) return GNUNET_SYSERR; } return GNUNET_OK; } #ifndef WINDOWS /** * Install a signal handler to ignore SIGPIPE. */ static void ignore_sigpipe () { struct sigaction oldsig; struct sigaction sig; memset (&sig, 0, sizeof (struct sigaction)); sig.sa_handler = SIG_IGN; sigemptyset (&sig.sa_mask); #ifdef SA_INTERRUPT sig.sa_flags = SA_INTERRUPT; /* SunOS */ #else sig.sa_flags = SA_RESTART; #endif if (0 != sigaction (SIGPIPE, &sig, &oldsig)) fprintf (stderr, "Failed to install SIGPIPE handler: %s\n", strerror (errno)); } /** * Turn the given file descriptor in to '/dev/null'. * * @param fd fd to bind to /dev/null * @param flags flags to use (O_RDONLY or O_WRONLY) */ static void make_dev_zero (int fd, int flags) { int z; GNUNET_assert (0 == close (fd)); z = open ("/dev/null", flags); GNUNET_assert (-1 != z); if (z == fd) return; dup2 (z, fd); GNUNET_assert (0 == close (z)); } #endif /** * Main function of the helper process to extract meta data. * * @param argc should be 3 * @param argv [0] our binary name * [1] name of the file or directory to process * [2] "-" to disable extraction, NULL for defaults, * otherwise custom plugins to load from LE * @return 0 on success */ int main (int argc, char *const *argv) { const char *filename_expanded; const char *ex; struct ScanTreeNode *root; #if WINDOWS /* We're using stdout to communicate binary data back to the parent; use * binary mode. */ _setmode (1, _O_BINARY); /* Get utf-8-encoded arguments */ if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 5; output_stream = 1; /* stdout */ #else ignore_sigpipe (); /* move stdout to some other FD for IPC, bind stdout/stderr to /dev/null */ output_stream = dup (1); make_dev_zero (1, O_WRONLY); make_dev_zero (2, O_WRONLY); #endif /* parse command line */ if ( (3 != argc) && (2 != argc) ) { FPRINTF (stderr, "%s", "gnunet-helper-fs-publish needs exactly one or two arguments\n"); #if WINDOWS GNUNET_free ((void*) argv); #endif return 1; } filename_expanded = argv[1]; ex = argv[2]; if ( (NULL == ex) || (0 != strcmp (ex, "-")) ) { plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY); if (NULL != ex) plugins = EXTRACTOR_plugin_add_config (plugins, ex, EXTRACTOR_OPTION_DEFAULT_POLICY); } /* scan tree to find out how much work there is to be done */ if (GNUNET_OK != preprocess_file (filename_expanded, &root)) { (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR, NULL, 0); EXTRACTOR_plugin_remove_all (plugins); #if WINDOWS GNUNET_free ((void*) argv); #endif return 2; } /* signal that we're done counting files, so that a percentage of progress can now be calculated */ if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE, NULL, 0)) { EXTRACTOR_plugin_remove_all (plugins); #if WINDOWS GNUNET_free ((void*) argv); #endif return 3; } if (NULL != root) { if (GNUNET_OK != extract_files (root)) { (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR, NULL, 0); free_tree (root); EXTRACTOR_plugin_remove_all (plugins); #if WINDOWS GNUNET_free ((void*) argv); #endif return 4; } free_tree (root); } /* enable "clean" shutdown by telling parent that we are done */ (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED, NULL, 0); EXTRACTOR_plugin_remove_all (plugins); #if WINDOWS GNUNET_free ((void*) argv); #endif return 0; } /* end of gnunet-helper-fs-publish.c */ gnunet-0.10.1/src/fs/gnunet-service-fs_mesh.h0000644000175000017500000000667412225777503015771 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_mesh.h * @brief non-anonymous file-transfer * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_FS_MESH_H #define GNUNET_SERVICE_FS_MESH_H /** * Handle for a request that is going out via mesh API. */ struct GSF_MeshRequest; /** * Function called with a reply from the mesh. * * @param cls closure * @param type type of the block, ANY on error * @param expiration expiration time for the block * @param data_size number of bytes in 'data', 0 on error * @param data reply block data, NULL on error */ typedef void (*GSF_MeshReplyProcessor)(void *cls, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration, size_t data_size, const void *data); /** * Look for a block by directly contacting a particular peer. * * @param target peer that should have the block * @param query hash to query for the block * @param type desired type for the block * @param proc function to call with result * @param proc_cls closure for 'proc' * @return handle to cancel the operation */ struct GSF_MeshRequest * GSF_mesh_query (const struct GNUNET_PeerIdentity *target, const struct GNUNET_HashCode *query, enum GNUNET_BLOCK_Type type, GSF_MeshReplyProcessor proc, void *proc_cls); /** * Cancel an active request; must not be called after 'proc' * was calld. * * @param sr request to cancel */ void GSF_mesh_query_cancel (struct GSF_MeshRequest *sr); /** * Initialize subsystem for non-anonymous file-sharing. */ void GSF_mesh_start_server (void); /** * Shutdown subsystem for non-anonymous file-sharing. */ void GSF_mesh_stop_server (void); /** * Initialize subsystem for non-anonymous file-sharing. */ void GSF_mesh_start_client (void); /** * Shutdown subsystem for non-anonymous file-sharing. */ void GSF_mesh_stop_client (void); GNUNET_NETWORK_STRUCT_BEGIN /** * Query from one peer, asking the other for CHK-data. */ struct MeshQueryMessage { /** * Type is GNUNET_MESSAGE_TYPE_FS_MESH_QUERY. */ struct GNUNET_MessageHeader header; /** * Block type must be DBLOCK or IBLOCK. */ uint32_t type GNUNET_PACKED; /** * Query hash from CHK (hash of encrypted block). */ struct GNUNET_HashCode query; }; /** * Reply to a MeshQueryMessage. */ struct MeshReplyMessage { /** * Type is GNUNET_MESSAGE_TYPE_FS_MESH_REPLY. */ struct GNUNET_MessageHeader header; /** * Block type must be DBLOCK or IBLOCK. */ uint32_t type GNUNET_PACKED; /** * Expiration time for the block. */ struct GNUNET_TIME_AbsoluteNBO expiration; /* followed by the encrypted block */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/fs/fs_test_lib.h0000644000175000017500000000665012225777503013700 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_test_lib.h * @brief library routines for testing FS publishing and downloading; * this code is limited to flat files * and no keywords (those functions can be tested with * single-peer setups; this is for testing routing). * @author Christian Grothoff */ #ifndef FS_TEST_LIB_H #define FS_TEST_LIB_H #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "gnunet_testbed_service.h" /** * Function signature. * * @param cls closure (user defined) * @param uri a URI, NULL for errors * @param fn name of the file on disk to be removed upon * completion, or NULL for inserted files (also NULL on error) */ typedef void (*GNUNET_FS_TEST_UriContinuation) (void *cls, const struct GNUNET_FS_Uri * uri, const char *fn); /** * Publish a file at the given daemon. * * @param peer where to publish * @param timeout if this operation cannot be completed within the * given period, call the continuation with an error code * @param anonymity option for publication * @param do_index GNUNET_YES for index, GNUNET_NO for insertion, * GNUNET_SYSERR for simulation * @param size size of the file to publish * @param seed seed to use for file generation * @param verbose how verbose to be in reporting * @param cont function to call when done * @param cont_cls closure for cont */ void GNUNET_FS_TEST_publish (struct GNUNET_TESTBED_Peer *peer, struct GNUNET_TIME_Relative timeout, uint32_t anonymity, int do_index, uint64_t size, uint32_t seed, unsigned int verbose, GNUNET_FS_TEST_UriContinuation cont, void *cont_cls); /** * Perform test download. * * @param peer which peer to download from * @param timeout if this operation cannot be completed within the * given period, call the continuation with an error code * @param anonymity option for download * @param seed used for file validation * @param uri URI of file to download (CHK/LOC only) * @param verbose how verbose to be in reporting * @param cont function to call when done * @param cont_cls closure for cont */ void GNUNET_FS_TEST_download (struct GNUNET_TESTBED_Peer *peer, struct GNUNET_TIME_Relative timeout, uint32_t anonymity, uint32_t seed, const struct GNUNET_FS_Uri *uri, unsigned int verbose, GNUNET_SCHEDULER_Task cont, void *cont_cls); #endif gnunet-0.10.1/src/fs/gnunet-service-fs_mesh_client.c0000644000175000017500000004544312250315331017300 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_mesh_client.c * @brief non-anonymous file-transfer * @author Christian Grothoff * * TODO: * - PORT is set to old application type, unsure if we should keep * it that way (fine for now) */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_util_lib.h" #include "gnunet_mesh_service.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet-service-fs.h" #include "gnunet-service-fs_indexing.h" #include "gnunet-service-fs_mesh.h" /** * After how long do we reset connections without replies? */ #define CLIENT_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) /** * Handle for a mesh to another peer. */ struct MeshHandle; /** * Handle for a request that is going out via mesh API. */ struct GSF_MeshRequest { /** * DLL. */ struct GSF_MeshRequest *next; /** * DLL. */ struct GSF_MeshRequest *prev; /** * Which mesh is this request associated with? */ struct MeshHandle *mh; /** * Function to call with the result. */ GSF_MeshReplyProcessor proc; /** * Closure for 'proc' */ void *proc_cls; /** * Query to transmit to the other peer. */ struct GNUNET_HashCode query; /** * Desired type for the reply. */ enum GNUNET_BLOCK_Type type; /** * Did we transmit this request already? #GNUNET_YES if we are * in the 'waiting_map', #GNUNET_NO if we are in the 'pending' DLL. */ int was_transmitted; }; /** * Handle for a mesh to another peer. */ struct MeshHandle { /** * Head of DLL of pending requests on this mesh. */ struct GSF_MeshRequest *pending_head; /** * Tail of DLL of pending requests on this mesh. */ struct GSF_MeshRequest *pending_tail; /** * Map from query to `struct GSF_MeshRequest`s waiting for * a reply. */ struct GNUNET_CONTAINER_MultiHashMap *waiting_map; /** * Channel to the other peer. */ struct GNUNET_MESH_Channel *channel; /** * Handle for active write operation, or NULL. */ struct GNUNET_MESH_TransmitHandle *wh; /** * Which peer does this mesh go to? */ struct GNUNET_PeerIdentity target; /** * Task to kill inactive meshs (we keep them around for * a few seconds to give the application a chance to give * us another query). */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Task to reset meshs that had errors (asynchronously, * as we may not be able to do it immediately during a * callback from the mesh API). */ GNUNET_SCHEDULER_TaskIdentifier reset_task; }; /** * Mesh channel for creating outbound channels. */ static struct GNUNET_MESH_Handle *mesh_handle; /** * Map from peer identities to 'struct MeshHandles' with mesh * channels to those peers. */ static struct GNUNET_CONTAINER_MultiPeerMap *mesh_map; /* ********************* client-side code ************************* */ /** * Transmit pending requests via the mesh. * * @param mh mesh to process */ static void transmit_pending (struct MeshHandle *mh); /** * Iterator called on each entry in a waiting map to * move it back to the pending list. * * @param cls the `struct MeshHandle` * @param key the key of the entry in the map (the query) * @param value the `struct GSF_MeshRequest` to move to pending * @return #GNUNET_YES (continue to iterate) */ static int move_to_pending (void *cls, const struct GNUNET_HashCode *key, void *value) { struct MeshHandle *mh = cls; struct GSF_MeshRequest *sr = value; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (mh->waiting_map, key, value)); GNUNET_CONTAINER_DLL_insert (mh->pending_head, mh->pending_tail, sr); sr->was_transmitted = GNUNET_NO; return GNUNET_YES; } /** * We had a serious error, tear down and re-create mesh from scratch. * * @param mh mesh to reset */ static void reset_mesh (struct MeshHandle *mh) { struct GNUNET_MESH_Channel *channel = mh->channel; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resetting mesh channel to %s\n", GNUNET_i2s (&mh->target)); mh->channel = NULL; if (NULL != channel) GNUNET_MESH_channel_destroy (channel); GNUNET_CONTAINER_multihashmap_iterate (mh->waiting_map, &move_to_pending, mh); mh->channel = GNUNET_MESH_channel_create (mesh_handle, mh, &mh->target, GNUNET_APPLICATION_TYPE_FS_BLOCK_TRANSFER, GNUNET_MESH_OPTION_RELIABLE); transmit_pending (mh); } /** * Task called when it is time to destroy an inactive mesh channel. * * @param cls the `struct MeshHandle` to tear down * @param tc scheduler context, unused */ static void mesh_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshHandle *mh = cls; struct GNUNET_MESH_Channel *tun; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout on mesh channel to %s\n", GNUNET_i2s (&mh->target)); mh->timeout_task = GNUNET_SCHEDULER_NO_TASK; tun = mh->channel; mh->channel = NULL; GNUNET_MESH_channel_destroy (tun); } /** * Task called when it is time to reset an mesh. * * @param cls the `struct MeshHandle` to tear down * @param tc scheduler context, unused */ static void reset_mesh_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshHandle *mh = cls; mh->reset_task = GNUNET_SCHEDULER_NO_TASK; reset_mesh (mh); } /** * We had a serious error, tear down and re-create mesh from scratch, * but do so asynchronously. * * @param mh mesh to reset */ static void reset_mesh_async (struct MeshHandle *mh) { if (GNUNET_SCHEDULER_NO_TASK != mh->reset_task) GNUNET_SCHEDULER_cancel (mh->reset_task); mh->reset_task = GNUNET_SCHEDULER_add_now (&reset_mesh_task, mh); } /** * Functions of this signature are called whenever we are ready to transmit * query via a mesh. * * @param cls the struct MeshHandle for which we did the write call * @param size the number of bytes that can be written to @a buf * @param buf where to write the message * @return number of bytes written to @a buf */ static size_t transmit_sqm (void *cls, size_t size, void *buf) { struct MeshHandle *mh = cls; struct MeshQueryMessage sqm; struct GSF_MeshRequest *sr; mh->wh = NULL; if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh channel to %s failed during transmission attempt, rebuilding\n", GNUNET_i2s (&mh->target)); reset_mesh_async (mh); return 0; } sr = mh->pending_head; if (NULL == sr) return 0; GNUNET_assert (size >= sizeof (struct MeshQueryMessage)); GNUNET_CONTAINER_DLL_remove (mh->pending_head, mh->pending_tail, sr); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (mh->waiting_map, &sr->query, sr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); sr->was_transmitted = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending query for %s via mesh to %s\n", GNUNET_h2s (&sr->query), GNUNET_i2s (&mh->target)); sqm.header.size = htons (sizeof (sqm)); sqm.header.type = htons (GNUNET_MESSAGE_TYPE_FS_MESH_QUERY); sqm.type = htonl (sr->type); sqm.query = sr->query; memcpy (buf, &sqm, sizeof (sqm)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully transmitted %u bytes via mesh to %s\n", (unsigned int) size, GNUNET_i2s (&mh->target)); transmit_pending (mh); return sizeof (sqm); } /** * Transmit pending requests via the mesh. * * @param mh mesh to process */ static void transmit_pending (struct MeshHandle *mh) { if (NULL == mh->channel) return; if (NULL != mh->wh) return; mh->wh = GNUNET_MESH_notify_transmit_ready (mh->channel, GNUNET_YES /* allow cork */, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct MeshQueryMessage), &transmit_sqm, mh); } /** * Closure for handle_reply(). */ struct HandleReplyClosure { /** * Reply payload. */ const void *data; /** * Expiration time for the block. */ struct GNUNET_TIME_Absolute expiration; /** * Number of bytes in 'data'. */ size_t data_size; /** * Type of the block. */ enum GNUNET_BLOCK_Type type; /** * Did we have a matching query? */ int found; }; /** * Iterator called on each entry in a waiting map to * process a result. * * @param cls the `struct HandleReplyClosure` * @param key the key of the entry in the map (the query) * @param value the `struct GSF_MeshRequest` to handle result for * @return #GNUNET_YES (continue to iterate) */ static int handle_reply (void *cls, const struct GNUNET_HashCode *key, void *value) { struct HandleReplyClosure *hrc = cls; struct GSF_MeshRequest *sr = value; sr->proc (sr->proc_cls, hrc->type, hrc->expiration, hrc->data_size, hrc->data); sr->proc = NULL; GSF_mesh_query_cancel (sr); hrc->found = GNUNET_YES; return GNUNET_YES; } /** * Functions with this signature are called whenever a complete reply * is received. * * @param cls closure with the `struct MeshHandle` * @param channel channel handle * @param channel_ctx channel context * @param message the actual message * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing */ static int reply_cb (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct MeshHandle *mh = *channel_ctx; const struct MeshReplyMessage *srm; struct HandleReplyClosure hrc; uint16_t msize; enum GNUNET_BLOCK_Type type; struct GNUNET_HashCode query; msize = ntohs (message->size); if (sizeof (struct MeshReplyMessage) > msize) { GNUNET_break_op (0); reset_mesh_async (mh); return GNUNET_SYSERR; } srm = (const struct MeshReplyMessage *) message; msize -= sizeof (struct MeshReplyMessage); type = (enum GNUNET_BLOCK_Type) ntohl (srm->type); if (GNUNET_YES != GNUNET_BLOCK_get_key (GSF_block_ctx, type, &srm[1], msize, &query)) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received bogus reply of type %u with %u bytes via mesh from peer %s\n", type, msize, GNUNET_i2s (&mh->target)); reset_mesh_async (mh); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received reply `%s' via mesh from peer %s\n", GNUNET_h2s (&query), GNUNET_i2s (&mh->target)); GNUNET_MESH_receive_done (channel); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies received via mesh"), 1, GNUNET_NO); hrc.data = &srm[1]; hrc.data_size = msize; hrc.expiration = GNUNET_TIME_absolute_ntoh (srm->expiration); hrc.type = type; hrc.found = GNUNET_NO; GNUNET_CONTAINER_multihashmap_get_multiple (mh->waiting_map, &query, &handle_reply, &hrc); if (GNUNET_NO == hrc.found) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies received via mesh dropped"), 1, GNUNET_NO); return GNUNET_OK; } return GNUNET_OK; } /** * Get (or create) a mesh to talk to the given peer. * * @param target peer we want to communicate with */ static struct MeshHandle * get_mesh (const struct GNUNET_PeerIdentity *target) { struct MeshHandle *mh; mh = GNUNET_CONTAINER_multipeermap_get (mesh_map, target); if (NULL != mh) { if (GNUNET_SCHEDULER_NO_TASK != mh->timeout_task) { GNUNET_SCHEDULER_cancel (mh->timeout_task); mh->timeout_task = GNUNET_SCHEDULER_NO_TASK; } return mh; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating mesh channel to %s\n", GNUNET_i2s (target)); mh = GNUNET_new (struct MeshHandle); mh->reset_task = GNUNET_SCHEDULER_add_delayed (CLIENT_RETRY_TIMEOUT, &reset_mesh_task, mh); mh->waiting_map = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_YES); mh->target = *target; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (mesh_map, &mh->target, mh, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); mh->channel = GNUNET_MESH_channel_create (mesh_handle, mh, &mh->target, GNUNET_APPLICATION_TYPE_FS_BLOCK_TRANSFER, GNUNET_MESH_OPTION_RELIABLE); GNUNET_assert (mh == GNUNET_CONTAINER_multipeermap_get (mesh_map, target)); return mh; } /** * Look for a block by directly contacting a particular peer. * * @param target peer that should have the block * @param query hash to query for the block * @param type desired type for the block * @param proc function to call with result * @param proc_cls closure for @a proc * @return handle to cancel the operation */ struct GSF_MeshRequest * GSF_mesh_query (const struct GNUNET_PeerIdentity *target, const struct GNUNET_HashCode *query, enum GNUNET_BLOCK_Type type, GSF_MeshReplyProcessor proc, void *proc_cls) { struct MeshHandle *mh; struct GSF_MeshRequest *sr; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Preparing to send query for %s via mesh to %s\n", GNUNET_h2s (query), GNUNET_i2s (target)); mh = get_mesh (target); sr = GNUNET_new (struct GSF_MeshRequest); sr->mh = mh; sr->proc = proc; sr->proc_cls = proc_cls; sr->type = type; sr->query = *query; GNUNET_CONTAINER_DLL_insert (mh->pending_head, mh->pending_tail, sr); transmit_pending (mh); return sr; } /** * Cancel an active request; must not be called after 'proc' * was calld. * * @param sr request to cancel */ void GSF_mesh_query_cancel (struct GSF_MeshRequest *sr) { struct MeshHandle *mh = sr->mh; GSF_MeshReplyProcessor p; p = sr->proc; sr->proc = NULL; if (NULL != p) { /* signal failure / cancellation to callback */ p (sr->proc_cls, GNUNET_BLOCK_TYPE_ANY, GNUNET_TIME_UNIT_ZERO_ABS, 0, NULL); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cancelled query for %s via mesh to %s\n", GNUNET_h2s (&sr->query), GNUNET_i2s (&sr->mh->target)); if (GNUNET_YES == sr->was_transmitted) GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (mh->waiting_map, &sr->query, sr)); else GNUNET_CONTAINER_DLL_remove (mh->pending_head, mh->pending_tail, sr); GNUNET_free (sr); if ( (0 == GNUNET_CONTAINER_multihashmap_size (mh->waiting_map)) && (NULL == mh->pending_head) ) mh->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &mesh_timeout, mh); } /** * Iterator called on each entry in a waiting map to * call the 'proc' continuation and release associated * resources. * * @param cls the `struct MeshHandle` * @param key the key of the entry in the map (the query) * @param value the `struct GSF_MeshRequest` to clean up * @return #GNUNET_YES (continue to iterate) */ static int free_waiting_entry (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GSF_MeshRequest *sr = value; GSF_mesh_query_cancel (sr); return GNUNET_YES; } /** * Function called by mesh when a client disconnects. * Cleans up our `struct MeshClient` of that channel. * * @param cls NULL * @param channel channel of the disconnecting client * @param channel_ctx our `struct MeshClient` */ static void cleaner_cb (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { struct MeshHandle *mh = channel_ctx; struct GSF_MeshRequest *sr; if (NULL == mh->channel) return; /* being destroyed elsewhere */ GNUNET_assert (channel == mh->channel); mh->channel = NULL; while (NULL != (sr = mh->pending_head)) GSF_mesh_query_cancel (sr); /* first remove `mh` from the `mesh_map`, so that if the callback from `free_waiting_entry()` happens to re-issue the request, we don't immediately have it back in the `waiting_map`. */ GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (mesh_map, &mh->target, mh)); GNUNET_CONTAINER_multihashmap_iterate (mh->waiting_map, &free_waiting_entry, mh); if (NULL != mh->wh) GNUNET_MESH_notify_transmit_ready_cancel (mh->wh); if (GNUNET_SCHEDULER_NO_TASK != mh->timeout_task) GNUNET_SCHEDULER_cancel (mh->timeout_task); if (GNUNET_SCHEDULER_NO_TASK != mh->reset_task) GNUNET_SCHEDULER_cancel (mh->reset_task); GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (mh->waiting_map)); GNUNET_CONTAINER_multihashmap_destroy (mh->waiting_map); GNUNET_free (mh); } /** * Initialize subsystem for non-anonymous file-sharing. */ void GSF_mesh_start_client () { static const struct GNUNET_MESH_MessageHandler handlers[] = { { &reply_cb, GNUNET_MESSAGE_TYPE_FS_MESH_REPLY, 0 }, { NULL, 0, 0 } }; mesh_map = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES); mesh_handle = GNUNET_MESH_connect (GSF_cfg, NULL, NULL, &cleaner_cb, handlers, NULL); } /** * Function called on each active meshs to shut them down. * * @param cls NULL * @param key target peer, unused * @param value the `struct MeshHandle` to destroy * @return #GNUNET_YES (continue to iterate) */ static int release_meshs (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct MeshHandle *mh = value; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout on mesh channel to %s\n", GNUNET_i2s (&mh->target)); if (NULL != mh->channel) GNUNET_MESH_channel_destroy (mh->channel); return GNUNET_YES; } /** * Shutdown subsystem for non-anonymous file-sharing. */ void GSF_mesh_stop_client () { GNUNET_CONTAINER_multipeermap_iterate (mesh_map, &release_meshs, NULL); GNUNET_CONTAINER_multipeermap_destroy (mesh_map); mesh_map = NULL; if (NULL != mesh_handle) { GNUNET_MESH_disconnect (mesh_handle); mesh_handle = NULL; } } /* end of gnunet-service-fs_mesh_client.c */ gnunet-0.10.1/src/fs/test_gnunet_fs_rec_data.tgz0000644000175000017500000004263611374167231016630 00000000000000‹³IºKí}{oW–gþ¾Ÿ¢ , i†’ßN'î4 ÈtÌmYÒH² Ä%²(U›¬bW%sûÝ÷üÎã>Ф’lºw0&ºcI¬ºsÏûu'eóè›?øó˜>ß¾xŸ|ûâqü¯}¾yòäÙ‹—ÏŸ?ùôÛo?yúøåËo²ôÂðY¶]ÞdÙ77MÝÝÖÓé¶ç~ëûÿ¢Ÿ ÿõŒÿ¡óöçÿìñ‹¯çÿøÈùŸ¾üãæÀÓÙn?ÿ'ßöÎÿÙãÇO¿ÉÿqK ŸÿæçYÙñm^Ý'õÍ¡ûg/çëçüýÿ±Ôÿ¤‘ÿ/^>ûJÿÿˆÏWúÿïýýçÿ?餸±þ÷ô«þ÷øÈùŸþôÍñ ÿòøù‹'Ïüù¿ø–õ¿gÏ_~åÿÿˆO¶áóÓéûì§áéðâè$;ÿãÉè8£ÿO/‡nÓãôùP4mYWÙ³Aöô»ì.«"{J4ï\v\/VMysÛe{ÇûüÇìMC2粞v÷ySdoêe5É;z{ªñaöçÛ®[|ÿèÑ´ÖÍÍ£¿¸lxW4«š-ÛlQ4ó²ëŠIÖÕÙ˜FÏòj’MʶkÊëeWdôì57Ç—eѺ¬žfÝ-½9+ÇEÕÙ¤/çEÕ 2z>Cø•ÕMVv¾ª»,ŸÍêûbrè¶m—?çM‘ϯgžºº-jEU4ù,;_^ÓlÙ‰ÎHãæÙ”¶=àÏŠiçW3­×0°B³¢É>—Õ¤ÅÒïëæs{h“è[-^ËæuÛeÞ]4ù¸+Ç´~9÷“¢-oªbâj]þ™¿ÏWÙª^6¼°I=<Û[‰ÁRà ]A–ý¸¢ÕW]“·ÝÀu¿¹ã²êŠj"çt³Ì›œ~/ú3ºµ ø8B ï?§íÔ7M>?8 æXz»¤W踚bž—ô† 0d0Hٵٲ¥‘hé?ä±âí¨GOâ ÷Àž<ÈiUØ…Íø kÉ‹aÍÜÖØW^­ô4>Zê¬È[˜Ð_¯x…ù’¸ ¯ñc½ÌÆyÅ#á;ŒÂÐÒý·´…ºfLøù¶¨²{Ä¢È?c9€€_Ï_aM1-š¸MS˜€ánÑОhÎ3~ónS¬ÉÐw·y‡ƒt·ù H„B% ®­/ÛÓãnnýi„yVN1dv_¶·û?ía\”wxyÙŒ1ä¤È訛¢c¢åÝ=áý½Šg"4öÓÓë8mZÛXV‡Aª¬*î¯3ÀëôÃ}®ê{?î¤Æ˜Œ3_¥Ï¯vŸ,g¶×òiT…ÀpÑwÄy3€¸³IQ­pFØ„Œ)/byûY¿bê\6 HªáýÈS‡Ìè¤k<Ä¡¸qÑtD¾vA„T^—³²Ãa(˜7žR ¥¦/§À@BúI9J~¿>- æcD‰ð2oh¬âK>_Ìh܇VÐ.Ç·â t·Fqô[W2D˜º³i¡›“øÎyKßUX ¦—4`E äåóÂéºÚ5Äš(åñ@=§·WLt{ÚE¨'ÐòXIãºøEµ·„.ŒÙŠ($·Ú¬å%®#ýTš0œ^vÌêPƒ LIíùÉ&ô"‚én³îž°£+í÷nïÉ>¡ ñ½ŽeÈ^'9\`öÞÓ}‚9±Á/0&%~wSÞÞÍŠb,u[–ñ*vñ Òp˜;*¢øSǬ¿«]žWYÞ®m‡ù/o“¶8&>Ùÿ+¾,f`îÎN¢)D<ól KVŒ ¼ê„»ÊÄׄ~ÂþyRç'méŒÃtMñ÷eÙ o^I¤êÐuAHÑ|¦?å­f2È)ʲJæÏ¤Ìq$v @Ð[y§°™dăIw©—-m ’AVt;(é ?Ãí²ž3ÐÊñ. n!ûÊò1=ÀHpê òhßͲrëÛè7^('Œ[DdùŒ´¼¹åGæyµœ’ú@DÐ8åtmÍ\2€ ™ õ‰&¤£®Æõ|AÄIPT¤AòÀÙù&éIDrbg^–µ+Bå99v42ÑMXÃ5H¢—  ™Œô0f=YŽ;QH{"ž,Iæô˜IIC@…‡h Zþ½àk~,Ú— ºèrÚOÊZï wá0…°(Ål¾¾%)„¯þ1f͘Åil·…®†ï.³£Ó×ÙñÙéëÑÕèìô?>$q6-+™‘ßß¹ŠdÌŽ¨§|¾FEÏ<mÕÂe oUîˆÂ=/rÚ•—w³’Ž`–ß+_•š&Jm+Ç–Í@Y ¡`1/$"M3R¾üº 2÷Ðñ²¡ãû9sæ€ÐõÕF#ìÔS*[g«Ï²aN“é#bN&tä-‹˜l‡Dî=µ£/íÉNPjvhe+`CÌãh½d+çUùïy€7¡ÙŽˆdDÖ&€2Ë™õO(T“|Ád‡_yÓÙ9àG$Cxž··8"˜`éA»ÊÁ@!LP¯Tœ° ;®r¤ŽE+QNOû^ÎX>ðâJàúlHèÂ#!¶£krÐJ³«XäŸv®Ù¾Âƒ˜8~Šq”íŒk‹žÁßvE© &êªüœzØÑð<ºS=J¿ö@uç7D®ëpž0š°• ò‘¥BNv ~«—Dæôî™2™ŽŒ“ÖÑ@M’ôë¬dlƒíTVSœFÁ,QŽùÓ˜ŸgDÄ@lú dýSŒ—ú<@óΘdæ•8| E¼¼ËECÇ™ë>$ùgK†ž¸„ìñfi8Ýf32ð1ò»¼œñREyw ¦vQP ñZèBÄV+&äé˜D2÷ÅlæO‚`tWôÑt šW-ÁoyCQazÚùÕ¬áS€F¥¨X)…w¬3T®œ•W9לå"t)—{ÁCµÃbäÄ¡Áv¤¿¶Ð»Ù½!Ê´ºždýÁÙ*ÌsWÈüÒÐ ðmÒ‘WÄ4Ž"_pT'¬¯ŸÖP9Ú§6k‚ybîêáå2cUšD¥æeU°¸†×”D¹7Š`_ø™Å]áçèVñüÞÎp’˜c ¥‡•zå¤{аŠñ&ô…RUdÖxHm1×1Ø–™¥@•Çàqc6±"+e“ÄQYÜëÁxça`à£);¿Â9¤mE1 iÅ=Ä›$ mz"ÌyÁl9ÈšÜÅ.bì Äé`àÃ#Í‹‚X0Ɔ¾mh FŒ'‡d%°éy ÓÓdþNd³#Q à"G_Ï>Ïþ-!˘XÅÂè ”Î®ÿV0Çð¶ {ÈÌÎÍÆ{ U5o&ÙÈ€^)ô( ¹äïÈ<-¡‡‰²‹&Ð)hõ¤Jæ Íú†dýnÉVOVð^ ”ã\´D?Q+êsz“ýx9˽·m0ÌHû[æ7p†T²<ï!Úl%ÊX>¯é¹`áò¶™³*{±!Â]²yCuÝä`j;"•+5BiÔ‹•­ÎËV~ ¨DfL=+ó÷ò}ñ¾òÛBEC|AχøÜøs~#Lþ]þ7Â1±«ºònqo,+•€&àÇ]ô8Óøõ>I¨æŒ´]K«ªèaÁj$(׿éªÁM$~¶Ž8|`²8Ò(ü³*“Ú5’‰@Y\ˆ€<6n§·ŠE\M“~¡u)ªqàQèjl˜1‡ç—ÜÞg²R‹X|5!&"&¬€†ÔS’xÞÌg@—œ…°<ìöJ ÁjY6(Œ;Å ²ïÛè%˜¾œ™jV§½¹2PûFfW×¢„ëD9G`j¶r³²‚[­]^{ИVà­#hìS·ÝÀ™8E4…ˆr-d’wLóeeF,›»‚ Sø®I%+ u¸x Q Û&à5ÙWqñÇ8äÕ~så6-;ÔšÂȞК]¼A±ÆÖçN¦s2ÝÃkIIµÏ÷Ä?C žñ°³§‡ÙyKœéÜ$bF‘]¨ÎæŽâM6(PŒ”öµ)qð=@Ú¬9¢ÏÍÁÏþ`h´‹»ZŒÓå¯àš¸ÈwÇçEg.I›cÒ ·æ¤5ÀéÁnòe5+ç%ÆH}ØÆ[Ö­>5NÉh!ý]N…®XXºØ†dƒU¿^¥à`)XÊÊHƒì†”xpÚ–ù‹·¤×«Ô&äæø©Ésv0j ˆQ›,+Š i‹X¢(×ÞžÝL$úfÐr= ‹yóïáÒ.| „4“´Õ¨ÒÞ›¼ö±3ű¶Ê†+ó6¿¢#¦Í&\ªË’E1[¶â”ô.æè ! %‚çg´×TüêU`Ëê8Š0ÕbŽ$“áW¦œQ@Û7"@”ÞÐc· øVSŠ~¦B ìÔ(dÖåOŽqCœ˜ËÖûXâEöÍéV%4Å.ýD|@×Åm>›”¾ùO⃠Ø9õ!b)&dÞ›¸F#‡÷\HÆ |ñ‘I|OâÙ~Å$lœ0ÇBˆ‰39¯Ûr!"ˆÞd\=öpSg‡³Ëf¼œÃ€†ŸdŠG ±ã 'À 8Ê †v/g–]²ºH§ÄJ|’ò >'O³“·…î@ G¹…g |v>bq÷÷£üBö ÀsDÒêà˜— ?0F=Qr<­“Ã(%¹†œ&]wâÅ>4&s1ÓaŒo«zVß@˜m™s3À(r ÙgÓ匤ùŒñ†6|£Ô¡ÏÃ"%ìÉA?ÎÏ"ÆÑÁ¹OcNȬeŸ[öôqöšÀ0¿¦×Ÿ|÷ÝKДk‰ñ¤bG¬¡ˆ¡ªºôÙ“˜€Ac=¶‡6d<1WHy¥Ä‚ïs›Õ˜%[„ü×%Éþ4 Ì2›/K]&¬a$¯ÂÀ C%µµ—Œ0Ê’7ˆGFb)¯]ŸDEj`|j!H1¿íY‚<ÊÖÀË+ÀFýK‰ðêϤòžiMK`½SgÚ>‹Èl‚wá}lø°..é;⇇¡×RJðG oÓ(ܤX á ê,`žº¡Øô…Ö^I˜ˆ§$ï(Qt˜¿§#Ю٫oRs눺1GdòÄ{ç0aì"4}WÏ–s‘jÄiê†ß%áHS¢såvò› 4â¶¥­4€ˆ7ßµQ”:ˆ|]¹3ª¨f,d%+‹(NõÚø»šžì® b ‰z¿B\_^1dzªØdÛt|¥§ÿÙŽ‚OsœKaD’àC±öbŸAW°w^Æ2õ””§oèp¶ÈÒÔQ²Áaì% 0#$`KœÀ±UF½9&áΡ˜çmôˆõ&ë«4‚OU+1ŸH¤ûùzÎtV Èì!iúônW-ëÀšæÅƒìÿtôÄݰ¾7_äUi~%á›]}åÑVòl²lÄf£Ë€"ÁˆsÕsÉ`œemH$¨HB^íÿÔ=çÂÔØï•hƒŒ¹¾h{$‡Iu½ ÿjUä¸n£GDrFþ'S&"­I±ÈDJ¦8–Ä©á·BêÂ;ˆa¨‘iR\E·j1¤4’É ¹r^™~Èo+>>º"Õ£¶:›ñA6Âÿýø0°)kî*Åçµd¨×ˆH¯­+M8‘¸Í [*Ži¨>¼_^-f¬BJrHkUóà!ì‡Ê[†…D ;ªZM Á)>GÜ5µ.ã£ÓŒŽèÀÖñQ3$ïÔkµq±—ÏÊš³zQ¶æTGq=ç-kfbŽ"¤Ž ’a £˜_9Naß¼|‘¡žx¼);‘'®MA|yô¢-„­Ö“³œ‘‚_"3ì§g,!¨´×ÏÙ—óØÕR ¼ÔÑ©?xàjQIä"Ç"ŸºÌ”Éx”é²ï `ƒ*¯'©a” ü¼ëYÀ˜$¥—ϼµ0lÈ”•¶k¸;ØŠJBx’ù'ä]†ì¢´ßÏðæw{ðæ¬öy fÊìÚø4‘+ò|GòW r˜H¥X]œ¨¼ÃÈþÒy…"Úe›ó¨’j …®”áVè/3ƒ5#Ýä-1˜öÁ×JX­97EI#ÞèÓ˜‚jYlx‘âÖ-0Y¢ÍmbM¶J5ÅVªY²_pQÍAWà_Iÿò)a+/+ñH °à¤݆HxÄŠ¡‰/^¾.„ÛNY`è1i´Úr$Õ¨ûFmíˆMLÔ” ¥ ¡Qä|Œ;AŠØíQjöþ’Í$âH‚ïÄ=á^û@ö$¦¬±Â( ÎxØa¡;¼”HBsî`»œ‹‘Á˜¡ã3\‡ZQÞ5 Ò°Ì ¢­8a™6±\µ‡I–æs’¸”ÝÖô=ÙÝ ^µAZ䨇¼Y8Ï&ZÚ@\œ ž‹/ºâ4ô ² ‘6#Þƒ–[VJw¼ÉÜk¥¦ý%›¸I½¼î¦ËçKµ!ê@GSÏîÎÓü®æ´EÖ<ò«¶‰3¨¬º!ˆ'ÎÕŠR¬`ö ²PI^µëV ÖkÉ¢#ôòiD„¤ãYÞ¶QÉÇ ç–°¸ñÒ×6ô&ÏdL 9—W„„›Þ£µ0¶J9¢â œø,Ù  …s™‰dÙñÂaäÕÈ`ï­Ü+ƒQ9ˆ z„úd mZ@/²Ÿ@–»¬xhÖðšOÓ9ÁÚpŒšâ6+4Ñ d{áLø‘äíˆGÆA¥‚ g]ÕŽô@z»ãb0 AÙ[Å´ÕÃI-ºÍ;8'îùt³Ø™êït@‘gïö}ÚR¼þÈŽÚ¶õõ ½Üõ†0*‹‡3“º#§£[ôˆz¹€ Yr#4öÃ4ÈÆÃ¡‰¶¢§äñj ¨äÖÀã±¹ü­A!(¼”;³ Tݟ칿-ªµ U1›úD gNÀË I†biÅì>„Ž…ûØD´–»²žq!on9“”=®á¬ÇÈnœª0Yuù¸©Û6HS4 á [ÏÙ´avÈÅqÏÄ#•Iü²÷‰ˆ.Kt`m>rÜp@ã#Y/gx{°ë'Ωíʳ›åHLÚjQ†~ Hš1N,+„E8ð¥&?¨¥ÅÐúö0; q™«Âª;Ñ_C€å`M§ÞÇ5_zͽiegÀYÍÇ‘Š )ä|ꢟ¦0±Bn‡nó"dæ\#Pk²´ ‰‰Y¸ƒÕHâ’3"En¡Ü˜Ôf)¦‰“ÕcGV’‹ákÁ%à$¾¾µš'dµ±¤Ë7®Ý‰çÛ²ÔãZ·ÕrϦ3 dU>Ä“œ1t˜7ÑØ®ÚëTr•DÊÜZz’çDÙ¶7ï`kBŒ8«6¥Æ`¹ö RbŸóZÓe6Ocñì¼Ó%°9vø ¨/`s–ØÛ‚% <óš…¼]Õ÷º zFœö¬ûãÞ6ØËô>ÜÁv±¸-ËŸP¦8ÐØ±úEØbJcRiÞ‡­Õû{7æ}„Ù4o«Ã1r%Š¥¾YC«ÇîǤ©Œ%Á!…Vºaþ¹J@ç ŒÂš`QÜ]@¨ÅÆÞQ¤iJüU~¼Ö„$¶&-ýñ-ļ¸L¦4%Âû¤,Ù5ý$‡6{ò‚™é“—ý5¼‚ŽiAˆ _nÊfKsçÅW(á‰ÜÏrói/pùŽ <»™!ÿ°1ßâZ´•ш«Ådôžƒæ‘‹±]vaõã}¿Ïy#Lñ¶W"ƒé$oÊÊ·guù¡âvK kŽà÷šV¨¯.‚Ð=—íµ‘÷лad!¹o¿¶2Ù§ÃÑÃÆ“Kí†$¢o> ,¦Êçòƒ„÷¹×E|ÞF·‡‰Š}¤Î˜¶ÙzYu 3Øžä1ªùÁa„¹âžU Âãb\ª&ÈðiüÓÓðžWIZ]ØIÔÀÄŽL=³üUšãîÜ&ÛÍö¬Ê¶wŒšy³/T(½¶ØûÀ}æ*¶y9‘ÖÞSF§ëj?§’SR†6Žë‹IAª9ƒ]ÝÅøe#|u€p¹^[?Û„e6ܤ߯í¨kÞùTPVo°w¥Dø,Fä3oƒƒÝ„kš8áÜ%5zLº—’j/VO® bSZR$ ³m9o¹‹¦pæÙ††­rV àª3è&kÝèüúœ0‹dÍB`ý…e)mIr¢cÕ/’ÿ›K@ÊtçQP>®§z祑y¼±iÕ°Û8‡½]áÝiÂζõÇ> ^®¨¹k‹~À6àý:i íÀ'áù¶¸˜iÀ)#>u*¬!nÚCBB_gÓQÑ ‘Å1c”[ v$в×ñÖ²"ú©û50…JSÖ50Jn£„'Ó¹f>"ÜØky¯œø€¢q\C·«~¼Þ?²RVâˆó>¸ÍWŒ„^P½“Ó‚n^„aKʴǤõ4@nªÕ•NhÑEu#bäûÙœï<ŠD1Õ8_.­²êtEÒEËJ"г˜•p:¸oÀØ/…*ÄÃÇVNß-n¶õD\o£¤0VÞ‘ÿ(-ÙüÞ¨"vª 7Î÷Œ”¸käªî+€ûˆØ¿ ð¾óJ¨”Õ3Ì52VfõȤªªš¸©4ü @L {B-0°6—6ƒ[¥ƒ;|J–7“7hª1Ky6€ƒ{Í‹X‡a¿2zJÁðËÇÙ„µši§'ÁõEß‘m[3Ô“"¤ßD1ÚÓÚ–ì ÞIY´Ñ^Üoïe '^Šž0-d¶”ó"ôóóÂMy ½c¬žVôÓý`ǹþrCÑÁx©Æ0ª‡ï³¾N3>h9 o8ˢĹø¾]£±Ô‘ãÝz*1OdpþjGhSl—yPXú†Ÿ€7ŠÝ¬Só¡Éÿ0Å9?÷DS/ºø¨# DeoÙßIb»´öBªâ>mÐjY ÎKÙ${Ú `öÝ!{ÿ\ºKC•Q ¾•ж^¹„åNÆÁé]–"'JN$]ÅJ “«ü’Œ¤PýxT‰oæ’Êí»¥¬§²7ŸUfBäâ¢5Y¥ÁoÀ]´,]š71“÷ØanƒÜC)*à†zÁÑÒ¤õPœ€ N-™¦o’ ’sÞ+Ã,´[,Gi¸Ѿu´”j½ ‡v’ƒ3Î÷Ø‘ÒCòZé@X¯P`°F÷ÒnHÓ}¡)™äÓGT™~]ßF£}1!š%¾ðKÜœÊsž-µViT%‘®Æ§ÚHÁ]·/½11ÐBÜ×Ä㬧"^xÎv)¡Ö¿À¦´ ÝIg¬…²'©Ë,j×q,„9‹×!ãcGU¶/Œ§ÿÙ?Žù˜“Ì#¥šÒð*nÉ%*XÒÖr­:%ë–LF{†3ÔDñXc^47‚9q¿/æoÛÈÕibä1[ÖV•­ïNÓÜ%HÔI“KïL8:â˜}H¦ ’sýÈÛ‰~nõk‘`ûj—;2N¸ŠRÜ0ä$+‚˜ôD ôÕcO\P·|óL¯q‘ú<[b]Z¥Ø¯«Ø¨‹·àÑuËš Î¸þ÷œÔßõkÉŸõÅtŠ”«5µYímpž &Tk‘7-3ô±Ï^I>D>×½oS¤“Öjºxþ@±è®ÛÔ«|¦‘²:J¡“ê­°–þ:¶õVZÅ;F· P8ÒÌ_]’,Ì¥)ƒ”óçŒTþƒ>()]ÂU‚ðÙñ.RÔõáÀ°'! 2©DlE²f!³‘Û±ç3í<çì&õzÅMá0OH|Òª’'O³skki-ç*ñ:ÖÍŽ%ÞôTFД÷èrMÀ3¾'¤£ÆtI·˜óÐ“ËØDð8¥·ez†BKQÐe5Æ«öí÷| Iòdh†ƒ]£TàoÉŸ žbuãˆâ©ÑÀƒ´4“þ¦ùX•:RQõí¯“hžÇaÁèÄYá&e®‚ºëKÂÝzÊô´ì.”i ‹õ2pðʨBh‘iÙêÖ%qà‰€õ%£ýM%½æŠv±ã•7š¹ ô ëÙNhø+̽ª}F!w<Ÿf ‰Ë®åG|Âkâ*àPCOz¥¼3¬:RÂrökøöèzØÌ&èªå¹ÎôÌILîˆõ§H¸¡\8iiÁyY8K%tÉvg*m_¤+Å*‰Ì®߆âȲêOdz áf±&®Øû´“nR˜Dµ2÷ˆ£G õNIø½ìÄÿ¦õeH¨Õ|ˆ)U«ÞS°uËÓ=ßv®²‘×taíRlïÈ|wE•K!'_Ö°T¿¿<÷žÜ—¶¶;|Î;¾‘{z‚œÜ Ú…o©=×%W}Ën×öe¨³ó¸›²œzê+ڨЪ¹*p&:xµ¶T©RÛšœ+ Ö$"M#æ€ó½Ò¹M0ò&­.zò›%I™å¶çÎr¢Iz%^Hs–žät’2¸\çªpŽF©¯V ¶e¯´øÑY'‰ªÞˆáQ W¨Ø(œ¢ º.*bHÞ·ÚCßÂ=òÂøÎe{Ïü ƒ˜#¹ßÁ‘ÖÓ|lk=íf±Ùä-¢P €Ž‡í#‹5.ôž¤øæ<™tw…`0@µ2í‚¥,»5÷¶è<è_æs‘…Iáà¦ÚJ—¾)ÒǬqªG‰rN3’­¦5(êt€Ì×ܩߚ¬ Ã¬,¡T7@°]æ’%j3m³*’6©®³4©Žä˜´ð¶¨@l ³í† Ò¥ÙZô„Zƒ5Ó™Ë×9~¸‰±Zg­¯›èxÍ·²l_¿6Î4°Wëö[JkÖtµKøâ Y~Ùö\Ø‚ÊêòAs®P½’N!Š;Â9Rí[¨ÂzÔ Mµƒþ#MÉ"¥nV\»©EžÄé¤Ùí.Ê’ÌðïøÒöÍÑ­ÛÐÔ+ô[Í :½ô$¯½„¤4u»r˜]}á  RO+¯Á †` è郀QB¥ÆÆš®¡Aji(wd?™]À! )',ùjÎyNu(è IW mMcþUm¸’Ä|e+½}ñ|ý±E7XKsϪƒãU8‰ùé֨ï.KŠÑ§Ïð¹;é:WH+ñ–æ“h5ygOòçJní;ñî%iõ?ï‹ð@‚ÖÁ%Ž’âYM6MíIÔß!ª‡•i·Æ9:»€5‚µì#˜HOEÐÀÖœ/,MarŸ{ëy¼îOÿ”½Ë:-Ü™fùE·¥µ–Ü~¾Rƒ›É5KãSs:JÕa È<ðÝØLw ÓÁ»i’¾âš˜B¼Í«ÈH]Ž3'½Û=ŽtÚFµ±Õ“§‡hnué¯1¢ó>Èí.ßÌ5©ç¦¿õúý‰‹b¢}ʲ=³¹Ý’;ÃH8#ÒÃb÷3ÍbCâäû´|›bSÈmeýí·˜×û†¶¿{ÔO¹¶ÁM*âÛZÛXiY[Η³.·{b$So­3Wâ°)V)Oo=¼¦âeÍ/»t¸ÃŒ›Ÿô]EÆZvà…˜¸U×ÉÝUÐuÉ¢G ³ãXò%˜^ã‰h–Þ"3D¾ë¥bj•Š^W'¾@6¾æGGò]$Pò&8¦ ˆX²3-G--‹»=yvˆŒî eâ^Š#XõC×Sü§½BÙo‘R}VŽ„kñ “FÉÍšŸºñZ—Ÿi9™èh.ôå½^ãæ ½ ´6fs 2‡âã$ý¤'êøº5&ë,¯Ör­×Õýß±»ó·gœ4.IÛ‹šù{«Ë›X’D­Vá¢ùãR]%øòü0»(è„iÝŠøî¥ž{`Úv¡d¶j²FGÓ ¶aŒÆlÛÛn,d:C8 §¹Á!Á8ûC†¶µëC‡¤EÙ”¾šW³½×‹¬R’ñÂ%3¾CG®3á)ü¥F¢ÜQœÉГ`#QYy6-ië8{¢Z¢± Ïür>¹\s@Mô)ÄòBZÑÕƒ•ëÁjGݺ(‚^O¯#÷ÀTÊËLjöÝE>ž-Wî¨Ám U¶BçW(×AôW`˜¥ Þ¸€7ë‰q^g8AÛM!jªÞv écãÛÚ¢6ûŸüúܦõExm¢=^áÚÆ|YÉ ‹ô Ì æ re•»+ÒûÌ@} ¡‰û–Ï¡w[u¦¤i_iP5€)Nùˆ|ô&î$<º½a6,FNø@MÝò›ToÔggKÖMÈÎuqÞ”?TÕÉ‘¢ÐS—Pµ¬ Ðõ† Ö „‹{s‚·¥ ¸‚ؤ½$H)ÌîÅ¡O TúY“ÅŽ^ ³Ñevz–ý|tqqtzõ1{sv/²ó‹³Ÿ.ŽÞ ²«3þ}øËÕðô*;^¼]] _g?~tGçç'£ã£O†ÙÉÑϸ9é—ãáùUöóÛáiv†á]³Ë«#¼0:Í~¾]Nâq¡õÅè§·WîíÙÉëáßPõˆfç³ó£‹«Ñðëø0z=Œ×”í]Ò²w²ŸGWoÏÞ_ùÅ»³74ÈÇ쯣Ó׃l8↿œ_ //i4öè­xH_ŽNOÞ¿¦µ ²i„Ó³«ìdD;£Ç®Î³é³6:Cã¿^¿¥_~Œ^¸VëÍèꔦ`ØÉÊߟ]¸ó÷çg—ÃÃL@HƒÀ/F—Íh Ø{ä"èÒïŽN‡˜+Ú³£cÂv³gï!"hß'¯ PÃìõðÍðøjôa8À“4ÍåûwC…÷å êŽNN²Óá1­÷èâcv9¼ø0:f8\ ÏF€ÒñÙÅF9;4zy(Éå>àqbYËÂ1NAÃÀ÷§'€ÄÅðßÞÓ^%YŠ%ÿè§‹!: ÷óˆ†Óóˆ‘ b øú" ÆGB±³ìÝÙëÑ‹"ÎñÙé‡áÇKC…àPöèÇ3æGZȈ×C+”pn¯Þý4¼Œ0s:½d{]žGø¾'|$8P^Ò^q´ô$;¢3Æ@N9G÷žxjˆCsãoñb÷ÂÜëH™œ]Ý룫£ŒWLÿþ8ÄÓÃSÓØÑññû ¢7<7h5—ï‰G§rØ/“øèâµ3"c¼}s4:yÑG<Ì|F ÄŒ€ÑIÈ—û‡ÃÏFohªã·zlYBʳ·t?é±£×FLŽ:-r¤0¡Ýñ GÁ¾oån\‰á1ðr­H%^“„éùŠ<8K9¤ßû&’inôÅgV£Ù¯HgaÍoV.Üq¹”¤;¨„Ž8@—há"ö¿(¨:R~¯6;Ú1gµT‚¢°å ß‘Ð:ø´®Ûz†úynœ,êtôò®œEkßà3‰t°HšÔ…‚¡ÜY" kég_ZLÒ¾ßÖuÇð’ÏyË „áóVîu:bI:ו¥–„È;%eUÐF$½×‡mûp+±¥3è•Ó!Ñ}ÜpcK’»ÖøË²íÕ–42ÒvÒÉ{·ìQ÷i +;—^-ê_· רÜ'‘^Äk7«úø’ÙÆvIçˆ T«30¨¯V:å5Ë ±ºÍ§ØVìßžÛäQIµ'Eiör_K›ÜˆéXÿRofÔÕ0mJÌ#ñz=(ëÞÖýÍŸ¯ÓìÀXV·H¶¨Ù¨ÿ‚uÏ™.}oW¾Êº©"ןN~ßz¼Eûßm¹œH‡¾nÊbŠJƒüð/Ú•È´¬½ãýìÏèN÷š‡¨­|ï/2ï•Þ×jiÉqïïO¹ìÌÔƒÔ mŽ(>¨%çmb_hÁÏv~`fÌšk!äQHùÑ^Znº¿nÙn@ا¿»êá+Òak\4{:NéJ {ÔÔ5HSÙ^ùºZtÐà±Ìù˜•”]õ5/î6Å+ Š×e!– FxÈ·†˜ÉÖ5 ñˆ¯}fsšY·}`í+õ" °s™EöçÛ®[|ÿèÑýýýáMµ<¬››G–îñè/´ #¤î¡è&nm‚&"Â;Ùÿ-WsÏ{øùšºB×(Ü’/¹B{‹å"¶C5Ëz;[Æå첕ðh:§4Ê׸ò¦¸a;îÛ(ÍNㆽh\£%«Öyÿò»)q ¥53ÃôèÇ˳“÷WÓ±%óŠÏT3ëV„ ŸøÆ÷ûÝÃ0\Ÿžƒè`^^Ì08&ò愚}Q´÷$¼Š§ïÆ !àót»ZÀÝÈáÂÌßBhëã5ø·ÿì¶ú¸Ò9m»Åß™egSVD|`;ðL›ÚÍùÐÉÂìÚW*Ýz? Ýõ^Ð’} Ù)L„×õ—Ÿ7©Kæ\S¤Zò¬Ñu½BFƒú«Ã-v£_ÑìsNì[brÝG½ÐI:€ºo'„ñ}[wtXñw~¼ñ1õ”päfçèZIÑÐðµª=qãæm"R÷›D*žÃ8wùH¦[Ü,Œ˜D|>Ò9l/Ú¨V"âË9ÄšqÌB¯õZi±´ýåºNÐ(CØ3gÉJàÈ–:î0£†Š:uCê9:¸ù³„Žî-á^Ó pu·å­ 'Hk¶y÷%Tä“ Ñ´ÔáŠds9Rh6Åâ¶$Uº^Ü®Ý̳߮›Åìð¶›Ïèt¾ù¯ø™”Í£üÑ蔌¸““?hŽÇôyùü9þ}òí‹Çñ¿ôyöòÙ³§ßùî»çü÷Å@ïþ¡ÿ~7@àú1ÿ÷ ÿ÷)ÿ÷9ÿ÷ÅÀÑ_òÏßòÿÄÿýîÍsTEo:Ö>¥|£`ÜLÚˆƒÞ¶\o¾€zิ¿ *¹0&4cÑ fr!]¨bT%Å"ŽfXÈuÄܬ"\†À6 ºájμ= éàl¦HÍì¶jÚ¬ÜÇ‘ûaíÃ0ù6 j-Ù»-f±à?|DìyZÞ,›âk\¯Tï’M pþ)DxÊÙÄnáæ§,O/yÐHŸ·xþh!…¼bx$‚+—ãW¬Šb‰Ÿ.†G¯ß w0r‘yôŽOʰzŸ0ï%T&ýÕ_l'¡ÆOÊÆtÔ87;Ü)ëoOÉôZë6 ¢œ]†ÝÍh95bp?›^…͉vâ¼Ñµh¨3Í€“0i hɉ T¾¬˜”Åg)„àò{Ñ[¥È$ú®ÈÞÑIñv¸Á,ß¶Ô~ŸíùûŽ÷7= „‚M|ò‡º«x!×£ZM5›ú7KxpÆÈþ$ÿ.Ÿ-õžÏ;ÚJläŠÚD†/äÞtn4±Œ<Ÿ6#.´œtž×QaJ°‡„€óÉ–¾ x²­/M(êÆ?vðn$!Giÿ/#ÄÉaŸowõ‚Ò¨KÝ.dÇCÍySj14é'2&ë91˜~‡ÒOtW’¼U¾¬ü?K¹"ËŸdyÌ-8×…“,ø”—±#Áñ©Ù³úf7^º¿ÝWM£=Õ¨ÐHJú.Òf½¸ø%:e)4ð±B—êÒ‰1ïžöX­¬ÄV2¦ƒ(v¥Ã&W.i›…OüÕÞÿ!y˜õê’¯>ütp¼« 7-µ­ y>cþ1É~Y ¡ïrÁÄ!;&¶Ç|«nàsÄâe׸vš#TÅš+wÅ 1fI„9µ¥¶Ú†~./SðCá#V7–ºÉeµl‘ÉËIVÚœ ÆC¯$vÍÊqgÄZ~Lm’¨BÓñ}]y&8Í´•ñK£¨µv€ž†`N×»C«”{¶µ¤*ÑQ»ë¤»Š-Ü•[/Z ¹Irý°Ïtp);Ç™±ì>ëaDè bÇ)U¯Õnçµr\¤¬í}‚l¢ Œ‘.ð¥÷ \‡9Ù¢Hí‹þTV»|•¹Ý±"dåbKga3Ú‘,‹gvãnゥJ¾‹Ò/[]¦RÂ]ÐÏ%ðbWppb¡AJ4¡ßCäà ¨„í=OižÉ®x`7ˆP°ýÔÕB|A‰¬ßU¿âh4„Ý|Ú(ƒ4û…Þo[l÷ú®·¢M¢û6£×2û$›®ê¤¡º–\A Þ°ãGj¨4’oBWZu0yhÝÝB|Åî h(»[¨Ð.ÚϽ¨îʦ®æ‰=*ªŒñ=äÆË‘Î³ÈÆMM3®ÎãúŒùŒmѱã<˜»¾„+1½C£%![x_ûPY6½F¨²xÏÇÇ?Œ¿û.;~srôÓå7ÙÉèGúw¶¨Ûò ?ÿ/§p¼fÓ•óÁóý÷ƒM¡E9w<‰ÐÄ;$hÓÔÙQC&®Ì…úµ 6aÅLJ¹rtÌñ>KÎDj9¾› ‚šÛß 3_ï²=µÞ œG‹õ‚í‚ :´d ´cQƒ7ˆIEºµ L’‚ Ð_I¸_BÎüºæ¿¥mÁrž,ü1-Úc>âÛB%½ÅyÂâÖÄd©!OöT~:<ܵ‹Åè P”–xì|8?ºz»#Þ;¡„Ÿ¥<uu*ª$r:G³EÇæ•¢†99 NÒe…ËnâÚ¤ ‡whðE AùÚ0ErÚÕé‹pÒVÑ<É%~­´‰![?«²wùøì2ûÍ$“K2”ɤQDžT)rÉñ[+"n+m$%ã°müAìLón‰;ÄÒa(泯o€¯HB6÷¶Á>` »žÓ†ZñA‘æVB›¾eëó-+hLsˆ«ƒIšD¶ðž›ñ8ã²òÙŸ^ê_þôò×—Ïõ—Åb~zù|'û_ëùXÇ¿üBCýë¿þ¿êü\W5ÜÁ¸ò;†î¨-1AÈ“›eÎ¥sâ"°Û¸qR\ú&¾3ÐÎL/6 Þ ÓØZÖð0BuÉä—ú›È›å‚ÍñiV.jp™z–\AlÎ)BÈ$ÐrŠæÄ[}ùÞÏ5è+ úCÛÓ:½«_ß}z´l›Gœ øˆ r×¢]ám’Y?¥ßÓ“E7·‰]øÂ*µ;Ìòì|ǵh4vËÈÅታ†y¬ ê§ƒâ‡ó‹á›Ñ/¬_!˯áv”Êù,Eö!s#ñ¶Dgñ†…ª7;>Þbü>ù>ºöXý†¦Ð;\ôÐÛ xEoK@­hûƒ„ó±c\7›·F·€é4Ü ¢áòà/ðüéнŽ]¡}IìNh;¤JYŒÜìS™F •¯"ðu~ê,6½/¥Y¾‚›s©VÎx•(¶ÄÚЫ®ùáõèbWÝ»|6Ád‹ô®èÆ0h lü Y1\S 5gdV¶¾ó¤-åû¶²¶~.œ2 .‚k.Ö‹*Ñr‰y—UF·…çÅ¥ïW«Yi–_÷éüoèÿ¡nµcZÄÝá8 ؾ«µdšâBQzvëPÓ*å¦ °¼¨'«E&ƒã‘ó,ÑÒÆº½sæ‰L˜P†9A,ßÔÚY(<"rtµù\úmõbq–q\ši¡6Ÿ`Êù]$Vµ·gÛÆê5҆˛jnqb9=˜(Þ‘çvóÖ4¾ên¥…¦Dg)4|Æ7ëUµÇ&õ.új- ©ÐŸ‘ ¦~ÑCÁ@Ü7m1GÈ1ŸK{›7EÄúå(ØÎ_DwC$SKº¤©'d&6÷̳«fùò¹ª9ýý `”òG”pdŒèéÏ÷hŒxxû—Ýì¶ÈùnI4¸Š­ìªžtŸwãÒ~Ü$+½Oò†‹¹ì ²¢³Vìñ‘pÏ-²¼¶öA>ôb&ËÞ1À]Ö„‰pXKâ ÜSâ;YޝwI1倱Ü÷‘}‚;×ûz×CpÂWLV­Ý-,w’³l}åý`¬†ù^­E,¹×™ïäTš'~#ζôŽI£ñKué"¼ð¯Ü›÷×xO\yùy9ÅŒÁ)¬fŒ„®ÈH—@˧G×uÝ=’Àw¹Ñâgòe‰¿—´6Ñ÷DÅ“9wlx ¥Ñ#ÁãЉiÉMá¯êIøœ—žèÂ~B™Û ›óVÚkJýTá¯gZI˽9'Ê%ž{Ç"ANy/òq 5¹½d"îÍ$¯FÕRkW ÷+b6¿&N±v]úú䢜‹¸b‘ª)A¹¥em¾’fʶyÉ;Årü6h[ Û•¢1À«íWϽ‚’ _yZ‘o¡x¤VÓß¿Á'çd`kƒû©]VÏwõú&…l¸8/Šd¹U¯ÔyC›ãó÷ÇgïÎN?\~¼¼¾szÓ“üÆË‘»#+‹WJõŸ¿N‘ø¦üû×áÅéðäàL*•µŽ0ÉŠ;l—×»!ÅÀª‰Õƒfe¶¤ÌÏ„í¹ä½’ÙÓÚŪ>Ë©“¶“Q6š²4g)‘©íŸM’< þ•‡Žõ×Àßa1jlUú¸[@RŒÍ67* ŠºÄ¶õ ¡8q•a‚îqá«cKöŸˆÇß.éMhé}¿Ò\¿Z[y¿Ní c9­wÕ’ÛtO¢Ä ì‰xO±ªçvnë¶ÛñÏe{åaq¨s&MÛm“À”ykœßÊ´«”¹ïóp1´À‰ö{I¢tõZ$íºz³ $p’šhŽœ²ëAMÉÓ…"èÆ>ƒ»%ÎæK÷r‰ñÀ®ÂwB¸ s•X&ÇÇ»à3È9ý•³ÃÅàý¤>ÔÃ$¨0«kª~Ãî¯õQ2¿ð£âKÉÙc@}gOÝxû³0×›`¹fÌ’ŽÏNߌ~úõrtEˆº) ÁbqÞO§ÊÀK‚ÅîeP‡¿÷©3›Àªç;yÝ­'lSlý<çÀkÑËÆdõ ›ÕæâÂe+ü!ZkÜ™¨M Î^V¡´DR‡ÌwèÉI›ËqÆ|Kb/· ¬Ž© ˆ¢ÒuFd ~|¯0³ç$³BhßR-8Eeî3©“„íàZÖK²OŽ.~àuì¦~Ü-*xÐNžB÷yt3;§BFï€ùD_íªÔUU–Ÿˆôä=m­!‘‘c±÷þÙ!÷ÿ=ªP»eÅ÷êÅb$¾o«òï˨>Tú¶‚l ™ßQ93áæ|hr¤YÍZÃòÞ_G¿sesù¥˜d©¹ŒBM¯Œ{±MðCå:oo³ðSû„æGÕÒÕ]Œ'Žßî†-6—V¸ãêÙeçÕ©@ ýdiIŸnweOçÐm¸&–pFªUâpN5qIR §Áë˜?°Æ²ë¥….ÜŠ°}žx‚¥œj¯JjWÓ7Ï­uA2±YTkø­åûqÆâ[W/²2ÞjÎ3…%o,J¹´F‚ZnWIj 1 ŠÚɇ˜,jççÑÓÊ|nd®5• ¤Q=Ë›ÑÉPŸÊ}=•F|¯fø„+Zâ;I-§ma”&ý¡×¬¥9÷J)ÀKèI“À‚)&ÅÝ£j))˜>‘—2–r]4t e:¨·‘‡fe®¢p{¥Ž ñ÷eYÖ‰Ë?þ]‡y]ëežºÏâWÝ]Ý.’Ëýïºà$²Ù9K½\È9÷[ibZp|QçÄ»Þã‹/šÆr}ýälÐH8ûš[ÁÜWû²‘¶[ÀYÞ91i™fHôÒ­‚)Moil´¡Ù^búûwƒMÖ£¶dXÚÇÒoÆÝ7$'ÐôRé·ž!òý÷!Ï8Nò³„Žpënz äüA‡¼Ò›Pè°9T*˯êÑí€Õ®¯ ZðLZÎ_l½\AÃ/ü®ïxËe ¦\\’°¹ñb«žØŠäã6®Àà&/¶=É ˆFI2ziÿìÊꯟ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯Ÿ¯ŸÞçÿ©§9Èðgnunet-0.10.1/src/fs/test_gnunet_fs_psd_data.conf0000644000175000017500000000015712225230043016742 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-py-psd/ [transport] PLUGINS = gnunet-0.10.1/src/fs/test_fs_file_information_data.conf0000644000175000017500000000017112225230043020114 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-file-information/ [transport] PLUGINS = gnunet-0.10.1/src/fs/test_fs_search_probes.c0000644000175000017500000001661212226007012015721 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_search_probes.c * @brief simple testcase for publish + search operation with probes * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_fs_service.h" /** * File-size we use for testing. */ #define FILESIZE 1024 /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static struct GNUNET_TIME_Absolute start; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_SearchContext *search; static struct GNUNET_FS_PublishContext *publish; static GNUNET_SCHEDULER_TaskIdentifier timeout_task; static int err; static void abort_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { timeout_task = GNUNET_SCHEDULER_NO_TASK; fprintf (stderr, "Timeout\n"); if (NULL != search) { GNUNET_FS_search_stop (search); search = NULL; } if (NULL != publish) { GNUNET_FS_publish_stop (publish); publish = NULL; } err = 1; } static void abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != publish) { GNUNET_FS_publish_stop (publish); publish = NULL; } if (GNUNET_SCHEDULER_NO_TASK != timeout_task) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } } static void abort_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (search != NULL) GNUNET_FS_search_stop (search); search = NULL; } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { const char *keywords[] = { "down_foo" }; struct GNUNET_FS_Uri *kuri; switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_PROGRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: kuri = GNUNET_FS_uri_ksk_create_from_args (1, keywords); start = GNUNET_TIME_absolute_get (); search = GNUNET_FS_search_start (fs, kuri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "search"); GNUNET_FS_uri_destroy (kuri); GNUNET_assert (search != NULL); break; case GNUNET_FS_STATUS_SEARCH_RESULT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Search complete.\n"); break; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); GNUNET_break (0); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_SEARCH_ERROR: FPRINTF (stderr, "Error searching file: %s\n", event->value.search.specifics.error.message); GNUNET_SCHEDULER_add_continuation (&abort_search_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_START: GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); GNUNET_assert (NULL == event->value.publish.pctx); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_assert (publish == event->value.publish.pc); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (1 == event->value.publish.anonymity); GNUNET_FS_stop (fs); fs = NULL; break; case GNUNET_FS_STATUS_SEARCH_UPDATE: if ( (0 < event->value.search.specifics.update.availability_rank) && (0 < event->value.search.specifics.update.availability_certainty) ) GNUNET_SCHEDULER_add_now (&abort_search_task, NULL); break; case GNUNET_FS_STATUS_SEARCH_START: GNUNET_assert (search == NULL); GNUNET_assert (0 == strcmp ("search", event->value.search.cctx)); GNUNET_assert (1 == event->value.search.anonymity); break; case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: break; case GNUNET_FS_STATUS_SEARCH_STOPPED: GNUNET_assert (search == event->value.search.sc); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; default: FPRINTF (stderr, "Unexpected event: %d\n", event->status); break; } return NULL; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar" }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_BlockOptions bo; struct GNUNET_FS_FileInformation *fi; size_t i; fs = GNUNET_FS_start (cfg, "test-fs-search", &progress_cb, NULL, GNUNET_FS_FLAGS_DO_PROBES, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi = GNUNET_FS_file_information_create_from_data (fs, "publish-context", FILESIZE, buf, kuri, meta, GNUNET_NO, &bo); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fi); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); timeout_task = GNUNET_SCHEDULER_add_delayed (LIFETIME, &abort_error, NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-search-probes", "test_fs_search_data.conf", &run, NULL)) return 1; return err; } /* end of test_fs_search_probes.c */ gnunet-0.10.1/src/fs/test_fs_search_data.conf0000644000175000017500000000015712225230043016041 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-search/ [transport] PLUGINS = gnunet-0.10.1/src/fs/gnunet-service-fs_pe.c0000644000175000017500000006000012245715040015401 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_pe.c * @brief API to manage query plan * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-fs.h" #include "gnunet-service-fs_cp.h" #include "gnunet-service-fs_pe.h" #include "gnunet-service-fs_pr.h" /** * Collect an instane number of statistics? May cause excessive IPC. */ #define INSANE_STATISTICS GNUNET_NO /** * List of GSF_PendingRequests this request plan * participates with. */ struct PendingRequestList; /** * Transmission plan for a peer. */ struct PeerPlan; /** * M:N binding of plans to pending requests. * Each pending request can be in a number of plans, * and each plan can have a number of pending requests. * Objects of this type indicate a mapping of a plan to * a particular pending request. * * The corresponding head and tail of the "PE" MDLL * are stored in a `struct GSF_RequestPlan`. (We need * to be able to lookup all pending requests corresponding * to a given plan entry.) * * Similarly head and tail of the "PR" MDLL are stored * with the 'struct GSF_PendingRequest'. (We need * to be able to lookup all plan entries corresponding * to a given pending request.) */ struct GSF_PendingRequestPlanBijection { /** * This is a doubly-linked list. */ struct GSF_PendingRequestPlanBijection *next_PR; /** * This is a doubly-linked list. */ struct GSF_PendingRequestPlanBijection *prev_PR; /** * This is a doubly-linked list. */ struct GSF_PendingRequestPlanBijection *next_PE; /** * This is a doubly-linked list. */ struct GSF_PendingRequestPlanBijection *prev_PE; /** * Associated request plan. */ struct GSF_RequestPlan *rp; /** * Associated pending request. */ struct GSF_PendingRequest *pr; }; /** * Information we keep per request per peer. This is a doubly-linked * list (with head and tail in the 'struct GSF_PendingRequestData') * with one entry in each heap of each 'struct PeerPlan'. Each * entry tracks information relevant for this request and this peer. */ struct GSF_RequestPlan { /** * This is a doubly-linked list. */ struct GSF_RequestPlan *next; /** * This is a doubly-linked list. */ struct GSF_RequestPlan *prev; /** * Heap node associated with this request and this peer. */ struct GNUNET_CONTAINER_HeapNode *hn; /** * The transmission plan for a peer that this request is associated with. */ struct PeerPlan *pp; /** * Head of list of associated pending requests. */ struct GSF_PendingRequestPlanBijection *pe_head; /** * Tail of list of associated pending requests. */ struct GSF_PendingRequestPlanBijection *pe_tail; /** * Earliest time we'd be happy to (re)transmit this request. */ struct GNUNET_TIME_Absolute earliest_transmission; /** * When was the last time we transmitted this request to this peer? 0 for never. */ struct GNUNET_TIME_Absolute last_transmission; /** * Current priority for this request for this target. */ uint64_t priority; /** * How often did we transmit this request to this peer? */ unsigned int transmission_counter; }; /** * Transmission plan for a peer. */ struct PeerPlan { /** * Heap with pending queries (struct GSF_RequestPlan), higher weights mean higher priority. */ struct GNUNET_CONTAINER_Heap *priority_heap; /** * Heap with pending queries (struct GSF_RequestPlan), by transmission time, lowest first. */ struct GNUNET_CONTAINER_Heap *delay_heap; /** * Map of queries to plan entries. All entries in the priority_heap or delay_heap * should be in the plan map. Note that it IS possible for the plan map to have * multiple entries for the same query. */ struct GNUNET_CONTAINER_MultiHashMap *plan_map; /** * Current transmission request handle. */ struct GSF_PeerTransmitHandle *pth; /** * Peer for which this is the plan. */ struct GSF_ConnectedPeer *cp; /** * Current task for executing the plan. */ GNUNET_SCHEDULER_TaskIdentifier task; }; /** * Hash map from peer identities to PeerPlans. */ static struct GNUNET_CONTAINER_MultiPeerMap *plans; /** * Sum of all transmission counters (equals total delay for all plan entries). */ static unsigned long long total_delay; /** * Number of plan entries. */ static unsigned long long plan_count; /** * Return the query (key in the plan_map) for the given request plan. * Note that this key may change as there can be multiple pending * requests for the same key and we just return _one_ of them; this * particular one might complete while another one might still be * active, hence the lifetime of the returned hash code is NOT * necessarily identical to that of the 'struct GSF_RequestPlan' * given. * * @param rp a request plan * @return the associated query */ static const struct GNUNET_HashCode * get_rp_key (struct GSF_RequestPlan *rp) { return &GSF_pending_request_get_data_ (rp->pe_head->pr)->query; } /** * Figure out when and how to transmit to the given peer. * * @param cls the `struct GSF_ConnectedPeer` for transmission * @param tc scheduler context */ static void schedule_peer_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Insert the given request plan into the heap with the appropriate weight. * * @param pp associated peer's plan * @param rp request to plan */ static void plan (struct PeerPlan *pp, struct GSF_RequestPlan *rp) { #define N ((double)128.0) /** * Running average delay we currently impose. */ static double avg_delay; struct GSF_PendingRequestData *prd; struct GNUNET_TIME_Relative delay; GNUNET_assert (rp->pp == pp); GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# average retransmission delay (ms)"), total_delay * 1000LL / plan_count, GNUNET_NO); prd = GSF_pending_request_get_data_ (rp->pe_head->pr); if (rp->transmission_counter < 8) delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, rp->transmission_counter); else if (rp->transmission_counter < 32) delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 8 + (1LL << (rp->transmission_counter - 8))); else delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 8 + (1LL << 24)); delay.rel_value_us = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, delay.rel_value_us + 1); /* Add 0.01 to avg_delay to avoid division-by-zero later */ avg_delay = (((avg_delay * (N - 1.0)) + delay.rel_value_us) / N) + 0.01; /* * For the priority, we need to consider a few basic rules: * 1) if we just started requesting (delay is small), we should * virtually always have a priority of zero. * 2) for requests with average latency, our priority should match * the average priority observed on the network * 3) even the longest-running requests should not be WAY out of * the observed average (thus we bound by a factor of 2) * 4) we add +1 to the observed average priority to avoid everyone * staying put at zero (2 * 0 = 0...). * * Using the specific calculation below, we get: * * delay = 0 => priority = 0; * delay = avg delay => priority = running-average-observed-priority; * delay >> avg_delay => priority = 2 * running-average-observed-priority; * * which satisfies all of the rules above. * * Note: M_PI_4 = PI/4 = arctan(1) */ rp->priority = round ((GSF_current_priorities + 1.0) * atan (delay.rel_value_us / avg_delay)) / M_PI_4; /* Note: usage of 'round' and 'atan' requires -lm */ if (rp->transmission_counter != 0) delay.rel_value_us += TTL_DECREMENT * 1000; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Considering (re)transmission number %u in %s\n", (unsigned int) rp->transmission_counter, GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); rp->earliest_transmission = GNUNET_TIME_relative_to_absolute (delay); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Earliest (re)transmission for `%s' in %us\n", GNUNET_h2s (&prd->query), rp->transmission_counter); GNUNET_assert (rp->hn == NULL); if (0 == GNUNET_TIME_absolute_get_remaining (rp->earliest_transmission).rel_value_us) rp->hn = GNUNET_CONTAINER_heap_insert (pp->priority_heap, rp, rp->priority); else rp->hn = GNUNET_CONTAINER_heap_insert (pp->delay_heap, rp, rp->earliest_transmission.abs_value_us); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains_value (pp->plan_map, get_rp_key (rp), rp)); if (GNUNET_SCHEDULER_NO_TASK != pp->task) GNUNET_SCHEDULER_cancel (pp->task); pp->task = GNUNET_SCHEDULER_add_now (&schedule_peer_transmission, pp); #undef N } /** * Get the pending request with the highest TTL from the given plan. * * @param rp plan to investigate * @return pending request with highest TTL */ struct GSF_PendingRequest * get_latest (const struct GSF_RequestPlan *rp) { struct GSF_PendingRequest *ret; struct GSF_PendingRequestPlanBijection *bi; bi = rp->pe_head; if (NULL == bi) return NULL; /* should never happen */ ret = bi->pr; bi = bi->next_PE; while (NULL != bi) { if (GSF_pending_request_get_data_ (bi->pr)->ttl.abs_value_us > GSF_pending_request_get_data_ (ret)->ttl.abs_value_us) ret = bi->pr; bi = bi->next_PE; } return ret; } /** * Function called to get a message for transmission. * * @param cls closure * @param buf_size number of bytes available in @a buf * @param buf where to copy the message, NULL on error (peer disconnect) * @return number of bytes copied to 'buf', can be 0 (without indicating an error) */ static size_t transmit_message_callback (void *cls, size_t buf_size, void *buf) { struct PeerPlan *pp = cls; struct GSF_RequestPlan *rp; size_t msize; pp->pth = NULL; if (NULL == buf) { /* failed, try again... */ if (GNUNET_SCHEDULER_NO_TASK != pp->task) GNUNET_SCHEDULER_cancel (pp->task); pp->task = GNUNET_SCHEDULER_add_now (&schedule_peer_transmission, pp); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# transmission failed (core has no bandwidth)"), 1, GNUNET_NO); return 0; } rp = GNUNET_CONTAINER_heap_peek (pp->priority_heap); if (NULL == rp) { if (GNUNET_SCHEDULER_NO_TASK != pp->task) GNUNET_SCHEDULER_cancel (pp->task); pp->task = GNUNET_SCHEDULER_add_now (&schedule_peer_transmission, pp); return 0; } msize = GSF_pending_request_get_message_ (get_latest (rp), buf_size, buf); if (msize > buf_size) { if (GNUNET_SCHEDULER_NO_TASK != pp->task) GNUNET_SCHEDULER_cancel (pp->task); /* buffer to small (message changed), try again */ pp->task = GNUNET_SCHEDULER_add_now (&schedule_peer_transmission, pp); return 0; } /* remove from root, add again elsewhere... */ GNUNET_assert (rp == GNUNET_CONTAINER_heap_remove_root (pp->priority_heap)); rp->hn = NULL; rp->last_transmission = GNUNET_TIME_absolute_get (); rp->transmission_counter++; total_delay++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing plan %p executed %u times, planning retransmission\n", rp, rp->transmission_counter); plan (pp, rp); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# query messages sent to other peers"), 1, GNUNET_NO); return msize; } /** * Figure out when and how to transmit to the given peer. * * @param cls the `struct PeerPlan` * @param tc scheduler context */ static void schedule_peer_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerPlan *pp = cls; struct GSF_RequestPlan *rp; size_t msize; struct GNUNET_TIME_Relative delay; pp->task = GNUNET_SCHEDULER_NO_TASK; if (NULL != pp->pth) { GSF_peer_transmit_cancel_ (pp->pth); pp->pth = NULL; } /* move ready requests to priority queue */ while ((NULL != (rp = GNUNET_CONTAINER_heap_peek (pp->delay_heap))) && (0 == GNUNET_TIME_absolute_get_remaining (rp->earliest_transmission).rel_value_us)) { GNUNET_assert (rp == GNUNET_CONTAINER_heap_remove_root (pp->delay_heap)); rp->hn = GNUNET_CONTAINER_heap_insert (pp->priority_heap, rp, rp->priority); } if (0 == GNUNET_CONTAINER_heap_get_size (pp->priority_heap)) { /* priority heap (still) empty, check for delay... */ rp = GNUNET_CONTAINER_heap_peek (pp->delay_heap); if (NULL == rp) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No active requests for plan %p.\n", pp); return; /* both queues empty */ } delay = GNUNET_TIME_absolute_get_remaining (rp->earliest_transmission); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sleeping for %s before retrying requests on plan %p.\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES), pp); GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# delay heap timeout (ms)"), delay.rel_value_us / 1000LL, GNUNET_NO); pp->task = GNUNET_SCHEDULER_add_delayed (delay, &schedule_peer_transmission, pp); return; } #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# query plans executed"), 1, GNUNET_NO); #endif /* process from priority heap */ rp = GNUNET_CONTAINER_heap_peek (pp->priority_heap); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing query plan %p\n", rp); GNUNET_assert (NULL != rp); msize = GSF_pending_request_get_message_ (get_latest (rp), 0, NULL); pp->pth = GSF_peer_transmit_ (pp->cp, GNUNET_YES, rp->priority, GNUNET_TIME_UNIT_FOREVER_REL, msize, &transmit_message_callback, pp); GNUNET_assert (NULL != pp->pth); } /** * Closure for merge_pr(). */ struct MergeContext { struct GSF_PendingRequest *pr; int merged; }; /** * Iterator that checks if an equivalent request is already * present for this peer. * * @param cls closure * @param query the query * @param element request plan stored at the node * @return #GNUNET_YES if we should continue to iterate, * #GNUNET_NO if not (merge success) */ static int merge_pr (void *cls, const struct GNUNET_HashCode * query, void *element) { struct MergeContext *mpr = cls; struct GSF_RequestPlan *rp = element; struct GSF_PendingRequestData *prd; struct GSF_PendingRequestPlanBijection *bi; struct GSF_PendingRequest *latest; if (GNUNET_OK != GSF_pending_request_is_compatible_ (mpr->pr, rp->pe_head->pr)) return GNUNET_YES; /* merge new request with existing request plan */ bi = GNUNET_new (struct GSF_PendingRequestPlanBijection); bi->rp = rp; bi->pr = mpr->pr; prd = GSF_pending_request_get_data_ (mpr->pr); GNUNET_CONTAINER_MDLL_insert (PR, prd->pr_head, prd->pr_tail, bi); GNUNET_CONTAINER_MDLL_insert (PE, rp->pe_head, rp->pe_tail, bi); mpr->merged = GNUNET_YES; #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requests merged"), 1, GNUNET_NO); #endif latest = get_latest (rp); if (GSF_pending_request_get_data_ (latest)->ttl.abs_value_us < prd->ttl.abs_value_us) { #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requests refreshed"), 1, GNUNET_NO); #endif rp->transmission_counter = 0; /* reset */ } return GNUNET_NO; } /** * Create a new query plan entry. * * @param cp peer with the entry * @param pr request with the entry */ void GSF_plan_add_ (struct GSF_ConnectedPeer *cp, struct GSF_PendingRequest *pr) { const struct GNUNET_PeerIdentity *id; struct PeerPlan *pp; struct GSF_PendingRequestData *prd; struct GSF_RequestPlan *rp; struct GSF_PendingRequestPlanBijection *bi; struct MergeContext mpc; GNUNET_assert (NULL != cp); id = GSF_connected_peer_get_identity2_ (cp); pp = GNUNET_CONTAINER_multipeermap_get (plans, id); if (NULL == pp) { pp = GNUNET_new (struct PeerPlan); pp->plan_map = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO); pp->priority_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); pp->delay_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); pp->cp = cp; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (plans, id, pp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } mpc.merged = GNUNET_NO; mpc.pr = pr; GNUNET_CONTAINER_multihashmap_get_multiple (pp->plan_map, &GSF_pending_request_get_data_ (pr)->query, &merge_pr, &mpc); if (GNUNET_NO != mpc.merged) return; GNUNET_CONTAINER_multihashmap_get_multiple (pp->plan_map, &GSF_pending_request_get_data_ (pr)->query, &merge_pr, &mpc); if (GNUNET_NO != mpc.merged) return; plan_count++; GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# query plan entries"), 1, GNUNET_NO); prd = GSF_pending_request_get_data_ (pr); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Planning transmission of query `%s' to peer `%s'\n", GNUNET_h2s (&prd->query), GNUNET_i2s (id)); rp = GNUNET_new (struct GSF_RequestPlan); bi = GNUNET_new (struct GSF_PendingRequestPlanBijection); bi->rp = rp; bi->pr = pr; GNUNET_CONTAINER_MDLL_insert (PR, prd->pr_head, prd->pr_tail, bi); GNUNET_CONTAINER_MDLL_insert (PE, rp->pe_head, rp->pe_tail, bi); rp->pp = pp; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (pp->plan_map, get_rp_key (rp), rp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); plan (pp, rp); } /** * Notify the plan about a peer being no longer available; * destroy all entries associated with this peer. * * @param cp connected peer */ void GSF_plan_notify_peer_disconnect_ (const struct GSF_ConnectedPeer *cp) { const struct GNUNET_PeerIdentity *id; struct PeerPlan *pp; struct GSF_RequestPlan *rp; struct GSF_PendingRequestData *prd; struct GSF_PendingRequestPlanBijection *bi; id = GSF_connected_peer_get_identity2_ (cp); pp = GNUNET_CONTAINER_multipeermap_get (plans, id); if (NULL == pp) return; /* nothing was ever planned for this peer */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (plans, id, pp)); if (NULL != pp->pth) { GSF_peer_transmit_cancel_ (pp->pth); pp->pth = NULL; } if (GNUNET_SCHEDULER_NO_TASK != pp->task) { GNUNET_SCHEDULER_cancel (pp->task); pp->task = GNUNET_SCHEDULER_NO_TASK; } while (NULL != (rp = GNUNET_CONTAINER_heap_remove_root (pp->priority_heap))) { GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (pp->plan_map, get_rp_key (rp), rp)); while (NULL != (bi = rp->pe_head)) { GNUNET_CONTAINER_MDLL_remove (PE, rp->pe_head, rp->pe_tail, bi); prd = GSF_pending_request_get_data_ (bi->pr); GNUNET_CONTAINER_MDLL_remove (PR, prd->pr_head, prd->pr_tail, bi); GNUNET_free (bi); } plan_count--; GNUNET_free (rp); } GNUNET_CONTAINER_heap_destroy (pp->priority_heap); while (NULL != (rp = GNUNET_CONTAINER_heap_remove_root (pp->delay_heap))) { GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (pp->plan_map, get_rp_key (rp), rp)); while (NULL != (bi = rp->pe_head)) { prd = GSF_pending_request_get_data_ (bi->pr); GNUNET_CONTAINER_MDLL_remove (PE, rp->pe_head, rp->pe_tail, bi); GNUNET_CONTAINER_MDLL_remove (PR, prd->pr_head, prd->pr_tail, bi); GNUNET_free (bi); } plan_count--; GNUNET_free (rp); } GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# query plan entries"), plan_count, GNUNET_NO); GNUNET_CONTAINER_heap_destroy (pp->delay_heap); GNUNET_CONTAINER_multihashmap_destroy (pp->plan_map); GNUNET_free (pp); } /** * Get the last transmission attempt time for the request plan list * referenced by @a pr_head, that was sent to @a sender * * @param pr_head request plan reference list to check. * @param sender the peer that we've sent the request to. * @param result the timestamp to fill, set to #GNUNET_TIME_UNIT_FOREVER_ABS if never transmitted * @return #GNUNET_YES if @a result was changed, #GNUNET_NO otherwise. */ int GSF_request_plan_reference_get_last_transmission_ (struct GSF_PendingRequestPlanBijection *pr_head, struct GSF_ConnectedPeer *sender, struct GNUNET_TIME_Absolute *result) { struct GSF_PendingRequestPlanBijection *bi; for (bi = pr_head; NULL != bi; bi = bi->next_PR) { if (bi->rp->pp->cp == sender) { if (0 == bi->rp->last_transmission.abs_value_us) *result = GNUNET_TIME_UNIT_FOREVER_ABS; else *result = bi->rp->last_transmission; return GNUNET_YES; } } return GNUNET_NO; } /** * Notify the plan about a request being done; destroy all entries * associated with this request. * * @param pr request that is done */ void GSF_plan_notify_request_done_ (struct GSF_PendingRequest *pr) { struct GSF_RequestPlan *rp; struct GSF_PendingRequestData *prd; struct GSF_PendingRequestPlanBijection *bi; prd = GSF_pending_request_get_data_ (pr); while (NULL != (bi = prd->pr_head)) { rp = bi->rp; GNUNET_CONTAINER_MDLL_remove (PR, prd->pr_head, prd->pr_tail, bi); GNUNET_CONTAINER_MDLL_remove (PE, rp->pe_head, rp->pe_tail, bi); if (NULL == rp->pe_head) { GNUNET_CONTAINER_heap_remove_node (rp->hn); plan_count--; GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (rp->pp->plan_map, &GSF_pending_request_get_data_ (bi->pr)->query, rp)); GNUNET_free (rp); } GNUNET_free (bi); } GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# query plan entries"), plan_count, GNUNET_NO); } /** * Initialize plan subsystem. */ void GSF_plan_init () { plans = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_YES); } /** * Shutdown plan subsystem. */ void GSF_plan_done () { GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (plans)); GNUNET_CONTAINER_multipeermap_destroy (plans); } /* end of gnunet-service-fs_pe.h */ gnunet-0.10.1/src/fs/test_fs_download_persistence.c0000644000175000017500000002540712226007024017322 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2008, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_download_persistence.c * @brief simple testcase for persistence of simple download operation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_fs_service.h" /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 2) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static struct GNUNET_TIME_Absolute start; static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_DownloadContext *download; static struct GNUNET_FS_PublishContext *publish; static GNUNET_SCHEDULER_TaskIdentifier timeout_kill; static char *fn; static int err; static void timeout_kill_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout downloading file\n"); if (download != NULL) { GNUNET_FS_download_stop (download, GNUNET_YES); download = NULL; } else if (publish != NULL) { GNUNET_FS_publish_stop (publish); publish = NULL; } timeout_kill = GNUNET_SCHEDULER_NO_TASK; err = 1; } static void abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (publish != NULL) { GNUNET_FS_publish_stop (publish); publish = NULL; } } static void abort_download_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { uint64_t size; if (download != NULL) { GNUNET_FS_download_stop (download, GNUNET_YES); download = NULL; } GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_size (fn, &size, GNUNET_YES, GNUNET_NO)); GNUNET_assert (size == FILESIZE); GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); fn = NULL; GNUNET_SCHEDULER_cancel (timeout_kill); timeout_kill = GNUNET_SCHEDULER_NO_TASK; } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event); static void restart_fs_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Restarting FS.\n"); GNUNET_FS_stop (fs); fs = GNUNET_FS_start (cfg, "test-fs-download-persistence", &progress_cb, NULL, GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END); } /** * Consider scheduling the restart-task. * Only runs the restart task once per event * category. * * @param ev type of the event to consider */ static void consider_restart (int ev) { static int prev[32]; static int off; int i; for (i = 0; i < off; i++) if (prev[i] == ev) return; prev[off++] = ev; GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_URGENT, &restart_fs_task, NULL); } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_PROGRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: printf ("Publishing complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024LL)); fn = GNUNET_DISK_mktemp ("gnunet-download-test-dst"); start = GNUNET_TIME_absolute_get (); GNUNET_assert (download == NULL); GNUNET_FS_download_start (fs, event->value.publish.specifics.completed.chk_uri, NULL, fn, NULL, 0, FILESIZE, 1, GNUNET_FS_DOWNLOAD_OPTION_NONE, "download", NULL); break; case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: consider_restart (event->status); printf ("Download complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024LL)); GNUNET_SCHEDULER_add_now (&abort_download_task, NULL); break; case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: consider_restart (event->status); GNUNET_assert (download == event->value.download.dc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.download.completed, (unsigned long long) event->value.download.size, event->value.download.specifics.progress.depth, (unsigned long long) event->value.download.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); GNUNET_break (0); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_DOWNLOAD_ERROR: FPRINTF (stderr, "Error downloading file: %s\n", event->value.download.specifics.error.message); GNUNET_SCHEDULER_add_now (&abort_download_task, NULL); break; case GNUNET_FS_STATUS_PUBLISH_SUSPEND: GNUNET_assert (event->value.publish.pc == publish); publish = NULL; break; case GNUNET_FS_STATUS_PUBLISH_RESUME: GNUNET_assert (NULL == publish); publish = event->value.publish.pc; break; case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download suspended.\n"); GNUNET_assert (event->value.download.dc == download); download = NULL; break; case GNUNET_FS_STATUS_DOWNLOAD_RESUME: GNUNET_assert (NULL == download); download = event->value.download.dc; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download resumed.\n"); break; case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: consider_restart (event->status); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download active.\n"); break; case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: consider_restart (event->status); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download inactive.\n"); break; case GNUNET_FS_STATUS_PUBLISH_START: GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); GNUNET_assert (NULL == event->value.publish.pctx); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_assert (publish == event->value.publish.pc); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (1 == event->value.publish.anonymity); GNUNET_FS_stop (fs); fs = NULL; break; case GNUNET_FS_STATUS_DOWNLOAD_START: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download started.\n"); consider_restart (event->status); GNUNET_assert (download == NULL); download = event->value.download.dc; GNUNET_assert (0 == strcmp ("download", event->value.download.cctx)); GNUNET_assert (NULL == event->value.download.pctx); GNUNET_assert (NULL != event->value.download.uri); GNUNET_assert (0 == strcmp (fn, event->value.download.filename)); GNUNET_assert (FILESIZE == event->value.download.size); GNUNET_assert (0 == event->value.download.completed); GNUNET_assert (1 == event->value.download.anonymity); break; case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: GNUNET_assert (download == event->value.download.dc); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); download = NULL; break; default: printf ("Unexpected event: %d\n", event->status); break; } return NULL; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar", }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi; size_t i; struct GNUNET_FS_BlockOptions bo; cfg = c; fs = GNUNET_FS_start (cfg, "test-fs-download-persistence", &progress_cb, NULL, GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi = GNUNET_FS_file_information_create_from_data (fs, "publish-context", FILESIZE, buf, kuri, meta, GNUNET_NO, &bo); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fi); timeout_kill = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_kill_task, NULL); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-download-persistence", "test_fs_download_data.conf", &run, NULL)) return 1; return err; } /* end of test_fs_download_persistence.c */ gnunet-0.10.1/src/fs/fs_publish_ublock.h0000644000175000017500000000627312225777503015101 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_publish_ublock.h * @brief publish a UBLOCK in GNUnet * @see https://gnunet.org/encoding and #2564 * @author Krista Bennett * @author Christian Grothoff */ #ifndef FS_PUBLISH_UBLOCK_H #define FS_PUBLISH_UBLOCK_H #include "gnunet_util_lib.h" #include "gnunet_datastore_service.h" #include "gnunet_fs_service.h" #include "gnunet_identity_service.h" /** * Decrypt the given UBlock, storing the result in output. * * @param input input data * @param input_len number of bytes in input * @param ns public key under which the UBlock was stored * @param label label under which the UBlock was stored * @param output where to write the result, has input_len bytes */ void GNUNET_FS_ublock_decrypt_ (const void *input, size_t input_len, const struct GNUNET_CRYPTO_EcdsaPublicKey *ns, const char *label, void *output); /** * Context for 'ublock_put_cont'. */ struct GNUNET_FS_PublishUblockContext; /** * Signature of a function called as the continuation of a UBlock * publication. * * @param cls closure * @param emsg error message, NULL on success */ typedef void (*GNUNET_FS_UBlockContinuation) (void *cls, const char *emsg); /** * Publish a UBlock. * * @param h handle to the file sharing subsystem * @param dsh datastore handle to use for storage operation * @param label identifier to use * @param ulabel update label to use, may be an empty string for none * @param ns namespace to publish in * @param meta metadata to use * @param uri URI to refer to in the UBlock * @param bo per-block options * @param options publication options * @param cont continuation * @param cont_cls closure for cont * @return NULL on error ('cont' will still be called) */ struct GNUNET_FS_PublishUblockContext * GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h, struct GNUNET_DATASTORE_Handle *dsh, const char *label, const char *ulabel, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_BlockOptions *bo, enum GNUNET_FS_PublishOptions options, GNUNET_FS_UBlockContinuation cont, void *cont_cls); /** * Abort UBlock publishing operation. * * @param uc operation to abort. */ void GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc); #endif gnunet-0.10.1/src/fs/fs_getopt.c0000644000175000017500000001470312255010511013344 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_getopt.c * @brief helper functions for command-line argument processing * @author Igor Wronsky, Christian Grothoff */ #include "platform.h" #include "gnunet_fs_service.h" #include "fs_api.h" /* ******************** command-line option parsing API ******************** */ /** * Command-line option parser function that allows the user * to specify one or more '-k' options with keywords. Each * specified keyword will be added to the URI. A pointer to * the URI must be passed as the "scls" argument. * * @param ctx command line processor context * @param scls must be of type "struct GNUNET_FS_Uri **" * @param option name of the option (typically 'k') * @param value command line argument given * @return GNUNET_OK on success */ int GNUNET_FS_getopt_set_keywords (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { struct GNUNET_FS_Uri **uri = scls; struct GNUNET_FS_Uri *u = *uri; char *val; size_t slen; if (u == NULL) { u = GNUNET_new (struct GNUNET_FS_Uri); *uri = u; u->type = GNUNET_FS_URI_KSK; u->data.ksk.keywordCount = 0; u->data.ksk.keywords = NULL; } else { GNUNET_assert (u->type == GNUNET_FS_URI_KSK); } slen = strlen (value); if (slen == 0) return GNUNET_SYSERR; /* cannot be empty */ if (value[0] == '+') { /* simply preserve the "mandatory" flag */ if (slen < 2) return GNUNET_SYSERR; /* empty keywords not allowed */ if ((value[1] == '"') && (slen > 3) && (value[slen - 1] == '"')) { /* remove the quotes, keep the '+' */ val = GNUNET_malloc (slen - 1); val[0] = '+'; memcpy (&val[1], &value[2], slen - 3); val[slen - 2] = '\0'; } else { /* no quotes, just keep the '+' */ val = GNUNET_strdup (value); } } else { if ((value[0] == '"') && (slen > 2) && (value[slen - 1] == '"')) { /* remove the quotes, add a space */ val = GNUNET_malloc (slen); val[0] = ' '; memcpy (&val[1], &value[1], slen - 2); val[slen - 1] = '\0'; } else { /* add a space to indicate "not mandatory" */ val = GNUNET_malloc (slen + 2); strcpy (val, " "); strcat (val, value); } } GNUNET_array_append (u->data.ksk.keywords, u->data.ksk.keywordCount, val); return GNUNET_OK; } /** * Command-line option parser function that allows the user to specify * one or more '-m' options with metadata. Each specified entry of * the form "type=value" will be added to the metadata. A pointer to * the metadata must be passed as the "scls" argument. * * @param ctx command line processor context * @param scls must be of type "struct GNUNET_MetaData **" * @param option name of the option (typically 'k') * @param value command line argument given * @return GNUNET_OK on success */ int GNUNET_FS_getopt_set_metadata (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, void *scls, const char *option, const char *value) { struct GNUNET_CONTAINER_MetaData **mm = scls; enum EXTRACTOR_MetaType type; const char *typename; const char *typename_i18n; struct GNUNET_CONTAINER_MetaData *meta; char *tmp; meta = *mm; if (meta == NULL) { meta = GNUNET_CONTAINER_meta_data_create (); *mm = meta; } /* Use GNUNET_STRINGS_get_utf8_args() in main() to acquire utf-8-encoded * commandline arguments, so that the following line is not needed. */ /*tmp = GNUNET_STRINGS_to_utf8 (value, strlen (value), locale_charset ());*/ tmp = GNUNET_strdup (value); type = EXTRACTOR_metatype_get_max (); while (type > 0) { type--; typename = EXTRACTOR_metatype_to_string (type); typename_i18n = dgettext (LIBEXTRACTOR_GETTEXT_DOMAIN, typename); if ((strlen (tmp) >= strlen (typename) + 1) && (tmp[strlen (typename)] == ':') && (0 == strncmp (typename, tmp, strlen (typename)))) { GNUNET_CONTAINER_meta_data_insert (meta, "", type, EXTRACTOR_METAFORMAT_UTF8, "text/plain", &tmp[strlen (typename) + 1], strlen (&tmp[strlen (typename) + 1]) + 1); GNUNET_free (tmp); tmp = NULL; break; } if ((strlen (tmp) >= strlen (typename_i18n) + 1) && (tmp[strlen (typename_i18n)] == ':') && (0 == strncmp (typename_i18n, tmp, strlen (typename_i18n)))) { GNUNET_CONTAINER_meta_data_insert (meta, "", type, EXTRACTOR_METAFORMAT_UTF8, "text/plain", &tmp[strlen (typename_i18n) + 1], strlen (&tmp [strlen (typename_i18n) + 1]) + 1); GNUNET_free (tmp); tmp = NULL; break; } } if (tmp != NULL) { GNUNET_CONTAINER_meta_data_insert (meta, "", EXTRACTOR_METATYPE_UNKNOWN, EXTRACTOR_METAFORMAT_UTF8, "text/plain", tmp, strlen (tmp) + 1); GNUNET_free (tmp); printf (_ ("Unknown metadata type in metadata option `%s'. Using metadata type `unknown' instead.\n"), value); } return GNUNET_OK; } /* end of fs_getopt.c */ gnunet-0.10.1/src/fs/test_fs_uri_data.conf0000644000175000017500000000017712225230043015375 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-uri/ [arm] DEFAULTSERVICES = topology hostlist gnunet-0.10.1/src/fs/Makefile.am0000644000175000017500000003716112320754752013264 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ fs.conf plugindir = $(libdir)/gnunet lib_LTLIBRARIES = libgnunetfs.la plugin_LTLIBRARIES = \ libgnunet_plugin_block_fs.la if HAVE_TESTING noinst_LIBRARIES = libgnunetfstest.a endif libgnunetfs_la_SOURCES = \ fs_api.c fs_api.h fs.h \ fs_directory.c \ fs_dirmetascan.c \ fs_download.c \ fs_file_information.c \ fs_getopt.c \ fs_list_indexed.c \ fs_publish.c \ fs_publish_ksk.c \ fs_publish_ublock.c fs_publish_ublock.h \ fs_misc.c \ fs_namespace.c \ fs_search.c \ fs_sharetree.c \ fs_tree.c fs_tree.h \ fs_unindex.c \ fs_uri.c libgnunetfs_la_LIBADD = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) $(LIBGCRYPT_LIBS) -lunistring -lextractor libgnunetfs_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 3:1:1 libgnunetfstest_a_SOURCES = \ fs_test_lib.c fs_test_lib.h libgnunetfstest_a_LIBADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la libexec_PROGRAMS = \ gnunet-helper-fs-publish \ gnunet-service-fs if HAVE_TESTING noinst_PROGRAMS = \ gnunet-fs-profiler \ gnunet-daemon-fsprofiler endif bin_PROGRAMS = \ gnunet-auto-share \ gnunet-directory \ gnunet-download \ gnunet-publish \ gnunet-search \ gnunet-fs \ gnunet-unindex bin_SCRIPTS = \ gnunet-download-manager.scm gnunet_directory_SOURCES = \ gnunet-directory.c gnunet_directory_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_directory_DEPENDENCIES = \ libgnunetfs.la gnunet_fs_profiler_SOURCES = \ gnunet-fs-profiler.c gnunet_fs_profiler_LDADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_fs_SOURCES = \ gnunet-fs.c gnunet_fs_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_fs_DEPENDENCIES = \ libgnunetfs.la gnunet_download_SOURCES = \ gnunet-download.c gnunet_download_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_download_DEPENDENCIES = \ libgnunetfs.la gnunet_publish_SOURCES = \ gnunet-publish.c gnunet_publish_LDADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_publish_DEPENDENCIES = \ libgnunetfs.la gnunet_auto_share_SOURCES = \ gnunet-auto-share.c gnunet_auto_share_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_auto_share_DEPENDENCIES = \ libgnunetfs.la gnunet_helper_fs_publish_SOURCES = \ gnunet-helper-fs-publish.c gnunet_helper_fs_publish_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_helper_fs_publish_DEPENDENCIES = \ libgnunetfs.la gnunet_search_SOURCES = \ gnunet-search.c gnunet_search_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ $(GN_LIBINTL) gnunet_search_DEPENDENCIES = \ libgnunetfs.la gnunet_daemon_fsprofiler_SOURCES = \ gnunet-daemon-fsprofiler.c gnunet_daemon_fsprofiler_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_daemon_fsprofiler_DEPENDENCIES = \ libgnunetfs.la gnunet_service_fs_SOURCES = \ gnunet-service-fs.c gnunet-service-fs.h \ gnunet-service-fs_cp.c gnunet-service-fs_cp.h \ gnunet-service-fs_indexing.c gnunet-service-fs_indexing.h \ gnunet-service-fs_lc.c gnunet-service-fs_lc.h \ gnunet-service-fs_pe.c gnunet-service-fs_pe.h \ gnunet-service-fs_pr.c gnunet-service-fs_pr.h \ gnunet-service-fs_push.c gnunet-service-fs_push.h \ gnunet-service-fs_put.c gnunet-service-fs_put.h \ gnunet-service-fs_mesh_client.c gnunet-service-fs_mesh.h \ gnunet-service-fs_mesh_server.c gnunet_service_fs_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) -lm gnunet_service_fs_DEPENDENCIES = \ libgnunetfs.la gnunet_unindex_SOURCES = \ gnunet-unindex.c gnunet_unindex_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_unindex_DEPENDENCIES = \ libgnunetfs.la libgnunet_plugin_block_fs_la_SOURCES = \ plugin_block_fs.c libgnunet_plugin_block_fs_la_LIBADD = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_fs_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_fs_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/block/libgnunetblock.la \ libgnunetfs.la if HAVE_BENCHMARKS FS_BENCHMARKS = \ perf_gnunet_service_fs_p2p \ perf_gnunet_service_fs_p2p_dht \ perf_gnunet_service_fs_p2p_index \ perf_gnunet_service_fs_p2p_respect endif if HAVE_TESTING check_PROGRAMS = \ test_plugin_block_fs \ test_fs_directory \ test_fs_download \ test_fs_download_mesh \ test_fs_download_indexed \ test_fs_download_persistence \ test_fs_file_information \ test_fs_getopt \ test_fs_list_indexed \ test_fs_namespace \ test_fs_namespace_list_updateable \ test_fs_publish \ test_fs_publish_persistence \ test_fs_search \ test_fs_search_probes \ test_fs_search_persistence \ test_fs_start_stop \ test_fs_test_lib \ test_fs_unindex \ test_fs_unindex_persistence \ test_fs_uri \ test_gnunet_service_fs_migration \ test_gnunet_service_fs_p2p \ test_gnunet_service_fs_p2p_mesh \ $(FS_BENCHMARKS) endif test_plugin_block_fs_SOURCES = \ test_plugin_block_fs.c test_plugin_block_fs_LDADD = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la if HAVE_PYTHON check_SCRIPTS = \ test_gnunet_fs_psd.py \ test_gnunet_fs_rec.py \ test_gnunet_fs_idx.py endif if ENABLE_MONKEY MONKEY = @MONKEYPREFIX@ AM_LDFLAGS = -no-install endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; $(MONKEY) TESTS = \ test_fs_directory \ test_fs_download \ test_fs_download_indexed \ test_fs_download_persistence \ test_fs_file_information \ test_fs_list_indexed \ test_fs_namespace \ test_fs_namespace_list_updateable \ test_fs_publish \ test_fs_publish_persistence \ test_fs_search \ test_fs_search_probes \ test_fs_search_persistence \ test_fs_start_stop \ test_fs_unindex \ test_fs_unindex_persistence \ test_fs_uri \ test_fs_test_lib \ test_gnunet_service_fs_migration \ test_gnunet_service_fs_p2p \ test_gnunet_service_fs_p2p_mesh \ perf_gnunet_service_fs_p2p \ perf_gnunet_service_fs_p2p_index \ perf_gnunet_service_fs_p2p_respect \ $(check_SCRIPTS) endif test_fs_directory_SOURCES = \ test_fs_directory.c test_fs_directory_LDADD = \ -lextractor \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_download_SOURCES = \ test_fs_download.c test_fs_download_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_download_indexed_SOURCES = \ test_fs_download.c test_fs_download_indexed_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_download_mesh_SOURCES = \ test_fs_download.c test_fs_download_mesh_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_download_persistence_SOURCES = \ test_fs_download_persistence.c test_fs_download_persistence_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_file_information_SOURCES = \ test_fs_file_information.c test_fs_file_information_LDADD = \ -lextractor \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_getopt_SOURCES = \ test_fs_getopt.c test_fs_getopt_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_list_indexed_SOURCES = \ test_fs_list_indexed.c test_fs_list_indexed_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_namespace_SOURCES = \ test_fs_namespace.c test_fs_namespace_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_namespace_list_updateable_SOURCES = \ test_fs_namespace_list_updateable.c test_fs_namespace_list_updateable_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_publish_SOURCES = \ test_fs_publish.c test_fs_publish_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_publish_persistence_SOURCES = \ test_fs_publish_persistence.c test_fs_publish_persistence_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_search_SOURCES = \ test_fs_search.c test_fs_search_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_search_probes_SOURCES = \ test_fs_search_probes.c test_fs_search_probes_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_search_persistence_SOURCES = \ test_fs_search_persistence.c test_fs_search_persistence_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_start_stop_SOURCES = \ test_fs_start_stop.c test_fs_start_stop_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_unindex_SOURCES = \ test_fs_unindex.c test_fs_unindex_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_unindex_persistence_SOURCES = \ test_fs_unindex_persistence.c test_fs_unindex_persistence_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_uri_SOURCES = \ test_fs_uri.c test_fs_uri_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_test_lib_SOURCES = \ test_fs_test_lib.c test_fs_test_lib_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_service_fs_p2p_SOURCES = \ test_gnunet_service_fs_p2p.c test_gnunet_service_fs_p2p_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_service_fs_p2p_mesh_SOURCES = \ test_gnunet_service_fs_p2p.c test_gnunet_service_fs_p2p_mesh_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_service_fs_migration_SOURCES = \ test_gnunet_service_fs_migration.c test_gnunet_service_fs_migration_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la perf_gnunet_service_fs_p2p_SOURCES = \ perf_gnunet_service_fs_p2p.c perf_gnunet_service_fs_p2p_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la perf_gnunet_service_fs_p2p_index_SOURCES = \ perf_gnunet_service_fs_p2p.c perf_gnunet_service_fs_p2p_index_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la perf_gnunet_service_fs_p2p_dht_SOURCES = \ perf_gnunet_service_fs_p2p.c perf_gnunet_service_fs_p2p_dht_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la perf_gnunet_service_fs_p2p_respect_SOURCES = \ perf_gnunet_service_fs_p2p_respect.c perf_gnunet_service_fs_p2p_respect_LDADD = \ $(top_builddir)/src/fs/libgnunetfstest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' test_gnunet_fs_psd.py: test_gnunet_fs_psd.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_fs_psd.py.in > test_gnunet_fs_psd.py chmod +x test_gnunet_fs_psd.py test_gnunet_fs_rec.py: test_gnunet_fs_rec.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_fs_rec.py.in > test_gnunet_fs_rec.py chmod +x test_gnunet_fs_rec.py test_gnunet_fs_ns.py: test_gnunet_fs_ns.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_fs_ns.py.in > test_gnunet_fs_ns.py chmod +x test_gnunet_fs_ns.py test_gnunet_fs_idx.py: test_gnunet_fs_idx.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_fs_idx.py.in > test_gnunet_fs_idx.py chmod +x test_gnunet_fs_idx.py EXTRA_DIST = \ test_fs_defaults.conf \ fs_test_lib_data.conf \ test_fs_data.conf \ test_fs_download_data.conf \ test_fs_download_indexed.conf \ test_fs_download_mesh.conf \ test_fs_file_information_data.conf \ fs_test_lib_data.conf \ test_fs_list_indexed_data.conf \ test_fs_namespace_data.conf \ test_fs_publish_data.conf \ test_fs_search_data.conf \ test_fs_unindex_data.conf \ test_fs_uri_data.conf \ test_gnunet_service_fs_migration_data.conf \ test_gnunet_service_fs_p2p_mesh.conf \ test_gnunet_fs_idx_data.conf \ test_gnunet_fs_psd_data.conf \ test_gnunet_fs_rec_data.conf \ perf_gnunet_service_fs_p2p.conf \ test_gnunet_fs_rec_data.tgz \ test_gnunet_fs_psd.py.in \ test_gnunet_fs_rec.py.in \ test_gnunet_fs_idx.py.in \ test_pseudonym_data.conf \ $(bin_SCRIPTS) CLEANFILES = $(check_SCRIPTS) gnunet-0.10.1/src/fs/test_plugin_block_fs.c0000644000175000017500000000460312225777502015570 00000000000000/* This file is part of GNUnet (C) 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_plugin_block_fs.c * @brief test for plugin_block_fs.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_block_lib.h" static int test_fs (struct GNUNET_BLOCK_Context *ctx) { struct GNUNET_HashCode key; char block[4]; memset (block, 1, sizeof (block)); if (GNUNET_OK != GNUNET_BLOCK_get_key (ctx, GNUNET_BLOCK_TYPE_FS_DBLOCK, block, sizeof (block), &key)) return 1; if (GNUNET_BLOCK_EVALUATION_OK_LAST != GNUNET_BLOCK_evaluate (ctx, GNUNET_BLOCK_TYPE_FS_DBLOCK, &key, NULL, 0, NULL, 0, block, sizeof (block))) return 2; if (GNUNET_BLOCK_EVALUATION_REQUEST_VALID != GNUNET_BLOCK_evaluate (ctx, GNUNET_BLOCK_TYPE_FS_DBLOCK, &key, NULL, 0, NULL, 0, NULL, 0)) return 4; GNUNET_log_skip (1, GNUNET_NO); if (GNUNET_BLOCK_EVALUATION_REQUEST_INVALID != GNUNET_BLOCK_evaluate (ctx, GNUNET_BLOCK_TYPE_FS_DBLOCK, &key, NULL, 0, "bogus", 5, NULL, 0)) return 8; GNUNET_log_skip (0, GNUNET_YES); return 0; } int main (int argc, char *argv[]) { int ret; struct GNUNET_BLOCK_Context *ctx; struct GNUNET_CONFIGURATION_Handle *cfg; GNUNET_log_setup ("test-block", "WARNING", NULL); cfg = GNUNET_CONFIGURATION_create (); ctx = GNUNET_BLOCK_context_create (cfg); ret = test_fs (ctx); GNUNET_BLOCK_context_destroy (ctx); GNUNET_CONFIGURATION_destroy (cfg); if (ret != 0) FPRINTF (stderr, "Tests failed: %d\n", ret); return ret; } /* end of test_plugin_block_fs.c */ gnunet-0.10.1/src/fs/fs_misc.c0000644000175000017500000001312612225777502013014 00000000000000/* This file is part of GNUnet. (C) 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_misc.c * @brief misc. functions related to file-sharing in general * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_fs_service.h" #include "fs_api.h" /** * Suggest a filename based on given metadata. * * @param md given meta data * @return NULL if meta data is useless for suggesting a filename */ char * GNUNET_FS_meta_data_suggest_filename (const struct GNUNET_CONTAINER_MetaData *md) { static const char *mimeMap[][2] = { {"application/bz2", ".bz2"}, {"application/gnunet-directory", ".gnd"}, {"application/java", ".class"}, {"application/msword", ".doc"}, {"application/ogg", ".ogg"}, {"application/pdf", ".pdf"}, {"application/pgp-keys", ".key"}, {"application/pgp-signature", ".pgp"}, {"application/postscript", ".ps"}, {"application/rar", ".rar"}, {"application/rtf", ".rtf"}, {"application/xml", ".xml"}, {"application/x-debian-package", ".deb"}, {"application/x-dvi", ".dvi"}, {"applixation/x-flac", ".flac"}, {"applixation/x-gzip", ".gz"}, {"application/x-java-archive", ".jar"}, {"application/x-java-vm", ".class"}, {"application/x-python-code", ".pyc"}, {"application/x-redhat-package-manager", ".rpm"}, {"application/x-rpm", ".rpm"}, {"application/x-tar", ".tar"}, {"application/x-tex-pk", ".pk"}, {"application/x-texinfo", ".texinfo"}, {"application/x-xcf", ".xcf"}, {"application/x-xfig", ".xfig"}, {"application/zip", ".zip"}, {"audio/midi", ".midi"}, {"audio/mpeg", ".mp3"}, {"audio/real", ".rm"}, {"audio/x-wav", ".wav"}, {"image/gif", ".gif"}, {"image/jpeg", ".jpg"}, {"image/pcx", ".pcx"}, {"image/png", ".png"}, {"image/tiff", ".tiff"}, {"image/x-ms-bmp", ".bmp"}, {"image/x-xpixmap", ".xpm"}, {"text/css", ".css"}, {"text/html", ".html"}, {"text/plain", ".txt"}, {"text/rtf", ".rtf"}, {"text/x-c++hdr", ".h++"}, {"text/x-c++src", ".c++"}, {"text/x-chdr", ".h"}, {"text/x-csrc", ".c"}, {"text/x-java", ".java"}, {"text/x-moc", ".moc"}, {"text/x-pascal", ".pas"}, {"text/x-perl", ".pl"}, {"text/x-python", ".py"}, {"text/x-tex", ".tex"}, {"video/avi", ".avi"}, {"video/mpeg", ".mpeg"}, {"video/quicktime", ".qt"}, {"video/real", ".rm"}, {"video/x-msvideo", ".avi"}, {NULL, NULL}, }; char *ret; unsigned int i; char *mime; char *base; const char *ext; ret = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); if (ret != NULL) return ret; ext = NULL; mime = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_MIMETYPE); if (mime != NULL) { i = 0; while ((mimeMap[i][0] != NULL) && (0 != strcmp (mime, mimeMap[i][0]))) i++; if (mimeMap[i][1] == NULL) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, _("Did not find mime type `%s' in extension list.\n"), mime); else ext = mimeMap[i][1]; GNUNET_free (mime); } base = GNUNET_CONTAINER_meta_data_get_first_by_types (md, EXTRACTOR_METATYPE_TITLE, EXTRACTOR_METATYPE_BOOK_TITLE, EXTRACTOR_METATYPE_ORIGINAL_TITLE, EXTRACTOR_METATYPE_PACKAGE_NAME, EXTRACTOR_METATYPE_URL, EXTRACTOR_METATYPE_URI, EXTRACTOR_METATYPE_DESCRIPTION, EXTRACTOR_METATYPE_ISRC, EXTRACTOR_METATYPE_JOURNAL_NAME, EXTRACTOR_METATYPE_AUTHOR_NAME, EXTRACTOR_METATYPE_SUBJECT, EXTRACTOR_METATYPE_ALBUM, EXTRACTOR_METATYPE_ARTIST, EXTRACTOR_METATYPE_KEYWORDS, EXTRACTOR_METATYPE_COMMENT, EXTRACTOR_METATYPE_UNKNOWN, -1); if ((base == NULL) && (ext == NULL)) return NULL; if (base == NULL) return GNUNET_strdup (ext); if (ext == NULL) return base; GNUNET_asprintf (&ret, "%s%s", base, ext); GNUNET_free (base); return ret; } /* end of fs_misc.c */ gnunet-0.10.1/src/fs/gnunet-publish.c0000644000175000017500000006213212226007340014321 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-publish.c * @brief publishing files on GNUnet * @author Christian Grothoff * @author Krista Bennett * @author James Blackwell * @author Igor Wronsky */ #include "platform.h" #include "gnunet_fs_service.h" #include "gnunet_identity_service.h" /** * Global return value from 'main'. */ static int ret = 1; /** * Command line option 'verbose' set */ static int verbose; /** * Handle to our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for interaction with file-sharing service. */ static struct GNUNET_FS_Handle *ctx; /** * Handle to FS-publishing operation. */ static struct GNUNET_FS_PublishContext *pc; /** * Meta-data provided via command-line option. */ static struct GNUNET_CONTAINER_MetaData *meta; /** * Keywords provided via command-line option. */ static struct GNUNET_FS_Uri *topKeywords; /** * Options we set for published blocks. */ static struct GNUNET_FS_BlockOptions bo = { {0LL}, 1, 365, 1 }; /** * Value of URI provided on command-line (when not publishing * a file but just creating UBlocks to refer to an existing URI). */ static char *uri_string; /** * Value of URI provided on command-line (when not publishing * a file but just creating UBlocks to refer to an existing URI); * parsed version of 'uri_string'. */ static struct GNUNET_FS_Uri *uri; /** * Command-line option for namespace publishing: identifier for updates * to this publication. */ static char *next_id; /** * Command-line option for namespace publishing: identifier for this * publication. */ static char *this_id; /** * Command-line option identifying the pseudonym to use for the publication. */ static char *pseudonym; /** * Command-line option for 'inserting' */ static int do_insert; /** * Command-line option to disable meta data extraction. */ static int disable_extractor; /** * Command-line option to merely simulate publishing operation. */ static int do_simulate; /** * Command-line option to only perform meta data extraction, but not publish. */ static int extract_only; /** * Command-line option to disable adding creation time. */ static int do_disable_creation_time; /** * Task run on CTRL-C to kill everything nicely. */ static GNUNET_SCHEDULER_TaskIdentifier kill_task; /** * Handle to the directory scanner (for recursive insertions). */ static struct GNUNET_FS_DirScanner *ds; /** * Which namespace do we publish to? NULL if we do not publish to * a namespace. */ static struct GNUNET_IDENTITY_Ego *namespace; /** * Handle to identity service. */ static struct GNUNET_IDENTITY_Handle *identity; /** * We are finished with the publishing operation, clean up all * FS state. * * @param cls NULL * @param tc scheduler context */ static void do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_PublishContext *p; kill_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != pc) { p = pc; pc = NULL; GNUNET_FS_publish_stop (p); } if (NULL != meta) { GNUNET_CONTAINER_meta_data_destroy (meta); meta = NULL; } } /** * Stop the directory scanner (we had an error). * * @param cls closure * @param tc scheduler context */ static void stop_scanner_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { kill_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != ds) { GNUNET_FS_directory_scan_abort (ds); ds = NULL; } if (NULL != identity) { GNUNET_IDENTITY_disconnect (identity); identity = NULL; } GNUNET_FS_stop (ctx); ctx = NULL; ret = 1; } /** * Called by FS client to give information about the progress of an * operation. * * @param cls closure * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the GNUNET_FS_ProgressInfo struct. */ static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { const char *s; char *suri; switch (info->status) { case GNUNET_FS_STATUS_PUBLISH_START: break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS: if (verbose) { s = GNUNET_STRINGS_relative_time_to_string (info->value.publish.eta, GNUNET_YES); FPRINTF (stdout, _("Publishing `%s' at %llu/%llu (%s remaining)\n"), info->value.publish.filename, (unsigned long long) info->value.publish.completed, (unsigned long long) info->value.publish.size, s); } break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: if (verbose) { s = GNUNET_STRINGS_relative_time_to_string (info->value.publish.specifics.progress_directory.eta, GNUNET_YES); FPRINTF (stdout, _("Publishing `%s' at %llu/%llu (%s remaining)\n"), info->value.publish.filename, (unsigned long long) info->value.publish.specifics.progress_directory.completed, (unsigned long long) info->value.publish.specifics.progress_directory.total, s); } break; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, _("Error publishing: %s.\n"), info->value.publish.specifics.error.message); if (kill_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (kill_task); kill_task = GNUNET_SCHEDULER_NO_TASK; } kill_task = GNUNET_SCHEDULER_add_now (&do_stop_task, NULL); break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: FPRINTF (stdout, _("Publishing `%s' done.\n"), info->value.publish.filename); suri = GNUNET_FS_uri_to_string (info->value.publish.specifics. completed.chk_uri); FPRINTF (stdout, _("URI is `%s'.\n"), suri); GNUNET_free (suri); if (NULL == info->value.publish.pctx) { if (GNUNET_SCHEDULER_NO_TASK != kill_task) { GNUNET_SCHEDULER_cancel (kill_task); kill_task = GNUNET_SCHEDULER_NO_TASK; } kill_task = GNUNET_SCHEDULER_add_now (&do_stop_task, NULL); } ret = 0; break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_break (NULL == pc); return NULL; case GNUNET_FS_STATUS_UNINDEX_PROGRESS: return NULL; case GNUNET_FS_STATUS_UNINDEX_COMPLETED: FPRINTF (stderr, "%s", _("Cleanup after abort complete.\n")); return NULL; default: FPRINTF (stderr, _("Unexpected status: %d\n"), info->status); return NULL; } return ""; /* non-null */ } /** * Print metadata entries (except binary * metadata and the filename). * * @param cls closure * @param plugin_name name of the plugin that generated the meta data * @param type type of the meta data * @param format format of data * @param data_mime_type mime type of data * @param data value of the meta data * @param data_size number of bytes in data * @return always 0 */ static int meta_printer (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size) { if ((EXTRACTOR_METAFORMAT_UTF8 != format) && (EXTRACTOR_METAFORMAT_C_STRING != format)) return 0; if (EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME == type) return 0; FPRINTF (stdout, "\t%s - %s\n", EXTRACTOR_metatype_to_string (type), data); return 0; } /** * Iterator printing keywords * * @param cls closure * @param keyword the keyword * @param is_mandatory is the keyword mandatory (in a search) * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR to abort */ static int keyword_printer (void *cls, const char *keyword, int is_mandatory) { FPRINTF (stdout, "\t%s\n", keyword); return GNUNET_OK; } /** * Function called on all entries before the publication. This is * where we perform modifications to the default based on command-line * options. * * @param cls closure * @param fi the entry in the publish-structure * @param length length of the file or directory * @param m metadata for the file or directory (can be modified) * @param uri pointer to the keywords that will be used for this entry (can be modified) * @param bo block options * @param do_index should we index? * @param client_info pointer to client context set upon creation (can be modified) * @return GNUNET_OK to continue, GNUNET_NO to remove * this entry from the directory, GNUNET_SYSERR * to abort the iteration */ static int publish_inspector (void *cls, struct GNUNET_FS_FileInformation *fi, uint64_t length, struct GNUNET_CONTAINER_MetaData *m, struct GNUNET_FS_Uri **uri, struct GNUNET_FS_BlockOptions *bo, int *do_index, void **client_info) { char *fn; char *fs; struct GNUNET_FS_Uri *new_uri; if (cls == fi) return GNUNET_OK; if ( (disable_extractor) && (NULL != *uri) ) { GNUNET_FS_uri_destroy (*uri); *uri = NULL; } if (NULL != topKeywords) { if (NULL != *uri) { new_uri = GNUNET_FS_uri_ksk_merge (topKeywords, *uri); GNUNET_FS_uri_destroy (*uri); *uri = new_uri; GNUNET_FS_uri_destroy (topKeywords); } else { *uri = topKeywords; } topKeywords = NULL; } if (NULL != meta) { GNUNET_CONTAINER_meta_data_merge (m, meta); GNUNET_CONTAINER_meta_data_destroy (meta); meta = NULL; } if (!do_disable_creation_time) GNUNET_CONTAINER_meta_data_add_publication_date (m); if (extract_only) { fn = GNUNET_CONTAINER_meta_data_get_by_type (m, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); fs = GNUNET_STRINGS_byte_size_fancy (length); FPRINTF (stdout, _("Meta data for file `%s' (%s)\n"), fn, fs); GNUNET_CONTAINER_meta_data_iterate (m, &meta_printer, NULL); FPRINTF (stdout, _("Keywords for file `%s' (%s)\n"), fn, fs); GNUNET_free (fn); GNUNET_free (fs); if (NULL != *uri) GNUNET_FS_uri_ksk_get_keywords (*uri, &keyword_printer, NULL); FPRINTF (stdout, "%s", "\n"); } if (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (m)) GNUNET_FS_file_information_inspect (fi, &publish_inspector, fi); return GNUNET_OK; } /** * Function called upon completion of the publishing * of the UBLOCK for the SKS URI. As this is the last * step, stop our interaction with FS (clean up). * * @param cls NULL (closure) * @param sks_uri URI for the block that was published * @param emsg error message, NULL on success */ static void uri_sks_continuation (void *cls, const struct GNUNET_FS_Uri *sks_uri, const char *emsg) { if (NULL != emsg) { FPRINTF (stderr, "%s\n", emsg); ret = 1; } GNUNET_FS_uri_destroy (uri); uri = NULL; GNUNET_FS_stop (ctx); ctx = NULL; } /** * Function called upon completion of the publishing * of the UBLOCK for the KSK URI. Continue with * publishing the SKS URI (if applicable) or clean up. * * @param cls NULL (closure) * @param ksk_uri URI for the block that was published * @param emsg error message, NULL on success */ static void uri_ksk_continuation (void *cls, const struct GNUNET_FS_Uri *ksk_uri, const char *emsg) { const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv; if (NULL != emsg) { FPRINTF (stderr, "%s\n", emsg); ret = 1; } if (NULL != namespace) { priv = GNUNET_IDENTITY_ego_get_private_key (namespace); GNUNET_FS_publish_sks (ctx, priv, this_id, next_id, meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &uri_sks_continuation, NULL); return; } GNUNET_FS_uri_destroy (uri); uri = NULL; GNUNET_FS_stop (ctx); ctx = NULL; } /** * Iterate over the results from the directory scan and extract * the desired information for the publishing operation. * * @param item root with the data from the directroy scan * @return handle with the information for the publishing operation */ static struct GNUNET_FS_FileInformation * get_file_information (struct GNUNET_FS_ShareTreeItem *item) { struct GNUNET_FS_FileInformation *fi; struct GNUNET_FS_FileInformation *fic; struct GNUNET_FS_ShareTreeItem *child; if (GNUNET_YES == item->is_directory) { GNUNET_CONTAINER_meta_data_delete (item->meta, EXTRACTOR_METATYPE_MIMETYPE, NULL, 0); GNUNET_FS_meta_data_make_directory (item->meta); if (NULL == item->ksk_uri) { const char *mime = GNUNET_FS_DIRECTORY_MIME; item->ksk_uri = GNUNET_FS_uri_ksk_create_from_args (1, &mime); } else GNUNET_FS_uri_ksk_add_keyword (item->ksk_uri, GNUNET_FS_DIRECTORY_MIME, GNUNET_NO); fi = GNUNET_FS_file_information_create_empty_directory (ctx, NULL, item->ksk_uri, item->meta, &bo, item->filename); for (child = item->children_head; child; child = child->next) { fic = get_file_information (child); GNUNET_break (GNUNET_OK == GNUNET_FS_file_information_add (fi, fic)); } } else { fi = GNUNET_FS_file_information_create_from_file (ctx, NULL, item->filename, item->ksk_uri, item->meta, !do_insert, &bo); } return fi; } /** * We've finished scanning the directory and optimized the meta data. * Begin the publication process. * * @param directory_scan_result result from the directory scan, freed in this function */ static void directory_trim_complete (struct GNUNET_FS_ShareTreeItem *directory_scan_result) { struct GNUNET_FS_FileInformation *fi; const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv; fi = get_file_information (directory_scan_result); GNUNET_FS_share_tree_free (directory_scan_result); if (NULL == fi) { FPRINTF (stderr, "%s", _("Could not publish\n")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } GNUNET_FS_file_information_inspect (fi, &publish_inspector, NULL); if (extract_only) { GNUNET_FS_file_information_destroy (fi, NULL, NULL); GNUNET_SCHEDULER_shutdown (); return; } if (NULL == namespace) priv = NULL; else priv = GNUNET_IDENTITY_ego_get_private_key (namespace); pc = GNUNET_FS_publish_start (ctx, fi, priv, this_id, next_id, (do_simulate) ? GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY : GNUNET_FS_PUBLISH_OPTION_NONE); if (NULL == pc) { FPRINTF (stderr, "%s", _("Could not start publishing.\n")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } } /** * Function called by the directory scanner as we build the tree * that we will need to publish later. * * @param cls closure * @param filename which file we are making progress on * @param is_directory GNUNET_YES if this is a directory, * GNUNET_NO if this is a file * GNUNET_SYSERR if it is neither (or unknown) * @param reason kind of progress we are making */ static void directory_scan_cb (void *cls, const char *filename, int is_directory, enum GNUNET_FS_DirScannerProgressUpdateReason reason) { struct GNUNET_FS_ShareTreeItem *directory_scan_result; switch (reason) { case GNUNET_FS_DIRSCANNER_FILE_START: if (verbose > 1) { if (is_directory == GNUNET_YES) FPRINTF (stdout, _("Scanning directory `%s'.\n"), filename); else FPRINTF (stdout, _("Scanning file `%s'.\n"), filename); } break; case GNUNET_FS_DIRSCANNER_FILE_IGNORED: FPRINTF (stderr, _("There was trouble processing file `%s', skipping it.\n"), filename); break; case GNUNET_FS_DIRSCANNER_ALL_COUNTED: if (verbose) FPRINTF (stdout, "%s", _("Preprocessing complete.\n")); break; case GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED: if (verbose > 2) FPRINTF (stdout, _("Extracting meta data from file `%s' complete.\n"), filename); break; case GNUNET_FS_DIRSCANNER_FINISHED: if (verbose > 1) FPRINTF (stdout, "%s", _("Meta data extraction has finished.\n")); directory_scan_result = GNUNET_FS_directory_scan_get_result (ds); ds = NULL; GNUNET_FS_share_tree_trim (directory_scan_result); directory_trim_complete (directory_scan_result); break; case GNUNET_FS_DIRSCANNER_INTERNAL_ERROR: FPRINTF (stdout, "%s", _("Internal error scanning directory.\n")); if (kill_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (kill_task); kill_task = GNUNET_SCHEDULER_NO_TASK; } kill_task = GNUNET_SCHEDULER_add_now (&stop_scanner_task, NULL); break; default: GNUNET_assert (0); break; } fflush (stdout); } /** * Continuation proceeding with initialization after identity subsystem * has been initialized. * * @param args0 filename to publish */ static void identity_continuation (const char *args0) { char *ex; char *emsg; if ( (NULL != pseudonym) && (NULL == namespace) ) { FPRINTF (stderr, _("Selected pseudonym `%s' unknown\n"), pseudonym); GNUNET_SCHEDULER_shutdown (); return; } if (NULL != uri_string) { emsg = NULL; if (NULL == (uri = GNUNET_FS_uri_parse (uri_string, &emsg))) { FPRINTF (stderr, _("Failed to parse URI: %s\n"), emsg); GNUNET_free (emsg); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } GNUNET_FS_publish_ksk (ctx, topKeywords, meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &uri_ksk_continuation, NULL); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "FS", "EXTRACTORS", &ex)) ex = NULL; if (0 != ACCESS (args0, R_OK)) { FPRINTF (stderr, _("Failed to access `%s': %s\n"), args0, STRERROR (errno)); GNUNET_free_non_null (ex); return; } ds = GNUNET_FS_directory_scan_start (args0, disable_extractor, ex, &directory_scan_cb, NULL); if (NULL == ds) { FPRINTF (stderr, "%s", _("Failed to start meta directory scanner. Is gnunet-helper-publish-fs installed?\n")); GNUNET_free_non_null (ex); return; } GNUNET_free_non_null (ex); } /** * Function called by identity service with known pseudonyms. * * @param cls closure with 'const char *' of filename to publish * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { const char *args0 = cls; if (NULL == ego) { identity_continuation (args0); return; } if (0 == strcmp (name, pseudonym)) namespace = ego; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { /* check arguments */ if ((NULL != uri_string) && (extract_only)) { printf (_("Cannot extract metadata from a URI!\n")); ret = -1; return; } if (((NULL == uri_string) || (extract_only)) && ((NULL == args[0]) || (NULL != args[1]))) { printf (_("You must specify one and only one filename for insertion.\n")); ret = -1; return; } if ((NULL != uri_string) && (NULL != args[0])) { printf (_("You must NOT specify an URI and a filename.\n")); ret = -1; return; } if (NULL != pseudonym) { if (NULL == this_id) { FPRINTF (stderr, _("Option `%s' is required when using option `%s'.\n"), "-t", "-P"); ret = -1; return; } } else { /* ordinary insertion checks */ if (NULL != next_id) { FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"), "-N", "-P"); ret = -1; return; } if (NULL != this_id) { FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"), "-t", "-P"); ret = -1; return; } } cfg = c; ctx = GNUNET_FS_start (cfg, "gnunet-publish", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); if (NULL == ctx) { FPRINTF (stderr, _("Could not initialize `%s' subsystem.\n"), "FS"); ret = 1; return; } kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task, NULL); if (NULL != pseudonym) identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, args[0]); else identity_continuation (args[0]); } /** * The main function to publish content to GNUnet. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'a', "anonymity", "LEVEL", gettext_noop ("set the desired LEVEL of sender-anonymity"), 1, &GNUNET_GETOPT_set_uint, &bo.anonymity_level}, {'d', "disable-creation-time", NULL, gettext_noop ("disable adding the creation time to the metadata of the uploaded file"), 0, &GNUNET_GETOPT_set_one, &do_disable_creation_time}, {'D', "disable-extractor", NULL, gettext_noop ("do not use libextractor to add keywords or metadata"), 0, &GNUNET_GETOPT_set_one, &disable_extractor}, {'e', "extract", NULL, gettext_noop ("print list of extracted keywords that would be used, but do not perform upload"), 0, &GNUNET_GETOPT_set_one, &extract_only}, {'k', "key", "KEYWORD", gettext_noop ("add an additional keyword for the top-level file or directory" " (this option can be specified multiple times)"), 1, &GNUNET_FS_getopt_set_keywords, &topKeywords}, {'m', "meta", "TYPE:VALUE", gettext_noop ("set the meta-data for the given TYPE to the given VALUE"), 1, &GNUNET_FS_getopt_set_metadata, &meta}, {'n', "noindex", NULL, gettext_noop ("do not index, perform full insertion (stores entire " "file in encrypted form in GNUnet database)"), 0, &GNUNET_GETOPT_set_one, &do_insert}, {'N', "next", "ID", gettext_noop ("specify ID of an updated version to be published in the future" " (for namespace insertions only)"), 1, &GNUNET_GETOPT_set_string, &next_id}, {'p', "priority", "PRIORITY", gettext_noop ("specify the priority of the content"), 1, &GNUNET_GETOPT_set_uint, &bo.content_priority}, {'P', "pseudonym", "NAME", gettext_noop ("publish the files under the pseudonym NAME (place file into namespace)"), 1, &GNUNET_GETOPT_set_string, &pseudonym}, {'r', "replication", "LEVEL", gettext_noop ("set the desired replication LEVEL"), 1, &GNUNET_GETOPT_set_uint, &bo.replication_level}, {'s', "simulate-only", NULL, gettext_noop ("only simulate the process but do not do any " "actual publishing (useful to compute URIs)"), 0, &GNUNET_GETOPT_set_one, &do_simulate}, {'t', "this", "ID", gettext_noop ("set the ID of this version of the publication" " (for namespace insertions only)"), 1, &GNUNET_GETOPT_set_string, &this_id}, {'u', "uri", "URI", gettext_noop ("URI to be published (can be used instead of passing a " "file to add keywords to the file with the respective URI)"), 1, &GNUNET_GETOPT_set_string, &uri_string}, {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_set_one, &verbose}, GNUNET_GETOPT_OPTION_END }; bo.expiration_time = GNUNET_TIME_year_to_time (GNUNET_TIME_get_current_year () + 2); if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-publish [OPTIONS] FILENAME", gettext_noop ("Publish a file or directory on GNUnet"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-publish.c */ gnunet-0.10.1/src/fs/fs_directory.c0000644000175000017500000004330212274646702014065 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_directory.c * @brief Helper functions for building directories. * @author Christian Grothoff * * TODO: * - modify directory builder API to support incremental * generation of directories (to allow directories that * would not fit into memory to be created) * - modify directory processor API to support incremental * iteration over FULL directories (without missing entries) * to allow access to directories that do not fit entirely * into memory */ #include "platform.h" #include "gnunet_fs_service.h" #include "fs_api.h" /** * String that is used to indicate that a file * is a GNUnet directory. */ #define GNUNET_DIRECTORY_MAGIC "\211GND\r\n\032\n" /** * Does the meta-data claim that this is a directory? * Checks if the mime-type is that of a GNUnet directory. * * @return #GNUNET_YES if it is, #GNUNET_NO if it is not, #GNUNET_SYSERR if * we have no mime-type information (treat as #GNUNET_NO) */ int GNUNET_FS_meta_data_test_for_directory (const struct GNUNET_CONTAINER_MetaData *md) { char *mime; int ret; if (NULL == md) return GNUNET_SYSERR; mime = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_MIMETYPE); if (NULL == mime) return GNUNET_SYSERR; ret = (0 == strcasecmp (mime, GNUNET_FS_DIRECTORY_MIME)) ? GNUNET_YES : GNUNET_NO; GNUNET_free (mime); return ret; } /** * Set the MIMETYPE information for the given * metadata to "application/gnunet-directory". * * @param md metadata to add mimetype to */ void GNUNET_FS_meta_data_make_directory (struct GNUNET_CONTAINER_MetaData *md) { char *mime; mime = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_MIMETYPE); if (mime != NULL) { GNUNET_break (0 == strcmp (mime, GNUNET_FS_DIRECTORY_MIME)); GNUNET_free (mime); return; } GNUNET_CONTAINER_meta_data_insert (md, "", EXTRACTOR_METATYPE_MIMETYPE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", GNUNET_FS_DIRECTORY_MIME, strlen (GNUNET_FS_DIRECTORY_MIME) + 1); } /** * Closure for 'find_full_data'. */ struct GetFullDataClosure { /** * Extracted binary meta data. */ void *data; /** * Number of bytes stored in data. */ size_t size; }; /** * Type of a function that libextractor calls for each * meta data item found. * * @param cls closure (user-defined) * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_len number of bytes in data * @return 0 to continue extracting, 1 to abort */ static int find_full_data (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len) { struct GetFullDataClosure *gfdc = cls; if (type == EXTRACTOR_METATYPE_GNUNET_FULL_DATA) { gfdc->size = data_len; if (data_len > 0) { gfdc->data = GNUNET_malloc (data_len); memcpy (gfdc->data, data, data_len); } return 1; } return 0; } /** * Iterate over all entries in a directory. Note that directories * are structured such that it is possible to iterate over the * individual blocks as well as over the entire directory. Thus * a client can call this function on the buffer in the * GNUNET_FS_ProgressCallback. Also, directories can optionally * include the contents of (small) files embedded in the directory * itself; for those files, the processor may be given the * contents of the file directly by this function. *

* * Note that this function maybe called on parts of directories. Thus * parser errors should not be reported _at all_ (with GNUNET_break). * Still, if some entries can be recovered despite these parsing * errors, the function should try to do this. * * @param size number of bytes in data * @param data pointer to the beginning of the directory * @param offset offset of data in the directory * @param dep function to call on each entry * @param dep_cls closure for dep * @return GNUNET_OK if this could be a block in a directory, * GNUNET_NO if this could be part of a directory (but not 100% OK) * GNUNET_SYSERR if 'data' does not represent a directory */ int GNUNET_FS_directory_list_contents (size_t size, const void *data, uint64_t offset, GNUNET_FS_DirectoryEntryProcessor dep, void *dep_cls) { struct GetFullDataClosure full_data; const char *cdata = data; char *emsg; uint64_t pos; uint64_t align; uint32_t mdSize; uint64_t epos; struct GNUNET_FS_Uri *uri; struct GNUNET_CONTAINER_MetaData *md; char *filename; if ((offset == 0) && ((size < 8 + sizeof (uint32_t)) || (0 != memcmp (cdata, GNUNET_FS_DIRECTORY_MAGIC, 8)))) return GNUNET_SYSERR; pos = offset; if (offset == 0) { memcpy (&mdSize, &cdata[8], sizeof (uint32_t)); mdSize = ntohl (mdSize); if (mdSize > size - 8 - sizeof (uint32_t)) { /* invalid size */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("MAGIC mismatch. This is not a GNUnet directory.\n")); return GNUNET_SYSERR; } md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[8 + sizeof (uint32_t)], mdSize); if (md == NULL) { GNUNET_break (0); return GNUNET_SYSERR; /* malformed ! */ } dep (dep_cls, NULL, NULL, md, 0, NULL); GNUNET_CONTAINER_meta_data_destroy (md); pos = 8 + sizeof (uint32_t) + mdSize; } while (pos < size) { /* find end of URI */ if (cdata[pos] == '\0') { /* URI is never empty, must be end of block, * skip to next alignment */ align = ((pos / DBLOCK_SIZE) + 1) * DBLOCK_SIZE; if (align == pos) { /* if we were already aligned, still skip a block! */ align += DBLOCK_SIZE; } pos = align; if (pos >= size) { /* malformed - or partial download... */ break; } } epos = pos; while ((epos < size) && (cdata[epos] != '\0')) epos++; if (epos >= size) return GNUNET_NO; /* malformed - or partial download */ uri = GNUNET_FS_uri_parse (&cdata[pos], &emsg); pos = epos + 1; if (uri == NULL) { GNUNET_free (emsg); pos--; /* go back to '\0' to force going to next alignment */ continue; } if (GNUNET_FS_uri_test_ksk (uri)) { GNUNET_FS_uri_destroy (uri); GNUNET_break (0); return GNUNET_NO; /* illegal in directory! */ } memcpy (&mdSize, &cdata[pos], sizeof (uint32_t)); mdSize = ntohl (mdSize); pos += sizeof (uint32_t); if (pos + mdSize > size) { GNUNET_FS_uri_destroy (uri); return GNUNET_NO; /* malformed - or partial download */ } md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[pos], mdSize); if (md == NULL) { GNUNET_FS_uri_destroy (uri); GNUNET_break (0); return GNUNET_NO; /* malformed ! */ } pos += mdSize; filename = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); full_data.size = 0; full_data.data = NULL; GNUNET_CONTAINER_meta_data_iterate (md, &find_full_data, &full_data); if (dep != NULL) { dep (dep_cls, filename, uri, md, full_data.size, full_data.data); } GNUNET_free_non_null (full_data.data); GNUNET_free_non_null (filename); GNUNET_CONTAINER_meta_data_destroy (md); GNUNET_FS_uri_destroy (uri); } return GNUNET_OK; } /** * Entries in the directory (builder). */ struct BuilderEntry { /** * This is a linked list. */ struct BuilderEntry *next; /** * Length of this entry. */ size_t len; }; /** * Internal state of a directory builder. */ struct GNUNET_FS_DirectoryBuilder { /** * Meta-data for the directory itself. */ struct GNUNET_CONTAINER_MetaData *meta; /** * Head of linked list of entries. */ struct BuilderEntry *head; /** * Number of entires in the directory. */ unsigned int count; }; /** * Create a directory builder. * * @param mdir metadata for the directory */ struct GNUNET_FS_DirectoryBuilder * GNUNET_FS_directory_builder_create (const struct GNUNET_CONTAINER_MetaData *mdir) { struct GNUNET_FS_DirectoryBuilder *ret; ret = GNUNET_new (struct GNUNET_FS_DirectoryBuilder); if (mdir != NULL) ret->meta = GNUNET_CONTAINER_meta_data_duplicate (mdir); else ret->meta = GNUNET_CONTAINER_meta_data_create (); GNUNET_FS_meta_data_make_directory (ret->meta); return ret; } /** * Add an entry to a directory. * * @param bld directory to extend * @param uri uri of the entry (must not be a KSK) * @param md metadata of the entry * @param data raw data of the entry, can be NULL, otherwise * data must point to exactly the number of bytes specified * by the uri which must be of type LOC or CHK */ void GNUNET_FS_directory_builder_add (struct GNUNET_FS_DirectoryBuilder *bld, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *md, const void *data) { struct GNUNET_FS_Uri *curi; struct BuilderEntry *e; uint64_t fsize; uint32_t big; ssize_t ret; size_t mds; size_t mdxs; char *uris; char *ser; char *sptr; size_t slen; struct GNUNET_CONTAINER_MetaData *meta; const struct GNUNET_CONTAINER_MetaData *meta_use; GNUNET_assert (!GNUNET_FS_uri_test_ksk (uri)); if (NULL != data) { GNUNET_assert (!GNUNET_FS_uri_test_sks (uri)); if (GNUNET_FS_uri_test_chk (uri)) { fsize = GNUNET_FS_uri_chk_get_file_size (uri); } else { curi = GNUNET_FS_uri_loc_get_uri (uri); GNUNET_assert (NULL != curi); fsize = GNUNET_FS_uri_chk_get_file_size (curi); GNUNET_FS_uri_destroy (curi); } } else { fsize = 0; /* not given */ } if (fsize > MAX_INLINE_SIZE) fsize = 0; /* too large */ uris = GNUNET_FS_uri_to_string (uri); slen = strlen (uris) + 1; mds = GNUNET_CONTAINER_meta_data_get_serialized_size (md); meta_use = md; meta = NULL; if (fsize > 0) { meta = GNUNET_CONTAINER_meta_data_duplicate (md); GNUNET_CONTAINER_meta_data_insert (meta, "", EXTRACTOR_METATYPE_GNUNET_FULL_DATA, EXTRACTOR_METAFORMAT_BINARY, NULL, data, fsize); mdxs = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); if ((slen + sizeof (uint32_t) + mdxs - 1) / DBLOCK_SIZE == (slen + sizeof (uint32_t) + mds - 1) / DBLOCK_SIZE) { /* adding full data would not cause us to cross * additional blocks, so add it! */ meta_use = meta; mds = mdxs; } } if (mds > GNUNET_MAX_MALLOC_CHECKED / 2) mds = GNUNET_MAX_MALLOC_CHECKED / 2; e = GNUNET_malloc (sizeof (struct BuilderEntry) + slen + mds + sizeof (uint32_t)); ser = (char *) &e[1]; memcpy (ser, uris, slen); GNUNET_free (uris); sptr = &ser[slen + sizeof (uint32_t)]; ret = GNUNET_CONTAINER_meta_data_serialize (meta_use, &sptr, mds, GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); if (NULL != meta) GNUNET_CONTAINER_meta_data_destroy (meta); if (ret == -1) mds = 0; else mds = ret; big = htonl (mds); memcpy (&ser[slen], &big, sizeof (uint32_t)); e->len = slen + sizeof (uint32_t) + mds; e->next = bld->head; bld->head = e; bld->count++; } /** * Given the start and end position of a block of * data, return the end position of that data * after alignment to the DBLOCK_SIZE. */ static size_t do_align (size_t start_position, size_t end_position) { size_t align; align = (end_position / DBLOCK_SIZE) * DBLOCK_SIZE; if ((start_position < align) && (end_position > align)) return align + end_position - start_position; return end_position; } /** * Compute a permuation of the blocks to * minimize the cost of alignment. Greedy packer. * * @param start starting position for the first block * @param count size of the two arrays * @param sizes the sizes of the individual blocks * @param perm the permutation of the blocks (updated) */ static void block_align (size_t start, unsigned int count, const size_t * sizes, unsigned int *perm) { unsigned int i; unsigned int j; unsigned int tmp; unsigned int best; ssize_t badness; size_t cpos; size_t cend; ssize_t cbad; unsigned int cval; cpos = start; for (i = 0; i < count; i++) { start = cpos; badness = 0x7FFFFFFF; best = -1; for (j = i; j < count; j++) { cval = perm[j]; cend = cpos + sizes[cval]; if (cpos % DBLOCK_SIZE == 0) { /* prefer placing the largest blocks first */ cbad = -(cend % DBLOCK_SIZE); } else { if (cpos / DBLOCK_SIZE == cend / DBLOCK_SIZE) { /* Data fits into the same block! Prefer small left-overs! */ cbad = DBLOCK_SIZE - cend % DBLOCK_SIZE; } else { /* Would have to waste space to re-align, add big factor, this * case is a real loss (proportional to space wasted)! */ cbad = DBLOCK_SIZE * (DBLOCK_SIZE - cpos % DBLOCK_SIZE); } } if (cbad < badness) { best = j; badness = cbad; } } GNUNET_assert (best != -1); tmp = perm[i]; perm[i] = perm[best]; perm[best] = tmp; cpos += sizes[perm[i]]; cpos = do_align (start, cpos); } } /** * Finish building the directory. Frees the * builder context and returns the directory * in-memory. * * @param bld directory to finish * @param rsize set to the number of bytes needed * @param rdata set to the encoded directory * @return GNUNET_OK on success */ int GNUNET_FS_directory_builder_finish (struct GNUNET_FS_DirectoryBuilder *bld, size_t * rsize, void **rdata) { char *data; char *sptr; size_t *sizes; unsigned int *perm; unsigned int i; unsigned int j; struct BuilderEntry *pos; struct BuilderEntry **bes; size_t size; size_t psize; size_t off; ssize_t ret; uint32_t big; size = strlen (GNUNET_DIRECTORY_MAGIC) + sizeof (uint32_t); size += GNUNET_CONTAINER_meta_data_get_serialized_size (bld->meta); sizes = NULL; perm = NULL; bes = NULL; if (0 < bld->count) { sizes = GNUNET_malloc (bld->count * sizeof (size_t)); perm = GNUNET_malloc (bld->count * sizeof (unsigned int)); bes = GNUNET_malloc (bld->count * sizeof (struct BuilderEntry *)); pos = bld->head; for (i = 0; i < bld->count; i++) { perm[i] = i; bes[i] = pos; sizes[i] = pos->len; pos = pos->next; } block_align (size, bld->count, sizes, perm); /* compute final size with alignment */ for (i = 0; i < bld->count; i++) { psize = size; size += sizes[perm[i]]; size = do_align (psize, size); } } *rsize = size; data = GNUNET_malloc_large (size); if (data == NULL) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "malloc"); *rsize = 0; *rdata = NULL; GNUNET_free_non_null (sizes); GNUNET_free_non_null (perm); GNUNET_free_non_null (bes); return GNUNET_SYSERR; } *rdata = data; memcpy (data, GNUNET_DIRECTORY_MAGIC, strlen (GNUNET_DIRECTORY_MAGIC)); off = strlen (GNUNET_DIRECTORY_MAGIC); sptr = &data[off + sizeof (uint32_t)]; ret = GNUNET_CONTAINER_meta_data_serialize (bld->meta, &sptr, size - off - sizeof (uint32_t), GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); GNUNET_assert (ret != -1); big = htonl (ret); memcpy (&data[off], &big, sizeof (uint32_t)); off += sizeof (uint32_t) + ret; for (j = 0; j < bld->count; j++) { i = perm[j]; psize = off; off += sizes[i]; off = do_align (psize, off); memcpy (&data[off - sizes[i]], &(bes[i])[1], sizes[i]); GNUNET_free (bes[i]); } GNUNET_free_non_null (sizes); GNUNET_free_non_null (perm); GNUNET_free_non_null (bes); GNUNET_assert (off == size); GNUNET_CONTAINER_meta_data_destroy (bld->meta); GNUNET_free (bld); return GNUNET_OK; } /* end of fs_directory.c */ gnunet-0.10.1/src/fs/test_fs_test_lib.c0000644000175000017500000001031112225777502014716 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_test_lib.c * @brief test fs test library * @author Christian Grothoff */ #include "platform.h" #include "fs_test_lib.h" #define VERBOSE GNUNET_NO /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 2) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) #define NUM_DAEMONS 2 #define SEED 42 static struct GNUNET_TESTBED_Peer *the_peers[NUM_DAEMONS]; static int ret; static void do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { char *fn = cls; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { GNUNET_break (0); ret = 1; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished download, shutting down\n", (unsigned long long) FILESIZE); } if (NULL != fn) { GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); } GNUNET_SCHEDULER_shutdown (); } static void do_download (void *cls, const struct GNUNET_FS_Uri *uri, const char *fn) { if (NULL == uri) { GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Downloading %llu bytes\n", (unsigned long long) FILESIZE); GNUNET_FS_TEST_download (the_peers[0], TIMEOUT, 1, SEED, uri, VERBOSE, &do_stop, (NULL == fn) ? NULL : GNUNET_strdup (fn)); } static void do_publish (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { GNUNET_TESTBED_operation_done (op); if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect peers: %s\n", emsg); GNUNET_break (0); ret = 1; GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing %llu bytes\n", (unsigned long long) FILESIZE); GNUNET_FS_TEST_publish (the_peers[0], TIMEOUT, 1, GNUNET_NO, FILESIZE, SEED, VERBOSE, &do_download, NULL); } /** * Actual main function for the test. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { unsigned int i; GNUNET_assert (NUM_DAEMONS == num_peers); for (i=0;ireason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { del = GNUNET_TIME_absolute_get_duration (start_time); if (del.rel_value_us == 0) del.rel_value_us = 1; fancy = GNUNET_STRINGS_byte_size_fancy (((unsigned long long) FILESIZE) * 1000000LL / del.rel_value_us); FPRINTF (stdout, "Download speed was %s/s\n", fancy); GNUNET_free (fancy); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished download, shutting down\n", (unsigned long long) FILESIZE); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout during download, shutting down with error\n"); ok = 1; } if (NULL != fn) { GNUNET_DISK_directory_remove (fn); GNUNET_free (fn); } } static void do_download (void *cls, const struct GNUNET_FS_Uri *uri, const char *fn) { if (NULL == uri) { GNUNET_SCHEDULER_shutdown (); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout during upload attempt, shutting down with error\n"); ok = 1; return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Downloading %llu bytes\n", (unsigned long long) FILESIZE); start_time = GNUNET_TIME_absolute_get (); GNUNET_FS_TEST_download (daemons[0], TIMEOUT, anonymity_level, SEED, uri, VERBOSE, &do_stop, (NULL == fn) ? NULL : GNUNET_strdup (fn)); } static void do_publish (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { unsigned int i; if (NULL != strstr (progname, "mesh")) anonymity_level = 0; else anonymity_level = 1; GNUNET_assert (NUM_DAEMONS == num_peers); for (i=0;i 0. A depth of 1 means only a DBLOCK. */ unsigned int GNUNET_FS_compute_depth (uint64_t flen); /** * Calculate how many bytes of payload a block tree of the given * depth MAY correspond to at most (this function ignores the fact that * some blocks will only be present partially due to the total file * size cutting some blocks off at the end). * * @param depth depth of the block. depth==0 is a DBLOCK. * @return number of bytes of payload a subtree of this depth may correspond to */ uint64_t GNUNET_FS_tree_compute_tree_size (unsigned int depth); /** * Compute how many bytes of data should be stored in * the specified block. * * @param fsize overall file size, must be > 0. * @param offset offset in the original data corresponding * to the beginning of the tree induced by the block; * must be < fsize * @param depth depth of the node in the tree, 0 for DBLOCK * @return number of bytes stored in this node */ size_t GNUNET_FS_tree_calculate_block_size (uint64_t fsize, uint64_t offset, unsigned int depth); /** * Context for an ECRS-based file encoder that computes * the Merkle-ish-CHK tree. */ struct GNUNET_FS_TreeEncoder; /** * Function called asking for the current (encoded) * block to be processed. After processing the * client should either call "GNUNET_FS_tree_encode_next" * or (on error) "GNUNET_FS_tree_encode_finish". * * @param cls closure * @param chk content hash key for the block * @param offset offset of the block * @param depth depth of the block, 0 for DBLOCKs * @param type type of the block (IBLOCK or DBLOCK) * @param block the (encrypted) block * @param block_size size of block (in bytes) */ typedef void (*GNUNET_FS_TreeBlockProcessor) (void *cls, const struct ContentHashKey * chk, uint64_t offset, unsigned int depth, enum GNUNET_BLOCK_Type type, const void *block, uint16_t block_size); /** * Function called with information about our * progress in computing the tree encoding. * * @param cls closure * @param offset where are we in the file * @param pt_block plaintext of the currently processed block * @param pt_size size of pt_block * @param depth depth of the block in the tree, 0 for DBLOCKS */ typedef void (*GNUNET_FS_TreeProgressCallback) (void *cls, uint64_t offset, const void *pt_block, size_t pt_size, unsigned int depth); /** * Initialize a tree encoder. This function will call "proc" and * "progress" on each block in the tree. Once all blocks have been * processed, "cont" will be scheduled. The "reader" will be called * to obtain the (plaintext) blocks for the file. Note that this * function will actually never call "proc"; the "proc" function must * be triggered by calling "GNUNET_FS_tree_encoder_next" to trigger * encryption (and calling of "proc") for each block. * * @param h the global FS context * @param size overall size of the file to encode * @param cls closure for reader, proc, progress and cont * @param reader function to call to read plaintext data * @param proc function to call on each encrypted block * @param progress function to call with progress information * @param cont function to call when done * @return tree encoder context */ struct GNUNET_FS_TreeEncoder * GNUNET_FS_tree_encoder_create (struct GNUNET_FS_Handle *h, uint64_t size, void *cls, GNUNET_FS_DataReader reader, GNUNET_FS_TreeBlockProcessor proc, GNUNET_FS_TreeProgressCallback progress, GNUNET_SCHEDULER_Task cont); /** * Encrypt the next block of the file (and * call proc and progress accordingly; or * of course "cont" if we have already completed * encoding of the entire file). * * @param te tree encoder to use */ void GNUNET_FS_tree_encoder_next (struct GNUNET_FS_TreeEncoder *te); /** * Get the resulting URI from the encoding. * * @param te the tree encoder to clean up * @return uri set to the resulting URI (if encoding finished), NULL otherwise */ struct GNUNET_FS_Uri * GNUNET_FS_tree_encoder_get_uri (struct GNUNET_FS_TreeEncoder *te); /** * Clean up a tree encoder and return information * about possible errors. * * @param te the tree encoder to clean up * @param emsg set to an error message (if an error occured * within the tree encoder; if this function is called * prior to completion and prior to an internal error, * both "*emsg" will be set to NULL). */ void GNUNET_FS_tree_encoder_finish (struct GNUNET_FS_TreeEncoder *te, char **emsg); #if 0 /* the functions below will be needed for persistence but are not yet implemented -- FIXME... */ /** * Get data that would be needed to resume * the encoding later. * * @param te encoding to resume * @param data set to the resume data * @param size set to the size of the resume data */ void GNUNET_FS_tree_encoder_resume_get_data (const struct GNUNET_FS_TreeEncoder *te, void **data, size_t * size); /** * Reset tree encoder to point previously * obtained for resuming. * * @param te encoding to resume * @param data the resume data * @param size the size of the resume data */ void GNUNET_FS_tree_encoder_resume (struct GNUNET_FS_TreeEncoder *te, const void *data, size_t size); #endif #endif /* end of fs_tree.h */ gnunet-0.10.1/src/fs/fs_api.c0000644000175000017500000026327112301361474012632 00000000000000/* This file is part of GNUnet. (C) 2001--2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_api.c * @brief main FS functions (master initialization, serialization, deserialization, shared code) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "fs_api.h" #include "fs_tree.h" /** * How many block requests can we have outstanding in parallel at a time by default? */ #define DEFAULT_MAX_PARALLEL_REQUESTS (1024 * 10) /** * How many downloads can we have outstanding in parallel at a time by default? */ #define DEFAULT_MAX_PARALLEL_DOWNLOADS 16 /** * Start the given job (send signal, remove from pending queue, update * counters and state). * * @param qe job to start */ static void start_job (struct GNUNET_FS_QueueEntry *qe) { GNUNET_assert (NULL == qe->client); qe->client = GNUNET_CLIENT_connect ("fs", qe->h->cfg); if (NULL == qe->client) { GNUNET_break (0); return; } qe->start (qe->cls, qe->client); qe->start_times++; qe->h->active_blocks += qe->blocks; qe->h->active_downloads++; qe->start_time = GNUNET_TIME_absolute_get (); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting job %p (%u active)\n", qe, qe->h->active_downloads); GNUNET_CONTAINER_DLL_remove (qe->h->pending_head, qe->h->pending_tail, qe); GNUNET_CONTAINER_DLL_insert_after (qe->h->running_head, qe->h->running_tail, qe->h->running_tail, qe); } /** * Stop the given job (send signal, remove from active queue, update * counters and state). * * @param qe job to stop */ static void stop_job (struct GNUNET_FS_QueueEntry *qe) { qe->client = NULL; qe->stop (qe->cls); GNUNET_assert (0 < qe->h->active_downloads); qe->h->active_downloads--; qe->h->active_blocks -= qe->blocks; qe->run_time = GNUNET_TIME_relative_add (qe->run_time, GNUNET_TIME_absolute_get_duration (qe->start_time)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping job %p (%u active)\n", qe, qe->h->active_downloads); GNUNET_CONTAINER_DLL_remove (qe->h->running_head, qe->h->running_tail, qe); GNUNET_CONTAINER_DLL_insert_after (qe->h->pending_head, qe->h->pending_tail, qe->h->pending_tail, qe); } /** * Process the jobs in the job queue, possibly starting some * and stopping others. * * @param cls the 'struct GNUNET_FS_Handle' * @param tc scheduler context */ static void process_job_queue (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_Handle *h = cls; struct GNUNET_FS_QueueEntry *qe; struct GNUNET_FS_QueueEntry *next; struct GNUNET_TIME_Relative run_time; struct GNUNET_TIME_Relative restart_at; struct GNUNET_TIME_Relative rst; struct GNUNET_TIME_Absolute end_time; unsigned int num_downloads_waiting; unsigned int num_downloads_active; unsigned int num_downloads_expired; unsigned int num_probes_active; unsigned int num_probes_waiting; unsigned int num_probes_expired; int num_probes_change; int num_downloads_change; int block_limit_hit; h->queue_job = GNUNET_SCHEDULER_NO_TASK; /* restart_at will be set to the time when it makes sense to re-evaluate the job queue (unless, of course, jobs complete or are added, then we'll be triggered immediately */ restart_at = GNUNET_TIME_UNIT_FOREVER_REL; /* first, calculate some basic statistics on pending jobs */ num_probes_waiting = 0; num_downloads_waiting = 0; for (qe = h->pending_head; NULL != qe; qe = qe->next) { switch (qe->priority) { case GNUNET_FS_QUEUE_PRIORITY_PROBE: num_probes_waiting++; break; case GNUNET_FS_QUEUE_PRIORITY_NORMAL: num_downloads_waiting++; break; default: GNUNET_break (0); break; } } /* now, calculate some basic statistics on running jobs */ num_probes_active = 0; num_probes_expired = 0; num_downloads_active = 0; num_downloads_expired = 0; next = h->running_head; while (NULL != (qe = next)) { next = qe->next; switch (qe->priority) { case GNUNET_FS_QUEUE_PRIORITY_PROBE: run_time = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2); end_time = GNUNET_TIME_absolute_add (qe->start_time, run_time); rst = GNUNET_TIME_absolute_get_remaining (end_time); if (0 == rst.rel_value_us) { num_probes_expired++; stop_job (qe); } else { num_probes_active++; restart_at = GNUNET_TIME_relative_min (rst, restart_at); } break; case GNUNET_FS_QUEUE_PRIORITY_NORMAL: run_time = GNUNET_TIME_relative_multiply (h->avg_block_latency, qe->blocks * qe->start_times); end_time = GNUNET_TIME_absolute_add (qe->start_time, run_time); rst = GNUNET_TIME_absolute_get_remaining (end_time); if (0 == rst.rel_value_us) { num_downloads_expired++; stop_job (qe); } else { num_downloads_active++; restart_at = GNUNET_TIME_relative_min (rst, restart_at); } break; default: GNUNET_break (0); break; } } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PA: %u, PE: %u, PW: %u; DA: %u, DE: %u, DW: %u\n", num_probes_active, num_probes_expired, num_probes_waiting, num_downloads_active, num_downloads_expired, num_downloads_waiting); /* calculate start/stop decisions */ if (h->active_downloads + num_downloads_waiting > h->max_parallel_requests) { /* stop probes if possible */ num_probes_change = - num_probes_active; num_downloads_change = h->max_parallel_requests - h->active_downloads; } else { /* start all downloads */ num_downloads_change = num_downloads_waiting; /* start as many probes as we can */ num_probes_change = GNUNET_MIN (num_probes_waiting, h->max_parallel_requests - (h->active_downloads + num_downloads_waiting)); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Changing %d probes and %d downloads\n", num_probes_change, num_downloads_change); /* actually stop probes */ next = h->running_head; while (NULL != (qe = next)) { next = qe->next; if (GNUNET_FS_QUEUE_PRIORITY_PROBE != qe->priority) continue; if (num_probes_change < 0) { stop_job (qe); num_probes_change++; if (0 == num_probes_change) break; } } GNUNET_break (0 <= num_probes_change); /* start some more tasks if we now have empty slots */ block_limit_hit = GNUNET_NO; next = h->pending_head; while ( (NULL != (qe = next)) && ( (num_probes_change > 0) || (num_downloads_change > 0) ) ) { next = qe->next; switch (qe->priority) { case GNUNET_FS_QUEUE_PRIORITY_PROBE: if (num_probes_change > 0) { start_job (qe); num_probes_change--; run_time = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2); restart_at = GNUNET_TIME_relative_min (run_time, restart_at); } break; case GNUNET_FS_QUEUE_PRIORITY_NORMAL: if ( (num_downloads_change > 0) && ( (qe->blocks + h->active_blocks <= h->max_parallel_requests) || ( (qe->blocks > h->max_parallel_requests) && (0 == h->active_downloads) ) ) ) { start_job (qe); num_downloads_change--; } else if (num_downloads_change > 0) block_limit_hit = GNUNET_YES; break; default: GNUNET_break (0); break; } } GNUNET_break ( (0 == num_downloads_change) || (GNUNET_YES == block_limit_hit) ); GNUNET_break (0 == num_probes_change); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "AD: %u, MP: %u; %d probes and %d downloads to start, will run again in %s\n", h->active_downloads, h->max_parallel_requests, num_probes_change, num_downloads_change, GNUNET_STRINGS_relative_time_to_string (restart_at, GNUNET_YES)); /* make sure we run again */ h->queue_job = GNUNET_SCHEDULER_add_delayed (restart_at, &process_job_queue, h); } /** * Add a job to the queue. * * @param h handle to the overall FS state * @param start function to call to begin the job * @param stop function to call to pause the job, or on dequeue (if the job was running) * @param cls closure for start and stop * @param blocks number of blocks this jobs uses * @param priority how important is this download * @return queue handle */ struct GNUNET_FS_QueueEntry * GNUNET_FS_queue_ (struct GNUNET_FS_Handle *h, GNUNET_FS_QueueStart start, GNUNET_FS_QueueStop stop, void *cls, unsigned int blocks, enum GNUNET_FS_QueuePriority priority) { struct GNUNET_FS_QueueEntry *qe; qe = GNUNET_new (struct GNUNET_FS_QueueEntry); qe->h = h; qe->start = start; qe->stop = stop; qe->cls = cls; qe->queue_time = GNUNET_TIME_absolute_get (); qe->blocks = blocks; qe->priority = priority; GNUNET_CONTAINER_DLL_insert_after (h->pending_head, h->pending_tail, h->pending_tail, qe); if (h->queue_job != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (h->queue_job); h->queue_job = GNUNET_SCHEDULER_add_now (&process_job_queue, h); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing job %p\n", qe); return qe; } /** * Dequeue a job from the queue. * * @param qe handle for the job */ void GNUNET_FS_dequeue_ (struct GNUNET_FS_QueueEntry *qe) { struct GNUNET_FS_Handle *h; h = qe->h; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dequeueing job %p\n", qe); if (NULL != qe->client) stop_job (qe); GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, qe); GNUNET_free (qe); if (h->queue_job != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (h->queue_job); h->queue_job = GNUNET_SCHEDULER_add_now (&process_job_queue, h); } /** * Create a top-level activity entry. * * @param h global fs handle * @param ssf suspend signal function to use * @param ssf_cls closure for ssf * @return fresh top-level activity handle */ struct TopLevelActivity * GNUNET_FS_make_top (struct GNUNET_FS_Handle *h, SuspendSignalFunction ssf, void *ssf_cls) { struct TopLevelActivity *ret; ret = GNUNET_new (struct TopLevelActivity); ret->ssf = ssf; ret->ssf_cls = ssf_cls; GNUNET_CONTAINER_DLL_insert (h->top_head, h->top_tail, ret); return ret; } /** * Destroy a top-level activity entry. * * @param h global fs handle * @param top top level activity entry */ void GNUNET_FS_end_top (struct GNUNET_FS_Handle *h, struct TopLevelActivity *top) { GNUNET_CONTAINER_DLL_remove (h->top_head, h->top_tail, top); GNUNET_free (top); } /** * Closure for "data_reader_file". */ struct FileInfo { /** * Name of the file to read. */ char *filename; /** * File descriptor, NULL if it has not yet been opened. */ struct GNUNET_DISK_FileHandle *fd; }; /** * Function that provides data by reading from a file. * * @param cls closure (points to the file information) * @param offset offset to read from; it is possible * that the caller might need to go backwards * a bit at times; set to UINT64_MAX to tell * the reader that we won't be reading for a while * (used to close the file descriptor but NOT fully * clean up the reader's state); in this case, * a value of '0' for max should be ignored * @param max maximum number of bytes that should be * copied to buf; readers are not allowed * to provide less data unless there is an error; * a value of "0" will be used at the end to allow * the reader to clean up its internal state * @param buf where the reader should write the data * @param emsg location for the reader to store an error message * @return number of bytes written, usually "max", 0 on error */ size_t GNUNET_FS_data_reader_file_ (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) { struct FileInfo *fi = cls; ssize_t ret; if (UINT64_MAX == offset) { if (NULL != fi->fd) { GNUNET_DISK_file_close (fi->fd); fi->fd = NULL; } return 0; } if (0 == max) { if (NULL != fi->fd) GNUNET_DISK_file_close (fi->fd); GNUNET_free (fi->filename); GNUNET_free (fi); return 0; } if (NULL == fi->fd) { fi->fd = GNUNET_DISK_file_open (fi->filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (NULL == fi->fd) { GNUNET_asprintf (emsg, _("Could not open file `%s': %s"), fi->filename, STRERROR (errno)); return 0; } } if ( (GNUNET_SYSERR == GNUNET_DISK_file_seek (fi->fd, offset, GNUNET_DISK_SEEK_SET)) || (-1 == (ret = GNUNET_DISK_file_read (fi->fd, buf, max))) ) { GNUNET_asprintf (emsg, _("Could not read file `%s': %s"), fi->filename, STRERROR (errno)); return 0; } if (ret != max) { GNUNET_asprintf (emsg, _("Short read reading from file `%s'!"), fi->filename); return 0; } return max; } /** * Create the closure for the 'GNUNET_FS_data_reader_file_' callback. * * @param filename file to read * @return closure to use, NULL on error */ void * GNUNET_FS_make_file_reader_context_ (const char *filename) { struct FileInfo *fi; fi = GNUNET_new (struct FileInfo); fi->filename = GNUNET_STRINGS_filename_expand (filename); if (NULL == fi->filename) { GNUNET_free (fi); return NULL; } return fi; } /** * Function that provides data by copying from a buffer. * * @param cls closure (points to the buffer) * @param offset offset to read from; it is possible * that the caller might need to go backwards * a bit at times; set to UINT64_MAX to tell * the reader that we won't be reading for a while * (used to close the file descriptor but NOT fully * clean up the reader's state); in this case, * a value of '0' for max should be ignored * @param max maximum number of bytes that should be * copied to buf; readers are not allowed * to provide less data unless there is an error; * a value of "0" will be used at the end to allow * the reader to clean up its internal state * @param buf where the reader should write the data * @param emsg location for the reader to store an error message * @return number of bytes written, usually "max", 0 on error */ size_t GNUNET_FS_data_reader_copy_ (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) { char *data = cls; if (UINT64_MAX == offset) return 0; if (0 == max) { GNUNET_free_non_null (data); return 0; } memcpy (buf, &data[offset], max); return max; } /** * Return the full filename where we would store state information * (for serialization/deserialization). * * @param h master context * @param ext component of the path * @param ent entity identifier (or emtpy string for the directory) * @return NULL on error */ static char * get_serialization_file_name (struct GNUNET_FS_Handle *h, const char *ext, const char *ent) { char *basename; char *ret; if (0 == (h->flags & GNUNET_FS_FLAGS_PERSISTENCE)) return NULL; /* persistence not requested */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (h->cfg, "fs", "STATE_DIR", &basename)) return NULL; GNUNET_asprintf (&ret, "%s%s%s%s%s%s%s", basename, DIR_SEPARATOR_STR, h->client_name, DIR_SEPARATOR_STR, ext, DIR_SEPARATOR_STR, ent); GNUNET_free (basename); return ret; } /** * Return the full filename where we would store state information * (for serialization/deserialization) that is associated with a * parent operation. * * @param h master context * @param ext component of the path * @param uni name of the parent operation * @param ent entity identifier (or emtpy string for the directory) * @return NULL on error */ static char * get_serialization_file_name_in_dir (struct GNUNET_FS_Handle *h, const char *ext, const char *uni, const char *ent) { char *basename; char *ret; if (0 == (h->flags & GNUNET_FS_FLAGS_PERSISTENCE)) return NULL; /* persistence not requested */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (h->cfg, "fs", "STATE_DIR", &basename)) return NULL; GNUNET_asprintf (&ret, "%s%s%s%s%s%s%s.dir%s%s", basename, DIR_SEPARATOR_STR, h->client_name, DIR_SEPARATOR_STR, ext, DIR_SEPARATOR_STR, uni, DIR_SEPARATOR_STR, ent); GNUNET_free (basename); return ret; } /** * Return a read handle for deserialization. * * @param h master context * @param ext component of the path * @param ent entity identifier (or emtpy string for the directory) * @return NULL on error */ static struct GNUNET_BIO_ReadHandle * get_read_handle (struct GNUNET_FS_Handle *h, const char *ext, const char *ent) { char *fn; struct GNUNET_BIO_ReadHandle *ret; fn = get_serialization_file_name (h, ext, ent); if (NULL == fn) return NULL; ret = GNUNET_BIO_read_open (fn); GNUNET_free (fn); return ret; } /** * Return a write handle for serialization. * * @param h master context * @param ext component of the path * @param ent entity identifier (or emtpy string for the directory) * @return NULL on error */ static struct GNUNET_BIO_WriteHandle * get_write_handle (struct GNUNET_FS_Handle *h, const char *ext, const char *ent) { char *fn; struct GNUNET_BIO_WriteHandle *ret; fn = get_serialization_file_name (h, ext, ent); if (NULL == fn) return NULL; ret = GNUNET_BIO_write_open (fn); GNUNET_break (NULL != ret); GNUNET_free (fn); return ret; } /** * Return a write handle for serialization. * * @param h master context * @param ext component of the path * @param uni name of parent * @param ent entity identifier (or emtpy string for the directory) * @return NULL on error */ static struct GNUNET_BIO_WriteHandle * get_write_handle_in_dir (struct GNUNET_FS_Handle *h, const char *ext, const char *uni, const char *ent) { char *fn; struct GNUNET_BIO_WriteHandle *ret; fn = get_serialization_file_name_in_dir (h, ext, uni, ent); if (NULL == fn) return NULL; ret = GNUNET_BIO_write_open (fn); GNUNET_free (fn); return ret; } /** * Remove serialization/deserialization file from disk. * * @param h master context * @param ext component of the path * @param ent entity identifier */ void GNUNET_FS_remove_sync_file_ (struct GNUNET_FS_Handle *h, const char *ext, const char *ent) { char *filename; if ((NULL == ent) || (0 == strlen (ent))) { GNUNET_break (0); return; } filename = get_serialization_file_name (h, ext, ent); if (NULL != filename) { if ( (0 != UNLINK (filename)) && (ENOENT != errno) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); GNUNET_free (filename); } } /** * Remove serialization/deserialization file from disk. * * @param h master context * @param ext component of the path * @param uni parent name * @param ent entity identifier */ static void remove_sync_file_in_dir (struct GNUNET_FS_Handle *h, const char *ext, const char *uni, const char *ent) { char *filename; if ((NULL == ent) || (0 == strlen (ent))) { GNUNET_break (0); return; } filename = get_serialization_file_name_in_dir (h, ext, uni, ent); if (NULL == filename) return; if (0 != UNLINK (filename)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); GNUNET_free (filename); } /** * Remove serialization/deserialization directory from disk. * * @param h master context * @param ext component of the path * @param uni unique name of parent */ void GNUNET_FS_remove_sync_dir_ (struct GNUNET_FS_Handle *h, const char *ext, const char *uni) { char *dn; if (NULL == uni) return; dn = get_serialization_file_name_in_dir (h, ext, uni, ""); if (NULL == dn) return; if ((GNUNET_YES == GNUNET_DISK_directory_test (dn, GNUNET_YES)) && (GNUNET_OK != GNUNET_DISK_directory_remove (dn))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rmdir", dn); GNUNET_free (dn); } /** * Serialize a 'start_time'. Since we use start-times to * calculate the duration of some operation, we actually * do not serialize the absolute time but the (relative) * duration since the start time. When we then * deserialize the start time, we take the current time and * subtract that duration so that we get again an absolute * time stamp that will result in correct performance * calculations. * * @param wh handle for writing * @param timestamp time to serialize * @return GNUNET_OK on success */ static int write_start_time (struct GNUNET_BIO_WriteHandle *wh, struct GNUNET_TIME_Absolute timestamp) { struct GNUNET_TIME_Relative dur; dur = GNUNET_TIME_absolute_get_duration (timestamp); return GNUNET_BIO_write_int64 (wh, dur.rel_value_us); } /** * Serialize a 'start_time'. Since we use start-times to * calculate the duration of some operation, we actually * do not serialize the absolute time but the (relative) * duration since the start time. When we then * deserialize the start time, we take the current time and * subtract that duration so that we get again an absolute * time stamp that will result in correct performance * calculations. * * @param rh handle for reading * @param timestamp where to write the deserialized timestamp * @return #GNUNET_OK on success */ static int read_start_time (struct GNUNET_BIO_ReadHandle *rh, struct GNUNET_TIME_Absolute *timestamp) { struct GNUNET_TIME_Relative dur; if (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dur.rel_value_us)) return GNUNET_SYSERR; *timestamp = GNUNET_TIME_absolute_subtract (GNUNET_TIME_absolute_get (), dur); return GNUNET_OK; } /** * Using the given serialization filename, try to deserialize * the file-information tree associated with it. * * @param h master context * @param filename name of the file (without directory) with * the infromation * @return NULL on error */ static struct GNUNET_FS_FileInformation * deserialize_file_information (struct GNUNET_FS_Handle *h, const char *filename); /** * Using the given serialization filename, try to deserialize * the file-information tree associated with it. * * @param h master context * @param fn name of the file (without directory) with * the infromation * @param rh handle for reading * @return NULL on error */ static struct GNUNET_FS_FileInformation * deserialize_fi_node (struct GNUNET_FS_Handle *h, const char *fn, struct GNUNET_BIO_ReadHandle *rh) { struct GNUNET_FS_FileInformation *ret; struct GNUNET_FS_FileInformation *nxt; char b; char *ksks; char *chks; char *filename; uint32_t dsize; if (GNUNET_OK != GNUNET_BIO_read (rh, "status flag", &b, sizeof (b))) { GNUNET_break (0); return NULL; } ret = GNUNET_new (struct GNUNET_FS_FileInformation); ret->h = h; ksks = NULL; chks = NULL; filename = NULL; if ((GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "metadata", &ret->meta)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "ksk-uri", &ksks, 32 * 1024)) || ( (NULL != ksks) && ( (NULL == (ret->keywords = GNUNET_FS_uri_parse (ksks, NULL))) || (GNUNET_YES != GNUNET_FS_uri_test_ksk (ret->keywords)) ) ) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "chk-uri", &chks, 1024)) || ( (NULL != chks) && ( (NULL == (ret->chk_uri = GNUNET_FS_uri_parse (chks, NULL))) || (GNUNET_YES != GNUNET_FS_uri_test_chk (ret->chk_uri))) ) || (GNUNET_OK != read_start_time (rh, &ret->start_time)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "emsg", &ret->emsg, 16 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "fn", &ret->filename, 16 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->bo.expiration_time.abs_value_us)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &ret->bo.anonymity_level)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &ret->bo.content_priority)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &ret->bo.replication_level))) { GNUNET_break (0); goto cleanup; } switch (b) { case 0: /* file-insert */ if (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) { GNUNET_break (0); goto cleanup; } ret->is_directory = GNUNET_NO; ret->data.file.do_index = GNUNET_NO; ret->data.file.have_hash = GNUNET_NO; ret->data.file.index_start_confirmed = GNUNET_NO; if (GNUNET_NO == ret->is_published) { if (NULL == ret->filename) { ret->data.file.reader = &GNUNET_FS_data_reader_copy_; ret->data.file.reader_cls = GNUNET_malloc_large (ret->data.file.file_size); if (ret->data.file.reader_cls == NULL) goto cleanup; if (GNUNET_OK != GNUNET_BIO_read (rh, "file-data", ret->data.file.reader_cls, ret->data.file.file_size)) { GNUNET_break (0); goto cleanup; } } else { ret->data.file.reader = &GNUNET_FS_data_reader_file_; ret->data.file.reader_cls = GNUNET_FS_make_file_reader_context_ (ret->filename); } } break; case 1: /* file-index, no hash */ if (NULL == ret->filename) { GNUNET_break (0); goto cleanup; } if (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) { GNUNET_break (0); goto cleanup; } ret->is_directory = GNUNET_NO; ret->data.file.do_index = GNUNET_YES; ret->data.file.have_hash = GNUNET_NO; ret->data.file.index_start_confirmed = GNUNET_NO; ret->data.file.reader = &GNUNET_FS_data_reader_file_; ret->data.file.reader_cls = GNUNET_FS_make_file_reader_context_ (ret->filename); break; case 2: /* file-index-with-hash */ if (NULL == ret->filename) { GNUNET_break (0); goto cleanup; } if ((GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) || (GNUNET_OK != GNUNET_BIO_read (rh, "fileid", &ret->data.file.file_id, sizeof (struct GNUNET_HashCode)))) { GNUNET_break (0); goto cleanup; } ret->is_directory = GNUNET_NO; ret->data.file.do_index = GNUNET_YES; ret->data.file.have_hash = GNUNET_YES; ret->data.file.index_start_confirmed = GNUNET_NO; ret->data.file.reader = &GNUNET_FS_data_reader_file_; ret->data.file.reader_cls = GNUNET_FS_make_file_reader_context_ (ret->filename); break; case 3: /* file-index-with-hash-confirmed */ if (NULL == ret->filename) { GNUNET_break (0); goto cleanup; } if ((GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) || (GNUNET_OK != GNUNET_BIO_read (rh, "fileid", &ret->data.file.file_id, sizeof (struct GNUNET_HashCode)))) { GNUNET_break (0); goto cleanup; } ret->is_directory = GNUNET_NO; ret->data.file.do_index = GNUNET_YES; ret->data.file.have_hash = GNUNET_YES; ret->data.file.index_start_confirmed = GNUNET_YES; ret->data.file.reader = &GNUNET_FS_data_reader_file_; ret->data.file.reader_cls = GNUNET_FS_make_file_reader_context_ (ret->filename); break; case 4: /* directory */ ret->is_directory = GNUNET_YES; if ((GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dsize)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.dir.contents_completed)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.dir.contents_size)) || (NULL == (ret->data.dir.dir_data = GNUNET_malloc_large (dsize))) || (GNUNET_OK != GNUNET_BIO_read (rh, "dir-data", ret->data.dir.dir_data, dsize)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "ent-filename", &filename, 16 * 1024))) { GNUNET_break (0); goto cleanup; } ret->data.dir.dir_size = (uint32_t) dsize; if (NULL != filename) { ret->data.dir.entries = deserialize_file_information (h, filename); GNUNET_free (filename); filename = NULL; nxt = ret->data.dir.entries; while (NULL != nxt) { nxt->dir = ret; nxt = nxt->next; } } break; default: GNUNET_break (0); goto cleanup; } ret->serialization = GNUNET_strdup (fn); if (GNUNET_OK != GNUNET_BIO_read_string (rh, "nxt-filename", &filename, 16 * 1024)) { GNUNET_break (0); goto cleanup; } if (NULL != filename) { ret->next = deserialize_file_information (h, filename); GNUNET_free (filename); filename = NULL; } GNUNET_free_non_null (ksks); GNUNET_free_non_null (chks); return ret; cleanup: GNUNET_free_non_null (ksks); GNUNET_free_non_null (chks); GNUNET_free_non_null (filename); GNUNET_FS_file_information_destroy (ret, NULL, NULL); return NULL; } /** * Using the given serialization filename, try to deserialize * the file-information tree associated with it. * * @param h master context * @param filename name of the file (without directory) with * the infromation * @return NULL on error */ static struct GNUNET_FS_FileInformation * deserialize_file_information (struct GNUNET_FS_Handle *h, const char *filename) { struct GNUNET_FS_FileInformation *ret; struct GNUNET_BIO_ReadHandle *rh; char *emsg; char *fn; rh = get_read_handle (h, GNUNET_FS_SYNC_PATH_FILE_INFO, filename); if (NULL == rh) return NULL; ret = deserialize_fi_node (h, filename, rh); if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to resume publishing information `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } if (NULL == ret) { fn = get_serialization_file_name (h, GNUNET_FS_SYNC_PATH_FILE_INFO, filename); if (NULL != fn) { if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); GNUNET_free (fn); } } return ret; } /** * Given a serialization name (full absolute path), return the * basename of the file (without the path), which must only * consist of the 6 random characters. * * @param fullname name to extract the basename from * @return copy of the basename, NULL on error */ static char * get_serialization_short_name (const char *fullname) { const char *end; const char *nxt; end = NULL; nxt = fullname; /* FIXME: we could do this faster since we know * the length of 'end'... */ while ('\0' != *nxt) { if (DIR_SEPARATOR == *nxt) end = nxt + 1; nxt++; } if ((NULL == end) || (0 == strlen (end))) { GNUNET_break (0); return NULL; } GNUNET_break (6 == strlen (end)); return GNUNET_strdup (end); } /** * Create a new random name for serialization. Also checks if persistence * is enabled and returns NULL if not. * * @param h master context * @param ext component of the path * @return NULL on errror */ static char * make_serialization_file_name (struct GNUNET_FS_Handle *h, const char *ext) { char *fn; char *dn; char *ret; if (0 == (h->flags & GNUNET_FS_FLAGS_PERSISTENCE)) return NULL; /* persistence not requested */ dn = get_serialization_file_name (h, ext, ""); if (NULL == dn) return NULL; if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (dn)) { GNUNET_free (dn); return NULL; } fn = GNUNET_DISK_mktemp (dn); GNUNET_free (dn); if (NULL == fn) return NULL; /* epic fail */ ret = get_serialization_short_name (fn); GNUNET_free (fn); return ret; } /** * Create a new random name for serialization. Also checks if persistence * is enabled and returns NULL if not. * * @param h master context * @param ext component of the path * @param uni name of parent * @return NULL on errror */ static char * make_serialization_file_name_in_dir (struct GNUNET_FS_Handle *h, const char *ext, const char *uni) { char *fn; char *dn; char *ret; if (0 == (h->flags & GNUNET_FS_FLAGS_PERSISTENCE)) return NULL; /* persistence not requested */ dn = get_serialization_file_name_in_dir (h, ext, uni, ""); if (NULL == dn) return NULL; if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (dn)) { GNUNET_free (dn); return NULL; } fn = GNUNET_DISK_mktemp (dn); GNUNET_free (dn); if (NULL == fn) return NULL; /* epic fail */ ret = get_serialization_short_name (fn); GNUNET_free (fn); return ret; } /** * Copy all of the data from the reader to the write handle. * * @param wh write handle * @param fi file with reader * @return #GNUNET_OK on success */ static int copy_from_reader (struct GNUNET_BIO_WriteHandle *wh, struct GNUNET_FS_FileInformation *fi) { char buf[32 * 1024]; uint64_t off; size_t ret; size_t left; char *emsg; emsg = NULL; off = 0; while (off < fi->data.file.file_size) { left = GNUNET_MIN (sizeof (buf), fi->data.file.file_size - off); ret = fi->data.file.reader (fi->data.file.reader_cls, off, left, buf, &emsg); if (0 == ret) { GNUNET_free (emsg); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_BIO_write (wh, buf, ret)) return GNUNET_SYSERR; off += ret; } return GNUNET_OK; } /** * Create a temporary file on disk to store the current * state of "fi" in. * * @param fi file information to sync with disk */ void GNUNET_FS_file_information_sync_ (struct GNUNET_FS_FileInformation *fi) { char *fn; struct GNUNET_BIO_WriteHandle *wh; char b; char *ksks; char *chks; if (NULL == fi->serialization) fi->serialization = make_serialization_file_name (fi->h, GNUNET_FS_SYNC_PATH_FILE_INFO); if (NULL == fi->serialization) return; wh = get_write_handle (fi->h, GNUNET_FS_SYNC_PATH_FILE_INFO, fi->serialization); if (NULL == wh) { GNUNET_free (fi->serialization); fi->serialization = NULL; return; } if (GNUNET_YES == fi->is_directory) b = 4; else if (GNUNET_YES == fi->data.file.index_start_confirmed) b = 3; else if (GNUNET_YES == fi->data.file.have_hash) b = 2; else if (GNUNET_YES == fi->data.file.do_index) b = 1; else b = 0; if (NULL != fi->keywords) ksks = GNUNET_FS_uri_to_string (fi->keywords); else ksks = NULL; if (NULL != fi->chk_uri) chks = GNUNET_FS_uri_to_string (fi->chk_uri); else chks = NULL; if ((GNUNET_OK != GNUNET_BIO_write (wh, &b, sizeof (b))) || (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, fi->meta)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, ksks)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, chks)) || (GNUNET_OK != write_start_time (wh, fi->start_time)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, fi->emsg)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, fi->filename)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->bo.expiration_time.abs_value_us)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, fi->bo.anonymity_level)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, fi->bo.content_priority)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, fi->bo.replication_level))) { GNUNET_break (0); goto cleanup; } GNUNET_free_non_null (chks); chks = NULL; GNUNET_free_non_null (ksks); ksks = NULL; switch (b) { case 0: /* file-insert */ if (GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->data.file.file_size)) { GNUNET_break (0); goto cleanup; } if ((GNUNET_NO == fi->is_published) && (NULL == fi->filename)) if (GNUNET_OK != copy_from_reader (wh, fi)) { GNUNET_break (0); goto cleanup; } break; case 1: /* file-index, no hash */ if (NULL == fi->filename) { GNUNET_break (0); goto cleanup; } if (GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->data.file.file_size)) { GNUNET_break (0); goto cleanup; } break; case 2: /* file-index-with-hash */ case 3: /* file-index-with-hash-confirmed */ if (NULL == fi->filename) { GNUNET_break (0); goto cleanup; } if ((GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->data.file.file_size)) || (GNUNET_OK != GNUNET_BIO_write (wh, &fi->data.file.file_id, sizeof (struct GNUNET_HashCode)))) { GNUNET_break (0); goto cleanup; } break; case 4: /* directory */ if ( (NULL != fi->data.dir.entries) && (NULL == fi->data.dir.entries->serialization) ) GNUNET_FS_file_information_sync_ (fi->data.dir.entries); if ((GNUNET_OK != GNUNET_BIO_write_int32 (wh, fi->data.dir.dir_size)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->data.dir.contents_completed)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->data.dir.contents_size)) || (GNUNET_OK != GNUNET_BIO_write (wh, fi->data.dir.dir_data, (uint32_t) fi->data.dir.dir_size)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, (fi->data.dir.entries == NULL) ? NULL : fi->data.dir. entries->serialization))) { GNUNET_break (0); goto cleanup; } break; default: GNUNET_assert (0); goto cleanup; } if ( (NULL != fi->next) && (NULL == fi->next->serialization) ) GNUNET_FS_file_information_sync_ (fi->next); if (GNUNET_OK != GNUNET_BIO_write_string (wh, (fi->next != NULL) ? fi->next->serialization : NULL)) { GNUNET_break (0); goto cleanup; } if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { wh = NULL; GNUNET_break (0); goto cleanup; } return; /* done! */ cleanup: if (NULL != wh) (void) GNUNET_BIO_write_close (wh); GNUNET_free_non_null (chks); GNUNET_free_non_null (ksks); fn = get_serialization_file_name (fi->h, GNUNET_FS_SYNC_PATH_FILE_INFO, fi->serialization); if (NULL != fn) { if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); GNUNET_free (fn); } GNUNET_free (fi->serialization); fi->serialization = NULL; } /** * Find the entry in the file information struct where the * serialization filename matches the given name. * * @param pos file information to search * @param srch filename to search for * @return NULL if srch was not found in this subtree */ static struct GNUNET_FS_FileInformation * find_file_position (struct GNUNET_FS_FileInformation *pos, const char *srch) { struct GNUNET_FS_FileInformation *r; while (NULL != pos) { if (0 == strcmp (srch, pos->serialization)) return pos; if ( (GNUNET_YES == pos->is_directory) && (NULL != (r = find_file_position (pos->data.dir.entries, srch))) ) return r; pos = pos->next; } return NULL; } /** * Signal the FS's progress function that we are resuming * an upload. * * @param cls closure (of type `struct GNUNET_FS_PublishContext *`, for the parent (!)) * @param fi the entry in the publish-structure * @param length length of the file or directory * @param meta metadata for the file or directory (can be modified) * @param uri pointer to the keywords that will be used for this entry (can be modified) * @param bo block options (can be modified) * @param do_index should we index? * @param client_info pointer to client context set upon creation (can be modified) * @return #GNUNET_OK to continue (always) */ static int fip_signal_resume (void *cls, struct GNUNET_FS_FileInformation *fi, uint64_t length, struct GNUNET_CONTAINER_MetaData *meta, struct GNUNET_FS_Uri **uri, struct GNUNET_FS_BlockOptions *bo, int *do_index, void **client_info) { struct GNUNET_FS_PublishContext *pc = cls; struct GNUNET_FS_ProgressInfo pi; if (GNUNET_YES == pc->skip_next_fi_callback) { pc->skip_next_fi_callback = GNUNET_NO; return GNUNET_OK; } pi.status = GNUNET_FS_STATUS_PUBLISH_RESUME; pi.value.publish.specifics.resume.message = fi->emsg; pi.value.publish.specifics.resume.chk_uri = fi->chk_uri; *client_info = GNUNET_FS_publish_make_status_ (&pi, pc, fi, 0); if (GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (meta)) { /* process entries in directory */ pc->skip_next_fi_callback = GNUNET_YES; GNUNET_FS_file_information_inspect (fi, &fip_signal_resume, pc); } return GNUNET_OK; } /** * Function called with a filename of serialized publishing operation * to deserialize. * * @param cls the `struct GNUNET_FS_Handle *` * @param filename complete filename (absolute path) * @return #GNUNET_OK (continue to iterate) */ static int deserialize_publish_file (void *cls, const char *filename) { struct GNUNET_FS_Handle *h = cls; struct GNUNET_BIO_ReadHandle *rh; struct GNUNET_FS_PublishContext *pc; int32_t options; int32_t all_done; int32_t have_ns; char *fi_root; struct GNUNET_CRYPTO_EcdsaPrivateKey ns; char *fi_pos; char *emsg; pc = GNUNET_new (struct GNUNET_FS_PublishContext); pc->h = h; pc->serialization = get_serialization_short_name (filename); fi_root = NULL; fi_pos = NULL; rh = GNUNET_BIO_read_open (filename); if (NULL == rh) { GNUNET_break (0); goto cleanup; } if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "publish-nid", &pc->nid, 1024)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "publish-nuid", &pc->nuid, 1024)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &all_done)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &have_ns)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "publish-firoot", &fi_root, 128)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "publish-fipos", &fi_pos, 128)) || ( (GNUNET_YES == have_ns) && (GNUNET_OK != GNUNET_BIO_read (rh, "publish-ns", &ns, sizeof (ns)))) ) { GNUNET_break (0); goto cleanup; } pc->options = options; pc->all_done = all_done; if (NULL == fi_root) { GNUNET_break (0); goto cleanup; } pc->fi = deserialize_file_information (h, fi_root); if (NULL == pc->fi) { GNUNET_break (0); goto cleanup; } if (GNUNET_YES == have_ns) { pc->ns = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); *pc->ns = ns; } if ((0 == (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) && (GNUNET_YES != pc->all_done)) { pc->dsh = GNUNET_DATASTORE_connect (h->cfg); if (NULL == pc->dsh) goto cleanup; } if (NULL != fi_pos) { pc->fi_pos = find_file_position (pc->fi, fi_pos); GNUNET_free (fi_pos); fi_pos = NULL; if (NULL == pc->fi_pos) { /* failed to find position for resuming, outch! Will start from root! */ GNUNET_break (0); if (GNUNET_YES != pc->all_done) pc->fi_pos = pc->fi; } } GNUNET_free (fi_root); fi_root = NULL; /* generate RESUME event(s) */ GNUNET_FS_file_information_inspect (pc->fi, &fip_signal_resume, pc); /* re-start publishing (if needed)... */ if (GNUNET_YES != pc->all_done) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pc->upload_task); pc->upload_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_BACKGROUND, &GNUNET_FS_publish_main_, pc); } if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failure while resuming publishing operation `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } pc->top = GNUNET_FS_make_top (h, &GNUNET_FS_publish_signal_suspend_, pc); return GNUNET_OK; cleanup: GNUNET_free_non_null (pc->nid); GNUNET_free_non_null (pc->nuid); GNUNET_free_non_null (fi_root); GNUNET_free_non_null (fi_pos); if ((NULL != rh) && (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to resume publishing operation `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } if (NULL != pc->fi) GNUNET_FS_file_information_destroy (pc->fi, NULL, NULL); if (0 != UNLINK (filename)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); GNUNET_free (pc->serialization); GNUNET_free (pc); return GNUNET_OK; } /** * Synchronize this publishing struct with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param pc the struct to sync */ void GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext *pc) { struct GNUNET_BIO_WriteHandle *wh; int32_t have_ns; if (NULL == pc->serialization) pc->serialization = make_serialization_file_name (pc->h, GNUNET_FS_SYNC_PATH_MASTER_PUBLISH); if (NULL == pc->serialization) return; if (NULL == pc->fi) return; if (NULL == pc->fi->serialization) { GNUNET_break (0); return; } wh = get_write_handle (pc->h, GNUNET_FS_SYNC_PATH_MASTER_PUBLISH, pc->serialization); if (NULL == wh) { GNUNET_break (0); goto cleanup; } have_ns = (NULL != pc->ns) ? GNUNET_YES : GNUNET_NO; if ((GNUNET_OK != GNUNET_BIO_write_string (wh, pc->nid)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, pc->nuid)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pc->options)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pc->all_done)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, have_ns)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, pc->fi->serialization)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, (NULL == pc->fi_pos) ? NULL : pc->fi_pos->serialization)) || ( (NULL != pc->ns) && (GNUNET_OK != GNUNET_BIO_write (wh, pc->ns, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) ) )) { GNUNET_break (0); goto cleanup; } if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { wh = NULL; GNUNET_break (0); goto cleanup; } return; cleanup: if (NULL != wh) (void) GNUNET_BIO_write_close (wh); GNUNET_FS_remove_sync_file_ (pc->h, GNUNET_FS_SYNC_PATH_MASTER_PUBLISH, pc->serialization); GNUNET_free (pc->serialization); pc->serialization = NULL; } /** * Synchronize this unindex struct with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param uc the struct to sync */ void GNUNET_FS_unindex_sync_ (struct GNUNET_FS_UnindexContext *uc) { struct GNUNET_BIO_WriteHandle *wh; char *uris; if (NULL == uc->serialization) uc->serialization = make_serialization_file_name (uc->h, GNUNET_FS_SYNC_PATH_MASTER_UNINDEX); if (NULL == uc->serialization) return; wh = get_write_handle (uc->h, GNUNET_FS_SYNC_PATH_MASTER_UNINDEX, uc->serialization); if (NULL == wh) { GNUNET_break (0); goto cleanup; } if (NULL != uc->ksk_uri) uris = GNUNET_FS_uri_to_string (uc->ksk_uri); else uris = NULL; if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uc->filename)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, uc->file_size)) || (GNUNET_OK != write_start_time (wh, uc->start_time)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) uc->state)) || (GNUNET_OK != GNUNET_BIO_write (wh, &uc->chk, sizeof (struct ContentHashKey))) || (GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) uc->ksk_offset)) || ((uc->state == UNINDEX_STATE_FS_NOTIFY) && (GNUNET_OK != GNUNET_BIO_write (wh, &uc->file_id, sizeof (struct GNUNET_HashCode)))) || ((uc->state == UNINDEX_STATE_ERROR) && (GNUNET_OK != GNUNET_BIO_write_string (wh, uc->emsg)))) { GNUNET_break (0); goto cleanup; } if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { wh = NULL; GNUNET_break (0); goto cleanup; } return; cleanup: if (NULL != wh) (void) GNUNET_BIO_write_close (wh); GNUNET_FS_remove_sync_file_ (uc->h, GNUNET_FS_SYNC_PATH_MASTER_UNINDEX, uc->serialization); GNUNET_free (uc->serialization); uc->serialization = NULL; } /** * Serialize a download request. * * @param wh the `struct GNUNET_BIO_WriteHandle*` * @param dr the the request to write to disk * @return #GNUNET_YES on success, #GNUNET_NO on error */ static int write_download_request (struct GNUNET_BIO_WriteHandle *wh, struct DownloadRequest *dr) { unsigned int i; if ((GNUNET_OK != GNUNET_BIO_write_int32 (wh, dr->state)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dr->offset)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, dr->num_children)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, dr->depth))) return GNUNET_NO; if ((BRS_CHK_SET == dr->state) && (GNUNET_OK != GNUNET_BIO_write (wh, &dr->chk, sizeof (struct ContentHashKey)))) return GNUNET_NO; for (i = 0; i < dr->num_children; i++) if (GNUNET_NO == write_download_request (wh, dr->children[i])) return GNUNET_NO; return GNUNET_YES; } /** * Read a download request tree. * * @param rh mesh to read from * @return value the download request read from disk, NULL on error */ static struct DownloadRequest * read_download_request (struct GNUNET_BIO_ReadHandle *rh) { struct DownloadRequest *dr; unsigned int i; dr = GNUNET_new (struct DownloadRequest); if ((GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dr->state)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dr->offset)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dr->num_children)) || (dr->num_children > CHK_PER_INODE) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dr->depth)) || ((0 == dr->depth) && (dr->num_children > 0)) || ((dr->depth > 0) && (0 == dr->num_children))) { GNUNET_break (0); dr->num_children = 0; goto cleanup; } if (dr->num_children > 0) dr->children = GNUNET_malloc (dr->num_children * sizeof (struct DownloadRequest *)); switch (dr->state) { case BRS_INIT: case BRS_RECONSTRUCT_DOWN: case BRS_RECONSTRUCT_META_UP: case BRS_RECONSTRUCT_UP: break; case BRS_CHK_SET: if (GNUNET_OK != GNUNET_BIO_read (rh, "chk", &dr->chk, sizeof (struct ContentHashKey))) goto cleanup; break; case BRS_DOWNLOAD_DOWN: case BRS_DOWNLOAD_UP: case BRS_ERROR: break; default: GNUNET_break (0); goto cleanup; } for (i = 0; i < dr->num_children; i++) { if (NULL == (dr->children[i] = read_download_request (rh))) goto cleanup; dr->children[i]->parent = dr; } return dr; cleanup: GNUNET_FS_free_download_request_ (dr); return NULL; } /** * Compute the name of the sync file (or directory) for the given download * context. * * @param dc download context to compute for * @param uni unique filename to use, use "" for the directory name * @param ext extension to use, use ".dir" for our own subdirectory * @return the expanded file name, NULL for none */ static char * get_download_sync_filename (struct GNUNET_FS_DownloadContext *dc, const char *uni, const char *ext) { char *par; char *epar; if (dc->parent == NULL) return get_serialization_file_name (dc->h, (dc->search != NULL) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, uni); if (NULL == dc->parent->serialization) return NULL; par = get_download_sync_filename (dc->parent, dc->parent->serialization, ""); if (NULL == par) return NULL; GNUNET_asprintf (&epar, "%s.dir%s%s%s", par, DIR_SEPARATOR_STR, uni, ext); GNUNET_free (par); return epar; } /** * Synchronize this download struct with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param dc the struct to sync */ void GNUNET_FS_download_sync_ (struct GNUNET_FS_DownloadContext *dc) { struct GNUNET_BIO_WriteHandle *wh; char *uris; char *fn; char *dir; if (0 != (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) return; /* we don't sync probes */ if (NULL == dc->serialization) { dir = get_download_sync_filename (dc, "", ""); if (NULL == dir) return; if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (dir)) { GNUNET_free (dir); return; } fn = GNUNET_DISK_mktemp (dir); GNUNET_free (dir); if (NULL == fn) return; dc->serialization = get_serialization_short_name (fn); } else { fn = get_download_sync_filename (dc, dc->serialization, ""); if (NULL == fn) { GNUNET_free (dc->serialization); dc->serialization = NULL; GNUNET_free (fn); return; } } wh = GNUNET_BIO_write_open (fn); if (NULL == wh) { GNUNET_free (dc->serialization); dc->serialization = NULL; GNUNET_free (fn); return; } GNUNET_assert ((GNUNET_YES == GNUNET_FS_uri_test_chk (dc->uri)) || (GNUNET_YES == GNUNET_FS_uri_test_loc (dc->uri))); uris = GNUNET_FS_uri_to_string (dc->uri); if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) || (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, dc->meta)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, dc->emsg)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, dc->filename)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, dc->temp_filename)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dc->old_file_size)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dc->offset)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dc->length)) || (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dc->completed)) || (GNUNET_OK != write_start_time (wh, dc->start_time)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, dc->anonymity)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) dc->options)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) dc->has_finished))) { GNUNET_break (0); goto cleanup; } if (NULL == dc->emsg) { GNUNET_assert (dc->top_request != NULL); if (GNUNET_YES != write_download_request (wh, dc->top_request)) { GNUNET_break (0); goto cleanup; } } GNUNET_free_non_null (uris); uris = NULL; if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { wh = NULL; GNUNET_break (0); goto cleanup; } GNUNET_free (fn); return; cleanup: if (NULL != wh) (void) GNUNET_BIO_write_close (wh); GNUNET_free_non_null (uris); if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); GNUNET_free (fn); GNUNET_free (dc->serialization); dc->serialization = NULL; } /** * Synchronize this search result with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param sr the struct to sync */ void GNUNET_FS_search_result_sync_ (struct GNUNET_FS_SearchResult *sr) { struct GNUNET_BIO_WriteHandle *wh; char *uris; if (NULL == sr->sc) return; uris = NULL; if (NULL == sr->serialization) sr->serialization = make_serialization_file_name_in_dir (sr->h, (sr->sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sr->sc->serialization); if (NULL == sr->serialization) return; wh = get_write_handle_in_dir (sr->h, (sr->sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sr->sc->serialization, sr->serialization); if (NULL == wh) { GNUNET_break (0); goto cleanup; } uris = GNUNET_FS_uri_to_string (sr->uri); if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, sr->download != NULL ? sr->download->serialization : NULL)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, sr->update_search != NULL ? sr->update_search->serialization : NULL)) || (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, sr->meta)) || (GNUNET_OK != GNUNET_BIO_write (wh, &sr->key, sizeof (struct GNUNET_HashCode))) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sr->mandatory_missing)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sr->optional_support)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sr->availability_success)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sr->availability_trials)) ) { GNUNET_break (0); goto cleanup; } if ( (NULL != sr->uri) && (GNUNET_FS_URI_KSK == sr->sc->uri->type) && (GNUNET_OK != GNUNET_BIO_write (wh, sr->keyword_bitmap, (sr->sc->uri->data.ksk.keywordCount + 7) / 8)) ) { GNUNET_break (0); goto cleanup; } if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { wh = NULL; GNUNET_break (0); goto cleanup; } GNUNET_free_non_null (uris); return; cleanup: GNUNET_free_non_null (uris); if (NULL != wh) (void) GNUNET_BIO_write_close (wh); remove_sync_file_in_dir (sr->h, (NULL == sr->sc->psearch_result) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sr->sc->serialization, sr->serialization); GNUNET_free (sr->serialization); sr->serialization = NULL; } /** * Synchronize this search struct with its mirror * on disk. Note that all internal FS-operations that change * publishing structs should already call "sync" internally, * so this function is likely not useful for clients. * * @param sc the struct to sync */ void GNUNET_FS_search_sync_ (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_BIO_WriteHandle *wh; char *uris; char in_pause; const char *category; category = (NULL == sc->psearch_result) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH; if (NULL == sc->serialization) sc->serialization = make_serialization_file_name (sc->h, category); if (NULL == sc->serialization) return; uris = NULL; wh = get_write_handle (sc->h, category, sc->serialization); if (NULL == wh) { GNUNET_break (0); goto cleanup; } GNUNET_assert ((GNUNET_YES == GNUNET_FS_uri_test_ksk (sc->uri)) || (GNUNET_YES == GNUNET_FS_uri_test_sks (sc->uri))); uris = GNUNET_FS_uri_to_string (sc->uri); in_pause = (sc->task != GNUNET_SCHEDULER_NO_TASK) ? 'r' : '\0'; if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) || (GNUNET_OK != write_start_time (wh, sc->start_time)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, sc->emsg)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) sc->options)) || (GNUNET_OK != GNUNET_BIO_write (wh, &in_pause, sizeof (in_pause))) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sc->anonymity))) { GNUNET_break (0); goto cleanup; } GNUNET_free (uris); uris = NULL; if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { wh = NULL; GNUNET_break (0); goto cleanup; } return; cleanup: if (NULL != wh) (void) GNUNET_BIO_write_close (wh); GNUNET_free_non_null (uris); GNUNET_FS_remove_sync_file_ (sc->h, category, sc->serialization); GNUNET_free (sc->serialization); sc->serialization = NULL; } /** * Function called with a filename of serialized unindexing operation * to deserialize. * * @param cls the 'struct GNUNET_FS_Handle*' * @param filename complete filename (absolute path) * @return GNUNET_OK (continue to iterate) */ static int deserialize_unindex_file (void *cls, const char *filename) { struct GNUNET_FS_Handle *h = cls; struct GNUNET_BIO_ReadHandle *rh; struct GNUNET_FS_UnindexContext *uc; struct GNUNET_FS_ProgressInfo pi; char *emsg; char *uris; uint32_t state; uc = GNUNET_new (struct GNUNET_FS_UnindexContext); uc->h = h; uc->serialization = get_serialization_short_name (filename); rh = GNUNET_BIO_read_open (filename); if (NULL == rh) { GNUNET_break (0); goto cleanup; } uris = NULL; if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "unindex-fn", &uc->filename, 10 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &uc->file_size)) || (GNUNET_OK != read_start_time (rh, &uc->start_time)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &state)) || (GNUNET_OK != GNUNET_BIO_read (rh, "uri", &uc->chk, sizeof (struct ContentHashKey))) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "unindex-kskuri", &uris, 10 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &uc->ksk_offset)) ) { GNUNET_free_non_null (uris); GNUNET_break (0); goto cleanup; } if (NULL != uris) { uc->ksk_uri = GNUNET_FS_uri_parse (uris, &emsg); GNUNET_free (uris); if (NULL == uc->ksk_uri) { GNUNET_break (0); GNUNET_free_non_null (emsg); goto cleanup; } } if ( (uc->ksk_offset > 0) && ( (NULL == uc->ksk_uri) || (uc->ksk_offset > uc->ksk_uri->data.ksk.keywordCount) ) ) { GNUNET_break (0); goto cleanup; } uc->state = (enum UnindexState) state; switch (state) { case UNINDEX_STATE_HASHING: break; case UNINDEX_STATE_FS_NOTIFY: if (GNUNET_OK != GNUNET_BIO_read (rh, "unindex-hash", &uc->file_id, sizeof (struct GNUNET_HashCode))) { GNUNET_break (0); goto cleanup; } break; case UNINDEX_STATE_DS_REMOVE: case UNINDEX_STATE_EXTRACT_KEYWORDS: case UNINDEX_STATE_DS_REMOVE_KBLOCKS: break; case UNINDEX_STATE_COMPLETE: break; case UNINDEX_STATE_ERROR: if (GNUNET_OK != GNUNET_BIO_read_string (rh, "unindex-emsg", &uc->emsg, 10 * 1024)) { GNUNET_break (0); goto cleanup; } break; default: GNUNET_break (0); goto cleanup; } uc->top = GNUNET_FS_make_top (h, &GNUNET_FS_unindex_signal_suspend_, uc); pi.status = GNUNET_FS_STATUS_UNINDEX_RESUME; pi.value.unindex.specifics.resume.message = uc->emsg; GNUNET_FS_unindex_make_status_ (&pi, uc, (uc->state == UNINDEX_STATE_COMPLETE) ? uc->file_size : 0); switch (uc->state) { case UNINDEX_STATE_HASHING: uc->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE, uc->filename, HASHING_BLOCKSIZE, &GNUNET_FS_unindex_process_hash_, uc); break; case UNINDEX_STATE_FS_NOTIFY: uc->state = UNINDEX_STATE_HASHING; GNUNET_FS_unindex_process_hash_ (uc, &uc->file_id); break; case UNINDEX_STATE_DS_REMOVE: GNUNET_FS_unindex_do_remove_ (uc); break; case UNINDEX_STATE_EXTRACT_KEYWORDS: GNUNET_FS_unindex_do_extract_keywords_ (uc); break; case UNINDEX_STATE_DS_REMOVE_KBLOCKS: GNUNET_FS_unindex_do_remove_kblocks_ (uc); break; case UNINDEX_STATE_COMPLETE: case UNINDEX_STATE_ERROR: /* no need to resume any operation, we were done */ break; default: break; } if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failure while resuming unindexing operation `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } return GNUNET_OK; cleanup: GNUNET_free_non_null (uc->filename); if ((NULL != rh) && (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to resume unindexing operation `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } if (NULL != uc->serialization) GNUNET_FS_remove_sync_file_ (h, GNUNET_FS_SYNC_PATH_MASTER_UNINDEX, uc->serialization); GNUNET_free_non_null (uc->serialization); GNUNET_free (uc); return GNUNET_OK; } /** * Deserialize a download. * * @param h overall context * @param rh file to deserialize from * @param parent parent download * @param search associated search * @param serialization name under which the search was serialized */ static void deserialize_download (struct GNUNET_FS_Handle *h, struct GNUNET_BIO_ReadHandle *rh, struct GNUNET_FS_DownloadContext *parent, struct GNUNET_FS_SearchResult *search, const char *serialization); /** * Deserialize a search. * * @param h overall context * @param rh file to deserialize from * @param psearch_result parent search result * @param serialization name under which the search was serialized */ static struct GNUNET_FS_SearchContext * deserialize_search (struct GNUNET_FS_Handle *h, struct GNUNET_BIO_ReadHandle *rh, struct GNUNET_FS_SearchResult *psearch_result, const char *serialization); /** * Function called with a filename of serialized search result * to deserialize. * * @param cls the 'struct GNUNET_FS_SearchContext*' * @param filename complete filename (absolute path) * @return #GNUNET_OK (continue to iterate) */ static int deserialize_search_result (void *cls, const char *filename) { struct GNUNET_FS_SearchContext *sc = cls; char *ser; char *uris; char *emsg; char *download; char *update_srch; struct GNUNET_BIO_ReadHandle *rh; struct GNUNET_BIO_ReadHandle *drh; struct GNUNET_FS_SearchResult *sr; ser = get_serialization_short_name (filename); rh = GNUNET_BIO_read_open (filename); if (NULL == rh) { if (NULL != ser) { remove_sync_file_in_dir (sc->h, (NULL == sc->psearch_result) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sc->serialization, ser); GNUNET_free (ser); } return GNUNET_OK; } emsg = NULL; uris = NULL; download = NULL; update_srch = NULL; sr = GNUNET_new (struct GNUNET_FS_SearchResult); sr->h = sc->h; sr->sc = sc; sr->serialization = ser; if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "result-uri", &uris, 10 * 1024)) || (NULL == (sr->uri = GNUNET_FS_uri_parse (uris, &emsg))) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "download-lnk", &download, 16)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "search-lnk", &update_srch, 16)) || (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "result-meta", &sr->meta)) || (GNUNET_OK != GNUNET_BIO_read (rh, "result-key", &sr->key, sizeof (struct GNUNET_HashCode))) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->mandatory_missing)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->optional_support)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->availability_success)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->availability_trials))) { GNUNET_break (0); goto cleanup; } if (GNUNET_FS_URI_KSK == sr->sc->uri->type) { sr->keyword_bitmap = GNUNET_malloc ((sr->sc->uri->data.ksk.keywordCount + 7) / 8); /* round up, count bits */ if (GNUNET_OK != GNUNET_BIO_read (rh, "keyword-bitmap", sr->keyword_bitmap, (sr->sc->uri->data.ksk.keywordCount + 7) / 8)) { GNUNET_break (0); goto cleanup; } } GNUNET_free (uris); if (NULL != download) { drh = get_read_handle (sc->h, GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD, download); if (NULL != drh) { deserialize_download (sc->h, drh, NULL, sr, download); if (GNUNET_OK != GNUNET_BIO_read_close (drh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to resume sub-download `%s': %s\n"), download, emsg); GNUNET_free (emsg); } } GNUNET_free (download); } if (NULL != update_srch) { drh = get_read_handle (sc->h, GNUNET_FS_SYNC_PATH_CHILD_SEARCH, update_srch); if (NULL != drh) { deserialize_search (sc->h, drh, sr, update_srch); if (GNUNET_OK != GNUNET_BIO_read_close (drh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to resume sub-search `%s': %s\n"), update_srch, emsg); GNUNET_free (emsg); } } GNUNET_free (update_srch); } GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, &sr->key, sr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failure while resuming search operation `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } return GNUNET_OK; cleanup: GNUNET_free_non_null (download); GNUNET_free_non_null (emsg); GNUNET_free_non_null (uris); GNUNET_free_non_null (update_srch); if (NULL != sr->uri) GNUNET_FS_uri_destroy (sr->uri); if (NULL != sr->meta) GNUNET_CONTAINER_meta_data_destroy (sr->meta); GNUNET_free (sr->serialization); GNUNET_free (sr); if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failure while resuming search operation `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } return GNUNET_OK; } /** * Send the 'resume' signal to the callback; also actually * resume the download (put it in the queue). Does this * recursively for the top-level download and all child * downloads. * * @param dc download to resume */ static void signal_download_resume (struct GNUNET_FS_DownloadContext *dc) { struct GNUNET_FS_DownloadContext *dcc; struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_DOWNLOAD_RESUME; pi.value.download.specifics.resume.meta = dc->meta; pi.value.download.specifics.resume.message = dc->emsg; GNUNET_FS_download_make_status_ (&pi, dc); dcc = dc->child_head; while (NULL != dcc) { signal_download_resume (dcc); dcc = dcc->next; } if (NULL != dc->pending_head) GNUNET_FS_download_start_downloading_ (dc); } /** * Signal resuming of a search to our clients (for the * top level search and all sub-searches). * * @param sc search being resumed */ static void signal_search_resume (struct GNUNET_FS_SearchContext *sc); /** * Iterator over search results signaling resume to the client for * each result. * * @param cls closure, the 'struct GNUNET_FS_SearchContext' * @param key current key code * @param value value in the hash map, the 'struct GNUNET_FS_SearchResult' * @return GNUNET_YES (we should continue to iterate) */ static int signal_result_resume (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GNUNET_FS_SearchContext *sc = cls; struct GNUNET_FS_ProgressInfo pi; struct GNUNET_FS_SearchResult *sr = value; if (0 == sr->mandatory_missing) { pi.status = GNUNET_FS_STATUS_SEARCH_RESUME_RESULT; pi.value.search.specifics.resume_result.meta = sr->meta; pi.value.search.specifics.resume_result.uri = sr->uri; pi.value.search.specifics.resume_result.result = sr; pi.value.search.specifics.resume_result.availability_rank = 2 * sr->availability_success - sr->availability_trials; pi.value.search.specifics.resume_result.availability_certainty = sr->availability_trials; pi.value.search.specifics.resume_result.applicability_rank = sr->optional_support; sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); } if (NULL != sr->download) { signal_download_resume (sr->download); } else { GNUNET_FS_search_start_probe_ (sr); } if (NULL != sr->update_search) signal_search_resume (sr->update_search); return GNUNET_YES; } /** * Free memory allocated by the search context and its children * * @param sc search context to free */ static void free_search_context (struct GNUNET_FS_SearchContext *sc); /** * Iterator over search results freeing each. * * @param cls closure, the 'struct GNUNET_FS_SearchContext' * @param key current key code * @param value value in the hash map, the 'struct GNUNET_FS_SearchResult' * @return GNUNET_YES (we should continue to iterate) */ static int free_result (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GNUNET_FS_SearchResult *sr = value; if (NULL != sr->update_search) { free_search_context (sr->update_search); GNUNET_assert (NULL == sr->update_search); } GNUNET_CONTAINER_meta_data_destroy (sr->meta); GNUNET_FS_uri_destroy (sr->uri); GNUNET_free (sr); return GNUNET_YES; } /** * Free memory allocated by the search context and its children * * @param sc search context to free */ static void free_search_context (struct GNUNET_FS_SearchContext *sc) { if (NULL != sc->serialization) { GNUNET_FS_remove_sync_file_ (sc->h, (sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sc->serialization); GNUNET_FS_remove_sync_dir_ (sc->h, (sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sc->serialization); } GNUNET_free_non_null (sc->serialization); GNUNET_free_non_null (sc->emsg); if (NULL != sc->uri) GNUNET_FS_uri_destroy (sc->uri); if (NULL != sc->master_result_map) { GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &free_result, sc); GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); } GNUNET_free (sc); } /** * Function called with a filename of serialized sub-download * to deserialize. * * @param cls the 'struct GNUNET_FS_DownloadContext*' (parent) * @param filename complete filename (absolute path) * @return #GNUNET_OK (continue to iterate) */ static int deserialize_subdownload (void *cls, const char *filename) { struct GNUNET_FS_DownloadContext *parent = cls; char *ser; char *emsg; struct GNUNET_BIO_ReadHandle *rh; ser = get_serialization_short_name (filename); rh = GNUNET_BIO_read_open (filename); if (NULL == rh) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Failed to resume sub-download `%s': could not open file `%s'\n"), ser, filename); GNUNET_free (ser); return GNUNET_OK; } deserialize_download (parent->h, rh, parent, NULL, ser); if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to resume sub-download `%s': %s\n"), ser, emsg); GNUNET_free (emsg); } GNUNET_free (ser); return GNUNET_OK; } /** * Free this download context and all of its descendants. * (only works during deserialization since not all possible * state it taken care of). * * @param dc context to free */ static void free_download_context (struct GNUNET_FS_DownloadContext *dc) { struct GNUNET_FS_DownloadContext *dcc; if (NULL != dc->meta) GNUNET_CONTAINER_meta_data_destroy (dc->meta); if (NULL != dc->uri) GNUNET_FS_uri_destroy (dc->uri); GNUNET_free_non_null (dc->temp_filename); GNUNET_free_non_null (dc->emsg); GNUNET_free_non_null (dc->filename); GNUNET_free_non_null (dc->serialization); while (NULL != (dcc = dc->child_head)) { GNUNET_CONTAINER_DLL_remove (dc->child_head, dc->child_tail, dcc); free_download_context (dcc); } GNUNET_FS_free_download_request_ (dc->top_request); if (NULL != dc->active) GNUNET_CONTAINER_multihashmap_destroy (dc->active); GNUNET_free (dc); } /** * Deserialize a download. * * @param h overall context * @param rh file to deserialize from * @param parent parent download * @param search associated search * @param serialization name under which the search was serialized */ static void deserialize_download (struct GNUNET_FS_Handle *h, struct GNUNET_BIO_ReadHandle *rh, struct GNUNET_FS_DownloadContext *parent, struct GNUNET_FS_SearchResult *search, const char *serialization) { struct GNUNET_FS_DownloadContext *dc; char *emsg; char *uris; char *dn; uint32_t options; uint32_t status; uris = NULL; emsg = NULL; dc = GNUNET_new (struct GNUNET_FS_DownloadContext); dc->parent = parent; dc->h = h; dc->serialization = GNUNET_strdup (serialization); if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "download-uri", &uris, 10 * 1024)) || (NULL == (dc->uri = GNUNET_FS_uri_parse (uris, &emsg))) || ((GNUNET_YES != GNUNET_FS_uri_test_chk (dc->uri)) && (GNUNET_YES != GNUNET_FS_uri_test_loc (dc->uri))) || (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "download-meta", &dc->meta)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "download-emsg", &dc->emsg, 10 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "download-fn", &dc->filename, 10 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "download-tfn", &dc->temp_filename, 10 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->old_file_size)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->offset)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->length)) || (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->completed)) || (GNUNET_OK != read_start_time (rh, &dc->start_time)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dc->anonymity)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &status))) { GNUNET_break (0); goto cleanup; } dc->options = (enum GNUNET_FS_DownloadOptions) options; dc->active = GNUNET_CONTAINER_multihashmap_create (1 + 2 * (dc->length / DBLOCK_SIZE), GNUNET_NO); dc->has_finished = (int) status; dc->treedepth = GNUNET_FS_compute_depth (GNUNET_FS_uri_chk_get_file_size (dc->uri)); if (GNUNET_FS_uri_test_loc (dc->uri)) GNUNET_assert (GNUNET_OK == GNUNET_FS_uri_loc_get_peer_identity (dc->uri, &dc->target)); if (NULL == dc->emsg) { dc->top_request = read_download_request (rh); if (NULL == dc->top_request) { GNUNET_break (0); goto cleanup; } } dn = get_download_sync_filename (dc, dc->serialization, ".dir"); if (NULL != dn) { if (GNUNET_YES == GNUNET_DISK_directory_test (dn, GNUNET_YES)) GNUNET_DISK_directory_scan (dn, &deserialize_subdownload, dc); GNUNET_free (dn); } if (NULL != parent) { GNUNET_CONTAINER_DLL_insert (parent->child_head, parent->child_tail, dc); } if (NULL != search) { dc->search = search; search->download = dc; } if ((NULL == parent) && (NULL == search)) { dc->top = GNUNET_FS_make_top (dc->h, &GNUNET_FS_download_signal_suspend_, dc); signal_download_resume (dc); } GNUNET_free (uris); dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, dc); return; cleanup: GNUNET_free_non_null (uris); GNUNET_free_non_null (emsg); free_download_context (dc); } /** * Signal resuming of a search to our clients (for the * top level search and all sub-searches). * * @param sc search being resumed */ static void signal_search_resume (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_SEARCH_RESUME; pi.value.search.specifics.resume.message = sc->emsg; pi.value.search.specifics.resume.is_paused = (NULL == sc->client) ? GNUNET_YES : GNUNET_NO; sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &signal_result_resume, sc); } /** * Deserialize a search. * * @param h overall context * @param rh file to deserialize from * @param psearch_result parent search result * @param serialization name under which the search was serialized */ static struct GNUNET_FS_SearchContext * deserialize_search (struct GNUNET_FS_Handle *h, struct GNUNET_BIO_ReadHandle *rh, struct GNUNET_FS_SearchResult *psearch_result, const char *serialization) { struct GNUNET_FS_SearchContext *sc; char *emsg; char *uris; char *dn; uint32_t options; char in_pause; if ((NULL != psearch_result) && (NULL != psearch_result->update_search)) { GNUNET_break (0); return NULL; } uris = NULL; emsg = NULL; sc = GNUNET_new (struct GNUNET_FS_SearchContext); if (NULL != psearch_result) { sc->psearch_result = psearch_result; psearch_result->update_search = sc; } sc->h = h; sc->serialization = GNUNET_strdup (serialization); if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "search-uri", &uris, 10 * 1024)) || (NULL == (sc->uri = GNUNET_FS_uri_parse (uris, &emsg))) || ((GNUNET_YES != GNUNET_FS_uri_test_ksk (sc->uri)) && (GNUNET_YES != GNUNET_FS_uri_test_sks (sc->uri))) || (GNUNET_OK != read_start_time (rh, &sc->start_time)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "search-emsg", &sc->emsg, 10 * 1024)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) || (GNUNET_OK != GNUNET_BIO_read (rh, "search-pause", &in_pause, sizeof (in_pause))) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sc->anonymity))) { GNUNET_break (0); goto cleanup; } sc->options = (enum GNUNET_FS_SearchOptions) options; sc->master_result_map = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO); dn = get_serialization_file_name_in_dir (h, (sc->psearch_result == NULL) ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH : GNUNET_FS_SYNC_PATH_CHILD_SEARCH, sc->serialization, ""); if (NULL != dn) { if (GNUNET_YES == GNUNET_DISK_directory_test (dn, GNUNET_YES)) GNUNET_DISK_directory_scan (dn, &deserialize_search_result, sc); GNUNET_free (dn); } if (('\0' == in_pause) && (GNUNET_OK != GNUNET_FS_search_start_searching_ (sc))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not resume running search, will resume as paused search\n")); } signal_search_resume (sc); GNUNET_free (uris); return sc; cleanup: GNUNET_free_non_null (emsg); free_search_context (sc); GNUNET_free_non_null (uris); return NULL; } /** * Function called with a filename of serialized search operation * to deserialize. * * @param cls the 'struct GNUNET_FS_Handle*' * @param filename complete filename (absolute path) * @return #GNUNET_OK (continue to iterate) */ static int deserialize_search_file (void *cls, const char *filename) { struct GNUNET_FS_Handle *h = cls; char *ser; char *emsg; struct GNUNET_BIO_ReadHandle *rh; struct GNUNET_FS_SearchContext *sc; struct stat buf; if (0 != STAT (filename, &buf)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename); return GNUNET_OK; } if (S_ISDIR (buf.st_mode)) return GNUNET_OK; /* skip directories */ ser = get_serialization_short_name (filename); rh = GNUNET_BIO_read_open (filename); if (NULL == rh) { if (NULL != ser) { GNUNET_FS_remove_sync_file_ (h, GNUNET_FS_SYNC_PATH_MASTER_SEARCH, ser); GNUNET_free (ser); } return GNUNET_OK; } sc = deserialize_search (h, rh, NULL, ser); if (NULL != sc) sc->top = GNUNET_FS_make_top (h, &GNUNET_FS_search_signal_suspend_, sc); GNUNET_free (ser); if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failure while resuming search operation `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } return GNUNET_OK; } /** * Function called with a filename of serialized download operation * to deserialize. * * @param cls the 'struct GNUNET_FS_Handle*' * @param filename complete filename (absolute path) * @return #GNUNET_OK (continue to iterate) */ static int deserialize_download_file (void *cls, const char *filename) { struct GNUNET_FS_Handle *h = cls; char *ser; char *emsg; struct GNUNET_BIO_ReadHandle *rh; ser = get_serialization_short_name (filename); rh = GNUNET_BIO_read_open (filename); if (NULL == rh) { if (0 != UNLINK (filename)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); GNUNET_free (ser); return GNUNET_OK; } deserialize_download (h, rh, NULL, NULL, ser); GNUNET_free (ser); if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failure while resuming download operation `%s': %s\n"), filename, emsg); GNUNET_free (emsg); } return GNUNET_OK; } /** * Deserialize informatin about pending operations. * * @param master_path which master directory should be scanned * @param proc function to call for each entry (will get 'h' for 'cls') * @param h the 'struct GNUNET_FS_Handle*' */ static void deserialization_master (const char *master_path, GNUNET_FileNameCallback proc, struct GNUNET_FS_Handle *h) { char *dn; dn = get_serialization_file_name (h, master_path, ""); if (NULL == dn) return; if (GNUNET_YES == GNUNET_DISK_directory_test (dn, GNUNET_YES)) GNUNET_DISK_directory_scan (dn, proc, h); GNUNET_free (dn); } /** * Setup a connection to the file-sharing service. * * @param cfg configuration to use * @param client_name unique identifier for this client * @param upcb function to call to notify about FS actions * @param upcb_cls closure for upcb * @param flags specific attributes for fs-operations * @param ... list of optional options, terminated with GNUNET_FS_OPTIONS_END * @return NULL on error */ struct GNUNET_FS_Handle * GNUNET_FS_start (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *client_name, GNUNET_FS_ProgressCallback upcb, void *upcb_cls, enum GNUNET_FS_Flags flags, ...) { struct GNUNET_FS_Handle *ret; enum GNUNET_FS_OPTIONS opt; va_list ap; ret = GNUNET_new (struct GNUNET_FS_Handle); ret->cfg = cfg; ret->client_name = GNUNET_strdup (client_name); ret->upcb = upcb; ret->upcb_cls = upcb_cls; ret->flags = flags; ret->max_parallel_downloads = DEFAULT_MAX_PARALLEL_DOWNLOADS; ret->max_parallel_requests = DEFAULT_MAX_PARALLEL_REQUESTS; ret->avg_block_latency = GNUNET_TIME_UNIT_MINUTES; /* conservative starting point */ va_start (ap, flags); while (GNUNET_FS_OPTIONS_END != (opt = va_arg (ap, enum GNUNET_FS_OPTIONS))) { switch (opt) { case GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM: ret->max_parallel_downloads = va_arg (ap, unsigned int); break; case GNUNET_FS_OPTIONS_REQUEST_PARALLELISM: ret->max_parallel_requests = va_arg (ap, unsigned int); break; default: GNUNET_break (0); GNUNET_free (ret->client_name); GNUNET_free (ret); va_end (ap); return NULL; } } va_end (ap); if (0 != (GNUNET_FS_FLAGS_PERSISTENCE & flags)) { deserialization_master (GNUNET_FS_SYNC_PATH_MASTER_PUBLISH, &deserialize_publish_file, ret); deserialization_master (GNUNET_FS_SYNC_PATH_MASTER_SEARCH, &deserialize_search_file, ret); deserialization_master (GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, &deserialize_download_file, ret); deserialization_master (GNUNET_FS_SYNC_PATH_MASTER_UNINDEX, &deserialize_unindex_file, ret); } return ret; } /** * Close our connection with the file-sharing service. * The callback given to GNUNET_FS_start will no longer be * called after this function returns. * * @param h handle that was returned from GNUNET_FS_start */ void GNUNET_FS_stop (struct GNUNET_FS_Handle *h) { while (h->top_head != NULL) h->top_head->ssf (h->top_head->ssf_cls); if (h->queue_job != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (h->queue_job); GNUNET_free (h->client_name); GNUNET_free (h); } /* end of fs.c */ gnunet-0.10.1/src/fs/test_fs_list_indexed_data.conf0000644000175000017500000000022012225230043017236 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-list-indexed/ [transport] PLUGINS = [fs] ACTIVEMIGRATION = NO gnunet-0.10.1/src/fs/gnunet-service-fs_cp.c0000644000175000017500000015420312272516176015421 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_cp.c * @brief API to handle 'connected peers' * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_load_lib.h" #include "gnunet-service-fs.h" #include "gnunet-service-fs_cp.h" #include "gnunet-service-fs_pe.h" #include "gnunet-service-fs_pr.h" #include "gnunet-service-fs_push.h" /** * Ratio for moving average delay calculation. The previous * average goes in with a factor of (n-1) into the calculation. * Must be > 0. */ #define RUNAVG_DELAY_N 16 /** * How often do we flush respect values to disk? */ #define RESPECT_FLUSH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) /** * After how long do we discard a reply? */ #define REPLY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) /** * Collect an instane number of statistics? May cause excessive IPC. */ #define INSANE_STATISTICS GNUNET_NO /** * Handle to cancel a transmission request. */ struct GSF_PeerTransmitHandle { /** * Kept in a doubly-linked list. */ struct GSF_PeerTransmitHandle *next; /** * Kept in a doubly-linked list. */ struct GSF_PeerTransmitHandle *prev; /** * Time when this transmission request was issued. */ struct GNUNET_TIME_Absolute transmission_request_start_time; /** * Timeout for this request. */ struct GNUNET_TIME_Absolute timeout; /** * Task called on timeout, or 0 for none. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Function to call to get the actual message. */ GSF_GetMessageCallback gmc; /** * Peer this request targets. */ struct GSF_ConnectedPeer *cp; /** * Closure for @e gmc. */ void *gmc_cls; /** * Size of the message to be transmitted. */ size_t size; /** * #GNUNET_YES if this is a query, #GNUNET_NO for content. */ int is_query; /** * Did we get a reservation already? */ int was_reserved; /** * Priority of this request. */ uint32_t priority; }; /** * Handle for an entry in our delay list. */ struct GSF_DelayedHandle { /** * Kept in a doubly-linked list. */ struct GSF_DelayedHandle *next; /** * Kept in a doubly-linked list. */ struct GSF_DelayedHandle *prev; /** * Peer this transmission belongs to. */ struct GSF_ConnectedPeer *cp; /** * The PUT that was delayed. */ struct PutMessage *pm; /** * Task for the delay. */ GNUNET_SCHEDULER_TaskIdentifier delay_task; /** * Size of the message. */ size_t msize; }; /** * Information per peer and request. */ struct PeerRequest { /** * Handle to generic request. */ struct GSF_PendingRequest *pr; /** * Handle to specific peer. */ struct GSF_ConnectedPeer *cp; /** * Task for asynchronous stopping of this request. */ GNUNET_SCHEDULER_TaskIdentifier kill_task; }; /** * A connected peer. */ struct GSF_ConnectedPeer { /** * Performance data for this peer. */ struct GSF_PeerPerformanceData ppd; /** * Time until when we blocked this peer from migrating * data to us. */ struct GNUNET_TIME_Absolute last_migration_block; /** * Task scheduled to revive migration to this peer. */ GNUNET_SCHEDULER_TaskIdentifier mig_revive_task; /** * Messages (replies, queries, content migration) we would like to * send to this peer in the near future. Sorted by priority, head. */ struct GSF_PeerTransmitHandle *pth_head; /** * Messages (replies, queries, content migration) we would like to * send to this peer in the near future. Sorted by priority, tail. */ struct GSF_PeerTransmitHandle *pth_tail; /** * Messages (replies, queries, content migration) we would like to * send to this peer in the near future. Sorted by priority, head. */ struct GSF_DelayedHandle *delayed_head; /** * Messages (replies, queries, content migration) we would like to * send to this peer in the near future. Sorted by priority, tail. */ struct GSF_DelayedHandle *delayed_tail; /** * Migration stop message in our queue, or NULL if we have none pending. */ struct GSF_PeerTransmitHandle *migration_pth; /** * Context of our GNUNET_ATS_reserve_bandwidth call (or NULL). */ struct GNUNET_ATS_ReservationContext *rc; /** * Task scheduled if we need to retry bandwidth reservation later. */ GNUNET_SCHEDULER_TaskIdentifier rc_delay_task; /** * Active requests from this neighbour, map of query to 'struct PeerRequest'. */ struct GNUNET_CONTAINER_MultiHashMap *request_map; /** * Handle for an active request for transmission to this * peer, or NULL (if core queue was full). */ struct GNUNET_CORE_TransmitHandle *cth; /** * Increase in traffic preference still to be submitted * to the core service for this peer. */ uint64_t inc_preference; /** * Set to 1 if we're currently in the process of calling * #GNUNET_CORE_notify_transmit_ready() (so while @e cth is * NULL, we should not call notify_transmit_ready for this * handle right now). */ unsigned int cth_in_progress; /** * Respect rating for this peer on disk. */ uint32_t disk_respect; /** * Which offset in "last_p2p_replies" will be updated next? * (we go round-robin). */ unsigned int last_p2p_replies_woff; /** * Which offset in "last_client_replies" will be updated next? * (we go round-robin). */ unsigned int last_client_replies_woff; /** * Current offset into 'last_request_times' ring buffer. */ unsigned int last_request_times_off; /** * GNUNET_YES if we did successfully reserve 32k bandwidth, * GNUNET_NO if not. */ int did_reserve; }; /** * Map from peer identities to 'struct GSF_ConnectPeer' entries. */ static struct GNUNET_CONTAINER_MultiPeerMap *cp_map; /** * Where do we store respect information? */ static char *respectDirectory; /** * Get the filename under which we would store respect * for the given peer. * * @param id peer to get the filename for * @return filename of the form DIRECTORY/PEERID */ static char * get_respect_filename (const struct GNUNET_PeerIdentity *id) { char *fn; GNUNET_asprintf (&fn, "%s%s%s", respectDirectory, DIR_SEPARATOR_STR, GNUNET_i2s_full (id)); return fn; } /** * Update the latency information kept for the given peer. * * @param id peer record to update * @param latency current latency value */ void GSF_update_peer_latency_ (const struct GNUNET_PeerIdentity *id, struct GNUNET_TIME_Relative latency) { struct GSF_ConnectedPeer *cp; cp = GSF_peer_get_ (id); if (NULL == cp) return; /* we're not yet connected at the core level, ignore */ GNUNET_LOAD_value_set_decline (cp->ppd.transmission_delay, latency); /* LATER: merge atsi into cp's performance data (if we ever care...) */ } /** * Return the performance data record for the given peer * * @param cp peer to query * @return performance data record for the peer */ struct GSF_PeerPerformanceData * GSF_get_peer_performance_data_ (struct GSF_ConnectedPeer *cp) { return &cp->ppd; } /** * Core is ready to transmit to a peer, get the message. * * @param cls the 'struct GSF_PeerTransmitHandle' of the message * @param size number of bytes core is willing to take * @param buf where to copy the message * @return number of bytes copied to buf */ static size_t peer_transmit_ready_cb (void *cls, size_t size, void *buf); /** * Function called by core upon success or failure of our bandwidth reservation request. * * @param cls the 'struct GSF_ConnectedPeer' of the peer for which we made the request * @param peer identifies the peer * @param amount set to the amount that was actually reserved or unreserved; * either the full requested amount or zero (no partial reservations) * @param res_delay if the reservation could not be satisfied (amount was 0), how * long should the client wait until re-trying? */ static void ats_reserve_callback (void *cls, const struct GNUNET_PeerIdentity *peer, int32_t amount, struct GNUNET_TIME_Relative res_delay); /** * If ready (bandwidth reserved), try to schedule transmission via * core for the given handle. * * @param pth transmission handle to schedule */ static void schedule_transmission (struct GSF_PeerTransmitHandle *pth) { struct GSF_ConnectedPeer *cp; struct GNUNET_PeerIdentity target; cp = pth->cp; if ((NULL != cp->cth) || (0 != cp->cth_in_progress)) return; /* already done */ GNUNET_assert (0 != cp->ppd.pid); GNUNET_PEER_resolve (cp->ppd.pid, &target); if (0 != cp->inc_preference) { GNUNET_ATS_performance_change_preference (GSF_ats, &target, GNUNET_ATS_PREFERENCE_BANDWIDTH, (double) cp->inc_preference, GNUNET_ATS_PREFERENCE_END); cp->inc_preference = 0; } if ((GNUNET_YES == pth->is_query) && (GNUNET_YES != pth->was_reserved)) { /* query, need reservation */ if (GNUNET_YES != cp->did_reserve) return; /* not ready */ cp->did_reserve = GNUNET_NO; /* reservation already done! */ pth->was_reserved = GNUNET_YES; cp->rc = GNUNET_ATS_reserve_bandwidth (GSF_ats, &target, DBLOCK_SIZE, &ats_reserve_callback, cp); return; } GNUNET_assert (NULL == cp->cth); cp->cth_in_progress++; cp->cth = GNUNET_CORE_notify_transmit_ready (GSF_core, GNUNET_YES, GNUNET_CORE_PRIO_BACKGROUND, GNUNET_TIME_absolute_get_remaining (pth->timeout), &target, pth->size, &peer_transmit_ready_cb, cp); GNUNET_assert (NULL != cp->cth); GNUNET_assert (0 < cp->cth_in_progress--); } /** * Core is ready to transmit to a peer, get the message. * * @param cls the 'struct GSF_PeerTransmitHandle' of the message * @param size number of bytes core is willing to take * @param buf where to copy the message * @return number of bytes copied to buf */ static size_t peer_transmit_ready_cb (void *cls, size_t size, void *buf) { struct GSF_ConnectedPeer *cp = cls; struct GSF_PeerTransmitHandle *pth = cp->pth_head; struct GSF_PeerTransmitHandle *pos; size_t ret; cp->cth = NULL; if (NULL == pth) return 0; if (pth->size > size) { schedule_transmission (pth); return 0; } if (GNUNET_SCHEDULER_NO_TASK != pth->timeout_task) { GNUNET_SCHEDULER_cancel (pth->timeout_task); pth->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_DLL_remove (cp->pth_head, cp->pth_tail, pth); if (GNUNET_YES == pth->is_query) { cp->ppd.last_request_times[(cp->last_request_times_off++) % MAX_QUEUE_PER_PEER] = GNUNET_TIME_absolute_get (); GNUNET_assert (0 < cp->ppd.pending_queries--); } else if (GNUNET_NO == pth->is_query) { GNUNET_assert (0 < cp->ppd.pending_replies--); } GNUNET_LOAD_update (cp->ppd.transmission_delay, GNUNET_TIME_absolute_get_duration (pth->transmission_request_start_time).rel_value_us); ret = pth->gmc (pth->gmc_cls, size, buf); if (NULL != (pos = cp->pth_head)) { GNUNET_assert (pos != pth); schedule_transmission (pos); } GNUNET_free (pth); return ret; } /** * (re)try to reserve bandwidth from the given peer. * * @param cls the 'struct GSF_ConnectedPeer' to reserve from * @param tc scheduler context */ static void retry_reservation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSF_ConnectedPeer *cp = cls; struct GNUNET_PeerIdentity target; GNUNET_PEER_resolve (cp->ppd.pid, &target); cp->rc_delay_task = GNUNET_SCHEDULER_NO_TASK; cp->rc = GNUNET_ATS_reserve_bandwidth (GSF_ats, &target, DBLOCK_SIZE, &ats_reserve_callback, cp); } /** * Function called by core upon success or failure of our bandwidth reservation request. * * @param cls the 'struct GSF_ConnectedPeer' of the peer for which we made the request * @param peer identifies the peer * @param amount set to the amount that was actually reserved or unreserved; * either the full requested amount or zero (no partial reservations) * @param res_delay if the reservation could not be satisfied (amount was 0), how * long should the client wait until re-trying? */ static void ats_reserve_callback (void *cls, const struct GNUNET_PeerIdentity *peer, int32_t amount, struct GNUNET_TIME_Relative res_delay) { struct GSF_ConnectedPeer *cp = cls; struct GSF_PeerTransmitHandle *pth; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reserved %d bytes / need to wait %s for reservation\n", (int) amount, GNUNET_STRINGS_relative_time_to_string (res_delay, GNUNET_YES)); cp->rc = NULL; if (0 == amount) { cp->rc_delay_task = GNUNET_SCHEDULER_add_delayed (res_delay, &retry_reservation, cp); return; } cp->did_reserve = GNUNET_YES; pth = cp->pth_head; if ((NULL != pth) && (NULL == cp->cth) && (0 == cp->cth_in_progress)) { /* reservation success, try transmission now! */ cp->cth_in_progress++; cp->cth = GNUNET_CORE_notify_transmit_ready (GSF_core, GNUNET_YES, GNUNET_CORE_PRIO_BACKGROUND, GNUNET_TIME_absolute_get_remaining (pth->timeout), peer, pth->size, &peer_transmit_ready_cb, cp); GNUNET_assert (NULL != cp->cth); GNUNET_assert (0 < cp->cth_in_progress--); } } /** * A peer connected to us. Setup the connected peer * records. * * @param peer identity of peer that connected * @return handle to connected peer entry */ struct GSF_ConnectedPeer * GSF_peer_connect_handler_ (const struct GNUNET_PeerIdentity *peer) { struct GSF_ConnectedPeer *cp; char *fn; uint32_t respect; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to peer %s\n", GNUNET_i2s (peer)); cp = GNUNET_new (struct GSF_ConnectedPeer); cp->ppd.pid = GNUNET_PEER_intern (peer); cp->ppd.transmission_delay = GNUNET_LOAD_value_init (GNUNET_TIME_UNIT_ZERO); cp->rc = GNUNET_ATS_reserve_bandwidth (GSF_ats, peer, DBLOCK_SIZE, &ats_reserve_callback, cp); fn = get_respect_filename (peer); if ((GNUNET_YES == GNUNET_DISK_file_test (fn)) && (sizeof (respect) == GNUNET_DISK_fn_read (fn, &respect, sizeof (respect)))) cp->disk_respect = cp->ppd.respect = ntohl (respect); GNUNET_free (fn); cp->request_map = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (cp_map, GSF_connected_peer_get_identity2_ (cp), cp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# peers connected"), GNUNET_CONTAINER_multipeermap_size (cp_map), GNUNET_NO); GSF_push_start_ (cp); return cp; } /** * It may be time to re-start migrating content to this * peer. Check, and if so, restart migration. * * @param cls the 'struct GSF_ConnectedPeer' * @param tc scheduler context */ static void revive_migration (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSF_ConnectedPeer *cp = cls; struct GNUNET_TIME_Relative bt; cp->mig_revive_task = GNUNET_SCHEDULER_NO_TASK; bt = GNUNET_TIME_absolute_get_remaining (cp->ppd.migration_blocked_until); if (0 != bt.rel_value_us) { /* still time left... */ cp->mig_revive_task = GNUNET_SCHEDULER_add_delayed (bt, &revive_migration, cp); return; } GSF_push_start_ (cp); } /** * Get a handle for a connected peer. * * @param peer peer's identity * @return NULL if the peer is not currently connected */ struct GSF_ConnectedPeer * GSF_peer_get_ (const struct GNUNET_PeerIdentity *peer) { if (NULL == cp_map) return NULL; return GNUNET_CONTAINER_multipeermap_get (cp_map, peer); } /** * Handle P2P "MIGRATION_STOP" message. * * @param cls closure, always NULL * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GSF_handle_p2p_migration_stop_ (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { struct GSF_ConnectedPeer *cp; const struct MigrationStopMessage *msm; struct GNUNET_TIME_Relative bt; msm = (const struct MigrationStopMessage *) message; cp = GSF_peer_get_ (other); if (NULL == cp) { GNUNET_break (0); return GNUNET_OK; } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# migration stop messages received"), 1, GNUNET_NO); bt = GNUNET_TIME_relative_ntoh (msm->duration); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Migration of content to peer `%s' blocked for %s\n"), GNUNET_i2s (other), GNUNET_STRINGS_relative_time_to_string (bt, GNUNET_YES)); cp->ppd.migration_blocked_until = GNUNET_TIME_relative_to_absolute (bt); if (GNUNET_SCHEDULER_NO_TASK == cp->mig_revive_task) { GSF_push_stop_ (cp); cp->mig_revive_task = GNUNET_SCHEDULER_add_delayed (bt, &revive_migration, cp); } return GNUNET_OK; } /** * Copy reply and free put message. * * @param cls the 'struct PutMessage' * @param buf_size number of bytes available in buf * @param buf where to copy the message, NULL on error (peer disconnect) * @return number of bytes copied to 'buf', can be 0 (without indicating an error) */ static size_t copy_reply (void *cls, size_t buf_size, void *buf) { struct PutMessage *pm = cls; size_t size; if (NULL != buf) { GNUNET_assert (buf_size >= ntohs (pm->header.size)); size = ntohs (pm->header.size); memcpy (buf, pm, size); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies transmitted to other peers"), 1, GNUNET_NO); } else { size = 0; GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies dropped"), 1, GNUNET_NO); } GNUNET_free (pm); return size; } /** * Free resources associated with the given peer request. * * @param peerreq request to free * @param query associated key for the request */ static void free_pending_request (struct PeerRequest *peerreq, const struct GNUNET_HashCode *query) { struct GSF_ConnectedPeer *cp = peerreq->cp; if (GNUNET_SCHEDULER_NO_TASK != peerreq->kill_task) { GNUNET_SCHEDULER_cancel (peerreq->kill_task); peerreq->kill_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# P2P searches active"), -1, GNUNET_NO); GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (cp->request_map, query, peerreq)); GNUNET_free (peerreq); } /** * Cancel all requests associated with the peer. * * @param cls unused * @param query hash code of the request * @param value the 'struct GSF_PendingRequest' * @return GNUNET_YES (continue to iterate) */ static int cancel_pending_request (void *cls, const struct GNUNET_HashCode * query, void *value) { struct PeerRequest *peerreq = value; struct GSF_PendingRequest *pr = peerreq->pr; struct GSF_PendingRequestData *prd; prd = GSF_pending_request_get_data_ (pr); GSF_pending_request_cancel_ (pr, GNUNET_NO); free_pending_request (peerreq, &prd->query); return GNUNET_OK; } /** * Free the given request. * * @param cls the request to free * @param tc task context */ static void peer_request_destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerRequest *peerreq = cls; struct GSF_PendingRequest *pr = peerreq->pr; struct GSF_PendingRequestData *prd; peerreq->kill_task = GNUNET_SCHEDULER_NO_TASK; prd = GSF_pending_request_get_data_ (pr); cancel_pending_request (NULL, &prd->query, peerreq); } /** * The artificial delay is over, transmit the message now. * * @param cls the 'struct GSF_DelayedHandle' with the message * @param tc scheduler context */ static void transmit_delayed_now (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSF_DelayedHandle *dh = cls; struct GSF_ConnectedPeer *cp = dh->cp; GNUNET_CONTAINER_DLL_remove (cp->delayed_head, cp->delayed_tail, dh); if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) { GNUNET_free (dh->pm); GNUNET_free (dh); return; } (void) GSF_peer_transmit_ (cp, GNUNET_NO, UINT32_MAX, REPLY_TIMEOUT, dh->msize, ©_reply, dh->pm); GNUNET_free (dh); } /** * Get the randomized delay a response should be subjected to. * * @return desired delay */ static struct GNUNET_TIME_Relative get_randomized_delay () { struct GNUNET_TIME_Relative ret; ret = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2 * GSF_avg_latency.rel_value_us + 1)); #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# artificial delays introduced (ms)"), ret.rel_value_us / 1000LL, GNUNET_NO); #endif return ret; } /** * Handle a reply to a pending request. Also called if a request * expires (then with data == NULL). The handler may be called * many times (depending on the request type), but will not be * called during or after a call to GSF_pending_request_cancel * and will also not be called anymore after a call signalling * expiration. * * @param cls 'struct PeerRequest' this is an answer for * @param eval evaluation of the result * @param pr handle to the original pending request * @param reply_anonymity_level anonymity level for the reply, UINT32_MAX for "unknown" * @param expiration when does 'data' expire? * @param last_transmission when did we last transmit a request for this block * @param type type of the block * @param data response data, NULL on request expiration * @param data_len number of bytes in data */ static void handle_p2p_reply (void *cls, enum GNUNET_BLOCK_EvaluationResult eval, struct GSF_PendingRequest *pr, uint32_t reply_anonymity_level, struct GNUNET_TIME_Absolute expiration, struct GNUNET_TIME_Absolute last_transmission, enum GNUNET_BLOCK_Type type, const void *data, size_t data_len) { struct PeerRequest *peerreq = cls; struct GSF_ConnectedPeer *cp = peerreq->cp; struct GSF_PendingRequestData *prd; struct PutMessage *pm; size_t msize; GNUNET_assert (data_len + sizeof (struct PutMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); GNUNET_assert (peerreq->pr == pr); prd = GSF_pending_request_get_data_ (pr); if (NULL == data) { free_pending_request (peerreq, &prd->query); return; } GNUNET_break (GNUNET_BLOCK_TYPE_ANY != type); if ((prd->type != type) && (GNUNET_BLOCK_TYPE_ANY != prd->type)) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies dropped due to type mismatch"), 1, GNUNET_NO); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting result for query `%s' to peer\n", GNUNET_h2s (&prd->query)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies received for other peers"), 1, GNUNET_NO); msize = sizeof (struct PutMessage) + data_len; if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } if ((UINT32_MAX != reply_anonymity_level) && (reply_anonymity_level > 1)) { if (reply_anonymity_level - 1 > GSF_cover_content_count) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies dropped due to insufficient cover traffic"), 1, GNUNET_NO); return; } GSF_cover_content_count -= (reply_anonymity_level - 1); } pm = GNUNET_malloc (msize); pm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT); pm->header.size = htons (msize); pm->type = htonl (type); pm->expiration = GNUNET_TIME_absolute_hton (expiration); memcpy (&pm[1], data, data_len); if ((UINT32_MAX != reply_anonymity_level) && (0 != reply_anonymity_level) && (GNUNET_YES == GSF_enable_randomized_delays)) { struct GSF_DelayedHandle *dh; dh = GNUNET_new (struct GSF_DelayedHandle); dh->cp = cp; dh->pm = pm; dh->msize = msize; GNUNET_CONTAINER_DLL_insert (cp->delayed_head, cp->delayed_tail, dh); dh->delay_task = GNUNET_SCHEDULER_add_delayed (get_randomized_delay (), &transmit_delayed_now, dh); } else { (void) GSF_peer_transmit_ (cp, GNUNET_NO, UINT32_MAX, REPLY_TIMEOUT, msize, ©_reply, pm); } if (GNUNET_BLOCK_EVALUATION_OK_LAST != eval) return; if (GNUNET_SCHEDULER_NO_TASK == peerreq->kill_task) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# P2P searches destroyed due to ultimate reply"), 1, GNUNET_NO); peerreq->kill_task = GNUNET_SCHEDULER_add_now (&peer_request_destroy, peerreq); } } /** * Increase the peer's respect by a value. * * @param cp which peer to change the respect value on * @param value is the int value by which the * peer's credit is to be increased or decreased * @returns the actual change in respect (positive or negative) */ static int change_peer_respect (struct GSF_ConnectedPeer *cp, int value) { if (0 == value) return 0; GNUNET_assert (NULL != cp); if (value > 0) { if (cp->ppd.respect + value < cp->ppd.respect) { value = UINT32_MAX - cp->ppd.respect; cp->ppd.respect = UINT32_MAX; } else cp->ppd.respect += value; } else { if (cp->ppd.respect < -value) { value = -cp->ppd.respect; cp->ppd.respect = 0; } else cp->ppd.respect += value; } return value; } /** * We've received a request with the specified priority. Bound it * according to how much we respect the given peer. * * @param prio_in requested priority * @param cp the peer making the request * @return effective priority */ static int32_t bound_priority (uint32_t prio_in, struct GSF_ConnectedPeer *cp) { #define N ((double)128.0) uint32_t ret; double rret; int ld; ld = GSF_test_get_load_too_high_ (0); if (GNUNET_SYSERR == ld) { #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requests done for free (low load)"), 1, GNUNET_NO); #endif return 0; /* excess resources */ } if (prio_in > INT32_MAX) prio_in = INT32_MAX; ret = -change_peer_respect (cp, -(int) prio_in); if (ret > 0) { if (ret > GSF_current_priorities + N) rret = GSF_current_priorities + N; else rret = ret; GSF_current_priorities = (GSF_current_priorities * (N - 1) + rret) / N; } if ((GNUNET_YES == ld) && (ret > 0)) { /* try with charging */ ld = GSF_test_get_load_too_high_ (ret); } if (GNUNET_YES == ld) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# request dropped, priority insufficient"), 1, GNUNET_NO); /* undo charge */ change_peer_respect (cp, (int) ret); return -1; /* not enough resources */ } else { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requests done for a price (normal load)"), 1, GNUNET_NO); } #undef N return ret; } /** * The priority level imposes a bound on the maximum * value for the ttl that can be requested. * * @param ttl_in requested ttl * @param prio given priority * @return ttl_in if ttl_in is below the limit, * otherwise the ttl-limit for the given priority */ static int32_t bound_ttl (int32_t ttl_in, uint32_t prio) { unsigned long long allowed; if (ttl_in <= 0) return ttl_in; allowed = ((unsigned long long) prio) * TTL_DECREMENT / 1000; if (ttl_in > allowed) { if (allowed >= (1 << 30)) return 1 << 30; return allowed; } return ttl_in; } /** * Handle P2P "QUERY" message. Creates the pending request entry * and sets up all of the data structures to that we will * process replies properly. Does not initiate forwarding or * local database lookups. * * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message * @return pending request handle, NULL on error */ struct GSF_PendingRequest * GSF_handle_p2p_query_ (const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { struct PeerRequest *peerreq; struct GSF_PendingRequest *pr; struct GSF_PendingRequestData *prd; struct GSF_ConnectedPeer *cp; struct GSF_ConnectedPeer *cps; const struct GNUNET_PeerIdentity *target; enum GSF_PendingRequestOptions options; uint16_t msize; const struct GetMessage *gm; unsigned int bits; const struct GNUNET_PeerIdentity *opt; uint32_t bm; size_t bfsize; uint32_t ttl_decrement; int32_t priority; int32_t ttl; enum GNUNET_BLOCK_Type type; GNUNET_PEER_Id spid; GNUNET_assert (other != NULL); msize = ntohs (message->size); if (msize < sizeof (struct GetMessage)) { GNUNET_break_op (0); return NULL; } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# GET requests received (from other peers)"), 1, GNUNET_NO); gm = (const struct GetMessage *) message; type = ntohl (gm->type); bm = ntohl (gm->hash_bitmap); bits = 0; while (bm > 0) { if (1 == (bm & 1)) bits++; bm >>= 1; } if (msize < sizeof (struct GetMessage) + bits * sizeof (struct GNUNET_PeerIdentity)) { GNUNET_break_op (0); return NULL; } opt = (const struct GNUNET_PeerIdentity *) &gm[1]; bfsize = msize - sizeof (struct GetMessage) - bits * sizeof (struct GNUNET_PeerIdentity); /* bfsize must be power of 2, check! */ if (0 != ((bfsize - 1) & bfsize)) { GNUNET_break_op (0); return NULL; } GSF_cover_query_count++; bm = ntohl (gm->hash_bitmap); bits = 0; cps = GSF_peer_get_ (other); if (NULL == cps) { /* peer must have just disconnected */ GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requests dropped due to initiator not being connected"), 1, GNUNET_NO); return NULL; } if (0 != (bm & GET_MESSAGE_BIT_RETURN_TO)) cp = GSF_peer_get_ (&opt[bits++]); else cp = cps; if (NULL == cp) { if (0 != (bm & GET_MESSAGE_BIT_RETURN_TO)) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to find RETURN-TO peer `%4s' in connection set. Dropping query.\n", GNUNET_i2s (&opt[bits - 1])); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to find peer `%4s' in connection set. Dropping query.\n", GNUNET_i2s (other)); #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requests dropped due to missing reverse route"), 1, GNUNET_NO); #endif return NULL; } /* note that we can really only check load here since otherwise * peers could find out that we are overloaded by not being * disconnected after sending us a malformed query... */ priority = bound_priority (ntohl (gm->priority), cps); if (priority < 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dropping query from `%s', this peer is too busy.\n", GNUNET_i2s (other)); return NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received request for `%s' of type %u from peer `%4s' with flags %u\n", GNUNET_h2s (&gm->query), (unsigned int) type, GNUNET_i2s (other), (unsigned int) bm); target = (0 != (bm & GET_MESSAGE_BIT_TRANSMIT_TO)) ? (&opt[bits++]) : NULL; options = GSF_PRO_DEFAULTS; spid = 0; if ((GNUNET_LOAD_get_load (cp->ppd.transmission_delay) > 3 * (1 + priority)) || (GNUNET_LOAD_get_average (cp->ppd.transmission_delay) > GNUNET_CONSTANTS_MAX_CORK_DELAY.rel_value_us * 2 + GNUNET_LOAD_get_average (GSF_rt_entry_lifetime))) { /* don't have BW to send to peer, or would likely take longer than we have for it, * so at best indirect the query */ priority = 0; options |= GSF_PRO_FORWARD_ONLY; spid = GNUNET_PEER_intern (other); GNUNET_assert (0 != spid); } ttl = bound_ttl (ntohl (gm->ttl), priority); /* decrement ttl (always) */ ttl_decrement = 2 * TTL_DECREMENT + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, TTL_DECREMENT); if ((ttl < 0) && (((int32_t) (ttl - ttl_decrement)) > 0)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dropping query from `%s' due to TTL underflow (%d - %u).\n", GNUNET_i2s (other), ttl, ttl_decrement); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requests dropped due TTL underflow"), 1, GNUNET_NO); /* integer underflow => drop (should be very rare)! */ return NULL; } ttl -= ttl_decrement; /* test if the request already exists */ peerreq = GNUNET_CONTAINER_multihashmap_get (cp->request_map, &gm->query); if (peerreq != NULL) { pr = peerreq->pr; prd = GSF_pending_request_get_data_ (pr); if (prd->type == type) { if (prd->ttl.abs_value_us >= GNUNET_TIME_absolute_get ().abs_value_us + ttl * 1000LL) { /* existing request has higher TTL, drop new one! */ prd->priority += priority; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have existing request with higher TTL, dropping new request.\n", GNUNET_i2s (other)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requests dropped due to higher-TTL request"), 1, GNUNET_NO); return NULL; } /* existing request has lower TTL, drop old one! */ priority += prd->priority; GSF_pending_request_cancel_ (pr, GNUNET_YES); free_pending_request (peerreq, &gm->query); } } peerreq = GNUNET_new (struct PeerRequest); peerreq->cp = cp; pr = GSF_pending_request_create_ (options, type, &gm->query, target, (bfsize > 0) ? (const char *) &opt[bits] : NULL, bfsize, ntohl (gm->filter_mutator), 1 /* anonymity */ , (uint32_t) priority, ttl, spid, GNUNET_PEER_intern (other), NULL, 0, /* replies_seen */ &handle_p2p_reply, peerreq); GNUNET_assert (NULL != pr); peerreq->pr = pr; GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (cp->request_map, &gm->query, peerreq, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# P2P query messages received and processed"), 1, GNUNET_NO); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# P2P searches active"), 1, GNUNET_NO); return pr; } /** * Function called if there has been a timeout trying to satisfy * a transmission request. * * @param cls the 'struct GSF_PeerTransmitHandle' of the request * @param tc scheduler context */ static void peer_transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSF_PeerTransmitHandle *pth = cls; struct GSF_ConnectedPeer *cp; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout trying to transmit to other peer\n"); pth->timeout_task = GNUNET_SCHEDULER_NO_TASK; cp = pth->cp; GNUNET_CONTAINER_DLL_remove (cp->pth_head, cp->pth_tail, pth); if (GNUNET_YES == pth->is_query) GNUNET_assert (0 < cp->ppd.pending_queries--); else if (GNUNET_NO == pth->is_query) GNUNET_assert (0 < cp->ppd.pending_replies--); GNUNET_LOAD_update (cp->ppd.transmission_delay, UINT64_MAX); if (NULL != cp->cth) { GNUNET_CORE_notify_transmit_ready_cancel (cp->cth); cp->cth = NULL; } pth->gmc (pth->gmc_cls, 0, NULL); GNUNET_assert (0 == cp->cth_in_progress); GNUNET_free (pth); } /** * Transmit a message to the given peer as soon as possible. * If the peer disconnects before the transmission can happen, * the callback is invoked with a `NULL` @a buffer. * * @param cp target peer * @param is_query is this a query (#GNUNET_YES) or content (#GNUNET_NO) or neither (#GNUNET_SYSERR) * @param priority how important is this request? * @param timeout when does this request timeout (call gmc with error) * @param size number of bytes we would like to send to the peer * @param gmc function to call to get the message * @param gmc_cls closure for @a gmc * @return handle to cancel request */ struct GSF_PeerTransmitHandle * GSF_peer_transmit_ (struct GSF_ConnectedPeer *cp, int is_query, uint32_t priority, struct GNUNET_TIME_Relative timeout, size_t size, GSF_GetMessageCallback gmc, void *gmc_cls) { struct GSF_PeerTransmitHandle *pth; struct GSF_PeerTransmitHandle *pos; struct GSF_PeerTransmitHandle *prev; pth = GNUNET_new (struct GSF_PeerTransmitHandle); pth->transmission_request_start_time = GNUNET_TIME_absolute_get (); pth->timeout = GNUNET_TIME_relative_to_absolute (timeout); pth->gmc = gmc; pth->gmc_cls = gmc_cls; pth->size = size; pth->is_query = is_query; pth->priority = priority; pth->cp = cp; /* insertion sort (by priority, descending) */ prev = NULL; pos = cp->pth_head; while ((NULL != pos) && (pos->priority > priority)) { prev = pos; pos = pos->next; } GNUNET_CONTAINER_DLL_insert_after (cp->pth_head, cp->pth_tail, prev, pth); if (GNUNET_YES == is_query) cp->ppd.pending_queries++; else if (GNUNET_NO == is_query) cp->ppd.pending_replies++; pth->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &peer_transmit_timeout, pth); schedule_transmission (pth); return pth; } /** * Cancel an earlier request for transmission. * * @param pth request to cancel */ void GSF_peer_transmit_cancel_ (struct GSF_PeerTransmitHandle *pth) { struct GSF_ConnectedPeer *cp; if (GNUNET_SCHEDULER_NO_TASK != pth->timeout_task) { GNUNET_SCHEDULER_cancel (pth->timeout_task); pth->timeout_task = GNUNET_SCHEDULER_NO_TASK; } cp = pth->cp; GNUNET_CONTAINER_DLL_remove (cp->pth_head, cp->pth_tail, pth); if (GNUNET_YES == pth->is_query) GNUNET_assert (0 < cp->ppd.pending_queries--); else if (GNUNET_NO == pth->is_query) GNUNET_assert (0 < cp->ppd.pending_replies--); GNUNET_free (pth); } /** * Report on receiving a reply; update the performance record of the given peer. * * @param cp responding peer (will be updated) * @param request_time time at which the original query was transmitted * @param request_priority priority of the original request */ void GSF_peer_update_performance_ (struct GSF_ConnectedPeer *cp, struct GNUNET_TIME_Absolute request_time, uint32_t request_priority) { struct GNUNET_TIME_Relative delay; delay = GNUNET_TIME_absolute_get_duration (request_time); cp->ppd.avg_reply_delay.rel_value_us = (cp->ppd.avg_reply_delay.rel_value_us * (RUNAVG_DELAY_N - 1) + delay.rel_value_us) / RUNAVG_DELAY_N; cp->ppd.avg_priority = (cp->ppd.avg_priority * (RUNAVG_DELAY_N - 1) + request_priority) / RUNAVG_DELAY_N; } /** * Report on receiving a reply in response to an initiating client. * Remember that this peer is good for this client. * * @param cp responding peer (will be updated) * @param initiator_client local client on responsible for query */ void GSF_peer_update_responder_client_ (struct GSF_ConnectedPeer *cp, struct GSF_LocalClient *initiator_client) { cp->ppd.last_client_replies[cp->last_client_replies_woff++ % CS2P_SUCCESS_LIST_SIZE] = initiator_client; } /** * Report on receiving a reply in response to an initiating peer. * Remember that this peer is good for this initiating peer. * * @param cp responding peer (will be updated) * @param initiator_peer other peer responsible for query */ void GSF_peer_update_responder_peer_ (struct GSF_ConnectedPeer *cp, const struct GSF_ConnectedPeer *initiator_peer) { unsigned int woff; woff = cp->last_p2p_replies_woff % P2P_SUCCESS_LIST_SIZE; GNUNET_PEER_change_rc (cp->ppd.last_p2p_replies[woff], -1); cp->ppd.last_p2p_replies[woff] = initiator_peer->ppd.pid; GNUNET_PEER_change_rc (initiator_peer->ppd.pid, 1); cp->last_p2p_replies_woff = (woff + 1) % P2P_SUCCESS_LIST_SIZE; } /** * A peer disconnected from us. Tear down the connected peer * record. * * @param cls unused * @param peer identity of peer that connected */ void GSF_peer_disconnect_handler_ (void *cls, const struct GNUNET_PeerIdentity *peer) { struct GSF_ConnectedPeer *cp; struct GSF_PeerTransmitHandle *pth; struct GSF_DelayedHandle *dh; cp = GSF_peer_get_ (peer); if (NULL == cp) return; /* must have been disconnect from core with * 'peer' == my_id, ignore */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (cp_map, peer, cp)); GNUNET_STATISTICS_set (GSF_stats, gettext_noop ("# peers connected"), GNUNET_CONTAINER_multipeermap_size (cp_map), GNUNET_NO); if (NULL != cp->migration_pth) { GSF_peer_transmit_cancel_ (cp->migration_pth); cp->migration_pth = NULL; } if (NULL != cp->rc) { GNUNET_ATS_reserve_bandwidth_cancel (cp->rc); cp->rc = NULL; } if (GNUNET_SCHEDULER_NO_TASK != cp->rc_delay_task) { GNUNET_SCHEDULER_cancel (cp->rc_delay_task); cp->rc_delay_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_multihashmap_iterate (cp->request_map, &cancel_pending_request, cp); GNUNET_CONTAINER_multihashmap_destroy (cp->request_map); cp->request_map = NULL; GSF_plan_notify_peer_disconnect_ (cp); GNUNET_LOAD_value_free (cp->ppd.transmission_delay); GNUNET_PEER_decrement_rcs (cp->ppd.last_p2p_replies, P2P_SUCCESS_LIST_SIZE); memset (cp->ppd.last_p2p_replies, 0, sizeof (cp->ppd.last_p2p_replies)); GSF_push_stop_ (cp); if (NULL != cp->cth) { GNUNET_CORE_notify_transmit_ready_cancel (cp->cth); cp->cth = NULL; } GNUNET_assert (0 == cp->cth_in_progress); while (NULL != (pth = cp->pth_head)) { if (pth->timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (pth->timeout_task); pth->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_DLL_remove (cp->pth_head, cp->pth_tail, pth); pth->gmc (pth->gmc_cls, 0, NULL); GNUNET_free (pth); } while (NULL != (dh = cp->delayed_head)) { GNUNET_CONTAINER_DLL_remove (cp->delayed_head, cp->delayed_tail, dh); GNUNET_SCHEDULER_cancel (dh->delay_task); GNUNET_free (dh->pm); GNUNET_free (dh); } GNUNET_PEER_change_rc (cp->ppd.pid, -1); if (GNUNET_SCHEDULER_NO_TASK != cp->mig_revive_task) { GNUNET_SCHEDULER_cancel (cp->mig_revive_task); cp->mig_revive_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (cp); } /** * Closure for 'call_iterator'. */ struct IterationContext { /** * Function to call on each entry. */ GSF_ConnectedPeerIterator it; /** * Closure for 'it'. */ void *it_cls; }; /** * Function that calls the callback for each peer. * * @param cls the `struct IterationContext *` * @param key identity of the peer * @param value the `struct GSF_ConnectedPeer *` * @return #GNUNET_YES to continue iteration */ static int call_iterator (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct IterationContext *ic = cls; struct GSF_ConnectedPeer *cp = value; ic->it (ic->it_cls, (const struct GNUNET_PeerIdentity *) key, cp, &cp->ppd); return GNUNET_YES; } /** * Iterate over all connected peers. * * @param it function to call for each peer * @param it_cls closure for @a it */ void GSF_iterate_connected_peers_ (GSF_ConnectedPeerIterator it, void *it_cls) { struct IterationContext ic; ic.it = it; ic.it_cls = it_cls; GNUNET_CONTAINER_multipeermap_iterate (cp_map, &call_iterator, &ic); } /** * Obtain the identity of a connected peer. * * @param cp peer to get identity of * @param id identity to set (written to) */ void GSF_connected_peer_get_identity_ (const struct GSF_ConnectedPeer *cp, struct GNUNET_PeerIdentity *id) { GNUNET_assert (0 != cp->ppd.pid); GNUNET_PEER_resolve (cp->ppd.pid, id); } /** * Obtain the identity of a connected peer. * * @param cp peer to get identity of * @return reference to peer identity, valid until peer disconnects (!) */ const struct GNUNET_PeerIdentity * GSF_connected_peer_get_identity2_ (const struct GSF_ConnectedPeer *cp) { GNUNET_assert (0 != cp->ppd.pid); return GNUNET_PEER_resolve2 (cp->ppd.pid); } /** * Assemble a migration stop message for transmission. * * @param cls the 'struct GSF_ConnectedPeer' to use * @param size number of bytes we're allowed to write to buf * @param buf where to copy the message * @return number of bytes copied to buf */ static size_t create_migration_stop_message (void *cls, size_t size, void *buf) { struct GSF_ConnectedPeer *cp = cls; struct MigrationStopMessage msm; cp->migration_pth = NULL; if (NULL == buf) return 0; GNUNET_assert (size >= sizeof (struct MigrationStopMessage)); msm.header.size = htons (sizeof (struct MigrationStopMessage)); msm.header.type = htons (GNUNET_MESSAGE_TYPE_FS_MIGRATION_STOP); msm.reserved = htonl (0); msm.duration = GNUNET_TIME_relative_hton (GNUNET_TIME_absolute_get_remaining (cp->last_migration_block)); memcpy (buf, &msm, sizeof (struct MigrationStopMessage)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# migration stop messages sent"), 1, GNUNET_NO); return sizeof (struct MigrationStopMessage); } /** * Ask a peer to stop migrating data to us until the given point * in time. * * @param cp peer to ask * @param block_time until when to block */ void GSF_block_peer_migration_ (struct GSF_ConnectedPeer *cp, struct GNUNET_TIME_Absolute block_time) { if (cp->last_migration_block.abs_value_us > block_time.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Migration already blocked for another %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (cp->last_migration_block), GNUNET_YES)); return; /* already blocked */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking to stop migration for %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (block_time), GNUNET_YES)); cp->last_migration_block = block_time; if (NULL != cp->migration_pth) GSF_peer_transmit_cancel_ (cp->migration_pth); cp->migration_pth = GSF_peer_transmit_ (cp, GNUNET_SYSERR, UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct MigrationStopMessage), &create_migration_stop_message, cp); } /** * Write peer-respect information to a file - flush the buffer entry! * * @param cls unused * @param key peer identity * @param value the 'struct GSF_ConnectedPeer' to flush * @return GNUNET_OK to continue iteration */ static int flush_respect (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct GSF_ConnectedPeer *cp = value; char *fn; uint32_t respect; struct GNUNET_PeerIdentity pid; if (cp->ppd.respect == cp->disk_respect) return GNUNET_OK; /* unchanged */ GNUNET_assert (0 != cp->ppd.pid); GNUNET_PEER_resolve (cp->ppd.pid, &pid); fn = get_respect_filename (&pid); if (cp->ppd.respect == 0) { if ((0 != UNLINK (fn)) && (errno != ENOENT)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "unlink", fn); } else { respect = htonl (cp->ppd.respect); if (sizeof (uint32_t) == GNUNET_DISK_fn_write (fn, &respect, sizeof (uint32_t), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ)) cp->disk_respect = cp->ppd.respect; } GNUNET_free (fn); return GNUNET_OK; } /** * Notify core about a preference we have for the given peer * (to allocate more resources towards it). The change will * be communicated the next time we reserve bandwidth with * core (not instantly). * * @param cp peer to reserve bandwidth from * @param pref preference change */ void GSF_connected_peer_change_preference_ (struct GSF_ConnectedPeer *cp, uint64_t pref) { cp->inc_preference += pref; } /** * Call this method periodically to flush respect information to disk. * * @param cls closure, not used * @param tc task context, not used */ static void cron_flush_respect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL == cp_map) return; GNUNET_CONTAINER_multipeermap_iterate (cp_map, &flush_respect, NULL); if (NULL == tc) return; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_SCHEDULER_add_delayed_with_priority (RESPECT_FLUSH_FREQ, GNUNET_SCHEDULER_PRIORITY_HIGH, &cron_flush_respect, NULL); } /** * Initialize peer management subsystem. */ void GSF_connected_peer_init_ () { cp_map = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (GSF_cfg, "fs", "RESPECT", &respectDirectory)); GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_create (respectDirectory)); GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_HIGH, &cron_flush_respect, NULL); } /** * Iterator to free peer entries. * * @param cls closure, unused * @param key current key code * @param value value in the hash map (peer entry) * @return #GNUNET_YES (we should continue to iterate) */ static int clean_peer (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { GSF_peer_disconnect_handler_ (NULL, key); return GNUNET_YES; } /** * Shutdown peer management subsystem. */ void GSF_connected_peer_done_ () { cron_flush_respect (NULL, NULL); GNUNET_CONTAINER_multipeermap_iterate (cp_map, &clean_peer, NULL); GNUNET_CONTAINER_multipeermap_destroy (cp_map); cp_map = NULL; GNUNET_free (respectDirectory); respectDirectory = NULL; } /** * Iterator to remove references to LC entry. * * @param cls the 'struct GSF_LocalClient*' to look for * @param key current key code * @param value value in the hash map (peer entry) * @return #GNUNET_YES (we should continue to iterate) */ static int clean_local_client (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { const struct GSF_LocalClient *lc = cls; struct GSF_ConnectedPeer *cp = value; unsigned int i; for (i = 0; i < CS2P_SUCCESS_LIST_SIZE; i++) if (cp->ppd.last_client_replies[i] == lc) cp->ppd.last_client_replies[i] = NULL; return GNUNET_YES; } /** * Notification that a local client disconnected. Clean up all of our * references to the given handle. * * @param lc handle to the local client (henceforth invalid) */ void GSF_handle_local_client_disconnect_ (const struct GSF_LocalClient *lc) { if (NULL == cp_map) return; /* already cleaned up */ GNUNET_CONTAINER_multipeermap_iterate (cp_map, &clean_local_client, (void *) lc); } /* end of gnunet-service-fs_cp.c */ gnunet-0.10.1/src/fs/gnunet-daemon-fsprofiler.c0000644000175000017500000004403512226007054016273 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-daemon-fsprofiler.c * @brief daemon that publishes and downloads (random) files * @author Christian Grothoff * * TODO: * - how to signal driver that we're done? */ #include "platform.h" #include "gnunet_fs_service.h" #include "gnunet_statistics_service.h" /** * We use 'patterns' of the form (x,y,t) to specify desired download/publish * activities of a peer. They are stored in a DLL. */ struct Pattern { /** * Kept in a DLL. */ struct Pattern *next; /** * Kept in a DLL. */ struct Pattern *prev; /** * Execution context for the pattern (FS-handle to the operation). */ void *ctx; /** * Secondary execution context for the pattern (FS-handle to the operation). */ void *sctx; /** * When did the operation start? */ struct GNUNET_TIME_Absolute start_time; /** * With how much delay should this operation be started? */ struct GNUNET_TIME_Relative delay; /** * Task to run the operation. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Secondary task to run the operation. */ GNUNET_SCHEDULER_TaskIdentifier stask; /** * X-value. */ unsigned long long x; /** * Y-value. */ unsigned long long y; }; /** * Return value from 'main'. */ static int global_ret; /** * Configuration we use. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the statistics service. */ static struct GNUNET_STATISTICS_Handle *stats_handle; /** * Peer's FS handle. */ static struct GNUNET_FS_Handle *fs_handle; /** * Unique number for this peer in the testbed. */ static unsigned long long my_peerid; /** * Desired anonymity level. */ static unsigned long long anonymity_level; /** * Desired replication level. */ static unsigned long long replication_level; /** * String describing which publishing operations this peer should * perform. The format is "(SIZE,SEED,TIME)*", for example: * "(1,5,0)(7,3,13)" means to publish a file with 1 byte and * seed/keyword 5 immediately and another file with 7 bytes and * seed/keyword 3 after 13 ms. */ static char *publish_pattern; /** * Head of the DLL of publish patterns. */ static struct Pattern *publish_head; /** * Tail of the DLL of publish patterns. */ static struct Pattern *publish_tail; /** * String describing which download operations this peer should * perform. The format is "(KEYWORD,SIZE,DELAY)*"; for example, * "(1,7,3)(3,8,8)" means to download one file of 7 bytes under * keyword "1" starting the search after 3 ms; and another one of 8 * bytes under keyword '3' starting after 8 ms. The file size is * used to determine which search result(s) should be used or ignored. */ static char *download_pattern; /** * Head of the DLL of publish patterns. */ static struct Pattern *download_head; /** * Tail of the DLL of publish patterns. */ static struct Pattern *download_tail; /** * Parse a pattern string and store the corresponding * 'struct Pattern' in the given head/tail. * * @param head where to store the head * @param tail where to store the tail * @param pattern pattern to parse * @return GNUNET_OK on success */ static int parse_pattern (struct Pattern **head, struct Pattern **tail, const char *pattern) { struct Pattern *p; unsigned long long x; unsigned long long y; unsigned long long t; while (3 == sscanf (pattern, "(%llu,%llu,%llu)", &x, &y, &t)) { p = GNUNET_new (struct Pattern); p->x = x; p->y = y; p->delay.rel_value_us = (uint64_t) t; GNUNET_CONTAINER_DLL_insert (*head, *tail, p); pattern = strstr (pattern, ")"); GNUNET_assert (NULL != pattern); pattern++; } return (0 == strlen (pattern)) ? GNUNET_OK : GNUNET_SYSERR; } /** * Create a KSK URI from a number. * * @param kval the number * @return corresponding KSK URI */ static struct GNUNET_FS_Uri * make_keywords (uint64_t kval) { char kw[128]; GNUNET_snprintf (kw, sizeof (kw), "%llu", (unsigned long long) kval); return GNUNET_FS_uri_ksk_create (kw, NULL); } /** * Create a file of the given length with a deterministic amount * of data to be published under keyword 'kval'. * * @param length number of bytes in the file * @param kval keyword value and seed for the data of the file * @param ctx context to pass to 'fi' * @return file information handle for the file */ static struct GNUNET_FS_FileInformation * make_file (uint64_t length, uint64_t kval, void *ctx) { struct GNUNET_FS_FileInformation *fi; struct GNUNET_FS_BlockOptions bo; char *data; struct GNUNET_FS_Uri *keywords; unsigned long long i; uint64_t xor; data = NULL; /* to make compilers happy */ if ( (0 != length) && (NULL == (data = GNUNET_malloc_large ((size_t) length))) ) return NULL; /* initialize data with 'unique' data only depending on 'kval' and 'size', making sure that blocks do not repeat */ for (i=0;itask) GNUNET_SCHEDULER_cancel (p->task); if (NULL != p->ctx) GNUNET_FS_publish_stop (p->ctx); GNUNET_CONTAINER_DLL_remove (publish_head, publish_tail, p); GNUNET_free (p); } while (NULL != (p = download_head)) { if (GNUNET_SCHEDULER_NO_TASK != p->task) GNUNET_SCHEDULER_cancel (p->task); if (GNUNET_SCHEDULER_NO_TASK != p->stask) GNUNET_SCHEDULER_cancel (p->stask); if (NULL != p->ctx) GNUNET_FS_download_stop (p->ctx, GNUNET_YES); if (NULL != p->sctx) GNUNET_FS_search_stop (p->sctx); GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p); GNUNET_free (p); } if (NULL != fs_handle) { GNUNET_FS_stop (fs_handle); fs_handle = NULL; } if (NULL != stats_handle) { GNUNET_STATISTICS_destroy (stats_handle, GNUNET_YES); stats_handle = NULL; } } /** * Task run when a publish operation should be stopped. * * @param cls the 'struct Pattern' of the publish operation to stop * @param tc unused */ static void publish_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Pattern *p = cls; p->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_FS_publish_stop (p->ctx); } /** * Task run when a download operation should be stopped. * * @param cls the 'struct Pattern' of the download operation to stop * @param tc unused */ static void download_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Pattern *p = cls; p->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_FS_download_stop (p->ctx, GNUNET_YES); } /** * Task run when a download operation should be stopped. * * @param cls the 'struct Pattern' of the download operation to stop * @param tc unused */ static void search_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Pattern *p = cls; p->stask = GNUNET_SCHEDULER_NO_TASK; GNUNET_FS_search_stop (p->sctx); } /** * Notification of FS to a client about the progress of an * operation. Callbacks of this type will be used for uploads, * downloads and searches. Some of the arguments depend a bit * in their meaning on the context in which the callback is used. * * @param cls closure * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the GNUNET_FS_ProgressInfo struct. */ static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { struct Pattern *p; const struct GNUNET_FS_Uri *uri; switch (info->status) { case GNUNET_FS_STATUS_PUBLISH_START: case GNUNET_FS_STATUS_PUBLISH_PROGRESS: p = info->value.publish.cctx; return p; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: p = info->value.publish.cctx; return p; case GNUNET_FS_STATUS_PUBLISH_ERROR: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Publishing failed\n"); GNUNET_STATISTICS_update (stats_handle, "# failed publish operations", 1, GNUNET_NO); p = info->value.publish.cctx; p->task = GNUNET_SCHEDULER_add_now (&publish_stop_task, p); return p; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: p = info->value.publish.cctx; GNUNET_STATISTICS_update (stats_handle, "# publishing time (ms)", (long long) GNUNET_TIME_absolute_get_duration (p->start_time).rel_value_us / 1000LL, GNUNET_NO); p->task = GNUNET_SCHEDULER_add_now (&publish_stop_task, p); return p; case GNUNET_FS_STATUS_PUBLISH_STOPPED: p = info->value.publish.cctx; p->ctx = NULL; GNUNET_CONTAINER_DLL_remove (publish_head, publish_tail, p); GNUNET_free (p); return NULL; case GNUNET_FS_STATUS_DOWNLOAD_START: case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: p = info->value.download.cctx; return p; case GNUNET_FS_STATUS_DOWNLOAD_ERROR: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Download failed\n"); GNUNET_STATISTICS_update (stats_handle, "# failed downloads", 1, GNUNET_NO); p = info->value.download.cctx; p->task = GNUNET_SCHEDULER_add_now (&download_stop_task, p); return p; case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: p = info->value.download.cctx; GNUNET_STATISTICS_update (stats_handle, "# download time (ms)", (long long) GNUNET_TIME_absolute_get_duration (p->start_time).rel_value_us / 1000LL, GNUNET_NO); p->task = GNUNET_SCHEDULER_add_now (&download_stop_task, p); return p; case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: p = info->value.download.cctx; p->ctx = NULL; if (NULL == p->sctx) { GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p); GNUNET_free (p); } return NULL; case GNUNET_FS_STATUS_SEARCH_START: case GNUNET_FS_STATUS_SEARCH_RESULT_NAMESPACE: p = info->value.search.cctx; return p; case GNUNET_FS_STATUS_SEARCH_RESULT: p = info->value.search.cctx; uri = info->value.search.specifics.result.uri; if (GNUNET_YES != GNUNET_FS_uri_test_chk (uri)) return NULL; /* not what we want */ if (p->y != GNUNET_FS_uri_chk_get_file_size (uri)) return NULL; /* not what we want */ GNUNET_STATISTICS_update (stats_handle, "# search time (ms)", (long long) GNUNET_TIME_absolute_get_duration (p->start_time).rel_value_us / 1000LL, GNUNET_NO); p->start_time = GNUNET_TIME_absolute_get (); p->ctx = GNUNET_FS_download_start (fs_handle, uri, NULL, NULL, NULL, 0, GNUNET_FS_uri_chk_get_file_size (uri), anonymity_level, GNUNET_FS_DOWNLOAD_NO_TEMPORARIES, p, NULL); p->stask = GNUNET_SCHEDULER_add_now (&search_stop_task, p); return NULL; case GNUNET_FS_STATUS_SEARCH_UPDATE: case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: return NULL; /* don't care */ case GNUNET_FS_STATUS_SEARCH_ERROR: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Search failed\n"); GNUNET_STATISTICS_update (stats_handle, "# failed searches", 1, GNUNET_NO); p = info->value.search.cctx; p->stask = GNUNET_SCHEDULER_add_now (&search_stop_task, p); return p; case GNUNET_FS_STATUS_SEARCH_STOPPED: p = info->value.search.cctx; p->sctx = NULL; if (NULL == p->ctx) { GNUNET_CONTAINER_DLL_remove (download_head, download_tail, p); GNUNET_free (p); } return NULL; default: /* unexpected event during profiling */ GNUNET_break (0); return NULL; } } /** * Start publish operation. * * @param cls the 'struct Pattern' specifying the operation to perform * @param tc scheduler context */ static void start_publish (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Pattern *p = cls; struct GNUNET_FS_FileInformation *fi; p->task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; fi = make_file (p->x, p->y, p); p->start_time = GNUNET_TIME_absolute_get (); p->ctx = GNUNET_FS_publish_start (fs_handle, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); } /** * Start download operation. * * @param cls the 'struct Pattern' specifying the operation to perform * @param tc scheduler context */ static void start_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Pattern *p = cls; struct GNUNET_FS_Uri *keywords; p->task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; keywords = make_keywords (p->x); p->start_time = GNUNET_TIME_absolute_get (); p->sctx = GNUNET_FS_search_start (fs_handle, keywords, anonymity_level, GNUNET_FS_SEARCH_OPTION_NONE, p); } /** * @brief Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg_ configuration */ static void run (void *cls, char *const *args GNUNET_UNUSED, const char *cfgfile GNUNET_UNUSED, const struct GNUNET_CONFIGURATION_Handle *cfg_) { char myoptname[128]; struct Pattern *p; cfg = cfg_; /* Scheduled the task to clean up when shutdown is called */ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED", "PEERID", &my_peerid)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "TESTBED", "PEERID"); global_ret = GNUNET_SYSERR; GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "FSPROFILER", "ANONYMITY_LEVEL", &anonymity_level)) anonymity_level = 1; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "FSPROFILER", "REPLICATION_LEVEL", &replication_level)) replication_level = 1; GNUNET_snprintf (myoptname, sizeof (myoptname), "DOWNLOAD-PATTERN-%u", my_peerid); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "FSPROFILER", myoptname, &download_pattern)) download_pattern = GNUNET_strdup (""); GNUNET_snprintf (myoptname, sizeof (myoptname), "PUBLISH-PATTERN-%u", my_peerid); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "FSPROFILER", myoptname, &publish_pattern)) publish_pattern = GNUNET_strdup (""); if ( (GNUNET_OK != parse_pattern (&download_head, &download_tail, download_pattern)) || (GNUNET_OK != parse_pattern (&publish_head, &publish_tail, publish_pattern)) ) { GNUNET_SCHEDULER_shutdown (); return; } stats_handle = GNUNET_STATISTICS_create ("fsprofiler", cfg); fs_handle = GNUNET_FS_start (cfg, "fsprofiler", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_DOWNLOAD_PARALLELISM, 1, GNUNET_FS_OPTIONS_REQUEST_PARALLELISM, 1, GNUNET_FS_OPTIONS_END); if (NULL == fs_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not acquire FS handle. Exiting.\n"); global_ret = GNUNET_SYSERR; GNUNET_SCHEDULER_shutdown (); return; } for (p = publish_head; NULL != p; p = p->next) p->task = GNUNET_SCHEDULER_add_delayed (p->delay, &start_publish, p); for (p = download_head; NULL != p; p = p->next) p->task = GNUNET_SCHEDULER_add_delayed (p->delay, &start_download, p); } /** * Program that performs various "random" FS activities. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-fsprofiler", gettext_noop ("Daemon to use file-sharing to measure its performance."), options, &run, NULL)) ? global_ret : 1; } /* end of gnunet-daemon-fsprofiler.c */ gnunet-0.10.1/src/fs/gnunet-service-fs.h0000644000175000017500000001643712247442021014737 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs.h * @brief shared data structures of gnunet-service-fs.c * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_FS_H #define GNUNET_SERVICE_FS_H #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_core_service.h" #include "gnunet_block_lib.h" #include "gnunet_ats_service.h" #include "fs.h" /** * By which amount do we decrement the TTL for simple forwarding / * indirection of the query; in milli-seconds. Set somewhat in * accordance to your network latency (above the time it'll take you * to send a packet and get a reply). */ #define TTL_DECREMENT 5000 /** * At what frequency should our datastore load decrease * automatically (since if we don't use it, clearly the * load must be going down). */ #define DATASTORE_LOAD_AUTODECLINE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) /** * Only the (mandatory) query is included. */ #define GET_MESSAGE_BIT_QUERY_ONLY 0 /** * The peer identity of a peer waiting for the * reply is included (used if the response * should be transmitted to someone other than * the sender of the GET). */ #define GET_MESSAGE_BIT_RETURN_TO 1 /** * The peer identity of a peer that had claimed to have the content * previously is included (can be used if responder-anonymity is not * desired; note that the precursor presumably lacked a direct * connection to the specified peer; still, the receiver is in no way * required to limit forwarding only to the specified peer, it should * only prefer it somewhat if possible). */ #define GET_MESSAGE_BIT_TRANSMIT_TO 4 GNUNET_NETWORK_STRUCT_BEGIN /** * Message sent between peers asking for FS-content. */ struct GetMessage { /** * Message type will be #GNUNET_MESSAGE_TYPE_FS_GET. */ struct GNUNET_MessageHeader header; /** * Type of the query (block type). */ uint32_t type GNUNET_PACKED; /** * How important is this request (network byte order) */ uint32_t priority GNUNET_PACKED; /** * Relative time to live in MILLISECONDS (network byte order) */ int32_t ttl GNUNET_PACKED; /** * The content hash should be mutated using this value * before checking against the bloomfilter (used to * get many different filters for the same hash codes). * The number should be in big-endian format when used * for mingling. */ uint32_t filter_mutator GNUNET_PACKED; /** * Which of the optional hash codes are present at the end of the * message? See GET_MESSAGE_BIT_xx constants. For each bit that is * set, an additional `struct GNUNET_HashCode` with the respective content * (in order of the bits) will be appended to the end of the GET * message. */ uint32_t hash_bitmap GNUNET_PACKED; /** * Hashcodes of the file(s) we're looking for. * Details depend on the query type. */ struct GNUNET_HashCode query; /* this is followed by PeerIdentities as specified in the "hash_bitmap"; * after that, an optional bloomfilter (with bits set for replies * that should be suppressed) can be present */ }; /** * Message send by a peer that wants to be excluded * from migration for a while. */ struct MigrationStopMessage { /** * Message type will be * GNUNET_MESSAGE_TYPE_FS_MIGRATION_STOP. */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * How long should the block last? */ struct GNUNET_TIME_RelativeNBO duration; }; GNUNET_NETWORK_STRUCT_END /** * A connected peer. */ struct GSF_ConnectedPeer; /** * An active request. */ struct GSF_PendingRequest; /** * A local client. */ struct GSF_LocalClient; /** * Information kept per plan per request ('pe' module). */ struct GSF_RequestPlan; /** * Bijection between request plans and pending requests. */ struct GSF_PendingRequestPlanBijection; /** * Our connection to the datastore. */ extern struct GNUNET_DATASTORE_Handle *GSF_dsh; /** * Our configuration. */ extern const struct GNUNET_CONFIGURATION_Handle *GSF_cfg; /** * Handle for reporting statistics. */ extern struct GNUNET_STATISTICS_Handle *GSF_stats; /** * Pointer to handle to the core service (points to NULL until we've * connected to it). */ extern struct GNUNET_CORE_Handle *GSF_core; /** * Handle for DHT operations. */ extern struct GNUNET_DHT_Handle *GSF_dht; /** * How long do requests typically stay in the routing table? */ extern struct GNUNET_LOAD_Value *GSF_rt_entry_lifetime; /** * Running average of the observed latency to other peers (round trip). */ extern struct GNUNET_TIME_Relative GSF_avg_latency; /** * Handle to ATS service. */ extern struct GNUNET_ATS_PerformanceHandle *GSF_ats; /** * Typical priorities we're seeing from other peers right now. Since * most priorities will be zero, this value is the weighted average of * non-zero priorities seen "recently". In order to ensure that new * values do not dramatically change the ratio, values are first * "capped" to a reasonable range (+N of the current value) and then * averaged into the existing value by a ratio of 1:N. Hence * receiving the largest possible priority can still only raise our * "current_priorities" by at most 1. */ extern double GSF_current_priorities; /** * How many query messages have we received 'recently' that * have not yet been claimed as cover traffic? */ extern unsigned int GSF_cover_query_count; /** * How many content messages have we received 'recently' that * have not yet been claimed as cover traffic? */ extern unsigned int GSF_cover_content_count; /** * Our block context. */ extern struct GNUNET_BLOCK_Context *GSF_block_ctx; /** * Are we introducing randomized delays for better anonymity? */ extern int GSF_enable_randomized_delays; /** * Size of the datastore queue we assume for common requests. */ extern unsigned int GSF_datastore_queue_size; /** * Test if the DATABASE (GET) load on this peer is too high * to even consider processing the query at * all. * * @return GNUNET_YES if the load is too high to do anything (load high) * GNUNET_NO to process normally (load normal) * GNUNET_SYSERR to process for free (load low) */ int GSF_test_get_load_too_high_ (uint32_t priority); /** * We've just now completed a datastore request. Update our * datastore load calculations. * * @param start time when the datastore request was issued */ void GSF_update_datastore_delay_ (struct GNUNET_TIME_Absolute start); #endif /* end of gnunet-service-fs.h */ gnunet-0.10.1/src/fs/gnunet-service-fs_lc.h0000644000175000017500000000534112225777503015421 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_lc.h * @brief API to handle 'local clients' * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_FS_LC_H #define GNUNET_SERVICE_FS_LC_H #include "gnunet-service-fs.h" /** * Look up a local client record or create one if it * doesn't exist yet. * * @param client handle of the client * @return handle to local client entry */ struct GSF_LocalClient * GSF_local_client_lookup_ (struct GNUNET_SERVER_Client *client); /** * Handle START_SEARCH-message (search request from local client). * Only responsible for creating the request entry itself and setting * up reply callback and cancellation on client disconnect. Does NOT * execute the actual request strategy (planning). * * @param client identification of the client * @param message the actual message * @param prptr where to store the pending request handle for the request * @return GNUNET_YES to start local processing, * GNUNET_NO to not (yet) start local processing, * GNUNET_SYSERR on error */ int GSF_local_client_start_search_handler_ (struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message, struct GSF_PendingRequest **prptr); /** * Transmit a message to the given local client as soon as possible. * If the client disconnects before transmission, the message is * simply discarded. * * @param lc recipient * @param msg message to transmit to client */ void GSF_local_client_transmit_ (struct GSF_LocalClient *lc, const struct GNUNET_MessageHeader *msg); /** * A client disconnected from us. Tear down the local client record. * * @param cls unused * @param client handle of the client */ void GSF_client_disconnect_handler_ (void *cls, struct GNUNET_SERVER_Client *client); #endif /* end of gnunet-service-fs_lc.h */ gnunet-0.10.1/src/fs/fs_publish_ksk.c0000644000175000017500000001473612225777502014407 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_publish_ksk.c * @brief publish a URI under a keyword in GNUnet * @see https://gnunet.org/encoding and #2564 * @author Krista Bennett * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "fs_api.h" #include "fs_tree.h" #include "fs_publish_ublock.h" /** * Context for the KSK publication. */ struct GNUNET_FS_PublishKskContext { /** * Keywords to use. */ struct GNUNET_FS_Uri *ksk_uri; /** * URI to publish. */ struct GNUNET_FS_Uri *uri; /** * Metadata to use. */ struct GNUNET_CONTAINER_MetaData *meta; /** * Global FS context. */ struct GNUNET_FS_Handle *h; /** * UBlock publishing operation that is active. */ struct GNUNET_FS_PublishUblockContext *uc; /** * Handle to the datastore, NULL if we are just simulating. */ struct GNUNET_DATASTORE_Handle *dsh; /** * Current task. */ GNUNET_SCHEDULER_TaskIdentifier ksk_task; /** * Function to call once we're done. */ GNUNET_FS_PublishContinuation cont; /** * Closure for cont. */ void *cont_cls; /** * When should the KBlocks expire? */ struct GNUNET_FS_BlockOptions bo; /** * Options to use. */ enum GNUNET_FS_PublishOptions options; /** * Keyword that we are currently processing. */ unsigned int i; }; /** * Continuation of "GNUNET_FS_publish_ksk" that performs * the actual publishing operation (iterating over all * of the keywords). * * @param cls closure of type "struct PublishKskContext*" * @param tc unused */ static void publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Function called by the datastore API with * the result from the PUT request. * * @param cls closure of type "struct GNUNET_FS_PublishKskContext*" * @param msg error message (or NULL) */ static void kb_put_cont (void *cls, const char *msg) { struct GNUNET_FS_PublishKskContext *pkc = cls; pkc->uc = NULL; if (NULL != msg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KBlock PUT operation failed: %s\n", msg); pkc->cont (pkc->cont_cls, NULL, msg); GNUNET_FS_publish_ksk_cancel (pkc); return; } pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc); } /** * Continuation of "GNUNET_FS_publish_ksk" that performs the actual * publishing operation (iterating over all of the keywords). * * @param cls closure of type "struct GNUNET_FS_PublishKskContext*" * @param tc unused */ static void publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_PublishKskContext *pkc = cls; const char *keyword; pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK; if ( (pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || (NULL == pkc->dsh) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KSK PUT operation complete\n"); pkc->cont (pkc->cont_cls, pkc->ksk_uri, NULL); GNUNET_FS_publish_ksk_cancel (pkc); return; } keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++]; pkc->uc = GNUNET_FS_publish_ublock_ (pkc->h, pkc->dsh, keyword + 1 /* skip '+' */, NULL, GNUNET_CRYPTO_ecdsa_key_get_anonymous (), pkc->meta, pkc->uri, &pkc->bo, pkc->options, &kb_put_cont, pkc); } /** * Publish a CHK under various keywords on GNUnet. * * @param h handle to the file sharing subsystem * @param ksk_uri keywords to use * @param meta metadata to use * @param uri URI to refer to in the KBlock * @param bo per-block options * @param options publication options * @param cont continuation * @param cont_cls closure for cont * @return NULL on error ('cont' will still be called) */ struct GNUNET_FS_PublishKskContext * GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *ksk_uri, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_BlockOptions *bo, enum GNUNET_FS_PublishOptions options, GNUNET_FS_PublishContinuation cont, void *cont_cls) { struct GNUNET_FS_PublishKskContext *pkc; GNUNET_assert (NULL != uri); pkc = GNUNET_new (struct GNUNET_FS_PublishKskContext); pkc->h = h; pkc->bo = *bo; pkc->options = options; pkc->cont = cont; pkc->cont_cls = cont_cls; pkc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) { pkc->dsh = GNUNET_DATASTORE_connect (h->cfg); if (NULL == pkc->dsh) { cont (cont_cls, NULL, _("Could not connect to datastore.")); GNUNET_free (pkc); return NULL; } } pkc->uri = GNUNET_FS_uri_dup (uri); pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri); pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc); return pkc; } /** * Abort the KSK publishing operation. * * @param pkc context of the operation to abort. */ void GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc) { if (GNUNET_SCHEDULER_NO_TASK != pkc->ksk_task) { GNUNET_SCHEDULER_cancel (pkc->ksk_task); pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != pkc->uc) { GNUNET_FS_publish_ublock_cancel_ (pkc->uc); pkc->uc = NULL; } if (NULL != pkc->dsh) { GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); pkc->dsh = NULL; } GNUNET_CONTAINER_meta_data_destroy (pkc->meta); GNUNET_FS_uri_destroy (pkc->ksk_uri); GNUNET_FS_uri_destroy (pkc->uri); GNUNET_free (pkc); } /* end of fs_publish_ksk.c */ gnunet-0.10.1/src/fs/fs_test_lib_data.conf0000644000175000017500000000035412225230043015341 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-fs-test-lib/ [ats] WAN_QUOTA_IN = 3932160 WAN_QUOTA_OUT = 3932160 [datastore] QUOTA = 2 GB #PLUGIN = heap # #[fs] #DELAY = YES [testbed] OVERLAY_TOPOLOGY = CLIQUE gnunet-0.10.1/src/fs/test_fs_unindex_data.conf0000644000175000017500000000016012225230043016240 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-unindex/ [transport] PLUGINS = gnunet-0.10.1/src/fs/test_gnunet_service_fs_migration.c0000644000175000017500000001240512255010511020167 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_gnunet_service_fs_migration.c * @brief test content migration between two peers * @author Christian Grothoff */ #include "platform.h" #include "fs_test_lib.h" #include "gnunet_testbed_service.h" #define VERBOSE GNUNET_NO /** * File-size we use for testing. */ #define FILESIZE (2 * 32 * 1024) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long do we give the peers for content migration? */ #define MIGRATION_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90) #define SEED 42 static struct GNUNET_TESTBED_Peer *daemons[2]; static int ok; static struct GNUNET_TIME_Absolute start_time; static struct GNUNET_TESTBED_Operation *op; struct DownloadContext { char *fn; struct GNUNET_FS_Uri *uri; }; static void do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Relative del; char *fancy; GNUNET_SCHEDULER_shutdown (); if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { del = GNUNET_TIME_absolute_get_duration (start_time); if (del.rel_value_us == 0) del.rel_value_us = 1; fancy = GNUNET_STRINGS_byte_size_fancy (((unsigned long long) FILESIZE) * 1000000LL / del.rel_value_us); FPRINTF (stdout, "Download speed was %s/s\n", fancy); GNUNET_free (fancy); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished download, shutting down\n", (unsigned long long) FILESIZE); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout during download, shutting down with error\n"); ok = 1; } } static void do_download (void *cls, const char *emsg) { struct DownloadContext *dc = cls; struct GNUNET_FS_Uri *uri = dc->uri; GNUNET_TESTBED_operation_done (op); op = NULL; if (NULL != dc->fn) { GNUNET_DISK_directory_remove (dc->fn); GNUNET_free (dc->fn); } GNUNET_free (dc); if (NULL != emsg) { GNUNET_SCHEDULER_shutdown (); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to stop source daemon: %s\n", emsg); GNUNET_FS_uri_destroy (uri); ok = 1; return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Downloading %llu bytes\n", (unsigned long long) FILESIZE); start_time = GNUNET_TIME_absolute_get (); GNUNET_FS_TEST_download (daemons[0], TIMEOUT, 1, SEED, uri, VERBOSE, &do_stop, NULL); GNUNET_FS_uri_destroy (uri); } static void stop_source_peer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct DownloadContext *dc = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping source peer\n"); op = GNUNET_TESTBED_peer_stop (NULL, daemons[1], &do_download, dc); GNUNET_assert (NULL != op); } static void do_wait (void *cls, const struct GNUNET_FS_Uri *uri, const char *fn) { struct DownloadContext *dc; if (NULL == uri) { GNUNET_SCHEDULER_shutdown (); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout during upload attempt, shutting down with error\n"); ok = 1; return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting to allow content to migrate\n"); dc = GNUNET_new (struct DownloadContext); dc->uri = GNUNET_FS_uri_dup (uri); if (NULL != fn) dc->fn = GNUNET_strdup (fn); (void) GNUNET_SCHEDULER_add_delayed (MIGRATION_DELAY, &stop_source_peer, dc); } static void do_publish (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { unsigned int i; GNUNET_assert (2 == num_peers); for (i=0;istatus) { case GNUNET_FS_STATUS_PUBLISH_COMPLETED: consider_restart (event->status); ret = event->value.publish.cctx; printf ("Publish complete, %llu kbps.\n", (unsigned long long) (FILESIZE * 1000000LL / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us) / 1024)); if ( (NULL != event->value.publish.cctx) && (0 == strcmp ("publish-context-dir", event->value.publish.cctx)) ) GNUNET_SCHEDULER_add_now (&abort_publish_task, NULL); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: ret = event->value.publish.cctx; return ret; case GNUNET_FS_STATUS_PUBLISH_PROGRESS: consider_restart (event->status); ret = event->value.publish.cctx; GNUNET_assert (publish == event->value.publish.pc); #if VERBOSE printf ("Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); #endif break; case GNUNET_FS_STATUS_PUBLISH_SUSPEND: if (event->value.publish.pc == publish) publish = NULL; break; case GNUNET_FS_STATUS_PUBLISH_RESUME: if (NULL == publish) { GNUNET_assert (GNUNET_YES == GNUNET_FS_file_information_is_directory (event-> value.publish. fi)); publish = event->value.publish.pc; return "publish-context-dir"; } break; case GNUNET_FS_STATUS_PUBLISH_ERROR: ret = event->value.publish.cctx; FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); err = 1; GNUNET_SCHEDULER_add_now (&abort_publish_task, NULL); break; case GNUNET_FS_STATUS_PUBLISH_START: consider_restart (event->status); publish = event->value.publish.pc; ret = event->value.publish.cctx; if (0 == strcmp ("publish-context1", event->value.publish.cctx)) { GNUNET_assert (0 == strcmp ("publish-context-dir", event->value.publish.pctx)); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); } else if (0 == strcmp ("publish-context2", event->value.publish.cctx)) { GNUNET_assert (0 == strcmp ("publish-context-dir", event->value.publish.pctx)); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (2 == event->value.publish.anonymity); } else if (0 == strcmp ("publish-context-dir", event->value.publish.cctx)) { GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (3 == event->value.publish.anonymity); } else GNUNET_assert (0); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: consider_restart (event->status); if ( (NULL != event->value.publish.cctx) && (0 == strcmp ("publish-context-dir", event->value.publish.cctx)) ) GNUNET_assert (publish == event->value.publish.pc); break; default: printf ("Unexpected event: %d\n", event->status); break; } return ret; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar", }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi1; struct GNUNET_FS_FileInformation *fi2; struct GNUNET_FS_FileInformation *fidir; size_t i; struct GNUNET_FS_BlockOptions bo; cfg = c; fs = GNUNET_FS_start (cfg, "test-fs-publish-persistence", &progress_cb, NULL, GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); fn1 = GNUNET_DISK_mktemp ("gnunet-publish-test-dst"); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn1, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); fn2 = GNUNET_DISK_mktemp ("gnunet-publish-test-dst"); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn2, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi1 = GNUNET_FS_file_information_create_from_file (fs, "publish-context1", fn1, kuri, meta, GNUNET_YES, &bo); GNUNET_assert (NULL != fi1); bo.anonymity_level = 2; fi2 = GNUNET_FS_file_information_create_from_file (fs, "publish-context2", fn2, kuri, meta, GNUNET_YES, &bo); GNUNET_assert (NULL != fi2); bo.anonymity_level = 3; fidir = GNUNET_FS_file_information_create_empty_directory (fs, "publish-context-dir", kuri, meta, &bo, NULL); GNUNET_assert (GNUNET_OK == GNUNET_FS_file_information_add (fidir, fi1)); GNUNET_assert (GNUNET_OK == GNUNET_FS_file_information_add (fidir, fi2)); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fidir); start = GNUNET_TIME_absolute_get (); GNUNET_FS_publish_start (fs, fidir, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-publish-persistence", "test_fs_publish_data.conf", &run, NULL)) return 1; return err; } /* end of test_fs_publish_persistence.c */ gnunet-0.10.1/src/fs/test_fs_namespace_data.conf0000644000175000017500000000016212225230043016524 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-namespace/ [transport] PLUGINS = gnunet-0.10.1/src/fs/fs_download.c0000644000175000017500000023401012301361474013655 00000000000000/* This file is part of GNUnet. (C) 2001-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_download.c * @brief download methods * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_fs_service.h" #include "fs_api.h" #include "fs_tree.h" /** * Determine if the given download (options and meta data) should cause * use to try to do a recursive download. */ static int is_recursive_download (struct GNUNET_FS_DownloadContext *dc) { return (0 != (dc->options & GNUNET_FS_DOWNLOAD_OPTION_RECURSIVE)) && ((GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (dc->meta)) || ((NULL == dc->meta) && ((NULL == dc->filename) || ((strlen (dc->filename) >= strlen (GNUNET_FS_DIRECTORY_EXT)) && (NULL != strstr (dc->filename + strlen (dc->filename) - strlen (GNUNET_FS_DIRECTORY_EXT), GNUNET_FS_DIRECTORY_EXT)))))); } /** * We're storing the IBLOCKS after the DBLOCKS on disk (so that we * only have to truncate the file once we're done). * * Given the offset of a block (with respect to the DBLOCKS) and its * depth, return the offset where we would store this block in the * file. * * @param fsize overall file size * @param off offset of the block in the file * @param depth depth of the block in the tree, 0 for DBLOCK * @return off for DBLOCKS (depth == treedepth), * otherwise an offset past the end * of the file that does not overlap * with the range for any other block */ static uint64_t compute_disk_offset (uint64_t fsize, uint64_t off, unsigned int depth) { unsigned int i; uint64_t lsize; /* what is the size of all IBlocks for depth "i"? */ uint64_t loff; /* where do IBlocks for depth "i" start? */ unsigned int ioff; /* which IBlock corresponds to "off" at depth "i"? */ if (0 == depth) return off; /* first IBlocks start at the end of file, rounded up * to full DBLOCK_SIZE */ loff = ((fsize + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * DBLOCK_SIZE; lsize = ((fsize + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * sizeof (struct ContentHashKey); GNUNET_assert (0 == (off % DBLOCK_SIZE)); ioff = (off / DBLOCK_SIZE); for (i = 1; i < depth; i++) { loff += lsize; lsize = (lsize + CHK_PER_INODE - 1) / CHK_PER_INODE; GNUNET_assert (lsize > 0); GNUNET_assert (0 == (ioff % CHK_PER_INODE)); ioff /= CHK_PER_INODE; } return loff + ioff * sizeof (struct ContentHashKey); } /** * Fill in all of the generic fields for a download event and call the * callback. * * @param pi structure to fill in * @param dc overall download context */ void GNUNET_FS_download_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_DownloadContext *dc) { pi->value.download.dc = dc; pi->value.download.cctx = dc->client_info; pi->value.download.pctx = (NULL == dc->parent) ? NULL : dc->parent->client_info; pi->value.download.sctx = (NULL == dc->search) ? NULL : dc->search->client_info; pi->value.download.uri = dc->uri; pi->value.download.filename = dc->filename; pi->value.download.size = dc->length; /* FIXME: Fix duration calculation to account for pauses */ pi->value.download.duration = GNUNET_TIME_absolute_get_duration (dc->start_time); pi->value.download.completed = dc->completed; pi->value.download.anonymity = dc->anonymity; pi->value.download.eta = GNUNET_TIME_calculate_eta (dc->start_time, dc->completed, dc->length); pi->value.download.is_active = (NULL == dc->client) ? GNUNET_NO : GNUNET_YES; pi->fsh = dc->h; if (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) dc->client_info = dc->h->upcb (dc->h->upcb_cls, pi); else dc->client_info = GNUNET_FS_search_probe_progress_ (NULL, pi); } /** * We're ready to transmit a search request to the * file-sharing service. Do it. If there is * more than one request pending, try to send * multiple or request another transmission. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_download_request (void *cls, size_t size, void *buf); /** * Closure for iterator processing results. */ struct ProcessResultClosure { /** * Hash of data. */ struct GNUNET_HashCode query; /** * Data found in P2P network. */ const void *data; /** * Our download context. */ struct GNUNET_FS_DownloadContext *dc; /** * When did we last transmit the request? */ struct GNUNET_TIME_Absolute last_transmission; /** * Number of bytes in data. */ size_t size; /** * Type of data. */ enum GNUNET_BLOCK_Type type; /** * Flag to indicate if this block should be stored on disk. */ int do_store; /** * how much respect did we offer to get this reply? */ uint32_t respect_offered; /** * how often did we transmit the query? */ uint32_t num_transmissions; }; /** * Iterator over entries in the pending requests in the 'active' map for the * reply that we just got. * * @param cls closure (our 'struct ProcessResultClosure') * @param key query for the given value / request * @param value value in the hash map (a 'struct DownloadRequest') * @return GNUNET_YES (we should continue to iterate); unless serious error */ static int process_result_with_request (void *cls, const struct GNUNET_HashCode * key, void *value); /** * We've found a matching block without downloading it. * Encrypt it and pass it to our "receive" function as * if we had received it from the network. * * @param dc download in question * @param chk request this relates to * @param dr request details * @param block plaintext data matching request * @param len number of bytes in block * @param do_store should we still store the block on disk? * @return GNUNET_OK on success */ static int encrypt_existing_match (struct GNUNET_FS_DownloadContext *dc, const struct ContentHashKey *chk, struct DownloadRequest *dr, const char *block, size_t len, int do_store) { struct ProcessResultClosure prc; char enc[len]; struct GNUNET_CRYPTO_SymmetricSessionKey sk; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_HashCode query; GNUNET_CRYPTO_hash_to_aes_key (&chk->key, &sk, &iv); if (-1 == GNUNET_CRYPTO_symmetric_encrypt (block, len, &sk, &iv, enc)) { GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_CRYPTO_hash (enc, len, &query); if (0 != memcmp (&query, &chk->query, sizeof (struct GNUNET_HashCode))) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Matching %u byte block for `%s' at offset %llu already present, no need for download!\n", (unsigned int) len, dc->filename, (unsigned long long) dr->offset); /* already got it! */ prc.dc = dc; prc.data = enc; prc.size = len; prc.type = (0 == dr->depth) ? GNUNET_BLOCK_TYPE_FS_DBLOCK : GNUNET_BLOCK_TYPE_FS_IBLOCK; prc.query = chk->query; prc.do_store = do_store; prc.last_transmission = GNUNET_TIME_UNIT_FOREVER_ABS; process_result_with_request (&prc, &chk->key, dr); return GNUNET_OK; } /** * We've lost our connection with the FS service. * Re-establish it and re-transmit all of our * pending requests. * * @param dc download context that is having trouble */ static void try_reconnect (struct GNUNET_FS_DownloadContext *dc); /** * We found an entry in a directory. Check if the respective child * already exists and if not create the respective child download. * * @param cls the parent download * @param filename name of the file in the directory * @param uri URI of the file (CHK or LOC) * @param meta meta data of the file * @param length number of bytes in data * @param data contents of the file (or NULL if they were not inlined) */ static void trigger_recursive_download (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, size_t length, const void *data); /** * We're done downloading a directory. Open the file and * trigger all of the (remaining) child downloads. * * @param dc context of download that just completed */ static void full_recursive_download (struct GNUNET_FS_DownloadContext *dc) { size_t size; uint64_t size64; void *data; struct GNUNET_DISK_FileHandle *h; struct GNUNET_DISK_MapHandle *m; size64 = GNUNET_FS_uri_chk_get_file_size (dc->uri); size = (size_t) size64; if (size64 != (uint64_t) size) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Recursive downloads of directories larger than 4 GB are not supported on 32-bit systems\n")); return; } if (NULL != dc->filename) { h = GNUNET_DISK_file_open (dc->filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); } else { GNUNET_assert (NULL != dc->temp_filename); h = GNUNET_DISK_file_open (dc->temp_filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); } if (NULL == h) return; /* oops */ data = GNUNET_DISK_file_map (h, &m, GNUNET_DISK_MAP_TYPE_READ, size); if (NULL == data) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Directory too large for system address space\n")); } else { GNUNET_FS_directory_list_contents (size, data, 0, &trigger_recursive_download, dc); GNUNET_DISK_file_unmap (m); } GNUNET_DISK_file_close (h); if (NULL == dc->filename) { if (0 != UNLINK (dc->temp_filename)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", dc->temp_filename); GNUNET_free (dc->temp_filename); dc->temp_filename = NULL; } } /** * Check if all child-downloads have completed (or trigger them if * necessary) and once we're completely done, signal completion (and * possibly recurse to parent). This function MUST be called when the * download of a file itself is done or when the download of a file is * done and then later a direct child download has completed (and * hence this download may complete itself). * * @param dc download to check for completion of children */ static void check_completed (struct GNUNET_FS_DownloadContext *dc) { struct GNUNET_FS_ProgressInfo pi; struct GNUNET_FS_DownloadContext *pos; /* first, check if we need to download children */ if ((NULL == dc->child_head) && (is_recursive_download (dc))) full_recursive_download (dc); /* then, check if children are done already */ for (pos = dc->child_head; NULL != pos; pos = pos->next) { if ((pos->emsg == NULL) && (pos->completed < pos->length)) return; /* not done yet */ if ((pos->child_head != NULL) && (pos->has_finished != GNUNET_YES)) return; /* not transitively done yet */ } /* All of our children are done, so mark this download done */ dc->has_finished = GNUNET_YES; if (NULL != dc->job_queue) { GNUNET_FS_dequeue_ (dc->job_queue); dc->job_queue = NULL; } if (GNUNET_SCHEDULER_NO_TASK != dc->task) { GNUNET_SCHEDULER_cancel (dc->task); dc->task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != dc->rfh) { GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (dc->rfh)); dc->rfh = NULL; } GNUNET_FS_download_sync_ (dc); /* signal completion */ pi.status = GNUNET_FS_STATUS_DOWNLOAD_COMPLETED; GNUNET_FS_download_make_status_ (&pi, dc); /* let parent know */ if (NULL != dc->parent) check_completed (dc->parent); } /** * We got a block of plaintext data (from the meta data). * Try it for upward reconstruction of the data. On success, * the top-level block will move to state BRS_DOWNLOAD_UP. * * @param dc context for the download * @param dr download request to match against * @param data plaintext data, starting from the beginning of the file * @param data_len number of bytes in data */ static void try_match_block (struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr, const char *data, size_t data_len) { struct GNUNET_FS_ProgressInfo pi; unsigned int i; char enc[DBLOCK_SIZE]; struct ContentHashKey chks[CHK_PER_INODE]; struct ContentHashKey in_chk; struct GNUNET_CRYPTO_SymmetricSessionKey sk; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; size_t dlen; struct DownloadRequest *drc; struct GNUNET_DISK_FileHandle *fh; int complete; const char *fn; const char *odata; size_t odata_len; odata = data; odata_len = data_len; if (BRS_DOWNLOAD_UP == dr->state) return; if (dr->depth > 0) { if ( (dc->offset > 0) || (dc->length < GNUNET_ntohll (dc->uri->data.chk.file_length)) ) { /* NOTE: this test is not tight, but should suffice; the issue here is that 'dr->num_children' may inherently only specify a smaller range than what is in the original file; thus, reconstruction of (some) inner blocks will fail. FIXME: we might eventually want to write a tighter test to maximize the circumstances under which we do succeed with IBlock reconstruction. (need good tests though). */ return; } complete = GNUNET_YES; for (i = 0; i < dr->num_children; i++) { drc = dr->children[i]; try_match_block (dc, drc, data, data_len); if (drc->state != BRS_RECONSTRUCT_META_UP) complete = GNUNET_NO; else chks[i] = drc->chk; } if (GNUNET_YES != complete) return; data = (const char *) chks; dlen = dr->num_children * sizeof (struct ContentHashKey); } else { if (dr->offset > data_len) return; /* oops */ dlen = GNUNET_MIN (data_len - dr->offset, DBLOCK_SIZE); } GNUNET_CRYPTO_hash (&data[dr->offset], dlen, &in_chk.key); GNUNET_CRYPTO_hash_to_aes_key (&in_chk.key, &sk, &iv); if (-1 == GNUNET_CRYPTO_symmetric_encrypt (&data[dr->offset], dlen, &sk, &iv, enc)) { GNUNET_break (0); return; } GNUNET_CRYPTO_hash (enc, dlen, &in_chk.query); switch (dr->state) { case BRS_INIT: dr->chk = in_chk; dr->state = BRS_RECONSTRUCT_META_UP; break; case BRS_CHK_SET: if (0 != memcmp (&in_chk, &dr->chk, sizeof (struct ContentHashKey))) { /* other peer provided bogus meta data */ GNUNET_break_op (0); break; } /* write block to disk */ fn = (NULL != dc->filename) ? dc->filename : dc->temp_filename; if (NULL != fn) { fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_TRUNCATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ); if (NULL == fh) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); GNUNET_asprintf (&dc->emsg, _("Failed to open file `%s' for writing"), fn); GNUNET_DISK_file_close (fh); dr->state = BRS_ERROR; pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; pi.value.download.specifics.error.message = dc->emsg; GNUNET_FS_download_make_status_ (&pi, dc); return; } if (data_len != GNUNET_DISK_file_write (fh, odata, odata_len)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn); GNUNET_asprintf (&dc->emsg, _("Failed to open file `%s' for writing"), fn); GNUNET_DISK_file_close (fh); dr->state = BRS_ERROR; pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; pi.value.download.specifics.error.message = dc->emsg; GNUNET_FS_download_make_status_ (&pi, dc); return; } GNUNET_DISK_file_close (fh); } /* signal success */ dr->state = BRS_DOWNLOAD_UP; dc->completed = dc->length; GNUNET_FS_download_sync_ (dc); pi.status = GNUNET_FS_STATUS_DOWNLOAD_PROGRESS; pi.value.download.specifics.progress.data = data; pi.value.download.specifics.progress.offset = 0; pi.value.download.specifics.progress.data_len = dlen; pi.value.download.specifics.progress.depth = 0; pi.value.download.specifics.progress.respect_offered = 0; pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; GNUNET_FS_download_make_status_ (&pi, dc); if ((NULL != dc->filename) && (0 != TRUNCATE (dc->filename, GNUNET_ntohll (dc->uri->data.chk.file_length)))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "truncate", dc->filename); check_completed (dc); break; default: /* how did we get here? */ GNUNET_break (0); break; } } /** * Type of a function that libextractor calls for each * meta data item found. If we find full data meta data, * call 'try_match_block' on it. * * @param cls our 'struct GNUNET_FS_DownloadContext*' * @param plugin_name name of the plugin that produced this value; * special values can be used (i.e. '<zlib>' for zlib being * used in the main libextractor library and yielding * meta data). * @param type libextractor-type describing the meta data * @param format basic format information about data * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found * @param data_len number of bytes in data * @return 0 to continue extracting, 1 to abort */ static int match_full_data (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len) { struct GNUNET_FS_DownloadContext *dc = cls; if (EXTRACTOR_METATYPE_GNUNET_FULL_DATA != type) return 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u bytes of FD!\n", (unsigned int) data_len); if (GNUNET_FS_uri_chk_get_file_size (dc->uri) != data_len) { GNUNET_break_op (0); return 1; /* bogus meta data */ } try_match_block (dc, dc->top_request, data, data_len); return 1; } /** * Set the state of the given download request to * BRS_DOWNLOAD_UP and propagate it up the tree. * * @param dr download request that is done */ static void propagate_up (struct DownloadRequest *dr) { unsigned int i; do { dr->state = BRS_DOWNLOAD_UP; dr = dr->parent; if (NULL == dr) break; for (i = 0; i < dr->num_children; i++) if (dr->children[i]->state != BRS_DOWNLOAD_UP) break; } while (i == dr->num_children); } /** * Try top-down reconstruction. Before, the given request node * must have the state BRS_CHK_SET. Afterwards, more nodes may * have that state or advanced to BRS_DOWNLOAD_DOWN or even * BRS_DOWNLOAD_UP. It is also possible to get BRS_ERROR on the * top level. * * @param dc overall download this block belongs to * @param dr block to reconstruct */ static void try_top_down_reconstruction (struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr) { uint64_t off; char block[DBLOCK_SIZE]; struct GNUNET_HashCode key; uint64_t total; size_t len; unsigned int i; struct DownloadRequest *drc; uint64_t child_block_size; const struct ContentHashKey *chks; int up_done; GNUNET_assert (NULL != dc->rfh); GNUNET_assert (BRS_CHK_SET == dr->state); total = GNUNET_FS_uri_chk_get_file_size (dc->uri); GNUNET_assert (dr->depth < dc->treedepth); len = GNUNET_FS_tree_calculate_block_size (total, dr->offset, dr->depth); GNUNET_assert (len <= DBLOCK_SIZE); off = compute_disk_offset (total, dr->offset, dr->depth); if (dc->old_file_size < off + len) return; /* failure */ if (off != GNUNET_DISK_file_seek (dc->rfh, off, GNUNET_DISK_SEEK_SET)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "seek", dc->filename); return; /* failure */ } if (len != GNUNET_DISK_file_read (dc->rfh, block, len)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "read", dc->filename); return; /* failure */ } GNUNET_CRYPTO_hash (block, len, &key); if (0 != memcmp (&key, &dr->chk.key, sizeof (struct GNUNET_HashCode))) return; /* mismatch */ if (GNUNET_OK != encrypt_existing_match (dc, &dr->chk, dr, block, len, GNUNET_NO)) { /* hash matches but encrypted block does not, really bad */ dr->state = BRS_ERROR; /* propagate up */ while (NULL != dr->parent) { dr = dr->parent; dr->state = BRS_ERROR; } return; } /* block matches */ dr->state = BRS_DOWNLOAD_DOWN; /* set CHKs for children */ up_done = GNUNET_YES; chks = (const struct ContentHashKey *) block; for (i = 0; i < dr->num_children; i++) { drc = dr->children[i]; GNUNET_assert (drc->offset >= dr->offset); child_block_size = GNUNET_FS_tree_compute_tree_size (drc->depth); GNUNET_assert (0 == (drc->offset - dr->offset) % child_block_size); if (BRS_INIT == drc->state) { drc->state = BRS_CHK_SET; drc->chk = chks[drc->chk_idx]; try_top_down_reconstruction (dc, drc); } if (BRS_DOWNLOAD_UP != drc->state) up_done = GNUNET_NO; /* children not all done */ } if (GNUNET_YES == up_done) propagate_up (dr); /* children all done (or no children...) */ } /** * Schedule the download of the specified block in the tree. * * @param dc overall download this block belongs to * @param dr request to schedule */ static void schedule_block_download (struct GNUNET_FS_DownloadContext *dc, struct DownloadRequest *dr) { unsigned int i; switch (dr->state) { case BRS_INIT: GNUNET_assert (0); break; case BRS_RECONSTRUCT_DOWN: GNUNET_assert (0); break; case BRS_RECONSTRUCT_META_UP: GNUNET_assert (0); break; case BRS_RECONSTRUCT_UP: GNUNET_assert (0); break; case BRS_CHK_SET: /* normal case, start download */ break; case BRS_DOWNLOAD_DOWN: for (i = 0; i < dr->num_children; i++) schedule_block_download (dc, dr->children[i]); return; case BRS_DOWNLOAD_UP: /* We're done! */ return; case BRS_ERROR: GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scheduling download at offset %llu and depth %u for `%s'\n", (unsigned long long) dr->offset, dr->depth, GNUNET_h2s (&dr->chk.query)); if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains_value (dc->active, &dr->chk.query, dr)) return; /* already active */ GNUNET_CONTAINER_multihashmap_put (dc->active, &dr->chk.query, dr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); if (NULL == dc->client) return; /* download not active */ GNUNET_CONTAINER_DLL_insert (dc->pending_head, dc->pending_tail, dr); dr->is_pending = GNUNET_YES; if (NULL == dc->th) dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client, sizeof (struct SearchMessage), GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_download_request, dc); } #define GNUNET_FS_URI_CHK_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_CHK_INFIX /** * We found an entry in a directory. Check if the respective child * already exists and if not create the respective child download. * * @param cls the parent download * @param filename name of the file in the directory * @param uri URI of the file (CHK or LOC) * @param meta meta data of the file * @param length number of bytes in data * @param data contents of the file (or NULL if they were not inlined) */ static void trigger_recursive_download (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, size_t length, const void *data) { struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_FS_DownloadContext *cpos; char *temp_name; char *fn; char *us; char *ext; char *dn; char *pos; char *full_name; char *sfn; if (NULL == uri) return; /* entry for the directory itself */ cpos = dc->child_head; while (NULL != cpos) { if ((GNUNET_FS_uri_test_equal (uri, cpos->uri)) || ((NULL != filename) && (0 == strcmp (cpos->filename, filename)))) break; cpos = cpos->next; } if (NULL != cpos) return; /* already exists */ fn = NULL; if (NULL == filename) { fn = GNUNET_FS_meta_data_suggest_filename (meta); if (NULL == fn) { us = GNUNET_FS_uri_to_string (uri); fn = GNUNET_strdup (&us[strlen (GNUNET_FS_URI_CHK_PREFIX)]); GNUNET_free (us); } else if ('.' == fn[0]) { ext = fn; us = GNUNET_FS_uri_to_string (uri); GNUNET_asprintf (&fn, "%s%s", &us[strlen (GNUNET_FS_URI_CHK_PREFIX)], ext); GNUNET_free (ext); GNUNET_free (us); } /* change '\' to '/' (this should have happened * during insertion, but malicious peers may * not have done this) */ while (NULL != (pos = strstr (fn, "\\"))) *pos = '/'; /* remove '../' everywhere (again, well-behaved * peers don't do this, but don't trust that * we did not get something nasty) */ while (NULL != (pos = strstr (fn, "../"))) { pos[0] = '_'; pos[1] = '_'; pos[2] = '_'; } filename = fn; } if (NULL == dc->filename) { full_name = NULL; } else { dn = GNUNET_strdup (dc->filename); GNUNET_break ((strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) && (NULL != strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT), GNUNET_FS_DIRECTORY_EXT))); sfn = GNUNET_strdup (filename); while ((strlen (sfn) > 0) && ('/' == filename[strlen (sfn) - 1])) sfn[strlen (sfn) - 1] = '\0'; if ((strlen (dn) >= strlen (GNUNET_FS_DIRECTORY_EXT)) && (NULL != strstr (dn + strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT), GNUNET_FS_DIRECTORY_EXT))) dn[strlen (dn) - strlen (GNUNET_FS_DIRECTORY_EXT)] = '\0'; if ((GNUNET_YES == GNUNET_FS_meta_data_test_for_directory (meta)) && ((strlen (filename) < strlen (GNUNET_FS_DIRECTORY_EXT)) || (NULL == strstr (filename + strlen (filename) - strlen (GNUNET_FS_DIRECTORY_EXT), GNUNET_FS_DIRECTORY_EXT)))) { GNUNET_asprintf (&full_name, "%s%s%s%s", dn, DIR_SEPARATOR_STR, sfn, GNUNET_FS_DIRECTORY_EXT); } else { GNUNET_asprintf (&full_name, "%s%s%s", dn, DIR_SEPARATOR_STR, sfn); } GNUNET_free (sfn); GNUNET_free (dn); } if ((NULL != full_name) && (GNUNET_OK != GNUNET_DISK_directory_create_for_file (full_name))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to create directory for recursive download of `%s'\n"), full_name); GNUNET_free (full_name); GNUNET_free_non_null (fn); return; } temp_name = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering recursive download of size %llu with %u bytes MD\n", (unsigned long long) GNUNET_FS_uri_chk_get_file_size (uri), (unsigned int) GNUNET_CONTAINER_meta_data_get_serialized_size (meta)); GNUNET_FS_download_start (dc->h, uri, meta, full_name, temp_name, 0, GNUNET_FS_uri_chk_get_file_size (uri), dc->anonymity, dc->options, NULL, dc); GNUNET_free_non_null (full_name); GNUNET_free_non_null (temp_name); GNUNET_free_non_null (fn); } /** * (recursively) free download request structure * * @param dr request to free */ void GNUNET_FS_free_download_request_ (struct DownloadRequest *dr) { unsigned int i; if (NULL == dr) return; for (i = 0; i < dr->num_children; i++) GNUNET_FS_free_download_request_ (dr->children[i]); GNUNET_free_non_null (dr->children); GNUNET_free (dr); } /** * Iterator over entries in the pending requests in the 'active' map for the * reply that we just got. * * @param cls closure (our 'struct ProcessResultClosure') * @param key query for the given value / request * @param value value in the hash map (a 'struct DownloadRequest') * @return #GNUNET_YES (we should continue to iterate); unless serious error */ static int process_result_with_request (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ProcessResultClosure *prc = cls; struct DownloadRequest *dr = value; struct GNUNET_FS_DownloadContext *dc = prc->dc; struct DownloadRequest *drc; struct GNUNET_DISK_FileHandle *fh = NULL; struct GNUNET_CRYPTO_SymmetricSessionKey skey; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; char pt[prc->size]; struct GNUNET_FS_ProgressInfo pi; uint64_t off; size_t bs; size_t app; int i; struct ContentHashKey *chkarr; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %u byte block `%s' matching pending request at depth %u and offset %llu/%llu\n", (unsigned int) prc->size, GNUNET_h2s (key), dr->depth, (unsigned long long) dr->offset, (unsigned long long) GNUNET_ntohll (dc->uri->data. chk.file_length)); bs = GNUNET_FS_tree_calculate_block_size (GNUNET_ntohll (dc->uri->data.chk.file_length), dr->offset, dr->depth); if (prc->size != bs) { GNUNET_asprintf (&dc->emsg, _ ("Internal error or bogus download URI (expected %u bytes at depth %u and offset %llu/%llu, got %u bytes)"), bs, dr->depth, (unsigned long long) dr->offset, (unsigned long long) GNUNET_ntohll (dc->uri->data. chk.file_length), prc->size); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n", dc->emsg); while (NULL != dr->parent) { dr->state = BRS_ERROR; dr = dr->parent; } dr->state = BRS_ERROR; goto signal_error; } (void) GNUNET_CONTAINER_multihashmap_remove (dc->active, &prc->query, dr); if (GNUNET_YES == dr->is_pending) { GNUNET_CONTAINER_DLL_remove (dc->pending_head, dc->pending_tail, dr); dr->is_pending = GNUNET_NO; } GNUNET_CRYPTO_hash_to_aes_key (&dr->chk.key, &skey, &iv); if (-1 == GNUNET_CRYPTO_symmetric_decrypt (prc->data, prc->size, &skey, &iv, pt)) { GNUNET_break (0); dc->emsg = GNUNET_strdup (_("internal error decrypting content")); goto signal_error; } off = compute_disk_offset (GNUNET_ntohll (dc->uri->data.chk.file_length), dr->offset, dr->depth); /* save to disk */ if ((GNUNET_YES == prc->do_store) && ((NULL != dc->filename) || (is_recursive_download (dc))) && ((dr->depth == dc->treedepth) || (0 == (dc->options & GNUNET_FS_DOWNLOAD_NO_TEMPORARIES)))) { fh = GNUNET_DISK_file_open (NULL != dc->filename ? dc->filename : dc->temp_filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ); if (NULL == fh) { GNUNET_asprintf (&dc->emsg, _("Download failed: could not open file `%s': %s"), dc->filename, STRERROR (errno)); goto signal_error; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Saving decrypted block to disk at offset %llu\n", (unsigned long long) off); if ((off != GNUNET_DISK_file_seek (fh, off, GNUNET_DISK_SEEK_SET))) { GNUNET_asprintf (&dc->emsg, _("Failed to seek to offset %llu in file `%s': %s"), (unsigned long long) off, dc->filename, STRERROR (errno)); goto signal_error; } if (prc->size != GNUNET_DISK_file_write (fh, pt, prc->size)) { GNUNET_asprintf (&dc->emsg, _ ("Failed to write block of %u bytes at offset %llu in file `%s': %s"), (unsigned int) prc->size, (unsigned long long) off, dc->filename, STRERROR (errno)); goto signal_error; } GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fh)); fh = NULL; } if (0 == dr->depth) { /* DBLOCK, update progress and try recursion if applicable */ app = prc->size; if (dr->offset < dc->offset) { /* starting offset begins in the middle of pt, * do not count first bytes as progress */ GNUNET_assert (app > (dc->offset - dr->offset)); app -= (dc->offset - dr->offset); } if (dr->offset + prc->size > dc->offset + dc->length) { /* end of block is after relevant range, * do not count last bytes as progress */ GNUNET_assert (app > (dr->offset + prc->size) - (dc->offset + dc->length)); app -= (dr->offset + prc->size) - (dc->offset + dc->length); } dc->completed += app; /* do recursive download if option is set and either meta data * says it is a directory or if no meta data is given AND filename * ends in '.gnd' (top-level case) */ if (is_recursive_download (dc)) GNUNET_FS_directory_list_contents (prc->size, pt, off, &trigger_recursive_download, dc); } GNUNET_assert (dc->completed <= dc->length); dr->state = BRS_DOWNLOAD_DOWN; pi.status = GNUNET_FS_STATUS_DOWNLOAD_PROGRESS; pi.value.download.specifics.progress.data = pt; pi.value.download.specifics.progress.offset = dr->offset; pi.value.download.specifics.progress.data_len = prc->size; pi.value.download.specifics.progress.depth = dr->depth; pi.value.download.specifics.progress.respect_offered = prc->respect_offered; pi.value.download.specifics.progress.num_transmissions = prc->num_transmissions; if (prc->last_transmission.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_absolute_get_duration (prc->last_transmission); else pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; /* found locally */ GNUNET_FS_download_make_status_ (&pi, dc); if (0 == dr->depth) propagate_up (dr); if (dc->completed == dc->length) { /* download completed, signal */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download completed, truncating file to desired length %llu\n", (unsigned long long) GNUNET_ntohll (dc->uri->data. chk.file_length)); /* truncate file to size (since we store IBlocks at the end) */ if (NULL != dc->filename) { if (0 != TRUNCATE (dc->filename, GNUNET_ntohll (dc->uri->data.chk.file_length))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "truncate", dc->filename); } GNUNET_assert (0 == dr->depth); check_completed (dc); } if (0 == dr->depth) { /* bottom of the tree, no child downloads possible, just sync */ GNUNET_FS_download_sync_ (dc); return GNUNET_YES; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering downloads of children (this block was at depth %u and offset %llu)\n", dr->depth, (unsigned long long) dr->offset); GNUNET_assert (0 == (prc->size % sizeof (struct ContentHashKey))); chkarr = (struct ContentHashKey *) pt; for (i = dr->num_children - 1; i >= 0; i--) { drc = dr->children[i]; switch (drc->state) { case BRS_INIT: if ((drc->chk_idx + 1) * sizeof (struct ContentHashKey) > prc->size) { /* 'chkarr' does not have enough space for this chk_idx; internal error! */ GNUNET_break (0); GNUNET_assert (0); dc->emsg = GNUNET_strdup (_("internal error decoding tree")); goto signal_error; } drc->chk = chkarr[drc->chk_idx]; drc->state = BRS_CHK_SET; if (GNUNET_YES == dc->issue_requests) schedule_block_download (dc, drc); break; case BRS_RECONSTRUCT_DOWN: GNUNET_assert (0); break; case BRS_RECONSTRUCT_META_UP: GNUNET_assert (0); break; case BRS_RECONSTRUCT_UP: GNUNET_assert (0); break; case BRS_CHK_SET: GNUNET_assert (0); break; case BRS_DOWNLOAD_DOWN: GNUNET_assert (0); break; case BRS_DOWNLOAD_UP: GNUNET_assert (0); break; case BRS_ERROR: GNUNET_assert (0); break; default: GNUNET_assert (0); break; } } GNUNET_FS_download_sync_ (dc); return GNUNET_YES; signal_error: if (NULL != fh) GNUNET_DISK_file_close (fh); pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; pi.value.download.specifics.error.message = dc->emsg; GNUNET_FS_download_make_status_ (&pi, dc); /* abort all pending requests */ if (NULL != dc->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th); dc->th = NULL; } GNUNET_CLIENT_disconnect (dc->client); dc->in_receive = GNUNET_NO; dc->client = NULL; GNUNET_FS_free_download_request_ (dc->top_request); dc->top_request = NULL; GNUNET_CONTAINER_multihashmap_destroy (dc->active); dc->active = NULL; if (NULL != dc->job_queue) { GNUNET_FS_dequeue_ (dc->job_queue); dc->job_queue = NULL; } dc->pending_head = NULL; dc->pending_tail = NULL; GNUNET_FS_download_sync_ (dc); return GNUNET_NO; } /** * Process a download result. * * @param dc our download context * @param type type of the result * @param respect_offered how much respect did we offer to get this reply? * @param num_transmissions how often did we transmit the query? * @param last_transmission when was this block requested the last time? (FOREVER if unknown/not applicable) * @param data the (encrypted) response * @param size size of data */ static void process_result (struct GNUNET_FS_DownloadContext *dc, enum GNUNET_BLOCK_Type type, uint32_t respect_offered, uint32_t num_transmissions, struct GNUNET_TIME_Absolute last_transmission, const void *data, size_t size) { struct ProcessResultClosure prc; prc.dc = dc; prc.data = data; prc.last_transmission = last_transmission; prc.size = size; prc.type = type; prc.do_store = GNUNET_YES; prc.respect_offered = respect_offered; prc.num_transmissions = num_transmissions; GNUNET_CRYPTO_hash (data, size, &prc.query); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received result for query `%s' from `%s'-service\n", GNUNET_h2s (&prc.query), "FS"); GNUNET_CONTAINER_multihashmap_get_multiple (dc->active, &prc.query, &process_result_with_request, &prc); } /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void receive_results (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_FS_DownloadContext *dc = cls; const struct ClientPutMessage *cm; uint16_t msize; if ((NULL == msg) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_PUT) || (sizeof (struct ClientPutMessage) > ntohs (msg->size))) { GNUNET_break (NULL == msg); try_reconnect (dc); return; } msize = ntohs (msg->size); cm = (const struct ClientPutMessage *) msg; process_result (dc, ntohl (cm->type), ntohl (cm->respect_offered), ntohl (cm->num_transmissions), GNUNET_TIME_absolute_ntoh (cm->last_transmission), &cm[1], msize - sizeof (struct ClientPutMessage)); if (NULL == dc->client) return; /* fatal error */ /* continue receiving */ GNUNET_CLIENT_receive (dc->client, &receive_results, dc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * We're ready to transmit a search request to the * file-sharing service. Do it. If there is * more than one request pending, try to send * multiple or request another transmission. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_download_request (void *cls, size_t size, void *buf) { struct GNUNET_FS_DownloadContext *dc = cls; size_t msize; struct SearchMessage *sm; struct DownloadRequest *dr; dc->th = NULL; if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting download request failed, trying to reconnect\n"); try_reconnect (dc); return 0; } GNUNET_assert (size >= sizeof (struct SearchMessage)); msize = 0; sm = buf; while ((NULL != (dr = dc->pending_head)) && (size >= msize + sizeof (struct SearchMessage))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting download request for `%s' to `%s'-service\n", GNUNET_h2s (&dr->chk.query), "FS"); memset (sm, 0, sizeof (struct SearchMessage)); sm->header.size = htons (sizeof (struct SearchMessage)); sm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); if (0 != (dc->options & GNUNET_FS_DOWNLOAD_OPTION_LOOPBACK_ONLY)) sm->options = htonl (GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY); else sm->options = htonl (GNUNET_FS_SEARCH_OPTION_NONE); if (0 == dr->depth) sm->type = htonl (GNUNET_BLOCK_TYPE_FS_DBLOCK); else sm->type = htonl (GNUNET_BLOCK_TYPE_FS_IBLOCK); sm->anonymity_level = htonl (dc->anonymity); sm->target = dc->target; sm->query = dr->chk.query; GNUNET_CONTAINER_DLL_remove (dc->pending_head, dc->pending_tail, dr); dr->is_pending = GNUNET_NO; msize += sizeof (struct SearchMessage); sm++; } if (NULL != dc->pending_head) { dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client, sizeof (struct SearchMessage), GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_download_request, dc); GNUNET_assert (NULL != dc->th); } if (GNUNET_NO == dc->in_receive) { dc->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (dc->client, &receive_results, dc, GNUNET_TIME_UNIT_FOREVER_REL); } return msize; } /** * Reconnect to the FS service and transmit our queries NOW. * * @param cls our download context * @param tc unused */ static void do_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_CLIENT_Connection *client; dc->task = GNUNET_SCHEDULER_NO_TASK; client = GNUNET_CLIENT_connect ("fs", dc->h->cfg); if (NULL == client) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Connecting to `%s'-service failed, will try again.\n", "FS"); try_reconnect (dc); return; } dc->client = client; if (NULL != dc->pending_head) { dc->th = GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct SearchMessage), GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_download_request, dc); GNUNET_assert (NULL != dc->th); } } /** * Add entries to the pending list. * * @param cls our download context * @param key unused * @param entry entry of type "struct DownloadRequest" * @return GNUNET_OK */ static int retry_entry (void *cls, const struct GNUNET_HashCode * key, void *entry) { struct GNUNET_FS_DownloadContext *dc = cls; struct DownloadRequest *dr = entry; dr->next = NULL; dr->prev = NULL; GNUNET_CONTAINER_DLL_insert (dc->pending_head, dc->pending_tail, dr); dr->is_pending = GNUNET_YES; return GNUNET_OK; } /** * We've lost our connection with the FS service. * Re-establish it and re-transmit all of our * pending requests. * * @param dc download context that is having trouble */ static void try_reconnect (struct GNUNET_FS_DownloadContext *dc) { if (NULL != dc->client) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Moving all requests back to pending list\n"); if (NULL != dc->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th); dc->th = NULL; } /* full reset of the pending list */ dc->pending_head = NULL; dc->pending_tail = NULL; GNUNET_CONTAINER_multihashmap_iterate (dc->active, &retry_entry, dc); GNUNET_CLIENT_disconnect (dc->client); dc->in_receive = GNUNET_NO; dc->client = NULL; } if (0 == dc->reconnect_backoff.rel_value_us) dc->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS; else dc->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (dc->reconnect_backoff); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will try to reconnect in %s\n", GNUNET_STRINGS_relative_time_to_string (dc->reconnect_backoff, GNUNET_YES)); dc->task = GNUNET_SCHEDULER_add_delayed (dc->reconnect_backoff, &do_reconnect, dc); } /** * We're allowed to ask the FS service for our blocks. Start the download. * * @param cls the 'struct GNUNET_FS_DownloadContext' * @param client handle to use for communcation with FS (we must destroy it!) */ static void activate_fs_download (void *cls, struct GNUNET_CLIENT_Connection *client) { struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_FS_ProgressInfo pi; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download activated\n"); GNUNET_assert (NULL != client); GNUNET_assert (NULL == dc->client); GNUNET_assert (NULL == dc->th); GNUNET_assert (NULL != dc->active); dc->client = client; pi.status = GNUNET_FS_STATUS_DOWNLOAD_ACTIVE; GNUNET_FS_download_make_status_ (&pi, dc); dc->pending_head = NULL; dc->pending_tail = NULL; GNUNET_CONTAINER_multihashmap_iterate (dc->active, &retry_entry, dc); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking for transmission to FS service\n"); if (NULL != dc->pending_head) { dc->th = GNUNET_CLIENT_notify_transmit_ready (dc->client, sizeof (struct SearchMessage), GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_download_request, dc); GNUNET_assert (NULL != dc->th); } } /** * We must stop to ask the FS service for our blocks. Pause the download. * * @param cls the `struct GNUNET_FS_DownloadContext` */ static void deactivate_fs_download (void *cls) { struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_FS_ProgressInfo pi; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download deactivated\n"); if (NULL != dc->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (dc->th); dc->th = NULL; } if (NULL != dc->client) { GNUNET_CLIENT_disconnect (dc->client); dc->in_receive = GNUNET_NO; dc->client = NULL; } dc->pending_head = NULL; dc->pending_tail = NULL; pi.status = GNUNET_FS_STATUS_DOWNLOAD_INACTIVE; GNUNET_FS_download_make_status_ (&pi, dc); } /** * (recursively) Create a download request structure. * * @param parent parent of the current entry * @param chk_idx index of the chk for this block in the parent block * @param depth depth of the current entry, 0 are the DBLOCKs, * top level block is 'dc->treedepth - 1' * @param dr_offset offset in the original file this block maps to * (as in, offset of the first byte of the first DBLOCK * in the subtree rooted in the returned download request tree) * @param file_start_offset desired starting offset for the download * in the original file; requesting tree should not contain * DBLOCKs prior to the file_start_offset * @param desired_length desired number of bytes the user wanted to access * (from file_start_offset). Resulting tree should not contain * DBLOCKs after file_start_offset + file_length. * @return download request tree for the given range of DBLOCKs at * the specified depth */ static struct DownloadRequest * create_download_request (struct DownloadRequest *parent, unsigned int chk_idx, unsigned int depth, uint64_t dr_offset, uint64_t file_start_offset, uint64_t desired_length) { struct DownloadRequest *dr; unsigned int i; unsigned int head_skip; uint64_t child_block_size; dr = GNUNET_new (struct DownloadRequest); dr->parent = parent; dr->depth = depth; dr->offset = dr_offset; dr->chk_idx = chk_idx; if (0 == depth) return dr; child_block_size = GNUNET_FS_tree_compute_tree_size (depth - 1); /* calculate how many blocks at this level are not interesting * from the start (rounded down), either because of the requested * file offset or because this IBlock is further along */ if (dr_offset < file_start_offset) { head_skip = (file_start_offset - dr_offset) / child_block_size; } else { head_skip = 0; } /* calculate index of last block at this level that is interesting (rounded up) */ dr->num_children = (file_start_offset + desired_length - dr_offset) / child_block_size; if (dr->num_children * child_block_size < file_start_offset + desired_length - dr_offset) dr->num_children++; /* round up */ GNUNET_assert (dr->num_children > head_skip); dr->num_children -= head_skip; if (dr->num_children > CHK_PER_INODE) dr->num_children = CHK_PER_INODE; /* cap at max */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Block at offset %llu and depth %u has %u children\n", (unsigned long long) dr_offset, depth, dr->num_children); /* now we can get the total number of *interesting* children for this block */ /* why else would we have gotten here to begin with? (that'd be a bad logic error) */ GNUNET_assert (dr->num_children > 0); dr->children = GNUNET_malloc (dr->num_children * sizeof (struct DownloadRequest *)); for (i = 0; i < dr->num_children; i++) { dr->children[i] = create_download_request (dr, i + head_skip, depth - 1, dr_offset + (i + head_skip) * child_block_size, file_start_offset, desired_length); } return dr; } /** * Continuation after a possible attempt to reconstruct * the current IBlock from the existing file. * * @param cls the 'struct ReconstructContext' * @param tc scheduler context */ static void reconstruct_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_DownloadContext *dc = cls; /* clean up state from tree encoder */ if (dc->task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (dc->task); dc->task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != dc->rfh) { GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (dc->rfh)); dc->rfh = NULL; } /* start "normal" download */ dc->issue_requests = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting normal download\n"); schedule_block_download (dc, dc->top_request); } /** * Task requesting the next block from the tree encoder. * * @param cls the 'struct GNUJNET_FS_DownloadContext' we're processing * @param tc task context */ static void get_next_block (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_DownloadContext *dc = cls; dc->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_FS_tree_encoder_next (dc->te); } /** * Function called asking for the current (encoded) * block to be processed. After processing the * client should either call "GNUNET_FS_tree_encode_next" * or (on error) "GNUNET_FS_tree_encode_finish". * * This function checks if the content on disk matches * the expected content based on the URI. * * @param cls closure * @param chk content hash key for the block * @param offset offset of the block * @param depth depth of the block, 0 for DBLOCK * @param type type of the block (IBLOCK or DBLOCK) * @param block the (encrypted) block * @param block_size size of block (in bytes) */ static void reconstruct_cb (void *cls, const struct ContentHashKey *chk, uint64_t offset, unsigned int depth, enum GNUNET_BLOCK_Type type, const void *block, uint16_t block_size) { struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_FS_ProgressInfo pi; struct DownloadRequest *dr; uint64_t blen; unsigned int chld; /* find corresponding request entry */ dr = dc->top_request; while (dr->depth > depth) { GNUNET_assert (dr->num_children > 0); blen = GNUNET_FS_tree_compute_tree_size (dr->depth - 1); chld = (offset - dr->offset) / blen; if (chld < dr->children[0]->chk_idx) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Block %u < %u irrelevant for our range\n", chld, dr->children[0]->chk_idx); dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); return; /* irrelevant block */ } if (chld > dr->children[dr->num_children-1]->chk_idx) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Block %u > %u irrelevant for our range\n", chld, dr->children[dr->num_children-1]->chk_idx); dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); return; /* irrelevant block */ } dr = dr->children[chld - dr->children[0]->chk_idx]; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Matched TE block with request at offset %llu and depth %u in state %d\n", (unsigned long long) dr->offset, dr->depth, dr->state); /* FIXME: this code needs more testing and might need to handle more states... */ switch (dr->state) { case BRS_INIT: break; case BRS_RECONSTRUCT_DOWN: break; case BRS_RECONSTRUCT_META_UP: break; case BRS_RECONSTRUCT_UP: break; case BRS_CHK_SET: if (0 == memcmp (chk, &dr->chk, sizeof (struct ContentHashKey))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconstruction succeeded, can use block at offset %llu, depth %u\n", (unsigned long long) offset, depth); /* block matches, hence tree below matches; * this request is done! */ dr->state = BRS_DOWNLOAD_UP; (void) GNUNET_CONTAINER_multihashmap_remove (dc->active, &dr->chk.query, dr); if (GNUNET_YES == dr->is_pending) { GNUNET_break (0); /* how did we get here? */ GNUNET_CONTAINER_DLL_remove (dc->pending_head, dc->pending_tail, dr); dr->is_pending = GNUNET_NO; } /* calculate how many bytes of payload this block * corresponds to */ blen = GNUNET_FS_tree_compute_tree_size (dr->depth); /* how many of those bytes are in the requested range? */ blen = GNUNET_MIN (blen, dc->length + dc->offset - dr->offset); /* signal progress */ dc->completed += blen; pi.status = GNUNET_FS_STATUS_DOWNLOAD_PROGRESS; pi.value.download.specifics.progress.data = NULL; pi.value.download.specifics.progress.offset = offset; pi.value.download.specifics.progress.data_len = 0; pi.value.download.specifics.progress.depth = 0; pi.value.download.specifics.progress.respect_offered = 0; pi.value.download.specifics.progress.block_download_duration = GNUNET_TIME_UNIT_ZERO; GNUNET_FS_download_make_status_ (&pi, dc); /* FIXME: duplicated code from 'process_result_with_request - refactor */ if (dc->completed == dc->length) { /* download completed, signal */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download completed, truncating file to desired length %llu\n", (unsigned long long) GNUNET_ntohll (dc->uri->data. chk.file_length)); /* truncate file to size (since we store IBlocks at the end) */ if (NULL != dc->filename) { if (0 != TRUNCATE (dc->filename, GNUNET_ntohll (dc->uri->data.chk.file_length))) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "truncate", dc->filename); } } } else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconstruction failed, need to download block at offset %llu, depth %u\n", (unsigned long long) offset, depth); break; case BRS_DOWNLOAD_DOWN: break; case BRS_DOWNLOAD_UP: break; case BRS_ERROR: break; default: GNUNET_assert (0); break; } dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); if ((dr == dc->top_request) && (dr->state == BRS_DOWNLOAD_UP)) check_completed (dc); } /** * Function called by the tree encoder to obtain a block of plaintext * data (for the lowest level of the tree). * * @param cls our 'struct ReconstructContext' * @param offset identifies which block to get * @param max (maximum) number of bytes to get; returning * fewer will also cause errors * @param buf where to copy the plaintext buffer * @param emsg location to store an error message (on error) * @return number of bytes copied to buf, 0 on error */ static size_t fh_reader (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) { struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_DISK_FileHandle *fh = dc->rfh; ssize_t ret; if (NULL != emsg) *emsg = NULL; if (offset != GNUNET_DISK_file_seek (fh, offset, GNUNET_DISK_SEEK_SET)) { if (NULL != emsg) *emsg = GNUNET_strdup (strerror (errno)); return 0; } ret = GNUNET_DISK_file_read (fh, buf, max); if (ret < 0) { if (NULL != emsg) *emsg = GNUNET_strdup (strerror (errno)); return 0; } return ret; } /** * Task that creates the initial (top-level) download * request for the file. * * @param cls the 'struct GNUNET_FS_DownloadContext' * @param tc scheduler context */ void GNUNET_FS_download_start_task_ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_FS_ProgressInfo pi; struct GNUNET_DISK_FileHandle *fh; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start task running...\n"); dc->task = GNUNET_SCHEDULER_NO_TASK; if (0 == dc->length) { /* no bytes required! */ if (NULL != dc->filename) { fh = GNUNET_DISK_file_open (dc->filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE | ((0 == GNUNET_FS_uri_chk_get_file_size (dc->uri)) ? GNUNET_DISK_OPEN_TRUNCATE : 0), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ); GNUNET_DISK_file_close (fh); } GNUNET_FS_download_sync_ (dc); pi.status = GNUNET_FS_STATUS_DOWNLOAD_START; pi.value.download.specifics.start.meta = dc->meta; GNUNET_FS_download_make_status_ (&pi, dc); check_completed (dc); return; } if (NULL != dc->emsg) return; if (NULL == dc->top_request) { dc->top_request = create_download_request (NULL, 0, dc->treedepth - 1, 0, dc->offset, dc->length); dc->top_request->state = BRS_CHK_SET; dc->top_request->chk = (dc->uri->type == GNUNET_FS_URI_CHK) ? dc->uri->data.chk.chk : dc->uri->data.loc.fi.chk; /* signal start */ GNUNET_FS_download_sync_ (dc); if (NULL != dc->search) GNUNET_FS_search_result_sync_ (dc->search); pi.status = GNUNET_FS_STATUS_DOWNLOAD_START; pi.value.download.specifics.start.meta = dc->meta; GNUNET_FS_download_make_status_ (&pi, dc); } GNUNET_FS_download_start_downloading_ (dc); /* attempt reconstruction from disk */ if (GNUNET_YES == GNUNET_DISK_file_test (dc->filename)) dc->rfh = GNUNET_DISK_file_open (dc->filename, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE); if (dc->top_request->state == BRS_CHK_SET) { if (NULL != dc->rfh) { /* first, try top-down */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying top-down reconstruction for `%s'\n", dc->filename); try_top_down_reconstruction (dc, dc->top_request); switch (dc->top_request->state) { case BRS_CHK_SET: break; /* normal */ case BRS_DOWNLOAD_DOWN: break; /* normal, some blocks already down */ case BRS_DOWNLOAD_UP: /* already done entirely, party! */ if (NULL != dc->rfh) { /* avoid hanging on to file handle longer than * necessary */ GNUNET_DISK_file_close (dc->rfh); dc->rfh = NULL; } return; case BRS_ERROR: GNUNET_asprintf (&dc->emsg, _("Invalid URI")); GNUNET_FS_download_sync_ (dc); pi.status = GNUNET_FS_STATUS_DOWNLOAD_ERROR; pi.value.download.specifics.error.message = dc->emsg; GNUNET_FS_download_make_status_ (&pi, dc); return; default: GNUNET_assert (0); break; } } } /* attempt reconstruction from meta data */ if ((GNUNET_FS_uri_chk_get_file_size (dc->uri) <= MAX_INLINE_SIZE) && (NULL != dc->meta)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to find embedded meta data for download of size %llu with %u bytes MD\n", (unsigned long long) GNUNET_FS_uri_chk_get_file_size (dc->uri), (unsigned int) GNUNET_CONTAINER_meta_data_get_serialized_size (dc->meta)); GNUNET_CONTAINER_meta_data_iterate (dc->meta, &match_full_data, dc); if (BRS_DOWNLOAD_UP == dc->top_request->state) { if (NULL != dc->rfh) { /* avoid hanging on to file handle longer than * necessary */ GNUNET_DISK_file_close (dc->rfh); dc->rfh = NULL; } return; /* finished, status update was already done for us */ } } if (NULL != dc->rfh) { /* finally, actually run bottom-up */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying bottom-up reconstruction of file `%s'\n", dc->filename); dc->te = GNUNET_FS_tree_encoder_create (dc->h, GNUNET_FS_uri_chk_get_file_size (dc->uri), dc, &fh_reader, &reconstruct_cb, NULL, &reconstruct_cont); dc->task = GNUNET_SCHEDULER_add_now (&get_next_block, dc); } else { /* simple, top-level download */ dc->issue_requests = GNUNET_YES; schedule_block_download (dc, dc->top_request); } if (BRS_DOWNLOAD_UP == dc->top_request->state) check_completed (dc); } /** * Create SUSPEND event for the given download operation * and then clean up our state (without stop signal). * * @param cls the 'struct GNUNET_FS_DownloadContext' to signal for */ void GNUNET_FS_download_signal_suspend_ (void *cls) { struct GNUNET_FS_DownloadContext *dc = cls; struct GNUNET_FS_ProgressInfo pi; if (NULL != dc->top) GNUNET_FS_end_top (dc->h, dc->top); while (NULL != dc->child_head) GNUNET_FS_download_signal_suspend_ (dc->child_head); if (NULL != dc->search) { dc->search->download = NULL; dc->search = NULL; } if (NULL != dc->job_queue) { GNUNET_FS_dequeue_ (dc->job_queue); dc->job_queue = NULL; } if (NULL != dc->parent) GNUNET_CONTAINER_DLL_remove (dc->parent->child_head, dc->parent->child_tail, dc); if (GNUNET_SCHEDULER_NO_TASK != dc->task) { GNUNET_SCHEDULER_cancel (dc->task); dc->task = GNUNET_SCHEDULER_NO_TASK; } pi.status = GNUNET_FS_STATUS_DOWNLOAD_SUSPEND; GNUNET_FS_download_make_status_ (&pi, dc); if (NULL != dc->te) { GNUNET_FS_tree_encoder_finish (dc->te, NULL); dc->te = NULL; } if (NULL != dc->rfh) { GNUNET_DISK_file_close (dc->rfh); dc->rfh = NULL; } GNUNET_FS_free_download_request_ (dc->top_request); if (NULL != dc->active) { GNUNET_CONTAINER_multihashmap_destroy (dc->active); dc->active = NULL; } GNUNET_free_non_null (dc->filename); GNUNET_CONTAINER_meta_data_destroy (dc->meta); GNUNET_FS_uri_destroy (dc->uri); GNUNET_free_non_null (dc->temp_filename); GNUNET_free_non_null (dc->serialization); GNUNET_assert (NULL == dc->job_queue); GNUNET_free (dc); } /** * Helper function to setup the download context. * * @param h handle to the file sharing subsystem * @param uri the URI of the file (determines what to download); CHK or LOC URI * @param meta known metadata for the file (can be NULL) * @param filename where to store the file, maybe NULL (then no file is * created on disk and data must be grabbed from the callbacks) * @param tempname where to store temporary file data, not used if filename is non-NULL; * can be NULL (in which case we will pick a name if needed); the temporary file * may already exist, in which case we will try to use the data that is there and * if it is not what is desired, will overwrite it * @param offset at what offset should we start the download (typically 0) * @param length how many bytes should be downloaded starting at offset * @param anonymity anonymity level to use for the download * @param options various options * @param cctx initial value for the client context for this download * @return context that can be used to control this download */ struct GNUNET_FS_DownloadContext * create_download_context (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx) { struct GNUNET_FS_DownloadContext *dc; GNUNET_assert (GNUNET_FS_uri_test_chk (uri) || GNUNET_FS_uri_test_loc (uri)); if ((offset + length < offset) || (offset + length > GNUNET_FS_uri_chk_get_file_size (uri))) { GNUNET_break (0); return NULL; } dc = GNUNET_new (struct GNUNET_FS_DownloadContext); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting download %p, %u bytes at offset %llu\n", dc, (unsigned long long) length, (unsigned long long) offset); dc->h = h; dc->uri = GNUNET_FS_uri_dup (uri); dc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); dc->client_info = cctx; dc->start_time = GNUNET_TIME_absolute_get (); if (NULL != filename) { dc->filename = GNUNET_strdup (filename); if (GNUNET_YES == GNUNET_DISK_file_test (filename)) GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (filename, &dc->old_file_size, GNUNET_YES, GNUNET_YES)); } if (GNUNET_FS_uri_test_loc (dc->uri)) GNUNET_assert (GNUNET_OK == GNUNET_FS_uri_loc_get_peer_identity (dc->uri, &dc->target)); dc->offset = offset; dc->length = length; dc->anonymity = anonymity; dc->options = options; dc->active = GNUNET_CONTAINER_multihashmap_create (1 + 2 * (length / DBLOCK_SIZE), GNUNET_NO); dc->treedepth = GNUNET_FS_compute_depth (GNUNET_FS_uri_chk_get_file_size (dc->uri)); if ((NULL == filename) && (is_recursive_download (dc))) { if (NULL != tempname) dc->temp_filename = GNUNET_strdup (tempname); else dc->temp_filename = GNUNET_DISK_mktemp ("gnunet-directory-download-tmp"); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting download `%s' of %llu bytes with tree depth %u\n", filename, (unsigned long long) length, dc->treedepth); dc->task = GNUNET_SCHEDULER_add_now (&GNUNET_FS_download_start_task_, dc); return dc; } /** * Download parts of a file. Note that this will store * the blocks at the respective offset in the given file. Also, the * download is still using the blocking of the underlying FS * encoding. As a result, the download may *write* outside of the * given boundaries (if offset and length do not match the 32k FS * block boundaries).

* * This function should be used to focus a download towards a * particular portion of the file (optimization), not to strictly * limit the download to exactly those bytes. * * @param h handle to the file sharing subsystem * @param uri the URI of the file (determines what to download); CHK or LOC URI * @param meta known metadata for the file (can be NULL) * @param filename where to store the file, maybe NULL (then no file is * created on disk and data must be grabbed from the callbacks) * @param tempname where to store temporary file data, not used if filename is non-NULL; * can be NULL (in which case we will pick a name if needed); the temporary file * may already exist, in which case we will try to use the data that is there and * if it is not what is desired, will overwrite it * @param offset at what offset should we start the download (typically 0) * @param length how many bytes should be downloaded starting at offset * @param anonymity anonymity level to use for the download * @param options various options * @param cctx initial value for the client context for this download * @param parent parent download to associate this download with (use NULL * for top-level downloads; useful for manually-triggered recursive downloads) * @return context that can be used to control this download */ struct GNUNET_FS_DownloadContext * GNUNET_FS_download_start (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx, struct GNUNET_FS_DownloadContext *parent) { struct GNUNET_FS_DownloadContext *dc; dc = create_download_context (h, uri, meta, filename, tempname, offset, length, anonymity, options, cctx); if (NULL == dc) return NULL; dc->parent = parent; if (NULL != parent) GNUNET_CONTAINER_DLL_insert (parent->child_head, parent->child_tail, dc); else if (0 == (GNUNET_FS_DOWNLOAD_IS_PROBE & options) ) dc->top = GNUNET_FS_make_top (dc->h, &GNUNET_FS_download_signal_suspend_, dc); return dc; } /** * Download parts of a file based on a search result. The download * will be associated with the search result (and the association * will be preserved when serializing/deserializing the state). * If the search is stopped, the download will not be aborted but * be 'promoted' to a stand-alone download. * * As with the other download function, this will store * the blocks at the respective offset in the given file. Also, the * download is still using the blocking of the underlying FS * encoding. As a result, the download may *write* outside of the * given boundaries (if offset and length do not match the 32k FS * block boundaries).

* * The given range can be used to focus a download towards a * particular portion of the file (optimization), not to strictly * limit the download to exactly those bytes. * * @param h handle to the file sharing subsystem * @param sr the search result to use for the download (determines uri and * meta data and associations) * @param filename where to store the file, maybe NULL (then no file is * created on disk and data must be grabbed from the callbacks) * @param tempname where to store temporary file data, not used if filename is non-NULL; * can be NULL (in which case we will pick a name if needed); the temporary file * may already exist, in which case we will try to use the data that is there and * if it is not what is desired, will overwrite it * @param offset at what offset should we start the download (typically 0) * @param length how many bytes should be downloaded starting at offset * @param anonymity anonymity level to use for the download * @param options various download options * @param cctx initial value for the client context for this download * @return context that can be used to control this download */ struct GNUNET_FS_DownloadContext * GNUNET_FS_download_start_from_search (struct GNUNET_FS_Handle *h, struct GNUNET_FS_SearchResult *sr, const char *filename, const char *tempname, uint64_t offset, uint64_t length, uint32_t anonymity, enum GNUNET_FS_DownloadOptions options, void *cctx) { struct GNUNET_FS_DownloadContext *dc; if ((NULL == sr) || (NULL != sr->download)) { GNUNET_break (0); return NULL; } dc = create_download_context (h, sr->uri, sr->meta, filename, tempname, offset, length, anonymity, options, cctx); if (NULL == dc) return NULL; dc->search = sr; sr->download = dc; if (NULL != sr->probe_ctx) { GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); sr->probe_ctx = NULL; } if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task) { GNUNET_SCHEDULER_cancel (sr->probe_ping_task); sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK; } return dc; } /** * Start the downloading process (by entering the queue). * * @param dc our download context */ void GNUNET_FS_download_start_downloading_ (struct GNUNET_FS_DownloadContext *dc) { if (dc->completed == dc->length) return; GNUNET_assert (NULL == dc->job_queue); GNUNET_assert (NULL != dc->active); dc->job_queue = GNUNET_FS_queue_ (dc->h, &activate_fs_download, &deactivate_fs_download, dc, (dc->length + DBLOCK_SIZE - 1) / DBLOCK_SIZE, (0 == (dc->options & GNUNET_FS_DOWNLOAD_IS_PROBE)) ? GNUNET_FS_QUEUE_PRIORITY_NORMAL : GNUNET_FS_QUEUE_PRIORITY_PROBE); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download %p put into queue as job %p\n", dc, dc->job_queue); } /** * Stop a download (aborts if download is incomplete). * * @param dc handle for the download * @param do_delete delete files of incomplete downloads */ void GNUNET_FS_download_stop (struct GNUNET_FS_DownloadContext *dc, int do_delete) { struct GNUNET_FS_ProgressInfo pi; int have_children; int search_was_null; if (NULL != dc->top) GNUNET_FS_end_top (dc->h, dc->top); if (GNUNET_SCHEDULER_NO_TASK != dc->task) { GNUNET_SCHEDULER_cancel (dc->task); dc->task = GNUNET_SCHEDULER_NO_TASK; } search_was_null = (NULL == dc->search); if (NULL != dc->search) { dc->search->download = NULL; GNUNET_FS_search_result_sync_ (dc->search); dc->search = NULL; } if (NULL != dc->job_queue) { GNUNET_FS_dequeue_ (dc->job_queue); dc->job_queue = NULL; } if (NULL != dc->te) { GNUNET_FS_tree_encoder_finish (dc->te, NULL); dc->te = NULL; } have_children = (NULL != dc->child_head) ? GNUNET_YES : GNUNET_NO; while (NULL != dc->child_head) GNUNET_FS_download_stop (dc->child_head, do_delete); if (NULL != dc->parent) GNUNET_CONTAINER_DLL_remove (dc->parent->child_head, dc->parent->child_tail, dc); if (NULL != dc->serialization) GNUNET_FS_remove_sync_file_ (dc->h, ((NULL != dc->parent) || (! search_was_null)) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, dc->serialization); if ((GNUNET_YES == have_children) && (NULL == dc->parent)) GNUNET_FS_remove_sync_dir_ (dc->h, (! search_was_null) ? GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD : GNUNET_FS_SYNC_PATH_MASTER_DOWNLOAD, dc->serialization); pi.status = GNUNET_FS_STATUS_DOWNLOAD_STOPPED; GNUNET_FS_download_make_status_ (&pi, dc); GNUNET_FS_free_download_request_ (dc->top_request); dc->top_request = NULL; if (NULL != dc->active) { GNUNET_CONTAINER_multihashmap_destroy (dc->active); dc->active = NULL; } if (NULL != dc->filename) { if ((dc->completed != dc->length) && (GNUNET_YES == do_delete)) { if ( (0 != UNLINK (dc->filename)) && (ENOENT != errno) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", dc->filename); } GNUNET_free (dc->filename); } GNUNET_CONTAINER_meta_data_destroy (dc->meta); GNUNET_FS_uri_destroy (dc->uri); if (NULL != dc->temp_filename) { if (0 != UNLINK (dc->temp_filename)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink", dc->temp_filename); GNUNET_free (dc->temp_filename); } GNUNET_free_non_null (dc->serialization); GNUNET_assert (NULL == dc->job_queue); GNUNET_free (dc); } /* end of fs_download.c */ gnunet-0.10.1/src/fs/gnunet-service-fs_indexing.c0000644000175000017500000004506412225777502016630 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_indexing.c * @brief program that provides indexing functions of the file-sharing service * @author Christian Grothoff */ #include "platform.h" #include #include "gnunet_core_service.h" #include "gnunet_datastore_service.h" #include "gnunet_peer_lib.h" #include "gnunet_protocols.h" #include "gnunet_signatures.h" #include "gnunet_util_lib.h" #include "gnunet-service-fs.h" #include "gnunet-service-fs_indexing.h" #include "fs.h" /** * In-memory information about indexed files (also available * on-disk). */ struct IndexInfo { /** * This is a doubly linked list. */ struct IndexInfo *next; /** * This is a doubly linked list. */ struct IndexInfo *prev; /** * Name of the indexed file. Memory allocated * at the end of this struct (do not free). */ const char *filename; /** * Context for transmitting confirmation to client, * NULL if we've done this already. */ struct GNUNET_SERVER_TransmitContext *tc; /** * Context for hashing of the file. */ struct GNUNET_CRYPTO_FileHashContext *fhc; /** * Hash of the contents of the file. */ struct GNUNET_HashCode file_id; }; /** * Head of linked list of indexed files. */ static struct IndexInfo *indexed_files_head; /** * Tail of linked list of indexed files. */ static struct IndexInfo *indexed_files_tail; /** * Maps hash over content of indexed files to the respective 'struct IndexInfo'. * The filenames are pointers into the indexed_files linked list and * do not need to be freed. */ static struct GNUNET_CONTAINER_MultiHashMap *ifm; /** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Datastore handle. Created and destroyed by code in * gnunet-service-fs (this is an alias). */ static struct GNUNET_DATASTORE_Handle *dsh; /** * Write the current index information list to disk. */ static void write_index_list () { struct GNUNET_BIO_WriteHandle *wh; char *fn; struct IndexInfo *pos; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "FS", "INDEXDB", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "fs", "INDEXDB"); return; } wh = GNUNET_BIO_write_open (fn); if (NULL == wh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, _("Could not open `%s'.\n"), fn); GNUNET_free (fn); return; } for (pos = indexed_files_head; NULL != pos; pos = pos->next) if ((GNUNET_OK != GNUNET_BIO_write (wh, &pos->file_id, sizeof (struct GNUNET_HashCode))) || (GNUNET_OK != GNUNET_BIO_write_string (wh, pos->filename))) break; if (GNUNET_OK != GNUNET_BIO_write_close (wh)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, _("Error writing `%s'.\n"), fn); GNUNET_free (fn); return; } GNUNET_free (fn); } /** * Read index information from disk. */ static void read_index_list () { struct GNUNET_BIO_ReadHandle *rh; char *fn; struct IndexInfo *pos; char *fname; struct GNUNET_HashCode hc; size_t slen; char *emsg; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "FS", "INDEXDB", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "fs", "INDEXDB"); return; } if (GNUNET_NO == GNUNET_DISK_file_test (fn)) { /* no index info yet */ GNUNET_free (fn); return; } rh = GNUNET_BIO_read_open (fn); if (NULL == rh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, _("Could not open `%s'.\n"), fn); GNUNET_free (fn); return; } while ((GNUNET_OK == GNUNET_BIO_read (rh, "Hash of indexed file", &hc, sizeof (struct GNUNET_HashCode))) && (GNUNET_OK == GNUNET_BIO_read_string (rh, "Name of indexed file", &fname, 1024 * 16)) && (fname != NULL)) { slen = strlen (fname) + 1; pos = GNUNET_malloc (sizeof (struct IndexInfo) + slen); pos->file_id = hc; pos->filename = (const char *) &pos[1]; memcpy (&pos[1], fname, slen); if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (ifm, &pos->file_id, pos, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { GNUNET_free (pos); } else { GNUNET_CONTAINER_DLL_insert (indexed_files_head, indexed_files_tail, pos); } GNUNET_free (fname); } if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) GNUNET_free (emsg); GNUNET_free (fn); } /** * We've validated the hash of the file we're about to index. Signal * success to the client and update our internal data structures. * * @param ii the index info entry for the request */ static void signal_index_ok (struct IndexInfo *ii) { struct IndexInfo *ir; if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_put (ifm, &ii->file_id, ii, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { ir = GNUNET_CONTAINER_multihashmap_get (ifm, &ii->file_id); GNUNET_assert (NULL != ir); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Index request received for file `%s' is already indexed as `%s'. Permitting anyway.\n"), ii->filename, ir->filename); GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK); GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES); GNUNET_free (ii); return; } GNUNET_CONTAINER_DLL_insert (indexed_files_head, indexed_files_tail, ii); write_index_list (); GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK); GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES); ii->tc = NULL; } /** * Function called once the hash computation over an * indexed file has completed. * * @param cls closure, our publishing context * @param res resulting hash, NULL on error */ static void hash_for_index_val (void *cls, const struct GNUNET_HashCode * res) { struct IndexInfo *ii = cls; ii->fhc = NULL; if ((res == NULL) || (0 != memcmp (res, &ii->file_id, sizeof (struct GNUNET_HashCode)))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Hash mismatch trying to index file `%s' which has hash `%s'\n"), ii->filename, GNUNET_h2s (res)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Wanted `%s'\n", GNUNET_h2s (&ii->file_id)); GNUNET_SERVER_transmit_context_append_data (ii->tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED); GNUNET_SERVER_transmit_context_run (ii->tc, GNUNET_TIME_UNIT_MINUTES); GNUNET_free (ii); return; } signal_index_ok (ii); } /** * Handle INDEX_START-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ void GNUNET_FS_handle_index_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct IndexStartMessage *ism; char *fn; uint16_t msize; struct IndexInfo *ii; size_t slen; uint64_t dev; uint64_t ino; uint64_t mydev; uint64_t myino; msize = ntohs (message->size); if ((msize <= sizeof (struct IndexStartMessage)) || (((const char *) message)[msize - 1] != '\0')) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } ism = (const struct IndexStartMessage *) message; if (0 != ism->reserved) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } fn = GNUNET_STRINGS_filename_expand ((const char *) &ism[1]); if (fn == NULL) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } dev = GNUNET_ntohll (ism->device); ino = GNUNET_ntohll (ism->inode); ism = (const struct IndexStartMessage *) message; slen = strlen (fn) + 1; ii = GNUNET_malloc (sizeof (struct IndexInfo) + slen); ii->filename = (const char *) &ii[1]; memcpy (&ii[1], fn, slen); ii->file_id = ism->file_id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message for file `%s'\n", "START_INDEX", ii->filename); ii->tc = GNUNET_SERVER_transmit_context_create (client); mydev = 0; myino = 0; if (((dev != 0) || (ino != 0)) && (GNUNET_OK == GNUNET_DISK_file_get_identifiers (fn, &mydev, &myino)) && ((dev == mydev) && (ino == myino))) { /* fast validation OK! */ signal_index_ok (ii); GNUNET_free (fn); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mismatch in file identifiers (%llu != %llu or %u != %u), need to hash.\n", (unsigned long long) ino, (unsigned long long) myino, (unsigned int) dev, (unsigned int) mydev); /* slow validation, need to hash full file (again) */ ii->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE, fn, HASHING_BLOCKSIZE, &hash_for_index_val, ii); if (ii->fhc == NULL) hash_for_index_val (ii, NULL); GNUNET_free (fn); } /** * Handle INDEX_LIST_GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ void GNUNET_FS_handle_index_list_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_SERVER_TransmitContext *tc; struct IndexInfoMessage *iim; char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; size_t slen; const char *fn; struct IndexInfo *pos; tc = GNUNET_SERVER_transmit_context_create (client); iim = (struct IndexInfoMessage *) buf; for (pos = indexed_files_head; NULL != pos; pos = pos->next) { fn = pos->filename; slen = strlen (fn) + 1; if (slen + sizeof (struct IndexInfoMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); break; } iim->header.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY); iim->header.size = htons (slen + sizeof (struct IndexInfoMessage)); iim->reserved = 0; iim->file_id = pos->file_id; memcpy (&iim[1], fn, slen); GNUNET_SERVER_transmit_context_append_message (tc, &iim->header); } GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_MINUTES); } /** * Handle UNINDEX-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ void GNUNET_FS_handle_unindex (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct UnindexMessage *um; struct IndexInfo *pos; struct GNUNET_SERVER_TransmitContext *tc; int found; um = (const struct UnindexMessage *) message; if (0 != um->reserved) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } found = GNUNET_NO; for (pos = indexed_files_head; NULL != pos; pos = pos->next) { if (0 == memcmp (&pos->file_id, &um->file_id, sizeof (struct GNUNET_HashCode))) { GNUNET_CONTAINER_DLL_remove (indexed_files_head, indexed_files_tail, pos); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (ifm, &pos->file_id, pos)); GNUNET_free (pos); found = GNUNET_YES; break; } } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client requested unindexing of file `%s': %s\n", GNUNET_h2s (&um->file_id), found ? "found" : "not found"); if (GNUNET_YES == found) write_index_list (); tc = GNUNET_SERVER_transmit_context_create (client); GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_MINUTES); } /** * Continuation called from datastore's remove * function. * * @param cls unused * @param success did the deletion work? * @param min_expiration minimum expiration time required for content to be stored * @param msg error message */ static void remove_cont (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { if (GNUNET_OK != success) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to delete bogus block: %s\n"), msg); } /** * We've received an on-demand encoded block from the datastore. * Attempt to do on-demand encoding and (if successful), call the * continuation with the resulting block. On error, clean up and ask * the datastore for more results. * * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * @param cont function to call with the actual block (at most once, on success) * @param cont_cls closure for cont * @return GNUNET_OK on success */ int GNUNET_FS_handle_on_demand_block (const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid, GNUNET_DATASTORE_DatumProcessor cont, void *cont_cls) { const struct OnDemandBlock *odb; struct GNUNET_HashCode nkey; struct GNUNET_CRYPTO_SymmetricSessionKey skey; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_HashCode query; ssize_t nsize; char ndata[DBLOCK_SIZE]; char edata[DBLOCK_SIZE]; const char *fn; struct GNUNET_DISK_FileHandle *fh; uint64_t off; struct IndexInfo *ii; if (size != sizeof (struct OnDemandBlock)) { GNUNET_break (0); GNUNET_DATASTORE_remove (dsh, key, size, data, -1, -1, GNUNET_TIME_UNIT_FOREVER_REL, &remove_cont, NULL); return GNUNET_SYSERR; } odb = (const struct OnDemandBlock *) data; off = GNUNET_ntohll (odb->offset); ii = GNUNET_CONTAINER_multihashmap_get (ifm, &odb->file_id); if (NULL == ii) { GNUNET_break (0); return GNUNET_SYSERR; } fn = ii->filename; if ((NULL == fn) || (0 != ACCESS (fn, R_OK))) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# index blocks removed: original file inaccessible"), 1, GNUNET_YES); GNUNET_DATASTORE_remove (dsh, key, size, data, -1, -1, GNUNET_TIME_UNIT_FOREVER_REL, &remove_cont, NULL); return GNUNET_SYSERR; } if ((NULL == (fh = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE))) || (off != GNUNET_DISK_file_seek (fh, off, GNUNET_DISK_SEEK_SET)) || (-1 == (nsize = GNUNET_DISK_file_read (fh, ndata, sizeof (ndata))))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not access indexed file `%s' (%s) at offset %llu: %s\n"), GNUNET_h2s (&odb->file_id), fn, (unsigned long long) off, (fn == NULL) ? _("not indexed") : STRERROR (errno)); if (fh != NULL) GNUNET_DISK_file_close (fh); GNUNET_DATASTORE_remove (dsh, key, size, data, -1, -1, GNUNET_TIME_UNIT_FOREVER_REL, &remove_cont, NULL); return GNUNET_SYSERR; } GNUNET_DISK_file_close (fh); GNUNET_CRYPTO_hash (ndata, nsize, &nkey); GNUNET_CRYPTO_hash_to_aes_key (&nkey, &skey, &iv); GNUNET_CRYPTO_symmetric_encrypt (ndata, nsize, &skey, &iv, edata); GNUNET_CRYPTO_hash (edata, nsize, &query); if (0 != memcmp (&query, key, sizeof (struct GNUNET_HashCode))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Indexed file `%s' changed at offset %llu\n"), fn, (unsigned long long) off); GNUNET_DATASTORE_remove (dsh, key, size, data, -1, -1, GNUNET_TIME_UNIT_FOREVER_REL, &remove_cont, NULL); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "On-demand encoded block for query `%s'\n", GNUNET_h2s (key)); cont (cont_cls, key, nsize, edata, GNUNET_BLOCK_TYPE_FS_DBLOCK, priority, anonymity, expiration, uid); return GNUNET_OK; } /** * Shutdown the module. */ void GNUNET_FS_indexing_done () { struct IndexInfo *pos; while (NULL != (pos = indexed_files_head)) { GNUNET_CONTAINER_DLL_remove (indexed_files_head, indexed_files_tail, pos); if (pos->fhc != NULL) GNUNET_CRYPTO_hash_file_cancel (pos->fhc); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (ifm, &pos->file_id, pos)); GNUNET_free (pos); } GNUNET_CONTAINER_multihashmap_destroy (ifm); ifm = NULL; cfg = NULL; } /** * Initialize the indexing submodule. * * @param c configuration to use * @param d datastore to use */ int GNUNET_FS_indexing_init (const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_DATASTORE_Handle *d) { cfg = c; dsh = d; ifm = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_YES); read_index_list (); return GNUNET_OK; } /* end of gnunet-service-fs_indexing.c */ gnunet-0.10.1/src/fs/test_gnunet_service_fs_migration_data.conf0000644000175000017500000000027412225230043021665 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-service-fs-migration/ [testbed] OVERLAY_TOPOLOGY = CLIQUE [ats] WAN_QUOTA_IN = 3932160 WAN_QUOTA_OUT = 3932160 gnunet-0.10.1/src/fs/gnunet-service-fs_push.h0000644000175000017500000000315712225777503016005 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_push.h * @brief support for pushing out content * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_FS_PUSH_H #define GNUNET_SERVICE_FS_PUSH_H #include "gnunet-service-fs.h" /** * Setup the module. */ void GSF_push_init_ (void); /** * Shutdown the module. */ void GSF_push_done_ (void); /** * A peer connected to us or we are now again allowed to push content. * Start pushing content to this peer. * * @param peer handle for the peer that connected */ void GSF_push_start_ (struct GSF_ConnectedPeer *peer); /** * A peer disconnected from us or asked us to stop pushing content for * a while. Stop pushing content to this peer. * * @param peer handle for the peer that disconnected */ void GSF_push_stop_ (struct GSF_ConnectedPeer *peer); #endif gnunet-0.10.1/src/fs/fs_search.c0000644000175000017500000014263412301361474013325 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Tem ple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/fs_search.c * @brief Helper functions for searching. * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_fs_service.h" #include "gnunet_protocols.h" #include "fs_api.h" #include "fs_publish_ublock.h" /** * Number of availability trials we perform per search result. */ #define AVAILABILITY_TRIALS_MAX 8 /** * Fill in all of the generic fields for a search event and * call the callback. * * @param pi structure to fill in * @param h file-sharing handle * @param sc overall search context * @return value returned by the callback */ void * GNUNET_FS_search_make_status_ (struct GNUNET_FS_ProgressInfo *pi, struct GNUNET_FS_Handle *h, struct GNUNET_FS_SearchContext *sc) { void *ret; pi->value.search.sc = sc; pi->value.search.cctx = (NULL != sc) ? sc->client_info : NULL; pi->value.search.pctx = ((NULL == sc) || (NULL == sc->psearch_result)) ? NULL : sc->psearch_result->client_info; pi->value.search.query = (NULL != sc) ? sc->uri : NULL; pi->value.search.duration = (NULL != sc) ? GNUNET_TIME_absolute_get_duration (sc->start_time) : GNUNET_TIME_UNIT_ZERO; pi->value.search.anonymity = (NULL != sc) ? sc->anonymity : 0; pi->fsh = h; ret = h->upcb (h->upcb_cls, pi); return ret; } /** * Check if the given result is identical to the given URI. * * @param cls points to the URI we check against * @param key not used * @param value a `struct GNUNET_FS_SearchResult` who's URI we * should compare with * @return #GNUNET_SYSERR if the result is present, * #GNUNET_OK otherwise */ static int test_result_present (void *cls, const struct GNUNET_HashCode * key, void *value) { const struct GNUNET_FS_Uri *uri = cls; struct GNUNET_FS_SearchResult *sr = value; if (GNUNET_FS_uri_test_equal (uri, sr->uri)) return GNUNET_SYSERR; return GNUNET_OK; } /** * We've found a new CHK result. Let the client * know about it. * * @param sc the search context * @param sr the specific result */ static void notify_client_chk_result (struct GNUNET_FS_SearchContext *sc, struct GNUNET_FS_SearchResult *sr) { struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_SEARCH_RESULT; pi.value.search.specifics.result.meta = sr->meta; pi.value.search.specifics.result.uri = sr->uri; pi.value.search.specifics.result.result = sr; pi.value.search.specifics.result.applicability_rank = sr->optional_support; sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); } /** * We've found new information about an existing CHK result. Let the * client know about it. * * @param sc the search context * @param sr the specific result */ static void notify_client_chk_update (struct GNUNET_FS_SearchContext *sc, struct GNUNET_FS_SearchResult *sr) { struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_SEARCH_UPDATE; pi.value.search.specifics.update.cctx = sr->client_info; pi.value.search.specifics.update.meta = sr->meta; pi.value.search.specifics.update.uri = sr->uri; pi.value.search.specifics.update.availability_rank = 2 * sr->availability_success - sr->availability_trials; pi.value.search.specifics.update.availability_certainty = sr->availability_trials; pi.value.search.specifics.update.applicability_rank = sr->optional_support; pi.value.search.specifics.update.current_probe_time = GNUNET_TIME_absolute_get_duration (sr->probe_active_time); sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); } /** * Context for "get_result_present". */ struct GetResultContext { /** * The URI we're looking for. */ const struct GNUNET_FS_Uri *uri; /** * Where to store a pointer to the search * result struct if we found a match. */ struct GNUNET_FS_SearchResult *sr; }; /** * Check if the given result is identical to the given URI and if so * return it. * * @param cls a `struct GetResultContext` * @param key not used * @param value a `struct GNUNET_FS_SearchResult` who's URI we * should compare with * @return #GNUNET_OK */ static int get_result_present (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GetResultContext *grc = cls; struct GNUNET_FS_SearchResult *sr = value; if (GNUNET_FS_uri_test_equal (grc->uri, sr->uri)) grc->sr = sr; return GNUNET_OK; } /** * Signal result of last probe to client and then schedule next * probe. * * @param sr search result to signal for */ static void signal_probe_result (struct GNUNET_FS_SearchResult *sr) { struct GNUNET_FS_ProgressInfo pi; pi.status = GNUNET_FS_STATUS_SEARCH_UPDATE; pi.value.search.specifics.update.cctx = sr->client_info; pi.value.search.specifics.update.meta = sr->meta; pi.value.search.specifics.update.uri = sr->uri; pi.value.search.specifics.update.availability_rank = 2 * sr->availability_success - sr->availability_trials; pi.value.search.specifics.update.availability_certainty = sr->availability_trials; pi.value.search.specifics.update.applicability_rank = sr->optional_support; pi.value.search.specifics.update.current_probe_time = GNUNET_TIME_absolute_get_duration (sr->probe_active_time); sr->client_info = GNUNET_FS_search_make_status_ (&pi, sr->h, sr->sc); GNUNET_FS_search_start_probe_ (sr); } /** * Handle the case where we have failed to receive a response for our probe. * * @param cls our `struct GNUNET_FS_SearchResult *` * @param tc scheduler context */ static void probe_failure_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_SearchResult *sr = cls; sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; sr->availability_trials++; GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); sr->probe_ctx = NULL; if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task) { GNUNET_SCHEDULER_cancel (sr->probe_ping_task); sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_FS_search_result_sync_ (sr); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Probe #%u for search result %p failed\n", sr->availability_trials, sr); signal_probe_result (sr); } /** * Handle the case where we have gotten a response for our probe. * * @param cls our `struct GNUNET_FS_SearchResult *` * @param tc scheduler context */ static void probe_success_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_SearchResult *sr = cls; sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; sr->availability_trials++; sr->availability_success++; GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); sr->probe_ctx = NULL; if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task) { GNUNET_SCHEDULER_cancel (sr->probe_ping_task); sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_FS_search_result_sync_ (sr); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Probe #%u for search result %p succeeded\n", sr->availability_trials, sr); signal_probe_result (sr); } /** * Notification of FS that a search probe has made progress. * This function is used INSTEAD of the client's event handler * for downloads where the #GNUNET_FS_DOWNLOAD_IS_PROBE flag is set. * * @param cls closure, always NULL (!), actual closure * is in the client-context of the info struct * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the `struct GNUNET_FS_ProgressInfo`. */ void * GNUNET_FS_search_probe_progress_ (void *cls, const struct GNUNET_FS_ProgressInfo *info) { struct GNUNET_FS_SearchResult *sr = info->value.download.cctx; struct GNUNET_TIME_Relative dur; switch (info->status) { case GNUNET_FS_STATUS_DOWNLOAD_START: /* ignore */ break; case GNUNET_FS_STATUS_DOWNLOAD_RESUME: /* probes should never be resumed */ GNUNET_assert (0); break; case GNUNET_FS_STATUS_DOWNLOAD_SUSPEND: /* probes should never be suspended */ GNUNET_break (0); break; case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: /* ignore */ break; case GNUNET_FS_STATUS_DOWNLOAD_ERROR: if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->remaining_probe_time, &probe_failure_handler, sr); break; case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED: if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } sr->probe_cancel_task = GNUNET_SCHEDULER_add_now (&probe_success_handler, sr); break; case GNUNET_FS_STATUS_DOWNLOAD_STOPPED: if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } sr = NULL; break; case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE: if (GNUNET_SCHEDULER_NO_TASK == sr->probe_cancel_task) { sr->probe_active_time = GNUNET_TIME_absolute_get (); sr->probe_cancel_task = GNUNET_SCHEDULER_add_delayed (sr->remaining_probe_time, &probe_failure_handler, sr); } break; case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE: if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } dur = GNUNET_TIME_absolute_get_duration (sr->probe_active_time); sr->remaining_probe_time = GNUNET_TIME_relative_subtract (sr->remaining_probe_time, dur); if (0 == sr->remaining_probe_time.rel_value_us) sr->probe_cancel_task = GNUNET_SCHEDULER_add_now (&probe_failure_handler, sr); GNUNET_FS_search_result_sync_ (sr); break; default: GNUNET_break (0); return NULL; } return sr; } /** * Task run periodically to remind clients that a probe is active. * * @param cls the 'struct GNUNET_FS_SearchResult' that we are probing for * @param tc scheduler context */ static void probe_ping_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_SearchResult *sr = cls; signal_probe_result (sr); sr->probe_ping_task = GNUNET_SCHEDULER_add_delayed (GNUNET_FS_PROBE_UPDATE_FREQUENCY, &probe_ping_task, sr); } /** * Start download probes for the given search result. * * @param sr the search result */ void GNUNET_FS_search_start_probe_ (struct GNUNET_FS_SearchResult *sr) { uint64_t off; uint64_t len; if (NULL != sr->probe_ctx) return; if (NULL != sr->download) return; if (0 == (sr->h->flags & GNUNET_FS_FLAGS_DO_PROBES)) return; if (sr->availability_trials > AVAILABILITY_TRIALS_MAX) return; if ( (GNUNET_FS_URI_CHK != sr->uri->type) && (GNUNET_FS_URI_LOC != sr->uri->type)) return; len = GNUNET_FS_uri_chk_get_file_size (sr->uri); if (0 == len) return; if ((len <= DBLOCK_SIZE) && (sr->availability_success > 0)) return; off = len / DBLOCK_SIZE; if (off > 0) off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, off); off *= DBLOCK_SIZE; if (len - off < DBLOCK_SIZE) len = len - off; else len = DBLOCK_SIZE; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting probe #%u (at offset %llu) for search result %p\n", sr->availability_trials + 1, (unsigned long long) off, sr); sr->remaining_probe_time = GNUNET_TIME_relative_multiply (sr->h->avg_block_latency, 2 * (1 + sr->availability_trials)); sr->probe_ctx = GNUNET_FS_download_start (sr->h, sr->uri, sr->meta, NULL, NULL, off, len, sr->anonymity, GNUNET_FS_DOWNLOAD_NO_TEMPORARIES | GNUNET_FS_DOWNLOAD_IS_PROBE, sr, NULL); sr->probe_ping_task = GNUNET_SCHEDULER_add_now (&probe_ping_task, sr); } /** * Start download probes for the given search result. * * @param h file-sharing handle to use for the operation * @param uri URI to probe * @param meta meta data associated with the URI * @param client_info client info pointer to use for associated events * @param anonymity anonymity level to use for the probes * @return the search result handle to access the probe activity */ struct GNUNET_FS_SearchResult * GNUNET_FS_probe (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, void *client_info, uint32_t anonymity) { struct GNUNET_FS_SearchResult *sr; GNUNET_assert (NULL != h); sr = GNUNET_new (struct GNUNET_FS_SearchResult); sr->h = h; sr->uri = GNUNET_FS_uri_dup (uri); sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); sr->client_info = client_info; sr->anonymity = anonymity; GNUNET_FS_search_start_probe_ (sr); return sr; } /** * Stop probing activity associated with a search result. * * @param sr search result */ static void GNUNET_FS_search_stop_probe_ (struct GNUNET_FS_SearchResult *sr) { if (NULL != sr->probe_ctx) { GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); sr->probe_ctx = NULL; } if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task) { GNUNET_SCHEDULER_cancel (sr->probe_ping_task); sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Stop probe activity. Must ONLY be used on values * returned from #GNUNET_FS_probe. * * @param sr search result to stop probing for (freed) * @return the value of the 'client_info' pointer */ void * GNUNET_FS_probe_stop (struct GNUNET_FS_SearchResult *sr) { void *client_info; GNUNET_assert (NULL == sr->sc); GNUNET_FS_search_stop_probe_ (sr); GNUNET_FS_uri_destroy (sr->uri); GNUNET_CONTAINER_meta_data_destroy (sr->meta); client_info = sr->client_info; GNUNET_free (sr); return client_info; } /** * We have received a KSK result. Check how it fits in with the * overall query and notify the client accordingly. * * @param sc context for the overall query * @param ent entry for the specific keyword * @param uri the URI that was found * @param meta metadata associated with the URI * under the @a ent keyword */ static void process_ksk_result (struct GNUNET_FS_SearchContext *sc, struct SearchRequestEntry *ent, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta) { struct GNUNET_HashCode key; struct GNUNET_FS_SearchResult *sr; struct GetResultContext grc; int is_new; unsigned int koff; /* check if new */ GNUNET_assert (NULL != sc); GNUNET_FS_uri_to_key (uri, &key); if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_get_multiple (ent->results, &key, &test_result_present, (void *) uri)) return; /* duplicate result */ /* try to find search result in master map */ grc.sr = NULL; grc.uri = uri; GNUNET_CONTAINER_multihashmap_get_multiple (sc->master_result_map, &key, &get_result_present, &grc); sr = grc.sr; is_new = (NULL == sr) || (sr->mandatory_missing > 0); if (NULL == sr) { sr = GNUNET_new (struct GNUNET_FS_SearchResult); sr->h = sc->h; sr->sc = sc; sr->anonymity = sc->anonymity; sr->uri = GNUNET_FS_uri_dup (uri); sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); sr->mandatory_missing = sc->mandatory_count; sr->key = key; sr->keyword_bitmap = GNUNET_malloc ((sc->uri->data.ksk.keywordCount + 7) / 8); /* round up, count bits */ GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, &key, sr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } else { GNUNET_CONTAINER_meta_data_merge (sr->meta, meta); } koff = ent - sc->requests; GNUNET_assert ( (ent >= sc->requests) && (koff < sc->uri->data.ksk.keywordCount)); sr->keyword_bitmap[koff / 8] |= (1 << (koff % 8)); /* check if mandatory satisfied */ if (ent->mandatory) sr->mandatory_missing--; else sr->optional_support++; if (0 != sr->mandatory_missing) return; if (is_new) notify_client_chk_result (sc, sr); else notify_client_chk_update (sc, sr); GNUNET_FS_search_result_sync_ (sr); GNUNET_FS_search_start_probe_ (sr); } /** * Start search for content, internal API. * * @param h handle to the file sharing subsystem * @param uri specifies the search parameters; can be * a KSK URI or an SKS URI. * @param anonymity desired level of anonymity * @param options options for the search * @param cctx client context * @param psearch parent search result (for namespace update searches) * @return context that can be used to control the search */ static struct GNUNET_FS_SearchContext * search_start (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, uint32_t anonymity, enum GNUNET_FS_SearchOptions options, void *cctx, struct GNUNET_FS_SearchResult *psearch); /** * We have received an SKS result. Start searching for updates and * notify the client if it is a new result. * * @param sc context for the overall query * @param id_update identifier for updates, NULL for none * @param uri the URI that was found * @param meta metadata associated with the URI */ static void process_sks_result (struct GNUNET_FS_SearchContext *sc, const char *id_update, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta) { struct GNUNET_FS_Uri uu; struct GNUNET_HashCode key; struct GNUNET_FS_SearchResult *sr; /* check if new */ GNUNET_assert (NULL != sc); GNUNET_FS_uri_to_key (uri, &key); GNUNET_CRYPTO_hash_xor (&uri->data.chk.chk.key, &uri->data.chk.chk.query, &key); if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_get_multiple (sc->master_result_map, &key, &test_result_present, (void *) uri)) return; /* duplicate result */ sr = GNUNET_new (struct GNUNET_FS_SearchResult); sr->h = sc->h; sr->sc = sc; sr->anonymity = sc->anonymity; sr->uri = GNUNET_FS_uri_dup (uri); sr->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); sr->key = key; GNUNET_CONTAINER_multihashmap_put (sc->master_result_map, &key, sr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GNUNET_FS_search_result_sync_ (sr); GNUNET_FS_search_start_probe_ (sr); /* notify client */ notify_client_chk_result (sc, sr); /* search for updates */ if (0 == strlen (id_update)) return; /* no updates */ uu.type = GNUNET_FS_URI_SKS; uu.data.sks.ns = sc->uri->data.sks.ns; uu.data.sks.identifier = GNUNET_strdup (id_update); (void) search_start (sc->h, &uu, sc->anonymity, sc->options, NULL, sr); GNUNET_free (uu.data.sks.identifier); } /** * Decrypt a ublock using a 'keyword' as the passphrase. Given the * KSK public key derived from the keyword, this function looks up * the original keyword in the search context and decrypts the * given ciphertext block. * * @param sc search context with the keywords * @param dpub derived public key used for the search * @param edata encrypted data * @param edata_size number of bytes in @a edata (and @a data) * @param data where to store the plaintext * @return keyword index on success, #GNUNET_SYSERR on error (no such * keyword, internal error) */ static int decrypt_block_with_keyword (const struct GNUNET_FS_SearchContext *sc, const struct GNUNET_CRYPTO_EcdsaPublicKey *dpub, const void *edata, size_t edata_size, char *data) { const struct GNUNET_CRYPTO_EcdsaPrivateKey *anon; struct GNUNET_CRYPTO_EcdsaPublicKey anon_pub; unsigned int i; /* find key */ for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) if (0 == memcmp (dpub, &sc->requests[i].dpub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) break; if (i == sc->uri->data.ksk.keywordCount) { /* oops, does not match any of our keywords!? */ GNUNET_break (0); return GNUNET_SYSERR; } /* decrypt */ anon = GNUNET_CRYPTO_ecdsa_key_get_anonymous (); GNUNET_CRYPTO_ecdsa_key_get_public (anon, &anon_pub); GNUNET_FS_ublock_decrypt_ (edata, edata_size, &anon_pub, sc->requests[i].keyword, data); return i; } /** * Process a keyword search result. The actual type of block is * a UBlock; we know it is a keyword search result because that's * what we were searching for. * * @param sc our search context * @param ub the ublock with the keyword search result * @param size size of @a ub */ static void process_kblock (struct GNUNET_FS_SearchContext *sc, const struct UBlock *ub, size_t size) { size_t j; char pt[size - sizeof (struct UBlock)]; const char *eos; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *uri; char *emsg; int i; if (-1 == (i = decrypt_block_with_keyword (sc, &ub->verification_key, &ub[1], size - sizeof (struct UBlock), pt))) return; /* parse; pt[0] is just '\0', so we skip over that */ eos = memchr (&pt[1], '\0', sizeof (pt) - 1); if (NULL == eos) { GNUNET_break_op (0); return; } if (NULL == (uri = GNUNET_FS_uri_parse (&pt[1], &emsg))) { GNUNET_break_op (0); /* ublock malformed */ GNUNET_free_non_null (emsg); return; } j = eos - pt + 1; if (sizeof (pt) == j) meta = GNUNET_CONTAINER_meta_data_create (); else meta = GNUNET_CONTAINER_meta_data_deserialize (&pt[j], sizeof (pt) - j); if (NULL == meta) { GNUNET_break_op (0); /* ublock malformed */ GNUNET_FS_uri_destroy (uri); return; } process_ksk_result (sc, &sc->requests[i], uri, meta); /* clean up */ GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_FS_uri_destroy (uri); } /** * Process a namespace-search result. The actual type of block is * a UBlock; we know it is a namespace search result because that's * what we were searching for. * * @param sc our search context * @param ub the ublock with a namespace result * @param size size of @a ub */ static void process_sblock (struct GNUNET_FS_SearchContext *sc, const struct UBlock *ub, size_t size) { size_t len = size - sizeof (struct UBlock); char pt[len]; struct GNUNET_FS_Uri *uri; struct GNUNET_CONTAINER_MetaData *meta; const char *id; const char *uris; size_t off; char *emsg; GNUNET_FS_ublock_decrypt_ (&ub[1], len, &sc->uri->data.sks.ns, sc->uri->data.sks.identifier, pt); /* parse */ if (0 == (off = GNUNET_STRINGS_buffer_tokenize (pt, len, 2, &id, &uris))) { GNUNET_break_op (0); /* ublock malformed */ return; } if (NULL == (meta = GNUNET_CONTAINER_meta_data_deserialize (&pt[off], len - off))) { GNUNET_break_op (0); /* ublock malformed */ return; } if (NULL == (uri = GNUNET_FS_uri_parse (uris, &emsg))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse URI `%s': %s\n"), uris, emsg); GNUNET_break_op (0); /* ublock malformed */ GNUNET_free_non_null (emsg); GNUNET_CONTAINER_meta_data_destroy (meta); return; } /* process */ process_sks_result (sc, id, uri, meta); /* clean up */ GNUNET_FS_uri_destroy (uri); GNUNET_CONTAINER_meta_data_destroy (meta); } /** * Process a search result. * * @param sc our search context * @param type type of the result * @param expiration when it will expire * @param data the (encrypted) response * @param size size of @a data */ static void process_result (struct GNUNET_FS_SearchContext *sc, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration, const void *data, size_t size) { if (GNUNET_TIME_absolute_get_duration (expiration).rel_value_us > 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result received has already expired.\n"); return; /* result expired */ } switch (type) { case GNUNET_BLOCK_TYPE_FS_UBLOCK: if (GNUNET_FS_URI_SKS == sc->uri->type) process_sblock (sc, data, size); else process_kblock (sc, data, size); break; case GNUNET_BLOCK_TYPE_ANY: GNUNET_break (0); break; case GNUNET_BLOCK_TYPE_FS_DBLOCK: GNUNET_break (0); break; case GNUNET_BLOCK_TYPE_FS_ONDEMAND: GNUNET_break (0); break; case GNUNET_BLOCK_TYPE_FS_IBLOCK: GNUNET_break (0); break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Got result with unknown block type `%d', ignoring"), type); break; } } /** * Shutdown any existing connection to the FS * service and try to establish a fresh one * (and then re-transmit our search request). * * @param sc the search to reconnec */ static void try_reconnect (struct GNUNET_FS_SearchContext *sc); /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void receive_results (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_FS_SearchContext *sc = cls; const struct ClientPutMessage *cm; uint16_t msize; if ((NULL == msg) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_FS_PUT) || (ntohs (msg->size) <= sizeof (struct ClientPutMessage))) { try_reconnect (sc); return; } msize = ntohs (msg->size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving %u bytes of result from fs service\n", msize); cm = (const struct ClientPutMessage *) msg; process_result (sc, ntohl (cm->type), GNUNET_TIME_absolute_ntoh (cm->expiration), &cm[1], msize - sizeof (struct ClientPutMessage)); /* continue receiving */ GNUNET_CLIENT_receive (sc->client, &receive_results, sc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Schedule the transmission of the (next) search request * to the service. * * @param sc context for the search */ static void schedule_transmit_search_request (struct GNUNET_FS_SearchContext *sc); /** * Closure for 'build_result_set'. */ struct MessageBuilderContext { /** * How many entries can we store to xoff. */ unsigned int put_cnt; /** * How many entries should we skip. */ unsigned int skip_cnt; /** * Where to store the keys. */ struct GNUNET_HashCode *xoff; /** * Search context we are iterating for. */ struct GNUNET_FS_SearchContext *sc; /** * Keyword offset the search result must match (0 for SKS) */ unsigned int keyword_offset; }; /** * Iterating over the known results, pick those matching the given * result range and store their keys at 'xoff'. * * @param cls the `struct MessageBuilderContext` * @param key key for a result * @param value the search result * @return #GNUNET_OK to continue iterating */ static int build_result_set (void *cls, const struct GNUNET_HashCode * key, void *value) { struct MessageBuilderContext *mbc = cls; struct GNUNET_FS_SearchResult *sr = value; if ( (NULL != sr->keyword_bitmap) && (0 == (sr->keyword_bitmap[mbc->keyword_offset / 8] & (1 << (mbc->keyword_offset % 8)))) ) return GNUNET_OK; /* have no match for this keyword yet */ if (mbc->skip_cnt > 0) { mbc->skip_cnt--; return GNUNET_OK; } if (0 == mbc->put_cnt) return GNUNET_SYSERR; mbc->sc->search_request_map_offset++; mbc->xoff[--mbc->put_cnt] = *key; return GNUNET_OK; } /** * Iterating over the known results, count those * matching the given result range and increment * put count for each. * * @param cls the `struct MessageBuilderContext` * @param key key for a result * @param value the search result * @return #GNUNET_OK to continue iterating */ static int find_result_set (void *cls, const struct GNUNET_HashCode * key, void *value) { struct MessageBuilderContext *mbc = cls; struct GNUNET_FS_SearchResult *sr = value; if ( (NULL != sr->keyword_bitmap) && (0 == (sr->keyword_bitmap[mbc->keyword_offset / 8] & (1 << (mbc->keyword_offset % 8)))) ) return GNUNET_OK; /* have no match for this keyword yet */ mbc->put_cnt++; return GNUNET_OK; } /** * We're ready to transmit the search request to the * file-sharing service. Do it. * * @param cls closure * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ static size_t transmit_search_request (void *cls, size_t size, void *buf) { struct GNUNET_FS_SearchContext *sc = cls; struct MessageBuilderContext mbc; size_t msize; struct SearchMessage *sm; struct GNUNET_CRYPTO_EcdsaPublicKey dpub; unsigned int sqms; uint32_t options; if (NULL == buf) { try_reconnect (sc); return 0; } mbc.sc = sc; mbc.skip_cnt = sc->search_request_map_offset; sm = buf; sm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_START_SEARCH); mbc.xoff = (struct GNUNET_HashCode *) & sm[1]; options = SEARCH_MESSAGE_OPTION_NONE; if (0 != (sc->options & GNUNET_FS_SEARCH_OPTION_LOOPBACK_ONLY)) options |= SEARCH_MESSAGE_OPTION_LOOPBACK_ONLY; if (GNUNET_FS_uri_test_ksk (sc->uri)) { msize = sizeof (struct SearchMessage); GNUNET_assert (size >= msize); mbc.keyword_offset = sc->keyword_offset; /* calculate total number of known results (in put_cnt => sqms) */ mbc.put_cnt = 0; GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &find_result_set, &mbc); sqms = mbc.put_cnt; /* calculate how many results we can send in this message */ mbc.put_cnt = (size - msize) / sizeof (struct GNUNET_HashCode); mbc.put_cnt = GNUNET_MIN (mbc.put_cnt, sqms - mbc.skip_cnt); if (sc->search_request_map_offset < sqms) GNUNET_assert (mbc.put_cnt > 0); /* now build message */ msize += sizeof (struct GNUNET_HashCode) * mbc.put_cnt; sm->header.size = htons (msize); sm->type = htonl (GNUNET_BLOCK_TYPE_FS_UBLOCK); sm->anonymity_level = htonl (sc->anonymity); memset (&sm->target, 0, sizeof (struct GNUNET_PeerIdentity)); sm->query = sc->requests[sc->keyword_offset].uquery; GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &build_result_set, &mbc); GNUNET_assert (sqms >= sc->search_request_map_offset); if (sqms != sc->search_request_map_offset) { /* more requesting to be done... */ sm->options = htonl (options | SEARCH_MESSAGE_OPTION_CONTINUED); schedule_transmit_search_request (sc); return msize; } sm->options = htonl (options); sc->keyword_offset++; if (sc->uri->data.ksk.keywordCount != sc->keyword_offset) { /* more requesting to be done... */ schedule_transmit_search_request (sc); return msize; } } else { GNUNET_assert (GNUNET_FS_uri_test_sks (sc->uri)); msize = sizeof (struct SearchMessage); GNUNET_assert (size >= msize); sm->type = htonl (GNUNET_BLOCK_TYPE_FS_UBLOCK); sm->anonymity_level = htonl (sc->anonymity); memset (&sm->target, 0, sizeof (struct GNUNET_PeerIdentity)); GNUNET_CRYPTO_ecdsa_public_key_derive (&sc->uri->data.sks.ns, sc->uri->data.sks.identifier, "fs-ublock", &dpub); GNUNET_CRYPTO_hash (&dpub, sizeof (dpub), &sm->query); mbc.put_cnt = (size - msize) / sizeof (struct GNUNET_HashCode); sqms = GNUNET_CONTAINER_multihashmap_size (sc->master_result_map); mbc.put_cnt = GNUNET_MIN (mbc.put_cnt, sqms - mbc.skip_cnt); mbc.keyword_offset = 0; if (sc->search_request_map_offset < sqms) GNUNET_assert (mbc.put_cnt > 0); msize += sizeof (struct GNUNET_HashCode) * mbc.put_cnt; GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &build_result_set, &mbc); sm->header.size = htons (msize); GNUNET_assert (sqms >= sc->search_request_map_offset); if (sqms != sc->search_request_map_offset) { /* more requesting to be done... */ sm->options = htonl (options | SEARCH_MESSAGE_OPTION_CONTINUED); schedule_transmit_search_request (sc); return msize; } sm->options = htonl (options); } GNUNET_CLIENT_receive (sc->client, &receive_results, sc, GNUNET_TIME_UNIT_FOREVER_REL); return msize; } /** * Schedule the transmission of the (next) search request * to the service. * * @param sc context for the search */ static void schedule_transmit_search_request (struct GNUNET_FS_SearchContext *sc) { size_t size; unsigned int sqms; unsigned int fit; size = sizeof (struct SearchMessage); sqms = GNUNET_CONTAINER_multihashmap_size (sc->master_result_map) - sc->search_request_map_offset; fit = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - size) / sizeof (struct GNUNET_HashCode); fit = GNUNET_MIN (fit, sqms); size += sizeof (struct GNUNET_HashCode) * fit; GNUNET_CLIENT_notify_transmit_ready (sc->client, size, GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_NO, &transmit_search_request, sc); } /** * Reconnect to the FS service and transmit * our queries NOW. * * @param cls our search context * @param tc unused */ static void do_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_SearchContext *sc = cls; struct GNUNET_CLIENT_Connection *client; sc->task = GNUNET_SCHEDULER_NO_TASK; client = GNUNET_CLIENT_connect ("fs", sc->h->cfg); if (NULL == client) { try_reconnect (sc); return; } sc->client = client; sc->search_request_map_offset = 0; sc->keyword_offset = 0; schedule_transmit_search_request (sc); } /** * Shutdown any existing connection to the FS * service and try to establish a fresh one * (and then re-transmit our search request). * * @param sc the search to reconnec */ static void try_reconnect (struct GNUNET_FS_SearchContext *sc) { if (NULL != sc->client) { GNUNET_CLIENT_disconnect (sc->client); sc->client = NULL; } sc->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (sc->reconnect_backoff); sc->task = GNUNET_SCHEDULER_add_delayed (sc->reconnect_backoff, &do_reconnect, sc); } /** * Start search for content, internal API. * * @param h handle to the file sharing subsystem * @param uri specifies the search parameters; can be * a KSK URI or an SKS URI. * @param anonymity desired level of anonymity * @param options options for the search * @param cctx initial value for the client context * @param psearch parent search result (for namespace update searches) * @return context that can be used to control the search */ static struct GNUNET_FS_SearchContext * search_start (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, uint32_t anonymity, enum GNUNET_FS_SearchOptions options, void *cctx, struct GNUNET_FS_SearchResult *psearch) { struct GNUNET_FS_SearchContext *sc; struct GNUNET_FS_ProgressInfo pi; sc = GNUNET_new (struct GNUNET_FS_SearchContext); sc->h = h; sc->options = options; sc->uri = GNUNET_FS_uri_dup (uri); sc->anonymity = anonymity; sc->start_time = GNUNET_TIME_absolute_get (); if (NULL != psearch) { sc->psearch_result = psearch; psearch->update_search = sc; } sc->master_result_map = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO); sc->client_info = cctx; if (GNUNET_OK != GNUNET_FS_search_start_searching_ (sc)) { GNUNET_FS_uri_destroy (sc->uri); GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); GNUNET_free (sc); return NULL; } GNUNET_FS_search_sync_ (sc); pi.status = GNUNET_FS_STATUS_SEARCH_START; sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); return sc; } /** * Build the request and actually initiate the search using the * GNUnet FS service. * * @param sc search context * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) { unsigned int i; const char *keyword; const struct GNUNET_CRYPTO_EcdsaPrivateKey *anon; struct GNUNET_CRYPTO_EcdsaPublicKey anon_pub; struct SearchRequestEntry *sre; GNUNET_assert (NULL == sc->client); if (GNUNET_FS_uri_test_ksk (sc->uri)) { GNUNET_assert (0 != sc->uri->data.ksk.keywordCount); anon = GNUNET_CRYPTO_ecdsa_key_get_anonymous (); GNUNET_CRYPTO_ecdsa_key_get_public (anon, &anon_pub); sc->requests = GNUNET_malloc (sizeof (struct SearchRequestEntry) * sc->uri->data.ksk.keywordCount); for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) { keyword = &sc->uri->data.ksk.keywords[i][1]; sre = &sc->requests[i]; sre->keyword = GNUNET_strdup (keyword); GNUNET_CRYPTO_ecdsa_public_key_derive (&anon_pub, keyword, "fs-ublock", &sre->dpub); GNUNET_CRYPTO_hash (&sre->dpub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &sre->uquery); sre->mandatory = (sc->uri->data.ksk.keywords[i][0] == '+'); if (sre->mandatory) sc->mandatory_count++; sre->results = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); } } sc->client = GNUNET_CLIENT_connect ("fs", sc->h->cfg); if (NULL == sc->client) return GNUNET_SYSERR; schedule_transmit_search_request (sc); return GNUNET_OK; } /** * Freeze probes for the given search result. * * @param cls the global FS handle * @param key the key for the search result (unused) * @param value the search result to free * @return #GNUNET_OK */ static int search_result_freeze_probes (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_FS_SearchResult *sr = value; if (NULL != sr->probe_ctx) { GNUNET_FS_download_stop (sr->probe_ctx, GNUNET_YES); sr->probe_ctx = NULL; } if (GNUNET_SCHEDULER_NO_TASK != sr->probe_ping_task) { GNUNET_SCHEDULER_cancel (sr->probe_ping_task); sr->probe_ping_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != sr->probe_cancel_task) { GNUNET_SCHEDULER_cancel (sr->probe_cancel_task); sr->probe_cancel_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sr->update_search) GNUNET_FS_search_pause (sr->update_search); return GNUNET_OK; } /** * Resume probes for the given search result. * * @param cls the global FS handle * @param key the key for the search result (unused) * @param value the search result to free * @return #GNUNET_OK */ static int search_result_resume_probes (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GNUNET_FS_SearchResult *sr = value; GNUNET_FS_search_start_probe_ (sr); if (NULL != sr->update_search) GNUNET_FS_search_continue (sr->update_search); return GNUNET_OK; } /** * Signal suspend and free the given search result. * * @param cls the global FS handle * @param key the key for the search result (unused) * @param value the search result to free * @return #GNUNET_OK */ static int search_result_suspend (void *cls, const struct GNUNET_HashCode * key, void *value) { struct GNUNET_FS_SearchContext *sc = cls; struct GNUNET_FS_SearchResult *sr = value; struct GNUNET_FS_ProgressInfo pi; if (NULL != sr->download) { GNUNET_FS_download_signal_suspend_ (sr->download); sr->download = NULL; } if (NULL != sr->update_search) { GNUNET_FS_search_signal_suspend_ (sr->update_search); sr->update_search = NULL; } GNUNET_FS_search_stop_probe_ (sr); pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_SUSPEND; pi.value.search.specifics.result_suspend.cctx = sr->client_info; pi.value.search.specifics.result_suspend.meta = sr->meta; pi.value.search.specifics.result_suspend.uri = sr->uri; sr->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); GNUNET_break (NULL == sr->client_info); GNUNET_free_non_null (sr->serialization); GNUNET_FS_uri_destroy (sr->uri); GNUNET_CONTAINER_meta_data_destroy (sr->meta); GNUNET_free_non_null (sr->keyword_bitmap); GNUNET_free (sr); return GNUNET_OK; } /** * Create SUSPEND event for the given search operation * and then clean up our state (without stop signal). * * @param cls the `struct GNUNET_FS_SearchContext` to signal for */ void GNUNET_FS_search_signal_suspend_ (void *cls) { struct GNUNET_FS_SearchContext *sc = cls; struct GNUNET_FS_ProgressInfo pi; unsigned int i; GNUNET_FS_end_top (sc->h, sc->top); GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &search_result_suspend, sc); pi.status = GNUNET_FS_STATUS_SEARCH_SUSPEND; sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); GNUNET_break (NULL == sc->client_info); if (sc->task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (sc->task); sc->task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sc->client) { GNUNET_CLIENT_disconnect (sc->client); sc->client = NULL; } GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); if (NULL != sc->requests) { GNUNET_assert (GNUNET_FS_uri_test_ksk (sc->uri)); for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) { GNUNET_CONTAINER_multihashmap_destroy (sc->requests[i].results); GNUNET_free (sc->requests[i].keyword); } } GNUNET_free_non_null (sc->requests); GNUNET_free_non_null (sc->emsg); GNUNET_FS_uri_destroy (sc->uri); GNUNET_free_non_null (sc->serialization); GNUNET_free (sc); } /** * Start search for content. * * @param h handle to the file sharing subsystem * @param uri specifies the search parameters; can be * a KSK URI or an SKS URI. * @param anonymity desired level of anonymity * @param options options for the search * @param cctx initial value for the client context * @return context that can be used to control the search */ struct GNUNET_FS_SearchContext * GNUNET_FS_search_start (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *uri, uint32_t anonymity, enum GNUNET_FS_SearchOptions options, void *cctx) { struct GNUNET_FS_SearchContext *ret; ret = search_start (h, uri, anonymity, options, cctx, NULL); if (NULL == ret) return NULL; ret->top = GNUNET_FS_make_top (h, &GNUNET_FS_search_signal_suspend_, ret); return ret; } /** * Pause search. * * @param sc context for the search that should be paused */ void GNUNET_FS_search_pause (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_FS_ProgressInfo pi; if (GNUNET_SCHEDULER_NO_TASK != sc->task) { GNUNET_SCHEDULER_cancel (sc->task); sc->task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sc->client) GNUNET_CLIENT_disconnect (sc->client); sc->client = NULL; GNUNET_FS_search_sync_ (sc); GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &search_result_freeze_probes, sc); pi.status = GNUNET_FS_STATUS_SEARCH_PAUSED; sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); } /** * Continue paused search. * * @param sc context for the search that should be resumed */ void GNUNET_FS_search_continue (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_FS_ProgressInfo pi; GNUNET_assert (NULL == sc->client); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sc->task); do_reconnect (sc, NULL); GNUNET_FS_search_sync_ (sc); pi.status = GNUNET_FS_STATUS_SEARCH_CONTINUED; sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &search_result_resume_probes, sc); } /** * Signal stop for the given search result. * * @param cls the global FS handle * @param key the key for the search result (unused) * @param value the search result to free * @return #GNUNET_OK */ static int search_result_stop (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_FS_SearchContext *sc = cls; struct GNUNET_FS_SearchResult *sr = value; struct GNUNET_FS_ProgressInfo pi; GNUNET_FS_search_stop_probe_ (sr); if (NULL != sr->download) { sr->download->search = NULL; sr->download->top = GNUNET_FS_make_top (sr->download->h, &GNUNET_FS_download_signal_suspend_, sr->download); if (NULL != sr->download->serialization) { GNUNET_FS_remove_sync_file_ (sc->h, GNUNET_FS_SYNC_PATH_CHILD_DOWNLOAD, sr->download->serialization); GNUNET_free (sr->download->serialization); sr->download->serialization = NULL; } pi.status = GNUNET_FS_STATUS_DOWNLOAD_LOST_PARENT; GNUNET_FS_download_make_status_ (&pi, sr->download); GNUNET_FS_download_sync_ (sr->download); sr->download = NULL; } pi.status = GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED; pi.value.search.specifics.result_stopped.cctx = sr->client_info; pi.value.search.specifics.result_stopped.meta = sr->meta; pi.value.search.specifics.result_stopped.uri = sr->uri; sr->client_info = GNUNET_FS_search_make_status_ (&pi, sr->h, sc); return GNUNET_OK; } /** * Free the given search result. * * @param cls the global FS handle * @param key the key for the search result (unused) * @param value the search result to free * @return #GNUNET_OK */ static int search_result_free (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_FS_SearchResult *sr = value; if (NULL != sr->update_search) { GNUNET_FS_search_stop (sr->update_search); GNUNET_assert (NULL == sr->update_search); } GNUNET_break (NULL == sr->probe_ctx); GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sr->probe_cancel_task); GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sr->probe_ping_task); GNUNET_break (NULL == sr->client_info); GNUNET_free_non_null (sr->serialization); GNUNET_FS_uri_destroy (sr->uri); GNUNET_CONTAINER_meta_data_destroy (sr->meta); GNUNET_free_non_null (sr->keyword_bitmap); GNUNET_free (sr); return GNUNET_OK; } /** * Stop search for content. * * @param sc context for the search that should be stopped */ void GNUNET_FS_search_stop (struct GNUNET_FS_SearchContext *sc) { struct GNUNET_FS_ProgressInfo pi; unsigned int i; if (NULL != sc->top) GNUNET_FS_end_top (sc->h, sc->top); GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &search_result_stop, sc); if (NULL != sc->psearch_result) sc->psearch_result->update_search = NULL; if (NULL != sc->serialization) { GNUNET_FS_remove_sync_file_ (sc->h, (sc->psearch_result != NULL) ? GNUNET_FS_SYNC_PATH_CHILD_SEARCH : GNUNET_FS_SYNC_PATH_MASTER_SEARCH, sc->serialization); GNUNET_FS_remove_sync_dir_ (sc->h, (sc->psearch_result != NULL) ? GNUNET_FS_SYNC_PATH_CHILD_SEARCH : GNUNET_FS_SYNC_PATH_MASTER_SEARCH, sc->serialization); GNUNET_free (sc->serialization); } pi.status = GNUNET_FS_STATUS_SEARCH_STOPPED; sc->client_info = GNUNET_FS_search_make_status_ (&pi, sc->h, sc); GNUNET_break (NULL == sc->client_info); if (GNUNET_SCHEDULER_NO_TASK != sc->task) GNUNET_SCHEDULER_cancel (sc->task); if (NULL != sc->client) GNUNET_CLIENT_disconnect (sc->client); GNUNET_CONTAINER_multihashmap_iterate (sc->master_result_map, &search_result_free, sc); GNUNET_CONTAINER_multihashmap_destroy (sc->master_result_map); if (NULL != sc->requests) { GNUNET_assert (GNUNET_FS_uri_test_ksk (sc->uri)); for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) GNUNET_CONTAINER_multihashmap_destroy (sc->requests[i].results); } GNUNET_free_non_null (sc->requests); GNUNET_free_non_null (sc->emsg); GNUNET_FS_uri_destroy (sc->uri); GNUNET_free (sc); } /* end of fs_search.c */ gnunet-0.10.1/src/fs/test_fs_publish_data.conf0000644000175000017500000000021312225230043016233 00000000000000@INLINE@ test_fs_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-fs-publish/ [transport] PLUGINS = [fs] ACTIVEMIGRATION = NO gnunet-0.10.1/src/fs/gnunet-service-fs_pr.c0000644000175000017500000016315312255010511015423 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_pr.c * @brief API to handle pending requests * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_load_lib.h" #include "gnunet-service-fs.h" #include "gnunet-service-fs_cp.h" #include "gnunet-service-fs_indexing.h" #include "gnunet-service-fs_pe.h" #include "gnunet-service-fs_pr.h" #include "gnunet-service-fs_mesh.h" /** * Desired replication level for GETs. */ #define DHT_GET_REPLICATION 5 /** * Maximum size of the datastore queue for P2P operations. Needs to * be large enough to queue MAX_QUEUE_PER_PEER operations for roughly * the number of active (connected) peers. */ #define MAX_DATASTORE_QUEUE (16 * MAX_QUEUE_PER_PEER) /** * Bandwidth value of a 0-priority content (must be fairly high * compared to query since content is typically significantly larger * -- and more valueable since it can take many queries to get one * piece of content). */ #define CONTENT_BANDWIDTH_VALUE 800 /** * Hard limit on the number of results we may get from the datastore per query. */ #define MAX_RESULTS (100 * 1024) /** * Collect an instane number of statistics? May cause excessive IPC. */ #define INSANE_STATISTICS GNUNET_NO /** * If obtaining a block via mesh fails, how often do we retry it before * giving up for good (and sticking to non-anonymous transfer)? */ #define MESH_RETRY_MAX 3 /** * An active request. */ struct GSF_PendingRequest { /** * Public data for the request. */ struct GSF_PendingRequestData public_data; /** * Function to call if we encounter a reply. */ GSF_PendingRequestReplyHandler rh; /** * Closure for @e rh */ void *rh_cls; /** * Array of hash codes of replies we've already seen. */ struct GNUNET_HashCode *replies_seen; /** * Bloomfilter masking replies we've already seen. */ struct GNUNET_CONTAINER_BloomFilter *bf; /** * Entry for this pending request in the expiration heap, or NULL. */ struct GNUNET_CONTAINER_HeapNode *hnode; /** * Datastore queue entry for this request (or NULL for none). */ struct GNUNET_DATASTORE_QueueEntry *qe; /** * DHT request handle for this request (or NULL for none). */ struct GNUNET_DHT_GetHandle *gh; /** * Mesh request handle for this request (or NULL for none). */ struct GSF_MeshRequest *mesh_request; /** * Function to call upon completion of the local get * request, or NULL for none. */ GSF_LocalLookupContinuation llc_cont; /** * Closure for llc_cont. */ void *llc_cont_cls; /** * Last result from the local datastore lookup evaluation. */ enum GNUNET_BLOCK_EvaluationResult local_result; /** * Identity of the peer that we should use for the 'sender' * (recipient of the response) when forwarding (0 for none). */ GNUNET_PEER_Id sender_pid; /** * Identity of the peer that we should never forward this query * to since it originated this query (0 for none). */ GNUNET_PEER_Id origin_pid; /** * Time we started the last datastore lookup. */ struct GNUNET_TIME_Absolute qe_start; /** * Task that warns us if the local datastore lookup takes too long. */ GNUNET_SCHEDULER_TaskIdentifier warn_task; /** * Current offset for querying our local datastore for results. * Starts at a random value, incremented until we get the same * UID again (detected using 'first_uid'), which is then used * to termiante the iteration. */ uint64_t local_result_offset; /** * Unique ID of the first result from the local datastore; * used to detect wrap-around of the offset. */ uint64_t first_uid; /** * How often have we retried this request via 'mesh'? * (used to bound overall retries). */ unsigned int mesh_retry_count; /** * Number of valid entries in the 'replies_seen' array. */ unsigned int replies_seen_count; /** * Length of the 'replies_seen' array. */ unsigned int replies_seen_size; /** * Mingle value we currently use for the bf. */ uint32_t mingle; /** * Do we have a first UID yet? */ unsigned int have_first_uid; }; /** * All pending requests, ordered by the query. Entries * are of type 'struct GSF_PendingRequest*'. */ static struct GNUNET_CONTAINER_MultiHashMap *pr_map; /** * Datastore 'PUT' load tracking. */ static struct GNUNET_LOAD_Value *datastore_put_load; /** * Are we allowed to migrate content to this peer. */ static int active_to_migration; /** * Heap with the request that will expire next at the top. Contains * pointers of type "struct PendingRequest*"; these will *also* be * aliased from the "requests_by_peer" data structures and the * "requests_by_query" table. Note that requests from our clients * don't expire and are thus NOT in the "requests_by_expiration" * (or the "requests_by_peer" tables). */ static struct GNUNET_CONTAINER_Heap *requests_by_expiration_heap; /** * Maximum number of requests (from other peers, overall) that we're * willing to have pending at any given point in time. Can be changed * via the configuration file (32k is just the default). */ static unsigned long long max_pending_requests = (32 * 1024); /** * Recalculate our bloom filter for filtering replies. This function * will create a new bloom filter from scratch, so it should only be * called if we have no bloomfilter at all (and hence can create a * fresh one of minimal size without problems) OR if our peer is the * initiator (in which case we may resize to larger than mimimum size). * * @param pr request for which the BF is to be recomputed */ static void refresh_bloomfilter (struct GSF_PendingRequest *pr) { if (pr->bf != NULL) GNUNET_CONTAINER_bloomfilter_free (pr->bf); pr->mingle = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); pr->bf = GNUNET_BLOCK_construct_bloomfilter (pr->mingle, pr->replies_seen, pr->replies_seen_count); } /** * Create a new pending request. * * @param options request options * @param type type of the block that is being requested * @param query key for the lookup * @param target preferred target for the request, NULL for none * @param bf_data raw data for bloom filter for known replies, can be NULL * @param bf_size number of bytes in @a bf_data * @param mingle mingle value for bf * @param anonymity_level desired anonymity level * @param priority maximum outgoing cummulative request priority to use * @param ttl current time-to-live for the request * @param sender_pid peer ID to use for the sender when forwarding, 0 for none * @param origin_pid peer ID of origin of query (do not loop back) * @param replies_seen hash codes of known local replies * @param replies_seen_count size of the @a replies_seen array * @param rh handle to call when we get a reply * @param rh_cls closure for @a rh * @return handle for the new pending request */ struct GSF_PendingRequest * GSF_pending_request_create_ (enum GSF_PendingRequestOptions options, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *query, const struct GNUNET_PeerIdentity *target, const char *bf_data, size_t bf_size, uint32_t mingle, uint32_t anonymity_level, uint32_t priority, int32_t ttl, GNUNET_PEER_Id sender_pid, GNUNET_PEER_Id origin_pid, const struct GNUNET_HashCode *replies_seen, unsigned int replies_seen_count, GSF_PendingRequestReplyHandler rh, void *rh_cls) { struct GSF_PendingRequest *pr; struct GSF_PendingRequest *dpr; size_t extra; struct GNUNET_HashCode *eptr; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating request handle for `%s' of type %d\n", GNUNET_h2s (query), type); #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Pending requests created"), 1, GNUNET_NO); #endif extra = 0; if (NULL != target) extra += sizeof (struct GNUNET_PeerIdentity); pr = GNUNET_malloc (sizeof (struct GSF_PendingRequest) + extra); pr->local_result_offset = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); pr->public_data.query = *query; eptr = (struct GNUNET_HashCode *) &pr[1]; if (NULL != target) { pr->public_data.target = (struct GNUNET_PeerIdentity *) eptr; memcpy (eptr, target, sizeof (struct GNUNET_PeerIdentity)); } pr->public_data.anonymity_level = anonymity_level; pr->public_data.priority = priority; pr->public_data.original_priority = priority; pr->public_data.options = options; pr->public_data.type = type; pr->public_data.start_time = GNUNET_TIME_absolute_get (); pr->sender_pid = sender_pid; pr->origin_pid = origin_pid; pr->rh = rh; pr->rh_cls = rh_cls; GNUNET_assert ((sender_pid != 0) || (0 == (options & GSF_PRO_FORWARD_ONLY))); if (ttl >= 0) pr->public_data.ttl = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, (uint32_t) ttl)); else pr->public_data.ttl = GNUNET_TIME_absolute_subtract (pr->public_data.start_time, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, (uint32_t) (-ttl))); if (replies_seen_count > 0) { pr->replies_seen_size = replies_seen_count; pr->replies_seen = GNUNET_malloc (sizeof (struct GNUNET_HashCode) * pr->replies_seen_size); memcpy (pr->replies_seen, replies_seen, replies_seen_count * sizeof (struct GNUNET_HashCode)); pr->replies_seen_count = replies_seen_count; } if (NULL != bf_data) { pr->bf = GNUNET_CONTAINER_bloomfilter_init (bf_data, bf_size, GNUNET_CONSTANTS_BLOOMFILTER_K); pr->mingle = mingle; } else if ((replies_seen_count > 0) && (0 != (options & GSF_PRO_BLOOMFILTER_FULL_REFRESH))) { refresh_bloomfilter (pr); } GNUNET_CONTAINER_multihashmap_put (pr_map, &pr->public_data.query, pr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); if (0 == (options & GSF_PRO_REQUEST_NEVER_EXPIRES)) { pr->hnode = GNUNET_CONTAINER_heap_insert (requests_by_expiration_heap, pr, pr->public_data.ttl.abs_value_us); /* make sure we don't track too many requests */ while (GNUNET_CONTAINER_heap_get_size (requests_by_expiration_heap) > max_pending_requests) { dpr = GNUNET_CONTAINER_heap_peek (requests_by_expiration_heap); GNUNET_assert (dpr != NULL); if (pr == dpr) break; /* let the request live briefly... */ if (NULL != dpr->rh) dpr->rh (dpr->rh_cls, GNUNET_BLOCK_EVALUATION_REQUEST_VALID, dpr, UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_BLOCK_TYPE_ANY, NULL, 0); GSF_pending_request_cancel_ (dpr, GNUNET_YES); } } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Pending requests active"), 1, GNUNET_NO); return pr; } /** * Obtain the public data associated with a pending request * * @param pr pending request * @return associated public data */ struct GSF_PendingRequestData * GSF_pending_request_get_data_ (struct GSF_PendingRequest *pr) { return &pr->public_data; } /** * Test if two pending requests are compatible (would generate * the same query modulo filters and should thus be processed * jointly). * * @param pra a pending request * @param prb another pending request * @return #GNUNET_OK if the requests are compatible */ int GSF_pending_request_is_compatible_ (struct GSF_PendingRequest *pra, struct GSF_PendingRequest *prb) { if ((pra->public_data.type != prb->public_data.type) || (0 != memcmp (&pra->public_data.query, &prb->public_data.query, sizeof (struct GNUNET_HashCode)))) return GNUNET_NO; return GNUNET_OK; } /** * Update a given pending request with additional replies * that have been seen. * * @param pr request to update * @param replies_seen hash codes of replies that we've seen * @param replies_seen_count size of the replies_seen array */ void GSF_pending_request_update_ (struct GSF_PendingRequest *pr, const struct GNUNET_HashCode * replies_seen, unsigned int replies_seen_count) { unsigned int i; struct GNUNET_HashCode mhash; if (replies_seen_count + pr->replies_seen_count < pr->replies_seen_count) return; /* integer overflow */ if (0 != (pr->public_data.options & GSF_PRO_BLOOMFILTER_FULL_REFRESH)) { /* we're responsible for the BF, full refresh */ if (replies_seen_count + pr->replies_seen_count > pr->replies_seen_size) GNUNET_array_grow (pr->replies_seen, pr->replies_seen_size, replies_seen_count + pr->replies_seen_count); memcpy (&pr->replies_seen[pr->replies_seen_count], replies_seen, sizeof (struct GNUNET_HashCode) * replies_seen_count); pr->replies_seen_count += replies_seen_count; refresh_bloomfilter (pr); } else { if (NULL == pr->bf) { /* we're not the initiator, but the initiator did not give us * any bloom-filter, so we need to create one on-the-fly */ pr->mingle = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); pr->bf = GNUNET_BLOCK_construct_bloomfilter (pr->mingle, replies_seen, replies_seen_count); } else { for (i = 0; i < pr->replies_seen_count; i++) { GNUNET_BLOCK_mingle_hash (&replies_seen[i], pr->mingle, &mhash); GNUNET_CONTAINER_bloomfilter_add (pr->bf, &mhash); } } } if (NULL != pr->gh) GNUNET_DHT_get_filter_known_results (pr->gh, replies_seen_count, replies_seen); } /** * Generate the message corresponding to the given pending request for * transmission to other peers (or at least determine its size). * * @param pr request to generate the message for * @param buf_size number of bytes available in @a buf * @param buf where to copy the message (can be NULL) * @return number of bytes needed (if `>` @a buf_size) or used */ size_t GSF_pending_request_get_message_ (struct GSF_PendingRequest *pr, size_t buf_size, void *buf) { char lbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE]; struct GetMessage *gm; struct GNUNET_PeerIdentity *ext; size_t msize; unsigned int k; uint32_t bm; uint32_t prio; size_t bf_size; struct GNUNET_TIME_Absolute now; int64_t ttl; int do_route; if (buf_size > 0) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Building request message for `%s' of type %d\n", GNUNET_h2s (&pr->public_data.query), pr->public_data.type); k = 0; bm = 0; do_route = (0 == (pr->public_data.options & GSF_PRO_FORWARD_ONLY)); if ((!do_route) && (pr->sender_pid == 0)) { GNUNET_break (0); do_route = GNUNET_YES; } if (!do_route) { bm |= GET_MESSAGE_BIT_RETURN_TO; k++; } if (NULL != pr->public_data.target) { bm |= GET_MESSAGE_BIT_TRANSMIT_TO; k++; } bf_size = GNUNET_CONTAINER_bloomfilter_get_size (pr->bf); msize = sizeof (struct GetMessage) + bf_size + k * sizeof (struct GNUNET_PeerIdentity); GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); if (buf_size < msize) return msize; gm = (struct GetMessage *) lbuf; gm->header.type = htons (GNUNET_MESSAGE_TYPE_FS_GET); gm->header.size = htons (msize); gm->type = htonl (pr->public_data.type); if (do_route) prio = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pr->public_data.priority + 1); else prio = 0; pr->public_data.priority -= prio; pr->public_data.num_transmissions++; pr->public_data.respect_offered += prio; gm->priority = htonl (prio); now = GNUNET_TIME_absolute_get (); ttl = (int64_t) (pr->public_data.ttl.abs_value_us - now.abs_value_us); gm->ttl = htonl (ttl / 1000LL / 1000LL); gm->filter_mutator = htonl (pr->mingle); gm->hash_bitmap = htonl (bm); gm->query = pr->public_data.query; ext = (struct GNUNET_PeerIdentity *) &gm[1]; k = 0; if (!do_route) GNUNET_PEER_resolve (pr->sender_pid, &ext[k++]); if (NULL != pr->public_data.target) ext[k++] = *pr->public_data.target; if (NULL != pr->bf) GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_bloomfilter_get_raw_data (pr->bf, (char *) &ext[k], bf_size)); memcpy (buf, gm, msize); return msize; } /** * Iterator to free pending requests. * * @param cls closure, unused * @param key current key code * @param value value in the hash map (pending request) * @return #GNUNET_YES (we should continue to iterate) */ static int clean_request (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GSF_PendingRequest *pr = value; GSF_LocalLookupContinuation cont; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up pending request for `%s'.\n", GNUNET_h2s (key)); if (NULL != pr->mesh_request) { pr->mesh_retry_count = MESH_RETRY_MAX; GSF_mesh_query_cancel (pr->mesh_request); pr->mesh_request = NULL; } if (NULL != (cont = pr->llc_cont)) { pr->llc_cont = NULL; cont (pr->llc_cont_cls, pr, pr->local_result); } GSF_plan_notify_request_done_ (pr); GNUNET_free_non_null (pr->replies_seen); if (NULL != pr->bf) { GNUNET_CONTAINER_bloomfilter_free (pr->bf); pr->bf = NULL; } GNUNET_PEER_change_rc (pr->sender_pid, -1); pr->sender_pid = 0; GNUNET_PEER_change_rc (pr->origin_pid, -1); pr->origin_pid = 0; if (NULL != pr->hnode) { GNUNET_CONTAINER_heap_remove_node (pr->hnode); pr->hnode = NULL; } if (NULL != pr->qe) { GNUNET_DATASTORE_cancel (pr->qe); pr->qe = NULL; } if (NULL != pr->gh) { GNUNET_DHT_get_stop (pr->gh); pr->gh = NULL; } if (GNUNET_SCHEDULER_NO_TASK != pr->warn_task) { GNUNET_SCHEDULER_cancel (pr->warn_task); pr->warn_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (pr_map, &pr->public_data.query, pr)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Pending requests active"), -1, GNUNET_NO); GNUNET_free (pr); return GNUNET_YES; } /** * Explicitly cancel a pending request. * * @param pr request to cancel * @param full_cleanup fully purge the request */ void GSF_pending_request_cancel_ (struct GSF_PendingRequest *pr, int full_cleanup) { GSF_LocalLookupContinuation cont; if (NULL == pr_map) return; /* already cleaned up! */ if (GNUNET_YES != full_cleanup) { /* make request inactive (we're no longer interested in more results), * but do NOT remove from our data-structures, we still need it there * to prevent the request from looping */ pr->rh = NULL; if (NULL != pr->mesh_request) { pr->mesh_retry_count = MESH_RETRY_MAX; GSF_mesh_query_cancel (pr->mesh_request); pr->mesh_request = NULL; } if (NULL != (cont = pr->llc_cont)) { pr->llc_cont = NULL; cont (pr->llc_cont_cls, pr, pr->local_result); } GSF_plan_notify_request_done_ (pr); if (NULL != pr->qe) { GNUNET_DATASTORE_cancel (pr->qe); pr->qe = NULL; } if (NULL != pr->gh) { GNUNET_DHT_get_stop (pr->gh); pr->gh = NULL; } if (GNUNET_SCHEDULER_NO_TASK != pr->warn_task) { GNUNET_SCHEDULER_cancel (pr->warn_task); pr->warn_task = GNUNET_SCHEDULER_NO_TASK; } return; } GNUNET_assert (GNUNET_YES == clean_request (NULL, &pr->public_data.query, pr)); } /** * Iterate over all pending requests. * * @param it function to call for each request * @param cls closure for it */ void GSF_iterate_pending_requests_ (GSF_PendingRequestIterator it, void *cls) { GNUNET_CONTAINER_multihashmap_iterate (pr_map, (GNUNET_CONTAINER_HashMapIterator) it, cls); } /** * Closure for process_reply() function. */ struct ProcessReplyClosure { /** * The data for the reply. */ const void *data; /** * Who gave us this reply? NULL for local host (or DHT) */ struct GSF_ConnectedPeer *sender; /** * When the reply expires. */ struct GNUNET_TIME_Absolute expiration; /** * Size of data. */ size_t size; /** * Type of the block. */ enum GNUNET_BLOCK_Type type; /** * How much was this reply worth to us? */ uint32_t priority; /** * Anonymity requirements for this reply. */ uint32_t anonymity_level; /** * Evaluation result (returned). */ enum GNUNET_BLOCK_EvaluationResult eval; /** * Did we find a matching request? */ int request_found; }; /** * Update the performance data for the sender (if any) since * the sender successfully answered one of our queries. * * @param prq information about the sender * @param pr request that was satisfied */ static void update_request_performance_data (struct ProcessReplyClosure *prq, struct GSF_PendingRequest *pr) { if (prq->sender == NULL) return; GSF_peer_update_performance_ (prq->sender, pr->public_data.start_time, prq->priority); } /** * We have received a reply; handle it! * * @param cls response (struct ProcessReplyClosure) * @param key our query * @param value value in the hash map (info about the query) * @return #GNUNET_YES (we should continue to iterate) */ static int process_reply (void *cls, const struct GNUNET_HashCode *key, void *value) { struct ProcessReplyClosure *prq = cls; struct GSF_PendingRequest *pr = value; struct GNUNET_HashCode chash; struct GNUNET_TIME_Absolute last_transmission; if (NULL == pr->rh) return GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Matched result (type %u) for query `%s' with pending request\n", (unsigned int) prq->type, GNUNET_h2s (key)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# replies received and matched"), 1, GNUNET_NO); prq->eval = GNUNET_BLOCK_evaluate (GSF_block_ctx, prq->type, key, &pr->bf, pr->mingle, NULL, 0, prq->data, prq->size); switch (prq->eval) { case GNUNET_BLOCK_EVALUATION_OK_MORE: update_request_performance_data (prq, pr); break; case GNUNET_BLOCK_EVALUATION_OK_LAST: /* short cut: stop processing early, no BF-update, etc. */ update_request_performance_data (prq, pr); GNUNET_LOAD_update (GSF_rt_entry_lifetime, GNUNET_TIME_absolute_get_duration (pr-> public_data.start_time).rel_value_us); if (GNUNET_YES != GSF_request_plan_reference_get_last_transmission_ (pr->public_data.pr_head, prq->sender, &last_transmission)) last_transmission.abs_value_us = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; /* pass on to other peers / local clients */ pr->rh (pr->rh_cls, prq->eval, pr, prq->anonymity_level, prq->expiration, last_transmission, prq->type, prq->data, prq->size); return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# duplicate replies discarded (bloomfilter)"), 1, GNUNET_NO); #endif GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Duplicate response, discarding.\n"); return GNUNET_YES; /* duplicate */ case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# irrelevant replies discarded"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Irrelevant response, ignoring.\n"); return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: return GNUNET_YES; /* wrong namespace */ case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: GNUNET_break (0); return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: GNUNET_break (0); return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported block type %u\n"), prq->type); return GNUNET_NO; } /* update bloomfilter */ GNUNET_CRYPTO_hash (prq->data, prq->size, &chash); GSF_pending_request_update_ (pr, &chash, 1); if (NULL == prq->sender) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found result for query `%s' in local datastore\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# results found locally"), 1, GNUNET_NO); } else { GSF_dht_lookup_ (pr); } prq->priority += pr->public_data.original_priority; pr->public_data.priority = 0; pr->public_data.original_priority = 0; pr->public_data.results_found++; prq->request_found = GNUNET_YES; /* finally, pass on to other peer / local client */ if (! GSF_request_plan_reference_get_last_transmission_ (pr->public_data.pr_head, prq->sender, &last_transmission)) last_transmission.abs_value_us = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; pr->rh (pr->rh_cls, prq->eval, pr, prq->anonymity_level, prq->expiration, last_transmission, prq->type, prq->data, prq->size); return GNUNET_YES; } /** * Context for put_migration_continuation(). */ struct PutMigrationContext { /** * Start time for the operation. */ struct GNUNET_TIME_Absolute start; /** * Request origin. */ struct GNUNET_PeerIdentity origin; /** * GNUNET_YES if we had a matching request for this block, * GNUNET_NO if not. */ int requested; }; /** * Continuation called to notify client about result of the * operation. * * @param cls closure * @param success #GNUNET_SYSERR on failure * @param min_expiration minimum expiration time required for content to be stored * @param msg NULL on success, otherwise an error message */ static void put_migration_continuation (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct PutMigrationContext *pmc = cls; struct GSF_ConnectedPeer *cp; struct GNUNET_TIME_Relative mig_pause; struct GSF_PeerPerformanceData *ppd; if (NULL != datastore_put_load) { if (GNUNET_SYSERR != success) { GNUNET_LOAD_update (datastore_put_load, GNUNET_TIME_absolute_get_duration (pmc->start).rel_value_us); } else { /* on queue failure / timeout, increase the put load dramatically */ GNUNET_LOAD_update (datastore_put_load, GNUNET_TIME_UNIT_MINUTES.rel_value_us); } } cp = GSF_peer_get_ (&pmc->origin); if (GNUNET_OK == success) { if (NULL != cp) { ppd = GSF_get_peer_performance_data_ (cp); ppd->migration_delay.rel_value_us /= 2; } GNUNET_free (pmc); return; } if ( (GNUNET_NO == success) && (GNUNET_NO == pmc->requested) && (NULL != cp) ) { ppd = GSF_get_peer_performance_data_ (cp); if (min_expiration.abs_value_us > 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking to stop migration for %s because datastore is full\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (min_expiration), GNUNET_YES)); GSF_block_peer_migration_ (cp, min_expiration); } else { ppd->migration_delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_SECONDS, ppd->migration_delay); ppd->migration_delay = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_HOURS, ppd->migration_delay); mig_pause.rel_value_us = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, ppd->migration_delay.rel_value_us); ppd->migration_delay = GNUNET_TIME_relative_multiply (ppd->migration_delay, 2); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Replicated content already exists locally, asking to stop migration for %s\n", GNUNET_STRINGS_relative_time_to_string (mig_pause, GNUNET_YES)); GSF_block_peer_migration_ (cp, GNUNET_TIME_relative_to_absolute (mig_pause)); } } GNUNET_free (pmc); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore `PUT' failures"), 1, GNUNET_NO); } /** * Test if the DATABASE (PUT) load on this peer is too high * to even consider processing the query at * all. * * @param priority the priority of the item * @return #GNUNET_YES if the load is too high to do anything (load high) * #GNUNET_NO to process normally (load normal or low) */ static int test_put_load_too_high (uint32_t priority) { double ld; if (NULL == datastore_put_load) return GNUNET_NO; if (GNUNET_LOAD_get_average (datastore_put_load) < 50) return GNUNET_NO; /* very fast */ ld = GNUNET_LOAD_get_load (datastore_put_load); if (ld < 2.0 * (1 + priority)) return GNUNET_NO; GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# storage requests dropped due to high load"), 1, GNUNET_NO); return GNUNET_YES; } /** * Iterator called on each result obtained for a DHT * operation that expects a reply * * @param cls closure * @param exp when will this value expire * @param key key of the result * @param get_path peers on reply path (or NULL if not recorded) * @param get_path_length number of entries in @a get_path * @param put_path peers on the PUT path (or NULL if not recorded) * @param put_path_length number of entries in @a get_path * @param type type of the result * @param size number of bytes in @a data * @param data pointer to the result data */ static void handle_dht_reply (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { struct GSF_PendingRequest *pr = cls; struct ProcessReplyClosure prq; struct PutMigrationContext *pmc; GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Replies received from DHT"), 1, GNUNET_NO); memset (&prq, 0, sizeof (prq)); prq.data = data; prq.expiration = exp; /* do not allow migrated content to live longer than 1 year */ prq.expiration = GNUNET_TIME_absolute_min (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS), prq.expiration); prq.size = size; prq.type = type; process_reply (&prq, key, pr); if ((GNUNET_YES == active_to_migration) && (GNUNET_NO == test_put_load_too_high (prq.priority))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Replicating result for query `%s' with priority %u\n", GNUNET_h2s (key), prq.priority); pmc = GNUNET_new (struct PutMigrationContext); pmc->start = GNUNET_TIME_absolute_get (); pmc->requested = GNUNET_YES; if (NULL == GNUNET_DATASTORE_put (GSF_dsh, 0, key, size, data, type, prq.priority, 1 /* anonymity */ , 0 /* replication */ , exp, 1 + prq.priority, MAX_DATASTORE_QUEUE, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &put_migration_continuation, pmc)) { put_migration_continuation (pmc, GNUNET_SYSERR, GNUNET_TIME_UNIT_ZERO_ABS, NULL); } } } /** * Consider looking up the data in the DHT (anonymity-level permitting). * * @param pr the pending request to process */ void GSF_dht_lookup_ (struct GSF_PendingRequest *pr) { const void *xquery; size_t xquery_size; struct GNUNET_PeerIdentity pi; char buf[sizeof (struct GNUNET_HashCode) * 2] GNUNET_ALIGN; if (0 != pr->public_data.anonymity_level) return; if (NULL != pr->gh) { GNUNET_DHT_get_stop (pr->gh); pr->gh = NULL; } xquery = NULL; xquery_size = 0; if (0 != (pr->public_data.options & GSF_PRO_FORWARD_ONLY)) { GNUNET_assert (0 != pr->sender_pid); GNUNET_PEER_resolve (pr->sender_pid, &pi); memcpy (&buf[xquery_size], &pi, sizeof (struct GNUNET_PeerIdentity)); xquery_size += sizeof (struct GNUNET_PeerIdentity); } pr->gh = GNUNET_DHT_get_start (GSF_dht, pr->public_data.type, &pr->public_data.query, DHT_GET_REPLICATION, GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, xquery, xquery_size, &handle_dht_reply, pr); if ( (NULL != pr->gh) && (0 != pr->replies_seen_count) ) GNUNET_DHT_get_filter_known_results (pr->gh, pr->replies_seen_count, pr->replies_seen); } /** * Function called with a reply from the mesh. * * @param cls the pending request struct * @param type type of the block, ANY on error * @param expiration expiration time for the block * @param data_size number of bytes in @a data, 0 on error * @param data reply block data, NULL on error */ static void mesh_reply_proc (void *cls, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration, size_t data_size, const void *data) { struct GSF_PendingRequest *pr = cls; struct ProcessReplyClosure prq; struct GNUNET_HashCode query; pr->mesh_request = NULL; if (GNUNET_BLOCK_TYPE_ANY == type) { GNUNET_break (NULL == data); GNUNET_break (0 == data_size); pr->mesh_retry_count++; if (pr->mesh_retry_count >= MESH_RETRY_MAX) return; /* give up on mesh */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error retrieiving block via mesh\n"); /* retry -- without delay, as this is non-anonymous and mesh/mesh connect will take some time anyway */ pr->mesh_request = GSF_mesh_query (pr->public_data.target, &pr->public_data.query, pr->public_data.type, &mesh_reply_proc, pr); return; } if (GNUNET_YES != GNUNET_BLOCK_get_key (GSF_block_ctx, type, data, data_size, &query)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to derive key for block of type %d\n", (int) type); GNUNET_break_op (0); return; } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Replies received from MESH"), 1, GNUNET_NO); memset (&prq, 0, sizeof (prq)); prq.data = data; prq.expiration = expiration; /* do not allow migrated content to live longer than 1 year */ prq.expiration = GNUNET_TIME_absolute_min (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS), prq.expiration); prq.size = data_size; prq.type = type; process_reply (&prq, &query, pr); } /** * Consider downloading via mesh (if possible) * * @param pr the pending request to process */ void GSF_mesh_lookup_ (struct GSF_PendingRequest *pr) { if (0 != pr->public_data.anonymity_level) return; if (0 == pr->public_data.target) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cannot do mesh-based download, target peer not known\n"); return; } if (NULL != pr->mesh_request) return; pr->mesh_request = GSF_mesh_query (pr->public_data.target, &pr->public_data.query, pr->public_data.type, &mesh_reply_proc, pr); } /** * Task that issues a warning if the datastore lookup takes too long. * * @param cls the 'struct GSF_PendingRequest' * @param tc task context */ static void warn_delay_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSF_PendingRequest *pr = cls; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Datastore lookup already took %s!\n"), GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pr->qe_start), GNUNET_YES)); pr->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &warn_delay_task, pr); } /** * Task that issues a warning if the datastore lookup takes too long. * * @param cls the 'struct GSF_PendingRequest' * @param tc task context */ static void odc_warn_delay_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSF_PendingRequest *pr = cls; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("On-demand lookup already took %s!\n"), GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pr->qe_start), GNUNET_YES)); pr->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &odc_warn_delay_task, pr); } /** * We're processing (local) results for a search request * from another peer. Pass applicable results to the * peer and if we are done either clean up (operation * complete) or forward to other peers (more results possible). * * @param cls our closure (struct PendingRequest) * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ static void process_local_reply (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct GSF_PendingRequest *pr = cls; GSF_LocalLookupContinuation cont; struct ProcessReplyClosure prq; struct GNUNET_HashCode query; unsigned int old_rf; GNUNET_SCHEDULER_cancel (pr->warn_task); pr->warn_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != pr->qe) { pr->qe = NULL; if (NULL == key) { #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups concluded (no results)"), 1, GNUNET_NO); #endif } if (GNUNET_NO == pr->have_first_uid) { pr->first_uid = uid; pr->have_first_uid = 1; } else { if ((uid == pr->first_uid) && (key != NULL)) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups concluded (seen all)"), 1, GNUNET_NO); key = NULL; /* all replies seen! */ } pr->have_first_uid++; if ((pr->have_first_uid > MAX_RESULTS) && (key != NULL)) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups aborted (more than MAX_RESULTS)"), 1, GNUNET_NO); key = NULL; /* all replies seen! */ } } } if (NULL == key) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "No further local responses available.\n"); #if INSANE_STATISTICS if ((pr->public_data.type == GNUNET_BLOCK_TYPE_FS_DBLOCK) || (pr->public_data.type == GNUNET_BLOCK_TYPE_FS_IBLOCK)) GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# requested DBLOCK or IBLOCK not found"), 1, GNUNET_NO); #endif goto check_error_and_continue; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received reply for `%s' of type %d with UID %llu from datastore.\n", GNUNET_h2s (key), type, (unsigned long long) uid); if (type == GNUNET_BLOCK_TYPE_FS_ONDEMAND) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found ONDEMAND block, performing on-demand encoding\n"); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# on-demand blocks matched requests"), 1, GNUNET_NO); pr->qe_start = GNUNET_TIME_absolute_get (); pr->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &odc_warn_delay_task, pr); if (GNUNET_OK == GNUNET_FS_handle_on_demand_block (key, size, data, type, priority, anonymity, expiration, uid, &process_local_reply, pr)) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# on-demand lookups performed successfully"), 1, GNUNET_NO); return; /* we're done */ } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# on-demand lookups failed"), 1, GNUNET_NO); GNUNET_SCHEDULER_cancel (pr->warn_task); pr->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &warn_delay_task, pr); pr->qe = GNUNET_DATASTORE_get_key (GSF_dsh, pr->local_result_offset - 1, &pr->public_data.query, pr->public_data.type == GNUNET_BLOCK_TYPE_FS_DBLOCK ? GNUNET_BLOCK_TYPE_ANY : pr->public_data.type, (0 != (GSF_PRO_PRIORITY_UNLIMITED & pr->public_data.options)) ? UINT_MAX : 1 /* queue priority */ , (0 != (GSF_PRO_PRIORITY_UNLIMITED & pr->public_data.options)) ? UINT_MAX : GSF_datastore_queue_size /* max queue size */ , GNUNET_TIME_UNIT_FOREVER_REL, &process_local_reply, pr); if (NULL != pr->qe) return; /* we're done */ GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups concluded (error queueing)"), 1, GNUNET_NO); goto check_error_and_continue; } old_rf = pr->public_data.results_found; memset (&prq, 0, sizeof (prq)); prq.data = data; prq.expiration = expiration; prq.size = size; if (GNUNET_OK != GNUNET_BLOCK_get_key (GSF_block_ctx, type, data, size, &query)) { GNUNET_break (0); GNUNET_DATASTORE_remove (GSF_dsh, key, size, data, -1, -1, GNUNET_TIME_UNIT_FOREVER_REL, NULL, NULL); pr->qe_start = GNUNET_TIME_absolute_get (); pr->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &warn_delay_task, pr); pr->qe = GNUNET_DATASTORE_get_key (GSF_dsh, pr->local_result_offset - 1, &pr->public_data.query, pr->public_data.type == GNUNET_BLOCK_TYPE_FS_DBLOCK ? GNUNET_BLOCK_TYPE_ANY : pr->public_data.type, (0 != (GSF_PRO_PRIORITY_UNLIMITED & pr->public_data.options)) ? UINT_MAX : 1 /* queue priority */ , (0 != (GSF_PRO_PRIORITY_UNLIMITED & pr->public_data.options)) ? UINT_MAX : GSF_datastore_queue_size /* max queue size */ , GNUNET_TIME_UNIT_FOREVER_REL, &process_local_reply, pr); if (pr->qe == NULL) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups concluded (error queueing)"), 1, GNUNET_NO); goto check_error_and_continue; } return; } prq.type = type; prq.priority = priority; prq.request_found = GNUNET_NO; prq.anonymity_level = anonymity; if ((old_rf == 0) && (pr->public_data.results_found == 0)) GSF_update_datastore_delay_ (pr->public_data.start_time); process_reply (&prq, key, pr); pr->local_result = prq.eval; if (prq.eval == GNUNET_BLOCK_EVALUATION_OK_LAST) { GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups concluded (found last result)"), 1, GNUNET_NO); goto check_error_and_continue; } if ((0 == (GSF_PRO_PRIORITY_UNLIMITED & pr->public_data.options)) && ((GNUNET_YES == GSF_test_get_load_too_high_ (0)) || (pr->public_data.results_found > 5 + 2 * pr->public_data.priority))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Load too high, done with request\n"); GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups concluded (load too high)"), 1, GNUNET_NO); goto check_error_and_continue; } pr->qe_start = GNUNET_TIME_absolute_get (); pr->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &warn_delay_task, pr); pr->qe = GNUNET_DATASTORE_get_key (GSF_dsh, pr->local_result_offset++, &pr->public_data.query, pr->public_data.type == GNUNET_BLOCK_TYPE_FS_DBLOCK ? GNUNET_BLOCK_TYPE_ANY : pr->public_data.type, (0 != (GSF_PRO_PRIORITY_UNLIMITED & pr-> public_data.options)) ? UINT_MAX : 1 /* queue priority */ , (0 != (GSF_PRO_PRIORITY_UNLIMITED & pr-> public_data.options)) ? UINT_MAX : GSF_datastore_queue_size /* max queue size */ , GNUNET_TIME_UNIT_FOREVER_REL, &process_local_reply, pr); /* check if we successfully queued another datastore request; * if so, return, otherwise call our continuation (if we have * any) */ check_error_and_continue: if (NULL != pr->qe) return; if (GNUNET_SCHEDULER_NO_TASK != pr->warn_task) { GNUNET_SCHEDULER_cancel (pr->warn_task); pr->warn_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL == (cont = pr->llc_cont)) return; /* no continuation */ pr->llc_cont = NULL; cont (pr->llc_cont_cls, pr, pr->local_result); } /** * Is the given target a legitimate peer for forwarding the given request? * * @param pr request * @param target * @return GNUNET_YES if this request could be forwarded to the given peer */ int GSF_pending_request_test_target_ (struct GSF_PendingRequest *pr, const struct GNUNET_PeerIdentity *target) { struct GNUNET_PeerIdentity pi; if (0 == pr->origin_pid) return GNUNET_YES; GNUNET_PEER_resolve (pr->origin_pid, &pi); return (0 == memcmp (&pi, target, sizeof (struct GNUNET_PeerIdentity))) ? GNUNET_NO : GNUNET_YES; } /** * Look up the request in the local datastore. * * @param pr the pending request to process * @param cont function to call at the end * @param cont_cls closure for cont */ void GSF_local_lookup_ (struct GSF_PendingRequest *pr, GSF_LocalLookupContinuation cont, void *cont_cls) { GNUNET_assert (NULL == pr->gh); GNUNET_assert (NULL == pr->mesh_request); GNUNET_assert (NULL == pr->llc_cont); pr->llc_cont = cont; pr->llc_cont_cls = cont_cls; pr->qe_start = GNUNET_TIME_absolute_get (); pr->warn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &warn_delay_task, pr); #if INSANE_STATISTICS GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups initiated"), 1, GNUNET_NO); #endif pr->qe = GNUNET_DATASTORE_get_key (GSF_dsh, pr->local_result_offset++, &pr->public_data.query, pr->public_data.type == GNUNET_BLOCK_TYPE_FS_DBLOCK ? GNUNET_BLOCK_TYPE_ANY : pr->public_data.type, (0 != (GSF_PRO_PRIORITY_UNLIMITED & pr-> public_data.options)) ? UINT_MAX : 1 /* queue priority */ , (0 != (GSF_PRO_PRIORITY_UNLIMITED & pr-> public_data.options)) ? UINT_MAX : GSF_datastore_queue_size /* max queue size */ , GNUNET_TIME_UNIT_FOREVER_REL, &process_local_reply, pr); if (NULL != pr->qe) return; GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# Datastore lookups concluded (error queueing)"), 1, GNUNET_NO); GNUNET_SCHEDULER_cancel (pr->warn_task); pr->warn_task = GNUNET_SCHEDULER_NO_TASK; pr->llc_cont = NULL; if (NULL != cont) cont (cont_cls, pr, pr->local_result); } /** * Handle P2P "CONTENT" message. Checks that the message is * well-formed and then checks if there are any pending requests for * this content and possibly passes it on (to local clients or other * peers). Does NOT perform migration (content caching at this peer). * * @param cp the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message * @return GNUNET_OK if the message was well-formed, * GNUNET_SYSERR if the message was malformed (close connection, * do not cache under any circumstances) */ int GSF_handle_p2p_content_ (struct GSF_ConnectedPeer *cp, const struct GNUNET_MessageHeader *message) { const struct PutMessage *put; uint16_t msize; size_t dsize; enum GNUNET_BLOCK_Type type; struct GNUNET_TIME_Absolute expiration; struct GNUNET_HashCode query; struct ProcessReplyClosure prq; struct GNUNET_TIME_Relative block_time; double putl; struct PutMigrationContext *pmc; msize = ntohs (message->size); if (msize < sizeof (struct PutMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } put = (const struct PutMessage *) message; dsize = msize - sizeof (struct PutMessage); type = ntohl (put->type); expiration = GNUNET_TIME_absolute_ntoh (put->expiration); /* do not allow migrated content to live longer than 1 year */ expiration = GNUNET_TIME_absolute_min (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS), expiration); if (type == GNUNET_BLOCK_TYPE_FS_ONDEMAND) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_BLOCK_get_key (GSF_block_ctx, type, &put[1], dsize, &query)) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (GSF_stats, gettext_noop ("# GAP PUT messages received"), 1, GNUNET_NO); /* now, lookup 'query' */ prq.data = (const void *) &put[1]; prq.sender = cp; prq.size = dsize; prq.type = type; prq.expiration = expiration; prq.priority = 0; prq.anonymity_level = UINT32_MAX; prq.request_found = GNUNET_NO; GNUNET_CONTAINER_multihashmap_get_multiple (pr_map, &query, &process_reply, &prq); if (NULL != cp) { GSF_connected_peer_change_preference_ (cp, CONTENT_BANDWIDTH_VALUE + 1000 * prq.priority); GSF_get_peer_performance_data_ (cp)->respect += prq.priority; } if ((GNUNET_YES == active_to_migration) && (NULL != cp) && (GNUNET_NO == test_put_load_too_high (prq.priority))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Replicating result for query `%s' with priority %u\n", GNUNET_h2s (&query), prq.priority); pmc = GNUNET_new (struct PutMigrationContext); pmc->start = GNUNET_TIME_absolute_get (); pmc->requested = prq.request_found; GNUNET_assert (0 != GSF_get_peer_performance_data_ (cp)->pid); GNUNET_PEER_resolve (GSF_get_peer_performance_data_ (cp)->pid, &pmc->origin); if (NULL == GNUNET_DATASTORE_put (GSF_dsh, 0, &query, dsize, &put[1], type, prq.priority, 1 /* anonymity */ , 0 /* replication */ , expiration, 1 + prq.priority, MAX_DATASTORE_QUEUE, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &put_migration_continuation, pmc)) { put_migration_continuation (pmc, GNUNET_SYSERR, GNUNET_TIME_UNIT_ZERO_ABS, NULL); } } else if (NULL != cp) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Choosing not to keep content `%s' (%d/%d)\n", GNUNET_h2s (&query), active_to_migration, test_put_load_too_high (prq.priority)); } putl = GNUNET_LOAD_get_load (datastore_put_load); if ( (NULL != cp) && (GNUNET_NO == prq.request_found) && ( (GNUNET_YES != active_to_migration) || (putl > 2.5 * (1 + prq.priority)) ) ) { if (GNUNET_YES != active_to_migration) putl = 1.0 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 5); block_time = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 5000 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, (unsigned int) (60000 * putl * putl))); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking to stop migration for %s because of load %f and events %d/%d\n", GNUNET_STRINGS_relative_time_to_string (block_time, GNUNET_YES), putl, active_to_migration, (GNUNET_NO == prq.request_found)); GSF_block_peer_migration_ (cp, GNUNET_TIME_relative_to_absolute (block_time)); } return GNUNET_OK; } /** * Setup the subsystem. */ void GSF_pending_request_init_ () { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (GSF_cfg, "fs", "MAX_PENDING_REQUESTS", &max_pending_requests)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_INFO, "fs", "MAX_PENDING_REQUESTS"); } active_to_migration = GNUNET_CONFIGURATION_get_value_yesno (GSF_cfg, "FS", "CONTENT_CACHING"); datastore_put_load = GNUNET_LOAD_value_init (DATASTORE_LOAD_AUTODECLINE); pr_map = GNUNET_CONTAINER_multihashmap_create (32 * 1024, GNUNET_YES); requests_by_expiration_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); } /** * Shutdown the subsystem. */ void GSF_pending_request_done_ () { GNUNET_CONTAINER_multihashmap_iterate (pr_map, &clean_request, NULL); GNUNET_CONTAINER_multihashmap_destroy (pr_map); pr_map = NULL; GNUNET_CONTAINER_heap_destroy (requests_by_expiration_heap); requests_by_expiration_heap = NULL; GNUNET_LOAD_value_free (datastore_put_load); datastore_put_load = NULL; } /* end of gnunet-service-fs_pr.c */ gnunet-0.10.1/src/fs/test_fs_file_information.c0000644000175000017500000001277312225777502016453 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_file_information.c * @brief simple testcase for file_information operations * @author Christian Grothoff * * TODO: * - test that metatdata, etc. are all correct (for example, * there is a known bug with dirname never being set that is * not detected!) * - need to iterate over file-information structure * - other API functions may not yet be tested (such as * filedata-from-callback) */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" /** * File-size we use for testing. */ #define FILESIZE (1024 * 1024 * 2) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static int mycleaner (void *cls, struct GNUNET_FS_FileInformation *fi, uint64_t length, struct GNUNET_CONTAINER_MetaData *meta, struct GNUNET_FS_Uri **uri, struct GNUNET_FS_BlockOptions *bo, int *do_index, void **client_info) { return GNUNET_OK; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { const char *keywords[] = { "down_foo", "down_bar", }; char *fn1; char *fn2; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi1; struct GNUNET_FS_FileInformation *fi2; struct GNUNET_FS_FileInformation *fidir; struct GNUNET_FS_Handle *fs; size_t i; struct GNUNET_FS_BlockOptions bo; fs = GNUNET_FS_start (cfg, "test-fs-file-information", NULL, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); fn1 = GNUNET_DISK_mktemp ("gnunet-file_information-test-dst"); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn1, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); fn2 = GNUNET_DISK_mktemp ("gnunet-file_information-test-dst"); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); GNUNET_assert (FILESIZE == GNUNET_DISK_fn_write (fn2, buf, FILESIZE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)); GNUNET_free (buf); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi1 = GNUNET_FS_file_information_create_from_file (fs, "file_information-context1", fn1, kuri, meta, GNUNET_YES, &bo); GNUNET_assert (fi1 != NULL); fi2 = GNUNET_FS_file_information_create_from_file (fs, "file_information-context2", fn2, kuri, meta, GNUNET_YES, &bo); GNUNET_assert (fi2 != NULL); fidir = GNUNET_FS_file_information_create_empty_directory (fs, "file_information-context-dir", kuri, meta, &bo, NULL); GNUNET_assert (GNUNET_OK == GNUNET_FS_file_information_add (fidir, fi1)); GNUNET_assert (GNUNET_OK == GNUNET_FS_file_information_add (fidir, fi2)); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fidir); /* FIXME: test more of API! */ GNUNET_FS_file_information_destroy (fidir, &mycleaner, NULL); GNUNET_DISK_directory_remove (fn1); GNUNET_DISK_directory_remove (fn2); GNUNET_free_non_null (fn1); GNUNET_free_non_null (fn2); GNUNET_FS_stop (fs); } int main (int argc, char *argv[]) { char *const argvx[] = { "test-fs-file_information", "-c", "test_fs_file_information_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_log_setup ("test_fs_file_information", "WARNING", NULL); GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-fs-file_information", "nohelp", options, &run, NULL); return 0; } /* end of test_fs_file_information.c */ gnunet-0.10.1/src/fs/test_fs_search_persistence.c0000644000175000017500000002162212226007114016753 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2008, 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_search_persistence.c * @brief simple testcase for persistence of search operation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_fs_service.h" /** * File-size we use for testing. */ #define FILESIZE 1024 /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How long should our test-content live? */ #define LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) static struct GNUNET_TIME_Absolute start; static struct GNUNET_FS_Handle *fs; static struct GNUNET_FS_SearchContext *search; static struct GNUNET_FS_PublishContext *publish; static const struct GNUNET_CONFIGURATION_Handle *cfg; static GNUNET_SCHEDULER_TaskIdentifier timeout_task; static int err; static void abort_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { timeout_task = GNUNET_SCHEDULER_NO_TASK; fprintf (stderr, "Timeout\n"); if (NULL != search) { GNUNET_FS_search_stop (search); search = NULL; } if (NULL != publish) { GNUNET_FS_publish_stop (publish); publish = NULL; } err = 1; } static void abort_publish_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != publish) { GNUNET_FS_publish_stop (publish); publish = NULL; } if (GNUNET_SCHEDULER_NO_TASK != timeout_task) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } } static void abort_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != search) { GNUNET_FS_search_stop (search); search = NULL; } } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event); static void restart_fs_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_FS_stop (fs); fs = GNUNET_FS_start (cfg, "test-fs-search-persistence", &progress_cb, NULL, GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END); } /** * Consider scheduling the restart-task. * Only runs the restart task once per event * category. * * @param ev type of the event to consider */ static void consider_restart (int ev) { static int prev[32]; static int off; int i; for (i = 0; i < off; i++) if (prev[i] == ev) return; prev[off++] = ev; GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_URGENT, &restart_fs_task, NULL); } static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *event) { const char *keywords[] = { "down_foo" }; struct GNUNET_FS_Uri *kuri; switch (event->status) { case GNUNET_FS_STATUS_PUBLISH_PROGRESS: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publish is progressing (%llu/%llu at level %u off %llu)...\n", (unsigned long long) event->value.publish.completed, (unsigned long long) event->value.publish.size, event->value.publish.specifics.progress.depth, (unsigned long long) event->value.publish.specifics. progress.offset); break; case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY: break; case GNUNET_FS_STATUS_PUBLISH_COMPLETED: kuri = GNUNET_FS_uri_ksk_create_from_args (1, keywords); start = GNUNET_TIME_absolute_get (); GNUNET_FS_search_start (fs, kuri, 1, GNUNET_FS_SEARCH_OPTION_NONE, "search"); GNUNET_FS_uri_destroy (kuri); GNUNET_assert (search != NULL); break; case GNUNET_FS_STATUS_PUBLISH_SUSPEND: if (event->value.publish.pc == publish) publish = NULL; break; case GNUNET_FS_STATUS_PUBLISH_RESUME: if (NULL == publish) publish = event->value.publish.pc; break; case GNUNET_FS_STATUS_SEARCH_RESULT: /* FIXME: consider_restart (event->status); cannot be tested with * search result since we exit here after the first one... */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Search complete.\n"); GNUNET_SCHEDULER_add_continuation (&abort_search_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_PUBLISH_ERROR: FPRINTF (stderr, "Error publishing file: %s\n", event->value.publish.specifics.error.message); GNUNET_break (0); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_SEARCH_ERROR: FPRINTF (stderr, "Error searching file: %s\n", event->value.search.specifics.error.message); GNUNET_SCHEDULER_add_continuation (&abort_search_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case GNUNET_FS_STATUS_SEARCH_SUSPEND: if (event->value.search.sc == search) search = NULL; break; case GNUNET_FS_STATUS_SEARCH_RESUME: if (NULL == search) { search = event->value.search.sc; return "search"; } break; case GNUNET_FS_STATUS_PUBLISH_START: GNUNET_assert (0 == strcmp ("publish-context", event->value.publish.cctx)); GNUNET_assert (NULL == event->value.publish.pctx); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (0 == event->value.publish.completed); GNUNET_assert (1 == event->value.publish.anonymity); break; case GNUNET_FS_STATUS_PUBLISH_STOPPED: GNUNET_assert (publish == event->value.publish.pc); GNUNET_assert (FILESIZE == event->value.publish.size); GNUNET_assert (1 == event->value.publish.anonymity); GNUNET_FS_stop (fs); fs = NULL; break; case GNUNET_FS_STATUS_SEARCH_START: consider_restart (event->status); GNUNET_assert (search == NULL); search = event->value.search.sc; GNUNET_assert (0 == strcmp ("search", event->value.search.cctx)); GNUNET_assert (1 == event->value.search.anonymity); break; case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: break; case GNUNET_FS_STATUS_SEARCH_STOPPED: GNUNET_assert (search == event->value.search.sc); GNUNET_SCHEDULER_add_continuation (&abort_publish_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); search = NULL; break; default: FPRINTF (stderr, "Unexpected event: %d\n", event->status); break; } return NULL; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_TESTING_Peer *peer) { const char *keywords[] = { "down_foo", "down_bar" }; char *buf; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *kuri; struct GNUNET_FS_FileInformation *fi; size_t i; struct GNUNET_FS_BlockOptions bo; cfg = c; fs = GNUNET_FS_start (cfg, "test-fs-search-persistence", &progress_cb, NULL, GNUNET_FS_FLAGS_PERSISTENCE, GNUNET_FS_OPTIONS_END); GNUNET_assert (NULL != fs); buf = GNUNET_malloc (FILESIZE); for (i = 0; i < FILESIZE; i++) buf[i] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); meta = GNUNET_CONTAINER_meta_data_create (); kuri = GNUNET_FS_uri_ksk_create_from_args (2, keywords); bo.content_priority = 42; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (LIFETIME); fi = GNUNET_FS_file_information_create_from_data (fs, "publish-context", FILESIZE, buf, kuri, meta, GNUNET_NO, &bo); GNUNET_FS_uri_destroy (kuri); GNUNET_CONTAINER_meta_data_destroy (meta); GNUNET_assert (NULL != fi); start = GNUNET_TIME_absolute_get (); publish = GNUNET_FS_publish_start (fs, fi, NULL, NULL, NULL, GNUNET_FS_PUBLISH_OPTION_NONE); GNUNET_assert (publish != NULL); timeout_task = GNUNET_SCHEDULER_add_delayed (LIFETIME, &abort_error, NULL); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-fs-search-persistence", "test_fs_search_data.conf", &run, NULL)) return 1; return err; } /* end of test_fs_search_persistence.c */ gnunet-0.10.1/src/fs/gnunet-service-fs_put.c0000644000175000017500000001640512225777502015630 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_put.c * @brief API to PUT zero-anonymity index data from our datastore into the DHT * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-fs.h" #include "gnunet-service-fs_put.h" /** * How often do we at most PUT content into the DHT? */ #define MAX_DHT_PUT_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * How many replicas do we try to create per PUT? */ #define DEFAULT_PUT_REPLICATION 5 /** * Context for each zero-anonymity iterator. */ struct PutOperator { /** * Request to datastore for DHT PUTs (or NULL). */ struct GNUNET_DATASTORE_QueueEntry *dht_qe; /** * Type we request from the datastore. */ enum GNUNET_BLOCK_Type dht_put_type; /** * Handle to PUT operation. */ struct GNUNET_DHT_PutHandle *dht_put; /** * ID of task that collects blocks for DHT PUTs. */ GNUNET_SCHEDULER_TaskIdentifier dht_task; /** * How many entires with zero anonymity of our type do we currently * estimate to have in the database? */ uint64_t zero_anonymity_count_estimate; /** * Current offset when iterating the database. */ uint64_t current_offset; }; /** * ANY-terminated list of our operators (one per type * of block that we're putting into the DHT). */ static struct PutOperator operators[] = { {NULL, GNUNET_BLOCK_TYPE_FS_UBLOCK, 0, 0, 0}, {NULL, GNUNET_BLOCK_TYPE_ANY, 0, 0, 0} }; /** * Task that is run periodically to obtain blocks for DHT PUTs. * * @param cls type of blocks to gather * @param tc scheduler context (unused) */ static void gather_dht_put_blocks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Calculate when to run the next PUT operation and schedule it. * * @param po put operator to schedule */ static void schedule_next_put (struct PutOperator *po) { struct GNUNET_TIME_Relative delay; if (po->zero_anonymity_count_estimate > 0) { delay = GNUNET_TIME_relative_divide (GNUNET_DHT_DEFAULT_REPUBLISH_FREQUENCY, po->zero_anonymity_count_estimate); delay = GNUNET_TIME_relative_min (delay, MAX_DHT_PUT_FREQ); } else { /* if we have NO zero-anonymity content yet, wait 5 minutes for some to * (hopefully) appear */ delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5); } po->dht_task = GNUNET_SCHEDULER_add_delayed (delay, &gather_dht_put_blocks, po); } /** * Continuation called after DHT PUT operation has finished. * * @param cls type of blocks to gather * @param success GNUNET_OK if the PUT was transmitted, * GNUNET_NO on timeout, * GNUNET_SYSERR on disconnect from service * after the PUT message was transmitted * (so we don't know if it was received or not) */ static void delay_dht_put_blocks (void *cls, int success) { struct PutOperator *po = cls; po->dht_put = NULL; schedule_next_put (po); } /** * Task that is run periodically to obtain blocks for DHT PUTs. * * @param cls type of blocks to gather * @param tc scheduler context */ static void delay_dht_put_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PutOperator *po = cls; po->dht_task = GNUNET_SCHEDULER_NO_TASK; schedule_next_put (po); } /** * Store content in DHT. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ static void process_dht_put_content (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct PutOperator *po = cls; po->dht_qe = NULL; if (key == NULL) { po->zero_anonymity_count_estimate = po->current_offset - 1; po->current_offset = 0; po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_task, po); return; } po->zero_anonymity_count_estimate = GNUNET_MAX (po->current_offset, po->zero_anonymity_count_estimate); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Retrieved block `%s' of type %u for DHT PUT\n", GNUNET_h2s (key), type); po->dht_put = GNUNET_DHT_put (GSF_dht, key, DEFAULT_PUT_REPLICATION, GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, type, size, data, expiration, GNUNET_TIME_UNIT_FOREVER_REL, &delay_dht_put_blocks, po); } /** * Task that is run periodically to obtain blocks for DHT PUTs. * * @param cls type of blocks to gather * @param tc scheduler context (unused) */ static void gather_dht_put_blocks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PutOperator *po = cls; po->dht_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; po->dht_qe = GNUNET_DATASTORE_get_zero_anonymity (GSF_dsh, po->current_offset++, 0, UINT_MAX, GNUNET_TIME_UNIT_FOREVER_REL, po->dht_put_type, &process_dht_put_content, po); if (NULL == po->dht_qe) po->dht_task = GNUNET_SCHEDULER_add_now (&delay_dht_put_task, po); } /** * Setup the module. */ void GSF_put_init_ () { unsigned int i; i = 0; while (operators[i].dht_put_type != GNUNET_BLOCK_TYPE_ANY) { operators[i].dht_task = GNUNET_SCHEDULER_add_now (&gather_dht_put_blocks, &operators[i]); i++; } } /** * Shutdown the module. */ void GSF_put_done_ () { struct PutOperator *po; unsigned int i; i = 0; while ((po = &operators[i])->dht_put_type != GNUNET_BLOCK_TYPE_ANY) { if (GNUNET_SCHEDULER_NO_TASK != po->dht_task) { GNUNET_SCHEDULER_cancel (po->dht_task); po->dht_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != po->dht_put) { GNUNET_DHT_put_cancel (po->dht_put); po->dht_put = NULL; } if (NULL != po->dht_qe) { GNUNET_DATASTORE_cancel (po->dht_qe); po->dht_qe = NULL; } i++; } } /* end of gnunet-service-fs_put.c */ gnunet-0.10.1/src/fs/gnunet-service-fs_push.c0000644000175000017500000003771012225777502016001 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/gnunet-service-fs_push.c * @brief API to push content from our datastore to other peers * ('anonymous'-content P2P migration) * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-fs.h" #include "gnunet-service-fs_cp.h" #include "gnunet-service-fs_indexing.h" #include "gnunet-service-fs_push.h" /** * Maximum number of blocks we keep in memory for migration. */ #define MAX_MIGRATION_QUEUE 8 /** * Blocks are at most migrated to this number of peers * plus one, each time they are fetched from the database. */ #define MIGRATION_LIST_SIZE 2 /** * How long must content remain valid for us to consider it for migration? * If content will expire too soon, there is clearly no point in pushing * it to other peers. This value gives the threshold for migration. Note * that if this value is increased, the migration testcase may need to be * adjusted as well (especially the CONTENT_LIFETIME in fs_test_lib.c). */ #define MIN_MIGRATION_CONTENT_LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) /** * Block that is ready for migration to other peers. Actual data is at the end of the block. */ struct MigrationReadyBlock { /** * This is a doubly-linked list. */ struct MigrationReadyBlock *next; /** * This is a doubly-linked list. */ struct MigrationReadyBlock *prev; /** * Query for the block. */ struct GNUNET_HashCode query; /** * When does this block expire? */ struct GNUNET_TIME_Absolute expiration; /** * Peers we already forwarded this * block to. Zero for empty entries. */ GNUNET_PEER_Id target_list[MIGRATION_LIST_SIZE]; /** * Size of the block. */ size_t size; /** * Number of targets already used. */ unsigned int used_targets; /** * Type of the block. */ enum GNUNET_BLOCK_Type type; }; /** * Information about a peer waiting for * migratable data. */ struct MigrationReadyPeer { /** * This is a doubly-linked list. */ struct MigrationReadyPeer *next; /** * This is a doubly-linked list. */ struct MigrationReadyPeer *prev; /** * Handle to peer. */ struct GSF_ConnectedPeer *peer; /** * Handle for current transmission request, * or NULL for none. */ struct GSF_PeerTransmitHandle *th; /** * Message we are trying to push right now (or NULL) */ struct PutMessage *msg; }; /** * Head of linked list of blocks that can be migrated. */ static struct MigrationReadyBlock *mig_head; /** * Tail of linked list of blocks that can be migrated. */ static struct MigrationReadyBlock *mig_tail; /** * Head of linked list of peers. */ static struct MigrationReadyPeer *peer_head; /** * Tail of linked list of peers. */ static struct MigrationReadyPeer *peer_tail; /** * Request to datastore for migration (or NULL). */ static struct GNUNET_DATASTORE_QueueEntry *mig_qe; /** * ID of task that collects blocks for migration. */ static GNUNET_SCHEDULER_TaskIdentifier mig_task; /** * What is the maximum frequency at which we are allowed to * poll the datastore for migration content? */ static struct GNUNET_TIME_Relative min_migration_delay; /** * Size of the doubly-linked list of migration blocks. */ static unsigned int mig_size; /** * Is this module enabled? */ static int enabled; /** * Delete the given migration block. * * @param mb block to delete */ static void delete_migration_block (struct MigrationReadyBlock *mb) { GNUNET_CONTAINER_DLL_remove (mig_head, mig_tail, mb); GNUNET_PEER_decrement_rcs (mb->target_list, MIGRATION_LIST_SIZE); mig_size--; GNUNET_free (mb); } /** * Find content for migration to this peer. */ static void find_content (struct MigrationReadyPeer *mrp); /** * Transmit the message currently scheduled for * transmission. * * @param cls the 'struct MigrationReadyPeer' * @param buf_size number of bytes available in buf * @param buf where to copy the message, NULL on error (peer disconnect) * @return number of bytes copied to 'buf', can be 0 (without indicating an error) */ static size_t transmit_message (void *cls, size_t buf_size, void *buf) { struct MigrationReadyPeer *peer = cls; struct PutMessage *msg; uint16_t msize; peer->th = NULL; msg = peer->msg; peer->msg = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to migrate content to another peer (disconnect)\n"); GNUNET_free (msg); return 0; } msize = ntohs (msg->header.size); GNUNET_assert (msize <= buf_size); memcpy (buf, msg, msize); GNUNET_free (msg); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Pushing %u bytes to another peer\n", msize); find_content (peer); return msize; } /** * Send the given block to the given peer. * * @param peer target peer * @param block the block * @return GNUNET_YES if the block was deleted (!) */ static int transmit_content (struct MigrationReadyPeer *peer, struct MigrationReadyBlock *block) { size_t msize; struct PutMessage *msg; unsigned int i; struct GSF_PeerPerformanceData *ppd; int ret; ppd = GSF_get_peer_performance_data_ (peer->peer); GNUNET_assert (NULL == peer->th); msize = sizeof (struct PutMessage) + block->size; msg = GNUNET_malloc (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_FS_PUT); msg->header.size = htons (msize); msg->type = htonl (block->type); msg->expiration = GNUNET_TIME_absolute_hton (block->expiration); memcpy (&msg[1], &block[1], block->size); peer->msg = msg; for (i = 0; i < MIGRATION_LIST_SIZE; i++) { if (block->target_list[i] == 0) { block->target_list[i] = ppd->pid; GNUNET_PEER_change_rc (block->target_list[i], 1); break; } } if (MIGRATION_LIST_SIZE == i) { delete_migration_block (block); ret = GNUNET_YES; } else { ret = GNUNET_NO; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking for transmission of %u bytes for migration\n", msize); peer->th = GSF_peer_transmit_ (peer->peer, GNUNET_NO, 0 /* priority */ , GNUNET_TIME_UNIT_FOREVER_REL, msize, &transmit_message, peer); return ret; } /** * Count the number of peers this block has * already been forwarded to. * * @param block the block * @return number of times block was forwarded */ static unsigned int count_targets (struct MigrationReadyBlock *block) { unsigned int i; for (i = 0; i < MIGRATION_LIST_SIZE; i++) if (block->target_list[i] == 0) return i; return i; } /** * Check if sending this block to this peer would * be a good idea. * * @param peer target peer * @param block the block * @return score (>= 0: feasible, negative: infeasible) */ static long score_content (struct MigrationReadyPeer *peer, struct MigrationReadyBlock *block) { unsigned int i; struct GSF_PeerPerformanceData *ppd; struct GNUNET_PeerIdentity id; struct GNUNET_HashCode hc; uint32_t dist; ppd = GSF_get_peer_performance_data_ (peer->peer); for (i = 0; i < MIGRATION_LIST_SIZE; i++) if (block->target_list[i] == ppd->pid) return -1; GNUNET_assert (0 != ppd->pid); GNUNET_PEER_resolve (ppd->pid, &id); GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &hc); dist = GNUNET_CRYPTO_hash_distance_u32 (&block->query, &hc); /* closer distance, higher score: */ return UINT32_MAX - dist; } /** * If the migration task is not currently running, consider * (re)scheduling it with the appropriate delay. */ static void consider_gathering (void); /** * Find content for migration to this peer. * * @param mrp peer to find content for */ static void find_content (struct MigrationReadyPeer *mrp) { struct MigrationReadyBlock *pos; long score; long best_score; struct MigrationReadyBlock *best; GNUNET_assert (NULL == mrp->th); best = NULL; best_score = -1; pos = mig_head; while (NULL != pos) { score = score_content (mrp, pos); if (score > best_score) { best_score = score; best = pos; } pos = pos->next; } if (NULL == best) { if (mig_size < MAX_MIGRATION_QUEUE) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No content found for pushing, waiting for queue to fill\n"); return; /* will fill up eventually... */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No suitable content found, purging content from full queue\n"); /* failed to find migration target AND * queue is full, purge most-forwarded * block from queue to make room for more */ pos = mig_head; while (NULL != pos) { score = count_targets (pos); if (score >= best_score) { best_score = score; best = pos; } pos = pos->next; } GNUNET_assert (NULL != best); delete_migration_block (best); consider_gathering (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Preparing to push best content to peer\n"); transmit_content (mrp, best); } /** * Task that is run periodically to obtain blocks for content * migration * * @param cls unused * @param tc scheduler context (also unused) */ static void gather_migration_blocks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * If the migration task is not currently running, consider * (re)scheduling it with the appropriate delay. */ static void consider_gathering () { struct GNUNET_TIME_Relative delay; if (GSF_dsh == NULL) return; if (mig_qe != NULL) return; if (mig_task != GNUNET_SCHEDULER_NO_TASK) return; if (mig_size >= MAX_MIGRATION_QUEUE) return; delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, mig_size); delay = GNUNET_TIME_relative_divide (delay, MAX_MIGRATION_QUEUE); delay = GNUNET_TIME_relative_max (delay, min_migration_delay); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Scheduling gathering task (queue size: %u)\n", mig_size); mig_task = GNUNET_SCHEDULER_add_delayed (delay, &gather_migration_blocks, NULL); } /** * Process content offered for migration. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ static void process_migration_content (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct MigrationReadyBlock *mb; struct MigrationReadyPeer *pos; mig_qe = NULL; if (key == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No content found for migration...\n"); consider_gathering (); return; } if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us < MIN_MIGRATION_CONTENT_LIFETIME.rel_value_us) { /* content will expire soon, don't bother */ consider_gathering (); return; } if (type == GNUNET_BLOCK_TYPE_FS_ONDEMAND) { if (GNUNET_OK != GNUNET_FS_handle_on_demand_block (key, size, data, type, priority, anonymity, expiration, uid, &process_migration_content, NULL)) consider_gathering (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Retrieved block `%s' of type %u for migration (queue size: %u/%u)\n", GNUNET_h2s (key), type, mig_size + 1, MAX_MIGRATION_QUEUE); mb = GNUNET_malloc (sizeof (struct MigrationReadyBlock) + size); mb->query = *key; mb->expiration = expiration; mb->size = size; mb->type = type; memcpy (&mb[1], data, size); GNUNET_CONTAINER_DLL_insert_after (mig_head, mig_tail, mig_tail, mb); mig_size++; pos = peer_head; while (pos != NULL) { if (NULL == pos->th) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Preparing to push best content to peer\n"); if (GNUNET_YES == transmit_content (pos, mb)) break; /* 'mb' was freed! */ } pos = pos->next; } consider_gathering (); } /** * Task that is run periodically to obtain blocks for content * migration * * @param cls unused * @param tc scheduler context (also unused) */ static void gather_migration_blocks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { mig_task = GNUNET_SCHEDULER_NO_TASK; if (mig_size >= MAX_MIGRATION_QUEUE) return; if (GSF_dsh != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking datastore for content for replication (queue size: %u)\n", mig_size); mig_qe = GNUNET_DATASTORE_get_for_replication (GSF_dsh, 0, UINT_MAX, GNUNET_TIME_UNIT_FOREVER_REL, &process_migration_content, NULL); if (NULL == mig_qe) consider_gathering (); } } /** * A peer connected to us. Start pushing content * to this peer. * * @param peer handle for the peer that connected */ void GSF_push_start_ (struct GSF_ConnectedPeer *peer) { struct MigrationReadyPeer *mrp; if (GNUNET_YES != enabled) return; mrp = GNUNET_new (struct MigrationReadyPeer); mrp->peer = peer; find_content (mrp); GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, mrp); } /** * A peer disconnected from us. Stop pushing content * to this peer. * * @param peer handle for the peer that disconnected */ void GSF_push_stop_ (struct GSF_ConnectedPeer *peer) { struct MigrationReadyPeer *pos; pos = peer_head; while (pos != NULL) { if (pos->peer == peer) { GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos); if (NULL != pos->th) { GSF_peer_transmit_cancel_ (pos->th); pos->th = NULL; } if (NULL != pos->msg) { GNUNET_free (pos->msg); pos->msg = NULL; } GNUNET_free (pos); return; } pos = pos->next; } } /** * Setup the module. */ void GSF_push_init_ () { enabled = GNUNET_CONFIGURATION_get_value_yesno (GSF_cfg, "FS", "CONTENT_PUSHING"); if (GNUNET_YES != enabled) return; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (GSF_cfg, "fs", "MIN_MIGRATION_DELAY", &min_migration_delay)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "fs", "MIN_MIGRATION_DELAY", _("time required, content pushing disabled")); return; } consider_gathering (); } /** * Shutdown the module. */ void GSF_push_done_ () { if (GNUNET_SCHEDULER_NO_TASK != mig_task) { GNUNET_SCHEDULER_cancel (mig_task); mig_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != mig_qe) { GNUNET_DATASTORE_cancel (mig_qe); mig_qe = NULL; } while (NULL != mig_head) delete_migration_block (mig_head); GNUNET_assert (0 == mig_size); } /* end of gnunet-service-fs_push.c */ gnunet-0.10.1/src/fs/test_fs_uri.c0000644000175000017500000002152312225777502013717 00000000000000/* This file is part of GNUnet. (C) 2003, 2004, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_uri.c * @brief Test for fs_uri.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "fs_api.h" static int testKeyword () { char *uri; struct GNUNET_FS_Uri *ret; char *emsg; if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/ksk/++", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); ret = GNUNET_FS_uri_parse ("gnunet://fs/ksk/foo+bar", &emsg); if (ret == NULL) { GNUNET_free (emsg); GNUNET_assert (0); } if (!GNUNET_FS_uri_test_ksk (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } if ((2 != ret->data.ksk.keywordCount) || (0 != strcmp (" foo", ret->data.ksk.keywords[0])) || (0 != strcmp (" bar", ret->data.ksk.keywords[1]))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, "gnunet://fs/ksk/foo+bar")) { GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); return 0; } static int testLocation () { struct GNUNET_FS_Uri *uri; char *uric; struct GNUNET_FS_Uri *uri2; struct GNUNET_FS_Uri *baseURI; char *emsg; struct GNUNET_CONFIGURATION_Handle *cfg; baseURI = GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42", &emsg); GNUNET_assert (baseURI != NULL); GNUNET_assert (emsg == NULL); cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, "test_fs_uri_data.conf")) { FPRINTF (stderr, "%s", "Failed to parse configuration file\n"); GNUNET_FS_uri_destroy (baseURI); GNUNET_CONFIGURATION_destroy (cfg); return 1; } uri = GNUNET_FS_uri_loc_create (baseURI, cfg, GNUNET_TIME_absolute_get ()); if (uri == NULL) { GNUNET_break (0); GNUNET_FS_uri_destroy (baseURI); GNUNET_CONFIGURATION_destroy (cfg); return 1; } if (!GNUNET_FS_uri_test_loc (uri)) { GNUNET_break (0); GNUNET_FS_uri_destroy (uri); GNUNET_FS_uri_destroy (baseURI); GNUNET_CONFIGURATION_destroy (cfg); return 1; } uri2 = GNUNET_FS_uri_loc_get_uri (uri); if (!GNUNET_FS_uri_test_equal (baseURI, uri2)) { GNUNET_break (0); GNUNET_FS_uri_destroy (uri); GNUNET_FS_uri_destroy (uri2); GNUNET_FS_uri_destroy (baseURI); GNUNET_CONFIGURATION_destroy (cfg); return 1; } GNUNET_FS_uri_destroy (uri2); GNUNET_FS_uri_destroy (baseURI); uric = GNUNET_FS_uri_to_string (uri); #if 0 /* not for the faint of heart: */ printf ("URI: `%s'\n", uric); #endif uri2 = GNUNET_FS_uri_parse (uric, &emsg); GNUNET_free (uric); if (uri2 == NULL) { fprintf (stderr, "URI parsing failed: %s\n", emsg); GNUNET_break (0); GNUNET_FS_uri_destroy (uri); GNUNET_CONFIGURATION_destroy (cfg); GNUNET_free (emsg); return 1; } GNUNET_assert (NULL == emsg); if (GNUNET_YES != GNUNET_FS_uri_test_equal (uri, uri2)) { GNUNET_break (0); GNUNET_FS_uri_destroy (uri); GNUNET_FS_uri_destroy (uri2); GNUNET_CONFIGURATION_destroy (cfg); return 1; } GNUNET_FS_uri_destroy (uri2); GNUNET_FS_uri_destroy (uri); GNUNET_CONFIGURATION_destroy (cfg); return 0; } static int testNamespace (int i) { char *uri; struct GNUNET_FS_Uri *ret; char *emsg; struct GNUNET_CRYPTO_EcdsaPrivateKey *ph; struct GNUNET_CRYPTO_EcdsaPublicKey id; char buf[1024]; char ubuf[1024]; char *sret; if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3V/test", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/sks/test", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); ph = GNUNET_CRYPTO_ecdsa_key_create (); GNUNET_CRYPTO_ecdsa_key_get_public (ph, &id); sret = GNUNET_STRINGS_data_to_string (&id, sizeof (id), ubuf, sizeof (ubuf) - 1); GNUNET_assert (NULL != sret); sret[0] = '\0'; GNUNET_snprintf (buf, sizeof (buf), "gnunet://fs/sks/%s/test", ubuf); ret = GNUNET_FS_uri_parse (buf, &emsg); if (NULL == ret) { GNUNET_free (emsg); GNUNET_assert (0); } if (GNUNET_FS_uri_test_ksk (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } if (!GNUNET_FS_uri_test_sks (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, buf)) { GNUNET_FS_uri_destroy (ret); GNUNET_free (uri); GNUNET_assert (0); } GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); return 0; } static int testFile (int i) { char *uri; struct GNUNET_FS_Uri *ret; char *emsg; if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); ret = GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42", &emsg); if (ret == NULL) { GNUNET_free (emsg); GNUNET_assert (0); } if (GNUNET_FS_uri_test_ksk (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } if (GNUNET_FS_uri_test_sks (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } if (GNUNET_ntohll (ret->data.chk.file_length) != 42) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, "gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42")) { GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); return 0; } int main (int argc, char *argv[]) { int failureCount = 0; int i; GNUNET_log_setup ("test_fs_uri", "WARNING", NULL); failureCount += testKeyword (); failureCount += testLocation (); for (i = 0; i < 255; i++) { /* FPRINTF (stderr, "%s", "."); */ failureCount += testNamespace (i); failureCount += testFile (i); } /* FPRINTF (stderr, "%s", "\n"); */ GNUNET_DISK_directory_remove ("/tmp/gnunet-test-fs-uri"); if (failureCount != 0) return 1; return 0; } /* end of test_fs_uri.c */ gnunet-0.10.1/src/fs/test_fs_getopt.c0000644000175000017500000000233112225777502014416 00000000000000/* This file is part of GNUnet (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file fs/test_fs_getopt.c * @brief test for fs_getopt.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_fs_service.h" int main (int argc, char *argv[]) { GNUNET_log_setup ("test_fs_getopt", "WARNING", NULL); FPRINTF (stderr, "%s", "WARNING: testcase not yet written.\n"); return 0; /* testcase passed */ } gnunet-0.10.1/src/psycstore/0000755000175000017500000000000012320755627012725 500000000000000gnunet-0.10.1/src/psycstore/plugin_psycstore_sqlite.c0000644000175000017500000015202612306275771020012 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psycstore/plugin_psycstore_sqlite.c * @brief sqlite-based psycstore backend * @author Gabor X Toth * @author Christian Grothoff */ /* * FIXME: SQLite3 only supports signed 64-bit integers natively, * thus it can only store 63 bits of the uint64_t's. */ #include "platform.h" #include "gnunet_psycstore_plugin.h" #include "gnunet_psycstore_service.h" #include "gnunet_multicast_service.h" #include "gnunet_crypto_lib.h" #include "psycstore.h" #include /** * After how many ms "busy" should a DB operation fail for good? A * low value makes sure that we are more responsive to requests * (especially PUTs). A high value guarantees a higher success rate * (SELECTs in iterate can take several seconds despite LIMIT=1). * * The default value of 1s should ensure that users do not experience * huge latencies while at the same time allowing operations to * succeed with reasonable probability. */ #define BUSY_TIMEOUT_MS 1000 #define DEBUG_PSYCSTORE GNUNET_EXTRA_LOGGING /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "psycstore-sqlite", _("`%s' failed at %s:%d with error: %s (%d)\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh), sqlite3_errcode(db->dbh)); } while(0) #define LOG(kind,...) GNUNET_log_from (kind, "psycstore-sqlite", __VA_ARGS__) enum Transactions { TRANSACTION_NONE = 0, TRANSACTION_STATE_MODIFY }; /** * Context for all functions in this plugin. */ struct Plugin { const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Database filename. */ char *fn; /** * Native SQLite database handle. */ sqlite3 *dbh; /** * Current transaction. */ enum Transactions transaction; sqlite3_stmt *transaction_begin; sqlite3_stmt *transaction_commit; sqlite3_stmt *transaction_rollback; /** * Precompiled SQL for channel_key_store() */ sqlite3_stmt *insert_channel_key; /** * Precompiled SQL for slave_key_store() */ sqlite3_stmt *insert_slave_key; /** * Precompiled SQL for membership_store() */ sqlite3_stmt *insert_membership; /** * Precompiled SQL for membership_test() */ sqlite3_stmt *select_membership; /** * Precompiled SQL for fragment_store() */ sqlite3_stmt *insert_fragment; /** * Precompiled SQL for message_add_flags() */ sqlite3_stmt *update_message_flags; /** * Precompiled SQL for fragment_get() */ sqlite3_stmt *select_fragment; /** * Precompiled SQL for message_get() */ sqlite3_stmt *select_message; /** * Precompiled SQL for message_get_fragment() */ sqlite3_stmt *select_message_fragment; /** * Precompiled SQL for counters_get_message() */ sqlite3_stmt *select_counters_message; /** * Precompiled SQL for counters_get_state() */ sqlite3_stmt *select_counters_state; /** * Precompiled SQL for state_modify_end() */ sqlite3_stmt *update_state_hash_message_id; /** * Precompiled SQL for state_sync_end() */ sqlite3_stmt *update_max_state_message_id; /** * Precompiled SQL for message_modify_begin() */ sqlite3_stmt *select_message_state_delta; /** * Precompiled SQL for state_modify_set() */ sqlite3_stmt *insert_state_current; /** * Precompiled SQL for state_modify_end() */ sqlite3_stmt *delete_state_empty; /** * Precompiled SQL for state_set_signed() */ sqlite3_stmt *update_state_signed; /** * Precompiled SQL for state_sync() */ sqlite3_stmt *insert_state_sync; /** * Precompiled SQL for state_sync() */ sqlite3_stmt *delete_state; /** * Precompiled SQL for state_sync() */ sqlite3_stmt *insert_state_from_sync; /** * Precompiled SQL for state_sync() */ sqlite3_stmt *delete_state_sync; /** * Precompiled SQL for state_get_signed() */ sqlite3_stmt *select_state_signed; /** * Precompiled SQL for state_get() */ sqlite3_stmt *select_state_one; /** * Precompiled SQL for state_get_prefix() */ sqlite3_stmt *select_state_prefix; }; #if DEBUG_PSYCSTORE static void sql_trace (void *cls, const char *sql) { LOG (GNUNET_ERROR_TYPE_DEBUG, "SQL query:\n%s\n", sql); } #endif /** * @brief Prepare a SQL statement * * @param dbh handle to the database * @param sql SQL statement, UTF-8 encoded * @param stmt set to the prepared statement * @return 0 on success */ static int sql_prepare (sqlite3 *dbh, const char *sql, sqlite3_stmt **stmt) { char *tail; int result; result = sqlite3_prepare_v2 (dbh, sql, strlen (sql), stmt, (const char **) &tail); LOG (GNUNET_ERROR_TYPE_DEBUG, "Prepared `%s' / %p: %d\n", sql, *stmt, result); if (result != SQLITE_OK) LOG (GNUNET_ERROR_TYPE_ERROR, _("Error preparing SQL query: %s\n %s\n"), sqlite3_errmsg (dbh), sql); return result; } /** * @brief Prepare a SQL statement * * @param dbh handle to the database * @param sql SQL statement, UTF-8 encoded * @return 0 on success */ static int sql_exec (sqlite3 *dbh, const char *sql) { int result; result = sqlite3_exec (dbh, sql, NULL, NULL, NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, "Executed `%s' / %d\n", sql, result); if (result != SQLITE_OK) LOG (GNUNET_ERROR_TYPE_ERROR, _("Error executing SQL query: %s\n %s\n"), sqlite3_errmsg (dbh), sql); return result; } /** * Initialize the database connections and associated * data structures (create tables and indices * as needed as well). * * @param plugin the plugin context (state for this module) * @return GNUNET_OK on success */ static int database_setup (struct Plugin *plugin) { char *filename; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "psycstore-sqlite", "FILENAME", &filename)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "psycstore-sqlite", "FILENAME"); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_DISK_file_test (filename)) { if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (filename)) { GNUNET_break (0); GNUNET_free (filename); return GNUNET_SYSERR; } } /* filename should be UTF-8-encoded. If it isn't, it's a bug */ plugin->fn = filename; /* Open database and precompile statements */ if (SQLITE_OK != sqlite3_open (plugin->fn, &plugin->dbh)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Unable to initialize SQLite: %s.\n"), sqlite3_errmsg (plugin->dbh)); return GNUNET_SYSERR; } #if DEBUG_PSYCSTORE sqlite3_trace (plugin->dbh, &sql_trace, NULL); #endif sql_exec (plugin->dbh, "PRAGMA temp_store=MEMORY"); sql_exec (plugin->dbh, "PRAGMA synchronous=NORMAL"); sql_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF"); sql_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL"); sql_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\""); #if ! DEBUG_PSYCSTORE sql_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE"); #endif sql_exec (plugin->dbh, "PRAGMA count_changes=OFF"); sql_exec (plugin->dbh, "PRAGMA page_size=4096"); sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS); /* Create tables */ sql_exec (plugin->dbh, "CREATE TABLE IF NOT EXISTS channels (\n" " id INTEGER PRIMARY KEY,\n" " pub_key BLOB UNIQUE,\n" " max_state_message_id INTEGER,\n" " state_hash_message_id INTEGER\n" ");"); sql_exec (plugin->dbh, "CREATE TABLE IF NOT EXISTS slaves (\n" " id INTEGER PRIMARY KEY,\n" " pub_key BLOB UNIQUE\n" ");"); sql_exec (plugin->dbh, "CREATE TABLE IF NOT EXISTS membership (\n" " channel_id INTEGER NOT NULL REFERENCES channels(id),\n" " slave_id INTEGER NOT NULL REFERENCES slaves(id),\n" " did_join INTEGER NOT NULL,\n" " announced_at INTEGER NOT NULL,\n" " effective_since INTEGER NOT NULL,\n" " group_generation INTEGER NOT NULL\n" ");"); sql_exec (plugin->dbh, "CREATE INDEX IF NOT EXISTS idx_membership_channel_id_slave_id " "ON membership (channel_id, slave_id);"); sql_exec (plugin->dbh, "CREATE TABLE IF NOT EXISTS messages (\n" " channel_id INTEGER NOT NULL REFERENCES channels(id),\n" " hop_counter INTEGER NOT NULL,\n" " signature BLOB,\n" " purpose BLOB,\n" " fragment_id INTEGER NOT NULL,\n" " fragment_offset INTEGER NOT NULL,\n" " message_id INTEGER NOT NULL,\n" " group_generation INTEGER NOT NULL,\n" " multicast_flags INTEGER NOT NULL,\n" " psycstore_flags INTEGER NOT NULL,\n" " data BLOB,\n" " PRIMARY KEY (channel_id, fragment_id),\n" " UNIQUE (channel_id, message_id, fragment_offset)\n" ");"); sql_exec (plugin->dbh, "CREATE TABLE IF NOT EXISTS state (\n" " channel_id INTEGER NOT NULL REFERENCES channels(id),\n" " name TEXT NOT NULL,\n" " value_current BLOB,\n" " value_signed BLOB,\n" " PRIMARY KEY (channel_id, name)\n" ");"); sql_exec (plugin->dbh, "CREATE TABLE IF NOT EXISTS state_sync (\n" " channel_id INTEGER NOT NULL REFERENCES channels(id),\n" " name TEXT NOT NULL,\n" " value BLOB,\n" " PRIMARY KEY (channel_id, name)\n" ");"); /* Prepare statements */ sql_prepare (plugin->dbh, "BEGIN;", &plugin->transaction_begin); sql_prepare (plugin->dbh, "COMMIT;", &plugin->transaction_commit); sql_prepare (plugin->dbh, "ROLLBACK;", &plugin->transaction_rollback); sql_prepare (plugin->dbh, "INSERT OR IGNORE INTO channels (pub_key) VALUES (?);", &plugin->insert_channel_key); sql_prepare (plugin->dbh, "INSERT OR IGNORE INTO slaves (pub_key) VALUES (?);", &plugin->insert_slave_key); sql_prepare (plugin->dbh, "INSERT INTO membership\n" " (channel_id, slave_id, did_join, announced_at,\n" " effective_since, group_generation)\n" "VALUES ((SELECT id FROM channels WHERE pub_key = ?),\n" " (SELECT id FROM slaves WHERE pub_key = ?),\n" " ?, ?, ?, ?);", &plugin->insert_membership); sql_prepare (plugin->dbh, "SELECT did_join FROM membership\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" " AND slave_id = (SELECT id FROM slaves WHERE pub_key = ?)\n" " AND effective_since <= ? AND did_join = 1\n" "ORDER BY announced_at DESC LIMIT 1;", &plugin->select_membership); sql_prepare (plugin->dbh, "INSERT OR IGNORE INTO messages\n" " (channel_id, hop_counter, signature, purpose,\n" " fragment_id, fragment_offset, message_id,\n" " group_generation, multicast_flags, psycstore_flags, data)\n" "VALUES ((SELECT id FROM channels WHERE pub_key = ?),\n" " ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", &plugin->insert_fragment); sql_prepare (plugin->dbh, "UPDATE messages\n" "SET psycstore_flags = psycstore_flags | ?\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" " AND message_id = ? AND fragment_offset = 0;", &plugin->update_message_flags); sql_prepare (plugin->dbh, "SELECT hop_counter, signature, purpose, fragment_id,\n" " fragment_offset, message_id, group_generation,\n" " multicast_flags, psycstore_flags, data\n" "FROM messages\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" " AND fragment_id = ?;", &plugin->select_fragment); sql_prepare (plugin->dbh, "SELECT hop_counter, signature, purpose, fragment_id,\n" " fragment_offset, message_id, group_generation,\n" " multicast_flags, psycstore_flags, data\n" "FROM messages\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" " AND message_id = ? AND fragment_offset = ?;", &plugin->select_message_fragment); sql_prepare (plugin->dbh, "SELECT hop_counter, signature, purpose, fragment_id,\n" " fragment_offset, message_id, group_generation,\n" " multicast_flags, psycstore_flags, data\n" "FROM messages\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" " AND message_id = ?;", &plugin->select_message); sql_prepare (plugin->dbh, "SELECT fragment_id, message_id, group_generation\n" "FROM messages\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" "ORDER BY fragment_id DESC LIMIT 1;", &plugin->select_counters_message); sql_prepare (plugin->dbh, "SELECT max_state_message_id\n" "FROM channels\n" "WHERE pub_key = ? AND max_state_message_id IS NOT NULL;", &plugin->select_counters_state); sql_prepare (plugin->dbh, "UPDATE channels\n" "SET max_state_message_id = ?\n" "WHERE pub_key = ?;", &plugin->update_max_state_message_id); sql_prepare (plugin->dbh, "UPDATE channels\n" "SET state_hash_message_id = ?\n" "WHERE pub_key = ?;", &plugin->update_state_hash_message_id); sql_prepare (plugin->dbh, "SELECT 1\n" "FROM channels AS c\n" "LEFT JOIN messages AS m\n" "ON c.id = m.channel_id\n" "WHERE c.pub_key = ?\n" " AND ((? < c.state_hash_message_id AND c.state_hash_message_id < ?)\n" " OR (m.message_id = ? AND m.psycstore_flags & ?))\n" "LIMIT 1;", &plugin->select_message_state_delta); sql_prepare (plugin->dbh, "INSERT OR REPLACE INTO state\n" " (channel_id, name, value_current, value_signed)\n" "SELECT new.channel_id, new.name,\n" " new.value_current, old.value_signed\n" "FROM (SELECT (SELECT id FROM channels WHERE pub_key = ?)\n" " AS channel_id,\n" " ? AS name, ? AS value_current) AS new\n" "LEFT JOIN (SELECT channel_id, name, value_signed\n" " FROM state) AS old\n" "ON new.channel_id = old.channel_id AND new.name = old.name;", &plugin->insert_state_current); sql_prepare (plugin->dbh, "DELETE FROM state\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" " AND (value_current IS NULL OR length(value_current) = 0)\n" " AND (value_signed IS NULL OR length(value_signed) = 0);", &plugin->delete_state_empty); sql_prepare (plugin->dbh, "UPDATE state\n" "SET value_signed = value_current\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);", &plugin->update_state_signed); sql_prepare (plugin->dbh, "DELETE FROM state\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);", &plugin->delete_state); sql_prepare (plugin->dbh, "INSERT INTO state_sync (channel_id, name, value)\n" "VALUES ((SELECT id FROM channels WHERE pub_key = ?), ?, ?);", &plugin->insert_state_sync); sql_prepare (plugin->dbh, "INSERT INTO state\n" " (channel_id, name, value_current, value_signed)\n" "SELECT channel_id, name, value, value\n" "FROM state_sync\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);", &plugin->insert_state_from_sync); sql_prepare (plugin->dbh, "DELETE FROM state_sync\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?);", &plugin->delete_state_sync); sql_prepare (plugin->dbh, "SELECT value_current\n" "FROM state\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" " AND name = ?;", &plugin->select_state_one); sql_prepare (plugin->dbh, "SELECT name, value_current\n" "FROM state\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)\n" " AND (name = ? OR name LIKE ?);", &plugin->select_state_prefix); sql_prepare (plugin->dbh, "SELECT name, value_signed\n" "FROM state\n" "WHERE channel_id = (SELECT id FROM channels WHERE pub_key = ?)" " AND value_signed IS NOT NULL;", &plugin->select_state_signed); return GNUNET_OK; } /** * Shutdown database connection and associate data * structures. * @param plugin the plugin context (state for this module) */ static void database_shutdown (struct Plugin *plugin) { int result; sqlite3_stmt *stmt; while (NULL != (stmt = sqlite3_next_stmt (plugin->dbh, NULL))) { result = sqlite3_finalize (stmt); if (SQLITE_OK != result) LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to close statement %p: %d\n", stmt, result); } if (SQLITE_OK != sqlite3_close (plugin->dbh)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); GNUNET_free_non_null (plugin->fn); } /** * Execute a prepared statement with a @a channel_key argument. * * @param plugin Plugin handle. * @param stmt Statement to execute. * @param channel_key Public key of the channel. * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int exec_channel (struct Plugin *plugin, sqlite3_stmt *stmt, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) { if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Begin a transaction. */ static int transaction_begin (struct Plugin *plugin, enum Transactions transaction) { sqlite3_stmt *stmt = plugin->transaction_begin; if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } plugin->transaction = transaction; return GNUNET_OK; } /** * Commit current transaction. */ static int transaction_commit (struct Plugin *plugin) { sqlite3_stmt *stmt = plugin->transaction_commit; if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } plugin->transaction = TRANSACTION_NONE; return GNUNET_OK; } /** * Roll back current transaction. */ static int transaction_rollback (struct Plugin *plugin) { sqlite3_stmt *stmt = plugin->transaction_rollback; if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } plugin->transaction = TRANSACTION_NONE; return GNUNET_OK; } static int channel_key_store (struct Plugin *plugin, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) { sqlite3_stmt *stmt = plugin->insert_channel_key; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return GNUNET_OK; } static int slave_key_store (struct Plugin *plugin, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key) { sqlite3_stmt *stmt = plugin->insert_slave_key; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, slave_key, sizeof (*slave_key), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Store join/leave events for a PSYC channel in order to be able to answer * membership test queries later. * * @see GNUNET_PSYCSTORE_membership_store() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int membership_store (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, int did_join, uint64_t announced_at, uint64_t effective_since, uint64_t group_generation) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->insert_membership; GNUNET_assert (TRANSACTION_NONE == plugin->transaction); if (announced_at > INT64_MAX || effective_since > INT64_MAX || group_generation > INT64_MAX) { GNUNET_break (0); return GNUNET_SYSERR; } if (GNUNET_OK != channel_key_store (plugin, channel_key) || GNUNET_OK != slave_key_store (plugin, slave_key)) return GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_blob (stmt, 2, slave_key, sizeof (*slave_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int (stmt, 3, did_join) || SQLITE_OK != sqlite3_bind_int64 (stmt, 4, announced_at) || SQLITE_OK != sqlite3_bind_int64 (stmt, 5, effective_since) || SQLITE_OK != sqlite3_bind_int64 (stmt, 6, group_generation)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Test if a member was admitted to the channel at the given message ID. * * @see GNUNET_PSYCSTORE_membership_test() * * @return #GNUNET_YES if the member was admitted, #GNUNET_NO if not, * #GNUNET_SYSERR if there was en error. */ static int membership_test (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t message_id) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->select_membership; int ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_blob (stmt, 2, slave_key, sizeof (*slave_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_id)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = GNUNET_NO; break; case SQLITE_ROW: ret = GNUNET_YES; } } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Store a message fragment sent to a channel. * * @see GNUNET_PSYCSTORE_fragment_store() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int fragment_store (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_MULTICAST_MessageHeader *msg, uint32_t psycstore_flags) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->insert_fragment; GNUNET_assert (TRANSACTION_NONE == plugin->transaction); uint64_t fragment_id = GNUNET_ntohll (msg->fragment_id); uint64_t fragment_offset = GNUNET_ntohll (msg->fragment_offset); uint64_t message_id = GNUNET_ntohll (msg->message_id); uint64_t group_generation = GNUNET_ntohll (msg->group_generation); if (fragment_id > INT64_MAX || fragment_offset > INT64_MAX || message_id > INT64_MAX || group_generation > INT64_MAX) { LOG (GNUNET_ERROR_TYPE_ERROR, "Tried to store fragment with a field > INT64_MAX: " "%lu, %lu, %lu, %lu\n", fragment_id, fragment_offset, message_id, group_generation); GNUNET_break (0); return GNUNET_SYSERR; } if (GNUNET_OK != channel_key_store (plugin, channel_key)) return GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, ntohl (msg->hop_counter) ) || SQLITE_OK != sqlite3_bind_blob (stmt, 3, (const void *) &msg->signature, sizeof (msg->signature), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_blob (stmt, 4, (const void *) &msg->purpose, sizeof (msg->purpose), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int64 (stmt, 5, fragment_id) || SQLITE_OK != sqlite3_bind_int64 (stmt, 6, fragment_offset) || SQLITE_OK != sqlite3_bind_int64 (stmt, 7, message_id) || SQLITE_OK != sqlite3_bind_int64 (stmt, 8, group_generation) || SQLITE_OK != sqlite3_bind_int64 (stmt, 9, ntohl (msg->flags)) || SQLITE_OK != sqlite3_bind_int64 (stmt, 10, psycstore_flags) || SQLITE_OK != sqlite3_bind_blob (stmt, 11, (const void *) &msg[1], ntohs (msg->header.size) - sizeof (*msg), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Set additional flags for a given message. * * They are OR'd with any existing flags set. * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int message_add_flags (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t psycstore_flags) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->update_message_flags; int ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, psycstore_flags) || SQLITE_OK != sqlite3_bind_blob (stmt, 2, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_id)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = sqlite3_total_changes (plugin->dbh) > 0 ? GNUNET_OK : GNUNET_NO; break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return ret; } static int fragment_row (sqlite3_stmt *stmt, GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls) { int data_size = sqlite3_column_bytes (stmt, 9); struct GNUNET_MULTICAST_MessageHeader *msg = GNUNET_malloc (sizeof (*msg) + data_size); msg->header.size = htons (sizeof (*msg) + data_size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE); msg->hop_counter = htonl ((uint32_t) sqlite3_column_int64 (stmt, 0)); memcpy (&msg->signature, sqlite3_column_blob (stmt, 1), sqlite3_column_bytes (stmt, 1)); memcpy (&msg->purpose, sqlite3_column_blob (stmt, 2), sqlite3_column_bytes (stmt, 2)); msg->fragment_id = GNUNET_htonll (sqlite3_column_int64 (stmt, 3)); msg->fragment_offset = GNUNET_htonll (sqlite3_column_int64 (stmt, 4)); msg->message_id = GNUNET_htonll (sqlite3_column_int64 (stmt, 5)); msg->group_generation = GNUNET_htonll (sqlite3_column_int64 (stmt, 6)); msg->flags = htonl (sqlite3_column_int64 (stmt, 7)); memcpy (&msg[1], sqlite3_column_blob (stmt, 9), data_size); return cb (cb_cls, (void *) msg, sqlite3_column_int64 (stmt, 8)); } /** * Retrieve a message fragment by fragment ID. * * @see GNUNET_PSYCSTORE_fragment_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int fragment_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t fragment_id, GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->select_fragment; int ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, fragment_id)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = GNUNET_NO; break; case SQLITE_ROW: ret = fragment_row (stmt, cb, cb_cls); break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Retrieve all fragments of a message. * * @see GNUNET_PSYCSTORE_message_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int message_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t *returned_fragments, GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->select_message; int ret = GNUNET_SYSERR; *returned_fragments = 0; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, message_id)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { int sql_ret; do { sql_ret = sqlite3_step (stmt); switch (sql_ret) { case SQLITE_DONE: if (ret != GNUNET_OK) ret = GNUNET_NO; break; case SQLITE_ROW: ret = fragment_row (stmt, cb, cb_cls); (*returned_fragments)++; if (ret != GNUNET_YES) sql_ret = SQLITE_DONE; break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } while (sql_ret == SQLITE_ROW); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Retrieve a fragment of message specified by its message ID and fragment * offset. * * @see GNUNET_PSYCSTORE_message_get_fragment() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int message_get_fragment (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t fragment_offset, GNUNET_PSYCSTORE_FragmentCallback cb, void *cb_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->select_message_fragment; int ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, message_id) || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, fragment_offset)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = GNUNET_NO; break; case SQLITE_ROW: ret = fragment_row (stmt, cb, cb_cls); break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Retrieve the max. values of message counters for a channel. * * @see GNUNET_PSYCSTORE_counters_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int counters_message_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t *max_fragment_id, uint64_t *max_message_id, uint64_t *max_group_generation) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->select_counters_message; int ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = GNUNET_NO; break; case SQLITE_ROW: *max_fragment_id = sqlite3_column_int64 (stmt, 0); *max_message_id = sqlite3_column_int64 (stmt, 1); *max_group_generation = sqlite3_column_int64 (stmt, 2); ret = GNUNET_OK; break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Retrieve the max. values of state counters for a channel. * * @see GNUNET_PSYCSTORE_counters_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int counters_state_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t *max_state_message_id) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->select_counters_state; int ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = GNUNET_NO; break; case SQLITE_ROW: *max_state_message_id = sqlite3_column_int64 (stmt, 0); ret = GNUNET_OK; break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Set a state variable to the given value. * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int state_set (struct Plugin *plugin, sqlite3_stmt *stmt, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, const void *value, size_t value_size) { int ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_text (stmt, 2, name, -1, SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_blob (stmt, 3, value, value_size, SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = 0 < sqlite3_total_changes (plugin->dbh) ? GNUNET_OK : GNUNET_NO; break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return ret; } static int update_message_id (struct Plugin *plugin, sqlite3_stmt *stmt, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id) { if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, message_id) || SQLITE_OK != sqlite3_bind_blob (stmt, 2, channel_key, sizeof (*channel_key), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else if (SQLITE_DONE != sqlite3_step (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Begin modifying current state. */ static int state_modify_begin (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t state_delta) { struct Plugin *plugin = cls; sqlite3_stmt *stmt = plugin->select_message_state_delta; if (state_delta > 0) { int ret = GNUNET_SYSERR; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_int64 (stmt, 2, message_id - state_delta) || SQLITE_OK != sqlite3_bind_int64 (stmt, 3, message_id) || SQLITE_OK != sqlite3_bind_int64 (stmt, 4, message_id - state_delta) || SQLITE_OK != sqlite3_bind_int64 (stmt, 5, GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = GNUNET_NO; break; case SQLITE_ROW: ret = GNUNET_OK; break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } if (SQLITE_OK != sqlite3_reset (stmt)) { ret = GNUNET_SYSERR; LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } if (GNUNET_OK != ret) return ret; } if (TRANSACTION_NONE != plugin->transaction) if (GNUNET_OK != transaction_rollback (plugin)) return GNUNET_SYSERR; return transaction_begin (plugin, TRANSACTION_STATE_MODIFY); } /** * Set the current value of state variable. * * @see GNUNET_PSYCSTORE_state_modify() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int state_modify_set (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, const void *value, size_t value_size) { struct Plugin *plugin = cls; GNUNET_assert (TRANSACTION_STATE_MODIFY == plugin->transaction); return state_set (plugin, plugin->insert_state_current, channel_key, name, value, value_size); } /** * End modifying current state. */ static int state_modify_end (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id) { struct Plugin *plugin = cls; GNUNET_assert (TRANSACTION_STATE_MODIFY == plugin->transaction); return GNUNET_OK == exec_channel (plugin, plugin->delete_state_empty, channel_key) && GNUNET_OK == update_message_id (plugin, plugin->update_max_state_message_id, channel_key, message_id) && GNUNET_OK == transaction_commit (plugin) ? GNUNET_OK : GNUNET_SYSERR; } /** * Begin state synchronization. */ static int state_sync_begin (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) { struct Plugin *plugin = cls; return exec_channel (plugin, plugin->delete_state_sync, channel_key); } /** * Set the current value of state variable. * * @see GNUNET_PSYCSTORE_state_modify() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int state_sync_set (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, const void *value, size_t value_size) { struct Plugin *plugin = cls; return state_set (cls, plugin->insert_state_sync, channel_key, name, value, value_size); } /** * End modifying current state. */ static int state_sync_end (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id) { struct Plugin *plugin = cls; int ret = GNUNET_SYSERR; GNUNET_OK == transaction_begin (plugin, TRANSACTION_NONE) && GNUNET_OK == exec_channel (plugin, plugin->delete_state, channel_key) && GNUNET_OK == exec_channel (plugin, plugin->insert_state_from_sync, channel_key) && GNUNET_OK == exec_channel (plugin, plugin->delete_state_sync, channel_key) && GNUNET_OK == update_message_id (plugin, plugin->update_state_hash_message_id, channel_key, message_id) && GNUNET_OK == transaction_commit (plugin) ? ret = GNUNET_OK : transaction_rollback (plugin); return ret; } /** * Reset the state of a channel. * * @see GNUNET_PSYCSTORE_state_reset() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int state_reset (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) { struct Plugin *plugin = cls; return exec_channel (plugin, plugin->delete_state, channel_key); } /** * Update signed values of state variables in the state store. * * @see GNUNET_PSYCSTORE_state_hash_update() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int state_update_signed (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key) { struct Plugin *plugin = cls; return exec_channel (plugin, plugin->update_state_signed, channel_key); } /** * Retrieve a state variable by name. * * @see GNUNET_PSYCSTORE_state_get() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int state_get (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls) { struct Plugin *plugin = cls; int ret = GNUNET_SYSERR; sqlite3_stmt *stmt = plugin->select_state_one; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_text (stmt, 2, name, -1, SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { switch (sqlite3_step (stmt)) { case SQLITE_DONE: ret = GNUNET_NO; break; case SQLITE_ROW: ret = cb (cb_cls, name, sqlite3_column_blob (stmt, 0), sqlite3_column_bytes (stmt, 0)); break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Retrieve all state variables for a channel with the given prefix. * * @see GNUNET_PSYCSTORE_state_get_prefix() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int state_get_prefix (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls) { struct Plugin *plugin = cls; int ret = GNUNET_SYSERR; sqlite3_stmt *stmt = plugin->select_state_prefix; size_t name_len = strlen (name); char *name_prefix = GNUNET_malloc (name_len + 2); memcpy (name_prefix, name, name_len); memcpy (name_prefix + name_len, "_%", 2); if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_text (stmt, 2, name, name_len, SQLITE_STATIC) || SQLITE_OK != sqlite3_bind_text (stmt, 3, name_prefix, name_len + 2, SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { int sql_ret; do { sql_ret = sqlite3_step (stmt); switch (sql_ret) { case SQLITE_DONE: if (ret != GNUNET_OK) ret = GNUNET_NO; break; case SQLITE_ROW: ret = cb (cb_cls, (const char *) sqlite3_column_text (stmt, 0), sqlite3_column_blob (stmt, 1), sqlite3_column_bytes (stmt, 1)); if (ret != GNUNET_YES) sql_ret = SQLITE_DONE; break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } while (sql_ret == SQLITE_ROW); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Retrieve all signed state variables for a channel. * * @see GNUNET_PSYCSTORE_state_get_signed() * * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int state_get_signed (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, GNUNET_PSYCSTORE_StateCallback cb, void *cb_cls) { struct Plugin *plugin = cls; int ret = GNUNET_SYSERR; sqlite3_stmt *stmt = plugin->select_state_signed; if (SQLITE_OK != sqlite3_bind_blob (stmt, 1, channel_key, sizeof (*channel_key), SQLITE_STATIC)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind"); } else { int sql_ret; do { sql_ret = sqlite3_step (stmt); switch (sql_ret) { case SQLITE_DONE: if (ret != GNUNET_OK) ret = GNUNET_NO; break; case SQLITE_ROW: ret = cb (cb_cls, (const char *) sqlite3_column_text (stmt, 0), sqlite3_column_blob (stmt, 1), sqlite3_column_bytes (stmt, 1)); if (ret != GNUNET_YES) sql_ret = SQLITE_DONE; break; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); } } while (sql_ret == SQLITE_ROW); } if (SQLITE_OK != sqlite3_reset (stmt)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } return ret; } /** * Entry point for the plugin. * * @param cls The struct GNUNET_CONFIGURATION_Handle. * @return NULL on error, otherwise the plugin context */ void * libgnunet_plugin_psycstore_sqlite_init (void *cls) { static struct Plugin plugin; const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_PSYCSTORE_PluginFunctions *api; if (NULL != plugin.cfg) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); plugin.cfg = cfg; if (GNUNET_OK != database_setup (&plugin)) { database_shutdown (&plugin); return NULL; } api = GNUNET_new (struct GNUNET_PSYCSTORE_PluginFunctions); api->cls = &plugin; api->membership_store = &membership_store; api->membership_test = &membership_test; api->fragment_store = &fragment_store; api->message_add_flags = &message_add_flags; api->fragment_get = &fragment_get; api->message_get = &message_get; api->message_get_fragment = &message_get_fragment; api->counters_message_get = &counters_message_get; api->counters_state_get = &counters_state_get; api->state_modify_begin = &state_modify_begin; api->state_modify_set = &state_modify_set; api->state_modify_end = &state_modify_end; api->state_sync_begin = &state_sync_begin; api->state_sync_set = &state_sync_set; api->state_sync_end = &state_sync_end; api->state_reset = &state_reset; api->state_update_signed = &state_update_signed; api->state_get = &state_get; api->state_get_prefix = &state_get_prefix; api->state_get_signed = &state_get_signed; LOG (GNUNET_ERROR_TYPE_INFO, _("SQLite database running\n")); return api; } /** * Exit point from the plugin. * * @param cls The plugin context (as returned by "init") * @return Always NULL */ void * libgnunet_plugin_psycstore_sqlite_done (void *cls) { struct GNUNET_PSYCSTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; database_shutdown (plugin); plugin->cfg = NULL; GNUNET_free (api); LOG (GNUNET_ERROR_TYPE_DEBUG, "SQLite plugin is finished\n"); return NULL; } /* end of plugin_psycstore_sqlite.c */ gnunet-0.10.1/src/psycstore/test_psycstore.c0000644000175000017500000003632012225777502016107 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psycstore/test_psycstore.c * @brief Test for the PSYCstore service. * @author Gabor X Toth * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_common.h" #include "gnunet_testing_lib.h" #include "gnunet_psycstore_service.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) #define DEBUG_SERVICE 0 /** * Return value from 'main'. */ static int res; /** * Handle to PSYCstore service. */ static struct GNUNET_PSYCSTORE_Handle *h; /** * Handle to PSYCstore operation. */ static struct GNUNET_PSYCSTORE_OperationHandle *op; /** * Handle for task for timeout termination. */ static GNUNET_SCHEDULER_TaskIdentifier end_badly_task; static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key; static struct GNUNET_CRYPTO_EddsaPrivateKey *slave_key; static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key; static struct GNUNET_CRYPTO_EddsaPublicKey slave_pub_key; static struct FragmentClosure { uint8_t n; uint8_t n_expected; uint64_t flags[16]; struct GNUNET_MULTICAST_MessageHeader *msg[16]; } fcls; struct StateClosure { size_t n; char *name[16]; void *value[16]; size_t value_size[16]; } scls; static struct GNUNET_ENV_Modifier modifiers[16]; /** * Clean up all resources used. */ static void cleanup () { if (NULL != op) { GNUNET_PSYCSTORE_operation_cancel (op); op = NULL; } if (NULL != h) { GNUNET_PSYCSTORE_disconnect (h); h = NULL; } if (NULL != channel_key) { GNUNET_free (channel_key); channel_key = NULL; } if (NULL != slave_key) { GNUNET_free (slave_key); slave_key = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Terminate the testcase (failure). * * @param cls NULL * @param tc scheduler context */ static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { res = 1; cleanup (); } /** * Terminate the testcase (success). * * @param cls NULL * @param tc scheduler context */ static void end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { res = 0; cleanup (); } /** * Finish the testcase (successfully). */ static void end () { if (end_badly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (end_badly_task); end_badly_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &end_normally, NULL); } void state_reset_result (void *cls, int64_t result, const char *err_msg) { op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_reset_result:\t%d\n", result); GNUNET_assert (GNUNET_OK == result); op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key, &state_reset_result, cls); GNUNET_PSYCSTORE_operation_cancel (op); op = NULL; end (); } static int state_result (void *cls, const char *name, const void *value, size_t value_size) { struct StateClosure *scls = cls; const char *nam = scls->name[scls->n]; const void *val = scls->value[scls->n]; size_t val_size = scls->value_size[scls->n++]; if (value_size == val_size && 0 == memcmp (value, val, val_size) && 0 == strcmp (name, nam)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " variable %s matches\n", name); return GNUNET_YES; } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " variable %s differs\nReceived: %.*s\nExpected: %.*s\n", name, value_size, value, val_size, val); GNUNET_assert (0); return GNUNET_SYSERR; } } void state_get_prefix_result (void *cls, int64_t result, const char *err_msg) { struct StateClosure *scls = cls; op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_prefix_result:\t%d\n", result); GNUNET_assert (GNUNET_OK == result && 2 == scls->n); op = GNUNET_PSYCSTORE_state_reset (h, &channel_pub_key, &state_reset_result, cls); } void state_get_result (void *cls, int64_t result, const char *err_msg) { op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_get_result:\t%d\n", result); GNUNET_assert (GNUNET_OK == result); scls.n = 0; scls.name[0] = "_sync_bar"; scls.value[0] = "ten eleven twelve"; scls.value_size[0] = sizeof ("ten eleven twelve") - 1; scls.name[1] = "_sync_foo"; scls.value[1] = "one two three"; scls.value_size[1] = sizeof ("one two three") - 1; op = GNUNET_PSYCSTORE_state_get_prefix (h, &channel_pub_key, "_sync", &state_result, &state_get_prefix_result, &scls); } void counters_result (void *cls, int status, uint64_t max_fragment_id, uint64_t max_message_id, uint64_t max_group_generation, uint64_t max_state_message_id) { struct FragmentClosure *fcls = cls; int result = 0; op = NULL; if (GNUNET_OK == status && max_fragment_id == GNUNET_ntohll (fcls->msg[2]->fragment_id) && max_message_id == GNUNET_ntohll (fcls->msg[2]->message_id) && max_group_generation == GNUNET_ntohll (fcls->msg[2]->group_generation) && max_state_message_id == GNUNET_ntohll (fcls->msg[0]->message_id)) result = 1; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "counters_get:\t%d\n", result); GNUNET_assert (result == 1); scls.n = 0; scls.name[0] = "_bar"; scls.value[0] = "four five six"; scls.value_size[0] = sizeof ("four five six") - 1; op = GNUNET_PSYCSTORE_state_get (h, &channel_pub_key, "_bar_x_yy_zzz", &state_result, &state_get_result, &scls); } void state_modify_result (void *cls, int64_t result, const char *err_msg) { op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_modify_result:\t%d\n", result); GNUNET_assert (GNUNET_OK == result); op = GNUNET_PSYCSTORE_counters_get (h, &channel_pub_key, &counters_result, cls); } void state_sync_result (void *cls, int64_t result, const char *err_msg) { struct FragmentClosure *fcls = cls; op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "state_sync_result:\t%d\n", result); GNUNET_assert (GNUNET_OK == result); modifiers[0] = (struct GNUNET_ENV_Modifier) { .oper = '=', .name = "_sync_foo", .value = "one two three", .value_size = sizeof ("one two three") - 1 }; modifiers[1] = (struct GNUNET_ENV_Modifier) { .oper = '=', .name = "_bar", .value = "four five six", .value_size = sizeof ("four five six") - 1 }; op = GNUNET_PSYCSTORE_state_modify (h, &channel_pub_key, GNUNET_ntohll (fcls->msg[0]->message_id), 0, 2, modifiers, state_modify_result, fcls); } int fragment_result (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg, enum GNUNET_PSYCSTORE_MessageFlags flags) { struct FragmentClosure *fcls = cls; struct GNUNET_MULTICAST_MessageHeader *msg0 = fcls->msg[fcls->n]; uint64_t flags0 = fcls->flags[fcls->n++]; if (flags == flags0 && msg->header.size == msg0->header.size && 0 == memcmp (msg, msg0, ntohs (msg->header.size))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " fragment %llu matches\n", GNUNET_ntohll (msg->fragment_id)); return GNUNET_YES; } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " fragment %llu differs\n", GNUNET_ntohll (msg->fragment_id)); GNUNET_assert (0); return GNUNET_SYSERR; } } void message_get_result (void *cls, int64_t result, const char *err_msg) { struct FragmentClosure *fcls = cls; op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get:\t%d\n", result); GNUNET_assert (result > 0 && fcls->n && fcls->n_expected); modifiers[0] = (struct GNUNET_ENV_Modifier) { .oper = '=', .name = "_sync_foo", .value = "three two one", .value_size = sizeof ("three two one") - 1 }; modifiers[1] = (struct GNUNET_ENV_Modifier) { .oper = '=', .name = "_sync_bar", .value = "ten eleven twelve", .value_size = sizeof ("ten eleven twelve") - 1 }; op = GNUNET_PSYCSTORE_state_sync (h, &channel_pub_key, GNUNET_ntohll (fcls->msg[0]->message_id) + 1, 2, modifiers, state_sync_result, fcls); } void message_get_fragment_result (void *cls, int64_t result, const char *err_msg) { struct FragmentClosure *fcls = cls; op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "message_get_fragment:\t%d\n", result); GNUNET_assert (result > 0 && fcls->n && fcls->n_expected); fcls->n = 0; fcls->n_expected = 3; op = GNUNET_PSYCSTORE_message_get (h, &channel_pub_key, GNUNET_ntohll (fcls->msg[0]->message_id), &fragment_result, &message_get_result, fcls); } void fragment_get_result (void *cls, int64_t result, const char *err_msg) { struct FragmentClosure *fcls = cls; op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_get:\t%d\n", result); GNUNET_assert (result > 0 && fcls->n && fcls->n_expected); fcls->n = 1; fcls->n_expected = 2; op = GNUNET_PSYCSTORE_message_get_fragment (h, &channel_pub_key, GNUNET_ntohll (fcls->msg[1]->message_id), GNUNET_ntohll (fcls->msg[1]->fragment_offset), &fragment_result, &message_get_fragment_result, fcls); } void fragment_store_result (void *cls, int64_t result, const char *err_msg) { op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "fragment_store:\t%d\n", result); GNUNET_assert (GNUNET_OK == result); if ((intptr_t) cls == GNUNET_YES) { fcls.n = 0; fcls.n_expected = 1; op = GNUNET_PSYCSTORE_fragment_get (h, &channel_pub_key, GNUNET_ntohll (fcls.msg[0]->fragment_id), &fragment_result, &fragment_get_result, &fcls); } } void membership_test_result (void *cls, int64_t result, const char *err_msg) { op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_test:\t%d\n", result); GNUNET_assert (GNUNET_OK == result); struct GNUNET_MULTICAST_MessageHeader *msg; fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE; fcls.msg[0] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key)); GNUNET_assert (msg != NULL); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE); msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key)); msg->hop_counter = htonl (9); msg->fragment_id = GNUNET_htonll (INT64_MAX - 8); msg->fragment_offset = GNUNET_htonll (0); msg->message_id = GNUNET_htonll (INT64_MAX - 10); msg->group_generation = GNUNET_htonll (INT64_MAX - 3); msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT); memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key)); msg->purpose.size = htonl (ntohs (msg->header.size) - sizeof (msg->header) - sizeof (msg->hop_counter) - sizeof (msg->signature)); msg->purpose.purpose = htonl (234); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (slave_key, &msg->purpose, &msg->signature)); op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[0], &fragment_store_result, GNUNET_NO); fcls.flags[1] = GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED; fcls.msg[1] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key)); memcpy (msg, fcls.msg[0], sizeof (*msg) + sizeof (channel_pub_key)); msg->fragment_id = GNUNET_htonll (INT64_MAX - 4); msg->fragment_offset = GNUNET_htonll (1024); op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[1], &fragment_store_result, GNUNET_NO); fcls.flags[2] = GNUNET_PSYCSTORE_MESSAGE_STATE_HASH; fcls.msg[2] = msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key)); memcpy (msg, fcls.msg[1], sizeof (*msg) + sizeof (channel_pub_key)); msg->fragment_id = GNUNET_htonll (INT64_MAX); msg->fragment_offset = GNUNET_htonll (16384); op = GNUNET_PSYCSTORE_fragment_store (h, &channel_pub_key, msg, fcls.flags[2], &fragment_store_result, (void *) GNUNET_YES); } void membership_store_result (void *cls, int64_t result, const char *err_msg) { op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "membership_store:\t%d\n", result); GNUNET_assert (GNUNET_OK == result); op = GNUNET_PSYCSTORE_membership_test (h, &channel_pub_key, &slave_pub_key, 4, 1, &membership_test_result, NULL); } /** * Main function of the test, run from scheduler. * * @param cls NULL * @param cfg configuration we use (also to connect to PSYCstore service) * @param peer handle to access more of the peer (not used) */ static void #if DEBUG_SERVICE run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) #else run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) #endif { end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); h = GNUNET_PSYCSTORE_connect (cfg); GNUNET_assert (NULL != h); channel_key = GNUNET_CRYPTO_eddsa_key_create (); slave_key = GNUNET_CRYPTO_eddsa_key_create (); GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key); GNUNET_CRYPTO_eddsa_key_get_public (slave_key, &slave_pub_key); op = GNUNET_PSYCSTORE_membership_store (h, &channel_pub_key, &slave_pub_key, GNUNET_YES, 4, 2, 1, &membership_store_result, NULL); } int main (int argc, char *argv[]) { res = 1; #if DEBUG_SERVICE const struct GNUNET_GETOPT_CommandLineOption opts[] = { GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psycstore", "test-psycstore [options]", opts, &run, NULL)) return 1; #else if (0 != GNUNET_TESTING_service_run ("test-psycstore", "psycstore", "test_psycstore.conf", &run, NULL)) return 1; #endif return res; } /* end of test_psycstore.c */ gnunet-0.10.1/src/psycstore/test_plugin_psycstore.c0000644000175000017500000003512112225777502017463 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * @file psycstore/test_plugin_psycstore.c * @brief Test for the PSYCstore plugins. * @author Gabor X Toth * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_psycstore_plugin.h" #include "gnunet_psycstore_service.h" #include "gnunet_multicast_service.h" #define DEBUG_PSYCSTORE GNUNET_EXTRA_LOGGING #if DEBUG_PSYCSTORE # define LOG_LEVEL "DEBUG" #else # define LOG_LEVEL "WARNING" #endif #define C2ARG(str) str, (sizeof (str) - 1) #define LOG(kind,...) \ GNUNET_log_from (kind, "test-plugin-psycstore", __VA_ARGS__) static int ok; /** * Name of plugin under test. */ static const char *plugin_name; static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key; static struct GNUNET_CRYPTO_EddsaPrivateKey *slave_key; static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key; static struct GNUNET_CRYPTO_EddsaPublicKey slave_pub_key; /** * Function called when the service shuts down. Unloads our psycstore * plugin. * * @param api api to unload */ static void unload_plugin (struct GNUNET_PSYCSTORE_PluginFunctions *api) { char *libname; GNUNET_asprintf (&libname, "libgnunet_plugin_psycstore_%s", plugin_name); GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api)); GNUNET_free (libname); } /** * Load the psycstore plugin. * * @param cfg configuration to pass * @return NULL on error */ static struct GNUNET_PSYCSTORE_PluginFunctions * load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_PSYCSTORE_PluginFunctions *ret; char *libname; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' psycstore plugin\n"), plugin_name); GNUNET_asprintf (&libname, "libgnunet_plugin_psycstore_%s", plugin_name); if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void*) cfg))) { FPRINTF (stderr, "Failed to load plugin `%s'!\n", plugin_name); return NULL; } GNUNET_free (libname); return ret; } struct FragmentClosure { uint8_t n; uint64_t flags[16]; struct GNUNET_MULTICAST_MessageHeader *msg[16]; }; static int fragment_cb (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg2, enum GNUNET_PSYCSTORE_MessageFlags flags) { struct FragmentClosure *fcls = cls; struct GNUNET_MULTICAST_MessageHeader *msg1 = fcls->msg[fcls->n]; uint64_t flags1 = fcls->flags[fcls->n++]; int ret; if (flags1 == flags && msg1->header.size == msg2->header.size && 0 == memcmp (msg1, msg2, ntohs (msg1->header.size))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Fragment %llu matches\n", GNUNET_ntohll (msg1->fragment_id)); ret = GNUNET_YES; } else { LOG (GNUNET_ERROR_TYPE_ERROR, "Fragment %llu differs\n", GNUNET_ntohll (msg1->fragment_id)); ret = GNUNET_SYSERR; } GNUNET_free (msg2); return ret; } struct StateClosure { size_t n; char *name[16]; void *value[16]; size_t value_size[16]; }; static int state_cb (void *cls, const char *name, const void *value, size_t value_size) { struct StateClosure *scls = cls; const void *val = scls->value[scls->n]; size_t val_size = scls->value_size[scls->n++]; /* FIXME: check name */ return value_size == val_size && 0 == memcmp (value, val, val_size) ? GNUNET_YES : GNUNET_SYSERR; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_PSYCSTORE_PluginFunctions *db; ok = 1; db = load_plugin (cfg); if (NULL == db) { FPRINTF (stderr, "%s", "Failed to initialize PSYCstore. " "Database likely not setup, skipping test.\n"); return; } /* Store & test membership */ channel_key = GNUNET_CRYPTO_eddsa_key_create (); slave_key = GNUNET_CRYPTO_eddsa_key_create (); GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key); GNUNET_CRYPTO_eddsa_key_get_public (slave_key, &slave_pub_key); GNUNET_assert (GNUNET_OK == db->membership_store (db->cls, &channel_pub_key, &slave_pub_key, GNUNET_YES, 4, 2, 1)); GNUNET_assert (GNUNET_YES == db->membership_test (db->cls, &channel_pub_key, &slave_pub_key, 4)); GNUNET_assert (GNUNET_YES == db->membership_test (db->cls, &channel_pub_key, &slave_pub_key, 2)); GNUNET_assert (GNUNET_NO == db->membership_test (db->cls, &channel_pub_key, &slave_pub_key, 1)); /* Store & get messages */ struct GNUNET_MULTICAST_MessageHeader *msg = GNUNET_malloc (sizeof (*msg) + sizeof (channel_pub_key)); GNUNET_assert (msg != NULL); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE); msg->header.size = htons (sizeof (*msg) + sizeof (channel_pub_key)); msg->hop_counter = htonl (9); msg->fragment_id = GNUNET_htonll (INT64_MAX - 1); msg->fragment_offset = GNUNET_htonll (0); msg->message_id = GNUNET_htonll (INT64_MAX - 10); msg->group_generation = GNUNET_htonll (INT64_MAX - 3); msg->flags = htonl (GNUNET_MULTICAST_MESSAGE_LAST_FRAGMENT); memcpy (&msg[1], &channel_pub_key, sizeof (channel_pub_key)); msg->purpose.size = htonl (ntohs (msg->header.size) - sizeof (msg->header) - sizeof (msg->hop_counter) - sizeof (msg->signature)); msg->purpose.purpose = htonl (234); GNUNET_CRYPTO_eddsa_sign (slave_key, &msg->purpose, &msg->signature); struct FragmentClosure fcls = { 0 }; fcls.n = 0; fcls.msg[0] = msg; fcls.flags[0] = GNUNET_PSYCSTORE_MESSAGE_STATE; GNUNET_assert (GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg, fcls.flags[0])); GNUNET_assert (GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key, GNUNET_ntohll (msg->fragment_id), fragment_cb, &fcls)); GNUNET_assert (fcls.n == 1); fcls.n = 0; GNUNET_assert ( GNUNET_OK == db->message_get_fragment (db->cls, &channel_pub_key, GNUNET_ntohll (msg->message_id), GNUNET_ntohll (msg->fragment_offset), fragment_cb, &fcls)); GNUNET_assert (fcls.n == 1); GNUNET_assert ( GNUNET_OK == db->message_add_flags (db->cls, &channel_pub_key, GNUNET_ntohll (msg->message_id), GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED)); fcls.n = 0; fcls.flags[0] |= GNUNET_PSYCSTORE_MESSAGE_STATE_APPLIED; GNUNET_assert (GNUNET_OK == db->fragment_get (db->cls, &channel_pub_key, GNUNET_ntohll (msg->fragment_id), fragment_cb, &fcls)); GNUNET_assert (fcls.n == 1); struct GNUNET_MULTICAST_MessageHeader *msg1 = GNUNET_malloc (sizeof (*msg1) + sizeof (channel_pub_key)); memcpy (msg1, msg, sizeof (*msg1) + sizeof (channel_pub_key)); msg1->fragment_id = GNUNET_htonll (INT64_MAX); msg1->fragment_offset = GNUNET_htonll (32768); fcls.n = 0; fcls.msg[1] = msg1; fcls.flags[1] = GNUNET_PSYCSTORE_MESSAGE_STATE_HASH; GNUNET_assert (GNUNET_OK == db->fragment_store (db->cls, &channel_pub_key, msg1, fcls.flags[1])); uint64_t retfrags = 0; GNUNET_assert (GNUNET_OK == db->message_get (db->cls, &channel_pub_key, GNUNET_ntohll (msg->message_id), &retfrags, fragment_cb, &fcls)); GNUNET_assert (fcls.n == 2 && retfrags == 2); /* Message counters */ uint64_t fragment_id = 0, message_id = 0, group_generation = 0; GNUNET_assert ( GNUNET_OK == db->counters_message_get (db->cls, &channel_pub_key, &fragment_id, &message_id, &group_generation) && fragment_id == GNUNET_ntohll (msg1->fragment_id) && message_id == GNUNET_ntohll (msg1->message_id) && group_generation == GNUNET_ntohll (msg1->group_generation)); /* Modify state */ message_id = GNUNET_ntohll (fcls.msg[0]->message_id) + 1; GNUNET_assert (GNUNET_OK == db->state_modify_begin (db->cls, &channel_pub_key, message_id, 1)); GNUNET_assert (GNUNET_OK == db->state_modify_set (db->cls, &channel_pub_key, "_foo", C2ARG("one two three"))); GNUNET_assert (GNUNET_OK == db->state_modify_set (db->cls, &channel_pub_key, "_foo_bar", slave_key, sizeof (*slave_key))); GNUNET_assert (GNUNET_OK == db->state_modify_end (db->cls, &channel_pub_key, message_id)); struct StateClosure scls = { 0 }; scls.n = 0; scls.value[0] = "one two three"; scls.value_size[0] = strlen ("one two three"); GNUNET_assert (GNUNET_OK == db->state_get (db->cls, &channel_pub_key, "_foo", state_cb, &scls)); GNUNET_assert (scls.n == 1); scls.n = 0; scls.value[1] = slave_key; scls.value_size[1] = sizeof (*slave_key); GNUNET_assert (GNUNET_OK == db->state_get_prefix (db->cls, &channel_pub_key, "_foo", state_cb, &scls)); GNUNET_assert (scls.n == 2); scls.n = 0; GNUNET_assert (GNUNET_NO == db->state_get_signed (db->cls, &channel_pub_key, state_cb, &scls)); GNUNET_assert (scls.n == 0); GNUNET_assert (GNUNET_OK == db->state_update_signed (db->cls, &channel_pub_key)); scls.n = 0; GNUNET_assert (GNUNET_YES == db->state_get_signed (db->cls, &channel_pub_key, state_cb, &scls)); GNUNET_assert (scls.n == 2); /* State counters */ uint64_t max_state_msg_id = 0; GNUNET_assert (GNUNET_OK == db->counters_state_get (db->cls, &channel_pub_key, &max_state_msg_id) && max_state_msg_id == message_id); /* State sync */ scls.n = 0; scls.value[0] = channel_key; scls.value_size[0] = sizeof (*channel_key); scls.value[1] = "three two one"; scls.value_size[1] = strlen ("three two one"); GNUNET_assert (GNUNET_OK == db->state_sync_begin (db->cls, &channel_pub_key)); GNUNET_assert (GNUNET_OK == db->state_sync_set (db->cls, &channel_pub_key, "_sync_bar", scls.value[0], scls.value_size[0])); GNUNET_assert (GNUNET_OK == db->state_sync_set (db->cls, &channel_pub_key, "_sync_foo", scls.value[1], scls.value_size[1])); GNUNET_assert (GNUNET_OK == db->state_sync_end (db->cls, &channel_pub_key, INT64_MAX - 5)); GNUNET_assert (GNUNET_NO == db->state_get_prefix (db->cls, &channel_pub_key, "_foo", state_cb, &scls)); GNUNET_assert (scls.n == 0); GNUNET_assert (GNUNET_OK == db->state_get_prefix (db->cls, &channel_pub_key, "_sync", state_cb, &scls)); GNUNET_assert (scls.n == 2); scls.n = 0; GNUNET_assert (GNUNET_OK == db->state_get_signed (db->cls, &channel_pub_key, state_cb, &scls)); GNUNET_assert (scls.n == 2); /* Modify state after sync */ message_id = GNUNET_ntohll (fcls.msg[0]->message_id) + 6; GNUNET_assert (GNUNET_OK == db->state_modify_begin (db->cls, &channel_pub_key, message_id, 3)); GNUNET_assert (GNUNET_OK == db->state_modify_set (db->cls, &channel_pub_key, "_sync_foo", C2ARG("five six seven"))); GNUNET_assert (GNUNET_OK == db->state_modify_end (db->cls, &channel_pub_key, message_id)); /* Reset state */ scls.n = 0; GNUNET_assert (GNUNET_OK == db->state_reset (db->cls, &channel_pub_key)); GNUNET_assert (scls.n == 0); ok = 0; if (NULL != channel_key) { GNUNET_free (channel_key); channel_key = NULL; } if (NULL != slave_key) { GNUNET_free (slave_key); slave_key = NULL; } unload_plugin (db); } int main (int argc, char *argv[]) { char cfg_name[128]; char *const xargv[] = { "test-plugin-psycstore", "-c", cfg_name, "-L", LOG_LEVEL, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-psycstore-sqlite"); GNUNET_log_setup ("test-plugin-psycstore", LOG_LEVEL, NULL); plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_plugin_psycstore_%s.conf", plugin_name); GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "test-plugin-psycstore", "nohelp", options, &run, NULL); if (ok != 0) FPRINTF (stderr, "Missed some testcases: %d\n", ok); #if ! DEBUG_PSYCSTORE GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-psycstore-sqlite"); #endif return ok; } /* end of test_plugin_psycstore.c */ gnunet-0.10.1/src/psycstore/psycstore_api.c0000644000175000017500000011724712241134530015673 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psycstore/psycstore_api.c * @brief API to interact with the PSYCstore service * @author Gabor X Toth * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_psycstore_service.h" #include "gnunet_multicast_service.h" #include "psycstore.h" #define LOG(kind,...) GNUNET_log_from (kind, "psycstore-api",__VA_ARGS__) typedef void (*DataCallback) (); /** * Handle for an operation with the PSYCstore service. */ struct GNUNET_PSYCSTORE_OperationHandle { /** * Main PSYCstore handle. */ struct GNUNET_PSYCSTORE_Handle *h; /** * We keep operations in a DLL. */ struct GNUNET_PSYCSTORE_OperationHandle *next; /** * We keep operations in a DLL. */ struct GNUNET_PSYCSTORE_OperationHandle *prev; /** * Continuation to invoke with the result of an operation. */ GNUNET_PSYCSTORE_ResultCallback res_cb; /** * Continuation to invoke with the result of an operation returning data. */ DataCallback data_cb; /** * Closure for the callbacks. */ void *cls; /** * Operation ID. */ uint32_t op_id; /** * Message to send to the PSYCstore service. * Allocated at the end of this struct. */ const struct GNUNET_MessageHeader *msg; }; /** * Handle for the service. */ struct GNUNET_PSYCSTORE_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Head of operations to transmit. */ struct GNUNET_PSYCSTORE_OperationHandle *transmit_head; /** * Tail of operations to transmit. */ struct GNUNET_PSYCSTORE_OperationHandle *transmit_tail; /** * Head of active operations waiting for response. */ struct GNUNET_PSYCSTORE_OperationHandle *op_head; /** * Tail of active operations waiting for response. */ struct GNUNET_PSYCSTORE_OperationHandle *op_tail; /** * Currently pending transmission request, or NULL for none. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Task doing exponential back-off trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Time for next connect retry. */ struct GNUNET_TIME_Relative reconnect_delay; /** * Are we polling for incoming messages right now? */ int in_receive; /** * The last operation id used for a PSYCstore operation. */ uint32_t last_op_id_used; }; /** * Get a fresh operation ID to distinguish between PSYCstore requests. * * @param h Handle to the PSYCstore service. * @return next operation id to use */ static uint32_t get_next_op_id (struct GNUNET_PSYCSTORE_Handle *h) { return h->last_op_id_used++; } /** * Find operation by ID. * * @return OperationHandle if found, or NULL otherwise. */ static struct GNUNET_PSYCSTORE_OperationHandle * find_op_by_id (struct GNUNET_PSYCSTORE_Handle *h, uint32_t op_id) { struct GNUNET_PSYCSTORE_OperationHandle *op = h->op_head; while (NULL != op) { if (op->op_id == op_id) return op; op = op->next; } return NULL; } /** * Try again to connect to the PSYCstore service. * * @param cls handle to the PSYCstore service. * @param tc scheduler context */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Reschedule a connect attempt to the service. * * @param h transport service to reconnect */ static void reschedule_connect (struct GNUNET_PSYCSTORE_Handle *h) { GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->in_receive = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task to reconnect to PSYCstore service in %s.\n", GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, GNUNET_YES)); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); } /** * Schedule transmission of the next message from our queue. * * @param h PSYCstore handle */ static void transmit_next (struct GNUNET_PSYCSTORE_Handle *h); /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void message_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_PSYCSTORE_Handle *h = cls; struct GNUNET_PSYCSTORE_OperationHandle *op; const struct OperationResult *opres; const struct CountersResult *cres; const struct FragmentResult *fres; const struct StateResult *sres; const char *str; if (NULL == msg) { reschedule_connect (h); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %d from PSYCstore service.\n", ntohs (msg->type)); uint16_t size = ntohs (msg->size); uint16_t type = ntohs (msg->type); switch (type) { case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE: if (size < sizeof (struct OperationResult)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Received message of type %d with length %lu bytes. " "Expected >= %lu\n", type, size, sizeof (struct OperationResult)); GNUNET_break (0); reschedule_connect (h); return; } opres = (const struct OperationResult *) msg; str = (const char *) &opres[1]; if ( (size > sizeof (struct OperationResult)) && ('\0' != str[size - sizeof (struct OperationResult) - 1]) ) { GNUNET_break (0); reschedule_connect (h); return; } if (size == sizeof (struct OperationResult)) str = NULL; op = find_op_by_id (h, ntohl (opres->op_id)); if (NULL == op) { LOG (GNUNET_ERROR_TYPE_DEBUG, "No callback registered for operation with ID %ld.\n", type, ntohl (opres->op_id)); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Received result message (type %d) with operation ID: %ld\n", type, op->op_id); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); if (NULL != op->res_cb) { const struct StateModifyRequest *smreq; const struct StateSyncRequest *ssreq; switch (ntohs (op->msg->type)) { case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY: smreq = (const struct StateModifyRequest *) op->msg; if (!(smreq->flags & STATE_OP_LAST || GNUNET_OK != ntohl (opres->result_code))) op->res_cb = NULL; break; case GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC: ssreq = (const struct StateSyncRequest *) op->msg; if (!(ssreq->flags & STATE_OP_LAST || GNUNET_OK != ntohl (opres->result_code))) op->res_cb = NULL; break; } } if (NULL != op->res_cb) op->res_cb (op->cls, ntohl (opres->result_code), str); GNUNET_free (op); } break; case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS: if (size != sizeof (struct CountersResult)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Received message of type %d with length %lu bytes. " "Expected %lu\n", type, size, sizeof (struct CountersResult)); GNUNET_break (0); reschedule_connect (h); return; } cres = (const struct CountersResult *) msg; op = find_op_by_id (h, ntohl (cres->op_id)); if (NULL == op) { LOG (GNUNET_ERROR_TYPE_DEBUG, "No callback registered for operation with ID %ld.\n", type, ntohl (cres->op_id)); } else { GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); if (NULL != op->data_cb) ((GNUNET_PSYCSTORE_CountersCallback) op->data_cb) (op->cls, ntohl (cres->result_code), GNUNET_ntohll (cres->max_fragment_id), GNUNET_ntohll (cres->max_message_id), GNUNET_ntohll (cres->max_group_generation), GNUNET_ntohll (cres->max_state_message_id)); GNUNET_free (op); } break; case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_FRAGMENT: if (size < sizeof (struct FragmentResult)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Received message of type %d with length %lu bytes. " "Expected >= %lu\n", type, size, sizeof (struct FragmentResult)); GNUNET_break (0); reschedule_connect (h); return; } fres = (const struct FragmentResult *) msg; struct GNUNET_MULTICAST_MessageHeader *mmsg = (struct GNUNET_MULTICAST_MessageHeader *) &fres[1]; if (size != sizeof (struct FragmentResult) + ntohs (mmsg->header.size)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Received message of type %d with length %lu bytes. " "Expected = %lu\n", type, size, sizeof (struct FragmentResult) + ntohs (mmsg->header.size)); GNUNET_break (0); reschedule_connect (h); return; } op = find_op_by_id (h, ntohl (fres->op_id)); if (NULL == op) { LOG (GNUNET_ERROR_TYPE_DEBUG, "No callback registered for operation with ID %ld.\n", type, ntohl (fres->op_id)); } else { if (NULL != op->data_cb) ((GNUNET_PSYCSTORE_FragmentCallback) op->data_cb) (op->cls, mmsg, ntohl (fres->psycstore_flags)); } break; case GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE: if (size < sizeof (struct StateResult)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Received message of type %d with length %lu bytes. " "Expected >= %lu\n", type, size, sizeof (struct StateResult)); GNUNET_break (0); reschedule_connect (h); return; } sres = (const struct StateResult *) msg; const char *name = (const char *) &sres[1]; uint16_t name_size = ntohs (sres->name_size); if (name_size <= 2 || '\0' != name[name_size - 1]) { LOG (GNUNET_ERROR_TYPE_ERROR, "Received state result message (type %d) with invalid name.\n", type); GNUNET_break (0); reschedule_connect (h); return; } op = find_op_by_id (h, ntohl (sres->op_id)); if (NULL == op) { LOG (GNUNET_ERROR_TYPE_DEBUG, "No callback registered for operation with ID %ld.\n", type, ntohl (sres->op_id)); } else { if (NULL != op->data_cb) ((GNUNET_PSYCSTORE_StateCallback) op->data_cb) (op->cls, name, (char *) &sres[1] + name_size, ntohs (sres->header.size) - sizeof (*sres) - name_size); } break; default: GNUNET_break (0); reschedule_connect (h); return; } GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Transmit next message to service. * * @param cls The 'struct GNUNET_PSYCSTORE_Handle'. * @param size Number of bytes available in buf. * @param buf Where to copy the message. * @return Number of bytes copied to buf. */ static size_t send_next_message (void *cls, size_t size, void *buf) { struct GNUNET_PSYCSTORE_Handle *h = cls; struct GNUNET_PSYCSTORE_OperationHandle *op = h->transmit_head; size_t ret; h->th = NULL; if (NULL == op) return 0; ret = ntohs (op->msg->size); if (ret > size) { reschedule_connect (h); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending message of type %d to PSYCstore service. ID: %u\n", ntohs (op->msg->type), op->op_id); memcpy (buf, op->msg, ret); GNUNET_CONTAINER_DLL_remove (h->transmit_head, h->transmit_tail, op); if (NULL == op->res_cb && NULL == op->data_cb) { GNUNET_free (op); } else { GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, op); } if (NULL != h->transmit_head) transmit_next (h); if (GNUNET_NO == h->in_receive) { h->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); } return ret; } /** * Schedule transmission of the next message from our queue. * * @param h PSYCstore handle. */ static void transmit_next (struct GNUNET_PSYCSTORE_Handle *h) { if (NULL != h->th || NULL == h->client) return; struct GNUNET_PSYCSTORE_OperationHandle *op = h->transmit_head; if (NULL == op) return; h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ntohs (op->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_next_message, h); } /** * Try again to connect to the PSYCstore service. * * @param cls Handle to the PSYCstore service. * @param tc Scheduler context. */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PSYCSTORE_Handle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to PSYCstore service.\n"); GNUNET_assert (NULL == h->client); h->client = GNUNET_CLIENT_connect ("psycstore", h->cfg); GNUNET_assert (NULL != h->client); transmit_next (h); } /** * Connect to the PSYCstore service. * * @param cfg The configuration to use * @return Handle to use */ struct GNUNET_PSYCSTORE_Handle * GNUNET_PSYCSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_PSYCSTORE_Handle *h = GNUNET_new (struct GNUNET_PSYCSTORE_Handle); h->cfg = cfg; h->reconnect_delay = GNUNET_TIME_UNIT_ZERO; h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, h); return h; } /** * Disconnect from PSYCstore service * * @param h Handle to destroy */ void GNUNET_PSYCSTORE_disconnect (struct GNUNET_PSYCSTORE_Handle *h) { GNUNET_assert (NULL != h); if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } GNUNET_free (h); } /** * Cancel a PSYCstore operation. Note that the operation MAY still * be executed; this merely cancels the continuation; if the request * was already transmitted, the service may still choose to complete * the operation. * * @param op Operation to cancel. */ void GNUNET_PSYCSTORE_operation_cancel (struct GNUNET_PSYCSTORE_OperationHandle *op) { struct GNUNET_PSYCSTORE_Handle *h = op->h; if (h->transmit_head != NULL && (h->transmit_head != op || NULL == h->client)) { /* request not active, can simply remove */ GNUNET_CONTAINER_DLL_remove (h->transmit_head, h->transmit_tail, op); GNUNET_free (op); return; } if (NULL != h->th) { /* request active but not yet with service, can still abort */ GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; GNUNET_CONTAINER_DLL_remove (h->transmit_head, h->transmit_tail, op); GNUNET_free (op); transmit_next (h); return; } /* request active with service, simply ensure continuations are not called */ op->res_cb = NULL; op->data_cb = NULL; } /** * Store join/leave events for a PSYC channel in order to be able to answer * membership test queries later. * * @param h Handle for the PSYCstore. * @param channel_key The channel where the event happened. * @param slave_key Public key of joining/leaving slave. * @param did_join #GNUNET_YES on join, #GNUNET_NO on part. * @param announced_at ID of the message that announced the membership change. * @param effective_since Message ID this membership change is in effect since. * For joins it is <= announced_at, for parts it is always 0. * @param group_generation In case of a part, the last group generation the * slave has access to. It has relevance when a larger message have * fragments with different group generations. * @param rcb Callback to call with the result of the storage operation. * @param rcb_cls Closure for the callback. * * @return Operation handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_membership_store (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, int did_join, uint64_t announced_at, uint64_t effective_since, uint64_t group_generation, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls) { GNUNET_assert (NULL != h); GNUNET_assert (NULL != channel_key); GNUNET_assert (NULL != slave_key); GNUNET_assert (did_join ? effective_since <= announced_at : effective_since == 0); struct MembershipStoreRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req)); op->h = h; op->res_cb = rcb; op->cls = rcb_cls; req = (struct MembershipStoreRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE); req->header.size = htons (sizeof (*req)); req->channel_key = *channel_key; req->slave_key = *slave_key; req->did_join = htonl (did_join); req->announced_at = GNUNET_htonll (announced_at); req->effective_since = GNUNET_htonll (effective_since); req->group_generation = GNUNET_htonll (group_generation); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Test if a member was admitted to the channel at the given message ID. * * This is useful when relaying and replaying messages to check if a particular * slave has access to the message fragment with a given group generation. It * is also used when handling join requests to determine whether the slave is * currently admitted to the channel. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param slave_key Public key of slave whose membership to check. * @param message_id Message ID for which to do the membership test. * @param group_generation Group generation of the fragment of the message to * test. It has relevance if the message consists of multiple fragments * with different group generations. * @param rcb Callback to call with the test result. * @param rcb_cls Closure for the callback. * * @return Operation handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_membership_test (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t message_id, uint64_t group_generation, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls) { struct MembershipTestRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req)); op->h = h; op->res_cb = rcb; op->cls = rcb_cls; req = (struct MembershipTestRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST); req->header.size = htons (sizeof (*req)); req->channel_key = *channel_key; req->slave_key = *slave_key; req->message_id = GNUNET_htonll (message_id); req->group_generation = GNUNET_htonll (group_generation); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Store a message fragment sent to a channel. * * @param h Handle for the PSYCstore. * @param channel_key The channel the message belongs to. * @param message Message to store. * @param psycstore_flags Flags indicating whether the PSYC message contains * state modifiers. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_fragment_store (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_MULTICAST_MessageHeader *message, uint32_t psycstore_flags, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls) { uint16_t size = ntohs (message->header.size); struct FragmentStoreRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + size); op->h = h; op->res_cb = rcb; op->cls = rcb_cls; req = (struct FragmentStoreRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE); req->header.size = htons (sizeof (*req) + size); req->channel_key = *channel_key; req->psycstore_flags = htonl (psycstore_flags); memcpy (&req[1], message, size); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Retrieve a message fragment by fragment ID. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param fragment_id Fragment ID to check. Use 0 to get the latest message fragment. * @param fcb Callback to call with the retrieved fragments. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_fragment_get (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t fragment_id, GNUNET_PSYCSTORE_FragmentCallback fcb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls) { struct FragmentGetRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req)); op->h = h; op->data_cb = (DataCallback) fcb; op->res_cb = rcb; op->cls = cls; req = (struct FragmentGetRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET); req->header.size = htons (sizeof (*req)); req->channel_key = *channel_key; req->fragment_id = GNUNET_htonll (fragment_id); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Retrieve all fragments of a message. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id Message ID to check. Use 0 to get the latest message. * @param fcb Callback to call with the retrieved fragments. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_message_get (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, GNUNET_PSYCSTORE_FragmentCallback fcb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls) { struct MessageGetRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req)); op->h = h; op->data_cb = (DataCallback) fcb; op->res_cb = rcb; op->cls = cls; req = (struct MessageGetRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET); req->header.size = htons (sizeof (*req)); req->channel_key = *channel_key; req->message_id = GNUNET_htonll (message_id); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Retrieve a fragment of message specified by its message ID and fragment * offset. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id Message ID to check. Use 0 to get the latest message. * @param fragment_offset Offset of the fragment to retrieve. * @param fcb Callback to call with the retrieved fragments. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_message_get_fragment (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t fragment_offset, GNUNET_PSYCSTORE_FragmentCallback fcb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls) { struct MessageGetFragmentRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req)); op->h = h; op->data_cb = (DataCallback) fcb; op->res_cb = rcb; op->cls = cls; req = (struct MessageGetFragmentRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET_FRAGMENT); req->header.size = htons (sizeof (*req)); req->channel_key = *channel_key; req->message_id = GNUNET_htonll (message_id); req->fragment_offset = GNUNET_htonll (fragment_offset); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Retrieve latest values of counters for a channel master. * * The current value of counters are needed when a channel master is restarted, * so that it can continue incrementing the counters from their last value. * * @param h Handle for the PSYCstore. * @param channel_key Public key that identifies the channel. * @param ccb Callback to call with the result. * @param ccb_cls Closure for the @a ccb callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_counters_get (struct GNUNET_PSYCSTORE_Handle *h, struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, GNUNET_PSYCSTORE_CountersCallback ccb, void *ccb_cls) { struct OperationRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req)); op->h = h; op->data_cb = ccb; op->cls = ccb_cls; req = (struct OperationRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET); req->header.size = htons (sizeof (*req)); req->channel_key = *channel_key; op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Apply modifiers of a message to the current channel state. * * An error is returned if there are missing messages containing state * operations before the current one. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id ID of the message that contains the @a modifiers. * @param state_delta Value of the _state_delta PSYC header variable of the message. * @param modifier_count Number of elements in the @a modifiers array. * @param modifiers List of modifiers to apply. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the @a rcb callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_modify (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, uint64_t state_delta, size_t modifier_count, const struct GNUNET_ENV_Modifier *modifiers, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls) { struct GNUNET_PSYCSTORE_OperationHandle *op = NULL; size_t i; for (i = 0; i < modifier_count; i++) { struct StateModifyRequest *req; uint16_t name_size = strlen (modifiers[i].name) + 1; op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size + modifiers[i].value_size); op->h = h; op->res_cb = rcb; op->cls = rcb_cls; req = (struct StateModifyRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY); req->header.size = htons (sizeof (*req) + name_size + modifiers[i].value_size); req->channel_key = *channel_key; req->message_id = GNUNET_htonll (message_id); req->state_delta = GNUNET_htonll (state_delta); req->oper = modifiers[i].oper; req->name_size = htons (name_size); req->flags = 0 == i ? STATE_OP_FIRST : modifier_count - 1 == i ? STATE_OP_LAST : 0; memcpy (&req[1], modifiers[i].name, name_size); memcpy ((char *) &req[1] + name_size, modifiers[i].value, modifiers[i].value_size); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); } return op; /* FIXME: only the last operation is returned, * operation_cancel() should be able to cancel all of them. */ } /** * Store synchronized state. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id ID of the message that contains the state_hash PSYC header variable. * @param modifier_count Number of elements in the @a modifiers array. * @param modifiers Full state to store. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_sync (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, size_t modifier_count, const struct GNUNET_ENV_Modifier *modifiers, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls) { struct GNUNET_PSYCSTORE_OperationHandle *op = NULL; size_t i; for (i = 0; i < modifier_count; i++) { struct StateSyncRequest *req; uint16_t name_size = strlen (modifiers[i].name) + 1; op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size + modifiers[i].value_size); op->h = h; op->res_cb = rcb; op->cls = rcb_cls; req = (struct StateSyncRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC); req->header.size = htons (sizeof (*req) + name_size + modifiers[i].value_size); req->channel_key = *channel_key; req->message_id = GNUNET_htonll (message_id); req->name_size = htons (name_size); req->flags = 0 == i ? STATE_OP_FIRST : modifier_count - 1 == i ? STATE_OP_LAST : 0; memcpy (&req[1], modifiers[i].name, name_size); memcpy ((char *) &req[1] + name_size, modifiers[i].value, modifiers[i].value_size); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); } return op; } /** * Reset the state of a channel. * * Delete all state variables stored for the given channel. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the callback. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_reset (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls) { struct OperationRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req)); op->h = h; op->res_cb = rcb; op->cls = rcb_cls; req = (struct OperationRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_RESET); req->header.size = htons (sizeof (*req)); req->channel_key = *channel_key; op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Update signed values of state variables in the state store. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param message_id Message ID that contained the state @a hash. * @param hash Hash of the serialized full state. * @param rcb Callback to call with the result of the operation. * @param rcb_cls Closure for the callback. * */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_hash_update (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, uint64_t message_id, const struct GNUNET_HashCode *hash, GNUNET_PSYCSTORE_ResultCallback rcb, void *rcb_cls) { struct StateHashUpdateRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req)); op->h = h; op->res_cb = rcb; op->cls = rcb_cls; req = (struct StateHashUpdateRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_RESET); req->header.size = htons (sizeof (*req)); req->channel_key = *channel_key; req->hash = *hash; op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Retrieve the best matching state variable. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param name Name of variable to match, the returned variable might be less specific. * @param scb Callback to return the matching state variable. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_get (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name, GNUNET_PSYCSTORE_StateCallback scb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls) { size_t name_size = strlen (name) + 1; struct OperationRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size); op->h = h; op->data_cb = (DataCallback) scb; op->res_cb = rcb; op->cls = cls; req = (struct OperationRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET); req->header.size = htons (sizeof (*req) + name_size); req->channel_key = *channel_key; memcpy (&req[1], name, name_size); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /** * Retrieve all state variables for a channel with the given prefix. * * @param h Handle for the PSYCstore. * @param channel_key The channel we are interested in. * @param name_prefix Prefix of state variable names to match. * @param scb Callback to return matching state variables. * @param rcb Callback to call with the result of the operation. * @param cls Closure for the callbacks. * * @return Handle that can be used to cancel the operation. */ struct GNUNET_PSYCSTORE_OperationHandle * GNUNET_PSYCSTORE_state_get_prefix (struct GNUNET_PSYCSTORE_Handle *h, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const char *name_prefix, GNUNET_PSYCSTORE_StateCallback scb, GNUNET_PSYCSTORE_ResultCallback rcb, void *cls) { size_t name_size = strlen (name_prefix) + 1; struct OperationRequest *req; struct GNUNET_PSYCSTORE_OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*req) + name_size); op->h = h; op->data_cb = (DataCallback) scb; op->res_cb = rcb; op->cls = cls; req = (struct OperationRequest *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) req; req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET_PREFIX); req->header.size = htons (sizeof (*req) + name_size); req->channel_key = *channel_key; memcpy (&req[1], name_prefix, name_size); op->op_id = get_next_op_id (h); req->op_id = htonl (op->op_id); GNUNET_CONTAINER_DLL_insert_tail (h->transmit_head, h->transmit_tail, op); transmit_next (h); return op; } /* end of psycstore_api.c */ gnunet-0.10.1/src/psycstore/Makefile.in0000644000175000017500000013760112320752063014711 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = libexec_PROGRAMS = gnunet-service-psycstore$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = $(am__EXEEXT_1) \ @HAVE_TESTING_TRUE@ test_psycstore$(EXEEXT) subdir = src/psycstore DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/psycstore.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = psycstore.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunet_plugin_psycstore_sqlite_la_OBJECTS = \ plugin_psycstore_sqlite.lo libgnunet_plugin_psycstore_sqlite_la_OBJECTS = \ $(am_libgnunet_plugin_psycstore_sqlite_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_psycstore_sqlite_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_psycstore_sqlite_la_LDFLAGS) $(LDFLAGS) -o \ $@ @HAVE_SQLITE_TRUE@am_libgnunet_plugin_psycstore_sqlite_la_rpath = \ @HAVE_SQLITE_TRUE@ -rpath $(plugindir) am_libgnunetpsycstore_la_OBJECTS = psycstore_api.lo libgnunetpsycstore_la_OBJECTS = $(am_libgnunetpsycstore_la_OBJECTS) libgnunetpsycstore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetpsycstore_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_1 = test_plugin_psycstore_sqlite$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_service_psycstore_OBJECTS = \ gnunet-service-psycstore.$(OBJEXT) gnunet_service_psycstore_OBJECTS = \ $(am_gnunet_service_psycstore_OBJECTS) am_test_plugin_psycstore_sqlite_OBJECTS = \ test_plugin_psycstore.$(OBJEXT) test_plugin_psycstore_sqlite_OBJECTS = \ $(am_test_plugin_psycstore_sqlite_OBJECTS) test_plugin_psycstore_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_psycstore_OBJECTS = test_psycstore.$(OBJEXT) test_psycstore_OBJECTS = $(am_test_psycstore_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_psycstore_sqlite_la_SOURCES) \ $(libgnunetpsycstore_la_SOURCES) \ $(gnunet_service_psycstore_SOURCES) \ $(test_plugin_psycstore_sqlite_SOURCES) \ $(test_psycstore_SOURCES) DIST_SOURCES = $(libgnunet_plugin_psycstore_sqlite_la_SOURCES) \ $(libgnunetpsycstore_la_SOURCES) \ $(gnunet_service_psycstore_SOURCES) \ $(test_plugin_psycstore_sqlite_SOURCES) \ $(test_psycstore_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ psycstore.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov @HAVE_SQLITE_TRUE@SQLITE_PLUGIN = libgnunet_plugin_psycstore_sqlite.la @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@SQLITE_TESTS = test_plugin_psycstore_sqlite lib_LTLIBRARIES = libgnunetpsycstore.la libgnunetpsycstore_la_SOURCES = \ psycstore_api.c \ psycstore.h libgnunetpsycstore_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetpsycstore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetpsycstore_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_service_psycstore_SOURCES = \ gnunet-service-psycstore.c gnunet_service_psycstore_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_psycstore_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) libgnunet_plugin_psycstore_sqlite_la_SOURCES = \ plugin_psycstore_sqlite.c libgnunet_plugin_psycstore_sqlite_la_LIBADD = \ $(top_builddir)/src/psycstore/libgnunetpsycstore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_psycstore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_psycstore_sqlite_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetpsycstore.la @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_psycstore_SOURCES = \ test_psycstore.c test_psycstore_LDADD = \ libgnunetpsycstore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_psycstore_DEPENDENCIES = \ libgnunetpsycstore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_psycstore.conf test_plugin_psycstore_sqlite_SOURCES = \ test_plugin_psycstore.c test_plugin_psycstore_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/psycstore/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/psycstore/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): psycstore.conf: $(top_builddir)/config.status $(srcdir)/psycstore.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_psycstore_sqlite.la: $(libgnunet_plugin_psycstore_sqlite_la_OBJECTS) $(libgnunet_plugin_psycstore_sqlite_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_psycstore_sqlite_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_psycstore_sqlite_la_LINK) $(am_libgnunet_plugin_psycstore_sqlite_la_rpath) $(libgnunet_plugin_psycstore_sqlite_la_OBJECTS) $(libgnunet_plugin_psycstore_sqlite_la_LIBADD) $(LIBS) libgnunetpsycstore.la: $(libgnunetpsycstore_la_OBJECTS) $(libgnunetpsycstore_la_DEPENDENCIES) $(EXTRA_libgnunetpsycstore_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetpsycstore_la_LINK) -rpath $(libdir) $(libgnunetpsycstore_la_OBJECTS) $(libgnunetpsycstore_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-service-psycstore$(EXEEXT): $(gnunet_service_psycstore_OBJECTS) $(gnunet_service_psycstore_DEPENDENCIES) $(EXTRA_gnunet_service_psycstore_DEPENDENCIES) @rm -f gnunet-service-psycstore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_psycstore_OBJECTS) $(gnunet_service_psycstore_LDADD) $(LIBS) test_plugin_psycstore_sqlite$(EXEEXT): $(test_plugin_psycstore_sqlite_OBJECTS) $(test_plugin_psycstore_sqlite_DEPENDENCIES) $(EXTRA_test_plugin_psycstore_sqlite_DEPENDENCIES) @rm -f test_plugin_psycstore_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_psycstore_sqlite_OBJECTS) $(test_plugin_psycstore_sqlite_LDADD) $(LIBS) test_psycstore$(EXEEXT): $(test_psycstore_OBJECTS) $(test_psycstore_DEPENDENCIES) $(EXTRA_test_psycstore_DEPENDENCIES) @rm -f test_psycstore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_psycstore_OBJECTS) $(test_psycstore_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-psycstore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_psycstore_sqlite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psycstore_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_psycstore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_psycstore.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_plugin_psycstore_sqlite.log: test_plugin_psycstore_sqlite$(EXEEXT) @p='test_plugin_psycstore_sqlite$(EXEEXT)'; \ b='test_plugin_psycstore_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_psycstore.log: test_psycstore$(EXEEXT) @p='test_psycstore$(EXEEXT)'; \ b='test_psycstore'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/psycstore/psycstore.h0000644000175000017500000001662512225777503015064 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psycstore/psycstore.h * @brief Common type definitions for the PSYCstore service and API. * @author Gabor X Toth */ #ifndef GNUNET_PSYCSTORE_H #define GNUNET_PSYCSTORE_H #include "gnunet_common.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Answer from service to client about last operation. */ struct OperationResult { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Status code for the operation. */ int64_t result_code GNUNET_PACKED; /* followed by 0-terminated error message (on error) */ }; /** * Answer from service to client about master counters. * * @see GNUNET_PSYCSTORE_counters_get() */ struct CountersResult { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; uint64_t max_fragment_id GNUNET_PACKED; uint64_t max_message_id GNUNET_PACKED; uint64_t max_group_generation GNUNET_PACKED; uint64_t max_state_message_id GNUNET_PACKED; /** * Status code for the operation: * #GNUNET_OK: success, counter values are returned. * #GNUNET_NO: no message has been sent to the channel yet. * #GNUNET_SYSERR: an error occurred. */ int32_t result_code GNUNET_PACKED; }; /** * Answer from service to client containing a message fragment. */ struct FragmentResult { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; uint32_t psycstore_flags GNUNET_PACKED; /* followed by GNUNET_MULTICAST_MessageHeader */ }; /** * Answer from service to client containing a state variable. */ struct StateResult { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; uint16_t name_size GNUNET_PACKED; /* followed by name and value */ }; /** * Generic operation request. */ struct OperationRequest { struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; struct GNUNET_CRYPTO_EddsaPublicKey channel_key; }; /** * @see GNUNET_PSYCSTORE_membership_store() */ struct MembershipStoreRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; /** * Slave's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey slave_key; uint64_t announced_at GNUNET_PACKED; uint64_t effective_since GNUNET_PACKED; uint64_t group_generation GNUNET_PACKED; int did_join GNUNET_PACKED; }; /** * @see GNUNET_PSYCSTORE_membership_test() */ struct MembershipTestRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; /** * Slave's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey slave_key; uint64_t message_id GNUNET_PACKED; uint64_t group_generation GNUNET_PACKED; }; /** * @see GNUNET_PSYCSTORE_fragment_store() */ struct FragmentStoreRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; uint32_t psycstore_flags GNUNET_PACKED; }; /** * @see GNUNET_PSYCSTORE_fragment_get() */ struct FragmentGetRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; uint64_t fragment_id GNUNET_PACKED; }; /** * @see GNUNET_PSYCSTORE_message_get() */ struct MessageGetRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; uint64_t message_id GNUNET_PACKED; }; /** * @see GNUNET_PSYCSTORE_message_get_fragment() */ struct MessageGetFragmentRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_FRAGMENT_GET */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; uint64_t message_id GNUNET_PACKED; uint64_t fragment_offset GNUNET_PACKED; }; /** * @see GNUNET_PSYCSTORE_state_hash_update() */ struct StateHashUpdateRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_HASH_UPDATE */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; struct GNUNET_HashCode hash; }; enum StateOpFlags { STATE_OP_FIRST = 1 << 0, STATE_OP_LAST = 1 << 1 }; /** * @see GNUNET_PSYCSTORE_state_modify() */ struct StateModifyRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; uint64_t message_id GNUNET_PACKED; uint64_t state_delta GNUNET_PACKED; /** * Size of name, including NUL terminator. */ uint16_t name_size GNUNET_PACKED; /** * OR'd StateOpFlags */ uint8_t flags; /** * enum GNUNET_ENV_Operator */ uint8_t oper; /* Followed by NUL-terminated name, then the value. */ }; /** * @see GNUNET_PSYCSTORE_state_sync() */ struct StateSyncRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Channel's public key. */ struct GNUNET_CRYPTO_EddsaPublicKey channel_key; uint64_t message_id GNUNET_PACKED; /** * Size of name, including NUL terminator. */ uint16_t name_size GNUNET_PACKED; /** * OR'd StateOpFlags */ uint8_t flags; /* Followed by NUL-terminated name, then the value. */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/psycstore/Makefile.am0000644000175000017500000000525512320751517014702 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ psycstore.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif if HAVE_SQLITE SQLITE_PLUGIN = libgnunet_plugin_psycstore_sqlite.la if HAVE_TESTING SQLITE_TESTS = test_plugin_psycstore_sqlite endif endif lib_LTLIBRARIES = libgnunetpsycstore.la libgnunetpsycstore_la_SOURCES = \ psycstore_api.c \ psycstore.h libgnunetpsycstore_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetpsycstore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetpsycstore_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la bin_PROGRAMS = libexec_PROGRAMS = \ gnunet-service-psycstore gnunet_service_psycstore_SOURCES = \ gnunet-service-psycstore.c gnunet_service_psycstore_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_psycstore_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) libgnunet_plugin_psycstore_sqlite_la_SOURCES = \ plugin_psycstore_sqlite.c libgnunet_plugin_psycstore_sqlite_la_LIBADD = \ $(top_builddir)/src/psycstore/libgnunetpsycstore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_psycstore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_psycstore_sqlite_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetpsycstore.la if HAVE_TESTING check_PROGRAMS = \ $(SQLITE_TESTS) \ test_psycstore endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_psycstore_SOURCES = \ test_psycstore.c test_psycstore_LDADD = \ libgnunetpsycstore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_psycstore_DEPENDENCIES = \ libgnunetpsycstore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_psycstore.conf test_plugin_psycstore_sqlite_SOURCES = \ test_plugin_psycstore.c test_plugin_psycstore_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet-0.10.1/src/psycstore/test_psycstore.conf0000644000175000017500000000063412241134530016573 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-psycstore/ [arm] UNIXPATH = $GNUNET_RUNTIME_DIR/test-gnunet-service-arm.sock DEFAULTSERVICES = psycstore [psycstore] AUTOSTART = YES BINARY = gnunet-service-psycstore UNIXPATH = $GNUNET_RUNTIME_DIR/test-gnunet-service-psycstore.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES DATABASE = sqlite [psycstore-sqlite] FILENAME = $GNUNET_TEST_HOME/psycstore/sqlite_test.db gnunet-0.10.1/src/psycstore/gnunet-service-psycstore.c0000644000175000017500000005404312225777502020006 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psycstore/gnunet-service-psycstore.c * @brief PSYCstore service * @author Gabor X Toth * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet_psycstore_service.h" #include "gnunet_psycstore_plugin.h" #include "psycstore.h" /** * Handle to our current configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the statistics service. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Notification context, simplifies client broadcasts. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Database handle */ static struct GNUNET_PSYCSTORE_PluginFunctions *db; /** * Name of the database plugin */ static char *db_lib_name; /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db)); GNUNET_free (db_lib_name); db_lib_name = NULL; } /** * Send a result code back to the client. * * @param client Client that should receive the result code. * @param result_code Code to transmit. * @param op_id Operation ID. * @param err_msg Error message to include (or NULL for none). */ static void send_result_code (struct GNUNET_SERVER_Client *client, uint32_t result_code, uint32_t op_id, const char *err_msg) { struct OperationResult *res; size_t err_len; if (NULL == err_msg) err_len = 0; else err_len = strlen (err_msg) + 1; res = GNUNET_malloc (sizeof (struct OperationResult) + err_len); res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_CODE); res->header.size = htons (sizeof (struct OperationResult) + err_len); res->result_code = htonl (result_code); res->op_id = op_id; if (0 < err_len) memcpy (&res[1], err_msg, err_len); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending result %d (%s) to client\n", (int) result_code, err_msg); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_notification_context_unicast (nc, client, &res->header, GNUNET_NO); GNUNET_free (res); } struct SendClosure { struct GNUNET_SERVER_Client *client; uint64_t op_id; }; static int send_fragment (void *cls, struct GNUNET_MULTICAST_MessageHeader *msg, enum GNUNET_PSYCSTORE_MessageFlags flags) { struct SendClosure *sc = cls; struct FragmentResult *res; size_t msg_size = ntohs (msg->header.size); res = GNUNET_malloc (sizeof (struct FragmentResult) + msg_size); res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_FRAGMENT); res->header.size = htons (sizeof (struct FragmentResult) + msg_size); res->op_id = sc->op_id; res->psycstore_flags = htonl (flags); memcpy (&res[1], msg, msg_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending fragment %ld to client\n", GNUNET_ntohll (msg->fragment_id)); GNUNET_free (msg); GNUNET_SERVER_notification_context_add (nc, sc->client); GNUNET_SERVER_notification_context_unicast (nc, sc->client, &res->header, GNUNET_NO); GNUNET_free (res); return GNUNET_OK; } static int send_state_var (void *cls, const char *name, const void *value, size_t value_size) { struct SendClosure *sc = cls; struct StateResult *res; size_t name_size = strlen (name) + 1; res = GNUNET_malloc (sizeof (struct StateResult) + name_size + value_size); res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_STATE); res->header.size = htons (sizeof (struct StateResult) + name_size + value_size); res->op_id = sc->op_id; res->name_size = htons (name_size); memcpy (&res[1], name, name_size); memcpy ((char *) &res[1] + name_size, value, value_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending state variable %s to client\n", name); GNUNET_SERVER_notification_context_add (nc, sc->client); GNUNET_SERVER_notification_context_unicast (nc, sc->client, &res->header, GNUNET_NO); GNUNET_free (res); return GNUNET_OK; } static void handle_membership_store (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct MembershipStoreRequest *req = (const struct MembershipStoreRequest *) msg; int ret = db->membership_store (db->cls, &req->channel_key, &req->slave_key, ntohl (req->did_join), GNUNET_ntohll (req->announced_at), GNUNET_ntohll (req->effective_since), GNUNET_ntohll (req->group_generation)); if (ret != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to store membership information!\n")); send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_membership_test (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct MembershipTestRequest *req = (const struct MembershipTestRequest *) msg; int ret = db->membership_test (db->cls, &req->channel_key, &req->slave_key, GNUNET_ntohll (req->message_id)); switch (ret) { case GNUNET_YES: case GNUNET_NO: break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to test membership!\n")); } send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_fragment_store (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct FragmentStoreRequest *req = (const struct FragmentStoreRequest *) msg; int ret = db->fragment_store (db->cls, &req->channel_key, (const struct GNUNET_MULTICAST_MessageHeader *) &req[1], ntohl (req->psycstore_flags)); if (ret != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to store fragment!\n")); send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_fragment_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct FragmentGetRequest *req = (const struct FragmentGetRequest *) msg; struct SendClosure sc = { .op_id = req->op_id, .client = client }; int ret = db->fragment_get (db->cls, &req->channel_key, GNUNET_ntohll (req->fragment_id), &send_fragment, &sc); switch (ret) { case GNUNET_YES: case GNUNET_NO: break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to get fragment!\n")); } send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_message_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct MessageGetRequest *req = (const struct MessageGetRequest *) msg; struct SendClosure sc = { .op_id = req->op_id, .client = client }; uint64_t ret_frags = 0; int64_t ret = db->message_get (db->cls, &req->channel_key, GNUNET_ntohll (req->message_id), &ret_frags, &send_fragment, &sc); switch (ret) { case GNUNET_YES: case GNUNET_NO: break; default: ret_frags = ret; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to get message!\n")); } send_result_code (client, ret_frags, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_message_get_fragment (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct MessageGetFragmentRequest *req = (const struct MessageGetFragmentRequest *) msg; struct SendClosure sc = { .op_id = req->op_id, .client = client }; int ret = db->message_get_fragment (db->cls, &req->channel_key, GNUNET_ntohll (req->message_id), GNUNET_ntohll (req->fragment_offset), &send_fragment, &sc); switch (ret) { case GNUNET_YES: case GNUNET_NO: break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to get message fragment!\n")); } send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_counters_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct OperationRequest *req = (const struct OperationRequest *) msg; struct CountersResult res = { {0} }; int ret = db->counters_message_get (db->cls, &req->channel_key, &res.max_fragment_id, &res.max_message_id, &res.max_group_generation); switch (ret) { case GNUNET_OK: ret = db->counters_state_get (db->cls, &req->channel_key, &res.max_state_message_id); case GNUNET_NO: break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to get master counters!\n")); } res.header.type = htons (GNUNET_MESSAGE_TYPE_PSYCSTORE_RESULT_COUNTERS); res.header.size = htons (sizeof (res)); res.result_code = htonl (ret); res.op_id = req->op_id; res.max_fragment_id = GNUNET_htonll (res.max_fragment_id); res.max_message_id = GNUNET_htonll (res.max_message_id); res.max_group_generation = GNUNET_htonll (res.max_group_generation); res.max_state_message_id = GNUNET_htonll (res.max_state_message_id); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_notification_context_unicast (nc, client, &res.header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /* FIXME: stop processing further state modify messages after an error */ static void handle_state_modify (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct StateModifyRequest *req = (const struct StateModifyRequest *) msg; int ret = GNUNET_SYSERR; const char *name = (const char *) &req[1]; uint16_t name_size = ntohs (req->name_size); if (name_size <= 2 || '\0' != name[name_size - 1]) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Tried to set invalid state variable name!\n")); GNUNET_break_op (0); } else { ret = GNUNET_OK; if (req->flags & STATE_OP_FIRST) { ret = db->state_modify_begin (db->cls, &req->channel_key, GNUNET_ntohll (req->message_id), GNUNET_ntohll (req->state_delta)); } if (ret != GNUNET_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to begin modifying state!\n")); } else { switch (req->oper) { case GNUNET_ENV_OP_ASSIGN: ret = db->state_modify_set (db->cls, &req->channel_key, (const char *) &req[1], name + ntohs (req->name_size), ntohs (req->header.size) - sizeof (*req) - ntohs (req->name_size)); break; default: #if TODO ret = GNUNET_ENV_operation ((const char *) &req[1], current_value, current_value_size, req->oper, name + ntohs (req->name_size), ntohs (req->header.size) - sizeof (*req) - ntohs (req->name_size), &value, &value_size); #endif ret = GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unknown operator: %c\n"), req->oper); } } if (GNUNET_OK == ret && req->flags & STATE_OP_LAST) { ret = db->state_modify_end (db->cls, &req->channel_key, GNUNET_ntohll (req->message_id)); if (ret != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to end modifying state!\n")); } } send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /* FIXME: stop processing further state sync messages after an error */ static void handle_state_sync (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct StateSyncRequest *req = (const struct StateSyncRequest *) msg; int ret = GNUNET_SYSERR; const char *name = (const char *) &req[1]; uint16_t name_size = ntohs (req->name_size); if (name_size <= 2 || '\0' != name[name_size - 1]) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Tried to set invalid state variable name!\n")); GNUNET_break_op (0); } else { ret = GNUNET_OK; if (req->flags & STATE_OP_FIRST) { ret = db->state_sync_begin (db->cls, &req->channel_key); } if (ret != GNUNET_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to begin synchronizing state!\n")); } else { ret = db->state_sync_set (db->cls, &req->channel_key, name, name + ntohs (req->name_size), ntohs (req->header.size) - sizeof (*req) - ntohs (req->name_size)); } if (GNUNET_OK == ret && req->flags & STATE_OP_LAST) { ret = db->state_sync_end (db->cls, &req->channel_key, GNUNET_ntohll (req->message_id)); if (ret != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to end synchronizing state!\n")); } } send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_state_reset (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct OperationRequest *req = (const struct OperationRequest *) msg; int ret = db->state_reset (db->cls, &req->channel_key); if (ret != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to reset state!\n")); send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_state_hash_update (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct OperationRequest *req = (const struct OperationRequest *) msg; int ret = db->state_reset (db->cls, &req->channel_key); if (ret != GNUNET_OK) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to reset state!\n")); send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_state_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct OperationRequest *req = (const struct OperationRequest *) msg; struct SendClosure sc = { .op_id = req->op_id, .client = client }; int64_t ret = GNUNET_SYSERR; const char *name = (const char *) &req[1]; uint16_t name_size = ntohs (req->header.size) - sizeof (*req); if (name_size <= 2 || '\0' != name[name_size - 1]) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Tried to get invalid state variable name!\n")); GNUNET_break (0); } else { ret = db->state_get (db->cls, &req->channel_key, name, &send_state_var, &sc); if (GNUNET_NO == ret && name_size >= 5) /* min: _a_b\0 */ { char *p, *n = GNUNET_malloc (name_size); memcpy (n, name, name_size); while (&n[1] < (p = strrchr (n, '_')) && GNUNET_NO == ret) { *p = '\0'; ret = db->state_get (db->cls, &req->channel_key, n, &send_state_var, &sc); } GNUNET_free (n); } } switch (ret) { case GNUNET_OK: case GNUNET_NO: break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to get state variable!\n")); } send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void handle_state_get_prefix (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct OperationRequest *req = (const struct OperationRequest *) msg; struct SendClosure sc = { .op_id = req->op_id, .client = client }; int64_t ret = GNUNET_SYSERR; const char *name = (const char *) &req[1]; uint16_t name_size = ntohs (req->header.size) - sizeof (*req); if (name_size <= 1 || '\0' != name[name_size - 1]) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Tried to get invalid state variable name!\n")); GNUNET_break (0); } else { ret = db->state_get_prefix (db->cls, &req->channel_key, name, &send_state_var, &sc); } switch (ret) { case GNUNET_OK: case GNUNET_NO: break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to get state variable!\n")); } send_result_code (client, ret, req->op_id, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Initialize the PSYCstore service. * * @param cls Closure. * @param server The initialized server. * @param c Configuration to use. */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { { &handle_membership_store, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_STORE, sizeof (struct MembershipStoreRequest) }, { &handle_membership_test, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_MEMBERSHIP_TEST, sizeof (struct MembershipTestRequest) }, { &handle_fragment_store, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_STORE, 0, }, { &handle_fragment_get, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_FRAGMENT_GET, sizeof (struct FragmentGetRequest) }, { &handle_message_get, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET, sizeof (struct MessageGetRequest) }, { &handle_message_get_fragment, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_MESSAGE_GET_FRAGMENT, sizeof (struct MessageGetFragmentRequest) }, { &handle_counters_get, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_COUNTERS_GET, sizeof (struct OperationRequest) }, { &handle_state_modify, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_MODIFY, 0 }, { &handle_state_sync, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_SYNC, 0 }, { &handle_state_reset, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_RESET, sizeof (struct OperationRequest) }, { &handle_state_hash_update, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_HASH_UPDATE, sizeof (struct StateHashUpdateRequest) }, { &handle_state_get, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET, 0 }, { &handle_state_get_prefix, NULL, GNUNET_MESSAGE_TYPE_PSYCSTORE_STATE_GET_PREFIX, 0 }, { NULL, NULL, 0, 0 } }; cfg = c; /* Loading database plugin */ char *database; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "psycstore", "database", &database)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); } else { GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_psycstore_%s", database); db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg); GNUNET_free (database); } if (NULL == db) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n", db_lib_name); GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); return; } stats = GNUNET_STATISTICS_create ("psycstore", cfg); GNUNET_SERVER_add_handlers (server, handlers); nc = GNUNET_SERVER_notification_context_create (server, 1); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for the service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "psycstore", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-psycstore.c */ gnunet-0.10.1/src/psycstore/psycstore.conf.in0000644000175000017500000000045612251306467016156 00000000000000[psycstore] AUTOSTART = @AUTOSTART@ BINARY = gnunet-service-psycstore UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-psycstore.sock HOSTNAME = localhost @UNIXONLY@PORT = 2111 UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES DATABASE = sqlite [psycstore-sqlite] FILENAME = $GNUNET_DATA_HOME/psycstore/sqlite.db gnunet-0.10.1/src/ats/0000755000175000017500000000000012320755624011456 500000000000000gnunet-0.10.1/src/ats/test_ats_api_scheduling_add_address.c0000644000175000017500000001347612263724143020754 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_scheduling_add_address.c * @brief adding addresses with scheduling API * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (1 == value) { GNUNET_SCHEDULER_add_now (&end, NULL); } return GNUNET_OK; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void got_initial_value (void *cls, int success) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got initial value\n"); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); } static int dummy_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got dummy stat %s%s:%s = %llu\n", is_persistent ? "!" : " ", subsystem, name, value); return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); GNUNET_STATISTICS_get (stats, "ats", "# addresses", TIMEOUT, &got_initial_value, &dummy_stat, GNUNET_CONFIGURATION_dup (cfg)); } int main (int argc, char *argv[]) { ret = 0; if (0 != GNUNET_TESTING_peer_run ("test-ats-api", "test_ats_api.conf", &run, NULL)) return 1; return ret; } /* end of file test_ats_api_scheduling_add_address.c */ gnunet-0.10.1/src/ats/test_ats_solver_alternative_after_delete_address.c0000644000175000017500000002475412320466615023603 00000000000000/* if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_solver_add_address.c * @brief solver test: add 2 addresses, request address, delete, expect alternative * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Alternative test address */ static struct Test_Address alt_test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ static struct GNUNET_HELLO_Address test_hello_address; /** * HELLO address */ static struct GNUNET_HELLO_Address alt_test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ static struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ static uint32_t test_ats_count; /** * Test state */ int addresses_added = GNUNET_NO; int first_address_suggested = GNUNET_NO; int first_address_deleted = GNUNET_NO; int second_address_deleted = GNUNET_NO; int second_address_suggested = GNUNET_YES; static struct GNUNET_HELLO_Address *first_suggestion = NULL; static struct GNUNET_HELLO_Address *second_suggestion = NULL; static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent); static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); GNUNET_free_non_null (first_suggestion); GNUNET_free_non_null (second_suggestion); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void end_badly_now () { if (GNUNET_SCHEDULER_NO_TASK != die_task) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_now (&end_badly, NULL); } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received a sugggestion for peer `%s' : `%s'\n", GNUNET_i2s (&address->peer), (char *) address->address); if (GNUNET_NO == first_address_suggested) { if (NULL == first_suggestion) { if ((NULL == address) || (NULL != session)) { GNUNET_break (0); end_badly_now (); return; } if ((ntohl(bandwidth_in.value__) == 0) || (ntohl(bandwidth_out.value__) == 0)) { GNUNET_break (0); end_badly_now (); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received 1st sugggestion for peer `%s' : `%s'\n", GNUNET_i2s (&address->peer), (char *) address->address); first_suggestion = GNUNET_HELLO_address_copy (address); first_address_suggested = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Deleting 1st address for peer `%s' : `%s'\n", GNUNET_i2s (&address->peer), (char *) address->address); GNUNET_ATS_address_destroyed (sched_ats, address, session); first_address_deleted = GNUNET_YES; return; } } if (GNUNET_YES == first_address_deleted) { if (NULL == second_suggestion) { if ((NULL == address) || (NULL != session)) { GNUNET_break (0); end_badly_now (); return; } if (0 == memcmp (address->address, first_suggestion->address, (first_suggestion->address_length < address->address_length) ? first_suggestion->address_length : address->address_length)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Deleted 1st address for peer `%s' was suggested after deletion: `%s' `%s'\n", GNUNET_i2s (&address->peer), (char *) address->address, first_suggestion->address); GNUNET_break (0); end_badly_now (); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received 2nd sugggestion for peer `%s' : `%s'\n", GNUNET_i2s (&address->peer), (char *) address->address); second_suggestion = GNUNET_HELLO_address_copy (address); second_address_suggested = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Deleting 2nd address for peer `%s' : `%s'\n", GNUNET_i2s (&address->peer), (char *) address->address); GNUNET_ATS_address_destroyed (sched_ats, address, session); second_address_deleted = GNUNET_YES; return; } } if (GNUNET_YES == second_address_deleted) { /* Expecting disconnect */ if ((ntohl(bandwidth_in.value__) == 0) && (ntohl(bandwidth_out.value__) == 0)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS tells me to disconnect\n"); GNUNET_SCHEDULER_add_now (&end, NULL); return; } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Expected disconnect but received address `%s' with bandwidth \n", (char *) address->address); } } return; } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if ((GNUNET_NO == addresses_added) && (value == 2)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All addresses added, requesting....\n"); /* We have 2 addresses, so we can request */ addresses_added = GNUNET_YES; GNUNET_ATS_suggest_address (sched_ats, &p.id, NULL, NULL); } return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", mycfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (mycfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); end_badly_now (); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding alternative address without session */ test_session = NULL; create_test_address (&alt_test_addr, "test", test_session, "alt_test", strlen ("alt_test") + 1); alt_test_hello_address.peer = p.id; alt_test_hello_address.transport_name = alt_test_addr.plugin; alt_test_hello_address.address = alt_test_addr.addr; alt_test_hello_address.address_length = alt_test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, NULL, test_ats_info, test_ats_count); /* Adding alternative address */ GNUNET_ATS_address_add (sched_ats, &alt_test_hello_address, NULL, test_ats_info, test_ats_count); } int main (int argc, char *argv[]) { char *sep; char *src_filename = GNUNET_strdup (__FILE__); char *test_filename = GNUNET_strdup (argv[0]); char *config_file; char *solver; ret = 0; if (NULL == (sep = (strstr (src_filename,".c")))) { GNUNET_break (0); return -1; } sep[0] = '\0'; if (NULL != (sep = strstr (test_filename, ".exe"))) sep[0] = '\0'; if (NULL == (solver = strstr (test_filename, src_filename))) { GNUNET_break (0); return -1; } solver += strlen (src_filename) +1; if (0 == strcmp(solver, "proportional")) { config_file = "test_ats_solver_proportional.conf"; } else if (0 == strcmp(solver, "mlp")) { config_file = "test_ats_solver_mlp.conf"; } else if ((0 == strcmp(solver, "ril"))) { config_file = "test_ats_solver_ril.conf"; } else { GNUNET_break (0); GNUNET_free (src_filename); GNUNET_free (test_filename); return 1; } GNUNET_free (src_filename); GNUNET_free (test_filename); if (0 != GNUNET_TESTING_peer_run ("test-ats-solver", config_file, &run, NULL )) return GNUNET_SYSERR; return ret; } /* end of file test_ats_solver_add_address.c */ gnunet-0.10.1/src/ats/gnunet-ats-solver-eval.c0000644000175000017500000022467712320724374016104 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing-experiment.c * @brief ats benchmark: controlled experiment execution * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet-ats-solver-eval.h" #define BIG_M_STRING "unlimited" static struct Experiment *e; static struct LoggingHandle *l; static struct SolverHandle *sh; static struct TestPeer *peer_head; static struct TestPeer *peer_tail; /** * cmd option -e: experiment file */ static char *opt_exp_file; static char *opt_solver; /** * cmd option -l: enable logging */ static int opt_log; /** * cmd option -p: enable plots */ static int opt_plot; /** * cmd option -v: verbose logs */ static int opt_verbose; /** * cmd option -p: print logs */ static int opt_print; static int res; static void end_now (); static char * print_generator_type (enum GeneratorType g) { switch (g) { case GNUNET_ATS_TEST_TG_CONSTANT: return "CONSTANT"; case GNUNET_ATS_TEST_TG_LINEAR: return "LINEAR"; case GNUNET_ATS_TEST_TG_RANDOM: return "RANDOM"; case GNUNET_ATS_TEST_TG_SINUS: return "SINUS"; default: return "INVALID"; break; } } struct AddressLookupCtx { struct ATS_Address *res; char *plugin; char *addr; }; int find_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct AddressLookupCtx *ctx = cls; struct ATS_Address *addr = value; if ( (0 == strcmp (ctx->plugin, addr->plugin)) && (0 == strcmp (ctx->addr, addr->addr)) ) { ctx->res = addr; return GNUNET_NO; } return GNUNET_YES; } static struct TestPeer * find_peer_by_id (int id) { struct TestPeer *cur; for (cur = peer_head; NULL != cur; cur = cur->next) if (cur->id == id) return cur; return NULL; } static struct TestAddress * find_address_by_id (struct TestPeer *peer, int aid) { struct TestAddress *cur; for (cur = peer->addr_head; NULL != cur; cur = cur->next) if (cur->aid == aid) return cur; return NULL; } /** * Logging */ void GNUNET_ATS_solver_logging_now (struct LoggingHandle *l) { struct LoggingTimeStep *lts; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Logging\n"); lts = GNUNET_new (struct LoggingTimeStep); lts->timestamp = GNUNET_TIME_absolute_get(); /* Store logging data here */ GNUNET_CONTAINER_DLL_insert_tail(l->head, l->tail, lts); } static void logging_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct LoggingHandle *l = cls; l->logging_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_ATS_solver_logging_now (l); l->logging_task = GNUNET_SCHEDULER_add_delayed (l->log_freq, &logging_task, l); } struct LoggingHandle * GNUNET_ATS_solver_logging_start (struct GNUNET_TIME_Relative freq) { struct LoggingHandle *l; l = GNUNET_new (struct LoggingHandle); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start logging every %s\n", GNUNET_STRINGS_relative_time_to_string(freq, GNUNET_NO)); /* Iterate over peers */ l->log_freq = freq; l->logging_task = GNUNET_SCHEDULER_add_now (&logging_task, l); return l; } void GNUNET_ATS_solver_logging_stop (struct LoggingHandle *l) { if (GNUNET_SCHEDULER_NO_TASK != l->logging_task) GNUNET_SCHEDULER_cancel (l->logging_task); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop logging\n"); l->logging_task = GNUNET_SCHEDULER_NO_TASK; } void GNUNET_ATS_solver_logging_eval (struct LoggingHandle *l) { struct LoggingTimeStep *lts; for (lts = l->head; NULL != lts; lts = lts->next) { fprintf (stderr, "Log %llu: \n", (long long unsigned int) lts->timestamp.abs_value_us); } } void GNUNET_ATS_solver_logging_free (struct LoggingHandle *l) { struct LoggingTimeStep *cur; struct LoggingTimeStep *next; if (GNUNET_SCHEDULER_NO_TASK != l->logging_task) GNUNET_SCHEDULER_cancel (l->logging_task); l->logging_task = GNUNET_SCHEDULER_NO_TASK; next = l->head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove (l->head, l->tail, cur); GNUNET_free (cur); } GNUNET_free (l); } /** * Property Generators */ static struct PropertyGenerator *prop_gen_head; static struct PropertyGenerator *prop_gen_tail; static double get_property (struct PropertyGenerator *pg) { struct GNUNET_TIME_Relative time_delta; double delta_value; double pref_value; /* Calculate the current preference value */ switch (pg->type) { case GNUNET_ATS_TEST_TG_CONSTANT: pref_value = pg->base_value; break; case GNUNET_ATS_TEST_TG_LINEAR: time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % pg->duration_period.rel_value_us; delta_value = ((double) time_delta.rel_value_us / pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value); if ((pg->max_value < pg->base_value) && ((pg->max_value - pg->base_value) > pg->base_value)) { /* This will cause an underflow */ GNUNET_break (0); } pref_value = pg->base_value + delta_value; break; case GNUNET_ATS_TEST_TG_RANDOM: delta_value = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10000 * (pg->max_value - pg->base_value)) / 10000; pref_value = pg->base_value + delta_value; break; case GNUNET_ATS_TEST_TG_SINUS: time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % pg->duration_period.rel_value_us; if ((pg->max_value - pg->base_value) > pg->base_value) { /* This will cause an underflow for second half of sinus period, * will be detected in general when experiments are loaded */ GNUNET_break (0); } delta_value = (pg->max_value - pg->base_value) * sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) * time_delta.rel_value_us); pref_value = pg->base_value + delta_value; break; default: pref_value = 0.0; break; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current property value is %f\n", pref_value); return pref_value; } static void set_prop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PropertyGenerator *pg = cls; double pref_value; struct GNUNET_ATS_Information atsi; pg->set_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains_value (sh->addresses, &pg->test_peer->peer_id, pg->test_address->ats_addr)) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Setting property generation for unknown address [%u:%u]\n", pg->peer, pg->address_id); return; } pref_value = get_property (pg); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Setting property for peer [%u] address [%u] for %s to %f\n", pg->peer, pg->address_id, GNUNET_ATS_print_property_type (pg->ats_property), pref_value); atsi.type = htonl (pg->ats_property); atsi.value = htonl ((uint32_t) pref_value); /* set performance here! */ sh->env.sf.s_bulk_start (sh->solver); GAS_normalization_normalize_property (sh->addresses, pg->test_address->ats_addr, &atsi, 1); sh->env.sf.s_bulk_stop (sh->solver); switch (pg->ats_property) { case GNUNET_ATS_PREFERENCE_BANDWIDTH: //p->pref_bandwidth = pref_value; break; case GNUNET_ATS_PREFERENCE_LATENCY: //p->pref_delay = pref_value; break; default: break; } pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency, &set_prop_task, pg); } static struct PropertyGenerator * find_prop_gen (unsigned int peer, unsigned int address, uint32_t ats_property) { struct PropertyGenerator *cur; for (cur = prop_gen_head; NULL != cur; cur = cur->next) if ((cur->peer == peer) && (cur->address_id == address) && (cur->ats_property == ats_property)) return cur; return NULL; } void GNUNET_ATS_solver_generate_property_stop (struct PropertyGenerator *pg) { GNUNET_CONTAINER_DLL_remove (prop_gen_head, prop_gen_tail, pg); if (GNUNET_SCHEDULER_NO_TASK != pg->set_task) { GNUNET_SCHEDULER_cancel (pg->set_task); pg->set_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Removing old up preference generator peer [%u] address [%u] `%s'\n", pg->peer, pg->address_id, GNUNET_ATS_print_property_type(pg->ats_property)); GNUNET_free (pg); } /** * Generate between the source master and the partner and set property with a * value depending on the generator. * * @param peer source * @param address_id partner * @param test_peer the peer * @param test_address the address * @param type type of generator * @param base_value base value * @param value_rate maximum value * @param period duration of a period of generation (~ 1/frequency) * @param frequency how long to generate property * @param ats_property ATS property to generate * @return the property generator */ struct PropertyGenerator * GNUNET_ATS_solver_generate_property_start (unsigned int peer, unsigned int address_id, struct TestPeer *test_peer, struct TestAddress *test_address, enum GeneratorType type, long int base_value, long int value_rate, struct GNUNET_TIME_Relative period, struct GNUNET_TIME_Relative frequency, uint32_t ats_property) { struct PropertyGenerator *pg; pg = GNUNET_new (struct PropertyGenerator); GNUNET_CONTAINER_DLL_insert (prop_gen_head, prop_gen_tail, pg); pg->type = type; pg->peer = peer; pg->test_address = test_address; pg->test_peer = test_peer; pg->address_id = address_id; pg->ats_property = ats_property; pg->base_value = base_value; pg->max_value = value_rate; pg->duration_period = period; pg->frequency = frequency; pg->time_start = GNUNET_TIME_absolute_get(); switch (type) { case GNUNET_ATS_TEST_TG_CONSTANT: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up %s property generator peer [%u] address [%u] `%s'"\ "max %u Bips\n", print_generator_type(type), pg->peer, pg->address_id, GNUNET_ATS_print_property_type (ats_property), base_value); break; case GNUNET_ATS_TEST_TG_LINEAR: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up %s property generator peer [%u] address [%u] `%s' " \ "min %u Bips max %u Bips\n", print_generator_type(type), pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property), base_value, value_rate); break; case GNUNET_ATS_TEST_TG_SINUS: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up %s property generator peer [%u] address [%u] `%s' "\ "baserate %u Bips, amplitude %u Bps\n", print_generator_type(type), pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property), base_value, value_rate); break; case GNUNET_ATS_TEST_TG_RANDOM: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up %s property generator peer [%u] address [%u] `%s' "\ "min %u Bips max %u Bps\n", print_generator_type(type), pg->peer, pg->address_id, GNUNET_ATS_print_property_type(ats_property), base_value, value_rate); break; default: break; } pg->set_task = GNUNET_SCHEDULER_add_now (&set_prop_task, pg); return pg; } /** * Stop all preferences generators */ void GNUNET_ATS_solver_generate_property_stop_all () { struct PropertyGenerator *cur; struct PropertyGenerator *next; next = prop_gen_head; for (cur = next; NULL != cur; cur = next) { next = cur->next; GNUNET_ATS_solver_generate_property_stop (cur); } } /** * Preference Generators */ static struct PreferenceGenerator *pref_gen_head; static struct PreferenceGenerator *pref_gen_tail; static double get_preference (struct PreferenceGenerator *pg) { struct GNUNET_TIME_Relative time_delta; double delta_value; double pref_value; /* Calculate the current preference value */ switch (pg->type) { case GNUNET_ATS_TEST_TG_CONSTANT: pref_value = pg->base_value; break; case GNUNET_ATS_TEST_TG_LINEAR: time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % pg->duration_period.rel_value_us; delta_value = ((double) time_delta.rel_value_us / pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value); if ((pg->max_value < pg->base_value) && ((pg->max_value - pg->base_value) > pg->base_value)) { /* This will cause an underflow */ GNUNET_break (0); } pref_value = pg->base_value + delta_value; break; case GNUNET_ATS_TEST_TG_RANDOM: delta_value = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10000 * (pg->max_value - pg->base_value)) / 10000; pref_value = pg->base_value + delta_value; break; case GNUNET_ATS_TEST_TG_SINUS: time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % pg->duration_period.rel_value_us; if ((pg->max_value - pg->base_value) > pg->base_value) { /* This will cause an underflow for second half of sinus period, * will be detected in general when experiments are loaded */ GNUNET_break (0); } delta_value = (pg->max_value - pg->base_value) * sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) * time_delta.rel_value_us); pref_value = pg->base_value + delta_value; break; default: pref_value = 0.0; break; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n", pref_value); return pref_value; } static void set_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PreferenceGenerator *pg = cls; struct TestPeer *p; double pref_value; pg->set_task = GNUNET_SCHEDULER_NO_TASK; if (NULL == (p = find_peer_by_id (pg->peer))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Setting preference for unknown peer %u\n", pg->peer); return; } pref_value = get_preference (pg); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Setting preference for peer [%u] address [%u] for client %p pref %s to %f\n", pg->peer, pg->address_id, NULL + (pg->client_id), GNUNET_ATS_print_preference_type (pg->kind), pref_value); sh->env.sf.s_bulk_start (sh->solver); GAS_normalization_normalize_preference (NULL + (pg->client_id), &p->peer_id, pg->kind, pref_value); sh->env.sf.s_bulk_stop (sh->solver); switch (pg->kind) { case GNUNET_ATS_PREFERENCE_BANDWIDTH: //p->pref_bandwidth = pref_value; break; case GNUNET_ATS_PREFERENCE_LATENCY: //p->pref_delay = pref_value; break; default: break; } pg->set_task = GNUNET_SCHEDULER_add_delayed (pg->frequency, set_pref_task, pg); } static struct PreferenceGenerator * find_pref_gen (unsigned int peer, unsigned int address, enum GNUNET_ATS_PreferenceKind kind) { struct PreferenceGenerator *cur; for (cur = pref_gen_head; NULL != cur; cur = cur->next) if ((cur->peer == peer) && (cur->address_id == address) && (cur->kind == kind)) return cur; return NULL; } void GNUNET_ATS_solver_generate_preferences_stop (struct PreferenceGenerator *pg) { GNUNET_CONTAINER_DLL_remove (pref_gen_head, pref_gen_tail, pg); if (GNUNET_SCHEDULER_NO_TASK != pg->set_task) { GNUNET_SCHEDULER_cancel (pg->set_task); pg->set_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Removing old up preference generator peer [%u] address [%u] `%s'\n", pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(pg->kind)); GNUNET_free (pg); } /** * Generate between the source master and the partner and set property with a * value depending on the generator. * * @param peer source * @param address_id partner * @param client_id the client * @param type type of generator * @param base_value base value * @param value_rate maximum value * @param period duration of a period of generation (~ 1/frequency) * @param frequency how long to generate property * @param kind ATS preference to generate * @return the preference generator */ struct PreferenceGenerator * GNUNET_ATS_solver_generate_preferences_start (unsigned int peer, unsigned int address_id, unsigned int client_id, enum GeneratorType type, long int base_value, long int value_rate, struct GNUNET_TIME_Relative period, struct GNUNET_TIME_Relative frequency, enum GNUNET_ATS_PreferenceKind kind) { struct PreferenceGenerator *pg; pg = GNUNET_new (struct PreferenceGenerator); GNUNET_CONTAINER_DLL_insert (pref_gen_head, pref_gen_tail, pg); pg->type = type; pg->peer = peer; pg->address_id = address_id; pg->client_id = client_id; pg->kind = kind; pg->base_value = base_value; pg->max_value = value_rate; pg->duration_period = period; pg->frequency = frequency; pg->time_start = GNUNET_TIME_absolute_get(); switch (type) { case GNUNET_ATS_TEST_TG_CONSTANT: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Setting up %s preference generator peer [%u] address [%u] `%s' max %u Bips\n", print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind), base_value); break; case GNUNET_ATS_TEST_TG_LINEAR: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Setting up %s preference generator peer [%u] address [%u] `%s' min %u Bips max %u Bips\n", print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind), base_value, value_rate); break; case GNUNET_ATS_TEST_TG_SINUS: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Setting up %s preference generator peer [%u] address [%u] `%s' baserate %u Bips, amplitude %u Bps\n", print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind), base_value, value_rate); break; case GNUNET_ATS_TEST_TG_RANDOM: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Setting up %s preference generator peer [%u] address [%u] `%s' min %u Bips max %u Bps\n", print_generator_type (type), pg->peer, pg->address_id, GNUNET_ATS_print_preference_type(kind), base_value, value_rate); break; default: break; } pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, pg); return pg; } /** * Stop all preferences generators */ void GNUNET_ATS_solver_generate_preferences_stop_all () { struct PreferenceGenerator *cur; struct PreferenceGenerator *next; next = pref_gen_head; for (cur = next; NULL != cur; cur = next) { next = cur->next; GNUNET_ATS_solver_generate_preferences_stop(cur); } } /** * Experiments */ const char * print_op (enum OperationType op) { switch (op) { case SOLVER_OP_ADD_ADDRESS: return "ADD_ADDRESS"; case SOLVER_OP_DEL_ADDRESS: return "DEL_ADDRESS"; case SOLVER_OP_START_SET_PREFERENCE: return "START_SET_PREFERENCE"; case SOLVER_OP_STOP_SET_PREFERENCE: return "STOP_STOP_PREFERENCE"; case SOLVER_OP_START_SET_PROPERTY: return "START_SET_PROPERTY"; case SOLVER_OP_STOP_SET_PROPERTY: return "STOP_SET_PROPERTY"; case SOLVER_OP_START_REQUEST: return "START_REQUEST"; case SOLVER_OP_STOP_REQUEST: return "STOP_REQUEST"; default: break; } return ""; } static struct Experiment * create_experiment () { struct Experiment *e; e = GNUNET_new (struct Experiment); e->name = NULL; e->start = NULL; e->total_duration = GNUNET_TIME_UNIT_ZERO; return e; } static void free_experiment (struct Experiment *e) { struct Episode *cur; struct Episode *next; struct GNUNET_ATS_TEST_Operation *cur_o; struct GNUNET_ATS_TEST_Operation *next_o; next = e->start; for (cur = next; NULL != cur; cur = next) { next = cur->next; next_o = cur->head; for (cur_o = next_o; NULL != cur_o; cur_o = next_o) { next_o = cur_o->next; GNUNET_free_non_null (cur_o->address); GNUNET_free_non_null (cur_o->plugin); GNUNET_free (cur_o); } GNUNET_free (cur); } GNUNET_free_non_null (e->name); GNUNET_free_non_null (e->cfg_file); GNUNET_free (e); } static int load_op_add_address (struct GNUNET_ATS_TEST_Operation *o, struct Episode *e, int op_counter, char *sec_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *op_name; /* peer id */ GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->peer_id)) { fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n", op_counter, "ADD_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address id */ GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_id)) { fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n", op_counter, "ADD_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* plugin */ GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &o->plugin)) { fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n", op_counter, "ADD_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address */ GNUNET_asprintf(&op_name, "op-%u-address", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &o->address)) { fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n", op_counter, "ADD_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* session */ GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_session)) { fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n", op_counter, "ADD_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* network */ GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_network)) { fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n", op_counter, "ADD_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); fprintf (stderr, "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n", "ADD_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin); return GNUNET_OK; } static int load_op_del_address (struct GNUNET_ATS_TEST_Operation *o, struct Episode *e, int op_counter, char *sec_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *op_name; /* peer id */ GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->peer_id)) { fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n", op_counter, "DEL_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address id */ GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_id)) { fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n", op_counter, "DEL_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* plugin */ GNUNET_asprintf(&op_name, "op-%u-plugin", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &o->plugin)) { fprintf (stderr, "Missing plugin in operation %u `%s' in episode `%s'\n", op_counter, "DEL_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address */ GNUNET_asprintf(&op_name, "op-%u-address", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &o->address)) { fprintf (stderr, "Missing address in operation %u `%s' in episode `%s'\n", op_counter, "DEL_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* session */ GNUNET_asprintf(&op_name, "op-%u-address-session", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_session)) { fprintf (stderr, "Missing address-session in operation %u `%s' in episode `%s'\n", op_counter, "DEL_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* network */ GNUNET_asprintf(&op_name, "op-%u-address-network", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_network)) { fprintf (stderr, "Missing address-network in operation %u `%s' in episode `%s'\n", op_counter, "DEL_ADDRESS", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); fprintf (stderr, "Found operation %s: [%llu:%llu] address `%s' plugin `%s' \n", "DEL_ADDRESS", o->peer_id, o->address_id, o->address, o->plugin); return GNUNET_OK; } static enum GNUNET_ATS_Property parse_preference_string (const char * str) { int c = 0; char *props[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString; for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) if (0 == strcmp(str, props[c])) return c; return 0; }; static int load_op_start_set_preference (struct GNUNET_ATS_TEST_Operation *o, struct Episode *e, int op_counter, char *sec_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *op_name; char *type; char *pref; /* peer id */ GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->peer_id)) { fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n", op_counter, "START_SET_PREFERENCE", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address id */ GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_id)) { fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n", op_counter, "START_SET_PREFERENCE", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address id */ GNUNET_asprintf(&op_name, "op-%u-client-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->client_id)) { fprintf (stderr, "Missing client-id in operation %u `%s' in episode `%s'\n", op_counter, "START_SET_PREFERENCE", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* generator */ GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter); if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, sec_name, op_name, &type)) ) { fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n", op_counter, "START_SET_PREFERENCE", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } /* Load arguments for set_rate, start_send, set_preference */ if (0 == strcmp (type, "constant")) { o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT; } else if (0 == strcmp (type, "linear")) { o->gen_type = GNUNET_ATS_TEST_TG_LINEAR; } else if (0 == strcmp (type, "sinus")) { o->gen_type = GNUNET_ATS_TEST_TG_SINUS; } else if (0 == strcmp (type, "random")) { o->gen_type = GNUNET_ATS_TEST_TG_RANDOM; } else { fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (type); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (type); GNUNET_free (op_name); /* Get base rate */ GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->base_rate)) { fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get max rate */ GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->max_rate)) { if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) || (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) || (GNUNET_ATS_TEST_TG_SINUS == o->gen_type)) { fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); return GNUNET_SYSERR; } } GNUNET_free (op_name); /* Get period */ GNUNET_asprintf(&op_name, "op-%u-period", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, sec_name, op_name, &o->period)) { o->period = e->duration; } GNUNET_free (op_name); /* Get frequency */ GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, sec_name, op_name, &o->frequency)) { fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get preference */ GNUNET_asprintf(&op_name, "op-%u-pref", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &pref)) { fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); return GNUNET_SYSERR; } if (0 == (o->pref_type = parse_preference_string(pref))) { fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); GNUNET_free (pref); return GNUNET_SYSERR; } GNUNET_free (pref); GNUNET_free (op_name); fprintf (stderr, "Found operation %s: [%llu:%llu]: %s = %llu\n", "START_SET_PREFERENCE", o->peer_id, o->address_id, GNUNET_ATS_print_preference_type(o->pref_type), o->base_rate); return GNUNET_OK; } static int load_op_stop_set_preference (struct GNUNET_ATS_TEST_Operation *o, struct Episode *e, int op_counter, char *sec_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *op_name; char *pref; /* peer id */ GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->peer_id)) { fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n", op_counter, "STOP_SET_PREFERENCE", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address id */ GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_id)) { fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n", op_counter, "STOP_SET_PREFERENCE", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get preference */ GNUNET_asprintf(&op_name, "op-%u-pref", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &pref)) { fprintf (stderr, "Missing preference in operation %u `%s' in episode `%s'\n", op_counter, "STOP_SET_PREFERENCE", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } if (0 == (o->pref_type = parse_preference_string(pref))) { fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); GNUNET_free (pref); return GNUNET_SYSERR; } GNUNET_free (pref); GNUNET_free (op_name); fprintf (stderr, "Found operation %s: [%llu:%llu]: %s\n", "STOP_SET_PREFERENCE", o->peer_id, o->address_id, GNUNET_ATS_print_preference_type(o->pref_type)); return GNUNET_OK; } static enum GNUNET_ATS_Property parse_property_string (const char * str) { int c = 0; char *props[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings; for (c = 0; c < GNUNET_ATS_PropertyCount; c++) if (0 == strcmp(str, props[c])) return c; return 0; }; static int load_op_start_set_property(struct GNUNET_ATS_TEST_Operation *o, struct Episode *e, int op_counter, char *sec_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *op_name; char *type; char *prop; /* peer id */ GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->peer_id)) { fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n", op_counter, "START_SET_PROPERTY", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address id */ GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_id)) { fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n", op_counter, "START_SET_PROPERTY", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* generator */ GNUNET_asprintf(&op_name, "op-%u-gen-type", op_counter); if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, sec_name, op_name, &type)) ) { fprintf (stderr, "Missing type in operation %u `%s' in episode `%s'\n", op_counter, "START_SET_PROPERTY", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } /* Load arguments for set_rate, start_send, set_preference */ if (0 == strcmp (type, "constant")) { o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT; } else if (0 == strcmp (type, "linear")) { o->gen_type = GNUNET_ATS_TEST_TG_LINEAR; } else if (0 == strcmp (type, "sinus")) { o->gen_type = GNUNET_ATS_TEST_TG_SINUS; } else if (0 == strcmp (type, "random")) { o->gen_type = GNUNET_ATS_TEST_TG_RANDOM; } else { fprintf (stderr, "Invalid generator type %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (type); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (type); GNUNET_free (op_name); /* Get base rate */ GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->base_rate)) { fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get max rate */ GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->max_rate)) { if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) || (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) || (GNUNET_ATS_TEST_TG_SINUS == o->gen_type)) { fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); return GNUNET_SYSERR; } } GNUNET_free (op_name); /* Get period */ GNUNET_asprintf(&op_name, "op-%u-period", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, sec_name, op_name, &o->period)) { o->period = e->duration; } GNUNET_free (op_name); /* Get frequency */ GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, sec_name, op_name, &o->frequency)) { fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get preference */ GNUNET_asprintf(&op_name, "op-%u-property", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &prop)) { fprintf (stderr, "Missing property in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); GNUNET_free_non_null (prop); return GNUNET_SYSERR; } if (0 == (o->prop_type = parse_property_string(prop))) { fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); GNUNET_free (prop); return GNUNET_SYSERR; } GNUNET_free (prop); GNUNET_free (op_name); fprintf (stderr, "Found operation %s: [%llu:%llu] %s = %llu\n", "START_SET_PROPERTY", o->peer_id, o->address_id, GNUNET_ATS_print_property_type (o->prop_type), o->base_rate); return GNUNET_OK; } static int load_op_stop_set_property (struct GNUNET_ATS_TEST_Operation *o, struct Episode *e, int op_counter, char *sec_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *op_name; char *pref; /* peer id */ GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->peer_id)) { fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n", op_counter, "STOP_SET_PROPERTY", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* address id */ GNUNET_asprintf(&op_name, "op-%u-address-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->address_id)) { fprintf (stderr, "Missing address-id in operation %u `%s' in episode `%s'\n", op_counter, "STOP_SET_PROPERTY", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get property */ GNUNET_asprintf(&op_name, "op-%u-property", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &pref)) { fprintf (stderr, "Missing property in operation %u `%s' in episode `%s'\n", op_counter, "STOP_SET_PROPERTY", op_name); GNUNET_free (op_name); GNUNET_free_non_null (pref); return GNUNET_SYSERR; } if (0 == (o->prop_type = parse_property_string(pref))) { fprintf (stderr, "Invalid property in operation %u `%s' in episode %u\n", op_counter, op_name, e->id); GNUNET_free (op_name); GNUNET_free_non_null (pref); return GNUNET_SYSERR; } GNUNET_free (pref); GNUNET_free (op_name); fprintf (stderr, "Found operation %s: [%llu:%llu] %s\n", "STOP_SET_PROPERTY", o->peer_id, o->address_id, GNUNET_ATS_print_property_type (o->prop_type)); return GNUNET_OK; } static int load_op_start_request (struct GNUNET_ATS_TEST_Operation *o, struct Episode *e, int op_counter, char *sec_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *op_name; /* peer id */ GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->peer_id)) { fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n", op_counter, "START_REQUEST", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); return GNUNET_OK; } static int load_op_stop_request (struct GNUNET_ATS_TEST_Operation *o, struct Episode *e, int op_counter, char *sec_name, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *op_name; /* peer id */ GNUNET_asprintf(&op_name, "op-%u-peer-id", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->peer_id)) { fprintf (stderr, "Missing peer-id in operation %u `%s' in episode `%s'\n", op_counter, "STOP_REQUEST", op_name); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); return GNUNET_OK; } static int load_episode (struct Experiment *e, struct Episode *cur, struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_ATS_TEST_Operation *o; char *sec_name; char *op_name; char *op; int op_counter = 0; int res; fprintf (stderr, "Parsing episode %u\n",cur->id); GNUNET_asprintf(&sec_name, "episode-%u", cur->id); while (1) { /* Load operation */ GNUNET_asprintf(&op_name, "op-%u-operation", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, sec_name, op_name, &op)) { GNUNET_free (op_name); break; } o = GNUNET_new (struct GNUNET_ATS_TEST_Operation); /* operations = set_rate, start_send, stop_send, set_preference */ if (0 == strcmp (op, "address_add")) { o->type = SOLVER_OP_ADD_ADDRESS; res = load_op_add_address (o, cur, op_counter, sec_name, cfg); } else if (0 == strcmp (op, "address_del")) { o->type = SOLVER_OP_DEL_ADDRESS; res = load_op_del_address (o, cur, op_counter, sec_name, cfg); } else if (0 == strcmp (op, "start_set_property")) { o->type = SOLVER_OP_START_SET_PROPERTY; res = load_op_start_set_property (o, cur, op_counter, sec_name, cfg); } else if (0 == strcmp (op, "stop_set_property")) { o->type = SOLVER_OP_STOP_SET_PROPERTY; res = load_op_stop_set_property (o, cur, op_counter, sec_name, cfg); } else if (0 == strcmp (op, "start_set_preference")) { o->type = SOLVER_OP_START_SET_PREFERENCE; res = load_op_start_set_preference (o, cur, op_counter, sec_name, cfg); } else if (0 == strcmp (op, "stop_set_preference")) { o->type = SOLVER_OP_STOP_SET_PREFERENCE; res = load_op_stop_set_preference (o, cur, op_counter, sec_name, cfg); } else if (0 == strcmp (op, "start_request")) { o->type = SOLVER_OP_START_REQUEST; res = load_op_start_request (o, cur, op_counter, sec_name, cfg); } else if (0 == strcmp (op, "stop_request")) { o->type = SOLVER_OP_STOP_REQUEST; res = load_op_stop_request(o, cur, op_counter, sec_name, cfg); } else { fprintf (stderr, "Invalid operation %u `%s' in episode %u\n", op_counter, op, cur->id); res = GNUNET_SYSERR; } GNUNET_free (op); GNUNET_free (op_name); if (GNUNET_SYSERR == res) { GNUNET_free (o); GNUNET_free (sec_name); return GNUNET_SYSERR; } GNUNET_CONTAINER_DLL_insert_tail (cur->head,cur->tail, o); op_counter++; } GNUNET_free (sec_name); return GNUNET_OK; } static int load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg) { int e_counter = 0; char *sec_name; struct GNUNET_TIME_Relative e_duration; struct Episode *cur; struct Episode *last; e_counter = 0; last = NULL; while (1) { GNUNET_asprintf(&sec_name, "episode-%u", e_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, sec_name, "duration", &e_duration)) { fprintf (stderr, "Missing duration in episode %u \n",e_counter); GNUNET_free (sec_name); break; } cur = GNUNET_new (struct Episode); cur->duration = e_duration; cur->id = e_counter; if (GNUNET_OK != load_episode (e, cur, cfg)) { GNUNET_free (sec_name); GNUNET_free (cur); return GNUNET_SYSERR; } fprintf (stderr, "Found episode %u with duration %s \n", e_counter, GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES)); /* Update experiment */ e->num_episodes ++; e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration); /* Put in linked list */ if (NULL == last) e->start = cur; else last->next = cur; GNUNET_free (sec_name); e_counter ++; last = cur; } return e_counter; } static void timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { struct Experiment *e = cls; e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; fprintf (stderr, "Experiment timeout!\n"); if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task) { GNUNET_SCHEDULER_cancel (e->episode_timeout_task); e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; } e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_SYSERR); } struct ATS_Address * create_ats_address (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id) { struct ATS_Address *aa = NULL; aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len + strlen (plugin_name) + 1); aa->peer = *peer; aa->addr_len = plugin_addr_len; aa->addr = &aa[1]; aa->plugin = (char *) &aa[1] + plugin_addr_len; memcpy (&aa[1], plugin_addr, plugin_addr_len); memcpy (aa->plugin, plugin_name, strlen (plugin_name) + 1); aa->session_id = session_id; aa->active = GNUNET_NO; aa->used = GNUNET_NO; aa->solver_information = NULL; aa->assigned_bw_in = GNUNET_BANDWIDTH_value_init(0); aa->assigned_bw_out = GNUNET_BANDWIDTH_value_init(0); return aa; } static void enforce_add_address (struct GNUNET_ATS_TEST_Operation *op) { struct TestPeer *p; struct TestAddress *a; if (NULL == (p = find_peer_by_id (op->peer_id))) { p = GNUNET_new (struct TestPeer); p->id = op->peer_id; memset (&p->peer_id, op->peer_id, sizeof (p->peer_id)); GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, p); } if (NULL != (find_address_by_id (p, op->address_id))) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Duplicate address %u for peer %u\n", op->address_id, op->peer_id); return; } a = GNUNET_new (struct TestAddress); a->aid = op->address_id; a->ats_addr = create_ats_address (&p->peer_id, op->plugin, op->address, strlen (op->address) + 1, op->address_session); memset (&p->peer_id, op->peer_id, sizeof (p->peer_id)); GNUNET_CONTAINER_DLL_insert (p->addr_head, p->addr_tail, a); GNUNET_CONTAINER_multipeermap_put (sh->addresses, &p->peer_id, a->ats_addr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding address %u for peer %u\n", op->address_id, op->peer_id); sh->env.sf.s_add (sh->solver, a->ats_addr, op->address_network); } static void enforce_del_address (struct GNUNET_ATS_TEST_Operation *op) { struct TestPeer *p; struct AddressLookupCtx ctx; if (NULL == (p = find_peer_by_id (op->peer_id))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Deleting address for unknown peer %u\n", op->peer_id); return; } ctx.plugin = op->plugin; ctx.addr = op->address; ctx.res = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (sh->addresses, &p->peer_id, find_address_it, &ctx); if (NULL == ctx.res) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Deleting unknown address for peer %u\n", op->peer_id); return; } if (NULL == (find_address_by_id (p, op->address_id))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Deleting address for unknown peer %u\n", op->peer_id); return; } GNUNET_CONTAINER_multipeermap_remove (sh->addresses, &p->peer_id, ctx.res); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Removing address %u for peer %u\n", op->address_id, op->peer_id); sh->env.sf.s_del (sh->solver, ctx.res, GNUNET_NO); GNUNET_free (ctx.res); } static void enforce_start_property (struct GNUNET_ATS_TEST_Operation *op) { struct PropertyGenerator *pg; struct TestPeer *p; struct TestAddress *a; if (NULL != (pg = find_prop_gen (op->peer_id, op->address_id, op->prop_type))) { GNUNET_ATS_solver_generate_property_stop (pg); GNUNET_free (pg); } if (NULL == (p = find_peer_by_id (op->peer_id))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Starting property generation for unknown peer %u\n", op->peer_id); return; } if (NULL == (a = find_address_by_id (p, op->address_id))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Setting property for unknown address %u\n", op->peer_id); return; } GNUNET_ATS_solver_generate_property_start (op->peer_id, op->address_id, p, a, op->gen_type, op->base_rate, op->max_rate, op->period, op->frequency, op->prop_type); } static void enforce_stop_property (struct GNUNET_ATS_TEST_Operation *op) { struct PropertyGenerator *pg = find_prop_gen(op->peer_id, op->address_id, op->prop_type); if (NULL != pg) GNUNET_ATS_solver_generate_property_stop (pg); } static void enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op) { struct PreferenceGenerator *pg; if (NULL != (pg = find_pref_gen (op->peer_id, op->address_id, op->pref_type))) { GNUNET_ATS_solver_generate_preferences_stop (pg); GNUNET_free (pg); } if (NULL == (find_peer_by_id (op->peer_id))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Starting preference generation for unknown peer %u\n", op->peer_id); return; } GNUNET_ATS_solver_generate_preferences_start (op->peer_id, op->address_id, op->client_id, op->gen_type, op->base_rate, op->max_rate, op->period, op->frequency, op->pref_type); } static void enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op) { struct PreferenceGenerator *pg = find_pref_gen(op->peer_id, op->address_id, op->pref_type); if (NULL != pg) GNUNET_ATS_solver_generate_preferences_stop (pg); } static void enforce_start_request (struct GNUNET_ATS_TEST_Operation *op) { struct TestPeer *p; const struct ATS_Address *res; if (NULL == (p = find_peer_by_id (op->peer_id))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Requesting address for unknown peer %u\n", op->peer_id); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Requesting address for peer %u\n", op->peer_id); res = sh->env.sf.s_get (sh->solver, &p->peer_id); if (NULL != res) { } } static void enforce_stop_request (struct GNUNET_ATS_TEST_Operation *op) { struct TestPeer *p; if (NULL == (p = find_peer_by_id (op->peer_id))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Requesting address for unknown peer %u\n", op->peer_id); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stop requesting address for peer %u\n", op->peer_id); sh->env.sf.s_get_stop (sh->solver, &p->peer_id); } static void enforce_episode (struct Episode *ep) { struct GNUNET_ATS_TEST_Operation *cur; for (cur = ep->head; NULL != cur; cur = cur->next) { switch (cur->type) { case SOLVER_OP_ADD_ADDRESS: fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n", print_op (cur->type), cur->peer_id, cur->address_id); enforce_add_address (cur); break; case SOLVER_OP_DEL_ADDRESS: fprintf (stderr, "Enforcing operation: %s [%llu:%llu]\n", print_op (cur->type), cur->peer_id, cur->address_id); enforce_del_address (cur); break; case SOLVER_OP_START_SET_PROPERTY: fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n", print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate); enforce_start_property (cur); break; case SOLVER_OP_STOP_SET_PROPERTY: fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n", print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate); enforce_stop_property (cur); break; case SOLVER_OP_START_SET_PREFERENCE: fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n", print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate); enforce_start_preference (cur); break; case SOLVER_OP_STOP_SET_PREFERENCE: fprintf (stderr, "Enforcing operation: %s [%llu:%llu] == %llu\n", print_op (cur->type), cur->peer_id, cur->address_id, cur->base_rate); enforce_stop_preference (cur); break; case SOLVER_OP_START_REQUEST: fprintf (stderr, "Enforcing operation: %s [%llu]\n", print_op (cur->type), cur->peer_id); enforce_start_request (cur); break; case SOLVER_OP_STOP_REQUEST: fprintf (stderr, "Enforcing operation: %s [%llu]\n", print_op (cur->type), cur->peer_id); enforce_stop_request (cur); break; default: break; } } } static void timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { struct Experiment *e = cls; e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != e->ep_done_cb) e->ep_done_cb (e->cur); /* Scheduling next */ e->cur = e->cur->next; if (NULL == e->cur) { /* done */ fprintf (stderr, "Last episode done!\n"); if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task) { GNUNET_SCHEDULER_cancel (e->experiment_timeout_task); e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; } e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK); return; } fprintf (stderr, "Running episode %u with timeout %s\n", e->cur->id, GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES)); e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration, &timeout_episode, e); enforce_episode(e->cur); } void GNUNET_ATS_solvers_experimentation_run (struct Experiment *e, GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb, GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb) { fprintf (stderr, "Running experiment `%s' with timeout %s\n", e->name, GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES)); e->e_done_cb = e_done_cb; e->ep_done_cb = ep_done_cb; e->start_time = GNUNET_TIME_absolute_get(); /* Start total time out */ e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration, &timeout_experiment, e); /* Start */ if (NULL == e->start) { GNUNET_break (0); return; } e->cur = e->start; fprintf (stderr, "Running episode %u with timeout %s\n", e->cur->id, GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES)); e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration, &timeout_episode, e); enforce_episode(e->cur); } void GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e) { if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task) { GNUNET_SCHEDULER_cancel (e->experiment_timeout_task); e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task) { GNUNET_SCHEDULER_cancel (e->episode_timeout_task); e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != e->cfg) { GNUNET_CONFIGURATION_destroy(e->cfg); e->cfg = NULL; } free_experiment (e); } struct Experiment * GNUNET_ATS_solvers_experimentation_load (char *filename) { struct Experiment *e; struct GNUNET_CONFIGURATION_Handle *cfg; e = NULL; cfg = GNUNET_CONFIGURATION_create(); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename)) { fprintf (stderr, "Failed to load `%s'\n", filename); GNUNET_CONFIGURATION_destroy (cfg); return NULL; } e = create_experiment (); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment", "name", &e->name)) { fprintf (stderr, "Invalid %s", "name"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment name: `%s'\n", e->name); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment", "cfg_file", &e->cfg_file)) { fprintf (stderr, "Invalid %s", "cfg_file"); free_experiment (e); return NULL; } else { fprintf (stderr, "Experiment configuration: `%s'\n", e->cfg_file); e->cfg = GNUNET_CONFIGURATION_create(); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (e->cfg, e->cfg_file)) { fprintf (stderr, "Invalid configuration %s", "cfg_file"); free_experiment (e); return NULL; } } if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment", "log_freq", &e->log_freq)) { fprintf (stderr, "Invalid %s", "log_freq"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment logging frequency: `%s'\n", GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES)); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment", "max_duration", &e->max_duration)) { fprintf (stderr, "Invalid %s", "max_duration"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment duration: `%s'\n", GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES)); if (GNUNET_SYSERR == load_episodes (e, cfg)) { GNUNET_ATS_solvers_experimentation_stop (e); GNUNET_CONFIGURATION_destroy (cfg); e = NULL; fprintf (stderr, "Failed to load experiment\n"); return NULL; } fprintf (stderr, "Loaded %u episodes with total duration %s\n", e->num_episodes, GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES)); GNUNET_CONFIGURATION_destroy (cfg); return e; } /** * Solver */ static int free_all_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct ATS_Address *address = value; GNUNET_break (GNUNET_OK != GNUNET_CONTAINER_multipeermap_remove (sh->env.addresses, key, value)); GNUNET_free (address); return GNUNET_OK; } void GNUNET_ATS_solvers_solver_stop (struct SolverHandle *sh) { GNUNET_STATISTICS_destroy ((struct GNUNET_STATISTICS_Handle *) sh->env.stats, GNUNET_NO); GNUNET_PLUGIN_unload (sh->plugin, sh->solver); GNUNET_CONTAINER_multipeermap_iterate (sh->addresses, &free_all_it, NULL); GNUNET_CONTAINER_multipeermap_destroy(sh->addresses); GNUNET_free (sh->plugin); GNUNET_free (sh); } /** * Load quotas for networks from configuration * * @param cfg configuration handle * @param out_dest where to write outbound quotas * @param in_dest where to write inbound quotas * @param dest_length length of inbound and outbound arrays * @return number of networks loaded */ unsigned int GNUNET_ATS_solvers_load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length) { char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; char * entry_in = NULL; char * entry_out = NULL; char * quota_out_str; char * quota_in_str; int c; int res; for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++) { in_dest[c] = 0; out_dest[c] = 0; GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]); GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]); /* quota out */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, "a_out_str)) { res = GNUNET_NO; if (0 == strcmp(quota_out_str, BIG_M_STRING)) { out_dest[c] = GNUNET_ATS_MaxBandwidth; res = GNUNET_YES; } if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c]))) res = GNUNET_YES; if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out, &out_dest[c]))) res = GNUNET_YES; if (GNUNET_NO == res) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"), network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"), network_str[c], out_dest[c]); } GNUNET_free (quota_out_str); } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"), network_str[c], GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } /* quota in */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, "a_in_str)) { res = GNUNET_NO; if (0 == strcmp(quota_in_str, BIG_M_STRING)) { in_dest[c] = GNUNET_ATS_MaxBandwidth; res = GNUNET_YES; } if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c]))) res = GNUNET_YES; if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in, &in_dest[c]))) res = GNUNET_YES; if (GNUNET_NO == res) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"), network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth); in_dest[c] = GNUNET_ATS_DefaultBandwidth; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"), network_str[c], in_dest[c]); } GNUNET_free (quota_in_str); } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"), network_str[c], GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loaded quota for network `%s' (in/out): %llu %llu\n", network_str[c], in_dest[c], out_dest[c]); GNUNET_free (entry_out); GNUNET_free (entry_in); } return GNUNET_ATS_NetworkTypeCount; } /** * Information callback for the solver * * @param cls the closure * @param op the solver operation * @param stat status of the solver operation * @param add additional solver information */ static void solver_info_cb (void *cls, enum GAS_Solver_Operation op, enum GAS_Solver_Status stat, enum GAS_Solver_Additional_Information add) { char *add_info; switch (add) { case GAS_INFO_NONE: add_info = "GAS_INFO_NONE"; break; case GAS_INFO_FULL: add_info = "GAS_INFO_MLP_FULL"; break; case GAS_INFO_UPDATED: add_info = "GAS_INFO_MLP_UPDATED"; break; case GAS_INFO_PROP_ALL: add_info = "GAS_INFO_PROP_ALL"; break; case GAS_INFO_PROP_SINGLE: add_info = "GAS_INFO_PROP_SINGLE"; break; default: add_info = "INVALID"; break; } switch (op) { case GAS_OP_SOLVE_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info); return; case GAS_OP_SOLVE_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info); return; case GAS_OP_SOLVE_SETUP_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_SETUP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_MLP_LP_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_MLP_LP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_MLP_MLP_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_MLP_MLP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; default: break; } } static void solver_bandwidth_changed_cb (void *cls, struct ATS_Address *address) { if ( (0 == ntohl (address->assigned_bw_out.value__)) && (0 == ntohl (address->assigned_bw_in.value__)) ) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Solver notified to disconnect peer `%s'\n", GNUNET_i2s (&address->peer)); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n", GNUNET_i2s (&address->peer), address, (unsigned int) ntohl (address->assigned_bw_out.value__), (unsigned int) ntohl (address->assigned_bw_in.value__)); /*if (GNUNET_YES == ph.bulk_running) GNUNET_break (0);*/ return; } const double * get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id) { return GAS_normalization_get_preferences_by_peer (id); } const double * get_property_cb (void *cls, const struct ATS_Address *address) { return GAS_normalization_get_properties ((struct ATS_Address *) address); } static void normalized_property_changed_cb (void *cls, struct ATS_Address *address, uint32_t type, double prop_rel) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Normalized property %s for peer `%s' changed to %.3f \n", GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer), prop_rel); sh->env.sf.s_address_update_property (sh->solver, address, type, 0, prop_rel); } static void normalized_preference_changed_cb (void *cls, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Normalized preference %s for peer `%s' changed to %.3f \n", GNUNET_ATS_print_preference_type (kind), GNUNET_i2s (peer), pref_rel); sh->env.sf.s_pref (sh->solver, peer, kind, pref_rel); } struct SolverHandle * GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type) { struct SolverHandle *sh; char * solver_str; switch (type) { case GNUNET_ATS_SOLVER_PROPORTIONAL: solver_str = "proportional"; break; case GNUNET_ATS_SOLVER_MLP: solver_str = "mlp"; break; case GNUNET_ATS_SOLVER_RIL: solver_str = "ril"; break; default: GNUNET_break (0); return NULL; break; } sh = GNUNET_new (struct SolverHandle); GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str); sh->addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); /* setup environment */ sh->env.cfg = e->cfg; sh->env.stats = GNUNET_STATISTICS_create ("ats", e->cfg); sh->env.addresses = sh->addresses; sh->env.bandwidth_changed_cb = &solver_bandwidth_changed_cb; sh->env.get_preferences = &get_preferences_cb; sh->env.get_property = &get_property_cb; sh->env.network_count = GNUNET_ATS_NetworkTypeCount; sh->env.info_cb = &solver_info_cb; sh->env.info_cb_cls = NULL; /* start normalization */ GAS_normalization_start (&normalized_preference_changed_cb, NULL, &normalized_property_changed_cb, NULL ); /* load quotas */ if (GNUNET_ATS_NetworkTypeCount != GNUNET_ATS_solvers_load_quotas (e->cfg, sh->env.out_quota, sh->env.in_quota, GNUNET_ATS_NetworkTypeCount)) { GNUNET_break(0); GNUNET_free (sh->plugin); GNUNET_free (sh); end_now (); return NULL; } sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env); if (NULL == sh->solver) { fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin); GNUNET_break(0); GNUNET_free (sh->plugin); GNUNET_free (sh); end_now (); return NULL; } return sh; } static void done () { struct TestPeer *cur; struct TestPeer *next; struct TestAddress *cur_a; struct TestAddress *next_a; /* Stop logging */ GNUNET_ATS_solver_logging_stop (l); /* Stop all preference generation */ GNUNET_ATS_solver_generate_preferences_stop_all (); /* Stop all property generation */ GNUNET_ATS_solver_generate_property_stop_all (); /* Clean up experiment */ if (NULL != e) { GNUNET_ATS_solvers_experimentation_stop (e); e = NULL; } if (opt_print) GNUNET_ATS_solver_logging_eval (l); if (NULL != l) { GNUNET_ATS_solver_logging_free (l); l = NULL; } next = peer_head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, cur); next_a = cur->addr_head; while (NULL != (cur_a = next_a)) { next_a = cur_a->next; GNUNET_CONTAINER_DLL_remove (cur->addr_head, cur->addr_tail, cur_a); GNUNET_free (cur_a); } GNUNET_free (cur); } if (NULL != sh) { GNUNET_ATS_solvers_solver_stop (sh); sh = NULL; } /* Shutdown */ end_now(); } static void experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success) { if (GNUNET_OK == success) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n", GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n"); GNUNET_SCHEDULER_add_now (&done, NULL); } static void episode_done_cb (struct Episode *ep) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id); } /** * Do shutdown */ static void end_now () { if (NULL != e) { GNUNET_ATS_solvers_experimentation_stop (e); e = NULL; } if (NULL != sh) { GNUNET_ATS_solvers_solver_stop (sh); sh = NULL; } } static void run (void *cls, char * const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { enum GNUNET_ATS_Solvers solver; if (NULL == opt_exp_file) { fprintf (stderr, "No experiment given ...\n"); res = 1; end_now (); return; } if (NULL == opt_solver) { fprintf (stderr, "No solver given ...\n"); res = 1; end_now (); return; } if (0 == strcmp(opt_solver, "mlp")) { solver = GNUNET_ATS_SOLVER_MLP; } else if (0 == strcmp(opt_solver, "proportional")) { solver = GNUNET_ATS_SOLVER_PROPORTIONAL; } else if (0 == strcmp(opt_solver, "ril")) { solver = GNUNET_ATS_SOLVER_RIL; } else { fprintf (stderr, "No solver given ..."); res = 1; end_now (); return; } /* load experiment */ e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file); if (NULL == e) { fprintf (stderr, "Failed to load experiment ...\n"); res = 1; end_now (); return; } /* load solver */ sh = GNUNET_ATS_solvers_solver_start (solver); if (NULL == sh) { fprintf (stderr, "Failed to start solver ...\n"); end_now (); res = 1; return; } /* start logging */ l = GNUNET_ATS_solver_logging_start (e->log_freq); /* run experiment */ GNUNET_ATS_solvers_experimentation_run (e, episode_done_cb, experiment_done_cb); /* WAIT */ } /** * Main function of the benchmark * * @param argc argument count * @param argv argument values */ int main (int argc, char *argv[]) { opt_exp_file = NULL; opt_solver = NULL; opt_log = GNUNET_NO; opt_plot = GNUNET_NO; res = 0; static struct GNUNET_GETOPT_CommandLineOption options[] = { { 's', "solver", NULL, gettext_noop ("solver to use"), 1, &GNUNET_GETOPT_set_string, &opt_solver}, { 'e', "experiment", NULL, gettext_noop ("experiment to use"), 1, &GNUNET_GETOPT_set_string, &opt_exp_file}, { 'e', "experiment", NULL, gettext_noop ("experiment to use"), 1, &GNUNET_GETOPT_set_one, &opt_verbose}, { 'p', "print", NULL, gettext_noop ("print logging"), 0, &GNUNET_GETOPT_set_one, &opt_print}, GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run (argc, argv, "gnunet-ats-solver-eval", NULL, options, &run, argv[0]); return res; } /* end of file ats-testing-experiment.c*/ gnunet-0.10.1/src/ats/test_ats_solver_mlp.conf0000644000175000017500000000061212225230043016317 00000000000000@INLINE@ test_ats_solver_default.conf [ats] #PREFIX = valgrind --leak-check=yes MODE = MLP # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 64 KiB UNSPECIFIED_QUOTA_OUT = 64 KiB # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited # LAN LAN_QUOTA_IN = unlimited LAN_QUOTA_OUT = unlimited # WAN WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB # WLAN WLAN_QUOTA_IN = 512 WLAN_QUOTA_OUT = 512gnunet-0.10.1/src/ats/test_ats_solver_add_address_and_request.c0000644000175000017500000001500212263724143021665 00000000000000/* if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_solver_add_address.c * @brief solver test: add address, request address and wait for suggest * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent); static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_assert (NULL != address); GNUNET_assert (NULL == session); GNUNET_assert (ntohl(bandwidth_in.value__) > 0); GNUNET_assert (ntohl(bandwidth_out.value__) > 0); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received sugggestion for peer `%s'\n", GNUNET_i2s (&address->peer)); GNUNET_SCHEDULER_add_now (&end, NULL); return; } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); GNUNET_ATS_suggest_address (sched_ats, &p.id, NULL, NULL); return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", mycfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (mycfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, NULL, test_ats_info, test_ats_count); } int main (int argc, char *argv[]) { char *sep; char *src_filename = GNUNET_strdup (__FILE__); char *test_filename = GNUNET_strdup (argv[0]); char *config_file; char *solver; ret = 0; if (NULL == (sep = (strstr (src_filename,".c")))) { GNUNET_break (0); return -1; } sep[0] = '\0'; if (NULL != (sep = strstr (test_filename, ".exe"))) sep[0] = '\0'; if (NULL == (solver = strstr (test_filename, src_filename))) { GNUNET_break (0); return -1; } solver += strlen (src_filename) +1; if (0 == strcmp(solver, "proportional")) { config_file = "test_ats_solver_proportional.conf"; } else if (0 == strcmp(solver, "mlp")) { config_file = "test_ats_solver_mlp.conf"; } else if ((0 == strcmp(solver, "ril"))) { config_file = "test_ats_solver_ril.conf"; } else { GNUNET_break (0); GNUNET_free (src_filename); GNUNET_free (test_filename); return 1; } GNUNET_free (src_filename); GNUNET_free (test_filename); if (0 != GNUNET_TESTING_peer_run ("test-ats-solver", config_file, &run, NULL )) return GNUNET_SYSERR; return ret; } /* end of file test_ats_solver_add_address.c */ gnunet-0.10.1/src/ats/test_ats_solver_request_and_delete_address.c0000644000175000017500000001646712263724143022417 00000000000000/* if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_solver_add_address.c * @brief solver test: add address, request address, delete address and wait for disconnect * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ static uint32_t test_ats_count; static int address_deleted = GNUNET_NO; static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent); static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { if (GNUNET_NO == address_deleted) { /* Expected address suggestion */ GNUNET_assert (NULL != address); GNUNET_assert (NULL == session); GNUNET_assert (ntohl(bandwidth_in.value__) > 0); GNUNET_assert (ntohl(bandwidth_out.value__) > 0); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received sugggestion for peer `%s', deleting address\n", GNUNET_i2s (&address->peer)); address_deleted = GNUNET_YES; GNUNET_ATS_address_destroyed (sched_ats, &test_hello_address, NULL); } else { /* Expecting disconnect */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received sugggestion for peer `%s': %u %u\n", GNUNET_i2s (&address->peer), (unsigned int) ntohl (bandwidth_in.value__), (unsigned int) ntohl (bandwidth_out.value__)); if ((ntohl(bandwidth_in.value__) == 0) && (ntohl(bandwidth_out.value__) == 0)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n"); GNUNET_SCHEDULER_add_now (&end, NULL); } } return; } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (GNUNET_NO == address_deleted) GNUNET_ATS_suggest_address (sched_ats, &p.id, NULL, NULL); return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", mycfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (mycfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, NULL, test_ats_info, test_ats_count); } int main (int argc, char *argv[]) { char *sep; char *src_filename = GNUNET_strdup (__FILE__); char *test_filename = GNUNET_strdup (argv[0]); char *config_file; char *solver; ret = 0; if (NULL == (sep = (strstr (src_filename,".c")))) { GNUNET_break (0); return -1; } sep[0] = '\0'; if (NULL != (sep = strstr (test_filename, ".exe"))) sep[0] = '\0'; if (NULL == (solver = strstr (test_filename, src_filename))) { GNUNET_break (0); return -1; } solver += strlen (src_filename) +1; if (0 == strcmp(solver, "proportional")) { config_file = "test_ats_solver_proportional.conf"; } else if (0 == strcmp(solver, "mlp")) { config_file = "test_ats_solver_mlp.conf"; } else if ((0 == strcmp(solver, "ril"))) { config_file = "test_ats_solver_ril.conf"; } else { GNUNET_break (0); GNUNET_free (src_filename); GNUNET_free (test_filename); return 1; } GNUNET_free (src_filename); GNUNET_free (test_filename); if (0 != GNUNET_TESTING_peer_run ("test-ats-solver", config_file, &run, NULL )) return GNUNET_SYSERR; return ret; } /* end of file test_ats_solver_add_address.c */ gnunet-0.10.1/src/ats/ats.conf.in0000644000175000017500000000252412272425070013437 00000000000000[ats] AUTOSTART = @AUTOSTART@ @UNIXONLY@ PORT = 2098 HOSTNAME = localhost BINARY = gnunet-service-ats ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-ats.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # Designated assignment mode: PROPORTIONAL / MLP / RIL MODE = PROPORTIONAL # Network specific inbound/outbound quotas UNSPECIFIED_QUOTA_IN = 64 KiB UNSPECIFIED_QUOTA_OUT = 64 KiB # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited # LAN LAN_QUOTA_IN = unlimited LAN_QUOTA_OUT = unlimited # WAN WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB # WLAN WLAN_QUOTA_IN = 1 MiB WLAN_QUOTA_OUT = 1 MiB # BLUETOOTH BLUETOOTH_QUOTA_IN = 128 KiB BLUETOOTH_QUOTA_OUT = 128 KiB # ATS options # MLP specific settings # MLP defaults # Maximum duration for a solution process # MLP_MAX_DURATION = 3 s # Maximum number of iterations for a solution process # MLP_MAX_ITERATIONS = 1024 # MLP_COEFFICIENT_D = 1.0 # MLP_COEFFICIENT_U = 1.0 # MLP_COEFFICIENT_R = 1.0 # MLP_MIN_BANDWIDTH = 1024 # MLP_MIN_CONNECTIONS = 4 # MLP Log settings # Dump all problems to disk # MLP_DUMP_PROBLEM_ALL = YES # Dump all solution to disk # MLP_DUMP_SOLUTION_ALL = YES # Print GLPK output # MLP_GLPK_VERBOSE = YES # Dump all problems to disk MLP_DUMP_PROBLEM_ON_FAIL = YES # Dump all solution to disk MLP_DUMP_SOLUTION_ON_FAIL = YESgnunet-0.10.1/src/ats/gnunet-ats-solver-eval.h0000644000175000017500000004032312320530515016061 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing-experiment.c * @brief ats benchmark: controlled experiment execution * @author Christian Grothoff * @author Matthias Wachs */ #ifndef GNUNET_ATS_SOLVER_EVAL_H #define GNUNET_ATS_SOLVER_EVAL_H #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_ats_plugin.h" #include "gnunet_ats_service.h" #include "gnunet-service-ats_addresses.h" #include "gnunet-service-ats_normalization.h" #include "test_ats_api_common.h" enum GeneratorType { GNUNET_ATS_TEST_TG_LINEAR, GNUNET_ATS_TEST_TG_CONSTANT, GNUNET_ATS_TEST_TG_RANDOM, GNUNET_ATS_TEST_TG_SINUS }; enum OperationType { SOLVER_OP_ADD_ADDRESS, SOLVER_OP_DEL_ADDRESS, SOLVER_OP_START_SET_PROPERTY, SOLVER_OP_STOP_SET_PROPERTY, SOLVER_OP_START_SET_PREFERENCE, SOLVER_OP_STOP_SET_PREFERENCE, SOLVER_OP_START_REQUEST, SOLVER_OP_STOP_REQUEST, }; struct SolverHandle { /** * Solver plugin name */ char *plugin; /** * Solver environment */ struct GNUNET_ATS_PluginEnvironment env; /** * Solver handle */ void *solver; /** * Address hashmap */ struct GNUNET_CONTAINER_MultiPeerMap *addresses; }; enum GNUNET_ATS_Solvers { GNUNET_ATS_SOLVER_PROPORTIONAL, GNUNET_ATS_SOLVER_MLP, GNUNET_ATS_SOLVER_RIL, }; struct LoggingTimeStep { struct LoggingTimeStep *prev; struct LoggingTimeStep *next; struct GNUNET_TIME_Absolute timestamp; }; struct TestPeer { struct TestPeer *prev; struct TestPeer *next; int id; struct GNUNET_PeerIdentity peer_id; struct TestAddress *addr_head; struct TestAddress *addr_tail; }; struct TestAddress { struct TestAddress *next; struct TestAddress *prev; int aid; struct ATS_Address *ats_addr; }; struct Episode; struct Experiment; typedef void (*GNUNET_ATS_TESTING_EpisodeDoneCallback) ( struct Episode *e); typedef void (*GNUNET_ATS_TESTING_ExperimentDoneCallback) (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success); /** * An operation in an experiment */ struct GNUNET_ATS_TEST_Operation { struct GNUNET_ATS_TEST_Operation *next; struct GNUNET_ATS_TEST_Operation *prev; long long unsigned int address_id; long long unsigned int peer_id; long long unsigned int client_id; long long unsigned int address_session; long long unsigned int address_network; char*address; char*plugin; long long unsigned int base_rate; long long unsigned int max_rate; struct GNUNET_TIME_Relative period; struct GNUNET_TIME_Relative frequency; enum OperationType type; enum GeneratorType gen_type; enum GNUNET_ATS_PreferenceKind pref_type; enum GNUNET_ATS_Property prop_type; }; struct Episode { int id; struct Episode *next; struct GNUNET_TIME_Relative duration; struct GNUNET_ATS_TEST_Operation *head; struct GNUNET_ATS_TEST_Operation *tail; }; struct LoggingHandle { GNUNET_SCHEDULER_TaskIdentifier logging_task; struct GNUNET_TIME_Relative log_freq; struct LoggingTimeStep *head; struct LoggingTimeStep *tail; }; struct Experiment { char *name; char *cfg_file; struct GNUNET_TIME_Relative log_freq; struct GNUNET_TIME_Relative max_duration; struct GNUNET_TIME_Relative total_duration; struct GNUNET_TIME_Absolute start_time; unsigned int num_episodes; struct Episode *start; struct GNUNET_CONFIGURATION_Handle *cfg; GNUNET_SCHEDULER_TaskIdentifier experiment_timeout_task; GNUNET_SCHEDULER_TaskIdentifier episode_timeout_task; struct Episode *cur; GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb; GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb; }; struct PreferenceGenerator { struct PreferenceGenerator *prev; struct PreferenceGenerator *next; enum GeneratorType type; unsigned int peer; unsigned int address_id; unsigned int client_id; enum GNUNET_ATS_PreferenceKind kind; long int base_value; long int max_value; struct GNUNET_TIME_Relative duration_period; struct GNUNET_TIME_Relative frequency; GNUNET_SCHEDULER_TaskIdentifier set_task; struct GNUNET_TIME_Absolute next_ping_transmission; struct GNUNET_TIME_Absolute time_start; }; struct PropertyGenerator { struct PropertyGenerator *prev; struct PropertyGenerator *next; enum GeneratorType type; unsigned int peer; unsigned int address_id; struct TestPeer *test_peer; struct TestAddress *test_address; uint32_t ats_property; long int base_value; long int max_value; struct GNUNET_TIME_Relative duration_period; struct GNUNET_TIME_Relative frequency; GNUNET_SCHEDULER_TaskIdentifier set_task; struct GNUNET_TIME_Absolute next_ping_transmission; struct GNUNET_TIME_Absolute time_start; }; /* LEGACY */ #if 0 #define TEST_ATS_PREFERENCE_DEFAULT 1.0 /** * Message type sent for traffic generation */ #define TEST_MESSAGE_TYPE_PING 12345 /** * Message type sent as response during traffic generation */ #define TEST_MESSAGE_TYPE_PONG 12346 /** * Size of test messages */ #define TEST_MESSAGE_SIZE 100 struct BenchmarkPartner; struct BenchmarkPeer; struct GNUNET_ATS_TEST_Topology; struct TrafficGenerator; /** * Callback to call when topology setup is completed * * @param cls the closure * @param masters array of master peers * @param slaves array of master peers */ typedef void (*GNUNET_ATS_TEST_TopologySetupDoneCallback) (void *cls, struct BenchmarkPeer *masters, struct BenchmarkPeer *slaves); /** * Callback called when logging is required for the data contained * * @param cls the closure * @param address an address * @param address_active is address active * @param bandwidth_out bandwidth outbound * @param bandwidth_in bandwidth inbound * @param ats ats information * @param ats_count number of ats inforation */ typedef void (*GNUNET_ATS_TEST_LogRequest) (void *cls, const struct GNUNET_HELLO_Address *address_id, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * Information we track for a peer in the testbed. */ struct BenchmarkPeer { /** * Handle with testbed. */ struct GNUNET_TESTBED_Peer *peer; /** * Unique identifier */ int no; /** * Is this peer a measter: GNUNET_YES/GNUNET_NO */ int master; /** * Peer ID */ struct GNUNET_PeerIdentity id; /** * Testbed operation to get peer information */ struct GNUNET_TESTBED_Operation *peer_id_op; /** * Testbed operation to connect to ATS performance service */ struct GNUNET_TESTBED_Operation *ats_perf_op; /** * Testbed operation to connect to core */ struct GNUNET_TESTBED_Operation *comm_op; /** * ATS performance handle */ struct GNUNET_ATS_PerformanceHandle *ats_perf_handle; /** * Masters only: * Testbed connect operations to connect masters to slaves */ struct TestbedConnectOperation *core_connect_ops; /** * Core handle */ struct GNUNET_CORE_Handle *ch; /** * Core handle */ struct GNUNET_TRANSPORT_Handle *th; /** * Masters only: * Peer to set ATS preferences for */ struct BenchmarkPeer *pref_partner; /** * Masters only * Progress task */ GNUNET_SCHEDULER_TaskIdentifier ats_task; /** * Masters only * Progress task */ double pref_value; /** * Array of partners with num_slaves entries (if master) or * num_master entries (if slave) */ struct BenchmarkPartner *partners; /** * Number of partners */ int num_partners; /** * Number of core connections */ int core_connections; /** * Masters only: * Number of connections to slave peers */ int core_slave_connections; /** * Total number of messages this peer has sent */ unsigned int total_messages_sent; /** * Total number of bytes this peer has sent */ unsigned int total_bytes_sent; /** * Total number of messages this peer has received */ unsigned int total_messages_received; /** * Total number of bytes this peer has received */ unsigned int total_bytes_received; }; struct TrafficGenerator { struct TrafficGenerator *prev; struct TrafficGenerator *next; enum GeneratorType type; struct BenchmarkPeer *src; struct BenchmarkPartner *dest; long int base_rate; long int max_rate; struct GNUNET_TIME_Relative duration_period; GNUNET_SCHEDULER_TaskIdentifier send_task; struct GNUNET_TIME_Absolute next_ping_transmission; struct GNUNET_TIME_Absolute time_start; }; struct PreferenceGenerator { struct PreferenceGenerator *prev; struct PreferenceGenerator *next; enum GeneratorType type; struct BenchmarkPeer *src; struct BenchmarkPartner *dest; enum GNUNET_ATS_PreferenceKind kind; long int base_value; long int max_value; struct GNUNET_TIME_Relative duration_period; struct GNUNET_TIME_Relative frequency; GNUNET_SCHEDULER_TaskIdentifier set_task; struct GNUNET_TIME_Absolute next_ping_transmission; struct GNUNET_TIME_Absolute time_start; }; /** * Information about a benchmarking partner */ struct BenchmarkPartner { /** * The peer itself this partner belongs to */ struct BenchmarkPeer *me; /** * The partner peer */ struct BenchmarkPeer *dest; /** * Core transmit handles */ struct GNUNET_CORE_TransmitHandle *cth; /** * Transport transmit handles */ struct GNUNET_TRANSPORT_TransmitHandle *tth; struct TrafficGenerator *tg; struct PreferenceGenerator *pg; /** * Timestamp to calculate communication layer delay */ struct GNUNET_TIME_Absolute last_message_sent; /** * Accumulated RTT for all messages */ unsigned int total_app_rtt; /** * Number of messages sent to this partner */ unsigned int messages_sent; /** * Number of bytes sent to this partner */ unsigned int bytes_sent; /** * Number of messages received from this partner */ unsigned int messages_received; /** * Number of bytes received from this partner */ unsigned int bytes_received; /* Current ATS properties */ uint32_t ats_distance; uint32_t ats_delay; uint32_t bandwidth_in; uint32_t bandwidth_out; uint32_t ats_utilization_up; uint32_t ats_utilization_down; uint32_t ats_network_type; uint32_t ats_cost_wan; uint32_t ats_cost_lan; uint32_t ats_cost_wlan; double pref_bandwidth; double pref_delay; }; /** * Overall state of the performance benchmark */ struct BenchmarkState { /** * Are we connected to ATS service of all peers: GNUNET_YES/NO */ int connected_ATS_service; /** * Are we connected to CORE service of all peers: GNUNET_YES/NO */ int connected_COMM_service; /** * Are we connected to all peers: GNUNET_YES/NO */ int connected_PEERS; /** * Are we connected to all slave peers on CORE level: GNUNET_YES/NO */ int connected_CORE; /** * Are we connected to CORE service of all peers: GNUNET_YES/NO */ int benchmarking; }; struct GNUNET_ATS_TEST_Topology { /** * Shutdown task */ GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Progress task */ GNUNET_SCHEDULER_TaskIdentifier progress_task; /** * Test result */ int result; /**Test core (GNUNET_YES) or transport (GNUNET_NO) */ int test_core; /** * Solver string */ char *solver; /** * Preference string */ char *testname; /** * Preference string */ char *pref_str; /** * ATS preference value */ int pref_val; /** * Number master peers */ unsigned int num_masters; /** * Array of master peers */ struct BenchmarkPeer *mps; /** * Number slave peers */ unsigned int num_slaves; /** * Array of slave peers */ struct BenchmarkPeer *sps; /** * Benchmark duration */ struct GNUNET_TIME_Relative perf_duration; /** * Logging frequency */ struct GNUNET_TIME_Relative log_frequency; /** * Benchmark state */ struct BenchmarkState state; struct GNUNET_CORE_MessageHandler *handlers; GNUNET_TRANSPORT_ReceiveCallback transport_recv_cb; GNUNET_ATS_TEST_TopologySetupDoneCallback done_cb; GNUNET_ATS_AddressInformationCallback ats_perf_cb; void *done_cb_cls; }; /* * Experiment related functions */ /** * Execute the specified experiment * * @param e the Experiment * @param ep_done_cb a episode is completed * @param e_done_cb the experiment is completed */ void GNUNET_ATS_TEST_experimentation_run (struct Experiment *e, GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb, GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb); /** * Load an experiment from a file * * @param filename the file * @return the Experiment or NULL on failure */ struct Experiment * GNUNET_ATS_TEST_experimentation_load (char *filename); /** * Stop an experiment * * @param e the experiment */ void GNUNET_ATS_TEST_experimentation_stop (struct Experiment *e); /* * Traffic related functions */ void GNUNET_ATS_TEST_traffic_handle_ping (struct BenchmarkPartner *p); void GNUNET_ATS_TEST_traffic_handle_pong (struct BenchmarkPartner *p); /** * Generate between the source master and the partner and send traffic with a * maximum rate. * * @param src traffic source * @param dest traffic partner * @param type type of traffic to generate * @param base_rate traffic base rate to send data with * @param max_rate traffic maximum rate to send data with * @param period duration of a period of traffic generation (~ 1/frequency) * @param duration how long to generate traffic * @return the traffic generator */ struct TrafficGenerator * GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src, struct BenchmarkPartner *dest, enum GeneratorType type, long int base_rate, long int max_rate, struct GNUNET_TIME_Relative period, struct GNUNET_TIME_Relative duration); void GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg); /** * Stop all traffic generators */ void GNUNET_ATS_TEST_generate_traffic_stop_all (); struct PreferenceGenerator * GNUNET_ATS_TEST_generate_preferences_start (struct BenchmarkPeer *src, struct BenchmarkPartner *dest, enum GeneratorType type, long int base_value, long int value_rate, struct GNUNET_TIME_Relative period, struct GNUNET_TIME_Relative frequency, enum GNUNET_ATS_PreferenceKind kind); void GNUNET_ATS_TEST_generate_preferences_stop (struct PreferenceGenerator *pg); void GNUNET_ATS_TEST_generate_preferences_stop_all (); /* * Logging related functions */ /* * Topology related functions */ struct BenchmarkPeer * GNUNET_ATS_TEST_get_peer (int src); struct BenchmarkPartner * GNUNET_ATS_TEST_get_partner (int src, int dest); /** * Create a topology for ats testing * * @param name test name * @param cfg_file configuration file to use for the peers * @param num_slaves number of slaves * @param num_masters number of masters * @param test_core connect to CORE service (GNUNET_YES) or transport (GNUNET_NO) * @param done_cb function to call when topology is setup * @param done_cb_cls cls for callback * @param recv_cb callback to call when data are received * @param perf_cb callback to call when performance info are received */ void GNUNET_ATS_TEST_create_topology (char *name, char *cfg_file, unsigned int num_slaves, unsigned int num_masters, int test_core, GNUNET_ATS_TEST_TopologySetupDoneCallback done_cb, void *done_cb_cls, GNUNET_TRANSPORT_ReceiveCallback recv_cb, GNUNET_ATS_TEST_LogRequest ats_perf_cb); /** * Shutdown topology */ void GNUNET_ATS_TEST_shutdown_topology (void); #endif #endif /* #ifndef GNUNET_ATS_SOLVER_EVAL_H */ /* end of file ats-testing.h */ gnunet-0.10.1/src/ats/test_ats_mlp.conf0000644000175000017500000000237612225230043014736 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-ats-api-scheduling/ [arm] PORT = 12001 DEFAULTSERVICES = ats UNIXPATH = $GNUNET_RUNTIME_DIR/test-ats-scheduling-arm.sock [ats] #PREFIX = valgrind --leak-check=full --track-origins=yes --num-callers=25 AUTOSTART = YES PORT = 12002 HOSTNAME = localhost BINARY = gnunet-service-ats ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/test-ats-scheduling-ats.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # Enable MLP mode (default: NO) MODE = MLP # Network specific inbound/outbound quotas # UNSPECIFIED UNSPECIFIED_QUOTA_IN = unlimited UNSPECIFIED_QUOTA_OUT = unlimited # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited # LAN LAN_QUOTA_IN = unlimited LAN_QUOTA_OUT = unlimited # WAN WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB # WLAN WLAN_QUOTA_IN = 4096 WLAN_QUOTA_OUT = 4096 # MLP specific settings ATS_MIN_INTERVAL = 15000 ATS_EXEC_INTERVAL = 30000 # MLP defaults # MLP_MAX_DURATION = 3 s # MLP_MAX_ITERATIONS = 1024 # MLP_COEFFICIENT_D = 1.0 # MLP_COEFFICIENT_U = 1.0 # MLP_COEFFICIENT_R = 1.0 # MLP_MIN_BANDWIDTH = 1024 # MLP_MIN_CONNECTIONS = 4 # MLP Debugging settings DUMP_MLP = NO DUMP_SOLUTION = NO DUMP_OVERWRITE = NO DUMP_MIN_PEERS = 0 DUMP_MIN_ADDRS = 0 DUMP_OVERWRITE = NO gnunet-0.10.1/src/ats/plugin_ats_ril.c0000644000175000017500000023235212320724374014562 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/plugin_ats_ril.c * @brief ATS reinforcement learning solver * @author Fabian Oehlmann * @author Matthias Wachs */ #include "plugin_ats_ril.h" #define LOG(kind,...) GNUNET_log_from (kind, "ats-ril",__VA_ARGS__) #define RIL_MIN_BW (5 * ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__)) #define RIL_MAX_BW GNUNET_ATS_MaxBandwidth #define RIL_ACTION_INVALID -1 #define RIL_INTERVAL_EXPONENT 10 #define RIL_UTILITY_DELAY_MAX 1000 #define RIL_DEFAULT_STEP_TIME_MIN GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 200) #define RIL_DEFAULT_STEP_TIME_MAX GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 2000) #define RIL_DEFAULT_ALGORITHM RIL_ALGO_SARSA #define RIL_DEFAULT_SELECT RIL_SELECT_SOFTMAX #define RIL_DEFAULT_WELFARE RIL_WELFARE_NASH #define RIL_DEFAULT_DISCOUNT_BETA 0.6 #define RIL_DEFAULT_DISCOUNT_GAMMA 0.5 #define RIL_DEFAULT_GRADIENT_STEP_SIZE 0.01 #define RIL_DEFAULT_TRACE_DECAY 0.5 #define RIL_DEFAULT_EXPLORE_RATIO 1 #define RIL_DEFAULT_EXPLORE_DECAY 0.95 #define RIL_DEFAULT_RBF_DIVISOR 50 #define RIL_DEFAULT_TEMPERATURE 0.1 #define RIL_DEFAULT_TEMPERATURE_DECAY 1 #define RIL_INC_DEC_STEP_SIZE 1 #define RIL_NOP_DECAY 0.5 /** * ATS reinforcement learning solver * * General description */ /** * The actions, how an agent can manipulate the current assignment. I.e. how the bandwidth can be * changed for the currently chosen address. Not depicted in the enum are the actions of switching * to a particular address. The action of switching to address with index i is depicted by the * number (RIL_ACTION_TYPE_NUM + i). */ enum RIL_Action_Type { RIL_ACTION_NOTHING = 0, RIL_ACTION_BW_IN_DBL = -2, //TODO? Potentially add more actions RIL_ACTION_BW_IN_HLV = -3, RIL_ACTION_BW_IN_INC = 1, RIL_ACTION_BW_IN_DEC = 2, RIL_ACTION_BW_OUT_DBL = -4, RIL_ACTION_BW_OUT_HLV = -5, RIL_ACTION_BW_OUT_INC = 3, RIL_ACTION_BW_OUT_DEC = 4, RIL_ACTION_TYPE_NUM = 5 }; enum RIL_Algorithm { RIL_ALGO_SARSA = 0, RIL_ALGO_Q = 1 }; enum RIL_Select { RIL_SELECT_SOFTMAX = 0, RIL_SELECT_EGREEDY = 1 }; enum RIL_Welfare { RIL_WELFARE_NASH, RIL_WELFARE_EGALITARIAN }; enum RIL_E_Modification { RIL_E_DECAY, RIL_E_ZERO, RIL_E_ACCUMULATE, RIL_E_REPLACE }; /** * Global learning parameters */ struct RIL_Learning_Parameters { /** * The TD-algorithm to use */ enum RIL_Algorithm algorithm; /** * Gradient-descent step-size */ double alpha; /** * Learning discount variable in the TD-update for semi-MDPs */ double beta; /** * Learning discount factor in the TD-update for MDPs */ double gamma; /** * Trace-decay factor for eligibility traces */ double lambda; /** * Whether to accumulate or replace eligibility traces */ enum RIL_E_Modification eligibility_trace_mode; /** * Initial softmax action-selection temperature */ double temperature_init; /** * Softmax action-selection temperature */ double temperature; /** * Decay factor of the temperature value */ double temperature_decay; /** * Which measure of social welfare should be used */ enum RIL_Welfare social_welfare; /** * State space divisor */ unsigned long long rbf_divisor; /** * Action selection strategy; */ enum RIL_Select select; /** * Initial exploration ratio value */ double epsilon_init; /** * Ratio, with what probability an agent should explore in the e-greed policy */ double epsilon; /** * Decay factor of the explore ratio */ double epsilon_decay; /** * Minimal interval time between steps in milliseconds */ struct GNUNET_TIME_Relative step_time_min; /** * Maximum interval time between steps in milliseconds */ struct GNUNET_TIME_Relative step_time_max; }; /** * Wrapper for addresses to store them in agent's linked list */ struct RIL_Address_Wrapped { /** * Next in DLL */ struct RIL_Address_Wrapped *next; /** * Previous in DLL */ struct RIL_Address_Wrapped *prev; /** * The address */ struct ATS_Address *address_naked; }; struct RIL_Peer_Agent { /** * Next agent in solver's linked list */ struct RIL_Peer_Agent *next; /** * Previous agent in solver's linked list */ struct RIL_Peer_Agent *prev; /** * Environment handle */ struct GAS_RIL_Handle *envi; /** * Peer ID */ struct GNUNET_PeerIdentity peer; /** * Whether the agent is active or not */ int is_active; /** * Number of performed time-steps */ unsigned long long step_count; /** * Experience matrix W */ double ** W; /** * Number of rows of W / Number of state-vector features */ unsigned int m; /** * Number of columns of W / Number of actions */ unsigned int n; /** * Last perceived state feature vector */ double * s_old; /** * Last chosen action */ int a_old; /** * Eligibility traces */ double ** E; /** * Whether to reset the eligibility traces to 0 after a Q-exploration step */ int eligibility_reset; /** * Address in use */ struct ATS_Address * address_inuse; /** * Head of addresses DLL */ struct RIL_Address_Wrapped * addresses_head; /** * Tail of addresses DLL */ struct RIL_Address_Wrapped * addresses_tail; /** * Inbound bandwidth assigned by the agent */ unsigned long long bw_in; /** * Outbound bandwidth assigned by the agent */ unsigned long long bw_out; /** * Flag whether a suggestion has to be issued */ int suggestion_issue; /** * The address which has to be issued */ struct ATS_Address * suggestion_address; /** * The agent's last objective value */ double objective_old; /** * NOP bonus */ double nop_bonus; }; struct RIL_Scope { /** * ATS network type */ enum GNUNET_ATS_Network_Type type; /** * Total available inbound bandwidth */ unsigned long long bw_in_available; /** * Bandwidth inbound assigned in network after last step */ unsigned long long bw_in_assigned; /** * Bandwidth inbound actually utilized in the network */ unsigned long long bw_in_utilized; /** * Total available outbound bandwidth */ unsigned long long bw_out_available; /** * Bandwidth outbound assigned in network after last step */ unsigned long long bw_out_assigned; /** * Bandwidth outbound actually utilized in the network */ unsigned long long bw_out_utilized; /** * Number of active agents in scope */ unsigned int active_agent_count; /** * The social welfare achieved in the scope */ double social_welfare; }; /** * A handle for the reinforcement learning solver */ struct GAS_RIL_Handle { /** * The solver-plugin environment of the solver-plugin API */ struct GNUNET_ATS_PluginEnvironment *plugin_envi; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Number of performed steps */ unsigned long long step_count; /** * Timestamp for the last time-step */ struct GNUNET_TIME_Absolute step_time_last; /** * Task identifier of the next time-step to be executed */ GNUNET_SCHEDULER_TaskIdentifier step_next_task_id; /** * Variable discount factor, dependent on time between steps */ double global_discount_variable; /** * Integrated variable discount factor, dependent on time between steps */ double global_discount_integrated; /** * Lock for bulk operations */ int bulk_lock; /** * Number of changes during a lock */ int bulk_changes; /** * Learning parameters */ struct RIL_Learning_Parameters parameters; /** * Array of networks with global assignment state */ struct RIL_Scope * network_entries; /** * Networks count */ unsigned int networks_count; /** * List of active peer-agents */ struct RIL_Peer_Agent * agents_head; struct RIL_Peer_Agent * agents_tail; /** * Shutdown */ int done; /** * Simulate steps, i.e. schedule steps immediately */ unsigned long long simulate; }; /* * "Private" functions * --------------------------- */ /** * Estimate the current action-value for state s and action a * * @param agent agent performing the estimation * @param state s * @param action a * @return estimation value */ static double agent_q (struct RIL_Peer_Agent *agent, double *state, int action) { int i; double result = 0; for (i = 0; i < agent->m; i++) { result += state[i] * agent->W[action][i]; } GNUNET_assert(!isnan(result)); //prevent crash when learning diverges if (isinf(result)) { return isinf(result) * UINT32_MAX; } return result; } /** * Get the index of the address in the agent's list. * * @param agent agent handle * @param address address handle * @return the index, starting with zero */ static int agent_address_get_index (struct RIL_Peer_Agent *agent, struct ATS_Address *address) { int i; struct RIL_Address_Wrapped *cur; i = -1; for (cur = agent->addresses_head; NULL != cur; cur = cur->next) { i++; if (cur->address_naked == address) return i; } return i; } /** * Gets the wrapped address from the agent's list * * @param agent agent handle * @param address address handle * @return wrapped address */ static struct RIL_Address_Wrapped * agent_address_get_wrapped (struct RIL_Peer_Agent *agent, struct ATS_Address *address) { struct RIL_Address_Wrapped *cur; for (cur = agent->addresses_head; NULL != cur; cur = cur->next) if (cur->address_naked == address) return cur; return NULL; } static int agent_action_is_possible (struct RIL_Peer_Agent *agent, int action) { int address_index; switch (action) { case RIL_ACTION_NOTHING: return GNUNET_YES; break; case RIL_ACTION_BW_IN_INC: case RIL_ACTION_BW_IN_DBL: if (agent->bw_in >= RIL_MAX_BW) return GNUNET_NO; else return GNUNET_YES; break; case RIL_ACTION_BW_IN_DEC: case RIL_ACTION_BW_IN_HLV: if (agent->bw_in <= 0) return GNUNET_NO; else return GNUNET_YES; break; case RIL_ACTION_BW_OUT_INC: case RIL_ACTION_BW_OUT_DBL: if (agent->bw_out >= RIL_MAX_BW) return GNUNET_NO; else return GNUNET_YES; break; case RIL_ACTION_BW_OUT_DEC: case RIL_ACTION_BW_OUT_HLV: if (agent->bw_out <= 0) return GNUNET_NO; else return GNUNET_YES; break; default: if ((action >= RIL_ACTION_TYPE_NUM) && (action < agent->n)) //switch address action { address_index = action - RIL_ACTION_TYPE_NUM; GNUNET_assert(address_index >= 0); GNUNET_assert( address_index <= agent_address_get_index (agent, agent->addresses_tail->address_naked)); if ((agent_address_get_index(agent, agent->address_inuse) == address_index) || agent->address_inuse->active) return GNUNET_NO; else return GNUNET_YES; break; } // error - action does not exist GNUNET_assert(GNUNET_NO); } } /** * Gets the action, with the maximal estimated Q-value (i.e. the one currently estimated to bring the * most reward in the future) * * @param agent agent performing the calculation * @param state the state from which to take the action * @return the action promising most future reward */ static int agent_get_action_max (struct RIL_Peer_Agent *agent, double *state) { int i; int max_i = RIL_ACTION_INVALID; double cur_q; double max_q = -DBL_MAX; for (i = 0; i < agent->n; i++) { if (agent_action_is_possible(agent, i)) { cur_q = agent_q (agent, state, i); if (cur_q > max_q) { max_q = cur_q; max_i = i; } } } GNUNET_assert(RIL_ACTION_INVALID != max_i); return max_i; } /** * Chooses a random action from the set of possible ones * * @param agent the agent performing the action * @return the action index */ static int agent_get_action_random (struct RIL_Peer_Agent *agent) { int i; int is_possible[agent->n]; int sum = 0; int r; for (i = 0; in; i++) { if (agent_action_is_possible(agent, i)) { is_possible[i] = GNUNET_YES; sum++; } else { is_possible[i] = GNUNET_NO; } } r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, sum); sum = -1; for (i = 0; in; i++) { if (is_possible[i]) { sum++; if (sum == r) return i; } } GNUNET_assert(GNUNET_NO); return RIL_ACTION_INVALID; } /** * Updates the weights (i.e. coefficients) of the weight vector in matrix W for action a * * @param agent the agent performing the update * @param reward the reward received for the last action * @param s_next the new state, the last step got the agent into * @param a_prime the new */ static void agent_update (struct RIL_Peer_Agent *agent, double reward, double *s_next, int a_prime) { int i; int k; double delta; double **theta = agent->W; delta = agent->envi->global_discount_integrated * reward; //reward delta += agent->envi->global_discount_variable * agent_q (agent, s_next, a_prime); //discounted future value delta -= agent_q (agent, agent->s_old, agent->a_old); //one step // LOG(GNUNET_ERROR_TYPE_INFO, "update() Step# %llu Q(s,a): %f a: %f r: %f y: %f Q(s+1,a+1) = %f delta: %f\n", // agent->step_count, // agent_q (agent, agent->s_old, agent->a_old), // agent->envi->parameters.alpha, // reward, // agent->envi->global_discount_variable, // agent_q (agent, s_next, a_prime), // delta); for (k = 0; k < agent->n; k++) { for (i = 0; i < agent->m; i++) { // LOG(GNUNET_ERROR_TYPE_INFO, "alpha = %f delta = %f e[%d] = %f\n", // agent->envi->parameters.alpha, // delta, // i, // agent->e[i]); theta[k][i] += agent->envi->parameters.alpha * delta * agent->E[k][i]; } } } /** * Changes the eligibility trace vector e in various manners: * #RIL_E_ACCUMULATE - adds @a feature to each component as in accumulating eligibility traces * #RIL_E_REPLACE - resets each component to @a feature as in replacing traces * #RIL_E_DECAY - multiplies e with discount factor and lambda as in the update rule * #RIL_E_ZERO - sets e to 0 as in Watkin's Q-learning algorithm when exploring and when initializing * * @param agent the agent handle * @param mod the kind of modification * @param feature the feature vector * @param action the action to take */ static void agent_modify_eligibility (struct RIL_Peer_Agent *agent, enum RIL_E_Modification mod, double *feature, int action) { int i; int k; for (i = 0; i < agent->m; i++) { switch (mod) { case RIL_E_ACCUMULATE: agent->E[action][i] += feature[i]; break; case RIL_E_REPLACE: agent->E[action][i] = agent->E[action][i] > feature[i] ? agent->E[action][i] : feature[i]; break; case RIL_E_DECAY: for (k = 0; k < agent->n; k++) { agent->E[k][i] *= agent->envi->global_discount_variable * agent->envi->parameters.lambda; } break; case RIL_E_ZERO: for (k = 0; k < agent->n; k++) { agent->E[k][i] = 0; } break; } } } /** * Informs the environment about the status of the solver * * @param solver * @param op * @param stat */ static void ril_inform (struct GAS_RIL_Handle *solver, enum GAS_Solver_Operation op, enum GAS_Solver_Status stat) { if (NULL != solver->plugin_envi->info_cb) solver->plugin_envi->info_cb (solver->plugin_envi->info_cb_cls, op, stat, GAS_INFO_NONE); } /** * Calculates the maximum bandwidth an agent can assign in a network scope * * @param net */ static unsigned long long ril_get_max_bw (struct RIL_Scope *net) { return GNUNET_MIN(2 * GNUNET_MAX(net->bw_in_available, net->bw_out_available), GNUNET_ATS_MaxBandwidth); } /** * Changes the active assignment suggestion of the handler and invokes the bw_changed callback to * notify ATS of its new decision * * @param solver solver handle * @param agent agent handle * @param new_address the address which is to be used * @param new_bw_in the new amount of inbound bandwidth set for this address * @param new_bw_out the new amount of outbound bandwidth set for this address * @param silent disables invocation of the bw_changed callback, if GNUNET_YES */ static void envi_set_active_suggestion (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, struct ATS_Address *new_address, unsigned long long new_bw_in, unsigned long long new_bw_out, int silent) { int notify = GNUNET_NO; LOG(GNUNET_ERROR_TYPE_DEBUG, " set_active_suggestion() for peer '%s'\n", GNUNET_i2s (&agent->peer)); //address change if (agent->address_inuse != new_address) { if (NULL != agent->address_inuse) { agent->address_inuse->active = GNUNET_NO; agent->address_inuse->assigned_bw_in.value__ = htonl (0); agent->address_inuse->assigned_bw_out.value__ = htonl (0); } if (NULL != new_address) { LOG(GNUNET_ERROR_TYPE_DEBUG, " set address active: %s\n", agent->is_active ? "yes" : "no"); new_address->active = agent->is_active; new_address->assigned_bw_in.value__ = htonl (agent->bw_in); new_address->assigned_bw_out.value__ = htonl (agent->bw_out); } notify |= GNUNET_YES; } if (new_address) { //activity change if (new_address->active != agent->is_active) { new_address->active = agent->is_active; notify |= GNUNET_YES; } //bw change if (agent->bw_in != new_bw_in) { agent->bw_in = new_bw_in; new_address->assigned_bw_in.value__ = htonl (new_bw_in); notify |= GNUNET_YES; } if (agent->bw_out != new_bw_out) { agent->bw_out = new_bw_out; new_address->assigned_bw_out.value__ = htonl (new_bw_out); notify |= GNUNET_YES; } } if (notify && agent->is_active && (GNUNET_NO == silent)) { if (new_address) { LOG(GNUNET_ERROR_TYPE_DEBUG, " envi_set_active_suggestion() notify\n"); agent->suggestion_issue = GNUNET_YES; agent->suggestion_address = new_address; } else if (agent->address_inuse) { //disconnect case, no new address GNUNET_assert(0 == ntohl (agent->address_inuse->assigned_bw_in.value__)); GNUNET_assert(0 == ntohl (agent->address_inuse->assigned_bw_out.value__)); agent->bw_in = 0; agent->bw_out = 0; agent->suggestion_issue = GNUNET_YES; agent->suggestion_address = agent->address_inuse; } } agent->address_inuse = new_address; } /** * Allocates a state vector and fills it with the features present * @param solver the solver handle * @param agent the agent handle * @return pointer to the state vector */ static double * envi_get_state (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent) { double *state; double y[2]; double x[2]; double d[2]; double sigma; double f; int m; int i; int k; unsigned long long max_bw; state = GNUNET_malloc (sizeof(double) * agent->m); max_bw = ril_get_max_bw((struct RIL_Scope *) agent->address_inuse->solver_information); y[0] = (double) agent->bw_out; y[1] = (double) agent->bw_in; m = agent_address_get_index (agent, agent->address_inuse) * (solver->parameters.rbf_divisor+1) * (solver->parameters.rbf_divisor+1); for (i = 0; i <= solver->parameters.rbf_divisor; i++) { for (k = 0; k <= solver->parameters.rbf_divisor; k++) { x[0] = (double) i * (double) max_bw / (double) solver->parameters.rbf_divisor; x[1] = (double) k * (double) max_bw / (double) solver->parameters.rbf_divisor; d[0] = x[0]-y[0]; d[1] = x[1]-y[1]; sigma = (((double) max_bw / ((double) solver->parameters.rbf_divisor + 1)) * 0.5); f = exp(-((d[0]*d[0] + d[1]*d[1]) / (2 * sigma * sigma))); state[m++] = f; } } return state; } /** * Retrieves an ATS information value of an address * * @param address the address in question * @param type the ATS information type * @return the value */ static unsigned int ril_get_atsi (struct ATS_Address *address, uint32_t type) { int c1; GNUNET_assert(NULL != address); if ((NULL == address->atsi) || (0 == address->atsi_count)) return GNUNET_ATS_QUALITY_NET_DELAY == type ? UINT32_MAX : 1; for (c1 = 0; c1 < address->atsi_count; c1++) { if (ntohl (address->atsi[c1].type) == type) return ntohl (address->atsi[c1].value); } return GNUNET_ATS_QUALITY_NET_DELAY == type ? UINT32_MAX : 1; } /** * Returns the utility value of the connection an agent manages * * @param agent the agent in question * @return the utility value */ static double agent_get_utility (struct RIL_Peer_Agent *agent) { const double *preferences; double delay_atsi; double delay_norm; double pref_match; preferences = agent->envi->plugin_envi->get_preferences (agent->envi->plugin_envi->get_preference_cls, &agent->peer); delay_atsi = (double) ril_get_atsi (agent->address_inuse, GNUNET_ATS_QUALITY_NET_DELAY); delay_norm = RIL_UTILITY_DELAY_MAX*exp(-delay_atsi*0.00001); pref_match = preferences[GNUNET_ATS_PREFERENCE_LATENCY] * delay_norm; pref_match += preferences[GNUNET_ATS_PREFERENCE_BANDWIDTH] * sqrt((double) (agent->bw_in/RIL_MIN_BW) * (double) (agent->bw_out/RIL_MIN_BW)); // sqrt((double) (ril_get_atsi (agent->address_inuse, GNUNET_ATS_UTILIZATION_IN)/RIL_MIN_BW) * (double) (ril_get_atsi (agent->address_inuse, GNUNET_ATS_UTILIZATION_OUT)/RIL_MIN_BW)); // return (double) (agent->bw_in/RIL_MIN_BW); // return sqrt((double) (agent->bw_in/RIL_MIN_BW) * (double) (agent->bw_out/RIL_MIN_BW)); return pref_match; } /** * Calculates the social welfare within a network scope according to what social * welfare measure is set in the configuration. * * @param solver the solver handle * @param scope the network scope in question * @return the social welfare value */ static double ril_network_get_social_welfare (struct GAS_RIL_Handle *solver, struct RIL_Scope *scope) { struct RIL_Peer_Agent *cur; double result; switch (solver->parameters.social_welfare) { case RIL_WELFARE_EGALITARIAN: result = DBL_MAX; for (cur = solver->agents_head; NULL != cur; cur = cur->next) { if (cur->is_active && cur->address_inuse && (cur->address_inuse->solver_information == scope)) { result = GNUNET_MIN(result, agent_get_utility(cur)); } } return result; case RIL_WELFARE_NASH: result = 0; for (cur = solver->agents_head; NULL != cur; cur = cur->next) { if (cur->is_active && cur->address_inuse && (cur->address_inuse->solver_information == scope)) { result *= pow(agent_get_utility(cur), 1.0 / (double) scope->active_agent_count); } } return result; } GNUNET_assert(GNUNET_NO); return 1; } static double envi_get_penalty (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent) { struct RIL_Scope *net; unsigned long long over_max; unsigned long long over_in = 0; unsigned long long over_out = 0; net = agent->address_inuse->solver_information; if (net->bw_in_utilized > net->bw_in_available) { over_in = net->bw_in_utilized - net->bw_in_available; if (RIL_ACTION_BW_IN_INC == agent->a_old) { over_in *= 2; } } if (net->bw_out_utilized > net->bw_out_available) { over_out = net->bw_out_utilized - net->bw_out_available; if (RIL_ACTION_BW_OUT_INC == agent->a_old) { over_out *= 2; } } over_max = (over_in + over_out) / RIL_MIN_BW; return -1.0 * (double) over_max; } /** * Gets the reward for the last performed step, which is calculated in equal * parts from the local (the peer specific) and the global (for all peers * identical) reward. * * @param solver the solver handle * @param agent the agent handle * @return the reward */ static double envi_get_reward (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent) { struct RIL_Scope *net; double objective; double delta; double steady; double penalty; double reward; net = agent->address_inuse->solver_information; penalty = envi_get_penalty(solver, agent); objective = (agent_get_utility (agent) + net->social_welfare) / 2; delta = objective - agent->objective_old; agent->objective_old = objective; if (delta != 0 && penalty == 0) { agent->nop_bonus = delta * RIL_NOP_DECAY; } else { agent->nop_bonus *= RIL_NOP_DECAY; } steady = (RIL_ACTION_NOTHING == agent->a_old) ? agent->nop_bonus : 0; reward = delta + steady; return reward + penalty; } /** * Doubles the bandwidth for the active address * * @param solver solver handle * @param agent agent handle * @param direction_in if GNUNET_YES, change inbound bandwidth, otherwise the outbound bandwidth */ static void envi_action_bw_double (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, int direction_in) { unsigned long long new_bw; unsigned long long max_bw; max_bw = ril_get_max_bw((struct RIL_Scope *) agent->address_inuse->solver_information); if (direction_in) { new_bw = agent->bw_in * 2; if (new_bw < agent->bw_in || new_bw > max_bw) new_bw = max_bw; envi_set_active_suggestion (solver, agent, agent->address_inuse, new_bw, agent->bw_out, GNUNET_NO); } else { new_bw = agent->bw_out * 2; if (new_bw < agent->bw_out || new_bw > max_bw) new_bw = max_bw; envi_set_active_suggestion (solver, agent, agent->address_inuse, agent->bw_in, new_bw, GNUNET_NO); } } /** * Cuts the bandwidth for the active address in half. The least amount of bandwidth suggested, is * the minimum bandwidth for a peer, in order to not invoke a disconnect. * * @param solver solver handle * @param agent agent handle * @param direction_in if GNUNET_YES, change inbound bandwidth, otherwise change the outbound * bandwidth */ static void envi_action_bw_halven (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, int direction_in) { unsigned long long new_bw; if (direction_in) { new_bw = agent->bw_in / 2; if (new_bw <= 0 || new_bw > agent->bw_in) new_bw = 0; envi_set_active_suggestion (solver, agent, agent->address_inuse, new_bw, agent->bw_out, GNUNET_NO); } else { new_bw = agent->bw_out / 2; if (new_bw <= 0 || new_bw > agent->bw_out) new_bw = 0; envi_set_active_suggestion (solver, agent, agent->address_inuse, agent->bw_in, new_bw, GNUNET_NO); } } /** * Increases the bandwidth by 5 times the minimum bandwidth for the active address. * * @param solver solver handle * @param agent agent handle * @param direction_in if GNUNET_YES, change inbound bandwidth, otherwise change the outbound * bandwidth */ static void envi_action_bw_inc (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, int direction_in) { unsigned long long new_bw; unsigned long long max_bw; max_bw = ril_get_max_bw((struct RIL_Scope *) agent->address_inuse->solver_information); if (direction_in) { new_bw = agent->bw_in + (RIL_INC_DEC_STEP_SIZE * RIL_MIN_BW); if (new_bw < agent->bw_in || new_bw > max_bw) new_bw = max_bw; envi_set_active_suggestion (solver, agent, agent->address_inuse, new_bw, agent->bw_out, GNUNET_NO); } else { new_bw = agent->bw_out + (RIL_INC_DEC_STEP_SIZE * RIL_MIN_BW); if (new_bw < agent->bw_out || new_bw > max_bw) new_bw = max_bw; envi_set_active_suggestion (solver, agent, agent->address_inuse, agent->bw_in, new_bw, GNUNET_NO); } } /** * Decreases the bandwidth by 5 times the minimum bandwidth for the active address. The least amount * of bandwidth suggested, is the minimum bandwidth for a peer, in order to not invoke a disconnect. * * @param solver solver handle * @param agent agent handle * @param direction_in if GNUNET_YES, change inbound bandwidth, otherwise change the outbound * bandwidth */ static void envi_action_bw_dec (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, int direction_in) { unsigned long long new_bw; if (direction_in) { new_bw = agent->bw_in - (RIL_INC_DEC_STEP_SIZE * RIL_MIN_BW); if (new_bw <= 0 || new_bw > agent->bw_in) new_bw = 0; envi_set_active_suggestion (solver, agent, agent->address_inuse, new_bw, agent->bw_out, GNUNET_NO); } else { new_bw = agent->bw_out - (RIL_INC_DEC_STEP_SIZE * RIL_MIN_BW); if (new_bw <= 0 || new_bw > agent->bw_out) new_bw = 0; envi_set_active_suggestion (solver, agent, agent->address_inuse, agent->bw_in, new_bw, GNUNET_NO); } } /** * Switches to the address given by its index * * @param solver solver handle * @param agent agent handle * @param address_index index of the address as it is saved in the agent's list, starting with zero */ static void envi_action_address_switch (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, unsigned int address_index) { struct RIL_Address_Wrapped *cur; int i = 0; //cur = agent_address_get_wrapped(agent, agent->address_inuse); for (cur = agent->addresses_head; NULL != cur; cur = cur->next) { if (i == address_index) { envi_set_active_suggestion (solver, agent, cur->address_naked, agent->bw_in, agent->bw_out, GNUNET_NO); return; } i++; } //no address with address_index exists, in this case this action should not be callable GNUNET_assert(GNUNET_NO); } /** * Puts the action into effect by calling the according function * * @param solver the solver handle * @param agent the action handle * @param action the action to perform by the solver */ static void envi_do_action (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, int action) { int address_index; switch (action) { case RIL_ACTION_NOTHING: break; case RIL_ACTION_BW_IN_DBL: envi_action_bw_double (solver, agent, GNUNET_YES); break; case RIL_ACTION_BW_IN_HLV: envi_action_bw_halven (solver, agent, GNUNET_YES); break; case RIL_ACTION_BW_IN_INC: envi_action_bw_inc (solver, agent, GNUNET_YES); break; case RIL_ACTION_BW_IN_DEC: envi_action_bw_dec (solver, agent, GNUNET_YES); break; case RIL_ACTION_BW_OUT_DBL: envi_action_bw_double (solver, agent, GNUNET_NO); break; case RIL_ACTION_BW_OUT_HLV: envi_action_bw_halven (solver, agent, GNUNET_NO); break; case RIL_ACTION_BW_OUT_INC: envi_action_bw_inc (solver, agent, GNUNET_NO); break; case RIL_ACTION_BW_OUT_DEC: envi_action_bw_dec (solver, agent, GNUNET_NO); break; default: if ((action >= RIL_ACTION_TYPE_NUM) && (action < agent->n)) //switch address action { address_index = action - RIL_ACTION_TYPE_NUM; GNUNET_assert(address_index >= 0); GNUNET_assert( address_index <= agent_address_get_index (agent, agent->addresses_tail->address_naked)); envi_action_address_switch (solver, agent, address_index); break; } // error - action does not exist GNUNET_assert(GNUNET_NO); } } /** * Selects the next action using the e-greedy strategy. I.e. with a probability * of (1-e) the action with the maximum expected return will be chosen * (=> exploitation) and with probability (e) a random action will be chosen. * In case the Q-learning rule is set, the function also resets the eligibility * traces in the exploration case (after Watkin's Q-learning). * * @param agent the agent selecting an action * @param state the current state-feature vector * @return the action index */ static int agent_select_egreedy (struct RIL_Peer_Agent *agent, double *state) { int action; double r = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX) / (double) UINT32_MAX; if (r < agent->envi->parameters.epsilon) //explore { action = agent_get_action_random(agent); if (RIL_ALGO_Q == agent->envi->parameters.algorithm) { agent->eligibility_reset = GNUNET_YES; } agent->envi->parameters.epsilon *= agent->envi->parameters.epsilon_decay; return action; } else //exploit { action = agent_get_action_max(agent, state); return action; } } /** * Selects the next action with a probability corresponding to its value. The * probability is calculated using a Boltzmann distribution with a temperature * value. The higher the temperature, the more are the action selection * probabilities the same. With a temperature of 0, the selection is greedy, * i.e. always the action with the highest value is chosen. * @param agent * @param state * @return */ static int agent_select_softmax (struct RIL_Peer_Agent *agent, double *state) { int i; int a_max; double eqt[agent->n]; double p[agent->n]; double sum = 0; double r; a_max = agent_get_action_max(agent, state); for (i=0; in; i++) { if (agent_action_is_possible(agent, i)) { eqt[i] = exp(agent_q(agent,state,i) / agent->envi->parameters.temperature); sum += eqt[i]; } } for (i=0; in; i++) { if (agent_action_is_possible(agent, i)) { p[i] = eqt[i]/sum; } else { p[i] = 0; } } r = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX) / (double) UINT32_MAX; sum = 0; for (i=0; in; i++) { if (sum + p[i] > r) { if (i != a_max) { if (RIL_ALGO_Q == agent->envi->parameters.algorithm) agent->eligibility_reset = GNUNET_YES; agent->envi->parameters.temperature *= agent->envi->parameters.temperature_decay; } return i; } sum += p[i]; } GNUNET_assert(GNUNET_NO); return RIL_ACTION_INVALID; } /** * Select the next action of an agent either according to the e-greedy strategy * or the softmax strategy. * * @param agent the agent in question * @param state the current state-feature vector * @return the action index */ static int agent_select_action (struct RIL_Peer_Agent *agent, double *state) { if (agent->envi->parameters.select == RIL_SELECT_EGREEDY) { return agent_select_egreedy(agent, state); } else { return agent_select_softmax(agent, state); } } /** * Performs one step of the Markov Decision Process. Other than in the literature the step starts * after having done the last action a_old. It observes the new state s_next and the reward * received. Then the coefficient update is done according to the SARSA or Q-learning method. The * next action is put into effect. * * @param agent the agent performing the step */ static void agent_step (struct RIL_Peer_Agent *agent) { int a_next = RIL_ACTION_INVALID; int a_max; double *s_next; double reward; LOG(GNUNET_ERROR_TYPE_DEBUG, " agent_step() Peer '%s', algorithm %s\n", GNUNET_i2s (&agent->peer), agent->envi->parameters.algorithm ? "Q" : "SARSA"); s_next = envi_get_state (agent->envi, agent); reward = envi_get_reward (agent->envi, agent); if (agent->eligibility_reset) { agent_modify_eligibility(agent, RIL_E_ZERO, NULL, -1); agent->eligibility_reset = GNUNET_NO; } else { agent_modify_eligibility (agent, RIL_E_DECAY, NULL, -1); } if (RIL_ACTION_INVALID != agent->a_old) { agent_modify_eligibility (agent, agent->envi->parameters.eligibility_trace_mode, agent->s_old, agent->a_old); } switch (agent->envi->parameters.algorithm) { case RIL_ALGO_SARSA: a_next = agent_select_action (agent, s_next); if (RIL_ACTION_INVALID != agent->a_old) { //updates weights with selected action (on-policy), if not first step agent_update (agent, reward, s_next, a_next); } break; case RIL_ALGO_Q: a_max = agent_get_action_max (agent, s_next); if (RIL_ACTION_INVALID != agent->a_old) { //updates weights with best action, disregarding actually selected action (off-policy), if not first step agent_update (agent, reward, s_next, a_max); } a_next = agent_select_action (agent, s_next); break; } GNUNET_assert(RIL_ACTION_INVALID != a_next); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "step() Step# %llu R: %f IN %llu OUT %llu A: %d\n", agent->step_count, reward, agent->bw_in/1024, agent->bw_out/1024, a_next); envi_do_action (agent->envi, agent, a_next); GNUNET_free(agent->s_old); agent->s_old = s_next; agent->a_old = a_next; agent->step_count += 1; } /** * Prototype of the ril_step() procedure * * @param solver the solver handle */ static void ril_step (struct GAS_RIL_Handle *solver); /** * Task for the scheduler, which performs one step and lets the solver know that * no further step is scheduled. * * @param cls the solver handle * @param tc the task context for the scheduler */ static void ril_step_scheduler_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GAS_RIL_Handle *solver = cls; solver->step_next_task_id = GNUNET_SCHEDULER_NO_TASK; ril_step (solver); } /** * Determines how much of the available bandwidth is assigned. If more is * assigned than available it returns 1. The function is used to determine the * step size of the adaptive stepping. * * @param solver the solver handle * @return the ratio */ static double ril_get_used_resource_ratio (struct GAS_RIL_Handle *solver) { int i; struct RIL_Scope net; unsigned long long sum_assigned = 0; unsigned long long sum_available = 0; double ratio; for (i = 0; i < solver->networks_count; i++) { net = solver->network_entries[i]; if (net.bw_in_assigned > 0) //only consider scopes where an address is actually active { sum_assigned += net.bw_in_utilized; sum_assigned += net.bw_out_utilized; sum_available += net.bw_in_available; sum_available += net.bw_out_available; } } if (sum_available > 0) { ratio = ((double) sum_assigned) / ((double) sum_available); } else { ratio = 0; } return ratio > 1 ? 1 : ratio; //overutilization is possible, cap at 1 } /** * Lookup network struct by type * * @param s the solver handle * @param type the network type * @return the network struct */ static struct RIL_Scope * ril_get_network (struct GAS_RIL_Handle *s, uint32_t type) { int i; for (i = 0; i < s->networks_count; i++) { if (s->network_entries[i].type == type) { return &s->network_entries[i]; } } return NULL ; } /** * Determines whether more connections are allocated in a network scope, than * they would theoretically fit. This is used as a heuristic to determine, * whether a new connection can be allocated or not. * * @param solver the solver handle * @param network the network scope in question * @return GNUNET_YES if there are theoretically enough resources left */ static int ril_network_is_not_full (struct GAS_RIL_Handle *solver, enum GNUNET_ATS_Network_Type network) { struct RIL_Scope *net; struct RIL_Peer_Agent *agent; unsigned long long address_count = 0; for (agent = solver->agents_head; NULL != agent; agent = agent->next) { if (agent->address_inuse && agent->is_active) { net = agent->address_inuse->solver_information; if (net->type == network) { address_count++; } } } net = ril_get_network (solver, network); return (net->bw_in_available > RIL_MIN_BW * address_count) && (net->bw_out_available > RIL_MIN_BW * address_count); } /** * Unblocks an agent for which a connection request is there, that could not * be satisfied. Iterates over the addresses of the agent, if one of its * addresses can now be allocated in its scope the agent is unblocked, * otherwise it remains unchanged. * * @param solver the solver handle * @param agent the agent in question * @param silent */ static void ril_try_unblock_agent (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent, int silent) { struct RIL_Address_Wrapped *addr_wrap; struct RIL_Scope *net; unsigned long long start_in; unsigned long long start_out; for (addr_wrap = agent->addresses_head; NULL != addr_wrap; addr_wrap = addr_wrap->next) { net = addr_wrap->address_naked->solver_information; if (ril_network_is_not_full(solver, net->type)) { if (NULL == agent->address_inuse) { start_in = net->bw_in_available < net->bw_in_utilized ? (net->bw_in_available - net->bw_in_utilized) / 2 : RIL_MIN_BW; start_out = net->bw_out_available < net->bw_out_utilized ? (net->bw_out_available - net->bw_out_utilized) / 2 : RIL_MIN_BW; envi_set_active_suggestion (solver, agent, addr_wrap->address_naked, start_in, start_out, silent); } return; } } agent->address_inuse = NULL; } /** * Determines how much the reward needs to be discounted depending on the amount * of time, which has passed since the last time-step. * * @param solver the solver handle */ static void ril_calculate_discount (struct GAS_RIL_Handle *solver) { struct GNUNET_TIME_Absolute time_now; struct GNUNET_TIME_Relative time_delta; double tau; // MDP case only for debugging purposes if (solver->simulate) { solver->global_discount_variable = solver->parameters.gamma; solver->global_discount_integrated = 1; return; } // semi-MDP case //calculate tau, i.e. how many real valued time units have passed, one time unit is one minimum time step time_now = GNUNET_TIME_absolute_get (); time_delta = GNUNET_TIME_absolute_get_difference (solver->step_time_last, time_now); solver->step_time_last = time_now; tau = (double) time_delta.rel_value_us / (double) solver->parameters.step_time_min.rel_value_us; //calculate reward discounts (once per step for all agents) solver->global_discount_variable = pow (M_E, ((-1.0) * ((double) solver->parameters.beta) * tau)); solver->global_discount_integrated = (1.0 - solver->global_discount_variable) / (double) solver->parameters.beta; } /** * Count the number of active agents/connections in a network scope * * @param solver the solver handle * @param scope the network scope in question * @return the number of allocated connections */ static int ril_network_count_active_agents (struct GAS_RIL_Handle *solver, struct RIL_Scope *scope) { int c = 0; struct RIL_Peer_Agent *cur_agent; for (cur_agent = solver->agents_head; NULL != cur_agent; cur_agent = cur_agent->next) { if (cur_agent->is_active && cur_agent->address_inuse && (cur_agent->address_inuse->solver_information == scope)) { c++; } } return c; } /** * Calculates how much bandwidth is assigned in sum in a network scope, either * in the inbound or in the outbound direction. * * @param solver the solver handle * @param type the type of the network scope in question * @param direction_in GNUNET_YES if the inbound direction should be summed up, * otherwise the outbound direction will be summed up * @return the sum of the assigned bandwidths */ static unsigned long long ril_network_get_assigned (struct GAS_RIL_Handle *solver, enum GNUNET_ATS_Network_Type type, int direction_in) { struct RIL_Peer_Agent *cur; struct RIL_Scope *net; unsigned long long sum = 0; for (cur = solver->agents_head; NULL != cur; cur = cur->next) { if (cur->is_active && cur->address_inuse) { net = cur->address_inuse->solver_information; if (net->type == type) { if (direction_in) sum += cur->bw_in; else sum += cur->bw_out; } } } return sum; } /** * Calculates how much bandwidth is actually utilized in sum in a network scope, * either in the inbound or in the outbound direction. * * @param solver the solver handle * @param type the type of the network scope in question * @param direction_in GNUNET_YES if the inbound direction should be summed up, * otherwise the outbound direction will be summed up * @return the sum of the utilized bandwidths (in bytes/second) */ static unsigned long long ril_network_get_utilized (struct GAS_RIL_Handle *solver, enum GNUNET_ATS_Network_Type type, int direction_in) { struct RIL_Peer_Agent *cur; struct RIL_Scope *net; unsigned long long sum = 0; for (cur = solver->agents_head; NULL != cur; cur = cur->next) { if (cur->is_active && cur->address_inuse) { net = cur->address_inuse->solver_information; if (net->type == type) { if (direction_in) sum += ril_get_atsi (cur->address_inuse, GNUNET_ATS_UTILIZATION_IN); else sum += ril_get_atsi (cur->address_inuse, GNUNET_ATS_UTILIZATION_OUT); } } } return sum; } /** * Retrieves the state of the network scope, so that its attributes are up-to- * date. * * @param solver the solver handle */ static void ril_networks_update_state (struct GAS_RIL_Handle *solver) { int c; struct RIL_Scope *net; for (c = 0; c < solver->networks_count; c++) { net = &solver->network_entries[c]; net->bw_in_assigned = ril_network_get_assigned(solver, net->type, GNUNET_YES); net->bw_in_utilized = ril_network_get_utilized(solver, net->type, GNUNET_YES); net->bw_out_assigned = ril_network_get_assigned(solver, net->type, GNUNET_NO); net->bw_out_utilized = ril_network_get_utilized(solver, net->type, GNUNET_NO); net->active_agent_count = ril_network_count_active_agents(solver, net); net->social_welfare = ril_network_get_social_welfare(solver, net); } } /** * Schedules the next global step in an adaptive way. The more resources are * left, the earlier the next step is scheduled. This serves the reactivity of * the solver to changed inputs. * * @param solver the solver handle */ static void ril_step_schedule_next (struct GAS_RIL_Handle *solver) { double used_ratio; double factor; double y; double offset; struct GNUNET_TIME_Relative time_next; used_ratio = ril_get_used_resource_ratio (solver); GNUNET_assert( solver->parameters.step_time_min.rel_value_us <= solver->parameters.step_time_max.rel_value_us); factor = (double) GNUNET_TIME_relative_subtract (solver->parameters.step_time_max, solver->parameters.step_time_min).rel_value_us; offset = (double) solver->parameters.step_time_min.rel_value_us; y = factor * pow (used_ratio, RIL_INTERVAL_EXPONENT) + offset; GNUNET_assert(y <= (double) solver->parameters.step_time_max.rel_value_us); GNUNET_assert(y >= (double) solver->parameters.step_time_min.rel_value_us); time_next = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, (unsigned long long) y); // LOG (GNUNET_ERROR_TYPE_INFO, "ratio: %f, factor: %f, offset: %f, y: %f\n", // used_ratio, // factor, // offset, // y); if (solver->simulate) { time_next = GNUNET_TIME_UNIT_ZERO; } if ((GNUNET_SCHEDULER_NO_TASK == solver->step_next_task_id) && (GNUNET_NO == solver->done)) { solver->step_next_task_id = GNUNET_SCHEDULER_add_delayed (time_next, &ril_step_scheduler_task, solver); } } /** * Triggers one step per agent * * @param solver */ static void ril_step (struct GAS_RIL_Handle *solver) { struct RIL_Peer_Agent *cur; if (GNUNET_YES == solver->bulk_lock) { solver->bulk_changes++; return; } ril_inform (solver, GAS_OP_SOLVE_START, GAS_STAT_SUCCESS); LOG(GNUNET_ERROR_TYPE_DEBUG, " RIL step number %d\n", solver->step_count); if (0 == solver->step_count) { solver->step_time_last = GNUNET_TIME_absolute_get (); } ril_calculate_discount (solver); ril_networks_update_state (solver); //trigger one step per active, unblocked agent for (cur = solver->agents_head; NULL != cur; cur = cur->next) { if (cur->is_active) { if (NULL == cur->address_inuse) { ril_try_unblock_agent(solver, cur, GNUNET_NO); } if (cur->address_inuse) { agent_step (cur); } } } ril_networks_update_state (solver); solver->step_count += 1; ril_step_schedule_next (solver); ril_inform (solver, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS); ril_inform (solver, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, GAS_STAT_SUCCESS); for (cur = solver->agents_head; NULL != cur; cur = cur->next) { if (cur->suggestion_issue) { solver->plugin_envi->bandwidth_changed_cb(solver->plugin_envi->bw_changed_cb_cls, cur->suggestion_address); cur->suggestion_issue = GNUNET_NO; } } ril_inform (solver, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, GAS_STAT_SUCCESS); } /** * Initializes the matrix W of parameter vectors theta with small random numbers. * * @param agent The respective agent */ static void agent_w_init (struct RIL_Peer_Agent *agent) { int i; int k; for (i = 0; i < agent->n; i++) { for (k = 0; k < agent->m; k++) { agent->W[i][k] = agent->envi->parameters.alpha * (1.0 - 2.0 * ((double) GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)/(double) UINT32_MAX)); } } } /** * Initialize an agent without addresses and its knowledge base * * @param s ril solver * @param peer the one in question * @return handle to the new agent */ static struct RIL_Peer_Agent * agent_init (void *s, const struct GNUNET_PeerIdentity *peer) { int i; struct GAS_RIL_Handle * solver = s; struct RIL_Peer_Agent * agent = GNUNET_new (struct RIL_Peer_Agent); agent->envi = solver; agent->peer = *peer; agent->step_count = 0; agent->is_active = GNUNET_NO; agent->bw_in = RIL_MIN_BW; agent->bw_out = RIL_MIN_BW; agent->suggestion_issue = GNUNET_NO; agent->n = RIL_ACTION_TYPE_NUM; agent->m = 0; agent->W = (double **) GNUNET_malloc (sizeof (double *) * agent->n); agent->E = (double **) GNUNET_malloc (sizeof (double *) * agent->n); for (i = 0; i < agent->n; i++) { agent->W[i] = (double *) GNUNET_malloc (sizeof (double) * agent->m); agent->E[i] = (double *) GNUNET_malloc (sizeof (double) * agent->m); } agent_w_init(agent); agent->eligibility_reset = GNUNET_NO; agent->a_old = RIL_ACTION_INVALID; agent->s_old = GNUNET_malloc (sizeof (double) * agent->m); agent->address_inuse = NULL; agent->objective_old = 0; agent->nop_bonus = 0; return agent; } /** * Deallocate agent * * @param solver the solver handle * @param agent the agent to retire */ static void agent_die (struct GAS_RIL_Handle *solver, struct RIL_Peer_Agent *agent) { int i; for (i = 0; i < agent->n; i++) { GNUNET_free_non_null(agent->W[i]); GNUNET_free_non_null(agent->E[i]); } GNUNET_free_non_null(agent->W); GNUNET_free_non_null(agent->E); GNUNET_free_non_null(agent->s_old); GNUNET_free(agent); } /** * Returns the agent for a peer * * @param solver the solver handle * @param peer the identity of the peer * @param create whether or not to create an agent, if none is allocated yet * @return the agent */ static struct RIL_Peer_Agent * ril_get_agent (struct GAS_RIL_Handle *solver, const struct GNUNET_PeerIdentity *peer, int create) { struct RIL_Peer_Agent *cur; for (cur = solver->agents_head; NULL != cur; cur = cur->next) { if (0 == memcmp (peer, &cur->peer, sizeof(struct GNUNET_PeerIdentity))) { return cur; } } if (create) { cur = agent_init (solver, peer); GNUNET_CONTAINER_DLL_insert_tail(solver->agents_head, solver->agents_tail, cur); return cur; } return NULL ; } /** * Determine whether at least the minimum bandwidth is set for the network. Otherwise the network is * considered inactive and not used. Addresses in an inactive network are ignored. * * @param solver solver handle * @param network the network type * @return whether or not the network is considered active */ static int ril_network_is_active (struct GAS_RIL_Handle *solver, enum GNUNET_ATS_Network_Type network) { struct RIL_Scope *net; net = ril_get_network (solver, network); return net->bw_out_available >= RIL_MIN_BW; } /** * Cuts a slice out of a vector of elements. This is used to decrease the size of the matrix storing * the reward function approximation. It copies the memory, which is not cut, to the new vector, * frees the memory of the old vector, and redirects the pointer to the new one. * * @param old pointer to the pointer to the first element of the vector * @param element_size byte size of the vector elements * @param hole_start the first element to cut out * @param hole_length the number of elements to cut out * @param old_length the length of the old vector */ static void ril_cut_from_vector (void **old, size_t element_size, unsigned int hole_start, unsigned int hole_length, unsigned int old_length) { char *tmpptr; char *oldptr = (char *) *old; size_t size; unsigned int bytes_before; unsigned int bytes_hole; unsigned int bytes_after; GNUNET_assert(old_length >= hole_length); GNUNET_assert(old_length >= (hole_start + hole_length)); size = element_size * (old_length - hole_length); bytes_before = element_size * hole_start; bytes_hole = element_size * hole_length; bytes_after = element_size * (old_length - hole_start - hole_length); if (0 == size) { tmpptr = NULL; } else { tmpptr = GNUNET_malloc (size); memcpy (tmpptr, oldptr, bytes_before); memcpy (tmpptr + bytes_before, oldptr + (bytes_before + bytes_hole), bytes_after); } if (NULL != *old) { GNUNET_free(*old); } *old = (void *) tmpptr; } /* * Solver API functions * --------------------------- */ /** * Change relative preference for quality in solver * * @param solver the solver handle * @param peer the peer to change the preference for * @param kind the kind to change the preference * @param pref_rel the normalized preference value for this kind over all clients */ void GAS_ril_address_change_preference (void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel) { LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_change_preference() Preference '%s' for peer '%s' changed to %.2f \n", GNUNET_ATS_print_preference_type (kind), GNUNET_i2s (peer), pref_rel); struct GAS_RIL_Handle *s = solver; s->parameters.temperature = s->parameters.temperature_init; s->parameters.epsilon = s->parameters.epsilon_init; ril_step (s); } /** * Entry point for the plugin * * @param cls pointer to the 'struct GNUNET_ATS_PluginEnvironment' */ void * libgnunet_plugin_ats_ril_init (void *cls) { struct GNUNET_ATS_PluginEnvironment *env = cls; struct GAS_RIL_Handle *solver = GNUNET_new (struct GAS_RIL_Handle); struct RIL_Scope * cur; int c; char *string; LOG(GNUNET_ERROR_TYPE_DEBUG, "API_init() Initializing RIL solver\n"); GNUNET_assert(NULL != env); GNUNET_assert(NULL != env->cfg); GNUNET_assert(NULL != env->stats); GNUNET_assert(NULL != env->bandwidth_changed_cb); GNUNET_assert(NULL != env->get_preferences); GNUNET_assert(NULL != env->get_property); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number(env->cfg, "ats", "RIL_RBF_DIVISOR", &solver->parameters.rbf_divisor)) { solver->parameters.rbf_divisor = RIL_DEFAULT_RBF_DIVISOR; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (env->cfg, "ats", "RIL_STEP_TIME_MIN", &solver->parameters.step_time_min)) { solver->parameters.step_time_min = RIL_DEFAULT_STEP_TIME_MIN; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (env->cfg, "ats", "RIL_STEP_TIME_MAX", &solver->parameters.step_time_max)) { solver->parameters.step_time_max = RIL_DEFAULT_STEP_TIME_MAX; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_ALGORITHM", &string)) { solver->parameters.algorithm = !strcmp (string, "SARSA") ? RIL_ALGO_SARSA : RIL_ALGO_Q; GNUNET_free (string); } else { solver->parameters.algorithm = RIL_DEFAULT_ALGORITHM; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_SELECT", &string)) { solver->parameters.select = !strcmp (string, "EGREEDY") ? RIL_SELECT_EGREEDY : RIL_SELECT_SOFTMAX; GNUNET_free (string); } else { solver->parameters.select = RIL_DEFAULT_SELECT; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_DISCOUNT_BETA", &string)) { solver->parameters.beta = strtod (string, NULL); GNUNET_free (string); if (!(solver->parameters.beta > 0)) { LOG (GNUNET_ERROR_TYPE_WARNING, "RIL_DISCOUNT_BETA not configured as positive number. Set to default value of %f instead.\n", RIL_DEFAULT_DISCOUNT_BETA); solver->parameters.beta = RIL_DEFAULT_DISCOUNT_BETA; } } else { solver->parameters.beta = RIL_DEFAULT_DISCOUNT_BETA; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_DISCOUNT_GAMMA", &string)) { solver->parameters.gamma = strtod (string, NULL); GNUNET_free (string); if (!(solver->parameters.gamma < 1) || (solver->parameters.gamma < 0)) { LOG (GNUNET_ERROR_TYPE_WARNING, "RIL_DISCOUNT_GAMMA not configured in range [0,1[. Set to default value of %f instead.\n", RIL_DEFAULT_DISCOUNT_GAMMA); solver->parameters.gamma = RIL_DEFAULT_DISCOUNT_GAMMA; } } else { solver->parameters.gamma = RIL_DEFAULT_DISCOUNT_GAMMA; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_GRADIENT_STEP_SIZE", &string)) { solver->parameters.alpha = strtod (string, NULL); GNUNET_free (string); if (!(solver->parameters.alpha > 0) || solver->parameters.alpha > 1) { LOG (GNUNET_ERROR_TYPE_WARNING, "RIL_GRADIENT_STEP_SIZE not configured in range ]0,1]. Set to default value of %f instead.\n", RIL_DEFAULT_GRADIENT_STEP_SIZE); solver->parameters.alpha = RIL_DEFAULT_GRADIENT_STEP_SIZE; } } else { solver->parameters.alpha = RIL_DEFAULT_GRADIENT_STEP_SIZE; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_TRACE_DECAY", &string)) { solver->parameters.lambda = strtod (string, NULL); GNUNET_free (string); if (solver->parameters.lambda < 0 || solver->parameters.lambda > 1) { LOG (GNUNET_ERROR_TYPE_WARNING, "RIL_TRACE_DECAY not configured in range [0,1]. Set to default value of %f instead.\n", RIL_DEFAULT_TRACE_DECAY); solver->parameters.lambda = RIL_DEFAULT_TRACE_DECAY; } } else { solver->parameters.lambda = RIL_DEFAULT_TRACE_DECAY; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_EXPLORE_RATIO", &string)) { solver->parameters.epsilon_init = strtod (string, NULL); GNUNET_free (string); if (solver->parameters.epsilon_init < 0 || solver->parameters.epsilon_init > 1) { LOG (GNUNET_ERROR_TYPE_WARNING, "RIL_EXPLORE_RATIO not configured in range [0,1]. Set to default value of %f instead.\n", RIL_DEFAULT_EXPLORE_RATIO); solver->parameters.epsilon_init = RIL_DEFAULT_EXPLORE_RATIO; } } else { solver->parameters.epsilon_init = RIL_DEFAULT_EXPLORE_RATIO; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_EXPLORE_DECAY", &string)) { solver->parameters.epsilon_decay = strtod (string, NULL); GNUNET_free (string); if (solver->parameters.epsilon_decay < 0 || solver->parameters.epsilon_decay > 1) { LOG (GNUNET_ERROR_TYPE_WARNING, "RIL_EXPLORE_RATIO not configured in range [0,1]. Set to default value of %f instead.\n", RIL_DEFAULT_EXPLORE_DECAY); solver->parameters.epsilon_decay = RIL_DEFAULT_EXPLORE_DECAY; } } else { solver->parameters.epsilon_decay = RIL_DEFAULT_EXPLORE_DECAY; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_TEMPERATURE", &string)) { solver->parameters.temperature_init = strtod (string, NULL); GNUNET_free (string); if (solver->parameters.temperature_init <= 0) { LOG (GNUNET_ERROR_TYPE_WARNING, "RIL_TEMPERATURE not positive. Set to default value of %f instead.\n", RIL_DEFAULT_TEMPERATURE); solver->parameters.temperature_init = RIL_DEFAULT_TEMPERATURE; } } else { solver->parameters.temperature_init = RIL_DEFAULT_TEMPERATURE; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_TEMPERATURE_DECAY", &string)) { solver->parameters.temperature_decay = strtod (string, NULL); GNUNET_free (string); if (solver->parameters.temperature_decay <= 0 || solver->parameters.temperature_decay > 1) { LOG (GNUNET_ERROR_TYPE_WARNING, "RIL_TEMPERATURE_DECAY not in range [0,1]. Set to default value of %f instead.\n", RIL_DEFAULT_TEMPERATURE_DECAY); solver->parameters.temperature_decay = RIL_DEFAULT_TEMPERATURE_DECAY; } } else { solver->parameters.temperature_decay = RIL_DEFAULT_TEMPERATURE_DECAY; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "ats", "RIL_SIMULATE", &solver->simulate)) { solver->simulate = GNUNET_NO; } if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno(env->cfg, "ats", "RIL_REPLACE_TRACES")) { solver->parameters.eligibility_trace_mode = RIL_E_REPLACE; } else { solver->parameters.eligibility_trace_mode = RIL_E_ACCUMULATE; } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (env->cfg, "ats", "RIL_SOCIAL_WELFARE", &string)) { solver->parameters.social_welfare = !strcmp (string, "NASH") ? RIL_WELFARE_NASH : RIL_WELFARE_EGALITARIAN; GNUNET_free (string); } else { solver->parameters.social_welfare = RIL_DEFAULT_WELFARE; } env->sf.s_add = &GAS_ril_address_add; env->sf.s_address_update_property = &GAS_ril_address_property_changed; env->sf.s_address_update_session = &GAS_ril_address_session_changed; env->sf.s_address_update_inuse = &GAS_ril_address_inuse_changed; env->sf.s_address_update_network = &GAS_ril_address_change_network; env->sf.s_get = &GAS_ril_get_preferred_address; env->sf.s_get_stop = &GAS_ril_stop_get_preferred_address; env->sf.s_pref = &GAS_ril_address_change_preference; env->sf.s_feedback = &GAS_ril_address_preference_feedback; env->sf.s_del = &GAS_ril_address_delete; env->sf.s_bulk_start = &GAS_ril_bulk_start; env->sf.s_bulk_stop = &GAS_ril_bulk_stop; solver->plugin_envi = env; solver->networks_count = env->network_count; solver->network_entries = GNUNET_malloc (env->network_count * sizeof (struct RIL_Scope)); solver->step_count = 0; solver->done = GNUNET_NO; for (c = 0; c < env->network_count; c++) { cur = &solver->network_entries[c]; cur->type = env->networks[c]; cur->bw_in_available = env->in_quota[c]; cur->bw_out_available = env->out_quota[c]; LOG(GNUNET_ERROR_TYPE_DEBUG, "init() Quotas for %s network: IN %llu - OUT %llu\n", GNUNET_ATS_print_network_type(cur->type), cur->bw_in_available/1024, cur->bw_out_available/1024); } LOG(GNUNET_ERROR_TYPE_DEBUG, "init() Parameters:\n"); LOG(GNUNET_ERROR_TYPE_DEBUG, "init() Algorithm = %s, alpha = %f, beta = %f, lambda = %f\n", solver->parameters.algorithm ? "Q" : "SARSA", solver->parameters.alpha, solver->parameters.beta, solver->parameters.lambda); LOG(GNUNET_ERROR_TYPE_DEBUG, "init() exploration_ratio = %f, temperature = %f, ActionSelection = %s\n", solver->parameters.epsilon, solver->parameters.temperature, solver->parameters.select ? "EGREEDY" : "SOFTMAX"); LOG(GNUNET_ERROR_TYPE_DEBUG, "init() RBF_DIVISOR = %llu\n", solver->parameters.rbf_divisor); return solver; } /** * Exit point for the plugin * * @param cls the solver handle */ void * libgnunet_plugin_ats_ril_done (void *cls) { struct GAS_RIL_Handle *s = cls; struct RIL_Peer_Agent *cur_agent; struct RIL_Peer_Agent *next_agent; LOG(GNUNET_ERROR_TYPE_DEBUG, "API_done() Shutting down RIL solver\n"); s->done = GNUNET_YES; cur_agent = s->agents_head; while (NULL != cur_agent) { next_agent = cur_agent->next; GNUNET_CONTAINER_DLL_remove(s->agents_head, s->agents_tail, cur_agent); agent_die (s, cur_agent); cur_agent = next_agent; } if (GNUNET_SCHEDULER_NO_TASK != s->step_next_task_id) { GNUNET_SCHEDULER_cancel (s->step_next_task_id); } GNUNET_free(s->network_entries); GNUNET_free(s); return NULL; } /** * Add a new address for a peer to the solver * * The address is already contained in the addresses hashmap! * * @param solver the solver Handle * @param address the address to add * @param network network type of this address */ void GAS_ril_address_add (void *solver, struct ATS_Address *address, uint32_t network) { struct GAS_RIL_Handle *s = solver; struct RIL_Peer_Agent *agent; struct RIL_Address_Wrapped *address_wrapped; struct RIL_Scope *net; unsigned int m_new; unsigned int m_old; unsigned int n_new; unsigned int n_old; int i; unsigned int zero; LOG (GNUNET_ERROR_TYPE_DEBUG, "API_address_add()\n"); net = ril_get_network (s, network); address->solver_information = net; if (!ril_network_is_active (s, network)) { LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_add() Did not add %s address %s for peer '%s', network does not have enough bandwidth\n", address->plugin, address->addr, GNUNET_i2s (&address->peer)); return; } s->parameters.temperature = s->parameters.temperature_init; s->parameters.epsilon = s->parameters.epsilon_init; agent = ril_get_agent (s, &address->peer, GNUNET_YES); //add address address_wrapped = GNUNET_new (struct RIL_Address_Wrapped); address_wrapped->address_naked = address; GNUNET_CONTAINER_DLL_insert_tail(agent->addresses_head, agent->addresses_tail, address_wrapped); //increase size of W m_new = agent->m + ((s->parameters.rbf_divisor+1) * (s->parameters.rbf_divisor+1)); m_old = agent->m; n_new = agent->n + 1; n_old = agent->n; GNUNET_array_grow(agent->W, agent->n, n_new); agent->n = n_old; GNUNET_array_grow(agent->E, agent->n, n_new); for (i = 0; i < n_new; i++) { if (i < n_old) { agent->m = m_old; GNUNET_array_grow(agent->W[i], agent->m, m_new); agent->m = m_old; GNUNET_array_grow(agent->E[i], agent->m, m_new); } else { zero = 0; GNUNET_array_grow(agent->W[i], zero, m_new); zero = 0; GNUNET_array_grow(agent->E[i], zero, m_new); } } //increase size of old state vector agent->m = m_old; GNUNET_array_grow(agent->s_old, agent->m, m_new); ril_try_unblock_agent(s, agent, GNUNET_NO); ril_step (s); LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_add() Added %s %s address %s for peer '%s'\n", address->active ? "active" : "inactive", address->plugin, address->addr, GNUNET_i2s (&address->peer)); } /** * Delete an address in the solver * * The address is not contained in the address hashmap anymore! * * @param solver the solver handle * @param address the address to remove * @param session_only delete only session not whole address */ void GAS_ril_address_delete (void *solver, struct ATS_Address *address, int session_only) { struct GAS_RIL_Handle *s = solver; struct RIL_Peer_Agent *agent; struct RIL_Address_Wrapped *address_wrapped; int address_was_used = address->active; int address_index; unsigned int m_new; unsigned int n_new; int i; struct RIL_Scope *net; LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_delete() Delete %s%s %s address %s for peer '%s'\n", session_only ? "session for " : "", address->active ? "active" : "inactive", address->plugin, address->addr, GNUNET_i2s (&address->peer)); agent = ril_get_agent (s, &address->peer, GNUNET_NO); if (NULL == agent) { net = address->solver_information; GNUNET_assert(!ril_network_is_active (s, net->type)); LOG(GNUNET_ERROR_TYPE_DEBUG, "No agent allocated for peer yet, since address was in inactive network\n"); return; } s->parameters.temperature = s->parameters.temperature_init; s->parameters.epsilon = s->parameters.epsilon_init; address_index = agent_address_get_index (agent, address); address_wrapped = agent_address_get_wrapped (agent, address); if (NULL == address_wrapped) { net = address->solver_information; LOG(GNUNET_ERROR_TYPE_DEBUG, "Address not considered by agent, address was in inactive network\n"); return; } GNUNET_CONTAINER_DLL_remove(agent->addresses_head, agent->addresses_tail, address_wrapped); GNUNET_free(address_wrapped); //decrease W m_new = agent->m - ((s->parameters.rbf_divisor+1) * (s->parameters.rbf_divisor+1)); n_new = agent->n - 1; for (i = 0; i < agent->n; i++) { ril_cut_from_vector ((void **) &agent->W[i], sizeof(double), address_index * ((s->parameters.rbf_divisor+1) * (s->parameters.rbf_divisor+1)), ((s->parameters.rbf_divisor+1) * (s->parameters.rbf_divisor+1)), agent->m); ril_cut_from_vector ((void **) &agent->E[i], sizeof(double), address_index * ((s->parameters.rbf_divisor+1) * (s->parameters.rbf_divisor+1)), ((s->parameters.rbf_divisor+1) * (s->parameters.rbf_divisor+1)), agent->m); } GNUNET_free_non_null(agent->W[RIL_ACTION_TYPE_NUM + address_index]); GNUNET_free_non_null(agent->E[RIL_ACTION_TYPE_NUM + address_index]); ril_cut_from_vector ((void **) &agent->W, sizeof(double *), RIL_ACTION_TYPE_NUM + address_index, 1, agent->n); ril_cut_from_vector ((void **) &agent->E, sizeof(double *), RIL_ACTION_TYPE_NUM + address_index, 1, agent->n); //correct last action if (agent->a_old > (RIL_ACTION_TYPE_NUM + address_index)) { agent->a_old -= 1; } else if (agent->a_old == (RIL_ACTION_TYPE_NUM + address_index)) { agent->a_old = RIL_ACTION_INVALID; } //decrease old state vector ril_cut_from_vector ((void **) &agent->s_old, sizeof(double), address_index * ((s->parameters.rbf_divisor+1) * (s->parameters.rbf_divisor+1)), ((s->parameters.rbf_divisor+1) * (s->parameters.rbf_divisor+1)), agent->m); agent->m = m_new; agent->n = n_new; if (address_was_used) { if (NULL != agent->addresses_head) //if peer has an address left, use it { envi_set_active_suggestion (s, agent, agent->addresses_head->address_naked, agent->bw_in, agent->bw_out, GNUNET_YES); } else { envi_set_active_suggestion (s, agent, NULL, 0, 0, GNUNET_NO); } } ril_step (solver); } /** * Update the properties of an address in the solver * * @param solver solver handle * @param address the address * @param type the ATSI type in HBO * @param abs_value the absolute value of the property * @param rel_value the normalized value */ void GAS_ril_address_property_changed (void *solver, struct ATS_Address *address, uint32_t type, uint32_t abs_value, double rel_value) { LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_property_changed() Property '%s' for peer '%s' address %s changed " "to %.2f \n", GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer), address->addr, rel_value); struct GAS_RIL_Handle *s = solver; s->parameters.temperature = s->parameters.temperature_init; s->parameters.epsilon = s->parameters.epsilon_init; ril_step (s); } /** * Update the session of an address in the solver * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param cur_session the current session * @param new_session the new session */ void GAS_ril_address_session_changed (void *solver, struct ATS_Address *address, uint32_t cur_session, uint32_t new_session) { LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_session_changed()\n"); } /** * Notify the solver that an address is (not) actively used by transport * to communicate with a remote peer * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param in_use usage state */ void GAS_ril_address_inuse_changed (void *solver, struct ATS_Address *address, int in_use) { LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_inuse_changed() Usage for %s address of peer '%s' changed to %s\n", address->plugin, GNUNET_i2s (&address->peer), (GNUNET_YES == in_use) ? "USED" : "UNUSED"); } /** * Notify solver that the network an address is located in has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param current_network the current network * @param new_network the new network */ void GAS_ril_address_change_network (void *solver, struct ATS_Address *address, uint32_t current_network, uint32_t new_network) { struct GAS_RIL_Handle *s = solver; struct RIL_Peer_Agent *agent; LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_change_network() Network type changed, moving " "%s address of peer %s from '%s' to '%s'\n", (GNUNET_YES == address->active) ? "active" : "inactive", GNUNET_i2s (&address->peer), GNUNET_ATS_print_network_type (current_network), GNUNET_ATS_print_network_type (new_network)); s->parameters.temperature = s->parameters.temperature_init; s->parameters.epsilon = s->parameters.epsilon_init; if (address->active && !ril_network_is_active (solver, new_network)) { GAS_ril_address_delete (solver, address, GNUNET_NO); return; } agent = ril_get_agent (s, &address->peer, GNUNET_NO); if (NULL == agent) { GNUNET_assert(!ril_network_is_active (solver, current_network)); GAS_ril_address_add (s, address, new_network); return; } address->solver_information = ril_get_network(solver, new_network); } /** * Give feedback about the current assignment * * @param solver the solver handle * @param application the application * @param peer the peer to change the preference for * @param scope the time interval for this feedback: [now - scope .. now] * @param kind the kind to change the preference * @param score the score */ void GAS_ril_address_preference_feedback (void *solver, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score) { LOG(GNUNET_ERROR_TYPE_DEBUG, "API_address_preference_feedback() Peer '%s' got a feedback of %+.3f from application %s for " "preference %s for %d seconds\n", GNUNET_i2s (peer), "UNKNOWN", GNUNET_ATS_print_preference_type (kind), scope.rel_value_us / 1000000); } /** * Start a bulk operation * * @param solver the solver */ void GAS_ril_bulk_start (void *solver) { struct GAS_RIL_Handle *s = solver; LOG(GNUNET_ERROR_TYPE_DEBUG, "API_bulk_start() lock: %d\n", s->bulk_lock+1); s->bulk_lock++; } /** * Bulk operation done * * @param solver the solver handle */ void GAS_ril_bulk_stop (void *solver) { struct GAS_RIL_Handle *s = solver; LOG(GNUNET_ERROR_TYPE_DEBUG, "API_bulk_stop() lock: %d\n", s->bulk_lock-1); if (s->bulk_lock < 1) { GNUNET_break(0); return; } s->bulk_lock--; if (0 < s->bulk_changes) { ril_step (solver); s->bulk_changes = 0; } } /** * Tell solver to notify ATS if the address to use changes for a specific * peer using the bandwidth changed callback * * The solver must only notify about changes for peers with pending address * requests! * * @param solver the solver handle * @param peer the identity of the peer */ const struct ATS_Address * GAS_ril_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer) { struct GAS_RIL_Handle *s = solver; struct RIL_Peer_Agent *agent; LOG(GNUNET_ERROR_TYPE_DEBUG, "API_get_preferred_address()\n"); agent = ril_get_agent (s, peer, GNUNET_YES); agent->is_active = GNUNET_YES; envi_set_active_suggestion (solver, agent, agent->address_inuse, agent->bw_in, agent->bw_out, GNUNET_YES); ril_try_unblock_agent(solver, agent, GNUNET_YES); if (agent->address_inuse) { LOG(GNUNET_ERROR_TYPE_DEBUG, "API_get_preferred_address() Activated agent for peer '%s' with %s address %s\n", GNUNET_i2s (peer), agent->address_inuse->plugin, agent->address_inuse->addr); } else { LOG(GNUNET_ERROR_TYPE_DEBUG, "API_get_preferred_address() Activated agent for peer '%s', but no address available\n", GNUNET_i2s (peer)); s->parameters.temperature = s->parameters.temperature_init; s->parameters.epsilon = s->parameters.epsilon_init; } return agent->address_inuse; } /** * Tell solver stop notifying ATS about changes for this peers * * The solver must only notify about changes for peers with pending address * requests! * * @param solver the solver handle * @param peer the peer */ void GAS_ril_stop_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer) { struct GAS_RIL_Handle *s = solver; struct RIL_Peer_Agent *agent; LOG(GNUNET_ERROR_TYPE_DEBUG, "API_stop_get_preferred_address()"); agent = ril_get_agent (s, peer, GNUNET_NO); if (NULL == agent) { GNUNET_break(0); return; } if (GNUNET_NO == agent->is_active) { GNUNET_break(0); return; } s->parameters.temperature = s->parameters.temperature_init; s->parameters.epsilon = s->parameters.epsilon_init; agent->is_active = GNUNET_NO; envi_set_active_suggestion (s, agent, agent->address_inuse, agent->bw_in, agent->bw_out, GNUNET_YES); ril_step (s); LOG(GNUNET_ERROR_TYPE_DEBUG, "API_stop_get_preferred_address() Paused agent for peer '%s' with %s address\n", GNUNET_i2s (peer), agent->address_inuse->plugin); } /* end of plugin_ats_ril.c */ gnunet-0.10.1/src/ats/gnunet-service-ats_scheduling.c0000644000175000017500000004041212267431203017465 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_scheduling.c * @brief ats service, interaction with 'scheduling' API * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-ats.h" #include "gnunet-service-ats_addresses.h" #include "gnunet-service-ats_scheduling.h" #include "ats.h" /** * Context for sending messages to clients. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Actual handle to the client. */ static struct GNUNET_SERVER_Client *my_client; /** * Handle to address subsystem */ static struct GAS_Addresses_Handle *address_handle; /** * Register a new scheduling client. * * @param client handle of the new client * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GAS_scheduling_add_client (struct GNUNET_SERVER_Client *client) { if (my_client != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "This ATS already has a scheduling client, refusing new scheduling client for now.\n"); return GNUNET_SYSERR; } my_client = client; GNUNET_SERVER_notification_context_add (nc, client); return GNUNET_OK; } /** * Unregister a client (which may have been a scheduling client, * but this is not assured). * * @param client handle of the (now dead) client */ void GAS_scheduling_remove_client (struct GNUNET_SERVER_Client *client) { if (my_client != client) return; GAS_addresses_destroy_all (address_handle); my_client = NULL; } /** * Transmit the given address suggestion and bandwidth update to all scheduling * clients. * * @param peer peer for which this is an address suggestion * @param plugin_name 0-termintated string specifying the transport plugin * @param plugin_addr binary address for the plugin to use * @param plugin_addr_len number of bytes in plugin_addr * @param local_address_info the local address for the address * @param session_id session ID to use for the given client (other clients will see 0) * @param atsi performance data for the address * @param atsi_count number of performance records in 'ats' * @param bandwidth_out assigned outbound bandwidth * @param bandwidth_in assigned inbound bandwidth */ void GAS_scheduling_transmit_address_suggestion (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { struct AddressSuggestionMessage *msg; size_t plugin_name_length = strlen (plugin_name) + 1; size_t msize = sizeof (struct AddressSuggestionMessage) + atsi_count * sizeof (struct GNUNET_ATS_Information) + plugin_addr_len + plugin_name_length; char buf[msize] GNUNET_ALIGN; struct GNUNET_ATS_Information *atsp; char *addrp; if (my_client == NULL) return; GNUNET_STATISTICS_update (GSA_stats, "# address suggestions made", 1, GNUNET_NO); GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); GNUNET_assert (atsi_count < GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)); msg = (struct AddressSuggestionMessage *) buf; msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION); msg->ats_count = htonl (atsi_count); msg->peer = *peer; msg->address_length = htons (plugin_addr_len); msg->plugin_name_length = htons (plugin_name_length); msg->address_local_info = htonl (local_address_info); msg->session_id = htonl (session_id); msg->bandwidth_out = bandwidth_out; msg->bandwidth_in = bandwidth_in; atsp = (struct GNUNET_ATS_Information *) &msg[1]; memcpy (atsp, atsi, sizeof (struct GNUNET_ATS_Information) * atsi_count); addrp = (char *) &atsp[atsi_count]; memcpy (addrp, plugin_addr, plugin_addr_len); strcpy (&addrp[plugin_addr_len], plugin_name); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS sends quota for peer `%s': (in/out) %u/%u\n", GNUNET_i2s (peer), (unsigned int) ntohl (bandwidth_in.value__), (unsigned int) ntohl (bandwidth_out.value__)); GNUNET_SERVER_notification_context_unicast (nc, my_client, &msg->header, GNUNET_YES); } /** * Handle 'request address' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_request_address (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct RequestAddressMessage *msg = (const struct RequestAddressMessage *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "REQUEST_ADDRESS"); GNUNET_break (0 == ntohl (msg->reserved)); GAS_addresses_request_address (address_handle, &msg->peer); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle 'request address' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_request_address_cancel (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct RequestAddressMessage *msg = (const struct RequestAddressMessage *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "REQUEST_ADDRESS_CANCEL"); GNUNET_break (0 == ntohl (msg->reserved)); GAS_addresses_request_address_cancel (address_handle, &msg->peer); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle 'reset backoff' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_reset_backoff (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ResetBackoffMessage *msg = (const struct ResetBackoffMessage *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "RESET_BACKOFF"); GNUNET_break (0 == ntohl (msg->reserved)); GAS_addresses_handle_backoff_reset (address_handle, &msg->peer); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle 'address add' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_address_add (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct AddressUpdateMessage *m; const struct GNUNET_ATS_Information *atsi; const char *address; const char *plugin_name; uint16_t address_length; uint16_t plugin_name_length; uint32_t ats_count; uint16_t size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ADDRESS_ADD"); size = ntohs (message->size); if (size < sizeof (struct AddressUpdateMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } m = (const struct AddressUpdateMessage *) message; ats_count = ntohl (m->ats_count); address_length = ntohs (m->address_length); plugin_name_length = ntohs (m->plugin_name_length); atsi = (const struct GNUNET_ATS_Information *) &m[1]; address = (const char *) &atsi[ats_count]; if (plugin_name_length != 0) plugin_name = &address[address_length]; else plugin_name = ""; if ((address_length + plugin_name_length + ats_count * sizeof (struct GNUNET_ATS_Information) + sizeof (struct AddressUpdateMessage) != ntohs (message->size)) || (ats_count > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)) || ((plugin_name_length > 0) && (plugin_name[plugin_name_length - 1] != '\0'))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GSA_stats, "# address updates received", 1, GNUNET_NO); GAS_addresses_add (address_handle, &m->peer, plugin_name, address, address_length, ntohl(m->address_local_info), ntohl (m->session_id), atsi, ats_count); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle 'address update' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_address_update (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct AddressUpdateMessage *m; const struct GNUNET_ATS_Information *atsi; const char *address; const char *plugin_name; uint16_t address_length; uint16_t plugin_name_length; uint32_t ats_count; uint16_t size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ADDRESS_UPDATE"); size = ntohs (message->size); if (size < sizeof (struct AddressUpdateMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } m = (const struct AddressUpdateMessage *) message; ats_count = ntohl (m->ats_count); address_length = ntohs (m->address_length); plugin_name_length = ntohs (m->plugin_name_length); atsi = (const struct GNUNET_ATS_Information *) &m[1]; address = (const char *) &atsi[ats_count]; if (plugin_name_length != 0) plugin_name = &address[address_length]; else plugin_name = ""; if ((address_length + plugin_name_length + ats_count * sizeof (struct GNUNET_ATS_Information) + sizeof (struct AddressUpdateMessage) != ntohs (message->size)) || (ats_count > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)) || ((plugin_name_length > 0) && (plugin_name[plugin_name_length - 1] != '\0'))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GSA_stats, "# address updates received", 1, GNUNET_NO); GAS_addresses_update (address_handle, &m->peer, plugin_name, address, address_length, ntohl (m->address_local_info), ntohl (m->session_id), atsi, ats_count); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle 'address in use' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_address_in_use (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct AddressUseMessage *m; const char *address; const char *plugin_name; int res; uint16_t address_length; uint16_t plugin_name_length; uint16_t size; uint16_t in_use; size = ntohs (message->size); if (size < sizeof (struct AddressUseMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } m = (const struct AddressUseMessage *) message; address_length = ntohs (m->address_length); plugin_name_length = ntohs (m->plugin_name_length); address = (const char *) &m[1]; if (plugin_name_length != 0) plugin_name = &address[address_length]; else plugin_name = ""; if ((address_length + plugin_name_length + sizeof (struct AddressUseMessage) != ntohs (message->size)) || ((plugin_name_length > 0) && (plugin_name[plugin_name_length - 1] != '\0'))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } in_use = ntohs (m->in_use); res = GAS_addresses_in_use (address_handle, &m->peer, plugin_name, address, address_length, ntohl (m->address_local_info), ntohl (m->session_id), in_use); if (res == GNUNET_OK) GNUNET_SERVER_receive_done (client, GNUNET_OK); else { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); } } /** * Handle 'address destroyed' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_address_destroyed (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct AddressDestroyedMessage *m; struct SessionReleaseMessage srm; const char *address; const char *plugin_name; uint16_t address_length; uint16_t plugin_name_length; uint16_t size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message of size %u %u\n", "ADDRESS_DESTROYED", ntohs (message->size), sizeof (struct AddressDestroyedMessage)); size = ntohs (message->size); if ((size < sizeof (struct AddressDestroyedMessage)) || (client != my_client)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } m = (const struct AddressDestroyedMessage *) message; GNUNET_break (0 == ntohl (m->reserved)); address_length = ntohs (m->address_length); plugin_name_length = ntohs (m->plugin_name_length); address = (const char *) &m[1]; if (plugin_name_length != 0) plugin_name = &address[address_length]; else plugin_name = ""; if ((address_length + plugin_name_length + sizeof (struct AddressDestroyedMessage) != ntohs (message->size))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if ((plugin_name_length == 0) || (plugin_name[plugin_name_length - 1] != '\0')) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GSA_stats, "# addresses destroyed", 1, GNUNET_NO); GAS_addresses_destroy (address_handle, &m->peer, plugin_name, address, address_length, ntohl (m->address_local_info), ntohl (m->session_id)); if (0 != ntohl (m->session_id)) { srm.header.type = ntohs (GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE); srm.header.size = ntohs (sizeof (struct SessionReleaseMessage)); srm.session_id = m->session_id; srm.peer = m->peer; GNUNET_SERVER_notification_context_unicast (nc, client, &srm.header, GNUNET_NO); } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Initialize scheduling subsystem. * * @param server handle to our server * @param ah the address handle to use */ void GAS_scheduling_init (struct GNUNET_SERVER_Handle *server, struct GAS_Addresses_Handle *ah) { GNUNET_assert (NULL != ah); address_handle = ah; nc = GNUNET_SERVER_notification_context_create (server, 128); } /** * Shutdown scheduling subsystem. */ void GAS_scheduling_done () { if (NULL != my_client) { my_client = NULL; } GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } /* end of gnunet-service-ats_scheduling.c */ gnunet-0.10.1/src/ats/test_ats_api_performance_list_all_addresses_active.c0000644000175000017500000002027412263724143024060 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_performance_list_addresses.c * @brief test performance API's address listing feature * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Configuration handle */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * ATS scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * ATS performance handle */ static struct GNUNET_ATS_PerformanceHandle *perf_ats; struct GNUNET_ATS_AddressListHandle* phal; static int ret; struct Address { char *plugin; size_t plugin_len; void *addr; size_t addr_len; struct GNUNET_ATS_Information *ats; int ats_count; void *session; }; struct PeerContext { struct GNUNET_PeerIdentity id; struct Address *addr; }; static struct PeerContext p[2]; static struct Address p0_addresses[2]; static struct Address p1_addresses[2]; struct GNUNET_HELLO_Address p0_ha[2]; struct GNUNET_HELLO_Address p1_ha[2]; struct GNUNET_HELLO_Address *s_ha[2]; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void ats_perf_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { static int counter = 0; if (NULL == address) { phal = 0; if (0 == counter) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n"); GNUNET_SCHEDULER_add_now (end, NULL); } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (end_badly, NULL); } return; } else { if (0 != memcmp (&address->peer, &p[0].id, sizeof (p[0].id))) { GNUNET_break (0); GNUNET_SCHEDULER_add_now (end_badly, NULL); } } counter ++; } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (4 == value) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All addresses added, connecting to performance\n"); if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, NULL, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } phal = GNUNET_ATS_performance_list_addresses (perf_ats, &p[0].id, GNUNET_NO, ats_perf_cb, NULL); } return GNUNET_OK; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } if (phal != NULL ) { GNUNET_ATS_performance_list_addresses_cancel (phal); phal = NULL; } if (perf_ats != NULL ) { GNUNET_ATS_performance_done (perf_ats); perf_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } GNUNET_free_non_null(p0_addresses[0].addr); GNUNET_free_non_null(p0_addresses[1].addr); GNUNET_free_non_null(p1_addresses[0].addr); GNUNET_free_non_null(p1_addresses[1].addr); ret = 0; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { ret = 1; cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL ); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* set up peer 0 */ memset (&p[0].id, '1', sizeof (p[0].id)); p0_addresses[0].plugin = "test"; p0_addresses[0].session = NULL; p0_addresses[0].addr = GNUNET_strdup ("test_p0_a0"); p0_addresses[0].addr_len = strlen (p0_addresses[0].addr) + 1; p0_ha[0].address = p0_addresses[0].addr; p0_ha[0].address_length = p0_addresses[0].addr_len; p0_ha[0].peer = p[0].id; p0_ha[0].transport_name = p0_addresses[0].plugin; p0_addresses[1].plugin = "test"; p0_addresses[1].session = NULL; p0_addresses[1].addr = GNUNET_strdup ("test_p0_a1"); p0_addresses[1].addr_len = strlen (p0_addresses[1].addr) + 1; p0_ha[1].address = p0_addresses[1].addr; p0_ha[1].address_length = p0_addresses[1].addr_len; p0_ha[1].peer = p[0].id; p0_ha[1].transport_name = p0_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 0: `%s'\n", GNUNET_i2s (&p[0].id)); memset (&p[1].id, '2', sizeof (p[1].id)); p1_addresses[0].plugin = "test"; p1_addresses[0].session = NULL; p1_addresses[0].addr = GNUNET_strdup ("test_p1_a0"); p1_addresses[0].addr_len = strlen (p1_addresses[0].addr) + 1; p1_ha[0].address = p1_addresses[0].addr; p1_ha[0].address_length = p1_addresses[0].addr_len; p1_ha[0].peer = p[1].id; p1_ha[0].transport_name = p1_addresses[0].plugin; p1_addresses[1].plugin = "test"; p1_addresses[1].session = NULL; p1_addresses[1].addr = GNUNET_strdup ("test_p1_a1"); p1_addresses[1].addr_len = strlen (p1_addresses[1].addr) + 1; p1_ha[1].address = p1_addresses[1].addr; p1_ha[1].address_length = p1_addresses[1].addr_len; p1_ha[1].peer = p[1].id; p1_ha[1].transport_name = p1_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 1: `%s'\n", GNUNET_i2s (&p[1].id)); /* Add addresses */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL ); if (sched_ats == NULL ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } GNUNET_ATS_address_add (sched_ats, &p0_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p0_ha[1], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[1], NULL, NULL, 0); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test_ats_api_performance", "test_ats_api.conf", &run, NULL )) return 1; return ret; } /* end of file test_ats_api_performance_list_addresses.c */ gnunet-0.10.1/src/ats/test_ats_solver_preferences.c0000644000175000017500000001751612263724143017353 00000000000000/* if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_solver_preferences.c * @brief solver test: preference client handling * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Scheduling handle */ static struct GNUNET_ATS_PerformanceHandle *perf_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[3]; /** * Test ats count */ uint32_t test_ats_count; static int stat_cb (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent); static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Done!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } if (NULL != perf_ats) { GNUNET_ATS_performance_done (perf_ats); perf_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# active performance clients", &stat_cb, NULL ); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end (NULL, NULL ); ret = GNUNET_SYSERR; } static void perf_info_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "ATS performance info: `%s'\n", GNUNET_i2s (&address->peer)); } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { int c; double pref_val; if (NULL == perf_ats) return; for (c = 1; c < GNUNET_ATS_PreferenceCount; c++) { pref_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10); GNUNET_ATS_performance_change_preference (perf_ats, &test_hello_address.peer, GNUNET_ATS_PREFERENCE_LATENCY, pref_val, GNUNET_ATS_PREFERENCE_END); } } static int stat_cb (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { static int last_value = 0; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem, name, value); if ((0 == last_value) && (1 == value)) { if (perf_ats != NULL) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Disconnecting performance client\n"); GNUNET_ATS_performance_done(perf_ats); perf_ats = NULL; } } if ((1 == last_value) && (0 == value)) { GNUNET_SCHEDULER_add_now (&end, NULL); } last_value = value; return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL ); stats = GNUNET_STATISTICS_create ("ats", mycfg); GNUNET_STATISTICS_watch (stats, "ats", "# active performance clients", &stat_cb, NULL ); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (mycfg, &address_suggest_cb, NULL ); if (sched_ats == NULL ) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL ); return; } perf_ats = GNUNET_ATS_performance_init (mycfg, &perf_info_cb, NULL ); if (perf_ats == NULL ) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS performance!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL ); return; } /* Set up peer */ memset (&p.id, '1', sizeof(p.id)); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full (&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl (GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl (1); test_ats_info[2].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); test_ats_info[2].value = htonl (100); test_ats_count = 3; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); GNUNET_ATS_suggest_address(sched_ats, &test_hello_address.peer, NULL, NULL); } int main (int argc, char *argv[]) { char *sep; char *src_filename = GNUNET_strdup (__FILE__); char *test_filename = GNUNET_strdup (argv[0]); char *config_file; char *solver; ret = 0; if (NULL == (sep = (strstr (src_filename, ".c")))) { GNUNET_break(0); return -1; } sep[0] = '\0'; if (NULL != (sep = strstr (test_filename, ".exe"))) sep[0] = '\0'; if (NULL == (solver = strstr (test_filename, src_filename))) { GNUNET_break(0); return -1; } solver += strlen (src_filename) + 1; if (0 == strcmp (solver, "proportional")) { config_file = "test_ats_solver_proportional.conf"; } else if (0 == strcmp (solver, "mlp")) { config_file = "test_ats_solver_mlp.conf"; } else if ((0 == strcmp (solver, "ril"))) { config_file = "test_ats_solver_ril.conf"; } else { GNUNET_break(0); GNUNET_free(src_filename); GNUNET_free(test_filename); return 1; } GNUNET_free(src_filename); GNUNET_free(test_filename); if (0 != GNUNET_TESTING_peer_run ("test-ats-solver", config_file, &run, NULL )) return GNUNET_SYSERR; return ret; } /* end of file test_ats_solver_preferences.c */ gnunet-0.10.1/src/ats/gnunet-service-ats_addresses.h0000644000175000017500000005075112320530515017325 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_addresses.h * @brief ats service address management * @author Matthias Wachs * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_ATS_ADDRESSES_H #define GNUNET_SERVICE_ATS_ADDRESSES_H #include "gnunet_util_lib.h" #include "gnunet_ats_service.h" #include "gnunet-service-ats.h" #include "gnunet_statistics_service.h" #include "ats.h" /** * NOTE: Do not change this documentation. This documentation is based on * gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex * use build_txt.sh to generate plaintext output * * 1 ATS addresses : ATS address management * * This ATS addresses ("addresses") component manages the addresses known to * ATS service and suggests addresses to transport service when it is * interested in address suggestion for a peer. ATS addresses also * instantiates the bandwidth assignment mechanism (solver), notifies it * about changes to addresses and forwards changes to bandwidth assignments * to transport, depending if transport is interested in this change. * * 1.1 Input data * * 1.1.1 Addresses * * Addresses are added by specifying peer ID, plugin, address, address length * and session, if available. ATS information can be specified if available. * * 1.1.2 Networks * * ATS specifies a fix set of networks an address can belong to. For each * network an inbound and outbound quota will be specified. The available * networks and addtional helper varaibles are defined in * gnunet_ats_service.h. At the moment 5 networks are defined: * * GNUNET_ATS_NET_UNSPECIFIED * * GNUNET_ATS_NET_LOOPBACK * * GNUNET_ATS_NET_LAN * * GNUNET_ATS_NET_WAN * * GNUNET_ATS_NET_WLAN * * The total number of networks defined is stored in * GNUNET_ATS_NetworkTypeCount GNUNET_ATS_NetworkType can be used array * initializer for an int array, while GNUNET_ATS_NetworkType is an * initializer for a char array containing a string description of all * networks * * 1.1.3 Quotas * * An inbound and outbound quota for each of the networks mentioned in 1.1.2 * is loaded from ats configuration during initialization. This quota defines * to total amount of inbound and outbound traffic allowed for a specific * network. The configuration values used are in section ats: * * "NETWORK"_QUOTA_IN = * * "NETWORK"_QUOTA_IN = * * You can specify quotas by setting the to a: * * unrestricted: unlimited * * number of bytes: e.g. 10240 * * fancy value: e.g. 64 Kib * * unlimited is defined as GNUNET_ATS_MaxBandwidthString and equivalent to * the value GNUNET_ATS_MaxBandwidth Important predefined values for quotas * are: * * GNUNET_ATS_DefaultBandwidth: 65536 * * GNUNET_ATS_MaxBandwidth: UINT32_MAX * * GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT: 1024 * * Details of loading quotas and default values will be described on * * 1.1.4 Preference values * * 1.2 Data structures used * * Addresse uses struct ATS_Address for each address. The structs are stored * in a linked list and provides a pointer void *solver_information for the * solver to store address specific information. It provides the int values * active which is set to GNUNET_YES if the address is select for transport * use and used, representing that transport service is actively using this * address. Address information are stored in peer, addr, addr_len, plugin. * * 1.3 Initialization * * During initialization a hashmap to store addresses is created. The quotas * for all networks defined for ATS are loaded from configuration. For each * network first the logic will check if the string * GNUNET_ATS_MaxBandwidthString is configured, if not it will try to convert * the configured value as a fancy size and if this fails it will try to use * it as a value_number. If no configuration value is found it will assign * GNUNET_ATS_DefaultBandwidth. The most important step is to load the * configured solver using configuration "[ats]:MODE". Current solvers are * MODE_PROPORTIONAL, MODE_MLP. Interaction is done using a solver API * * 1.4 Solver API * * Solver functions: * * s_init: init the solver with required information * * s_add: add a new address * * s_update: update ATS values or session for an address * * s_get: get prefered address for a peer * * s_del: delete an address * * s_pref: change preference value for a peer * * s_done: shutdown solver * * Callbacks: addresses provides a bandwidth_changed_cb callback to the * solver which is called when bandwidth assigned to peer has changed * * 1.5 Shutdown * * During shutdown all addresses are freed and the solver told to shutdown * * 1.6 Addresses and sessions * * Addresses consist of the address itself and a numerical session. When a * new address without a session is added it has no session, so it gets * session 0 assigned. When an address with a session is added and an address * object with session 0 is found, this object is updated with the session * otherwise a new address object with this session assigned is created. * * 1.6.1 Terminology * * Addresses a1,a2 with session s1, s2 are "exact" if: * (a1 == a2)&&(s1 == s2) * Addresses a1,a2 with session s1, s2 are "equivalent" if: * (a1 == a2)&&((s1 == s2)||(s1 == 0)||(s2 == 0) * * 1.7 Address management * * Transport service notifies ATS about changes to the addresses known to * him. * * 1.7.1 Adding an address * * When transport learns a new address it tells ATS and ATS is telling * addresses about it using GAS_address_add. If not known to addresses it * creates a new address object and calls solver's s_add. ATS information are * deserialized and solver is notified about the session and ATS information * using s_update. * * 1.7.2 Updating an address * * Addresses does an lookup up for the existing address with the given * session. If disassembles included ATS information and notifies the solver * using s_update about the update. * * 1.7.3 Deleting an address * * Addresses does an lookup for the exact address and session and if removes * this address. If session != 0 the session is set to 0 and the address is * kept. If session == 0, the addresses is removed. * * 1.7.4 Requesting an address suggestion * * The address client issues a request address message to be notified about * address suggestions for a specific peer. Addresses asks the solver with * s_get. If no address is available, it will not send a response, otherwise * it will respond with the choosen address. * * 1.7.5 Address suggestions * * Addresses will notify the client automatically on any bandwidth_changed_cb * by the solver if a address suggestion request is pending. If no address is * available it will not respond at all If the client is not interested * anymore, it has to cancel the address suggestion request. * * 1.7.6 Suggestions blocks and reset * * After suggesting an address it is blocked for ATS_BLOCKING_DELTA sec. to * prevent the client from being thrashed. If the client requires immediately * it can reset this block using GAS_addresses_handle_backoff_reset. * * 1.7.7 Marking address in use * * The client can notify addresses that it successfully uses an address and * wants this address to be kept by calling GSA_address_in_use. Adresses will * mark the address as used an notify the solver about the use. * * 1.7.8 Address lifecycle * * * (add address) * * (updated address) || (address in use) * * (delete address) * * 1.8 Bandwidth assignment * * The addresses are used to perform resource allocation operations. ATS * addresses takes care of instantiating the solver configured and notifies * the respective solver about address changes and receives changes to the * bandwidth assignment from the solver. The current bandwidth assignment is * sent to transport. The specific solvers will be described in the specific * section. * * 1.9 Changing peer preferences * * The bandwidth assigned to a peer can be influenced by setting a preference * for a peer. The prefernce will be given to to the solver with s_pref which * has to take care of the preference value */ /** * Available ressource assignment modes */ enum ATS_Mode { /* * proportional mode: * * Assign each peer an equal amount of bandwidth (bw) * * bw_per_peer = bw_total / #active addresses */ MODE_PROPORTIONAL, /* * MLP mode: * * Solve ressource assignment as an optimization problem * Uses an mixed integer programming solver */ MODE_MLP, /* * Reinforcement Learning mode: * * Solve resource assignment using a learning agent */ MODE_RIL }; /* * How long will address suggestions blocked after a suggestion */ #define ATS_BLOCKING_DELTA GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100) /** * Information provided by ATS normalization */ struct GAS_NormalizationInfo { /** * Next index to use in averaging queue */ unsigned int avg_queue_index; /** * Averaging queue */ uint32_t atsi_abs[GAS_normalization_queue_length]; /** * Averaged ATSI values from queue */ uint32_t avg; /** * Normalized values from queue to a range of values [1.0...2.0] */ double norm; }; /** * Address with additional information */ struct ATS_Address { /** * Next element in DLL */ struct ATS_Address *next; /** * Previous element in DLL */ struct ATS_Address *prev; /** * Peer ID */ struct GNUNET_PeerIdentity peer; /** * Session ID, 0 if no session is given */ uint32_t session_id; uint32_t local_address_info; /** * Address */ const void *addr; /** * Address length */ size_t addr_len; /** * Plugin name */ char *plugin; /** * Solver specific information for this address */ void *solver_information; /** * ATS performance information for this address */ struct GNUNET_ATS_Information *atsi; /** * ATS performance information for this address */ uint32_t atsi_count; /** * Inbound bandwidth assigned by solver in NBO */ struct GNUNET_BANDWIDTH_Value32NBO assigned_bw_in; /** * Outbound bandwidth assigned by solver in NBO */ struct GNUNET_BANDWIDTH_Value32NBO assigned_bw_out; /** * Blocking interval */ struct GNUNET_TIME_Relative block_interval; /** * Time when address can be suggested again */ struct GNUNET_TIME_Absolute blocked_until; /** * Time when address had last activity (update, in uses) */ struct GNUNET_TIME_Absolute t_last_activity; /** * Time when address was added */ struct GNUNET_TIME_Absolute t_added; /** * Is this the active address for this peer? */ int active; /** * Is this the address for this peer in use? */ int used; /** * Normalized ATS performance information for this address * Each entry can be accessed using the GNUNET_ATS_QualityProperties avg_queue_index */ struct GAS_NormalizationInfo atsin[GNUNET_ATS_QualityPropertiesCount]; }; /** * Handle for ATS address component */ struct GAS_Addresses_Handle; /** * Initialize address subsystem. The addresses subsystem manages the addresses * known and current performance information. It has a solver component * responsible for the resource allocation. It tells the solver about changes * and receives updates when the solver changes the ressource allocation. * * @param cfg configuration to use * @param stats the statistics handle to use * @return an address handle */ struct GAS_Addresses_Handle * GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_STATISTICS_Handle *stats); /** * Shutdown address subsystem. * * @param handle the address handle to shutdown */ void GAS_addresses_done (struct GAS_Addresses_Handle *handle); /** * Add a new address for a peer. * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param local_address_info the local address for the address * @param session_id session id, can be 0 * @param atsi performance information for this address * @param atsi_count number of performance information contained */ void GAS_addresses_add (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count); /** * Notification about active use of an address. * in_use == GNUNET_YES: * This address is used to maintain an active connection with a peer. * in_use == GNUNET_NO: * This address is no longer used to maintain an active connection with a peer. * * Note: can only be called with in_use == GNUNET_NO if called with GNUNET_YES * before * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param local_address_info the local address for the address * @param session_id session id, can be 0 * @param in_use GNUNET_YES if GNUNET_NO * @return GNUNET_SYSERR on failure (address unknown ...) */ int GAS_addresses_in_use (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id, int in_use); /** * Update an address with a session or performance information for a peer. * * If an address was added without a session it will be updated with the * session * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param local_address_info the local address for the address * @param session_id session id, can be 0 * @param atsi performance information for this address * @param atsi_count number of performance information contained */ void GAS_addresses_update (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count); /** * Remove an address or just a session for a peer. * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param session_id session id, can be 0 * @param local_address_info the local address for the address */ void GAS_addresses_destroy (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id); /** * Remove all addresses * * @param handle the address handle to use */ void GAS_addresses_destroy_all (struct GAS_Addresses_Handle *handle); /** * Request address suggestions for a peer * * @param handle the address handle * @param peer the peer id */ void GAS_addresses_request_address (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer); /** * Cancel address suggestions for a peer * * @param handle the address handle * @param peer the peer id */ void GAS_addresses_request_address_cancel (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer); /** * Reset suggestion backoff for a peer * * Suggesting addresses is blocked for ATS_BLOCKING_DELTA. Blocking can be * reset using this function * * @param handle the address handle * @param peer the peer id */ void GAS_addresses_handle_backoff_reset (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer); /** * A performance client disconnected * * @param handle address handle * @param client the client */ void GAS_addresses_preference_client_disconnect (struct GAS_Addresses_Handle *handle, void *client); /** * Change the preference for a peer * * @param handle the address handle * @param client the client sending this request * @param peer the peer id * @param kind the preference kind to change * @param score_abs the new preference score */ void GAS_addresses_preference_change (struct GAS_Addresses_Handle *handle, void *client, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, float score_abs); /** * Application feedback on how good preference requirements are fulfilled * for a specific preference in the given time scope [now - scope .. now] * * An application notifies ATS if (and only if) it has feedback information * for a specific property. This value is valid until the feedback score is * updated by the application. * * If the application has no feedback for this preference kind the application * will not explicitly call. * * @param handle the address handle * @param application the application sending this request * @param peer the peer id * @param scope the time interval this valid for: [now - scope .. now] * @param kind the preference kind this feedback is intended for * @param score_abs the new preference score */ void GAS_addresses_preference_feedback (struct GAS_Addresses_Handle *handle, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, float score_abs); /** * Iterator for GAS_addresses_iterate_peers * * @param p_it_cls closure * @param id the peer id */ typedef void (*GNUNET_ATS_Peer_Iterator) (void *p_it_cls, const struct GNUNET_PeerIdentity *id); /** * Return all peers currently known to ATS * * @param handle the address handle to use * @param p_it the iterator to call for every peer * @param p_it_cls the closure for the iterator */ void GAS_addresses_iterate_peers (struct GAS_Addresses_Handle *handle, GNUNET_ATS_Peer_Iterator p_it, void *p_it_cls); /** * Iterator for GAS_addresses_get_peer_info * * @param p_it_cls closure closure * @param id the peer id * @param plugin_name plugin name * @param plugin_addr address * @param plugin_addr_len address length * @param address_active is address actively used * @param atsi ats performance information * @param atsi_count number of ats performance elements * @param bandwidth_out current outbound bandwidth assigned to address * @param bandwidth_in current inbound bandwidth assigned to address */ typedef void (*GNUNET_ATS_PeerInfo_Iterator) (void *p_it_cls, const struct GNUNET_PeerIdentity *id, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, const int address_active, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in); /** * Return information all peers currently known to ATS * * @param handle the address handle to use * @param peer the respective peer * @param pi_it the iterator to call for every peer * @param pi_it_cls the closure for the iterator */ void GAS_addresses_get_peer_info (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, GNUNET_ATS_PeerInfo_Iterator pi_it, void *pi_it_cls); #endif /* end of gnunet-service-ats_addresses.h */ gnunet-0.10.1/src/ats/plugin_ats_mlp.h0000644000175000017500000003166212272425070014567 00000000000000/* (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/plugin_ats_mlp.h * @brief ats MLP problem solver * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_ats_service.h" #include "gnunet_ats_plugin.h" #include "gnunet-service-ats_addresses.h" #include "gnunet_statistics_service.h" #if HAVE_LIBGLPK #include "glpk.h" #endif #ifndef GNUNET_SERVICE_ATS_ADDRESSES_MLP_H #define GNUNET_SERVICE_ATS_ADDRESSES_MLP_H #define BIG_M_VALUE (UINT32_MAX) /10 #define BIG_M_STRING "unlimited" #define MLP_AVERAGING_QUEUE_LENGTH 3 #define MLP_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10) #define MLP_MAX_ITERATIONS 4096 #define DEFAULT_D 1.0 #define DEFAULT_R 1.0 #define DEFAULT_U 1.0 #define DEFAULT_QUALITY 1.0 #define DEFAULT_MIN_CONNECTIONS 4 #define DEFAULT_PEER_PREFERENCE 1.0 #define MLP_NaN -1 #define MLP_UNDEFINED 0 #define GLP_YES 1.0 #define GLP_NO 0.0 struct MLP_Solution { int lp_res; int lp_presolv; int mip_res; int mip_presolv; int p_elements; int p_cols; int p_rows; int n_peers; int n_addresses; }; struct ATS_Peer { struct GNUNET_PeerIdentity id; /* Was this peer already added to the current problem? */ int processed; /* constraint 2: 1 address per peer*/ unsigned int r_c2; /* constraint 9: relativity */ unsigned int r_c9; /* Legacy preference value */ double f; }; struct MLP_Problem { /** * GLPK (MLP) problem object */ #if HAVE_LIBGLPK glp_prob *prob; #else void *prob; #endif /* Number of addresses in problem */ unsigned int num_addresses; /* Number of peers in problem */ unsigned int num_peers; /* Number of elements in problem matrix */ unsigned int num_elements; /* Row index constraint 2: */ unsigned int r_c2; /* Row index constraint 4: minimum connections */ unsigned int r_c4; /* Row index constraint 6: maximize diversity */ unsigned int r_c6; /* Row index constraint 8: utilization*/ unsigned int r_c8; /* Row index constraint 9: relativity*/ unsigned int r_c9; /* Row indices quality metrics */ int r_q[GNUNET_ATS_QualityPropertiesCount]; /* Row indices ATS network quotas */ int r_quota[GNUNET_ATS_NetworkTypeCount]; /* Column index Diversity (D) column */ int c_d; /* Column index Utilization (U) column */ int c_u; /* Column index Proportionality (R) column */ int c_r; /* Column index quality metrics */ int c_q[GNUNET_ATS_QualityPropertiesCount]; /* Problem matrix */ /* Current index */ unsigned int ci; /* Row index array */ int *ia; /* Column index array */ int *ja; /* Column index value */ double *ar; }; struct MLP_Variables { /* Big M value for bandwidth capping */ double BIG_M; /* ATS Quality metrics * * Array with GNUNET_ATS_QualityPropertiesCount elements * contains mapping to GNUNET_ATS_Property*/ int q[GNUNET_ATS_QualityPropertiesCount]; /* Number of quality metrics */ int m_q; /* Number of quality metrics */ int m_rc; /* Quality metric coefficients*/ double co_Q[GNUNET_ATS_QualityPropertiesCount]; /* Ressource costs coefficients*/ double co_RC[GNUNET_ATS_QualityPropertiesCount]; /* Diversity coefficient */ double co_D; /* Utility coefficient */ double co_U; /* Relativity coefficient */ double co_R; /* Minimum bandwidth assigned to an address */ unsigned int b_min; /* Minimum number of addresses with bandwidth assigned */ unsigned int n_min; /* Quotas */ /* Array mapping array index to ATS network */ int quota_index[GNUNET_ATS_NetworkTypeCount]; /* Outbound quotas */ unsigned long long quota_out[GNUNET_ATS_NetworkTypeCount]; /* Inbound quotas */ unsigned long long quota_in[GNUNET_ATS_NetworkTypeCount]; /* ATS ressource costs * array with GNUNET_ATS_QualityPropertiesCount elements * contains mapping to GNUNET_ATS_Property * */ int rc[GNUNET_ATS_QualityPropertiesCount]; }; /** * MLP Handle */ struct GAS_MLP_Handle { struct GNUNET_ATS_PluginEnvironment *env; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Address hashmap for lookups */ const struct GNUNET_CONTAINER_MultiPeerMap *addresses; /** * Addresses' bandwidth changed callback */ GAS_bandwidth_changed_cb bw_changed_cb; /** * Addresses' bandwidth changed callback closure */ void *bw_changed_cb_cls; /** * ATS function to get preferences */ GAS_get_preferences get_preferences; /** * Closure for ATS function to get preferences */ void *get_preferences_cls; /** * ATS function to get properties */ GAS_get_properties get_properties; /** * Closure for ATS function to get properties */ void *get_properties_cls; /** * Exclude peer from next result propagation */ const struct GNUNET_PeerIdentity *exclude_peer; /** * Encapsulation for the MLP problem */ struct MLP_Problem p; /** * Encapsulation for the MLP problem variables */ struct MLP_Variables pv; /** * Encapsulation for the MLP solution */ struct MLP_Solution ps; /** * Bulk lock */ int stat_bulk_lock; /** * Number of changes while solver was locked */ int stat_bulk_requests; /** * GLPK LP control parameter */ #if HAVE_LIBGLPK glp_smcp control_param_lp; #else void *control_param_lp; #endif /** * GLPK LP control parameter */ #if HAVE_LIBGLPK glp_iocp control_param_mlp; #else void *control_param_mlp; #endif /** * Peers with pending address requests */ struct GNUNET_CONTAINER_MultiPeerMap *requested_peers; /** * Was the problem updated since last solution */ int stat_mlp_prob_updated; /** * Has the problem size changed since last solution */ int stat_mlp_prob_changed; /** * Solve the problem automatically when updates occur? * Default: GNUNET_YES * Can be disabled for test and measurements */ int opt_mlp_auto_solve; /** * Write all MILP problems to a MPS file */ int opt_dump_problem_all; /** * Write all MILP problem solutions to a file */ int opt_dump_solution_all; /** * Write MILP problems to a MPS file when solver fails */ int opt_dump_problem_on_fail; /** * Write MILP problem solutions to a file when solver fails */ int opt_dump_solution_on_fail; /** * Print GLPK output */ int opt_glpk_verbose; }; /** * Address specific MLP information */ struct MLP_information { /* Bandwidth assigned */ struct GNUNET_BANDWIDTH_Value32NBO b_out; struct GNUNET_BANDWIDTH_Value32NBO b_in; /* Address selected */ int n; /* bandwidth column index */ signed int c_b; /* address usage column */ signed int c_n; /* row indexes */ /* constraint 1: bandwidth capping */ unsigned int r_c1; /* constraint 3: minimum bandwidth */ unsigned int r_c3; }; /** * Solves the MLP problem * * @param solver the MLP Handle * @return #GNUNET_OK if could be solved, GNUNET_SYSERR on failure */ int GAS_mlp_solve_problem (void *solver); /** * Init the MLP problem solving component * * @param cfg the GNUNET_CONFIGURATION_Handle handle * @param stats the GNUNET_STATISTICS handle * @param addresses Hashmap containing addresses * @param network array of GNUNET_ATS_NetworkType with length dest_length * @param out_dest array of outbound quotas * @param in_dest array of outbound quota * @param dest_length array length for quota arrays * @param bw_changed_cb callback for changed bandwidth amounts * @param bw_changed_cb_cls cls for callback * @param get_preference callback to get relative preferences for a peer * @param get_preference_cls cls for callback to get relative preferences for a peer * @param get_properties callback to get relative properties * @param get_properties_cls cls for callback to get relative properties * @return struct GAS_MLP_Handle on success, NULL on fail */ void * GAS_mlp_init (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_STATISTICS_Handle *stats, const struct GNUNET_CONTAINER_MultiPeerMap *addresses, int *network, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length, GAS_bandwidth_changed_cb bw_changed_cb, void *bw_changed_cb_cls, GAS_get_preferences get_preference, void *get_preference_cls, GAS_get_properties get_properties, void *get_properties_cls); /** * Add a single address within a network to the solver * * @param solver the solver Handle * @param address the address to add * @param network network type of this address */ void GAS_mlp_address_add (void *solver, struct ATS_Address *address, uint32_t network); /** * Transport properties for this address have changed * * @param solver solver handle * @param address the address * @param type the ATSI type in HBO * @param abs_value the absolute value of the property * @param rel_value the normalized value */ void GAS_mlp_address_property_changed (void *solver, struct ATS_Address *address, uint32_t type, uint32_t abs_value, double rel_value); /** * Transport session for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param cur_session the current session * @param new_session the new session */ void GAS_mlp_address_session_changed (void *solver, struct ATS_Address *address, uint32_t cur_session, uint32_t new_session); /** * Usage for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param in_use usage state */ void GAS_mlp_address_inuse_changed (void *solver, struct ATS_Address *address, int in_use); /** * Network scope for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param current_network the current network * @param new_network the new network */ void GAS_mlp_address_change_network (void *solver, struct ATS_Address *address, uint32_t current_network, uint32_t new_network); /** * Deletes a single address in the MLP problem * * The MLP problem has to be recreated and the problem has to be resolved * * @param solver the MLP Handle * @param address the address to delete * @param session_only delete only session not whole address */ void GAS_mlp_address_delete (void *solver, struct ATS_Address *address, int session_only); /** * Changes the preferences for a peer in the MLP problem * * @param solver the MLP Handle * @param peer the peer * @param kind the kind to change the preference * @param pref_rel the relative score */ void GAS_mlp_address_change_preference (void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel); /** * Get application feedback for a peer * * @param solver the solver handle * @param application the application * @param peer the peer to change the preference for * @param scope the time interval for this feedback: [now - scope .. now] * @param kind the kind to change the preference * @param score the score */ void GAS_mlp_address_preference_feedback (void *solver, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score); /** * Start a bulk operation * * @param solver the solver */ void GAS_mlp_bulk_start (void *solver); /** * Bulk operation done */ void GAS_mlp_bulk_stop (void *solver); /** * Get the preferred address for a specific peer until * GAS_mlp_stop_get_preferred_address is called * * @param solver the MLP Handle * @param peer the peer * @return suggested address */ const struct ATS_Address * GAS_mlp_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer); /** * Stop notifying about address and bandwidth changes for this peer * * @param solver the MLP handle * @param peer the peer */ void GAS_mlp_stop_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer); /** * Shutdown the MLP problem solving component * * @param solver the solver handle */ void GAS_mlp_done (void *solver); #endif /* end of plugin_ats_mlp.h */ gnunet-0.10.1/src/ats/ats_api_scheduling.c0000644000175000017500000012632512316473376015406 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/ats_api_scheduling.c * @brief automatic transport selection and outbound bandwidth determination * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "ats.h" #define INTERFACE_PROCESSING_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) #define NOT_FOUND 0 /** * Message in linked list we should send to the ATS service. The * actual binary message follows this struct. */ struct PendingMessage { /** * Kept in a DLL. */ struct PendingMessage *next; /** * Kept in a DLL. */ struct PendingMessage *prev; /** * Size of the message. */ size_t size; /** * Is this the 'ATS_START' message? */ int is_init; }; /** * Information we track per session. */ struct SessionRecord { /** * Identity of the peer (just needed for error checking). */ struct GNUNET_PeerIdentity peer; /** * Session handle. */ struct Session *session; /** * Set to GNUNET_YES if the slot is used. */ int slot_used; }; struct ATS_Network { struct ATS_Network * next; struct ATS_Network * prev; struct sockaddr *network; struct sockaddr *netmask; socklen_t length; }; /** * Handle for address suggestions */ struct GNUNET_ATS_SuggestHandle { struct GNUNET_ATS_SuggestHandle *prev; struct GNUNET_ATS_SuggestHandle *next; struct GNUNET_PeerIdentity id; }; /** * Handle to the ATS subsystem for bandwidth/transport scheduling information. */ struct GNUNET_ATS_SchedulingHandle { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Callback to invoke on suggestions. */ GNUNET_ATS_AddressSuggestionCallback suggest_cb; /** * Closure for 'suggest_cb'. */ void *suggest_cb_cls; /** * DLL for suggestions head */ struct GNUNET_ATS_SuggestHandle *sug_head; /** * DLL for suggestions tail */ struct GNUNET_ATS_SuggestHandle *sug_tail; /** * Connection to ATS service. */ struct GNUNET_CLIENT_Connection *client; /** * Head of list of messages for the ATS service. */ struct PendingMessage *pending_head; /** * Tail of list of messages for the ATS service */ struct PendingMessage *pending_tail; /** * Current request for transmission to ATS. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of network list */ struct ATS_Network * net_head; /** * Tail of network list */ struct ATS_Network * net_tail; /** * Array of session objects (we need to translate them to numbers and back * for the protocol; the offset in the array is the session number on the * network). Index 0 is always NULL and reserved to represent the NULL pointer. * Unused entries are also NULL. */ struct SessionRecord *session_array; /** * Task to trigger reconnect. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Task retrieving interfaces from the system */ GNUNET_SCHEDULER_TaskIdentifier interface_task; /** * Size of the session array. */ unsigned int session_array_size; /** * Should we reconnect to ATS due to some serious error? */ int reconnect; }; /** * Re-establish the connection to the ATS service. * * @param sh handle to use to re-connect. */ static void reconnect (struct GNUNET_ATS_SchedulingHandle *sh); /** * Re-establish the connection to the ATS service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_ATS_SchedulingHandle *sh = cls; sh->task = GNUNET_SCHEDULER_NO_TASK; reconnect (sh); } /** * Disconnect from ATS and then reconnect. * * @param sh our handle */ static void force_reconnect (struct GNUNET_ATS_SchedulingHandle *sh) { sh->reconnect = GNUNET_NO; GNUNET_CLIENT_disconnect (sh->client); sh->client = NULL; sh->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task, sh); } /** * Transmit messages from the message queue to the service * (if there are any, and if we are not already trying). * * @param sh handle to use */ static void do_transmit (struct GNUNET_ATS_SchedulingHandle *sh); /** * Type of a function to call when we receive a message * from the service. * * @param cls the 'struct GNUNET_ATS_SchedulingHandle' * @param msg message received, NULL on timeout or fatal error */ static void process_ats_message (void *cls, const struct GNUNET_MessageHeader *msg); /** * We can now transmit a message to ATS. Do it. * * @param cls the 'struct GNUNET_ATS_SchedulingHandle' * @param size number of bytes we can transmit to ATS * @param buf where to copy the messages * @return number of bytes copied into buf */ static size_t transmit_message_to_ats (void *cls, size_t size, void *buf) { struct GNUNET_ATS_SchedulingHandle *sh = cls; struct PendingMessage *p; size_t ret; char *cbuf; sh->th = NULL; if ((size == 0) || (buf == NULL)) { force_reconnect (sh); return 0; } ret = 0; cbuf = buf; while ((NULL != (p = sh->pending_head)) && (p->size <= size)) { memcpy (&cbuf[ret], &p[1], p->size); ret += p->size; size -= p->size; GNUNET_CONTAINER_DLL_remove (sh->pending_head, sh->pending_tail, p); GNUNET_free (p); } do_transmit (sh); return ret; } /** * Transmit messages from the message queue to the service * (if there are any, and if we are not already trying). * * @param sh handle to use */ static void do_transmit (struct GNUNET_ATS_SchedulingHandle *sh) { struct PendingMessage *p; if (NULL != sh->th) return; if (NULL == (p = sh->pending_head)) return; if (NULL == sh->client) return; /* currently reconnecting */ sh->th = GNUNET_CLIENT_notify_transmit_ready (sh->client, p->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_message_to_ats, sh); } /** * Find the session object corresponding to the given session ID. * * @param sh our handle * @param session_id current session ID * @param peer peer the session belongs to * @return the session object (or NULL) */ static struct Session * find_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id, const struct GNUNET_PeerIdentity *peer) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Find session %u from peer %s in %p\n", (unsigned int) session_id, GNUNET_i2s (peer), sh); if (session_id >= sh->session_array_size) { GNUNET_break (0); return NULL; } if (0 == session_id) return NULL; if (sh->session_array[session_id].session == NULL) { GNUNET_break (0 == memcmp (peer, &sh->session_array[session_id].peer, sizeof (struct GNUNET_PeerIdentity))); return NULL; } if (0 != memcmp (peer, &sh->session_array[session_id].peer, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); sh->reconnect = GNUNET_YES; return NULL; } /* This check exploits the fact that first field of a session object * is peer identity. */ if (0 != memcmp (peer, sh->session_array[session_id].session, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Session %p belongs to peer `%s'\n", sh->session_array[session_id].session, GNUNET_i2s_full ((struct GNUNET_PeerIdentity *) &sh->session_array[session_id].peer)); /* GNUNET_break (0); sh->reconnect = GNUNET_YES; return NULL; */ } return sh->session_array[session_id].session; } /** * Get an available session ID for the given session object. * * @param sh our handle * @param session session object * @param peer peer the session belongs to * @return the session id */ static uint32_t find_empty_session_slot (struct GNUNET_ATS_SchedulingHandle *sh, struct Session *session, const struct GNUNET_PeerIdentity *peer) { unsigned int i; unsigned int f; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Get session ID for session %p from peer %s in %p\n", session, GNUNET_i2s (peer), sh); if (NULL == session) return NOT_FOUND; f = 0; for (i = 1; i < sh->session_array_size; i++) { if ((f == 0) && (sh->session_array[i].slot_used == GNUNET_NO)) f = i; } if (f == 0) { f = sh->session_array_size; GNUNET_array_grow (sh->session_array, sh->session_array_size, sh->session_array_size * 2); } GNUNET_assert (f > 0); sh->session_array[f].session = session; sh->session_array[f].peer = *peer; sh->session_array[f].slot_used = GNUNET_YES; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Assigning session ID %u for session %p of peer %s in %p\n", f, session, GNUNET_i2s (peer), sh); return f; } /** * Get the ID for the given session object. * * @param sh our handle * @param session session object * @param peer peer the session belongs to * @return the session id or NOT_FOUND for error */ static uint32_t find_session_id (struct GNUNET_ATS_SchedulingHandle *sh, struct Session *session, const struct GNUNET_PeerIdentity *peer) { unsigned int i; char * p2; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Get session ID for session %p from peer %s in %p\n", session, GNUNET_i2s (peer), sh); if (NULL == session) return NOT_FOUND; for (i = 1; i < sh->session_array_size; i++) { if (session == sh->session_array[i].session) { if (0 != memcmp (peer, &sh->session_array[i].peer, sizeof (struct GNUNET_PeerIdentity))) { p2 = strdup (GNUNET_i2s (&sh->session_array[i].peer)); GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "ats-scheduling-api", "Session %p did not match: old session was for peer `%s' new session is for `%s'\n", session, GNUNET_i2s (peer), p2); GNUNET_free (p2); return NOT_FOUND; } return i; } } return NOT_FOUND; } /** * Remove the session of the given session ID from the session * table (it is no longer valid). * * @param sh our handle * @param session_id identifies session that is no longer valid * @param peer peer the session belongs to */ static void remove_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id, const struct GNUNET_PeerIdentity *peer) { GNUNET_assert (peer != NULL); GNUNET_assert (sh != NULL); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Release sessionID %u from peer %s in %p\n", (unsigned int) session_id, GNUNET_i2s (peer), sh); if (0 == session_id) return; GNUNET_assert (session_id < sh->session_array_size); GNUNET_assert (GNUNET_YES == sh->session_array[session_id].slot_used); GNUNET_assert (0 == memcmp (peer, &sh->session_array[session_id].peer, sizeof (struct GNUNET_PeerIdentity))); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Session %p for peer `%s' removed from slot %u \n", sh->session_array[session_id].session, GNUNET_i2s (peer), session_id); sh->session_array[session_id].session = NULL; } /** * Release the session slot from the session table (ATS service is * also done using it). * * @param sh our handle * @param session_id identifies session that is no longer valid * @param peer peer the session belongs to */ static void release_session (struct GNUNET_ATS_SchedulingHandle *sh, uint32_t session_id, const struct GNUNET_PeerIdentity *peer) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "Release sessionID %u from peer %s in %p\n", (unsigned int) session_id, GNUNET_i2s (peer), sh); if (session_id >= sh->session_array_size) { GNUNET_break (0); sh->reconnect = GNUNET_YES; return; } /* this slot should have been removed from remove_session before */ GNUNET_assert (sh->session_array[session_id].session == NULL); if (0 != memcmp (peer, &sh->session_array[session_id].peer, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); sh->reconnect = GNUNET_YES; return; } sh->session_array[session_id].slot_used = GNUNET_NO; memset (&sh->session_array[session_id].peer, 0, sizeof (struct GNUNET_PeerIdentity)); } static void process_release_message (struct GNUNET_ATS_SchedulingHandle *sh, const struct SessionReleaseMessage *srm) { release_session (sh, ntohl (srm->session_id), &srm->peer); } /** * Type of a function to call when we receive a message * from the service. * * @param cls the 'struct GNUNET_ATS_SchedulingHandle' * @param msg message received, NULL on timeout or fatal error */ static void process_ats_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_ATS_SchedulingHandle *sh = cls; const struct AddressSuggestionMessage *m; const struct GNUNET_ATS_Information *atsi; const char *plugin_address; const char *plugin_name; uint16_t plugin_address_length; uint16_t plugin_name_length; uint32_t ats_count; struct GNUNET_HELLO_Address address; struct Session *s; if (NULL == msg) { force_reconnect (sh); return; } if ((ntohs (msg->type) == GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE) && (ntohs (msg->size) == sizeof (struct SessionReleaseMessage))) { process_release_message (sh, (const struct SessionReleaseMessage *) msg); GNUNET_CLIENT_receive (sh->client, &process_ats_message, sh, GNUNET_TIME_UNIT_FOREVER_REL); if (GNUNET_YES == sh->reconnect) force_reconnect (sh); return; } if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION) || (ntohs (msg->size) <= sizeof (struct AddressSuggestionMessage))) { GNUNET_break (0); force_reconnect (sh); return; } m = (const struct AddressSuggestionMessage *) msg; ats_count = ntohl (m->ats_count); plugin_address_length = ntohs (m->address_length); atsi = (const struct GNUNET_ATS_Information *) &m[1]; plugin_address = (const char *) &atsi[ats_count]; plugin_name = &plugin_address[plugin_address_length]; plugin_name_length = ntohs (m->plugin_name_length); if ((plugin_address_length + plugin_name_length + ats_count * sizeof (struct GNUNET_ATS_Information) + sizeof (struct AddressSuggestionMessage) != ntohs (msg->size)) || (ats_count > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)) || (plugin_name[plugin_name_length - 1] != '\0')) { GNUNET_break (0); force_reconnect (sh); return; } uint32_t session_id = ntohl (m->session_id); if (session_id == 0) s = NULL; else { s = find_session (sh, session_id, &m->peer); if (s == NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "ATS tries to use outdated session `%s'\n", GNUNET_i2s (&m->peer)); GNUNET_CLIENT_receive (sh->client, &process_ats_message, sh, GNUNET_TIME_UNIT_FOREVER_REL); return; } } if (NULL == sh->suggest_cb) return; address.peer = m->peer; address.address = plugin_address; address.address_length = plugin_address_length; address.transport_name = plugin_name; address.local_info = ntohl(m->address_local_info); if ((s == NULL) && (0 == address.address_length)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ATS returned invalid address for peer `%s' transport `%s' address length %i, session_id %i\n", GNUNET_i2s (&address.peer), address.transport_name, plugin_address_length, session_id); GNUNET_break_op (0); GNUNET_CLIENT_receive (sh->client, &process_ats_message, sh, GNUNET_TIME_UNIT_FOREVER_REL); return; } sh->suggest_cb (sh->suggest_cb_cls, (const struct GNUNET_PeerIdentity *) &m->peer, &address, s, m->bandwidth_out, m->bandwidth_in, atsi, ats_count); GNUNET_CLIENT_receive (sh->client, &process_ats_message, sh, GNUNET_TIME_UNIT_FOREVER_REL); if (GNUNET_YES == sh->reconnect) force_reconnect (sh); } /** * Re-establish the connection to the ATS service. * * @param sh handle to use to re-connect. */ static void reconnect (struct GNUNET_ATS_SchedulingHandle *sh) { struct PendingMessage *p; struct ClientStartMessage *init; GNUNET_assert (NULL == sh->client); sh->client = GNUNET_CLIENT_connect ("ats", sh->cfg); GNUNET_assert (NULL != sh->client); GNUNET_CLIENT_receive (sh->client, &process_ats_message, sh, GNUNET_TIME_UNIT_FOREVER_REL); if ((NULL == (p = sh->pending_head)) || (GNUNET_YES != p->is_init)) { p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct ClientStartMessage)); p->size = sizeof (struct ClientStartMessage); p->is_init = GNUNET_YES; init = (struct ClientStartMessage *) &p[1]; init->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_START); init->header.size = htons (sizeof (struct ClientStartMessage)); init->start_flag = htonl (START_FLAG_SCHEDULING); GNUNET_CONTAINER_DLL_insert (sh->pending_head, sh->pending_tail, p); } do_transmit (sh); } /** * delete the current network list */ static void delete_networks (struct GNUNET_ATS_SchedulingHandle *sh) { struct ATS_Network * cur = sh->net_head; while (cur != NULL) { GNUNET_CONTAINER_DLL_remove(sh->net_head, sh->net_tail, cur); GNUNET_free (cur); cur = sh->net_head; } } static int interface_proc (void *cls, const char *name, int isDefault, const struct sockaddr * addr, const struct sockaddr * broadcast_addr, const struct sockaddr * netmask, socklen_t addrlen) { struct GNUNET_ATS_SchedulingHandle * sh = cls; /* Calculate network */ struct ATS_Network *net = NULL; /* Skipping IPv4 loopback addresses since we have special check */ if (addr->sa_family == AF_INET) { struct sockaddr_in * a4 = (struct sockaddr_in *) addr; if ((a4->sin_addr.s_addr & htonl(0xff000000)) == htonl (0x7f000000)) return GNUNET_OK; } /* Skipping IPv6 loopback addresses since we have special check */ if (addr->sa_family == AF_INET6) { struct sockaddr_in6 * a6 = (struct sockaddr_in6 *) addr; if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr)) return GNUNET_OK; } if (addr->sa_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *) addr; struct sockaddr_in *netmask4 = (struct sockaddr_in *) netmask; struct sockaddr_in *tmp = NULL; struct sockaddr_in network4; net = GNUNET_malloc(sizeof (struct ATS_Network) + 2 * sizeof (struct sockaddr_in)); tmp = (struct sockaddr_in *) &net[1]; net->network = (struct sockaddr *) &tmp[0]; net->netmask = (struct sockaddr *) &tmp[1]; net->length = addrlen; memset (&network4, 0, sizeof (network4)); network4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN network4.sin_len = sizeof (network4); #endif network4.sin_addr.s_addr = (addr4->sin_addr.s_addr & netmask4->sin_addr.s_addr); memcpy (net->netmask, netmask4, sizeof (struct sockaddr_in)); memcpy (net->network, &network4, sizeof (struct sockaddr_in)); } if (addr->sa_family == AF_INET6) { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr; struct sockaddr_in6 *netmask6 = (struct sockaddr_in6 *) netmask; struct sockaddr_in6 * tmp = NULL; struct sockaddr_in6 network6; net = GNUNET_malloc(sizeof (struct ATS_Network) + 2 * sizeof (struct sockaddr_in6)); tmp = (struct sockaddr_in6 *) &net[1]; net->network = (struct sockaddr *) &tmp[0]; net->netmask = (struct sockaddr *) &tmp[1]; net->length = addrlen; memset (&network6, 0, sizeof (network6)); network6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN network6.sin6_len = sizeof (network6); #endif int c = 0; uint32_t *addr_elem = (uint32_t *) &addr6->sin6_addr; uint32_t *mask_elem = (uint32_t *) &netmask6->sin6_addr; uint32_t *net_elem = (uint32_t *) &network6.sin6_addr; for (c = 0; c < 4; c++) net_elem[c] = addr_elem[c] & mask_elem[c]; memcpy (net->netmask, netmask6, sizeof (struct sockaddr_in6)); memcpy (net->network, &network6, sizeof (struct sockaddr_in6)); } /* Store in list */ if (net != NULL) { #if VERBOSE_ATS char * netmask = GNUNET_strdup (GNUNET_a2s((struct sockaddr *) net->netmask, addrlen)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding network `%s', netmask `%s'\n", GNUNET_a2s((struct sockaddr *) net->network, addrlen), netmask); GNUNET_free (netmask); # endif GNUNET_CONTAINER_DLL_insert(sh->net_head, sh->net_tail, net); } return GNUNET_OK; } /** * Periodically get list of addresses * @param cls closure * @param tc Task context */ static void get_addresses (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_ATS_SchedulingHandle * sh = cls; sh->interface_task = GNUNET_SCHEDULER_NO_TASK; delete_networks (sh); GNUNET_OS_network_interfaces_list(interface_proc, sh); sh->interface_task = GNUNET_SCHEDULER_add_delayed (INTERFACE_PROCESSING_INTERVALL, get_addresses, sh); } /** * Convert a GNUNET_ATS_NetworkType to a string * * @param net the network type * @return a string or NULL if invalid */ const char * GNUNET_ATS_print_network_type (uint32_t net) { char *networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; if (net < GNUNET_ATS_NetworkTypeCount) return networks[net]; return NULL; } /** * Convert a ATS property to a string * * @param type the atsi type * @return a string or NULL if invalid */ const char * GNUNET_ATS_print_property_type (uint32_t type) { char *props[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings; if ((type > 0) && (type < GNUNET_ATS_PropertyCount)) return props[type]; return NULL; } /** * Returns where the address is located: LAN or WAN or ... * * @param sh the scheduling handle * @param addr address * @param addrlen address length * @return location as GNUNET_ATS_Information */ struct GNUNET_ATS_Information GNUNET_ATS_address_get_type (struct GNUNET_ATS_SchedulingHandle * sh, const struct sockaddr * addr, socklen_t addrlen) { GNUNET_assert (sh != NULL); struct ATS_Network * cur = sh->net_head; int type = GNUNET_ATS_NET_UNSPECIFIED; struct GNUNET_ATS_Information ats; if (addr->sa_family == AF_UNIX) { type = GNUNET_ATS_NET_LOOPBACK; } /* IPv4 loopback check */ if (addr->sa_family == AF_INET) { struct sockaddr_in * a4 = (struct sockaddr_in *) addr; if ((a4->sin_addr.s_addr & htonl(0xff000000)) == htonl (0x7f000000)) type = GNUNET_ATS_NET_LOOPBACK; } /* IPv6 loopback check */ if (addr->sa_family == AF_INET6) { struct sockaddr_in6 * a6 = (struct sockaddr_in6 *) addr; if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr)) type = GNUNET_ATS_NET_LOOPBACK; } /* Check local networks */ while ((cur != NULL) && (type == GNUNET_ATS_NET_UNSPECIFIED)) { if (addrlen != cur->length) { cur = cur->next; continue; } if (addr->sa_family == AF_INET) { struct sockaddr_in * a4 = (struct sockaddr_in *) addr; struct sockaddr_in * net4 = (struct sockaddr_in *) cur->network; struct sockaddr_in * mask4 = (struct sockaddr_in *) cur->netmask; if (((a4->sin_addr.s_addr & mask4->sin_addr.s_addr)) == net4->sin_addr.s_addr) type = GNUNET_ATS_NET_LAN; } if (addr->sa_family == AF_INET6) { struct sockaddr_in6 * a6 = (struct sockaddr_in6 *) addr; struct sockaddr_in6 * net6 = (struct sockaddr_in6 *) cur->network; struct sockaddr_in6 * mask6 = (struct sockaddr_in6 *) cur->netmask; int res = GNUNET_YES; int c = 0; uint32_t *addr_elem = (uint32_t *) &a6->sin6_addr; uint32_t *mask_elem = (uint32_t *) &mask6->sin6_addr; uint32_t *net_elem = (uint32_t *) &net6->sin6_addr; for (c = 0; c < 4; c++) if ((addr_elem[c] & mask_elem[c]) != net_elem[c]) res = GNUNET_NO; if (res == GNUNET_YES) type = GNUNET_ATS_NET_LAN; } cur = cur->next; } /* no local network found for this address, default: WAN */ if (type == GNUNET_ATS_NET_UNSPECIFIED) type = GNUNET_ATS_NET_WAN; ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.value = htonl (type); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "ats-scheduling-api", "`%s' is in network `%s'\n", GNUNET_a2s ((const struct sockaddr *) addr, addrlen), GNUNET_ATS_print_network_type(type)); return ats; } /** * Initialize the ATS subsystem. * * @param cfg configuration to use * @param suggest_cb notification to call whenever the suggestation changed * @param suggest_cb_cls closure for 'suggest_cb' * @return ats context */ struct GNUNET_ATS_SchedulingHandle * GNUNET_ATS_scheduling_init (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ATS_AddressSuggestionCallback suggest_cb, void *suggest_cb_cls) { struct GNUNET_ATS_SchedulingHandle *sh; sh = GNUNET_new (struct GNUNET_ATS_SchedulingHandle); sh->cfg = cfg; sh->suggest_cb = suggest_cb; sh->suggest_cb_cls = suggest_cb_cls; GNUNET_array_grow (sh->session_array, sh->session_array_size, 4); GNUNET_OS_network_interfaces_list(interface_proc, sh); sh->interface_task = GNUNET_SCHEDULER_add_delayed (INTERFACE_PROCESSING_INTERVALL, get_addresses, sh); reconnect (sh); return sh; } /** * Client is done with ATS scheduling, release resources. * * @param sh handle to release */ void GNUNET_ATS_scheduling_done (struct GNUNET_ATS_SchedulingHandle *sh) { struct PendingMessage *p; struct GNUNET_ATS_SuggestHandle *cur; struct GNUNET_ATS_SuggestHandle *next; while (NULL != (p = sh->pending_head)) { GNUNET_CONTAINER_DLL_remove (sh->pending_head, sh->pending_tail, p); GNUNET_free (p); } if (NULL != sh->client) { GNUNET_CLIENT_disconnect (sh->client); sh->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != sh->task) { GNUNET_SCHEDULER_cancel (sh->task); sh->task = GNUNET_SCHEDULER_NO_TASK; } next = sh->sug_head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove (sh->sug_head, sh->sug_tail, cur); GNUNET_free (cur); } delete_networks (sh); if (sh->interface_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel(sh->interface_task); sh->interface_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_array_grow (sh->session_array, sh->session_array_size, 0); GNUNET_free (sh); sh = NULL; } /** * We would like to reset the address suggestion block time for this * peer * * @param sh handle * @param peer identity of the peer we want to reset */ void GNUNET_ATS_reset_backoff (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_PeerIdentity *peer) { struct PendingMessage *p; struct ResetBackoffMessage *m; p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct ResetBackoffMessage)); p->size = sizeof (struct ResetBackoffMessage); p->is_init = GNUNET_NO; m = (struct ResetBackoffMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_RESET_BACKOFF); m->header.size = htons (sizeof (struct ResetBackoffMessage)); m->reserved = htonl (0); m->peer = *peer; GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); } /** * We would like to receive address suggestions for a peer. ATS will * respond with a call to the continuation immediately containing an address or * no address if none is available. ATS can suggest more addresses until we call * #GNUNET_ATS_suggest_address_cancel. * * * @param sh handle * @param peer identity of the peer we need an address for * @param cont the continuation to call with the address * @param cont_cls the cls for the continuation * @return suggest handle */ struct GNUNET_ATS_SuggestHandle * GNUNET_ATS_suggest_address (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_PeerIdentity *peer, GNUNET_ATS_AddressSuggestionCallback cont, void *cont_cls) { struct PendingMessage *p; struct RequestAddressMessage *m; struct GNUNET_ATS_SuggestHandle *s; // FIXME: ATS needs to remember this in case of // a disconnect! p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct RequestAddressMessage)); p->size = sizeof (struct RequestAddressMessage); p->is_init = GNUNET_NO; m = (struct RequestAddressMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS); m->header.size = htons (sizeof (struct RequestAddressMessage)); m->reserved = htonl (0); m->peer = *peer; GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); s = GNUNET_new (struct GNUNET_ATS_SuggestHandle); s->id = (*peer); GNUNET_CONTAINER_DLL_insert_tail (sh->sug_head, sh->sug_tail, s); return s; } /** * We would like to stop receiving address updates for this peer * * @param sh handle * @param peer identity of the peer */ void GNUNET_ATS_suggest_address_cancel (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_PeerIdentity *peer) { struct PendingMessage *p; struct RequestAddressMessage *m; struct GNUNET_ATS_SuggestHandle *s; for (s = sh->sug_head; NULL != s; s = s->next) if (0 == memcmp(peer, &s->id, sizeof (s->id))) break; if (NULL == s) { GNUNET_break (0); return; } else { GNUNET_CONTAINER_DLL_remove (sh->sug_head, sh->sug_tail, s); GNUNET_free (s); } p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct RequestAddressMessage)); p->size = sizeof (struct RequestAddressMessage); p->is_init = GNUNET_NO; m = (struct RequestAddressMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL); m->header.size = htons (sizeof (struct RequestAddressMessage)); m->reserved = htonl (0); m->peer = *peer; GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); } /** * Test if a address and a session is known to ATS * * @param sh the scheduling handle * @param address the address * @param session the session * @return GNUNET_YES or GNUNET_NO */ int GNUNET_ATS_session_known (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session) { int s; if (NULL != session) { if (NOT_FOUND != (s = find_session_id (sh, session, &address->peer))) { /* Existing */ return GNUNET_YES; } return GNUNET_NO; } return GNUNET_NO; } /** * We have a new address ATS should know. Addresses have to be added with this * function before they can be: updated, set in use and destroyed * * @param sh handle * @param address the address * @param session session handle, can be NULL * @param ats performance data for the address * @param ats_count number of performance records in 'ats' * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GNUNET_ATS_address_add (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct PendingMessage *p; struct AddressUpdateMessage *m; struct GNUNET_ATS_Information *am; char *pm; size_t namelen; size_t msize; uint32_t s = 0; if (address == NULL) { GNUNET_break (0); return GNUNET_SYSERR; } namelen = (address->transport_name == NULL) ? 0 : strlen (address->transport_name) + 1; msize = sizeof (struct AddressUpdateMessage) + address->address_length + ats_count * sizeof (struct GNUNET_ATS_Information) + namelen; if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (address->address_length >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (namelen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (ats_count >= GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information))) { GNUNET_break (0); return GNUNET_SYSERR; } if (NULL != session) { if (NOT_FOUND != (s = find_session_id (sh, session, &address->peer))) { /* Already existing, nothing todo */ return GNUNET_SYSERR; } s = find_empty_session_slot (sh, session, &address->peer); GNUNET_break (NOT_FOUND != s); } p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; m = (struct AddressUpdateMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD); m->header.size = htons (msize); m->ats_count = htonl (ats_count); m->peer = address->peer; m->address_length = htons (address->address_length); m->address_local_info = htonl ((uint32_t) address->local_info); m->plugin_name_length = htons (namelen); m->session_id = htonl (s); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s', plugin `%s', session %p id %u\n", GNUNET_i2s (&address->peer), address->transport_name, session, s); am = (struct GNUNET_ATS_Information *) &m[1]; memcpy (am, ats, ats_count * sizeof (struct GNUNET_ATS_Information)); pm = (char *) &am[ats_count]; memcpy (pm, address->address, address->address_length); if (NULL != address->transport_name) memcpy (&pm[address->address_length], address->transport_name, namelen); GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); return GNUNET_OK; } /** * We have updated performance statistics for a given address. Note * that this function can be called for addresses that are currently * in use as well as addresses that are valid but not actively in use. * Furthermore, the peer may not even be connected to us right now (in * which case the call may be ignored or the information may be stored * for later use). Update bandwidth assignments. * * @param sh handle * @param address the address * @param session session handle, can be NULL * @param ats performance data for the address * @param ats_count number of performance records in 'ats' * @return GNUNET_YES on success, GNUNET_NO if address or session are unknown, * GNUNET_SYSERR on hard failure */ int GNUNET_ATS_address_update (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct PendingMessage *p; struct AddressUpdateMessage *m; struct GNUNET_ATS_Information *am; char *pm; size_t namelen; size_t msize; uint32_t s = 0; if (NULL == address) { GNUNET_break (0); return GNUNET_SYSERR; } if (NULL == sh) { GNUNET_break (0); return GNUNET_SYSERR; } namelen = (address->transport_name == NULL) ? 0 : strlen (address->transport_name) + 1; msize = sizeof (struct AddressUpdateMessage) + address->address_length + ats_count * sizeof (struct GNUNET_ATS_Information) + namelen; if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (address->address_length >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (namelen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (ats_count >= GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information))) { GNUNET_break (0); return GNUNET_SYSERR; } if (NULL != session) { s = find_session_id (sh, session, &address->peer); if (NOT_FOUND == s) return GNUNET_NO; } p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; m = (struct AddressUpdateMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE); m->header.size = htons (msize); m->ats_count = htonl (ats_count); m->peer = address->peer; m->address_length = htons (address->address_length); m->address_local_info = htonl ((uint32_t) address->local_info); m->plugin_name_length = htons (namelen); m->session_id = htonl (s); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating address for peer `%s', plugin `%s', session %p id %u\n", GNUNET_i2s (&address->peer), address->transport_name, session, s); am = (struct GNUNET_ATS_Information *) &m[1]; memcpy (am, ats, ats_count * sizeof (struct GNUNET_ATS_Information)); pm = (char *) &am[ats_count]; memcpy (pm, address->address, address->address_length); memcpy (&pm[address->address_length], address->transport_name, namelen); GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); return GNUNET_YES; } /** * An address is now in use or not used any more. * * @param sh handle * @param address the address * @param session session handle, can be NULL * @param in_use GNUNET_YES if this address is now used, GNUNET_NO * if address is not used any more */ void GNUNET_ATS_address_in_use (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session, int in_use) { struct PendingMessage *p; struct AddressUseMessage *m; char *pm; size_t namelen; size_t msize; uint32_t s = 0; GNUNET_assert (NULL != address); namelen = (address->transport_name == NULL) ? 0 : strlen (address->transport_name) + 1; msize = sizeof (struct AddressUseMessage) + address->address_length + namelen; if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (address->address_length >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (namelen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)) { GNUNET_break (0); return; } if (session != NULL) { s = find_session_id (sh, session, &address->peer); if ((s == NOT_FOUND) && (GNUNET_NO == in_use)) { /* trying to set unknown address to NO */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Trying to set unknown address to unused for peer `%s', plugin `%s', session %p\n", GNUNET_i2s (&address->peer), address->transport_name, session); GNUNET_break (0); return; } if ((s == NOT_FOUND) && (GNUNET_YES == in_use)) { /* trying to set new address to YES */ s = find_empty_session_slot (sh, session, &address->peer); GNUNET_assert (NOT_FOUND != s); } } p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; m = (struct AddressUseMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_IN_USE); m->header.size = htons (msize); m->peer = address->peer; m->in_use = htons (in_use); m->address_length = htons (address->address_length); m->address_local_info = htonl ((uint32_t) address->local_info); m->plugin_name_length = htons (namelen); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting address used to %s for peer `%s', plugin `%s', session %p\n", (GNUNET_YES == in_use) ? "YES" : "NO", GNUNET_i2s (&address->peer), address->transport_name, session); m->session_id = htonl (s); pm = (char *) &m[1]; memcpy (pm, address->address, address->address_length); memcpy (&pm[address->address_length], address->transport_name, namelen); GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); return; } /** * An address got destroyed, stop including it as a valid address. * * If a session is given, only the session will be removed, if no session is * given the full address will be deleted. * * @param sh handle * @param address the address * @param session session handle that is no longer valid, can be NULL */ void GNUNET_ATS_address_destroyed (struct GNUNET_ATS_SchedulingHandle *sh, const struct GNUNET_HELLO_Address *address, struct Session *session) { struct PendingMessage *p; struct AddressDestroyedMessage *m; char *pm; size_t namelen; size_t msize; uint32_t s = 0; if (address == NULL) { GNUNET_break (0); return; } GNUNET_assert (address->transport_name != NULL); namelen = strlen (address->transport_name) + 1; GNUNET_assert (namelen > 1); msize = sizeof (struct AddressDestroyedMessage) + address->address_length + namelen; if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (address->address_length >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (namelen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)) { GNUNET_break (0); return; } s = find_session_id (sh, session, &address->peer); if ((NULL != session) && (NOT_FOUND == s)) { /* trying to delete unknown address */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to delete unknown address for peer `%s', plugin `%s', session %p\n", GNUNET_i2s (&address->peer), address->transport_name, session); return; } p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; m = (struct AddressDestroyedMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED); m->header.size = htons (msize); m->reserved = htonl (0); m->peer = address->peer; m->address_length = htons (address->address_length); m->address_local_info = htonl ((uint32_t) address->local_info); m->plugin_name_length = htons (namelen); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting address for peer `%s', plugin `%s', session %p\n", GNUNET_i2s (&address->peer), address->transport_name, session); m->session_id = htonl (s); pm = (char *) &m[1]; memcpy (pm, address->address, address->address_length); memcpy (&pm[address->address_length], address->transport_name, namelen); GNUNET_CONTAINER_DLL_insert_tail (sh->pending_head, sh->pending_tail, p); do_transmit (sh); remove_session (sh, s, &address->peer); } /* end of ats_api_scheduling.c */ gnunet-0.10.1/src/ats/gnunet-service-ats_reservations.h0000644000175000017500000000444012225777503020104 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_reservations.h * @brief ats service, inbound bandwidth reservation management * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_ATS_RESERVATIONS_H #define GNUNET_SERVICE_ATS_RESERVATIONS_H #include "gnunet_util_lib.h" /** * Set the amount of bandwidth the other peer could currently transmit * to us (as far as we know) to the given value. * * @param peer identity of the peer * @param bandwidth_in currently available bandwidth from that peer to * this peer (estimate) */ void GAS_reservations_set_bandwidth (const struct GNUNET_PeerIdentity *peer, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in); /** * Reserve the given amount of incoming bandwidth (in bytes) from the * given peer. If a reservation is not possible right now, return how * long the client should wait before trying again. * * @param peer peer to reserve bandwidth from * @param amount number of bytes to reserve * @return 0 if the reservation was successful, FOREVER if the * peer is not connected, otherwise the time to wait * until the reservation might succeed */ struct GNUNET_TIME_Relative GAS_reservations_reserve (const struct GNUNET_PeerIdentity *peer, int32_t amount); /** * Initialize reservations subsystem. */ void GAS_reservations_init (void); /** * Shutdown reservations subsystem. */ void GAS_reservations_done (void); #endif gnunet-0.10.1/src/ats/plugin_ats_mlp.c0000644000175000017500000020673512274162760014575 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/plugin_ats_mlp.c * @brief ats mlp problem solver * @author Matthias Wachs * @author Christian Grothoff */ #include "plugin_ats_mlp.h" /** * * NOTE: Do not modify this documentation. This documentation is based on * gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex * use build_txt.sh to generate plaintext output * * The MLP solver (mlp) tries to finds an optimal bandwidth assignmentby * optimizing an mixed integer programming problem. The MLP solver uses a * number of constraints to find the best adddress for a peer and an optimal * bandwidth assignment. mlp uses the GNU Linear Programming Kit to solve the * MLP problem. * * We defined a constraint system to find an optimal bandwidth assignment. * This constraint system uses as an input data addresses, bandwidth quotas, * preferences and quality values. This constraint system is stored in an * matrix based equotation system. * * 5 Using GLPK * * A (M)LP problem consists of a target function to optimizes, constraints * and rows and columns. FIXME GLP uses three arrays to index the matrix: two * integer arrays storing the row and column indices in the matrix and an * float array to store the coeeficient. * * To solve the problem we first find an initial solution for the LP problem * using the LP solver and then find an MLP solution based on this solution * using the MLP solver. * * Solving (M)LP problems has the property that finding an initial solution * for the LP problem is computationally expensive and finding the MLP * solution is cheaper. This is especially interesting an existing LP * solution can be reused if only coefficients in the matrix have changed * (addresses updated). Only when the problem size changes (addresses added * or deleted) a new LP solution has to be found. * * Intended usage * The mlp solver solves the bandwidth assignment problem only on demand when * an address suggestion is requested. When an address is requested mlp the * solves the mlp problem and if the active address or the bandwidth assigned * changes it calls the callback to addresses. The mlp solver gets notified * about new addresses (adding sessions), removed addresses (address * deletions) and address updates. To benefit from the mlp properties * mentioned in section 5 the solver rembers if since the last solution * addresses were added or deleted (problem size changed, problem has to be * rebuild and solved from sratch) or if addresses were updated and the * existing solution can be reused. * * 5.1 Input data * * The quotas for each network segment are passed by addresses. MLP can be * adapted using configuration settings and uses the following parameters: * * MLP_MAX_DURATION: * Maximum duration for a MLP solution procees (default: 3 sec.) * * MLP_MAX_ITERATIONS: * Maximum number of iterations for a MLP solution process (default: * 1024) * * MLP_MIN_CONNECTIONS: * Minimum number of desired connections (default: 4) * * MLP_MIN_BANDWIDTH: * Minimum amount of bandwidth assigned to an address (default: 1024) * * MLP_COEFFICIENT_D: * Diversity coefficient (default: 1.0) * * MLP_COEFFICIENT_R: * Relativity coefficient (default: 1.0) * * MLP_COEFFICIENT_U: * Utilization coefficient (default: 1.0) * * MLP_COEFFICIENT_D: * Diversity coefficient (default: 1.0) * * MLP_COEFFICIENT_QUALITY_DELAY: * Quality delay coefficient (default: 1.0) * * MLP_COEFFICIENT_QUALITY_DISTANCE: * Quality distance coefficient (default: 1.0) * * MLP_COEFFICIENT_QUALITY_DISTANCE: * Quality distance coefficient (default: 1.0) * * MLP_COEFFICIENT_QUALITY_DISTANCE: * Quality distance coefficient (default: 1.0) * * MLP_COEFFICIENT_QUALITY_DISTANCE: * Quality distance coefficient (default: 1.0) * * 5.2 Data structures used * * mlp has for each known peer a struct ATS_Peer containing information about * a specific peer. The address field solver_information contains information * about the mlp properties of this address. * * 5.3 Initializing * * During initialization mlp initializes the GLPK libray used to solve the * MLP problem: it initializes the glpk environment and creates an initial LP * problem. Next it loads the configuration values from the configuration or * uses the default values configured in -addresses_mlp.h. The quotas used * are given by addresses but may have to be adjusted. mlp uses a upper limit * for the bandwidth assigned called BIG M and a minimum amount of bandwidth * an address gets assigned as well as a minium desired number of * connections. If the configured quota is bigger than BIG M, it is reduced * to BIG M. If the configured quota is smaller than MLP_MIN_CONNECTIONS * *MLP_MIN_BANDWIDTH it is increased to this value. * * 5.4 Shutdown */ #define LOG(kind,...) GNUNET_log_from (kind, "ats-mlp",__VA_ARGS__) /** * Print debug output for mlp problem creation */ #define DEBUG_MLP_PROBLEM_CREATION GNUNET_NO /** * Maximize bandwidth assigned * * This option can be used to test if problem can be solved at all without * optimizing for utility, diversity or relativity * */ #define MAXIMIZE_FOR_BANDWIDTH_ASSIGNED GNUNET_NO /** * Intercept GLPK terminal output * @param info the mlp handle * @param s the string to print * @return 0: glpk prints output on terminal, 0 != surpress output */ static int mlp_term_hook (void *info, const char *s) { /* Not needed atm struct MLP_information *mlp = info; */ LOG (GNUNET_ERROR_TYPE_ERROR, "%s", s); return 1; } /** * Reset peers for next problem creation * * @param cls not used * @param key the key * @param value ATS_Peer * @return GNUNET_OK */ static int reset_peers (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct ATS_Peer *peer = value; peer->processed = GNUNET_NO; return GNUNET_OK; } /** * Delete the MLP problem and free the constrain matrix * * @param mlp the MLP handle */ static void mlp_delete_problem (struct GAS_MLP_Handle *mlp) { int c; if (mlp == NULL) return; if (mlp->p.prob != NULL) { glp_delete_prob(mlp->p.prob); mlp->p.prob = NULL; } /* delete row index */ if (mlp->p.ia != NULL) { GNUNET_free (mlp->p.ia); mlp->p.ia = NULL; } /* delete column index */ if (mlp->p.ja != NULL) { GNUNET_free (mlp->p.ja); mlp->p.ja = NULL; } /* delete coefficients */ if (mlp->p.ar != NULL) { GNUNET_free (mlp->p.ar); mlp->p.ar = NULL; } mlp->p.ci = 0; mlp->p.prob = NULL; mlp->p.c_d = MLP_UNDEFINED; mlp->p.c_r = MLP_UNDEFINED; mlp->p.r_c2 = MLP_UNDEFINED; mlp->p.r_c4 = MLP_UNDEFINED; mlp->p.r_c6 = MLP_UNDEFINED; mlp->p.r_c9 = MLP_UNDEFINED; for (c = 0; c < mlp->pv.m_q ; c ++) mlp->p.r_q[c] = MLP_UNDEFINED; for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c ++) mlp->p.r_quota[c] = MLP_UNDEFINED; mlp->p.ci = MLP_UNDEFINED; GNUNET_CONTAINER_multipeermap_iterate (mlp->requested_peers, &reset_peers, NULL); } /** * Translate ATS properties to text * Just intended for debugging * * @param ats_index the ATS index * @return string with result */ const char * mlp_ats_to_string (int ats_index) { switch (ats_index) { case GNUNET_ATS_ARRAY_TERMINATOR: return "GNUNET_ATS_ARRAY_TERMINATOR"; case GNUNET_ATS_UTILIZATION_OUT: return "GNUNET_ATS_UTILIZATION_OUT"; case GNUNET_ATS_UTILIZATION_IN: return "GNUNET_ATS_UTILIZATION_IN"; case GNUNET_ATS_UTILIZATION_PAYLOAD_OUT: return "GNUNET_ATS_UTILIZATION_PAYLOAD_OUT"; case GNUNET_ATS_UTILIZATION_PAYLOAD_IN: return "GNUNET_ATS_UTILIZATION_PAYLOAD_IN"; case GNUNET_ATS_COST_LAN: return "GNUNET_ATS_COST_LAN"; case GNUNET_ATS_COST_WAN: return "GNUNET_ATS_COST_LAN"; case GNUNET_ATS_COST_WLAN: return "GNUNET_ATS_COST_WLAN"; case GNUNET_ATS_NETWORK_TYPE: return "GNUNET_ATS_NETWORK_TYPE"; case GNUNET_ATS_QUALITY_NET_DELAY: return "GNUNET_ATS_QUALITY_NET_DELAY"; case GNUNET_ATS_QUALITY_NET_DISTANCE: return "GNUNET_ATS_QUALITY_NET_DISTANCE"; default: GNUNET_break (0); return "unknown"; } } /** * Translate glpk status error codes to text * @param retcode return code * @return string with result */ const char * mlp_status_to_string (int retcode) { switch (retcode) { case GLP_UNDEF: return "solution is undefined"; case GLP_FEAS: return "solution is feasible"; case GLP_INFEAS: return "solution is infeasible"; case GLP_NOFEAS: return "no feasible solution exists"; case GLP_OPT: return "solution is optimal"; case GLP_UNBND: return "solution is unbounded"; default: GNUNET_break (0); return "unknown error"; } } /** * Translate glpk solver error codes to text * @param retcode return code * @return string with result */ const char * mlp_solve_to_string (int retcode) { switch (retcode) { case 0: return "ok"; case GLP_EBADB: return "invalid basis"; case GLP_ESING: return "singular matrix"; case GLP_ECOND: return "ill-conditioned matrix"; case GLP_EBOUND: return "invalid bounds"; case GLP_EFAIL: return "solver failed"; case GLP_EOBJLL: return "objective lower limit reached"; case GLP_EOBJUL: return "objective upper limit reached"; case GLP_EITLIM: return "iteration limit exceeded"; case GLP_ETMLIM: return "time limit exceeded"; case GLP_ENOPFS: return "no primal feasible solution"; case GLP_ENODFS: return "no dual feasible solution"; case GLP_EROOT: return "root LP optimum not provided"; case GLP_ESTOP: return "search terminated by application"; case GLP_EMIPGAP: return "relative mip gap tolerance reached"; case GLP_ENOFEAS: return "no dual feasible solution"; case GLP_ENOCVG: return "no convergence"; case GLP_EINSTAB: return "numerical instability"; case GLP_EDATA: return "invalid data"; case GLP_ERANGE: return "result out of range"; default: GNUNET_break (0); return "unknown error"; } } /** * Extract an ATS performance info from an address * * @param address the address * @param type the type to extract in HBO * @return the value in HBO or GNUNET_ATS_VALUE_UNDEFINED in HBO if value does not exist */ static int get_performance_info (struct ATS_Address *address, uint32_t type) { int c1; GNUNET_assert (NULL != address); if ((NULL == address->atsi) || (0 == address->atsi_count)) return GNUNET_ATS_VALUE_UNDEFINED; for (c1 = 0; c1 < address->atsi_count; c1++) { if (ntohl(address->atsi[c1].type) == type) return ntohl(address->atsi[c1].value); } return GNUNET_ATS_VALUE_UNDEFINED; } struct CountContext { const struct GNUNET_CONTAINER_MultiPeerMap *map; int result; }; static int mlp_create_problem_count_addresses_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct CountContext *cctx = cls; /* Check if we have to add this peer due to a pending request */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (cctx->map, key)) cctx->result++; return GNUNET_OK; } static int mlp_create_problem_count_addresses (const struct GNUNET_CONTAINER_MultiPeerMap *requested_peers, const struct GNUNET_CONTAINER_MultiPeerMap *addresses) { struct CountContext cctx; cctx.map = requested_peers; cctx.result = 0; GNUNET_CONTAINER_multipeermap_iterate (addresses, &mlp_create_problem_count_addresses_it, &cctx); return cctx.result; } static int mlp_create_problem_count_peers_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct CountContext *cctx = cls; /* Check if we have to addresses for the requested peer */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (cctx->map, key)) cctx->result++; return GNUNET_OK; } static int mlp_create_problem_count_peers (const struct GNUNET_CONTAINER_MultiPeerMap *requested_peers, const struct GNUNET_CONTAINER_MultiPeerMap *addresses) { struct CountContext cctx; cctx.map = addresses; cctx.result = 0; GNUNET_CONTAINER_multipeermap_iterate (requested_peers, &mlp_create_problem_count_peers_it, &cctx); return cctx.result; } /** * Updates an existing value in the matrix * * Extract the row, updates the value and updates the row in the problem * * @param p the mlp problem * @param row the row to create the value in * @param col the column to create the value in * @param val the value to set * @param line calling line for debbuging * @return GNUNET_YES value changed, GNUNET_NO value did not change, GNUNET_SYSERR * on error */ static int mlp_create_problem_update_value (struct MLP_Problem *p, int row, int col, double val, int line) { int c_cols; int c_elems; int c1; int res; int found; double *val_array; int *ind_array; GNUNET_assert (NULL != p); GNUNET_assert (NULL != p->prob); /* Get number of columns and prepare data structure */ c_cols = glp_get_num_cols(p->prob); if (0 >= c_cols) return GNUNET_SYSERR; val_array = GNUNET_malloc ((c_cols +1)* sizeof (double)); GNUNET_assert (NULL != val_array); ind_array = GNUNET_malloc ((c_cols+1) * sizeof (int)); GNUNET_assert (NULL != ind_array); /* Extract the row */ /* Update the value */ c_elems = glp_get_mat_row (p->prob, row, ind_array, val_array); found = GNUNET_NO; for (c1 = 1; c1 < (c_elems+1); c1++) { if (ind_array[c1] == col) { found = GNUNET_YES; break; } } if (GNUNET_NO == found) { ind_array[c_elems+1] = col; val_array[c_elems+1] = val; LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Setting value in [%s : %s] to `%.2f'\n", glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col), val); glp_set_mat_row (p->prob, row, c_elems+1, ind_array, val_array); GNUNET_free (ind_array); GNUNET_free (val_array); return GNUNET_YES; } else { /* Update value */ LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Updating value in [%s : %s] from `%.2f' to `%.2f'\n", glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col), val_array[c1], val); if (val != val_array[c1]) res = GNUNET_YES; else res = GNUNET_NO; val_array[c1] = val; /* Update the row in the matrix */ glp_set_mat_row (p->prob, row, c_elems, ind_array, val_array); } GNUNET_free (ind_array); GNUNET_free (val_array); return res; } /** * Creates a new value in the matrix * * Sets the row and column index in the problem array and increments the * position field * * @param p the mlp problem * @param row the row to create the value in * @param col the column to create the value in * @param val the value to set * @param line calling line for debbuging */ static void mlp_create_problem_set_value (struct MLP_Problem *p, int row, int col, double val, int line) { if ((p->ci) >= p->num_elements) { LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: line %u: Request for index %u bigger than array size of %u\n", line, p->ci + 1, p->num_elements); GNUNET_break (0); return; } if ((0 == row) || (0 == col)) GNUNET_break (0); p->ia[p->ci] = row ; p->ja[p->ci] = col; p->ar[p->ci] = val; #if DEBUG_MLP_PROBLEM_CREATION LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: line %u: Set value [%u,%u] in index %u == %.2f\n", line, p->ia[p->ci], p->ja[p->ci], p->ci, p->ar[p->ci]); #endif p->ci++; } static int mlp_create_problem_create_column (struct MLP_Problem *p, char *name, unsigned int type, unsigned int bound, double lb, double ub, double coef) { int col = glp_add_cols (p->prob, 1); glp_set_col_name (p->prob, col, name); glp_set_col_bnds (p->prob, col, bound, lb, ub); glp_set_col_kind (p->prob, col, type); glp_set_obj_coef (p->prob, col, coef); #if DEBUG_MLP_PROBLEM_CREATION LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added column [%u] `%s': %.2f\n", col, name, coef); #endif return col; } static int mlp_create_problem_create_constraint (struct MLP_Problem *p, char *name, unsigned int bound, double lb, double ub) { char * op; int row = glp_add_rows (p->prob, 1); /* set row name */ glp_set_row_name (p->prob, row, name); /* set row bounds: <= 0 */ glp_set_row_bnds (p->prob, row, bound, lb, ub); switch (bound) { case GLP_UP: GNUNET_asprintf(&op, "-inf <= x <= %.2f", ub); break; case GLP_DB: GNUNET_asprintf(&op, "%.2f <= x <= %.2f", lb, ub); break; case GLP_FX: GNUNET_asprintf(&op, "%.2f == x == %.2f", lb, ub); break; case GLP_LO: GNUNET_asprintf(&op, "%.2f <= x <= inf", lb); break; default: GNUNET_asprintf(&op, "ERROR"); break; } #if DEBUG_MLP_PROBLEM_CREATION LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added row [%u] `%s': %s\n", row, name, op); #endif GNUNET_free (op); return row; } /** * Create the * - address columns b and n * - address dependent constraint rows c1, c3 * - peer dependent rows c2 and c9 * - Set address dependent entries in problem matrix as well */ static int mlp_create_problem_add_address_information (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GAS_MLP_Handle *mlp = cls; struct MLP_Problem *p = &mlp->p; struct ATS_Address *address = value; struct ATS_Peer *peer; struct MLP_information *mlpi; char *name; const double *props; uint32_t addr_net; int c; /* Check if we have to add this peer due to a pending request */ if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains(mlp->requested_peers, key)) return GNUNET_OK; mlpi = address->solver_information; if (NULL == mlpi) { fprintf (stderr, "%s %p\n",GNUNET_i2s (&address->peer), address); GNUNET_break (0); return GNUNET_OK; } /* Get peer */ peer = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, key); if (peer->processed == GNUNET_NO) { /* Add peer dependent constraints */ /* Add constraint c2 */ GNUNET_asprintf(&name, "c2_%s", GNUNET_i2s(&address->peer)); peer->r_c2 = mlp_create_problem_create_constraint (p, name, GLP_FX, 1.0, 1.0); GNUNET_free (name); /* Add constraint c9 */ GNUNET_asprintf(&name, "c9_%s", GNUNET_i2s(&address->peer)); peer->r_c9 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 0.0); GNUNET_free (name); /* c 9) set coefficient */ mlp_create_problem_set_value (p, peer->r_c9, p->c_r, -peer->f, __LINE__); peer->processed = GNUNET_YES; } /* Reset addresses' solver information */ mlpi->c_b = 0; mlpi->c_n = 0; mlpi->n = 0; mlpi->r_c1 = 0; mlpi->r_c3 = 0; /* Add bandwidth column */ GNUNET_asprintf (&name, "b_%s_%s_%p", GNUNET_i2s (&address->peer), address->plugin, address); #if TEST_MAX_BW_ASSIGNMENT mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 0.0, 1.0); #else mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 0.0, 0.0); #endif GNUNET_free (name); /* Add usage column */ GNUNET_asprintf (&name, "n_%s_%s_%p", GNUNET_i2s (&address->peer), address->plugin, address); mlpi->c_n = mlp_create_problem_create_column (p, name, GLP_IV, GLP_DB, 0.0, 1.0, 0.0); GNUNET_free (name); /* Add address dependent constraints */ /* Add constraint c1) bandwidth capping * b_t + (-M) * n_t <= 0 * */ GNUNET_asprintf(&name, "c1_%s_%s_%p", GNUNET_i2s(&address->peer), address->plugin, address); mlpi->r_c1 = mlp_create_problem_create_constraint (p, name, GLP_UP, 0.0, 0.0); GNUNET_free (name); /* c1) set b = 1 coefficient */ mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_b, 1, __LINE__); /* c1) set n = -M coefficient */ mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_n, -mlp->pv.BIG_M, __LINE__); /* Add constraint c 3) minimum bandwidth * b_t + (-n_t * b_min) >= 0 * */ GNUNET_asprintf(&name, "c3_%s_%s_%p", GNUNET_i2s(&address->peer), address->plugin, address); mlpi->r_c3 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 0.0); GNUNET_free (name); /* c3) set b = 1 coefficient */ mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_b, 1, __LINE__); /* c3) set n = -b_min coefficient */ mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_n, - ((double )mlp->pv.b_min), __LINE__); /* Set coefficient entries in invariant rows */ /* c 4) minimum connections */ mlp_create_problem_set_value (p, p->r_c4, mlpi->c_n, 1, __LINE__); /* c 6) maximize diversity */ mlp_create_problem_set_value (p, p->r_c6, mlpi->c_n, 1, __LINE__); /* c 2) 1 address peer peer */ mlp_create_problem_set_value (p, peer->r_c2, mlpi->c_n, 1, __LINE__); /* c 9) relativity */ mlp_create_problem_set_value (p, peer->r_c9, mlpi->c_b, 1, __LINE__); /* c 8) utility */ mlp_create_problem_set_value (p, p->r_c8, mlpi->c_b, 1, __LINE__); /* c 10) obey network specific quotas * (1)*b_1 + ... + (1)*b_m <= quota_n */ for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { addr_net = get_performance_info (address, GNUNET_ATS_NETWORK_TYPE); if (GNUNET_ATS_VALUE_UNDEFINED == addr_net) addr_net = GNUNET_ATS_NET_UNSPECIFIED; if (mlp->pv.quota_index[c] == addr_net) { mlp_create_problem_set_value (p, p->r_quota[c], mlpi->c_b, 1, __LINE__); break; } } /* c 7) Optimize quality */ /* For all quality metrics, set quality of this address */ props = mlp->get_properties (mlp->get_properties_cls, address); for (c = 0; c < mlp->pv.m_q; c++) mlp_create_problem_set_value (p, p->r_q[c], mlpi->c_b, props[c], __LINE__); return GNUNET_OK; } /** * Create the invariant columns c4, c6, c10, c8, c7 */ static void mlp_create_problem_add_invariant_rows (struct GAS_MLP_Handle *mlp, struct MLP_Problem *p) { char *name; int c; /* Row for c4) minimum connection */ /* Number of minimum connections is min(|Peers|, n_min) */ p->r_c4 = mlp_create_problem_create_constraint (p, "c4", GLP_LO, (mlp->pv.n_min > p->num_peers) ? p->num_peers : mlp->pv.n_min, 0.0); /* Add row for c6) */ p->r_c6 = mlp_create_problem_create_constraint (p, "c6", GLP_FX, 0.0, 0.0); /* c6 )Setting -D */ mlp_create_problem_set_value (p, p->r_c6, p->c_d, -1, __LINE__); /* Add rows for c 10) */ for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { char * text; GNUNET_asprintf(&text, "c10_quota_ats_%s", GNUNET_ATS_print_network_type(mlp->pv.quota_index[c])); p->r_quota[c] = mlp_create_problem_create_constraint (p, text, GLP_DB, 0.0, mlp->pv.quota_out[c]); GNUNET_free (text); } /* Adding rows for c 8) */ p->r_c8 = mlp_create_problem_create_constraint (p, "c8", GLP_FX, 0.0, 0.0); /* -u */ mlp_create_problem_set_value (p, p->r_c8, p->c_u, -1, __LINE__); /* c 7) For all quality metrics */ for (c = 0; c < mlp->pv.m_q; c++) { GNUNET_asprintf(&name, "c7_q%i_%s", c, mlp_ats_to_string(mlp->pv.q[c])); p->r_q[c] = mlp_create_problem_create_constraint (p, name, GLP_FX, 0.0, 0.0); GNUNET_free (name); mlp_create_problem_set_value (p, p->r_q[c], p->c_q[c], -1, __LINE__); } } /** * Create the invariant columns d, u, r, q0 ... qm */ static void mlp_create_problem_add_invariant_columns (struct GAS_MLP_Handle *mlp, struct MLP_Problem *p) { char *name; int c; #if TEST_MAX_BW_ASSIGNMENT mlp->pv.co_D = 0.0; mlp->pv.co_U = 0.0; #endif //mlp->pv.co_R = 0.0; /* Diversity d column */ p->c_d = mlp_create_problem_create_column (p, "d", GLP_CV, GLP_LO, 0.0, 0.0, mlp->pv.co_D); /* Utilization u column */ p->c_u = mlp_create_problem_create_column (p, "u", GLP_CV, GLP_LO, 0.0, 0.0, mlp->pv.co_U); /* Relativity r column */ p->c_r = mlp_create_problem_create_column (p, "r", GLP_CV, GLP_LO, 0.0, 0.0, mlp->pv.co_R); /* Quality metric columns */ for (c = 0; c < mlp->pv.m_q; c++) { GNUNET_asprintf (&name, "q_%u", mlp->pv.q[c]); #if TEST_MAX_BW_ASSIGNMENT p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 0.0, 0.0); #else p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 0.0, mlp->pv.co_Q[c]); #endif GNUNET_free (name); } } /** * Create the MLP problem * * @param mlp the MLP handle * @return GNUNET_OK or GNUNET_SYSERR */ static int mlp_create_problem (struct GAS_MLP_Handle *mlp) { struct MLP_Problem *p = &mlp->p; int res = GNUNET_OK; GNUNET_assert (p->prob == NULL); GNUNET_assert (p->ia == NULL); GNUNET_assert (p->ja == NULL); GNUNET_assert (p->ar == NULL); /* Reset MLP problem struct */ /* create the glpk problem */ p->prob = glp_create_prob (); GNUNET_assert (NULL != p->prob); p->num_peers = mlp_create_problem_count_peers (mlp->requested_peers, mlp->addresses); p->num_addresses = mlp_create_problem_count_addresses (mlp->requested_peers, mlp->addresses); /* Create problem matrix: 10 * #addresses + #q * #addresses + #q, + #peer + 2 + 1 */ p->num_elements = (10 * p->num_addresses + mlp->pv.m_q * p->num_addresses + mlp->pv.m_q + p->num_peers + 2 + 1); LOG (GNUNET_ERROR_TYPE_DEBUG, "Rebuilding problem for %u peer(s) and %u addresse(s) and %u quality metrics == %u elements\n", p->num_peers, p->num_addresses, mlp->pv.m_q, p->num_elements); /* Set a problem name */ glp_set_prob_name (p->prob, "GNUnet ATS bandwidth distribution"); /* Set optimization direction to maximize */ glp_set_obj_dir (p->prob, GLP_MAX); /* Create problem matrix */ /* last +1 caused by glpk index starting with one: [1..elements]*/ p->ci = 1; /* row index */ p->ia = GNUNET_malloc (p->num_elements * sizeof (int)); /* column index */ p->ja = GNUNET_malloc (p->num_elements * sizeof (int)); /* coefficient */ p->ar = GNUNET_malloc (p->num_elements * sizeof (double)); if ((NULL == p->ia) || (NULL == p->ja) || (NULL == p->ar)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Problem size too large, cannot allocate memory!\n")); return GNUNET_SYSERR; } /* Adding invariant columns */ mlp_create_problem_add_invariant_columns (mlp, p); /* Adding address independent constraint rows */ mlp_create_problem_add_invariant_rows (mlp, p); /* Adding address dependent columns constraint rows */ GNUNET_CONTAINER_multipeermap_iterate (mlp->addresses, &mlp_create_problem_add_address_information, mlp); /* Load the matrix */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Loading matrix\n"); glp_load_matrix(p->prob, (p->ci)-1, p->ia, p->ja, p->ar); return res; } /** * Solves the LP problem * * @param mlp the MLP Handle * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure */ static int mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp) { int res = 0; res = glp_simplex(mlp->p.prob, &mlp->control_param_lp); if (0 == res) LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: 0x%02X %s\n", res, mlp_solve_to_string(res)); else LOG (GNUNET_ERROR_TYPE_WARNING, "Solving LP problem failed: 0x%02X %s\n", res, mlp_solve_to_string(res)); /* Analyze problem status */ res = glp_get_status (mlp->p.prob); switch (res) { /* solution is optimal */ case GLP_OPT: /* solution is feasible */ case GLP_FEAS: LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: 0x%02X %s\n", res, mlp_status_to_string(res)); return GNUNET_OK; /* Problem was ill-defined, no way to handle that */ default: LOG (GNUNET_ERROR_TYPE_WARNING, "Solving LP problem failed, no solution: 0x%02X %s\n", res, mlp_status_to_string(res)); return GNUNET_SYSERR; } } /** * Solves the MLP problem * * @param mlp the MLP Handle * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure */ int mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp) { int res = 0; res = glp_intopt(mlp->p.prob, &mlp->control_param_mlp); if (0 == res) LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving MLP problem: 0x%02X %s\n", res, mlp_solve_to_string(res)); else LOG (GNUNET_ERROR_TYPE_WARNING, "Solving MLP problem failed: 0x%02X %s\n", res, mlp_solve_to_string(res)); /* Analyze problem status */ res = glp_mip_status(mlp->p.prob); switch (res) { /* solution is optimal */ case GLP_OPT: /* solution is feasible */ case GLP_FEAS: LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving MLP problem: 0x%02X %s\n", res, mlp_status_to_string(res)); return GNUNET_OK; /* Problem was ill-defined, no way to handle that */ default: LOG (GNUNET_ERROR_TYPE_WARNING,"Solving MLP problem failed, 0x%02X %s\n\n", res, mlp_status_to_string(res)); return GNUNET_SYSERR; } } /** * Propagates the results when MLP problem was solved * * @param cls the MLP handle * @param key the peer identity * @param value the address * @return #GNUNET_OK to continue */ int mlp_propagate_results (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GAS_MLP_Handle *mlp = cls; struct ATS_Address *address; struct MLP_information *mlpi; double mlp_bw_in = MLP_NaN; double mlp_bw_out = MLP_NaN; double mlp_use = MLP_NaN; /* Check if we have to add this peer due to a pending request */ if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (mlp->requested_peers, key)) { return GNUNET_OK; } address = value; GNUNET_assert (address->solver_information != NULL); mlpi = address->solver_information; mlp_bw_in = glp_mip_col_val(mlp->p.prob, mlpi->c_b);/* FIXME */ if (mlp_bw_in > (double) UINT32_MAX) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Overflow in assigned bandwidth, reducing ...\n" ); mlp_bw_in = (double) UINT32_MAX; } mlp_bw_out = glp_mip_col_val(mlp->p.prob, mlpi->c_b); if (mlp_bw_out > (double) UINT32_MAX) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Overflow in assigned bandwidth, reducing ...\n" ); mlp_bw_out = (double) UINT32_MAX; } mlp_use = glp_mip_col_val(mlp->p.prob, mlpi->c_n); /* * Debug: solution * LOG (GNUNET_ERROR_TYPE_INFO, "MLP result address: `%s' `%s' length %u session %u, mlp use %f\n", * GNUNET_i2s(&address->peer), address->plugin, * address->addr_len, address->session_id); */ if (GLP_YES == mlp_use) { /* This address was selected by the solver to be used */ mlpi->n = GNUNET_YES; if (GNUNET_NO == address->active) { /* Address was not used before, enabling address */ LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : enabling address\n", (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out); address->active = GNUNET_YES; address->assigned_bw_in.value__ = htonl (mlp_bw_in); mlpi->b_in.value__ = htonl(mlp_bw_in); address->assigned_bw_out.value__ = htonl (mlp_bw_out); mlpi->b_out.value__ = htonl(mlp_bw_out); if ((NULL == mlp->exclude_peer) || (0 != memcmp (&address->peer, mlp->exclude_peer, sizeof (address->peer)))) mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address); return GNUNET_OK; } else if (GNUNET_YES == address->active) { /* Address was used before, check for bandwidth change */ if ((mlp_bw_out != ntohl(address->assigned_bw_out.value__)) || (mlp_bw_in != ntohl(address->assigned_bw_in.value__))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : bandwidth changed\n", (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out); address->assigned_bw_in.value__ = htonl (mlp_bw_in); mlpi->b_in.value__ = htonl(mlp_bw_in); address->assigned_bw_out.value__ = htonl (mlp_bw_out); mlpi->b_out.value__ = htonl(mlp_bw_out); if ((NULL == mlp->exclude_peer) || (0 != memcmp (&address->peer, mlp->exclude_peer, sizeof (address->peer)))) mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address); return GNUNET_OK; } } else GNUNET_break (0); } else if (GLP_NO == mlp_use) { /* This address was selected by the solver to be not used */ mlpi->n = GNUNET_NO; if (GNUNET_NO == address->active) { /* Address was not used before, nothing to do */ LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : no change\n", (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out); return GNUNET_OK; } else if (GNUNET_YES == address->active) { /* Address was used before, disabling address */ LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : disabling address\n", (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out); address->active = GNUNET_NO; /* Set bandwidth to 0 */ address->assigned_bw_in = BANDWIDTH_ZERO; mlpi->b_in.value__ = htonl(mlp_bw_in); address->assigned_bw_out = BANDWIDTH_ZERO; mlpi->b_out.value__ = htonl(mlp_bw_out); //mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address); return GNUNET_OK; } else GNUNET_break (0); } else GNUNET_break (0); return GNUNET_OK; } static void notify (struct GAS_MLP_Handle *mlp, enum GAS_Solver_Operation op, enum GAS_Solver_Status stat, enum GAS_Solver_Additional_Information add) { if (NULL != mlp->env->info_cb) mlp->env->info_cb (mlp->env->info_cb_cls, op, stat, add); } /** * Solves the MLP problem * * @param solver the MLP Handle * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure */ int GAS_mlp_solve_problem (void *solver) { struct GAS_MLP_Handle *mlp = solver; char *filename; int res_lp = 0; int res_mip = 0; struct GNUNET_TIME_Absolute start_total; struct GNUNET_TIME_Absolute start_cur_op; struct GNUNET_TIME_Relative dur_total; struct GNUNET_TIME_Relative dur_setup; struct GNUNET_TIME_Relative dur_lp; struct GNUNET_TIME_Relative dur_mlp; GNUNET_assert(NULL != solver); if (GNUNET_YES == mlp->stat_bulk_lock) { mlp->stat_bulk_requests++; return GNUNET_NO; } notify(mlp, GAS_OP_SOLVE_START, GAS_STAT_SUCCESS, (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED); start_total = GNUNET_TIME_absolute_get(); if (0 == GNUNET_CONTAINER_multipeermap_size(mlp->requested_peers)) { notify(mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE); return GNUNET_OK; /* No pending requests */ } if (0 == GNUNET_CONTAINER_multipeermap_size(mlp->addresses)) { notify(mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE); return GNUNET_OK; /* No addresses available */ } if ((GNUNET_NO == mlp->stat_mlp_prob_changed) && (GNUNET_NO == mlp->stat_mlp_prob_updated)) { LOG(GNUNET_ERROR_TYPE_DEBUG, "No changes to problem\n"); notify(mlp, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_NONE); return GNUNET_OK; } if (GNUNET_YES == mlp->stat_mlp_prob_changed) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Problem size changed, rebuilding\n"); notify(mlp, GAS_OP_SOLVE_SETUP_START, GAS_STAT_SUCCESS, GAS_INFO_FULL); mlp_delete_problem(mlp); if (GNUNET_SYSERR == mlp_create_problem(mlp)) { notify(mlp, GAS_OP_SOLVE_SETUP_STOP, GAS_STAT_FAIL, GAS_INFO_FULL); return GNUNET_SYSERR; } notify(mlp, GAS_OP_SOLVE_SETUP_STOP, GAS_STAT_SUCCESS, GAS_INFO_FULL); mlp->control_param_lp.presolve = GLP_YES; mlp->control_param_mlp.presolve = GNUNET_NO; /* No presolver, we have LP solution */ } else { LOG(GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n"); } dur_setup = GNUNET_TIME_absolute_get_duration (start_total); /* Run LP solver */ notify(mlp, GAS_OP_SOLVE_MLP_LP_START, GAS_STAT_SUCCESS, (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED); LOG(GNUNET_ERROR_TYPE_DEBUG, "Running LP solver %s\n", (GLP_YES == mlp->control_param_lp.presolve)? "with presolver": "without presolver"); start_cur_op = GNUNET_TIME_absolute_get(); /* Solve LP */ mlp->control_param_lp.presolve = GLP_YES; res_lp = mlp_solve_lp_problem(mlp); dur_lp = GNUNET_TIME_absolute_get_duration (start_cur_op); notify(mlp, GAS_OP_SOLVE_MLP_LP_STOP, (GNUNET_OK == res_lp) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL, (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED); /* Run MLP solver */ if (GNUNET_OK == res_lp) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n"); notify(mlp, GAS_OP_SOLVE_MLP_MLP_START, GAS_STAT_SUCCESS, (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED); start_cur_op = GNUNET_TIME_absolute_get(); /* Solve MIP */ //mlp->control_param_mlp.presolve = GNUNET_YES; res_mip = mlp_solve_mlp_problem(mlp); dur_mlp = GNUNET_TIME_absolute_get_duration (start_cur_op); dur_total = GNUNET_TIME_absolute_get_duration (start_total); notify(mlp, GAS_OP_SOLVE_MLP_MLP_STOP, (GNUNET_OK == res_mip) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL, (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED); } else { /* Do not execute mip solver since lp solution is invalid */ dur_mlp = GNUNET_TIME_UNIT_ZERO; dur_total = GNUNET_TIME_absolute_get_duration (start_total); notify(mlp, GAS_OP_SOLVE_MLP_MLP_STOP, GAS_STAT_FAIL, (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED); res_mip = GNUNET_SYSERR; } /* Notify about end */ notify(mlp, GAS_OP_SOLVE_STOP, ((GNUNET_OK == res_mip) && (GNUNET_OK == res_mip)) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL, (GNUNET_YES == mlp->stat_mlp_prob_changed) ? GAS_INFO_FULL : GAS_INFO_UPDATED); LOG (GNUNET_ERROR_TYPE_DEBUG, "Execution time for %s solve: (total/setup/lp/mlp) : %llu %llu %llu %llu\n", (GNUNET_YES == mlp->stat_mlp_prob_changed) ? "full" : "updated", (unsigned long long) dur_total.rel_value_us, (unsigned long long) dur_setup.rel_value_us, (unsigned long long) dur_lp.rel_value_us, (unsigned long long) dur_mlp.rel_value_us); /* Save stats */ mlp->ps.lp_res = res_lp; mlp->ps.mip_res = res_mip; mlp->ps.lp_presolv = mlp->control_param_lp.presolve; mlp->ps.mip_presolv = mlp->control_param_mlp.presolve; mlp->ps.p_cols = glp_get_num_cols(mlp->p.prob); mlp->ps.p_rows = glp_get_num_rows(mlp->p.prob); mlp->ps.p_elements = mlp->p.num_elements; /* Propagate result*/ notify(mlp, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, (GNUNET_OK == res_lp) && (GNUNET_OK == res_mip) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL, GAS_INFO_NONE); if ((GNUNET_OK == res_lp) && (GNUNET_OK == res_mip)) { GNUNET_CONTAINER_multipeermap_iterate(mlp->addresses, &mlp_propagate_results, mlp); } notify(mlp, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, (GNUNET_OK == res_lp) && (GNUNET_OK == res_mip) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL, GAS_INFO_NONE); struct GNUNET_TIME_Absolute time = GNUNET_TIME_absolute_get(); if ( (GNUNET_YES == mlp->opt_dump_solution_all) || (mlp->opt_dump_solution_on_fail && ((GNUNET_OK != res_lp) || (GNUNET_OK != res_mip))) ) { /* Write problem to disk */ GNUNET_asprintf(&filename, "problem_p_%u_a%u_%llu.lp", mlp->p.num_peers, mlp->p.num_addresses, time.abs_value_us); LOG(GNUNET_ERROR_TYPE_ERROR, "Dumped problem to file: `%s' \n", filename); glp_write_lp (mlp->p.prob, NULL, filename); GNUNET_free(filename); } if ( (mlp->opt_dump_solution_all) || (mlp->opt_dump_solution_on_fail && ((GNUNET_OK != res_lp) || (GNUNET_OK != res_mip))) ) { /* Write solution to disk */ GNUNET_asprintf(&filename, "problem_p_%u_a%u_%llu.sol", mlp->p.num_peers, mlp->p.num_addresses, time.abs_value_us); glp_print_mip(mlp->p.prob, filename); LOG(GNUNET_ERROR_TYPE_ERROR, "Dumped solution to file: `%s' \n", filename); GNUNET_free(filename); } /* Reset change and update marker */ mlp->control_param_lp.presolve = GLP_NO; mlp->stat_mlp_prob_updated = GNUNET_NO; mlp->stat_mlp_prob_changed = GNUNET_NO; if ((GNUNET_OK == res_lp) && (GNUNET_OK == res_mip)) return GNUNET_OK; else return GNUNET_SYSERR; } /** * Add a single address to the solve * * @param solver the solver Handle * @param address the address to add * @param network network type of this address */ void GAS_mlp_address_add (void *solver, struct ATS_Address *address, uint32_t network) { struct GAS_MLP_Handle *mlp = solver; struct ATS_Peer *p; GNUNET_assert (NULL != solver); GNUNET_assert (NULL != address); if (GNUNET_ATS_NetworkTypeCount <= network) { GNUNET_break (0); return; } if (NULL == address->solver_information) { address->solver_information = GNUNET_new (struct MLP_information); } else LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding address for peer `%s' multiple times\n"), GNUNET_i2s(&address->peer)); /* Is this peer included in the problem? */ if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, &address->peer))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s' without address request \n", GNUNET_i2s(&address->peer)); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer `%s' with address request \n", GNUNET_i2s(&address->peer)); /* Problem size changed: new address for peer with pending request */ mlp->stat_mlp_prob_changed = GNUNET_YES; if (GNUNET_YES == mlp->opt_mlp_auto_solve) GAS_mlp_solve_problem (solver); } /** * Transport properties for this address have changed * * @param solver solver handle * @param address the address * @param type the ATSI type in HBO * @param abs_value the absolute value of the property * @param rel_value the normalized value */ void GAS_mlp_address_property_changed (void *solver, struct ATS_Address *address, uint32_t type, uint32_t abs_value, double rel_value) { struct MLP_information *mlpi = address->solver_information; struct GAS_MLP_Handle *mlp = solver; struct ATS_Peer *p; int c1; int type_index; GNUNET_assert (NULL != solver); GNUNET_assert (NULL != address); if (NULL == mlpi) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Updating address property `%s' for peer `%s' %p not added before\n"), GNUNET_ATS_print_property_type (type), GNUNET_i2s(&address->peer), address); GNUNET_break (0); return; } if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, &address->peer))) { /* Peer is not requested, so no need to update problem */ return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Updating property `%s' address for peer `%s'\n", GNUNET_ATS_print_property_type (type), GNUNET_i2s(&address->peer)); /* Find row index */ type_index = -1; for (c1 = 0; c1 < mlp->pv.m_q; c1++) { if (type == mlp->pv.q[c1]) { type_index = c1; break; } } if (-1 == type_index) { GNUNET_break (0); return; /* quality index not found */ } /* Update c7) [r_q[index]][c_b] = f_q * q_averaged[type_index] */ if (GNUNET_YES == mlp_create_problem_update_value (&mlp->p, mlp->p.r_q[type_index], mlpi->c_b, rel_value, __LINE__)) { mlp->stat_mlp_prob_updated = GNUNET_YES; if (GNUNET_YES == mlp->opt_mlp_auto_solve) GAS_mlp_solve_problem (solver); } } /** * Transport session for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param cur_session the current session * @param new_session the new session */ void GAS_mlp_address_session_changed (void *solver, struct ATS_Address *address, uint32_t cur_session, uint32_t new_session) { /* Nothing to do here */ return; } /** * Transport session for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param in_use usage state */ void GAS_mlp_address_inuse_changed (void *solver, struct ATS_Address *address, int in_use) { /* Nothing to do here */ return; } /** * Network scope for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param current_network the current network * @param new_network the new network */ void GAS_mlp_address_change_network (void *solver, struct ATS_Address *address, uint32_t current_network, uint32_t new_network) { struct MLP_information *mlpi = address->solver_information; struct GAS_MLP_Handle *mlp = solver; struct ATS_Peer *p; int nets_avail[] = GNUNET_ATS_NetworkType; int c1; GNUNET_assert (NULL != solver); GNUNET_assert (NULL != address); if (GNUNET_ATS_NetworkTypeCount <= new_network) { GNUNET_break (0); return; } if (NULL == mlpi) { GNUNET_break (0); return; } if (mlpi->c_b == MLP_UNDEFINED) return; /* This address is not yet in the matrix*/ if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, &address->peer))) { /* Peer is not requested, so no need to update problem */ GNUNET_break (0); return; } if (current_network == new_network) { GNUNET_break (0); return; } for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount ; c1 ++) { if (nets_avail[c1] == new_network) break; } if (GNUNET_ATS_NetworkTypeCount == c1) { /* Invalid network */ GNUNET_break (0); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Updating network for peer `%s' from `%s' to `%s'\n", GNUNET_i2s (&address->peer), GNUNET_ATS_print_network_type(current_network), GNUNET_ATS_print_network_type(new_network)); for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount; c1++) { if (mlp->pv.quota_index[c1] == current_network) { /* Remove from old network */ mlp_create_problem_update_value (&mlp->p, mlp->p.r_quota[c1], mlpi->c_b, 0.0, __LINE__); break; } } for (c1 = 0; c1 < GNUNET_ATS_NetworkTypeCount; c1++) { if (mlp->pv.quota_index[c1] == new_network) { /* Remove from old network */ if (GNUNET_SYSERR == mlp_create_problem_update_value (&mlp->p, mlp->p.r_quota[c1], mlpi->c_b, 1.0, __LINE__)) { /* This quota did not exist in the problem, recreate */ GNUNET_break (0); } break; } } mlp->stat_mlp_prob_changed = GNUNET_YES; } /** * Deletes a single address in the MLP problem * * The MLP problem has to be recreated and the problem has to be resolved * * @param solver the MLP Handle * @param address the address to delete * @param session_only delete only session not whole address */ void GAS_mlp_address_delete (void *solver, struct ATS_Address *address, int session_only) { struct ATS_Peer *p; struct GAS_MLP_Handle *mlp = solver; struct MLP_information *mlpi; int was_active; GNUNET_assert (NULL != solver); GNUNET_assert (NULL != address); mlpi = address->solver_information; if ((GNUNET_NO == session_only) && (NULL != mlpi)) { /* Remove full address */ GNUNET_free (mlpi); address->solver_information = NULL; } was_active = address->active; address->active = GNUNET_NO; address->assigned_bw_in = BANDWIDTH_ZERO; address->assigned_bw_out = BANDWIDTH_ZERO; /* Is this peer included in the problem? */ if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, &address->peer))) { LOG (GNUNET_ERROR_TYPE_INFO, "Deleting %s for peer `%s' without address request \n", (session_only == GNUNET_YES) ? "session" : "address", GNUNET_i2s(&address->peer)); return; } LOG (GNUNET_ERROR_TYPE_INFO, "Deleting %s for peer `%s' with address request \n", (session_only == GNUNET_YES) ? "session" : "address", GNUNET_i2s(&address->peer)); /* Problem size changed: new address for peer with pending request */ mlp->stat_mlp_prob_changed = GNUNET_YES; if (GNUNET_YES == mlp->opt_mlp_auto_solve) { GAS_mlp_solve_problem (solver); } if (GNUNET_YES == was_active) { if (NULL == GAS_mlp_get_preferred_address (solver, &address->peer)) { /* No alternative address, disconnecting peer */ mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address); } } return; } /** * Find the active address in the set of addresses of a peer * @param cls destination * @param key peer id * @param value address * @return GNUNET_OK */ static int mlp_get_preferred_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { static int counter = 0; struct ATS_Address **aa = cls; struct ATS_Address *addr = value; struct MLP_information *mlpi = addr->solver_information; if (mlpi == NULL) return GNUNET_YES; /* * Debug output * GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, * "MLP [%u] Peer `%s' %s length %u session %u active %s mlp active %s\n", * counter, GNUNET_i2s (&addr->peer), addr->plugin, addr->addr_len, addr->session_id, * (GNUNET_YES == addr->active) ? "active" : "inactive", * (GNUNET_YES == mlpi->n) ? "active" : "inactive"); */ if (GNUNET_YES == mlpi->n) { (*aa) = addr; (*aa)->assigned_bw_in = mlpi->b_in; (*aa)->assigned_bw_out = mlpi->b_out; return GNUNET_NO; } counter ++; return GNUNET_YES; } static double get_peer_pref_value (struct GAS_MLP_Handle *mlp, const struct GNUNET_PeerIdentity *peer) { double res; const double *preferences = NULL; int c; preferences = mlp->get_preferences (mlp->get_preferences_cls, peer); res = 0.0; for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) { if (c != GNUNET_ATS_PREFERENCE_END) { //fprintf (stderr, "VALUE[%u] %s %.3f \n", c, GNUNET_i2s (&cur->addr->peer), t[c]); res += preferences[c]; } } res /= (GNUNET_ATS_PreferenceCount -1); return res; } /** * Get the preferred address for a specific peer * * @param solver the MLP Handle * @param peer the peer * @return suggested address */ const struct ATS_Address * GAS_mlp_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer) { struct GAS_MLP_Handle *mlp = solver; struct ATS_Peer *p; struct ATS_Address *res; GNUNET_assert (NULL != solver); GNUNET_assert (NULL != peer); LOG (GNUNET_ERROR_TYPE_DEBUG, "Getting preferred address for `%s'\n", GNUNET_i2s (peer)); /* Is this peer included in the problem? */ if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, peer))) { LOG (GNUNET_ERROR_TYPE_INFO, "Adding peer `%s' to list of requested_peers with requests\n", GNUNET_i2s (peer)); p = GNUNET_new (struct ATS_Peer); p->id = (*peer); p->f = get_peer_pref_value (mlp, peer); GNUNET_CONTAINER_multipeermap_put (mlp->requested_peers, peer, p, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); /* Added new peer, we have to rebuild problem before solving */ mlp->stat_mlp_prob_changed = GNUNET_YES; if ((GNUNET_YES == mlp->opt_mlp_auto_solve)&& (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(mlp->addresses, peer))) { mlp->exclude_peer = peer; GAS_mlp_solve_problem (mlp); mlp->exclude_peer = NULL; } } /* Get prefered address */ res = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (mlp->addresses, peer, mlp_get_preferred_address_it, &res); return res; } /** * Start a bulk operation * * @param solver the solver */ void GAS_mlp_bulk_start (void *solver) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Locking solver for bulk operation ...\n"); struct GAS_MLP_Handle *s = (struct GAS_MLP_Handle *) solver; GNUNET_assert (NULL != solver); s->stat_bulk_lock ++; } void GAS_mlp_bulk_stop (void *solver) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Unlocking solver from bulk operation ...\n"); struct GAS_MLP_Handle *s = (struct GAS_MLP_Handle *) solver; GNUNET_assert (NULL != solver); if (s->stat_bulk_lock < 1) { GNUNET_break (0); return; } s->stat_bulk_lock --; if (0 < s->stat_bulk_requests) { GAS_mlp_solve_problem (solver); s->stat_bulk_requests= 0; } } /** * Stop notifying about address and bandwidth changes for this peer * * @param solver the MLP handle * @param peer the peer */ void GAS_mlp_stop_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer) { struct GAS_MLP_Handle *mlp = solver; struct ATS_Peer *p = NULL; GNUNET_assert (NULL != solver); GNUNET_assert (NULL != peer); if (NULL != (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, peer))) { GNUNET_CONTAINER_multipeermap_remove (mlp->requested_peers, peer, p); GNUNET_free (p); mlp->stat_mlp_prob_changed = GNUNET_YES; if (GNUNET_YES == mlp->opt_mlp_auto_solve) { GAS_mlp_solve_problem (solver); } } } /** * Changes the preferences for a peer in the MLP problem * * @param solver the MLP Handle * @param peer the peer * @param kind the kind to change the preference * @param pref_rel the relative score */ void GAS_mlp_address_change_preference (void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel) { struct GAS_MLP_Handle *mlp = solver; struct ATS_Peer *p = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "Changing preference for address for peer `%s' to %.2f\n", GNUNET_i2s(peer), pref_rel); GNUNET_STATISTICS_update (mlp->stats,"# LP address preference changes", 1, GNUNET_NO); /* Update the constraints with changed preferences */ /* Update quality constraint c7 */ /* Update relativity constraint c9 */ if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, peer))) { LOG (GNUNET_ERROR_TYPE_ERROR, "Updating preference for unknown peer `%s'\n", GNUNET_i2s(peer)); return; } p->f = get_peer_pref_value (mlp, peer); /* LOG (GNUNET_ERROR_TYPE_ERROR, "PEER PREF: %s %.2f\n", GNUNET_i2s(peer), p->f);*/ mlp_create_problem_update_value (&mlp->p, p->r_c9, mlp->p.c_r, -p->f, __LINE__); /* Problem size changed: new address for peer with pending request */ mlp->stat_mlp_prob_updated = GNUNET_YES; if (GNUNET_YES == mlp->opt_mlp_auto_solve) GAS_mlp_solve_problem (solver); return; } /** * Get application feedback for a peer * * @param solver the solver handle * @param application the application * @param peer the peer to change the preference for * @param scope the time interval for this feedback: [now - scope .. now] * @param kind the kind to change the preference * @param score the score */ void GAS_mlp_address_preference_feedback (void *solver, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score) { struct GAS_PROPORTIONAL_Handle *s = solver; GNUNET_assert (NULL != solver); GNUNET_assert (NULL != peer); GNUNET_assert (NULL != s); } static int mlp_free_peers (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_CONTAINER_MultiPeerMap *map = cls; struct ATS_Peer *p = value; GNUNET_CONTAINER_multipeermap_remove (map, key, value); GNUNET_free (p); return GNUNET_OK; } /** * Shutdown the MLP problem solving component * * @param cls the solver handle * @return NULL */ void * libgnunet_plugin_ats_mlp_done (void *cls) { struct GAS_MLP_Handle *mlp = cls; GNUNET_assert (mlp != NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down mlp solver\n"); mlp_delete_problem (mlp); GNUNET_CONTAINER_multipeermap_iterate (mlp->requested_peers, &mlp_free_peers, mlp->requested_peers); GNUNET_CONTAINER_multipeermap_destroy (mlp->requested_peers); mlp->requested_peers = NULL; /* Clean up GLPK environment */ glp_free_env(); GNUNET_free (mlp); LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutdown down of mlp solver complete\n"); return NULL; } void * libgnunet_plugin_ats_mlp_init (void *cls) { struct GNUNET_ATS_PluginEnvironment *env = cls; struct GAS_MLP_Handle * mlp = GNUNET_new (struct GAS_MLP_Handle); double D; double R; double U; unsigned long long tmp; unsigned int b_min; unsigned int n_min; int c; int c2; int found; struct GNUNET_TIME_Relative max_duration; long long unsigned int max_iterations; GNUNET_assert (NULL != env->cfg); GNUNET_assert (NULL != env->addresses); GNUNET_assert (NULL != env->bandwidth_changed_cb); GNUNET_assert (NULL != env->get_preferences); GNUNET_assert (NULL != env->get_property); /* Init GLPK environment */ int res = glp_init_env(); switch (res) { case 0: LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n", "initialization successful"); break; case 1: LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n", "environment is already initialized"); break; case 2: LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n", "initialization failed (insufficient memory)"); GNUNET_free(mlp); return NULL; break; case 3: LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n", "initialization failed (unsupported programming model)"); GNUNET_free(mlp); return NULL; break; default: break; } mlp->opt_dump_problem_all = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "ats", "MLP_DUMP_PROBLEM_ALL"); if (GNUNET_SYSERR == mlp->opt_dump_problem_all) mlp->opt_dump_problem_all = GNUNET_NO; mlp->opt_dump_solution_all = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "ats", "MLP_DUMP_SOLUTION_ALL"); if (GNUNET_SYSERR == mlp->opt_dump_solution_all) mlp->opt_dump_solution_all = GNUNET_NO; mlp->opt_dump_problem_on_fail = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "ats", "MLP_DUMP_PROBLEM_ON_FAIL"); if (GNUNET_SYSERR == mlp->opt_dump_problem_on_fail) mlp->opt_dump_problem_on_fail = GNUNET_NO; mlp->opt_dump_solution_on_fail = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "ats", "MLP_DUMP_SOLUTION_ON_FAIL"); if (GNUNET_SYSERR == mlp->opt_dump_solution_on_fail) mlp->opt_dump_solution_on_fail = GNUNET_NO; mlp->opt_glpk_verbose = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "ats", "MLP_GLPK_VERBOSE"); if (GNUNET_SYSERR == mlp->opt_glpk_verbose) mlp->opt_glpk_verbose = GNUNET_NO; mlp->pv.BIG_M = (double) BIG_M_VALUE; /* Get timeout for iterations */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time(env->cfg, "ats", "MLP_MAX_DURATION", &max_duration)) { max_duration = MLP_MAX_EXEC_DURATION; } /* Get maximum number of iterations */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size(env->cfg, "ats", "MLP_MAX_ITERATIONS", &max_iterations)) { max_iterations = MLP_MAX_ITERATIONS; } /* Get diversity coefficient from configuration */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", "MLP_COEFFICIENT_D", &tmp)) D = (double) tmp / 100; else D = DEFAULT_D; /* Get proportionality coefficient from configuration */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", "MLP_COEFFICIENT_R", &tmp)) R = (double) tmp / 100; else R = DEFAULT_R; /* Get utilization coefficient from configuration */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", "MLP_COEFFICIENT_U", &tmp)) U = (double) tmp / 100; else U = DEFAULT_U; /* Get quality metric coefficients from configuration */ int i_delay = MLP_NaN; int i_distance = MLP_NaN; int q[GNUNET_ATS_QualityPropertiesCount] = GNUNET_ATS_QualityProperties; for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++) { /* initialize quality coefficients with default value 1.0 */ mlp->pv.co_Q[c] = DEFAULT_QUALITY; mlp->pv.q[c] = q[c]; if (q[c] == GNUNET_ATS_QUALITY_NET_DELAY) i_delay = c; if (q[c] == GNUNET_ATS_QUALITY_NET_DISTANCE) i_distance = c; } if ( (i_delay != MLP_NaN) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", "MLP_COEFFICIENT_QUALITY_DELAY", &tmp)) ) mlp->pv.co_Q[i_delay] = (double) tmp / 100; else mlp->pv.co_Q[i_delay] = DEFAULT_QUALITY; if ( (i_distance != MLP_NaN) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", "MLP_COEFFICIENT_QUALITY_DISTANCE", &tmp)) ) mlp->pv.co_Q[i_distance] = (double) tmp / 100; else mlp->pv.co_Q[i_distance] = DEFAULT_QUALITY; /* Get minimum bandwidth per used address from configuration */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", "MLP_MIN_BANDWIDTH", &tmp)) b_min = tmp; else { b_min = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); } /* Get minimum number of connections from configuration */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_size (env->cfg, "ats", "MLP_MIN_CONNECTIONS", &tmp)) n_min = tmp; else n_min = DEFAULT_MIN_CONNECTIONS; /* Init network quotas */ int quotas[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType; for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { found = GNUNET_NO; for (c2 = 0; c2 < env->network_count; c2++) { if (quotas[c] == env->networks[c2]) { mlp->pv.quota_index[c] = env->networks[c2]; mlp->pv.quota_out[c] = env->out_quota[c2]; mlp->pv.quota_in[c] = env->in_quota[c2]; found = GNUNET_YES; LOG (GNUNET_ERROR_TYPE_DEBUG, "Quota for network `%s' (in/out) %llu/%llu\n", GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]), mlp->pv.quota_out[c], mlp->pv.quota_in[c]); break; } } /* Check if defined quota could make problem unsolvable */ if ((n_min * b_min) > mlp->pv.quota_out[c]) { LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inconsistent outbound quota configuration for network `%s', is %llu must be at least %llu\n"), GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]), mlp->pv.quota_out[c], (n_min * b_min)); mlp->pv.quota_out[c] = (n_min * b_min); } if ((n_min * b_min) > mlp->pv.quota_in[c]) { LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inconsistent inbound quota configuration for network `%s', is %llu must be at least %llu\n"), GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]), mlp->pv.quota_in[c], (n_min * b_min)); mlp->pv.quota_in[c] = (n_min * b_min); } /* Check if bandwidth is too big to make problem solvable */ if (mlp->pv.BIG_M < mlp->pv.quota_out[c]) { LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n"), GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]), mlp->pv.quota_out[c], mlp->pv.BIG_M); mlp->pv.quota_out[c] = mlp->pv.BIG_M ; } if (mlp->pv.BIG_M < mlp->pv.quota_in[c]) { LOG (GNUNET_ERROR_TYPE_INFO, _("Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n"), GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]), mlp->pv.quota_in[c], mlp->pv.BIG_M); mlp->pv.quota_in[c] = mlp->pv.BIG_M ; } if (GNUNET_NO == found) { mlp->pv.quota_in[c] = ntohl(GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); mlp->pv.quota_out[c] = ntohl(GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); LOG (GNUNET_ERROR_TYPE_INFO, _("Using default quota configuration for network `%s' (in/out) %llu/%llu\n"), GNUNET_ATS_print_network_type(mlp->pv.quota_index[c]), mlp->pv.quota_in[c], mlp->pv.quota_out[c]); } } mlp->env = env; env->sf.s_add = &GAS_mlp_address_add; env->sf.s_address_update_property = &GAS_mlp_address_property_changed; env->sf.s_address_update_session = &GAS_mlp_address_session_changed; env->sf.s_address_update_inuse = &GAS_mlp_address_inuse_changed; env->sf.s_address_update_network = &GAS_mlp_address_change_network; env->sf.s_get = &GAS_mlp_get_preferred_address; env->sf.s_get_stop = &GAS_mlp_stop_get_preferred_address; env->sf.s_pref = &GAS_mlp_address_change_preference; env->sf.s_feedback = &GAS_mlp_address_preference_feedback; env->sf.s_del = &GAS_mlp_address_delete; env->sf.s_bulk_start = &GAS_mlp_bulk_start; env->sf.s_bulk_stop = &GAS_mlp_bulk_stop; /* Assign options to handle */ mlp->stats = (struct GNUNET_STATISTICS_Handle *) env->stats; mlp->addresses = env->addresses; mlp->bw_changed_cb = env->bandwidth_changed_cb; mlp->bw_changed_cb_cls = env->bw_changed_cb_cls; mlp->get_preferences = env->get_preferences; mlp->get_preferences_cls = env->get_preference_cls; mlp->get_properties = env->get_property; mlp->get_properties_cls = env->get_property_cls; /* Setting MLP Input variables */ mlp->pv.co_D = D; mlp->pv.co_R = R; mlp->pv.co_U = U; mlp->pv.b_min = b_min; mlp->pv.n_min = n_min; mlp->pv.m_q = GNUNET_ATS_QualityPropertiesCount; mlp->stat_mlp_prob_changed = GNUNET_NO; mlp->stat_mlp_prob_updated = GNUNET_NO; mlp->opt_mlp_auto_solve = GNUNET_YES; mlp->requested_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); mlp->stat_bulk_requests = 0; mlp->stat_bulk_lock = 0; /* Setup GLPK */ /* Redirect GLPK output to GNUnet logging */ glp_term_hook (&mlp_term_hook, (void *) mlp); /* Init LP solving parameters */ glp_init_smcp(&mlp->control_param_lp); mlp->control_param_lp.msg_lev = GLP_MSG_OFF; if (GNUNET_YES == mlp->opt_glpk_verbose) mlp->control_param_lp.msg_lev = GLP_MSG_ALL; mlp->control_param_lp.it_lim = max_iterations; mlp->control_param_lp.tm_lim = max_duration.rel_value_us / 1000LL; /* Init MLP solving parameters */ glp_init_iocp(&mlp->control_param_mlp); mlp->control_param_mlp.msg_lev = GLP_MSG_OFF; if (GNUNET_YES == mlp->opt_glpk_verbose) mlp->control_param_mlp.msg_lev = GLP_MSG_ALL; mlp->control_param_mlp.tm_lim = max_duration.rel_value_us / 1000LL; LOG (GNUNET_ERROR_TYPE_DEBUG, "solver ready\n"); return mlp; } /* end of plugin_ats_mlp.c */ gnunet-0.10.1/src/ats/gnunet-service-ats_normalization.c0000644000175000017500000006022512255010512020223 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_normalization.c * @brief ats service address: management of ATS properties and preferences normalization * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet-service-ats_addresses.h" #include "gnunet-service-ats_normalization.h" #define LOG(kind,...) GNUNET_log_from (kind, "ats-normalization",__VA_ARGS__) /** * Preference client */ struct PreferenceClient { /** * Next in DLL */ struct PreferenceClient *prev; /** * Next in DLL */ struct PreferenceClient *next; /** * Client handle */ void *client; /** * Total preference for this peer */ double f_abs_sum[GNUNET_ATS_PreferenceCount]; /** * List of peer preferences for this client */ /** * Head of peer list */ struct PreferencePeer *p_head; /** * Tail of peer list */ struct PreferencePeer *p_tail; }; /** * Preference peer */ struct PreferencePeer { /** * Next in DLL */ struct PreferencePeer *next; /** * Previous in DLL */ struct PreferencePeer *prev; /** * Client */ struct PreferenceClient *client; /** * Peer id */ struct GNUNET_PeerIdentity id; /** * Absolute preference values */ double f_abs[GNUNET_ATS_PreferenceCount]; /** * Relative preference values */ double f_rel[GNUNET_ATS_PreferenceCount]; struct GNUNET_TIME_Absolute next_aging[GNUNET_ATS_PreferenceCount]; }; /** * Relative preferences for a peer */ struct PeerRelative { /** * Relative preference values */ double f_rel[GNUNET_ATS_PreferenceCount]; /** * Peer id */ struct GNUNET_PeerIdentity id; }; /** * Callback to call on changing preference values */ static GAS_Normalization_preference_changed_cb pref_changed_cb; /** * Closure for callback to call on changing preference values */ static void *pref_changed_cb_cls; /** * Callback to call on changing property values */ GAS_Normalization_property_changed_cb prop_ch_cb; /** * Closure for callback to call on changing property values */ void *prop_ch_cb_cls; /** * Hashmap to store peer information for preference normalization */ static struct GNUNET_CONTAINER_MultiPeerMap *preference_peers; /** * Hashmap to store peer information for property normalization * FIXME: this map is not used! */ static struct GNUNET_CONTAINER_MultiPeerMap *property_peers; /** * Clients in DLL: head */ static struct PreferenceClient *pc_head; /** * Clients in DLL: tail */ static struct PreferenceClient *pc_tail; /** * Default values */ static struct PeerRelative defvalues; static GNUNET_SCHEDULER_TaskIdentifier aging_task; /** * Application Preference Normalization */ /** * Update a peer * @param id peer id * @param kind the kind * @return the new relative preference */ static double update_peers (struct GNUNET_PeerIdentity *id, enum GNUNET_ATS_PreferenceKind kind) { struct PreferenceClient *c_cur; struct PreferencePeer *p_cur; struct PeerRelative *rp; double f_rel_total; double backup; unsigned int count; f_rel_total = 0.0; count = 0; /* For all clients */ for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) { /* Find peer with id */ for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) { if (0 == memcmp (id, &p_cur->id, sizeof(struct GNUNET_PeerIdentity))) break; } if (NULL != p_cur) { /* Found peer with id */ f_rel_total += p_cur->f_rel[kind]; count++; } } /* Find a client */ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%u clients have a total relative preference for peer `%s''s `%s' of %.3f\n", count, GNUNET_i2s (id), GNUNET_ATS_print_preference_type (kind), f_rel_total); if (NULL != (rp = GNUNET_CONTAINER_multipeermap_get (preference_peers, id))) { backup = rp->f_rel[kind]; if (0 < count) { rp->f_rel[kind] = f_rel_total / count; } else { rp->f_rel[kind] = DEFAULT_REL_PREFERENCE; } } else { return DEFAULT_REL_PREFERENCE; } if ((backup != rp->f_rel[kind]) && (NULL != pref_changed_cb)) { pref_changed_cb (pref_changed_cb_cls, &rp->id, kind, rp->f_rel[kind]); } return rp->f_rel[kind]; } /** * Recalculate preference for a specific ATS property * * @param c the preference client * @param p the peer * @param kind the preference kind * @return the result */ static double recalculate_rel_preferences (struct PreferenceClient *c, struct PreferencePeer *p, enum GNUNET_ATS_PreferenceKind kind) { struct PreferencePeer *p_cur; struct PeerRelative *rp; double backup; double res; double ret; /* For this client: sum preferences to total preference */ c->f_abs_sum[kind] = 0; for (p_cur = c->p_head; NULL != p_cur; p_cur = p_cur->next) c->f_abs_sum[kind] += p_cur->f_abs[kind]; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Client %p has total preference for %s of %.3f\n", c->client, GNUNET_ATS_print_preference_type (kind), c->f_abs_sum[kind]); ret = DEFAULT_REL_PREFERENCE; /* For all peers: calculate relative preference */ for (p_cur = c->p_head; NULL != p_cur; p_cur = p_cur->next) { /* Calculate relative preference for specific kind */ backup = p_cur->f_rel[kind]; if (DEFAULT_ABS_PREFERENCE == c->f_abs_sum[kind]) /* No peer has a preference for this property, * so set default preference */ p_cur->f_rel[kind] = DEFAULT_REL_PREFERENCE; else p_cur->f_rel[kind] = (c->f_abs_sum[kind] + p_cur->f_abs[kind]) / c->f_abs_sum[kind]; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Client %p: peer `%s' has relative preference for %s of %.3f\n", c->client, GNUNET_i2s (&p_cur->id), GNUNET_ATS_print_preference_type (kind), p_cur->f_rel[kind]); if (p_cur->f_rel[kind] != backup) { /* Value changed, recalculate */ res = update_peers (&p_cur->id, kind); if (0 == memcmp (&p->id, &p_cur->id, sizeof(struct GNUNET_PeerIdentity))) ret = res; } else { /* Value did not chang, return old value*/ GNUNET_assert( NULL != (rp = GNUNET_CONTAINER_multipeermap_get (preference_peers, &p->id))); ret = rp->f_rel[kind]; } } return ret; } /** * Update the absolute preference value for a peer * @param c the client * @param p the peer * @param kind the preference kind * @param score_abs the absolute value * @return the new relative preference value */ static double update_preference (struct PreferenceClient *c, struct PreferencePeer *p, enum GNUNET_ATS_PreferenceKind kind, float score_abs) { double score = score_abs; /* Update preference value according to type */ switch (kind) { case GNUNET_ATS_PREFERENCE_BANDWIDTH: case GNUNET_ATS_PREFERENCE_LATENCY: p->f_abs[kind] = (p->f_abs[kind] + score) / 2; p->next_aging[kind] = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), PREF_AGING_INTERVAL); break; case GNUNET_ATS_PREFERENCE_END: break; default: break; } return recalculate_rel_preferences (c, p, kind); } /** * Reduce absolute preferences since they got old * * @param cls the PreferencePeer * @param tc context */ static void preference_aging (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PreferencePeer *p; struct PreferenceClient *cur_client; int i; int values_to_update; double backup; aging_task = GNUNET_SCHEDULER_NO_TASK; values_to_update = 0; cur_client = NULL; for (cur_client = pc_head; NULL != cur_client; cur_client = cur_client->next) { for (p = cur_client->p_head; NULL != p; p = p->next) { /* Aging absolute values: */ for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) { if (0 == GNUNET_TIME_absolute_get_remaining (p->next_aging[i]).rel_value_us) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Aging preference for peer `%s'\n", GNUNET_i2s (&p->id)); backup = p->f_abs[i]; if (p->f_abs[i] > DEFAULT_ABS_PREFERENCE) p->f_abs[i] *= PREF_AGING_FACTOR; if (p->f_abs[i] <= DEFAULT_ABS_PREFERENCE + PREF_EPSILON) p->f_abs[i] = DEFAULT_ABS_PREFERENCE; if ((p->f_abs[i] != DEFAULT_ABS_PREFERENCE) && (backup != p->f_abs[i])) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Aged preference for peer `%s' from %.3f to %.3f\n", GNUNET_i2s (&p->id), backup, p->f_abs[i]); recalculate_rel_preferences (p->client, p, i); p->next_aging[i] = GNUNET_TIME_absolute_add ( GNUNET_TIME_absolute_get (), PREF_AGING_INTERVAL); values_to_update++; } } } } } if (values_to_update > 0) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Rescheduling aging task due to %u elements to age\n", values_to_update); aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL, &preference_aging, NULL ); } else GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No values to age left, not rescheduling aging task\n"); } /** * Normalize an updated preference value * * @param src the client with this preference * @param peer the peer to change the preference for * @param kind the kind to change the preference * @param score_abs the normalized score */ void GAS_normalization_normalize_preference (void *src, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, float score_abs) { struct PreferenceClient *c_cur; struct PreferencePeer *p_cur; struct PeerRelative *r_cur; int i; GNUNET_assert(NULL != src); GNUNET_assert(NULL != peer); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Client %p changes preference for peer `%s' for `%s' to %.2f\n", src, GNUNET_i2s (peer), GNUNET_ATS_print_preference_type (kind), score_abs); if (kind >= GNUNET_ATS_PreferenceCount) { GNUNET_break(0); return; } /* Find preference client */ for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) { if (src == c_cur->client) break; } /* Not found: create new preference client */ if (NULL == c_cur) { c_cur = GNUNET_new (struct PreferenceClient); c_cur->client = src; GNUNET_CONTAINER_DLL_insert(pc_head, pc_tail, c_cur); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Adding new client %p \n", c_cur); } /* Find entry for peer */ for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) if (0 == memcmp (&p_cur->id, peer, sizeof(p_cur->id))) break; /* Not found: create new peer entry */ if (NULL == p_cur) { p_cur = GNUNET_new (struct PreferencePeer); p_cur->client = c_cur; p_cur->id = (*peer); for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) { /* Default value per peer absolut preference for a quality: * No value set, so absolute preference 0 */ p_cur->f_abs[i] = DEFAULT_ABS_PREFERENCE; /* Default value per peer relative preference for a quality: 1.0 */ p_cur->f_rel[i] = DEFAULT_REL_PREFERENCE; p_cur->next_aging[i] = GNUNET_TIME_UNIT_FOREVER_ABS; } GNUNET_CONTAINER_DLL_insert(c_cur->p_head, c_cur->p_tail, p_cur); } if (NULL == GNUNET_CONTAINER_multipeermap_get (preference_peers, peer)) { r_cur = GNUNET_new (struct PeerRelative); r_cur->id = (*peer); for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) r_cur->f_rel[i] = DEFAULT_REL_PREFERENCE; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (preference_peers, &r_cur->id, r_cur, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } if (GNUNET_SCHEDULER_NO_TASK == aging_task) aging_task = GNUNET_SCHEDULER_add_delayed (PREF_AGING_INTERVAL, &preference_aging, NULL ); update_preference (c_cur, p_cur, kind, score_abs); } /** * Get the normalized preference values for a specific peer or * the default values if * * @param id the peer * @return pointer to the values, can be indexed with GNUNET_ATS_PreferenceKind, * default preferences if peer does not exist */ const double * GAS_normalization_get_preferences_by_peer (const struct GNUNET_PeerIdentity *id) { GNUNET_assert(NULL != preference_peers); GNUNET_assert(NULL != id); struct PeerRelative *rp; if (NULL == (rp = GNUNET_CONTAINER_multipeermap_get (preference_peers, id))) { return defvalues.f_rel; } return rp->f_rel; } /** * Get the normalized preference values for a specific client and peer * * @param client client * @param peer the peer * @param pref the preference type * @return the value */ const double GAS_normalization_get_preferences_by_client (const void *client, struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind pref) { struct PreferenceClient *c_cur; struct PreferencePeer *p_cur; /* Find preference client */ for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) { if (client == c_cur->client) break; } if (NULL == c_cur) return -1.0; for (p_cur = c_cur->p_head; NULL != p_cur; p_cur = p_cur->next) { if (0 == memcmp (peer, &p_cur->id, sizeof (struct GNUNET_PeerIdentity))) break; } if (NULL == p_cur) return DEFAULT_REL_PREFERENCE; /* Not found, return default */ return p_cur->f_rel[pref]; } /** * Get the normalized properties values for a specific peer or * the default values if * * @param address the address * @return pointer to the values, can be indexed with GNUNET_ATS_PreferenceKind, * default preferences if peer does not exist */ const double * GAS_normalization_get_properties (struct ATS_Address *address) { static double norm_values[GNUNET_ATS_QualityPropertiesCount]; int i; GNUNET_assert(NULL != address); for (i = 0; i < GNUNET_ATS_QualityPropertiesCount; i++) { if ((address->atsin[i].norm >= 1.0) && (address->atsin[i].norm <= 2.0)) norm_values[i] = address->atsin[i].norm; else norm_values[i] = DEFAULT_REL_QUALITY; } return norm_values; } /** * Quality Normalization */ struct Property { uint32_t prop_type; uint32_t atsi_type; uint32_t min; uint32_t max; }; struct Property properties[GNUNET_ATS_QualityPropertiesCount]; /** * Normalize a specific ATS type with the values in queue * @param address the address * @param atsi the ats information * @return the new average or GNUNET_ATS_VALUE_UNDEFINED */ uint32_t property_average (struct ATS_Address *address, const struct GNUNET_ATS_Information *atsi) { struct GAS_NormalizationInfo *ni; uint32_t current_type; uint32_t current_val; uint32_t res; uint64_t sum; uint32_t count; unsigned int c1; unsigned int index; unsigned int props[] = GNUNET_ATS_QualityProperties; /* Average the values of this property */ current_type = ntohl (atsi->type); current_val = ntohl (atsi->value); for (c1 = 0; c1 < GNUNET_ATS_QualityPropertiesCount; c1++) { if (current_type == props[c1]) break; } if (c1 == GNUNET_ATS_QualityPropertiesCount) { GNUNET_break(0); return GNUNET_ATS_VALUE_UNDEFINED; } index = c1; ni = &address->atsin[index]; ni->atsi_abs[ni->avg_queue_index] = current_val; ni->avg_queue_index++; if (GAS_normalization_queue_length == ni->avg_queue_index) ni->avg_queue_index = 0; count = 0; sum = 0; for (c1 = 0; c1 < GAS_normalization_queue_length; c1++) { if (GNUNET_ATS_VALUE_UNDEFINED != ni->atsi_abs[c1]) { count++; if (GNUNET_ATS_VALUE_UNDEFINED > (sum + ni->atsi_abs[c1])) sum += ni->atsi_abs[c1]; else { sum = GNUNET_ATS_VALUE_UNDEFINED - 1; GNUNET_break(0); } } } GNUNET_assert(0 != count); res = sum / count; LOG(GNUNET_ERROR_TYPE_DEBUG, "New average of `%s' created by adding %u from %u elements: %u\n", GNUNET_ATS_print_property_type (current_type), current_val, count, res, sum); ni->avg = res; return res; } struct FindMinMaxCtx { struct Property *p; uint32_t min; uint32_t max; }; static int find_min_max_it (void *cls, const struct GNUNET_PeerIdentity *h, void *k) { struct FindMinMaxCtx *find_res = cls; struct ATS_Address *a = k; if (a->atsin[find_res->p->prop_type].avg > find_res->max) find_res->max = a->atsin[find_res->p->prop_type].avg; if (a->atsin[find_res->p->prop_type].avg < find_res->min) find_res->min = a->atsin[find_res->p->prop_type].avg; return GNUNET_OK; } static int normalize_address (void *cls, const struct GNUNET_PeerIdentity *h, void *k) { struct Property *p = cls; struct ATS_Address *address = k; double delta; uint32_t avg_value = address->atsin[p->prop_type].avg; delta = p->max - p->min; address->atsin[p->prop_type].norm = (delta + (avg_value - p->min)) / (delta); LOG(GNUNET_ERROR_TYPE_DEBUG, "Normalize `%s' address %p's '%s' with value %u to range [%u..%u] = %.3f\n", GNUNET_i2s (&address->peer), address, GNUNET_ATS_print_property_type (p->atsi_type), address->atsin[p->prop_type].avg, p->min, p->max, address->atsin[p->prop_type].norm); if (NULL != prop_ch_cb) prop_ch_cb (prop_ch_cb_cls, address, p->atsi_type, address->atsin[p->prop_type].norm); return GNUNET_OK; } /** * Normalize avg_value to a range of values between [1.0, 2.0] * based on min max values currently known. * * @param addresses the address hashmap * @param p the property * @param address the address * @param avg_value the value to normalize */ static void property_normalize (struct GNUNET_CONTAINER_MultiPeerMap *addresses, struct Property *p, struct ATS_Address *address, uint32_t avg_value) { struct FindMinMaxCtx find_ctx; int addr_count; int limits_changed; find_ctx.p = p; find_ctx.max = 0; find_ctx.min = UINT32_MAX; addr_count = GNUNET_CONTAINER_multipeermap_iterate (addresses, &find_min_max_it, &find_ctx); if (0 == addr_count) { GNUNET_break(0); return; } limits_changed = GNUNET_NO; if (find_ctx.max != p->max) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Normalizing %s: new maximum %u -> recalculate all values\n", GNUNET_ATS_print_property_type (p->atsi_type), find_ctx.max); p->max = find_ctx.max; limits_changed = GNUNET_YES; } if ((find_ctx.min != p->min) && (find_ctx.min < p->max)) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Normalizing %s: new minimum %u -> recalculate all values\n", GNUNET_ATS_print_property_type (p->atsi_type), find_ctx.min, find_ctx.max); p->min = find_ctx.min; limits_changed = GNUNET_YES; } else if (find_ctx.min == p->max) { /* Only one value, so minimum has to be 0 */ p->min = 0; } /* Normalize the values of this property */ if (GNUNET_NO == limits_changed) { /* normalize just this address */ normalize_address (p, &address->peer, address); return; } else { /* limits changed, normalize all addresses */ GNUNET_CONTAINER_multipeermap_iterate (addresses, &normalize_address, p); return; } } /** * Update and normalize atsi performance information * * @param addresses hashmap containing all addresses * @param address the address to update * @param atsi the array of performance information * @param atsi_count the number of atsi information in the array */ void GAS_normalization_normalize_property ( struct GNUNET_CONTAINER_MultiPeerMap *addresses, struct ATS_Address *address, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { struct Property *cur_prop; int c1; int c2; uint32_t current_type; uint32_t current_val; unsigned int existing_properties[] = GNUNET_ATS_QualityProperties; GNUNET_assert(NULL != address); GNUNET_assert(NULL != atsi); LOG(GNUNET_ERROR_TYPE_DEBUG, "Updating %u elements for peer `%s'\n", atsi_count, GNUNET_i2s (&address->peer)); for (c1 = 0; c1 < atsi_count; c1++) { current_type = ntohl (atsi[c1].type); for (c2 = 0; c2 < GNUNET_ATS_QualityPropertiesCount; c2++) { /* Check if type is valid */ if (current_type == existing_properties[c2]) break; } if (GNUNET_ATS_QualityPropertiesCount == c2) { /* Invalid property, continue with next element */ continue; } /* Averaging */ current_val = property_average (address, &atsi[c1]); if (GNUNET_ATS_VALUE_UNDEFINED == current_val) { GNUNET_break(0); continue; } /* Normalizing */ /* Check min, max */ cur_prop = &properties[c2]; property_normalize (addresses, cur_prop, address, current_val); } } static void free_client (struct PreferenceClient *pc) { struct PreferencePeer *next_p; struct PreferencePeer *p; next_p = pc->p_head; while (NULL != (p = next_p)) { next_p = p->next; GNUNET_CONTAINER_DLL_remove(pc->p_head, pc->p_tail, p); GNUNET_free(p); } GNUNET_free(pc); } /** * A performance client disconnected * * @param client the client */ void GAS_normalization_preference_client_disconnect (void *client) { struct PreferenceClient *c_cur; /* Find preference client */ for (c_cur = pc_head; NULL != c_cur; c_cur = c_cur->next) { if (client == c_cur->client) break; } if (NULL == c_cur) return; GNUNET_CONTAINER_DLL_remove(pc_head, pc_tail, c_cur); free_client (c_cur); } /** * Start the normalization component * * @param pref_ch_cb callback to call on relative preference changing * @param pref_ch_cb_cls cls for the preference callback * @param property_ch_cb callback to call on relative property changing * @param property_ch_cb_cls cls for the property callback */ void GAS_normalization_start (GAS_Normalization_preference_changed_cb pref_ch_cb, void *pref_ch_cb_cls, GAS_Normalization_property_changed_cb property_ch_cb, void *property_ch_cb_cls) { int c1; int i; preference_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); property_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); unsigned int existing_properties[] = GNUNET_ATS_QualityProperties; for (c1 = 0; c1 < GNUNET_ATS_QualityPropertiesCount; c1++) { properties[c1].prop_type = c1; properties[c1].atsi_type = existing_properties[c1]; properties[c1].min = 0; properties[c1].max = 0; } pref_changed_cb = pref_ch_cb; pref_changed_cb_cls = pref_ch_cb_cls; prop_ch_cb = property_ch_cb; prop_ch_cb_cls = pref_ch_cb_cls; pc_head = NULL; pc_tail = NULL; for (i = 0; i < GNUNET_ATS_PreferenceCount; i++) defvalues.f_rel[i] = DEFAULT_REL_PREFERENCE; aging_task = GNUNET_SCHEDULER_NO_TASK; return; } /** * Free a peer * * @param cls unused * @param key the key * @param value RelativePeer * @return #GNUNET_OK to continue */ static int free_peer (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct PeerRelative *rp = value; if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (preference_peers, key, value)) GNUNET_free(rp); else GNUNET_break(0); return GNUNET_OK; } /** * Stop the normalization component and free all items */ void GAS_normalization_stop () { struct PreferenceClient *pc; struct PreferenceClient *next_pc; if (GNUNET_SCHEDULER_NO_TASK != aging_task) { GNUNET_SCHEDULER_cancel (aging_task); aging_task = GNUNET_SCHEDULER_NO_TASK; } next_pc = pc_head; while (NULL != (pc = next_pc)) { next_pc = pc->next; GNUNET_CONTAINER_DLL_remove(pc_head, pc_tail, pc); free_client (pc); } GNUNET_CONTAINER_multipeermap_iterate (preference_peers, &free_peer, NULL ); GNUNET_CONTAINER_multipeermap_destroy (preference_peers); GNUNET_CONTAINER_multipeermap_destroy (property_peers); return; } /* end of gnunet-service-ats_normalization.c */ gnunet-0.10.1/src/ats/gnunet-service-ats_performance.h0000644000175000017500000001251612225777503017664 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_performance.h * @brief ats service, interaction with 'performance' API * @author Matthias Wachs * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_ATS_PERFORMANCE_H #define GNUNET_SERVICE_ATS_PERFORMANCE_H #include "gnunet_util_lib.h" #include "gnunet_ats_service.h" #include "ats.h" /** * Register a new performance client. * * @param client handle of the new client * @param flag flag specifying the type of the client */ void GAS_performance_add_client (struct GNUNET_SERVER_Client *client, enum StartFlag flag); /** * Unregister a client (which may have been a performance client, * but this is not assured). * * @param client handle of the (now dead) client */ void GAS_performance_remove_client (struct GNUNET_SERVER_Client *client); void GAS_handle_performance_update (struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, const int active, struct GNUNET_ATS_Information *ats, uint32_t ats_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in); /** * Transmit the given performance information to all performance * clients. * * @param peer peer for which this is an address suggestion * @param plugin_name 0-termintated string specifying the transport plugin * @param plugin_addr binary address for the plugin to use * @param plugin_addr_len number of bytes in plugin_addr * @param active is this address active * @param atsi performance data for the address * @param atsi_count number of performance records in 'ats' * @param bandwidth_out assigned outbound bandwidth * @param bandwidth_in assigned inbound bandwidth */ void GAS_performance_notify_all_clients (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, const int active, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in); /** * Handle 'address list request' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_request_address_list (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle 'reservation request' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_reservation_request (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle 'preference change' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_preference_change (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle 'preference feedback' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_preference_feedback (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); void GAS_handle_monitor (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Initialize performance subsystem. * * @param server handle to our server * @param addresses the address handle to use */ void GAS_performance_init (struct GNUNET_SERVER_Handle *server, struct GAS_Addresses_Handle *GSA_addresses); /** * Shutdown performance subsystem. */ void GAS_performance_done (void); /* FIXME: add API to broadcast performance updates! */ #endif /* end of gnunet-service-ats_performance.h */ gnunet-0.10.1/src/ats/perf_ats_solver_mlp.conf0000644000175000017500000000000012233724131016270 00000000000000gnunet-0.10.1/src/ats/perf_ats_solver_ril.conf0000644000175000017500000000000012233724131016266 00000000000000gnunet-0.10.1/src/ats/perf_ats_solver_proportional.conf0000644000175000017500000000000012233724131020230 00000000000000gnunet-0.10.1/src/ats/test_ats_api_scheduling_add_address_inbound.c0000644000175000017500000001401112263724143022454 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_scheduling_add_address.c * @brief adding addresses with scheduling API * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ //static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (1 == value) { GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &end, NULL); } if (1 < value) { GNUNET_SCHEDULER_add_now (&end_badly, NULL); } return GNUNET_OK; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void got_initial_value (void *cls, int success) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got initial value\n"); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ create_test_address (&test_addr, "test-plugin", NULL, NULL, 0); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = NULL; test_hello_address.address_length = 0; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, NULL, test_ats_info, test_ats_count); GNUNET_ATS_address_add (sched_ats, &test_hello_address, NULL, test_ats_info, test_ats_count); } static int dummy_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got dummy stat %s%s:%s = %llu\n", is_persistent ? "!" : " ", subsystem, name, value); return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); GNUNET_STATISTICS_get (stats, "ats", "# addresses", TIMEOUT, &got_initial_value, &dummy_stat, GNUNET_CONFIGURATION_dup (cfg)); } int main (int argc, char *argv[]) { ret = 0; if (0 != GNUNET_TESTING_peer_run ("test-ats-api", "test_ats_api.conf", &run, NULL)) return 1; return ret; } /* end of file test_ats_api_scheduling_add_address.c */ gnunet-0.10.1/src/ats/test_ats_solver_proportional.conf0000644000175000017500000000062312225230043020261 00000000000000@INLINE@ test_ats_solver_default.conf [ats] #PREFIX = valgrind --leak-check=yes MODE = PROPORTIONAL # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 64 KiB UNSPECIFIED_QUOTA_OUT = 64 KiB # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited # LAN LAN_QUOTA_IN = unlimited LAN_QUOTA_OUT = unlimited # WAN WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB # WLAN WLAN_QUOTA_IN = 512 WLAN_QUOTA_OUT = 512gnunet-0.10.1/src/ats/Makefile.in0000644000175000017500000036463112320752060013447 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ noinst_PROGRAMS = gnunet-ats-solver-eval$(EXEEXT) libexec_PROGRAMS = gnunet-service-ats$(EXEEXT) check_PROGRAMS = $(am__EXEEXT_8) subdir = src/ats DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/ats.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = ats.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__libgnunet_plugin_ats_mlp_la_SOURCES_DIST = plugin_ats_mlp.c @HAVE_LIBGLPK_TRUE@am_libgnunet_plugin_ats_mlp_la_OBJECTS = \ @HAVE_LIBGLPK_TRUE@ plugin_ats_mlp.lo libgnunet_plugin_ats_mlp_la_OBJECTS = \ $(am_libgnunet_plugin_ats_mlp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_ats_mlp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunet_plugin_ats_mlp_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_LIBGLPK_TRUE@am_libgnunet_plugin_ats_mlp_la_rpath = -rpath \ @HAVE_LIBGLPK_TRUE@ $(plugindir) am__DEPENDENCIES_1 = am_libgnunet_plugin_ats_proportional_la_OBJECTS = \ plugin_ats_proportional.lo libgnunet_plugin_ats_proportional_la_OBJECTS = \ $(am_libgnunet_plugin_ats_proportional_la_OBJECTS) libgnunet_plugin_ats_proportional_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_ats_proportional_la_LDFLAGS) $(LDFLAGS) -o \ $@ am_libgnunet_plugin_ats_ril_la_OBJECTS = plugin_ats_ril.lo libgnunet_plugin_ats_ril_la_OBJECTS = \ $(am_libgnunet_plugin_ats_ril_la_OBJECTS) libgnunet_plugin_ats_ril_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunet_plugin_ats_ril_la_LDFLAGS) \ $(LDFLAGS) -o $@ libgnunetats_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetats_la_OBJECTS = ats_api_scheduling.lo \ ats_api_performance.lo libgnunetats_la_OBJECTS = $(am_libgnunetats_la_OBJECTS) libgnunetats_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetats_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_LIBGLPK_TRUE@am__EXEEXT_1 = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_add_address_mlp$(EXEEXT) @HAVE_LIBGLPK_TRUE@am__EXEEXT_2 = test_ats_solver_add_address_and_request_mlp$(EXEEXT) @HAVE_LIBGLPK_TRUE@am__EXEEXT_3 = test_ats_solver_request_and_add_address_mlp$(EXEEXT) @HAVE_LIBGLPK_TRUE@am__EXEEXT_4 = test_ats_solver_request_and_delete_address_mlp$(EXEEXT) @HAVE_LIBGLPK_TRUE@am__EXEEXT_5 = test_ats_solver_alternative_after_delete_address_mlp$(EXEEXT) @HAVE_LIBGLPK_TRUE@am__EXEEXT_6 = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_preferences_mlp$(EXEEXT) @HAVE_LIBGLPK_TRUE@am__EXEEXT_7 = perf_ats_solver_mlp$(EXEEXT) @HAVE_TESTING_TRUE@am__EXEEXT_8 = \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_init$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_add_address$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_add_address_duplicate$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_add_address_inbound$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_destroy_address$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_destroy_address_twice$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_add_session$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_destroy_session$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_performance_list_all_addresses$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_performance_list_peer_addresses$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_performance_list_all_addresses_active$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_performance_monitor$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_api_performance_monitor_initial_callback$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_add_address_proportional$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_add_address_and_request_proportional$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_request_and_add_address_proportional$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_request_and_delete_address_proportional$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_alternative_after_delete_address_proportional$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_preferences_proportional$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_preferences_ril$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_1) $(am__EXEEXT_2) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_3) $(am__EXEEXT_4) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_5) $(am__EXEEXT_6) \ @HAVE_TESTING_TRUE@ test_ats_solver_add_address_ril$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_add_address_and_request_ril$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_request_and_add_address_ril$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_request_and_delete_address_ril$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_ats_solver_alternative_after_delete_address_ril$(EXEEXT) \ @HAVE_TESTING_TRUE@ perf_ats_solver_proportional$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_7) \ @HAVE_TESTING_TRUE@ perf_ats_solver_ril$(EXEEXT) PROGRAMS = $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_ats_solver_eval_OBJECTS = gnunet-ats-solver-eval.$(OBJEXT) \ gnunet-service-ats_normalization.$(OBJEXT) gnunet_ats_solver_eval_OBJECTS = $(am_gnunet_ats_solver_eval_OBJECTS) am_gnunet_service_ats_OBJECTS = gnunet-service-ats.$(OBJEXT) \ gnunet-service-ats_addresses.$(OBJEXT) \ gnunet-service-ats_normalization.$(OBJEXT) \ gnunet-service-ats_performance.$(OBJEXT) \ gnunet-service-ats_scheduling.$(OBJEXT) \ gnunet-service-ats_reservations.$(OBJEXT) gnunet_service_ats_OBJECTS = $(am_gnunet_service_ats_OBJECTS) am_perf_ats_solver_mlp_OBJECTS = perf_ats_solver.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) \ gnunet-service-ats_normalization.$(OBJEXT) perf_ats_solver_mlp_OBJECTS = $(am_perf_ats_solver_mlp_OBJECTS) perf_ats_solver_mlp_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la am_perf_ats_solver_proportional_OBJECTS = perf_ats_solver.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) \ gnunet-service-ats_normalization.$(OBJEXT) perf_ats_solver_proportional_OBJECTS = \ $(am_perf_ats_solver_proportional_OBJECTS) perf_ats_solver_proportional_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la am_perf_ats_solver_ril_OBJECTS = perf_ats_solver.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) \ gnunet-service-ats_normalization.$(OBJEXT) perf_ats_solver_ril_OBJECTS = $(am_perf_ats_solver_ril_OBJECTS) perf_ats_solver_ril_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la am_test_ats_api_performance_list_all_addresses_OBJECTS = \ test_ats_api_performance_list_all_addresses.$(OBJEXT) test_ats_api_performance_list_all_addresses_OBJECTS = \ $(am_test_ats_api_performance_list_all_addresses_OBJECTS) test_ats_api_performance_list_all_addresses_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_performance_list_all_addresses_active_OBJECTS = \ test_ats_api_performance_list_all_addresses_active.$(OBJEXT) test_ats_api_performance_list_all_addresses_active_OBJECTS = $(am_test_ats_api_performance_list_all_addresses_active_OBJECTS) test_ats_api_performance_list_all_addresses_active_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_performance_list_peer_addresses_OBJECTS = \ test_ats_api_performance_list_peer_addresses.$(OBJEXT) test_ats_api_performance_list_peer_addresses_OBJECTS = \ $(am_test_ats_api_performance_list_peer_addresses_OBJECTS) test_ats_api_performance_list_peer_addresses_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_performance_monitor_OBJECTS = \ test_ats_api_performance_monitor.$(OBJEXT) test_ats_api_performance_monitor_OBJECTS = \ $(am_test_ats_api_performance_monitor_OBJECTS) test_ats_api_performance_monitor_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_performance_monitor_initial_callback_OBJECTS = \ test_ats_api_performance_monitor_initial_callback.$(OBJEXT) test_ats_api_performance_monitor_initial_callback_OBJECTS = $(am_test_ats_api_performance_monitor_initial_callback_OBJECTS) test_ats_api_performance_monitor_initial_callback_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_scheduling_add_address_OBJECTS = \ test_ats_api_scheduling_add_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_api_scheduling_add_address_OBJECTS = \ $(am_test_ats_api_scheduling_add_address_OBJECTS) test_ats_api_scheduling_add_address_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_scheduling_add_address_duplicate_OBJECTS = \ test_ats_api_scheduling_add_address_duplicate.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_api_scheduling_add_address_duplicate_OBJECTS = \ $(am_test_ats_api_scheduling_add_address_duplicate_OBJECTS) test_ats_api_scheduling_add_address_duplicate_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_scheduling_add_address_inbound_OBJECTS = \ test_ats_api_scheduling_add_address_inbound.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_api_scheduling_add_address_inbound_OBJECTS = \ $(am_test_ats_api_scheduling_add_address_inbound_OBJECTS) test_ats_api_scheduling_add_address_inbound_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_scheduling_add_session_OBJECTS = \ test_ats_api_scheduling_add_session.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_api_scheduling_add_session_OBJECTS = \ $(am_test_ats_api_scheduling_add_session_OBJECTS) test_ats_api_scheduling_add_session_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_scheduling_destroy_address_OBJECTS = \ test_ats_api_scheduling_destroy_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_api_scheduling_destroy_address_OBJECTS = \ $(am_test_ats_api_scheduling_destroy_address_OBJECTS) test_ats_api_scheduling_destroy_address_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_scheduling_destroy_address_twice_OBJECTS = \ test_ats_api_scheduling_destroy_address_twice.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_api_scheduling_destroy_address_twice_OBJECTS = \ $(am_test_ats_api_scheduling_destroy_address_twice_OBJECTS) test_ats_api_scheduling_destroy_address_twice_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_scheduling_destroy_session_OBJECTS = \ test_ats_api_scheduling_destroy_session.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_api_scheduling_destroy_session_OBJECTS = \ $(am_test_ats_api_scheduling_destroy_session_OBJECTS) test_ats_api_scheduling_destroy_session_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_api_scheduling_init_OBJECTS = \ test_ats_api_scheduling_init.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_api_scheduling_init_OBJECTS = \ $(am_test_ats_api_scheduling_init_OBJECTS) test_ats_api_scheduling_init_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am__test_ats_solver_add_address_and_request_mlp_SOURCES_DIST = \ test_ats_solver_add_address_and_request.c \ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@am_test_ats_solver_add_address_and_request_mlp_OBJECTS = test_ats_solver_add_address_and_request.$(OBJEXT) \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.$(OBJEXT) test_ats_solver_add_address_and_request_mlp_OBJECTS = \ $(am_test_ats_solver_add_address_and_request_mlp_OBJECTS) @HAVE_LIBGLPK_TRUE@test_ats_solver_add_address_and_request_mlp_DEPENDENCIES = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_add_address_and_request_proportional_OBJECTS = \ test_ats_solver_add_address_and_request.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_add_address_and_request_proportional_OBJECTS = $(am_test_ats_solver_add_address_and_request_proportional_OBJECTS) test_ats_solver_add_address_and_request_proportional_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_add_address_and_request_ril_OBJECTS = \ test_ats_solver_add_address_and_request.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_add_address_and_request_ril_OBJECTS = \ $(am_test_ats_solver_add_address_and_request_ril_OBJECTS) test_ats_solver_add_address_and_request_ril_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am__test_ats_solver_add_address_mlp_SOURCES_DIST = \ test_ats_solver_add_address.c test_ats_api_common.c \ test_ats_api_common.h @HAVE_LIBGLPK_TRUE@am_test_ats_solver_add_address_mlp_OBJECTS = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_add_address.$(OBJEXT) \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.$(OBJEXT) test_ats_solver_add_address_mlp_OBJECTS = \ $(am_test_ats_solver_add_address_mlp_OBJECTS) @HAVE_LIBGLPK_TRUE@test_ats_solver_add_address_mlp_DEPENDENCIES = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_add_address_proportional_OBJECTS = \ test_ats_solver_add_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_add_address_proportional_OBJECTS = \ $(am_test_ats_solver_add_address_proportional_OBJECTS) test_ats_solver_add_address_proportional_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_add_address_ril_OBJECTS = \ test_ats_solver_add_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_add_address_ril_OBJECTS = \ $(am_test_ats_solver_add_address_ril_OBJECTS) test_ats_solver_add_address_ril_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am__test_ats_solver_alternative_after_delete_address_mlp_SOURCES_DIST = \ test_ats_solver_alternative_after_delete_address.c \ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@am_test_ats_solver_alternative_after_delete_address_mlp_OBJECTS = test_ats_solver_alternative_after_delete_address.$(OBJEXT) \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.$(OBJEXT) test_ats_solver_alternative_after_delete_address_mlp_OBJECTS = $(am_test_ats_solver_alternative_after_delete_address_mlp_OBJECTS) @HAVE_LIBGLPK_TRUE@test_ats_solver_alternative_after_delete_address_mlp_DEPENDENCIES = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_alternative_after_delete_address_proportional_OBJECTS = \ test_ats_solver_alternative_after_delete_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_alternative_after_delete_address_proportional_OBJECTS = $(am_test_ats_solver_alternative_after_delete_address_proportional_OBJECTS) test_ats_solver_alternative_after_delete_address_proportional_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_alternative_after_delete_address_ril_OBJECTS = \ test_ats_solver_alternative_after_delete_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_alternative_after_delete_address_ril_OBJECTS = $(am_test_ats_solver_alternative_after_delete_address_ril_OBJECTS) test_ats_solver_alternative_after_delete_address_ril_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am__test_ats_solver_preferences_mlp_SOURCES_DIST = \ test_ats_solver_preferences.c test_ats_api_common.c \ test_ats_api_common.h @HAVE_LIBGLPK_TRUE@am_test_ats_solver_preferences_mlp_OBJECTS = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_preferences.$(OBJEXT) \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.$(OBJEXT) test_ats_solver_preferences_mlp_OBJECTS = \ $(am_test_ats_solver_preferences_mlp_OBJECTS) @HAVE_LIBGLPK_TRUE@test_ats_solver_preferences_mlp_DEPENDENCIES = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_preferences_proportional_OBJECTS = \ test_ats_solver_preferences.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_preferences_proportional_OBJECTS = \ $(am_test_ats_solver_preferences_proportional_OBJECTS) test_ats_solver_preferences_proportional_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_preferences_ril_OBJECTS = \ test_ats_solver_preferences.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_preferences_ril_OBJECTS = \ $(am_test_ats_solver_preferences_ril_OBJECTS) test_ats_solver_preferences_ril_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am__test_ats_solver_request_and_add_address_mlp_SOURCES_DIST = \ test_ats_solver_request_and_add_address.c \ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@am_test_ats_solver_request_and_add_address_mlp_OBJECTS = test_ats_solver_request_and_add_address.$(OBJEXT) \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.$(OBJEXT) test_ats_solver_request_and_add_address_mlp_OBJECTS = \ $(am_test_ats_solver_request_and_add_address_mlp_OBJECTS) @HAVE_LIBGLPK_TRUE@test_ats_solver_request_and_add_address_mlp_DEPENDENCIES = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_request_and_add_address_proportional_OBJECTS = \ test_ats_solver_request_and_add_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_request_and_add_address_proportional_OBJECTS = $(am_test_ats_solver_request_and_add_address_proportional_OBJECTS) test_ats_solver_request_and_add_address_proportional_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_request_and_add_address_ril_OBJECTS = \ test_ats_solver_request_and_add_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_request_and_add_address_ril_OBJECTS = \ $(am_test_ats_solver_request_and_add_address_ril_OBJECTS) test_ats_solver_request_and_add_address_ril_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am__test_ats_solver_request_and_delete_address_mlp_SOURCES_DIST = \ test_ats_solver_request_and_delete_address.c \ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@am_test_ats_solver_request_and_delete_address_mlp_OBJECTS = test_ats_solver_request_and_delete_address.$(OBJEXT) \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.$(OBJEXT) test_ats_solver_request_and_delete_address_mlp_OBJECTS = \ $(am_test_ats_solver_request_and_delete_address_mlp_OBJECTS) @HAVE_LIBGLPK_TRUE@test_ats_solver_request_and_delete_address_mlp_DEPENDENCIES = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_request_and_delete_address_proportional_OBJECTS = \ test_ats_solver_request_and_delete_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_request_and_delete_address_proportional_OBJECTS = $(am_test_ats_solver_request_and_delete_address_proportional_OBJECTS) test_ats_solver_request_and_delete_address_proportional_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_ats_solver_request_and_delete_address_ril_OBJECTS = \ test_ats_solver_request_and_delete_address.$(OBJEXT) \ test_ats_api_common.$(OBJEXT) test_ats_solver_request_and_delete_address_ril_OBJECTS = \ $(am_test_ats_solver_request_and_delete_address_ril_OBJECTS) test_ats_solver_request_and_delete_address_ril_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_ats_mlp_la_SOURCES) \ $(libgnunet_plugin_ats_proportional_la_SOURCES) \ $(libgnunet_plugin_ats_ril_la_SOURCES) \ $(libgnunetats_la_SOURCES) $(gnunet_ats_solver_eval_SOURCES) \ $(gnunet_service_ats_SOURCES) $(perf_ats_solver_mlp_SOURCES) \ $(perf_ats_solver_proportional_SOURCES) \ $(perf_ats_solver_ril_SOURCES) \ $(test_ats_api_performance_list_all_addresses_SOURCES) \ $(test_ats_api_performance_list_all_addresses_active_SOURCES) \ $(test_ats_api_performance_list_peer_addresses_SOURCES) \ $(test_ats_api_performance_monitor_SOURCES) \ $(test_ats_api_performance_monitor_initial_callback_SOURCES) \ $(test_ats_api_scheduling_add_address_SOURCES) \ $(test_ats_api_scheduling_add_address_duplicate_SOURCES) \ $(test_ats_api_scheduling_add_address_inbound_SOURCES) \ $(test_ats_api_scheduling_add_session_SOURCES) \ $(test_ats_api_scheduling_destroy_address_SOURCES) \ $(test_ats_api_scheduling_destroy_address_twice_SOURCES) \ $(test_ats_api_scheduling_destroy_session_SOURCES) \ $(test_ats_api_scheduling_init_SOURCES) \ $(test_ats_solver_add_address_and_request_mlp_SOURCES) \ $(test_ats_solver_add_address_and_request_proportional_SOURCES) \ $(test_ats_solver_add_address_and_request_ril_SOURCES) \ $(test_ats_solver_add_address_mlp_SOURCES) \ $(test_ats_solver_add_address_proportional_SOURCES) \ $(test_ats_solver_add_address_ril_SOURCES) \ $(test_ats_solver_alternative_after_delete_address_mlp_SOURCES) \ $(test_ats_solver_alternative_after_delete_address_proportional_SOURCES) \ $(test_ats_solver_alternative_after_delete_address_ril_SOURCES) \ $(test_ats_solver_preferences_mlp_SOURCES) \ $(test_ats_solver_preferences_proportional_SOURCES) \ $(test_ats_solver_preferences_ril_SOURCES) \ $(test_ats_solver_request_and_add_address_mlp_SOURCES) \ $(test_ats_solver_request_and_add_address_proportional_SOURCES) \ $(test_ats_solver_request_and_add_address_ril_SOURCES) \ $(test_ats_solver_request_and_delete_address_mlp_SOURCES) \ $(test_ats_solver_request_and_delete_address_proportional_SOURCES) \ $(test_ats_solver_request_and_delete_address_ril_SOURCES) DIST_SOURCES = $(am__libgnunet_plugin_ats_mlp_la_SOURCES_DIST) \ $(libgnunet_plugin_ats_proportional_la_SOURCES) \ $(libgnunet_plugin_ats_ril_la_SOURCES) \ $(libgnunetats_la_SOURCES) $(gnunet_ats_solver_eval_SOURCES) \ $(gnunet_service_ats_SOURCES) $(perf_ats_solver_mlp_SOURCES) \ $(perf_ats_solver_proportional_SOURCES) \ $(perf_ats_solver_ril_SOURCES) \ $(test_ats_api_performance_list_all_addresses_SOURCES) \ $(test_ats_api_performance_list_all_addresses_active_SOURCES) \ $(test_ats_api_performance_list_peer_addresses_SOURCES) \ $(test_ats_api_performance_monitor_SOURCES) \ $(test_ats_api_performance_monitor_initial_callback_SOURCES) \ $(test_ats_api_scheduling_add_address_SOURCES) \ $(test_ats_api_scheduling_add_address_duplicate_SOURCES) \ $(test_ats_api_scheduling_add_address_inbound_SOURCES) \ $(test_ats_api_scheduling_add_session_SOURCES) \ $(test_ats_api_scheduling_destroy_address_SOURCES) \ $(test_ats_api_scheduling_destroy_address_twice_SOURCES) \ $(test_ats_api_scheduling_destroy_session_SOURCES) \ $(test_ats_api_scheduling_init_SOURCES) \ $(am__test_ats_solver_add_address_and_request_mlp_SOURCES_DIST) \ $(test_ats_solver_add_address_and_request_proportional_SOURCES) \ $(test_ats_solver_add_address_and_request_ril_SOURCES) \ $(am__test_ats_solver_add_address_mlp_SOURCES_DIST) \ $(test_ats_solver_add_address_proportional_SOURCES) \ $(test_ats_solver_add_address_ril_SOURCES) \ $(am__test_ats_solver_alternative_after_delete_address_mlp_SOURCES_DIST) \ $(test_ats_solver_alternative_after_delete_address_proportional_SOURCES) \ $(test_ats_solver_alternative_after_delete_address_ril_SOURCES) \ $(am__test_ats_solver_preferences_mlp_SOURCES_DIST) \ $(test_ats_solver_preferences_proportional_SOURCES) \ $(test_ats_solver_preferences_ril_SOURCES) \ $(am__test_ats_solver_request_and_add_address_mlp_SOURCES_DIST) \ $(test_ats_solver_request_and_add_address_proportional_SOURCES) \ $(test_ats_solver_request_and_add_address_ril_SOURCES) \ $(am__test_ats_solver_request_and_delete_address_mlp_SOURCES_DIST) \ $(test_ats_solver_request_and_delete_address_proportional_SOURCES) \ $(test_ats_solver_request_and_delete_address_ril_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ ats.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage @HAVE_LIBGLPK_TRUE@GN_LIBGLPK = -lglpk @HAVE_LIBGLPK_TRUE@GN_MLP_LIB = libgnunet_plugin_ats_mlp.la @HAVE_LIBGLPK_TRUE@GN_MLP_PERF = perf_ats_mlp @HAVE_LIBGLPK_TRUE@GN_MLP_ADD_ADDRESS = test_ats_solver_add_address_mlp @HAVE_LIBGLPK_TRUE@GN_MLP_ADD_REQUEST_ADDRESS = test_ats_solver_add_address_and_request_mlp @HAVE_LIBGLPK_TRUE@GN_MLP_REQUEST_ADD_ADDRESS = test_ats_solver_request_and_add_address_mlp @HAVE_LIBGLPK_TRUE@GN_MLP_REQUEST_DELETE_ADDRESS = test_ats_solver_request_and_delete_address_mlp @HAVE_LIBGLPK_TRUE@GN_MLP_PREFERENCES_ADDRESS = test_ats_solver_preferences_mlp @HAVE_LIBGLPK_TRUE@GN_MLP_ALTERNATIVE_DELETE_ADDRESS = test_ats_solver_alternative_after_delete_address_mlp @HAVE_LIBGLPK_TRUE@GN_MLP_SOLVER_PERF = perf_ats_solver_mlp lib_LTLIBRARIES = libgnunetats.la plugin_LTLIBRARIES = \ libgnunet_plugin_ats_proportional.la \ $(GN_MLP_LIB) \ libgnunet_plugin_ats_ril.la gnunet_ats_solver_eval_SOURCES = \ gnunet-ats-solver-eval.c gnunet-ats-solver-eval.h \ gnunet-service-ats_normalization.c gnunet_ats_solver_eval_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(LTLIBINTL) gnunet_ats_solver_eval_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la libgnunetats_la_SOURCES = \ ats_api_scheduling.c \ ats_api_performance.c libgnunetats_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetats_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 4:0:0 libgnunet_plugin_ats_proportional_la_SOURCES = \ plugin_ats_proportional.c libgnunet_plugin_ats_proportional_la_LIBADD = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_ats_proportional_la_DEPENDENCIES = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_ats_proportional_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) @HAVE_LIBGLPK_TRUE@libgnunet_plugin_ats_mlp_la_SOURCES = \ @HAVE_LIBGLPK_TRUE@ plugin_ats_mlp.c @HAVE_LIBGLPK_TRUE@libgnunet_plugin_ats_mlp_la_LIBADD = \ @HAVE_LIBGLPK_TRUE@ libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la @HAVE_LIBGLPK_TRUE@libgnunet_plugin_ats_mlp_la_LDFLAGS = \ @HAVE_LIBGLPK_TRUE@ $(GN_PLUGIN_LDFLAGS) $(GN_LIBGLPK) @HAVE_LIBGLPK_TRUE@libgnunet_plugin_ats_mlp_la_DEPENDENCIES = \ @HAVE_LIBGLPK_TRUE@ libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_ats_ril_la_SOURCES = \ plugin_ats_ril.c libgnunet_plugin_ats_ril_la_LIBADD = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_ats_ril_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_ats_ril_la_DEPENDENCIES = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_service_ats_SOURCES = \ gnunet-service-ats.c gnunet-service-ats.h\ gnunet-service-ats_addresses.c gnunet-service-ats_addresses.h \ gnunet-service-ats_normalization.c gnunet-service-ats_normalization.h \ gnunet-service-ats_performance.c gnunet-service-ats_performance.h \ gnunet-service-ats_scheduling.c gnunet-service-ats_scheduling.h \ gnunet-service-ats_reservations.c gnunet-service-ats_reservations.h gnunet_service_ats_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetats.la \ $(GN_LIBINTL) gnunet_service_ats_DEPENDENCIES = \ libgnunetats.la @HAVE_TESTING_TRUE@TESTING_TESTS = \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_init \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_add_address \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_add_address_duplicate \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_add_address_inbound \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_destroy_address \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_destroy_address_twice \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_add_session \ @HAVE_TESTING_TRUE@ test_ats_api_scheduling_destroy_session \ @HAVE_TESTING_TRUE@ test_ats_api_performance_list_all_addresses \ @HAVE_TESTING_TRUE@ test_ats_api_performance_list_peer_addresses \ @HAVE_TESTING_TRUE@ test_ats_api_performance_list_all_addresses_active \ @HAVE_TESTING_TRUE@ test_ats_api_performance_monitor \ @HAVE_TESTING_TRUE@ test_ats_api_performance_monitor_initial_callback \ @HAVE_TESTING_TRUE@ test_ats_solver_add_address_proportional \ @HAVE_TESTING_TRUE@ test_ats_solver_add_address_and_request_proportional \ @HAVE_TESTING_TRUE@ test_ats_solver_request_and_add_address_proportional \ @HAVE_TESTING_TRUE@ test_ats_solver_request_and_delete_address_proportional \ @HAVE_TESTING_TRUE@ test_ats_solver_alternative_after_delete_address_proportional \ @HAVE_TESTING_TRUE@ test_ats_solver_preferences_proportional \ @HAVE_TESTING_TRUE@ test_ats_solver_preferences_ril \ @HAVE_TESTING_TRUE@ $(GN_MLP_ADD_ADDRESS) \ @HAVE_TESTING_TRUE@ $(GN_MLP_ADD_REQUEST_ADDRESS) \ @HAVE_TESTING_TRUE@ $(GN_MLP_REQUEST_ADD_ADDRESS) \ @HAVE_TESTING_TRUE@ $(GN_MLP_REQUEST_DELETE_ADDRESS) \ @HAVE_TESTING_TRUE@ $(GN_MLP_ALTERNATIVE_DELETE_ADDRESS) \ @HAVE_TESTING_TRUE@ $(GN_MLP_PREFERENCES_ADDRESS) \ @HAVE_TESTING_TRUE@ test_ats_solver_add_address_ril \ @HAVE_TESTING_TRUE@ test_ats_solver_add_address_and_request_ril \ @HAVE_TESTING_TRUE@ test_ats_solver_request_and_add_address_ril \ @HAVE_TESTING_TRUE@ test_ats_solver_request_and_delete_address_ril \ @HAVE_TESTING_TRUE@ test_ats_solver_alternative_after_delete_address_ril \ @HAVE_TESTING_TRUE@ perf_ats_solver_proportional \ @HAVE_TESTING_TRUE@ $(GN_MLP_SOLVER_PERF) \ @HAVE_TESTING_TRUE@ perf_ats_solver_ril @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) # scheduling API tests test_ats_api_scheduling_init_SOURCES = \ test_ats_api_scheduling_init.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_init_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_add_address_SOURCES = \ test_ats_api_scheduling_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_add_address_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_add_address_inbound_SOURCES = \ test_ats_api_scheduling_add_address_inbound.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_add_address_inbound_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_add_address_duplicate_SOURCES = \ test_ats_api_scheduling_add_address_duplicate.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_add_address_duplicate_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_destroy_address_SOURCES = \ test_ats_api_scheduling_destroy_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_destroy_address_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_destroy_address_twice_SOURCES = \ test_ats_api_scheduling_destroy_address_twice.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_destroy_address_twice_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_add_session_SOURCES = \ test_ats_api_scheduling_add_session.c test_ats_api_common.c test_ats_api_scheduling_add_session_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_destroy_session_SOURCES = \ test_ats_api_scheduling_destroy_session.c test_ats_api_common.c test_ats_api_scheduling_destroy_session_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la # performance API tests test_ats_api_performance_list_all_addresses_SOURCES = \ test_ats_api_performance_list_all_addresses.c test_ats_api_performance_list_all_addresses_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_performance_list_peer_addresses_SOURCES = \ test_ats_api_performance_list_peer_addresses.c test_ats_api_performance_list_peer_addresses_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_performance_list_all_addresses_active_SOURCES = \ test_ats_api_performance_list_all_addresses_active.c test_ats_api_performance_list_all_addresses_active_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_performance_monitor_SOURCES = \ test_ats_api_performance_monitor.c test_ats_api_performance_monitor_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_performance_monitor_initial_callback_SOURCES = \ test_ats_api_performance_monitor_initial_callback.c test_ats_api_performance_monitor_initial_callback_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la # solver tests test_ats_solver_add_address_proportional_SOURCES = \ test_ats_solver_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la @HAVE_LIBGLPK_TRUE@test_ats_solver_add_address_mlp_SOURCES = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_add_address.c \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@test_ats_solver_add_address_mlp_LDADD = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_add_address_ril_SOURCES = \ test_ats_solver_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_add_address_and_request_proportional_SOURCES = \ test_ats_solver_add_address_and_request.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_and_request_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la @HAVE_LIBGLPK_TRUE@test_ats_solver_add_address_and_request_mlp_SOURCES = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_add_address_and_request.c \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@test_ats_solver_add_address_and_request_mlp_LDADD = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_add_address_and_request_ril_SOURCES = \ test_ats_solver_add_address_and_request.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_and_request_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_request_and_add_address_proportional_SOURCES = \ test_ats_solver_request_and_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_add_address_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la @HAVE_LIBGLPK_TRUE@test_ats_solver_request_and_add_address_mlp_SOURCES = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_request_and_add_address.c \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@test_ats_solver_request_and_add_address_mlp_LDADD = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_request_and_add_address_ril_SOURCES = \ test_ats_solver_request_and_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_add_address_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_request_and_delete_address_proportional_SOURCES = \ test_ats_solver_request_and_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_delete_address_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la @HAVE_LIBGLPK_TRUE@test_ats_solver_request_and_delete_address_mlp_SOURCES = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_request_and_delete_address.c \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@test_ats_solver_request_and_delete_address_mlp_LDADD = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_request_and_delete_address_ril_SOURCES = \ test_ats_solver_request_and_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_delete_address_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_alternative_after_delete_address_proportional_SOURCES = \ test_ats_solver_alternative_after_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_alternative_after_delete_address_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_preferences_proportional_SOURCES = \ test_ats_solver_preferences.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_preferences_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la @HAVE_LIBGLPK_TRUE@test_ats_solver_alternative_after_delete_address_mlp_SOURCES = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_alternative_after_delete_address.c \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@test_ats_solver_alternative_after_delete_address_mlp_LDADD = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la @HAVE_LIBGLPK_TRUE@test_ats_solver_preferences_mlp_SOURCES = \ @HAVE_LIBGLPK_TRUE@ test_ats_solver_preferences.c \ @HAVE_LIBGLPK_TRUE@ test_ats_api_common.c test_ats_api_common.h @HAVE_LIBGLPK_TRUE@test_ats_solver_preferences_mlp_LDADD = \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/testing/libgnunettesting.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/ats/libgnunetats.la \ @HAVE_LIBGLPK_TRUE@ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_alternative_after_delete_address_ril_SOURCES = \ test_ats_solver_alternative_after_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_alternative_after_delete_address_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la #perf_ats_mlp_SOURCES = \ # $(GN_MLP_SRC) perf_ats_mlp.c test_ats_api_common.c gnunet-service-ats_normalization.c #perf_ats_mlp_LDADD = \ # $(GN_LIBGLPK) \ # $(top_builddir)/src/util/libgnunetutil.la \ # $(top_builddir)/src/statistics/libgnunetstatistics.la \ # $(top_builddir)/src/ats/libgnunetats.la perf_ats_solver_mlp_SOURCES = \ perf_ats_solver.c test_ats_api_common.c gnunet-service-ats_normalization.c perf_ats_solver_mlp_LDADD = \ $(GN_LIBGLPK) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la perf_ats_solver_proportional_SOURCES = \ perf_ats_solver.c test_ats_api_common.c gnunet-service-ats_normalization.c perf_ats_solver_proportional_LDADD = \ $(GN_LIBGLPK) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la perf_ats_solver_ril_SOURCES = \ perf_ats_solver.c test_ats_api_common.c gnunet-service-ats_normalization.c perf_ats_solver_ril_LDADD = \ $(GN_LIBGLPK) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la test_ats_solver_preferences_ril_SOURCES = \ test_ats_solver_preferences.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_preferences_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la EXTRA_DIST = \ ats.h \ plugin_ats_proportional.h \ plugin_ats_mlp.h \ plugin_ats_ril.h \ test_ats_api.conf \ test_ats_mlp.conf \ test_ats_solver_default.conf \ test_ats_solver_proportional.conf \ test_ats_solver_mlp.conf \ test_ats_solver_ril.conf \ perf_ats_solver_mlp.conf \ perf_ats_solver_proportional.conf \ perf_ats_solver_ril.conf \ perf_ats_solver.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ats/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/ats/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): ats.conf: $(top_builddir)/config.status $(srcdir)/ats.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_ats_mlp.la: $(libgnunet_plugin_ats_mlp_la_OBJECTS) $(libgnunet_plugin_ats_mlp_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_ats_mlp_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_ats_mlp_la_LINK) $(am_libgnunet_plugin_ats_mlp_la_rpath) $(libgnunet_plugin_ats_mlp_la_OBJECTS) $(libgnunet_plugin_ats_mlp_la_LIBADD) $(LIBS) libgnunet_plugin_ats_proportional.la: $(libgnunet_plugin_ats_proportional_la_OBJECTS) $(libgnunet_plugin_ats_proportional_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_ats_proportional_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_ats_proportional_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_ats_proportional_la_OBJECTS) $(libgnunet_plugin_ats_proportional_la_LIBADD) $(LIBS) libgnunet_plugin_ats_ril.la: $(libgnunet_plugin_ats_ril_la_OBJECTS) $(libgnunet_plugin_ats_ril_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_ats_ril_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_ats_ril_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_ats_ril_la_OBJECTS) $(libgnunet_plugin_ats_ril_la_LIBADD) $(LIBS) libgnunetats.la: $(libgnunetats_la_OBJECTS) $(libgnunetats_la_DEPENDENCIES) $(EXTRA_libgnunetats_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetats_la_LINK) -rpath $(libdir) $(libgnunetats_la_OBJECTS) $(libgnunetats_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-ats-solver-eval$(EXEEXT): $(gnunet_ats_solver_eval_OBJECTS) $(gnunet_ats_solver_eval_DEPENDENCIES) $(EXTRA_gnunet_ats_solver_eval_DEPENDENCIES) @rm -f gnunet-ats-solver-eval$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_ats_solver_eval_OBJECTS) $(gnunet_ats_solver_eval_LDADD) $(LIBS) gnunet-service-ats$(EXEEXT): $(gnunet_service_ats_OBJECTS) $(gnunet_service_ats_DEPENDENCIES) $(EXTRA_gnunet_service_ats_DEPENDENCIES) @rm -f gnunet-service-ats$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_ats_OBJECTS) $(gnunet_service_ats_LDADD) $(LIBS) perf_ats_solver_mlp$(EXEEXT): $(perf_ats_solver_mlp_OBJECTS) $(perf_ats_solver_mlp_DEPENDENCIES) $(EXTRA_perf_ats_solver_mlp_DEPENDENCIES) @rm -f perf_ats_solver_mlp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_solver_mlp_OBJECTS) $(perf_ats_solver_mlp_LDADD) $(LIBS) perf_ats_solver_proportional$(EXEEXT): $(perf_ats_solver_proportional_OBJECTS) $(perf_ats_solver_proportional_DEPENDENCIES) $(EXTRA_perf_ats_solver_proportional_DEPENDENCIES) @rm -f perf_ats_solver_proportional$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_solver_proportional_OBJECTS) $(perf_ats_solver_proportional_LDADD) $(LIBS) perf_ats_solver_ril$(EXEEXT): $(perf_ats_solver_ril_OBJECTS) $(perf_ats_solver_ril_DEPENDENCIES) $(EXTRA_perf_ats_solver_ril_DEPENDENCIES) @rm -f perf_ats_solver_ril$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_solver_ril_OBJECTS) $(perf_ats_solver_ril_LDADD) $(LIBS) test_ats_api_performance_list_all_addresses$(EXEEXT): $(test_ats_api_performance_list_all_addresses_OBJECTS) $(test_ats_api_performance_list_all_addresses_DEPENDENCIES) $(EXTRA_test_ats_api_performance_list_all_addresses_DEPENDENCIES) @rm -f test_ats_api_performance_list_all_addresses$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_performance_list_all_addresses_OBJECTS) $(test_ats_api_performance_list_all_addresses_LDADD) $(LIBS) test_ats_api_performance_list_all_addresses_active$(EXEEXT): $(test_ats_api_performance_list_all_addresses_active_OBJECTS) $(test_ats_api_performance_list_all_addresses_active_DEPENDENCIES) $(EXTRA_test_ats_api_performance_list_all_addresses_active_DEPENDENCIES) @rm -f test_ats_api_performance_list_all_addresses_active$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_performance_list_all_addresses_active_OBJECTS) $(test_ats_api_performance_list_all_addresses_active_LDADD) $(LIBS) test_ats_api_performance_list_peer_addresses$(EXEEXT): $(test_ats_api_performance_list_peer_addresses_OBJECTS) $(test_ats_api_performance_list_peer_addresses_DEPENDENCIES) $(EXTRA_test_ats_api_performance_list_peer_addresses_DEPENDENCIES) @rm -f test_ats_api_performance_list_peer_addresses$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_performance_list_peer_addresses_OBJECTS) $(test_ats_api_performance_list_peer_addresses_LDADD) $(LIBS) test_ats_api_performance_monitor$(EXEEXT): $(test_ats_api_performance_monitor_OBJECTS) $(test_ats_api_performance_monitor_DEPENDENCIES) $(EXTRA_test_ats_api_performance_monitor_DEPENDENCIES) @rm -f test_ats_api_performance_monitor$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_performance_monitor_OBJECTS) $(test_ats_api_performance_monitor_LDADD) $(LIBS) test_ats_api_performance_monitor_initial_callback$(EXEEXT): $(test_ats_api_performance_monitor_initial_callback_OBJECTS) $(test_ats_api_performance_monitor_initial_callback_DEPENDENCIES) $(EXTRA_test_ats_api_performance_monitor_initial_callback_DEPENDENCIES) @rm -f test_ats_api_performance_monitor_initial_callback$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_performance_monitor_initial_callback_OBJECTS) $(test_ats_api_performance_monitor_initial_callback_LDADD) $(LIBS) test_ats_api_scheduling_add_address$(EXEEXT): $(test_ats_api_scheduling_add_address_OBJECTS) $(test_ats_api_scheduling_add_address_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_add_address_DEPENDENCIES) @rm -f test_ats_api_scheduling_add_address$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_add_address_OBJECTS) $(test_ats_api_scheduling_add_address_LDADD) $(LIBS) test_ats_api_scheduling_add_address_duplicate$(EXEEXT): $(test_ats_api_scheduling_add_address_duplicate_OBJECTS) $(test_ats_api_scheduling_add_address_duplicate_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_add_address_duplicate_DEPENDENCIES) @rm -f test_ats_api_scheduling_add_address_duplicate$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_add_address_duplicate_OBJECTS) $(test_ats_api_scheduling_add_address_duplicate_LDADD) $(LIBS) test_ats_api_scheduling_add_address_inbound$(EXEEXT): $(test_ats_api_scheduling_add_address_inbound_OBJECTS) $(test_ats_api_scheduling_add_address_inbound_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_add_address_inbound_DEPENDENCIES) @rm -f test_ats_api_scheduling_add_address_inbound$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_add_address_inbound_OBJECTS) $(test_ats_api_scheduling_add_address_inbound_LDADD) $(LIBS) test_ats_api_scheduling_add_session$(EXEEXT): $(test_ats_api_scheduling_add_session_OBJECTS) $(test_ats_api_scheduling_add_session_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_add_session_DEPENDENCIES) @rm -f test_ats_api_scheduling_add_session$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_add_session_OBJECTS) $(test_ats_api_scheduling_add_session_LDADD) $(LIBS) test_ats_api_scheduling_destroy_address$(EXEEXT): $(test_ats_api_scheduling_destroy_address_OBJECTS) $(test_ats_api_scheduling_destroy_address_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_destroy_address_DEPENDENCIES) @rm -f test_ats_api_scheduling_destroy_address$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_destroy_address_OBJECTS) $(test_ats_api_scheduling_destroy_address_LDADD) $(LIBS) test_ats_api_scheduling_destroy_address_twice$(EXEEXT): $(test_ats_api_scheduling_destroy_address_twice_OBJECTS) $(test_ats_api_scheduling_destroy_address_twice_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_destroy_address_twice_DEPENDENCIES) @rm -f test_ats_api_scheduling_destroy_address_twice$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_destroy_address_twice_OBJECTS) $(test_ats_api_scheduling_destroy_address_twice_LDADD) $(LIBS) test_ats_api_scheduling_destroy_session$(EXEEXT): $(test_ats_api_scheduling_destroy_session_OBJECTS) $(test_ats_api_scheduling_destroy_session_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_destroy_session_DEPENDENCIES) @rm -f test_ats_api_scheduling_destroy_session$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_destroy_session_OBJECTS) $(test_ats_api_scheduling_destroy_session_LDADD) $(LIBS) test_ats_api_scheduling_init$(EXEEXT): $(test_ats_api_scheduling_init_OBJECTS) $(test_ats_api_scheduling_init_DEPENDENCIES) $(EXTRA_test_ats_api_scheduling_init_DEPENDENCIES) @rm -f test_ats_api_scheduling_init$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_api_scheduling_init_OBJECTS) $(test_ats_api_scheduling_init_LDADD) $(LIBS) test_ats_solver_add_address_and_request_mlp$(EXEEXT): $(test_ats_solver_add_address_and_request_mlp_OBJECTS) $(test_ats_solver_add_address_and_request_mlp_DEPENDENCIES) $(EXTRA_test_ats_solver_add_address_and_request_mlp_DEPENDENCIES) @rm -f test_ats_solver_add_address_and_request_mlp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_add_address_and_request_mlp_OBJECTS) $(test_ats_solver_add_address_and_request_mlp_LDADD) $(LIBS) test_ats_solver_add_address_and_request_proportional$(EXEEXT): $(test_ats_solver_add_address_and_request_proportional_OBJECTS) $(test_ats_solver_add_address_and_request_proportional_DEPENDENCIES) $(EXTRA_test_ats_solver_add_address_and_request_proportional_DEPENDENCIES) @rm -f test_ats_solver_add_address_and_request_proportional$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_add_address_and_request_proportional_OBJECTS) $(test_ats_solver_add_address_and_request_proportional_LDADD) $(LIBS) test_ats_solver_add_address_and_request_ril$(EXEEXT): $(test_ats_solver_add_address_and_request_ril_OBJECTS) $(test_ats_solver_add_address_and_request_ril_DEPENDENCIES) $(EXTRA_test_ats_solver_add_address_and_request_ril_DEPENDENCIES) @rm -f test_ats_solver_add_address_and_request_ril$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_add_address_and_request_ril_OBJECTS) $(test_ats_solver_add_address_and_request_ril_LDADD) $(LIBS) test_ats_solver_add_address_mlp$(EXEEXT): $(test_ats_solver_add_address_mlp_OBJECTS) $(test_ats_solver_add_address_mlp_DEPENDENCIES) $(EXTRA_test_ats_solver_add_address_mlp_DEPENDENCIES) @rm -f test_ats_solver_add_address_mlp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_add_address_mlp_OBJECTS) $(test_ats_solver_add_address_mlp_LDADD) $(LIBS) test_ats_solver_add_address_proportional$(EXEEXT): $(test_ats_solver_add_address_proportional_OBJECTS) $(test_ats_solver_add_address_proportional_DEPENDENCIES) $(EXTRA_test_ats_solver_add_address_proportional_DEPENDENCIES) @rm -f test_ats_solver_add_address_proportional$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_add_address_proportional_OBJECTS) $(test_ats_solver_add_address_proportional_LDADD) $(LIBS) test_ats_solver_add_address_ril$(EXEEXT): $(test_ats_solver_add_address_ril_OBJECTS) $(test_ats_solver_add_address_ril_DEPENDENCIES) $(EXTRA_test_ats_solver_add_address_ril_DEPENDENCIES) @rm -f test_ats_solver_add_address_ril$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_add_address_ril_OBJECTS) $(test_ats_solver_add_address_ril_LDADD) $(LIBS) test_ats_solver_alternative_after_delete_address_mlp$(EXEEXT): $(test_ats_solver_alternative_after_delete_address_mlp_OBJECTS) $(test_ats_solver_alternative_after_delete_address_mlp_DEPENDENCIES) $(EXTRA_test_ats_solver_alternative_after_delete_address_mlp_DEPENDENCIES) @rm -f test_ats_solver_alternative_after_delete_address_mlp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_alternative_after_delete_address_mlp_OBJECTS) $(test_ats_solver_alternative_after_delete_address_mlp_LDADD) $(LIBS) test_ats_solver_alternative_after_delete_address_proportional$(EXEEXT): $(test_ats_solver_alternative_after_delete_address_proportional_OBJECTS) $(test_ats_solver_alternative_after_delete_address_proportional_DEPENDENCIES) $(EXTRA_test_ats_solver_alternative_after_delete_address_proportional_DEPENDENCIES) @rm -f test_ats_solver_alternative_after_delete_address_proportional$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_alternative_after_delete_address_proportional_OBJECTS) $(test_ats_solver_alternative_after_delete_address_proportional_LDADD) $(LIBS) test_ats_solver_alternative_after_delete_address_ril$(EXEEXT): $(test_ats_solver_alternative_after_delete_address_ril_OBJECTS) $(test_ats_solver_alternative_after_delete_address_ril_DEPENDENCIES) $(EXTRA_test_ats_solver_alternative_after_delete_address_ril_DEPENDENCIES) @rm -f test_ats_solver_alternative_after_delete_address_ril$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_alternative_after_delete_address_ril_OBJECTS) $(test_ats_solver_alternative_after_delete_address_ril_LDADD) $(LIBS) test_ats_solver_preferences_mlp$(EXEEXT): $(test_ats_solver_preferences_mlp_OBJECTS) $(test_ats_solver_preferences_mlp_DEPENDENCIES) $(EXTRA_test_ats_solver_preferences_mlp_DEPENDENCIES) @rm -f test_ats_solver_preferences_mlp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_preferences_mlp_OBJECTS) $(test_ats_solver_preferences_mlp_LDADD) $(LIBS) test_ats_solver_preferences_proportional$(EXEEXT): $(test_ats_solver_preferences_proportional_OBJECTS) $(test_ats_solver_preferences_proportional_DEPENDENCIES) $(EXTRA_test_ats_solver_preferences_proportional_DEPENDENCIES) @rm -f test_ats_solver_preferences_proportional$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_preferences_proportional_OBJECTS) $(test_ats_solver_preferences_proportional_LDADD) $(LIBS) test_ats_solver_preferences_ril$(EXEEXT): $(test_ats_solver_preferences_ril_OBJECTS) $(test_ats_solver_preferences_ril_DEPENDENCIES) $(EXTRA_test_ats_solver_preferences_ril_DEPENDENCIES) @rm -f test_ats_solver_preferences_ril$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_preferences_ril_OBJECTS) $(test_ats_solver_preferences_ril_LDADD) $(LIBS) test_ats_solver_request_and_add_address_mlp$(EXEEXT): $(test_ats_solver_request_and_add_address_mlp_OBJECTS) $(test_ats_solver_request_and_add_address_mlp_DEPENDENCIES) $(EXTRA_test_ats_solver_request_and_add_address_mlp_DEPENDENCIES) @rm -f test_ats_solver_request_and_add_address_mlp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_request_and_add_address_mlp_OBJECTS) $(test_ats_solver_request_and_add_address_mlp_LDADD) $(LIBS) test_ats_solver_request_and_add_address_proportional$(EXEEXT): $(test_ats_solver_request_and_add_address_proportional_OBJECTS) $(test_ats_solver_request_and_add_address_proportional_DEPENDENCIES) $(EXTRA_test_ats_solver_request_and_add_address_proportional_DEPENDENCIES) @rm -f test_ats_solver_request_and_add_address_proportional$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_request_and_add_address_proportional_OBJECTS) $(test_ats_solver_request_and_add_address_proportional_LDADD) $(LIBS) test_ats_solver_request_and_add_address_ril$(EXEEXT): $(test_ats_solver_request_and_add_address_ril_OBJECTS) $(test_ats_solver_request_and_add_address_ril_DEPENDENCIES) $(EXTRA_test_ats_solver_request_and_add_address_ril_DEPENDENCIES) @rm -f test_ats_solver_request_and_add_address_ril$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_request_and_add_address_ril_OBJECTS) $(test_ats_solver_request_and_add_address_ril_LDADD) $(LIBS) test_ats_solver_request_and_delete_address_mlp$(EXEEXT): $(test_ats_solver_request_and_delete_address_mlp_OBJECTS) $(test_ats_solver_request_and_delete_address_mlp_DEPENDENCIES) $(EXTRA_test_ats_solver_request_and_delete_address_mlp_DEPENDENCIES) @rm -f test_ats_solver_request_and_delete_address_mlp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_request_and_delete_address_mlp_OBJECTS) $(test_ats_solver_request_and_delete_address_mlp_LDADD) $(LIBS) test_ats_solver_request_and_delete_address_proportional$(EXEEXT): $(test_ats_solver_request_and_delete_address_proportional_OBJECTS) $(test_ats_solver_request_and_delete_address_proportional_DEPENDENCIES) $(EXTRA_test_ats_solver_request_and_delete_address_proportional_DEPENDENCIES) @rm -f test_ats_solver_request_and_delete_address_proportional$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_request_and_delete_address_proportional_OBJECTS) $(test_ats_solver_request_and_delete_address_proportional_LDADD) $(LIBS) test_ats_solver_request_and_delete_address_ril$(EXEEXT): $(test_ats_solver_request_and_delete_address_ril_OBJECTS) $(test_ats_solver_request_and_delete_address_ril_DEPENDENCIES) $(EXTRA_test_ats_solver_request_and_delete_address_ril_DEPENDENCIES) @rm -f test_ats_solver_request_and_delete_address_ril$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_ats_solver_request_and_delete_address_ril_OBJECTS) $(test_ats_solver_request_and_delete_address_ril_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ats_api_performance.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ats_api_scheduling.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-ats-solver-eval.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_addresses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_normalization.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_performance.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_reservations.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-ats_scheduling.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_ats_solver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_ats_mlp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_ats_proportional.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_ats_ril.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_performance_list_all_addresses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_performance_list_all_addresses_active.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_performance_list_peer_addresses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_performance_monitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_performance_monitor_initial_callback.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_add_address.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_add_address_duplicate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_add_address_inbound.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_add_session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_destroy_address.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_destroy_address_twice.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_destroy_session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_api_scheduling_init.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_solver_add_address.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_solver_add_address_and_request.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_solver_alternative_after_delete_address.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_solver_preferences.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_solver_request_and_add_address.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ats_solver_request_and_delete_address.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_ats_api_scheduling_init.log: test_ats_api_scheduling_init$(EXEEXT) @p='test_ats_api_scheduling_init$(EXEEXT)'; \ b='test_ats_api_scheduling_init'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_scheduling_add_address.log: test_ats_api_scheduling_add_address$(EXEEXT) @p='test_ats_api_scheduling_add_address$(EXEEXT)'; \ b='test_ats_api_scheduling_add_address'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_scheduling_add_address_duplicate.log: test_ats_api_scheduling_add_address_duplicate$(EXEEXT) @p='test_ats_api_scheduling_add_address_duplicate$(EXEEXT)'; \ b='test_ats_api_scheduling_add_address_duplicate'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_scheduling_add_address_inbound.log: test_ats_api_scheduling_add_address_inbound$(EXEEXT) @p='test_ats_api_scheduling_add_address_inbound$(EXEEXT)'; \ b='test_ats_api_scheduling_add_address_inbound'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_scheduling_destroy_address.log: test_ats_api_scheduling_destroy_address$(EXEEXT) @p='test_ats_api_scheduling_destroy_address$(EXEEXT)'; \ b='test_ats_api_scheduling_destroy_address'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_scheduling_destroy_address_twice.log: test_ats_api_scheduling_destroy_address_twice$(EXEEXT) @p='test_ats_api_scheduling_destroy_address_twice$(EXEEXT)'; \ b='test_ats_api_scheduling_destroy_address_twice'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_scheduling_add_session.log: test_ats_api_scheduling_add_session$(EXEEXT) @p='test_ats_api_scheduling_add_session$(EXEEXT)'; \ b='test_ats_api_scheduling_add_session'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_scheduling_destroy_session.log: test_ats_api_scheduling_destroy_session$(EXEEXT) @p='test_ats_api_scheduling_destroy_session$(EXEEXT)'; \ b='test_ats_api_scheduling_destroy_session'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_performance_list_all_addresses.log: test_ats_api_performance_list_all_addresses$(EXEEXT) @p='test_ats_api_performance_list_all_addresses$(EXEEXT)'; \ b='test_ats_api_performance_list_all_addresses'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_performance_list_peer_addresses.log: test_ats_api_performance_list_peer_addresses$(EXEEXT) @p='test_ats_api_performance_list_peer_addresses$(EXEEXT)'; \ b='test_ats_api_performance_list_peer_addresses'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_performance_list_all_addresses_active.log: test_ats_api_performance_list_all_addresses_active$(EXEEXT) @p='test_ats_api_performance_list_all_addresses_active$(EXEEXT)'; \ b='test_ats_api_performance_list_all_addresses_active'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_performance_monitor.log: test_ats_api_performance_monitor$(EXEEXT) @p='test_ats_api_performance_monitor$(EXEEXT)'; \ b='test_ats_api_performance_monitor'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_api_performance_monitor_initial_callback.log: test_ats_api_performance_monitor_initial_callback$(EXEEXT) @p='test_ats_api_performance_monitor_initial_callback$(EXEEXT)'; \ b='test_ats_api_performance_monitor_initial_callback'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_add_address_proportional.log: test_ats_solver_add_address_proportional$(EXEEXT) @p='test_ats_solver_add_address_proportional$(EXEEXT)'; \ b='test_ats_solver_add_address_proportional'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_add_address_and_request_proportional.log: test_ats_solver_add_address_and_request_proportional$(EXEEXT) @p='test_ats_solver_add_address_and_request_proportional$(EXEEXT)'; \ b='test_ats_solver_add_address_and_request_proportional'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_request_and_add_address_proportional.log: test_ats_solver_request_and_add_address_proportional$(EXEEXT) @p='test_ats_solver_request_and_add_address_proportional$(EXEEXT)'; \ b='test_ats_solver_request_and_add_address_proportional'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_request_and_delete_address_proportional.log: test_ats_solver_request_and_delete_address_proportional$(EXEEXT) @p='test_ats_solver_request_and_delete_address_proportional$(EXEEXT)'; \ b='test_ats_solver_request_and_delete_address_proportional'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_alternative_after_delete_address_proportional.log: test_ats_solver_alternative_after_delete_address_proportional$(EXEEXT) @p='test_ats_solver_alternative_after_delete_address_proportional$(EXEEXT)'; \ b='test_ats_solver_alternative_after_delete_address_proportional'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_preferences_proportional.log: test_ats_solver_preferences_proportional$(EXEEXT) @p='test_ats_solver_preferences_proportional$(EXEEXT)'; \ b='test_ats_solver_preferences_proportional'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_preferences_ril.log: test_ats_solver_preferences_ril$(EXEEXT) @p='test_ats_solver_preferences_ril$(EXEEXT)'; \ b='test_ats_solver_preferences_ril'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_add_address_mlp.log: test_ats_solver_add_address_mlp$(EXEEXT) @p='test_ats_solver_add_address_mlp$(EXEEXT)'; \ b='test_ats_solver_add_address_mlp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_add_address_and_request_mlp.log: test_ats_solver_add_address_and_request_mlp$(EXEEXT) @p='test_ats_solver_add_address_and_request_mlp$(EXEEXT)'; \ b='test_ats_solver_add_address_and_request_mlp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_request_and_add_address_mlp.log: test_ats_solver_request_and_add_address_mlp$(EXEEXT) @p='test_ats_solver_request_and_add_address_mlp$(EXEEXT)'; \ b='test_ats_solver_request_and_add_address_mlp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_request_and_delete_address_mlp.log: test_ats_solver_request_and_delete_address_mlp$(EXEEXT) @p='test_ats_solver_request_and_delete_address_mlp$(EXEEXT)'; \ b='test_ats_solver_request_and_delete_address_mlp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_alternative_after_delete_address_mlp.log: test_ats_solver_alternative_after_delete_address_mlp$(EXEEXT) @p='test_ats_solver_alternative_after_delete_address_mlp$(EXEEXT)'; \ b='test_ats_solver_alternative_after_delete_address_mlp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_preferences_mlp.log: test_ats_solver_preferences_mlp$(EXEEXT) @p='test_ats_solver_preferences_mlp$(EXEEXT)'; \ b='test_ats_solver_preferences_mlp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_add_address_ril.log: test_ats_solver_add_address_ril$(EXEEXT) @p='test_ats_solver_add_address_ril$(EXEEXT)'; \ b='test_ats_solver_add_address_ril'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_add_address_and_request_ril.log: test_ats_solver_add_address_and_request_ril$(EXEEXT) @p='test_ats_solver_add_address_and_request_ril$(EXEEXT)'; \ b='test_ats_solver_add_address_and_request_ril'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_request_and_add_address_ril.log: test_ats_solver_request_and_add_address_ril$(EXEEXT) @p='test_ats_solver_request_and_add_address_ril$(EXEEXT)'; \ b='test_ats_solver_request_and_add_address_ril'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_request_and_delete_address_ril.log: test_ats_solver_request_and_delete_address_ril$(EXEEXT) @p='test_ats_solver_request_and_delete_address_ril$(EXEEXT)'; \ b='test_ats_solver_request_and_delete_address_ril'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_ats_solver_alternative_after_delete_address_ril.log: test_ats_solver_alternative_after_delete_address_ril$(EXEEXT) @p='test_ats_solver_alternative_after_delete_address_ril$(EXEEXT)'; \ b='test_ats_solver_alternative_after_delete_address_ril'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_solver_proportional.log: perf_ats_solver_proportional$(EXEEXT) @p='perf_ats_solver_proportional$(EXEEXT)'; \ b='perf_ats_solver_proportional'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_solver_mlp.log: perf_ats_solver_mlp$(EXEEXT) @p='perf_ats_solver_mlp$(EXEEXT)'; \ b='perf_ats_solver_mlp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_solver_ril.log: perf_ats_solver_ril$(EXEEXT) @p='perf_ats_solver_ril$(EXEEXT)'; \ b='perf_ats_solver_ril'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-noinstPROGRAMS \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-noinstPROGRAMS \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/ats/test_ats_api_performance_monitor.c0000644000175000017500000002007312263724143020351 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_performance_monitor.c * @brief test performance API's address monitor feature * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) #define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Configuration handle */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * ATS scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * ATS performance handle */ static struct GNUNET_ATS_PerformanceHandle *perf_ats; struct GNUNET_ATS_AddressListHandle* phal; static int ret; struct Address { char *plugin; size_t plugin_len; void *addr; size_t addr_len; struct GNUNET_ATS_Information *ats; int ats_count; void *session; }; struct PeerContext { struct GNUNET_PeerIdentity id; struct Address *addr; }; static struct PeerContext p[2]; static struct Address p0_addresses[2]; static struct Address p1_addresses[2]; struct GNUNET_HELLO_Address p0_ha[2]; struct GNUNET_HELLO_Address p1_ha[2]; struct GNUNET_HELLO_Address *s_ha[2]; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void ats_perf_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { static int peer0 = GNUNET_NO; static int peer1 = GNUNET_NO; static int done = GNUNET_NO; if ((GNUNET_NO == peer0) && (0 == memcmp (address, &p[0].id, sizeof (p[0].id)))) { peer0 = GNUNET_YES; } if ((GNUNET_NO == peer0) && (0 == memcmp (address, &p[1].id, sizeof (p[1].id)))) { peer1 = GNUNET_YES; } if ((peer0 == GNUNET_YES) && (peer1 = GNUNET_YES) && (GNUNET_NO == done)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done\n"); done = GNUNET_YES; GNUNET_SCHEDULER_add_now (&end, NULL); } } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (4 == value) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All addresses added\n"); } return GNUNET_OK; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } if (NULL != perf_ats) { GNUNET_ATS_performance_done (perf_ats); perf_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } GNUNET_free_non_null(p0_addresses[0].addr); GNUNET_free_non_null(p0_addresses[1].addr); GNUNET_free_non_null(p1_addresses[0].addr); GNUNET_free_non_null(p1_addresses[1].addr); ret = 0; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { ret = 1; cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL ); if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* set up peer 0 */ memset (&p[0].id, '1', sizeof (p[0].id)); p0_addresses[0].plugin = "test"; p0_addresses[0].session = NULL; p0_addresses[0].addr = GNUNET_strdup ("test_p0_a0"); p0_addresses[0].addr_len = strlen (p0_addresses[0].addr) + 1; p0_ha[0].address = p0_addresses[0].addr; p0_ha[0].address_length = p0_addresses[0].addr_len; p0_ha[0].peer = p[0].id; p0_ha[0].transport_name = p0_addresses[0].plugin; p0_addresses[1].plugin = "test"; p0_addresses[1].session = NULL; p0_addresses[1].addr = GNUNET_strdup ("test_p0_a1"); p0_addresses[1].addr_len = strlen (p0_addresses[1].addr) + 1; p0_ha[1].address = p0_addresses[1].addr; p0_ha[1].address_length = p0_addresses[1].addr_len; p0_ha[1].peer = p[0].id; p0_ha[1].transport_name = p0_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 0: `%s'\n", GNUNET_i2s (&p[0].id)); memset (&p[1].id, '2', sizeof (p[1].id)); p1_addresses[0].plugin = "test"; p1_addresses[0].session = NULL; p1_addresses[0].addr = GNUNET_strdup ("test_p1_a0"); p1_addresses[0].addr_len = strlen (p1_addresses[0].addr) + 1; p1_ha[0].address = p1_addresses[0].addr; p1_ha[0].address_length = p1_addresses[0].addr_len; p1_ha[0].peer = p[1].id; p1_ha[0].transport_name = p1_addresses[0].plugin; p1_addresses[1].plugin = "test"; p1_addresses[1].session = NULL; p1_addresses[1].addr = GNUNET_strdup ("test_p1_a1"); p1_addresses[1].addr_len = strlen (p1_addresses[1].addr) + 1; p1_ha[1].address = p1_addresses[1].addr; p1_ha[1].address_length = p1_addresses[1].addr_len; p1_ha[1].peer = p[1].id; p1_ha[1].transport_name = p1_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 1: `%s'\n", GNUNET_i2s (&p[1].id)); /* Add addresses */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL ); if (sched_ats == NULL ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } GNUNET_ATS_address_add (sched_ats, &p0_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p0_ha[1], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[1], NULL, NULL, 0); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test_ats_api_performance", "test_ats_api.conf", &run, NULL )) return 1; return ret; } /* end of file test_ats_api_performance_monitor.c */ gnunet-0.10.1/src/ats/gnunet-service-ats_normalization.h0000644000175000017500000001037212247442021020233 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_normalization.h * @brief ats service address: management of ATS properties and preferences normalization * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_ats_service.h" #define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) #define PREF_AGING_FACTOR 0.95 #define PREF_EPSILON 0.1 #define DEFAULT_REL_PREFERENCE 1.0 #define DEFAULT_ABS_PREFERENCE 0.0 #define DEFAULT_REL_QUALITY 1.0 typedef void (*GAS_Normalization_preference_changed_cb) (void *cls, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel); typedef void (*GAS_Normalization_property_changed_cb) (void *cls, struct ATS_Address *peer, uint32_t type, double prop_rel); /** * Get the normalized preference values for a specific peer * * @param id the peer @return pointer to the values, can be indexed * with GNUNET_ATS_PreferenceKind, NULL if peer does not exist */ const double * GAS_normalization_get_preferences_by_peer (const struct GNUNET_PeerIdentity *id); /** * Get the normalized properties values for a specific peer or * the default values if * * @param address the address * @return pointer to the values, can be indexed with GNUNET_ATS_PreferenceKind, * default preferences if peer does not exist */ const double * GAS_normalization_get_properties (struct ATS_Address *address); /** * Get the normalized preference values for a specific client and peer * * @param client client * @param peer the peer * @param pref the preference type * @return the value */ const double GAS_normalization_get_preferences_by_client (const void *client, struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind pref); /** * Normalize an updated preference value * * @param src the client with this preference * @param peer the peer to change the preference for * @param kind the kind to change the preference * @param score_abs the normalized score */ void GAS_normalization_normalize_preference (void *src, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, float score_abs); /** * Update and normalize a atsi performance information * * @param addresses hashmap containing all addresses * @param address the address to update * @param atsi the array of performance information * @param atsi_count the number of atsi information in the array */ void GAS_normalization_normalize_property (struct GNUNET_CONTAINER_MultiPeerMap *addresses, struct ATS_Address *address, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count); /** * A performance client disconnected * * @param client the disconnecting client */ void GAS_normalization_preference_client_disconnect (void *client); /** * Start the normalization component * * @param pref_ch_cb callback to call on relative preference changing * @param pref_ch_cb_cls cls for the preference callback * @param property_ch_cb callback to call on relative property changing * @param property_ch_cb_cls cls for the property callback */ void GAS_normalization_start (GAS_Normalization_preference_changed_cb pref_ch_cb, void *pref_ch_cb_cls, GAS_Normalization_property_changed_cb property_ch_cb, void *property_ch_cb_cls); /** * Stop the normalization component and free all items */ void GAS_normalization_stop (); /* end of gnunet-service-ats_normalization.h */ gnunet-0.10.1/src/ats/perf_ats_solver.c0000644000175000017500000014363012272425070014741 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/perf_ats_solver.c * @brief generic performance test for ATS solvers * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet-service-ats_addresses.h" #include "gnunet-service-ats_normalization.h" #include "gnunet_ats_service.h" #include "gnunet_ats_plugin.h" #include "test_ats_api_common.h" #define DEFAULT_UPDATE_PERCENTAGE 20 #define DEFAULT_PEERS_START 10 #define DEFAULT_PEERS_END 10 #define DEFAULT_ADDRESSES 10 #define DEFAULT_ATS_COUNT 2 #define GNUPLOT_PROP_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Execution time Proportional solver \" \n" \ "set xlabel \"Number of peers\" \n" \ "set ylabel \"Execution time in us\" \n" \ "set grid \n" #define GNUPLOT_PROP_UPDATE_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Execution time Proportional solver with updated problem\" \n" \ "set xlabel \"Number of peers\" \n" \ "set ylabel \"Execution time in us\" \n" \ "set grid \n" #define GNUPLOT_MLP_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Execution time MLP solver \" \n" \ "set xlabel \"Number of peers\" \n" \ "set ylabel \"Execution time in us\" \n" \ "set grid \n" #define GNUPLOT_MLP_UPDATE_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Execution time MLP solver with updated problem\" \n" \ "set xlabel \"Number of peers\" \n" \ "set ylabel \"Execution time in us\" \n" \ "set grid \n" #define GNUPLOT_RIL_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Execution time RIL solver \" \n" \ "set xlabel \"Number of peers\" \n" \ "set ylabel \"Execution time in us\" \n" \ "set grid \n" #define GNUPLOT_RIL_UPDATE_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Execution time RIL solver with updated problem\" \n" \ "set xlabel \"Number of peers\" \n" \ "set ylabel \"Execution time in us\" \n" \ "set grid \n" /** * Handle for ATS address component */ struct PerfHandle { /** * Performance peers */ struct PerfPeer *peers; /** * Solver handle */ void *solver; /** * Statistics stat; */ struct GNUNET_STATISTICS_Handle *stat; /** * A multihashmap to store all addresses */ struct GNUNET_CONTAINER_MultiPeerMap *addresses; /** * Solver functions * */ struct GNUNET_ATS_PluginEnvironment env; /** * Array for results for each iteration with length iterations */ struct Iteration *iterations_results; /** * Array to store averaged full solution result with length #peers */ struct Result *averaged_full_result; /** * Array to store averaged updated solution result with length #peers */ struct Result *averaged_update_result; /** * The current result */ struct Result *current_result; /** * Current number of peers benchmarked */ int current_p; /** * Current number of addresses benchmarked */ int current_a; /** * Solver description as string */ char *ats_string; /** * Configured ATS solver */ int ats_mode; /** * #peers to start benchmarking with */ int N_peers_start; /** * #peers to end benchmarking with */ int N_peers_end; /** * #addresses to benchmarking with */ int N_address; /** * Percentage of peers to update */ int opt_update_percent; /** * Create gnuplot file */ int create_plot; /** * Measure updates */ int measure_updates; /** * Number of iterations */ int total_iterations; /** * Current iteration */ int current_iteration; /** * Is a bulk operation running? */ int bulk_running; /** * Is a bulk operation running? */ int expecting_solution; /** * Was the problem just updates? */ int performed_update; }; /** * Data structure to store results for a single iteration */ struct Iteration { /** * Head of the linked list */ struct Result *result_head; /** * Tail of the linked list */ struct Result *result_tail; }; /** * Result for a solver calculcation */ struct Result { /** * Previous element in the linked list */ struct Result *prev; /** * Next element in the linked list */ struct Result *next; /** * Number of peers this solution included */ int peers; /** * Number of addresses per peer this solution included */ int addresses; /** * Is this an update or a full solution */ int update; /** * Was the solution valid or did the solver fail */ int valid; /** * Result of the solver */ enum GAS_Solver_Additional_Information info; /** * Duration of setting up the problem in the solver */ struct GNUNET_TIME_Relative d_setup; /** * Duration of solving the LP problem in the solver * MLP solver only */ struct GNUNET_TIME_Relative d_lp; /** * Duration of solving the MLP problem in the solver * MLP solver only */ struct GNUNET_TIME_Relative d_mlp; /** * Duration of solving whole problem in the solver */ struct GNUNET_TIME_Relative d_total; /** * Start time of setting up the problem in the solver */ struct GNUNET_TIME_Absolute s_setup; /** * Start time of solving the LP problem in the solver * MLP solver only */ struct GNUNET_TIME_Absolute s_lp; /** * Start time of solving the MLP problem in the solver * MLP solver only */ struct GNUNET_TIME_Absolute s_mlp; /** * Start time of solving whole problem in the solver */ struct GNUNET_TIME_Absolute s_total; /** * End time of setting up the problem in the solver */ struct GNUNET_TIME_Absolute e_setup; /** * End time of solving the LP problem in the solver * MLP solver only */ struct GNUNET_TIME_Absolute e_lp; /** * End time of solving the MLP problem in the solver * MLP solver only */ struct GNUNET_TIME_Absolute e_mlp; /** * End time of solving whole problem in the solver */ struct GNUNET_TIME_Absolute e_total; }; /** * Peer used for the benchmarking */ struct PerfPeer { /** * Peer identitity */ struct GNUNET_PeerIdentity id; /** * Head of linked list of addresses used with this peer */ struct ATS_Address *head; /** * Head of linked list of addresses used with this peer */ struct ATS_Address *tail; }; /** * ATS performance handle */ static struct PerfHandle ph; /** * Return value */ static int ret; /** * Do shutdown */ static void end_now (int res) { if (NULL != ph.stat) { GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO); ph.stat = NULL; } GNUNET_free_non_null (ph.peers); GNUNET_free_non_null (ph.iterations_results); GNUNET_free_non_null (ph.averaged_full_result); GNUNET_free_non_null (ph.averaged_update_result); GAS_normalization_stop (); ret = res; } /** * Create a peer used for benchmarking * * @param cp the number of the peer */ static void perf_create_peer (int cp) { GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &ph.peers[cp].id, sizeof (struct GNUNET_PeerIdentity)); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating peer #%u: %s \n", cp, GNUNET_i2s (&ph.peers[cp].id)); } /** * Perform an update for an address * * @param cur the address to update */ static void perf_update_address (struct ATS_Address *cur) { int r_type; int r_val; r_type = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2); switch (r_type) { case 0: r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating peer `%s' address %p type %s val %u\n", GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DELAY", r_val); ph.env.sf.s_address_update_property (ph.solver, cur, GNUNET_ATS_QUALITY_NET_DELAY, r_val, (double) (100 + r_val / 100)); break; case 1: r_val = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating peer `%s' address %p type %s val %u\n", GNUNET_i2s (&cur->peer), cur, "GNUNET_ATS_QUALITY_NET_DISTANCE", r_val); ph.env.sf.s_address_update_property (ph.solver, cur, GNUNET_ATS_QUALITY_NET_DISTANCE, r_val, (double) (100 + r_val) / 100); break; default: break; } ph.env.sf.s_address_update_inuse (ph.solver, cur, GNUNET_YES); } static void bandwidth_changed_cb (void *cls, struct ATS_Address *address) { if ( (0 == ntohl (address->assigned_bw_out.value__)) && (0 == ntohl (address->assigned_bw_in.value__)) ) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth changed addresses %s %p to %u Bps out / %u Bps in\n", GNUNET_i2s (&address->peer), address, (unsigned int) ntohl (address->assigned_bw_out.value__), (unsigned int) ntohl (address->assigned_bw_in.value__)); if (GNUNET_YES == ph.bulk_running) GNUNET_break (0); return; } const double * get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id) { return GAS_normalization_get_preferences_by_peer (id); } const double * get_property_cb (void *cls, const struct ATS_Address *address) { return GAS_normalization_get_properties ((struct ATS_Address *) address); } static void normalized_property_changed_cb (void *cls, struct ATS_Address *peer, uint32_t type, double prop_rel) { /* TODO */ } static void perf_address_initial_update (void *solver, struct GNUNET_CONTAINER_MultiPeerMap * addresses, struct ATS_Address *address) { ph.env.sf.s_address_update_property (solver, address, GNUNET_ATS_QUALITY_NET_DELAY, 100, (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100)) / 100); ph.env.sf.s_address_update_property (solver, address, GNUNET_ATS_QUALITY_NET_DISTANCE, 10, (double) (100 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100)) / 100); } /** * Update a certain percentage of peers * * @param cp the current number of peers * @param ca the current number of addresses * @param percentage_peers the percentage of peers to update */ static void perf_update_all_addresses (unsigned int cp, unsigned int ca, unsigned int percentage_peers) { struct ATS_Address *cur_address; int c_peer; int c_select; int c_cur_p; int c_cur_a; int r; int count; unsigned int m[cp]; count = cp * ((double) percentage_peers / 100); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Updating %u of %u peers \n", count, cp); for (c_peer = 0; c_peer < cp; c_peer++) m[c_peer] = 0; c_select = 0; while (c_select < count) { r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, cp); if (0 == m[r]) { m[r] = 1; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating peer [%u] \n", r); c_select++; } } for (c_cur_p = 0; c_cur_p < cp; c_cur_p++) { if (1 == m[c_cur_p]) { r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, ca); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating peer [%u] address [%u]\n", c_cur_p, r); c_cur_a = 0; for (cur_address = ph.peers[c_cur_p].head; NULL != cur_address; cur_address = cur_address->next) { if (c_cur_a == r) perf_update_address (cur_address); c_cur_a ++; } } } } /** * Create an address for a peer * * @param cp index of the peer * @param ca index of the address * @return the address */ static struct ATS_Address * perf_create_address (int cp, int ca) { struct ATS_Address *a; a = create_address (&ph.peers[cp].id, "Test 1", "test 1", strlen ("test 1") + 1, 0); GNUNET_CONTAINER_DLL_insert (ph.peers[cp].head, ph.peers[cp].tail, a); GNUNET_CONTAINER_multipeermap_put (ph.addresses, &ph.peers[cp].id, a, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); return a; } /** * Information callback for the solver * * @param op the solver operation * @param stat status of the solver operation * @param add additional solver information */ static void solver_info_cb (void *cls, enum GAS_Solver_Operation op, enum GAS_Solver_Status stat, enum GAS_Solver_Additional_Information add) { char *add_info; switch (add) { case GAS_INFO_NONE: add_info = "GAS_INFO_NONE"; break; case GAS_INFO_FULL: add_info = "GAS_INFO_MLP_FULL"; break; case GAS_INFO_UPDATED: add_info = "GAS_INFO_MLP_UPDATED"; break; case GAS_INFO_PROP_ALL: add_info = "GAS_INFO_PROP_ALL"; break; case GAS_INFO_PROP_SINGLE: add_info = "GAS_INFO_PROP_SINGLE"; break; default: add_info = "INVALID"; break; } struct Result *tmp; switch (op) { case GAS_OP_SOLVE_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info); if (GNUNET_NO == ph.expecting_solution) { /* We do not expect a solution at the moment */ GNUNET_break (0); return; } if ((GAS_STAT_SUCCESS == stat) && (NULL == ph.current_result)) { /* Create new result */ tmp = GNUNET_new (struct Result); ph.current_result = tmp; GNUNET_CONTAINER_DLL_insert_tail(ph.iterations_results[ph.current_iteration-1].result_head, ph.iterations_results[ph.current_iteration-1].result_tail, tmp); ph.current_result->addresses = ph.current_a; ph.current_result->peers = ph.current_p; ph.current_result->s_total = GNUNET_TIME_absolute_get(); ph.current_result->d_total = GNUNET_TIME_UNIT_FOREVER_REL; ph.current_result->d_setup = GNUNET_TIME_UNIT_FOREVER_REL; ph.current_result->d_lp = GNUNET_TIME_UNIT_FOREVER_REL; ph.current_result->d_mlp = GNUNET_TIME_UNIT_FOREVER_REL; ph.current_result->info = add; if ((add == GAS_INFO_UPDATED) || (GNUNET_YES == ph.performed_update)) { ph.current_result->update = GNUNET_YES; } else { ph.current_result->update = GNUNET_NO; } } return; case GAS_OP_SOLVE_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info); if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result)) { /* We do not expect a solution at the moment */ GNUNET_break (0); return; } if (GAS_STAT_SUCCESS == stat) ph.current_result->valid = GNUNET_YES; else ph.current_result->valid = GNUNET_NO; if (NULL != ph.current_result) { /* Finalize result */ ph.current_result->e_total = GNUNET_TIME_absolute_get (); ph.current_result->d_total = GNUNET_TIME_absolute_get_difference ( ph.current_result->s_total, ph.current_result->e_total); } ph.current_result = NULL; return; case GAS_OP_SOLVE_SETUP_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result)) { GNUNET_break(0); return; } if (GAS_STAT_SUCCESS == stat) ph.current_result->valid = GNUNET_YES; else ph.current_result->valid = GNUNET_NO; ph.current_result->s_setup = GNUNET_TIME_absolute_get (); return; case GAS_OP_SOLVE_SETUP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result)) { GNUNET_break(0); return; } if (GAS_STAT_SUCCESS == stat) ph.current_result->valid = GNUNET_YES; else ph.current_result->valid = GNUNET_NO; ph.current_result->e_setup = GNUNET_TIME_absolute_get (); ph.current_result->d_setup = GNUNET_TIME_absolute_get_difference ( ph.current_result->s_setup, ph.current_result->e_setup); return; case GAS_OP_SOLVE_MLP_LP_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result)) { GNUNET_break(0); return; } if (GAS_STAT_SUCCESS == stat) ph.current_result->valid = GNUNET_YES; else ph.current_result->valid = GNUNET_NO; ph.current_result->s_lp = GNUNET_TIME_absolute_get (); return; case GAS_OP_SOLVE_MLP_LP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result)) { GNUNET_break(0); return; } if (GAS_STAT_SUCCESS == stat) ph.current_result->valid = GNUNET_YES; else ph.current_result->valid = GNUNET_NO; ph.current_result->e_lp = GNUNET_TIME_absolute_get (); ph.current_result->d_lp = GNUNET_TIME_absolute_get_difference ( ph.current_result->s_lp, ph.current_result->e_lp); return; case GAS_OP_SOLVE_MLP_MLP_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result)) { GNUNET_break(0); return; } if (GAS_STAT_SUCCESS == stat) ph.current_result->valid = GNUNET_YES; else ph.current_result->valid = GNUNET_NO; ph.current_result->s_mlp = GNUNET_TIME_absolute_get (); return; case GAS_OP_SOLVE_MLP_MLP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); if ((GNUNET_NO == ph.expecting_solution) || (NULL == ph.current_result)) { GNUNET_break(0); return; } if (GAS_STAT_SUCCESS == stat) ph.current_result->valid = GNUNET_YES; else ph.current_result->valid = GNUNET_NO; ph.current_result->e_mlp = GNUNET_TIME_absolute_get (); ph.current_result->d_mlp = GNUNET_TIME_absolute_get_difference ( ph.current_result->s_mlp, ph.current_result->e_mlp); return; case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP: GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); if (GAS_STAT_SUCCESS != stat) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Solver `%s' failed to update problem with %u peers and %u address!\n", ph.ats_string, ph.current_p, ph.current_a); } return; default: break; } } static void write_gnuplot_script (char * data_fn, int iteration, int full) { struct GNUNET_DISK_FileHandle *f; char * gfn; char *data; char *iter_text; char *template; /* Write header */ switch (ph.ats_mode) { case MODE_PROPORTIONAL: if (GNUNET_YES == full) template = GNUPLOT_PROP_TEMPLATE; else template = GNUPLOT_PROP_UPDATE_TEMPLATE; break; case MODE_MLP: if (GNUNET_YES == full) template = GNUPLOT_MLP_TEMPLATE; else template = GNUPLOT_MLP_UPDATE_TEMPLATE; break; case MODE_RIL: if (GNUNET_YES == full) template = GNUPLOT_RIL_TEMPLATE; else template = GNUPLOT_RIL_UPDATE_TEMPLATE; break; default: GNUNET_break (0); return; } if (-1 == iteration) GNUNET_asprintf (&iter_text, "%s_%u", "avg",ph.total_iterations); else GNUNET_asprintf (&iter_text, "%u", iteration); if (GNUNET_YES == full) { GNUNET_asprintf (&gfn, "perf_%s_full_%s-%u_%u_%u.gnuplot", ph.ats_string, iter_text, ph.N_peers_start, ph.N_peers_end, ph.N_address); } else { GNUNET_asprintf (&gfn, "perf_%s_updat_%s-%u_%u_%u.gnuplot", ph.ats_string, iter_text, ph.N_peers_start, ph.N_peers_end, ph.N_address); } GNUNET_free (iter_text); f = GNUNET_DISK_file_open (gfn, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn); GNUNET_free (gfn); return; } if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, template, strlen(template))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); data = NULL; if (MODE_PROPORTIONAL == ph.ats_mode) { GNUNET_asprintf (&data, "plot '%s' using 1:%u with lines title 'Total time to solve'\n" \ "pause -1", data_fn, 3); } else if (MODE_MLP == ph.ats_mode) { GNUNET_asprintf (&data, "plot '%s' using 1:%u with lines title 'Total time to solve',\\\n" \ "'%s' using 1:%u with lines title 'Time to setup',\\\n" "'%s' using 1:%u with lines title 'Time to solve LP',\\\n" "'%s' using 1:%u with lines title 'Total time to solve MLP'\n" \ "pause -1", data_fn, 3, data_fn, 4, data_fn, 5, data_fn, 6); } else if (MODE_RIL == ph.ats_mode) { GNUNET_asprintf (&data, "plot '%s' using 1:%u with lines title 'Total time to solve'\n" \ "pause -1", data_fn, 3); } if ((NULL != data) && (GNUNET_SYSERR == GNUNET_DISK_file_write (f, data, strlen(data)))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); GNUNET_free_non_null (data); if (GNUNET_SYSERR == GNUNET_DISK_file_close(f)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn); GNUNET_free (gfn); } /** * Evaluate results for a specific iteration * * @param iteration the iteration to evaluate */ static void evaluate (int iteration) { struct GNUNET_DISK_FileHandle *f_full; struct GNUNET_DISK_FileHandle *f_update; char * data_fn_full; char * data_fn_update; char * data; struct Result *cur; struct Result *next; struct Result *cur_res; char * str_d_total; char * str_d_setup; char * str_d_lp; char * str_d_mlp; char * iter_text; f_full = NULL; f_update = NULL; data_fn_full = NULL; if (ph.create_plot) { if (-1 == iteration) GNUNET_asprintf (&iter_text, "%s", "avg"); else GNUNET_asprintf (&iter_text, "%u", iteration); GNUNET_asprintf (&data_fn_full, "perf_%s_full_%s_%u_%u_%u.data", ph.ats_string, iter_text, ph.N_peers_start, ph.N_peers_end, ph.N_address); GNUNET_free (iter_text); f_full = GNUNET_DISK_file_open (data_fn_full, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f_full) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", data_fn_full); GNUNET_free (data_fn_full); return; } data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n"; if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_full, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", data_fn_full); write_gnuplot_script (data_fn_full, iteration, GNUNET_YES); } data_fn_update = NULL; if ((ph.create_plot) && (GNUNET_YES == ph.measure_updates)) { if (-1 == iteration) GNUNET_asprintf (&iter_text, "%s", "avg"); else GNUNET_asprintf (&iter_text, "%u", iteration); GNUNET_asprintf (&data_fn_update, "perf_%s_update_i%u_%u_%u_%u.data", ph.ats_string, iter_text, ph.N_peers_start, ph.N_peers_end, ph.N_address); GNUNET_free (iter_text); f_update = GNUNET_DISK_file_open (data_fn_update, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f_update) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", data_fn_update); GNUNET_free (data_fn_update); if (NULL != f_full) GNUNET_DISK_file_close (f_full); GNUNET_free (data_fn_full); return; } data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n"; if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", data_fn_update); write_gnuplot_script (data_fn_update, iteration, GNUNET_NO); } next = ph.iterations_results[ph.current_iteration -1].result_head; while (NULL != (cur = next)) { next = cur->next; str_d_total = NULL; str_d_setup = NULL; str_d_lp = NULL; str_d_mlp = NULL; /* Print log */ if (GNUNET_NO == cur->update) { cur_res = &ph.averaged_full_result[cur->peers - ph.N_peers_start]; } else { cur_res = &ph.averaged_update_result[cur->peers - ph.N_peers_start]; } cur_res->peers = cur->peers; cur_res->addresses = cur->addresses; cur_res->update = cur->update; if (GNUNET_NO == cur->valid) { fprintf (stderr, "Total time to solve %s for %u peers %u addresses: %s\n", (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses, "Failed to solve!"); continue; } else cur_res->valid ++; if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_total.rel_value_us) { if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == cur_res->d_total.rel_value_us) cur_res->d_total.rel_value_us = 0; if (GNUNET_YES == cur->valid) cur_res->d_total.rel_value_us += cur->d_total.rel_value_us; fprintf (stderr, "Total time to solve %s for %u peers %u addresses: %llu us\n", (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses, (unsigned long long) cur->d_total.rel_value_us); GNUNET_asprintf(&str_d_total, "%llu", (unsigned long long) cur->d_total.rel_value_us); } else GNUNET_asprintf(&str_d_total, "-1"); if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_setup.rel_value_us) { if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == cur_res->d_setup.rel_value_us) cur_res->d_setup.rel_value_us = 0; if (GNUNET_YES == cur->valid) cur_res->d_setup.rel_value_us += cur->d_setup.rel_value_us; fprintf (stderr, "Total time to setup %s %u peers %u addresses: %llu us\n", (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses, (unsigned long long) cur->d_setup.rel_value_us); GNUNET_asprintf(&str_d_setup, "%llu", (unsigned long long )cur->d_setup.rel_value_us); } else GNUNET_asprintf(&str_d_setup, "-1"); if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_lp.rel_value_us) { if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == cur_res->d_lp.rel_value_us) cur_res->d_lp.rel_value_us = 0; if (GNUNET_YES == cur->valid) cur_res->d_lp.rel_value_us += cur->d_lp.rel_value_us; fprintf (stderr, "Total time to solve %s LP for %u peers %u addresses: %llu us\n", (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses, (unsigned long long )cur->d_lp.rel_value_us); GNUNET_asprintf (&str_d_lp, "%llu", (unsigned long long )cur->d_lp.rel_value_us); } else GNUNET_asprintf (&str_d_lp, "-1"); if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_mlp.rel_value_us) { if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == cur_res->d_mlp.rel_value_us) cur_res->d_mlp.rel_value_us = 0; if (GNUNET_YES == cur->valid) cur_res->d_mlp.rel_value_us += cur->d_mlp.rel_value_us; fprintf (stderr, "Total time to solve %s MLP for %u peers %u addresses: %llu us\n", (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses, (unsigned long long )cur->d_mlp.rel_value_us); GNUNET_asprintf (&str_d_mlp, "%llu", (unsigned long long )cur->d_mlp.rel_value_us); } else GNUNET_asprintf (&str_d_mlp, "-1"); data = NULL; if (GNUNET_YES == ph.create_plot) { GNUNET_asprintf (&data, "%u;%u;%s;%s;%s;%s\n", cur->peers, cur->addresses, str_d_total, str_d_setup, str_d_lp, str_d_mlp); if (cur->update == GNUNET_NO) { if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", data_fn_full); } if ((cur->update == GNUNET_YES) && (NULL != f_update)) { if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", data_fn_update); } GNUNET_free (data); } GNUNET_free_non_null (str_d_total); GNUNET_free_non_null (str_d_setup); GNUNET_free_non_null (str_d_lp); GNUNET_free_non_null (str_d_mlp); GNUNET_CONTAINER_DLL_remove (ph.iterations_results[ph.current_iteration-1].result_head, ph.iterations_results[ph.current_iteration-1].result_tail, cur); GNUNET_free (cur); } if ((NULL != f_full) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_full))) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n", data_fn_full); GNUNET_free_non_null (data_fn_full); if ((NULL != f_update) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_update))) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n", data_fn_update); GNUNET_free_non_null (data_fn_update); } /** * Evaluate average results for all iterations */ static void evaluate_average (void) { int c_o; int c_i; struct GNUNET_DISK_FileHandle *f_full; struct GNUNET_DISK_FileHandle *f_update; struct Result *cur; char * data_fn_full; char * data_fn_update; char * data; char * str_d_total; char * str_d_setup; char * str_d_lp; char * str_d_mlp; f_full = NULL; f_update = NULL; data_fn_full = NULL; if (ph.create_plot) { GNUNET_asprintf (&data_fn_full, "perf_%s_full_avg_%u-%u_%u_%u.data", ph.ats_string, ph.total_iterations, ph.N_peers_start, ph.N_peers_end, ph.N_address); f_full = GNUNET_DISK_file_open (data_fn_full, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f_full) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", data_fn_full); GNUNET_free (data_fn_full); return; } data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n"; if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_full, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", data_fn_full); write_gnuplot_script (data_fn_full, -1, GNUNET_YES); } data_fn_update = NULL; if ((ph.create_plot) && (GNUNET_YES == ph.measure_updates)) { GNUNET_asprintf (&data_fn_update, "perf_%s_update_avg_%u-%u_%u_%u.data", ph.ats_string, ph.total_iterations, ph.N_peers_start, ph.N_peers_end, ph.N_address); f_update = GNUNET_DISK_file_open (data_fn_update, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f_update) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", data_fn_update); GNUNET_free (data_fn_update); if (NULL != f_full) GNUNET_DISK_file_close (f_full); GNUNET_free (data_fn_full); return; } data = "#peers;addresses;time total in us;#time setup in us;#time lp in us;#time mlp in us;\n"; if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", data_fn_update); write_gnuplot_script (data_fn_update, -1, GNUNET_NO); } for (c_o = 0; c_o < 2; c_o++) { if (0 == c_o) fprintf (stderr, "Duration for a full solution averaged over %i iterations\n", ph.total_iterations); if (1 == c_o) fprintf (stderr, "Duration for a full solution averaged over %i iterations\n", ph.total_iterations); for (c_i = 0; c_i <= ph.N_peers_end - ph.N_peers_start; c_i++) { if (0 == c_o) { cur = &ph.averaged_full_result[c_i]; } else if ((GNUNET_YES == ph.measure_updates) && (1 == c_o)) { cur = &ph.averaged_update_result[c_i]; } else break; if (0 == cur->peers) continue; str_d_total = NULL; str_d_setup = NULL; str_d_lp = NULL; str_d_mlp = NULL; if (0 >= cur->valid) { fprintf (stderr, "No valid results for %s for %u peers %u addresses!\n", (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses); continue; } if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_total.rel_value_us) { fprintf (stderr, "Average total time from %u iterations to solve %s for %u peers %u addresses: %llu us\n", cur->valid, (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses, (unsigned long long) cur->d_total.rel_value_us / cur->valid); GNUNET_asprintf(&str_d_total, "%llu", (unsigned long long) cur->d_total.rel_value_us / cur->valid); } else GNUNET_asprintf (&str_d_total, "-1"); if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_setup.rel_value_us) { fprintf (stderr, "Average total time from %u iterations to setup for %u peers %u addresses: %llu us\n", cur->valid, cur->peers, cur->addresses, (unsigned long long) cur->d_setup.rel_value_us / cur->valid); GNUNET_asprintf(&str_d_setup, "%llu", (unsigned long long) cur->d_setup.rel_value_us / cur->valid); } else GNUNET_asprintf (&str_d_setup, "-1"); if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_lp.rel_value_us) { fprintf (stderr, "Average total time from %u iterations to solve lp %s for %u peers %u addresses: %llu us\n", cur->valid, (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses, (unsigned long long) cur->d_lp.rel_value_us / cur->valid); GNUNET_asprintf(&str_d_lp, "%llu", (unsigned long long) cur->d_lp.rel_value_us / ph.total_iterations); } else GNUNET_asprintf (&str_d_lp, "-1"); if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != cur->d_mlp.rel_value_us) { fprintf (stderr, "Average total time from %u iterations to solve mlp %s for %u peers %u addresses: %llu us\n", cur->valid, (GNUNET_YES == cur->update) ? "updated" : "full", cur->peers, cur->addresses, (unsigned long long) cur->d_mlp.rel_value_us / cur->valid); GNUNET_asprintf(&str_d_mlp, "%llu", (unsigned long long) cur->d_mlp.rel_value_us / cur->valid); } else GNUNET_asprintf (&str_d_mlp, "-1"); data = NULL; if (GNUNET_YES == ph.create_plot) { GNUNET_asprintf (&data, "%u;%u;%s;%s;%s;%s\n", cur->peers, cur->addresses, str_d_total, str_d_setup, str_d_lp, str_d_mlp); if (cur->update == GNUNET_NO) { if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_full, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", data_fn_full); } if ((cur->update == GNUNET_YES) && (NULL != f_update)) { if (GNUNET_SYSERR == GNUNET_DISK_file_write (f_update, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", data_fn_update); } GNUNET_free (data); } GNUNET_free_non_null (str_d_total); GNUNET_free_non_null (str_d_setup); GNUNET_free_non_null (str_d_lp); GNUNET_free_non_null (str_d_mlp); } } if ((NULL != f_full) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_full))) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n", data_fn_full); GNUNET_free_non_null (data_fn_full); if ((NULL != f_update) && (GNUNET_SYSERR == GNUNET_DISK_file_close (f_update))) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n", data_fn_update); GNUNET_free_non_null (data_fn_update); } /** * Run a performance iteration */ static void perf_run_iteration (void) { struct ATS_Address *cur; struct ATS_Address *next; int cp; int ca; int count_p = ph.N_peers_end; int count_a = ph.N_address; struct ATS_Address * cur_addr; ph.peers = GNUNET_malloc ((count_p) * sizeof (struct PerfPeer)); for (cp = 0; cp < count_p; cp++) perf_create_peer (cp); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Iteration %u of %u, added %u peers\n", ph.current_iteration, ph.total_iterations, cp); for (cp = 0; cp < count_p; cp++) { if (GNUNET_NO == ph.bulk_running) { ph.bulk_running = GNUNET_YES; ph.env.sf.s_bulk_start (ph.solver); } ph.current_p = cp + 1; for (ca = 0; ca < count_a; ca++) { cur_addr = perf_create_address (cp, ca); /* Add address */ ph.env.sf.s_add (ph.solver, cur_addr, GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_ATS_NetworkTypeCount)); ph.current_a = ca + 1; perf_address_initial_update (ph.solver, ph.addresses, cur_addr); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Adding address for peer %u address %u\n", cp, ca); } /* Notify solver about request */ ph.env.sf.s_get (ph.solver, &ph.peers[cp].id); if (cp + 1 >= ph.N_peers_start) { /* Disable bulk to solve the problem */ if (GNUNET_YES == ph.bulk_running) { ph.expecting_solution = GNUNET_YES; ph.bulk_running = GNUNET_NO; ph.env.sf.s_bulk_stop (ph.solver); } else GNUNET_break (0); /* Problem is solved by the solver here due to unlocking */ ph.expecting_solution = GNUNET_NO; /* Update the problem */ if ((0 < ph.opt_update_percent) && (GNUNET_YES == ph.measure_updates)) { /* Update */ GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Updating problem with %u peers and %u addresses\n", cp + 1, ca); ph.expecting_solution = GNUNET_YES; ph.performed_update = GNUNET_YES; if (GNUNET_NO == ph.bulk_running) { ph.bulk_running = GNUNET_YES; ph.env.sf.s_bulk_start (ph.solver); } perf_update_all_addresses (cp + 1, ca, ph.opt_update_percent); ph.bulk_running = GNUNET_NO; ph.env.sf.s_bulk_stop (ph.solver); /* Problem is solved by the solver here due to unlocking */ ph.performed_update = GNUNET_NO; ph.expecting_solution = GNUNET_NO; } GNUNET_assert (GNUNET_NO == ph.bulk_running); } } GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Done, cleaning up addresses\n"); if (GNUNET_NO == ph.bulk_running) { ph.env.sf.s_bulk_start (ph.solver); ph.bulk_running = GNUNET_YES; } for (cp = 0; cp < count_p; cp++) { for (cur = ph.peers[cp].head; cur != NULL ; cur = next) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Deleting addresses for peer %u\n", cp); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (ph.addresses, &ph.peers[cp].id, cur)); ph.env.sf.s_del (ph.solver, cur, GNUNET_NO); next = cur->next; GNUNET_CONTAINER_DLL_remove(ph.peers[cp].head, ph.peers[cp].tail, cur); GNUNET_free(cur); } } GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Iteration done\n"); GNUNET_free(ph.peers); } static void run (void *cls, char * const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_log_setup ("perf-ats-solver", "WARNING", NULL); char *sep; char *src_filename = GNUNET_strdup (__FILE__); char *test_filename = cls; char *solver; char *plugin; struct GNUNET_CONFIGURATION_Handle *solver_cfg; unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount]; unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount]; int c; /* Extract test name */ if (NULL == (sep = (strstr (src_filename,".c")))) { GNUNET_free (src_filename); GNUNET_break (0); ret = 1; return ; } sep[0] = '\0'; if (NULL != (sep = strstr (test_filename, ".exe"))) sep[0] = '\0'; if (NULL == (solver = strstr (test_filename, src_filename))) { GNUNET_free (src_filename); GNUNET_break (0); ret = 1; return ; } solver += strlen (src_filename) +1; if (0 == strcmp(solver, "proportional")) { ph.ats_mode = MODE_PROPORTIONAL; ph.ats_string = "proportional"; } else if (0 == strcmp(solver, "mlp")) { ph.ats_mode = MODE_MLP; ph.ats_string = "mlp"; } else if ((0 == strcmp(solver, "ril"))) { ph.ats_mode = MODE_RIL; ph.ats_string = "ril"; } else { GNUNET_free (src_filename); GNUNET_break (0); ret = 1; return ; } GNUNET_free (src_filename); /* Calculcate peers */ if ((0 == ph.N_peers_start) && (0 == ph.N_peers_end)) { ph.N_peers_start = DEFAULT_PEERS_START; ph.N_peers_end = DEFAULT_PEERS_END; } if (0 == ph.N_address) ph.N_address = DEFAULT_ADDRESSES; if (ph.N_peers_start != ph.N_peers_end) fprintf (stderr, "Benchmarking solver `%s' with %u to %u peers and %u addresses in %u iterations\n", ph.ats_string, ph.N_peers_start, ph.N_peers_end, ph.N_address, ph.total_iterations); else fprintf (stderr, "Benchmarking solver `%s' with %u peers and %u addresses in %u iterations\n", ph.ats_string, ph.N_peers_end, ph.N_address, ph.total_iterations); if (0 == ph.opt_update_percent) ph.opt_update_percent = DEFAULT_UPDATE_PERCENTAGE; /* Load quotas */ solver_cfg = GNUNET_CONFIGURATION_create(); if ((NULL == solver_cfg) || (GNUNET_SYSERR == (GNUNET_CONFIGURATION_load ( solver_cfg, "perf_ats_solver.conf")))) { GNUNET_break(0); end_now (1); return; } if (GNUNET_ATS_NetworkTypeCount != load_quotas (solver_cfg, quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount)) { GNUNET_break(0); end_now (1); return; } /* Create array of DLL to store results for iterations */ ph.iterations_results = GNUNET_malloc (sizeof (struct Iteration) * ph.total_iterations); ph.averaged_full_result = GNUNET_malloc (sizeof (struct Result) * ((ph.N_peers_end + 1) - ph.N_peers_start)); for (c = 0; c <= ph.N_peers_end - ph.N_peers_start; c++) { ph.averaged_full_result[c].d_setup = GNUNET_TIME_UNIT_FOREVER_REL; ph.averaged_full_result[c].d_total = GNUNET_TIME_UNIT_FOREVER_REL; ph.averaged_full_result[c].d_lp = GNUNET_TIME_UNIT_FOREVER_REL; ph.averaged_full_result[c].d_mlp = GNUNET_TIME_UNIT_FOREVER_REL; } ph.averaged_update_result = GNUNET_malloc (sizeof (struct Result) * ((ph.N_peers_end + 1) - ph.N_peers_start)); for (c = 0; c <= ph.N_peers_end - ph.N_peers_start; c++) { ph.averaged_update_result[c].d_setup = GNUNET_TIME_UNIT_FOREVER_REL; ph.averaged_update_result[c].d_total = GNUNET_TIME_UNIT_FOREVER_REL; ph.averaged_update_result[c].d_lp = GNUNET_TIME_UNIT_FOREVER_REL; ph.averaged_update_result[c].d_mlp = GNUNET_TIME_UNIT_FOREVER_REL; } /* Load solver */ ph.env.cfg = solver_cfg; ph.stat = GNUNET_STATISTICS_create ("ats", cfg); ph.env.stats = ph.stat; ph.addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); ph.env.addresses = ph.addresses; ph.env.bandwidth_changed_cb = bandwidth_changed_cb; ph.env.get_preferences = &get_preferences_cb; ph.env.get_property = &get_property_cb; ph.env.network_count = GNUNET_ATS_NetworkTypeCount; ph.env.info_cb = &solver_info_cb; ph.env.info_cb_cls = NULL; int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType; for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { ph.env.networks[c] = networks[c]; ph.env.out_quota[c] = quotas_out[c]; ph.env.in_quota[c] = quotas_in[c]; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loading network quotas: `%s' %llu %llu \n", GNUNET_ATS_print_network_type(ph.env.networks[c]), ph.env.out_quota[c], ph.env.in_quota[c]); } GAS_normalization_start (NULL, NULL, &normalized_property_changed_cb, NULL ); GNUNET_asprintf (&plugin, "libgnunet_plugin_ats_%s", ph.ats_string); GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initializing solver `%s'\n"), ph.ats_string); if (NULL == (ph.solver = GNUNET_PLUGIN_load (plugin, &ph.env))) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver `%s'!\n"), plugin); ret = 1; return; } /* Do the benchmark */ for (ph.current_iteration = 1; ph.current_iteration <= ph.total_iterations; ph.current_iteration++) { perf_run_iteration (); evaluate (ph.current_iteration); } evaluate_average (); /* Unload solver*/ GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Unloading solver `%s'\n"), ph.ats_string); GNUNET_PLUGIN_unload (plugin, ph.solver); GNUNET_free (plugin); GNUNET_free (ph.iterations_results); GNUNET_free (ph.averaged_full_result); GNUNET_free (ph.averaged_update_result); GNUNET_CONFIGURATION_destroy (solver_cfg); GNUNET_STATISTICS_destroy (ph.stat, GNUNET_NO); ph.solver = NULL; } /** * Main function of the benchmark * * @param argc argument count * @param argv argument values */ int main (int argc, char *argv[]) { /* extract command line arguments */ ph.opt_update_percent = 0; ph.N_peers_start = 0; ph.N_peers_end = 0; ph.N_address = 0; ph.ats_string = NULL; ph.create_plot = GNUNET_NO; ph.measure_updates = GNUNET_NO; ph.total_iterations = 1; static struct GNUNET_GETOPT_CommandLineOption options[] = { { 'a', "addresses", NULL, gettext_noop ("addresses to use"), 1, &GNUNET_GETOPT_set_uint, &ph.N_address }, { 's', "start", NULL, gettext_noop ("start with peer"), 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_start }, { 'e', "end", NULL, gettext_noop ("end with peer"), 1, &GNUNET_GETOPT_set_uint, &ph.N_peers_end }, { 'i', "iterations", NULL, gettext_noop ("number of iterations used for averaging (default: 1)"), 1, &GNUNET_GETOPT_set_uint, &ph.total_iterations }, { 'p', "percentage", NULL, gettext_noop ("update a fix percentage of addresses"), 1, &GNUNET_GETOPT_set_uint, &ph.opt_update_percent }, { 'g', "gnuplot", NULL, gettext_noop ("create GNUplot file"), 0, &GNUNET_GETOPT_set_one, &ph.create_plot}, { 'u', "update", NULL, gettext_noop ("measure updates"), 0, &GNUNET_GETOPT_set_one, &ph.measure_updates}, GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]); return ret; } /* end of file perf_ats_solver.c */ gnunet-0.10.1/src/ats/test_ats_api_scheduling_add_session.c0000644000175000017500000001347312263724143021007 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_scheduling_add_session.c * @brief test adding a session to an existing addresses * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { static int first_stat_cb = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if ((GNUNET_YES == first_stat_cb) && (1 == value)) { GNUNET_ATS_address_add (sched_ats, &test_hello_address, (struct Session *) &test_session, test_ats_info, test_ats_count); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &end, NULL); } if ((GNUNET_NO == first_stat_cb) && (1 == value)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS updated existing address\n"); } if (value > 1) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ATS did not update existing address, but added 2nd address!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); } return GNUNET_OK; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, NULL, test_ats_info, test_ats_count); } int main (int argc, char *argv[]) { ret = 0; if (0 != GNUNET_TESTING_peer_run ("test-ats-api", "test_ats_api.conf", &run, NULL)) return 1; return ret; } /* end of file test_ats_api_scheduling_add_session.c */ gnunet-0.10.1/src/ats/test_ats_api_scheduling_destroy_address_twice.c0000644000175000017500000001445712263724143023110 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_scheduling_destroy_address.c * @brief test destroying addresses in automatic transport selection scheduling API * @author Christian Grothoff * @author Matthias Wachs * */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { static int initial_ats_stat_cb = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if ((0 == value) && (initial_ats_stat_cb == GNUNET_NO)) { fprintf (stderr, "We now expect a warning about destroying an unknown address...\n"); GNUNET_ATS_address_destroyed (sched_ats, &test_hello_address, test_session); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &end, NULL); } if ((0 == value) && (initial_ats_stat_cb == GNUNET_YES)) { initial_ats_stat_cb = GNUNET_NO; } if (1 == value) { GNUNET_ATS_address_destroyed (sched_ats, &test_hello_address, test_session); } return GNUNET_OK; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static int dummy_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got dummy stat %s%s:%s = %llu\n", is_persistent ? "!" : " ", subsystem, name, value); return GNUNET_OK; } static void got_initial_value (void *cls, int success) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got initial value\n"); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); GNUNET_STATISTICS_get (stats, "ats", "# addresses", TIMEOUT, &got_initial_value, &dummy_stat, GNUNET_CONFIGURATION_dup (cfg)); } int main (int argc, char *argv[]) { ret = 0; if (0 != GNUNET_TESTING_peer_run ("test-ats-api", "test_ats_api.conf", &run, NULL)) return 1; return ret; } /* end of file test_ats_api_scheduling_destroy_address.c */ gnunet-0.10.1/src/ats/ats_api_performance.c0000644000175000017500000006402612255010512015536 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/ats_api_performance.c * @brief automatic transport selection and outbound bandwidth determination * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "ats.h" /** * Message in linked list we should send to the ATS service. The * actual binary message follows this struct. */ struct PendingMessage { /** * Kept in a DLL. */ struct PendingMessage *next; /** * Kept in a DLL. */ struct PendingMessage *prev; /** * Size of the message. */ size_t size; /** * Is this the 'ATS_START' message? */ int is_init; }; /** * Linked list of pending reservations. */ struct GNUNET_ATS_ReservationContext { /** * Kept in a DLL. */ struct GNUNET_ATS_ReservationContext *next; /** * Kept in a DLL. */ struct GNUNET_ATS_ReservationContext *prev; /** * Target peer. */ struct GNUNET_PeerIdentity peer; /** * Desired reservation */ int32_t size; /** * Function to call on result. */ GNUNET_ATS_ReservationCallback rcb; /** * Closure for 'rcb' */ void *rcb_cls; /** * Do we need to undo this reservation if it succeeded? Set to * GNUNET_YES if a reservation is cancelled. (at that point, 'info' * is also set to NULL; however, info will ALSO be NULL for the * reservation context that is created to undo the original request, * so 'info' being NULL cannot be used to check if undo is * required). */ int undo; }; /** * Linked list of pending reservations. */ struct GNUNET_ATS_AddressListHandle { /** * Kept in a DLL. */ struct GNUNET_ATS_AddressListHandle *next; /** * Kept in a DLL. */ struct GNUNET_ATS_AddressListHandle *prev; /** * Performance handle */ struct GNUNET_ATS_PerformanceHandle *ph; /** * Callback */ GNUNET_ATS_AddressInformationCallback cb; /** * Callback closure */ void *cb_cls; /** * Target peer. */ struct GNUNET_PeerIdentity peer; /** * Return all or specific peer only */ int all_peers; /** * Return all or used address only */ int all_addresses; /** * Request multiplexing */ uint32_t id; }; /** * ATS Handle to obtain and/or modify performance information. */ struct GNUNET_ATS_PerformanceHandle { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Callback to invoke when an address has performance changes. */ GNUNET_ATS_AddressInformationCallback addr_info_cb; /** * Closure for 'addr_info_cb'. */ void *addr_info_cb_cls; /** * Connection to ATS service. */ struct GNUNET_CLIENT_Connection *client; /** * Head of list of messages for the ATS service. */ struct PendingMessage *pending_head; /** * Tail of list of messages for the ATS service */ struct PendingMessage *pending_tail; /** * Head of linked list of pending reservation requests. */ struct GNUNET_ATS_ReservationContext *reservation_head; /** * Tail of linked list of pending reservation requests. */ struct GNUNET_ATS_ReservationContext *reservation_tail; /** * Head of linked list of pending address list requests. */ struct GNUNET_ATS_AddressListHandle *addresslist_head; /** * Tail of linked list of pending address list requests. */ struct GNUNET_ATS_AddressListHandle *addresslist_tail; /** * Current request for transmission to ATS. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Task to trigger reconnect. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Monitor request multiplexing */ uint32_t monitor_id; /** * Request multiplexing */ uint32_t id; }; /** * Re-establish the connection to the ATS service. * * @param ph handle to use to re-connect. */ static void reconnect (struct GNUNET_ATS_PerformanceHandle *ph); /** * Re-establish the connection to the ATS service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_ATS_PerformanceHandle *ph = cls; ph->task = GNUNET_SCHEDULER_NO_TASK; reconnect (ph); } /** * Transmit messages from the message queue to the service * (if there are any, and if we are not already trying). * * @param ph handle to use */ static void do_transmit (struct GNUNET_ATS_PerformanceHandle *ph); /** * Type of a function to call when we receive a message * from the service. * * @param cls the 'struct GNUNET_ATS_SchedulingHandle' * @param msg message received, NULL on timeout or fatal error */ static void process_ats_message (void *cls, const struct GNUNET_MessageHeader *msg); /** * We can now transmit a message to ATS. Do it. * * @param cls the 'struct GNUNET_ATS_SchedulingHandle' * @param size number of bytes we can transmit to ATS * @param buf where to copy the messages * @return number of bytes copied into buf */ static size_t transmit_message_to_ats (void *cls, size_t size, void *buf) { struct GNUNET_ATS_PerformanceHandle *ph = cls; struct PendingMessage *p; size_t ret; char *cbuf; ph->th = NULL; ret = 0; cbuf = buf; while ((NULL != (p = ph->pending_head)) && (p->size <= size)) { memcpy (&cbuf[ret], &p[1], p->size); ret += p->size; size -= p->size; GNUNET_CONTAINER_DLL_remove(ph->pending_head, ph->pending_tail, p); GNUNET_free(p); } do_transmit (ph); return ret; } /** * Transmit messages from the message queue to the service * (if there are any, and if we are not already trying). * * @param ph handle to use */ static void do_transmit (struct GNUNET_ATS_PerformanceHandle *ph) { struct PendingMessage *p; if (NULL != ph->th) return; if (NULL == (p = ph->pending_head)) return; if (NULL == ph->client) return; /* currently reconnecting */ ph->th = GNUNET_CLIENT_notify_transmit_ready (ph->client, p->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_message_to_ats, ph); } /** * We received a peer information message. Validate and process it. * * @param ph our context with the callback * @param msg the message * @return GNUNET_OK if the message was well-formed */ static int process_pi_message (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_MessageHeader *msg) { const struct PeerInformationMessage *pi; const struct GNUNET_ATS_Information *atsi; const char *plugin_address; const char *plugin_name; struct GNUNET_HELLO_Address address; uint16_t plugin_address_length; uint16_t plugin_name_length; uint32_t ats_count; int addr_active; if (ntohs (msg->size) < sizeof(struct PeerInformationMessage)) { GNUNET_break(0); return GNUNET_SYSERR; } pi = (const struct PeerInformationMessage *) msg; ats_count = ntohl (pi->ats_count); plugin_address_length = ntohs (pi->address_length); plugin_name_length = ntohs (pi->plugin_name_length); addr_active = ntohl (pi->address_active); atsi = (const struct GNUNET_ATS_Information *) &pi[1]; plugin_address = (const char *) &atsi[ats_count]; plugin_name = &plugin_address[plugin_address_length]; if ((plugin_address_length + plugin_name_length + ats_count * sizeof(struct GNUNET_ATS_Information) + sizeof(struct PeerInformationMessage) != ntohs (msg->size)) || (ats_count > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_ATS_Information)) || (plugin_name[plugin_name_length - 1] != '\0')) { GNUNET_break(0); return GNUNET_SYSERR; } if (NULL != ph->addr_info_cb) { address.peer = pi->peer; address.address = plugin_address; address.address_length = plugin_address_length; address.transport_name = plugin_name; ph->addr_info_cb (ph->addr_info_cb_cls, &address, addr_active, pi->bandwidth_out, pi->bandwidth_in, atsi, ats_count); } return GNUNET_OK; } /** * We received a reservation result message. Validate and process it. * * @param ph our context with the callback * @param msg the message * @return GNUNET_OK if the message was well-formed */ static int process_rr_message (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_MessageHeader *msg) { const struct ReservationResultMessage *rr; struct GNUNET_ATS_ReservationContext *rc; int32_t amount; if (ntohs (msg->size) < sizeof(struct ReservationResultMessage)) { GNUNET_break(0); return GNUNET_SYSERR; } rr = (const struct ReservationResultMessage *) msg; amount = ntohl (rr->amount); rc = ph->reservation_head; if (0 != memcmp (&rr->peer, &rc->peer, sizeof(struct GNUNET_PeerIdentity))) { GNUNET_break(0); return GNUNET_SYSERR; } GNUNET_CONTAINER_DLL_remove(ph->reservation_head, ph->reservation_tail, rc); if ((amount == 0) || (rc->rcb != NULL )) { /* tell client if not cancelled */ if (rc->rcb != NULL ) rc->rcb (rc->rcb_cls, &rr->peer, amount, GNUNET_TIME_relative_ntoh (rr->res_delay)); GNUNET_free(rc); return GNUNET_OK; } /* amount non-zero, but client cancelled, consider undo! */ if (GNUNET_YES != rc->undo) { GNUNET_free(rc); return GNUNET_OK; /* do not try to undo failed undos or negative amounts */ } GNUNET_free(rc); (void) GNUNET_ATS_reserve_bandwidth (ph, &rr->peer, -amount, NULL, NULL ); return GNUNET_OK; } /** * We received a reservation result message. Validate and process it. * * @param ph our context with the callback * @param msg the message * @return GNUNET_OK if the message was well-formed */ static int process_ar_message (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_MessageHeader *msg) { const struct PeerInformationMessage *pi; struct GNUNET_ATS_AddressListHandle *alh; struct GNUNET_ATS_AddressListHandle *next; const struct GNUNET_ATS_Information *atsi; const char *plugin_address; const char *plugin_name; struct GNUNET_HELLO_Address address; struct GNUNET_PeerIdentity allzeros; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero; uint16_t plugin_address_length; uint16_t plugin_name_length; uint32_t ats_count; uint32_t active; uint32_t id; if (ntohs (msg->size) < sizeof(struct PeerInformationMessage)) { GNUNET_break(0); return GNUNET_SYSERR; } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Received %s message\n"), "ATS_ADDRESSLIST_RESPONSE"); pi = (const struct PeerInformationMessage *) msg; id = ntohl (pi->id); ats_count = ntohl (pi->ats_count); active = ntohl (pi->address_active); plugin_address_length = ntohs (pi->address_length); plugin_name_length = ntohs (pi->plugin_name_length); atsi = (const struct GNUNET_ATS_Information *) &pi[1]; plugin_address = (const char *) &atsi[ats_count]; plugin_name = &plugin_address[plugin_address_length]; if ((plugin_address_length + plugin_name_length + ats_count * sizeof(struct GNUNET_ATS_Information) + sizeof(struct PeerInformationMessage) != ntohs (msg->size)) || (ats_count > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof(struct GNUNET_ATS_Information)) || (plugin_name[plugin_name_length - 1] != '\0')) { GNUNET_break(0); return GNUNET_SYSERR; } next = ph->addresslist_head; while (NULL != (alh = next)) { next = alh->next; if (alh->id == id) break; } if (NULL == alh) { /* was canceled */ return GNUNET_SYSERR; } memset (&allzeros, '\0', sizeof(allzeros)); if ((0 == memcmp (&allzeros, &pi->peer, sizeof(allzeros))) && (0 == plugin_name_length) && (0 == plugin_address_length) && (0 == ats_count)) { /* Done */ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Received last message for %s \n"), "ATS_ADDRESSLIST_RESPONSE"); bandwidth_zero.value__ = htonl (0); if (NULL != alh->cb) alh->cb (ph->addr_info_cb_cls, NULL, GNUNET_NO, bandwidth_zero, bandwidth_zero, NULL, 0); GNUNET_CONTAINER_DLL_remove(ph->addresslist_head, ph->addresslist_tail, alh); GNUNET_free(alh); return GNUNET_OK; } address.peer = pi->peer; address.address = plugin_address; address.address_length = plugin_address_length; address.transport_name = plugin_name; if ((GNUNET_YES == alh->all_addresses) || (GNUNET_YES == active)) { if (NULL != alh->cb) alh->cb (ph->addr_info_cb_cls, &address, active, pi->bandwidth_out, pi->bandwidth_in, atsi, ats_count); } return GNUNET_OK; } /** * Type of a function to call when we receive a message * from the service. * * @param cls the 'struct GNUNET_ATS_SchedulingHandle' * @param msg message received, NULL on timeout or fatal error */ static void process_ats_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_ATS_PerformanceHandle *ph = cls; if (NULL == msg) goto reconnect; switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION: if (GNUNET_OK != process_pi_message (ph, msg)) goto reconnect; break; case GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT: if (GNUNET_OK != process_rr_message (ph, msg)) goto reconnect; break; case GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE: if (GNUNET_OK != process_ar_message (ph, msg)) goto reconnect; break; default: GNUNET_break(0); goto reconnect; } GNUNET_CLIENT_receive (ph->client, &process_ats_message, ph, GNUNET_TIME_UNIT_FOREVER_REL); return; reconnect: if (NULL != ph->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (ph->th); ph->th = NULL; } GNUNET_CLIENT_disconnect (ph->client); ph->client = NULL; ph->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task, ph); } /** * Re-establish the connection to the ATS service. * * @param ph handle to use to re-connect. */ static void reconnect (struct GNUNET_ATS_PerformanceHandle *ph) { struct PendingMessage *p; struct ClientStartMessage *init; GNUNET_assert(NULL == ph->client); ph->client = GNUNET_CLIENT_connect ("ats", ph->cfg); GNUNET_assert(NULL != ph->client); GNUNET_CLIENT_receive (ph->client, &process_ats_message, ph, GNUNET_TIME_UNIT_FOREVER_REL); if ((NULL == (p = ph->pending_head)) || (GNUNET_YES != p->is_init)) { p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct ClientStartMessage)); p->size = sizeof(struct ClientStartMessage); p->is_init = GNUNET_YES; init = (struct ClientStartMessage *) &p[1]; init->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_START); init->header.size = htons (sizeof(struct ClientStartMessage)); init->start_flag = htonl ( (NULL == ph->addr_info_cb) ? START_FLAG_PERFORMANCE_NO_PIC : START_FLAG_PERFORMANCE_WITH_PIC); GNUNET_CONTAINER_DLL_insert(ph->pending_head, ph->pending_tail, p); } do_transmit (ph); } /** * Get handle to access performance API of the ATS subsystem. * * @param cfg configuration to use * @param addr_info_cb callback called when performance characteristics for * an address change * @param addr_info_cb_cls closure for infocb * @return ats performance context */ struct GNUNET_ATS_PerformanceHandle * GNUNET_ATS_performance_init (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ATS_AddressInformationCallback addr_info_cb, void *addr_info_cb_cls) { struct GNUNET_ATS_PerformanceHandle *ph; ph = GNUNET_new (struct GNUNET_ATS_PerformanceHandle); ph->cfg = cfg; ph->addr_info_cb = addr_info_cb; ph->addr_info_cb_cls = addr_info_cb_cls; ph->id = 0; reconnect (ph); return ph; } /** * Client is done using the ATS performance subsystem, release resources. * * @param ph handle */ void GNUNET_ATS_performance_done (struct GNUNET_ATS_PerformanceHandle *ph) { struct PendingMessage *p; struct GNUNET_ATS_ReservationContext *rc; struct GNUNET_ATS_AddressListHandle *alh; while (NULL != (p = ph->pending_head)) { GNUNET_CONTAINER_DLL_remove(ph->pending_head, ph->pending_tail, p); GNUNET_free(p); } while (NULL != (alh = ph->addresslist_head)) { GNUNET_CONTAINER_DLL_remove(ph->addresslist_head, ph->addresslist_tail, alh); GNUNET_free(alh); } while (NULL != (rc = ph->reservation_head)) { GNUNET_CONTAINER_DLL_remove(ph->reservation_head, ph->reservation_tail, rc); GNUNET_break(NULL == rc->rcb); GNUNET_free(rc); } if (GNUNET_SCHEDULER_NO_TASK != ph->task) { GNUNET_SCHEDULER_cancel (ph->task); ph->task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != ph->client) { GNUNET_CLIENT_disconnect (ph->client); ph->client = NULL; } GNUNET_free(ph); } /** * Reserve inbound bandwidth from the given peer. ATS will look at * the current amount of traffic we receive from the peer and ensure * that the peer could add 'amount' of data to its stream. * * @param ph performance handle * @param peer identifies the peer * @param amount reserve N bytes for receiving, negative * amounts can be used to undo a (recent) reservation; * @param rcb function to call with the resulting reservation information * @param rcb_cls closure for info * @return NULL on error * @deprecated will be replaced soon */ struct GNUNET_ATS_ReservationContext * GNUNET_ATS_reserve_bandwidth (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, int32_t amount, GNUNET_ATS_ReservationCallback rcb, void *rcb_cls) { struct GNUNET_ATS_ReservationContext *rc; struct PendingMessage *p; struct ReservationRequestMessage *m; rc = GNUNET_new (struct GNUNET_ATS_ReservationContext); rc->size = amount; rc->peer = *peer; rc->rcb = rcb; rc->rcb_cls = rcb_cls; if ((rcb != NULL )&& (amount > 0))rc->undo = GNUNET_YES; GNUNET_CONTAINER_DLL_insert_tail(ph->reservation_head, ph->reservation_tail, rc); p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct ReservationRequestMessage)); p->size = sizeof(struct ReservationRequestMessage); p->is_init = GNUNET_NO; m = (struct ReservationRequestMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST); m->header.size = htons (sizeof(struct ReservationRequestMessage)); m->amount = htonl (amount); m->peer = *peer; GNUNET_CONTAINER_DLL_insert_tail(ph->pending_head, ph->pending_tail, p); do_transmit (ph); return rc; } /** * Cancel request for reserving bandwidth. * * @param rc context returned by the original GNUNET_ATS_reserve_bandwidth call */ void GNUNET_ATS_reserve_bandwidth_cancel (struct GNUNET_ATS_ReservationContext *rc) { rc->rcb = NULL; } /** * Get information about addresses known to the ATS subsystem. * * @param handle the performance handle to use * @param peer peer idm can be NULL for all peers * @param all GNUNET_YES to get information about all addresses or GNUNET_NO to * get only address currently used * @param infocb callback to call with the addresses, * will callback with address == NULL when done * @param infocb_cls closure for infocb * @return ats performance context */ struct GNUNET_ATS_AddressListHandle* GNUNET_ATS_performance_list_addresses ( struct GNUNET_ATS_PerformanceHandle *handle, const struct GNUNET_PeerIdentity *peer, int all, GNUNET_ATS_AddressInformationCallback infocb, void *infocb_cls) { struct GNUNET_ATS_AddressListHandle *alh; struct PendingMessage *p; struct AddressListRequestMessage *m; GNUNET_assert(NULL != handle); if (NULL == infocb) return NULL ; alh = GNUNET_new (struct GNUNET_ATS_AddressListHandle); alh->id = handle->id; handle->id++; alh->cb = infocb; alh->cb_cls = infocb_cls; alh->ph = handle; alh->all_addresses = all; if (NULL == peer) alh->all_peers = GNUNET_YES; else { alh->all_peers = GNUNET_NO; alh->peer = (*peer); } GNUNET_CONTAINER_DLL_insert(handle->addresslist_head, handle->addresslist_tail, alh); p = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct AddressListRequestMessage)); p->size = sizeof(struct AddressListRequestMessage); m = (struct AddressListRequestMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST); m->header.size = htons (sizeof(struct AddressListRequestMessage)); m->all = htonl (all); m->id = htonl (alh->id); if (NULL != peer) m->peer = *peer; else { memset (&m->peer, '\0', sizeof(struct GNUNET_PeerIdentity)); } GNUNET_CONTAINER_DLL_insert_tail(handle->pending_head, handle->pending_tail, p); do_transmit (handle); return alh; } /** * Cancel a pending address listing operation * * @param handle the GNUNET_ATS_AddressListHandle handle to cancel */ void GNUNET_ATS_performance_list_addresses_cancel ( struct GNUNET_ATS_AddressListHandle *handle) { GNUNET_assert(NULL != handle); GNUNET_CONTAINER_DLL_remove(handle->ph->addresslist_head, handle->ph->addresslist_tail, handle); GNUNET_free(handle); } /** * Convert a GNUNET_ATS_PreferenceType to a string * * @param type the preference type * @return a string or NULL if invalid */ const char * GNUNET_ATS_print_preference_type (uint32_t type) { char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString; if (type < GNUNET_ATS_PreferenceCount) return prefs[type]; return NULL ; } /** * Change preferences for the given peer. Preference changes are forgotten if peers * disconnect. * * @param ph performance handle * @param peer identifies the peer * @param ... 0-terminated specification of the desired changes */ void GNUNET_ATS_performance_change_preference ( struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, ...) { struct PendingMessage *p; struct ChangePreferenceMessage *m; size_t msize; uint32_t count; struct PreferenceInformation *pi; va_list ap; enum GNUNET_ATS_PreferenceKind kind; count = 0; va_start(ap, peer); while (GNUNET_ATS_PREFERENCE_END != (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind) )) { switch (kind) { case GNUNET_ATS_PREFERENCE_BANDWIDTH: count++; (void) va_arg (ap, double); break; case GNUNET_ATS_PREFERENCE_LATENCY: count++; (void) va_arg (ap, double); break; default: GNUNET_assert(0); } } va_end(ap); msize = count * sizeof(struct PreferenceInformation) + sizeof(struct ChangePreferenceMessage); p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; m = (struct ChangePreferenceMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE); m->header.size = htons (msize); m->num_preferences = htonl (count); m->peer = *peer; pi = (struct PreferenceInformation *) &m[1]; count = 0; va_start(ap, peer); while (GNUNET_ATS_PREFERENCE_END != (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind) )) { pi[count].preference_kind = htonl (kind); switch (kind) { case GNUNET_ATS_PREFERENCE_BANDWIDTH: pi[count].preference_value = (float) va_arg (ap, double); count++; break; case GNUNET_ATS_PREFERENCE_LATENCY: pi[count].preference_value = (float) va_arg (ap, double); count++; break; default: GNUNET_assert(0); } } va_end(ap); GNUNET_CONTAINER_DLL_insert_tail(ph->pending_head, ph->pending_tail, p); do_transmit (ph); } /** * Send feedback to ATS on how good a the requirements for a peer and a * preference is satisfied by ATS * * @param ph performance handle * @param scope the time interval this valid for: [now - scope .. now] * @param peer identifies the peer * @param ... 0-terminated specification of the desired changes */ void GNUNET_ATS_performance_give_feedback (struct GNUNET_ATS_PerformanceHandle *ph, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, ...) { struct PendingMessage *p; struct FeedbackPreferenceMessage *m; size_t msize; uint32_t count; struct PreferenceInformation *pi; va_list ap; enum GNUNET_ATS_PreferenceKind kind; count = 0; va_start(ap, scope); while (GNUNET_ATS_PREFERENCE_END != (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind) )) { switch (kind) { case GNUNET_ATS_PREFERENCE_BANDWIDTH: count++; (void) va_arg (ap, double); break; case GNUNET_ATS_PREFERENCE_LATENCY: count++; (void) va_arg (ap, double); break; default: GNUNET_assert(0); } } va_end(ap); msize = count * sizeof(struct PreferenceInformation) + sizeof(struct FeedbackPreferenceMessage); p = GNUNET_malloc (sizeof (struct PendingMessage) + msize); p->size = msize; p->is_init = GNUNET_NO; m = (struct FeedbackPreferenceMessage *) &p[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK); m->header.size = htons (msize); m->scope = GNUNET_TIME_relative_hton (scope); m->num_feedback = htonl (count); m->peer = *peer; pi = (struct PreferenceInformation *) &m[1]; count = 0; va_start(ap, scope); while (GNUNET_ATS_PREFERENCE_END != (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind) )) { pi[count].preference_kind = htonl (kind); switch (kind) { case GNUNET_ATS_PREFERENCE_BANDWIDTH: pi[count].preference_value = (float) va_arg (ap, double); count++; break; case GNUNET_ATS_PREFERENCE_LATENCY: pi[count].preference_value = (float) va_arg (ap, double); count++; break; default: GNUNET_assert(0); } } va_end(ap); GNUNET_CONTAINER_DLL_insert_tail(ph->pending_head, ph->pending_tail, p); do_transmit (ph); } /* end of ats_api_performance.c */ gnunet-0.10.1/src/ats/plugin_ats_ril.h0000644000175000017500000001141312320530515014550 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/plugin_ats_ril.h * @brief ATS reinforcement learning solver * @author Fabian Oehlmann * @author Matthias Wachs */ #include "platform.h" #include #include #include "gnunet_ats_plugin.h" #include "gnunet-service-ats_addresses.h" /** * ATS reinforcement learning solver * * General description */ /** * Changes the preferences for a peer in the problem * * @param solver the solver handle * @param peer the peer to change the preference for * @param kind the kind to change the preference * @param pref_rel the normalized preference value for this kind over all clients */ void GAS_ril_address_change_preference (void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel); /** * Add a single address within a network to the solver * * @param solver the solver Handle * @param address the address to add * @param network network type of this address */ void GAS_ril_address_add (void *solver, struct ATS_Address *address, uint32_t network); /** * Transport properties for this address have changed * * @param solver solver handle * @param address the address * @param type the ATSI type in HBO * @param abs_value the absolute value of the property * @param rel_value the normalized value */ void GAS_ril_address_property_changed (void *solver, struct ATS_Address *address, uint32_t type, uint32_t abs_value, double rel_value); /** * Transport session for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param cur_session the current session * @param new_session the new session */ void GAS_ril_address_session_changed (void *solver, struct ATS_Address *address, uint32_t cur_session, uint32_t new_session); /** * Usage for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param in_use usage state */ void GAS_ril_address_inuse_changed (void *solver, struct ATS_Address *address, int in_use); /** * Network scope for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param current_network the current network * @param new_network the new network */ void GAS_ril_address_change_network (void *solver, struct ATS_Address *address, uint32_t current_network, uint32_t new_network); /** * Remove an address from the solver * * @param solver the solver handle * @param address the address to remove * @param session_only delete only session not whole address */ void GAS_ril_address_delete (void *solver, struct ATS_Address *address, int session_only); /** * Get application feedback for a peer * * @param solver the solver handle * @param application the application * @param peer the peer to change the preference for * @param scope the time interval for this feedback: [now - scope .. now] * @param kind the kind to change the preference * @param score the score */ void GAS_ril_address_preference_feedback (void *solver, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score); /** * Start a bulk operation * * @param solver the solver */ void GAS_ril_bulk_start (void *solver); /** * Bulk operation done */ void GAS_ril_bulk_stop (void *solver); /** * Stop notifying about address and bandwidth changes for this peer * * @param solver the solver handle * @param peer the peer */ void GAS_ril_stop_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer); /** * Get the prefered address for a specific peer * * @param solver the solver handle * @param peer the identity of the peer */ const struct ATS_Address * GAS_ril_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer); /* end of plugin_ats_ril.h */ gnunet-0.10.1/src/ats/test_ats_api_scheduling_destroy_session.c0000644000175000017500000001506612263724143021750 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_scheduling_destroy_session.c * @brief test destroying sessions: first add an address with a session, * request the address and compare, delete the session, request and * compare again, delete whole address, request and wait for timeout, * shutdown * @author Christian Grothoff * @author Matthias Wachs * */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { static int first_stat_cb = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if ((GNUNET_YES == first_stat_cb) && (1 == value)) { GNUNET_ATS_address_add (sched_ats, &test_hello_address, (struct Session *) &test_session, test_ats_info, test_ats_count); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &end, NULL); } if ((GNUNET_NO == first_stat_cb) && (1 == value)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS updated existing address\n"); } if (value > 1) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ATS did not update existing address, but added 2nd address!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); } return GNUNET_OK; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void got_initial_value (void *cls, int success) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got initial value\n"); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, NULL, test_ats_info, test_ats_count); } static int dummy_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got dummy stat %s%s:%s = %llu\n", is_persistent ? "!" : " ", subsystem, name, value); return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); GNUNET_STATISTICS_get (stats, "ats", "# addresses", TIMEOUT, &got_initial_value, &dummy_stat, GNUNET_CONFIGURATION_dup (cfg)); } int main (int argc, char *argv[]) { ret = 0; if (0 != GNUNET_TESTING_peer_run ("test-ats-api", "test_ats_api.conf", &run, NULL)) return 1; return ret; } /* end of file test_ats_api_scheduling_destroy_session.c */ gnunet-0.10.1/src/ats/plugin_ats_proportional.c0000644000175000017500000013631612276375236016540 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/plugin_ats_proportional.c * @brief ATS proportional solver * @author Matthias Wachs * @author Christian Grothoff */ #include "plugin_ats_proportional.h" #define LOG(kind,...) GNUNET_log_from (kind, "ats-proportional",__VA_ARGS__) /** * * NOTE: Do not change this documentation. This documentation is based * on gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex * use build_txt.sh to generate plaintext output * * ATS addresses : proportional solver * * The proportional solver ("proportional") distributes the available * bandwidth fair over all the addresses influenced by the * preference values. For each available network type an in- and * outbound quota is configured and the bandwidth available in * these networks is distributed over the addresses. The solver * first assigns every addresses the minimum amount of bandwidth * GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT and then distributes the * remaining bandwidth available according to the preference * values. For each peer only a single address gets bandwidth * assigned and only one address marked as active. The most * important functionality for the solver is implemented in: * * find_address_it is an hashmap iterator returning the prefered * address for an peer * update_quota_per_network distributes * available bandwidth for a network over active addresses * * Changes to addresses automatically have an impact on the the * bandwidth assigned to other addresses in the same network since * the solver distributes the remaining bandwidth over the * addresses in the network. When changes to the addresses occur, * the solver first performs the changes, like adding or deleting * addresses, and then updates bandwidth assignment for the * affected network. Bandwidth assignment is only recalculated on * demand when an address is requested by a client for a peer or * when the addresses available have changed or an address changed * the network it is located in. When the bandwidth assignment has * changed the callback is called with the new bandwidth * assignments. The bandwidth distribution for a network is * recalculated due to: * address suggestion requests * address * deletions * address switching networks during address update * * preference changes * * 3.1 Data structures used * * For each ATS network (e.g. WAN, LAN, loopback) a struct Network * is used to specify network related information as total adresses * and active addresses in this network and the configured in- and * outbound quota. Each network also contains a list of addresses * added to the solver located in this network. The proportional * solver uses the addresses' solver_information field to store the * proportional network it belongs to for each address. * * 3.2 Initializing * * When the proportional solver is initialized the solver creates a * new solver handle and initializes the network structures with * the quotas passed from addresses and returns the handle solver. * * 3.3 Adding an address * * When a new address is added to the solver using s_add, a lookup * for the network for this address is done and the address is * enqueued in in the linked list of the network. * * 3.4 Updating an address * * The main purpose of address updates is to update the ATS * information for addresse selection. Important for the proportional * solver is when an address switches network it is located * in. This is common because addresses added by transport's * validation mechanism are commonly located in * GNUNET_ATS_NET_UNSPECIFIED. Addresses in validation are located * in this network type and only if a connection is successful on * return of payload data transport switches to the real network * the address is located in. When an address changes networks it * is first of all removed from the old network using the solver * API function GAS_proportional_address_delete and the network in * the address struct is updated. A lookup for the respective new * proportional network is done and stored in the addresse's * solver_information field. Next the address is re-added to the * solver using the solver API function * GAS_proportional_address_add. If the address was marked as in * active, the solver checks if bandwidth is available in the * network and if yes sets the address to active and updates the * bandwidth distribution in this network. If no bandwidth is * available it sets the bandwidth for this address to 0 and tries * to suggest an alternative address. If an alternative address was * found, addresses' callback is called for this address. * * 3.5 Deleting an address * * When an address is removed from the solver, it removes the * respective address from the network and if the address was * marked as active, it updates the bandwidth distribution for this * network. * * 3.6 Requesting addresses * * When an address is requested for a peer the solver performs a * lookup for the peer entry in addresses address hashmap and * selects the best address. The selection of the most suitable * address is done in the find_address_it hashmap iterator * described in detail in section 3.7. If no address is returned, * no address can be suggested at the moment. If the address * returned is marked as active, the solver can return this * address. If the address is not marked as active, the solver * checks if another address belongign to this peer is marked as * active and marks the address as inactive, updates the bandwidth * for this address to 0, call the bandwidth changed callback for * this address due to the change and updates quota assignment for * the addresse's network. the now in-active address is belonging * to. The solver marks the new address as active and updates the * bandwidth assignment for this network. * * 3.7 Choosing addresses * * Choosing the best possible address for suggestion is done by * iterating over all addresses of a peer stored in addresses' * hashmap and using the hashmap iterator find_address_it to select * the best available address. Several checks are done when an * address is selected. First if this address is currently blocked * by addresses from being suggested. An address is blocked for the * duration of ATS_BLOCKING_DELTA when it is suggested to * transport. Next it is checked if at least * GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT bytes bandwidth is available * in the addresse's network, because suggesting an address without * bandwidth does not make sense. This also ensures that all active * addresses in this network get at least the minimum amount of * bandwidth assigned. In the next step the solver ensures that for * tcp connections inbound connections are prefered over outbound * connections. In the next stet the solver ensures that * connections are prefered in the following order: * connections * are already established and have bandwidth assigned * * connections with a shorter distance * connectes have a shorter * latency * * 3.8 Changing preferences * * 3.9 Shutdown * * During shutdown all network entries and aging processes are * destroyed and freed. * * * OLD DOCUMENTATION * * This solver assigns in and outbound bandwidth equally for all * addresses in specific network type (WAN, LAN) based on configured * in and outbound quota for this network. * * The solver is notified by addresses about changes to the addresses * and recalculates the bandwith assigned if required. The solver * notifies addresses by calling the GAS_bandwidth_changed_cb * callback. * * - Initialization * * * * * For each peer only a single is selected and marked as "active" in the address * struct. * * E.g.: * * You have the networks WAN and LAN and quotas * WAN_TOTAL_IN, WAN_TOTAL_OUT * LAN_TOTAL_IN, LAN_TOTAL_OUT * * If you have x addresses in the network segment LAN, the quotas are * QUOTA_PER_ADDRESS = LAN_TOTAL_OUT / x * * Quotas are automatically recalculated and reported back when addresses are * - requested * */ #define PREF_AGING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) #define PREF_AGING_FACTOR 0.95 #define DEFAULT_REL_PREFERENCE 1.0 #define DEFAULT_ABS_PREFERENCE 0.0 #define MIN_UPDATE_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) /** * A handle for the proportional solver */ struct GAS_PROPORTIONAL_Handle { struct GNUNET_ATS_PluginEnvironment *env; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Hashmap containing all valid addresses */ const struct GNUNET_CONTAINER_MultiPeerMap *addresses; /** * Pending address requests */ struct GNUNET_CONTAINER_MultiPeerMap *requests; /** * Bandwidth changed callback */ GAS_bandwidth_changed_cb bw_changed; /** * Bandwidth changed callback cls */ void *bw_changed_cls; /** * ATS function to get preferences */ GAS_get_preferences get_preferences; /** * Closure for ATS function to get preferences */ void *get_preferences_cls; /** * ATS function to get properties */ GAS_get_properties get_properties; /** * Closure for ATS function to get properties */ void *get_properties_cls; /** * Bulk lock */ int bulk_lock; /** * Number of changes while solver was locked */ int bulk_requests; /** * Total number of addresses for solver */ unsigned int total_addresses; /** * Number of active addresses for solver */ unsigned int active_addresses; /** * Networks array */ struct Network *network_entries; /** * Number of networks */ unsigned int network_count; }; /** * Representation of a network */ struct Network { /** * ATS network type */ unsigned int type; /** * Network description */ char *desc; /** * Total inbound quota * */ unsigned long long total_quota_in; /** * Total outbound quota * */ unsigned long long total_quota_out; /** * Number of active addresses for this network */ unsigned int active_addresses; /** * Number of total addresses for this network */ unsigned int total_addresses; /** * String for statistics total addresses */ char *stat_total; /** * String for statistics active addresses */ char *stat_active; struct AddressWrapper *head; struct AddressWrapper *tail; }; /** * Address information stored in the solver */ struct AddressSolverInformation { struct Network *network; /** * Inbound quota * */ unsigned long long calculated_quota_in_NBO; /** * Outbound quota * */ unsigned long long calculated_quota_out_NBO; }; /** * Wrapper for addresses to store them in network's linked list */ struct AddressWrapper { /** * Next in DLL */ struct AddressWrapper *next; /** * Previous in DLL */ struct AddressWrapper *prev; /** * The address */ struct ATS_Address *addr; }; /** * Important solver functions * --------------------------- */ void * libgnunet_plugin_ats_proportional_init (void *cls) { struct GNUNET_ATS_PluginEnvironment *env = cls; struct GAS_PROPORTIONAL_Handle *s; struct Network * cur; char * net_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; int c; GNUNET_assert (NULL != env); GNUNET_assert(NULL != env->cfg); GNUNET_assert(NULL != env->bandwidth_changed_cb); GNUNET_assert(NULL != env->get_preferences); GNUNET_assert(NULL != env->get_property); s = GNUNET_new (struct GAS_PROPORTIONAL_Handle); s->env = env; env->sf.s_add = &GAS_proportional_address_add; env->sf.s_address_update_property = &GAS_proportional_address_property_changed; env->sf.s_address_update_session = &GAS_proportional_address_session_changed; env->sf.s_address_update_inuse = &GAS_proportional_address_inuse_changed; env->sf.s_address_update_network = &GAS_proportional_address_change_network; env->sf.s_get = &GAS_proportional_get_preferred_address; env->sf.s_get_stop = &GAS_proportional_stop_get_preferred_address; env->sf.s_pref = &GAS_proportional_address_change_preference; env->sf.s_feedback = &GAS_proportional_address_preference_feedback; env->sf.s_del = &GAS_proportional_address_delete; env->sf.s_bulk_start = &GAS_proportional_bulk_start; env->sf.s_bulk_stop = &GAS_proportional_bulk_stop; s->stats = (struct GNUNET_STATISTICS_Handle *) env->stats; s->bw_changed = env->bandwidth_changed_cb; s->bw_changed_cls = env->bw_changed_cb_cls; s->get_preferences = env->get_preferences; s->get_preferences_cls = env->get_preference_cls; s->get_properties = env->get_property; s->get_properties_cls = env->get_property_cls; s->network_count = env->network_count; s->network_entries = GNUNET_malloc (env->network_count * sizeof (struct Network)); /* Init */ s->active_addresses = 0; s->total_addresses = 0; s->bulk_lock = GNUNET_NO; s->addresses = env->addresses; s->requests = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); for (c = 0; c < env->network_count; c++) { cur = &s->network_entries[c]; cur->total_addresses = 0; cur->active_addresses = 0; cur->type = env->networks[c]; cur->total_quota_in = env->in_quota[c]; cur->total_quota_out = env->out_quota[c]; cur->desc = net_str[c]; GNUNET_asprintf (&cur->stat_total, "# ATS addresses %s total", cur->desc); GNUNET_asprintf (&cur->stat_active, "# ATS active addresses %s total", cur->desc); LOG (GNUNET_ERROR_TYPE_INFO, "Added network %u `%s' (%llu/%llu)\n", c, cur->desc, cur->total_quota_in, cur->total_quota_out); } return s; } void * libgnunet_plugin_ats_proportional_done (void *cls) { struct GAS_PROPORTIONAL_Handle *s = cls; struct AddressWrapper *cur; struct AddressWrapper *next; int c; GNUNET_assert(s != NULL); for (c = 0; c < s->network_count; c++) { if (s->network_entries[c].total_addresses > 0) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Had %u addresses for network `%s' not deleted during shutdown\n", s->network_entries[c].total_addresses, s->network_entries[c].desc); //GNUNET_break(0); } if (s->network_entries[c].active_addresses > 0) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Had %u active addresses for network `%s' not deleted during shutdown\n", s->network_entries[c].active_addresses, s->network_entries[c].desc); //GNUNET_break(0); } next = s->network_entries[c].head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove(s->network_entries[c].head, s->network_entries[c].tail, cur); GNUNET_free_non_null (cur->addr->solver_information); GNUNET_free(cur); } GNUNET_free(s->network_entries[c].stat_total); GNUNET_free(s->network_entries[c].stat_active); } if (s->total_addresses > 0) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Had %u addresses not deleted during shutdown\n", s->total_addresses); // GNUNET_break(0); } if (s->active_addresses > 0) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Had %u active addresses not deleted during shutdown\n", s->active_addresses); // GNUNET_break (0); } GNUNET_free (s->network_entries); GNUNET_CONTAINER_multipeermap_destroy (s->requests); GNUNET_free (s); return NULL; } /** * Test if bandwidth is available in this network to add an additional address * * @param net the network type to update * @return GNUNET_YES or GNUNET_NO */ static int is_bandwidth_available_in_network (struct Network *net) { GNUNET_assert(NULL != net); unsigned int na = net->active_addresses + 1; uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); if (((net->total_quota_in / na) > min_bw) && ((net->total_quota_out / na) > min_bw)) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Enough bandwidth available for %u active addresses in network `%s'\n", na, net->desc); return GNUNET_YES; } LOG(GNUNET_ERROR_TYPE_DEBUG, "Not enough bandwidth available for %u active addresses in network `%s'\n", na, net->desc); return GNUNET_NO; } /** * Update bandwidth assigned to peers in this network * * @param s the solver handle * @param net the network type to update * @param address_except address excluded from notification, since we suggest * this address */ static void distribute_bandwidth (struct GAS_PROPORTIONAL_Handle *s, struct Network *net, struct ATS_Address *address_except) { struct AddressSolverInformation *asi; struct AddressWrapper *cur; unsigned long long remaining_quota_in = 0; unsigned long long quota_out_used = 0; unsigned long long remaining_quota_out = 0; unsigned long long quota_in_used = 0; uint32_t min_bw = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__); double peer_prefs; double total_prefs; /* Important: has to be double not float due to precision */ double cur_pref; /* Important: has to be double not float due to precision */ const double *t = NULL; /* Important: has to be double not float due to precision */ int c; unsigned long long assigned_quota_in = 0; unsigned long long assigned_quota_out = 0; LOG(GNUNET_ERROR_TYPE_DEBUG, "Recalculate quota for network type `%s' for %u addresses (in/out): %llu/%llu \n", net->desc, net->active_addresses, net->total_quota_in, net->total_quota_in); if (net->active_addresses == 0) return; /* no addresses to update */ /* Idea * Assign every peer in network minimum Bandwidth * Distribute bandwidth left according to preference */ if ((net->active_addresses * min_bw) > net->total_quota_in) { GNUNET_break(0); return; } if ((net->active_addresses * min_bw) > net->total_quota_out) { GNUNET_break(0); return; } remaining_quota_in = net->total_quota_in - (net->active_addresses * min_bw); remaining_quota_out = net->total_quota_out - (net->active_addresses * min_bw); LOG(GNUNET_ERROR_TYPE_DEBUG, "Remaining bandwidth : (in/out): %llu/%llu \n", remaining_quota_in, remaining_quota_out); total_prefs = 0.0; for (cur = net->head; NULL != cur; cur = cur->next) { if (GNUNET_YES == cur->addr->active) { GNUNET_assert( NULL != (t = s->get_preferences (s->get_preferences_cls, &cur->addr->peer))); peer_prefs = 0.0; for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) { if (c != GNUNET_ATS_PREFERENCE_END) { //fprintf (stderr, "VALUE[%u] %s %.3f \n", c, GNUNET_i2s (&cur->addr->peer), t[c]); peer_prefs += t[c]; } } total_prefs += (peer_prefs / (GNUNET_ATS_PreferenceCount - 1)); } } for (cur = net->head; NULL != cur; cur = cur->next) { if (GNUNET_YES == cur->addr->active) { cur_pref = 0.0; GNUNET_assert( NULL != (t = s->get_preferences (s->get_preferences_cls, &cur->addr->peer))); for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) { if (c != GNUNET_ATS_PREFERENCE_END) cur_pref += t[c]; } cur_pref /= 2; assigned_quota_in = min_bw + ((cur_pref / total_prefs) * remaining_quota_in); assigned_quota_out = min_bw + ((cur_pref / total_prefs) * remaining_quota_out); LOG(GNUNET_ERROR_TYPE_DEBUG, "New quota for peer `%s' with preference (cur/total) %.3f/%.3f (in/out): %llu / %llu\n", GNUNET_i2s (&cur->addr->peer), cur_pref, total_prefs, assigned_quota_in, assigned_quota_out); } else { assigned_quota_in = 0; assigned_quota_out = 0; } quota_in_used += assigned_quota_in; quota_out_used += assigned_quota_out; /* Prevent overflow due to rounding errors */ if (assigned_quota_in > UINT32_MAX) assigned_quota_in = UINT32_MAX; if (assigned_quota_out > UINT32_MAX) assigned_quota_out = UINT32_MAX; /* Compare to current bandwidth assigned */ asi = cur->addr->solver_information; asi->calculated_quota_in_NBO = htonl (assigned_quota_in); asi->calculated_quota_out_NBO = htonl (assigned_quota_out); } LOG(GNUNET_ERROR_TYPE_DEBUG, "Total bandwidth assigned is (in/out): %llu /%llu\n", quota_in_used, quota_out_used); if (quota_out_used > net->total_quota_out + 1) /* +1 is required due to rounding errors */ { LOG(GNUNET_ERROR_TYPE_ERROR, "Total outbound bandwidth assigned is larger than allowed (used/allowed) for %u active addresses: %llu / %llu\n", net->active_addresses, quota_out_used, net->total_quota_out); } if (quota_in_used > net->total_quota_in + 1) /* +1 is required due to rounding errors */ { LOG(GNUNET_ERROR_TYPE_ERROR, "Total inbound bandwidth assigned is larger than allowed (used/allowed) for %u active addresses: %llu / %llu\n", net->active_addresses, quota_in_used, net->total_quota_in); } } struct FindBestAddressCtx { struct GAS_PROPORTIONAL_Handle *s; struct ATS_Address *best; }; static int find_property_index (uint32_t type) { int existing_types[] = GNUNET_ATS_QualityProperties; int c; for (c = 0; c < GNUNET_ATS_QualityPropertiesCount; c++) if (existing_types[c] == type) return c; return GNUNET_SYSERR; } /** * Find a "good" address to use for a peer by iterating over the addresses for this peer. * If we already have an existing address, we stick to it. * Otherwise, we pick by lowest distance and then by lowest latency. * * @param cls the 'struct ATS_Address**' where we store the result * @param key unused * @param value another 'struct ATS_Address*' to consider using * @return GNUNET_OK (continue to iterate) */ static int find_best_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct FindBestAddressCtx *ctx = (struct FindBestAddressCtx *) cls; struct ATS_Address *current = (struct ATS_Address *) value; struct ATS_Address *current_best = (struct ATS_Address *) value; struct GNUNET_TIME_Absolute now; struct AddressSolverInformation *asi; const double *norm_prop_cur; const double *norm_prop_best; int index; current_best = NULL; asi = current->solver_information; now = GNUNET_TIME_absolute_get (); if (current->blocked_until.abs_value_us == GNUNET_TIME_absolute_max (now, current->blocked_until).abs_value_us) { /* This address is blocked for suggestion */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Address %p blocked for suggestion for %s \n", current, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (now, current->blocked_until), GNUNET_YES)); return GNUNET_OK; } if (GNUNET_NO == is_bandwidth_available_in_network (asi->network)) return GNUNET_OK; /* There's no bandwidth available in this network */ if (NULL != ctx->best) { /* Compare current addresses with denominated 'best' address */ current_best = ctx->best; if ((0 != ctx->best->addr_len) && (0 == current->addr_len)) { /* saved address was an outbound address, but we have an inbound address */ current_best = current; goto end; } if (ctx->best->t_last_activity.abs_value_us < current->t_last_activity.abs_value_us) { /* Current address is newer */ current_best = current; } if (ctx->best->t_added.abs_value_us < current->t_added.abs_value_us) { /* Current address is newer */ current_best = current; goto end; } } if (NULL == ctx->best) { /* We do not have a 'best' address so take this address */ current_best = current; goto end; } if ( (ntohl (ctx->best->assigned_bw_in.value__) == 0) && (ntohl (current->assigned_bw_in.value__) > 0) ) { /* stick to existing connection */ current_best = current; } /* Now compare ATS information */ norm_prop_cur = ctx->s->get_properties (ctx->s->get_properties_cls, (const struct ATS_Address *) current); norm_prop_best = ctx->s->get_properties (ctx->s->get_properties_cls, (const struct ATS_Address *) ctx->best); index = find_property_index (GNUNET_ATS_QUALITY_NET_DISTANCE); if (GNUNET_SYSERR != index) { /* user shorter distance */ if (norm_prop_cur[index] < norm_prop_best[index]) current_best = current; else current_best = ctx->best; } index = find_property_index (GNUNET_ATS_QUALITY_NET_DELAY); if (GNUNET_SYSERR != index) { /* User connection with less delay */ if (norm_prop_cur[index] < norm_prop_best[index]) current_best = current; else current_best = ctx->best; } end: ctx->best = current_best; return GNUNET_OK; } /** * Helper functions * --------------------------- */ static void propagate_bandwidth (struct GAS_PROPORTIONAL_Handle *s, struct Network *net, struct ATS_Address *address_except) { struct AddressWrapper *cur; struct AddressSolverInformation *asi; for (cur = net->head; NULL != cur; cur = cur->next) { asi = cur->addr->solver_information; if ( (cur->addr->assigned_bw_in.value__ != asi->calculated_quota_in_NBO) || (cur->addr->assigned_bw_out.value__ != asi->calculated_quota_out_NBO) ) { cur->addr->assigned_bw_in.value__ = asi->calculated_quota_in_NBO; cur->addr->assigned_bw_out.value__ = asi->calculated_quota_in_NBO; /* Notify on change */ if ((GNUNET_YES == cur->addr->active) && (cur->addr != address_except)) s->bw_changed (s->bw_changed_cls, cur->addr); } } } /** * Distribibute bandwidth * * @param s the solver handle * @param n the network, can be NULL for all network * @param address_except do not notify for this address */ static void distribute_bandwidth_in_network (struct GAS_PROPORTIONAL_Handle *s, struct Network *n, struct ATS_Address *address_except) { if (GNUNET_YES == s->bulk_lock) { s->bulk_requests++; return; } if (NULL != n) { if (NULL != s->env->info_cb) s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_START, GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE); distribute_bandwidth(s, n, address_except); if (NULL != s->env->info_cb) s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE); if (NULL != s->env->info_cb) s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE); propagate_bandwidth(s, n, address_except); if (NULL != s->env->info_cb) s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, GAS_STAT_SUCCESS, GAS_INFO_PROP_SINGLE); } else { int i; if (NULL != s->env->info_cb) s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_START, GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL); for (i = 0; i < s->network_count; i++) distribute_bandwidth(s, &s->network_entries[i], NULL); if (NULL != s->env->info_cb) s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_STOP, GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL); if (NULL != s->env->info_cb) s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL); for (i = 0; i < s->network_count; i++) { propagate_bandwidth(s, &s->network_entries[i], address_except); } if (NULL != s->env->info_cb) s->env->info_cb(s->env->info_cb_cls, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, GAS_STAT_SUCCESS, GAS_INFO_PROP_ALL); } } /** * Lookup network struct by type * * @param s the solver handle * @param type the network type * @return the network struct */ static struct Network * get_network (struct GAS_PROPORTIONAL_Handle *s, uint32_t type) { int c; for (c = 0; c < s->network_count; c++) { if (s->network_entries[c].type == type) return &s->network_entries[c]; } return NULL ; } /** * Hashmap Iterator to find current active address for peer * * @param cls last active address * @param key peer's key * @param value address to check * @return #GNUNET_NO on double active address else #GNUNET_YES; */ static int get_active_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct ATS_Address **dest = cls; struct ATS_Address *aa = (struct ATS_Address *) value; if (GNUNET_YES == aa->active) { if (NULL != (*dest)) { /* should never happen */ LOG(GNUNET_ERROR_TYPE_ERROR, "Multiple active addresses for peer `%s'\n", GNUNET_i2s (&aa->peer)); GNUNET_break(0); return GNUNET_NO; } (*dest) = aa; } return GNUNET_OK; } /** * Find current active address for peer * * @param solver the solver handle * @param addresses the address set * @param peer the peer * @return active address or NULL */ static struct ATS_Address * get_active_address (void *solver, const struct GNUNET_CONTAINER_MultiPeerMap * addresses, const struct GNUNET_PeerIdentity *peer) { struct ATS_Address * dest = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (addresses, peer, &get_active_address_it, &dest); return dest; } static void addresse_increment (struct GAS_PROPORTIONAL_Handle *s, struct Network *net, int total, int active) { if (GNUNET_YES == total) { s->total_addresses++; net->total_addresses++; GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", 1, GNUNET_NO); GNUNET_STATISTICS_update (s->stats, net->stat_total, 1, GNUNET_NO); } if (GNUNET_YES == active) { net->active_addresses++; s->active_addresses++; GNUNET_STATISTICS_update (s->stats, "# ATS active addresses total", 1, GNUNET_NO); GNUNET_STATISTICS_update (s->stats, net->stat_active, 1, GNUNET_NO); } } static int addresse_decrement (struct GAS_PROPORTIONAL_Handle *s, struct Network *net, int total, int active) { int res = GNUNET_OK; if (GNUNET_YES == total) { if (s->total_addresses < 1) { GNUNET_break(0); res = GNUNET_SYSERR; } else { s->total_addresses--; GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1, GNUNET_NO); } if (net->total_addresses < 1) { GNUNET_break(0); res = GNUNET_SYSERR; } else { net->total_addresses--; GNUNET_STATISTICS_update (s->stats, net->stat_total, -1, GNUNET_NO); } } if (GNUNET_YES == active) { if (net->active_addresses < 1) { GNUNET_break(0); res = GNUNET_SYSERR; } else { net->active_addresses--; GNUNET_STATISTICS_update (s->stats, net->stat_active, -1, GNUNET_NO); } if (s->active_addresses < 1) { GNUNET_break(0); res = GNUNET_SYSERR; } else { s->active_addresses--; GNUNET_STATISTICS_update (s->stats, "# ATS addresses total", -1, GNUNET_NO); } } return res; } /** * Solver API functions * --------------------------- */ /** * Changes the preferences for a peer in the problem * * @param solver the solver handle * @param peer the peer to change the preference for * @param kind the kind to change the preference * @param pref_rel the normalized preference value for this kind over all clients */ void GAS_proportional_address_change_preference (void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel) { struct GAS_PROPORTIONAL_Handle *s = solver; GNUNET_assert(NULL != solver); GNUNET_assert(NULL != peer); distribute_bandwidth_in_network (s, NULL, NULL); } /** * Get application feedback for a peer * * @param solver the solver handle * @param application the application * @param peer the peer to change the preference for * @param scope the time interval for this feedback: [now - scope .. now] * @param kind the kind to change the preference * @param score the score */ void GAS_proportional_address_preference_feedback (void *solver, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score) { struct GAS_PROPORTIONAL_Handle *s = solver; GNUNET_assert(NULL != solver); GNUNET_assert(NULL != peer); GNUNET_assert(NULL != s); GNUNET_break(0); } /** * Get the preferred address for a specific peer * * @param solver the solver handle * @param peer the identity of the peer */ const struct ATS_Address * GAS_proportional_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer) { struct GAS_PROPORTIONAL_Handle *s = solver; struct Network *net_prev; struct Network *net_cur; struct ATS_Address *prev; struct FindBestAddressCtx fba_ctx; struct AddressSolverInformation *asi; struct AddressSolverInformation *asi_prev; GNUNET_assert(s != NULL); GNUNET_assert(peer != NULL); /* Add to list of pending requests */ if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (s->requests, peer)) { GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (s->requests, peer, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } /* Get address with: stick to current address, lower distance, lower latency */ fba_ctx.s = s; fba_ctx.best = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (s->addresses, peer, &find_best_address_it, &fba_ctx); if (NULL == fba_ctx.best) { LOG(GNUNET_ERROR_TYPE_INFO, "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer)); return NULL ; } LOG(GNUNET_ERROR_TYPE_INFO, "Suggesting %s address %p for peer `%s'\n", (GNUNET_NO == fba_ctx.best->active) ? "inactive" : "active", fba_ctx.best, GNUNET_i2s (peer)); asi = fba_ctx.best->solver_information; net_cur = asi->network ; if (NULL == fba_ctx.best) { LOG(GNUNET_ERROR_TYPE_ERROR, "Trying to suggesting unknown address peer `%s'\n", GNUNET_i2s (peer)); GNUNET_break(0); return NULL ; } if (GNUNET_YES == fba_ctx.best->active) { /* This address was selected previously, so no need to update quotas */ return fba_ctx.best; } /* This address was not active, so we have to: * * - mark previous active address as not active * - update quota for previous address network * - update quota for this address network */ prev = get_active_address (s, s->addresses, peer); if (NULL != prev) { asi_prev = prev->solver_information; net_prev = (struct Network *) asi_prev->network; prev->active = GNUNET_NO; /* No active any longer */ prev->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */ prev->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */ if (GNUNET_SYSERR == addresse_decrement (s, net_prev, GNUNET_NO, GNUNET_YES)) GNUNET_break(0); distribute_bandwidth_in_network (s, net_prev, NULL); } if (GNUNET_NO == (is_bandwidth_available_in_network (net_cur))) { GNUNET_break(0); /* This should never happen*/ return NULL ; } fba_ctx.best->active = GNUNET_YES; addresse_increment (s, net_cur, GNUNET_NO, GNUNET_YES); distribute_bandwidth_in_network (s, net_cur, fba_ctx.best); return fba_ctx.best; } /** * Stop notifying about address and bandwidth changes for this peer * * @param solver the solver handle * @param peer the peer */ void GAS_proportional_stop_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer) { struct GAS_PROPORTIONAL_Handle *s = solver; struct ATS_Address *cur; struct AddressSolverInformation *asi; struct Network *cur_net; if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (s->requests, peer)) GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (s->requests, peer, NULL)); cur = get_active_address (s, s->addresses, peer); if (NULL != cur) { /* Disabling current address */ asi = cur->solver_information; cur_net = asi->network ; cur->active = GNUNET_NO; /* No active any longer */ cur->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */ cur->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */ if (GNUNET_SYSERR == addresse_decrement (s, cur_net, GNUNET_NO, GNUNET_YES)) GNUNET_break(0); distribute_bandwidth_in_network (s, cur_net, NULL ); } return; } /** * Remove an address from the solver * * @param solver the solver handle * @param address the address to remove * @param session_only delete only session not whole address */ void GAS_proportional_address_delete (void *solver, struct ATS_Address *address, int session_only) { struct GAS_PROPORTIONAL_Handle *s = solver; struct Network *net; struct AddressWrapper *aw; struct AddressSolverInformation *asi; const struct ATS_Address *new_address; /* Remove an adress completely, we have to: * - Remove from specific network * - Decrease number of total addresses * - If active: * - decrease number of active addreses * - update quotas */ asi = address->solver_information; if (NULL == asi) { GNUNET_break (0); return; } net = asi->network; if (GNUNET_NO == session_only) { LOG(GNUNET_ERROR_TYPE_INFO, "Deleting %s address %p for peer `%s' from network `%s' (total: %u/ active: %u)\n", (GNUNET_NO == address->active) ? "inactive" : "active", address, GNUNET_i2s (&address->peer), net->desc, net->total_addresses, net->active_addresses); /* Remove address */ addresse_decrement (s, net, GNUNET_YES, GNUNET_NO); for (aw = net->head; NULL != aw; aw = aw->next) { if (aw->addr == address) break; } if (NULL == aw) { GNUNET_break(0); return; } GNUNET_CONTAINER_DLL_remove(net->head, net->tail, aw); GNUNET_free_non_null (aw->addr->solver_information); GNUNET_free(aw); } else { /* Remove session only: remove if active and update */ LOG(GNUNET_ERROR_TYPE_INFO, "Deleting %s session %p for peer `%s' from network `%s' (total: %u/ active: %u)\n", (GNUNET_NO == address->active) ? "inactive" : "active", address, GNUNET_i2s (&address->peer), net->desc, net->total_addresses, net->active_addresses); } if (GNUNET_YES == address->active) { /* Address was active, remove from network and update quotas*/ address->active = GNUNET_NO; address->assigned_bw_in = BANDWIDTH_ZERO; address->assigned_bw_out = BANDWIDTH_ZERO; if (GNUNET_SYSERR == addresse_decrement (s, net, GNUNET_NO, GNUNET_YES)) GNUNET_break(0); distribute_bandwidth_in_network (s, net, NULL); if (NULL == (new_address = GAS_proportional_get_preferred_address (s, &address->peer))) { /* No alternative address found, disconnect peer */ s->bw_changed (s->bw_changed_cls, address); } else { s->bw_changed (s->bw_changed_cls, (struct ATS_Address *) new_address); } } LOG(GNUNET_ERROR_TYPE_INFO, "After deleting address now total %u and active %u addresses in network `%s'\n", net->total_addresses, net->active_addresses, net->desc); } /** * Start a bulk operation * * @param solver the solver */ void GAS_proportional_bulk_start (void *solver) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Locking solver for bulk operation ...\n"); struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver; GNUNET_assert(NULL != solver); s->bulk_lock++; } /** * Bulk operation done */ void GAS_proportional_bulk_stop (void *solver) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Unlocking solver from bulk operation ...\n"); struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver; GNUNET_assert(NULL != solver); if (s->bulk_lock < 1) { GNUNET_break(0); return; } s->bulk_lock--; if ((0 == s->bulk_lock) && (0 < s->bulk_requests)) { LOG(GNUNET_ERROR_TYPE_DEBUG, "No lock pending, recalculating\n"); distribute_bandwidth_in_network (s, NULL, NULL); s->bulk_requests = 0; } } /** * Add a new single address to a network * * @param solver the solver Handle * @param address the address to add * @param network network type of this address */ void GAS_proportional_address_add (void *solver, struct ATS_Address *address, uint32_t network); /** * Transport properties for this address have changed * * @param solver solver handle * @param address the address * @param type the ATSI type in HBO * @param abs_value the absolute value of the property * @param rel_value the normalized value */ void GAS_proportional_address_property_changed (void *solver, struct ATS_Address *address, uint32_t type, uint32_t abs_value, double rel_value) { struct GAS_PROPORTIONAL_Handle *s; struct Network *n; struct AddressSolverInformation *asi; GNUNET_assert(NULL != solver); GNUNET_assert(NULL != address); s = (struct GAS_PROPORTIONAL_Handle *) solver; asi = address->solver_information; n = asi->network; if (NULL == n) { GNUNET_break(0); return; } LOG(GNUNET_ERROR_TYPE_DEBUG, "Property `%s' for peer `%s' address %p changed to %.2f \n", GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer), address, rel_value); switch (type) { case GNUNET_ATS_UTILIZATION_OUT: case GNUNET_ATS_UTILIZATION_IN: case GNUNET_ATS_UTILIZATION_PAYLOAD_IN: case GNUNET_ATS_UTILIZATION_PAYLOAD_OUT: case GNUNET_ATS_QUALITY_NET_DELAY: case GNUNET_ATS_QUALITY_NET_DISTANCE: case GNUNET_ATS_COST_WAN: case GNUNET_ATS_COST_LAN: case GNUNET_ATS_COST_WLAN: distribute_bandwidth_in_network (s, n, NULL); break; } } /** * Transport session for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param cur_session the current session * @param new_session the new session */ void GAS_proportional_address_session_changed (void *solver, struct ATS_Address *address, uint32_t cur_session, uint32_t new_session) { if (cur_session != new_session) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Session changed from %u to %u\n", cur_session, new_session); } } /** * Usage for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param in_use usage state */ void GAS_proportional_address_inuse_changed (void *solver, struct ATS_Address *address, int in_use) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Usage changed to %s\n", (GNUNET_YES == in_use) ? "USED" : "UNUSED"); } /** * Network scope for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param current_network the current network * @param new_network the new network */ void GAS_proportional_address_change_network (void *solver, struct ATS_Address *address, uint32_t current_network, uint32_t new_network) { struct GAS_PROPORTIONAL_Handle *s = (struct GAS_PROPORTIONAL_Handle *) solver; struct AddressSolverInformation *asi; int save_active = GNUNET_NO; struct Network *new_net = NULL; if (current_network == new_network) { GNUNET_break(0); return; } /* Network changed */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Network type changed, moving %s address from `%s' to `%s'\n", (GNUNET_YES == address->active) ? "active" : "inactive", GNUNET_ATS_print_network_type (current_network), GNUNET_ATS_print_network_type (new_network)); save_active = address->active; /* Disable and assign no bandwidth */ address->active = GNUNET_NO; address->assigned_bw_in = BANDWIDTH_ZERO; /* no bandwidth assigned */ address->assigned_bw_out = BANDWIDTH_ZERO; /* no bandwidth assigned */ /* Remove from old network */ GAS_proportional_address_delete (solver, address, GNUNET_NO); /* Set new network type */ if (NULL == (new_net = get_network (solver, new_network))) { /* Address changed to invalid network... */ LOG(GNUNET_ERROR_TYPE_ERROR, _("Invalid network type `%u' `%s': Disconnect!\n"), new_network, GNUNET_ATS_print_network_type (new_network)); /* Find new address to suggest since no bandwidth in network*/ if (NULL == GAS_proportional_get_preferred_address (s, &address->peer)) { /* No alternative address found, disconnect peer */ s->bw_changed (s->bw_changed_cls, address); } return; } /* Add to new network and update*/ asi = address->solver_information; asi->network = new_net; GAS_proportional_address_add (solver, address, new_network); if (GNUNET_YES == save_active) { /* check if bandwidth available in new network */ if (GNUNET_YES == (is_bandwidth_available_in_network (new_net))) { /* Assign bandwidth to updated address */ address->active = GNUNET_YES; addresse_increment (s, new_net, GNUNET_NO, GNUNET_YES); distribute_bandwidth_in_network (solver, new_net, NULL); } else { LOG(GNUNET_ERROR_TYPE_DEBUG, "Not enough bandwidth in new network, suggesting alternative address ..\n"); /* Find new address to suggest since no bandwidth in network*/ if (NULL == GAS_proportional_get_preferred_address (s, &address->peer)) { /* No alternative address found, disconnect peer */ s->bw_changed (s->bw_changed_cls, address); } } } } /** * Add a new single address to a network * * @param solver the solver Handle * @param address the address to add * @param network network type of this address */ void GAS_proportional_address_add (void *solver, struct ATS_Address *address, uint32_t network) { struct GAS_PROPORTIONAL_Handle *s = solver; struct Network *net = NULL; struct AddressWrapper *aw = NULL; struct AddressSolverInformation *asi; GNUNET_assert(NULL != s); net = get_network (s, network); if (NULL == net) { GNUNET_break(0); return; } aw = GNUNET_new (struct AddressWrapper); aw->addr = address; GNUNET_CONTAINER_DLL_insert(net->head, net->tail, aw); addresse_increment (s, net, GNUNET_YES, GNUNET_NO); asi = GNUNET_new (struct AddressSolverInformation); asi->network = net; asi->calculated_quota_in_NBO = 0; asi->calculated_quota_out_NBO = 0; aw->addr->solver_information = asi; if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (s->requests, &address->peer)) { if (NULL == get_active_address (s, s->addresses, &address->peer)) { if (NULL != GAS_proportional_get_preferred_address (s, &address->peer)) s->bw_changed (s->bw_changed_cls, (struct ATS_Address *) address); } } LOG(GNUNET_ERROR_TYPE_INFO, "Adding new address %p for peer `%s', now total %u and active %u addresses in network `%s'\n", address, GNUNET_i2s(&address->peer), net->total_addresses, net->active_addresses, net->desc); } /* end of plugin_ats_proportional.c */ gnunet-0.10.1/src/ats/test_ats_solver_ril.conf0000644000175000017500000000117012320466615016331 00000000000000@INLINE@ test_ats_solver_default.conf [ats] #PREFIX = valgrind --leak-check=yes MODE = RIL # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 64 KiB UNSPECIFIED_QUOTA_OUT = 64 KiB # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited # LAN LAN_QUOTA_IN = unlimited LAN_QUOTA_OUT = unlimited # WAN WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB # WLAN WLAN_QUOTA_IN = 512 WLAN_QUOTA_OUT = 512 # Reinforcement Learning Parameters RIL_STEP_TIME_MIN = 500 ms RIL_STEP_TIME_MAX = 1000 ms RIL_ALGORITHM = Q RIL_DISCOUNT_BETA = 0.7 RIL_GRADIENT_STEP_SIZE = 0.3 RIL_TRACE_DECAY = 0.2 RIL_EXPLORE_RATIO = 0.1 RIL_GLOBAL_REWARD_SHARE = 1gnunet-0.10.1/src/ats/gnunet-service-ats.h0000644000175000017500000000233612225777503015302 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats.h * @brief ats service * @author Matthias Wachs * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_ATS_H #define GNUNET_SERVICE_ATS_H #include "gnunet_statistics_service.h" #define GAS_normalization_queue_length 3 #define BANDWIDTH_ZERO GNUNET_BANDWIDTH_value_init (0) /** * Handle for statistics. */ extern struct GNUNET_STATISTICS_Handle *GSA_stats; #endif gnunet-0.10.1/src/ats/gnunet-service-ats.c0000644000175000017500000001363612225777502015301 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats.c * @brief ats service * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_ats_service.h" #include "gnunet-service-ats.h" #include "gnunet-service-ats_addresses.h" #include "gnunet-service-ats_performance.h" #include "gnunet-service-ats_scheduling.h" #include "gnunet-service-ats_reservations.h" #include "ats.h" /** * Handle for statistics. */ struct GNUNET_STATISTICS_Handle *GSA_stats; static struct GNUNET_SERVER_Handle *GSA_server; struct GAS_Addresses_Handle *GSA_addresses; /** * We have received a 'ClientStartMessage' from a client. Find out which * type of client it is and notify the respective subsystem. * * @param cls closure, unused * @param client handle to the client * @param message the start message */ static void handle_ats_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ClientStartMessage *msg = (const struct ClientStartMessage *) message; enum StartFlag flag; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ATS_START"); flag = ntohl (msg->start_flag); switch (flag) { case START_FLAG_SCHEDULING: if (GNUNET_OK != GAS_scheduling_add_client (client)) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } break; case START_FLAG_PERFORMANCE_WITH_PIC: GAS_performance_add_client (client, flag); break; case START_FLAG_PERFORMANCE_NO_PIC: GAS_performance_add_client (client, flag); break; default: GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * A client disconnected from us. Tear down the local client * record. * * @param cls unused * @param client handle of the client */ static void client_disconnect_handler (void *cls, struct GNUNET_SERVER_Client *client) { if (NULL == client) return; GAS_scheduling_remove_client (client); GAS_performance_remove_client (client); } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GAS_addresses_done (GSA_addresses); GAS_scheduling_done (); GAS_performance_done (); GAS_reservations_done (); GNUNET_SERVER_disconnect_notify_cancel (GSA_server, &client_disconnect_handler, NULL); if (NULL != GSA_stats) { GNUNET_STATISTICS_destroy (GSA_stats, GNUNET_NO); GSA_stats = NULL; } } /** * Process template requests. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_ats_start, NULL, GNUNET_MESSAGE_TYPE_ATS_START, sizeof (struct ClientStartMessage)}, {&GAS_handle_request_address, NULL, GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS, sizeof (struct RequestAddressMessage)}, {&GAS_handle_request_address_cancel, NULL, GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL, sizeof (struct RequestAddressMessage)}, {&GAS_handle_request_address_list, NULL, GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_REQUEST, sizeof (struct AddressListRequestMessage)}, {&GAS_handle_address_add, NULL, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_ADD, 0}, {&GAS_handle_address_update, NULL, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE, 0}, {&GAS_handle_address_in_use, NULL, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_IN_USE, 0}, {&GAS_handle_address_destroyed, NULL, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED, 0}, {&GAS_handle_reservation_request, NULL, GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST, sizeof (struct ReservationRequestMessage)}, {&GAS_handle_preference_change, NULL, GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE, 0}, {&GAS_handle_preference_feedback, NULL, GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_FEEDBACK, 0}, {&GAS_handle_reset_backoff, NULL, GNUNET_MESSAGE_TYPE_ATS_RESET_BACKOFF, sizeof (struct ResetBackoffMessage)}, {NULL, NULL, 0, 0} }; GSA_server = server; GSA_stats = GNUNET_STATISTICS_create ("ats", cfg); GAS_reservations_init (); GSA_addresses = GAS_addresses_init (cfg, GSA_stats); GAS_performance_init (server, GSA_addresses); GAS_scheduling_init (server, GSA_addresses); GNUNET_SERVER_disconnect_notify (server, &client_disconnect_handler, NULL); GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, NULL); } /** * The main function for the ats service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "ats", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-ats.c */ gnunet-0.10.1/src/ats/gnunet-service-ats_reservations.c0000644000175000017500000001146112272461615020074 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_reservations.c * @brief ats service, inbound bandwidth reservation management * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-ats_reservations.h" /** * Number of seconds that available bandwidth carries over * (can accumulate). */ #define MAX_BANDWIDTH_CARRY_S 5 /** * Map of peer identities to 'struct GNUNET_BANDWIDTH_Tracker *'s */ static struct GNUNET_CONTAINER_MultiPeerMap *trackers; /** * Reserve the given amount of incoming bandwidth (in bytes) from the * given peer. If a reservation is not possible right now, return how * long the client should wait before trying again. * * @param peer peer to reserve bandwidth from * @param amount number of bytes to reserve * @return 0 if the reservation was successful, FOREVER if the * peer is not connected, otherwise the time to wait * until the reservation might succeed */ struct GNUNET_TIME_Relative GAS_reservations_reserve (const struct GNUNET_PeerIdentity *peer, int32_t amount) { struct GNUNET_BANDWIDTH_Tracker *tracker; struct GNUNET_TIME_Relative ret; tracker = GNUNET_CONTAINER_multipeermap_get (trackers, peer); if (NULL == tracker) return GNUNET_TIME_UNIT_ZERO; /* not connected, satisfy now */ if (amount >= 0) { ret = GNUNET_BANDWIDTH_tracker_get_delay (tracker, amount); if (ret.rel_value_us > 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delay to satisfy reservation for %d bytes is %s\n", (int) amount, GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); return ret; } } (void) GNUNET_BANDWIDTH_tracker_consume (tracker, amount); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reserved %d bytes\n", (int) amount); return GNUNET_TIME_UNIT_ZERO; } /** * Set the amount of bandwidth the other peer could currently transmit * to us (as far as we know) to the given value. * * @param peer identity of the peer * @param bandwidth_in currently available bandwidth from that peer to * this peer (estimate) */ void GAS_reservations_set_bandwidth (const struct GNUNET_PeerIdentity *peer, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { struct GNUNET_BANDWIDTH_Tracker *tracker; tracker = GNUNET_CONTAINER_multipeermap_get (trackers, peer); if (0 == ntohl (bandwidth_in.value__)) { if (NULL == tracker) return; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (trackers, peer, tracker)); GNUNET_free (tracker); return; } if (NULL == tracker) { tracker = GNUNET_new (struct GNUNET_BANDWIDTH_Tracker); GNUNET_BANDWIDTH_tracker_init (tracker, NULL, NULL, bandwidth_in, MAX_BANDWIDTH_CARRY_S); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (trackers, peer, tracker, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return; } GNUNET_BANDWIDTH_tracker_update_quota (tracker, bandwidth_in); } /** * Initialize reservations subsystem. */ void GAS_reservations_init () { trackers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); } /** * Free memory of bandwidth tracker. * * @param cls NULL * @param key peer identity (unused) * @param value the 'struct GNUNET_BANDWIDTH_Tracker' to free * @return GNUNET_OK (continue to iterate) */ static int free_tracker (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_BANDWIDTH_Tracker *tracker = value; GNUNET_free (tracker); return GNUNET_OK; } /** * Shutdown reservations subsystem. */ void GAS_reservations_done () { GNUNET_CONTAINER_multipeermap_iterate (trackers, &free_tracker, NULL); GNUNET_CONTAINER_multipeermap_destroy (trackers); } /* end of gnunet-service-ats_reservations.c */ gnunet-0.10.1/src/ats/plugin_ats_proportional.h0000644000175000017500000001174712251551532016531 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/plugin_ats_proportional.h * @brief ATS proportional solver * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_statistics_service.h" #include "gnunet_ats_plugin.h" #include "gnunet-service-ats_addresses.h" /** * ATS proportional solver * * General description */ /** * Changes the preferences for a peer in the problem * * @param solver the solver handle * @param peer the peer to change the preference for * @param kind the kind to change the preference * @param pref_rel the normalized preference value for this kind over all clients */ void GAS_proportional_address_change_preference (void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel); /** * Get application feedback for a peer * * @param solver the solver handle * @param application the application * @param peer the peer to change the preference for * @param scope the time interval for this feedback: [now - scope .. now] * @param kind the kind to change the preference * @param score the score */ void GAS_proportional_address_preference_feedback (void *solver, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score); /** * Shutdown the proportional problem solver * * @param solver the respective handle to shutdown */ void GAS_proportional_done (void * solver); /** * Add a single address within a network to the solver * * @param solver the solver Handle * @param address the address to add * @param network network type of this address */ void GAS_proportional_address_add (void *solver, struct ATS_Address *address, uint32_t network); /** * Transport properties for this address have changed * * @param solver solver handle * @param address the address * @param type the ATSI type in HBO * @param abs_value the absolute value of the property * @param rel_value the normalized value */ void GAS_proportional_address_property_changed (void *solver, struct ATS_Address *address, uint32_t type, uint32_t abs_value, double rel_value); /** * Transport session for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param cur_session the current session * @param new_session the new session */ void GAS_proportional_address_session_changed (void *solver, struct ATS_Address *address, uint32_t cur_session, uint32_t new_session); /** * Usage for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param in_use usage state */ void GAS_proportional_address_inuse_changed (void *solver, struct ATS_Address *address, int in_use); /** * Network scope for this address has changed * * NOTE: values in addresses are already updated * * @param solver solver handle * @param address the address * @param current_network the current network * @param new_network the new network */ void GAS_proportional_address_change_network (void *solver, struct ATS_Address *address, uint32_t current_network, uint32_t new_network); /** * Remove an address from the solver * * @param solver the solver handle * @param address the address to remove * @param session_only delete only session not whole address */ void GAS_proportional_address_delete (void *solver, struct ATS_Address *address, int session_only); /** * Start a bulk operation * * @param solver the solver */ void GAS_proportional_bulk_start (void *solver); /** * Bulk operation done */ void GAS_proportional_bulk_stop (void *solver); /** * Stop notifying about address and bandwidth changes for this peer * * @param solver the proportional handle * @param peer the peer */ void GAS_proportional_stop_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer); /** * Get the prefered address for a specific peer * * @param solver the solver handle * @param peer the identity of the peer */ const struct ATS_Address * GAS_proportional_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer); /* end of plugin_ats_proportional.h */ gnunet-0.10.1/src/ats/test_ats_api_scheduling_destroy_address.c0000644000175000017500000001415112263724143021704 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_scheduling_destroy_address.c * @brief test destroying addresses in automatic transport selection scheduling API * @author Christian Grothoff * @author Matthias Wachs * */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { static int initial_ats_stat_cb = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if ((0 == value) && (initial_ats_stat_cb == GNUNET_NO)) { GNUNET_SCHEDULER_add_now (&end, NULL); } if ((0 == value) && (initial_ats_stat_cb == GNUNET_YES)) { initial_ats_stat_cb = GNUNET_NO; } if (1 == value) { GNUNET_ATS_address_destroyed (sched_ats, &test_hello_address, test_session); } return GNUNET_OK; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void got_initial_value (void *cls, int success) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got initial value\n"); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); } static int dummy_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got dummy stat %s%s:%s = %llu\n", is_persistent ? "!" : " ", subsystem, name, value); return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); GNUNET_STATISTICS_get (stats, "ats", "# addresses", TIMEOUT, &got_initial_value, &dummy_stat, GNUNET_CONFIGURATION_dup (cfg)); } int main (int argc, char *argv[]) { ret = 0; if (0 != GNUNET_TESTING_peer_run ("test-ats-api", "test_ats_api.conf", &run, NULL)) return 1; return ret; } /* end of file test_ats_api_scheduling_destroy_address.c */ gnunet-0.10.1/src/ats/test_ats_solver_add_address.c0000644000175000017500000001444212263724143017302 00000000000000/* if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_solver_add_address.c * @brief solver test: add address * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent); static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (1 == value) { GNUNET_SCHEDULER_add_now (&end, NULL); } return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", mycfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (mycfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); } int main (int argc, char *argv[]) { char *sep; char *src_filename = GNUNET_strdup (__FILE__); char *test_filename = GNUNET_strdup (argv[0]); char *config_file; char *solver; ret = 0; if (NULL == (sep = (strstr (src_filename,".c")))) { GNUNET_break (0); return -1; } sep[0] = '\0'; if (NULL != (sep = strstr (test_filename, ".exe"))) sep[0] = '\0'; if (NULL == (solver = strstr (test_filename, src_filename))) { GNUNET_break (0); return -1; } solver += strlen (src_filename) +1; if (0 == strcmp(solver, "proportional")) { config_file = "test_ats_solver_proportional.conf"; } else if (0 == strcmp(solver, "mlp")) { config_file = "test_ats_solver_mlp.conf"; } else if ((0 == strcmp(solver, "ril"))) { config_file = "test_ats_solver_ril.conf"; } else { GNUNET_break (0); GNUNET_free (src_filename); GNUNET_free (test_filename); return 1; } GNUNET_free (src_filename); GNUNET_free (test_filename); if (0 != GNUNET_TESTING_peer_run ("test-ats-solver", config_file, &run, NULL )) return GNUNET_SYSERR; return ret; } /* end of file test_ats_solver_add_address.c */ gnunet-0.10.1/src/ats/test_ats_api_scheduling_add_address_duplicate.c0000644000175000017500000001457012263724143023002 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_scheduling_add_address.c * @brief adding same addresses twice with scheduling API * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier wait_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (1 < value) { if (GNUNET_SCHEDULER_NO_TASK != wait_task) GNUNET_SCHEDULER_cancel (wait_task); GNUNET_SCHEDULER_add_now (&end_badly, NULL); } if (1 == value) { if (GNUNET_SCHEDULER_NO_TASK == wait_task) wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &end, NULL); } return GNUNET_OK; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); wait_task = GNUNET_SCHEDULER_NO_TASK; if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static int dummy_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got dummy stat %s%s:%s = %llu\n", is_persistent ? "!" : " ", subsystem, name, value); return GNUNET_OK; } static void got_initial_value (void *cls, int success) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got initial value\n"); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); /* Adding duplicate */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); GNUNET_STATISTICS_get (stats, "ats", "# addresses", TIMEOUT, &got_initial_value, &dummy_stat, GNUNET_CONFIGURATION_dup (cfg)); } int main (int argc, char *argv[]) { ret = 0; if (0 != GNUNET_TESTING_peer_run ("test-ats-api", "test_ats_api.conf", &run, NULL)) return 1; return ret; } /* end of file test_ats_api_scheduling_add_address.c */ gnunet-0.10.1/src/ats/Makefile.am0000644000175000017500000005015412320751517013434 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ ats.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif noinst_PROGRAMS = \ gnunet-ats-solver-eval if HAVE_LIBGLPK GN_LIBGLPK = -lglpk GN_MLP_LIB = libgnunet_plugin_ats_mlp.la GN_MLP_PERF = perf_ats_mlp GN_MLP_ADD_ADDRESS = test_ats_solver_add_address_mlp GN_MLP_ADD_REQUEST_ADDRESS = test_ats_solver_add_address_and_request_mlp GN_MLP_REQUEST_ADD_ADDRESS = test_ats_solver_request_and_add_address_mlp GN_MLP_REQUEST_DELETE_ADDRESS = test_ats_solver_request_and_delete_address_mlp GN_MLP_PREFERENCES_ADDRESS = test_ats_solver_preferences_mlp GN_MLP_ALTERNATIVE_DELETE_ADDRESS = test_ats_solver_alternative_after_delete_address_mlp GN_MLP_SOLVER_PERF = perf_ats_solver_mlp endif lib_LTLIBRARIES = libgnunetats.la plugin_LTLIBRARIES = \ libgnunet_plugin_ats_proportional.la \ $(GN_MLP_LIB) \ libgnunet_plugin_ats_ril.la gnunet_ats_solver_eval_SOURCES = \ gnunet-ats-solver-eval.c gnunet-ats-solver-eval.h \ gnunet-service-ats_normalization.c gnunet_ats_solver_eval_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(LTLIBINTL) gnunet_ats_solver_eval_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la libgnunetats_la_SOURCES = \ ats_api_scheduling.c \ ats_api_performance.c libgnunetats_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetats_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 4:0:0 libgnunet_plugin_ats_proportional_la_SOURCES = \ plugin_ats_proportional.c libgnunet_plugin_ats_proportional_la_LIBADD = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_ats_proportional_la_DEPENDENCIES = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_ats_proportional_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) if HAVE_LIBGLPK libgnunet_plugin_ats_mlp_la_SOURCES = \ plugin_ats_mlp.c libgnunet_plugin_ats_mlp_la_LIBADD = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_ats_mlp_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) $(GN_LIBGLPK) libgnunet_plugin_ats_mlp_la_DEPENDENCIES = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la endif libgnunet_plugin_ats_ril_la_SOURCES = \ plugin_ats_ril.c libgnunet_plugin_ats_ril_la_LIBADD = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_ats_ril_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_ats_ril_la_DEPENDENCIES = \ libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la libexec_PROGRAMS = \ gnunet-service-ats gnunet_service_ats_SOURCES = \ gnunet-service-ats.c gnunet-service-ats.h\ gnunet-service-ats_addresses.c gnunet-service-ats_addresses.h \ gnunet-service-ats_normalization.c gnunet-service-ats_normalization.h \ gnunet-service-ats_performance.c gnunet-service-ats_performance.h \ gnunet-service-ats_scheduling.c gnunet-service-ats_scheduling.h \ gnunet-service-ats_reservations.c gnunet-service-ats_reservations.h gnunet_service_ats_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetats.la \ $(GN_LIBINTL) gnunet_service_ats_DEPENDENCIES = \ libgnunetats.la if HAVE_TESTING TESTING_TESTS = \ test_ats_api_scheduling_init \ test_ats_api_scheduling_add_address \ test_ats_api_scheduling_add_address_duplicate \ test_ats_api_scheduling_add_address_inbound \ test_ats_api_scheduling_destroy_address \ test_ats_api_scheduling_destroy_address_twice \ test_ats_api_scheduling_add_session \ test_ats_api_scheduling_destroy_session \ test_ats_api_performance_list_all_addresses \ test_ats_api_performance_list_peer_addresses \ test_ats_api_performance_list_all_addresses_active \ test_ats_api_performance_monitor \ test_ats_api_performance_monitor_initial_callback \ test_ats_solver_add_address_proportional \ test_ats_solver_add_address_and_request_proportional \ test_ats_solver_request_and_add_address_proportional \ test_ats_solver_request_and_delete_address_proportional \ test_ats_solver_alternative_after_delete_address_proportional \ test_ats_solver_preferences_proportional \ test_ats_solver_preferences_ril \ $(GN_MLP_ADD_ADDRESS) \ $(GN_MLP_ADD_REQUEST_ADDRESS) \ $(GN_MLP_REQUEST_ADD_ADDRESS) \ $(GN_MLP_REQUEST_DELETE_ADDRESS) \ $(GN_MLP_ALTERNATIVE_DELETE_ADDRESS) \ $(GN_MLP_PREFERENCES_ADDRESS) \ test_ats_solver_add_address_ril \ test_ats_solver_add_address_and_request_ril \ test_ats_solver_request_and_add_address_ril \ test_ats_solver_request_and_delete_address_ril \ test_ats_solver_alternative_after_delete_address_ril \ perf_ats_solver_proportional \ $(GN_MLP_SOLVER_PERF) \ perf_ats_solver_ril endif check_PROGRAMS = \ $(TESTING_TESTS) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif # scheduling API tests test_ats_api_scheduling_init_SOURCES = \ test_ats_api_scheduling_init.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_init_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_add_address_SOURCES = \ test_ats_api_scheduling_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_add_address_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_add_address_inbound_SOURCES = \ test_ats_api_scheduling_add_address_inbound.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_add_address_inbound_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_add_address_duplicate_SOURCES = \ test_ats_api_scheduling_add_address_duplicate.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_add_address_duplicate_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_destroy_address_SOURCES = \ test_ats_api_scheduling_destroy_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_destroy_address_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_destroy_address_twice_SOURCES = \ test_ats_api_scheduling_destroy_address_twice.c \ test_ats_api_common.c test_ats_api_common.h test_ats_api_scheduling_destroy_address_twice_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_add_session_SOURCES = \ test_ats_api_scheduling_add_session.c test_ats_api_common.c test_ats_api_scheduling_add_session_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_scheduling_destroy_session_SOURCES = \ test_ats_api_scheduling_destroy_session.c test_ats_api_common.c test_ats_api_scheduling_destroy_session_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la # performance API tests test_ats_api_performance_list_all_addresses_SOURCES = \ test_ats_api_performance_list_all_addresses.c test_ats_api_performance_list_all_addresses_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_performance_list_peer_addresses_SOURCES = \ test_ats_api_performance_list_peer_addresses.c test_ats_api_performance_list_peer_addresses_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_performance_list_all_addresses_active_SOURCES = \ test_ats_api_performance_list_all_addresses_active.c test_ats_api_performance_list_all_addresses_active_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_performance_monitor_SOURCES = \ test_ats_api_performance_monitor.c test_ats_api_performance_monitor_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_api_performance_monitor_initial_callback_SOURCES = \ test_ats_api_performance_monitor_initial_callback.c test_ats_api_performance_monitor_initial_callback_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la # solver tests test_ats_solver_add_address_proportional_SOURCES = \ test_ats_solver_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la if HAVE_LIBGLPK test_ats_solver_add_address_mlp_SOURCES = \ test_ats_solver_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_mlp_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la endif test_ats_solver_add_address_ril_SOURCES = \ test_ats_solver_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_add_address_and_request_proportional_SOURCES = \ test_ats_solver_add_address_and_request.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_and_request_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la if HAVE_LIBGLPK test_ats_solver_add_address_and_request_mlp_SOURCES = \ test_ats_solver_add_address_and_request.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_and_request_mlp_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la endif test_ats_solver_add_address_and_request_ril_SOURCES = \ test_ats_solver_add_address_and_request.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_add_address_and_request_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_request_and_add_address_proportional_SOURCES = \ test_ats_solver_request_and_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_add_address_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la if HAVE_LIBGLPK test_ats_solver_request_and_add_address_mlp_SOURCES = \ test_ats_solver_request_and_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_add_address_mlp_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la endif test_ats_solver_request_and_add_address_ril_SOURCES = \ test_ats_solver_request_and_add_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_add_address_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_request_and_delete_address_proportional_SOURCES = \ test_ats_solver_request_and_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_delete_address_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la if HAVE_LIBGLPK test_ats_solver_request_and_delete_address_mlp_SOURCES = \ test_ats_solver_request_and_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_delete_address_mlp_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la endif test_ats_solver_request_and_delete_address_ril_SOURCES = \ test_ats_solver_request_and_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_request_and_delete_address_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_alternative_after_delete_address_proportional_SOURCES = \ test_ats_solver_alternative_after_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_alternative_after_delete_address_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_preferences_proportional_SOURCES = \ test_ats_solver_preferences.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_preferences_proportional_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la if HAVE_LIBGLPK test_ats_solver_alternative_after_delete_address_mlp_SOURCES = \ test_ats_solver_alternative_after_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_alternative_after_delete_address_mlp_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_ats_solver_preferences_mlp_SOURCES = \ test_ats_solver_preferences.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_preferences_mlp_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la endif test_ats_solver_alternative_after_delete_address_ril_SOURCES = \ test_ats_solver_alternative_after_delete_address.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_alternative_after_delete_address_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la #perf_ats_mlp_SOURCES = \ # $(GN_MLP_SRC) perf_ats_mlp.c test_ats_api_common.c gnunet-service-ats_normalization.c #perf_ats_mlp_LDADD = \ # $(GN_LIBGLPK) \ # $(top_builddir)/src/util/libgnunetutil.la \ # $(top_builddir)/src/statistics/libgnunetstatistics.la \ # $(top_builddir)/src/ats/libgnunetats.la perf_ats_solver_mlp_SOURCES = \ perf_ats_solver.c test_ats_api_common.c gnunet-service-ats_normalization.c perf_ats_solver_mlp_LDADD = \ $(GN_LIBGLPK) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la perf_ats_solver_proportional_SOURCES = \ perf_ats_solver.c test_ats_api_common.c gnunet-service-ats_normalization.c perf_ats_solver_proportional_LDADD = \ $(GN_LIBGLPK) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la perf_ats_solver_ril_SOURCES = \ perf_ats_solver.c test_ats_api_common.c gnunet-service-ats_normalization.c perf_ats_solver_ril_LDADD = \ $(GN_LIBGLPK) \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/ats/libgnunetats.la test_ats_solver_preferences_ril_SOURCES = \ test_ats_solver_preferences.c \ test_ats_api_common.c test_ats_api_common.h test_ats_solver_preferences_ril_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la EXTRA_DIST = \ ats.h \ plugin_ats_proportional.h \ plugin_ats_mlp.h \ plugin_ats_ril.h \ test_ats_api.conf \ test_ats_mlp.conf \ test_ats_solver_default.conf \ test_ats_solver_proportional.conf \ test_ats_solver_mlp.conf \ test_ats_solver_ril.conf \ perf_ats_solver_mlp.conf \ perf_ats_solver_proportional.conf \ perf_ats_solver_ril.conf \ perf_ats_solver.conf gnunet-0.10.1/src/ats/gnunet-service-ats_addresses.c0000644000175000017500000022475612316473376017350 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_addresses.c * @brief ats service address management * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_ats_plugin.h" #include "gnunet-service-ats.h" #include "gnunet-service-ats_addresses.h" #include "gnunet-service-ats_normalization.h" #include "gnunet-service-ats_performance.h" #include "gnunet-service-ats_scheduling.h" #include "gnunet-service-ats_reservations.h" /** * NOTE: Do not change this documentation. This documentation is based on * gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex * use build_txt.sh to generate plaintext output * * 1 ATS addresses : ATS address management * * This ATS addresses ("addresses") component manages the addresses known to * ATS service and suggests addresses to transport service when it is * interested in address suggestion for a peer. ATS addresses also * instantiates the bandwidth assignment mechanism (solver), notifies it * about changes to addresses and forwards changes to bandwidth assignments * to transport, depending if transport is interested in this change. * * 1.1 Input data * * 1.1.1 Addresses * * Addresses are added by specifying peer ID, plugin, address, address length * and session, if available. ATS information can be specified if available. * * 1.1.2 Networks * * ATS specifies a fix set of networks an address can belong to. For each * network an inbound and outbound quota will be specified. The available * networks and addtional helper varaibles are defined in * gnunet_ats_service.h. At the moment 5 networks are defined: * * GNUNET_ATS_NET_UNSPECIFIED * * GNUNET_ATS_NET_LOOPBACK * * GNUNET_ATS_NET_LAN * * GNUNET_ATS_NET_WAN * * GNUNET_ATS_NET_WLAN * * The total number of networks defined is stored in * GNUNET_ATS_NetworkTypeCount GNUNET_ATS_NetworkType can be used array * initializer for an int array, while GNUNET_ATS_NetworkType is an * initializer for a char array containing a string description of all * networks * * 1.1.3 Quotas * * An inbound and outbound quota for each of the networks mentioned in 1.1.2 * is loaded from ats configuration during initialization. This quota defines * to total amount of inbound and outbound traffic allowed for a specific * network. The configuration values used are in section ats: * * "NETWORK"_QUOTA_IN = * * "NETWORK"_QUOTA_IN = * * You can specify quotas by setting the to a: * * unrestricted: unlimited * * number of bytes: e.g. 10240 * * fancy value: e.g. 64 Kib * * unlimited is defined as GNUNET_ATS_MaxBandwidthString and equivalent to * the value GNUNET_ATS_MaxBandwidth Important predefined values for quotas * are: * * GNUNET_ATS_DefaultBandwidth: 65536 * * GNUNET_ATS_MaxBandwidth: UINT32_MAX * * GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT: 1024 * * Details of loading quotas and default values will be described on * * 1.1.4 Preference values * * 1.2 Data structures used * * Addresse uses struct ATS_Address for each address. The structs are stored * in a linked list and provides a pointer void *solver_information for the * solver to store address specific information. It provides the int values * active which is set to GNUNET_YES if the address is select for transport * use and used, representing that transport service is actively using this * address. Address information are stored in peer, addr, addr_len, plugin. * * 1.3 Initialization * * During initialization a hashmap to store addresses is created. The quotas * for all networks defined for ATS are loaded from configuration. For each * network first the logic will check if the string * GNUNET_ATS_MaxBandwidthString is configured, if not it will try to convert * the configured value as a fancy size and if this fails it will try to use * it as a value_number. If no configuration value is found it will assign * GNUNET_ATS_DefaultBandwidth. The most important step is to load the * configured solver using configuration "[ats]:MODE". Current solvers are * MODE_PROPORTIONAL, MODE_MLP. Interaction is done using a solver API * * 1.4 Solver API * * Solver functions: * * s_init: init the solver with required information * * s_add: add a new address * * s_update: update ATS values or session for an address * * s_get: get prefered address for a peer * * s_del: delete an address * * s_pref: change preference value for a peer * * s_done: shutdown solver * * Callbacks: addresses provides a bandwidth_changed_cb callback to the * solver which is called when bandwidth assigned to peer has changed * * 1.5 Shutdown * * During shutdown all addresses are freed and the solver told to shutdown * * 1.6 Addresses and sessions * * Addresses consist of the address itself and a numerical session. When a * new address without a session is added it has no session, so it gets * session 0 assigned. When an address with a session is added and an address * object with session 0 is found, this object is updated with the session * otherwise a new address object with this session assigned is created. * * 1.6.1 Terminology * * Addresses a1,a2 with session s1, s2 are "exact" if: * (a1 == a2)&&(s1 == s2) * Addresses a1,a2 with session s1, s2 are "equivalent" if: * (a1 == a2)&&((s1 == s2)||(s1 == 0)||(s2 == 0) * * 1.7 Address management * * Transport service notifies ATS about changes to the addresses known to * him. * * 1.7.1 Adding an address * * When transport learns a new address it tells ATS and ATS is telling * addresses about it using GAS_address_add. If not known to addresses it * creates a new address object and calls solver's s_add. ATS information are * deserialized and solver is notified about the session and ATS information * using s_update. * * 1.7.2 Updating an address * * Addresses does an lookup up for the existing address with the given * session. If disassembles included ATS information and notifies the solver * using s_update about the update. * * 1.7.3 Deleting an address * * Addresses does an lookup for the exact address and session and if removes * this address. If session != 0 the session is set to 0 and the address is * kept. If session == 0, the addresses is removed. * * 1.7.4 Requesting an address suggestion * * The address client issues a request address message to be notified about * address suggestions for a specific peer. Addresses asks the solver with * s_get. If no address is available, it will not send a response, otherwise * it will respond with the choosen address. * * 1.7.5 Address suggestions * * Addresses will notify the client automatically on any bandwidth_changed_cb * by the solver if a address suggestion request is pending. If no address is * available it will not respond at all If the client is not interested * anymore, it has to cancel the address suggestion request. * * 1.7.6 Suggestions blocks and reset * * After suggesting an address it is blocked for ATS_BLOCKING_DELTA sec. to * prevent the client from being thrashed. If the client requires immediately * it can reset this block using GAS_addresses_handle_backoff_reset. * * 1.7.7 Marking address in use * * The client can notify addresses that it successfully uses an address and * wants this address to be kept by calling GSA_address_in_use. Adresses will * mark the address as used an notify the solver about the use. * * 1.7.8 Address lifecycle * * * (add address) * * (updated address) || (address in use) * * (delete address) * * 1.8 Bandwidth assignment * * The addresses are used to perform resource allocation operations. ATS * addresses takes care of instantiating the solver configured and notifies * the respective solver about address changes and receives changes to the * bandwidth assignment from the solver. The current bandwidth assignment is * sent to transport. The specific solvers will be described in the specific * section. * * 1.9 Changing peer preferences * * The bandwidth assigned to a peer can be influenced by setting a preference * for a peer. The prefernce will be given to to the solver with s_pref which * has to take care of the preference value */ /** * Pending Address suggestion requests */ struct GAS_Addresses_Suggestion_Requests { /** * Next in DLL */ struct GAS_Addresses_Suggestion_Requests *next; /** * Previous in DLL */ struct GAS_Addresses_Suggestion_Requests *prev; /** * Peer ID */ struct GNUNET_PeerIdentity id; }; /** * Pending Address suggestion requests */ struct GAS_Addresses_Preference_Clients { /** * Next in DLL */ struct GAS_Addresses_Preference_Clients *next; /** * Previous in DLL */ struct GAS_Addresses_Preference_Clients *prev; /** * Peer ID */ void *client; }; /** * Handle for ATS address component */ struct GAS_Addresses_Handle { /** * */ struct GNUNET_STATISTICS_Handle *stat; /** * A multihashmap to store all addresses */ struct GNUNET_CONTAINER_MultiPeerMap *addresses; /** * Is ATS addresses running */ int running; /** * Preferences clients */ int pref_clients; /** * Configured ATS solver */ int ats_mode; /** * Solver handle */ void *solver; /** * Address suggestion requests DLL head */ struct GAS_Addresses_Suggestion_Requests *pending_requests_head; /** * Address suggestion requests DLL tail */ struct GAS_Addresses_Suggestion_Requests *pending_requests_tail; /** * Address suggestion requests DLL head */ struct GAS_Addresses_Preference_Clients *preference_clients_head; /** * Address suggestion requests DLL head */ struct GAS_Addresses_Preference_Clients *preference_clients_tail; /** * Solver functions */ struct GNUNET_ATS_PluginEnvironment env; /** * Solver plugin name as string */ char *plugin; }; /** * Disassemble ATS information and update performance information in address * * Updates existing information and adds new information * * @param dest destination address * @param update source ATS information * @param update_count number of ATS information * @param delta_dest ats performance information which were updated * including previous value * @param delta_count number of ATS information in the delta * @return GNUNET_YES if address was address updated, GNUNET_NO otherwise */ static unsigned int disassemble_ats_information (struct ATS_Address *dest, const struct GNUNET_ATS_Information *update, uint32_t update_count, struct GNUNET_ATS_Information **delta_dest, uint32_t *delta_count) { int c1; int c2; int found; int change; struct GNUNET_ATS_Information add_atsi[update_count]; struct GNUNET_ATS_Information delta_atsi[update_count]; struct GNUNET_ATS_Information *tmp_atsi; uint32_t add_atsi_count; uint32_t delta_atsi_count; change = GNUNET_NO; add_atsi_count = 0; delta_atsi_count = 0; if (0 == update_count) return GNUNET_NO; if (NULL == dest->atsi) { /* Create performance information */ dest->atsi = GNUNET_malloc (update_count * sizeof (struct GNUNET_ATS_Information)); dest->atsi_count = update_count; memcpy (dest->atsi, update, update_count * sizeof(struct GNUNET_ATS_Information)); (*delta_dest) = GNUNET_malloc (update_count * sizeof (struct GNUNET_ATS_Information)); for (c1 = 0; c1 < update_count; c1++) { (*delta_dest)[c1].type = update[c1].type; (*delta_dest)[c1].value = htonl (GNUNET_ATS_VALUE_UNDEFINED); } (*delta_count) = update_count; return GNUNET_YES; } for (c1 = 0; c1 < update_count; c1++) { /* Update existing performance information */ found = GNUNET_NO; for (c2 = 0; c2 < dest->atsi_count; c2++) { if (update[c1].type == dest->atsi[c2].type) { if (update[c1].value != dest->atsi[c2].value) { /* Save previous value in delta */ delta_atsi[delta_atsi_count] = dest->atsi[c2]; delta_atsi_count++; /* Set new value */ dest->atsi[c2].value = update[c1].value; change = GNUNET_YES; } found = GNUNET_YES; break; } } if (GNUNET_NO == found) { add_atsi[add_atsi_count] = update[c1]; add_atsi_count++; delta_atsi[delta_atsi_count].type = update[c1].type; delta_atsi[delta_atsi_count].value = htonl (GNUNET_ATS_VALUE_UNDEFINED); delta_atsi_count++; } } if (add_atsi_count > 0) { /* Extend ats performance information */ tmp_atsi = GNUNET_malloc ((dest->atsi_count + add_atsi_count) * (sizeof (struct GNUNET_ATS_Information))); memcpy (tmp_atsi, dest->atsi, dest->atsi_count * sizeof(struct GNUNET_ATS_Information)); memcpy (&tmp_atsi[dest->atsi_count], add_atsi, add_atsi_count * sizeof(struct GNUNET_ATS_Information)); GNUNET_free(dest->atsi); dest->atsi = tmp_atsi; dest->atsi_count = dest->atsi_count + add_atsi_count; change = GNUNET_YES; } if (delta_atsi_count > 0) { /* Copy delta */ (*delta_dest) = GNUNET_malloc (delta_atsi_count * sizeof (struct GNUNET_ATS_Information)); memcpy ((*delta_dest), delta_atsi, delta_atsi_count * sizeof(struct GNUNET_ATS_Information)); (*delta_count) = delta_atsi_count; } return change; } /** * Free the given address * * @param addr address to destroy */ static void free_address (struct ATS_Address *addr) { GNUNET_free(addr->plugin); GNUNET_free_non_null(addr->atsi); GNUNET_free(addr); } /** * Create a ATS_address with the given information * * @param peer peer * @param plugin_name plugin * @param plugin_addr address * @param plugin_addr_len address length * @param local_address_info additional local info for the address * @param session_id session * @return the ATS_Address */ static struct ATS_Address * create_address (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id) { struct ATS_Address *aa = NULL; int c1; int c2; aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len); aa->peer = *peer; aa->addr_len = plugin_addr_len; aa->addr = &aa[1]; memcpy (&aa[1], plugin_addr, plugin_addr_len); aa->plugin = GNUNET_strdup (plugin_name); aa->session_id = session_id; aa->local_address_info = local_address_info; aa->active = GNUNET_NO; aa->used = GNUNET_NO; aa->solver_information = NULL; aa->atsi = NULL; aa->atsi_count = 0; aa->assigned_bw_in = GNUNET_BANDWIDTH_value_init (0); aa->assigned_bw_out = GNUNET_BANDWIDTH_value_init (0); for (c1 = 0; c1 < GNUNET_ATS_QualityPropertiesCount; c1++) { aa->atsin[c1].avg_queue_index = 0; for (c2 = 0; c2 < GAS_normalization_queue_length; c2++) aa->atsin[c1].atsi_abs[c2] = GNUNET_ATS_VALUE_UNDEFINED; } return aa; } struct CompareAddressContext { const struct ATS_Address *search; /* exact_address != NULL if address and session is equal */ struct ATS_Address *exact_address; /* exact_address != NULL if address and session is 0 */ struct ATS_Address *base_address; }; /** * Comapre addresses * * @param cls a CompareAddressContext containin the source address * @param key peer id * @param value the address to compare with * @return #GNUNET_YES to continue, #GNUNET_NO if address is founce */ static int compare_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct CompareAddressContext *cac = cls; struct ATS_Address *aa = value; /* Find an matching exact address: * * Compare by: * aa->addr_len == cac->search->addr_len * aa->plugin == cac->search->plugin * aa->addr == cac->search->addr * aa->session == cac->search->session * * return as exact address */ if ((aa->addr_len == cac->search->addr_len) && (0 == strcmp (aa->plugin, cac->search->plugin))) { if ((0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)) && (aa->session_id == cac->search->session_id)) cac->exact_address = aa; } /* Find an matching base address: * * Properties: * * aa->session_id == 0 * * Compare by: * aa->addr_len == cac->search->addr_len * aa->plugin == cac->search->plugin * aa->addr == cac->search->addr * * return as base address */ if ((aa->addr_len == cac->search->addr_len) && (0 == strcmp (aa->plugin, cac->search->plugin))) { if ((0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)) && (aa->session_id == 0)) cac->base_address = aa; } /* Find an matching exact address based on session: * * Properties: * * cac->search->addr_len == 0 * * Compare by: * aa->plugin == cac->search->plugin * aa->session_id == cac->search->session_id * * return as exact address */ if (0 == cac->search->addr_len) { if ((0 == strcmp (aa->plugin, cac->search->plugin)) && (aa->session_id == cac->search->session_id)) cac->exact_address = aa; } if (cac->exact_address == NULL ) return GNUNET_YES; /* Continue iteration to find exact address */ else return GNUNET_NO; /* Stop iteration since we have an exact address */ } /** * Find an existing equivalent address record. * Compares by peer identity and network address OR by session ID * (one of the two must match). * * @param handle the address handle * @param peer peer to lookup addresses for * @param addr existing address record * @return existing address record, NULL for none */ struct ATS_Address * find_equivalent_address (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const struct ATS_Address *addr) { struct CompareAddressContext cac; cac.exact_address = NULL; cac.base_address = NULL; cac.search = addr; GNUNET_CONTAINER_multipeermap_get_multiple (handle->addresses, peer, &compare_address_it, &cac); if (cac.exact_address == NULL) return cac.base_address; return cac.exact_address; } /** * Find the exact address * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param local_address_info the local address for the address * @param session_id session id, can be 0 * @return an ATS_address or NULL */ static struct ATS_Address * find_exact_address (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id) { struct ATS_Address *aa; struct ATS_Address *ea; aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, local_address_info, session_id); /* Get existing address or address with session == 0 */ ea = find_equivalent_address (handle, peer, aa); free_address (aa); if (ea == NULL ) return NULL ; else if (ea->session_id != session_id) return NULL ; return ea; } /** * Function allowing the solver to obtain normalized preference * values from solver * * @param cls unused * @param id the peer to return the normalized properties for * @return array of double values with |GNUNET_ATS_PreferenceCount| elements */ const double * get_preferences_cb (void *cls, const struct GNUNET_PeerIdentity *id) { return GAS_normalization_get_preferences_by_peer (id); } /** * Function allowing the solver to obtain normalized property * values for an address from solver * * @param cls unused * @param address the address * @return array of double values with |GNUNET_ATS_QualityPropertiesCount| elements */ const double * get_property_cb (void *cls, const struct ATS_Address *address) { return GAS_normalization_get_properties ((struct ATS_Address *) address); } /** * Extract an ATS performance info from an address * * @param address the address * @param type the type to extract in HBO * @return the value in HBO or GNUNET_ATS_VALUE_UNDEFINED in HBO if value does not exist */ static int get_performance_info (struct ATS_Address *address, uint32_t type) { int c1; GNUNET_assert(NULL != address); if ((NULL == address->atsi) || (0 == address->atsi_count)) return GNUNET_ATS_VALUE_UNDEFINED; for (c1 = 0; c1 < address->atsi_count; c1++) { if (ntohl (address->atsi[c1].type) == type) return ntohl (address->atsi[c1].value); } return GNUNET_ATS_VALUE_UNDEFINED; } /** * Add a new address for a peer. * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param local_address_info the local address for the address * @param session_id session id, can be 0 * @param atsi performance information for this address * @param atsi_count number of performance information contained */ void GAS_addresses_add (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { struct ATS_Address *new_address; struct ATS_Address *existing_address; struct GNUNET_ATS_Information *atsi_delta; uint32_t atsi_delta_count; uint32_t addr_net; uint32_t previous_session; int c1; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for peer `%s'\n", "ADDRESS ADD", GNUNET_i2s (peer)); if (GNUNET_NO == handle->running) return; GNUNET_assert(NULL != handle->addresses); new_address = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, local_address_info, session_id); atsi_delta = NULL; disassemble_ats_information (new_address, atsi, atsi_count, &atsi_delta, &atsi_delta_count); GNUNET_free_non_null(atsi_delta); addr_net = get_performance_info (new_address, GNUNET_ATS_NETWORK_TYPE); if (GNUNET_ATS_VALUE_UNDEFINED == addr_net) addr_net = GNUNET_ATS_NET_UNSPECIFIED; /* Get existing address or address with session == 0 */ existing_address = find_equivalent_address (handle, peer, new_address); if (existing_address == NULL ) { /* Add a new address */ new_address->t_added = GNUNET_TIME_absolute_get(); new_address->t_last_activity = GNUNET_TIME_absolute_get(); GNUNET_assert( GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (handle->addresses, peer, new_address, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); GNUNET_STATISTICS_set (handle->stat, "# addresses", GNUNET_CONTAINER_multipeermap_size (handle->addresses), GNUNET_NO); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Adding new address %p for peer `%s', length %u, session id %u, %s\n", new_address, GNUNET_i2s (peer), plugin_addr_len, session_id, GNUNET_ATS_print_network_type (addr_net)); /* Tell solver about new address */ handle->env.sf.s_add (handle->solver, new_address, addr_net); handle->env.sf.s_bulk_start (handle->solver); GAS_normalization_normalize_property (handle->addresses, new_address, atsi, atsi_count); handle->env.sf.s_bulk_stop (handle->solver); /* Notify performance clients about new address */ GAS_performance_notify_all_clients (&new_address->peer, new_address->plugin, new_address->addr, new_address->addr_len, new_address->session_id, new_address->atsi, new_address->atsi_count, new_address->assigned_bw_out, new_address->assigned_bw_in); return; } /* We have an existing address we can use, clean up new */ GNUNET_free(new_address->plugin); GNUNET_free_non_null(new_address->atsi); GNUNET_free(new_address); new_address = NULL; if (0 != existing_address->session_id) { /* Should not happen */ GNUNET_break(0); return; } addr_net = get_performance_info (existing_address, GNUNET_ATS_NETWORK_TYPE); if (GNUNET_ATS_VALUE_UNDEFINED == addr_net) addr_net = GNUNET_ATS_NET_UNSPECIFIED; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Found existing address for peer `%s' %p with new session %u in network %s\n", GNUNET_i2s (peer), existing_address, session_id, GNUNET_ATS_print_network_type (addr_net)); /* We have an address without an session, update this address */ existing_address->t_added = GNUNET_TIME_absolute_get(); existing_address->t_last_activity = GNUNET_TIME_absolute_get(); atsi_delta = NULL; atsi_delta_count = 0; if (GNUNET_YES == disassemble_ats_information (existing_address, atsi, atsi_count, &atsi_delta, &atsi_delta_count)) { /* Notify performance clients about properties */ GAS_performance_notify_all_clients (&existing_address->peer, existing_address->plugin, existing_address->addr, existing_address->addr_len, existing_address->session_id, existing_address->atsi, existing_address->atsi_count, existing_address->assigned_bw_out, existing_address->assigned_bw_in); for (c1 = 0; c1 < atsi_delta_count; c1++) { if ((GNUNET_ATS_NETWORK_TYPE == ntohl (atsi_delta[c1].type)) && (addr_net != ntohl (atsi_delta[c1].value))) { /* Network type changed */ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Address for peer `%s' %p changed from network %s to %s\n", GNUNET_i2s (peer), existing_address, GNUNET_ATS_print_network_type (addr_net), GNUNET_ATS_print_network_type (ntohl (atsi_delta[c1].value))); handle->env.sf.s_address_update_network (handle->solver, existing_address, ntohl (atsi_delta[c1].value), get_performance_info (existing_address, GNUNET_ATS_NETWORK_TYPE)); addr_net = get_performance_info (existing_address, GNUNET_ATS_NETWORK_TYPE); } } /* Notify solver about update with atsi information and session */ handle->env.sf.s_bulk_start (handle->solver); GAS_normalization_normalize_property (handle->addresses, existing_address, atsi, atsi_count); handle->env.sf.s_bulk_stop (handle->solver); } GNUNET_free_non_null(atsi_delta); /* Notify solver about new session */ if (existing_address->session_id == session_id) return; /* possible, can both be 0 since address is revalidated */ previous_session = existing_address->session_id; existing_address->session_id = session_id; handle->env.sf.s_address_update_session (handle->solver, existing_address, previous_session, session_id); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Updated existing address for peer `%s' %p length %u with new session %u in network %s\n", GNUNET_i2s (peer), existing_address, existing_address->addr_len, session_id, GNUNET_ATS_print_network_type (addr_net)); } /** * Update an address with a session or performance information for a peer. * * If an address was added without a session it will be updated with the * session * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param local_address_info the local address for the address * @param session_id session id, can be 0 * @param atsi performance information for this address * @param atsi_count number of performance information contained */ void GAS_addresses_update (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { struct ATS_Address *aa; struct GNUNET_ATS_Information *atsi_delta; uint32_t atsi_delta_count; uint32_t prev_session; int c1; if (GNUNET_NO == handle->running) return; GNUNET_assert(NULL != handle->addresses); /* Get existing address */ aa = find_exact_address (handle, peer, plugin_name, plugin_addr, plugin_addr_len, local_address_info, session_id); if (aa == NULL ) return; if (NULL == aa->solver_information) return; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for peer `%s' address \n", "ADDRESS UPDATE", GNUNET_i2s (peer), aa); /* Update address */ aa->t_last_activity = GNUNET_TIME_absolute_get(); if (session_id != aa->session_id) { /* Session changed */ prev_session = aa->session_id; aa->session_id = session_id; handle->env.sf.s_address_update_session (handle->solver, aa, prev_session, aa->session_id); } atsi_delta = NULL; atsi_delta_count = 0; if (GNUNET_YES == disassemble_ats_information (aa, atsi, atsi_count, &atsi_delta, &atsi_delta_count)) { /* ATS properties changed */ for (c1 = 0; c1 < atsi_delta_count; c1++) { if (GNUNET_ATS_NETWORK_TYPE == ntohl (atsi_delta[c1].type)) { /* Network type changed */ handle->env.sf.s_address_update_network (handle->solver, aa, ntohl (atsi_delta[c1].value), get_performance_info (aa, GNUNET_ATS_NETWORK_TYPE)); } } /* Notify performance clients about updated address */ GAS_performance_notify_all_clients (&aa->peer, aa->plugin, aa->addr, aa->addr_len, aa->session_id, aa->atsi, aa->atsi_count, aa->assigned_bw_out, aa->assigned_bw_in); handle->env.sf.s_bulk_start (handle->solver); GAS_normalization_normalize_property (handle->addresses, aa, atsi, atsi_count); handle->env.sf.s_bulk_stop (handle->solver); } GNUNET_free_non_null(atsi_delta); } struct DestroyContext { struct ATS_Address *aa; struct GAS_Addresses_Handle *handle; /** * GNUNET_NO : full address * GNUNET_YES : just session */ int result; }; /** * Delete an address * * If session != 0, just the session is deleted, the address itself still exists * If session == 0, remove full address * If session == 0 and addrlen == 0, destroy inbound address * * @param cls unused * @param key unused * @param value the 'struct ATS_Address' * @return GNUNET_OK (continue to iterate) */ static int destroy_by_session_id (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct DestroyContext *dc = cls; struct GAS_Addresses_Handle *handle = dc->handle; const struct ATS_Address *des = dc->aa; struct ATS_Address *aa = value; GNUNET_assert( 0 == memcmp (&aa->peer, &des->peer, sizeof(struct GNUNET_PeerIdentity))); if (des->session_id == 0) { /* Session == 0, remove full address */ if ((0 == strcmp (des->plugin, aa->plugin)) && (aa->addr_len == des->addr_len) && (0 == memcmp (des->addr, aa->addr, aa->addr_len))) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deleting full address for peer `%s' session %u %p\n", GNUNET_i2s (&aa->peer), aa->session_id, aa); /* Notify solver about deletion */ GNUNET_assert( GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (handle->addresses, &aa->peer, aa)); handle->env.sf.s_del (handle->solver, aa, GNUNET_NO); free_address (aa); dc->result = GNUNET_NO; return GNUNET_OK; /* Continue iteration */ } } else { /* Session != 0, just remove session */ if (aa->session_id != des->session_id) return GNUNET_OK; /* irrelevant */ if ((aa->session_id != 0) && (0 != strcmp (des->plugin, aa->plugin))) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Different plugins during removal: `%s' vs `%s' \n", des->plugin, aa->plugin); GNUNET_break(0); return GNUNET_OK; } if (GNUNET_HELLO_ADDRESS_INFO_INBOUND == (aa->local_address_info && GNUNET_HELLO_ADDRESS_INFO_INBOUND)) { /* Inbound connection died, delete full address */ GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deleting inbound address for peer `%s': `%s' session %u\n", GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); /* Notify solver about deletion */ GNUNET_assert( GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (handle->addresses, &aa->peer, aa)); handle->env.sf.s_del (handle->solver, aa, GNUNET_NO); free_address (aa); dc->result = GNUNET_NO; return GNUNET_OK; /* Continue iteration */ } else { /* Session died */ GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deleting session for peer `%s': `%s' %u\n", GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); /* Notify solver to delete session */ handle->env.sf.s_del (handle->solver, aa, GNUNET_YES); aa->session_id = 0; aa->active = GNUNET_NO; return GNUNET_OK; } } return GNUNET_OK; } /** * Remove an address or just a session for a peer. * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param local_address_info the local address for the address * @param session_id session id, can be 0 */ void GAS_addresses_destroy (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id) { struct ATS_Address *ea; struct DestroyContext dc; if (GNUNET_NO == handle->running) return; /* Get existing address */ ea = find_exact_address (handle, peer, plugin_name, plugin_addr, plugin_addr_len, local_address_info, session_id); if (ea == NULL ) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Tried to destroy unknown address for peer `%s' `%s' session id %u\n", GNUNET_i2s (peer), plugin_name, session_id); return; } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for peer `%s' address %p session %u\n", "ADDRESS DESTROY", GNUNET_i2s (peer), ea, session_id); GNUNET_break(0 < strlen (plugin_name)); dc.handle = handle; dc.aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, local_address_info, session_id); GNUNET_CONTAINER_multipeermap_get_multiple (handle->addresses, peer, &destroy_by_session_id, &dc); GNUNET_STATISTICS_set (handle->stat, "# addresses", GNUNET_CONTAINER_multipeermap_size (handle->addresses), GNUNET_NO); free_address (dc.aa); } /** * Notification about active use of an address. * in_use == GNUNET_YES: * This address is used to maintain an active connection with a peer. * in_use == GNUNET_NO: * This address is no longer used to maintain an active connection with a peer. * * Note: can only be called with in_use == GNUNET_NO if called with GNUNET_YES * before * * @param handle the address handle to use * @param peer peer * @param plugin_name transport plugin name * @param plugin_addr plugin address * @param plugin_addr_len length of the plugin address * @param local_address_info the local address for the address * @param session_id session id, can be 0 * @param in_use GNUNET_YES if GNUNET_NO * @return GNUNET_SYSERR on failure (address unknown ...) */ int GAS_addresses_in_use (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id, int in_use) { struct ATS_Address *ea; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for peer `%s'\n", "ADDRESS IN USE", GNUNET_i2s (peer)); if (GNUNET_NO == handle->running) return GNUNET_SYSERR; ea = find_exact_address (handle, peer, plugin_name, plugin_addr, plugin_addr_len, local_address_info, session_id); if (NULL == ea) { GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Trying to set unknown address `%s' `%s' `%u' to %s \n", GNUNET_i2s (peer), plugin_name, session_id, (GNUNET_NO == in_use) ? "NO" : "YES"); GNUNET_break(0); return GNUNET_SYSERR; } if (ea->used == in_use) { GNUNET_break(0); GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Address in use called multiple times for peer `%s': %s -> %s \n", GNUNET_i2s (peer), (GNUNET_NO == ea->used) ? "NO" : "YES", (GNUNET_NO == in_use) ? "NO" : "YES"); return GNUNET_SYSERR; } /* Tell solver about update */ ea->used = in_use; ea->t_last_activity = GNUNET_TIME_absolute_get(); handle->env.sf.s_address_update_inuse (handle->solver, ea, ea->used); return GNUNET_OK; } /** * Cancel address suggestions for a peer * * @param handle the address handle * @param peer the peer id */ void GAS_addresses_request_address_cancel (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer) { struct GAS_Addresses_Suggestion_Requests *cur = handle->pending_requests_head; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received request: `%s' for peer %s\n", "request_address_cancel", GNUNET_i2s (peer)); while (NULL != cur) { if (0 == memcmp (peer, &cur->id, sizeof(cur->id))) break; /* found */ cur = cur->next; } if (NULL == cur) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "No address requests pending for peer `%s', cannot remove!\n", GNUNET_i2s (peer)); return; } handle->env.sf.s_get_stop (handle->solver, peer); GAS_addresses_handle_backoff_reset (handle, peer); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Removed request pending for peer `%s\n", GNUNET_i2s (peer)); GNUNET_CONTAINER_DLL_remove(handle->pending_requests_head, handle->pending_requests_tail, cur); GNUNET_free(cur); } /** * Request address suggestions for a peer * * @param handle the address handle * @param peer the peer id */ void GAS_addresses_request_address (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer) { struct GAS_Addresses_Suggestion_Requests *cur = handle->pending_requests_head; struct ATS_Address *aa; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for peer `%s'\n", "REQUEST ADDRESS", GNUNET_i2s (peer)); if (GNUNET_NO == handle->running) return; while (NULL != cur) { if (0 == memcmp (peer, &cur->id, sizeof(cur->id))) break; /* already suggesting */ cur = cur->next; } if (NULL == cur) { cur = GNUNET_new (struct GAS_Addresses_Suggestion_Requests); cur->id = (*peer); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Adding new address suggestion request for `%s'\n", GNUNET_i2s (peer)); GNUNET_CONTAINER_DLL_insert(handle->pending_requests_head, handle->pending_requests_tail, cur); } /* Get prefered address from solver */ aa = (struct ATS_Address *) handle->env.sf.s_get (handle->solver, peer); if (NULL == aa) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Cannot suggest address for peer `%s'\n", GNUNET_i2s (peer)); return; } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Suggesting address %p for peer `%s'\n", aa, GNUNET_i2s (peer)); GAS_scheduling_transmit_address_suggestion (peer, aa->plugin, aa->addr, aa->addr_len, aa->local_address_info, aa->session_id, aa->atsi, aa->atsi_count, aa->assigned_bw_out, aa->assigned_bw_in); aa->block_interval = GNUNET_TIME_relative_add (aa->block_interval, ATS_BLOCKING_DELTA); aa->blocked_until = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), aa->block_interval); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Address %p ready for suggestion, block interval now %llu \n", aa, aa->block_interval); } /** * Iterator to reset address blocking * * @param cls not used * @param key the peer * @param value the address to reset * @return #GNUNET_OK to continue */ static int reset_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct ATS_Address *aa = value; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Resetting interval for peer `%s' address %p from %llu to 0\n", GNUNET_i2s (&aa->peer), aa, aa->block_interval); aa->blocked_until = GNUNET_TIME_UNIT_ZERO_ABS; aa->block_interval = GNUNET_TIME_UNIT_ZERO; return GNUNET_OK; } /** * Reset suggestion backoff for a peer * * Suggesting addresses is blocked for ATS_BLOCKING_DELTA. Blocking can be * reset using this function * * @param handle the address handle * @param peer the peer id */ void GAS_addresses_handle_backoff_reset (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for peer `%s'\n", "RESET BACKOFF", GNUNET_i2s (peer)); GNUNET_break( GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_get_multiple (handle->addresses, peer, &reset_address_it, NULL)); } static int eval_count_active_it (void *cls, const struct GNUNET_PeerIdentity *id, void *obj) { int *request_fulfilled = cls; struct ATS_Address *addr = obj; if (GNUNET_YES == addr->active) (*request_fulfilled) = GNUNET_YES; if (*request_fulfilled == GNUNET_YES) return GNUNET_NO; else return GNUNET_YES; } /** * Summary context */ struct SummaryContext { /** * Sum of the utilized inbound bandwidth per network */ unsigned long long bandwidth_in_assigned[GNUNET_ATS_NetworkTypeCount]; /** * Sum of the utilized outbound bandwidth per network */ unsigned long long bandwidth_out_assigned[GNUNET_ATS_NetworkTypeCount]; /** * Sum addresses within a network */ unsigned int addresses_in_network[GNUNET_ATS_NetworkTypeCount]; }; static int eval_sum_bw_used (void *cls, const struct GNUNET_PeerIdentity *id, void *obj) { struct SummaryContext *ctx = cls; struct ATS_Address *addr = obj; int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType; int net; int c; if (GNUNET_YES == addr->active) { net = get_performance_info (addr, GNUNET_ATS_NETWORK_TYPE); for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { if (net == networks[c]) { ctx->addresses_in_network[c] ++; ctx->bandwidth_in_assigned[c] += ntohl (addr->assigned_bw_in.value__); ctx->bandwidth_out_assigned[c] += ntohl (addr->assigned_bw_out.value__); } } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Active address in %s with (in/out) %u/%u Bps\n", GNUNET_ATS_print_network_type (net), (unsigned int) ntohl (addr->assigned_bw_in.value__), (unsigned int) ntohl (addr->assigned_bw_out.value__)); } return GNUNET_OK; } /** * Summary context */ struct RelativityContext { struct GAS_Addresses_Handle *ah; }; static int find_active_address (void *cls, const struct GNUNET_PeerIdentity *id, void *obj) { struct ATS_Address **res = cls; struct ATS_Address *addr = obj; if (GNUNET_YES == addr->active) (*res) = addr; if (NULL != (*res)) return GNUNET_NO; else return GNUNET_YES; } /** * Evaluate current bandwidth assignment * * @param ah address handle */ void GAS_addresses_evaluate_assignment (struct GAS_Addresses_Handle *ah) { struct GAS_Addresses_Suggestion_Requests *cur; struct GAS_Addresses_Preference_Clients *pcur; int c; float quality_requests_fulfilled = 0.0; float quality_bandwidth_utilization[GNUNET_ATS_NetworkTypeCount]; float quality_bandwidth_utilization_total = 0.0; float quality_application_requirements = 0.0; float guq = 0.0; int include_requests; int include_utilization; int include_requirements; /* Variable related to requests */ unsigned int requests_pending; unsigned int requests_fulfilled; unsigned int request_active; /* Variable related to utilization */ struct SummaryContext sum; struct ATS_Address *active_address; int network_count; /* Variables for preferences */ int prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceType; double pref_val; double prop_val; const double *norm_values; double prefs_fulfill[GNUNET_ATS_PreferenceCount]; int prefs_clients[GNUNET_ATS_PreferenceCount]; int rels; GNUNET_assert (NULL != ah); GNUNET_assert (NULL != ah->addresses); requests_pending = 0; requests_fulfilled = 0; /* 1) How many requests could be fulfilled? */ for (cur = ah->pending_requests_head; NULL != cur; cur = cur->next) { request_active = GNUNET_NO; GNUNET_CONTAINER_multipeermap_get_multiple (ah->addresses, &cur->id, &eval_count_active_it, &request_active); if (GNUNET_YES == request_active) requests_fulfilled ++; requests_pending ++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s': %u pending requests, %s\n", GNUNET_i2s (&cur->id), requests_pending, (GNUNET_YES == request_active) ? "active adress" : "no active address"); } if (requests_pending > 0) { quality_requests_fulfilled = (float) requests_fulfilled / requests_pending; include_requests = GNUNET_YES; } else { quality_requests_fulfilled = 0.0; include_requests = GNUNET_NO; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u pending requests, %u requests fullfilled\n", requests_pending, requests_fulfilled); /* 2) How well is bandwidth utilized? */ network_count = 0; for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { quality_bandwidth_utilization[c] = 0.0; sum.addresses_in_network[c] = 0; sum.bandwidth_in_assigned[c] = 0; sum.bandwidth_out_assigned[c] = 0; } GNUNET_CONTAINER_multipeermap_iterate(ah->addresses, &eval_sum_bw_used, &sum); for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { quality_bandwidth_utilization[c] = (((float)sum.bandwidth_out_assigned[c] / ah->env.out_quota[c]) + ((float)sum.bandwidth_in_assigned[c] / ah->env.in_quota[c])) / 2; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Utilization for network `%s': %f\n", GNUNET_ATS_print_network_type(ah->env.networks[c]), quality_bandwidth_utilization[c]); if (sum.addresses_in_network[c] > 0) { quality_bandwidth_utilization_total += quality_bandwidth_utilization[c]; network_count ++; } } if (0 < network_count) { quality_bandwidth_utilization_total /= network_count; include_utilization = GNUNET_YES; } else { quality_bandwidth_utilization_total = 0.0; include_utilization = GNUNET_NO; } /* 3) How well does selection match application requirements */ if (0 == ah->pref_clients) { include_requirements = 0; } else { for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) { prefs_fulfill[c] = 0.0; prefs_clients[c] = 0; } for (cur = ah->pending_requests_head; NULL != cur; cur = cur->next) { active_address = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (ah->addresses, &cur->id, &find_active_address, &active_address); for (pcur = ah->preference_clients_head; NULL != pcur; pcur = pcur->next) { for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) { if (prefs[c] == GNUNET_ATS_PREFERENCE_END) continue; pref_val = GAS_normalization_get_preferences_by_client (pcur->client, &cur->id, prefs[c]); if (-1.0 == pref_val) { GNUNET_break (0); continue; } if (DEFAULT_REL_PREFERENCE == pref_val) { /* Default preference value */ continue; } if (NULL != active_address) { norm_values = GAS_normalization_get_properties (active_address); prop_val = norm_values[c]; if ((norm_values[c] <= 1.0) || (norm_values[c] >= 2.0)) prop_val = DEFAULT_REL_QUALITY; } else { prop_val = DEFAULT_REL_QUALITY; } /* We now have preference values [1..2] and properties [1..2] */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u Client %p, Peer %s Property %s: pref: %.3f prop %.3f \n", c, pcur->client, GNUNET_i2s (&cur->id), GNUNET_ATS_print_preference_type(prefs[c]), pref_val, prop_val); prefs_fulfill[c] += (pref_val * prop_val) / 2; prefs_clients[c] ++; } } } rels = 0; for (c = 0; c < GNUNET_ATS_PreferenceCount; c++) { if (0 < prefs_clients[c]) { prefs_fulfill[c] /= prefs_clients[c]; rels ++; quality_application_requirements += prefs_fulfill[c]; } } if (rels > 0) quality_application_requirements /= rels; else quality_application_requirements = 0.0; include_requirements = 1; } /* GUQ */ if (include_requests + include_utilization + include_requirements > 0) guq = (quality_requests_fulfilled + quality_bandwidth_utilization_total + quality_application_requirements) / (include_requests + include_utilization + include_requirements); else guq = 0.0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requests fulfilled %.3f bandwidth utilized %.3f application preferences met %.3f => %.3f\n", quality_requests_fulfilled, quality_bandwidth_utilization_total, quality_application_requirements, guq); } /** * Solver information callback * * @param cls the closure * @param op the operation * @param stat operation status * @param add additional information */ static void solver_info_cb (void *cls, enum GAS_Solver_Operation op, enum GAS_Solver_Status stat, enum GAS_Solver_Additional_Information add) { char *add_info; switch (add) { case GAS_INFO_NONE: add_info = "GAS_INFO_NONE"; break; case GAS_INFO_FULL: add_info = "GAS_INFO_MLP_FULL"; break; case GAS_INFO_UPDATED: add_info = "GAS_INFO_MLP_UPDATED"; break; case GAS_INFO_PROP_ALL: add_info = "GAS_INFO_PROP_ALL"; break; case GAS_INFO_PROP_SINGLE: add_info = "GAS_INFO_PROP_SINGLE"; break; default: add_info = "INVALID"; break; } switch (op) { case GAS_OP_SOLVE_START: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s' `%s'\n", "GAS_OP_SOLVE_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info); return; case GAS_OP_SOLVE_STOP: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL", add_info); return; case GAS_OP_SOLVE_SETUP_START: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_SETUP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_SETUP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_MLP_LP_START: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_MLP_LP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_LP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_MLP_MLP_START: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_MLP_MLP_STOP: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_MLP_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_UPDATE_NOTIFICATION_START: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_START", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); return; case GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Solver notifies `%s' with result `%s'\n", "GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP", (GAS_STAT_SUCCESS == stat) ? "SUCCESS" : "FAIL"); GAS_addresses_evaluate_assignment (cls); return; default: break; } } /** * The preference changed for a peer * * @param cls the address handle * @param peer the peer * @param kind the ATS kind * @param pref_rel the new relative preference value */ static void normalized_preference_changed_cb (void *cls, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel) { GNUNET_assert(NULL != cls); struct GAS_Addresses_Handle *handle = cls; /* Tell solver about update */ handle->env.sf.s_pref (handle->solver, peer, kind, pref_rel); } /** * The relative value for a property changed * * @param cls the address handle * @param address the peer * @param type the ATS type * @param prop_rel the new relative preference value */ static void normalized_property_changed_cb (void *cls, struct ATS_Address *address, uint32_t type, double prop_rel) { struct GAS_Addresses_Handle *ah = (struct GAS_Addresses_Handle *) cls; GNUNET_assert(NULL != ah); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Normalized property %s for peer `%s' changed to %.3f \n", GNUNET_ATS_print_property_type (type), GNUNET_i2s (&address->peer), prop_rel); ah->env.sf.s_address_update_property (ah->solver, address, type, 0, prop_rel); } static struct GAS_Addresses_Preference_Clients * find_preference_client (struct GAS_Addresses_Handle *handle, void *client) { struct GAS_Addresses_Preference_Clients *cur; for (cur = handle->preference_clients_head; NULL != cur; cur = cur->next) { if (cur->client == client) return cur; } return NULL; } /** * A performance client disconnected * * @param handle address handle * @param client the client */ void GAS_addresses_preference_client_disconnect (struct GAS_Addresses_Handle *handle, void *client) { struct GAS_Addresses_Preference_Clients * pc; if (NULL != (pc = find_preference_client (handle, client))) { GNUNET_CONTAINER_DLL_remove (handle->preference_clients_head, handle->preference_clients_tail, pc); GNUNET_free (pc); GNUNET_assert (handle->pref_clients > 0); handle->pref_clients --; GNUNET_STATISTICS_set (handle->stat, "# active performance clients", handle->pref_clients, GNUNET_NO); } GAS_normalization_preference_client_disconnect (client); } /** * Change the preference for a peer * * @param handle the address handle * @param client the client sending this request * @param peer the peer id * @param kind the preference kind to change * @param score_abs the new preference score */ void GAS_addresses_preference_change (struct GAS_Addresses_Handle *handle, void *client, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, float score_abs) { struct GAS_Addresses_Preference_Clients * pc; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for peer `%s' for client %p\n", "CHANGE PREFERENCE", GNUNET_i2s (peer), client); if (GNUNET_NO == handle->running) return; if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (handle->addresses, peer)) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for unknown peer `%s' from client %p\n", "CHANGE PREFERENCE", GNUNET_i2s (peer), client); return; } if (NULL == find_preference_client (handle, client)) { pc = GNUNET_new (struct GAS_Addresses_Preference_Clients); pc->client = client; GNUNET_CONTAINER_DLL_insert (handle->preference_clients_head, handle->preference_clients_tail, pc); handle->pref_clients ++; GNUNET_STATISTICS_set (handle->stat, "# active performance clients", handle->pref_clients, GNUNET_NO); } handle->env.sf.s_bulk_start (handle->solver); /* Tell normalization about change, normalization will call callback if preference changed */ GAS_normalization_normalize_preference (client, peer, kind, score_abs); handle->env.sf.s_bulk_stop (handle->solver); } /** * Change the preference for a peer * * @param handle the address handle * @param application the client sending this request * @param peer the peer id * @param scope the time interval for this feedback: [now - scope .. now] * @param kind the preference kind to change * @param score_abs the new preference score */ void GAS_addresses_preference_feedback (struct GAS_Addresses_Handle *handle, void *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, float score_abs) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for peer `%s' for client %p\n", "PREFERENCE FEEDBACK", GNUNET_i2s (peer), application); if (GNUNET_NO == handle->running) return; if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (handle->addresses, peer)) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received `%s' for unknown peer `%s' from client %p\n", "PREFERENCE FEEDBACK", GNUNET_i2s (peer), application); return; } handle->env.sf.s_feedback (handle->solver, application, peer, scope, kind, score_abs); } /** * Load quotas for networks from configuration * * @param cfg configuration handle * @param out_dest where to write outbound quotas * @param in_dest where to write inbound quotas * @param dest_length length of inbound and outbound arrays * @return number of networks loaded */ static unsigned int load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length) { char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; char * entry_in = NULL; char * entry_out = NULL; char * quota_out_str; char * quota_in_str; int c; int res; for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++) { in_dest[c] = 0; out_dest[c] = 0; GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]); GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]); /* quota out */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ats", entry_out, "a_out_str)) { res = GNUNET_NO; if (0 == strcmp (quota_out_str, GNUNET_ATS_MaxBandwidthString)) { out_dest[c] = GNUNET_ATS_MaxBandwidth; res = GNUNET_YES; } if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c]))) res = GNUNET_YES; if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out, &out_dest[c]))) res = GNUNET_YES; if (GNUNET_NO == res) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"), network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } else { GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Outbound quota configure for network `%s' is %llu\n"), network_str[c], out_dest[c]); } GNUNET_free(quota_out_str); } else { GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"), network_str[c], GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } /* quota in */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ats", entry_in, "a_in_str)) { res = GNUNET_NO; if (0 == strcmp (quota_in_str, GNUNET_ATS_MaxBandwidthString)) { in_dest[c] = GNUNET_ATS_MaxBandwidth; res = GNUNET_YES; } if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c]))) res = GNUNET_YES; if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in, &in_dest[c]))) res = GNUNET_YES; if (GNUNET_NO == res) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"), network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth); in_dest[c] = GNUNET_ATS_DefaultBandwidth; } else { GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Inbound quota configured for network `%s' is %llu\n"), network_str[c], in_dest[c]); } GNUNET_free(quota_in_str); } else { GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"), network_str[c], GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Loaded quota for network `%s' (in/out): %llu %llu\n", network_str[c], in_dest[c], out_dest[c]); GNUNET_free(entry_out); GNUNET_free(entry_in); } return GNUNET_ATS_NetworkTypeCount; } /** * Callback for solver to notify about assignment changes * * @param cls the GAS_Addresses_Handle * @param address the address with changes */ static void bandwidth_changed_cb (void *cls, struct ATS_Address *address) { struct GAS_Addresses_Handle *handle = cls; struct GAS_Addresses_Suggestion_Requests *cur; GNUNET_assert(handle != NULL); GNUNET_assert(address != NULL); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Bandwidth assignment changed for peer %s \n", GNUNET_i2s (&address->peer)); /* Notify performance clients about changes to address */ GAS_performance_notify_all_clients (&address->peer, address->plugin, address->addr, address->addr_len, address->session_id, address->atsi, address->atsi_count, address->assigned_bw_out, address->assigned_bw_in); cur = handle->pending_requests_head; while (NULL != cur) { if (0 == memcmp (&address->peer, &cur->id, sizeof(cur->id))) break; /* we have an address request pending*/ cur = cur->next; } if (NULL == cur) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Nobody is interested in peer `%s' :(\n", GNUNET_i2s (&address->peer)); return; } if ((0 == ntohl (address->assigned_bw_in.value__)) && (0 == ntohl (address->assigned_bw_out.value__))) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Telling transport to disconnect peer `%s'\n", GNUNET_i2s (&address->peer)); } else { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending bandwidth update for peer `%s': %u %u\n", GNUNET_i2s (&address->peer), (unsigned int) ntohl (address->assigned_bw_out.value__), (unsigned int) ntohl (address->assigned_bw_out.value__)); } /* *Notify scheduling clients about suggestion */ GAS_scheduling_transmit_address_suggestion (&address->peer, address->plugin, address->addr, address->addr_len, address->local_address_info, address->session_id, address->atsi, address->atsi_count, address->assigned_bw_out, address->assigned_bw_in); } /** * Initialize address subsystem. The addresses subsystem manages the addresses * known and current performance information. It has a solver component * responsible for the resource allocation. It tells the solver about changes * and receives updates when the solver changes the resource allocation. * * @param cfg configuration to use * @param stats the statistics handle to use * @return an address handle */ struct GAS_Addresses_Handle * GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_STATISTICS_Handle *stats) { struct GAS_Addresses_Handle *ah; unsigned long long quotas_in[GNUNET_ATS_NetworkTypeCount]; unsigned long long quotas_out[GNUNET_ATS_NetworkTypeCount]; char *mode_str; char *plugin_short; int c; ah = GNUNET_new (struct GAS_Addresses_Handle); ah->running = GNUNET_NO; ah->stat = (struct GNUNET_STATISTICS_Handle *) stats; /* Initialize the addresses database */ ah->addresses = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); ah->pref_clients = 0; GNUNET_assert(NULL != ah->addresses); /* Figure out configured solution method */ if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "ats", "MODE", &mode_str)) { GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "No resource assignment method configured, using proportional approach\n"); ah->ats_mode = MODE_PROPORTIONAL; } else { for (c = 0; c < strlen (mode_str); c++) mode_str[c] = toupper (mode_str[c]); if (0 == strcmp (mode_str, "PROPORTIONAL")) ah->ats_mode = MODE_PROPORTIONAL; else if (0 == strcmp (mode_str, "MLP")) { ah->ats_mode = MODE_MLP; #if !HAVE_LIBGLPK GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Assignment method `%s' configured, but GLPK is not available, please install \n", mode_str); ah->ats_mode = MODE_PROPORTIONAL; #endif } else if (0 == strcmp (mode_str, "RIL")) ah->ats_mode = MODE_RIL; else { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Invalid resource assignment method `%s' configured, using proportional approach\n", mode_str); ah->ats_mode = MODE_PROPORTIONAL; } GNUNET_free(mode_str); } load_quotas (cfg, quotas_out, quotas_in, GNUNET_ATS_NetworkTypeCount); ah->env.info_cb = &solver_info_cb; ah->env.info_cb_cls = ah; ah->env.bandwidth_changed_cb = &bandwidth_changed_cb; ah->env.bw_changed_cb_cls = ah; ah->env.get_preferences = &get_preferences_cb; ah->env.get_preference_cls = ah; ah->env.get_property = &get_property_cb; ah->env.get_property_cls = ah; ah->env.cfg = cfg; ah->env.stats = stats; ah->env.addresses = ah->addresses; ah->env.network_count = GNUNET_ATS_NetworkTypeCount; int networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkType; for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { ah->env.networks[c] = networks[c]; ah->env.out_quota[c] = quotas_out[c]; ah->env.in_quota[c] = quotas_in[c]; } switch (ah->ats_mode) { case MODE_PROPORTIONAL: plugin_short = "proportional"; break; case MODE_MLP: plugin_short = "mlp"; break; case MODE_RIL: plugin_short = "ril"; break; default: plugin_short = NULL; break; } GNUNET_asprintf (&ah->plugin, "libgnunet_plugin_ats_%s", plugin_short); GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initializing solver `%s '`%s'\n"), plugin_short, ah->plugin); if (NULL == (ah->solver = GNUNET_PLUGIN_load (ah->plugin, &ah->env))) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver `%s'!\n"), ah->plugin); return NULL; } GNUNET_assert (NULL != ah->env.sf.s_add); GNUNET_assert (NULL != ah->env.sf.s_address_update_inuse); GNUNET_assert (NULL != ah->env.sf.s_address_update_property); GNUNET_assert (NULL != ah->env.sf.s_address_update_session); GNUNET_assert (NULL != ah->env.sf.s_address_update_network); GNUNET_assert (NULL != ah->env.sf.s_get); GNUNET_assert (NULL != ah->env.sf.s_get_stop); GNUNET_assert (NULL != ah->env.sf.s_pref); GNUNET_assert (NULL != ah->env.sf.s_feedback); GNUNET_assert (NULL != ah->env.sf.s_del); GNUNET_assert (NULL != ah->env.sf.s_bulk_start); GNUNET_assert (NULL != ah->env.sf.s_bulk_stop); GAS_normalization_start (&normalized_preference_changed_cb, ah, &normalized_property_changed_cb, ah); if (NULL == ah->solver) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize solver!\n")); GNUNET_free(ah); return NULL ; } /* up and running */ ah->running = GNUNET_YES; GNUNET_STATISTICS_set (ah->stat, "# addresses", GNUNET_CONTAINER_multipeermap_size (ah->addresses), GNUNET_NO); return ah; } /** * Destroy all addresses iterator * * @param cls NULL * @param key peer identity (unused) * @param value the 'struct ATS_Address' to free * @return #GNUNET_OK (continue to iterate) */ static int destroy_all_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GAS_Addresses_Handle *handle = cls; struct ATS_Address *aa = value; /* Remove */ GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (handle->addresses, key, value)); /* Notify */ handle->env.sf.s_del (handle->solver, aa, GNUNET_NO); /* Destroy */ free_address (aa); return GNUNET_OK; } /** * Remove all addresses * * @param handle the address handle to use */ void GAS_addresses_destroy_all (struct GAS_Addresses_Handle *handle) { if (GNUNET_NO == handle->running) return; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Destroying all addresses\n"); handle->env.sf.s_bulk_start (handle->solver); if (handle->addresses != NULL ) GNUNET_CONTAINER_multipeermap_iterate (handle->addresses, &destroy_all_address_it, handle); handle->env.sf.s_bulk_start (handle->solver); } /** * Shutdown address subsystem. * * @param handle the address handle to shutdown */ void GAS_addresses_done (struct GAS_Addresses_Handle *handle) { struct GAS_Addresses_Suggestion_Requests *cur; struct GAS_Addresses_Preference_Clients *pcur; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Shutting down addresses\n"); GNUNET_assert(NULL != handle); GAS_addresses_destroy_all (handle); handle->running = GNUNET_NO; GNUNET_CONTAINER_multipeermap_destroy (handle->addresses); handle->addresses = NULL; while (NULL != (cur = handle->pending_requests_head)) { GNUNET_CONTAINER_DLL_remove(handle->pending_requests_head, handle->pending_requests_tail, cur); GNUNET_free(cur); } while (NULL != (pcur = handle->preference_clients_head)) { GNUNET_CONTAINER_DLL_remove (handle->preference_clients_head, handle->preference_clients_tail, pcur); GNUNET_assert (handle->pref_clients > 0); handle->pref_clients --; GNUNET_STATISTICS_set (handle->stat, "# active performance clients", handle->pref_clients, GNUNET_NO); GNUNET_free (pcur); } GNUNET_PLUGIN_unload (handle->plugin, handle->solver); GNUNET_free (handle->plugin); GNUNET_free(handle); /* Stop configured solution method */ GAS_normalization_stop (); } struct PeerIteratorContext { GNUNET_ATS_Peer_Iterator it; void *it_cls; struct GNUNET_CONTAINER_MultiPeerMap *peers_returned; }; /** * Iterator to iterate over all peers * * @param cls a PeerIteratorContext * @param key the peer id * @param value the ATS_address * @return #GNUNET_OK to continue */ static int peer_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct PeerIteratorContext *ip_ctx = cls; if (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (ip_ctx->peers_returned, key)) { GNUNET_CONTAINER_multipeermap_put (ip_ctx->peers_returned, key, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); ip_ctx->it (ip_ctx->it_cls, key); } return GNUNET_OK; } /** * Return information all peers currently known to ATS * * @param handle the address handle to use * @param p_it the iterator to call for every peer * @param p_it_cls the closure for the iterator */ void GAS_addresses_iterate_peers (struct GAS_Addresses_Handle *handle, GNUNET_ATS_Peer_Iterator p_it, void *p_it_cls) { struct PeerIteratorContext ip_ctx; unsigned int size; if (NULL == p_it) return; GNUNET_assert(NULL != handle->addresses); size = GNUNET_CONTAINER_multipeermap_size (handle->addresses); if (0 != size) { ip_ctx.it = p_it; ip_ctx.it_cls = p_it_cls; ip_ctx.peers_returned = GNUNET_CONTAINER_multipeermap_create (size, GNUNET_NO); GNUNET_CONTAINER_multipeermap_iterate (handle->addresses, &peer_it, &ip_ctx); GNUNET_CONTAINER_multipeermap_destroy (ip_ctx.peers_returned); } p_it (p_it_cls, NULL ); } struct PeerInfoIteratorContext { GNUNET_ATS_PeerInfo_Iterator it; void *it_cls; }; /** * Iterator to iterate over a peer's addresses * * @param cls a `struct PeerInfoIteratorContext` * @param key the peer id * @param value the `struct ATS_address` * @return #GNUNET_OK to continue */ static int peerinfo_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct PeerInfoIteratorContext *pi_ctx = cls; struct ATS_Address *addr = value; if (NULL != pi_ctx->it) { pi_ctx->it (pi_ctx->it_cls, &addr->peer, addr->plugin, addr->addr, addr->addr_len, addr->active, addr->atsi, addr->atsi_count, addr->assigned_bw_out, addr->assigned_bw_in); } return GNUNET_YES; } /** * Return information all peers currently known to ATS * * @param handle the address handle to use * @param peer the respective peer * @param pi_it the iterator to call for every peer * @param pi_it_cls the closure for the iterator */ void GAS_addresses_get_peer_info (struct GAS_Addresses_Handle *handle, const struct GNUNET_PeerIdentity *peer, GNUNET_ATS_PeerInfo_Iterator pi_it, void *pi_it_cls) { struct PeerInfoIteratorContext pi_ctx; struct GNUNET_BANDWIDTH_Value32NBO zero_bw; GNUNET_assert(NULL != peer); GNUNET_assert(NULL != handle->addresses); if (NULL == pi_it) return; /* does not make sense without callback */ zero_bw = GNUNET_BANDWIDTH_value_init (0); pi_ctx.it = pi_it; pi_ctx.it_cls = pi_it_cls; GNUNET_CONTAINER_multipeermap_get_multiple (handle->addresses, peer, &peerinfo_it, &pi_ctx); if (NULL != pi_it) pi_it (pi_it_cls, NULL, NULL, NULL, 0, GNUNET_NO, NULL, 0, zero_bw, zero_bw); } /* end of gnunet-service-ats_addresses.c */ gnunet-0.10.1/src/ats/test_ats_solver_default.conf0000644000175000017500000000020112225230043017145 00000000000000[arm] PORT = 12001 DEFAULTSERVICES = ats UNIXPATH = $GNUNET_RUNTIME_DIR/test-ats-scheduling-arm.sock [transport] AUTOSTART = NO gnunet-0.10.1/src/ats/gnunet-service-ats_scheduling.h0000644000175000017500000001304112267431203017470 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_scheduling.h * @brief ats service, interaction with 'scheduling' API * @author Matthias Wachs * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_ATS_SCHEDULING_H #define GNUNET_SERVICE_ATS_SCHEDULING_H #include "gnunet_util_lib.h" /** * Register a new scheduling client. * * @param client handle of the new client * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GAS_scheduling_add_client (struct GNUNET_SERVER_Client *client); /** * Unregister a client (which may have been a scheduling client, * but this is not assured). * * @param client handle of the (now dead) client */ void GAS_scheduling_remove_client (struct GNUNET_SERVER_Client *client); /** * Handle 'reset backoff' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_reset_backoff (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Transmit the given address suggestion and bandwidth update to all scheduling * clients. * * @param peer peer for which this is an address suggestion * @param plugin_name 0-termintated string specifying the transport plugin * @param plugin_addr binary address for the plugin to use * @param plugin_addr_len number of bytes in plugin_addr * @param session_id session ID to use * @param local_address_info the local address for the address * @param atsi performance data for the address * @param atsi_count number of performance records in 'ats' * @param bandwidth_out assigned outbound bandwidth * @param bandwidth_in assigned inbound bandwidth */ void GAS_scheduling_transmit_address_suggestion (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t local_address_info, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in); /** * Handle 'request address' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_request_address (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Cancel 'request address' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_request_address_cancel (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle 'address add' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_address_add (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle 'address update' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_address_update (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle 'address in use' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_address_in_use (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Handle 'address destroyed' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_address_destroyed (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Initialize scheduling subsystem. * * @param server handle to our server * @param ah the address handle to use */ void GAS_scheduling_init (struct GNUNET_SERVER_Handle *server, struct GAS_Addresses_Handle *ah); /** * Shutdown scheduling subsystem. */ void GAS_scheduling_done (void); #endif /* end of gnunet-service-ats_scheduling.h */ gnunet-0.10.1/src/ats/test_ats_solver_request_and_add_address.c0000644000175000017500000001465412301361474021676 00000000000000/* if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_solver_add_address.c * @brief solver test: request address, add address and wait for suggest * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; /** * Test address */ static struct Test_Address test_addr; /** * Test peer */ static struct PeerContext p; /** * HELLO address */ struct GNUNET_HELLO_Address test_hello_address; /** * Session */ static void *test_session; /** * Test ats info */ struct GNUNET_ATS_Information test_ats_info[2]; /** * Test ats count */ uint32_t test_ats_count; static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent); static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } free_test_address (&test_addr); ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_assert (NULL != address); GNUNET_assert (NULL == session); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received sugggestion for peer `%s'\n", GNUNET_i2s (&address->peer)); GNUNET_SCHEDULER_add_now (&end, NULL); return; } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); return GNUNET_OK; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", mycfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (mycfg, &address_suggest_cb, NULL); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } /* Set up peer */ memset (&p.id, '1', sizeof (p.id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n", GNUNET_i2s_full(&p.id)); /* Prepare ATS Information */ test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN); test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); test_ats_info[1].value = htonl(1); test_ats_count = 2; /* Adding address without session */ test_session = NULL; create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1); test_hello_address.peer = p.id; test_hello_address.transport_name = test_addr.plugin; test_hello_address.address = test_addr.addr; test_hello_address.address_length = test_addr.addr_len; /* Request */ GNUNET_ATS_suggest_address (sched_ats, &p.id, NULL, NULL); /* Adding address */ GNUNET_ATS_address_add (sched_ats, &test_hello_address, NULL, test_ats_info, test_ats_count); } int main (int argc, char *argv[]) { char *sep; char *src_filename = GNUNET_strdup (__FILE__); char *test_filename = GNUNET_strdup (argv[0]); char *config_file; char *solver; ret = 0; if (NULL == (sep = (strstr (src_filename,".c")))) { GNUNET_break (0); return -1; } sep[0] = '\0'; if (NULL != (sep = strstr (test_filename, ".exe"))) sep[0] = '\0'; if (NULL == (solver = strstr (test_filename, src_filename))) { GNUNET_break (0); return -1; } solver += strlen (src_filename) +1; if (0 == strcmp(solver, "proportional")) { config_file = "test_ats_solver_proportional.conf"; } else if (0 == strcmp(solver, "mlp")) { config_file = "test_ats_solver_mlp.conf"; } else if ((0 == strcmp(solver, "ril"))) { config_file = "test_ats_solver_ril.conf"; } else { GNUNET_break (0); GNUNET_free (src_filename); GNUNET_free (test_filename); return 1; } GNUNET_free (src_filename); GNUNET_free (test_filename); if (0 != GNUNET_TESTING_peer_run ("test-ats-solver", config_file, &run, NULL )) return GNUNET_SYSERR; return ret; } /* end of file test_ats_solver_add_address.c */ gnunet-0.10.1/src/ats/test_ats_api_performance_list_peer_addresses.c0000644000175000017500000002031012263724143022677 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_performance_list_addresses.c * @brief test performance API's address listing feature * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Configuration handle */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * ATS scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * ATS performance handle */ static struct GNUNET_ATS_PerformanceHandle *perf_ats; struct GNUNET_ATS_AddressListHandle* phal; static int ret; struct Address { char *plugin; size_t plugin_len; void *addr; size_t addr_len; struct GNUNET_ATS_Information *ats; int ats_count; void *session; }; struct PeerContext { struct GNUNET_PeerIdentity id; struct Address *addr; }; static struct PeerContext p[2]; static struct Address p0_addresses[2]; static struct Address p1_addresses[2]; struct GNUNET_HELLO_Address p0_ha[2]; struct GNUNET_HELLO_Address p1_ha[2]; struct GNUNET_HELLO_Address *s_ha[2]; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void ats_perf_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { static int counter = 0; if (NULL == address) { phal = 0; if (2 == counter) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done\n"); GNUNET_SCHEDULER_add_now (end, NULL); } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (end_badly, NULL); } return; } else { if (0 != memcmp (&address->peer, &p[0].id, sizeof (p[0].id))) { GNUNET_break (0); GNUNET_SCHEDULER_add_now (end_badly, NULL); } } counter ++; } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (4 == value) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All addresses added, connecting to performance\n"); if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, NULL, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } phal = GNUNET_ATS_performance_list_addresses (perf_ats, &p[0].id, GNUNET_YES, ats_perf_cb, NULL); } return GNUNET_OK; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } if (phal != NULL ) { GNUNET_ATS_performance_list_addresses_cancel (phal); phal = NULL; } if (perf_ats != NULL ) { GNUNET_ATS_performance_done (perf_ats); perf_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } GNUNET_free_non_null(p0_addresses[0].addr); GNUNET_free_non_null(p0_addresses[1].addr); GNUNET_free_non_null(p1_addresses[0].addr); GNUNET_free_non_null(p1_addresses[1].addr); ret = 0; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { ret = 1; cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL ); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* set up peer 0 */ memset (&p[0].id, '1', sizeof (p[0].id)); p0_addresses[0].plugin = "test"; p0_addresses[0].session = NULL; p0_addresses[0].addr = GNUNET_strdup ("test_p0_a0"); p0_addresses[0].addr_len = strlen (p0_addresses[0].addr) + 1; p0_ha[0].address = p0_addresses[0].addr; p0_ha[0].address_length = p0_addresses[0].addr_len; p0_ha[0].peer = p[0].id; p0_ha[0].transport_name = p0_addresses[0].plugin; p0_addresses[1].plugin = "test"; p0_addresses[1].session = NULL; p0_addresses[1].addr = GNUNET_strdup ("test_p0_a1"); p0_addresses[1].addr_len = strlen (p0_addresses[1].addr) + 1; p0_ha[1].address = p0_addresses[1].addr; p0_ha[1].address_length = p0_addresses[1].addr_len; p0_ha[1].peer = p[0].id; p0_ha[1].transport_name = p0_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 0: `%s'\n", GNUNET_i2s (&p[0].id)); memset (&p[1].id, '2', sizeof (p[1].id)); p1_addresses[0].plugin = "test"; p1_addresses[0].session = NULL; p1_addresses[0].addr = GNUNET_strdup ("test_p1_a0"); p1_addresses[0].addr_len = strlen (p1_addresses[0].addr) + 1; p1_ha[0].address = p1_addresses[0].addr; p1_ha[0].address_length = p1_addresses[0].addr_len; p1_ha[0].peer = p[1].id; p1_ha[0].transport_name = p1_addresses[0].plugin; p1_addresses[1].plugin = "test"; p1_addresses[1].session = NULL; p1_addresses[1].addr = GNUNET_strdup ("test_p1_a1"); p1_addresses[1].addr_len = strlen (p1_addresses[1].addr) + 1; p1_ha[1].address = p1_addresses[1].addr; p1_ha[1].address_length = p1_addresses[1].addr_len; p1_ha[1].peer = p[1].id; p1_ha[1].transport_name = p1_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 1: `%s'\n", GNUNET_i2s (&p[1].id)); /* Add addresses */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL ); if (sched_ats == NULL ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } GNUNET_ATS_address_add (sched_ats, &p0_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p0_ha[1], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[1], NULL, NULL, 0); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test_ats_api_performance", "test_ats_api.conf", &run, NULL )) return 1; return ret; } /* end of file test_ats_api_performance_list_addresses.c */ gnunet-0.10.1/src/ats/ats.h0000644000175000017500000001344612265232754012350 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/ats.h * @brief automatic transport selection messages * @author Christian Grothoff * @author Matthias Wachs */ #ifndef ATS_H #define ATS_H #include "gnunet_util_lib.h" enum StartFlag { START_FLAG_SCHEDULING = 0, START_FLAG_PERFORMANCE_WITH_PIC = 1, START_FLAG_PERFORMANCE_NO_PIC = 2 }; GNUNET_NETWORK_STRUCT_BEGIN struct ClientStartMessage { struct GNUNET_MessageHeader header; /** * NBO value of an 'enum StartFlag'. */ uint32_t start_flag GNUNET_PACKED; }; struct RequestAddressMessage { struct GNUNET_MessageHeader header; uint32_t reserved GNUNET_PACKED; struct GNUNET_PeerIdentity peer; }; struct ResetBackoffMessage { struct GNUNET_MessageHeader header; uint32_t reserved GNUNET_PACKED; struct GNUNET_PeerIdentity peer; }; struct AddressUpdateMessage { struct GNUNET_MessageHeader header; uint32_t ats_count GNUNET_PACKED; struct GNUNET_PeerIdentity peer; uint16_t address_length GNUNET_PACKED; uint16_t plugin_name_length GNUNET_PACKED; uint32_t session_id GNUNET_PACKED; uint32_t address_local_info GNUNET_PACKED; /* followed by: * - struct GNUNET_ATS_Information [ats_count]; * - char address[address_length] * - char plugin_name[plugin_name_length] (including '\0'-termination). */ }; struct AddressUseMessage { struct GNUNET_MessageHeader header; struct GNUNET_PeerIdentity peer; uint16_t in_use GNUNET_PACKED; uint16_t address_length GNUNET_PACKED; uint16_t plugin_name_length GNUNET_PACKED; uint32_t session_id GNUNET_PACKED; uint32_t address_local_info GNUNET_PACKED; /* followed by: * - char address[address_length] * - char plugin_name[plugin_name_length] (including '\0'-termination). */ }; struct AddressDestroyedMessage { struct GNUNET_MessageHeader header; uint32_t reserved GNUNET_PACKED; struct GNUNET_PeerIdentity peer; uint16_t address_length GNUNET_PACKED; uint16_t plugin_name_length GNUNET_PACKED; uint32_t session_id GNUNET_PACKED; uint32_t address_local_info GNUNET_PACKED; /* followed by: * - char address[address_length] * - char plugin_name[plugin_name_length] (including '\0'-termination). */ }; struct AddressSuggestionMessage { struct GNUNET_MessageHeader header; uint32_t ats_count GNUNET_PACKED; struct GNUNET_PeerIdentity peer; uint16_t address_length GNUNET_PACKED; uint16_t plugin_name_length GNUNET_PACKED; uint32_t session_id GNUNET_PACKED; uint32_t address_local_info GNUNET_PACKED; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; /* followed by: * - struct GNUNET_ATS_Information [ats_count]; * - char address[address_length] * - char plugin_name[plugin_name_length] (including '\0'-termination). */ }; struct PeerInformationMessage { struct GNUNET_MessageHeader header; uint32_t ats_count GNUNET_PACKED; uint32_t address_active GNUNET_PACKED; uint32_t id GNUNET_PACKED; struct GNUNET_PeerIdentity peer; uint16_t address_length GNUNET_PACKED; uint16_t plugin_name_length GNUNET_PACKED; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; /* followed by: * - struct GNUNET_ATS_Information [ats_count]; * - char address[address_length] * - char plugin_name[plugin_name_length] (including '\0'-termination). */ }; struct AddressListRequestMessage { struct GNUNET_MessageHeader header; uint32_t id GNUNET_PACKED; int32_t all GNUNET_PACKED; struct GNUNET_PeerIdentity peer; }; struct ReservationRequestMessage { struct GNUNET_MessageHeader header; int32_t amount GNUNET_PACKED; struct GNUNET_PeerIdentity peer; }; /** * Message sent by ATS service to client to confirm that it is done * using the given session ID. */ struct SessionReleaseMessage { struct GNUNET_MessageHeader header; uint32_t session_id GNUNET_PACKED; struct GNUNET_PeerIdentity peer; }; struct ReservationResultMessage { struct GNUNET_MessageHeader header; int32_t amount GNUNET_PACKED; struct GNUNET_PeerIdentity peer; struct GNUNET_TIME_RelativeNBO res_delay; }; struct PreferenceInformation { uint32_t preference_kind GNUNET_PACKED; float preference_value GNUNET_PACKED; }; struct ChangePreferenceMessage { struct GNUNET_MessageHeader header; uint32_t num_preferences GNUNET_PACKED; struct GNUNET_PeerIdentity peer; /* followed by 'num_preferences' * struct PreferenceInformation values */ }; /** * Message containing application feedback for a peer */ struct FeedbackPreferenceMessage { struct GNUNET_MessageHeader header; /** * Number of feedback values included */ uint32_t num_feedback GNUNET_PACKED; /** * Relative time describing for which time interval this feedback is */ struct GNUNET_TIME_RelativeNBO scope; /** * Peer this feedback is for */ struct GNUNET_PeerIdentity peer; /* followed by 'num_feedback' * struct PreferenceInformation values */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/ats/test_ats_api_common.c0000644000175000017500000002150612235670731015575 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_common.c * @brief shared functions for ats test * @author Christian Grothoff * @author Matthias Wachs */ #include "test_ats_api_common.h" #define BIG_M_STRING "unlimited" void create_test_address (struct Test_Address *dest, char * plugin, void *session, void *addr, size_t addrlen) { dest->plugin = GNUNET_strdup (plugin); dest->session = session; if (addrlen > 0) { dest->addr = GNUNET_malloc (addrlen); memcpy (dest->addr, addr, addrlen); } else dest->addr = NULL; dest->addr_len = addrlen; } void free_test_address (struct Test_Address *dest) { GNUNET_free_non_null (dest->plugin); dest->plugin = NULL; GNUNET_free_non_null (dest->addr); dest->addr = NULL; } int compare_addresses (const struct GNUNET_HELLO_Address *address1, void *session1, const struct GNUNET_HELLO_Address *address2, void *session2) { if (0 != memcmp (&address1->peer, &address2->peer, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid peer id'\n"); return GNUNET_SYSERR; } if (0 != strcmp (address1->transport_name, address2->transport_name)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid plugin'\n"); return GNUNET_SYSERR; } if (address1->address_length != address2->address_length) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid address length\n"); return GNUNET_SYSERR; } else if (0 != memcmp (address1->address, address2->address, address2->address_length)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid address\n"); return GNUNET_SYSERR; } if (session1 != session2) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Suggestion with invalid session1 %p vs session2 %p'\n", session1, session2); return GNUNET_SYSERR; } return GNUNET_OK; } int compare_ats (const struct GNUNET_ATS_Information *ats_is, uint32_t ats_count_is, const struct GNUNET_ATS_Information *ats_should, uint32_t ats_count_should) { unsigned int c_o; unsigned int c_i; char *prop[] = GNUNET_ATS_PropertyStrings; uint32_t type1; uint32_t type2; uint32_t val1; uint32_t val2; int res = GNUNET_OK; for (c_o = 0; c_o < ats_count_is; c_o++) { for (c_i = 0; c_i < ats_count_should; c_i++) { type1 = ntohl(ats_is[c_o].type); type2 = ntohl(ats_should[c_i].type); if (type1 == type2) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS type `%s'\n", prop[type1]); val1 = ntohl(ats_is[c_o].value); val2 = ntohl(ats_should[c_i].value); if (val1 != val2) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ATS value `%s' not equal: %u != %u\n", prop[type1], val1, val2); res = GNUNET_SYSERR; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS value `%s' equal: %u == %u\n", prop[type1], val1, val2); } } } } return res; } /** * Load quotas for networks from configuration * * @param cfg configuration handle * @param out_dest where to write outbound quotas * @param in_dest where to write inbound quotas * @param dest_length length of inbound and outbound arrays * @return number of networks loaded */ unsigned int load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length) { char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; char * entry_in = NULL; char * entry_out = NULL; char * quota_out_str; char * quota_in_str; int c; int res; for (c = 0; (c < GNUNET_ATS_NetworkTypeCount) && (c < dest_length); c++) { in_dest[c] = 0; out_dest[c] = 0; GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]); GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]); /* quota out */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_out, "a_out_str)) { res = GNUNET_NO; if (0 == strcmp(quota_out_str, BIG_M_STRING)) { out_dest[c] = GNUNET_ATS_MaxBandwidth; res = GNUNET_YES; } if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, &out_dest[c]))) res = GNUNET_YES; if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_out, &out_dest[c]))) res = GNUNET_YES; if (GNUNET_NO == res) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"), network_str[c], quota_out_str, GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Outbound quota configure for network `%s' is %llu\n"), network_str[c], out_dest[c]); } GNUNET_free (quota_out_str); } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configured for network `%s', assigning default bandwidth %llu\n"), network_str[c], GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } /* quota in */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(cfg, "ats", entry_in, "a_in_str)) { res = GNUNET_NO; if (0 == strcmp(quota_in_str, BIG_M_STRING)) { in_dest[c] = GNUNET_ATS_MaxBandwidth; res = GNUNET_YES; } if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, &in_dest[c]))) res = GNUNET_YES; if ((GNUNET_NO == res) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "ats", entry_in, &in_dest[c]))) res = GNUNET_YES; if (GNUNET_NO == res) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not load quota for network `%s': `%s', assigning default bandwidth %llu\n"), network_str[c], quota_in_str, GNUNET_ATS_DefaultBandwidth); in_dest[c] = GNUNET_ATS_DefaultBandwidth; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Inbound quota configured for network `%s' is %llu\n"), network_str[c], in_dest[c]); } GNUNET_free (quota_in_str); } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No outbound quota configure for network `%s', assigning default bandwidth %llu\n"), network_str[c], GNUNET_ATS_DefaultBandwidth); out_dest[c] = GNUNET_ATS_DefaultBandwidth; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded quota for network `%s' (in/out): %llu %llu\n", network_str[c], in_dest[c], out_dest[c]); GNUNET_free (entry_out); GNUNET_free (entry_in); } return GNUNET_ATS_NetworkTypeCount; } /** * Create a ATS_address with the given information * @param peer peer * @param plugin_name plugin * @param plugin_addr address * @param plugin_addr_len address length * @param session_id session * @return the ATS_Address */ struct ATS_Address * create_address (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id) { struct ATS_Address *aa = NULL; aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len + strlen (plugin_name) + 1); aa->peer = *peer; aa->addr_len = plugin_addr_len; aa->addr = &aa[1]; aa->plugin = (char *) &aa[1] + plugin_addr_len; memcpy (&aa[1], plugin_addr, plugin_addr_len); memcpy (aa->plugin, plugin_name, strlen (plugin_name) + 1); aa->session_id = session_id; aa->active = GNUNET_NO; aa->used = GNUNET_NO; aa->solver_information = NULL; aa->assigned_bw_in = GNUNET_BANDWIDTH_value_init(0); aa->assigned_bw_out = GNUNET_BANDWIDTH_value_init(0); return aa; } /* end of file test_ats_api_common.c */ gnunet-0.10.1/src/ats/test_ats_api_performance_monitor_initial_callback.c0000644000175000017500000001777412263724143023714 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_performance_monitor.c * @brief test performance API's address monitor feature * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) #define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Configuration handle */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * ATS scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * ATS performance handle */ static struct GNUNET_ATS_PerformanceHandle *perf_ats; struct GNUNET_ATS_AddressListHandle* phal; static int ret; struct Address { char *plugin; size_t plugin_len; void *addr; size_t addr_len; struct GNUNET_ATS_Information *ats; int ats_count; void *session; }; struct PeerContext { struct GNUNET_PeerIdentity id; struct Address *addr; }; static struct PeerContext p[2]; static struct Address p0_addresses[2]; static struct Address p1_addresses[2]; struct GNUNET_HELLO_Address p0_ha[2]; struct GNUNET_HELLO_Address p1_ha[2]; struct GNUNET_HELLO_Address *s_ha[2]; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void ats_perf_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { static int peer0 = GNUNET_NO; static int peer1 = GNUNET_NO; static int done = GNUNET_NO; if (0 == memcmp (&address->peer, &p[0].id, sizeof (p[0].id))) { peer0 ++; } if (0 == memcmp (&address->peer, &p[1].id, sizeof (p[1].id))) { peer1 ++; } if ((2 == peer0) && (2 == peer1) && (GNUNET_NO == done)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done\n"); done = GNUNET_YES; GNUNET_SCHEDULER_add_now (&end, NULL); } } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (4 == value) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All addresses added\n"); if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } } return GNUNET_OK; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } if (NULL != perf_ats) { GNUNET_ATS_performance_done (perf_ats); perf_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } GNUNET_free_non_null(p0_addresses[0].addr); GNUNET_free_non_null(p0_addresses[1].addr); GNUNET_free_non_null(p1_addresses[0].addr); GNUNET_free_non_null(p1_addresses[1].addr); ret = 0; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { ret = 1; cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL ); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* set up peer 0 */ memset (&p[0].id, '1', sizeof (p[0].id)); p0_addresses[0].plugin = "test"; p0_addresses[0].session = NULL; p0_addresses[0].addr = GNUNET_strdup ("test_p0_a0"); p0_addresses[0].addr_len = strlen (p0_addresses[0].addr) + 1; p0_ha[0].address = p0_addresses[0].addr; p0_ha[0].address_length = p0_addresses[0].addr_len; p0_ha[0].peer = p[0].id; p0_ha[0].transport_name = p0_addresses[0].plugin; p0_addresses[1].plugin = "test"; p0_addresses[1].session = NULL; p0_addresses[1].addr = GNUNET_strdup ("test_p0_a1"); p0_addresses[1].addr_len = strlen (p0_addresses[1].addr) + 1; p0_ha[1].address = p0_addresses[1].addr; p0_ha[1].address_length = p0_addresses[1].addr_len; p0_ha[1].peer = p[0].id; p0_ha[1].transport_name = p0_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 0: `%s'\n", GNUNET_i2s (&p[0].id)); memset (&p[1].id, '2', sizeof (p[1].id)); p1_addresses[0].plugin = "test"; p1_addresses[0].session = NULL; p1_addresses[0].addr = GNUNET_strdup ("test_p1_a0"); p1_addresses[0].addr_len = strlen (p1_addresses[0].addr) + 1; p1_ha[0].address = p1_addresses[0].addr; p1_ha[0].address_length = p1_addresses[0].addr_len; p1_ha[0].peer = p[1].id; p1_ha[0].transport_name = p1_addresses[0].plugin; p1_addresses[1].plugin = "test"; p1_addresses[1].session = NULL; p1_addresses[1].addr = GNUNET_strdup ("test_p1_a1"); p1_addresses[1].addr_len = strlen (p1_addresses[1].addr) + 1; p1_ha[1].address = p1_addresses[1].addr; p1_ha[1].address_length = p1_addresses[1].addr_len; p1_ha[1].peer = p[1].id; p1_ha[1].transport_name = p1_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 1: `%s'\n", GNUNET_i2s (&p[1].id)); /* Add addresses */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL ); if (sched_ats == NULL ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } GNUNET_ATS_address_add (sched_ats, &p0_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p0_ha[1], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[1], NULL, NULL, 0); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test_ats_api_performance", "test_ats_api.conf", &run, NULL )) return 1; return ret; } /* end of file test_ats_api_performance_monitor.c */ gnunet-0.10.1/src/ats/test_ats_api_performance_list_all_addresses.c0000644000175000017500000002002412263724143022516 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_performance_list_addresses.c * @brief test performance API's address listing feature * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Configuration handle */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * ATS scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * ATS performance handle */ static struct GNUNET_ATS_PerformanceHandle *perf_ats; struct GNUNET_ATS_AddressListHandle* phal; static int ret; struct Address { char *plugin; size_t plugin_len; void *addr; size_t addr_len; struct GNUNET_ATS_Information *ats; int ats_count; void *session; }; struct PeerContext { struct GNUNET_PeerIdentity id; struct Address *addr; }; static struct PeerContext p[2]; static struct Address p0_addresses[2]; static struct Address p1_addresses[2]; struct GNUNET_HELLO_Address p0_ha[2]; struct GNUNET_HELLO_Address p1_ha[2]; struct GNUNET_HELLO_Address *s_ha[2]; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void ats_perf_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { static int counter = 0; if (NULL == address) { phal = 0; if (4 == counter) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Done!\n"); GNUNET_SCHEDULER_add_now (end, NULL); } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (end_badly, NULL); } return; } counter ++; } static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (4 == value) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All addresses added, connecting to performance\n"); if (NULL == (perf_ats = GNUNET_ATS_performance_init (cfg, NULL, NULL))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to performance API\n"); GNUNET_SCHEDULER_add_now (end_badly, NULL); } phal = GNUNET_ATS_performance_list_addresses (perf_ats, NULL, GNUNET_YES, ats_perf_cb, NULL); } return GNUNET_OK; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } if (phal != NULL ) { GNUNET_ATS_performance_list_addresses_cancel (phal); phal = NULL; } if (perf_ats != NULL ) { GNUNET_ATS_performance_done (perf_ats); perf_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } GNUNET_free_non_null(p0_addresses[0].addr); GNUNET_free_non_null(p0_addresses[1].addr); GNUNET_free_non_null(p1_addresses[0].addr); GNUNET_free_non_null(p1_addresses[1].addr); ret = 0; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { ret = 1; cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL ); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); /* set up peer 0 */ memset (&p[0].id, '1', sizeof (p[0].id)); p0_addresses[0].plugin = "test"; p0_addresses[0].session = NULL; p0_addresses[0].addr = GNUNET_strdup ("test_p0_a0"); p0_addresses[0].addr_len = strlen (p0_addresses[0].addr) + 1; p0_ha[0].address = p0_addresses[0].addr; p0_ha[0].address_length = p0_addresses[0].addr_len; p0_ha[0].peer = p[0].id; p0_ha[0].transport_name = p0_addresses[0].plugin; p0_addresses[1].plugin = "test"; p0_addresses[1].session = NULL; p0_addresses[1].addr = GNUNET_strdup ("test_p0_a1"); p0_addresses[1].addr_len = strlen (p0_addresses[1].addr) + 1; p0_ha[1].address = p0_addresses[1].addr; p0_ha[1].address_length = p0_addresses[1].addr_len; p0_ha[1].peer = p[0].id; p0_ha[1].transport_name = p0_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 0: `%s'\n", GNUNET_i2s (&p[0].id)); memset (&p[1].id, '2', sizeof (p[1].id)); p1_addresses[0].plugin = "test"; p1_addresses[0].session = NULL; p1_addresses[0].addr = GNUNET_strdup ("test_p1_a0"); p1_addresses[0].addr_len = strlen (p1_addresses[0].addr) + 1; p1_ha[0].address = p1_addresses[0].addr; p1_ha[0].address_length = p1_addresses[0].addr_len; p1_ha[0].peer = p[1].id; p1_ha[0].transport_name = p1_addresses[0].plugin; p1_addresses[1].plugin = "test"; p1_addresses[1].session = NULL; p1_addresses[1].addr = GNUNET_strdup ("test_p1_a1"); p1_addresses[1].addr_len = strlen (p1_addresses[1].addr) + 1; p1_ha[1].address = p1_addresses[1].addr; p1_ha[1].address_length = p1_addresses[1].addr_len; p1_ha[1].peer = p[1].id; p1_ha[1].transport_name = p1_addresses[1].plugin; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Created peer 1: `%s'\n", GNUNET_i2s (&p[1].id)); /* Add addresses */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL ); if (sched_ats == NULL ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } GNUNET_ATS_address_add (sched_ats, &p0_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p0_ha[1], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[0], NULL, NULL, 0); GNUNET_ATS_address_add (sched_ats, &p1_ha[1], NULL, NULL, 0); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test_ats_api_performance", "test_ats_api.conf", &run, NULL )) return 1; return ret; } /* end of file test_ats_api_performance_list_addresses.c */ gnunet-0.10.1/src/ats/perf_ats_solver.conf0000644000175000017500000000066512236654562015456 00000000000000[ats] # Network specific inbound/outbound quotas UNSPECIFIED_QUOTA_IN = unlimited UNSPECIFIED_QUOTA_OUT = unlimited # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited # LAN LAN_QUOTA_IN = unlimited LAN_QUOTA_OUT = unlimited # WAN WAN_QUOTA_IN = unlimited WAN_QUOTA_OUT = unlimited # WLAN WLAN_QUOTA_IN = unlimited WLAN_QUOTA_OUT = unlimited # BLUETOOTH BLUETOOTH_QUOTA_IN = unlimited BLUETOOTH_QUOTA_OUT = unlimited gnunet-0.10.1/src/ats/test_ats_api_common.h0000644000175000017500000000524712225777503015612 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_common.h * @brief shared definitions for ats testcases * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet-service-ats_addresses.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) struct Test_Address { char *plugin; size_t plugin_len; void *addr; size_t addr_len; struct GNUNET_ATS_Information *ats; int ats_count; void *session; }; struct PeerContext { struct GNUNET_PeerIdentity id; struct Test_Address *addr; unsigned long long bw_out_assigned; unsigned long long bw_in_assigned; }; void free_test_address (struct Test_Address *dest); void create_test_address (struct Test_Address *dest, char * plugin, void *session, void *addr, size_t addrlen); int compare_addresses (const struct GNUNET_HELLO_Address *address1, void *session1, const struct GNUNET_HELLO_Address *address2, void *session2); int compare_ats (const struct GNUNET_ATS_Information *ats_is, uint32_t ats_count_is, const struct GNUNET_ATS_Information *ats_should, uint32_t ats_count_should); struct ATS_Address * create_address (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id); /** * Load quotas for networks from configuration * * @param cfg configuration handle * @param out_dest where to write outbound quotas * @param in_dest where to write inbound quotas * @param dest_length length of inbound and outbound arrays * @return number of networks loaded */ unsigned int load_quotas (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned long long *out_dest, unsigned long long *in_dest, int dest_length); /* end of file test_ats_api_common.h */ gnunet-0.10.1/src/ats/test_ats_api.conf0000644000175000017500000000203212242436626014722 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-ats-api-scheduling/ [arm] PORT = 12001 DEFAULTSERVICES = UNIXPATH = $GNUNET_RUNTIME_DIR/test-ats-scheduling-arm.sock [ats] #PREFIX = valgrind --leak-check=full --track-origins=yes --num-callers=25 AUTOSTART = YES PORT = 12002 HOSTNAME = localhost BINARY = gnunet-service-ats ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/test-ats-scheduling-ats.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # Enable MLP mode (default: NO) #MODE = RIL MODE = MLP # Network specific inbound/outbound quotas # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 64 KiB UNSPECIFIED_QUOTA_OUT = 64 KiB # LOOPBACK LOOPBACK_QUOTA_IN = unlimited LOOPBACK_QUOTA_OUT = unlimited # LAN LAN_QUOTA_IN = unlimited LAN_QUOTA_OUT = unlimited # WAN WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB # WLAN WLAN_QUOTA_IN = 512 WLAN_QUOTA_OUT = 512 # ATS extended options DUMP_MLP = NO DUMP_SOLUTION = NO DUMP_OVERWRITE = NO DUMP_MIN_PEERS = 0 DUMP_MIN_ADDRS = 0 DUMP_OVERWRITE = NO ATS_MIN_INTERVAL = 15000 ATS_EXEC_INTERVAL = 30000 gnunet-0.10.1/src/ats/gnunet-service-ats_performance.c0000644000175000017500000005535512265232754017665 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/gnunet-service-ats_performance.c * @brief ats service, interaction with 'performance' API * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-ats.h" #include "gnunet-service-ats_addresses.h" #include "gnunet-service-ats_performance.h" #include "gnunet-service-ats_reservations.h" #include "ats.h" /** * We keep clients that are interested in performance in a linked list. */ struct PerformanceClient { /** * Next in doubly-linked list. */ struct PerformanceClient *next; /** * Previous in doubly-linked list. */ struct PerformanceClient *prev; /** * Actual handle to the client. */ struct GNUNET_SERVER_Client *client; /** * Options for the client. */ enum StartFlag flag; }; /** * We keep clients that are interested in performance in a linked list. */ struct AddressIteration { /** * Actual handle to the client. */ struct PerformanceClient *pc; int all; uint32_t id; unsigned int msg_type; }; /** * Address handle */ static struct GAS_Addresses_Handle *GSA_addresses; /** * Head of linked list of all clients to this service. */ static struct PerformanceClient *pc_head; /** * Tail of linked list of all clients to this service. */ static struct PerformanceClient *pc_tail; /** * Context for sending messages to performance clients. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Find the performance client associated with the given handle. * * @param client server handle * @return internal handle */ static struct PerformanceClient * find_client (struct GNUNET_SERVER_Client *client) { struct PerformanceClient *pc; for (pc = pc_head; pc != NULL; pc = pc->next) if (pc->client == client) return pc; return NULL; } /** * Unregister a client (which may have been a performance client, * but this is not assured). * * @param client handle of the (now dead) client */ void GAS_performance_remove_client (struct GNUNET_SERVER_Client *client) { struct PerformanceClient *pc; pc = find_client (client); if (NULL == pc) return; GNUNET_CONTAINER_DLL_remove (pc_head, pc_tail, pc); GAS_addresses_preference_client_disconnect (GSA_addresses, client); GNUNET_free (pc); } /** * Transmit the given performance information to all performance * clients. * * @param pc performance client to send to * @param peer peer for which this is an address suggestion * @param plugin_name 0-termintated string specifying the transport plugin * @param plugin_addr binary address for the plugin to use * @param plugin_addr_len number of bytes in plugin_addr * @param active is this address active * @param atsi performance data for the address * @param atsi_count number of performance records in 'ats' * @param bandwidth_out assigned outbound bandwidth * @param bandwidth_in assigned inbound bandwidth */ void GAS_performance_notify_client (struct PerformanceClient *pc, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, int active, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { struct PeerInformationMessage *msg; size_t plugin_name_length = strlen (plugin_name) + 1; size_t msize = sizeof (struct PeerInformationMessage) + atsi_count * sizeof (struct GNUNET_ATS_Information) + plugin_addr_len + plugin_name_length; char buf[msize] GNUNET_ALIGN; struct GNUNET_ATS_Information *atsp; char *addrp; GNUNET_assert (NULL != pc); if (NULL == find_client (pc->client)) return; /* Client disconnected */ GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); GNUNET_assert (atsi_count < GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)); msg = (struct PeerInformationMessage *) buf; msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION); msg->id = htonl (0); msg->ats_count = htonl (atsi_count); msg->peer = *peer; msg->address_length = htons (plugin_addr_len); msg->address_active = ntohl (active); msg->plugin_name_length = htons (plugin_name_length); msg->bandwidth_out = bandwidth_out; msg->bandwidth_in = bandwidth_in; atsp = (struct GNUNET_ATS_Information *) &msg[1]; memcpy (atsp, atsi, sizeof (struct GNUNET_ATS_Information) * atsi_count); addrp = (char *) &atsp[atsi_count]; memcpy (addrp, plugin_addr, plugin_addr_len); strcpy (&addrp[plugin_addr_len], plugin_name); GNUNET_SERVER_notification_context_unicast (nc, pc->client, &msg->header, GNUNET_YES); } /** * Transmit the given performance information to all performance * clients. * * @param peer peer for which this is an address suggestion * @param plugin_name 0-termintated string specifying the transport plugin * @param plugin_addr binary address for the plugin to use * @param plugin_addr_len number of bytes in plugin_addr * @param active is this address active * @param atsi performance data for the address * @param atsi_count number of performance records in 'ats' * @param bandwidth_out assigned outbound bandwidth * @param bandwidth_in assigned inbound bandwidth */ void GAS_performance_notify_all_clients (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, int active, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { struct PerformanceClient *pc; for (pc = pc_head; pc != NULL; pc = pc->next) if (pc->flag == START_FLAG_PERFORMANCE_WITH_PIC) { GAS_performance_notify_client (pc, peer, plugin_name, plugin_addr, plugin_addr_len, active, atsi, atsi_count, bandwidth_out, bandwidth_in); } GNUNET_STATISTICS_update (GSA_stats, "# performance updates given to clients", 1, GNUNET_NO); } static void peerinfo_it (void *cls, const struct GNUNET_PeerIdentity *id, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, const int active, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { struct PerformanceClient *pc = cls; GNUNET_assert (NULL != pc); if (NULL == id) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer `%s' plugin `%s' BW out %u, BW in %u \n", GNUNET_i2s (id), plugin_name, (unsigned int) ntohl (bandwidth_out.value__), (unsigned int) ntohl (bandwidth_in.value__)); GAS_performance_notify_client(pc, id, plugin_name, plugin_addr, plugin_addr_len, active, atsi, atsi_count, bandwidth_out, bandwidth_in); } /** * Iterator for GAS_performance_add_client * * @param cls the client requesting information * @param id result */ static void peer_it (void *cls, const struct GNUNET_PeerIdentity *id) { struct PerformanceClient *pc = cls; if (NULL != id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer `%s'\n", GNUNET_i2s (id)); GAS_addresses_get_peer_info (GSA_addresses, id, &peerinfo_it, pc); } } /** * Register a new performance client. * * @param client handle of the new client * @param flag flag specifying the type of the client */ void GAS_performance_add_client (struct GNUNET_SERVER_Client *client, enum StartFlag flag) { struct PerformanceClient *pc; GNUNET_break (NULL == find_client (client)); pc = GNUNET_new (struct PerformanceClient); pc->client = client; pc->flag = flag; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding performance client %s PIC\n", (flag == START_FLAG_PERFORMANCE_WITH_PIC) ? "with" : "without"); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc); /* Send information about clients */ GAS_addresses_iterate_peers (GSA_addresses, &peer_it, pc); } static void transmit_req_addr (struct AddressIteration *ai, const struct GNUNET_PeerIdentity *id, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, const int active, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { struct GNUNET_ATS_Information *atsp; struct PeerInformationMessage *msg; char *addrp; size_t plugin_name_length; size_t msize; if (NULL != plugin_name) plugin_name_length = strlen (plugin_name) + 1; else plugin_name_length = 0; msize = sizeof (struct PeerInformationMessage) + atsi_count * sizeof (struct GNUNET_ATS_Information) + plugin_addr_len + plugin_name_length; char buf[msize] GNUNET_ALIGN; GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); GNUNET_assert (atsi_count < GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)); msg = (struct PeerInformationMessage *) buf; msg->header.size = htons (msize); msg->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE); msg->ats_count = htonl (atsi_count); msg->id = htonl (ai->id); if (NULL != id) msg->peer = *id; else memset (&msg->peer, '\0', sizeof (struct GNUNET_PeerIdentity)); msg->address_length = htons (plugin_addr_len); msg->address_active = ntohl (active); msg->plugin_name_length = htons (plugin_name_length); msg->bandwidth_out = bandwidth_out; msg->bandwidth_in = bandwidth_in; atsp = (struct GNUNET_ATS_Information *) &msg[1]; memcpy (atsp, atsi, sizeof (struct GNUNET_ATS_Information) * atsi_count); addrp = (char *) &atsp[atsi_count]; if (NULL != plugin_addr) memcpy (addrp, plugin_addr, plugin_addr_len); if (NULL != plugin_name) strcpy (&addrp[plugin_addr_len], plugin_name); GNUNET_SERVER_notification_context_unicast (nc, ai->pc->client, &msg->header, GNUNET_NO); } static void req_addr_peerinfo_it (void *cls, const struct GNUNET_PeerIdentity *id, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, const int active, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { struct AddressIteration *ai = cls; GNUNET_assert (NULL != ai); GNUNET_assert (NULL != ai->pc); if (NULL == find_client (ai->pc->client)) return; /* Client disconnected */ if ((NULL == id) && (NULL == plugin_name) && (NULL == plugin_addr)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Address iteration done\n"); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for %s peer `%s' plugin `%s' BW out %u, BW in %u\n", (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE", GNUNET_i2s (id), plugin_name, (unsigned int) ntohl (bandwidth_out.value__), (unsigned int) ntohl (bandwidth_in.value__)); /* Transmit result */ if ((GNUNET_YES == ai->all) || (GNUNET_YES == active)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending result for %s peer `%s' plugin `%s' BW out %u, BW in %u\n", (active == GNUNET_YES) ? "ACTIVE" : "INACTIVE", GNUNET_i2s (id), plugin_name, (unsigned int) ntohl (bandwidth_out.value__), (unsigned int) ntohl (bandwidth_in.value__)); transmit_req_addr (cls, id, plugin_name, plugin_addr, plugin_addr_len, active, atsi, atsi_count, bandwidth_out, bandwidth_in); } } /** * Iterator for GAS_handle_request_address_list * * @param cls the client requesting information * @param id result */ static void req_addr_peer_it (void *cls, const struct GNUNET_PeerIdentity *id) { struct AddressIteration *ai = cls; if (NULL != id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer `%s'\n", GNUNET_i2s (id)); GAS_addresses_get_peer_info (GSA_addresses, id, &req_addr_peerinfo_it, ai); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer iteration done\n"); } } /** * Handle 'address list request' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_request_address_list (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct PerformanceClient *pc; struct AddressIteration ai; struct AddressListRequestMessage * alrm = (struct AddressListRequestMessage *) message; struct GNUNET_PeerIdentity allzeros; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ADDRESSLIST_REQUEST"); if (NULL == (pc = find_client(client))) { GNUNET_break (0); return; } ai.all = ntohl (alrm->all); ai.id = ntohl (alrm->id); ai.pc = pc; memset (&allzeros, '\0', sizeof (struct GNUNET_PeerIdentity)); bandwidth_zero.value__ = htonl (0); if (0 == memcmp (&alrm->peer, &allzeros, sizeof (struct GNUNET_PeerIdentity))) { /* Return addresses for all peers */ GAS_addresses_iterate_peers (GSA_addresses, &req_addr_peer_it, &ai); transmit_req_addr (&ai, NULL, NULL, NULL, 0, GNUNET_NO, NULL, 0, bandwidth_zero, bandwidth_zero); } else { /* Return addresses for a specific peer */ GAS_addresses_get_peer_info (GSA_addresses, &alrm->peer, &req_addr_peerinfo_it, &ai); transmit_req_addr (&ai, NULL, NULL, NULL, 0, GNUNET_NO, NULL, 0, bandwidth_zero, bandwidth_zero); } GNUNET_SERVER_receive_done (client, GNUNET_OK); } void GAS_handle_performance_update (struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, const int active, struct GNUNET_ATS_Information *ats, uint32_t ats_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) { /* Notify here */ GAS_performance_notify_all_clients (peer, plugin_name, plugin_addr, plugin_addr_len, active, ats, ats_count, bandwidth_out, bandwidth_in); #if 0 struct PerformanceClient *cur; struct PerformanceMonitorClient *curm; struct MonitorResponseMessage *mrm; size_t msglen; msglen = sizeof (struct MonitorResponseMessage) + ats_count * sizeof (struct GNUNET_ATS_Information); mrm = GNUNET_malloc (msglen); mrm->header.type = htons (GNUNET_MESSAGE_TYPE_ATS_MONITOR_RESPONSE); mrm->header.size = htons (msglen); mrm->ats_count = htonl (ats_count); mrm->peer = *peer; memcpy (&mrm[1], ats, ats_count * sizeof (struct GNUNET_ATS_Information)); for (cur = pc_head; NULL != cur; cur = cur->next) for (curm = cur->pm_head; NULL != curm; curm = curm->next) { /* Notify client about update */ mrm->id = htonl (curm->id); GNUNET_SERVER_notification_context_unicast (nc, cur->client, (struct GNUNET_MessageHeader *) mrm, GNUNET_YES); } GNUNET_free (mrm); #endif } /** * Handle 'reservation request' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_reservation_request (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ReservationRequestMessage *msg = (const struct ReservationRequestMessage *) message; struct ReservationResultMessage result; int32_t amount; struct GNUNET_TIME_Relative res_delay; if (NULL == find_client (client)) { /* missing start message! */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "RESERVATION_REQUEST"); amount = (int32_t) ntohl (msg->amount); res_delay = GAS_reservations_reserve (&msg->peer, amount); if (res_delay.rel_value_us > 0) amount = 0; result.header.size = htons (sizeof (struct ReservationResultMessage)); result.header.type = htons (GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT); result.amount = htonl (amount); result.peer = msg->peer; result.res_delay = GNUNET_TIME_relative_hton (res_delay); GNUNET_STATISTICS_update (GSA_stats, "# reservation requests processed", 1, GNUNET_NO); GNUNET_SERVER_notification_context_unicast (nc, client, &result.header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle 'preference change' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_preference_change (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ChangePreferenceMessage *msg; const struct PreferenceInformation *pi; uint16_t msize; uint32_t nump; uint32_t i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "PREFERENCE_CHANGE"); msize = ntohs (message->size); if (msize < sizeof (struct ChangePreferenceMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct ChangePreferenceMessage *) message; nump = ntohl (msg->num_preferences); if (msize != sizeof (struct ChangePreferenceMessage) + nump * sizeof (struct PreferenceInformation)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GSA_stats, "# preference change requests processed", 1, GNUNET_NO); pi = (const struct PreferenceInformation *) &msg[1]; for (i = 0; i < nump; i++) GAS_addresses_preference_change (GSA_addresses, client, &msg->peer, (enum GNUNET_ATS_PreferenceKind) ntohl (pi[i].preference_kind), pi[i].preference_value); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle 'preference feedback' messages from clients. * * @param cls unused, NULL * @param client client that sent the request * @param message the request message */ void GAS_handle_preference_feedback (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct FeedbackPreferenceMessage *msg; const struct PreferenceInformation *pi; uint16_t msize; uint32_t nump; uint32_t i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "PREFERENCE_FEEDBACK"); msize = ntohs (message->size); if (msize < sizeof (struct FeedbackPreferenceMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct FeedbackPreferenceMessage *) message; nump = ntohl (msg->num_feedback); if (msize != sizeof (struct FeedbackPreferenceMessage) + nump * sizeof (struct PreferenceInformation)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GSA_stats, "# preference feedbacks requests processed", 1, GNUNET_NO); pi = (const struct PreferenceInformation *) &msg[1]; for (i = 0; i < nump; i++) GAS_addresses_preference_feedback (GSA_addresses, client, &msg->peer, GNUNET_TIME_relative_ntoh(msg->scope), (enum GNUNET_ATS_PreferenceKind) ntohl (pi[i].preference_kind), pi[i].preference_value); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Initialize performance subsystem. * * @param server handle to our server * @param addresses the address handle to use */ void GAS_performance_init (struct GNUNET_SERVER_Handle *server, struct GAS_Addresses_Handle *addresses) { GSA_addresses = addresses; nc = GNUNET_SERVER_notification_context_create (server, 128); } /** * Shutdown performance subsystem. */ void GAS_performance_done () { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } /* end of gnunet-service-ats_performance.c */ gnunet-0.10.1/src/ats/test_ats_api_scheduling_init.c0000644000175000017500000001140012263724143017443 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/test_ats_api_scheduling_init.c * @brief test automatic transport selection scheduling API init/shutdown * @author Christian Grothoff * @author Matthias Wachs * */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet_testing_lib.h" #include "ats.h" #include "test_ats_api_common.h" /** * Timeout task */ static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Initial statistics get request handle */ struct GNUNET_STATISTICS_GetHandle *initial_get; /** * Statistics handle */ struct GNUNET_STATISTICS_Handle *stats; /** * Scheduling handle */ static struct GNUNET_ATS_SchedulingHandle *sched_ats; /** * Return value */ static int ret; static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int stat_cb(void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS statistics: `%s' `%s' %llu\n", subsystem,name, value); if (0 == value) { GNUNET_SCHEDULER_add_now (&end, NULL); } return GNUNET_OK; } static int dummy_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got dummy stat %s%s:%s = %llu\n", is_persistent ? "!" : " ", subsystem, name, value); return GNUNET_OK; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != sched_ats) { GNUNET_ATS_scheduling_done (sched_ats); sched_ats = NULL; } GNUNET_STATISTICS_watch_cancel (stats, "ats", "# addresses", &stat_cb, NULL); if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } ret = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; end ( NULL, NULL); ret = GNUNET_SYSERR; } static void address_suggest_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *atsi, uint32_t ats_count) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not expect suggestion callback!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } static void got_initial_value (void *cls, int success) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got initial value\n"); /* Connect to ATS scheduling */ sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL); GNUNET_CONFIGURATION_destroy (cfg); if (sched_ats == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n"); GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); stats = GNUNET_STATISTICS_create ("ats", cfg); GNUNET_STATISTICS_watch (stats, "ats", "# addresses", &stat_cb, NULL); initial_get = GNUNET_STATISTICS_get (stats, "ats", "# addresses", TIMEOUT, &got_initial_value, &dummy_stat, GNUNET_CONFIGURATION_dup (cfg)); } int main (int argc, char *argv[]) { ret = 0; if (0 != GNUNET_TESTING_peer_run ("test-ats-api", "test_ats_api.conf", &run, NULL)) return 1; return ret; } /* end of file test_ats_api_scheduling_init.c */ gnunet-0.10.1/src/namestore/0000755000175000017500000000000012320755627012667 500000000000000gnunet-0.10.1/src/namestore/test_plugin_namestore_postgres.conf0000644000175000017500000000013312225230043021773 00000000000000[namestore-postgres] CONFIG = connect_timeout=10; dbname=gnunetcheck TEMPORARY_TABLE = YES gnunet-0.10.1/src/namestore/test_plugin_namestore_sqlite.conf0000644000175000017500000000012112225230043021423 00000000000000[namestore-sqlite] FILENAME = /tmp/gnunet-test-plugin-namestore-sqlite/sqlite.db gnunet-0.10.1/src/namestore/test_namestore_api_zone_iteration_stop.c0000644000175000017500000003016212251551532023010 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_zone_iteration.c * @brief testcase for zone iteration functionality: stop iterating of zones */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #include "namestore.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) #define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) static struct GNUNET_NAMESTORE_Handle * nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2; static struct GNUNET_NAMESTORE_ZoneIterator *zi; static int res; static int returned_records; static char * s_name_1; static struct GNUNET_GNSRECORD_Data *s_rd_1; static char * s_name_2; static struct GNUNET_GNSRECORD_Data *s_rd_2; static char * s_name_3; static struct GNUNET_GNSRECORD_Data *s_rd_3; static char *directory; /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != zi) { GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; } if (nsh != NULL) GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; GNUNET_free_non_null(s_name_1); GNUNET_free_non_null(s_name_2); GNUNET_free_non_null(s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (privkey != NULL) GNUNET_free (privkey); privkey = NULL; if (privkey2 != NULL) GNUNET_free (privkey2); privkey2 = NULL; res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != zi) { GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; } if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (privkey != NULL) GNUNET_free (privkey); privkey = NULL; if (privkey2 != NULL) GNUNET_free (privkey2); privkey2 = NULL; GNUNET_free (s_name_1); GNUNET_free (s_name_2); GNUNET_free (s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (nsh != NULL) GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } static void zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int failed = GNUNET_NO; if ((zone == NULL) && (label == NULL)) { GNUNET_break (1 <= returned_records); if (1 >= returned_records) res = 1; /* Last iteraterator callback, we are done */ else res = 0; zi = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n", returned_records ); GNUNET_SCHEDULER_add_now (&end, NULL); return; } else { if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { if (0 == strcmp (label, s_name_1)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_1)) { failed = GNUNET_YES; GNUNET_break (0); } } else { failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == strcmp (label, s_name_2)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_2)) { failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid record count\n"); failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s' for first zone\n", label); failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { if (0 == strcmp (label, s_name_3)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_3)) { failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid record count\n"); failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s' for first zone\n", label); failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid zone\n"); failed = GNUNET_YES; GNUNET_break (0); } } if (failed == GNUNET_NO) { if (1 == returned_records) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to stop zone iteration\n"); GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } res = 0; GNUNET_SCHEDULER_add_delayed (WAIT, &end, NULL); return; } returned_records ++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); GNUNET_NAMESTORE_zone_iterator_next (zi); } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (&end, NULL); } } static void put_cont (void *cls, int32_t success, const char *emsg) { static int c = 0; if (success == GNUNET_OK) { c++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", emsg); GNUNET_break (0); if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if (c == 3) { res = 1; returned_records = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n"); zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, NULL, &zone_proc, NULL); if (zi == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); GNUNET_break (0); if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } } } static struct GNUNET_GNSRECORD_Data * create_record (unsigned int count) { unsigned int c; struct GNUNET_GNSRECORD_Data * rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; rd[c].record_type = 1111; rd[c].data_size = 50; rd[c].data = GNUNET_malloc(50); rd[c].flags = 0; memset ((char *) rd[c].data, 'a', 50); } return rd; } /** * Callback called from the zone iterator when we iterate over * the empty zone. Check that we got no records and then * start the actual tests by filling the zone. */ static void empty_zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { char *hostkey_file; GNUNET_assert (nsh == cls); if (NULL != zone) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Expected empty zone but received zone private key\n")); GNUNET_break (0); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if ((NULL != label) || (NULL != rd) || (0 != rd)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Expected no zone content but received data\n")); GNUNET_break (0); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } zi = NULL; GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey2 != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); GNUNET_asprintf(&s_name_1, "dummy1"); s_rd_1 = create_record(1); GNUNET_NAMESTORE_records_store(nsh, privkey, s_name_1, 1, s_rd_1, &put_cont, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); GNUNET_asprintf(&s_name_2, "dummy2"); s_rd_2 = create_record(1); GNUNET_NAMESTORE_records_store(nsh, privkey, s_name_2, 1, s_rd_2, &put_cont, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); /* name in different zone */ GNUNET_asprintf(&s_name_3, "dummy3"); s_rd_3 = create_record(1); GNUNET_NAMESTORE_records_store(nsh, privkey2, s_name_3, 1, s_rd_3, &put_cont, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT, &endbadly, NULL); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); /* first, iterate over empty namestore */ zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, NULL, &empty_zone_proc, nsh); if (NULL == zi) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); } } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration-stop", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_zone_iteration_stop.c */ gnunet-0.10.1/src/namestore/gnunet-namestore.c0000644000175000017500000005767712255036702016265 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnunet-namestore.c * @brief command line tool to manipulate the local zone * @author Christian Grothoff * * TODO: * - test */ #include "platform.h" #include #include #include #include #include #include /** * Handle to the namestore. */ static struct GNUNET_NAMESTORE_Handle *ns; /** * Private key for the our zone. */ static struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey; /** * Handle to identity lookup. */ static struct GNUNET_IDENTITY_EgoLookup *el; /** * Identity service handle */ static struct GNUNET_IDENTITY_Handle *idh; /** * Obtain default ego */ struct GNUNET_IDENTITY_Operation *get_default; /** * Name of the ego controlling the zone. */ static char *ego_name; /** * Desired action is to add a record. */ static int add; /** * Queue entry for the 'add-uri' operation. */ static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri; /** * Queue entry for the 'add' operation. */ static struct GNUNET_NAMESTORE_QueueEntry *add_qe; /** * Queue entry for the 'reverse lookup' operation (in combination with a name). */ static struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; /** * Desired action is to list records. */ static int list; /** * List iterator for the 'list' operation. */ static struct GNUNET_NAMESTORE_ZoneIterator *list_it; /** * Desired action is to remove a record. */ static int del; /** * Is record public (opposite of #GNUNET_GNSRECORD_RF_PRIVATE) */ static int public; /** * Is record a shadow record (#GNUNET_GNSRECORD_RF_SHADOW_RECORD) */ static int shadow; /** * Queue entry for the 'del' operation. */ static struct GNUNET_NAMESTORE_QueueEntry *del_qe; /** * Name of the records to add/list/remove. */ static char *name; /** * Value of the record to add/remove. */ static char *value; /** * URI to import. */ static char *uri; /** * Reverse lookup to perform. */ static char *reverse_pkey; /** * Type of the record to add/remove, NULL to remove all. */ static char *typestring; /** * Desired expiration time. */ static char *expirationstring; /** * Desired nick name. */ static char *nickstring; /** * Global return value */ static int ret; /** * Type string converted to DNS type value. */ static uint32_t type; /** * Value in binary format. */ static void *data; /** * Number of bytes in 'data'. */ static size_t data_size; /** * Expirationstring converted to relative time. */ static struct GNUNET_TIME_Relative etime_rel; /** * Expirationstring converted to absolute time. */ static struct GNUNET_TIME_Absolute etime_abs; /** * Is expiration time relative or absolute time? */ static int etime_is_rel = GNUNET_SYSERR; /** * Monitor handle. */ static struct GNUNET_NAMESTORE_ZoneMonitor *zm; /** * Enables monitor mode. */ static int monitor; /** * Task run on shutdown. Cleans up everything. * * @param cls unused * @param tc scheduler context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != get_default) { GNUNET_IDENTITY_cancel (get_default); get_default = NULL; } if (NULL != idh) { GNUNET_IDENTITY_disconnect (idh); idh = NULL; } if (NULL != el) { GNUNET_IDENTITY_ego_lookup_cancel (el); el = NULL; } if (NULL != list_it) { GNUNET_NAMESTORE_zone_iteration_stop (list_it); list_it = NULL; } if (NULL != add_qe) { GNUNET_NAMESTORE_cancel (add_qe); add_qe = NULL; } if (NULL != add_qe_uri) { GNUNET_NAMESTORE_cancel (add_qe_uri); add_qe_uri = NULL; } if (NULL != del_qe) { GNUNET_NAMESTORE_cancel (del_qe); del_qe = NULL; } if (NULL != ns) { GNUNET_NAMESTORE_disconnect (ns); ns = NULL; } memset (&zone_pkey, 0, sizeof (zone_pkey)); if (NULL != uri) { GNUNET_free (uri); uri = NULL; } if (NULL != zm) { GNUNET_NAMESTORE_zone_monitor_stop (zm); zm = NULL; } if (NULL != data) { GNUNET_free (data); data = NULL; } } /** * Check if we are finished, and if so, perform shutdown. */ static void test_finished () { if ( (NULL == add_qe) && (NULL == add_qe_uri) && (NULL == del_qe) && (NULL == reverse_qe) && (NULL == list_it) ) GNUNET_SCHEDULER_shutdown (); } /** * Continuation called to notify client about result of the * operation. * * @param cls closure, location of the QueueEntry pointer to NULL out * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) * #GNUNET_NO if content was already there * #GNUNET_YES (or other positive value) on success * @param emsg NULL on success, otherwise an error message */ static void add_continuation (void *cls, int32_t success, const char *emsg) { struct GNUNET_NAMESTORE_QueueEntry **qe = cls; *qe = NULL; if (GNUNET_YES != success) { fprintf (stderr, _("Adding record failed: %s\n"), (GNUNET_NO == success) ? "record exists" : emsg); if (GNUNET_NO != success) ret = 1; } ret = 0; test_finished (); } /** * Continuation called to notify client about result of the * operation. * * @param cls closure, unused * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) * #GNUNET_NO if content was already there * #GNUNET_YES (or other positive value) on success * @param emsg NULL on success, otherwise an error message */ static void del_continuation (void *cls, int32_t success, const char *emsg) { del_qe = NULL; if (GNUNET_NO == success) { fprintf (stderr, _("Deleting record failed, record does not exist%s%s\n"), (NULL != emsg) ? ": " : "", (NULL != emsg) ? emsg : ""); } if (GNUNET_SYSERR == success) { fprintf (stderr, _("Deleting record failed%s%s\n"), (NULL != emsg) ? ": " : "", (NULL != emsg) ? emsg : ""); } test_finished (); } /** * Process a record that was stored in the namestore. * * @param cls closure * @param zone_key private key of the zone * @param rname name that is being mapped (at most 255 characters long) * @param rd_len number of entries in @a rd array * @param rd array of records with data to store */ static void display_record (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *rname, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { const char *typestring; char *s; unsigned int i; const char *ets; struct GNUNET_TIME_Absolute at; struct GNUNET_TIME_Relative rt; if (NULL == rname) { list_it = NULL; test_finished (); return; } if ( (NULL != name) && (0 != strcmp (name, rname)) ) { GNUNET_NAMESTORE_zone_iterator_next (list_it); return; } FPRINTF (stdout, "%s:\n", rname); for (i=0;idata = data; rde->data_size = data_size; rde->record_type = type; if (1 == shadow) rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; if (1 != public) rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; if (GNUNET_YES == etime_is_rel) { rde->expiration_time = etime_rel.rel_value_us; rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; } else if (GNUNET_NO == etime_is_rel) rde->expiration_time = etime_abs.abs_value_us; else rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; GNUNET_assert (NULL != name); add_qe = GNUNET_NAMESTORE_records_store (ns, &zone_pkey, name, rd_count + 1, rde, &add_continuation, &add_qe); } /** * Function called with the result of our attempt to obtain a name for a given * public key. * * @param cls NULL * @param zone private key of the zone; NULL on disconnect * @param label label of the records; NULL on disconnect * @param rd_count number of entries in @a rd array, 0 if label was deleted * @param rd array of records with data to store */ static void handle_reverse_lookup (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { reverse_qe = NULL; if (NULL == label) FPRINTF (stdout, "%s.zkey\n", reverse_pkey); else FPRINTF (stdout, "%s.gnu\n", label); test_finished (); } /** * Function called with the result from the check if the namestore * service is actually running. If it is, we start the actual * operation. * * @param cls closure with our configuration * @param result #GNUNET_YES if the namestore service is running */ static void testservice_task (void *cls, int result) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_GNSRECORD_Data rd; if (GNUNET_YES != result) { FPRINTF (stderr, _("Service `%s' is not running\n"), "namestore"); return; } if (! (add|del|list|(NULL != nickstring)|(NULL != uri)|(NULL != reverse_pkey)) ) { /* nothing more to be done */ fprintf (stderr, _("No options given\n")); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_CRYPTO_ecdsa_key_get_public (&zone_pkey, &pub); ns = GNUNET_NAMESTORE_connect (cfg); if (NULL == ns) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to namestore\n")); return; } if (add) { if (NULL == name) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-n", _("add")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } if (NULL == typestring) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-t", _("add")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } type = GNUNET_GNSRECORD_typename_to_number (typestring); if (UINT32_MAX == type) { fprintf (stderr, _("Unsupported type `%s'\n"), typestring); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } if (NULL == value) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-V", _("add")); ret = 1; GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (type, value, &data, &data_size)) { fprintf (stderr, _("Value `%s' invalid for record type `%s'\n"), value, typestring); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } if (NULL == expirationstring) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-e", _("add")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } if (0 == strcmp (expirationstring, "never")) { etime_abs = GNUNET_TIME_UNIT_FOREVER_ABS; etime_is_rel = GNUNET_NO; } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel)) { etime_is_rel = GNUNET_YES; } else if (GNUNET_OK == GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs)) { etime_is_rel = GNUNET_NO; } else { fprintf (stderr, _("Invalid time format `%s'\n"), expirationstring); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } add_qe = GNUNET_NAMESTORE_records_lookup (ns, &zone_pkey, name, &get_existing_record, NULL ); } if (del) { if (NULL == name) { fprintf (stderr, _("Missing option `%s' for operation `%s'\n"), "-n", _("del")); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } del_qe = GNUNET_NAMESTORE_records_store (ns, &zone_pkey, name, 0, NULL, &del_continuation, NULL); } if (list) { list_it = GNUNET_NAMESTORE_zone_iteration_start (ns, &zone_pkey, &display_record, NULL); } if (NULL != reverse_pkey) { struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (reverse_pkey, strlen (reverse_pkey), &pubkey)) { fprintf (stderr, _("Invalid public key for reverse lookup `%s'\n"), reverse_pkey); GNUNET_SCHEDULER_shutdown (); } reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns, &zone_pkey, &pubkey, &handle_reverse_lookup, NULL); } if (NULL != uri) { char sh[105]; char sname[64]; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; if ( (2 != (sscanf (uri, "gnunet://gns/%52s/%63s", sh, sname)) ) || (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (sh, strlen (sh), &pkey)) ) { fprintf (stderr, _("Invalid URI `%s'\n"), uri); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } memset (&rd, 0, sizeof (rd)); rd.data = &pkey; rd.data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY; if (GNUNET_YES == etime_is_rel) { rd.expiration_time = etime_rel.rel_value_us; rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; } else if (GNUNET_NO == etime_is_rel) rd.expiration_time = etime_abs.abs_value_us; else rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; if (1 == shadow) rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; add_qe_uri = GNUNET_NAMESTORE_records_store (ns, &zone_pkey, sname, 1, &rd, &add_continuation, &add_qe_uri); } if (NULL != nickstring) { if (0 == strlen(nickstring)) { fprintf (stderr, _("Invalid nick `%s'\n"), nickstring); GNUNET_SCHEDULER_shutdown (); ret = 1; return; } add_qe_uri = GNUNET_NAMESTORE_set_nick(ns, &zone_pkey, nickstring, &add_continuation, &add_qe_uri); } if (monitor) { zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, &zone_pkey, GNUNET_YES, &display_record, &sync_cb, NULL); } } /** * Callback invoked from identity service with ego information. * An @a ego of NULL means the ego was not found. * * @param cls closure with the configuration * @param ego an ego known to identity service, or NULL */ static void identity_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; el = NULL; if (NULL == ego) { if (NULL != ego_name) { fprintf (stderr, _("Ego `%s' not known to identity service\n"), ego_name); } GNUNET_SCHEDULER_shutdown (); ret = -1; return; } zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); GNUNET_free_non_null (ego_name); ego_name = NULL; GNUNET_CLIENT_service_test ("namestore", cfg, GNUNET_TIME_UNIT_SECONDS, &testservice_task, (void *) cfg); } static void default_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { get_default = NULL; if (NULL == ego) { fprintf (stderr, _("No default ego configured in identity service\n")); GNUNET_SCHEDULER_shutdown (); ret = -1; return; } else { identity_cb (cls, ego); } } static void id_connect_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; if (NULL == ego) { get_default = GNUNET_IDENTITY_get (idh, "namestore", &default_ego_cb, (void *) cfg); } } static void testservice_id_task (void *cls, int result) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; if (result != GNUNET_YES) { fprintf (stderr, _("Identity service is not running\n")); GNUNET_SCHEDULER_shutdown (); ret = -1; return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, (void *) cfg); if (NULL == ego_name) { idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg); if (NULL == idh) fprintf (stderr, _("Cannot connect to identity service\n")); ret = -1; return; } el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg); } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { if ( (NULL != args[0]) && (NULL == uri) ) uri = GNUNET_strdup (args[0]); GNUNET_CLIENT_service_test ("identity", cfg, GNUNET_TIME_UNIT_SECONDS, &testservice_id_task, (void *) cfg); } /** * The main function for gnunet-namestore. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { public = -1; shadow = -1; static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'a', "add", NULL, gettext_noop ("add record"), 0, &GNUNET_GETOPT_set_one, &add}, {'d', "delete", NULL, gettext_noop ("delete record"), 0, &GNUNET_GETOPT_set_one, &del}, {'D', "display", NULL, gettext_noop ("display records"), 0, &GNUNET_GETOPT_set_one, &list}, {'e', "expiration", "TIME", gettext_noop ("expiration time for record to use (for adding only), \"never\" is possible"), 1, &GNUNET_GETOPT_set_string, &expirationstring}, {'i', "nick", "NICKNAME", gettext_noop ("set the desired nick name for the zone"), 1, &GNUNET_GETOPT_set_string, &nickstring}, {'m', "monitor", NULL, gettext_noop ("monitor changes in the namestore"), 0, &GNUNET_GETOPT_set_one, &monitor}, {'n', "name", "NAME", gettext_noop ("name of the record to add/delete/display"), 1, &GNUNET_GETOPT_set_string, &name}, {'r', "reverse", "PKEY", gettext_noop ("determine our name for the given PKEY"), 1, &GNUNET_GETOPT_set_string, &reverse_pkey}, {'t', "type", "TYPE", gettext_noop ("type of the record to add/delete/display"), 1, &GNUNET_GETOPT_set_string, &typestring}, {'u', "uri", "URI", gettext_noop ("URI to import into our zone"), 1, &GNUNET_GETOPT_set_string, &uri}, {'V', "value", "VALUE", gettext_noop ("value of the record to add/delete"), 1, &GNUNET_GETOPT_set_string, &value}, {'p', "public", NULL, gettext_noop ("create or list public record"), 0, &GNUNET_GETOPT_set_one, &public}, {'s', "shadow", NULL, gettext_noop ("create shadow record (only valid if all other records of the same type have expired"), 0, &GNUNET_GETOPT_set_one, &shadow}, {'z', "zone", "EGO", gettext_noop ("name of the ego controlling the zone"), 1, &GNUNET_GETOPT_set_string, &ego_name}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; GNUNET_log_setup ("gnunet-namestore", "WARNING", NULL); if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "gnunet-namestore", _("GNUnet zone manipulation tool"), options, &run, NULL)) { GNUNET_free ((void*) argv); GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey); return 1; } GNUNET_free ((void*) argv); GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey); return ret; } /* end of gnunet-namestore.c */ gnunet-0.10.1/src/namestore/namestore.h0000644000175000017500000001545412233724131014753 00000000000000/* This file is part of GNUnet. (C) 2011-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/namestore.h * @brief common internal definitions for namestore service * @author Matthias Wachs * @author Christian Grothoff */ #ifndef NAMESTORE_H #define NAMESTORE_H /** * Maximum length of any name, including 0-termination. */ #define MAX_NAME_LEN 256 GNUNET_NETWORK_STRUCT_BEGIN /** * Generic namestore message with op id */ struct GNUNET_NAMESTORE_Header { /** * header.type will be GNUNET_MESSAGE_TYPE_NAMESTORE_* * header.size will be message size */ struct GNUNET_MessageHeader header; /** * Request ID in NBO */ uint32_t r_id GNUNET_PACKED; }; /** * Store a record to the namestore (as authority). */ struct RecordStoreMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE */ struct GNUNET_NAMESTORE_Header gns_header; /** * Expiration time */ struct GNUNET_TIME_AbsoluteNBO expire; /** * Name length */ uint16_t name_len GNUNET_PACKED; /** * Length of serialized record data */ uint16_t rd_len GNUNET_PACKED; /** * Number of records contained */ uint16_t rd_count GNUNET_PACKED; /** * always zero (for alignment) */ uint16_t reserved GNUNET_PACKED; /** * The private key of the authority. */ struct GNUNET_CRYPTO_EcdsaPrivateKey private_key; /* followed by: * name with length name_len * serialized record data with rd_count records */ }; /** * Response to a record storage request. */ struct RecordStoreResponseMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE */ struct GNUNET_NAMESTORE_Header gns_header; /** * #GNUNET_SYSERR on failure, #GNUNET_OK on success */ int32_t op_result GNUNET_PACKED; }; /** * Lookup a label */ struct LabelLookupMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP */ struct GNUNET_NAMESTORE_Header gns_header; /** * Length of the name */ uint32_t label_len GNUNET_PACKED; /** * The private key of the zone to look up in */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; /* followed by: * name with length name_len */ }; /** * Lookup a label */ struct LabelLookupResponseMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE */ struct GNUNET_NAMESTORE_Header gns_header; /** * Name length */ uint16_t name_len GNUNET_PACKED; /** * Length of serialized record data */ uint16_t rd_len GNUNET_PACKED; /** * Number of records contained */ uint16_t rd_count GNUNET_PACKED; /** * Was the label found in the database?? * GNUNET_YES or GNUNET_NO */ uint16_t found GNUNET_PACKED; /** * The private key of the authority. */ struct GNUNET_CRYPTO_EcdsaPrivateKey private_key; /* followed by: * name with length name_len * serialized record data with rd_count records */ }; /** * Lookup a name for a zone hash */ struct ZoneToNameMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME */ struct GNUNET_NAMESTORE_Header gns_header; /** * The private key of the zone to look up in */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; /** * The public key of the target zone */ struct GNUNET_CRYPTO_EcdsaPublicKey value_zone; }; /** * Respone for zone to name lookup */ struct ZoneToNameResponseMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE */ struct GNUNET_NAMESTORE_Header gns_header; /** * Length of the name */ uint16_t name_len GNUNET_PACKED; /** * Length of serialized record data */ uint16_t rd_len GNUNET_PACKED; /** * Number of records contained */ uint16_t rd_count GNUNET_PACKED; /** * result in NBO: #GNUNET_OK on success, #GNUNET_NO if there were no * results, #GNUNET_SYSERR on error */ int16_t res GNUNET_PACKED; /** * The private key of the zone that contained the name. */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; /* followed by: * name with length name_len * serialized record data with rd_count records */ }; /** * Record is returned from the namestore (as authority). */ struct RecordResultMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT */ struct GNUNET_NAMESTORE_Header gns_header; /** * Name length */ uint16_t name_len GNUNET_PACKED; /** * Length of serialized record data */ uint16_t rd_len GNUNET_PACKED; /** * Number of records contained */ uint16_t rd_count GNUNET_PACKED; /** * always zero (for alignment) */ uint16_t reserved GNUNET_PACKED; /** * The private key of the authority. */ struct GNUNET_CRYPTO_EcdsaPrivateKey private_key; /* followed by: * name with length name_len * serialized record data with rd_count records */ }; /** * Start monitoring a zone. */ struct ZoneMonitorStartMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START */ struct GNUNET_MessageHeader header; /** * #GNUNET_YES to first iterate over all records, * #GNUNET_NO to only monitor changes.o */ uint32_t iterate_first GNUNET_PACKED; /** * Zone key. */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; }; /** * Start a zone iteration for the given zone */ struct ZoneIterationStartMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START */ struct GNUNET_NAMESTORE_Header gns_header; /** * Zone key. All zeros for "all zones". */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; }; /** * Ask for next result of zone iteration for the given operation */ struct ZoneIterationNextMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT */ struct GNUNET_NAMESTORE_Header gns_header; }; /** * Stop zone iteration for the given operation */ struct ZoneIterationStopMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP */ struct GNUNET_NAMESTORE_Header gns_header; }; GNUNET_NETWORK_STRUCT_END /* end of namestore.h */ #endif gnunet-0.10.1/src/namestore/test_namestore_api_remove.c0000644000175000017500000001255412251551532020214 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api.c * @brief testcase for namestore_api.c to: remove record */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle *nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static int removed; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; static char *directory; static void cleanup () { if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } static void remove_cont (void *cls, int32_t success, const char *emsg) { if (GNUNET_YES != success) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Records could not be removed: `%s'\n"), emsg); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Records were removed, perform lookup\n"); removed = GNUNET_YES; if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); GNUNET_SCHEDULER_add_now (&end, NULL); } static void put_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; GNUNET_assert (NULL != cls); if (GNUNET_SYSERR == success) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Namestore could not store record: `%s'\n", emsg); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 0, NULL, &remove_cont, (void *) name); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_GNSRECORD_Data rd; char *hostkey_file; const char * name = "dummy.dummy.gnunet"; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); removed = GNUNET_NO; rd.expiration_time = GNUNET_TIME_absolute_get().abs_value_us; rd.record_type = TEST_RECORD_TYPE; rd.data_size = TEST_RECORD_DATALEN; rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); rd.flags = 0; memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 1, &rd, &put_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } GNUNET_free ((void *)rd.data); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_remove.c */ gnunet-0.10.1/src/namestore/test_plugin_namestore.c0000644000175000017500000001303112236654562017365 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file namestore/test_plugin_namestore.c * @brief Test for the namestore plugins * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_namestore_plugin.h" #include "gnunet_testing_lib.h" static int ok; /** * Name of plugin under test. */ static const char *plugin_name; /** * Function called when the service shuts down. Unloads our namestore * plugin. * * @param api api to unload */ static void unload_plugin (struct GNUNET_NAMESTORE_PluginFunctions *api) { char *libname; GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name); GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api)); GNUNET_free (libname); } /** * Load the namestore plugin. * * @param cfg configuration to pass * @return NULL on error */ static struct GNUNET_NAMESTORE_PluginFunctions * load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAMESTORE_PluginFunctions *ret; char *libname; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' namestore plugin\n"), plugin_name); GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name); if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void*) cfg))) { FPRINTF (stderr, "Failed to load plugin `%s'!\n", plugin_name); GNUNET_free (libname); return NULL; } GNUNET_free (libname); return ret; } static void test_record (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int *idp = cls; int id = *idp; struct GNUNET_CRYPTO_EcdsaPrivateKey tzone_private_key; char tname[64]; unsigned int trd_count = 1 + (id % 1024); unsigned int i; GNUNET_snprintf (tname, sizeof (tname), "a%u", (unsigned int ) id); for (i=0;iiterate_records (nsp->cls, NULL, 0, &test_record, &id)); } static void put_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id) { struct GNUNET_CRYPTO_EcdsaPrivateKey zone_private_key; char label[64]; unsigned int rd_count = 1 + (id % 1024); struct GNUNET_GNSRECORD_Data rd[rd_count]; struct GNUNET_CRYPTO_EcdsaSignature signature; unsigned int i; GNUNET_snprintf (label, sizeof (label), "a%u", (unsigned int ) id); for (i=0;istore_records (nsp->cls, &zone_private_key, label, rd_count, rd)); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAMESTORE_PluginFunctions *nsp; ok = 0; nsp = load_plugin (cfg); if (NULL == nsp) { FPRINTF (stderr, "%s", "Failed to initialize namestore. Database likely not setup, skipping test.\n"); return; } put_record (nsp, 1); get_record (nsp, 1); unload_plugin (nsp); } int main (int argc, char *argv[]) { char cfg_name[128]; char *const xargv[] = { "test-plugin-namestore", "-c", cfg_name, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namestore-sqlite"); GNUNET_log_setup ("test-plugin-namestore", "WARNING", NULL); plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_plugin_namestore_%s.conf", plugin_name); GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "test-plugin-namestore", "nohelp", options, &run, NULL); if (ok != 0) FPRINTF (stderr, "Missed some testcases: %d\n", ok); GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namestore-sqlite"); return ok; } /* end of test_plugin_namestore.c */ gnunet-0.10.1/src/namestore/test_namestore_api_lookup_nick.c0000644000175000017500000002023112251551532021223 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_store.c * @brief testcase for namestore_api.c: store a record */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_NICK "gnunettestnick" #define TEST_RECORD_DATA 'a' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) static struct GNUNET_NAMESTORE_Handle *nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static struct GNUNET_GNSRECORD_Data rd_orig; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; //static const char * name = "dummy.dummy.gnunet"; static const char * name = "d"; static char *directory; static void cleanup () { GNUNET_free_non_null ((void *)rd_orig.data); if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } void lookup_it (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { nsqe = NULL; int c; int found_record = GNUNET_NO; int found_nick = GNUNET_NO; if (0 != memcmp(privkey, zone, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (NULL == label) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (0 != strcmp (label, name)) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (2 != rd_count) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } for (c = 0; c < rd_count; c++) { if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type) { if (rd[c].data_size != strlen(TEST_NICK)+1) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_PRIVATE)) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (0 != strcmp(rd[c].data, TEST_NICK)) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } found_nick = GNUNET_YES; } else { if (rd[c].record_type != TEST_RECORD_TYPE) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (rd[c].data_size != TEST_RECORD_DATALEN) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (0 != memcmp (rd[c].data, rd_orig.data, TEST_RECORD_DATALEN)) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (rd[c].flags != rd->flags) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } found_record = GNUNET_YES; } } /* Done */ if ((GNUNET_YES == found_nick) && (GNUNET_YES == found_record)) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_SCHEDULER_add_now (&end, NULL ); } else { GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_SCHEDULER_add_now (&endbadly, NULL ); } } static void put_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; nsqe = NULL; GNUNET_assert (NULL != cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); if (GNUNET_OK != success) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } /* Lookup */ nsqe = GNUNET_NAMESTORE_records_lookup (nsh, privkey, name, lookup_it, NULL); } static void nick_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Nick added : %s\n", (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); rd_orig.expiration_time = GNUNET_TIME_absolute_get().abs_value_us; rd_orig.record_type = TEST_RECORD_TYPE; rd_orig.data_size = TEST_RECORD_DATALEN; rd_orig.data = GNUNET_malloc (TEST_RECORD_DATALEN); rd_orig.flags = 0; memset ((char *) rd_orig.data, 'a', TEST_RECORD_DATALEN); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 1, &rd_orig, &put_cont, (void *) name); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { char *hostkey_file; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); nsqe = GNUNET_NAMESTORE_set_nick (nsh, privkey, TEST_NICK, &nick_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_store.c */ gnunet-0.10.1/src/namestore/Makefile.in0000644000175000017500000024626112320752062014655 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @HAVE_SQLITE_TRUE@check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) \ @HAVE_SQLITE_TRUE@ $(am__EXEEXT_3) libexec_PROGRAMS = gnunet-service-namestore$(EXEEXT) $(am__EXEEXT_4) bin_PROGRAMS = gnunet-namestore$(EXEEXT) @HAVE_MHD_TRUE@am__append_1 = \ @HAVE_MHD_TRUE@ gnunet-namestore-fcfsd subdir = src/namestore DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/namestore.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = namestore.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunet_plugin_namestore_postgres_la_OBJECTS = \ plugin_namestore_postgres.lo libgnunet_plugin_namestore_postgres_la_OBJECTS = \ $(am_libgnunet_plugin_namestore_postgres_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_namestore_postgres_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_namestore_postgres_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_POSTGRES_TRUE@am_libgnunet_plugin_namestore_postgres_la_rpath = \ @HAVE_POSTGRES_TRUE@ -rpath $(plugindir) am_libgnunet_plugin_namestore_sqlite_la_OBJECTS = \ plugin_namestore_sqlite.lo libgnunet_plugin_namestore_sqlite_la_OBJECTS = \ $(am_libgnunet_plugin_namestore_sqlite_la_OBJECTS) libgnunet_plugin_namestore_sqlite_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_namestore_sqlite_la_LDFLAGS) $(LDFLAGS) -o \ $@ @HAVE_SQLITE_TRUE@am_libgnunet_plugin_namestore_sqlite_la_rpath = \ @HAVE_SQLITE_TRUE@ -rpath $(plugindir) libgnunetnamestore_la_DEPENDENCIES = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetnamestore_la_OBJECTS = namestore_api.lo \ namestore_api_monitor.lo libgnunetnamestore_la_OBJECTS = $(am_libgnunetnamestore_la_OBJECTS) libgnunetnamestore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetnamestore_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_1 = test_plugin_namestore_sqlite$(EXEEXT) @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_2 = test_plugin_namestore_postgres$(EXEEXT) @HAVE_TESTING_TRUE@am__EXEEXT_3 = test_namestore_api_store$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_store_update$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_public$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_private$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_nick$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_shadow$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_shadow_filter$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_remove$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_remove_not_existing_record$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_zone_iteration$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_zone_iteration_nick$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_zone_iteration_specific_zone$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_zone_iteration_stop$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_monitoring$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_namestore_api_monitoring_existing$(EXEEXT) @HAVE_MHD_TRUE@am__EXEEXT_4 = gnunet-namestore-fcfsd$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_namestore_OBJECTS = gnunet-namestore.$(OBJEXT) gnunet_namestore_OBJECTS = $(am_gnunet_namestore_OBJECTS) am_gnunet_namestore_fcfsd_OBJECTS = gnunet-namestore-fcfsd.$(OBJEXT) gnunet_namestore_fcfsd_OBJECTS = $(am_gnunet_namestore_fcfsd_OBJECTS) am_gnunet_service_namestore_OBJECTS = \ gnunet-service-namestore.$(OBJEXT) gnunet_service_namestore_OBJECTS = \ $(am_gnunet_service_namestore_OBJECTS) am_test_namestore_api_lookup_nick_OBJECTS = \ test_namestore_api_lookup_nick.$(OBJEXT) test_namestore_api_lookup_nick_OBJECTS = \ $(am_test_namestore_api_lookup_nick_OBJECTS) test_namestore_api_lookup_nick_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_lookup_private_OBJECTS = \ test_namestore_api_lookup_private.$(OBJEXT) test_namestore_api_lookup_private_OBJECTS = \ $(am_test_namestore_api_lookup_private_OBJECTS) test_namestore_api_lookup_private_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_lookup_public_OBJECTS = \ test_namestore_api_lookup_public.$(OBJEXT) test_namestore_api_lookup_public_OBJECTS = \ $(am_test_namestore_api_lookup_public_OBJECTS) test_namestore_api_lookup_public_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_lookup_shadow_OBJECTS = \ test_namestore_api_lookup_shadow.$(OBJEXT) test_namestore_api_lookup_shadow_OBJECTS = \ $(am_test_namestore_api_lookup_shadow_OBJECTS) test_namestore_api_lookup_shadow_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_lookup_shadow_filter_OBJECTS = \ test_namestore_api_lookup_shadow_filter.$(OBJEXT) test_namestore_api_lookup_shadow_filter_OBJECTS = \ $(am_test_namestore_api_lookup_shadow_filter_OBJECTS) test_namestore_api_lookup_shadow_filter_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_monitoring_OBJECTS = \ test_namestore_api_monitoring.$(OBJEXT) test_namestore_api_monitoring_OBJECTS = \ $(am_test_namestore_api_monitoring_OBJECTS) test_namestore_api_monitoring_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_namestore_api_monitoring_existing_OBJECTS = \ test_namestore_api_monitoring_existing.$(OBJEXT) test_namestore_api_monitoring_existing_OBJECTS = \ $(am_test_namestore_api_monitoring_existing_OBJECTS) test_namestore_api_monitoring_existing_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_namestore_api_remove_OBJECTS = \ test_namestore_api_remove.$(OBJEXT) test_namestore_api_remove_OBJECTS = \ $(am_test_namestore_api_remove_OBJECTS) test_namestore_api_remove_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_remove_not_existing_record_OBJECTS = \ test_namestore_api_remove_not_existing_record.$(OBJEXT) test_namestore_api_remove_not_existing_record_OBJECTS = \ $(am_test_namestore_api_remove_not_existing_record_OBJECTS) test_namestore_api_remove_not_existing_record_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_store_OBJECTS = \ test_namestore_api_store.$(OBJEXT) test_namestore_api_store_OBJECTS = \ $(am_test_namestore_api_store_OBJECTS) test_namestore_api_store_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_store_update_OBJECTS = \ test_namestore_api_store_update.$(OBJEXT) test_namestore_api_store_update_OBJECTS = \ $(am_test_namestore_api_store_update_OBJECTS) test_namestore_api_store_update_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_zone_iteration_OBJECTS = \ test_namestore_api_zone_iteration.$(OBJEXT) test_namestore_api_zone_iteration_OBJECTS = \ $(am_test_namestore_api_zone_iteration_OBJECTS) test_namestore_api_zone_iteration_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_zone_iteration_nick_OBJECTS = \ test_namestore_api_zone_iteration_nick.$(OBJEXT) test_namestore_api_zone_iteration_nick_OBJECTS = \ $(am_test_namestore_api_zone_iteration_nick_OBJECTS) test_namestore_api_zone_iteration_nick_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_zone_iteration_specific_zone_OBJECTS = \ test_namestore_api_zone_iteration_specific_zone.$(OBJEXT) test_namestore_api_zone_iteration_specific_zone_OBJECTS = \ $(am_test_namestore_api_zone_iteration_specific_zone_OBJECTS) test_namestore_api_zone_iteration_specific_zone_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_namestore_api_zone_iteration_stop_OBJECTS = \ test_namestore_api_zone_iteration_stop.$(OBJEXT) test_namestore_api_zone_iteration_stop_OBJECTS = \ $(am_test_namestore_api_zone_iteration_stop_OBJECTS) test_namestore_api_zone_iteration_stop_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la am_test_plugin_namestore_postgres_OBJECTS = \ test_plugin_namestore.$(OBJEXT) test_plugin_namestore_postgres_OBJECTS = \ $(am_test_plugin_namestore_postgres_OBJECTS) test_plugin_namestore_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_namestore_sqlite_OBJECTS = \ test_plugin_namestore.$(OBJEXT) test_plugin_namestore_sqlite_OBJECTS = \ $(am_test_plugin_namestore_sqlite_OBJECTS) test_plugin_namestore_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_namestore_postgres_la_SOURCES) \ $(libgnunet_plugin_namestore_sqlite_la_SOURCES) \ $(libgnunetnamestore_la_SOURCES) $(gnunet_namestore_SOURCES) \ $(gnunet_namestore_fcfsd_SOURCES) \ $(gnunet_service_namestore_SOURCES) \ $(test_namestore_api_lookup_nick_SOURCES) \ $(test_namestore_api_lookup_private_SOURCES) \ $(test_namestore_api_lookup_public_SOURCES) \ $(test_namestore_api_lookup_shadow_SOURCES) \ $(test_namestore_api_lookup_shadow_filter_SOURCES) \ $(test_namestore_api_monitoring_SOURCES) \ $(test_namestore_api_monitoring_existing_SOURCES) \ $(test_namestore_api_remove_SOURCES) \ $(test_namestore_api_remove_not_existing_record_SOURCES) \ $(test_namestore_api_store_SOURCES) \ $(test_namestore_api_store_update_SOURCES) \ $(test_namestore_api_zone_iteration_SOURCES) \ $(test_namestore_api_zone_iteration_nick_SOURCES) \ $(test_namestore_api_zone_iteration_specific_zone_SOURCES) \ $(test_namestore_api_zone_iteration_stop_SOURCES) \ $(test_plugin_namestore_postgres_SOURCES) \ $(test_plugin_namestore_sqlite_SOURCES) DIST_SOURCES = $(libgnunet_plugin_namestore_postgres_la_SOURCES) \ $(libgnunet_plugin_namestore_sqlite_la_SOURCES) \ $(libgnunetnamestore_la_SOURCES) $(gnunet_namestore_SOURCES) \ $(gnunet_namestore_fcfsd_SOURCES) \ $(gnunet_service_namestore_SOURCES) \ $(test_namestore_api_lookup_nick_SOURCES) \ $(test_namestore_api_lookup_private_SOURCES) \ $(test_namestore_api_lookup_public_SOURCES) \ $(test_namestore_api_lookup_shadow_SOURCES) \ $(test_namestore_api_lookup_shadow_filter_SOURCES) \ $(test_namestore_api_monitoring_SOURCES) \ $(test_namestore_api_monitoring_existing_SOURCES) \ $(test_namestore_api_remove_SOURCES) \ $(test_namestore_api_remove_not_existing_record_SOURCES) \ $(test_namestore_api_store_SOURCES) \ $(test_namestore_api_store_update_SOURCES) \ $(test_namestore_api_zone_iteration_SOURCES) \ $(test_namestore_api_zone_iteration_nick_SOURCES) \ $(test_namestore_api_zone_iteration_specific_zone_SOURCES) \ $(test_namestore_api_zone_iteration_stop_SOURCES) \ $(test_plugin_namestore_postgres_SOURCES) \ $(test_plugin_namestore_sqlite_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ namestore.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIBS = -lgcov @HAVE_SQLITE_TRUE@SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@SQLITE_TESTS = test_plugin_namestore_sqlite # postgres doesn't even build yet; thus: experimental! @HAVE_POSTGRES_TRUE@POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@POSTGRES_TESTS = test_plugin_namestore_postgres # testcases do not even build yet; thus: experimental! @HAVE_TESTING_TRUE@TESTING_TESTS = \ @HAVE_TESTING_TRUE@ test_namestore_api_store \ @HAVE_TESTING_TRUE@ test_namestore_api_store_update \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_public \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_private \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_nick \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_shadow \ @HAVE_TESTING_TRUE@ test_namestore_api_lookup_shadow_filter \ @HAVE_TESTING_TRUE@ test_namestore_api_remove \ @HAVE_TESTING_TRUE@ test_namestore_api_remove_not_existing_record \ @HAVE_TESTING_TRUE@ test_namestore_api_zone_iteration \ @HAVE_TESTING_TRUE@ test_namestore_api_zone_iteration_nick \ @HAVE_TESTING_TRUE@ test_namestore_api_zone_iteration_specific_zone \ @HAVE_TESTING_TRUE@ test_namestore_api_zone_iteration_stop \ @HAVE_TESTING_TRUE@ test_namestore_api_monitoring \ @HAVE_TESTING_TRUE@ test_namestore_api_monitoring_existing @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = \ @ENABLE_TEST_RUN_TRUE@ $(check_PROGRAMS) \ @ENABLE_TEST_RUN_TRUE@ $(check_SCRIPTS) lib_LTLIBRARIES = \ libgnunetnamestore.la libgnunetnamestore_la_SOURCES = \ namestore_api.c \ namestore_api_monitor.c \ namestore.h libgnunetnamestore_la_LIBADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetnamestore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:1:0 gnunet_namestore_SOURCES = \ gnunet-namestore.c gnunet_namestore_LDADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la \ $(GN_LIBINTL) gnunet_namestore_DEPENDENCIES = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la gnunet_namestore_fcfsd_SOURCES = \ gnunet-namestore-fcfsd.c gnunet_namestore_fcfsd_LDADD = -lmicrohttpd \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_namestore_fcfsd_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la gnunet_service_namestore_SOURCES = \ gnunet-service-namestore.c gnunet_service_namestore_LDADD = \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la \ $(GN_LIBINTL) gnunet_service_namestore_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ $(POSTGRES_PLUGIN) libgnunet_plugin_namestore_sqlite_la_SOURCES = \ plugin_namestore_sqlite.c libgnunet_plugin_namestore_sqlite_la_LIBADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la libgnunet_plugin_namestore_postgres_la_SOURCES = \ plugin_namestore_postgres.c libgnunet_plugin_namestore_postgres_la_LIBADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ $(LTLIBINTL) libgnunet_plugin_namestore_postgres_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_namestore_postgres_la_DEPENDENCIES = \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la test_namestore_api_store_SOURCES = \ test_namestore_api_store.c test_namestore_api_store_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_store_update_SOURCES = \ test_namestore_api_store_update.c test_namestore_api_store_update_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_public_SOURCES = \ test_namestore_api_lookup_public.c test_namestore_api_lookup_public_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_nick_SOURCES = \ test_namestore_api_lookup_nick.c test_namestore_api_lookup_nick_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_private_SOURCES = \ test_namestore_api_lookup_private.c test_namestore_api_lookup_private_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_shadow_SOURCES = \ test_namestore_api_lookup_shadow.c test_namestore_api_lookup_shadow_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_shadow_filter_SOURCES = \ test_namestore_api_lookup_shadow_filter.c test_namestore_api_lookup_shadow_filter_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_remove_SOURCES = \ test_namestore_api_remove.c test_namestore_api_remove_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_remove_not_existing_record_SOURCES = \ test_namestore_api_remove_not_existing_record.c test_namestore_api_remove_not_existing_record_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la #test_namestore_api_zone_to_name_SOURCES = \ # test_namestore_api_zone_to_name.c #test_namestore_api_zone_to_name_LDADD = \ # $(top_builddir)/src/testing/libgnunettesting.la \ # $(top_builddir)/src/util/libgnunetutil.la \ # $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_monitoring_SOURCES = \ test_namestore_api_monitoring.c test_namestore_api_monitoring_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_namestore_api_monitoring_existing_SOURCES = \ test_namestore_api_monitoring_existing.c test_namestore_api_monitoring_existing_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_namestore_api_zone_iteration_SOURCES = \ test_namestore_api_zone_iteration.c test_namestore_api_zone_iteration_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_iteration_nick_SOURCES = \ test_namestore_api_zone_iteration_nick.c test_namestore_api_zone_iteration_nick_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_iteration_specific_zone_SOURCES = \ test_namestore_api_zone_iteration_specific_zone.c test_namestore_api_zone_iteration_specific_zone_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_iteration_stop_SOURCES = \ test_namestore_api_zone_iteration_stop.c test_namestore_api_zone_iteration_stop_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_plugin_namestore_sqlite_SOURCES = \ test_plugin_namestore.c test_plugin_namestore_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_namestore_postgres_SOURCES = \ test_plugin_namestore.c test_plugin_namestore_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la check_SCRIPTS = \ test_namestore_put.sh \ test_namestore_lookup.sh \ test_namestore_delete.sh EXTRA_DIST = \ test_namestore_api.conf \ test_plugin_namestore_sqlite.conf \ test_plugin_namestore_postgres.conf \ test_hostkey \ zonefiles/S5I9DSGQVAB5FVV16T3B3CC5H1B2JGL3Q412JBKURME8EKU0600G.zkey \ zonefiles/AQ835GVL939H4O8QJQ7GBLPTQC0QAAO91BN7QK01BA63MDSK6I4G.zkey \ zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey \ zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey \ $(check_SCRIPTS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/namestore/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/namestore/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): namestore.conf: $(top_builddir)/config.status $(srcdir)/namestore.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_namestore_postgres.la: $(libgnunet_plugin_namestore_postgres_la_OBJECTS) $(libgnunet_plugin_namestore_postgres_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_namestore_postgres_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_namestore_postgres_la_LINK) $(am_libgnunet_plugin_namestore_postgres_la_rpath) $(libgnunet_plugin_namestore_postgres_la_OBJECTS) $(libgnunet_plugin_namestore_postgres_la_LIBADD) $(LIBS) libgnunet_plugin_namestore_sqlite.la: $(libgnunet_plugin_namestore_sqlite_la_OBJECTS) $(libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_namestore_sqlite_la_LINK) $(am_libgnunet_plugin_namestore_sqlite_la_rpath) $(libgnunet_plugin_namestore_sqlite_la_OBJECTS) $(libgnunet_plugin_namestore_sqlite_la_LIBADD) $(LIBS) libgnunetnamestore.la: $(libgnunetnamestore_la_OBJECTS) $(libgnunetnamestore_la_DEPENDENCIES) $(EXTRA_libgnunetnamestore_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetnamestore_la_LINK) -rpath $(libdir) $(libgnunetnamestore_la_OBJECTS) $(libgnunetnamestore_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-namestore$(EXEEXT): $(gnunet_namestore_OBJECTS) $(gnunet_namestore_DEPENDENCIES) $(EXTRA_gnunet_namestore_DEPENDENCIES) @rm -f gnunet-namestore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_namestore_OBJECTS) $(gnunet_namestore_LDADD) $(LIBS) gnunet-namestore-fcfsd$(EXEEXT): $(gnunet_namestore_fcfsd_OBJECTS) $(gnunet_namestore_fcfsd_DEPENDENCIES) $(EXTRA_gnunet_namestore_fcfsd_DEPENDENCIES) @rm -f gnunet-namestore-fcfsd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_namestore_fcfsd_OBJECTS) $(gnunet_namestore_fcfsd_LDADD) $(LIBS) gnunet-service-namestore$(EXEEXT): $(gnunet_service_namestore_OBJECTS) $(gnunet_service_namestore_DEPENDENCIES) $(EXTRA_gnunet_service_namestore_DEPENDENCIES) @rm -f gnunet-service-namestore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_namestore_OBJECTS) $(gnunet_service_namestore_LDADD) $(LIBS) test_namestore_api_lookup_nick$(EXEEXT): $(test_namestore_api_lookup_nick_OBJECTS) $(test_namestore_api_lookup_nick_DEPENDENCIES) $(EXTRA_test_namestore_api_lookup_nick_DEPENDENCIES) @rm -f test_namestore_api_lookup_nick$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_lookup_nick_OBJECTS) $(test_namestore_api_lookup_nick_LDADD) $(LIBS) test_namestore_api_lookup_private$(EXEEXT): $(test_namestore_api_lookup_private_OBJECTS) $(test_namestore_api_lookup_private_DEPENDENCIES) $(EXTRA_test_namestore_api_lookup_private_DEPENDENCIES) @rm -f test_namestore_api_lookup_private$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_lookup_private_OBJECTS) $(test_namestore_api_lookup_private_LDADD) $(LIBS) test_namestore_api_lookup_public$(EXEEXT): $(test_namestore_api_lookup_public_OBJECTS) $(test_namestore_api_lookup_public_DEPENDENCIES) $(EXTRA_test_namestore_api_lookup_public_DEPENDENCIES) @rm -f test_namestore_api_lookup_public$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_lookup_public_OBJECTS) $(test_namestore_api_lookup_public_LDADD) $(LIBS) test_namestore_api_lookup_shadow$(EXEEXT): $(test_namestore_api_lookup_shadow_OBJECTS) $(test_namestore_api_lookup_shadow_DEPENDENCIES) $(EXTRA_test_namestore_api_lookup_shadow_DEPENDENCIES) @rm -f test_namestore_api_lookup_shadow$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_lookup_shadow_OBJECTS) $(test_namestore_api_lookup_shadow_LDADD) $(LIBS) test_namestore_api_lookup_shadow_filter$(EXEEXT): $(test_namestore_api_lookup_shadow_filter_OBJECTS) $(test_namestore_api_lookup_shadow_filter_DEPENDENCIES) $(EXTRA_test_namestore_api_lookup_shadow_filter_DEPENDENCIES) @rm -f test_namestore_api_lookup_shadow_filter$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_lookup_shadow_filter_OBJECTS) $(test_namestore_api_lookup_shadow_filter_LDADD) $(LIBS) test_namestore_api_monitoring$(EXEEXT): $(test_namestore_api_monitoring_OBJECTS) $(test_namestore_api_monitoring_DEPENDENCIES) $(EXTRA_test_namestore_api_monitoring_DEPENDENCIES) @rm -f test_namestore_api_monitoring$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_monitoring_OBJECTS) $(test_namestore_api_monitoring_LDADD) $(LIBS) test_namestore_api_monitoring_existing$(EXEEXT): $(test_namestore_api_monitoring_existing_OBJECTS) $(test_namestore_api_monitoring_existing_DEPENDENCIES) $(EXTRA_test_namestore_api_monitoring_existing_DEPENDENCIES) @rm -f test_namestore_api_monitoring_existing$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_monitoring_existing_OBJECTS) $(test_namestore_api_monitoring_existing_LDADD) $(LIBS) test_namestore_api_remove$(EXEEXT): $(test_namestore_api_remove_OBJECTS) $(test_namestore_api_remove_DEPENDENCIES) $(EXTRA_test_namestore_api_remove_DEPENDENCIES) @rm -f test_namestore_api_remove$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_remove_OBJECTS) $(test_namestore_api_remove_LDADD) $(LIBS) test_namestore_api_remove_not_existing_record$(EXEEXT): $(test_namestore_api_remove_not_existing_record_OBJECTS) $(test_namestore_api_remove_not_existing_record_DEPENDENCIES) $(EXTRA_test_namestore_api_remove_not_existing_record_DEPENDENCIES) @rm -f test_namestore_api_remove_not_existing_record$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_remove_not_existing_record_OBJECTS) $(test_namestore_api_remove_not_existing_record_LDADD) $(LIBS) test_namestore_api_store$(EXEEXT): $(test_namestore_api_store_OBJECTS) $(test_namestore_api_store_DEPENDENCIES) $(EXTRA_test_namestore_api_store_DEPENDENCIES) @rm -f test_namestore_api_store$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_store_OBJECTS) $(test_namestore_api_store_LDADD) $(LIBS) test_namestore_api_store_update$(EXEEXT): $(test_namestore_api_store_update_OBJECTS) $(test_namestore_api_store_update_DEPENDENCIES) $(EXTRA_test_namestore_api_store_update_DEPENDENCIES) @rm -f test_namestore_api_store_update$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_store_update_OBJECTS) $(test_namestore_api_store_update_LDADD) $(LIBS) test_namestore_api_zone_iteration$(EXEEXT): $(test_namestore_api_zone_iteration_OBJECTS) $(test_namestore_api_zone_iteration_DEPENDENCIES) $(EXTRA_test_namestore_api_zone_iteration_DEPENDENCIES) @rm -f test_namestore_api_zone_iteration$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_iteration_OBJECTS) $(test_namestore_api_zone_iteration_LDADD) $(LIBS) test_namestore_api_zone_iteration_nick$(EXEEXT): $(test_namestore_api_zone_iteration_nick_OBJECTS) $(test_namestore_api_zone_iteration_nick_DEPENDENCIES) $(EXTRA_test_namestore_api_zone_iteration_nick_DEPENDENCIES) @rm -f test_namestore_api_zone_iteration_nick$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_iteration_nick_OBJECTS) $(test_namestore_api_zone_iteration_nick_LDADD) $(LIBS) test_namestore_api_zone_iteration_specific_zone$(EXEEXT): $(test_namestore_api_zone_iteration_specific_zone_OBJECTS) $(test_namestore_api_zone_iteration_specific_zone_DEPENDENCIES) $(EXTRA_test_namestore_api_zone_iteration_specific_zone_DEPENDENCIES) @rm -f test_namestore_api_zone_iteration_specific_zone$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_iteration_specific_zone_OBJECTS) $(test_namestore_api_zone_iteration_specific_zone_LDADD) $(LIBS) test_namestore_api_zone_iteration_stop$(EXEEXT): $(test_namestore_api_zone_iteration_stop_OBJECTS) $(test_namestore_api_zone_iteration_stop_DEPENDENCIES) $(EXTRA_test_namestore_api_zone_iteration_stop_DEPENDENCIES) @rm -f test_namestore_api_zone_iteration_stop$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_namestore_api_zone_iteration_stop_OBJECTS) $(test_namestore_api_zone_iteration_stop_LDADD) $(LIBS) test_plugin_namestore_postgres$(EXEEXT): $(test_plugin_namestore_postgres_OBJECTS) $(test_plugin_namestore_postgres_DEPENDENCIES) $(EXTRA_test_plugin_namestore_postgres_DEPENDENCIES) @rm -f test_plugin_namestore_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_namestore_postgres_OBJECTS) $(test_plugin_namestore_postgres_LDADD) $(LIBS) test_plugin_namestore_sqlite$(EXEEXT): $(test_plugin_namestore_sqlite_OBJECTS) $(test_plugin_namestore_sqlite_DEPENDENCIES) $(EXTRA_test_plugin_namestore_sqlite_DEPENDENCIES) @rm -f test_plugin_namestore_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_namestore_sqlite_OBJECTS) $(test_plugin_namestore_sqlite_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-namestore-fcfsd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-namestore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-namestore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namestore_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/namestore_api_monitor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_namestore_postgres.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_namestore_sqlite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_lookup_nick.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_lookup_private.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_lookup_public.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_lookup_shadow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_lookup_shadow_filter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_monitoring.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_monitoring_existing.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_remove.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_remove_not_existing_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_store.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_store_update.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_iteration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_iteration_nick.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_iteration_specific_zone.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_namestore_api_zone_iteration_stop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_namestore.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_plugin_namestore_sqlite.log: test_plugin_namestore_sqlite$(EXEEXT) @p='test_plugin_namestore_sqlite$(EXEEXT)'; \ b='test_plugin_namestore_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_namestore_postgres.log: test_plugin_namestore_postgres$(EXEEXT) @p='test_plugin_namestore_postgres$(EXEEXT)'; \ b='test_plugin_namestore_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_store.log: test_namestore_api_store$(EXEEXT) @p='test_namestore_api_store$(EXEEXT)'; \ b='test_namestore_api_store'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_store_update.log: test_namestore_api_store_update$(EXEEXT) @p='test_namestore_api_store_update$(EXEEXT)'; \ b='test_namestore_api_store_update'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_lookup_public.log: test_namestore_api_lookup_public$(EXEEXT) @p='test_namestore_api_lookup_public$(EXEEXT)'; \ b='test_namestore_api_lookup_public'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_lookup_private.log: test_namestore_api_lookup_private$(EXEEXT) @p='test_namestore_api_lookup_private$(EXEEXT)'; \ b='test_namestore_api_lookup_private'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_lookup_nick.log: test_namestore_api_lookup_nick$(EXEEXT) @p='test_namestore_api_lookup_nick$(EXEEXT)'; \ b='test_namestore_api_lookup_nick'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_lookup_shadow.log: test_namestore_api_lookup_shadow$(EXEEXT) @p='test_namestore_api_lookup_shadow$(EXEEXT)'; \ b='test_namestore_api_lookup_shadow'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_lookup_shadow_filter.log: test_namestore_api_lookup_shadow_filter$(EXEEXT) @p='test_namestore_api_lookup_shadow_filter$(EXEEXT)'; \ b='test_namestore_api_lookup_shadow_filter'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_remove.log: test_namestore_api_remove$(EXEEXT) @p='test_namestore_api_remove$(EXEEXT)'; \ b='test_namestore_api_remove'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_remove_not_existing_record.log: test_namestore_api_remove_not_existing_record$(EXEEXT) @p='test_namestore_api_remove_not_existing_record$(EXEEXT)'; \ b='test_namestore_api_remove_not_existing_record'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_zone_iteration.log: test_namestore_api_zone_iteration$(EXEEXT) @p='test_namestore_api_zone_iteration$(EXEEXT)'; \ b='test_namestore_api_zone_iteration'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_zone_iteration_nick.log: test_namestore_api_zone_iteration_nick$(EXEEXT) @p='test_namestore_api_zone_iteration_nick$(EXEEXT)'; \ b='test_namestore_api_zone_iteration_nick'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_zone_iteration_specific_zone.log: test_namestore_api_zone_iteration_specific_zone$(EXEEXT) @p='test_namestore_api_zone_iteration_specific_zone$(EXEEXT)'; \ b='test_namestore_api_zone_iteration_specific_zone'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_zone_iteration_stop.log: test_namestore_api_zone_iteration_stop$(EXEEXT) @p='test_namestore_api_zone_iteration_stop$(EXEEXT)'; \ b='test_namestore_api_zone_iteration_stop'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_monitoring.log: test_namestore_api_monitoring$(EXEEXT) @p='test_namestore_api_monitoring$(EXEEXT)'; \ b='test_namestore_api_monitoring'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_api_monitoring_existing.log: test_namestore_api_monitoring_existing$(EXEEXT) @p='test_namestore_api_monitoring_existing$(EXEEXT)'; \ b='test_namestore_api_monitoring_existing'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_put.sh.log: test_namestore_put.sh @p='test_namestore_put.sh'; \ b='test_namestore_put.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_lookup.sh.log: test_namestore_lookup.sh @p='test_namestore_lookup.sh'; \ b='test_namestore_lookup.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_namestore_delete.sh.log: test_namestore_delete.sh @p='test_namestore_delete.sh'; \ b='test_namestore_delete.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/namestore/test_namestore_api_monitoring.c0000644000175000017500000002145112251551532021100 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_monitoring.c * @brief testcase for zone monitoring functionality: monitor first, then add records */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #include "namestore.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle * nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2; static struct GNUNET_NAMESTORE_ZoneMonitor *zm; static int res; static char * s_name_1; static struct GNUNET_GNSRECORD_Data *s_rd_1; static char * s_name_2; static struct GNUNET_GNSRECORD_Data *s_rd_2; static char * s_name_3; static struct GNUNET_GNSRECORD_Data *s_rd_3; struct GNUNET_NAMESTORE_QueueEntry * ns_ops[3]; static char *directory; static void do_shutdown () { if (NULL != zm) { GNUNET_NAMESTORE_zone_monitor_stop (zm); zm = NULL; } if (NULL != ns_ops[0]) { GNUNET_NAMESTORE_cancel(ns_ops[0]); ns_ops[0] = NULL; } if (NULL != ns_ops[1]) { GNUNET_NAMESTORE_cancel(ns_ops[1]); ns_ops[1] = NULL; } if (NULL != ns_ops[2]) { GNUNET_NAMESTORE_cancel(ns_ops[2]); ns_ops[2] = NULL; } if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } GNUNET_free_non_null(s_name_1); GNUNET_free_non_null(s_name_2); GNUNET_free_non_null(s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } if (NULL != privkey2) { GNUNET_free (privkey2); privkey2 = NULL; } } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { do_shutdown (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { do_shutdown (); res = 0; } static void zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { static int returned_records; static int fail = GNUNET_NO; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing results name %s\n", name); if (0 != memcmp (zone_key, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitoring returned wrong zone key\n"); GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if (0 == strcmp (name, s_name_1)) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_1)) { GNUNET_break (0); fail = GNUNET_YES; } } else if (0 == strcmp (name, s_name_2)) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_2)) { GNUNET_break (0); fail = GNUNET_YES; } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid name %s\n", name); GNUNET_break (0); fail = GNUNET_YES; } if (2 == ++returned_records) { if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_YES == fail) GNUNET_SCHEDULER_add_now (&endbadly, NULL); else GNUNET_SCHEDULER_add_now (&end, NULL); } } static void put_cont (void *cls, int32_t success, const char *emsg) { static int c = 0; char *label = cls; if (0 == strcmp (label, s_name_1)) ns_ops[0] = NULL; else if (0 == strcmp (label, s_name_2)) ns_ops[1] = NULL; else if (0 == strcmp (label, s_name_3)) ns_ops[2] = NULL; if (success == GNUNET_OK) { c++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u: `%s'\n", c, label); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records\n"); GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); } } static struct GNUNET_GNSRECORD_Data * create_record (unsigned int count) { unsigned int c; struct GNUNET_GNSRECORD_Data * rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; rd[c].record_type = 1111; rd[c].data_size = 50; rd[c].data = GNUNET_malloc(50); rd[c].flags = 0; memset ((char *) rd[c].data, 'a', 50); } return rd; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { char *hostkey_file; res = 1; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); GNUNET_asprintf(&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); /* Start monitoring */ zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, privkey, GNUNET_YES, &zone_proc, NULL, NULL); if (NULL == zm) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone monitor\n"); GNUNET_break (0); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); /* Connect to namestore */ nsh = GNUNET_NAMESTORE_connect (cfg); if (NULL == nsh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connect to namestore\n"); GNUNET_break (0); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_asprintf(&hostkey_file,"zonefiles%s%s", DIR_SEPARATOR_STR, "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey2 != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); /* name in different zone */ GNUNET_asprintf(&s_name_3, "dummy3"); s_rd_3 = create_record(1); GNUNET_assert (NULL != (ns_ops[2] = GNUNET_NAMESTORE_records_store (nsh, privkey2, s_name_3, 1, s_rd_3, &put_cont, s_name_3))); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); GNUNET_asprintf(&s_name_1, "dummy1"); s_rd_1 = create_record(1); GNUNET_assert (NULL != (ns_ops[0] = GNUNET_NAMESTORE_records_store(nsh, privkey, s_name_1, 1, s_rd_1, &put_cont, s_name_1))); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); GNUNET_asprintf(&s_name_2, "dummy2"); s_rd_2 = create_record(1); GNUNET_assert (NULL != (ns_ops[1] = GNUNET_NAMESTORE_records_store(nsh, privkey, s_name_2, 1, s_rd_2, &put_cont, s_name_2))); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api-monitoring", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_monitoring.c */ gnunet-0.10.1/src/namestore/test_namestore_api_zone_iteration_nick.c0000644000175000017500000003007412251551532022751 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_zone_iteration.c * @brief testcase for zone iteration functionality: iterate all zones */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #include "namestore.h" #define ZONE_NICK_1 "nick1" #define ZONE_NICK_2 "nick2" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle * nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2; static struct GNUNET_NAMESTORE_ZoneIterator *zi; static int res; static int returned_records; static char * s_name_1; static struct GNUNET_GNSRECORD_Data *s_rd_1; static char * s_name_2; static struct GNUNET_GNSRECORD_Data *s_rd_2; static char * s_name_3; static struct GNUNET_GNSRECORD_Data *s_rd_3; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; static char *directory; /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != zi) { GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; } if (nsh != NULL) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } GNUNET_free_non_null(s_name_1); GNUNET_free_non_null(s_name_2); GNUNET_free_non_null(s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (privkey != NULL) GNUNET_free (privkey); privkey = NULL; if (privkey2 != NULL) GNUNET_free (privkey2); privkey2 = NULL; res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != zi) { GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; } if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (privkey != NULL) GNUNET_free (privkey); privkey = NULL; if (privkey2 != NULL) GNUNET_free (privkey2); privkey2 = NULL; GNUNET_free (s_name_1); GNUNET_free (s_name_2); GNUNET_free (s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (nsh != NULL) GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } static int check_zone_1 (const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int failed = GNUNET_NO; int c; for (c = 0; c< rd_count ; c++) { if (rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) if (0 != strcmp (rd[c].data, ZONE_NICK_1)) { GNUNET_break (0); return GNUNET_YES; } } return failed; } static int check_zone_2 (const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int failed = GNUNET_NO; int c; for (c = 0; c< rd_count ; c++) { if (rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) if (0 != strcmp (rd[c].data, ZONE_NICK_2)) { GNUNET_break (0); return GNUNET_YES; } } return failed; } static void zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int failed = GNUNET_NO; if ((zone == NULL) && (label == NULL)) { zi = NULL; res = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n", returned_records); GNUNET_SCHEDULER_add_now (&end, NULL); return; } if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { failed = check_zone_1 (label, rd_count, rd); if (GNUNET_YES == failed) GNUNET_break (0); } else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { failed = check_zone_2 (label, rd_count, rd); if (GNUNET_YES == failed) GNUNET_break (0); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid zone\n"); failed = GNUNET_YES; GNUNET_break (0); } if (failed == GNUNET_NO) { returned_records ++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); GNUNET_NAMESTORE_zone_iterator_next (zi); } else { GNUNET_break (0); res = 1; GNUNET_SCHEDULER_add_now (&end, NULL); } } static void put_cont (void *cls, int32_t success, const char *emsg) { static int c = 0; if (success == GNUNET_OK) { c++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", emsg); GNUNET_break (0); if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if (c == 3) { res = 1; returned_records = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n"); zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, NULL, &zone_proc, NULL); if (zi == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); GNUNET_break (0); if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } } } static struct GNUNET_GNSRECORD_Data * create_record (unsigned int count) { unsigned int c; struct GNUNET_GNSRECORD_Data * rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; rd[c].record_type = 1111; rd[c].data_size = 50; rd[c].data = GNUNET_malloc(50); rd[c].flags = 0; memset ((char *) rd[c].data, 'a', 50); } return rd; } static void nick_2_cont (void *cls, int32_t success, const char *emsg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Nick added : %s\n", (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); GNUNET_asprintf(&s_name_1, "dummy1"); s_rd_1 = create_record(1); GNUNET_NAMESTORE_records_store (nsh, privkey, s_name_1, 1, s_rd_1, &put_cont, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); GNUNET_asprintf(&s_name_2, "dummy2"); s_rd_2 = create_record(1); GNUNET_NAMESTORE_records_store (nsh, privkey, s_name_2, 1, s_rd_2, &put_cont, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); /* name in different zone */ GNUNET_asprintf(&s_name_3, "dummy3"); s_rd_3 = create_record(1); GNUNET_NAMESTORE_records_store (nsh, privkey2, s_name_3, 1, s_rd_3, &put_cont, NULL); } static void nick_1_cont (void *cls, int32_t success, const char *emsg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Nick 1 added : %s\n", (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); nsqe = GNUNET_NAMESTORE_set_nick (nsh, privkey2, ZONE_NICK_2, &nick_2_cont, &privkey2); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } } /** * Callback called from the zone iterator when we iterate over * the empty zone. Check that we got no records and then * start the actual tests by filling the zone. */ static void empty_zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { char *hostkey_file; GNUNET_assert (nsh == cls); if (NULL != zone) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Expected empty zone but received zone private key\n")); GNUNET_break (0); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if ((NULL != label) || (NULL != rd) || (0 != rd_count)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Expected no zone content but received data\n")); GNUNET_break (0); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } zi = NULL; GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey2 != NULL); nsqe = GNUNET_NAMESTORE_set_nick (nsh, privkey, ZONE_NICK_1, &nick_1_cont, &privkey); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT, &endbadly, NULL); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); /* first, iterate over empty namestore */ zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, NULL, &empty_zone_proc, nsh); if (NULL == zi) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); } } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_zone_iteration.c */ gnunet-0.10.1/src/namestore/test_namestore_api_monitoring_existing.c0000644000175000017500000002160612251551532023014 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_monitoring.c * @brief testcase for zone monitoring functionality: add records first, then monitor */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #include "namestore.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_NAMESTORE_Handle * nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2; static struct GNUNET_NAMESTORE_ZoneMonitor *zm; static int res; static char * s_name_1; static struct GNUNET_GNSRECORD_Data *s_rd_1; static char * s_name_2; static struct GNUNET_GNSRECORD_Data *s_rd_2; static char * s_name_3; static struct GNUNET_GNSRECORD_Data *s_rd_3; struct GNUNET_NAMESTORE_QueueEntry * ns_ops[3]; static char *directory; static void do_shutdown () { if (NULL != zm) { GNUNET_NAMESTORE_zone_monitor_stop (zm); zm = NULL; } if (NULL != ns_ops[0]) { GNUNET_NAMESTORE_cancel(ns_ops[0]); ns_ops[0] = NULL; } if (NULL != ns_ops[1]) { GNUNET_NAMESTORE_cancel(ns_ops[1]); ns_ops[1] = NULL; } if (NULL != ns_ops[2]) { GNUNET_NAMESTORE_cancel(ns_ops[2]); ns_ops[2] = NULL; } if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } GNUNET_free_non_null(s_name_1); GNUNET_free_non_null(s_name_2); GNUNET_free_non_null(s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } if (NULL != privkey2) { GNUNET_free (privkey2); privkey2 = NULL; } } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { do_shutdown (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { do_shutdown (); res = 0; } static void zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { static int returned_records; static int fail = GNUNET_NO; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing results name %s\n", name); if (0 != memcmp (zone_key, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitoring returned wrong zone key\n"); GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if (0 == strcmp (name, s_name_1)) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_1)) { GNUNET_break (0); fail = GNUNET_YES; } } else if (0 == strcmp (name, s_name_2)) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_2)) { GNUNET_break (0); fail = GNUNET_YES; } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid name %s\n", name); GNUNET_break (0); fail = GNUNET_YES; } if (2 == ++returned_records) { if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_YES == fail) GNUNET_SCHEDULER_add_now (&endbadly, NULL); else GNUNET_SCHEDULER_add_now (&end, NULL); } } static void put_cont (void *cls, int32_t success, const char *emsg) { static int c = 0; char *label = cls; if (0 == strcmp (label, s_name_1)) ns_ops[0] = NULL; else if (0 == strcmp (label, s_name_2)) ns_ops[1] = NULL; else if (0 == strcmp (label, s_name_3)) ns_ops[2] = NULL; if (success == GNUNET_OK) { c++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u: `%s'\n", c, label); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records\n"); GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); } if (3 == c) { /* Start monitoring */ zm = GNUNET_NAMESTORE_zone_monitor_start (cfg, privkey, GNUNET_YES, &zone_proc, NULL, NULL); if (NULL == zm) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone monitor\n"); GNUNET_break (0); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } } } static struct GNUNET_GNSRECORD_Data * create_record (unsigned int count) { unsigned int c; struct GNUNET_GNSRECORD_Data * rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; rd[c].record_type = 1111; rd[c].data_size = 50; rd[c].data = GNUNET_malloc(50); rd[c].flags = 0; memset ((char *) rd[c].data, 'a', 50); } return rd; } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *mycfg, struct GNUNET_TESTING_Peer *peer) { char *hostkey_file; directory = NULL; GNUNET_CONFIGURATION_get_value_string(mycfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); res = 1; GNUNET_asprintf(&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); cfg = mycfg; endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); /* Connect to namestore */ nsh = GNUNET_NAMESTORE_connect (cfg); if (NULL == nsh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connect to namestore\n"); GNUNET_break (0); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_asprintf(&hostkey_file,"zonefiles%s%s", DIR_SEPARATOR_STR, "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey2 != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); /* name in different zone */ GNUNET_asprintf(&s_name_3, "dummy3"); s_rd_3 = create_record(1); GNUNET_assert (NULL != (ns_ops[2] = GNUNET_NAMESTORE_records_store (nsh, privkey2, s_name_3, 1, s_rd_3, &put_cont, s_name_3))); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); GNUNET_asprintf(&s_name_1, "dummy1"); s_rd_1 = create_record(1); GNUNET_assert (NULL != (ns_ops[0] = GNUNET_NAMESTORE_records_store(nsh, privkey, s_name_1, 1, s_rd_1, &put_cont, s_name_1))); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); GNUNET_asprintf(&s_name_2, "dummy2"); s_rd_2 = create_record(1); GNUNET_assert (NULL != (ns_ops[1] = GNUNET_NAMESTORE_records_store(nsh, privkey, s_name_2, 1, s_rd_2, &put_cont, s_name_2))); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api-monitoring", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_monitoring.c */ gnunet-0.10.1/src/namestore/test_namestore_api_store_update.c0000644000175000017500000001771112251551532021415 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_store_update.c * @brief testcase for namestore_api.c: store a record, update it and perform a lookup * @author Matthias Wachs */ #include "platform.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TEST_RECORD_TYPE2 4321 #define TEST_RECORD_DATALEN2 234 #define TEST_RECORD_DATA2 'b' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle *nsh; static struct GNUNET_NAMECACHE_Handle *nch; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static int update_performed; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; static struct GNUNET_NAMECACHE_QueueEntry *ncqe; static const char *name = "dummy"; static char *directory; static void cleanup () { if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != nch) { GNUNET_NAMECACHE_disconnect (nch); nch = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } if (NULL != ncqe) { GNUNET_NAMECACHE_cancel (ncqe); ncqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } static void put_cont (void *cls, int32_t success, const char *emsg); static void rd_decrypt_cb (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_GNSRECORD_Data rd_new; GNUNET_assert (1 == rd_count); GNUNET_assert (NULL != rd); if (GNUNET_NO == update_performed) { char rd_cmp_data[TEST_RECORD_DATALEN]; memset (rd_cmp_data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type); GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size); GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Block was decrypted successfully, updating record \n"); rd_new.flags = GNUNET_GNSRECORD_RF_NONE; rd_new.expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 1000000000; rd_new.record_type = TEST_RECORD_TYPE2; rd_new.data_size = TEST_RECORD_DATALEN2; rd_new.data = GNUNET_malloc (TEST_RECORD_DATALEN2); memset ((char *) rd_new.data, TEST_RECORD_DATA2, TEST_RECORD_DATALEN2); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 1, &rd_new, &put_cont, (void *) name); update_performed = GNUNET_YES; } else { char rd_cmp_data[TEST_RECORD_DATALEN2]; memset (rd_cmp_data, TEST_RECORD_DATA2, TEST_RECORD_DATALEN2); GNUNET_assert (TEST_RECORD_TYPE2 == rd[0].record_type); GNUNET_assert (TEST_RECORD_DATALEN2 == rd[0].data_size); GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN2)); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_SCHEDULER_add_now (&end, NULL); } } static void name_lookup_proc (void *cls, const struct GNUNET_GNSRECORD_Block *block) { const char *name = cls; ncqe = NULL; GNUNET_assert (NULL != cls); if (NULL == block) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namecache returned no block for `%s'\n"), name); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namecache returned block, decrypting \n"); GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt(block, &pubkey, name, &rd_decrypt_cb, (void *) name)); } static void put_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; struct GNUNET_HashCode derived_hash; nsqe = NULL; GNUNET_assert (NULL != cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); /* Create derived hash */ GNUNET_GNSRECORD_query_from_private_key (privkey, name, &derived_hash); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking in namecache for `%s'\n", GNUNET_h2s (&derived_hash)); ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash, &name_lookup_proc, (void *) name); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_GNSRECORD_Data rd; char *hostkey_file; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); update_performed = GNUNET_NO; endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); rd.flags = GNUNET_GNSRECORD_RF_NONE; rd.expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 1000000000; rd.record_type = TEST_RECORD_TYPE; rd.data_size = TEST_RECORD_DATALEN; rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); memset ((char *) rd.data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); nch = GNUNET_NAMECACHE_connect (cfg); GNUNET_break (NULL != nch); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 1, &rd, &put_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } GNUNET_free ((void *)rd.data); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api-store-update", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_store_update.c*/ gnunet-0.10.1/src/namestore/plugin_namestore_sqlite.c0000644000175000017500000005435312233724131017706 00000000000000 /* * This file is part of GNUnet * (C) 2009-2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file namestore/plugin_namestore_sqlite.c * @brief sqlite-based namestore backend * @author Christian Grothoff */ #include "platform.h" #include "gnunet_namestore_plugin.h" #include "gnunet_namestore_service.h" #include "gnunet_gnsrecord_lib.h" #include "namestore.h" #include /** * After how many ms "busy" should a DB operation fail for good? A * low value makes sure that we are more responsive to requests * (especially PUTs). A high value guarantees a higher success rate * (SELECTs in iterate can take several seconds despite LIMIT=1). * * The default value of 1s should ensure that users do not experience * huge latencies while at the same time allowing operations to * succeed with reasonable probability. */ #define BUSY_TIMEOUT_MS 1000 /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, "namestore-sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) #define LOG(kind,...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__) /** * Context for all functions in this plugin. */ struct Plugin { const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Database filename. */ char *fn; /** * Native SQLite database handle. */ sqlite3 *dbh; /** * Precompiled SQL to store records. */ sqlite3_stmt *store_records; /** * Precompiled SQL to deltete existing records. */ sqlite3_stmt *delete_records; /** * Precompiled SQL for iterate records within a zone. */ sqlite3_stmt *iterate_zone; /** * Precompiled SQL for iterate all records within all zones. */ sqlite3_stmt *iterate_all_zones; /** * Precompiled SQL to for reverse lookup based on PKEY. */ sqlite3_stmt *zone_to_name; /** * Precompiled SQL to lookup records based on label. */ sqlite3_stmt *lookup_label; }; /** * @brief Prepare a SQL statement * * @param dbh handle to the database * @param zSql SQL statement, UTF-8 encoded * @param ppStmt set to the prepared statement * @return 0 on success */ static int sq_prepare (sqlite3 * dbh, const char *zSql, sqlite3_stmt ** ppStmt) { char *dummy; int result; result = sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt, (const char **) &dummy); LOG (GNUNET_ERROR_TYPE_DEBUG, "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result); return result; } /** * Create our database indices. * * @param dbh handle to the database */ static void create_indices (sqlite3 * dbh) { /* create indices */ if ( (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_pkey_reverse ON ns097records (zone_private_key,pkey)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS ir_pkey_iter ON ns097records (zone_private_key,rvalue)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS it_iter ON ns097records (rvalue)", NULL, NULL, NULL)) ) LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to create indices: %s\n", sqlite3_errmsg (dbh)); } #if 0 #define CHECK(a) GNUNET_break(a) #define ENULL NULL #else #define ENULL &e #define ENULL_DEFINED 1 #define CHECK(a) if (! a) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); } #endif /** * Initialize the database connections and associated * data structures (create tables and indices * as needed as well). * * @param plugin the plugin context (state for this module) * @return #GNUNET_OK on success */ static int database_setup (struct Plugin *plugin) { sqlite3_stmt *stmt; char *afsdir; #if ENULL_DEFINED char *e; #endif if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, "namestore-sqlite", "FILENAME", &afsdir)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "namestore-sqlite", "FILENAME"); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_DISK_file_test (afsdir)) { if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir)) { GNUNET_break (0); GNUNET_free (afsdir); return GNUNET_SYSERR; } } /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ plugin->fn = afsdir; /* Open database and precompile statements */ if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Unable to initialize SQLite: %s.\n"), sqlite3_errmsg (plugin->dbh)); return GNUNET_SYSERR; } CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA synchronous=NORMAL", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA encoding=\"UTF-8\"", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA count_changes=OFF", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA page_size=4092", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS)); /* Create table */ CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "SELECT 1 FROM sqlite_master WHERE tbl_name = 'ns097records'", &stmt)); if ((sqlite3_step (stmt) == SQLITE_DONE) && (sqlite3_exec (plugin->dbh, "CREATE TABLE ns097records (" " zone_private_key BLOB NOT NULL DEFAULT ''," " pkey BLOB," " rvalue INT8 NOT NULL DEFAULT ''," " record_count INT NOT NULL DEFAULT 0," " record_data BLOB NOT NULL DEFAULT ''," " label TEXT NOT NULL DEFAULT ''" ")", NULL, NULL, NULL) != SQLITE_OK)) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); sqlite3_finalize (stmt); return GNUNET_SYSERR; } sqlite3_finalize (stmt); create_indices (plugin->dbh); if ((sq_prepare (plugin->dbh, "INSERT INTO ns097records (zone_private_key, pkey, rvalue, record_count, record_data, label)" " VALUES (?, ?, ?, ?, ?, ?)", &plugin->store_records) != SQLITE_OK) || (sq_prepare (plugin->dbh, "DELETE FROM ns097records WHERE zone_private_key=? AND label=?", &plugin->delete_records) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT record_count,record_data,label" " FROM ns097records WHERE zone_private_key=? AND pkey=?", &plugin->zone_to_name) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT record_count,record_data,label" " FROM ns097records WHERE zone_private_key=? ORDER BY rvalue LIMIT 1 OFFSET ?", &plugin->iterate_zone) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT record_count,record_data,label,zone_private_key" " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET ?", &plugin->iterate_all_zones) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT record_count,record_data,label,zone_private_key" " FROM ns097records WHERE zone_private_key=? AND label=?", &plugin->lookup_label) != SQLITE_OK) ) { LOG_SQLITE (plugin,GNUNET_ERROR_TYPE_ERROR, "precompiling"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Shutdown database connection and associate data * structures. * @param plugin the plugin context (state for this module) */ static void database_shutdown (struct Plugin *plugin) { int result; sqlite3_stmt *stmt; if (NULL != plugin->store_records) sqlite3_finalize (plugin->store_records); if (NULL != plugin->delete_records) sqlite3_finalize (plugin->delete_records); if (NULL != plugin->iterate_zone) sqlite3_finalize (plugin->iterate_zone); if (NULL != plugin->iterate_all_zones) sqlite3_finalize (plugin->iterate_all_zones); if (NULL != plugin->zone_to_name) sqlite3_finalize (plugin->zone_to_name); if (NULL != plugin->zone_to_name) sqlite3_finalize (plugin->lookup_label); result = sqlite3_close (plugin->dbh); if (result == SQLITE_BUSY) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Tried to close sqlite without finalizing all prepared statements.\n")); stmt = sqlite3_next_stmt (plugin->dbh, NULL); while (stmt != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Closing statement %p\n", stmt); result = sqlite3_finalize (stmt); if (result != SQLITE_OK) GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", "Failed to close statement %p: %d\n", stmt, result); stmt = sqlite3_next_stmt (plugin->dbh, NULL); } result = sqlite3_close (plugin->dbh); } if (SQLITE_OK != result) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); GNUNET_free_non_null (plugin->fn); } /** * Store a record in the datastore. Removes any existing record in the * same zone with the same name. * * @param cls closure (internal context for the plugin) * @param zone_key private key of the zone * @param label name that is being mapped (at most 255 characters long) * @param rd_count number of entries in @a rd array * @param rd array of records with data to store * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int namestore_sqlite_store_records (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct Plugin *plugin = cls; int n; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; uint64_t rvalue; size_t data_size; unsigned int i; memset (&pkey, 0, sizeof (pkey)); for (i=0;i 64 * 65536) { GNUNET_break (0); return GNUNET_SYSERR; } { char data[data_size]; if (data_size != GNUNET_GNSRECORD_records_serialize (rd_count, rd, data_size, data)) { GNUNET_break (0); return GNUNET_SYSERR; } /* First delete 'old' records */ if ((SQLITE_OK != sqlite3_bind_blob (plugin->delete_records, 1, zone_key, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_text (plugin->delete_records, 2, label, -1, SQLITE_STATIC))) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->delete_records)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } n = sqlite3_step (plugin->delete_records); if (SQLITE_OK != sqlite3_reset (plugin->delete_records)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); if (0 != rd_count) { if ((SQLITE_OK != sqlite3_bind_blob (plugin->store_records, 1, zone_key, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_blob (plugin->store_records, 2, &pkey, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int64 (plugin->store_records, 3, rvalue)) || (SQLITE_OK != sqlite3_bind_int (plugin->store_records, 4, rd_count)) || (SQLITE_OK != sqlite3_bind_blob (plugin->store_records, 5, data, data_size, SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_text (plugin->store_records, 6, label, -1, SQLITE_STATIC))) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->store_records)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } n = sqlite3_step (plugin->store_records); if (SQLITE_OK != sqlite3_reset (plugin->store_records)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } } switch (n) { case SQLITE_DONE: if (0 != rd_count) GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Record stored\n"); else GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Record deleted\n"); return GNUNET_OK; case SQLITE_BUSY: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return GNUNET_NO; default: LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return GNUNET_SYSERR; } } /** * The given 'sqlite' statement has been prepared to be run. * It will return a record which should be given to the iterator. * Runs the statement and parses the returned record. * * @param plugin plugin context * @param stmt to run (and then clean up) * @param zone_key private key of the zone * @param iter iterator to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int get_record_and_call_iterator (struct Plugin *plugin, sqlite3_stmt *stmt, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { unsigned int record_count; size_t data_size; const char *data; const char *label; int ret; int sret; ret = GNUNET_NO; if (SQLITE_ROW == (sret = sqlite3_step (stmt))) { record_count = sqlite3_column_int (stmt, 0); data_size = sqlite3_column_bytes (stmt, 1); data = sqlite3_column_blob (stmt, 1); label = (const char*) sqlite3_column_text (stmt, 2); if (NULL == zone_key) { /* must be "iterate_all_zones", got one extra return value */ if (sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) != sqlite3_column_bytes (stmt, 3)) { GNUNET_break (0); ret = GNUNET_SYSERR; } else { zone_key = sqlite3_column_blob (stmt, 3); } } if (record_count > 64 * 1024) { /* sanity check, don't stack allocate far too much just because database might contain a large value here */ GNUNET_break (0); ret = GNUNET_SYSERR; } else { struct GNUNET_GNSRECORD_Data rd[record_count]; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (data_size, data, record_count, rd)) { GNUNET_break (0); ret = GNUNET_SYSERR; } else if (NULL != zone_key) { if (NULL != iter) iter (iter_cls, zone_key, label, record_count, rd); ret = GNUNET_YES; } } } else { if (SQLITE_DONE != sret) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); } if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return ret; } /** * Lookup records in the datastore for which we are the authority. * * @param cls closure (internal context for the plugin) * @param zone private key of the zone * @param label name of the record in the zone * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int namestore_sqlite_lookup_records (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; int err; if (NULL == zone) { return GNUNET_SYSERR; } else { stmt = plugin->lookup_label; err = ( (SQLITE_OK != sqlite3_bind_blob (stmt, 1, zone, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_text (stmt, 2, label, -1, SQLITE_STATIC)) ); } if (err) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return get_record_and_call_iterator (plugin, stmt, zone, iter, iter_cls); } /** * Iterate over the results for a particular key and zone in the * datastore. Will return at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param zone hash of public key of the zone, NULL to iterate over all zones * @param offset offset in the list of all matching records * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int namestore_sqlite_iterate_records (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, uint64_t offset, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; int err; if (NULL == zone) { stmt = plugin->iterate_all_zones; err = (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, offset)); } else { stmt = plugin->iterate_zone; err = ( (SQLITE_OK != sqlite3_bind_blob (stmt, 1, zone, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, offset)) ); } if (err) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } return get_record_and_call_iterator (plugin, stmt, zone, iter, iter_cls); } /** * Look for an existing PKEY delegation record for a given public key. * Returns at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param zone private key of the zone to look up in, never NULL * @param value_zone public key of the target zone (value), never NULL * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int namestore_sqlite_zone_to_name (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; stmt = plugin->zone_to_name; if ( (SQLITE_OK != sqlite3_bind_blob (stmt, 1, zone, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), SQLITE_STATIC)) || (SQLITE_OK != sqlite3_bind_blob (stmt, 2, value_zone, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), SQLITE_STATIC)) ) { LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Performing reverse lookup for `%s'\n", GNUNET_GNSRECORD_z2s (value_zone)); return get_record_and_call_iterator (plugin, stmt, zone, iter, iter_cls); } /** * Entry point for the plugin. * * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" * @return NULL on error, otherwise the plugin context */ void * libgnunet_plugin_namestore_sqlite_init (void *cls) { static struct Plugin plugin; const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_NAMESTORE_PluginFunctions *api; if (NULL != plugin.cfg) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); plugin.cfg = cfg; if (GNUNET_OK != database_setup (&plugin)) { database_shutdown (&plugin); return NULL; } api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); api->cls = &plugin; api->store_records = &namestore_sqlite_store_records; api->iterate_records = &namestore_sqlite_iterate_records; api->zone_to_name = &namestore_sqlite_zone_to_name; api->lookup_records = &namestore_sqlite_lookup_records; LOG (GNUNET_ERROR_TYPE_INFO, _("Sqlite database running\n")); return api; } /** * Exit point from the plugin. * * @param cls the plugin context (as returned by "init") * @return always NULL */ void * libgnunet_plugin_namestore_sqlite_done (void *cls) { struct GNUNET_NAMESTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; database_shutdown (plugin); plugin->cfg = NULL; GNUNET_free (api); LOG (GNUNET_ERROR_TYPE_DEBUG, "sqlite plugin is finished\n"); return NULL; } /* end of plugin_namestore_sqlite.c */ gnunet-0.10.1/src/namestore/test_namestore_api_lookup_shadow_filter.c0000644000175000017500000002427312255013665023147 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_lookup_shadow_filter.c * @brief testcase for namestore_api.c: store a record with short expiration * and a shadow record, perform lookup: * - when active record is valid, expect only active record * - when active record is expired, expect shadow record only */ #include "platform.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_NAME "dummy.dummy.gnunet" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TEST_SHADOW_RECORD_DATA 'b' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) #define EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) static struct GNUNET_NAMESTORE_Handle *nsh; static struct GNUNET_NAMECACHE_Handle *nch; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static GNUNET_SCHEDULER_TaskIdentifier delayed_lookup_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; static struct GNUNET_NAMECACHE_QueueEntry *ncqe; static struct GNUNET_NAMECACHE_QueueEntry *ncqe_shadow; static struct GNUNET_GNSRECORD_Data records[2]; static struct GNUNET_TIME_Absolute record_expiration; static struct GNUNET_HashCode derived_hash; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static char *directory; static void cleanup () { if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != nch) { GNUNET_NAMECACHE_disconnect (nch); nch = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != delayed_lookup_task) { GNUNET_SCHEDULER_cancel (delayed_lookup_task); delayed_lookup_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } if (NULL != ncqe) { GNUNET_NAMECACHE_cancel (ncqe); ncqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } static void rd_decrypt_cb (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_GNSRECORD_Data *expected_rd = cls; char rd_cmp_data[TEST_RECORD_DATALEN]; if (1 != rd_count) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (NULL == rd) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (expected_rd == &records[0]) { /* Expecting active record */ memset (rd_cmp_data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); if (TEST_RECORD_TYPE != rd[0].record_type) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (TEST_RECORD_DATALEN != rd[0].data_size) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags)) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Block was decrypted successfully with active record\n"); } if (expected_rd == &records[1]) { /* Expecting shadow record but without shadow flag*/ memset (rd_cmp_data, TEST_SHADOW_RECORD_DATA, TEST_RECORD_DATALEN); if (TEST_RECORD_TYPE != rd[0].record_type) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (TEST_RECORD_DATALEN != rd[0].data_size) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags)) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Block was decrypted successfully with former shadow record \n"); GNUNET_SCHEDULER_add_now (&end, NULL ); } } static void name_lookup_active_proc (void *cls, const struct GNUNET_GNSRECORD_Block *block) { struct GNUNET_GNSRECORD_Data *expected_rd = cls; GNUNET_assert (NULL != expected_rd); ncqe = NULL; ncqe_shadow = NULL; if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL == block) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore returned no block\n")); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned block, decrypting \n"); GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt(block, &pubkey, TEST_NAME, &rd_decrypt_cb, expected_rd)); } static void name_lookup_shadow (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Performing lookup for shadow record \n"); delayed_lookup_task = GNUNET_SCHEDULER_NO_TASK; ncqe_shadow = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash, &name_lookup_active_proc, &records[1]); } static void put_cont (void *cls, int32_t success, const char *emsg) { nsqe = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", TEST_NAME, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); /* Create derived hash */ GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); GNUNET_GNSRECORD_query_from_public_key (&pubkey, TEST_NAME, &derived_hash); if (0 == GNUNET_TIME_absolute_get_remaining(record_expiration).rel_value_us ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test to too long to store records, cannot run test!\n"); GNUNET_SCHEDULER_add_now (&end, NULL ); return; } /* Lookup active record now */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Performing lookup for active record \n"); ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash, &name_lookup_active_proc, &records[0]); delayed_lookup_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (EXPIRATION, 2), &name_lookup_shadow, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { char *hostkey_file; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); record_expiration = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), EXPIRATION); records[0].expiration_time = record_expiration.abs_value_us; records[0].record_type = TEST_RECORD_TYPE; records[0].data_size = TEST_RECORD_DATALEN; records[0].data = GNUNET_malloc (TEST_RECORD_DATALEN); records[0].flags = GNUNET_GNSRECORD_RF_NONE; memset ((char *) records[0].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); records[1].expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 1000000000; records[1].record_type = TEST_RECORD_TYPE; records[1].data_size = TEST_RECORD_DATALEN; records[1].data = GNUNET_malloc (TEST_RECORD_DATALEN); records[1].flags = GNUNET_GNSRECORD_RF_SHADOW_RECORD; memset ((char *) records[1].data, TEST_SHADOW_RECORD_DATA, TEST_RECORD_DATALEN); nsh = GNUNET_NAMESTORE_connect (cfg); nch = GNUNET_NAMECACHE_connect (cfg); GNUNET_break (NULL != nsh); GNUNET_break (NULL != nch); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, TEST_NAME, 2, records, &put_cont, NULL); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } GNUNET_free ((void *) records[0].data); GNUNET_free ((void *) records[1].data); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_lookup_shadow_filter.c */ gnunet-0.10.1/src/namestore/namestore.conf.in0000644000175000017500000000134412252271721016052 00000000000000[namestore] AUTOSTART = @AUTOSTART@ USER_SERVICE = YES UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-namestore.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES @UNIXONLY@ PORT = 2099 HOSTNAME = localhost BINARY = gnunet-service-namestore ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; DATABASE = sqlite [namestore-sqlite] FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db [namestore-postgres] CONFIG = connect_timeout=10; dbname=gnunet TEMPORARY_TABLE = NO [uri] gns = gnunet-namestore [fcfsd] # Name of the fcfs registration service binary (for ARM) BINARY = gnunet-namestore-fcfsd AUTOSTART = NO UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-fcfsd.sock # On what port does the FCFS daemon listen for HTTP clients? HTTPPORT = 18080 gnunet-0.10.1/src/namestore/test_namestore_delete.sh0000755000175000017500000000345212261236531017520 00000000000000#!/bin/bash CONFIGURATION="test_namestore_api.conf" trap "gnunet-arm -e -c $CONFIGURATION" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME` TEST_DOMAIN_PLUS="www.gnu" TEST_DOMAIN_DNS="www3.gnu" TEST_IP_PLUS="127.0.0.1" TEST_IP_DNS="131.159.74.67" TEST_RECORD_CNAME_SERVER="server" TEST_RECORD_CNAME_PLUS="server.+" TEST_RECORD_CNAME_DNS="gnunet.org" TEST_RECORD_NAME_SERVER="server" TEST_RECORD_NAME_PLUS="www" TEST_RECORD_NAME_DNS="www3" which timeout &> /dev/null && DO_TIMEOUT="timeout 5" function start_peer { gnunet-arm -s -c $CONFIGURATION gnunet-identity -C testego -c $CONFIGURATION } function stop_peer { gnunet-identity -D testego -c $CONFIGURATION gnunet-arm -e -c $CONFIGURATION } start_peer # Create a public record gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION # Delete record gnunet-namestore -p -z testego -d -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION # List all records OUTPUT=`gnunet-namestore -p -z testego -D` FOUND_IP=false FOUND_NAME=false for LINE in $OUTPUT ; do if echo "$LINE" | grep -q "$TEST_RECORD_NAME_DNS"; then FOUND_NAME=true; fi if echo "$LINE" | grep -q "$TEST_IP_PLUS"; then FOUND_IP=true; fi done stop_peer if [ $FOUND_NAME == false -a $FOUND_IP != false ] then echo "PASS: Delete name in namestore" exit 0 elif [ $FOUND_NAME == true ] then echo "FAIL: Delete name in namestore: name returned" exit 1 elif [ $FOUND_IP == true ] then echo "FAIL: Delete name in namestore: IP returned" exit 1 fi gnunet-0.10.1/src/namestore/test_hostkey0000644000175000017500000000147312164257527015266 00000000000000;(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:\“úXñ¨ï»fzÚ×ÞzPp† êFõàó‚|¹Y÷<-4ÄbcYA¿U—Iß5²=eýš ý’…z¸e;) (5:curve10:NIST P-256) ) ) (11:private-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:\“úXñ¨ï»fzÚ×ÞzPp† êFõàó‚|¹Y÷<-4ÄbcYA¿U—Iß5²=eýš ý’…z¸e;) (1:d33:Iî”KFÜqMéýQÃÿÑ&oûQ Ew£Ã+î) ) ) ) gnunet-0.10.1/src/namestore/test_namestore_api_lookup_private.c0000644000175000017500000001326112251551532021756 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_store.c * @brief testcase for namestore_api.c: store a record */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) static struct GNUNET_NAMESTORE_Handle *nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; //static const char * name = "dummy.dummy.gnunet"; static const char * name = "d"; static char *directory; static void cleanup () { if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } void lookup_it (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { nsqe = NULL; if (0 != memcmp(privkey, zone, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (NULL == label) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (0 != strcmp (label, name)) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } if (1 != rd_count) { GNUNET_break(0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL ); return; } /* Done */ GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_SCHEDULER_add_now (&end, NULL ); } static void put_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; nsqe = NULL; GNUNET_assert (NULL != cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); if (GNUNET_OK != success) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } /* Lookup */ nsqe = GNUNET_NAMESTORE_records_lookup (nsh, privkey, name, lookup_it, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_GNSRECORD_Data rd; char *hostkey_file; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); rd.expiration_time = GNUNET_TIME_absolute_get().abs_value_us; rd.record_type = TEST_RECORD_TYPE; rd.data_size = TEST_RECORD_DATALEN; rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); rd.flags = 0; memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 1, &rd, &put_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } GNUNET_free ((void *)rd.data); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_store.c */ gnunet-0.10.1/src/namestore/test_namestore_lookup.sh0000755000175000017500000000302612261236531017564 00000000000000#!/bin/bash CONFIGURATION="test_namestore_api.conf" trap "gnunet-arm -e -c $CONFIGURATION" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME` TEST_IP_PLUS="127.0.0.1" TEST_RECORD_NAME_DNS="www3" which timeout &> /dev/null && DO_TIMEOUT="timeout 5" function start_peer { gnunet-arm -s -c $CONFIGURATION gnunet-identity -C testego -c $CONFIGURATION } function stop_peer { gnunet-identity -D testego -c $CONFIGURATION gnunet-arm -e -c $CONFIGURATION } start_peer # Create a public record gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION NAMESTORE_RES=$? # Lookup specific name OUTPUT=`gnunet-namestore -p -z testego -n $TEST_RECORD_NAME_DNS -D` FOUND_IP=false FOUND_NAME=false for LINE in $OUTPUT ; do if echo "$LINE" | grep -q "$TEST_RECORD_NAME_DNS"; then FOUND_NAME=true; #echo $FOUND_NAME fi if echo "$LINE" | grep -q "$TEST_IP_PLUS"; then FOUND_IP=true; #echo $FOUND_IP fi done stop_peer if [ $FOUND_NAME == true -a $FOUND_IP == true ] then echo "PASS: Lookup name in namestore" exit 0 elif [ $FOUND_NAME == false ] then echo "FAIL: Lookup name in namestore: name not returned" exit 1 elif [ $FOUND_IP == false ] then echo "FAIL: Lookup name in namestore: IP not returned" exit 1 fi gnunet-0.10.1/src/namestore/gnunet-service-namestore.c0000644000175000017500000013554512300637202017703 00000000000000/* This file is part of GNUnet. (C) 2012, 2013, 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/gnunet-service-namestore.c * @brief namestore for the GNUnet naming system * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_gns_service.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_namestore_plugin.h" #include "gnunet_signatures.h" #include "namestore.h" #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) /** * A namestore client */ struct NamestoreClient; /** * A namestore iteration operation. */ struct ZoneIteration { /** * Next element in the DLL */ struct ZoneIteration *next; /** * Previous element in the DLL */ struct ZoneIteration *prev; /** * Namestore client which intiated this zone iteration */ struct NamestoreClient *client; /** * The nick to add to the records */ struct GNUNET_GNSRECORD_Data *nick; /** * Key of the zone we are iterating over. */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; /** * The operation id fot the zone iteration in the response for the client */ uint32_t request_id; /** * Offset of the zone iteration used to address next result of the zone * iteration in the store * * Initialy set to 0 in handle_iteration_start * Incremented with by every call to handle_iteration_next */ uint32_t offset; }; /** * A namestore client */ struct NamestoreClient { /** * Next element in the DLL */ struct NamestoreClient *next; /** * Previous element in the DLL */ struct NamestoreClient *prev; /** * The client */ struct GNUNET_SERVER_Client *client; /** * Head of the DLL of * Zone iteration operations in progress initiated by this client */ struct ZoneIteration *op_head; /** * Tail of the DLL of * Zone iteration operations in progress initiated by this client */ struct ZoneIteration *op_tail; }; /** * A namestore monitor. */ struct ZoneMonitor { /** * Next element in the DLL */ struct ZoneMonitor *next; /** * Previous element in the DLL */ struct ZoneMonitor *prev; /** * Namestore client which intiated this zone monitor */ struct NamestoreClient *nc; /** * Private key of the zone. */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; /** * Task active during initial iteration. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Offset of the zone iteration used to address next result of the zone * iteration in the store * * Initialy set to 0. * Incremented with by every call to #handle_iteration_next */ uint32_t offset; }; /** * Pending operation on the namecache. */ struct CacheOperation { /** * Kept in a DLL. */ struct CacheOperation *prev; /** * Kept in a DLL. */ struct CacheOperation *next; /** * Handle to namecache queue. */ struct GNUNET_NAMECACHE_QueueEntry *qe; /** * Client to notify about the result. */ struct GNUNET_SERVER_Client *client; /** * Client's request ID. */ uint32_t rid; }; /** * Public key of all zeros. */ static const struct GNUNET_CRYPTO_EcdsaPrivateKey zero; /** * Configuration handle. */ static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg; /** * Namecache handle. */ static struct GNUNET_NAMECACHE_Handle *namecache; /** * Database handle */ static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database; /** * Name of the database plugin */ static char *db_lib_name; /** * Our notification context. */ static struct GNUNET_SERVER_NotificationContext *snc; /** * Head of the Client DLL */ static struct NamestoreClient *client_head; /** * Tail of the Client DLL */ static struct NamestoreClient *client_tail; /** * Head of cop DLL. */ static struct CacheOperation *cop_head; /** * Tail of cop DLL. */ static struct CacheOperation *cop_tail; /** * First active zone monitor. */ static struct ZoneMonitor *monitor_head; /** * Last active zone monitor. */ static struct ZoneMonitor *monitor_tail; /** * Notification context shared by all monitors. */ static struct GNUNET_SERVER_NotificationContext *monitor_nc; /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ZoneIteration *no; struct NamestoreClient *nc; struct CacheOperation *cop; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n"); if (NULL != snc) { GNUNET_SERVER_notification_context_destroy (snc); snc = NULL; } while (NULL != (cop = cop_head)) { GNUNET_NAMECACHE_cancel (cop->qe); GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); GNUNET_free (cop); } GNUNET_NAMECACHE_disconnect (namecache); namecache = NULL; while (NULL != (nc = client_head)) { while (NULL != (no = nc->op_head)) { GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); GNUNET_free (no); } GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); GNUNET_SERVER_client_set_user_context (nc->client, (void *)NULL); GNUNET_free (nc); } GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database)); GNUNET_free (db_lib_name); db_lib_name = NULL; if (NULL != monitor_nc) { GNUNET_SERVER_notification_context_destroy (monitor_nc); monitor_nc = NULL; } } /** * Called whenever a client is disconnected. * Frees our resources associated with that client. * * @param cls closure * @param client identification of the client */ static void client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) { struct ZoneIteration *no; struct NamestoreClient *nc; struct ZoneMonitor *zm; struct CacheOperation *cop; if (NULL == client) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client); if (NULL == (nc = GNUNET_SERVER_client_get_user_context (client, struct NamestoreClient))) return; while (NULL != (no = nc->op_head)) { GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no); GNUNET_free (no); } GNUNET_CONTAINER_DLL_remove (client_head, client_tail, nc); GNUNET_free (nc); for (zm = monitor_head; NULL != zm; zm = zm->next) { if (client == zm->nc->client) { GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm); if (GNUNET_SCHEDULER_NO_TASK != zm->task) { GNUNET_SCHEDULER_cancel (zm->task); zm->task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (zm); break; } } for (cop = cop_head; NULL != cop; cop = cop->next) if (client == cop->client) cop->client = NULL; } /** * Add a client to our list of active clients, if it is not yet * in there. * * @param client client to add * @return internal namestore client structure for this client */ static struct NamestoreClient * client_lookup (struct GNUNET_SERVER_Client *client) { struct NamestoreClient *nc; nc = GNUNET_SERVER_client_get_user_context (client, struct NamestoreClient); if (NULL != nc) return nc; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client); nc = GNUNET_new (struct NamestoreClient); nc->client = client; GNUNET_SERVER_notification_context_add (snc, client); GNUNET_CONTAINER_DLL_insert (client_head, client_tail, nc); GNUNET_SERVER_client_set_user_context (client, nc); return nc; } /** * Function called with the records for the #GNUNET_GNS_MASTERZONE_STR * label in the zone. Used to locate the #GNUNET_GNSRECORD_TYPE_NICK * record, which (if found) is then copied to @a cls for future use. * * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found) * @param private_key the private key of the zone (unused) * @param label should be #GNUNET_GNS_MASTERZONE_STR * @param rd_count number of records in @a rd * @param rd records stored under @a label in the zone */ static void lookup_nick_it (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_GNSRECORD_Data **res = cls; int c; if (0 != strcmp (label, GNUNET_GNS_MASTERZONE_STR)) { GNUNET_break (0); return; } for (c = 0; c < rd_count; c++) { if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type) { (*res) = GNUNET_malloc (rd[c].data_size + sizeof (struct GNUNET_GNSRECORD_Data)); (*res)->data = &(*res)[1]; memcpy ((char *)(*res)->data, rd[c].data, rd[c].data_size); (*res)->data_size = rd[c].data_size; (*res)->expiration_time = rd[c].expiration_time; (*res)->flags = rd[c].flags; (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK; return; } } (*res) = NULL; } /** * Return the NICK record for the zone (if it exists). * * @param zone private key for the zone to look for nick * @return NULL if no NICK record was found */ static struct GNUNET_GNSRECORD_Data * get_nick_record (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone) { struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_GNSRECORD_Data *nick; int res; res = GSN_database->lookup_records (GSN_database->cls, zone, GNUNET_GNS_MASTERZONE_STR, &lookup_nick_it, &nick); if ((NULL == nick) || (GNUNET_OK != res)) { GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub); GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, "No nick name set for zone `%s'\n", GNUNET_GNSRECORD_z2s (&pub)); return NULL; } return nick; } static void merge_with_nick_records ( const struct GNUNET_GNSRECORD_Data *nick_rd, unsigned int rdc2, const struct GNUNET_GNSRECORD_Data *rd2, unsigned int *rdc_res, struct GNUNET_GNSRECORD_Data **rd_res) { uint64_t latest_expiration; int c; size_t req; char *data; int record_offset; size_t data_offset; (*rdc_res) = 1 + rdc2; if (0 == 1 + rdc2) { (*rd_res) = NULL; return; } req = 0; for (c=0; c< 1; c++) req += sizeof (struct GNUNET_GNSRECORD_Data) + nick_rd[c].data_size; for (c=0; c< rdc2; c++) req += sizeof (struct GNUNET_GNSRECORD_Data) + rd2[c].data_size; (*rd_res) = GNUNET_malloc (req); data = (char *) &(*rd_res)[1 + rdc2]; data_offset = 0; latest_expiration = 0; for (c=0; c< rdc2; c++) { if (0 != (rd2[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) { if ((GNUNET_TIME_absolute_get().abs_value_us + rd2[c].expiration_time) > latest_expiration) latest_expiration = rd2[c].expiration_time; } else if (rd2[c].expiration_time > latest_expiration) latest_expiration = rd2[c].expiration_time; (*rd_res)[c] = rd2[c]; (*rd_res)[c].data = (void *) &data[data_offset]; // WTF? memcpy ((void *) (*rd_res)[c].data, rd2[c].data, rd2[c].data_size); data_offset += (*rd_res)[c].data_size; } record_offset = rdc2; for (c=0; c< 1; c++) { (*rd_res)[c+record_offset] = nick_rd[c]; (*rd_res)[c+record_offset].expiration_time = latest_expiration; (*rd_res)[c+record_offset].data = (void *) &data[data_offset]; // WTF? memcpy ((void *) (*rd_res)[c+record_offset].data, nick_rd[c].data, nick_rd[c].data_size); data_offset += (*rd_res)[c+record_offset].data_size; } GNUNET_assert (req == (sizeof (struct GNUNET_GNSRECORD_Data)) * (*rdc_res) + data_offset); } /** * Generate a `struct LookupNameResponseMessage` and send it to the * given client using the given notification context. * * @param nc notification context to use * @param client client to unicast to * @param request_id request ID to use * @param zone_key zone key of the zone * @param name name * @param rd_count number of records in @a rd * @param rd array of records */ static void send_lookup_response (struct GNUNET_SERVER_NotificationContext *nc, struct GNUNET_SERVER_Client *client, uint32_t request_id, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct RecordResultMessage *zir_msg; struct GNUNET_GNSRECORD_Data *nick; struct GNUNET_GNSRECORD_Data *res; unsigned int res_count; size_t name_len; size_t rd_ser_len; size_t msg_size; char *name_tmp; char *rd_ser; nick = get_nick_record (zone_key); if ((NULL != nick) && (0 != strcmp(name, GNUNET_GNS_MASTERZONE_STR))) { nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; merge_with_nick_records (nick, rd_count, rd, &res_count, &res); //fprintf (stderr, "Merging %u records for `%s' with NICK records\n",rd_count, name); GNUNET_free (nick); } else { res_count = rd_count; res = (struct GNUNET_GNSRECORD_Data *) rd; //fprintf (stderr, "Not merging %u records for `%s' with NICK records\n",rd_count, name); } name_len = strlen (name) + 1; rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res); msg_size = sizeof (struct RecordResultMessage) + name_len + rd_ser_len; (void) client_lookup (client); zir_msg = GNUNET_malloc (msg_size); zir_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT); zir_msg->gns_header.header.size = htons (msg_size); zir_msg->gns_header.r_id = htonl (request_id); zir_msg->name_len = htons (name_len); zir_msg->rd_count = htons (res_count); zir_msg->rd_len = htons (rd_ser_len); zir_msg->private_key = *zone_key; name_tmp = (char *) &zir_msg[1]; memcpy (name_tmp, name, name_len); rd_ser = &name_tmp[name_len]; GNUNET_GNSRECORD_records_serialize (res_count, res, rd_ser_len, rd_ser); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %u records and size %u\n", "RECORD_RESULT", res_count, msg_size); GNUNET_SERVER_notification_context_unicast (nc, client, &zir_msg->gns_header.header, GNUNET_NO); if (rd != res) GNUNET_free (res); GNUNET_free (zir_msg); } /** * Send response to the store request to the client. * * @param client client to talk to * @param res status of the operation * @param rid client's request ID */ static void send_store_response (struct GNUNET_SERVER_Client *client, int res, uint32_t rid) { struct RecordStoreResponseMessage rcr_msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "RECORD_STORE_RESPONSE"); rcr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE); rcr_msg.gns_header.header.size = htons (sizeof (struct RecordStoreResponseMessage)); rcr_msg.gns_header.r_id = htonl (rid); rcr_msg.op_result = htonl (res); GNUNET_SERVER_notification_context_unicast (snc, client, &rcr_msg.gns_header.header, GNUNET_NO); } /** * Cache operation complete, clean up. * * @param cls the `struct CacheOperation` * @param success success * @param emsg error messages */ static void finish_cache_operation (void *cls, int32_t success, const char *emsg) { struct CacheOperation *cop = cls; if (NULL != emsg) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to replicate block in namecache: %s\n"), emsg); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n"); GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop); if (NULL != cop->client) send_store_response (cop->client, success, cop->rid); GNUNET_free (cop); } /** * We just touched the plaintext information about a name in our zone; * refresh the corresponding (encrypted) block in the namecache. * * @param client client responsible for the request * @param rid request ID of the client * @param zone_key private key of the zone * @param name label for the records * @param rd_count number of records * @param rd records stored under the given @a name */ static void refresh_block (struct GNUNET_SERVER_Client *client, uint32_t rid, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_GNSRECORD_Block *block; struct CacheOperation *cop; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; struct GNUNET_GNSRECORD_Data *nick; struct GNUNET_GNSRECORD_Data *res; unsigned int res_count; nick = get_nick_record (zone_key); res_count = rd_count; res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */ if (NULL != nick) { nick->flags = (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; merge_with_nick_records (nick, rd_count,rd, &res_count, &res); GNUNET_free (nick); } if (0 == res_count) block = GNUNET_GNSRECORD_block_create (zone_key, GNUNET_TIME_UNIT_ZERO_ABS, name, res, rd_count); else block = GNUNET_GNSRECORD_block_create (zone_key, GNUNET_GNSRECORD_record_get_expiration_time (res_count, res), name, res, res_count); GNUNET_assert (NULL != block); GNUNET_CRYPTO_ecdsa_key_get_public (zone_key, &pkey); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Caching block for label `%s' with %u records in zone `%s' in namecache\n", name, res_count, GNUNET_GNSRECORD_z2s (&pkey)); cop = GNUNET_new (struct CacheOperation); cop->client = client; cop->rid = rid; GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop); cop->qe = GNUNET_NAMECACHE_block_cache (namecache, block, &finish_cache_operation, cop); GNUNET_free (block); } /** * Closure for #lookup_it(). */ struct RecordLookupContext { const char *label; int found; unsigned int res_rd_count; size_t rd_ser_len; char *res_rd; struct GNUNET_GNSRECORD_Data *nick; }; static void lookup_it (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct RecordLookupContext *rlc = cls; struct GNUNET_GNSRECORD_Data *rd_res; unsigned int rdc_res; if (0 == strcmp (label, rlc->label)) { rlc->found = GNUNET_YES; if (0 != rd_count) { if ((NULL != rlc->nick) && (0 != strcmp(label, GNUNET_GNS_MASTERZONE_STR))) { /* Merge */ rd_res = NULL; rdc_res = 0; rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE; merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res); rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res); rlc->res_rd_count = rdc_res; rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); GNUNET_GNSRECORD_records_serialize (rdc_res, rd_res, rlc->rd_ser_len , rlc->res_rd); GNUNET_free (rd_res); GNUNET_free (rlc->nick); rlc->nick = NULL; } else { rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); rlc->res_rd_count = rd_count; rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len); GNUNET_GNSRECORD_records_serialize (rd_count, rd, rlc->rd_ser_len , rlc->res_rd); } } else { rlc->rd_ser_len = 0; rlc->res_rd_count = 0; rlc->res_rd = NULL; } } } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message * * @param cls unused * @param client client sending the message * @param message message of type 'struct RecordCreateMessage' */ static void handle_record_lookup (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct LabelLookupMessage *ll_msg; struct LabelLookupResponseMessage *llr_msg; struct RecordLookupContext rlc; const char *name_tmp; char *res_name; uint32_t name_len; size_t src_size; size_t res_size; int res; if (ntohs (message->size) < sizeof (struct LabelLookupMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } ll_msg = (const struct LabelLookupMessage *) message; name_len = ntohl (ll_msg->label_len); src_size = ntohs (message->size); if (name_len != src_size - sizeof (struct LabelLookupMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } name_tmp = (const char *) &ll_msg[1]; if ('\0' != name_tmp[name_len -1]) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message for name `%s'\n", "NAMESTORE_RECORD_LOOKUP", name_tmp); if (NULL == (client_lookup (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } rlc.label = name_tmp; rlc.found = GNUNET_NO; rlc.res_rd_count = 0; rlc.res_rd = NULL; rlc.rd_ser_len = 0; rlc.nick = get_nick_record (&ll_msg->zone); res = GSN_database->lookup_records (GSN_database->cls, &ll_msg->zone, name_tmp, &lookup_it, &rlc); res_size = sizeof (struct LabelLookupResponseMessage) + name_len + rlc.rd_ser_len; llr_msg = GNUNET_malloc (res_size); llr_msg->gns_header.header.size = htons (res_size); llr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE); llr_msg->gns_header.r_id = ll_msg->gns_header.r_id; llr_msg->private_key = ll_msg->zone; llr_msg->name_len = htons (name_len); llr_msg->rd_count = htons (rlc.res_rd_count); llr_msg->rd_len = htons (rlc.rd_ser_len); res_name = (char *) &llr_msg[1]; if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res)) llr_msg->found = ntohs (GNUNET_YES); else llr_msg->found = ntohs (GNUNET_NO); memcpy (&llr_msg[1], name_tmp, name_len); memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len); GNUNET_SERVER_notification_context_unicast (snc, client, &llr_msg->gns_header.header, GNUNET_NO); GNUNET_free_non_null (rlc.res_rd); GNUNET_free (llr_msg); } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message * * @param cls unused * @param client client sending the message * @param message message of type 'struct RecordCreateMessage' */ static void handle_record_store (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct RecordStoreMessage *rp_msg; size_t name_len; size_t msg_size; size_t msg_size_exp; size_t rd_ser_len; uint32_t rid; const char *name_tmp; char *conv_name; const char *rd_ser; unsigned int rd_count; int res; struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; struct ZoneMonitor *zm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "NAMESTORE_RECORD_STORE"); if (ntohs (message->size) < sizeof (struct RecordStoreMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } rp_msg = (const struct RecordStoreMessage *) message; rid = ntohl (rp_msg->gns_header.r_id); name_len = ntohs (rp_msg->name_len); msg_size = ntohs (message->size); rd_count = ntohs (rp_msg->rd_count); rd_ser_len = ntohs (rp_msg->rd_len); GNUNET_break (0 == ntohs (rp_msg->reserved)); msg_size_exp = sizeof (struct RecordStoreMessage) + name_len + rd_ser_len; if (msg_size != msg_size_exp) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if ((0 == name_len) || (name_len > MAX_NAME_LEN)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } name_tmp = (const char *) &rp_msg[1]; rd_ser = &name_tmp[name_len]; if ('\0' != name_tmp[name_len -1]) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } (void) client_lookup (client); { struct GNUNET_GNSRECORD_Data rd[rd_count]; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* Extracting and converting private key */ GNUNET_CRYPTO_ecdsa_key_get_public (&rp_msg->private_key, &pubkey); conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp); if (NULL == conv_name) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error converting name `%s'\n", name_tmp); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating %u records for name `%s' in zone `%s'\n", (unsigned int) rd_count, conv_name, GNUNET_GNSRECORD_z2s (&pubkey)); if ( (0 == rd_count) && (GNUNET_NO == GSN_database->iterate_records (GSN_database->cls, &rp_msg->private_key, 0, NULL, 0)) ) { /* This name does not exist, so cannot be removed */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name `%s' does not exist, no deletion required\n", conv_name); res = GNUNET_NO; } else { struct GNUNET_GNSRECORD_Data rd_clean[rd_count]; unsigned int i; unsigned int rd_clean_off; /* remove "NICK" records, unless this is for the "+" label */ rd_clean_off = 0; for (i=0;istore_records (GSN_database->cls, &rp_msg->private_key, conv_name, rd_clean_off, rd_clean); if (GNUNET_OK == res) { for (zm = monitor_head; NULL != zm; zm = zm->next) { if ( (0 == memcmp (&rp_msg->private_key, &zm->zone, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) || (0 == memcmp (&zm->zone, &zero, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying monitor about changes under label `%s'\n", conv_name); send_lookup_response (monitor_nc, zm->nc->client, 0, &rp_msg->private_key, conv_name, rd_count, rd); } else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor is for another zone\n"); } if (NULL == monitor_head) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No monitors active\n"); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error storing record: %d\n", res); } } if (GNUNET_OK == res) { refresh_block (client, rid, &rp_msg->private_key, conv_name, rd_count, rd); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_free (conv_name); return; } GNUNET_free (conv_name); } send_store_response (client, res, rid); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Context for record remove operations passed from #handle_zone_to_name to * #handle_zone_to_name_it as closure */ struct ZoneToNameCtx { /** * Namestore client */ struct NamestoreClient *nc; /** * Request id (to be used in the response to the client). */ uint32_t rid; /** * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that * not finding a name for the zone still counts as a 'success' here, * as this field is about the success of executing the IPC protocol. */ int success; }; /** * Zone to name iterator * * @param cls struct ZoneToNameCtx * * @param zone_key the zone key * @param name name * @param rd_count number of records in @a rd * @param rd record data */ static void handle_zone_to_name_it (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct ZoneToNameCtx *ztn_ctx = cls; struct ZoneToNameResponseMessage *ztnr_msg; int16_t res; size_t name_len; size_t rd_ser_len; size_t msg_size; char *name_tmp; char *rd_tmp; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found result for zone-to-name lookup: `%s'\n", name); res = GNUNET_YES; name_len = (NULL == name) ? 0 : strlen (name) + 1; rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); msg_size = sizeof (struct ZoneToNameResponseMessage) + name_len + rd_ser_len; if (msg_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); ztn_ctx->success = GNUNET_SYSERR; return; } ztnr_msg = GNUNET_malloc (msg_size); ztnr_msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE); ztnr_msg->gns_header.header.size = htons (msg_size); ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid); ztnr_msg->res = htons (res); ztnr_msg->rd_len = htons (rd_ser_len); ztnr_msg->rd_count = htons (rd_count); ztnr_msg->name_len = htons (name_len); ztnr_msg->zone = *zone_key; name_tmp = (char *) &ztnr_msg[1]; if (NULL != name) memcpy (name_tmp, name, name_len); rd_tmp = &name_tmp[name_len]; GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp); ztn_ctx->success = GNUNET_OK; GNUNET_SERVER_notification_context_unicast (snc, ztn_ctx->nc->client, &ztnr_msg->gns_header.header, GNUNET_NO); GNUNET_free (ztnr_msg); } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message * * @param cls unused * @param client client sending the message * @param message message of type 'struct ZoneToNameMessage' */ static void handle_zone_to_name (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct NamestoreClient *nc; const struct ZoneToNameMessage *ztn_msg; struct ZoneToNameCtx ztn_ctx; struct ZoneToNameResponseMessage ztnr_msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_TO_NAME"); ztn_msg = (const struct ZoneToNameMessage *) message; nc = client_lookup (client); ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id); ztn_ctx.nc = nc; ztn_ctx.success = GNUNET_NO; if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls, &ztn_msg->zone, &ztn_msg->value_zone, &handle_zone_to_name_it, &ztn_ctx)) { /* internal error, hang up instead of signalling something that might be wrong */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (GNUNET_NO == ztn_ctx.success) { /* no result found, send empty response */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found no result for zone-to-name lookup.\n"); memset (&ztnr_msg, 0, sizeof (ztnr_msg)); ztnr_msg.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE); ztnr_msg.gns_header.header.size = htons (sizeof (ztnr_msg)); ztnr_msg.gns_header.r_id = ztn_msg->gns_header.r_id; ztnr_msg.res = htons (GNUNET_NO); GNUNET_SERVER_notification_context_unicast (snc, client, &ztnr_msg.gns_header.header, GNUNET_NO); } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Zone iteration processor result */ enum ZoneIterationResult { /** * Iteration start. */ IT_START = 0, /** * Found records, * Continue to iterate with next iteration_next call */ IT_SUCCESS_MORE_AVAILABLE = 1, /** * Iteration complete */ IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE = 2 }; /** * Context for record remove operations passed from * #run_zone_iteration_round to #zone_iterate_proc as closure */ struct ZoneIterationProcResult { /** * The zone iteration handle */ struct ZoneIteration *zi; /** * Iteration result: iteration done? * #IT_SUCCESS_MORE_AVAILABLE: if there may be more results overall but * we got one for now and have sent it to the client * #IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE: if there are no further results, * #IT_START: if we are still trying to find a result. */ int res_iteration_finished; }; /** * Process results for zone iteration from database * * @param cls struct ZoneIterationProcResult *proc * @param zone_key the zone key * @param name name * @param rd_count number of records for this name * @param rd record data */ static void zone_iterate_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct ZoneIterationProcResult *proc = cls; unsigned int i; int do_refresh_block; if ((NULL == zone_key) && (NULL == name)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n"); proc->res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE; return; } if ((NULL == zone_key) || (NULL == name)) { /* what is this!? should never happen */ proc->res_iteration_finished = IT_START; GNUNET_break (0); return; } proc->res_iteration_finished = IT_SUCCESS_MORE_AVAILABLE; send_lookup_response (snc, proc->zi->client->client, proc->zi->request_id, zone_key, name, rd_count, rd); do_refresh_block = GNUNET_NO; for (i=0;iiterate_records (GSN_database->cls, (0 == memcmp (&zi->zone, &zero, sizeof (zero))) ? NULL : &zi->zone, zi->offset, &zone_iterate_proc, &proc))) { GNUNET_break (0); break; } if (GNUNET_NO == ret) proc.res_iteration_finished = IT_SUCCESS_NOT_MORE_RESULTS_AVAILABLE; zi->offset++; } if (IT_SUCCESS_MORE_AVAILABLE == proc.res_iteration_finished) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "More results available\n"); return; /* more results later */ } /* send empty response to indicate end of list */ memset (&rrm, 0, sizeof (rrm)); rrm.gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT); rrm.gns_header.header.size = htons (sizeof (rrm)); rrm.gns_header.r_id = htonl (zi->request_id); GNUNET_SERVER_notification_context_unicast (snc, zi->client->client, &rrm.gns_header.header, GNUNET_NO); GNUNET_CONTAINER_DLL_remove (zi->client->op_head, zi->client->op_tail, zi); GNUNET_free (zi); } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message * * @param cls unused * @param client the client sending the message * @param message message of type 'struct ZoneIterationStartMessage' */ static void handle_iteration_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ZoneIterationStartMessage *zis_msg; struct NamestoreClient *nc; struct ZoneIteration *zi; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_START"); if (NULL == (nc = client_lookup (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } zis_msg = (const struct ZoneIterationStartMessage *) message; zi = GNUNET_new (struct ZoneIteration); zi->request_id = ntohl (zis_msg->gns_header.r_id); zi->offset = 0; zi->client = nc; zi->zone = zis_msg->zone; GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi); run_zone_iteration_round (zi); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message * * @param cls unused * @param client GNUNET_SERVER_Client sending the message * @param message message of type 'struct ZoneIterationStopMessage' */ static void handle_iteration_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct NamestoreClient *nc; struct ZoneIteration *zi; const struct ZoneIterationStopMessage *zis_msg; uint32_t rid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_STOP"); if (NULL == (nc = client_lookup(client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } zis_msg = (const struct ZoneIterationStopMessage *) message; rid = ntohl (zis_msg->gns_header.r_id); for (zi = nc->op_head; NULL != zi; zi = zi->next) if (zi->request_id == rid) break; if (NULL == zi) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi); GNUNET_free (zi); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message * * @param cls unused * @param client GNUNET_SERVER_Client sending the message * @param message message of type 'struct ZoneIterationNextMessage' */ static void handle_iteration_next (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct NamestoreClient *nc; struct ZoneIteration *zi; const struct ZoneIterationNextMessage *zis_msg; uint32_t rid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_ITERATION_NEXT"); if (NULL == (nc = client_lookup(client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } zis_msg = (const struct ZoneIterationNextMessage *) message; rid = ntohl (zis_msg->gns_header.r_id); for (zi = nc->op_head; NULL != zi; zi = zi->next) if (zi->request_id == rid) break; if (NULL == zi) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } run_zone_iteration_round (zi); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Send 'sync' message to zone monitor, we're now in sync. * * @param zm monitor that is now in sync */ static void monitor_sync (struct ZoneMonitor *zm) { struct GNUNET_MessageHeader sync; sync.size = htons (sizeof (struct GNUNET_MessageHeader)); sync.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC); GNUNET_SERVER_notification_context_unicast (monitor_nc, zm->nc->client, &sync, GNUNET_NO); } /** * Obtain the next datum during the zone monitor's zone intiial iteration. * * @param cls zone monitor that does its initial iteration * @param tc scheduler context */ static void monitor_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * A #GNUNET_NAMESTORE_RecordIterator for monitors. * * @param cls a 'struct ZoneMonitor *' with information about the monitor * @param zone_key zone key of the zone * @param name name * @param rd_count number of records in @a rd * @param rd array of records */ static void monitor_iterate_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct ZoneMonitor *zm = cls; if (NULL == name) { /* finished with iteration */ monitor_sync (zm); return; } send_lookup_response (monitor_nc, zm->nc->client, 0, zone_key, name, rd_count, rd); zm->task = GNUNET_SCHEDULER_add_now (&monitor_next, zm); } /** * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message * * @param cls unused * @param client the client sending the message * @param message message of type 'struct ZoneMonitorStartMessage' */ static void handle_monitor_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ZoneMonitorStartMessage *zis_msg; struct ZoneMonitor *zm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ZONE_MONITOR_START"); zis_msg = (const struct ZoneMonitorStartMessage *) message; zm = GNUNET_new (struct ZoneMonitor); zm->offset = 0; zm->nc = client_lookup (client); zm->zone = zis_msg->zone; GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm); GNUNET_SERVER_client_mark_monitor (client); GNUNET_SERVER_disable_receive_done_warning (client); GNUNET_SERVER_notification_context_add (monitor_nc, client); if (GNUNET_YES == ntohl (zis_msg->iterate_first)) zm->task = GNUNET_SCHEDULER_add_now (&monitor_next, zm); else monitor_sync (zm); } /** * Obtain the next datum during the zone monitor's zone intiial iteration. * * @param cls zone monitor that does its initial iteration * @param tc scheduler context */ static void monitor_next (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ZoneMonitor *zm = cls; int ret; zm->task = GNUNET_SCHEDULER_NO_TASK; ret = GSN_database->iterate_records (GSN_database->cls, (0 == memcmp (&zm->zone, &zero, sizeof (zero))) ? NULL : &zm->zone, zm->offset++, &monitor_iterate_cb, zm); if (GNUNET_SYSERR == ret) { GNUNET_SERVER_client_disconnect (zm->nc->client); return; } if (GNUNET_NO == ret) { /* empty zone */ monitor_sync (zm); return; } } /** * Process namestore requests. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_record_store, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE, 0}, {&handle_record_lookup, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP, 0}, {&handle_zone_to_name, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME, sizeof (struct ZoneToNameMessage) }, {&handle_iteration_start, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START, sizeof (struct ZoneIterationStartMessage) }, {&handle_iteration_next, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT, sizeof (struct ZoneIterationNextMessage) }, {&handle_iteration_stop, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP, sizeof (struct ZoneIterationStopMessage) }, {&handle_monitor_start, NULL, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START, sizeof (struct ZoneMonitorStartMessage) }, {NULL, NULL, 0, 0} }; char *database; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n"); GSN_cfg = cfg; monitor_nc = GNUNET_SERVER_notification_context_create (server, 1); namecache = GNUNET_NAMECACHE_connect (cfg); /* Loading database plugin */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "namestore", "database", &database)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n"); GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database); GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg); GNUNET_free (database); if (NULL == GSN_database) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load database backend `%s'\n", db_lib_name); GNUNET_SCHEDULER_add_now (&cleanup_task, NULL); return; } /* Configuring server handles */ GNUNET_SERVER_add_handlers (server, handlers); snc = GNUNET_SERVER_notification_context_create (server, 16); GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, NULL); } /** * The main function for the template service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "namestore", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-namestore.c */ gnunet-0.10.1/src/namestore/test_namestore_api_lookup_public.c0000644000175000017500000001471112251551532021563 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api.c * @brief testcase for namestore_api.c: store a record and perform a lookup */ #include "platform.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle *nsh; static struct GNUNET_NAMECACHE_Handle *nch; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; static struct GNUNET_NAMECACHE_QueueEntry *ncqe; static char *directory; static void cleanup () { if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != nch) { GNUNET_NAMECACHE_disconnect (nch); nch = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } if (NULL != ncqe) { GNUNET_NAMECACHE_cancel (ncqe); ncqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } static void rd_decrypt_cb (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { char rd_cmp_data[TEST_RECORD_DATALEN]; GNUNET_assert (1 == rd_count); GNUNET_assert (NULL != rd); memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN); GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type); GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size); GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Block was decrypted successfully \n"); GNUNET_SCHEDULER_add_now (&end, NULL); } static void name_lookup_proc (void *cls, const struct GNUNET_GNSRECORD_Block *block) { const char *name = cls; ncqe = NULL; GNUNET_assert (NULL != cls); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL == block) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore returned no block\n")); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned block, decrypting \n"); GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt(block, &pubkey, name, &rd_decrypt_cb, (void *) name)); } static void put_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; struct GNUNET_HashCode derived_hash; struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; nsqe = NULL; GNUNET_assert (NULL != cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); /* Create derived hash */ GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); GNUNET_GNSRECORD_query_from_public_key (&pubkey, name, &derived_hash); ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash, &name_lookup_proc, (void *) name); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_GNSRECORD_Data rd; char *hostkey_file; const char * name = "dummy.dummy.gnunet"; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); rd.expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 1000000000; rd.record_type = TEST_RECORD_TYPE; rd.data_size = TEST_RECORD_DATALEN; rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); rd.flags = 0; memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); nsh = GNUNET_NAMESTORE_connect (cfg); nch = GNUNET_NAMECACHE_connect (cfg); GNUNET_break (NULL != nsh); GNUNET_break (NULL != nch); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 1, &rd, &put_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } GNUNET_free ((void *)rd.data); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_lookup_public.c */ gnunet-0.10.1/src/namestore/Makefile.am0000644000175000017500000002670312320751517014645 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ namestore.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIBS = -lgcov endif if HAVE_SQLITE SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la if HAVE_TESTING SQLITE_TESTS = test_plugin_namestore_sqlite endif endif if HAVE_POSTGRES # postgres doesn't even build yet; thus: experimental! POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la if HAVE_TESTING POSTGRES_TESTS = test_plugin_namestore_postgres endif endif # testcases do not even build yet; thus: experimental! if HAVE_TESTING TESTING_TESTS = \ test_namestore_api_store \ test_namestore_api_store_update \ test_namestore_api_lookup_public \ test_namestore_api_lookup_private \ test_namestore_api_lookup_nick \ test_namestore_api_lookup_shadow \ test_namestore_api_lookup_shadow_filter \ test_namestore_api_remove \ test_namestore_api_remove_not_existing_record \ test_namestore_api_zone_iteration \ test_namestore_api_zone_iteration_nick \ test_namestore_api_zone_iteration_specific_zone \ test_namestore_api_zone_iteration_stop \ test_namestore_api_monitoring \ test_namestore_api_monitoring_existing # test_namestore_api_zone_to_name endif if HAVE_SQLITE check_PROGRAMS = \ $(SQLITE_TESTS) \ $(POSTGRES_TESTS) \ $(TESTING_TESTS) endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ $(check_PROGRAMS) \ $(check_SCRIPTS) endif lib_LTLIBRARIES = \ libgnunetnamestore.la libgnunetnamestore_la_SOURCES = \ namestore_api.c \ namestore_api_monitor.c \ namestore.h libgnunetnamestore_la_LIBADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetnamestore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:1:0 libexec_PROGRAMS = \ gnunet-service-namestore bin_PROGRAMS = \ gnunet-namestore if HAVE_MHD libexec_PROGRAMS += \ gnunet-namestore-fcfsd endif gnunet_namestore_SOURCES = \ gnunet-namestore.c gnunet_namestore_LDADD = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la \ $(GN_LIBINTL) gnunet_namestore_DEPENDENCIES = \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la gnunet_namestore_fcfsd_SOURCES = \ gnunet-namestore-fcfsd.c gnunet_namestore_fcfsd_LDADD = -lmicrohttpd \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_namestore_fcfsd_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la gnunet_service_namestore_SOURCES = \ gnunet-service-namestore.c gnunet_service_namestore_LDADD = \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la \ $(GN_LIBINTL) gnunet_service_namestore_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ $(POSTGRES_PLUGIN) libgnunet_plugin_namestore_sqlite_la_SOURCES = \ plugin_namestore_sqlite.c libgnunet_plugin_namestore_sqlite_la_LIBADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_namestore_sqlite_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la libgnunet_plugin_namestore_postgres_la_SOURCES = \ plugin_namestore_postgres.c libgnunet_plugin_namestore_postgres_la_LIBADD = \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \ $(LTLIBINTL) libgnunet_plugin_namestore_postgres_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_namestore_postgres_la_DEPENDENCIES = \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ libgnunetnamestore.la test_namestore_api_store_SOURCES = \ test_namestore_api_store.c test_namestore_api_store_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_store_update_SOURCES = \ test_namestore_api_store_update.c test_namestore_api_store_update_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_public_SOURCES = \ test_namestore_api_lookup_public.c test_namestore_api_lookup_public_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_nick_SOURCES = \ test_namestore_api_lookup_nick.c test_namestore_api_lookup_nick_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_private_SOURCES = \ test_namestore_api_lookup_private.c test_namestore_api_lookup_private_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_shadow_SOURCES = \ test_namestore_api_lookup_shadow.c test_namestore_api_lookup_shadow_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_lookup_shadow_filter_SOURCES = \ test_namestore_api_lookup_shadow_filter.c test_namestore_api_lookup_shadow_filter_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namecache/libgnunetnamecache.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_remove_SOURCES = \ test_namestore_api_remove.c test_namestore_api_remove_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_remove_not_existing_record_SOURCES = \ test_namestore_api_remove_not_existing_record.c test_namestore_api_remove_not_existing_record_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la #test_namestore_api_zone_to_name_SOURCES = \ # test_namestore_api_zone_to_name.c #test_namestore_api_zone_to_name_LDADD = \ # $(top_builddir)/src/testing/libgnunettesting.la \ # $(top_builddir)/src/util/libgnunetutil.la \ # $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_monitoring_SOURCES = \ test_namestore_api_monitoring.c test_namestore_api_monitoring_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_namestore_api_monitoring_existing_SOURCES = \ test_namestore_api_monitoring_existing.c test_namestore_api_monitoring_existing_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_namestore_api_zone_iteration_SOURCES = \ test_namestore_api_zone_iteration.c test_namestore_api_zone_iteration_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_iteration_nick_SOURCES = \ test_namestore_api_zone_iteration_nick.c test_namestore_api_zone_iteration_nick_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_iteration_specific_zone_SOURCES = \ test_namestore_api_zone_iteration_specific_zone.c test_namestore_api_zone_iteration_specific_zone_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_namestore_api_zone_iteration_stop_SOURCES = \ test_namestore_api_zone_iteration_stop.c test_namestore_api_zone_iteration_stop_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/namestore/libgnunetnamestore.la test_plugin_namestore_sqlite_SOURCES = \ test_plugin_namestore.c test_plugin_namestore_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_namestore_postgres_SOURCES = \ test_plugin_namestore.c test_plugin_namestore_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la check_SCRIPTS = \ test_namestore_put.sh \ test_namestore_lookup.sh \ test_namestore_delete.sh EXTRA_DIST = \ test_namestore_api.conf \ test_plugin_namestore_sqlite.conf \ test_plugin_namestore_postgres.conf \ test_hostkey \ zonefiles/S5I9DSGQVAB5FVV16T3B3CC5H1B2JGL3Q412JBKURME8EKU0600G.zkey \ zonefiles/AQ835GVL939H4O8QJQ7GBLPTQC0QAAO91BN7QK01BA63MDSK6I4G.zkey \ zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey \ zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey \ $(check_SCRIPTS) gnunet-0.10.1/src/namestore/namestore_api.c0000644000175000017500000010615012254054615015577 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/namestore_api.c * @brief API to access the NAMESTORE service * @author Martin Schanzenbach * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_crypto_lib.h" #include "gnunet_constants.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_arm_service.h" #include "gnunet_signatures.h" #include "gnunet_gns_service.h" #include "gnunet_namestore_service.h" #include "namestore.h" #define LOG(kind,...) GNUNET_log_from (kind, "namestore-api",__VA_ARGS__) /** * An QueueEntry used to store information for a pending * NAMESTORE record operation */ struct GNUNET_NAMESTORE_QueueEntry { /** * Kept in a DLL. */ struct GNUNET_NAMESTORE_QueueEntry *next; /** * Kept in a DLL. */ struct GNUNET_NAMESTORE_QueueEntry *prev; /** * Main handle to access the namestore. */ struct GNUNET_NAMESTORE_Handle *nsh; /** * Continuation to call */ GNUNET_NAMESTORE_ContinuationWithStatus cont; /** * Closure for 'cont'. */ void *cont_cls; /** * Function to call with the records we get back; or NULL. */ GNUNET_NAMESTORE_RecordMonitor proc; /** * Closure for @e proc. */ void *proc_cls; /** * The operation id this zone iteration operation has */ uint32_t op_id; }; /** * Handle for a zone iterator operation */ struct GNUNET_NAMESTORE_ZoneIterator { /** * Kept in a DLL. */ struct GNUNET_NAMESTORE_ZoneIterator *next; /** * Kept in a DLL. */ struct GNUNET_NAMESTORE_ZoneIterator *prev; /** * Main handle to access the namestore. */ struct GNUNET_NAMESTORE_Handle *h; /** * The continuation to call with the results */ GNUNET_NAMESTORE_RecordMonitor proc; /** * Closure for @e proc. */ void* proc_cls; /** * Private key of the zone. */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; /** * The operation id this zone iteration operation has */ uint32_t op_id; }; /** * Message in linked list we should send to the service. The * actual binary message follows this struct. */ struct PendingMessage { /** * Kept in a DLL. */ struct PendingMessage *next; /** * Kept in a DLL. */ struct PendingMessage *prev; /** * Size of the message. */ size_t size; }; /** * Connection to the NAMESTORE service. */ struct GNUNET_NAMESTORE_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Currently pending transmission request (or NULL). */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of linked list of pending messages to send to the service */ struct PendingMessage *pending_head; /** * Tail of linked list of pending messages to send to the service */ struct PendingMessage *pending_tail; /** * Head of pending namestore queue entries */ struct GNUNET_NAMESTORE_QueueEntry *op_head; /** * Tail of pending namestore queue entries */ struct GNUNET_NAMESTORE_QueueEntry *op_tail; /** * Head of pending namestore zone iterator entries */ struct GNUNET_NAMESTORE_ZoneIterator *z_head; /** * Tail of pending namestore zone iterator entries */ struct GNUNET_NAMESTORE_ZoneIterator *z_tail; /** * Reconnect task */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Delay introduced before we reconnect. */ struct GNUNET_TIME_Relative reconnect_delay; /** * Should we reconnect to service due to some serious error? */ int reconnect; /** * Did we start to receive yet? */ int is_receiving; /** * The last operation id used for a NAMESTORE operation */ uint32_t last_op_id_used; }; /** * Disconnect from service and then reconnect. * * @param h our handle */ static void force_reconnect (struct GNUNET_NAMESTORE_Handle *h); /** * Handle an incoming message of type * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE * * @param qe the respective entry in the message queue * @param msg the message we received * @param size the message size * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and we did NOT notify the client */ static int handle_record_store_response (struct GNUNET_NAMESTORE_QueueEntry *qe, const struct RecordStoreResponseMessage* msg, size_t size) { int res; const char *emsg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' with result %i\n", "RECORD_STORE_RESPONSE", ntohl (msg->op_result)); /* TODO: add actual error message from namestore to response... */ res = ntohl (msg->op_result); if (GNUNET_SYSERR == res) emsg = _("Namestore failed to store record\n"); else emsg = NULL; if (NULL != qe->cont) qe->cont (qe->cont_cls, res, emsg); return GNUNET_OK; } /** * Handle an incoming message of type * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE * * @param qe the respective entry in the message queue * @param msg the message we received * @param size the message size * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and we did NOT notify the client */ static int handle_lookup_result (struct GNUNET_NAMESTORE_QueueEntry *qe, const struct LabelLookupResponseMessage *msg, size_t size) { const char *name; const char *rd_tmp; size_t exp_msg_len; size_t msg_len; size_t name_len; size_t rd_len; unsigned int rd_count; int found; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n", "RECORD_LOOKUP_RESULT"); rd_len = ntohs (msg->rd_len); rd_count = ntohs (msg->rd_count); msg_len = ntohs (msg->gns_header.header.size); name_len = ntohs (msg->name_len); found = ntohs (msg->found); exp_msg_len = sizeof (struct LabelLookupResponseMessage) + name_len + rd_len; if (msg_len != exp_msg_len) { GNUNET_break (0); return GNUNET_SYSERR; } name = (const char *) &msg[1]; if ( (name_len > 0) && ('\0' != name[name_len -1]) ) { GNUNET_break (0); return GNUNET_SYSERR; } if (GNUNET_NO == found) { /* label was not in namestore */ if (NULL != qe->proc) qe->proc (qe->proc_cls, &msg->private_key, name, 0, NULL); return GNUNET_OK; } rd_tmp = &name[name_len]; { struct GNUNET_GNSRECORD_Data rd[rd_count]; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize(rd_len, rd_tmp, rd_count, rd)) { GNUNET_break (0); return GNUNET_SYSERR; } if (0 == name_len) name = NULL; if (NULL != qe->proc) qe->proc (qe->proc_cls, &msg->private_key, name, rd_count, (rd_count > 0) ? rd : NULL); } return GNUNET_OK; } /** * Handle an incoming message of type * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT * * @param qe the respective entry in the message queue * @param msg the message we received * @param size the message size * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and we did NOT notify the client */ static int handle_record_result (struct GNUNET_NAMESTORE_QueueEntry *qe, const struct RecordResultMessage *msg, size_t size) { const char *name; const char *rd_tmp; size_t exp_msg_len; size_t msg_len; size_t name_len; size_t rd_len; unsigned int rd_count; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n", "RECORD_RESULT"); rd_len = ntohs (msg->rd_len); rd_count = ntohs (msg->rd_count); msg_len = ntohs (msg->gns_header.header.size); name_len = ntohs (msg->name_len); GNUNET_break (0 == ntohs (msg->reserved)); exp_msg_len = sizeof (struct RecordResultMessage) + name_len + rd_len; if (msg_len != exp_msg_len) { GNUNET_break (0); return GNUNET_SYSERR; } name = (const char *) &msg[1]; if ( (name_len > 0) && ('\0' != name[name_len -1]) ) { GNUNET_break (0); return GNUNET_SYSERR; } rd_tmp = &name[name_len]; { struct GNUNET_GNSRECORD_Data rd[rd_count]; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize(rd_len, rd_tmp, rd_count, rd)) { GNUNET_break (0); return GNUNET_SYSERR; } if (0 == name_len) name = NULL; if (NULL != qe->proc) qe->proc (qe->proc_cls, &msg->private_key, name, rd_count, (rd_count > 0) ? rd : NULL); } return GNUNET_OK; } /** * Handle an incoming message of type * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE. * * @param qe the respective entry in the message queue * @param msg the message we received * @param size the message size * @return #GNUNET_OK on success, #GNUNET_NO if we notified the client about * the error, #GNUNET_SYSERR on error and we did NOT notify the client */ static int handle_zone_to_name_response (struct GNUNET_NAMESTORE_QueueEntry *qe, const struct ZoneToNameResponseMessage *msg, size_t size) { int res; size_t name_len; size_t rd_ser_len; unsigned int rd_count; const char *name_tmp; const char *rd_tmp; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n", "ZONE_TO_NAME_RESPONSE"); res = ntohs (msg->res); switch (res) { case GNUNET_SYSERR: LOG (GNUNET_ERROR_TYPE_DEBUG, "An error occured during zone to name operation\n"); break; case GNUNET_NO: LOG (GNUNET_ERROR_TYPE_DEBUG, "Namestore has no result for zone to name mapping \n"); if (NULL != qe->proc) qe->proc (qe->proc_cls, &msg->zone, NULL, 0, NULL); return GNUNET_NO; case GNUNET_YES: LOG (GNUNET_ERROR_TYPE_DEBUG, "Namestore has result for zone to name mapping \n"); name_len = ntohs (msg->name_len); rd_count = ntohs (msg->rd_count); rd_ser_len = ntohs (msg->rd_len); name_tmp = (const char *) &msg[1]; if ( (name_len > 0) && ('\0' != name_tmp[name_len -1]) ) { GNUNET_break (0); return GNUNET_SYSERR; } rd_tmp = &name_tmp[name_len]; { struct GNUNET_GNSRECORD_Data rd[rd_count]; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize(rd_ser_len, rd_tmp, rd_count, rd)) { GNUNET_break (0); return GNUNET_SYSERR; } /* normal end, call continuation with result */ if (NULL != qe->proc) qe->proc (qe->proc_cls, &msg->zone, name_tmp, rd_count, rd); /* return is important here: break would call continuation with error! */ return GNUNET_OK; } default: GNUNET_break (0); return GNUNET_SYSERR; } /* error case, call continuation with error */ if (NULL != qe->proc) qe->proc (qe->proc_cls, NULL, NULL, 0, NULL); return GNUNET_NO; } /** * Handle incoming messages for record operations * * @param qe the respective zone iteration handle * @param msg the message we received * @param type the message type in host byte order * @param size the message size * @return #GNUNET_OK on success, #GNUNET_NO if we notified the client about * the error, #GNUNET_SYSERR on error and we did NOT notify the client */ static int manage_record_operations (struct GNUNET_NAMESTORE_QueueEntry *qe, const struct GNUNET_MessageHeader *msg, uint16_t type, size_t size) { /* handle different message type */ switch (type) { case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE: if (size != sizeof (struct RecordStoreResponseMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } return handle_record_store_response (qe, (const struct RecordStoreResponseMessage *) msg, size); case GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE: if (size < sizeof (struct ZoneToNameResponseMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } return handle_zone_to_name_response (qe, (const struct ZoneToNameResponseMessage *) msg, size); case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT: if (size < sizeof (struct RecordResultMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } return handle_record_result (qe, (const struct RecordResultMessage *) msg, size); case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE: if (size < sizeof (struct LabelLookupResponseMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } return handle_lookup_result (qe, (const struct LabelLookupResponseMessage *) msg, size); default: GNUNET_break (0); return GNUNET_SYSERR; } } /** * Handle a response from NAMESTORE service for a zone iteration request * * @param ze the respective iterator for this operation * @param msg the message containing the respoonse * @param size the message size * @return #GNUNET_YES on success, @a ze should be kept, #GNUNET_NO on success if @a ze should * not be kept any longer, #GNUNET_SYSERR on error (disconnect) and @a ze should be kept */ static int handle_zone_iteration_response (struct GNUNET_NAMESTORE_ZoneIterator *ze, const struct RecordResultMessage *msg, size_t size) { static struct GNUNET_CRYPTO_EcdsaPrivateKey priv_dummy; size_t msg_len; size_t exp_msg_len; size_t name_len; size_t rd_len; unsigned rd_count; const char *name_tmp; const char *rd_ser_tmp; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s'\n", "ZONE_ITERATION_RESPONSE"); msg_len = ntohs (msg->gns_header.header.size); rd_len = ntohs (msg->rd_len); rd_count = ntohs (msg->rd_count); name_len = ntohs (msg->name_len); exp_msg_len = sizeof (struct RecordResultMessage) + name_len + rd_len; if (msg_len != exp_msg_len) { GNUNET_break (0); return GNUNET_SYSERR; } if ( (0 == name_len) && (0 == (memcmp (&msg->private_key, &priv_dummy, sizeof (priv_dummy)))) ) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration completed!\n"); if (NULL != ze->proc) ze->proc (ze->proc_cls, NULL, NULL, 0, NULL); return GNUNET_NO; } name_tmp = (const char *) &msg[1]; if ((name_tmp[name_len -1] != '\0') || (name_len > MAX_NAME_LEN)) { GNUNET_break (0); return GNUNET_SYSERR; } rd_ser_tmp = (const char *) &name_tmp[name_len]; { struct GNUNET_GNSRECORD_Data rd[rd_count]; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)) { GNUNET_break (0); return GNUNET_SYSERR; } if (NULL != ze->proc) ze->proc (ze->proc_cls, &msg->private_key, name_tmp, rd_count, rd); return GNUNET_YES; } } /** * Handle incoming messages for zone iterations * * @param ze the respective zone iteration handle * @param msg the message we received * @param type the message type in HBO * @param size the message size * @return #GNUNET_YES on success, @a ze should be kept, #GNUNET_NO on success if @a ze should * not be kept any longer, #GNUNET_SYSERR on error (disconnect) and @a ze should be kept */ static int manage_zone_operations (struct GNUNET_NAMESTORE_ZoneIterator *ze, const struct GNUNET_MessageHeader *msg, int type, size_t size) { /* handle different message type */ switch (type) { case GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT: if (size < sizeof (struct RecordResultMessage)) { GNUNET_break (0); return GNUNET_SYSERR; } return handle_zone_iteration_response (ze, (const struct RecordResultMessage *) msg, size); default: GNUNET_break (0); return GNUNET_SYSERR; } } /** * Type of a function to call when we receive a message * from the service. * * @param cls the `struct GNUNET_NAMESTORE_SchedulingHandle` * @param msg message received, NULL on timeout or fatal error */ static void process_namestore_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_NAMESTORE_Handle *h = cls; const struct GNUNET_NAMESTORE_Header *gm; struct GNUNET_NAMESTORE_QueueEntry *qe; struct GNUNET_NAMESTORE_ZoneIterator *ze; uint16_t size; uint16_t type; uint32_t r_id; int ret; if (NULL == msg) { force_reconnect (h); return; } size = ntohs (msg->size); type = ntohs (msg->type); if (size < sizeof (struct GNUNET_NAMESTORE_Header)) { GNUNET_break_op (0); GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, GNUNET_TIME_UNIT_FOREVER_REL); return; } gm = (const struct GNUNET_NAMESTORE_Header *) msg; r_id = ntohl (gm->r_id); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message type %u size %u op %u\n", (unsigned int) type, (unsigned int) size, (unsigned int) r_id); /* Is it a record related operation ? */ for (qe = h->op_head; qe != NULL; qe = qe->next) if (qe->op_id == r_id) break; if (NULL != qe) { ret = manage_record_operations (qe, msg, type, size); if (GNUNET_SYSERR == ret) { /* protocol error, need to reconnect */ h->reconnect = GNUNET_YES; } else { /* client was notified about success or failure, clean up 'qe' */ GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe); GNUNET_free (qe); } } /* Is it a zone iteration operation? */ for (ze = h->z_head; ze != NULL; ze = ze->next) if (ze->op_id == r_id) break; if (NULL != ze) { ret = manage_zone_operations (ze, msg, type, size); if (GNUNET_NO == ret) { /* end of iteration, clean up 'ze' */ GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, ze); GNUNET_free (ze); } if (GNUNET_SYSERR == ret) { /* protocol error, need to reconnect */ h->reconnect = GNUNET_YES; } } if (GNUNET_YES == h->reconnect) { force_reconnect (h); return; } GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Transmit messages from the message queue to the service * (if there are any, and if we are not already trying). * * @param h handle to use */ static void do_transmit (struct GNUNET_NAMESTORE_Handle *h); /** * We can now transmit a message to NAMESTORE. Do it. * * @param cls the `struct GNUNET_NAMESTORE_Handle` * @param size number of bytes we can transmit * @param buf where to copy the messages * @return number of bytes copied into @a buf */ static size_t transmit_message_to_namestore (void *cls, size_t size, void *buf) { struct GNUNET_NAMESTORE_Handle *h = cls; struct PendingMessage *p; size_t ret; char *cbuf; h->th = NULL; if ((0 == size) || (NULL == buf)) { force_reconnect (h); return 0; } ret = 0; cbuf = buf; while ( (NULL != (p = h->pending_head)) && (p->size <= size) ) { memcpy (&cbuf[ret], &p[1], p->size); ret += p->size; size -= p->size; GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); if (GNUNET_NO == h->is_receiving) { h->is_receiving = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &process_namestore_message, h, GNUNET_TIME_UNIT_FOREVER_REL); } GNUNET_free (p); } do_transmit (h); return ret; } /** * Transmit messages from the message queue to the service * (if there are any, and if we are not already trying). * * @param h handle to use */ static void do_transmit (struct GNUNET_NAMESTORE_Handle *h) { struct PendingMessage *p; if (NULL != h->th) return; /* transmission request already pending */ if (NULL == (p = h->pending_head)) return; /* transmission queue empty */ if (NULL == h->client) return; /* currently reconnecting */ h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, p->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_message_to_namestore, h); GNUNET_break (NULL != h->th); } /** * Reconnect to namestore service. * * @param h the handle to the NAMESTORE service */ static void reconnect (struct GNUNET_NAMESTORE_Handle *h) { GNUNET_assert (NULL == h->client); h->client = GNUNET_CLIENT_connect ("namestore", h->cfg); GNUNET_assert (NULL != h->client); do_transmit (h); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NAMESTORE_Handle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; reconnect (h); } /** * Disconnect from service and then reconnect. * * @param h our handle */ static void force_reconnect (struct GNUNET_NAMESTORE_Handle *h) { if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } h->reconnect = GNUNET_NO; GNUNET_CLIENT_disconnect (h->client); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting to namestore\n"); h->is_receiving = GNUNET_NO; h->client = NULL; h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect_task, h); } /** * Get a fresh operation id to distinguish between namestore requests * * @param h the namestore handle * @return next operation id to use */ static uint32_t get_op_id (struct GNUNET_NAMESTORE_Handle *h) { return h->last_op_id_used++; } /** * Initialize the connection with the NAMESTORE service. * * @param cfg configuration to use * @return handle to the GNS service, or NULL on error */ struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_NAMESTORE_Handle *h; h = GNUNET_new (struct GNUNET_NAMESTORE_Handle); h->cfg = cfg; h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect_task, h); h->last_op_id_used = 0; return h; } /** * Disconnect from the namestore service (and free associated * resources). * * @param h handle to the namestore */ void GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h) { struct PendingMessage *p; struct GNUNET_NAMESTORE_QueueEntry *q; struct GNUNET_NAMESTORE_ZoneIterator *z; LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); GNUNET_assert (NULL != h); if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } while (NULL != (p = h->pending_head)) { GNUNET_CONTAINER_DLL_remove (h->pending_head, h->pending_tail, p); GNUNET_free (p); } GNUNET_break (NULL == h->op_head); while (NULL != (q = h->op_head)) { GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q); GNUNET_free (q); } GNUNET_break (NULL == h->z_head); while (NULL != (z = h->z_head)) { GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z); GNUNET_free (z); } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (h); } /** * Store an item in the namestore. If the item is already present, * it is replaced with the new record. Use an empty array to * remove all records under the given name. * * @param h handle to the namestore * @param pkey private key of the zone * @param label name that is being mapped (at most 255 characters long) * @param rd_count number of records in the 'rd' array * @param rd array of records with data to store * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return handle to abort the request */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; char *name_tmp; char *rd_ser; size_t rd_ser_len; size_t msg_size; size_t name_len; uint32_t rid; struct RecordStoreMessage *msg; GNUNET_assert (NULL != h); GNUNET_assert (NULL != pkey); GNUNET_assert (NULL != label); name_len = strlen (label) + 1; if (name_len > MAX_NAME_LEN) { GNUNET_break (0); return NULL; } rid = get_op_id (h); qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); qe->nsh = h; qe->cont = cont; qe->cont_cls = cont_cls; qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); /* setup msg */ rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); msg_size = sizeof (struct RecordStoreMessage) + name_len + rd_ser_len; pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; msg = (struct RecordStoreMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); msg->name_len = htons (name_len); msg->rd_count = htons (rd_count); msg->rd_len = htons (rd_ser_len); msg->reserved = htons (0); msg->private_key = *pkey; name_tmp = (char *) &msg[1]; memcpy (name_tmp, label, name_len); rd_ser = &name_tmp[name_len]; GNUNET_break (rd_ser_len == GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message for name `%s' with size %u and %u records\n", "NAMESTORE_RECORD_STORE", label, msg_size, rd_count); GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit (h); return qe; } /** * Set the desired nick name for a zone * * @param h handle to the namestore * @param pkey private key of the zone * @param nick the nick name to set * @param cont continuation to call when done * @param cont_cls closure for 'cont' * @return handle to abort the request */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_set_nick (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *nick, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_GNSRECORD_Data rd; memset (&rd, 0, sizeof (rd)); rd.data = nick; rd.data_size = strlen (nick) +1; rd.record_type = GNUNET_GNSRECORD_TYPE_NICK; rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE; return GNUNET_NAMESTORE_records_store(h, pkey, GNUNET_GNS_MASTERZONE_STR, 1, &rd, cont, cont_cls); } /** * Lookup an item in the namestore. * * @param h handle to the namestore * @param pkey private key of the zone * @param label name that is being mapped (at most 255 characters long) * @param rm function to call with the result (with 0 records if we don't have that label) * @param rm_cls closure for @a rm * @return handle to abort the request */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey, const char *label, GNUNET_NAMESTORE_RecordMonitor rm, void *rm_cls) { struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; struct LabelLookupMessage * msg; size_t msg_size; size_t label_len; GNUNET_assert (NULL != h); GNUNET_assert (NULL != pkey); GNUNET_assert (NULL != label); if (1 == (label_len = strlen (label) + 1)) return NULL; qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); qe->nsh = h; qe->proc = rm; qe->proc_cls = rm_cls; qe->op_id = get_op_id(h); GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); msg_size = sizeof (struct LabelLookupMessage) + label_len; pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; msg = (struct LabelLookupMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (qe->op_id); msg->zone = *pkey; msg->label_len = htonl(label_len); memcpy (&msg[1], label, label_len); /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit (h); return qe; } /** * Look for an existing PKEY delegation record for a given public key. * Returns at most one result to the processor. * * @param h handle to the namestore * @param zone public key of the zone to look up in, never NULL * @param value_zone public key of the target zone (value), never NULL * @param proc function to call on the matching records, or with * NULL (rd_count == 0) if there are no matching records * @param proc_cls closure for @a proc * @return a handle that can be used to * cancel */ struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_zone_to_name (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls) { struct GNUNET_NAMESTORE_QueueEntry *qe; struct PendingMessage *pe; struct ZoneToNameMessage * msg; size_t msg_size; uint32_t rid; GNUNET_assert (NULL != h); GNUNET_assert (NULL != zone); GNUNET_assert (NULL != value_zone); rid = get_op_id(h); qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); qe->nsh = h; qe->proc = proc; qe->proc_cls = proc_cls; qe->op_id = rid; GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe); msg_size = sizeof (struct ZoneToNameMessage); pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; msg = (struct ZoneToNameMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); msg->zone = *zone; msg->value_zone = *value_zone; /* transmit message */ GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit (h); return qe; } /** * Starts a new zone iteration (used to periodically PUT all of our * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once * immediately, and then again after * #GNUNET_NAMESTORE_zone_iterator_next is invoked. * * @param h handle to the namestore * @param zone zone to access, NULL for all zones * @param proc function to call on each name from the zone; it * will be called repeatedly with a value (if available) * and always once at the end with a name of NULL. * @param proc_cls closure for @a proc * @return an iterator handle to use for iteration */ struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start (struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, GNUNET_NAMESTORE_RecordMonitor proc, void *proc_cls) { struct GNUNET_NAMESTORE_ZoneIterator *it; struct PendingMessage *pe; struct ZoneIterationStartMessage * msg; size_t msg_size; uint32_t rid; GNUNET_assert (NULL != h); rid = get_op_id(h); it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator); it->h = h; it->proc = proc; it->proc_cls = proc_cls; it->op_id = rid; if (NULL != zone) it->zone = *zone; GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it); msg_size = sizeof (struct ZoneIterationStartMessage); pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; msg = (struct ZoneIterationStartMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (rid); if (NULL != zone) msg->zone = *zone; GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit (h); return it; } /** * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start * for the next record. * * @param it the iterator */ void GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it) { struct GNUNET_NAMESTORE_Handle *h; struct ZoneIterationNextMessage * msg; struct PendingMessage *pe; size_t msg_size; GNUNET_assert (NULL != it); h = it->h; msg_size = sizeof (struct ZoneIterationNextMessage); pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; msg = (struct ZoneIterationNextMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (it->op_id); LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_NEXT"); GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit (h); } /** * Stops iteration and releases the namestore handle for further calls. * * @param it the iterator */ void GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it) { struct GNUNET_NAMESTORE_Handle *h; struct PendingMessage *pe; size_t msg_size; struct ZoneIterationStopMessage * msg; GNUNET_assert (NULL != it); h = it->h; GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, it); msg_size = sizeof (struct ZoneIterationStopMessage); pe = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size); pe->size = msg_size; msg = (struct ZoneIterationStopMessage *) &pe[1]; msg->gns_header.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP); msg->gns_header.header.size = htons (msg_size); msg->gns_header.r_id = htonl (it->op_id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message\n", "ZONE_ITERATION_STOP"); GNUNET_CONTAINER_DLL_insert_tail (h->pending_head, h->pending_tail, pe); do_transmit (h); GNUNET_free (it); } /** * Cancel a namestore operation. The final callback from the * operation must not have been done yet. * * @param qe operation to cancel */ void GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe) { struct GNUNET_NAMESTORE_Handle *h = qe->nsh; GNUNET_assert (NULL != qe); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe); GNUNET_free(qe); } /* end of namestore_api.c */ gnunet-0.10.1/src/namestore/test_namestore_api_zone_iteration.c0000644000175000017500000002747312251551532021756 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_zone_iteration.c * @brief testcase for zone iteration functionality: iterate all zones */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #include "namestore.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle * nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2; static struct GNUNET_NAMESTORE_ZoneIterator *zi; static int res; static int returned_records; static char * s_name_1; static struct GNUNET_GNSRECORD_Data *s_rd_1; static char * s_name_2; static struct GNUNET_GNSRECORD_Data *s_rd_2; static char * s_name_3; static struct GNUNET_GNSRECORD_Data *s_rd_3; static char *directory; /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != zi) { GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; } if (nsh != NULL) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } GNUNET_free_non_null(s_name_1); GNUNET_free_non_null(s_name_2); GNUNET_free_non_null(s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (privkey != NULL) GNUNET_free (privkey); privkey = NULL; if (privkey2 != NULL) GNUNET_free (privkey2); privkey2 = NULL; res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != zi) { GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; } if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (privkey != NULL) GNUNET_free (privkey); privkey = NULL; if (privkey2 != NULL) GNUNET_free (privkey2); privkey2 = NULL; GNUNET_free (s_name_1); GNUNET_free (s_name_2); GNUNET_free (s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (nsh != NULL) GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } static void zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int failed = GNUNET_NO; if ((zone == NULL) && (label == NULL)) { GNUNET_break (3 == returned_records); if (3 == returned_records) { res = 0; /* Last iteraterator callback, we are done */ zi = NULL; } else res = 1; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n", returned_records); GNUNET_SCHEDULER_add_now (&end, NULL); return; } if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { if (0 == strcmp (label, s_name_1)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_1)) { failed = GNUNET_YES; GNUNET_break (0); } } else { failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == strcmp (label, s_name_2)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_2)) { failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid record count\n"); failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s' for first zone\n", label); failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { if (0 == strcmp (label, s_name_3)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_3)) { failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid record count\n"); failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s' for first zone\n", label); failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid zone\n"); failed = GNUNET_YES; GNUNET_break (0); } if (failed == GNUNET_NO) { returned_records ++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); GNUNET_NAMESTORE_zone_iterator_next (zi); } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (&end, NULL); } } static void put_cont (void *cls, int32_t success, const char *emsg) { static int c = 0; if (success == GNUNET_OK) { c++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", emsg); GNUNET_break (0); if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if (c == 3) { res = 1; returned_records = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n"); zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, NULL, &zone_proc, NULL); if (zi == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); GNUNET_break (0); if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } } } static struct GNUNET_GNSRECORD_Data * create_record (unsigned int count) { unsigned int c; struct GNUNET_GNSRECORD_Data * rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; rd[c].record_type = 1111; rd[c].data_size = 50; rd[c].data = GNUNET_malloc(50); rd[c].flags = 0; memset ((char *) rd[c].data, 'a', 50); } return rd; } /** * Callback called from the zone iterator when we iterate over * the empty zone. Check that we got no records and then * start the actual tests by filling the zone. */ static void empty_zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { char *hostkey_file; GNUNET_assert (nsh == cls); if (NULL != zone) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Expected empty zone but received zone private key\n")); GNUNET_break (0); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if ((NULL != label) || (NULL != rd) || (0 != rd_count)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Expected no zone content but received data\n")); GNUNET_break (0); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } zi = NULL; GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey2 != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); GNUNET_asprintf(&s_name_1, "dummy1"); s_rd_1 = create_record(1); GNUNET_NAMESTORE_records_store (nsh, privkey, s_name_1, 1, s_rd_1, &put_cont, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); GNUNET_asprintf(&s_name_2, "dummy2"); s_rd_2 = create_record(1); GNUNET_NAMESTORE_records_store (nsh, privkey, s_name_2, 1, s_rd_2, &put_cont, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); /* name in different zone */ GNUNET_asprintf(&s_name_3, "dummy3"); s_rd_3 = create_record(1); GNUNET_NAMESTORE_records_store (nsh, privkey2, s_name_3, 1, s_rd_3, &put_cont, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT, &endbadly, NULL); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); /* first, iterate over empty namestore */ zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, NULL, &empty_zone_proc, nsh); if (NULL == zi) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); } } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_zone_iteration.c */ gnunet-0.10.1/src/namestore/test_namestore_api_remove_not_existing_record.c0000644000175000017500000001125612251551532024342 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_remove_not_existing_record.c * @brief testcase for namestore_api.c */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle *nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; static char *directory; static void cleanup () { if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } static void put_cont (void *cls, int32_t success, const char *emsg) { GNUNET_assert (NULL != cls); nsqe = NULL; if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } switch (success) { case GNUNET_NO: /* We expected GNUNET_NO, since record was not found */ GNUNET_SCHEDULER_add_now (&end, NULL); break; case GNUNET_OK: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Namestore could remove non-existing record: `%s'\n", (NULL !=emsg) ? emsg : ""); GNUNET_SCHEDULER_add_now (&endbadly, NULL); break; case GNUNET_SYSERR: default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Namestore failed: `%s'\n", (NULL !=emsg) ? emsg : ""); GNUNET_SCHEDULER_add_now (&endbadly, NULL); break; } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { char *hostkey_file; const char * name = "dummy.dummy.gnunet"; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 0, NULL, &put_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_remove_not_existing_record.c */ gnunet-0.10.1/src/namestore/namestore_api_monitor.c0000644000175000017500000001767512231174262017357 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/namestore_api_monitor.c * @brief API to monitor changes in the NAMESTORE * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_crypto_lib.h" #include "gnunet_constants.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_arm_service.h" #include "gnunet_signatures.h" #include "gnunet_namestore_service.h" #include "namestore.h" /** * Handle for a monitoring activity. */ struct GNUNET_NAMESTORE_ZoneMonitor { /** * Configuration (to reconnect). */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to namestore service. */ struct GNUNET_CLIENT_Connection *h; /** * Function to call on events. */ GNUNET_NAMESTORE_RecordMonitor monitor; /** * Function called when we've synchronized. */ GNUNET_NAMESTORE_RecordsSynchronizedCallback sync_cb; /** * Closure for 'monitor' and 'sync_cb'. */ void *cls; /** * Transmission handle to client. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Monitored zone. */ struct GNUNET_CRYPTO_EcdsaPrivateKey zone; /** * Do we first iterate over all existing records? */ int iterate_first; }; /** * Send our request to start monitoring to the service. * * @param cls the monitor handle * @param size number of bytes available in buf * @param buf where to copy the message to the service * @return number of bytes copied to buf */ static size_t transmit_monitor_message (void *cls, size_t size, void *buf); /** * Reconnect to the namestore service. * * @param zm monitor to reconnect */ static void reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm) { if (NULL != zm->h) GNUNET_CLIENT_disconnect (zm->h); zm->monitor (zm->cls, NULL, NULL, 0, NULL); GNUNET_assert (NULL != (zm->h = GNUNET_CLIENT_connect ("namestore", zm->cfg))); zm->th = GNUNET_CLIENT_notify_transmit_ready (zm->h, sizeof (struct ZoneMonitorStartMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_monitor_message, zm); } /** * We've received a notification about a change to our zone. * Forward to monitor callback. * * @param cls the zone monitor handle * @param msg the message from the service. */ static void handle_updates (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; const struct RecordResultMessage *lrm; size_t lrm_len; size_t exp_lrm_len; size_t name_len; size_t rd_len; unsigned rd_count; const char *name_tmp; const char *rd_ser_tmp; if (NULL == msg) { reconnect (zm); return; } if ( (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader)) && (GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC == ntohs (msg->type) ) ) { GNUNET_CLIENT_receive (zm->h, &handle_updates, zm, GNUNET_TIME_UNIT_FOREVER_REL); if (NULL != zm->sync_cb) zm->sync_cb (zm->cls); return; } if ( (ntohs (msg->size) < sizeof (struct RecordResultMessage)) || (GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT != ntohs (msg->type) ) ) { GNUNET_break (0); reconnect (zm); return; } lrm = (const struct RecordResultMessage *) msg; lrm_len = ntohs (lrm->gns_header.header.size); rd_len = ntohs (lrm->rd_len); rd_count = ntohs (lrm->rd_count); name_len = ntohs (lrm->name_len); exp_lrm_len = sizeof (struct RecordResultMessage) + name_len + rd_len; if (lrm_len != exp_lrm_len) { GNUNET_break (0); reconnect (zm); return; } if (0 == name_len) { GNUNET_break (0); reconnect (zm); return; } name_tmp = (const char *) &lrm[1]; if ((name_tmp[name_len -1] != '\0') || (name_len > MAX_NAME_LEN)) { GNUNET_break (0); reconnect (zm); return; } rd_ser_tmp = (const char *) &name_tmp[name_len]; { struct GNUNET_GNSRECORD_Data rd[rd_count]; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd)) { GNUNET_break (0); reconnect (zm); return; } GNUNET_CLIENT_receive (zm->h, &handle_updates, zm, GNUNET_TIME_UNIT_FOREVER_REL); zm->monitor (zm->cls, &lrm->private_key, name_tmp, rd_count, rd); } } /** * Send our request to start monitoring to the service. * * @param cls the monitor handle * @param size number of bytes available in buf * @param buf where to copy the message to the service * @return number of bytes copied to buf */ static size_t transmit_monitor_message (void *cls, size_t size, void *buf) { struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls; struct ZoneMonitorStartMessage sm; zm->th = NULL; if (size < sizeof (struct ZoneMonitorStartMessage)) { reconnect (zm); return 0; } sm.header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START); sm.header.size = htons (sizeof (struct ZoneMonitorStartMessage)); sm.iterate_first = htonl (zm->iterate_first); sm.zone = zm->zone; memcpy (buf, &sm, sizeof (sm)); GNUNET_CLIENT_receive (zm->h, &handle_updates, zm, GNUNET_TIME_UNIT_FOREVER_REL); return sizeof (sm); } /** * Begin monitoring a zone for changes. If @a iterate_first is set, * we Will first call the @a monitor function on all existing records * in the selected zone(s). In any case, we will call @a sync and * afterwards call @a monitor whenever a record changes. * * @param cfg configuration to use to connect to namestore * @param zone zone to monitor * @param iterate_first #GNUNET_YES to first iterate over all existing records, * #GNUNET_NO to only return changes that happen from now on * @param monitor function to call on zone changes * @param sync_cb function called when we're in sync with the namestore * @param cls closure for @a monitor and @a sync_cb * @return handle to stop monitoring */ struct GNUNET_NAMESTORE_ZoneMonitor * GNUNET_NAMESTORE_zone_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, int iterate_first, GNUNET_NAMESTORE_RecordMonitor monitor, GNUNET_NAMESTORE_RecordsSynchronizedCallback sync_cb, void *cls) { struct GNUNET_NAMESTORE_ZoneMonitor *zm; struct GNUNET_CLIENT_Connection *client; if (NULL == (client = GNUNET_CLIENT_connect ("namestore", cfg))) return NULL; zm = GNUNET_new (struct GNUNET_NAMESTORE_ZoneMonitor); zm->cfg = cfg; zm->h = client; if (NULL != zone) zm->zone = *zone; zm->iterate_first = iterate_first; zm->monitor = monitor; zm->sync_cb = sync_cb; zm->cls = cls; zm->th = GNUNET_CLIENT_notify_transmit_ready (zm->h, sizeof (struct ZoneMonitorStartMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_monitor_message, zm); return zm; } /** * Stop monitoring a zone for changes. * * @param zm handle to the monitor activity to stop */ void GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm) { if (NULL != zm->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (zm->th); zm->th = NULL; } GNUNET_CLIENT_disconnect (zm->h); GNUNET_free (zm); } /* end of namestore_api_monitor.c */ gnunet-0.10.1/src/namestore/test_namestore_put.sh0000755000175000017500000000244012261236531017062 00000000000000#!/bin/bash CONFIGURATION="test_namestore_api.conf" trap "gnunet-arm -e -c $CONFIGURATION" SIGINT LOCATION=$(which gnunet-config) if [ -z $LOCATION ] then LOCATION="gnunet-config" fi $LOCATION --version 1> /dev/null if test $? != 0 then echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX" exit 77 fi rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME` TEST_DOMAIN_PLUS="www.gnu" TEST_DOMAIN_DNS="www3.gnu" TEST_IP_PLUS="127.0.0.1" TEST_IP_DNS="131.159.74.67" TEST_RECORD_CNAME_SERVER="server" TEST_RECORD_CNAME_PLUS="server.+" TEST_RECORD_CNAME_DNS="gnunet.org" TEST_RECORD_NAME_SERVER="server" TEST_RECORD_NAME_PLUS="www" TEST_RECORD_NAME_DNS="www3" which timeout &> /dev/null && DO_TIMEOUT="timeout 5" function start_peer { gnunet-arm -s -c $CONFIGURATION gnunet-identity -C testego -c $CONFIGURATION } function stop_peer { gnunet-identity -D testego -c $CONFIGURATION gnunet-arm -e -c $CONFIGURATION } start_peer # Create a public record gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION NAMESTORE_RES=$? stop_peer if [ $NAMESTORE_RES == 0 ] then echo "PASS: Creating name in namestore" else echo "FAIL: Creating name in namestore failed with $NAMESTORE_RES." exit 1 fi gnunet-0.10.1/src/namestore/gnunet-namestore-fcfsd.c0000644000175000017500000006451012255010512017317 00000000000000/* This file is part of GNUnet. (C) 2012-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnunet-namestore-fcfsd.c * @brief HTTP daemon that offers first-come-first-serve GNS domain registration * @author Christian Grothoff * * TODO: * - need to track active zone info requests so we can cancel them * during shutdown, right? * - the code currently contains a 'race' between checking that the * domain name is available and allocating it to the new public key * (should this race be solved by namestore or by fcfsd?) * - nicer error reporting to browser */ #include "platform.h" #include #include "gnunet_util_lib.h" #include "gnunet_identity_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_namestore_service.h" /** * Invalid method page. */ #define METHOD_ERROR "Illegal requestGo away." /** * Front page. (/) */ #define MAIN_PAGE "GNUnet FCFS Authority Name Registration Service

What is your desired domain name? (at most 63 lowercase characters, no dots allowed.)

What is your public key? (Copy from gnunet-setup.)
List of all registered names " /** * Second page (/S) */ #define SUBMIT_PAGE "%s%s" /** * Fcfs zoneinfo page (/Zoneinfo) */ #define ZONEINFO_PAGE "FCFS Zoneinfo

FCFS Zoneinfo

%s
namePKEY
" #define FCFS_ZONEINFO_URL "/Zoneinfo" /** * Mime type for HTML pages. */ #define MIME_HTML "text/html" /** * Name of our cookie. */ #define COOKIE_NAME "namestore-fcfsd" #define DEFAULT_ZONEINFO_BUFSIZE 2048 /** * Phases a request goes through. */ enum Phase { /** * Start phase (parsing POST, checking). */ RP_START = 0, /** * Lookup to see if the domain name is taken. */ RP_LOOKUP, /** * Storing of the record. */ RP_PUT, /** * We're done with success. */ RP_SUCCESS, /** * Send failure message. */ RP_FAIL }; /** * Data kept per request. */ struct Request { /** * Associated session. */ struct Session *session; /** * Post processor handling form data (IF this is * a POST request). */ struct MHD_PostProcessor *pp; /** * URL to serve in response to this POST (if this request * was a 'POST') */ const char *post_url; /** * Active request with the namestore. */ struct GNUNET_NAMESTORE_QueueEntry *qe; /** * Active iteration with the namestore. */ struct GNUNET_NAMESTORE_ZoneIterator *zi; /** * Current processing phase. */ enum Phase phase; /** * Domain name submitted via form. */ char domain_name[64]; /** * Public key submitted via form. */ char public_key[128]; struct GNUNET_CRYPTO_EcdsaPublicKey pub; }; /** * Zoneinfo request */ struct ZoneinfoRequest { /** * Connection */ struct MHD_Connection *connection; /** * List iterator */ struct GNUNET_NAMESTORE_ZoneIterator *list_it; /** * Buffer */ char* zoneinfo; /** * Buffer length */ size_t buf_len; /** * Buffer write offset */ size_t write_offset; }; /** * MHD deamon reference. */ static struct MHD_Daemon *httpd; /** * Main HTTP task. */ static GNUNET_SCHEDULER_TaskIdentifier httpd_task; /** * Handle to the namestore. */ static struct GNUNET_NAMESTORE_Handle *ns; /** * Private key for the fcfsd zone. */ static struct GNUNET_CRYPTO_EcdsaPrivateKey fcfs_zone_pkey; /** * Connection to identity service. */ static struct GNUNET_IDENTITY_Handle *identity; /** * Request for our ego. */ static struct GNUNET_IDENTITY_Operation *id_op; /** * Port we use for the HTTP server. */ static unsigned long long port; /** * Task run whenever HTTP server operations are pending. * * @param cls unused * @param tc scheduler context */ static void do_httpd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Schedule task to run MHD server now. */ static void run_httpd_now () { if (GNUNET_SCHEDULER_NO_TASK != httpd_task) { GNUNET_SCHEDULER_cancel (httpd_task); httpd_task = GNUNET_SCHEDULER_NO_TASK; } httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL); } static void iterate_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { struct ZoneinfoRequest *zr = cls; struct MHD_Response *response; char* full_page; size_t bytes_free; char* pkey; char* new_buf; if (NULL == name) { zr->list_it = NULL; /* return static form */ GNUNET_asprintf (&full_page, ZONEINFO_PAGE, zr->zoneinfo, zr->zoneinfo); response = MHD_create_response_from_buffer (strlen (full_page), (void *) full_page, MHD_RESPMEM_MUST_FREE); MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, MIME_HTML); MHD_queue_response (zr->connection, MHD_HTTP_OK, response); MHD_destroy_response (response); GNUNET_free (zr->zoneinfo); GNUNET_free (zr); run_httpd_now (); return; } if (1 != rd_len) { GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); return; } if (GNUNET_GNSRECORD_TYPE_PKEY != rd->record_type) { GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); return; } bytes_free = zr->buf_len - zr->write_offset; pkey = GNUNET_GNSRECORD_value_to_string (rd->record_type, rd->data, rd->data_size); if (bytes_free < (strlen (name) + strlen (pkey) + 40)) { new_buf = GNUNET_malloc (zr->buf_len * 2); memcpy (new_buf, zr->zoneinfo, zr->write_offset); GNUNET_free (zr->zoneinfo); zr->zoneinfo = new_buf; zr->buf_len *= 2; } sprintf (zr->zoneinfo + zr->write_offset, "%s%s", name, pkey); zr->write_offset = strlen (zr->zoneinfo); GNUNET_NAMESTORE_zone_iterator_next (zr->list_it); GNUNET_free (pkey); } /** * Handler that returns FCFS zoneinfo page. * * @param connection connection to use * @return MHD_YES on success */ static int serve_zoneinfo_page (struct MHD_Connection *connection) { struct ZoneinfoRequest *zr; zr = GNUNET_new (struct ZoneinfoRequest); zr->zoneinfo = GNUNET_malloc (DEFAULT_ZONEINFO_BUFSIZE); zr->buf_len = DEFAULT_ZONEINFO_BUFSIZE; zr->connection = connection; zr->write_offset = 0; zr->list_it = GNUNET_NAMESTORE_zone_iteration_start (ns, &fcfs_zone_pkey, &iterate_cb, zr); return MHD_YES; } /** * Handler that returns a simple static HTTP page. * * @param connection connection to use * @return MHD_YES on success */ static int serve_main_page (struct MHD_Connection *connection) { int ret; struct MHD_Response *response; /* return static form */ response = MHD_create_response_from_buffer (strlen (MAIN_PAGE), (void *) MAIN_PAGE, MHD_RESPMEM_PERSISTENT); MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, MIME_HTML); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return ret; } /** * Send the 'SUBMIT_PAGE'. * * @param info information string to send to the user * @param request request information * @param connection connection to use */ static int fill_s_reply (const char *info, struct Request *request, struct MHD_Connection *connection) { int ret; char *reply; struct MHD_Response *response; GNUNET_asprintf (&reply, SUBMIT_PAGE, info, info); /* return static form */ response = MHD_create_response_from_buffer (strlen (reply), (void *) reply, MHD_RESPMEM_MUST_FREE); MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, MIME_HTML); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return ret; } /** * Iterator over key-value pairs where the value * maybe made available in increments and/or may * not be zero-terminated. Used for processing * POST data. * * @param cls user-specified closure * @param kind type of the value * @param key 0-terminated key for the value * @param filename name of the uploaded file, NULL if not known * @param content_type mime-type of the data, NULL if not known * @param transfer_encoding encoding of the data, NULL if not known * @param data pointer to size bytes of data at the * specified offset * @param off offset of data in the overall value * @param size number of bytes in data available * @return MHD_YES to continue iterating, * MHD_NO to abort the iteration */ static int post_iterator (void *cls, enum MHD_ValueKind kind, const char *key, const char *filename, const char *content_type, const char *transfer_encoding, const char *data, uint64_t off, size_t size) { struct Request *request = cls; if (0 == strcmp ("domain", key)) { if (size + off >= sizeof(request->domain_name)) size = sizeof (request->domain_name) - off - 1; memcpy (&request->domain_name[off], data, size); request->domain_name[size+off] = '\0'; return MHD_YES; } if (0 == strcmp ("pkey", key)) { if (size + off >= sizeof(request->public_key)) size = sizeof (request->public_key) - off - 1; memcpy (&request->public_key[off], data, size); request->public_key[size+off] = '\0'; return MHD_YES; } GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported form value `%s'\n"), key); return MHD_YES; } /** * Continuation called to notify client about result of the * operation. * * @param cls closure * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate) * #GNUNET_NO if content was already there * #GNUNET_YES (or other positive value) on success * @param emsg NULL on success, otherwise an error message */ static void put_continuation (void *cls, int32_t success, const char *emsg) { struct Request *request = cls; request->qe = NULL; if (0 >= success) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to create record for domain `%s': %s\n"), request->domain_name, emsg); request->phase = RP_FAIL; } else request->phase = RP_SUCCESS; run_httpd_now (); } /** * Test if a name mapping was found, if so, refuse. If not, initiate storing of the record. * * @param cls closure * @param zone_key public key of the zone * @param name name that is being mapped (at most 255 characters long) * @param rd_count number of entries in @a rd array * @param rd array of records with data to store */ static void zone_to_name_cb (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *name, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct Request *request = cls; struct GNUNET_GNSRECORD_Data r; request->qe = NULL; if (0 != rd_count) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Found existing name `%s' for the given key\n"), name); request->phase = RP_FAIL; run_httpd_now (); return; } if (NULL == zone_key) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error when mapping zone to name\n")); request->phase = RP_FAIL; run_httpd_now (); return; } r.data = &request->pub; r.data_size = sizeof (request->pub); r.expiration_time = UINT64_MAX; r.record_type = GNUNET_GNSRECORD_TYPE_PKEY; r.flags = GNUNET_GNSRECORD_RF_NONE; request->qe = GNUNET_NAMESTORE_records_store (ns, &fcfs_zone_pkey, request->domain_name, 1, &r, &put_continuation, request); } /** * We got a block back from the namestore. Decrypt it * and continue to process the result. * * @param cls the 'struct Request' we are processing * @param zone private key of the zone; NULL on disconnect * @param label label of the records; NULL on disconnect * @param rd_count number of entries in @a rd array, 0 if label was deleted * @param rd array of records with data to store */ static void lookup_block_processor (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct Request *request = cls; request->qe = NULL; if (0 == rd_count) { if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key, strlen (request->public_key), &request->pub)) { GNUNET_break (0); request->phase = RP_FAIL; run_httpd_now (); return; } request->qe = GNUNET_NAMESTORE_zone_to_name (ns, &fcfs_zone_pkey, &request->pub, &zone_to_name_cb, request); return; } GNUNET_break (0 != rd_count); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Found %u existing records for domain `%s'\n"), rd_count, request->domain_name); request->phase = RP_FAIL; run_httpd_now (); return; } /** * Main MHD callback for handling requests. * * @param cls unused * @param connection MHD connection handle * @param url the requested url * @param method the HTTP method used ("GET", "PUT", etc.) * @param version the HTTP version string (i.e. "HTTP/1.1") * @param upload_data the data being uploaded (excluding HEADERS, * for a POST that fits into memory and that is encoded * with a supported encoding, the POST data will NOT be * given in upload_data and is instead available as * part of MHD_get_connection_values; very large POST * data *will* be made available incrementally in * upload_data) * @param upload_data_size set initially to the size of the * @a upload_data provided; the method must update this * value to the number of bytes NOT processed; * @param ptr pointer to location where we store the 'struct Request' * @return MHD_YES if the connection was handled successfully, * MHD_NO if the socket must be closed due to a serious * error while handling the request */ static int create_response (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) { struct MHD_Response *response; struct Request *request; struct GNUNET_CRYPTO_EcdsaPublicKey pub; int ret; if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) || (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) ) { if (0 == strcmp (url, FCFS_ZONEINFO_URL)) ret = serve_zoneinfo_page (connection); else ret = serve_main_page (connection); if (ret != MHD_YES) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to create page for `%s'\n"), url); return ret; } if (0 == strcmp (method, MHD_HTTP_METHOD_POST)) { request = *ptr; if (NULL == request) { request = GNUNET_new (struct Request); *ptr = request; request->pp = MHD_create_post_processor (connection, 1024, &post_iterator, request); if (NULL == request->pp) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to setup post processor for `%s'\n"), url); return MHD_NO; /* internal error */ } return MHD_YES; } if (NULL != request->pp) { /* evaluate POST data */ MHD_post_process (request->pp, upload_data, *upload_data_size); if (0 != *upload_data_size) { *upload_data_size = 0; return MHD_YES; } /* done with POST data, serve response */ MHD_destroy_post_processor (request->pp); request->pp = NULL; } if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (request->public_key, strlen (request->public_key), &pub)) { /* parse error */ return fill_s_reply ("Failed to parse given public key", request, connection); } switch (request->phase) { case RP_START: if (NULL != strchr (request->domain_name, (int) '.')) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Domain name must not contain `.'\n")); request->phase = RP_FAIL; return fill_s_reply ("Domain name must not contain `.', sorry.", request, connection); } if (NULL != strchr (request->domain_name, (int) '+')) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Domain name must not contain `+'\n")); request->phase = RP_FAIL; return fill_s_reply ("Domain name must not contain `+', sorry.", request, connection); } request->phase = RP_LOOKUP; request->qe = GNUNET_NAMESTORE_records_lookup (ns, &fcfs_zone_pkey, request->domain_name, &lookup_block_processor, request); break; case RP_LOOKUP: break; case RP_PUT: break; case RP_FAIL: return fill_s_reply ("Request failed, sorry.", request, connection); case RP_SUCCESS: return fill_s_reply ("Success.", request, connection); default: GNUNET_break (0); return MHD_NO; } return MHD_YES; /* will have a reply later... */ } /* unsupported HTTP method */ response = MHD_create_response_from_buffer (strlen (METHOD_ERROR), (void *) METHOD_ERROR, MHD_RESPMEM_PERSISTENT); ret = MHD_queue_response (connection, MHD_HTTP_METHOD_NOT_ACCEPTABLE, response); MHD_destroy_response (response); return ret; } /** * Callback called upon completion of a request. * Decrements session reference counter. * * @param cls not used * @param connection connection that completed * @param con_cls session handle * @param toe status code */ static void request_completed_callback (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe) { struct Request *request = *con_cls; if (NULL == request) return; if (NULL != request->pp) MHD_destroy_post_processor (request->pp); if (NULL != request->qe) GNUNET_NAMESTORE_cancel (request->qe); GNUNET_free (request); } #define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG /** * Schedule tasks to run MHD server. */ static void run_httpd () { fd_set rs; fd_set ws; fd_set es; struct GNUNET_NETWORK_FDSet *wrs; struct GNUNET_NETWORK_FDSet *wws; struct GNUNET_NETWORK_FDSet *wes; int max; int haveto; UNSIGNED_MHD_LONG_LONG timeout; struct GNUNET_TIME_Relative tv; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); wrs = GNUNET_NETWORK_fdset_create (); wes = GNUNET_NETWORK_fdset_create (); wws = GNUNET_NETWORK_fdset_create (); max = -1; GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max)); haveto = MHD_get_timeout (httpd, &timeout); if (haveto == MHD_YES) tv.rel_value_us = (uint64_t) timeout * 1000LL; else tv = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1); httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, tv, wrs, wws, &do_httpd, NULL); GNUNET_NETWORK_fdset_destroy (wrs); GNUNET_NETWORK_fdset_destroy (wws); GNUNET_NETWORK_fdset_destroy (wes); } /** * Task run whenever HTTP server operations are pending. * * @param cls unused * @param tc scheduler context */ static void do_httpd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { httpd_task = GNUNET_SCHEDULER_NO_TASK; MHD_run (httpd); run_httpd (); } /** * Task run on shutdown. Cleans up everything. * * @param cls unused * @param tc scheduler context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != httpd_task) { GNUNET_SCHEDULER_cancel (httpd_task); httpd_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != ns) { GNUNET_NAMESTORE_disconnect (ns); ns = NULL; } if (NULL != httpd) { MHD_stop_daemon (httpd); httpd = NULL; } if (NULL != id_op) { GNUNET_IDENTITY_cancel (id_op); id_op = NULL; } if (NULL != identity) { GNUNET_IDENTITY_disconnect (identity); identity = NULL; } } /** * Method called to inform about the egos of this peer. * * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, * this function is only called ONCE, and 'NULL' being passed in * @a ego does indicate an error (i.e. name is taken or no default * value is known). If @a ego is non-NULL and if '*ctx' * is set in those callbacks, the value WILL be passed to a subsequent * call to the identity callback of #GNUNET_IDENTITY_connect (if * that one was not NULL). * * @param cls closure, NULL * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { int options; id_op = NULL; if (NULL == ego) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No ego configured for `fcfsd` subsystem\n")); return; } fcfs_zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); options = MHD_USE_DUAL_STACK | MHD_USE_DEBUG; do { httpd = MHD_start_daemon (options, (uint16_t) port, NULL, NULL, &create_response, NULL, MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 128, MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (4 * 1024), MHD_OPTION_NOTIFY_COMPLETED, &request_completed_callback, NULL, MHD_OPTION_END); if (MHD_USE_DEBUG == options) break; options = MHD_USE_DEBUG; } while (NULL == httpd); if (NULL == httpd) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start HTTP server\n")); GNUNET_SCHEDULER_shutdown (); return; } run_httpd (); } /** * Main function that will be run. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "fcfsd", "HTTPPORT", &port)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "fcfsd", "HTTPPORT"); return; } ns = GNUNET_NAMESTORE_connect (cfg); if (NULL == ns) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to namestore\n")); return; } identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); if (NULL == identity) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to identity\n")); return; } id_op = GNUNET_IDENTITY_get (identity, "fcfsd", &identity_cb, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); } /** * The main function for the fcfs daemon. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; GNUNET_log_setup ("fcfsd", "WARNING", NULL); ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "fcfsd", _("GNU Name System First Come First Serve name registration service"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); GNUNET_CRYPTO_ecdsa_key_clear (&fcfs_zone_pkey); return ret; } /* end of gnunet-namestore-fcfsd.c */ gnunet-0.10.1/src/namestore/test_namestore_api.conf0000644000175000017500000000053212227705277017345 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-namestore/ [arm] PORT = 12000 DEFAULTSERVICES = namecache namestore [namestore] #PREFIX = valgrind AUTOSTART = YES DATABASE = sqlite [namestore-sqlite] FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db [namestore-postgres] CONFIG = connect_timeout=10; dbname=gnunetcheck TEMPORARY_TABLE = YES gnunet-0.10.1/src/namestore/test_namestore_api_store.c0000644000175000017500000001062112251551532020044 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_store.c * @brief testcase for namestore_api.c: store a record */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle *nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; static char *directory; static void cleanup () { if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } static void put_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; nsqe = NULL; GNUNET_assert (NULL != cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_SCHEDULER_add_now (&end, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_GNSRECORD_Data rd; char *hostkey_file; const char * name = "dummy.dummy.gnunet"; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); rd.expiration_time = GNUNET_TIME_absolute_get().abs_value_us; rd.record_type = TEST_RECORD_TYPE; rd.data_size = TEST_RECORD_DATALEN; rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); rd.flags = 0; memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 1, &rd, &put_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } GNUNET_free ((void *)rd.data); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_store.c */ gnunet-0.10.1/src/namestore/zonefiles/0000755000175000017500000000000012320755627014665 500000000000000gnunet-0.10.1/src/namestore/zonefiles/S5I9DSGQVAB5FVV16T3B3CC5H1B2JGL3Q412JBKURME8EKU0600G.zkey0000644000175000017500000000147312164257527024365 00000000000000;(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:Ét¦÷>‹‹¾ì¹´Šçkê×SErã•§ú:&£ÊB˜`aùúÉ¿Î_Ê×QVY¬ Þ…33U{‹™¨;D ä¢ßº) (5:curve10:NIST P-256) ) ) (11:private-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:Ét¦÷>‹‹¾ì¹´Šçkê×SErã•§ú:&£ÊB˜`aùúÉ¿Î_Ê×QVY¬ Þ…33U{‹™¨;D ä¢ßº) (1:d33:ûûEÁ5Œ¥ ¡¦Ò=“Ðv…Š=2ÆnÇ´gna¤ÞðQ) ) ) ) gnunet-0.10.1/src/namestore/zonefiles/N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey0000644000175000017500000000147212164257527024313 00000000000000:(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:§ª L“ÛFßhw‚O‘r­`¯©çÚ›' á¨TÇÔ°7’ý'Ю? ^7ž8ý_%œ­YÍâíûÀü•l?¡) (5:curve10:NIST P-256) ) ) (11:private-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:§ª L“ÛFßhw‚O‘r­`¯©çÚ›' á¨TÇÔ°7’ý'Ю? ^7ž8ý_%œ­YÍâíûÀü•l?¡) (1:d32:\vBf€ f5#Óƒ¬«MK$åîÄÖk³à6›¨Ïrd) ) ) ) gnunet-0.10.1/src/namestore/zonefiles/HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey0000644000175000017500000000147312164257527024632 00000000000000;(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:Ét¦÷>‹‹¾ì¹´Šçkê×SErã•§ú:&£ÊB˜`aùúÉ¿Î_Ê×QVY¬ Þ…33U{‹™¨;D ä¢ßº) (5:curve10:NIST P-256) ) ) (11:private-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:Ét¦÷>‹‹¾ì¹´Šçkê×SErã•§ú:&£ÊB˜`aùúÉ¿Î_Ê×QVY¬ Þ…33U{‹™¨;D ä¢ßº) (1:d33:ûûEÁ5Œ¥ ¡¦Ò=“Ðv…Š=2ÆnÇ´gna¤ÞðQ) ) ) ) gnunet-0.10.1/src/namestore/zonefiles/AQ835GVL939H4O8QJQ7GBLPTQC0QAAO91BN7QK01BA63MDSK6I4G.zkey0000644000175000017500000000147212164257527024406 00000000000000:(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:§ª L“ÛFßhw‚O‘r­`¯©çÚ›' á¨TÇÔ°7’ý'Ю? ^7ž8ý_%œ­YÍâíûÀü•l?¡) (5:curve10:NIST P-256) ) ) (11:private-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:§ª L“ÛFßhw‚O‘r­`¯©çÚ›' á¨TÇÔ°7’ý'Ю? ^7ž8ý_%œ­YÍâíûÀü•l?¡) (1:d32:\vBf€ f5#Óƒ¬«MK$åîÄÖk³à6›¨Ïrd) ) ) ) gnunet-0.10.1/src/namestore/test_namestore_api_lookup_shadow.c0000644000175000017500000001623112251551532021571 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_lookup_shadow_filter.c * @brief testcase for namestore_api.c: store a shadow record and perform a lookup * test passes if test returns the record but without the shadow flag since no * other valid record is available */ #include "platform.h" #include "gnunet_namecache_service.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle *nsh; static struct GNUNET_NAMECACHE_Handle *nch; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey; static struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; static int res; static struct GNUNET_NAMESTORE_QueueEntry *nsqe; static struct GNUNET_NAMECACHE_QueueEntry *ncqe; static char *directory; static void cleanup () { if (NULL != nsh) { GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } if (NULL != nch) { GNUNET_NAMECACHE_disconnect (nch); nch = NULL; } if (NULL != privkey) { GNUNET_free (privkey); privkey = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nsqe) { GNUNET_NAMESTORE_cancel (nsqe); nsqe = NULL; } if (NULL != ncqe) { GNUNET_NAMECACHE_cancel (ncqe); ncqe = NULL; } cleanup (); res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } static void rd_decrypt_cb (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { char rd_cmp_data[TEST_RECORD_DATALEN]; if (1 != rd_count) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (NULL == rd) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN); if (TEST_RECORD_TYPE != rd[0].record_type) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (TEST_RECORD_DATALEN != rd[0].data_size) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN)) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags)) { GNUNET_SCHEDULER_add_now (&endbadly, NULL); GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Block was decrypted successfully \n"); GNUNET_SCHEDULER_add_now (&end, NULL); } static void name_lookup_proc (void *cls, const struct GNUNET_GNSRECORD_Block *block) { const char *name = cls; ncqe = NULL; GNUNET_assert (NULL != cls); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL == block) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore returned no block\n")); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore returned block, decrypting \n"); GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt(block, &pubkey, name, &rd_decrypt_cb, (void *) name)); } static void put_cont (void *cls, int32_t success, const char *emsg) { const char *name = cls; struct GNUNET_HashCode derived_hash; struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; nsqe = NULL; GNUNET_assert (NULL != cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Name store added record for `%s': %s\n", name, (success == GNUNET_OK) ? "SUCCESS" : "FAIL"); /* Create derived hash */ GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); GNUNET_GNSRECORD_query_from_public_key (&pubkey, name, &derived_hash); ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash, &name_lookup_proc, (void *) name); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_GNSRECORD_Data rd; char *hostkey_file; const char * name = "dummy.dummy.gnunet"; directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); GNUNET_asprintf (&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file (hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_CRYPTO_ecdsa_key_get_public (privkey, &pubkey); rd.expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 1000000000; rd.record_type = TEST_RECORD_TYPE; rd.data_size = TEST_RECORD_DATALEN; rd.data = GNUNET_malloc (TEST_RECORD_DATALEN); rd.flags = GNUNET_GNSRECORD_RF_SHADOW_RECORD; memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN); nsh = GNUNET_NAMESTORE_connect (cfg); nch = GNUNET_NAMECACHE_connect (cfg); GNUNET_break (NULL != nsh); GNUNET_break (NULL != nch); nsqe = GNUNET_NAMESTORE_records_store (nsh, privkey, name, 1, &rd, &put_cont, (void *) name); if (NULL == nsqe) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Namestore cannot store no block\n")); } GNUNET_free ((void *)rd.data); } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_lookup_shadow_filter.c */ gnunet-0.10.1/src/namestore/plugin_namestore_postgres.c0000644000175000017500000004375512254263402020261 00000000000000 /* * This file is part of GNUnet * (C) 2009-2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file namestore/plugin_namestore_postgres.c * @brief postgres-based namestore backend * @author Christian Grothoff */ #include "platform.h" #include "gnunet_namestore_plugin.h" #include "gnunet_namestore_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_postgres_lib.h" #include "namestore.h" /** * After how many ms "busy" should a DB operation fail for good? * A low value makes sure that we are more responsive to requests * (especially PUTs). A high value guarantees a higher success * rate (SELECTs in iterate can take several seconds despite LIMIT=1). * * The default value of 1s should ensure that users do not experience * huge latencies while at the same time allowing operations to succeed * with reasonable probability. */ #define BUSY_TIMEOUT_MS 1000 /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_POSTGRES(db, level, cmd) do { GNUNET_log_from (level, "namestore-postgres", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) #define LOG(kind,...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__) /** * Context for all functions in this plugin. */ struct Plugin { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Native Postgres database handle. */ PGconn *dbh; }; /** * Create our database indices. * * @param dbh handle to the database */ static void create_indices (PGconn * dbh) { /* create indices */ if ( (GNUNET_OK != GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_pkey_reverse ON ns097records (zone_private_key,pkey)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_pkey_iter ON ns097records (zone_private_key,rvalue)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (dbh, "CREATE INDEX it_iter ON ns097records (rvalue)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (dbh, "CREATE INDEX ir_label ON ns097records (label)")) ) LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to create indices\n")); } /** * Initialize the database connections and associated * data structures (create tables and indices * as needed as well). * * @param plugin the plugin context (state for this module) * @return #GNUNET_OK on success */ static int database_setup (struct Plugin *plugin) { PGresult *res; plugin->dbh = GNUNET_POSTGRES_connect (plugin->cfg, "namestore-postgres"); if (NULL == plugin->dbh) return GNUNET_SYSERR; if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg, "namestore-postgres", "TEMPORARY_TABLE")) { res = PQexec (plugin->dbh, "CREATE TEMPORARY TABLE ns097records (" " zone_private_key BYTEA NOT NULL DEFAULT ''," " pkey BYTEA DEFAULT ''," " rvalue BYTEA NOT NULL DEFAULT ''," " record_count INTEGER NOT NULL DEFAULT 0," " record_data BYTEA NOT NULL DEFAULT ''," " label TEXT NOT NULL DEFAULT ''" ")" "WITH OIDS"); } else { res = PQexec (plugin->dbh, "CREATE TABLE ns097records (" " zone_private_key BYTEA NOT NULL DEFAULT ''," " pkey BYTEA DEFAULT ''," " rvalue BYTEA NOT NULL DEFAULT ''," " record_count INTEGER NOT NULL DEFAULT 0," " record_data BYTEA NOT NULL DEFAULT ''," " label TEXT NOT NULL DEFAULT ''" ")" "WITH OIDS"); } if ( (NULL == res) || ((PQresultStatus (res) != PGRES_COMMAND_OK) && (0 != strcmp ("42P07", /* duplicate table */ PQresultErrorField (res, PG_DIAG_SQLSTATE))))) { (void) GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_COMMAND_OK, "CREATE TABLE", "ns097records"); PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } create_indices (plugin->dbh); if ((GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "store_records", "INSERT INTO ns097records (zone_private_key, pkey, rvalue, record_count, record_data, label) VALUES " "($1, $2, $3, $4, $5, $6)", 6)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "delete_records", "DELETE FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "zone_to_name", "SELECT record_count,record_data,label FROM ns097records" " WHERE zone_private_key=$1 AND pkey=$2", 2)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "iterate_zone", "SELECT record_count,record_data,label FROM ns097records" " WHERE zone_private_key=$1 ORDER BY rvalue LIMIT 1 OFFSET $2", 2)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "iterate_all_zones", "SELECT record_count,record_data,label,zone_private_key" " FROM ns097records ORDER BY rvalue LIMIT 1 OFFSET $1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "lookup_label", "SELECT record_count,record_data,label" " FROM ns097records WHERE zone_private_key=$1 AND label=$2", 2))) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } return GNUNET_OK; } /** * Store a record in the datastore. Removes any existing record in the * same zone with the same name. * * @param cls closure (internal context for the plugin) * @param zone_key private key of the zone * @param label name that is being mapped (at most 255 characters long) * @param rd_count number of entries in @a rd array * @param rd array of records with data to store * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int namestore_postgres_store_records (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { struct Plugin *plugin = cls; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; uint64_t rvalue; uint32_t rd_count_nbo = htonl ((uint32_t) rd_count); size_t data_size; unsigned int i; memset (&pkey, 0, sizeof (pkey)); for (i=0;i 64 * 65536) { GNUNET_break (0); return GNUNET_SYSERR; } { char data[data_size]; const char *paramValues[] = { (const char *) zone_key, (const char *) &pkey, (const char *) &rvalue, (const char *) &rd_count_nbo, (const char *) data, label }; int paramLengths[] = { sizeof (*zone_key), sizeof (pkey), sizeof (rvalue), sizeof (rd_count_nbo), data_size, strlen (label) }; const int paramFormats[] = { 1, 1, 1, 1, 1, 1 }; PGresult *res; if (data_size != GNUNET_GNSRECORD_records_serialize (rd_count, rd, data_size, data)) { GNUNET_break (0); return GNUNET_SYSERR; } res = PQexecPrepared (plugin->dbh, "store_records", 6, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_COMMAND_OK, "PQexecPrepared", "store_records")) return GNUNET_SYSERR; PQclear (res); return GNUNET_OK; } } /** * A statement has been run. We should evaluate the result, and if possible * call the given @a iter with the result. * * @param plugin plugin context * @param res result from the statement that was run (to be cleaned up) * @param zone_key private key of the zone, could be NULL, in which case we should * get the zone from @a res * @param iter iterator to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int get_record_and_call_iterator (struct Plugin *plugin, PGresult *res, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { const char *data; size_t data_size; uint32_t record_count; const char *label; size_t label_len; unsigned int cnt; if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", "iteration")) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failing lookup (postgres error)\n"); return GNUNET_SYSERR; } if (0 == (cnt = PQntuples (res))) { /* no result */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Ending iteration (no more results)\n"); PQclear (res); return GNUNET_NO; } GNUNET_assert (1 == cnt); GNUNET_assert (3 + ((NULL == zone_key) ? 1 : 0) == PQnfields (res)); if (NULL == zone_key) { if (sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) != PQgetlength (res, 0, 3)) { GNUNET_break (0); PQclear (res); return GNUNET_SYSERR; } zone_key = (const struct GNUNET_CRYPTO_EcdsaPrivateKey *) PQgetvalue (res, 0, 3); } if (sizeof (uint32_t) != PQfsize (res, 0)) { GNUNET_break (0); PQclear (res); return GNUNET_SYSERR; } record_count = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); data = PQgetvalue (res, 0, 1); data_size = PQgetlength (res, 0, 1); label = PQgetvalue (res, 0, 2); label_len = PQgetlength (res, 0, 1); if (record_count > 64 * 1024) { /* sanity check, don't stack allocate far too much just because database might contain a large value here */ GNUNET_break (0); PQclear (res); return GNUNET_SYSERR; } { struct GNUNET_GNSRECORD_Data rd[record_count]; char buf[label_len + 1]; memcpy (buf, label, label_len); buf[label_len] = '\0'; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (data_size, data, record_count, rd)) { GNUNET_break (0); PQclear (res); return GNUNET_SYSERR; } iter (iter_cls, zone_key, buf, record_count, rd); } PQclear (res); return GNUNET_OK; } /** * Lookup records in the datastore for which we are the authority. * * @param cls closure (internal context for the plugin) * @param zone private key of the zone * @param label name of the record in the zone * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, else #GNUNET_SYSERR */ static int namestore_postgres_lookup_records (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { struct Plugin *plugin = cls; const char *paramValues[] = { (const char *) zone, label }; int paramLengths[] = { sizeof (*zone), strlen (label) }; const int paramFormats[] = { 1, 1 }; PGresult *res; res = PQexecPrepared (plugin->dbh, "lookup_label", 2, paramValues, paramLengths, paramFormats, 1); return get_record_and_call_iterator (plugin, res, zone, iter, iter_cls); } /** * Iterate over the results for a particular key and zone in the * datastore. Will return at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param zone hash of public key of the zone, NULL to iterate over all zones * @param offset offset in the list of all matching records * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int namestore_postgres_iterate_records (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, uint64_t offset, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { struct Plugin *plugin = cls; uint64_t offset_be = GNUNET_htonll (offset); if (NULL == zone) { const char *paramValues[] = { (const char *) &offset_be }; int paramLengths[] = { sizeof (offset_be) }; const int paramFormats[] = { 1 }; PGresult *res; res = PQexecPrepared (plugin->dbh, "iterate_all_zones", 1, paramValues, paramLengths, paramFormats, 1); return get_record_and_call_iterator (plugin, res, NULL, iter, iter_cls); } else { const char *paramValues[] = { (const char *) zone, (const char *) &offset_be }; int paramLengths[] = { sizeof (*zone), sizeof (offset_be) }; const int paramFormats[] = { 1, 1 }; PGresult *res; res = PQexecPrepared (plugin->dbh, "iterate_zone", 2, paramValues, paramLengths, paramFormats, 1); return get_record_and_call_iterator (plugin, res, zone, iter, iter_cls); } } /** * Look for an existing PKEY delegation record for a given public key. * Returns at most one result to the iterator. * * @param cls closure (internal context for the plugin) * @param zone private key of the zone to look up in, never NULL * @param value_zone public key of the target zone (value), never NULL * @param iter function to call with the result * @param iter_cls closure for @a iter * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error */ static int namestore_postgres_zone_to_name (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) { struct Plugin *plugin = cls; const char *paramValues[] = { (const char *) zone, (const char *) value_zone }; int paramLengths[] = { sizeof (*zone), sizeof (*value_zone) }; const int paramFormats[] = { 1, 1 }; PGresult *res; res = PQexecPrepared (plugin->dbh, "zone_to_name", 2, paramValues, paramLengths, paramFormats, 1); return get_record_and_call_iterator (plugin, res, zone, iter, iter_cls); } /** * Shutdown database connection and associate data * structures. * * @param plugin the plugin context (state for this module) */ static void database_shutdown (struct Plugin *plugin) { PQfinish (plugin->dbh); plugin->dbh = NULL; } /** * Entry point for the plugin. * * @param cls the `struct GNUNET_NAMESTORE_PluginEnvironment*` * @return NULL on error, othrewise the plugin context */ void * libgnunet_plugin_namestore_postgres_init (void *cls) { static struct Plugin plugin; const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_NAMESTORE_PluginFunctions *api; if (NULL != plugin.cfg) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); plugin.cfg = cfg; if (GNUNET_OK != database_setup (&plugin)) { database_shutdown (&plugin); return NULL; } api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); api->cls = &plugin; api->store_records = &namestore_postgres_store_records; api->iterate_records = &namestore_postgres_iterate_records; api->zone_to_name = &namestore_postgres_zone_to_name; api->lookup_records = &namestore_postgres_lookup_records; LOG (GNUNET_ERROR_TYPE_INFO, _("Postgres database running\n")); return api; } /** * Exit point from the plugin. * * @param cls the plugin context (as returned by "init") * @return always NULL */ void * libgnunet_plugin_namestore_postgres_done (void *cls) { struct GNUNET_NAMESTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; database_shutdown (plugin); plugin->cfg = NULL; GNUNET_free (api); LOG (GNUNET_ERROR_TYPE_DEBUG, "postgres plugin is finished\n"); return NULL; } /* end of plugin_namestore_postgres.c */ gnunet-0.10.1/src/namestore/test_namestore_api_zone_iteration_specific_zone.c0000644000175000017500000002640412251551532024647 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file namestore/test_namestore_api_zone_iteration_specific_zone.c * @brief testcase for zone iteration functionality: iterate over a specific zone */ #include "platform.h" #include "gnunet_namestore_service.h" #include "gnunet_testing_lib.h" #include "namestore.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static struct GNUNET_NAMESTORE_Handle * nsh; static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey2; static struct GNUNET_NAMESTORE_ZoneIterator *zi; static int res; static int returned_records; static char * s_name_1; static struct GNUNET_GNSRECORD_Data *s_rd_1; static char * s_name_2; static struct GNUNET_GNSRECORD_Data *s_rd_2; static char * s_name_3; static struct GNUNET_GNSRECORD_Data *s_rd_3; static char *directory; /** * Re-establish the connection to the service. * * @param cls handle to use to re-connect. * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != zi) { GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; } if (nsh != NULL) GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; GNUNET_free_non_null(s_name_1); GNUNET_free_non_null(s_name_2); GNUNET_free_non_null(s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (privkey != NULL) GNUNET_free (privkey); privkey = NULL; if (privkey2 != NULL) GNUNET_free (privkey2); privkey2 = NULL; res = 1; } static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != zi) { GNUNET_NAMESTORE_zone_iteration_stop (zi); zi = NULL; } if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } if (privkey != NULL) GNUNET_free (privkey); privkey = NULL; if (privkey2 != NULL) GNUNET_free (privkey2); privkey2 = NULL; GNUNET_free (s_name_1); GNUNET_free (s_name_2); GNUNET_free (s_name_3); if (s_rd_1 != NULL) { GNUNET_free ((void *)s_rd_1->data); GNUNET_free (s_rd_1); } if (s_rd_2 != NULL) { GNUNET_free ((void *)s_rd_2->data); GNUNET_free (s_rd_2); } if (s_rd_3 != NULL) { GNUNET_free ((void *)s_rd_3->data); GNUNET_free (s_rd_3); } if (nsh != NULL) GNUNET_NAMESTORE_disconnect (nsh); nsh = NULL; } static void zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { int failed = GNUNET_NO; if ((zone == NULL) && (label == NULL)) { GNUNET_break (2 == returned_records); if (2 == returned_records) { res = 0; /* Last iteraterator callback, we are done */ zi = NULL; } else res = 1; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received last result, iteration done after receing %u results\n", returned_records ); GNUNET_SCHEDULER_add_now (&end, NULL); return; } else { if (0 == memcmp (zone, privkey, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { if (0 == strcmp (label, s_name_1)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_1)) { failed = GNUNET_YES; GNUNET_break (0); } } else { failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == strcmp (label, s_name_2)) { if (rd_count == 1) { if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp(rd, s_rd_2)) { failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid record count\n"); failed = GNUNET_YES; GNUNET_break (0); } } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing result failed: got name `%s' for first zone\n", label); failed = GNUNET_YES; GNUNET_break (0); } } else if (0 == memcmp (zone, privkey2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received data for not requested zone\n"); failed = GNUNET_YES; GNUNET_break (0); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Received invalid zone\n"); failed = GNUNET_YES; GNUNET_break (0); } } if (failed == GNUNET_NO) { returned_records ++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Telling namestore to send the next result\n"); GNUNET_NAMESTORE_zone_iterator_next (zi); } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (&end, NULL); } } static void put_cont (void *cls, int32_t success, const char *emsg) { static int c = 0; if (success == GNUNET_OK) { c++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n", emsg); GNUNET_break (0); if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if (c == 3) { res = 1; returned_records = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All records created, starting iteration over all zones \n"); zi = GNUNET_NAMESTORE_zone_iteration_start(nsh, privkey, &zone_proc, NULL); if (zi == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); GNUNET_break (0); if (GNUNET_SCHEDULER_NO_TASK != endbadly_task) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } } } static struct GNUNET_GNSRECORD_Data * create_record (unsigned int count) { unsigned int c; struct GNUNET_GNSRECORD_Data * rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS).abs_value_us; rd[c].record_type = 1111; rd[c].data_size = 50; rd[c].data = GNUNET_malloc(50); rd[c].flags = 0; memset ((char *) rd[c].data, 'a', 50); } return rd; } /** * Callback called from the zone iterator when we iterate over * the empty zone. Check that we got no records and then * start the actual tests by filling the zone. */ static void empty_zone_proc (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { char *hostkey_file; GNUNET_assert (nsh == cls); if (NULL != zone) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Expected empty zone but received zone private key\n")); GNUNET_break (0); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } if ((NULL != label) || (NULL != rd) || (0 != rd_count)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Expected no zone content but received data\n")); GNUNET_break (0); if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); return; } zi = NULL; GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); GNUNET_asprintf(&hostkey_file,"zonefiles%s%s",DIR_SEPARATOR_STR, "HGU0A0VCU334DN7F2I9UIUMVQMM7JMSD142LIMNUGTTV9R0CF4EG.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s' \n", hostkey_file); privkey2 = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey2 != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n"); GNUNET_asprintf(&s_name_1, "dummy1"); s_rd_1 = create_record(1); GNUNET_NAMESTORE_records_store(nsh, privkey, s_name_1, 1, s_rd_1, &put_cont, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n"); GNUNET_asprintf(&s_name_2, "dummy2"); s_rd_2 = create_record(1); GNUNET_NAMESTORE_records_store(nsh, privkey, s_name_2, 1, s_rd_2, &put_cont, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 3\n"); /* name in different zone */ GNUNET_asprintf(&s_name_3, "dummy3"); s_rd_3 = create_record(1); GNUNET_NAMESTORE_records_store(nsh, privkey2, s_name_3, 1, s_rd_3, &put_cont, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { directory = NULL; GNUNET_CONFIGURATION_get_value_string(cfg, "PATHS", "GNUNET_TEST_HOME", &directory); GNUNET_DISK_directory_remove (directory); endbadly_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT, &endbadly, NULL); nsh = GNUNET_NAMESTORE_connect (cfg); GNUNET_break (NULL != nsh); /* first, iterate over empty namestore */ zi = GNUNET_NAMESTORE_zone_iteration_start (nsh, NULL, &empty_zone_proc, nsh); if (NULL == zi) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n"); GNUNET_break (0); GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL); } } int main (int argc, char *argv[]) { res = 1; if (0 != GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration", "test_namestore_api.conf", &run, NULL)) { res = 1; } if (NULL != directory) { GNUNET_DISK_directory_remove (directory); GNUNET_free (directory); } return res; } /* end of test_namestore_api_zone_iteration_specific_zone.c */ gnunet-0.10.1/src/block/0000755000175000017500000000000012320755622011757 500000000000000gnunet-0.10.1/src/block/plugin_block_template.c0000644000175000017500000001010112255010512016364 00000000000000/* This file is part of GNUnet (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file block/plugin_block_template.c * @brief template for a block plugin * @author Christian Grothoff */ #include "platform.h" #include "gnunet_block_plugin.h" #define DEBUG_TEMPLATE GNUNET_EXTRA_LOGGING /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for bf * @param xquery extrended query data (can be NULL, depending on type) * @param xquery_size number of bytes in xquery * @param reply_block response to validate * @param reply_block_size number of bytes in reply block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult block_plugin_template_evaluate (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { struct GNUNET_HashCode chash; struct GNUNET_HashCode mhash; /* FIXME: check validity first... */ /* mandatory duplicate-detection code... */ if (NULL != bf) { GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); if (NULL != *bf) { if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; } else { *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, 64 /* BLOOMFILTER_K */); } GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); } /* FIXME: other stuff here... */ return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; } /** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param block block to get the key for * @param block_size number of bytes in block * @param key set to the key (query) for the given block * @return GNUNET_OK on success, GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int block_plugin_template_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode * key) { return GNUNET_SYSERR; } /** * Entry point for the plugin. */ void * libgnunet_plugin_block_template_init (void *cls) { static enum GNUNET_BLOCK_Type types[] = { /* FIXME: insert supported block types here */ GNUNET_BLOCK_TYPE_ANY /* end of list */ }; struct GNUNET_BLOCK_PluginFunctions *api; api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_template_evaluate; api->get_key = &block_plugin_template_get_key; api->types = types; return api; } /** * Exit point from the plugin. */ void * libgnunet_plugin_block_template_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_block_template.c */ gnunet-0.10.1/src/block/Makefile.in0000644000175000017500000006526212320752060013750 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = src/block DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunet_plugin_block_template_la_OBJECTS = \ plugin_block_template.lo libgnunet_plugin_block_template_la_OBJECTS = \ $(am_libgnunet_plugin_block_template_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_block_template_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_block_template_la_LDFLAGS) $(LDFLAGS) -o $@ am_libgnunet_plugin_block_test_la_OBJECTS = plugin_block_test.lo libgnunet_plugin_block_test_la_OBJECTS = \ $(am_libgnunet_plugin_block_test_la_OBJECTS) libgnunet_plugin_block_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_block_test_la_LDFLAGS) $(LDFLAGS) -o $@ am_libgnunetblock_la_OBJECTS = block.lo libgnunetblock_la_OBJECTS = $(am_libgnunetblock_la_OBJECTS) libgnunetblock_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetblock_la_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_block_template_la_SOURCES) \ $(libgnunet_plugin_block_test_la_SOURCES) \ $(libgnunetblock_la_SOURCES) DIST_SOURCES = $(libgnunet_plugin_block_template_la_SOURCES) \ $(libgnunet_plugin_block_test_la_SOURCES) \ $(libgnunetblock_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage lib_LTLIBRARIES = libgnunetblock.la plugin_LTLIBRARIES = \ libgnunet_plugin_block_template.la \ libgnunet_plugin_block_test.la libgnunet_plugin_block_template_la_SOURCES = \ plugin_block_template.c libgnunet_plugin_block_template_la_LIBADD = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_template_la_DEPENDENCIES = \ libgnunetblock.la libgnunet_plugin_block_test_la_SOURCES = \ plugin_block_test.c libgnunet_plugin_block_test_la_LIBADD = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_test_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_test_la_DEPENDENCIES = \ libgnunetblock.la libgnunetblock_la_SOURCES = \ block.c libgnunetblock_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetblock_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetblock_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/block/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/block/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_block_template.la: $(libgnunet_plugin_block_template_la_OBJECTS) $(libgnunet_plugin_block_template_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_block_template_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_block_template_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_template_la_OBJECTS) $(libgnunet_plugin_block_template_la_LIBADD) $(LIBS) libgnunet_plugin_block_test.la: $(libgnunet_plugin_block_test_la_OBJECTS) $(libgnunet_plugin_block_test_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_block_test_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_block_test_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_test_la_OBJECTS) $(libgnunet_plugin_block_test_la_LIBADD) $(LIBS) libgnunetblock.la: $(libgnunetblock_la_OBJECTS) $(libgnunetblock_la_DEPENDENCIES) $(EXTRA_libgnunetblock_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetblock_la_LINK) -rpath $(libdir) $(libgnunetblock_la_OBJECTS) $(libgnunetblock_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/block.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_template.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_test.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-pluginLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-pluginLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-man install-pdf install-pdf-am \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/block/Makefile.am0000644000175000017500000000246112320751517013735 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage endif lib_LTLIBRARIES = libgnunetblock.la plugin_LTLIBRARIES = \ libgnunet_plugin_block_template.la \ libgnunet_plugin_block_test.la libgnunet_plugin_block_template_la_SOURCES = \ plugin_block_template.c libgnunet_plugin_block_template_la_LIBADD = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_template_la_DEPENDENCIES = \ libgnunetblock.la libgnunet_plugin_block_test_la_SOURCES = \ plugin_block_test.c libgnunet_plugin_block_test_la_LIBADD = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_test_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_test_la_DEPENDENCIES = \ libgnunetblock.la libgnunetblock_la_SOURCES = \ block.c libgnunetblock_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetblock_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la libgnunetblock_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 gnunet-0.10.1/src/block/block.c0000644000175000017500000002074512225777502013152 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file block/block.c * @brief library for data block manipulation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_block_lib.h" #include "gnunet_block_plugin.h" /** * Handle for a plugin. */ struct Plugin { /** * Name of the shared library. */ char *library_name; /** * Plugin API. */ struct GNUNET_BLOCK_PluginFunctions *api; }; /** * Handle to an initialized block library. */ struct GNUNET_BLOCK_Context { /** * Array of our plugins. */ struct Plugin **plugins; /** * Size of the 'plugins' array. */ unsigned int num_plugins; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; }; /** * Mingle hash with the mingle_number to produce different bits. * * @param in original hash code * @param mingle_number number for hash permutation * @param hc where to store the result. */ void GNUNET_BLOCK_mingle_hash (const struct GNUNET_HashCode *in, uint32_t mingle_number, struct GNUNET_HashCode *hc) { struct GNUNET_HashCode m; GNUNET_CRYPTO_hash (&mingle_number, sizeof (uint32_t), &m); GNUNET_CRYPTO_hash_xor (&m, in, hc); } /** * Add a plugin to the list managed by the block library. * * @param cls the block context * @param library_name name of the plugin * @param lib_ret the plugin API */ static void add_plugin (void *cls, const char *library_name, void *lib_ret) { struct GNUNET_BLOCK_Context *ctx = cls; struct GNUNET_BLOCK_PluginFunctions *api = lib_ret; struct Plugin *plugin; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading block plugin `%s'\n", library_name); plugin = GNUNET_new (struct Plugin); plugin->api = api; plugin->library_name = GNUNET_strdup (library_name); GNUNET_array_append (ctx->plugins, ctx->num_plugins, plugin); } /** * Create a block context. Loads the block plugins. * * @param cfg configuration to use * @return NULL on error */ struct GNUNET_BLOCK_Context * GNUNET_BLOCK_context_create (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_BLOCK_Context *ctx; ctx = GNUNET_new (struct GNUNET_BLOCK_Context); ctx->cfg = cfg; GNUNET_PLUGIN_load_all ("libgnunet_plugin_block_", NULL, &add_plugin, ctx); return ctx; } /** * Destroy the block context. * * @param ctx context to destroy */ void GNUNET_BLOCK_context_destroy (struct GNUNET_BLOCK_Context *ctx) { unsigned int i; struct Plugin *plugin; for (i = 0; i < ctx->num_plugins; i++) { plugin = ctx->plugins[i]; GNUNET_break (NULL == GNUNET_PLUGIN_unload (plugin->library_name, plugin->api)); GNUNET_free (plugin->library_name); GNUNET_free (plugin); } GNUNET_free (ctx->plugins); GNUNET_free (ctx); } /** * Find a plugin for the given type. * * @param ctx context to search * @param type type to look for * @return NULL if no matching plugin exists */ static struct GNUNET_BLOCK_PluginFunctions * find_plugin (struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type) { struct Plugin *plugin; unsigned int i; unsigned int j; for (i = 0; i < ctx->num_plugins; i++) { plugin = ctx->plugins[i]; j = 0; while (0 != (plugin->api->types[j])) { if (type == plugin->api->types[j]) return plugin->api; j++; } } return NULL; } /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * Note that it is assumed that the reply has already been * matched to the key (and signatures checked) as it would * be done with the "get_key" function. * * @param ctx block contxt * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for @a bf * @param xquery extended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param reply_block response to validate * @param reply_block_size number of bytes in @a reply_block * @return characterization of result */ enum GNUNET_BLOCK_EvaluationResult GNUNET_BLOCK_evaluate (struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx, type); if (plugin == NULL) return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; return plugin->evaluate (plugin->cls, type, query, bf, bf_mutator, xquery, xquery_size, reply_block, reply_block_size); } /** * Function called to obtain the key for a block. * * @param ctx block context * @param type block type * @param block block to get the key for * @param block_size number of bytes in @a block * @param key set to the key (query) for the given block * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ int GNUNET_BLOCK_get_key (struct GNUNET_BLOCK_Context *ctx, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode * key) { struct GNUNET_BLOCK_PluginFunctions *plugin = find_plugin (ctx, type); if (plugin == NULL) return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; return plugin->get_key (plugin->cls, type, block, block_size, key); } /** * How many bytes should a bloomfilter be if we have already seen * entry_count responses? Note that GNUNET_CONSTANTS_BLOOMFILTER_K gives us the number * of bits set per entry. Furthermore, we should not re-size the * filter too often (to keep it cheap). * * Since other peers will also add entries but not resize the filter, * we should generally pick a slightly larger size than what the * strict math would suggest. * * @param entry_count expected number of entries in the Bloom filter * @return must be a power of two and smaller or equal to 2^15. */ static size_t compute_bloomfilter_size (unsigned int entry_count) { size_t size; unsigned int ideal = (entry_count * GNUNET_CONSTANTS_BLOOMFILTER_K) / 4; uint16_t max = 1 << 15; if (entry_count > max) return max; size = 8; while ((size < max) && (size < ideal)) size *= 2; if (size > max) return max; return size; } /** * Construct a bloom filter that would filter out the given * results. * * @param bf_mutator mutation value to use * @param seen_results results already seen * @param seen_results_count number of entries in @a seen_results * @return NULL if seen_results_count is 0, otherwise a BF * that would match the given results. */ struct GNUNET_CONTAINER_BloomFilter * GNUNET_BLOCK_construct_bloomfilter (int32_t bf_mutator, const struct GNUNET_HashCode * seen_results, unsigned int seen_results_count) { struct GNUNET_CONTAINER_BloomFilter *bf; struct GNUNET_HashCode mhash; unsigned int i; size_t nsize; nsize = compute_bloomfilter_size (seen_results_count); bf = GNUNET_CONTAINER_bloomfilter_init (NULL, nsize, GNUNET_CONSTANTS_BLOOMFILTER_K); for (i = 0; i < seen_results_count; i++) { GNUNET_BLOCK_mingle_hash (&seen_results[i], bf_mutator, &mhash); GNUNET_CONTAINER_bloomfilter_add (bf, &mhash); } return bf; } /* end of block.c */ gnunet-0.10.1/src/block/plugin_block_test.c0000644000175000017500000001106212227705277015561 00000000000000/* This file is part of GNUnet (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file block/plugin_block_test.c * @brief block plugin to test the DHT as a simple key-value store; * this plugin simply accepts any (new) response for any key * @author Christian Grothoff */ #include "platform.h" #include "gnunet_block_plugin.h" /** * Number of bits we set per entry in the bloomfilter. * Do not change! */ #define BLOOMFILTER_K 16 /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for @a bf * @param xquery extrended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param reply_block response to validate * @param reply_block_size number of bytes in @a reply_block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult block_plugin_test_evaluate (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { struct GNUNET_HashCode chash; struct GNUNET_HashCode mhash; if ( GNUNET_BLOCK_TYPE_TEST != type) return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; if (0 != xquery_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } if (NULL == reply_block) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; if (NULL != bf) { GNUNET_CRYPTO_hash (reply_block, reply_block_size, &chash); GNUNET_BLOCK_mingle_hash (&chash, bf_mutator, &mhash); if (NULL != *bf) { if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; } else { *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, BLOOMFILTER_K); } GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); } return GNUNET_BLOCK_EVALUATION_OK_MORE; } /** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param block block to get the key for * @param block_size number of bytes in @a block * @param key set to the key (query) for the given block * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int block_plugin_test_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode * key) { /* always fails since there is no fixed relationship between * keys and values for test values */ return GNUNET_SYSERR; } /** * Entry point for the plugin. * * @param cls NULL * @return the exported block API */ void * libgnunet_plugin_block_test_init (void *cls) { static enum GNUNET_BLOCK_Type types[] = { GNUNET_BLOCK_TYPE_TEST, GNUNET_BLOCK_TYPE_ANY /* end of list */ }; struct GNUNET_BLOCK_PluginFunctions *api; api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_test_evaluate; api->get_key = &block_plugin_test_get_key; api->types = types; return api; } /** * Exit point from the plugin. * * @param cls the return value from #libgnunet_plugin_block_test_init * @return NULL */ void * libgnunet_plugin_block_test_done (void *cls) { struct GNUNET_BLOCK_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_block_test.c */ gnunet-0.10.1/src/integration-tests/0000755000175000017500000000000012320755627014355 500000000000000gnunet-0.10.1/src/integration-tests/confs/0000755000175000017500000000000012320755627015465 500000000000000gnunet-0.10.1/src/integration-tests/confs/c_no_nat_client.conf0000644000175000017500000000361312316473376021400 00000000000000@INLINE@ confs/test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/c_no_nat_client/ [PEER] PRIVATE_KEY = hostkeys/c_no_nat_client [transport] PLUGINS = tcp udp http_client https_client UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-transport-22 PORT = 20029 [transport-tcp] PORT = 20028 ADVERTISED_PORT = 20028 [transport-udp] PORT = 20027 BROADCAST_INTERVAL = 30 s [hostlist] SERVERS = http://localhost:8080/ [nat] BEHIND_NAT = NO DISABLEV6 = NO [arm] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-arm-18 PORT = 20022 [namestore] AUTOSTART = YES [dns] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dns-19 [consensus] AUTOSTART = YES [lockmanager] AUTOSTART = YES [core] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-core-17 PORT = 20021 [ats] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-ats-23 WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB PORT = 20030 [mesh] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-mesh-27 PORT = 20034 [datastore] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-datastore-25 PORT = 20032 [resolver] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-resolver-28 PORT = 20035 [dht] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dht-15 PORT = 20018 [dhtcache] DATABASE = heap QUOTA = 50 MB [gnunet-nat-server] PORT = 20020 [fs] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-fs-20 PORT = 20023 [vpn] UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn-29 [dv] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-b_no_nat_c-1 [peerinfo] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-peerinfo-24 PORT = 20031 [statistics] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-statistics-16 PORT = 20019 [template] PORT = 20024 UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-template-21 [nse] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nse-26 UNIX_MATCH_UID = NO WORKBITS = 22 PORT = 20033 [gns] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-gns-35 PORT = 20038 [dv] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-36 PORT = 20039 gnunet-0.10.1/src/integration-tests/confs/c_bootstrap_server.conf0000644000175000017500000000313612254263402022153 00000000000000@INLINE@ confs/test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/c_bootstrap_server/ [PEER] PRIVATE_KEY = hostkeys/c_bootstrap_server [transport] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-transport-8 PORT = 20011 PLUGINS = tcp udp http_client https_client http_server https_server [transport-tcp] PORT = 20010 ADVERTISED_PORT = 20010 [transport-udp] PORT = 20009 [transport-http_server] PORT = 20008 [transport-https_server] PORT = 20007 [hostlist] OPTIONS = -p SERVERs = [nat] BEHIND_NAT = NO DISABLEV6 = NO [arm] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-arm-4 PORT = 20004 [dns] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dns-5 [core] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-core-3 PORT = 20003 [ats] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-ats-9 PORT = 20012 [mesh] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-mesh-13 PORT = 20016 [datastore] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-datastore-11 PORT = 20014 [resolver] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-resolver-14 PORT = 20017 [dht] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dht-1 PORT = 20000 [nat] BEHIND_NAT = NO [fs] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-fs-6 PORT = 20005 [gns] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-gns-15 PORT = 20018 [dv] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-16 PORT = 20019 [vpn] UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn-15 [peerinfo] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-peerinfo-10 PORT = 20013 [statistics] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-statistics-2 PORT = 20001 [nse] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nse-12 PORT = 20015 gnunet-0.10.1/src/integration-tests/confs/c_no_nat_client_2.conf0000644000175000017500000000365312254263402021611 00000000000000@INLINE@ confs/test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/c_no_nat_client_2/ [PEER] PRIVATE_KEY = hostkeys/c_no_nat_client_2 [transport] PLUGINS = tcp udp http_client https_client UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-transport-22 PORT = 20039 [transport-tcp] PORT = 20038 ADVERTISED_PORT = 20038 [transport-udp] PORT = 20027 BROADCAST_INTERVAL = 30 s [hostlist] SERVERS = http://localhost:8080/ [nat] BEHIND_NAT = NO DISABLEV6 = NO [arm] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-arm-18 PORT = 20022 [namestore] AUTOSTART = YES [dns] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dns-19 [consensus] AUTOSTART = YES [lockmanager] AUTOSTART = YES [core] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-core-17 PORT = 20021 [ats] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-ats-23 WAN_QUOTA_IN = 64 KiB WAN_QUOTA_OUT = 64 KiB PORT = 20030 [mesh] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-mesh-27 PORT = 20034 [datastore] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-datastore-25 PORT = 20032 [resolver] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-resolver-28 PORT = 20035 [dht] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dht-15 PORT = 20018 [dhtcache] DATABASE = heap QUOTA = 50 MB [gnunet-nat-server] PORT = 20020 [fs] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-fs-20 PORT = 20023 [vpn] UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-vpn-29 [dv] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-b_no_nat_c-1 [peerinfo] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-peerinfo-24 USE_INCLUDED_HELLOS = YES PORT = 20031 [statistics] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-statistics-16 PORT = 20019 [template] PORT = 20024 UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-template-21 [nse] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nse-26 UNIX_MATCH_UID = NO WORKBITS = 22 PORT = 20033 [gns] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-gns-35 PORT = 20038 [dv] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-36 PORT = 20039 gnunet-0.10.1/src/integration-tests/confs/test_defaults.conf0000644000175000017500000000275712277162077021137 00000000000000[arm] DEFAULTSERVICES = topology hostlist fs [peerinfo] USE_INCLUDED_HELLOS = NO [transport-tcp] USE_LOCALADDR = YES [transport-udp] BROADCAST = NO BROADCAST_RECEIVE = no USE_LOCALADDR = YES [nat] BEHIND_NAT = NO EXTERNAL_ADDRESS = 127.0.0.1 INTERNAL_ADDRESS = 127.0.0.1 BINDTO = 127.0.0.1 RETURN_LOCAL_ADDRESSES = YES [hostlist] SERVERS = [dns] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dns-47 PORT = 0 ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; PROVIDE_EXIT = NO [ats] WAN_QUOTA_IN = unlimited WAN_QUOTA_OUT = unlimited ATS_MIN_INTERVAL = 15000 ATS_EXEC_INTERVAL = 30000 [datastore] UNIX_MATCH_UID = YES QUOTA = 100 MB BLOOMFILTER = $GNUNET_TEST_HOME/fs/bloomfilter [dhtcache] DATABASE = sqlite QUOTA = 1 MB [TESTING] WEAKRANDOM = NO [fs] INDEXDB = $GNUNET_TEST_HOME/idxinfo.lst IDENTITY_DIR = $GNUNET_TEST_HOME/identities/ STATE_DIR = $GNUNET_TEST_HOME/persistence/ UPDATE_DIR = $GNUNET_TEST_HOME/updates/ TRUST = $GNUNET_TEST_HOME/data/credit/ [mesh] AUTOSTART = NO [consensus] AUTOSTART = NO [lockmanager] AUTOSTART = NO [namestore] AUTOSTART = NO [vpn] AUTOSTART = NO [template] AUTOSTART = NO [nse] AUTOSTART = NO WORKBITS = 1 [gns] AUTOSTART = NO [regex] AUTOSTART = NO [revocation] AUTOSTART = NO [namecache] AUTOSTART = NO [identity] AUTOSTART = NO [conversation] AUTOSTART = NO [psycstore] AUTOSTART = NO [multicast] AUTOSTART = NO [psyc] AUTOSTART = NO [set] AUTOSTART = NO [dv] AUTOSTART = NO [gns] AUTOSTART = NO [datacache-mysql] DATABASE = gnunet CONFIG = ~/.my.cnf gnunet-0.10.1/src/integration-tests/confs/c_nat_client.conf0000644000175000017500000000217212254263402020667 00000000000000@INLINE@ confs/test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/c_nat_client/ [PEER] PRIVATE_KEY = hostkeys/c_nat_client [transport] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-transport-50 PORT = 20065 PLUGINS = tcp udp http_client https_client [transport-tcp] PORT = 0 ADVERTISED_PORT = 20064 [transport-udp] PORT = 0 [hostlist] SERVERS = http://localhost:8080/ [nat] BEHIND_NAT = YES DISABLEV6 = NO [arm] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-arm-46 PORT = 20058 [core] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-core-45 PORT = 20057 [ats] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-ats-51 PORT = 20066 [datastore] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-datastore-53 PORT = 20068 [resolver] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-resolver-56 PORT = 20071 [dht] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dht-43 PORT = 20054 [fs] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-fs-48 PORT = 20059 [dv] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-dv-b_nat_c-1 [peerinfo] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-peerinfo-52 PORT = 20067 [nse] UNIXPATH = $GNUNET_RUNTIME_DIR/test-service-nse-54 PORT = 20069gnunet-0.10.1/src/integration-tests/test_integration_reconnect.py.in0000755000175000017500000001456712256040736022712 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # import sys import os import subprocess import re import shutil import time import signal from gnunet_testing import Peer from gnunet_testing import Test from gnunet_testing import Check from gnunet_testing import Condition from gnunet_testing import * # # This test tests if a fresh peer bootstraps from a hostlist server and then # successfully connects to the server. When both peers are connected # in transport, core, topology, fs, botth peers are shutdown and restarted # # Conditions for successful exit: # Both peers have 1 connected peer in transport, core, topology, fs after restart #definitions testname = "test_integration_restart" verbose = True check_timeout = 180 if os.name == "nt": tmp = os.getenv ("TEMP") signals = [signal.SIGTERM, signal.SIGINT] else: tmp = "/tmp" signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] def cleanup_onerror (function, path, excinfo): import stat if not os.path.exists (path): pass elif not os.access(path, os.W_OK): # Is the error an access error ? os.chmod (path, stat.S_IWUSR) function (path) else: raise def cleanup (): retries = 10 path = os.path.join (tmp, "c_bootstrap_server") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) retries = 10 path = os.path.join (tmp, "c_no_nat_client") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) def success_restart_cont (check): global success print 'Peers connected successfully after restart' server.stop () client.stop () success = True; def fail_restart_cont (check): global success success = False; print 'Peers failed to connect after restart' check.evaluate(True) def success_connect_cont (check): print 'Peers connected successfully' server.stop () client.stop () time.sleep(5) test.p ('Restarting client & server') server.start () client.start () check = Check (test) check.add (StatisticsCondition (client, 'transport', '# peers connected',1)) check.add (StatisticsCondition (client, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (client, 'core', '# peers connected',1)) check.add (StatisticsCondition (client, 'topology', '# peers connected',1)) check.add (StatisticsCondition (client, 'fs', '# peers connected',1)) check.add (StatisticsCondition (server, 'transport', '# peers connected',1)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (server, 'core', '# peers connected',1)) check.add (StatisticsCondition (server, 'topology', '# peers connected',1)) check.add (StatisticsCondition (server, 'fs', '# peers connected',1)) check.run_blocking (check_timeout, success_restart_cont, fail_restart_cont) def fail_connect_cont (check): global success success= False; print 'Peers failed to connect' check.evaluate(True) def check_connect (): check = Check (test) check.add (StatisticsCondition (client, 'transport', '# peers connected',1)) check.add (StatisticsCondition (client, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (client, 'core', '# peers connected',1)) check.add (StatisticsCondition (client, 'topology', '# peers connected',1)) check.add (StatisticsCondition (client, 'fs', '# peers connected',1)) check.add (StatisticsCondition (server, 'transport', '# peers connected',1)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (server, 'core', '# peers connected',1)) check.add (StatisticsCondition (server, 'topology', '# peers connected',1)) check.add (StatisticsCondition (server, 'fs', '# peers connected',1)) check.run_blocking (check_timeout, success_connect_cont, fail_connect_cont) # # Test execution # def SigHandler(signum = None, frame = None): global success global server global client print 'Test was aborted!' if (None != server): server.stop () if (None != client): client.stop () cleanup () sys.exit(success) def run (): global success global test global server global client success = False server = None client = None for sig in signals: signal.signal(sig, SigHandler) test = Test ('test_integration_disconnect', verbose) cleanup () server = Peer(test, './confs/c_bootstrap_server.conf'); server.start(); client = Peer(test, './confs/c_no_nat_client.conf'); client.start(); if (True != server.start()): print 'Failed to start server' if (None != server): server.stop () if (None != server): client.stop () cleanup () sys.exit(success) # Give the server time to start time.sleep(5) if (True != client.start()): print 'Failed to start client' if (None != server): server.stop () if (None != server): client.stop () cleanup () sys.exit(success) check_connect () server.stop () client.stop () cleanup () if (success == False): print ('Test failed') return True else: return False try: run () except (KeyboardInterrupt, SystemExit): print 'Test interrupted' server.stop () client.stop () cleanup () if (success == False): sys.exit(1) else: sys.exit(0) gnunet-0.10.1/src/integration-tests/Makefile.in0000644000175000017500000010150312320752062016330 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = src/integration-tests DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SCRIPTS = $(noinst_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov noinst_SCRIPTS = \ gnunet_testing.py \ gnunet_pyexpect.py @HAVE_PYTHON_TRUE@check_SCRIPTS = \ @HAVE_PYTHON_TRUE@ test_integration_bootstrap_and_connect.py \ @HAVE_PYTHON_TRUE@ test_integration_disconnect.py \ @HAVE_PYTHON_TRUE@ test_integration_disconnect_nat.py \ @HAVE_PYTHON_TRUE@ test_integration_reconnect.py \ @HAVE_PYTHON_TRUE@ test_integration_reconnect_nat.py \ @HAVE_PYTHON_TRUE@ test_integration_clique.py @ENABLE_TEST_RUN_TRUE@@HAVE_MHD_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@@HAVE_MHD_TRUE@TESTS = \ @ENABLE_TEST_RUN_TRUE@@HAVE_MHD_TRUE@ $(check_SCRIPTS) do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' EXTRA_DIST = \ gnunet_testing.py.in \ gnunet_pyexpect.py.in \ test_integration_bootstrap_and_connect.py.in \ test_integration_disconnect.py.in \ test_integration_disconnect_nat.py.in \ test_integration_reconnect.py.in \ test_integration_reconnect_nat.py.in \ test_integration_clique.py.in \ confs/test_defaults.conf \ confs/c_bootstrap_server.conf \ confs/c_nat_client.conf \ confs/c_no_nat_client_2.conf \ confs/c_no_nat_client.conf \ hostkeys/c_bootstrap_server \ hostkeys/c_no_nat_client \ hostkeys/c_no_nat_client_2 \ hostkeys/c_nat_client CLEANFILES = \ $(check_SCRIPTS) \ gnunet_pyexpect.py \ gnunet_testing.py all: all-am .SUFFIXES: .SUFFIXES: .log .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/integration-tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/integration-tests/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_integration_bootstrap_and_connect.py.log: test_integration_bootstrap_and_connect.py @p='test_integration_bootstrap_and_connect.py'; \ b='test_integration_bootstrap_and_connect.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_integration_disconnect.py.log: test_integration_disconnect.py @p='test_integration_disconnect.py'; \ b='test_integration_disconnect.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_integration_disconnect_nat.py.log: test_integration_disconnect_nat.py @p='test_integration_disconnect_nat.py'; \ b='test_integration_disconnect_nat.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_integration_reconnect.py.log: test_integration_reconnect.py @p='test_integration_reconnect.py'; \ b='test_integration_reconnect.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_integration_reconnect_nat.py.log: test_integration_reconnect_nat.py @p='test_integration_reconnect_nat.py'; \ b='test_integration_reconnect_nat.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_integration_clique.py.log: test_integration_clique.py @p='test_integration_clique.py'; \ b='test_integration_clique.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(SCRIPTS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am check check-TESTS check-am clean clean-generic \ clean-libtool cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags-am \ uninstall uninstall-am %.py: %.py.in Makefile $(do_subst) < $(srcdir)/$< > $@ chmod +x $@ gnunet_testing.py: gnunet_testing.py.in Makefile $(do_subst) < $(srcdir)/gnunet_testing.py.in > gnunet_testing.py chmod +x gnunet_testing.py gnunet_pyexpect.py: gnunet_pyexpect.py.in Makefile $(do_subst) < $(srcdir)/gnunet_pyexpect.py.in > gnunet_pyexpect.py chmod +x gnunet_pyexpect.py test_integration_bootstrap_and_connect.py: test_integration_bootstrap_and_connect.py.in Makefile $(do_subst) < $(srcdir)/test_integration_bootstrap_and_connect.py.in > test_integration_bootstrap_and_connect.py chmod +x test_integration_bootstrap_and_connect.py test_integration_disconnect.py: test_integration_disconnect.py.in Makefile $(do_subst) < $(srcdir)/test_integration_disconnect.py.in > test_integration_disconnect.py chmod +x test_integration_disconnect.py test_integration_disconnect_nat.py: test_integration_disconnect_nat.py.in Makefile $(do_subst) < $(srcdir)/test_integration_disconnect_nat.py.in > test_integration_disconnect_nat.py chmod +x test_integration_disconnect_nat.py test_integration_reconnect.py: test_integration_reconnect.py.in Makefile $(do_subst) < $(srcdir)/test_integration_reconnect.py.in > test_integration_reconnect.py chmod +x test_integration_reconnect.py test_integration_reconnect_nat.py: test_integration_reconnect_nat.py.in Makefile $(do_subst) < $(srcdir)/test_integration_reconnect_nat.py.in > test_integration_reconnect_nat.py chmod +x test_integration_reconnect_nat.py test_integration_clique.py: test_integration_clique.py.in Makefile $(do_subst) < $(srcdir)/test_integration_clique.py.in > test_integration_clique.py chmod +x test_integration_clique.py # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/integration-tests/test_integration_reconnect_nat.py.in0000755000175000017500000001456112256040736023546 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # import sys import os import subprocess import re import shutil import time import signal from gnunet_testing import Peer from gnunet_testing import Test from gnunet_testing import Check from gnunet_testing import Condition from gnunet_testing import * # # This test tests if a fresh peer bootstraps from a hostlist server and then # successfully connects to the server. When both peers are connected # in transport, core, topology, fs, botth peers are shutdown and restarted # # Conditions for successful exit: # Both peers have 1 connected peer in transport, core, topology, fs after restart #definitions testname = "test_integration_restart" verbose = True check_timeout = 180 if os.name == "nt": tmp = os.getenv ("TEMP") signals = [signal.SIGTERM, signal.SIGINT] else: tmp = "/tmp" signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] def cleanup_onerror (function, path, excinfo): import stat if not os.path.exists (path): pass elif not os.access(path, os.W_OK): # Is the error an access error ? os.chmod (path, stat.S_IWUSR) function (path) else: raise def cleanup (): retries = 10 path = os.path.join (tmp, "c_bootstrap_server") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) retries = 10 path = os.path.join (tmp, "c_nat_client") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) def success_restart_cont (check): global success print 'Peers connected successfully after restart' server.stop () client.stop () success = True; def fail_restart_cont (check): global success success = False; print 'Peers failed to connect after restart' check.evaluate(True) def success_connect_cont (check): print 'Peers connected successfully' server.stop () client.stop () time.sleep(5) test.p ('Restarting client & server') server.start () client.start () check = Check (test) check.add (StatisticsCondition (client, 'transport', '# peers connected',1)) check.add (StatisticsCondition (client, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (client, 'core', '# peers connected',1)) check.add (StatisticsCondition (client, 'topology', '# peers connected',1)) check.add (StatisticsCondition (client, 'fs', '# peers connected',1)) check.add (StatisticsCondition (server, 'transport', '# peers connected',1)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (server, 'core', '# peers connected',1)) check.add (StatisticsCondition (server, 'topology', '# peers connected',1)) check.add (StatisticsCondition (server, 'fs', '# peers connected',1)) check.run_blocking (check_timeout, success_restart_cont, fail_restart_cont) def fail_connect_cont (check): global success success= False; print 'Peers failed to connect' check.evaluate(True) def check_connect (): check = Check (test) check.add (StatisticsCondition (client, 'transport', '# peers connected',1)) check.add (StatisticsCondition (client, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (client, 'core', '# peers connected',1)) check.add (StatisticsCondition (client, 'topology', '# peers connected',1)) check.add (StatisticsCondition (client, 'fs', '# peers connected',1)) check.add (StatisticsCondition (server, 'transport', '# peers connected',1)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (server, 'core', '# peers connected',1)) check.add (StatisticsCondition (server, 'topology', '# peers connected',1)) check.add (StatisticsCondition (server, 'fs', '# peers connected',1)) check.run_blocking (check_timeout, success_connect_cont, fail_connect_cont) # # Test execution # def SigHandler(signum = None, frame = None): global success global server global client print 'Test was aborted!' if (None != server): server.stop () if (None != client): client.stop () cleanup () sys.exit(success) def run (): global success global test global server global client success = False server = None client = None for sig in signals: signal.signal(sig, SigHandler) test = Test ('test_integration_disconnect', verbose) cleanup () server = Peer(test, './confs/c_bootstrap_server.conf'); server.start(); client = Peer(test, './confs/c_nat_client.conf'); client.start(); if (True != server.start()): print 'Failed to start server' if (None != server): server.stop () if (None != server): client.stop () cleanup () sys.exit(success) # Give the server time to start time.sleep(5) if (True != client.start()): print 'Failed to start client' if (None != server): server.stop () if (None != server): client.stop () cleanup () sys.exit(success) check_connect () server.stop () client.stop () cleanup () if (success == False): print ('Test failed') return True else: return False try: run () except (KeyboardInterrupt, SystemExit): print 'Test interrupted' server.stop () client.stop () cleanup () if (success == False): sys.exit(1) else: sys.exit(0) gnunet-0.10.1/src/integration-tests/gnunet_testing.py.in0000644000175000017500000002516412221077151020306 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Functions for integration testing import os import subprocess import sys import shutil import time from gnunet_pyexpect import pexpect class Check: def __init__(self, test): self.fulfilled = False self.conditions = list() self.test = test def add (self, condition): self.conditions.append(condition) def run (self): fulfilled = True pos = 0 neg = 0 for c in self.conditions: if (False == c.check ()): fulfilled = False neg += 1 else: pos += 1 return fulfilled def run_blocking (self, timeout, pos_cont, neg_cont): execs = 0; res = False while ((False == res) and (execs < timeout)): res = self.run() time.sleep(1) execs += 1 if ((False == res) and (execs >= timeout)): print ('Check had timeout after ' +str(timeout)+ ' seconds') neg_cont (self) elif ((False == res) and (execs < timeout)): if (None != neg_cont): neg_cont (self) else: if (None != pos_cont): pos_cont (self) return res def run_once (self, pos_cont, neg_cont): execs = 0; res = False res = self.run() if ((res == False) and (neg_cont != None)): neg_cont (self) if ((res == True) and (pos_cont != None)): pos_cont (self) return res def evaluate (self, failed_only): pos = 0 neg = 0 for c in self.conditions: if (False == c.evaluate (failed_only)): neg += 1 else: pos += 1 print (str(pos) +' out of '+ str (pos+neg) + ' conditions fulfilled') return self.fulfilled def reset (self): self.fulfilled = False for c in self.conditions: c.fulfilled = False class Condition: def __init__(self): self.fulfilled = False self.type = 'generic' def __init__(self, type): self.fulfilled = False self.type = type def check(self): return False; def evaluate (self, failed_only): if ((self.fulfilled == False) and (failed_only == True)): print str(self.type) + 'condition for was ' + str(self.fulfilled) elif (failed_only == False): print str(self.type) + 'condition for was ' + str(self.fulfilled) return self.fulfilled class FileExistCondition (Condition): def __init__(self, file): self.fulfilled = False self.type = 'file' self.file = file def check(self): if (self.fulfilled == False): res = os.path.isfile(self.file) if (res == True): self.fulfilled = True return True else: return False else: return True def evaluate (self, failed_only): if ((self.fulfilled == False) and (failed_only == True)): print str(self.type) + 'condition for file '+self.file+' was ' + str(self.fulfilled) elif (failed_only == False): print str(self.type) + 'condition for file '+self.file+' was ' + str(self.fulfilled) return self.fulfilled class StatisticsCondition (Condition): def __init__(self, peer, subsystem, name, value): self.fulfilled = False self.type = 'statistics' self.peer = peer; self.subsystem = subsystem; self.name = name; self.value = value; self.result = -1; def check(self): if (self.fulfilled == False): self.result = self.peer.get_statistics_value (self.subsystem, self.name) if (str(self.result) == str(self.value)): self.fulfilled = True return True else: return False else: return True def evaluate (self, failed_only): if (self.result == -1): res = 'NaN' else: res = str(self.result) if (self.fulfilled == False): fail = " FAIL!" op = " != " else: fail = "" op = " == " if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)): print self.peer.id[:4] + " " +self.peer.cfg + " " + str(self.type) + ' condition in subsystem "' + self.subsystem.ljust(12) +'" : "' + self.name.ljust(30) +'" : (expected/real value) ' + str(self.value) + op + res + fail return self.fulfilled # Specify two statistic values and check if they are equal class EqualStatisticsCondition (Condition): def __init__(self, peer, subsystem, name, peer2, subsystem2, name2): self.fulfilled = False self.type = 'equalstatistics' self.peer = peer; self.subsystem = subsystem; self.name = name; self.result = -1; self.peer2 = peer2; self.subsystem2 = subsystem2; self.name2 = name2; self.result2 = -1; def check(self): if (self.fulfilled == False): self.result = self.peer.get_statistics_value (self.subsystem, self.name); self.result2 = self.peer2.get_statistics_value (self.subsystem2, self.name2); if (str(self.result) == str(self.result2)): self.fulfilled = True return True else: return False else: return True def evaluate (self, failed_only): if (self.result == -1): res = 'NaN' else: res = str(self.result) if (self.result2 == -1): res2 = 'NaN' else: res2 = str(self.result2) if (self.fulfilled == False): fail = " FAIL!" op = " != " else: fail = "" op = " == " if (((self.fulfilled == False) and (failed_only == True)) or (failed_only == False)): print self.peer.id[:4] + ' "' + self.subsystem.ljust(12) + '" "' + self.name.ljust(30) + '" == ' + str(self.result) +" " + self.peer2.id[:4] + ' "' + self.subsystem2.ljust(12) + '" '+ self.name2.ljust(30) + '" ' + str(self.result2) return self.fulfilled class Test: def __init__(self, testname, verbose): self.peers = list() self.verbose = verbose; self.name = testname; srcdir = "../.." gnunet_pyexpect_dir = os.path.join (srcdir, "contrib") if gnunet_pyexpect_dir not in sys.path: sys.path.append (gnunet_pyexpect_dir) self.gnunetarm = '' self.gnunetstatistics = '' if os.name == 'posix': self.gnunetarm = 'gnunet-arm' self.gnunetstatistics = 'gnunet-statistics' self.gnunetpeerinfo = 'gnunet-peerinfo' elif os.name == 'nt': self.gnunetarm = 'gnunet-arm.exe' self.gnunetstatistics = 'gnunet-statistics.exe' self.gnunetpeerinfo = 'gnunet-peerinfo.exe' if os.name == "nt": shutil.rmtree (os.path.join (os.getenv ("TEMP"), testname), True) else: shutil.rmtree ("/tmp/" + testname, True) def add_peer (self, peer): self.peers.append(peer) def p (self, msg): if (self.verbose == True): print msg class Peer: def __init__(self, test, cfg_file): if (False == os.path.isfile(cfg_file)): print ("Peer cfg " + cfg_file + ": FILE NOT FOUND") self.id = "" self.test = test self.started = False self.cfg = cfg_file def __del__(self): if (self.started == True): print 'ERROR! Peer using cfg ' + self.cfg + ' was not stopped' ret = self.stop () if (False == ret): print 'ERROR! Peer using cfg ' + self.cfg + ' could not be stopped' self.started = False return ret else: return False def start (self): self.test.p ("Starting peer using cfg " + self.cfg) try: server = subprocess.Popen ([self.test.gnunetarm, '-sq', '-c', self.cfg]) server.communicate () except OSError: print "Can not start peer" self.started = False return False self.started = True; test = '' try: server = pexpect () server.spawn (None, [self.test.gnunetpeerinfo, '-c', self.cfg ,'-s'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) test = server.read("stdout", 1024) except OSError: print "Can not get peer identity" test = (test.split('`')[1]) self.id = test.split('\'')[0] return True def stop (self): if (self.started == False): return False self.test.p ("Stopping peer using cfg " + self.cfg) try: server = subprocess.Popen ([self.test.gnunetarm, '-eq', '-c', self.cfg]) server.communicate () except OSError: print "Can not stop peer" return False self.started = False return True; def get_statistics_value (self, subsystem, name): server = pexpect () server.spawn (None, [self.test.gnunetstatistics, '-c', self.cfg ,'-q','-n', name, '-s', subsystem ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) #server.expect ("stdout", re.compile (r"")) test = server.read("stdout", 10240) tests = test.partition('\n') # On W32 GNUnet outputs with \r\n, rather than \n if os.name == 'nt' and tests[1] == '\n' and tests[0][-1] == '\r': tests = (tests[0][:-1], tests[1], tests[2]) tests = tests[0] if (tests.isdigit() == True): return tests else: return -1 gnunet-0.10.1/src/integration-tests/Makefile.am0000644000175000017500000000604312320751517016326 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif noinst_SCRIPTS = \ gnunet_testing.py \ gnunet_pyexpect.py if HAVE_PYTHON check_SCRIPTS = \ test_integration_bootstrap_and_connect.py \ test_integration_disconnect.py \ test_integration_disconnect_nat.py \ test_integration_reconnect.py \ test_integration_reconnect_nat.py \ test_integration_clique.py endif if HAVE_MHD if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ $(check_SCRIPTS) endif endif do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' %.py: %.py.in Makefile $(do_subst) < $(srcdir)/$< > $@ chmod +x $@ gnunet_testing.py: gnunet_testing.py.in Makefile $(do_subst) < $(srcdir)/gnunet_testing.py.in > gnunet_testing.py chmod +x gnunet_testing.py gnunet_pyexpect.py: gnunet_pyexpect.py.in Makefile $(do_subst) < $(srcdir)/gnunet_pyexpect.py.in > gnunet_pyexpect.py chmod +x gnunet_pyexpect.py test_integration_bootstrap_and_connect.py: test_integration_bootstrap_and_connect.py.in Makefile $(do_subst) < $(srcdir)/test_integration_bootstrap_and_connect.py.in > test_integration_bootstrap_and_connect.py chmod +x test_integration_bootstrap_and_connect.py test_integration_disconnect.py: test_integration_disconnect.py.in Makefile $(do_subst) < $(srcdir)/test_integration_disconnect.py.in > test_integration_disconnect.py chmod +x test_integration_disconnect.py test_integration_disconnect_nat.py: test_integration_disconnect_nat.py.in Makefile $(do_subst) < $(srcdir)/test_integration_disconnect_nat.py.in > test_integration_disconnect_nat.py chmod +x test_integration_disconnect_nat.py test_integration_reconnect.py: test_integration_reconnect.py.in Makefile $(do_subst) < $(srcdir)/test_integration_reconnect.py.in > test_integration_reconnect.py chmod +x test_integration_reconnect.py test_integration_reconnect_nat.py: test_integration_reconnect_nat.py.in Makefile $(do_subst) < $(srcdir)/test_integration_reconnect_nat.py.in > test_integration_reconnect_nat.py chmod +x test_integration_reconnect_nat.py test_integration_clique.py: test_integration_clique.py.in Makefile $(do_subst) < $(srcdir)/test_integration_clique.py.in > test_integration_clique.py chmod +x test_integration_clique.py EXTRA_DIST = \ gnunet_testing.py.in \ gnunet_pyexpect.py.in \ test_integration_bootstrap_and_connect.py.in \ test_integration_disconnect.py.in \ test_integration_disconnect_nat.py.in \ test_integration_reconnect.py.in \ test_integration_reconnect_nat.py.in \ test_integration_clique.py.in \ confs/test_defaults.conf \ confs/c_bootstrap_server.conf \ confs/c_nat_client.conf \ confs/c_no_nat_client_2.conf \ confs/c_no_nat_client.conf \ hostkeys/c_bootstrap_server \ hostkeys/c_no_nat_client \ hostkeys/c_no_nat_client_2 \ hostkeys/c_nat_client CLEANFILES = \ $(check_SCRIPTS) \ gnunet_pyexpect.py \ gnunet_testing.py gnunet-0.10.1/src/integration-tests/test_integration_clique.py.in0000755000175000017500000001450712256040736022206 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # # # This test starts 3 peers (nated, server, no nat)and expects bootstrap # and a connected clique # # Conditions for successful exit: # Both peers have 2 connected peers in transport, core, topology, fs and dht import sys import signal import os import subprocess import re import shutil import time from gnunet_testing import Peer from gnunet_testing import Test from gnunet_testing import Check from gnunet_testing import Condition from gnunet_testing import * if os.name == "nt": tmp = os.getenv ("TEMP") else: tmp = "/tmp" #definitions testname = "test_integration_clique" verbose = True check_timeout = 180 def cleanup_onerror (function, path, excinfo): import stat if not os.path.exists (path): pass elif not os.access(path, os.W_OK): # Is the error an access error ? os.chmod (path, stat.S_IWUSR) function (path) else: raise def cleanup (): retries = 10 path = os.path.join (tmp, "c_bootstrap_server") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) retries = 10 path = os.path.join (tmp, "c_no_nat_client") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) retries = 10 path = os.path.join (tmp, "c_nat_client") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) def success_cont (check): global success success = True; print 'Connected clique successfully' def fail_cont (check): global success success= False; check.evaluate(True) print 'Failed to connect clique' def check_connect (): check = Check (test) check.add (StatisticsCondition (client, 'transport', '# peers connected',2)) check.add (StatisticsCondition (client, 'core', '# neighbour entries allocated',2)) check.add (StatisticsCondition (client, 'core', '# peers connected',2)) check.add (StatisticsCondition (client, 'topology', '# peers connected',2)) check.add (StatisticsCondition (client, 'dht', '# peers connected',2)) check.add (StatisticsCondition (client, 'fs', '# peers connected',2)) check.add (StatisticsCondition (client_nat, 'transport', '# peers connected',2)) check.add (StatisticsCondition (client_nat, 'core', '# neighbour entries allocated',2)) check.add (StatisticsCondition (client_nat, 'core', '# peers connected',2)) check.add (StatisticsCondition (client_nat, 'topology', '# peers connected',2)) check.add (StatisticsCondition (client_nat, 'dht', '# peers connected',2)) check.add (StatisticsCondition (client_nat, 'fs', '# peers connected',2)) check.add (StatisticsCondition (server, 'transport', '# peers connected',2)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',2)) check.add (StatisticsCondition (server, 'core', '# peers connected',2)) check.add (StatisticsCondition (server, 'topology', '# peers connected',2)) check.add (StatisticsCondition (server, 'dht', '# peers connected',2)) check.add (StatisticsCondition (server, 'fs', '# peers connected',2)) check.run_blocking (check_timeout, success_cont, fail_cont) # # Test execution # def SigHandler(signum = None, frame = None): global success global server global client global client_nat print 'Test was aborted!' if (None != server): server.stop () if (None != client): client.stop () if (None != client_nat): client_nat.stop () cleanup () sys.exit(success) def run (): global success global test global server global client global client_nat success = False server = None client = None client_nat = None test = Test ('test_integration_clique', verbose) cleanup () server = Peer(test, './confs/c_bootstrap_server.conf'); if (True != server.start()): print 'Failed to start server' if (None != server): server.stop () cleanup () sys.exit(success) # Server has to settle down time.sleep(5) client = Peer(test, './confs/c_no_nat_client.conf'); if (True != client.start()): print 'Failed to start client' if (None != server): server.stop () if (None != client): client.stop () cleanup () sys.exit(success) # Server has to settle down time.sleep(5) client_nat = Peer(test, './confs/c_nat_client.conf'); if (True != client_nat.start()): print 'Failed to start client_nat' if (None != server): server.stop () if (None != client): client.stop () if (None != client_nat): client_nat.stop () cleanup () sys.exit(success) if ((client.started == True) and (client_nat.started == True) and (server.started == True)): test.p ('Peers started, running check') check_connect () server.stop () client.stop () client_nat.stop () cleanup () if (success == False): print ('Test failed') return False else: return True try: run () except (KeyboardInterrupt, SystemExit): print 'Test interrupted' server.stop () client.stop () client_nat.stop () cleanup () if (success == False): sys.exit(1) else: sys.exit(0) gnunet-0.10.1/src/integration-tests/test_integration_disconnect.py.in0000755000175000017500000001327212256040736023053 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # import sys import signal import os import subprocess import re import shutil import time from gnunet_testing import Peer from gnunet_testing import Test from gnunet_testing import Check from gnunet_testing import Condition from gnunet_testing import * # # This test tests if a fresh peer bootstraps from a hostlist server and then # successfully connects to the server. When both peers are connected # in transport, core, topology, fs, the server is shutdown # # Conditions for successful exit: # Client peer has 0 connected peer in transport, core, topology, dht, fs #definitions testname = "test_integration_disconnect" verbose = True check_timeout = 180 if os.name == "nt": tmp = os.getenv ("TEMP") signals = [signal.SIGTERM, signal.SIGINT] else: tmp = "/tmp" signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] def cleanup_onerror (function, path, excinfo): import stat if not os.path.exists (path): pass elif not os.access(path, os.W_OK): # Is the error an access error ? os.chmod (path, stat.S_IWUSR) function (path) else: raise def cleanup (): shutil.rmtree (os.path.join (tmp, "c_bootstrap_server"), False, cleanup_onerror) shutil.rmtree (os.path.join (tmp, "c_no_nat_client"), False, cleanup_onerror) def success_disconnect_cont (check): print 'Peers disconnected successfully' global success success = True; def fail_disconnect_cont (check): global success success = False; print 'Peers failed to disconnect' check.evaluate(True) def check_disconnect (): test.p ('Shutting down bootstrap server') server.stop () check = Check (test) check.add (StatisticsCondition (client, 'transport', '# peers connected',0)) check.add (StatisticsCondition (client, 'core', '# neighbour entries allocated',0)) check.add (StatisticsCondition (client, 'core', '# peers connected',0)) check.add (StatisticsCondition (client, 'topology', '# peers connected',0)) check.add (StatisticsCondition (client, 'dht', '# peers connected',0)) check.add (StatisticsCondition (client, 'fs', '# peers connected',0)) check.run_blocking (check_timeout, success_disconnect_cont, fail_disconnect_cont) def success_connect_cont (check): print 'Peers connected successfully' check_disconnect () def fail_connect_cont (check): global success success= False print 'Peers failed to connected!' check.evaluate(True) def check_connect (): check = Check (test) check.add (StatisticsCondition (client, 'transport', '# peers connected',1)) check.add (StatisticsCondition (client, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (client, 'core', '# peers connected',1)) check.add (StatisticsCondition (client, 'topology', '# peers connected',1)) check.add (StatisticsCondition (client, 'dht', '# peers connected',1)) check.add (StatisticsCondition (client, 'fs', '# peers connected',1)) check.add (StatisticsCondition (server, 'transport', '# peers connected',1)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (server, 'core', '# peers connected',1)) check.add (StatisticsCondition (server, 'topology', '# peers connected',1)) check.add (StatisticsCondition (server, 'dht', '# peers connected',1)) check.add (StatisticsCondition (server, 'fs', '# peers connected',1)) check.run_blocking (check_timeout, success_connect_cont, fail_connect_cont) # # Test execution # def SigHandler(signum = None, frame = None): global success global server global client print 'Test was aborted!' if (None != server): server.stop () if (None != client): client.stop () cleanup () sys.exit(success) def run (): global success global test global server global client server = None client = None success = False for sig in signals: signal.signal(sig, SigHandler) test = Test ('test_integration_bootstrap_and_connect.py', verbose) cleanup () server = Peer(test, './confs/c_bootstrap_server.conf'); client = Peer(test, './confs/c_no_nat_client.conf'); if (True != server.start()): print 'Failed to start server' if (None != server): server.stop () cleanup () sys.exit(success) # Give the server time to start time.sleep(5) if (True != client.start()): print 'Failed to start client' if (None != server): server.stop () if (None != client): client.stop () cleanup () sys.exit(success) if ((client.started == True) and (server.started == True)): test.p ('Peers started, running check') time.sleep(5) check_connect () server.stop () client.stop () cleanup () if (success == False): print ('Test failed') return False else: return True try: run () except (KeyboardInterrupt, SystemExit): print 'Test interrupted' server.stop () client.stop () cleanup () if (success == False): sys.exit(1) else: sys.exit(0) gnunet-0.10.1/src/integration-tests/test_integration_disconnect_nat.py.in0000755000175000017500000001351012256040736023710 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # import sys import signal import os import subprocess import re import shutil import time from gnunet_testing import Peer from gnunet_testing import Test from gnunet_testing import Check from gnunet_testing import Condition from gnunet_testing import * # # This test tests if a fresh peer bootstraps from a hostlist server and then # successfully connects to the server. When both peers are connected # in transport, core, topology, fs, the server is shutdown # # Conditions for successful exit: # Client peer has 0 connected peer in transport, core, topology, dht, fs #definitions testname = "test_integration_disconnect" verbose = True check_timeout = 180 if os.name == "nt": tmp = os.getenv ("TEMP") signals = [signal.SIGTERM, signal.SIGINT] else: tmp = "/tmp" signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] def cleanup_onerror (function, path, excinfo): import stat if not os.path.exists (path): pass elif not os.access(path, os.W_OK): # Is the error an access error ? os.chmod (path, stat.S_IWUSR) function (path) else: raise def cleanup (): shutil.rmtree (os.path.join (tmp, "c_bootstrap_server"), False, cleanup_onerror) shutil.rmtree (os.path.join (tmp, "c_nat_client"), False, cleanup_onerror) def success_disconnect_cont (check): print 'Peers disconnected successfully' global success success = True; def fail_disconnect_cont (check): global success success = False; print 'Peers failed to disconnect' check.evaluate(True) def check_disconnect (): global server global nat_client test.p ('Shutting down nat client') nat_client.stop () check = Check (test) check.add (StatisticsCondition (server, 'transport', '# peers connected',0)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',0)) check.add (StatisticsCondition (server, 'core', '# peers connected',0)) check.add (StatisticsCondition (server, 'topology', '# peers connected',0)) check.add (StatisticsCondition (server, 'dht', '# peers connected',0)) check.add (StatisticsCondition (server, 'fs', '# peers connected',0)) check.run_blocking (check_timeout, success_disconnect_cont, fail_disconnect_cont) def success_connect_cont (check): print 'Peers connected successfully' check_disconnect () def fail_connect_cont (check): global success success= False print 'Peers failed to connected!' check.evaluate(True) def check_connect (): global server global nat_client check = Check (test) check.add (StatisticsCondition (nat_client, 'transport', '# peers connected',1)) check.add (StatisticsCondition (nat_client, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (nat_client, 'core', '# peers connected',1)) check.add (StatisticsCondition (nat_client, 'topology', '# peers connected',1)) check.add (StatisticsCondition (nat_client, 'dht', '# peers connected',1)) check.add (StatisticsCondition (nat_client, 'fs', '# peers connected',1)) check.add (StatisticsCondition (server, 'transport', '# peers connected',1)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (server, 'core', '# peers connected',1)) check.add (StatisticsCondition (server, 'topology', '# peers connected',1)) check.add (StatisticsCondition (server, 'dht', '# peers connected',1)) check.add (StatisticsCondition (server, 'fs', '# peers connected',1)) check.run_blocking (check_timeout, success_connect_cont, fail_connect_cont) # # Test execution # def SigHandler(signum = None, frame = None): global success global server global nat_client print 'Test was aborted!' if (None != server): server.stop () if (None != nat_client): nat_client.stop () cleanup () sys.exit(success) def run (): global success global test global server global nat_client server = None nat_client = None success = False for sig in signals: signal.signal(sig, SigHandler) test = Test ('test_integration_bootstrap_and_connect.py', verbose) cleanup () server = Peer(test, './confs/c_bootstrap_server.conf'); nat_client = Peer(test, './confs/c_nat_client.conf'); if (True != server.start()): print 'Failed to start server' if (None != server): server.stop () cleanup () sys.exit(success) # Give the server time to start time.sleep(5) if (True != nat_client.start()): print 'Failed to start nat_client' if (None != server): server.stop () if (None != nat_client): nat_client.stop () cleanup () sys.exit(success) if ((nat_client.started == True) and (server.started == True)): test.p ('Peers started, running check') time.sleep(5) check_connect () server.stop () nat_client.stop () cleanup () if (success == False): print ('Test failed') return False else: return True try: run () except (KeyboardInterrupt, SystemExit): print 'Test interrupted' server.stop () nat_client.stop () cleanup () if (success == False): sys.exit(1) else: sys.exit(0) gnunet-0.10.1/src/integration-tests/gnunet_pyexpect.py.in0000644000175000017500000000543112221077151020465 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Testcase for gnunet-peerinfo from __future__ import print_function import os import re import subprocess import sys import shutil import time class pexpect (object): def __init__ (self): super (pexpect, self).__init__ () def spawn (self, stdin, arglist, *pargs, **kwargs): env = kwargs.pop ('env', None) if env is None: env = os.environ.copy () # This messes up some testcases, disable log redirection env.pop ('GNUNET_FORCE_LOGFILE', None) self.proc = subprocess.Popen (arglist, *pargs, env=env, **kwargs) if self.proc is None: print ("Failed to spawn a process {0}".format (arglist)) sys.exit (1) if stdin is not None: self.stdo, self.stde = self.proc.communicate (stdin) else: self.stdo, self.stde = self.proc.communicate () return self.proc def expect (self, s, r, flags=0): stream = self.stdo if s == 'stdout' else self.stde if isinstance (r, str): if r == "EOF": if len (stream) == 0: return True else: print ("Failed to find `{1}' in {0}, which is `{2}' ({3})".format (s, r, stream, len (stream))) sys.exit (2) raise ValueError ("Argument `r' should be an instance of re.RegexObject or a special string, but is `{0}'".format (r)) m = r.search (stream, flags) if not m: print ("Failed to find `{1}' in {0}, which is is `{2}'".format (s, r.pattern, stream)) sys.exit (2) stream = stream[m.end ():] if s == 'stdout': self.stdo = stream else: self.stde = stream return m def read (self, s, size=-1): stream = self.stdo if s == 'stdout' else self.stde result = "" if size < 0: result = stream new_stream = "" else: result = stream[0:size] new_stream = stream[size:] if s == 'stdout': self.stdo = new_stream else: self.stde = new_stream return result gnunet-0.10.1/src/integration-tests/test_integration_bootstrap_and_connect.py.in0000755000175000017500000001273512256040736025275 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 2, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # import signal import sys import os import subprocess import re import shutil import time from gnunet_testing import Peer from gnunet_testing import Test from gnunet_testing import Check from gnunet_testing import Condition from gnunet_testing import * # # This test tests if a fresh peer bootstraps from a hostlist server and then # successfully connects to the server # # Conditions for successful exit: # Both peers have 1 connected peer in transport, core, topology, fs # # This test tests if a fresh peer bootstraps from a hostlist server and then # successfully connects to the server # # Conditions for successful exit: # Both peers have 1 connected peer in transport, core, topology, fs #definitions testname = "test_integration_bootstrap_and_connect" verbose = False check_timeout = 180 if os.name == "nt": tmp = os.getenv ("TEMP") signals = [signal.SIGTERM, signal.SIGINT] else: tmp = "/tmp" signals = [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT] def cleanup_onerror (function, path, excinfo): import stat if not os.path.exists (path): pass elif not os.access(path, os.W_OK): # Is the error an access error ? os.chmod (path, stat.S_IWUSR) function (path) else: raise def cleanup (): retries = 10 path = os.path.join (tmp, "c_bootstrap_server") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) retries = 10 path = os.path.join (tmp, "c_no_nat_client") test.p ("Removing " + path) while ((os.path.exists(path)) and (retries > 0)): shutil.rmtree ((path), False, cleanup_onerror) time.sleep (1) retries -= 1 if (os.path.exists(path)): test.p ("Failed to remove " + path) def success_cont (check): global success success = True; print 'Peers connected successfully' def fail_cont (check): global success success = False; print 'Peers did not connect' check.evaluate(True) def check (): check = Check (test) check.add (StatisticsCondition (client, 'transport', '# peers connected',1)) check.add (StatisticsCondition (client, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (client, 'core', '# peers connected',1)) check.add (StatisticsCondition (client, 'topology', '# peers connected',1)) check.add (StatisticsCondition (client, 'dht', '# peers connected',1)) check.add (StatisticsCondition (client, 'fs', '# peers connected',1)) check.add (StatisticsCondition (server, 'transport', '# peers connected',1)) check.add (StatisticsCondition (server, 'core', '# neighbour entries allocated',1)) check.add (StatisticsCondition (server, 'core', '# peers connected',1)) check.add (StatisticsCondition (server, 'topology', '# peers connected',1)) check.add (StatisticsCondition (server, 'dht', '# peers connected',1)) check.add (StatisticsCondition (server, 'fs', '# peers connected',1)) check.run_blocking (check_timeout, success_cont, fail_cont) # # Test execution # def SigHandler(signum = None, frame = None): global success global server global client print 'Test was aborted!' if (None != server): server.stop () if (None != client): client.stop () cleanup () sys.exit(success) def run (): global success global test global server global client server = None client = None success = False for sig in signals: signal.signal(sig, SigHandler) test = Test ('test_integration_bootstrap_and_connect.py', verbose) cleanup () server = Peer(test, './confs/c_bootstrap_server.conf'); client = Peer(test, './confs/c_no_nat_client.conf'); if (True != server.start()): print 'Failed to start server' if (None != server): server.stop () if (None != server): client.stop () cleanup () sys.exit(success) # Give the server time to start time.sleep(5) if (True != client.start()): print 'Failed to start client' if (None != server): server.stop () if (None != server): client.stop () cleanup () sys.exit(success) if ((client.started == True) and (server.started == True)): test.p ('Peers started, running check') time.sleep(5) check () server.stop () client.stop () cleanup () if (success == False): print ('Test failed') return False else: return True try: run () except (KeyboardInterrupt, SystemExit): print 'Test interrupted' server.stop () client.stop () cleanup () if (success == False): sys.exit(1) else: sys.exit(0) gnunet-0.10.1/src/integration-tests/hostkeys/0000755000175000017500000000000012320755627016226 500000000000000gnunet-0.10.1/src/integration-tests/hostkeys/c_no_nat_client0000644000175000017500000000004012236654562021203 00000000000000;ÇÒå‰ ÜÅhßVCji¾•ŽeÙ?œ€se^-W¹tgnunet-0.10.1/src/integration-tests/hostkeys/c_nat_client0000644000175000017500000000004012236654562020507 00000000000000äÅ»ªP yÑûc½q‰®j[U1úúÑÕГæ¿aŽlgnunet-0.10.1/src/integration-tests/hostkeys/c_no_nat_client_20000644000175000017500000000004012236654562021424 00000000000000Ĥ×O7†y`öظ‚ø:ŸÌŠá1´RWFtÏÉpÇgnunet-0.10.1/src/integration-tests/hostkeys/c_bootstrap_server0000644000175000017500000000004012236654562021772 00000000000000«´\{€ìº–„âÒq@AP­³­”I$Õ1Šrî˜gnunet-0.10.1/src/mesh/0000755000175000017500000000000012320755626011625 500000000000000gnunet-0.10.1/src/mesh/test_mesh_drop.conf0000644000175000017500000000225112306275771015435 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-mesh/ [mesh] # BINARY = gnunet-service-mesh-enc AUTOSTART = NO ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost PORT = 10511 #PREFIX = valgrind --leak-check=full #PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args REFRESH_CONNECTION_TIME = 2 s ID_ANNOUNCE_TIME = 5 s CONNECT_TIMEOUT = 30 s DEFAULT_TTL = 16 DHT_REPLICATION_LEVEL = 3 MAX_TUNNELS = 10 MAX_CONNECTIONS = 10 MAX_MSGS_QUEUE = 20 DROP_PERCENT = 1 [testbed] NUM_PEERS = 5 OVERLAY_TOPOLOGY = LINE [fs] AUTOSTART = NO [resolver] AUTOSTART = NO [vpn] AUTOSTART = NO PORT = 10012 [dht] AUTOSTART = YES ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost PORT = 12100 DISABLE_TRY_CONNECT = YES FORCE_NSE = 3 [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = tcp ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 PORT = 12365 [ats] WAN_QUOTA_OUT = 3932160 WAN_QUOTA_IN = 3932160 [core] PORT = 12092 [arm] DEFAULTSERVICES = core mesh PORT = 12366 [transport-tcp] TIMEOUT = 300 s PORT = 12368 [dns] AUTOSTART = NO [nse] AUTOSTART = NO [namestore] AUTOSTART = NO [consensus] AUTOSTART = NO [nat] RETURN_LOCAL_ADDRESSES = YES USE_LOCALADDR = YES gnunet-0.10.1/src/mesh/test_mesh.conf0000644000175000017500000000274512316473376014423 00000000000000[testbed] AUTOSTART = NO PORT = 12113 ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost OVERLAY_TOPOLOGY = LINE #PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args [fs] AUTOSTART = NO [resolver] AUTOSTART = NO [mesh] #BINARY = gnunet-service-mesh-enc #PREFIX = valgrind --leak-check=full #PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args AUTOSTART = NO ACCEPT_FROM = 127.0.0.1; REFRESH_CONNECTION_TIME = 2 s ID_ANNOUNCE_TIME = 5 s CONNECT_TIMEOUT = 30 s DEFAULT_TTL = 16 DHT_REPLICATION_LEVEL = 10 MAX_TUNNELS = 10 MAX_CONNECTIONS = 10 MAX_MSGS_QUEUE = 20 #DROP_PERCENT = 1 DISABLE_TRY_CONNECT = YES [dht] AUTOSTART = NO DISABLE_TRY_CONNECT = YES FORCE_NSE = 3 [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = udp ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 PORT = 12365 #MANIPULATE_DELAY_IN = 10 ms #MANIPULATE_DELAY_OUT = 10 ms [ats] WAN_QUOTA_OUT = 3932160 WAN_QUOTA_IN = 3932160 [core] PORT = 12092 AUTOSTART = YES USE_EPHEMERAL_KEYS = NO [arm] DEFAULTSERVICES = core transport dht mesh statistics PORT = 12366 [transport-udp] TIMEOUT = 300 s PORT = 12368 [gnunetd] HOSTKEY = $GNUNET_TEST_HOME/.hostkey [PATHS] GNUNET_TEST_HOME = /tmp/test-mesh/ [dns] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART = NO [nat] RETURN_LOCAL_ADDRESSES = YES DISABLEV6 = YES USE_LOCALADDR = YES [gns-helper-service-w32] AUTOSTART = NO [consensus] AUTOSTART = NO [gns] AUTOSTART = NO [statistics] AUTOSTART = NO [peerinfo] NO_IO = YES gnunet-0.10.1/src/mesh/gnunet-service-mesh_peer.h0000644000175000017500000002563112316473376016634 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh_peer.h * @brief mesh service; dealing with remote peers * @author Bartlomiej Polot * * All functions in this file should use the prefix GMP (Gnunet Mesh Peer) */ #ifndef GNUNET_SERVICE_MESH_PEER_H #define GNUNET_SERVICE_MESH_PEER_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "gnunet_util_lib.h" /** * Struct containing all information regarding a given peer */ struct MeshPeer; /** * Struct containing info about a queued transmission to this peer */ struct MeshPeerQueue; #include "gnunet-service-mesh_connection.h" /** * Callback called when a queued message is sent. * * @param cls Closure. * @param c Connection this message was on. * @param sent Was it really sent? (Could have been canceled) * @param type Type of message sent. * @param fwd Was this a FWD going message? * @param size Size of the message. * @param wait Time spent waiting for core (only the time for THIS message) */ typedef void (*GMP_sent) (void *cls, struct MeshConnection *c, int sent, uint16_t type, int fwd, size_t size, struct GNUNET_TIME_Relative wait); /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Initialize peer subsystem. * * @param c Configuration. */ void GMP_init (const struct GNUNET_CONFIGURATION_Handle *c); /** * Shut down the peer subsystem. */ void GMP_shutdown (void); /** * Retrieve the MeshPeer stucture associated with the peer, create one * and insert it in the appropriate structures if the peer is not known yet. * * @param peer_id Full identity of the peer. * * @return Existing or newly created peer structure. */ struct MeshPeer * GMP_get (const struct GNUNET_PeerIdentity *peer_id); /** * Retrieve the MeshPeer stucture associated with the peer, create one * and insert it in the appropriate structures if the peer is not known yet. * * @param peer Short identity of the peer. * * @return Existing or newly created peer structure. */ struct MeshPeer * GMP_get_short (const GNUNET_PEER_Id peer); /** * Try to establish a new connection to this peer (in its tunnel). * If the peer doesn't have any path to it yet, try to get one. * If the peer already has some path, send a CREATE CONNECTION towards it. * * @param peer Peer to connect to. */ void GMP_connect (struct MeshPeer *peer); /** * Free a transmission that was already queued with all resources * associated to the request. * * @param queue Queue handler to cancel. * @param clear_cls Is it necessary to free associated cls? * @param sent Was it really sent? (Could have been canceled) */ void GMP_queue_destroy (struct MeshPeerQueue *queue, int clear_cls, int sent); /** * @brief Queue and pass message to core when possible. * * @param peer Peer towards which to queue the message. * @param cls Closure (@c type dependant). It will be used by queue_send to * build the message to be sent if not already prebuilt. * @param type Type of the message, 0 for a raw message. * @param size Size of the message. * @param c Connection this message belongs to (cannot be NULL). * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!) * @param cont Continuation to be called once CORE has taken the message. * @param cont_cls Closure for @c cont. * * @return Handle to cancel the message before it is sent. Once cont is called * message has been sent and therefore the handle is no longer valid. */ struct MeshPeerQueue * GMP_queue_add (struct MeshPeer *peer, void *cls, uint16_t type, size_t size, struct MeshConnection *c, int fwd, GMP_sent cont, void *cont_cls); /** * Cancel all queued messages to a peer that belong to a certain connection. * * @param peer Peer towards whom to cancel. * @param c Connection whose queued messages to cancel. Might be destroyed by * the sent continuation call. */ void GMP_queue_cancel (struct MeshPeer *peer, struct MeshConnection *c); /** * Get the first message for a connection and unqueue it. * * @param peer Neighboring peer. * @param c Connection. * * @return First message for this connection. */ struct GNUNET_MessageHeader * GMP_connection_pop (struct MeshPeer *peer, struct MeshConnection *c); void GMP_queue_unlock (struct MeshPeer *peer, struct MeshConnection *c); /** * Set tunnel. * * @param peer Peer. * @param t Tunnel. */ void GMP_set_tunnel (struct MeshPeer *peer, struct MeshTunnel3 *t); /** * Check whether there is a direct (core level) connection to peer. * * @param peer Peer to check. * * @return #GNUNET_YES if there is a direct connection. */ int GMP_is_neighbor (const struct MeshPeer *peer); /** * Create and initialize a new tunnel towards a peer, in case it has none. * * Does not generate any traffic, just creates the local data structures. * * @param peer Peer towards which to create the tunnel. */ void GMP_add_tunnel (struct MeshPeer *peer); /** * Add a connection to a neighboring peer. * * Store that the peer is the first hop of the connection in one * direction and that on peer disconnect the connection must be * notified and destroyed, for it will no longer be valid. * * @param peer Peer to add connection to. * @param c Connection to add. * * @return GNUNET_OK on success. */ int GMP_add_connection (struct MeshPeer *peer, struct MeshConnection *c); /** * Add the path to the peer and update the path used to reach it in case this * is the shortest. * * @param peer Destination peer to add the path to. * @param path New path to add. Last peer must be the peer in arg 1. * Path will be either used of freed if already known. * @param trusted Do we trust that this path is real? * * @return path if path was taken, pointer to existing duplicate if exists * NULL on error. */ struct MeshPeerPath * GMP_add_path (struct MeshPeer *peer, struct MeshPeerPath *p, int trusted); /** * Add the path to the origin peer and update the path used to reach it in case * this is the shortest. * The path is given in peer_info -> destination, therefore we turn the path * upside down first. * * @param peer Peer to add the path to, being the origin of the path. * @param path New path to add after being inversed. * Path will be either used or freed. * @param trusted Do we trust that this path is real? * * @return path if path was taken, pointer to existing duplicate if exists * NULL on error. */ struct MeshPeerPath * GMP_add_path_to_origin (struct MeshPeer *peer, struct MeshPeerPath *path, int trusted); /** * Adds a path to the info of all the peers in the path * * @param p Path to process. * @param confirmed Whether we know if the path works or not. */ void GMP_add_path_to_all (const struct MeshPeerPath *p, int confirmed); /** * Remove any path to the peer that has the extact same peers as the one given. * * @param peer Peer to remove the path from. * @param path Path to remove. Is always destroyed . */ void GMP_remove_path (struct MeshPeer *peer, struct MeshPeerPath *path); /** * Remove a connection from a neighboring peer. * * @param peer Peer to remove connection from. * @param c Connection to remove. * * @return GNUNET_OK on success. */ int GMP_remove_connection (struct MeshPeer *peer, const struct MeshConnection *c); /** * Start the DHT search for new paths towards the peer: we don't have * enough good connections. * * @param peer Destination peer. */ void GMP_start_search (struct MeshPeer *peer); /** * Stop the DHT search for new paths towards the peer: we already have * enough good connections. * * @param peer Destination peer. */ void GMP_stop_search (struct MeshPeer *peer); /** * Get the Full ID of a peer. * * @param peer Peer to get from. * * @return Full ID of peer. */ const struct GNUNET_PeerIdentity * GMP_get_id (const struct MeshPeer *peer); /** * Get the Short ID of a peer. * * @param peer Peer to get from. * * @return Short ID of peer. */ GNUNET_PEER_Id GMP_get_short_id (const struct MeshPeer *peer); /** * Get the tunnel towards a peer. * * @param peer Peer to get from. * * @return Tunnel towards peer. */ struct MeshTunnel3 * GMP_get_tunnel (const struct MeshPeer *peer); /** * Set the hello message. * * @param peer Peer whose message to set. * @param hello Hello message. */ void GMP_set_hello (struct MeshPeer *peer, const struct GNUNET_HELLO_Message *hello); /** * Get the hello message. * * @param peer Peer whose message to get. * * @return Hello message. */ struct GNUNET_HELLO_Message * GMP_get_hello (struct MeshPeer *peer); /** * Try to connect to a peer on TRANSPORT level. * * @param peer Peer to whom to connect. */ void GMP_try_connect (struct MeshPeer *peer); /** * Notify a peer that a link between two other peers is broken. If any path * used that link, eliminate it. * * @param peer Peer affected by the change. * @param peer1 Peer whose link is broken. * @param peer2 Peer whose link is broken. */ void GMP_notify_broken_link (struct MeshPeer *peer, struct GNUNET_PeerIdentity *peer1, struct GNUNET_PeerIdentity *peer2); /** * Count the number of known paths toward the peer. * * @param peer Peer to get path info. * * @return Number of known paths. */ unsigned int GMP_count_paths (const struct MeshPeer *peer); /** * Iterate all known peers. * * @param iter Iterator. * @param cls Closure for @c iter. */ void GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls); /** * Get the static string for a peer ID. * * @param peer Peer. * * @return Static string for it's ID. */ const char * GMP_2s (const struct MeshPeer *peer); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_MESH_SERVICE_PEER_H */ #endif /* end of gnunet-mesh-service_peer.h */ gnunet-0.10.1/src/mesh/gnunet-service-mesh_local.h0000644000175000017500000001267212262754601016765 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh_local.h * @brief mesh service; dealing with local clients * @author Bartlomiej Polot * * All functions in this file should use the prefix GML (Gnunet Mesh Local) */ #ifndef GNUNET_SERVICE_MESH_LOCAL_H #define GNUNET_SERVICE_MESH_LOCAL_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "gnunet_util_lib.h" /** * Struct containing information about a client of the service */ struct MeshClient; #include "gnunet-service-mesh_channel.h" /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Initialize server subsystem. * * @param handle Server handle. */ void GML_init (struct GNUNET_SERVER_Handle *handle); /** * Install server (service) handlers and start listening to clients. */ void GML_start (void); /** * Shutdown server. */ void GML_shutdown (void); /** * Get a channel from a client. * * @param c Client to check. * @param chid Channel ID, must be local (> 0x800...). * * @return non-NULL if channel exists in the clients lists */ struct MeshChannel * GML_channel_get (struct MeshClient *c, uint32_t chid); /** * Add a channel to a client * * @param client Client. * @param chid Channel ID. * @param ch Channel. */ void GML_channel_add (struct MeshClient *client, uint32_t chid, struct MeshChannel *ch); /** * Remove a channel from a client * * @param client Client. * @param chid Channel ID. * @param ch Channel. */ void GML_channel_remove (struct MeshClient *client, uint32_t chid, struct MeshChannel *ch); /** * Get the tunnel's next free local channel ID. * * @param c Client. * * @return LID of a channel free to use. */ MESH_ChannelNumber GML_get_next_chid (struct MeshClient *c); /** * Check if client has registered with the service and has not disconnected * * @param client the client to check * * @return non-NULL if client exists in the global DLL */ struct MeshClient * GML_client_get (struct GNUNET_SERVER_Client *client); /** * Find a client that has opened a port * * @param port Port to check. * * @return non-NULL if a client has the port. */ struct MeshClient * GML_client_get_by_port (uint32_t port); /** * Deletes a tunnel from a client (either owner or destination). * * @param c Client whose tunnel to delete. * @param ch Channel which should be deleted. * @param id Channel ID. */ void GML_client_delete_channel (struct MeshClient *c, struct MeshChannel *ch, MESH_ChannelNumber id); /** * Build a local ACK message and send it to a local client, if needed. * * If the client was already allowed to send data, do nothing. * * @param c Client to whom send the ACK. * @param id Channel ID to use */ void GML_send_ack (struct MeshClient *c, MESH_ChannelNumber id); /** * Notify the appropriate client that a new incoming channel was created. * * @param c Client to notify. * @param id Channel ID. * @param port Channel's destination port. * @param opt Options (bit array). * @param peer Origin peer. */ void GML_send_channel_create (struct MeshClient *c, uint32_t id, uint32_t port, uint32_t opt, const struct GNUNET_PeerIdentity *peer); /** * Build a local channel NACK message and send it to a local client. * * @param c Client to whom send the NACK. * @param id Channel ID to use */ void GML_send_channel_nack (struct MeshClient *c, MESH_ChannelNumber id); /** * Notify a client that a channel is no longer valid. * * @param c Client. * @param id ID of the channel that is destroyed. */ void GML_send_channel_destroy (struct MeshClient *c, uint32_t id); /** * Modify the mesh message ID from global to local and send to client. * * @param c Client to send to. * @param msg Message to modify and send. * @param id Channel ID to use (c can be both owner and client). */ void GML_send_data (struct MeshClient *c, const struct GNUNET_MESH_Data *msg, MESH_ChannelNumber id); /** * Get the static string to represent a client. * * @param c Client. * * @return Static string for the client. */ const char * GML_2s (const struct MeshClient *c); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_MESH_SERVICE_LOCAL_H */ #endif /* end of gnunet-mesh-service_LOCAL.h */ gnunet-0.10.1/src/mesh/gnunet-service-mesh_channel.c0000644000175000017500000017275412320724374017305 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "mesh.h" #include "mesh_protocol.h" #include "gnunet-service-mesh_channel.h" #include "gnunet-service-mesh_local.h" #include "gnunet-service-mesh_tunnel.h" #include "gnunet-service-mesh_peer.h" #define LOG(level, ...) GNUNET_log_from(level,"mesh-chn",__VA_ARGS__) #define MESH_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(\ GNUNET_TIME_UNIT_MILLISECONDS, 250) #define MESH_RETRANSMIT_MARGIN 4 /** * All the states a connection can be in. */ enum MeshChannelState { /** * Uninitialized status, should never appear in operation. */ MESH_CHANNEL_NEW, /** * Connection create message sent, waiting for ACK. */ MESH_CHANNEL_SENT, /** * Connection confirmed, ready to carry traffic. */ MESH_CHANNEL_READY, }; /** * Info holder for channel messages in queues. */ struct MeshChannelQueue { /** * Tunnel Queue. */ struct MeshTunnel3Queue *tq; /** * Message type (DATA/DATA_ACK) */ uint16_t type; /** * Message copy (for DATAs, to start retransmission timer) */ struct MeshReliableMessage *copy; /** * Reliability (for DATA_ACKs, to access rel->ack_q) */ struct MeshChannelReliability *rel; }; /** * Info needed to retry a message in case it gets lost. */ struct MeshReliableMessage { /** * Double linked list, FIFO style */ struct MeshReliableMessage *next; struct MeshReliableMessage *prev; /** * Type of message (payload, channel management). */ int16_t type; /** * Tunnel Reliability queue this message is in. */ struct MeshChannelReliability *rel; /** * ID of the message (ACK needed to free) */ uint32_t mid; /** * Tunnel Queue. */ struct MeshChannelQueue *chq; /** * When was this message issued (to calculate ACK delay) */ struct GNUNET_TIME_Absolute timestamp; /* struct GNUNET_MESH_Data with payload */ }; /** * Info about the traffic state for a client in a channel. */ struct MeshChannelReliability { /** * Channel this is about. */ struct MeshChannel *ch; /** * DLL of messages sent and not yet ACK'd. */ struct MeshReliableMessage *head_sent; struct MeshReliableMessage *tail_sent; /** * DLL of messages received out of order. */ struct MeshReliableMessage *head_recv; struct MeshReliableMessage *tail_recv; /** * Messages received. */ unsigned int n_recv; /** * Next MID to use for outgoing traffic. */ uint32_t mid_send; /** * Next MID expected for incoming traffic. */ uint32_t mid_recv; /** * Handle for queued unique data CREATE, DATA_ACK. */ struct MeshChannelQueue *uniq; /** * Can we send data to the client? */ int client_ready; /** * Can the client send data to us? */ int client_allowed; /** * Task to resend/poll in case no ACK is received. */ GNUNET_SCHEDULER_TaskIdentifier retry_task; /** * Counter for exponential backoff. */ struct GNUNET_TIME_Relative retry_timer; /** * How long does it usually take to get an ACK. */ struct GNUNET_TIME_Relative expected_delay; }; /** * Struct containing all information regarding a channel to a remote client. */ struct MeshChannel { /** * Tunnel this channel is in. */ struct MeshTunnel3 *t; /** * Destination port of the channel. */ uint32_t port; /** * Global channel number ( < GNUNET_MESH_LOCAL_CHANNEL_ID_CLI) */ MESH_ChannelNumber gid; /** * Local tunnel number for root (owner) client. * ( >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI or 0 ) */ MESH_ChannelNumber lid_root; /** * Local tunnel number for local destination clients (incoming number) * ( >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV or 0). */ MESH_ChannelNumber lid_dest; /** * Channel state. */ enum MeshChannelState state; /** * Is the tunnel bufferless (minimum latency)? */ int nobuffer; /** * Is the tunnel reliable? */ int reliable; /** * Last time the channel was used */ struct GNUNET_TIME_Absolute timestamp; /** * Client owner of the tunnel, if any */ struct MeshClient *root; /** * Client destination of the tunnel, if any. */ struct MeshClient *dest; /** * Flag to signal the destruction of the channel. * If this is set GNUNET_YES the channel will be destroyed * when the queue is empty. */ int destroy; /** * Total (reliable) messages pending ACK for this channel. */ unsigned int pending_messages; /** * Reliability data. * Only present (non-NULL) at the owner of a tunnel. */ struct MeshChannelReliability *root_rel; /** * Reliability data. * Only present (non-NULL) at the destination of a tunnel. */ struct MeshChannelReliability *dest_rel; }; /******************************************************************************/ /******************************* GLOBALS ***********************************/ /******************************************************************************/ /** * Global handle to the statistics service. */ extern struct GNUNET_STATISTICS_Handle *stats; /** * Local peer own ID (memory efficient handle). */ extern GNUNET_PEER_Id myid; /******************************************************************************/ /******************************** STATIC ***********************************/ /******************************************************************************/ /** * Destroy a reliable message after it has been acknowledged, either by * direct mid ACK or bitfield. Updates the appropriate data structures and * timers and frees all memory. * * @param copy Message that is no longer needed: remote peer got it. * @param update_time Is the timing information relevant? * If this message is ACK in a batch the timing information * is skewed by the retransmission, count only for the * retransmitted message. */ static int rel_message_free (struct MeshReliableMessage *copy, int update_time); /** * send a channel create message. * * @param ch Channel for which to send. */ static void send_create (struct MeshChannel *ch); /** * Confirm we got a channel create, FWD ack. * * @param ch The channel to confirm. * @param fwd Should we send a FWD ACK? (going dest->root) * @param reaction This ACK is a reaction to a duplicate CREATE, don't save. */ static void send_ack (struct MeshChannel *ch, int fwd, int reaction); /** * Test if the channel is loopback: both root and dest are on the local peer. * * @param ch Channel to test. * * @return #GNUNET_YES if channel is loopback, #GNUNET_NO otherwise. */ static int is_loopback (const struct MeshChannel *ch) { if (NULL != ch->t) return GMT_is_loopback (ch->t); return (NULL != ch->root && NULL != ch->dest); } /** * Save a copy of the data message for later retransmission. * * @param msg Message to copy. * @param mid Message ID. * @param rel Reliability data for retransmission. */ static struct MeshReliableMessage * copy_message (const struct GNUNET_MESH_Data *msg, uint32_t mid, struct MeshChannelReliability *rel) { struct MeshReliableMessage *copy; uint16_t size; size = ntohs (msg->header.size); copy = GNUNET_malloc (sizeof (*copy) + size); copy->mid = mid; copy->rel = rel; copy->type = GNUNET_MESSAGE_TYPE_MESH_DATA; memcpy (©[1], msg, size); return copy; } /** * We have received a message out of order, or the client is not ready. * Buffer it until we receive an ACK from the client or the missing * message from the channel. * * @param msg Message to buffer (MUST be of type MESH_DATA). * @param rel Reliability data to the corresponding direction. */ static void add_buffered_data (const struct GNUNET_MESH_Data *msg, struct MeshChannelReliability *rel) { struct MeshReliableMessage *copy; struct MeshReliableMessage *prev; uint32_t mid; mid = ntohl (msg->mid); LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data %u\n", mid); rel->n_recv++; // FIXME do something better than O(n), although n < 64... // FIXME start from the end (most messages are the latest ones) for (prev = rel->head_recv; NULL != prev; prev = prev->next) { LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid); if (prev->mid == mid) { LOG (GNUNET_ERROR_TYPE_DEBUG, " already there!\n"); return; } else if (GM_is_pid_bigger (prev->mid, mid)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n"); copy = copy_message (msg, mid, rel); GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv, prev, copy); return; } } copy = copy_message (msg, mid, rel); LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail!\n"); GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy); LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n"); } /** * Add a destination client to a channel, initializing all data structures * in the channel and the client. * * @param ch Channel to which add the destination. * @param c Client which to add to the channel. */ static void add_destination (struct MeshChannel *ch, struct MeshClient *c) { if (NULL != ch->dest) { GNUNET_break (0); return; } /* Assign local id as destination */ ch->lid_dest = GML_get_next_chid (c); /* Store in client's hashmap */ GML_channel_add (c, ch->lid_dest, ch); GNUNET_break (NULL == ch->dest_rel); ch->dest_rel = GNUNET_new (struct MeshChannelReliability); ch->dest_rel->ch = ch; ch->dest_rel->expected_delay.rel_value_us = 0; ch->dest_rel->retry_timer = MESH_RETRANSMIT_TIME; ch->dest = c; } /** * Set options in a channel, extracted from a bit flag field. * * @param ch Channel to set options to. * @param options Bit array in host byte order. */ static void channel_set_options (struct MeshChannel *ch, uint32_t options) { ch->nobuffer = (options & GNUNET_MESH_OPTION_NOBUFFER) != 0 ? GNUNET_YES : GNUNET_NO; ch->reliable = (options & GNUNET_MESH_OPTION_RELIABLE) != 0 ? GNUNET_YES : GNUNET_NO; } /** * Get a bit flag field with the options of a channel. * * @param ch Channel to get options from. * * @return Bit array in host byte order. */ static uint32_t channel_get_options (struct MeshChannel *ch) { uint32_t options; options = 0; if (ch->nobuffer) options |= GNUNET_MESH_OPTION_NOBUFFER; if (ch->reliable) options |= GNUNET_MESH_OPTION_RELIABLE; return options; } /** * Notify the destination client that a new incoming channel was created. * * @param ch Channel that was created. */ static void send_client_create (struct MeshChannel *ch) { uint32_t opt; if (NULL == ch->dest) return; opt = 0; opt |= GNUNET_YES == ch->reliable ? GNUNET_MESH_OPTION_RELIABLE : 0; opt |= GNUNET_YES == ch->nobuffer ? GNUNET_MESH_OPTION_NOBUFFER : 0; GML_send_channel_create (ch->dest, ch->lid_dest, ch->port, opt, GMT_get_destination (ch->t)); } /** * Send data to a client. * * If the client is ready, send directly, otherwise buffer while listening * for a local ACK. * * @param ch Channel * @param msg Message. * @param fwd Is this a fwd (root->dest) message? */ static void send_client_data (struct MeshChannel *ch, const struct GNUNET_MESH_Data *msg, int fwd) { if (fwd) { if (ch->dest_rel->client_ready) GML_send_data (ch->dest, msg, ch->lid_dest); else add_buffered_data (msg, ch->dest_rel); } else { if (ch->root_rel->client_ready) GML_send_data (ch->root, msg, ch->lid_root); else add_buffered_data (msg, ch->root_rel); } } /** * Send a buffered message to the client, for in order delivery or * as result of client ACK. * * @param ch Channel on which to empty the message buffer. * @param c Client to send to. * @param fwd Is this to send FWD data?. */ static void send_client_buffered_data (struct MeshChannel *ch, struct MeshClient *c, int fwd) { struct MeshReliableMessage *copy; struct MeshChannelReliability *rel; LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n"); rel = fwd ? ch->dest_rel : ch->root_rel; if (GNUNET_NO == rel->client_ready) { LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n"); return; } copy = rel->head_recv; /* We never buffer channel management messages */ if (NULL != copy) { if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable) { struct GNUNET_MESH_Data *msg = (struct GNUNET_MESH_Data *) ©[1]; LOG (GNUNET_ERROR_TYPE_DEBUG, " have %u! now expecting %u\n", copy->mid, rel->mid_recv + 1); send_client_data (ch, msg, fwd); rel->n_recv--; rel->mid_recv++; GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE RECV %p\n", copy); GNUNET_free (copy); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " reliable && don't have %u, next is %u\n", rel->mid_recv, copy->mid); return; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n"); } /** * Allow a client to send more data. * * In case the client was already allowed to send data, do nothing. * * @param ch Channel. * @param fwd Is this a FWD ACK? (FWD ACKs are sent to root) */ static void send_client_ack (struct MeshChannel *ch, int fwd) { struct MeshChannelReliability *rel = fwd ? ch->root_rel : ch->dest_rel; struct MeshClient *c = fwd ? ch->root : ch->dest; if (NULL == c) { GNUNET_break (GNUNET_NO != ch->destroy); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " sending %s ack to client on channel %s\n", GM_f2s (fwd), GMCH_2s (ch)); if (NULL == rel) { GNUNET_break (0); return; } if (GNUNET_YES == rel->client_allowed) { LOG (GNUNET_ERROR_TYPE_DEBUG, " already allowed\n"); return; } rel->client_allowed = GNUNET_YES; GML_send_ack (c, fwd ? ch->lid_root : ch->lid_dest); } /** * Notify the root that the destination rejected the channel. * * @param ch Rejected channel. */ static void send_client_nack (struct MeshChannel *ch) { if (NULL == ch->root) { GNUNET_break (0); return; } GML_send_channel_nack (ch->root, ch->lid_root); } /** * We haven't received an ACK after a certain time: restransmit the message. * * @param cls Closure (MeshChannelReliability with the message to restransmit) * @param tc TaskContext. */ static void channel_retransmit_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshChannelReliability *rel = cls; struct MeshReliableMessage *copy; struct MeshChannel *ch; struct GNUNET_MESH_Data *payload; int fwd; rel->retry_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; ch = rel->ch; copy = rel->head_sent; if (NULL == copy) { GNUNET_break (0); return; } payload = (struct GNUNET_MESH_Data *) ©[1]; fwd = (rel == ch->root_rel); /* Message not found in the queue that we are going to use. */ LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid); GMCH_send_prebuilt_message (&payload->header, ch, fwd, copy); GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); } /** * We haven't received an Channel ACK after a certain time: resend the CREATE. * * @param cls Closure (MeshChannelReliability of the channel to recreate) * @param tc TaskContext. */ static void channel_recreate (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshChannelReliability *rel = cls; rel->retry_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RE-CREATE\n"); GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); if (rel == rel->ch->root_rel) { send_create (rel->ch); } else if (rel == rel->ch->dest_rel) { send_ack (rel->ch, GNUNET_YES, GNUNET_NO); } else { GNUNET_break (0); } } /** * Message has been sent: start retransmission timer. * * @param cls Closure (queue structure). * @param t Tunnel. * @param q Queue handler (no longer valid). * @param type Type of message. * @param size Size of the message. */ static void ch_message_sent (void *cls, struct MeshTunnel3 *t, struct MeshTunnel3Queue *q, uint16_t type, size_t size) { struct MeshChannelQueue *chq = cls; struct MeshReliableMessage *copy = chq->copy; struct MeshChannelReliability *rel; LOG (GNUNET_ERROR_TYPE_DEBUG, "channel message sent callback %s\n", GM_m2s (chq->type)); switch (chq->type) { case GNUNET_MESSAGE_TYPE_MESH_DATA: LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT DATA MID %u\n", copy->mid); GNUNET_assert (chq == copy->chq); copy->timestamp = GNUNET_TIME_absolute_get (); rel = copy->rel; if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task) { LOG (GNUNET_ERROR_TYPE_DEBUG, "!! scheduling retry in 4 * %s\n", GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, GNUNET_YES)); if (0 != rel->expected_delay.rel_value_us) { LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay != 0\n"); rel->retry_timer = GNUNET_TIME_relative_multiply (rel->expected_delay, MESH_RETRANSMIT_MARGIN); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay reset\n"); rel->retry_timer = MESH_RETRANSMIT_TIME; } LOG (GNUNET_ERROR_TYPE_DEBUG, "!! using delay %s\n", GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO)); rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer, &channel_retransmit_message, rel); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "!! retry task %u\n", rel->retry_task); } copy->chq = NULL; break; case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK: LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT %s\n", GM_m2s (chq->type)); rel = chq->rel; GNUNET_assert (rel->uniq == chq); rel->uniq = NULL; if (MESH_CHANNEL_READY != rel->ch->state && GNUNET_MESSAGE_TYPE_MESH_DATA_ACK != type && GNUNET_NO == rel->ch->destroy) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rel->retry_task); LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! STD BACKOFF %s\n", GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO)); rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer); rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer, &channel_recreate, rel); } break; default: GNUNET_break (0); } GNUNET_free (chq); } /** * send a channel create message. * * @param ch Channel for which to send. */ static void send_create (struct MeshChannel *ch) { struct GNUNET_MESH_ChannelCreate msgcc; msgcc.header.size = htons (sizeof (msgcc)); msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE); msgcc.chid = htonl (ch->gid); msgcc.port = htonl (ch->port); msgcc.opt = htonl (channel_get_options (ch)); GMCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL); } /** * Confirm we got a channel create or FWD ack. * * @param ch The channel to confirm. * @param fwd Should we send a FWD ACK? (going dest->root) * @param reaction This ACK is a reaction to a duplicate CREATE, don't save. */ static void send_ack (struct MeshChannel *ch, int fwd, int reaction) { struct GNUNET_MESH_ChannelManage msg; msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK); LOG (GNUNET_ERROR_TYPE_DEBUG, " sending channel %s ack for channel %s\n", GM_f2s (fwd), GMCH_2s (ch)); msg.chid = htonl (ch->gid); GMCH_send_prebuilt_message (&msg.header, ch, !fwd, reaction ? &msg : NULL); } /** * Send a message and don't keep any info about it: we won't need to cancel it * or resend it. * * @param msg Header of the message to fire away. * @param ch Channel on which the message should go. * @param force Is this a forced (undroppable) message? */ static void fire_and_forget (const struct GNUNET_MessageHeader *msg, struct MeshChannel *ch, int force) { GNUNET_break (NULL == GMT_send_prebuilt_message (msg, ch->t, NULL, force, NULL, NULL)); } /** * Notify that a channel create didn't succeed. * * @param ch The channel to reject. */ static void send_nack (struct MeshChannel *ch) { struct GNUNET_MESH_ChannelManage msg; msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK); LOG (GNUNET_ERROR_TYPE_DEBUG, " sending channel NACK for channel %s\n", GMCH_2s (ch)); msg.chid = htonl (ch->gid); GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); } /** * Notify a client that the channel is no longer valid. * * @param ch Channel that is destroyed. * @param local_only Should we avoid sending it to other peers? */ static void send_destroy (struct MeshChannel *ch, int local_only) { struct GNUNET_MESH_ChannelManage msg; msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY); msg.header.size = htons (sizeof (msg)); msg.chid = htonl (ch->gid); /* If root is not NULL, notify. * If it's NULL, check lid_root. When a local destroy comes in, root * is set to NULL but lid_root is left untouched. In this case, do nothing, * the client is the one who reuqested the channel to be destroyed. */ if (NULL != ch->root) GML_send_channel_destroy (ch->root, ch->lid_root); else if (0 == ch->lid_root && GNUNET_NO == local_only) GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); if (NULL != ch->dest) GML_send_channel_destroy (ch->dest, ch->lid_dest); else if (0 == ch->lid_dest && GNUNET_NO == local_only) GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL); } /** * Destroy all reliable messages queued for a channel, * during a channel destruction. * Frees the reliability structure itself. * * @param rel Reliability data for a channel. */ static void channel_rel_free_all (struct MeshChannelReliability *rel) { struct MeshReliableMessage *copy; struct MeshReliableMessage *next; if (NULL == rel) return; for (copy = rel->head_recv; NULL != copy; copy = next) { next = copy->next; GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH RECV %p\n", copy); GNUNET_break (NULL == copy->chq); GNUNET_free (copy); } for (copy = rel->head_sent; NULL != copy; copy = next) { next = copy->next; GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH %p\n", copy); if (NULL != copy->chq) { if (NULL != copy->chq->tq) { GMT_cancel (copy->chq->tq); /* ch_message_sent will free copy->q */ } else { GNUNET_free (copy->chq); GNUNET_break (0); } } GNUNET_free (copy); } if (NULL != rel->uniq && NULL != rel->uniq->tq) { GMT_cancel (rel->uniq->tq); /* ch_message_sent is called freeing uniq */ } if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) { GNUNET_SCHEDULER_cancel (rel->retry_task); rel->retry_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (rel); } /** * Mark future messages as ACK'd. * * @param rel Reliability data. * @param msg DataACK message with a bitfield of future ACK'd messages. */ static void channel_rel_free_sent (struct MeshChannelReliability *rel, const struct GNUNET_MESH_DataACK *msg) { struct MeshReliableMessage *copy; struct MeshReliableMessage *next; uint64_t bitfield; uint64_t mask; uint32_t mid; uint32_t target; unsigned int i; bitfield = msg->futures; mid = ntohl (msg->mid); LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! free_sent_reliable %u %llX\n", mid, bitfield); LOG (GNUNET_ERROR_TYPE_DEBUG, " rel %p, head %p\n", rel, rel->head_sent); for (i = 0, copy = rel->head_sent; i < 64 && NULL != copy && 0 != bitfield; i++) { LOG (GNUNET_ERROR_TYPE_DEBUG, " trying bit %u (mid %u)\n", i, mid + i + 1); mask = 0x1LL << i; if (0 == (bitfield & mask)) continue; LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n"); /* Bit was set, clear the bit from the bitfield */ bitfield &= ~mask; /* The i-th bit was set. Do we have that copy? */ /* Skip copies with mid < target */ target = mid + i + 1; LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target); while (NULL != copy && GM_is_pid_bigger (target, copy->mid)) copy = copy->next; /* Did we run out of copies? (previously freed, it's ok) */ if (NULL == copy) { LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n"); return; } /* Did we overshoot the target? (previously freed, it's ok) */ if (GM_is_pid_bigger (copy->mid, target)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid); continue; } /* Now copy->mid == target, free it */ next = copy->next; GNUNET_break (GNUNET_YES != rel_message_free (copy, GNUNET_YES)); copy = next; } LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n"); } /** * Destroy a reliable message after it has been acknowledged, either by * direct mid ACK or bitfield. Updates the appropriate data structures and * timers and frees all memory. * * @param copy Message that is no longer needed: remote peer got it. * @param update_time Is the timing information relevant? * If this message is ACK in a batch the timing information * is skewed by the retransmission, count only for the * retransmitted message. * * @return #GNUNET_YES if channel was destroyed as a result of the call, * #GNUNET_NO otherwise. */ static int rel_message_free (struct MeshReliableMessage *copy, int update_time) { struct MeshChannelReliability *rel; struct GNUNET_TIME_Relative time; rel = copy->rel; LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Freeing %u\n", copy->mid); if (update_time) { time = GNUNET_TIME_absolute_get_duration (copy->timestamp); if (0 == rel->expected_delay.rel_value_us) rel->expected_delay = time; else { rel->expected_delay.rel_value_us *= 7; rel->expected_delay.rel_value_us += time.rel_value_us; rel->expected_delay.rel_value_us /= 8; } LOG (GNUNET_ERROR_TYPE_INFO, "!!! took %s, new delay %s\n", GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO), GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, GNUNET_NO)); rel->retry_timer = rel->expected_delay; } else { LOG (GNUNET_ERROR_TYPE_INFO, "!!! batch free, ignoring timing\n"); } rel->ch->pending_messages--; if (NULL != copy->chq) { GMT_cancel (copy->chq->tq); /* copy->q is set to NULL by ch_message_sent */ } GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE %p\n", copy); GNUNET_free (copy); if (GNUNET_NO != rel->ch->destroy && 0 == rel->ch->pending_messages) { struct MeshTunnel3 *t = rel->ch->t; GMCH_destroy (rel->ch); GMT_destroy_if_empty (t); return GNUNET_YES; } return GNUNET_NO; } /** * Channel was ACK'd by remote peer, mark as ready and cancel retransmission. * * @param ch Channel to mark as ready. * @param fwd Was the ACK message a FWD ACK? (dest->root, SYNACK) */ static void channel_confirm (struct MeshChannel *ch, int fwd) { struct MeshChannelReliability *rel; enum MeshChannelState oldstate; rel = fwd ? ch->root_rel : ch->dest_rel; if (NULL == rel) { GNUNET_break (GNUNET_NO != ch->destroy); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " channel confirm %s %s\n", GM_f2s (fwd), GMCH_2s (ch)); oldstate = ch->state; ch->state = MESH_CHANNEL_READY; if (MESH_CHANNEL_READY != oldstate || GNUNET_YES == is_loopback (ch)) { rel->client_ready = GNUNET_YES; rel->expected_delay = rel->retry_timer; LOG (GNUNET_ERROR_TYPE_DEBUG, " !! retry timer confirm %s\n", GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO)); if (GMT_get_connections_buffer (ch->t) > 0 || GMT_is_loopback (ch->t)) send_client_ack (ch, fwd); if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) { GNUNET_SCHEDULER_cancel (rel->retry_task); rel->retry_task = GNUNET_SCHEDULER_NO_TASK; } else if (NULL != rel->uniq) { GMT_cancel (rel->uniq->tq); /* ch_message_sent will free and NULL uniq */ } else { if (GNUNET_NO == is_loopback (ch)) { /* We SHOULD have been trying to retransmit this! */ GNUNET_break (0); } } } /* In case of a FWD ACK (SYNACK) send a BCK ACK (ACK). */ if (GNUNET_YES == fwd) send_ack (ch, GNUNET_NO, GNUNET_NO); } /** * Save a copy to retransmit in case it gets lost. * * Initializes all needed callbacks and timers. * * @param ch Channel this message goes on. * @param msg Message to copy. * @param fwd Is this fwd traffic? */ static struct MeshReliableMessage * channel_save_copy (struct MeshChannel *ch, const struct GNUNET_MessageHeader *msg, int fwd) { struct MeshChannelReliability *rel; struct MeshReliableMessage *copy; uint32_t mid; uint16_t type; uint16_t size; rel = fwd ? ch->root_rel : ch->dest_rel; mid = rel->mid_send - 1; type = ntohs (msg->type); size = ntohs (msg->size); LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SAVE %u %s\n", mid, GM_m2s (type)); copy = GNUNET_malloc (sizeof (struct MeshReliableMessage) + size); LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", copy); copy->mid = mid; copy->rel = rel; copy->type = type; memcpy (©[1], msg, size); GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy); ch->pending_messages++; return copy; } /** * Create a new channel. * * @param t Tunnel this channel is in. * @param owner Client that owns the channel, NULL for foreign channels. * @param lid_root Local ID for root client. * * @return A new initialized channel. NULL on error. */ static struct MeshChannel * channel_new (struct MeshTunnel3 *t, struct MeshClient *owner, MESH_ChannelNumber lid_root) { struct MeshChannel *ch; ch = GNUNET_new (struct MeshChannel); ch->root = owner; ch->lid_root = lid_root; ch->t = t; GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); if (NULL != owner) { ch->gid = GMT_get_next_chid (t); GML_channel_add (owner, lid_root, ch); } GMT_add_channel (t, ch); return ch; } /** * Handle a loopback message: call the appropriate handler for the message type. * * @param ch Channel this message is on. * @param msgh Message header. * @param fwd Is this FWD traffic? */ void handle_loopback (struct MeshChannel *ch, const struct GNUNET_MessageHeader *msgh, int fwd) { uint16_t type; type = ntohs (msgh->type); LOG (GNUNET_ERROR_TYPE_DEBUG, "Loopback %s %s message!\n", GM_f2s (fwd), GM_m2s (type)); switch (type) { case GNUNET_MESSAGE_TYPE_MESH_DATA: /* Don't send hop ACK, wait for client to ACK */ LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SEND loopback %u (%u)\n", ntohl (((struct GNUNET_MESH_Data *) msgh)->mid), ntohs (msgh->size)); GMCH_handle_data (ch, (struct GNUNET_MESH_Data *) msgh, fwd); break; case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK: GMCH_handle_data_ack (ch, (struct GNUNET_MESH_DataACK *) msgh, fwd); break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: GMCH_handle_create (ch->t, (struct GNUNET_MESH_ChannelCreate *) msgh); break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK: GMCH_handle_ack (ch, (struct GNUNET_MESH_ChannelManage *) msgh, fwd); break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK: GMCH_handle_nack (ch); break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: GMCH_handle_destroy (ch, (struct GNUNET_MESH_ChannelManage *) msgh, fwd); break; default: GNUNET_break_op (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "end-to-end message not known (%u)\n", ntohs (msgh->type)); } } /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Destroy a channel and free all resources. * * @param ch Channel to destroy. */ void GMCH_destroy (struct MeshChannel *ch) { struct MeshClient *c; if (NULL == ch) return; if (2 == ch->destroy) return; /* recursive call */ ch->destroy = 2; LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n", GMT_2s (ch->t), ch->gid); GMCH_debug (ch); c = ch->root; if (NULL != c) { GML_channel_remove (c, ch->lid_root, ch); } c = ch->dest; if (NULL != c) { GML_channel_remove (c, ch->lid_dest, ch); } channel_rel_free_all (ch->root_rel); channel_rel_free_all (ch->dest_rel); GMT_remove_channel (ch->t, ch); GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO); GNUNET_free (ch); } /** * Get the channel's public ID. * * @param ch Channel. * * @return ID used to identify the channel with the remote peer. */ MESH_ChannelNumber GMCH_get_id (const struct MeshChannel *ch) { return ch->gid; } /** * Get the channel tunnel. * * @param ch Channel to get the tunnel from. * * @return tunnel of the channel. */ struct MeshTunnel3 * GMCH_get_tunnel (const struct MeshChannel *ch) { return ch->t; } /** * Get free buffer space towards the client on a specific channel. * * @param ch Channel. * @param fwd Is query about FWD traffic? * * @return Free buffer space [0 - 64] */ unsigned int GMCH_get_buffer (struct MeshChannel *ch, int fwd) { struct MeshChannelReliability *rel; rel = fwd ? ch->dest_rel : ch->root_rel; /* If rel is NULL it means that the end is not yet created, * most probably is a loopback channel at the point of sending * the ChannelCreate to itself. */ if (NULL == rel) return 64; return (64 - rel->n_recv); } /** * Get flow control status of end point: is client allow to send? * * @param ch Channel. * @param fwd Is query about FWD traffic? (Request root status). * * @return #GNUNET_YES if client is allowed to send us data. */ int GMCH_get_allowed (struct MeshChannel *ch, int fwd) { struct MeshChannelReliability *rel; rel = fwd ? ch->root_rel : ch->dest_rel; if (NULL == rel) { /* Probably shutting down: root/dest NULL'ed to mark disconnection */ GNUNET_break (GNUNET_NO != ch->destroy); return 0; } return rel->client_allowed; } /** * Is the root client for this channel on this peer? * * @param ch Channel. * @param fwd Is this for fwd traffic? * * @return #GNUNET_YES in case it is. */ int GMCH_is_origin (struct MeshChannel *ch, int fwd) { struct MeshClient *c; c = fwd ? ch->root : ch->dest; return NULL != c; } /** * Is the destination client for this channel on this peer? * * @param ch Channel. * @param fwd Is this for fwd traffic? * * @return #GNUNET_YES in case it is. */ int GMCH_is_terminal (struct MeshChannel *ch, int fwd) { struct MeshClient *c; c = fwd ? ch->dest : ch->root; return NULL != c; } /** * Send an end-to-end ACK message for the most recent in-sequence payload. * * If channel is not reliable, do nothing. * * @param ch Channel this is about. * @param fwd Is for FWD traffic? (ACK dest->owner) */ void GMCH_send_data_ack (struct MeshChannel *ch, int fwd) { struct GNUNET_MESH_DataACK msg; struct MeshChannelReliability *rel; struct MeshReliableMessage *copy; unsigned int delta; uint64_t mask; uint32_t ack; if (GNUNET_NO == ch->reliable) { return; } rel = fwd ? ch->dest_rel : ch->root_rel; ack = rel->mid_recv - 1; LOG (GNUNET_ERROR_TYPE_INFO, "=> DATA_ACK for %u\n", ack); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_DATA_ACK); msg.header.size = htons (sizeof (msg)); msg.chid = htonl (ch->gid); msg.futures = 0; for (copy = rel->head_recv; NULL != copy; copy = copy->next) { if (copy->type != GNUNET_MESSAGE_TYPE_MESH_DATA) { LOG (GNUNET_ERROR_TYPE_DEBUG, "!! Type %s, expected DATA\n", GM_m2s (copy->type)); continue; } if (copy->mid == ack + 1) { ack++; continue; } delta = copy->mid - (ack + 1); if (63 < delta) break; mask = 0x1LL << delta; msg.futures |= mask; LOG (GNUNET_ERROR_TYPE_DEBUG, " !! setting bit for %u (delta %u) (%llX) -> %llX\n", copy->mid, delta, mask, msg.futures); } msg.mid = htonl (ack); LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! ACK for %u, futures %llX\n", ack, msg.futures); GMCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n"); } /** * Allow a client to send us more data, in case it was choked. * * @param ch Channel. * @param fwd Is this about FWD traffic? (Root client). */ void GMCH_allow_client (struct MeshChannel *ch, int fwd) { struct MeshChannelReliability *rel; unsigned int buffer; LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n"); if (MESH_CHANNEL_READY != ch->state) { LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n"); return; } if (GNUNET_YES == ch->reliable) { rel = fwd ? ch->root_rel : ch->dest_rel; if (NULL == rel) { GNUNET_break (GNUNET_NO != ch->destroy); return; } if (NULL != rel->head_sent) { if (64 <= rel->mid_send - rel->head_sent->mid) { LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n"); return; } else LOG (GNUNET_ERROR_TYPE_DEBUG, " gap ok: %u - %u\n", rel->head_sent->mid, rel->mid_send); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " head sent is NULL\n"); } } if (is_loopback (ch)) buffer = GMCH_get_buffer (ch, fwd); else buffer = GMT_get_connections_buffer (ch->t); if (0 == buffer) { LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n"); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer); send_client_ack (ch, fwd); } /** * Log channel info. * * @param ch Channel. */ void GMCH_debug (struct MeshChannel *ch) { if (NULL == ch) { LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CHANNEL ***\n"); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %s:%X (%p)\n", GMT_2s (ch->t), ch->gid, ch); LOG (GNUNET_ERROR_TYPE_DEBUG, " root %p/%p\n", ch->root, ch->root_rel); if (NULL != ch->root) { LOG (GNUNET_ERROR_TYPE_DEBUG, " cli %s\n", GML_2s (ch->root)); LOG (GNUNET_ERROR_TYPE_DEBUG, " ready %s\n", ch->root_rel->client_ready ? "YES" : "NO"); LOG (GNUNET_ERROR_TYPE_DEBUG, " id %X\n", ch->lid_root); } LOG (GNUNET_ERROR_TYPE_DEBUG, " dest %p/%p\n", ch->dest, ch->dest_rel); if (NULL != ch->dest) { LOG (GNUNET_ERROR_TYPE_DEBUG, " cli %s\n", GML_2s (ch->dest)); LOG (GNUNET_ERROR_TYPE_DEBUG, " ready %s\n", ch->dest_rel->client_ready ? "YES" : "NO"); LOG (GNUNET_ERROR_TYPE_DEBUG, " id %X\n", ch->lid_dest); } } /** * Handle an ACK given by a client. * * Mark client as ready and send him any buffered data we could have for him. * * @param ch Channel. * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK) */ void GMCH_handle_local_ack (struct MeshChannel *ch, int fwd) { struct MeshChannelReliability *rel; struct MeshClient *c; rel = fwd ? ch->dest_rel : ch->root_rel; c = fwd ? ch->dest : ch->root; rel->client_ready = GNUNET_YES; send_client_buffered_data (ch, c, fwd); if (is_loopback (ch)) { unsigned int buffer; buffer = GMCH_get_buffer (ch, fwd); if (0 < buffer) GMCH_allow_client (ch, fwd); return; } GMT_send_connection_acks (ch->t); } /** * Handle data given by a client. * * Check whether the client is allowed to send in this tunnel, save if channel * is reliable and send an ACK to the client if there is still buffer space * in the tunnel. * * @param ch Channel. * @param c Client which sent the data. * @param message Message. * @param fwd Is this a FWD data? * * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error. */ int GMCH_handle_local_data (struct MeshChannel *ch, struct MeshClient *c, struct GNUNET_MessageHeader *message, int fwd) { struct MeshChannelReliability *rel; struct GNUNET_MESH_Data *payload; size_t size = ntohs (message->size); uint16_t p2p_size = sizeof(struct GNUNET_MESH_Data) + size; unsigned char cbuf[p2p_size]; /* Is the client in the channel? */ if ( !( (fwd && ch->root == c) || (!fwd && ch->dest == c) ) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } rel = fwd ? ch->root_rel : ch->dest_rel; if (GNUNET_NO == rel->client_allowed) { GNUNET_break_op (0); return GNUNET_SYSERR; } rel->client_allowed = GNUNET_NO; /* Ok, everything is correct, send the message. */ payload = (struct GNUNET_MESH_Data *) cbuf; payload->mid = htonl (rel->mid_send); rel->mid_send++; memcpy (&payload[1], message, size); payload->header.size = htons (p2p_size); payload->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_DATA); payload->chid = htonl (ch->gid); LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n"); GMCH_send_prebuilt_message (&payload->header, ch, fwd, NULL); if (is_loopback (ch)) { if (GMCH_get_buffer (ch, fwd) > 0) GMCH_allow_client (ch, fwd); return GNUNET_OK; } if (GMT_get_connections_buffer (ch->t) > 0) { GMCH_allow_client (ch, fwd); } return GNUNET_OK; } /** * Handle a channel destroy requested by a client. * * Destroy the channel and the tunnel in case this was the last channel. * * @param ch Channel. * @param c Client that requested the destruction (to avoid notifying him). * @param is_root Is the request coming from root? */ void GMCH_handle_local_destroy (struct MeshChannel *ch, struct MeshClient *c, int is_root) { struct MeshTunnel3 *t; ch->destroy = GNUNET_YES; /* Cleanup after the tunnel */ if (GNUNET_NO == is_root && c == ch->dest) { LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c)); GML_client_delete_channel (c, ch, ch->lid_dest); ch->dest = NULL; } if (GNUNET_YES == is_root && c == ch->root) { LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c)); GML_client_delete_channel (c, ch, ch->lid_root); ch->root = NULL; } t = ch->t; send_destroy (ch, GNUNET_NO); if (0 == ch->pending_messages) { GMCH_destroy (ch); GMT_destroy_if_empty (t); } } /** * Handle a channel create requested by a client. * * Create the channel and the tunnel in case this was the first0 channel. * * @param c Client that requested the creation (will be the root). * @param msg Create Channel message. * * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise. */ int GMCH_handle_local_create (struct MeshClient *c, struct GNUNET_MESH_ChannelMessage *msg) { struct MeshChannel *ch; struct MeshTunnel3 *t; struct MeshPeer *peer; MESH_ChannelNumber chid; LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n", GNUNET_i2s (&msg->peer), ntohl (msg->port)); chid = ntohl (msg->channel_id); /* Sanity check for duplicate channel IDs */ if (NULL != GML_channel_get (c, chid)) { GNUNET_break (0); return GNUNET_SYSERR; } peer = GMP_get (&msg->peer); GMP_add_tunnel (peer); t = GMP_get_tunnel (peer); if (GMP_get_short_id (peer) == myid) { GMT_change_cstate (t, MESH_TUNNEL3_READY); } else { /* FIXME change to a tunnel API, eliminate ch <-> peer connection */ GMP_connect (peer); } /* Create channel */ ch = channel_new (t, c, chid); if (NULL == ch) { GNUNET_break (0); return GNUNET_SYSERR; } ch->port = ntohl (msg->port); channel_set_options (ch, ntohl (msg->opt)); /* In unreliable channels, we'll use the DLL to buffer BCK data */ ch->root_rel = GNUNET_new (struct MeshChannelReliability); ch->root_rel->ch = ch; ch->root_rel->retry_timer = MESH_RETRANSMIT_TIME; ch->root_rel->expected_delay.rel_value_us = 0; LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s\n", GMCH_2s (ch)); send_create (ch); return GNUNET_OK; } /** * Handler for mesh network payload traffic. * * @param ch Channel for the message. * @param msg Unencryted data message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ void GMCH_handle_data (struct MeshChannel *ch, const struct GNUNET_MESH_Data *msg, int fwd) { struct MeshChannelReliability *rel; struct MeshClient *c; uint32_t mid; /* If this is a remote (non-loopback) channel, find 'fwd'. */ if (GNUNET_SYSERR == fwd) { if (is_loopback (ch)) { /* It is a loopback channel after all... */ GNUNET_break (0); return; } fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; } /* Initialize FWD/BCK data */ c = fwd ? ch->dest : ch->root; rel = fwd ? ch->dest_rel : ch->root_rel; if (NULL == c) { GNUNET_break (GNUNET_NO != ch->destroy); return; } if (MESH_CHANNEL_READY != ch->state) { if (GNUNET_NO == fwd) { /* If we are the root, this means the other peer has sent traffic before * receiving our ACK. Even if the SYNACK goes missing, no traffic should * be sent before the ACK. */ GNUNET_break_op (0); return; } /* If we are the dest, this means that the SYNACK got to the root but * the ACK went missing. Treat this as an ACK. */ channel_confirm (ch, GNUNET_NO); } GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO); mid = ntohl (msg->mid); LOG (GNUNET_ERROR_TYPE_DEBUG, "!! got mid %u\n", mid); if (GNUNET_NO == ch->reliable || ( !GM_is_pid_bigger (rel->mid_recv, mid) && GM_is_pid_bigger (rel->mid_recv + 64, mid) ) ) { LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RECV %u (%u)\n", mid, ntohs (msg->header.size)); if (GNUNET_YES == ch->reliable) { /* Is this the exact next expected messasge? */ if (mid == rel->mid_recv) { LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected\n"); rel->mid_recv++; send_client_data (ch, msg, fwd); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n"); add_buffered_data (msg, rel); } } else { /* Tunnel is unreliable: send to clients directly */ /* FIXME: accept Out Of Order traffic */ rel->mid_recv = mid + 1; send_client_data (ch, msg, fwd); } } else { GNUNET_break_op (GM_is_pid_bigger (rel->mid_recv, mid)); LOG (GNUNET_ERROR_TYPE_WARNING, "MID %u not expected (%u - %u), dropping!\n", mid, rel->mid_recv, rel->mid_recv + 63); } GMCH_send_data_ack (ch, fwd); } /** * Handler for mesh network traffic end-to-end ACKs. * * @param ch Channel on which we got this message. * @param msg Data message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ void GMCH_handle_data_ack (struct MeshChannel *ch, const struct GNUNET_MESH_DataACK *msg, int fwd) { struct MeshChannelReliability *rel; struct MeshReliableMessage *copy; struct MeshReliableMessage *next; uint32_t ack; int work; /* If this is a remote (non-loopback) channel, find 'fwd'. */ if (GNUNET_SYSERR == fwd) { if (is_loopback (ch)) { /* It is a loopback channel after all... */ GNUNET_break (0); return; } /* Inverted: if message came 'FWD' is a 'BCK ACK'. */ fwd = (NULL != ch->dest) ? GNUNET_NO : GNUNET_YES; } ack = ntohl (msg->mid); LOG (GNUNET_ERROR_TYPE_INFO, "<= %s ACK %u\n", GM_f2s (fwd), ack); if (GNUNET_YES == fwd) { rel = ch->root_rel; } else { rel = ch->dest_rel; } if (NULL == rel) { GNUNET_break_op (GNUNET_NO != ch->destroy); return; } /* Free ACK'd copies: no need to retransmit those anymore FIXME refactor */ for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next) { if (GM_is_pid_bigger (copy->mid, ack)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " head %u, out!\n", copy->mid); channel_rel_free_sent (rel, msg); break; } work = GNUNET_YES; LOG (GNUNET_ERROR_TYPE_DEBUG, " id %u\n", copy->mid); next = copy->next; if (GNUNET_YES == rel_message_free (copy, GNUNET_YES)) return; } /* ACK client if needed and possible */ GMCH_allow_client (ch, fwd); /* If some message was free'd, update the retransmission delay */ if (GNUNET_YES == work) { if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) { GNUNET_SCHEDULER_cancel (rel->retry_task); rel->retry_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != rel->head_sent && NULL == rel->head_sent->chq) { struct GNUNET_TIME_Absolute new_target; struct GNUNET_TIME_Relative delay; delay = GNUNET_TIME_relative_multiply (rel->retry_timer, MESH_RETRANSMIT_MARGIN); new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp, delay); delay = GNUNET_TIME_absolute_get_remaining (new_target); rel->retry_task = GNUNET_SCHEDULER_add_delayed (delay, &channel_retransmit_message, rel); } } else { /* Work was done but no task was pending? Shouldn't happen! */ GNUNET_break (0); } } } /** * Handler for channel create messages. * * Does not have fwd parameter because it's always 'FWD': channel is incoming. * * @param t Tunnel this channel will be in. * @param msg Channel crate message. */ struct MeshChannel * GMCH_handle_create (struct MeshTunnel3 *t, const struct GNUNET_MESH_ChannelCreate *msg) { MESH_ChannelNumber chid; struct MeshChannel *ch; struct MeshClient *c; int new_channel; int reaction; reaction = GNUNET_NO; chid = ntohl (msg->chid); ch = GMT_get_channel (t, chid); if (NULL == ch) { /* Create channel */ ch = channel_new (t, NULL, 0); ch->gid = chid; channel_set_options (ch, ntohl (msg->opt)); new_channel = GNUNET_YES; } else { new_channel = GNUNET_NO; } if (GNUNET_YES == new_channel || GMT_is_loopback (t)) { /* Find a destination client */ ch->port = ntohl (msg->port); LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", ch->port); c = GML_client_get_by_port (ch->port); if (NULL == c) { LOG (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n"); if (is_loopback (ch)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback: destroy on handler\n"); send_nack (ch); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " not loopback: destroy now\n"); send_nack (ch); GMCH_destroy (ch); } return NULL; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " client %p has port registered\n", c); } add_destination (ch, c); if (GNUNET_YES == ch->reliable) LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n"); else LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Not Reliable\n"); send_client_create (ch); ch->state = MESH_CHANNEL_SENT; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate create channel\n"); reaction = GNUNET_YES; if (GNUNET_SCHEDULER_NO_TASK != ch->dest_rel->retry_task) { LOG (GNUNET_ERROR_TYPE_DEBUG, " clearing retry task\n"); /* we were waiting to re-send our 'SYNACK', wait no more! */ GNUNET_SCHEDULER_cancel (ch->dest_rel->retry_task); ch->dest_rel->retry_task = GNUNET_SCHEDULER_NO_TASK; } } send_ack (ch, GNUNET_YES, reaction); return ch; } /** * Handler for channel NACK messages. * * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter. * * @param ch Channel. */ void GMCH_handle_nack (struct MeshChannel *ch) { send_client_nack (ch); GMCH_destroy (ch); } /** * Handler for channel ack messages. * * @param ch Channel. * @param msg Message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ void GMCH_handle_ack (struct MeshChannel *ch, const struct GNUNET_MESH_ChannelManage *msg, int fwd) { /* If this is a remote (non-loopback) channel, find 'fwd'. */ if (GNUNET_SYSERR == fwd) { if (is_loopback (ch)) { /* It is a loopback channel after all... */ GNUNET_break (0); return; } fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; } channel_confirm (ch, !fwd); } /** * Handler for channel destroy messages. * * @param ch Channel to be destroyed of. * @param msg Message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ void GMCH_handle_destroy (struct MeshChannel *ch, const struct GNUNET_MESH_ChannelManage *msg, int fwd) { struct MeshTunnel3 *t; /* If this is a remote (non-loopback) channel, find 'fwd'. */ if (GNUNET_SYSERR == fwd) { if (is_loopback (ch)) { /* It is a loopback channel after all... */ GNUNET_break (0); return; } fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; } GMCH_debug (ch); if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) ) { /* Not for us (don't destroy twice a half-open loopback channel) */ return; } t = ch->t; send_destroy (ch, GNUNET_YES); GMCH_destroy (ch); GMT_destroy_if_empty (t); } /** * Sends an already built message on a channel. * * If the channel is on a loopback tunnel, notifies the appropriate destination * client locally. * * On a normal channel passes the message to the tunnel for encryption and * sending on a connection. * * This function DOES NOT save the message for retransmission. * * @param message Message to send. Function makes a copy of it. * @param ch Channel on which this message is transmitted. * @param fwd Is this a fwd message? * @param existing_copy This is a retransmission, don't save a copy. */ void GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, struct MeshChannel *ch, int fwd, void *existing_copy) { struct MeshChannelQueue *chq; uint16_t type; type = ntohs (message->type); LOG (GNUNET_ERROR_TYPE_INFO, "=> %s %s on channel %s\n", GM_m2s (type), GM_f2s (fwd), GMCH_2s (ch)); if (GMT_is_loopback (ch->t)) { handle_loopback (ch, message, fwd); return; } switch (type) { struct GNUNET_MESH_Data *payload; case GNUNET_MESSAGE_TYPE_MESH_DATA: payload = (struct GNUNET_MESH_Data *) message; LOG (GNUNET_ERROR_TYPE_INFO, "=> %s %u\n", GM_m2s (type), ntohl (payload->mid)); if (GNUNET_YES == ch->reliable) { chq = GNUNET_new (struct MeshChannelQueue); chq->type = type; if (NULL == existing_copy) chq->copy = channel_save_copy (ch, message, fwd); else { chq->copy = (struct MeshReliableMessage *) existing_copy; if (NULL != chq->copy->chq) { /* Last retransmission was queued but not yet sent! * This retransmission was scheduled by a ch_message_sent which * followed a very fast RTT, so the tiny delay made the * retransmission function to execute before the previous * retransmitted message even had a chance to leave the peer. * Cancel this message and wait until the pending * retransmission leaves the peer and ch_message_sent starts * the timer for the next one. */ GNUNET_free (chq); LOG (GNUNET_ERROR_TYPE_DEBUG, " exisitng copy not yet transmitted!\n"); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " using existing copy: %p {r:%p q:%p t:%u}\n", existing_copy, chq->copy->rel, chq->copy->chq, chq->copy->type); } LOG (GNUNET_ERROR_TYPE_DEBUG, " new chq: %p\n", chq); chq->copy->chq = chq; chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL, NULL != existing_copy, &ch_message_sent, chq); /* q itself is stored in copy */ GNUNET_assert (NULL != chq->tq || GNUNET_NO != ch->destroy); } else { fire_and_forget (message, ch, GNUNET_NO); } break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK: if (GNUNET_YES == fwd || NULL != existing_copy) { /* BCK ACK (going FWD) is just a response for a SYNACK, don't keep*/ fire_and_forget (message, ch, GNUNET_YES); return; } /* fall-trough */ case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: chq = GNUNET_new (struct MeshChannelQueue); chq->type = type; chq->rel = fwd ? ch->root_rel : ch->dest_rel; if (NULL != chq->rel->uniq) { if (NULL != chq->rel->uniq->tq) { GMT_cancel (chq->rel->uniq->tq); /* ch_message_sent is called, freeing and NULLing uniq */ } else { GNUNET_break (0); GNUNET_free (chq->rel->uniq); } } chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES, &ch_message_sent, chq); if (NULL == chq->tq) { GNUNET_break (0); GNUNET_free (chq); chq = NULL; return; } chq->rel->uniq = chq; break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK: fire_and_forget (message, ch, GNUNET_YES); break; default: GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s unknown!\n", GM_m2s (type)); fire_and_forget (message, ch, GNUNET_YES); } } /** * Get the static string for identification of the channel. * * @param ch Channel. * * @return Static string with the channel IDs. */ const char * GMCH_2s (const struct MeshChannel *ch) { static char buf[64]; if (NULL == ch) return "(NULL Channel)"; sprintf (buf, "%s:%u gid:%X (%X / %X)", GMT_2s (ch->t), ch->port, ch->gid, ch->lid_root, ch->lid_dest); return buf; } gnunet-0.10.1/src/mesh/gnunet-service-mesh_tunnel.c0000644000175000017500000021500712320526362017164 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_signatures.h" #include "gnunet_statistics_service.h" #include "mesh_protocol.h" #include "mesh_path.h" #include "gnunet-service-mesh_tunnel.h" #include "gnunet-service-mesh_connection.h" #include "gnunet-service-mesh_channel.h" #include "gnunet-service-mesh_peer.h" #define LOG(level, ...) GNUNET_log_from(level,"mesh-tun",__VA_ARGS__) #define REKEY_WAIT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5) #define CONNECTIONS_PER_TUNNEL 3 /******************************************************************************/ /******************************** STRUCTS **********************************/ /******************************************************************************/ struct MeshTChannel { struct MeshTChannel *next; struct MeshTChannel *prev; struct MeshChannel *ch; }; /** * Connection list and metadata. */ struct MeshTConnection { /** * Next in DLL. */ struct MeshTConnection *next; /** * Prev in DLL. */ struct MeshTConnection *prev; /** * Connection handle. */ struct MeshConnection *c; /** * Creation time, to keep oldest connection alive. */ struct GNUNET_TIME_Absolute created; /** * Connection throughput, to keep fastest connection alive. */ uint32_t throughput; }; /** * Structure used during a Key eXchange. */ struct MeshTunnelKXCtx { /** * Decryption ("their") old key, for decrypting traffic sent by the * other end before the key exchange started. */ struct GNUNET_CRYPTO_SymmetricSessionKey d_key_old; /** * Challenge to send in a ping and expect in the pong. */ uint32_t challenge; }; /** * Struct containing all information regarding a tunnel to a peer. */ struct MeshTunnel3 { /** * Endpoint of the tunnel. */ struct MeshPeer *peer; /** * State of the tunnel connectivity. */ enum MeshTunnel3CState cstate; /** * State of the tunnel encryption. */ enum MeshTunnel3EState estate; /** * Key eXchange context. */ struct MeshTunnelKXCtx *kx_ctx; /** * Encryption ("our") key. */ struct GNUNET_CRYPTO_SymmetricSessionKey e_key; /** * Decryption ("their") key. */ struct GNUNET_CRYPTO_SymmetricSessionKey d_key; /** * Task to start the rekey process. */ GNUNET_SCHEDULER_TaskIdentifier rekey_task; /** * Paths that are actively used to reach the destination peer. */ struct MeshTConnection *connection_head; struct MeshTConnection *connection_tail; /** * Next connection number. */ uint32_t next_cid; /** * Channels inside this tunnel. */ struct MeshTChannel *channel_head; struct MeshTChannel *channel_tail; /** * Channel ID for the next created channel. */ MESH_ChannelNumber next_chid; /** * Destroy flag: if true, destroy on last message. */ GNUNET_SCHEDULER_TaskIdentifier destroy_task; /** * Queued messages, to transmit once tunnel gets connected. */ struct MeshTunnelDelayed *tq_head; struct MeshTunnelDelayed *tq_tail; }; /** * Struct used to save messages in a non-ready tunnel to send once connected. */ struct MeshTunnelDelayed { /** * DLL */ struct MeshTunnelDelayed *next; struct MeshTunnelDelayed *prev; /** * Tunnel. */ struct MeshTunnel3 *t; /** * Tunnel queue given to the channel to cancel request. Update on send_queued. */ struct MeshTunnel3Queue *tq; /** * Message to send. */ /* struct GNUNET_MessageHeader *msg; */ }; /** * Handle for messages queued but not yet sent. */ struct MeshTunnel3Queue { /** * Connection queue handle, to cancel if necessary. */ struct MeshConnectionQueue *cq; /** * Handle in case message hasn't been given to a connection yet. */ struct MeshTunnelDelayed *tqd; /** * Continuation to call once sent. */ GMT_sent cont; /** * Closure for @c cont. */ void *cont_cls; }; /******************************************************************************/ /******************************* GLOBALS ***********************************/ /******************************************************************************/ /** * Global handle to the statistics service. */ extern struct GNUNET_STATISTICS_Handle *stats; /** * Local peer own ID (memory efficient handle). */ extern GNUNET_PEER_Id myid; /** * Local peer own ID (full value). */ extern struct GNUNET_PeerIdentity my_full_id; /** * Don't try to recover tunnels if shutting down. */ extern int shutting_down; /** * Set of all tunnels, in order to trigger a new exchange on rekey. * Indexed by peer's ID. */ static struct GNUNET_CONTAINER_MultiPeerMap *tunnels; /** * Default TTL for payload packets. */ static unsigned long long default_ttl; /** * Own private key. */ const static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; /** * Own ephemeral private key. */ static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key; /** * Cached message used to perform a key exchange. */ static struct GNUNET_MESH_KX_Ephemeral kx_msg; /** * Task to generate a new ephemeral key. */ static GNUNET_SCHEDULER_TaskIdentifier rekey_task; /** * Rekey period. */ static struct GNUNET_TIME_Relative rekey_period; /******************************************************************************/ /******************************** STATIC ***********************************/ /******************************************************************************/ /** * Get string description for tunnel connectivity state. * * @param cs Tunnel state. * * @return String representation. */ static const char * cstate2s (enum MeshTunnel3CState cs) { static char buf[128]; switch (cs) { case MESH_TUNNEL3_NEW: return "MESH_TUNNEL3_NEW"; case MESH_TUNNEL3_SEARCHING: return "MESH_TUNNEL3_SEARCHING"; case MESH_TUNNEL3_WAITING: return "MESH_TUNNEL3_WAITING"; case MESH_TUNNEL3_READY: return "MESH_TUNNEL3_READY"; default: sprintf (buf, "%u (UNKNOWN STATE)", cs); return buf; } return ""; } /** * Get string description for tunnel encryption state. * * @param es Tunnel state. * * @return String representation. */ static const char * estate2s (enum MeshTunnel3EState es) { static char buf[128]; switch (es) { case MESH_TUNNEL3_KEY_UNINITIALIZED: return "MESH_TUNNEL3_KEY_UNINITIALIZED"; case MESH_TUNNEL3_KEY_SENT: return "MESH_TUNNEL3_KEY_SENT"; case MESH_TUNNEL3_KEY_PING: return "MESH_TUNNEL3_KEY_PING"; case MESH_TUNNEL3_KEY_OK: return "MESH_TUNNEL3_KEY_OK"; default: sprintf (buf, "%u (UNKNOWN STATE)", es); return buf; } return ""; } /** * @brief Check if tunnel is ready to send traffic. * * Tunnel must be connected and with encryption correctly set up. * * @param t Tunnel to check. * * @return #GNUNET_YES if ready, #GNUNET_NO otherwise */ static int is_ready (struct MeshTunnel3 *t) { int ready; GMT_debug (t); ready = (MESH_TUNNEL3_READY == t->cstate && MESH_TUNNEL3_KEY_OK == t->estate); ready = ready || GMT_is_loopback (t); return ready; } /** * Ephemeral key message purpose size. * * @return Size of the part of the ephemeral key message that must be signed. */ size_t ephemeral_purpose_size (void) { return sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + sizeof (struct GNUNET_PeerIdentity); } /** * Size of the encrypted part of a ping message. * * @return Size of the encrypted part of a ping message. */ size_t ping_encryption_size (void) { return sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t); } /** * Get the channel's buffer. ONLY FOR NON-LOOPBACK CHANNELS!! * * @param tch Tunnel's channel handle. * * @return Amount of messages the channel can still buffer towards the client. */ static unsigned int get_channel_buffer (const struct MeshTChannel *tch) { int fwd; /* If channel is outgoing, is origin in the FWD direction and fwd is YES */ fwd = GMCH_is_origin (tch->ch, GNUNET_YES); return GMCH_get_buffer (tch->ch, fwd); } /** * Get the channel's allowance status. * * @param tch Tunnel's channel handle. * * @return #GNUNET_YES if we allowed the client to send data to us. */ static int get_channel_allowed (const struct MeshTChannel *tch) { int fwd; /* If channel is outgoing, is origin in the FWD direction and fwd is YES */ fwd = GMCH_is_origin (tch->ch, GNUNET_YES); return GMCH_get_allowed (tch->ch, fwd); } /** * Get the connection's buffer. * * @param tc Tunnel's connection handle. * * @return Amount of messages the connection can still buffer. */ static unsigned int get_connection_buffer (const struct MeshTConnection *tc) { int fwd; /* If connection is outgoing, is origin in the FWD direction and fwd is YES */ fwd = GMC_is_origin (tc->c, GNUNET_YES); return GMC_get_buffer (tc->c, fwd); } /** * Get the connection's allowance. * * @param tc Tunnel's connection handle. * * @return Amount of messages we have allowed the next peer to send us. */ static unsigned int get_connection_allowed (const struct MeshTConnection *tc) { int fwd; /* If connection is outgoing, is origin in the FWD direction and fwd is YES */ fwd = GMC_is_origin (tc->c, GNUNET_YES); return GMC_get_allowed (tc->c, fwd); } /** * Check that a ephemeral key message s well formed and correctly signed. * * @param t Tunnel on which the message came. * @param msg The ephemeral key message. * * @return GNUNET_OK if message is fine, GNUNET_SYSERR otherwise. */ int check_ephemeral (struct MeshTunnel3 *t, const struct GNUNET_MESH_KX_Ephemeral *msg) { /* Check message size */ if (ntohs (msg->header.size) != sizeof (struct GNUNET_MESH_KX_Ephemeral)) return GNUNET_SYSERR; /* Check signature size */ if (ntohl (msg->purpose.size) != ephemeral_purpose_size ()) return GNUNET_SYSERR; /* Check origin */ if (0 != memcmp (&msg->origin_identity, GMP_get_id (t->peer), sizeof (struct GNUNET_PeerIdentity))) return GNUNET_SYSERR; /* Check signature */ if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_MESH_KX, &msg->purpose, &msg->signature, &msg->origin_identity.public_key)) return GNUNET_SYSERR; return GNUNET_OK; } /** * Encrypt data with the tunnel key. * * @param t Tunnel whose key to use. * @param dst Destination for the encrypted data. * @param src Source of the plaintext. Can overlap with @c dst. * @param size Size of the plaintext. * @param iv Initialization Vector to use. */ static int t_encrypt (struct MeshTunnel3 *t, void *dst, const void *src, size_t size, uint32_t iv) { struct GNUNET_CRYPTO_SymmetricInitializationVector siv; size_t out_size; LOG (GNUNET_ERROR_TYPE_DEBUG, " t_encrypt start\n"); GNUNET_CRYPTO_symmetric_derive_iv (&siv, &t->e_key, &iv, sizeof (iv), NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, " t_encrypt IV derived\n"); out_size = GNUNET_CRYPTO_symmetric_encrypt (src, size, &t->e_key, &siv, dst); LOG (GNUNET_ERROR_TYPE_DEBUG, " t_encrypt end\n"); return out_size; } /** * Decrypt data with the tunnel key. * * @param t Tunnel whose key to use. * @param dst Destination for the plaintext. * @param src Source of the encrypted data. Can overlap with @c dst. * @param size Size of the encrypted data. * @param iv Initialization Vector to use. */ static int t_decrypt (struct MeshTunnel3 *t, void *dst, const void *src, size_t size, uint32_t iv) { struct GNUNET_CRYPTO_SymmetricInitializationVector siv; struct GNUNET_CRYPTO_SymmetricSessionKey *key; size_t out_size; LOG (GNUNET_ERROR_TYPE_DEBUG, " t_decrypt start\n"); if (t->estate == MESH_TUNNEL3_KEY_OK || t->estate == MESH_TUNNEL3_KEY_PING) { key = &t->d_key; } else if (NULL != t->kx_ctx) { key = &t->kx_ctx->d_key_old; } else { GNUNET_STATISTICS_update (stats, "# non decryptable data", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING got data on %s without a valid key\n", GMT_2s (t)); GMT_debug (t); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, " t_decrypt iv\n"); GNUNET_CRYPTO_symmetric_derive_iv (&siv, key, &iv, sizeof (iv), NULL); LOG (GNUNET_ERROR_TYPE_DEBUG, " t_decrypt iv done\n"); out_size = GNUNET_CRYPTO_symmetric_decrypt (src, size, key, &siv, dst); LOG (GNUNET_ERROR_TYPE_DEBUG, " t_decrypt end\n"); return out_size; } /** * Create key material by doing ECDH on the local and remote ephemeral keys. * * @param key_material Where to store the key material. * @param ephemeral_key Peer's public ephemeral key. */ void derive_key_material (struct GNUNET_HashCode *key_material, const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key) { if (GNUNET_OK != GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key, ephemeral_key, key_material)) { GNUNET_break (0); } } /** * Create a symmetic key from the identities of both ends and the key material * from ECDH. * * @param key Destination for the generated key. * @param sender ID of the peer that will encrypt with @c key. * @param receiver ID of the peer that will decrypt with @c key. * @param key_material Hash created with ECDH with the ephemeral keys. */ void derive_symmertic (struct GNUNET_CRYPTO_SymmetricSessionKey *key, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_PeerIdentity *receiver, const struct GNUNET_HashCode *key_material) { const char salt[] = "MESH kx salt"; GNUNET_CRYPTO_kdf (key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), salt, sizeof (salt), key_material, sizeof (struct GNUNET_HashCode), sender, sizeof (struct GNUNET_PeerIdentity), receiver, sizeof (struct GNUNET_PeerIdentity), NULL); } /** * Pick a connection on which send the next data message. * * @param t Tunnel on which to send the message. * * @return The connection on which to send the next message. */ static struct MeshConnection * tunnel_get_connection (struct MeshTunnel3 *t) { struct MeshTConnection *iter; struct MeshConnection *best; unsigned int qn; unsigned int lowest_q; LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n", GMT_2s (t)); best = NULL; lowest_q = UINT_MAX; for (iter = t->connection_head; NULL != iter; iter = iter->next) { LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s: %u\n", GMC_2s (iter->c), GMC_get_state (iter->c)); if (MESH_CONNECTION_READY == GMC_get_state (iter->c)) { qn = GMC_get_qn (iter->c, GMC_is_origin (iter->c, GNUNET_YES)); LOG (GNUNET_ERROR_TYPE_DEBUG, " q_n %u, \n", qn); if (qn < lowest_q) { best = iter->c; lowest_q = qn; } } } LOG (GNUNET_ERROR_TYPE_DEBUG, " selected: connection %s\n", GMC_2s (best)); return best; } /** * Callback called when a queued message is sent. * * Calculates the average time and connection packet tracking. * * @param cls Closure (TunnelQueue handle). * @param c Connection this message was on. * @param q Connection queue handle (unused). * @param type Type of message sent. * @param fwd Was this a FWD going message? * @param size Size of the message. */ static void tun_message_sent (void *cls, struct MeshConnection *c, struct MeshConnectionQueue *q, uint16_t type, int fwd, size_t size) { struct MeshTunnel3Queue *qt = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "tun_message_sent\n"); GNUNET_assert (NULL != qt->cont); qt->cont (qt->cont_cls, GMC_get_tunnel (c), qt, type, size); GNUNET_free (qt); } /** * Delete a queued message: either was sent or the channel was destroyed * before the tunnel's key exchange had a chance to finish. * * @param tqd Delayed queue handle. */ static void unqueue_data (struct MeshTunnelDelayed *tqd) { GNUNET_CONTAINER_DLL_remove (tqd->t->tq_head, tqd->t->tq_tail, tqd); GNUNET_free (tqd); } /** * Cache a message to be sent once tunnel is online. * * @param t Tunnel to hold the message. * @param msg Message itself (copy will be made). */ static struct MeshTunnelDelayed * queue_data (struct MeshTunnel3 *t, const struct GNUNET_MessageHeader *msg) { struct MeshTunnelDelayed *tqd; uint16_t size = ntohs (msg->size); LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GMT_2s (t)); if (GNUNET_YES == is_ready (t)) { GNUNET_break (0); return NULL; } tqd = GNUNET_malloc (sizeof (struct MeshTunnelDelayed) + size); tqd->t = t; memcpy (&tqd[1], msg, size); GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tqd); return tqd; } /** * Calculate HMAC. * * @param t Tunnel to get keys from. * @param plaintext Content to HMAC. * @param size Size of @c plaintext. * @param iv Initialization vector for the message. * @param outgoing Is this an outgoing message that we encrypted? * @param hmac Destination to store the HMAC. */ static void t_hmac (struct MeshTunnel3 *t, const void *plaintext, size_t size, uint32_t iv, int outgoing, struct GNUNET_MESH_Hash *hmac) { struct GNUNET_CRYPTO_AuthKey auth_key; static const char ctx[] = "mesh authentication key"; struct GNUNET_CRYPTO_SymmetricSessionKey *key; struct GNUNET_HashCode hash; key = outgoing ? &t->e_key : &t->d_key; GNUNET_CRYPTO_hmac_derive_key (&auth_key, key, &iv, sizeof (iv), key, sizeof (*key), ctx, sizeof (ctx), NULL); GNUNET_CRYPTO_hmac (&auth_key, plaintext, size, &hash); memcpy (hmac, &hash, sizeof (*hmac)); } /** * Sends an already built message on a tunnel, encrypting it and * choosing the best connection. * * @param message Message to send. Function modifies it. * @param t Tunnel on which this message is transmitted. * @param c Connection to use (autoselect if NULL). * @param force Force the tunnel to take the message (buffer overfill). * @param cont Continuation to call once message is really sent. * @param cont_cls Closure for @c cont. * @param existing_q In case this a transmission of previously queued data, * this should be TunnelQueue given to the client. * Otherwise, NULL. * * @return Handle to cancel message. NULL if @c cont is NULL. */ static struct MeshTunnel3Queue * send_prebuilt_message (const struct GNUNET_MessageHeader *message, struct MeshTunnel3 *t, struct MeshConnection *c, int force, GMT_sent cont, void *cont_cls, struct MeshTunnel3Queue *existing_q) { struct MeshTunnel3Queue *tq; struct GNUNET_MESH_Encrypted *msg; size_t size = ntohs (message->size); char cbuf[sizeof (struct GNUNET_MESH_Encrypted) + size]; uint32_t iv; uint16_t type; int fwd; LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMT_2s (t)); if (GNUNET_NO == is_ready (t)) { struct MeshTunnelDelayed *tqd; /* A non null existing_q indicates sending of queued data. * Should only happen after tunnel becomes ready. */ GNUNET_assert (NULL == existing_q); tqd = queue_data (t, message); if (NULL == cont) return NULL; tq = GNUNET_new (struct MeshTunnel3Queue); tq->tqd = tqd; tqd->tq = tq; tq->cont = cont; tq->cont_cls = cont_cls; return tq; } GNUNET_assert (GNUNET_NO == GMT_is_loopback (t)); iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); msg = (struct GNUNET_MESH_Encrypted *) cbuf; msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED); msg->iv = iv; GNUNET_assert (t_encrypt (t, &msg[1], message, size, iv) == size); t_hmac (t, &msg[1], size, iv, GNUNET_YES, &msg->hmac); msg->header.size = htons (sizeof (struct GNUNET_MESH_Encrypted) + size); if (NULL == c) c = tunnel_get_connection (t); if (NULL == c) { if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task || MESH_TUNNEL3_SEARCHING != t->cstate) { GNUNET_break (0); GMT_debug (t); } return NULL; } type = ntohs (message->type); switch (type) { case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE: case GNUNET_MESSAGE_TYPE_MESH_DATA: case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK: msg->cid = *GMC_get_id (c); msg->ttl = htonl (default_ttl); break; default: LOG (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n", GM_m2s (type)); GNUNET_break (0); } fwd = GMC_is_origin (c, GNUNET_YES); if (NULL == cont) { (void) GMC_send_prebuilt_message (&msg->header, c, fwd, force, NULL, NULL); return NULL; } if (NULL == existing_q) { tq = GNUNET_new (struct MeshTunnel3Queue); /* FIXME valgrind: leak*/ } else { tq = existing_q; tq->tqd = NULL; } tq->cq = GMC_send_prebuilt_message (&msg->header, c, fwd, force, &tun_message_sent, tq); tq->cont = cont; tq->cont_cls = cont_cls; return tq; } /** * Send all cached messages that we can, tunnel is online. * * @param t Tunnel that holds the messages. Cannot be loopback. */ static void send_queued_data (struct MeshTunnel3 *t) { struct MeshTunnelDelayed *tqd; struct MeshTunnelDelayed *next; unsigned int room; LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_send_queued_data on tunnel %s\n", GMT_2s (t)); if (GMT_is_loopback (t)) { GNUNET_break (0); return; } if (GNUNET_NO == is_ready (t)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " not ready yet: %s/%s\n", estate2s (t->estate), cstate2s (t->cstate)); return; } room = GMT_get_connections_buffer (t); LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room); LOG (GNUNET_ERROR_TYPE_DEBUG, " tq head: %p\n", t->tq_head); for (tqd = t->tq_head; NULL != tqd && room > 0; tqd = next) { LOG (GNUNET_ERROR_TYPE_DEBUG, " sending queued data\n"); next = tqd->next; room--; send_prebuilt_message ((struct GNUNET_MessageHeader *) &tqd[1], tqd->t, NULL, GNUNET_YES, NULL != tqd->tq ? tqd->tq->cont : NULL, NULL != tqd->tq ? tqd->tq->cont_cls : NULL, tqd->tq); unqueue_data (tqd); } LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_send_queued_data end\n", GMP_2s (t->peer)); } /** * Sends key exchange message on a tunnel, choosing the best connection. * Should not be called on loopback tunnels. * * @param t Tunnel on which this message is transmitted. * @param message Message to send. Function modifies it. */ static void send_kx (struct MeshTunnel3 *t, const struct GNUNET_MessageHeader *message) { struct MeshConnection *c; struct GNUNET_MESH_KX *msg; size_t size = ntohs (message->size); char cbuf[sizeof (struct GNUNET_MESH_KX) + size]; uint16_t type; int fwd; LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT KX on Tunnel %s\n", GMT_2s (t)); /* Avoid loopback. */ if (GMT_is_loopback (t)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback!\n"); GNUNET_break (0); return; } if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task) { LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother\n"); return; } /* Must have a connection. */ if (NULL == t->connection_head) { GNUNET_break (MESH_TUNNEL3_SEARCHING == t->cstate); GMT_debug (t); return; } msg = (struct GNUNET_MESH_KX *) cbuf; msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_KX); msg->header.size = htons (sizeof (struct GNUNET_MESH_KX) + size); c = tunnel_get_connection (t); if (NULL == c) { GNUNET_break (GNUNET_SCHEDULER_NO_TASK != t->destroy_task || MESH_TUNNEL3_READY != t->cstate); GMT_debug (t); return; } type = ntohs (message->type); switch (type) { case GNUNET_MESSAGE_TYPE_MESH_KX_EPHEMERAL: case GNUNET_MESSAGE_TYPE_MESH_KX_PING: case GNUNET_MESSAGE_TYPE_MESH_KX_PONG: memcpy (&msg[1], message, size); break; default: LOG (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n", GM_m2s (type)); GNUNET_break (0); } fwd = GMC_is_origin (t->connection_head->c, GNUNET_YES); /* TODO save handle and cancel in case of a unneeded retransmission */ GMC_send_prebuilt_message (&msg->header, c, fwd, GNUNET_YES, NULL, NULL); } /** * Send the ephemeral key on a tunnel. * * @param t Tunnel on which to send the key. */ static void send_ephemeral (struct MeshTunnel3 *t) { LOG (GNUNET_ERROR_TYPE_INFO, "=> EPHM for %s\n", GMT_2s (t)); kx_msg.sender_status = htonl (t->estate); send_kx (t, &kx_msg.header); } /** * Send a ping message on a tunnel. * * @param t Tunnel on which to send the ping. */ static void send_ping (struct MeshTunnel3 *t) { struct GNUNET_MESH_KX_Ping msg; LOG (GNUNET_ERROR_TYPE_INFO, "=> PING for %s\n", GMT_2s (t)); msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_KX_PING); msg.iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); msg.target = *GMP_get_id (t->peer); msg.nonce = t->kx_ctx->challenge; LOG (GNUNET_ERROR_TYPE_DEBUG, " sending %u\n", msg.nonce); LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s\n", GNUNET_i2s (&msg.target)); t_encrypt (t, &msg.target, &msg.target, ping_encryption_size(), msg.iv); LOG (GNUNET_ERROR_TYPE_DEBUG, " e sending %u\n", msg.nonce); LOG (GNUNET_ERROR_TYPE_DEBUG, " e towards %s\n", GNUNET_i2s (&msg.target)); send_kx (t, &msg.header); } /** * Send a pong message on a tunnel. * * @param t Tunnel on which to send the pong. * @param challenge Value sent in the ping that we have to send back. */ static void send_pong (struct MeshTunnel3 *t, uint32_t challenge) { struct GNUNET_MESH_KX_Pong msg; LOG (GNUNET_ERROR_TYPE_INFO, "=> PONG for %s\n", GMT_2s (t)); msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_KX_PONG); msg.iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); msg.nonce = challenge; LOG (GNUNET_ERROR_TYPE_DEBUG, " sending %u\n", msg.nonce); t_encrypt (t, &msg.nonce, &msg.nonce, sizeof (msg.nonce), msg.iv); LOG (GNUNET_ERROR_TYPE_DEBUG, " e sending %u\n", msg.nonce); send_kx (t, &msg.header); } /** * Initiate a rekey with the remote peer. * * @param cls Closure (tunnel). * @param tc TaskContext. */ static void rekey_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshTunnel3 *t = cls; t->rekey_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Re-key Tunnel %s\n", GMT_2s (t)); if (NULL != tc && 0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; if (NULL == t->kx_ctx) { LOG (GNUNET_ERROR_TYPE_DEBUG, " new kx ctx\n"); t->kx_ctx = GNUNET_new (struct MeshTunnelKXCtx); t->kx_ctx->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); t->kx_ctx->d_key_old = t->d_key; LOG (GNUNET_ERROR_TYPE_DEBUG, " new challenge for %s: %u\n", GMT_2s (t), t->kx_ctx->challenge); } send_ephemeral (t); switch (t->estate) { case MESH_TUNNEL3_KEY_UNINITIALIZED: t->estate = MESH_TUNNEL3_KEY_SENT; break; case MESH_TUNNEL3_KEY_SENT: break; case MESH_TUNNEL3_KEY_PING: case MESH_TUNNEL3_KEY_OK: send_ping (t); t->estate = MESH_TUNNEL3_KEY_PING; break; default: LOG (GNUNET_ERROR_TYPE_DEBUG, "Unexpected state %u\n", t->estate); } LOG (GNUNET_ERROR_TYPE_DEBUG, " next call in %s\n", GNUNET_STRINGS_relative_time_to_string (REKEY_WAIT, GNUNET_YES)); t->rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_WAIT, &rekey_tunnel, t); } /** * Out ephemeral key has changed, create new session key on all tunnels. * * @param cls Closure (size of the hashmap). * @param key Current public key. * @param value Value in the hash map (tunnel). * * @return #GNUNET_YES, so we should continue to iterate, */ static int rekey_iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct MeshTunnel3 *t = value; struct GNUNET_TIME_Relative delay; long n = (long) cls; uint32_t r; if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task) return GNUNET_YES; if (GNUNET_YES == GMT_is_loopback (t)) return GNUNET_YES; r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, (uint32_t) n * 100); delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, r); t->rekey_task = GNUNET_SCHEDULER_add_delayed (delay, &rekey_tunnel, t); return GNUNET_YES; } /** * Create a new ephemeral key and key message, schedule next rekeying. * * @param cls Closure (unused). * @param tc TaskContext. */ static void rekey (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Absolute time; long n; rekey_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; GNUNET_free_non_null (my_ephemeral_key); my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create (); time = GNUNET_TIME_absolute_get (); kx_msg.creation_time = GNUNET_TIME_absolute_hton (time); time = GNUNET_TIME_absolute_add (time, rekey_period); time = GNUNET_TIME_absolute_add (time, GNUNET_TIME_UNIT_MINUTES); kx_msg.expiration_time = GNUNET_TIME_absolute_hton (time); GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key, &kx_msg.ephemeral_key); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_private_key, &kx_msg.purpose, &kx_msg.signature)); n = (long) GNUNET_CONTAINER_multipeermap_size (tunnels); GNUNET_CONTAINER_multipeermap_iterate (tunnels, &rekey_iterator, (void *) n); rekey_task = GNUNET_SCHEDULER_add_delayed (rekey_period, &rekey, NULL); } /** * Called only on shutdown, destroy every tunnel. * * @param cls Closure (unused). * @param key Current public key. * @param value Value in the hash map (tunnel). * * @return #GNUNET_YES, so we should continue to iterate, */ static int destroy_iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct MeshTunnel3 *t = value; GMT_destroy (t); return GNUNET_YES; } /** * Notify remote peer that we don't know a channel he is talking about, * probably CHANNEL_DESTROY was missed. * * @param t Tunnel on which to notify. * @param gid ID of the channel. */ static void send_channel_destroy (struct MeshTunnel3 *t, unsigned int gid) { struct GNUNET_MESH_ChannelManage msg; msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY); msg.header.size = htons (sizeof (msg)); msg.chid = htonl (gid); LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING destroying unknown channel %u on tunnel %s\n", gid, GMT_2s (t)); send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL); } /** * Demultiplex data per channel and call appropriate channel handler. * * @param t Tunnel on which the data came. * @param msg Data message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ static void handle_data (struct MeshTunnel3 *t, const struct GNUNET_MESH_Data *msg, int fwd) { struct MeshChannel *ch; size_t size; /* Check size */ size = ntohs (msg->header.size); if (size < sizeof (struct GNUNET_MESH_Data) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n", GM_m2s (ntohs (msg[1].header.type))); /* Check channel */ ch = GMT_get_channel (t, ntohl (msg->chid)); if (NULL == ch) { GNUNET_STATISTICS_update (stats, "# data on unknown channel", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel 0x%X unknown\n", ntohl (msg->chid)); send_channel_destroy (t, ntohl (msg->chid)); return; } GMCH_handle_data (ch, msg, fwd); } /** * Demultiplex data ACKs per channel and update appropriate channel buffer info. * * @param t Tunnel on which the DATA ACK came. * @param msg DATA ACK message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ static void handle_data_ack (struct MeshTunnel3 *t, const struct GNUNET_MESH_DataACK *msg, int fwd) { struct MeshChannel *ch; size_t size; /* Check size */ size = ntohs (msg->header.size); if (size != sizeof (struct GNUNET_MESH_DataACK)) { GNUNET_break (0); return; } /* Check channel */ ch = GMT_get_channel (t, ntohl (msg->chid)); if (NULL == ch) { GNUNET_STATISTICS_update (stats, "# data ack on unknown channel", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", ntohl (msg->chid)); return; } GMCH_handle_data_ack (ch, msg, fwd); } /** * Handle channel create. * * @param t Tunnel on which the data came. * @param msg Data message. */ static void handle_ch_create (struct MeshTunnel3 *t, const struct GNUNET_MESH_ChannelCreate *msg) { struct MeshChannel *ch; size_t size; /* Check size */ size = ntohs (msg->header.size); if (size != sizeof (struct GNUNET_MESH_ChannelCreate)) { GNUNET_break (0); return; } /* Check channel */ ch = GMT_get_channel (t, ntohl (msg->chid)); if (NULL != ch && ! GMT_is_loopback (t)) { /* Probably a retransmission, safe to ignore */ LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists...\n"); } ch = GMCH_handle_create (t, msg); if (NULL != ch) GMT_add_channel (t, ch); } /** * Handle channel NACK: check correctness and call channel handler for NACKs. * * @param t Tunnel on which the NACK came. * @param msg NACK message. */ static void handle_ch_nack (struct MeshTunnel3 *t, const struct GNUNET_MESH_ChannelManage *msg) { struct MeshChannel *ch; size_t size; /* Check size */ size = ntohs (msg->header.size); if (size != sizeof (struct GNUNET_MESH_ChannelManage)) { GNUNET_break (0); return; } /* Check channel */ ch = GMT_get_channel (t, ntohl (msg->chid)); if (NULL == ch) { GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", ntohl (msg->chid)); return; } GMCH_handle_nack (ch); } /** * Handle a CHANNEL ACK (SYNACK/ACK). * * @param t Tunnel on which the CHANNEL ACK came. * @param msg CHANNEL ACK message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ static void handle_ch_ack (struct MeshTunnel3 *t, const struct GNUNET_MESH_ChannelManage *msg, int fwd) { struct MeshChannel *ch; size_t size; /* Check size */ size = ntohs (msg->header.size); if (size != sizeof (struct GNUNET_MESH_ChannelManage)) { GNUNET_break (0); return; } /* Check channel */ ch = GMT_get_channel (t, ntohl (msg->chid)); if (NULL == ch) { GNUNET_STATISTICS_update (stats, "# channel ack on unknown channel", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", ntohl (msg->chid)); return; } GMCH_handle_ack (ch, msg, fwd); } /** * Handle a channel destruction message. * * @param t Tunnel on which the message came. * @param msg Channel destroy message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ static void handle_ch_destroy (struct MeshTunnel3 *t, const struct GNUNET_MESH_ChannelManage *msg, int fwd) { struct MeshChannel *ch; size_t size; /* Check size */ size = ntohs (msg->header.size); if (size != sizeof (struct GNUNET_MESH_ChannelManage)) { GNUNET_break (0); return; } /* Check channel */ ch = GMT_get_channel (t, ntohl (msg->chid)); if (NULL == ch) { /* Probably a retransmission, safe to ignore */ return; } GMCH_handle_destroy (ch, msg, fwd); } /** * The peer's ephemeral key has changed: update the symmetrical keys. * * @param t Tunnel this message came on. * @param msg Key eXchange message. */ static void handle_ephemeral (struct MeshTunnel3 *t, const struct GNUNET_MESH_KX_Ephemeral *msg) { struct GNUNET_HashCode km; LOG (GNUNET_ERROR_TYPE_INFO, "<= EPHM for %s\n", GMT_2s (t)); if (GNUNET_OK != check_ephemeral (t, msg)) { GNUNET_break_op (0); return; } derive_key_material (&km, &msg->ephemeral_key); LOG (GNUNET_ERROR_TYPE_DEBUG, " km is %s\n", GNUNET_h2s (&km)); derive_symmertic (&t->e_key, &my_full_id, GMP_get_id (t->peer), &km); derive_symmertic (&t->d_key, GMP_get_id (t->peer), &my_full_id, &km); if (MESH_TUNNEL3_KEY_SENT == t->estate) { LOG (GNUNET_ERROR_TYPE_DEBUG, " our key was sent, send ping\n"); send_ping (t); t->estate = MESH_TUNNEL3_KEY_PING; } } /** * Peer wants to check our symmetrical keys by sending an encrypted challenge. * Answer with by retransmitting the challenge with the "opposite" key. * * @param t Tunnel this message came on. * @param msg Key eXchange Ping message. */ static void handle_ping (struct MeshTunnel3 *t, const struct GNUNET_MESH_KX_Ping *msg) { struct GNUNET_MESH_KX_Ping res; if (ntohs (msg->header.size) != sizeof (res)) { GNUNET_break_op (0); return; } LOG (GNUNET_ERROR_TYPE_INFO, "<= PING for %s\n", GMT_2s (t)); t_decrypt (t, &res.target, &msg->target, ping_encryption_size (), msg->iv); if (0 != memcmp (&my_full_id, &res.target, sizeof (my_full_id))) { GNUNET_STATISTICS_update (stats, "# malformed PINGs", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_WARNING, " malformed PING\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " e got %u\n", msg->nonce); LOG (GNUNET_ERROR_TYPE_DEBUG, " e towards %s\n", GNUNET_i2s (&msg->target)); LOG (GNUNET_ERROR_TYPE_DEBUG, " got %u\n", res.nonce); LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s\n", GNUNET_i2s (&res.target)); return; } send_pong (t, res.nonce); } /** * Peer has answer to our challenge. * If answer is successful, consider the key exchange finished and clean * up all related state. * * @param t Tunnel this message came on. * @param msg Key eXchange Pong message. */ static void handle_pong (struct MeshTunnel3 *t, const struct GNUNET_MESH_KX_Pong *msg) { uint32_t challenge; LOG (GNUNET_ERROR_TYPE_INFO, "<= PONG for %s\n", GMT_2s (t)); if (GNUNET_SCHEDULER_NO_TASK == t->rekey_task) { GNUNET_STATISTICS_update (stats, "# duplicate PONG messages", 1, GNUNET_NO); return; } t_decrypt (t, &challenge, &msg->nonce, sizeof (uint32_t), msg->iv); if (challenge != t->kx_ctx->challenge) { LOG (GNUNET_ERROR_TYPE_WARNING, "Wrong PONG challenge\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "PONG: %u (e: %u). Expected: %u.\n", challenge, msg->nonce, t->kx_ctx->challenge); GNUNET_break_op (0); return; } GNUNET_SCHEDULER_cancel (t->rekey_task); t->rekey_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_free (t->kx_ctx); t->kx_ctx = NULL; GMT_change_estate (t, MESH_TUNNEL3_KEY_OK); } /** * Demultiplex by message type and call appropriate handler for a message * towards a channel of a local tunnel. * * @param t Tunnel this message came on. * @param msgh Message header. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ static void handle_decrypted (struct MeshTunnel3 *t, const struct GNUNET_MessageHeader *msgh, int fwd) { uint16_t type; type = ntohs (msgh->type); LOG (GNUNET_ERROR_TYPE_INFO, "<= %s on %s\n", GM_m2s (type), GMT_2s (t)); switch (type) { case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE: /* Do nothing, connection aleady got updated. */ GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO); break; case GNUNET_MESSAGE_TYPE_MESH_DATA: /* Don't send hop ACK, wait for client to ACK */ handle_data (t, (struct GNUNET_MESH_Data *) msgh, fwd); break; case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK: handle_data_ack (t, (struct GNUNET_MESH_DataACK *) msgh, fwd); break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: handle_ch_create (t, (struct GNUNET_MESH_ChannelCreate *) msgh); break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK: handle_ch_nack (t, (struct GNUNET_MESH_ChannelManage *) msgh); break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK: handle_ch_ack (t, (struct GNUNET_MESH_ChannelManage *) msgh, fwd); break; case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: handle_ch_destroy (t, (struct GNUNET_MESH_ChannelManage *) msgh, fwd); break; default: GNUNET_break_op (0); LOG (GNUNET_ERROR_TYPE_WARNING, "end-to-end message not known (%u)\n", ntohs (msgh->type)); GMT_debug (t); } } /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Decrypt and demultiplex by message type. Call appropriate handler * for every message. * * @param t Tunnel this message came on. * @param msg Encrypted message. */ void GMT_handle_encrypted (struct MeshTunnel3 *t, const struct GNUNET_MESH_Encrypted *msg) { size_t size = ntohs (msg->header.size); size_t payload_size = size - sizeof (struct GNUNET_MESH_Encrypted); size_t decrypted_size; char cbuf [payload_size]; struct GNUNET_MessageHeader *msgh; unsigned int off; struct GNUNET_MESH_Hash hmac; decrypted_size = t_decrypt (t, cbuf, &msg[1], payload_size, msg->iv); t_hmac (t, &msg[1], payload_size, msg->iv, GNUNET_NO, &hmac); if (0 != memcmp (&hmac, &msg->hmac, sizeof (hmac))) { /* checksum failed */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed checksum validation for a message on tunnel `%s'\n", GMT_2s (t)); GNUNET_STATISTICS_update (stats, "# wrong HMAC", 1, GNUNET_NO); return; } off = 0; while (off < decrypted_size) { msgh = (struct GNUNET_MessageHeader *) &cbuf[off]; handle_decrypted (t, msgh, GNUNET_SYSERR); off += ntohs (msgh->size); } } /** * Demultiplex an encapsulated KX message by message type. * * @param t Tunnel on which the message came. * @param message Payload of KX message. */ void GMT_handle_kx (struct MeshTunnel3 *t, const struct GNUNET_MessageHeader *message) { uint16_t type; type = ntohs (message->type); LOG (GNUNET_ERROR_TYPE_DEBUG, "kx message received\n", type); switch (type) { case GNUNET_MESSAGE_TYPE_MESH_KX_EPHEMERAL: handle_ephemeral (t, (struct GNUNET_MESH_KX_Ephemeral *) message); break; case GNUNET_MESSAGE_TYPE_MESH_KX_PING: handle_ping (t, (struct GNUNET_MESH_KX_Ping *) message); break; case GNUNET_MESSAGE_TYPE_MESH_KX_PONG: handle_pong (t, (struct GNUNET_MESH_KX_Pong *) message); break; default: GNUNET_break_op (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "kx message not known (%u)\n", type); } } /** * Initialize the tunnel subsystem. * * @param c Configuration handle. * @param key ECC private key, to derive all other keys and do crypto. */ void GMT_init (const struct GNUNET_CONFIGURATION_Handle *c, const struct GNUNET_CRYPTO_EddsaPrivateKey *key) { LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL", &default_ttl)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "MESH", "DEFAULT_TTL", "USING DEFAULT"); default_ttl = 64; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REKEY_PERIOD", &rekey_period)) { rekey_period = GNUNET_TIME_UNIT_DAYS; } my_private_key = key; kx_msg.header.size = htons (sizeof (kx_msg)); kx_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_KX_EPHEMERAL); kx_msg.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_MESH_KX); kx_msg.purpose.size = htonl (ephemeral_purpose_size ()); kx_msg.origin_identity = my_full_id; rekey_task = GNUNET_SCHEDULER_add_now (&rekey, NULL); tunnels = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES); } /** * Shut down the tunnel subsystem. */ void GMT_shutdown (void) { if (GNUNET_SCHEDULER_NO_TASK != rekey_task) { GNUNET_SCHEDULER_cancel (rekey_task); rekey_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_multipeermap_iterate (tunnels, &destroy_iterator, NULL); GNUNET_CONTAINER_multipeermap_destroy (tunnels); } /** * Create a tunnel. * * @param destination Peer this tunnel is towards. */ struct MeshTunnel3 * GMT_new (struct MeshPeer *destination) { struct MeshTunnel3 *t; t = GNUNET_new (struct MeshTunnel3); t->next_chid = 0; t->peer = destination; if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (tunnels, GMP_get_id (destination), t, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { GNUNET_break (0); GNUNET_free (t); return NULL; } return t; } /** * Change the tunnel's connection state. * * @param t Tunnel whose connection state to change. * @param cstate New connection state. */ void GMT_change_cstate (struct MeshTunnel3* t, enum MeshTunnel3CState cstate) { if (NULL == t) return; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s cstate %s => %s\n", GMP_2s (t->peer), cstate2s (t->cstate), cstate2s (cstate)); if (myid != GMP_get_short_id (t->peer) && MESH_TUNNEL3_READY != t->cstate && MESH_TUNNEL3_READY == cstate) { t->cstate = cstate; if (MESH_TUNNEL3_KEY_OK == t->estate) { LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered send queued data\n"); send_queued_data (t); } else if (MESH_TUNNEL3_KEY_UNINITIALIZED == t->estate) { LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered rekey\n"); rekey_tunnel (t, NULL); } } t->cstate = cstate; if (MESH_TUNNEL3_READY == cstate && CONNECTIONS_PER_TUNNEL <= GMT_count_connections (t)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered stop dht\n"); GMP_stop_search (t->peer); } } /** * Change the tunnel encryption state. * * @param t Tunnel whose encryption state to change. * @param state New encryption state. */ void GMT_change_estate (struct MeshTunnel3* t, enum MeshTunnel3EState state) { if (NULL == t) return; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s estate was %s\n", GMP_2s (t->peer), estate2s (t->estate)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s estate is now %s\n", GMP_2s (t->peer), estate2s (state)); if (myid != GMP_get_short_id (t->peer) && MESH_TUNNEL3_KEY_OK != t->estate && MESH_TUNNEL3_KEY_OK == state) { t->estate = state; send_queued_data (t); return; } t->estate = state; } /** * Check that the tunnel doesn't have too many connections, * remove one if necessary. * * For the time being, this means the newest connection. * * @param t Tunnel to check. */ static void check_connection_count (struct MeshTunnel3 *t) { if (GMT_count_connections (t) > CONNECTIONS_PER_TUNNEL) { struct MeshTConnection *iter; struct MeshTConnection *c; for (c = iter = t->connection_head; NULL != iter; iter = iter->next) { if (NULL == c || iter->created.abs_value_us > c->created.abs_value_us) { c = iter; } } if (NULL != c) GMC_destroy (c->c); else GNUNET_break (0); } } /** * Add a connection to a tunnel. * * @param t Tunnel. * @param c Connection. */ void GMT_add_connection (struct MeshTunnel3 *t, struct MeshConnection *c) { struct MeshTConnection *aux; GNUNET_assert (NULL != c); for (aux = t->connection_head; aux != NULL; aux = aux->next) if (aux->c == c) return; aux = GNUNET_new (struct MeshTConnection); aux->c = c; aux->created = GNUNET_TIME_absolute_get (); GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, aux); check_connection_count (t); } /** * Mark a path as no longer valid for this tunnel: has been tried and failed. * * @param t Tunnel to update. * @param path Invalid path to remove. Is destroyed after removal. */ void GMT_remove_path (struct MeshTunnel3 *t, struct MeshPeerPath *path) { GMP_remove_path (t->peer, path); } /** * Remove a connection from a tunnel. * * @param t Tunnel. * @param c Connection. */ void GMT_remove_connection (struct MeshTunnel3 *t, struct MeshConnection *c) { struct MeshTConnection *aux; struct MeshTConnection *next; LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing connection %s from tunnel %s\n", GMC_2s (c), GMT_2s (t)); for (aux = t->connection_head; aux != NULL; aux = next) { next = aux->next; if (aux->c == c) { GNUNET_CONTAINER_DLL_remove (t->connection_head, t->connection_tail, aux); GNUNET_free (aux); } } /* Start new connections if needed */ if (NULL == t->connection_head && GNUNET_SCHEDULER_NO_TASK == t->destroy_task && MESH_TUNNEL3_SHUTDOWN != t->cstate && GNUNET_NO == shutting_down) { LOG (GNUNET_ERROR_TYPE_DEBUG, " no more connections, getting new ones\n"); t->cstate = MESH_TUNNEL3_SEARCHING; GMP_connect (t->peer); return; } /* If not marked as ready, no change is needed */ if (MESH_TUNNEL3_READY != t->cstate) return; /* Check if any connection is ready to maintaing cstate */ for (aux = t->connection_head; aux != NULL; aux = aux->next) if (MESH_CONNECTION_READY == GMC_get_state (aux->c)) return; t->cstate = MESH_TUNNEL3_WAITING; } /** * Add a channel to a tunnel. * * @param t Tunnel. * @param ch Channel. */ void GMT_add_channel (struct MeshTunnel3 *t, struct MeshChannel *ch) { struct MeshTChannel *aux; GNUNET_assert (NULL != ch); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding channel %p to tunnel %p\n", ch, t); for (aux = t->channel_head; aux != NULL; aux = aux->next) { LOG (GNUNET_ERROR_TYPE_DEBUG, " already there %p\n", aux->ch); if (aux->ch == ch) return; } aux = GNUNET_new (struct MeshTChannel); aux->ch = ch; LOG (GNUNET_ERROR_TYPE_DEBUG, " adding %p to %p\n", aux, t->channel_head); GNUNET_CONTAINER_DLL_insert_tail (t->channel_head, t->channel_tail, aux); if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task) { GNUNET_SCHEDULER_cancel (t->destroy_task); t->destroy_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, " undo destroy!\n"); } } /** * Remove a channel from a tunnel. * * @param t Tunnel. * @param ch Channel. */ void GMT_remove_channel (struct MeshTunnel3 *t, struct MeshChannel *ch) { struct MeshTChannel *aux; LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing channel %p from tunnel %p\n", ch, t); for (aux = t->channel_head; aux != NULL; aux = aux->next) { if (aux->ch == ch) { LOG (GNUNET_ERROR_TYPE_DEBUG, " found! %s\n", GMCH_2s (ch)); GNUNET_CONTAINER_DLL_remove (t->channel_head, t->channel_tail, aux); GNUNET_free (aux); return; } } } /** * Search for a channel by global ID. * * @param t Tunnel containing the channel. * @param chid Public channel number. * * @return channel handler, NULL if doesn't exist */ struct MeshChannel * GMT_get_channel (struct MeshTunnel3 *t, MESH_ChannelNumber chid) { struct MeshTChannel *iter; if (NULL == t) return NULL; for (iter = t->channel_head; NULL != iter; iter = iter->next) { if (GMCH_get_id (iter->ch) == chid) break; } return NULL == iter ? NULL : iter->ch; } /** * @brief Destroy a tunnel and free all resources. * * Should only be called a while after the tunnel has been marked as destroyed, * in case there is a new channel added to the same peer shortly after marking * the tunnel. This way we avoid a new public key handshake. * * @param cls Closure (tunnel to destroy). * @param tc Task context. */ static void delayed_destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshTunnel3 *t = cls; struct MeshTConnection *iter; t->destroy_task = GNUNET_SCHEDULER_NO_TASK; t->cstate = MESH_TUNNEL3_SHUTDOWN; for (iter = t->connection_head; NULL != iter; iter = iter->next) { GMC_send_destroy (iter->c); } GMT_destroy (t); } /** * Tunnel is empty: destroy it. * * Notifies all connections about the destruction. * * @param t Tunnel to destroy. */ void GMT_destroy_empty (struct MeshTunnel3 *t) { if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s is already scheduled for destruction\n", GMT_2s (t)); GNUNET_break (0); /* should never happen, tunnel can only become empty once, and the * task identifier should be NO_TASK (cleaned when the tunnel was created * or became un-empty) */ return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s empty: destroying scheduled\n", GMT_2s (t)); t->destroy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &delayed_destroy, t); } /** * Destroy tunnel if empty (no more channels). * * @param t Tunnel to destroy if empty. */ void GMT_destroy_if_empty (struct MeshTunnel3 *t) { if (1 < GMT_count_channels (t)) return; GMT_destroy_empty (t); } /** * Destroy the tunnel. * * This function does not generate any warning traffic to clients or peers. * * Tasks: * Cancel messages belonging to this tunnel queued to neighbors. * Free any allocated resources linked to the tunnel. * * @param t The tunnel to destroy. */ void GMT_destroy (struct MeshTunnel3 *t) { struct MeshTConnection *iter_c; struct MeshTConnection *next_c; struct MeshTChannel *iter_ch; struct MeshTChannel *next_ch; if (NULL == t) return; if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task) { GNUNET_SCHEDULER_cancel (t->destroy_task); t->destroy_task = GNUNET_SCHEDULER_NO_TASK; } LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s\n", GMP_2s (t->peer)); GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (tunnels, GMP_get_id (t->peer), t)); for (iter_c = t->connection_head; NULL != iter_c; iter_c = next_c) { next_c = iter_c->next; GMC_destroy (iter_c->c); } for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = next_ch) { next_ch = iter_ch->next; GMCH_destroy (iter_ch->ch); /* Should only happen on shutdown, but it's ok. */ } GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO); GMP_set_tunnel (t->peer, NULL); if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task) { GNUNET_SCHEDULER_cancel (t->rekey_task); t->rekey_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != t->kx_ctx) GNUNET_free (t->kx_ctx); else GNUNET_break (0); } GNUNET_free (t); } /** * @brief Use the given path for the tunnel. * Update the next and prev hops (and RCs). * (Re)start the path refresh in case the tunnel is locally owned. * * @param t Tunnel to update. * @param p Path to use. * * @return Connection created. */ struct MeshConnection * GMT_use_path (struct MeshTunnel3 *t, struct MeshPeerPath *p) { struct MeshConnection *c; struct GNUNET_MESH_Hash cid; unsigned int own_pos; if (NULL == t || NULL == p) { GNUNET_break (0); return NULL; } if (MESH_TUNNEL3_SHUTDOWN == t->cstate) { GNUNET_break (0); return NULL; } for (own_pos = 0; own_pos < p->length; own_pos++) { if (p->peers[own_pos] == myid) break; } if (own_pos >= p->length) { GNUNET_break_op (0); return NULL; } GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof (cid)); c = GMC_new (&cid, t, p, own_pos); if (NULL == c) { /* Path was flawed */ return NULL; } GMT_add_connection (t, c); return c; } /** * Count established (ready) connections of a tunnel. * * @param t Tunnel on which to count. * * @return Number of connections. */ unsigned int GMT_count_connections (struct MeshTunnel3 *t) { struct MeshTConnection *iter; unsigned int count; if (NULL == t) return 0; for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next) if (MESH_CONNECTION_DESTROYED != GMC_get_state (iter->c)) count++; return count; } /** * Count channels of a tunnel. * * @param t Tunnel on which to count. * * @return Number of channels. */ unsigned int GMT_count_channels (struct MeshTunnel3 *t) { struct MeshTChannel *iter; unsigned int count; for (count = 0, iter = t->channel_head; NULL != iter; iter = iter->next, count++) /* skip */; return count; } /** * Get the connectivity state of a tunnel. * * @param t Tunnel. * * @return Tunnel's connectivity state. */ enum MeshTunnel3CState GMT_get_cstate (struct MeshTunnel3 *t) { if (NULL == t) { GNUNET_assert (0); return (enum MeshTunnel3CState) -1; } return t->cstate; } /** * Get the encryption state of a tunnel. * * @param t Tunnel. * * @return Tunnel's encryption state. */ enum MeshTunnel3EState GMT_get_estate (struct MeshTunnel3 *t) { if (NULL == t) { GNUNET_assert (0); return (enum MeshTunnel3EState) -1; } return t->estate; } /** * Get the maximum buffer space for a tunnel towards a local client. * * @param t Tunnel. * * @return Biggest buffer space offered by any channel in the tunnel. */ unsigned int GMT_get_channels_buffer (struct MeshTunnel3 *t) { struct MeshTChannel *iter; unsigned int buffer; unsigned int ch_buf; if (NULL == t->channel_head) { /* Probably getting buffer for a channel create/handshake. */ return 64; } buffer = 0; for (iter = t->channel_head; NULL != iter; iter = iter->next) { ch_buf = get_channel_buffer (iter); if (ch_buf > buffer) buffer = ch_buf; } return buffer; } /** * Get the total buffer space for a tunnel for P2P traffic. * * @param t Tunnel. * * @return Buffer space offered by all connections in the tunnel. */ unsigned int GMT_get_connections_buffer (struct MeshTunnel3 *t) { struct MeshTConnection *iter; unsigned int buffer; buffer = 0; for (iter = t->connection_head; NULL != iter; iter = iter->next) { if (GMC_get_state (iter->c) != MESH_CONNECTION_READY) { continue; } buffer += get_connection_buffer (iter); } return buffer; } /** * Get the tunnel's destination. * * @param t Tunnel. * * @return ID of the destination peer. */ const struct GNUNET_PeerIdentity * GMT_get_destination (struct MeshTunnel3 *t) { return GMP_get_id (t->peer); } /** * Get the tunnel's next free global channel ID. * * @param t Tunnel. * * @return GID of a channel free to use. */ MESH_ChannelNumber GMT_get_next_chid (struct MeshTunnel3 *t) { MESH_ChannelNumber chid; MESH_ChannelNumber mask; int result; /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID. * If our ID is bigger or loopback tunnel, start at 0, bit 30 = 0 * If peer's ID is bigger, start at 0x4... bit 30 = 1 */ result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GMP_get_id (t->peer)); if (0 > result) mask = 0x40000000; else mask = 0x0; t->next_chid |= mask; while (NULL != GMT_get_channel (t, t->next_chid)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", t->next_chid); t->next_chid = (t->next_chid + 1) & ~GNUNET_MESH_LOCAL_CHANNEL_ID_CLI; t->next_chid |= mask; } chid = t->next_chid; t->next_chid = (t->next_chid + 1) & ~GNUNET_MESH_LOCAL_CHANNEL_ID_CLI; t->next_chid |= mask; return chid; } /** * Send ACK on one or more channels due to buffer in connections. * * @param t Channel which has some free buffer space. */ void GMT_unchoke_channels (struct MeshTunnel3 *t) { struct MeshTChannel *iter; unsigned int buffer; unsigned int channels = GMT_count_channels (t); unsigned int choked_n; struct MeshChannel *choked[channels]; LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_unchoke_channels on %s\n", GMT_2s (t)); LOG (GNUNET_ERROR_TYPE_DEBUG, " head: %p\n", t->channel_head); if (NULL != t->channel_head) LOG (GNUNET_ERROR_TYPE_DEBUG, " head ch: %p\n", t->channel_head->ch); /* Get buffer space */ buffer = GMT_get_connections_buffer (t); if (0 == buffer) { return; } /* Count and remember choked channels */ choked_n = 0; for (iter = t->channel_head; NULL != iter; iter = iter->next) { if (GNUNET_NO == get_channel_allowed (iter)) { choked[choked_n++] = iter->ch; } } /* Unchoke random channels */ while (0 < buffer && 0 < choked_n) { unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, choked_n); GMCH_allow_client (choked[r], GMCH_is_origin (choked[r], GNUNET_YES)); choked_n--; buffer--; choked[r] = choked[choked_n]; } } /** * Send ACK on one or more connections due to buffer space to the client. * * Iterates all connections of the tunnel and sends ACKs appropriately. * * @param t Tunnel. */ void GMT_send_connection_acks (struct MeshTunnel3 *t) { struct MeshTConnection *iter; uint32_t allowed; uint32_t to_allow; uint32_t allow_per_connection; unsigned int cs; unsigned int buffer; LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel send connection ACKs on %s\n", GMT_2s (t)); if (NULL == t) { GNUNET_break (0); return; } buffer = GMT_get_channels_buffer (t); LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer %u\n", buffer); /* Count connections, how many messages are already allowed */ cs = GMT_count_connections (t); for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next) { allowed += get_connection_allowed (iter); } LOG (GNUNET_ERROR_TYPE_DEBUG, " allowed %u\n", allowed); /* Make sure there is no overflow */ if (allowed > buffer) { return; } /* Authorize connections to send more data */ to_allow = buffer; /* - allowed; */ for (iter = t->connection_head; NULL != iter && to_allow > 0; iter = iter->next) { allow_per_connection = to_allow/cs; to_allow -= allow_per_connection; cs--; if (get_connection_allowed (iter) > 64 / 3) { continue; } GMC_allow (iter->c, allow_per_connection, GMC_is_origin (iter->c, GNUNET_NO)); } GNUNET_break (to_allow == 0); } /** * Cancel a previously sent message while it's in the queue. * * ONLY can be called before the continuation given to the send function * is called. Once the continuation is called, the message is no longer in the * queue. * * @param q Handle to the queue. */ void GMT_cancel (struct MeshTunnel3Queue *q) { if (NULL != q->cq) { GMC_cancel (q->cq); /* tun_message_sent() will be called and free q */ } else if (NULL != q->tqd) { unqueue_data (q->tqd); q->tqd = NULL; if (NULL != q->cont) q->cont (q->cont_cls, NULL, q, 0, 0); GNUNET_free (q); } else { GNUNET_break (0); } } /** * Sends an already built message on a tunnel, encrypting it and * choosing the best connection if not provided. * * @param message Message to send. Function modifies it. * @param t Tunnel on which this message is transmitted. * @param c Connection to use (autoselect if NULL). * @param force Force the tunnel to take the message (buffer overfill). * @param cont Continuation to call once message is really sent. * @param cont_cls Closure for @c cont. * * @return Handle to cancel message. NULL if @c cont is NULL. */ struct MeshTunnel3Queue * GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, struct MeshTunnel3 *t, struct MeshConnection *c, int force, GMT_sent cont, void *cont_cls) { return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL); } /** * Is the tunnel directed towards the local peer? * * @param t Tunnel. * * @return #GNUNET_YES if it is loopback. */ int GMT_is_loopback (const struct MeshTunnel3 *t) { return (myid == GMP_get_short_id (t->peer)); } /** * Is the tunnel this path already? * * @param t Tunnel. * @param p Path. * * @return #GNUNET_YES a connection uses this path. */ int GMT_is_path_used (const struct MeshTunnel3 *t, const struct MeshPeerPath *p) { struct MeshTConnection *iter; for (iter = t->connection_head; NULL != iter; iter = iter->next) if (GMC_get_path (iter->c) == p) return GNUNET_YES; return GNUNET_NO; } /** * Get a cost of a path for a tunnel considering existing connections. * * @param t Tunnel. * @param path Candidate path. * * @return Cost of the path (path length + number of overlapping nodes) */ unsigned int GMT_get_path_cost (const struct MeshTunnel3 *t, const struct MeshPeerPath *path) { struct MeshTConnection *iter; const struct MeshPeerPath *aux; unsigned int overlap; unsigned int i; unsigned int j; if (NULL == path) return 0; overlap = 0; GNUNET_assert (NULL != t); for (i = 0; i < path->length; i++) { for (iter = t->connection_head; NULL != iter; iter = iter->next) { aux = GMC_get_path (iter->c); if (NULL == aux) continue; for (j = 0; j < aux->length; j++) { if (path->peers[i] == aux->peers[j]) { overlap++; break; } } } } return path->length + overlap; } /** * Get the static string for the peer this tunnel is directed. * * @param t Tunnel. * * @return Static string the destination peer's ID. */ const char * GMT_2s (const struct MeshTunnel3 *t) { if (NULL == t) return "(NULL)"; return GMP_2s (t->peer); } /******************************************************************************/ /***************************** INFO/DEBUG *******************************/ /******************************************************************************/ /** * Log all possible info about the tunnel state to stderr. * * @param t Tunnel to debug. */ void GMT_debug (const struct MeshTunnel3 *t) { struct MeshTChannel *iterch; struct MeshTConnection *iterc; LOG (GNUNET_ERROR_TYPE_DEBUG, "DEBUG TUNNEL TOWARDS %s\n", GMT_2s (t)); LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate %s, estate %s\n", cstate2s (t->cstate), estate2s (t->estate)); LOG (GNUNET_ERROR_TYPE_DEBUG, " kx_ctx %p, rekey_task %u\n", t->kx_ctx, t->rekey_task); LOG (GNUNET_ERROR_TYPE_DEBUG, " tq_head %p, tq_tail %p\n", t->tq_head, t->tq_tail); LOG (GNUNET_ERROR_TYPE_DEBUG, " destroy %u\n", t->destroy_task); LOG (GNUNET_ERROR_TYPE_DEBUG, " channels:\n"); for (iterch = t->channel_head; NULL != iterch; iterch = iterch->next) { LOG (GNUNET_ERROR_TYPE_DEBUG, " - %s\n", GMCH_2s (iterch->ch)); } LOG (GNUNET_ERROR_TYPE_DEBUG, " connections:\n"); for (iterc = t->connection_head; NULL != iterc; iterc = iterc->next) { LOG (GNUNET_ERROR_TYPE_DEBUG, " - %s [%u] buf: %u/%u (qn %u/%u)\n", GMC_2s (iterc->c), GMC_get_state (iterc->c), GMC_get_buffer (iterc->c, GNUNET_YES), GMC_get_buffer (iterc->c, GNUNET_NO), GMC_get_qn (iterc->c, GNUNET_YES), GMC_get_qn (iterc->c, GNUNET_NO)); } LOG (GNUNET_ERROR_TYPE_DEBUG, "DEBUG TUNNEL END\n"); } /** * Iterate all tunnels. * * @param iter Iterator. * @param cls Closure for @c iter. */ void GMT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls) { GNUNET_CONTAINER_multipeermap_iterate (tunnels, iter, cls); } /** * Count all tunnels. * * @return Number of tunnels to remote peers kept by this peer. */ unsigned int GMT_count_all (void) { return GNUNET_CONTAINER_multipeermap_size (tunnels); } /** * Iterate all connections of a tunnel. * * @param t Tunnel whose connections to iterate. * @param iter Iterator. * @param cls Closure for @c iter. */ void GMT_iterate_connections (struct MeshTunnel3 *t, GMT_conn_iter iter, void *cls) { struct MeshTConnection *ct; for (ct = t->connection_head; NULL != ct; ct = ct->next) iter (cls, ct->c); } /** * Iterate all channels of a tunnel. * * @param t Tunnel whose channels to iterate. * @param iter Iterator. * @param cls Closure for @c iter. */ void GMT_iterate_channels (struct MeshTunnel3 *t, GMT_chan_iter iter, void *cls) { struct MeshTChannel *cht; for (cht = t->channel_head; NULL != cht; cht = cht->next) iter (cls, cht->ch); } gnunet-0.10.1/src/mesh/gnunet-mesh.c0000644000175000017500000005410212320526362014136 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-mesh.c * @brief Print information about mesh tunnels and peers. * @author Bartlomiej Polot */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_mesh_service.h" #include "mesh.h" /** * Option -m. */ static int monitor_connections; /** * Option -P. */ static int request_peers; /** * Option --peer */ static char *peer_id; /** * Option -T. */ static int request_tunnels; /** * Option --tunnel */ static char *tunnel_id; /** * Option --connection */ static char *conn_id; /** * Option --channel */ static char *channel_id; /** * Port to listen on (-p). */ static uint32_t listen_port; /** * Request echo service */ int echo; /** * Time of last echo request. */ struct GNUNET_TIME_Absolute echo_time; /** * Task for next echo request. */ GNUNET_SCHEDULER_TaskIdentifier echo_task; /** * Peer to connect to. */ static char *target_id; /** * Port to connect to */ static uint32_t target_port; /** * Data pending in netcat mode. */ size_t data_size; /** * Mesh handle. */ static struct GNUNET_MESH_Handle *mh; /** * Channel handle. */ static struct GNUNET_MESH_Channel *ch; /** * Shutdown task handle. */ GNUNET_SCHEDULER_TaskIdentifier sd; static void listen_stdio (void); /** * Task run in monitor mode when the user presses CTRL-C to abort. * Stops monitoring activity. * * @param cls Closure (unused). * @param tc scheduler context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); if (NULL != ch) { GNUNET_MESH_channel_destroy (ch); ch = NULL; } if (NULL != mh) { GNUNET_MESH_disconnect (mh); mh = NULL; } } /** * Function called to notify a client about the connection * begin ready to queue more data. "buf" will be * NULL and "size" zero if the connection was closed for * writing in the meantime. * * FIXME * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ size_t data_ready (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg; size_t total_size; if (NULL == buf || 0 == size) { GNUNET_SCHEDULER_shutdown(); return 0; } total_size = data_size + sizeof (struct GNUNET_MessageHeader); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending %u bytes\n", data_size); GNUNET_assert (size >= total_size); msg = buf; msg->size = htons (total_size); msg->type = htons (GNUNET_MESSAGE_TYPE_MESH_CLI); memcpy (&msg[1], cls, data_size); if (GNUNET_NO == echo) { listen_stdio (); } else { echo_time = GNUNET_TIME_absolute_get (); } return total_size; } /** * Task run in monitor mode when the user presses CTRL-C to abort. * Stops monitoring activity. * * @param cls Closure (unused). * @param tc scheduler context */ static void read_stdio (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static char buf[60000]; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { return; } data_size = read (0, buf, 60000); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stdio read %u bytes\n", data_size); if (data_size < 1) { GNUNET_SCHEDULER_shutdown(); return; } GNUNET_MESH_notify_transmit_ready (ch, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, data_size + sizeof (struct GNUNET_MessageHeader), &data_ready, buf); } /** * Start listening to stdin */ static void listen_stdio (void) { struct GNUNET_NETWORK_FDSet *rs; rs = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_set_native (rs, 0); GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_UNIT_FOREVER_REL, rs, NULL, &read_stdio, NULL); GNUNET_NETWORK_fdset_destroy (rs); } /** * Function called whenever a channel is destroyed. Should clean up * any associated state. * * It must NOT call #GNUNET_MESH_channel_destroy on the channel. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void channel_ended (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n"); GNUNET_break (channel == ch); ch = NULL; GNUNET_SCHEDULER_shutdown (); } /** * Method called whenever another peer has added us to a channel * the other peer initiated. * Only called (once) upon reception of data with a message type which was * subscribed to in #GNUNET_MESH_connect. * * A call to #GNUNET_MESH_channel_destroy causes te channel to be ignored. In * this case the handler MUST return NULL. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel * @param port Port this channel is for. * @param options MeshOption flag field, with all active option bits set to 1. * * @return initial channel context for the channel * (can be NULL -- that's not an error) */ static void * channel_incoming (void *cls, struct GNUNET_MESH_Channel * channel, const struct GNUNET_PeerIdentity * initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Incoming channel %p on port %u\n", channel, port); if (NULL != ch) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "A channel already exists\n"); return NULL; } if (0 == listen_port) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not listening to channels\n"); return NULL; } ch = channel; if (GNUNET_NO == echo) { listen_stdio (); return NULL; } data_size = 0; return NULL; } /** * @brief Send an echo request to the remote peer. * * @param cls Closure (NULL). * @param tc Task context. */ static void send_echo (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) || NULL == ch) return; GNUNET_MESH_notify_transmit_ready (ch, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct GNUNET_MessageHeader), &data_ready, NULL); } /** * Call MESH's monitor API, get info of one connection. * * @param cls Closure (unused). * @param tc TaskContext */ static void create_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PeerIdentity pid; enum GNUNET_MESH_ChannelOption opt; GNUNET_assert (NULL == ch); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (target_id, strlen (target_id), &pid.public_key)) { FPRINTF (stderr, _("Invalid target `%s'\n"), target_id); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id); opt = GNUNET_MESH_OPTION_DEFAULT | GNUNET_MESH_OPTION_RELIABLE; ch = GNUNET_MESH_channel_create (mh, NULL, &pid, target_port, opt); if (GNUNET_NO == echo) listen_stdio (); else GNUNET_SCHEDULER_add_now (send_echo, NULL); } /** * Function called whenever a message is received. * * Each time the function must call #GNUNET_MESH_receive_done on the channel * in order to receive the next message. This doesn't need to be immediate: * can be delayed if some processing is done on the message. * * @param cls Closure (set from #GNUNET_MESH_connect). * @param channel Connection to the other end. * @param channel_ctx Place to store local state associated with the channel. * @param message The actual message. * @return #GNUNET_OK to keep the channel open, * #GNUNET_SYSERR to close it (signal serious error). */ static int data_callback (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { uint16_t len; ssize_t done; uint16_t off; const char *buf; GNUNET_break (ch == channel); if (GNUNET_YES == echo) { if (0 != listen_port) { /* Just listening to echo incoming messages*/ GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct GNUNET_MessageHeader), &data_ready, NULL); return GNUNET_OK; } else { struct GNUNET_TIME_Relative latency; latency = GNUNET_TIME_absolute_get_duration (echo_time); echo_time = GNUNET_TIME_UNIT_FOREVER_ABS; FPRINTF (stdout, "time: %s\n", GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO)); echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &send_echo, NULL); } } len = ntohs (message->size) - sizeof (*message); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len); buf = (const char *) &message[1]; off = 0; while (off < len) { done = write (1, &buf[off], len - off); if (done <= 0) { if (-1 == done) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write"); return GNUNET_SYSERR; } off += done; } return GNUNET_OK; } /** * Method called to retrieve information about all peers in MESH, called * once per peer. * * After last peer has been reported, an additional call with NULL is done. * * @param cls Closure. * @param peer Peer, or NULL on "EOF". * @param tunnel Do we have a tunnel towards this peer? * @param n_paths Number of known paths towards this peer. * @param best_path How long is the best path? * (0 = unknown, 1 = ourselves, 2 = neighbor) */ static void peers_callback (void *cls, const struct GNUNET_PeerIdentity *peer, int tunnel, unsigned int n_paths, unsigned int best_path) { if (NULL == peer) { if (GNUNET_YES != monitor_connections) { GNUNET_SCHEDULER_shutdown(); } return; } FPRINTF (stdout, "%s tunnel: %c, paths: %u\n", GNUNET_i2s_full (peer), tunnel ? 'Y' : 'N', n_paths); } /** * Method called to retrieve information about a specific peer * known to the service. * * @param cls Closure. * @param peer Peer ID. * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO * @param n_paths Number of paths known towards peer. * @param paths Array of PEER_IDs representing all paths to reach the peer. * Each path starts with the local peer. * Each path ends with the destination peer (given in @c peer). */ void peer_callback (void *cls, const struct GNUNET_PeerIdentity *peer, int tunnel, int neighbor, unsigned int n_paths, struct GNUNET_PeerIdentity *paths) { } /** * Method called to retrieve information about all tunnels in MESH. * * @param cls Closure. * @param peer Destination peer. * @param channels Number of channels. * @param connections Number of connections. * @param estate Encryption state. * @param cstate Connectivity state. */ void tunnels_callback (void *cls, const struct GNUNET_PeerIdentity *peer, unsigned int channels, unsigned int connections, uint16_t estate, uint16_t cstate) { if (NULL == peer) { if (GNUNET_YES != monitor_connections) { GNUNET_SCHEDULER_shutdown(); } return; } FPRINTF (stdout, "%s [ENC: %u, CON: %u] CHs: %u, CONNs: %u\n", GNUNET_i2s_full (peer), estate, cstate, channels, connections); } /** * Method called to retrieve information about a specific tunnel the mesh peer * has established, o`r is trying to establish. * * @param cls Closure. * @param peer Peer towards whom the tunnel is directed. * @param n_channels Number of channels. * @param n_connections Number of connections. * @param channels Channels. * @param connections Connections. * @param estate Encryption status. * @param cstate Connectivity status. */ void tunnel_callback (void *cls, const struct GNUNET_PeerIdentity *peer, unsigned int n_channels, unsigned int n_connections, uint32_t *channels, struct GNUNET_MESH_Hash *connections, unsigned int estate, unsigned int cstate) { unsigned int i; if (NULL != peer) { FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer)); FPRINTF (stdout, "- %u channels\n", n_channels); for (i = 0; i < n_channels; i++) FPRINTF (stdout, " %u\n", channels[i]); FPRINTF (stdout, "- %u connections\n", n_connections); for (i = 0; i < n_connections; i++) FPRINTF (stdout, " %s\n", GM_h2s (&connections[i])); FPRINTF (stdout, "- enc state: %u\n", estate); FPRINTF (stdout, "- con state: %u\n", cstate); } if (GNUNET_YES != monitor_connections) { GNUNET_SCHEDULER_shutdown(); } return; } /** * Call MESH's meta API, get all peers known to a peer. * * @param cls Closure (unused). * @param tc TaskContext */ static void get_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); return; } GNUNET_MESH_get_peers (mh, &peers_callback, NULL); } /** * Call MESH's monitor API, get info of one peer. * * @param cls Closure (unused). * @param tc TaskContext */ static void show_peer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PeerIdentity pid; if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id, strlen (peer_id), &pid.public_key)) { fprintf (stderr, _("Invalid peer ID `%s'\n"), peer_id); GNUNET_SCHEDULER_shutdown(); return; } GNUNET_MESH_get_peer (mh, &pid, peer_callback, NULL); } /** * Call MESH's meta API, get all tunnels known to a peer. * * @param cls Closure (unused). * @param tc TaskContext */ static void get_tunnels (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); return; } GNUNET_MESH_get_tunnels (mh, &tunnels_callback, NULL); } /** * Call MESH's monitor API, get info of one tunnel. * * @param cls Closure (unused). * @param tc TaskContext */ static void show_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PeerIdentity pid; if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id, strlen (tunnel_id), &pid.public_key)) { fprintf (stderr, _("Invalid tunnel owner `%s'\n"), tunnel_id); GNUNET_SCHEDULER_shutdown(); return; } GNUNET_MESH_get_tunnel (mh, &pid, tunnel_callback, NULL); } /** * Call MESH's monitor API, get info of one channel. * * @param cls Closure (unused). * @param tc TaskContext */ static void show_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { } /** * Call MESH's monitor API, get info of one connection. * * @param cls Closure (unused). * @param tc TaskContext */ static void show_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_MESH_InboundChannelNotificationHandler *newch = NULL; GNUNET_MESH_ChannelEndHandler *endch = NULL; static const struct GNUNET_MESH_MessageHandler handlers[] = { {&data_callback, GNUNET_MESSAGE_TYPE_MESH_CLI, 0}, {NULL, 0, 0} /* FIXME add option to monitor msg types */ }; static uint32_t *ports = NULL; /* FIXME add option to monitor apps */ target_id = args[0]; target_port = args[0] && args[1] ? atoi(args[1]) : 0; if ( (0 != (request_peers | request_tunnels) || 0 != monitor_connections || NULL != tunnel_id || NULL != conn_id || NULL != channel_id) && target_id != NULL) { FPRINTF (stderr, _("You must NOT give a TARGET" "when using 'request all' options\n")); return; } if (NULL != target_id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating channel to %s\n", target_id); GNUNET_SCHEDULER_add_now (&create_channel, NULL); endch = &channel_ended; } else if (0 != listen_port) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Listen\n"); newch = &channel_incoming; endch = &channel_ended; ports = GNUNET_malloc (sizeof (uint32_t) * 2); ports[0] = listen_port; } else if (NULL != peer_id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show peer\n"); GNUNET_SCHEDULER_add_now (&show_peer, NULL); } else if (NULL != tunnel_id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show tunnel\n"); GNUNET_SCHEDULER_add_now (&show_tunnel, NULL); } else if (NULL != channel_id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show channel\n"); GNUNET_SCHEDULER_add_now (&show_channel, NULL); } else if (NULL != conn_id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show connection\n"); GNUNET_SCHEDULER_add_now (&show_connection, NULL); } else if (GNUNET_YES == request_peers) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n"); GNUNET_SCHEDULER_add_now (&get_peers, NULL); } else if (GNUNET_YES == request_tunnels) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n"); GNUNET_SCHEDULER_add_now (&get_tunnels, NULL); } else { FPRINTF (stderr, "No action requested\n"); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to mesh\n"); mh = GNUNET_MESH_connect (cfg, NULL, /* cls */ newch, /* new channel */ endch, /* cleaner */ handlers, ports); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done\n"); if (NULL == mh) GNUNET_SCHEDULER_add_now (shutdown_task, NULL); else sd = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, shutdown_task, NULL); } /** * The main function to obtain peer information. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int res; const char helpstr[] = "Create channels and retreive info about meshs status."; static const struct GNUNET_GETOPT_CommandLineOption options[] = { // {'a', "channel", "TUNNEL_ID:CHANNEL_ID", // gettext_noop ("provide information about a particular channel"), // GNUNET_YES, &GNUNET_GETOPT_set_string, &channel_id}, {'C', "connection", "CONNECTION_ID", gettext_noop ("provide information about a particular connection"), GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id}, {'e', "echo", NULL, gettext_noop ("activate echo mode"), GNUNET_NO, &GNUNET_GETOPT_set_one, &echo}, // {'m', "monitor", NULL, // gettext_noop ("provide information about all tunnels (continuously) NOT IMPLEMENTED"), /* FIXME */ // GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor_connections}, {'o', "open-port", NULL, gettext_noop ("port to listen to (default; 0)"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &listen_port}, {'p', "peer", "PEER_ID", gettext_noop ("provide information about all peers"), GNUNET_NO, &GNUNET_GETOPT_set_string, &peer_id}, {'P', "peers", NULL, gettext_noop ("provide information about all peers"), GNUNET_NO, &GNUNET_GETOPT_set_one, &request_peers}, {'t', "tunnel", "TUNNEL_ID", gettext_noop ("provide information about a particular tunnel"), GNUNET_YES, &GNUNET_GETOPT_set_string, &tunnel_id}, {'T', "tunnels", NULL, gettext_noop ("provide information about all tunnels"), GNUNET_NO, &GNUNET_GETOPT_set_one, &request_tunnels}, GNUNET_GETOPT_OPTION_END }; monitor_connections = GNUNET_NO; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; res = GNUNET_PROGRAM_run (argc, argv, "gnunet-mesh (OPTIONS | TARGET PORT)", gettext_noop (helpstr), options, &run, NULL); GNUNET_free ((void *) argv); if (GNUNET_OK == res) return 0; else return 1; } /* end of gnunet-mesh.c */ gnunet-0.10.1/src/mesh/gnunet-service-mesh_connection.h0000644000175000017500000003423412320526362020024 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh_connection.h * @brief mesh service; dealing with connections * @author Bartlomiej Polot * * All functions in this file should use the prefix GMC (Gnunet Mesh Connection) */ #ifndef GNUNET_SERVICE_MESH_CONNECTION_H #define GNUNET_SERVICE_MESH_CONNECTION_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_util_lib.h" /** * All the states a connection can be in. */ enum MeshConnectionState { /** * Uninitialized status, should never appear in operation. */ MESH_CONNECTION_NEW, /** * Connection create message sent, waiting for ACK. */ MESH_CONNECTION_SENT, /** * Connection ACK sent, waiting for ACK. */ MESH_CONNECTION_ACK, /** * Connection confirmed, ready to carry traffic. */ MESH_CONNECTION_READY, /** * Connection to be destroyed, just waiting to empty queues. */ MESH_CONNECTION_DESTROYED, }; /** * Struct containing all information regarding a connection to a peer. */ struct MeshConnection; /** * Handle for messages queued but not yet sent. */ struct MeshConnectionQueue; #include "mesh_path.h" #include "gnunet-service-mesh_channel.h" #include "gnunet-service-mesh_peer.h" /** * Callback called when a queued message is sent. * * @param cls Closure. * @param c Connection this message was on. * @param type Type of message sent. * @param fwd Was this a FWD going message? * @param size Size of the message. */ typedef void (*GMC_sent) (void *cls, struct MeshConnection *c, struct MeshConnectionQueue *q, uint16_t type, int fwd, size_t size); /** * Core handler for connection creation. * * @param cls Closure (unused). * @param peer Sender (neighbor). * @param message Message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Core handler for path confirmations. * * @param cls closure * @param message message * @param peer peer identity this notification is about * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Core handler for notifications of broken paths * * @param cls Closure (unused). * @param id Peer identity of sending neighbor. * @param message Message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_broken (void* cls, const struct GNUNET_PeerIdentity* id, const struct GNUNET_MessageHeader* message); /** * Core handler for tunnel destruction * * @param cls Closure (unused). * @param peer Peer identity of sending neighbor. * @param message Message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Core handler for encrypted mesh network traffic (channel mgmt, data). * * @param cls Closure (unused). * @param message Message received. * @param peer Peer who sent the message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Core handler for key exchange traffic (ephemeral key, ping, pong). * * @param cls Closure (unused). * @param message Message received. * @param peer Peer who sent the message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Core handler for mesh network traffic point-to-point acks. * * @param cls closure * @param message message * @param peer peer identity this notification is about * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Core handler for mesh network traffic point-to-point ack polls. * * @param cls closure * @param message message * @param peer peer identity this notification is about * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Core handler for mesh keepalives. * * @param cls closure * @param message message * @param peer peer identity this notification is about * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) * * TODO: Check who we got this from, to validate route. */ int GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message); /** * Send an ACK on the appropriate connection/channel, depending on * the direction and the position of the peer. * * @param c Which connection to send the hop-by-hop ACK. * @param fwd Is this a fwd ACK? (will go dest->root). * @param force Send the ACK even if suboptimal (e.g. requested by POLL). */ void GMC_send_ack (struct MeshConnection *c, int fwd, int force); /** * Initialize the connections subsystem * * @param c Configuration handle. */ void GMC_init (const struct GNUNET_CONFIGURATION_Handle *c); /** * Shut down the connections subsystem. */ void GMC_shutdown (void); /** * Create a connection. * * @param cid Connection ID (either created locally or imposed remotely). * @param t Tunnel this connection belongs to (or NULL); * @param p Path this connection has to use. * @param own_pos Own position in the @c p path. * * @return Newly created connection, NULL in case of error (own id not in path). */ struct MeshConnection * GMC_new (const struct GNUNET_MESH_Hash *cid, struct MeshTunnel3 *t, struct MeshPeerPath *p, unsigned int own_pos); /** * Connection is no longer needed: destroy it. * * Cancels all pending traffic (including possible DESTROY messages), all * maintenance tasks and removes the connection from neighbor peers and tunnel. * * @param c Connection to destroy. */ void GMC_destroy (struct MeshConnection *c); /** * Get the connection ID. * * @param c Connection to get the ID from. * * @return ID of the connection. */ const struct GNUNET_MESH_Hash * GMC_get_id (const struct MeshConnection *c); /** * Get a hash for the connection ID. * * @param c Connection to get the hash. * * @return Hash expanded from the ID of the connection. */ const struct GNUNET_HashCode * GMC_get_h (const struct MeshConnection *c); /** * Get the connection path. * * @param c Connection to get the path from. * * @return path used by the connection. */ const struct MeshPeerPath * GMC_get_path (const struct MeshConnection *c); /** * Get the connection state. * * @param c Connection to get the state from. * * @return state of the connection. */ enum MeshConnectionState GMC_get_state (const struct MeshConnection *c); /** * Get the connection tunnel. * * @param c Connection to get the tunnel from. * * @return tunnel of the connection. */ struct MeshTunnel3 * GMC_get_tunnel (const struct MeshConnection *c); /** * Get free buffer space in a connection. * * @param c Connection. * @param fwd Is query about FWD traffic? * * @return Free buffer space [0 - max_msgs_queue/max_connections] */ unsigned int GMC_get_buffer (struct MeshConnection *c, int fwd); /** * Get how many messages have we allowed to send to us from a direction. * * @param c Connection. * @param fwd Are we asking about traffic from FWD (BCK messages)? * * @return last_ack_sent - last_pid_recv */ unsigned int GMC_get_allowed (struct MeshConnection *c, int fwd); /** * Get messages queued in a connection. * * @param c Connection. * @param fwd Is query about FWD traffic? * * @return Number of messages queued. */ unsigned int GMC_get_qn (struct MeshConnection *c, int fwd); /** * Allow the connection to advertise a buffer of the given size. * * The connection will send an @c fwd ACK message (so: in direction !fwd) * allowing up to last_pid_recv + buffer. * * @param c Connection. * @param buffer How many more messages the connection can accept. * @param fwd Is this about FWD traffic? (The ack will go dest->root). */ void GMC_allow (struct MeshConnection *c, unsigned int buffer, int fwd); /** * Send FWD keepalive packets for a connection. * * @param cls Closure (connection for which to send the keepalive). * @param tc Notification context. */ void GMC_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Send BCK keepalive packets for a connection. * * @param cls Closure (connection for which to send the keepalive). * @param tc Notification context. */ void GMC_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Notify other peers on a connection of a broken link. Mark connections * to destroy after all traffic has been sent. * * @param c Connection on which there has been a disconnection. * @param peer Peer that disconnected. */ void GMC_notify_broken (struct MeshConnection *c, struct MeshPeer *peer); /** * Is this peer the first one on the connection? * * @param c Connection. * @param fwd Is this about fwd traffic? * * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal. */ int GMC_is_origin (struct MeshConnection *c, int fwd); /** * Is this peer the last one on the connection? * * @param c Connection. * @param fwd Is this about fwd traffic? * Note that the ROOT is the terminal for BCK traffic! * * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. */ int GMC_is_terminal (struct MeshConnection *c, int fwd); /** * See if we are allowed to send by the next hop in the given direction. * * @param c Connection. * @param fwd Is this about fwd traffic? * * @return #GNUNET_YES in case it's OK to send. */ int GMC_is_sendable (struct MeshConnection *c, int fwd); /** * Cancel a previously sent message while it's in the queue. * * ONLY can be called before the continuation given to the send function * is called. Once the continuation is called, the message is no longer in the * queue. * * @param q Handle to the queue. */ void GMC_cancel (struct MeshConnectionQueue *q); /** * Sends an already built message on a connection, properly registering * all used resources. * * @param message Message to send. Function makes a copy of it. * If message is not hop-by-hop, decrements TTL of copy. * @param c Connection on which this message is transmitted. * @param fwd Is this a fwd message? * @param force Force the connection to accept the message (buffer overfill). * @param cont Continuation called once message is sent. Can be NULL. * @param cont_cls Closure for @c cont. * * @return Handle to cancel the message before it's sent. * NULL on error or if @c cont is NULL. * Invalid on @c cont call. */ struct MeshConnectionQueue * GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, struct MeshConnection *c, int fwd, int force, GMC_sent cont, void *cont_cls); /** * Sends a CREATE CONNECTION message for a path to a peer. * Changes the connection and tunnel states if necessary. * * @param connection Connection to create. */ void GMC_send_create (struct MeshConnection *connection); /** * Send a message to all peers in this connection that the connection * is no longer valid. * * If some peer should not receive the message, it should be zero'ed out * before calling this function. * * @param c The connection whose peers to notify. */ void GMC_send_destroy (struct MeshConnection *c); /** * @brief Start a polling timer for the connection. * * When a neighbor does not accept more traffic on the connection it could be * caused by a simple congestion or by a lost ACK. Polling enables to check * for the lastest ACK status for a connection. * * @param c Connection. * @param fwd Should we poll in the FWD direction? */ void GMC_start_poll (struct MeshConnection *c, int fwd); /** * @brief Stop polling a connection for ACKs. * * Once we have enough ACKs for future traffic, polls are no longer necessary. * * @param c Connection. * @param fwd Should we stop the poll in the FWD direction? */ void GMC_stop_poll (struct MeshConnection *c, int fwd); /** * Get a (static) string for a connection. * * @param c Connection. */ const char * GMC_2s (const struct MeshConnection *c); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_SERVICE_MESH_CONNECTION_H */ #endif /* end of gnunet-service-mesh_connection.h */ gnunet-0.10.1/src/mesh/test_mesh_single.c0000644000175000017500000002161012272445167015247 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/test_mesh_single.c * @brief test mesh single: test of mesh channels with just one client * @author Bartlomiej Polot */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dht_service.h" #include "gnunet_testing_lib.h" #include "gnunet_mesh_service.h" #define REPETITIONS 5 #define DATA_SIZE 35000 struct GNUNET_TESTING_Peer *me; static struct GNUNET_MESH_Handle *mesh; static struct GNUNET_MESH_Channel *ch1; static struct GNUNET_MESH_Channel *ch2; static int result; static GNUNET_SCHEDULER_TaskIdentifier abort_task; static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; static unsigned int repetition; /* forward declaration */ static size_t do_send (void *cls, size_t size, void *buf); /** * Shutdown nicely */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n"); if (GNUNET_SCHEDULER_NO_TASK != abort_task) { GNUNET_SCHEDULER_cancel (abort_task); } if (NULL != ch1) { GNUNET_MESH_channel_destroy (ch1); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n"); if (NULL != mesh) { GNUNET_MESH_disconnect (mesh); mesh = NULL; } else { GNUNET_break (0); } } /** * Something went wrong and timed out. Kill everything and set error flag */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n"); result = GNUNET_SYSERR; abort_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) { GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_NO_TASK; } do_shutdown (cls, tc); } static void finish (void) { if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, NULL); } /** * Function is called whenever a message is received. * * @param cls closure (set from GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int data_callback (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data callback! Repetition %u/%u\n", repetition, REPETITIONS); repetition = repetition + 1; if (repetition < REPETITIONS) { struct GNUNET_MESH_Channel *my_channel; if (repetition % 2 == 0) my_channel = ch1; else my_channel = ch2; GNUNET_MESH_notify_transmit_ready (my_channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct GNUNET_MessageHeader) + DATA_SIZE, &do_send, NULL); GNUNET_MESH_receive_done (channel); return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All data OK. Destroying channel.\n"); GNUNET_MESH_channel_destroy (ch1); ch1 = NULL; return GNUNET_OK; } /** * Method called whenever another peer has added us to a channel * the other peer initiated. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel * @param port port number * @param options channel option flags * @return initial channel context for the channel * (can be NULL -- that's not an error) */ static void * inbound_channel (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received incoming channel on port %u\n", port); ch2 = channel; return NULL; } /** * Function called whenever an inbound channel is destroyed. Should clean up * any associated state. * * @param cls closure (set from GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void channel_end (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { long id = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "incoming channel closed at peer %ld\n", id); if (REPETITIONS == repetition && channel == ch2) { ch2 = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "everything fine! finishing!\n"); result = GNUNET_OK; finish (); } } /** * Handler array for traffic received on peer1 */ static struct GNUNET_MESH_MessageHandler handlers1[] = { {&data_callback, 1, 0}, {NULL, 0, 0} }; /** * Data send callback: fillbuffer with test packet. * * @param cls Closure (unused). * @param size Buffer size. * @param buf Buffer to fill. * * @return size of test packet. */ static size_t do_send (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *m = buf; if (NULL == buf) { GNUNET_break (0); result = GNUNET_SYSERR; return 0; } m->size = htons (sizeof (struct GNUNET_MessageHeader)); m->type = htons (1); memset (&m[1], 0, DATA_SIZE); GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader) + DATA_SIZE); return sizeof (struct GNUNET_MessageHeader) + DATA_SIZE; } /** * Connect to other client and send data * * @param cls Closue (unused). * @param tc TaskContext. */ static void do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PeerIdentity id; size_t size = sizeof (struct GNUNET_MessageHeader) + DATA_SIZE; if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; GNUNET_TESTING_peer_get_identity (me, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n"); ch1 = GNUNET_MESH_channel_create (mesh, NULL, &id, 1, GNUNET_MESH_OPTION_DEFAULT); GNUNET_MESH_notify_transmit_ready (ch1, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, size, &do_send, NULL); } /** * Initialize framework and start test * * @param cls Closure (unused). * @param cfg Configuration handle. * @param peer Testing peer handle. */ static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { static uint32_t ports[] = {1, 0}; me = peer; abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort, NULL); mesh = GNUNET_MESH_connect (cfg, /* configuration */ (void *) 1L, /* cls */ &inbound_channel, /* inbound new hndlr */ &channel_end, /* inbound end hndlr */ handlers1, /* traffic handlers */ ports); /* ports offered */ if (NULL == mesh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh :(\n"); result = GNUNET_SYSERR; return; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO MESH :D\n"); } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_connect, NULL); } /** * Main */ int main (int argc, char *argv[]) { result = GNUNET_NO; if (0 != GNUNET_TESTING_peer_run ("test-mesh-local", "test_mesh.conf", &run, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n"); return 2; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result); return (result == GNUNET_OK) ? 0 : 1; } /* end of test_mesh_single.c */ gnunet-0.10.1/src/mesh/gnunet-service-mesh_dht.c0000644000175000017500000003176712316473376016462 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" #include "mesh_path.h" #include "gnunet-service-mesh_dht.h" #include "gnunet-service-mesh_peer.h" #include "gnunet-service-mesh_hello.h" #define LOG(level, ...) GNUNET_log_from (level,"mesh-dht",__VA_ARGS__) /******************************************************************************/ /******************************** STRUCTS **********************************/ /******************************************************************************/ /** * Handle for DHT searches. */ struct GMD_search_handle { /** DHT_GET handle. */ struct GNUNET_DHT_GetHandle *dhtget; /** Provided callback to call when a path is found. */ GMD_search_callback callback; /** Provided closure. */ void *cls; /** Peer ID searched for */ GNUNET_PEER_Id peer_id; }; /******************************************************************************/ /******************************* GLOBALS ***********************************/ /******************************************************************************/ /** * Global handle to the statistics service. */ extern struct GNUNET_STATISTICS_Handle *stats; /** * Own ID (short value). */ extern GNUNET_PEER_Id myid; /** * Own ID (full value). */ extern struct GNUNET_PeerIdentity my_full_id; /** * Handle to use DHT. */ static struct GNUNET_DHT_Handle *dht_handle; /** * How often to PUT own ID in the DHT. */ static struct GNUNET_TIME_Relative id_announce_time; /** * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put. */ static unsigned long long dht_replication_level; /** * Task to periodically announce itself in the network. */ static GNUNET_SCHEDULER_TaskIdentifier announce_id_task; /** * GET requests to stop on shutdown. */ static struct GNUNET_CONTAINER_MultiHashMap32 *get_requests; /******************************************************************************/ /******************************** STATIC ***********************************/ /******************************************************************************/ /** * Build a PeerPath from the paths returned from the DHT, reversing the paths * to obtain a local peer -> destination path and interning the peer ids. * * @return Newly allocated and created path * * FIXME refactor and use build_path_from_peer_ids */ static struct MeshPeerPath * path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length) { struct MeshPeerPath *p; GNUNET_PEER_Id id; int i; p = path_new (1); p->peers[0] = myid; GNUNET_PEER_change_rc (myid, 1); i = get_path_length; LOG (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", i); for (i--; i >= 0; i--) { id = GNUNET_PEER_intern (&get_path[i]); if (p->length > 0 && id == p->peers[p->length - 1]) { LOG (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n"); GNUNET_PEER_change_rc (id, -1); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " Adding from GET: %s.\n", GNUNET_i2s (&get_path[i])); p->length++; p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length); p->peers[p->length - 1] = id; } } i = put_path_length; LOG (GNUNET_ERROR_TYPE_DEBUG, " PUT has %d hops.\n", i); for (i--; i >= 0; i--) { id = GNUNET_PEER_intern (&put_path[i]); if (id == myid) { /* PUT path went through us, so discard the path up until now and start * from here to get a much shorter (and loop-free) path. */ path_destroy (p); p = path_new (0); } if (p->length > 0 && id == p->peers[p->length - 1]) { LOG (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n"); GNUNET_PEER_change_rc (id, -1); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " Adding from PUT: %s.\n", GNUNET_i2s (&put_path[i])); p->length++; p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length); p->peers[p->length - 1] = id; } } #if MESH_DEBUG if (get_path_length > 0) LOG (GNUNET_ERROR_TYPE_DEBUG, " (first of GET: %s)\n", GNUNET_i2s (&get_path[0])); if (put_path_length > 0) LOG (GNUNET_ERROR_TYPE_DEBUG, " (first of PUT: %s)\n", GNUNET_i2s (&put_path[0])); LOG (GNUNET_ERROR_TYPE_DEBUG, " In total: %d hops\n", p->length); for (i = 0; i < p->length; i++) { struct GNUNET_PeerIdentity peer_id; GNUNET_PEER_resolve (p->peers[i], &peer_id); LOG (GNUNET_ERROR_TYPE_DEBUG, " %u: %s\n", p->peers[i], GNUNET_i2s (&peer_id)); } #endif return p; } /** * Function to process paths received for a new peer addition. The recorded * paths form the initial tunnel, which can be optimized later. * Called on each result obtained for the DHT search. * * @param cls closure * @param exp when will this value expire * @param key key of the result * @param get_path path of the get request * @param get_path_length lenght of get_path * @param put_path path of the put request * @param put_path_length length of the put_path * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data */ static void dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { struct GMD_search_handle *h = cls; struct GNUNET_HELLO_Message *hello; struct MeshPeerPath *p; struct MeshPeer *peer; char *s; p = path_build_from_dht (get_path, get_path_length, put_path, put_path_length); s = path_2s (p); LOG (GNUNET_ERROR_TYPE_INFO, "Got path from DHT: %s\n", s); GNUNET_free_non_null (s); peer = GMP_get_short (p->peers[p->length - 1]); LOG (GNUNET_ERROR_TYPE_DEBUG, "Got HELLO for %s\n", GMP_2s (peer)); h->callback (h->cls, p); path_destroy (p); hello = (struct GNUNET_HELLO_Message *) data; GMP_set_hello (peer, hello); GMP_try_connect (peer); return; } /** * Periodically announce self id in the DHT * * @param cls closure * @param tc task context */ static void announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_HashCode phash; const struct GNUNET_HELLO_Message *hello; size_t size; struct GNUNET_TIME_Absolute expiration; struct GNUNET_TIME_Relative retry_time; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { announce_id_task = GNUNET_SCHEDULER_NO_TASK; return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n"); /* TODO * - Set data expiration in function of X * - Adapt X to churn */ hello = GMH_get_mine (); if (NULL == hello || (size = GNUNET_HELLO_size (hello)) == 0) { /* Peerinfo gave us no hello yet, try again in a second. */ announce_id_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &announce_id, cls); LOG (GNUNET_ERROR_TYPE_DEBUG, " no hello, waiting!\n"); return; } expiration = GNUNET_HELLO_get_last_expiration (hello); retry_time = GNUNET_TIME_absolute_get_remaining (expiration); LOG (GNUNET_ERROR_TYPE_DEBUG, "Hello %p size: %u\n", hello, size); memset (&phash, 0, sizeof (phash)); memcpy (&phash, &my_full_id, sizeof (my_full_id)); GNUNET_DHT_put (dht_handle, /* DHT handle */ &phash, /* Key to use */ dht_replication_level, /* Replication level */ GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ size, /* Size of the data */ (const char *) hello, /* Data itself */ expiration, /* Data expiration */ retry_time, /* Retry time */ NULL, /* Continuation */ NULL); /* Continuation closure */ announce_id_task = GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls); } /** * Iterator over hash map entries and stop GET requests before disconnecting * from the DHT. * * @param cls Closure (unused) * @param key Current peer ID. * @param value Value in the hash map (GMD_search_handle). * * @return #GNUNET_YES, we should continue to iterate, */ int stop_get (void *cls, uint32_t key, void *value) { struct GMD_search_handle *h = value; GMD_search_stop (h); return GNUNET_YES; } /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Initialize the DHT subsystem. * * @param c Configuration. */ void GMD_init (const struct GNUNET_CONFIGURATION_Handle *c) { LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL", &dht_replication_level)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "MESH", "DHT_REPLICATION_LEVEL", "USING DEFAULT"); dht_replication_level = 3; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME", &id_announce_time)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "MESH", "ID_ANNOUNCE_TIME", "MISSING"); GNUNET_SCHEDULER_shutdown (); return; } dht_handle = GNUNET_DHT_connect (c, 64); if (NULL == dht_handle) { GNUNET_break (0); } announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL); get_requests = GNUNET_CONTAINER_multihashmap32_create (32); } /** * Shut down the DHT subsystem. */ void GMD_shutdown (void) { GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL); GNUNET_CONTAINER_multihashmap32_destroy (get_requests); if (dht_handle != NULL) { GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; } if (GNUNET_SCHEDULER_NO_TASK != announce_id_task) { GNUNET_SCHEDULER_cancel (announce_id_task); announce_id_task = GNUNET_SCHEDULER_NO_TASK; } } struct GMD_search_handle * GMD_search (const struct GNUNET_PeerIdentity *peer_id, GMD_search_callback callback, void *cls) { struct GNUNET_HashCode phash; struct GMD_search_handle *h; LOG (GNUNET_ERROR_TYPE_DEBUG, " Starting DHT GET for peer %s\n", GNUNET_i2s (peer_id)); memset (&phash, 0, sizeof (phash)); memcpy (&phash, peer_id, sizeof (*peer_id)); h = GNUNET_new (struct GMD_search_handle); h->peer_id = GNUNET_PEER_intern (peer_id); h->callback = callback; h->cls = cls; h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ &phash, /* key to search */ dht_replication_level, /* replication level */ GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, /* xquery */ 0, /* xquery bits */ &dht_get_id_handler, h); GNUNET_CONTAINER_multihashmap32_put (get_requests, h->peer_id, h, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); return h; } void GMD_search_stop (struct GMD_search_handle *h) { GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_remove (get_requests, h->peer_id, h)); GNUNET_DHT_get_stop (h->dhtget); GNUNET_free (h); } gnunet-0.10.1/src/mesh/mesh_path.c0000644000175000017500000001162012316473376013665 00000000000000/* This file is part of GNUnet. (C) 2001 - 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/mesh_path.c * @brief Path handling functions * @author Bartlomiej Polot */ #include "mesh.h" #include "mesh_path.h" #include "gnunet-service-mesh_peer.h" /** * @brief Destroy a path after some time has past. * * If the path is returned from DHT again after a while, try again. * * @param cls Closure (path to destroy). * @param tc Task context. */ static void path_destroy_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshPeerPath *path = cls; struct MeshPeer *peer; path->path_delete = GNUNET_SCHEDULER_NO_TASK; peer = GMP_get_short (path->peers[path->length - 1]); GMP_remove_path (peer, path); } /** * Create a new path * * @param length How many hops will the path have. * * @return A newly allocated path with a peer array of the specified length. */ struct MeshPeerPath * path_new (unsigned int length) { struct MeshPeerPath *p; p = GNUNET_new (struct MeshPeerPath); if (length > 0) { p->length = length; p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id)); } return p; } /** * Invert the path * * @param path the path to invert */ void path_invert (struct MeshPeerPath *path) { GNUNET_PEER_Id aux; unsigned int i; for (i = 0; i < path->length / 2; i++) { aux = path->peers[i]; path->peers[i] = path->peers[path->length - i - 1]; path->peers[path->length - i - 1] = aux; } } /** * Duplicate a path, incrementing short peer's rc. * * @param path The path to duplicate. */ struct MeshPeerPath * path_duplicate (const struct MeshPeerPath *path) { struct MeshPeerPath *aux; unsigned int i; aux = path_new (path->length); memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id)); for (i = 0; i < aux->length; i++) GNUNET_PEER_change_rc (aux->peers[i], 1); return aux; } /** * Get the length of a path. * * @param path The path to measure, with the local peer at any point of it. * * @return Number of hops to reach destination. * UINT_MAX in case the peer is not in the path. */ unsigned int path_get_length (struct MeshPeerPath *path) { if (NULL == path) return UINT_MAX; return path->length; } /** * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop. * * DHT_get sometimes returns bad cached results, for instance, on a locally * cached result where the PUT followed a path that is no longer current. * * @param p Path to invalidate. */ void path_invalidate (struct MeshPeerPath *p) { if (GNUNET_SCHEDULER_NO_TASK != p->path_delete) return; p->path_delete = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &path_destroy_delayed, p); } /** * Test if a path is valid (or at least not known to be invalid). * * @param path Path to test. * * @return #GNUNET_YES If the path is valid or unknown, * #GNUNET_NO If the path is known to be invalid. */ int path_is_valid (const struct MeshPeerPath *path) { return (GNUNET_SCHEDULER_NO_TASK == path->path_delete); } /** * Destroy the path and free any allocated resources linked to it * * @param p the path to destroy * * @return GNUNET_OK on success */ int path_destroy (struct MeshPeerPath *p) { if (NULL == p) return GNUNET_OK; GNUNET_PEER_decrement_rcs (p->peers, p->length); GNUNET_free_non_null (p->peers); if (GNUNET_SCHEDULER_NO_TASK != p->path_delete) GNUNET_SCHEDULER_cancel (p->path_delete); GNUNET_free (p); return GNUNET_OK; } char * path_2s (struct MeshPeerPath *p) { char *s; char *old; unsigned int i; s = old = NULL; for (i = 0; i < p->length; i++) { GNUNET_asprintf (&s, "%s %s", old, GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i]))); GNUNET_free_non_null (old); old = s; } return s; } void path_debug (struct MeshPeerPath *p) { unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH:\n"); for (i = 0; i < p->length; i++) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i]))); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "END\n"); } gnunet-0.10.1/src/mesh/gnunet-service-mesh_peer.c0000644000175000017500000015546212320724374016625 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" #include "gnunet_core_service.h" #include "gnunet_statistics_service.h" #include "mesh_protocol.h" #include "gnunet-service-mesh_peer.h" #include "gnunet-service-mesh_dht.h" #include "gnunet-service-mesh_connection.h" #include "gnunet-service-mesh_tunnel.h" #include "mesh_path.h" #define LOG(level, ...) GNUNET_log_from (level,"mesh-p2p",__VA_ARGS__) /******************************************************************************/ /******************************** STRUCTS **********************************/ /******************************************************************************/ /** * Struct containing info about a queued transmission to this peer */ struct MeshPeerQueue { /** * DLL next */ struct MeshPeerQueue *next; /** * DLL previous */ struct MeshPeerQueue *prev; /** * Peer this transmission is directed to. */ struct MeshPeer *peer; /** * Connection this message belongs to. */ struct MeshConnection *c; /** * Is FWD in c? */ int fwd; /** * Pointer to info stucture used as cls. */ void *cls; /** * Type of message */ uint16_t type; /** * Size of the message */ size_t size; /** * Set when this message starts waiting for CORE. */ struct GNUNET_TIME_Absolute start_waiting; /** * Function to call on sending. */ GMP_sent callback; /** * Closure for callback. */ void *callback_cls; }; /** * Struct containing all information regarding a given peer */ struct MeshPeer { /** * ID of the peer */ GNUNET_PEER_Id id; /** * Last time we heard from this peer */ struct GNUNET_TIME_Absolute last_contact; /** * Paths to reach the peer, ordered by ascending hop count */ struct MeshPeerPath *path_head; /** * Paths to reach the peer, ordered by ascending hop count */ struct MeshPeerPath *path_tail; /** * Handle to stop the DHT search for paths to this peer */ struct GMD_search_handle *search_h; /** * Tunnel to this peer, if any. */ struct MeshTunnel3 *tunnel; /** * Connections that go through this peer, indexed by tid; */ struct GNUNET_CONTAINER_MultiHashMap *connections; /** * Handle for queued transmissions */ struct GNUNET_CORE_TransmitHandle *core_transmit; /** * Transmission queue to core DLL head */ struct MeshPeerQueue *queue_head; /** * Transmission queue to core DLL tail */ struct MeshPeerQueue *queue_tail; /** * How many messages are in the queue to this peer. */ unsigned int queue_n; /** * Hello message. */ struct GNUNET_HELLO_Message* hello; }; /******************************************************************************/ /******************************* GLOBALS ***********************************/ /******************************************************************************/ /** * Global handle to the statistics service. */ extern struct GNUNET_STATISTICS_Handle *stats; /** * Local peer own ID (full value). */ extern struct GNUNET_PeerIdentity my_full_id; /** * Local peer own ID (short) */ extern GNUNET_PEER_Id myid; /** * Peers known, indexed by PeerIdentity (MeshPeer). */ static struct GNUNET_CONTAINER_MultiPeerMap *peers; /** * How many peers do we want to remember? */ static unsigned long long max_peers; /** * Percentage of messages that will be dropped (for test purposes only). */ static unsigned long long drop_percent; /** * Handle to communicate with core. */ static struct GNUNET_CORE_Handle *core_handle; /** * Handle to try to start new connections. */ static struct GNUNET_TRANSPORT_Handle *transport_handle; /******************************************************************************/ /***************************** CORE CALLBACKS *********************************/ /******************************************************************************/ /** * Iterator to notify all connections of a broken link. Mark connections * to destroy after all traffic has been sent. * * @param cls Closure (peer disconnected). * @param key Current key code (peer id). * @param value Value in the hash map (connection). * * @return #GNUNET_YES to continue to iterate. */ static int notify_broken (void *cls, const struct GNUNET_HashCode *key, void *value) { struct MeshPeer *peer = cls; struct MeshConnection *c = value; LOG (GNUNET_ERROR_TYPE_DEBUG, " notifying %s due to %s\n", GMC_2s (c), GMP_2s (peer)); GMC_notify_broken (c, peer); return GNUNET_YES; } /** * Remove the direct path to the peer. * * @param peer Peer to remove the direct path from. * */ static struct MeshPeerPath * pop_direct_path (struct MeshPeer *peer) { struct MeshPeerPath *iter; for (iter = peer->path_head; NULL != iter; iter = iter->next) { if (2 <= iter->length) { GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter); return iter; } } return NULL; } /** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct MeshPeer *mp; struct MeshPeerPath *path; char own_id[16]; strncpy (own_id, GNUNET_i2s (&my_full_id), 15); mp = GMP_get (peer); if (myid == mp->id) { LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s (self)\n", own_id); path = path_new (1); } else { LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s <= %s\n", own_id, GNUNET_i2s (peer)); path = path_new (2); path->peers[1] = mp->id; GNUNET_PEER_change_rc (mp->id, 1); GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO); } path->peers[0] = myid; GNUNET_PEER_change_rc (myid, 1); GMP_add_path (mp, path, GNUNET_YES); mp->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); if (NULL != GMP_get_tunnel (mp)) GMP_connect (mp); return; } /** * Method called whenever a peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct MeshPeer *p; struct MeshPeerPath *direct_path; char own_id[16]; strncpy (own_id, GNUNET_i2s (&my_full_id), 15); p = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == p) { GNUNET_break (0); return; } if (myid == p->id) LOG (GNUNET_ERROR_TYPE_INFO, "DISCONNECTED %s (self)\n", own_id); else LOG (GNUNET_ERROR_TYPE_DEBUG, "DISCONNECTED %s <= %s\n", own_id, GNUNET_i2s (peer)); direct_path = pop_direct_path (p); GNUNET_CONTAINER_multihashmap_iterate (p->connections, ¬ify_broken, p); GNUNET_CONTAINER_multihashmap_destroy (p->connections); p->connections = NULL; if (NULL != p->core_transmit) { GNUNET_CORE_notify_transmit_ready_cancel (p->core_transmit); p->core_transmit = NULL; } GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO); path_destroy (direct_path); return; } /** * Functions to handle messages from core */ static struct GNUNET_CORE_MessageHandler core_handlers[] = { {&GMC_handle_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE, 0}, {&GMC_handle_confirm, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK, sizeof (struct GNUNET_MESH_ConnectionACK)}, {&GMC_handle_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN, sizeof (struct GNUNET_MESH_ConnectionBroken)}, {&GMC_handle_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY, sizeof (struct GNUNET_MESH_ConnectionDestroy)}, {&GMC_handle_ack, GNUNET_MESSAGE_TYPE_MESH_ACK, sizeof (struct GNUNET_MESH_ACK)}, {&GMC_handle_poll, GNUNET_MESSAGE_TYPE_MESH_POLL, sizeof (struct GNUNET_MESH_Poll)}, {&GMC_handle_encrypted, GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED, 0}, {&GMC_handle_kx, GNUNET_MESSAGE_TYPE_MESH_KX, 0}, {NULL, 0, 0} }; /** * To be called on core init/fail. * * @param cls Closure (config) * @param identity the public identity of this peer */ static void core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { const struct GNUNET_CONFIGURATION_Handle *c = cls; static int i = 0; LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n"); if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id))) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (identity)); LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id)); GNUNET_CORE_disconnect (core_handle); core_handle = GNUNET_CORE_connect (c, /* Main configuration */ NULL, /* Closure passed to MESH functions */ &core_init, /* Call core_init once connected */ &core_connect, /* Handle connects */ &core_disconnect, /* remove peers on disconnects */ NULL, /* Don't notify about all incoming messages */ GNUNET_NO, /* For header only in notification */ NULL, /* Don't notify about all outbound messages */ GNUNET_NO, /* For header-only out notification */ core_handlers); /* Register these handlers */ if (10 < i++) GNUNET_abort(); } GML_start (); return; } /** * Core callback to write a pre-constructed data packet to core buffer * * @param cls Closure (MeshTransmissionDescriptor with data in "data" member). * @param size Number of bytes available in buf. * @param buf Where the to write the message. * * @return number of bytes written to buf */ static size_t send_core_data_raw (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg = cls; size_t total_size; GNUNET_assert (NULL != msg); total_size = ntohs (msg->size); if (total_size > size) { GNUNET_break (0); return 0; } memcpy (buf, msg, total_size); GNUNET_free (cls); return total_size; } /** * Function to send a create connection message to a peer. * * @param c Connection to create. * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t send_core_connection_create (struct MeshConnection *c, size_t size, void *buf) { struct GNUNET_MESH_ConnectionCreate *msg; struct GNUNET_PeerIdentity *peer_ptr; const struct MeshPeerPath *p = GMC_get_path (c); size_t size_needed; int i; if (NULL == p) return 0; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n"); size_needed = sizeof (struct GNUNET_MESH_ConnectionCreate) + p->length * sizeof (struct GNUNET_PeerIdentity); if (size < size_needed || NULL == buf) { GNUNET_break (0); return 0; } msg = (struct GNUNET_MESH_ConnectionCreate *) buf; msg->header.size = htons (size_needed); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE); msg->cid = *GMC_get_id (c); peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1]; for (i = 0; i < p->length; i++) { GNUNET_PEER_resolve (p->peers[i], peer_ptr++); } LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION CREATE (%u bytes long) sent!\n", size_needed); return size_needed; } /** * Creates a path ack message in buf and frees all unused resources. * * @param c Connection to send an ACK on. * @param size number of bytes available in buf * @param buf where the callee should write the message * * @return number of bytes written to buf */ static size_t send_core_connection_ack (struct MeshConnection *c, size_t size, void *buf) { struct GNUNET_MESH_ConnectionACK *msg = buf; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n"); if (sizeof (struct GNUNET_MESH_ConnectionACK) > size) { GNUNET_break (0); return 0; } msg->header.size = htons (sizeof (struct GNUNET_MESH_ConnectionACK)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK); msg->cid = *GMC_get_id (c); LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n"); return sizeof (struct GNUNET_MESH_ConnectionACK); } /******************************************************************************/ /******************************** STATIC ***********************************/ /******************************************************************************/ /** * Get priority for a queued message. * * @param q Queued message * * @return CORE priority to use. */ static enum GNUNET_CORE_Priority get_priority (struct MeshPeerQueue *q) { enum GNUNET_CORE_Priority low; enum GNUNET_CORE_Priority high; if (NULL == q) { GNUNET_break (0); return GNUNET_CORE_PRIO_BACKGROUND; } /* Relayed traffic has lower priority, our own traffic has higher */ if (NULL == q->c || GNUNET_NO == GMC_is_origin (q->c, q->fwd)) { low = GNUNET_CORE_PRIO_BEST_EFFORT; high = GNUNET_CORE_PRIO_URGENT; } else { low = GNUNET_CORE_PRIO_URGENT; high = GNUNET_CORE_PRIO_CRITICAL_CONTROL; } /* Bulky payload has lower priority, control traffic has higher. */ if (GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED == q->type) return low; else return high; } /** * Iterator over tunnel hash map entries to destroy the tunnel during shutdown. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to iterate, * #GNUNET_NO if not. */ static int shutdown_tunnel (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct MeshPeer *p = value; struct MeshTunnel3 *t = p->tunnel; if (NULL != t) GMT_destroy (t); return GNUNET_YES; } /** * Destroy the peer_info and free any allocated resources linked to it * * @param peer The peer_info to destroy. * * @return GNUNET_OK on success */ static int peer_destroy (struct MeshPeer *peer) { struct GNUNET_PeerIdentity id; struct MeshPeerPath *p; struct MeshPeerPath *nextp; GNUNET_PEER_resolve (peer->id, &id); GNUNET_PEER_change_rc (peer->id, -1); LOG (GNUNET_ERROR_TYPE_WARNING, "destroying peer %s\n", GNUNET_i2s (&id)); if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer)) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, " not in peermap!!\n"); } if (NULL != peer->search_h) { GMD_search_stop (peer->search_h); } p = peer->path_head; while (NULL != p) { nextp = p->next; GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p); path_destroy (p); p = nextp; } GMT_destroy_empty (peer->tunnel); GNUNET_free (peer); return GNUNET_OK; } /** * Returns if peer is used (has a tunnel or is neighbor). * * @param peer Peer to check. * * @return #GNUNET_YES if peer is in use. */ static int peer_is_used (struct MeshPeer *peer) { struct MeshPeerPath *p; if (NULL != peer->tunnel) return GNUNET_YES; for (p = peer->path_head; NULL != p; p = p->next) { if (p->length < 3) return GNUNET_YES; } return GNUNET_NO; } /** * Iterator over all the peers to get the oldest timestamp. * * @param cls Closure (unsued). * @param key ID of the peer. * @param value Peer_Info of the peer. */ static int peer_get_oldest (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct MeshPeer *p = value; struct GNUNET_TIME_Absolute *abs = cls; /* Don't count active peers */ if (GNUNET_YES == peer_is_used (p)) return GNUNET_YES; if (abs->abs_value_us < p->last_contact.abs_value_us) abs->abs_value_us = p->last_contact.abs_value_us; return GNUNET_YES; } /** * Iterator over all the peers to remove the oldest entry. * * @param cls Closure (unsued). * @param key ID of the peer. * @param value Peer_Info of the peer. */ static int peer_timeout (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct MeshPeer *p = value; struct GNUNET_TIME_Absolute *abs = cls; LOG (GNUNET_ERROR_TYPE_WARNING, "peer %s timeout\n", GNUNET_i2s (key)); if (p->last_contact.abs_value_us == abs->abs_value_us && GNUNET_NO == peer_is_used (p)) { peer_destroy (p); return GNUNET_NO; } return GNUNET_YES; } /** * Delete oldest unused peer. */ static void peer_delete_oldest (void) { struct GNUNET_TIME_Absolute abs; abs = GNUNET_TIME_UNIT_FOREVER_ABS; GNUNET_CONTAINER_multipeermap_iterate (peers, &peer_get_oldest, &abs); GNUNET_CONTAINER_multipeermap_iterate (peers, &peer_timeout, &abs); } /** * Choose the best (yet unused) path towards a peer, * considering the tunnel properties. * * @param peer The destination peer. * * @return Best current known path towards the peer, if any. */ static struct MeshPeerPath * peer_get_best_path (const struct MeshPeer *peer) { struct MeshPeerPath *best_p; struct MeshPeerPath *p; unsigned int best_cost; unsigned int cost; best_cost = UINT_MAX; best_p = NULL; for (p = peer->path_head; NULL != p; p = p->next) { if (GNUNET_YES == GMT_is_path_used (peer->tunnel, p)) continue; /* If path is already in use, skip it. */ if (GNUNET_NO == path_is_valid (p)) continue; /* Don't use invalid paths. */ if ((cost = GMT_get_path_cost (peer->tunnel, p)) < best_cost) { best_cost = cost; best_p = p; } } return best_p; } static int queue_is_sendable (struct MeshPeerQueue *q) { /* Is PID-independent? */ switch (q->type) { case GNUNET_MESSAGE_TYPE_MESH_ACK: case GNUNET_MESSAGE_TYPE_MESH_POLL: case GNUNET_MESSAGE_TYPE_MESH_KX: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN: return GNUNET_YES; case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED: break; default: GNUNET_break (0); } return GMC_is_sendable (q->c, q->fwd); } /** * Get first sendable message. * * @param peer The destination peer. * * @return First transmittable message, if any. Otherwise, NULL. */ static struct MeshPeerQueue * peer_get_first_message (const struct MeshPeer *peer) { struct MeshPeerQueue *q; for (q = peer->queue_head; NULL != q; q = q->next) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking %p towards %s\n", q, GMC_2s (q->c)); if (queue_is_sendable (q)) return q; } return NULL; } /** * Function to process paths received for a new peer addition. The recorded * paths form the initial tunnel, which can be optimized later. * Called on each result obtained for the DHT search. * * @param cls closure * @param path */ static void search_handler (void *cls, const struct MeshPeerPath *path) { struct MeshPeer *peer = cls; unsigned int connection_count; GMP_add_path_to_all (path, GNUNET_NO); /* Count connections */ connection_count = GMT_count_connections (peer->tunnel); /* If we already have 3 (or more (?!)) connections, it's enough */ if (3 <= connection_count) return; if (MESH_TUNNEL3_SEARCHING == GMT_get_cstate (peer->tunnel)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n"); GMP_connect (peer); } return; } /** * Core callback to write a queued packet to core buffer * * @param cls Closure (peer info). * @param size Number of bytes available in buf. * @param buf Where the to write the message. * * @return number of bytes written to buf */ static size_t queue_send (void *cls, size_t size, void *buf) { struct MeshPeer *peer = cls; struct MeshConnection *c; struct MeshPeerQueue *queue; const struct GNUNET_PeerIdentity *dst_id; size_t data_size; peer->core_transmit = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "* Queue send towards %s (max %u)\n", GMP_2s (peer), size); if (NULL == buf || 0 == size) { LOG (GNUNET_ERROR_TYPE_DEBUG, "* Buffer size 0.\n"); return 0; } /* Initialize */ queue = peer_get_first_message (peer); if (NULL == queue) { GNUNET_assert (0); /* Core tmt_rdy should've been canceled */ return 0; } c = queue->c; dst_id = GNUNET_PEER_resolve2 (peer->id); LOG (GNUNET_ERROR_TYPE_DEBUG, "* on connection %s\n", GMC_2s (c)); /* Check if buffer size is enough for the message */ if (queue->size > size) { LOG (GNUNET_ERROR_TYPE_WARNING, "not enough room (%u vs %u), reissue\n", queue->size, size); peer->core_transmit = GNUNET_CORE_notify_transmit_ready (core_handle, GNUNET_NO, get_priority (queue), GNUNET_TIME_UNIT_FOREVER_REL, dst_id, queue->size, &queue_send, peer); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "* size %u ok\n", queue->size); /* Fill buf */ switch (queue->type) { case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN: case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED: case GNUNET_MESSAGE_TYPE_MESH_KX: case GNUNET_MESSAGE_TYPE_MESH_ACK: case GNUNET_MESSAGE_TYPE_MESH_POLL: LOG (GNUNET_ERROR_TYPE_DEBUG, "* raw: %s\n", GM_m2s (queue->type)); data_size = send_core_data_raw (queue->cls, size, buf); break; case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE: LOG (GNUNET_ERROR_TYPE_DEBUG, "* path create\n"); if (GMC_is_origin (c, GNUNET_YES)) data_size = send_core_connection_create (queue->c, size, buf); else data_size = send_core_data_raw (queue->cls, size, buf); break; case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK: LOG (GNUNET_ERROR_TYPE_DEBUG, "* path ack\n"); if (GMC_is_origin (c, GNUNET_NO) || GMC_is_origin (c, GNUNET_YES)) data_size = send_core_connection_ack (queue->c, size, buf); else data_size = send_core_data_raw (queue->cls, size, buf); break; case GNUNET_MESSAGE_TYPE_MESH_DATA: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: /* This should be encapsulted */ GNUNET_break (0); data_size = 0; break; default: GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, "* type unknown: %u\n", queue->type); data_size = 0; } if (0 < drop_percent && GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent) { LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s on connection\n", GM_m2s (queue->type), GMC_2s (c)); data_size = 0; } else { LOG (GNUNET_ERROR_TYPE_INFO, "ss %s on connection %s (%p) %s (size %u)\n", GM_m2s (queue->type), GMC_2s (c), c, GM_f2s (queue->fwd), data_size); } /* Free queue, but cls was freed by send_core_* */ GMP_queue_destroy (queue, GNUNET_NO, GNUNET_YES); /* If more data in queue, send next */ queue = peer_get_first_message (peer); if (NULL != queue) { LOG (GNUNET_ERROR_TYPE_DEBUG, "* more data!\n"); if (NULL == peer->core_transmit) { peer->core_transmit = GNUNET_CORE_notify_transmit_ready (core_handle, GNUNET_NO, get_priority (queue), GNUNET_TIME_UNIT_FOREVER_REL, dst_id, queue->size, &queue_send, peer); queue->start_waiting = GNUNET_TIME_absolute_get (); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "* tmt rdy called somewhere else\n"); } // GMC_start_poll (); FIXME needed? } else { // GMC_stop_poll(); FIXME needed? } LOG (GNUNET_ERROR_TYPE_DEBUG, "* Return %d\n", data_size); return data_size; } /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Free a transmission that was already queued with all resources * associated to the request. * * @param queue Queue handler to cancel. * @param clear_cls Is it necessary to free associated cls? * @param sent Was it really sent? (Could have been canceled) */ void GMP_queue_destroy (struct MeshPeerQueue *queue, int clear_cls, int sent) { struct MeshPeer *peer; peer = queue->peer; if (GNUNET_YES == clear_cls) { LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy type %s\n", GM_m2s (queue->type)); switch (queue->type) { case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY: LOG (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n"); /* fall through */ case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN: case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE: case GNUNET_MESSAGE_TYPE_MESH_KX: case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED: case GNUNET_MESSAGE_TYPE_MESH_ACK: case GNUNET_MESSAGE_TYPE_MESH_POLL: GNUNET_free_non_null (queue->cls); break; default: GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n", GM_m2s (queue->type)); } } GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue); if (queue->type != GNUNET_MESSAGE_TYPE_MESH_ACK && queue->type != GNUNET_MESSAGE_TYPE_MESH_POLL) { peer->queue_n--; } if (NULL != queue->callback) { LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n"); queue->callback (queue->callback_cls, queue->c, sent, queue->type, queue->fwd, queue->size, GNUNET_TIME_absolute_get_duration (queue->start_waiting)); } if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit) { GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); peer->core_transmit = NULL; } GNUNET_free (queue); } /** * @brief Queue and pass message to core when possible. * * @param peer Peer towards which to queue the message. * @param cls Closure (@c type dependant). It will be used by queue_send to * build the message to be sent if not already prebuilt. * @param type Type of the message, 0 for a raw message. * @param size Size of the message. * @param c Connection this message belongs to (can be NULL). * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!) * @param cont Continuation to be called once CORE has taken the message. * @param cont_cls Closure for @c cont. * * @return Handle to cancel the message before it is sent. Once cont is called * message has been sent and therefore the handle is no longer valid. */ struct MeshPeerQueue * GMP_queue_add (struct MeshPeer *peer, void *cls, uint16_t type, size_t size, struct MeshConnection *c, int fwd, GMP_sent cont, void *cont_cls) { struct MeshPeerQueue *queue; int priority; int call_core; LOG (GNUNET_ERROR_TYPE_INFO, "qq %s on connection %s (%p) %s towards %s (size %u)\n", GM_m2s (type), GMC_2s (c), c, GM_f2s (fwd), GMP_2s(peer), size); if (NULL == peer->connections) { /* We are not connected to this peer, ignore request. */ LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING %s not a neighbor\n", GMP_2s (peer)); GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1, GNUNET_NO); return NULL; } priority = 0; if (GNUNET_MESSAGE_TYPE_MESH_POLL == type || GNUNET_MESSAGE_TYPE_MESH_ACK == type) { priority = 100; } LOG (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority); call_core = NULL == c ? GNUNET_YES : GMC_is_sendable (c, fwd); queue = GNUNET_new (struct MeshPeerQueue); queue->cls = cls; queue->type = type; queue->size = size; queue->peer = peer; queue->c = c; queue->fwd = fwd; queue->callback = cont; queue->callback_cls = cont_cls; if (100 > priority) { GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, queue); peer->queue_n++; } else { GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue); call_core = GNUNET_YES; } if (NULL == peer->core_transmit && GNUNET_YES == call_core) { LOG (GNUNET_ERROR_TYPE_DEBUG, "calling core tmt rdy towards %s for %u bytes\n", GMP_2s (peer), size); peer->core_transmit = GNUNET_CORE_notify_transmit_ready (core_handle, GNUNET_NO, get_priority (queue), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_PEER_resolve2 (peer->id), size, &queue_send, peer); queue->start_waiting = GNUNET_TIME_absolute_get (); } else if (GNUNET_NO == call_core) { LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s not needed\n", GMP_2s (peer)); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s already called\n", GMP_2s (peer)); } return queue; } /** * Cancel all queued messages to a peer that belong to a certain connection. * * @param peer Peer towards whom to cancel. * @param c Connection whose queued messages to cancel. Might be destroyed by * the sent continuation call. */ void GMP_queue_cancel (struct MeshPeer *peer, struct MeshConnection *c) { struct MeshPeerQueue *q; struct MeshPeerQueue *next; struct MeshPeerQueue *prev; for (q = peer->queue_head; NULL != q; q = next) { prev = q->prev; if (q->c == c) { LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP_cancel_queue %s\n", GM_m2s (q->type)); GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO); /* Get next from prev, q->next might be already freed: * queue destroy -> callback -> GMC_destroy -> cancel_queues -> here */ if (NULL == prev) next = peer->queue_head; else next = prev->next; } else { next = q->next; } } if (NULL == peer->queue_head) { if (NULL != peer->core_transmit) { GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); peer->core_transmit = NULL; } } } /** * Get the first transmittable message for a connection. * * @param peer Neighboring peer. * @param c Connection. * * @return First transmittable message. */ static struct MeshPeerQueue * connection_get_first_message (struct MeshPeer *peer, struct MeshConnection *c) { struct MeshPeerQueue *q; for (q = peer->queue_head; NULL != q; q = q->next) { if (q->c != c) continue; if (queue_is_sendable (q)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable!!\n"); return q; } LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n"); } return NULL; } /** * Get the first message for a connection and unqueue it. * * @param peer Neighboring peer. * @param c Connection. * * @return First message for this connection. */ struct GNUNET_MessageHeader * GMP_connection_pop (struct MeshPeer *peer, struct MeshConnection *c) { struct MeshPeerQueue *q; struct MeshPeerQueue *next; struct GNUNET_MessageHeader *msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on %s\n", GMC_2s (c)); for (q = peer->queue_head; NULL != q; q = next) { next = q->next; if (q->c != c) continue; switch (q->type) { case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN: case GNUNET_MESSAGE_TYPE_MESH_ACK: case GNUNET_MESSAGE_TYPE_MESH_POLL: GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO); continue; case GNUNET_MESSAGE_TYPE_MESH_KX: case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED: msg = (struct GNUNET_MessageHeader *) q->cls; GMP_queue_destroy (q, GNUNET_NO, GNUNET_NO); return msg; default: GNUNET_break (0); } } return NULL; } void GMP_queue_unlock (struct MeshPeer *peer, struct MeshConnection *c) { struct MeshPeerQueue *q; size_t size; if (NULL != peer->core_transmit) { LOG (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n"); return; /* Already unlocked */ } q = connection_get_first_message (peer, c); if (NULL == q) { LOG (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n"); return; /* Nothing to transmit */ } size = q->size; peer->core_transmit = GNUNET_CORE_notify_transmit_ready (core_handle, GNUNET_NO, get_priority (q), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_PEER_resolve2 (peer->id), size, &queue_send, peer); } /** * Initialize the peer subsystem. * * @param c Configuration. */ void GMP_init (const struct GNUNET_CONFIGURATION_Handle *c) { LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS", &max_peers)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "MESH", "MAX_PEERS", "USING DEFAULT"); max_peers = 1000; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DROP_PERCENT", &drop_percent)) { drop_percent = 0; } else { LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); LOG (GNUNET_ERROR_TYPE_WARNING, "Mesh is running with DROP enabled.\n"); LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n"); LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n"); LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); } core_handle = GNUNET_CORE_connect (c, /* Main configuration */ NULL, /* Closure passed to MESH functions */ &core_init, /* Call core_init once connected */ &core_connect, /* Handle connects */ &core_disconnect, /* remove peers on disconnects */ NULL, /* Don't notify about all incoming messages */ GNUNET_NO, /* For header only in notification */ NULL, /* Don't notify about all outbound messages */ GNUNET_NO, /* For header-only out notification */ core_handlers); /* Register these handlers */ if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (c, "MESH", "DISABLE_TRY_CONNECT")) { transport_handle = GNUNET_TRANSPORT_connect (c, &my_full_id, NULL, /* cls */ /* Notify callbacks */ NULL, NULL, NULL); } else { LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); LOG (GNUNET_ERROR_TYPE_WARNING, "* DISABLE TRYING CONNECT in config *\n"); LOG (GNUNET_ERROR_TYPE_WARNING, "* Use this only for test purposes. *\n"); LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); } if (NULL == core_handle) { GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } } /** * Shut down the peer subsystem. */ void GMP_shutdown (void) { GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL); if (core_handle != NULL) { GNUNET_CORE_disconnect (core_handle); core_handle = NULL; } if (transport_handle != NULL) { GNUNET_TRANSPORT_disconnect (transport_handle); transport_handle = NULL; } GNUNET_PEER_change_rc (myid, -1); } /** * Retrieve the MeshPeer stucture associated with the peer, create one * and insert it in the appropriate structures if the peer is not known yet. * * @param peer_id Full identity of the peer. * * @return Existing or newly created peer structure. */ struct MeshPeer * GMP_get (const struct GNUNET_PeerIdentity *peer_id) { struct MeshPeer *peer; peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id); if (NULL == peer) { peer = GNUNET_new (struct MeshPeer); if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers) { peer_delete_oldest (); } GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); peer->id = GNUNET_PEER_intern (peer_id); } peer->last_contact = GNUNET_TIME_absolute_get(); return peer; } /** * Retrieve the MeshPeer stucture associated with the peer, create one * and insert it in the appropriate structures if the peer is not known yet. * * @param peer Short identity of the peer. * * @return Existing or newly created peer structure. */ struct MeshPeer * GMP_get_short (const GNUNET_PEER_Id peer) { return GMP_get (GNUNET_PEER_resolve2 (peer)); } /** * Try to connect to a peer on transport level. * * @param cls Closure (peer). * @param tc TaskContext. */ static void try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshPeer *peer = cls; if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; GNUNET_TRANSPORT_try_connect (transport_handle, GNUNET_PEER_resolve2 (peer->id), NULL, NULL); } /** * Try to establish a new connection to this peer (in its tunnel). * If the peer doesn't have any path to it yet, try to get one. * If the peer already has some path, send a CREATE CONNECTION towards it. * * @param peer Peer to connect to. */ void GMP_connect (struct MeshPeer *peer) { struct MeshTunnel3 *t; struct MeshPeerPath *p; struct MeshConnection *c; int rerun_search; LOG (GNUNET_ERROR_TYPE_DEBUG, "peer_connect towards %s\n", GMP_2s (peer)); /* If we have a current hello, try to connect using it. */ GMP_try_connect (peer); t = peer->tunnel; c = NULL; rerun_search = GNUNET_NO; if (NULL != peer->path_head) { LOG (GNUNET_ERROR_TYPE_DEBUG, " some path exists\n"); p = peer_get_best_path (peer); if (NULL != p) { char *s; s = path_2s (p); LOG (GNUNET_ERROR_TYPE_DEBUG, " path to use: %s\n", s); GNUNET_free (s); c = GMT_use_path (t, p); if (NULL == c) { /* This case can happen when the path includes a first hop that is * not yet known to be connected. * * This happens quite often during testing when running mesh * under valgrind: core connect notifications come very late and the * DHT result has already come and created a valid path. * In this case, the peer->connections hashmap will be NULL and * tunnel_use_path will not be able to create a connection from that * path. * * Re-running the DHT GET should give core time to callback. * * GMT_use_path -> GMC_new -> register_neighbors takes care of * updating statistics about this issue. */ rerun_search = GNUNET_YES; } else { GMC_send_create (c); return; } } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " but is NULL, all paths are in use\n"); } } if (NULL != peer->search_h && GNUNET_YES == rerun_search) { GMD_search_stop (peer->search_h); peer->search_h = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, " Stopping DHT GET for peer %s\n", GMP_2s (peer)); } if (NULL == peer->search_h) { const struct GNUNET_PeerIdentity *id; id = GNUNET_PEER_resolve2 (peer->id); LOG (GNUNET_ERROR_TYPE_DEBUG, " Starting DHT GET for peer %s\n", GMP_2s (peer)); peer->search_h = GMD_search (id, &search_handler, peer); if (MESH_TUNNEL3_NEW == GMT_get_cstate (t)) GMT_change_cstate (t, MESH_TUNNEL3_SEARCHING); } } /** * Chech whether there is a direct (core level) connection to peer. * * @param peer Peer to check. * * @return #GNUNET_YES if there is a direct connection. */ int GMP_is_neighbor (const struct MeshPeer *peer) { struct MeshPeerPath *path; if (NULL == peer->connections) return GNUNET_NO; for (path = peer->path_head; NULL != path; path = path->next) { if (3 > path->length) return GNUNET_YES; } /* Is not a neighbor but connections is not NULL, probably disconnecting */ return GNUNET_NO; } /** * Create and initialize a new tunnel towards a peer, in case it has none. * In case the peer already has a tunnel, nothing is done. * * Does not generate any traffic, just creates the local data structures. * * @param peer Peer towards which to create the tunnel. */ void GMP_add_tunnel (struct MeshPeer *peer) { if (NULL != peer->tunnel) return; peer->tunnel = GMT_new (peer); } /** * Add a connection to a neighboring peer. * * Store that the peer is the first hop of the connection in one * direction and that on peer disconnect the connection must be * notified and destroyed, for it will no longer be valid. * * @param peer Peer to add connection to. * @param c Connection to add. * * @return GNUNET_OK on success. */ int GMP_add_connection (struct MeshPeer *peer, struct MeshConnection *c) { int result; LOG (GNUNET_ERROR_TYPE_DEBUG, "adding connection %s\n", GMC_2s (c)); LOG (GNUNET_ERROR_TYPE_DEBUG, "to peer %s\n", GMP_2s (peer)); if (NULL == peer->connections) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %s is not a neighbor!\n", GMP_2s (peer)); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "peer %s ok, has %u connections.\n", GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections)); result = GNUNET_CONTAINER_multihashmap_put (peer->connections, GMC_get_h (c), c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); LOG (GNUNET_ERROR_TYPE_DEBUG, " now has %u connections.\n", GNUNET_CONTAINER_multihashmap_size (peer->connections)); LOG (GNUNET_ERROR_TYPE_DEBUG, "result %u\n", result); return result; } /** * Add the path to the peer and update the path used to reach it in case this * is the shortest. * * @param peer Destination peer to add the path to. * @param path New path to add. Last peer must be the peer in arg 1. * Path will be either used of freed if already known. * @param trusted Do we trust that this path is real? * * @return path if path was taken, pointer to existing duplicate if exists * NULL on error. */ struct MeshPeerPath * GMP_add_path (struct MeshPeer *peer, struct MeshPeerPath *path, int trusted) { struct MeshPeerPath *aux; unsigned int l; unsigned int l2; LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n", path->length, GMP_2s (peer)); if ((NULL == peer) || (NULL == path)) { GNUNET_break (0); path_destroy (path); return NULL; } if (path->peers[path->length - 1] != peer->id) { GNUNET_break (0); path_destroy (path); return NULL; } for (l = 1; l < path->length; l++) { if (path->peers[l] == myid) { LOG (GNUNET_ERROR_TYPE_DEBUG, " shortening path by %u\n", l); for (l2 = 0; l2 < path->length - l; l2++) { path->peers[l2] = path->peers[l + l2]; } path->length -= l; l = 1; path->peers = GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id)); } } LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length); if (2 >= path->length && GNUNET_NO == trusted) { /* Only allow CORE to tell us about direct paths */ path_destroy (path); return NULL; } l = path_get_length (path); if (0 == l) { path_destroy (path); return NULL; } GNUNET_assert (peer->id == path->peers[path->length - 1]); for (aux = peer->path_head; aux != NULL; aux = aux->next) { l2 = path_get_length (aux); if (l2 > l) { LOG (GNUNET_ERROR_TYPE_DEBUG, " added\n"); GNUNET_CONTAINER_DLL_insert_before (peer->path_head, peer->path_tail, aux, path); if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel)) { GMP_connect (peer); } return path; } else { if (l2 == l && memcmp (path->peers, aux->peers, l) == 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, " already known\n"); path_destroy (path); return aux; } } } GNUNET_CONTAINER_DLL_insert_tail (peer->path_head, peer->path_tail, path); LOG (GNUNET_ERROR_TYPE_DEBUG, " added last\n"); if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel)) { GMP_connect (peer); } return path; } /** * Add the path to the origin peer and update the path used to reach it in case * this is the shortest. * The path is given in peer_info -> destination, therefore we turn the path * upside down first. * * @param peer Peer to add the path to, being the origin of the path. * @param path New path to add after being inversed. * Path will be either used or freed. * @param trusted Do we trust that this path is real? * * @return path if path was taken, pointer to existing duplicate if exists * NULL on error. */ struct MeshPeerPath * GMP_add_path_to_origin (struct MeshPeer *peer, struct MeshPeerPath *path, int trusted) { if (NULL == path) return NULL; path_invert (path); return GMP_add_path (peer, path, trusted); } /** * Adds a path to the info of all the peers in the path * * @param p Path to process. * @param confirmed Whether we know if the path works or not. */ void GMP_add_path_to_all (const struct MeshPeerPath *p, int confirmed) { unsigned int i; /* TODO: invert and add */ for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ; for (i++; i < p->length; i++) { struct MeshPeer *aux; struct MeshPeerPath *copy; aux = GMP_get_short (p->peers[i]); copy = path_duplicate (p); copy->length = i + 1; GMP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed); } } /** * Remove any path to the peer that has the extact same peers as the one given. * * @param peer Peer to remove the path from. * @param path Path to remove. Is always destroyed . */ void GMP_remove_path (struct MeshPeer *peer, struct MeshPeerPath *path) { struct MeshPeerPath *iter; struct MeshPeerPath *next; GNUNET_assert (myid == path->peers[0]); GNUNET_assert (peer->id == path->peers[path->length - 1]); for (iter = peer->path_head; NULL != iter; iter = next) { next = iter->next; if (0 == memcmp (path->peers, iter->peers, sizeof (GNUNET_PEER_Id) * path->length)) { GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter); if (iter != path) path_destroy (iter); } } path_destroy (path); } /** * Remove a connection from a neighboring peer. * * @param peer Peer to remove connection from. * @param c Connection to remove. * * @return GNUNET_OK on success. */ int GMP_remove_connection (struct MeshPeer *peer, const struct MeshConnection *c) { LOG (GNUNET_ERROR_TYPE_DEBUG, "removing connection %s\n", GMC_2s (c)); LOG (GNUNET_ERROR_TYPE_DEBUG, "from peer %s\n", GMP_2s (peer)); if (NULL == peer || NULL == peer->connections) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %s is not a neighbor!\n", GMP_2s (peer)); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "peer %s ok, has %u connections.\n", GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections)); return GNUNET_CONTAINER_multihashmap_remove (peer->connections, GMC_get_h (c), c); } /** * Start the DHT search for new paths towards the peer: we don't have * enough good connections. * * @param peer Destination peer. */ void GMP_start_search (struct MeshPeer *peer) { if (NULL != peer->search_h) { GNUNET_break (0); return; } peer->search_h = GMD_search (GMP_get_id (peer), &search_handler, peer); } /** * Stop the DHT search for new paths towards the peer: we already have * enough good connections. * * @param peer Destination peer. */ void GMP_stop_search (struct MeshPeer *peer) { if (NULL == peer->search_h) { return; } GMD_search_stop (peer->search_h); peer->search_h = NULL; } /** * Get the Full ID of a peer. * * @param peer Peer to get from. * * @return Full ID of peer. */ const struct GNUNET_PeerIdentity * GMP_get_id (const struct MeshPeer *peer) { return GNUNET_PEER_resolve2 (peer->id); } /** * Get the Short ID of a peer. * * @param peer Peer to get from. * * @return Short ID of peer. */ GNUNET_PEER_Id GMP_get_short_id (const struct MeshPeer *peer) { return peer->id; } /** * Set tunnel. * * @param peer Peer. * @param t Tunnel. */ void GMP_set_tunnel (struct MeshPeer *peer, struct MeshTunnel3 *t) { peer->tunnel = t; if (NULL == t && NULL != peer->search_h) { GMP_stop_search (peer); } } /** * Get the tunnel towards a peer. * * @param peer Peer to get from. * * @return Tunnel towards peer. */ struct MeshTunnel3 * GMP_get_tunnel (const struct MeshPeer *peer) { return peer->tunnel; } /** * Set the hello message. * * @param peer Peer whose message to set. * @param hello Hello message. */ void GMP_set_hello (struct MeshPeer *peer, const struct GNUNET_HELLO_Message *hello) { struct GNUNET_HELLO_Message *old; size_t size; LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GMP_2s (peer)); if (NULL == hello) return; old = GMP_get_hello (peer); if (NULL == old) { size = GNUNET_HELLO_size (hello); LOG (GNUNET_ERROR_TYPE_DEBUG, " new (%u bytes)\n", size); peer->hello = GNUNET_malloc (size); memcpy (peer->hello, hello, size); } else { peer->hello = GNUNET_HELLO_merge (old, hello); LOG (GNUNET_ERROR_TYPE_DEBUG, " merge into %p (%u bytes)\n", peer->hello, GNUNET_HELLO_size (hello)); GNUNET_free (old); } } /** * Get the hello message. * * @param peer Peer whose message to get. * * @return Hello message. */ struct GNUNET_HELLO_Message * GMP_get_hello (struct MeshPeer *peer) { struct GNUNET_TIME_Absolute expiration; struct GNUNET_TIME_Relative remaining; if (NULL == peer->hello) return NULL; expiration = GNUNET_HELLO_get_last_expiration (peer->hello); remaining = GNUNET_TIME_absolute_get_remaining (expiration); if (0 == remaining.rel_value_us) { LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n", GNUNET_STRINGS_absolute_time_to_string (expiration)); GNUNET_free (peer->hello); peer->hello = NULL; } return peer->hello; } /** * Try to connect to a peer on TRANSPORT level. * * @param peer Peer to whom to connect. */ void GMP_try_connect (struct MeshPeer *peer) { struct GNUNET_HELLO_Message *hello; struct GNUNET_MessageHeader *mh; if (NULL == transport_handle) return; hello = GMP_get_hello (peer); if (NULL == hello) return; mh = GNUNET_HELLO_get_header (hello); GNUNET_TRANSPORT_offer_hello (transport_handle, mh, try_connect, peer); } /** * Notify a peer that a link between two other peers is broken. If any path * used that link, eliminate it. * * @param peer Peer affected by the change. * @param peer1 Peer whose link is broken. * @param peer2 Peer whose link is broken. */ void GMP_notify_broken_link (struct MeshPeer *peer, struct GNUNET_PeerIdentity *peer1, struct GNUNET_PeerIdentity *peer2) { struct MeshPeerPath *iter; struct MeshPeerPath *next; unsigned int i; GNUNET_PEER_Id p1; GNUNET_PEER_Id p2; p1 = GNUNET_PEER_search (peer1); p2 = GNUNET_PEER_search (peer2); LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2); if (0 == p1 || 0 == p2) { /* We don't even know them */ return; } for (iter = peer->path_head; NULL != iter; iter = next) { next = iter->next; for (i = 0; i < iter->length - 1; i++) { if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2) || (iter->peers[i] == p2 && iter->peers[i + 1] == p1)) { char *s; s = path_2s (iter); LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s); GNUNET_free (s); path_invalidate (iter); } } } } /** * Count the number of known paths toward the peer. * * @param peer Peer to get path info. * * @return Number of known paths. */ unsigned int GMP_count_paths (const struct MeshPeer *peer) { struct MeshPeerPath *iter; unsigned int i; for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) i++; return i; } /** * Iterate all known peers. * * @param iter Iterator. * @param cls Closure for @c iter. */ void GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls) { GNUNET_CONTAINER_multipeermap_iterate (peers, iter, cls); } /** * Get the static string for a peer ID. * * @param peer Peer. * * @return Static string for it's ID. */ const char * GMP_2s (const struct MeshPeer *peer) { if (NULL == peer) return "(NULL)"; return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id)); } gnunet-0.10.1/src/mesh/mesh_common.c0000644000175000017500000001620412320526362014211 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/mesh_common.c * @brief MESH helper functions * @author Bartlomiej Polot */ #include "mesh.h" /** * @brief Translate a fwd variable into a string representation, for logging. * * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO) * * @return String representing FWD or BCK. */ char * GM_f2s (int fwd) { if (GNUNET_YES == fwd) { return "FWD"; } else if (GNUNET_NO == fwd) { return "BCK"; } else { /* Not an error, can happen with CONNECTION_BROKEN messages. */ return ""; } } int GM_is_pid_bigger (uint32_t bigger, uint32_t smaller) { return (GNUNET_YES == PID_OVERFLOW (smaller, bigger) || (bigger > smaller && GNUNET_NO == PID_OVERFLOW (bigger, smaller))); } uint32_t GM_max_pid (uint32_t a, uint32_t b) { if (GM_is_pid_bigger(a, b)) return a; return b; } uint32_t GM_min_pid (uint32_t a, uint32_t b) { if (GM_is_pid_bigger(a, b)) return b; return a; } const struct GNUNET_HashCode * GM_h2hc (const struct GNUNET_MESH_Hash *id) { static struct GNUNET_HashCode hc; memcpy (&hc, id, sizeof (*id)); return &hc; } const char * GM_h2s (const struct GNUNET_MESH_Hash *id) { static char s[53]; memcpy (s, GNUNET_h2s_full (GM_h2hc (id)), 52); s[52] = '\0'; return s; } #if !defined(GNUNET_CULL_LOGGING) const char * GM_m2s (uint16_t m) { static char buf[32]; const char *t; switch (m) { /** * Request the creation of a path */ case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE: t = "CONNECTION_CREATE"; break; /** * Request the modification of an existing path */ case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK: t = "CONNECTION_ACK"; break; /** * Notify that a connection of a path is no longer valid */ case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN: t = "CONNECTION_BROKEN"; break; /** * At some point, the route will spontaneously change */ case GNUNET_MESSAGE_TYPE_MESH_PATH_CHANGED: t = "PATH_CHANGED"; break; /** * Transport payload data. */ case GNUNET_MESSAGE_TYPE_MESH_DATA: t = "DATA"; break; /** * Confirm receipt of payload data. */ case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK: t = "DATA_ACK"; break; /** * Key exchange encapsulation. */ case GNUNET_MESSAGE_TYPE_MESH_KX: t = "KX"; break; /** * New ephemeral key. */ case GNUNET_MESSAGE_TYPE_MESH_KX_EPHEMERAL: t = "KX_EPHEMERAL"; break; /** * Challenge to test peer's session key. */ case GNUNET_MESSAGE_TYPE_MESH_KX_PING: t = "KX_PING"; break; /** * Answer to session key challenge. */ case GNUNET_MESSAGE_TYPE_MESH_KX_PONG: t = "KX_PONG"; break; /** * Request the destuction of a path */ case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY: t = "CONNECTION_DESTROY"; break; /** * ACK for a data packet. */ case GNUNET_MESSAGE_TYPE_MESH_ACK: t = "ACK"; break; /** * POLL for ACK. */ case GNUNET_MESSAGE_TYPE_MESH_POLL: t = "POLL"; break; /** * Announce origin is still alive. */ case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE: t = "KEEPALIVE"; break; /** * Connect to the mesh service, specifying subscriptions */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT: t = "LOCAL_CONNECT"; break; /** * Ask the mesh service to create a new tunnel */ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: t = "CHANNEL_CREATE"; break; /** * Ask the mesh service to destroy a tunnel */ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: t = "CHANNEL_DESTROY"; break; /** * Confirm the creation of a channel. */ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK: t = "CHANNEL_ACK"; break; /** * Confirm the creation of a channel. */ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK: t = "CHANNEL_NACK"; break; /** * Encrypted payload. */ case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED: t = "ENCRYPTED"; break; /** * Local payload traffic */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA: t = "LOCAL_DATA"; break; /** * Local ACK for data. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: t = "LOCAL_ACK"; break; /** * Local monitoring of channels. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNELS: t = "LOCAL_INFO_CHANNELS"; break; /** * Local monitoring of a channel. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL: t = "LOCAL_INFO_CHANNEL"; break; /** * Local monitoring of service. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS: t = "LOCAL_INFO_TUNNELS"; break; /** * Local monitoring of service. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL: t = "LOCAL_INFO_TUNNEL"; break; /** * Local information about all connections of service. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CONNECTIONS: t = "LOCAL_INFO_CONNECTIONS"; break; /** * Local information of service about a specific connection. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CONNECTION: t = "LOCAL_INFO_CONNECTION"; break; /** * Local information about all peers known to the service. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS: t = "LOCAL_INFO_PEERS"; break; /** * Local information of service about a specific peer. */ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEER: t = "LOCAL_INFO_PEER"; break; /** * Traffic (net-cat style) used by the Command Line Interface. */ case GNUNET_MESSAGE_TYPE_MESH_CLI: t = "CLI"; break; /** * 640kb should be enough for everybody */ case 299: t = "RESERVE_END"; break; default: sprintf(buf, "%u (UNKNOWN TYPE)", m); return buf; } sprintf(buf, "{%22s}", t); return buf; } #else const char * GM_m2s (uint16_t m) { return ""; } #endif gnunet-0.10.1/src/mesh/Makefile.in0000644000175000017500000024642012320755225013615 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-mesh$(EXEEXT) bin_PROGRAMS = gnunet-mesh$(EXEEXT) @HAVE_TESTING_TRUE@noinst_PROGRAMS = gnunet-mesh-profiler$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = test_mesh_single$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_local$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_small_forward$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_small_signal$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_small_keepalive$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_small_speed$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_small_speed_ack$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_small_speed_backwards$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_small_speed_reliable$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_mesh_small_speed_reliable_backwards$(EXEEXT) subdir = src/mesh DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/mesh.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = mesh.conf CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = libgnunetmeshtest_a_AR = $(AR) $(ARFLAGS) am_libgnunetmeshtest_a_OBJECTS = mesh_test_lib.$(OBJEXT) libgnunetmeshtest_a_OBJECTS = $(am_libgnunetmeshtest_a_OBJECTS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetmesh_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetmesh_la_OBJECTS = mesh_api.lo mesh_common.lo libgnunetmesh_la_OBJECTS = $(am_libgnunetmesh_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetmesh_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetmesh_la_LDFLAGS) $(LDFLAGS) \ -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_mesh_OBJECTS = gnunet-mesh.$(OBJEXT) gnunet_mesh_OBJECTS = $(am_gnunet_mesh_OBJECTS) am_gnunet_mesh_profiler_OBJECTS = gnunet-mesh-profiler.$(OBJEXT) gnunet_mesh_profiler_OBJECTS = $(am_gnunet_mesh_profiler_OBJECTS) am_gnunet_service_mesh_OBJECTS = \ gnunet_service_mesh-gnunet-service-mesh_tunnel.$(OBJEXT) \ gnunet_service_mesh-gnunet-service-mesh_connection.$(OBJEXT) \ gnunet_service_mesh-gnunet-service-mesh_channel.$(OBJEXT) \ gnunet_service_mesh-gnunet-service-mesh_local.$(OBJEXT) \ gnunet_service_mesh-gnunet-service-mesh_peer.$(OBJEXT) \ gnunet_service_mesh-gnunet-service-mesh_dht.$(OBJEXT) \ gnunet_service_mesh-gnunet-service-mesh_hello.$(OBJEXT) \ gnunet_service_mesh-mesh_path.$(OBJEXT) \ gnunet_service_mesh-mesh_common.$(OBJEXT) \ gnunet_service_mesh-gnunet-service-mesh.$(OBJEXT) gnunet_service_mesh_OBJECTS = $(am_gnunet_service_mesh_OBJECTS) gnunet_service_mesh_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(gnunet_service_mesh_CFLAGS) $(CFLAGS) \ $(gnunet_service_mesh_LDFLAGS) $(LDFLAGS) -o $@ am_test_mesh_local_OBJECTS = test_mesh_local.$(OBJEXT) test_mesh_local_OBJECTS = $(am_test_mesh_local_OBJECTS) am_test_mesh_single_OBJECTS = test_mesh_single.$(OBJEXT) test_mesh_single_OBJECTS = $(am_test_mesh_single_OBJECTS) am_test_mesh_small_forward_OBJECTS = test_mesh_small.$(OBJEXT) test_mesh_small_forward_OBJECTS = \ $(am_test_mesh_small_forward_OBJECTS) am_test_mesh_small_keepalive_OBJECTS = test_mesh_small.$(OBJEXT) test_mesh_small_keepalive_OBJECTS = \ $(am_test_mesh_small_keepalive_OBJECTS) am_test_mesh_small_signal_OBJECTS = test_mesh_small.$(OBJEXT) test_mesh_small_signal_OBJECTS = $(am_test_mesh_small_signal_OBJECTS) am_test_mesh_small_speed_OBJECTS = test_mesh_small.$(OBJEXT) test_mesh_small_speed_OBJECTS = $(am_test_mesh_small_speed_OBJECTS) am_test_mesh_small_speed_ack_OBJECTS = test_mesh_small.$(OBJEXT) test_mesh_small_speed_ack_OBJECTS = \ $(am_test_mesh_small_speed_ack_OBJECTS) am_test_mesh_small_speed_backwards_OBJECTS = \ test_mesh_small.$(OBJEXT) test_mesh_small_speed_backwards_OBJECTS = \ $(am_test_mesh_small_speed_backwards_OBJECTS) am_test_mesh_small_speed_reliable_OBJECTS = test_mesh_small.$(OBJEXT) test_mesh_small_speed_reliable_OBJECTS = \ $(am_test_mesh_small_speed_reliable_OBJECTS) am_test_mesh_small_speed_reliable_backwards_OBJECTS = \ test_mesh_small.$(OBJEXT) test_mesh_small_speed_reliable_backwards_OBJECTS = \ $(am_test_mesh_small_speed_reliable_backwards_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetmeshtest_a_SOURCES) $(libgnunetmesh_la_SOURCES) \ $(gnunet_mesh_SOURCES) $(gnunet_mesh_profiler_SOURCES) \ $(gnunet_service_mesh_SOURCES) $(test_mesh_local_SOURCES) \ $(test_mesh_single_SOURCES) $(test_mesh_small_forward_SOURCES) \ $(test_mesh_small_keepalive_SOURCES) \ $(test_mesh_small_signal_SOURCES) \ $(test_mesh_small_speed_SOURCES) \ $(test_mesh_small_speed_ack_SOURCES) \ $(test_mesh_small_speed_backwards_SOURCES) \ $(test_mesh_small_speed_reliable_SOURCES) \ $(test_mesh_small_speed_reliable_backwards_SOURCES) DIST_SOURCES = $(libgnunetmeshtest_a_SOURCES) \ $(libgnunetmesh_la_SOURCES) $(gnunet_mesh_SOURCES) \ $(gnunet_mesh_profiler_SOURCES) $(gnunet_service_mesh_SOURCES) \ $(test_mesh_local_SOURCES) $(test_mesh_single_SOURCES) \ $(test_mesh_small_forward_SOURCES) \ $(test_mesh_small_keepalive_SOURCES) \ $(test_mesh_small_signal_SOURCES) \ $(test_mesh_small_speed_SOURCES) \ $(test_mesh_small_speed_ack_SOURCES) \ $(test_mesh_small_speed_backwards_SOURCES) \ $(test_mesh_small_speed_reliable_SOURCES) \ $(test_mesh_small_speed_reliable_backwards_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ mesh.conf plugindir = $(libdir)/gnunet AM_CLFAGS = -g lib_LTLIBRARIES = \ libgnunetmesh.la $(EXP_LIB) libgnunetmesh_la_SOURCES = \ mesh_api.c mesh_common.c libgnunetmesh_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) \ $(LTLIBINTL) libgnunetmesh_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 5:0:0 gnunet_mesh_SOURCES = \ gnunet-mesh.c gnunet_mesh_LDADD = \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_mesh_DEPENDENCIES = \ libgnunetmesh.la gnunet_service_mesh_SOURCES = \ gnunet-service-mesh_tunnel.c gnunet-service-mesh_tunnel.h \ gnunet-service-mesh_connection.c gnunet-service-mesh_connection.h \ gnunet-service-mesh_channel.c gnunet-service-mesh_channel.h \ gnunet-service-mesh_local.c gnunet-service-mesh_local.h \ gnunet-service-mesh_peer.c gnunet-service-mesh_peer.h \ gnunet-service-mesh_dht.c gnunet-service-mesh_dht.h \ gnunet-service-mesh_hello.c gnunet-service-mesh_hello.h \ mesh_path.c mesh_path.h \ mesh_common.c \ gnunet-service-mesh.c gnunet_service_mesh_CFLAGS = $(AM_CFLAGS) gnunet_service_mesh_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la gnunet_service_mesh_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la @LINUX_TRUE@gnunet_service_mesh_LDFLAGS = -lrt @HAVE_TESTING_TRUE@noinst_LIBRARIES = libgnunetmeshtest.a $(noinst_LIB_EXP) libgnunetmeshtest_a_SOURCES = \ mesh_test_lib.c mesh_test_lib.h libgnunetmeshtest_a_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/mesh/libgnunetmesh.la libgnunetmeshtest_a_DEPENDENCIES = \ libgnunetmesh.la ld_mesh_test_lib = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/mesh/libgnunetmeshtest.a \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la dep_mesh_test_lib = \ libgnunetmesh.la \ libgnunetmeshtest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la gnunet_mesh_profiler_SOURCES = \ gnunet-mesh-profiler.c gnunet_mesh_profiler_LDADD = $(ld_mesh_test_lib) gnunet_mesh_profiler_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_single_SOURCES = \ test_mesh_single.c test_mesh_single_LDADD = $(ld_mesh_test_lib) test_mesh_single_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_local_SOURCES = \ test_mesh_local.c test_mesh_local_LDADD = $(ld_mesh_test_lib) test_mesh_local_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_forward_SOURCES = \ test_mesh_small.c test_mesh_small_forward_LDADD = $(ld_mesh_test_lib) test_mesh_small_forward_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_signal_SOURCES = \ test_mesh_small.c test_mesh_small_signal_LDADD = $(ld_mesh_test_lib) test_mesh_small_signal_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_keepalive_SOURCES = \ test_mesh_small.c test_mesh_small_keepalive_LDADD = $(ld_mesh_test_lib) test_mesh_small_keepalive_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_SOURCES = \ test_mesh_small.c test_mesh_small_speed_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_ack_SOURCES = \ test_mesh_small.c test_mesh_small_speed_ack_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_ack_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_backwards_SOURCES = \ test_mesh_small.c test_mesh_small_speed_backwards_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_backwards_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_reliable_SOURCES = \ test_mesh_small.c test_mesh_small_speed_reliable_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_reliable_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_reliable_backwards_SOURCES = \ test_mesh_small.c test_mesh_small_speed_reliable_backwards_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_reliable_backwards_DEPENDENCIES = $(dep_mesh_test_lib) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = \ @ENABLE_TEST_RUN_TRUE@ $(check_PROGRAMS) EXTRA_DIST = \ mesh.h mesh_protocol.h \ test_mesh.conf \ test_mesh_drop.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/mesh/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/mesh/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mesh.conf: $(top_builddir)/config.status $(srcdir)/mesh.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libgnunetmeshtest.a: $(libgnunetmeshtest_a_OBJECTS) $(libgnunetmeshtest_a_DEPENDENCIES) $(EXTRA_libgnunetmeshtest_a_DEPENDENCIES) $(AM_V_at)-rm -f libgnunetmeshtest.a $(AM_V_AR)$(libgnunetmeshtest_a_AR) libgnunetmeshtest.a $(libgnunetmeshtest_a_OBJECTS) $(libgnunetmeshtest_a_LIBADD) $(AM_V_at)$(RANLIB) libgnunetmeshtest.a install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetmesh.la: $(libgnunetmesh_la_OBJECTS) $(libgnunetmesh_la_DEPENDENCIES) $(EXTRA_libgnunetmesh_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetmesh_la_LINK) -rpath $(libdir) $(libgnunetmesh_la_OBJECTS) $(libgnunetmesh_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-mesh$(EXEEXT): $(gnunet_mesh_OBJECTS) $(gnunet_mesh_DEPENDENCIES) $(EXTRA_gnunet_mesh_DEPENDENCIES) @rm -f gnunet-mesh$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_mesh_OBJECTS) $(gnunet_mesh_LDADD) $(LIBS) gnunet-mesh-profiler$(EXEEXT): $(gnunet_mesh_profiler_OBJECTS) $(gnunet_mesh_profiler_DEPENDENCIES) $(EXTRA_gnunet_mesh_profiler_DEPENDENCIES) @rm -f gnunet-mesh-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_mesh_profiler_OBJECTS) $(gnunet_mesh_profiler_LDADD) $(LIBS) gnunet-service-mesh$(EXEEXT): $(gnunet_service_mesh_OBJECTS) $(gnunet_service_mesh_DEPENDENCIES) $(EXTRA_gnunet_service_mesh_DEPENDENCIES) @rm -f gnunet-service-mesh$(EXEEXT) $(AM_V_CCLD)$(gnunet_service_mesh_LINK) $(gnunet_service_mesh_OBJECTS) $(gnunet_service_mesh_LDADD) $(LIBS) test_mesh_local$(EXEEXT): $(test_mesh_local_OBJECTS) $(test_mesh_local_DEPENDENCIES) $(EXTRA_test_mesh_local_DEPENDENCIES) @rm -f test_mesh_local$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_local_OBJECTS) $(test_mesh_local_LDADD) $(LIBS) test_mesh_single$(EXEEXT): $(test_mesh_single_OBJECTS) $(test_mesh_single_DEPENDENCIES) $(EXTRA_test_mesh_single_DEPENDENCIES) @rm -f test_mesh_single$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_single_OBJECTS) $(test_mesh_single_LDADD) $(LIBS) test_mesh_small_forward$(EXEEXT): $(test_mesh_small_forward_OBJECTS) $(test_mesh_small_forward_DEPENDENCIES) $(EXTRA_test_mesh_small_forward_DEPENDENCIES) @rm -f test_mesh_small_forward$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_small_forward_OBJECTS) $(test_mesh_small_forward_LDADD) $(LIBS) test_mesh_small_keepalive$(EXEEXT): $(test_mesh_small_keepalive_OBJECTS) $(test_mesh_small_keepalive_DEPENDENCIES) $(EXTRA_test_mesh_small_keepalive_DEPENDENCIES) @rm -f test_mesh_small_keepalive$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_small_keepalive_OBJECTS) $(test_mesh_small_keepalive_LDADD) $(LIBS) test_mesh_small_signal$(EXEEXT): $(test_mesh_small_signal_OBJECTS) $(test_mesh_small_signal_DEPENDENCIES) $(EXTRA_test_mesh_small_signal_DEPENDENCIES) @rm -f test_mesh_small_signal$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_small_signal_OBJECTS) $(test_mesh_small_signal_LDADD) $(LIBS) test_mesh_small_speed$(EXEEXT): $(test_mesh_small_speed_OBJECTS) $(test_mesh_small_speed_DEPENDENCIES) $(EXTRA_test_mesh_small_speed_DEPENDENCIES) @rm -f test_mesh_small_speed$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_small_speed_OBJECTS) $(test_mesh_small_speed_LDADD) $(LIBS) test_mesh_small_speed_ack$(EXEEXT): $(test_mesh_small_speed_ack_OBJECTS) $(test_mesh_small_speed_ack_DEPENDENCIES) $(EXTRA_test_mesh_small_speed_ack_DEPENDENCIES) @rm -f test_mesh_small_speed_ack$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_small_speed_ack_OBJECTS) $(test_mesh_small_speed_ack_LDADD) $(LIBS) test_mesh_small_speed_backwards$(EXEEXT): $(test_mesh_small_speed_backwards_OBJECTS) $(test_mesh_small_speed_backwards_DEPENDENCIES) $(EXTRA_test_mesh_small_speed_backwards_DEPENDENCIES) @rm -f test_mesh_small_speed_backwards$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_small_speed_backwards_OBJECTS) $(test_mesh_small_speed_backwards_LDADD) $(LIBS) test_mesh_small_speed_reliable$(EXEEXT): $(test_mesh_small_speed_reliable_OBJECTS) $(test_mesh_small_speed_reliable_DEPENDENCIES) $(EXTRA_test_mesh_small_speed_reliable_DEPENDENCIES) @rm -f test_mesh_small_speed_reliable$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_small_speed_reliable_OBJECTS) $(test_mesh_small_speed_reliable_LDADD) $(LIBS) test_mesh_small_speed_reliable_backwards$(EXEEXT): $(test_mesh_small_speed_reliable_backwards_OBJECTS) $(test_mesh_small_speed_reliable_backwards_DEPENDENCIES) $(EXTRA_test_mesh_small_speed_reliable_backwards_DEPENDENCIES) @rm -f test_mesh_small_speed_reliable_backwards$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_mesh_small_speed_reliable_backwards_OBJECTS) $(test_mesh_small_speed_reliable_backwards_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-mesh-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-mesh.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_channel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_connection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_dht.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_hello.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_local.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_peer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_tunnel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-mesh_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_mesh-mesh_path.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mesh_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mesh_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mesh_test_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mesh_local.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mesh_single.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_mesh_small.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< gnunet_service_mesh-gnunet-service-mesh_tunnel.o: gnunet-service-mesh_tunnel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_tunnel.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_tunnel.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_tunnel.o `test -f 'gnunet-service-mesh_tunnel.c' || echo '$(srcdir)/'`gnunet-service-mesh_tunnel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_tunnel.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_tunnel.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_tunnel.c' object='gnunet_service_mesh-gnunet-service-mesh_tunnel.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_tunnel.o `test -f 'gnunet-service-mesh_tunnel.c' || echo '$(srcdir)/'`gnunet-service-mesh_tunnel.c gnunet_service_mesh-gnunet-service-mesh_tunnel.obj: gnunet-service-mesh_tunnel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_tunnel.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_tunnel.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_tunnel.obj `if test -f 'gnunet-service-mesh_tunnel.c'; then $(CYGPATH_W) 'gnunet-service-mesh_tunnel.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_tunnel.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_tunnel.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_tunnel.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_tunnel.c' object='gnunet_service_mesh-gnunet-service-mesh_tunnel.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_tunnel.obj `if test -f 'gnunet-service-mesh_tunnel.c'; then $(CYGPATH_W) 'gnunet-service-mesh_tunnel.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_tunnel.c'; fi` gnunet_service_mesh-gnunet-service-mesh_connection.o: gnunet-service-mesh_connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_connection.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_connection.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_connection.o `test -f 'gnunet-service-mesh_connection.c' || echo '$(srcdir)/'`gnunet-service-mesh_connection.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_connection.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_connection.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_connection.c' object='gnunet_service_mesh-gnunet-service-mesh_connection.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_connection.o `test -f 'gnunet-service-mesh_connection.c' || echo '$(srcdir)/'`gnunet-service-mesh_connection.c gnunet_service_mesh-gnunet-service-mesh_connection.obj: gnunet-service-mesh_connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_connection.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_connection.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_connection.obj `if test -f 'gnunet-service-mesh_connection.c'; then $(CYGPATH_W) 'gnunet-service-mesh_connection.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_connection.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_connection.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_connection.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_connection.c' object='gnunet_service_mesh-gnunet-service-mesh_connection.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_connection.obj `if test -f 'gnunet-service-mesh_connection.c'; then $(CYGPATH_W) 'gnunet-service-mesh_connection.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_connection.c'; fi` gnunet_service_mesh-gnunet-service-mesh_channel.o: gnunet-service-mesh_channel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_channel.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_channel.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_channel.o `test -f 'gnunet-service-mesh_channel.c' || echo '$(srcdir)/'`gnunet-service-mesh_channel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_channel.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_channel.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_channel.c' object='gnunet_service_mesh-gnunet-service-mesh_channel.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_channel.o `test -f 'gnunet-service-mesh_channel.c' || echo '$(srcdir)/'`gnunet-service-mesh_channel.c gnunet_service_mesh-gnunet-service-mesh_channel.obj: gnunet-service-mesh_channel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_channel.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_channel.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_channel.obj `if test -f 'gnunet-service-mesh_channel.c'; then $(CYGPATH_W) 'gnunet-service-mesh_channel.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_channel.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_channel.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_channel.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_channel.c' object='gnunet_service_mesh-gnunet-service-mesh_channel.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_channel.obj `if test -f 'gnunet-service-mesh_channel.c'; then $(CYGPATH_W) 'gnunet-service-mesh_channel.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_channel.c'; fi` gnunet_service_mesh-gnunet-service-mesh_local.o: gnunet-service-mesh_local.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_local.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_local.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_local.o `test -f 'gnunet-service-mesh_local.c' || echo '$(srcdir)/'`gnunet-service-mesh_local.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_local.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_local.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_local.c' object='gnunet_service_mesh-gnunet-service-mesh_local.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_local.o `test -f 'gnunet-service-mesh_local.c' || echo '$(srcdir)/'`gnunet-service-mesh_local.c gnunet_service_mesh-gnunet-service-mesh_local.obj: gnunet-service-mesh_local.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_local.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_local.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_local.obj `if test -f 'gnunet-service-mesh_local.c'; then $(CYGPATH_W) 'gnunet-service-mesh_local.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_local.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_local.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_local.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_local.c' object='gnunet_service_mesh-gnunet-service-mesh_local.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_local.obj `if test -f 'gnunet-service-mesh_local.c'; then $(CYGPATH_W) 'gnunet-service-mesh_local.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_local.c'; fi` gnunet_service_mesh-gnunet-service-mesh_peer.o: gnunet-service-mesh_peer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_peer.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_peer.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_peer.o `test -f 'gnunet-service-mesh_peer.c' || echo '$(srcdir)/'`gnunet-service-mesh_peer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_peer.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_peer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_peer.c' object='gnunet_service_mesh-gnunet-service-mesh_peer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_peer.o `test -f 'gnunet-service-mesh_peer.c' || echo '$(srcdir)/'`gnunet-service-mesh_peer.c gnunet_service_mesh-gnunet-service-mesh_peer.obj: gnunet-service-mesh_peer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_peer.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_peer.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_peer.obj `if test -f 'gnunet-service-mesh_peer.c'; then $(CYGPATH_W) 'gnunet-service-mesh_peer.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_peer.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_peer.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_peer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_peer.c' object='gnunet_service_mesh-gnunet-service-mesh_peer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_peer.obj `if test -f 'gnunet-service-mesh_peer.c'; then $(CYGPATH_W) 'gnunet-service-mesh_peer.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_peer.c'; fi` gnunet_service_mesh-gnunet-service-mesh_dht.o: gnunet-service-mesh_dht.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_dht.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_dht.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_dht.o `test -f 'gnunet-service-mesh_dht.c' || echo '$(srcdir)/'`gnunet-service-mesh_dht.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_dht.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_dht.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_dht.c' object='gnunet_service_mesh-gnunet-service-mesh_dht.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_dht.o `test -f 'gnunet-service-mesh_dht.c' || echo '$(srcdir)/'`gnunet-service-mesh_dht.c gnunet_service_mesh-gnunet-service-mesh_dht.obj: gnunet-service-mesh_dht.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_dht.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_dht.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_dht.obj `if test -f 'gnunet-service-mesh_dht.c'; then $(CYGPATH_W) 'gnunet-service-mesh_dht.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_dht.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_dht.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_dht.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_dht.c' object='gnunet_service_mesh-gnunet-service-mesh_dht.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_dht.obj `if test -f 'gnunet-service-mesh_dht.c'; then $(CYGPATH_W) 'gnunet-service-mesh_dht.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_dht.c'; fi` gnunet_service_mesh-gnunet-service-mesh_hello.o: gnunet-service-mesh_hello.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_hello.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_hello.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_hello.o `test -f 'gnunet-service-mesh_hello.c' || echo '$(srcdir)/'`gnunet-service-mesh_hello.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_hello.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_hello.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_hello.c' object='gnunet_service_mesh-gnunet-service-mesh_hello.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_hello.o `test -f 'gnunet-service-mesh_hello.c' || echo '$(srcdir)/'`gnunet-service-mesh_hello.c gnunet_service_mesh-gnunet-service-mesh_hello.obj: gnunet-service-mesh_hello.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh_hello.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_hello.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh_hello.obj `if test -f 'gnunet-service-mesh_hello.c'; then $(CYGPATH_W) 'gnunet-service-mesh_hello.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_hello.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_hello.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh_hello.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh_hello.c' object='gnunet_service_mesh-gnunet-service-mesh_hello.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh_hello.obj `if test -f 'gnunet-service-mesh_hello.c'; then $(CYGPATH_W) 'gnunet-service-mesh_hello.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh_hello.c'; fi` gnunet_service_mesh-mesh_path.o: mesh_path.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-mesh_path.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-mesh_path.Tpo -c -o gnunet_service_mesh-mesh_path.o `test -f 'mesh_path.c' || echo '$(srcdir)/'`mesh_path.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-mesh_path.Tpo $(DEPDIR)/gnunet_service_mesh-mesh_path.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mesh_path.c' object='gnunet_service_mesh-mesh_path.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-mesh_path.o `test -f 'mesh_path.c' || echo '$(srcdir)/'`mesh_path.c gnunet_service_mesh-mesh_path.obj: mesh_path.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-mesh_path.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-mesh_path.Tpo -c -o gnunet_service_mesh-mesh_path.obj `if test -f 'mesh_path.c'; then $(CYGPATH_W) 'mesh_path.c'; else $(CYGPATH_W) '$(srcdir)/mesh_path.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-mesh_path.Tpo $(DEPDIR)/gnunet_service_mesh-mesh_path.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mesh_path.c' object='gnunet_service_mesh-mesh_path.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-mesh_path.obj `if test -f 'mesh_path.c'; then $(CYGPATH_W) 'mesh_path.c'; else $(CYGPATH_W) '$(srcdir)/mesh_path.c'; fi` gnunet_service_mesh-mesh_common.o: mesh_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-mesh_common.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-mesh_common.Tpo -c -o gnunet_service_mesh-mesh_common.o `test -f 'mesh_common.c' || echo '$(srcdir)/'`mesh_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-mesh_common.Tpo $(DEPDIR)/gnunet_service_mesh-mesh_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mesh_common.c' object='gnunet_service_mesh-mesh_common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-mesh_common.o `test -f 'mesh_common.c' || echo '$(srcdir)/'`mesh_common.c gnunet_service_mesh-mesh_common.obj: mesh_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-mesh_common.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-mesh_common.Tpo -c -o gnunet_service_mesh-mesh_common.obj `if test -f 'mesh_common.c'; then $(CYGPATH_W) 'mesh_common.c'; else $(CYGPATH_W) '$(srcdir)/mesh_common.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-mesh_common.Tpo $(DEPDIR)/gnunet_service_mesh-mesh_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mesh_common.c' object='gnunet_service_mesh-mesh_common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-mesh_common.obj `if test -f 'mesh_common.c'; then $(CYGPATH_W) 'mesh_common.c'; else $(CYGPATH_W) '$(srcdir)/mesh_common.c'; fi` gnunet_service_mesh-gnunet-service-mesh.o: gnunet-service-mesh.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh.o -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh.o `test -f 'gnunet-service-mesh.c' || echo '$(srcdir)/'`gnunet-service-mesh.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh.c' object='gnunet_service_mesh-gnunet-service-mesh.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh.o `test -f 'gnunet-service-mesh.c' || echo '$(srcdir)/'`gnunet-service-mesh.c gnunet_service_mesh-gnunet-service-mesh.obj: gnunet-service-mesh.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -MT gnunet_service_mesh-gnunet-service-mesh.obj -MD -MP -MF $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh.Tpo -c -o gnunet_service_mesh-gnunet-service-mesh.obj `if test -f 'gnunet-service-mesh.c'; then $(CYGPATH_W) 'gnunet-service-mesh.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh.Tpo $(DEPDIR)/gnunet_service_mesh-gnunet-service-mesh.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-mesh.c' object='gnunet_service_mesh-gnunet-service-mesh.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_mesh_CFLAGS) $(CFLAGS) -c -o gnunet_service_mesh-gnunet-service-mesh.obj `if test -f 'gnunet-service-mesh.c'; then $(CYGPATH_W) 'gnunet-service-mesh.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-mesh.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_mesh_single.log: test_mesh_single$(EXEEXT) @p='test_mesh_single$(EXEEXT)'; \ b='test_mesh_single'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_local.log: test_mesh_local$(EXEEXT) @p='test_mesh_local$(EXEEXT)'; \ b='test_mesh_local'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_small_forward.log: test_mesh_small_forward$(EXEEXT) @p='test_mesh_small_forward$(EXEEXT)'; \ b='test_mesh_small_forward'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_small_signal.log: test_mesh_small_signal$(EXEEXT) @p='test_mesh_small_signal$(EXEEXT)'; \ b='test_mesh_small_signal'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_small_keepalive.log: test_mesh_small_keepalive$(EXEEXT) @p='test_mesh_small_keepalive$(EXEEXT)'; \ b='test_mesh_small_keepalive'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_small_speed.log: test_mesh_small_speed$(EXEEXT) @p='test_mesh_small_speed$(EXEEXT)'; \ b='test_mesh_small_speed'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_small_speed_ack.log: test_mesh_small_speed_ack$(EXEEXT) @p='test_mesh_small_speed_ack$(EXEEXT)'; \ b='test_mesh_small_speed_ack'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_small_speed_backwards.log: test_mesh_small_speed_backwards$(EXEEXT) @p='test_mesh_small_speed_backwards$(EXEEXT)'; \ b='test_mesh_small_speed_backwards'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_small_speed_reliable.log: test_mesh_small_speed_reliable$(EXEEXT) @p='test_mesh_small_speed_reliable$(EXEEXT)'; \ b='test_mesh_small_speed_reliable'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mesh_small_speed_reliable_backwards.log: test_mesh_small_speed_reliable_backwards$(EXEEXT) @p='test_mesh_small_speed_reliable_backwards$(EXEEXT)'; \ b='test_mesh_small_speed_reliable_backwards'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstLIBRARIES clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstLIBRARIES clean-noinstPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libexecPROGRAMS install-man install-pdf install-pdf-am \ install-pkgcfgDATA install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/mesh/gnunet-mesh-profiler.c0000644000175000017500000007052512316473376016000 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-mesh-profiler.c * * @brief Profiler for mesh experiments. */ #include #include "platform.h" #include "mesh_test_lib.h" #include "gnunet_mesh_service.h" #include "gnunet_statistics_service.h" #define PING 1 #define PONG 2 /** * Paximum ping period in milliseconds. Real period = rand (0, PING_PERIOD) */ #define PING_PERIOD 1000 /** * How long until we give up on connecting the peers? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * Time to wait for stuff that should be rather fast */ #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) /** * Total number of rounds. */ #define number_rounds sizeof(rounds)/sizeof(rounds[0]) /** * Ratio of peers active. First round always is 1.0. */ static float rounds[] = {0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.0}; /** * Message type for pings. */ struct MeshPingMessage { /** * Header. Type PING/PONG. */ struct GNUNET_MessageHeader header; /** * Message number. */ uint32_t counter; /** * Time the message was sent. */ struct GNUNET_TIME_AbsoluteNBO timestamp; /** * Round number. */ uint32_t round_number; }; /** * Peer description. */ struct MeshPeer { /** * Testbed Operation (to get peer id, etc). */ struct GNUNET_TESTBED_Operation *op; /** * Peer ID. */ struct GNUNET_PeerIdentity id; /** * Mesh handle for the root peer */ struct GNUNET_MESH_Handle *mesh; /** * Channel handle for the root peer */ struct GNUNET_MESH_Channel *ch; /** * Channel handle for the dest peer */ struct GNUNET_MESH_Channel *incoming_ch; /** * Channel handle for a warmup channel. */ struct GNUNET_MESH_Channel *warmup_ch; /** * Number of payload packes sent */ int data_sent; /** * Number of payload packets received */ int data_received; /** * Is peer up? */ int up; /** * Destinaton to ping. */ struct MeshPeer *dest; /** * Incoming channel for pings. */ struct MeshPeer *incoming; /** * Task to do the next ping. */ GNUNET_SCHEDULER_TaskIdentifier ping_task; float mean[number_rounds]; float var[number_rounds]; unsigned int pongs[number_rounds]; unsigned int pings[number_rounds]; }; /** * Duration of each round. */ static struct GNUNET_TIME_Relative round_time; /** * GNUNET_PeerIdentity -> MeshPeer */ static struct GNUNET_CONTAINER_MultiPeerMap *ids; /** * Testbed peer handles. */ static struct GNUNET_TESTBED_Peer **testbed_handles; /** * Testbed Operation (to get stats). */ static struct GNUNET_TESTBED_Operation *stats_op; /** * Operation to get peer ids. */ struct MeshPeer *peers; /** * Peer ids counter. */ static unsigned int p_ids; /** * Total number of peers. */ static unsigned long long peers_total; /** * Number of currently running peers. */ static unsigned long long peers_running; /** * Number of peers doing pings. */ static unsigned long long peers_pinging; /** * Test context (to shut down). */ static struct GNUNET_MESH_TEST_Context *test_ctx; /** * Task called to shutdown test. */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; /** * Task called to disconnect peers, before shutdown. */ static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; /** * Task to perform tests */ static GNUNET_SCHEDULER_TaskIdentifier test_task; /** * Round number. */ static unsigned int current_round; /** * Do preconnect? (Each peer creates a tunnel to one other peer). */ static int do_warmup; /** * Warmup progress. */ static unsigned int peers_warmup; /** * Flag to notify callbacks not to generate any new traffic anymore. */ static int test_finished; /** * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES. * * Testcase continues when the root receives confirmation of connected peers, * on callback funtion ch. * * @param cls Closure (unsued). * @param tc Task Context. */ static void start_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Calculate a random delay. * * @param max Exclusive maximum, in ms. * * @return A time between 0 a max-1 ms. */ static struct GNUNET_TIME_Relative delay_ms_rnd (unsigned int max) { unsigned int rnd; rnd = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max); return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rnd); } /** * Get the index of a peer in the peers array. * * @param peer Peer whose index to get. * * @return Index of peer in peers. */ static unsigned int get_index (struct MeshPeer *peer) { return peer - peers; } /** * Show the results of the test (banwidth acheived) and log them to GAUGER */ static void show_end_data (void) { struct MeshPeer *peer; unsigned int i; unsigned int j; for (i = 0; i < number_rounds; i++) { for (j = 0; j < peers_pinging; j++) { peer = &peers[j]; FPRINTF (stdout, "ROUND %3u PEER %3u: %10.2f / %10.2f, PINGS: %3u, PONGS: %3u\n", i, j, peer->mean[i], sqrt (peer->var[i] / (peer->pongs[i] - 1)), peer->pings[i], peer->pongs[i]); } } } /** * Shut down peergroup, clean up. * * @param cls Closure (unused). * @param tc Task Context. */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Ending test.\n"); shutdown_handle = GNUNET_SCHEDULER_NO_TASK; } /** * Disconnect from mesh services af all peers, call shutdown. * * @param cls Closure (unused). * @param tc Task Context. */ static void disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { long line = (long) cls; unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting mesh service, called from line %ld\n", line); disconnect_task = GNUNET_SCHEDULER_NO_TASK; for (i = 0; i < peers_total; i++) { if (NULL != peers[i].op) GNUNET_TESTBED_operation_done (peers[i].op); if (peers[i].up != GNUNET_YES) continue; if (NULL != peers[i].ch) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: channel %p\n", i, peers[i].ch); GNUNET_MESH_channel_destroy (peers[i].ch); } if (NULL != peers[i].warmup_ch) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: warmup channel %p\n", i, peers[i].warmup_ch); GNUNET_MESH_channel_destroy (peers[i].warmup_ch); } if (NULL != peers[i].incoming_ch) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: incoming channel %p\n", i, peers[i].incoming_ch); GNUNET_MESH_channel_destroy (peers[i].incoming_ch); } } GNUNET_MESH_TEST_cleanup (test_ctx); if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) { GNUNET_SCHEDULER_cancel (shutdown_handle); } shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } /** * Finish test normally: schedule disconnect and shutdown * * @param line Line in the code the abort is requested from (__LINE__). */ static void abort_test (long line) { if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, (void *) line); } } /** * Stats callback. Finish the stats testbed operation and when all stats have * been iterated, shutdown the test. * * @param cls closure * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "... collecting statistics done.\n"); GNUNET_TESTBED_operation_done (stats_op); if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, (void *) __LINE__); } /** * Process statistic values. * * @param cls closure * @param peer the peer the statistic belong to * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, const char *subsystem, const char *name, uint64_t value, int is_persistent) { uint32_t i; i = GNUNET_TESTBED_get_index (peer); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " STATS %u - %s [%s]: %llu\n", i, subsystem, name, value); return GNUNET_OK; } /** * Task check that keepalives were sent and received. * * @param cls Closure (NULL). * @param tc Task Context. */ static void collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start collecting statistics...\n"); stats_op = GNUNET_TESTBED_get_statistics (peers_total, testbed_handles, NULL, NULL, stats_iterator, stats_cont, NULL); } /** * @brief Finish profiler normally. Signal finish and start collecting stats. * * @param cls Closure (unused). * @param tc Task context. */ static void finish_profiler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; test_finished = GNUNET_YES; show_end_data(); GNUNET_SCHEDULER_add_now (&collect_stats, NULL); } /** * Set the total number of running peers. * * @param target Desired number of running peers. */ static void adjust_running_peers (unsigned int target) { struct GNUNET_TESTBED_Operation *op; unsigned int delta; unsigned int run; unsigned int i; unsigned int r; GNUNET_assert (target <= peers_total); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "adjust peers to %u\n", target); if (target > peers_running) { delta = target - peers_running; run = GNUNET_YES; } else { delta = peers_running - target; run = GNUNET_NO; } for (i = 0; i < delta; i++) { do { r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, peers_total - peers_pinging); r += peers_pinging; } while (peers[r].up == run || NULL != peers[r].incoming); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "St%s peer %u: %s\n", run ? "arting" : "opping", r, GNUNET_i2s (&peers[r].id)); if (GNUNET_SCHEDULER_NO_TASK != peers[r].ping_task) GNUNET_SCHEDULER_cancel (peers[r].ping_task); peers[r].ping_task = GNUNET_SCHEDULER_NO_TASK; peers[r].up = run; if (NULL != peers[r].ch) GNUNET_MESH_channel_destroy (peers[r].ch); peers[r].ch = NULL; if (NULL != peers[r].dest) { if (NULL != peers[r].dest->incoming_ch) GNUNET_MESH_channel_destroy (peers[r].dest->incoming_ch); peers[r].dest->incoming_ch = NULL; } op = GNUNET_TESTBED_peer_manage_service (&peers[r], testbed_handles[r], "mesh", NULL, NULL, run); GNUNET_break (NULL != op); peers_running += run ? 1 : -1; GNUNET_assert (peers_running > 0); } } /** * @brief Move to next round. * * @param cls Closure (round #). * @param tc Task context. */ static void next_rnd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ROUND %ld\n", current_round); if (0.0 == rounds[current_round]) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finishing\n"); GNUNET_SCHEDULER_add_now (&finish_profiler, NULL); return; } adjust_running_peers (rounds[current_round] * peers_total); current_round++; GNUNET_SCHEDULER_add_delayed (round_time, &next_rnd, NULL); } /** * Transmit ping callback. * * @param cls Closure (peer for PING, NULL for PONG). * @param size Size of the tranmist buffer. * @param buf Pointer to the beginning of the buffer. * * @return Number of bytes written to buf. */ static size_t tmt_rdy_ping (void *cls, size_t size, void *buf); /** * Transmit pong callback. * * @param cls Closure (copy of PING message, to be freed). * @param size Size of the buffer we have. * @param buf Buffer to copy data to. */ static size_t tmt_rdy_pong (void *cls, size_t size, void *buf) { struct MeshPingMessage *ping = cls; struct MeshPingMessage *pong; if (0 == size || NULL == buf) { GNUNET_free (ping); return 0; } pong = (struct MeshPingMessage *) buf; memcpy (pong, ping, sizeof (*ping)); pong->header.type = htons (PONG); GNUNET_free (ping); return sizeof (*ping); } /** * @brief Send a ping to destination * * @param cls Closure (peer). * @param tc Task context. */ static void ping (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshPeer *peer = (struct MeshPeer *) cls; peer->ping_task = GNUNET_SCHEDULER_NO_TASK; if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0 || GNUNET_YES == test_finished) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u -> %u (%u)\n", get_index (peer), get_index (peer->dest), peer->data_sent); GNUNET_MESH_notify_transmit_ready (peer->ch, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct MeshPingMessage), &tmt_rdy_ping, peer); } /** * @brief Reply with a pong to origin. * * @param cls Closure (peer). * @param tc Task context. */ static void pong (struct GNUNET_MESH_Channel *channel, const struct MeshPingMessage *ping) { struct MeshPingMessage *copy; copy = GNUNET_new (struct MeshPingMessage); memcpy (copy, ping, sizeof (*ping)); GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct MeshPingMessage), &tmt_rdy_pong, copy); } /** * Transmit ping callback * * @param cls Closure (peer). * @param size Size of the buffer we have. * @param buf Buffer to copy data to. */ static size_t tmt_rdy_ping (void *cls, size_t size, void *buf) { struct MeshPeer *peer = (struct MeshPeer *) cls; struct MeshPingMessage *msg = buf; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tmt_rdy called, filling buffer\n"); if (size < sizeof (struct MeshPingMessage) || NULL == buf) { GNUNET_break (GNUNET_YES == test_finished); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size %u, buf %p, data_sent %u, data_received %u\n", size, buf, peer->data_sent, peer->data_received); return 0; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending: msg %d\n", peer->data_sent); msg->header.size = htons (size); msg->header.type = htons (PING); msg->counter = htonl (peer->data_sent++); msg->round_number = htonl (current_round); msg->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); peer->pings[current_round]++; peer->ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (PING_PERIOD), &ping, peer); return sizeof (struct MeshPingMessage); } /** * Function is called whenever a PING message is received. * * @param cls closure (peer #, set from GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int ping_handler (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { long n = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u got PING\n", n); GNUNET_MESH_receive_done (channel); if (GNUNET_NO == test_finished) pong (channel, (struct MeshPingMessage *) message); return GNUNET_OK; } /** * Function is called whenever a PONG message is received. * * @param cls closure (peer #, set from GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int pong_handler (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { long n = (long) cls; struct MeshPeer *peer; struct MeshPingMessage *msg; struct GNUNET_TIME_Absolute send_time; struct GNUNET_TIME_Relative latency; unsigned int r /* Ping round */; float delta; GNUNET_MESH_receive_done (channel); peer = &peers[n]; msg = (struct MeshPingMessage *) message; send_time = GNUNET_TIME_absolute_ntoh (msg->timestamp); latency = GNUNET_TIME_absolute_get_duration (send_time); r = ntohl (msg->round_number); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <- %u (%u) latency: %s\n", get_index (peer), get_index (peer->dest), ntohl (msg->counter), GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO)); /* Online variance calculation */ peer->pongs[r]++; delta = latency.rel_value_us - peer->mean[r]; peer->mean[r] = peer->mean[r] + delta/peer->pongs[r]; peer->var[r] += delta * (latency.rel_value_us - peer->mean[r]); return GNUNET_OK; } /** * Handlers, for diverse services */ static struct GNUNET_MESH_MessageHandler handlers[] = { {&ping_handler, PING, sizeof (struct MeshPingMessage)}, {&pong_handler, PONG, sizeof (struct MeshPingMessage)}, {NULL, 0, 0} }; /** * Method called whenever another peer has added us to a channel * the other peer initiated. * * @param cls Closure. * @param channel New handle to the channel. * @param initiator Peer that started the channel. * @param port Port this channel is connected to. * @param options channel option flags * @return Initial channel context for the channel * (can be NULL -- that's not an error). */ static void * incoming_channel (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { long n = (long) cls; struct MeshPeer *peer; peer = GNUNET_CONTAINER_multipeermap_get (ids, initiator); GNUNET_assert (NULL != peer); if (NULL == peers[n].incoming) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %3u: %u <= %u\n", peers_warmup, n, get_index (peer)); peers_warmup++; if (peers_warmup < peers_total) return NULL; if (GNUNET_SCHEDULER_NO_TASK != test_task) { GNUNET_SCHEDULER_cancel (test_task); test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &start_test, NULL); } return NULL; } GNUNET_assert (peer == peers[n].incoming); GNUNET_assert (peer->dest == &peers[n]); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <= %u %p\n", n, get_index (peer), channel); peers[n].incoming_ch = channel; return NULL; } /** * Function called whenever an inbound channel is destroyed. Should clean up * any associated state. * * @param cls closure (set from GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void channel_cleaner (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { long n = (long) cls; struct MeshPeer *peer = &peers[n]; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Channel %p disconnected at peer %ld\n", channel, n); if (peer->ch == channel) peer->ch = NULL; } /** * Select a random peer that has no incoming channel * * @param peer ID of the peer connecting. NULL if irrelevant (warmup). * * @return Random peer not yet connected to. */ static struct MeshPeer * select_random_peer (struct MeshPeer *peer) { unsigned int r; do { r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, peers_total); } while (NULL != peers[r].incoming); peers[r].incoming = peer; return &peers[r]; } /** * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES. * * Testcase continues when the root receives confirmation of connected peers, * on callback funtion ch. * * @param cls Closure (unsued). * @param tc Task Context. */ static void start_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { enum GNUNET_MESH_ChannelOption flags; unsigned long i; test_task = GNUNET_SCHEDULER_NO_TASK; if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start profiler\n"); flags = GNUNET_MESH_OPTION_DEFAULT; for (i = 0; i < peers_pinging; i++) { peers[i].dest = select_random_peer (&peers[i]); peers[i].ch = GNUNET_MESH_channel_create (peers[i].mesh, NULL, &peers[i].dest->id, 1, flags); if (NULL == peers[i].ch) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Channel %lu failed\n", i); GNUNET_MESH_TEST_cleanup (test_ctx); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u => %u %p\n", i, get_index (peers[i].dest), peers[i].ch); peers[i].ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (2000), &ping, &peers[i]); } peers_running = peers_total; if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(round_time, number_rounds + 1), &disconnect_mesh_peers, (void *) __LINE__); GNUNET_SCHEDULER_add_delayed (round_time, &next_rnd, NULL); } /** * Do warmup: create some channels to spread information about the topology. */ static void warmup (void) { struct MeshPeer *peer; unsigned int i; for (i = 0; i < peers_total; i++) { peer = select_random_peer (NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %u => %u\n", i, get_index (peer)); peers[i].warmup_ch = GNUNET_MESH_channel_create (peers[i].mesh, NULL, &peer->id, 1, GNUNET_MESH_OPTION_DEFAULT); if (NULL == peers[i].warmup_ch) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Warmup %u failed\n", i); GNUNET_MESH_TEST_cleanup (test_ctx); return; } } } /** * Callback to be called when the requested peer information is available * * @param cls the closure from GNUNET_TESTBED_peer_get_information() * @param op the operation this callback corresponds to * @param pinfo the result; will be NULL if the operation has failed * @param emsg error message if the operation has failed; * NULL if the operation is successfull */ static void peer_id_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) { long n = (long) cls; if (NULL == pinfo || NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); abort_test (__LINE__); return; } peers[n].id = *(pinfo->result.id); GNUNET_log (GNUNET_ERROR_TYPE_INFO, " %u id: %s\n", n, GNUNET_i2s (&peers[n].id)); GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (ids, &peers[n].id, &peers[n], GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); GNUNET_TESTBED_operation_done (peers[n].op); peers[n].op = NULL; p_ids++; if (p_ids < peers_total) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting profiler\n"); if (do_warmup) { struct GNUNET_TIME_Relative delay; warmup(); delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100 * peers_total); test_task = GNUNET_SCHEDULER_add_delayed (delay, &start_test, NULL); return; /* start_test from incoming_channel */ } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting in a second...\n"); test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &start_test, NULL); } /** * test main: start test when all peers are connected * * @param cls Closure. * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end. * @param num_peers Number of peers that are running. * @param testbed_peers Array of peers. * @param meshes Handle to each of the MESHs of the peers. */ static void tmain (void *cls, struct GNUNET_MESH_TEST_Context *ctx, unsigned int num_peers, struct GNUNET_TESTBED_Peer **testbed_peers, struct GNUNET_MESH_Handle **meshes) { unsigned long i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n"); test_ctx = ctx; GNUNET_assert (peers_total == num_peers); peers_running = num_peers; testbed_handles = testbed_peers; disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, (void *) __LINE__); shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); for (i = 0; i < peers_total; i++) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requesting id %ld\n", i); peers[i].up = GNUNET_YES; peers[i].mesh = meshes[i]; peers[i].op = GNUNET_TESTBED_peer_get_information (testbed_handles[i], GNUNET_TESTBED_PIT_IDENTITY, &peer_id_cb, (void *) i); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "requested peer ids\n"); /* Continues from pi_cb -> do_test */ } /** * Main: start profiler. */ int main (int argc, char *argv[]) { static uint32_t ports[2]; const char *config_file; config_file = ".profiler.conf"; if (4 > argc) { fprintf (stderr, "usage: %s ROUND_TIME PEERS PINGS [DO_WARMUP]\n", argv[0]); fprintf (stderr, "example: %s 30s 16 1 Y\n", argv[0]); return 1; } if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[1], &round_time)) { fprintf (stderr, "%s is not a valid time\n", argv[1]); return 1; } peers_total = atoll (argv[2]); if (2 > peers_total) { fprintf (stderr, "%s peers is not valid (> 2)\n", argv[1]); return 1; } peers = GNUNET_malloc (sizeof (struct MeshPeer) * peers_total); peers_pinging = atoll (argv[3]); if (peers_total < 2 * peers_pinging) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "not enough peers, total should be > 2 * peers_pinging\n"); return 1; } do_warmup = (5 > argc || argv[4][0] != 'N'); ids = GNUNET_CONTAINER_multipeermap_create (2 * peers_total, GNUNET_YES); GNUNET_assert (NULL != ids); p_ids = 0; test_finished = GNUNET_NO; ports[0] = 1; ports[1] = 0; GNUNET_MESH_TEST_run ("mesh-profiler", config_file, peers_total, &tmain, NULL, /* tmain cls */ &incoming_channel, &channel_cleaner, handlers, ports); GNUNET_free (peers); return 0; } /* end of gnunet-mesh-profiler.c */ gnunet-0.10.1/src/mesh/gnunet-service-mesh_dht.h0000644000175000017500000000466012225777503016455 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh_dht.h * @brief mesh service; dealing with DHT requests and results * @author Bartlomiej Polot * * All functions in this file should use the prefix GMD (Gnunet Mesh Dht) */ #ifndef GNUNET_SERVICE_MESH_DHT_H #define GNUNET_SERVICE_MESH_DHT_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "gnunet_util_lib.h" struct GMD_search_handle; /** * Callback called on each path found over the DHT. * * @param cls Closure. * @param path An unchecked, unoptimized path to the target node. * After callback will no longer be valid! */ typedef void (*GMD_search_callback) (void *cls, const struct MeshPeerPath *path); /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Initialize the DHT subsystem. * * @param c Configuration. */ void GMD_init (const struct GNUNET_CONFIGURATION_Handle *c); /** * Shut down the DHT subsystem. */ void GMD_shutdown (void); struct GMD_search_handle * GMD_search (const struct GNUNET_PeerIdentity *peer_id, GMD_search_callback callback, void *cls); void GMD_search_stop (struct GMD_search_handle *h); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_MESH_SERVICE_LOCAL_H */ #endif /* end of gnunet-mesh-service_LOCAL.h */gnunet-0.10.1/src/mesh/gnunet-service-mesh_tunnel.h0000644000175000017500000002777712306275771017221 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh_tunnel.h * @brief mesh service; dealing with tunnels and crypto * @author Bartlomiej Polot * * All functions in this file should use the prefix GMT (Gnunet Mesh Tunnel) */ #ifndef GNUNET_SERVICE_MESH_TUNNEL_H #define GNUNET_SERVICE_MESH_TUNNEL_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "gnunet_util_lib.h" /** * All the connectivity states a tunnel can be in. */ enum MeshTunnel3CState { /** * Uninitialized status, should never appear in operation. */ MESH_TUNNEL3_NEW, /** * Path to the peer not known yet. */ MESH_TUNNEL3_SEARCHING, /** * Request sent, not yet answered. */ MESH_TUNNEL3_WAITING, /** * Peer connected and ready to accept data. */ MESH_TUNNEL3_READY, /** * Tunnel being shut down, don't try to keep it alive. */ MESH_TUNNEL3_SHUTDOWN }; /** * All the encryption states a tunnel can be in. */ enum MeshTunnel3EState { /** * Uninitialized status, should never appear in operation. */ MESH_TUNNEL3_KEY_UNINITIALIZED, /** * Ephemeral key sent, waiting for peer's key. */ MESH_TUNNEL3_KEY_SENT, /** * New ephemeral key and ping sent, waiting for pong. * This means that we DO have the peer's ephemeral key, otherwise the * state would be KEY_SENT. */ MESH_TUNNEL3_KEY_PING, /** * Handshake completed: session key available. */ MESH_TUNNEL3_KEY_OK, }; /** * Struct containing all information regarding a given peer */ struct MeshTunnel3; #include "gnunet-service-mesh_channel.h" #include "gnunet-service-mesh_connection.h" #include "gnunet-service-mesh_peer.h" /** * Handle for messages queued but not yet sent. */ struct MeshTunnel3Queue; /** * Callback called when a queued message is sent. * * @param cls Closure. * @param t Tunnel this message was on. * @param type Type of message sent. * @param size Size of the message. */ typedef void (*GMT_sent) (void *cls, struct MeshTunnel3 *t, struct MeshTunnel3Queue *q, uint16_t type, size_t size); typedef void (*GMT_conn_iter) (void *cls, struct MeshConnection *c); typedef void (*GMT_chan_iter) (void *cls, struct MeshChannel *ch); /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Initialize tunnel subsystem. * * @param c Configuration handle. * @param key ECC private key, to derive all other keys and do crypto. */ void GMT_init (const struct GNUNET_CONFIGURATION_Handle *c, const struct GNUNET_CRYPTO_EddsaPrivateKey *key); /** * Shut down the tunnel subsystem. */ void GMT_shutdown (void); /** * Create a tunnel. * * @param destination Peer this tunnel is towards. */ struct MeshTunnel3 * GMT_new (struct MeshPeer *destination); /** * Tunnel is empty: destroy it. * * Notifies all connections about the destruction. * * @param t Tunnel to destroy. */ void GMT_destroy_empty (struct MeshTunnel3 *t); /** * Destroy tunnel if empty (no more channels). * * @param t Tunnel to destroy if empty. */ void GMT_destroy_if_empty (struct MeshTunnel3 *t); /** * Destroy the tunnel. * * This function does not generate any warning traffic to clients or peers. * * Tasks: * Cancel messages belonging to this tunnel queued to neighbors. * Free any allocated resources linked to the tunnel. * * @param t The tunnel to destroy. */ void GMT_destroy (struct MeshTunnel3 *t); /** * Change the tunnel's connection state. * * @param t Tunnel whose connection state to change. * @param cstate New connection state. */ void GMT_change_cstate (struct MeshTunnel3* t, enum MeshTunnel3CState cstate); /** * Change the tunnel encryption state. * * @param t Tunnel whose encryption state to change. * @param state New encryption state. */ void GMT_change_estate (struct MeshTunnel3* t, enum MeshTunnel3EState state); /** * Add a connection to a tunnel. * * @param t Tunnel. * @param c Connection. */ void GMT_add_connection (struct MeshTunnel3 *t, struct MeshConnection *c); /** * Mark a path as no longer valid for this tunnel: has been tried and failed. * * @param t Tunnel to update. * @param path Invalid path to remove. Is destroyed after removal. */ void GMT_remove_path (struct MeshTunnel3 *t, struct MeshPeerPath *path); /** * Remove a connection from a tunnel. * * @param t Tunnel. * @param c Connection. */ void GMT_remove_connection (struct MeshTunnel3 *t, struct MeshConnection *c); /** * Add a channel to a tunnel. * * @param t Tunnel. * @param ch Channel. */ void GMT_add_channel (struct MeshTunnel3 *t, struct MeshChannel *ch); /** * Remove a channel from a tunnel. * * @param t Tunnel. * @param ch Channel. */ void GMT_remove_channel (struct MeshTunnel3 *t, struct MeshChannel *ch); /** * Search for a channel by global ID. * * @param t Tunnel containing the channel. * @param chid Public channel number. * * @return channel handler, NULL if doesn't exist */ struct MeshChannel * GMT_get_channel (struct MeshTunnel3 *t, MESH_ChannelNumber chid); /** * Decrypt and demultiplex by message type. Call appropriate handler * for a message * towards a channel of a local tunnel. * * @param t Tunnel this message came on. * @param msg Message header. */ void GMT_handle_encrypted (struct MeshTunnel3 *t, const struct GNUNET_MESH_Encrypted *msg); /** * Demultiplex an encapsulated KX message by message type. * * @param t Tunnel on which the message came. * @param message KX message itself. */ void GMT_handle_kx (struct MeshTunnel3 *t, const struct GNUNET_MessageHeader *message); /** * @brief Use the given path for the tunnel. * Update the next and prev hops (and RCs). * (Re)start the path refresh in case the tunnel is locally owned. * * @param t Tunnel to update. * @param p Path to use. * * @return Connection created. */ struct MeshConnection * GMT_use_path (struct MeshTunnel3 *t, struct MeshPeerPath *p); /** * Count established (ready) connections of a tunnel. * * @param t Tunnel on which to count. * * @return Number of connections. */ unsigned int GMT_count_connections (struct MeshTunnel3 *t); /** * Count channels of a tunnel. * * @param t Tunnel on which to count. * * @return Number of channels. */ unsigned int GMT_count_channels (struct MeshTunnel3 *t); /** * Get the connectivity state of a tunnel. * * @param t Tunnel. * * @return Tunnel's connectivity state. */ enum MeshTunnel3CState GMT_get_cstate (struct MeshTunnel3 *t); /** * Get the encryption state of a tunnel. * * @param t Tunnel. * * @return Tunnel's encryption state. */ enum MeshTunnel3EState GMT_get_estate (struct MeshTunnel3 *t); /** * Get the maximum buffer space for a tunnel towards a local client. * * @param t Tunnel. * * @return Biggest buffer space offered by any channel in the tunnel. */ unsigned int GMT_get_channels_buffer (struct MeshTunnel3 *t); /** * Get the total buffer space for a tunnel for P2P traffic. * * @param t Tunnel. * * @return Buffer space offered by all connections in the tunnel. */ unsigned int GMT_get_connections_buffer (struct MeshTunnel3 *t); /** * Get the tunnel's destination. * * @param t Tunnel. * * @return ID of the destination peer. */ const struct GNUNET_PeerIdentity * GMT_get_destination (struct MeshTunnel3 *t); /** * Get the tunnel's next free Channel ID. * * @param t Tunnel. * * @return ID of a channel free to use. */ MESH_ChannelNumber GMT_get_next_chid (struct MeshTunnel3 *t); /** * Send ACK on one or more channels due to buffer in connections. * * @param t Channel which has some free buffer space. */ void GMT_unchoke_channels (struct MeshTunnel3 *t); /** * Send ACK on one or more connections due to buffer space to the client. * * Iterates all connections of the tunnel and sends ACKs appropriately. * * @param t Tunnel which has some free buffer space. */ void GMT_send_connection_acks (struct MeshTunnel3 *t); /** * Cancel a previously sent message while it's in the queue. * * ONLY can be called before the continuation given to the send function * is called. Once the continuation is called, the message is no longer in the * queue. * * @param q Handle to the queue. */ void GMT_cancel (struct MeshTunnel3Queue *q); /** * Sends an already built message on a tunnel, encrypting it and * choosing the best connection. * * @param message Message to send. Function modifies it. * @param t Tunnel on which this message is transmitted. * @param c Connection to use (autoselect if NULL). * @param force Force the tunnel to take the message (buffer overfill). * @param cont Continuation to call once message is really sent. * @param cont_cls Closure for @c cont. * * @return Handle to cancel message. NULL if @c cont is NULL. */ struct MeshTunnel3Queue * GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, struct MeshTunnel3 *t, struct MeshConnection *c, int force, GMT_sent cont, void *cont_cls); /** * Is the tunnel directed towards the local peer? * * @param t Tunnel. * * @return #GNUNET_YES if it is loopback. */ int GMT_is_loopback (const struct MeshTunnel3 *t); /** * Is the tunnel using this path already? * * @param t Tunnel. * @param p Path. * * @return #GNUNET_YES a connection uses this path. */ int GMT_is_path_used (const struct MeshTunnel3 *t, const struct MeshPeerPath *p); /** * Get a cost of a path for a tunnel considering existing connections. * * @param t Tunnel. * @param path Candidate path. * * @return Cost of the path (path length + number of overlapping nodes) */ unsigned int GMT_get_path_cost (const struct MeshTunnel3 *t, const struct MeshPeerPath *path); /** * Get the static string for the peer this tunnel is directed. * * @param t Tunnel. * * @return Static string the destination peer's ID. */ const char * GMT_2s (const struct MeshTunnel3 *t); /** * Log all possible info about the tunnel state. * * @param t Tunnel to debug. */ void GMT_debug (const struct MeshTunnel3 *t); /** * Iterate all tunnels. * * @param iter Iterator. * @param cls Closure for @c iter. */ void GMT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls); /** * Count all tunnels. * * @return Number of tunnels to remote peers kept by this peer. */ unsigned int GMT_count_all (void); /** * Iterate all connections of a tunnel. * * @param t Tunnel whose connections to iterate. * @param iter Iterator. * @param cls Closure for @c iter. */ void GMT_iterate_connections (struct MeshTunnel3 *t, GMT_conn_iter iter, void *cls); /** * Iterate all channels of a tunnel. * * @param t Tunnel whose channels to iterate. * @param iter Iterator. * @param cls Closure for @c iter. */ void GMT_iterate_channels (struct MeshTunnel3 *t, GMT_chan_iter iter, void *cls); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_MESH_SERVICE_TUNNEL_H */ #endif /* end of gnunet-mesh-service_tunnel.h */ gnunet-0.10.1/src/mesh/test_mesh_small.c0000644000175000017500000006166212320724374015103 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/test_mesh_small.c * * @brief Test for the mesh service: retransmission of traffic. */ #include #include "platform.h" #include "mesh_test_lib.h" #include "gnunet_mesh_service.h" #include "gnunet_statistics_service.h" #include /** * How namy messages to send */ #define TOTAL_PACKETS 1000 /** * How long until we give up on connecting the peers? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * Time to wait for stuff that should be rather fast */ #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * DIFFERENT TESTS TO RUN */ #define SETUP 0 #define FORWARD 1 #define KEEPALIVE 2 #define SPEED 3 #define SPEED_ACK 4 #define SPEED_REL 8 #define P2P_SIGNAL 10 /** * Which test are we running? */ static int test; /** * String with test name */ char *test_name; /** * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. */ static int test_backwards = GNUNET_NO; /** * How many events have happened */ static int ok; /** * Number of events expected to conclude the test successfully. */ int ok_goal; /** * Size of each test packet */ size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t); /** * Operation to get peer ids. */ struct GNUNET_TESTBED_Operation *t_op[2]; /** * Peer ids. */ struct GNUNET_PeerIdentity *p_id[2]; /** * Peer ids counter. */ unsigned int p_ids; /** * Is the setup initialized? */ static int initialized; /** * Number of payload packes sent */ static int data_sent; /** * Number of payload packets received */ static int data_received; /** * Number of payload packed explicitly (app level) acknowledged */ static int data_ack; /** * Total number of currently running peers. */ static unsigned long long peers_running; /** * Test context (to shut down). */ struct GNUNET_MESH_TEST_Context *test_ctx; /** * Task called to disconnect peers. */ static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; /** * Task To perform tests */ static GNUNET_SCHEDULER_TaskIdentifier test_task; /** * Task called to shutdown test. */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; /** * Mesh handle for the root peer */ static struct GNUNET_MESH_Handle *h1; /** * Mesh handle for the first leaf peer */ static struct GNUNET_MESH_Handle *h2; /** * Channel handle for the root peer */ static struct GNUNET_MESH_Channel *ch; /** * Channel handle for the dest peer */ static struct GNUNET_MESH_Channel *incoming_ch; /** * Time we started the data transmission (after channel has been established * and initilized). */ static struct GNUNET_TIME_Absolute start_time; static struct GNUNET_TESTBED_Peer **testbed_peers; static struct GNUNET_TESTBED_Operation *stats_op; static unsigned int ka_sent; static unsigned int ka_received; /** * Show the results of the test (banwidth acheived) and log them to GAUGER */ static void show_end_data (void) { static struct GNUNET_TIME_Absolute end_time; static struct GNUNET_TIME_Relative total_time; end_time = GNUNET_TIME_absolute_get(); total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time); FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); FPRINTF (stderr, "Test time %s\n", GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES)); FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms FPRINTF (stderr, "Test throughput: %f packets/s\n\n", TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms GAUGER ("MESH", test_name, TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000), "packets/s"); } /** * Shut down peergroup, clean up. * * @param cls Closure (unused). * @param tc Task Context. */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); shutdown_handle = GNUNET_SCHEDULER_NO_TASK; } /** * Disconnect from mesh services af all peers, call shutdown. * * @param cls Closure (unused). * @param tc Task Context. */ static void disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { long line = (long) cls; unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting mesh service of peers, called from line %ld\n", line); disconnect_task = GNUNET_SCHEDULER_NO_TASK; for (i = 0; i < 2; i++) { GNUNET_TESTBED_operation_done (t_op[i]); } if (NULL != ch) { GNUNET_MESH_channel_destroy (ch); ch = NULL; } if (NULL != incoming_ch) { GNUNET_MESH_channel_destroy (incoming_ch); incoming_ch = NULL; } GNUNET_MESH_TEST_cleanup (test_ctx); if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) { GNUNET_SCHEDULER_cancel (shutdown_handle); } shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } /** * Abort test: schedule disconnect and shutdown immediately * * @param line Line in the code the abort is requested from (__LINE__). */ static void abort_test (long line) { if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, (void *) line); } } /** * Transmit ready callback. * * @param cls Closure (message type). * @param size Size of the tranmist buffer. * @param buf Pointer to the beginning of the buffer. * * @return Number of bytes written to buf. */ static size_t tmt_rdy (void *cls, size_t size, void *buf); /** * Task to schedule a new data transmission. * * @param cls Closure (peer #). * @param tc Task Context. */ static void data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_MESH_TransmitHandle *th; struct GNUNET_MESH_Channel *channel; if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n"); if (GNUNET_YES == test_backwards) { channel = incoming_ch; } else { channel = ch; } th = GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, size_payload, &tmt_rdy, (void *) 1L); if (NULL == th) { unsigned long i = (unsigned long) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n"); if (0 == i) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n"); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &data_task, (void *)1UL); } else { i++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply( GNUNET_TIME_UNIT_MILLISECONDS, i), &data_task, (void *)i); } } } /** * Transmit ready callback * * @param cls Closure (message type). * @param size Size of the buffer we have. * @param buf Buffer to copy data to. */ size_t tmt_rdy (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg = buf; uint32_t *data; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tmt_rdy called, filling buffer\n"); if (size < size_payload || NULL == buf) { GNUNET_break (ok >= ok_goal - 2); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "size %u, buf %p, data_sent %u, data_received %u\n", size, buf, data_sent, data_received); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok %u, ok goal %u\n", ok, ok_goal); return 0; } msg->size = htons (size); msg->type = htons ((long) cls); data = (uint32_t *) &msg[1]; *data = htonl (data_sent); if (GNUNET_NO == initialized) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending initializer\n"); } else if (SPEED == test) { data_sent++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Sent packet %d\n", data_sent); if (data_sent < TOTAL_PACKETS) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Scheduling packet %d\n", data_sent + 1); GNUNET_SCHEDULER_add_now (&data_task, NULL); } } return size_payload; } /** * Function is called whenever a message is received. * * @param cls closure (set from GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int data_callback (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { long client = (long) cls; long expected_target_client; uint32_t *data; ok++; GNUNET_MESH_receive_done (channel); if ((ok % 20) == 0) { if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, (void *) __LINE__); } } switch (client) { case 0L: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); break; case 4L: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client %li got a message.\n", client); break; default: GNUNET_assert (0); break; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); data = (uint32_t *) &message[1]; GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data)); if (SPEED == test && GNUNET_YES == test_backwards) { expected_target_client = 0L; } else { expected_target_client = 4L; } if (GNUNET_NO == initialized) { initialized = GNUNET_YES; start_time = GNUNET_TIME_absolute_get (); if (SPEED == test) { GNUNET_assert (4L == client); GNUNET_SCHEDULER_add_now (&data_task, NULL); return GNUNET_OK; } } if (client == expected_target_client) // Normally 4 { data_received++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); if (SPEED != test || (ok_goal - 2) == ok) { GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, size_payload, &tmt_rdy, (void *) 1L); return GNUNET_OK; } else { if (data_received < TOTAL_PACKETS) return GNUNET_OK; } } else // Normally 0 { if (test == SPEED_ACK || test == SPEED) { data_ack++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", data_ack); GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, size_payload, &tmt_rdy, (void *) 1L); if (data_ack < TOTAL_PACKETS && SPEED != test) return GNUNET_OK; if (ok == 2 && SPEED == test) return GNUNET_OK; show_end_data(); } if (test == P2P_SIGNAL) { GNUNET_MESH_channel_destroy (incoming_ch); incoming_ch = NULL; } else { GNUNET_MESH_channel_destroy (ch); ch = NULL; } } if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, (void *) __LINE__); } return GNUNET_OK; } /** * Stats callback. Finish the stats testbed operation and when all stats have * been iterated, shutdown the test. * * @param cls closure * @param op the operation that has been finished * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stats_cont for peer %u\n", cls); GNUNET_log (GNUNET_ERROR_TYPE_INFO, " sent: %u, received: %u\n", ka_sent, ka_received); if (ka_sent < 2 || ka_sent > ka_received + 1) ok--; GNUNET_TESTBED_operation_done (stats_op); if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, (void *) __LINE__); } /** * Process statistic values. * * @param cls closure * @param peer the peer the statistic belong to * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, const char *subsystem, const char *name, uint64_t value, int is_persistent) { static const char *s_sent = "# keepalives sent"; static const char *s_recv = "# keepalives received"; uint32_t i; i = GNUNET_TESTBED_get_index (peer); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u - %s [%s]: %llu\n", i, subsystem, name, value); if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i) ka_sent = value; if (0 == strncmp(s_recv, name, strlen (s_recv)) && 4 == i) ka_received = value; return GNUNET_OK; } /** * Task check that keepalives were sent and received. * * @param cls Closure (NULL). * @param tc Task Context. */ static void check_keepalives (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; disconnect_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "check keepalives\n"); GNUNET_MESH_channel_destroy (ch); stats_op = GNUNET_TESTBED_get_statistics (5, testbed_peers, "mesh", NULL, stats_iterator, stats_cont, NULL); } /** * Handlers, for diverse services */ static struct GNUNET_MESH_MessageHandler handlers[] = { {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)}, {NULL, 0, 0} }; /** * Method called whenever another peer has added us to a channel * the other peer initiated. * * @param cls Closure. * @param channel New handle to the channel. * @param initiator Peer that started the channel. * @param port Port this channel is connected to. * @param options channel option flags * @return Initial channel context for the channel * (can be NULL -- that's not an error). */ static void * incoming_channel (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Incoming channel from %s to peer %d\n", GNUNET_i2s (initiator), (long) cls); ok++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); if ((long) cls == 4L) incoming_ch = channel; else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Incoming channel for unknown client %lu\n", (long) cls); GNUNET_break(0); } if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); if (KEEPALIVE == test) { struct GNUNET_TIME_Relative delay; delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS , 5); disconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &check_keepalives, NULL); } else disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, (void *) __LINE__); } return NULL; } /** * Function called whenever an inbound channel is destroyed. Should clean up * any associated state. * * @param cls closure (set from GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void channel_cleaner (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { long i = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Incoming channel disconnected at peer %ld\n", i); if (4L == i) { ok++; GNUNET_break (channel == incoming_ch); incoming_ch = NULL; } else if (0L == i) { if (P2P_SIGNAL == test) { ok ++; } GNUNET_break (channel == ch); ch = NULL; } else GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown peer! %d\n", i); GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, (void *) __LINE__); } return; } /** * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES. * * Testcase continues when the root receives confirmation of connected peers, * on callback funtion ch. * * @param cls Closure (unsued). * @param tc Task Context. */ static void do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { enum GNUNET_MESH_ChannelOption flags; if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n"); if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); } flags = GNUNET_MESH_OPTION_DEFAULT; if (SPEED_REL == test) { test = SPEED; flags |= GNUNET_MESH_OPTION_RELIABLE; } ch = GNUNET_MESH_channel_create (h1, NULL, p_id[1], 1, flags); disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, (void *) __LINE__); if (KEEPALIVE == test) return; /* Don't send any data. */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending data initializer...\n"); data_ack = 0; data_received = 0; data_sent = 0; GNUNET_MESH_notify_transmit_ready (ch, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, size_payload, &tmt_rdy, (void *) 1L); } /** * Callback to be called when the requested peer information is available * * @param cls the closure from GNUNET_TESTBED_peer_get_information() * @param op the operation this callback corresponds to * @param pinfo the result; will be NULL if the operation has failed * @param emsg error message if the operation has failed; * NULL if the operation is successfull */ static void pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) { long i = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i); if (NULL == pinfo || NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); abort_test (__LINE__); return; } p_id[i] = pinfo->result.id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); p_ids++; if (p_ids < 2) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_test, NULL); } /** * test main: start test when all peers are connected * * @param cls Closure. * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end. * @param num_peers Number of peers that are running. * @param peers Array of peers. * @param meshes Handle to each of the MESHs of the peers. */ static void tmain (void *cls, struct GNUNET_MESH_TEST_Context *ctx, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, struct GNUNET_MESH_Handle **meshes) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n"); ok = 0; test_ctx = ctx; peers_running = num_peers; testbed_peers = peers; h1 = meshes[0]; h2 = meshes[num_peers - 1]; disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, (void *) __LINE__); shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], GNUNET_TESTBED_PIT_IDENTITY, &pi_cb, (void *) 0L); t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], GNUNET_TESTBED_PIT_IDENTITY, &pi_cb, (void *) 1L); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); } /** * Main: start test */ int main (int argc, char *argv[]) { initialized = GNUNET_NO; static uint32_t ports[2]; const char *config_file; GNUNET_log_setup ("test", "DEBUG", NULL); config_file = "test_mesh.conf"; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); if (strstr (argv[0], "_small_forward") != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n"); test = FORWARD; test_name = "unicast"; ok_goal = 4; } else if (strstr (argv[0], "_small_signal") != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n"); test = P2P_SIGNAL; test_name = "signal"; ok_goal = 4; } else if (strstr (argv[0], "_small_speed_ack") != NULL) { /* Test is supposed to generate the following callbacks: * 1 incoming channel (@dest) * TOTAL_PACKETS received data packet (@dest) * TOTAL_PACKETS received data packet (@orig) * 1 received channel destroy (@dest) */ ok_goal = TOTAL_PACKETS * 2 + 2; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); test = SPEED_ACK; test_name = "speed ack"; } else if (strstr (argv[0], "_small_speed") != NULL) { /* Test is supposed to generate the following callbacks: * 1 incoming channel (@dest) * 1 initial packet (@dest) * TOTAL_PACKETS received data packet (@dest) * 1 received data packet (@orig) * 1 received channel destroy (@dest) */ ok_goal = TOTAL_PACKETS + 4; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); if (strstr (argv[0], "_reliable") != NULL) { test = SPEED_REL; test_name = "speed reliable"; config_file = "test_mesh_drop.conf"; } else { test = SPEED; test_name = "speed"; } } else if (strstr (argv[0], "_keepalive") != NULL) { test = KEEPALIVE; /* Test is supposed to generate the following callbacks: * 1 incoming channel (@dest) * [wait] * 1 received channel destroy (@dest) */ ok_goal = 2; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n"); test = SETUP; ok_goal = 0; } if (strstr (argv[0], "backwards") != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n"); test_backwards = GNUNET_YES; GNUNET_asprintf (&test_name, "backwards %s", test_name); } p_ids = 0; ports[0] = 1; ports[1] = 0; GNUNET_MESH_TEST_run ("test_mesh_small", config_file, 5, &tmain, NULL, /* tmain cls */ &incoming_channel, &channel_cleaner, handlers, ports); if (ok_goal > ok) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal); return 1; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); return 0; } /* end of test_mesh_small.c */ gnunet-0.10.1/src/mesh/mesh_path.h0000644000175000017500000001013312316473376013670 00000000000000/* This file is part of GNUnet. (C) 2001 - 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/mesh_path.h * @brief Path handling functions * @author Bartlomiej Polot */ #ifndef MESH_PATH_H_ #define MESH_PATH_H_ #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /******************************************************************************/ /************************ DATA STRUCTURES ****************************/ /******************************************************************************/ /** * Information regarding a possible path to reach a single peer */ struct MeshPeerPath { /** * Linked list */ struct MeshPeerPath *next; struct MeshPeerPath *prev; /** * List of all the peers that form the path from origin to target. */ GNUNET_PEER_Id *peers; /** * Number of peers (hops) in the path */ unsigned int length; /** * Path's score, how reliable is the path. */ // int score; /** * Task to delete the path. * We tried it, it didn't work, don't try again in a while. */ GNUNET_SCHEDULER_TaskIdentifier path_delete; }; /******************************************************************************/ /************************* FUNCTIONS *****************************/ /******************************************************************************/ /** * Create a new path. * * @param length How many hops will the path have. * * @return A newly allocated path with a peer array of the specified length. */ struct MeshPeerPath * path_new (unsigned int length); /** * Invert the path. * * @param path The path to invert. */ void path_invert (struct MeshPeerPath *path); /** * Duplicate a path, incrementing short peer's rc. * * @param path The path to duplicate. */ struct MeshPeerPath * path_duplicate (const struct MeshPeerPath *path); /** * Get the length of a path. * * @param path The path to measure, with the local peer at any point of it. * * @return Number of hops to reach destination. * UINT_MAX in case the peer is not in the path. */ unsigned int path_get_length (struct MeshPeerPath *path); /** * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop. * * DHT_get sometimes returns bad cached results, for instance, on a locally * cached result where the PUT followed a path that is no longer current. * * @param p Path to invalidate. */ void path_invalidate (struct MeshPeerPath *p); /** * Test if a path is valid (or at least not known to be invalid). * * @param path Path to test. * * @return #GNUNET_YES If the path is valid or unknown, * #GNUNET_NO If the path is known to be invalid. */ int path_is_valid (const struct MeshPeerPath *path); /** * Destroy the path and free any allocated resources linked to it * * @param p the path to destroy * * @return GNUNET_OK on success */ int path_destroy (struct MeshPeerPath *p); /** * Path -> allocated one line string. Caller must free. * * @param p Path. */ char * path_2s (struct MeshPeerPath *p); /** * Print info about the path for debug. * * @param p Path to debug. */ void path_debug (struct MeshPeerPath *p); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef MESH_PATH_H */ #endif gnunet-0.10.1/src/mesh/mesh.conf.in0000644000175000017500000000076212306275771013764 00000000000000[mesh] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2096 HOSTNAME = localhost BINARY = gnunet-service-mesh ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-mesh.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES REFRESH_CONNECTION_TIME = 5 min ID_ANNOUNCE_TIME = 1 h APP_ANNOUNCE_TIME = 1 h CONNECT_TIMEOUT = 30 s DEFAULT_TTL = 64 DHT_REPLICATION_LEVEL = 3 MAX_TUNNELS = 1000 # MAX_TUNNELS deprecated MAX_CONNECTIONS = 1000 MAX_MSGS_QUEUE = 10000 MAX_PEERS = 1000 gnunet-0.10.1/src/mesh/gnunet-service-mesh_hello.h0000644000175000017500000000346412274707232016776 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh_hello.h * @brief mesh service; dealing with hello messages * @author Bartlomiej Polot * * All functions in this file should use the prefix GMH (Gnunet Mesh Hello) */ #ifndef GNUNET_SERVICE_MESH_HELLO_H #define GNUNET_SERVICE_MESH_HELLO_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" /** * Initialize the hello subsystem. * * @param c Configuration. */ void GMH_init (const struct GNUNET_CONFIGURATION_Handle *c); /** * Shut down the hello subsystem. */ void GMH_shutdown (); /** * Get own hello message. * * @return Own hello message. */ const struct GNUNET_HELLO_Message * GMH_get_mine (void); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_MESH_SERVICE_HELLO_H */ #endif /* end of gnunet-mesh-service_hello.h */ gnunet-0.10.1/src/mesh/mesh.h0000644000175000017500000001736712320526362012661 00000000000000/* This file is part of GNUnet. (C) 2001 - 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Bartlomiej Polot * @file mesh/mesh.h */ #ifndef MESH_H_ #define MESH_H_ #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include #define MESH_DEBUG GNUNET_YES #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_peer_lib.h" #include "gnunet_core_service.h" #include "gnunet_protocols.h" #include /******************************************************************************/ /************************** CONSTANTS ******************************/ /******************************************************************************/ #define GNUNET_MESH_LOCAL_CHANNEL_ID_CLI 0x80000000 #define GNUNET_MESH_LOCAL_CHANNEL_ID_SERV 0xB0000000 #define HIGH_PID 0xFFFF0000 #define LOW_PID 0x0000FFFF #define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID) /******************************************************************************/ /************************** MESSAGES ******************************/ /******************************************************************************/ GNUNET_NETWORK_STRUCT_BEGIN /** * Message for a client to register to the service */ struct GNUNET_MESH_ClientConnect { /** * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT * * Size: sizeof(struct GNUNET_MESH_ClientConnect) + * sizeof(MESH_ApplicationType) * applications + * sizeof(uint16_t) * types */ struct GNUNET_MessageHeader header; /* uint32_t list_ports[] */ }; /** * Type for channel numbering. * - Local channel numbers given by the service (incoming) are >= 0xB0000000 * - Local channel numbers given by the client (created) are >= 0x80000000 * - Global channel numbers are < 0x80000000 */ typedef uint32_t MESH_ChannelNumber; /** * Message for a client to create and destroy channels. */ struct GNUNET_MESH_ChannelMessage { /** * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY] * * Size: sizeof(struct GNUNET_MESH_ChannelMessage) */ struct GNUNET_MessageHeader header; /** * ID of a channel controlled by this client. */ MESH_ChannelNumber channel_id GNUNET_PACKED; /** * Channel's peer */ struct GNUNET_PeerIdentity peer; /** * Port of the channel. */ uint32_t port GNUNET_PACKED; /** * Options. */ uint32_t opt GNUNET_PACKED; }; /** * Message for mesh data traffic. */ struct GNUNET_MESH_LocalData { /** * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA */ struct GNUNET_MessageHeader header; /** * ID of the channel */ uint32_t id GNUNET_PACKED; /** * Payload follows */ }; /** * Message to allow the client send more data to the service * (always service -> client). */ struct GNUNET_MESH_LocalAck { /** * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK */ struct GNUNET_MessageHeader header; /** * ID of the channel allowed to send more data. */ MESH_ChannelNumber channel_id GNUNET_PACKED; }; /** * Message to inform the client about channels in the service. */ struct GNUNET_MESH_LocalInfo { /** * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO[_TUNNEL,_PEER] */ struct GNUNET_MessageHeader header; /** * ID of the channel allowed to send more data. */ MESH_ChannelNumber channel_id GNUNET_PACKED; /** * ID of the owner of the channel (can be local peer). */ // struct GNUNET_PeerIdentity owner; /** * ID of the destination of the channel (can be local peer). */ struct GNUNET_PeerIdentity peer; }; /** * Message to inform the client about one of the peers in the service. */ struct GNUNET_MESH_LocalInfoPeer { /** * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEER[S] */ struct GNUNET_MessageHeader header; /** * Number of paths. */ uint16_t paths GNUNET_PACKED; /** * Do we have a tunnel toward this peer? */ int16_t tunnel GNUNET_PACKED; /** * ID of the destination of the tunnel (can be local peer). */ struct GNUNET_PeerIdentity destination; /* If type == PEER (no 'S'): GNUNET_PeerIdentity paths[] * (each path ends in destination) */ }; /** * Message to inform the client about one of the tunnels in the service. */ struct GNUNET_MESH_LocalInfoTunnel { /** * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL[S] */ struct GNUNET_MessageHeader header; /** * Number of channels. */ uint32_t channels GNUNET_PACKED; /** * ID of the destination of the tunnel (can be local peer). */ struct GNUNET_PeerIdentity destination; /** * Number of connections. */ uint32_t connections GNUNET_PACKED; /** * Encryption state. */ uint16_t estate GNUNET_PACKED; /** * Connection state. */ uint16_t cstate GNUNET_PACKED; /* If TUNNEL (no 'S'): GNUNET_PeerIdentity connection_ids[connections] */ /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */ }; GNUNET_NETWORK_STRUCT_END /** * @brief Translate a fwd variable into a string representation, for logging. * * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO) * * @return String representing FWD or BCK. */ char * GM_f2s (int fwd); /** * Check if one pid is bigger than other, accounting for overflow. * * @param bigger Argument that should be bigger. * @param smaller Argument that should be smaller. * * @return True if bigger (arg1) has a higher value than smaller (arg 2). */ int GM_is_pid_bigger (uint32_t bigger, uint32_t smaller); /** * Get the higher ACK value out of two values, taking in account overflow. * * @param a First ACK value. * @param b Second ACK value. * * @return Highest ACK value from the two. */ uint32_t GM_max_pid (uint32_t a, uint32_t b); /** * Get the lower ACK value out of two values, taking in account overflow. * * @param a First ACK value. * @param b Second ACK value. * * @return Lowest ACK value from the two. */ uint32_t GM_min_pid (uint32_t a, uint32_t b); /** * Convert a 256 bit MeshHash into a 512 HashCode to use in GNUNET_h2s, * multihashmap, and other HashCode-based functions. * * @param id A 256 bit hash to expand. * * @return A HashCode containing the original 256 bit hash right-padded with 0. */ const struct GNUNET_HashCode * GM_h2hc (const struct GNUNET_MESH_Hash *id); /** * Get a string from a Mesh Hash (256 bits). * WARNING: Not reentrant (based on GNUNET_h2s). */ const char * GM_h2s (const struct GNUNET_MESH_Hash *id); /** * Convert a message type into a string to help debug * Generated with: * FIND: "#define ([^ ]+)[ ]*([0-9]+)" * REPLACE: " case \2: return "\1"; break;" * * @param m Message type. * * @return Human readable string description. */ const char * GM_m2s (uint16_t m); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/mesh/mesh_protocol.h0000644000175000017500000002131712320526362014570 00000000000000/* This file is part of GNUnet. (C) 2001 - 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Bartlomiej Polot * @file mesh/mesh_protocol.h */ #ifndef MESH_PROTOCOL_H_ #define MESH_PROTOCOL_H_ #include "platform.h" #include "gnunet_util_lib.h" #include "mesh.h" #ifdef __cplusplus struct GNUNET_MESH_TunnelMessage; extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /******************************************************************************/ /******************** MESH NETWORK MESSAGES **************************/ /******************************************************************************/ GNUNET_NETWORK_STRUCT_BEGIN /** * Message for mesh connection creation. */ struct GNUNET_MESH_ConnectionCreate { /** * Type: GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE * * Size: sizeof (struct GNUNET_MESH_ConnectionCreate) + * path_length * sizeof (struct GNUNET_PeerIdentity) */ struct GNUNET_MessageHeader header; /** * ID of the connection */ struct GNUNET_MESH_Hash cid; /** * path_length structs defining the *whole* path from the origin [0] to the * final destination [path_length-1]. */ /* struct GNUNET_PeerIdentity peers[path_length]; */ }; /** * Message for ack'ing a connection */ struct GNUNET_MESH_ConnectionACK { /** * Type: GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK */ struct GNUNET_MessageHeader header; /** * ID of the connection. */ struct GNUNET_MESH_Hash cid; }; /** * Message for encapsulation of a Key eXchange message in a connection. */ struct GNUNET_MESH_KX { /** * Type: GNUNET_MESSAGE_TYPE_MESH_KX. */ struct GNUNET_MessageHeader header; /** * ID of the connection. */ struct GNUNET_MESH_Hash cid; /* Specific KX message follows. */ }; /** * Message transmitted with the signed ephemeral key of a peer. The * session key is then derived from the two ephemeral keys (ECDHE). * * As far as possible, same as CORE's EphemeralKeyMessage. */ struct GNUNET_MESH_KX_Ephemeral { /** * Message type is GNUNET_MESSAGE_TYPE_MESH_KX_EPHEMERAL. */ struct GNUNET_MessageHeader header; /** * Status of the sender (should be in "enum PeerStateMachine"), nbo. */ int32_t sender_status GNUNET_PACKED; /** * An ECC signature of the 'origin' asserting the validity of * the given ephemeral key. */ struct GNUNET_CRYPTO_EddsaSignature signature; /** * Information about what is being signed. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * At what time was this key created (beginning of validity). */ struct GNUNET_TIME_AbsoluteNBO creation_time; /** * When does the given ephemeral key expire (end of validity). */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * Ephemeral public ECC key (always for NIST P-521) encoded in a format suitable * for network transmission as created using 'gcry_sexp_sprint'. */ struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; /** * Public key of the signing peer (persistent version, not the ephemeral public key). */ struct GNUNET_PeerIdentity origin_identity; }; /** * We're sending an (encrypted) PING to the other peer to check if he * can decrypt. The other peer should respond with a PONG with the * same content, except this time encrypted with the receiver's key. */ struct GNUNET_MESH_KX_Ping { /** * Message type is GNUNET_MESSAGE_TYPE_MESH_KX_PING. */ struct GNUNET_MessageHeader header; /** * Seed for the IV */ uint32_t iv GNUNET_PACKED; /** * Intended target of the PING, used primarily to check * that decryption actually worked. */ struct GNUNET_PeerIdentity target; /** * Random number chosen to make reply harder. */ uint32_t nonce GNUNET_PACKED; }; /** * Response to a PING. Includes data from the original PING. */ struct GNUNET_MESH_KX_Pong { /** * Message type is GNUNET_MESSAGE_TYPE_MESH_KX_PONG. */ struct GNUNET_MessageHeader header; /** * Seed for the IV */ uint32_t iv GNUNET_PACKED; /** * Same nonce as in the reve. */ uint32_t nonce GNUNET_PACKED; }; /** * Tunnel(ed) message. */ struct GNUNET_MESH_Encrypted { /** * Type: GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED */ struct GNUNET_MessageHeader header; /** * ID of the connection. */ struct GNUNET_MESH_Hash cid; /** * ID of the packet (hop by hop). */ uint32_t pid GNUNET_PACKED; /** * Number of hops to live. */ uint32_t ttl GNUNET_PACKED; /** * Initialization Vector for payload encryption. */ uint32_t iv GNUNET_PACKED; /** * MAC of the encrypted message, used to verify message integrity. * Everything after this value will be encrypted and authenticated. */ struct GNUNET_MESH_Hash hmac; /** * Encrypted content follows. */ }; /** * Message to create a Channel. */ struct GNUNET_MESH_ChannelCreate { /** * Type: GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE */ struct GNUNET_MessageHeader header; /** * ID of the channel */ MESH_ChannelNumber chid GNUNET_PACKED; /** * Destination port. */ uint32_t port GNUNET_PACKED; /** * Channel options. */ uint32_t opt GNUNET_PACKED; }; /** * Message to manage a Channel (ACK, NACK, Destroy). */ struct GNUNET_MESH_ChannelManage { /** * Type: GNUNET_MESSAGE_TYPE_MESH_CHANNEL_{ACK|NACK|DESTROY} */ struct GNUNET_MessageHeader header; /** * ID of the channel */ MESH_ChannelNumber chid GNUNET_PACKED; }; /** * Message for mesh data traffic. */ struct GNUNET_MESH_Data { /** * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST, * GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN */ struct GNUNET_MessageHeader header; /** * Unique ID of the payload message */ uint32_t mid GNUNET_PACKED; /** * ID of the channel */ MESH_ChannelNumber chid GNUNET_PACKED; /** * Payload follows */ }; /** * Message to acknowledge end-to-end data. */ struct GNUNET_MESH_DataACK { /** * Type: GNUNET_MESSAGE_TYPE_MESH_DATA_ACK */ struct GNUNET_MessageHeader header; /** * ID of the channel */ MESH_ChannelNumber chid GNUNET_PACKED; /** * Bitfield of already-received newer messages * pid + 1 @ LSB * pid + 64 @ MSB */ uint64_t futures GNUNET_PACKED; /** * Last message ID received. */ uint32_t mid GNUNET_PACKED; }; /** * Message to acknowledge mesh encrypted traffic. */ struct GNUNET_MESH_ACK { /** * Type: GNUNET_MESSAGE_TYPE_MESH_ACK */ struct GNUNET_MessageHeader header; /** * Maximum packet ID authorized. */ uint32_t ack GNUNET_PACKED; /** * ID of the connection. */ struct GNUNET_MESH_Hash cid; }; /** * Message to query a peer about its Flow Control status regarding a tunnel. */ struct GNUNET_MESH_Poll { /** * Type: GNUNET_MESSAGE_TYPE_MESH_POLL */ struct GNUNET_MessageHeader header; /** * Last packet sent. */ uint32_t pid GNUNET_PACKED; /** * ID of the connection. */ struct GNUNET_MESH_Hash cid; }; /** * Message for notifying a disconnection in a path */ struct GNUNET_MESH_ConnectionBroken { /** * Type: GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN */ struct GNUNET_MessageHeader header; /** * ID of the connection. */ struct GNUNET_MESH_Hash cid; /** * ID of the endpoint */ struct GNUNET_PeerIdentity peer1; /** * ID of the endpoint */ struct GNUNET_PeerIdentity peer2; }; /** * Message to destroy a connection. */ struct GNUNET_MESH_ConnectionDestroy { /** * Type: GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY */ struct GNUNET_MessageHeader header; /** * ID of the connection. */ struct GNUNET_MESH_Hash cid; }; GNUNET_NETWORK_STRUCT_END #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef MESH_PROTOCOL_H */ #endif /* end of mesh_protocol.h */ gnunet-0.10.1/src/mesh/Makefile.am0000644000175000017500000001321012320754720013570 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ mesh.conf plugindir = $(libdir)/gnunet AM_CLFAGS = -g libexec_PROGRAMS = \ gnunet-service-mesh $(EXP_LIBEXEC) bin_PROGRAMS = \ gnunet-mesh lib_LTLIBRARIES = \ libgnunetmesh.la $(EXP_LIB) libgnunetmesh_la_SOURCES = \ mesh_api.c mesh_common.c libgnunetmesh_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) \ $(LTLIBINTL) libgnunetmesh_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 5:0:0 gnunet_mesh_SOURCES = \ gnunet-mesh.c gnunet_mesh_LDADD = \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_mesh_DEPENDENCIES = \ libgnunetmesh.la gnunet_service_mesh_SOURCES = \ gnunet-service-mesh_tunnel.c gnunet-service-mesh_tunnel.h \ gnunet-service-mesh_connection.c gnunet-service-mesh_connection.h \ gnunet-service-mesh_channel.c gnunet-service-mesh_channel.h \ gnunet-service-mesh_local.c gnunet-service-mesh_local.h \ gnunet-service-mesh_peer.c gnunet-service-mesh_peer.h \ gnunet-service-mesh_dht.c gnunet-service-mesh_dht.h \ gnunet-service-mesh_hello.c gnunet-service-mesh_hello.h \ mesh_path.c mesh_path.h \ mesh_common.c \ gnunet-service-mesh.c gnunet_service_mesh_CFLAGS = $(AM_CFLAGS) gnunet_service_mesh_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la gnunet_service_mesh_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la if LINUX gnunet_service_mesh_LDFLAGS = -lrt endif if HAVE_TESTING noinst_LIBRARIES = libgnunetmeshtest.a $(noinst_LIB_EXP) noinst_PROGRAMS = gnunet-mesh-profiler endif libgnunetmeshtest_a_SOURCES = \ mesh_test_lib.c mesh_test_lib.h libgnunetmeshtest_a_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/mesh/libgnunetmesh.la libgnunetmeshtest_a_DEPENDENCIES = \ libgnunetmesh.la if HAVE_TESTING check_PROGRAMS = \ test_mesh_single \ test_mesh_local \ test_mesh_small_forward \ test_mesh_small_signal \ test_mesh_small_keepalive \ test_mesh_small_speed \ test_mesh_small_speed_ack \ test_mesh_small_speed_backwards \ test_mesh_small_speed_reliable \ test_mesh_small_speed_reliable_backwards endif ld_mesh_test_lib = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/mesh/libgnunetmeshtest.a \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la dep_mesh_test_lib = \ libgnunetmesh.la \ libgnunetmeshtest.a \ $(top_builddir)/src/statistics/libgnunetstatistics.la gnunet_mesh_profiler_SOURCES = \ gnunet-mesh-profiler.c gnunet_mesh_profiler_LDADD = $(ld_mesh_test_lib) gnunet_mesh_profiler_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_single_SOURCES = \ test_mesh_single.c test_mesh_single_LDADD = $(ld_mesh_test_lib) test_mesh_single_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_local_SOURCES = \ test_mesh_local.c test_mesh_local_LDADD = $(ld_mesh_test_lib) test_mesh_local_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_forward_SOURCES = \ test_mesh_small.c test_mesh_small_forward_LDADD = $(ld_mesh_test_lib) test_mesh_small_forward_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_signal_SOURCES = \ test_mesh_small.c test_mesh_small_signal_LDADD = $(ld_mesh_test_lib) test_mesh_small_signal_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_keepalive_SOURCES = \ test_mesh_small.c test_mesh_small_keepalive_LDADD = $(ld_mesh_test_lib) test_mesh_small_keepalive_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_SOURCES = \ test_mesh_small.c test_mesh_small_speed_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_ack_SOURCES = \ test_mesh_small.c test_mesh_small_speed_ack_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_ack_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_backwards_SOURCES = \ test_mesh_small.c test_mesh_small_speed_backwards_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_backwards_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_reliable_SOURCES = \ test_mesh_small.c test_mesh_small_speed_reliable_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_reliable_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_reliable_backwards_SOURCES = \ test_mesh_small.c test_mesh_small_speed_reliable_backwards_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_reliable_backwards_DEPENDENCIES = $(dep_mesh_test_lib) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ $(check_PROGRAMS) endif EXTRA_DIST = \ mesh.h mesh_protocol.h \ test_mesh.conf \ test_mesh_drop.conf gnunet-0.10.1/src/mesh/gnunet-service-mesh.c0000644000175000017500000001222712316473376015611 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh.c * @brief GNUnet MESH service with encryption * @author Bartlomiej Polot * * FIXME in progress: * - rekey - reliability interaction * - channel retransmit timing * * TODO: * - relay corking down to core * - set ttl relative to path length * TODO END * * Dictionary: * - peer: other mesh instance. If there is direct connection it's a neighbor. * - tunnel: encrypted connection to a peer, neighbor or not. * - channel: connection between two clients, on the same or different peers. * have properties like reliability. * - path: series of directly connected peer from one peer to another. * - connection: path which is being used in a tunnel. */ #include "platform.h" #include "gnunet_util_lib.h" #include "mesh.h" #include "gnunet_statistics_service.h" #include "gnunet-service-mesh_local.h" #include "gnunet-service-mesh_channel.h" #include "gnunet-service-mesh_connection.h" #include "gnunet-service-mesh_tunnel.h" #include "gnunet-service-mesh_dht.h" #include "gnunet-service-mesh_peer.h" #include "gnunet-service-mesh_hello.h" /******************************************************************************/ /*********************** GLOBAL VARIABLES ****************************/ /******************************************************************************/ /****************************** Global variables ******************************/ /** * Handle to the statistics service. */ struct GNUNET_STATISTICS_Handle *stats; /** * Local peer own ID (memory efficient handle). */ GNUNET_PEER_Id myid; /** * Local peer own ID (full value). */ struct GNUNET_PeerIdentity my_full_id; /** * Signal that shutdown is happening: prevent recover measures. */ int shutting_down; /*************************** Static global variables **************************/ /** * Own private key. */ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; /******************************************************************************/ /************************ MAIN FUNCTIONS ****************************/ /******************************************************************************/ /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n"); shutting_down = GNUNET_YES; GML_shutdown (); GMH_shutdown (); GMC_shutdown (); GMT_shutdown (); GMD_shutdown (); GMP_shutdown (); GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); } /** * Process mesh requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); stats = GNUNET_STATISTICS_create ("mesh", c); /* Scheduled the task to clean up when shutdown is called */ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "reading key\n"); my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); GNUNET_assert (NULL != my_private_key); GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_full_id.public_key); myid = GNUNET_PEER_intern (&my_full_id); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STARTING SERVICE (MESH) for peer [%s]\n", GNUNET_i2s (&my_full_id)); GML_init (server); /* Local clients */ GMH_init (c); /* Hellos */ GMC_init (c); /* Connections */ GMP_init (c); /* Peers */ GMD_init (c); /* DHT */ GMT_init (c, my_private_key); /* Tunnels */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n"); } /** * The main function for the mesh service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; int r; shutting_down = GNUNET_NO; r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run, NULL); GNUNET_free (my_private_key); ret = (GNUNET_OK == r) ? 0 : 1; return ret; } gnunet-0.10.1/src/mesh/test_mesh_local.c0000644000175000017500000002261312272425071015054 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/test_mesh_local.c * @brief test mesh local: test of mesh channels with just one peer * @author Bartlomiej Polot */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dht_service.h" #include "gnunet_testing_lib.h" #include "gnunet_mesh_service.h" struct GNUNET_TESTING_Peer *me; static struct GNUNET_MESH_Handle *mesh_peer_1; static struct GNUNET_MESH_Handle *mesh_peer_2; static struct GNUNET_MESH_Channel *ch; static int result = GNUNET_OK; static int got_data = GNUNET_NO; static GNUNET_SCHEDULER_TaskIdentifier abort_task; static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; static struct GNUNET_MESH_TransmitHandle *mth; /** * Connect to other client and send data * * @param cls Closue (unused). * @param tc TaskContext. */ static void do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Shutdown nicely */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n"); if (GNUNET_SCHEDULER_NO_TASK != abort_task) { GNUNET_SCHEDULER_cancel (abort_task); } if (NULL != ch) { GNUNET_MESH_channel_destroy (ch); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n"); if (NULL != mesh_peer_1) { GNUNET_MESH_disconnect (mesh_peer_1); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n"); if (NULL != mesh_peer_2) { GNUNET_MESH_disconnect (mesh_peer_2); } } /** * Something went wrong and timed out. Kill everything and set error flag */ static void do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n"); result = GNUNET_SYSERR; abort_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) { GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_NO_TASK; } do_shutdown (cls, tc); } /** * Function is called whenever a message is received. * * @param cls closure (set from GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int data_callback (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data callback! Shutting down.\n"); got_data = GNUNET_YES; if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, NULL); GNUNET_MESH_receive_done (channel); return GNUNET_OK; } /** * Method called whenever another peer has added us to a channel * the other peer initiated. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel * @param port port number * @param options channel options * @return initial channel context for the channel * (can be NULL -- that's not an error) */ static void * inbound_channel (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { long id = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received incoming channel on peer %d, port %u\n", id, port); if (id != 2L) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "wrong peer\n"); result = GNUNET_SYSERR; } return NULL; } /** * Function called whenever an channel is destroyed. Should clean up * any associated state. * * @param cls closure (set from GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void channel_end (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { long id = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "incoming channel closed at peer %ld\n", id); if (NULL != mth) { GNUNET_MESH_notify_transmit_ready_cancel (mth); mth = NULL; } if (GNUNET_NO == got_data) { GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( GNUNET_TIME_UNIT_SECONDS, 2), &do_connect, NULL); } } /** * Handler array for traffic received on peer1 */ static struct GNUNET_MESH_MessageHandler handlers1[] = { {&data_callback, 1, 0}, {NULL, 0, 0} }; /** * Handler array for traffic received on peer2 (none expected) */ static struct GNUNET_MESH_MessageHandler handlers2[] = { {&data_callback, 1, 0}, {NULL, 0, 0} }; /** * Data send callback: fillbuffer with test packet. * * @param cls Closure (unused). * @param size Buffer size. * @param buf Buffer to fill. * * @return size of test packet. */ static size_t do_send (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *m = buf; mth = NULL; if (NULL == buf) { GNUNET_break (0); result = GNUNET_SYSERR; return 0; } m->size = htons (sizeof (struct GNUNET_MessageHeader)); m->type = htons (1); GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); return sizeof (struct GNUNET_MessageHeader); } /** * Connect to other client and send data * * @param cls Closue (unused). * @param tc TaskContext. */ static void do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PeerIdentity id; if (NULL != tc && 0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; GNUNET_TESTING_peer_get_identity (me, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n"); ch = GNUNET_MESH_channel_create (mesh_peer_1, NULL, &id, 1, GNUNET_MESH_OPTION_DEFAULT); mth = GNUNET_MESH_notify_transmit_ready (ch, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct GNUNET_MessageHeader), &do_send, NULL); } /** * Initialize framework and start test * * @param cls Closure (unused). * @param cfg Configuration handle. * @param peer Testing peer handle. */ static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { static uint32_t ports[] = {1, 0}; me = peer; abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort, NULL); mesh_peer_1 = GNUNET_MESH_connect (cfg, /* configuration */ (void *) 1L, /* cls */ NULL, /* inbound new hndlr */ &channel_end, /* channel end hndlr */ handlers1, /* traffic handlers */ NULL); /* ports offered */ mesh_peer_2 = GNUNET_MESH_connect (cfg, /* configuration */ (void *) 2L, /* cls */ &inbound_channel, /* inbound new hndlr */ &channel_end, /* channel end hndlr */ handlers2, /* traffic handlers */ ports); /* ports offered */ if (NULL == mesh_peer_1 || NULL == mesh_peer_2) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh :(\n"); result = GNUNET_SYSERR; return; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO MESH :D\n"); } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( GNUNET_TIME_UNIT_SECONDS, 2), &do_connect, NULL); } /** * Main */ int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-mesh-local", "test_mesh.conf", &run, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n"); return 2; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result); return (result == GNUNET_OK) ? 0 : 1; } /* end of test_mesh_local_1.c */ gnunet-0.10.1/src/mesh/gnunet-service-mesh_connection.c0000644000175000017500000024271712320724374020031 00000000000000/* This file is part of GNUnet. (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh_connection.c * @brief GNUnet MESH service connection handling * @author Bartlomiej Polot */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "mesh_path.h" #include "mesh_protocol.h" #include "mesh.h" #include "gnunet-service-mesh_connection.h" #include "gnunet-service-mesh_peer.h" #include "gnunet-service-mesh_tunnel.h" #define LOG(level, ...) GNUNET_log_from (level,"mesh-con",__VA_ARGS__) #define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ GNUNET_TIME_UNIT_MINUTES,\ 10) #define AVG_MSGS 32 /******************************************************************************/ /******************************** STRUCTS **********************************/ /******************************************************************************/ /** * Struct to encapsulate all the Flow Control information to a peer to which * we are directly connected (on a core level). */ struct MeshFlowControl { /** * Connection this controls. */ struct MeshConnection *c; /** * How many messages are in the queue on this connection. */ unsigned int queue_n; /** * How many messages do we accept in the queue. */ unsigned int queue_max; /** * Next ID to use. */ uint32_t next_pid; /** * ID of the last packet sent towards the peer. */ uint32_t last_pid_sent; /** * ID of the last packet received from the peer. */ uint32_t last_pid_recv; /** * Last ACK sent to the peer (peer can't send more than this PID). */ uint32_t last_ack_sent; /** * Last ACK sent towards the origin (for traffic towards leaf node). */ uint32_t last_ack_recv; /** * Task to poll the peer in case of a lost ACK causes stall. */ GNUNET_SCHEDULER_TaskIdentifier poll_task; /** * How frequently to poll for ACKs. */ struct GNUNET_TIME_Relative poll_time; /** * Queued poll message, to cancel if not necessary anymore (got ACK). */ struct MeshConnectionQueue *poll_msg; /** * Queued poll message, to cancel if not necessary anymore (got ACK). */ struct MeshConnectionQueue *ack_msg; }; /** * Keep a record of the last messages sent on this connection. */ struct MeshConnectionPerformance { /** * Circular buffer for storing measurements. */ double usecsperbyte[AVG_MSGS]; /** * Running average of @c usecsperbyte. */ double avg; /** * How many values of @c usecsperbyte are valid. */ uint16_t size; /** * Index of the next "free" position in @c usecsperbyte. */ uint16_t idx; }; /** * Struct containing all information regarding a connection to a peer. */ struct MeshConnection { /** * Tunnel this connection is part of. */ struct MeshTunnel3 *t; /** * Flow control information for traffic fwd. */ struct MeshFlowControl fwd_fc; /** * Flow control information for traffic bck. */ struct MeshFlowControl bck_fc; /** * Measure connection performance on the endpoint. */ struct MeshConnectionPerformance *perf; /** * ID of the connection. */ struct GNUNET_MESH_Hash id; /** * State of the connection. */ enum MeshConnectionState state; /** * Path being used for the tunnel. At the origin of the connection * it's a pointer to the destination's path pool, otherwise just a copy. */ struct MeshPeerPath *path; /** * Position of the local peer in the path. */ unsigned int own_pos; /** * Task to keep the used paths alive at the owner, * time tunnel out on all the other peers. */ GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task; /** * Task to keep the used paths alive at the destination, * time tunnel out on all the other peers. */ GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task; /** * Queue handle for maintainance traffic. One handle for FWD and BCK since * one peer never needs to maintain both directions (no loopback connections). */ struct MeshPeerQueue *maintenance_q; /** * Counter to do exponential backoff when creating a connection (max 64). */ unsigned short create_retry; /** * Pending message count. */ int pending_messages; /** * Destroy flag: if true, destroy on last message. */ int destroy; }; /** * Handle for messages queued but not yet sent. */ struct MeshConnectionQueue { /** * Peer queue handle, to cancel if necessary. */ struct MeshPeerQueue *q; /** * Was this a forced message? (Do not account for it) */ int forced; /** * Continuation to call once sent. */ GMC_sent cont; /** * Closure for @c cont. */ void *cont_cls; }; /******************************************************************************/ /******************************* GLOBALS ***********************************/ /******************************************************************************/ /** * Global handle to the statistics service. */ extern struct GNUNET_STATISTICS_Handle *stats; /** * Local peer own ID (memory efficient handle). */ extern GNUNET_PEER_Id myid; /** * Local peer own ID (full value). */ extern struct GNUNET_PeerIdentity my_full_id; /** * Connections known, indexed by cid (MeshConnection). */ static struct GNUNET_CONTAINER_MultiHashMap *connections; /** * How many connections are we willing to maintain. * Local connections are always allowed, even if there are more connections than max. */ static unsigned long long max_connections; /** * How many messages *in total* are we willing to queue, divide by number of * connections to get connection queue size. */ static unsigned long long max_msgs_queue; /** * How often to send path keepalives. Paths timeout after 4 missed. */ static struct GNUNET_TIME_Relative refresh_connection_time; /** * How often to send path create / ACKs. */ static struct GNUNET_TIME_Relative create_connection_time; /******************************************************************************/ /******************************** STATIC ***********************************/ /******************************************************************************/ #if 0 // avoid compiler warning for unused static function static void fc_debug (struct MeshFlowControl *fc) { LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n", fc->last_pid_recv, fc->last_ack_sent); LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n", fc->last_pid_sent, fc->last_ack_recv); LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n", fc->queue_n, fc->queue_max); } static void connection_debug (struct MeshConnection *c) { if (NULL == c) { LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n"); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n", peer2s (c->t->peer), GMC_2s (c)); LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n", c->state, c->pending_messages); LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); fc_debug (&c->fwd_fc); LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); fc_debug (&c->bck_fc); } #endif /** * Schedule next keepalive task, taking in consideration * the connection state and number of retries. * * @param c Connection for which to schedule the next keepalive. * @param fwd Direction for the next keepalive. */ static void schedule_next_keepalive (struct MeshConnection *c, int fwd); /** * Resets the connection timeout task, some other message has done the * task's job. * - For the first peer on the direction this means to send * a keepalive or a path confirmation message (either create or ACK). * - For all other peers, this means to destroy the connection, * due to lack of activity. * Starts the timeout if no timeout was running (connection just created). * * @param c Connection whose timeout to reset. * @param fwd Is this forward? */ static void connection_reset_timeout (struct MeshConnection *c, int fwd); /** * Get string description for tunnel state. Reentrant. * * @param s Tunnel state. * * @return String representation. */ static const char * GMC_state2s (enum MeshConnectionState s) { switch (s) { case MESH_CONNECTION_NEW: return "MESH_CONNECTION_NEW"; case MESH_CONNECTION_SENT: return "MESH_CONNECTION_SENT"; case MESH_CONNECTION_ACK: return "MESH_CONNECTION_ACK"; case MESH_CONNECTION_READY: return "MESH_CONNECTION_READY"; case MESH_CONNECTION_DESTROYED: return "MESH_CONNECTION_DESTROYED"; default: return "MESH_CONNECTION_STATE_ERROR"; } } /** * Initialize a Flow Control structure to the initial state. * * @param fc Flow Control structure to initialize. */ static void fc_init (struct MeshFlowControl *fc) { fc->next_pid = 0; fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */ fc->last_pid_recv = (uint32_t) -1; fc->last_ack_sent = (uint32_t) 0; fc->last_ack_recv = (uint32_t) 0; fc->poll_task = GNUNET_SCHEDULER_NO_TASK; fc->poll_time = GNUNET_TIME_UNIT_SECONDS; fc->queue_n = 0; fc->queue_max = (max_msgs_queue / max_connections) + 1; } /** * Find a connection. * * @param cid Connection ID. */ static struct MeshConnection * connection_get (const struct GNUNET_MESH_Hash *cid) { return GNUNET_CONTAINER_multihashmap_get (connections, GM_h2hc (cid)); } static void connection_change_state (struct MeshConnection* c, enum MeshConnectionState state) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s state %s -> %s\n", GMC_2s (c), GMC_state2s (c->state), GMC_state2s (state)); if (MESH_CONNECTION_DESTROYED == c->state) { LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n"); return; } c->state = state; if (MESH_CONNECTION_READY == state) c->create_retry = 1; } /** * Callback called when a queued ACK message is sent. * * @param cls Closure (FC). * @param c Connection this message was on. * @param q Queue handler this call invalidates. * @param type Type of message sent. * @param fwd Was this a FWD going message? * @param size Size of the message. */ static void ack_sent (void *cls, struct MeshConnection *c, struct MeshConnectionQueue *q, uint16_t type, int fwd, size_t size) { struct MeshFlowControl *fc = cls; fc->ack_msg = NULL; } /** * Send an ACK on the connection, informing the predecessor about * the available buffer space. Should not be called in case the peer * is origin (no predecessor) in the @c fwd direction. * * Note that for fwd ack, the FWD mean forward *traffic* (root->dest), * the ACK itself goes "back" (dest->root). * * @param c Connection on which to send the ACK. * @param buffer How much space free to advertise? * @param fwd Is this FWD ACK? (Going dest -> root) * @param force Don't optimize out. */ static void send_ack (struct MeshConnection *c, unsigned int buffer, int fwd, int force) { struct MeshFlowControl *next_fc; struct MeshFlowControl *prev_fc; struct GNUNET_MESH_ACK msg; uint32_t ack; int delta; /* If origin, there is no connection to send ACKs. Wrong function! */ if (GMC_is_origin (c, fwd)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "connection %s is origin in %s\n", GMC_2s (c), GM_f2s (fwd)); GNUNET_break (0); return; } next_fc = fwd ? &c->fwd_fc : &c->bck_fc; prev_fc = fwd ? &c->bck_fc : &c->fwd_fc; LOG (GNUNET_ERROR_TYPE_DEBUG, "connection send %s ack on %s\n", GM_f2s (fwd), GMC_2s (c)); /* Check if we need to transmit the ACK. */ delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv; if (3 < delta && buffer < delta && GNUNET_NO == force) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid recv: %u, last ack sent: %u\n", prev_fc->last_pid_recv, prev_fc->last_ack_sent); return; } /* Ok, ACK might be necessary, what PID to ACK? */ ack = prev_fc->last_pid_recv + buffer; LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack); LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid %u, last ack %u, qmax %u, q %u\n", prev_fc->last_pid_recv, prev_fc->last_ack_sent, next_fc->queue_max, next_fc->queue_n); if (ack == prev_fc->last_ack_sent && GNUNET_NO == force) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); return; } /* Check if message is already in queue */ if (NULL != prev_fc->ack_msg) { if (GM_is_pid_bigger (ack, prev_fc->last_ack_sent)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n"); GMC_cancel (prev_fc->ack_msg); /* GMC_cancel triggers ack_sent(), which clears fc->ack_msg */ } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n"); return; } } prev_fc->last_ack_sent = ack; /* Build ACK message and send on connection */ msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK); msg.ack = htonl (ack); msg.cid = c->id; prev_fc->ack_msg = GMC_send_prebuilt_message (&msg.header, c, !fwd, GNUNET_YES, &ack_sent, prev_fc); } /** * Callback called when a queued message is sent. * * Calculates the average time and connection packet tracking. * * @param cls Closure (ConnectionQueue Handle). * @param c Connection this message was on. * @param sent Was it really sent? (Could have been canceled) * @param type Type of message sent. * @param fwd Was this a FWD going message? * @param size Size of the message. * @param wait Time spent waiting for core (only the time for THIS message) */ static void message_sent (void *cls, struct MeshConnection *c, int sent, uint16_t type, int fwd, size_t size, struct GNUNET_TIME_Relative wait) { struct MeshConnectionPerformance *p; struct MeshFlowControl *fc; struct MeshConnectionQueue *q = cls; double usecsperbyte; int forced; LOG (GNUNET_ERROR_TYPE_DEBUG, "connection message_sent\n"); fc = fwd ? &c->fwd_fc : &c->bck_fc; LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s\n", sent ? "" : "not ", GM_f2s (fwd), GM_m2s (type)); LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages); if (NULL != q) { forced = q->forced; if (NULL != q->cont) { LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n"); q->cont (q->cont_cls, c, q, type, fwd, size); } GNUNET_free (q); } else if (type == GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED) { /* If NULL == q and ENCRYPTED == type, message must have been ch_mngmnt */ forced = GNUNET_YES; } else { forced = GNUNET_NO; } c->pending_messages--; if (GNUNET_YES == c->destroy && 0 == c->pending_messages) { LOG (GNUNET_ERROR_TYPE_DEBUG, "! destroying connection!\n"); GMC_destroy (c); return; } /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ switch (type) { case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK: c->maintenance_q = NULL; /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */ if (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE == type || !fwd) schedule_next_keepalive (c, fwd); break; case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED: if (GNUNET_YES == sent) fc->last_pid_sent++; LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n); if (GNUNET_NO == forced) { fc->queue_n--; LOG (GNUNET_ERROR_TYPE_DEBUG, "! accounting pid %u\n", fc->last_pid_sent); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "! forced, Q_N not accounting pid %u\n", fc->last_pid_sent); } if (GNUNET_YES == sent) { GMC_send_ack (c, fwd, GNUNET_NO); connection_reset_timeout (c, fwd); } break; case GNUNET_MESSAGE_TYPE_MESH_POLL: fc->poll_msg = NULL; break; case GNUNET_MESSAGE_TYPE_MESH_ACK: fc->ack_msg = NULL; break; default: break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n"); if (NULL == c->perf) return; /* Only endpoints are interested in timing. */ p = c->perf; usecsperbyte = ((double) wait.rel_value_us) / size; if (p->size == AVG_MSGS) { /* Array is full. Substract oldest value, add new one and store. */ p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS); p->usecsperbyte[p->idx] = usecsperbyte; p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS); } else { /* Array not yet full. Add current value to avg and store. */ p->usecsperbyte[p->idx] = usecsperbyte; p->avg *= p->size; p->avg += p->usecsperbyte[p->idx]; p->size++; p->avg /= p->size; } p->idx = (p->idx + 1) % AVG_MSGS; } /** * Get the previous hop in a connection * * @param c Connection. * * @return Previous peer in the connection. */ static struct MeshPeer * get_prev_hop (const struct MeshConnection *c) { GNUNET_PEER_Id id; LOG (GNUNET_ERROR_TYPE_DEBUG, " get prev hop %s [%u/%u]\n", GMC_2s (c), c->own_pos, c->path->length); if (0 == c->own_pos || c->path->length < 2) id = c->path->peers[0]; else id = c->path->peers[c->own_pos - 1]; LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); return GMP_get_short (id); } /** * Get the next hop in a connection * * @param c Connection. * * @return Next peer in the connection. */ static struct MeshPeer * get_next_hop (const struct MeshConnection *c) { GNUNET_PEER_Id id; LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n", GMC_2s (c), c->own_pos, c->path->length); if ((c->path->length - 1) == c->own_pos || c->path->length < 2) id = c->path->peers[c->path->length - 1]; else id = c->path->peers[c->own_pos + 1]; LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); return GMP_get_short (id); } /** * Get the hop in a connection. * * @param c Connection. * @param fwd Next hop? * * @return Next peer in the connection. */ static struct MeshPeer * get_hop (struct MeshConnection *c, int fwd) { if (fwd) return get_next_hop (c); return get_prev_hop (c); } /** * Is traffic coming from this sender 'FWD' traffic? * * @param c Connection to check. * @param sender Peer identity of neighbor. * * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore * the traffic is 'FWD'. * #GNUNET_NO for BCK. * #GNUNET_SYSERR for errors. */ static int is_fwd (const struct MeshConnection *c, const struct GNUNET_PeerIdentity *sender) { GNUNET_PEER_Id id; id = GNUNET_PEER_search (sender); if (GMP_get_short_id (get_prev_hop (c)) == id) return GNUNET_YES; if (GMP_get_short_id (get_next_hop (c)) == id) return GNUNET_NO; GNUNET_break (0); return GNUNET_SYSERR; } /** * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE * or a first CONNECTION_ACK directed to us. * * @param connection Connection to confirm. * @param fwd Should we send it FWD? (root->dest) * (First (~SYNACK) goes BCK, second (~ACK) goes FWD) */ static void send_connection_ack (struct MeshConnection *connection, int fwd) { struct MeshTunnel3 *t; t = connection->t; LOG (GNUNET_ERROR_TYPE_INFO, "=> {%18s ACK} on connection %s\n", GM_f2s (!fwd), GMC_2s (connection)); GMP_queue_add (get_hop (connection, fwd), NULL, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK, sizeof (struct GNUNET_MESH_ConnectionACK), connection, fwd, &message_sent, NULL); connection->pending_messages++; if (MESH_TUNNEL3_NEW == GMT_get_cstate (t)) GMT_change_cstate (t, MESH_TUNNEL3_WAITING); if (MESH_CONNECTION_READY != connection->state) connection_change_state (connection, MESH_CONNECTION_SENT); } /** * Send a notification that a connection is broken. * * @param c Connection that is broken. * @param id1 Peer that has disconnected. * @param id2 Peer that has disconnected. * @param fwd Direction towards which to send it. */ static void send_broken (struct MeshConnection *c, const struct GNUNET_PeerIdentity *id1, const struct GNUNET_PeerIdentity *id2, int fwd) { struct GNUNET_MESH_ConnectionBroken msg; msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN); msg.cid = c->id; msg.peer1 = *id1; msg.peer2 = *id2; GMC_send_prebuilt_message (&msg.header, c, fwd, GNUNET_YES, NULL, NULL); } /** * Send a notification that a connection is broken, when a connection * isn't even created. * * @param connection_id Connection ID. * @param id1 Peer that has disconnected. * @param id2 Peer that has disconnected. * @param peer Peer to notify (neighbor who sent the connection). */ static void send_broken2 (struct GNUNET_MESH_Hash *connection_id, const struct GNUNET_PeerIdentity *id1, const struct GNUNET_PeerIdentity *id2, GNUNET_PEER_Id peer_id) { struct GNUNET_MESH_ConnectionBroken *msg; struct MeshPeer *neighbor; LOG (GNUNET_ERROR_TYPE_INFO, "=> BROKEN on unknown connection %s\n", GNUNET_h2s (GM_h2hc (connection_id))); msg = GNUNET_new (struct GNUNET_MESH_ConnectionBroken); msg->header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN); msg->cid = *connection_id; msg->peer1 = *id1; msg->peer2 = *id2; neighbor = GMP_get_short (peer_id); GMP_queue_add (neighbor, msg, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN, sizeof (struct GNUNET_MESH_ConnectionBroken), NULL, GNUNET_SYSERR, /* connection, fwd */ NULL, NULL); /* continuation */ } /** * Send keepalive packets for a connection. * * @param c Connection to keep alive.. * @param fwd Is this a FWD keepalive? (owner -> dest). */ static void send_connection_keepalive (struct MeshConnection *c, int fwd) { struct GNUNET_MessageHeader msg; struct MeshFlowControl *fc; LOG (GNUNET_ERROR_TYPE_INFO, "keepalive %s for connection %s\n", GM_f2s (fwd), GMC_2s (c)); fc = fwd ? &c->fwd_fc : &c->bck_fc; if (0 < fc->queue_n) { LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n"); } GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO); GNUNET_assert (NULL != c->t); msg.size = htons (sizeof (msg)); msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE); GNUNET_assert (NULL == GMT_send_prebuilt_message (&msg, c->t, c, GNUNET_NO, NULL, NULL)); } /** * Send CONNECTION_{CREATE/ACK} packets for a connection. * * @param c Connection for which to send the message. * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK. */ static void connection_recreate (struct MeshConnection *c, int fwd) { LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n"); if (fwd) GMC_send_create (c); else send_connection_ack (c, GNUNET_NO); } /** * Generic connection timer management. * Depending on the role of the peer in the connection will send the * appropriate message (build or keepalive) * * @param c Conncetion to maintain. * @param fwd Is FWD? */ static void connection_maintain (struct MeshConnection *c, int fwd) { if (GNUNET_NO != c->destroy) return; if (MESH_TUNNEL3_SEARCHING == GMT_get_cstate (c->t)) { /* TODO DHT GET with RO_BART */ return; } switch (c->state) { case MESH_CONNECTION_NEW: GNUNET_break (0); /* fall-through */ case MESH_CONNECTION_SENT: connection_recreate (c, fwd); break; case MESH_CONNECTION_READY: send_connection_keepalive (c, fwd); break; default: break; } } /** * Keep the connection alive. * * @param c Connection to keep alive. * @param fwd Direction. * @param shutdown Are we shutting down? (Don't send traffic) * Non-zero value for true, not necessarily GNUNET_YES. */ static void connection_keepalive (struct MeshConnection *c, int fwd, int shutdown) { LOG (GNUNET_ERROR_TYPE_DEBUG, "%s keepalive for %s\n", GM_f2s (fwd), GMC_2s (c)); if (fwd) c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK; else c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_NO != shutdown) return; connection_maintain (c, fwd); /* Next execution will be scheduled by message_sent */ } /** * Keep the connection alive in the FWD direction. * * @param cls Closure (connection to keepalive). * @param tc TaskContext. */ static void connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { connection_keepalive ((struct MeshConnection *) cls, GNUNET_YES, tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN); } /** * Keep the connection alive in the BCK direction. * * @param cls Closure (connection to keepalive). * @param tc TaskContext. */ static void connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { connection_keepalive ((struct MeshConnection *) cls, GNUNET_NO, tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN); } /** * Schedule next keepalive task, taking in consideration * the connection state and number of retries. * * If the peer is not the origin, do nothing. * * @param c Connection for which to schedule the next keepalive. * @param fwd Direction for the next keepalive. */ static void schedule_next_keepalive (struct MeshConnection *c, int fwd) { struct GNUNET_TIME_Relative delay; GNUNET_SCHEDULER_TaskIdentifier *task_id; GNUNET_SCHEDULER_Task keepalive_task; if (GNUNET_NO == GMC_is_origin (c, fwd)) return; /* Calculate delay to use, depending on the state of the connection */ if (MESH_CONNECTION_READY == c->state) { delay = refresh_connection_time; } else { if (1 > c->create_retry) c->create_retry = 1; delay = GNUNET_TIME_relative_multiply (create_connection_time, c->create_retry); if (c->create_retry < 64) c->create_retry *= 2; } /* Select direction-dependent parameters */ if (GNUNET_YES == fwd) { task_id = &c->fwd_maintenance_task; keepalive_task = &connection_fwd_keepalive; } else { task_id = &c->bck_maintenance_task; keepalive_task = &connection_bck_keepalive; } /* Check that no one scheduled it before us */ if (GNUNET_SCHEDULER_NO_TASK != *task_id) { /* No need for a _break. It can happen for instance when sending a SYNACK * for a duplicate SYN: the first SYNACK scheduled the task. */ GNUNET_SCHEDULER_cancel (*task_id); } /* Schedule the task */ *task_id = GNUNET_SCHEDULER_add_delayed (delay, keepalive_task, c); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "next keepalive in %s\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); } /** * @brief Re-initiate traffic on this connection if necessary. * * Check if there is traffic queued towards this peer * and the core transmit handle is NULL (traffic was stalled). * If so, call core tmt rdy. * * @param c Connection on which initiate traffic. * @param fwd Is this about fwd traffic? */ static void connection_unlock_queue (struct MeshConnection *c, int fwd) { struct MeshPeer *peer; LOG (GNUNET_ERROR_TYPE_DEBUG, "connection_unlock_queue %s on %s\n", GM_f2s (fwd), GMC_2s (c)); if (GMC_is_terminal (c, fwd)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n"); return; } peer = get_hop (c, fwd); GMP_queue_unlock (peer, c); } /** * Cancel all transmissions that belong to a certain connection. * * If the connection is scheduled for destruction and no more messages are left, * the connection will be destroyed by the continuation call. * * @param c Connection which to cancel. Might be destroyed during this call. * @param fwd Cancel fwd traffic? */ static void connection_cancel_queues (struct MeshConnection *c, int fwd) { struct MeshFlowControl *fc; struct MeshPeer *peer; LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Cancel %s queues for connection %s\n", GM_f2s (fwd), GMC_2s (c)); if (NULL == c) { GNUNET_break (0); return; } fc = fwd ? &c->fwd_fc : &c->bck_fc; if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task) { GNUNET_SCHEDULER_cancel (fc->poll_task); fc->poll_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Cancel POLL in ccq for fc %p\n", fc); } peer = get_hop (c, fwd); GMP_queue_cancel (peer, c); } /** * Function called if a connection has been stalled for a while, * possibly due to a missed ACK. Poll the neighbor about its ACK status. * * @param cls Closure (poll ctx). * @param tc TaskContext. */ static void connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Callback called when a queued POLL message is sent. * * @param cls Closure (FC). * @param c Connection this message was on. * @param q Queue handler this call invalidates. * @param type Type of message sent. * @param fwd Was this a FWD going message? * @param size Size of the message. */ static void poll_sent (void *cls, struct MeshConnection *c, struct MeshConnectionQueue *q, uint16_t type, int fwd, size_t size) { struct MeshFlowControl *fc = cls; if (2 == c->destroy) { LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n"); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL sent for , scheduling new one!\n"); fc->poll_msg = NULL; fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, &connection_poll, fc); LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task); } /** * Function called if a connection has been stalled for a while, * possibly due to a missed ACK. Poll the neighbor about its ACK status. * * @param cls Closure (poll ctx). * @param tc TaskContext. */ static void connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshFlowControl *fc = cls; struct GNUNET_MESH_Poll msg; struct MeshConnection *c; fc->poll_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { return; } c = fc->c; LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%s]\n", GMC_2s (c)); LOG (GNUNET_ERROR_TYPE_DEBUG, " *** %s\n", fc == &c->fwd_fc ? "FWD" : "BCK"); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL); msg.header.size = htons (sizeof (msg)); msg.pid = htonl (fc->last_pid_sent); LOG (GNUNET_ERROR_TYPE_DEBUG, " *** last pid sent: %u!\n", fc->last_pid_sent); fc->poll_msg = GMC_send_prebuilt_message (&msg.header, c, fc == &c->fwd_fc, GNUNET_YES, &poll_sent, fc); } /** * Timeout function due to lack of keepalive/traffic from the owner. * Destroys connection if called. * * @param cls Closure (connection to destroy). * @param tc TaskContext. */ static void connection_fwd_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshConnection *c = cls; c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s FWD timed out. Destroying.\n", GMC_2s (c)); if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */ { GNUNET_break (0); return; } GMC_destroy (c); } /** * Timeout function due to lack of keepalive/traffic from the destination. * Destroys connection if called. * * @param cls Closure (connection to destroy). * @param tc TaskContext */ static void connection_bck_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MeshConnection *c = cls; c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s BCK timed out. Destroying.\n", GMC_2s (c)); if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */ { GNUNET_break (0); return; } GMC_destroy (c); } /** * Resets the connection timeout task, some other message has done the * task's job. * - For the first peer on the direction this means to send * a keepalive or a path confirmation message (either create or ACK). * - For all other peers, this means to destroy the connection, * due to lack of activity. * Starts the timeout if no timeout was running (connection just created). * * @param c Connection whose timeout to reset. * @param fwd Is this forward? * * TODO use heap to improve efficiency of scheduler. */ static void connection_reset_timeout (struct MeshConnection *c, int fwd) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GM_f2s (fwd)); if (GMC_is_origin (c, fwd)) /* Startpoint */ { schedule_next_keepalive (c, fwd); } else /* Relay, endpoint. */ { struct GNUNET_TIME_Relative delay; GNUNET_SCHEDULER_TaskIdentifier *ti; GNUNET_SCHEDULER_Task f; ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task; if (GNUNET_SCHEDULER_NO_TASK != *ti) GNUNET_SCHEDULER_cancel (*ti); delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4); f = fwd ? &connection_fwd_timeout : &connection_bck_timeout; *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c); } } /** * Add the connection to the list of both neighbors. * * @param c Connection. * * @return #GNUNET_OK if everything went fine * #GNUNET_SYSERR if the was an error and @c c is malformed. */ static int register_neighbors (struct MeshConnection *c) { struct MeshPeer *next_peer; struct MeshPeer *prev_peer; next_peer = get_next_hop (c); prev_peer = get_prev_hop (c); LOG (GNUNET_ERROR_TYPE_DEBUG, "register neighbors for connection %s\n", GMC_2s (c)); path_debug (c->path); LOG (GNUNET_ERROR_TYPE_DEBUG, "own pos %u\n", c->own_pos); LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to next peer %p\n", GMC_2s (c), next_peer); LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n", next_peer, GMP_2s (next_peer)); LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to prev peer %p\n", GMC_2s (c), prev_peer); LOG (GNUNET_ERROR_TYPE_DEBUG, "prev peer %p %s\n", prev_peer, GMP_2s (prev_peer)); if (GNUNET_NO == GMP_is_neighbor (next_peer) || GNUNET_NO == GMP_is_neighbor (prev_peer)) { if (GMC_is_origin (c, GNUNET_YES)) GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO); GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, " register neighbors failed\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " prev: %s, neighbor?: %d\n", GMP_2s (prev_peer), GMP_is_neighbor (prev_peer)); LOG (GNUNET_ERROR_TYPE_DEBUG, " next: %s, neighbor?: %d\n", GMP_2s (next_peer), GMP_is_neighbor (next_peer)); return GNUNET_SYSERR; } GMP_add_connection (next_peer, c); GMP_add_connection (prev_peer, c); return GNUNET_OK; } /** * Remove the connection from the list of both neighbors. * * @param c Connection. */ static void unregister_neighbors (struct MeshConnection *c) { struct MeshPeer *peer; peer = get_next_hop (c); if (GNUNET_OK != GMP_remove_connection (peer, c)) { GNUNET_assert (MESH_CONNECTION_NEW == c->state || MESH_CONNECTION_DESTROYED == c->state); LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate: %u\n", c->state); if (NULL != c->t) GMT_debug (c->t); } peer = get_prev_hop (c); if (GNUNET_OK != GMP_remove_connection (peer, c)) { GNUNET_assert (MESH_CONNECTION_NEW == c->state || MESH_CONNECTION_DESTROYED == c->state); LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate: %u\n", c->state); if (NULL != c->t) GMT_debug (c->t); } } /** * Bind the connection to the peer and the tunnel to that peer. * * If the peer has no tunnel, create one. Update tunnel and connection * data structres to reflect new status. * * @param c Connection. * @param peer Peer. */ static void add_to_peer (struct MeshConnection *c, struct MeshPeer *peer) { GMP_add_tunnel (peer); c->t = GMP_get_tunnel (peer); GMT_add_connection (c->t, c); } /** * Builds a path from a PeerIdentity array. * * @param peers PeerIdentity array. * @param size Size of the @c peers array. * @param own_pos Output parameter: own position in the path. * * @return Fixed and shortened path. */ static struct MeshPeerPath * build_path_from_peer_ids (struct GNUNET_PeerIdentity *peers, unsigned int size, unsigned int *own_pos) { struct MeshPeerPath *path; GNUNET_PEER_Id shortid; unsigned int i; unsigned int j; unsigned int offset; /* Create path */ LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n"); path = path_new (size); *own_pos = 0; offset = 0; for (i = 0; i < size; i++) { LOG (GNUNET_ERROR_TYPE_DEBUG, " - %u: taking %s\n", i, GNUNET_i2s (&peers[i])); shortid = GNUNET_PEER_intern (&peers[i]); /* Check for loops / duplicates */ for (j = 0; j < i - offset; j++) { if (path->peers[j] == shortid) { LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists at pos %u\n", j); offset = i - j; LOG (GNUNET_ERROR_TYPE_DEBUG, " offset now %u\n", offset); GNUNET_PEER_change_rc (shortid, -1); } } LOG (GNUNET_ERROR_TYPE_DEBUG, " storing at %u\n", i - offset); path->peers[i - offset] = shortid; if (path->peers[i - offset] == myid) *own_pos = i - offset; } path->length -= offset; if (path->peers[*own_pos] != myid) { /* create path: self not found in path through self */ GNUNET_break_op (0); path_destroy (path); return NULL; } return path; } /** * Log receipt of message on stderr (INFO level). * * @param message Message received. * @param peer Peer who sent the message. * @param hash Connection ID. */ static void log_message (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MESH_Hash *hash) { LOG (GNUNET_ERROR_TYPE_INFO, "<- %s on connection %s from %s\n", GM_m2s (ntohs (message->type)), GNUNET_h2s (GM_h2hc (hash)), GNUNET_i2s (peer)); } /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Core handler for connection creation. * * @param cls Closure (unused). * @param peer Sender (neighbor). * @param message Message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_ConnectionCreate *msg; struct GNUNET_PeerIdentity *id; struct GNUNET_MESH_Hash *cid; struct MeshPeerPath *path; struct MeshPeer *dest_peer; struct MeshPeer *orig_peer; struct MeshConnection *c; unsigned int own_pos; uint16_t size; /* Check size */ size = ntohs (message->size); if (size < sizeof (struct GNUNET_MESH_ConnectionCreate)) { GNUNET_break_op (0); return GNUNET_OK; } /* Calculate hops */ size -= sizeof (struct GNUNET_MESH_ConnectionCreate); if (size % sizeof (struct GNUNET_PeerIdentity)) { GNUNET_break_op (0); return GNUNET_OK; } size /= sizeof (struct GNUNET_PeerIdentity); if (1 > size) { GNUNET_break_op (0); return GNUNET_OK; } LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); /* Get parameters */ msg = (struct GNUNET_MESH_ConnectionCreate *) message; cid = &msg->cid; log_message (message, peer, cid); id = (struct GNUNET_PeerIdentity *) &msg[1]; LOG (GNUNET_ERROR_TYPE_DEBUG, " origin: %s\n", GNUNET_i2s (id)); /* Create connection */ c = connection_get (cid); if (NULL == c) { path = build_path_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1], size, &own_pos); if (NULL == path) return GNUNET_OK; if (0 == own_pos) { GNUNET_break_op (0); path_destroy (path); return GNUNET_OK; } LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n"); c = GMC_new (cid, NULL, path_duplicate (path), own_pos); if (NULL == c) { if (path->length - 1 == own_pos) { /* If we are destination, why did the creation fail? */ GNUNET_break (0); return GNUNET_OK; } send_broken2 (cid, &my_full_id, GNUNET_PEER_resolve2 (path->peers[own_pos + 1]), path->peers[own_pos - 1]); path_destroy (path); return GNUNET_OK; } GMP_add_path_to_all (path, GNUNET_NO); connection_reset_timeout (c, GNUNET_YES); } else { path = path_duplicate (c->path); } if (MESH_CONNECTION_NEW == c->state) connection_change_state (c, MESH_CONNECTION_SENT); /* Remember peers */ dest_peer = GMP_get (&id[size - 1]); orig_peer = GMP_get (&id[0]); /* Is it a connection to us? */ if (c->own_pos == path->length - 1) { LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES); add_to_peer (c, orig_peer); if (MESH_TUNNEL3_NEW == GMT_get_cstate (c->t)) GMT_change_cstate (c->t, MESH_TUNNEL3_WAITING); send_connection_ack (c, GNUNET_NO); if (MESH_CONNECTION_SENT == c->state) connection_change_state (c, MESH_CONNECTION_ACK); } else { /* It's for somebody else! Retransmit. */ LOG (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n"); GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO); GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO); GMC_send_prebuilt_message (message, c, GNUNET_YES, GNUNET_YES, NULL, NULL); } path_destroy (path); return GNUNET_OK; } /** * Core handler for path confirmations. * * @param cls closure * @param message message * @param peer peer identity this notification is about * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_ConnectionACK *msg; struct MeshConnection *c; struct MeshPeerPath *p; struct MeshPeer *pi; enum MeshConnectionState oldstate; int fwd; msg = (struct GNUNET_MESH_ConnectionACK *) message; log_message (message, peer, &msg->cid); c = connection_get (&msg->cid); if (NULL == c) { GNUNET_STATISTICS_update (stats, "# control on unknown connection", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n"); return GNUNET_OK; } if (GNUNET_NO != c->destroy) { LOG (GNUNET_ERROR_TYPE_DEBUG, " connection being destroyed\n"); return GNUNET_OK; } oldstate = c->state; LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GNUNET_i2s (peer)); pi = GMP_get (peer); if (get_next_hop (c) == pi) { LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n"); fwd = GNUNET_NO; if (MESH_CONNECTION_SENT == oldstate) connection_change_state (c, MESH_CONNECTION_ACK); } else if (get_prev_hop (c) == pi) { LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK\n"); fwd = GNUNET_YES; connection_change_state (c, MESH_CONNECTION_READY); } else { GNUNET_break_op (0); return GNUNET_OK; } connection_reset_timeout (c, fwd); /* Add path to peers? */ p = c->path; if (NULL != p) { GMP_add_path_to_all (p, GNUNET_YES); } else { GNUNET_break (0); } /* Message for us as creator? */ if (GMC_is_origin (c, GNUNET_YES)) { if (GNUNET_NO != fwd) { GNUNET_break_op (0); return GNUNET_OK; } LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n"); /* If just created, cancel the short timeout and start a long one */ if (MESH_CONNECTION_SENT == oldstate) connection_reset_timeout (c, GNUNET_YES); /* Change connection state */ connection_change_state (c, MESH_CONNECTION_READY); send_connection_ack (c, GNUNET_YES); /* Change tunnel state, trigger KX */ if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t)) GMT_change_cstate (c->t, MESH_TUNNEL3_READY); return GNUNET_OK; } /* Message for us as destination? */ if (GMC_is_terminal (c, GNUNET_YES)) { if (GNUNET_YES != fwd) { GNUNET_break_op (0); return GNUNET_OK; } LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n"); /* If just created, cancel the short timeout and start a long one */ if (MESH_CONNECTION_ACK == oldstate) connection_reset_timeout (c, GNUNET_NO); /* Change tunnel state */ if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t)) GMT_change_cstate (c->t, MESH_TUNNEL3_READY); return GNUNET_OK; } LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); GMC_send_prebuilt_message (message, c, fwd, GNUNET_YES, NULL, NULL); return GNUNET_OK; } /** * Core handler for notifications of broken connections. * * @param cls Closure (unused). * @param id Peer identity of sending neighbor. * @param message Message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_broken (void* cls, const struct GNUNET_PeerIdentity* id, const struct GNUNET_MessageHeader* message) { struct GNUNET_MESH_ConnectionBroken *msg; struct MeshConnection *c; int fwd; msg = (struct GNUNET_MESH_ConnectionBroken *) message; log_message (message, id, &msg->cid); LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer1)); LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer2)); c = connection_get (&msg->cid); if (NULL == c) { LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate CONNECTION_BROKEN\n"); return GNUNET_OK; } fwd = is_fwd (c, id); if (GMC_is_terminal (c, fwd)) { struct GNUNET_MessageHeader *out_msg; struct MeshPeer *neighbor; struct MeshPeer *endpoint; neighbor = get_hop (c, !fwd); endpoint = GMP_get_short (c->path->peers[c->path->length - 1]); path_invalidate (c->path); GMP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2); c->state = MESH_CONNECTION_DESTROYED; while (NULL != (out_msg = GMP_connection_pop (neighbor, c))) { GNUNET_assert (NULL == GMT_send_prebuilt_message (out_msg, c->t, NULL, GNUNET_YES, NULL, NULL)); } GMC_destroy (c); } else { GMC_send_prebuilt_message (message, c, fwd, GNUNET_YES, NULL, NULL); c->destroy = GNUNET_YES; connection_cancel_queues (c, !fwd); } return GNUNET_OK; } /** * Core handler for tunnel destruction * * @param cls Closure (unused). * @param peer Peer identity of sending neighbor. * @param message Message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_ConnectionDestroy *msg; struct MeshConnection *c; int fwd; msg = (struct GNUNET_MESH_ConnectionDestroy *) message; log_message (message, peer, &msg->cid); c = connection_get (&msg->cid); if (NULL == c) { /* Probably already got the message from another path, * destroyed the tunnel and retransmitted to children. * Safe to ignore. */ GNUNET_STATISTICS_update (stats, "# control on unknown connection", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, " connection unknown: already destroyed?\n"); return GNUNET_OK; } fwd = is_fwd (c, peer); if (GNUNET_SYSERR == fwd) { GNUNET_break_op (0); /* FIXME */ return GNUNET_OK; } if (GNUNET_NO == GMC_is_terminal (c, fwd)) GMC_send_prebuilt_message (message, c, fwd, GNUNET_YES, NULL, NULL); else if (0 == c->pending_messages) { LOG (GNUNET_ERROR_TYPE_DEBUG, "! directly destroying connection!\n"); GMC_destroy (c); return GNUNET_OK; } c->destroy = GNUNET_YES; c->state = MESH_CONNECTION_DESTROYED; if (NULL != c->t) { GMT_remove_connection (c->t, c); c->t = NULL; } return GNUNET_OK; } /** * Generic handler for mesh network encrypted traffic. * * @param peer Peer identity this notification is about. * @param msg Encrypted message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MESH_Encrypted *msg) { struct MeshConnection *c; struct MeshPeer *neighbor; struct MeshFlowControl *fc; GNUNET_PEER_Id peer_id; uint32_t pid; uint32_t ttl; size_t size; int fwd; log_message (&msg->header, peer, &msg->cid); /* Check size */ size = ntohs (msg->header.size); if (size < sizeof (struct GNUNET_MESH_Encrypted) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_OK; } /* Check connection */ c = connection_get (&msg->cid); if (NULL == c) { GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "enc on unknown connection %s\n", GNUNET_h2s (GM_h2hc (&msg->cid))); return GNUNET_OK; } LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s\n", GMC_2s (c)); /* Check if origin is as expected */ neighbor = get_prev_hop (c); peer_id = GNUNET_PEER_search (peer); if (peer_id == GMP_get_short_id (neighbor)) { fwd = GNUNET_YES; } else { neighbor = get_next_hop (c); if (peer_id == GMP_get_short_id (neighbor)) { fwd = GNUNET_NO; } else { /* Unexpected peer sending traffic on a connection. */ GNUNET_break_op (0); return GNUNET_OK; } } /* Check PID */ fc = fwd ? &c->bck_fc : &c->fwd_fc; pid = ntohl (msg->pid); LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u+)\n", pid, fc->last_pid_recv + 1); if (GM_is_pid_bigger (pid, fc->last_ack_sent)) { GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING Received PID %u, (prev %u), ACK %u\n", pid, fc->last_pid_recv, fc->last_ack_sent); return GNUNET_OK; } if (GNUNET_NO == GM_is_pid_bigger (pid, fc->last_pid_recv)) { GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u not expected (%u+), dropping!\n", pid, fc->last_pid_recv + 1); return GNUNET_OK; } if (MESH_CONNECTION_SENT == c->state || MESH_CONNECTION_ACK == c->state) connection_change_state (c, MESH_CONNECTION_READY); connection_reset_timeout (c, fwd); fc->last_pid_recv = pid; /* Is this message for us? */ if (GMC_is_terminal (c, fwd)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); if (NULL == c->t) { GNUNET_break (GNUNET_NO != c->destroy); return GNUNET_OK; } fc->last_pid_recv = pid; GMT_handle_encrypted (c->t, msg); GMC_send_ack (c, fwd, GNUNET_NO); return GNUNET_OK; } /* Message not for us: forward to next hop */ LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); ttl = ntohl (msg->ttl); LOG (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); if (ttl == 0) { GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n"); GMC_send_ack (c, fwd, GNUNET_NO); return GNUNET_OK; } GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); GMC_send_prebuilt_message (&msg->header, c, fwd, GNUNET_NO, NULL, NULL); return GNUNET_OK; } /** * Generic handler for mesh network encrypted traffic. * * @param peer Peer identity this notification is about. * @param msg Encrypted message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_mesh_kx (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MESH_KX *msg) { struct MeshConnection *c; struct MeshPeer *neighbor; GNUNET_PEER_Id peer_id; size_t size; int fwd; log_message (&msg->header, peer, &msg->cid); /* Check size */ size = ntohs (msg->header.size); if (size < sizeof (struct GNUNET_MESH_KX) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_OK; } /* Check connection */ c = connection_get (&msg->cid); if (NULL == c) { GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "kx on unknown connection %s\n", GNUNET_h2s (GM_h2hc (&msg->cid))); return GNUNET_OK; } LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n", GMC_2s (c)); /* Check if origin is as expected */ neighbor = get_prev_hop (c); peer_id = GNUNET_PEER_search (peer); if (peer_id == GMP_get_short_id (neighbor)) { fwd = GNUNET_YES; } else { neighbor = get_next_hop (c); if (peer_id == GMP_get_short_id (neighbor)) { fwd = GNUNET_NO; } else { /* Unexpected peer sending traffic on a connection. */ GNUNET_break_op (0); return GNUNET_OK; } } /* Count as connection confirmation. */ if (MESH_CONNECTION_SENT == c->state || MESH_CONNECTION_ACK == c->state) { connection_change_state (c, MESH_CONNECTION_READY); if (NULL != c->t) { if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t)) GMT_change_cstate (c->t, MESH_TUNNEL3_READY); } } connection_reset_timeout (c, fwd); /* Is this message for us? */ if (GMC_is_terminal (c, fwd)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); if (NULL == c->t) { GNUNET_break (0); return GNUNET_OK; } GMT_handle_kx (c->t, &msg[1].header); return GNUNET_OK; } /* Message not for us: forward to next hop */ LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); GMC_send_prebuilt_message (&msg->header, c, fwd, GNUNET_NO, NULL, NULL); return GNUNET_OK; } /** * Core handler for encrypted mesh network traffic (channel mgmt, data). * * @param cls Closure (unused). * @param message Message received. * @param peer Peer who sent the message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { return handle_mesh_encrypted (peer, (struct GNUNET_MESH_Encrypted *)message); } /** * Core handler for key exchange traffic (ephemeral key, ping, pong). * * @param cls Closure (unused). * @param message Message received. * @param peer Peer who sent the message. * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { return handle_mesh_kx (peer, (struct GNUNET_MESH_KX *) message); } /** * Core handler for mesh network traffic point-to-point acks. * * @param cls closure * @param message message * @param peer peer identity this notification is about * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_ACK *msg; struct MeshConnection *c; struct MeshFlowControl *fc; GNUNET_PEER_Id id; uint32_t ack; int fwd; msg = (struct GNUNET_MESH_ACK *) message; log_message (message, peer, &msg->cid); c = connection_get (&msg->cid); if (NULL == c) { GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1, GNUNET_NO); return GNUNET_OK; } /* Is this a forward or backward ACK? */ id = GNUNET_PEER_search (peer); if (GMP_get_short_id (get_next_hop (c)) == id) { LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); fc = &c->fwd_fc; fwd = GNUNET_YES; } else if (GMP_get_short_id (get_prev_hop (c)) == id) { LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); fc = &c->bck_fc; fwd = GNUNET_NO; } else { GNUNET_break_op (0); return GNUNET_OK; } ack = ntohl (msg->ack); LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n", ack, fc->last_ack_recv); if (GM_is_pid_bigger (ack, fc->last_ack_recv)) fc->last_ack_recv = ack; /* Cancel polling if the ACK is big enough. */ if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task && GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n"); GNUNET_SCHEDULER_cancel (fc->poll_task); fc->poll_task = GNUNET_SCHEDULER_NO_TASK; fc->poll_time = GNUNET_TIME_UNIT_SECONDS; } connection_unlock_queue (c, fwd); return GNUNET_OK; } /** * Core handler for mesh network traffic point-to-point ack polls. * * @param cls closure * @param message message * @param peer peer identity this notification is about * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_Poll *msg; struct MeshConnection *c; struct MeshFlowControl *fc; GNUNET_PEER_Id id; uint32_t pid; int fwd; msg = (struct GNUNET_MESH_Poll *) message; log_message (message, peer, &msg->cid); c = connection_get (&msg->cid); if (NULL == c) { GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING POLL message on unknown connection %s!\n", GNUNET_h2s (GM_h2hc (&msg->cid))); return GNUNET_OK; } /* Is this a forward or backward ACK? * Note: a poll should never be needed in a loopback case, * since there is no possiblility of packet loss there, so * this way of discerining FWD/BCK should not be a problem. */ id = GNUNET_PEER_search (peer); if (GMP_get_short_id (get_next_hop (c)) == id) { LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); fc = &c->fwd_fc; } else if (GMP_get_short_id (get_prev_hop (c)) == id) { LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); fc = &c->bck_fc; } else { GNUNET_break_op (0); return GNUNET_OK; } pid = ntohl (msg->pid); LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n", pid, fc->last_pid_recv); fc->last_pid_recv = pid; fwd = fc == &c->bck_fc; GMC_send_ack (c, fwd, GNUNET_YES); return GNUNET_OK; } /** * Send an ACK on the appropriate connection/channel, depending on * the direction and the position of the peer. * * @param c Which connection to send the hop-by-hop ACK. * @param fwd Is this a fwd ACK? (will go dest->root). * @param force Send the ACK even if suboptimal (e.g. requested by POLL). */ void GMC_send_ack (struct MeshConnection *c, int fwd, int force) { unsigned int buffer; LOG (GNUNET_ERROR_TYPE_DEBUG, "GMC send %s ACK on %s\n", GM_f2s (fwd), GMC_2s (c)); if (NULL == c) { GNUNET_break (0); return; } if (GNUNET_NO != c->destroy) { LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother...\n"); return; } /* Get available buffer space */ if (GMC_is_terminal (c, fwd)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all channels\n"); buffer = GMT_get_channels_buffer (c->t); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n"); buffer = GMC_get_buffer (c, fwd); } LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer); if (0 == buffer && GNUNET_NO == force) return; /* Send available buffer space */ if (GMC_is_origin (c, fwd)) { GNUNET_assert (NULL != c->t); LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channels...\n"); GMT_unchoke_channels (c->t); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n"); send_ack (c, buffer, fwd, force); } } /** * Initialize the connections subsystem * * @param c Configuration handle. */ void GMC_init (const struct GNUNET_CONFIGURATION_Handle *c) { LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE", &max_msgs_queue)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "MESH", "MAX_MSGS_QUEUE", "MISSING"); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS", &max_connections)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "MESH", "MAX_CONNECTIONS", "MISSING"); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME", &refresh_connection_time)) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "MESH", "REFRESH_CONNECTION_TIME", "MISSING"); GNUNET_SCHEDULER_shutdown (); return; } create_connection_time = GNUNET_TIME_UNIT_SECONDS; connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); } /** * Destroy each connection on shutdown. * * @param cls Closure (unused). * @param key Current key code (CID, unused). * @param value Value in the hash map (connection) * * @return #GNUNET_YES, because we should continue to iterate, */ static int shutdown_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct MeshConnection *c = value; GMC_destroy (c); return GNUNET_YES; } /** * Shut down the connections subsystem. */ void GMC_shutdown (void) { GNUNET_CONTAINER_multihashmap_iterate (connections, &shutdown_iterator, NULL); GNUNET_CONTAINER_multihashmap_destroy (connections); connections = NULL; } struct MeshConnection * GMC_new (const struct GNUNET_MESH_Hash *cid, struct MeshTunnel3 *t, struct MeshPeerPath *p, unsigned int own_pos) { struct MeshConnection *c; c = GNUNET_new (struct MeshConnection); c->id = *cid; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (connections, GMC_get_h (c), c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); fc_init (&c->fwd_fc); fc_init (&c->bck_fc); c->fwd_fc.c = c; c->bck_fc.c = c; c->t = t; GNUNET_assert (own_pos <= p->length - 1); c->own_pos = own_pos; c->path = p; if (GNUNET_OK != register_neighbors (c)) { if (0 == own_pos) { path_invalidate (c->path); c->t = NULL; c->path = NULL; } GMC_destroy (c); return NULL; } return c; } void GMC_destroy (struct MeshConnection *c) { if (NULL == c) { GNUNET_break (0); return; } if (2 == c->destroy) /* cancel queues -> GMP_queue_cancel -> q_destroy -> */ return; /* -> message_sent -> GMC_destroy. Don't loop. */ c->destroy = 2; LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", GMC_2s (c)); LOG (GNUNET_ERROR_TYPE_DEBUG, " fc's f: %p, b: %p\n", &c->fwd_fc, &c->bck_fc); LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n", c->fwd_fc.poll_task, c->bck_fc.poll_task); /* Cancel all traffic */ if (NULL != c->path) { connection_cancel_queues (c, GNUNET_YES); connection_cancel_queues (c, GNUNET_NO); unregister_neighbors (c); } LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n", c->fwd_fc.poll_task, c->bck_fc.poll_task); /* Cancel maintainance task (keepalive/timeout) */ if (NULL != c->fwd_fc.poll_msg) { GMC_cancel (c->fwd_fc.poll_msg); LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg FWD canceled\n"); } if (NULL != c->bck_fc.poll_msg) { GMC_cancel (c->bck_fc.poll_msg); LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg BCK canceled\n"); } /* Delete from tunnel */ if (NULL != c->t) GMT_remove_connection (c->t, c); if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES) && NULL != c->path) path_destroy (c->path); if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task) GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task); if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task) GNUNET_SCHEDULER_cancel (c->bck_maintenance_task); if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task) { GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task); LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n"); } if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task) { GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task); LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n"); } GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (connections, GMC_get_h (c), c)); GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO); GNUNET_free (c); } /** * Get the connection ID. * * @param c Connection to get the ID from. * * @return ID of the connection. */ const struct GNUNET_MESH_Hash * GMC_get_id (const struct MeshConnection *c) { return &c->id; } /** * Get the connection ID. * * @param c Connection to get the ID from. * * @return ID of the connection. */ const struct GNUNET_HashCode * GMC_get_h (const struct MeshConnection *c) { return GM_h2hc (&c->id); } /** * Get the connection path. * * @param c Connection to get the path from. * * @return path used by the connection. */ const struct MeshPeerPath * GMC_get_path (const struct MeshConnection *c) { if (GNUNET_NO == c->destroy) return c->path; return NULL; } /** * Get the connection state. * * @param c Connection to get the state from. * * @return state of the connection. */ enum MeshConnectionState GMC_get_state (const struct MeshConnection *c) { return c->state; } /** * Get the connection tunnel. * * @param c Connection to get the tunnel from. * * @return tunnel of the connection. */ struct MeshTunnel3 * GMC_get_tunnel (const struct MeshConnection *c) { return c->t; } /** * Get free buffer space in a connection. * * @param c Connection. * @param fwd Is query about FWD traffic? * * @return Free buffer space [0 - max_msgs_queue/max_connections] */ unsigned int GMC_get_buffer (struct MeshConnection *c, int fwd) { struct MeshFlowControl *fc; fc = fwd ? &c->fwd_fc : &c->bck_fc; return (fc->queue_max - fc->queue_n); } /** * Get how many messages have we allowed to send to us from a direction. * * @param c Connection. * @param fwd Are we asking about traffic from FWD (BCK messages)? * * @return last_ack_sent - last_pid_recv */ unsigned int GMC_get_allowed (struct MeshConnection *c, int fwd) { struct MeshFlowControl *fc; fc = fwd ? &c->fwd_fc : &c->bck_fc; if (GM_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent)) { return 0; } return (fc->last_ack_sent - fc->last_pid_recv); } /** * Get messages queued in a connection. * * @param c Connection. * @param fwd Is query about FWD traffic? * * @return Number of messages queued. */ unsigned int GMC_get_qn (struct MeshConnection *c, int fwd) { struct MeshFlowControl *fc; fc = fwd ? &c->fwd_fc : &c->bck_fc; return fc->queue_n; } /** * Allow the connection to advertise a buffer of the given size. * * The connection will send an @c fwd ACK message (so: in direction !fwd) * allowing up to last_pid_recv + buffer. * * @param c Connection. * @param buffer How many more messages the connection can accept. * @param fwd Is this about FWD traffic? (The ack will go dest->root). */ void GMC_allow (struct MeshConnection *c, unsigned int buffer, int fwd) { LOG (GNUNET_ERROR_TYPE_DEBUG, " allowing %s %u messages %s\n", GMC_2s (c), buffer, GM_f2s (fwd)); send_ack (c, buffer, fwd, GNUNET_NO); } /** * Notify other peers on a connection of a broken link. Mark connections * to destroy after all traffic has been sent. * * @param c Connection on which there has been a disconnection. * @param peer Peer that disconnected. */ void GMC_notify_broken (struct MeshConnection *c, struct MeshPeer *peer) { int fwd; LOG (GNUNET_ERROR_TYPE_DEBUG, " notify broken on %s due to %s disconnect\n", GMC_2s (c), GMP_2s (peer)); fwd = peer == get_prev_hop (c); if (GNUNET_YES == GMC_is_terminal (c, fwd)) { /* Local shutdown, no one to notify about this. */ GMC_destroy (c); return; } if (GNUNET_NO == c->destroy) send_broken (c, &my_full_id, GMP_get_id (peer), fwd); /* Connection will have at least one pending message * (the one we just scheduled), so no point in checking whether to * destroy immediately. */ c->destroy = GNUNET_YES; c->state = MESH_CONNECTION_DESTROYED; /** * Cancel all queues, if no message is left, connection will be destroyed. */ connection_cancel_queues (c, !fwd); return; } /** * Is this peer the first one on the connection? * * @param c Connection. * @param fwd Is this about fwd traffic? * * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal. */ int GMC_is_origin (struct MeshConnection *c, int fwd) { if (!fwd && c->path->length - 1 == c->own_pos ) return GNUNET_YES; if (fwd && 0 == c->own_pos) return GNUNET_YES; return GNUNET_NO; } /** * Is this peer the last one on the connection? * * @param c Connection. * @param fwd Is this about fwd traffic? * Note that the ROOT is the terminal for BCK traffic! * * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. */ int GMC_is_terminal (struct MeshConnection *c, int fwd) { return GMC_is_origin (c, !fwd); } /** * See if we are allowed to send by the next hop in the given direction. * * @param c Connection. * @param fwd Is this about fwd traffic? * * @return #GNUNET_YES in case it's OK to send. */ int GMC_is_sendable (struct MeshConnection *c, int fwd) { struct MeshFlowControl *fc; LOG (GNUNET_ERROR_TYPE_DEBUG, " checking sendability of %s traffic on %s\n", GM_f2s (fwd), GMC_2s (c)); if (NULL == c) { GNUNET_break (0); return GNUNET_YES; } fc = fwd ? &c->fwd_fc : &c->bck_fc; LOG (GNUNET_ERROR_TYPE_DEBUG, " last ack recv: %u, last pid sent: %u\n", fc->last_ack_recv, fc->last_pid_sent); if (GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) return GNUNET_YES; return GNUNET_NO; } /** * Sends an already built message on a connection, properly registering * all used resources. * * @param message Message to send. Function makes a copy of it. * If message is not hop-by-hop, decrements TTL of copy. * @param c Connection on which this message is transmitted. * @param fwd Is this a fwd message? * @param force Force the connection to accept the message (buffer overfill). * @param cont Continuation called once message is sent. Can be NULL. * @param cont_cls Closure for @c cont. * * @return Handle to cancel the message before it's sent. * NULL on error or if @c cont is NULL. * Invalid on @c cont call. */ struct MeshConnectionQueue * GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, struct MeshConnection *c, int fwd, int force, GMC_sent cont, void *cont_cls) { struct MeshFlowControl *fc; struct MeshConnectionQueue *q; void *data; size_t size; uint16_t type; int droppable; size = ntohs (message->size); data = GNUNET_malloc (size); memcpy (data, message, size); type = ntohs (message->type); LOG (GNUNET_ERROR_TYPE_INFO, "-> %s on connection %s (%u bytes)\n", GM_m2s (type), GMC_2s (c), size); fc = fwd ? &c->fwd_fc : &c->bck_fc; droppable = GNUNET_NO == force; switch (type) { struct GNUNET_MESH_Encrypted *emsg; struct GNUNET_MESH_KX *kmsg; struct GNUNET_MESH_ACK *amsg; struct GNUNET_MESH_Poll *pmsg; struct GNUNET_MESH_ConnectionDestroy *dmsg; struct GNUNET_MESH_ConnectionBroken *bmsg; uint32_t ttl; case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED: emsg = (struct GNUNET_MESH_Encrypted *) data; ttl = ntohl (emsg->ttl); if (0 == ttl) { GNUNET_break_op (0); GNUNET_free (data); return NULL; } emsg->cid = c->id; emsg->ttl = htonl (ttl - 1); emsg->pid = htonl (fc->next_pid++); LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u\n", fc, fc->queue_n); if (GNUNET_YES == droppable) { fc->queue_n++; LOG (GNUNET_ERROR_TYPE_DEBUG, "pid %u\n", ntohl (emsg->pid)); LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent); LOG (GNUNET_ERROR_TYPE_DEBUG, " ack recv %u\n", fc->last_ack_recv); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, " not droppable, Q_N stays the same\n"); } if (GM_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv)) { GMC_start_poll (c, fwd); } break; case GNUNET_MESSAGE_TYPE_MESH_KX: kmsg = (struct GNUNET_MESH_KX *) data; kmsg->cid = c->id; break; case GNUNET_MESSAGE_TYPE_MESH_ACK: amsg = (struct GNUNET_MESH_ACK *) data; amsg->cid = c->id; LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack)); droppable = GNUNET_NO; break; case GNUNET_MESSAGE_TYPE_MESH_POLL: pmsg = (struct GNUNET_MESH_Poll *) data; pmsg->cid = c->id; LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid)); droppable = GNUNET_NO; break; case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY: dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data; dmsg->cid = c->id; break; case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN: bmsg = (struct GNUNET_MESH_ConnectionBroken *) data; bmsg->cid = c->id; break; case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE: GNUNET_break (0); /* falltrough */ case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK: break; default: GNUNET_break (0); GNUNET_free (data); return NULL; } if (fc->queue_n > fc->queue_max && droppable) { GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)", 1, GNUNET_NO); GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "queue full: %u/%u\n", fc->queue_n, fc->queue_max); if (GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED == type) { fc->queue_n--; fc->next_pid--; } GNUNET_free (data); return NULL; /* Drop this message */ } LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u\n", c, c->pending_messages); c->pending_messages++; q = GNUNET_new (struct MeshConnectionQueue); q->forced = !droppable; q->q = GMP_queue_add (get_hop (c, fwd), data, type, size, c, fwd, &message_sent, q); if (NULL == q->q) { LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING dropping msg on %s\n", GMC_2s (c)); GNUNET_free (data); GNUNET_free (q); return NULL; } q->cont = cont; q->cont_cls = cont_cls; return q; } /** * Cancel a previously sent message while it's in the queue. * * ONLY can be called before the continuation given to the send function * is called. Once the continuation is called, the message is no longer in the * queue. * * @param q Handle to the queue. */ void GMC_cancel (struct MeshConnectionQueue *q) { LOG (GNUNET_ERROR_TYPE_DEBUG, "! GMC cancel message\n"); /* queue destroy calls message_sent, which calls q->cont and frees q */ GMP_queue_destroy (q->q, GNUNET_YES, GNUNET_NO); } /** * Sends a CREATE CONNECTION message for a path to a peer. * Changes the connection and tunnel states if necessary. * * @param connection Connection to create. */ void GMC_send_create (struct MeshConnection *connection) { enum MeshTunnel3CState state; size_t size; size = sizeof (struct GNUNET_MESH_ConnectionCreate); size += connection->path->length * sizeof (struct GNUNET_PeerIdentity); LOG (GNUNET_ERROR_TYPE_INFO, "=> %s on connection %s (%u bytes)\n", GM_m2s (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE), GMC_2s (connection), size); LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (create)\n", connection, connection->pending_messages); connection->pending_messages++; connection->maintenance_q = GMP_queue_add (get_next_hop (connection), NULL, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE, size, connection, GNUNET_YES, &message_sent, NULL); state = GMT_get_cstate (connection->t); if (MESH_TUNNEL3_SEARCHING == state || MESH_TUNNEL3_NEW == state) GMT_change_cstate (connection->t, MESH_TUNNEL3_WAITING); if (MESH_CONNECTION_NEW == connection->state) connection_change_state (connection, MESH_CONNECTION_SENT); } /** * Send a message to all peers in this connection that the connection * is no longer valid. * * If some peer should not receive the message, it should be zero'ed out * before calling this function. * * @param c The connection whose peers to notify. */ void GMC_send_destroy (struct MeshConnection *c) { struct GNUNET_MESH_ConnectionDestroy msg; if (GNUNET_YES == c->destroy) return; msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY);; msg.cid = c->id; LOG (GNUNET_ERROR_TYPE_DEBUG, " sending connection destroy for connection %s\n", GMC_2s (c)); if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES)) GMC_send_prebuilt_message (&msg.header, c, GNUNET_YES, GNUNET_YES, NULL, NULL); if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO)) GMC_send_prebuilt_message (&msg.header, c, GNUNET_NO, GNUNET_YES, NULL, NULL); c->destroy = GNUNET_YES; c->state = MESH_CONNECTION_DESTROYED; } /** * @brief Start a polling timer for the connection. * * When a neighbor does not accept more traffic on the connection it could be * caused by a simple congestion or by a lost ACK. Polling enables to check * for the lastest ACK status for a connection. * * @param c Connection. * @param fwd Should we poll in the FWD direction? */ void GMC_start_poll (struct MeshConnection *c, int fwd) { struct MeshFlowControl *fc; fc = fwd ? &c->fwd_fc : &c->bck_fc; LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL %s requested\n", GM_f2s (fwd)); if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task || NULL != fc->poll_msg) { LOG (GNUNET_ERROR_TYPE_DEBUG, " *** not needed (%u, %p)\n", fc->poll_task, fc->poll_msg); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL started on request\n"); fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, &connection_poll, fc); } /** * @brief Stop polling a connection for ACKs. * * Once we have enough ACKs for future traffic, polls are no longer necessary. * * @param c Connection. * @param fwd Should we stop the poll in the FWD direction? */ void GMC_stop_poll (struct MeshConnection *c, int fwd) { struct MeshFlowControl *fc; fc = fwd ? &c->fwd_fc : &c->bck_fc; if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task) { GNUNET_SCHEDULER_cancel (fc->poll_task); fc->poll_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Get a (static) string for a connection. * * @param c Connection. */ const char * GMC_2s (const struct MeshConnection *c) { if (NULL == c) return "NULL"; if (NULL != c->t) { static char buf[128]; sprintf (buf, "%s (->%s)", GNUNET_h2s (GM_h2hc (GMC_get_id(c))), GMT_2s (c->t)); return buf; } return GNUNET_h2s (GM_h2hc (&c->id)); } gnunet-0.10.1/src/mesh/mesh_test_lib.c0000644000175000017500000002030712316473376014540 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/mesh_test_lib.c * @author Bartlomiej Polot * @brief library for writing MESH tests */ #include "platform.h" #include "gnunet_util_lib.h" #include "mesh_test_lib.h" #include "gnunet_mesh_service.h" /** * Test context for a MESH Test. */ struct GNUNET_MESH_TEST_Context { /** * Array of running peers. */ struct GNUNET_TESTBED_Peer **peers; /** * Array of handles to the MESH for each peer. */ struct GNUNET_MESH_Handle **meshes; /** * Operation associated with the connection to the MESH. */ struct GNUNET_TESTBED_Operation **ops; /** * Main function of the test to run once all MESHs are available. */ GNUNET_MESH_TEST_AppMain app_main; /** * Closure for 'app_main'. */ void *app_main_cls; /** * Number of peers running, size of the arrays above. */ unsigned int num_peers; /** * Handler for incoming tunnels. */ GNUNET_MESH_InboundChannelNotificationHandler *new_channel; /** * Cleaner for destroyed incoming tunnels. */ GNUNET_MESH_ChannelEndHandler *cleaner; /** * Message handlers. */ struct GNUNET_MESH_MessageHandler* handlers; /** * Application ports. */ const uint32_t *ports; }; /** * Context for a mesh adapter callback. */ struct GNUNET_MESH_TEST_AdapterContext { /** * Peer number for the particular peer. */ unsigned int peer; /** * General context. */ struct GNUNET_MESH_TEST_Context *ctx; }; /** * Adapter function called to establish a connection to * the MESH service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * mesh_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_MESH_TEST_AdapterContext *actx = cls; struct GNUNET_MESH_TEST_Context *ctx = actx->ctx; struct GNUNET_MESH_Handle *h; h = GNUNET_MESH_connect (cfg, (void *) (long) actx->peer, ctx->new_channel, ctx->cleaner, ctx->handlers, ctx->ports); return h; } /** * Adapter function called to destroy a connection to * the MESH service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void mesh_disconnect_adapter (void *cls, void *op_result) { struct GNUNET_MESH_Handle *mesh = op_result; struct GNUNET_MESH_TEST_AdapterContext *actx = cls; GNUNET_free (actx); GNUNET_MESH_disconnect (mesh); } /** * Callback to be called when a service connect operation is completed. * * @param cls The callback closure from functions generating an operation. * @param op The operation that has been finished. * @param ca_result The service handle returned from * GNUNET_TESTBED_ConnectAdapter() (mesh handle). * @param emsg Error message in case the operation has failed. * NULL if operation has executed successfully. */ static void mesh_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct GNUNET_MESH_TEST_Context *ctx = cls; unsigned int i; if (NULL != emsg) { fprintf (stderr, "Failed to connect to MESH service: %s\n", emsg); GNUNET_SCHEDULER_shutdown (); return; } for (i = 0; i < ctx->num_peers; i++) if (op == ctx->ops[i]) { ctx->meshes[i] = ca_result; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...mesh %u connected\n", i); } for (i = 0; i < ctx->num_peers; i++) if (NULL == ctx->meshes[i]) return; /* still some MESH connections missing */ /* all MESH connections ready! */ ctx->app_main (ctx->app_main_cls, ctx, ctx->num_peers, ctx->peers, ctx->meshes); } void GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx) { unsigned int i; for (i = 0; i < ctx->num_peers; i++) { GNUNET_assert (NULL != ctx->ops[i]); GNUNET_TESTBED_operation_done (ctx->ops[i]); ctx->ops[i] = NULL; } GNUNET_free (ctx->ops); GNUNET_free (ctx->meshes); GNUNET_free (ctx); GNUNET_SCHEDULER_shutdown (); } /** * Callback run when the testbed is ready (peers running and connected to * each other) * * @param cls Closure (context). * @param h the run handle * @param num_peers Number of peers that are running. * @param peers Handles to each one of the @c num_peers peers. * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void mesh_test_run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { struct GNUNET_MESH_TEST_Context *ctx = cls; unsigned int i; if (num_peers != ctx->num_peers) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n", num_peers, ctx->num_peers); exit (1); } ctx->peers = peers; for (i = 0; i < num_peers; i++) { struct GNUNET_MESH_TEST_AdapterContext *newctx; newctx = GNUNET_new (struct GNUNET_MESH_TEST_AdapterContext); newctx->peer = i; newctx->ctx = ctx; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to mesh %u\n", i); ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx, peers[i], "mesh", &mesh_connect_cb, ctx, &mesh_connect_adapter, &mesh_disconnect_adapter, newctx); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "op handle %p\n", ctx->ops[i]); } } void GNUNET_MESH_TEST_run (const char *testname, const char *cfgname, unsigned int num_peers, GNUNET_MESH_TEST_AppMain tmain, void *tmain_cls, GNUNET_MESH_InboundChannelNotificationHandler new_channel, GNUNET_MESH_ChannelEndHandler cleaner, struct GNUNET_MESH_MessageHandler* handlers, const uint32_t *ports) { struct GNUNET_MESH_TEST_Context *ctx; ctx = GNUNET_new (struct GNUNET_MESH_TEST_Context); ctx->num_peers = num_peers; ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *)); ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle *)); ctx->app_main = tmain; ctx->app_main_cls = tmain_cls; ctx->new_channel = new_channel; ctx->cleaner = cleaner; ctx->handlers = handlers; ctx->ports = ports; GNUNET_TESTBED_test_run (testname, cfgname, num_peers, 0LL, NULL, NULL, &mesh_test_run, ctx); } /* end of mesh_test_lib.c */ gnunet-0.10.1/src/mesh/mesh_test_lib.h0000644000175000017500000000631012241362142014524 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/mesh_test_lib.h * @author Bartlomiej Polot * @brief library for writing MESH tests */ #ifndef MESH_TEST_LIB_H #define MESH_TEST_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_testbed_service.h" #include "gnunet_mesh_service.h" /** * Test context for a MESH Test. */ struct GNUNET_MESH_TEST_Context; /** * Main function of a MESH test. * * @param cls Closure. * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end. * @param num_peers Number of peers that are running. * @param peers Array of peers. * @param meshes Handle to each of the MESHs of the peers. */ typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls, struct GNUNET_MESH_TEST_Context *ctx, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, struct GNUNET_MESH_Handle **meshes); /** * Run a test using the given name, configuration file and number of * peers. * All mesh callbacks will receive the peer number as the closure. * * @param testname Name of the test (for logging). * @param cfgname Name of the configuration file. * @param num_peers Number of peers to start. * @param tmain Main function to run once the testbed is ready. * @param tmain_cls Closure for 'tmain'. * @param new_channel Handler for incoming tunnels. * @param cleaner Cleaner for destroyed incoming tunnels. * @param handlers Message handlers. * @param ports Ports the peers offer. */ void GNUNET_MESH_TEST_run (const char *testname, const char *cfgname, unsigned int num_peers, GNUNET_MESH_TEST_AppMain tmain, void *tmain_cls, GNUNET_MESH_InboundChannelNotificationHandler new_channel, GNUNET_MESH_ChannelEndHandler cleaner, struct GNUNET_MESH_MessageHandler* handlers, const uint32_t* ports); /** * Clean up the testbed. * * @param ctx handle for the testbed */ void GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef MESH_TEST_LIB_H */ #endif gnunet-0.10.1/src/mesh/gnunet-service-mesh_channel.h0000644000175000017500000002264412261236531017277 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/gnunet-service-mesh_channel.h * @brief mesh service; dealing with end-to-end channels * @author Bartlomiej Polot * * All functions in this file should use the prefix GMCH (Gnunet Mesh CHannel) */ #ifndef GNUNET_SERVICE_MESH_CHANNEL_H #define GNUNET_SERVICE_MESH_CHANNEL_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "platform.h" #include "gnunet_util_lib.h" #include "mesh_protocol.h" #include "mesh.h" /** * Struct containing all information regarding a channel to a remote client. */ struct MeshChannel; #include "gnunet-service-mesh_tunnel.h" #include "gnunet-service-mesh_local.h" /** * Destroy a channel and free all resources. * * @param ch Channel to destroy. */ void GMCH_destroy (struct MeshChannel *ch); /** * Get the channel's public ID. * * @param ch Channel. * * @return ID used to identify the channel with the remote peer. */ MESH_ChannelNumber GMCH_get_id (const struct MeshChannel *ch); /** * Get the channel tunnel. * * @param ch Channel to get the tunnel from. * * @return tunnel of the channel. */ struct MeshTunnel3 * GMCH_get_tunnel (const struct MeshChannel *ch); /** * Get free buffer space towards the client on a specific channel. * * @param ch Channel. * @param fwd Is query about FWD traffic? * * @return Free buffer space [0 - 64] */ unsigned int GMCH_get_buffer (struct MeshChannel *ch, int fwd); /** * Get flow control status of end point: is client allow to send? * * @param ch Channel. * @param fwd Is query about FWD traffic? (Request root status). * * @return #GNUNET_YES if client is allowed to send us data. */ int GMCH_get_allowed (struct MeshChannel *ch, int fwd); /** * Is the root client for this channel on this peer? * * @param ch Channel. * @param fwd Is this for fwd traffic? * * @return #GNUNET_YES in case it is. */ int GMCH_is_origin (struct MeshChannel *ch, int fwd); /** * Is the destination client for this channel on this peer? * * @param ch Channel. * @param fwd Is this for fwd traffic? * * @return #GNUNET_YES in case it is. */ int GMCH_is_terminal (struct MeshChannel *ch, int fwd); /** * Send an end-to-end ACK message for the most recent in-sequence payload. * * If channel is not reliable, do nothing. * * @param ch Channel this is about. * @param fwd Is for FWD traffic? (ACK dest->owner) */ void GMCH_send_data_ack (struct MeshChannel *ch, int fwd); /** * Notify the destination client that a new incoming channel was created. * * @param ch Channel that was created. */ void GMCH_send_create (struct MeshChannel *ch); /** * Allow a client to send us more data, in case it was choked. * * @param ch Channel. * @param fwd Is this about FWD traffic? (Root client). */ void GMCH_allow_client (struct MeshChannel *ch, int fwd); /** * Log channel info. * * @param ch Channel. */ void GMCH_debug (struct MeshChannel *ch); /** * Handle an ACK given by a client. * * Mark client as ready and send him any buffered data we could have for him. * * @param ch Channel. * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by root and go BCK) */ void GMCH_handle_local_ack (struct MeshChannel *ch, int fwd); /** * Handle data given by a client. * * Check whether the client is allowed to send in this tunnel, save if channel * is reliable and send an ACK to the client if there is still buffer space * in the tunnel. * * @param ch Channel. * @param c Client which sent the data. * @param message Message. * @param fwd Is this a FWD data? * * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error. */ int GMCH_handle_local_data (struct MeshChannel *ch, struct MeshClient *c, struct GNUNET_MessageHeader *message, int fwd); /** * Handle a channel destroy requested by a client. * * Destroy the channel and the tunnel in case this was the last channel. * * @param ch Channel. * @param c Client that requested the destruction (to avoid notifying him). * @param is_root Is the request coming from root? */ void GMCH_handle_local_destroy (struct MeshChannel *ch, struct MeshClient *c, int is_root); /** * Handle a channel create requested by a client. * * Create the channel and the tunnel in case this was the first0 channel. * * @param c Client that requested the creation (will be the root). * @param msg Create Channel message. * * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise. */ int GMCH_handle_local_create (struct MeshClient *c, struct GNUNET_MESH_ChannelMessage *msg); /** * Handler for mesh network payload traffic. * * @param ch Channel for the message. * @param msg Unencryted data message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ void GMCH_handle_data (struct MeshChannel *ch, const struct GNUNET_MESH_Data *msg, int fwd); /** * Handler for mesh network traffic end-to-end ACKs. * * @param ch Channel on which we got this message. * @param msg Data message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ void GMCH_handle_data_ack (struct MeshChannel *ch, const struct GNUNET_MESH_DataACK *msg, int fwd); /** * Handler for channel create messages. * * Does not have fwd parameter because it's always 'FWD': channel is incoming. * * @param t Tunnel this channel will be in. * @param msg Channel crate message. */ struct MeshChannel * GMCH_handle_create (struct MeshTunnel3 *t, const struct GNUNET_MESH_ChannelCreate *msg); /** * Handler for channel NACK messages. * * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter. * * @param ch Channel. */ void GMCH_handle_nack (struct MeshChannel *ch); /** * Handler for channel ack messages. * * @param ch Channel this channel is to be created in. * @param msg Message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ void GMCH_handle_ack (struct MeshChannel *ch, const struct GNUNET_MESH_ChannelManage *msg, int fwd); /** * Handler for channel destroy messages. * * @param ch Channel this channel is to be destroyed of. * @param msg Message. * @param fwd Is this message fwd? This only is meaningful in loopback channels. * #GNUNET_YES if message is FWD on the respective channel (loopback) * #GNUNET_NO if message is BCK on the respective channel (loopback) * #GNUNET_SYSERR if message on a one-ended channel (remote) */ void GMCH_handle_destroy (struct MeshChannel *ch, const struct GNUNET_MESH_ChannelManage *msg, int fwd); /** * Sends an already built message on a channel. * * If the channel is on a loopback tunnel, notifies the appropriate destination * client locally. * * On a normal channel passes the message to the tunnel for encryption and * sending on a connection. * * This function DOES NOT save the message for retransmission. * * @param message Message to send. Function makes a copy of it. * @param ch Channel on which this message is transmitted. * @param fwd Is this a fwd message? * @param existing_copy This is a retransmission, don't save a copy. */ void GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, struct MeshChannel *ch, int fwd, void *existing_copy); /** * Get the static string for identification of the channel. * * @param ch Channel.i * * @return Static string with the channel IDs. */ const char * GMCH_2s (const struct MeshChannel *ch); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef GNUNET_SERVICE_MESH_CHANNEL_H */ #endif /* end of gnunet-service-mesh_channel.h */ gnunet-0.10.1/src/mesh/gnunet-service-mesh_local.c0000644000175000017500000010464512320526362016756 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "mesh.h" #include "mesh_protocol.h" /* GNUNET_MESH_Data is shared */ #include "gnunet-service-mesh_local.h" #include "gnunet-service-mesh_channel.h" /* INFO DEBUG */ #include "gnunet-service-mesh_tunnel.h" #include "gnunet-service-mesh_peer.h" #define LOG(level, ...) GNUNET_log_from(level,"mesh-loc",__VA_ARGS__) /******************************************************************************/ /******************************** STRUCTS **********************************/ /******************************************************************************/ /** * Struct containing information about a client of the service * * TODO: add a list of 'waiting' ports */ struct MeshClient { /** * Linked list next */ struct MeshClient *next; /** * Linked list prev */ struct MeshClient *prev; /** * Tunnels that belong to this client, indexed by local id */ struct GNUNET_CONTAINER_MultiHashMap32 *own_channels; /** * Tunnels this client has accepted, indexed by incoming local id */ struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels; /** * Channel ID for the next incoming channel. */ MESH_ChannelNumber next_chid; /** * Handle to communicate with the client */ struct GNUNET_SERVER_Client *handle; /** * Ports that this client has declared interest in. * Indexed by port, contains *Client. */ struct GNUNET_CONTAINER_MultiHashMap32 *ports; /** * Whether the client is active or shutting down (don't send confirmations * to a client that is shutting down. */ int shutting_down; /** * ID of the client, mainly for debug messages */ unsigned int id; }; /******************************************************************************/ /******************************* GLOBALS ***********************************/ /******************************************************************************/ /** * Global handle to the statistics service. */ extern struct GNUNET_STATISTICS_Handle *stats; /** * Handle to server lib. */ static struct GNUNET_SERVER_Handle *server_handle; /** * DLL with all the clients, head. */ static struct MeshClient *clients_head; /** * DLL with all the clients, tail. */ static struct MeshClient *clients_tail; /** * Next ID to assign to a client. */ unsigned int next_client_id; /** * All ports clients of this peer have opened. */ static struct GNUNET_CONTAINER_MultiHashMap32 *ports; /** * Notification context, to send messages to local clients. */ static struct GNUNET_SERVER_NotificationContext *nc; /******************************************************************************/ /******************************** STATIC ***********************************/ /******************************************************************************/ /** * Remove client's ports from the global hashmap on disconnect. * * @param cls Closure (unused). * @param key Port. * @param value Client structure. * * @return GNUNET_OK, keep iterating. */ static int client_release_ports (void *cls, uint32_t key, void *value) { int res; res = GNUNET_CONTAINER_multihashmap32_remove (ports, key, value); if (GNUNET_YES != res) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, "Port %u by client %p was not registered.\n", key, value); } return GNUNET_OK; } /******************************************************************************/ /******************************** HANDLES ***********************************/ /******************************************************************************/ /** * Handler for client connection. * * @param cls Closure (unused). * @param client Client handler. */ static void handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client) { struct MeshClient *c; LOG (GNUNET_ERROR_TYPE_DEBUG, "client connected: %p\n", client); if (NULL == client) return; c = GNUNET_new (struct MeshClient); c->handle = client; c->id = next_client_id++; /* overflow not important: just for debug */ c->next_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; GNUNET_SERVER_client_keep (client); GNUNET_SERVER_client_set_user_context (client, c); GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c); } /** * Iterator for deleting each channel whose client endpoint disconnected. * * @param cls Closure (client that has disconnected). * @param key The local channel id (used to access the hashmap). * @param value The value stored at the key (channel to destroy). * * @return GNUNET_OK, keep iterating. */ static int channel_destroy_iterator (void *cls, uint32_t key, void *value) { struct MeshChannel *ch = value; struct MeshClient *c = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, " Channel %s destroy, due to client %s shutdown.\n", GMCH_2s (ch), GML_2s (c)); GMCH_handle_local_destroy (ch, c, key < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV); return GNUNET_OK; } /** * Handler for client disconnection * * @param cls closure * @param client identification of the client; NULL * for the last call when the server is destroyed */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct MeshClient *c; LOG (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client); if (client == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); return; } c = GML_client_get (client); if (NULL != c) { LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n", c->id, c); GNUNET_SERVER_client_drop (c->handle); c->shutting_down = GNUNET_YES; if (NULL != c->own_channels) { GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels, &channel_destroy_iterator, c); GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels); } if (NULL != c->incoming_channels) { GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels, &channel_destroy_iterator, c); GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels); } if (NULL != c->ports) { GNUNET_CONTAINER_multihashmap32_iterate (c->ports, &client_release_ports, c); GNUNET_CONTAINER_multihashmap32_destroy (c->ports); } GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c); GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, " client free (%p)\n", c); GNUNET_free (c); } else { LOG (GNUNET_ERROR_TYPE_WARNING, " context NULL!\n"); } LOG (GNUNET_ERROR_TYPE_DEBUG, "done!\n"); return; } /** * Handler for new clients * * @param cls closure * @param client identification of the client * @param message the actual message, which includes messages the client wants */ static void handle_new_client (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_ClientConnect *cc_msg; struct MeshClient *c; unsigned int size; uint32_t *p; unsigned int i; LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client); /* Check data sanity */ size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect); cc_msg = (struct GNUNET_MESH_ClientConnect *) message; if (0 != (size % sizeof (uint32_t))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } size /= sizeof (uint32_t); /* Initialize new client structure */ c = GNUNET_SERVER_client_get_user_context (client, struct MeshClient); LOG (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id); LOG (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size); if (size > 0) { uint32_t u32; p = (uint32_t *) &cc_msg[1]; c->ports = GNUNET_CONTAINER_multihashmap32_create (size); for (i = 0; i < size; i++) { u32 = ntohl (p[i]); LOG (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32); /* store in client's hashmap */ GNUNET_CONTAINER_multihashmap32_put (c->ports, u32, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); /* store in global hashmap */ /* FIXME only allow one client to have the port open, * have a backup hashmap with waiting clients */ GNUNET_CONTAINER_multihashmap32_put (ports, u32, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } } c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32); c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); LOG (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n"); } /** * Handler for requests of new tunnels * * @param cls Closure. * @param client Identification of the client. * @param message The actual message. */ static void handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct MeshClient *c; LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n"); /* Sanity check for client registration */ if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); /* Message size sanity check */ if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (GNUNET_OK != GMCH_handle_local_create (c, (struct GNUNET_MESH_ChannelMessage *) message)) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } /** * Handler for requests of deleting tunnels * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_ChannelMessage *msg; struct MeshClient *c; struct MeshChannel *ch; MESH_ChannelNumber chid; LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n"); /* Sanity check for client registration */ if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); /* Message sanity check */ if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (struct GNUNET_MESH_ChannelMessage *) message; /* Retrieve tunnel */ chid = ntohl (msg->channel_id); LOG (GNUNET_ERROR_TYPE_DEBUG, " for channel %X\n", chid); ch = GML_channel_get (c, chid); if (NULL == ch) { LOG (GNUNET_ERROR_TYPE_DEBUG, " channel %X not found\n", chid); GNUNET_STATISTICS_update (stats, "# client destroy messages on unknown channel", 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GMCH_handle_local_destroy (ch, c, chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } /** * Handler for client traffic * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_data (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalData *msg; struct MeshClient *c; struct MeshChannel *ch; MESH_ChannelNumber chid; size_t size; int fwd; LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client!\n"); /* Sanity check for client registration */ if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); msg = (struct GNUNET_MESH_LocalData *) message; /* Sanity check for message size */ size = ntohs (message->size) - sizeof (struct GNUNET_MESH_LocalData); if (size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* Channel exists? */ chid = ntohl (msg->id); LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid); fwd = chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; ch = GML_channel_get (c, chid); if (NULL == ch) { GNUNET_STATISTICS_update (stats, "# client data messages on unknown channel", 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (GNUNET_OK != GMCH_handle_local_data (ch, c, (struct GNUNET_MessageHeader *)&msg[1], fwd)) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } /** * Handler for client's ACKs for payload traffic. * * @param cls Closure (unused). * @param client Identification of the client. * @param message The actual message. */ static void handle_ack (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalAck *msg; struct MeshChannel *ch; struct MeshClient *c; MESH_ChannelNumber chid; int fwd; LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n"); /* Sanity check for client registration */ if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); msg = (struct GNUNET_MESH_LocalAck *) message; /* Channel exists? */ chid = ntohl (msg->channel_id); LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid); ch = GML_channel_get (c, chid); LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch); if (NULL == ch) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X unknown.\n", chid); LOG (GNUNET_ERROR_TYPE_DEBUG, " for client %u.\n", c->id); GNUNET_STATISTICS_update (stats, "# client ack messages on unknown channel", 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */ /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */ fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; GMCH_handle_local_ack (ch, fwd); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } /** * Iterator over all peers to send a monitoring client info about each peer. * * @param cls Closure (). * @param peer Peer ID (tunnel remote peer). * @param value Peer info. * * @return #GNUNET_YES, to keep iterating. */ static int get_all_peers_iterator (void *cls, const struct GNUNET_PeerIdentity * peer, void *value) { struct GNUNET_SERVER_Client *client = cls; struct MeshPeer *p = value; struct GNUNET_MESH_LocalInfoPeer msg; msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS); msg.destination = *peer; msg.paths = htons (GMP_count_paths (p)); msg.tunnel = htons (NULL != GMP_get_tunnel (p)); LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about peer %s\n", GNUNET_i2s (peer)); GNUNET_SERVER_notification_context_unicast (nc, client, &msg.header, GNUNET_NO); return GNUNET_YES; } /** * Handler for client's INFO PEERS request. * * @param cls Closure (unused). * @param client Identification of the client. * @param message The actual message. */ static void handle_get_peers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct MeshClient *c; struct GNUNET_MessageHeader reply; /* Sanity check for client registration */ if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received get peers request from client %u (%p)\n", c->id, client); GMP_iterate_all (get_all_peers_iterator, client); reply.size = htons (sizeof (reply)); reply.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS); GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Get peers request from client %u completed\n", c->id); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Iterator over all tunnels to send a monitoring client info about each tunnel. * * @param cls Closure (). * @param peer Peer ID (tunnel remote peer). * @param value Tunnel info. * * @return #GNUNET_YES, to keep iterating. */ static int get_all_tunnels_iterator (void *cls, const struct GNUNET_PeerIdentity * peer, void *value) { struct GNUNET_SERVER_Client *client = cls; struct MeshTunnel3 *t = value; struct GNUNET_MESH_LocalInfoTunnel msg; msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); msg.destination = *peer; msg.channels = htonl (GMT_count_channels (t)); msg.connections = htonl (GMT_count_connections (t)); msg.cstate = htons ((uint16_t) GMT_get_cstate (t)); msg.estate = htons ((uint16_t) GMT_get_estate (t)); LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about tunnel ->%s\n", GNUNET_i2s (peer)); GNUNET_SERVER_notification_context_unicast (nc, client, &msg.header, GNUNET_NO); return GNUNET_YES; } /** * Handler for client's INFO TUNNELS request. * * @param cls Closure (unused). * @param client Identification of the client. * @param message The actual message. */ static void handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct MeshClient *c; struct GNUNET_MessageHeader reply; /* Sanity check for client registration */ if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received get tunnels request from client %u (%p)\n", c->id, client); GMT_iterate_all (get_all_tunnels_iterator, client); reply.size = htons (sizeof (reply)); reply.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Get tunnels request from client %u completed\n", c->id); GNUNET_SERVER_receive_done (client, GNUNET_OK); } static void iter_connection (void *cls, struct MeshConnection *c) { struct GNUNET_MESH_LocalInfoTunnel *msg = cls; struct GNUNET_MESH_Hash *h = (struct GNUNET_MESH_Hash *) &msg[1]; h[msg->connections] = *(GMC_get_id (c)); msg->connections++; } static void iter_channel (void *cls, struct MeshChannel *ch) { struct GNUNET_MESH_LocalInfoTunnel *msg = cls; struct GNUNET_HashCode *h = (struct GNUNET_HashCode *) &msg[1]; MESH_ChannelNumber *chn = (MESH_ChannelNumber *) &h[msg->connections]; chn[msg->channels] = GMCH_get_id (ch); msg->channels++; } /** * Handler for client's SHOW_TUNNEL request. * * @param cls Closure (unused). * @param client Identification of the client. * @param message The actual message. */ void handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_MESH_LocalInfo *msg; struct GNUNET_MESH_LocalInfoTunnel *resp; struct MeshClient *c; struct MeshTunnel3 *t; unsigned int ch_n; unsigned int c_n; size_t size; /* Sanity check for client registration */ if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (struct GNUNET_MESH_LocalInfo *) message; LOG (GNUNET_ERROR_TYPE_INFO, "Received tunnel info request from client %u for tunnel %s\n", c->id, GNUNET_i2s_full(&msg->peer)); t = GMP_get_tunnel (GMP_get (&msg->peer)); if (NULL == t) { /* We don't know the tunnel */ struct GNUNET_MESH_LocalInfoTunnel warn; LOG (GNUNET_ERROR_TYPE_INFO, "Tunnel %s unknown %u\n", GNUNET_i2s_full(&msg->peer), sizeof (warn)); warn.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL); warn.header.size = htons (sizeof (warn)); warn.destination = msg->peer; warn.channels = htonl (0); warn.connections = htonl (0); warn.cstate = htons (0); warn.estate = htons (0); GNUNET_SERVER_notification_context_unicast (nc, client, &warn.header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } /* Initialize context */ ch_n = GMT_count_channels (t); c_n = GMT_count_connections (t); size = sizeof (struct GNUNET_MESH_LocalInfoTunnel); size += c_n * sizeof (struct GNUNET_MESH_Hash); size += ch_n * sizeof (MESH_ChannelNumber); resp = GNUNET_malloc (size); resp->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL); resp->header.size = htons (size); GMT_iterate_connections (t, &iter_connection, resp); GMT_iterate_channels (t, &iter_channel, resp); /* Do not interleave with iterators, iter_channel needs conn in HBO */ resp->destination = msg->peer; resp->connections = htonl (resp->connections); resp->channels = htonl (resp->channels); resp->cstate = htons (GMT_get_cstate (t)); resp->estate = htons (GMT_get_estate (t)); GNUNET_SERVER_notification_context_unicast (nc, c->handle, &resp->header, GNUNET_NO); GNUNET_free (resp); LOG (GNUNET_ERROR_TYPE_INFO, "Show tunnel request from client %u completed. %u conn, %u ch\n", c->id, c_n, ch_n); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Functions to handle messages from clients */ static struct GNUNET_SERVER_MessageHandler client_handlers[] = { {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0}, {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE, sizeof (struct GNUNET_MESH_ChannelMessage)}, {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY, sizeof (struct GNUNET_MESH_ChannelMessage)}, {&handle_data, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0}, {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK, sizeof (struct GNUNET_MESH_LocalAck)}, {&handle_get_peers, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS, sizeof (struct GNUNET_MessageHeader)}, {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS, sizeof (struct GNUNET_MessageHeader)}, {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL, sizeof (struct GNUNET_MESH_LocalInfo)}, {NULL, NULL, 0, 0} }; /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Initialize server subsystem. * * @param handle Server handle. */ void GML_init (struct GNUNET_SERVER_Handle *handle) { LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); server_handle = handle; GNUNET_SERVER_suspend (server_handle); ports = GNUNET_CONTAINER_multihashmap32_create (32); } /** * Install server (service) handlers and start listening to clients. */ void GML_start (void) { GNUNET_SERVER_add_handlers (server_handle, client_handlers); GNUNET_SERVER_connect_notify (server_handle, &handle_client_connect, NULL); GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect, NULL); nc = GNUNET_SERVER_notification_context_create (server_handle, 1); clients_head = NULL; clients_tail = NULL; next_client_id = 0; GNUNET_SERVER_resume (server_handle); } /** * Shutdown server. */ void GML_shutdown (void) { if (nc != NULL) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } } /** * Get a channel from a client. * * @param c Client to check. * @param chid Channel ID, must be local (> 0x800...). * * @return non-NULL if channel exists in the clients lists */ struct MeshChannel * GML_channel_get (struct MeshClient *c, MESH_ChannelNumber chid) { struct GNUNET_CONTAINER_MultiHashMap32 *map; if (0 == (chid & GNUNET_MESH_LOCAL_CHANNEL_ID_CLI)) { GNUNET_break_op (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid); return NULL; } if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) map = c->incoming_channels; else if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI) map = c->own_channels; else { GNUNET_break (0); map = NULL; } if (NULL == map) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Client %s does no t have a valid map for CHID %X\n", GML_2s (c), chid); return NULL; } return GNUNET_CONTAINER_multihashmap32_get (map, chid); } /** * Add a channel to a client * * @param client Client. * @param chid Channel ID. * @param ch Channel. */ void GML_channel_add (struct MeshClient *client, uint32_t chid, struct MeshChannel *ch) { if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); else if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI) GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); else GNUNET_break (0); } /** * Remove a channel from a client. * * @param client Client. * @param chid Channel ID. * @param ch Channel. */ void GML_channel_remove (struct MeshClient *client, uint32_t chid, struct MeshChannel *ch) { if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= chid) GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels, chid, ch)); else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= chid) GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_multihashmap32_remove (client->own_channels, chid, ch)); else GNUNET_break (0); } /** * Get the tunnel's next free local channel ID. * * @param c Client. * * @return LID of a channel free to use. */ MESH_ChannelNumber GML_get_next_chid (struct MeshClient *c) { MESH_ChannelNumber chid; while (NULL != GML_channel_get (c, c->next_chid)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid); c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; } chid = c->next_chid; c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; return chid; } /** * Check if client has registered with the service and has not disconnected * * @param client the client to check * * @return non-NULL if client exists in the global DLL */ struct MeshClient * GML_client_get (struct GNUNET_SERVER_Client *client) { return GNUNET_SERVER_client_get_user_context (client, struct MeshClient); } /** * Find a client that has opened a port * * @param port Port to check. * * @return non-NULL if a client has the port. */ struct MeshClient * GML_client_get_by_port (uint32_t port) { return GNUNET_CONTAINER_multihashmap32_get (ports, port); } /** * Deletes a channel from a client (either owner or destination). * * @param c Client whose tunnel to delete. * @param ch Channel which should be deleted. * @param id Channel ID. */ void GML_client_delete_channel (struct MeshClient *c, struct MeshChannel *ch, MESH_ChannelNumber id) { int res; if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= id) { res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels, id, ch); if (GNUNET_YES != res) LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n"); } else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= id) { res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels, id, ch); if (GNUNET_YES != res) LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n"); } else { GNUNET_break (0); } } /** * Build a local ACK message and send it to a local client, if needed. * * If the client was already allowed to send data, do nothing. * * @param c Client to whom send the ACK. * @param id Channel ID to use */ void GML_send_ack (struct MeshClient *c, MESH_ChannelNumber id) { struct GNUNET_MESH_LocalAck msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "send local %s ack on %X towards %p\n", id < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c); msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); msg.channel_id = htonl (id); GNUNET_SERVER_notification_context_unicast (nc, c->handle, &msg.header, GNUNET_NO); } /** * Notify the client that a new incoming channel was created. * * @param c Client to notify. * @param id Channel ID. * @param port Channel's destination port. * @param opt Options (bit array). * @param peer Origin peer. */ void GML_send_channel_create (struct MeshClient *c, uint32_t id, uint32_t port, uint32_t opt, const struct GNUNET_PeerIdentity *peer) { struct GNUNET_MESH_ChannelMessage msg; msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE); msg.channel_id = htonl (id); msg.port = htonl (port); msg.opt = htonl (opt); msg.peer = *peer; GNUNET_SERVER_notification_context_unicast (nc, c->handle, &msg.header, GNUNET_NO); } /** * Build a local channel NACK message and send it to a local client. * * @param c Client to whom send the NACK. * @param id Channel ID to use */ void GML_send_channel_nack (struct MeshClient *c, MESH_ChannelNumber id) { struct GNUNET_MESH_LocalAck msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "send local nack on %X towards %p\n", id, c); msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK); msg.channel_id = htonl (id); GNUNET_SERVER_notification_context_unicast (nc, c->handle, &msg.header, GNUNET_NO); } /** * Notify a client that a channel is no longer valid. * * @param c Client. * @param id ID of the channel that is destroyed. */ void GML_send_channel_destroy (struct MeshClient *c, uint32_t id) { struct GNUNET_MESH_ChannelMessage msg; if (NULL == c) { GNUNET_break (0); return; } if (GNUNET_YES == c->shutting_down) return; msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY); msg.channel_id = htonl (id); msg.port = htonl (0); memset (&msg.peer, 0, sizeof (msg.peer)); msg.opt = htonl (0); GNUNET_SERVER_notification_context_unicast (nc, c->handle, &msg.header, GNUNET_NO); } /** * Modify the mesh message ID from global to local and send to client. * * @param c Client to send to. * @param msg Message to modify and send. * @param id Channel ID to use (c can be both owner and client). */ void GML_send_data (struct MeshClient *c, const struct GNUNET_MESH_Data *msg, MESH_ChannelNumber id) { struct GNUNET_MESH_LocalData *copy; uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_MESH_Data); char cbuf[size + sizeof (struct GNUNET_MESH_LocalData)]; if (size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return; } if (NULL == c) { GNUNET_break (0); return; } copy = (struct GNUNET_MESH_LocalData *) cbuf; memcpy (©[1], &msg[1], size); copy->header.size = htons (sizeof (struct GNUNET_MESH_LocalData) + size); copy->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA); copy->id = htonl (id); GNUNET_SERVER_notification_context_unicast (nc, c->handle, ©->header, GNUNET_NO); } /** * Get the static string to represent a client. * * @param c Client. * * @return Static string for the client. */ const char * GML_2s (const struct MeshClient *c) { static char buf[32]; sprintf (buf, "%u", c->id); return buf; } gnunet-0.10.1/src/mesh/mesh_api.c0000644000175000017500000016511112320526362013474 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file mesh/mesh_api.c * @brief mesh api: client implementation of new mesh service * @author Bartlomiej Polot */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_mesh_service.h" #include "mesh.h" #include "mesh_protocol.h" #define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__) /******************************************************************************/ /************************ DATA STRUCTURES ****************************/ /******************************************************************************/ /** * Transmission queue to the service */ struct GNUNET_MESH_TransmitHandle { /** * Double Linked list */ struct GNUNET_MESH_TransmitHandle *next; /** * Double Linked list */ struct GNUNET_MESH_TransmitHandle *prev; /** * Channel this message is sent on / for (may be NULL for control messages). */ struct GNUNET_MESH_Channel *channel; /** * Callback to obtain the message to transmit, or NULL if we * got the message in 'data'. Notice that messages built * by 'notify' need to be encapsulated with information about * the 'target'. */ GNUNET_CONNECTION_TransmitReadyNotify notify; /** * Closure for 'notify' */ void *notify_cls; /** * How long is this message valid. Once the timeout has been * reached, the message must no longer be sent. If this * is a message with a 'notify' callback set, the 'notify' * function should be called with 'buf' NULL and size 0. */ struct GNUNET_TIME_Absolute timeout; /** * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL. */ size_t size; }; union MeshInfoCB { /** * Channel callback. */ GNUNET_MESH_ChannelCB channel_cb; /** * Monitor callback */ GNUNET_MESH_PeersCB peers_cb; /** * Monitor callback */ GNUNET_MESH_PeerCB peer_cb; /** * Monitor callback */ GNUNET_MESH_TunnelsCB tunnels_cb; /** * Tunnel callback. */ GNUNET_MESH_TunnelCB tunnel_cb; }; /** * Opaque handle to the service. */ struct GNUNET_MESH_Handle { /** * Handle to the server connection, to send messages later */ struct GNUNET_CLIENT_Connection *client; /** * Set of handlers used for processing incoming messages in the channels */ const struct GNUNET_MESH_MessageHandler *message_handlers; /** * Number of handlers in the handlers array. */ unsigned int n_handlers; /** * Ports open. */ const uint32_t *ports; /** * Number of ports. */ unsigned int n_ports; /** * Double linked list of the channels this client is connected to, head. */ struct GNUNET_MESH_Channel *channels_head; /** * Double linked list of the channels this client is connected to, tail. */ struct GNUNET_MESH_Channel *channels_tail; /** * Callback for inbound channel creation */ GNUNET_MESH_InboundChannelNotificationHandler *new_channel; /** * Callback for inbound channel disconnection */ GNUNET_MESH_ChannelEndHandler *cleaner; /** * Handle to cancel pending transmissions in case of disconnection */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Closure for all the handlers given by the client */ void *cls; /** * Messages to send to the service, head. */ struct GNUNET_MESH_TransmitHandle *th_head; /** * Messages to send to the service, tail. */ struct GNUNET_MESH_TransmitHandle *th_tail; /** * chid of the next channel to create (to avoid reusing IDs often) */ MESH_ChannelNumber next_chid; /** * Have we started the task to receive messages from the service * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message. */ int in_receive; /** * Configuration given by the client, in case of reconnection */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Time to the next reconnect in case one reconnect fails */ struct GNUNET_TIME_Relative reconnect_time; /** * Task for trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Callback for an info task (only one active at a time). */ union MeshInfoCB info_cb; /** * Info callback closure for @c info_cb. */ void *info_cls; }; /** * Description of a peer */ struct GNUNET_MESH_Peer { /** * ID of the peer in short form */ GNUNET_PEER_Id id; /** * Channel this peer belongs to */ struct GNUNET_MESH_Channel *t; }; /** * Opaque handle to a channel. */ struct GNUNET_MESH_Channel { /** * DLL next */ struct GNUNET_MESH_Channel *next; /** * DLL prev */ struct GNUNET_MESH_Channel *prev; /** * Handle to the mesh this channel belongs to */ struct GNUNET_MESH_Handle *mesh; /** * Local ID of the channel */ MESH_ChannelNumber chid; /** * Port number. */ uint32_t port; /** * Other end of the channel. */ GNUNET_PEER_Id peer; /** * Any data the caller wants to put in here */ void *ctx; /** * Size of packet queued in this channel */ unsigned int packet_size; /** * Channel options: reliability, etc. */ enum GNUNET_MESH_ChannelOption options; /** * Are we allowed to send to the service? */ int allow_send; }; /** * Implementation state for mesh's message queue. */ struct MeshMQState { /** * The current transmit handle, or NULL * if no transmit is active. */ struct GNUNET_MESH_TransmitHandle *th; /** * Channel to send the data over. */ struct GNUNET_MESH_Channel *channel; }; /******************************************************************************/ /*********************** DECLARATIONS *************************/ /******************************************************************************/ /** * Function called to send a message to the service. * "buf" will be NULL and "size" zero if the socket was closed for writing in * the meantime. * * @param cls closure, the mesh handle * @param size number of bytes available in buf * @param buf where the callee should write the connect message * @return number of bytes written to buf */ static size_t send_callback (void *cls, size_t size, void *buf); /******************************************************************************/ /*********************** AUXILIARY FUNCTIONS *************************/ /******************************************************************************/ /** * Check if transmission is a payload packet. * * @param th Transmission handle. * * @return GNUNET_YES if it is a payload packet, * GNUNET_NO if it is a mesh management packet. */ static int th_is_payload (struct GNUNET_MESH_TransmitHandle *th) { return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO; } /** * Check whether there is any message ready in the queue and find the size. * * @param h Mesh handle. * * @return The size of the first ready message in the queue, * 0 if there is none. */ static size_t message_ready_size (struct GNUNET_MESH_Handle *h) { struct GNUNET_MESH_TransmitHandle *th; struct GNUNET_MESH_Channel *ch; for (th = h->th_head; NULL != th; th = th->next) { ch = th->channel; if (GNUNET_NO == th_is_payload (th)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "# message internal\n"); return th->size; } if (GNUNET_YES == ch->allow_send) { LOG (GNUNET_ERROR_TYPE_DEBUG, "# message payload ok\n"); return th->size; } } return 0; } /** * Get the channel handler for the channel specified by id from the given handle * @param h Mesh handle * @param chid ID of the wanted channel * @return handle to the required channel or NULL if not found */ static struct GNUNET_MESH_Channel * retrieve_channel (struct GNUNET_MESH_Handle *h, MESH_ChannelNumber chid) { struct GNUNET_MESH_Channel *ch; ch = h->channels_head; while (ch != NULL) { if (ch->chid == chid) return ch; ch = ch->next; } return NULL; } /** * Create a new channel and insert it in the channel list of the mesh handle * * @param h Mesh handle * @param chid Desired chid of the channel, 0 to assign one automatically. * * @return Handle to the created channel. */ static struct GNUNET_MESH_Channel * create_channel (struct GNUNET_MESH_Handle *h, MESH_ChannelNumber chid) { struct GNUNET_MESH_Channel *ch; ch = GNUNET_new (struct GNUNET_MESH_Channel); GNUNET_CONTAINER_DLL_insert (h->channels_head, h->channels_tail, ch); ch->mesh = h; if (0 == chid) { ch->chid = h->next_chid; while (NULL != retrieve_channel (h, h->next_chid)) { h->next_chid++; h->next_chid &= ~GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; h->next_chid |= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI; } } else { ch->chid = chid; } ch->allow_send = GNUNET_NO; return ch; } /** * Destroy the specified channel. * - Destroys all peers, calling the disconnect callback on each if needed * - Cancels all outgoing traffic for that channel, calling respective notifys * - Calls cleaner if channel was inbound * - Frees all memory used * * @param ch Pointer to the channel. * @param call_cleaner Whether to call the cleaner handler. * * @return Handle to the required channel or NULL if not found. */ static void destroy_channel (struct GNUNET_MESH_Channel *ch, int call_cleaner) { struct GNUNET_MESH_Handle *h; struct GNUNET_MESH_TransmitHandle *th; struct GNUNET_MESH_TransmitHandle *next; LOG (GNUNET_ERROR_TYPE_DEBUG, " destroy_channel %X\n", ch->chid); if (NULL == ch) { GNUNET_break (0); return; } h = ch->mesh; GNUNET_CONTAINER_DLL_remove (h->channels_head, h->channels_tail, ch); /* signal channel destruction */ if ( (NULL != h->cleaner) && (0 != ch->peer) && (GNUNET_YES == call_cleaner) ) { LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cleaner\n"); h->cleaner (h->cls, ch, ch->ctx); } /* check that clients did not leave messages behind in the queue */ for (th = h->th_head; NULL != th; th = next) { next = th->next; if (th->channel != ch) continue; /* Clients should have aborted their requests already. * Management traffic should be ok, as clients can't cancel that. * If the service crashed and we are reconnecting, it's ok. */ GNUNET_break (GNUNET_NO == th_is_payload (th) || GNUNET_NO == h->in_receive); GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); /* clean up request */ if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task) GNUNET_SCHEDULER_cancel (th->timeout_task); GNUNET_free (th); } /* if there are no more pending requests with mesh service, cancel active request */ /* Note: this should be unnecessary... */ if ((0 == message_ready_size (h)) && (NULL != h->th)) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (0 != ch->peer) GNUNET_PEER_change_rc (ch->peer, -1); GNUNET_free (ch); return; } /** * Notify client that the transmission has timed out * * @param cls closure * @param tc task context */ static void timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_MESH_TransmitHandle *th = cls; struct GNUNET_MESH_Handle *mesh; mesh = th->channel->mesh; GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th); th->channel->packet_size = 0; if (GNUNET_YES == th_is_payload (th)) th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); if ((0 == message_ready_size (mesh)) && (NULL != mesh->th)) { /* nothing ready to transmit, no point in asking for transmission */ GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th); mesh->th = NULL; } } /** * Add a transmit handle to the transmission queue and set the * timeout if needed. * * @param h mesh handle with the queue head and tail * @param th handle to the packet to be transmitted */ static void add_to_queue (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_TransmitHandle *th) { GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th); if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == th->timeout.abs_value_us) return; th->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (th->timeout), &timeout_transmission, th); } /** * Auxiliary function to send an already constructed packet to the service. * Takes care of creating a new queue element, copying the message and * calling the tmt_rdy function if necessary. * * @param h mesh handle * @param msg message to transmit * @param channel channel this send is related to (NULL if N/A) */ static void send_packet (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *msg, struct GNUNET_MESH_Channel *channel); /** * Send an ack on the channel to confirm the processing of a message. * * @param ch Channel on which to send the ACK. */ static void send_ack (struct GNUNET_MESH_Channel *ch) { struct GNUNET_MESH_LocalAck msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on channel %X\n", ch->chid); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); msg.header.size = htons (sizeof (msg)); msg.channel_id = htonl (ch->chid); send_packet (ch->mesh, &msg.header, ch); return; } /** * Reconnect callback: tries to reconnect again after a failer previous * reconnecttion * @param cls closure (mesh handle) * @param tc task context */ static void reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Send a connect packet to the service with the applications and types * requested by the user. * * @param h The mesh handle. * */ static void send_connect (struct GNUNET_MESH_Handle *h) { size_t size; size = sizeof (struct GNUNET_MESH_ClientConnect); size += h->n_ports * sizeof (uint32_t); { char buf[size] GNUNET_ALIGN; struct GNUNET_MESH_ClientConnect *msg; uint32_t *ports; uint16_t i; /* build connection packet */ msg = (struct GNUNET_MESH_ClientConnect *) buf; msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT); msg->header.size = htons (size); ports = (uint32_t *) &msg[1]; for (i = 0; i < h->n_ports; i++) { ports[i] = htonl (h->ports[i]); LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", h->ports[i]); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending %lu bytes long message with %u ports\n", ntohs (msg->header.size), h->n_ports); send_packet (h, &msg->header, NULL); } } /** * Reconnect to the service, retransmit all infomation to try to restore the * original state. * * @param h handle to the mesh * * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...) */ static int do_reconnect (struct GNUNET_MESH_Handle *h) { LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h); LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); /* disconnect */ if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); } /* connect again */ h->client = GNUNET_CLIENT_connect ("mesh", h->cfg); if (h->client == NULL) { h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, &reconnect_cbk, h); h->reconnect_time = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, GNUNET_TIME_relative_multiply (h->reconnect_time, 2)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Next retry in %s\n", GNUNET_STRINGS_relative_time_to_string (h->reconnect_time, GNUNET_NO)); GNUNET_break (0); return GNUNET_NO; } else { h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; } send_connect (h); return GNUNET_YES; } /** * Reconnect callback: tries to reconnect again after a failer previous * reconnecttion * @param cls closure (mesh handle) * @param tc task context */ static void reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_MESH_Handle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; do_reconnect (h); } /** * Reconnect to the service, retransmit all infomation to try to restore the * original state. * * @param h handle to the mesh * * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...) */ static void reconnect (struct GNUNET_MESH_Handle *h) { struct GNUNET_MESH_Channel *ch; struct GNUNET_MESH_Channel *next; LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT, destroying all channels\n"); h->in_receive = GNUNET_NO; for (ch = h->channels_head; NULL != ch; ch = next) { next = ch->next; destroy_channel (ch, GNUNET_YES); } if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task) h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, &reconnect_cbk, h); } /******************************************************************************/ /*********************** RECEIVE HANDLERS ****************************/ /******************************************************************************/ /** * Process the new channel notification and add it to the channels in the handle * * @param h The mesh handle * @param msg A message with the details of the new incoming channel */ static void process_channel_created (struct GNUNET_MESH_Handle *h, const struct GNUNET_MESH_ChannelMessage *msg) { struct GNUNET_MESH_Channel *ch; MESH_ChannelNumber chid; uint32_t port; chid = ntohl (msg->channel_id); port = ntohl (msg->port); LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X:%u\n", chid, port); if (chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) { GNUNET_break (0); return; } if (NULL != h->new_channel) { void *ctx; ch = create_channel (h, chid); ch->allow_send = GNUNET_NO; ch->peer = GNUNET_PEER_intern (&msg->peer); ch->mesh = h; ch->chid = chid; ch->port = port; ch->options = ntohl (msg->opt); LOG (GNUNET_ERROR_TYPE_DEBUG, " created channel %p\n", ch); ctx = h->new_channel (h->cls, ch, &msg->peer, ch->port, ch->options); if (NULL != ctx) ch->ctx = ctx; LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n"); } else { struct GNUNET_MESH_ChannelMessage d_msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming channels\n"); d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY); d_msg.header.size = htons (sizeof (struct GNUNET_MESH_ChannelMessage)); d_msg.channel_id = msg->channel_id; memset (&d_msg.peer, 0, sizeof (struct GNUNET_PeerIdentity)); d_msg.port = 0; d_msg.opt = 0; send_packet (h, &d_msg.header, NULL); } return; } /** * Process the channel destroy notification and free associated resources * * @param h The mesh handle * @param msg A message with the details of the channel being destroyed */ static void process_channel_destroy (struct GNUNET_MESH_Handle *h, const struct GNUNET_MESH_ChannelMessage *msg) { struct GNUNET_MESH_Channel *ch; MESH_ChannelNumber chid; LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel Destroy received from service\n"); chid = ntohl (msg->channel_id); ch = retrieve_channel (h, chid); if (NULL == ch) { LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X unknown\n", chid); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " destroying channel %X\n", ch->chid); destroy_channel (ch, GNUNET_YES); } /** * Process the incoming data packets, call appropriate handlers. * * @param h The mesh handle * @param message A message encapsulating the data */ static void process_incoming_data (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { const struct GNUNET_MessageHeader *payload; const struct GNUNET_MESH_MessageHandler *handler; struct GNUNET_MESH_LocalData *dmsg; struct GNUNET_MESH_Channel *ch; size_t size; unsigned int i; uint16_t type; LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n"); dmsg = (struct GNUNET_MESH_LocalData *) message; ch = retrieve_channel (h, ntohl (dmsg->id)); payload = (struct GNUNET_MessageHeader *) &dmsg[1]; LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on channel %s [%X]\n", GM_f2s (ch->chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV), GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), ntohl (dmsg->id)); size = ntohs (message->size); LOG (GNUNET_ERROR_TYPE_DEBUG, " %u bytes\n", size); if (NULL == ch) { /* Channel was ignored/destroyed, probably service didn't get it yet */ LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n"); return; } type = ntohs (payload->type); size = ntohs (payload->size); LOG (GNUNET_ERROR_TYPE_DEBUG, " payload type %s\n", GM_m2s (type)); for (i = 0; i < h->n_handlers; i++) { handler = &h->message_handlers[i]; LOG (GNUNET_ERROR_TYPE_DEBUG, " checking handler for type %u\n", handler->type); if (handler->type == type) { if (GNUNET_OK != handler->callback (h->cls, ch, &ch->ctx, payload)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n"); GNUNET_MESH_channel_destroy (ch); return; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "callback completed successfully\n"); return; } } } } /** * Process a local ACK message, enabling the client to send * more data to the service. * * @param h Mesh handle. * @param message Message itself. */ static void process_ack (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalAck *msg; struct GNUNET_MESH_Channel *ch; MESH_ChannelNumber chid; LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n"); msg = (struct GNUNET_MESH_LocalAck *) message; chid = ntohl (msg->channel_id); ch = retrieve_channel (h, chid); if (NULL == ch) { LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK on unknown channel %X\n", chid); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X!\n", ch->chid); ch->allow_send = GNUNET_YES; if (NULL == h->th && 0 < ch->packet_size) { LOG (GNUNET_ERROR_TYPE_DEBUG, " tmt rdy was NULL, requesting!\n"); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ch->packet_size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_callback, h); } } /* * Process a local reply about info on all channels, pass info to the user. * * @param h Mesh handle. * @param message Message itself. */ // static void // process_get_channels (struct GNUNET_MESH_Handle *h, // const struct GNUNET_MessageHeader *message) // { // struct GNUNET_MESH_LocalInfo *msg; // // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Channels messasge received\n"); // // if (NULL == h->channels_cb) // { // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); // return; // } // // msg = (struct GNUNET_MESH_LocalInfo *) message; // if (ntohs (message->size) != // (sizeof (struct GNUNET_MESH_LocalInfo) + // sizeof (struct GNUNET_PeerIdentity))) // { // GNUNET_break_op (0); // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, // "Get channels message: size %hu - expected %u\n", // ntohs (message->size), // sizeof (struct GNUNET_MESH_LocalInfo)); // return; // } // h->channels_cb (h->channels_cls, // ntohl (msg->channel_id), // &msg->owner, // &msg->destination); // } /* * Process a local monitor_channel reply, pass info to the user. * * @param h Mesh handle. * @param message Message itself. */ // static void // process_show_channel (struct GNUNET_MESH_Handle *h, // const struct GNUNET_MessageHeader *message) // { // struct GNUNET_MESH_LocalInfo *msg; // size_t esize; // // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Channel messasge received\n"); // // if (NULL == h->channel_cb) // { // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); // return; // } // // /* Verify message sanity */ // msg = (struct GNUNET_MESH_LocalInfo *) message; // esize = sizeof (struct GNUNET_MESH_LocalInfo); // if (ntohs (message->size) != esize) // { // GNUNET_break_op (0); // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, // "Show channel message: size %hu - expected %u\n", // ntohs (message->size), // esize); // // h->channel_cb (h->channel_cls, NULL, NULL); // h->channel_cb = NULL; // h->channel_cls = NULL; // // return; // } // // h->channel_cb (h->channel_cls, // &msg->destination, // &msg->owner); // } /** * Process a local reply about info on all tunnels, pass info to the user. * * @param h Mesh handle. * @param message Message itself. */ static void process_get_peers (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalInfoPeer *msg; uint16_t size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Peer messasge received\n"); if (NULL == h->info_cb.peers_cb) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); return; } size = ntohs (message->size); if (sizeof (struct GNUNET_MESH_LocalInfoPeer) > size) { h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0); h->info_cb.peers_cb = NULL; h->info_cls = NULL; return; } msg = (struct GNUNET_MESH_LocalInfoPeer *) message; h->info_cb.peers_cb (h->info_cls, &msg->destination, (int) ntohs (msg->tunnel), (unsigned int ) ntohs (msg->paths), 0); } /** * Process a local peer info reply, pass info to the user. * * @param h Mesh handle. * @param message Message itself. */ static void process_get_peer (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalInfoTunnel *msg; size_t esize; size_t msize; unsigned int ch_n; unsigned int c_n; struct GNUNET_MESH_Hash *conns; MESH_ChannelNumber *chns; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n"); if (NULL == h->info_cb.tunnel_cb) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); return; } /* Verify message sanity */ msg = (struct GNUNET_MESH_LocalInfoTunnel *) message; msize = ntohs (message->size); esize = sizeof (struct GNUNET_MESH_LocalInfoTunnel); if (esize > msize) { GNUNET_break_op (0); h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); goto clean_cls; } ch_n = ntohl (msg->channels); c_n = ntohl (msg->connections); esize += ch_n * sizeof (MESH_ChannelNumber); esize += c_n * sizeof (struct GNUNET_MESH_Hash); if (msize != esize) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n", msize, esize, ch_n, c_n); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n", sizeof (struct GNUNET_MESH_LocalInfoTunnel), sizeof (MESH_ChannelNumber), sizeof (struct GNUNET_HashCode)); h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); goto clean_cls; } /* Call Callback with tunnel info. */ conns = (struct GNUNET_MESH_Hash *) &msg[1]; chns = (MESH_ChannelNumber *) &conns[c_n]; h->info_cb.tunnel_cb (h->info_cls, &msg->destination, ch_n, c_n, chns, conns, ntohs (msg->estate), ntohs (msg->cstate)); clean_cls: h->info_cb.tunnel_cb = NULL; h->info_cls = NULL; } /** * Process a local reply about info on all tunnels, pass info to the user. * * @param h Mesh handle. * @param message Message itself. */ static void process_get_tunnels (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalInfoTunnel *msg; uint16_t size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnels messasge received\n"); if (NULL == h->info_cb.tunnels_cb) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); return; } size = ntohs (message->size); if (sizeof (struct GNUNET_MESH_LocalInfoTunnel) > size) { h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0); h->info_cb.tunnels_cb = NULL; h->info_cls = NULL; return; } msg = (struct GNUNET_MESH_LocalInfoTunnel *) message; h->info_cb.tunnels_cb (h->info_cls, &msg->destination, ntohl (msg->channels), ntohl (msg->connections), ntohs (msg->estate), ntohs (msg->cstate)); } /** * Process a local tunnel info reply, pass info to the user. * * @param h Mesh handle. * @param message Message itself. */ static void process_get_tunnel (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalInfoTunnel *msg; size_t esize; size_t msize; unsigned int ch_n; unsigned int c_n; struct GNUNET_MESH_Hash *conns; MESH_ChannelNumber *chns; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n"); if (NULL == h->info_cb.tunnel_cb) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); return; } /* Verify message sanity */ msg = (struct GNUNET_MESH_LocalInfoTunnel *) message; msize = ntohs (message->size); esize = sizeof (struct GNUNET_MESH_LocalInfoTunnel); if (esize > msize) { GNUNET_break_op (0); h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); goto clean_cls; } ch_n = ntohl (msg->channels); c_n = ntohl (msg->connections); esize += ch_n * sizeof (MESH_ChannelNumber); esize += c_n * sizeof (struct GNUNET_MESH_Hash); if (msize != esize) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n", msize, esize, ch_n, c_n); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n", sizeof (struct GNUNET_MESH_LocalInfoTunnel), sizeof (MESH_ChannelNumber), sizeof (struct GNUNET_HashCode)); h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); goto clean_cls; } /* Call Callback with tunnel info. */ conns = (struct GNUNET_MESH_Hash *) &msg[1]; chns = (MESH_ChannelNumber *) &conns[c_n]; h->info_cb.tunnel_cb (h->info_cls, &msg->destination, ch_n, c_n, chns, conns, ntohs (msg->estate), ntohs (msg->cstate)); clean_cls: h->info_cb.tunnel_cb = NULL; h->info_cls = NULL; } /** * Function to process all messages received from the service * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void msg_received (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_MESH_Handle *h = cls; uint16_t type; if (msg == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Mesh service disconnected, reconnecting\n", h); reconnect (h); return; } type = ntohs (msg->type); LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n", GM_m2s (type)); switch (type) { /* Notify of a new incoming channel */ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: process_channel_created (h, (struct GNUNET_MESH_ChannelMessage *) msg); break; /* Notify of a channel disconnection */ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: /* TODO separate(gid problem)*/ case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK: process_channel_destroy (h, (struct GNUNET_MESH_ChannelMessage *) msg); break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA: process_incoming_data (h, msg); break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: process_ack (h, msg); break; // case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNELS: // process_get_channels (h, msg); // break; // case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL: // process_show_channel (h, msg); // break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS: process_get_peers (h, msg); break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEER: process_get_peer (h, msg); break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS: process_get_tunnels (h, msg); break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL: process_get_tunnel (h, msg); break; // case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL: // process_show_channel (h, msg); // break; default: /* We shouldn't get any other packages, log and ignore */ LOG (GNUNET_ERROR_TYPE_WARNING, "unsolicited message form service (type %s)\n", GM_m2s (ntohs (msg->type))); } LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n"); if (GNUNET_YES == h->in_receive) { GNUNET_CLIENT_receive (h->client, &msg_received, h, GNUNET_TIME_UNIT_FOREVER_REL); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "in receive off, not calling CLIENT_receive\n"); } } /******************************************************************************/ /************************ SEND FUNCTIONS ****************************/ /******************************************************************************/ /** * Function called to send a message to the service. * "buf" will be NULL and "size" zero if the socket was closed for writing in * the meantime. * * @param cls closure, the mesh handle * @param size number of bytes available in buf * @param buf where the callee should write the connect message * @return number of bytes written to buf */ static size_t send_callback (void *cls, size_t size, void *buf) { struct GNUNET_MESH_Handle *h = cls; struct GNUNET_MESH_TransmitHandle *th; struct GNUNET_MESH_TransmitHandle *next; struct GNUNET_MESH_Channel *ch; char *cbuf = buf; size_t tsize; size_t psize; size_t nsize; LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size); if ((0 == size) || (NULL == buf)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h); reconnect (h); h->th = NULL; return 0; } tsize = 0; next = h->th_head; nsize = message_ready_size (h); while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize)) { ch = th->channel; if (GNUNET_YES == th_is_payload (th)) { struct GNUNET_MESH_LocalData *dmsg; struct GNUNET_MessageHeader *mh; LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload\n"); if (GNUNET_NO == ch->allow_send) { /* This channel is not ready to transmit yet, try next message */ next = th->next; continue; } ch->packet_size = 0; GNUNET_assert (size >= th->size); dmsg = (struct GNUNET_MESH_LocalData *) cbuf; mh = (struct GNUNET_MessageHeader *) &dmsg[1]; psize = th->notify (th->notify_cls, size - sizeof (struct GNUNET_MESH_LocalData), mh); if (psize > 0) { psize += sizeof (struct GNUNET_MESH_LocalData); GNUNET_assert (size >= psize); dmsg->header.size = htons (psize); dmsg->id = htonl (ch->chid); dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA); LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload type %s\n", GM_m2s (ntohs (mh->type))); ch->allow_send = GNUNET_NO; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "# callback returned size 0, " "application canceled transmission\n"); } } else { struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1]; LOG (GNUNET_ERROR_TYPE_DEBUG, "# mesh internal traffic, type %s\n", GM_m2s (ntohs (mh->type))); memcpy (cbuf, &th[1], th->size); psize = th->size; } if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (th->timeout_task); GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); GNUNET_free (th); next = h->th_head; nsize = message_ready_size (h); cbuf += psize; size -= psize; tsize += psize; } LOG (GNUNET_ERROR_TYPE_DEBUG, "# total size: %u\n", tsize); h->th = NULL; size = message_ready_size (h); if (0 != size) { LOG (GNUNET_ERROR_TYPE_DEBUG, "# next size: %u\n", size); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_callback, h); } else { if (NULL != h->th_head) LOG (GNUNET_ERROR_TYPE_DEBUG, "# can't transmit any more\n"); else LOG (GNUNET_ERROR_TYPE_DEBUG, "# nothing left to transmit\n"); } if (GNUNET_NO == h->in_receive) { LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n"); h->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &msg_received, h, GNUNET_TIME_UNIT_FOREVER_REL); } LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n"); return tsize; } /** * Auxiliary function to send an already constructed packet to the service. * Takes care of creating a new queue element, copying the message and * calling the tmt_rdy function if necessary. * * @param h mesh handle * @param msg message to transmit * @param channel channel this send is related to (NULL if N/A) */ static void send_packet (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *msg, struct GNUNET_MESH_Channel *channel) { struct GNUNET_MESH_TransmitHandle *th; size_t msize; LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n", GM_m2s(ntohs(msg->type))); msize = ntohs (msg->size); th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize); th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; th->size = msize; th->channel = channel; memcpy (&th[1], msg, msize); add_to_queue (h, th); LOG (GNUNET_ERROR_TYPE_DEBUG, " queued\n"); if (NULL != h->th) return; LOG (GNUNET_ERROR_TYPE_DEBUG, " calling ntfy tmt rdy for %u bytes\n", msize); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, msize, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_callback, h); } /******************************************************************************/ /********************** API CALL DEFINITIONS *************************/ /******************************************************************************/ struct GNUNET_MESH_Handle * GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_MESH_InboundChannelNotificationHandler new_channel, GNUNET_MESH_ChannelEndHandler cleaner, const struct GNUNET_MESH_MessageHandler *handlers, const uint32_t *ports) { struct GNUNET_MESH_Handle *h; LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n"); h = GNUNET_new (struct GNUNET_MESH_Handle); LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h); h->cfg = cfg; h->new_channel = new_channel; h->cleaner = cleaner; h->client = GNUNET_CLIENT_connect ("mesh", cfg); if (h->client == NULL) { GNUNET_break (0); GNUNET_free (h); return NULL; } h->cls = cls; h->message_handlers = handlers; h->ports = ports; h->next_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_CLI; h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != ports && ports[0] != 0 && NULL == new_channel) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "no new channel handler given, ports parameter is useless!!\n"); } if ((NULL == ports || ports[0] == 0) && NULL != new_channel) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "no ports given, new channel handler will never be called!!\n"); } /* count handlers */ for (h->n_handlers = 0; handlers && handlers[h->n_handlers].type; h->n_handlers++) ; for (h->n_ports = 0; ports && ports[h->n_ports]; h->n_ports++) ; send_connect (h); LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n"); return h; } void GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) { struct GNUNET_MESH_Channel *ch; struct GNUNET_MESH_Channel *aux; struct GNUNET_MESH_TransmitHandle *th; LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n"); ch = handle->channels_head; while (NULL != ch) { aux = ch->next; if (ch->chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X not destroyed\n", ch->chid); } destroy_channel (ch, GNUNET_YES); ch = aux; } while ( (th = handle->th_head) != NULL) { struct GNUNET_MessageHeader *msg; /* Make sure it is an allowed packet (everything else should have been * already canceled). */ GNUNET_break (GNUNET_NO == th_is_payload (th)); msg = (struct GNUNET_MessageHeader *) &th[1]; switch (ntohs(msg->type)) { case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNELS: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEER: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS: break; default: GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n", ntohs(msg->type)); } GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th); GNUNET_free (th); } if (NULL != handle->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); handle->th = NULL; } if (NULL != handle->client) { GNUNET_CLIENT_disconnect (handle->client); handle->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task) { GNUNET_SCHEDULER_cancel(handle->reconnect_task); handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (handle); } /** * Create a new channel towards a remote peer. * * If the destination port is not open by any peer or the destination peer * does not accept the channel, #GNUNET_MESH_ChannelEndHandler will be called * for this channel. * * @param h mesh handle * @param channel_ctx client's channel context to associate with the channel * @param peer peer identity the channel should go to * @param port Port number. * @param options MeshOption flag field, with all desired option bits set to 1. * * @return handle to the channel */ struct GNUNET_MESH_Channel * GNUNET_MESH_channel_create (struct GNUNET_MESH_Handle *h, void *channel_ctx, const struct GNUNET_PeerIdentity *peer, uint32_t port, enum GNUNET_MESH_ChannelOption options) { struct GNUNET_MESH_Channel *ch; struct GNUNET_MESH_ChannelMessage msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new channel to %s:%u\n", GNUNET_i2s (peer), port); ch = create_channel (h, 0); LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", ch); LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", ch->chid); ch->ctx = channel_ctx; ch->peer = GNUNET_PEER_intern (peer); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE); msg.header.size = htons (sizeof (struct GNUNET_MESH_ChannelMessage)); msg.channel_id = htonl (ch->chid); msg.port = htonl (port); msg.peer = *peer; msg.opt = htonl (options); ch->allow_send = 0; send_packet (h, &msg.header, ch); return ch; } void GNUNET_MESH_channel_destroy (struct GNUNET_MESH_Channel *channel) { struct GNUNET_MESH_Handle *h; struct GNUNET_MESH_ChannelMessage msg; struct GNUNET_MESH_TransmitHandle *th; LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying channel\n"); h = channel->mesh; msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY); msg.header.size = htons (sizeof (struct GNUNET_MESH_ChannelMessage)); msg.channel_id = htonl (channel->chid); memset (&msg.peer, 0, sizeof (struct GNUNET_PeerIdentity)); msg.port = 0; msg.opt = 0; th = h->th_head; while (th != NULL) { struct GNUNET_MESH_TransmitHandle *aux; if (th->channel == channel) { aux = th->next; /* FIXME call the handler? */ if (GNUNET_YES == th_is_payload (th)) th->notify (th->notify_cls, 0, NULL); GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); GNUNET_free (th); th = aux; } else th = th->next; } destroy_channel (channel, GNUNET_YES); send_packet (h, &msg.header, NULL); } /** * Get information about a channel. * * @param channel Channel handle. * @param option Query (GNUNET_MESH_OPTION_*). * @param ... dependant on option, currently not used * * @return Union with an answer to the query. */ const union GNUNET_MESH_ChannelInfo * GNUNET_MESH_channel_get_info (struct GNUNET_MESH_Channel *channel, enum GNUNET_MESH_ChannelOption option, ...) { static int bool_flag; const union GNUNET_MESH_ChannelInfo *ret; switch (option) { case GNUNET_MESH_OPTION_NOBUFFER: case GNUNET_MESH_OPTION_RELIABLE: case GNUNET_MESH_OPTION_OOORDER: if (0 != (option & channel->options)) bool_flag = GNUNET_YES; else bool_flag = GNUNET_NO; ret = (const union GNUNET_MESH_ChannelInfo *) &bool_flag; break; case GNUNET_MESH_OPTION_PEER: ret = (const union GNUNET_MESH_ChannelInfo *) GNUNET_PEER_resolve2 (channel->peer); break; default: GNUNET_break (0); return NULL; } return ret; } struct GNUNET_MESH_TransmitHandle * GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Channel *channel, int cork, struct GNUNET_TIME_Relative maxdelay, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { struct GNUNET_MESH_TransmitHandle *th; GNUNET_assert (NULL != channel); LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", channel->chid); LOG (GNUNET_ERROR_TYPE_DEBUG, " allow_send %d\n", channel->allow_send); if (channel->chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n"); else LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size); GNUNET_assert (NULL != notify); GNUNET_assert (0 == channel->packet_size); // Only one data packet allowed th = GNUNET_new (struct GNUNET_MESH_TransmitHandle); th->channel = channel; th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); th->size = notify_size + sizeof (struct GNUNET_MESH_LocalData); channel->packet_size = th->size; LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size); th->notify = notify; th->notify_cls = notify_cls; add_to_queue (channel->mesh, th); if (NULL != channel->mesh->th) return th; if (GNUNET_NO == channel->allow_send) return th; LOG (GNUNET_ERROR_TYPE_DEBUG, " call client notify tmt rdy\n"); channel->mesh->th = GNUNET_CLIENT_notify_transmit_ready (channel->mesh->client, th->size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &send_callback, channel->mesh); LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n"); return th; } void GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th) { struct GNUNET_MESH_Handle *mesh; th->channel->packet_size = 0; mesh = th->channel->mesh; if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (th->timeout_task); GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th); GNUNET_free (th); if ((0 == message_ready_size (mesh)) && (NULL != mesh->th)) { /* queue empty, no point in asking for transmission */ GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th); mesh->th = NULL; } } void GNUNET_MESH_receive_done (struct GNUNET_MESH_Channel *channel) { send_ack (channel); } static void send_info_request (struct GNUNET_MESH_Handle *h, uint16_t type) { struct GNUNET_MessageHeader msg; msg.size = htons (sizeof (msg)); msg.type = htons (type); send_packet (h, &msg, NULL); } /** * Request information about peers known to the running mesh service. * The callback will be called for every peer known to the service. * Only one info request (of any kind) can be active at once. * * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_get_peers (struct GNUNET_MESH_Handle *h, GNUNET_MESH_PeersCB callback, void *callback_cls) { if (NULL != h->info_cb.peers_cb) { GNUNET_break (0); return GNUNET_SYSERR; } send_info_request (h, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEERS); h->info_cb.peers_cb = callback; h->info_cls = callback_cls; return GNUNET_OK; } /** * Cancel a peer info request. The callback will not be called (anymore). * * WARNING: unstable API, likely to change in the future! * * @param h Mesh handle. * * @return Closure given to GNUNET_MESH_get_peers. */ void * GNUNET_MESH_get_peers_cancel (struct GNUNET_MESH_Handle *h) { void *cls; cls = h->info_cls; h->info_cb.peers_cb = NULL; h->info_cls = NULL; return cls; } /** * Request information about a peer known to the running mesh peer. * The callback will be called for the tunnel once. * Only one info request (of any kind) can be active at once. * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param id Peer whose tunnel to examine. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_get_peer (struct GNUNET_MESH_Handle *h, const struct GNUNET_PeerIdentity *id, GNUNET_MESH_PeerCB callback, void *callback_cls) { struct GNUNET_MESH_LocalInfo msg; if (NULL != h->info_cb.peer_cb) { GNUNET_break (0); return GNUNET_SYSERR; } memset (&msg, 0, sizeof (msg)); msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_PEER); msg.peer = *id; send_packet (h, &msg.header, NULL); h->info_cb.peer_cb = callback; h->info_cls = callback_cls; return GNUNET_OK; } /** * Request information about tunnels of the running mesh peer. * The callback will be called for every tunnel of the service. * Only one info request (of any kind) can be active at once. * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h, GNUNET_MESH_TunnelsCB callback, void *callback_cls) { if (NULL != h->info_cb.tunnels_cb) { GNUNET_break (0); return GNUNET_SYSERR; } send_info_request (h, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); h->info_cb.tunnels_cb = callback; h->info_cls = callback_cls; return GNUNET_OK; } /** * Cancel a monitor request. The monitor callback will not be called. * * @param h Mesh handle. * * @return Closure given to GNUNET_MESH_get_tunnels. */ void * GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h) { void *cls; h->info_cb.tunnels_cb = NULL; cls = h->info_cls; h->info_cls = NULL; return cls; } /** * Request information about a tunnel of the running mesh peer. * The callback will be called for the tunnel once. * Only one info request (of any kind) can be active at once. * * WARNING: unstable API, likely to change in the future! * * @param h Handle to the mesh peer. * @param id Peer whose tunnel to examine. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_get_tunnel (struct GNUNET_MESH_Handle *h, const struct GNUNET_PeerIdentity *id, GNUNET_MESH_TunnelCB callback, void *callback_cls) { struct GNUNET_MESH_LocalInfo msg; if (NULL != h->info_cb.tunnel_cb) { GNUNET_break (0); return GNUNET_SYSERR; } memset (&msg, 0, sizeof (msg)); msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL); msg.peer = *id; send_packet (h, &msg.header, NULL); h->info_cb.tunnel_cb = callback; h->info_cls = callback_cls; return GNUNET_OK; } /** * Request information about a specific channel of the running mesh peer. * * WARNING: unstable API, likely to change in the future! * FIXME Add destination option. * * @param h Handle to the mesh peer. * @param initiator ID of the owner of the channel. * @param channel_number Channel number. * @param callback Function to call with the requested data. * @param callback_cls Closure for @c callback. * * @return #GNUNET_OK / #GNUNET_SYSERR */ int GNUNET_MESH_show_channel (struct GNUNET_MESH_Handle *h, struct GNUNET_PeerIdentity *initiator, unsigned int channel_number, GNUNET_MESH_ChannelCB callback, void *callback_cls) { struct GNUNET_MESH_LocalInfo msg; if (NULL != h->info_cb.channel_cb) { GNUNET_break (0); return GNUNET_SYSERR; } msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_CHANNEL); msg.peer = *initiator; msg.channel_id = htonl (channel_number); // msg.reserved = 0; send_packet (h, &msg.header, NULL); h->info_cb.channel_cb = callback; h->info_cls = callback_cls; return GNUNET_OK; } /** * Function called to notify a client about the connection * begin ready to queue more data. "buf" will be * NULL and "size" zero if the connection was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t mesh_mq_ntr (void *cls, size_t size, void *buf) { struct GNUNET_MQ_Handle *mq = cls; struct MeshMQState *state = GNUNET_MQ_impl_state (mq); const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq); uint16_t msize; state->th = NULL; if (NULL == buf) { GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE); return 0; } msize = ntohs (msg->size); GNUNET_assert (msize <= size); memcpy (buf, msg, msize); GNUNET_MQ_impl_send_continue (mq); return msize; } /** * Signature of functions implementing the * sending functionality of a message queue. * * @param mq the message queue * @param msg the message to send * @param impl_state state of the implementation */ static void mesh_mq_send_impl (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state) { struct MeshMQState *state = impl_state; GNUNET_assert (NULL == state->th); state->th = GNUNET_MESH_notify_transmit_ready (state->channel, /* FIXME: add option for corking */ GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, ntohs (msg->size), mesh_mq_ntr, mq); } /** * Signature of functions implementing the * destruction of a message queue. * Implementations must not free 'mq', but should * take care of 'impl_state'. * * @param mq the message queue to destroy * @param impl_state state of the implementation */ static void mesh_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) { struct MeshMQState *state = impl_state; if (NULL != state->th) GNUNET_MESH_notify_transmit_ready_cancel (state->th); GNUNET_free (state); } /** * Create a message queue for a mesh channel. * The message queue can only be used to transmit messages, * not to receive them. * * @param channel the channel to create the message qeue for * @return a message queue to messages over the channel */ struct GNUNET_MQ_Handle * GNUNET_MESH_mq_create (struct GNUNET_MESH_Channel *channel) { struct GNUNET_MQ_Handle *mq; struct MeshMQState *state; state = GNUNET_new (struct MeshMQState); state->channel = channel; mq = GNUNET_MQ_queue_for_callbacks (mesh_mq_send_impl, mesh_mq_destroy_impl, NULL, /* FIXME: cancel impl. */ state, NULL, /* no msg handlers */ NULL, /* no err handlers */ NULL); /* no handler cls */ return mq; } gnunet-0.10.1/src/mesh/gnunet-service-mesh_hello.c0000644000175000017500000001145612320724374016767 00000000000000/* This file is part of GNUnet. (C) 2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_peerinfo_service.h" #include "mesh_protocol.h" #include "mesh_path.h" #include "gnunet-service-mesh_hello.h" #include "gnunet-service-mesh_peer.h" #define LOG(level, ...) GNUNET_log_from(level,"mesh-hll",__VA_ARGS__) /******************************************************************************/ /******************************** STRUCTS **********************************/ /******************************************************************************/ /******************************************************************************/ /******************************* GLOBALS ***********************************/ /******************************************************************************/ /** * Global handle to the statistics service. */ extern struct GNUNET_STATISTICS_Handle *stats; /** * Local peer own ID (memory efficient handle). */ extern GNUNET_PEER_Id myid; /** * Local peer own ID (full value). */ extern struct GNUNET_PeerIdentity my_full_id; /** * Don't try to recover tunnels if shutting down. */ extern int shutting_down; /** * Hello message of local peer. */ const struct GNUNET_HELLO_Message *mine; /** * Handle to peerinfo service. */ static struct GNUNET_PEERINFO_Handle *peerinfo; /** * Iterator context. */ struct GNUNET_PEERINFO_NotifyContext* nc; /******************************************************************************/ /******************************** STATIC ***********************************/ /******************************************************************************/ /** * Process each hello message received from peerinfo. * * @param cls Closure (unused). * @param peer Identity of the peer. * @param hello Hello of the peer. * @param err_msg Error message. */ static void got_hello (void *cls, const struct GNUNET_PeerIdentity *id, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { struct MeshPeer *peer; if (NULL == id || NULL == hello) { LOG (GNUNET_ERROR_TYPE_DEBUG, " hello with id %p and msg %p\n", id, hello); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " hello for %s (%d bytes), expires on %s\n", GNUNET_i2s (id), GNUNET_HELLO_size (hello), GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration(hello))); peer = GMP_get (id); GMP_set_hello (peer, hello); if (GMP_get_short_id (peer) == myid) { mine = GMP_get_hello (peer); LOG (GNUNET_ERROR_TYPE_DEBUG, " updated mine to %p\n", mine); } } /******************************************************************************/ /******************************** API ***********************************/ /******************************************************************************/ /** * Initialize the hello subsystem. * * @param c Configuration. */ void GMH_init (const struct GNUNET_CONFIGURATION_Handle *c) { LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); GNUNET_assert (NULL == nc); peerinfo = GNUNET_PEERINFO_connect (c); nc = GNUNET_PEERINFO_notify (c, GNUNET_NO, &got_hello, NULL); } /** * Shut down the hello subsystem. */ void GMH_shutdown () { if (NULL != nc) { GNUNET_PEERINFO_notify_cancel (nc); nc = NULL; } if (NULL != peerinfo) { GNUNET_PEERINFO_disconnect (peerinfo); peerinfo = NULL; } } /** * Get own hello message. * * @return Own hello message. */ const struct GNUNET_HELLO_Message * GMH_get_mine (void) { LOG (GNUNET_ERROR_TYPE_DEBUG, " mine is %p\n", mine); return mine; } /** * Get another peer's hello message. * * @param id ID of the peer whose hello message is requested. * * @return Hello message, if any (NULL possible). */ const struct GNUNET_HELLO_Message * GMH_get (const struct GNUNET_PeerIdentity *id) { return GMP_get_hello (GMP_get (id)); } /** * Convert a hello message to a string. * * @param h Hello message. */ char * GMH_2s (const struct GNUNET_HELLO_Message *h) { return "hello (TODO)"; } gnunet-0.10.1/src/template/0000755000175000017500000000000012320755623012501 500000000000000gnunet-0.10.1/src/template/gnunet-template.c0000644000175000017500000000417212225777502015706 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file template/gnunet-template.c * @brief template for writing a tool * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" /* #include "gnunet_template_service.h" */ /** * Final status code. */ static int ret; /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { /* main code here */ } /** * The main function. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { /* FIMXE: add options here */ GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-template", gettext_noop ("help text"), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-template.c */ gnunet-0.10.1/src/template/test_template_api.c0000644000175000017500000000210312225777502016270 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file template/test_template_api.c * @brief testcase for template.c */ #include "platform.h" static int check () { return 0; } int main (int argc, char *argv[]) { int ret; ret = check (); return ret; } /* end of test_template_api.c */ gnunet-0.10.1/src/template/Makefile.in0000644000175000017500000012125112320752064014464 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-template$(EXEEXT) libexec_PROGRAMS = gnunet-service-template$(EXEEXT) check_PROGRAMS = test_template_api$(EXEEXT) subdir = src/template DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgcfg_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_service_template_OBJECTS = \ gnunet-service-template.$(OBJEXT) gnunet_service_template_OBJECTS = \ $(am_gnunet_service_template_OBJECTS) am__DEPENDENCIES_1 = gnunet_service_template_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_gnunet_template_OBJECTS = gnunet-template.$(OBJEXT) gnunet_template_OBJECTS = $(am_gnunet_template_OBJECTS) gnunet_template_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_template_api_OBJECTS = test_template_api.$(OBJEXT) test_template_api_OBJECTS = $(am_test_template_api_OBJECTS) test_template_api_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gnunet_service_template_SOURCES) \ $(gnunet_template_SOURCES) $(test_template_api_SOURCES) DIST_SOURCES = $(gnunet_service_template_SOURCES) \ $(gnunet_template_SOURCES) $(test_template_api_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } DATA = $(dist_pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ template.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage gnunet_template_SOURCES = \ gnunet-template.c gnunet_template_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_template_SOURCES = \ gnunet-service-template.c gnunet_service_template_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_template_api_SOURCES = \ test_template_api.c test_template_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/template/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/template/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-service-template$(EXEEXT): $(gnunet_service_template_OBJECTS) $(gnunet_service_template_DEPENDENCIES) $(EXTRA_gnunet_service_template_DEPENDENCIES) @rm -f gnunet-service-template$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_template_OBJECTS) $(gnunet_service_template_LDADD) $(LIBS) gnunet-template$(EXEEXT): $(gnunet_template_OBJECTS) $(gnunet_template_DEPENDENCIES) $(EXTRA_gnunet_template_DEPENDENCIES) @rm -f gnunet-template$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_template_OBJECTS) $(gnunet_template_LDADD) $(LIBS) test_template_api$(EXEEXT): $(test_template_api_OBJECTS) $(test_template_api_DEPENDENCIES) $(EXTRA_test_template_api_DEPENDENCIES) @rm -f test_template_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_template_api_OBJECTS) $(test_template_api_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-template.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-template.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_template_api.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_template_api.log: test_template_api$(EXEEXT) @p='test_template_api$(EXEEXT)'; \ b='test_template_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libexecPROGRAMS clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_pkgcfgDATA \ uninstall-libexecPROGRAMS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dist_pkgcfgDATA \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-libexecPROGRAMS install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-dist_pkgcfgDATA \ uninstall-libexecPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/template/template.conf0000644000175000017500000000057212225230043015073 00000000000000[template] AUTOSTART = NO PORT = 9999 HOSTNAME = localhost BINARY = gnunet-service-template ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-template.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = gnunet-0.10.1/src/template/Makefile.am0000644000175000017500000000200612320751520014443 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ dist_pkgcfg_DATA = \ template.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif bin_PROGRAMS = \ gnunet-template libexec_PROGRAMS = \ gnunet-service-template gnunet_template_SOURCES = \ gnunet-template.c gnunet_template_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_template_SOURCES = \ gnunet-service-template.c gnunet_service_template_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) check_PROGRAMS = \ test_template_api if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_template_api_SOURCES = \ test_template_api.c test_template_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet-0.10.1/src/template/gnunet-service-template.c0000644000175000017500000000425012225777502017341 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file template/gnunet-service-template.c * @brief program that does template * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { /* FIXME: do clean up here */ } /** * Process template requests. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { /* FIXME: add handlers here! */ {NULL, NULL, 0, 0} }; /* FIXME: do setup here */ GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, NULL); } /** * The main function for the template service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "template", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-template.c */ gnunet-0.10.1/src/exit/0000755000175000017500000000000012320755627011643 500000000000000gnunet-0.10.1/src/exit/gnunet-helper-exit-windows.c0000644000175000017500000015520712225777502017155 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file exit/gnunet-helper-exit-windows.c * @brief the helper for the EXIT service in win32 builds. * Opens a virtual network-interface, sends data received on the if to stdout, * sends data received on stdin to the interface * @author Christian M. Fuchs * * The following list of people have reviewed this code and considered * it safe since the last modification (if you reviewed it, please * have your name added to the list): * */ #include #include #include #include #ifndef __MINGW64_VERSION_MAJOR #include #include #else #include #include #endif #include #include "platform.h" #include "tap-windows.h" /** * Need 'struct GNUNET_HashCode' and 'struct GNUNET_PeerIdentity'. */ #include "gnunet_crypto_lib.h" /** * Need 'struct GNUNET_MessageHeader'. */ #include "gnunet_common.h" /** * Need VPN message types. */ #include "gnunet_protocols.h" /** * Should we print (interesting|debug) messages that can happen during * normal operation? */ #define DEBUG GNUNET_NO #if DEBUG /* FIXME: define with varargs... */ #define LOG_DEBUG(msg) fprintf (stderr, "%s", msg); #else #define LOG_DEBUG(msg) do {} while (0) #endif /** * Will this binary be run in permissions testing mode? */ static boolean privilege_testing = FALSE; /** * Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE) */ #define MAX_SIZE 65536 /** * Name or Path+Name of our win32 driver. * The .sys and .cat files HAVE to be in the same location as this file! */ #define INF_FILE "share/gnunet/openvpn-tap32/tapw32/OemWin2k.inf" /** * Name or Path+Name of our win64 driver. * The .sys and .cat files HAVE to be in the same location as this file! */ #define INF_FILE64 "share/gnunet/openvpn-tap32/tapw64/OemWin2k.inf" /** * Hardware ID used in the inf-file. * This might change over time, as openvpn advances their driver */ #define HARDWARE_ID "tap0901" /** * Minimum major-id of the driver version we can work with */ #define TAP_WIN_MIN_MAJOR 9 /** * Minimum minor-id of the driver version we can work with. * v <= 7 has buggy IPv6. * v == 8 is broken for small IPv4 Packets */ #define TAP_WIN_MIN_MINOR 9 /** * Time in seconds to wait for our virtual device to go up after telling it to do so. * * openvpn doesn't specify a value, 4 seems sane for testing, even for openwrt * (in fact, 4 was chosen by a fair dice roll...) */ #define TAP32_POSTUP_WAITTIME 4 /** * Location of the network interface list resides in registry. */ #define INTERFACE_REGISTRY_LOCATION "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" /** * Our local process' PID. Used for creating a sufficiently unique additional * hardware ID for our device. */ static char secondary_hwid[LINE_LEN / 2]; /** * Device's visible Name, used to identify a network device in netsh. * eg: "Local Area Connection 9" */ static char device_visible_name[256]; /** * This is our own local instance of a virtual network interface * It is (somewhat) equivalent to using tun/tap in unixoid systems * * Upon initialization, we create such an device node. * Upon termination, we remove it again. * * If we crash this device might stay around. */ static HDEVINFO DeviceInfo = INVALID_HANDLE_VALUE; /** * Registry Key we hand over to windows to spawn a new virtual interface */ static SP_DEVINFO_DATA DeviceNode; /** * GUID of our virtual device in the form of * {12345678-1234-1234-1234-123456789abc} - in hex */ static char device_guid[256]; /** * Possible states of an IO facility. */ enum IO_State { /** * overlapped I/O is ready for work */ IOSTATE_READY = 0, /** * overlapped I/O has been queued */ IOSTATE_QUEUED, /** * overlapped I/O has finished, but is waiting for it's write-partner */ IOSTATE_WAITING, /** * there is a full buffer waiting */ IOSTATE_RESUME, /** * Operlapped IO states for facility objects * overlapped I/O has failed, stop processing */ IOSTATE_FAILED }; /** * A IO Object + read/writebuffer + buffer-size for windows asynchronous IO handling */ struct io_facility { /** * The mode the state machine associated with this object is in. */ enum IO_State facility_state; /** * If the path is open or blocked in general (used for quickly checking) */ BOOL path_open; // BOOL is winbool (int), NOT boolean (unsigned char)! /** * Windows Object-Handle (used for accessing TAP and STDIN/STDOUT) */ HANDLE handle; /** * Overlaped IO structure used for asynchronous IO in windows. */ OVERLAPPED overlapped; /** * Buffer for reading things to and writing from... */ unsigned char buffer[MAX_SIZE]; /** * How much of this buffer was used when reading or how much data can be written */ DWORD buffer_size; /** * Amount of data actually written or read by readfile/writefile. */ DWORD buffer_size_processed; /** * How much of this buffer we have written in total */ DWORD buffer_size_written; }; /** * ReOpenFile is only available as of XP SP2 and 2003 SP1 */ WINBASEAPI HANDLE WINAPI ReOpenFile (HANDLE, DWORD, DWORD, DWORD); /** * IsWow64Process definition for our is_win64, as this is a kernel function */ typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); /** * Determines if the host OS is win32 or win64 * * @return true if */ BOOL is_win64 () { #if defined(_WIN64) //this is a win64 binary, return TRUE; #elif defined(_WIN32) //this is a 32bit binary, and we need to check if we are running in WOW64 BOOL success = FALSE; BOOL on_wow64 = FALSE; LPFN_ISWOW64PROCESS IsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle ("kernel32"), "IsWow64Process"); if (NULL != IsWow64Process) success = IsWow64Process (GetCurrentProcess (), &on_wow64); return success && on_wow64; #endif } /** * Wrapper for executing a shellcommand in windows. * * @param command - the command + parameters to execute * @return * exitcode of the program executed, * * EINVAL (cmd/file not found) * * EPIPE (could not read STDOUT) */ static int execute_shellcommand (const char *command) { FILE *pipe; if ( (NULL == command) || (NULL == (pipe = _popen (command, "rt"))) ) return EINVAL; #if DEBUG fprintf (stderr, "DEBUG: Command output: \n"); char output[LINE_LEN]; while (NULL != fgets (output, sizeof (output), pipe)) fprintf (stderr, "%s", output); #endif return _pclose (pipe); } /** * @brief Sets the IPv6-Address given in address on the interface dev * * @param address the IPv6-Address * @param prefix_len the length of the network-prefix */ static int set_address6 (const char *address, unsigned long prefix_len) { int ret = EINVAL; char command[LINE_LEN]; struct sockaddr_in6 sa6; /* * parse the new address */ memset (&sa6, 0, sizeof (struct sockaddr_in6)); sa6.sin6_family = AF_INET6; if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr.s6_addr)) { fprintf (stderr, "ERROR: Failed to parse address `%s': %s\n", address, strerror (errno)); return -1; } /* * prepare the command */ snprintf (command, LINE_LEN, "netsh interface ipv6 add address \"%s\" %s/%d store=active", device_visible_name, address, prefix_len); /* * Set the address */ ret = execute_shellcommand (command); /* Did it work?*/ if (0 != ret) fprintf (stderr, "FATAL: Setting IPv6 address failed: %s\n", strerror (ret)); return ret; } /** * @brief Removes the IPv6-Address given in address from the interface dev * * @param address the IPv4-Address */ static void remove_address6 (const char *address) { char command[LINE_LEN]; int ret = EINVAL; // sanity checking was already done in set_address6 /* * prepare the command */ snprintf (command, LINE_LEN, "netsh interface ipv6 delete address \"%s\" store=persistent", device_visible_name); /* * Set the address */ ret = execute_shellcommand (command); /* Did it work?*/ if (0 != ret) fprintf (stderr, "FATAL: removing IPv6 address failed: %s\n", strerror (ret)); } /** * @brief Sets the IPv4-Address given in address on the interface dev * * @param address the IPv4-Address * @param mask the netmask */ static int set_address4 (const char *address, const char *mask) { int ret = EINVAL; char command[LINE_LEN]; struct sockaddr_in addr; addr.sin_family = AF_INET; /* * Parse the address */ if (1 != inet_pton (AF_INET, address, &addr.sin_addr.s_addr)) { fprintf (stderr, "ERROR: Failed to parse address `%s': %s\n", address, strerror (errno)); return -1; } // Set Device to Subnet-Mode? // do we really need tun.c:2925 ? /* * prepare the command */ snprintf (command, LINE_LEN, "netsh interface ipv4 add address \"%s\" %s %s store=active", device_visible_name, address, mask); /* * Set the address */ ret = execute_shellcommand (command); /* Did it work?*/ if (0 != ret) fprintf (stderr, "FATAL: Setting IPv4 address failed: %s\n", strerror (ret)); return ret; } /** * @brief Removes the IPv4-Address given in address from the interface dev * * @param address the IPv4-Address */ static void remove_address4 (const char *address) { char command[LINE_LEN]; int ret = EINVAL; // sanity checking was already done in set_address4 /* * prepare the command */ snprintf (command, LINE_LEN, "netsh interface ipv4 delete address \"%s\" gateway=all store=persistent", device_visible_name); /* * Set the address */ ret = execute_shellcommand (command); /* Did it work?*/ if (0 != ret) fprintf (stderr, "FATAL: removing IPv4 address failed: %s\n", strerror (ret)); } /** * Setup a new virtual interface to use for tunneling. * * @return: TRUE if setup was successful, else FALSE */ static BOOL setup_interface () { /* * where to find our inf-file. (+ the "full" path, after windows found") * * We do not directly input all the props here, because openvpn will update * these details over time. */ char inf_file_path[MAX_PATH]; char * temp_inf_filename; char hwidlist[LINE_LEN + 4]; char class_name[128]; GUID class_guid; int str_length = 0; /** * Set the device's hardware ID and add it to a list. * This information will later on identify this device in registry. */ strncpy (hwidlist, HARDWARE_ID, LINE_LEN); /** * this is kind of over-complicated, but allows keeps things independent of * how the openvpn-hwid is actually stored. * * A HWID list is double-\0 terminated and \0 separated */ str_length = strlen (hwidlist) + 1; strncpy (&hwidlist[str_length], secondary_hwid, LINE_LEN); str_length += strlen (&hwidlist[str_length]) + 1; /** * Locate the inf-file, we need to store it somewhere where the system can * find it. We need to pick the correct driver for win32/win64. */ if (is_win64()) GetFullPathNameA (INF_FILE64, MAX_PATH, inf_file_path, &temp_inf_filename); else GetFullPathNameA (INF_FILE, MAX_PATH, inf_file_path, &temp_inf_filename); fprintf (stderr, "INFO: Located our driver's .inf file at %s\n", inf_file_path); /** * Bootstrap our device info using the drivers inf-file */ if ( ! SetupDiGetINFClassA (inf_file_path, &class_guid, class_name, sizeof (class_name) / sizeof (char), NULL)) return FALSE; /** * Collect all the other needed information... * let the system fill our this form */ DeviceInfo = SetupDiCreateDeviceInfoList (&class_guid, NULL); if (DeviceInfo == INVALID_HANDLE_VALUE) return FALSE; DeviceNode.cbSize = sizeof (SP_DEVINFO_DATA); if ( ! SetupDiCreateDeviceInfoA (DeviceInfo, class_name, &class_guid, NULL, 0, DICD_GENERATE_ID, &DeviceNode)) return FALSE; /* Deploy all the information collected into the registry */ if ( ! SetupDiSetDeviceRegistryPropertyA (DeviceInfo, &DeviceNode, SPDRP_HARDWAREID, (LPBYTE) hwidlist, str_length * sizeof (char))) return FALSE; /* Install our new class(=device) into the system */ if ( ! SetupDiCallClassInstaller (DIF_REGISTERDEVICE, DeviceInfo, &DeviceNode)) return FALSE; /* This system call tends to take a while (several seconds!) on "modern" Windoze systems */ if ( ! UpdateDriverForPlugAndPlayDevicesA (NULL, secondary_hwid, inf_file_path, INSTALLFLAG_FORCE | INSTALLFLAG_NONINTERACTIVE, NULL)) //reboot required? NEVER! return FALSE; fprintf (stderr, "DEBUG: successfully created a network device\n"); return TRUE; } /** * Remove our new virtual interface to use for tunneling. * This function must be called AFTER setup_interface! * * @return: TRUE if destruction was successful, else FALSE */ static BOOL remove_interface () { SP_REMOVEDEVICE_PARAMS remove; if (INVALID_HANDLE_VALUE == DeviceInfo) return FALSE; remove.ClassInstallHeader.cbSize = sizeof (SP_CLASSINSTALL_HEADER); remove.HwProfile = 0; remove.Scope = DI_REMOVEDEVICE_GLOBAL; remove.ClassInstallHeader.InstallFunction = DIF_REMOVE; /* * 1. Prepare our existing device information set, and place the * uninstall related information into the structure */ if ( ! SetupDiSetClassInstallParamsA (DeviceInfo, (PSP_DEVINFO_DATA) & DeviceNode, &remove.ClassInstallHeader, sizeof (remove))) return FALSE; /* * 2. Uninstall the virtual interface using the class installer */ if ( ! SetupDiCallClassInstaller (DIF_REMOVE, DeviceInfo, (PSP_DEVINFO_DATA) & DeviceNode)) return FALSE; SetupDiDestroyDeviceInfoList (DeviceInfo); fprintf (stderr, "DEBUG: removed interface successfully\n"); return TRUE; } /** * Do all the lookup necessary to retrieve the inteface's actual name * off the registry. * * @return: TRUE if we were able to lookup the interface's name, else FALSE */ static BOOL resolve_interface_name () { SP_DEVINFO_LIST_DETAIL_DATA device_details; char pnp_instance_id [MAX_DEVICE_ID_LEN]; HKEY adapter_key_handle; LONG status; DWORD len; int i = 0; int retrys; BOOL retval = FALSE; char adapter[] = INTERFACE_REGISTRY_LOCATION; /* We can obtain the PNP instance ID from our setupapi handle */ device_details.cbSize = sizeof (device_details); if (CR_SUCCESS != CM_Get_Device_ID_ExA (DeviceNode.DevInst, (PCHAR) pnp_instance_id, MAX_DEVICE_ID_LEN, 0, //must be 0 NULL)) //hMachine, we are local return FALSE; fprintf (stderr, "DEBUG: Resolving interface name for network device %s\n",pnp_instance_id); /* Registry is incredibly slow, retry for up to 30 seconds to allow registry to refresh */ for (retrys = 0; retrys < 120 && !retval; retrys++) { /* sleep for 250ms*/ Sleep (250); /* Now we can use this ID to locate the correct networks interface in registry */ if (ERROR_SUCCESS != RegOpenKeyExA ( HKEY_LOCAL_MACHINE, adapter, 0, KEY_READ, &adapter_key_handle)) return FALSE; /* Of course there is a multitude of entries here, with arbitrary names, * thus we need to iterate through there. */ while (!retval) { char instance_key[256]; char query_key [256]; HKEY instance_key_handle; char pnpinstanceid_name[] = "PnpInstanceID"; char pnpinstanceid_value[256]; char adaptername_name[] = "Name"; DWORD data_type; len = 256 * sizeof (char); /* optain a subkey of {4D36E972-E325-11CE-BFC1-08002BE10318} */ status = RegEnumKeyExA ( adapter_key_handle, i, instance_key, &len, NULL, NULL, NULL, NULL); /* this may fail due to one of two reasons: * we are at the end of the list*/ if (ERROR_NO_MORE_ITEMS == status) break; // * we found a broken registry key, continue with the next key. if (ERROR_SUCCESS != status) goto cleanup; /* prepare our new query string: */ snprintf (query_key, 256, "%s\\%s\\Connection", adapter, instance_key); /* look inside instance_key\\Connection */ if (ERROR_SUCCESS != RegOpenKeyExA ( HKEY_LOCAL_MACHINE, query_key, 0, KEY_READ, &instance_key_handle)) goto cleanup; /* now, read our PnpInstanceID */ len = sizeof (pnpinstanceid_value); status = RegQueryValueExA (instance_key_handle, pnpinstanceid_name, NULL, //reserved, always NULL according to MSDN &data_type, (LPBYTE) pnpinstanceid_value, &len); if (status != ERROR_SUCCESS || data_type != REG_SZ) goto cleanup; /* compare the value we got to our devices PNPInstanceID*/ if (0 != strncmp (pnpinstanceid_value, pnp_instance_id, sizeof (pnpinstanceid_value) / sizeof (char))) goto cleanup; len = sizeof (device_visible_name); status = RegQueryValueExA ( instance_key_handle, adaptername_name, NULL, //reserved, always NULL according to MSDN &data_type, (LPBYTE) device_visible_name, &len); if (status != ERROR_SUCCESS || data_type != REG_SZ) goto cleanup; /* * we have successfully found OUR instance, * save the device GUID before exiting */ strncpy (device_guid, instance_key, 256); retval = TRUE; fprintf (stderr, "DEBUG: Interface Name lookup succeeded on retry %d, got \"%s\" %s\n", retrys, device_visible_name, device_guid); cleanup: RegCloseKey (instance_key_handle); ++i; } RegCloseKey (adapter_key_handle); } return retval; } /** * Determines the version of the installed TAP32 driver and checks if it's sufficiently new for GNUNET * * @param handle the handle to our tap device * @return TRUE if the version is sufficient, else FALSE */ static BOOL check_tapw32_version (HANDLE handle) { ULONG version[3]; DWORD len; memset (&(version), 0, sizeof (version)); if (DeviceIoControl (handle, TAP_WIN_IOCTL_GET_VERSION, &version, sizeof (version), &version, sizeof (version), &len, NULL)) fprintf (stderr, "INFO: TAP-Windows Driver Version %d.%d %s\n", (int) version[0], (int) version[1], (version[2] ? "(DEBUG)" : "")); if ((version[0] != TAP_WIN_MIN_MAJOR) || (version[1] < TAP_WIN_MIN_MINOR )){ fprintf (stderr, "FATAL: This version of gnunet requires a TAP-Windows driver that is at least version %d.%d\n", TAP_WIN_MIN_MAJOR, TAP_WIN_MIN_MINOR); return FALSE; } return TRUE; } /** * Creates a tun-interface called dev; * * @return the fd to the tun or -1 on error */ static HANDLE init_tun () { char device_path[256]; HANDLE handle; if (! setup_interface ()) { errno = ENODEV; return INVALID_HANDLE_VALUE; } if (! resolve_interface_name ()) { errno = ENODEV; return INVALID_HANDLE_VALUE; } /* Open Windows TAP-Windows adapter */ snprintf (device_path, sizeof (device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid, TAP_WIN_SUFFIX); handle = CreateFile ( device_path, GENERIC_READ | GENERIC_WRITE, 0, /* was: FILE_SHARE_READ */ 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0 ); if (INVALID_HANDLE_VALUE == handle) { fprintf (stderr, "FATAL: CreateFile failed on TAP device: %s\n", device_path); return handle; } /* get driver version info */ if (! check_tapw32_version (handle)) { CloseHandle (handle); return INVALID_HANDLE_VALUE; } /* TODO (opt?): get MTU-Size */ fprintf (stderr, "DEBUG: successfully opened TAP device\n"); return handle; } /** * Brings a TAP device up and sets it to connected state. * * @param handle the handle to our TAP device * @return True if the operation succeeded, else false */ static BOOL tun_up (HANDLE handle) { ULONG status = TRUE; DWORD len; if (! DeviceIoControl (handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, &status, sizeof (status), &status, sizeof (status), &len, NULL)) { fprintf (stderr, "FATAL: TAP driver ignored request to UP interface (DeviceIoControl call)\n"); return FALSE; } /* Wait for the device to go UP, might take some time. */ Sleep (TAP32_POSTUP_WAITTIME * 1000); fprintf (stderr, "DEBUG: successfully set TAP device to UP\n"); return TRUE; } /** * Attempts to read off an input facility (tap or named pipe) in overlapped mode. * * 1. * If the input facility is in IOSTATE_READY, it will issue a new read operation to the * input handle. Then it goes into IOSTATE_QUEUED state. * In case the read succeeded instantly the input facility enters 3. * * 2. * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already. * If it has finished, go to state 3. * If it has failed, set IOSTATE_FAILED * * 3. * If the output facility is in state IOSTATE_READY, the read-buffer is copied to the output buffer. * The input facility enters state IOSTATE_READY * The output facility enters state IOSTATE_READY * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING * * IOSTATE_WAITING is reset by the output facility, once it has completed. * * @param input_facility input named pipe or file to work with. * @param output_facility output pipe or file to hand over data to. * @return false if an event reset was impossible (OS error), else true */ static BOOL attempt_read_tap (struct io_facility * input_facility, struct io_facility * output_facility) { struct GNUNET_MessageHeader * hdr; unsigned short size; switch (input_facility->facility_state) { case IOSTATE_READY: { if (! ResetEvent (input_facility->overlapped.hEvent)) { return FALSE; } input_facility->buffer_size = 0; /* Check how the task is handled */ if (ReadFile (input_facility->handle, input_facility->buffer, sizeof (input_facility->buffer) - sizeof (struct GNUNET_MessageHeader), &input_facility->buffer_size, &input_facility->overlapped)) {/* async event processed immediately*/ /* reset event manually*/ if (! SetEvent (input_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: tap read succeeded immediately\n"); /* we successfully read something from the TAP and now need to * send it our via STDOUT. Is that possible at the moment? */ if ((IOSTATE_READY == output_facility->facility_state || IOSTATE_WAITING == output_facility->facility_state) && (0 < input_facility->buffer_size)) { /* hand over this buffers content and apply message header for gnunet */ hdr = (struct GNUNET_MessageHeader *) output_facility->buffer; size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader); memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer, input_facility->buffer_size); output_facility->buffer_size = size; hdr->size = htons (size); hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); output_facility->facility_state = IOSTATE_READY; } else if (0 < input_facility->buffer_size) /* If we have have read our buffer, wait for our write-partner*/ input_facility->facility_state = IOSTATE_WAITING; } else /* operation was either queued or failed*/ { int err = GetLastError (); if (ERROR_IO_PENDING == err) { /* operation queued */ input_facility->facility_state = IOSTATE_QUEUED; } else { /* error occurred, let the rest of the elements finish */ input_facility->path_open = FALSE; input_facility->facility_state = IOSTATE_FAILED; if (IOSTATE_WAITING == output_facility->facility_state) output_facility->path_open = FALSE; fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish\n"); } } } return TRUE; // We are queued and should check if the read has finished case IOSTATE_QUEUED: { // there was an operation going on already, check if that has completed now. if (GetOverlappedResult (input_facility->handle, &input_facility->overlapped, &input_facility->buffer_size, FALSE)) {/* successful return for a queued operation */ if (! ResetEvent (input_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: tap read succeeded delayed\n"); /* we successfully read something from the TAP and now need to * send it our via STDOUT. Is that possible at the moment? */ if ((IOSTATE_READY == output_facility->facility_state || IOSTATE_WAITING == output_facility->facility_state) && 0 < input_facility->buffer_size) { /* hand over this buffers content and apply message header for gnunet */ hdr = (struct GNUNET_MessageHeader *) output_facility->buffer; size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader); memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer, input_facility->buffer_size); output_facility->buffer_size = size; hdr->size = htons(size); hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; } else if (0 < input_facility->buffer_size) { /* If we have have read our buffer, wait for our write-partner*/ input_facility->facility_state = IOSTATE_WAITING; // TODO: shall we attempt to fill our buffer or should we wait for our write-partner to finish? } } else { /* operation still pending/queued or failed? */ int err = GetLastError (); if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err)) { /* error occurred, let the rest of the elements finish */ input_facility->path_open = FALSE; input_facility->facility_state = IOSTATE_FAILED; if (IOSTATE_WAITING == output_facility->facility_state) output_facility->path_open = FALSE; fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish\n"); } } } return TRUE; case IOSTATE_RESUME: hdr = (struct GNUNET_MessageHeader *) output_facility->buffer; size = input_facility->buffer_size + sizeof (struct GNUNET_MessageHeader); memcpy (output_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer, input_facility->buffer_size); output_facility->buffer_size = size; hdr->size = htons (size); hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; return TRUE; default: return TRUE; } } /** * Attempts to read off an input facility (tap or named pipe) in overlapped mode. * * 1. * If the input facility is in IOSTATE_READY, it will issue a new read operation to the * input handle. Then it goes into IOSTATE_QUEUED state. * In case the read succeeded instantly the input facility enters 3. * * 2. * If the input facility is in IOSTATE_QUEUED state, it will check if the queued read has finished already. * If it has finished, go to state 3. * If it has failed, set IOSTATE_FAILED * * 3. * If the facility is finished with ready * The read-buffer is copied to the output buffer, except for the GNUNET_MessageHeader. * The input facility enters state IOSTATE_READY * The output facility enters state IOSTATE_READY * If the output facility is in state IOSTATE_QUEUED, the input facility enters IOSTATE_WAITING * * IOSTATE_WAITING is reset by the output facility, once it has completed. * * @param input_facility input named pipe or file to work with. * @param output_facility output pipe or file to hand over data to. * @return false if an event reset was impossible (OS error), else true */ static BOOL attempt_read_stdin (struct io_facility * input_facility, struct io_facility * output_facility) { struct GNUNET_MessageHeader * hdr; switch (input_facility->facility_state) { case IOSTATE_READY: { input_facility->buffer_size = 0; partial_read_iostate_ready: if (! ResetEvent (input_facility->overlapped.hEvent)) return FALSE; /* Check how the task is handled */ if (ReadFile (input_facility->handle, input_facility->buffer + input_facility->buffer_size, sizeof (input_facility->buffer) - input_facility->buffer_size, &input_facility->buffer_size_processed, &input_facility->overlapped)) {/* async event processed immediately*/ hdr = (struct GNUNET_MessageHeader *) input_facility->buffer; /* reset event manually*/ if (!SetEvent (input_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: stdin read succeeded immediately\n"); input_facility->buffer_size += input_facility->buffer_size_processed; if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER || ntohs (hdr->size) > sizeof (input_facility->buffer)) { fprintf (stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs (hdr->type), ntohs (hdr->size)); input_facility->facility_state = IOSTATE_READY; return TRUE; } /* we got the a part of a packet */ if (ntohs (hdr->size) > input_facility->buffer_size) goto partial_read_iostate_ready; /* have we read more than 0 bytes of payload? (sizeread > header)*/ if (input_facility->buffer_size > sizeof (struct GNUNET_MessageHeader) && ((IOSTATE_READY == output_facility->facility_state) || (IOSTATE_WAITING == output_facility->facility_state))) {/* we successfully read something from the TAP and now need to * send it our via STDOUT. Is that possible at the moment? */ /* hand over this buffers content and strip gnunet message header */ memcpy (output_facility->buffer, input_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader)); output_facility->buffer_size = input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; } else if (input_facility->buffer_size > sizeof (struct GNUNET_MessageHeader)) /* If we have have read our buffer, wait for our write-partner*/ input_facility->facility_state = IOSTATE_WAITING; else /* we read nothing */ input_facility->facility_state = IOSTATE_READY; } else /* operation was either queued or failed*/ { int err = GetLastError (); if (ERROR_IO_PENDING == err) /* operation queued */ input_facility->facility_state = IOSTATE_QUEUED; else { /* error occurred, let the rest of the elements finish */ input_facility->path_open = FALSE; input_facility->facility_state = IOSTATE_FAILED; if (IOSTATE_WAITING == output_facility->facility_state) output_facility->path_open = FALSE; fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish\n"); } } } return TRUE; // We are queued and should check if the read has finished case IOSTATE_QUEUED: { // there was an operation going on already, check if that has completed now. if (GetOverlappedResult (input_facility->handle, &input_facility->overlapped, &input_facility->buffer_size_processed, FALSE)) {/* successful return for a queued operation */ hdr = (struct GNUNET_MessageHeader *) input_facility->buffer; if (! ResetEvent (input_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: stdin read succeeded delayed\n"); input_facility->buffer_size += input_facility->buffer_size_processed; if ((ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) || (ntohs (hdr->size) > sizeof (input_facility->buffer))) { fprintf (stderr, "WARNING: Protocol violation, got GNUnet Message type %h, size %h\n", ntohs (hdr->type), ntohs (hdr->size)); input_facility->facility_state = IOSTATE_READY; return TRUE; } /* we got the a part of a packet */ if (ntohs (hdr->size) > input_facility->buffer_size ); goto partial_read_iostate_ready; /* we successfully read something from the TAP and now need to * send it our via STDOUT. Is that possible at the moment? */ if ((IOSTATE_READY == output_facility->facility_state || IOSTATE_WAITING == output_facility->facility_state) && input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader)) { /* hand over this buffers content and strip gnunet message header */ memcpy (output_facility->buffer, input_facility->buffer + sizeof(struct GNUNET_MessageHeader), input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader)); output_facility->buffer_size = input_facility->buffer_size - sizeof(struct GNUNET_MessageHeader); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; } else if (input_facility->buffer_size > sizeof(struct GNUNET_MessageHeader)) input_facility->facility_state = IOSTATE_WAITING; else input_facility->facility_state = IOSTATE_READY; } else { /* operation still pending/queued or failed? */ int err = GetLastError (); if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err)) { /* error occurred, let the rest of the elements finish */ input_facility->path_open = FALSE; input_facility->facility_state = IOSTATE_FAILED; if (IOSTATE_WAITING == output_facility->facility_state) output_facility->path_open = FALSE; fprintf (stderr, "FATAL: Read from handle failed, allowing write to finish\n"); } } } return TRUE; case IOSTATE_RESUME: /* Our buffer was filled already but our write facility was busy. */ memcpy (output_facility->buffer, input_facility->buffer + sizeof (struct GNUNET_MessageHeader), input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader)); output_facility->buffer_size = input_facility->buffer_size - sizeof (struct GNUNET_MessageHeader); output_facility->facility_state = IOSTATE_READY; input_facility->facility_state = IOSTATE_READY; return TRUE; default: return TRUE; } } /** * Attempts to write to an output facility (tap or named pipe) in overlapped mode. * * TODO: high level description * * @param output_facility output pipe or file to hand over data to. * @param input_facility input named pipe or file to work with. * @return false if an event reset was impossible (OS error), else true */ static BOOL attempt_write (struct io_facility * output_facility, struct io_facility * input_facility) { switch (output_facility->facility_state) { case IOSTATE_READY: output_facility->buffer_size_written = 0; continue_partial_write: if (! ResetEvent (output_facility->overlapped.hEvent)) return FALSE; /* Check how the task was handled */ if (WriteFile (output_facility->handle, output_facility->buffer + output_facility->buffer_size_written, output_facility->buffer_size - output_facility->buffer_size_written, &output_facility->buffer_size_processed, &output_facility->overlapped)) {/* async event processed immediately*/ fprintf (stderr, "DEBUG: write succeeded immediately\n"); output_facility->buffer_size_written += output_facility->buffer_size_processed; /* reset event manually*/ if (! SetEvent (output_facility->overlapped.hEvent)) return FALSE; /* partial write */ if (output_facility->buffer_size_written < output_facility->buffer_size) goto continue_partial_write; /* we are now waiting for our buffer to be filled*/ output_facility->facility_state = IOSTATE_WAITING; /* we successfully wrote something and now need to reset our reader */ if (IOSTATE_WAITING == input_facility->facility_state) input_facility->facility_state = IOSTATE_RESUME; else if (IOSTATE_FAILED == input_facility->facility_state) output_facility->path_open = FALSE; } else /* operation was either queued or failed*/ { int err = GetLastError (); if (ERROR_IO_PENDING == err) { /* operation queued */ output_facility->facility_state = IOSTATE_QUEUED; } else { /* error occurred, close this path */ output_facility->path_open = FALSE; output_facility->facility_state = IOSTATE_FAILED; fprintf (stderr, "FATAL: Write to handle failed, exiting\n"); } } return TRUE; case IOSTATE_QUEUED: // there was an operation going on already, check if that has completed now. if (GetOverlappedResult (output_facility->handle, &output_facility->overlapped, &output_facility->buffer_size_processed, FALSE)) {/* successful return for a queued operation */ if (! ResetEvent (output_facility->overlapped.hEvent)) return FALSE; fprintf (stderr, "DEBUG: write succeeded delayed\n"); output_facility->buffer_size_written += output_facility->buffer_size_processed; /* partial write */ if (output_facility->buffer_size_written < output_facility->buffer_size) goto continue_partial_write; /* we are now waiting for our buffer to be filled*/ output_facility->facility_state = IOSTATE_WAITING; /* we successfully wrote something and now need to reset our reader */ if (IOSTATE_WAITING == input_facility->facility_state) input_facility->facility_state = IOSTATE_RESUME; else if (IOSTATE_FAILED == input_facility->facility_state) output_facility->path_open = FALSE; } else { /* operation still pending/queued or failed? */ int err = GetLastError (); if ((ERROR_IO_INCOMPLETE != err) && (ERROR_IO_PENDING != err)) { /* error occurred, close this path */ output_facility->path_open = FALSE; output_facility->facility_state = IOSTATE_FAILED; fprintf (stderr, "FATAL: Write to handle failed, exiting\n"); } } default: return TRUE; } } /** * Initialize a overlapped structure * * @param elem the element to initilize * @param initial_state the initial state for this instance * @param signaled if the hEvent created should default to signaled or not * @return true on success, else false */ static BOOL initialize_io_facility (struct io_facility * elem, int initial_state, BOOL signaled) { elem->path_open = TRUE; elem->handle = INVALID_HANDLE_VALUE; elem->facility_state = initial_state; elem->buffer_size = 0; elem->overlapped.hEvent = CreateEvent (NULL, TRUE, signaled, NULL); if (NULL == elem->overlapped.hEvent) return FALSE; return TRUE; } /** * Start forwarding to and from the tunnel. * * @param tap_handle device handle for interacting with the Virtual interface */ static void run (HANDLE tap_handle) { /* IO-Facility for reading from our virtual interface */ struct io_facility tap_read; /* IO-Facility for writing to our virtual interface */ struct io_facility tap_write; /* IO-Facility for reading from stdin */ struct io_facility std_in; /* IO-Facility for writing to stdout */ struct io_facility std_out; HANDLE parent_std_in_handle = GetStdHandle (STD_INPUT_HANDLE); HANDLE parent_std_out_handle = GetStdHandle (STD_OUTPUT_HANDLE); /* tun up: */ /* we do this HERE and not beforehand (in init_tun()), in contrast to openvpn * to remove the need to flush the arp cache, handle DHCP and wrong IPs. * * DHCP and such are all features we will never use in gnunet afaik. * But for openvpn those are essential. */ if ((privilege_testing) || (! tun_up (tap_handle) )) goto teardown_final; /* Initialize our overlapped IO structures*/ if (! (initialize_io_facility (&tap_read, IOSTATE_READY, FALSE) && initialize_io_facility (&tap_write, IOSTATE_WAITING, TRUE) && initialize_io_facility (&std_in, IOSTATE_READY, FALSE) && initialize_io_facility (&std_out, IOSTATE_WAITING, TRUE))) goto teardown_final; /* Handles for STDIN and STDOUT */ tap_read.handle = tap_handle; tap_write.handle = tap_handle; #ifdef DEBUG_TO_CONSOLE /* Debug output to console STDIN/STDOUT*/ std_in.handle = parent_std_in_handle; std_out.handle = parent_std_out_handle; #else fprintf (stderr, "DEBUG: reopening stdin/out for overlapped IO\n"); /* * Find out the types of our handles. * This part is a problem, because in windows we need to handle files, * pipes and the console differently. */ if ((FILE_TYPE_PIPE != GetFileType (parent_std_in_handle)) || (FILE_TYPE_PIPE != GetFileType (parent_std_out_handle))) { fprintf (stderr, "ERROR: stdin/stdout must be named pipes\n"); goto teardown; } std_in.handle = ReOpenFile (parent_std_in_handle, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, FILE_FLAG_OVERLAPPED); if (INVALID_HANDLE_VALUE == std_in.handle) { fprintf (stderr, "FATAL: Could not reopen stdin for in overlapped mode, has to be a named pipe\n"); goto teardown; } std_out.handle = ReOpenFile (parent_std_out_handle, GENERIC_WRITE, FILE_SHARE_READ, FILE_FLAG_OVERLAPPED); if (INVALID_HANDLE_VALUE == std_out.handle) { fprintf (stderr, "FATAL: Could not reopen stdout for in overlapped mode, has to be a named pipe\n"); goto teardown; } #endif fprintf (stderr, "DEBUG: mainloop has begun\n"); while (std_out.path_open || tap_write.path_open) { /* perform READ from stdin if possible */ if (std_in.path_open && (! attempt_read_stdin (&std_in, &tap_write))) break; /* perform READ from tap if possible */ if (tap_read.path_open && (! attempt_read_tap (&tap_read, &std_out))) break; /* perform WRITE to tap if possible */ if (tap_write.path_open && (! attempt_write (&tap_write, &std_in))) break; /* perform WRITE to STDOUT if possible */ if (std_out.path_open && (! attempt_write (&std_out, &tap_read))) break; } fprintf (stderr, "DEBUG: teardown initiated\n"); teardown: CancelIo (tap_handle); CancelIo (std_in.handle); CancelIo (std_out.handle); teardown_final: CloseHandle (tap_handle); } /** * Open VPN tunnel interface. * * @param argc must be 6 * @param argv 0: binary name ("gnunet-helper-exit") * 1: tunnel interface name ("gnunet-exit") * 2: IPv4 "physical" interface name ("eth0"), or "-" to not do IPv4 NAT * 3: IPv6 address ("::1"), or "-" to skip IPv6 * 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"] * 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4 * 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"] */ int main (int argc, char **argv) { char hwid[LINE_LEN]; HANDLE handle; int global_ret = 1; int local_ret = EINVAL; BOOL have_ip4 = FALSE; BOOL have_ip6 = FALSE; BOOL have_nat44 = FALSE; if ( (1 < argc) && (0 != strcmp (argv[1], "-d"))){ privilege_testing = TRUE; fprintf (stderr, "%s", "DEBUG: Running binary in privilege testing mode."); argv++; argc--; } if (6 != argc) { fprintf (stderr, "%s", "FATAL: must supply 6 arguments\nUsage:\ngnunet-helper-exit [-d] \n"); return 1; } strncpy (hwid, argv[1], LINE_LEN); hwid[LINE_LEN - 1] = '\0'; /* * We use our PID for finding/resolving the control-panel name of our virtual * device. PIDs are (of course) unique at runtime, thus we can safely use it * as additional hardware-id for our device. */ snprintf (secondary_hwid, LINE_LEN / 2, "%s-%d", hwid, _getpid ()); if (INVALID_HANDLE_VALUE == (handle = init_tun ())) { fprintf (stderr, "FATAL: could not initialize virtual-interface %s with IPv6 %s/%s and IPv4 %s/%s\n", hwid, argv[3], argv[4], argv[5], argv[6]); global_ret = -1; goto cleanup; } fprintf (stderr, "DEBUG: Setting IPs, if needed\n"); if (0 != strcmp (argv[3], "-")) { char command[LINE_LEN]; const char *address = argv[3]; long prefix_len = atol (argv[4]); if ((prefix_len < 1) || (prefix_len > 127)) { fprintf (stderr, "FATAL: ipv6 prefix_len out of range\n"); global_ret = -1; goto cleanup; } fprintf (stderr, "DEBUG: Setting IP6 address: %s/%d\n", address, prefix_len); if (0 != (global_ret = set_address6 (address, prefix_len))) goto cleanup; have_ip6 = TRUE; /* install our the windows NAT module*/ fprintf (stderr, "DEBUG: Setting IPv6 Forwarding for internal and external interface.\n"); /* outside interface (maybe that's already set) */ snprintf (command, LINE_LEN, "netsh interface ipv6 set interface interface=\"%s\" metric=1 forwarding=enabled store=active", argv[2]); local_ret = execute_shellcommand (command); if (0 != local_ret) { fprintf (stderr, "FATAL: Could not enable forwarding via netsh: %s\n", strerror (local_ret)); goto cleanup; } /* internal interface */ snprintf (command, LINE_LEN, "netsh interface ipv6 set interface interface=\"%s\" metric=1 forwarding=enabled advertise=enabled store=active", device_visible_name); local_ret = execute_shellcommand (command); if (0 != local_ret) { fprintf (stderr, "FATAL: Could not enable forwarding via netsh: %s\n", strerror (local_ret)); goto cleanup; } /* we can keep IPv6 forwarding around, as all interfaces have * their forwarding mode reset to false at bootup. */ } if (0 != strcmp (argv[5], "-")) { const char *address = argv[5]; const char *mask = argv[6]; fprintf (stderr, "DEBUG: Setting IP4 address: %s/%s\n", address, mask); if (0 != (global_ret = set_address4 (address, mask))) goto cleanup; // setup NAPT, if possible /* MS has REMOVED the routing/nat capabilities from Vista+, thus * we can not setup NAT like in XP or on the server. Actually the * the only feasible solution seems to be to use * Internet Connection Sharing, which introduces a horde of problems * such as sending out rogue-RAs on the external interface in an ipv6 * network. * Thus, below stuff ONLY works on * WinXP SP3 * Win Server 2003 SP1+ * Win Server 2008 * ... */ have_ip4 = TRUE; if (0 != strcmp (argv[2], "-")) { char command[LINE_LEN]; /* install our the windows NAT module*/ fprintf (stderr, "DEBUG: Adding NAPT/Masquerading between external IF %s and mine.\n", argv[2]); local_ret = execute_shellcommand ("netsh routing ip nat install"); if (0 != local_ret) { fprintf (stderr, "FATAL: Could not install NAPT support via Netsh: %s\n", strerror (local_ret)); goto cleanup; } /* external IF */ snprintf (command, LINE_LEN, "netsh routing ip nat add interface \"%s\" full", /*full = NAPT (addr+port)*/ argv[2]); local_ret = execute_shellcommand (command); if (0 != local_ret) { fprintf (stderr, "FATAL: IPv4-NAPT on external interface failed: %s\n", strerror (local_ret)); goto cleanup; } /* private/internal/virtual IF */ snprintf (command, LINE_LEN, "netsh routing ip nat add interface \"%s\" private", device_visible_name); local_ret = execute_shellcommand (command); if (0 != local_ret) { fprintf (stderr, "FATAL: IPv4-NAPT on internal interface failed: %s\n", strerror (local_ret)); goto cleanup; have_nat44 = TRUE; } } } run (handle); cleanup: if (have_ip4) { const char *address = argv[5]; if (have_nat44) { char command[LINE_LEN]; fprintf(stderr, "DEBUG: removing IP4 NAPT from virtual interface \n"); snprintf(command, LINE_LEN, "netsh routing ip nat del interface \"%s\"", device_visible_name); local_ret = execute_shellcommand(command); if (0 != local_ret) fprintf(stderr, "WARNING: Could not remove IPv4-NAPT from internal interface, hopefully this will have no effect in future runs: %s\n", strerror(local_ret)); } fprintf(stderr, "DEBUG: Removing IP4 address\n"); remove_address4 (address); } if (have_ip6) { const char *address = argv[3]; fprintf (stderr, "DEBUG: Removing IP6 address\n"); remove_address6 (address); } fprintf (stderr, "DEBUG: removing interface\n"); remove_interface (); fprintf (stderr, "DEBUG: graceful exit completed\n"); return global_ret; } gnunet-0.10.1/src/exit/gnunet-daemon-exit.c0000644000175000017500000032645712255411517015452 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file exit/gnunet-daemon-exit.c * @brief tool to allow IP traffic exit from the GNUnet mesh to the Internet * @author Philipp Toelke * @author Christian Grothoff * * TODO: * - test * * Design: * - which code should advertise services? the service model is right * now a bit odd, especially as this code DOES the exit and knows * the DNS "name", but OTOH this is clearly NOT the place to advertise * the service's existence; maybe the daemon should turn into a * service with an API to add local-exit services dynamically? */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet_dht_service.h" #include "gnunet_mesh_service.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_dnsstub_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_tun_lib.h" #include "gnunet_regex_service.h" #include "exit.h" #include "block_dns.h" /** * Maximum path compression length for mesh regex announcing for IPv4 address * based regex. */ #define REGEX_MAX_PATH_LEN_IPV4 4 /** * Maximum path compression length for mesh regex announcing for IPv6 address * based regex. */ #define REGEX_MAX_PATH_LEN_IPV6 8 /** * How frequently do we re-announce the regex for the exit? */ #define REGEX_REFRESH_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30) /** * How frequently do we re-announce the DNS exit in the DHT? */ #define DHT_PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) /** * How long do we typically sign the DNS exit advertisement for? */ #define DNS_ADVERTISEMENT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 3) /** * Generic logging shorthand */ #define LOG(kind, ...) \ GNUNET_log_from (kind, "exit", __VA_ARGS__); /** * Information about an address. */ struct SocketAddress { /** * AF_INET or AF_INET6. */ int af; /** * Remote address information. */ union { /** * Address, if af is AF_INET. */ struct in_addr ipv4; /** * Address, if af is AF_INET6. */ struct in6_addr ipv6; } address; /** * IPPROTO_TCP or IPPROTO_UDP; */ uint8_t proto; /** * Remote port, in host byte order! */ uint16_t port; }; /** * This struct is saved into the services-hashmap to represent * a service this peer is specifically offering an exit for * (for a specific domain name). */ struct LocalService { /** * Remote address to use for the service. */ struct SocketAddress address; /** * DNS name of the service. */ char *name; /** * Port I am listening on within GNUnet for this service, in host * byte order. (as we may redirect ports). */ uint16_t my_port; }; /** * Information we use to track a connection (the classical 6-tuple of * IP-version, protocol, source-IP, destination-IP, source-port and * destinatin-port. */ struct RedirectInformation { /** * Address information for the other party (equivalent of the * arguments one would give to "connect"). */ struct SocketAddress remote_address; /** * Address information we used locally (AF and proto must match * "remote_address"). Equivalent of the arguments one would give to * "bind". */ struct SocketAddress local_address; /* Note 1: additional information might be added here in the future to support protocols that require special handling, such as ftp/tftp Note 2: we might also sometimes not match on all components of the tuple, to support protocols where things do not always fully map. */ }; /** * Queue of messages to a channel. */ struct ChannelMessageQueue { /** * This is a doubly-linked list. */ struct ChannelMessageQueue *next; /** * This is a doubly-linked list. */ struct ChannelMessageQueue *prev; /** * Payload to send via the channel. */ const void *payload; /** * Number of bytes in 'payload'. */ size_t len; }; /** * This struct is saved into connections_map to allow finding the * right channel given an IP packet from TUN. It is also associated * with the channel's closure so we can find it again for the next * message from the channel. */ struct ChannelState { /** * Mesh channel that is used for this connection. */ struct GNUNET_MESH_Channel *channel; /** * Who is the other end of this channel. * FIXME is this needed? Only used for debugging messages */ struct GNUNET_PeerIdentity peer; /** * Active channel transmission request (or NULL). */ struct GNUNET_MESH_TransmitHandle *th; /** * #GNUNET_NO if this is a channel for TCP/UDP, * #GNUNET_YES if this is a channel for DNS, * #GNUNET_SYSERR if the channel is not yet initialized. */ int is_dns; union { struct { /** * Heap node for this state in the connections_heap. */ struct GNUNET_CONTAINER_HeapNode *heap_node; /** * Key this state has in the connections_map. */ struct GNUNET_HashCode state_key; /** * Associated service record, or NULL for no service. */ struct LocalService *serv; /** * Head of DLL of messages for this channel. */ struct ChannelMessageQueue *head; /** * Tail of DLL of messages for this channel. */ struct ChannelMessageQueue *tail; /** * Primary redirection information for this connection. */ struct RedirectInformation ri; } tcp_udp; struct { /** * DNS reply ready for transmission. */ char *reply; /** * Socket we are using to transmit this request (must match if we receive * a response). */ struct GNUNET_DNSSTUB_RequestSocket *rs; /** * Number of bytes in 'reply'. */ size_t reply_length; /** * Original DNS request ID as used by the client. */ uint16_t original_id; /** * DNS request ID that we used for forwarding. */ uint16_t my_id; } dns; } specifics; }; /** * Return value from 'main'. */ static int global_ret; /** * Handle to our regex announcement for IPv4. */ static struct GNUNET_REGEX_Announcement *regex4; /** * Handle to our regex announcement for IPv4. */ static struct GNUNET_REGEX_Announcement *regex6; /** * The handle to the configuration used throughout the process */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * The handle to the helper */ static struct GNUNET_HELPER_Handle *helper_handle; /** * Arguments to the exit helper. */ static char *exit_argv[8]; /** * IPv6 address of our TUN interface. */ static struct in6_addr exit_ipv6addr; /** * IPv6 prefix (0..127) from configuration file. */ static unsigned long long ipv6prefix; /** * IPv4 address of our TUN interface. */ static struct in_addr exit_ipv4addr; /** * IPv4 netmask of our TUN interface. */ static struct in_addr exit_ipv4mask; /** * Statistics. */ static struct GNUNET_STATISTICS_Handle *stats; /** * The handle to mesh */ static struct GNUNET_MESH_Handle *mesh_handle; /** * This hashmaps contains the mapping from peer, service-descriptor, * source-port and destination-port to a struct ChannelState */ static struct GNUNET_CONTAINER_MultiHashMap *connections_map; /** * Heap so we can quickly find "old" connections. */ static struct GNUNET_CONTAINER_Heap *connections_heap; /** * If there are at least this many connections, old ones will be removed */ static unsigned long long max_connections; /** * This hashmaps saves interesting things about the configured UDP services */ static struct GNUNET_CONTAINER_MultiHashMap *udp_services; /** * This hashmaps saves interesting things about the configured TCP services */ static struct GNUNET_CONTAINER_MultiHashMap *tcp_services; /** * Array of all open DNS requests from channels. */ static struct ChannelState *channels[UINT16_MAX + 1]; /** * Handle to the DNS Stub resolver. */ static struct GNUNET_DNSSTUB_Context *dnsstub; /** * Handle for ongoing DHT PUT operations to advertise exit service. */ static struct GNUNET_DHT_PutHandle *dht_put; /** * Handle to the DHT. */ static struct GNUNET_DHT_Handle *dht; /** * Task for doing DHT PUTs to advertise exit service. */ static GNUNET_SCHEDULER_TaskIdentifier dht_task; /** * Advertisement message we put into the DHT to advertise us * as a DNS exit. */ static struct GNUNET_DNS_Advertisement dns_advertisement; /** * Key we store the DNS advertismenet under. */ static struct GNUNET_HashCode dht_put_key; /** * Private key for this peer. */ static struct GNUNET_CRYPTO_EddsaPrivateKey *peer_key; /** * Are we an IPv4-exit? */ static int ipv4_exit; /** * Are we an IPv6-exit? */ static int ipv6_exit; /** * Do we support IPv4 at all on the TUN interface? */ static int ipv4_enabled; /** * Do we support IPv6 at all on the TUN interface? */ static int ipv6_enabled; /** * We got a reply from DNS for a request of a MESH channel. Send it * via the channel (after changing the request ID back). * * @param cls the 'struct ChannelState' * @param size number of bytes available in buf * @param buf where to copy the reply * @return number of bytes written to buf */ static size_t transmit_reply_to_mesh (void *cls, size_t size, void *buf) { struct ChannelState *ts = cls; size_t off; size_t ret; char *cbuf = buf; struct GNUNET_MessageHeader hdr; struct GNUNET_TUN_DnsHeader dns; GNUNET_assert (GNUNET_YES == ts->is_dns); ts->th = NULL; GNUNET_assert (ts->specifics.dns.reply != NULL); if (size == 0) return 0; ret = sizeof (struct GNUNET_MessageHeader) + ts->specifics.dns.reply_length; GNUNET_assert (ret <= size); hdr.size = htons (ret); hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET); memcpy (&dns, ts->specifics.dns.reply, sizeof (dns)); dns.id = ts->specifics.dns.original_id; off = 0; memcpy (&cbuf[off], &hdr, sizeof (hdr)); off += sizeof (hdr); memcpy (&cbuf[off], &dns, sizeof (dns)); off += sizeof (dns); memcpy (&cbuf[off], &ts->specifics.dns.reply[sizeof (dns)], ts->specifics.dns.reply_length - sizeof (dns)); off += ts->specifics.dns.reply_length - sizeof (dns); GNUNET_free (ts->specifics.dns.reply); ts->specifics.dns.reply = NULL; ts->specifics.dns.reply_length = 0; GNUNET_assert (ret == off); return ret; } /** * Callback called from DNSSTUB resolver when a resolution * succeeded. * * @param cls NULL * @param rs the socket that received the response * @param dns the response itself * @param r number of bytes in dns */ static void process_dns_result (void *cls, struct GNUNET_DNSSTUB_RequestSocket *rs, const struct GNUNET_TUN_DnsHeader *dns, size_t r) { struct ChannelState *ts; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing DNS result from stub resolver\n"); GNUNET_assert (NULL == cls); /* Handle case that this is a reply to a request from a MESH DNS channel */ ts = channels[dns->id]; if ( (NULL == ts) || (ts->specifics.dns.rs != rs) ) return; LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a response from the stub resolver for DNS request received via MESH!\n"); channels[dns->id] = NULL; GNUNET_free_non_null (ts->specifics.dns.reply); ts->specifics.dns.reply = GNUNET_malloc (r); ts->specifics.dns.reply_length = r; memcpy (ts->specifics.dns.reply, dns, r); if (NULL != ts->th) GNUNET_MESH_notify_transmit_ready_cancel (ts->th); ts->th = GNUNET_MESH_notify_transmit_ready (ts->channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct GNUNET_MessageHeader) + r, &transmit_reply_to_mesh, ts); } /** * Process a request via mesh to perform a DNS query. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our `struct ChannelState *` * @param message the actual message * * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_dns_request (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *ts = *channel_ctx; const struct GNUNET_TUN_DnsHeader *dns; size_t mlen = ntohs (message->size); size_t dlen = mlen - sizeof (struct GNUNET_MessageHeader); char buf[dlen] GNUNET_ALIGN; struct GNUNET_TUN_DnsHeader *dout; if (NULL == dnsstub) return GNUNET_SYSERR; if (GNUNET_NO == ts->is_dns) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_SYSERR == ts->is_dns) { /* channel is DNS from now on */ ts->is_dns = GNUNET_YES; } if (dlen < sizeof (struct GNUNET_TUN_DnsHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } dns = (const struct GNUNET_TUN_DnsHeader *) &message[1]; ts->specifics.dns.original_id = dns->id; if (channels[ts->specifics.dns.my_id] == ts) channels[ts->specifics.dns.my_id] = NULL; ts->specifics.dns.my_id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT16_MAX + 1); channels[ts->specifics.dns.my_id] = ts; memcpy (buf, dns, dlen); dout = (struct GNUNET_TUN_DnsHeader *) buf; dout->id = ts->specifics.dns.my_id; ts->specifics.dns.rs = GNUNET_DNSSTUB_resolve2 (dnsstub, buf, dlen, &process_dns_result, NULL); if (NULL == ts->specifics.dns.rs) return GNUNET_SYSERR; return GNUNET_OK; } /** * Given IP information about a connection, calculate the respective * hash we would use for the 'connections_map'. * * @param hash resulting hash * @param ri information about the connection */ static void hash_redirect_info (struct GNUNET_HashCode *hash, const struct RedirectInformation *ri) { char *off; memset (hash, 0, sizeof (struct GNUNET_HashCode)); /* the GNUnet hashmap only uses the first sizeof(unsigned int) of the hash, so we put the IP address in there (and hope for few collisions) */ off = (char*) hash; switch (ri->remote_address.af) { case AF_INET: memcpy (off, &ri->remote_address.address.ipv4, sizeof (struct in_addr)); off += sizeof (struct in_addr); break; case AF_INET6: memcpy (off, &ri->remote_address.address.ipv6, sizeof (struct in6_addr)); off += sizeof (struct in_addr); break; default: GNUNET_assert (0); } memcpy (off, &ri->remote_address.port, sizeof (uint16_t)); off += sizeof (uint16_t); switch (ri->local_address.af) { case AF_INET: memcpy (off, &ri->local_address.address.ipv4, sizeof (struct in_addr)); off += sizeof (struct in_addr); break; case AF_INET6: memcpy (off, &ri->local_address.address.ipv6, sizeof (struct in6_addr)); off += sizeof (struct in_addr); break; default: GNUNET_assert (0); } memcpy (off, &ri->local_address.port, sizeof (uint16_t)); off += sizeof (uint16_t); memcpy (off, &ri->remote_address.proto, sizeof (uint8_t)); /* off += sizeof (uint8_t); */ } /** * Get our connection tracking state. Warns if it does not exists, * refreshes the timestamp if it does exist. * * @param af address family * @param protocol IPPROTO_UDP or IPPROTO_TCP * @param destination_ip target IP * @param destination_port target port * @param local_ip local IP * @param local_port local port * @param state_key set to hash's state if non-NULL * @return NULL if we have no tracking information for this tuple */ static struct ChannelState * get_redirect_state (int af, int protocol, const void *destination_ip, uint16_t destination_port, const void *local_ip, uint16_t local_port, struct GNUNET_HashCode *state_key) { struct RedirectInformation ri; struct GNUNET_HashCode key; struct ChannelState *state; if ( ( (af == AF_INET) && (protocol == IPPROTO_ICMP) ) || ( (af == AF_INET6) && (protocol == IPPROTO_ICMPV6) ) ) { /* ignore ports */ destination_port = 0; local_port = 0; } ri.remote_address.af = af; if (af == AF_INET) ri.remote_address.address.ipv4 = *((struct in_addr*) destination_ip); else ri.remote_address.address.ipv6 = * ((struct in6_addr*) destination_ip); ri.remote_address.port = destination_port; ri.remote_address.proto = protocol; ri.local_address.af = af; if (af == AF_INET) ri.local_address.address.ipv4 = *((struct in_addr*) local_ip); else ri.local_address.address.ipv6 = * ((struct in6_addr*) local_ip); ri.local_address.port = local_port; ri.local_address.proto = protocol; hash_redirect_info (&key, &ri); if (NULL != state_key) *state_key = key; state = GNUNET_CONTAINER_multihashmap_get (connections_map, &key); if (NULL == state) return NULL; /* Mark this connection as freshly used */ if (NULL == state_key) GNUNET_CONTAINER_heap_update_cost (connections_heap, state->specifics.tcp_udp.heap_node, GNUNET_TIME_absolute_get ().abs_value_us); return state; } /** * Given a service descriptor and a destination port, find the * respective service entry. * * @param service_map map of services (TCP or UDP) * @param desc service descriptor * @param destination_port destination port * @return NULL if we are not aware of such a service */ static struct LocalService * find_service (struct GNUNET_CONTAINER_MultiHashMap *service_map, const struct GNUNET_HashCode *desc, uint16_t destination_port) { char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)]; memcpy (&key[0], &destination_port, sizeof (uint16_t)); memcpy (&key[sizeof(uint16_t)], desc, sizeof (struct GNUNET_HashCode)); return GNUNET_CONTAINER_multihashmap_get (service_map, (struct GNUNET_HashCode *) key); } /** * Free memory associated with a service record. * * @param cls unused * @param key service descriptor * @param value service record to free * @return GNUNET_OK */ static int free_service_record (void *cls, const struct GNUNET_HashCode *key, void *value) { struct LocalService *service = value; GNUNET_free_non_null (service->name); GNUNET_free (service); return GNUNET_OK; } /** * Given a service descriptor and a destination port, find the * respective service entry. * * @param service_map map of services (TCP or UDP) * @param name name of the service * @param destination_port destination port * @param service service information record to store (service->name will be set). */ static void store_service (struct GNUNET_CONTAINER_MultiHashMap *service_map, const char *name, uint16_t destination_port, struct LocalService *service) { char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)]; struct GNUNET_HashCode desc; GNUNET_TUN_service_name_to_hash (name, &desc); service->name = GNUNET_strdup (name); memcpy (&key[0], &destination_port, sizeof (uint16_t)); memcpy (&key[sizeof(uint16_t)], &desc, sizeof (struct GNUNET_HashCode)); if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (service_map, (struct GNUNET_HashCode *) key, service, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { free_service_record (NULL, (struct GNUNET_HashCode *) key, service); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Got duplicate service records for `%s:%u'\n"), name, (unsigned int) destination_port); } } /** * MESH is ready to receive a message for the channel. Transmit it. * * @param cls the 'struct ChannelState'. * @param size number of bytes available in buf * @param buf where to copy the message * @return number of bytes copied to buf */ static size_t send_to_peer_notify_callback (void *cls, size_t size, void *buf) { struct ChannelState *s = cls; struct GNUNET_MESH_Channel *channel = s->channel; struct ChannelMessageQueue *tnq; s->th = NULL; tnq = s->specifics.tcp_udp.head; if (NULL == tnq) return 0; if (0 == size) { s->th = GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO /* corking */, GNUNET_TIME_UNIT_FOREVER_REL, tnq->len, &send_to_peer_notify_callback, s); return 0; } GNUNET_assert (size >= tnq->len); memcpy (buf, tnq->payload, tnq->len); size = tnq->len; GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head, s->specifics.tcp_udp.tail, tnq); GNUNET_free (tnq); if (NULL != (tnq = s->specifics.tcp_udp.head)) s->th = GNUNET_MESH_notify_transmit_ready (channel, GNUNET_NO /* corking */, GNUNET_TIME_UNIT_FOREVER_REL, tnq->len, &send_to_peer_notify_callback, s); GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes transmitted via mesh channels"), size, GNUNET_NO); return size; } /** * Send the given packet via the mesh channel. * * @param s channel destination * @param tnq message to queue */ static void send_packet_to_mesh_channel (struct ChannelState *s, struct ChannelMessageQueue *tnq) { struct GNUNET_MESH_Channel *mesh_channel; mesh_channel = s->channel; GNUNET_assert (NULL != s); GNUNET_CONTAINER_DLL_insert_tail (s->specifics.tcp_udp.head, s->specifics.tcp_udp.tail, tnq); if (NULL == s->th) s->th = GNUNET_MESH_notify_transmit_ready (mesh_channel, GNUNET_NO /* cork */, GNUNET_TIME_UNIT_FOREVER_REL, tnq->len, &send_to_peer_notify_callback, s); } /** * @brief Handles an ICMP packet received from the helper. * * @param icmp A pointer to the Packet * @param pktlen number of bytes in 'icmp' * @param af address family (AFINET or AF_INET6) * @param destination_ip destination IP-address of the IP packet (should * be our local address) * @param source_ip original source IP-address of the IP packet (should * be the original destination address) */ static void icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp, size_t pktlen, int af, const void *destination_ip, const void *source_ip) { struct ChannelState *state; struct ChannelMessageQueue *tnq; struct GNUNET_EXIT_IcmpToVPNMessage *i2v; const struct GNUNET_TUN_IPv4Header *ipv4; const struct GNUNET_TUN_IPv6Header *ipv6; const struct GNUNET_TUN_UdpHeader *udp; size_t mlen; uint16_t source_port; uint16_t destination_port; uint8_t protocol; { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ICMP packet going from %s to %s\n", inet_ntop (af, source_ip, sbuf, sizeof (sbuf)), inet_ntop (af, destination_ip, dbuf, sizeof (dbuf))); } if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader)) { /* blame kernel */ GNUNET_break (0); return; } /* Find out if this is an ICMP packet in response to an existing TCP/UDP packet and if so, figure out ports / protocol of the existing session from the IP data in the ICMP payload */ source_port = 0; destination_port = 0; switch (af) { case AF_INET: protocol = IPPROTO_ICMP; switch (icmp->type) { case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: break; case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader) + sizeof (struct GNUNET_TUN_IPv4Header) + 8) { /* blame kernel */ GNUNET_break (0); return; } ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1]; protocol = ipv4->protocol; /* could be TCP or UDP, but both have the ports in the right place, so that doesn't matter here */ udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1]; /* swap ports, as they are from the original message */ destination_port = ntohs (udp->source_port); source_port = ntohs (udp->destination_port); /* throw away ICMP payload, won't be useful for the other side anyway */ pktlen = sizeof (struct GNUNET_TUN_IcmpHeader); break; default: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 1, GNUNET_NO); return; } break; case AF_INET6: protocol = IPPROTO_ICMPV6; switch (icmp->type) { case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader) + sizeof (struct GNUNET_TUN_IPv6Header) + 8) { /* blame kernel */ GNUNET_break (0); return; } ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1]; protocol = ipv6->next_header; /* could be TCP or UDP, but both have the ports in the right place, so that doesn't matter here */ udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1]; /* swap ports, as they are from the original message */ destination_port = ntohs (udp->source_port); source_port = ntohs (udp->destination_port); /* throw away ICMP payload, won't be useful for the other side anyway */ pktlen = sizeof (struct GNUNET_TUN_IcmpHeader); break; case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY: break; default: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 1, GNUNET_NO); return; } break; default: GNUNET_assert (0); } switch (protocol) { case IPPROTO_ICMP: state = get_redirect_state (af, IPPROTO_ICMP, source_ip, 0, destination_ip, 0, NULL); break; case IPPROTO_ICMPV6: state = get_redirect_state (af, IPPROTO_ICMPV6, source_ip, 0, destination_ip, 0, NULL); break; case IPPROTO_UDP: state = get_redirect_state (af, IPPROTO_UDP, source_ip, source_port, destination_ip, destination_port, NULL); break; case IPPROTO_TCP: state = get_redirect_state (af, IPPROTO_TCP, source_ip, source_port, destination_ip, destination_port, NULL); break; default: GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMP packets dropped (not allowed)"), 1, GNUNET_NO); return; } if (NULL == state) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("ICMP Packet dropped, have no matching connection information\n")); return; } mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader); tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen); tnq->payload = &tnq[1]; tnq->len = mlen; i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1]; i2v->header.size = htons ((uint16_t) mlen); i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN); i2v->af = htonl (af); memcpy (&i2v->icmp_header, icmp, pktlen); send_packet_to_mesh_channel (state, tnq); } /** * @brief Handles an UDP packet received from the helper. * * @param udp A pointer to the Packet * @param pktlen number of bytes in 'udp' * @param af address family (AFINET or AF_INET6) * @param destination_ip destination IP-address of the IP packet (should * be our local address) * @param source_ip original source IP-address of the IP packet (should * be the original destination address) */ static void udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp, size_t pktlen, int af, const void *destination_ip, const void *source_ip) { struct ChannelState *state; struct ChannelMessageQueue *tnq; struct GNUNET_EXIT_UdpReplyMessage *urm; size_t mlen; { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received UDP packet going from %s:%u to %s:%u\n", inet_ntop (af, source_ip, sbuf, sizeof (sbuf)), (unsigned int) ntohs (udp->source_port), inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)), (unsigned int) ntohs (udp->destination_port)); } if (pktlen < sizeof (struct GNUNET_TUN_UdpHeader)) { /* blame kernel */ GNUNET_break (0); return; } if (pktlen != ntohs (udp->len)) { /* blame kernel */ GNUNET_break (0); return; } state = get_redirect_state (af, IPPROTO_UDP, source_ip, ntohs (udp->source_port), destination_ip, ntohs (udp->destination_port), NULL); if (NULL == state) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("UDP Packet dropped, have no matching connection information\n")); return; } mlen = sizeof (struct GNUNET_EXIT_UdpReplyMessage) + pktlen - sizeof (struct GNUNET_TUN_UdpHeader); tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen); tnq->payload = &tnq[1]; tnq->len = mlen; urm = (struct GNUNET_EXIT_UdpReplyMessage *) &tnq[1]; urm->header.size = htons ((uint16_t) mlen); urm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY); urm->source_port = htons (0); urm->destination_port = htons (0); memcpy (&urm[1], &udp[1], pktlen - sizeof (struct GNUNET_TUN_UdpHeader)); send_packet_to_mesh_channel (state, tnq); } /** * @brief Handles a TCP packet received from the helper. * * @param tcp A pointer to the Packet * @param pktlen the length of the packet, including its TCP header * @param af address family (AFINET or AF_INET6) * @param destination_ip destination IP-address of the IP packet (should * be our local address) * @param source_ip original source IP-address of the IP packet (should * be the original destination address) */ static void tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp, size_t pktlen, int af, const void *destination_ip, const void *source_ip) { struct ChannelState *state; char buf[pktlen] GNUNET_ALIGN; struct GNUNET_TUN_TcpHeader *mtcp; struct GNUNET_EXIT_TcpDataMessage *tdm; struct ChannelMessageQueue *tnq; size_t mlen; { char sbuf[INET6_ADDRSTRLEN]; char dbuf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received TCP packet with %u bytes going from %s:%u to %s:%u\n", pktlen - sizeof (struct GNUNET_TUN_TcpHeader), inet_ntop (af, source_ip, sbuf, sizeof (sbuf)), (unsigned int) ntohs (tcp->source_port), inet_ntop (af, destination_ip, dbuf, sizeof (dbuf)), (unsigned int) ntohs (tcp->destination_port)); } if (pktlen < sizeof (struct GNUNET_TUN_TcpHeader)) { /* blame kernel */ GNUNET_break (0); return; } state = get_redirect_state (af, IPPROTO_TCP, source_ip, ntohs (tcp->source_port), destination_ip, ntohs (tcp->destination_port), NULL); if (NULL == state) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("TCP Packet dropped, have no matching connection information\n")); return; } /* mug port numbers and crc to avoid information leakage; sender will need to lookup the correct values anyway */ memcpy (buf, tcp, pktlen); mtcp = (struct GNUNET_TUN_TcpHeader *) buf; mtcp->source_port = 0; mtcp->destination_port = 0; mtcp->crc = 0; mlen = sizeof (struct GNUNET_EXIT_TcpDataMessage) + (pktlen - sizeof (struct GNUNET_TUN_TcpHeader)); if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } tnq = GNUNET_malloc (sizeof (struct ChannelMessageQueue) + mlen); tnq->payload = &tnq[1]; tnq->len = mlen; tdm = (struct GNUNET_EXIT_TcpDataMessage *) &tnq[1]; tdm->header.size = htons ((uint16_t) mlen); tdm->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_VPN); tdm->reserved = htonl (0); memcpy (&tdm->tcp_header, buf, pktlen); send_packet_to_mesh_channel (state, tnq); } /** * Receive packets from the helper-process * * @param cls unused * @param client unsued * @param message message received from helper */ static int message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, const struct GNUNET_MessageHeader *message) { const struct GNUNET_TUN_Layer2PacketHeader *pkt_tun; size_t size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u-byte message of type %u from gnunet-helper-exit\n", ntohs (message->size), ntohs (message->type)); GNUNET_STATISTICS_update (stats, gettext_noop ("# Packets received from TUN"), 1, GNUNET_NO); if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) { GNUNET_break (0); return GNUNET_OK; } size = ntohs (message->size); if (size < sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); return GNUNET_OK; } GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes received from TUN"), size, GNUNET_NO); pkt_tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1]; size -= sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_MessageHeader); switch (ntohs (pkt_tun->proto)) { case ETH_P_IPV4: { const struct GNUNET_TUN_IPv4Header *pkt4; if (size < sizeof (struct GNUNET_TUN_IPv4Header)) { /* Kernel to blame? */ GNUNET_break (0); return GNUNET_OK; } pkt4 = (const struct GNUNET_TUN_IPv4Header *) &pkt_tun[1]; if (size != ntohs (pkt4->total_length)) { /* Kernel to blame? */ GNUNET_break (0); return GNUNET_OK; } if (pkt4->header_length * 4 != sizeof (struct GNUNET_TUN_IPv4Header)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("IPv4 packet options received. Ignored.\n")); return GNUNET_OK; } size -= sizeof (struct GNUNET_TUN_IPv4Header); switch (pkt4->protocol) { case IPPROTO_UDP: udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt4[1], size, AF_INET, &pkt4->destination_address, &pkt4->source_address); break; case IPPROTO_TCP: tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt4[1], size, AF_INET, &pkt4->destination_address, &pkt4->source_address); break; case IPPROTO_ICMP: icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size, AF_INET, &pkt4->destination_address, &pkt4->source_address); break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("IPv4 packet with unsupported next header %u received. Ignored.\n"), (int) pkt4->protocol); return GNUNET_OK; } } break; case ETH_P_IPV6: { const struct GNUNET_TUN_IPv6Header *pkt6; if (size < sizeof (struct GNUNET_TUN_IPv6Header)) { /* Kernel to blame? */ GNUNET_break (0); return GNUNET_OK; } pkt6 = (struct GNUNET_TUN_IPv6Header *) &pkt_tun[1]; if (size != ntohs (pkt6->payload_length) + sizeof (struct GNUNET_TUN_IPv6Header)) { /* Kernel to blame? */ GNUNET_break (0); return GNUNET_OK; } size -= sizeof (struct GNUNET_TUN_IPv6Header); switch (pkt6->next_header) { case IPPROTO_UDP: udp_from_helper ((const struct GNUNET_TUN_UdpHeader *) &pkt6[1], size, AF_INET6, &pkt6->destination_address, &pkt6->source_address); break; case IPPROTO_TCP: tcp_from_helper ((const struct GNUNET_TUN_TcpHeader *) &pkt6[1], size, AF_INET6, &pkt6->destination_address, &pkt6->source_address); break; case IPPROTO_ICMPV6: icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size, AF_INET6, &pkt6->destination_address, &pkt6->source_address); break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("IPv6 packet with unsupported next header %d received. Ignored.\n"), pkt6->next_header); return GNUNET_OK; } } break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Packet from unknown protocol %u received. Ignored.\n"), ntohs (pkt_tun->proto)); break; } return GNUNET_OK; } /** * We need to create a (unique) fresh local address (IP+port). * Fill one in. * * @param af desired address family * @param proto desired protocol (IPPROTO_UDP or IPPROTO_TCP) * @param local_address address to initialize */ static void setup_fresh_address (int af, uint8_t proto, struct SocketAddress *local_address) { local_address->af = af; local_address->proto = (uint8_t) proto; /* default "local" port range is often 32768--61000, so we pick a random value in that range */ if ( ( (af == AF_INET) && (proto == IPPROTO_ICMP) ) || ( (af == AF_INET6) && (proto == IPPROTO_ICMPV6) ) ) local_address->port = 0; else local_address->port = (uint16_t) 32768 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 28232); switch (af) { case AF_INET: { struct in_addr addr; struct in_addr mask; struct in_addr rnd; addr = exit_ipv4addr; mask = exit_ipv4mask; if (0 == ~mask.s_addr) { /* only one valid IP anyway */ local_address->address.ipv4 = addr; return; } /* Given 192.168.0.1/255.255.0.0, we want a mask of '192.168.255.255', thus: */ mask.s_addr = addr.s_addr | ~mask.s_addr; /* Pick random IPv4 address within the subnet, except 'addr' or 'mask' itself */ do { rnd.s_addr = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); local_address->address.ipv4.s_addr = (addr.s_addr | rnd.s_addr) & mask.s_addr; } while ( (local_address->address.ipv4.s_addr == addr.s_addr) || (local_address->address.ipv4.s_addr == mask.s_addr) ); } break; case AF_INET6: { struct in6_addr addr; struct in6_addr mask; struct in6_addr rnd; int i; addr = exit_ipv6addr; GNUNET_assert (ipv6prefix < 128); if (ipv6prefix == 127) { /* only one valid IP anyway */ local_address->address.ipv6 = addr; return; } /* Given ABCD::/96, we want a mask of 'ABCD::FFFF:FFFF, thus: */ mask = addr; for (i=127;i>=ipv6prefix;i--) mask.s6_addr[i / 8] |= (1 << (i % 8)); /* Pick random IPv6 address within the subnet, except 'addr' or 'mask' itself */ do { for (i=0;i<16;i++) { rnd.s6_addr[i] = (unsigned char) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 256); local_address->address.ipv6.s6_addr[i] = (addr.s6_addr[i] | rnd.s6_addr[i]) & mask.s6_addr[i]; } } while ( (0 == memcmp (&local_address->address.ipv6, &addr, sizeof (struct in6_addr))) || (0 == memcmp (&local_address->address.ipv6, &mask, sizeof (struct in6_addr))) ); } break; default: GNUNET_assert (0); } } /** * We are starting a fresh connection (TCP or UDP) and need * to pick a source port and IP address (within the correct * range and address family) to associate replies with the * connection / correct mesh channel. This function generates * a "fresh" source IP and source port number for a connection * After picking a good source address, this function sets up * the state in the 'connections_map' and 'connections_heap' * to allow finding the state when needed later. The function * also makes sure that we remain within memory limits by * cleaning up 'old' states. * * @param state skeleton state to setup a record for; should * 'state->specifics.tcp_udp.ri.remote_address' filled in so that * this code can determine which AF/protocol is * going to be used (the 'channel' should also * already be set); after calling this function, * heap_node and the local_address will be * also initialized (heap_node != NULL can be * used to test if a state has been fully setup). */ static void setup_state_record (struct ChannelState *state) { struct GNUNET_HashCode key; struct ChannelState *s; /* generate fresh, unique address */ do { if (NULL == state->specifics.tcp_udp.serv) setup_fresh_address (state->specifics.tcp_udp.ri.remote_address.af, state->specifics.tcp_udp.ri.remote_address.proto, &state->specifics.tcp_udp.ri.local_address); else setup_fresh_address (state->specifics.tcp_udp.serv->address.af, state->specifics.tcp_udp.serv->address.proto, &state->specifics.tcp_udp.ri.local_address); } while (NULL != get_redirect_state (state->specifics.tcp_udp.ri.remote_address.af, state->specifics.tcp_udp.ri.remote_address.proto, &state->specifics.tcp_udp.ri.remote_address.address, state->specifics.tcp_udp.ri.remote_address.port, &state->specifics.tcp_udp.ri.local_address.address, state->specifics.tcp_udp.ri.local_address.port, &key)); { char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Picked local address %s:%u for new connection\n", inet_ntop (state->specifics.tcp_udp.ri.local_address.af, &state->specifics.tcp_udp.ri.local_address.address, buf, sizeof (buf)), (unsigned int) state->specifics.tcp_udp.ri.local_address.port); } state->specifics.tcp_udp.state_key = key; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (connections_map, &key, state, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); state->specifics.tcp_udp.heap_node = GNUNET_CONTAINER_heap_insert (connections_heap, state, GNUNET_TIME_absolute_get ().abs_value_us); while (GNUNET_CONTAINER_heap_get_size (connections_heap) > max_connections) { s = GNUNET_CONTAINER_heap_remove_root (connections_heap); GNUNET_assert (state != s); s->specifics.tcp_udp.heap_node = NULL; GNUNET_MESH_channel_destroy (s->channel); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (connections_map, &s->specifics.tcp_udp.state_key, s)); GNUNET_free (s); } } /** * Prepare an IPv4 packet for transmission via the TUN interface. * Initializes the IP header and calculates checksums (IP+UDP/TCP). * For UDP, the UDP header will be fully created, whereas for TCP * only the ports and checksum will be filled in. So for TCP, * a skeleton TCP header must be part of the provided payload. * * @param payload payload of the packet (starting with UDP payload or * TCP header, depending on protocol) * @param payload_length number of bytes in 'payload' * @param protocol IPPROTO_UDP or IPPROTO_TCP * @param tcp_header skeleton of the TCP header, NULL for UDP * @param src_address source address to use (IP and port) * @param dst_address destination address to use (IP and port) * @param pkt4 where to write the assembled packet; must * contain enough space for the IP header, UDP/TCP header * AND the payload */ static void prepare_ipv4_packet (const void *payload, size_t payload_length, int protocol, const struct GNUNET_TUN_TcpHeader *tcp_header, const struct SocketAddress *src_address, const struct SocketAddress *dst_address, struct GNUNET_TUN_IPv4Header *pkt4) { size_t len; len = payload_length; switch (protocol) { case IPPROTO_UDP: len += sizeof (struct GNUNET_TUN_UdpHeader); break; case IPPROTO_TCP: len += sizeof (struct GNUNET_TUN_TcpHeader); GNUNET_assert (NULL != tcp_header); break; default: GNUNET_break (0); return; } if (len + sizeof (struct GNUNET_TUN_IPv4Header) > UINT16_MAX) { GNUNET_break (0); return; } GNUNET_TUN_initialize_ipv4_header (pkt4, protocol, len, &src_address->address.ipv4, &dst_address->address.ipv4); switch (protocol) { case IPPROTO_UDP: { struct GNUNET_TUN_UdpHeader *pkt4_udp = (struct GNUNET_TUN_UdpHeader *) &pkt4[1]; pkt4_udp->source_port = htons (src_address->port); pkt4_udp->destination_port = htons (dst_address->port); pkt4_udp->len = htons ((uint16_t) payload_length); GNUNET_TUN_calculate_udp4_checksum (pkt4, pkt4_udp, payload, payload_length); memcpy (&pkt4_udp[1], payload, payload_length); } break; case IPPROTO_TCP: { struct GNUNET_TUN_TcpHeader *pkt4_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt4[1]; *pkt4_tcp = *tcp_header; pkt4_tcp->source_port = htons (src_address->port); pkt4_tcp->destination_port = htons (dst_address->port); GNUNET_TUN_calculate_tcp4_checksum (pkt4, pkt4_tcp, payload, payload_length); memcpy (&pkt4_tcp[1], payload, payload_length); } break; default: GNUNET_assert (0); } } /** * Prepare an IPv6 packet for transmission via the TUN interface. * Initializes the IP header and calculates checksums (IP+UDP/TCP). * For UDP, the UDP header will be fully created, whereas for TCP * only the ports and checksum will be filled in. So for TCP, * a skeleton TCP header must be part of the provided payload. * * @param payload payload of the packet (starting with UDP payload or * TCP header, depending on protocol) * @param payload_length number of bytes in 'payload' * @param protocol IPPROTO_UDP or IPPROTO_TCP * @param tcp_header skeleton TCP header data to send, NULL for UDP * @param src_address source address to use (IP and port) * @param dst_address destination address to use (IP and port) * @param pkt6 where to write the assembled packet; must * contain enough space for the IP header, UDP/TCP header * AND the payload */ static void prepare_ipv6_packet (const void *payload, size_t payload_length, int protocol, const struct GNUNET_TUN_TcpHeader *tcp_header, const struct SocketAddress *src_address, const struct SocketAddress *dst_address, struct GNUNET_TUN_IPv6Header *pkt6) { size_t len; len = payload_length; switch (protocol) { case IPPROTO_UDP: len += sizeof (struct GNUNET_TUN_UdpHeader); break; case IPPROTO_TCP: len += sizeof (struct GNUNET_TUN_TcpHeader); break; default: GNUNET_break (0); return; } if (len > UINT16_MAX) { GNUNET_break (0); return; } GNUNET_TUN_initialize_ipv6_header (pkt6, protocol, len, &src_address->address.ipv6, &dst_address->address.ipv6); switch (protocol) { case IPPROTO_UDP: { struct GNUNET_TUN_UdpHeader *pkt6_udp = (struct GNUNET_TUN_UdpHeader *) &pkt6[1]; pkt6_udp->source_port = htons (src_address->port); pkt6_udp->destination_port = htons (dst_address->port); pkt6_udp->len = htons ((uint16_t) payload_length); GNUNET_TUN_calculate_udp6_checksum (pkt6, pkt6_udp, payload, payload_length); memcpy (&pkt6_udp[1], payload, payload_length); } break; case IPPROTO_TCP: { struct GNUNET_TUN_TcpHeader *pkt6_tcp = (struct GNUNET_TUN_TcpHeader *) &pkt6[1]; /* memcpy first here as some TCP header fields are initialized this way! */ *pkt6_tcp = *tcp_header; pkt6_tcp->source_port = htons (src_address->port); pkt6_tcp->destination_port = htons (dst_address->port); GNUNET_TUN_calculate_tcp6_checksum (pkt6, pkt6_tcp, payload, payload_length); memcpy (&pkt6_tcp[1], payload, payload_length); } break; default: GNUNET_assert (0); break; } } /** * Send a TCP packet via the TUN interface. * * @param destination_address IP and port to use for the TCP packet's destination * @param source_address IP and port to use for the TCP packet's source * @param tcp_header header template to use * @param payload payload of the TCP packet * @param payload_length number of bytes in @a payload */ static void send_tcp_packet_via_tun (const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const struct GNUNET_TUN_TcpHeader *tcp_header, const void *payload, size_t payload_length) { size_t len; GNUNET_STATISTICS_update (stats, gettext_noop ("# TCP packets sent via TUN"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending packet with %u bytes TCP payload via TUN\n", (unsigned int) payload_length); len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader); switch (source_address->af) { case AF_INET: len += sizeof (struct GNUNET_TUN_IPv4Header); break; case AF_INET6: len += sizeof (struct GNUNET_TUN_IPv6Header); break; default: GNUNET_break (0); return; } len += sizeof (struct GNUNET_TUN_TcpHeader); len += payload_length; if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } { char buf[len] GNUNET_ALIGN; struct GNUNET_MessageHeader *hdr; struct GNUNET_TUN_Layer2PacketHeader *tun; hdr = (struct GNUNET_MessageHeader *) buf; hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); hdr->size = htons (len); tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1]; tun->flags = htons (0); switch (source_address->af) { case AF_INET: { struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1]; tun->proto = htons (ETH_P_IPV4); prepare_ipv4_packet (payload, payload_length, IPPROTO_TCP, tcp_header, source_address, destination_address, ipv4); } break; case AF_INET6: { struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1]; tun->proto = htons (ETH_P_IPV6); prepare_ipv6_packet (payload, payload_length, IPPROTO_TCP, tcp_header, source_address, destination_address, ipv6); } break; default: GNUNET_assert (0); break; } if (NULL != helper_handle) (void) GNUNET_HELPER_send (helper_handle, (const struct GNUNET_MessageHeader*) buf, GNUNET_YES, NULL, NULL); } } /** * Process a request via mesh to send a request to a TCP service * offered by this system. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our `struct ChannelState *` * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_tcp_service (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *state = *channel_ctx; const struct GNUNET_EXIT_TcpServiceStartMessage *start; uint16_t pkt_len = ntohs (message->size); if (NULL == state) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_YES == state->is_dns) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_SYSERR == state->is_dns) { /* channel is UDP/TCP from now on */ state->is_dns = GNUNET_NO; } GNUNET_STATISTICS_update (stats, gettext_noop ("# TCP service creation requests received via mesh"), 1, GNUNET_NO); GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes received from MESH"), pkt_len, GNUNET_NO); /* check that we got at least a valid header */ if (pkt_len < sizeof (struct GNUNET_EXIT_TcpServiceStartMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } start = (const struct GNUNET_EXIT_TcpServiceStartMessage*) message; pkt_len -= sizeof (struct GNUNET_EXIT_TcpServiceStartMessage); if ( (NULL != state->specifics.tcp_udp.serv) || (NULL != state->specifics.tcp_udp.heap_node) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_break_op (ntohl (start->reserved) == 0); /* setup fresh connection */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for forwarding to TCP service %s on port %u\n", GNUNET_i2s (&state->peer), GNUNET_h2s (&start->service_descriptor), (unsigned int) ntohs (start->tcp_header.destination_port)); if (NULL == (state->specifics.tcp_udp.serv = find_service (tcp_services, &start->service_descriptor, ntohs (start->tcp_header.destination_port)))) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("No service %s found for %s on port %d!\n"), GNUNET_h2s (&start->service_descriptor), "TCP", ntohs (start->tcp_header.destination_port)); GNUNET_STATISTICS_update (stats, gettext_noop ("# TCP requests dropped (no such service)"), 1, GNUNET_NO); return GNUNET_SYSERR; } state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address; setup_state_record (state); send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, &state->specifics.tcp_udp.ri.local_address, &start->tcp_header, &start[1], pkt_len); return GNUNET_YES; } /** * Process a request to forward TCP data to the Internet via this peer. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our 'struct ChannelState *' * @param message the actual message * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Channel *channel, void **channel_ctx GNUNET_UNUSED, const struct GNUNET_MessageHeader *message) { struct ChannelState *state = *channel_ctx; const struct GNUNET_EXIT_TcpInternetStartMessage *start; uint16_t pkt_len = ntohs (message->size); const struct in_addr *v4; const struct in6_addr *v6; const void *payload; int af; if (NULL == state) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_YES == state->is_dns) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_SYSERR == state->is_dns) { /* channel is UDP/TCP from now on */ state->is_dns = GNUNET_NO; } GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes received from MESH"), pkt_len, GNUNET_NO); GNUNET_STATISTICS_update (stats, gettext_noop ("# TCP IP-exit creation requests received via mesh"), 1, GNUNET_NO); if (pkt_len < sizeof (struct GNUNET_EXIT_TcpInternetStartMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } start = (const struct GNUNET_EXIT_TcpInternetStartMessage*) message; pkt_len -= sizeof (struct GNUNET_EXIT_TcpInternetStartMessage); if ( (NULL != state->specifics.tcp_udp.serv) || (NULL != state->specifics.tcp_udp.heap_node) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (start->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } af = (int) ntohl (start->af); state->specifics.tcp_udp.ri.remote_address.af = af; switch (af) { case AF_INET: if (pkt_len < sizeof (struct in_addr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (! ipv4_exit) { GNUNET_break_op (0); return GNUNET_SYSERR; } v4 = (const struct in_addr*) &start[1]; payload = &v4[1]; pkt_len -= sizeof (struct in_addr); state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4; break; case AF_INET6: if (pkt_len < sizeof (struct in6_addr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (! ipv6_exit) { GNUNET_break_op (0); return GNUNET_SYSERR; } v6 = (const struct in6_addr*) &start[1]; payload = &v6[1]; pkt_len -= sizeof (struct in6_addr); state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6; break; default: GNUNET_break_op (0); return GNUNET_SYSERR; } { char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for starting TCP stream to %s:%u\n", GNUNET_i2s (&state->peer), inet_ntop (af, &state->specifics.tcp_udp.ri.remote_address.address, buf, sizeof (buf)), (unsigned int) ntohs (start->tcp_header.destination_port)); } state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_TCP; state->specifics.tcp_udp.ri.remote_address.port = ntohs (start->tcp_header.destination_port); setup_state_record (state); send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, &state->specifics.tcp_udp.ri.local_address, &start->tcp_header, payload, pkt_len); return GNUNET_YES; } /** * Process a request to forward TCP data on an established * connection via this peer. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our 'struct ChannelState *' * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Channel *channel, void **channel_ctx GNUNET_UNUSED, const struct GNUNET_MessageHeader *message) { struct ChannelState *state = *channel_ctx; const struct GNUNET_EXIT_TcpDataMessage *data; uint16_t pkt_len = ntohs (message->size); GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes received from MESH"), pkt_len, GNUNET_NO); GNUNET_STATISTICS_update (stats, gettext_noop ("# TCP data requests received via mesh"), 1, GNUNET_NO); if (pkt_len < sizeof (struct GNUNET_EXIT_TcpDataMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } data = (const struct GNUNET_EXIT_TcpDataMessage*) message; pkt_len -= sizeof (struct GNUNET_EXIT_TcpDataMessage); if ( (NULL == state) || (NULL == state->specifics.tcp_udp.heap_node) ) { /* connection should have been up! */ GNUNET_STATISTICS_update (stats, gettext_noop ("# TCP DATA requests dropped (no session)"), 1, GNUNET_NO); return GNUNET_SYSERR; } if (data->tcp_header.off * 4 < sizeof (struct GNUNET_TUN_TcpHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_YES == state->is_dns) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_SYSERR == state->is_dns) { /* channel is UDP/TCP from now on */ state->is_dns = GNUNET_NO; } GNUNET_break_op (ntohl (data->reserved) == 0); { char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received additional %u bytes of data from %s for TCP stream to %s:%u\n", pkt_len, GNUNET_i2s (&state->peer), inet_ntop (state->specifics.tcp_udp.ri.remote_address.af, &state->specifics.tcp_udp.ri.remote_address.address, buf, sizeof (buf)), (unsigned int) state->specifics.tcp_udp.ri.remote_address.port); } send_tcp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, &state->specifics.tcp_udp.ri.local_address, &data->tcp_header, &data[1], pkt_len); return GNUNET_YES; } /** * Send an ICMP packet via the TUN interface. * * @param destination_address IP to use for the ICMP packet's destination * @param source_address IP to use for the ICMP packet's source * @param icmp_header ICMP header to send * @param payload payload of the ICMP packet (does NOT include ICMP header) * @param payload_length number of bytes of data in @a payload */ static void send_icmp_packet_via_tun (const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const struct GNUNET_TUN_IcmpHeader *icmp_header, const void *payload, size_t payload_length) { size_t len; struct GNUNET_TUN_IcmpHeader *icmp; GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMP packets sent via TUN"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending packet with %u bytes ICMP payload via TUN\n", (unsigned int) payload_length); len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader); switch (destination_address->af) { case AF_INET: len += sizeof (struct GNUNET_TUN_IPv4Header); break; case AF_INET6: len += sizeof (struct GNUNET_TUN_IPv6Header); break; default: GNUNET_break (0); return; } len += sizeof (struct GNUNET_TUN_IcmpHeader); len += payload_length; if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } { char buf[len] GNUNET_ALIGN; struct GNUNET_MessageHeader *hdr; struct GNUNET_TUN_Layer2PacketHeader *tun; hdr= (struct GNUNET_MessageHeader *) buf; hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); hdr->size = htons (len); tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1]; tun->flags = htons (0); switch (source_address->af) { case AF_INET: { struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1]; tun->proto = htons (ETH_P_IPV4); GNUNET_TUN_initialize_ipv4_header (ipv4, IPPROTO_ICMP, sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length, &source_address->address.ipv4, &destination_address->address.ipv4); icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1]; } break; case AF_INET6: { struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1]; tun->proto = htons (ETH_P_IPV6); GNUNET_TUN_initialize_ipv6_header (ipv6, IPPROTO_ICMPV6, sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length, &source_address->address.ipv6, &destination_address->address.ipv6); icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1]; } break; default: GNUNET_assert (0); break; } *icmp = *icmp_header; memcpy (&icmp[1], payload, payload_length); GNUNET_TUN_calculate_icmp_checksum (icmp, payload, payload_length); if (NULL != helper_handle) (void) GNUNET_HELPER_send (helper_handle, (const struct GNUNET_MessageHeader*) buf, GNUNET_YES, NULL, NULL); } } /** * Synthesize a plausible ICMP payload for an ICMPv4 error * response on the given channel. * * @param state channel information * @param ipp IPv6 header to fill in (ICMP payload) * @param udp "UDP" header to fill in (ICMP payload); might actually * also be the first 8 bytes of the TCP header */ static void make_up_icmpv4_payload (struct ChannelState *state, struct GNUNET_TUN_IPv4Header *ipp, struct GNUNET_TUN_UdpHeader *udp) { GNUNET_TUN_initialize_ipv4_header (ipp, state->specifics.tcp_udp.ri.remote_address.proto, sizeof (struct GNUNET_TUN_TcpHeader), &state->specifics.tcp_udp.ri.remote_address.address.ipv4, &state->specifics.tcp_udp.ri.local_address.address.ipv4); udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port); udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port); udp->len = htons (0); udp->crc = htons (0); } /** * Synthesize a plausible ICMP payload for an ICMPv6 error * response on the given channel. * * @param state channel information * @param ipp IPv6 header to fill in (ICMP payload) * @param udp "UDP" header to fill in (ICMP payload); might actually * also be the first 8 bytes of the TCP header */ static void make_up_icmpv6_payload (struct ChannelState *state, struct GNUNET_TUN_IPv6Header *ipp, struct GNUNET_TUN_UdpHeader *udp) { GNUNET_TUN_initialize_ipv6_header (ipp, state->specifics.tcp_udp.ri.remote_address.proto, sizeof (struct GNUNET_TUN_TcpHeader), &state->specifics.tcp_udp.ri.remote_address.address.ipv6, &state->specifics.tcp_udp.ri.local_address.address.ipv6); udp->source_port = htons (state->specifics.tcp_udp.ri.remote_address.port); udp->destination_port = htons (state->specifics.tcp_udp.ri.local_address.port); udp->len = htons (0); udp->crc = htons (0); } /** * Process a request to forward ICMP data to the Internet via this peer. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our 'struct ChannelState *' * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_icmp_remote (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *state = *channel_ctx; const struct GNUNET_EXIT_IcmpInternetMessage *msg; uint16_t pkt_len = ntohs (message->size); const struct in_addr *v4; const struct in6_addr *v6; const void *payload; char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN; int af; if (GNUNET_YES == state->is_dns) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_SYSERR == state->is_dns) { /* channel is UDP/TCP from now on */ state->is_dns = GNUNET_NO; } GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes received from MESH"), pkt_len, GNUNET_NO); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMP IP-exit requests received via mesh"), 1, GNUNET_NO); if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message; pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage); af = (int) ntohl (msg->af); if ( (NULL != state->specifics.tcp_udp.heap_node) && (af != state->specifics.tcp_udp.ri.remote_address.af) ) { /* other peer switched AF on this channel; not allowed */ GNUNET_break_op (0); return GNUNET_SYSERR; } switch (af) { case AF_INET: if (pkt_len < sizeof (struct in_addr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (! ipv4_exit) { GNUNET_break_op (0); return GNUNET_SYSERR; } v4 = (const struct in_addr*) &msg[1]; payload = &v4[1]; pkt_len -= sizeof (struct in_addr); state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4; if (NULL == state->specifics.tcp_udp.heap_node) { state->specifics.tcp_udp.ri.remote_address.af = af; state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMP; setup_state_record (state); } /* check that ICMP type is something we want to support and possibly make up payload! */ switch (msg->icmp_header.type) { case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: break; case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: if (0 != pkt_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } /* make up payload */ { struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) buf; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); pkt_len = sizeof (struct GNUNET_TUN_IPv4Header) + 8; make_up_icmpv4_payload (state, ipp, udp); payload = ipp; } break; default: GNUNET_break_op (0); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 1, GNUNET_NO); return GNUNET_SYSERR; } /* end AF_INET */ break; case AF_INET6: if (pkt_len < sizeof (struct in6_addr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (! ipv6_exit) { GNUNET_break_op (0); return GNUNET_SYSERR; } v6 = (const struct in6_addr*) &msg[1]; payload = &v6[1]; pkt_len -= sizeof (struct in6_addr); state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6; if (NULL == state->specifics.tcp_udp.heap_node) { state->specifics.tcp_udp.ri.remote_address.af = af; state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_ICMPV6; setup_state_record (state); } /* check that ICMP type is something we want to support and possibly make up payload! */ switch (msg->icmp_header.type) { case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY: case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: break; case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: if (0 != pkt_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } /* make up payload */ { struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) buf; struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); pkt_len = sizeof (struct GNUNET_TUN_IPv6Header) + 8; make_up_icmpv6_payload (state, ipp, udp); payload = ipp; } break; default: GNUNET_break_op (0); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 1, GNUNET_NO); return GNUNET_SYSERR; } /* end AF_INET6 */ break; default: /* bad AF */ GNUNET_break_op (0); return GNUNET_SYSERR; } { char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ICMP data from %s for forwarding to %s\n", GNUNET_i2s (&state->peer), inet_ntop (af, &state->specifics.tcp_udp.ri.remote_address.address, buf, sizeof (buf))); } send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, &state->specifics.tcp_udp.ri.local_address, &msg->icmp_header, payload, pkt_len); return GNUNET_YES; } /** * Setup ICMP payload for ICMP error messages. Called * for both IPv4 and IPv6 addresses. * * @param state context for creating the IP Packet * @param buf where to create the payload, has at least * sizeof (struct GNUNET_TUN_IPv6Header) + 8 bytes * @return number of bytes of payload we created in buf */ static uint16_t make_up_icmp_service_payload (struct ChannelState *state, char *buf) { switch (state->specifics.tcp_udp.serv->address.af) { case AF_INET: { struct GNUNET_TUN_IPv4Header *ipv4; struct GNUNET_TUN_UdpHeader *udp; ipv4 = (struct GNUNET_TUN_IPv4Header *)buf; udp = (struct GNUNET_TUN_UdpHeader *) &ipv4[1]; make_up_icmpv4_payload (state, ipv4, udp); GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); return sizeof (struct GNUNET_TUN_IPv4Header) + 8; } break; case AF_INET6: { struct GNUNET_TUN_IPv6Header *ipv6; struct GNUNET_TUN_UdpHeader *udp; ipv6 = (struct GNUNET_TUN_IPv6Header *)buf; udp = (struct GNUNET_TUN_UdpHeader *) &ipv6[1]; make_up_icmpv6_payload (state, ipv6, udp); GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); return sizeof (struct GNUNET_TUN_IPv6Header) + 8; } break; default: GNUNET_break (0); } return 0; } /** * Process a request via mesh to send ICMP data to a service * offered by this system. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our 'struct ChannelState *' * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_icmp_service (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *state = *channel_ctx; const struct GNUNET_EXIT_IcmpServiceMessage *msg; uint16_t pkt_len = ntohs (message->size); struct GNUNET_TUN_IcmpHeader icmp; char buf[sizeof (struct GNUNET_TUN_IPv6Header) + 8] GNUNET_ALIGN; const void *payload; if (GNUNET_YES == state->is_dns) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_SYSERR == state->is_dns) { /* channel is UDP/TCP from now on */ state->is_dns = GNUNET_NO; } GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes received from MESH"), pkt_len, GNUNET_NO); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMP service requests received via mesh"), 1, GNUNET_NO); /* check that we got at least a valid header */ if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message; pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for forwarding to ICMP service %s\n", GNUNET_i2s (&state->peer), GNUNET_h2s (&msg->service_descriptor)); if (NULL == state->specifics.tcp_udp.serv) { /* first packet to service must not be ICMP (cannot determine service!) */ GNUNET_break_op (0); return GNUNET_SYSERR; } icmp = msg->icmp_header; payload = &msg[1]; state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address; setup_state_record (state); /* check that ICMP type is something we want to support, perform ICMP PT if needed ans possibly make up payload */ switch (msg->af) { case AF_INET: switch (msg->icmp_header.type) { case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: if (state->specifics.tcp_udp.serv->address.af == AF_INET6) icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY; break; case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: if (state->specifics.tcp_udp.serv->address.af == AF_INET6) icmp.type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST; break; case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: if (state->specifics.tcp_udp.serv->address.af == AF_INET6) icmp.type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE; if (0 != pkt_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } payload = buf; pkt_len = make_up_icmp_service_payload (state, buf); break; case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: if (state->specifics.tcp_udp.serv->address.af == AF_INET6) icmp.type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED; if (0 != pkt_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } payload = buf; pkt_len = make_up_icmp_service_payload (state, buf); break; case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: if (state->specifics.tcp_udp.serv->address.af == AF_INET6) { GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"), 1, GNUNET_NO); return GNUNET_OK; } if (0 != pkt_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } payload = buf; pkt_len = make_up_icmp_service_payload (state, buf); break; default: GNUNET_break_op (0); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), 1, GNUNET_NO); return GNUNET_SYSERR; } /* end of AF_INET */ break; case AF_INET6: switch (msg->icmp_header.type) { case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY: if (state->specifics.tcp_udp.serv->address.af == AF_INET) icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY; break; case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: if (state->specifics.tcp_udp.serv->address.af == AF_INET) icmp.type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST; break; case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: if (state->specifics.tcp_udp.serv->address.af == AF_INET) icmp.type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE; if (0 != pkt_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } payload = buf; pkt_len = make_up_icmp_service_payload (state, buf); break; case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: if (state->specifics.tcp_udp.serv->address.af == AF_INET) icmp.type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED; if (0 != pkt_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } payload = buf; pkt_len = make_up_icmp_service_payload (state, buf); break; case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: if (state->specifics.tcp_udp.serv->address.af == AF_INET) { GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"), 1, GNUNET_NO); return GNUNET_OK; } if (0 != pkt_len) { GNUNET_break_op (0); return GNUNET_SYSERR; } payload = buf; pkt_len = make_up_icmp_service_payload (state, buf); break; default: GNUNET_break_op (0); GNUNET_STATISTICS_update (stats, gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), 1, GNUNET_NO); return GNUNET_SYSERR; } /* end of AF_INET6 */ break; default: GNUNET_break_op (0); return GNUNET_SYSERR; } send_icmp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, &state->specifics.tcp_udp.ri.local_address, &icmp, payload, pkt_len); return GNUNET_YES; } /** * Send a UDP packet via the TUN interface. * * @param destination_address IP and port to use for the UDP packet's destination * @param source_address IP and port to use for the UDP packet's source * @param payload payload of the UDP packet (does NOT include UDP header) * @param payload_length number of bytes of data in @a payload */ static void send_udp_packet_via_tun (const struct SocketAddress *destination_address, const struct SocketAddress *source_address, const void *payload, size_t payload_length) { size_t len; GNUNET_STATISTICS_update (stats, gettext_noop ("# UDP packets sent via TUN"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending packet with %u bytes UDP payload via TUN\n", (unsigned int) payload_length); len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader); switch (source_address->af) { case AF_INET: len += sizeof (struct GNUNET_TUN_IPv4Header); break; case AF_INET6: len += sizeof (struct GNUNET_TUN_IPv6Header); break; default: GNUNET_break (0); return; } len += sizeof (struct GNUNET_TUN_UdpHeader); len += payload_length; if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } { char buf[len] GNUNET_ALIGN; struct GNUNET_MessageHeader *hdr; struct GNUNET_TUN_Layer2PacketHeader *tun; hdr= (struct GNUNET_MessageHeader *) buf; hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); hdr->size = htons (len); tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1]; tun->flags = htons (0); switch (source_address->af) { case AF_INET: { struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1]; tun->proto = htons (ETH_P_IPV4); prepare_ipv4_packet (payload, payload_length, IPPROTO_UDP, NULL, source_address, destination_address, ipv4); } break; case AF_INET6: { struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1]; tun->proto = htons (ETH_P_IPV6); prepare_ipv6_packet (payload, payload_length, IPPROTO_UDP, NULL, source_address, destination_address, ipv6); } break; default: GNUNET_assert (0); break; } if (NULL != helper_handle) (void) GNUNET_HELPER_send (helper_handle, (const struct GNUNET_MessageHeader*) buf, GNUNET_YES, NULL, NULL); } } /** * Process a request to forward UDP data to the Internet via this peer. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our 'struct ChannelState *' * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_udp_remote (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *state = *channel_ctx; const struct GNUNET_EXIT_UdpInternetMessage *msg; uint16_t pkt_len = ntohs (message->size); const struct in_addr *v4; const struct in6_addr *v6; const void *payload; int af; if (GNUNET_YES == state->is_dns) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_SYSERR == state->is_dns) { /* channel is UDP/TCP from now on */ state->is_dns = GNUNET_NO; } GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes received from MESH"), pkt_len, GNUNET_NO); GNUNET_STATISTICS_update (stats, gettext_noop ("# UDP IP-exit requests received via mesh"), 1, GNUNET_NO); if (pkt_len < sizeof (struct GNUNET_EXIT_UdpInternetMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } msg = (const struct GNUNET_EXIT_UdpInternetMessage*) message; pkt_len -= sizeof (struct GNUNET_EXIT_UdpInternetMessage); af = (int) ntohl (msg->af); state->specifics.tcp_udp.ri.remote_address.af = af; switch (af) { case AF_INET: if (pkt_len < sizeof (struct in_addr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (! ipv4_exit) { GNUNET_break_op (0); return GNUNET_SYSERR; } v4 = (const struct in_addr*) &msg[1]; payload = &v4[1]; pkt_len -= sizeof (struct in_addr); state->specifics.tcp_udp.ri.remote_address.address.ipv4 = *v4; break; case AF_INET6: if (pkt_len < sizeof (struct in6_addr)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (! ipv6_exit) { GNUNET_break_op (0); return GNUNET_SYSERR; } v6 = (const struct in6_addr*) &msg[1]; payload = &v6[1]; pkt_len -= sizeof (struct in6_addr); state->specifics.tcp_udp.ri.remote_address.address.ipv6 = *v6; break; default: GNUNET_break_op (0); return GNUNET_SYSERR; } { char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for forwarding to UDP %s:%u\n", GNUNET_i2s (&state->peer), inet_ntop (af, &state->specifics.tcp_udp.ri.remote_address.address, buf, sizeof (buf)), (unsigned int) ntohs (msg->destination_port)); } state->specifics.tcp_udp.ri.remote_address.proto = IPPROTO_UDP; state->specifics.tcp_udp.ri.remote_address.port = msg->destination_port; if (NULL == state->specifics.tcp_udp.heap_node) setup_state_record (state); if (0 != ntohs (msg->source_port)) state->specifics.tcp_udp.ri.local_address.port = msg->source_port; send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, &state->specifics.tcp_udp.ri.local_address, payload, pkt_len); return GNUNET_YES; } /** * Process a request via mesh to send a request to a UDP service * offered by this system. * * @param cls closure, NULL * @param channel connection to the other end * @param channel_ctx pointer to our 'struct ChannelState *' * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_udp_service (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct ChannelState *state = *channel_ctx; const struct GNUNET_EXIT_UdpServiceMessage *msg; uint16_t pkt_len = ntohs (message->size); if (GNUNET_YES == state->is_dns) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_SYSERR == state->is_dns) { /* channel is UDP/TCP from now on */ state->is_dns = GNUNET_NO; } GNUNET_STATISTICS_update (stats, gettext_noop ("# Bytes received from MESH"), pkt_len, GNUNET_NO); GNUNET_STATISTICS_update (stats, gettext_noop ("# UDP service requests received via mesh"), 1, GNUNET_NO); /* check that we got at least a valid header */ if (pkt_len < sizeof (struct GNUNET_EXIT_UdpServiceMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } msg = (const struct GNUNET_EXIT_UdpServiceMessage*) message; pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for forwarding to UDP service %s on port %u\n", GNUNET_i2s (&state->peer), GNUNET_h2s (&msg->service_descriptor), (unsigned int) ntohs (msg->destination_port)); if (NULL == (state->specifics.tcp_udp.serv = find_service (udp_services, &msg->service_descriptor, ntohs (msg->destination_port)))) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("No service %s found for %s on port %d!\n"), GNUNET_h2s (&msg->service_descriptor), "UDP", ntohs (msg->destination_port)); GNUNET_STATISTICS_update (stats, gettext_noop ("# UDP requests dropped (no such service)"), 1, GNUNET_NO); return GNUNET_SYSERR; } state->specifics.tcp_udp.ri.remote_address = state->specifics.tcp_udp.serv->address; setup_state_record (state); if (0 != ntohs (msg->source_port)) state->specifics.tcp_udp.ri.local_address.port = msg->source_port; send_udp_packet_via_tun (&state->specifics.tcp_udp.ri.remote_address, &state->specifics.tcp_udp.ri.local_address, &msg[1], pkt_len); return GNUNET_YES; } /** * Callback from GNUNET_MESH for new channels. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel * @param port destination port * @param options channel options flags * @return initial channel context for the channel */ static void * new_channel (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { struct ChannelState *s = GNUNET_new (struct ChannelState); s->is_dns = GNUNET_SYSERR; s->peer = *initiator; GNUNET_STATISTICS_update (stats, gettext_noop ("# Inbound MESH channels created"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received inbound channel from `%s'\n", GNUNET_i2s (initiator)); s->channel = channel; return s; } /** * Function called by mesh whenever an inbound channel is destroyed. * Should clean up any associated state. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void clean_channel (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { struct ChannelState *s = channel_ctx; struct ChannelMessageQueue *tnq; LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel destroyed\n"); if (GNUNET_SYSERR == s->is_dns) { GNUNET_free (s); return; } if (GNUNET_YES == s->is_dns) { if (channels[s->specifics.dns.my_id] == s) channels[s->specifics.dns.my_id] = NULL; GNUNET_free_non_null (s->specifics.dns.reply); } else { while (NULL != (tnq = s->specifics.tcp_udp.head)) { GNUNET_CONTAINER_DLL_remove (s->specifics.tcp_udp.head, s->specifics.tcp_udp.tail, tnq); GNUNET_free (tnq); } if (NULL != s->specifics.tcp_udp.heap_node) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (connections_map, &s->specifics.tcp_udp.state_key, s)); GNUNET_CONTAINER_heap_remove_node (s->specifics.tcp_udp.heap_node); s->specifics.tcp_udp.heap_node = NULL; } } if (NULL != s->th) { GNUNET_MESH_notify_transmit_ready_cancel (s->th); s->th = NULL; } GNUNET_free (s); } /** * Function that frees everything from a hashmap * * @param cls unused * @param hash key * @param value value to free */ static int free_iterate (void *cls, const struct GNUNET_HashCode * hash, void *value) { GNUNET_free (value); return GNUNET_YES; } /** * Function scheduled as very last function, cleans up after us */ static void cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tskctx) { unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exit service is shutting down now\n"); if (NULL != helper_handle) { GNUNET_HELPER_stop (helper_handle, GNUNET_NO); helper_handle = NULL; } if (NULL != regex4) { GNUNET_REGEX_announce_cancel (regex4); regex4 = NULL; } if (NULL != regex6) { GNUNET_REGEX_announce_cancel (regex6); regex6 = NULL; } if (NULL != mesh_handle) { GNUNET_MESH_disconnect (mesh_handle); mesh_handle = NULL; } if (NULL != connections_map) { GNUNET_CONTAINER_multihashmap_iterate (connections_map, &free_iterate, NULL); GNUNET_CONTAINER_multihashmap_destroy (connections_map); connections_map = NULL; } if (NULL != connections_heap) { GNUNET_CONTAINER_heap_destroy (connections_heap); connections_heap = NULL; } if (NULL != tcp_services) { GNUNET_CONTAINER_multihashmap_iterate (tcp_services, &free_service_record, NULL); GNUNET_CONTAINER_multihashmap_destroy (tcp_services); tcp_services = NULL; } if (NULL != udp_services) { GNUNET_CONTAINER_multihashmap_iterate (udp_services, &free_service_record, NULL); GNUNET_CONTAINER_multihashmap_destroy (udp_services); udp_services = NULL; } if (NULL != dnsstub) { GNUNET_DNSSTUB_stop (dnsstub); dnsstub = NULL; } if (NULL != peer_key) { GNUNET_free (peer_key); peer_key = NULL; } if (GNUNET_SCHEDULER_NO_TASK != dht_task) { GNUNET_SCHEDULER_cancel (dht_task); dht_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != dht_put) { GNUNET_DHT_put_cancel (dht_put); dht_put = NULL; } if (NULL != dht) { GNUNET_DHT_disconnect (dht); dht = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } for (i=0;i<8;i++) GNUNET_free_non_null (exit_argv[i]); } /** * Add services to the service map. * * @param proto IPPROTO_TCP or IPPROTO_UDP * @param cpy copy of the service descriptor (can be mutilated) * @param name DNS name of the service */ static void add_services (int proto, char *cpy, const char *name) { char *redirect; char *hostname; char *hostport; struct LocalService *serv; char *n; size_t slen; slen = strlen (name); GNUNET_assert (slen >= 8); n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */); for (redirect = strtok (cpy, " "); redirect != NULL; redirect = strtok (NULL, " ")) { if (NULL == (hostname = strstr (redirect, ":"))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Option `%s' for domain `%s' is not formatted correctly!\n"), redirect, name); continue; } hostname[0] = '\0'; hostname++; if (NULL == (hostport = strstr (hostname, ":"))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Option `%s' for domain `%s' is not formatted correctly!\n"), redirect, name); continue; } hostport[0] = '\0'; hostport++; int local_port = atoi (redirect); int remote_port = atoi (hostport); if (!((local_port > 0) && (local_port < 65536))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("`%s' is not a valid port number (for domain `%s')!"), redirect, name); continue; } if (!((remote_port > 0) && (remote_port < 65536))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("`%s' is not a valid port number (for domain `%s')!"), hostport, name); continue; } serv = GNUNET_new (struct LocalService); serv->address.proto = proto; serv->my_port = (uint16_t) local_port; serv->address.port = remote_port; if (0 == strcmp ("localhost4", hostname)) { const char *ip4addr = exit_argv[5]; serv->address.af = AF_INET; GNUNET_assert (1 == inet_pton (AF_INET, ip4addr, &serv->address.address.ipv4)); } else if (0 == strcmp ("localhost6", hostname)) { const char *ip6addr = exit_argv[3]; serv->address.af = AF_INET6; GNUNET_assert (1 == inet_pton (AF_INET6, ip6addr, &serv->address.address.ipv6)); } else { struct addrinfo *res; int ret; ret = getaddrinfo (hostname, NULL, NULL, &res); if ( (ret != 0) || (res == NULL) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No addresses found for hostname `%s' of service `%s'!\n"), hostname, n); GNUNET_free (serv); continue; } serv->address.af = res->ai_family; switch (res->ai_family) { case AF_INET: if (! ipv4_enabled) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"), n); freeaddrinfo (res); GNUNET_free (serv); continue; } serv->address.address.ipv4 = ((struct sockaddr_in *) res->ai_addr)->sin_addr; break; case AF_INET6: if (! ipv6_enabled) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Service `%s' configured for IPv4, but IPv4 is disabled!\n"), n); freeaddrinfo (res); GNUNET_free (serv); continue; } serv->address.address.ipv6 = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; break; default: freeaddrinfo (res); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("No IP addresses found for hostname `%s' of service `%s'!\n"), hostname, n); GNUNET_free (serv); continue; } freeaddrinfo (res); } store_service ((IPPROTO_UDP == proto) ? udp_services : tcp_services, n, local_port, serv); } GNUNET_free (n); } /** * Reads the configuration servicecfg and populates udp_services * * @param cls unused * @param section name of section in config, equal to hostname */ static void read_service_conf (void *cls, const char *section) { char *cpy; if ((strlen (section) < 8) || (0 != strcmp (".gnunet.", section + (strlen (section) - 8)))) return; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, section, "UDP_REDIRECTS", &cpy)) { add_services (IPPROTO_UDP, cpy, section); GNUNET_free (cpy); } if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, section, "TCP_REDIRECTS", &cpy)) { add_services (IPPROTO_TCP, cpy, section); GNUNET_free (cpy); } } /** * We are running a DNS exit service, advertise it in the * DHT. This task is run periodically to do the DHT PUT. * * @param cls closure * @param tc scheduler context */ static void do_dht_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Function called when the DHT PUT operation is complete. * Schedules the next PUT. * * @param cls closure, NULL * @param success #GNUNET_OK if the operation worked (unused) */ static void dht_put_cont (void *cls, int success) { dht_put = NULL; dht_task = GNUNET_SCHEDULER_add_delayed (DHT_PUT_FREQUENCY, &do_dht_put, NULL); } /** * We are running a DNS exit service, advertise it in the * DHT. This task is run periodically to do the DHT PUT. * * @param cls closure * @param tc scheduler context */ static void do_dht_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Absolute expiration; dht_task = GNUNET_SCHEDULER_NO_TASK; expiration = GNUNET_TIME_absolute_ntoh (dns_advertisement.expiration_time); if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us < GNUNET_TIME_UNIT_HOURS.rel_value_us) { /* refresh advertisement */ expiration = GNUNET_TIME_relative_to_absolute (DNS_ADVERTISEMENT_TIMEOUT); dns_advertisement.expiration_time = GNUNET_TIME_absolute_hton (expiration); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (peer_key, &dns_advertisement.purpose, &dns_advertisement.signature)); } dht_put = GNUNET_DHT_put (dht, &dht_put_key, 1 /* replication */, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_DNS, sizeof (struct GNUNET_DNS_Advertisement), &dns_advertisement, expiration, GNUNET_TIME_UNIT_FOREVER_REL, &dht_put_cont, NULL); } /** * @brief Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg_ configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg_) { static struct GNUNET_MESH_MessageHandler handlers[] = { {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0}, {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0}, {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0}, {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0}, {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0}, {&receive_tcp_remote, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START, 0}, {&receive_tcp_data, GNUNET_MESSAGE_TYPE_VPN_TCP_DATA_TO_EXIT, 0}, {&receive_dns_request, GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET, 0}, {NULL, 0, 0} }; static uint32_t apptypes[] = { GNUNET_APPLICATION_TYPE_END, GNUNET_APPLICATION_TYPE_END, GNUNET_APPLICATION_TYPE_END, GNUNET_APPLICATION_TYPE_END }; unsigned int app_idx; char *exit_ifname; char *tun_ifname; char *policy; char *ipv6addr; char *ipv6prefix_s; char *ipv4addr; char *ipv4mask; char *binary; char *regex; char *prefixed_regex; struct in_addr dns_exit4; struct in6_addr dns_exit6; char *dns_exit; cfg = cfg_; ipv4_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV4"); ipv6_exit = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "EXIT_IPV6"); ipv4_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV4"); ipv6_enabled = GNUNET_CONFIGURATION_get_value_yesno (cfg, "exit", "ENABLE_IPV6"); if ( (ipv4_exit) || (ipv6_exit) ) { binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit"); if (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) //no nat, ipv4 only { GNUNET_free (binary); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("`%s' must be installed SUID, refusing to run\n"), "gnunet-helper-exit"); global_ret = 1; return; } GNUNET_free (binary); } stats = GNUNET_STATISTICS_create ("exit", cfg); if ( (ipv4_exit || ipv4_enabled) && GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("This system does not support IPv4, will disable IPv4 functions despite them being enabled in the configuration\n")); ipv4_exit = GNUNET_NO; ipv4_enabled = GNUNET_NO; } if ( (ipv6_exit || ipv6_enabled) && GNUNET_OK != GNUNET_NETWORK_test_pf (PF_INET6)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("This system does not support IPv6, will disable IPv6 functions despite them being enabled in the configuration\n")); ipv6_exit = GNUNET_NO; ipv6_enabled = GNUNET_NO; } if (ipv4_exit && (! ipv4_enabled)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot enable IPv4 exit but disable IPv4 on TUN interface, will use ENABLE_IPv4=YES\n")); ipv4_enabled = GNUNET_YES; } if (ipv6_exit && (! ipv6_enabled)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot enable IPv6 exit but disable IPv6 on TUN interface, will use ENABLE_IPv6=YES\n")); ipv6_enabled = GNUNET_YES; } if (! (ipv4_enabled || ipv6_enabled)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No useful service enabled. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } dns_exit = NULL; if ( (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg_, "exit", "EXIT_DNS")) && ( (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "DNS_RESOLVER", &dns_exit)) || ( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) && (1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) ) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "dns", "DNS_RESOLVER", _("need a valid IPv4 or IPv6 address\n")); GNUNET_free_non_null (dns_exit); dns_exit = NULL; } app_idx = 0; if (GNUNET_YES == ipv4_exit) { apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY; app_idx++; } if (GNUNET_YES == ipv6_exit) { apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY; app_idx++; } if (NULL != dns_exit) { dht = GNUNET_DHT_connect (cfg, 1); peer_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); GNUNET_CRYPTO_eddsa_key_get_public (peer_key, &dns_advertisement.peer.public_key); dns_advertisement.purpose.size = htonl (sizeof (struct GNUNET_DNS_Advertisement) - sizeof (struct GNUNET_CRYPTO_EddsaSignature)); dns_advertisement.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD); GNUNET_CRYPTO_hash ("dns", strlen ("dns"), &dht_put_key); dht_task = GNUNET_SCHEDULER_add_now (&do_dht_put, NULL); apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER; app_idx++; } GNUNET_free_non_null (dns_exit); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "MAX_CONNECTIONS", &max_connections)) max_connections = 1024; exit_argv[0] = GNUNET_strdup ("exit-gnunet"); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "TUN_IFNAME", &tun_ifname)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "TUN_IFNAME"); GNUNET_SCHEDULER_shutdown (); return; } exit_argv[1] = tun_ifname; if (ipv4_enabled) { if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_IFNAME", &exit_ifname)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "EXIT_IFNAME"); GNUNET_SCHEDULER_shutdown (); return; } exit_argv[2] = exit_ifname; } else { exit_argv[2] = GNUNET_strdup ("-"); } if (GNUNET_YES == ipv6_enabled) { if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6ADDR", &ipv6addr) || (1 != inet_pton (AF_INET6, ipv6addr, &exit_ipv6addr))) ) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV6ADDR"); GNUNET_SCHEDULER_shutdown (); return; } exit_argv[3] = ipv6addr; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV6PREFIX", &ipv6prefix_s)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV6PREFIX"); GNUNET_SCHEDULER_shutdown (); return; } exit_argv[4] = ipv6prefix_s; if ( (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "exit", "IPV6PREFIX", &ipv6prefix)) || (ipv6prefix >= 127) ) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV6PREFIX", _("Must be a number")); GNUNET_SCHEDULER_shutdown (); return; } } else { /* IPv6 explicitly disabled */ exit_argv[3] = GNUNET_strdup ("-"); exit_argv[4] = GNUNET_strdup ("-"); } if (GNUNET_YES == ipv4_enabled) { if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4ADDR", &ipv4addr) || (1 != inet_pton (AF_INET, ipv4addr, &exit_ipv4addr))) ) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV4ADDR"); GNUNET_SCHEDULER_shutdown (); return; } exit_argv[5] = ipv4addr; ipv4mask = NULL; if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "IPV4MASK", &ipv4mask) || (1 != inet_pton (AF_INET, ipv4mask, &exit_ipv4mask))) ) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "EXIT", "IPV4MASK"); GNUNET_SCHEDULER_shutdown (); GNUNET_free_non_null (ipv4mask); return; } exit_argv[6] = ipv4mask; } else { /* IPv4 explicitly disabled */ exit_argv[5] = GNUNET_strdup ("-"); exit_argv[6] = GNUNET_strdup ("-"); } exit_argv[7] = NULL; udp_services = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO); tcp_services = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO); GNUNET_CONFIGURATION_iterate_sections (cfg, &read_service_conf, NULL); connections_map = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO); connections_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); if (0 == app_idx) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No useful service enabled. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } mesh_handle = GNUNET_MESH_connect (cfg, NULL, &new_channel, &clean_channel, handlers, apptypes); if (NULL == mesh_handle) { GNUNET_SCHEDULER_shutdown (); return; } /* Mesh handle acquired, now announce regular expressions matching our exit */ if ( (GNUNET_YES == ipv4_enabled) && (GNUNET_YES == ipv4_exit) ) { policy = NULL; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_RANGE_IPV4_POLICY", &policy)) regex = NULL; else regex = GNUNET_TUN_ipv4policy2regex (policy); GNUNET_free_non_null (policy); if (NULL != regex) { (void) GNUNET_asprintf (&prefixed_regex, "%s%s%s", GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, "4", regex); regex4 = GNUNET_REGEX_announce (cfg, prefixed_regex, REGEX_REFRESH_FREQUENCY, REGEX_MAX_PATH_LEN_IPV4); GNUNET_free (regex); GNUNET_free (prefixed_regex); } } if (GNUNET_YES == ipv6_enabled && GNUNET_YES == ipv6_exit) { policy = NULL; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "exit", "EXIT_RANGE_IPV6_POLICY", &policy)) regex = NULL; else regex = GNUNET_TUN_ipv6policy2regex (policy); GNUNET_free_non_null (policy); if (NULL != regex) { (void) GNUNET_asprintf (&prefixed_regex, "%s%s%s", GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX, "6", regex); regex6 = GNUNET_REGEX_announce (cfg, prefixed_regex, REGEX_REFRESH_FREQUENCY, REGEX_MAX_PATH_LEN_IPV6); GNUNET_free (regex); GNUNET_free (prefixed_regex); } } if ((ipv4_exit) || (ipv6_exit)) helper_handle = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-exit", exit_argv, &message_token, NULL, NULL); } /** * The main function * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-exit", gettext_noop ("Daemon to run to provide an IP exit node for the VPN"), options, &run, NULL)) ? global_ret : 1; } /* end of gnunet-daemon-exit.c */ gnunet-0.10.1/src/exit/Makefile.in0000644000175000017500000006517212320752061013630 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-daemon-exit$(EXEEXT) $(am__EXEEXT_1) subdir = src/exit DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgcfg_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @LINUX_FALSE@@MINGW_TRUE@am__EXEEXT_1 = gnunet-helper-exit$(EXEEXT) @LINUX_TRUE@am__EXEEXT_1 = gnunet-helper-exit$(EXEEXT) am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" PROGRAMS = $(libexec_PROGRAMS) am_gnunet_daemon_exit_OBJECTS = gnunet-daemon-exit.$(OBJEXT) gnunet_daemon_exit_OBJECTS = $(am_gnunet_daemon_exit_OBJECTS) am__DEPENDENCIES_1 = gnunet_daemon_exit_DEPENDENCIES = \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/regex/libgnunetregex.la \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__gnunet_helper_exit_SOURCES_DIST = gnunet-helper-exit.c \ gnunet-helper-exit-windows.c @MINGW_FALSE@am_gnunet_helper_exit_OBJECTS = \ @MINGW_FALSE@ gnunet-helper-exit.$(OBJEXT) @MINGW_TRUE@am_gnunet_helper_exit_OBJECTS = \ @MINGW_TRUE@ gnunet-helper-exit-windows.$(OBJEXT) gnunet_helper_exit_OBJECTS = $(am_gnunet_helper_exit_OBJECTS) gnunet_helper_exit_DEPENDENCIES = gnunet_helper_exit_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(gnunet_helper_exit_LDFLAGS) \ $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gnunet_daemon_exit_SOURCES) $(gnunet_helper_exit_SOURCES) DIST_SOURCES = $(gnunet_daemon_exit_SOURCES) \ $(am__gnunet_helper_exit_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } DATA = $(dist_pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined,--export-all-symbols @LINUX_TRUE@EXITBIN = gnunet-helper-exit @MINGW_TRUE@EXITBIN = gnunet-helper-exit @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 pkgcfgdir = $(pkgdatadir)/config.d/ plugindir = $(libdir)/gnunet dist_pkgcfg_DATA = \ exit.conf @MINGW_TRUE@gnunet_helper_exit_LDFLAGS = \ @MINGW_TRUE@ -no-undefined -Wl,--export-all-symbols @MINGW_TRUE@gnunet_helper_exit_LDADD = \ @MINGW_TRUE@ -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \ @MINGW_TRUE@ -lcomdlg32 -lgdi32 -liphlpapi @MINGW_FALSE@gnunet_helper_exit_SOURCES = \ @MINGW_FALSE@ gnunet-helper-exit.c @MINGW_TRUE@gnunet_helper_exit_SOURCES = \ @MINGW_TRUE@ gnunet-helper-exit-windows.c gnunet_daemon_exit_SOURCES = \ gnunet-daemon-exit.c exit.h gnunet_daemon_exit_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/regex/libgnunetregex.la \ $(GN_LIBINTL) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/exit/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/exit/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-daemon-exit$(EXEEXT): $(gnunet_daemon_exit_OBJECTS) $(gnunet_daemon_exit_DEPENDENCIES) $(EXTRA_gnunet_daemon_exit_DEPENDENCIES) @rm -f gnunet-daemon-exit$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_exit_OBJECTS) $(gnunet_daemon_exit_LDADD) $(LIBS) gnunet-helper-exit$(EXEEXT): $(gnunet_helper_exit_OBJECTS) $(gnunet_helper_exit_DEPENDENCIES) $(EXTRA_gnunet_helper_exit_DEPENDENCIES) @rm -f gnunet-helper-exit$(EXEEXT) $(AM_V_CCLD)$(gnunet_helper_exit_LINK) $(gnunet_helper_exit_OBJECTS) $(gnunet_helper_exit_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-exit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-exit-windows.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-exit.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libexecPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_pkgcfgDATA uninstall-libexecPROGRAMS .MAKE: install-am install-exec-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dist_pkgcfgDATA install-dvi \ install-dvi-am install-exec install-exec-am install-exec-hook \ install-html install-html-am install-info install-info-am \ install-libexecPROGRAMS install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-dist_pkgcfgDATA \ uninstall-libexecPROGRAMS @LINUX_TRUE@install-exec-hook: @LINUX_TRUE@ $(top_srcdir)/src/exit/install-exit-helper.sh $(libexecdir) $(SUDO_BINARY) || true @LINUX_FALSE@install-exec-hook: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/exit/Makefile.am0000644000175000017500000000247612320751520013614 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined,--export-all-symbols EXITBIN = gnunet-helper-exit endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ plugindir = $(libdir)/gnunet dist_pkgcfg_DATA = \ exit.conf if LINUX EXITBIN = gnunet-helper-exit install-exec-hook: $(top_srcdir)/src/exit/install-exit-helper.sh $(libexecdir) $(SUDO_BINARY) || true else install-exec-hook: endif libexec_PROGRAMS = \ gnunet-daemon-exit \ $(EXITBIN) if MINGW gnunet_helper_exit_LDFLAGS = \ -no-undefined -Wl,--export-all-symbols gnunet_helper_exit_LDADD = \ -lsetupapi -lnewdev -lshell32 -liconv -lstdc++ \ -lcomdlg32 -lgdi32 -liphlpapi gnunet_helper_exit_SOURCES = \ gnunet-helper-exit-windows.c else gnunet_helper_exit_SOURCES = \ gnunet-helper-exit.c endif gnunet_daemon_exit_SOURCES = \ gnunet-daemon-exit.c exit.h gnunet_daemon_exit_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/regex/libgnunetregex.la \ $(GN_LIBINTL) gnunet-0.10.1/src/exit/exit.h0000644000175000017500000001740412225777503012714 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file exit/exit.h * @brief format for mesh messages exchanged between VPN service and exit daemon * @author Christian Grothoff */ #ifndef EXIT_H #define EXIT_H #include "gnunet_util_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Message send via mesh to an exit daemon to initiate forwarding of * TCP data to a local service. */ struct GNUNET_EXIT_TcpServiceStartMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START */ struct GNUNET_MessageHeader header; /** * Always 0. */ uint32_t reserved GNUNET_PACKED; /** * Identification for the desired service. */ struct GNUNET_HashCode service_descriptor; /** * Skeleton of the TCP header to send. Port numbers are to * be replaced and the checksum may be updated as necessary. */ struct GNUNET_TUN_TcpHeader tcp_header; /* followed by TCP payload */ }; /** * Message send via mesh to an exit daemon to initiate forwarding of * TCP data to the Internet. */ struct GNUNET_EXIT_TcpInternetStartMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_TCP_TO_INTERNET_START */ struct GNUNET_MessageHeader header; /** * Address family, AF_INET or AF_INET6, in network byte order. */ int32_t af GNUNET_PACKED; /** * Skeleton of the TCP header to send. Port numbers are to * be replaced and the checksum may be updated as necessary. */ struct GNUNET_TUN_TcpHeader tcp_header; /* followed by IP address of the destination; either 'struct in_addr' or 'struct in6_addr', depending on af */ /* followed by TCP payload */ }; /** * Message send via mesh between VPN and entry and an exit daemon to * transmit TCP data between the VPN entry and an exit session. This * format is used for both Internet-exits and service-exits and * in both directions (VPN to exit and exit to VPN). */ struct GNUNET_EXIT_TcpDataMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_TCP_DATA */ struct GNUNET_MessageHeader header; /** * Always 0. */ uint32_t reserved GNUNET_PACKED; /** * Skeleton of the TCP header to send. Port numbers are to * be replaced and the checksum may be updated as necessary. (The destination port number should not be changed, as it contains the desired destination port.) */ struct GNUNET_TUN_TcpHeader tcp_header; /* followed by TCP payload */ }; /** * Message send via mesh to an exit daemon to send * UDP data to a local service. */ struct GNUNET_EXIT_UdpServiceMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE */ struct GNUNET_MessageHeader header; /** * Source port to use for the UDP request (0 to use a random port). In NBO. */ uint16_t source_port GNUNET_PACKED; /** * Destination port to use for the UDP request. In NBO. */ uint16_t destination_port GNUNET_PACKED; /** * Identification for the desired service. */ struct GNUNET_HashCode service_descriptor; /* followed by UDP payload */ }; /** * Message send via mesh to an exit daemon to forward * UDP data to the Internet. */ struct GNUNET_EXIT_UdpInternetMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET */ struct GNUNET_MessageHeader header; /** * Address family, AF_INET or AF_INET6, in network byte order. */ int32_t af GNUNET_PACKED; /** * Source port to use for the UDP request (0 to use a random port). In NBO. */ uint16_t source_port GNUNET_PACKED; /** * Destination port to use for the UDP request. In NBO. */ uint16_t destination_port GNUNET_PACKED; /* followed by IP address of the destination; either 'struct in_addr' or 'struct in6_addr', depending on af */ /* followed by UDP payload */ }; /** * Message send from exit daemon back to the UDP entry point * (used for both Internet and Service exit replies). */ struct GNUNET_EXIT_UdpReplyMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_UDP_REPLY */ struct GNUNET_MessageHeader header; /** * Source port to use for the UDP reply (0 to use the same * port as for the original request). In NBO. */ uint16_t source_port GNUNET_PACKED; /** * Destination port to use for the UDP reply (0 to use the same * port as for the original request). In NBO. */ uint16_t destination_port GNUNET_PACKED; /* followed by UDP payload */ }; /** * Message send via mesh to an exit daemon to send * ICMP data to a local service. */ struct GNUNET_EXIT_IcmpServiceMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE */ struct GNUNET_MessageHeader header; /** * Address family, AF_INET or AF_INET6, in network byte order. This * AF value determines if the 'icmp_header' is ICMPv4 or ICMPv6. * The receiver (exit) may still have to translate (PT) to the services' * ICMP version (if possible). */ int32_t af GNUNET_PACKED; /** * Identification for the desired service. */ struct GNUNET_HashCode service_descriptor; /** * ICMP header to use. */ struct GNUNET_TUN_IcmpHeader icmp_header; /* followed by ICMP payload; however, for certain ICMP message types where the payload is the original IP packet, the payload is omitted as it is useless for the receiver (who will need to create some fake payload manually) */ }; /** * Message send via mesh to an exit daemon to forward * ICMP data to the Internet. */ struct GNUNET_EXIT_IcmpInternetMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET */ struct GNUNET_MessageHeader header; /** * Address family, AF_INET or AF_INET6, in network byte order. * Determines both the ICMP version used in the 'icmp_header' and * the IP address format that is used for the target IP. If * PT is necessary, the sender has already done it. */ int32_t af GNUNET_PACKED; /** * ICMP header to use. Must match the target 'af' given * above. */ struct GNUNET_TUN_IcmpHeader icmp_header; /* followed by IP address of the destination; either 'struct in_addr' or 'struct in6_addr', depending on af */ /* followed by ICMP payload; however, for certain ICMP message types where the payload is the original IP packet, the payload is omitted as it is useless for the receiver (who will need to create some fake payload manually) */ }; /** * Message send via mesh to the vpn service to send * ICMP data to the VPN's TUN interface. */ struct GNUNET_EXIT_IcmpToVPNMessage { /** * Type is GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN */ struct GNUNET_MessageHeader header; /** * Address family, AF_INET or AF_INET6, in network byte order. * Useful to determine if this is an ICMPv4 or ICMPv6 header. */ int32_t af GNUNET_PACKED; /** * ICMP header to use. ICMPv4 or ICMPv6, depending on 'af'. */ struct GNUNET_TUN_IcmpHeader icmp_header; /* followed by ICMP payload; however, for certain ICMP message types where the payload is the original IP packet, the payload is omitted as it is useless for the receiver (who will need to create some fake payload manually) */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/exit/exit.conf0000644000175000017500000000443212264756022013403 00000000000000[exit] BINARY = gnunet-daemon-exit # IPv6 address for the TUN interface (must be changed as this # must be within the global IPv6 range of your system!) IPV6ADDR = 2001:DB8::1 # Prefix for our IPv6 subnet on the TUN interface. IPV6PREFIX = 64 # IPv4 address to use on our TUN interface (may need to be # changed to avoid conflicts with existing addresses on your system). # Use RFC 3927-style link-local address IPV4ADDR = 169.254.86.1 # Netmask for the IPv4 subnet on the TUN interface. IPV4MASK = 255.255.255.0 # IPv4 networks to which we are allowed to exit. # The format is "(network[/netmask][:[!]SPORT-DPORT];)*" EXIT_RANGE_IPV4_POLICY = 0.0.0.0/0:!25; # IPv6 networks to which we are allowed to exit. # The format is "(network[/netmask][:[!]SPORT-DPORT];)*" EXIT_RANGE_IPV6_POLICY = ::/0:!25; # Name of the (virtual) tunnel interface the exit daemon will manage TUN_IFNAME = exit-gnunet # Name of the "real" interface that IPv4 traffic from this system will # leave from; this is the name of the interface where we need to # enable NAT on postrouting (typically something like 'eth0' or 'eth1' # or 'wlan0'). Not needed if EXIT_IPv4 is disabled AND if all # offered services run on 'localhost'. In this case, the value # of the option can instead be set to "%" (to not enable NAT on any # interface). EXIT_IFNAME = eth0 # Set this to YES to allow exiting this system via IPv4 to the Internet EXIT_IPV4 = NO # Set this to YES to allow exiting this system via IPv6 to the Internet EXIT_IPV6 = NO # This option should be set to YES to allow the DNS service to # perform lookups against the locally configured DNS resolver. # (set to "NO" if no normal ISP is locally available and thus # requests for normal ".com"/".org"/etc. must be routed via # the GNUnet VPN (the GNUNET PT daemon then needs to be configured # to intercept and route DNS queries via mesh). # Set this to YES to allow using this system for DNS queries. EXIT_DNS = NO # Set this to an IPv4 or IPv6 address of a DNS resolver to use for DNS queries DNS_RESOLVER = 8.8.8.8 # For IPv4-services offered by this peer, we need to at least enable IPv4 ENABLE_IPV4 = YES # For IPv6-services offered by this peer, we need to at least enable IPv6 ENABLE_IPV6 = YES # Maximum number of concurrent connections this exit supports. MAX_CONNECTIONS = 256 gnunet-0.10.1/src/exit/gnunet-helper-exit.c0000644000175000017500000004523412225777502015463 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file exit/gnunet-helper-exit.c * * @brief the helper for exit nodes. Opens a virtual * network-interface, sends data received on the if to stdout, sends * data received on stdin to the interface. The code also enables * IPv4/IPv6 forwarding and NAT on the current system (the latter on * an interface specified on the command-line); these changes to the * network configuration are NOT automatically undone when the program * is stopped (this is because we cannot be sure that some other * application didn't enable them before or after us; also, these * changes should be mostly harmless as it simply turns the system * into a router). * * @author Philipp Tölke * @author Christian Grothoff * * The following list of people have reviewed this code and considered * it safe since the last modification (if you reviewed it, please * have your name added to the list): * * - Philipp Tölke */ #include "platform.h" #include /** * Need 'struct GNUNET_MessageHeader'. */ #include "gnunet_crypto_lib.h" #include "gnunet_common.h" /** * Need VPN message types. */ #include "gnunet_protocols.h" /** * Should we print (interesting|debug) messages that can happen during * normal operation? */ #define DEBUG GNUNET_NO /** * Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE) */ #define MAX_SIZE 65536 /** * Path to 'sysctl' binary. */ static const char *sbin_sysctl; /** * Path to 'iptables' binary. */ static const char *sbin_iptables; #ifndef _LINUX_IN6_H /** * This is in linux/include/net/ipv6.h, but not always exported... */ struct in6_ifreq { struct in6_addr ifr6_addr; uint32_t ifr6_prefixlen; /* __u32 in the original */ int ifr6_ifindex; }; #endif /** * Open '/dev/null' and make the result the given * file descriptor. * * @param target_fd desired FD to point to /dev/null * @param flags open flags (O_RDONLY, O_WRONLY) */ static void open_dev_null (int target_fd, int flags) { int fd; fd = open ("/dev/null", flags); if (-1 == fd) abort (); if (fd == target_fd) return; if (-1 == dup2 (fd, target_fd)) { (void) close (fd); abort (); } (void) close (fd); } /** * Run the given command and wait for it to complete. * * @param file name of the binary to run * @param cmd command line arguments (as given to 'execv') * @return 0 on success, 1 on any error */ static int fork_and_exec (const char *file, char *const cmd[]) { int status; pid_t pid; pid_t ret; pid = fork (); if (-1 == pid) { fprintf (stderr, "fork failed: %s\n", strerror (errno)); return 1; } if (0 == pid) { /* we are the child process */ /* close stdin/stdout to not cause interference with the helper's main protocol! */ (void) close (0); open_dev_null (0, O_RDONLY); (void) close (1); open_dev_null (1, O_WRONLY); (void) execv (file, cmd); /* can only get here on error */ fprintf (stderr, "exec `%s' failed: %s\n", file, strerror (errno)); _exit (1); } /* keep running waitpid as long as the only error we get is 'EINTR' */ while ( (-1 == (ret = waitpid (pid, &status, 0))) && (errno == EINTR) ); if (-1 == ret) { fprintf (stderr, "waitpid failed: %s\n", strerror (errno)); return 1; } if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)))) return 1; /* child process completed and returned success, we're happy */ return 0; } /** * Creates a tun-interface called dev; * * @param dev is asumed to point to a char[IFNAMSIZ] * if *dev == '\\0', uses the name supplied by the kernel; * @return the fd to the tun or -1 on error */ static int init_tun (char *dev) { struct ifreq ifr; int fd; if (NULL == dev) { errno = EINVAL; return -1; } if (-1 == (fd = open ("/dev/net/tun", O_RDWR))) { fprintf (stderr, "Error opening `%s': %s\n", "/dev/net/tun", strerror (errno)); return -1; } if (fd >= FD_SETSIZE) { fprintf (stderr, "File descriptor to large: %d", fd); (void) close (fd); return -1; } memset (&ifr, 0, sizeof (ifr)); ifr.ifr_flags = IFF_TUN; if ('\0' != *dev) strncpy (ifr.ifr_name, dev, IFNAMSIZ); if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr)) { fprintf (stderr, "Error with ioctl on `%s': %s\n", "/dev/net/tun", strerror (errno)); (void) close (fd); return -1; } strcpy (dev, ifr.ifr_name); return fd; } /** * @brief Sets the IPv6-Address given in address on the interface dev * * @param dev the interface to configure * @param address the IPv6-Address * @param prefix_len the length of the network-prefix */ static void set_address6 (const char *dev, const char *address, unsigned long prefix_len) { struct ifreq ifr; struct sockaddr_in6 sa6; int fd; struct in6_ifreq ifr6; /* * parse the new address */ memset (&sa6, 0, sizeof (struct sockaddr_in6)); sa6.sin6_family = AF_INET6; if (1 != inet_pton (AF_INET6, address, &sa6.sin6_addr)) { fprintf (stderr, "Failed to parse address `%s': %s\n", address, strerror (errno)); exit (1); } if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0))) { fprintf (stderr, "Error creating socket: %s\n", strerror (errno)); exit (1); } memset (&ifr, 0, sizeof (struct ifreq)); /* * Get the index of the if */ strncpy (ifr.ifr_name, dev, IFNAMSIZ); if (-1 == ioctl (fd, SIOGIFINDEX, &ifr)) { fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } memset (&ifr6, 0, sizeof (struct in6_ifreq)); ifr6.ifr6_addr = sa6.sin6_addr; ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; /* * Set the address */ if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Get the flags */ if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Add the UP and RUNNING flags */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } if (0 != close (fd)) { fprintf (stderr, "close failed: %s\n", strerror (errno)); exit (1); } } /** * @brief Sets the IPv4-Address given in address on the interface dev * * @param dev the interface to configure * @param address the IPv4-Address * @param mask the netmask */ static void set_address4 (const char *dev, const char *address, const char *mask) { int fd; struct sockaddr_in *addr; struct ifreq ifr; memset (&ifr, 0, sizeof (struct ifreq)); addr = (struct sockaddr_in *) &(ifr.ifr_addr); addr->sin_family = AF_INET; /* * Parse the address */ if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr)) { fprintf (stderr, "Failed to parse address `%s': %s\n", address, strerror (errno)); exit (1); } if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0))) { fprintf (stderr, "Error creating socket: %s\n", strerror (errno)); exit (1); } strncpy (ifr.ifr_name, dev, IFNAMSIZ); /* * Set the address */ if (-1 == ioctl (fd, SIOCSIFADDR, &ifr)) { fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Parse the netmask */ addr = (struct sockaddr_in *) &(ifr.ifr_netmask); if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr)) { fprintf (stderr, "Failed to parse address `%s': %s\n", mask, strerror (errno)); (void) close (fd); exit (1); } /* * Set the netmask */ if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Get the flags */ if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Add the UP and RUNNING flags */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } if (0 != close (fd)) { fprintf (stderr, "close failed: %s\n", strerror (errno)); (void) close (fd); exit (1); } } /** * Start forwarding to and from the tunnel. * * @param fd_tun tunnel FD */ static void run (int fd_tun) { /* * The buffer filled by reading from fd_tun */ unsigned char buftun[MAX_SIZE]; ssize_t buftun_size = 0; unsigned char *buftun_read = NULL; /* * The buffer filled by reading from stdin */ unsigned char bufin[MAX_SIZE]; ssize_t bufin_size = 0; size_t bufin_rpos = 0; unsigned char *bufin_read = NULL; fd_set fds_w; fd_set fds_r; /* read refers to reading from fd_tun, writing to stdout */ int read_open = 1; /* write refers to reading from stdin, writing to fd_tun */ int write_open = 1; while ((1 == read_open) || (1 == write_open)) { FD_ZERO (&fds_w); FD_ZERO (&fds_r); /* * We are supposed to read and the buffer is empty * -> select on read from tun */ if (read_open && (0 == buftun_size)) FD_SET (fd_tun, &fds_r); /* * We are supposed to read and the buffer is not empty * -> select on write to stdout */ if (read_open && (0 != buftun_size)) FD_SET (1, &fds_w); /* * We are supposed to write and the buffer is empty * -> select on read from stdin */ if (write_open && (NULL == bufin_read)) FD_SET (0, &fds_r); /* * We are supposed to write and the buffer is not empty * -> select on write to tun */ if (write_open && (NULL != bufin_read)) FD_SET (fd_tun, &fds_w); int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL); if (-1 == r) { if (EINTR == errno) continue; fprintf (stderr, "select failed: %s\n", strerror (errno)); exit (1); } if (r > 0) { if (FD_ISSET (fd_tun, &fds_r)) { buftun_size = read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader), MAX_SIZE - sizeof (struct GNUNET_MessageHeader)); if (-1 == buftun_size) { fprintf (stderr, "read-error: %s\n", strerror (errno)); shutdown (fd_tun, SHUT_RD); shutdown (1, SHUT_WR); read_open = 0; buftun_size = 0; } else if (0 == buftun_size) { #if DEBUG fprintf (stderr, "EOF on tun\n"); #endif shutdown (fd_tun, SHUT_RD); shutdown (1, SHUT_WR); read_open = 0; buftun_size = 0; } else { buftun_read = buftun; struct GNUNET_MessageHeader *hdr = (struct GNUNET_MessageHeader *) buftun; buftun_size += sizeof (struct GNUNET_MessageHeader); hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); hdr->size = htons (buftun_size); } } else if (FD_ISSET (1, &fds_w)) { ssize_t written = write (1, buftun_read, buftun_size); if (-1 == written) { #if !DEBUG if (errno != EPIPE) #endif fprintf (stderr, "write-error to stdout: %s\n", strerror (errno)); shutdown (fd_tun, SHUT_RD); shutdown (1, SHUT_WR); read_open = 0; buftun_size = 0; } else if (0 == written) { fprintf (stderr, "write returned 0!?\n"); exit (1); } else { buftun_size -= written; buftun_read += written; } } if (FD_ISSET (0, &fds_r)) { bufin_size = read (0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos); if (-1 == bufin_size) { fprintf (stderr, "read-error: %s\n", strerror (errno)); shutdown (0, SHUT_RD); shutdown (fd_tun, SHUT_WR); write_open = 0; bufin_size = 0; } else if (0 == bufin_size) { #if DEBUG fprintf (stderr, "EOF on stdin\n"); #endif shutdown (0, SHUT_RD); shutdown (fd_tun, SHUT_WR); write_open = 0; bufin_size = 0; } else { struct GNUNET_MessageHeader *hdr; PROCESS_BUFFER: bufin_rpos += bufin_size; if (bufin_rpos < sizeof (struct GNUNET_MessageHeader)) continue; hdr = (struct GNUNET_MessageHeader *) bufin; if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) { fprintf (stderr, "protocol violation!\n"); exit (1); } if (ntohs (hdr->size) > bufin_rpos) continue; bufin_read = bufin + sizeof (struct GNUNET_MessageHeader); bufin_size = ntohs (hdr->size) - sizeof (struct GNUNET_MessageHeader); bufin_rpos -= bufin_size + sizeof (struct GNUNET_MessageHeader); } } else if (FD_ISSET (fd_tun, &fds_w)) { ssize_t written = write (fd_tun, bufin_read, bufin_size); if (-1 == written) { fprintf (stderr, "write-error to tun: %s\n", strerror (errno)); shutdown (0, SHUT_RD); shutdown (fd_tun, SHUT_WR); write_open = 0; bufin_size = 0; } else if (0 == written) { fprintf (stderr, "write returned 0!?\n"); exit (1); } else { bufin_size -= written; bufin_read += written; if (0 == bufin_size) { memmove (bufin, bufin_read, bufin_rpos); bufin_read = NULL; /* start reading again */ bufin_size = 0; goto PROCESS_BUFFER; } } } } } } /** * Open VPN tunnel interface. * * @param argc must be 6 * @param argv 0: binary name ("gnunet-helper-exit") * 1: tunnel interface name ("gnunet-exit") * 2: IPv4 "physical" interface name ("eth0"), or "-" to not do IPv4 NAT * 3: IPv6 address ("::1"), or "-" to skip IPv6 * 4: IPv6 netmask length in bits ("64") [ignored if #4 is "-"] * 5: IPv4 address ("1.2.3.4"), or "-" to skip IPv4 * 6: IPv4 netmask ("255.255.0.0") [ignored if #4 is "-"] */ int main (int argc, char **argv) { char dev[IFNAMSIZ]; int fd_tun; int global_ret; if (7 != argc) { fprintf (stderr, "Fatal: must supply 6 arguments!\n"); return 1; } if ( (0 == strcmp (argv[3], "-")) && (0 == strcmp (argv[5], "-")) ) { fprintf (stderr, "Fatal: disabling both IPv4 and IPv6 makes no sense.\n"); return 1; } if (0 == access ("/sbin/iptables", X_OK)) sbin_iptables = "/sbin/iptables"; else if (0 == access ("/usr/sbin/iptables", X_OK)) sbin_iptables = "/usr/sbin/iptables"; else { fprintf (stderr, "Fatal: executable iptables not found in approved directories: %s\n", strerror (errno)); return 1; } if (0 == access ("/sbin/sysctl", X_OK)) sbin_sysctl = "/sbin/sysctl"; else if (0 == access ("/usr/sbin/sysctl", X_OK)) sbin_sysctl = "/usr/sbin/sysctl"; else { fprintf (stderr, "Fatal: executable sysctl not found in approved directories: %s\n", strerror (errno)); return 1; } strncpy (dev, argv[1], IFNAMSIZ); dev[IFNAMSIZ - 1] = '\0'; if (-1 == (fd_tun = init_tun (dev))) { fprintf (stderr, "Fatal: could not initialize tun-interface `%s' with IPv6 %s/%s and IPv4 %s/%s\n", dev, argv[3], argv[4], argv[5], argv[6]); return 1; } if (0 != strcmp (argv[3], "-")) { { const char *address = argv[3]; long prefix_len = atol (argv[4]); if ((prefix_len < 1) || (prefix_len > 127)) { fprintf (stderr, "Fatal: prefix_len out of range\n"); return 1; } set_address6 (dev, address, prefix_len); } { char *const sysctl_args[] = { "sysctl", "-w", "net.ipv6.conf.all.forwarding=1", NULL }; if (0 != fork_and_exec (sbin_sysctl, sysctl_args)) { fprintf (stderr, "Failed to enable IPv6 forwarding. Will continue anyway.\n"); } } } if (0 != strcmp (argv[5], "-")) { { const char *address = argv[5]; const char *mask = argv[6]; set_address4 (dev, address, mask); } { char *const sysctl_args[] = { "sysctl", "-w", "net.ipv4.ip_forward=1", NULL }; if (0 != fork_and_exec (sbin_sysctl, sysctl_args)) { fprintf (stderr, "Failed to enable IPv4 forwarding. Will continue anyway.\n"); } } if (0 != strcmp (argv[2], "-")) { char *const iptables_args[] = { "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", argv[2], "-j", "MASQUERADE", NULL }; if (0 != fork_and_exec (sbin_iptables, iptables_args)) { fprintf (stderr, "Failed to enable IPv4 masquerading (NAT). Will continue anyway.\n"); } } } uid_t uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); global_ret = 2; goto cleanup; } #else if (0 != (setuid (uid) | seteuid (uid))) { fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); global_ret = 2; goto cleanup; } #endif if (SIG_ERR == signal (SIGPIPE, SIG_IGN)) { fprintf (stderr, "Failed to protect against SIGPIPE: %s\n", strerror (errno)); /* no exit, we might as well die with SIGPIPE should it ever happen */ } run (fd_tun); global_ret = 0; cleanup: (void) close (fd_tun); return global_ret; } /* end of gnunet-helper-exit.c */ gnunet-0.10.1/src/hello/0000755000175000017500000000000012320755622011770 500000000000000gnunet-0.10.1/src/hello/test_friend_hello.c0000644000175000017500000001424412225777502015557 00000000000000/* This file is part of GNUnet (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hello/test_hello.c * @brief test for hello.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_hello_lib.h" static size_t my_addr_gen (void *cls, size_t max, void *buf) { unsigned int *i = cls; size_t ret; struct GNUNET_HELLO_Address address; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DEBUG: my_addr_gen called with i = %d\n", *i); if (0 == *i) return 0; memset (&address.peer, 0, sizeof (struct GNUNET_PeerIdentity)); address.address = "address_information"; address.transport_name = "test"; address.address_length = *i; ret = GNUNET_HELLO_add_address (&address, GNUNET_TIME_absolute_get (), buf, max); (*i)--; return ret; } static int check_addr (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { unsigned int *i = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DEBUG: check_addr called with i = %d and addrlen = %u\n", *i, (unsigned int) address->address_length); GNUNET_assert (address->address_length > 0); GNUNET_assert (*i & (1 << (address->address_length - 1))); *i -= (1 << (address->address_length - 1)); GNUNET_assert (0 == strncmp ("address_information", address->address, address->address_length)); GNUNET_assert (0 == strcmp ("test", address->transport_name)); return GNUNET_OK; } static int remove_some (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { unsigned int *i = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DEBUG: remove_some called with i = %d and addrlen = %u\n", *i, (unsigned int) address->address_length); GNUNET_assert (address->address_length > 0); if (*i & (1 << (address->address_length - 1))) { *i -= (1 << (address->address_length - 1)); return GNUNET_NO; } return GNUNET_OK; } int main (int argc, char *argv[]) { struct GNUNET_HELLO_Message *msg1; struct GNUNET_HELLO_Message *msg2; struct GNUNET_HELLO_Message *msg3; struct GNUNET_CRYPTO_EddsaPublicKey publicKey; struct GNUNET_CRYPTO_EddsaPublicKey pk; struct GNUNET_TIME_Absolute startup_time; unsigned int i; GNUNET_log_setup ("test-hello", "DEBUG", NULL); startup_time = GNUNET_TIME_absolute_get (); memset (&publicKey, 42, sizeof (publicKey)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing HELLO creation (without addresses)...\n"); i = 0; msg1 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_YES); GNUNET_assert (msg1 != NULL); GNUNET_assert (0 < GNUNET_HELLO_size (msg1)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address iteration (empty set)...\n"); GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr, &i)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing HELLO creation (with one address)...\n"); i = 1; msg2 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_YES); GNUNET_assert (msg2 != NULL); GNUNET_assert (GNUNET_HELLO_size (msg1) < GNUNET_HELLO_size (msg2)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address iteration (one address)...\n"); i = 1; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg2, GNUNET_NO, &check_addr, &i)); GNUNET_assert (i == 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing get_key from HELLO...\n"); GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_key (msg2, &pk)); GNUNET_assert (0 == memcmp (&publicKey, &pk, sizeof (pk))); GNUNET_free (msg1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing HELLO creation (with two addresses)...\n"); i = 2; msg3 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_YES); GNUNET_assert (msg3 != NULL); GNUNET_assert (GNUNET_HELLO_size (msg2) < GNUNET_HELLO_size (msg3)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address iteration (two addresses)...\n"); i = 3; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg3, GNUNET_NO, &check_addr, &i)); GNUNET_assert (i == 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing HELLO merge...\n"); msg1 = GNUNET_HELLO_merge (msg2, msg3); GNUNET_assert (GNUNET_HELLO_size (msg1) == GNUNET_HELLO_size (msg3)); i = 3; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr, &i)); GNUNET_assert (i == 0); GNUNET_free (msg1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address iteration to copy HELLO...\n"); i = 2; msg1 = GNUNET_HELLO_iterate_addresses (msg3, GNUNET_YES, &remove_some, &i); GNUNET_assert (msg1 != NULL); GNUNET_assert (i == 0); i = 1; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr, &i)); GNUNET_assert (i == 0); GNUNET_free (msg1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing delta address iteration...\n"); i = 2; GNUNET_HELLO_iterate_new_addresses (msg3, msg2, startup_time, &check_addr, &i); GNUNET_assert (i == 0); GNUNET_free (msg2); GNUNET_free (msg3); return 0; /* testcase passed */ } gnunet-0.10.1/src/hello/Makefile.in0000644000175000017500000011463612320752062013763 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ noinst_PROGRAMS = gnunet-hello$(EXEEXT) check_PROGRAMS = test_hello$(EXEEXT) test_friend_hello$(EXEEXT) subdir = src/hello DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunethello_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunethello_la_OBJECTS = hello.lo address.lo libgnunethello_la_OBJECTS = $(am_libgnunethello_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunethello_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunethello_la_LDFLAGS) $(LDFLAGS) \ -o $@ PROGRAMS = $(noinst_PROGRAMS) am_gnunet_hello_OBJECTS = gnunet-hello.$(OBJEXT) gnunet_hello_OBJECTS = $(am_gnunet_hello_OBJECTS) am_test_friend_hello_OBJECTS = test_friend_hello.$(OBJEXT) test_friend_hello_OBJECTS = $(am_test_friend_hello_OBJECTS) test_friend_hello_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_hello_OBJECTS = test_hello.$(OBJEXT) test_hello_OBJECTS = $(am_test_hello_OBJECTS) test_hello_DEPENDENCIES = $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunethello_la_SOURCES) $(gnunet_hello_SOURCES) \ $(test_friend_hello_SOURCES) $(test_hello_SOURCES) DIST_SOURCES = $(libgnunethello_la_SOURCES) $(gnunet_hello_SOURCES) \ $(test_friend_hello_SOURCES) $(test_hello_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov lib_LTLIBRARIES = libgnunethello.la libgnunethello_la_SOURCES = \ hello.c address.c libgnunethello_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ $(LTLIBINTL) libgnunethello_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 1:0:1 @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_hello_SOURCES = \ test_hello.c test_hello_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la test_friend_hello_SOURCES = \ test_friend_hello.c test_friend_hello_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_hello_SOURCES = \ gnunet-hello.c gnunet_hello_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_hello_DEPENDENCIES = \ libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/hello/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/hello/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunethello.la: $(libgnunethello_la_OBJECTS) $(libgnunethello_la_DEPENDENCIES) $(EXTRA_libgnunethello_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunethello_la_LINK) -rpath $(libdir) $(libgnunethello_la_OBJECTS) $(libgnunethello_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-hello$(EXEEXT): $(gnunet_hello_OBJECTS) $(gnunet_hello_DEPENDENCIES) $(EXTRA_gnunet_hello_DEPENDENCIES) @rm -f gnunet-hello$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_hello_OBJECTS) $(gnunet_hello_LDADD) $(LIBS) test_friend_hello$(EXEEXT): $(test_friend_hello_OBJECTS) $(test_friend_hello_DEPENDENCIES) $(EXTRA_test_friend_hello_DEPENDENCIES) @rm -f test_friend_hello$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_friend_hello_OBJECTS) $(test_friend_hello_LDADD) $(LIBS) test_hello$(EXEEXT): $(test_hello_OBJECTS) $(test_hello_DEPENDENCIES) $(EXTRA_test_hello_DEPENDENCIES) @rm -f test_hello$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_hello_OBJECTS) $(test_hello_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-hello.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hello.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_friend_hello.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_hello.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_hello.log: test_hello$(EXEEXT) @p='test_hello$(EXEEXT)'; \ b='test_hello'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_friend_hello.log: test_friend_hello$(EXEEXT) @p='test_friend_hello$(EXEEXT)'; \ b='test_friend_hello'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/hello/hello.c0000644000175000017500000007425112274707232013172 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hello/hello.c * @brief helper library for handling HELLOs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" #include "gnunet_transport_plugin.h" GNUNET_NETWORK_STRUCT_BEGIN /** * A HELLO message is used to exchange information about * transports with other peers. This struct is always * followed by the actual network addresses which have * the format: * * 1) transport-name (0-terminated) * 2) address-length (uint16_t, network byte order; possibly * unaligned!) * 3) address expiration (`struct GNUNET_TIME_AbsoluteNBO`); possibly * unaligned!) * 4) address (address-length bytes; possibly unaligned!) */ struct GNUNET_HELLO_Message { /** * Type will be #GNUNET_MESSAGE_TYPE_HELLO. */ struct GNUNET_MessageHeader header; /** * Use in F2F mode: Do not gossip this HELLO message */ uint32_t friend_only GNUNET_PACKED; /** * The public key of the peer. */ struct GNUNET_CRYPTO_EddsaPublicKey publicKey; }; GNUNET_NETWORK_STRUCT_END /** * Context used for building our own URI. */ struct GNUNET_HELLO_ComposeUriContext { /** * Final URI. */ char *uri; /** * Function for finding transport plugins by name. */ GNUNET_HELLO_TransportPluginsFind plugins_find; }; /** * Context for 'add_address_to_hello'. */ struct GNUNET_HELLO_ParseUriContext { /** * Position in the URI with the next address to parse. */ const char *pos; /** * Set to #GNUNET_SYSERR to indicate parse errors. */ int ret; /** * Function for finding transport plugins by name. */ GNUNET_HELLO_TransportPluginsFind plugins_find; }; /** Return HELLO type * * @param h HELLO Message to test * @return #GNUNET_YES or #GNUNET_NO */ int GNUNET_HELLO_is_friend_only (const struct GNUNET_HELLO_Message *h) { if (GNUNET_YES == ntohl(h->friend_only)) return GNUNET_YES; return GNUNET_NO; } /** * Copy the given address information into * the given buffer using the format of HELLOs. * * @param address the address * @param expiration expiration for the @a address * @param target where to copy the @a address * @param max maximum number of bytes to copy to target * @return number of bytes copied, 0 if * the target buffer was not big enough. */ size_t GNUNET_HELLO_add_address (const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration, char *target, size_t max) { uint16_t alen; size_t slen; struct GNUNET_TIME_AbsoluteNBO exp; slen = strlen (address->transport_name) + 1; if (slen + sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + address->address_length > max) return 0; exp = GNUNET_TIME_absolute_hton (expiration); alen = htons ((uint16_t) address->address_length); memcpy (target, address->transport_name, slen); memcpy (&target[slen], &alen, sizeof (uint16_t)); slen += sizeof (uint16_t); memcpy (&target[slen], &exp, sizeof (struct GNUNET_TIME_AbsoluteNBO)); slen += sizeof (struct GNUNET_TIME_AbsoluteNBO); memcpy (&target[slen], address->address, address->address_length); slen += address->address_length; return slen; } /** * Get the size of an address entry in a HELLO message. * * @param buf pointer to the start of the address entry * @param max maximum size of the entry (end of buf) * @param ralen set to the address length * @return size of the entry, or 0 if max is not large enough */ static size_t get_hello_address_size (const char *buf, size_t max, uint16_t *ralen) { const char *pos; uint16_t alen; size_t left; size_t slen; left = max; pos = buf; slen = 1; while ((left > 0) && ('\0' != *pos)) { left--; pos++; slen++; } if (0 == left) { /* 0-termination not found */ GNUNET_break_op (0); return 0; } pos++; if (left < sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO)) { /* not enough space for addrlen */ GNUNET_break_op (0); return 0; } memcpy (&alen, pos, sizeof (uint16_t)); alen = ntohs (alen); *ralen = alen; slen += alen + sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO); if (max < slen) { /* not enough space for addr */ GNUNET_break_op (0); return 0; } return slen; } /** * Construct a HELLO message given the public key, * expiration time and an iterator that spews the * transport addresses. * * @return the hello message */ struct GNUNET_HELLO_Message * GNUNET_HELLO_create (const struct GNUNET_CRYPTO_EddsaPublicKey *publicKey, GNUNET_HELLO_GenerateAddressListCallback addrgen, void *addrgen_cls, int friend_only) { char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - 256 - sizeof (struct GNUNET_HELLO_Message)]; size_t max; size_t used; size_t ret; struct GNUNET_HELLO_Message *hello; GNUNET_assert (NULL != publicKey); GNUNET_assert ((GNUNET_YES == friend_only) || (GNUNET_NO == friend_only)); max = sizeof (buffer); used = 0; if (addrgen != NULL) { while (0 != (ret = addrgen (addrgen_cls, max, &buffer[used]))) { max -= ret; used += ret; } } hello = GNUNET_malloc (sizeof (struct GNUNET_HELLO_Message) + used); hello->header.type = htons (GNUNET_MESSAGE_TYPE_HELLO); hello->header.size = htons (sizeof (struct GNUNET_HELLO_Message) + used); hello->friend_only = htonl (friend_only); memcpy (&hello->publicKey, publicKey, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); memcpy (&hello[1], buffer, used); return hello; } /** * Iterate over all of the addresses in the HELLO. * * @param msg HELLO to iterate over * @param return_modified if a modified copy should be returned, * otherwise NULL will be returned * @param it iterator to call on each address * @param it_cls closure for @a it * @return modified HELLO message */ struct GNUNET_HELLO_Message * GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg, int return_modified, GNUNET_HELLO_AddressIterator it, void *it_cls) { struct GNUNET_HELLO_Address address; uint16_t msize; struct GNUNET_HELLO_Message *ret; const char *inptr; size_t insize; size_t esize; size_t wpos; char *woff; uint16_t alen; struct GNUNET_TIME_AbsoluteNBO expire; int iret; msize = GNUNET_HELLO_size (msg); if ((msize < sizeof (struct GNUNET_HELLO_Message)) || (ntohs (msg->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) return NULL; ret = NULL; if (return_modified) { ret = GNUNET_malloc (msize); memcpy (ret, msg, msize); } inptr = (const char *) &msg[1]; insize = msize - sizeof (struct GNUNET_HELLO_Message); wpos = 0; woff = (ret != NULL) ? (char *) &ret[1] : NULL; address.peer.public_key = msg->publicKey; while (insize > 0) { esize = get_hello_address_size (inptr, insize, &alen); if (0 == esize) { GNUNET_break (0); GNUNET_free_non_null (ret); return NULL; } memcpy (&expire, &inptr[esize - alen - sizeof (struct GNUNET_TIME_AbsoluteNBO)], sizeof (struct GNUNET_TIME_AbsoluteNBO)); address.address = &inptr[esize - alen]; address.address_length = alen; address.transport_name = inptr; address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE; iret = it (it_cls, &address, GNUNET_TIME_absolute_ntoh (expire)); if (iret == GNUNET_SYSERR) { if (ret != NULL) ret->header.size = ntohs (sizeof (struct GNUNET_HELLO_Message) + wpos); return ret; } if ((iret == GNUNET_OK) && (ret != NULL)) { memcpy (woff, inptr, esize); woff += esize; wpos += esize; } insize -= esize; inptr += esize; } if (ret != NULL) ret->header.size = ntohs (sizeof (struct GNUNET_HELLO_Message) + wpos); return ret; } struct ExpireContext { const struct GNUNET_HELLO_Address *address; int found; struct GNUNET_TIME_Absolute expiration; }; static int get_match_exp (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct ExpireContext *ec = cls; if (0 == GNUNET_HELLO_address_cmp (address, ec->address)) { ec->found = GNUNET_YES; ec->expiration = expiration; return GNUNET_SYSERR; /* done here */ } return GNUNET_OK; } struct MergeContext { const struct GNUNET_HELLO_Message *h1; const struct GNUNET_HELLO_Message *h2; const struct GNUNET_HELLO_Message *other; char *buf; size_t max; size_t ret; int take_equal; }; static int copy_latest (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct MergeContext *mc = cls; struct ExpireContext ec; ec.address = address; ec.found = GNUNET_NO; GNUNET_HELLO_iterate_addresses (mc->other, GNUNET_NO, &get_match_exp, &ec); if ((ec.found == GNUNET_NO) || (ec.expiration.abs_value_us < expiration.abs_value_us) || ((ec.expiration.abs_value_us == expiration.abs_value_us) && (mc->take_equal == GNUNET_YES))) { mc->ret += GNUNET_HELLO_add_address (address, expiration, &mc->buf[mc->ret], mc->max - mc->ret); } return GNUNET_OK; } static size_t merge_addr (void *cls, size_t max, void *buf) { struct MergeContext *mc = cls; if (mc->h1 == NULL) return 0; mc->ret = 0; mc->max = max; mc->buf = buf; mc->take_equal = GNUNET_NO; mc->other = mc->h2; GNUNET_HELLO_iterate_addresses (mc->h1, GNUNET_NO, ©_latest, mc); mc->take_equal = GNUNET_YES; mc->other = mc->h1; GNUNET_HELLO_iterate_addresses (mc->h2, GNUNET_NO, ©_latest, mc); mc->h1 = NULL; return mc->ret; } /** * Construct a HELLO message by merging the * addresses in two existing HELLOs (which * must be for the same peer). * * @param h1 first HELLO message * @param h2 the second HELLO message * @return the combined hello message */ struct GNUNET_HELLO_Message * GNUNET_HELLO_merge (const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2) { struct MergeContext mc = { h1, h2, NULL, NULL, 0, 0, 0 }; int friend_only; if (h1->friend_only != h2->friend_only) friend_only = GNUNET_YES; /* One of the HELLOs is friend only */ else friend_only = ntohl (h1->friend_only); /* Both HELLO's have the same type */ return GNUNET_HELLO_create (&h1->publicKey, &merge_addr, &mc, friend_only); } struct DeltaContext { struct GNUNET_TIME_Absolute expiration_limit; GNUNET_HELLO_AddressIterator it; void *it_cls; const struct GNUNET_HELLO_Message *old_hello; }; static int delta_match (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct DeltaContext *dc = cls; int ret; struct ExpireContext ec; ec.address = address; ec.found = GNUNET_NO; GNUNET_HELLO_iterate_addresses (dc->old_hello, GNUNET_NO, &get_match_exp, &ec); if ((ec.found == GNUNET_YES) && ((ec.expiration.abs_value_us > expiration.abs_value_us) || (ec.expiration.abs_value_us >= dc->expiration_limit.abs_value_us))) return GNUNET_YES; /* skip */ ret = dc->it (dc->it_cls, address, expiration); return ret; } /** * Iterate over addresses in "new_hello" that * are NOT already present in "old_hello". * * @param new_hello a HELLO message * @param old_hello a HELLO message * @param expiration_limit ignore addresses in old_hello * that expired before the given time stamp * @param it iterator to call on each address * @param it_cls closure for it */ void GNUNET_HELLO_iterate_new_addresses (const struct GNUNET_HELLO_Message *new_hello, const struct GNUNET_HELLO_Message *old_hello, struct GNUNET_TIME_Absolute expiration_limit, GNUNET_HELLO_AddressIterator it, void *it_cls) { struct DeltaContext dc; dc.expiration_limit = expiration_limit; dc.it = it; dc.it_cls = it_cls; dc.old_hello = old_hello; GNUNET_HELLO_iterate_addresses (new_hello, GNUNET_NO, &delta_match, &dc); } /** * Return the size of the given HELLO message. * @param hello to inspect * @return the size, 0 if HELLO is invalid */ uint16_t GNUNET_HELLO_size (const struct GNUNET_HELLO_Message *hello) { uint16_t ret = ntohs (hello->header.size); if ((ret < sizeof (struct GNUNET_HELLO_Message)) || (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) return 0; return ret; } /** * Get the public key from a HELLO message. * * @param hello the hello message * @param publicKey where to copy the public key information, can be NULL * @return GNUNET_SYSERR if the HELLO was malformed */ int GNUNET_HELLO_get_key (const struct GNUNET_HELLO_Message *hello, struct GNUNET_CRYPTO_EddsaPublicKey *publicKey) { uint16_t ret = ntohs (hello->header.size); if ((ret < sizeof (struct GNUNET_HELLO_Message)) || (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) return GNUNET_SYSERR; *publicKey = hello->publicKey; return GNUNET_OK; } /** * Get the peer identity from a HELLO message. * * @param hello the hello message * @param peer where to store the peer's identity * @return #GNUNET_SYSERR if the HELLO was malformed */ int GNUNET_HELLO_get_id (const struct GNUNET_HELLO_Message *hello, struct GNUNET_PeerIdentity *peer) { uint16_t ret = ntohs (hello->header.size); if ((ret < sizeof (struct GNUNET_HELLO_Message)) || (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) return GNUNET_SYSERR; peer->public_key = hello->publicKey; return GNUNET_OK; } /** * Get the header from a HELLO message, used so other code * can correctly send HELLO messages. * * @param hello the hello message * * @return header or NULL if the HELLO was malformed */ struct GNUNET_MessageHeader * GNUNET_HELLO_get_header (struct GNUNET_HELLO_Message *hello) { uint16_t ret = ntohs (hello->header.size); if ((ret < sizeof (struct GNUNET_HELLO_Message)) || (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) return NULL; return &hello->header; } struct EqualsContext { struct GNUNET_TIME_Absolute expiration_limit; struct GNUNET_TIME_Absolute result; const struct GNUNET_HELLO_Message *h2; const struct GNUNET_HELLO_Address *address; struct GNUNET_TIME_Absolute expiration; int found; }; static int find_other_matching (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct EqualsContext *ec = cls; if (expiration.abs_value_us < ec->expiration_limit.abs_value_us) return GNUNET_YES; if (0 == GNUNET_HELLO_address_cmp (address, ec->address)) { ec->found = GNUNET_YES; if (expiration.abs_value_us < ec->expiration.abs_value_us) ec->result = GNUNET_TIME_absolute_min (expiration, ec->result); return GNUNET_SYSERR; } return GNUNET_YES; } static int find_matching (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct EqualsContext *ec = cls; if (expiration.abs_value_us < ec->expiration_limit.abs_value_us) return GNUNET_YES; ec->address = address; ec->expiration = expiration; ec->found = GNUNET_NO; GNUNET_HELLO_iterate_addresses (ec->h2, GNUNET_NO, &find_other_matching, ec); if (ec->found == GNUNET_NO) { ec->result = GNUNET_TIME_UNIT_ZERO_ABS; return GNUNET_SYSERR; } return GNUNET_OK; } /** * Test if two HELLO messages contain the same addresses. * If they only differ in expiration time, the lowest * expiration time larger than 'now' where they differ * is returned. * * @param h1 first HELLO message * @param h2 the second HELLO message * @param now time to use for deciding which addresses have * expired and should not be considered at all * @return absolute time forever if the two HELLOs are * totally identical; smallest timestamp >= now if * they only differ in timestamps; * zero if the some addresses with expirations >= now * do not match at all */ struct GNUNET_TIME_Absolute GNUNET_HELLO_equals (const struct GNUNET_HELLO_Message *h1, const struct GNUNET_HELLO_Message *h2, struct GNUNET_TIME_Absolute now) { struct EqualsContext ec; if (h1->header.type != h2->header.type) return GNUNET_TIME_UNIT_ZERO_ABS; if (0 != memcmp (&h1->publicKey, &h2->publicKey, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) return GNUNET_TIME_UNIT_ZERO_ABS; ec.expiration_limit = now; ec.result = GNUNET_TIME_UNIT_FOREVER_ABS; ec.h2 = h2; GNUNET_HELLO_iterate_addresses (h1, GNUNET_NO, &find_matching, &ec); if (ec.result.abs_value_us == GNUNET_TIME_UNIT_ZERO.rel_value_us) return ec.result; ec.h2 = h1; GNUNET_HELLO_iterate_addresses (h2, GNUNET_NO, &find_matching, &ec); return ec.result; } static int find_max_expire (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct GNUNET_TIME_Absolute *max = cls; *max = GNUNET_TIME_absolute_max (*max, expiration); return GNUNET_OK; } /** * When does the last address in the given HELLO expire? * * @param msg HELLO to inspect * @return time the last address expires, 0 if there are no addresses in the HELLO */ struct GNUNET_TIME_Absolute GNUNET_HELLO_get_last_expiration (const struct GNUNET_HELLO_Message *msg) { struct GNUNET_TIME_Absolute ret; ret.abs_value_us = 0; GNUNET_HELLO_iterate_addresses (msg, GNUNET_NO, &find_max_expire, &ret); return ret; } /** * GNUnet URIs are of the general form "gnunet://MODULE/IDENTIFIER". * The specific structure of "IDENTIFIER" depends on the module and * maybe differenciated into additional subcategories if applicable. * This module only deals with hello identifiers (MODULE = "hello"). *

* * The concrete URI format is: * * "gnunet://hello/PEER[!YYYYMMDDHHMMSS!!

]...". * These URIs can be used to add a peer record to peerinfo service. * PEER is the string representation of peer's public key. * YYYYMMDDHHMMSS is the expiration date. * TYPE is a transport type. * ADDRESS is the address, its format depends upon the transport type. * The concrete transport types and corresponding address formats are: * *
  • * * !IPADDRESS * IPVDDRESS is either IPV4 .-delimited address in form of XXX.XXX.XXX.XXX:PPPPP * or IPV6 :-delimited address, but with '(' and ')' instead of '[' and ']' (RFC2396 advises against using square brackets in URIs): * (XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX):PPPPP * PPPPP is the port number. May be 0. * *
  • * * [add SMTP, HTTP and other addresses here] * *
* * The encoding for hexadecimal values is defined in the crypto_hash.c * module in the gnunetutil library and discussed there. * * Examples: * * gnunet://hello/0430205UC7D56PTQK8NV05776671CNN44FK4TL6D0GQ35OMF8MEN4RNMKA5UF6AL3DQO8B1SC5AQF50SQ2MABIRU4HC8H2HAJKJ59JL1JVRJAK308F9GASRFLMGUBB5TQ5AKR94AS5T3MDG8B9O1EMPRKB0HVCG7T6QPP4CDJ913LAEHVJ2DI1TOBB15Q1JIT5ARBOD12U4SIGRFDV3Q7T66G4TBVSJJ90UQF1BG29TGJJKLGEIMSPHHKO544D6EALQ4F2K0416311JC22GVAD48R616I7VK03K7MP7N0RS2MBV1TE9JV8CK1LSQMR7KCDRTLDA6917UGA67DHTGHERIACCGQ54TGSR48RMSGS9BA5HLMOKASFC1I6V4TT09TUGCU8GNDHQF0JF3H7LPV59UL5I38QID040G000!20120302010059!TCP!192.168.0.1:2086!TCP!64.23.8.174:0 * gnunet://hello/0430205UC7D56PTQK8NV05776671CNN44FK4TL6D0GQ35OMF8MEN4RNMKA5UF6AL3DQO8B1SC5AQF50SQ2MABIRU4HC8H2HAJKJ59JL1JVRJAK308F9GASRFLMGUBB5TQ5AKR94AS5T3MDG8B9O1EMPRKB0HVCG7T6QPP4CDJ913LAEHVJ2DI1TOBB15Q1JIT5ARBOD12U4SIGRFDV3Q7T66G4TBVSJJ90UQF1BG29TGJJKLGEIMSPHHKO544D6EALQ4F2K0416311JC22GVAD48R616I7VK03K7MP7N0RS2MBV1TE9JV8CK1LSQMR7KCDRTLDA6917UGA67DHTGHERIACCGQ54TGSR48RMSGS9BA5HLMOKASFC1I6V4TT09TUGCU8GNDHQF0JF3H7LPV59UL5I38QID040G000!20120302010059!TCP!(2001:db8:85a3:8d3:1319:8a2e:370:7348):2086 * *

*/ /* ************************* Compose HELLO URI ************************** */ /** * Replace all characters in the input 'in' according * to the mapping. The mapping says to map each character * in 'oldchars' to the corresponding character (by offset) * in 'newchars'. * * @param in input string to remap * @param oldchars characters to replace * @param newchars replacement characters, must have same length as 'oldchars' * @return copy of string with replacement applied. */ static char * map_characters (const char *in, const char *oldchars, const char *newchars) { char *ret; const char *off; size_t i; GNUNET_assert (strlen (oldchars) == strlen (newchars)); ret = GNUNET_strdup (in); i = 0; while (ret[i] != '\0') { off = strchr (oldchars, ret[i]); if (NULL != off) ret[i] = newchars[off - oldchars]; i++; } return ret; } /** * Function that is called on each address of this peer. * Expands the corresponding URI string. * * @param cls the 'GNUNET_HELLO_GetUriContext' * @param address address to add * @param expiration expiration time for the address * @return GNUNET_OK (continue iteration). */ static int add_address_to_uri (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct GNUNET_HELLO_ComposeUriContext *ctx = cls; struct GNUNET_TRANSPORT_PluginFunctions *papi; const char *addr; char *uri_addr; char *ret; char *addr_dup; char *pos; char tbuf[16] = ""; char *client_str = "_client"; struct tm *t; time_t seconds; papi = ctx->plugins_find (address->transport_name); if (papi == NULL) { /* Not an error - we might just not have the right plugin. */ return GNUNET_OK; } if (NULL == papi->address_to_string) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "URI conversion not implemented for plugin `%s'\n", address->transport_name); return GNUNET_OK; } addr = papi->address_to_string (papi->cls, address->address, address->address_length); if ( (addr == NULL) || (strlen(addr) == 0) ) return GNUNET_OK; addr_dup = GNUNET_strdup (addr); if (NULL != (pos = strstr (addr_dup, "_server"))) memcpy (pos, client_str, strlen(client_str)); /* Replace all server addresses with client addresses */ /* For URIs we use '(' and ')' instead of '[' and ']' as brackets are reserved characters in URIs */ uri_addr = map_characters (addr_dup, "[]", "()"); GNUNET_free (addr_dup); seconds = expiration.abs_value_us / 1000LL / 1000LL; t = gmtime (&seconds); GNUNET_asprintf (&ret, "%s!%s!%s!%s", ctx->uri, strftime (tbuf, sizeof (tbuf), "%Y%m%d%H%M%S", t) ? tbuf : "0", address->transport_name, uri_addr); GNUNET_free (uri_addr); GNUNET_free (ctx->uri); ctx->uri = ret; return GNUNET_OK; } /** * Compose a hello URI string from a hello message. * * @param hello Hello message * @param plugins_find Function to find transport plugins by name * @return Hello URI string */ char * GNUNET_HELLO_compose_uri (const struct GNUNET_HELLO_Message *hello, GNUNET_HELLO_TransportPluginsFind plugins_find) { struct GNUNET_HELLO_ComposeUriContext ctx; ctx.plugins_find = plugins_find; char *pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&(hello->publicKey)); GNUNET_asprintf (&(ctx.uri), "%s%s", (GNUNET_YES == GNUNET_HELLO_is_friend_only (hello)) ? GNUNET_FRIEND_HELLO_URI_PREFIX : GNUNET_HELLO_URI_PREFIX, pkey); GNUNET_free (pkey); GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &add_address_to_uri, &ctx); return ctx.uri; } /* ************************* Parse HELLO URI ********************* */ /** * We're building a HELLO. Parse the next address from the * parsing context and append it. * * @param cls the 'struct GNUNET_HELLO_AddressParsingContext' * @param max number of bytes available for HELLO construction * @param buffer where to copy the next address (in binary format) * @return number of bytes added to buffer */ static size_t add_address_to_hello (void *cls, size_t max, void *buffer) { struct GNUNET_HELLO_ParseUriContext *ctx = cls; const char *tname; const char *address; char *uri_address; char *plugin_address; const char *end; char *plugin_name; struct tm expiration_time; time_t expiration_seconds; struct GNUNET_TIME_Absolute expire; struct GNUNET_TRANSPORT_PluginFunctions *papi; void *addr; size_t addr_len; struct GNUNET_HELLO_Address haddr; size_t ret; if (NULL == ctx->pos) return 0; if ('!' != ctx->pos[0]) { ctx->ret = GNUNET_SYSERR; GNUNET_break (0); return 0; } ctx->pos++; if ('0' == ctx->pos[0] && '!' == ctx->pos[1]) { expire = GNUNET_TIME_UNIT_FOREVER_ABS; tname = ctx->pos + 1; } else { memset (&expiration_time, 0, sizeof (expiration_time)); tname = strptime (ctx->pos, "%Y%m%d%H%M%S", &expiration_time); if (NULL == tname) { ctx->ret = GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO message: missing expiration time\n")); GNUNET_break (0); return 0; } expiration_seconds = mktime (&expiration_time); if (expiration_seconds == (time_t) -1) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO message: invalid expiration time\n")); ctx->ret = GNUNET_SYSERR; GNUNET_break (0); return 0; } expire.abs_value_us = expiration_seconds * 1000LL * 1000LL; } if ('!' != tname[0]) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO message: malformed\n")); ctx->ret = GNUNET_SYSERR; GNUNET_break (0); return 0; } tname++; address = strchr (tname, (int) '!'); if (NULL == address) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO message: missing transport plugin\n")); ctx->ret = GNUNET_SYSERR; GNUNET_break (0); return 0; } address++; end = strchr (address, (int) '!'); ctx->pos = end; plugin_name = GNUNET_strndup (tname, address - (tname+1)); papi = ctx->plugins_find (plugin_name); if (NULL == papi) { /* Not an error - we might just not have the right plugin. * Skip this part, advance to the next one and recurse. * But only if this is not the end of string. */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Plugin `%s' not found\n"), plugin_name); GNUNET_free (plugin_name); GNUNET_break (0); return 0; } if (NULL == papi->string_to_address) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Plugin `%s' does not support URIs yet\n"), plugin_name); GNUNET_free (plugin_name); GNUNET_break (0); return 0; } uri_address = GNUNET_strndup (address, end - address); /* For URIs we use '(' and ')' instead of '[' and ']' as brackets are reserved characters in URIs; need to convert back to '[]' for the plugin */ plugin_address = map_characters (uri_address, "()", "[]"); GNUNET_free (uri_address); if (GNUNET_OK != papi->string_to_address (papi->cls, plugin_address, strlen (plugin_address) + 1, &addr, &addr_len)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse `%s' as an address for plugin `%s'\n"), plugin_address, plugin_name); GNUNET_free (plugin_name); GNUNET_free (plugin_address); return 0; } GNUNET_free (plugin_address); /* address.peer is unset - not used by add_address() */ haddr.address_length = addr_len; haddr.address = addr; haddr.transport_name = plugin_name; ret = GNUNET_HELLO_add_address (&haddr, expire, buffer, max); GNUNET_free (addr); GNUNET_free (plugin_name); return ret; } /** * Parse a hello URI string to a hello message. * * @param uri URI string to parse * @param pubkey Pointer to struct where public key is parsed * @param hello Pointer to struct where hello message is parsed * @param plugins_find Function to find transport plugins by name * @return GNUNET_OK on success, GNUNET_SYSERR if the URI was invalid, GNUNET_NO on other errors */ int GNUNET_HELLO_parse_uri (const char *uri, struct GNUNET_CRYPTO_EddsaPublicKey *pubkey, struct GNUNET_HELLO_Message **hello, GNUNET_HELLO_TransportPluginsFind plugins_find) { const char *pks; const char *exc; int friend_only; struct GNUNET_HELLO_ParseUriContext ctx; if (0 == strncmp (uri, GNUNET_HELLO_URI_PREFIX, strlen (GNUNET_HELLO_URI_PREFIX))) { pks = &uri[strlen (GNUNET_HELLO_URI_PREFIX)]; friend_only = GNUNET_NO; } else if (0 == strncmp (uri, GNUNET_FRIEND_HELLO_URI_PREFIX, strlen (GNUNET_FRIEND_HELLO_URI_PREFIX))) { pks = &uri[strlen (GNUNET_FRIEND_HELLO_URI_PREFIX)]; friend_only = GNUNET_YES; } else return GNUNET_SYSERR; exc = strstr (pks, "!"); if (GNUNET_OK != GNUNET_STRINGS_string_to_data (pks, (NULL == exc) ? strlen (pks) : (exc - pks), (unsigned char *) pubkey, sizeof (*pubkey))) return GNUNET_SYSERR; ctx.pos = exc; ctx.ret = GNUNET_OK; ctx.plugins_find = plugins_find; *hello = GNUNET_HELLO_create (pubkey, &add_address_to_hello, &ctx, friend_only); return ctx.ret; } /* end of hello.c */ gnunet-0.10.1/src/hello/Makefile.am0000644000175000017500000000237612320751517013753 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif lib_LTLIBRARIES = libgnunethello.la libgnunethello_la_SOURCES = \ hello.c address.c libgnunethello_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ $(LTLIBINTL) libgnunethello_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 1:0:1 noinst_PROGRAMS = \ gnunet-hello check_PROGRAMS = \ test_hello \ test_friend_hello if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_hello_SOURCES = \ test_hello.c test_hello_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la test_friend_hello_SOURCES = \ test_friend_hello.c test_friend_hello_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_hello_SOURCES = \ gnunet-hello.c gnunet_hello_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_hello_DEPENDENCIES = \ libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet-0.10.1/src/hello/gnunet-hello.c0000644000175000017500000001165312225777502014470 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hello/gnunet-hello.c * @brief change HELLO files to never expire * @author Christian Grothoff */ #include "platform.h" #include "gnunet_protocols.h" #include "gnunet_hello_lib.h" /** * Closure for 'add_to_buf'. */ struct AddContext { /** * Where to add. */ char *buf; /** * Maximum number of bytes left */ size_t max; /** * Number of bytes added so far. */ size_t ret; }; static int address_count; /** * Add the given address with infinit expiration to the buffer. * * @param cls closure * @param address address to add * @param expiration old expiration * @return GNUNET_OK keep iterating */ static int add_to_buf (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct AddContext *ac = cls; size_t ret; ret = GNUNET_HELLO_add_address (address, GNUNET_TIME_UNIT_FOREVER_ABS, ac->buf, ac->max); ac->buf += ret; ac->max -= ret; ac->ret += ret; address_count ++; return GNUNET_OK; } /** * Add addresses from the address list to the HELLO. * * @param cls the HELLO with the addresses to add * @param max maximum space available * @param buf where to add the addresses * @return number of bytes added, 0 to terminate */ static size_t add_from_hello (void *cls, size_t max, void *buf) { struct GNUNET_HELLO_Message **orig = cls; struct AddContext ac; if (NULL == *orig) return 0; /* already done */ ac.buf = buf; ac.max = max; ac.ret = 0; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (*orig, GNUNET_NO, &add_to_buf, &ac)); *orig = NULL; return ac.ret; } int main (int argc, char *argv[]) { struct GNUNET_DISK_FileHandle *fh; struct GNUNET_HELLO_Message *orig; struct GNUNET_HELLO_Message *result; struct GNUNET_CRYPTO_EddsaPublicKey pk; uint64_t fsize; address_count = 0; GNUNET_log_setup ("gnunet-hello", "INFO", NULL); if (argc != 2) { FPRINTF (stderr, "%s", _("Call with name of HELLO file to modify.\n")); return 1; } if (GNUNET_OK != GNUNET_DISK_file_size (argv[1], &fsize, GNUNET_YES, GNUNET_YES)) { FPRINTF (stderr, _("Error accessing file `%s': %s\n"), argv[1], STRERROR (errno)); return 1; } if (fsize > 65536) { FPRINTF (stderr, _("File `%s' is too big to be a HELLO\n"), argv[1]); return 1; } if (fsize < sizeof (struct GNUNET_MessageHeader)) { FPRINTF (stderr, _("File `%s' is too small to be a HELLO\n"), argv[1]); return 1; } fh = GNUNET_DISK_file_open (argv[1], GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_USER_READ); if (NULL == fh) { FPRINTF (stderr, _("Error opening file `%s': %s\n"), argv[1], STRERROR (errno)); return 1; } { char buf[fsize] GNUNET_ALIGN; GNUNET_assert (fsize == GNUNET_DISK_file_read (fh, buf, fsize)); GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); orig = (struct GNUNET_HELLO_Message *) buf; if ( (fsize != GNUNET_HELLO_size (orig)) || (GNUNET_OK != GNUNET_HELLO_get_key (orig, &pk)) ) { FPRINTF (stderr, _("Did not find well-formed HELLO in file `%s'\n"), argv[1]); return 1; } result = GNUNET_HELLO_create (&pk, &add_from_hello, &orig, GNUNET_HELLO_is_friend_only (orig)); GNUNET_assert (NULL != result); fh = GNUNET_DISK_file_open (argv[1], GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == fh) { FPRINTF (stderr, _("Error opening file `%s': %s\n"), argv[1], STRERROR (errno)); GNUNET_free (result); return 1; } fsize = GNUNET_HELLO_size (result); if (fsize != GNUNET_DISK_file_write (fh, result, fsize)) { FPRINTF (stderr, _("Error writing HELLO to file `%s': %s\n"), argv[1], STRERROR (errno)); (void) GNUNET_DISK_file_close (fh); return 1; } GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh)); } FPRINTF (stderr, _("Modified %u addresses \n"), address_count); return 0; } /* end of gnunet-hello.c */ gnunet-0.10.1/src/hello/test_hello.c0000644000175000017500000001424112225777502014225 00000000000000/* This file is part of GNUnet (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hello/test_hello.c * @brief test for hello.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_hello_lib.h" static size_t my_addr_gen (void *cls, size_t max, void *buf) { unsigned int *i = cls; size_t ret; struct GNUNET_HELLO_Address address; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DEBUG: my_addr_gen called with i = %d\n", *i); if (0 == *i) return 0; memset (&address.peer, 0, sizeof (struct GNUNET_PeerIdentity)); address.address = "address_information"; address.transport_name = "test"; address.address_length = *i; ret = GNUNET_HELLO_add_address (&address, GNUNET_TIME_absolute_get (), buf, max); (*i)--; return ret; } static int check_addr (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { unsigned int *i = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DEBUG: check_addr called with i = %d and addrlen = %u\n", *i, (unsigned int) address->address_length); GNUNET_assert (address->address_length > 0); GNUNET_assert (*i & (1 << (address->address_length - 1))); *i -= (1 << (address->address_length - 1)); GNUNET_assert (0 == strncmp ("address_information", address->address, address->address_length)); GNUNET_assert (0 == strcmp ("test", address->transport_name)); return GNUNET_OK; } static int remove_some (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { unsigned int *i = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DEBUG: remove_some called with i = %d and addrlen = %u\n", *i, (unsigned int) address->address_length); GNUNET_assert (address->address_length > 0); if (*i & (1 << (address->address_length - 1))) { *i -= (1 << (address->address_length - 1)); return GNUNET_NO; } return GNUNET_OK; } int main (int argc, char *argv[]) { struct GNUNET_HELLO_Message *msg1; struct GNUNET_HELLO_Message *msg2; struct GNUNET_HELLO_Message *msg3; struct GNUNET_CRYPTO_EddsaPublicKey publicKey; struct GNUNET_CRYPTO_EddsaPublicKey pk; struct GNUNET_TIME_Absolute startup_time; unsigned int i; GNUNET_log_setup ("test-hello", "DEBUG", NULL); startup_time = GNUNET_TIME_absolute_get (); memset (&publicKey, 42, sizeof (publicKey)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing HELLO creation (without addresses)...\n"); i = 0; msg1 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_NO); GNUNET_assert (msg1 != NULL); GNUNET_assert (0 < GNUNET_HELLO_size (msg1)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address iteration (empty set)...\n"); GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr, &i)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing HELLO creation (with one address)...\n"); i = 1; msg2 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_NO); GNUNET_assert (msg2 != NULL); GNUNET_assert (GNUNET_HELLO_size (msg1) < GNUNET_HELLO_size (msg2)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address iteration (one address)...\n"); i = 1; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg2, GNUNET_NO, &check_addr, &i)); GNUNET_assert (i == 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing get_key from HELLO...\n"); GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_key (msg2, &pk)); GNUNET_assert (0 == memcmp (&publicKey, &pk, sizeof (pk))); GNUNET_free (msg1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing HELLO creation (with two addresses)...\n"); i = 2; msg3 = GNUNET_HELLO_create (&publicKey, &my_addr_gen, &i, GNUNET_NO); GNUNET_assert (msg3 != NULL); GNUNET_assert (GNUNET_HELLO_size (msg2) < GNUNET_HELLO_size (msg3)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address iteration (two addresses)...\n"); i = 3; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg3, GNUNET_NO, &check_addr, &i)); GNUNET_assert (i == 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing HELLO merge...\n"); msg1 = GNUNET_HELLO_merge (msg2, msg3); GNUNET_assert (GNUNET_HELLO_size (msg1) == GNUNET_HELLO_size (msg3)); i = 3; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr, &i)); GNUNET_assert (i == 0); GNUNET_free (msg1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing address iteration to copy HELLO...\n"); i = 2; msg1 = GNUNET_HELLO_iterate_addresses (msg3, GNUNET_YES, &remove_some, &i); GNUNET_assert (msg1 != NULL); GNUNET_assert (i == 0); i = 1; GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (msg1, GNUNET_NO, &check_addr, &i)); GNUNET_assert (i == 0); GNUNET_free (msg1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing delta address iteration...\n"); i = 2; GNUNET_HELLO_iterate_new_addresses (msg3, msg2, startup_time, &check_addr, &i); GNUNET_assert (i == 0); GNUNET_free (msg2); GNUNET_free (msg3); return 0; /* testcase passed */ } gnunet-0.10.1/src/hello/address.c0000644000175000017500000000775612267431203013514 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file hello/address.c * @brief helper functions for handling addresses * @author Christian Grothoff */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" /** * Check if an address has a local option set * * @param address the address to check * @param option the respective option to check for * @return GNUNET_YES or GNUNET_NO */ int GNUNET_HELLO_address_check_option (const struct GNUNET_HELLO_Address * address, enum GNUNET_HELLO_AddressInfo option) { if (option == (address->local_info & option)) return GNUNET_YES; return GNUNET_NO; } /** * Get the size of an address struct. * * @param address address * @return the size */ size_t GNUNET_HELLO_address_get_size (const struct GNUNET_HELLO_Address * address) { return sizeof (struct GNUNET_HELLO_Address) + address->address_length + strlen (address->transport_name) + 1; } /** * Allocate an address struct. * * @param peer the peer * @param transport_name plugin name * @param address binary address * @param address_length number of bytes in 'address' * @param local_info additional local information for the address * @return the address struct */ struct GNUNET_HELLO_Address * GNUNET_HELLO_address_allocate (const struct GNUNET_PeerIdentity *peer, const char *transport_name, const void *address, size_t address_length, enum GNUNET_HELLO_AddressInfo local_info) { struct GNUNET_HELLO_Address *addr; size_t slen; char *end; GNUNET_assert (transport_name != NULL); slen = strlen (transport_name) + 1; addr = GNUNET_malloc (sizeof (struct GNUNET_HELLO_Address) + address_length + slen); addr->peer = *peer; addr->address = &addr[1]; end = (char *) &addr[1]; memcpy (end, address, address_length); addr->address_length = address_length; addr->transport_name = &end[address_length]; addr->local_info = local_info; memcpy (&end[address_length], transport_name, slen); return addr; } /** * Copy an address struct. * * @param address address to copy * @return a copy of the address struct */ struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy (const struct GNUNET_HELLO_Address *address) { return GNUNET_HELLO_address_allocate (&address->peer, address->transport_name, address->address, address->address_length, address->local_info); } /** * Compare two addresses. Does NOT compare the peer identity, * that is assumed already to match! * * @param a1 first address * @param a2 second address * @return 0 if the addresses are equal, -1 if a1a2. */ int GNUNET_HELLO_address_cmp (const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2) { int ret; ret = strcmp (a1->transport_name, a2->transport_name); if (0 != ret) return ret; if (a1->address_length < a2->address_length) return -1; if (a1->address_length > a2->address_length) return 1; return memcmp (a1->address, a2->address, a1->address_length); } /* end of address.c */ gnunet-0.10.1/src/arm/0000755000175000017500000000000012320755623011445 500000000000000gnunet-0.10.1/src/arm/test_arm_api_data.conf0000644000175000017500000000116412225230043015662 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunetd-arm/ [arm] PORT = 23354 DEFAULTSERVICES = BINARY = gnunet-service-arm OPTIONS = -L ERROR #PREFIX = valgrind --tool=memcheck --leak-check=yes [resolver] PORT = 23355 # PREFIX = valgrind [do-nothing] AUTOSTART = NO PORT = 2223 HOSTNAME = localhost BINARY = /will/be/overwritten/by/test_exponential_backoff ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; [fs] AUTOSTART = NO [datastore] AUTOSTART = NO [core] AUTOSTART = NO [transport] AUTOSTART = NO [peerinfo] AUTOSTART = NO [statistics] AUTOSTART = YES [dns] AUTOSTART = NO [consensus] AUTOSTART = NO [nse] AUTOSTART = NO gnunet-0.10.1/src/arm/test_gnunet_service_arm.c0000644000175000017500000001335112316473376016461 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file arm/test_gnunet_service_arm.c * @brief testcase for gnunet-service-arm.c; tests ARM by making it start the resolver * @author Safey * @author Christian Grothoff */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_resolver_service.h" #include "gnunet_os_lib.h" #include "gnunet_program_lib.h" /** * Timeout for starting services, very short because of the strange way start works * (by checking if running before starting, so really this time is always waited on * startup (annoying)). */ #define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 50) #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) static int ret = 1; static int resolved_ok = 0; static int asked_for_a_list = 0; static struct GNUNET_ARM_Handle *arm; static void trigger_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_ARM_disconnect_and_free (arm); arm = NULL; } static void arm_stop_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) { GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED); if (result != GNUNET_ARM_RESULT_STOPPED) ret = 4; GNUNET_SCHEDULER_add_now (trigger_disconnect, NULL); } static void service_list (void *cls, enum GNUNET_ARM_RequestStatus rs, unsigned int count, const char *const*list) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u services are are currently running\n", count); if (GNUNET_ARM_REQUEST_SENT_OK != rs) goto stop_arm; if (1 == count) { GNUNET_break (0 == strcasecmp (list[0], "resolver (gnunet-service-resolver)")); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got service list, now stopping arm\n"); ret = 0; } stop_arm: GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL); } static void hostNameResolveCB (void *cls, const struct sockaddr *addr, socklen_t addrlen) { if ((ret == 0) || (ret == 4) || (resolved_ok == 1)) return; if (NULL == addr) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Name not resolved!\n"); ret = 3; GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL); } else if (asked_for_a_list == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Resolved hostname, now checking the service list\n"); GNUNET_ARM_request_service_list (arm, TIMEOUT, service_list, NULL); asked_for_a_list = 1; resolved_ok = 1; } } static void arm_start_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) { GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); GNUNET_break (result == GNUNET_ARM_RESULT_STARTING); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to resolve our own hostname!\n"); /* connect to the resolver service */ if (NULL == GNUNET_RESOLVER_hostname_resolve ( AF_UNSPEC, TIMEOUT, &hostNameResolveCB, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable initiate connection to resolver service\n"); ret = 2; GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL); } } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char *armconfig; if (NULL != cfgfile) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "arm", "CONFIG", &armconfig)) { GNUNET_CONFIGURATION_set_value_string ((struct GNUNET_CONFIGURATION_Handle *) c, "arm", "CONFIG", cfgfile); } else GNUNET_free (armconfig); } arm = GNUNET_ARM_connect (c, NULL, NULL); GNUNET_ARM_request_service_start (arm, "arm", GNUNET_OS_INHERIT_STD_OUT_AND_ERR, START_TIMEOUT, arm_start_cb, NULL); } int main (int argc, char *av[]) { static char *const argv[] = { "test-gnunet-service-arm", "-c", "test_arm_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; char hostname[GNUNET_OS_get_hostname_max_length () + 1]; if (0 != gethostname (hostname, sizeof (hostname) - 1)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "gethostname"); FPRINTF (stderr, "%s", "Failed to determine my own hostname, testcase not run.\n"); return 0; } if (NULL == gethostbyname (hostname)) { FPRINTF (stderr, "Failed to resolve my hostname `%s', testcase not run.\n", hostname); return 0; } GNUNET_log_setup ("test-gnunet-service-arm", "WARNING", NULL); GNUNET_break (GNUNET_OK == GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-gnunet-service-arm", "nohelp", options, &run, NULL)); return ret; } /* end of test_gnunet_service_arm.c */ gnunet-0.10.1/src/arm/mockup-service.c0000644000175000017500000000434112237153764014474 00000000000000/* This file is part of GNUnet. (C) 2007, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" static int special_ret = 0; /** * Handler for STOP message. * * @param cls closure (refers to service) * @param client identification of the client * @param message the actual message */ static void handle_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Initiating shutdown as requested by client.\n")); GNUNET_SERVER_client_persist_ (client); GNUNET_SCHEDULER_shutdown (); /* ARM won't exponentially increase restart delay if we * terminate normally. This changes the return code. */ special_ret = 1; } static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; /* process client requests */ GNUNET_SERVER_add_handlers (server, handlers); } int main (int argc, char *const *argv) { int ret; ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "do-nothing", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; if (0 != special_ret) return special_ret; return ret; } gnunet-0.10.1/src/arm/gnunet-service-arm.c0000644000175000017500000012727012277162077015263 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file arm/gnunet-service-arm.c * @brief the automated restart manager service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_protocols.h" #include "arm.h" /** * How many messages do we queue up at most for optional * notifications to a client? (this can cause notifications * about outgoing messages to be dropped). */ #define MAX_NOTIFY_QUEUE 1024 /** * List of our services. */ struct ServiceList; /** * Record with information about a listen socket we have open. */ struct ServiceListeningInfo { /** * This is a linked list. */ struct ServiceListeningInfo *next; /** * This is a linked list. */ struct ServiceListeningInfo *prev; /** * Address this socket is listening on. */ struct sockaddr *service_addr; /** * Service this listen socket is for. */ struct ServiceList *sl; /** * Number of bytes in 'service_addr' */ socklen_t service_addr_len; /** * Our listening socket. */ struct GNUNET_NETWORK_Handle *listen_socket; /** * Task doing the accepting. */ GNUNET_SCHEDULER_TaskIdentifier accept_task; }; /** * List of our services. */ struct ServiceList { /** * This is a doubly-linked list. */ struct ServiceList *next; /** * This is a doubly-linked list. */ struct ServiceList *prev; /** * Linked list of listen sockets associated with this service. */ struct ServiceListeningInfo *listen_head; /** * Linked list of listen sockets associated with this service. */ struct ServiceListeningInfo *listen_tail; /** * Name of the service. */ char *name; /** * Name of the binary used. */ char *binary; /** * Name of the configuration file used. */ char *config; /** * Client to notify upon kill completion (waitpid), NULL * if we should simply restart the process. */ struct GNUNET_SERVER_Client *killing_client; /** * ID of the request that killed the service (for reporting back). */ uint64_t killing_client_request_id; /** * Process structure pointer of the child. */ struct GNUNET_OS_Process *proc; /** * Process exponential backoff time */ struct GNUNET_TIME_Relative backoff; /** * Absolute time at which the process is scheduled to restart in case of death */ struct GNUNET_TIME_Absolute restart_at; /** * Time we asked the service to shut down (used to calculate time it took * the service to terminate). */ struct GNUNET_TIME_Absolute killed_at; /** * Is this service to be started by default (or did a client tell us explicitly * to start it)? #GNUNET_NO if the service is started only upon 'accept' on a * listen socket or possibly explicitly by a client changing the value. */ int is_default; /** * Should we use pipes to signal this process? (YES for Java binaries and if we * are on Windoze). */ int pipe_control; }; /** * List of running services. */ static struct ServiceList *running_head; /** * List of running services. */ static struct ServiceList *running_tail; /** * Our configuration */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Command to prepend to each actual command. */ static char *prefix_command; /** * Option to append to each actual command. */ static char *final_option; /** * ID of task called whenever we get a SIGCHILD. */ static GNUNET_SCHEDULER_TaskIdentifier child_death_task; /** * ID of task called whenever the timeout for restarting a child * expires. */ static GNUNET_SCHEDULER_TaskIdentifier child_restart_task; /** * Pipe used to communicate shutdown via signal. */ static struct GNUNET_DISK_PipeHandle *sigpipe; /** * Are we in shutdown mode? */ static int in_shutdown; /** * Are we starting user services? */ static int start_user = GNUNET_YES; /** * Are we starting system services? */ static int start_system = GNUNET_YES; /** * Handle to our server instance. Our server is a bit special in that * its service is not immediately stopped once we get a shutdown * request (since we need to continue service until all of our child * processes are dead). This handle is used to shut down the server * (and thus trigger process termination) once all child processes are * also dead. A special option in the ARM configuration modifies the * behaviour of the service implementation to not do the shutdown * immediately. */ static struct GNUNET_SERVER_Handle *server; /** * Context for notifications we need to send to our clients. */ static struct GNUNET_SERVER_NotificationContext *notifier; /** * Transmit a status result message. * * @param cls a `unit16_t *` with message type * @param size number of bytes available in @a buf * @param buf where to copy the message, NULL on error * @return number of bytes copied to @a buf */ static size_t write_result (void *cls, size_t size, void *buf) { struct GNUNET_ARM_ResultMessage *msg = cls; size_t msize; if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Could not send status result to client\n")); GNUNET_free (msg); return 0; /* error, not much we can do */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending status response %u to client\n", (unsigned int) msg->result); msize = msg->arm_msg.header.size; GNUNET_assert (size >= msize); msg->arm_msg.header.size = htons (msg->arm_msg.header.size); msg->arm_msg.header.type = htons (msg->arm_msg.header.type); msg->result = htonl (msg->result); msg->arm_msg.request_id = GNUNET_htonll (msg->arm_msg.request_id); memcpy (buf, msg, msize); GNUNET_free (msg); return msize; } /** * Transmit the list of running services. * * @param cls pointer to `struct GNUNET_ARM_ListResultMessage` with the message * @param size number of bytes available in @a buf * @param buf where to copy the message, NULL on error * @return number of bytes copied to @a buf */ static size_t write_list_result (void *cls, size_t size, void *buf) { struct GNUNET_ARM_ListResultMessage *msg = cls; size_t rslt_size; if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Could not send list result to client\n")); GNUNET_free (msg); return 0; /* error, not much we can do */ } rslt_size = msg->arm_msg.header.size; GNUNET_assert (size >= rslt_size); msg->arm_msg.header.size = htons (msg->arm_msg.header.size); msg->arm_msg.header.type = htons (msg->arm_msg.header.type); msg->arm_msg.request_id = GNUNET_htonll (msg->arm_msg.request_id); msg->count = htons (msg->count); memcpy (buf, msg, rslt_size); GNUNET_free (msg); return rslt_size; } /** * Signal our client that we will start or stop the * service. * * @param client who is being signalled * @param name name of the service * @param request_id id of the request that is being responded to. * @param result message type to send * @return NULL if it was not found */ static void signal_result (struct GNUNET_SERVER_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result) { struct GNUNET_ARM_ResultMessage *msg; size_t msize; msize = sizeof (struct GNUNET_ARM_ResultMessage); msg = GNUNET_malloc (msize); msg->arm_msg.header.size = msize; msg->arm_msg.header.type = GNUNET_MESSAGE_TYPE_ARM_RESULT; msg->result = result; msg->arm_msg.request_id = request_id; GNUNET_SERVER_notify_transmit_ready (client, msize, GNUNET_TIME_UNIT_FOREVER_REL, write_result, msg); } /** * Tell all clients about status change of a service. * * @param name name of the service * @param status message type to send * @param unicast if not NULL, send to this client only. * otherwise, send to all clients in the notifier */ static void broadcast_status (const char *name, enum GNUNET_ARM_ServiceStatus status, struct GNUNET_SERVER_Client *unicast) { struct GNUNET_ARM_StatusMessage *msg; size_t namelen; if (NULL == notifier) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending status %u of service `%s' to client\n", (unsigned int) status, name); namelen = strlen (name); msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_StatusMessage) + namelen + 1); msg->header.size = htons (sizeof (struct GNUNET_ARM_StatusMessage) + namelen + 1); msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_STATUS); msg->status = htonl ((uint32_t) (status)); memcpy ((char *) &msg[1], name, namelen + 1); if (NULL == unicast) GNUNET_SERVER_notification_context_broadcast (notifier, (struct GNUNET_MessageHeader *) msg, GNUNET_YES); else GNUNET_SERVER_notification_context_unicast (notifier, unicast, (const struct GNUNET_MessageHeader *) msg, GNUNET_NO); GNUNET_free (msg); } /** * Actually start the process for the given service. * * @param sl identifies service to start * @param client that asked to start the service (may be NULL) * @param request_id id of the request in response to which the process is * being started. 0 if starting was not requested. */ static void start_process (struct ServiceList *sl, struct GNUNET_SERVER_Client *client, uint64_t request_id) { char *loprefix; char *options; char *optpos; char *optend; const char *next; int use_debug; char b; char *val; struct ServiceListeningInfo *sli; SOCKTYPE *lsocks; unsigned int ls; char *binary; char *quotedbinary; /* calculate listen socket list */ lsocks = NULL; ls = 0; for (sli = sl->listen_head; NULL != sli; sli = sli->next) { GNUNET_array_append (lsocks, ls, GNUNET_NETWORK_get_fd (sli->listen_socket)); if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (sli->accept_task); sli->accept_task = GNUNET_SCHEDULER_NO_TASK; } } #if WINDOWS GNUNET_array_append (lsocks, ls, INVALID_SOCKET); #else GNUNET_array_append (lsocks, ls, -1); #endif /* obtain configuration */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "PREFIX", &loprefix)) loprefix = GNUNET_strdup (prefix_command); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "OPTIONS", &options)) { options = GNUNET_strdup (final_option); if (NULL == strstr (options, "%")) { /* replace '{}' with service name */ while (NULL != (optpos = strstr (options, "{}"))) { optpos[0] = '%'; optpos[1] = 's'; GNUNET_asprintf (&optpos, options, sl->name); GNUNET_free (options); options = optpos; } /* replace '$PATH' with value associated with "PATH" */ while (NULL != (optpos = strstr (options, "$"))) { optend = optpos + 1; while (isupper ((unsigned char) *optend)) optend++; b = *optend; if ('\0' == b) next = ""; else next = optend + 1; *optend = '\0'; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", optpos + 1, &val)) val = GNUNET_strdup (""); *optpos = '\0'; GNUNET_asprintf (&optpos, "%s%s%c%s", options, val, b, next); GNUNET_free (options); GNUNET_free (val); options = optpos; } } } use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG"); /* actually start process */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting service `%s' using binary `%s' and configuration `%s'\n", sl->name, sl->binary, sl->config); binary = GNUNET_OS_get_libexec_binary_path (sl->binary); GNUNET_asprintf ("edbinary, "\"%s\"", binary); GNUNET_assert (NULL == sl->proc); if (GNUNET_YES == use_debug) { if (NULL == sl->config) sl->proc = GNUNET_OS_start_process_s (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, lsocks, loprefix, quotedbinary, "-L", "DEBUG", options, NULL); else sl->proc = GNUNET_OS_start_process_s (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, lsocks, loprefix, quotedbinary, "-c", sl->config, "-L", "DEBUG", options, NULL); } else { if (NULL == sl->config) sl->proc = GNUNET_OS_start_process_s (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, lsocks, loprefix, quotedbinary, options, NULL); else sl->proc = GNUNET_OS_start_process_s (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, lsocks, loprefix, quotedbinary, "-c", sl->config, options, NULL); } GNUNET_free (binary); GNUNET_free (quotedbinary); if (sl->proc == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start service `%s'\n"), sl->name); if (client) signal_result (client, sl->name, request_id, GNUNET_ARM_RESULT_START_FAILED); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"), sl->name); broadcast_status (sl->name, GNUNET_ARM_SERVICE_STARTING, NULL); if (client) signal_result (client, sl->name, request_id, GNUNET_ARM_RESULT_STARTING); } /* clean up */ GNUNET_free (loprefix); GNUNET_free (options); GNUNET_array_grow (lsocks, ls, 0); } /** * Find the process with the given service * name in the given list and return it. * * @param name which service entry to look up * @return NULL if it was not found */ static struct ServiceList * find_service (const char *name) { struct ServiceList *sl; sl = running_head; while (sl != NULL) { if (0 == strcasecmp (sl->name, name)) return sl; sl = sl->next; } return NULL; } /** * First connection has come to the listening socket associated with the service, * create the service in order to relay the incoming connection to it * * @param cls callback data, `struct ServiceListeningInfo` describing a listen socket * @param tc context */ static void accept_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceListeningInfo *sli = cls; struct ServiceList *sl = sli->sl; sli->accept_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_NO == in_shutdown); if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; start_process (sl, NULL, 0); } /** * Creating a listening socket for each of the service's addresses and * wait for the first incoming connection to it * * @param sa address associated with the service * @param addr_len length of @a sa * @param sl service entry for the service in question */ static void create_listen_socket (struct sockaddr *sa, socklen_t addr_len, struct ServiceList *sl) { static int on = 1; struct GNUNET_NETWORK_Handle *sock; struct ServiceListeningInfo *sli; #ifndef WINDOWS int match_uid; int match_gid; #endif switch (sa->sa_family) { case AF_INET: sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); break; case AF_INET6: sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); break; case AF_UNIX: if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0) /* Do not bind to blank UNIX path! */ return; sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); break; default: GNUNET_break (0); sock = NULL; errno = EAFNOSUPPORT; break; } if (NULL == sock) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to create socket for service `%s': %s\n"), sl->name, STRERROR (errno)); GNUNET_free (sa); return; } if (GNUNET_NETWORK_socket_setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); #ifdef IPV6_V6ONLY if ((sa->sa_family == AF_INET6) && (GNUNET_NETWORK_socket_setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); #endif if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Unable to bind listening socket for service `%s' to address `%s': %s\n"), sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno)); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); GNUNET_free (sa); return; } #ifndef WINDOWS if ((AF_UNIX == sa->sa_family) #ifdef LINUX /* Permission settings are not required when abstract sockets are used */ && ('\0' != ((const struct sockaddr_un *)sa)->sun_path[0]) #endif ) { match_uid = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "UNIX_MATCH_UID"); match_gid = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "UNIX_MATCH_GID"); GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sa)->sun_path, match_uid, match_gid); } #endif if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); GNUNET_free (sa); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("ARM now monitors connections to service `%s' at `%s'\n"), sl->name, GNUNET_a2s (sa, addr_len)); sli = GNUNET_new (struct ServiceListeningInfo); sli->service_addr = sa; sli->service_addr_len = addr_len; sli->listen_socket = sock; sli->sl = sl; sli->accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock, &accept_connection, sli); GNUNET_CONTAINER_DLL_insert (sl->listen_head, sl->listen_tail, sli); } /** * Remove and free an entry in the service list. Listen sockets * must have already been cleaned up. Only to be called during shutdown. * * @param sl entry to free */ static void free_service (struct ServiceList *sl) { GNUNET_assert (GNUNET_YES == in_shutdown); GNUNET_CONTAINER_DLL_remove (running_head, running_tail, sl); GNUNET_assert (NULL == sl->listen_head); GNUNET_free_non_null (sl->config); GNUNET_free_non_null (sl->binary); GNUNET_free (sl->name); GNUNET_free (sl); } /** * Handle START-message. * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static void handle_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const char *servicename; struct ServiceList *sl; uint16_t size; uint64_t request_id; struct GNUNET_ARM_Message *amsg; amsg = (struct GNUNET_ARM_Message *) message; request_id = GNUNET_ntohll (amsg->request_id); size = ntohs (amsg->header.size); size -= sizeof (struct GNUNET_ARM_Message); servicename = (const char *) &amsg[1]; if ((size == 0) || (servicename[size - 1] != '\0')) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (GNUNET_YES == in_shutdown) { signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IN_SHUTDOWN); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } sl = find_service (servicename); if (NULL == sl) { signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IS_NOT_KNOWN); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } sl->is_default = GNUNET_YES; if (NULL != sl->proc) { signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IS_STARTED_ALREADY); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } start_process (sl, client, request_id); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Start a shutdown sequence. * * @param cls closure (refers to service) * @param tc task context */ static void trigger_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n"); GNUNET_SCHEDULER_shutdown (); } /** * Handle STOP-message. * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static void handle_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct ServiceList *sl; const char *servicename; uint16_t size; uint64_t request_id; struct GNUNET_ARM_Message *amsg; amsg = (struct GNUNET_ARM_Message *) message; request_id = GNUNET_ntohll (amsg->request_id); size = ntohs (amsg->header.size); size -= sizeof (struct GNUNET_ARM_Message); servicename = (const char *) &amsg[1]; if ((size == 0) || (servicename[size - 1] != '\0')) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Preparing to stop `%s'\n"), servicename); if (0 == strcasecmp (servicename, "arm")) { broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL); signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING); GNUNET_SERVER_client_persist_ (client); GNUNET_SCHEDULER_add_now (trigger_shutdown, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } sl = find_service (servicename); if (sl == NULL) { signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IS_NOT_KNOWN); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } sl->is_default = GNUNET_NO; if (GNUNET_YES == in_shutdown) { /* shutdown in progress */ signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IN_SHUTDOWN); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (NULL != sl->killing_client) { /* killing already in progress */ signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IS_STOPPING_ALREADY); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (NULL == sl->proc) { /* process is down */ signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_IS_STOPPED_ALREADY); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending kill signal to service `%s', waiting for process to die.\n", servicename); broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL); /* no signal_start - only when it's STOPPED */ sl->killed_at = GNUNET_TIME_absolute_get (); if (0 != GNUNET_OS_process_kill (sl->proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); sl->killing_client = client; sl->killing_client_request_id = request_id; GNUNET_SERVER_client_keep (client); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle LIST-message. * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message */ static void handle_list (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_ARM_ListResultMessage *msg; struct GNUNET_ARM_Message *request; size_t string_list_size; size_t total_size; struct ServiceList *sl; uint16_t count; if (NULL == client) return; request = (struct GNUNET_ARM_Message *) message; GNUNET_break (0 == ntohl (request->reserved)); count = 0; string_list_size = 0; /* first count the running processes get their name's size */ for (sl = running_head; NULL != sl; sl = sl->next) { if (NULL != sl->proc) { string_list_size += strlen (sl->name); string_list_size += strlen (sl->binary); string_list_size += 4; count++; } } total_size = sizeof (struct GNUNET_ARM_ListResultMessage) + string_list_size; msg = GNUNET_malloc (total_size); msg->arm_msg.header.size = total_size; msg->arm_msg.header.type = GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT; msg->arm_msg.reserved = htonl (0); msg->arm_msg.request_id = GNUNET_ntohll (request->request_id); msg->count = count; char *pos = (char *)&msg[1]; for (sl = running_head; NULL != sl; sl = sl->next) { if (NULL != sl->proc) { size_t s = strlen (sl->name) + strlen (sl->binary) + 4; GNUNET_snprintf (pos, s, "%s (%s)", sl->name, sl->binary); pos += s; } } GNUNET_SERVER_notify_transmit_ready (client, total_size, GNUNET_TIME_UNIT_FOREVER_REL, &write_list_result, msg); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * We are done with everything. Stop remaining * tasks, signal handler and the server. */ static void do_shutdown () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n"); if (NULL != notifier) { GNUNET_SERVER_notification_context_destroy (notifier); notifier = NULL; } if (NULL != server) { GNUNET_SERVER_destroy (server); server = NULL; } if (GNUNET_SCHEDULER_NO_TASK != child_death_task) { GNUNET_SCHEDULER_cancel (child_death_task); child_death_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Count how many services are still active. * * @param running_head list of services * @return number of active services found */ static unsigned int list_count (struct ServiceList *running_head) { struct ServiceList *i; unsigned int res = 0; for (res = 0, i = running_head; i; i = i->next, res++) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", i->name); return res; } /** * Task run for shutdown. * * @param cls closure, NULL if we need to self-restart * @param tc context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceList *pos; struct ServiceList *nxt; struct ServiceListeningInfo *sli; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n"); if (GNUNET_SCHEDULER_NO_TASK != child_restart_task) { GNUNET_SCHEDULER_cancel (child_restart_task); child_restart_task = GNUNET_SCHEDULER_NO_TASK; } in_shutdown = GNUNET_YES; /* first, stop listening */ for (pos = running_head; NULL != pos; pos = pos->next) { while (NULL != (sli = pos->listen_head)) { GNUNET_CONTAINER_DLL_remove (pos->listen_head, pos->listen_tail, sli); if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (sli->accept_task); sli->accept_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sli->listen_socket)); GNUNET_free (sli->service_addr); GNUNET_free (sli); } } /* then, shutdown all existing service processes */ nxt = running_head; while (NULL != (pos = nxt)) { nxt = pos->next; if (pos->proc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name); pos->killed_at = GNUNET_TIME_absolute_get (); if (0 != GNUNET_OS_process_kill (pos->proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); } else { free_service (pos); } } /* finally, should all service processes be already gone, terminate for real */ if (running_head == NULL) do_shutdown (); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delaying shutdown, have %u childs still running\n", list_count (running_head)); } /** * Task run whenever it is time to restart a child that died. * * @param cls closure, always NULL * @param tc context */ static void delayed_restart_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceList *sl; struct GNUNET_TIME_Relative lowestRestartDelay; struct ServiceListeningInfo *sli; child_restart_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_assert (GNUNET_NO == in_shutdown); lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL; /* check for services that need to be restarted due to * configuration changes or because the last restart failed */ for (sl = running_head; NULL != sl; sl = sl->next) { if (NULL != sl->proc) continue; /* service is currently not running */ if (0 == GNUNET_TIME_absolute_get_remaining (sl->restart_at).rel_value_us) { /* restart is now allowed */ if (sl->is_default) { /* process should run by default, start immediately */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Restarting service `%s'.\n"), sl->name); start_process (sl, NULL, 0); } else { /* process is run on-demand, ensure it is re-started if there is demand */ for (sli = sl->listen_head; NULL != sli; sli = sli->next) if (GNUNET_SCHEDULER_NO_TASK == sli->accept_task) { /* accept was actually paused, so start it again */ sli->accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket, &accept_connection, sli); } } } else { /* update calculation for earliest time to reactivate a service */ lowestRestartDelay = GNUNET_TIME_relative_min (lowestRestartDelay, GNUNET_TIME_absolute_get_remaining (sl->restart_at)); } } if (lowestRestartDelay.rel_value_us != GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will restart process in %s\n", GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay, GNUNET_YES)); child_restart_task = GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay, GNUNET_SCHEDULER_PRIORITY_IDLE, &delayed_restart_task, NULL); } } /** * Task triggered whenever we receive a SIGCHLD (child * process died). * * @param cls closure, NULL if we need to self-restart * @param tc context */ static void maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceList *pos; struct ServiceList *next; struct ServiceListeningInfo *sli; const char *statstr; int statcode; int ret; char c[16]; enum GNUNET_OS_ProcessStatusType statusType; unsigned long statusCode; const struct GNUNET_DISK_FileHandle *pr; pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); child_death_task = GNUNET_SCHEDULER_NO_TASK; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) { /* shutdown scheduled us, ignore! */ child_death_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, pr, &maint_child_death, NULL); return; } /* consume the signal */ GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); /* check for services that died (WAITPID) */ next = running_head; while (NULL != (pos = next)) { next = pos->next; if (pos->proc == NULL) { if (GNUNET_YES == in_shutdown) free_service (pos); continue; } if ((GNUNET_SYSERR == (ret = GNUNET_OS_process_status (pos->proc, &statusType, &statusCode))) || ((ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) || (statusType == GNUNET_OS_PROCESS_RUNNING))) continue; if (statusType == GNUNET_OS_PROCESS_EXITED) { statstr = _( /* process termination method */ "exit"); statcode = statusCode; } else if (statusType == GNUNET_OS_PROCESS_SIGNALED) { statstr = _( /* process termination method */ "signal"); statcode = statusCode; } else { statstr = _( /* process termination method */ "unknown"); statcode = 0; } if (0 != pos->killed_at.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' took %s to terminate\n"), pos->name, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->killed_at), GNUNET_YES)); } GNUNET_OS_process_destroy (pos->proc); pos->proc = NULL; broadcast_status (pos->name, GNUNET_ARM_SERVICE_STOPPED, NULL); if (NULL != pos->killing_client) { signal_result (pos->killing_client, pos->name, pos->killing_client_request_id, GNUNET_ARM_RESULT_STOPPED); GNUNET_SERVER_client_drop (pos->killing_client); pos->killing_client = NULL; pos->killing_client_request_id = 0; } if (GNUNET_YES != in_shutdown) { if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0)) { /* process terminated normally, allow restart at any time */ pos->restart_at.abs_value_us = 0; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' terminated normally, will restart at any time\n"), pos->name); /* process can still be re-started on-demand, ensure it is re-started if there is demand */ for (sli = pos->listen_head; NULL != sli; sli = sli->next) { GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sli->accept_task); sli->accept_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket, &accept_connection, sli); } } else { if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' terminated with status %s/%d, will restart in %s\n"), pos->name, statstr, statcode, GNUNET_STRINGS_relative_time_to_string (pos->backoff, GNUNET_YES)); /* schedule restart */ pos->restart_at = GNUNET_TIME_relative_to_absolute (pos->backoff); pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff); if (GNUNET_SCHEDULER_NO_TASK != child_restart_task) GNUNET_SCHEDULER_cancel (child_restart_task); child_restart_task = GNUNET_SCHEDULER_add_with_priority ( GNUNET_SCHEDULER_PRIORITY_IDLE, &delayed_restart_task, NULL); } } else { free_service (pos); } } child_death_task = GNUNET_SCHEDULER_add_read_file ( GNUNET_TIME_UNIT_FOREVER_REL, pr, &maint_child_death, NULL); if ((NULL == running_head) && (GNUNET_YES == in_shutdown)) do_shutdown (); else if (GNUNET_YES == in_shutdown) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delaying shutdown after child's death, still have %u children\n", list_count (running_head)); } /** * Signal handler called for SIGCHLD. Triggers the * respective handler by writing to the trigger pipe. */ static void sighandler_child_death () { static char c; int old_errno = errno; /* back-up errno */ GNUNET_break (1 == GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_WRITE), &c, sizeof (c))); errno = old_errno; /* restore errno */ } /** * Setup our service record for the given section in the configuration file * (assuming the section is for a service). * * @param cls unused * @param section a section in the configuration file * @return #GNUNET_OK (continue) */ static void setup_service (void *cls, const char *section) { struct ServiceList *sl; char *binary; char *config; struct stat sbuf; struct sockaddr **addrs; socklen_t *addr_lens; int ret; unsigned int i; if (strcasecmp (section, "arm") == 0) return; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary)) { /* not a service section */ return; } if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value (cfg, section, "USER_SERVICE")) && (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "USER_SERVICE"))) { if (GNUNET_NO == start_user) { GNUNET_free (binary); return; /* user service, and we don't deal with those */ } } else { if (GNUNET_NO == start_system) { GNUNET_free (binary); return; /* system service, and we don't deal with those */ } } sl = find_service (section); if (NULL != sl) { /* got the same section twice!? */ GNUNET_break (0); GNUNET_free (binary); return; } config = NULL; if (( (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG", &config)) && (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", "DEFAULTCONFIG", &config)) ) || (0 != STAT (config, &sbuf))) { if (NULL != config) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, section, "CONFIG", STRERROR (errno)); GNUNET_free (config); config = NULL; } } sl = GNUNET_new (struct ServiceList); sl->name = GNUNET_strdup (section); sl->binary = binary; sl->config = config; sl->backoff = GNUNET_TIME_UNIT_MILLISECONDS; sl->restart_at = GNUNET_TIME_UNIT_FOREVER_ABS; #if WINDOWS sl->pipe_control = GNUNET_YES; #else if (GNUNET_CONFIGURATION_have_value (cfg, section, "PIPECONTROL")) sl->pipe_control = GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "PIPECONTROL"); #endif GNUNET_CONTAINER_DLL_insert (running_head, running_tail, sl); if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "AUTOSTART")) return; if (0 >= (ret = GNUNET_SERVICE_get_server_addresses (section, cfg, &addrs, &addr_lens))) return; /* this will free (or capture) addrs[i] */ for (i = 0; i < ret; i++) create_listen_socket (addrs[i], addr_lens[i], sl); GNUNET_free (addrs); GNUNET_free (addr_lens); } /** * A client connected, add it to the notification context. * * @param cls closure * @param client identification of the client */ static void handle_client_connecting (void *cls, struct GNUNET_SERVER_Client *client) { /* All clients are considered to be of the "monitor" kind * (that is, they don't affect ARM shutdown). */ if (NULL != client) GNUNET_SERVER_client_mark_monitor (client); } /** * Handle MONITOR-message. * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static void handle_monitor (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { /* Removal is handled by the server implementation, internally. */ if ((NULL != client) && (NULL != notifier)) { GNUNET_SERVER_notification_context_add (notifier, client); broadcast_status ("arm", GNUNET_ARM_SERVICE_MONITORING_STARTED, client); GNUNET_SERVER_receive_done (client, GNUNET_OK); } } /** * Process arm requests. * * @param cls closure * @param serv the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *serv, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_start, NULL, GNUNET_MESSAGE_TYPE_ARM_START, 0}, {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0}, {&handle_monitor, NULL, GNUNET_MESSAGE_TYPE_ARM_MONITOR, sizeof (struct GNUNET_MessageHeader)}, {&handle_list, NULL, GNUNET_MESSAGE_TYPE_ARM_LIST, sizeof (struct GNUNET_ARM_Message)}, {NULL, NULL, 0, 0} }; char *defaultservices; const char *pos; struct ServiceList *sl; cfg = c; server = serv; GNUNET_assert (NULL != serv); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); child_death_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), &maint_child_death, NULL); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_PREFIX", &prefix_command)) prefix_command = GNUNET_strdup (""); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_POSTFIX", &final_option)) final_option = GNUNET_strdup (""); if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "USER_ONLY")) { GNUNET_break (GNUNET_YES == start_user); start_system = GNUNET_NO; } if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "SYSTEM_ONLY")) { GNUNET_break (GNUNET_YES == start_system); start_user = GNUNET_NO; } GNUNET_CONFIGURATION_iterate_sections (cfg, &setup_service, NULL); /* start default services... */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "DEFAULTSERVICES", &defaultservices)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting default services `%s'\n"), defaultservices); if (0 < strlen (defaultservices)) { for (pos = strtok (defaultservices, " "); NULL != pos; pos = strtok (NULL, " ")) { sl = find_service (pos); if (NULL == sl) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Default service `%s' not configured correctly!\n"), pos); continue; } sl->is_default = GNUNET_YES; start_process (sl, NULL, 0); } } GNUNET_free (defaultservices); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("No default services configured, GNUnet will not really start right now.\n")); } notifier = GNUNET_SERVER_notification_context_create (server, MAX_NOTIFY_QUEUE); GNUNET_SERVER_connect_notify (server, handle_client_connecting, NULL); /* process client requests */ GNUNET_SERVER_add_handlers (server, handlers); } /** * The main function for the arm service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; struct GNUNET_SIGNAL_Context *shc_chld; sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); GNUNET_assert (sigpipe != NULL); shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "arm", GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, &run, NULL)) ? 0 : 1; GNUNET_SIGNAL_handler_uninstall (shc_chld); shc_chld = NULL; GNUNET_DISK_pipe_close (sigpipe); sigpipe = NULL; return ret; } #ifdef LINUX #include /** * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ void __attribute__ ((constructor)) GNUNET_ARM_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); malloc_trim (0); } #endif /* end of gnunet-service-arm.c */ gnunet-0.10.1/src/arm/gnunet-arm.c0000644000175000017500000005125212246052320013602 00000000000000/* This file is part of GNUnet. (C) 2009, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file arm/gnunet-arm.c * @brief arm for writing a tool * @author Christian Grothoff */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_constants.h" #include "gnunet_util_lib.h" /** * Timeout for stopping services. Long to give some services a real chance. */ #define STOP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1) /** * Timeout for stopping ARM. Extra-long since ARM needs to stop everyone else. */ #define STOP_TIMEOUT_ARM GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) /** * Timeout for starting services, very short because of the strange way start works * (by checking if running before starting, so really this time is always waited on * startup (annoying)). */ #define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * Timeout for listing all running services. */ #define LIST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) /** * Set if we are to shutdown all services (including ARM). */ static int end; /** * Set if we are to start default services (including ARM). */ static int start; /** * Set if we are to stop/start default services (including ARM). */ static int restart; /** * Set if we should delete configuration and temp directory on exit. */ static int delete; /** * Set if we should not print status messages. */ static int quiet; /** * Monitor ARM activity. */ static int monitor; /** * Set if we should print a list of currently running services. */ static int list; /** * Set to the name of a service to start. */ static char *init; /** * Set to the name of a service to kill. */ static char *term; /** * Set to the name of the config file used. */ static const char *config_file; /** * Set to the directory where runtime files are stored. */ static char *dir; /** * Final status code. */ static int ret; /** * Connection with ARM. */ static struct GNUNET_ARM_Handle *h; /** * Monitor connection with ARM. */ static struct GNUNET_ARM_MonitorHandle *m; /** * Our configuration. */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Processing stage that we are in. Simple counter. */ static unsigned int phase; /** * User defined timestamp for completing operations. */ static struct GNUNET_TIME_Relative timeout; /** * Do we want to give our stdout to gnunet-service-arm? */ static unsigned int no_stdout; /** * Do we want to give our stderr to gnunet-service-arm? */ static unsigned int no_stderr; /** * Attempts to delete configuration file and GNUNET_HOME * on ARM shutdown provided the end and delete options * were specified when gnunet-arm was run. */ static void delete_files () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will attempt to remove configuration file %s and service directory %s\n", config_file, dir); if (0 != UNLINK (config_file)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to remove configuration file %s\n"), config_file); } if (GNUNET_OK != GNUNET_DISK_directory_remove (dir)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to remove servicehome directory %s\n"), dir); } } /** * Main continuation-passing-style loop. Runs the various * jobs that we've been asked to do in order. * * @param cls closure, unused * @param tc context, unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != h) { GNUNET_ARM_disconnect_and_free (h); h = NULL; } if (NULL != m) { GNUNET_ARM_monitor_disconnect_and_free (m); m = NULL; } if ((GNUNET_YES == end) && (GNUNET_YES == delete)) delete_files (); GNUNET_CONFIGURATION_destroy (cfg); cfg = NULL; } /** * Returns a string interpretation of 'rs' * * @param rs the request status from ARM * @return a string interpretation of the request status */ static const char * req_string (enum GNUNET_ARM_RequestStatus rs) { switch (rs) { case GNUNET_ARM_REQUEST_SENT_OK: return _("Message was sent successfully"); case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR: return _("Misconfiguration (can not connect to the ARM service)"); case GNUNET_ARM_REQUEST_DISCONNECTED: return _("We disconnected from ARM before we could send a request"); case GNUNET_ARM_REQUEST_BUSY: return _("ARM API is busy"); case GNUNET_ARM_REQUEST_TOO_LONG: return _("Request does not fit into a message"); case GNUNET_ARM_REQUEST_TIMEOUT: return _("Request timed out"); } return _("Unknown request status"); } /** * Returns a string interpretation of the 'result' * * @param result the arm result * @return a string interpretation */ static const char * ret_string (enum GNUNET_ARM_Result result) { switch (result) { case GNUNET_ARM_RESULT_STOPPED: return _("%s is stopped"); case GNUNET_ARM_RESULT_STARTING: return _("%s is starting"); case GNUNET_ARM_RESULT_STOPPING: return _("%s is stopping"); case GNUNET_ARM_RESULT_IS_STARTING_ALREADY: return _("%s is starting already"); case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY: return _("%s is stopping already"); case GNUNET_ARM_RESULT_IS_STARTED_ALREADY: return _("%s is started already"); case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY: return _("%s is stopped already"); case GNUNET_ARM_RESULT_IS_NOT_KNOWN: return _("%s service is not known to ARM"); case GNUNET_ARM_RESULT_START_FAILED: return _("%s service failed to start"); case GNUNET_ARM_RESULT_IN_SHUTDOWN: return _("%s service cannot be started because ARM is shutting down"); } return _("%.s Unknown result code."); } /** * Main task that runs our various operations in order. * * @param cls closure * @param tc scheudler context */ static void action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Function called whenever we connect to or disconnect from ARM. * Termiantes the process if we fail to connect to the service on * our first attempt. * * @param cls closure * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected, * GNUNET_SYSERR on error. */ static void conn_status (void *cls, int connected) { static int once; if ( (GNUNET_SYSERR == connected) && (0 == once) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fatal error initializing ARM API.\n")); GNUNET_SCHEDULER_shutdown (); return; } once = 1; } /** * We have requested ARM to be started, this function * is called with the result of the operation. Informs the * use of the result; on success, we continue with the event * loop, on failure we terminate the process. * * @param cls closure unused * @param rs what happened to our request * @param service name of the service we tried to start ("arm") * @param result if the request was processed, this is the result * according to ARM */ static void start_callback (void *cls, enum GNUNET_ARM_RequestStatus rs, const char *service, enum GNUNET_ARM_Result result) { char *msg; if (GNUNET_ARM_REQUEST_SENT_OK != rs) { GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n")); FPRINTF (stdout, msg, req_string (rs)); GNUNET_free (msg); GNUNET_SCHEDULER_shutdown (); return; } if ( (GNUNET_ARM_RESULT_STARTING != result) && (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result) ) { GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n")); FPRINTF (stdout, msg, ret_string (result)); GNUNET_free (msg); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM service [re]start successful\n"); start = 0; GNUNET_SCHEDULER_add_now (action_loop, NULL); } /** * We have requested ARM to be stopped, this function * is called with the result of the operation. Informs the * use of the result; on success, we continue with the event * loop, on failure we terminate the process. * * @param cls closure unused * @param rs what happened to our request * @param service name of the service we tried to start ("arm") * @param result if the request was processed, this is the result * according to ARM */ static void stop_callback (void *cls, enum GNUNET_ARM_RequestStatus rs, const char *service, enum GNUNET_ARM_Result result) { char *msg; if (GNUNET_ARM_REQUEST_SENT_OK != rs) { GNUNET_asprintf (&msg, "%s", _("Failed to send a stop request to the ARM service: %s\n")); FPRINTF (stdout, msg, req_string (rs)); GNUNET_free (msg); GNUNET_SCHEDULER_shutdown (); return; } if ((GNUNET_ARM_RESULT_STOPPING != result) && (GNUNET_ARM_RESULT_STOPPED != result) && (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY != result)) { GNUNET_asprintf (&msg, "%s", _("Failed to stop the ARM service: %s\n")); FPRINTF (stdout, msg, ret_string (result)); GNUNET_free (msg); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM service shutdown successful\n"); end = 0; if (restart) { restart = 0; start = 1; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initiating an ARM restart\n"); } GNUNET_SCHEDULER_add_now (&action_loop, NULL); } /** * We have requested a service to be started, this function * is called with the result of the operation. Informs the * use of the result; on success, we continue with the event * loop, on failure we terminate the process. * * @param cls closure unused * @param rs what happened to our request * @param service name of the service we tried to start * @param result if the request was processed, this is the result * according to ARM */ static void init_callback (void *cls, enum GNUNET_ARM_RequestStatus rs, const char *service, enum GNUNET_ARM_Result result) { char *msg; if (GNUNET_ARM_REQUEST_SENT_OK != rs) { GNUNET_asprintf (&msg, _("Failed to send a request to start the `%s' service: %%s\n"), init); FPRINTF (stdout, msg, req_string (rs)); GNUNET_free (msg); GNUNET_SCHEDULER_shutdown (); return; } if ((GNUNET_ARM_RESULT_STARTING != result) && (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result)) { GNUNET_asprintf (&msg, _("Failed to start the `%s' service: %s\n"), init, ret_string (result)); FPRINTF (stdout, msg, service); GNUNET_free (msg); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service %s [re]started successfully\n", init); GNUNET_free (init); init = NULL; GNUNET_SCHEDULER_add_now (&action_loop, NULL); } /** * We have requested a service to be stopped, this function * is called with the result of the operation. Informs the * use of the result; on success, we continue with the event * loop, on failure we terminate the process. * * @param cls closure unused * @param rs what happened to our request * @param service name of the service we tried to start * @param result if the request was processed, this is the result * according to ARM */ static void term_callback (void *cls, enum GNUNET_ARM_RequestStatus rs, const char *service, enum GNUNET_ARM_Result result) { char *msg; if (GNUNET_ARM_REQUEST_SENT_OK != rs) { GNUNET_asprintf (&msg, _("Failed to send a request to kill the `%s' service: %%s\n"), term); FPRINTF (stdout, msg, req_string (rs)); GNUNET_free (msg); GNUNET_SCHEDULER_shutdown (); return; } if ((GNUNET_ARM_RESULT_STOPPED != result) && (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY != result)) { GNUNET_asprintf (&msg, _("Failed to kill the `%s' service: %s\n"), term, ret_string (result)); FPRINTF (stdout, msg, service); GNUNET_free (msg); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service %s stopped successfully\n", term); GNUNET_free (term); term = NULL; GNUNET_SCHEDULER_add_now (&action_loop, NULL); } /** * Function called with the list of running services. Prints * the list to stdout, then starts the event loop again. * Prints an error message and terminates the process on errors. * * @param cls closure (unused) * @param rs request status (success, failure, etc.) * @param count number of services in the list * @param list list of services that are running */ static void list_callback (void *cls, enum GNUNET_ARM_RequestStatus rs, unsigned int count, const char *const*list) { unsigned int i; if (GNUNET_ARM_REQUEST_SENT_OK != rs) { char *msg; GNUNET_asprintf (&msg, "%s", _("Failed to request a list of services: %s\n")); FPRINTF (stdout, msg, req_string (rs)); GNUNET_free (msg); ret = 3; GNUNET_SCHEDULER_shutdown (); } if (NULL == list) { FPRINTF (stderr, "%s", _("Error communicating with ARM. ARM not running?\n")); GNUNET_SCHEDULER_shutdown (); ret = 3; return; } FPRINTF (stdout, "%s", _("Running services:\n")); for (i = 0; i < count; i++) FPRINTF (stdout, "%s\n", list[i]); GNUNET_SCHEDULER_add_now (&action_loop, NULL); } /** * Main action loop. Runs the various jobs that we've been asked to * do, in order. * * @param cls closure, unused * @param tc context, unused */ static void action_loop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running requested actions\n"); while (1) { switch (phase++) { case 0: if (NULL != term) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Termination action\n"); GNUNET_ARM_request_service_stop (h, term, (0 == timeout.rel_value_us) ? STOP_TIMEOUT : timeout, &term_callback, NULL); return; } break; case 1: if (end || restart) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "End action\n"); GNUNET_ARM_request_service_stop (h, "arm", (0 == timeout.rel_value_us) ? STOP_TIMEOUT_ARM : timeout, &stop_callback, NULL); return; } break; case 2: if (start) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start action\n"); GNUNET_ARM_request_service_start (h, "arm", (no_stdout ? 0 : GNUNET_OS_INHERIT_STD_OUT) | (no_stderr ? 0 : GNUNET_OS_INHERIT_STD_ERR), (0 == timeout.rel_value_us) ? START_TIMEOUT: timeout, start_callback, NULL); return; } break; case 3: if (NULL != init) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initialization action\n"); GNUNET_ARM_request_service_start (h, init, GNUNET_OS_INHERIT_STD_NONE, (0 == timeout.rel_value_us) ? STOP_TIMEOUT : timeout, &init_callback, NULL); return; } break; case 4: if (list) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Going to list all running services controlled by ARM.\n"); GNUNET_ARM_request_service_list (h, (0 == timeout.rel_value_us) ? LIST_TIMEOUT : timeout, &list_callback, &list); return; } break; case 5: if (monitor) { if (! quiet) fprintf (stderr, _("Now only monitoring, press CTRL-C to stop.\n")); quiet = 0; /* does not make sense to stay quiet in monitor mode at this time */ return; /* done with tasks, just monitor */ } break; default: /* last phase */ GNUNET_SCHEDULER_shutdown (); return; } } } /** * Function called when a service starts or stops. * * @param cls closure * @param service service name * @param status status of the service */ static void srv_status (void *cls, const char *service, enum GNUNET_ARM_ServiceStatus status) { const char *msg; switch (status) { case GNUNET_ARM_SERVICE_MONITORING_STARTED: return; /* this should be done silently */ case GNUNET_ARM_SERVICE_STOPPED: msg = _("Stopped %s.\n"); break; case GNUNET_ARM_SERVICE_STARTING: msg = _("Starting %s...\n"); break; case GNUNET_ARM_SERVICE_STOPPING: msg = _("Stopping %s...\n"); break; default: msg = NULL; break; } if (! quiet) { if (NULL != msg) FPRINTF (stderr, msg, service); else FPRINTF (stderr, _("Unknown status %u for service %s.\n"), status, service); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got service %s status %d\n", service, (int) status); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char *armconfig; cfg = GNUNET_CONFIGURATION_dup (c); config_file = cfgfile; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "GNUNET_HOME", &dir)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "PATHS", "GNUNET_HOME"); return; } if (NULL != cfgfile) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "arm", "CONFIG", &armconfig)) { GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG", cfgfile); } else GNUNET_free (armconfig); } if (NULL == (h = GNUNET_ARM_connect (cfg, &conn_status, NULL))) return; if (monitor) m = GNUNET_ARM_monitor (cfg, &srv_status, NULL); GNUNET_SCHEDULER_add_now (&action_loop, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function to obtain arm from gnunetd. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'e', "end", NULL, gettext_noop ("stop all GNUnet services"), GNUNET_NO, &GNUNET_GETOPT_set_one, &end}, {'i', "init", "SERVICE", gettext_noop ("start a particular service"), GNUNET_YES, &GNUNET_GETOPT_set_string, &init}, {'k', "kill", "SERVICE", gettext_noop ("stop a particular service"), GNUNET_YES, &GNUNET_GETOPT_set_string, &term}, {'s', "start", NULL, gettext_noop ("start all GNUnet default services"), GNUNET_NO, &GNUNET_GETOPT_set_one, &start}, {'r', "restart", NULL, gettext_noop ("stop and start all GNUnet default services"), GNUNET_NO, &GNUNET_GETOPT_set_one, &restart}, {'d', "delete", NULL, gettext_noop ("delete config file and directory on exit"), GNUNET_NO, &GNUNET_GETOPT_set_one, &delete}, {'m', "monitor", NULL, gettext_noop ("monitor ARM activities"), GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor}, {'q', "quiet", NULL, gettext_noop ("don't print status messages"), GNUNET_NO, &GNUNET_GETOPT_set_one, &quiet}, {'T', "timeout", "MSECS", gettext_noop ("timeout in MSECS milliseconds for completing current operation"), GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &timeout}, {'I', "info", NULL, gettext_noop ("list currently running services"), GNUNET_NO, &GNUNET_GETOPT_set_one, &list}, {'O', "no-stdout", NULL, gettext_noop ("don't let gnunet-service-arm inherit standard output"), GNUNET_NO, &GNUNET_GETOPT_set_one, &no_stdout}, {'E', "no-stderr", NULL, gettext_noop ("don't let gnunet-service-arm inherit standard error"), GNUNET_NO, &GNUNET_GETOPT_set_one, &no_stderr}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; if (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-arm", gettext_noop ("Control services and the Automated Restart Manager (ARM)"), options, &run, NULL)) { GNUNET_free ((void *) argv); return ret; } GNUNET_free ((void*) argv); return 1; } /* end of gnunet-arm.c */ gnunet-0.10.1/src/arm/Makefile.in0000644000175000017500000013702212320752057013435 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-arm$(EXEEXT) noinst_PROGRAMS = mockup-service$(EXEEXT) libexec_PROGRAMS = gnunet-service-arm$(EXEEXT) check_PROGRAMS = test_arm_api$(EXEEXT) \ test_exponential_backoff$(EXEEXT) \ test_gnunet_service_arm$(EXEEXT) subdir = src/arm DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/arm.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = arm.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetarm_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetarm_la_OBJECTS = arm_api.lo arm_monitor_api.lo libgnunetarm_la_OBJECTS = $(am_libgnunetarm_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetarm_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetarm_la_LDFLAGS) $(LDFLAGS) \ -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_arm_OBJECTS = gnunet-arm.$(OBJEXT) gnunet_arm_OBJECTS = $(am_gnunet_arm_OBJECTS) am_gnunet_service_arm_OBJECTS = gnunet-service-arm.$(OBJEXT) gnunet_service_arm_OBJECTS = $(am_gnunet_service_arm_OBJECTS) am_mockup_service_OBJECTS = mockup-service.$(OBJEXT) mockup_service_OBJECTS = $(am_mockup_service_OBJECTS) mockup_service_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_arm_api_OBJECTS = test_arm_api.$(OBJEXT) test_arm_api_OBJECTS = $(am_test_arm_api_OBJECTS) test_arm_api_DEPENDENCIES = $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_exponential_backoff_OBJECTS = \ test_exponential_backoff.$(OBJEXT) test_exponential_backoff_OBJECTS = \ $(am_test_exponential_backoff_OBJECTS) test_exponential_backoff_DEPENDENCIES = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_service_arm_OBJECTS = \ test_gnunet_service_arm.$(OBJEXT) test_gnunet_service_arm_OBJECTS = \ $(am_test_gnunet_service_arm_OBJECTS) test_gnunet_service_arm_DEPENDENCIES = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetarm_la_SOURCES) $(gnunet_arm_SOURCES) \ $(gnunet_service_arm_SOURCES) $(mockup_service_SOURCES) \ $(test_arm_api_SOURCES) $(test_exponential_backoff_SOURCES) \ $(test_gnunet_service_arm_SOURCES) DIST_SOURCES = $(libgnunetarm_la_SOURCES) $(gnunet_arm_SOURCES) \ $(gnunet_service_arm_SOURCES) $(mockup_service_SOURCES) \ $(test_arm_api_SOURCES) $(test_exponential_backoff_SOURCES) \ $(test_gnunet_service_arm_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ arm.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov lib_LTLIBRARIES = libgnunetarm.la libgnunetarm_la_SOURCES = \ arm_api.c arm_monitor_api.c arm.h libgnunetarm_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetarm_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:3:0 gnunet_arm_SOURCES = \ gnunet-arm.c gnunet_arm_LDADD = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_arm_DEPENDENCIES = \ libgnunetarm.la gnunet_service_arm_SOURCES = \ gnunet-service-arm.c gnunet_service_arm_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_arm_DEPENDENCIES = \ libgnunetarm.la mockup_service_SOURCES = \ mockup-service.c mockup_service_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la @HAVE_PYTHON_TRUE@check_SCRIPTS = \ @HAVE_PYTHON_TRUE@ test_gnunet_arm.py @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) $(check_SCRIPTS) test_arm_api_SOURCES = \ test_arm_api.c test_arm_api_LDADD = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la test_exponential_backoff_SOURCES = \ test_exponential_backoff.c test_exponential_backoff_LDADD = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_service_arm_SOURCES = \ test_gnunet_service_arm.c test_gnunet_service_arm_LDADD = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' EXTRA_DIST = \ test_arm_api_data.conf \ test_gnunet_arm.py.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/arm/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/arm/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): arm.conf: $(top_builddir)/config.status $(srcdir)/arm.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetarm.la: $(libgnunetarm_la_OBJECTS) $(libgnunetarm_la_DEPENDENCIES) $(EXTRA_libgnunetarm_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetarm_la_LINK) -rpath $(libdir) $(libgnunetarm_la_OBJECTS) $(libgnunetarm_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-arm$(EXEEXT): $(gnunet_arm_OBJECTS) $(gnunet_arm_DEPENDENCIES) $(EXTRA_gnunet_arm_DEPENDENCIES) @rm -f gnunet-arm$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_arm_OBJECTS) $(gnunet_arm_LDADD) $(LIBS) gnunet-service-arm$(EXEEXT): $(gnunet_service_arm_OBJECTS) $(gnunet_service_arm_DEPENDENCIES) $(EXTRA_gnunet_service_arm_DEPENDENCIES) @rm -f gnunet-service-arm$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_arm_OBJECTS) $(gnunet_service_arm_LDADD) $(LIBS) mockup-service$(EXEEXT): $(mockup_service_OBJECTS) $(mockup_service_DEPENDENCIES) $(EXTRA_mockup_service_DEPENDENCIES) @rm -f mockup-service$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mockup_service_OBJECTS) $(mockup_service_LDADD) $(LIBS) test_arm_api$(EXEEXT): $(test_arm_api_OBJECTS) $(test_arm_api_DEPENDENCIES) $(EXTRA_test_arm_api_DEPENDENCIES) @rm -f test_arm_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_arm_api_OBJECTS) $(test_arm_api_LDADD) $(LIBS) test_exponential_backoff$(EXEEXT): $(test_exponential_backoff_OBJECTS) $(test_exponential_backoff_DEPENDENCIES) $(EXTRA_test_exponential_backoff_DEPENDENCIES) @rm -f test_exponential_backoff$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_exponential_backoff_OBJECTS) $(test_exponential_backoff_LDADD) $(LIBS) test_gnunet_service_arm$(EXEEXT): $(test_gnunet_service_arm_OBJECTS) $(test_gnunet_service_arm_DEPENDENCIES) $(EXTRA_test_gnunet_service_arm_DEPENDENCIES) @rm -f test_gnunet_service_arm$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_service_arm_OBJECTS) $(test_gnunet_service_arm_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm_monitor_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-arm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-arm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mockup-service.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_arm_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_exponential_backoff.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_service_arm.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_arm_api.log: test_arm_api$(EXEEXT) @p='test_arm_api$(EXEEXT)'; \ b='test_arm_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_exponential_backoff.log: test_exponential_backoff$(EXEEXT) @p='test_exponential_backoff$(EXEEXT)'; \ b='test_exponential_backoff'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_service_arm.log: test_gnunet_service_arm$(EXEEXT) @p='test_gnunet_service_arm$(EXEEXT)'; \ b='test_gnunet_service_arm'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_arm.py.log: test_gnunet_arm.py @p='test_gnunet_arm.py'; \ b='test_gnunet_arm.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA %.py: %.py.in Makefile $(do_subst) < $(srcdir)/$< > $@ chmod +x $@ test_gnunet_arm.py: test_gnunet_arm.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_arm.py.in > test_gnunet_arm.py chmod +x test_gnunet_arm.py # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/arm/arm_monitor_api.c0000644000175000017500000002401712255010512014700 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file arm/arm_monitor_api.c * @brief API for monitoring the ARM service * @author Christian Grothoff, LRN */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "arm.h" #define INIT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) #define LOG(kind,...) GNUNET_log_from (kind, "arm-monitor-api",__VA_ARGS__) /** * Handle for interacting with ARM. */ struct GNUNET_ARM_MonitorHandle { /** * Our control connection to the ARM service. */ struct GNUNET_CLIENT_Connection *monitor; /** * The configuration that we are using. */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for our current transmission request. */ struct GNUNET_CLIENT_TransmitHandle *cth; /** * ID of the reconnect task (if any). */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Current delay we use for re-trying to connect to core. */ struct GNUNET_TIME_Relative retry_backoff; /** * Are we currently disconnected and hence unable to send? */ unsigned char currently_down; /** * Callback to invoke on status updates. */ GNUNET_ARM_ServiceStatusCallback service_status; /** * Closure for service_status. */ void *cls; /** * ID of a task to run if we fail to get a reply to the init message in time. */ GNUNET_SCHEDULER_TaskIdentifier init_timeout_task_id; }; static void monitor_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg); static int reconnect_arm_monitor (struct GNUNET_ARM_MonitorHandle *h); /** * Task scheduled to try to re-connect to arm. * * @param cls the 'struct GNUNET_ARM_MonitorHandle' * @param tc task context */ static void reconnect_arm_monitor_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_ARM_MonitorHandle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to ARM service for monitoring after delay\n"); reconnect_arm_monitor (h); } /** * Close down any existing connection to the ARM service and * try re-establishing it later. * * @param h our handle */ static void reconnect_arm_monitor_later (struct GNUNET_ARM_MonitorHandle *h) { if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (NULL != h->monitor) { GNUNET_CLIENT_disconnect (h->monitor); h->monitor = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->init_timeout_task_id) { GNUNET_SCHEDULER_cancel (h->init_timeout_task_id); h->init_timeout_task_id = GNUNET_SCHEDULER_NO_TASK; } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_arm_monitor_task, h); h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); } /** * Init message timed out. Disconnect and try again. * * @param cls arm monitor handle * @param tc task context */ static void init_timeout_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_ARM_MonitorHandle *h = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Init message timed out\n"); h->init_timeout_task_id = GNUNET_SCHEDULER_NO_TASK; reconnect_arm_monitor_later (h); } /** * Transmit the monitoring initialization message to the arm service. * * @param cls closure with the 'struct GNUNET_ARM_MonitorHandle' * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_monitoring_init_message (void *cls, size_t size, void *buf) { struct GNUNET_ARM_MonitorHandle *h = cls; struct GNUNET_MessageHeader *msg; uint16_t msize; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->init_timeout_task_id); h->cth = NULL; if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed, initiating reconnect\n"); reconnect_arm_monitor_later (h); return 0; } msize = sizeof (struct GNUNET_MessageHeader); if (size < msize) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Request is too big (%u < %u), not sending it\n", size, msize); h->cth = GNUNET_CLIENT_notify_transmit_ready (h->monitor, msize, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, transmit_monitoring_init_message, h); return 0; } msg = buf; msg->size = htons (msize); msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_MONITOR); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting ARM monitoring init message with %u bytes to arm.\n", (unsigned int) msize); h->init_timeout_task_id = GNUNET_SCHEDULER_add_delayed ( INIT_TIMEOUT, init_timeout_task, h); GNUNET_CLIENT_receive (h->monitor, &monitor_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); return msize; } static int reconnect_arm_monitor (struct GNUNET_ARM_MonitorHandle *h) { GNUNET_assert (NULL == h->monitor); h->monitor = GNUNET_CLIENT_connect ("arm", h->cfg); if (NULL == h->monitor) { LOG (GNUNET_ERROR_TYPE_DEBUG, "arm_api, GNUNET_CLIENT_connect returned NULL\n"); if (NULL != h->service_status) h->service_status (h->cls, NULL, GNUNET_ARM_SERVICE_STOPPED); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "arm_api, GNUNET_CLIENT_connect returned non-NULL\n"); h->cth = GNUNET_CLIENT_notify_transmit_ready (h->monitor, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_monitoring_init_message, h); return GNUNET_OK; } /** * Setup a context for monitoring ARM, then * start connecting to the ARM service for monitoring using that context. * * @param cfg configuration to use (needed to contact ARM; * the ARM service may internally use a different * configuration to determine how to start the service). * @param cont callback to invoke on status updates * @param cont_cls closure * @return context to use for further ARM monitor operations, NULL on error. */ struct GNUNET_ARM_MonitorHandle * GNUNET_ARM_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ARM_ServiceStatusCallback cont, void *cont_cls) { struct GNUNET_ARM_MonitorHandle *h; h = GNUNET_new (struct GNUNET_ARM_MonitorHandle); h->cfg = GNUNET_CONFIGURATION_dup (cfg); h->currently_down = GNUNET_YES; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; h->init_timeout_task_id = GNUNET_SCHEDULER_NO_TASK; h->service_status = cont; h->cls = cont_cls; if (GNUNET_OK != reconnect_arm_monitor (h)) { GNUNET_free (h); return NULL; } return h; } /** * Disconnect from the ARM service (if connected) and destroy the context. * * @param h the handle that was being used */ void GNUNET_ARM_monitor_disconnect_and_free (struct GNUNET_ARM_MonitorHandle *h) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from ARM service\n"); if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->init_timeout_task_id) { GNUNET_SCHEDULER_cancel (h->init_timeout_task_id); h->init_timeout_task_id = GNUNET_SCHEDULER_NO_TASK; } if (NULL != h->monitor) { GNUNET_CLIENT_disconnect (h->monitor); h->monitor = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONFIGURATION_destroy (h->cfg); GNUNET_free (h); } /** * Handler for notification messages received from ARM. * * @param cls our "struct GNUNET_ARM_MonitorHandle" * @param msg the message received from the arm service */ static void monitor_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_ARM_MonitorHandle *h = cls; uint16_t msize; const struct GNUNET_ARM_StatusMessage *res; enum GNUNET_ARM_ServiceStatus status; if (NULL == msg) { LOG (GNUNET_ERROR_TYPE_INFO, _("Monitoring client was disconnected from arm service, trying to reconnect.\n")); reconnect_arm_monitor_later (h); return; } msize = ntohs (msg->size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing message of type %u and size %u from arm service\n", ntohs (msg->type), msize); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_ARM_STATUS: if (msize <= sizeof (struct GNUNET_ARM_StatusMessage)) { GNUNET_break (0); reconnect_arm_monitor_later (h); return; } if (GNUNET_SCHEDULER_NO_TASK != h->init_timeout_task_id) { GNUNET_SCHEDULER_cancel (h->init_timeout_task_id); h->init_timeout_task_id = GNUNET_SCHEDULER_NO_TASK; } res = (const struct GNUNET_ARM_StatusMessage *) msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received response from ARM for service `%s': %u\n", (const char *) &res[1], ntohs (msg->type)); status = (enum GNUNET_ARM_ServiceStatus) ntohl (res->status); GNUNET_CLIENT_receive (h->monitor, &monitor_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); if (NULL != h->service_status) h->service_status (h->cls, (const char *) &res[1], status); break; default: reconnect_arm_monitor_later (h); return; } } /* end of arm_api.c */ gnunet-0.10.1/src/arm/Makefile.am0000644000175000017500000000460412320751517013423 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ arm.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif lib_LTLIBRARIES = libgnunetarm.la libgnunetarm_la_SOURCES = \ arm_api.c arm_monitor_api.c arm.h libgnunetarm_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetarm_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:3:0 bin_PROGRAMS = \ gnunet-arm noinst_PROGRAMS = \ mockup-service libexec_PROGRAMS = \ gnunet-service-arm gnunet_arm_SOURCES = \ gnunet-arm.c gnunet_arm_LDADD = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_arm_DEPENDENCIES = \ libgnunetarm.la gnunet_service_arm_SOURCES = \ gnunet-service-arm.c gnunet_service_arm_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_arm_DEPENDENCIES = \ libgnunetarm.la mockup_service_SOURCES = \ mockup-service.c mockup_service_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la check_PROGRAMS = \ test_arm_api \ test_exponential_backoff \ test_gnunet_service_arm if HAVE_PYTHON check_SCRIPTS = \ test_gnunet_arm.py endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) $(check_SCRIPTS) endif test_arm_api_SOURCES = \ test_arm_api.c test_arm_api_LDADD = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la test_exponential_backoff_SOURCES = \ test_exponential_backoff.c test_exponential_backoff_LDADD = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_service_arm_SOURCES = \ test_gnunet_service_arm.c test_gnunet_service_arm_LDADD = \ $(top_builddir)/src/arm/libgnunetarm.la \ $(top_builddir)/src/util/libgnunetutil.la do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' %.py: %.py.in Makefile $(do_subst) < $(srcdir)/$< > $@ chmod +x $@ test_gnunet_arm.py: test_gnunet_arm.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_arm.py.in > test_gnunet_arm.py chmod +x test_gnunet_arm.py EXTRA_DIST = \ test_arm_api_data.conf \ test_gnunet_arm.py.in gnunet-0.10.1/src/arm/arm_api.c0000644000175000017500000007722012261236532013146 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file arm/arm_api.c * @brief API for accessing the ARM service * @author Christian Grothoff * @author LRN */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_protocols.h" #include "arm.h" #define LOG(kind,...) GNUNET_log_from (kind, "arm-api",__VA_ARGS__) /** * Handle for interacting with ARM. */ struct GNUNET_ARM_Handle { /** * Our control connection to the ARM service. */ struct GNUNET_CLIENT_Connection *client; /** * The configuration that we are using. */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for our current transmission request. */ struct GNUNET_CLIENT_TransmitHandle *cth; /** * Head of doubly-linked list of pending requests. */ struct ARMControlMessage *control_pending_head; /** * Tail of doubly-linked list of pending requests. */ struct ARMControlMessage *control_pending_tail; /** * Head of doubly-linked list of sent requests. */ struct ARMControlMessage *control_sent_head; /** * Tail of doubly-linked list of sent requests. */ struct ARMControlMessage *control_sent_tail; /** * Callback to invoke on connection/disconnection. */ GNUNET_ARM_ConnectionStatusCallback conn_status; /** * Closure for conn_status. */ void *conn_status_cls; /** * ARM control message for the 'arm_termination_handler' * with the continuation to call once the ARM shutdown is done. */ struct ARMControlMessage *thm; /** * ID of the reconnect task (if any). */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Current delay we use for re-trying to connect to core. */ struct GNUNET_TIME_Relative retry_backoff; /** * Counter for request identifiers */ uint64_t request_id_counter; /** * Are we currently disconnected and hence unable to send? */ unsigned char currently_down; /** * GNUNET_YES if we're running a service test. */ unsigned char service_test_is_active; }; /** * Entry in a doubly-linked list of control messages to be transmitted * to the arm service. * * The actual message is allocated at the end of this struct. */ struct ARMControlMessage { /** * This is a doubly-linked list. */ struct ARMControlMessage *next; /** * This is a doubly-linked list. */ struct ARMControlMessage *prev; /** * ARM handle. */ struct GNUNET_ARM_Handle *h; /** * Message to send. */ struct GNUNET_ARM_Message *msg; /** * Callback for service state change requests. */ GNUNET_ARM_ResultCallback result_cont; /** * Callback for service list requests. */ GNUNET_ARM_ServiceListCallback list_cont; /** * Closure for 'result_cont' or 'list_cont'. */ void *cont_cls; /** * Timeout for the operation. */ struct GNUNET_TIME_Absolute timeout; /** * Task to run when request times out. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task_id; /** * Flags for passing std descriptors to ARM (when starting ARM). */ enum GNUNET_OS_InheritStdioFlags std_inheritance; /** * Type of the request expressed as a message type (start, stop or list). */ uint16_t type; }; /** * Connect to arm. * * @param h arm handle * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ static int reconnect_arm (struct GNUNET_ARM_Handle *h); /** * Check the list of pending requests, send the next * one to the arm. * * @param h arm handle * @param ignore_currently_down transmit message even if not initialized? */ static void trigger_next_request (struct GNUNET_ARM_Handle *h, int ignore_currently_down); /** * Task scheduled to try to re-connect to arm. * * @param cls the 'struct GNUNET_ARM_Handle' * @param tc task context */ static void reconnect_arm_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_ARM_Handle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to ARM service after delay\n"); reconnect_arm (h); } /** * Close down any existing connection to the ARM service and * try re-establishing it later. * * @param h our handle */ static void reconnect_arm_later (struct GNUNET_ARM_Handle *h) { if (GNUNET_NO != h->currently_down) return; if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->currently_down = GNUNET_YES; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_arm_task, h); /* Don't clear pending messages on disconnection, deliver them later clear_pending_messages (h, GNUNET_ARM_REQUEST_DISCONNECTED); GNUNET_assert (NULL == h->control_pending_head); */ h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); if (NULL != h->conn_status) h->conn_status (h->conn_status_cls, GNUNET_NO); } /** * Find a control message by its unique ID. * * @param h ARM handle * @param id unique message ID to use for the lookup * @return NULL if not found */ static struct ARMControlMessage * find_cm_by_id (struct GNUNET_ARM_Handle *h, uint64_t id) { struct ARMControlMessage *result; for (result = h->control_sent_head; result; result = result->next) if (id == result->msg->request_id) return result; return NULL; } /** * Handler for ARM 'termination' reply (failure to receive). * * @param cls our "struct GNUNET_ARM_Handle" * @param msg expected to be NULL */ static void arm_termination_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_ARM_Handle *h = cls; struct ARMControlMessage *cm; if (NULL != msg) { GNUNET_break (0); GNUNET_CLIENT_receive (h->client, &arm_termination_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); return; } cm = h->thm; h->thm = NULL; h->currently_down = GNUNET_YES; GNUNET_CLIENT_disconnect (h->client); h->client = NULL; if (NULL != cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, (const char *) &cm->msg[1], GNUNET_ARM_RESULT_STOPPED); GNUNET_free (cm->msg); GNUNET_free (cm); } /** * Handler for ARM replies. * * @param cls our `struct GNUNET_ARM_Handle` * @param msg the message received from the arm service */ static void client_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_ARM_Handle *h = cls; const struct GNUNET_ARM_Message *arm_msg; const struct GNUNET_ARM_ResultMessage *res; const struct GNUNET_ARM_ListResultMessage *lres; struct ARMControlMessage *cm; const char **list; const char *pos; uint64_t id; enum GNUNET_ARM_Result result; uint16_t size_check; uint16_t rcount; uint16_t msize; unsigned char fail; list = NULL; rcount = 0; if (NULL == msg) { LOG (GNUNET_ERROR_TYPE_INFO, _("Client was disconnected from arm service, trying to reconnect.\n")); reconnect_arm_later (h); return; } msize = ntohs (msg->size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing message of type %u and size %u from arm service\n", ntohs (msg->type), msize); if (msize < sizeof (struct GNUNET_ARM_Message)) { GNUNET_break (0); reconnect_arm_later (h); return; } arm_msg = (const struct GNUNET_ARM_Message *) msg; GNUNET_break (0 == ntohl (arm_msg->reserved)); id = GNUNET_ntohll (arm_msg->request_id); cm = find_cm_by_id (h, id); if (NULL == cm) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Message with unknown id %llu\n", id); return; } fail = GNUNET_NO; switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_ARM_RESULT: if (msize < sizeof (struct GNUNET_ARM_ResultMessage)) { GNUNET_assert (0); fail = GNUNET_YES; } break; case GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT: if (msize < sizeof (struct GNUNET_ARM_ListResultMessage)) { GNUNET_break (0); fail = GNUNET_YES; break; } size_check = 0; lres = (const struct GNUNET_ARM_ListResultMessage *) msg; rcount = ntohs (lres->count); { unsigned int i; list = GNUNET_malloc (sizeof (const char *) * rcount); pos = (const char *)&lres[1]; for (i = 0; i < rcount; i++) { const char *end = memchr (pos, 0, msize - size_check); if (NULL == end) { GNUNET_break (0); fail = GNUNET_YES; break; } list[i] = pos; size_check += (end - pos) + 1; pos = end + 1; } if (GNUNET_YES == fail) { GNUNET_free (list); list = NULL; } } break; default: fail = GNUNET_YES; break; } GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != cm->timeout_task_id); GNUNET_SCHEDULER_cancel (cm->timeout_task_id); GNUNET_CONTAINER_DLL_remove (h->control_sent_head, h->control_sent_tail, cm); if (GNUNET_YES == fail) { reconnect_arm_later (h); GNUNET_free (cm->msg); GNUNET_free (cm); return; } if ( (GNUNET_MESSAGE_TYPE_ARM_RESULT == ntohs (msg->type)) && (0 == strcasecmp ((const char *) &cm->msg[1], "arm")) && (NULL != (res = (const struct GNUNET_ARM_ResultMessage *) msg)) && (GNUNET_ARM_RESULT_STOPPING == ntohl (res->result)) ) { /* special case: if we are stopping 'gnunet-service-arm', we do not just wait for the result message, but also wait for the service to close the connection (and then we have to close our client handle as well); this is done by installing a different receive handler, waiting for the connection to go down */ if (NULL != h->thm) { GNUNET_break (0); cm->result_cont (h->thm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, (const char *) &h->thm->msg[1], GNUNET_ARM_RESULT_IS_NOT_KNOWN); GNUNET_free (h->thm->msg); GNUNET_free (h->thm); } h->thm = cm; GNUNET_CLIENT_receive (h->client, &arm_termination_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); return; } GNUNET_CLIENT_receive (h->client, &client_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_ARM_RESULT: res = (const struct GNUNET_ARM_ResultMessage *) msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received response from ARM for service `%s': %u\n", (const char *) &cm->msg[1], ntohs (msg->type)); result = (enum GNUNET_ARM_Result) ntohl (res->result); if (NULL != cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, (const char *) &cm->msg[1], result); break; case GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT: if (NULL != cm->list_cont) cm->list_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, rcount, list); GNUNET_free_non_null (list); break; } GNUNET_free (cm->msg); GNUNET_free (cm); } /** * Transmit the next message to the arm service. * * @param cls closure with the `struct GNUNET_ARM_Handle` * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ static size_t transmit_arm_message (void *cls, size_t size, void *buf) { struct GNUNET_ARM_Handle *h = cls; struct ARMControlMessage *cm; struct GNUNET_ARM_Message *arm_msg; uint64_t request_id; int notify_connection; uint16_t msize; notify_connection = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_arm_message is running with %p buffer of size %lu. ARM is known to be %s\n", buf, size, h->currently_down ? "unconnected" : "connected"); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task); h->cth = NULL; if ((GNUNET_YES == h->currently_down) && (NULL != buf)) { h->currently_down = GNUNET_NO; notify_connection = GNUNET_YES; h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS; GNUNET_CLIENT_receive (h->client, &client_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); } if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed, initiating reconnect\n"); reconnect_arm_later (h); return 0; } if (NULL == (cm = h->control_pending_head)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue is empty, not sending anything\n"); msize = 0; goto end; } GNUNET_assert (NULL != cm->msg); msize = ntohs (cm->msg->header.size); if (size < msize) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Request is too big (%u < %u), not sending it\n", size, msize); trigger_next_request (h, GNUNET_NO); msize = 0; goto end; } arm_msg = cm->msg; if (0 == h->request_id_counter) h->request_id_counter++; request_id = h->request_id_counter++; LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting control message with %u bytes of type %u to arm with id %llu\n", (unsigned int) msize, (unsigned int) ntohs (cm->msg->header.type), request_id); arm_msg->reserved = htonl (0); arm_msg->request_id = GNUNET_htonll (request_id); memcpy (buf, cm->msg, msize); /* Otherwise we won't be able to find it later! */ arm_msg->request_id = request_id; GNUNET_CONTAINER_DLL_remove (h->control_pending_head, h->control_pending_tail, cm); GNUNET_CONTAINER_DLL_insert_tail (h->control_sent_head, h->control_sent_tail, cm); /* Don't free msg, keep it around (kind of wasteful, but then we don't * really have many messages to handle, and it'll be freed when it times * out anyway. */ trigger_next_request (h, GNUNET_NO); end: if ((GNUNET_YES == notify_connection) && (NULL != h->conn_status)) h->conn_status (h->conn_status_cls, GNUNET_YES); return msize; } /** * Check the list of pending requests, send the next * one to the arm. * * @param h arm handle * @param ignore_currently_down transmit message even if not initialized? */ static void trigger_next_request (struct GNUNET_ARM_Handle *h, int ignore_currently_down) { uint16_t msize; msize = sizeof (struct GNUNET_MessageHeader); if ((GNUNET_YES == h->currently_down) && (ignore_currently_down == GNUNET_NO)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "ARM connection down, not processing queue\n"); return; } if (NULL != h->cth) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Request pending, not processing queue\n"); return; } if (NULL != h->control_pending_head) msize = ntohs (h->control_pending_head->msg->header.size); else if (GNUNET_NO == ignore_currently_down) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Request queue empty, not processing queue\n"); return; /* no pending message */ } h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client, msize, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_arm_message, h); } /** * Connect to arm. * * @param h arm handle * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ static int reconnect_arm (struct GNUNET_ARM_Handle *h) { GNUNET_assert (NULL == h->client); GNUNET_assert (GNUNET_YES == h->currently_down); h->client = GNUNET_CLIENT_connect ("arm", h->cfg); if (NULL == h->client) { LOG (GNUNET_ERROR_TYPE_DEBUG, "arm_api, GNUNET_CLIENT_connect returned NULL\n"); if (NULL != h->conn_status) h->conn_status (h->conn_status_cls, GNUNET_SYSERR); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "arm_api, GNUNET_CLIENT_connect returned non-NULL\n"); trigger_next_request (h, GNUNET_YES); return GNUNET_OK; } /** * Set up a context for communicating with ARM, then * start connecting to the ARM service using that context. * * @param cfg configuration to use (needed to contact ARM; * the ARM service may internally use a different * configuration to determine how to start the service). * @param conn_status will be called when connecting/disconnecting * @param cls closure for conn_status * @return context to use for further ARM operations, NULL on error. */ struct GNUNET_ARM_Handle * GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ARM_ConnectionStatusCallback conn_status, void *cls) { struct GNUNET_ARM_Handle *h; h = GNUNET_new (struct GNUNET_ARM_Handle); h->cfg = GNUNET_CONFIGURATION_dup (cfg); h->currently_down = GNUNET_YES; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; h->conn_status = conn_status; h->conn_status_cls = cls; if (GNUNET_OK != reconnect_arm (h)) { GNUNET_free (h); return NULL; } return h; } /** * Disconnect from the ARM service (if connected) and destroy the context. * * @param h the handle that was being used */ void GNUNET_ARM_disconnect_and_free (struct GNUNET_ARM_Handle *h) { struct ARMControlMessage *cm; LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from ARM service\n"); if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } while ((NULL != (cm = h->control_pending_head)) || (NULL != (cm = h->control_sent_head)) ) { if (NULL != h->control_pending_head) GNUNET_CONTAINER_DLL_remove (h->control_pending_head, h->control_pending_tail, cm); else GNUNET_CONTAINER_DLL_remove (h->control_sent_head, h->control_sent_tail, cm); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != cm->timeout_task_id); GNUNET_SCHEDULER_cancel (cm->timeout_task_id); if (NULL != cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_DISCONNECTED, NULL, 0); /* FIXME: What about list callback? */ GNUNET_free_non_null (cm->msg); GNUNET_free (cm); } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_NO == h->service_test_is_active) { GNUNET_CONFIGURATION_destroy (h->cfg); GNUNET_free (h); } } /** * Message timed out. Remove it from the queue. * * @param cls the message (struct ARMControlMessage *) * @param tc task context */ static void control_message_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ARMControlMessage *cm = cls; struct GNUNET_ARM_Message *arm_msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Control message timed out\n"); arm_msg = cm->msg; if ((NULL == arm_msg) || (0 == arm_msg->request_id)) { GNUNET_CONTAINER_DLL_remove (cm->h->control_pending_head, cm->h->control_pending_tail, cm); } else { GNUNET_CONTAINER_DLL_remove (cm->h->control_sent_head, cm->h->control_sent_tail, cm); } if (NULL != cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_TIMEOUT, NULL, 0); else if (NULL != cm->list_cont) cm->list_cont (cm->cont_cls, GNUNET_ARM_REQUEST_TIMEOUT, 0, NULL); GNUNET_free_non_null (cm->msg); GNUNET_free (cm); } /** * A client specifically requested starting of ARM itself. * This function is called with information about whether * or not ARM is running; if it is, report success. If * it is not, start the ARM process. * * @param cls the context for the request that we will report on (struct ARMControlMessage *) * @param result GNUNET_YES if ARM is running */ static void arm_service_report (void *cls, int result) { struct ARMControlMessage *cm = cls; struct GNUNET_ARM_Handle *h; struct GNUNET_OS_Process *proc; unsigned char test_is_active; char *cbinary; char *binary; char *quotedbinary; char *config; char *loprefix; char *lopostfix; test_is_active = cm->h->service_test_is_active; if ((GNUNET_YES == test_is_active) && (GNUNET_YES == result)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Looks like `%s' is already running.\n", "gnunet-service-arm"); /* arm is running! */ if (cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_RESULT_IS_STARTED_ALREADY); } if (GNUNET_NO == test_is_active) { /* User disconnected & destroyed ARM handle in the middle of * the service test, so we kept the handle around until now. */ GNUNET_CONFIGURATION_destroy (cm->h->cfg); GNUNET_free (cm->h); } if ((GNUNET_YES == result) || (GNUNET_NO == test_is_active)) { GNUNET_free (cm); return; } cm->h->service_test_is_active = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_DEBUG, "Looks like `%s' is not running, will start it.\n", "gnunet-service-arm"); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string ( cm->h->cfg, "arm", "PREFIX", &loprefix)) loprefix = GNUNET_strdup (""); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string ( cm->h->cfg, "arm", "OPTIONS", &lopostfix)) lopostfix = GNUNET_strdup (""); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string ( cm->h->cfg, "arm", "BINARY", &cbinary)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING, "arm", "BINARY"); if (cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_RESULT_IS_NOT_KNOWN); GNUNET_free (cm); GNUNET_free (loprefix); GNUNET_free (lopostfix); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename ( cm->h->cfg, "arm", "CONFIG", &config)) config = NULL; binary = GNUNET_OS_get_libexec_binary_path (cbinary); GNUNET_asprintf ("edbinary, "\"%s\"", binary); GNUNET_free (cbinary); if ((GNUNET_YES == GNUNET_CONFIGURATION_have_value ( cm->h->cfg, "TESTING", "WEAKRANDOM")) && (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno ( cm->h->cfg, "TESTING", "WEAKRANDOM")) && (GNUNET_NO == GNUNET_CONFIGURATION_have_value ( cm->h->cfg, "TESTING", "HOSTFILE"))) { /* Means we are ONLY running locally */ /* we're clearly running a test, don't daemonize */ if (NULL == config) proc = GNUNET_OS_start_process_s (GNUNET_NO, cm->std_inheritance, NULL, loprefix, quotedbinary, /* no daemonization! */ lopostfix, NULL); else proc = GNUNET_OS_start_process_s (GNUNET_NO, cm->std_inheritance, NULL, loprefix, quotedbinary, "-c", config, /* no daemonization! */ lopostfix, NULL); } else { if (NULL == config) proc = GNUNET_OS_start_process_s (GNUNET_NO, cm->std_inheritance, NULL, loprefix, quotedbinary, "-d", lopostfix, NULL); else proc = GNUNET_OS_start_process_s (GNUNET_NO, cm->std_inheritance, NULL, loprefix, quotedbinary, "-c", config, "-d", lopostfix, NULL); } GNUNET_free (binary); GNUNET_free (quotedbinary); GNUNET_free_non_null (config); GNUNET_free (loprefix); GNUNET_free (lopostfix); if (NULL == proc) { if (cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_RESULT_START_FAILED); GNUNET_free (cm); return; } if (cm->result_cont) cm->result_cont (cm->cont_cls, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_RESULT_STARTING); GNUNET_OS_process_destroy (proc); h = cm->h; GNUNET_free (cm); reconnect_arm (h); } /** * Start or stop a service. * * @param h handle to ARM * @param service_name name of the service * @param timeout how long to wait before failing for good * @param cb callback to invoke when service is ready * @param cb_cls closure for callback * @param type type of the request */ static void change_service (struct GNUNET_ARM_Handle *h, const char *service_name, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ResultCallback cb, void *cb_cls, uint16_t type) { struct ARMControlMessage *cm; size_t slen; struct GNUNET_ARM_Message *msg; slen = strlen (service_name) + 1; if (slen + sizeof (struct GNUNET_ARM_Message) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); if (cb != NULL) cb (cb_cls, GNUNET_ARM_REQUEST_TOO_LONG, NULL, 0); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting %s of service `%s'.\n", (GNUNET_MESSAGE_TYPE_ARM_START == type) ? "start" : "termination", service_name); cm = GNUNET_malloc (sizeof (struct ARMControlMessage) + slen); cm->h = h; cm->result_cont = cb; cm->cont_cls = cb_cls; cm->timeout = GNUNET_TIME_relative_to_absolute (timeout); memcpy (&cm[1], service_name, slen); msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message) + slen); msg->header.size = htons (sizeof (struct GNUNET_ARM_Message) + slen); msg->header.type = htons (type); msg->reserved = htonl (0); memcpy (&msg[1], service_name, slen); cm->msg = msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Inserting a control message into the queue. Timeout is %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (cm->timeout), GNUNET_NO)); GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, h->control_pending_tail, cm); cm->timeout_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (cm->timeout), &control_message_timeout, cm); trigger_next_request (h, GNUNET_NO); } /** * Request for a service to be started. * * @param h handle to ARM * @param service_name name of the service * @param std_inheritance inheritance of std streams * @param timeout how long to wait before failing for good * @param cont callback to invoke after request is sent or not sent * @param cont_cls closure for callback */ void GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h, const char *service_name, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ResultCallback cont, void *cont_cls) { struct ARMControlMessage *cm; size_t slen; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to start service `%s' within %s\n", service_name, GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO)); if (0 == strcasecmp ("arm", service_name)) { /* Possible cases: * 1) We're connected to ARM already. Invoke the callback immediately. * 2) We're not connected to ARM. * Cancel any reconnection attempts temporarily, then perform * a service test. */ if (GNUNET_NO == h->currently_down) { LOG (GNUNET_ERROR_TYPE_DEBUG, "ARM is already running\n"); if (NULL != cont) cont (cont_cls, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_RESULT_IS_STARTED_ALREADY); } else if (GNUNET_NO == h->service_test_is_active) { if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != h->reconnect_task) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Not connected to ARM, will do a service test\n"); slen = strlen ("arm") + 1; cm = GNUNET_malloc (sizeof (struct ARMControlMessage) + slen); cm->h = h; cm->result_cont = cont; cm->cont_cls = cont_cls; cm->timeout = GNUNET_TIME_relative_to_absolute (timeout); cm->std_inheritance = std_inheritance; memcpy (&cm[1], service_name, slen); h->service_test_is_active = GNUNET_YES; GNUNET_CLIENT_service_test ("arm", h->cfg, timeout, &arm_service_report, cm); } else { /* Service test is already running - tell user to chill out and try * again later. */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Service test is already in progress, we're busy\n"); if (NULL != cont) cont (cont_cls, GNUNET_ARM_REQUEST_BUSY, NULL, 0); } return; } change_service (h, service_name, timeout, cont, cont_cls, GNUNET_MESSAGE_TYPE_ARM_START); } /** * Request a service to be stopped. * Stopping arm itself will not invalidate its handle, and * ARM API will try to restore connection to the ARM service, * even if ARM connection was lost because you asked for ARM to be stopped. * Call GNUNET_ARM_disconnect_and_free () to free the handle and prevent * further connection attempts. * * @param h handle to ARM * @param service_name name of the service * @param timeout how long to wait before failing for good * @param cont callback to invoke after request is sent or is not sent * @param cont_cls closure for callback */ void GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h, const char *service_name, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ResultCallback cont, void *cont_cls) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping service `%s' within %s\n", service_name, GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO)); change_service (h, service_name, timeout, cont, cont_cls, GNUNET_MESSAGE_TYPE_ARM_STOP); } /** * Request a list of running services. * * @param h handle to ARM * @param timeout how long to wait before failing for good * @param cont callback to invoke after request is sent or is not sent * @param cont_cls closure for callback */ void GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h, struct GNUNET_TIME_Relative timeout, GNUNET_ARM_ServiceListCallback cont, void *cont_cls) { struct ARMControlMessage *cm; struct GNUNET_ARM_Message *msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting LIST from ARM service with timeout: %s\n", GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_YES)); cm = GNUNET_new (struct ARMControlMessage); cm->h = h; cm->list_cont = cont; cm->cont_cls = cont_cls; cm->timeout = GNUNET_TIME_relative_to_absolute (timeout); msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message)); msg->header.size = htons (sizeof (struct GNUNET_ARM_Message)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_LIST); msg->reserved = htonl (0); cm->msg = msg; GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, h->control_pending_tail, cm); cm->timeout_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (cm->timeout), &control_message_timeout, cm); trigger_next_request (h, GNUNET_NO); } /* end of arm_api.c */ gnunet-0.10.1/src/arm/test_arm_api.c0000644000175000017500000001552712237153764014217 00000000000000/* This file is part of GNUnet. (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file arm/test_arm_api.c * @brief testcase for arm_api.c */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_resolver_service.h" #define LOG(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) #define START_ARM GNUNET_YES #define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 1500) #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_ARM_Handle *arm; static int ok = 1; static int phase = 0; static void arm_stop_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) { /* (6), a stop request should be sent to ARM successfully */ /* ARM should report that it is stopping */ GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED); GNUNET_break (phase == 6); phase++; LOG ("Sent 'STOP' request for arm to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); } static void resolver_stop_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) { /* (5), a stop request should be sent to ARM successfully. * ARM should report that resolver is stopped. */ GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED); GNUNET_break (phase == 5); LOG ("Sent 'STOP' request for resolver to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); phase++; #if START_ARM GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL); #else arm_stop_cb (NULL, GNUNET_ARM_STATUS_SENT_OK, "arm", GNUNET_ARM_SERVICE_STOPPING); arm_conn (NULL, GNUNET_NO); #endif } static void dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen) { if (addr == NULL) { /* (4), resolver should finish resolving localhost */ GNUNET_break (phase == 4); phase++; LOG ("Finished resolving localhost\n"); if (ok != 0) ok = 2; GNUNET_ARM_request_service_stop (arm, "resolver", TIMEOUT, resolver_stop_cb, NULL); return; } /* (3), resolver should resolve localhost */ GNUNET_break (phase == 3); LOG ("Resolved localhost\n"); phase++; GNUNET_break (addr != NULL); ok = 0; } static void resolver_start_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) { /* (2), the start request for resolver should be sent successfully * ARM should report that resolver service is starting. */ GNUNET_assert (status == GNUNET_ARM_REQUEST_SENT_OK); GNUNET_break (phase == 2); GNUNET_break (result == GNUNET_ARM_RESULT_STARTING); LOG ("Sent 'START' request for resolver to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); phase++; GNUNET_RESOLVER_ip_get ("localhost", AF_INET, TIMEOUT, &dns_notify, NULL); } static void trigger_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_ARM_disconnect_and_free ((struct GNUNET_ARM_Handle *) cls); } static void arm_conn (void *cls, int connected) { if (GNUNET_SYSERR == connected) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fatal error initializing ARM API.\n")); GNUNET_SCHEDULER_shutdown (); GNUNET_assert (0); return; } if (GNUNET_YES == connected) { /* (1), arm connection should be established */ LOG ("Connected to ARM\n"); GNUNET_break (phase == 1); phase++; GNUNET_ARM_request_service_start (arm, "resolver", GNUNET_OS_INHERIT_STD_OUT_AND_ERR, START_TIMEOUT, resolver_start_cb, NULL); } else { /* (7), ARM should stop (we disconnect from it) */ LOG ("Disconnected from ARM\n"); GNUNET_break (phase == 7); if (phase != 7) ok = 3; else if (ok == 1) ok = 0; GNUNET_SCHEDULER_add_now (trigger_disconnect, arm); } } static void arm_start_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) { /* (0) The request should be "sent" successfully * ("sent", because it isn't going anywhere, ARM API starts ARM service * by itself). * ARM API should report that ARM service is starting. */ GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); GNUNET_break (phase == 0); LOG ("Sent 'START' request for arm to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); GNUNET_break (result == GNUNET_ARM_RESULT_STARTING); phase++; } static void task (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char *armconfig; cfg = c; if (NULL != cfgfile) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "arm", "CONFIG", &armconfig)) { GNUNET_CONFIGURATION_set_value_string ((struct GNUNET_CONFIGURATION_Handle *) cfg, "arm", "CONFIG", cfgfile); } else GNUNET_free (armconfig); } arm = GNUNET_ARM_connect (cfg, &arm_conn, NULL); if (NULL == arm) return; #if START_ARM GNUNET_ARM_request_service_start (arm, "arm", GNUNET_OS_INHERIT_STD_OUT_AND_ERR, START_TIMEOUT, arm_start_cb, NULL); #else arm_start_cb (NULL, arm, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_RESULT_STARTING); arm_conn (NULL, arm, GNUNET_YES); #endif } int main (int argc, char *argvx[]) { char *const argv[] = { "test-arm-api", "-c", "test_arm_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_log_setup ("test-arm-api", "WARNING", NULL); GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-arm-api", "nohelp", options, &task, NULL)); return ok; } /* end of test_arm_api.c */ gnunet-0.10.1/src/arm/test_gnunet_arm.py.in0000644000175000017500000000522312221077151015535 00000000000000#!@PYTHON@ from __future__ import print_function import os import sys import shutil import re import subprocess import time if os.name == "nt": tmp = os.getenv ("TEMP") else: tmp = "/tmp" if os.name == 'nt': st = 'gnunet-statistics.exe' arm = './gnunet-arm.exe' else: st = 'gnunet-statistics' arm = './gnunet-arm' run_arm = [arm, '-c', 'test_arm_api_data.conf', '--no-stdout', '--no-stderr'] debug = os.getenv ('DEBUG') if debug: run_arm += [debug.split (' ')] def cleanup (): shutil.rmtree (os.path.join (tmp, "test-gnunetd-arm"), True) def sub_run (args, want_stdo = True, want_stde = False, nofail = False): if want_stdo: stdo = subprocess.PIPE else: stdo = None if want_stde: stde = subprocess.PIPE else: stde = None p = subprocess.Popen (args, stdout = stdo, stderr = stde) stdo, stde = p.communicate () if not nofail: if p.returncode != 0: sys.exit (p.returncode) return (p.returncode, stdo, stde) def fail (result): print (result) r_arm (['-e'], want_stdo = False) sys.exit (1) def end_arm_failer (command, rc, stdo, stde, normal): if normal: if rc != 0: fail ("FAIL: error running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) else: if rc == 0: fail ("FAIL: expected error while running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) def print_only_failer (command, rc, stdo, stde, normal): if normal: if rc != 0: print ("FAIL: error running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) sys.exit (1) else: if rc == 0: print ("FAIL: expected error while running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) sys.exit (1) def r_something (to_run, extra_args, failer = None, normal = True, **kw): rc, stdo, stde = sub_run (to_run + extra_args, nofail = True, want_stde = True, **kw) if failer is not None: failer (to_run + extra_args, rc, stdo, stde, normal) return (rc, stdo, stde) def r_arm (extra_args, **kw): return r_something (run_arm, extra_args, **kw) cleanup () print ("TEST: Bad argument checking...", end='') r_arm (['-x'], normal = False, failer = print_only_failer) print ("PASS") print ("TEST: Start ARM...", end='') r_arm (['-s'], failer = print_only_failer) time.sleep (1) print ("PASS") print ("TEST: Start another service...", end='') r_arm (['-i', 'resolver'], failer = end_arm_failer) time.sleep (1) print ("PASS") print ("TEST: Stop a service...", end='') r_arm (['-k', 'resolver'], failer = end_arm_failer) time.sleep (1) print ("PASS") print ("TEST: Stop ARM...", end='') r_arm (['-e'], failer = print_only_failer) time.sleep (1) print ("PASS") cleanup () gnunet-0.10.1/src/arm/test_exponential_backoff.c0000644000175000017500000003151312255010512016560 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file arm/test_exponential_backoff.c * @brief testcase for gnunet-service-arm.c */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #define LOG(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) #define START_ARM GNUNET_YES #define LOG_BACKOFF GNUNET_NO #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) #define SERVICE_TEST_TIMEOUT GNUNET_TIME_UNIT_FOREVER_REL #define FIVE_MILLISECONDS GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 5) #define SERVICE "do-nothing" #define BINARY "mockup-service" #define CFGFILENAME "test_arm_api_data2.conf" static const struct GNUNET_CONFIGURATION_Handle *cfg; static struct GNUNET_ARM_Handle *arm; static struct GNUNET_ARM_MonitorHandle *mon; static int ok = 1; static int phase = 0; static int trialCount; static struct GNUNET_TIME_Absolute startedWaitingAt; struct GNUNET_TIME_Relative waitedFor; struct GNUNET_TIME_Relative waitedFor_prev; #if LOG_BACKOFF static FILE *killLogFilePtr; static char *killLogFileName; #endif typedef void (*GNUNET_CLIENT_ShutdownTask) (void *cls, int reason); /** * Context for handling the shutdown of a service. */ struct ShutdownContext { /** * Connection to the service that is being shutdown. */ struct GNUNET_CLIENT_Connection *sock; /** * Time allowed for shutdown to happen. */ struct GNUNET_TIME_Absolute timeout; /** * Task set up to cancel the shutdown request on timeout. */ GNUNET_SCHEDULER_TaskIdentifier cancel_task; /** * Task to call once shutdown complete */ GNUNET_CLIENT_ShutdownTask cont; /** * Closure for shutdown continuation */ void *cont_cls; /** * We received a confirmation that the service will shut down. */ int confirmed; }; /** * Handler receiving response to service shutdown requests. * We expect it to be called with NULL, since the service that * we are shutting down will just die without replying. * * @param cls closure * @param msg NULL, indicating socket closure. */ static void service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct ShutdownContext *shutdown_ctx = cls; if (NULL == msg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n"); if (shutdown_ctx->cont != NULL) shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_NO); GNUNET_SCHEDULER_cancel (shutdown_ctx->cancel_task); GNUNET_CLIENT_disconnect (shutdown_ctx->sock); GNUNET_free (shutdown_ctx); return; } GNUNET_assert (0); } /** * Shutting down took too long, cancel receive and return error. * * @param cls closure * @param tc context information (why was this task triggered now) */ void service_shutdown_cancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ShutdownContext *shutdown_ctx = cls; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "service_shutdown_cancel called!\n"); shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); GNUNET_CLIENT_disconnect (shutdown_ctx->sock); GNUNET_free (shutdown_ctx); } /** * If possible, write a shutdown message to the target * buffer and destroy the client connection. * * @param cls the "struct GNUNET_CLIENT_Connection" to destroy * @param size number of bytes available in buf * @param buf NULL on error, otherwise target buffer * @return number of bytes written to buf */ static size_t write_shutdown (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg; struct ShutdownContext *shutdown_ctx = cls; if (size < sizeof (struct GNUNET_MessageHeader)) { LOG ("Failed to send a shutdown request\n"); shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR); GNUNET_CLIENT_disconnect (shutdown_ctx->sock); GNUNET_free (shutdown_ctx); return 0; /* client disconnected */ } GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler, shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL); shutdown_ctx->cancel_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_absolute_get_remaining (shutdown_ctx->timeout), &service_shutdown_cancel, shutdown_ctx); msg = (struct GNUNET_MessageHeader *) buf; msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_STOP); msg->size = htons (sizeof (struct GNUNET_MessageHeader)); strcpy ((char *) &msg[1], SERVICE); LOG ("Sent a shutdown request\n"); return sizeof (struct GNUNET_MessageHeader) + strlen (SERVICE) + 1; } /** * Request that the service should shutdown. * Afterwards, the connection will automatically be * disconnected. Hence the "sock" should not * be used by the caller after this call * (calling this function frees "sock" after a while). * * @param sock the socket connected to the service * @param timeout how long to wait before giving up on transmission * @param cont continuation to call once the service is really down * @param cont_cls closure for continuation * */ static void do_nothing_service_shutdown (struct GNUNET_CLIENT_Connection *sock, struct GNUNET_TIME_Relative timeout, GNUNET_CLIENT_ShutdownTask cont, void *cont_cls) { struct ShutdownContext *shutdown_ctx; shutdown_ctx = GNUNET_new (struct ShutdownContext); shutdown_ctx->cont = cont; shutdown_ctx->cont_cls = cont_cls; shutdown_ctx->sock = sock; shutdown_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); GNUNET_CLIENT_notify_transmit_ready (sock, sizeof (struct GNUNET_MessageHeader) + strlen (SERVICE) + 1, timeout, GNUNET_NO, &write_shutdown, shutdown_ctx); } static void kill_task (void *cbData, const struct GNUNET_SCHEDULER_TaskContext *tc); static void shutdown_cont (void *cls, int reason) { if (GNUNET_NO != reason) { /* Re-try shutdown */ LOG ("do-nothing didn't die, trying again\n"); GNUNET_SCHEDULER_add_now (kill_task, NULL); return; } startedWaitingAt = GNUNET_TIME_absolute_get (); LOG ("do-nothing is dead, starting the countdown\n"); } static void kill_task (void *cbData, const struct GNUNET_SCHEDULER_TaskContext *tc) { static struct GNUNET_CLIENT_Connection *doNothingConnection = NULL; if (NULL != cbData) { waitedFor = GNUNET_TIME_absolute_get_duration (startedWaitingAt); LOG ("Waited for: %s\n", GNUNET_STRINGS_relative_time_to_string (waitedFor, GNUNET_YES)); } else { waitedFor.rel_value_us = 0; } /* Connect to the doNothing task */ doNothingConnection = GNUNET_CLIENT_connect (SERVICE, cfg); GNUNET_assert (doNothingConnection != NULL); if (trialCount == 12) waitedFor_prev = waitedFor; else if (trialCount == 13) { GNUNET_CLIENT_disconnect (doNothingConnection); GNUNET_ARM_request_service_stop (arm, SERVICE, TIMEOUT, NULL, NULL); if (waitedFor_prev.rel_value_us >= waitedFor.rel_value_us) ok = 9; else ok = 0; trialCount += 1; return; } trialCount += 1; /* Use the created connection to kill the doNothingTask */ do_nothing_service_shutdown (doNothingConnection, TIMEOUT, &shutdown_cont, NULL); } static void trigger_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_ARM_disconnect_and_free (arm); GNUNET_ARM_monitor_disconnect_and_free (mon); } static void arm_stop_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) { GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED); LOG ("ARM service stopped\n"); GNUNET_SCHEDULER_add_now (trigger_disconnect, NULL); } static void srv_status (void *cls, const char *service, enum GNUNET_ARM_ServiceStatus status) { LOG ("Service %s is %u, phase %u\n", service, status, phase); if (status == GNUNET_ARM_SERVICE_MONITORING_STARTED) { phase++; GNUNET_ARM_request_service_start (arm, SERVICE, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, TIMEOUT, NULL, NULL); return; } if (phase == 1) { GNUNET_break (status == GNUNET_ARM_SERVICE_STARTING); GNUNET_break (0 == strcasecmp (service, SERVICE)); GNUNET_break (phase == 1); LOG ("do-nothing is starting\n"); phase++; ok = 1; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &kill_task, NULL); } else if ((phase == 2) && (strcasecmp (SERVICE, service) == 0)) { /* We passively monitor ARM for status updates. ARM should tell us * when do-nothing dies (no need to run a service upness test ourselves). */ if (status == GNUNET_ARM_SERVICE_STARTING) { LOG ("do-nothing is starting\n"); GNUNET_SCHEDULER_add_now (kill_task, &ok); } else if ((status == GNUNET_ARM_SERVICE_STOPPED) && (trialCount == 14)) { phase++; GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL); } } } static void arm_start_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char *servicename, enum GNUNET_ARM_Result result) { GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK); GNUNET_break (result == GNUNET_ARM_RESULT_STARTING); GNUNET_break (phase == 0); LOG ("Sent 'START' request for arm to ARM %s\n", (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully"); } static void task (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char *armconfig; cfg = c; if (NULL != cfgfile) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "arm", "CONFIG", &armconfig)) { GNUNET_CONFIGURATION_set_value_string ((struct GNUNET_CONFIGURATION_Handle *) cfg, "arm", "CONFIG", cfgfile); } else GNUNET_free (armconfig); } arm = GNUNET_ARM_connect (cfg, NULL, NULL); if (NULL != arm) { mon = GNUNET_ARM_monitor (cfg, &srv_status, NULL); if (NULL != mon) { #if START_ARM GNUNET_ARM_request_service_start (arm, "arm", GNUNET_OS_INHERIT_STD_OUT_AND_ERR, GNUNET_TIME_UNIT_ZERO, arm_start_cb, NULL); #else arm_start_cb (NULL, arm, GNUNET_ARM_REQUEST_SENT_OK, "arm", GNUNET_ARM_SERVICE_STARTING); #endif } else { GNUNET_ARM_disconnect_and_free (arm); arm = NULL; } } } static int check () { char *const argv[] = { "test-exponential-backoff", "-c", CFGFILENAME, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; /* Running ARM and running the do_nothing task */ GNUNET_assert (GNUNET_OK == GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-exponential-backoff", "nohelp", options, &task, NULL)); return ok; } static int init () { struct GNUNET_CONFIGURATION_Handle *cfg; char pwd[PATH_MAX]; char *binary; cfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, "test_arm_api_data.conf")) return GNUNET_SYSERR; if (NULL == getcwd (pwd, PATH_MAX)) return GNUNET_SYSERR; GNUNET_assert (0 < GNUNET_asprintf (&binary, "%s/%s", pwd, BINARY)); GNUNET_CONFIGURATION_set_value_string (cfg, SERVICE, "BINARY", binary); GNUNET_free (binary); if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, CFGFILENAME)) { GNUNET_CONFIGURATION_destroy (cfg); return GNUNET_SYSERR; } GNUNET_CONFIGURATION_destroy (cfg); #if LOG_BACKOFF killLogFileName = GNUNET_DISK_mktemp ("exponential-backoff-waiting.log"); if (NULL == (killLogFilePtr = FOPEN (killLogFileName, "w"))) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "fopen", killLogFileName); GNUNET_free (killLogFileName); return GNUNET_SYSERR; } #endif return GNUNET_OK; } static void houseKeep () { #if LOG_BACKOFF GNUNET_assert (0 == fclose (killLogFilePtr)); GNUNET_free (killLogFileName); #endif (void) unlink (CFGFILENAME); } int main (int argc, char *argv[]) { int ret; GNUNET_log_setup ("test-exponential-backoff", "WARNING", NULL); if (GNUNET_OK != init ()) return 1; ret = check (); houseKeep (); return ret; } /* end of test_exponential_backoff.c */ gnunet-0.10.1/src/arm/arm.conf.in0000644000175000017500000000357312255411517013426 00000000000000 [arm] @UNIXONLY@ PORT = 2087 HOSTNAME = localhost BINARY = gnunet-service-arm ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; DEFAULTSERVICES = topology hostlist dht nse mesh fs revocation # Special case, uses user runtime dir even for per-system service. UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-arm.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # In the "-l" option, format characters from 'strftime' are allowed; # In the GLOBAL_POSTFIX, "{}" stands for the name of the respective # service. Thus the following option would introduce per-service # logging with a new log file each day. Note that only the last 3 # log files are preserved. # GLOBAL_POSTFIX = -l $GNUNET_CACHE_HOME/{}-%Y-%m-%d.log GLOBAL_PREFIX = @MONKEYPREFIX@ # If set to YES, ARM will only start services that are marked as # system-level services (and we'll expect a second ARM to be # run per-user to run user-level services). Note that in this # case you must have manually created a different configuration # file with the user where at least this and the USER_ONLY # options differ. # SYSTEM_ONLY = YES # If set to YES, ARM will only start services that are marked as # per-user services (and we'll expect a system user to run ARM to # provide system-level services). Per-user services enable # better personalization and priviledge separation and in particular # ensures that personal data is stored under $HOME, which might # be important in a multi-user system (or if $HOME is encrypted # and /var/ is not). # # Note that if you have different ARM services for SYSTEM and USER, # and you are not on UNIX, you need to change the PORT option for the # USER ARM instances to some free port (counting down from 2085 should # be sane). # # USER_ONLY = YES # Name of the user that will be used to provide the service # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = gnunet-0.10.1/src/arm/arm.h0000644000175000017500000000535212242135660012316 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file arm/arm.h */ #ifndef ARM_H #define ARM_H #include "gnunet_common.h" /** * This option will turn on the DEBUG loglevel for * all processes controlled by this ARM! */ #define DEBUG_ARM GNUNET_EXTRA_LOGGING GNUNET_NETWORK_STRUCT_BEGIN /** * Status update from ARM to client. */ struct GNUNET_ARM_StatusMessage { /** * Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_STATUS. */ struct GNUNET_MessageHeader header; /** * Status from the 'enum GNUNET_ARM_ServiceStatus' */ uint32_t status; /* followed by a 0-terminated service name */ }; struct GNUNET_ARM_Message { /** * Reply to client, type is #GNUNET_MESSAGE_TYPE_ARM_RESULT or * #GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT. * OR * Request from client, type is #GNUNET_MESSAGE_TYPE_ARM_START or * #GNUNET_MESSAGE_TYPE_ARM_STOP. */ struct GNUNET_MessageHeader header; /** * For alignment. */ uint32_t reserved; /** * ID of a request that is being replied to. * OR * ID of a request that is being sent. */ uint64_t request_id; /* For requests - followed by a 0-terminated service name */ }; /** * Reply from ARM to client. */ struct GNUNET_ARM_ResultMessage { /** * Reply to client, of type is #GNUNET_MESSAGE_TYPE_ARM_RESULT, with an ID. */ struct GNUNET_ARM_Message arm_msg; /** * Result from the `enum GNUNET_ARM_Result` */ uint32_t result; }; /** * Reply from ARM to client for the * GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count * '\0' terminated strings. header->size contains the * total size (including all strings). */ struct GNUNET_ARM_ListResultMessage { /** * Reply to client, of type is #GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, * with an ID. */ struct GNUNET_ARM_Message arm_msg; /** * Number of '\0' terminated strings that follow * this message. */ uint16_t count; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/Makefile.am0000644000175000017500000000225512320751517012644 00000000000000#if WANT_FRAMEWORK # INTLEMU_SUBDIRS = intlemu #endif if HAVE_TESTING TESTING = testing TESTBED = testbed CONSENSUS = consensus SECRETSHARING = secretsharing EXPERIMENTATION = experimentation SCALARPRODUCT = scalarproduct endif if HAVE_EXPERIMENTAL EXP_DIR = \ dv \ multicast \ env \ psycstore \ psyc \ $(CONSENSUS) \ $(SECRETSHARING) \ $(SCALARPRODUCT) \ $(EXPERIMENTATION) endif if BUILD_PULSE_HELPERS CONVERSATION_DIR = conversation else if BUILD_GST_HELPERS CONVERSATION_DIR = conversation endif endif if HAVE_MYSQL MYSQL_DIR = mysql endif if HAVE_POSTGRES POSTGRES_DIR = postgres endif SUBDIRS = \ include $(INTLEMU_SUBDIRS) \ util \ hello \ tun \ block \ statistics \ arm \ $(TESTING) \ peerinfo \ $(MYSQL_DIR) \ $(POSTGRES_DIR) \ datacache \ datastore \ template \ ats \ nat \ fragmentation \ transport \ ats-tool \ peerinfo-tool \ core \ $(TESTBED) \ ats-tests \ nse \ dht \ hostlist \ topology \ regex \ mesh \ dns \ identity \ set \ revocation \ gnsrecord \ namecache \ namestore \ vpn \ gns \ $(CONVERSATION_DIR) \ fs \ exit \ pt \ integration-tests \ $(EXP_DIR) gnunet-0.10.1/src/dht/0000755000175000017500000000000012320755625011447 500000000000000gnunet-0.10.1/src/dht/test_dht_topo.c0000644000175000017500000002767612255010512014416 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/test_dht_topo.c * @author Christian Grothoff * @brief Test for the dht service: store and retrieve in various topologies. * Each peer stores a value from the DHT and then each peer tries to get each * value from each other peer. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dht_service.h" #include "dht_test_lib.h" /** * How long until we give up on fetching the data? */ #define GET_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How frequently do we execute the PUTs? */ #define PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Information we keep for each GET operation. */ struct GetOperation { /** * DLL. */ struct GetOperation *next; /** * DLL. */ struct GetOperation *prev; /** * Handle for the operation. */ struct GNUNET_DHT_GetHandle *get; }; /** * Result of the test. */ static int ok = 1; /** * Task to do DHT_puts */ static GNUNET_SCHEDULER_TaskIdentifier put_task; /** * Task to time out / regular shutdown. */ static GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Head of list of active GET operations. */ static struct GetOperation *get_head; /** * Tail of list of active GET operations. */ static struct GetOperation *get_tail; /** * Array of the testbed's peers. */ static struct GNUNET_TESTBED_Peer **my_peers; /** * Number of peers to run. */ static unsigned int NUM_PEERS; /** * Statistics we print out. */ static struct { const char *subsystem; const char *name; unsigned long long total; } stats[] = { {"core", "# bytes decrypted", 0}, {"core", "# bytes encrypted", 0}, {"core", "# type maps received", 0}, {"core", "# session keys confirmed via PONG", 0}, {"core", "# peers connected", 0}, {"core", "# key exchanges initiated", 0}, {"core", "# send requests dropped (disconnected)", 0}, {"core", "# transmissions delayed due to corking", 0}, {"core", "# messages discarded (expired prior to transmission)", 0}, {"core", "# messages discarded (disconnected)", 0}, {"core", "# discarded CORE_SEND requests", 0}, {"core", "# discarded lower priority CORE_SEND requests", 0}, {"transport", "# bytes received via TCP", 0}, {"transport", "# bytes transmitted via TCP", 0}, {"dht", "# PUT messages queued for transmission", 0}, {"dht", "# P2P PUT requests received", 0}, {"dht", "# GET messages queued for transmission", 0}, {"dht", "# P2P GET requests received", 0}, {"dht", "# RESULT messages queued for transmission", 0}, {"dht", "# P2P RESULTS received", 0}, {"dht", "# Queued messages discarded (peer disconnected)", 0}, {"dht", "# Peers excluded from routing due to Bloomfilter", 0}, {"dht", "# Peer selection failed", 0}, {"dht", "# FIND PEER requests ignored due to Bloomfilter", 0}, {"dht", "# FIND PEER requests ignored due to lack of HELLO", 0}, {"dht", "# P2P FIND PEER requests processed", 0}, {"dht", "# P2P GET requests ONLY routed", 0}, {"dht", "# Preference updates given to core", 0}, {"dht", "# REPLIES ignored for CLIENTS (no match)", 0}, {"dht", "# GET requests from clients injected", 0}, {"dht", "# GET requests received from clients", 0}, {"dht", "# GET STOP requests received from clients", 0}, {"dht", "# ITEMS stored in datacache", 0}, {"dht", "# Good RESULTS found in datacache", 0}, {"dht", "# GET requests given to datacache", 0}, {NULL, NULL, 0} }; /** * Function called once we're done processing stats. * * @param cls the test context * @param op the stats operation * @param emsg error message on failure */ static void stats_finished (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { struct GNUNET_DHT_TEST_Context *ctx = cls; unsigned int i; if (NULL != op) GNUNET_TESTBED_operation_done (op); // needed? if (NULL != emsg) { fprintf (stderr, _("Gathering statistics failed: %s\n"), emsg); GNUNET_SCHEDULER_cancel (put_task); GNUNET_DHT_TEST_cleanup (ctx); return; } for (i = 0; NULL != stats[i].name; i++) FPRINTF (stderr, "%6s/%60s = %12llu\n", stats[i].subsystem, stats[i].name, stats[i].total); GNUNET_SCHEDULER_cancel (put_task); GNUNET_DHT_TEST_cleanup (ctx); } /** * Function called to process statistic values from all peers. * * @param cls closure * @param peer the peer the statistic belong to * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int handle_stats (void *cls, const struct GNUNET_TESTBED_Peer *peer, const char *subsystem, const char *name, uint64_t value, int is_persistent) { unsigned int i; for (i = 0; NULL != stats[i].name; i++) if ( (0 == strcasecmp (subsystem, stats[i].subsystem)) && (0 == strcasecmp (name, stats[i].name)) ) stats[i].total += value; return GNUNET_OK; } /** * Task run on success or timeout to clean up. * Terminates active get operations and shuts down * the testbed. * * @param cls the 'struct GNUNET_DHT_TestContext' * @param tc scheduler context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DHT_TEST_Context *ctx = cls; struct GetOperation *get_op; while (NULL != (get_op = get_tail)) { GNUNET_DHT_get_stop (get_op->get); GNUNET_CONTAINER_DLL_remove (get_head, get_tail, get_op); GNUNET_free (get_op); } (void) GNUNET_TESTBED_get_statistics (NUM_PEERS, my_peers, NULL, NULL, &handle_stats, &stats_finished, ctx); } /** * Iterator called on each result obtained for a DHT * operation that expects a reply * * @param cls closure with our 'struct GetOperation' * @param exp when will this value expire * @param key key of the result * @param get_path peers on reply path (or NULL if not recorded) * @param get_path_length number of entries in get_path * @param put_path peers on the PUT path (or NULL if not recorded) * @param put_path_length number of entries in get_path * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data */ static void dht_get_handler (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { struct GetOperation *get_op = cls; struct GNUNET_HashCode want; struct GNUNET_DHT_TestContext *ctx; if (sizeof (struct GNUNET_HashCode) != size) { GNUNET_break (0); return; } GNUNET_CRYPTO_hash (key, sizeof (*key), &want); if (0 != memcmp (&want, data, sizeof (want))) { GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get successful\n"); #if 0 { int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH: (get %u, put %u)\n", get_path_length, put_path_length); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " LOCAL\n"); for (i = get_path_length - 1; i >= 0; i--) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&get_path[i])); for (i = put_path_length - 1; i >= 0; i--) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&put_path[i])); } #endif GNUNET_DHT_get_stop (get_op->get); GNUNET_CONTAINER_DLL_remove (get_head, get_tail, get_op); GNUNET_free (get_op); if (NULL != get_head) return; /* all DHT GET operations successful; terminate! */ ok = 0; ctx = GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_add_now (&shutdown_task, ctx); } /** * Task to put the id of each peer into the DHT. * * @param cls array with NUM_PEERS DHT handles * @param tc Task context */ static void do_puts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DHT_Handle **hs = cls; struct GNUNET_HashCode key; struct GNUNET_HashCode value; unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting values into DHT\n"); for (i = 0; i < NUM_PEERS; i++) { GNUNET_CRYPTO_hash (&i, sizeof (i), &key); GNUNET_CRYPTO_hash (&key, sizeof (key), &value); GNUNET_DHT_put (hs[i], &key, 10U, GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_BLOCK_TYPE_TEST, sizeof (value), &value, GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL, NULL, NULL); } put_task = GNUNET_SCHEDULER_add_delayed (PUT_FREQUENCY, &do_puts, hs); } /** * Main function of the test. * * @param cls closure (NULL) * @param ctx argument to give to GNUNET_DHT_TEST_cleanup on test end * @param num_peers number of peers that are running * @param peers array of peers * @param dhts handle to each of the DHTs of the peers */ static void run (void *cls, struct GNUNET_DHT_TEST_Context *ctx, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, struct GNUNET_DHT_Handle **dhts) { unsigned int i; unsigned int j; struct GNUNET_HashCode key; struct GetOperation *get_op; GNUNET_assert (NUM_PEERS == num_peers); my_peers = peers; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers setup, starting test\n"); put_task = GNUNET_SCHEDULER_add_now (&do_puts, dhts); for (i=0;iget = GNUNET_DHT_get_start (dhts[j], GNUNET_BLOCK_TYPE_TEST, /* type */ &key, /*key to search */ 4U, /* replication level */ GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, /* xquery */ 0, /* xquery bits */ &dht_get_handler, get_op); } } timeout_task = GNUNET_SCHEDULER_add_delayed (GET_TIMEOUT, &shutdown_task, ctx); } /** * Main: start test */ int main (int xargc, char *xargv[]) { const char *cfg_filename; const char *test_name; if (NULL != strstr (xargv[0], "test_dht_2dtorus")) { cfg_filename = "test_dht_2dtorus.conf"; test_name = "test-dht-2dtorus"; NUM_PEERS = 16; } else if (NULL != strstr (xargv[0], "test_dht_line")) { cfg_filename = "test_dht_line.conf"; test_name = "test-dht-line"; NUM_PEERS = 5; } else if (NULL != strstr (xargv[0], "test_dht_twopeer")) { cfg_filename = "test_dht_line.conf"; test_name = "test-dht-twopeer"; NUM_PEERS = 2; } else if (NULL != strstr (xargv[0], "test_dht_multipeer")) { cfg_filename = "test_dht_multipeer.conf"; test_name = "test-dht-multipeer"; NUM_PEERS = 10; } else { GNUNET_break (0); return 1; } GNUNET_DHT_TEST_run (test_name, cfg_filename, NUM_PEERS, &run, NULL); return ok; } /* end of test_dht_topo.c */ gnunet-0.10.1/src/dht/gnunet-service-dht_clients.c0000644000175000017500000013615712320471427016777 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_clients.c * @brief GNUnet DHT service's client management code * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet-service-dht.h" #include "gnunet-service-dht_clients.h" #include "gnunet-service-dht_datacache.h" #include "gnunet-service-dht_neighbours.h" #include "dht.h" /** * Should routing details be logged to stderr (for debugging)? */ #define LOG_TRAFFIC(kind,...) GNUNET_log_from (kind, "dht-traffic",__VA_ARGS__) #define LOG(kind,...) GNUNET_log_from (kind, "dht-clients",__VA_ARGS__) /** * Linked list of messages to send to clients. */ struct PendingMessage { /** * Pointer to next item in the list */ struct PendingMessage *next; /** * Pointer to previous item in the list */ struct PendingMessage *prev; /** * Actual message to be sent, allocated at the end of the struct: * // msg = (cast) &pm[1]; * // memcpy (&pm[1], data, len); */ const struct GNUNET_MessageHeader *msg; }; /** * Struct containing information about a client, * handle to connect to it, and any pending messages * that need to be sent to it. */ struct ClientList { /** * Linked list of active clients */ struct ClientList *next; /** * Linked list of active clients */ struct ClientList *prev; /** * The handle to this client */ struct GNUNET_SERVER_Client *client_handle; /** * Handle to the current transmission request, NULL * if none pending. */ struct GNUNET_SERVER_TransmitHandle *transmit_handle; /** * Linked list of pending messages for this client */ struct PendingMessage *pending_head; /** * Tail of linked list of pending messages for this client */ struct PendingMessage *pending_tail; }; /** * Entry in the local forwarding map for a client's GET request. */ struct ClientQueryRecord { /** * The key this request was about */ struct GNUNET_HashCode key; /** * Client responsible for the request. */ struct ClientList *client; /** * Extended query (see gnunet_block_lib.h), allocated at the end of this struct. */ const void *xquery; /** * Replies we have already seen for this request. */ struct GNUNET_HashCode *seen_replies; /** * Pointer to this nodes heap location in the retry-heap (for fast removal) */ struct GNUNET_CONTAINER_HeapNode *hnode; /** * What's the delay between re-try operations that we currently use for this * request? */ struct GNUNET_TIME_Relative retry_frequency; /** * What's the next time we should re-try this request? */ struct GNUNET_TIME_Absolute retry_time; /** * The unique identifier of this request */ uint64_t unique_id; /** * Number of bytes in xquery. */ size_t xquery_size; /** * Number of entries in 'seen_replies'. */ unsigned int seen_replies_count; /** * Desired replication level */ uint32_t replication; /** * Any message options for this request */ uint32_t msg_options; /** * The type for the data for the GET request. */ enum GNUNET_BLOCK_Type type; }; /** * Struct containing paremeters of monitoring requests. */ struct ClientMonitorRecord { /** * Next element in DLL. */ struct ClientMonitorRecord *next; /** * Previous element in DLL. */ struct ClientMonitorRecord *prev; /** * Type of blocks that are of interest */ enum GNUNET_BLOCK_Type type; /** * Key of data of interest, NULL for all. */ struct GNUNET_HashCode *key; /** * Flag whether to notify about GET messages. */ int16_t get; /** * Flag whether to notify about GET_REPONSE messages. */ int16_t get_resp; /** * Flag whether to notify about PUT messages. */ uint16_t put; /** * Client to notify of these requests. */ struct ClientList *client; }; /** * List of active clients. */ static struct ClientList *client_head; /** * List of active clients. */ static struct ClientList *client_tail; /** * List of active monitoring requests. */ static struct ClientMonitorRecord *monitor_head; /** * List of active monitoring requests. */ static struct ClientMonitorRecord *monitor_tail; /** * Hashmap for fast key based lookup, maps keys to `struct ClientQueryRecord` entries. */ static struct GNUNET_CONTAINER_MultiHashMap *forward_map; /** * Heap with all of our client's request, sorted by retry time (earliest on top). */ static struct GNUNET_CONTAINER_Heap *retry_heap; /** * Task that re-transmits requests (using retry_heap). */ static GNUNET_SCHEDULER_TaskIdentifier retry_task; /** * Task run to check for messages that need to be sent to a client. * * @param client a ClientList, containing the client and any messages to be sent to it */ static void process_pending_messages (struct ClientList *client); /** * Add a PendingMessage to the clients list of messages to be sent * * @param client the active client to send the message to * @param pending_message the actual message to send */ static void add_pending_message (struct ClientList *client, struct PendingMessage *pending_message) { GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, client->pending_tail, pending_message); process_pending_messages (client); } /** * Find a client if it exists, add it otherwise. * * @param client the server handle to the client * * @return the client if found, a new client otherwise */ static struct ClientList * find_active_client (struct GNUNET_SERVER_Client *client) { struct ClientList *pos = client_head; struct ClientList *ret; while (pos != NULL) { if (pos->client_handle == client) return pos; pos = pos->next; } ret = GNUNET_new (struct ClientList); ret->client_handle = client; GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ret); return ret; } /** * Iterator over hash map entries that frees all entries * associated with the given client. * * @param cls client to search for in source routes * @param key current key code (ignored) * @param value value in the hash map, a ClientQueryRecord * @return #GNUNET_YES (we should continue to iterate) */ static int remove_client_records (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ClientList *client = cls; struct ClientQueryRecord *record = value; if (record->client != client) return GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing client %p's record for key %s\n", client, GNUNET_h2s (key)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (forward_map, key, record)); if (NULL != record->hnode) GNUNET_CONTAINER_heap_remove_node (record->hnode); GNUNET_array_grow (record->seen_replies, record->seen_replies_count, 0); GNUNET_free (record); return GNUNET_YES; } /** * Functions with this signature are called whenever a client * is disconnected on the network level. * * @param cls closure (NULL for dht) * @param client identification of the client; NULL * for the last call when the server is destroyed */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ClientList *pos; struct PendingMessage *reply; struct ClientMonitorRecord *monitor; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Local client %p disconnects\n", client); pos = find_active_client (client); GNUNET_CONTAINER_DLL_remove (client_head, client_tail, pos); if (pos->transmit_handle != NULL) GNUNET_SERVER_notify_transmit_ready_cancel (pos->transmit_handle); while (NULL != (reply = pos->pending_head)) { GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, reply); GNUNET_free (reply); } monitor = monitor_head; while (NULL != monitor) { if (monitor->client == pos) { struct ClientMonitorRecord *next; GNUNET_free_non_null (monitor->key); next = monitor->next; GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, monitor); GNUNET_free (monitor); monitor = next; } else monitor = monitor->next; } GNUNET_CONTAINER_multihashmap_iterate (forward_map, &remove_client_records, pos); GNUNET_free (pos); } /** * Route the given request via the DHT. This includes updating * the bloom filter and retransmission times, building the P2P * message and initiating the routing operation. */ static void transmit_request (struct ClientQueryRecord *cqr) { int32_t reply_bf_mutator; struct GNUNET_CONTAINER_BloomFilter *reply_bf; struct GNUNET_CONTAINER_BloomFilter *peer_bf; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests from clients injected"), 1, GNUNET_NO); reply_bf_mutator = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); reply_bf = GNUNET_BLOCK_construct_bloomfilter (reply_bf_mutator, cqr->seen_replies, cqr->seen_replies_count); peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); LOG (GNUNET_ERROR_TYPE_DEBUG, "Initiating GET for %s, replication %u, already have %u replies\n", GNUNET_h2s (&cqr->key), cqr->replication, cqr->seen_replies_count); GDS_NEIGHBOURS_handle_get (cqr->type, cqr->msg_options, cqr->replication, 0 /* hop count */ , &cqr->key, cqr->xquery, cqr->xquery_size, reply_bf, reply_bf_mutator, peer_bf); GNUNET_CONTAINER_bloomfilter_free (reply_bf); GNUNET_CONTAINER_bloomfilter_free (peer_bf); /* exponential back-off for retries. * max GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */ cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency); cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency); } /** * Task that looks at the 'retry_heap' and transmits all of the requests * on the heap that are ready for transmission. Then re-schedules * itself (unless the heap is empty). * * @param cls unused * @param tc scheduler context */ static void transmit_next_request_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ClientQueryRecord *cqr; struct GNUNET_TIME_Relative delay; retry_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap))) { cqr->hnode = NULL; delay = GNUNET_TIME_absolute_get_remaining (cqr->retry_time); if (delay.rel_value_us > 0) { cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, cqr->retry_time.abs_value_us); retry_task = GNUNET_SCHEDULER_add_delayed (delay, &transmit_next_request_task, NULL); return; } transmit_request (cqr); cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, cqr->retry_time.abs_value_us); } } /** * Handler for PUT messages. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientPutMessage *dht_msg; struct GNUNET_CONTAINER_BloomFilter *peer_bf; uint16_t size; struct PendingMessage *pm; struct GNUNET_DHT_ClientPutConfirmationMessage *conf; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientPutMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# PUT requests received from clients"), 1, GNUNET_NO); dht_msg = (const struct GNUNET_DHT_ClientPutMessage *) message; LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-PUT %s\n", GNUNET_h2s_full (&dht_msg->key)); /* give to local clients */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Handling local PUT of %u-bytes for query %s\n", size - sizeof (struct GNUNET_DHT_ClientPutMessage), GNUNET_h2s (&dht_msg->key)); GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, 0, NULL, 0, NULL, ntohl (dht_msg->type), size - sizeof (struct GNUNET_DHT_ClientPutMessage), &dht_msg[1]); /* store locally */ GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, 0, NULL, ntohl (dht_msg->type), size - sizeof (struct GNUNET_DHT_ClientPutMessage), &dht_msg[1]); /* route to other peers */ peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); GDS_NEIGHBOURS_handle_put (ntohl (dht_msg->type), ntohl (dht_msg->options), ntohl (dht_msg->desired_replication_level), GNUNET_TIME_absolute_ntoh (dht_msg->expiration), 0 /* hop count */ , peer_bf, &dht_msg->key, 0, NULL, &dht_msg[1], size - sizeof (struct GNUNET_DHT_ClientPutMessage)); GDS_CLIENTS_process_put (ntohl (dht_msg->options), ntohl (dht_msg->type), 0, ntohl (dht_msg->desired_replication_level), 1, GDS_NEIGHBOURS_get_id(), GNUNET_TIME_absolute_ntoh (dht_msg->expiration), &dht_msg->key, &dht_msg[1], size - sizeof (struct GNUNET_DHT_ClientPutMessage)); GNUNET_CONTAINER_bloomfilter_free (peer_bf); pm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); conf = (struct GNUNET_DHT_ClientPutConfirmationMessage *) &pm[1]; conf->header.size = htons (sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); conf->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK); conf->reserved = htonl (0); conf->unique_id = dht_msg->unique_id; pm->msg = &conf->header; add_pending_message (find_active_client (client), pm); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handler for DHT GET messages from the client. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientGetMessage *get; struct ClientQueryRecord *cqr; size_t xquery_size; const char *xquery; uint16_t size; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientGetMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } xquery_size = size - sizeof (struct GNUNET_DHT_ClientGetMessage); get = (const struct GNUNET_DHT_ClientGetMessage *) message; xquery = (const char *) &get[1]; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests received from clients"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received GET request for %s from local client %p, xq: %.*s\n", GNUNET_h2s (&get->key), client, xquery_size, xquery); LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-GET %s\n", GNUNET_h2s_full (&get->key)); cqr = GNUNET_malloc (sizeof (struct ClientQueryRecord) + xquery_size); cqr->key = get->key; cqr->client = find_active_client (client); cqr->xquery = (void *) &cqr[1]; memcpy (&cqr[1], xquery, xquery_size); cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, 0); cqr->retry_frequency = GNUNET_TIME_UNIT_SECONDS; cqr->retry_time = GNUNET_TIME_absolute_get (); cqr->unique_id = get->unique_id; cqr->xquery_size = xquery_size; cqr->replication = ntohl (get->desired_replication_level); cqr->msg_options = ntohl (get->options); cqr->type = ntohl (get->type); // FIXME use cqr->key, set multihashmap create to GNUNET_YES GNUNET_CONTAINER_multihashmap_put (forward_map, &get->key, cqr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GDS_CLIENTS_process_get (ntohl (get->options), ntohl (get->type), 0, ntohl (get->desired_replication_level), 1, GDS_NEIGHBOURS_get_id(), &get->key); /* start remote requests */ if (GNUNET_SCHEDULER_NO_TASK != retry_task) GNUNET_SCHEDULER_cancel (retry_task); retry_task = GNUNET_SCHEDULER_add_now (&transmit_next_request_task, NULL); /* perform local lookup */ GDS_DATACACHE_handle_get (&get->key, cqr->type, cqr->xquery, xquery_size, NULL, 0); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Closure for 'find_by_unique_id'. */ struct FindByUniqueIdContext { /** * Where to store the result, if found. */ struct ClientQueryRecord *cqr; uint64_t unique_id; }; /** * Function called for each existing DHT record for the given * query. Checks if it matches the UID given in the closure * and if so returns the entry as a result. * * @param cls the search context * @param key query for the lookup (not used) * @param value the 'struct ClientQueryRecord' * @return GNUNET_YES to continue iteration (result not yet found) */ static int find_by_unique_id (void *cls, const struct GNUNET_HashCode *key, void *value) { struct FindByUniqueIdContext *fui_ctx = cls; struct ClientQueryRecord *cqr = value; if (cqr->unique_id != fui_ctx->unique_id) return GNUNET_YES; fui_ctx->cqr = cqr; return GNUNET_NO; } /** * Handler for "GET result seen" messages from the client. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_get_result_seen (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientGetResultSeenMessage *seen; uint16_t size; unsigned int hash_count; unsigned int old_count; const struct GNUNET_HashCode *hc; struct FindByUniqueIdContext fui_ctx; struct ClientQueryRecord *cqr; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } seen = (const struct GNUNET_DHT_ClientGetResultSeenMessage *) message; hash_count = (size - sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) / sizeof (struct GNUNET_HashCode); if (size != sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage) + hash_count * sizeof (struct GNUNET_HashCode)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } hc = (const struct GNUNET_HashCode*) &seen[1]; fui_ctx.unique_id = seen->unique_id; fui_ctx.cqr = NULL; GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &seen->key, &find_by_unique_id, &fui_ctx); if (NULL == (cqr = fui_ctx.cqr)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* finally, update 'seen' list */ old_count = cqr->seen_replies_count; GNUNET_array_grow (cqr->seen_replies, cqr->seen_replies_count, cqr->seen_replies_count + hash_count); memcpy (&cqr->seen_replies[old_count], hc, sizeof (struct GNUNET_HashCode) * hash_count); } /** * Closure for 'remove_by_unique_id'. */ struct RemoveByUniqueIdContext { /** * Client that issued the removal request. */ struct ClientList *client; /** * Unique ID of the request. */ uint64_t unique_id; }; /** * Iterator over hash map entries that frees all entries * that match the given client and unique ID. * * @param cls unique ID and client to search for in source routes * @param key current key code * @param value value in the hash map, a ClientQueryRecord * @return GNUNET_YES (we should continue to iterate) */ static int remove_by_unique_id (void *cls, const struct GNUNET_HashCode * key, void *value) { const struct RemoveByUniqueIdContext *ctx = cls; struct ClientQueryRecord *record = value; if (record->unique_id != ctx->unique_id) return GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing client %p's record for key %s (by unique id)\n", ctx->client->client_handle, GNUNET_h2s (key)); return remove_client_records (ctx->client, key, record); } /** * Handler for any generic DHT stop messages, calls the appropriate handler * depending on message type (if processed locally) * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received * */ static void handle_dht_local_get_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg = (const struct GNUNET_DHT_ClientGetStopMessage *) message; struct RemoveByUniqueIdContext ctx; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET STOP requests received from clients"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received GET STOP request for %s from local client %p\n", client, GNUNET_h2s (&dht_stop_msg->key)); ctx.client = find_active_client (client); ctx.unique_id = dht_stop_msg->unique_id; GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &dht_stop_msg->key, &remove_by_unique_id, &ctx); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handler for monitor start messages * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received * */ static void handle_dht_local_monitor (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct ClientMonitorRecord *r; const struct GNUNET_DHT_MonitorStartStopMessage *msg; msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message; r = GNUNET_new (struct ClientMonitorRecord); r->client = find_active_client(client); r->type = ntohl(msg->type); r->get = ntohs(msg->get); r->get_resp = ntohs(msg->get_resp); r->put = ntohs(msg->put); if (0 == ntohs(msg->filter_key)) r->key = NULL; else { r->key = GNUNET_new (struct GNUNET_HashCode); memcpy (r->key, &msg->key, sizeof (struct GNUNET_HashCode)); } GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, r); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handler for monitor stop messages * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received * */ static void handle_dht_local_monitor_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct ClientMonitorRecord *r; const struct GNUNET_DHT_MonitorStartStopMessage *msg; int keys_match; msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message; r = monitor_head; while (NULL != r) { if (NULL == r->key) keys_match = (0 == ntohs(msg->filter_key)); else { keys_match = (0 != ntohs(msg->filter_key) && !memcmp(r->key, &msg->key, sizeof(struct GNUNET_HashCode))); } if (find_active_client(client) == r->client && ntohl(msg->type) == r->type && r->get == msg->get && r->get_resp == msg->get_resp && r->put == msg->put && keys_match ) { GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, r); GNUNET_free_non_null (r->key); GNUNET_free (r); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; /* Delete only ONE entry */ } r = r->next; } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Callback called as a result of issuing a GNUNET_SERVER_notify_transmit_ready * request. A ClientList is passed as closure, take the head of the list * and copy it into buf, which has the result of sending the message to the * client. * * @param cls closure to this call * @param size maximum number of bytes available to send * @param buf where to copy the actual message to * * @return the number of bytes actually copied, 0 indicates failure */ static size_t send_reply_to_client (void *cls, size_t size, void *buf) { struct ClientList *client = cls; char *cbuf = buf; struct PendingMessage *reply; size_t off; size_t msize; client->transmit_handle = NULL; if (buf == NULL) { /* client disconnected */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected, pending messages will be discarded\n", client->client_handle); return 0; } off = 0; while ((NULL != (reply = client->pending_head)) && (size >= off + (msize = ntohs (reply->msg->size)))) { GNUNET_CONTAINER_DLL_remove (client->pending_head, client->pending_tail, reply); memcpy (&cbuf[off], reply->msg, msize); GNUNET_free (reply); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes to client %p\n", msize, client->client_handle); off += msize; } process_pending_messages (client); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %u/%u bytes to client %p\n", (unsigned int) off, (unsigned int) size, client->client_handle); return off; } /** * Task run to check for messages that need to be sent to a client. * * @param client a ClientList, containing the client and any messages to be sent to it */ static void process_pending_messages (struct ClientList *client) { if ((client->pending_head == NULL) || (client->transmit_handle != NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not asking for transmission to %p now: %s\n", client->client_handle, client->pending_head == NULL ? "no more messages" : "request already pending"); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking for transmission of %u bytes to client %p\n", ntohs (client->pending_head->msg->size), client->client_handle); client->transmit_handle = GNUNET_SERVER_notify_transmit_ready (client->client_handle, ntohs (client->pending_head-> msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &send_reply_to_client, client); } /** * Closure for 'forward_reply' */ struct ForwardReplyContext { /** * Actual message to send to matching clients. */ struct PendingMessage *pm; /** * Embedded payload. */ const void *data; /** * Type of the data. */ enum GNUNET_BLOCK_Type type; /** * Number of bytes in data. */ size_t data_size; /** * Do we need to copy 'pm' because it was already used? */ int do_copy; }; /** * Iterator over hash map entries that send a given reply to * each of the matching clients. With some tricky recycling * of the buffer. * * @param cls the 'struct ForwardReplyContext' * @param key current key * @param value value in the hash map, a ClientQueryRecord * @return GNUNET_YES (we should continue to iterate), * if the result is mal-formed, GNUNET_NO */ static int forward_reply (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ForwardReplyContext *frc = cls; struct ClientQueryRecord *record = value; struct PendingMessage *pm; struct GNUNET_DHT_ClientResultMessage *reply; enum GNUNET_BLOCK_EvaluationResult eval; int do_free; struct GNUNET_HashCode ch; unsigned int i; LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-RESULT %s\n", GNUNET_h2s_full (key)); if ((record->type != GNUNET_BLOCK_TYPE_ANY) && (record->type != frc->type)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Record type missmatch, not passing request for key %s to local client\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Key match, type mismatches in REPLY to CLIENT"), 1, GNUNET_NO); return GNUNET_YES; /* type mismatch */ } GNUNET_CRYPTO_hash (frc->data, frc->data_size, &ch); for (i = 0; i < record->seen_replies_count; i++) if (0 == memcmp (&record->seen_replies[i], &ch, sizeof (struct GNUNET_HashCode))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Duplicate reply, not passing request for key %s to local client\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Duplicate REPLIES to CLIENT request dropped"), 1, GNUNET_NO); return GNUNET_YES; /* duplicate */ } eval = GNUNET_BLOCK_evaluate (GDS_block_context, record->type, key, NULL, 0, record->xquery, record->xquery_size, frc->data, frc->data_size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Evaluation result is %d for key %s for local client's query\n", (int) eval, GNUNET_h2s (key)); switch (eval) { case GNUNET_BLOCK_EVALUATION_OK_LAST: do_free = GNUNET_YES; break; case GNUNET_BLOCK_EVALUATION_OK_MORE: GNUNET_array_append (record->seen_replies, record->seen_replies_count, ch); do_free = GNUNET_NO; break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: /* should be impossible to encounter here */ GNUNET_break (0); return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: GNUNET_break_op (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: GNUNET_break (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: GNUNET_break (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Unsupported block type (%u) in request!\n"), record->type); return GNUNET_NO; default: GNUNET_break (0); return GNUNET_NO; } if (GNUNET_NO == frc->do_copy) { /* first time, we can use the original data */ pm = frc->pm; frc->do_copy = GNUNET_YES; } else { /* two clients waiting for same reply, must copy for queueing */ pm = GNUNET_malloc (sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size)); memcpy (pm, frc->pm, sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size)); pm->next = pm->prev = NULL; pm->msg = (struct GNUNET_MessageHeader *) &pm[1]; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# RESULTS queued for clients"), 1, GNUNET_NO); reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1]; reply->unique_id = record->unique_id; LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing reply to query %s for client %p\n", GNUNET_h2s (key), record->client->client_handle); add_pending_message (record->client, pm); if (GNUNET_YES == do_free) remove_client_records (record->client, key, record); return GNUNET_YES; } /** * Handle a reply we've received from another peer. If the reply * matches any of our pending queries, forward it to the respective * client(s). * * @param expiration when will the reply expire * @param key the query this reply is for * @param get_path_length number of peers in @a get_path * @param get_path path the reply took on get * @param put_path_length number of peers in @a put_path * @param put_path path the reply took on put * @param type type of the reply * @param data_size number of bytes in @a data * @param data application payload data */ void GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode *key, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data) { struct ForwardReplyContext frc; struct PendingMessage *pm; struct GNUNET_DHT_ClientResultMessage *reply; struct GNUNET_PeerIdentity *paths; size_t msize; LOG (GNUNET_ERROR_TYPE_DEBUG, "reply for key %s\n", GNUNET_h2s (key)); if (NULL == GNUNET_CONTAINER_multihashmap_get (forward_map, key)) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# REPLIES ignored for CLIENTS (no match)"), 1, GNUNET_NO); return; /* no matching request, fast exit! */ } msize = sizeof (struct GNUNET_DHT_ClientResultMessage) + data_size + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Could not pass reply to client, message too big!\n")); return; } pm = GNUNET_malloc (msize + sizeof (struct PendingMessage)); reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1]; pm->msg = &reply->header; reply->header.size = htons ((uint16_t) msize); reply->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT); reply->type = htonl (type); reply->get_path_length = htonl (get_path_length); reply->put_path_length = htonl (put_path_length); reply->unique_id = 0; /* filled in later */ reply->expiration = GNUNET_TIME_absolute_hton (expiration); reply->key = *key; paths = (struct GNUNET_PeerIdentity *) &reply[1]; memcpy (paths, put_path, sizeof (struct GNUNET_PeerIdentity) * put_path_length); memcpy (&paths[put_path_length], get_path, sizeof (struct GNUNET_PeerIdentity) * get_path_length); memcpy (&paths[get_path_length + put_path_length], data, data_size); frc.do_copy = GNUNET_NO; frc.pm = pm; frc.data = data; frc.data_size = data_size; frc.type = type; GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, key, &forward_reply, &frc); if (GNUNET_NO == frc.do_copy) { /* did not match any of the requests, free! */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# REPLIES ignored for CLIENTS (no match)"), 1, GNUNET_NO); GNUNET_free (pm); } } /** * Check if some client is monitoring GET messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the GET path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param key Key of the requested data. */ void GDS_CLIENTS_process_get (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode * key) { struct ClientMonitorRecord *m; struct ClientList **cl; unsigned int cl_size; cl = NULL; cl_size = 0; for (m = monitor_head; NULL != m; m = m->next) { if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) && (NULL == m->key || memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0)) { struct PendingMessage *pm; struct GNUNET_DHT_MonitorGetMessage *mmsg; struct GNUNET_PeerIdentity *msg_path; size_t msize; unsigned int i; /* Don't send duplicates */ for (i = 0; i < cl_size; i++) if (cl[i] == m->client) break; if (i < cl_size) continue; GNUNET_array_append (cl, cl_size, m->client); msize = path_length * sizeof (struct GNUNET_PeerIdentity); msize += sizeof (struct GNUNET_DHT_MonitorGetMessage); msize += sizeof (struct PendingMessage); pm = GNUNET_malloc (msize); mmsg = (struct GNUNET_DHT_MonitorGetMessage *) &pm[1]; pm->msg = &mmsg->header; mmsg->header.size = htons (msize - sizeof (struct PendingMessage)); mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET); mmsg->options = htonl(options); mmsg->type = htonl(type); mmsg->hop_count = htonl(hop_count); mmsg->desired_replication_level = htonl(desired_replication_level); mmsg->get_path_length = htonl(path_length); memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode)); msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; if (path_length > 0) memcpy (msg_path, path, path_length * sizeof (struct GNUNET_PeerIdentity)); add_pending_message (m->client, pm); } } GNUNET_free_non_null (cl); } /** * Check if some client is monitoring GET RESP messages and notify * them in that case. * * @param type The type of data in the result. * @param get_path Peers on GET path (or NULL if not recorded). * @param get_path_length number of entries in get_path. * @param put_path peers on the PUT path (or NULL if not recorded). * @param put_path_length number of entries in get_path. * @param exp Expiration time of the data. * @param key Key of the data. * @param data Pointer to the result data. * @param size Number of bytes in data. */ void GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size) { struct ClientMonitorRecord *m; struct ClientList **cl; unsigned int cl_size; cl = NULL; cl_size = 0; for (m = monitor_head; NULL != m; m = m->next) { if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) && (NULL == m->key || memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0)) { struct PendingMessage *pm; struct GNUNET_DHT_MonitorGetRespMessage *mmsg; struct GNUNET_PeerIdentity *path; size_t msize; unsigned int i; /* Don't send duplicates */ for (i = 0; i < cl_size; i++) if (cl[i] == m->client) break; if (i < cl_size) continue; GNUNET_array_append (cl, cl_size, m->client); msize = size; msize += (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity); msize += sizeof (struct GNUNET_DHT_MonitorGetRespMessage); msize += sizeof (struct PendingMessage); pm = GNUNET_malloc (msize); mmsg = (struct GNUNET_DHT_MonitorGetRespMessage *) &pm[1]; pm->msg = (struct GNUNET_MessageHeader *) mmsg; mmsg->header.size = htons (msize - sizeof (struct PendingMessage)); mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP); mmsg->type = htonl(type); mmsg->put_path_length = htonl(put_path_length); mmsg->get_path_length = htonl(get_path_length); path = (struct GNUNET_PeerIdentity *) &mmsg[1]; if (put_path_length > 0) { memcpy (path, put_path, put_path_length * sizeof (struct GNUNET_PeerIdentity)); path = &path[put_path_length]; } if (get_path_length > 0) memcpy (path, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); mmsg->expiration_time = GNUNET_TIME_absolute_hton(exp); memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode)); if (size > 0) memcpy (&path[get_path_length], data, size); add_pending_message (m->client, pm); } } GNUNET_free_non_null (cl); } /** * Check if some client is monitoring PUT messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the PUT path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param exp Expiration time of the data. * @param key Key under which data is to be stored. * @param data Pointer to the data carried. * @param size Number of bytes in data. */ void GDS_CLIENTS_process_put (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size) { struct ClientMonitorRecord *m; struct ClientList **cl; unsigned int cl_size; cl = NULL; cl_size = 0; for (m = monitor_head; NULL != m; m = m->next) { if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) && (NULL == m->key || memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0)) { struct PendingMessage *pm; struct GNUNET_DHT_MonitorPutMessage *mmsg; struct GNUNET_PeerIdentity *msg_path; size_t msize; unsigned int i; /* Don't send duplicates */ for (i = 0; i < cl_size; i++) if (cl[i] == m->client) break; if (i < cl_size) continue; GNUNET_array_append (cl, cl_size, m->client); msize = size; msize += path_length * sizeof (struct GNUNET_PeerIdentity); msize += sizeof (struct GNUNET_DHT_MonitorPutMessage); msize += sizeof (struct PendingMessage); pm = GNUNET_malloc (msize); mmsg = (struct GNUNET_DHT_MonitorPutMessage *) &pm[1]; pm->msg = (struct GNUNET_MessageHeader *) mmsg; mmsg->header.size = htons (msize - sizeof (struct PendingMessage)); mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT); mmsg->options = htonl(options); mmsg->type = htonl(type); mmsg->hop_count = htonl(hop_count); mmsg->desired_replication_level = htonl(desired_replication_level); mmsg->put_path_length = htonl(path_length); msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; if (path_length > 0) { memcpy (msg_path, path, path_length * sizeof (struct GNUNET_PeerIdentity)); } mmsg->expiration_time = GNUNET_TIME_absolute_hton(exp); memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode)); if (size > 0) memcpy (&msg_path[path_length], data, size); add_pending_message (m->client, pm); } } GNUNET_free_non_null (cl); } /** * Initialize client subsystem. * * @param server the initialized server */ void GDS_CLIENTS_init (struct GNUNET_SERVER_Handle *server) { static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = { {&handle_dht_local_put, NULL, GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT, 0}, {&handle_dht_local_get, NULL, GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET, 0}, {&handle_dht_local_get_stop, NULL, GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP, sizeof (struct GNUNET_DHT_ClientGetStopMessage)}, {&handle_dht_local_monitor, NULL, GNUNET_MESSAGE_TYPE_DHT_MONITOR_START, sizeof (struct GNUNET_DHT_MonitorStartStopMessage)}, {&handle_dht_local_monitor_stop, NULL, GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP, sizeof (struct GNUNET_DHT_MonitorStartStopMessage)}, {&handle_dht_local_get_result_seen, NULL, GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, 0}, {NULL, NULL, 0, 0} }; forward_map = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); retry_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); GNUNET_SERVER_add_handlers (server, plugin_handlers); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); } /** * Shutdown client subsystem. */ void GDS_CLIENTS_done () { GNUNET_assert (client_head == NULL); GNUNET_assert (client_tail == NULL); if (GNUNET_SCHEDULER_NO_TASK != retry_task) { GNUNET_SCHEDULER_cancel (retry_task); retry_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != retry_heap) { GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (retry_heap)); GNUNET_CONTAINER_heap_destroy (retry_heap); retry_heap = NULL; } if (NULL != forward_map) { GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (forward_map)); GNUNET_CONTAINER_multihashmap_destroy (forward_map); forward_map = NULL; } } /* end of gnunet-service-dht_clients.c */ gnunet-0.10.1/src/dht/gnunet-service-dht_datacache.h0000644000175000017500000000541512225777503017240 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_datacache.h * @brief GNUnet DHT service's datacache integration * @author Christian Grothoff * @author Nathan Evans */ #ifndef GNUNET_SERVICE_DHT_DATACACHE_H #define GNUNET_SERVICE_DHT_DATACACHE_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" /** * Handle a datum we've received from another peer. Cache if * possible. * * @param expiration when will the reply expire * @param key the query this reply is for * @param put_path_length number of peers in 'put_path' * @param put_path path the reply took on put * @param type type of the reply * @param data_size number of bytes in 'data' * @param data application payload data */ void GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data); /** * Handle a GET request we've received from another peer. * * @param key the query * @param type requested data type * @param xquery extended query * @param xquery_size number of bytes in xquery * @param reply_bf where the reply bf is (to be) stored, possibly updated!, can be NULL * @param reply_bf_mutator mutation value for reply_bf * @return evaluation result for the local replies */ enum GNUNET_BLOCK_EvaluationResult GDS_DATACACHE_handle_get (const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_CONTAINER_BloomFilter **reply_bf, uint32_t reply_bf_mutator); /** * Initialize datacache subsystem. */ void GDS_DATACACHE_init (void); /** * Shutdown datacache subsystem. */ void GDS_DATACACHE_done (void); #endif gnunet-0.10.1/src/dht/gnunet-service-dht_routing.h0000644000175000017500000000630712225777503017033 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_routing.h * @brief GNUnet DHT tracking of requests for routing replies * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_DHT_ROUTING_H #define GNUNET_SERVICE_DHT_ROUTING_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_dht_service.h" /** * Handle a reply (route to origin). Only forwards the reply back to * other peers waiting for it. Does not do local caching or * forwarding to local clients. Essentially calls * GDS_NEIGHBOURS_handle_reply for all peers that sent us a matching * request recently. * * @param type type of the block * @param expiration_time when does the content expire * @param key key for the content * @param put_path_length number of entries in @a put_path * @param put_path peers the original PUT traversed (if tracked) * @param get_path_length number of entries in @a get_path * @param get_path peers this reply has traversed so far (if tracked) * @param data payload of the reply * @param data_size number of bytes in @a data */ void GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size); /** * Add a new entry to our routing table. * * @param sender peer that originated the request * @param type type of the block * @param options options for processing * @param key key for the content * @param xquery extended query * @param xquery_size number of bytes in @a xquery * @param reply_bf bloomfilter to filter duplicates * @param reply_bf_mutator mutator for @a reply_bf */ void GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender, enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, const struct GNUNET_HashCode * key, const void *xquery, size_t xquery_size, const struct GNUNET_CONTAINER_BloomFilter *reply_bf, uint32_t reply_bf_mutator); /** * Initialize routing subsystem. */ void GDS_ROUTING_init (void); /** * Shutdown routing subsystem. */ void GDS_ROUTING_done (void); #endif gnunet-0.10.1/src/dht/gnunet-service-dht_nse.c0000644000175000017500000000570412225777502016123 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_nse.c * @brief GNUnet DHT integration with NSE * @author Christian Grothoff */ #include "platform.h" #include "gnunet_nse_service.h" #include "gnunet-service-dht.h" #include "gnunet-service-dht_nse.h" /** * log of the current network size estimate, used as the point where * we switch between random and deterministic routing. Default * value of 4.0 is used if NSE module is not available (i.e. not * configured). */ static double log_of_network_size_estimate = 4.0; /** * Network size estimation handle. */ static struct GNUNET_NSE_Handle *nse; /** * Callback that is called when network size estimate is updated. * * @param cls closure * @param timestamp time when the estimate was received from the server (or created by the server) * @param logestimate the log(Base 2) value of the current network size estimate * @param std_dev standard deviation for the estimate * */ static void update_network_size_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, double logestimate, double std_dev) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Network size estimates received"), 1, GNUNET_NO); /* do not allow estimates < 0.5 */ log_of_network_size_estimate = GNUNET_MAX (0.5, logestimate); } /** * Return the log of the current network size estimate. * * @return log of NSE */ double GDS_NSE_get () { return log_of_network_size_estimate; } /** * Initialize NSE subsystem. */ void GDS_NSE_init () { unsigned long long hops; if ( (GNUNET_YES == GNUNET_CONFIGURATION_have_value (GDS_cfg, "dht", "FORCE_NSE")) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GDS_cfg, "dht", "FORCE_NSE", &hops)) ) { log_of_network_size_estimate = (double) hops; return; } nse = GNUNET_NSE_connect (GDS_cfg, &update_network_size_estimate, NULL); } /** * Shutdown NSE subsystem. */ void GDS_NSE_done () { if (NULL != nse) { GNUNET_NSE_disconnect (nse); nse = NULL; } } /* end of gnunet-service-dht_nse.c */ gnunet-0.10.1/src/dht/test_dht_multipeer.conf0000644000175000017500000000126612225230043016131 00000000000000[fs] AUTOSTART = NO [resolver] AUTOSTART = NO [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = tcp [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [arm] DEFAULTSERVICES = dht core [TESTING] WEAKRANDOM = YES [testbed] OVERLAY_TOPOLOGY = FROM_FILE OVERLAY_TOPOLOGY_FILE = test_dht_multipeer_topology.dat [gnunetd] HOSTKEY = $GNUNET_TEST_HOME/.hostkey [PATHS] GNUNET_TEST_HOME = /tmp/test-dht-multipeer/ [nat] DISABLEV6 = YES RETURN_LOCAL_ADDRESSES = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 USE_LOCALADDR = YES [dns] AUTOSTART = NO [namestore] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART=NO gnunet-0.10.1/src/dht/gnunet-service-xdht_clients.c0000644000175000017500000012632112320724374017161 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_clients.c * @brief GNUnet DHT service's client management code * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet-service-xdht.h" #include "gnunet-service-xdht_clients.h" #include "gnunet-service-xdht_datacache.h" #include "gnunet-service-xdht_neighbours.h" #include "dht.h" /** * Should routing details be logged to stderr (for debugging)? */ #define LOG_TRAFFIC(kind,...) GNUNET_log_from (kind, "dht-traffic",__VA_ARGS__) #define LOG(kind,...) GNUNET_log_from (kind, "dht-clients",__VA_ARGS__) /** * Linked list of messages to send to clients. */ struct PendingMessage { /** * Pointer to next item in the list */ struct PendingMessage *next; /** * Pointer to previous item in the list */ struct PendingMessage *prev; /** * Actual message to be sent, allocated at the end of the struct: * // msg = (cast) &pm[1]; * // memcpy (&pm[1], data, len); */ const struct GNUNET_MessageHeader *msg; }; /** * Struct containing information about a client, * handle to connect to it, and any pending messages * that need to be sent to it. */ struct ClientList { /** * Linked list of active clients */ struct ClientList *next; /** * Linked list of active clients */ struct ClientList *prev; /** * The handle to this client */ struct GNUNET_SERVER_Client *client_handle; /** * Handle to the current transmission request, NULL * if none pending. */ struct GNUNET_SERVER_TransmitHandle *transmit_handle; /** * Linked list of pending messages for this client */ struct PendingMessage *pending_head; /** * Tail of linked list of pending messages for this client */ struct PendingMessage *pending_tail; }; /** * Entry in the local forwarding map for a client's GET request. */ struct ClientQueryRecord { /** * The key this request was about */ struct GNUNET_HashCode key; /** * Client responsible for the request. */ struct ClientList *client; /** * Extended query (see gnunet_block_lib.h), allocated at the end of this struct. */ const void *xquery; /** * Replies we have already seen for this request. */ struct GNUNET_HashCode *seen_replies; /** * Pointer to this nodes heap location in the retry-heap (for fast removal) */ struct GNUNET_CONTAINER_HeapNode *hnode; /** * What's the delay between re-try operations that we currently use for this * request? */ struct GNUNET_TIME_Relative retry_frequency; /** * What's the next time we should re-try this request? */ struct GNUNET_TIME_Absolute retry_time; /** * The unique identifier of this request */ uint64_t unique_id; /** * Number of bytes in xquery. */ size_t xquery_size; /** * Number of entries in 'seen_replies'. */ unsigned int seen_replies_count; /** * Desired replication level */ uint32_t replication; /** * Any message options for this request */ uint32_t msg_options; /** * The type for the data for the GET request. */ enum GNUNET_BLOCK_Type type; }; /** * Struct containing paremeters of monitoring requests. */ struct ClientMonitorRecord { /** * Next element in DLL. */ struct ClientMonitorRecord *next; /** * Previous element in DLL. */ struct ClientMonitorRecord *prev; /** * Type of blocks that are of interest */ enum GNUNET_BLOCK_Type type; /** * Key of data of interest, NULL for all. */ struct GNUNET_HashCode *key; /** * Flag whether to notify about GET messages. */ int16_t get; /** * Flag whether to notify about GET_REPONSE messages. */ int16_t get_resp; /** * Flag whether to notify about PUT messages. */ uint16_t put; /** * Client to notify of these requests. */ struct ClientList *client; }; /** * List of active clients. */ static struct ClientList *client_head; /** * List of active clients. */ static struct ClientList *client_tail; /** * List of active monitoring requests. */ static struct ClientMonitorRecord *monitor_head; /** * List of active monitoring requests. */ static struct ClientMonitorRecord *monitor_tail; /** * Hashmap for fast key based lookup, maps keys to `struct ClientQueryRecord` entries. */ static struct GNUNET_CONTAINER_MultiHashMap *forward_map; /** * Heap with all of our client's request, sorted by retry time (earliest on top). */ static struct GNUNET_CONTAINER_Heap *retry_heap; /** * Task that re-transmits requests (using retry_heap). */ static GNUNET_SCHEDULER_TaskIdentifier retry_task; /** * Task run to check for messages that need to be sent to a client. * * @param client a ClientList, containing the client and any messages to be sent to it */ static void process_pending_messages (struct ClientList *client); /** * Callback called as a result of issuing a GNUNET_SERVER_notify_transmit_ready * request. A ClientList is passed as closure, take the head of the list * and copy it into buf, which has the result of sending the message to the * client. * * @param cls closure to this call * @param size maximum number of bytes available to send * @param buf where to copy the actual message to * * @return the number of bytes actually copied, 0 indicates failure */ static size_t send_reply_to_client (void *cls, size_t size, void *buf) { struct ClientList *client = cls; char *cbuf = buf; struct PendingMessage *reply; size_t off; size_t msize; client->transmit_handle = NULL; if (buf == NULL) { /* client disconnected */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected, pending messages will be discarded\n", client->client_handle); return 0; } off = 0; while ((NULL != (reply = client->pending_head)) && (size >= off + (msize = ntohs (reply->msg->size)))) { GNUNET_CONTAINER_DLL_remove (client->pending_head, client->pending_tail, reply); memcpy (&cbuf[off], reply->msg, msize); GNUNET_free (reply); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes to client %p\n", msize, client->client_handle); off += msize; } process_pending_messages (client); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %u/%u bytes to client %p\n", (unsigned int) off, (unsigned int) size, client->client_handle); return off; } /** * Task run to check for messages that need to be sent to a client. * * @param client a ClientList, containing the client and any messages to be sent to it */ static void process_pending_messages (struct ClientList *client) { if ((client->pending_head == NULL) || (client->transmit_handle != NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not asking for transmission to %p now: %s\n", client->client_handle, client->pending_head == NULL ? "no more messages" : "request already pending"); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking for transmission of %u bytes to client %p\n", ntohs (client->pending_head->msg->size), client->client_handle); client->transmit_handle = GNUNET_SERVER_notify_transmit_ready (client->client_handle, ntohs (client->pending_head-> msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &send_reply_to_client, client); } /** * Add a PendingMessage to the clients list of messages to be sent * * @param client the active client to send the message to * @param pending_message the actual message to send */ static void add_pending_message (struct ClientList *client, struct PendingMessage *pending_message) { GNUNET_CONTAINER_DLL_insert_tail (client->pending_head, client->pending_tail, pending_message); process_pending_messages (client); } /** * Closure for 'forward_reply' */ struct ForwardReplyContext { /** * Actual message to send to matching clients. */ struct PendingMessage *pm; /** * Embedded payload. */ const void *data; /** * Type of the data. */ enum GNUNET_BLOCK_Type type; /** * Number of bytes in data. */ size_t data_size; /** * Do we need to copy 'pm' because it was already used? */ int do_copy; }; /** * Find a client if it exists, add it otherwise. * * @param client the server handle to the client * * @return the client if found, a new client otherwise */ static struct ClientList * find_active_client (struct GNUNET_SERVER_Client *client) { struct ClientList *pos = client_head; struct ClientList *ret; while (pos != NULL) { if (pos->client_handle == client) return pos; pos = pos->next; } ret = GNUNET_new (struct ClientList); ret->client_handle = client; GNUNET_CONTAINER_DLL_insert (client_head, client_tail, ret); return ret; } /** * Iterator over hash map entries that frees all entries * associated with the given client. * * @param cls client to search for in source routes * @param key current key code (ignored) * @param value value in the hash map, a ClientQueryRecord * @return #GNUNET_YES (we should continue to iterate) */ static int remove_client_records (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ClientList *client = cls; struct ClientQueryRecord *record = value; if (record->client != client) return GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing client %p's record for key %s\n", client, GNUNET_h2s (key)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (forward_map, key, record)); if (NULL != record->hnode) GNUNET_CONTAINER_heap_remove_node (record->hnode); GNUNET_array_grow (record->seen_replies, record->seen_replies_count, 0); GNUNET_free (record); return GNUNET_YES; } /** * Iterator over hash map entries that send a given reply to * each of the matching clients. With some tricky recycling * of the buffer. * * @param cls the 'struct ForwardReplyContext' * @param key current key * @param value value in the hash map, a ClientQueryRecord * @return GNUNET_YES (we should continue to iterate), * if the result is mal-formed, GNUNET_NO */ static int forward_reply (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ForwardReplyContext *frc = cls; struct ClientQueryRecord *record = value; struct PendingMessage *pm; struct GNUNET_DHT_ClientResultMessage *reply; enum GNUNET_BLOCK_EvaluationResult eval; int do_free; struct GNUNET_HashCode ch; unsigned int i; LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-RESULT %s\n", GNUNET_h2s_full (key)); if ((record->type != GNUNET_BLOCK_TYPE_ANY) && (record->type != frc->type)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Record type missmatch, not passing request for key %s to local client\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Key match, type mismatches in REPLY to CLIENT"), 1, GNUNET_NO); return GNUNET_YES; /* type mismatch */ } GNUNET_CRYPTO_hash (frc->data, frc->data_size, &ch); for (i = 0; i < record->seen_replies_count; i++) if (0 == memcmp (&record->seen_replies[i], &ch, sizeof (struct GNUNET_HashCode))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Duplicate reply, not passing request for key %s to local client\n", GNUNET_h2s (key)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Duplicate REPLIES to CLIENT request dropped"), 1, GNUNET_NO); return GNUNET_YES; /* duplicate */ } eval = GNUNET_BLOCK_evaluate (GDS_block_context, record->type, key, NULL, 0, record->xquery, record->xquery_size, frc->data, frc->data_size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Evaluation result is %d for key %s for local client's query\n", (int) eval, GNUNET_h2s (key)); switch (eval) { case GNUNET_BLOCK_EVALUATION_OK_LAST: do_free = GNUNET_YES; break; case GNUNET_BLOCK_EVALUATION_OK_MORE: GNUNET_array_append (record->seen_replies, record->seen_replies_count, ch); do_free = GNUNET_NO; break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: /* should be impossible to encounter here */ GNUNET_break (0); return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: GNUNET_break_op (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: GNUNET_break (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: GNUNET_break (0); return GNUNET_NO; case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: return GNUNET_YES; case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Unsupported block type (%u) in request!\n"), record->type); return GNUNET_NO; default: GNUNET_break (0); return GNUNET_NO; } if (GNUNET_NO == frc->do_copy) { /* first time, we can use the original data */ pm = frc->pm; frc->do_copy = GNUNET_YES; } else { /* two clients waiting for same reply, must copy for queueing */ pm = GNUNET_malloc (sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size)); memcpy (pm, frc->pm, sizeof (struct PendingMessage) + ntohs (frc->pm->msg->size)); pm->next = pm->prev = NULL; pm->msg = (struct GNUNET_MessageHeader *) &pm[1]; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# RESULTS queued for clients"), 1, GNUNET_NO); reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1]; reply->unique_id = record->unique_id; LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing reply to query %s for client %p\n", GNUNET_h2s (key), record->client->client_handle); add_pending_message (record->client, pm); if (GNUNET_YES == do_free) remove_client_records (record->client, key, record); return GNUNET_YES; } /** * Handle a reply we've received from another peer. If the reply * matches any of our pending queries, forward it to the respective * client(s). * * @param expiration when will the reply expire * @param key the query this reply is for * @param get_path_length number of peers in @a get_path * @param get_path path the reply took on get * @param put_path_length number of peers in @a put_path * @param put_path path the reply took on put * @param type type of the reply * @param data_size number of bytes in @a data * @param data application payload data */ void GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode *key, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data) { struct ForwardReplyContext frc; struct PendingMessage *pm; struct GNUNET_DHT_ClientResultMessage *reply; struct GNUNET_PeerIdentity *paths; size_t msize; LOG (GNUNET_ERROR_TYPE_DEBUG, "reply for key %s\n", GNUNET_h2s (key)); if (NULL == GNUNET_CONTAINER_multihashmap_get (forward_map, key)) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# REPLIES ignored for CLIENTS (no match)"), 1, GNUNET_NO); return; /* no matching request, fast exit! */ } msize = sizeof (struct GNUNET_DHT_ClientResultMessage) + data_size + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Could not pass reply to client, message too big!\n")); return; } pm = GNUNET_malloc (msize + sizeof (struct PendingMessage)); reply = (struct GNUNET_DHT_ClientResultMessage *) &pm[1]; pm->msg = &reply->header; reply->header.size = htons ((uint16_t) msize); reply->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT); reply->type = htonl (type); reply->get_path_length = htonl (get_path_length); reply->put_path_length = htonl (put_path_length); reply->unique_id = 0; /* filled in later */ reply->expiration = GNUNET_TIME_absolute_hton (expiration); reply->key = *key; paths = (struct GNUNET_PeerIdentity *) &reply[1]; memcpy (paths, put_path, sizeof (struct GNUNET_PeerIdentity) * put_path_length); memcpy (&paths[put_path_length], get_path, sizeof (struct GNUNET_PeerIdentity) * get_path_length); memcpy (&paths[get_path_length + put_path_length], data, data_size); frc.do_copy = GNUNET_NO; frc.pm = pm; frc.data = data; frc.data_size = data_size; frc.type = type; GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, key, &forward_reply, &frc); if (GNUNET_NO == frc.do_copy) { /* did not match any of the requests, free! */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# REPLIES ignored for CLIENTS (no match)"), 1, GNUNET_NO); GNUNET_free (pm); } } /** * Check if some client is monitoring GET messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the GET path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param key Key of the requested data. */ void GDS_CLIENTS_process_get (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode * key) { struct ClientMonitorRecord *m; struct ClientList **cl; unsigned int cl_size; cl = NULL; cl_size = 0; for (m = monitor_head; NULL != m; m = m->next) { if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) && (NULL == m->key || memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0)) { struct PendingMessage *pm; struct GNUNET_DHT_MonitorGetMessage *mmsg; struct GNUNET_PeerIdentity *msg_path; size_t msize; unsigned int i; /* Don't send duplicates */ for (i = 0; i < cl_size; i++) if (cl[i] == m->client) break; if (i < cl_size) continue; GNUNET_array_append (cl, cl_size, m->client); msize = path_length * sizeof (struct GNUNET_PeerIdentity); msize += sizeof (struct GNUNET_DHT_MonitorGetMessage); msize += sizeof (struct PendingMessage); pm = GNUNET_malloc (msize); mmsg = (struct GNUNET_DHT_MonitorGetMessage *) &pm[1]; pm->msg = &mmsg->header; mmsg->header.size = htons (msize - sizeof (struct PendingMessage)); mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET); mmsg->options = htonl(options); mmsg->type = htonl(type); mmsg->hop_count = htonl(hop_count); mmsg->desired_replication_level = htonl(desired_replication_level); mmsg->get_path_length = htonl(path_length); memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode)); msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; if (path_length > 0) memcpy (msg_path, path, path_length * sizeof (struct GNUNET_PeerIdentity)); add_pending_message (m->client, pm); } } GNUNET_free_non_null (cl); } /** * Check if some client is monitoring PUT messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the PUT path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param exp Expiration time of the data. * @param key Key under which data is to be stored. * @param data Pointer to the data carried. * @param size Number of bytes in data. */ void GDS_CLIENTS_process_put (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size) { struct ClientMonitorRecord *m; struct ClientList **cl; unsigned int cl_size; cl = NULL; cl_size = 0; for (m = monitor_head; NULL != m; m = m->next) { if ((GNUNET_BLOCK_TYPE_ANY == m->type || m->type == type) && (NULL == m->key || memcmp (key, m->key, sizeof(struct GNUNET_HashCode)) == 0)) { struct PendingMessage *pm; struct GNUNET_DHT_MonitorPutMessage *mmsg; struct GNUNET_PeerIdentity *msg_path; size_t msize; unsigned int i; /* Don't send duplicates */ for (i = 0; i < cl_size; i++) if (cl[i] == m->client) break; if (i < cl_size) continue; GNUNET_array_append (cl, cl_size, m->client); msize = size; msize += path_length * sizeof (struct GNUNET_PeerIdentity); msize += sizeof (struct GNUNET_DHT_MonitorPutMessage); msize += sizeof (struct PendingMessage); pm = GNUNET_malloc (msize); mmsg = (struct GNUNET_DHT_MonitorPutMessage *) &pm[1]; pm->msg = (struct GNUNET_MessageHeader *) mmsg; mmsg->header.size = htons (msize - sizeof (struct PendingMessage)); mmsg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT); mmsg->options = htonl(options); mmsg->type = htonl(type); mmsg->hop_count = htonl(hop_count); mmsg->desired_replication_level = htonl(desired_replication_level); mmsg->put_path_length = htonl(path_length); msg_path = (struct GNUNET_PeerIdentity *) &mmsg[1]; if (path_length > 0) { memcpy (msg_path, path, path_length * sizeof (struct GNUNET_PeerIdentity)); } mmsg->expiration_time = GNUNET_TIME_absolute_hton(exp); memcpy (&mmsg->key, key, sizeof (struct GNUNET_HashCode)); if (size > 0) memcpy (&msg_path[path_length], data, size); add_pending_message (m->client, pm); } } GNUNET_free_non_null (cl); } /** * Route the given request via the DHT. */ static void transmit_request (struct ClientQueryRecord *cqr) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests from clients injected"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Initiating GET for %s, replication %u, already have %u replies\n", GNUNET_h2s (&cqr->key), cqr->replication, cqr->seen_replies_count); #if 0 /* FIXME: Change it to your own handle_get. */ GDS_NEIGHBOURS_handle_get (cqr->type, cqr->msg_options, cqr->replication, 0 /* hop count */ , &cqr->key, cqr->xquery, cqr->xquery_size, reply_bf, reply_bf_mutator, peer_bf); #endif /* exponential back-off for retries. * max GNUNET_TIME_STD_EXPONENTIAL_BACKOFF_THRESHOLD (15 min) */ cqr->retry_frequency = GNUNET_TIME_STD_BACKOFF (cqr->retry_frequency); cqr->retry_time = GNUNET_TIME_relative_to_absolute (cqr->retry_frequency); } /** * Task that looks at the 'retry_heap' and transmits all of the requests * on the heap that are ready for transmission. Then re-schedules * itself (unless the heap is empty). * * @param cls unused * @param tc scheduler context */ static void transmit_next_request_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ClientQueryRecord *cqr; struct GNUNET_TIME_Relative delay; retry_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; while (NULL != (cqr = GNUNET_CONTAINER_heap_remove_root (retry_heap))) { cqr->hnode = NULL; delay = GNUNET_TIME_absolute_get_remaining (cqr->retry_time); if (delay.rel_value_us > 0) { cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, cqr->retry_time.abs_value_us); retry_task = GNUNET_SCHEDULER_add_delayed (delay, &transmit_next_request_task, NULL); return; } transmit_request (cqr); cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, cqr->retry_time.abs_value_us); } } /** * Handler for PUT messages. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_put (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientPutMessage *put_msg; struct PendingMessage *pm; struct GNUNET_DHT_ClientPutConfirmationMessage *conf; uint16_t size; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientPutMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# PUT requests received from clients"), 1, GNUNET_NO); put_msg = (const struct GNUNET_DHT_ClientPutMessage *) message; LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-PUT %s\n", GNUNET_h2s_full (&put_msg->key)); /* give to local clients */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Handling local PUT of %u-bytes for query %s\n", size - sizeof (struct GNUNET_DHT_ClientPutMessage), GNUNET_h2s (&put_msg->key)); GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (put_msg->expiration), &put_msg->key, 0, NULL, 0, NULL, ntohl (put_msg->type), size - sizeof (struct GNUNET_DHT_ClientPutMessage), &put_msg[1]); /* store locally */ GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put_msg->expiration), &put_msg->key, 0, NULL, ntohl (put_msg->type), size - sizeof (struct GNUNET_DHT_ClientPutMessage), &put_msg[1]); /* FIXME: At the moment we don't use replication in x-vine. But keep it for time being. Check all the fields again. */ GDS_NEIGHBOURS_handle_put (ntohl (put_msg->type), ntohl (put_msg->options), ntohl (put_msg->desired_replication_level), GNUNET_TIME_absolute_ntoh (put_msg->expiration), 0 /* hop count */ , &put_msg->key, 0, NULL, &put_msg[1], size - sizeof (struct GNUNET_DHT_ClientPutMessage), NULL, 0, NULL); GDS_CLIENTS_process_put (ntohl (put_msg->options), ntohl (put_msg->type), 0, ntohl (put_msg->desired_replication_level), 1, GDS_NEIGHBOURS_get_id(), GNUNET_TIME_absolute_ntoh (put_msg->expiration), &put_msg->key, &put_msg[1], size - sizeof (struct GNUNET_DHT_ClientPutMessage)); pm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); conf = (struct GNUNET_DHT_ClientPutConfirmationMessage *) &pm[1]; conf->header.size = htons (sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)); conf->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK); conf->reserved = htonl (0); conf->unique_id = put_msg->unique_id; pm->msg = &conf->header; add_pending_message (find_active_client (client), pm); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handler for DHT GET messages from the client. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientGetMessage *get; struct ClientQueryRecord *cqr; size_t xquery_size; const char *xquery; uint16_t size; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientGetMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } xquery_size = size - sizeof (struct GNUNET_DHT_ClientGetMessage); get = (const struct GNUNET_DHT_ClientGetMessage *) message; xquery = (const char *) &get[1]; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests received from clients"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received GET request for %s from local client %p, xq: %.*s\n", GNUNET_h2s (&get->key), client, xquery_size, xquery); LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N CLIENT-GET %s\n", GNUNET_h2s_full (&get->key)); cqr = GNUNET_malloc (sizeof (struct ClientQueryRecord) + xquery_size); cqr->key = get->key; cqr->client = find_active_client (client); cqr->xquery = (void *) &cqr[1]; memcpy (&cqr[1], xquery, xquery_size); cqr->hnode = GNUNET_CONTAINER_heap_insert (retry_heap, cqr, 0); cqr->retry_frequency = GNUNET_TIME_UNIT_SECONDS; cqr->retry_time = GNUNET_TIME_absolute_get (); cqr->unique_id = get->unique_id; cqr->xquery_size = xquery_size; cqr->replication = ntohl (get->desired_replication_level); cqr->msg_options = ntohl (get->options); cqr->type = ntohl (get->type); // FIXME use cqr->key, set multihashmap create to GNUNET_YES GNUNET_CONTAINER_multihashmap_put (forward_map, &get->key, cqr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GDS_CLIENTS_process_get (ntohl (get->options), ntohl (get->type), 0, ntohl (get->desired_replication_level), 1, GDS_NEIGHBOURS_get_id(), &get->key); /* start remote requests */ if (GNUNET_SCHEDULER_NO_TASK != retry_task) GNUNET_SCHEDULER_cancel (retry_task); retry_task = GNUNET_SCHEDULER_add_now (&transmit_next_request_task, NULL); /* perform local lookup */ GDS_DATACACHE_handle_get (&get->key, cqr->type, cqr->xquery, xquery_size, NULL, 0); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Closure for 'find_by_unique_id'. */ struct FindByUniqueIdContext { /** * Where to store the result, if found. */ struct ClientQueryRecord *cqr; uint64_t unique_id; }; /** * Function called for each existing DHT record for the given * query. Checks if it matches the UID given in the closure * and if so returns the entry as a result. * * @param cls the search context * @param key query for the lookup (not used) * @param value the 'struct ClientQueryRecord' * @return GNUNET_YES to continue iteration (result not yet found) */ static int find_by_unique_id (void *cls, const struct GNUNET_HashCode *key, void *value) { struct FindByUniqueIdContext *fui_ctx = cls; struct ClientQueryRecord *cqr = value; if (cqr->unique_id != fui_ctx->unique_id) return GNUNET_YES; fui_ctx->cqr = cqr; return GNUNET_NO; } /** * Handler for "GET result seen" messages from the client. * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received */ static void handle_dht_local_get_result_seen (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientGetResultSeenMessage *seen; uint16_t size; unsigned int hash_count; unsigned int old_count; const struct GNUNET_HashCode *hc; struct FindByUniqueIdContext fui_ctx; struct ClientQueryRecord *cqr; size = ntohs (message->size); if (size < sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } seen = (const struct GNUNET_DHT_ClientGetResultSeenMessage *) message; hash_count = (size - sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) / sizeof (struct GNUNET_HashCode); if (size != sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage) + hash_count * sizeof (struct GNUNET_HashCode)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } hc = (const struct GNUNET_HashCode*) &seen[1]; fui_ctx.unique_id = seen->unique_id; fui_ctx.cqr = NULL; GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &seen->key, &find_by_unique_id, &fui_ctx); if (NULL == (cqr = fui_ctx.cqr)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* finally, update 'seen' list */ old_count = cqr->seen_replies_count; GNUNET_array_grow (cqr->seen_replies, cqr->seen_replies_count, cqr->seen_replies_count + hash_count); memcpy (&cqr->seen_replies[old_count], hc, sizeof (struct GNUNET_HashCode) * hash_count); } /** * Closure for 'remove_by_unique_id'. */ struct RemoveByUniqueIdContext { /** * Client that issued the removal request. */ struct ClientList *client; /** * Unique ID of the request. */ uint64_t unique_id; }; /** * Iterator over hash map entries that frees all entries * that match the given client and unique ID. * * @param cls unique ID and client to search for in source routes * @param key current key code * @param value value in the hash map, a ClientQueryRecord * @return GNUNET_YES (we should continue to iterate) */ static int remove_by_unique_id (void *cls, const struct GNUNET_HashCode * key, void *value) { const struct RemoveByUniqueIdContext *ctx = cls; struct ClientQueryRecord *record = value; if (record->unique_id != ctx->unique_id) return GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing client %p's record for key %s (by unique id)\n", ctx->client->client_handle, GNUNET_h2s (key)); return remove_client_records (ctx->client, key, record); } /** * Handler for any generic DHT stop messages, calls the appropriate handler * depending on message type (if processed locally) * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received * */ static void handle_dht_local_get_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DHT_ClientGetStopMessage *dht_stop_msg = (const struct GNUNET_DHT_ClientGetStopMessage *) message; struct RemoveByUniqueIdContext ctx; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET STOP requests received from clients"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received GET STOP request for %s from local client %p\n", client, GNUNET_h2s (&dht_stop_msg->key)); ctx.client = find_active_client (client); ctx.unique_id = dht_stop_msg->unique_id; GNUNET_CONTAINER_multihashmap_get_multiple (forward_map, &dht_stop_msg->key, &remove_by_unique_id, &ctx); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handler for monitor start messages * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received * */ static void handle_dht_local_monitor (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct ClientMonitorRecord *r; const struct GNUNET_DHT_MonitorStartStopMessage *msg; msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message; r = GNUNET_new (struct ClientMonitorRecord); r->client = find_active_client(client); r->type = ntohl(msg->type); r->get = ntohs(msg->get); r->get_resp = ntohs(msg->get_resp); r->put = ntohs(msg->put); if (0 == ntohs(msg->filter_key)) r->key = NULL; else { r->key = GNUNET_new (struct GNUNET_HashCode); memcpy (r->key, &msg->key, sizeof (struct GNUNET_HashCode)); } GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, r); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handler for monitor stop messages * * @param cls closure for the service * @param client the client we received this message from * @param message the actual message received * */ static void handle_dht_local_monitor_stop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct ClientMonitorRecord *r; const struct GNUNET_DHT_MonitorStartStopMessage *msg; int keys_match; msg = (struct GNUNET_DHT_MonitorStartStopMessage *) message; r = monitor_head; while (NULL != r) { if (NULL == r->key) keys_match = (0 == ntohs(msg->filter_key)); else { keys_match = (0 != ntohs(msg->filter_key) && !memcmp(r->key, &msg->key, sizeof(struct GNUNET_HashCode))); } if (find_active_client(client) == r->client && ntohl(msg->type) == r->type && r->get == msg->get && r->get_resp == msg->get_resp && r->put == msg->put && keys_match ) { GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, r); GNUNET_free_non_null (r->key); GNUNET_free (r); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; /* Delete only ONE entry */ } r = r->next; } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Functions with this signature are called whenever a client * is disconnected on the network level. * * @param cls closure (NULL for dht) * @param client identification of the client; NULL * for the last call when the server is destroyed */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ClientList *pos; struct PendingMessage *reply; struct ClientMonitorRecord *monitor; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Local client %p disconnects\n", client); pos = find_active_client (client); GNUNET_CONTAINER_DLL_remove (client_head, client_tail, pos); if (pos->transmit_handle != NULL) GNUNET_SERVER_notify_transmit_ready_cancel (pos->transmit_handle); while (NULL != (reply = pos->pending_head)) { GNUNET_CONTAINER_DLL_remove (pos->pending_head, pos->pending_tail, reply); GNUNET_free (reply); } monitor = monitor_head; while (NULL != monitor) { if (monitor->client == pos) { struct ClientMonitorRecord *next; GNUNET_free_non_null (monitor->key); next = monitor->next; GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, monitor); GNUNET_free (monitor); monitor = next; } else monitor = monitor->next; } GNUNET_CONTAINER_multihashmap_iterate (forward_map, &remove_client_records, pos); GNUNET_free (pos); } /** * Initialize client subsystem. * * @param server the initialized server */ void GDS_CLIENTS_init (struct GNUNET_SERVER_Handle *server) { static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = { {&handle_dht_local_put, NULL, GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT, 0}, {&handle_dht_local_get, NULL, GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET, 0}, {&handle_dht_local_get_stop, NULL, GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP, sizeof (struct GNUNET_DHT_ClientGetStopMessage)}, {&handle_dht_local_monitor, NULL, GNUNET_MESSAGE_TYPE_DHT_MONITOR_START, sizeof (struct GNUNET_DHT_MonitorStartStopMessage)}, {&handle_dht_local_monitor_stop, NULL, GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP, sizeof (struct GNUNET_DHT_MonitorStartStopMessage)}, {&handle_dht_local_get_result_seen, NULL, GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN, 0}, {NULL, NULL, 0, 0} }; forward_map = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); retry_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); GNUNET_SERVER_add_handlers (server, plugin_handlers); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); } /** * Shutdown client subsystem. */ void GDS_CLIENTS_done () { GNUNET_assert (client_head == NULL); GNUNET_assert (client_tail == NULL); if (GNUNET_SCHEDULER_NO_TASK != retry_task) { GNUNET_SCHEDULER_cancel (retry_task); retry_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != retry_heap) { GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (retry_heap)); GNUNET_CONTAINER_heap_destroy (retry_heap); retry_heap = NULL; } if (NULL != forward_map) { GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (forward_map)); GNUNET_CONTAINER_multihashmap_destroy (forward_map); forward_map = NULL; } } /* end of gnunet-service-dht_clients.c */ gnunet-0.10.1/src/dht/gnunet-service-dht_neighbours.h0000644000175000017500000001270412320471044017472 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_neighbours.h * @brief GNUnet DHT routing code * @author Christian Grothoff * @author Nathan Evans */ #ifndef GNUNET_SERVICE_DHT_NEIGHBOURS_H #define GNUNET_SERVICE_DHT_NEIGHBOURS_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_dht_service.h" /** * Perform a PUT operation. Forwards the given request to other * peers. Does not store the data locally. Does not give the * data to local clients. May do nothing if this is the only * peer in the network (or if we are the closest peer in the * network). * * @param type type of the block * @param options routing options * @param desired_replication_level desired replication level * @param expiration_time when does the content expire * @param hop_count how many hops has this message traversed so far * @param bf Bloom filter of peers this PUT has already traversed * @param key key for the content * @param put_path_length number of entries in put_path * @param put_path peers this request has traversed so far (if tracked) * @param data payload to store * @param data_size number of bytes in data */ void GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint32_t desired_replication_level, struct GNUNET_TIME_Absolute expiration_time, uint32_t hop_count, struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode * key, unsigned int put_path_length, struct GNUNET_PeerIdentity *put_path, const void *data, size_t data_size); /** * Perform a GET operation. Forwards the given request to other * peers. Does not lookup the key locally. May do nothing if this is * the only peer in the network (or if we are the closest peer in the * network). * * @param type type of the block * @param options routing options * @param desired_replication_level desired replication count * @param hop_count how many hops did this request traverse so far? * @param key key for the content * @param xquery extended query * @param xquery_size number of bytes in @a xquery * @param reply_bf bloomfilter to filter duplicates * @param reply_bf_mutator mutator for @a reply_bf * @param peer_bf filter for peers not to select (again, updated) */ void GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint32_t desired_replication_level, uint32_t hop_count, const struct GNUNET_HashCode *key, const void *xquery, size_t xquery_size, const struct GNUNET_CONTAINER_BloomFilter *reply_bf, uint32_t reply_bf_mutator, struct GNUNET_CONTAINER_BloomFilter *peer_bf); /** * Handle a reply (route to origin). Only forwards the reply back to * other peers waiting for it. Does not do local caching or * forwarding to local clients. * * @param target neighbour that should receive the block (if still connected) * @param type type of the block * @param expiration_time when does the content expire * @param key key for the content * @param put_path_length number of entries in put_path * @param put_path peers the original PUT traversed (if tracked) * @param get_path_length number of entries in put_path * @param get_path peers this reply has traversed so far (if tracked) * @param data payload of the reply * @param data_size number of bytes in data */ void GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size); /** * Initialize neighbours subsystem. * * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GDS_NEIGHBOURS_init (void); /** * Shutdown neighbours subsystem. */ void GDS_NEIGHBOURS_done (void); /** * Get the ID of the local node. * * @return identity of the local node */ struct GNUNET_PeerIdentity * GDS_NEIGHBOURS_get_id (); #endif gnunet-0.10.1/src/dht/gnunet-service-xdht.c0000644000175000017500000001262312305632676015445 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht.c * @brief GNUnet DHT service * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_block_lib.h" #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" #include "gnunet_hello_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" #include "gnunet-service-xdht.h" #include "gnunet-service-xdht_clients.h" #include "gnunet-service-xdht_datacache.h" #include "gnunet-service-xdht_hello.h" #include "gnunet-service-xdht_neighbours.h" #include "gnunet-service-xdht_nse.h" #include "gnunet-service-xdht_routing.h" /** * Handle for the statistics service. */ struct GNUNET_STATISTICS_Handle *GDS_stats; /** * Our handle to the BLOCK library. */ struct GNUNET_BLOCK_Context *GDS_block_context; /** * The configuration the DHT service is running with */ const struct GNUNET_CONFIGURATION_Handle *GDS_cfg; /** * Our HELLO */ struct GNUNET_MessageHeader *GDS_my_hello; /** * Handle to the transport service, for getting our hello */ struct GNUNET_TRANSPORT_Handle *GDS_transport_handle; /** * Handle to get our current HELLO. */ static struct GNUNET_TRANSPORT_GetHelloHandle *ghh; /** * Hello address expiration */ struct GNUNET_TIME_Relative hello_expiration; /** * Receive the HELLO from transport service, free current and replace * if necessary. * * @param cls NULL * @param message HELLO message of peer */ static void process_hello (void *cls, const struct GNUNET_MessageHeader *message) { GNUNET_assert (message != NULL); GNUNET_free_non_null (GDS_my_hello); GDS_my_hello = GNUNET_malloc (ntohs (message->size)); memcpy (GDS_my_hello, message, ntohs (message->size)); } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != ghh) { GNUNET_TRANSPORT_get_hello_cancel (ghh); ghh = NULL; } if (GDS_transport_handle != NULL) { GNUNET_TRANSPORT_disconnect (GDS_transport_handle); GDS_transport_handle = NULL; } GDS_NEIGHBOURS_done (); GDS_DATACACHE_done (); GDS_ROUTING_done (); GDS_HELLO_done (); GDS_NSE_done (); if (GDS_block_context != NULL) { GNUNET_BLOCK_context_destroy (GDS_block_context); GDS_block_context = NULL; } if (GDS_stats != NULL) { GNUNET_STATISTICS_destroy (GDS_stats, GNUNET_YES); GDS_stats = NULL; } GNUNET_free_non_null (GDS_my_hello); GDS_my_hello = NULL; } /** * Process dht requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { GDS_cfg = c; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, "transport", "HELLO_EXPIRATION", &hello_expiration)) { hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; } GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg); GDS_stats = GNUNET_STATISTICS_create ("dht", GDS_cfg); GDS_ROUTING_init (); GDS_NSE_init (); GDS_DATACACHE_init (); GDS_HELLO_init (); GDS_CLIENTS_init (server); if (GNUNET_OK != GDS_NEIGHBOURS_init ()) { shutdown_task (NULL, NULL); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); GDS_transport_handle = GNUNET_TRANSPORT_connect (GDS_cfg, NULL, NULL, NULL, NULL, NULL); if (GDS_transport_handle == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to connect to transport service!\n")); return; } ghh = GNUNET_TRANSPORT_get_hello (GDS_transport_handle, &process_hello, NULL); } /** * The main function for the dht service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; /* FIXME: Here add a new field threshold to set user defined threshold on routing table size and trail length. Pass the thr1 and thr2 to neighbours_init and in neighbours file, in function where we are adding a new entry into our routing table and trail length, check the threshold values. After conducting experiments, try to find the correct threshold to have a balance between attack tolerance and performance.*/ ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "dht", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; GDS_CLIENTS_done (); return ret; } /* end of gnunet-service-dht.c */ gnunet-0.10.1/src/dht/test_dht_2dtorus.conf0000644000175000017500000000076112252673741015544 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test_dht_2dtorus/ [arm] DEFAULTSERVICES = core dht [dhtcache] QUOTA = 1 MB DATABASE = heap [dns] AUTOSTART = NO [nat] DISABLEV6 = YES RETURN_LOCAL_ADDRESSES = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [testbed] OVERLAY_TOPOLOGY = 2D_TORUS [nse] WORKDELAY = 500 ms INTERVAL = 60 s WORKBITS = 0 [vpn] AUTOSTART = NO [namestore] AUTOSTART = NO gnunet-0.10.1/src/dht/gnunet-service-xdht_datacache.h0000644000175000017500000000542012252673741017423 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_datacache.h * @brief GNUnet DHT service's datacache integration * @author Christian Grothoff * @author Nathan Evans */ #ifndef GNUNET_SERVICE_XDHT_DATACACHE_H #define GNUNET_SERVICE_XDHT_DATACACHE_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" /** * Handle a datum we've received from another peer. Cache if * possible. * * @param expiration when will the reply expire * @param key the query this reply is for * @param put_path_length number of peers in 'put_path' * @param put_path path the reply took on put * @param type type of the reply * @param data_size number of bytes in 'data' * @param data application payload data */ void GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data); /** * Handle a GET request we've received from another peer. * * @param key the query * @param type requested data type * @param xquery extended query * @param xquery_size number of bytes in xquery * @param reply_bf where the reply bf is (to be) stored, possibly updated!, can be NULL * @param reply_bf_mutator mutation value for reply_bf * @return evaluation result for the local replies */ enum GNUNET_BLOCK_EvaluationResult GDS_DATACACHE_handle_get (const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_CONTAINER_BloomFilter **reply_bf, uint32_t reply_bf_mutator); /** * Initialize datacache subsystem. */ void GDS_DATACACHE_init (void); /** * Shutdown datacache subsystem. */ void GDS_DATACACHE_done (void); #endif gnunet-0.10.1/src/dht/test_dht_line.conf0000644000175000017500000000106712225230043015051 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test_dht_line/ [dhtcache] QUOTA = 1 MB DATABASE = heap [arm] DEFAULTSERVICES = core dht [dns] AUTOSTART = NO [nat] DISABLEV6 = YES RETURN_LOCAL_ADDRESSES = YES USE_LOCALADDR = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [testing] WEAKRANDOM = YES [testbed] OVERLAY_TOPOLOGY = LINE [namestore] AUTOSTART = NO [transport] plugins = tcp [nse] WORKDELAY = 500 ms INTERVAL = 60 s WORKBITS = 0 [vpn] AUTOSTART = NO gnunet-0.10.1/src/dht/gnunet-service-dht_hello.h0000644000175000017500000000266112225777503016446 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_hello.h * @brief GNUnet DHT integration with peerinfo * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_DHT_HELLO_H #define GNUNET_SERVICE_DHT_HELLO_H #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" /** * Obtain a peer's HELLO if available * * @param peer peer to look for a HELLO from * @return HELLO for the given peer */ const struct GNUNET_HELLO_Message * GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer); /** * Initialize HELLO subsystem. */ void GDS_HELLO_init (void); /** * Shutdown HELLO subsystem. */ void GDS_HELLO_done (void); #endif gnunet-0.10.1/src/dht/gnunet-service-xdht_neighbours.c0000644000175000017500000030071612320724443017664 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_neighbours.c * @brief GNUnet DHT service's finger and friend table management code * @author Supriti Singh */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_hello_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_nse_service.h" #include "gnunet_ats_service.h" #include "gnunet_core_service.h" #include "gnunet_datacache_lib.h" #include "gnunet_transport_service.h" #include "gnunet_hello_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" #include "gnunet-service-xdht.h" #include "gnunet-service-xdht_clients.h" #include "gnunet-service-xdht_datacache.h" #include "gnunet-service-xdht_hello.h" #include "gnunet-service-xdht_neighbours.h" #include "gnunet-service-xdht_nse.h" #include "gnunet-service-xdht_routing.h" #include #include "dht.h" /* TODO: 1. Use a global array of all known peers in find_successor, Only when a new peer is added in finger or friend peer map, then re calculate the array. Or else use the old one. 2. Should we be using const in all the handle for the message we received * and then copy the fields and make changes to the fields instead of sending * them as they come. * 3. Everywhere you are storing yourself as the first element in the trail. * It is obviously taking too much space. Try to remove it and think of something * better. 4. Choose the correct interval to send finger and verify message. 5. Do we need expiration time for trail setup and all other messages? TTL 6. In case of trail setup after TTL, we should again send the request but * through a different route. How do we remeber each time which friend we * chose last time for the trail setup. We will need a data structure where we * add entry in finger table add and when setup is done remove it. * 7. I have not added any authentication on messages exachanged between peers. * Only when basic put/get is correct I will add it. */ /** * Maximum possible fingers of a peer. */ #define MAX_FINGERS 64 /** * Maximum allowed number of pending messages per friend peer. */ #define MAXIMUM_PENDING_PER_FRIEND 64 /** * How long at least to wait before sending another find finger trail request. */ #define DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) /** * How long at most to wait before sending another find finger trail request. */ #define DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 10) /** * How long at most to wait for transmission of a GET request to another peer? */ #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2) /** * Maximum number of trails allowed to go through a friend. */ #define LINK_THRESHOLD 64 GNUNET_NETWORK_STRUCT_BEGIN /** * P2P PUT message */ struct PeerPutMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT */ struct GNUNET_MessageHeader header; /** * Processing options */ uint32_t options GNUNET_PACKED; /** * Content type. */ uint32_t type GNUNET_PACKED; /** * Hop count */ uint32_t hop_count GNUNET_PACKED; /** * Replication level for this message */ uint32_t desired_replication_level GNUNET_PACKED; /** * Length of the PUT path that follows (if tracked). */ uint32_t put_path_length GNUNET_PACKED; /** * Source peer */ struct GNUNET_PeerIdentity source_peer; /** * Current destination */ struct GNUNET_PeerIdentity current_destination; /** * Current destination type */ enum current_destination_type current_destination_type; /** * When does the content expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The key to store the value under. */ struct GNUNET_HashCode key GNUNET_PACKED; /* put path (if tracked) */ /* Payload */ }; /** * P2P Result message */ struct PeerGetResultMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT */ struct GNUNET_MessageHeader header; /** * Peer which is sending get result message. */ struct GNUNET_PeerIdentity source_peer; /** * Peer which will receive the get result message. */ struct GNUNET_PeerIdentity destination_peer; /** * Current index in get path. */ unsigned int current_path_index; /** * Length of the GET path that follows (if tracked). */ uint32_t get_path_length GNUNET_PACKED; /** * When does the content expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The key of the corresponding GET request. */ struct GNUNET_HashCode key; /* put path (if tracked) */ /* get path (if tracked) */ /* Payload */ }; /** * P2P GET message */ struct PeerGetMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET */ struct GNUNET_MessageHeader header; /** * Source peer */ struct GNUNET_PeerIdentity source_peer; /** * Total number of peers in get path. */ unsigned int get_path_length; /** * */ struct GNUNET_PeerIdentity current_destination; /** * */ enum current_destination_type current_dest_type; /** * Unique identifier of the request. */ uint64_t request_id; /** * When does the content expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The key we are looking for. */ struct GNUNET_HashCode key; /* Get path. */ }; /** * P2P Trail setup message */ struct PeerTrailSetupMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP */ struct GNUNET_MessageHeader header; /** * Source peer which wants to setup the trail to one of its finger. */ struct GNUNET_PeerIdentity source_peer; /** * Successor of this finger value will be our finger peer. */ uint64_t destination_finger; /** * Peer which gets this message can be either an intermediate finger or friend. */ enum current_destination_type current_destination_type; /** * Peer to which this packet is forwarded. */ struct GNUNET_PeerIdentity current_destination; /** * Index into finger peer map. */ unsigned int finger_map_index; /** * Number of entries in trail list. */ uint32_t trail_length GNUNET_PACKED; }; /** * P2P Trail Setup Result message */ struct PeerTrailSetupResultMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT */ struct GNUNET_MessageHeader header; /** * Finger to which we have found the path. */ struct GNUNET_PeerIdentity finger_identity; /** * Peer which was looking for the trail to finger. */ struct GNUNET_PeerIdentity destination_peer; /** * Trail index which points to next destination to send this message. */ unsigned int current_index; /** * Index into finger peer map */ unsigned int finger_map_index; /** * Number of entries in trail list. */ uint32_t trail_length GNUNET_PACKED; }; /** * P2P Verify Successor message. */ struct PeerVerifySuccessorMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR */ struct GNUNET_MessageHeader header; /** * Source peer which wants to verify its successor. */ struct GNUNET_PeerIdentity source_peer; /** * My current successor. */ struct GNUNET_PeerIdentity successor; /** * Total number of peers in trail to current successor. */ unsigned int trail_length; /** * Trail index which points to next destination to send this message. */ unsigned int current_trail_index; }; /** * P2P Verify Successor Result message. */ struct PeerVerifySuccessorResultMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT */ struct GNUNET_MessageHeader header; /** * Destination peer which sent the request to verify its successor. */ struct GNUNET_PeerIdentity destination_peer; /** * Successor to which PeerVerifySuccessorMessage was sent. */ struct GNUNET_PeerIdentity source_successor; /** * source_successor's predecessor */ struct GNUNET_PeerIdentity my_predecessor; /** * Total number of peers in trail. * If source_successor is not destination peer, then trail is from destination_peer * to my_predecessor. * If source_successor is destination peer, then trail is from destination_peer * to source_successor. */ unsigned int trail_length; /** * Trail index which points to next destination to send this message. */ unsigned int current_index; }; /** * P2P Notify New Successor message. */ struct PeerNotifyNewSuccessorMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR */ struct GNUNET_MessageHeader header; /** * Source peer which wants to notify its new successor. */ struct GNUNET_PeerIdentity source_peer; /** * New successor identity. */ struct GNUNET_PeerIdentity destination_peer; /** * Number of peers in trail from source_peer to new successor. */ unsigned int trail_length; /** * Trail index which points to next destination to send this message. */ unsigned int current_index; }; GNUNET_NETWORK_STRUCT_END /** * Linked list of messages to send to a particular other peer. */ struct P2PPendingMessage { /** * Pointer to next item in the list */ struct P2PPendingMessage *next; /** * Pointer to previous item in the list */ struct P2PPendingMessage *prev; /** * When does this message time out? */ struct GNUNET_TIME_Absolute timeout; /** * Message importance level. FIXME: used? useful? */ unsigned int importance; /** * Actual message to be sent, allocated at the end of the struct: * // msg = (cast) &pm[1]; * // memcpy (&pm[1], data, len); */ const struct GNUNET_MessageHeader *msg; }; /** * Linked List of peers which are part of trail to reach a particular Finger. */ struct TrailPeerList { /** * Pointer to next item in the list */ struct TrailPeerList *next; /** * Pointer to previous item in the list */ struct TrailPeerList *prev; /** * An element in this trail list */ struct GNUNET_PeerIdentity peer; }; /** * Entry in friend_peermap. */ struct FriendInfo { /** * Friend Identity */ struct GNUNET_PeerIdentity id; /** * Number of trail of which this friend is the first hop. */ unsigned int trail_links; /** * Count of outstanding messages for this friend. */ unsigned int pending_count; /** * Head of pending messages to be sent to this friend. */ struct P2PPendingMessage *head; /** * Tail of pending messages to be sent to this friend. */ struct P2PPendingMessage *tail; /** * Core handle for sending messages to this friend. */ struct GNUNET_CORE_TransmitHandle *th; }; /** * Entry in finger_peermap. */ struct FingerInfo { /** * Finger identity. */ struct GNUNET_PeerIdentity finger_identity; /** * Index in finger peer map */ unsigned int finger_map_index; /** * Total number of entries in trail from [me,finger] */ unsigned int trail_length; /** * Head of trail to reach this finger. */ struct TrailPeerList *head; /** * Tail of trail to reach this finger. */ struct TrailPeerList *tail; }; /** * FIXME: Think of a better name. * Data structure passed to sorting algorithm in find_successor. */ struct Sorting_List { /** * 64 bit value of peer identity */ uint64_t peer_id; /** * Type : MY_ID, FINGER, FINGER, Value */ enum current_destination_type type; /** * Pointer to original data structure linked to peer id. */ void *data; }; /** * Task that sends FIND FINGER TRAIL requests. */ static GNUNET_SCHEDULER_TaskIdentifier find_finger_trail_task; /** * * Task that periodically verifies my successor. */ static GNUNET_SCHEDULER_TaskIdentifier verify_successor; /** * Identity of this peer. */ static struct GNUNET_PeerIdentity my_identity; /** * Hash map of all the friends of a peer */ static struct GNUNET_CONTAINER_MultiPeerMap *friend_peermap; /** * Hash map of all the fingers of a peer */ static struct GNUNET_CONTAINER_MultiPeerMap *finger_peermap; /** * Handle to CORE. */ static struct GNUNET_CORE_Handle *core_api; /** * FIXME: Is it safe to assume its initialized to 0 by default. * The current finger index that we have found trail to. */ static unsigned int current_finger_index; /** * Called when core is ready to send a message we asked for * out to the destination. * * @param cls the 'struct FriendInfo' of the target friend * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t core_transmit_notify (void *cls, size_t size, void *buf) { struct FriendInfo *peer = cls; char *cbuf = buf; struct P2PPendingMessage *pending; size_t off; size_t msize; peer->th = NULL; while ((NULL != (pending = peer->head)) && (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us)) { peer->pending_count--; GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending); GNUNET_free (pending); } if (NULL == pending) { /* no messages pending */ return 0; } if (NULL == buf) { peer->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_absolute_get_remaining (pending->timeout), &peer->id, ntohs (pending->msg->size), &core_transmit_notify, peer); GNUNET_break (NULL != peer->th); return 0; } off = 0; while ((NULL != (pending = peer->head)) && (size - off >= (msize = ntohs (pending->msg->size)))) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Bytes transmitted to other peers"), msize, GNUNET_NO); memcpy (&cbuf[off], pending->msg, msize); off += msize; peer->pending_count--; GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending); GNUNET_free (pending); } if (peer->head != NULL) { peer->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_absolute_get_remaining (pending->timeout), &peer->id, msize, &core_transmit_notify, peer); GNUNET_break (NULL != peer->th); } return off; } /** * Transmit all messages in the friend's message queue. * * @param peer message queue to process */ static void process_friend_queue (struct FriendInfo *peer) { struct P2PPendingMessage *pending; if (NULL == (pending = peer->head)) return; if (NULL != peer->th) return; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Bytes of bandwidth requested from core"), ntohs (pending->msg->size), GNUNET_NO); /* FIXME: Are we correctly initializing importance and pending. */ peer->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, pending->importance, GNUNET_TIME_absolute_get_remaining (pending->timeout), &peer->id, ntohs (pending->msg->size), &core_transmit_notify, peer); GNUNET_break (NULL != peer->th); } /** * Construct a trail message and forward it to a friend. * @param source_peer Peer which wants to set up the trail to one of its finger. * @param destination_finger Value whose successor we are searching the network. * @param current_destination Peer which gets this message. * @param target_friend Current friend to which this message should be forwarded. * @param trail_length Numbers of peers in the trail. * @param trail_peer_list peers this request has traversed so far * @param finger_map_index Index in finger peer map * @param type Type of current destination can be either FRIEND or FINGER */ void GDS_NEIGHBOURS_send_trail_setup (struct GNUNET_PeerIdentity *source_peer, uint64_t destination_finger, struct GNUNET_PeerIdentity *current_destination, struct FriendInfo *target_friend, unsigned int trail_length, struct GNUNET_PeerIdentity *trail_peer_list, unsigned int finger_map_index, enum current_destination_type type) { struct P2PPendingMessage *pending; struct PeerTrailSetupMessage *tsm; struct GNUNET_PeerIdentity *peer_list; size_t msize; msize = sizeof (struct PeerTrailSetupMessage) + (trail_length * sizeof (struct GNUNET_PeerIdentity)); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); } pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); tsm = (struct PeerTrailSetupMessage *) &pending[1]; pending->msg = &tsm->header; tsm->header.size = htons (msize); tsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP); memcpy (&(tsm->destination_finger), &destination_finger, sizeof (uint64_t)); memcpy (&(tsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(tsm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity)); tsm->current_destination_type = htonl (type); tsm->trail_length = htonl (trail_length); tsm->finger_map_index = htonl (finger_map_index); if (trail_peer_list != NULL) { peer_list = (struct GNUNET_PeerIdentity *) &tsm[1]; memcpy (peer_list, trail_peer_list, trail_length * sizeof(struct GNUNET_PeerIdentity)); } GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } /** * Construct a trail setup result message and forward it to a friend. * @param destination_peer Peer which will get the trail to one of its finger. * @param source_finger Peer to which the trail has been setup to. * @param target_friend Friend to which this message should be forwarded. * @param trail_length Numbers of peers in the trail. * @param trail_peer_list Peers which are part of the trail from source to destination. * @param current_trail_index Index at which sender of this message is located. * @param finger_map_index Index in finger peer map */ void GDS_NEIGHBOURS_send_trail_setup_result (struct GNUNET_PeerIdentity *destination_peer, struct GNUNET_PeerIdentity *source_finger, struct FriendInfo *target_friend, unsigned int trail_length, struct GNUNET_PeerIdentity *trail_peer_list, unsigned int current_trail_index, unsigned int finger_map_index) { struct P2PPendingMessage *pending; struct PeerTrailSetupResultMessage *tsrm; struct GNUNET_PeerIdentity *peer_list; size_t msize; msize = sizeof (struct PeerTrailSetupResultMessage) + (trail_length * sizeof (struct GNUNET_PeerIdentity)); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); } pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); tsrm = (struct PeerTrailSetupResultMessage *) &pending[1]; pending->msg = &tsrm->header; tsrm->header.size = htons (msize); tsrm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT); memcpy (&(tsrm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(tsrm->finger_identity), source_finger, sizeof (struct GNUNET_PeerIdentity)); tsrm->trail_length = htonl (trail_length); tsrm->current_index = htonl (current_trail_index); tsrm->finger_map_index = htonl (finger_map_index); peer_list = (struct GNUNET_PeerIdentity *) &tsrm[1]; memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); /* Send the message to chosen friend. */ GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } /** * Construct a PeerVerifySuccessor message and send it to friend. * @param source_peer Peer which wants to verify its successor * @param successor Peer which is our current successor * @param target_friend Friend to which this message should be forwarded. * @param trail_peer_list Peer which are part of trail from source to destination * @param trail_length Number of peers in the trail list. * @param current_trail_index Index in the trial list at which receiving peer should * read the next element. */ void GDS_NEIGHBOURS_send_verify_successor(struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *successor, struct FriendInfo *target_friend, struct GNUNET_PeerIdentity *trail_peer_list, unsigned int trail_length, unsigned int current_trail_index) { struct PeerVerifySuccessorMessage *vsm; struct P2PPendingMessage *pending; struct GNUNET_PeerIdentity *peer_list; size_t msize; msize = sizeof (struct PeerVerifySuccessorMessage) + (trail_length * sizeof (struct GNUNET_PeerIdentity)); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); } pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); vsm = (struct PeerVerifySuccessorMessage *) &pending[1]; pending->msg = &vsm->header; vsm->header.size = htons (msize); vsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR); memcpy (&(vsm->successor), successor, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(vsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity)); vsm->trail_length = htonl (trail_length); vsm->current_trail_index = htonl (current_trail_index); peer_list = (struct GNUNET_PeerIdentity *) &vsm[1]; memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); /* Send the message to chosen friend. */ GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } /** * Construct a PeerVerifySuccessorResult message and send it to friend. * @param destination_peer Peer which sent verify successor message * @param source_successor Peer to which verify successor message was sent. * @param my_predecessor source_successor's predecessor. * @param target_friend Friend to which this message should be forwarded. * @param trail_peer_list Peers which are part of trail from source to destination * @param trail_length Number of peers in the trail list. * @param current_trail_index Index in the trial list at which receiving peer should * get the next element. */ void GDS_NEIGHBOURS_send_verify_successor_result (struct GNUNET_PeerIdentity *destination_peer, struct GNUNET_PeerIdentity *source_successor, struct GNUNET_PeerIdentity *my_predecessor, struct FriendInfo *target_friend, struct GNUNET_PeerIdentity *trail_peer_list, unsigned int trail_length, unsigned int current_trail_index) { struct PeerVerifySuccessorResultMessage *vsmr; struct P2PPendingMessage *pending; struct GNUNET_PeerIdentity *peer_list; size_t msize; msize = sizeof (struct PeerVerifySuccessorResultMessage) + (trail_length * sizeof(struct GNUNET_PeerIdentity)); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); } pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); vsmr = (struct PeerVerifySuccessorResultMessage *) &pending[1]; pending->msg = &vsmr->header; vsmr->header.size = htons (msize); vsmr->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT); memcpy (&(vsmr->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(vsmr->source_successor), source_successor, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(vsmr->my_predecessor), my_predecessor, sizeof (struct GNUNET_PeerIdentity)); vsmr->trail_length = htonl (trail_length); vsmr->current_index = htonl (current_trail_index); peer_list = (struct GNUNET_PeerIdentity *) &vsmr[1]; memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); /* Send the message to chosen friend. */ GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } /** * Construct a PeerNotifyNewSuccessor message and send it to friend. * @param source_peer Peer which is sending notify message to its new successor. * @param destination_peer Peer which is the new destination. * @param target_friend Next friend to pass this message to. * @param peer_list List of peers in the trail to reach to destination_peer. * @param current_trail_index Index of peer_list for next target friend position. * @param trail_length Total number of peers in peer list */ void GDS_NEIGHBOURS_send_notify_new_successor (struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *destination_peer, struct FriendInfo *target_friend, struct GNUNET_PeerIdentity *trail_peer_list, unsigned int trail_length, unsigned int current_trail_index) { struct PeerNotifyNewSuccessorMessage *nsm; struct P2PPendingMessage *pending; struct GNUNET_PeerIdentity *peer_list; size_t msize; msize = sizeof (struct PeerNotifyNewSuccessorMessage) + (trail_length * sizeof(struct GNUNET_PeerIdentity)); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } if (target_friend->pending_count >= MAXIMUM_PENDING_PER_FRIEND) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); } pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); nsm = (struct PeerNotifyNewSuccessorMessage *) &pending[1]; pending->msg = &nsm->header; nsm->header.size = htons (msize); nsm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR); memcpy (&(nsm->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(nsm->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity)); nsm->trail_length = htonl (trail_length); nsm->current_index = htonl (current_trail_index); peer_list = (struct GNUNET_PeerIdentity *) &nsm[1]; memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); /* Send the message to chosen friend. */ GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } /** * FIXME: Optimizaiton Once the basic code is running. Add the optimization * where you check if the threshold on number of links that should go through * a particular friend has crossed. If yes then again choose a different * friend. Important that the new friend chosen should be different. How to * ensure this? This is an important optimization as without this one x-vine * is actually not a sybil tolerant DHT. * Randomly choose one of your friends from the friends_peer map * @return Friend */ static struct FriendInfo * select_random_friend() { unsigned int current_size; unsigned int *index; unsigned int j = 0; struct GNUNET_CONTAINER_MultiPeerMapIterator *iter; struct GNUNET_PeerIdentity key_ret; struct FriendInfo *friend; current_size = GNUNET_CONTAINER_multipeermap_size (friend_peermap); index = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, current_size); iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap); while(j < (*index)) { if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,NULL,NULL)) { j++; } else return NULL; } if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iter,&key_ret,(const void **)&friend)) return friend; else return NULL; } /** * Compute finger_identity to which we want to setup the trail * @return finger_identity */ static uint64_t * compute_finger_identity() { uint64_t my_id64 ; uint64_t *finger_identity64; finger_identity64 = GNUNET_malloc (sizeof (uint64_t)); memcpy (&my_id64, &my_identity, sizeof (uint64_t)); /*FIXME: Do we need a mod finger = ((my_id + pow(2, finger_index)) mod (pow (2, MAX_FINGERS))*/ *finger_identity64 = (my_id64 + (unsigned long) pow (2,current_finger_index)); return finger_identity64; } /** * Compute immediate predecessor identity in the network. * @return peer identity of immediate predecessor. */ static uint64_t * compute_predecessor_identity() { uint64_t my_id ; uint64_t *predecessor; predecessor = GNUNET_malloc (sizeof (uint64_t)); memcpy (&my_id, &my_identity, sizeof (uint64_t)); /* FIXME: Do we need to use mod pow(2, MAX_FINGERS) here? */ *predecessor = (my_id -1); return predecessor; } /** * Periodically ping your successor to ask its current predecessor * * @param cls closure for this task * @param tc the context under which the task is running */ static void send_verify_successor_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc ) { struct GNUNET_TIME_Relative next_send_time; struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; struct GNUNET_PeerIdentity key_ret; struct FriendInfo *target_friend; struct GNUNET_PeerIdentity *next_hop; struct GNUNET_PeerIdentity *peer_list; unsigned int finger_trail_current_index; struct FingerInfo *finger; unsigned int finger_index; unsigned int i; int flag = 0; finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) { if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret, (const void **)&finger)) { if (0 == finger->finger_map_index) { flag = 1; break; } } } GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter); if( flag == 0) goto send_new_request; peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * finger->trail_length); struct TrailPeerList *iterate; iterate = finger->head; i = 0; while ( i < (finger->trail_length)) { memcpy (&peer_list[i], &(iterate->peer), sizeof (struct GNUNET_PeerIdentity)); iterate = iterate->next; i++; } next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (next_hop, &peer_list[0], sizeof (struct GNUNET_PeerIdentity)); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); finger_trail_current_index = 0; GDS_NEIGHBOURS_send_verify_successor (&my_identity, &(finger->finger_identity), target_friend, peer_list, finger->trail_length, finger_trail_current_index); /* FIXME: Use a random value so that this message is send not at the same interval as send_find_finger_trail_message. */ send_new_request: next_send_time.rel_value_us = DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us / (current_finger_index + 50)); verify_successor = GNUNET_SCHEDULER_add_delayed (next_send_time, &send_verify_successor_message, NULL); } /** * Task to send a find finger trail message. We attempt to find trail * to our fingers, successor and predecessor in the network. * * @param cls closure for this task * @param tc the context under which the task is running */ static void send_find_finger_trail_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct FriendInfo *target_friend; struct GNUNET_TIME_Relative next_send_time; uint64_t *finger_identity; unsigned int finger_map_index; if (1 == current_finger_index) { finger_identity = compute_predecessor_identity(); goto select_friend; } else { finger_identity = compute_finger_identity(); } select_friend: /* FIXME: Here should we choose randomly or not. */ target_friend = select_random_friend(); finger_map_index = current_finger_index; current_finger_index = ( current_finger_index + 1) % MAX_FINGERS; if(NULL != target_friend) { GDS_NEIGHBOURS_send_trail_setup (&my_identity, *finger_identity, &(target_friend->id), target_friend, 0, NULL, finger_map_index, FRIEND); } /* FIXME: How to decide the correct interval? */ next_send_time.rel_value_us = DHT_MINIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, DHT_MAXIMUM_FIND_FINGER_TRAIL_INTERVAL.rel_value_us / (current_finger_index + 10)); find_finger_trail_task = GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_finger_trail_message, NULL); } /** * Method called whenever a peer connects. * * @param cls closure * @param peer_identity peer identity this notification is about */ static void handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer_identity) { struct FriendInfo *friend; /* Check for connect to self message */ if (0 == memcmp (&my_identity, peer_identity, sizeof (struct GNUNET_PeerIdentity))) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer_identity)); /* If peer already exists in our friend_peermap, then exit. */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (friend_peermap, peer_identity)) { GNUNET_break (0); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1, GNUNET_NO); friend = GNUNET_new (struct FriendInfo); friend->id = *peer_identity; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (friend_peermap, peer_identity, friend, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); /* got a first connection, good time to start with FIND FINGER TRAIL requests... */ if (1 == GNUNET_CONTAINER_multipeermap_size (friend_peermap)) find_finger_trail_task = GNUNET_SCHEDULER_add_now (&send_find_finger_trail_message, NULL); } /** * Method called whenever a peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct FriendInfo *remove_friend; struct FingerInfo *remove_finger; struct GNUNET_PeerIdentity key_ret; struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; struct TrailPeerList *iterator; struct GNUNET_PeerIdentity *finger_identity; int finger_index; /* Check for self message. */ if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; /* Search for peer to remove in your friend_peermap. */ remove_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, peer); if (NULL == remove_friend) { GNUNET_break (0); return; } iterator = GNUNET_malloc (sizeof (struct TrailPeerList)); finger_identity = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) { if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret, (const void **)&remove_finger)) { iterator = remove_finger->head->next; if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(iterator->peer), &(remove_friend->id))) { memcpy (finger_identity, &(remove_finger->finger_identity), sizeof (struct GNUNET_PeerIdentity)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (finger_peermap, finger_identity, remove_finger)); } } } /* Remove the friend from friend_peermap. */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (friend_peermap, peer, remove_friend)); } /** * To be called on core init/fail. * * @param cls service closure * @param identity the public identity of this peer */ static void core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { my_identity = *identity; #if 0 /* SUPU TEST CODE */ struct GNUNET_PeerIdentity *print_peer; print_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (print_peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)); FPRINTF (stderr,_("\nSUPU %s, %s, %d,my_identity = %s"), __FILE__, __func__,__LINE__, GNUNET_i2s (print_peer)); /* SUPU TEST CODE ENDS */ #endif } /** * * @param destination_peer * @param existing_trail * @param trail_length * @return */ static struct GNUNET_PeerIdentity * invert_trail_list (struct GNUNET_PeerIdentity *destination_peer, struct GNUNET_PeerIdentity *existing_trail, unsigned int trail_length) { int i; int j; struct GNUNET_PeerIdentity *new_trail; j = 0; new_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * trail_length); if (trail_length > 1) { i = trail_length - 2; while (i >= 0 ) { memcpy( &new_trail[j], &existing_trail[i], sizeof (struct GNUNET_PeerIdentity)); i--; j++; } } memcpy (&new_trail[j], destination_peer, sizeof(struct GNUNET_PeerIdentity)); return new_trail; } /** * * @param existing_finger * @param new_finger * @return */ #if 0 static int compare_finger_identity (struct GNUNET_PeerIdentity *existing_finger, struct GNUNET_PeerIdentity *new_finger) { int ret; ret = (existing_finger > new_finger) ? 1 : (existing_finger == new_finger) ? 0 : -1; return ret; } #endif /** * FIXME: Not sure of the logic to find the correct predecessor. * Given two finger identities, find the closest predecessor. * @param existing_predecessor * @param new_predecessor * @return */ #if 0 static int compare_predecessor(struct GNUNET_PeerIdentity *existing_predecessor, struct GNUNET_PeerIdentity *new_predecessor) { int ret; ret = (existing_predecessor < new_predecessor) ? 1 : (existing_predecessor == new_predecessor) ? 0 : -1; return ret; } #endif /* * Add an entry in finger table. * Add an entry into finger table * @param finger_identity Peer identity of finger * @param finger_trail Trail to reach the finger * @param trail_length Number of peers in the trail. * @param finger_map_index Index in finger peer map. */ static void finger_table_add (struct GNUNET_PeerIdentity *finger_identity, struct GNUNET_PeerIdentity *finger_trail, unsigned int trail_length, unsigned int finger_map_index) { struct FingerInfo *new_finger_entry; int i; #if 0 struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; struct GNUNET_PeerIdentity key_ret; struct FingerInfo *existing_finger; int finger_index; int i; finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) { if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter, &key_ret, (const void **)&existing_finger)) { /* If we already have an entry at the finger map index. */ if ((finger_map_index == existing_finger->finger_map_index)) { /* Check if the finger entry are same. */ if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(existing_finger->finger_identity),finger_identity)) { FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); goto add_new_entry; } else { /* FIXME: here you should have something better to check which finger is closer one. */ int ret; if (finger_map_index == 1) { FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); ret = compare_predecessor (&(existing_finger->finger_identity), finger_identity); } else { FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); ret = compare_finger_identity (&(existing_finger->finger_identity), finger_identity); } if (ret > 0) { FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (finger_peermap, &(existing_finger->finger_identity), existing_finger)); goto add_new_entry; } else { FPRINTF (stderr,_("\nSUPU %s, %s, %d"), __FILE__, __func__,__LINE__); return; } } } } } add_new_entry: #endif new_finger_entry = GNUNET_malloc (sizeof (struct FingerInfo)); memcpy (&(new_finger_entry->finger_identity), finger_identity, sizeof (struct GNUNET_PeerIdentity)); i = 0; while (i < trail_length) { struct TrailPeerList *element; element = GNUNET_malloc (sizeof (struct TrailPeerList)); element->next = NULL; element->prev = NULL; memcpy (&(element->peer), &finger_trail[i], sizeof(struct GNUNET_PeerIdentity)); GNUNET_CONTAINER_DLL_insert_tail(new_finger_entry->head, new_finger_entry->tail, element); i++; } new_finger_entry->finger_map_index = finger_map_index; new_finger_entry->trail_length = trail_length; /* FIXME: Here we are keeping multiple hashmap option so that there are multiple routes to reach to same finger, redundant routing. * Also same peers could be our fingers for different finger map index */ GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (finger_peermap, &(new_finger_entry->finger_identity), new_finger_entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); /* Fixme: change to multiple */ if (1 == GNUNET_CONTAINER_multipeermap_size (finger_peermap) && (new_finger_entry->finger_map_index!= 1)) { verify_successor = GNUNET_SCHEDULER_add_now (&send_verify_successor_message, NULL); } } /** * Compare two peer identities. * @param p1 Peer identity * @param p2 Peer identity * @return 1 if p1 > p2, -1 if p1 < p2 and 0 if p1 == p2. */ static int compare_peer_id (const void *p1, const void *p2) { struct Sorting_List *p11; struct Sorting_List *p22; int ret; p11 = GNUNET_malloc (sizeof (struct Sorting_List)); p22 = GNUNET_malloc (sizeof (struct Sorting_List)); p11 = (struct Sorting_List *)p1; p22 = (struct Sorting_List *)p2; ret = ( (p11->peer_id) > (p22->peer_id) ) ? 1 : ( (p11->peer_id) == (p22->peer_id) ) ? 0 : -1; return ret; } /** * Return the successor of value in all_known_peers. * @param all_known_peers list of all the peers * @param value value we have to search in the all_known_peers. * @return */ static struct Sorting_List * find_closest_successor(struct Sorting_List *all_known_peers, uint64_t value, unsigned int size) { int first; int last; int middle; first = 0; last = size - 1; middle = (first + last)/2; while(first <= last) { if(all_known_peers[middle].peer_id < value) { first = middle + 1; } else if(all_known_peers[middle].peer_id == value) { if(middle == (size -1)) { return &all_known_peers[0]; } else { return &all_known_peers[middle+1]; } } else { last = middle - 1; } middle = (first + last)/2; } return NULL; } /** * Find closest successor for the value. * @param value Value for which we are looking for successor * @param current_destination NULL if my_identity is successor else finger/friend * identity * @param type Next destination type * @return Peer identity of next destination i.e. successor of value. */ static struct GNUNET_PeerIdentity * find_successor (uint64_t value, struct GNUNET_PeerIdentity *current_destination, enum current_destination_type *type) { struct GNUNET_CONTAINER_MultiPeerMapIterator *friend_iter; struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; struct GNUNET_PeerIdentity key_ret; struct FriendInfo *friend; struct FingerInfo *finger; unsigned int finger_index; unsigned int friend_index; struct Sorting_List *successor; unsigned int size; int j; /* 2 is added in size for my_identity and value which will part of all_known_peers. */ size = GNUNET_CONTAINER_multipeermap_size (friend_peermap)+ GNUNET_CONTAINER_multipeermap_size (finger_peermap)+ 2; struct Sorting_List all_known_peers[size]; int k; for (k = 0; k < size; k++) all_known_peers[k].peer_id = 0; /* Copy your identity at 0th index in all_known_peers. */ j = 0; memcpy (&(all_known_peers[j].peer_id), &my_identity, sizeof (uint64_t)); all_known_peers[j].type = MY_ID; all_known_peers[j].data = 0; j++; /* Copy value */ all_known_peers[j].peer_id = value; all_known_peers[j].type = VALUE; all_known_peers[j].data = 0; j++; /* Iterate over friend peer map and copy all the elements into array. */ friend_iter = GNUNET_CONTAINER_multipeermap_iterator_create (friend_peermap); for (friend_index = 0; friend_index < GNUNET_CONTAINER_multipeermap_size (friend_peermap); friend_index++) { if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(friend_iter,&key_ret,(const void **)&friend)) { memcpy (&(all_known_peers[j].peer_id), &(friend->id), sizeof (uint64_t)); all_known_peers[j].type = FRIEND; all_known_peers[j].data = friend; j++; } } /* Iterate over finger map and copy all the entries into all_known_peers array. */ finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) { if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next(finger_iter,&key_ret,(const void **)&finger)) { memcpy (&(all_known_peers[j].peer_id), &(finger->finger_identity), sizeof (uint64_t)); all_known_peers[j].type = FINGER; all_known_peers[j].data = finger; j++; } } GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter); GNUNET_CONTAINER_multipeermap_iterator_destroy (friend_iter); qsort (&all_known_peers, size, sizeof (struct Sorting_List), &compare_peer_id); /* search value in all_known_peers array. */ successor = find_closest_successor (all_known_peers, value, size); if (successor->type == MY_ID) { *type = MY_ID; return NULL; } else if (successor->type == FRIEND) { *type = FRIEND; struct FriendInfo *target_friend; target_friend = (struct FriendInfo *)successor->data; memcpy (current_destination, &(target_friend->id), sizeof (struct GNUNET_PeerIdentity)); return current_destination; } else if (successor->type == FINGER) { *type = FINGER; struct GNUNET_PeerIdentity *next_hop; struct FingerInfo *finger; struct TrailPeerList *iterator; iterator = GNUNET_malloc (sizeof (struct TrailPeerList)); finger = successor->data; iterator = finger->head; next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (next_hop, &(iterator->peer), sizeof (struct GNUNET_PeerIdentity)); memcpy (current_destination, &(finger->finger_identity), sizeof (struct GNUNET_PeerIdentity)); return next_hop; } else { type = NULL; return NULL; } } /** * FIXME: * 1. Do we have an expiration time for get request? Yes but I don't know its * use case and how to handle it * Send a get message to selected target friend. If target friend in NULL, * then search for a target friend. * @param request_id Unique ID identifying this request * @param source_peer Peer which started get request * @param get_peer_path Peer list to reach to final destination which contains the data. * @param get_path_length Total numbers of peer in get_path * @param key Key key for the content * @param target_peer Next peer to forward the message to. * @param current_destination Peer which will get this message. * @param current_dest_type Type of current destination can be either FRIEND or FINGER */ void GDS_NEIGHBOURS_handle_get (struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *get_peer_path, unsigned int get_path_length, struct GNUNET_HashCode *key, struct GNUNET_PeerIdentity *target_peer, struct GNUNET_PeerIdentity *current_destination, enum current_destination_type *current_dest_type) { struct PeerGetMessage *get_request; struct P2PPendingMessage *pending; struct GNUNET_PeerIdentity *get_path; struct FriendInfo *target_friend; uint64_t key_value; size_t msize; msize = sizeof (struct PeerGetMessage) + (get_path_length * sizeof (struct GNUNET_PeerIdentity)); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } memcpy (&key_value, key, sizeof (uint64_t)); /* FIXME: Is this correct comparison? */ if (NULL == target_peer) { /* This is the first call made from client file. */ struct GNUNET_PeerIdentity *next_hop; next_hop = find_successor (key_value, current_destination, current_dest_type); if (*current_dest_type == MY_ID) { struct GNUNET_PeerIdentity *destination_peer; get_path = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (get_path, &my_identity, sizeof (struct GNUNET_PeerIdentity)); get_path_length = 1; destination_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (destination_peer, source_peer, sizeof (struct GNUNET_PeerIdentity)); /* FIXME: We enter in this part of code only when this is our first call from client file. In client file we already have done datacache_get and if we already have the result. So, ideally code should never reach here. Remove it after verifying. */ /* FIXME: Call datacache_get but remove after verified above thing. */ GDS_NEIGHBOURS_send_get_result (&my_identity,get_path, get_path_length, key,destination_peer, 0, NULL,0,NULL); return; } else { /* Find the friend corresponding to next_hop */ target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); } } else target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer); pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ /* FIXME: Do we have an expiration time for get request */ get_request = (struct PeerGetMessage *) &pending[1]; pending->msg = &get_request->header; get_request->header.size = htons (msize); get_request->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET); get_request->get_path_length = htonl (get_path_length); get_request->key = *key; memcpy (&(get_request->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(get_request->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity)); get_request->current_dest_type = htonl (*current_dest_type); get_path = (struct GNUNET_PeerIdentity *) &get_request[1]; memcpy (get_path, get_peer_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } /** * FIXME: In this function, you just find the target friend and send the message * to next peer. In handle_dht_p2p_put, you should check the options and type * and check if you are final destination or not. if not then find the next * destination and send the message forward. * @param type type of the block * @param options routing options * @param desired_replication_level desired replication count * @param expiration_time when does the content expire * @param hop_count how many hops has this message traversed so far * @param key key for the content * @param put_path_length number of entries in @a put_path * @param put_path peers this request has traversed so far (if tracked) * @param data payload to store * @param data_size number of bytes in @a data * @param current_destination * @param dest_type * @param target_peer_id */ void GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint32_t desired_replication_level, struct GNUNET_TIME_Absolute expiration_time, uint32_t hop_count, const struct GNUNET_HashCode *key, unsigned int put_path_length, struct GNUNET_PeerIdentity *put_path, const void *data, size_t data_size, struct GNUNET_PeerIdentity *current_destination, enum current_destination_type dest_type, struct GNUNET_PeerIdentity *target_peer) { struct PeerPutMessage *ppm; struct P2PPendingMessage *pending; struct FriendInfo *target_friend; struct GNUNET_PeerIdentity *pp; size_t msize; uint64_t key_value; msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size + sizeof (struct PeerPutMessage); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { put_path_length = 0; msize = data_size + sizeof (struct PeerPutMessage); } if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } memcpy (&key_value, key, sizeof (uint64_t)); struct GNUNET_PeerIdentity *current_dest; current_dest = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); if (target_peer == NULL) { /* This is the first time the call has been made from handle_dht_local_put. So, you need to search for the next peer to send this message to. */ struct GNUNET_PeerIdentity *next_hop; next_hop = find_successor (key_value, current_dest, &dest_type); if (dest_type == MY_ID) { /* FIXME: How do we handle different block types? */ /* FIXME: Here depending on the replication level choose 'r' successors to this peer and send put to all of these peers. */ //replicate_put(); GDS_DATACACHE_handle_put (expiration_time, key, put_path_length, put_path, type, data_size, data); return; } else { /* Find the friend corresponding to next_hop */ target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); } } else target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, target_peer); pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ pending->timeout = expiration_time; ppm = (struct PeerPutMessage *) &pending[1]; pending->msg = &ppm->header; ppm->header.size = htons (msize); ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); ppm->options = htonl (options); ppm->type = htonl (type); ppm->hop_count = htonl (hop_count + 1); ppm->desired_replication_level = htonl (desired_replication_level); ppm->put_path_length = htonl (put_path_length); ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); if (current_destination != NULL) memcpy (&(ppm->current_destination), current_destination, sizeof (struct GNUNET_PeerIdentity)); else memcpy (&(ppm->current_destination), current_dest, sizeof (struct GNUNET_PeerIdentity)); ppm->current_destination_type = htonl (dest_type); ppm->key = *key; pp = (struct GNUNET_PeerIdentity *) &ppm[1]; memcpy (pp, put_path, sizeof (struct GNUNET_PeerIdentity) * put_path_length); memcpy (&pp[put_path_length], data, data_size); GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } /** * Send get result back to requesting client. * @param source_peer * @param get_path * @param target_friend * @param get_path_length * @param key * @param destination_peer * @param current_path_index * @param data * @param data_size */ void GDS_NEIGHBOURS_send_get_result (struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, struct GNUNET_HashCode *key, struct GNUNET_PeerIdentity *destination_peer, unsigned int current_path_index, const void *data, size_t data_size, struct GNUNET_PeerIdentity *next_hop) { /* Add get_result into pending message and send the data to target friend. make a call GDS_CLIENTS_process_get_result() with all the fields. */ struct PeerGetResultMessage *get_result; struct GNUNET_PeerIdentity *get_result_path; struct P2PPendingMessage *pending; struct FriendInfo *target_friend; size_t msize; msize = get_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size + sizeof (struct PeerPutMessage); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ /* FIXME: Should we add an expiration time like in put message. */ get_result = (struct PeerGetResultMessage *)&pending[1]; pending->msg = &get_result->header; get_result->header.size = htons (msize); get_result->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT); memcpy (&(get_result->source_peer), source_peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(get_result->destination_peer), destination_peer, sizeof (struct GNUNET_PeerIdentity)); get_result->current_path_index = current_path_index; get_result->key = *key; get_result_path = (struct GNUNET_PeerIdentity *)&get_result[1]; memcpy (get_result_path, get_path, sizeof (struct GNUNET_PeerIdentity) * get_path_length); memcpy (&get_result_path[get_path_length], data, data_size); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); GNUNET_CONTAINER_DLL_insert_tail (target_friend->head, target_friend->tail, pending); target_friend->pending_count++; process_friend_queue (target_friend); } /** * * @param cls * @param peer * @param message * @return */ static int handle_dht_p2p_get_result (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { /* If you are the source, go back to the client file and there search for the requesting client and send back the result. */ struct PeerGetResultMessage *get_result; struct GNUNET_PeerIdentity *get_path; void *payload; size_t payload_size; size_t msize; unsigned int getlen; int current_path_index; msize = ntohs (message->size); if (msize < sizeof (struct PeerGetResultMessage)) { GNUNET_break_op (0); return GNUNET_YES; } get_result = (struct PeerGetResultMessage *)message; getlen = ntohl (get_result->get_path_length); if ((msize < sizeof (struct PeerGetResultMessage) + getlen * sizeof (struct GNUNET_PeerIdentity)) || (getlen > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } get_path = (struct GNUNET_PeerIdentity *) &get_result[1]; payload = &get_path[getlen]; payload_size = msize - (sizeof (struct PeerGetResultMessage) + getlen * sizeof (struct GNUNET_PeerIdentity)); current_path_index = ntohl (get_result->current_path_index); /* Here you just have to check if you are the destination or not if not then read the next peer and send the message. */ if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&my_identity, &(get_result->destination_peer)))) { /* I am the destination. Call the function in client file. * FIXME: Here I don't know how I communicate the result back to client file. */ //GDS_CLIENTS_process_get_result(); return GNUNET_YES; } else { /* Read the element from the get path at trail index. set the trail index and call gds_neighbours_send_get_result.*/ struct GNUNET_PeerIdentity *next_hop; next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (next_hop, &get_path[current_path_index], sizeof (struct GNUNET_PeerIdentity)); if (current_path_index != 0) current_path_index--; GDS_NEIGHBOURS_send_get_result (&my_identity, get_path, getlen,&(get_result->key),&(get_result->destination_peer), current_path_index, payload, payload_size, next_hop); return GNUNET_YES; } return GNUNET_SYSERR; } /** * Core handler for p2p put requests. * * @param cls closure * @param peer sender of the request * @param message message * @param peer peer identity this notification is about * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerPutMessage *put; struct GNUNET_PeerIdentity *put_path; enum GNUNET_DHT_RouteOption options; enum current_destination_type current_dst_type; struct GNUNET_PeerIdentity *current_destination; struct GNUNET_PeerIdentity *source_peer; struct GNUNET_PeerIdentity *next_hop; struct GNUNET_HashCode test_key; uint64_t key_value; void *payload; size_t payload_size; size_t msize; uint32_t putlen; put = (struct PeerPutMessage *) message; putlen = ntohl (put->put_path_length); msize = ntohs (message->size); if ((msize < sizeof (struct PeerPutMessage) + putlen * sizeof (struct GNUNET_PeerIdentity)) || (putlen > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } put_path = (struct GNUNET_PeerIdentity *) &put[1]; payload = &put_path[putlen]; options = ntohl (put->options); payload_size = msize - (sizeof (struct PeerPutMessage) + putlen * sizeof (struct GNUNET_PeerIdentity)); /* FIXME: I don't understand what exactly are we doing here. */ switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->type), payload, payload_size, &test_key)) { case GNUNET_YES: if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode))) { char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key)); GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "PUT with key `%s' for block with key %s\n", put_s, GNUNET_h2s_full (&test_key)); GNUNET_free (put_s); return GNUNET_YES; } break; case GNUNET_NO: GNUNET_break_op (0); return GNUNET_YES; case GNUNET_SYSERR: /* cannot verify, good luck */ break; } /* FIXME: This part is also not clear to me.*/ if (ntohl (put->type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */ { switch (GNUNET_BLOCK_evaluate (GDS_block_context, ntohl (put->type), NULL, /* query */ NULL, 0, /* bloom filer */ NULL, 0, /* xquery */ payload, payload_size)) { case GNUNET_BLOCK_EVALUATION_OK_MORE: case GNUNET_BLOCK_EVALUATION_OK_LAST: break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: default: GNUNET_break_op (0); return GNUNET_OK; } } struct GNUNET_PeerIdentity pp[putlen + 1]; /* extend 'put path' by sender */ if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE)) { memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity)); pp[putlen] = *peer; putlen++; } else putlen = 0; /* Copy the fields of message, call find successor or gds_routing_search, depending on the destination_type and if you are the final destination, do a datache put or if option is. else call gds_neighbours_handle_get with correct parameters. */ current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (current_destination, &(put->current_destination), sizeof (struct GNUNET_PeerIdentity)); current_dst_type = ntohl (put->current_destination_type); memcpy (&key_value, &(put->key), sizeof (uint64_t)); source_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (source_peer, &(put->source_peer), sizeof (struct GNUNET_PeerIdentity)); if (current_dst_type == FRIEND) { next_hop = find_successor (key_value, current_destination, ¤t_dst_type); } else if (current_dst_type == FINGER) { next_hop = GDS_ROUTING_search (source_peer, current_destination, peer); } if (current_dst_type == MY_ID) { /* Here datacache_put*/ /* FIXME: Here depending on replication, call replicate_put() to do the put operation on 'r' successors. */ GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time), &(put->key),putlen, pp, ntohl (put->type), payload_size, payload); return GNUNET_YES; } else { /* here call gds_neighbours*/ GDS_NEIGHBOURS_handle_put (ntohl (put->type),ntohl (put->options), ntohl (put->desired_replication_level), GNUNET_TIME_absolute_ntoh (put->expiration_time), ntohl (put->hop_count),&put->key, putlen, pp, payload, payload_size, current_destination, current_dst_type, next_hop); return GNUNET_YES; } return GNUNET_SYSERR; } /** * FIXME: Handle expiration, options, block type, replication * referring the old code. * Core handler for p2p get requests. * * @param cls closure * @param peer sender of the request * @param message message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerGetMessage *get; struct GNUNET_PeerIdentity *current_destination; uint64_t key_value; enum current_destination_type cuurent_dest_type; struct GNUNET_PeerIdentity *next_hop; struct GNUNET_PeerIdentity *get_path; size_t msize; unsigned int get_length; msize = ntohs (message->size); if (msize < sizeof (struct PeerGetMessage)) { GNUNET_break_op (0); return GNUNET_YES; } get = (struct PeerGetMessage *)message; get_length = ntohl (get->get_path_length); get_path = (struct GNUNET_PeerIdentity *)&get[1]; if ((msize < sizeof (struct PeerGetMessage) + get_length * sizeof (struct GNUNET_PeerIdentity)) || (get_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } get = (struct PeerGetMessage *) message; current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (current_destination, &(get->current_destination), sizeof (struct GNUNET_PeerIdentity)); memcpy (&key_value, &(get->key), sizeof (uint64_t)); cuurent_dest_type = ntohl (get->current_dest_type); if (cuurent_dest_type == FRIEND) { next_hop = find_successor (key_value, current_destination, &cuurent_dest_type); } else if (cuurent_dest_type == FINGER) { next_hop = GDS_ROUTING_search (&(get->source_peer), current_destination, peer); } if (cuurent_dest_type == MY_ID) { struct GNUNET_PeerIdentity *destination_peer; //struct GNUNET_PeerIdentity *next_hop; //int current_path_index; /* Add yourself to the get path, increment the get length. */ destination_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (destination_peer, &(get->source_peer), sizeof (struct GNUNET_PeerIdentity)); //current_path_index = get_length - 1; /* I am the final destination. Call GDS_NEIGHBOURS_send_get_result. * FIXME: Last parameters are data and data size. First implement datacache get * and get the result and send the data. Also seach for the next friend to pass * this message to. */ #if 0 /* FIXME: Here we should call GDS_CLIENT_handle_reply. */ GDS_NEIGHBOURS_send_get_result (get->request_id, &my_identity, get_path, get_length,&(get->key), destination_peer, current_path_index, NULL, 0, next_hop); #endif return GNUNET_YES; } else { /* FIXME: Add your self to the get path and increment the get length. */ /* FIXME: Does it matter if the dest_type is friend or finger. */ GDS_NEIGHBOURS_handle_get (&(get->source_peer), get_path, get_length, &(get->key),next_hop, current_destination,&cuurent_dest_type); return GNUNET_YES; } return GNUNET_SYSERR; } /** * Handle a PeerTrailSetupMessage. * @param cls closure * @param message message * @param peer peer identity this notification is about * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int handle_dht_p2p_trail_setup(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerTrailSetupMessage *trail_setup; struct GNUNET_PeerIdentity *next_hop; struct FriendInfo *target_friend; struct GNUNET_PeerIdentity *current_destination; struct GNUNET_PeerIdentity *trail_peer_list; enum current_destination_type current_dest_type; struct GNUNET_PeerIdentity *next_peer; unsigned int trail_length; uint32_t current_trail_index; unsigned int finger_map_index; uint64_t destination_finger_value; size_t msize; msize = ntohs (message->size); if (msize < sizeof (struct PeerTrailSetupMessage)) { GNUNET_break_op (0); return GNUNET_YES; } trail_setup = (struct PeerTrailSetupMessage *) message; trail_length = ntohl (trail_setup->trail_length); if ((msize < sizeof (struct PeerTrailSetupMessage) + trail_length * sizeof (struct GNUNET_PeerIdentity)) || (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } current_dest_type = ntohl (trail_setup->current_destination_type); finger_map_index = ntohl (trail_setup->finger_map_index); trail_peer_list = (struct GNUNET_PeerIdentity *)&trail_setup[1]; destination_finger_value = trail_setup->destination_finger; current_destination = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (current_destination, &(trail_setup->current_destination), sizeof (struct GNUNET_PeerIdentity)); /* Find the next hop to send the packet to. */ if (current_dest_type == FRIEND) { if (0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination), &my_identity))) { next_hop = find_successor (destination_finger_value, current_destination, &(current_dest_type)); } else return GNUNET_SYSERR; } else if (current_dest_type == FINGER) { if (0 != (GNUNET_CRYPTO_cmp_peer_identity (&(trail_setup->current_destination), &my_identity))) { next_hop = GDS_ROUTING_search (&(trail_setup->source_peer), &(trail_setup->current_destination), peer); /* As an optimization, find the successor from the find successor and compare both the ids to find the closest peer. */ } else { next_hop = find_successor (destination_finger_value, current_destination, &(current_dest_type)); } } /* Add yourself to the trail list and increment the trail length. */ struct GNUNET_PeerIdentity *peer_list; peer_list = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * (trail_length + 1)); if ( trail_length > 0) { memcpy (peer_list, trail_peer_list, trail_length * sizeof (struct GNUNET_PeerIdentity)); } memcpy (&peer_list[trail_length], &my_identity, sizeof (struct GNUNET_PeerIdentity)); trail_length++; if (current_dest_type == MY_ID || (0 == GNUNET_CRYPTO_cmp_peer_identity(next_hop, &(trail_setup->source_peer)))) { struct GNUNET_PeerIdentity *source_peer; source_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (source_peer, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity)); current_trail_index = trail_length - 1; next_peer= GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); if (current_trail_index == 0) { memcpy (next_peer, &(trail_setup->source_peer), sizeof (struct GNUNET_PeerIdentity)); } else { memcpy (next_peer, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity)); } target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_peer); GNUNET_free (next_peer); if (0 == trail_setup->finger_map_index) { struct GNUNET_PeerIdentity *new_trail_list; new_trail_list = invert_trail_list (source_peer, peer_list, trail_length); finger_table_add (source_peer, new_trail_list, trail_length, 1); } GDS_NEIGHBOURS_send_trail_setup_result (&(trail_setup->source_peer), &(my_identity), target_friend, trail_length, peer_list, current_trail_index, finger_map_index); return GNUNET_YES; } else if (next_hop == NULL) { return GNUNET_SYSERR; } else { target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); if(current_dest_type == FINGER) { /* FIXME: Here it can even return err if routing entries have crossed the threshold. In such a case, you should send back a trail setup fail message to node just before your. THen its the responsiblity of node before you to find an alternate path to reach to the current_desintation which doesnot involve you.*/ if ( GNUNET_SYSERR == GDS_ROUTING_add (&(trail_setup->source_peer), &(trail_setup->current_destination), next_hop, peer)) { //trail_setup_rejection()--> add to a list of fail trails and start // a new search rejecting this peer. } } GDS_NEIGHBOURS_send_trail_setup (&(trail_setup->source_peer), trail_setup->destination_finger, current_destination, target_friend, trail_length, peer_list, finger_map_index, current_dest_type); return GNUNET_YES; } return GNUNET_SYSERR; } /** * Core handle for p2p trail construction result messages. * @param cls closure * @param message message * @param peer peer identity this notification is about * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int handle_dht_p2p_trail_setup_result(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerTrailSetupResultMessage *trail_result; struct GNUNET_PeerIdentity *trail_peer_list; struct GNUNET_PeerIdentity *next_hop; struct FriendInfo *target_friend; unsigned int current_trail_index; unsigned int finger_map_index; unsigned int trail_length; size_t msize; msize = ntohs (message->size); if (msize < sizeof (struct PeerTrailSetupResultMessage)) { GNUNET_break_op (0); return GNUNET_YES; } trail_result = (struct PeerTrailSetupResultMessage *) message; trail_length = ntohl (trail_result->trail_length); if ((msize < sizeof (struct PeerTrailSetupResultMessage) + trail_length * sizeof (struct GNUNET_PeerIdentity)) || (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } current_trail_index = ntohl (trail_result->current_index); finger_map_index = ntohl (trail_result->finger_map_index); trail_peer_list = (struct GNUNET_PeerIdentity *) &trail_result[1]; if ( 0 == (GNUNET_CRYPTO_cmp_peer_identity (&(trail_result->destination_peer), &my_identity))) { #if 0 /* I don't remember why I have written this code. */ if (finger_map_index == 1) { struct GNUNET_PeerIdentity *new_trail_list; new_trail_list = invert_trail_list (&(trail_result->finger_identity), trail_peer_list, trail_length); finger_table_add (&(trail_result->finger_identity), new_trail_list, trail_length, finger_map_index); return GNUNET_YES; } else { #endif finger_table_add (&(trail_result->finger_identity), trail_peer_list, trail_length, finger_map_index); return GNUNET_YES; //} } else { next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); current_trail_index = current_trail_index - 1; if (current_trail_index == 0) { memcpy (next_hop, &(trail_result->destination_peer),sizeof (struct GNUNET_PeerIdentity)); } else { memcpy (next_hop, &(trail_peer_list[current_trail_index-1]),sizeof (struct GNUNET_PeerIdentity)); } target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); GNUNET_free (next_hop); GDS_NEIGHBOURS_send_trail_setup_result (&(trail_result->destination_peer), &(trail_result->finger_identity), target_friend, trail_length, trail_peer_list,current_trail_index, finger_map_index); return GNUNET_YES; } return GNUNET_SYSERR; } /** * FIXME: Use flag in the case finger peer map does not contain predcessor * then its NULL. Ideally it should never happen. * Get my current predecessor from the finger peer map * @return Current predecessor. */ static struct FingerInfo * get_predecessor() { struct GNUNET_CONTAINER_MultiPeerMapIterator *finger_iter; struct GNUNET_PeerIdentity key_ret; unsigned int finger_index; struct FingerInfo *my_predecessor; /* Iterate over finger peer map and extract your predecessor. */ finger_iter = GNUNET_CONTAINER_multipeermap_iterator_create (finger_peermap); for (finger_index = 0; finger_index < GNUNET_CONTAINER_multipeermap_size (finger_peermap); finger_index++) { if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (finger_iter,&key_ret,(const void **)&my_predecessor)) { if(1 == my_predecessor->finger_map_index) { break; } } } GNUNET_CONTAINER_multipeermap_iterator_destroy (finger_iter); return my_predecessor; } /** * Core handle for p2p verify successor messages. * @param cls closure * @param message message * @param peer peer identity this notification is about * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int handle_dht_p2p_verify_successor(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerVerifySuccessorMessage *vsm; struct GNUNET_PeerIdentity *trail_peer_list; struct FriendInfo *target_friend; struct GNUNET_PeerIdentity *next_hop; struct GNUNET_PeerIdentity *source_peer; unsigned int trail_length; unsigned int current_trail_index; size_t msize; msize = ntohs (message->size); if (msize < sizeof (struct PeerVerifySuccessorMessage)) { GNUNET_break_op (0); return GNUNET_YES; } vsm = (struct PeerVerifySuccessorMessage *) message; trail_length = ntohl (vsm->trail_length); if ((msize < sizeof (struct PeerVerifySuccessorMessage) + trail_length * sizeof (struct GNUNET_PeerIdentity)) || (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } current_trail_index = ntohl (vsm->current_trail_index); trail_peer_list = (struct GNUNET_PeerIdentity *) &vsm[1]; source_peer = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (source_peer, &(vsm->source_peer), sizeof (struct GNUNET_PeerIdentity)); next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsm->successor),&my_identity))) { struct FingerInfo *my_predecessor; current_trail_index = trail_length - 1; if (current_trail_index == 0) memcpy (next_hop, source_peer, sizeof (struct GNUNET_PeerIdentity)); else memcpy (next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity)); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); GNUNET_free (next_hop); my_predecessor = get_predecessor(); if (0 == (GNUNET_CRYPTO_cmp_peer_identity (source_peer, &(my_predecessor->finger_identity)))) { GDS_NEIGHBOURS_send_verify_successor_result (source_peer, &(my_identity), &(my_predecessor->finger_identity), target_friend, trail_peer_list, trail_length, current_trail_index); } else { struct GNUNET_PeerIdentity *new_successor_trail; int new_trail_length; int i; new_trail_length = trail_length + my_predecessor->trail_length; new_successor_trail = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity) * new_trail_length); memcpy (new_successor_trail, trail_peer_list, (trail_length) * sizeof (struct GNUNET_PeerIdentity)); struct TrailPeerList *iterator; iterator = GNUNET_malloc (sizeof (struct TrailPeerList)); iterator = my_predecessor->head; i = trail_length; while (i < new_trail_length) { memcpy (&new_successor_trail[i], &(iterator->peer), sizeof (struct GNUNET_PeerIdentity)); iterator = iterator->next; i++; } GDS_NEIGHBOURS_send_verify_successor_result (source_peer, &(my_identity), &(my_predecessor->finger_identity), target_friend, new_successor_trail, new_trail_length, current_trail_index); } } else { current_trail_index = current_trail_index + 1; memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); GNUNET_free (next_hop); GDS_NEIGHBOURS_send_verify_successor (source_peer, &(vsm->successor),target_friend, trail_peer_list, trail_length, current_trail_index); } return GNUNET_YES; } /** * Core handle for p2p notify new successor messages. * @param cls closure * @param message message * @param peer peer identity this notification is about * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int handle_dht_p2p_notify_new_successor(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerNotifyNewSuccessorMessage *nsm; struct GNUNET_PeerIdentity *trail_peer_list; unsigned int current_trail_index; size_t msize; unsigned int trail_length; msize = ntohs (message->size); if (msize < sizeof (struct PeerNotifyNewSuccessorMessage)) { GNUNET_break_op (0); return GNUNET_YES; } nsm = (struct PeerNotifyNewSuccessorMessage *) message; trail_length = ntohl (nsm->trail_length); if ((msize < sizeof (struct PeerNotifyNewSuccessorMessage) + trail_length * sizeof (struct GNUNET_PeerIdentity)) || (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } current_trail_index = ntohl (nsm->current_index); trail_peer_list = (struct GNUNET_PeerIdentity *) &nsm[1]; if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(nsm->destination_peer), &my_identity))) { struct GNUNET_PeerIdentity *new_trail; new_trail = invert_trail_list (&(nsm->source_peer), trail_peer_list, trail_length); finger_table_add (&(nsm->source_peer), new_trail, trail_length, 1); return GNUNET_YES; } else { struct FriendInfo *target_friend; struct GNUNET_PeerIdentity *next_hop; target_friend = GNUNET_malloc (sizeof (struct FriendInfo)); next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); current_trail_index = current_trail_index + 1; memcpy (next_hop, &trail_peer_list[current_trail_index], sizeof (struct GNUNET_PeerIdentity)); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); GNUNET_free (next_hop); GDS_NEIGHBOURS_send_notify_new_successor (&(nsm->source_peer), &(nsm->destination_peer), target_friend, trail_peer_list, trail_length, current_trail_index); } return GNUNET_YES; } /** * Core handle for p2p verify successor result messages. * @param cls closure * @param message message * @param peer peer identity this notification is about * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int handle_dht_p2p_verify_successor_result(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerVerifySuccessorResultMessage *vsrm; struct FriendInfo *target_friend; struct GNUNET_PeerIdentity *trail_peer_list; struct GNUNET_PeerIdentity *next_hop; unsigned int trail_length; unsigned int current_trail_index; size_t msize; msize = ntohs (message->size); if (msize < sizeof (struct PeerVerifySuccessorResultMessage)) { GNUNET_break_op (0); return GNUNET_YES; } vsrm = (struct PeerVerifySuccessorResultMessage *) message; trail_length = ntohl (vsrm->trail_length); if ((msize < sizeof (struct PeerVerifySuccessorResultMessage) + trail_length * sizeof (struct GNUNET_PeerIdentity)) || (trail_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } current_trail_index = ntohl (vsrm->current_index); trail_peer_list = (struct GNUNET_PeerIdentity *) &vsrm[1]; if(0 == (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->destination_peer), &(my_identity)))) { if(0 != (GNUNET_CRYPTO_cmp_peer_identity (&(vsrm->my_predecessor), &(my_identity)))) { finger_table_add (&(vsrm->my_predecessor), trail_peer_list, trail_length, 0); next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); memcpy (next_hop, &trail_peer_list[0], sizeof (struct GNUNET_PeerIdentity)); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); current_trail_index = 0; GNUNET_free (next_hop); GDS_NEIGHBOURS_send_notify_new_successor (&my_identity, &(vsrm->my_predecessor), target_friend, trail_peer_list, trail_length, current_trail_index); } } else { next_hop = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); current_trail_index = current_trail_index - 1; if (current_trail_index == 0) memcpy (next_hop, &(vsrm->destination_peer), sizeof (struct GNUNET_PeerIdentity)); else memcpy (next_hop, &trail_peer_list[current_trail_index-1], sizeof (struct GNUNET_PeerIdentity)); target_friend = GNUNET_CONTAINER_multipeermap_get (friend_peermap, next_hop); GNUNET_free (next_hop); GDS_NEIGHBOURS_send_verify_successor_result (&(vsrm->destination_peer), &(vsrm->source_successor), &(vsrm->my_predecessor), target_friend, trail_peer_list, trail_length, current_trail_index); } return GNUNET_YES; } /** * Initialize neighbours subsystem. * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GDS_NEIGHBOURS_init() { static struct GNUNET_CORE_MessageHandler core_handlers[] = { {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0}, {&handle_dht_p2p_get_result, GNUNET_MESSAGE_TYPE_DHT_P2P_GET_RESULT, 0}, {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0}, {&handle_dht_p2p_trail_setup, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP, 0}, {&handle_dht_p2p_trail_setup_result, GNUNET_MESSAGE_TYPE_DHT_P2P_TRAIL_SETUP_RESULT, 0}, {&handle_dht_p2p_verify_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR, 0}, {&handle_dht_p2p_verify_successor_result, GNUNET_MESSAGE_TYPE_DHT_P2P_VERIFY_SUCCESSOR_RESULT, 0}, {&handle_dht_p2p_notify_new_successor, GNUNET_MESSAGE_TYPE_DHT_P2P_NOTIFY_NEW_SUCCESSOR, 0}, {NULL, 0, 0} }; core_api = GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect, &handle_core_disconnect, NULL, GNUNET_NO, NULL, GNUNET_NO, core_handlers); if (NULL == core_api) return GNUNET_SYSERR; friend_peermap = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO); finger_peermap = GNUNET_CONTAINER_multipeermap_create (MAX_FINGERS, GNUNET_NO); return GNUNET_OK; } /** * Shutdown neighbours subsystem. */ void GDS_NEIGHBOURS_done () { if (NULL == core_api) return; GNUNET_CORE_disconnect (core_api); core_api = NULL; GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (friend_peermap)); GNUNET_CONTAINER_multipeermap_destroy (friend_peermap); friend_peermap = NULL; GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (finger_peermap)); GNUNET_CONTAINER_multipeermap_destroy (finger_peermap); finger_peermap = NULL; if (GNUNET_SCHEDULER_NO_TASK != find_finger_trail_task) { GNUNET_SCHEDULER_cancel (find_finger_trail_task); find_finger_trail_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != verify_successor) { GNUNET_SCHEDULER_cancel (verify_successor); verify_successor = GNUNET_SCHEDULER_NO_TASK; } } /** * Get the ID of the local node. * * @return identity of the local node */ struct GNUNET_PeerIdentity * GDS_NEIGHBOURS_get_id () { return &my_identity; } /* end of gnunet-service-xdht_neighbours.c */ gnunet-0.10.1/src/dht/gnunet-service-xdht_neighbours.h0000644000175000017500000001111312320724374017662 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_neighbours.h * @brief GNUnet DHT routing code * @author Christian Grothoff * @author Nathan Evans */ #ifndef GNUNET_SERVICE_XDHT_NEIGHBOURS_H #define GNUNET_SERVICE_XDHT_NEIGHBOURS_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_dht_service.h" /** * FIXME: Change the comment to explain about usage of this in find successor. * Field in trail setup message to understand if the message is sent to an * intermediate finger, friend or me. */ enum current_destination_type { FRIEND , FINGER , MY_ID , VALUE }; /** * Perform a PUT operation. Forwards the given request to other * peers. Does not store the data locally. Does not give the * data to local clients. May do nothing if this is the only * peer in the network (or if we are the closest peer in the * network). * * @param type type of the block * @param options routing options * @param desired_replication_level desired replication count * @param expiration_time when does the content expire * @param hop_count how many hops has this message traversed so far * @param key key for the content * @param put_path_length number of entries in @a put_path * @param put_path peers this request has traversed so far (if tracked) * @param data payload to store * @param data_size number of bytes in @a data */ void GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint32_t desired_replication_level, struct GNUNET_TIME_Absolute expiration_time, uint32_t hop_count, const struct GNUNET_HashCode * key, unsigned int put_path_length, struct GNUNET_PeerIdentity *put_path, const void *data, size_t data_size, struct GNUNET_PeerIdentity *current_destination, enum current_destination_type dest_type, struct GNUNET_PeerIdentity *target_peer_id); /** * * @param source_peer * @param get_path * @param get_path_length * @param key */ void GDS_NEIGHBOURS_handle_get (struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, struct GNUNET_HashCode *key, struct GNUNET_PeerIdentity *target_peer, struct GNUNET_PeerIdentity *current_destination, enum current_destination_type *type); /** * Send get result back to requesting client. * @param source_peer * @param get_path * @param get_path_length * @param key * @param destination_peer * @param current_path_index * @param data * @param data_size */ void GDS_NEIGHBOURS_send_get_result (struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, struct GNUNET_HashCode *key, struct GNUNET_PeerIdentity *destination_peer, unsigned int current_path_index, const void *data, size_t data_size, struct GNUNET_PeerIdentity *next_peer); /** * Initialize neighbours subsystem. * * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GDS_NEIGHBOURS_init (void); /** * Shutdown neighbours subsystem. */ void GDS_NEIGHBOURS_done (void); /** * Get the ID of the local node. * * @return identity of the local node */ struct GNUNET_PeerIdentity * GDS_NEIGHBOURS_get_id (); #endifgnunet-0.10.1/src/dht/gnunet-service-dht_routing.c0000644000175000017500000003236012225777502017023 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_routing.c * @brief GNUnet DHT tracking of requests for routing replies * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-dht_neighbours.h" #include "gnunet-service-dht_routing.h" #include "gnunet-service-dht.h" /** * Number of requests we track at most (for routing replies). */ #define DHT_MAX_RECENT (1024 * 16) /** * Information we keep about all recent GET requests * so that we can route replies. */ struct RecentRequest { /** * The peer this request was received from. */ struct GNUNET_PeerIdentity peer; /** * Key of this request. */ struct GNUNET_HashCode key; /** * Position of this node in the min heap. */ struct GNUNET_CONTAINER_HeapNode *heap_node; /** * Bloomfilter for replies to drop. */ struct GNUNET_CONTAINER_BloomFilter *reply_bf; /** * Type of the requested block. */ enum GNUNET_BLOCK_Type type; /** * extended query (see gnunet_block_lib.h). Allocated at the * end of this struct. */ const void *xquery; /** * Number of bytes in xquery. */ size_t xquery_size; /** * Mutator value for the reply_bf, see gnunet_block_lib.h */ uint32_t reply_bf_mutator; /** * Request options. */ enum GNUNET_DHT_RouteOption options; }; /** * Recent requests by time inserted. */ static struct GNUNET_CONTAINER_Heap *recent_heap; /** * Recently seen requests by key. */ static struct GNUNET_CONTAINER_MultiHashMap *recent_map; /** * Closure for the 'process' function. */ struct ProcessContext { /** * Path of the original PUT */ const struct GNUNET_PeerIdentity *put_path; /** * Path of the reply. */ const struct GNUNET_PeerIdentity *get_path; /** * Payload of the reply. */ const void *data; /** * Expiration time of the result. */ struct GNUNET_TIME_Absolute expiration_time; /** * Number of entries in 'put_path'. */ unsigned int put_path_length; /** * Number of entries in 'get_path'. */ unsigned int get_path_length; /** * Number of bytes in 'data'. */ size_t data_size; /** * Type of the reply. */ enum GNUNET_BLOCK_Type type; }; /** * Forward the result to the given peer if it matches the request. * * @param cls the `struct ProcessContext` with the result * @param key the query * @param value the `struct RecentRequest` with the request * @return #GNUNET_OK (continue to iterate), * #GNUNET_SYSERR if the result is malformed or type unsupported */ static int process (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ProcessContext *pc = cls; struct RecentRequest *rr = value; enum GNUNET_BLOCK_EvaluationResult eval; unsigned int gpl; unsigned int ppl; struct GNUNET_HashCode hc; const struct GNUNET_HashCode *eval_key; if ((rr->type != GNUNET_BLOCK_TYPE_ANY) && (rr->type != pc->type)) return GNUNET_OK; /* type missmatch */ if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE)) { gpl = pc->get_path_length; ppl = pc->put_path_length; } else { gpl = 0; ppl = 0; } if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) && (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO)) { /* key may not match HELLO, which is OK since * the search is approximate. Still, the evaluation * would fail since the match is not exact. So * we fake it by changing the key to the actual PID ... */ GNUNET_BLOCK_get_key (GDS_block_context, GNUNET_BLOCK_TYPE_DHT_HELLO, pc->data, pc->data_size, &hc); eval_key = &hc; } else { eval_key = key; } eval = GNUNET_BLOCK_evaluate (GDS_block_context, pc->type, eval_key, &rr->reply_bf, rr->reply_bf_mutator, rr->xquery, rr->xquery_size, pc->data, pc->data_size); switch (eval) { case GNUNET_BLOCK_EVALUATION_OK_MORE: case GNUNET_BLOCK_EVALUATION_OK_LAST: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Good REPLIES matched against routing table"), 1, GNUNET_NO); GDS_NEIGHBOURS_handle_reply (&rr->peer, pc->type, pc->expiration_time, key, ppl, pc->put_path, gpl, pc->get_path, pc->data, pc->data_size); break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Duplicate REPLIES matched against routing table"), 1, GNUNET_NO); return GNUNET_OK; case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Invalid REPLIES matched against routing table"), 1, GNUNET_NO); return GNUNET_SYSERR; case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Irrelevant REPLIES matched against routing table"), 1, GNUNET_NO); return GNUNET_OK; case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: GNUNET_break (0); return GNUNET_OK; case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: GNUNET_break (0); return GNUNET_OK; case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Unsupported REPLIES matched against routing table"), 1, GNUNET_NO); return GNUNET_SYSERR; default: GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Handle a reply (route to origin). Only forwards the reply back to * other peers waiting for it. Does not do local caching or * forwarding to local clients. Essentially calls * GDS_NEIGHBOURS_handle_reply for all peers that sent us a matching * request recently. * * @param type type of the block * @param expiration_time when does the content expire * @param key key for the content * @param put_path_length number of entries in put_path * @param put_path peers the original PUT traversed (if tracked) * @param get_path_length number of entries in get_path * @param get_path peers this reply has traversed so far (if tracked) * @param data payload of the reply * @param data_size number of bytes in data */ void GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size) { struct ProcessContext pc; pc.type = type; pc.expiration_time = expiration_time; pc.put_path_length = put_path_length; pc.put_path = put_path; pc.get_path_length = get_path_length; pc.get_path = get_path; pc.data = data; pc.data_size = data_size; if (NULL == data) { /* Some apps might have an 'empty' reply as a valid reply; however, 'process' will call GNUNET_BLOCK_evaluate' which treats a 'NULL' reply as request-validation (but we need response-validation). So we set 'data' to a 0-byte non-NULL value just to be sure */ GNUNET_break (0 == data_size); pc.data_size = 0; pc.data = ""; /* something not null */ } GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, &process, &pc); } /** * Remove the oldest entry from the DHT routing table. Must only * be called if it is known that there is at least one entry * in the heap and hashmap. */ static void expire_oldest_entry () { struct RecentRequest *recent_req; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Entries removed from routing table"), 1, GNUNET_NO); recent_req = GNUNET_CONTAINER_heap_peek (recent_heap); GNUNET_assert (recent_req != NULL); GNUNET_CONTAINER_heap_remove_node (recent_req->heap_node); GNUNET_CONTAINER_bloomfilter_free (recent_req->reply_bf); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (recent_map, &recent_req->key, recent_req)); GNUNET_free (recent_req); } /** * Try to combine multiple recent requests for the same value * (if they come from the same peer). * * @param cls the new 'struct RecentRequest' (to discard upon successful combination) * @param key the query * @param value the existing 'struct RecentRequest' (to update upon successful combination) * @return GNUNET_OK (continue to iterate), * GNUNET_SYSERR if the request was successfully combined */ static int try_combine_recent (void *cls, const struct GNUNET_HashCode * key, void *value) { struct RecentRequest *in = cls; struct RecentRequest *rr = value; if ( (0 != memcmp (&in->peer, &rr->peer, sizeof (struct GNUNET_PeerIdentity))) || (in->type != rr->type) || (in->xquery_size != rr->xquery_size) || (0 != memcmp (in->xquery, rr->xquery, in->xquery_size)) ) return GNUNET_OK; if (in->reply_bf_mutator != rr->reply_bf_mutator) { rr->reply_bf_mutator = in->reply_bf_mutator; GNUNET_CONTAINER_bloomfilter_free (rr->reply_bf); rr->reply_bf = in->reply_bf; } else { GNUNET_CONTAINER_bloomfilter_or2 (rr->reply_bf, in->reply_bf); GNUNET_CONTAINER_bloomfilter_free (in->reply_bf); } GNUNET_free (in); return GNUNET_SYSERR; } /** * Add a new entry to our routing table. * * @param sender peer that originated the request * @param type type of the block * @param options options for processing * @param key key for the content * @param xquery extended query * @param xquery_size number of bytes in @a xquery * @param reply_bf bloomfilter to filter duplicates * @param reply_bf_mutator mutator for @a reply_bf */ void GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender, enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, const struct GNUNET_HashCode * key, const void *xquery, size_t xquery_size, const struct GNUNET_CONTAINER_BloomFilter *reply_bf, uint32_t reply_bf_mutator) { struct RecentRequest *recent_req; while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT) expire_oldest_entry (); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Entries added to routing table"), 1, GNUNET_NO); recent_req = GNUNET_malloc (sizeof (struct RecentRequest) + xquery_size); recent_req->peer = *sender; recent_req->key = *key; recent_req->reply_bf = GNUNET_CONTAINER_bloomfilter_copy (reply_bf); recent_req->type = type; recent_req->options = options; recent_req->xquery = &recent_req[1]; memcpy (&recent_req[1], xquery, xquery_size); recent_req->xquery_size = xquery_size; recent_req->reply_bf_mutator = reply_bf_mutator; if (GNUNET_SYSERR == GNUNET_CONTAINER_multihashmap_get_multiple (recent_map, key, &try_combine_recent, recent_req)) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# DHT requests combined"), 1, GNUNET_NO); return; } recent_req->heap_node = GNUNET_CONTAINER_heap_insert (recent_heap, recent_req, GNUNET_TIME_absolute_get ().abs_value_us); GNUNET_CONTAINER_multihashmap_put (recent_map, key, recent_req, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } /** * Initialize routing subsystem. */ void GDS_ROUTING_init () { recent_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); recent_map = GNUNET_CONTAINER_multihashmap_create (DHT_MAX_RECENT * 4 / 3, GNUNET_NO); } /** * Shutdown routing subsystem. */ void GDS_ROUTING_done () { while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0) expire_oldest_entry (); GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (recent_heap)); GNUNET_CONTAINER_heap_destroy (recent_heap); recent_heap = NULL; GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (recent_map)); GNUNET_CONTAINER_multihashmap_destroy (recent_map); recent_map = NULL; } /* end of gnunet-service-dht_routing.c */ gnunet-0.10.1/src/dht/gnunet-service-dht_hello.c0000644000175000017500000000730512274162760016436 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_hello.c * @brief GNUnet DHT integration with peerinfo * @author Christian Grothoff * * TODO: * - consider adding mechanism to remove expired HELLOs */ #include "platform.h" #include "gnunet-service-dht.h" #include "gnunet-service-dht_hello.h" #include "gnunet_peerinfo_service.h" /** * Handle for peerinfo notifications. */ static struct GNUNET_PEERINFO_NotifyContext *pnc; /** * Hash map of peers to HELLOs. */ static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello; /** * Obtain a peer's HELLO if available * * @param peer peer to look for a HELLO from * @return HELLO for the given peer */ const struct GNUNET_HELLO_Message * GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer) { if (NULL == peer_to_hello) return NULL; return GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer); } /** * Function called for each HELLO known to PEERINFO. * * @param cls closure * @param peer id of the peer, NULL for last call * @param hello hello message for the peer (can be NULL) * @param err_msg error message (not used) * * FIXME this is called once per address. Merge instead of replacing? */ static void process_hello (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { struct GNUNET_TIME_Absolute ex; struct GNUNET_HELLO_Message *hm; if (hello == NULL) return; ex = GNUNET_HELLO_get_last_expiration (hello); if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us) return; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# HELLOs obtained from peerinfo"), 1, GNUNET_NO); hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer); GNUNET_free_non_null (hm); hm = GNUNET_malloc (GNUNET_HELLO_size (hello)); memcpy (hm, hello, GNUNET_HELLO_size (hello)); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_put (peer_to_hello, peer, hm, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); } /** * Initialize HELLO subsystem. */ void GDS_HELLO_init () { pnc = GNUNET_PEERINFO_notify (GDS_cfg, GNUNET_NO, &process_hello, NULL); peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO); } /** * Free memory occopied by the HELLO. */ static int free_hello (void *cls, const struct GNUNET_PeerIdentity *key, void *hello) { GNUNET_free (hello); return GNUNET_OK; } /** * Shutdown HELLO subsystem. */ void GDS_HELLO_done () { if (NULL != pnc) { GNUNET_PEERINFO_notify_cancel (pnc); pnc = NULL; } if (NULL != peer_to_hello) { GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello, &free_hello, NULL); GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello); } } /* end of gnunet-service-dht_hello.c */ gnunet-0.10.1/src/dht/gnunet-service-xdht_datacache.c0000644000175000017500000002116712320724374017417 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_datacache.c * @brief GNUnet DHT service's datacache integration * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_datacache_lib.h" #include "gnunet-service-xdht_clients.h" #include "gnunet-service-xdht_datacache.h" #include "gnunet-service-xdht_routing.h" #include "gnunet-service-xdht.h" #define LOG(kind,...) GNUNET_log_from (kind, "dht-dtcache",__VA_ARGS__) /** * Handle to the datacache service (for inserting/retrieving data) */ static struct GNUNET_DATACACHE_Handle *datacache; /** * Handle a datum we've received from another peer. Cache if * possible. * * @param expiration when will the reply expire * @param key the query this reply is for * @param put_path_length number of peers in 'put_path' * @param put_path path the reply took on put * @param type type of the reply * @param data_size number of bytes in 'data' * @param data application payload data */ void GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data) { int r; if (NULL == datacache) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("%s request received, but have no datacache!\n"), "PUT"); return; } if (data_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } /* Put size is actual data size plus struct overhead plus path length (if any) */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# ITEMS stored in datacache"), 1, GNUNET_NO); r = GNUNET_DATACACHE_put (datacache, key, data_size, data, type, expiration, put_path_length, put_path); LOG (GNUNET_ERROR_TYPE_DEBUG, "DATACACHE PUT for key %s [%u] completed (%d) after %u hops\n", GNUNET_h2s (key), data_size, r, put_path_length); } /** * Context containing information about a GET request. */ struct GetRequestContext { /** * extended query (see gnunet_block_lib.h). */ const void *xquery; /** * Bloomfilter to filter out duplicate replies (updated) */ struct GNUNET_CONTAINER_BloomFilter **reply_bf; /** * The key this request was about */ struct GNUNET_HashCode key; /** * Number of bytes in xquery. */ size_t xquery_size; /** * Mutator value for the reply_bf, see gnunet_block_lib.h */ uint32_t reply_bf_mutator; /** * Return value to give back. */ enum GNUNET_BLOCK_EvaluationResult eval; }; /** * Iterator for local get request results, * * @param cls closure for iterator, a DatacacheGetContext * @param exp when does this value expire? * @param key the key this data is stored under * @param size the size of the data identified by key * @param data the actual data * @param type the type of the data * @param put_path_length number of peers in 'put_path' * @param put_path path the reply took on put * @return GNUNET_OK to continue iteration, anything else * to stop iteration. */ static int datacache_get_iterator (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path) { struct GetRequestContext *ctx = cls; enum GNUNET_BLOCK_EvaluationResult eval; eval = GNUNET_BLOCK_evaluate (GDS_block_context, type, key, ctx->reply_bf, ctx->reply_bf_mutator, ctx->xquery, ctx->xquery_size, data, size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Found reply for query %s in datacache, evaluation result is %d\n", GNUNET_h2s (key), (int) eval); ctx->eval = eval; switch (eval) { case GNUNET_BLOCK_EVALUATION_OK_MORE: case GNUNET_BLOCK_EVALUATION_OK_LAST: /* forward to local clients */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Good RESULTS found in datacache"), 1, GNUNET_NO); /* GDS_CLIENTS_handle_reply (exp, key, 0, NULL, put_path_length, put_path, type, size, data);*/ /* forward to other peers */ GDS_ROUTING_process (type, exp, key, put_path_length, put_path, 0, NULL, data, size); break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Duplicate RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Invalid RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Irrelevant RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: GNUNET_break (0); break; case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: GNUNET_break_op (0); return GNUNET_SYSERR; case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Unsupported RESULTS found in datacache"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Unsupported block type (%u) in local response!\n"), type); break; } return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK; } /** * Handle a GET request we've received from another peer. * * @param key the query * @param type requested data type * @param xquery extended query * @param xquery_size number of bytes in xquery * @param reply_bf where the reply bf is (to be) stored, possibly updated, can be NULL * @param reply_bf_mutator mutation value for reply_bf * @return evaluation result for the local replies */ enum GNUNET_BLOCK_EvaluationResult GDS_DATACACHE_handle_get (const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_CONTAINER_BloomFilter **reply_bf, uint32_t reply_bf_mutator) { struct GetRequestContext ctx; unsigned int r; if (datacache == NULL) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests given to datacache"), 1, GNUNET_NO); ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID; ctx.key = *key; ctx.xquery = xquery; ctx.xquery_size = xquery_size; ctx.reply_bf = reply_bf; ctx.reply_bf_mutator = reply_bf_mutator; r = GNUNET_DATACACHE_get (datacache, key, type, &datacache_get_iterator, &ctx); LOG (GNUNET_ERROR_TYPE_DEBUG, "DATACACHE GET for key %s completed (%d). %u results found.\n", GNUNET_h2s (key), ctx.eval, r); return ctx.eval; } /** * Initialize datacache subsystem. */ void GDS_DATACACHE_init () { datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache"); } /** * Shutdown datacache subsystem. */ void GDS_DATACACHE_done () { if (datacache != NULL) { GNUNET_DATACACHE_destroy (datacache); datacache = NULL; } } /* end of gnunet-service-dht_datacache.c */ gnunet-0.10.1/src/dht/gnunet-service-xdht_clients.h0000644000175000017500000001274212320724374017167 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_clients.h * @brief GNUnet DHT service's client management code * @author Christian Grothoff * @author Nathan Evans */ #ifndef GNUNET_SERVICE_DHT_CLIENT_H #define GNUNET_SERVICE_DHT_CLIENT_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" /** * Handle a reply we've received from another peer. If the reply * matches any of our pending queries, forward it to the respective * client(s). * * @param expiration when will the reply expire * @param key the query this reply is for * @param get_path_length number of peers in @a get_path * @param get_path path the reply took on get * @param put_path_length number of peers in @a put_path * @param put_path path the reply took on put * @param type type of the reply * @param data_size number of bytes in @a data * @param data application payload data */ void GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode *key, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data); /** * Check if some client is monitoring GET messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the GET path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param key Key of the requested data. */ void GDS_CLIENTS_process_get (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode *key); /** * Check if some client is monitoring GET RESP messages and notify * them in that case. * * @param type The type of data in the result. * @param get_path Peers on GET path (or NULL if not recorded). * @param get_path_length number of entries in @a get_path. * @param put_path peers on the PUT path (or NULL if not recorded). * @param put_path_length number of entries in @a get_path. * @param exp Expiration time of the data. * @param key Key of the @a data. * @param data Pointer to the result data. * @param size Number of bytes in @a data. */ void GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size); /** * Check if some client is monitoring PUT messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the PUT path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param exp Expiration time of the data. * @param key Key under which data is to be stored. * @param data Pointer to the data carried. * @param size Number of bytes in data. */ void GDS_CLIENTS_process_put (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size); /** * Initialize client subsystem. * * @param server the initialized server */ void GDS_CLIENTS_init (struct GNUNET_SERVER_Handle *server); /** * Shutdown client subsystem. */ void GDS_CLIENTS_done (void); #endif gnunet-0.10.1/src/dht/Makefile.in0000644000175000017500000016610112320752060013427 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-dht$(EXEEXT) \ gnunet-service-dht-xvine$(EXEEXT) noinst_PROGRAMS = gnunet-dht-monitor$(EXEEXT) gnunet-dht-get$(EXEEXT) \ gnunet-dht-put$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = test_dht_api$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_dht_twopeer$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_dht_multipeer$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_dht_line$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_dht_2dtorus$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_dht_monitor$(EXEEXT) @ENABLE_TEST_RUN_TRUE@TESTS = test_dht_api$(EXEEXT) $(check_SCRIPTS) \ @ENABLE_TEST_RUN_TRUE@ test_dht_twopeer$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_dht_line$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_dht_monitor$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_1) subdir = src/dht DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/dht.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = dht.conf CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = libgnunetdhttest_a_AR = $(AR) $(ARFLAGS) am_libgnunetdhttest_a_OBJECTS = dht_test_lib.$(OBJEXT) libgnunetdhttest_a_OBJECTS = $(am_libgnunetdhttest_a_OBJECTS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunet_plugin_block_dht_la_OBJECTS = plugin_block_dht.lo libgnunet_plugin_block_dht_la_OBJECTS = \ $(am_libgnunet_plugin_block_dht_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_block_dht_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_block_dht_la_LDFLAGS) $(LDFLAGS) -o $@ libgnunetdht_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetdht_la_OBJECTS = dht_api.lo libgnunetdht_la_OBJECTS = $(am_libgnunetdht_la_OBJECTS) libgnunetdht_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetdht_la_LDFLAGS) $(LDFLAGS) \ -o $@ PROGRAMS = $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_dht_get_OBJECTS = gnunet-dht-get.$(OBJEXT) gnunet_dht_get_OBJECTS = $(am_gnunet_dht_get_OBJECTS) am_gnunet_dht_monitor_OBJECTS = gnunet-dht-monitor.$(OBJEXT) gnunet_dht_monitor_OBJECTS = $(am_gnunet_dht_monitor_OBJECTS) am_gnunet_dht_put_OBJECTS = gnunet-dht-put.$(OBJEXT) gnunet_dht_put_OBJECTS = $(am_gnunet_dht_put_OBJECTS) am_gnunet_service_dht_OBJECTS = gnunet-service-dht.$(OBJEXT) \ gnunet-service-dht_clients.$(OBJEXT) \ gnunet-service-dht_datacache.$(OBJEXT) \ gnunet-service-dht_hello.$(OBJEXT) \ gnunet-service-dht_nse.$(OBJEXT) \ gnunet-service-dht_neighbours.$(OBJEXT) \ gnunet-service-dht_routing.$(OBJEXT) gnunet_service_dht_OBJECTS = $(am_gnunet_service_dht_OBJECTS) gnunet_service_dht_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_gnunet_service_dht_xvine_OBJECTS = gnunet-service-xdht.$(OBJEXT) \ gnunet-service-xdht_clients.$(OBJEXT) \ gnunet-service-xdht_datacache.$(OBJEXT) \ gnunet-service-xdht_hello.$(OBJEXT) \ gnunet-service-xdht_nse.$(OBJEXT) \ gnunet-service-xdht_neighbours.$(OBJEXT) \ gnunet-service-xdht_routing.$(OBJEXT) gnunet_service_dht_xvine_OBJECTS = \ $(am_gnunet_service_dht_xvine_OBJECTS) gnunet_service_dht_xvine_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_dht_2dtorus_OBJECTS = test_dht_topo.$(OBJEXT) test_dht_2dtorus_OBJECTS = $(am_test_dht_2dtorus_OBJECTS) am_test_dht_api_OBJECTS = test_dht_api.$(OBJEXT) test_dht_api_OBJECTS = $(am_test_dht_api_OBJECTS) am_test_dht_line_OBJECTS = test_dht_topo.$(OBJEXT) test_dht_line_OBJECTS = $(am_test_dht_line_OBJECTS) am_test_dht_monitor_OBJECTS = test_dht_monitor.$(OBJEXT) test_dht_monitor_OBJECTS = $(am_test_dht_monitor_OBJECTS) am_test_dht_multipeer_OBJECTS = test_dht_topo.$(OBJEXT) test_dht_multipeer_OBJECTS = $(am_test_dht_multipeer_OBJECTS) am_test_dht_twopeer_OBJECTS = test_dht_topo.$(OBJEXT) test_dht_twopeer_OBJECTS = $(am_test_dht_twopeer_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetdhttest_a_SOURCES) \ $(libgnunet_plugin_block_dht_la_SOURCES) \ $(libgnunetdht_la_SOURCES) $(gnunet_dht_get_SOURCES) \ $(gnunet_dht_monitor_SOURCES) $(gnunet_dht_put_SOURCES) \ $(gnunet_service_dht_SOURCES) \ $(gnunet_service_dht_xvine_SOURCES) \ $(test_dht_2dtorus_SOURCES) $(test_dht_api_SOURCES) \ $(test_dht_line_SOURCES) $(test_dht_monitor_SOURCES) \ $(test_dht_multipeer_SOURCES) $(test_dht_twopeer_SOURCES) DIST_SOURCES = $(libgnunetdhttest_a_SOURCES) \ $(libgnunet_plugin_block_dht_la_SOURCES) \ $(libgnunetdht_la_SOURCES) $(gnunet_dht_get_SOURCES) \ $(gnunet_dht_monitor_SOURCES) $(gnunet_dht_put_SOURCES) \ $(gnunet_service_dht_SOURCES) \ $(gnunet_service_dht_xvine_SOURCES) \ $(test_dht_2dtorus_SOURCES) $(test_dht_api_SOURCES) \ $(test_dht_line_SOURCES) $(test_dht_monitor_SOURCES) \ $(test_dht_multipeer_SOURCES) $(test_dht_twopeer_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck @HAVE_EXPERIMENTAL_TRUE@am__EXEEXT_1 = test_dht_2dtorus$(EXEEXT) \ @HAVE_EXPERIMENTAL_TRUE@ test_dht_multipeer$(EXEEXT) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ dht.conf @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov lib_LTLIBRARIES = \ libgnunetdht.la libgnunetdht_la_SOURCES = \ dht_api.c dht.h libgnunetdht_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) \ $(LTLIBINTL) libgnunetdht_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 2:0:2 plugin_LTLIBRARIES = \ libgnunet_plugin_block_dht.la libgnunet_plugin_block_dht_la_SOURCES = \ plugin_block_dht.c libgnunet_plugin_block_dht_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_dht_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_dht_la_DEPENDENCIES = \ $(top_builddir)/src/block/libgnunetblock.la gnunet_service_dht_SOURCES = \ gnunet-service-dht.c gnunet-service-dht.h \ gnunet-service-dht_clients.c gnunet-service-dht_clients.h \ gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \ gnunet-service-dht_hello.c gnunet-service-dht_hello.h \ gnunet-service-dht_nse.c gnunet-service-dht_nse.h \ gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \ gnunet-service-dht_routing.c gnunet-service-dht_routing.h gnunet_service_dht_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lm gnunet_service_dht_xvine_SOURCES = \ gnunet-service-xdht.c gnunet-service-xdht.h \ gnunet-service-xdht_clients.c gnunet-service-xdht_clients.h \ gnunet-service-xdht_datacache.c gnunet-service-xdht_datacache.h \ gnunet-service-xdht_hello.c gnunet-service-xdht_hello.h \ gnunet-service-xdht_nse.c gnunet-service-xdht_nse.h \ gnunet-service-xdht_neighbours.c gnunet-service-xdht_neighbours.h \ gnunet-service-xdht_routing.c gnunet-service-xdht_routing.h gnunet_service_dht_xvine_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lm gnunet_dht_get_SOURCES = \ gnunet-dht-get.c gnunet_dht_get_LDADD = \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_dht_get_DEPENDENCIES = \ libgnunetdht.la gnunet_dht_put_SOURCES = \ gnunet-dht-put.c gnunet_dht_put_LDADD = \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_dht_put_DEPENDENCIES = \ libgnunetdht.la gnunet_dht_monitor_SOURCES = \ gnunet-dht-monitor.c gnunet_dht_monitor_LDADD = \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_dht_monitor_DEPENDENCIES = \ libgnunetdht.la @HAVE_TESTING_TRUE@noinst_LIBRARIES = libgnunetdhttest.a libgnunetdhttest_a_SOURCES = \ dht_test_lib.c dht_test_lib.h libgnunetdhttest_a_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la libgnunetdhttest_a_DEPENDENCIES = \ libgnunetdht.la # These tests still do not work as testbed does # not support the respective topology op @HAVE_EXPERIMENTAL_TRUE@NEW_TESTS = test_dht_2dtorus test_dht_multipeer @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; test_dht_api_SOURCES = \ test_dht_api.c test_dht_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_api_DEPENDENCIES = \ libgnunetdht.la test_dht_twopeer_SOURCES = \ test_dht_topo.c test_dht_twopeer_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_twopeer_DEPENDENCIES = \ libgnunetdht.la test_dht_2dtorus_SOURCES = \ test_dht_topo.c test_dht_2dtorus_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_2dtorus_DEPENDENCIES = \ libgnunetdht.la test_dht_line_SOURCES = \ test_dht_topo.c test_dht_line_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_line_DEPENDENCIES = \ libgnunetdht.la test_dht_multipeer_SOURCES = \ test_dht_topo.c test_dht_multipeer_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_multipeer_DEPENDENCIES = \ libgnunetdht.la test_dht_monitor_SOURCES = \ test_dht_monitor.c test_dht_monitor_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_monitor_DEPENDENCIES = \ libgnunetdht.la EXTRA_DIST = \ $(check_SCRIPTS) \ test_dht_api_data.conf \ test_dht_api_peer1.conf \ test_dht_monitor.conf \ test_dht_multipeer.conf \ test_dht_2dtorus.conf \ test_dht_line.conf \ test_dht_tools.py.in \ test_dht_multipeer_topology.dat @HAVE_PYTHON_TRUE@check_SCRIPTS = \ @HAVE_PYTHON_TRUE@ test_dht_tools.py do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/dht/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/dht/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): dht.conf: $(top_builddir)/config.status $(srcdir)/dht.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libgnunetdhttest.a: $(libgnunetdhttest_a_OBJECTS) $(libgnunetdhttest_a_DEPENDENCIES) $(EXTRA_libgnunetdhttest_a_DEPENDENCIES) $(AM_V_at)-rm -f libgnunetdhttest.a $(AM_V_AR)$(libgnunetdhttest_a_AR) libgnunetdhttest.a $(libgnunetdhttest_a_OBJECTS) $(libgnunetdhttest_a_LIBADD) $(AM_V_at)$(RANLIB) libgnunetdhttest.a install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_block_dht.la: $(libgnunet_plugin_block_dht_la_OBJECTS) $(libgnunet_plugin_block_dht_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_block_dht_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_block_dht_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_dht_la_OBJECTS) $(libgnunet_plugin_block_dht_la_LIBADD) $(LIBS) libgnunetdht.la: $(libgnunetdht_la_OBJECTS) $(libgnunetdht_la_DEPENDENCIES) $(EXTRA_libgnunetdht_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetdht_la_LINK) -rpath $(libdir) $(libgnunetdht_la_OBJECTS) $(libgnunetdht_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-dht-get$(EXEEXT): $(gnunet_dht_get_OBJECTS) $(gnunet_dht_get_DEPENDENCIES) $(EXTRA_gnunet_dht_get_DEPENDENCIES) @rm -f gnunet-dht-get$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_dht_get_OBJECTS) $(gnunet_dht_get_LDADD) $(LIBS) gnunet-dht-monitor$(EXEEXT): $(gnunet_dht_monitor_OBJECTS) $(gnunet_dht_monitor_DEPENDENCIES) $(EXTRA_gnunet_dht_monitor_DEPENDENCIES) @rm -f gnunet-dht-monitor$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_dht_monitor_OBJECTS) $(gnunet_dht_monitor_LDADD) $(LIBS) gnunet-dht-put$(EXEEXT): $(gnunet_dht_put_OBJECTS) $(gnunet_dht_put_DEPENDENCIES) $(EXTRA_gnunet_dht_put_DEPENDENCIES) @rm -f gnunet-dht-put$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_dht_put_OBJECTS) $(gnunet_dht_put_LDADD) $(LIBS) gnunet-service-dht$(EXEEXT): $(gnunet_service_dht_OBJECTS) $(gnunet_service_dht_DEPENDENCIES) $(EXTRA_gnunet_service_dht_DEPENDENCIES) @rm -f gnunet-service-dht$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_dht_OBJECTS) $(gnunet_service_dht_LDADD) $(LIBS) gnunet-service-dht-xvine$(EXEEXT): $(gnunet_service_dht_xvine_OBJECTS) $(gnunet_service_dht_xvine_DEPENDENCIES) $(EXTRA_gnunet_service_dht_xvine_DEPENDENCIES) @rm -f gnunet-service-dht-xvine$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_dht_xvine_OBJECTS) $(gnunet_service_dht_xvine_LDADD) $(LIBS) test_dht_2dtorus$(EXEEXT): $(test_dht_2dtorus_OBJECTS) $(test_dht_2dtorus_DEPENDENCIES) $(EXTRA_test_dht_2dtorus_DEPENDENCIES) @rm -f test_dht_2dtorus$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_dht_2dtorus_OBJECTS) $(test_dht_2dtorus_LDADD) $(LIBS) test_dht_api$(EXEEXT): $(test_dht_api_OBJECTS) $(test_dht_api_DEPENDENCIES) $(EXTRA_test_dht_api_DEPENDENCIES) @rm -f test_dht_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_dht_api_OBJECTS) $(test_dht_api_LDADD) $(LIBS) test_dht_line$(EXEEXT): $(test_dht_line_OBJECTS) $(test_dht_line_DEPENDENCIES) $(EXTRA_test_dht_line_DEPENDENCIES) @rm -f test_dht_line$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_dht_line_OBJECTS) $(test_dht_line_LDADD) $(LIBS) test_dht_monitor$(EXEEXT): $(test_dht_monitor_OBJECTS) $(test_dht_monitor_DEPENDENCIES) $(EXTRA_test_dht_monitor_DEPENDENCIES) @rm -f test_dht_monitor$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_dht_monitor_OBJECTS) $(test_dht_monitor_LDADD) $(LIBS) test_dht_multipeer$(EXEEXT): $(test_dht_multipeer_OBJECTS) $(test_dht_multipeer_DEPENDENCIES) $(EXTRA_test_dht_multipeer_DEPENDENCIES) @rm -f test_dht_multipeer$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_dht_multipeer_OBJECTS) $(test_dht_multipeer_LDADD) $(LIBS) test_dht_twopeer$(EXEEXT): $(test_dht_twopeer_OBJECTS) $(test_dht_twopeer_DEPENDENCIES) $(EXTRA_test_dht_twopeer_DEPENDENCIES) @rm -f test_dht_twopeer$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_dht_twopeer_OBJECTS) $(test_dht_twopeer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dht_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dht_test_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-dht-get.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-dht-monitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-dht-put.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dht.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dht_clients.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dht_datacache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dht_hello.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dht_neighbours.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dht_nse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dht_routing.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-xdht.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-xdht_clients.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-xdht_datacache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-xdht_hello.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-xdht_neighbours.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-xdht_nse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-xdht_routing.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_dht.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dht_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dht_monitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_dht_topo.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_dht_api.log: test_dht_api$(EXEEXT) @p='test_dht_api$(EXEEXT)'; \ b='test_dht_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_dht_tools.py.log: test_dht_tools.py @p='test_dht_tools.py'; \ b='test_dht_tools.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_dht_twopeer.log: test_dht_twopeer$(EXEEXT) @p='test_dht_twopeer$(EXEEXT)'; \ b='test_dht_twopeer'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_dht_line.log: test_dht_line$(EXEEXT) @p='test_dht_line$(EXEEXT)'; \ b='test_dht_line'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_dht_monitor.log: test_dht_monitor$(EXEEXT) @p='test_dht_monitor$(EXEEXT)'; \ b='test_dht_monitor'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_dht_2dtorus.log: test_dht_2dtorus$(EXEEXT) @p='test_dht_2dtorus$(EXEEXT)'; \ b='test_dht_2dtorus'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_dht_multipeer.log: test_dht_multipeer$(EXEEXT) @p='test_dht_multipeer$(EXEEXT)'; \ b='test_dht_multipeer'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-noinstLIBRARIES \ clean-noinstPROGRAMS clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-noinstLIBRARIES \ clean-noinstPROGRAMS clean-pluginLTLIBRARIES cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES %.py: %.py.in Makefile $(do_subst) < $(srcdir)/$< > $@ chmod +x $@ test_dht_tools.py: test_dht_tools.py.in Makefile $(do_subst) < $(srcdir)/test_dht_tools.py.in > test_dht_tools.py chmod +x test_dht_tools.py # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/dht/dht_test_lib.h0000644000175000017500000000474012225777503014214 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/dht_test_lib.h * @author Christian Grothoff * @brief library for writing DHT tests */ #ifndef DHT_TEST_LIB_H #define DHT_TEST_LIB_H #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif #include "gnunet_testbed_service.h" #include "gnunet_dht_service.h" /** * Test context for a DHT Test. */ struct GNUNET_DHT_TEST_Context; /** * Main function of a DHT test. * * @param cls closure * @param ctx argument to give to GNUNET_DHT_TEST_cleanup on test end * @param num_peers number of peers that are running * @param peers array of peers * @param dhts handle to each of the DHTs of the peers */ typedef void (*GNUNET_DHT_TEST_AppMain) (void *cls, struct GNUNET_DHT_TEST_Context *ctx, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, struct GNUNET_DHT_Handle **dhts); /** * Run a test using the given name, configuration file and number of * peers. * * @param testname name of the test (for logging) * @param cfgname name of the configuration file * @param num_peers number of peers to start * @param tmain main function to run once the testbed is ready * @param tmain_cls closure for 'tmain' */ void GNUNET_DHT_TEST_run (const char *testname, const char *cfgname, unsigned int num_peers, GNUNET_DHT_TEST_AppMain tmain, void *tmain_cls); /** * Clean up the testbed. * * @param ctx handle for the testbed */ void GNUNET_DHT_TEST_cleanup (struct GNUNET_DHT_TEST_Context *ctx); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif /* ifndef DHT_TEST_LIB_H */ #endif gnunet-0.10.1/src/dht/plugin_block_dht.c0000644000175000017500000001371012274707232015043 00000000000000/* This file is part of GNUnet (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/plugin_block_dht.c * @brief block plugin for DHT internals (right now, find-peer requests only); * other plugins should be used to store "useful" data in the * DHT (see fs block plugin) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_hello_lib.h" #include "gnunet_block_plugin.h" #define DEBUG_DHT GNUNET_EXTRA_LOGGING /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for @a bf * @param xquery extended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param reply_block response to validate * @param reply_block_size number of bytes in @a reply_block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult block_plugin_dht_evaluate (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { struct GNUNET_HashCode mhash; const struct GNUNET_HELLO_Message *hello; struct GNUNET_PeerIdentity pid; const struct GNUNET_MessageHeader *msg; struct GNUNET_HashCode phash; if (type != GNUNET_BLOCK_TYPE_DHT_HELLO) return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; if (xquery_size != 0) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; } if (NULL == reply_block) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; if (reply_block_size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } msg = reply_block; if (reply_block_size != ntohs (msg->size)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } hello = reply_block; if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (NULL != bf) { GNUNET_CRYPTO_hash (&pid, sizeof (pid), &phash); GNUNET_BLOCK_mingle_hash (&phash, bf_mutator, &mhash); if (NULL != *bf) { if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (*bf, &mhash)) return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE; } else { *bf = GNUNET_CONTAINER_bloomfilter_init (NULL, 8, GNUNET_CONSTANTS_BLOOMFILTER_K); } GNUNET_CONTAINER_bloomfilter_add (*bf, &mhash); } return GNUNET_BLOCK_EVALUATION_OK_MORE; } /** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param block block to get the key for * @param block_size number of bytes @a block * @param key set to the key (query) for the given block * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int block_plugin_dht_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode * key) { const struct GNUNET_MessageHeader *msg; const struct GNUNET_HELLO_Message *hello; struct GNUNET_PeerIdentity *pid; if (type != GNUNET_BLOCK_TYPE_DHT_HELLO) return GNUNET_SYSERR; if (block_size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "block-dht", _("Block not of type %u\n"), GNUNET_BLOCK_TYPE_DHT_HELLO); return GNUNET_NO; } msg = block; if (block_size != ntohs (msg->size)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "block-dht", _("Size mismatch for block\n"), GNUNET_BLOCK_TYPE_DHT_HELLO); return GNUNET_NO; } hello = block; memset (key, 0, sizeof (*key)); pid = (struct GNUNET_PeerIdentity *) key; if (GNUNET_OK != GNUNET_HELLO_get_id (hello, pid)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "block-dht", _("Block of type %u is malformed\n"), GNUNET_BLOCK_TYPE_DHT_HELLO); return GNUNET_NO; } return GNUNET_OK; } /** * Entry point for the plugin. */ void * libgnunet_plugin_block_dht_init (void *cls) { static enum GNUNET_BLOCK_Type types[] = { GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_BLOCK_TYPE_ANY /* end of list */ }; struct GNUNET_BLOCK_PluginFunctions *api; api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_dht_evaluate; api->get_key = &block_plugin_dht_get_key; api->types = types; return api; } /** * Exit point from the plugin. */ void * libgnunet_plugin_block_dht_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_block_dht.c */ gnunet-0.10.1/src/dht/gnunet-service-dht_datacache.c0000644000175000017500000002115312225777502017227 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_datacache.c * @brief GNUnet DHT service's datacache integration * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_datacache_lib.h" #include "gnunet-service-dht_clients.h" #include "gnunet-service-dht_datacache.h" #include "gnunet-service-dht_routing.h" #include "gnunet-service-dht.h" #define LOG(kind,...) GNUNET_log_from (kind, "dht-dtcache",__VA_ARGS__) /** * Handle to the datacache service (for inserting/retrieving data) */ static struct GNUNET_DATACACHE_Handle *datacache; /** * Handle a datum we've received from another peer. Cache if * possible. * * @param expiration when will the reply expire * @param key the query this reply is for * @param put_path_length number of peers in 'put_path' * @param put_path path the reply took on put * @param type type of the reply * @param data_size number of bytes in 'data' * @param data application payload data */ void GDS_DATACACHE_handle_put (struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data) { int r; if (NULL == datacache) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("%s request received, but have no datacache!\n"), "PUT"); return; } if (data_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } /* Put size is actual data size plus struct overhead plus path length (if any) */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# ITEMS stored in datacache"), 1, GNUNET_NO); r = GNUNET_DATACACHE_put (datacache, key, data_size, data, type, expiration, put_path_length, put_path); LOG (GNUNET_ERROR_TYPE_DEBUG, "DATACACHE PUT for key %s [%u] completed (%d) after %u hops\n", GNUNET_h2s (key), data_size, r, put_path_length); } /** * Context containing information about a GET request. */ struct GetRequestContext { /** * extended query (see gnunet_block_lib.h). */ const void *xquery; /** * Bloomfilter to filter out duplicate replies (updated) */ struct GNUNET_CONTAINER_BloomFilter **reply_bf; /** * The key this request was about */ struct GNUNET_HashCode key; /** * Number of bytes in xquery. */ size_t xquery_size; /** * Mutator value for the reply_bf, see gnunet_block_lib.h */ uint32_t reply_bf_mutator; /** * Return value to give back. */ enum GNUNET_BLOCK_EvaluationResult eval; }; /** * Iterator for local get request results, * * @param cls closure for iterator, a DatacacheGetContext * @param exp when does this value expire? * @param key the key this data is stored under * @param size the size of the data identified by key * @param data the actual data * @param type the type of the data * @param put_path_length number of peers in 'put_path' * @param put_path path the reply took on put * @return GNUNET_OK to continue iteration, anything else * to stop iteration. */ static int datacache_get_iterator (void *cls, const struct GNUNET_HashCode * key, size_t size, const char *data, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute exp, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path) { struct GetRequestContext *ctx = cls; enum GNUNET_BLOCK_EvaluationResult eval; eval = GNUNET_BLOCK_evaluate (GDS_block_context, type, key, ctx->reply_bf, ctx->reply_bf_mutator, ctx->xquery, ctx->xquery_size, data, size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Found reply for query %s in datacache, evaluation result is %d\n", GNUNET_h2s (key), (int) eval); ctx->eval = eval; switch (eval) { case GNUNET_BLOCK_EVALUATION_OK_MORE: case GNUNET_BLOCK_EVALUATION_OK_LAST: /* forward to local clients */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Good RESULTS found in datacache"), 1, GNUNET_NO); GDS_CLIENTS_handle_reply (exp, key, 0, NULL, put_path_length, put_path, type, size, data); /* forward to other peers */ GDS_ROUTING_process (type, exp, key, put_path_length, put_path, 0, NULL, data, size); break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Duplicate RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Invalid RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Irrelevant RESULTS found in datacache"), 1, GNUNET_NO); break; case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: GNUNET_break (0); break; case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: GNUNET_break_op (0); return GNUNET_SYSERR; case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Unsupported RESULTS found in datacache"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Unsupported block type (%u) in local response!\n"), type); break; } return (eval == GNUNET_BLOCK_EVALUATION_OK_LAST) ? GNUNET_NO : GNUNET_OK; } /** * Handle a GET request we've received from another peer. * * @param key the query * @param type requested data type * @param xquery extended query * @param xquery_size number of bytes in xquery * @param reply_bf where the reply bf is (to be) stored, possibly updated, can be NULL * @param reply_bf_mutator mutation value for reply_bf * @return evaluation result for the local replies */ enum GNUNET_BLOCK_EvaluationResult GDS_DATACACHE_handle_get (const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, const void *xquery, size_t xquery_size, struct GNUNET_CONTAINER_BloomFilter **reply_bf, uint32_t reply_bf_mutator) { struct GetRequestContext ctx; unsigned int r; if (datacache == NULL) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests given to datacache"), 1, GNUNET_NO); ctx.eval = GNUNET_BLOCK_EVALUATION_REQUEST_VALID; ctx.key = *key; ctx.xquery = xquery; ctx.xquery_size = xquery_size; ctx.reply_bf = reply_bf; ctx.reply_bf_mutator = reply_bf_mutator; r = GNUNET_DATACACHE_get (datacache, key, type, &datacache_get_iterator, &ctx); LOG (GNUNET_ERROR_TYPE_DEBUG, "DATACACHE GET for key %s completed (%d). %u results found.\n", GNUNET_h2s (key), ctx.eval, r); return ctx.eval; } /** * Initialize datacache subsystem. */ void GDS_DATACACHE_init () { datacache = GNUNET_DATACACHE_create (GDS_cfg, "dhtcache"); } /** * Shutdown datacache subsystem. */ void GDS_DATACACHE_done () { if (datacache != NULL) { GNUNET_DATACACHE_destroy (datacache); datacache = NULL; } } /* end of gnunet-service-dht_datacache.c */ gnunet-0.10.1/src/dht/dht.h0000644000175000017500000002144212225777503012325 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @author Nathan Evans * @file dht/dht.h */ #ifndef DHT_H #define DHT_H /** * Size of the bloom filter the DHT uses to filter peers. */ #define DHT_BLOOM_SIZE 128 GNUNET_NETWORK_STRUCT_BEGIN /** * Message which indicates the DHT should cancel outstanding * requests and discard any state. */ struct GNUNET_DHT_ClientGetStopMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Unique ID identifying this request */ uint64_t unique_id GNUNET_PACKED; /** * Key of this request */ struct GNUNET_HashCode key; }; /** * DHT GET message sent from clients to service. Indicates that a GET * request should be issued. */ struct GNUNET_DHT_ClientGetMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET */ struct GNUNET_MessageHeader header; /** * Message options, actually an 'enum GNUNET_DHT_RouteOption' value. */ uint32_t options GNUNET_PACKED; /** * Replication level for this message */ uint32_t desired_replication_level GNUNET_PACKED; /** * The type for the data for the GET request; actually an 'enum * GNUNET_BLOCK_Type'. */ uint32_t type GNUNET_PACKED; /** * The key to search for */ struct GNUNET_HashCode key GNUNET_PACKED; /** * Unique ID identifying this request, if 0 then * the client will not expect a response */ uint64_t unique_id GNUNET_PACKED; /* Possibly followed by xquery, copied to end of this dealy do */ }; /** * DHT GET RESULTS KNOWN message sent from clients to service. Indicates that a GET * request should exclude certain results which are already known. */ struct GNUNET_DHT_ClientGetResultSeenMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN */ struct GNUNET_MessageHeader header; /** * Reserved, always 0. */ uint32_t reserved GNUNET_PACKED; /** * The key we are searching for (to make it easy to find the corresponding * GET inside the service). */ struct GNUNET_HashCode key GNUNET_PACKED; /** * Unique ID identifying this request. */ uint64_t unique_id GNUNET_PACKED; /* Followed by an array of the hash codes of known results */ }; /** * Reply to a GET send from the service to a client. */ struct GNUNET_DHT_ClientResultMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT */ struct GNUNET_MessageHeader header; /** * The type for the data. */ uint32_t type GNUNET_PACKED; /** * Number of peers recorded in the outgoing path from source to the * storgage location of this message. */ uint32_t put_path_length GNUNET_PACKED; /** * The number of peer identities recorded from the storage location * to this peer. */ uint32_t get_path_length GNUNET_PACKED; /** * Unique ID of the matching GET request. */ uint64_t unique_id GNUNET_PACKED; /** * When does this entry expire? */ struct GNUNET_TIME_AbsoluteNBO expiration; /** * The key that was searched for */ struct GNUNET_HashCode key GNUNET_PACKED; /* put path, get path and actual data are copied to end of this dealy do */ }; /** * Message to insert data into the DHT, sent from clients to DHT service. */ struct GNUNET_DHT_ClientPutMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT */ struct GNUNET_MessageHeader header; /** * The type of data to insert. */ uint32_t type GNUNET_PACKED; /** * Message options, actually an 'enum GNUNET_DHT_RouteOption' value. */ uint32_t options GNUNET_PACKED; /** * Replication level for this message */ uint32_t desired_replication_level GNUNET_PACKED; /** * Unique ID for the PUT message. */ uint64_t unique_id GNUNET_PACKED; /** * How long should this data persist? */ struct GNUNET_TIME_AbsoluteNBO expiration; /** * The key to store the value under. */ struct GNUNET_HashCode key GNUNET_PACKED; /* DATA copied to end of this message */ }; /** * Message to confirming receipt of PUT, sent from DHT service to clients. */ struct GNUNET_DHT_ClientPutConfirmationMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Unique ID from the PUT message that is being confirmed. */ uint64_t unique_id GNUNET_PACKED; }; /** * Message to monitor put requests going through peer, DHT service -> clients. */ struct GNUNET_DHT_MonitorPutMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT */ struct GNUNET_MessageHeader header; /** * Message options, actually an 'enum GNUNET_DHT_RouteOption' value. */ uint32_t options GNUNET_PACKED; /** * The type of data in the request. */ uint32_t type GNUNET_PACKED; /** * Hop count so far. */ uint32_t hop_count GNUNET_PACKED; /** * Replication level for this message */ uint32_t desired_replication_level GNUNET_PACKED; /** * Number of peers recorded in the outgoing path from source to the * storage location of this message. */ uint32_t put_path_length GNUNET_PACKED; /** * How long should this data persist? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The key to store the value under. */ struct GNUNET_HashCode key GNUNET_PACKED; /* put path (if tracked) */ /* Payload */ }; /** * Message to request monitoring messages, clients -> DHT service. */ struct GNUNET_DHT_MonitorStartStopMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_MONITOR_START or * #GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP */ struct GNUNET_MessageHeader header; /** * The type of data desired, GNUNET_BLOCK_TYPE_ANY for all. */ uint32_t type GNUNET_PACKED; /** * Flag whether to notify about GET messages. */ int16_t get GNUNET_PACKED; /** * Flag whether to notify about GET_REPONSE messages. */ int16_t get_resp GNUNET_PACKED; /** * Flag whether to notify about PUT messages. */ int16_t put GNUNET_PACKED; /** * Flag whether to use the provided key to filter messages. */ int16_t filter_key GNUNET_PACKED; /** * The key to filter messages by. */ struct GNUNET_HashCode key GNUNET_PACKED; }; /** * Message to monitor get requests going through peer, DHT service -> clients. */ struct GNUNET_DHT_MonitorGetMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET */ struct GNUNET_MessageHeader header; /** * Message options, actually an 'enum GNUNET_DHT_RouteOption' value. */ uint32_t options GNUNET_PACKED; /** * The type of data in the request. */ uint32_t type GNUNET_PACKED; /** * Hop count */ uint32_t hop_count GNUNET_PACKED; /** * Replication level for this message */ uint32_t desired_replication_level GNUNET_PACKED; /** * Number of peers recorded in the outgoing path from source to the * storage location of this message. */ uint32_t get_path_length GNUNET_PACKED; /** * The key to store the value under. */ struct GNUNET_HashCode key GNUNET_PACKED; /* get path (if tracked) */ }; /** * Message to monitor get results going through peer, DHT service -> clients. */ struct GNUNET_DHT_MonitorGetRespMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT */ struct GNUNET_MessageHeader header; /** * Content type. */ uint32_t type GNUNET_PACKED; /** * Length of the PUT path that follows (if tracked). */ uint32_t put_path_length GNUNET_PACKED; /** * Length of the GET path that follows (if tracked). */ uint32_t get_path_length GNUNET_PACKED; /** * When does the content expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The key of the corresponding GET request. */ struct GNUNET_HashCode key GNUNET_PACKED; /* put path (if tracked) */ /* get path (if tracked) */ /* Payload */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/dht/gnunet-service-xdht_hello.h0000644000175000017500000000266412252673741016640 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_hello.h * @brief GNUnet DHT integration with peerinfo * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_XDHT_HELLO_H #define GNUNET_SERVICE_XDHT_HELLO_H #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" /** * Obtain a peer's HELLO if available * * @param peer peer to look for a HELLO from * @return HELLO for the given peer */ const struct GNUNET_HELLO_Message * GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer); /** * Initialize HELLO subsystem. */ void GDS_HELLO_init (void); /** * Shutdown HELLO subsystem. */ void GDS_HELLO_done (void); #endif gnunet-0.10.1/src/dht/test_dht_tools.py.in0000644000175000017500000000661712221077151015405 00000000000000#!@PYTHON@ from __future__ import print_function import os import sys import shutil import re import subprocess import time import tempfile if os.name == "nt": tmp = os.getenv ("TEMP") else: tmp = "/tmp" if os.name == 'nt': pif = 'gnunet-peerinfo.exe' get = './gnunet-dht-get.exe' put = './gnunet-dht-put.exe' arm = 'gnunet-arm.exe' else: pif = 'gnunet-peerinfo' get = './gnunet-dht-get' put = './gnunet-dht-put' arm = 'gnunet-arm' tf, tempcfg = tempfile.mkstemp (prefix='test_dht_api_peer1.') os.close (tf) run_pif = [pif, '-c', tempcfg, '-sq'] run_get = [get, '-c', tempcfg] run_put = [put, '-c', tempcfg] run_arm = [arm, '-c', tempcfg] debug = os.getenv ('DEBUG') if debug: run_arm += [debug.split (' ')] def cleanup (exitcode): os.remove (tempcfg) sys.exit (exitcode) def sub_run (args, want_stdo = True, want_stde = False, nofail = False): if want_stdo: stdo = subprocess.PIPE else: stdo = None if want_stde: stde = subprocess.PIPE else: stde = None p = subprocess.Popen (args, stdout = stdo, stderr = stde) stdo, stde = p.communicate () if not nofail: if p.returncode != 0: sys.exit (p.returncode) return (p.returncode, stdo, stde) def fail (result): print (result) r_arm (['-e'], want_stdo = False) cleanup (1) def r_something (to_run, extra_args, failer = None, normal = True, **kw): rc, stdo, stde = sub_run (to_run + extra_args, nofail = True, **kw) if failer is not None: failer (to_run + extra_args, rc, stdo, stde, normal) return (rc, stdo, stde) def r_arm (extra_args, **kw): return r_something (run_arm, extra_args, **kw) def r_pif (extra_args, **kw): return r_something (run_pif, extra_args, **kw) def r_get (extra_args, **kw): return r_something (run_get, extra_args, **kw) def r_put (extra_args, **kw): return r_something (run_put, extra_args, **kw) def end_arm_failer (command, rc, stdo, stde, normal): if normal: if rc != 0: fail ("FAIL: error running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) else: if rc == 0: fail ("FAIL: expected error while running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) def print_only_failer (command, rc, stdo, stde, normal): if normal: if rc != 0: print ("FAIL: error running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) cleanup (1) else: if rc == 0: print ("FAIL: expected error while running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) cleanup (1) shutil.copyfile ('test_dht_api_peer1.conf', tempcfg) print ("TEST: Generating hostkey...", end='') r_pif ([], failer = print_only_failer) print ("PASS") print ("TEST: Starting ARM...", end='') r_arm (['-s'], failer = end_arm_failer, want_stdo = False, want_stde = False) print ("PASS") time.sleep (1) print ("TEST: Testing put...", end='') r_put (['-k', 'testkey', '-d', 'testdata', '-t', '8'], failer = end_arm_failer) print ("PASS") time.sleep (1) print ("TEST: Testing get...", end='') rc, stdo, stde = r_get (['-k', 'testkey', '-T', '5 ms', '-t', '8'], want_stdo = True, failer = end_arm_failer) stdo = stdo.replace ('\r', '').splitlines () expect = "Result 0, type 8:\ntestdata".splitlines() if len (stdo) != 2 or len (expect) != 2 or stdo[0] != expect[0] or stdo[1] != expect[1]: fail ("output `{}' differs from expected `{}'".format (stdo, expect)) print ("PASS") r_arm (['-e', '-d'], failer = print_only_failer) gnunet-0.10.1/src/dht/gnunet-service-dht.h0000644000175000017500000000314712225777503015263 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht.h * @brief GNUnet DHT globals * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_DHT_H #define GNUNET_SERVICE_DHT_H #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #define DEBUG_DHT GNUNET_EXTRA_LOGGING /** * Configuration we use. */ extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg; /** * Our handle to the BLOCK library. */ extern struct GNUNET_BLOCK_Context *GDS_block_context; /** * Handle for the statistics service. */ extern struct GNUNET_STATISTICS_Handle *GDS_stats; /** * Our HELLO */ extern struct GNUNET_MessageHeader *GDS_my_hello; /** * Handle to the transport service, for getting our hello */ extern struct GNUNET_TRANSPORT_Handle *GDS_transport_handle; #endif gnunet-0.10.1/src/dht/test_dht_api_data.conf0000644000175000017500000000144512225230043015664 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-dht-api/ [fs] AUTOSTART = NO [resolver] AUTOSTART = NO [datastore] AUTOSTART = NO [dhtcache] QUOTA = 1 MB DATABASE = heap [topology] TARGET-CONNECTION-COUNT = 16 AUTOCONNECT = YES FRIENDS-ONLY = NO MINIMUM-FRIENDS = 0 [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [core] PORT = 2092 [dht] PORT = 12370 [transport] plugins = tcp NEIGHBOUR_LIMIT = 50 PORT = 2091 [peerinfo] PORT = 2090 [resolver] PORT = 2089 [statistics] PORT = 2088 [arm] DEFAULTSERVICES = PORT = 2087 [transport-tcp] TIMEOUT = 300 s PORT = 2094 [nat] DISABLEV6 = YES BINDTO = 127.0.0.1 ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 [dns] AUTOSTART = NO [namestore] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART=NO gnunet-0.10.1/src/dht/gnunet-service-xdht_routing.c0000644000175000017500000001563612320724374017215 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_routing.c * @brief GNUnet DHT tracking of requests for routing replies * @author Supriti Singh */ #include "platform.h" #include "gnunet-service-xdht_neighbours.h" #include "gnunet-service-xdht_routing.h" #include "gnunet-service-xdht.h" /** * Number of requests we track at most (for routing replies). */ #define DHT_MAX_RECENT (1024 * 16) /** * Maximum number of entries in routing table. */ #define ROUTING_TABLE_THRESHOLD 64 /** * Routing table entry . */ struct RoutingTrail { /** * Source peer . */ struct GNUNET_PeerIdentity source; /** * Destination peer. */ struct GNUNET_PeerIdentity destination; /** * The peer to which this request should be passed to. */ struct GNUNET_PeerIdentity next_hop; /** * Peer just before next hop in the trail. */ struct GNUNET_PeerIdentity prev_hop; }; /** * Routing table of the peer */ static struct GNUNET_CONTAINER_MultiPeerMap *routing_table; /** * Add a new entry to our routing table. * @param source peer Source of the trail. * @param destintation Destination of the trail. * @param next_hop Next peer to forward the message to reach the destination. * @return GNUNET_YES * GNUNET_SYSERR If the number of routing entries crossed thershold. */ int GDS_ROUTING_add (struct GNUNET_PeerIdentity *source, struct GNUNET_PeerIdentity *dest, struct GNUNET_PeerIdentity *next_hop, const struct GNUNET_PeerIdentity *prev_hop) { struct RoutingTrail *new_routing_entry; if (GNUNET_CONTAINER_multipeermap_size(routing_table) > ROUTING_TABLE_THRESHOLD) return GNUNET_SYSERR; //FPRINTF (stderr,_("\nSUPU ROUTING ADD %s, %s, %d"),__FILE__, __func__,__LINE__); new_routing_entry = GNUNET_malloc (sizeof (struct RoutingTrail)); memcpy (&(new_routing_entry->source) , source, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(new_routing_entry->next_hop), next_hop, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(new_routing_entry->destination), dest, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(new_routing_entry->prev_hop), prev_hop, sizeof (struct GNUNET_PeerIdentity)); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (routing_table, dest, new_routing_entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); return GNUNET_YES; } /** * Iterate over multiple entries for same destinational value and get * the correct next hop. * @param cls struct RoutingTrail * @param key Destination identity * @param value struct RoutingTrail * @return #GNUNET_YES to continue looking, #GNUNET_NO if we found the next hop */ int get_next_hop (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { /* Here you should match if source, prev hop matches if yes then send GNUNET_NO as you don't need to check more entries. */ struct RoutingTrail *request = cls; struct RoutingTrail *existing_entry = (struct RoutingTrail *)value; if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(request->source), &(existing_entry->source))) { if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(request->prev_hop), &(existing_entry->prev_hop))) { memcpy (&(request->next_hop), &(existing_entry->next_hop), sizeof (struct GNUNET_PeerIdentity)); return GNUNET_YES; } } return GNUNET_NO; } /** * Find the next hop to send packet to. * @param source_peer Source of the trail. * @param destination_peer Destination of the trail. * @param prev_hop Previous hop in the trail. * @return Next hop in the trail from source to destination. */ struct GNUNET_PeerIdentity * GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *destination_peer, const struct GNUNET_PeerIdentity *prev_hop) { struct RoutingTrail *trail; trail = GNUNET_malloc (sizeof (struct RoutingTrail)); memcpy (&(trail->destination), destination_peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(trail->source), source_peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&(trail->prev_hop), prev_hop, sizeof (struct GNUNET_PeerIdentity)); //trail->next_hop = NULL; //FPRINTF (stderr,_("\nSUPU ROUTING SEARCH %s, %s, %d"),__FILE__, __func__,__LINE__); GNUNET_CONTAINER_multipeermap_get_multiple (routing_table, destination_peer, get_next_hop, trail); if(trail != NULL) return &(trail->next_hop); else return NULL; } /**FIXME: Old implementation just to remove error * Handle a reply (route to origin). Only forwards the reply back to * other peers waiting for it. Does not do local caching or * forwarding to local clients. Essentially calls * GDS_NEIGHBOURS_handle_reply for all peers that sent us a matching * request recently. * * @param type type of the block * @param expiration_time when does the content expire * @param key key for the content * @param put_path_length number of entries in put_path * @param put_path peers the original PUT traversed (if tracked) * @param get_path_length number of entries in get_path * @param get_path peers this reply has traversed so far (if tracked) * @param data payload of the reply * @param data_size number of bytes in data */ void GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size) { return; } /** * Initialize routing subsystem. */ void GDS_ROUTING_init () { routing_table = GNUNET_CONTAINER_multipeermap_create (DHT_MAX_RECENT * 4 / 3, GNUNET_NO); } /** * Shutdown routing subsystem. */ void GDS_ROUTING_done () { GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (routing_table)); GNUNET_CONTAINER_multipeermap_destroy (routing_table); } /* end of gnunet-service-xdht_routing.c */gnunet-0.10.1/src/dht/test_dht_multipeer_topology.dat0000644000175000017500000000012112063624234017706 000000000000000:1|6|8 1:2|7|9 2:0|3|8 3:1|4|9 4:0|2|5 5:1|3|6 6:2|4|7 7:3|5|8 8:4|6|9 9:0|5|7 gnunet-0.10.1/src/dht/Makefile.am0000644000175000017500000001645212320751517013427 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 endif plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ dht.conf if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif lib_LTLIBRARIES = \ libgnunetdht.la libgnunetdht_la_SOURCES = \ dht_api.c dht.h libgnunetdht_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) \ $(LTLIBINTL) libgnunetdht_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 2:0:2 plugin_LTLIBRARIES = \ libgnunet_plugin_block_dht.la libgnunet_plugin_block_dht_la_SOURCES = \ plugin_block_dht.c libgnunet_plugin_block_dht_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_block_dht_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_block_dht_la_DEPENDENCIES = \ $(top_builddir)/src/block/libgnunetblock.la libexec_PROGRAMS = \ gnunet-service-dht \ gnunet-service-dht-xvine noinst_PROGRAMS = \ gnunet-dht-monitor \ gnunet-dht-get \ gnunet-dht-put gnunet_service_dht_SOURCES = \ gnunet-service-dht.c gnunet-service-dht.h \ gnunet-service-dht_clients.c gnunet-service-dht_clients.h \ gnunet-service-dht_datacache.c gnunet-service-dht_datacache.h \ gnunet-service-dht_hello.c gnunet-service-dht_hello.h \ gnunet-service-dht_nse.c gnunet-service-dht_nse.h \ gnunet-service-dht_neighbours.c gnunet-service-dht_neighbours.h \ gnunet-service-dht_routing.c gnunet-service-dht_routing.h gnunet_service_dht_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lm gnunet_service_dht_xvine_SOURCES = \ gnunet-service-xdht.c gnunet-service-xdht.h \ gnunet-service-xdht_clients.c gnunet-service-xdht_clients.h \ gnunet-service-xdht_datacache.c gnunet-service-xdht_datacache.h \ gnunet-service-xdht_hello.c gnunet-service-xdht_hello.h \ gnunet-service-xdht_nse.c gnunet-service-xdht_nse.h \ gnunet-service-xdht_neighbours.c gnunet-service-xdht_neighbours.h \ gnunet-service-xdht_routing.c gnunet-service-xdht_routing.h gnunet_service_dht_xvine_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/datacache/libgnunetdatacache.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lm gnunet_dht_get_SOURCES = \ gnunet-dht-get.c gnunet_dht_get_LDADD = \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_dht_get_DEPENDENCIES = \ libgnunetdht.la gnunet_dht_put_SOURCES = \ gnunet-dht-put.c gnunet_dht_put_LDADD = \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_dht_put_DEPENDENCIES = \ libgnunetdht.la gnunet_dht_monitor_SOURCES = \ gnunet-dht-monitor.c gnunet_dht_monitor_LDADD = \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_dht_monitor_DEPENDENCIES = \ libgnunetdht.la if HAVE_TESTING noinst_LIBRARIES = libgnunetdhttest.a endif libgnunetdhttest_a_SOURCES = \ dht_test_lib.c dht_test_lib.h libgnunetdhttest_a_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la libgnunetdhttest_a_DEPENDENCIES = \ libgnunetdht.la if HAVE_TESTING check_PROGRAMS = \ test_dht_api \ test_dht_twopeer \ test_dht_multipeer \ test_dht_line \ test_dht_2dtorus \ test_dht_monitor endif if HAVE_EXPERIMENTAL # These tests still do not work as testbed does # not support the respective topology op NEW_TESTS = test_dht_2dtorus test_dht_multipeer endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = test_dht_api $(check_SCRIPTS) \ test_dht_twopeer \ test_dht_line \ test_dht_monitor \ $(NEW_TESTS) endif test_dht_api_SOURCES = \ test_dht_api.c test_dht_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_api_DEPENDENCIES = \ libgnunetdht.la test_dht_twopeer_SOURCES = \ test_dht_topo.c test_dht_twopeer_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_twopeer_DEPENDENCIES = \ libgnunetdht.la test_dht_2dtorus_SOURCES = \ test_dht_topo.c test_dht_2dtorus_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_2dtorus_DEPENDENCIES = \ libgnunetdht.la test_dht_line_SOURCES = \ test_dht_topo.c test_dht_line_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_line_DEPENDENCIES = \ libgnunetdht.la test_dht_multipeer_SOURCES = \ test_dht_topo.c test_dht_multipeer_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_multipeer_DEPENDENCIES = \ libgnunetdht.la test_dht_monitor_SOURCES = \ test_dht_monitor.c test_dht_monitor_LDADD = \ $(top_builddir)/src/dht/libgnunetdhttest.a \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/dht/libgnunetdht.la test_dht_monitor_DEPENDENCIES = \ libgnunetdht.la EXTRA_DIST = \ $(check_SCRIPTS) \ test_dht_api_data.conf \ test_dht_api_peer1.conf \ test_dht_monitor.conf \ test_dht_multipeer.conf \ test_dht_2dtorus.conf \ test_dht_line.conf \ test_dht_tools.py.in \ test_dht_multipeer_topology.dat if HAVE_PYTHON check_SCRIPTS = \ test_dht_tools.py endif do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' %.py: %.py.in Makefile $(do_subst) < $(srcdir)/$< > $@ chmod +x $@ test_dht_tools.py: test_dht_tools.py.in Makefile $(do_subst) < $(srcdir)/test_dht_tools.py.in > test_dht_tools.py chmod +x test_dht_tools.py gnunet-0.10.1/src/dht/dht.conf.in0000644000175000017500000000137412250373167013426 00000000000000[dht] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2095 HOSTNAME = localhost BINARY = gnunet-service-dht ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; BUCKET_SIZE = 4 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-dht.sock # This could be relaxed... UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = # Should the DHT cache results that we are routing in the DATACACHE as well? CACHE_RESULTS = YES # Special option to disable DHT calling 'try_connect' (for testing) DISABLE_TRY_CONNECT = NO [dhtcache] DATABASE = heap QUOTA = 50 MB # Disable RC-file for Bloom filter? (for benchmarking with limited IO availability) DISABLE_BF_RC = NO gnunet-0.10.1/src/dht/gnunet-service-xdht_nse.h0000644000175000017500000000237412252673741016320 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_nse.h * @brief GNUnet DHT integration with NSE * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_XDHT_NSE_H #define GNUNET_SERVICE_XDHT_NSE_H /** * Return the log of the current network size estimate. * * @return log of NSE */ double GDS_NSE_get (void); /** * Initialize NSE subsystem. */ void GDS_NSE_init (void); /** * Shutdown NSE subsystem. */ void GDS_NSE_done (void); #endif gnunet-0.10.1/src/dht/dht_test_lib.c0000644000175000017500000001304712255010512014166 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/dht_test_lib.c * @author Christian Grothoff * @brief library for writing DHT tests */ #include "platform.h" #include "dht_test_lib.h" /** * Test context for a DHT Test. */ struct GNUNET_DHT_TEST_Context { /** * Array of running peers. */ struct GNUNET_TESTBED_Peer **peers; /** * Array of handles to the DHT for each peer. */ struct GNUNET_DHT_Handle **dhts; /** * Operation associated with the connection to the DHT. */ struct GNUNET_TESTBED_Operation **ops; /** * Main function of the test to run once all DHTs are available. */ GNUNET_DHT_TEST_AppMain app_main; /** * Closure for 'app_main'. */ void *app_main_cls; /** * Number of peers running, size of the arrays above. */ unsigned int num_peers; }; /** * Adapter function called to establish a connection to * the DHT service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * dht_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_DHT_connect (cfg, 16); } /** * Adapter function called to destroy a connection to * the DHT service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void dht_disconnect_adapter (void *cls, void *op_result) { struct GNUNET_DHT_Handle *dht = op_result; GNUNET_DHT_disconnect (dht); } /** * Callback to be called when a service connect operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void dht_connect_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { struct GNUNET_DHT_TEST_Context *ctx = cls; unsigned int i; if (NULL != emsg) { fprintf (stderr, "Failed to connect to DHT service: %s\n", emsg); GNUNET_SCHEDULER_shutdown (); return; } for (i=0;inum_peers;i++) if (op == ctx->ops[i]) ctx->dhts[i] = ca_result; for (i=0;inum_peers;i++) if (NULL == ctx->dhts[i]) return; /* still some DHT connections missing */ /* all DHT connections ready! */ ctx->app_main (ctx->app_main_cls, ctx, ctx->num_peers, ctx->peers, ctx->dhts); } /** * Clean up the testbed. * * @param ctx handle for the testbed */ void GNUNET_DHT_TEST_cleanup (struct GNUNET_DHT_TEST_Context *ctx) { unsigned int i; for (i=0;inum_peers;i++) GNUNET_TESTBED_operation_done (ctx->ops[i]); GNUNET_free (ctx->ops); GNUNET_free (ctx->dhts); GNUNET_free (ctx); GNUNET_SCHEDULER_shutdown (); } static void dht_test_run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { struct GNUNET_DHT_TEST_Context *ctx = cls; unsigned int i; GNUNET_assert (num_peers == ctx->num_peers); ctx->peers = peers; for (i=0;iops[i] = GNUNET_TESTBED_service_connect (ctx, peers[i], "dht", &dht_connect_cb, ctx, &dht_connect_adapter, &dht_disconnect_adapter, ctx); } /** * Run a test using the given name, configuration file and number of * peers. * * @param testname name of the test (for logging) * @param cfgname name of the configuration file * @param num_peers number of peers to start * @param tmain main function to run once the testbed is ready * @param tmain_cls closure for 'tmain' */ void GNUNET_DHT_TEST_run (const char *testname, const char *cfgname, unsigned int num_peers, GNUNET_DHT_TEST_AppMain tmain, void *tmain_cls) { struct GNUNET_DHT_TEST_Context *ctx; ctx = GNUNET_new (struct GNUNET_DHT_TEST_Context); ctx->num_peers = num_peers; ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *)); ctx->dhts = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_Handle *)); ctx->app_main = tmain; ctx->app_main_cls = tmain_cls; (void) GNUNET_TESTBED_test_run (testname, cfgname, num_peers, 0LL, NULL, NULL, &dht_test_run, ctx); } /* end of dht_test_lib.c */ gnunet-0.10.1/src/dht/gnunet-service-dht_nse.h0000644000175000017500000000237112225777503016126 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_nse.h * @brief GNUnet DHT integration with NSE * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_DHT_NSE_H #define GNUNET_SERVICE_DHT_NSE_H /** * Return the log of the current network size estimate. * * @return log of NSE */ double GDS_NSE_get (void); /** * Initialize NSE subsystem. */ void GDS_NSE_init (void); /** * Shutdown NSE subsystem. */ void GDS_NSE_done (void); #endif gnunet-0.10.1/src/dht/test_dht_monitor.c0000644000175000017500000002667412255010512015121 00000000000000/* This file is part of GNUnet. (C) 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/test_dht_monitor.c * @brief Test for the dht monitoring API; checks that we receive "some" monitor events * @author Christian Grothoff */ #include "platform.h" #include "gnunet_testbed_service.h" #include "gnunet_dht_service.h" #include "dht_test_lib.h" /** * How long do we run the test at most? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) /** * How often do we run the PUTs? */ #define PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) /** * Information we keep for each GET operation. */ struct GetOperation { /** * DLL. */ struct GetOperation *next; /** * DLL. */ struct GetOperation *prev; /** * Handle for the operation. */ struct GNUNET_DHT_GetHandle *get; }; /** * Return value from 'main'. */ static int ok; /** * Head of list of active GET operations. */ static struct GetOperation *get_head; /** * Tail of list of active GET operations. */ static struct GetOperation *get_tail; /** * Array of the testbed's peers. */ static struct GNUNET_TESTBED_Peer **my_peers; /** * Number of peers to run. */ static unsigned int NUM_PEERS = 3; /** * Task called to disconnect peers. */ static GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Task to do DHT_puts */ static GNUNET_SCHEDULER_TaskIdentifier put_task; static struct GNUNET_DHT_MonitorHandle **monitors; static unsigned int monitor_counter; /** * Task run on success or timeout to clean up. * Terminates active get operations and shuts down * the testbed. * * @param cls the 'struct GNUNET_DHT_TestContext' * @param tc scheduler context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DHT_TEST_Context *ctx = cls; unsigned int i; struct GetOperation *get_op; ok = (monitor_counter > NUM_PEERS) ? 0 : 2; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received %u monitor events\n", monitor_counter); while (NULL != (get_op = get_tail)) { GNUNET_DHT_get_stop (get_op->get); GNUNET_CONTAINER_DLL_remove (get_head, get_tail, get_op); GNUNET_free (get_op); } for (i=0;iget); GNUNET_CONTAINER_DLL_remove (get_head, get_tail, get_op); GNUNET_free (get_op); if (NULL != get_head) return; /* all DHT GET operations successful; terminate! */ ok = 0; ctx = GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_add_now (&shutdown_task, ctx); } /** * Task to put the id of each peer into the DHT. * * @param cls array with NUM_PEERS DHT handles * @param tc Task context */ static void do_puts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DHT_Handle **hs = cls; struct GNUNET_HashCode key; struct GNUNET_HashCode value; unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Putting values into DHT\n"); for (i = 0; i < NUM_PEERS; i++) { GNUNET_CRYPTO_hash (&i, sizeof (i), &key); GNUNET_CRYPTO_hash (&key, sizeof (key), &value); GNUNET_DHT_put (hs[i], &key, 10U, GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_BLOCK_TYPE_TEST, sizeof (value), &value, GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL, NULL, NULL); } put_task = GNUNET_SCHEDULER_add_delayed (PUT_FREQUENCY, &do_puts, hs); } /** * Callback called on each GET request going through the DHT. * Prints the info about the intercepted packet and increments a counter. * * @param cls Closure. * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the GET path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param key Key of the requested data. */ static void monitor_get_cb (void *cls, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode * key) { unsigned int i; i = (unsigned int) (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u got a GET message for key %s\n", i, GNUNET_h2s (key)); monitor_counter++; } /** * Callback called on each PUT request going through the DHT. * Prints the info about the intercepted packet and increments a counter. * * @param cls Closure. * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the PUT path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param exp Expiration time of the data. * @param key Key under which data is to be stored. * @param data Pointer to the data carried. * @param size Number of bytes in data. */ static void monitor_put_cb (void *cls, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size) { unsigned int i; i = (unsigned int) (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u got a PUT message for key %s with %u bytes\n", i, GNUNET_h2s (key), size); monitor_counter++; } /** * Callback called on each GET reply going through the DHT. * Prints the info about the intercepted packet and increments a counter. * * @param cls Closure. * @param type The type of data in the result. * @param get_path Peers on GET path (or NULL if not recorded). * @param get_path_length number of entries in get_path. * @param put_path peers on the PUT path (or NULL if not recorded). * @param put_path_length number of entries in get_path. * @param exp Expiration time of the data. * @param key Key of the data. * @param data Pointer to the result data. * @param size Number of bytes in data. */ static void monitor_res_cb (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size) { unsigned int i; i = (unsigned int) (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u got a REPLY message for key %s with %u bytes\n", i, GNUNET_h2s (key), size); monitor_counter++; } /** * Main function of the test. * * @param cls closure (NULL) * @param ctx argument to give to GNUNET_DHT_TEST_cleanup on test end * @param num_peers number of peers that are running * @param peers array of peers * @param dhts handle to each of the DHTs of the peers */ static void run (void *cls, struct GNUNET_DHT_TEST_Context *ctx, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, struct GNUNET_DHT_Handle **dhts) { unsigned int i; unsigned int j; struct GNUNET_HashCode key; struct GetOperation *get_op; GNUNET_assert (NUM_PEERS == num_peers); my_peers = peers; monitors = GNUNET_malloc (num_peers * sizeof (struct GNUNET_DHT_MonitorHandle *)); for (i = 0; i < num_peers; i++) monitors[i] = GNUNET_DHT_monitor_start (dhts[i], GNUNET_BLOCK_TYPE_ANY, NULL, &monitor_get_cb, &monitor_res_cb, &monitor_put_cb, (void *)(long)i); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers setup, starting test\n"); put_task = GNUNET_SCHEDULER_add_now (&do_puts, dhts); for (i=0;iget = GNUNET_DHT_get_start (dhts[j], GNUNET_BLOCK_TYPE_TEST, /* type */ &key, /*key to search */ 4U, /* replication level */ GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, /* xquery */ 0, /* xquery bits */ &dht_get_handler, get_op); } } timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &shutdown_task, ctx); } /** * Main: start test */ int main (int xargc, char *xargv[]) { GNUNET_DHT_TEST_run ("test-dht-monitor", "test_dht_monitor.conf", NUM_PEERS, &run, NULL); return ok; } /* end of test_dht_monitor.c */ gnunet-0.10.1/src/dht/test_dht_tools.py0000755000175000017500000000662612320752372015010 00000000000000#!/usr/bin/python from __future__ import print_function import os import sys import shutil import re import subprocess import time import tempfile if os.name == "nt": tmp = os.getenv ("TEMP") else: tmp = "/tmp" if os.name == 'nt': pif = 'gnunet-peerinfo.exe' get = './gnunet-dht-get.exe' put = './gnunet-dht-put.exe' arm = 'gnunet-arm.exe' else: pif = 'gnunet-peerinfo' get = './gnunet-dht-get' put = './gnunet-dht-put' arm = 'gnunet-arm' tf, tempcfg = tempfile.mkstemp (prefix='test_dht_api_peer1.') os.close (tf) run_pif = [pif, '-c', tempcfg, '-sq'] run_get = [get, '-c', tempcfg] run_put = [put, '-c', tempcfg] run_arm = [arm, '-c', tempcfg] debug = os.getenv ('DEBUG') if debug: run_arm += [debug.split (' ')] def cleanup (exitcode): os.remove (tempcfg) sys.exit (exitcode) def sub_run (args, want_stdo = True, want_stde = False, nofail = False): if want_stdo: stdo = subprocess.PIPE else: stdo = None if want_stde: stde = subprocess.PIPE else: stde = None p = subprocess.Popen (args, stdout = stdo, stderr = stde) stdo, stde = p.communicate () if not nofail: if p.returncode != 0: sys.exit (p.returncode) return (p.returncode, stdo, stde) def fail (result): print (result) r_arm (['-e'], want_stdo = False) cleanup (1) def r_something (to_run, extra_args, failer = None, normal = True, **kw): rc, stdo, stde = sub_run (to_run + extra_args, nofail = True, **kw) if failer is not None: failer (to_run + extra_args, rc, stdo, stde, normal) return (rc, stdo, stde) def r_arm (extra_args, **kw): return r_something (run_arm, extra_args, **kw) def r_pif (extra_args, **kw): return r_something (run_pif, extra_args, **kw) def r_get (extra_args, **kw): return r_something (run_get, extra_args, **kw) def r_put (extra_args, **kw): return r_something (run_put, extra_args, **kw) def end_arm_failer (command, rc, stdo, stde, normal): if normal: if rc != 0: fail ("FAIL: error running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) else: if rc == 0: fail ("FAIL: expected error while running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) def print_only_failer (command, rc, stdo, stde, normal): if normal: if rc != 0: print ("FAIL: error running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) cleanup (1) else: if rc == 0: print ("FAIL: expected error while running {}\nCommand output was:\n{}\n{}".format (command, stdo, stde)) cleanup (1) shutil.copyfile ('test_dht_api_peer1.conf', tempcfg) print ("TEST: Generating hostkey...", end='') r_pif ([], failer = print_only_failer) print ("PASS") print ("TEST: Starting ARM...", end='') r_arm (['-s'], failer = end_arm_failer, want_stdo = False, want_stde = False) print ("PASS") time.sleep (1) print ("TEST: Testing put...", end='') r_put (['-k', 'testkey', '-d', 'testdata', '-t', '8'], failer = end_arm_failer) print ("PASS") time.sleep (1) print ("TEST: Testing get...", end='') rc, stdo, stde = r_get (['-k', 'testkey', '-T', '5 ms', '-t', '8'], want_stdo = True, failer = end_arm_failer) stdo = stdo.replace ('\r', '').splitlines () expect = "Result 0, type 8:\ntestdata".splitlines() if len (stdo) != 2 or len (expect) != 2 or stdo[0] != expect[0] or stdo[1] != expect[1]: fail ("output `{}' differs from expected `{}'".format (stdo, expect)) print ("PASS") r_arm (['-e', '-d'], failer = print_only_failer) gnunet-0.10.1/src/dht/gnunet-service-xdht.h0000644000175000017500000000315212252673741015446 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht.h * @brief GNUnet DHT globals * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_XDHT_H #define GNUNET_SERVICE_XDHT_H #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #define DEBUG_DHT GNUNET_EXTRA_LOGGING /** * Configuration we use. */ extern const struct GNUNET_CONFIGURATION_Handle *GDS_cfg; /** * Our handle to the BLOCK library. */ extern struct GNUNET_BLOCK_Context *GDS_block_context; /** * Handle for the statistics service. */ extern struct GNUNET_STATISTICS_Handle *GDS_stats; /** * Our HELLO */ extern struct GNUNET_MessageHeader *GDS_my_hello; /** * Handle to the transport service, for getting our hello */ extern struct GNUNET_TRANSPORT_Handle *GDS_transport_handle; #endif gnunet-0.10.1/src/dht/gnunet-service-dht_clients.h0000644000175000017500000001274112320470550016770 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_clients.h * @brief GNUnet DHT service's client management code * @author Christian Grothoff * @author Nathan Evans */ #ifndef GNUNET_SERVICE_DHT_CLIENT_H #define GNUNET_SERVICE_DHT_CLIENT_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" /** * Handle a reply we've received from another peer. If the reply * matches any of our pending queries, forward it to the respective * client(s). * * @param expiration when will the reply expire * @param key the query this reply is for * @param get_path_length number of peers in @a get_path * @param get_path path the reply took on get * @param put_path_length number of peers in @a put_path * @param put_path path the reply took on put * @param type type of the reply * @param data_size number of bytes in @a data * @param data application payload data */ void GDS_CLIENTS_handle_reply (struct GNUNET_TIME_Absolute expiration, const struct GNUNET_HashCode *key, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, enum GNUNET_BLOCK_Type type, size_t data_size, const void *data); /** * Check if some client is monitoring GET messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the GET path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param key Key of the requested data. */ void GDS_CLIENTS_process_get (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode *key); /** * Check if some client is monitoring GET RESP messages and notify * them in that case. * * @param type The type of data in the result. * @param get_path Peers on GET path (or NULL if not recorded). * @param get_path_length number of entries in @a get_path. * @param put_path peers on the PUT path (or NULL if not recorded). * @param put_path_length number of entries in @a get_path. * @param exp Expiration time of the data. * @param key Key of the @a data. * @param data Pointer to the result data. * @param size Number of bytes in @a data. */ void GDS_CLIENTS_process_get_resp (enum GNUNET_BLOCK_Type type, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size); /** * Check if some client is monitoring PUT messages and notify * them in that case. * * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the PUT path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param exp Expiration time of the data. * @param key Key under which data is to be stored. * @param data Pointer to the data carried. * @param size Number of bytes in data. */ void GDS_CLIENTS_process_put (uint32_t options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size); /** * Initialize client subsystem. * * @param server the initialized server */ void GDS_CLIENTS_init (struct GNUNET_SERVER_Handle *server); /** * Shutdown client subsystem. */ void GDS_CLIENTS_done (void); #endif gnunet-0.10.1/src/dht/test_dht_api_peer1.conf0000644000175000017500000000143612255013321015770 00000000000000[fs] AUTOSTART = NO [resolver] AUTOSTART = NO [dht] AUTOSTART = YES ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost PORT = 12100 BINARY = gnunet-service-dht [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = tcp ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 PORT = 12365 [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [core] PORT = 12092 [arm] DEFAULTSERVICES = core PORT = 12366 [transport-tcp] TIMEOUT = 300 s PORT = 12368 BINDTO = 127.0.0.1 [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-dht-peer-1/ [nat] DISABLEV6 = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 USE_LOCALADDR = NO [dns] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART=NO [namestore] AUTOSTART = NO gnunet-0.10.1/src/dht/gnunet-service-xdht_nse.c0000644000175000017500000000570712252673741016316 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_nse.c * @brief GNUnet DHT integration with NSE * @author Christian Grothoff */ #include "platform.h" #include "gnunet_nse_service.h" #include "gnunet-service-xdht.h" #include "gnunet-service-xdht_nse.h" /** * log of the current network size estimate, used as the point where * we switch between random and deterministic routing. Default * value of 4.0 is used if NSE module is not available (i.e. not * configured). */ static double log_of_network_size_estimate = 4.0; /** * Network size estimation handle. */ static struct GNUNET_NSE_Handle *nse; /** * Callback that is called when network size estimate is updated. * * @param cls closure * @param timestamp time when the estimate was received from the server (or created by the server) * @param logestimate the log(Base 2) value of the current network size estimate * @param std_dev standard deviation for the estimate * */ static void update_network_size_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, double logestimate, double std_dev) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Network size estimates received"), 1, GNUNET_NO); /* do not allow estimates < 0.5 */ log_of_network_size_estimate = GNUNET_MAX (0.5, logestimate); } /** * Return the log of the current network size estimate. * * @return log of NSE */ double GDS_NSE_get () { return log_of_network_size_estimate; } /** * Initialize NSE subsystem. */ void GDS_NSE_init () { unsigned long long hops; if ( (GNUNET_YES == GNUNET_CONFIGURATION_have_value (GDS_cfg, "dht", "FORCE_NSE")) && (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GDS_cfg, "dht", "FORCE_NSE", &hops)) ) { log_of_network_size_estimate = (double) hops; return; } nse = GNUNET_NSE_connect (GDS_cfg, &update_network_size_estimate, NULL); } /** * Shutdown NSE subsystem. */ void GDS_NSE_done () { if (NULL != nse) { GNUNET_NSE_disconnect (nse); nse = NULL; } } /* end of gnunet-service-dht_nse.c */ gnunet-0.10.1/src/dht/gnunet-dht-monitor.c0000644000175000017500000002060712225777502015304 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-dht-monitor.c * @brief search for data in DHT * @author Christian Grothoff * @author Bartlomiej Polot */ #include "platform.h" #include "gnunet_dht_service.h" /** * The type of the query */ static unsigned int block_type; /** * The key to be monitored */ static char *query_key; /** * User supplied timeout value (in seconds) */ static struct GNUNET_TIME_Relative timeout_request = { 60000 }; /** * Be verbose */ static int verbose; /** * Handle to the DHT */ static struct GNUNET_DHT_Handle *dht_handle; /** * Global handle of the configuration */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for the get request */ static struct GNUNET_DHT_MonitorHandle *monitor_handle; /** * Count of messages received */ static unsigned int result_count; /** * Global status value */ static int ret; /** * Stop monitoring request and start shutdown * * @param cls closure (unused) * @param tc Task Context */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (verbose) FPRINTF (stderr, "%s", "Cleaning up!\n"); if (NULL != monitor_handle) { GNUNET_DHT_monitor_stop (monitor_handle); monitor_handle = NULL; } if (NULL != dht_handle) { GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; } } /** * Callback called on each GET request going through the DHT. * * @param cls Closure. * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the GET path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param key Key of the requested data. */ void get_callback (void *cls, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, const struct GNUNET_HashCode * key) { FPRINTF (stdout, "GET #%u: type %d, key `%s'\n", result_count, (int) type, GNUNET_h2s_full(key)); result_count++; } /** * Callback called on each GET reply going through the DHT. * * @param cls Closure. * @param type The type of data in the result. * @param get_path Peers on GET path (or NULL if not recorded). * @param get_path_length number of entries in get_path. * @param put_path peers on the PUT path (or NULL if not recorded). * @param put_path_length number of entries in get_path. * @param exp Expiration time of the data. * @param key Key of the data. * @param data Pointer to the result data. * @param size Number of bytes in data. */ void get_resp_callback (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size) { FPRINTF (stdout, "RESPONSE #%u: type %d, key `%s', data `%.*s'\n", result_count, (int) type, GNUNET_h2s_full (key), (unsigned int) size, (char *) data); result_count++; } /** * Callback called on each PUT request going through the DHT. * * @param cls Closure. * @param options Options, for instance RecordRoute, DemultiplexEverywhere. * @param type The type of data in the request. * @param hop_count Hop count so far. * @param path_length number of entries in path (or 0 if not recorded). * @param path peers on the PUT path (or NULL if not recorded). * @param desired_replication_level Desired replication level. * @param exp Expiration time of the data. * @param key Key under which data is to be stored. * @param data Pointer to the data carried. * @param size Number of bytes in data. */ void put_callback (void *cls, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, uint32_t hop_count, uint32_t desired_replication_level, unsigned int path_length, const struct GNUNET_PeerIdentity *path, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const void *data, size_t size) { FPRINTF (stdout, "PUT %u: type %d, key `%s', data `%.*s'\n", result_count, (int) type, GNUNET_h2s_full(key), (unsigned int) size, (char *) data); result_count++; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_HashCode *key; struct GNUNET_HashCode hc; cfg = c; if (NULL == (dht_handle = GNUNET_DHT_connect (cfg, 1))) { FPRINTF (stderr, "%s", _("Failed to connect to DHT service!\n")); ret = 1; return; } if (GNUNET_BLOCK_TYPE_ANY == block_type) /* Type of data not set */ block_type = GNUNET_BLOCK_TYPE_TEST; if (NULL != query_key) { key = &hc; if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (query_key, key)) GNUNET_CRYPTO_hash (query_key, strlen (query_key), key); } else { key = NULL; } if (verbose) FPRINTF (stderr, "Monitoring for %s\n", GNUNET_STRINGS_relative_time_to_string (timeout_request, GNUNET_NO)); GNUNET_SCHEDULER_add_delayed (timeout_request, &cleanup_task, NULL); monitor_handle = GNUNET_DHT_monitor_start (dht_handle, block_type, key, &get_callback, &get_resp_callback, &put_callback, NULL); } /** * gnunet-dht-monitor command line options */ static struct GNUNET_GETOPT_CommandLineOption options[] = { {'k', "key", "KEY", gettext_noop ("the query key"), 1, &GNUNET_GETOPT_set_string, &query_key}, {'t', "type", "TYPE", gettext_noop ("the type of data to look for"), 1, &GNUNET_GETOPT_set_uint, &block_type}, {'T', "timeout", "TIMEOUT", gettext_noop ("how long should the monitor command run"), 1, &GNUNET_GETOPT_set_relative_time, &timeout_request}, {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_set_one, &verbose}, GNUNET_GETOPT_OPTION_END }; /** * Entry point for gnunet-dht-monitor * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-dht-monitor", gettext_noop ("Prints all packets that go through the DHT."), options, &run, NULL)) ? ret : 1; } /* end of gnunet-dht-monitor.c */ gnunet-0.10.1/src/dht/gnunet-service-dht.c0000644000175000017500000001171412274162760015252 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht.c * @brief GNUnet DHT service * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_block_lib.h" #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" #include "gnunet_hello_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" #include "gnunet-service-dht.h" #include "gnunet-service-dht_clients.h" #include "gnunet-service-dht_datacache.h" #include "gnunet-service-dht_hello.h" #include "gnunet-service-dht_neighbours.h" #include "gnunet-service-dht_nse.h" #include "gnunet-service-dht_routing.h" /** * Handle for the statistics service. */ struct GNUNET_STATISTICS_Handle *GDS_stats; /** * Our handle to the BLOCK library. */ struct GNUNET_BLOCK_Context *GDS_block_context; /** * The configuration the DHT service is running with */ const struct GNUNET_CONFIGURATION_Handle *GDS_cfg; /** * Our HELLO */ struct GNUNET_MessageHeader *GDS_my_hello; /** * Handle to the transport service, for getting our hello */ struct GNUNET_TRANSPORT_Handle *GDS_transport_handle; /** * Handle to get our current HELLO. */ static struct GNUNET_TRANSPORT_GetHelloHandle *ghh; /** * Hello address expiration */ struct GNUNET_TIME_Relative hello_expiration; /** * Receive the HELLO from transport service, free current and replace * if necessary. * * @param cls NULL * @param message HELLO message of peer */ static void process_hello (void *cls, const struct GNUNET_MessageHeader *message) { GNUNET_assert (message != NULL); GNUNET_free_non_null (GDS_my_hello); GDS_my_hello = GNUNET_malloc (ntohs (message->size)); memcpy (GDS_my_hello, message, ntohs (message->size)); } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != ghh) { GNUNET_TRANSPORT_get_hello_cancel (ghh); ghh = NULL; } if (GDS_transport_handle != NULL) { GNUNET_TRANSPORT_disconnect (GDS_transport_handle); GDS_transport_handle = NULL; } GDS_NEIGHBOURS_done (); GDS_DATACACHE_done (); GDS_ROUTING_done (); GDS_HELLO_done (); GDS_NSE_done (); if (GDS_block_context != NULL) { GNUNET_BLOCK_context_destroy (GDS_block_context); GDS_block_context = NULL; } if (GDS_stats != NULL) { GNUNET_STATISTICS_destroy (GDS_stats, GNUNET_YES); GDS_stats = NULL; } GNUNET_free_non_null (GDS_my_hello); GDS_my_hello = NULL; } /** * Process dht requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { GDS_cfg = c; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, "transport", "HELLO_EXPIRATION", &hello_expiration)) { hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; } GDS_block_context = GNUNET_BLOCK_context_create (GDS_cfg); GDS_stats = GNUNET_STATISTICS_create ("dht", GDS_cfg); GDS_ROUTING_init (); GDS_NSE_init (); GDS_DATACACHE_init (); GDS_HELLO_init (); GDS_CLIENTS_init (server); if (GNUNET_OK != GDS_NEIGHBOURS_init ()) { shutdown_task (NULL, NULL); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); GDS_transport_handle = GNUNET_TRANSPORT_connect (GDS_cfg, NULL, NULL, NULL, NULL, NULL); if (GDS_transport_handle == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to connect to transport service!\n")); return; } ghh = GNUNET_TRANSPORT_get_hello (GDS_transport_handle, &process_hello, NULL); } /** * The main function for the dht service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "dht", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; GDS_CLIENTS_done (); return ret; } /* end of gnunet-service-dht.c */ gnunet-0.10.1/src/dht/gnunet-service-xdht_routing.h0000644000175000017500000000602412320724374017211 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_routing.h * @brief GNUnet DHT tracking of requests for routing replies * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_XDHT_ROUTING_H #define GNUNET_SERVICE_XDHT_ROUTING_H #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_dht_service.h" /** * Add a new entry to our routing table. */ int GDS_ROUTING_add (struct GNUNET_PeerIdentity *source, struct GNUNET_PeerIdentity *destination_peer, struct GNUNET_PeerIdentity *next_hop, const struct GNUNET_PeerIdentity *prev_hop); /** * Search the next hop to send the packet to in routing table. * @return next hop peer id */ struct GNUNET_PeerIdentity * GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer, struct GNUNET_PeerIdentity *destination_peer, const struct GNUNET_PeerIdentity *prev_hop); /** * Handle a reply (route to origin). Only forwards the reply back to * other peers waiting for it. Does not do local caching or * forwarding to local clients. Essentially calls * GDS_NEIGHBOURS_handle_reply for all peers that sent us a matching * request recently. * * @param type type of the block * @param expiration_time when does the content expire * @param key key for the content * @param put_path_length number of entries in @a put_path * @param put_path peers the original PUT traversed (if tracked) * @param get_path_length number of entries in @a get_path * @param get_path peers this reply has traversed so far (if tracked) * @param data payload of the reply * @param data_size number of bytes in @a data */ void GDS_ROUTING_process (enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size); /** * Initialize routing subsystem. */ void GDS_ROUTING_init (void); /** * Shutdown routing subsystem. */ void GDS_ROUTING_done (void); #endif gnunet-0.10.1/src/dht/gnunet-dht-put.c0000644000175000017500000001451612272425070014417 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-dht-put.c * @brief search for data in DHT * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_dht_service.h" /** * The type of the query */ static unsigned int query_type; /** * The key used in the DHT */ struct GNUNET_HashCode key; /** * The key for the query */ static char *query_key; /** * User supplied timeout value */ static unsigned long long timeout_request = 5; /** * User supplied expiration value */ static unsigned long long expiration_seconds = 3600; /** * Desired replication level. */ static unsigned int replication = 5; /** * Be verbose */ static int verbose; /** * Use DHT demultixplex_everywhere */ static int demultixplex_everywhere; /** * Handle to the DHT */ static struct GNUNET_DHT_Handle *dht_handle; /** * Global handle of the configuration */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Global status value */ static int ret; /** * The data to insert into the dht */ static char *data; static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != dht_handle) { GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; } } /** * Signature of the main function of a task. * * @param cls closure * @param success GNUNET_OK if the PUT was transmitted, * GNUNET_NO on timeout, * GNUNET_SYSERR on disconnect from service * after the PUT message was transmitted * (so we don't know if it was received or not) */ static void message_sent_cont (void *cls, int success) { if (verbose) { switch (success) { case GNUNET_OK: FPRINTF (stderr, "%s `%s'!\n", _("PUT request sent with key"), GNUNET_h2s_full(&key)); break; case GNUNET_NO: FPRINTF (stderr, "%s", _("Timeout sending PUT request!\n")); break; case GNUNET_SYSERR: FPRINTF (stderr, "%s", _("PUT request not confirmed!\n")); break; default: GNUNET_break (0); break; } } GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_TIME_Relative timeout; struct GNUNET_TIME_Absolute expiration; cfg = c; if ((NULL == query_key) || (NULL == data)) { FPRINTF (stderr, "%s", _("Must provide KEY and DATA for DHT put!\n")); ret = 1; return; } if (NULL == (dht_handle = GNUNET_DHT_connect (cfg, 1))) { FPRINTF (stderr, _("Could not connect to %s service!\n"), "DHT"); ret = 1; return; } if (GNUNET_BLOCK_TYPE_ANY == query_type) /* Type of data not set */ query_type = GNUNET_BLOCK_TYPE_TEST; GNUNET_CRYPTO_hash (query_key, strlen (query_key), &key); timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, timeout_request); expiration = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, expiration_seconds)); if (verbose) FPRINTF (stderr, _("Issuing put request for `%s' with data `%s'!\n"), query_key, data); GNUNET_DHT_put (dht_handle, &key, replication, (demultixplex_everywhere) ? GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE : GNUNET_DHT_RO_NONE, query_type, strlen (data), data, expiration, timeout, &message_sent_cont, NULL); } /** * gnunet-dht-put command line options */ static struct GNUNET_GETOPT_CommandLineOption options[] = { {'d', "data", "DATA", gettext_noop ("the data to insert under the key"), 1, &GNUNET_GETOPT_set_string, &data}, {'e', "expiration", "EXPIRATION", gettext_noop ("how long to store this entry in the dht (in seconds)"), 1, &GNUNET_GETOPT_set_ulong, &expiration_seconds}, {'k', "key", "KEY", gettext_noop ("the query key"), 1, &GNUNET_GETOPT_set_string, &query_key}, {'x', "demultiplex", NULL, gettext_noop ("use DHT's demultiplex everywhere option"), 0, &GNUNET_GETOPT_set_one, &demultixplex_everywhere}, {'r', "replication", "LEVEL", gettext_noop ("how many replicas to create"), 1, &GNUNET_GETOPT_set_uint, &replication}, {'t', "type", "TYPE", gettext_noop ("the type to insert data as"), 1, &GNUNET_GETOPT_set_uint, &query_type}, {'T', "timeout", "TIMEOUT", gettext_noop ("how long to execute this query before giving up?"), 1, &GNUNET_GETOPT_set_ulong, &timeout_request}, {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_set_one, &verbose}, GNUNET_GETOPT_OPTION_END }; /** * Entry point for gnunet-dht-put * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-dht-put", gettext_noop ("Issue a PUT request to the GNUnet DHT insert DATA under KEY."), options, &run, NULL)) ? ret : 1; } /* end of gnunet-dht-put.c */ gnunet-0.10.1/src/dht/test_dht_monitor.conf0000644000175000017500000000105212225230043015603 00000000000000[fs] AUTOSTART = NO [resolver] AUTOSTART = NO [dhtcache] QUOTA = 1 MB DATABASE = heap [transport] PLUGINS = tcp [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [arm] DEFAULTSERVICES = dht core [testbed] OVERLAY_TOPOLOGY = LINE [PATHS] GNUNET_TEST_HOME = /tmp/test-dht-monitor/ [nat] DISABLEV6 = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 USE_LOCALADDR = YES RETURN_LOCAL_ADDRESSES = YES [dns] AUTOSTART = NO [namestore] AUTOSTART = NO [nse] AUTOSTART = NO [vpn] AUTOSTART=NO gnunet-0.10.1/src/dht/gnunet-dht-get.c0000644000175000017500000001427012272425070014363 00000000000000/* This file is part of GNUnet. (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-dht-get.c * @brief search for data in DHT * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_dht_service.h" #define LOG(kind,...) GNUNET_log_from (kind, "dht-clients",__VA_ARGS__) /** * The type of the query */ static unsigned int query_type; /** * Desired replication level */ static unsigned int replication = 5; /** * The key for the query */ static char *query_key; /** * User supplied timeout value */ static struct GNUNET_TIME_Relative timeout_request = { 60000 }; /** * Be verbose */ static int verbose; /** * Use DHT demultixplex_everywhere */ static int demultixplex_everywhere; /** * Handle to the DHT */ static struct GNUNET_DHT_Handle *dht_handle; /** * Global handle of the configuration */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for the get request */ static struct GNUNET_DHT_GetHandle *get_handle; /** * Count of results found */ static unsigned int result_count; /** * Global status value */ static int ret; /** * Task run to clean up on timeout. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != get_handle) { GNUNET_DHT_get_stop (get_handle); get_handle = NULL; } if (NULL != dht_handle) { GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; } } /** * Iterator called on each result obtained for a DHT * operation that expects a reply * * @param cls closure * @param exp when will this value expire * @param key key of the result * @param get_path peers on reply path (or NULL if not recorded) * @param get_path_length number of entries in get_path * @param put_path peers on the PUT path (or NULL if not recorded) * @param put_path_length number of entries in get_path * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data */ static void get_result_iterator (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { FPRINTF (stdout, _("Result %d, type %d:\n%.*s\n"), result_count, type, (unsigned int) size, (char *) data); result_count++; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_HashCode key; cfg = c; if (NULL == query_key) { FPRINTF (stderr, "%s", _("Must provide key for DHT GET!\n")); ret = 1; return; } if (NULL == (dht_handle = GNUNET_DHT_connect (cfg, 1))) { FPRINTF (stderr, "%s", _("Failed to connect to DHT service!\n")); ret = 1; return; } if (query_type == GNUNET_BLOCK_TYPE_ANY) /* Type of data not set */ query_type = GNUNET_BLOCK_TYPE_TEST; GNUNET_CRYPTO_hash (query_key, strlen (query_key), &key); if (verbose) FPRINTF (stderr, "%s `%s' \n", _("Issueing DHT GET with key"), GNUNET_h2s_full (&key)); GNUNET_SCHEDULER_add_delayed (timeout_request, &cleanup_task, NULL); get_handle = GNUNET_DHT_get_start (dht_handle, query_type, &key, replication, (demultixplex_everywhere) ? GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE : GNUNET_DHT_RO_NONE, NULL, 0, &get_result_iterator, NULL); } /** * gnunet-dht-get command line options */ static struct GNUNET_GETOPT_CommandLineOption options[] = { {'k', "key", "KEY", gettext_noop ("the query key"), 1, &GNUNET_GETOPT_set_string, &query_key}, {'r', "replication", "LEVEL", gettext_noop ("how many parallel requests (replicas) to create"), 1, &GNUNET_GETOPT_set_uint, &replication}, {'t', "type", "TYPE", gettext_noop ("the type of data to look for"), 1, &GNUNET_GETOPT_set_uint, &query_type}, {'T', "timeout", "TIMEOUT", gettext_noop ("how long to execute this query before giving up?"), 1, &GNUNET_GETOPT_set_relative_time, &timeout_request}, {'x', "demultiplex", NULL, gettext_noop ("use DHT's demultiplex everywhere option"), 0, &GNUNET_GETOPT_set_one, &demultixplex_everywhere}, {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_set_one, &verbose}, GNUNET_GETOPT_OPTION_END }; /** * Entry point for gnunet-dht-get * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-dht-get", gettext_noop ("Issue a GET request to the GNUnet DHT, prints results."), options, &run, NULL)) ? ret : 1; } /* end of gnunet-dht-get.c */ gnunet-0.10.1/src/dht/test_dht_api.c0000644000175000017500000001432112272425070014175 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/test_dht_api.c * @brief base test case for dht api * * This test case tests DHT api to DUMMY DHT service communication. * */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_dht_service.h" /** * How long until we really give up on a particular testcase portion? */ #define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600) /** * How long until we give up on any particular operation (and retry)? */ #define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) #define MTYPE 12345 struct RetryContext { /** * When to really abort the operation. */ struct GNUNET_TIME_Absolute real_timeout; /** * What timeout to set for the current attempt (increases) */ struct GNUNET_TIME_Relative next_timeout; /** * The task identifier of the retry task, so it can be cancelled. */ GNUNET_SCHEDULER_TaskIdentifier retry_task; }; static struct GNUNET_DHT_Handle *dht_handle; static struct GNUNET_DHT_GetHandle *get_handle; struct RetryContext retry_context; static int ok = 1; static GNUNET_SCHEDULER_TaskIdentifier die_task; #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DHT disconnected, returning success!\n"); ok = 0; } static void end_badly () { /* do work here */ FPRINTF (stderr, "%s", "Ending on an unhappy note.\n"); if (get_handle != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping get request!\n"); GNUNET_DHT_get_stop (get_handle); } if (retry_context.retry_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (retry_context.retry_task); GNUNET_DHT_disconnect (dht_handle); dht_handle = NULL; ok = 1; } /** * Signature of the main function of a task. * * @param cls closure * @param tc context information (why was this task triggered now) */ static void test_get_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called test_get_stop!\n"); if ((tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT) != 0) { GNUNET_break (0); GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } GNUNET_assert (dht_handle != NULL); GNUNET_DHT_get_stop (get_handle); get_handle = NULL; GNUNET_SCHEDULER_add_now (&end, NULL); } static void test_get_iterator (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode * key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_get_iterator called (we got a result), stopping get request!\n"); GNUNET_SCHEDULER_add_continuation (&test_get_stop, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } /** * Signature of the main function of a task. * * @param cls closure * @param success result of PUT */ static void test_get (void *cls, int success) { struct GNUNET_HashCode hash; memset (&hash, 42, sizeof (struct GNUNET_HashCode)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called test_get!\n"); GNUNET_assert (dht_handle != NULL); retry_context.real_timeout = GNUNET_TIME_relative_to_absolute (TOTAL_TIMEOUT); retry_context.next_timeout = BASE_TIMEOUT; get_handle = GNUNET_DHT_get_start (dht_handle, GNUNET_BLOCK_TYPE_TEST, &hash, 1, GNUNET_DHT_RO_NONE, NULL, 0, &test_get_iterator, NULL); if (get_handle == NULL) { GNUNET_break (0); GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_HashCode hash; char *data; size_t data_size = 42; GNUNET_assert (ok == 1); OKPP; die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1), &end_badly, NULL); memset (&hash, 42, sizeof (struct GNUNET_HashCode)); data = GNUNET_malloc (data_size); memset (data, 43, data_size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called test_put!\n"); dht_handle = GNUNET_DHT_connect (cfg, 100); GNUNET_assert (dht_handle != NULL); GNUNET_DHT_put (dht_handle, &hash, 1, GNUNET_DHT_RO_NONE, GNUNET_BLOCK_TYPE_TEST, data_size, data, GNUNET_TIME_relative_to_absolute (TOTAL_TIMEOUT), TOTAL_TIMEOUT, &test_get, NULL); GNUNET_free (data); } int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-dht-api", "test_dht_api_data.conf", &run, NULL)) return 1; return ok; } /* end of test_dht_api.c */ gnunet-0.10.1/src/dht/dht_api.c0000644000175000017500000012661712316473376013165 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/dht_api.c * @brief library to access the DHT service * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_arm_service.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_dht_service.h" #include "dht.h" #define LOG(kind,...) GNUNET_log_from (kind, "dht-api",__VA_ARGS__) /** * Entry in our list of messages to be (re-)transmitted. */ struct PendingMessage { /** * This is a doubly-linked list. */ struct PendingMessage *prev; /** * This is a doubly-linked list. */ struct PendingMessage *next; /** * Message that is pending, allocated at the end * of this struct. */ const struct GNUNET_MessageHeader *msg; /** * Handle to the DHT API context. */ struct GNUNET_DHT_Handle *handle; /** * Continuation to call when the request has been * transmitted (for the first time) to the service; can be NULL. */ GNUNET_SCHEDULER_Task cont; /** * Closure for 'cont'. */ void *cont_cls; /** * Unique ID for this request */ uint64_t unique_id; /** * Free the saved message once sent, set to GNUNET_YES for messages * that do not receive responses; GNUNET_NO if this pending message * is aliased from a 'struct GNUNET_DHT_RouteHandle' and will be freed * from there. */ int free_on_send; /** * GNUNET_YES if this message is in our pending queue right now. */ int in_pending_queue; }; /** * Handle to a PUT request. */ struct GNUNET_DHT_PutHandle { /** * Kept in a DLL. */ struct GNUNET_DHT_PutHandle *next; /** * Kept in a DLL. */ struct GNUNET_DHT_PutHandle *prev; /** * Continuation to call when done. */ GNUNET_DHT_PutContinuation cont; /** * Pending message associated with this PUT operation, * NULL after the message has been transmitted to the service. */ struct PendingMessage *pending; /** * Main handle to this DHT api */ struct GNUNET_DHT_Handle *dht_handle; /** * Closure for 'cont'. */ void *cont_cls; /** * Timeout task for this operation. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Unique ID for the PUT operation. */ uint64_t unique_id; }; /** * Handle to a GET request */ struct GNUNET_DHT_GetHandle { /** * Iterator to call on data receipt */ GNUNET_DHT_GetIterator iter; /** * Closure for the iterator callback */ void *iter_cls; /** * Main handle to this DHT api */ struct GNUNET_DHT_Handle *dht_handle; /** * The actual message sent for this request, * used for retransmitting requests on service * failure/reconnect. Freed on route_stop. */ struct PendingMessage *message; /** * Array of hash codes over the results that we have already * seen. */ struct GNUNET_HashCode *seen_results; /** * Key that this get request is for */ struct GNUNET_HashCode key; /** * Unique identifier for this request (for key collisions). */ uint64_t unique_id; /** * Size of the 'seen_results' array. Note that not * all positions might be used (as we over-allocate). */ unsigned int seen_results_size; /** * Offset into the 'seen_results' array marking the * end of the positions that are actually used. */ unsigned int seen_results_end; /** * Offset into the 'seen_results' array marking the * position up to where we've send the hash codes to * the DHT for blocking (needed as we might not be * able to send all hash codes at once). */ unsigned int seen_results_transmission_offset; }; /** * Handle to a monitoring request. */ struct GNUNET_DHT_MonitorHandle { /** * DLL. */ struct GNUNET_DHT_MonitorHandle *next; /** * DLL. */ struct GNUNET_DHT_MonitorHandle *prev; /** * Main handle to this DHT api. */ struct GNUNET_DHT_Handle *dht_handle; /** * Type of block looked for. */ enum GNUNET_BLOCK_Type type; /** * Key being looked for, NULL == all. */ struct GNUNET_HashCode *key; /** * Callback for each received message of type get. */ GNUNET_DHT_MonitorGetCB get_cb; /** * Callback for each received message of type get response. */ GNUNET_DHT_MonitorGetRespCB get_resp_cb; /** * Callback for each received message of type put. */ GNUNET_DHT_MonitorPutCB put_cb; /** * Closure for cb. */ void *cb_cls; }; /** * Connection to the DHT service. */ struct GNUNET_DHT_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Currently pending transmission request (or NULL). */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of linked list of messages we would like to transmit. */ struct PendingMessage *pending_head; /** * Tail of linked list of messages we would like to transmit. */ struct PendingMessage *pending_tail; /** * Head of linked list of messages we would like to monitor. */ struct GNUNET_DHT_MonitorHandle *monitor_head; /** * Tail of linked list of messages we would like to monitor. */ struct GNUNET_DHT_MonitorHandle *monitor_tail; /** * Head of active PUT requests. */ struct GNUNET_DHT_PutHandle *put_head; /** * Tail of active PUT requests. */ struct GNUNET_DHT_PutHandle *put_tail; /** * Hash map containing the current outstanding unique GET requests * (values are of type `struct GNUNET_DHT_GetHandle`). */ struct GNUNET_CONTAINER_MultiHashMap *active_requests; /** * Task for trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * How quickly should we retry? Used for exponential back-off on * connect-errors. */ struct GNUNET_TIME_Relative retry_time; /** * Generator for unique ids. */ uint64_t uid_gen; /** * Did we start our receive loop yet? */ int in_receive; }; /** * Handler for messages received from the DHT service * a demultiplexer which handles numerous message types * * @param cls the `struct GNUNET_DHT_Handle` * @param msg the incoming message */ static void service_message_handler (void *cls, const struct GNUNET_MessageHeader *msg); /** * Try to (re)connect to the DHT service. * * @param handle DHT handle to reconnect * @return #GNUNET_YES on success, #GNUNET_NO on failure. */ static int try_connect (struct GNUNET_DHT_Handle *handle) { if (NULL != handle->client) return GNUNET_OK; handle->in_receive = GNUNET_NO; handle->client = GNUNET_CLIENT_connect ("dht", handle->cfg); if (NULL == handle->client) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to connect to the DHT service!\n")); return GNUNET_NO; } return GNUNET_YES; } /** * Queue messages to DHT to block certain results from the result set. * * @param get_handle GET to generate messages for. */ static void queue_filter_messages (struct GNUNET_DHT_GetHandle *get_handle) { struct PendingMessage *pm; struct GNUNET_DHT_ClientGetResultSeenMessage *msg; uint16_t msize; unsigned int delta; unsigned int max; while (get_handle->seen_results_transmission_offset < get_handle->seen_results_end) { delta = get_handle->seen_results_end - get_handle->seen_results_transmission_offset; max = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage)) / sizeof (struct GNUNET_HashCode); if (delta > max) delta = max; msize = sizeof (struct GNUNET_DHT_ClientGetResultSeenMessage) + delta * sizeof (struct GNUNET_HashCode); pm = GNUNET_malloc (sizeof (struct PendingMessage) + msize); msg = (struct GNUNET_DHT_ClientGetResultSeenMessage *) &pm[1]; pm->msg = &msg->header; pm->handle = get_handle->dht_handle; pm->unique_id = get_handle->unique_id; pm->free_on_send = GNUNET_YES; pm->in_pending_queue = GNUNET_YES; msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_RESULTS_KNOWN); msg->header.size = htons (msize); msg->key = get_handle->key; msg->unique_id = get_handle->unique_id; memcpy (&msg[1], &get_handle->seen_results[get_handle->seen_results_transmission_offset], sizeof (struct GNUNET_HashCode) * delta); get_handle->seen_results_transmission_offset += delta; GNUNET_CONTAINER_DLL_insert_tail (get_handle->dht_handle->pending_head, get_handle->dht_handle->pending_tail, pm); } } /** * Add the request corresponding to the given route handle * to the pending queue (if it is not already in there). * * @param cls the `struct GNUNET_DHT_Handle *` * @param key key for the request (not used) * @param value the `struct GNUNET_DHT_GetHandle *` * @return #GNUNET_YES (always) */ static int add_request_to_pending (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_DHT_Handle *handle = cls; struct GNUNET_DHT_GetHandle *get_handle = value; if (GNUNET_NO == get_handle->message->in_pending_queue) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Retransmitting request related to %s to DHT %p\n", GNUNET_h2s (key), handle); get_handle->seen_results_transmission_offset = 0; GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, get_handle->message); queue_filter_messages (get_handle); get_handle->message->in_pending_queue = GNUNET_YES; } return GNUNET_YES; } /** * Try to send messages from list of messages to send * * @param handle DHT_Handle */ static void process_pending_messages (struct GNUNET_DHT_Handle *handle); /** * Try reconnecting to the dht service. * * @param cls a `struct GNUNET_DHT_Handle` * @param tc scheduler context */ static void try_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DHT_Handle *handle = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting with DHT %p\n", handle); handle->retry_time = GNUNET_TIME_STD_BACKOFF (handle->retry_time); handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_YES != try_connect (handle)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "dht reconnect failed(!)\n"); return; } GNUNET_CONTAINER_multihashmap_iterate (handle->active_requests, &add_request_to_pending, handle); process_pending_messages (handle); } /** * Try reconnecting to the DHT service. * * @param handle handle to dht to (possibly) disconnect and reconnect */ static void do_disconnect (struct GNUNET_DHT_Handle *handle) { struct GNUNET_DHT_PutHandle *ph; struct GNUNET_DHT_PutHandle *next; if (NULL == handle->client) return; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == handle->reconnect_task); if (NULL != handle->th) GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); handle->th = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from DHT service, will try to reconnect in %s\n", GNUNET_STRINGS_relative_time_to_string (handle->retry_time, GNUNET_YES)); GNUNET_CLIENT_disconnect (handle->client); handle->client = NULL; /* signal disconnect to all PUT requests that were transmitted but waiting for the put confirmation */ next = handle->put_head; while (NULL != (ph = next)) { next = ph->next; if (NULL == ph->pending) { if (NULL != ph->cont) ph->cont (ph->cont_cls, GNUNET_SYSERR); GNUNET_DHT_put_cancel (ph); } } handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->retry_time, &try_reconnect, handle); } /** * Transmit the next pending message, called by notify_transmit_ready * * @param cls the DHT handle * @param size number of bytes available in @a buf for transmission * @param buf where to copy messages for the service * @return number of bytes written to @a buf */ static size_t transmit_pending (void *cls, size_t size, void *buf); /** * Try to send messages from list of messages to send * * @param handle handle to DHT */ static void process_pending_messages (struct GNUNET_DHT_Handle *handle) { struct PendingMessage *head; if (NULL == handle->client) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "process_pending_messages called, but client is NULL, reconnecting\n"); do_disconnect (handle); return; } if (NULL != handle->th) return; if (NULL == (head = handle->pending_head)) return; handle->th = GNUNET_CLIENT_notify_transmit_ready (handle->client, ntohs (head->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_pending, handle); if (NULL != handle->th) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "notify_transmit_ready returned NULL, reconnecting\n"); do_disconnect (handle); } /** * Transmit the next pending message, called by notify_transmit_ready * * @param cls the DHT handle * @param size number of bytes available in @a buf for transmission * @param buf where to copy messages for the service * @return number of bytes written to @a buf */ static size_t transmit_pending (void *cls, size_t size, void *buf) { struct GNUNET_DHT_Handle *handle = cls; struct PendingMessage *head; size_t tsize; handle->th = NULL; if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission to DHT service failed! Reconnecting!\n"); do_disconnect (handle); return 0; } if (NULL == (head = handle->pending_head)) return 0; tsize = ntohs (head->msg->size); if (size < tsize) { process_pending_messages (handle); return 0; } memcpy (buf, head->msg, tsize); GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, head); head->in_pending_queue = GNUNET_NO; if (NULL != head->cont) { head->cont (head->cont_cls, NULL); head->cont = NULL; head->cont_cls = NULL; } if (GNUNET_YES == head->free_on_send) GNUNET_free (head); process_pending_messages (handle); LOG (GNUNET_ERROR_TYPE_DEBUG, "Forwarded request of %u bytes to DHT service\n", (unsigned int) tsize); if (GNUNET_NO == handle->in_receive) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting to process replies from DHT\n"); handle->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (handle->client, &service_message_handler, handle, GNUNET_TIME_UNIT_FOREVER_REL); } return tsize; } /** * Process a given reply that might match the given * request. * * @param cls the `struct GNUNET_DHT_ClientResultMessage` * @param key query of the request * @param value the `struct GNUNET_DHT_RouteHandle` of a request matching the same key * @return #GNUNET_YES to continue to iterate over all results, * #GNUNET_NO if the reply is malformed or we found a matching request */ static int process_reply (void *cls, const struct GNUNET_HashCode *key, void *value) { const struct GNUNET_DHT_ClientResultMessage *dht_msg = cls; struct GNUNET_DHT_GetHandle *get_handle = value; const struct GNUNET_PeerIdentity *put_path; const struct GNUNET_PeerIdentity *get_path; struct GNUNET_HashCode hc; uint32_t put_path_length; uint32_t get_path_length; size_t data_length; size_t msize; size_t meta_length; const void *data; if (dht_msg->unique_id != get_handle->unique_id) { /* UID mismatch */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Ignoring reply for %s: UID mismatch: %llu/%llu\n", GNUNET_h2s (key), dht_msg->unique_id, get_handle->unique_id); return GNUNET_YES; } msize = ntohs (dht_msg->header.size); put_path_length = ntohl (dht_msg->put_path_length); get_path_length = ntohl (dht_msg->get_path_length); meta_length = sizeof (struct GNUNET_DHT_ClientResultMessage) + sizeof (struct GNUNET_PeerIdentity) * (get_path_length + put_path_length); if ((msize < meta_length) || (get_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || (put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); return GNUNET_NO; } data_length = msize - meta_length; LOG (GNUNET_ERROR_TYPE_DEBUG, "Giving %u byte reply for %s to application\n", (unsigned int) data_length, GNUNET_h2s (key)); put_path = (const struct GNUNET_PeerIdentity *) &dht_msg[1]; get_path = &put_path[put_path_length]; data = &get_path[get_path_length]; /* remember that we've seen this result */ GNUNET_CRYPTO_hash (data, data_length, &hc); if (get_handle->seen_results_size == get_handle->seen_results_end) GNUNET_array_grow (get_handle->seen_results, get_handle->seen_results_size, get_handle->seen_results_size * 2 + 1); GNUNET_assert (get_handle->seen_results_end == get_handle->seen_results_transmission_offset); get_handle->seen_results[get_handle->seen_results_end++] = hc; /* no need to block it explicitly, service already knows about it! */ get_handle->seen_results_transmission_offset++; get_handle->iter (get_handle->iter_cls, GNUNET_TIME_absolute_ntoh (dht_msg->expiration), key, get_path, get_path_length, put_path, put_path_length, ntohl (dht_msg->type), data_length, data); return GNUNET_NO; } /** * Process a get monitor message from the service. * * @param handle The DHT handle. * @param msg Monitor get message from the service. * @return #GNUNET_OK if everything went fine, * #GNUNET_SYSERR if the message is malformed. */ static int process_monitor_get_message (struct GNUNET_DHT_Handle *handle, const struct GNUNET_DHT_MonitorGetMessage *msg) { struct GNUNET_DHT_MonitorHandle *h; for (h = handle->monitor_head; NULL != h; h = h->next) { int type_ok; int key_ok; type_ok = (GNUNET_BLOCK_TYPE_ANY == h->type) || (h->type == ntohl(msg->type)); key_ok = (NULL == h->key) || (0 == memcmp (h->key, &msg->key, sizeof (struct GNUNET_HashCode))); if (type_ok && key_ok && (NULL != h->get_cb)) h->get_cb (h->cb_cls, ntohl (msg->options), (enum GNUNET_BLOCK_Type) ntohl(msg->type), ntohl (msg->hop_count), ntohl (msg->desired_replication_level), ntohl (msg->get_path_length), (struct GNUNET_PeerIdentity *) &msg[1], &msg->key); } return GNUNET_OK; } /** * Process a get response monitor message from the service. * * @param handle The DHT handle. * @param msg monitor get response message from the service * @return #GNUNET_OK if everything went fine, * #GNUNET_SYSERR if the message is malformed. */ static int process_monitor_get_resp_message (struct GNUNET_DHT_Handle *handle, const struct GNUNET_DHT_MonitorGetRespMessage *msg) { struct GNUNET_DHT_MonitorHandle *h; struct GNUNET_PeerIdentity *path; uint32_t getl; uint32_t putl; size_t msize; msize = ntohs (msg->header.size); path = (struct GNUNET_PeerIdentity *) &msg[1]; getl = ntohl (msg->get_path_length); putl = ntohl (msg->put_path_length); if ( (getl + putl < getl) || ( ((msize - sizeof (struct GNUNET_DHT_MonitorGetRespMessage)) / sizeof (struct GNUNET_PeerIdentity)) < getl + putl) ) { GNUNET_break (0); return GNUNET_SYSERR; } for (h = handle->monitor_head; NULL != h; h = h->next) { int type_ok; int key_ok; type_ok = (GNUNET_BLOCK_TYPE_ANY == h->type) || (h->type == ntohl(msg->type)); key_ok = (NULL == h->key) || (0 == memcmp (h->key, &msg->key, sizeof (struct GNUNET_HashCode))); if (type_ok && key_ok && (NULL != h->get_resp_cb)) h->get_resp_cb (h->cb_cls, (enum GNUNET_BLOCK_Type) ntohl(msg->type), path, getl, &path[getl], putl, GNUNET_TIME_absolute_ntoh(msg->expiration_time), &msg->key, (void *) &path[getl + putl], msize - sizeof (struct GNUNET_DHT_MonitorGetRespMessage) - sizeof (struct GNUNET_PeerIdentity) * (putl + getl)); } return GNUNET_OK; } /** * Process a put monitor message from the service. * * @param handle The DHT handle. * @param msg Monitor put message from the service. * @return #GNUNET_OK if everything went fine, * #GNUNET_SYSERR if the message is malformed. */ static int process_monitor_put_message (struct GNUNET_DHT_Handle *handle, const struct GNUNET_DHT_MonitorPutMessage *msg) { struct GNUNET_DHT_MonitorHandle *h; size_t msize; struct GNUNET_PeerIdentity *path; uint32_t putl; msize = ntohs (msg->header.size); path = (struct GNUNET_PeerIdentity *) &msg[1]; putl = ntohl (msg->put_path_length); if (((msize - sizeof (struct GNUNET_DHT_MonitorGetRespMessage)) / sizeof (struct GNUNET_PeerIdentity)) < putl) { GNUNET_break (0); return GNUNET_SYSERR; } for (h = handle->monitor_head; NULL != h; h = h->next) { int type_ok; int key_ok; type_ok = (GNUNET_BLOCK_TYPE_ANY == h->type) || (h->type == ntohl(msg->type)); key_ok = (NULL == h->key) || (0 == memcmp (h->key, &msg->key, sizeof (struct GNUNET_HashCode))); if (type_ok && key_ok && (NULL != h->put_cb)) h->put_cb (h->cb_cls, ntohl (msg->options), (enum GNUNET_BLOCK_Type) ntohl(msg->type), ntohl (msg->hop_count), ntohl (msg->desired_replication_level), putl, path, GNUNET_TIME_absolute_ntoh(msg->expiration_time), &msg->key, (void *) &path[putl], msize - sizeof (struct GNUNET_DHT_MonitorPutMessage) - sizeof (struct GNUNET_PeerIdentity) * putl); } return GNUNET_OK; } /** * Process a put confirmation message from the service. * * @param handle The DHT handle. * @param msg confirmation message from the service. * @return #GNUNET_OK if everything went fine, * #GNUNET_SYSERR if the message is malformed. */ static int process_put_confirmation_message (struct GNUNET_DHT_Handle *handle, const struct GNUNET_DHT_ClientPutConfirmationMessage *msg) { struct GNUNET_DHT_PutHandle *ph; GNUNET_DHT_PutContinuation cont; void *cont_cls; for (ph = handle->put_head; NULL != ph; ph = ph->next) if (ph->unique_id == msg->unique_id) break; if (NULL == ph) return GNUNET_OK; cont = ph->cont; cont_cls = ph->cont_cls; GNUNET_DHT_put_cancel (ph); if (NULL != cont) cont (cont_cls, GNUNET_OK); return GNUNET_OK; } /** * Handler for messages received from the DHT service * a demultiplexer which handles numerous message types * * @param cls the `struct GNUNET_DHT_Handle` * @param msg the incoming message */ static void service_message_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_DHT_Handle *handle = cls; const struct GNUNET_DHT_ClientResultMessage *dht_msg; uint16_t msize; int ret; if (NULL == msg) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Error receiving data from DHT service, reconnecting\n"); do_disconnect (handle); return; } GNUNET_CLIENT_receive (handle->client, &service_message_handler, handle, GNUNET_TIME_UNIT_FOREVER_REL); ret = GNUNET_SYSERR; msize = ntohs (msg->size); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET: if (msize < sizeof (struct GNUNET_DHT_MonitorGetMessage)) { GNUNET_break (0); break; } ret = process_monitor_get_message(handle, (const struct GNUNET_DHT_MonitorGetMessage *) msg); break; case GNUNET_MESSAGE_TYPE_DHT_MONITOR_GET_RESP: if (msize < sizeof (struct GNUNET_DHT_MonitorGetRespMessage)) { GNUNET_break (0); break; } ret = process_monitor_get_resp_message(handle, (const struct GNUNET_DHT_MonitorGetRespMessage *) msg); break; case GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT: if (msize < sizeof (struct GNUNET_DHT_MonitorPutMessage)) { GNUNET_break (0); break; } ret = process_monitor_put_message(handle, (const struct GNUNET_DHT_MonitorPutMessage *) msg); break; case GNUNET_MESSAGE_TYPE_DHT_MONITOR_PUT_RESP: /* Not implemented yet */ GNUNET_break(0); break; case GNUNET_MESSAGE_TYPE_DHT_CLIENT_RESULT: if (ntohs (msg->size) < sizeof (struct GNUNET_DHT_ClientResultMessage)) { GNUNET_break (0); break; } dht_msg = (const struct GNUNET_DHT_ClientResultMessage *) msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received reply for `%s' from DHT service %p\n", GNUNET_h2s (&dht_msg->key), handle); GNUNET_CONTAINER_multihashmap_get_multiple (handle->active_requests, &dht_msg->key, &process_reply, (void *) dht_msg); ret = GNUNET_OK; break; case GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT_OK: if (ntohs (msg->size) != sizeof (struct GNUNET_DHT_ClientPutConfirmationMessage)) { GNUNET_break (0); break; } ret = process_put_confirmation_message (handle, (const struct GNUNET_DHT_ClientPutConfirmationMessage*) msg); break; default: GNUNET_break(0); LOG (GNUNET_ERROR_TYPE_WARNING, "Unknown DHT message type: %hu (%hu) size: %hu\n", ntohs (msg->type), msg->type, msize); break; } if (GNUNET_OK != ret) { GNUNET_break (0); do_disconnect (handle); return; } } /** * Initialize the connection with the DHT service. * * @param cfg configuration to use * @param ht_len size of the internal hash table to use for * processing multiple GET/FIND requests in parallel * @return handle to the DHT service, or NULL on error */ struct GNUNET_DHT_Handle * GNUNET_DHT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int ht_len) { struct GNUNET_DHT_Handle *handle; handle = GNUNET_new (struct GNUNET_DHT_Handle); handle->cfg = cfg; handle->uid_gen = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); handle->active_requests = GNUNET_CONTAINER_multihashmap_create (ht_len, GNUNET_YES); if (GNUNET_NO == try_connect (handle)) { GNUNET_DHT_disconnect (handle); return NULL; } return handle; } /** * Shutdown connection with the DHT service. * * @param handle handle of the DHT connection to stop */ void GNUNET_DHT_disconnect (struct GNUNET_DHT_Handle *handle) { struct PendingMessage *pm; struct GNUNET_DHT_PutHandle *ph; GNUNET_assert (NULL != handle); GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (handle->active_requests)); if (NULL != handle->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); handle->th = NULL; } while (NULL != (pm = handle->pending_head)) { GNUNET_assert (GNUNET_YES == pm->in_pending_queue); GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, pm); pm->in_pending_queue = GNUNET_NO; GNUNET_assert (GNUNET_YES == pm->free_on_send); if (NULL != pm->cont) pm->cont (pm->cont_cls, NULL); GNUNET_free (pm); } while (NULL != (ph = handle->put_head)) { GNUNET_break (NULL == ph->pending); if (NULL != ph->cont) ph->cont (ph->cont_cls, GNUNET_SYSERR); GNUNET_DHT_put_cancel (ph); } if (NULL != handle->client) { GNUNET_CLIENT_disconnect (handle->client); handle->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task) GNUNET_SCHEDULER_cancel (handle->reconnect_task); GNUNET_CONTAINER_multihashmap_destroy (handle->active_requests); GNUNET_free (handle); } /** * Timeout for the transmission of a fire&forget-request. Clean it up. * * @param cls the `struct GNUNET_DHT_PutHandle *` * @param tc scheduler context */ static void timeout_put_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DHT_PutHandle *ph = cls; struct GNUNET_DHT_Handle *handle = ph->dht_handle; ph->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != ph->pending) { GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, ph->pending); ph->pending->in_pending_queue = GNUNET_NO; GNUNET_free (ph->pending); } if (NULL != ph->cont) ph->cont (ph->cont_cls, GNUNET_NO); GNUNET_CONTAINER_DLL_remove (handle->put_head, handle->put_tail, ph); GNUNET_free (ph); } /** * Function called whenever the PUT message leaves the queue. Sets * the message pointer in the put handle to NULL. * * @param cls the `struct GNUNET_DHT_PutHandle` * @param tc unused */ static void mark_put_message_gone (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DHT_PutHandle *ph = cls; ph->pending = NULL; } /** * Perform a PUT operation storing data in the DHT. FIXME: we should * change the protocol to get a confirmation for the PUT from the DHT * and call 'cont' only after getting the confirmation; otherwise, the * client has no good way of telling if the 'PUT' message actually got * to the DHT service! * * @param handle handle to DHT service * @param key the key to store under * @param desired_replication_level estimate of how many * nearest peers this request should reach * @param options routing options for this message * @param type type of the value * @param size number of bytes in data; must be less than 64k * @param data the data to store * @param exp desired expiration time for the value * @param timeout how long to wait for transmission of this request * @param cont continuation to call when done (transmitting request to service) * You must not call #GNUNET_DHT_disconnect in this continuation * @param cont_cls closure for @a cont */ struct GNUNET_DHT_PutHandle * GNUNET_DHT_put (struct GNUNET_DHT_Handle *handle, const struct GNUNET_HashCode * key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, enum GNUNET_BLOCK_Type type, size_t size, const void *data, struct GNUNET_TIME_Absolute exp, struct GNUNET_TIME_Relative timeout, GNUNET_DHT_PutContinuation cont, void *cont_cls) { struct GNUNET_DHT_ClientPutMessage *put_msg; size_t msize; struct PendingMessage *pending; struct GNUNET_DHT_PutHandle *ph; msize = sizeof (struct GNUNET_DHT_ClientPutMessage) + size; if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)) { GNUNET_break (0); return NULL; } ph = GNUNET_new (struct GNUNET_DHT_PutHandle); ph->dht_handle = handle; ph->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_put_request, ph); ph->cont = cont; ph->cont_cls = cont_cls; ph->unique_id = ++handle->uid_gen; pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); ph->pending = pending; put_msg = (struct GNUNET_DHT_ClientPutMessage *) &pending[1]; pending->msg = &put_msg->header; pending->handle = handle; pending->cont = &mark_put_message_gone; pending->cont_cls = ph; pending->free_on_send = GNUNET_YES; put_msg->header.size = htons (msize); put_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_PUT); put_msg->type = htonl (type); put_msg->options = htonl ((uint32_t) options); put_msg->desired_replication_level = htonl (desired_replication_level); put_msg->unique_id = ph->unique_id; put_msg->expiration = GNUNET_TIME_absolute_hton (exp); put_msg->key = *key; memcpy (&put_msg[1], data, size); GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; GNUNET_CONTAINER_DLL_insert_tail (handle->put_head, handle->put_tail, ph); process_pending_messages (handle); return ph; } /** * Cancels a DHT PUT operation. Note that the PUT request may still * go out over the network (we can't stop that); However, if the PUT * has not yet been sent to the service, cancelling the PUT will stop * this from happening (but there is no way for the user of this API * to tell if that is the case). The only use for this API is to * prevent a later call to 'cont' from #GNUNET_DHT_put (i.e. because * the system is shutting down). * * @param ph put operation to cancel ('cont' will no longer be called) */ void GNUNET_DHT_put_cancel (struct GNUNET_DHT_PutHandle *ph) { struct GNUNET_DHT_Handle *handle = ph->dht_handle; if (NULL != ph->pending) { GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, ph->pending); GNUNET_free (ph->pending); ph->pending = NULL; } if (ph->timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ph->timeout_task); ph->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_DLL_remove (handle->put_head, handle->put_tail, ph); GNUNET_free (ph); } /** * Perform an asynchronous GET operation on the DHT identified. See * also #GNUNET_BLOCK_evaluate. * * @param handle handle to the DHT service * @param type expected type of the response object * @param key the key to look up * @param desired_replication_level estimate of how many nearest peers this request should reach * @param options routing options for this message * @param xquery extended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param iter function to call on each result * @param iter_cls closure for iter * @return handle to stop the async get */ struct GNUNET_DHT_GetHandle * GNUNET_DHT_get_start (struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * key, uint32_t desired_replication_level, enum GNUNET_DHT_RouteOption options, const void *xquery, size_t xquery_size, GNUNET_DHT_GetIterator iter, void *iter_cls) { struct GNUNET_DHT_ClientGetMessage *get_msg; struct GNUNET_DHT_GetHandle *get_handle; size_t msize; struct PendingMessage *pending; msize = sizeof (struct GNUNET_DHT_ClientGetMessage) + xquery_size; if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (xquery_size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)) { GNUNET_break (0); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending query for %s to DHT %p\n", GNUNET_h2s (key), handle); pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize); get_msg = (struct GNUNET_DHT_ClientGetMessage *) &pending[1]; pending->msg = &get_msg->header; pending->handle = handle; pending->free_on_send = GNUNET_NO; get_msg->header.size = htons (msize); get_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET); get_msg->options = htonl ((uint32_t) options); get_msg->desired_replication_level = htonl (desired_replication_level); get_msg->type = htonl (type); get_msg->key = *key; get_msg->unique_id = ++handle->uid_gen; memcpy (&get_msg[1], xquery, xquery_size); GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; get_handle = GNUNET_new (struct GNUNET_DHT_GetHandle); get_handle->key = *key; get_handle->dht_handle = handle; get_handle->iter = iter; get_handle->iter_cls = iter_cls; get_handle->message = pending; get_handle->unique_id = get_msg->unique_id; GNUNET_CONTAINER_multihashmap_put (handle->active_requests, &get_handle->key, get_handle, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); process_pending_messages (handle); return get_handle; } /** * Tell the DHT not to return any of the following known results * to this client. * * @param get_handle get operation for which results should be filtered * @param num_results number of results to be blocked that are * provided in this call (size of the @a results array) * @param results array of hash codes over the 'data' of the results * to be blocked */ void GNUNET_DHT_get_filter_known_results (struct GNUNET_DHT_GetHandle *get_handle, unsigned int num_results, const struct GNUNET_HashCode *results) { unsigned int needed; needed = get_handle->seen_results_end + num_results; if (needed > get_handle->seen_results_size) GNUNET_array_grow (get_handle->seen_results, get_handle->seen_results_size, needed); memcpy (&get_handle->seen_results[get_handle->seen_results_end], results, num_results * sizeof (struct GNUNET_HashCode)); get_handle->seen_results_end += num_results; queue_filter_messages (get_handle); process_pending_messages (get_handle->dht_handle); } /** * Stop async DHT-get. * * @param get_handle handle to the GET operation to stop */ void GNUNET_DHT_get_stop (struct GNUNET_DHT_GetHandle *get_handle) { struct GNUNET_DHT_Handle *handle; const struct GNUNET_DHT_ClientGetMessage *get_msg; struct GNUNET_DHT_ClientGetStopMessage *stop_msg; struct PendingMessage *pending; handle = get_handle->message->handle; get_msg = (const struct GNUNET_DHT_ClientGetMessage *) get_handle->message->msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending STOP for %s to DHT via %p\n", GNUNET_h2s (&get_msg->key), handle); /* generate STOP */ pending = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct GNUNET_DHT_ClientGetStopMessage)); stop_msg = (struct GNUNET_DHT_ClientGetStopMessage *) &pending[1]; pending->msg = &stop_msg->header; pending->handle = handle; pending->free_on_send = GNUNET_YES; stop_msg->header.size = htons (sizeof (struct GNUNET_DHT_ClientGetStopMessage)); stop_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_CLIENT_GET_STOP); stop_msg->reserved = htonl (0); stop_msg->unique_id = get_msg->unique_id; stop_msg->key = get_msg->key; GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; /* remove 'GET' from active status */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->active_requests, &get_handle->key, get_handle)); if (GNUNET_YES == get_handle->message->in_pending_queue) { GNUNET_CONTAINER_DLL_remove (handle->pending_head, handle->pending_tail, get_handle->message); get_handle->message->in_pending_queue = GNUNET_NO; } GNUNET_free (get_handle->message); GNUNET_array_grow (get_handle->seen_results, get_handle->seen_results_end, 0); GNUNET_free (get_handle); process_pending_messages (handle); } /** * Start monitoring the local DHT service. * * @param handle Handle to the DHT service. * @param type Type of blocks that are of interest. * @param key Key of data of interest, NULL for all. * @param get_cb Callback to process monitored get messages. * @param get_resp_cb Callback to process monitored get response messages. * @param put_cb Callback to process monitored put messages. * @param cb_cls Closure for callbacks. * @return Handle to stop monitoring. */ struct GNUNET_DHT_MonitorHandle * GNUNET_DHT_monitor_start (struct GNUNET_DHT_Handle *handle, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode *key, GNUNET_DHT_MonitorGetCB get_cb, GNUNET_DHT_MonitorGetRespCB get_resp_cb, GNUNET_DHT_MonitorPutCB put_cb, void *cb_cls) { struct GNUNET_DHT_MonitorHandle *h; struct GNUNET_DHT_MonitorStartStopMessage *m; struct PendingMessage *pending; h = GNUNET_new (struct GNUNET_DHT_MonitorHandle); GNUNET_CONTAINER_DLL_insert(handle->monitor_head, handle->monitor_tail, h); h->get_cb = get_cb; h->get_resp_cb = get_resp_cb; h->put_cb = put_cb; h->cb_cls = cb_cls; h->type = type; h->dht_handle = handle; if (NULL != key) { h->key = GNUNET_new (struct GNUNET_HashCode); *h->key = *key; } pending = GNUNET_malloc (sizeof (struct GNUNET_DHT_MonitorStartStopMessage) + sizeof (struct PendingMessage)); m = (struct GNUNET_DHT_MonitorStartStopMessage *) &pending[1]; pending->msg = &m->header; pending->handle = handle; pending->free_on_send = GNUNET_YES; m->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_START); m->header.size = htons (sizeof (struct GNUNET_DHT_MonitorStartStopMessage)); m->type = htonl(type); m->get = htons(NULL != get_cb); m->get_resp = htons(NULL != get_resp_cb); m->put = htons(NULL != put_cb); if (NULL != key) { m->filter_key = htons(1); memcpy (&m->key, key, sizeof(struct GNUNET_HashCode)); } GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; process_pending_messages (handle); return h; } /** * Stop monitoring. * * @param handle The handle to the monitor request returned by monitor_start. * * On return get_handle will no longer be valid, caller must not use again!!! */ void GNUNET_DHT_monitor_stop (struct GNUNET_DHT_MonitorHandle *handle) { struct GNUNET_DHT_MonitorStartStopMessage *m; struct PendingMessage *pending; GNUNET_CONTAINER_DLL_remove (handle->dht_handle->monitor_head, handle->dht_handle->monitor_tail, handle); pending = GNUNET_malloc (sizeof (struct GNUNET_DHT_MonitorStartStopMessage) + sizeof (struct PendingMessage)); m = (struct GNUNET_DHT_MonitorStartStopMessage *) &pending[1]; pending->msg = &m->header; pending->handle = handle->dht_handle; pending->free_on_send = GNUNET_YES; m->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_MONITOR_STOP); m->header.size = htons (sizeof (struct GNUNET_DHT_MonitorStartStopMessage)); m->type = htonl(handle->type); m->get = htons (NULL != handle->get_cb); m->get_resp = htons(NULL != handle->get_resp_cb); m->put = htons (NULL != handle->put_cb); if (NULL != handle->key) { m->filter_key = htons (1); m->key = *handle->key; } GNUNET_CONTAINER_DLL_insert (handle->dht_handle->pending_head, handle->dht_handle->pending_tail, pending); pending->in_pending_queue = GNUNET_YES; process_pending_messages (handle->dht_handle); GNUNET_free_non_null (handle->key); GNUNET_free (handle); } /* end of dht_api.c */ gnunet-0.10.1/src/dht/gnunet-service-dht_neighbours.c0000644000175000017500000021345012316473376017505 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-dht_neighbours.c * @brief GNUnet DHT service's bucket and neighbour management code * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_block_lib.h" #include "gnunet_hello_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_nse_service.h" #include "gnunet_ats_service.h" #include "gnunet_core_service.h" #include "gnunet_datacache_lib.h" #include "gnunet_transport_service.h" #include "gnunet_hello_lib.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" #include "gnunet-service-dht.h" #include "gnunet-service-dht_clients.h" #include "gnunet-service-dht_datacache.h" #include "gnunet-service-dht_hello.h" #include "gnunet-service-dht_neighbours.h" #include "gnunet-service-dht_nse.h" #include "gnunet-service-dht_routing.h" #include #include "dht.h" #define LOG_TRAFFIC(kind,...) GNUNET_log_from (kind, "dht-traffic",__VA_ARGS__) /** * How many buckets will we allow total. */ #define MAX_BUCKETS sizeof (struct GNUNET_HashCode) * 8 /** * What is the maximum number of peers in a given bucket. */ #define DEFAULT_BUCKET_SIZE 8 /** * Desired replication level for FIND PEER requests */ #define FIND_PEER_REPLICATION_LEVEL 4 /** * Maximum allowed replication level for all requests. */ #define MAXIMUM_REPLICATION_LEVEL 16 /** * Maximum allowed number of pending messages per peer. */ #define MAXIMUM_PENDING_PER_PEER 64 /** * How often to update our preference levels for peers in our routing tables. */ #define DHT_DEFAULT_PREFERENCE_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2) /** * How long at least to wait before sending another find peer request. */ #define DHT_MINIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) /** * How long at most to wait before sending another find peer request. */ #define DHT_MAXIMUM_FIND_PEER_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 10) /** * How long at most to wait for transmission of a GET request to another peer? */ #define GET_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2) /** * Hello address expiration */ extern struct GNUNET_TIME_Relative hello_expiration; GNUNET_NETWORK_STRUCT_BEGIN /** * P2P PUT message */ struct PeerPutMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_PUT */ struct GNUNET_MessageHeader header; /** * Processing options */ uint32_t options GNUNET_PACKED; /** * Content type. */ uint32_t type GNUNET_PACKED; /** * Hop count */ uint32_t hop_count GNUNET_PACKED; /** * Replication level for this message */ uint32_t desired_replication_level GNUNET_PACKED; /** * Length of the PUT path that follows (if tracked). */ uint32_t put_path_length GNUNET_PACKED; /** * When does the content expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * Bloomfilter (for peer identities) to stop circular routes */ char bloomfilter[DHT_BLOOM_SIZE]; /** * The key we are storing under. */ struct GNUNET_HashCode key; /* put path (if tracked) */ /* Payload */ }; /** * P2P Result message */ struct PeerResultMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT */ struct GNUNET_MessageHeader header; /** * Content type. */ uint32_t type GNUNET_PACKED; /** * Length of the PUT path that follows (if tracked). */ uint32_t put_path_length GNUNET_PACKED; /** * Length of the GET path that follows (if tracked). */ uint32_t get_path_length GNUNET_PACKED; /** * When does the content expire? */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * The key of the corresponding GET request. */ struct GNUNET_HashCode key; /* put path (if tracked) */ /* get path (if tracked) */ /* Payload */ }; /** * P2P GET message */ struct PeerGetMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DHT_P2P_GET */ struct GNUNET_MessageHeader header; /** * Processing options */ uint32_t options GNUNET_PACKED; /** * Desired content type. */ uint32_t type GNUNET_PACKED; /** * Hop count */ uint32_t hop_count GNUNET_PACKED; /** * Desired replication level for this request. */ uint32_t desired_replication_level GNUNET_PACKED; /** * Size of the extended query. */ uint32_t xquery_size; /** * Bloomfilter mutator. */ uint32_t bf_mutator; /** * Bloomfilter (for peer identities) to stop circular routes */ char bloomfilter[DHT_BLOOM_SIZE]; /** * The key we are looking for. */ struct GNUNET_HashCode key; /* xquery */ /* result bloomfilter */ }; GNUNET_NETWORK_STRUCT_END /** * Linked list of messages to send to a particular other peer. */ struct P2PPendingMessage { /** * Pointer to next item in the list */ struct P2PPendingMessage *next; /** * Pointer to previous item in the list */ struct P2PPendingMessage *prev; /** * Message importance level. FIXME: used? useful? */ unsigned int importance; /** * When does this message time out? */ struct GNUNET_TIME_Absolute timeout; /** * Actual message to be sent, allocated at the end of the struct: * // msg = (cast) &pm[1]; * // memcpy (&pm[1], data, len); */ const struct GNUNET_MessageHeader *msg; }; /** * Entry for a peer in a bucket. */ struct PeerInfo { /** * Next peer entry (DLL) */ struct PeerInfo *next; /** * Prev peer entry (DLL) */ struct PeerInfo *prev; /** * Count of outstanding messages for peer. */ unsigned int pending_count; /** * Head of pending messages to be sent to this peer. */ struct P2PPendingMessage *head; /** * Tail of pending messages to be sent to this peer. */ struct P2PPendingMessage *tail; /** * Core handle for sending messages to this peer. */ struct GNUNET_CORE_TransmitHandle *th; /** * Task for scheduling preference updates */ GNUNET_SCHEDULER_TaskIdentifier preference_task; /** * What is the identity of the peer? */ struct GNUNET_PeerIdentity id; #if 0 /** * What is the average latency for replies received? */ struct GNUNET_TIME_Relative latency; /** * Transport level distance to peer. */ unsigned int distance; #endif }; /** * Peers are grouped into buckets. */ struct PeerBucket { /** * Head of DLL */ struct PeerInfo *head; /** * Tail of DLL */ struct PeerInfo *tail; /** * Number of peers in the bucket. */ unsigned int peers_size; }; /** * Do we cache all results that we are routing in the local datacache? */ static int cache_results; /** * Should routing details be logged to stderr (for debugging)? */ static int log_route_details_stderr; /** * The lowest currently used bucket, initially 0 (for 0-bits matching bucket). */ static unsigned int closest_bucket; /** * How many peers have we added since we sent out our last * find peer request? */ static unsigned int newly_found_peers; /** * Option for testing that disables the 'connect' function of the DHT. */ static int disable_try_connect; /** * The buckets. Array of size MAX_BUCKET_SIZE. Offset 0 means 0 bits matching. */ static struct PeerBucket k_buckets[MAX_BUCKETS]; /** * Hash map of all known peers, for easy removal from k_buckets on disconnect. */ static struct GNUNET_CONTAINER_MultiPeerMap *all_known_peers; /** * Maximum size for each bucket. */ static unsigned int bucket_size = DEFAULT_BUCKET_SIZE; /** * Task that sends FIND PEER requests. */ static GNUNET_SCHEDULER_TaskIdentifier find_peer_task; /** * Identity of this peer. */ static struct GNUNET_PeerIdentity my_identity; /** * Hash of the identity of this peer. */ static struct GNUNET_HashCode my_identity_hash; /** * Handle to CORE. */ static struct GNUNET_CORE_Handle *core_api; /** * Handle to ATS. */ static struct GNUNET_ATS_PerformanceHandle *atsAPI; /** * Find the optimal bucket for this key. * * @param hc the hashcode to compare our identity to * @return the proper bucket index, or GNUNET_SYSERR * on error (same hashcode) */ static int find_bucket (const struct GNUNET_HashCode *hc) { unsigned int bits; bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, hc); if (bits == MAX_BUCKETS) { /* How can all bits match? Got my own ID? */ GNUNET_break (0); return GNUNET_SYSERR; } return MAX_BUCKETS - bits - 1; } /** * Let GNUnet core know that we like the given peer. * * @param cls the `struct PeerInfo` of the peer * @param tc scheduler context. */ static void update_core_preference (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerInfo *peer = cls; uint64_t preference; unsigned int matching; int bucket; struct GNUNET_HashCode phash; peer->preference_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; GNUNET_CRYPTO_hash (&peer->id, sizeof (struct GNUNET_PeerIdentity), &phash); matching = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, &phash); if (matching >= 64) matching = 63; bucket = find_bucket (&phash); if (bucket == GNUNET_SYSERR) preference = 0; else { GNUNET_assert (k_buckets[bucket].peers_size != 0); preference = (1LL << matching) / k_buckets[bucket].peers_size; } if (preference == 0) { peer->preference_task = GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL, &update_core_preference, peer); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Preference updates given to core"), 1, GNUNET_NO); GNUNET_ATS_performance_change_preference (atsAPI, &peer->id, GNUNET_ATS_PREFERENCE_BANDWIDTH, (double) preference, GNUNET_ATS_PREFERENCE_END); peer->preference_task = GNUNET_SCHEDULER_add_delayed (DHT_DEFAULT_PREFERENCE_INTERVAL, &update_core_preference, peer); } /** * Closure for 'add_known_to_bloom'. */ struct BloomConstructorContext { /** * Bloom filter under construction. */ struct GNUNET_CONTAINER_BloomFilter *bloom; /** * Mutator to use. */ uint32_t bf_mutator; }; /** * Add each of the peers we already know to the bloom filter of * the request so that we don't get duplicate HELLOs. * * @param cls the 'struct BloomConstructorContext'. * @param key peer identity to add to the bloom filter * @param value value the peer information (unused) * @return #GNUNET_YES (we should continue to iterate) */ static int add_known_to_bloom (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct BloomConstructorContext *ctx = cls; struct GNUNET_HashCode key_hash; struct GNUNET_HashCode mh; GNUNET_CRYPTO_hash (key, sizeof (struct GNUNET_PeerIdentity), &key_hash); GNUNET_BLOCK_mingle_hash (&key_hash, ctx->bf_mutator, &mh); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding known peer (%s) to bloomfilter for FIND PEER with mutation %u\n", GNUNET_i2s (key), ctx->bf_mutator); GNUNET_CONTAINER_bloomfilter_add (ctx->bloom, &mh); return GNUNET_YES; } /** * Task to send a find peer message for our own peer identifier * so that we can find the closest peers in the network to ourselves * and attempt to connect to them. * * @param cls closure for this task * @param tc the context under which the task is running */ static void send_find_peer_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Relative next_send_time; struct BloomConstructorContext bcc; struct GNUNET_CONTAINER_BloomFilter *peer_bf; find_peer_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; if (newly_found_peers > bucket_size) { /* If we are finding many peers already, no need to send out our request right now! */ find_peer_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &send_find_peer_message, NULL); newly_found_peers = 0; return; } bcc.bf_mutator = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); bcc.bloom = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); GNUNET_CONTAINER_multipeermap_iterate (all_known_peers, &add_known_to_bloom, &bcc); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# FIND PEER messages initiated"), 1, GNUNET_NO); peer_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); // FIXME: pass priority!? GDS_NEIGHBOURS_handle_get (GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_DHT_RO_FIND_PEER, FIND_PEER_REPLICATION_LEVEL, 0, &my_identity_hash, NULL, 0, bcc.bloom, bcc.bf_mutator, peer_bf); GNUNET_CONTAINER_bloomfilter_free (peer_bf); GNUNET_CONTAINER_bloomfilter_free (bcc.bloom); /* schedule next round */ next_send_time.rel_value_us = DHT_MINIMUM_FIND_PEER_INTERVAL.rel_value_us + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, DHT_MAXIMUM_FIND_PEER_INTERVAL.rel_value_us / (newly_found_peers + 1)); newly_found_peers = 0; find_peer_task = GNUNET_SCHEDULER_add_delayed (next_send_time, &send_find_peer_message, NULL); } /** * Method called whenever a peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerInfo *ret; struct GNUNET_HashCode phash; int peer_bucket; /* Check for connect to self message */ if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to %s\n", GNUNET_i2s (peer)); if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (all_known_peers, peer)) { GNUNET_break (0); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), 1, GNUNET_NO); GNUNET_CRYPTO_hash (peer, sizeof (struct GNUNET_PeerIdentity), &phash); peer_bucket = find_bucket (&phash); GNUNET_assert ((peer_bucket >= 0) && (peer_bucket < MAX_BUCKETS)); ret = GNUNET_new (struct PeerInfo); #if 0 ret->latency = latency; ret->distance = distance; #endif ret->id = *peer; GNUNET_CONTAINER_DLL_insert_tail (k_buckets[peer_bucket].head, k_buckets[peer_bucket].tail, ret); k_buckets[peer_bucket].peers_size++; closest_bucket = GNUNET_MAX (closest_bucket, peer_bucket); if ((peer_bucket > 0) && (k_buckets[peer_bucket].peers_size <= bucket_size)) { ret->preference_task = GNUNET_SCHEDULER_add_now (&update_core_preference, ret); newly_found_peers++; } GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (all_known_peers, peer, ret, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); if (1 == GNUNET_CONTAINER_multipeermap_size (all_known_peers) && (GNUNET_YES != disable_try_connect)) { /* got a first connection, good time to start with FIND PEER requests... */ find_peer_task = GNUNET_SCHEDULER_add_now (&send_find_peer_message, NULL); } } /** * Method called whenever a peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerInfo *to_remove; int current_bucket; struct P2PPendingMessage *pos; unsigned int discarded; struct GNUNET_HashCode phash; /* Check for disconnect from self message */ if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnected %s\n", GNUNET_i2s (peer)); to_remove = GNUNET_CONTAINER_multipeermap_get (all_known_peers, peer); if (NULL == to_remove) { GNUNET_break (0); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# peers connected"), -1, GNUNET_NO); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (all_known_peers, peer, to_remove)); if (GNUNET_SCHEDULER_NO_TASK != to_remove->preference_task) { GNUNET_SCHEDULER_cancel (to_remove->preference_task); to_remove->preference_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CRYPTO_hash (peer, sizeof (struct GNUNET_PeerIdentity), &phash); current_bucket = find_bucket (&phash); GNUNET_assert (current_bucket >= 0); GNUNET_CONTAINER_DLL_remove (k_buckets[current_bucket].head, k_buckets[current_bucket].tail, to_remove); GNUNET_assert (k_buckets[current_bucket].peers_size > 0); k_buckets[current_bucket].peers_size--; while ((closest_bucket > 0) && (k_buckets[closest_bucket].peers_size == 0)) closest_bucket--; if (to_remove->th != NULL) { GNUNET_CORE_notify_transmit_ready_cancel (to_remove->th); to_remove->th = NULL; } discarded = 0; while (NULL != (pos = to_remove->head)) { GNUNET_CONTAINER_DLL_remove (to_remove->head, to_remove->tail, pos); discarded++; GNUNET_free (pos); } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Queued messages discarded (peer disconnected)"), discarded, GNUNET_NO); GNUNET_free (to_remove); } /** * Called when core is ready to send a message we asked for * out to the destination. * * @param cls the 'struct PeerInfo' of the target peer * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t core_transmit_notify (void *cls, size_t size, void *buf) { struct PeerInfo *peer = cls; char *cbuf = buf; struct P2PPendingMessage *pending; size_t off; size_t msize; peer->th = NULL; while ((NULL != (pending = peer->head)) && (0 == GNUNET_TIME_absolute_get_remaining (pending->timeout).rel_value_us)) { peer->pending_count--; GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending); GNUNET_free (pending); } if (NULL == pending) { /* no messages pending */ return 0; } if (NULL == buf) { peer->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_absolute_get_remaining (pending->timeout), &peer->id, ntohs (pending->msg->size), &core_transmit_notify, peer); GNUNET_break (NULL != peer->th); return 0; } off = 0; while ((NULL != (pending = peer->head)) && (size - off >= (msize = ntohs (pending->msg->size)))) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Bytes transmitted to other peers"), msize, GNUNET_NO); memcpy (&cbuf[off], pending->msg, msize); off += msize; peer->pending_count--; GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, pending); GNUNET_free (pending); } if (peer->head != NULL) { peer->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_absolute_get_remaining (pending->timeout), &peer->id, msize, &core_transmit_notify, peer); GNUNET_break (NULL != peer->th); } return off; } /** * Transmit all messages in the peer's message queue. * * @param peer message queue to process */ static void process_peer_queue (struct PeerInfo *peer) { struct P2PPendingMessage *pending; if (NULL == (pending = peer->head)) return; if (NULL != peer->th) return; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Bytes of bandwidth requested from core"), ntohs (pending->msg->size), GNUNET_NO); peer->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_absolute_get_remaining (pending->timeout), &peer->id, ntohs (pending->msg->size), &core_transmit_notify, peer); GNUNET_break (NULL != peer->th); } /** * To how many peers should we (on average) forward the request to * obtain the desired target_replication count (on average). * * @param hop_count number of hops the message has traversed * @param target_replication the number of total paths desired * @return Some number of peers to forward the message to */ static unsigned int get_forward_count (uint32_t hop_count, uint32_t target_replication) { uint32_t random_value; uint32_t forward_count; float target_value; if (hop_count > GDS_NSE_get () * 4.0) { /* forcefully terminate */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# requests TTL-dropped"), 1, GNUNET_NO); return 0; } if (hop_count > GDS_NSE_get () * 2.0) { /* Once we have reached our ideal number of hops, only forward to 1 peer */ return 1; } /* bound by system-wide maximum */ target_replication = GNUNET_MIN (MAXIMUM_REPLICATION_LEVEL, target_replication); target_value = 1 + (target_replication - 1.0) / (GDS_NSE_get () + ((float) (target_replication - 1.0) * hop_count)); /* Set forward count to floor of target_value */ forward_count = (uint32_t) target_value; /* Subtract forward_count (floor) from target_value (yields value between 0 and 1) */ target_value = target_value - forward_count; random_value = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); if (random_value < (target_value * UINT32_MAX)) forward_count++; return forward_count; } /** * Compute the distance between have and target as a 32-bit value. * Differences in the lower bits must count stronger than differences * in the higher bits. * * @param target * @param have * @return 0 if have==target, otherwise a number * that is larger as the distance between * the two hash codes increases */ static unsigned int get_distance (const struct GNUNET_HashCode *target, const struct GNUNET_HashCode *have) { unsigned int bucket; unsigned int msb; unsigned int lsb; unsigned int i; /* We have to represent the distance between two 2^9 (=512)-bit * numbers as a 2^5 (=32)-bit number with "0" being used for the * two numbers being identical; furthermore, we need to * guarantee that a difference in the number of matching * bits is always represented in the result. * * We use 2^32/2^9 numerical values to distinguish between * hash codes that have the same LSB bit distance and * use the highest 2^9 bits of the result to signify the * number of (mis)matching LSB bits; if we have 0 matching * and hence 512 mismatching LSB bits we return -1 (since * 512 itself cannot be represented with 9 bits) */ /* first, calculate the most significant 9 bits of our * result, aka the number of LSBs */ bucket = GNUNET_CRYPTO_hash_matching_bits (target, have); /* bucket is now a value between 0 and 512 */ if (bucket == 512) return 0; /* perfect match */ if (bucket == 0) return (unsigned int) -1; /* LSB differs; use max (if we did the bit-shifting * below, we'd end up with max+1 (overflow)) */ /* calculate the most significant bits of the final result */ msb = (512 - bucket) << (32 - 9); /* calculate the 32-9 least significant bits of the final result by * looking at the differences in the 32-9 bits following the * mismatching bit at 'bucket' */ lsb = 0; for (i = bucket + 1; (i < sizeof (struct GNUNET_HashCode) * 8) && (i < bucket + 1 + 32 - 9); i++) { if (GNUNET_CRYPTO_hash_get_bit (target, i) != GNUNET_CRYPTO_hash_get_bit (have, i)) lsb |= (1 << (bucket + 32 - 9 - i)); /* first bit set will be 10, * last bit set will be 31 -- if * i does not reach 512 first... */ } return msb | lsb; } /** * Check whether my identity is closer than any known peers. If a * non-null bloomfilter is given, check if this is the closest peer * that hasn't already been routed to. * * @param key hash code to check closeness to * @param bloom bloomfilter, exclude these entries from the decision * @return #GNUNET_YES if node location is closest, * #GNUNET_NO otherwise. */ static int am_closest_peer (const struct GNUNET_HashCode *key, const struct GNUNET_CONTAINER_BloomFilter *bloom) { int bits; int other_bits; int bucket_num; int count; struct PeerInfo *pos; struct GNUNET_HashCode phash; if (0 == memcmp (&my_identity_hash, key, sizeof (struct GNUNET_HashCode))) return GNUNET_YES; bucket_num = find_bucket (key); GNUNET_assert (bucket_num >= 0); bits = GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, key); pos = k_buckets[bucket_num].head; count = 0; while ((pos != NULL) && (count < bucket_size)) { GNUNET_CRYPTO_hash (&pos->id, sizeof (struct GNUNET_PeerIdentity), &phash); if ((bloom != NULL) && (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bloom, &phash))) { pos = pos->next; continue; /* Skip already checked entries */ } other_bits = GNUNET_CRYPTO_hash_matching_bits (&phash, key); if (other_bits > bits) return GNUNET_NO; if (other_bits == bits) /* We match the same number of bits */ return GNUNET_YES; pos = pos->next; } /* No peers closer, we are the closest! */ return GNUNET_YES; } /** * Select a peer from the routing table that would be a good routing * destination for sending a message for "key". The resulting peer * must not be in the set of blocked peers.

* * Note that we should not ALWAYS select the closest peer to the * target, peers further away from the target should be chosen with * exponentially declining probability. * * FIXME: double-check that this is fine * * * @param key the key we are selecting a peer to route to * @param bloom a bloomfilter containing entries this request has seen already * @param hops how many hops has this message traversed thus far * @return Peer to route to, or NULL on error */ static struct PeerInfo * select_peer (const struct GNUNET_HashCode * key, const struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hops) { unsigned int bc; unsigned int count; unsigned int selected; struct PeerInfo *pos; unsigned int dist; unsigned int smallest_distance; struct PeerInfo *chosen; struct GNUNET_HashCode phash; if (hops >= GDS_NSE_get ()) { /* greedy selection (closest peer that is not in bloomfilter) */ smallest_distance = UINT_MAX; chosen = NULL; for (bc = 0; bc <= closest_bucket; bc++) { pos = k_buckets[bc].head; count = 0; while ((pos != NULL) && (count < bucket_size)) { GNUNET_CRYPTO_hash (&pos->id, sizeof (struct GNUNET_PeerIdentity), &phash); if ((bloom == NULL) || (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &phash))) { dist = get_distance (key, &phash); if (dist < smallest_distance) { chosen = pos; smallest_distance = dist; } } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Excluded peer `%s' due to BF match in greedy routing for %s\n", GNUNET_i2s (&pos->id), GNUNET_h2s (key)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Peers excluded from routing due to Bloomfilter"), 1, GNUNET_NO); dist = get_distance (key, &phash); if (dist < smallest_distance) { chosen = NULL; smallest_distance = dist; } } count++; pos = pos->next; } } if (NULL == chosen) GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Peer selection failed"), 1, GNUNET_NO); return chosen; } /* select "random" peer */ /* count number of peers that are available and not filtered */ count = 0; for (bc = 0; bc <= closest_bucket; bc++) { pos = k_buckets[bc].head; while ((pos != NULL) && (count < bucket_size)) { GNUNET_CRYPTO_hash (&pos->id, sizeof (struct GNUNET_PeerIdentity), &phash); if ((bloom != NULL) && (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bloom, &phash))) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Peers excluded from routing due to Bloomfilter"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Excluded peer `%s' due to BF match in random routing for %s\n", GNUNET_i2s (&pos->id), GNUNET_h2s (key)); pos = pos->next; continue; /* Ignore bloomfiltered peers */ } count++; pos = pos->next; } } if (0 == count) /* No peers to select from! */ { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# Peer selection failed"), 1, GNUNET_NO); return NULL; } /* Now actually choose a peer */ selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, count); count = 0; for (bc = 0; bc <= closest_bucket; bc++) { for (pos = k_buckets[bc].head; ((pos != NULL) && (count < bucket_size)); pos = pos->next) { GNUNET_CRYPTO_hash (&pos->id, sizeof (struct GNUNET_PeerIdentity), &phash); if ((bloom != NULL) && (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bloom, &phash))) { continue; /* Ignore bloomfiltered peers */ } if (0 == selected--) return pos; } } GNUNET_break (0); return NULL; } /** * Compute the set of peers that the given request should be * forwarded to. * * @param key routing key * @param bloom bloom filter excluding peers as targets, all selected * peers will be added to the bloom filter * @param hop_count number of hops the request has traversed so far * @param target_replication desired number of replicas * @param targets where to store an array of target peers (to be * free'd by the caller) * @return number of peers returned in 'targets'. */ static unsigned int get_target_peers (const struct GNUNET_HashCode *key, struct GNUNET_CONTAINER_BloomFilter *bloom, uint32_t hop_count, uint32_t target_replication, struct PeerInfo ***targets) { unsigned int ret; unsigned int off; struct PeerInfo **rtargets; struct PeerInfo *nxt; struct GNUNET_HashCode nhash; GNUNET_assert (NULL != bloom); ret = get_forward_count (hop_count, target_replication); if (0 == ret) { *targets = NULL; return 0; } rtargets = GNUNET_malloc (sizeof (struct PeerInfo *) * ret); for (off = 0; off < ret; off++) { nxt = select_peer (key, bloom, hop_count); if (NULL == nxt) break; rtargets[off] = nxt; GNUNET_CRYPTO_hash (&nxt->id, sizeof (struct GNUNET_PeerIdentity), &nhash); GNUNET_break (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (bloom, &nhash)); GNUNET_CONTAINER_bloomfilter_add (bloom, &nhash); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Selected %u/%u peers at hop %u for %s (target was %u)\n", off, GNUNET_CONTAINER_multipeermap_size (all_known_peers), (unsigned int) hop_count, GNUNET_h2s (key), ret); if (0 == off) { GNUNET_free (rtargets); *targets = NULL; return 0; } *targets = rtargets; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarding query `%s' to %u peers (goal was %u peers)\n", GNUNET_h2s (key), off, ret); return off; } /** * Perform a PUT operation. Forwards the given request to other * peers. Does not store the data locally. Does not give the * data to local clients. May do nothing if this is the only * peer in the network (or if we are the closest peer in the * network). * * @param type type of the block * @param options routing options * @param desired_replication_level desired replication count * @param expiration_time when does the content expire * @param hop_count how many hops has this message traversed so far * @param bf Bloom filter of peers this PUT has already traversed * @param key key for the content * @param put_path_length number of entries in @a put_path * @param put_path peers this request has traversed so far (if tracked) * @param data payload to store * @param data_size number of bytes in @a data */ void GDS_NEIGHBOURS_handle_put (enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint32_t desired_replication_level, struct GNUNET_TIME_Absolute expiration_time, uint32_t hop_count, struct GNUNET_CONTAINER_BloomFilter *bf, const struct GNUNET_HashCode *key, unsigned int put_path_length, struct GNUNET_PeerIdentity *put_path, const void *data, size_t data_size) { unsigned int target_count; unsigned int i; struct PeerInfo **targets; struct PeerInfo *target; struct P2PPendingMessage *pending; size_t msize; struct PeerPutMessage *ppm; struct GNUNET_PeerIdentity *pp; struct GNUNET_HashCode thash; GNUNET_assert (NULL != bf); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding myself (%s) to PUT bloomfilter for %s\n", GNUNET_i2s (&my_identity), GNUNET_h2s (key)); GNUNET_CONTAINER_bloomfilter_add (bf, &my_identity_hash); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# PUT requests routed"), 1, GNUNET_NO); target_count = get_target_peers (key, bf, hop_count, desired_replication_level, &targets); if (0 == target_count) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing PUT for %s terminates after %u hops at %s\n", GNUNET_h2s (key), (unsigned int) hop_count, GNUNET_i2s (&my_identity)); return; } msize = put_path_length * sizeof (struct GNUNET_PeerIdentity) + data_size + sizeof (struct PeerPutMessage); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { put_path_length = 0; msize = data_size + sizeof (struct PeerPutMessage); } if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); GNUNET_free (targets); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# PUT messages queued for transmission"), target_count, GNUNET_NO); for (i = 0; i < target_count; i++) { target = targets[i]; if (target->pending_count >= MAXIMUM_PENDING_PER_PEER) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); continue; /* skip */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing PUT for %s after %u hops to %s\n", GNUNET_h2s (key), (unsigned int) hop_count, GNUNET_i2s (&target->id)); pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ pending->timeout = expiration_time; ppm = (struct PeerPutMessage *) &pending[1]; pending->msg = &ppm->header; ppm->header.size = htons (msize); ppm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_PUT); ppm->options = htonl (options); ppm->type = htonl (type); ppm->hop_count = htonl (hop_count + 1); ppm->desired_replication_level = htonl (desired_replication_level); ppm->put_path_length = htonl (put_path_length); ppm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); GNUNET_CRYPTO_hash (&target->id, sizeof (struct GNUNET_PeerIdentity), &thash); GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bf, &thash)); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_bloomfilter_get_raw_data (bf, ppm->bloomfilter, DHT_BLOOM_SIZE)); ppm->key = *key; pp = (struct GNUNET_PeerIdentity *) &ppm[1]; memcpy (pp, put_path, sizeof (struct GNUNET_PeerIdentity) * put_path_length); memcpy (&pp[put_path_length], data, data_size); GNUNET_CONTAINER_DLL_insert_tail (target->head, target->tail, pending); target->pending_count++; process_peer_queue (target); } GNUNET_free (targets); } /** * Perform a GET operation. Forwards the given request to other * peers. Does not lookup the key locally. May do nothing if this is * the only peer in the network (or if we are the closest peer in the * network). * * @param type type of the block * @param options routing options * @param desired_replication_level desired replication count * @param hop_count how many hops did this request traverse so far? * @param key key for the content * @param xquery extended query * @param xquery_size number of bytes in @a xquery * @param reply_bf bloomfilter to filter duplicates * @param reply_bf_mutator mutator for @a reply_bf * @param peer_bf filter for peers not to select (again) */ void GDS_NEIGHBOURS_handle_get (enum GNUNET_BLOCK_Type type, enum GNUNET_DHT_RouteOption options, uint32_t desired_replication_level, uint32_t hop_count, const struct GNUNET_HashCode * key, const void *xquery, size_t xquery_size, const struct GNUNET_CONTAINER_BloomFilter *reply_bf, uint32_t reply_bf_mutator, struct GNUNET_CONTAINER_BloomFilter *peer_bf) { unsigned int target_count; unsigned int i; struct PeerInfo **targets; struct PeerInfo *target; struct P2PPendingMessage *pending; size_t msize; struct PeerGetMessage *pgm; char *xq; size_t reply_bf_size; struct GNUNET_HashCode thash; GNUNET_assert (NULL != peer_bf); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET requests routed"), 1, GNUNET_NO); target_count = get_target_peers (key, peer_bf, hop_count, desired_replication_level, &targets); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding myself (%s) to GET bloomfilter for %s\n", GNUNET_i2s (&my_identity), GNUNET_h2s (key)); GNUNET_CONTAINER_bloomfilter_add (peer_bf, &my_identity_hash); if (0 == target_count) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing GET for %s terminates after %u hops at %s\n", GNUNET_h2s (key), (unsigned int) hop_count, GNUNET_i2s (&my_identity)); return; } reply_bf_size = GNUNET_CONTAINER_bloomfilter_get_size (reply_bf); msize = xquery_size + sizeof (struct PeerGetMessage) + reply_bf_size; if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); GNUNET_free (targets); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# GET messages queued for transmission"), target_count, GNUNET_NO); /* forward request */ for (i = 0; i < target_count; i++) { target = targets[i]; if (target->pending_count >= MAXIMUM_PENDING_PER_PEER) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); continue; /* skip */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing GET for %s after %u hops to %s\n", GNUNET_h2s (key), (unsigned int) hop_count, GNUNET_i2s (&target->id)); pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ pending->timeout = GNUNET_TIME_relative_to_absolute (GET_TIMEOUT); pgm = (struct PeerGetMessage *) &pending[1]; pending->msg = &pgm->header; pgm->header.size = htons (msize); pgm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_GET); pgm->options = htonl (options); pgm->type = htonl (type); pgm->hop_count = htonl (hop_count + 1); pgm->desired_replication_level = htonl (desired_replication_level); pgm->xquery_size = htonl (xquery_size); pgm->bf_mutator = reply_bf_mutator; GNUNET_CRYPTO_hash (&target->id, sizeof (struct GNUNET_PeerIdentity), &thash); GNUNET_break (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (peer_bf, &thash)); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_bloomfilter_get_raw_data (peer_bf, pgm->bloomfilter, DHT_BLOOM_SIZE)); pgm->key = *key; xq = (char *) &pgm[1]; memcpy (xq, xquery, xquery_size); if (NULL != reply_bf) GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_bloomfilter_get_raw_data (reply_bf, &xq [xquery_size], reply_bf_size)); GNUNET_CONTAINER_DLL_insert_tail (target->head, target->tail, pending); target->pending_count++; process_peer_queue (target); } GNUNET_free (targets); } /** * Handle a reply (route to origin). Only forwards the reply back to * the given peer. Does not do local caching or forwarding to local * clients. * * @param target neighbour that should receive the block (if still connected) * @param type type of the block * @param expiration_time when does the content expire * @param key key for the content * @param put_path_length number of entries in @a put_path * @param put_path peers the original PUT traversed (if tracked) * @param get_path_length number of entries in @a get_path * @param get_path peers this reply has traversed so far (if tracked) * @param data payload of the reply * @param data_size number of bytes in @a data */ void GDS_NEIGHBOURS_handle_reply (const struct GNUNET_PeerIdentity *target, enum GNUNET_BLOCK_Type type, struct GNUNET_TIME_Absolute expiration_time, const struct GNUNET_HashCode * key, unsigned int put_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *get_path, const void *data, size_t data_size) { struct PeerInfo *pi; struct P2PPendingMessage *pending; size_t msize; struct PeerResultMessage *prm; struct GNUNET_PeerIdentity *paths; msize = data_size + sizeof (struct PeerResultMessage) + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity); if ((msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (get_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || (put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || (data_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)) { GNUNET_break (0); return; } pi = GNUNET_CONTAINER_multipeermap_get (all_known_peers, target); if (NULL == pi) { /* peer disconnected in the meantime, drop reply */ return; } if (pi->pending_count >= MAXIMUM_PENDING_PER_PEER) { /* skip */ GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P messages dropped due to full queue"), 1, GNUNET_NO); return; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# RESULT messages queued for transmission"), 1, GNUNET_NO); pending = GNUNET_malloc (sizeof (struct P2PPendingMessage) + msize); pending->importance = 0; /* FIXME */ pending->timeout = expiration_time; prm = (struct PeerResultMessage *) &pending[1]; pending->msg = &prm->header; prm->header.size = htons (msize); prm->header.type = htons (GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT); prm->type = htonl (type); prm->put_path_length = htonl (put_path_length); prm->get_path_length = htonl (get_path_length); prm->expiration_time = GNUNET_TIME_absolute_hton (expiration_time); prm->key = *key; paths = (struct GNUNET_PeerIdentity *) &prm[1]; memcpy (paths, put_path, put_path_length * sizeof (struct GNUNET_PeerIdentity)); memcpy (&paths[put_path_length], get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); memcpy (&paths[put_path_length + get_path_length], data, data_size); GNUNET_CONTAINER_DLL_insert (pi->head, pi->tail, pending); pi->pending_count++; process_peer_queue (pi); } /** * To be called on core init/fail. * * @param cls service closure * @param identity the public identity of this peer */ static void core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { my_identity = *identity; GNUNET_CRYPTO_hash (identity, sizeof (struct GNUNET_PeerIdentity), &my_identity_hash); } /** * Core handler for p2p put requests. * * @param cls closure * @param peer sender of the request * @param message message * @param peer peer identity this notification is about * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handle_dht_p2p_put (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { const struct PeerPutMessage *put; const struct GNUNET_PeerIdentity *put_path; const void *payload; uint32_t putlen; uint16_t msize; size_t payload_size; enum GNUNET_DHT_RouteOption options; struct GNUNET_CONTAINER_BloomFilter *bf; struct GNUNET_HashCode test_key; struct GNUNET_HashCode phash; msize = ntohs (message->size); if (msize < sizeof (struct PeerPutMessage)) { GNUNET_break_op (0); return GNUNET_YES; } put = (const struct PeerPutMessage *) message; putlen = ntohl (put->put_path_length); if ((msize < sizeof (struct PeerPutMessage) + putlen * sizeof (struct GNUNET_PeerIdentity)) || (putlen > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P PUT requests received"), 1, GNUNET_NO); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P PUT bytes received"), msize, GNUNET_NO); put_path = (const struct GNUNET_PeerIdentity *) &put[1]; payload = &put_path[putlen]; options = ntohl (put->options); payload_size = msize - (sizeof (struct PeerPutMessage) + putlen * sizeof (struct GNUNET_PeerIdentity)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PUT for `%s' from %s\n", GNUNET_h2s (&put->key), GNUNET_i2s (peer)); GNUNET_CRYPTO_hash (peer, sizeof (struct GNUNET_PeerIdentity), &phash); if (GNUNET_YES == log_route_details_stderr) { char *tmp; tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N PUT %s: %s->%s (%u, %u=>%u)\n", GNUNET_h2s (&put->key), GNUNET_i2s (peer), tmp, ntohl(put->hop_count), GNUNET_CRYPTO_hash_matching_bits (&phash, &put->key), GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, &put->key) ); GNUNET_free (tmp); } switch (GNUNET_BLOCK_get_key (GDS_block_context, ntohl (put->type), payload, payload_size, &test_key)) { case GNUNET_YES: if (0 != memcmp (&test_key, &put->key, sizeof (struct GNUNET_HashCode))) { char *put_s = GNUNET_strdup (GNUNET_h2s_full (&put->key)); GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "PUT with key `%s' for block with key %s\n", put_s, GNUNET_h2s_full (&test_key)); GNUNET_free (put_s); return GNUNET_YES; } break; case GNUNET_NO: GNUNET_break_op (0); return GNUNET_YES; case GNUNET_SYSERR: /* cannot verify, good luck */ break; } if (ntohl (put->type) == GNUNET_BLOCK_TYPE_REGEX) /* FIXME: do for all tpyes */ { switch (GNUNET_BLOCK_evaluate (GDS_block_context, ntohl (put->type), NULL, /* query */ NULL, 0, /* bloom filer */ NULL, 0, /* xquery */ payload, payload_size)) { case GNUNET_BLOCK_EVALUATION_OK_MORE: case GNUNET_BLOCK_EVALUATION_OK_LAST: break; case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: default: GNUNET_break_op (0); return GNUNET_OK; } } bf = GNUNET_CONTAINER_bloomfilter_init (put->bloomfilter, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); GNUNET_break_op (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bf, &phash)); { struct GNUNET_PeerIdentity pp[putlen + 1]; /* extend 'put path' by sender */ if (0 != (options & GNUNET_DHT_RO_RECORD_ROUTE)) { memcpy (pp, put_path, putlen * sizeof (struct GNUNET_PeerIdentity)); pp[putlen] = *peer; putlen++; } else putlen = 0; /* give to local clients */ GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (put->expiration_time), &put->key, 0, NULL, putlen, pp, ntohl (put->type), payload_size, payload); /* store locally */ if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || (am_closest_peer (&put->key, bf))) GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (put->expiration_time), &put->key, putlen, pp, ntohl (put->type), payload_size, payload); /* route to other peers */ GDS_NEIGHBOURS_handle_put (ntohl (put->type), options, ntohl (put->desired_replication_level), GNUNET_TIME_absolute_ntoh (put->expiration_time), ntohl (put->hop_count), bf, &put->key, putlen, pp, payload, payload_size); /* notify monitoring clients */ GDS_CLIENTS_process_put (options, ntohl (put->type), ntohl (put->hop_count), ntohl (put->desired_replication_level), putlen, pp, GNUNET_TIME_absolute_ntoh (put->expiration_time), &put->key, payload, payload_size); } GNUNET_CONTAINER_bloomfilter_free (bf); return GNUNET_YES; } /** * We have received a FIND PEER request. Send matching * HELLOs back. * * @param sender sender of the FIND PEER request * @param key peers close to this key are desired * @param bf peers matching this bf are excluded * @param bf_mutator mutator for bf */ static void handle_find_peer (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_HashCode * key, struct GNUNET_CONTAINER_BloomFilter *bf, uint32_t bf_mutator) { int bucket_idx; struct PeerBucket *bucket; struct PeerInfo *peer; unsigned int choice; struct GNUNET_HashCode phash; struct GNUNET_HashCode mhash; const struct GNUNET_HELLO_Message *hello; /* first, check about our own HELLO */ if (NULL != GDS_my_hello) { GNUNET_BLOCK_mingle_hash (&my_identity_hash, bf_mutator, &mhash); if ((NULL == bf) || (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (bf, &mhash))) { GDS_NEIGHBOURS_handle_reply (sender, GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_TIME_relative_to_absolute (hello_expiration), key, 0, NULL, 0, NULL, GDS_my_hello, GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message *) GDS_my_hello)); } else { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# FIND PEER requests ignored due to Bloomfilter"), 1, GNUNET_NO); } } else { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# FIND PEER requests ignored due to lack of HELLO"), 1, GNUNET_NO); } /* then, also consider sending a random HELLO from the closest bucket */ if (0 == memcmp (&my_identity_hash, key, sizeof (struct GNUNET_HashCode))) bucket_idx = closest_bucket; else bucket_idx = GNUNET_MIN (closest_bucket, find_bucket (key)); if (bucket_idx == GNUNET_SYSERR) return; bucket = &k_buckets[bucket_idx]; if (bucket->peers_size == 0) return; choice = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, bucket->peers_size); peer = bucket->head; while (choice > 0) { GNUNET_assert (NULL != peer); peer = peer->next; choice--; } choice = bucket->peers_size; do { peer = peer->next; if (choice-- == 0) return; /* no non-masked peer available */ if (peer == NULL) peer = bucket->head; GNUNET_CRYPTO_hash (&peer->id, sizeof (struct GNUNET_PeerIdentity), &phash); GNUNET_BLOCK_mingle_hash (&phash, bf_mutator, &mhash); hello = GDS_HELLO_get (&peer->id); } while ((hello == NULL) || (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bf, &mhash))); GDS_NEIGHBOURS_handle_reply (sender, GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION), key, 0, NULL, 0, NULL, hello, GNUNET_HELLO_size (hello)); } /** * Core handler for p2p get requests. * * @param cls closure * @param peer sender of the request * @param message message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handle_dht_p2p_get (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerGetMessage *get; uint32_t xquery_size; size_t reply_bf_size; uint16_t msize; enum GNUNET_BLOCK_Type type; enum GNUNET_DHT_RouteOption options; enum GNUNET_BLOCK_EvaluationResult eval; struct GNUNET_CONTAINER_BloomFilter *reply_bf; struct GNUNET_CONTAINER_BloomFilter *peer_bf; const char *xquery; struct GNUNET_HashCode phash; GNUNET_break (0 != memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity))); /* parse and validate message */ msize = ntohs (message->size); if (msize < sizeof (struct PeerGetMessage)) { GNUNET_break_op (0); return GNUNET_YES; } get = (struct PeerGetMessage *) message; xquery_size = ntohl (get->xquery_size); if (msize < sizeof (struct PeerGetMessage) + xquery_size) { GNUNET_break_op (0); return GNUNET_YES; } reply_bf_size = msize - (sizeof (struct PeerGetMessage) + xquery_size); type = ntohl (get->type); options = ntohl (get->options); xquery = (const char *) &get[1]; reply_bf = NULL; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P GET requests received"), 1, GNUNET_NO); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P GET bytes received"), msize, GNUNET_NO); GNUNET_CRYPTO_hash (peer, sizeof (struct GNUNET_PeerIdentity), &phash); if (GNUNET_YES == log_route_details_stderr) { char *tmp; tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N GET %s: %s->%s (%u, %u=>%u) xq: %.*s\n", GNUNET_h2s (&get->key), GNUNET_i2s (peer), tmp, ntohl(get->hop_count), GNUNET_CRYPTO_hash_matching_bits (&phash, &get->key), GNUNET_CRYPTO_hash_matching_bits (&my_identity_hash, &get->key), ntohl(get->xquery_size), xquery ); GNUNET_free (tmp); } if (reply_bf_size > 0) reply_bf = GNUNET_CONTAINER_bloomfilter_init (&xquery[xquery_size], reply_bf_size, GNUNET_CONSTANTS_BLOOMFILTER_K); eval = GNUNET_BLOCK_evaluate (GDS_block_context, type, &get->key, &reply_bf, get->bf_mutator, xquery, xquery_size, NULL, 0); if (eval != GNUNET_BLOCK_EVALUATION_REQUEST_VALID) { /* request invalid or block type not supported */ GNUNET_break_op (eval == GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED); if (NULL != reply_bf) GNUNET_CONTAINER_bloomfilter_free (reply_bf); return GNUNET_YES; } peer_bf = GNUNET_CONTAINER_bloomfilter_init (get->bloomfilter, DHT_BLOOM_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); GNUNET_break_op (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (peer_bf, &phash)); /* remember request for routing replies */ GDS_ROUTING_add (peer, type, options, &get->key, xquery, xquery_size, reply_bf, get->bf_mutator); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GET for %s at %s after %u hops\n", GNUNET_h2s (&get->key), GNUNET_i2s (&my_identity), (unsigned int) ntohl (get->hop_count)); /* local lookup (this may update the reply_bf) */ if ((0 != (options & GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE)) || (am_closest_peer (&get->key, peer_bf))) { if ((0 != (options & GNUNET_DHT_RO_FIND_PEER))) { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P FIND PEER requests processed"), 1, GNUNET_NO); handle_find_peer (peer, &get->key, reply_bf, get->bf_mutator); } else { eval = GDS_DATACACHE_handle_get (&get->key, type, xquery, xquery_size, &reply_bf, get->bf_mutator); } } else { GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P GET requests ONLY routed"), 1, GNUNET_NO); } GDS_CLIENTS_process_get (options, type, ntohl(get->hop_count), ntohl(get->desired_replication_level), 0, NULL, &get->key); /* P2P forwarding */ if (eval != GNUNET_BLOCK_EVALUATION_OK_LAST) GDS_NEIGHBOURS_handle_get (type, options, ntohl (get->desired_replication_level), ntohl (get->hop_count), &get->key, xquery, xquery_size, reply_bf, get->bf_mutator, peer_bf); /* clean up */ if (NULL != reply_bf) GNUNET_CONTAINER_bloomfilter_free (reply_bf); GNUNET_CONTAINER_bloomfilter_free (peer_bf); return GNUNET_YES; } /** * Core handler for p2p result messages. * * @param cls closure * @param message message * @param peer peer identity this notification is about * @return #GNUNET_YES (do not cut p2p connection) */ static int handle_dht_p2p_result (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { const struct PeerResultMessage *prm; const struct GNUNET_PeerIdentity *put_path; const struct GNUNET_PeerIdentity *get_path; const void *data; uint32_t get_path_length; uint32_t put_path_length; uint16_t msize; size_t data_size; enum GNUNET_BLOCK_Type type; /* parse and validate message */ msize = ntohs (message->size); if (msize < sizeof (struct PeerResultMessage)) { GNUNET_break_op (0); return GNUNET_YES; } prm = (struct PeerResultMessage *) message; put_path_length = ntohl (prm->put_path_length); get_path_length = ntohl (prm->get_path_length); if ((msize < sizeof (struct PeerResultMessage) + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity)) || (get_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity)) || (put_path_length > GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_YES; } put_path = (const struct GNUNET_PeerIdentity *) &prm[1]; get_path = &put_path[put_path_length]; type = ntohl (prm->type); data = (const void *) &get_path[get_path_length]; data_size = msize - (sizeof (struct PeerResultMessage) + (get_path_length + put_path_length) * sizeof (struct GNUNET_PeerIdentity)); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P RESULTS received"), 1, GNUNET_NO); GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# P2P RESULT bytes received"), msize, GNUNET_NO); if (GNUNET_YES == log_route_details_stderr) { char *tmp; tmp = GNUNET_strdup (GNUNET_i2s (&my_identity)); LOG_TRAFFIC (GNUNET_ERROR_TYPE_DEBUG, "R5N RESULT %s: %s->%s (%u)\n", GNUNET_h2s (&prm->key), GNUNET_i2s (peer), tmp, get_path_length + 1); GNUNET_free (tmp); } /* if we got a HELLO, consider it for our own routing table */ if (type == GNUNET_BLOCK_TYPE_DHT_HELLO) { const struct GNUNET_MessageHeader *h; struct GNUNET_PeerIdentity pid; int bucket; /* Should be a HELLO, validate and consider using it! */ if (data_size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_YES; } h = data; if (data_size != ntohs (h->size)) { GNUNET_break_op (0); return GNUNET_YES; } if (GNUNET_OK != GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) h, &pid)) { GNUNET_break_op (0); return GNUNET_YES; } if ((GNUNET_YES != disable_try_connect) && 0 != memcmp (&my_identity, &pid, sizeof (struct GNUNET_PeerIdentity))) { struct GNUNET_HashCode pid_hash; GNUNET_CRYPTO_hash (&pid, sizeof (struct GNUNET_PeerIdentity), &pid_hash); bucket = find_bucket (&pid_hash); if ((bucket >= 0) && (k_buckets[bucket].peers_size < bucket_size) && (NULL != GDS_transport_handle)) { GNUNET_TRANSPORT_offer_hello (GDS_transport_handle, h, NULL, NULL); GNUNET_TRANSPORT_try_connect (GDS_transport_handle, &pid, NULL, NULL); /*FIXME TRY_CONNECT change */ } } } /* append 'peer' to 'get_path' */ { struct GNUNET_PeerIdentity xget_path[get_path_length + 1]; memcpy (xget_path, get_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); xget_path[get_path_length] = *peer; get_path_length++; /* forward to local clients */ GDS_CLIENTS_handle_reply (GNUNET_TIME_absolute_ntoh (prm->expiration_time), &prm->key, get_path_length, xget_path, put_path_length, put_path, type, data_size, data); GDS_CLIENTS_process_get_resp (type, xget_path, get_path_length, put_path, put_path_length, GNUNET_TIME_absolute_ntoh ( prm->expiration_time), &prm->key, data, data_size); if (GNUNET_YES == cache_results) { struct GNUNET_PeerIdentity xput_path[get_path_length + 1 + put_path_length]; memcpy (xput_path, put_path, put_path_length * sizeof (struct GNUNET_PeerIdentity)); memcpy (&xput_path[put_path_length], xget_path, get_path_length * sizeof (struct GNUNET_PeerIdentity)); GDS_DATACACHE_handle_put (GNUNET_TIME_absolute_ntoh (prm->expiration_time), &prm->key, get_path_length + put_path_length, xput_path, type, data_size, data); } /* forward to other peers */ GDS_ROUTING_process (type, GNUNET_TIME_absolute_ntoh (prm->expiration_time), &prm->key, put_path_length, put_path, get_path_length, xget_path, data, data_size); } return GNUNET_YES; } /** * Initialize neighbours subsystem. * * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int GDS_NEIGHBOURS_init () { static struct GNUNET_CORE_MessageHandler core_handlers[] = { {&handle_dht_p2p_get, GNUNET_MESSAGE_TYPE_DHT_P2P_GET, 0}, {&handle_dht_p2p_put, GNUNET_MESSAGE_TYPE_DHT_P2P_PUT, 0}, {&handle_dht_p2p_result, GNUNET_MESSAGE_TYPE_DHT_P2P_RESULT, 0}, {NULL, 0, 0} }; unsigned long long temp_config_num; disable_try_connect = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg, "DHT", "DISABLE_TRY_CONNECT"); if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GDS_cfg, "DHT", "bucket_size", &temp_config_num)) bucket_size = (unsigned int) temp_config_num; cache_results = GNUNET_CONFIGURATION_get_value_yesno (GDS_cfg, "DHT", "CACHE_RESULTS"); log_route_details_stderr = (NULL != getenv("GNUNET_DHT_ROUTE_DEBUG")) ? GNUNET_YES : GNUNET_NO; atsAPI = GNUNET_ATS_performance_init (GDS_cfg, NULL, NULL); core_api = GNUNET_CORE_connect (GDS_cfg, NULL, &core_init, &handle_core_connect, &handle_core_disconnect, NULL, GNUNET_NO, NULL, GNUNET_NO, core_handlers); if (core_api == NULL) return GNUNET_SYSERR; all_known_peers = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO); return GNUNET_OK; } /** * Shutdown neighbours subsystem. */ void GDS_NEIGHBOURS_done () { if (NULL == core_api) return; GNUNET_CORE_disconnect (core_api); core_api = NULL; GNUNET_ATS_performance_done (atsAPI); atsAPI = NULL; GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (all_known_peers)); GNUNET_CONTAINER_multipeermap_destroy (all_known_peers); all_known_peers = NULL; if (GNUNET_SCHEDULER_NO_TASK != find_peer_task) { GNUNET_SCHEDULER_cancel (find_peer_task); find_peer_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Get the ID of the local node. * * @return identity of the local node */ struct GNUNET_PeerIdentity * GDS_NEIGHBOURS_get_id () { return &my_identity; } /* end of gnunet-service-dht_neighbours.c */ gnunet-0.10.1/src/dht/gnunet-service-xdht_hello.c0000644000175000017500000000717712252673741016637 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dht/gnunet-service-xdht_hello.c * @brief GNUnet DHT integration with peerinfo * @author Christian Grothoff * * TODO: * - consider adding mechanism to remove expired HELLOs */ #include "platform.h" #include "gnunet-service-xdht.h" #include "gnunet-service-xdht_hello.h" #include "gnunet_peerinfo_service.h" /** * Handle for peerinfo notifications. */ static struct GNUNET_PEERINFO_NotifyContext *pnc; /** * Hash map of peers to HELLOs. */ static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello; /** * Obtain a peer's HELLO if available * * @param peer peer to look for a HELLO from * @return HELLO for the given peer */ const struct GNUNET_HELLO_Message * GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer) { if (NULL == peer_to_hello) return NULL; return GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer); } /** * Function called for each HELLO known to PEERINFO. * * @param cls closure * @param peer id of the peer, NULL for last call * @param hello hello message for the peer (can be NULL) * @param err_msg error message (not used) */ static void process_hello (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { struct GNUNET_TIME_Absolute ex; struct GNUNET_HELLO_Message *hm; if (hello == NULL) return; ex = GNUNET_HELLO_get_last_expiration (hello); if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us) return; GNUNET_STATISTICS_update (GDS_stats, gettext_noop ("# HELLOs obtained from peerinfo"), 1, GNUNET_NO); hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer); GNUNET_free_non_null (hm); hm = GNUNET_malloc (GNUNET_HELLO_size (hello)); memcpy (hm, hello, GNUNET_HELLO_size (hello)); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_multipeermap_put (peer_to_hello, peer, hm, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); } /** * Initialize HELLO subsystem. */ void GDS_HELLO_init () { pnc = GNUNET_PEERINFO_notify (GDS_cfg, GNUNET_NO, &process_hello, NULL); peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256, GNUNET_NO); } /** * Free memory occopied by the HELLO. */ static int free_hello (void *cls, const struct GNUNET_PeerIdentity *key, void *hello) { GNUNET_free (hello); return GNUNET_OK; } /** * Shutdown HELLO subsystem. */ void GDS_HELLO_done () { if (NULL != pnc) { GNUNET_PEERINFO_notify_cancel (pnc); pnc = NULL; } if (NULL != peer_to_hello) { GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello, &free_hello, NULL); GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello); } } /* end of gnunet-service-dht_hello.c */ gnunet-0.10.1/src/transport/0000755000175000017500000000000012320755625012724 500000000000000gnunet-0.10.1/src/transport/test_transport_api_multi_peer2.conf0000644000175000017500000000137712225230043021740 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-multi-p2/ [nat] ALLOW_NAT = NO [transport-tcp] PORT = 12150 TIMEOUT = 5 s [transport-udp] PORT = 12151 [transport-http] PORT = 12152 [transport-https] PORT = 12153 [arm] PORT = 12159 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12158 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12157 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12156 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12155 PLUGINS = tcp udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-unix] PORT = 12154 gnunet-0.10.1/src/transport/test_quota_compliance_wlan_asymmetric_peer2.conf0000644000175000017500000000112112225230043024425 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p2/ [transport-wlan] INTERFACE = mon1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_unreliability_udp_peer1.conf0000644000175000017500000000112012225230043024313 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-p1/ [transport-udp] PORT = 12040 MAX_BPS = 5000000 [arm] PORT = 12045 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12044 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12043 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12042 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12041 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/gnunet-helper-transport-wlan.c0000644000175000017500000017507112225777502020573 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) Copyright (c) 2007, 2008, Andy Green Copyright (C) 2009 Thomas d'Otreppe GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/transport/gnunet-helper-transport-wlan.c * @brief mediator between the wlan interface and gnunet; must run as root (SUID will do) * This code will work under GNU/Linux only. * @author David Brodski * @author Christian Grothoff * * This program will allow receiving and sending traffic from the WLAN * interface. It will force traffic to be in 'ad-hoc' mode, use the * proper MAC address of the WLAN interface and use a GNUnet-specific * SSID (and a GNUnet-specific SNAP header). It only takes a single * argument, which is the name of the WLAN interface to use. The * program detects if the interface is not a WLAN interface and exits * with an error in that case. * * Once initialized, the program will first send a 'struct * GNUNET_TRANSPORT_WLAN_HelperControlMessage' to 'stdout'. That * message contains the MAC address of the WLAN interface. It will * then read messages from the WLAN interface and send them together * with performance information as 'struct * GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage' messages to 'stdout'. * Furthermore, it will read a stream of messages from 'stdin' that * have the format from 'struct * GNUNET_TRANSPORT_WLAN_RadiotapSendMessage'. Those messages will * then be sent via the WLAN interface; however, the sender MAC * address will be forced to be the correct address from our WLAN * card. If 'stdin' closes, receiving from the WLAN interface will * continue. If 'stdout' causes a SIGPIPE, the process dies from the * signal. Errors cause an error message to be reported to 'stderr', * in most cases the process also exits (with status code '1'). The * program never terminates normally; it is safe to kill the * process with SIGTERM or SIGKILL at any time. * * Since it uses RAW sockets, the binary must be installed SUID or run * as 'root'. In order to keep the security risk of the resulting * SUID binary minimal, the program ONLY opens the RAW socket with * root privileges, then drops them and only then starts to process * command line arguments. The code also does not link against any * shared libraries (except libc) and is strictly minimal (except for * checking for errors). The following list of people have reviewed * this code and considered it safe since the last modification (if * you reviewed it, please have your name added to the list): * * - Christian Grothoff (Apr 3rd 2012) */ /*- * we use our local copy of ieee80211_radiotap.h * * - since we can't support extensions we don't understand * - since linux does not include it in userspace headers * * Portions of this code were taken from the ieee80211_radiotap.h header, * which is * * Copyright (c) 2003, 2004 David Young. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of David Young may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ /* * Modifications to fit into the linux IEEE 802.11 stack, * Mike Kershaw (dragorn@kismetwireless.net) */ /* * parts taken from aircrack-ng, parts changend. */ #include "gnunet_config.h" #define SOCKTYPE int #define FDTYPE int #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnunet_protocols.h" #include "plugin_transport_wlan.h" /** * Packet format type for the messages we receive from * the kernel. This is for Ethernet 10Mbps format (no * performance information included). */ #define ARPHRD_ETHER 1 /** * Packet format type for the messages we receive from * the kernel. This is for plain messages (with no * performance information included). */ #define ARPHRD_IEEE80211 801 /** * Packet format type for the messages we receive from * the kernel. This is for the PRISM format. */ #define ARPHRD_IEEE80211_PRISM 802 /** * Packet format type for the messages we receive from * the kernel. This is for messages with a * 'struct Ieee80211RadiotapHeader' (see below). */ #define ARPHRD_IEEE80211_FULL 803 /** * Maximum size of a message allowed in either direction * (used for our receive and sent buffers). */ #define MAXLINE 4096 /* ********* structure of messages of type ARPHRD_IEEE80211_PRISM *********** */ /** * Device name length in PRISM frames. * (In the kernel, this is "WLAN_DEVNAMELEN_MAX") */ #define PRISM_DEVICE_NAME_LENGTH 16 /** * Monitor Frame (indicator that we have a 'struct PrismHeader'). */ #define PRISM_MSGCODE_MONITOR 0x0041 /** * Mac time element. In micro-seconds. * Drivers appear to use a 64bit counter to hold mactime internal * the then fill the prism header with the lower 32 bits */ #define PRISM_DID_MACTIME 0x2041 /** * Channel element */ #define PRISM_DID_CHANNEL 0x3041 /** * Signal element. Should be the signal strength in dbm, some people * suggest that instead "100 - (strength in dbm)" is used (to make this * a positive integer). */ #define PRISM_DID_SIGNAL 0x6041 /** * Noise element */ #define PRISM_DID_NOISE 0x7041 /** * Rate element, in units/multiples of 500Khz */ #define PRISM_DID_RATE 0x8041 /** * Value is set (supplied) */ #define PRISM_STATUS_OK 0 /** * Value not supplied. */ #define PRISM_STATUS_NO_VALUE 1 /** * Values in the 'struct PrismHeader'. All in host byte order (!). */ struct PrismValue { /** * This has a different ID for each parameter, see * PRISM_DID_* constants. */ uint32_t did; /** * See PRISM_STATUS_*-constants. Note that they are unusual: 0 = set; 1 = not set */ uint16_t status; /** * length of data (which is always a uint32_t, but presumably this can be used * to specify that fewer bytes are used (with values in 'len' from 0-4). We * ignore this field. */ uint16_t len; /** * The data value */ uint32_t data; } __attribute__ ((packed)); /** * Prism header format ('struct p80211msg' in Linux). All in host byte order (!). */ struct PrismHeader { /** * We expect this to be a PRISM_MSGCODE_*. */ uint32_t msgcode; /** * The length of the entire header. */ uint32_t msglen; /** * Name of the device that captured the packet. */ char devname[PRISM_DEVICE_NAME_LENGTH]; /* followed by 'struct PrismValue's. Documentation suggests that these are typically the hosttime, mactime, channel, rssi, sq, signal, noise, rate, istx and frmlen values, but documentation is sparse. So we will use the 'did' fields to find out what we actually got. */ } __attribute__ ((packed)); /* ****** end of structure of messages of type ARPHRD_IEEE80211_PRISM ******* */ /* ********** structure of messages of type ARPHRD_IEEE80211_FULL *********** */ /** * Bits in the 'it_present' bitmask from the 'struct * Ieee80211RadiotapHeader'. For each value, we give the name, data * type, unit and then a description below. Note that the actual size * of the extension can be bigger as arguments must be padded so that * args of a given length must begin at a boundary of that length. * However, note that compound args are allowed (eg, 2 x uint16_t for * IEEE80211_RADIOTAP_CHANNEL) so total argument length is not a * reliable indicator of alignment requirement. See also * 'man 9 ieee80211_radiotap'. */ enum RadiotapType { /** * IEEE80211_RADIOTAP_TSFT __le64 microseconds * * Value in microseconds of the MAC's 64-bit 802.11 Time * Synchronization Function timer when the first bit of the * MPDU arrived at the MAC. For received frames, only. */ IEEE80211_RADIOTAP_TSFT = 0, /** * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap * * Properties of transmitted and received frames. See flags * defined below. */ IEEE80211_RADIOTAP_FLAGS = 1, /** * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s * * Tx/Rx data rate */ IEEE80211_RADIOTAP_RATE = 2, /** * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap * * Tx/Rx frequency in MHz, followed by flags (see below). */ IEEE80211_RADIOTAP_CHANNEL = 3, /** * IEEE80211_RADIOTAP_FHSS __le16 see below * * For frequency-hopping radios, the hop set (first byte) * and pattern (second byte). */ IEEE80211_RADIOTAP_FHSS = 4, /** * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from * one milliwatt (dBm) * * RF signal power at the antenna, decibel difference from * one milliwatt. */ IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, /** * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from * one milliwatt (dBm) * * RF noise power at the antenna, decibel difference from one * milliwatt. */ IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, /** * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless * * Quality of Barker code lock. Unitless. Monotonically * nondecreasing with "better" lock strength. Called "Signal * Quality" in datasheets. (Is there a standard way to measure * this?) */ IEEE80211_RADIOTAP_LOCK_QUALITY = 7, /** * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless * * Transmit power expressed as unitless distance from max * power set at factory calibration. 0 is max power. * Monotonically nondecreasing with lower power levels. */ IEEE80211_RADIOTAP_TX_ATTENUATION = 8, /** * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB) * * Transmit power expressed as decibel distance from max power * set at factory calibration. 0 is max power. Monotonically * nondecreasing with lower power levels. */ IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, /** * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from * one milliwatt (dBm) * * Transmit power expressed as dBm (decibels from a 1 milliwatt * reference). This is the absolute power level measured at * the antenna port. */ IEEE80211_RADIOTAP_DBM_TX_POWER = 10, /** * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index * * Unitless indication of the Rx/Tx antenna for this packet. * The first antenna is antenna 0. */ IEEE80211_RADIOTAP_ANTENNA = 11, /** * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB) * * RF signal power at the antenna, decibel difference from an * arbitrary, fixed reference. */ IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, /** * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB) * * RF noise power at the antenna, decibel difference from an * arbitrary, fixed reference point. */ IEEE80211_RADIOTAP_DB_ANTNOISE = 13, /** * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap * * Properties of received frames. See flags defined below. */ IEEE80211_RADIOTAP_RX_FLAGS = 14, /** * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap * * Properties of transmitted frames. See flags defined below. */ IEEE80211_RADIOTAP_TX_FLAGS = 15, /** * IEEE80211_RADIOTAP_RTS_RETRIES uint8_t data * * Number of rts retries a transmitted frame used. */ IEEE80211_RADIOTAP_RTS_RETRIES = 16, /** * IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data * * Number of unicast retries a transmitted frame used. */ IEEE80211_RADIOTAP_DATA_RETRIES = 17, /** * Extension bit, used to indicate that more bits are needed for * the bitmask. */ IEEE80211_RADIOTAP_EXT = 31 }; /** * Bitmask indicating an extension of the bitmask is used. * (Mask corresponding to IEEE80211_RADIOTAP_EXT). */ #define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK (1 << IEEE80211_RADIOTAP_EXT) /** * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get * as part of a 'struct Ieee80211RadiotapHeader' extension * if the IEEE80211_RADIOTAP_FLAGS bit is set in * 'it_present'). The radiotap flags are an 8-bit field. * * Frame was sent/received during CFP (Contention Free Period) */ #define IEEE80211_RADIOTAP_F_CFP 0x01 /** * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get * as part of a 'struct Ieee80211RadiotapHeader' extension * if the IEEE80211_RADIOTAP_FLAGS bit is set in * 'it_present'). The radiotap flags are an 8-bit field. * * Frame was sent/received with short preamble */ #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /** * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get * as part of a 'struct Ieee80211RadiotapHeader' extension * if the IEEE80211_RADIOTAP_FLAGS bit is set in * 'it_present'). The radiotap flags are an 8-bit field. * * Frame was sent/received with WEP encryption */ #define IEEE80211_RADIOTAP_F_WEP 0x04 /** * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get * as part of a 'struct Ieee80211RadiotapHeader' extension * if the IEEE80211_RADIOTAP_FLAGS bit is set in * 'it_present'). The radiotap flags are an 8-bit field. * * Frame was sent/received with fragmentation */ #define IEEE80211_RADIOTAP_F_FRAG 0x08 /** * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get * as part of a 'struct Ieee80211RadiotapHeader' extension * if the IEEE80211_RADIOTAP_FLAGS bit is set in * 'it_present'). The radiotap flags are an 8-bit field. * * Frame includes FCS (CRC at the end that needs to be removeD). */ #define IEEE80211_RADIOTAP_F_FCS 0x10 /** * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get * as part of a 'struct Ieee80211RadiotapHeader' extension * if the IEEE80211_RADIOTAP_FLAGS bit is set in * 'it_present'). The radiotap flags are an 8-bit field. * * Frame has padding between 802.11 header and payload * (to 32-bit boundary) */ #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /** * For IEEE80211_RADIOTAP_RX_FLAGS: * frame failed crc check */ #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /** * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): * failed due to excessive retries */ #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /** * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): * used cts 'protection' */ #define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /** * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): * used rts/cts handshake */ #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /** * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): * frame should not be ACKed */ #define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /** * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'): * sequence number handled by userspace */ #define IEEE80211_RADIOTAP_F_TX_NOSEQ 0x0010 /** * Generic header for radiotap messages (receiving and sending). A * bit mask (it_present) determines which specific records follow. * * I am trying to describe precisely what the application programmer * should expect in the following, and for that reason I tell the * units and origin of each measurement (where it applies), or else I * use sufficiently weaselly language ("is a monotonically nondecreasing * function of...") that I cannot set false expectations for lawyerly * readers. * * The radio capture header precedes the 802.11 header. * All data in the header is little endian on all platforms. */ struct Ieee80211RadiotapHeader { /** * Version 0. Only increases for drastic changes, introduction of * compatible new fields does not count. */ uint8_t it_version; /** * Padding. Set to 0. */ uint8_t it_pad; /** * length of the whole header in bytes, including it_version, * it_pad, it_len, and data fields. */ uint16_t it_len; /** * A bitmap telling which fields are present. Set bit 31 * (0x80000000) to extend the bitmap by another 32 bits. Additional * extensions are made by setting bit 31. */ uint32_t it_present; }; /** * Format of the header we need to prepend to messages to be sent to the * Kernel. */ struct RadiotapTransmissionHeader { /** * First we begin with the 'generic' header we also get when receiving * messages. */ struct Ieee80211RadiotapHeader header; /** * Transmission rate (we use 0, kernel makes up its mind anyway). */ uint8_t rate; /** * Padding (we use 0). There is a requirement to pad args, so that * args of a given length must begin at a boundary of that length. * As our next argument is the 'it_len' with 2 bytes, we need 1 byte * of padding. */ uint8_t pad1; /** * Transmission flags from on the IEEE80211_RADIOTAP_F_TX_* constant family. */ uint16_t txflags; }; /** * The above 'struct RadiotapTransmissionHeader' should have the * following value for 'header.it_present' based on the presence of * the 'rate' and 'txflags' in the overall struct. */ #define IEEE80211_RADIOTAP_OUR_TRANSMISSION_HEADER_MASK ((1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_TX_FLAGS)) /** * struct Ieee80211RadiotapHeaderIterator - tracks walk through present radiotap arguments * in the radiotap header. Used when we parse radiotap packets received from the kernel. */ struct Ieee80211RadiotapHeaderIterator { /** * pointer to the radiotap header we are walking through */ const struct Ieee80211RadiotapHeader *rtheader; /** * pointer to current radiotap arg */ const uint8_t *this_arg; /** * internal next argument pointer */ const uint8_t *arg; /** * internal pointer to next present uint32_t (if IEEE80211_RADIOTAP_EXT is used). */ const uint32_t *next_bitmap; /** * length of radiotap header in host byte ordering */ size_t max_length; /** * internal shifter for current uint32_t bitmap, (it_present in host byte order), * If bit 0 is set, the 'arg_index' argument is present. */ uint32_t bitmap_shifter; /** * IEEE80211_RADIOTAP_... index of current arg */ unsigned int this_arg_index; /** * internal next argument index */ unsigned int arg_index; }; /* ************** end of structure of ARPHRD_IEEE80211_FULL ************** */ /* ************************** our globals ******************************* */ /** * struct for storing the information of the hardware. There is only * one of these. */ struct HardwareInfos { /** * file descriptor for the raw socket */ int fd_raw; /** * Which format has the header that we're getting when receiving packets? * Some ARPHRD_IEEE80211_XXX-value. */ int arptype_in; /** * Name of the interface, not necessarily 0-terminated (!). */ char iface[IFNAMSIZ]; /** * MAC address of our own WLAN interface. */ struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac; }; /** * IO buffer used for buffering data in transit (to wireless or to stdout). */ struct SendBuffer { /** * How many bytes of data are stored in 'buf' for transmission right now? * Data always starts at offset 0 and extends to 'size'. */ size_t size; /** * How many bytes that were stored in 'buf' did we already write to the * destination? Always smaller than 'size'. */ size_t pos; /** * Buffered data; twice the maximum allowed message size as we add some * headers. */ char buf[MAXLINE * 2]; }; /** * Buffer for data read from stdin to be transmitted to the wirless card. */ static struct SendBuffer write_pout; /** * Buffer for data read from the wireless card to be transmitted to stdout. */ static struct SendBuffer write_std; /* *********** specialized version of server_mst.c begins here ********** */ /** * To what multiple do we align messages? 8 byte should suffice for everyone * for now. */ #define ALIGN_FACTOR 8 /** * Smallest supported message. */ #define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader) /** * Functions with this signature are called whenever a * complete message is received by the tokenizer. * * @param cls closure * @param message the actual message */ typedef void (*MessageTokenizerCallback) (void *cls, const struct GNUNET_MessageHeader * message); /** * Handle to a message stream tokenizer. */ struct MessageStreamTokenizer { /** * Function to call on completed messages. */ MessageTokenizerCallback cb; /** * Closure for cb. */ void *cb_cls; /** * Size of the buffer (starting at 'hdr'). */ size_t curr_buf; /** * How many bytes in buffer have we already processed? */ size_t off; /** * How many bytes in buffer are valid right now? */ size_t pos; /** * Beginning of the buffer. Typed like this to force alignment. */ struct GNUNET_MessageHeader *hdr; }; /** * Create a message stream tokenizer. * * @param cb function to call on completed messages * @param cb_cls closure for cb * @return handle to tokenizer */ static struct MessageStreamTokenizer * mst_create (MessageTokenizerCallback cb, void *cb_cls) { struct MessageStreamTokenizer *ret; ret = malloc (sizeof (struct MessageStreamTokenizer)); if (NULL == ret) { fprintf (stderr, "Failed to allocate buffer for tokenizer\n"); exit (1); } ret->hdr = malloc (MIN_BUFFER_SIZE); if (NULL == ret->hdr) { fprintf (stderr, "Failed to allocate buffer for alignment\n"); exit (1); } ret->curr_buf = MIN_BUFFER_SIZE; ret->cb = cb; ret->cb_cls = cb_cls; return ret; } /** * Add incoming data to the receive buffer and call the * callback for all complete messages. * * @param mst tokenizer to use * @param buf input data to add * @param size number of bytes in buf * @return GNUNET_OK if we are done processing (need more data) * GNUNET_SYSERR if the data stream is corrupt */ static int mst_receive (struct MessageStreamTokenizer *mst, const char *buf, size_t size) { const struct GNUNET_MessageHeader *hdr; size_t delta; uint16_t want; char *ibuf; int need_align; unsigned long offset; int ret; ret = GNUNET_OK; ibuf = (char *) mst->hdr; while (mst->pos > 0) { do_align: if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) || (0 != (mst->off % ALIGN_FACTOR))) { /* need to align or need more space */ mst->pos -= mst->off; memmove (ibuf, &ibuf[mst->off], mst->pos); mst->off = 0; } if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) { delta = GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) - (mst->pos - mst->off), size); memcpy (&ibuf[mst->pos], buf, delta); mst->pos += delta; buf += delta; size -= delta; } if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) { return GNUNET_OK; } hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; want = ntohs (hdr->size); if (want < sizeof (struct GNUNET_MessageHeader)) { fprintf (stderr, "Received invalid message from stdin\n"); exit (1); } if (mst->curr_buf - mst->off < want) { /* need more space */ mst->pos -= mst->off; memmove (ibuf, &ibuf[mst->off], mst->pos); mst->off = 0; } if (want > mst->curr_buf) { mst->hdr = realloc (mst->hdr, want); if (NULL == mst->hdr) { fprintf (stderr, "Failed to allocate buffer for alignment\n"); exit (1); } ibuf = (char *) mst->hdr; mst->curr_buf = want; } hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; if (mst->pos - mst->off < want) { delta = GNUNET_MIN (want - (mst->pos - mst->off), size); memcpy (&ibuf[mst->pos], buf, delta); mst->pos += delta; buf += delta; size -= delta; } if (mst->pos - mst->off < want) { return GNUNET_OK; } mst->cb (mst->cb_cls, hdr); mst->off += want; if (mst->off == mst->pos) { /* reset to beginning of buffer, it's free right now! */ mst->off = 0; mst->pos = 0; } } while (size > 0) { if (size < sizeof (struct GNUNET_MessageHeader)) break; offset = (unsigned long) buf; need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO; if (GNUNET_NO == need_align) { /* can try to do zero-copy and process directly from original buffer */ hdr = (const struct GNUNET_MessageHeader *) buf; want = ntohs (hdr->size); if (want < sizeof (struct GNUNET_MessageHeader)) { fprintf (stderr, "Received invalid message from stdin\n"); exit (1); } if (size < want) break; /* or not, buffer incomplete, so copy to private buffer... */ mst->cb (mst->cb_cls, hdr); buf += want; size -= want; } else { /* need to copy to private buffer to align; * yes, we go a bit more spagetti than usual here */ goto do_align; } } if (size > 0) { if (size + mst->pos > mst->curr_buf) { mst->hdr = realloc (mst->hdr, size + mst->pos); if (NULL == mst->hdr) { fprintf (stderr, "Failed to allocate buffer for alignment\n"); exit (1); } ibuf = (char *) mst->hdr; mst->curr_buf = size + mst->pos; } if (mst->pos + size > mst->curr_buf) { fprintf (stderr, "Assertion failed\n"); exit (1); } memcpy (&ibuf[mst->pos], buf, size); mst->pos += size; } return ret; } /** * Destroys a tokenizer. * * @param mst tokenizer to destroy */ static void mst_destroy (struct MessageStreamTokenizer *mst) { free (mst->hdr); free (mst); } /* ***************** end of server_mst.c clone ***************** **/ /* ************** code for handling of ARPHRD_IEEE80211_FULL ************** */ /** * Radiotap header iteration * * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator * struct Ieee80211RadiotapHeaderIterator (no need to init the struct beforehand) * then loop calling __ieee80211_radiotap_iterator_next()... it returns -1 * if there are no more args in the header, or the next argument type index * that is present. The iterator's this_arg member points to the start of the * argument associated with the current argument index that is present, * which can be found in the iterator's this_arg_index member. This arg * index corresponds to the IEEE80211_RADIOTAP_... defines. * * @param iterator iterator to initialize * @param radiotap_header message to parse * @param max_length number of valid bytes in radiotap_header * @return 0 on success, -1 on error */ static int ieee80211_radiotap_iterator_init (struct Ieee80211RadiotapHeaderIterator *iterator, const struct Ieee80211RadiotapHeader *radiotap_header, size_t max_length) { if ( (iterator == NULL) || (radiotap_header == NULL) ) return -1; /* Linux only supports version 0 radiotap format */ if (0 != radiotap_header->it_version) return -1; /* sanity check for allowed length and radiotap length field */ if ( (max_length < sizeof (struct Ieee80211RadiotapHeader)) || (max_length < (GNUNET_le16toh (radiotap_header->it_len))) ) return -1; memset (iterator, 0, sizeof (struct Ieee80211RadiotapHeaderIterator)); iterator->rtheader = radiotap_header; iterator->max_length = GNUNET_le16toh (radiotap_header->it_len); iterator->bitmap_shifter = GNUNET_le32toh (radiotap_header->it_present); iterator->arg = ((uint8_t *) radiotap_header) + sizeof (struct Ieee80211RadiotapHeader); /* find payload start allowing for extended bitmap(s) */ if (0 != (iterator->bitmap_shifter & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK)) { while (GNUNET_le32toh (*((uint32_t *) iterator->arg)) & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK) { iterator->arg += sizeof (uint32_t); /* * check for insanity where the present bitmaps * keep claiming to extend up to or even beyond the * stated radiotap header length */ if (iterator->arg - ((uint8_t*) iterator->rtheader) > iterator->max_length) return -1; } iterator->arg += sizeof (uint32_t); /* * no need to check again for blowing past stated radiotap * header length, becuase ieee80211_radiotap_iterator_next * checks it before it is dereferenced */ } /* we are all initialized happily */ return 0; } /** * Returns the next radiotap parser iterator arg. * * This function returns the next radiotap arg index (IEEE80211_RADIOTAP_...) * and sets iterator->this_arg to point to the payload for the arg. It takes * care of alignment handling and extended present fields. interator->this_arg * can be changed by the caller. The args pointed to are in little-endian * format. * * @param iterator: radiotap_iterator to move to next arg (if any) * @return next present arg index on success or -1 if no more or error */ static int ieee80211_radiotap_iterator_next (struct Ieee80211RadiotapHeaderIterator *iterator) { /* * small length lookup table for all radiotap types we heard of * starting from b0 in the bitmap, so we can walk the payload * area of the radiotap header * * There is a requirement to pad args, so that args * of a given length must begin at a boundary of that length * -- but note that compound args are allowed (eg, 2 x uint16_t * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not * a reliable indicator of alignment requirement. * * upper nybble: content alignment for arg * lower nybble: content length for arg */ static const uint8_t rt_sizes[] = { [IEEE80211_RADIOTAP_TSFT] = 0x88, [IEEE80211_RADIOTAP_FLAGS] = 0x11, [IEEE80211_RADIOTAP_RATE] = 0x11, [IEEE80211_RADIOTAP_CHANNEL] = 0x24, [IEEE80211_RADIOTAP_FHSS] = 0x22, [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, [IEEE80211_RADIOTAP_ANTENNA] = 0x11, [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11, [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22, [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22, [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11, [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11 /* * add more here as they are defined in * include/net/ieee80211_radiotap.h */ }; /* * for every radiotap entry we can at * least skip (by knowing the length)... */ while (iterator->arg_index < sizeof (rt_sizes)) { int hit = (0 != (iterator->bitmap_shifter & 1)); if (hit) { unsigned int wanted_alignment; unsigned int unalignment; /* * arg is present, account for alignment padding * 8-bit args can be at any alignment * 16-bit args must start on 16-bit boundary * 32-bit args must start on 32-bit boundary * 64-bit args must start on 64-bit boundary * * note that total arg size can differ from alignment of * elements inside arg, so we use upper nybble of length table * to base alignment on. First, 'wanted_alignment' is set to be * 1 for 8-bit, 2 for 16-bit, 4 for 32-bit and 8 for 64-bit * arguments. Then, we calculate the 'unalignment' (how many * bytes we are over by taking the difference of 'arg' and the * overall starting point modulo the desired alignment. As * desired alignments are powers of two, we can do modulo with * binary "&" (and also avoid the possibility of a division by * zero if the 'rt_sizes' table contains bogus entries). * * also note: these alignments are relative to the start of the * radiotap header. There is no guarantee that the radiotap * header itself is aligned on any kind of boundary, thus we * need to really look at the delta here. */ wanted_alignment = rt_sizes[iterator->arg_index] >> 4; unalignment = (((void *) iterator->arg) - ((void *) iterator->rtheader)) & (wanted_alignment - 1); if (0 != unalignment) { /* need padding (by 'wanted_alignment - unalignment') */ iterator->arg_index += wanted_alignment - unalignment; } /* * this is what we will return to user, but we need to * move on first so next call has something fresh to test */ iterator->this_arg_index = iterator->arg_index; iterator->this_arg = iterator->arg; /* internally move on the size of this arg (using lower nybble from the table) */ iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; /* * check for insanity where we are given a bitmap that * claims to have more arg content than the length of the * radiotap section. We will normally end up equalling this * max_length on the last arg, never exceeding it. */ if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) > iterator->max_length) return -1; } /* Now, move on to next bit / next entry */ iterator->arg_index++; if (0 == (iterator->arg_index % 32)) { /* completed current uint32_t bitmap */ if (0 != (iterator->bitmap_shifter & 1)) { /* bit 31 was set, there is more; move to next uint32_t bitmap */ iterator->bitmap_shifter = GNUNET_le32toh (*iterator->next_bitmap); iterator->next_bitmap++; } else { /* no more bitmaps: end (by setting arg_index to high, unsupported value) */ iterator->arg_index = sizeof (rt_sizes); } } else { /* just try the next bit (while loop will move on) */ iterator->bitmap_shifter >>= 1; } /* if we found a valid arg earlier, return it now */ if (hit) return iterator->this_arg_index; } /* we don't know how to handle any more args (or there are no more), so we're done (this is not an error) */ return -1; } /** * Calculate crc32, the start of the calculation * * @param buf buffer to calc the crc * @param len len of the buffer * @return crc sum */ static unsigned long calc_crc_osdep (const unsigned char *buf, size_t len) { static const unsigned long int crc_tbl_osdep[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; unsigned long crc = 0xFFFFFFFF; for (; len > 0; len--, buf++) crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8); return (~crc); } /** * Calculate and check crc of the wlan packet * * @param buf buffer of the packet, with len + 4 bytes of data, * the last 4 bytes being the checksum * @param len length of the payload in data * @return 0 on success (checksum matches), 1 on error */ static int check_crc_buf_osdep (const unsigned char *buf, size_t len) { unsigned long crc; crc = calc_crc_osdep (buf, len); buf += len; if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] && ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3]) return 0; return 1; } /* ************end of code for handling of ARPHRD_IEEE80211_FULL ************** */ /* ************beginning of code for reading packets from kernel ************** */ /** * Return the channel from the frequency (in Mhz) * * @param frequency of the channel * @return number of the channel */ static int get_channel_from_frequency (int32_t frequency) { if (frequency >= 2412 && frequency <= 2472) return (frequency - 2407) / 5; if (frequency == 2484) return 14; if (frequency >= 5000 && frequency <= 6100) return (frequency - 5000) / 5; return -1; } /** * Get the channel used by our WLAN interface. * * @param dev pointer to the dev struct of the card * @return channel number, -1 on error */ static int linux_get_channel (const struct HardwareInfos *dev) { struct iwreq wrq; int32_t frequency; memset (&wrq, 0, sizeof (struct iwreq)); strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ); if (0 > ioctl (dev->fd_raw, SIOCGIWFREQ, &wrq)) return -1; frequency = wrq.u.freq.m; /* 'iw_freq' defines 'm' as '__s32', so we keep it signed */ if (100000000 < frequency) frequency /= 100000; else if (1000000 < frequency) frequency /= 1000; if (1000 < frequency) return get_channel_from_frequency (frequency); return frequency; } /** * Read from the raw socket (the wlan card), parse the packet and * put the result into the buffer for transmission to 'stdout'. * * @param dev pointer to the struct of the wlan card * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame', * followed by the actual payload * @param buf_size size of the buffer * @param ri where to write radiotap_rx info * @return number of bytes written to 'buf' */ static ssize_t linux_read (struct HardwareInfos *dev, unsigned char *buf, size_t buf_size, struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri) { unsigned char tmpbuf[buf_size]; ssize_t caplen; size_t n; int got_signal = 0; int got_noise = 0; int got_channel = 0; int fcs_removed = 0; caplen = read (dev->fd_raw, tmpbuf, buf_size); if (0 > caplen) { if (EAGAIN == errno) return 0; fprintf (stderr, "Failed to read from RAW socket: %s\n", strerror (errno)); return -1; } memset (ri, 0, sizeof (*ri)); switch (dev->arptype_in) { case ARPHRD_IEEE80211_PRISM: { const struct PrismHeader *ph; ph = (const struct PrismHeader*) tmpbuf; n = ph->msglen; if ( (n < 8) || (n >= caplen) ) return 0; /* invalid format */ if ( (PRISM_MSGCODE_MONITOR == ph->msgcode) && (n >= sizeof (struct PrismHeader)) ) { const char *pos; size_t left; struct PrismValue pv; left = n - sizeof (struct PrismHeader); pos = (const char *) &ph[1]; while (left > sizeof (struct PrismValue)) { left -= sizeof (struct PrismValue); memcpy (&pv, pos, sizeof (struct PrismValue)); pos += sizeof (struct PrismValue); switch (pv.did) { case PRISM_DID_NOISE: if (PRISM_STATUS_OK == pv.status) { ri->ri_noise = pv.data; /* got_noise = 1; */ } break; case PRISM_DID_RATE: if (PRISM_STATUS_OK == pv.status) ri->ri_rate = pv.data * 500000; break; case PRISM_DID_CHANNEL: if (PRISM_STATUS_OK == pv.status) { ri->ri_channel = pv.data; got_channel = 1; } break; case PRISM_DID_MACTIME: if (PRISM_STATUS_OK == pv.status) ri->ri_mactime = pv.data; break; case PRISM_DID_SIGNAL: if (PRISM_STATUS_OK == pv.status) { ri->ri_power = pv.data; /* got_signal = 1; */ } break; } } } if ( (n < 8) || (n >= caplen) ) return 0; /* invalid format */ } break; case ARPHRD_IEEE80211_FULL: { struct Ieee80211RadiotapHeaderIterator iterator; struct Ieee80211RadiotapHeader *rthdr; memset (&iterator, 0, sizeof (iterator)); rthdr = (struct Ieee80211RadiotapHeader *) tmpbuf; n = GNUNET_le16toh (rthdr->it_len); if ( (n < sizeof (struct Ieee80211RadiotapHeader)) || (n >= caplen)) return 0; /* invalid 'it_len' */ if (0 != ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen)) return 0; /* go through the radiotap arguments we have been given by the driver */ while (0 <= ieee80211_radiotap_iterator_next (&iterator)) { switch (iterator.this_arg_index) { case IEEE80211_RADIOTAP_TSFT: ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg)); break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: if (!got_signal) { ri->ri_power = * ((int8_t*) iterator.this_arg); got_signal = 1; } break; case IEEE80211_RADIOTAP_DB_ANTSIGNAL: if (!got_signal) { ri->ri_power = * ((int8_t*) iterator.this_arg); got_signal = 1; } break; case IEEE80211_RADIOTAP_DBM_ANTNOISE: if (!got_noise) { ri->ri_noise = * ((int8_t*) iterator.this_arg); got_noise = 1; } break; case IEEE80211_RADIOTAP_DB_ANTNOISE: if (!got_noise) { ri->ri_noise = * ((int8_t*) iterator.this_arg); got_noise = 1; } break; case IEEE80211_RADIOTAP_ANTENNA: ri->ri_antenna = *iterator.this_arg; break; case IEEE80211_RADIOTAP_CHANNEL: ri->ri_channel = *iterator.this_arg; got_channel = 1; break; case IEEE80211_RADIOTAP_RATE: ri->ri_rate = (*iterator.this_arg) * 500000; break; case IEEE80211_RADIOTAP_FLAGS: { uint8_t flags = *iterator.this_arg; /* is the CRC visible at the end? if so, remove */ if (0 != (flags & IEEE80211_RADIOTAP_F_FCS)) { fcs_removed = 1; caplen -= sizeof (uint32_t); } break; } case IEEE80211_RADIOTAP_RX_FLAGS: { uint16_t flags = ntohs (* ((uint16_t *) iterator.this_arg)); if (0 != (flags & IEEE80211_RADIOTAP_F_RX_BADFCS)) return 0; } break; } /* end of 'switch' */ } /* end of the 'while' loop */ } break; case ARPHRD_IEEE80211: n = 0; /* no header */ break; case ARPHRD_ETHER: { if (sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame) > caplen) return 0; /* invalid */ memcpy (&buf[sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame)], tmpbuf + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame), caplen - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame) - 4 /* 4 byte FCS */); return caplen - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame) - 4; } default: errno = ENOTSUP; /* unsupported format */ return -1; } caplen -= n; if (! got_channel) ri->ri_channel = linux_get_channel (dev); /* detect CRC32 at the end, even if the flag wasn't set and remove it */ if ( (0 == fcs_removed) && (0 == check_crc_buf_osdep (tmpbuf + n, caplen - sizeof (uint32_t))) ) { /* NOTE: this heuristic can of course fail if there happens to be a matching checksum at the end. Would be good to have some data to see how often this heuristic actually works. */ caplen -= sizeof (uint32_t); } /* copy payload to target buffer */ memcpy (buf, tmpbuf + n, caplen); return caplen; } /* ************end of code for reading packets from kernel ************** */ /* ************other helper functions for main start here ************** */ /** * Open the wireless network interface for reading/writing. * * @param dev pointer to the device struct * @return 0 on success */ static int open_device_raw (struct HardwareInfos *dev) { struct ifreq ifr; struct iwreq wrq; struct packet_mreq mr; struct sockaddr_ll sll; /* find the interface index */ memset (&ifr, 0, sizeof (ifr)); strncpy (ifr.ifr_name, dev->iface, IFNAMSIZ); if (-1 == ioctl (dev->fd_raw, SIOCGIFINDEX, &ifr)) { fprintf (stderr, "ioctl(SIOCGIFINDEX) on interface `%.*s' failed: %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } /* lookup the hardware type */ memset (&sll, 0, sizeof (sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = ifr.ifr_ifindex; sll.sll_protocol = htons (ETH_P_ALL); if (-1 == ioctl (dev->fd_raw, SIOCGIFHWADDR, &ifr)) { fprintf (stderr, "ioctl(SIOCGIFHWADDR) on interface `%.*s' failed: %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } if (((ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) && (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL)) ) { fprintf (stderr, "Error: interface `%.*s' is not using a supported hardware address family (got %d)\n", IFNAMSIZ, dev->iface, ifr.ifr_hwaddr.sa_family); return 1; } /* lookup iw mode */ memset (&wrq, 0, sizeof (struct iwreq)); strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ); if (-1 == ioctl (dev->fd_raw, SIOCGIWMODE, &wrq)) { /* most probably not supported (ie for rtap ipw interface) * * so just assume its correctly set... */ wrq.u.mode = IW_MODE_MONITOR; } if ( (wrq.u.mode != IW_MODE_MONITOR) && (wrq.u.mode != IW_MODE_ADHOC) ) { fprintf (stderr, "Error: interface `%.*s' is not in monitor or ad-hoc mode (got %d)\n", IFNAMSIZ, dev->iface, wrq.u.mode); return 1; } /* Is interface st to up, broadcast & running ? */ if ((ifr.ifr_flags | IFF_UP | IFF_BROADCAST | IFF_RUNNING) != ifr.ifr_flags) { /* Bring interface up */ ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING; if (-1 == ioctl (dev->fd_raw, SIOCSIFFLAGS, &ifr)) { fprintf (stderr, "ioctl(SIOCSIFFLAGS) on interface `%.*s' failed: %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } } /* bind the raw socket to the interface */ if (-1 == bind (dev->fd_raw, (struct sockaddr *) &sll, sizeof (sll))) { fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } /* lookup the hardware type */ if (-1 == ioctl (dev->fd_raw, SIOCGIFHWADDR, &ifr)) { fprintf (stderr, "ioctl(SIOCGIFHWADDR) on interface `%.*s' failed: %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } memcpy (&dev->pl_mac, ifr.ifr_hwaddr.sa_data, MAC_ADDR_SIZE); dev->arptype_in = ifr.ifr_hwaddr.sa_family; if ((ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL)) { fprintf (stderr, "Unsupported hardware link type %d on interface `%.*s'\n", ifr.ifr_hwaddr.sa_family, IFNAMSIZ, dev->iface); return 1; } /* enable promiscuous mode */ memset (&mr, 0, sizeof (mr)); mr.mr_ifindex = sll.sll_ifindex; mr.mr_type = PACKET_MR_PROMISC; if (0 != setsockopt (dev->fd_raw, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof (mr))) { fprintf (stderr, "Failed to enable promiscuous mode on interface `%.*s'\n", IFNAMSIZ, dev->iface); return 1; } return 0; } /** * Test if the given interface name really corresponds to a wireless * device. * * @param iface name of the interface * @return 0 on success, 1 on error */ static int test_wlan_interface (const char *iface) { char strbuf[512]; struct stat sbuf; int ret; ret = snprintf (strbuf, sizeof (strbuf), "/sys/class/net/%s/phy80211/subsystem", iface); if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf))) { fprintf (stderr, "Did not find 802.11 interface `%s'. Exiting.\n", iface); exit (1); } return 0; } /** * Test incoming packets mac for being our own. * * @param taIeeeHeader buffer of the packet * @param dev the Hardware_Infos struct * @return 0 if mac belongs to us, 1 if mac is for another target */ static int mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader, const struct HardwareInfos *dev) { static struct GNUNET_TRANSPORT_WLAN_MacAddress all_zeros; if ( (0 == memcmp (&taIeeeHeader->addr3, &all_zeros, MAC_ADDR_SIZE)) || (0 == memcmp (&taIeeeHeader->addr1, &all_zeros, MAC_ADDR_SIZE)) ) return 0; /* some drivers set no Macs, then assume it is all for us! */ if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE)) return 1; /* not a GNUnet ad-hoc package */ if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) || (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) ) return 0; /* for us, or broadcast */ return 1; /* not for us */ } /** * Set the wlan header to sane values to make attacks more difficult * * @param taIeeeHeader pointer to the header of the packet * @param dev pointer to the Hardware_Infos struct */ static void mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader, const struct HardwareInfos *dev) { taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA); taIeeeHeader->addr2 = dev->pl_mac; taIeeeHeader->addr3 = mac_bssid_gnunet; } /** * Process data from the stdin. Takes the message, prepends the * radiotap transmission header, forces the sender MAC to be correct * and puts it into our buffer for transmission to the kernel. * * @param cls pointer to the device struct ('struct HardwareInfos*') * @param hdr pointer to the start of the packet */ static void stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr) { struct HardwareInfos *dev = cls; const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header; struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *wlanheader; size_t sendsize; struct RadiotapTransmissionHeader rtheader; struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame etheader; sendsize = ntohs (hdr->size); if ( (sendsize < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) || (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) ) { fprintf (stderr, "Received malformed message\n"); exit (1); } sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame)); if (MAXLINE < sendsize) { fprintf (stderr, "Packet too big for buffer\n"); exit (1); } header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr; switch (dev->arptype_in) { case ARPHRD_IEEE80211_PRISM: case ARPHRD_IEEE80211_FULL: case ARPHRD_IEEE80211: rtheader.header.it_version = 0; rtheader.header.it_pad = 0; rtheader.header.it_len = GNUNET_htole16 (sizeof (rtheader)); rtheader.header.it_present = GNUNET_htole16 (IEEE80211_RADIOTAP_OUR_TRANSMISSION_HEADER_MASK); rtheader.rate = header->rate; rtheader.pad1 = 0; rtheader.txflags = GNUNET_htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80211_RADIOTAP_F_TX_NOSEQ); memcpy (write_pout.buf, &rtheader, sizeof (rtheader)); memcpy (&write_pout.buf[sizeof (rtheader)], &header->frame, sendsize); wlanheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf[sizeof (rtheader)]; /* payload contains MAC address, but we don't trust it, so we'll * overwrite it with OUR MAC address to prevent mischief */ mac_set (wlanheader, dev); write_pout.size = sendsize + sizeof (rtheader); break; case ARPHRD_ETHER: etheader.dst = header->frame.addr1; /* etheader.src = header->frame.addr2; --- untrusted input */ etheader.src = dev->pl_mac; etheader.type = htons (ETH_P_IP); memcpy (write_pout.buf, ðeader, sizeof (etheader)); memcpy (&write_pout.buf[sizeof (etheader)], &header[1], sendsize - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame)); write_pout.size = sendsize - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame) + sizeof (etheader); break; default: fprintf (stderr, "Unsupported ARPTYPE!\n"); break; } } /** * Main function of the helper. This code accesses a WLAN interface * in monitoring mode (layer 2) and then forwards traffic in both * directions between the WLAN interface and stdin/stdout of this * process. Error messages are written to stdout. * * @param argc number of arguments, must be 2 * @param argv arguments only argument is the name of the interface (i.e. 'mon0') * @return 0 on success (never happens, as we don't return unless aborted), 1 on error */ int main (int argc, char *argv[]) { struct HardwareInfos dev; char readbuf[MAXLINE]; int maxfd; fd_set rfds; fd_set wfds; int stdin_open; struct MessageStreamTokenizer *stdin_mst; int raw_eno; uid_t uid; /* assert privs so we can modify the firewall rules! */ uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, 0, 0)) { fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno)); return 254; } #else if (0 != seteuid (0)) { fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); return 254; } #endif /* make use of SGID capabilities on POSIX */ memset (&dev, 0, sizeof (dev)); dev.fd_raw = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL)); raw_eno = errno; /* remember for later */ /* now that we've dropped root rights, we can do error checking */ if (2 != argc) { fprintf (stderr, "You must specify the name of the interface as the first and only argument to this program.\n"); if (-1 != dev.fd_raw) (void) close (dev.fd_raw); return 1; } if (-1 == dev.fd_raw) { fprintf (stderr, "Failed to create raw socket: %s\n", strerror (raw_eno)); return 1; } if (dev.fd_raw >= FD_SETSIZE) { fprintf (stderr, "File descriptor too large for select (%d > %d)\n", dev.fd_raw, FD_SETSIZE); (void) close (dev.fd_raw); return 1; } if (0 != test_wlan_interface (argv[1])) { (void) close (dev.fd_raw); return 1; } strncpy (dev.iface, argv[1], IFNAMSIZ); if (0 != open_device_raw (&dev)) { (void) close (dev.fd_raw); return 1; } /* drop privs */ { uid_t uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); if (-1 != dev.fd_raw) (void) close (dev.fd_raw); return 1; } #else if (0 != (setuid (uid) | seteuid (uid))) { fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); if (-1 != dev.fd_raw) (void) close (dev.fd_raw); return 1; } #endif } /* send MAC address of the WLAN interface to STDOUT first */ { struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg; macmsg.hdr.size = htons (sizeof (macmsg)); macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL); memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)); memcpy (write_std.buf, &macmsg, sizeof (macmsg)); write_std.size = sizeof (macmsg); } stdin_mst = mst_create (&stdin_send_hw, &dev); stdin_open = 1; while (1) { maxfd = -1; FD_ZERO (&rfds); if ((0 == write_pout.size) && (1 == stdin_open)) { FD_SET (STDIN_FILENO, &rfds); maxfd = MAX (maxfd, STDIN_FILENO); } if (0 == write_std.size) { FD_SET (dev.fd_raw, &rfds); maxfd = MAX (maxfd, dev.fd_raw); } FD_ZERO (&wfds); if (0 < write_std.size) { FD_SET (STDOUT_FILENO, &wfds); maxfd = MAX (maxfd, STDOUT_FILENO); } if (0 < write_pout.size) { FD_SET (dev.fd_raw, &wfds); maxfd = MAX (maxfd, dev.fd_raw); } { int retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL); if ((-1 == retval) && (EINTR == errno)) continue; if (0 > retval) { fprintf (stderr, "select failed: %s\n", strerror (errno)); break; } } if (FD_ISSET (STDOUT_FILENO, &wfds)) { ssize_t ret = write (STDOUT_FILENO, write_std.buf + write_std.pos, write_std.size - write_std.pos); if (0 > ret) { fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno)); break; } write_std.pos += ret; if (write_std.pos == write_std.size) { write_std.pos = 0; write_std.size = 0; } } if (FD_ISSET (dev.fd_raw, &wfds)) { ssize_t ret = write (dev.fd_raw, write_pout.buf + write_std.pos, write_pout.size - write_pout.pos); if (0 > ret) { fprintf (stderr, "Failed to write to WLAN device: %s\n", strerror (errno)); break; } write_pout.pos += ret; if ((write_pout.pos != write_pout.size) && (0 != ret)) { /* we should not get partial sends with packet-oriented devices... */ fprintf (stderr, "Write error, partial send: %u/%u\n", (unsigned int) write_pout.pos, (unsigned int) write_pout.size); break; } if (write_pout.pos == write_pout.size) { write_pout.pos = 0; write_pout.size = 0; } } if (FD_ISSET (STDIN_FILENO, &rfds)) { ssize_t ret = read (STDIN_FILENO, readbuf, sizeof (readbuf)); if (0 > ret) { fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno)); break; } if (0 == ret) { /* stop reading... */ stdin_open = 0; } mst_receive (stdin_mst, readbuf, ret); } if (FD_ISSET (dev.fd_raw, &rfds)) { struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm; ssize_t ret; rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf; ret = linux_read (&dev, (unsigned char *) &rrm->frame, sizeof (write_std.buf) - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame), rrm); if (0 > ret) { fprintf (stderr, "Read error from raw socket: %s\n", strerror (errno)); break; } if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev))) { write_std.size = ret + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame); rrm->header.size = htons (write_std.size); rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER); } } } /* Error handling, try to clean up a bit at least */ mst_destroy (stdin_mst); (void) close (dev.fd_raw); return 1; /* we never exit 'normally' */ } /* end of gnunet-helper-transport-wlan.c */ gnunet-0.10.1/src/transport/plugin_transport_wlan.c0000644000175000017500000016123712316473377017463 00000000000000/* This file is part of GNUnet (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_wlan.c * @brief transport plugin for wlan * @author David Brodski * @author Christian Grothoff */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "plugin_transport_wlan.h" #include "gnunet_common.h" #include "gnunet_crypto_lib.h" #include "gnunet_fragmentation_lib.h" #include "gnunet_constants.h" #define LOG(kind,...) GNUNET_log_from (kind, "transport-wlan",__VA_ARGS__) #define PLUGIN_NAME "wlan" /** * Max size of packet (that we give to the WLAN driver for transmission) */ #define WLAN_MTU 1430 /** * time out of a mac endpoint */ #define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2) /** * We reduce the frequence of HELLO beacons in relation to * the number of MAC addresses currently visible to us. * This is the multiplication factor. */ #define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) /** * Maximum number of messages in defragmentation queue per MAC */ #define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 2 /** * Link layer control fields for better compatibility * (i.e. GNUnet over WLAN is not IP-over-WLAN). */ #define WLAN_LLC_DSAP_FIELD 0x1f #define WLAN_LLC_SSAP_FIELD 0x1f GNUNET_NETWORK_STRUCT_BEGIN /** * Header for messages which need fragmentation. This is the format of * a message we obtain AFTER defragmentation. We then need to check * the CRC and then tokenize the payload and pass it to the * 'receive' callback. */ struct WlanHeader { /** * Message type is GNUNET_MESSAGE_TYPE_WLAN_DATA. */ struct GNUNET_MessageHeader header; /** * CRC32 checksum (only over the payload), in NBO. */ uint32_t crc GNUNET_PACKED; /** * Sender of the message. */ struct GNUNET_PeerIdentity sender; /** * Target of the message. */ struct GNUNET_PeerIdentity target; /* followed by payload, possibly including multiple messages! */ }; struct WlanAddress { uint32_t options GNUNET_PACKED; struct GNUNET_TRANSPORT_WLAN_MacAddress mac; }; GNUNET_NETWORK_STRUCT_END /** * Information kept for each message that is yet to be fragmented and * transmitted. */ struct PendingMessage { /** * next entry in the DLL */ struct PendingMessage *next; /** * previous entry in the DLL */ struct PendingMessage *prev; /** * The pending message */ struct WlanHeader *msg; /** * Continuation function to call once the message * has been sent. Can be NULL if there is no * continuation to call. */ GNUNET_TRANSPORT_TransmitContinuation transmit_cont; /** * Cls for transmit_cont */ void *transmit_cont_cls; /** * Timeout task (for this message). */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; /** * Session handle for connections with other peers. */ struct Session { /** * To whom are we talking to (set to our identity * if we are still waiting for the welcome message) */ struct GNUNET_PeerIdentity target; /** * API requirement (must be first). */ struct SessionHeader header; /** * We keep all sessions in a DLL at their respective * 'struct MACEndpoint'. */ struct Session *next; /** * We keep all sessions in a DLL at their respective * 'struct MACEndpoint'. */ struct Session *prev; /** * MAC endpoint with the address of this peer. */ struct MacEndpoint *mac; /** * Address associated with this session and MAC endpoint */ struct GNUNET_HELLO_Address *address; /** * Head of messages currently pending for transmission to this peer. */ struct PendingMessage *pending_message_head; /** * Tail of messages currently pending for transmission to this peer. */ struct PendingMessage *pending_message_tail; /** * When should this session time out? */ struct GNUNET_TIME_Absolute timeout; /** * Timeout task (for the session). */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; /** * Struct for messages that are being fragmented in a MAC's transmission queue. */ struct FragmentMessage { /** * This is a doubly-linked list. */ struct FragmentMessage *next; /** * This is a doubly-linked list. */ struct FragmentMessage *prev; /** * MAC endpoint this message belongs to */ struct MacEndpoint *macendpoint; /** * Fragmentation context */ struct GNUNET_FRAGMENT_Context *fragcontext; /** * Transmission handle to helper (to cancel if the frag context * is destroyed early for some reason). */ struct GNUNET_HELPER_SendHandle *sh; /** * Intended recipient. */ struct GNUNET_PeerIdentity target; /** * Timeout value for the message. */ struct GNUNET_TIME_Absolute timeout; /** * Timeout task. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Continuation to call when we're done with this message. */ GNUNET_TRANSPORT_TransmitContinuation cont; /** * Closure for 'cont' */ void *cont_cls; /** * Size of original message */ size_t size_payload; /** * Number of bytes used to transmit message */ size_t size_on_wire; }; /** * Struct to represent one network card connection */ struct MacEndpoint { /** * We keep all MACs in a DLL in the plugin. */ struct MacEndpoint *next; /** * We keep all MACs in a DLL in the plugin. */ struct MacEndpoint *prev; /** * Pointer to the global plugin struct. */ struct Plugin *plugin; /** * Head of sessions that use this MAC. */ struct Session *sessions_head; /** * Tail of sessions that use this MAC. */ struct Session *sessions_tail; /** * Head of messages we are currently sending to this MAC. */ struct FragmentMessage *sending_messages_head; /** * Tail of messages we are currently sending to this MAC. */ struct FragmentMessage *sending_messages_tail; /** * Defrag context for this MAC */ struct GNUNET_DEFRAGMENT_Context *defrag; /** * When should this endpoint time out? */ struct GNUNET_TIME_Absolute timeout; /** * Timeout task. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * count of messages in the fragment out queue for this mac endpoint */ unsigned int fragment_messages_out_count; /** * peer MAC address */ struct WlanAddress wlan_addr; /** * Message delay for fragmentation context */ struct GNUNET_TIME_Relative msg_delay; /** * ACK delay for fragmentation context */ struct GNUNET_TIME_Relative ack_delay; /** * Desired transmission power for this MAC */ uint16_t tx_power; /** * Desired transmission rate for this MAC */ uint8_t rate; /** * Antenna we should use for this MAC */ uint8_t antenna; }; /** * Encapsulation of all of the state of the plugin. */ struct Plugin { /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * Handle to helper process for priviledged operations. */ struct GNUNET_HELPER_Handle *suid_helper; /** * ARGV-vector for the helper (all helpers take only the binary * name, one actual argument, plus the NULL terminator for 'argv'). */ char * helper_argv[3]; /** * The interface of the wlan card given to us by the user. */ char *interface; /** * Tokenizer for demultiplexing of data packets resulting from defragmentation. */ struct GNUNET_SERVER_MessageStreamTokenizer *fragment_data_tokenizer; /** * Tokenizer for demultiplexing of data packets received from the suid helper */ struct GNUNET_SERVER_MessageStreamTokenizer *helper_payload_tokenizer; /** * Tokenizer for demultiplexing of data packets that follow the WLAN Header */ struct GNUNET_SERVER_MessageStreamTokenizer *wlan_header_payload_tokenizer; /** * Head of list of open connections. */ struct MacEndpoint *mac_head; /** * Tail of list of open connections. */ struct MacEndpoint *mac_tail; /** * Number of connections */ unsigned int mac_count; /** * Task that periodically sends a HELLO beacon via the helper. */ GNUNET_SCHEDULER_TaskIdentifier beacon_task; /** * Tracker for bandwidth limit */ struct GNUNET_BANDWIDTH_Tracker tracker; /** * The mac_address of the wlan card given to us by the helper. */ struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address; /** * Have we received a control message with our MAC address yet? */ int have_mac; /** * Options for addresses */ uint32_t options; }; /** * Information associated with a message. Can contain * the session or the MAC endpoint associated with the * message (or both). */ struct MacAndSession { /** * NULL if the identity of the other peer is not known. */ struct Session *session; /** * MAC address of the other peer, NULL if not known. */ struct MacEndpoint *endpoint; }; /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ static const char * wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen); /** * Print MAC addresses nicely. * * @param mac the mac address * @return string to a static buffer with the human-readable mac, will be overwritten during the next call to this function */ static const char * mac_to_string (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac) { static char macstr[20]; GNUNET_snprintf (macstr, sizeof (macstr), "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3], mac->mac[4], mac->mac[5]); return macstr; } /** * Fill the radiotap header * * @param endpoint pointer to the endpoint, can be NULL * @param header pointer to the radiotap header * @param size total message size */ static void get_radiotap_header (struct MacEndpoint *endpoint, struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header, uint16_t size) { header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER); header->header.size = ntohs (size); if (NULL != endpoint) { header->rate = endpoint->rate; header->tx_power = endpoint->tx_power; header->antenna = endpoint->antenna; } else { header->rate = 255; header->tx_power = 0; header->antenna = 0; } } /** * Generate the WLAN hardware header for one packet * * @param plugin the plugin handle * @param header address to write the header to * @param to_mac_addr address of the recipient * @param size size of the whole packet, needed to calculate the time to send the packet */ static void get_wlan_header (struct Plugin *plugin, struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *header, const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr, unsigned int size) { const int rate = 11000000; header->frame_control = htons (IEEE80211_FC0_TYPE_DATA); header->addr1 = *to_mac_addr; header->addr2 = plugin->mac_address; header->addr3 = mac_bssid_gnunet; header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290); header->sequence_control = 0; // FIXME? header->llc[0] = WLAN_LLC_DSAP_FIELD; header->llc[1] = WLAN_LLC_SSAP_FIELD; header->llc[2] = 0; // FIXME? header->llc[3] = 0; // FIXME? } /** * Send an ACK for a fragment we received. * * @param cls the 'struct MacEndpoint' the ACK must be sent to * @param msg_id id of the message * @param hdr pointer to the hdr where the ack is stored */ static void send_ack (void *cls, uint32_t msg_id, const struct GNUNET_MessageHeader *hdr) { struct MacEndpoint *endpoint = cls; struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage* radio_header; uint16_t msize = ntohs (hdr->size); size_t size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize; char buf[size]; if (NULL == endpoint) { GNUNET_break (0); return; } if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK to helper\n"); radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf; get_radiotap_header (endpoint, radio_header, size); get_wlan_header (endpoint->plugin, &radio_header->frame, &endpoint->wlan_addr.mac, sizeof (endpoint->wlan_addr.mac)); memcpy (&radio_header[1], hdr, msize); if (NULL != GNUNET_HELPER_send (endpoint->plugin->suid_helper, &radio_header->header, GNUNET_NO /* dropping ACKs is bad */, NULL, NULL)) GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN ACKs sent"), 1, GNUNET_NO); } /** * Handles the data after all fragments are put together * * @param cls macendpoint this messages belongs to * @param hdr pointer to the data */ static void wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr) { struct MacEndpoint *endpoint = cls; struct Plugin *plugin = endpoint->plugin; struct MacAndSession mas; GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN messages defragmented"), 1, GNUNET_NO); mas.session = NULL; mas.endpoint = endpoint; (void) GNUNET_SERVER_mst_receive (plugin->fragment_data_tokenizer, &mas, (const char *) hdr, ntohs (hdr->size), GNUNET_YES, GNUNET_NO); } /** * Free a session * * @param cls our `struct Plugin`. * @param session the session free */ static int wlan_plugin_disconnect_session (void *cls, struct Session *session) { struct MacEndpoint *endpoint = session->mac; struct PendingMessage *pm; endpoint->plugin->env->session_end (endpoint->plugin->env->cls, session->address, session); while (NULL != (pm = session->pending_message_head)) { GNUNET_CONTAINER_DLL_remove (session->pending_message_head, session->pending_message_tail, pm); if (GNUNET_SCHEDULER_NO_TASK != pm->timeout_task) { GNUNET_SCHEDULER_cancel (pm->timeout_task); pm->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (pm->msg); GNUNET_free (pm); } GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, endpoint->sessions_tail, session); if (session->timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (session->timeout_task); session->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN sessions allocated"), -1, GNUNET_NO); GNUNET_HELLO_address_free (session->address); GNUNET_free (session); return GNUNET_OK; } /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int wlan_plugin_query_keepalive_factor (void *cls) { return 3; } /** * A session is timing out. Clean up. * * @param cls pointer to the Session * @param tc pointer to the GNUNET_SCHEDULER_TaskContext */ static void session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *session = cls; struct GNUNET_TIME_Relative timeout; session->timeout_task = GNUNET_SCHEDULER_NO_TASK; timeout = GNUNET_TIME_absolute_get_remaining (session->timeout); if (0 == timeout.rel_value_us) { wlan_plugin_disconnect_session (session->mac->plugin, session); return; } session->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &session_timeout, session); } /** * Lookup a new session * * @param endpoint pointer to the mac endpoint of the peer * @param peer peer identity to use for this session * @return returns the session or NULL */ static struct Session * lookup_session (struct MacEndpoint *endpoint, const struct GNUNET_PeerIdentity *peer) { struct Session *session; for (session = endpoint->sessions_head; NULL != session; session = session->next) if (0 == memcmp (peer, &session->target, sizeof (struct GNUNET_PeerIdentity))) { session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); return session; } return NULL; } /** * Create a new session * * @param endpoint pointer to the mac endpoint of the peer * @param peer peer identity to use for this session * @return returns the session or NULL */ static struct Session * create_session (struct MacEndpoint *endpoint, const struct GNUNET_PeerIdentity *peer) { struct Session *session; GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN sessions allocated"), 1, GNUNET_NO); session = GNUNET_new (struct Session); GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head, endpoint->sessions_tail, session); session->address = GNUNET_HELLO_address_allocate (peer, PLUGIN_NAME, &endpoint->wlan_addr, sizeof (endpoint->wlan_addr), GNUNET_HELLO_ADDRESS_INFO_NONE); session->mac = endpoint; session->target = *peer; session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); session->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session); LOG (GNUNET_ERROR_TYPE_DEBUG, "Created new session %p for peer `%s' with endpoint %s\n", session, GNUNET_i2s (peer), mac_to_string (&endpoint->wlan_addr.mac)); return session; } /** * Look up a session for a peer and create a new session if none is found * * @param endpoint pointer to the mac endpoint of the peer * @param peer peer identity to use for this session * @return returns the session */ static struct Session * get_session (struct MacEndpoint *endpoint, const struct GNUNET_PeerIdentity *peer) { struct Session *session; if (NULL != (session = lookup_session (endpoint, peer))) return session; return create_session (endpoint, peer); } /** * Function called once we have successfully given the fragment * message to the SUID helper process and we are thus ready for * the next fragment. * * @param cls the 'struct FragmentMessage' * @param result result of the operation (#GNUNET_OK on success, #GNUNET_NO if the helper died, #GNUNET_SYSERR * if the helper was stopped) */ static void fragment_transmission_done (void *cls, int result) { struct FragmentMessage *fm = cls; fm->sh = NULL; GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext); } /** * Transmit a fragment of a message. * * @param cls 'struct FragmentMessage' this fragment message belongs to * @param hdr pointer to the start of the fragment message */ static void transmit_fragment (void *cls, const struct GNUNET_MessageHeader *hdr) { struct FragmentMessage *fm = cls; struct MacEndpoint *endpoint = fm->macendpoint; size_t size; uint16_t msize; if (NULL == endpoint) { GNUNET_break (0); return; } msize = ntohs (hdr->size); size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize; { char buf[size]; struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radio_header; radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf; get_radiotap_header (endpoint, radio_header, size); get_wlan_header (endpoint->plugin, &radio_header->frame, &endpoint->wlan_addr.mac, sizeof (endpoint->wlan_addr.mac)); memcpy (&radio_header[1], hdr, msize); GNUNET_assert (NULL == fm->sh); fm->sh = GNUNET_HELPER_send (endpoint->plugin->suid_helper, &radio_header->header, GNUNET_NO, &fragment_transmission_done, fm); fm->size_on_wire += size; if (NULL != fm->sh) GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN message fragments sent"), 1, GNUNET_NO); else GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext); GNUNET_STATISTICS_update (endpoint->plugin->env->stats, "# bytes currently in WLAN buffers", -msize, GNUNET_NO); GNUNET_STATISTICS_update (endpoint->plugin->env->stats, "# bytes transmitted via WLAN", msize, GNUNET_NO); } } /** * Frees the space of a message in the fragment queue (send queue) * * @param fm message to free */ static void free_fragment_message (struct FragmentMessage *fm) { struct MacEndpoint *endpoint = fm->macendpoint; GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN messages pending (with fragmentation)"), -1, GNUNET_NO); GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head, endpoint->sending_messages_tail, fm); if (NULL != fm->sh) { GNUNET_HELPER_send_cancel (fm->sh); fm->sh = NULL; } GNUNET_FRAGMENT_context_destroy (fm->fragcontext, &endpoint->msg_delay, &endpoint->ack_delay); if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (fm->timeout_task); fm->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (fm); } /** * A FragmentMessage has timed out. Remove it. * * @param cls pointer to the 'struct FragmentMessage' * @param tc pointer to the GNUNET_SCHEDULER_TaskContext */ static void fragmentmessage_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct FragmentMessage *fm = cls; fm->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != fm->cont) { fm->cont (fm->cont_cls, &fm->target, GNUNET_SYSERR, fm->size_payload, fm->size_on_wire); fm->cont = NULL; } free_fragment_message (fm); } /** * Transmit a message to the given destination with fragmentation. * * @param endpoint desired destination * @param timeout how long can the message wait? * @param target peer that should receive the message * @param msg message to transmit * @param payload_size bytes of payload * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for cont */ static void send_with_fragmentation (struct MacEndpoint *endpoint, struct GNUNET_TIME_Relative timeout, const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, size_t payload_size, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct FragmentMessage *fm; struct Plugin *plugin; plugin = endpoint->plugin; fm = GNUNET_new (struct FragmentMessage); fm->macendpoint = endpoint; fm->target = *target; fm->size_payload = payload_size; fm->size_on_wire = 0; fm->timeout = GNUNET_TIME_relative_to_absolute (timeout); fm->cont = cont; fm->cont_cls = cont_cls; /* 1 MBit/s typical data rate, 1430 byte fragments => ~100 ms per message */ fm->fragcontext = GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU, &plugin->tracker, endpoint->msg_delay, endpoint->ack_delay, msg, &transmit_fragment, fm); fm->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &fragmentmessage_timeout, fm); GNUNET_CONTAINER_DLL_insert_tail (endpoint->sending_messages_head, endpoint->sending_messages_tail, fm); } /** * Free a MAC endpoint. * * @param endpoint pointer to the MacEndpoint to free */ static void free_macendpoint (struct MacEndpoint *endpoint) { struct Plugin *plugin = endpoint->plugin; struct FragmentMessage *fm; struct Session *session; GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN MAC endpoints allocated"), -1, GNUNET_NO); while (NULL != (session = endpoint->sessions_head)) wlan_plugin_disconnect_session (plugin, session); while (NULL != (fm = endpoint->sending_messages_head)) free_fragment_message (fm); GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint); if (NULL != endpoint->defrag) { GNUNET_DEFRAGMENT_context_destroy(endpoint->defrag); endpoint->defrag = NULL; } plugin->mac_count--; if (GNUNET_SCHEDULER_NO_TASK != endpoint->timeout_task) { GNUNET_SCHEDULER_cancel (endpoint->timeout_task); endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (endpoint); } /** * A MAC endpoint is timing out. Clean up. * * @param cls pointer to the MacEndpoint * @param tc pointer to the GNUNET_SCHEDULER_TaskContext */ static void macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MacEndpoint *endpoint = cls; struct GNUNET_TIME_Relative timeout; endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK; timeout = GNUNET_TIME_absolute_get_remaining (endpoint->timeout); if (0 == timeout.rel_value_us) { free_macendpoint (endpoint); return; } endpoint->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &macendpoint_timeout, endpoint); } /** * Find (or create) a MacEndpoint with a specific MAC address * * @param plugin pointer to the plugin struct * @param mac the MAC address of the endpoint * @return handle to our data structure for this MAC */ static struct MacEndpoint * create_macendpoint (struct Plugin *plugin, struct WlanAddress *mac) { struct MacEndpoint *pos; for (pos = plugin->mac_head; NULL != pos; pos = pos->next) { if (0 == memcmp (mac, &pos->wlan_addr, sizeof (pos->wlan_addr))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing MAC endpoint `%s'\n", wlan_plugin_address_to_string(NULL, &pos->wlan_addr.mac, sizeof (pos->wlan_addr))); return pos; } } pos = GNUNET_new (struct MacEndpoint); pos->wlan_addr = (*mac); pos->plugin = plugin; pos->defrag = GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU, MESSAGES_IN_DEFRAG_QUEUE_PER_MAC, pos, &wlan_data_message_handler, &send_ack); pos->msg_delay = GNUNET_TIME_UNIT_MILLISECONDS; pos->ack_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); pos->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT); pos->timeout_task = GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout, pos); GNUNET_CONTAINER_DLL_insert (plugin->mac_head, plugin->mac_tail, pos); plugin->mac_count++; GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN MAC endpoints allocated"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "New MAC endpoint `%s'\n", wlan_plugin_address_to_string(NULL, &pos->wlan_addr, sizeof (struct WlanAddress))); return pos; } /** * Function obtain the network type for a session * * @param cls closure ('struct Plugin*') * @param session the session * @return the network type in HBO or GNUNET_SYSERR */ static enum GNUNET_ATS_Network_Type wlan_get_network (void *cls, struct Session *session) { GNUNET_assert (NULL != session); return GNUNET_ATS_NET_WLAN; } /** * Creates a new outbound session the transport service will use to send data to the * peer * * @param cls the plugin * @param address the address * @return the session or NULL of max connections exceeded */ static struct Session * wlan_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct Plugin *plugin = cls; struct MacEndpoint *endpoint; if (NULL == address) return NULL; if (sizeof (struct WlanAddress) != address->address_length) { GNUNET_break (0); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Service asked to create session for peer `%s' with MAC `%s'\n", GNUNET_i2s (&address->peer), wlan_plugin_address_to_string(NULL, address->address, address->address_length)); endpoint = create_macendpoint (plugin, (struct WlanAddress *) address->address); return get_session (endpoint, &address->peer); } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuation). * * @param cls closure * @param target peer from which to disconnect */ static void wlan_plugin_disconnect_peer (void *cls, const struct GNUNET_PeerIdentity *target) { struct Plugin *plugin = cls; struct Session *session; struct MacEndpoint *endpoint; for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = endpoint->next) for (session = endpoint->sessions_head; NULL != session; session = session->next) if (0 == memcmp (target, &session->target, sizeof (struct GNUNET_PeerIdentity))) { wlan_plugin_disconnect_session (plugin, session); break; /* inner-loop only (in case peer has another MAC as well!) */ } } /** * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param session which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in 'msgbuf' * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t wlan_plugin_send (void *cls, struct Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin *plugin = cls; struct WlanHeader *wlanheader; size_t size = msgbuf_size + sizeof (struct WlanHeader); char buf[size] GNUNET_ALIGN; LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes of payload to peer `%s' (starting with %u byte message of type %u)\n", msgbuf_size, GNUNET_i2s (&session->target), (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->size), (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->type)); wlanheader = (struct WlanHeader *) buf; wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader)); wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA); wlanheader->sender = *plugin->env->my_identity; wlanheader->target = session->target; wlanheader->crc = htonl (GNUNET_CRYPTO_crc32_n (msgbuf, msgbuf_size)); memcpy (&wlanheader[1], msgbuf, msgbuf_size); GNUNET_STATISTICS_update (plugin->env->stats, "# bytes currently in WLAN buffers", msgbuf_size, GNUNET_NO); send_with_fragmentation (session->mac, to, &session->target, &wlanheader->header, msgbuf_size, cont, cont_cls); return size; } /** * We have received data from the WLAN via some session. Process depending * on the message type (HELLO, DATA, FRAGMENTATION or FRAGMENTATION-ACK). * * @param cls pointer to the plugin * @param client pointer to the session this message belongs to * @param hdr start of the message */ static int process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr) { struct Plugin *plugin = cls; struct GNUNET_HELLO_Address *address; struct MacAndSession *mas = client; struct MacAndSession xmas; struct GNUNET_ATS_Information ats; struct FragmentMessage *fm; struct GNUNET_PeerIdentity tmpsource; const struct WlanHeader *wlanheader; int ret; uint16_t msize; ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.value = htonl (GNUNET_ATS_NET_WLAN); msize = ntohs (hdr->size); GNUNET_STATISTICS_update (plugin->env->stats, "# bytes received via WLAN", msize, GNUNET_NO); switch (ntohs (hdr->type)) { case GNUNET_MESSAGE_TYPE_HELLO: if (GNUNET_OK != GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource)) { GNUNET_break_op (0); break; } if (NULL == mas->endpoint) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing %u bytes of HELLO from peer `%s' at MAC %s\n", (unsigned int) msize, GNUNET_i2s (&tmpsource), wlan_plugin_address_to_string (NULL, &mas->endpoint->wlan_addr, sizeof (mas->endpoint->wlan_addr))); GNUNET_STATISTICS_update (plugin->env->stats, _("# HELLO messages received via WLAN"), 1, GNUNET_NO); address = GNUNET_HELLO_address_allocate (&tmpsource, PLUGIN_NAME, &mas->endpoint->wlan_addr, sizeof (mas->endpoint->wlan_addr), GNUNET_HELLO_ADDRESS_INFO_INBOUND); plugin->env->receive (plugin->env->cls, address, mas->session, hdr); plugin->env->update_address_metrics (plugin->env->cls, address, mas->session, &ats, 1); GNUNET_HELLO_address_free (address); break; case GNUNET_MESSAGE_TYPE_FRAGMENT: if (NULL == mas->endpoint) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing %u bytes of FRAGMENT from MAC %s\n", (unsigned int) msize, wlan_plugin_address_to_string (NULL, &mas->endpoint->wlan_addr, sizeof (mas->endpoint->wlan_addr))); GNUNET_STATISTICS_update (plugin->env->stats, _("# fragments received via WLAN"), 1, GNUNET_NO); (void) GNUNET_DEFRAGMENT_process_fragment (mas->endpoint->defrag, hdr); break; case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK: if (NULL == mas->endpoint) { GNUNET_break (0); break; } GNUNET_STATISTICS_update (plugin->env->stats, _("# ACKs received via WLAN"), 1, GNUNET_NO); for (fm = mas->endpoint->sending_messages_head; NULL != fm; fm = fm->next) { ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr); if (GNUNET_OK == ret) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Got last ACK, finished message transmission to `%s' (%p)\n", wlan_plugin_address_to_string (NULL, &mas->endpoint->wlan_addr, sizeof (mas->endpoint->wlan_addr)), fm); mas->endpoint->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT); if (NULL != fm->cont) { fm->cont (fm->cont_cls, &fm->target, GNUNET_OK, fm->size_payload, fm->size_on_wire); fm->cont = NULL; } free_fragment_message (fm); break; } if (GNUNET_NO == ret) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK, message transmission to `%s' not yet finished\n", wlan_plugin_address_to_string (NULL, &mas->endpoint->wlan_addr, sizeof (mas->endpoint->wlan_addr))); break; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK not matched against any active fragmentation with MAC `%s'\n", wlan_plugin_address_to_string (NULL, &mas->endpoint->wlan_addr, sizeof (mas->endpoint->wlan_addr))); break; case GNUNET_MESSAGE_TYPE_WLAN_DATA: if (NULL == mas->endpoint) { GNUNET_break (0); break; } if (msize < sizeof (struct WlanHeader)) { GNUNET_break (0); break; } wlanheader = (const struct WlanHeader *) hdr; if (0 != memcmp (&wlanheader->target, plugin->env->my_identity, sizeof (struct GNUNET_PeerIdentity))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "WLAN data for `%s', not for me, ignoring\n", GNUNET_i2s (&wlanheader->target)); break; } if (ntohl (wlanheader->crc) != GNUNET_CRYPTO_crc32_n (&wlanheader[1], msize - sizeof (struct WlanHeader))) { GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN DATA messages discarded due to CRC32 error"), 1, GNUNET_NO); break; } xmas.endpoint = mas->endpoint; if (NULL == (xmas.session = lookup_session (mas->endpoint, &wlanheader->sender))) { xmas.session = create_session (mas->endpoint, &wlanheader->sender); address = GNUNET_HELLO_address_allocate (&wlanheader->sender, PLUGIN_NAME, &mas->endpoint->wlan_addr, sizeof (struct WlanAddress), GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->session_start (NULL, address, xmas.session, NULL, 0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Notifying transport about peer `%s''s new session %p \n", GNUNET_i2s (&wlanheader->sender), xmas.session); GNUNET_HELLO_address_free (address); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing %u bytes of WLAN DATA from peer `%s'\n", (unsigned int) msize, GNUNET_i2s (&wlanheader->sender)); (void) GNUNET_SERVER_mst_receive (plugin->wlan_header_payload_tokenizer, &xmas, (const char *) &wlanheader[1], msize - sizeof (struct WlanHeader), GNUNET_YES, GNUNET_NO); break; default: if (NULL == mas->endpoint) { GNUNET_break (0); break; } if (NULL == mas->session) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received packet with %u bytes of type %u from peer %s\n", (unsigned int) msize, (unsigned int) ntohs (hdr->type), GNUNET_i2s (&mas->session->target)); plugin->env->receive (plugin->env->cls, mas->session->address, mas->session, hdr); plugin->env->update_address_metrics (plugin->env->cls, mas->session->address, mas->session, &ats, 1); break; } return GNUNET_OK; } /** * Function used for to process the data from the suid process * * @param cls the plugin handle * @param client client that send the data (not used) * @param hdr header of the GNUNET_MessageHeader */ static int handle_helper_message (void *cls, void *client, const struct GNUNET_MessageHeader *hdr) { struct Plugin *plugin = cls; struct GNUNET_HELLO_Address *my_address; const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo; const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm; struct WlanAddress wa; struct MacAndSession mas; uint16_t msize; msize = ntohs (hdr->size); switch (ntohs (hdr->type)) { case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL: if (msize != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage)) { GNUNET_break (0); break; } cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr; if (GNUNET_YES == plugin->have_mac) { if (0 == memcmp (&plugin->mac_address, &cm->mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) break; /* no change */ /* remove old address */ memset (&wa, 0, sizeof (struct WlanAddress)); wa.mac = plugin->mac_address; wa.options = htonl(plugin->options); my_address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, &wa, sizeof (wa), GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->notify_address (plugin->env->cls, GNUNET_NO, my_address); GNUNET_HELLO_address_free (my_address); } plugin->mac_address = cm->mac; plugin->have_mac = GNUNET_YES; memset (&wa, 0, sizeof (struct WlanAddress)); wa.mac = plugin->mac_address; wa.options = htonl(plugin->options); my_address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, &wa, sizeof (wa), GNUNET_HELLO_ADDRESS_INFO_NONE); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received WLAN_HELPER_CONTROL message with MAC address `%s' for peer `%s'\n", mac_to_string (&cm->mac), GNUNET_i2s (plugin->env->my_identity)); plugin->env->notify_address (plugin->env->cls, GNUNET_YES, my_address); GNUNET_HELLO_address_free (my_address); break; case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER: LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data message from helper with %u bytes\n", msize); GNUNET_STATISTICS_update (plugin->env->stats, _("# DATA messages received via WLAN"), 1, GNUNET_NO); if (msize < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Size of packet is too small (%u bytes)\n", msize); break; } rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr; /* check if message is actually for us */ if (0 != memcmp (&rxinfo->frame.addr3, &mac_bssid_gnunet, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) { /* Not the GNUnet BSSID */ break; } if ( (0 != memcmp (&rxinfo->frame.addr1, &bc_all_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) && (0 != memcmp (&rxinfo->frame.addr1, &plugin->mac_address, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) ) { /* Neither broadcast nor specifically for us */ break; } if (0 == memcmp (&rxinfo->frame.addr2, &plugin->mac_address, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) { /* packet is FROM us, thus not FOR us */ break; } GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN DATA messages processed"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving %u bytes of data from MAC `%s'\n", (unsigned int) (msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)), mac_to_string (&rxinfo->frame.addr2)); wa.mac = rxinfo->frame.addr2; wa.options = htonl (0); mas.endpoint = create_macendpoint (plugin, &wa); mas.session = NULL; (void) GNUNET_SERVER_mst_receive (plugin->helper_payload_tokenizer, &mas, (const char*) &rxinfo[1], msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage), GNUNET_YES, GNUNET_NO); break; default: GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Unexpected message of type %u (%u bytes)", ntohs (hdr->type), ntohs (hdr->size)); break; } return GNUNET_OK; } /** * Task to (periodically) send a HELLO beacon * * @param cls pointer to the plugin struct * @param tc scheduler context */ static void send_hello_beacon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Plugin *plugin = cls; uint16_t size; uint16_t hello_size; struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader; const struct GNUNET_MessageHeader *hello; hello = plugin->env->get_our_hello (); hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello); GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU); size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + hello_size; { char buf[size] GNUNET_ALIGN; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending %u byte HELLO beacon\n", (unsigned int) size); radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) buf; get_radiotap_header (NULL, radioHeader, size); get_wlan_header (plugin, &radioHeader->frame, &bc_all_mac, size); memcpy (&radioHeader[1], hello, hello_size); if (NULL != GNUNET_HELPER_send (plugin->suid_helper, &radioHeader->header, GNUNET_YES /* can drop */, NULL, NULL)) GNUNET_STATISTICS_update (plugin->env->stats, _("# HELLO beacons sent via WLAN"), 1, GNUNET_NO); } plugin->beacon_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (HELLO_BEACON_SCALING_FACTOR, plugin->mac_count + 1), &send_hello_beacon, plugin); } /** * Another peer has suggested an address for this * peer and transport plugin. Check that this could be a valid * address. If so, consider adding it to the list * of addresses. * * @param cls closure * @param addr pointer to the address * @param addrlen length of addr * @return GNUNET_OK if this is a plausible address for this peer * and transport */ static int wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) { struct Plugin *plugin = cls; struct WlanAddress *wa = (struct WlanAddress *) addr; if (addrlen != sizeof (struct WlanAddress)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_YES != plugin->have_mac) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Rejecting MAC `%s': I don't know my MAC!\n", mac_to_string (addr)); return GNUNET_NO; /* don't know my MAC */ } if (0 != memcmp (&wa->mac, &plugin->mac_address, sizeof (wa->mac))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Rejecting MAC `%s': not my MAC!\n", mac_to_string (addr)); return GNUNET_NO; /* not my MAC */ } return GNUNET_OK; } /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ static const char * wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) { const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac; static char macstr[36]; if (sizeof (struct WlanAddress) != addrlen) { GNUNET_break (0); return NULL; } mac = &((struct WlanAddress *) addr)->mac; GNUNET_snprintf (macstr, sizeof (macstr), "%s.%u.%s", PLUGIN_NAME, ntohl (((struct WlanAddress *) addr)->options), mac_to_string (mac)); return macstr; } /** * Convert the transports address to a nice, human-readable format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the address * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for asc */ static void wlan_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { char *ret; if (sizeof (struct WlanAddress) != addrlen) { /* invalid address */ LOG (GNUNET_ERROR_TYPE_WARNING, _("WLAN address with invalid size encountered\n")); asc (asc_cls, NULL); return; } ret = GNUNET_strdup (wlan_plugin_address_to_string(NULL, addr, addrlen)); asc (asc_cls, ret); GNUNET_free (ret); asc (asc_cls, NULL); } /** * Exit point from the plugin. * * @param cls pointer to the api struct */ void * libgnunet_plugin_transport_wlan_done (void *cls) { struct WlanAddress wa; struct GNUNET_HELLO_Address *address; struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; struct MacEndpoint *endpoint; struct MacEndpoint *endpoint_next; if (NULL == plugin) { GNUNET_free (api); return NULL; } if (GNUNET_YES == plugin->have_mac) { memset (&wa, 0, sizeof(wa)); wa.options = htonl (plugin->options); wa.mac = plugin->mac_address; address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, &wa, sizeof (struct WlanAddress), GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->notify_address (plugin->env->cls, GNUNET_NO, address); plugin->have_mac = GNUNET_NO; GNUNET_HELLO_address_free (address); } if (GNUNET_SCHEDULER_NO_TASK != plugin->beacon_task) { GNUNET_SCHEDULER_cancel (plugin->beacon_task); plugin->beacon_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != plugin->suid_helper) { GNUNET_HELPER_stop (plugin->suid_helper, GNUNET_NO); plugin->suid_helper = NULL; } endpoint_next = plugin->mac_head; while (NULL != (endpoint = endpoint_next)) { endpoint_next = endpoint->next; free_macendpoint (endpoint); } if (NULL != plugin->fragment_data_tokenizer) { GNUNET_SERVER_mst_destroy (plugin->fragment_data_tokenizer); plugin->fragment_data_tokenizer = NULL; } if (NULL != plugin->wlan_header_payload_tokenizer) { GNUNET_SERVER_mst_destroy (plugin->wlan_header_payload_tokenizer); plugin->wlan_header_payload_tokenizer = NULL; } if (NULL != plugin->helper_payload_tokenizer) { GNUNET_SERVER_mst_destroy (plugin->helper_payload_tokenizer); plugin->helper_payload_tokenizer = NULL; } GNUNET_free_non_null (plugin->interface); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /** * Function called to convert a string address to * a binary address. * * @param cls closure ('struct Plugin*') * @param addr string address * @param addrlen length of the address * @param buf location to store the buffer * @param added location to store the number of bytes in the buffer. * If the function returns GNUNET_SYSERR, its contents are undefined. * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ static int wlan_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added) { struct WlanAddress *wa; unsigned int a[6]; unsigned int i; char plugin[5]; uint32_t options; if ((NULL == addr) || (addrlen == 0)) { GNUNET_break (0); return GNUNET_SYSERR; } if ('\0' != addr[addrlen - 1]) { GNUNET_break (0); return GNUNET_SYSERR; } if (strlen (addr) != addrlen - 1) { GNUNET_break (0); return GNUNET_SYSERR; } if (8 != SSCANF (addr, "%4s.%u.%X:%X:%X:%X:%X:%X", plugin, &options, &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])) { GNUNET_break (0); return GNUNET_SYSERR; } wa = GNUNET_new (struct WlanAddress); for (i=0;i<6;i++) wa->mac.mac[i] = a[i]; wa->options = htonl (0); *buf = wa; *added = sizeof (struct WlanAddress); return GNUNET_OK; } static void wlan_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { if (session->timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (session->timeout_task); session->timeout_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session); } /** * Entry point for the plugin. * * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*' * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error */ void * libgnunet_plugin_transport_wlan_init (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *plugin; char *interface; unsigned long long testmode; char *binary; /* check for 'special' mode */ if (NULL == env->receive) { /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully initialze the plugin or the API */ api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = NULL; api->address_pretty_printer = &wlan_plugin_address_pretty_printer; api->address_to_string = &wlan_plugin_address_to_string; api->string_to_address = &wlan_string_to_address; return api; } testmode = 0; /* check configuration */ if ( (GNUNET_YES == GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE")) && ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan", "TESTMODE", &testmode)) || (testmode > 2) ) ) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "transport-wlan", "TESTMODE"); return NULL; } binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-transport-wlan"); if ( (0 == testmode) && (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, NULL)) ) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Helper binary `%s' not SUID, cannot run WLAN transport\n"), "gnunet-helper-transport-wlan"); GNUNET_free (binary); return NULL; } GNUNET_free (binary); if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-wlan", "INTERFACE", &interface)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "transport-wlan", "INTERFACE"); return NULL; } plugin = GNUNET_new (struct Plugin); plugin->interface = interface; plugin->env = env; GNUNET_STATISTICS_set (plugin->env->stats, _("# WLAN sessions allocated"), 0, GNUNET_NO); GNUNET_STATISTICS_set (plugin->env->stats, _("# WLAN MAC endpoints allocated"), 0, 0); GNUNET_BANDWIDTH_tracker_init (&plugin->tracker, NULL, NULL, GNUNET_BANDWIDTH_value_init (100 * 1024 * 1024 / 8), 100); plugin->fragment_data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin); plugin->wlan_header_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin); plugin->helper_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin); plugin->beacon_task = GNUNET_SCHEDULER_add_now (&send_hello_beacon, plugin); plugin->options = 0; /* some compilers do not like switch on 'long long'... */ switch ((unsigned int) testmode) { case 0: /* normal */ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan"; plugin->helper_argv[1] = interface; plugin->helper_argv[2] = NULL; plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-transport-wlan", plugin->helper_argv, &handle_helper_message, NULL, plugin); break; case 1: /* testmode, peer 1 */ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy"; plugin->helper_argv[1] = (char *) "1"; plugin->helper_argv[2] = NULL; plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-transport-wlan-dummy", plugin->helper_argv, &handle_helper_message, NULL, plugin); break; case 2: /* testmode, peer 2 */ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy"; plugin->helper_argv[1] = (char *) "2"; plugin->helper_argv[2] = NULL; plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-transport-wlan-dummy", plugin->helper_argv, &handle_helper_message, NULL, plugin); break; default: GNUNET_assert (0); } api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = plugin; api->send = &wlan_plugin_send; api->get_session = &wlan_plugin_get_session; api->disconnect_peer = &wlan_plugin_disconnect_peer; api->disconnect_session = &wlan_plugin_disconnect_session; api->query_keepalive_factor = &wlan_plugin_query_keepalive_factor; api->address_pretty_printer = &wlan_plugin_address_pretty_printer; api->check_address = &wlan_plugin_address_suggested; api->address_to_string = &wlan_plugin_address_to_string; api->string_to_address = &wlan_string_to_address; api->get_network = &wlan_get_network; api->update_session_timeout = &wlan_plugin_update_session_timeout; return api; } /* end of plugin_transport_wlan.c */ gnunet-0.10.1/src/transport/gnunet-service-transport_clients.c0000644000175000017500000012725012316473377021536 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_clients.c * @brief plugin management API * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_clients.h" #include "gnunet-service-transport_hello.h" #include "gnunet-service-transport_neighbours.h" #include "gnunet-service-transport_plugins.h" #include "gnunet-service-transport_validation.h" #include "gnunet-service-transport_manipulation.h" #include "gnunet-service-transport.h" #include "transport.h" /** * How many messages can we have pending for a given client process * before we start to drop incoming messages? We typically should * have only one client and so this would be the primary buffer for * messages, so the number should be chosen rather generously. * * The expectation here is that most of the time the queue is large * enough so that a drop is virtually never required. Note that * this value must be about as large as 'TOTAL_MSGS' in the * 'test_transport_api_reliability.c', otherwise that testcase may * fail. */ #define MAX_PENDING (128 * 1024) /** * Linked list of messages to be transmitted to the client. Each * entry is followed by the actual message. */ struct ClientMessageQueueEntry { /** * This is a doubly-linked list. */ struct ClientMessageQueueEntry *next; /** * This is a doubly-linked list. */ struct ClientMessageQueueEntry *prev; }; /** * Client connected to the transport service. */ struct TransportClient { /** * This is a doubly-linked list. */ struct TransportClient *next; /** * This is a doubly-linked list. */ struct TransportClient *prev; /** * Handle to the client. */ struct GNUNET_SERVER_Client *client; /** * Linked list of messages yet to be transmitted to * the client. */ struct ClientMessageQueueEntry *message_queue_head; /** * Tail of linked list of messages yet to be transmitted to the * client. */ struct ClientMessageQueueEntry *message_queue_tail; /** * Current transmit request handle. */ struct GNUNET_SERVER_TransmitHandle *th; /** * Length of the list of messages pending for this client. */ unsigned int message_count; /** * Is this client interested in payload messages? */ int send_payload; }; /** * Context for address to string operations */ struct AddressToStringContext { /** * This is a doubly-linked list. */ struct AddressToStringContext *next; /** * This is a doubly-linked list. */ struct AddressToStringContext *prev; /** * Transmission context */ struct GNUNET_SERVER_TransmitContext* tc; }; /** * Client monitoring changes of active addresses of our neighbours. */ struct MonitoringClient { /** * This is a doubly-linked list. */ struct MonitoringClient *next; /** * This is a doubly-linked list. */ struct MonitoringClient *prev; /** * Handle to the client. */ struct GNUNET_SERVER_Client *client; /** * Peer identity to monitor the addresses of. * Zero to monitor all neighrours. */ struct GNUNET_PeerIdentity peer; }; /** * Head of linked list of all clients to this service. */ static struct TransportClient *clients_head; /** * Tail of linked list of all clients to this service. */ static struct TransportClient *clients_tail; /** * Head of linked list of all pending address iterations */ struct AddressToStringContext *a2s_head; /** * Tail of linked list of all pending address iterations */ struct AddressToStringContext *a2s_tail; /** * Head of linked list of monitoring clients. */ static struct MonitoringClient *peer_monitoring_clients_head; /** * Tail of linked list of monitoring clients. */ static struct MonitoringClient *peer_monitoring_clients_tail; /** * Head of linked list of validation monitoring clients. */ static struct MonitoringClient *val_monitoring_clients_head; /** * Tail of linked list of validation monitoring clients. */ static struct MonitoringClient *val_monitoring_clients_tail; /** * Notification context, to send updates on changes to active addresses * of our neighbours. */ static struct GNUNET_SERVER_NotificationContext *peer_nc; /** * Notification context, to send updates on changes to active addresses * of our neighbours. */ static struct GNUNET_SERVER_NotificationContext *val_nc; /** * Find the internal handle associated with the given client handle * * @param client server's client handle to look up * @return internal client handle */ static struct TransportClient * lookup_client (struct GNUNET_SERVER_Client *client) { struct TransportClient *tc; for (tc = clients_head; NULL != tc; tc = tc->next) if (tc->client == client) return tc; return NULL; } /** * Create the internal handle for the given server client handle * * @param client server's client handle to create our internal handle for * @return fresh internal client handle */ static struct TransportClient * setup_client (struct GNUNET_SERVER_Client *client) { struct TransportClient *tc; GNUNET_assert (NULL == lookup_client (client)); tc = GNUNET_new (struct TransportClient); tc->client = client; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc); return tc; } /** * Find the handle to the monitoring client associated with the given * client handle * * @param head the head of the client queue to look in * @param client server's client handle to look up * @return handle to the monitoring client */ static struct MonitoringClient * lookup_monitoring_client (struct MonitoringClient *head, struct GNUNET_SERVER_Client *client) { struct MonitoringClient *mc; for (mc = head; NULL != mc; mc = mc->next) if (mc->client == client) return mc; return NULL; } /** * Setup a new monitoring client using the given server client handle and * the peer identity. * * @param client server's client handle to create our internal handle for * @param peer identity of the peer to monitor the addresses of, * zero to monitor all neighrours. * @return handle to the new monitoring client */ static struct MonitoringClient * setup_peer_monitoring_client (struct GNUNET_SERVER_Client *client, struct GNUNET_PeerIdentity *peer) { struct MonitoringClient *mc; static struct GNUNET_PeerIdentity all_zeros; GNUNET_assert (lookup_monitoring_client (peer_monitoring_clients_head, client) == NULL); mc = GNUNET_new (struct MonitoringClient); mc->client = client; mc->peer = *peer; GNUNET_CONTAINER_DLL_insert (peer_monitoring_clients_head, peer_monitoring_clients_tail, mc); GNUNET_SERVER_notification_context_add (peer_nc, client); if (0 != memcmp (peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client %p started monitoring of the peer `%s'\n", mc, GNUNET_i2s (peer)); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client %p started monitoring all peers\n", mc); return mc; } /** * Setup a new monitoring client using the given server client handle and * the peer identity. * * @param client server's client handle to create our internal handle for * @param peer identity of the peer to monitor the addresses of, * zero to monitor all neighrours. * @return handle to the new monitoring client */ static struct MonitoringClient * setup_val_monitoring_client (struct GNUNET_SERVER_Client *client, struct GNUNET_PeerIdentity *peer) { struct MonitoringClient *mc; static struct GNUNET_PeerIdentity all_zeros; GNUNET_assert (lookup_monitoring_client (val_monitoring_clients_head, client) == NULL); mc = GNUNET_new (struct MonitoringClient); mc->client = client; mc->peer = *peer; GNUNET_CONTAINER_DLL_insert (val_monitoring_clients_head, val_monitoring_clients_tail, mc); GNUNET_SERVER_notification_context_add (val_nc, client); if (0 != memcmp (peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client %p started monitoring of the peer `%s'\n", mc, GNUNET_i2s (peer)); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Client %p started monitoring all peers\n", mc); return mc; } /** * Function called to notify a client about the socket being ready to * queue more data. "buf" will be NULL and "size" zero if the socket * was closed for writing in the meantime. * * @param cls closure * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ static size_t transmit_to_client_callback (void *cls, size_t size, void *buf) { struct TransportClient *tc = cls; struct ClientMessageQueueEntry *q; const struct GNUNET_MessageHeader *msg; char *cbuf; uint16_t msize; size_t tsize; tc->th = NULL; if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission to client failed, closing connection.\n"); return 0; } cbuf = buf; tsize = 0; while (NULL != (q = tc->message_queue_head)) { msg = (const struct GNUNET_MessageHeader *) &q[1]; msize = ntohs (msg->size); if (msize + tsize > size) break; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting message of type %u to client %p.\n", ntohs (msg->type), tc); GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail, q); tc->message_count--; memcpy (&cbuf[tsize], msg, msize); GNUNET_free (q); tsize += msize; } if (NULL != q) { GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader)); tc->th = GNUNET_SERVER_notify_transmit_ready (tc->client, msize, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_to_client_callback, tc); GNUNET_assert (NULL != tc->th); } return tsize; } /** * Queue the given message for transmission to the given client * * @param tc target of the message * @param msg message to transmit * @param may_drop #GNUNET_YES if the message can be dropped */ static void unicast (struct TransportClient *tc, const struct GNUNET_MessageHeader *msg, int may_drop) { struct ClientMessageQueueEntry *q; uint16_t msize; if (NULL == msg) { GNUNET_break (0); return; } if ((tc->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Dropping message of type %u and size %u, have %u/%u messages pending\n"), ntohs (msg->type), ntohs (msg->size), tc->message_count, MAX_PENDING); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# messages dropped due to slow client"), 1, GNUNET_NO); return; } msize = ntohs (msg->size); GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader)); q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize); memcpy (&q[1], msg, msize); GNUNET_CONTAINER_DLL_insert_tail (tc->message_queue_head, tc->message_queue_tail, q); tc->message_count++; if (NULL != tc->th) return; tc->th = GNUNET_SERVER_notify_transmit_ready (tc->client, msize, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_to_client_callback, tc); GNUNET_assert (NULL != tc->th); } /** * Called whenever a client is disconnected. Frees our * resources associated with that client. * * @param cls closure * @param client identification of the client */ static void client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) { struct TransportClient *tc; struct MonitoringClient *mc; struct ClientMessageQueueEntry *mqe; if (client == NULL) return; mc = lookup_monitoring_client (peer_monitoring_clients_head, client); if (mc != NULL) { GNUNET_CONTAINER_DLL_remove (peer_monitoring_clients_head, peer_monitoring_clients_tail, mc); GNUNET_free (mc); } mc = lookup_monitoring_client (val_monitoring_clients_head, client); if (mc != NULL) { GNUNET_CONTAINER_DLL_remove (val_monitoring_clients_head, val_monitoring_clients_tail, mc); GNUNET_free (mc); } tc = lookup_client (client); if (tc == NULL) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Client %p disconnected, cleaning up.\n", tc); while (NULL != (mqe = tc->message_queue_head)) { GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail, mqe); tc->message_count--; GNUNET_free (mqe); } GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc); if (tc->th != NULL) { GNUNET_SERVER_notify_transmit_ready_cancel (tc->th); tc->th = NULL; } GNUNET_break (0 == tc->message_count); GNUNET_free (tc); } /** * Function called for each of our connected neighbours. Notify the * client about the existing neighbour. * * @param cls the `struct TransportClient *` to notify * @param peer identity of the neighbour * @param address the address * @param state the current state of the peer * @param state_timeout the time out for the state * @param bandwidth_in inbound bandwidth in NBO * @param bandwidth_out outbound bandwidth in NBO */ static void notify_client_about_neighbour (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { struct TransportClient *tc = cls; struct ConnectInfoMessage *cim; size_t size = sizeof (struct ConnectInfoMessage); char buf[size] GNUNET_ALIGN; if (GNUNET_NO == GST_neighbours_test_connected (peer)) return; GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE); cim = (struct ConnectInfoMessage *) buf; cim->header.size = htons (size); cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); cim->id = *peer; cim->quota_in = bandwidth_in; cim->quota_out = bandwidth_out; unicast (tc, &cim->header, GNUNET_NO); } /** * Initialize a normal client. We got a start message from this * client, add him to the list of clients for broadcasting of inbound * messages. * * @param cls unused * @param client the client * @param message the start message that was sent */ static void clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct StartMessage *start; struct TransportClient *tc; uint32_t options; tc = lookup_client (client); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Client %p sent START\n", tc); if (tc != NULL) { /* got 'start' twice from the same client, not allowed */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "TransportClient %p ServerClient %p sent multiple START messages\n", tc, tc->client); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } start = (const struct StartMessage *) message; options = ntohl (start->options); if ((0 != (1 & options)) && (0 != memcmp (&start->self, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity)))) { /* client thinks this is a different peer, reject */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Rejecting control connection from peer `%s', which is not me!\n"), GNUNET_i2s (&start->self)); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } tc = setup_client (client); tc->send_payload = (0 != (2 & options)); unicast (tc, GST_hello_get (), GNUNET_NO); GST_neighbours_iterate (¬ify_client_about_neighbour, tc); GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Client sent us a HELLO. Process the request. * * @param cls unused * @param client the client * @param message the HELLO message */ static void clients_handle_hello (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GST_validation_handle_hello (message); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Closure for 'handle_send_transmit_continuation' */ struct SendTransmitContinuationContext { /** * Client that made the request. */ struct GNUNET_SERVER_Client *client; /** * Peer that was the target. */ struct GNUNET_PeerIdentity target; }; /** * Function called after the transmission is done. Notify the client that it is * OK to send the next message. * * @param cls closure * @param success #GNUNET_OK on success, #GNUNET_NO on failure, #GNUNET_SYSERR if we're not connected * @param bytes_payload bytes payload sent * @param bytes_on_wire bytes sent on wire */ static void handle_send_transmit_continuation (void *cls, int success, size_t bytes_payload, size_t bytes_on_wire) { struct SendTransmitContinuationContext *stcc = cls; struct SendOkMessage send_ok_msg; if (GNUNET_OK == success) GST_neighbours_notify_payload_sent (&stcc->target, bytes_payload); send_ok_msg.header.size = htons (sizeof (send_ok_msg)); send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); send_ok_msg.bytes_msg = htonl (bytes_payload); send_ok_msg.bytes_physical = htonl (bytes_on_wire); send_ok_msg.success = htonl (success); send_ok_msg.latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_FOREVER_REL); send_ok_msg.peer = stcc->target; GST_clients_unicast (stcc->client, &send_ok_msg.header, GNUNET_NO); GNUNET_SERVER_client_drop (stcc->client); GNUNET_free (stcc); } /** * Client asked for transmission to a peer. Process the request. * * @param cls unused * @param client the client * @param message the send message that was sent */ static void clients_handle_send (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct OutboundMessage *obm; const struct GNUNET_MessageHeader *obmm; struct SendTransmitContinuationContext *stcc; uint16_t size; uint16_t msize; struct TransportClient *tc; tc = lookup_client (client); if (NULL == tc) { /* client asked for transmission before 'START' */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } size = ntohs (message->size); if (size < sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } obm = (const struct OutboundMessage *) message; obmm = (const struct GNUNET_MessageHeader *) &obm[1]; msize = size - sizeof (struct OutboundMessage); if (msize < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n", "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize); if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer)) { /* not connected, not allowed to send; can happen due to asynchronous operations */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not send message to peer `%s': not connected\n", GNUNET_i2s (&obm->peer)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes payload dropped (other peer was not connected)"), msize, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); stcc = GNUNET_new (struct SendTransmitContinuationContext); stcc->target = obm->peer; stcc->client = client; GNUNET_SERVER_client_keep (client); GST_manipulation_send (&obm->peer, obmm, msize, GNUNET_TIME_relative_ntoh (obm->timeout), &handle_send_transmit_continuation, stcc); } /** * Try to initiate a connection to the given peer if the blacklist * allowed it. * * @param cls closure (unused, NULL) * @param peer identity of peer that was tested * @param result #GNUNET_OK if the connection is allowed, * #GNUNET_NO if not */ static void try_connect_if_allowed (void *cls, const struct GNUNET_PeerIdentity *peer, int result) { if (GNUNET_OK != result) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Blacklist refuses connection attempt to peer `%s'\n"), GNUNET_i2s (peer)); return; /* not allowed */ } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Blacklist allows connection attempt to peer `%s'\n"), GNUNET_i2s (peer)); GST_neighbours_try_connect (peer); } /** * Handle request connect message * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message */ static void clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct TransportRequestConnectMessage *trcm = (const struct TransportRequestConnectMessage *) message; if (GNUNET_YES == ntohl (trcm->connect)) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# REQUEST CONNECT messages received"), 1, GNUNET_NO); if (0 == memcmp (&trcm->peer, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received a request connect message myself `%s'\n", GNUNET_i2s (&trcm->peer)); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received a request connect message for peer `%s'\n"), GNUNET_i2s (&trcm->peer)); (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed, NULL); } } else if (GNUNET_NO == ntohl (trcm->connect)) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# REQUEST DISCONNECT messages received"), 1, GNUNET_NO); if (0 == memcmp (&trcm->peer, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received a request disconnect message myself `%s'\n", GNUNET_i2s (&trcm->peer)); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received a request disconnect message for peer `%s'\n"), GNUNET_i2s (&trcm->peer)); (void) GST_neighbours_force_disconnect (&trcm->peer); } } else { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Take the given address and append it to the set of results sent back to * the client. * * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*') * @param buf text to transmit */ static void transmit_address_to_client (void *cls, const char *buf) { struct AddressToStringContext *actx = cls; if (NULL == buf) { GNUNET_SERVER_transmit_context_append_data (actx->tc, NULL, 0, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); GNUNET_SERVER_transmit_context_run (actx->tc, GNUNET_TIME_UNIT_FOREVER_REL); GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, actx); GNUNET_free (actx); return; } GNUNET_SERVER_transmit_context_append_data (actx->tc, buf, strlen (buf) + 1, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); } /** * Client asked to resolve an address. Process the request. * * @param cls unused * @param client the client * @param message the resolution request */ static void clients_handle_address_to_string (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct AddressLookupMessage *alum; struct GNUNET_TRANSPORT_PluginFunctions *papi; const char *plugin_name; const char *address; uint32_t address_len; uint16_t size; struct GNUNET_SERVER_TransmitContext *tc; struct AddressToStringContext *actx; struct GNUNET_TIME_Relative rtimeout; int32_t numeric; size = ntohs (message->size); if (size < sizeof (struct AddressLookupMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } alum = (const struct AddressLookupMessage *) message; address_len = ntohs (alum->addrlen); if (size <= sizeof (struct AddressLookupMessage) + address_len) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } address = (const char *) &alum[1]; plugin_name = (const char *) &address[address_len]; if ('\0' != plugin_name[size - sizeof (struct AddressLookupMessage) - address_len - 1]) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout); numeric = ntohs (alum->numeric_only); tc = GNUNET_SERVER_transmit_context_create (client); papi = GST_plugins_printer_find (plugin_name); if (NULL == papi) { GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); GNUNET_SERVER_transmit_context_run (tc, rtimeout); return; } actx = GNUNET_new (struct AddressToStringContext); actx->tc = tc; GNUNET_CONTAINER_DLL_insert (a2s_head, a2s_tail, actx); GNUNET_SERVER_disable_receive_done_warning (client); papi->address_pretty_printer (papi->cls, plugin_name, address, address_len, numeric, rtimeout, &transmit_address_to_client, actx); } /** * Compose #PeerIterateResponseMessage using the given peer and address. * * @param peer identity of the peer * @param address the address, NULL on disconnect * @return composed message */ static struct PeerIterateResponseMessage * compose_address_iterate_response_message (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address) { struct PeerIterateResponseMessage *msg; size_t size; size_t tlen; size_t alen; char *addr; GNUNET_assert (NULL != peer); if (NULL != address) { tlen = strlen (address->transport_name) + 1; alen = address->address_length; } else tlen = alen = 0; size = (sizeof (struct PeerIterateResponseMessage) + alen + tlen); msg = GNUNET_malloc (size); msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE); msg->reserved = htonl (0); msg->peer = *peer; msg->addrlen = htonl (alen); msg->pluginlen = htonl (tlen); if (NULL != address) { msg->local_address_info = htonl((uint32_t) address->local_info); addr = (char *) &msg[1]; memcpy (addr, address->address, alen); memcpy (&addr[alen], address->transport_name, tlen); } return msg; } /** * Compose #PeerIterateResponseMessage using the given peer and address. * * @param peer identity of the peer * @param address the address, NULL on disconnect * @return composed message */ static struct ValidationIterateResponseMessage * compose_validation_iterate_response_message (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address) { struct ValidationIterateResponseMessage *msg; size_t size; size_t tlen; size_t alen; char *addr; GNUNET_assert (NULL != peer); if (NULL != address) { tlen = strlen (address->transport_name) + 1; alen = address->address_length; } else tlen = alen = 0; size = (sizeof (struct ValidationIterateResponseMessage) + alen + tlen); msg = GNUNET_malloc (size); msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE); msg->reserved = htonl (0); msg->peer = *peer; msg->addrlen = htonl (alen); msg->pluginlen = htonl (tlen); if (NULL != address) { msg->local_address_info = htonl((uint32_t) address->local_info); addr = (char *) &msg[1]; memcpy (addr, address->address, alen); memcpy (&addr[alen], address->transport_name, tlen); } return msg; } struct IterationContext { struct GNUNET_SERVER_TransmitContext *tc; struct GNUNET_PeerIdentity id; int all; }; /** * Output information of validation entries to the given client. * * @param cls the 'struct IterationContext' * @param peer identity of the neighbour * @param address the address * @param last_validation point in time when last validation was performed * @param valid_until point in time how long address is valid * @param next_validation point in time when next validation will be performed * @param state state of validation notification */ static void send_validation_information (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state) { struct IterationContext *pc = cls; struct ValidationIterateResponseMessage *msg; if ( (GNUNET_YES == pc->all) || (0 == memcmp (peer, &pc->id, sizeof (pc->id))) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending information about for validation entry for peer `%s' using address `%s'\n", GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : ""); msg = compose_validation_iterate_response_message (peer, address); msg->last_validation = GNUNET_TIME_absolute_hton(last_validation); msg->valid_until = GNUNET_TIME_absolute_hton(valid_until); msg->next_validation = GNUNET_TIME_absolute_hton(next_validation); msg->state = htonl ((uint32_t) state); GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header); GNUNET_free (msg); } } /** * Output information of neighbours to the given client. * * @param cls the 'struct PeerIterationContext' * @param peer identity of the neighbour * @param address the address * @param state current state this peer is in * @param state_timeout timeout for the current state of the peer * @param bandwidth_in inbound quota in NBO * @param bandwidth_out outbound quota in NBO */ static void send_peer_information (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { struct IterationContext *pc = cls; struct PeerIterateResponseMessage *msg; if ( (GNUNET_YES == pc->all) || (0 == memcmp (peer, &pc->id, sizeof (pc->id))) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending information about `%s' using address `%s' in state `%s'\n", GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "", GNUNET_TRANSPORT_ps2s (state)); msg = compose_address_iterate_response_message (peer, address); msg->state = htonl (state); msg->state_timeout = GNUNET_TIME_absolute_hton(state_timeout); GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header); GNUNET_free (msg); } } /** * Client asked to obtain information about a specific or all peers * Process the request. * * @param cls unused * @param client the client * @param message the peer address information request */ static void clients_handle_monitor_peers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { static struct GNUNET_PeerIdentity all_zeros; struct GNUNET_SERVER_TransmitContext *tc; struct PeerMonitorMessage *msg; struct IterationContext pc; if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (ntohs (message->size) != sizeof (struct PeerMonitorMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (struct PeerMonitorMessage *) message; if ( (GNUNET_YES != ntohl (msg->one_shot)) && (NULL != lookup_monitoring_client (peer_monitoring_clients_head, client)) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "ServerClient %p tried to start monitoring twice\n", client); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_disable_receive_done_warning (client); pc.tc = tc = GNUNET_SERVER_transmit_context_create (client); /* Send initial list */ if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) { /* iterate over all neighbours */ pc.all = GNUNET_YES; pc.id = msg->peer; } else { /* just return one neighbour */ pc.all = GNUNET_NO; pc.id = msg->peer; } GST_neighbours_iterate (&send_peer_information, &pc); if (GNUNET_YES != ntohl (msg->one_shot)) { setup_peer_monitoring_client (client, &msg->peer); } else { GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE); } GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Client asked to obtain information about a specific or all validation * processes * * @param cls unused * @param client the client * @param message the peer address information request */ static void clients_handle_monitor_validation (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { static struct GNUNET_PeerIdentity all_zeros; struct GNUNET_SERVER_TransmitContext *tc; struct PeerMonitorMessage *msg; struct IterationContext pc; if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (ntohs (message->size) != sizeof (struct ValidationMonitorMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (struct PeerMonitorMessage *) message; if ( (GNUNET_YES != ntohl (msg->one_shot)) && (NULL != lookup_monitoring_client (val_monitoring_clients_head, client)) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "ServerClient %p tried to start monitoring twice\n", client); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_disable_receive_done_warning (client); pc.tc = tc = GNUNET_SERVER_transmit_context_create (client); /* Send initial list */ if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) { /* iterate over all neighbours */ pc.all = GNUNET_YES; pc.id = msg->peer; } else { /* just return one neighbour */ pc.all = GNUNET_NO; pc.id = msg->peer; } GST_validation_iterate (&send_validation_information, &pc); if (GNUNET_YES != ntohl (msg->one_shot)) { setup_val_monitoring_client (client, &msg->peer); } else { GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE); } GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Start handling requests from clients. * * @param server server used to accept clients from. */ void GST_clients_start (struct GNUNET_SERVER_Handle *server) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&clients_handle_start, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_START, sizeof (struct StartMessage)}, {&clients_handle_hello, NULL, GNUNET_MESSAGE_TYPE_HELLO, 0}, {&clients_handle_send, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0}, {&clients_handle_request_connect, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT, sizeof (struct TransportRequestConnectMessage)}, {&clients_handle_address_to_string, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING, 0}, {&clients_handle_monitor_peers, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST, sizeof (struct PeerMonitorMessage)}, {&clients_handle_monitor_validation, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST, sizeof (struct ValidationMonitorMessage)}, {&GST_blacklist_handle_init, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT, sizeof (struct GNUNET_MessageHeader)}, {&GST_blacklist_handle_reply, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY, sizeof (struct BlacklistMessage)}, {&GST_manipulation_set_metric, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC, 0}, {NULL, NULL, 0, 0} }; peer_nc = GNUNET_SERVER_notification_context_create (server, 0); val_nc = GNUNET_SERVER_notification_context_create (server, 0); GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification, NULL); } /** * Stop processing clients. */ void GST_clients_stop () { struct AddressToStringContext *cur; while (NULL != (cur = a2s_head)) { GNUNET_SERVER_transmit_context_destroy (cur->tc, GNUNET_NO); GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, cur); GNUNET_free (cur); } if (NULL != peer_nc) { GNUNET_SERVER_notification_context_destroy (peer_nc); peer_nc = NULL; } if (NULL != val_nc) { GNUNET_SERVER_notification_context_destroy (val_nc); val_nc = NULL; } } /** * Broadcast the given message to all of our clients. * * @param msg message to broadcast * @param may_drop #GNUNET_YES if the message can be dropped / is payload */ void GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, int may_drop) { struct TransportClient *tc; for (tc = clients_head; NULL != tc; tc = tc->next) { if ((GNUNET_YES == may_drop) && (GNUNET_YES != tc->send_payload)) continue; /* skip, this client does not care about payload */ unicast (tc, msg, may_drop); } } /** * Send the given message to a particular client * * @param client target of the message * @param msg message to transmit * @param may_drop #GNUNET_YES if the message can be dropped */ void GST_clients_unicast (struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg, int may_drop) { struct TransportClient *tc; tc = lookup_client (client); if (NULL == tc) return; /* client got disconnected in the meantime, drop message */ unicast (tc, msg, may_drop); } /** * Broadcast the new active address to all clients monitoring the peer. * * @param peer peer this update is about (never NULL) * @param address address, NULL on disconnect * @param state the current state of the peer * @param state_timeout the time out for the state */ void GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { struct PeerIterateResponseMessage *msg; struct MonitoringClient *mc; static struct GNUNET_PeerIdentity all_zeros; msg = compose_address_iterate_response_message (peer, address); msg->state = htonl (state); msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout); mc = peer_monitoring_clients_head; while (mc != NULL) { if ((0 == memcmp (&mc->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) || (0 == memcmp (&mc->peer, peer, sizeof (struct GNUNET_PeerIdentity)))) { GNUNET_SERVER_notification_context_unicast (peer_nc, mc->client, &msg->header, GNUNET_NO); } mc = mc->next; } GNUNET_free (msg); } /** * Broadcast the new validation changes to all clients monitoring the peer. * * @param peer peer this update is about (never NULL) * @param address address, NULL on disconnect * @param last_validation point in time when last validation was performed * @param valid_until point in time how long address is valid * @param next_validation point in time when next validation will be performed * @param state state of validation notification */ void GST_clients_broadcast_validation_notification ( const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state) { struct ValidationIterateResponseMessage *msg; struct MonitoringClient *mc; static struct GNUNET_PeerIdentity all_zeros; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending information about for validation entry for peer `%s' using address `%s'\n", GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : ""); msg = compose_validation_iterate_response_message (peer, address); msg->last_validation = GNUNET_TIME_absolute_hton(last_validation); msg->valid_until = GNUNET_TIME_absolute_hton(valid_until); msg->next_validation = GNUNET_TIME_absolute_hton(next_validation); msg->state = htonl ((uint32_t) state); mc = val_monitoring_clients_head; while (mc != NULL) { if ((0 == memcmp (&mc->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) || (0 == memcmp (&mc->peer, peer, sizeof (struct GNUNET_PeerIdentity)))) { GNUNET_SERVER_notification_context_unicast (val_nc, mc->client, &msg->header, GNUNET_NO); } mc = mc->next; } GNUNET_free (msg); } /* end of file gnunet-service-transport_clients.c */ gnunet-0.10.1/src/transport/test_transport_api_unreliability_constant.c0000644000175000017500000003161512274162761023610 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_unreliability_constant.c * @brief test case for transports; ensures messages get * through, regardless of order, constant packet size * * This test case serves as a base for unreliable * transport test cases to check that the transports * achieve reliable message delivery. */ #include "platform.h" #include "gnunet_transport_service.h" #include "gauger.h" #include "transport-testing.h" /** * Testcase timeout */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 900) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) static char *test_source; static char *test_plugin; static char *test_name; static int ok; static GNUNET_SCHEDULER_TaskIdentifier die_task; struct PeerContext *p1; struct PeerContext *p2; struct GNUNET_TRANSPORT_TransmitHandle *th; struct GNUNET_TRANSPORT_TESTING_handle *tth; char *cfg_file_p1; char *cfg_file_p2; uint32_t max_bps_p1; uint32_t max_bps_p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; /* * Testcase specific declarations */ /** * Note that this value must not significantly exceed * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise * messages may be dropped even for a reliable transport. */ #define TOTAL_MSGS (1024 * 3) #define MTYPE 12345 #define MSG_SIZE 10000 GNUNET_NETWORK_STRUCT_BEGIN struct TestMessage { struct GNUNET_MessageHeader header; uint32_t num; }; GNUNET_NETWORK_STRUCT_END static char *test_name; static int msg_scheduled; static int msg_sent; static int msg_recv_expected; static int msg_recv; static int test_failed; static unsigned long long total_bytes; static struct GNUNET_TIME_Absolute start_time; /* * END Testcase specific declarations */ #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif int get_bit (const char *map, unsigned int bit); static void end () { unsigned long long delta; char *value_name; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us / (1000 * 1000); FPRINTF (stderr, "\nThroughput was %llu kb/s total_bytes\n", (total_bytes / 1024) / delta); GNUNET_asprintf (&value_name, "unreliable_%s", test_plugin); GAUGER ("TRANSPORT", value_name, (int) (total_bytes / 1024 / delta), "kb/s"); GNUNET_free (value_name); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); ok = 0; if (test_failed == GNUNET_NO) ok = GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GOT %u of %u messages\n", msg_recv, TOTAL_MSGS); } static void end_badly () { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (test_failed == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Testcase timeout\n"); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Reliability failed: Last message sent %u, Next message scheduled %u, Last message received %u, Message expected %u\n", msg_sent, msg_scheduled, msg_recv, msg_recv_expected); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); ok = GNUNET_SYSERR; } static unsigned int get_size (unsigned int iter) { /* unsigned int ret; ret = (iter * iter * iter); return sizeof (struct TestMessage) + (ret % 60000); */ return MSG_SIZE; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { static int n; unsigned int s; char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; const struct TestMessage *hdr; hdr = (const struct TestMessage *) message; if (MTYPE != ntohs (message->type)) return; msg_recv_expected = n; msg_recv = ntohl (hdr->num); if (msg_recv_expected != msg_recv) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message no %u, got %u\n", msg_recv_expected, msg_recv); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } s = get_size (ntohl (hdr->num)); if (ntohs (message->size) != s) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", ntohl (hdr->num), s, ntohs (message->size), ntohl (hdr->num)); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } memset (cbuf, ntohl (hdr->num), s - sizeof (struct TestMessage)); if (0 != memcmp (cbuf, &hdr[1], s - sizeof (struct TestMessage))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u with bits %u, but body did not match\n", ntohl (hdr->num), (unsigned char) n); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } #if VERBOSE if (ntohl (hdr->num) % 5 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got message %u of size %u\n", ntohl (hdr->num), ntohs (message->size)); } #endif n++; if (0 == (n % (TOTAL_MSGS / 100))) { FPRINTF (stderr, "%s", "."); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); } if (n == TOTAL_MSGS) { /* because of starting with 0 */ msg_recv++; FPRINTF (stderr, "%s", "\n"); end (); } } static size_t notify_ready (void *cls, size_t size, void *buf) { static int n; char *cbuf = buf; struct TestMessage hdr; unsigned int s; unsigned int ret; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } ret = 0; s = get_size (n); GNUNET_assert (size >= s); GNUNET_assert (buf != NULL); cbuf = buf; do { hdr.header.size = htons (s); hdr.header.type = htons (MTYPE); hdr.num = htonl (n); msg_sent = n; memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage)); ret += sizeof (struct TestMessage); memset (&cbuf[ret], n, s - sizeof (struct TestMessage)); ret += s - sizeof (struct TestMessage); #if VERBOSE if (n % 1 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message %u of size %u\n", n, s); } #endif n++; s = get_size (n); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16)) break; /* sometimes pack buffer full, sometimes not */ } while (size - ret >= s); if (n < TOTAL_MSGS) { th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, s, TIMEOUT_TRANSMIT, ¬ify_ready, NULL); msg_scheduled = n; } else { FPRINTF (stderr, "%s", "\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All messages scheduled to be sent!!\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); } if (n % 5000 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning total message block of size %u\n", ret); } total_bytes += ret; return ret; } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer `%4s' disconnected (%p)!\n", GNUNET_i2s (peer), cls); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void sendtask () { start_time = GNUNET_TIME_absolute_get (); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, get_size (0), TIMEOUT_TRANSMIT, ¬ify_ready, NULL); } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peers connected: %s <-> %s\n", p1_c, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); cc = NULL; GNUNET_SCHEDULER_add_now (&sendtask, NULL); } void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api-unreliability-constant", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; ok = GNUNET_SYSERR; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); return ret; } /* end of test_transport_api_unreliability_constant.c */ gnunet-0.10.1/src/transport/test_transport_api_reliability_tcp_peer2.conf0000644000175000017500000000114612225230043023757 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_unreliability_unix_peer2.conf0000644000175000017500000000110012225230043024505 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-unix-p2/ [arm] PORT = 12135 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12134 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12133 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12132 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12131 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-unix] PORT = 12131 gnunet-0.10.1/src/transport/test_transport_blacklisting_cfg_blp_peer1_multiple_plugins.conf0000644000175000017500000000142712236654562027570 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] #PREFIX = valgrind --leak-check=full PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PLUGINS = tcp udp [transport-blacklist-6ULBJK6QQJ64FAG9DF0292AS5IA9CCAC04IQU0HF8THM635HMBBG] DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50 = tcp gnunet-0.10.1/src/transport/test_transport_api_http_peer1.conf0000644000175000017500000000134312225230043021555 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-http-p1/ [transport-http_client] [arm] PORT = 12085 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12084 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12083 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12082 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12081 PLUGINS = http_client #BINARY = .libs/gnunet-service-transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock #PREFIX = valgrind --leak-check=full #PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args gnunet-0.10.1/src/transport/test_quota_compliance_https_asymmetric_peer1.conf0000644000175000017500000000122012225230043024625 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer1/ [transport-https_client] [arm] PORT = 4006 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_arm_peer1.sock [statistics] PORT = 4005 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_statistics_peer1.sock [resolver] PORT = 4004 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_resolver_peer1.sock [peerinfo] PORT = 4003 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_peerinfo_peer1.sock [transport] PORT = 4002 PLUGINS = https_client UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_transport_peer1.sock gnunet-0.10.1/src/transport/test_transport_api_timeout_unix_peer1.conf0000644000175000017500000000110012225230043023316 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-unix-p1/ [arm] PORT = 12125 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12124 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12123 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12122 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12121 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [transport-unix] PORT = 12120 gnunet-0.10.1/src/transport/test_transport_api_udp_nat_peer1.conf0000644000175000017500000000123212225230043022225 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-nat-p1/ [nat] BEHIND_NAT = YES ALLOW_NAT = NO ONLY_NAT_ADDRESSES = YES [transport-udp] PORT = 0 [arm] PORT = 12065 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12064 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12063 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12062 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12061 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_restart_2peers.c0000644000175000017500000002746112274162761021773 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_restart_2peers.c * @brief base test case for transport implementations * * This test case starts 2 peers, connects and exchanges a message * boths peer are restarted and tested if peers reconnect * C code apparently. */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) #define MTYPE 12345 static char *test_name; static int ok; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static GNUNET_SCHEDULER_TaskIdentifier reconnect_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static int restarted; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; if (reconnect_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (reconnect_task); reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; if (restarted == GNUNET_YES) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer was restarted, but communication did not resume\n"); if (restarted == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer was NOT (even) restarted\n"); if (reconnect_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (reconnect_task); reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); ok = GNUNET_SYSERR; } static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerContext *p = cls; reconnect_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_TRANSPORT_try_connect (p1->th, &p2->id, NULL, NULL); /*FIXME TRY_CONNECT change */ reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect, p); } static void restart_cb (struct PeerContext *p, void *cls) { static int c; c++; if (c != 2) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Restarted peer %u (`%4s'), issuing reconnect\n", p->no, GNUNET_i2s (&p->id)); reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, p); } static void restart (struct PeerContext *p, char *cfg_file) { GNUNET_assert (p != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Restarting peer %u (`%4s')\n", p->no, GNUNET_i2s (&p->id)); GNUNET_TRANSPORT_TESTING_restart_peer (tth, p, cfg_file, &restart_cb, p); } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if ((MTYPE == ntohs (message->type)) && (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size))) { if (restarted == GNUNET_NO) { restarted = GNUNET_YES; restart (p1, cfg_file_p1); restart (p2, cfg_file_p2); return; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Restarted peers connected, stopping test...\n"); ok = 0; end (); } } else { GNUNET_break (0); ok = 1; if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); } } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= 256); if (buf != NULL) { hdr = buf; hdr->size = htons (sizeof (struct GNUNET_MessageHeader)); hdr->type = htons (MTYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return sizeof (struct GNUNET_MessageHeader); } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, 256, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); if ((restarted == GNUNET_YES) && (c == 4)) { send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (GNUNET_SCHEDULER_NO_TASK != send_task) GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, NULL); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_asprintf (&cfg_file_p1, "test_transport_api_tcp_peer1.conf"); GNUNET_asprintf (&cfg_file_p2, "test_transport_api_tcp_peer2.conf"); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of test_transport_api_restart_2peers.c */ gnunet-0.10.1/src/transport/test_quota_compliance_tcp_asymmetric_peer1.conf0000644000175000017500000000123512225230043024257 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/quota-tcp-p1/ [transport-tcp] PORT = 4094 [transport-udp] PORT = 4094 [arm] PORT = 4087 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_arm_peer1.sock [statistics] PORT = 4088 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_statistics_peer1.sock [resolver] PORT = 4089 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_resolver_peer1.sock [peerinfo] PORT = 4090 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_peerinfo_peer1.sock [transport] PORT = 4091 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_transport_peer1.sock gnunet-0.10.1/src/transport/gnunet-service-transport_neighbours.c0000644000175000017500000036656412320724370022242 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_neighbours.c * @brief neighbour management * @author Christian Grothoff */ #include "platform.h" #include "gnunet_ats_service.h" #include "gnunet-service-transport_neighbours.h" #include "gnunet-service-transport_plugins.h" #include "gnunet-service-transport_validation.h" #include "gnunet-service-transport_clients.h" #include "gnunet-service-transport.h" #include "gnunet_peerinfo_service.h" #include "gnunet-service-transport_blacklist.h" #include "gnunet_constants.h" #include "transport.h" /** * Size of the neighbour hash map. */ #define NEIGHBOUR_TABLE_SIZE 256 /** * Time we give plugin to transmit DISCONNECT message before the * neighbour entry self-destructs. */ #define DISCONNECT_SENT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) /** * How often must a peer violate bandwidth quotas before we start * to simply drop its messages? */ #define QUOTA_VIOLATION_DROP_THRESHOLD 10 /** * How long are we willing to wait for a response from ATS before timing out? */ #define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 5000) /** * How long are we willing to wait for an ACK from the other peer before * giving up on our connect operation? */ #define SETUP_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) /** * How long are we willing to wait for a successful reconnect if * an existing connection went down? Much shorter than the * usual SETUP_CONNECTION_TIMEOUT as we do not inform the * higher layers about the disconnect during this period. */ #define FAST_RECONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * How long are we willing to wait for a response from the blacklist * subsystem before timing out? */ #define BLACKLIST_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) /** * Interval to send utilization data */ #define UTIL_TRANSMISSION_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * State describing which kind a reply this neighbour should send */ enum GST_ACK_State { /** * We did not receive a CONNECT message for this neighbour */ ACK_UNDEFINED = 0, /* The neighbour received a CONNECT message and has to send a CONNECT_ACK * as reply */ ACK_SEND_CONNECT_ACK = 1, /* The neighbour sent a CONNECT_ACK message and has to send a SESSION_ACK * as reply */ ACK_SEND_SESSION_ACK = 2 }; GNUNET_NETWORK_STRUCT_BEGIN /** * Message a peer sends to another to indicate that it intends to * setup a connection/session for data exchange. A 'SESSION_CONNECT' * should be answered with a 'SESSION_CONNECT_ACK' with the same body * to confirm. A 'SESSION_CONNECT_ACK' should then be followed with * a 'SESSION_ACK'. Once the 'SESSION_ACK' is received, both peers * should be connected. */ struct SessionConnectMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT * or #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Absolute time at the sender. Only the most recent connect * message implies which session is preferred by the sender. */ struct GNUNET_TIME_AbsoluteNBO timestamp; }; /** * Message a peer sends to another when connected to indicate that a * session is in use and the peer is still alive or to respond to a keep alive. * A peer sends a message with type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE * to request a message with #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE. * When the keep alive response with type is received, transport service * will call the respective plugin to update the session timeout */ struct SessionKeepAliveMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE or * #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE. */ struct GNUNET_MessageHeader header; /** * A nonce to identify the session the keep alive is used for */ uint32_t nonce GNUNET_PACKED; }; /** * Message we send to the other peer to notify him that we intentionally * are disconnecting (to reduce timeouts). This is just a friendly * notification, peers must not rely on always receiving disconnect * messages. */ struct SessionDisconnectMessage { /** * Header of type #GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Purpose of the signature. Extends over the timestamp. * Purpose should be #GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DISCONNECT. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * Absolute time at the sender. Only the most recent connect * message implies which session is preferred by the sender. */ struct GNUNET_TIME_AbsoluteNBO timestamp; /** * Public key of the sender. */ struct GNUNET_CRYPTO_EddsaPublicKey public_key; /** * Signature of the peer that sends us the disconnect. Only * valid if the timestamp is AFTER the timestamp from the * corresponding 'CONNECT' message. */ struct GNUNET_CRYPTO_EddsaSignature signature; }; GNUNET_NETWORK_STRUCT_END /** * For each neighbour we keep a list of messages * that we still want to transmit to the neighbour. */ struct MessageQueue { /** * This is a doubly linked list. */ struct MessageQueue *next; /** * This is a doubly linked list. */ struct MessageQueue *prev; /** * Function to call once we're done. */ GST_NeighbourSendContinuation cont; /** * Closure for @e cont */ void *cont_cls; /** * The message(s) we want to transmit, GNUNET_MessageHeader(s) * stuck together in memory. Allocated at the end of this struct. */ const char *message_buf; /** * Size of the message buf */ size_t message_buf_size; /** * At what time should we fail? */ struct GNUNET_TIME_Absolute timeout; }; /** * A possible address we could use to communicate with a neighbour. */ struct NeighbourAddress { /** * Active session for this address. */ struct Session *session; /** * Network-level address information. */ struct GNUNET_HELLO_Address *address; /** * Timestamp of the 'SESSION_CONNECT' message we sent to the other * peer for this address. Use to check that the ACK is in response * to our most recent 'CONNECT'. */ struct GNUNET_TIME_Absolute connect_timestamp; /** * Inbound bandwidth from ATS for this address. */ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; /** * Outbound bandwidth from ATS for this address. */ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; /** * Did we tell ATS that this is our 'active' address? */ int ats_active; /** * The current nonce sent in the last keep alive messages */ uint32_t keep_alive_nonce; }; /** * Entry in neighbours. */ struct NeighbourMapEntry { /** * Head of list of messages we would like to send to this peer; * must contain at most one message per client. */ struct MessageQueue *messages_head; /** * Tail of list of messages we would like to send to this peer; must * contain at most one message per client. */ struct MessageQueue *messages_tail; /** * Are we currently trying to send a message? If so, which one? */ struct MessageQueue *is_active; /** * Primary address we currently use to communicate with the neighbour. */ struct NeighbourAddress primary_address; /** * Alternative address currently under consideration for communicating * with the neighbour. */ struct NeighbourAddress alternative_address; /** * Identity of this neighbour. */ struct GNUNET_PeerIdentity id; /** * Main task that drives this peer (timeouts, keepalives, etc.). * Always runs the 'master_task'. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Task to disconnect neighbour after we received a DISCONNECT message */ GNUNET_SCHEDULER_TaskIdentifier delayed_disconnect_task; /** * At what time should we sent the next keep-alive message? */ struct GNUNET_TIME_Absolute keep_alive_time; /** * At what time did we sent the last keep-alive message? Used * to calculate round-trip time ("latency"). */ struct GNUNET_TIME_Absolute last_keep_alive_time; /** * Timestamp we should include in our next CONNECT_ACK message. * (only valid if 'send_connect_ack' is #GNUNET_YES). Used to build * our CONNECT_ACK message. */ struct GNUNET_TIME_Absolute connect_ack_timestamp; /** * ATS address suggest handle */ struct GNUNET_ATS_SuggestHandle *suggest_handle; /** * Time where we should cut the connection (timeout) if we don't * make progress in the state machine (or get a KEEPALIVE_RESPONSE * if we are in S_CONNECTED). */ struct GNUNET_TIME_Absolute timeout; /** * Latest calculated latency value */ struct GNUNET_TIME_Relative latency; /** * Tracker for inbound bandwidth. */ struct GNUNET_BANDWIDTH_Tracker in_tracker; /** * How often has the other peer (recently) violated the inbound * traffic limit? Incremented by 10 per violation, decremented by 1 * per non-violation (for each time interval). */ unsigned int quota_violation_count; /** * The current state of the peer. */ enum GNUNET_TRANSPORT_PeerState state; /** * Did we sent an KEEP_ALIVE message and are we expecting a response? */ int expect_latency_response; /** * When a peer wants to connect we have to reply to the 1st CONNECT message * with a CONNECT_ACK message. But sometime we cannot send this message * immediately since we do not have an address and then we have to remember * to send this message as soon as we have an address. * * Flag to set if we still need to send a CONNECT_ACK message to the other peer * (once we have an address to use and the peer has been allowed by our * blacklist). Initially set to #ACK_UNDEFINED. Set to #ACK_SEND_CONNECT_ACK * if we need to send a CONNECT_ACK. Set to #ACK_SEND_SESSION_ACK if we did * send a CONNECT_ACK and should go to 'S_CONNECTED' upon receiving a * 'SESSION_ACK' (regardless of what our own state machine might say). */ enum GST_ACK_State ack_state; /** * Tracking utilization of outbound bandwidth */ uint32_t util_payload_bytes_sent; /** * Tracking utilization of inbound bandwidth */ uint32_t util_payload_bytes_recv; /** * Tracking utilization of outbound bandwidth */ uint32_t util_total_bytes_sent; /** * Tracking utilization of inbound bandwidth */ uint32_t util_total_bytes_recv; /** * Date of last utilization transmission */ struct GNUNET_TIME_Absolute last_util_transmission; }; /** * Context for blacklist checks and the #try_connect_bl_check_cont() * function. Stores information about ongoing blacklist checks. */ struct BlackListCheckContext { /** * We keep blacklist checks in a DLL. */ struct BlackListCheckContext *next; /** * We keep blacklist checks in a DLL. */ struct BlackListCheckContext *prev; /** * Address that is being checked. */ struct NeighbourAddress na; /** * Handle to the ongoing blacklist check. */ struct GST_BlacklistCheck *bc; }; /** * Hash map from peer identities to the respective 'struct NeighbourMapEntry'. */ static struct GNUNET_CONTAINER_MultiPeerMap *neighbours; /** * We keep blacklist checks in a DLL so that we can find * the 'sessions' in their 'struct NeighbourAddress' if * a session goes down. */ static struct BlackListCheckContext *bc_head; /** * We keep blacklist checks in a DLL. */ static struct BlackListCheckContext *bc_tail; /** * List of pending blacklist checks: head */ static struct BlacklistCheckSwitchContext *pending_bc_head; /** * List of pending blacklist checks: tail */ static struct BlacklistCheckSwitchContext *pending_bc_tail; /** * Closure for #connect_notify_cb, #disconnect_notify_cb and #neighbour_change_cb */ static void *callback_cls; /** * Function to call when we connected to a neighbour. */ static NotifyConnect connect_notify_cb; /** * Function to call when we disconnected from a neighbour. */ static GNUNET_TRANSPORT_NotifyDisconnect disconnect_notify_cb; /** * Function to call when a neighbour changed address, state or bandwidth. */ static GNUNET_TRANSPORT_NeighbourChangeCallback neighbour_change_cb; /** * counter for connected neighbours */ static unsigned int neighbours_connected; /** * Number of bytes we have currently queued for transmission. */ static unsigned long long bytes_in_send_queue; /** * Task transmitting utilization data */ static GNUNET_SCHEDULER_TaskIdentifier util_transmission_tk; static struct GNUNET_CONTAINER_MultiPeerMap *registered_quota_notifications; static char * print_ack_state (enum GST_ACK_State s) { switch (s) { case ACK_UNDEFINED: return "UNDEFINED"; case ACK_SEND_CONNECT_ACK: return "SEND_CONNECT_ACK"; case ACK_SEND_SESSION_ACK: return "SEND_SESSION_ACK"; default: GNUNET_break (0); return "N/A"; } } /** * Lookup a neighbour entry in the neighbours hash map. * * @param pid identity of the peer to look up * @return the entry, NULL if there is no existing record */ static struct NeighbourMapEntry * lookup_neighbour (const struct GNUNET_PeerIdentity *pid) { if (NULL == neighbours) return NULL; return GNUNET_CONTAINER_multipeermap_get (neighbours, pid); } /** * Test if we're connected to the given peer. * * @param n neighbour entry of peer to test * @return #GNUNET_YES if we are connected, #GNUNET_NO if not */ static int test_connected (struct NeighbourMapEntry *n) { if (NULL == n) return GNUNET_NO; return GNUNET_TRANSPORT_is_connected (n->state); } /** * Send information about a new outbound quota to our clients. * * @param target affected peer * @param quota new quota */ static void send_outbound_quota (const struct GNUNET_PeerIdentity *target, struct GNUNET_BANDWIDTH_Value32NBO quota) { struct QuotaSetMessage q_msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending outbound quota of %u Bps for peer `%s' to all clients\n", ntohl (quota.value__), GNUNET_i2s (target)); q_msg.header.size = htons (sizeof (struct QuotaSetMessage)); q_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA); q_msg.quota = quota; q_msg.peer = (*target); GST_clients_broadcast (&q_msg.header, GNUNET_NO); } /** * We don't need a given neighbour address any more. * Release its resources and give appropriate notifications * to ATS and other subsystems. * * @param na address we are done with; @a na itself must NOT be 'free'd, only the contents! */ static void free_address (struct NeighbourAddress *na) { if (GNUNET_YES == na->ats_active) { GST_validation_set_address_use (na->address, na->session, GNUNET_NO); GNUNET_ATS_address_in_use (GST_ats, na->address, na->session, GNUNET_NO); } na->bandwidth_in = GNUNET_BANDWIDTH_value_init (0); na->bandwidth_out = GNUNET_BANDWIDTH_value_init (0); na->ats_active = GNUNET_NO; na->keep_alive_nonce = 0; if (NULL != na->address) { GNUNET_HELLO_address_free (na->address); na->address = NULL; } na->session = NULL; } /** * Set net state for this neighbour and notify monitoring * * @param n the respective neighbour * @param s the new state */ static void set_state (struct NeighbourMapEntry *n, enum GNUNET_TRANSPORT_PeerState s) { n->state = s; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Neighbour `%s' changed state to %s\n", GNUNET_i2s (&n->id), GNUNET_TRANSPORT_ps2s(s)); neighbour_change_cb (callback_cls, &n->id, n->primary_address.address, n->state, n->timeout, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out); } /** * Set net state and state timeout for this neighbour and notify monitoring * * @param n the respective neighbour * @param s the new state * @param timeout the new timeout */ static void set_state_and_timeout (struct NeighbourMapEntry *n, enum GNUNET_TRANSPORT_PeerState s, struct GNUNET_TIME_Absolute timeout) { n->state = s; n->timeout = timeout; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Neighbour `%s' changed state to %s with timeout %s\n", GNUNET_i2s (&n->id), GNUNET_TRANSPORT_ps2s(s), GNUNET_STRINGS_absolute_time_to_string (timeout)); neighbour_change_cb (callback_cls, &n->id, n->primary_address.address, n->state, n->timeout, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out); } /** * Set new state timeout for this neighbour and notify monitoring * * @param n the respective neighbour * @param timeout the new timeout */ static void set_timeout (struct NeighbourMapEntry *n, struct GNUNET_TIME_Absolute timeout) { n->timeout = timeout; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Neighbour `%s' changed timeout %s\n", GNUNET_i2s (&n->id), GNUNET_STRINGS_absolute_time_to_string (timeout)); neighbour_change_cb (callback_cls, &n->id, n->primary_address.address, n->state, n->timeout, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out); } /** * Initialize the alternative address of a neighbour * * @param n the neighbour * @param address address of the other peer, NULL if other peer * connected to us * @param session session to use (or NULL, in which case an * address must be setup) * @param bandwidth_in inbound quota to be used when connection is up * @param bandwidth_out outbound quota to be used when connection is up */ static void set_alternative_address (struct NeighbourMapEntry *n, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { struct GNUNET_TRANSPORT_PluginFunctions *papi; if (NULL == (papi = GST_plugins_find (address->transport_name))) { GNUNET_break (0); return; } if (session == n->alternative_address.session) { n->alternative_address.bandwidth_in = bandwidth_in; n->alternative_address.bandwidth_out = bandwidth_out; return; } free_address (&n->alternative_address); if (NULL == session) session = papi->get_session (papi->cls, address); if (NULL == session) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to obtain new session for peer `%s' and address '%s'\n", GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); GNUNET_ATS_address_destroyed (GST_ats, address, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Neighbour `%s' configured alternative address %s\n", GNUNET_i2s (&n->id), GST_plugins_a2s(address)); n->alternative_address.address = GNUNET_HELLO_address_copy (address); n->alternative_address.bandwidth_in = bandwidth_in; n->alternative_address.bandwidth_out = bandwidth_out; n->alternative_address.session = session; n->alternative_address.ats_active = GNUNET_NO; n->alternative_address.keep_alive_nonce = 0; } /** * Initialize the primary address of a neighbour * * @param n the neighbour * @param address address of the other peer, NULL if other peer * connected to us * @param session session to use (or NULL, in which case an * address must be setup) * @param bandwidth_in inbound quota to be used when connection is up * @param bandwidth_out outbound quota to be used when connection is up * @param is_active #GNUNET_YES to mark this as the active address with ATS */ static void set_primary_address (struct NeighbourMapEntry *n, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, int is_active) { struct GNUNET_TRANSPORT_PluginFunctions *papi; if (NULL == (papi = GST_plugins_find (address->transport_name))) { GNUNET_break (0); return; } if (session == n->primary_address.session) { n->primary_address.bandwidth_in = bandwidth_in; n->primary_address.bandwidth_out = bandwidth_out; if (is_active != n->primary_address.ats_active) { n->primary_address.ats_active = is_active; GNUNET_ATS_address_in_use (GST_ats, n->primary_address.address, n->primary_address.session, is_active); GST_validation_set_address_use (n->primary_address.address, n->primary_address.session, is_active); } if (GNUNET_YES == is_active) { GST_neighbours_set_incoming_quota (&address->peer, bandwidth_in); send_outbound_quota (&address->peer, bandwidth_out); } return; } free_address (&n->primary_address); if (NULL == session) session = papi->get_session (papi->cls, address); if (NULL == session) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to obtain new session for peer `%s' and address '%s'\n", GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); GNUNET_ATS_address_destroyed (GST_ats, address, NULL); return; } n->primary_address.address = GNUNET_HELLO_address_copy (address); n->primary_address.bandwidth_in = bandwidth_in; n->primary_address.bandwidth_out = bandwidth_out; n->primary_address.session = session; n->primary_address.ats_active = is_active; n->primary_address.keep_alive_nonce = 0; if (GNUNET_YES == is_active) { /* Telling ATS about new session */ GNUNET_ATS_address_in_use (GST_ats, n->primary_address.address, n->primary_address.session, GNUNET_YES); GST_validation_set_address_use (n->primary_address.address, n->primary_address.session, GNUNET_YES); GST_neighbours_set_incoming_quota (&address->peer, bandwidth_in); send_outbound_quota (&address->peer, bandwidth_out); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Neighbour `%s' switched to address `%s'\n", GNUNET_i2s (&n->id), GST_plugins_a2s(address)); neighbour_change_cb (callback_cls, &n->id, n->primary_address.address, n->state, n->timeout, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out); } /** * Clear the primary address of a neighbour since this address is not * valid anymore and notify monitoring about it * * @param n the neighbour */ static void unset_primary_address (struct NeighbourMapEntry *n) { /* Unset primary address */ free_address (&n->primary_address); /* Notify monitoring about it */ neighbour_change_cb (callback_cls, &n->id, NULL, n->state, n->timeout, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out); } /** * Clear the alternative address of a neighbour since this address is not * valid anymore * * @param n the neighbour */ static void unset_alternative_address (struct NeighbourMapEntry *n) { /* Unset primary address */ free_address (&n->alternative_address); } /** * Free a neighbour map entry. * * @param n entry to free * @param keep_sessions #GNUNET_NO to tell plugin to terminate sessions, * #GNUNET_YES to keep all sessions */ static void free_neighbour (struct NeighbourMapEntry *n, int keep_sessions) { struct MessageQueue *mq; struct GNUNET_TRANSPORT_PluginFunctions *papi; struct GNUNET_HELLO_Address *backup_primary; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Freeing neighbour state of peer `%s'\n", GNUNET_i2s (&n->id)); n->is_active = NULL; /* always free'd by its own continuation! */ /* fail messages currently in the queue */ while (NULL != (mq = n->messages_head)) { GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq); if (NULL != mq->cont) mq->cont (mq->cont_cls, GNUNET_SYSERR, mq->message_buf_size, 0); GNUNET_free (mq); } /* It is too late to send other peer disconnect notifications, but at least internally we need to get clean... */ if (GNUNET_YES == test_connected (n)) { GNUNET_STATISTICS_set (GST_stats, gettext_noop ("# peers connected"), --neighbours_connected, GNUNET_NO); disconnect_notify_cb (callback_cls, &n->id); } /* Mark peer as disconnected */ set_state (n, GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED); if (NULL != n->primary_address.address) backup_primary = GNUNET_HELLO_address_copy (n->primary_address.address); else backup_primary = NULL; /* free addresses and mark as unused */ unset_primary_address (n); free_address (&n->alternative_address); /* cut all transport-level connection for this peer */ if ((GNUNET_NO == keep_sessions) && (NULL != backup_primary) && (NULL != (papi = GST_plugins_find (backup_primary->transport_name)))) papi->disconnect_peer (papi->cls, &n->id); if (NULL != backup_primary) GNUNET_HELLO_address_free (backup_primary); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (neighbours, &n->id, n)); /* Cancel address requests for this peer */ if (NULL != n->suggest_handle) { GNUNET_ATS_suggest_address_cancel (GST_ats, &n->id); n->suggest_handle = NULL; } /* Cancel the disconnect task */ if (GNUNET_SCHEDULER_NO_TASK != n->delayed_disconnect_task) { GNUNET_SCHEDULER_cancel (n->delayed_disconnect_task); n->delayed_disconnect_task = GNUNET_SCHEDULER_NO_TASK; } /* Cancel the master task */ if (GNUNET_SCHEDULER_NO_TASK != n->task) { GNUNET_SCHEDULER_cancel (n->task); n->task = GNUNET_SCHEDULER_NO_TASK; } /* free rest of memory */ GNUNET_free (n); } /** * Transmit a message using the current session of the given * neighbour. * * @param n entry for the recipient * @param msgbuf buffer to transmit * @param msgbuf_size number of bytes in @a msgbuf buffer * @param priority transmission priority * @param timeout transmission timeout * @param use_keepalive_timeout #GNUNET_YES to use plugin-specific keep-alive * timeout (@a timeout is ignored in that case), #GNUNET_NO otherwise * @param cont continuation to call when finished (can be NULL) * @param cont_cls closure for @a cont * @return timeout (copy of @a timeout or a calculated one if * @a use_keepalive_timeout is #GNUNET_YES. */ static struct GNUNET_TIME_Relative send_with_session (struct NeighbourMapEntry *n, const char *msgbuf, size_t msgbuf_size, uint32_t priority, struct GNUNET_TIME_Relative timeout, unsigned int use_keepalive_timeout, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct GNUNET_TRANSPORT_PluginFunctions *papi; struct GNUNET_TIME_Relative result = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_assert (n->primary_address.session != NULL); if ( ((NULL == (papi = GST_plugins_find (n->primary_address.address->transport_name)) || (-1 == papi->send (papi->cls, n->primary_address.session, msgbuf, msgbuf_size, priority, (result = (GNUNET_NO == use_keepalive_timeout) ? timeout : GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, papi->query_keepalive_factor (papi->cls))), cont, cont_cls)))) && (NULL != cont)) cont (cont_cls, &n->id, GNUNET_SYSERR, msgbuf_size, 0); GST_neighbours_notify_data_sent (&n->id, n->primary_address.address, n->primary_address.session, msgbuf_size); GNUNET_break (NULL != papi); return result; } /** * Master task run for every neighbour. Performs all of the time-related * activities (keep alive, send next message, disconnect if idle, finish * clean up after disconnect). * * @param cls the `struct NeighbourMapEntry` for which we are running * @param tc scheduler context (unused) */ static void master_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Function called when the 'DISCONNECT' message has been sent by the * plugin. Frees the neighbour --- if the entry still exists. * * @param cls NULL * @param target identity of the neighbour that was disconnected * @param result #GNUNET_OK if the disconnect got out successfully * @param payload bytes payload * @param physical bytes physical */ static void send_disconnect_cont (void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t payload, size_t physical) { struct NeighbourMapEntry *n; n = lookup_neighbour (target); if (NULL == n) return; /* already gone */ if (GNUNET_TRANSPORT_PS_DISCONNECT != n->state) return; /* have created a fresh entry since */ if (GNUNET_SCHEDULER_NO_TASK != n->task) GNUNET_SCHEDULER_cancel (n->task); n->task = GNUNET_SCHEDULER_add_now (&master_task, n); } /** * Transmit a DISCONNECT message to the other peer. * * @param n neighbour to send DISCONNECT message. */ static void send_disconnect (struct NeighbourMapEntry *n) { struct SessionDisconnectMessage disconnect_msg; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending DISCONNECT message to peer `%4s'\n", GNUNET_i2s (&n->id)); disconnect_msg.header.size = htons (sizeof (struct SessionDisconnectMessage)); disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT); disconnect_msg.reserved = htonl (0); disconnect_msg.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) + sizeof (struct GNUNET_TIME_AbsoluteNBO)); disconnect_msg.purpose.purpose = htonl (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT); disconnect_msg.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); disconnect_msg.public_key = GST_my_identity.public_key; GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, &disconnect_msg.purpose, &disconnect_msg.signature)); (void) send_with_session (n, (const char *) &disconnect_msg, sizeof (disconnect_msg), UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_disconnect_cont, NULL ); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# DISCONNECT messages sent"), 1, GNUNET_NO); } /** * Disconnect from the given neighbour, clean up the record. * * @param n neighbour to disconnect from */ static void disconnect_neighbour (struct NeighbourMapEntry *n) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnecting from peer %s in state %s\n", GNUNET_i2s (&n->id), GNUNET_TRANSPORT_ps2s (n->state)); /* depending on state, notify neighbour and/or upper layers of this peer about disconnect */ switch (n->state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: case GNUNET_TRANSPORT_PS_INIT_ATS: /* other peer is completely unaware of us, no need to send DISCONNECT */ free_neighbour (n, GNUNET_NO); return; case GNUNET_TRANSPORT_PS_CONNECT_SENT: send_disconnect (n); set_state (n, GNUNET_TRANSPORT_PS_DISCONNECT); break; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: /* we never ACK'ed the other peer's request, no need to send DISCONNECT */ free_neighbour (n, GNUNET_NO); return; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: /* we DID ACK the other peer's request, must send DISCONNECT */ send_disconnect (n); set_state (n, GNUNET_TRANSPORT_PS_DISCONNECT); break; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: case GNUNET_TRANSPORT_PS_CONNECTED: case GNUNET_TRANSPORT_PS_RECONNECT_SENT: /* we are currently connected, need to send disconnect and do internal notifications and update statistics */ send_disconnect (n); GNUNET_STATISTICS_set (GST_stats, gettext_noop ("# peers connected"), --neighbours_connected, GNUNET_NO); disconnect_notify_cb (callback_cls, &n->id); set_state (n, GNUNET_TRANSPORT_PS_DISCONNECT); break; case GNUNET_TRANSPORT_PS_RECONNECT_ATS: /* Disconnecting while waiting for an ATS address to reconnect, * cannot send DISCONNECT */ free_neighbour (n, GNUNET_NO); return; case GNUNET_TRANSPORT_PS_DISCONNECT: /* already disconnected, ignore */ break; case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: /* already cleaned up, how did we get here!? */ GNUNET_assert (0); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s'\n", GNUNET_TRANSPORT_ps2s (n->state)); GNUNET_break (0); break; } /* schedule timeout to clean up */ if (GNUNET_SCHEDULER_NO_TASK != n->task) GNUNET_SCHEDULER_cancel (n->task); n->task = GNUNET_SCHEDULER_add_delayed (DISCONNECT_SENT_TIMEOUT, &master_task, n); } /** * We're done with our transmission attempt, continue processing. * * @param cls the `struct MessageQueue` of the message * @param receiver intended receiver * @param success whether it worked or not * @param size_payload bytes payload sent * @param physical bytes sent on wire */ static void transmit_send_continuation (void *cls, const struct GNUNET_PeerIdentity *receiver, int success, size_t size_payload, size_t physical) { struct MessageQueue *mq = cls; struct NeighbourMapEntry *n; if (NULL == (n = lookup_neighbour (receiver))) { GNUNET_free (mq); return; /* disconnect or other error while transmitting, can happen */ } if (n->is_active == mq) { /* this is still "our" neighbour, remove us from its queue and allow it to send the next message now */ n->is_active = NULL; if (GNUNET_SCHEDULER_NO_TASK != n->task) GNUNET_SCHEDULER_cancel (n->task); n->task = GNUNET_SCHEDULER_add_now (&master_task, n); } if (bytes_in_send_queue < mq->message_buf_size) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Bytes_in_send_queue `%u', Message_size %u, result: %s, payload %u, on wire %u\n", bytes_in_send_queue, mq->message_buf_size, (GNUNET_OK == success) ? "OK" : "FAIL", size_payload, physical); GNUNET_break (0); } GNUNET_break (size_payload == mq->message_buf_size); bytes_in_send_queue -= mq->message_buf_size; GNUNET_STATISTICS_set (GST_stats, gettext_noop ("# bytes in message queue for other peers"), bytes_in_send_queue, GNUNET_NO); if (GNUNET_OK == success) GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# messages transmitted to other peers"), 1, GNUNET_NO); else GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# transmission failures for messages to other peers"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message to `%s' of type %u was a %s\n", GNUNET_i2s (receiver), ntohs (((struct GNUNET_MessageHeader *) mq->message_buf)->type), (success == GNUNET_OK) ? "success" : "FAILURE"); if (NULL != mq->cont) mq->cont (mq->cont_cls, success, size_payload, physical); GNUNET_free (mq); } /** * Check the message list for the given neighbour and if we can * send a message, do so. This function should only be called * if the connection is at least generally ready for transmission. * While we will only send one message at a time, no bandwidth * quota management is performed here. If a message was given to * the plugin, the continuation will automatically re-schedule * the 'master' task once the next message might be transmitted. * * @param n target peer for which to transmit */ static void try_transmission_to_peer (struct NeighbourMapEntry *n) { struct MessageQueue *mq; struct GNUNET_TIME_Relative timeout; if (NULL == n->primary_address.address) { /* no address, why are we here? */ GNUNET_break (0); return; } if ((0 == n->primary_address.address->address_length) && (NULL == n->primary_address.session)) { /* no address, why are we here? */ GNUNET_break (0); return; } if (NULL != n->is_active) { /* transmission already pending */ return; } /* timeout messages from the queue that are past their due date */ while (NULL != (mq = n->messages_head)) { timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout); if (timeout.rel_value_us > 0) break; GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# messages timed out while in transport queue"), 1, GNUNET_NO); GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq); n->is_active = mq; transmit_send_continuation (mq, &n->id, GNUNET_SYSERR, mq->message_buf_size, 0); /* timeout */ } if (NULL == mq) return; /* no more messages */ GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq); n->is_active = mq; (void) send_with_session (n, mq->message_buf, mq->message_buf_size, 0 /* priority */, timeout, GNUNET_NO, &transmit_send_continuation, mq); } /** * Send keepalive message to the neighbour. Must only be called * if we are on 'connected' state or while trying to switch addresses. * Will internally determine if a keepalive is truly needed (so can * always be called). * * @param n neighbour that went idle and needs a keepalive */ static void send_keepalive (struct NeighbourMapEntry *n) { struct SessionKeepAliveMessage m; struct GNUNET_TIME_Relative timeout; uint32_t nonce; GNUNET_assert ((GNUNET_TRANSPORT_PS_CONNECTED == n->state) || (GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT)); if (GNUNET_TIME_absolute_get_remaining (n->keep_alive_time).rel_value_us > 0) return; /* no keepalive needed at this time */ nonce = 0; /* 0 indicates 'not set' */ while (0 == nonce) nonce = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending keep alive to peer `%s' with nonce %u\n", GNUNET_i2s (&n->id), nonce); m.header.size = htons (sizeof (struct SessionKeepAliveMessage)); m.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE); m.nonce = htonl (nonce); timeout = send_with_session (n, (const void *) &m, sizeof (m), UINT32_MAX /* priority */, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, NULL, NULL); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# keepalives sent"), 1, GNUNET_NO); n->primary_address.keep_alive_nonce = nonce; n->expect_latency_response = GNUNET_YES; n->last_keep_alive_time = GNUNET_TIME_absolute_get (); n->keep_alive_time = GNUNET_TIME_relative_to_absolute (timeout); } /** * Keep the connection to the given neighbour alive longer, * we received a KEEPALIVE (or equivalent); send a response. * * @param neighbour neighbour to keep alive (by sending keep alive response) * @param m the keep alive message containing the nonce to respond to */ void GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m) { struct NeighbourMapEntry *n; const struct SessionKeepAliveMessage *msg_in; struct SessionKeepAliveMessage msg; if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size)) return; msg_in = (struct SessionKeepAliveMessage *) m; if (NULL == (n = lookup_neighbour (neighbour))) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# KEEPALIVE messages discarded (peer unknown)"), 1, GNUNET_NO); return; } if (NULL == n->primary_address.session) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# KEEPALIVE messages discarded (no session)"), 1, GNUNET_NO); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received keep alive request from peer `%s' with nonce %u\n", GNUNET_i2s (&n->id), ntohl (msg_in->nonce)); /* send reply to allow neighbour to measure latency */ msg.header.size = htons (sizeof (struct SessionKeepAliveMessage)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE); msg.nonce = msg_in->nonce; (void) send_with_session(n, (const void *) &msg, sizeof (struct SessionKeepAliveMessage), UINT32_MAX /* priority */, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, NULL, NULL); } /** * We received a KEEP_ALIVE_RESPONSE message and use this to calculate * latency to this peer. Pass the updated information (existing ats * plus calculated latency) to ATS. * * @param neighbour neighbour to keep alive * @param m the message containing the keep alive response */ void GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m) { struct NeighbourMapEntry *n; const struct SessionKeepAliveMessage *msg; struct GNUNET_TRANSPORT_PluginFunctions *papi; uint32_t latency; struct GNUNET_ATS_Information ats; if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size)) return; msg = (const struct SessionKeepAliveMessage *) m; if (NULL == (n = lookup_neighbour (neighbour))) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# KEEPALIVE_RESPONSE messages discarded (not connected)"), 1, GNUNET_NO); return; } if ( (GNUNET_TRANSPORT_PS_CONNECTED != n->state) || (GNUNET_YES != n->expect_latency_response) ) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# KEEPALIVE_RESPONSE messages discarded (not expected)"), 1, GNUNET_NO); return; } if (NULL == n->primary_address.address) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# KEEPALIVE_RESPONSE messages discarded (address changed)"), 1, GNUNET_NO); return; } if (n->primary_address.keep_alive_nonce != ntohl (msg->nonce)) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# KEEPALIVE_RESPONSE messages discarded (wrong nonce)"), 1, GNUNET_NO); return; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received keep alive response from peer `%s' for session %p\n", GNUNET_i2s (&n->id), n->primary_address.session); } /* Update session timeout here */ if (NULL != (papi = GST_plugins_find (n->primary_address.address->transport_name))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating session for peer `%s' for session %p\n", GNUNET_i2s (&n->id), n->primary_address.session); papi->update_session_timeout (papi->cls, &n->id, n->primary_address.session); } else { GNUNET_break (0); } n->primary_address.keep_alive_nonce = 0; n->expect_latency_response = GNUNET_NO; n->latency = GNUNET_TIME_absolute_get_duration (n->last_keep_alive_time); set_timeout (n, GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Latency for peer `%s' is %s\n", GNUNET_i2s (&n->id), GNUNET_STRINGS_relative_time_to_string (n->latency, GNUNET_YES)); /* append latency */ ats.type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); if (n->latency.rel_value_us > UINT32_MAX) latency = UINT32_MAX; else latency = n->latency.rel_value_us; ats.value = htonl (latency); GST_ats_update_metrics (&n->id, n->primary_address.address, n->primary_address.session, &ats, 1); } /** * We have received a message from the given sender. How long should * we delay before receiving more? (Also used to keep the peer marked * as live). * * @param sender sender of the message * @param size size of the message * @param do_forward set to #GNUNET_YES if the message should be forwarded to clients * #GNUNET_NO if the neighbour is not connected or violates the quota, * #GNUNET_SYSERR if the connection is not fully up yet * @return how long to wait before reading more from this sender */ struct GNUNET_TIME_Relative GST_neighbours_calculate_receive_delay (const struct GNUNET_PeerIdentity *sender, ssize_t size, int *do_forward) { struct NeighbourMapEntry *n; struct GNUNET_TIME_Relative ret; if (NULL == neighbours) { *do_forward = GNUNET_NO; return GNUNET_TIME_UNIT_FOREVER_REL; /* This can happen during shutdown */ } if (NULL == (n = lookup_neighbour (sender))) { GST_neighbours_try_connect (sender); if (NULL == (n = lookup_neighbour (sender))) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# messages discarded due to lack of neighbour record"), 1, GNUNET_NO); *do_forward = GNUNET_NO; return GNUNET_TIME_UNIT_ZERO; } } if (! test_connected (n)) { *do_forward = GNUNET_SYSERR; return GNUNET_TIME_UNIT_ZERO; } if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, size)) { n->quota_violation_count++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth quota (%u b/s) violation detected (total of %u).\n", n->in_tracker.available_bytes_per_s__, n->quota_violation_count); /* Discount 32k per violation */ GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, -32 * 1024); } else { if (n->quota_violation_count > 0) { /* try to add 32k back */ GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, 32 * 1024); n->quota_violation_count--; } } if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bandwidth quota violations by other peers"), 1, GNUNET_NO); *do_forward = GNUNET_NO; return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT; } *do_forward = GNUNET_YES; ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 32 * 1024); if (ret.rel_value_us > 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Throttling read (%llu bytes excess at %u b/s), waiting %s before reading more.\n", (unsigned long long) n->in_tracker. consumption_since_last_update__, (unsigned int) n->in_tracker.available_bytes_per_s__, GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# ms throttling suggested"), (int64_t) ret.rel_value_us / 1000LL, GNUNET_NO); } return ret; } /** * Transmit a message to the given target using the active connection. * * @param target destination * @param msg message to send * @param msg_size number of bytes in msg * @param timeout when to fail with timeout * @param cont function to call when done * @param cont_cls closure for 'cont' */ void GST_neighbours_send (const struct GNUNET_PeerIdentity *target, const void *msg, size_t msg_size, struct GNUNET_TIME_Relative timeout, GST_NeighbourSendContinuation cont, void *cont_cls) { struct NeighbourMapEntry *n; struct MessageQueue *mq; /* All ove these cases should never happen; they are all API violations. But we check anyway, just to be sure. */ if (NULL == (n = lookup_neighbour (target))) { GNUNET_break (0); if (NULL != cont) cont (cont_cls, GNUNET_SYSERR, msg_size, 0); return; } if (GNUNET_YES != test_connected (n)) { GNUNET_break (0); if (NULL != cont) cont (cont_cls, GNUNET_SYSERR, msg_size, 0); return; } bytes_in_send_queue += msg_size; GNUNET_STATISTICS_set (GST_stats, gettext_noop ("# bytes in message queue for other peers"), bytes_in_send_queue, GNUNET_NO); mq = GNUNET_malloc (sizeof (struct MessageQueue) + msg_size); mq->cont = cont; mq->cont_cls = cont_cls; memcpy (&mq[1], msg, msg_size); mq->message_buf = (const char *) &mq[1]; mq->message_buf_size = msg_size; mq->timeout = GNUNET_TIME_relative_to_absolute (timeout); GNUNET_CONTAINER_DLL_insert_tail (n->messages_head, n->messages_tail, mq); if ( (NULL != n->is_active) || ( (NULL == n->primary_address.session) && (NULL == n->primary_address.address)) ) return; if (GNUNET_SCHEDULER_NO_TASK != n->task) GNUNET_SCHEDULER_cancel (n->task); n->task = GNUNET_SCHEDULER_add_now (&master_task, n); } static void send_session_connect_cont (void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire) { struct NeighbourMapEntry *n; n = lookup_neighbour (target); if (NULL == n) { /* CONNECT continuation was called after neighbor was freed, * for example due to a time out for the state or the session * used was already terminated: nothing to do here... */ return; } if ( (GNUNET_TRANSPORT_PS_CONNECT_SENT != n->state) && (GNUNET_TRANSPORT_PS_RECONNECT_SENT != n->state) && (GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT != n->state)) { /* CONNECT continuation was called after neighbor changed state, * for example due to a time out for the state or the session * used was already terminated: nothing to do here... */ return; } if (GNUNET_OK == result) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Failed to send CONNECT message to peer `%s' using address `%s' session %p\n"), GNUNET_i2s (target), GST_plugins_a2s (n->primary_address.address), n->primary_address.session); switch (n->state) { case GNUNET_TRANSPORT_PS_CONNECT_SENT: /* Remove address and request and additional one */ GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, n->primary_address.session); GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, NULL ); unset_primary_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_ATS, GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: /* Remove address and request and additional one */ GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, n->primary_address.session); GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, NULL ); unset_primary_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: /* Remove address and request and go back to primary address */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# Failed attempts to switch addresses (failed to send CONNECT CONT)"), 1, GNUNET_NO); GNUNET_ATS_address_destroyed (GST_ats, n->alternative_address.address, n->alternative_address.session); GNUNET_ATS_address_destroyed (GST_ats, n->alternative_address.address, NULL ); unset_alternative_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECTED, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); break; default: GNUNET_break(0); disconnect_neighbour (n); break; } } /** * Send a SESSION_CONNECT message via the given address. * * @param na address to use */ static void send_session_connect (struct NeighbourAddress *na) { struct GNUNET_TRANSPORT_PluginFunctions *papi; struct SessionConnectMessage connect_msg; struct NeighbourMapEntry *n; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending SESSION_CONNECT message to peer `%s'\n", GNUNET_i2s (&na->address->peer)); if (NULL == (papi = GST_plugins_find (na->address->transport_name))) { GNUNET_break (0); return; } if (NULL == na->session) na->session = papi->get_session (papi->cls, na->address); if (NULL == na->session) { GNUNET_break (0); return; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# SESSION_CONNECT messages sent"), 1, GNUNET_NO); na->connect_timestamp = GNUNET_TIME_absolute_get (); connect_msg.header.size = htons (sizeof (struct SessionConnectMessage)); connect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT); connect_msg.reserved = htonl (0); connect_msg.timestamp = GNUNET_TIME_absolute_hton (na->connect_timestamp); if (-1 == papi->send (papi->cls, na->session, (const char *) &connect_msg, sizeof (struct SessionConnectMessage), UINT_MAX, SETUP_CONNECTION_TIMEOUT, send_session_connect_cont, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to transmit CONNECT message via plugin to %s\n"), GST_plugins_a2s (na->address)); n = lookup_neighbour (&na->address->peer); if (NULL == n) { GNUNET_break (0); return; } switch (n->state) { case GNUNET_TRANSPORT_PS_CONNECT_SENT: /* Remove address and request and additional one */ unset_primary_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_ATS, GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT)); /* Hard failure to send the CONNECT message with this address: Destroy address and session */ break; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: /* Remove address and request and additional one */ unset_primary_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# Failed attempts to switch addresses (failed to send CONNECT)"), 1, GNUNET_NO); /* Remove address and request and additional one */ unset_alternative_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECTED, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); break; default: GNUNET_break (0); disconnect_neighbour (n); break; } GNUNET_ATS_address_destroyed (GST_ats, na->address, na->session); GNUNET_ATS_address_destroyed (GST_ats, na->address, NULL); } GST_neighbours_notify_data_sent (&na->address->peer, na->address, na->session, sizeof (struct SessionConnectMessage)); } static void send_session_connect_ack_cont (void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t size_payload, size_t size_on_wire) { struct NeighbourMapEntry *n; n = lookup_neighbour (target); if (NULL == n) { /* CONNECT_ACK continuation was called after neighbor was freed, * for example due to a time out for the state or the session * used was already terminated: nothing to do here... */ return; } if (GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK != n->state) { /* CONNECT_ACK continuation was called after neighbor changed state, * for example due to a time out for the state or the session * used was already terminated: nothing to do here... */ return; } if (GNUNET_OK == result) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Failed to send CONNECT_ACK message to peer `%s' using address `%s' session %p\n"), GNUNET_i2s (target), GST_plugins_a2s (n->primary_address.address), n->primary_address.session); /* Failed to send CONNECT_ACK message with this address */ GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, n->primary_address.session); GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, NULL); /* Remove address and request and additional one */ unset_primary_address (n); n->ack_state = ACK_SEND_CONNECT_ACK; set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); return; } /** * Send a CONNECT_ACK message via the given address. * * @param address address to use * @param session session to use * @param timestamp timestamp to use for the ACK message * @return GNUNET_SYSERR if sending immediately failed, GNUNET_OK otherwise */ static void send_connect_ack_message (const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_TIME_Absolute timestamp) { struct GNUNET_TRANSPORT_PluginFunctions *papi; struct SessionConnectMessage connect_msg; struct NeighbourMapEntry *n; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending CONNECT_ACK to peer `%s'\n", GNUNET_i2s (&address->peer)); if (NULL == (papi = GST_plugins_find (address->transport_name))) { GNUNET_break (0); return; } if (NULL == session) session = papi->get_session (papi->cls, address); if (NULL == session) { GNUNET_break (0); return; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# CONNECT_ACK messages sent"), 1, GNUNET_NO); connect_msg.header.size = htons (sizeof (struct SessionConnectMessage)); connect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK); connect_msg.reserved = htonl (0); connect_msg.timestamp = GNUNET_TIME_absolute_hton (timestamp); if (GNUNET_SYSERR == papi->send (papi->cls, session, (const char *) &connect_msg, sizeof (struct SessionConnectMessage), UINT_MAX, GNUNET_TIME_UNIT_FOREVER_REL, send_session_connect_ack_cont, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to transmit CONNECT_ACK message via plugin to %s\n"), GST_plugins_a2s (address)); n = lookup_neighbour (&address->peer); if (NULL == n) { GNUNET_break (0); return; } /* Hard failure to send the CONNECT_ACK message with this address: Destroy session (and address) */ if (GNUNET_YES == GNUNET_HELLO_address_check_option(address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)) { GNUNET_ATS_address_destroyed (GST_ats, address, session); GNUNET_ATS_address_destroyed (GST_ats, address, NULL); } else GNUNET_ATS_address_destroyed (GST_ats, address, session); /* Remove address and request and additional one */ unset_primary_address (n); n->ack_state = ACK_SEND_CONNECT_ACK; set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); return; } } struct QuotaNotificationRequest { struct GNUNET_PeerIdentity peer; struct Session *session; char *plugin; }; struct QNR_LookContext { struct GNUNET_PeerIdentity peer; struct Session *session; const char *plugin; struct QuotaNotificationRequest *res; }; static int find_notification_request (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct QNR_LookContext *qnr_ctx = cls; struct QuotaNotificationRequest *qnr = value; if ((qnr->session == qnr_ctx->session) && (0 == memcmp (&qnr->peer, &qnr_ctx->peer, sizeof (struct GNUNET_PeerIdentity))) && (0 == strcmp(qnr_ctx->plugin, qnr->plugin))) { qnr_ctx->res = value; return GNUNET_NO; } return GNUNET_YES; } void GST_neighbours_register_quota_notification(void *cls, const struct GNUNET_PeerIdentity *peer, const char *plugin, struct Session *session) { struct QuotaNotificationRequest *qnr; struct QNR_LookContext qnr_ctx; if (NULL == registered_quota_notifications) { return; /* init or shutdown */ } qnr_ctx.peer = (*peer); qnr_ctx.plugin = plugin; qnr_ctx.session = session; qnr_ctx.res = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (registered_quota_notifications, peer, &find_notification_request, &qnr_ctx); if (NULL != qnr_ctx.res) { GNUNET_break(0); return; } qnr = GNUNET_new (struct QuotaNotificationRequest); qnr->peer = (*peer); qnr->plugin = GNUNET_strdup (plugin); qnr->session = session; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding notification for peer `%s' plugin `%s' session %p \n", GNUNET_i2s (peer), plugin, session); GNUNET_CONTAINER_multipeermap_put (registered_quota_notifications, peer, qnr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } void GST_neighbours_unregister_quota_notification(void *cls, const struct GNUNET_PeerIdentity *peer, const char *plugin, struct Session *session) { struct QNR_LookContext qnr_ctx; if (NULL == registered_quota_notifications) { return; /* init or shutdown */ } qnr_ctx.peer = (*peer); qnr_ctx.plugin = plugin; qnr_ctx.session = session; qnr_ctx.res = NULL; GNUNET_CONTAINER_multipeermap_iterate (registered_quota_notifications, &find_notification_request, &qnr_ctx); if (NULL == qnr_ctx.res) { GNUNET_break(0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing notification for peer `%s' plugin `%s' session %p \n", GNUNET_i2s (peer), plugin, session); GNUNET_CONTAINER_multipeermap_remove (registered_quota_notifications, peer, qnr_ctx.res); GNUNET_free (qnr_ctx.res->plugin); GNUNET_free (qnr_ctx.res); } static int notification_cb(void *cls, const struct GNUNET_PeerIdentity *key, void *value) { /* struct NeighbourMapEntry *n = cls; */ struct QuotaNotificationRequest *qnr = value; struct GNUNET_TRANSPORT_PluginFunctions *papi; struct GNUNET_TIME_Relative delay; int do_forward; papi = GST_plugins_find(qnr->plugin); if (NULL == papi) { GNUNET_break (0); return GNUNET_OK; } delay = GST_neighbours_calculate_receive_delay (key, 0, &do_forward); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New inbound delay for peer `%s' is %llu ms\n", GNUNET_i2s (key), delay.rel_value_us / 1000); if (NULL != papi->update_inbound_delay) papi->update_inbound_delay (papi->cls, key, qnr->session, delay); return GNUNET_OK; } static int free_notification_cb(void *cls, const struct GNUNET_PeerIdentity *key, void *value) { /* struct NeighbourMapEntry *n = cls; */ struct QuotaNotificationRequest *qnr = value; GNUNET_break (GNUNET_OK != GNUNET_CONTAINER_multipeermap_remove (registered_quota_notifications, key, qnr)); GNUNET_free(qnr->plugin); GNUNET_free(qnr); return GNUNET_OK; } static void inbound_bw_tracker_update(void *cls) { struct NeighbourMapEntry *n = cls; /* Quota was updated, tell plugins to update the time to receive next */ GNUNET_CONTAINER_multipeermap_get_multiple (registered_quota_notifications, &n->id, ¬ification_cb, n); } /** * Create a fresh entry in the neighbour map for the given peer * * @param peer peer to create an entry for * @return new neighbour map entry */ static struct NeighbourMapEntry * setup_neighbour (const struct GNUNET_PeerIdentity *peer) { struct NeighbourMapEntry *n; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating new neighbour entry for `%s'\n", GNUNET_i2s (peer)); n = GNUNET_new (struct NeighbourMapEntry); n->id = *peer; n->ack_state = ACK_UNDEFINED; n->latency = GNUNET_TIME_UNIT_FOREVER_REL; n->last_util_transmission = GNUNET_TIME_absolute_get(); n->util_payload_bytes_recv = 0; n->util_payload_bytes_sent = 0; n->util_total_bytes_recv = 0; n->util_total_bytes_sent = 0; GNUNET_BANDWIDTH_tracker_init (&n->in_tracker, &inbound_bw_tracker_update, n, GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, MAX_BANDWIDTH_CARRY_S); n->task = GNUNET_SCHEDULER_add_now (&master_task, n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_FOREVER_ABS); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (neighbours, &n->id, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return n; } /* We received a address suggestion after requesting an address in * try_connect or after receiving a connect, switch to address */ static void address_suggest_cont (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { GST_neighbours_switch_to_address(peer, address, session, ats, ats_count, bandwidth_in, bandwidth_out); } struct BlacklistCheckSwitchContext { struct BlacklistCheckSwitchContext *prev; struct BlacklistCheckSwitchContext *next; struct GST_BlacklistCheck *blc; struct GNUNET_HELLO_Address *address; struct Session *session; struct GNUNET_ATS_Information *ats; uint32_t ats_count; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; }; /** * Black list check result for try_connect call * If connection to the peer is allowed request adddress and * * @param cls blc_ctx bl context * @param peer the peer * @param result the result */ static void try_connect_bl_check_cont (void *cls, const struct GNUNET_PeerIdentity *peer, int result) { struct BlacklistCheckSwitchContext *blc_ctx = cls; struct NeighbourMapEntry *n; GNUNET_CONTAINER_DLL_remove (pending_bc_head, pending_bc_tail, blc_ctx); GNUNET_free (blc_ctx); if (GNUNET_OK != result) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Blacklisting disapproved to connect to peer `%s'\n"), GNUNET_i2s (peer)); return; } /* Setup a new neighbour */ n = setup_neighbour (peer); /* Request address suggestions for this peer */ set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); GNUNET_ATS_reset_backoff (GST_ats, peer); n->suggest_handle = GNUNET_ATS_suggest_address (GST_ats, peer, &address_suggest_cont, n); } /** * Try to create a connection to the given target (eventually). * * @param target peer to try to connect to */ void GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target) { struct NeighbourMapEntry *n; struct GST_BlacklistCheck *blc; struct BlacklistCheckSwitchContext *blc_ctx; if (NULL == neighbours) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked to connect to peer `%s' during shutdown\n", GNUNET_i2s (target)); return; /* during shutdown, do nothing */ } n = lookup_neighbour (target); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Asked to connect to peer `%s' (state: %s)\n", GNUNET_i2s (target), (NULL != n) ? GNUNET_TRANSPORT_ps2s(n->state) : "NEW PEER"); if (NULL != n) { switch (n->state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: /* this should not be possible */ GNUNET_break (0); free_neighbour (n, GNUNET_NO); break; case GNUNET_TRANSPORT_PS_INIT_ATS: case GNUNET_TRANSPORT_PS_CONNECT_SENT: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Ignoring request to try to connect to `%s', already trying!\n", GNUNET_i2s (target)); return; /* already trying */ case GNUNET_TRANSPORT_PS_CONNECTED: case GNUNET_TRANSPORT_PS_RECONNECT_ATS: case GNUNET_TRANSPORT_PS_RECONNECT_SENT: case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Ignoring request to try to connect, already connected to `%s'!\n", GNUNET_i2s (target)); return; /* already connected */ case GNUNET_TRANSPORT_PS_DISCONNECT: /* get rid of remains, ready to re-try immediately */ free_neighbour (n, GNUNET_NO); break; case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: /* should not be possible */ GNUNET_assert (0); return; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s'\n", GNUNET_TRANSPORT_ps2s (n->state)); GNUNET_break (0); free_neighbour (n, GNUNET_NO); break; } } /* Do blacklist check if connecting to this peer is allowed */ blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext); GNUNET_CONTAINER_DLL_insert (pending_bc_head, pending_bc_tail, blc_ctx); if (NULL != (blc = GST_blacklist_test_allowed (target, NULL, &try_connect_bl_check_cont, blc_ctx))) { blc_ctx->blc = blc; } } /** * We received a 'SESSION_CONNECT' message from the other peer. * Consider switching to it. * * @param message possibly a 'struct SessionConnectMessage' (check format) * @param peer identity of the peer to switch the address for * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer) { const struct SessionConnectMessage *scm; struct NeighbourMapEntry *n; struct GNUNET_TIME_Absolute ts; if (ntohs (message->size) != sizeof (struct SessionConnectMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# CONNECT messages received"), 1, GNUNET_NO); if (NULL == neighbours) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("CONNECT request from peer `%s' ignored due impending shutdown\n"), GNUNET_i2s (peer)); return GNUNET_OK; /* we're shutting down */ } scm = (const struct SessionConnectMessage *) message; GNUNET_break_op (0 == ntohl (scm->reserved)); ts = GNUNET_TIME_absolute_ntoh (scm->timestamp); n = lookup_neighbour (peer); if (NULL == n) { /* This is a new neighbour and set to not connected */ n = setup_neighbour (peer); } /* Remember this CONNECT message in neighbour */ n->ack_state = ACK_SEND_CONNECT_ACK; n->connect_ack_timestamp = ts; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CONNECT for peer `%s' in state %s/%s\n", GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s (n->state), print_ack_state (n->ack_state)); switch (n->state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: /* Request an address from ATS to send CONNECT_ACK to this peer */ set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); if (NULL == n->suggest_handle) GNUNET_ATS_suggest_address (GST_ats, peer, address_suggest_cont, n); break; case GNUNET_TRANSPORT_PS_INIT_ATS: /* CONNECT message takes priority over us asking ATS for address: * Wait for ATS to suggest an address and send CONNECT_ACK */ set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: /* We already wait for an address to send an CONNECT_ACK */ break; case GNUNET_TRANSPORT_PS_CONNECT_SENT: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: /* Send ACK immediately */ n->ack_state = ACK_SEND_SESSION_ACK; send_connect_ack_message (n->primary_address.address, n->primary_address.session, ts); break; case GNUNET_TRANSPORT_PS_CONNECTED: /* we are already connected and can thus send the ACK immediately */ GNUNET_assert (NULL != n->primary_address.address); GNUNET_assert (NULL != n->primary_address.session); n->ack_state = ACK_SEND_SESSION_ACK; send_connect_ack_message (n->primary_address.address, n->primary_address.session, ts); break; case GNUNET_TRANSPORT_PS_RECONNECT_ATS: /* We wait for ATS address suggestion */ break; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: /* We received a CONNECT message while waiting for a CONNECT_ACK in fast * reconnect. Send CONNECT_ACK immediately */ n->ack_state = ACK_SEND_SESSION_ACK; send_connect_ack_message (n->primary_address.address, n->primary_address.session, n->connect_ack_timestamp); break; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: /* We are already connected and can thus send the ACK immediately; still, it can never hurt to have an alternative address, so also tell ATS about it */ GNUNET_assert (NULL != n->primary_address.address); GNUNET_assert (NULL != n->primary_address.session); n->ack_state = ACK_SEND_SESSION_ACK; send_connect_ack_message (n->primary_address.address, n->primary_address.session, ts); break; case GNUNET_TRANSPORT_PS_DISCONNECT: /* Get rid of remains without terminating sessions, ready to re-try */ free_neighbour (n, GNUNET_YES); n = setup_neighbour (peer); /* Remember the CONNECT time stamp for ACK message */ n->ack_state = ACK_SEND_CONNECT_ACK; n->connect_ack_timestamp = ts; /* Request an address for the peer */ GNUNET_ATS_suggest_address (GST_ats, peer, address_suggest_cont, n); GNUNET_ATS_reset_backoff (GST_ats, peer); set_state (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS); break; case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: /* should not be possible */ GNUNET_assert (0); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s'\n", GNUNET_TRANSPORT_ps2s (n->state)); GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; } static void switch_address_bl_check_cont (void *cls, const struct GNUNET_PeerIdentity *peer, int result) { struct BlacklistCheckSwitchContext *blc_ctx = cls; struct GNUNET_TRANSPORT_PluginFunctions *papi; struct NeighbourMapEntry *n; papi = GST_plugins_find (blc_ctx->address->transport_name); if ( (NULL == (n = lookup_neighbour (peer))) || (result == GNUNET_NO) || (NULL == (papi)) ) { if (NULL == n) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %s is unknown, suggestion ignored\n", GNUNET_i2s (peer)); } if (result == GNUNET_NO) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist denied to switch to suggested address `%s' session %p for peer `%s'\n", GST_plugins_a2s (blc_ctx->address), blc_ctx->session, GNUNET_i2s (&blc_ctx->address->peer)); } if (NULL == papi) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plugin `%s' for suggested address `%s' session %p for peer `%s' is not available\n", blc_ctx->address->transport_name, GST_plugins_a2s (blc_ctx->address), blc_ctx->session, GNUNET_i2s (&blc_ctx->address->peer)); } /* This address is blacklisted, delete address and session (if existing) in ATS */ GNUNET_ATS_address_destroyed (GST_ats, blc_ctx->address, blc_ctx->session); if ( (GNUNET_YES == (GNUNET_HELLO_address_check_option (blc_ctx->address, GNUNET_HELLO_ADDRESS_INFO_INBOUND))) && (NULL != blc_ctx->session)) { /* This is an inbound address, destroy full address */ GNUNET_ATS_address_destroyed (GST_ats, blc_ctx->address, NULL ); } /* Remove blacklist check and clean up */ GNUNET_CONTAINER_DLL_remove (pending_bc_head, pending_bc_tail, blc_ctx); GNUNET_HELLO_address_free (blc_ctx->address); GNUNET_free_non_null (blc_ctx->ats); GNUNET_free (blc_ctx); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Blacklist accepted address `%s' session %p for peer `%s'\n", GST_plugins_a2s (blc_ctx->address), blc_ctx->session, GNUNET_i2s (&blc_ctx->address->peer)); if (NULL == blc_ctx->session) { blc_ctx->session = papi->get_session (papi->cls, blc_ctx->address); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Obtained new session for peer `%s' and address '%s': %p\n", GNUNET_i2s (&blc_ctx->address->peer), GST_plugins_a2s (blc_ctx->address), blc_ctx->session); } if (NULL == blc_ctx->session) { /* No session could be obtained, remove blacklist check and clean up */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to obtain new session for peer `%s' and address '%s'\n", GNUNET_i2s (&blc_ctx->address->peer), GST_plugins_a2s (blc_ctx->address)); /* Delete address in ATS */ GNUNET_ATS_address_destroyed (GST_ats, blc_ctx->address, NULL); GNUNET_CONTAINER_DLL_remove (pending_bc_head, pending_bc_tail, blc_ctx); GNUNET_HELLO_address_free (blc_ctx->address); GNUNET_free_non_null (blc_ctx->ats); GNUNET_free (blc_ctx); return; } switch (n->state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: GNUNET_break (0); free_neighbour (n, GNUNET_NO); return; case GNUNET_TRANSPORT_PS_INIT_ATS: /* We requested an address and ATS suggests one: * set primary address and send CONNECT message*/ set_primary_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO); if ( (ACK_SEND_CONNECT_ACK == n->ack_state) ) { /* Send pending CONNECT_ACK message */ n->ack_state = ACK_SEND_SESSION_ACK; send_connect_ack_message (n->primary_address.address, n->primary_address.session, n->connect_ack_timestamp); } set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_SENT, GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT)); send_session_connect (&n->primary_address); break; case GNUNET_TRANSPORT_PS_CONNECT_SENT: /* ATS suggested a new address while waiting for an CONNECT_ACK: * Switch and send new CONNECT */ /* ATS suggests a different address, switch again */ set_primary_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO); if (ACK_SEND_CONNECT_ACK == n->ack_state) { /* Send pending CONNECT_ACK message */ n->ack_state = ACK_SEND_SESSION_ACK; send_connect_ack_message (n->primary_address.address, n->primary_address.session, n->connect_ack_timestamp); } set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_SENT, GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT)); send_session_connect (&n->primary_address); break; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: /* We requested an address and ATS suggests one: * set primary address and send CONNECT_ACK message*/ set_primary_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO); /* Send an ACK message as a response to the CONNECT msg */ set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK, GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT)); send_connect_ack_message (n->primary_address.address, n->primary_address.session, n->connect_ack_timestamp); if ( (ACK_SEND_CONNECT_ACK == n->ack_state) || (ACK_UNDEFINED == n->ack_state) ) n->ack_state = ACK_SEND_SESSION_ACK; break; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: /* ATS asks us to switch while we were trying to connect; switch to new address and check blacklist again */ if ( (ACK_SEND_CONNECT_ACK == n->ack_state) ) { n->ack_state = ACK_SEND_SESSION_ACK; send_connect_ack_message (n->primary_address.address, n->primary_address.session, n->connect_ack_timestamp); } set_primary_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK, GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_CONNECTED: GNUNET_assert (NULL != n->primary_address.address); GNUNET_assert (NULL != n->primary_address.session); if (n->primary_address.session == blc_ctx->session) { /* not an address change, just a quota change */ set_primary_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_YES); break; } /* ATS asks us to switch a life connection; see if we can get a CONNECT_ACK on it before we actually do this! */ set_alternative_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT, GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# Attempts to switch addresses"), 1, GNUNET_NO); send_session_connect (&n->alternative_address); break; case GNUNET_TRANSPORT_PS_RECONNECT_ATS: set_primary_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO); if ( (ACK_SEND_CONNECT_ACK == n->ack_state) ) { /* Send pending CONNECT_ACK message */ n->ack_state = ACK_SEND_SESSION_ACK; send_connect_ack_message (n->primary_address.address, n->primary_address.session, n->connect_ack_timestamp); } set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_SENT, GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT)); send_session_connect (&n->primary_address); break; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: /* ATS asks us to switch while we were trying to reconnect; switch to new address and send CONNECT again */ set_primary_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out, GNUNET_NO); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_SENT, GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT)); send_session_connect (&n->primary_address); break; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: if ( (0 == GNUNET_HELLO_address_cmp(n->primary_address.address, blc_ctx->address) && n->primary_address.session == blc_ctx->session) ) { /* ATS switches back to still-active session */ free_address (&n->alternative_address); set_state (n, GNUNET_TRANSPORT_PS_CONNECTED); break; } /* ATS asks us to switch a life connection, send */ set_alternative_address (n, blc_ctx->address, blc_ctx->session, blc_ctx->bandwidth_in, blc_ctx->bandwidth_out); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT, GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT)); send_session_connect (&n->alternative_address); break; case GNUNET_TRANSPORT_PS_DISCONNECT: /* not going to switch addresses while disconnecting */ return; case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: GNUNET_assert (0); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s'\n", GNUNET_TRANSPORT_ps2s (n->state)); GNUNET_break (0); break; } GNUNET_CONTAINER_DLL_remove (pending_bc_head, pending_bc_tail, blc_ctx); GNUNET_HELLO_address_free(blc_ctx->address); GNUNET_free_non_null (blc_ctx->ats); GNUNET_free (blc_ctx); return; } /** * For the given peer, switch to this address. * * Before accepting this addresses and actively using it, a blacklist check * is performed. If this blacklist check fails the address will be destroyed. * * @param peer identity of the peer to switch the address for * @param address address of the other peer, * @param session session to use or NULL if transport should initiate a session * @param ats performance data * @param ats_count number of entries in ats * @param bandwidth_in inbound quota to be used when connection is up, * 0 to disconnect from peer * @param bandwidth_out outbound quota to be used when connection is up, * 0 to disconnect from peer */ void GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { struct NeighbourMapEntry *n; struct GST_BlacklistCheck *blc; struct BlacklistCheckSwitchContext *blc_ctx; int c; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS has decided on an address for peer %s\n", GNUNET_i2s (peer)); GNUNET_assert (NULL != address->transport_name); if (NULL == (n = lookup_neighbour (peer))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %s is unknown, suggestion ignored\n", GNUNET_i2s (peer)); return; } /* Check if plugin is available */ if (NULL == (GST_plugins_find (address->transport_name))) { /* we don't have the plugin for this address */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plugin `%s' is unknown, suggestion for peer %s ignored\n", address->transport_name, GNUNET_i2s (peer)); GNUNET_ATS_address_destroyed (GST_ats, address, NULL); return; } if ((NULL == session) && (GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND))) { /* This is a inbound address and we do not have a session to use! */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Inbound address without session `%s'! Destroying address...\n", GST_plugins_a2s (address)); GNUNET_ATS_address_destroyed (GST_ats, address, NULL); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ATS suggests %s address '%s' session %p for " "peer `%s' in state %s/%s (quota in/out %u %u )\n", GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? "inbound" : "outbound", GST_plugins_a2s (address), session, GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s (n->state), print_ack_state (n->ack_state), ntohl (bandwidth_in.value__), ntohl (bandwidth_out.value__)); /* Perform blacklist check */ blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext); blc_ctx->address = GNUNET_HELLO_address_copy (address); blc_ctx->session = session; blc_ctx->bandwidth_in = bandwidth_in; blc_ctx->bandwidth_out = bandwidth_out; blc_ctx->ats_count = ats_count; blc_ctx->ats = NULL; if (ats_count > 0) { blc_ctx->ats = GNUNET_malloc (ats_count * sizeof (struct GNUNET_ATS_Information)); for (c = 0; c < ats_count; c++) { blc_ctx->ats[c].type = ats[c].type; blc_ctx->ats[c].value = ats[c].value; } } GNUNET_CONTAINER_DLL_insert (pending_bc_head, pending_bc_tail, blc_ctx); if (NULL != (blc = GST_blacklist_test_allowed (peer, address->transport_name, &switch_address_bl_check_cont, blc_ctx))) { blc_ctx->blc = blc; } } static int send_utilization_data (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct NeighbourMapEntry *n = value; struct GNUNET_ATS_Information atsi[4]; uint32_t bps_pl_in; uint32_t bps_pl_out; uint32_t bps_in; uint32_t bps_out; struct GNUNET_TIME_Relative delta; delta = GNUNET_TIME_absolute_get_difference (n->last_util_transmission, GNUNET_TIME_absolute_get ()); bps_pl_in = 0; if ((0 != n->util_payload_bytes_recv) && (0 != delta.rel_value_us)) bps_pl_in = (1000LL * 1000LL * n->util_payload_bytes_recv) / (delta.rel_value_us); bps_pl_out = 0; if ((0 != n->util_payload_bytes_sent) && (0 != delta.rel_value_us)) bps_pl_out = (1000LL * 1000LL * n->util_payload_bytes_sent) / delta.rel_value_us; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' payload: received %u Bytes/s, sent %u Bytes/s\n", GNUNET_i2s (key), bps_pl_in, bps_pl_out); bps_in = 0; if ((0 != n->util_total_bytes_recv) && (0 != delta.rel_value_us)) bps_in = (1000LL * 1000LL * n->util_total_bytes_recv) / (delta.rel_value_us); bps_out = 0; if ((0 != n->util_total_bytes_sent) && (0 != delta.rel_value_us)) bps_out = (1000LL * 1000LL * n->util_total_bytes_sent) / delta.rel_value_us; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' total: received %u Bytes/s, sent %u Bytes/s\n", GNUNET_i2s (key), bps_in, bps_out); atsi[0].type = htonl (GNUNET_ATS_UTILIZATION_OUT); atsi[0].value = htonl (bps_out); atsi[1].type = htonl (GNUNET_ATS_UTILIZATION_IN); atsi[1].value = htonl (bps_in); atsi[2].type = htonl (GNUNET_ATS_UTILIZATION_PAYLOAD_OUT); atsi[2].value = htonl (bps_pl_out); atsi[3].type = htonl (GNUNET_ATS_UTILIZATION_PAYLOAD_IN); atsi[3].value = htonl (bps_pl_in); GST_ats_update_metrics (key, n->primary_address.address, n->primary_address.session, atsi, 4); n->util_payload_bytes_recv = 0; n->util_payload_bytes_sent = 0; n->util_total_bytes_recv = 0; n->util_total_bytes_sent = 0; n->last_util_transmission = GNUNET_TIME_absolute_get(); return GNUNET_OK; } /** * Task transmitting utilization in a regular interval * * @param cls the 'struct NeighbourMapEntry' for which we are running * @param tc scheduler context (unused) */ static void utilization_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { util_transmission_tk = GNUNET_SCHEDULER_NO_TASK; if (0 < GNUNET_CONTAINER_multipeermap_size (neighbours)) GNUNET_CONTAINER_multipeermap_iterate (neighbours, send_utilization_data, NULL); util_transmission_tk = GNUNET_SCHEDULER_add_delayed (UTIL_TRANSMISSION_INTERVAL, utilization_transmission, NULL); } void GST_neighbours_notify_data_recv (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message) { struct NeighbourMapEntry *n; n = lookup_neighbour (peer); if (NULL == n) return; n->util_total_bytes_recv += ntohs(message->size); } void GST_neighbours_notify_payload_recv (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message) { struct NeighbourMapEntry *n; n = lookup_neighbour (peer); if (NULL == n) return; n->util_payload_bytes_recv += ntohs(message->size); } void GST_neighbours_notify_data_sent (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, size_t size) { struct NeighbourMapEntry *n; n = lookup_neighbour (peer); if (NULL == n) return; if (n->primary_address.session != session) return; n->util_total_bytes_sent += size; } void GST_neighbours_notify_payload_sent (const struct GNUNET_PeerIdentity *peer, size_t size) { struct NeighbourMapEntry *n; n = lookup_neighbour (peer); if (NULL == n) return; n->util_payload_bytes_sent += size; } /** * Master task run for every neighbour. Performs all of the time-related * activities (keep alive, send next message, disconnect if idle, finish * clean up after disconnect). * * @param cls the 'struct NeighbourMapEntry' for which we are running * @param tc scheduler context (unused) */ static void master_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct NeighbourMapEntry *n = cls; struct GNUNET_TIME_Relative delay; n->task = GNUNET_SCHEDULER_NO_TASK; delay = GNUNET_TIME_absolute_get_remaining (n->timeout); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Master task runs for neighbour `%s' in state %s with timeout in %s\n", GNUNET_i2s (&n->id), GNUNET_TRANSPORT_ps2s(n->state), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); switch (n->state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: /* invalid state for master task, clean up */ GNUNET_break (0); free_neighbour (n, GNUNET_NO); return; case GNUNET_TRANSPORT_PS_INIT_ATS: if (0 == delay.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connection to `%s' timed out waiting for ATS to provide address\n", GNUNET_i2s (&n->id)); free_neighbour (n, GNUNET_NO); return; } break; case GNUNET_TRANSPORT_PS_CONNECT_SENT: if (0 == delay.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connection to `%s' timed out waiting for other peer to send CONNECT_ACK\n", GNUNET_i2s (&n->id)); /* We could not send to this address, delete address and session */ if (NULL != n->primary_address.session) GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, n->primary_address.session); GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, NULL); /* Remove address and request and additional one */ unset_primary_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); return; } break; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: if (0 == delay.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connection to `%s' timed out waiting ATS to provide address to use for CONNECT_ACK\n", GNUNET_i2s (&n->id)); free_neighbour (n, GNUNET_NO); return; } break; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: if (0 == delay.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connection to `%s' timed out waiting for other peer to send SESSION_ACK\n", GNUNET_i2s (&n->id)); disconnect_neighbour (n); return; } break; case GNUNET_TRANSPORT_PS_CONNECTED: if (0 == delay.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs\n", GNUNET_i2s (&n->id)); disconnect_neighbour (n); return; } try_transmission_to_peer (n); send_keepalive (n); break; case GNUNET_TRANSPORT_PS_RECONNECT_ATS: if (0 == delay.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connection to `%s' timed out, waiting for ATS replacement address\n", GNUNET_i2s (&n->id)); disconnect_neighbour (n); return; } break; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: if (0 == delay.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connection to `%s' timed out, waiting for other peer to CONNECT_ACK replacement address\n", GNUNET_i2s (&n->id)); disconnect_neighbour (n); return; } break; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: if (0 == delay.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs (after trying to CONNECT on alternative address)\n", GNUNET_i2s (&n->id)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# Failed attempts to switch addresses (no response)"), 1, GNUNET_NO); disconnect_neighbour (n); return; } try_transmission_to_peer (n); send_keepalive (n); break; case GNUNET_TRANSPORT_PS_DISCONNECT: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Cleaning up connection to `%s' after sending DISCONNECT\n", GNUNET_i2s (&n->id)); free_neighbour (n, GNUNET_NO); return; case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: /* how did we get here!? */ GNUNET_assert (0); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s'\n", GNUNET_TRANSPORT_ps2s (n->state)); GNUNET_break (0); break; } if ( (GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT == n->state) || (GNUNET_TRANSPORT_PS_CONNECTED == n->state) ) { /* if we are *now* in one of the two states, we're sending keep alive messages, so we need to consider the keepalive delay, not just the connection timeout */ delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (n->keep_alive_time), delay); } if (GNUNET_SCHEDULER_NO_TASK == n->task) n->task = GNUNET_SCHEDULER_add_delayed (delay, &master_task, n); } /** * Send a SESSION_ACK message to the neighbour to confirm that we * got his CONNECT_ACK. * * @param n neighbour to send the SESSION_ACK to */ static void send_session_ack_message (struct NeighbourMapEntry *n) { struct GNUNET_MessageHeader msg; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending SESSION_ACK message to peer `%s'\n", GNUNET_i2s (&n->id)); msg.size = htons (sizeof (struct GNUNET_MessageHeader)); msg.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK); (void) send_with_session(n, (const char *) &msg, sizeof (struct GNUNET_MessageHeader), UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, NULL, NULL); } /** * We received a 'SESSION_CONNECT_ACK' message from the other peer. * Consider switching to it. * * @param message possibly a 'struct SessionConnectMessage' (check format) * @param peer identity of the peer to switch the address for * @param address address of the other peer, NULL if other peer * connected to us * @param session session to use (or NULL) * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_neighbours_handle_connect_ack (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session) { const struct SessionConnectMessage *scm; struct GNUNET_TIME_Absolute ts; struct NeighbourMapEntry *n; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received CONNECT_ACK message from peer `%s'\n", GNUNET_i2s (peer)); if (ntohs (message->size) != sizeof (struct SessionConnectMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# CONNECT_ACK messages received"), 1, GNUNET_NO); scm = (const struct SessionConnectMessage *) message; GNUNET_break_op (ntohl (scm->reserved) == 0); if (NULL == (n = lookup_neighbour (peer))) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# unexpected CONNECT_ACK messages (no peer)"), 1, GNUNET_NO); return GNUNET_SYSERR; } ts = GNUNET_TIME_absolute_ntoh (scm->timestamp); switch (n->state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: GNUNET_break (0); free_neighbour (n, GNUNET_NO); return GNUNET_SYSERR; case GNUNET_TRANSPORT_PS_INIT_ATS: GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# unexpected CONNECT_ACK messages (not ready)"), 1, GNUNET_NO); break; case GNUNET_TRANSPORT_PS_CONNECT_SENT: if (ts.abs_value_us != n->primary_address.connect_timestamp.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CONNECT_ACK ignored as the timestamp does not match our CONNECT request\n"); return GNUNET_OK; } set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECTED, GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT)); GNUNET_STATISTICS_set (GST_stats, gettext_noop ("# peers connected"), ++neighbours_connected, GNUNET_NO); connect_notify_cb (callback_cls, &n->id, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out); /* Tell ATS that the outbound session we created to send CONNECT was successful */ GST_ats_add_address (n->primary_address.address, n->primary_address.session, NULL, 0); set_primary_address (n, n->primary_address.address, n->primary_address.session, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out, GNUNET_YES); send_session_ack_message (n); break; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# unexpected CONNECT_ACK messages (not ready)"), 1, GNUNET_NO); break; case GNUNET_TRANSPORT_PS_CONNECTED: /* duplicate CONNECT_ACK, let's answer by duplicate SESSION_ACK just in case */ send_session_ack_message (n); break; case GNUNET_TRANSPORT_PS_RECONNECT_ATS: /* we didn't expect any CONNECT_ACK, as we are waiting for ATS to give us a new address... */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# unexpected CONNECT_ACK messages (waiting on ATS)"), 1, GNUNET_NO); break; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: /* Reconnecting with new address address worked; go back to connected! */ set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECTED, GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT)); send_session_ack_message (n); break; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: /* new address worked; adopt it and go back to connected! */ set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECTED, GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT)); GNUNET_break (GNUNET_NO == n->alternative_address.ats_active); /* Notify about session... perhaps we obtained it */ GST_ats_add_address (n->alternative_address.address, n->alternative_address.session, NULL, 0); /* Set primary addresses */ set_primary_address (n, n->alternative_address.address, n->alternative_address.session, n->alternative_address.bandwidth_in, n->alternative_address.bandwidth_out, GNUNET_YES); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# Successful attempts to switch addresses"), 1, GNUNET_NO); free_address (&n->alternative_address); send_session_ack_message (n); break; case GNUNET_TRANSPORT_PS_DISCONNECT: GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# unexpected CONNECT_ACK messages (disconnecting)"), 1, GNUNET_NO); return GNUNET_SYSERR; case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: GNUNET_assert (0); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s'\n", GNUNET_TRANSPORT_ps2s (n->state)); GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; } /** * A session was terminated. Take note; if needed, try to get * an alternative address from ATS. * * @param peer identity of the peer where the session died * @param session session that is gone * @return #GNUNET_YES if this was a session used, #GNUNET_NO if * this session was not in use */ int GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer, struct Session *session) { struct NeighbourMapEntry *n; struct BlackListCheckContext *bcc; struct BlackListCheckContext *bcc_next; /* make sure to cancel all ongoing blacklist checks involving 'session' */ bcc_next = bc_head; while (NULL != (bcc = bcc_next)) { bcc_next = bcc->next; if (bcc->na.session == session) { if (NULL != bcc->bc) GST_blacklist_test_cancel (bcc->bc); GNUNET_HELLO_address_free (bcc->na.address); GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bcc); GNUNET_free (bcc); } } if (NULL == (n = lookup_neighbour (peer))) return GNUNET_NO; /* can't affect us */ if (session != n->primary_address.session) { if (session == n->alternative_address.session) { if ( (GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT == n->state) ) set_state (n, GNUNET_TRANSPORT_PS_CONNECTED); else free_address (&n->alternative_address); } return GNUNET_NO; /* doesn't affect us further */ } n->expect_latency_response = GNUNET_NO; /* The session for neighbour's primary address died */ switch (n->state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: GNUNET_break (0); free_neighbour (n, GNUNET_NO); return GNUNET_YES; case GNUNET_TRANSPORT_PS_INIT_ATS: GNUNET_break (0); free_neighbour (n, GNUNET_NO); return GNUNET_YES; case GNUNET_TRANSPORT_PS_CONNECT_SENT: /* The session used to send the CONNECT terminated: * this implies a connect error*/ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failed to send CONNECT in %s with `%s' %p: session terminated\n", "CONNECT_SENT", GST_plugins_a2s (n->primary_address.address), n->primary_address.session, GNUNET_i2s (peer)); /* Destroy the address since it cannot be used */ GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, NULL); unset_primary_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_INIT_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: /* error on inbound session; free neighbour entirely */ free_address (&n->primary_address); free_neighbour (n, GNUNET_NO); return GNUNET_YES; case GNUNET_TRANSPORT_PS_CONNECTED: /* Our primary connection died, try a fast reconnect */ unset_primary_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_RECONNECT_ATS: /* we don't have an address, how can it go down? */ GNUNET_break (0); break; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failed to send CONNECT in %s with `%s' %p: session terminated\n", "RECONNECT_SENT", GST_plugins_a2s (n->primary_address.address), n->primary_address.session, GNUNET_i2s (peer)); /* Destroy the address since it cannot be used */ GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, NULL); unset_primary_address (n); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_ATS, GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: /* primary went down while we were waiting for CONNECT_ACK on secondary; secondary as primary */ /* Destroy the inbound address since it cannot be used */ if (GNUNET_YES == GNUNET_HELLO_address_check_option (n->primary_address.address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)) GNUNET_ATS_address_destroyed (GST_ats, n->primary_address.address, NULL); free_address (&n->primary_address); n->primary_address = n->alternative_address; memset (&n->alternative_address, 0, sizeof (struct NeighbourAddress)); set_state_and_timeout (n, GNUNET_TRANSPORT_PS_RECONNECT_ATS, GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT)); break; case GNUNET_TRANSPORT_PS_DISCONNECT: free_address (&n->primary_address); break; case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: /* neighbour was freed and plugins told to terminate session */ return GNUNET_NO; break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s'\n", GNUNET_TRANSPORT_ps2s (n->state)); GNUNET_break (0); break; } if (GNUNET_SCHEDULER_NO_TASK != n->task) GNUNET_SCHEDULER_cancel (n->task); n->task = GNUNET_SCHEDULER_add_now (&master_task, n); return GNUNET_YES; } /** * We received a 'SESSION_ACK' message from the other peer. * If we sent a 'CONNECT_ACK' last, this means we are now * connected. Otherwise, do nothing. * * @param message possibly a 'struct SessionConnectMessage' (check format) * @param peer identity of the peer to switch the address for * @param address address of the other peer, NULL if other peer * connected to us * @param session session to use (or NULL) * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session) { struct NeighbourMapEntry *n; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received SESSION_ACK message from peer `%s'\n", GNUNET_i2s (peer)); if (ntohs (message->size) != sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# SESSION_ACK messages received"), 1, GNUNET_NO); if (NULL == (n = lookup_neighbour (peer))) { GNUNET_break_op (0); return GNUNET_SYSERR; } /* Check if we are in a plausible state for having sent a CONNECT_ACK. If not, return, otherwise break. The remote peers sends a SESSION_ACK as a response for a CONNECT_ACK message. We expect a SESSION_ACK: - If a remote peer has sent a CONNECT, we responded with a CONNECT_ACK and now wait for the ACK to finally be connected - If we sent a CONNECT_ACK to this peer before */ if ( (GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK != n->state) && (ACK_SEND_SESSION_ACK != n->ack_state)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received unexpected SESSION_ACK message from peer `%s' in state %s/%s\n", GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s (n->state), print_ack_state (n->ack_state)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# unexpected SESSION_ACK messages"), 1, GNUNET_NO); return GNUNET_OK; } /* We are connected */ if (GNUNET_NO == GST_neighbours_test_connected(&n->id)) { /* Notify about connection */ connect_notify_cb (callback_cls, &n->id, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out);\ GNUNET_STATISTICS_set (GST_stats, gettext_noop ("# peers connected"), ++neighbours_connected, GNUNET_NO); } set_state_and_timeout (n, GNUNET_TRANSPORT_PS_CONNECTED, GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT)); /* Add session to ATS since no session was given (NULL) and we may have * obtained a new session */ GST_ats_add_address (n->primary_address.address, n->primary_address.session, NULL, 0); /* Set primary address to used */ set_primary_address (n, n->primary_address.address, n->primary_address.session, n->primary_address.bandwidth_in, n->primary_address.bandwidth_out, GNUNET_YES); return GNUNET_OK; } /** * Test if we're connected to the given peer. * * @param target peer to test * @return #GNUNET_YES if we are connected, #GNUNET_NO if not */ int GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target) { return test_connected (lookup_neighbour (target)); } /** * Change the incoming quota for the given peer. * * @param neighbour identity of peer to change qutoa for * @param quota new quota */ void GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour, struct GNUNET_BANDWIDTH_Value32NBO quota) { struct NeighbourMapEntry *n; if (NULL == (n = lookup_neighbour (neighbour))) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# SET QUOTA messages ignored (no such peer)"), 1, GNUNET_NO); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting inbound quota of %u Bps for peer `%s' to all clients\n", ntohl (quota.value__), GNUNET_i2s (&n->id)); GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker, quota); if (0 != ntohl (quota.value__)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnecting peer `%4s' due to SET_QUOTA\n", GNUNET_i2s (&n->id)); if (GNUNET_YES == test_connected (n)) GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# disconnects due to quota of 0"), 1, GNUNET_NO); disconnect_neighbour (n); } void delayed_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { struct NeighbourMapEntry *n = cls; n->delayed_disconnect_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnecting by request from peer %s\n", GNUNET_i2s (&n->id)); free_neighbour (n, GNUNET_NO); } /** * We received a disconnect message from the given peer, * validate and process. * * @param peer sender of the message * @param msg the disconnect message */ void GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg) { struct NeighbourMapEntry *n; const struct SessionDisconnectMessage *sdm; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received DISCONNECT message from peer `%s'\n", GNUNET_i2s (peer)); if (ntohs (msg->size) != sizeof (struct SessionDisconnectMessage)) { GNUNET_break_op (0); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# disconnect messages ignored (malformed)"), 1, GNUNET_NO); return; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# DISCONNECT messages received"), 1, GNUNET_NO); sdm = (const struct SessionDisconnectMessage *) msg; if (NULL == (n = lookup_neighbour (peer))) return; /* gone already */ if (GNUNET_TIME_absolute_ntoh (sdm->timestamp).abs_value_us <= n->connect_ack_timestamp.abs_value_us) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# disconnect messages ignored (timestamp)"), 1, GNUNET_NO); return; } if (0 != memcmp (peer, &sdm->public_key, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return; } if (ntohl (sdm->purpose.size) != sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) + sizeof (struct GNUNET_TIME_AbsoluteNBO)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s message from peer `%s' has invalid size \n", "DISCONNECT", GNUNET_i2s (peer)); GNUNET_break_op (0); return; } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT, &sdm->purpose, &sdm->signature, &sdm->public_key)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s message from peer `%s' cannot be verified \n", "DISCONNECT", GNUNET_i2s (peer)); GNUNET_break_op (0); return; } n->delayed_disconnect_task = GNUNET_SCHEDULER_add_now (&delayed_disconnect, n); } /** * Closure for the neighbours_iterate function. */ struct IteratorContext { /** * Function to call on each connected neighbour. */ GST_NeighbourIterator cb; /** * Closure for 'cb'. */ void *cb_cls; }; /** * Call the callback from the closure for each neighbour. * * @param cls the `struct IteratorContext` * @param key the hash of the public key of the neighbour * @param value the `struct NeighbourMapEntry` * @return #GNUNET_OK (continue to iterate) */ static int neighbours_iterate (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct IteratorContext *ic = cls; struct NeighbourMapEntry *n = value; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; if (NULL != n->primary_address.address) { bandwidth_in = n->primary_address.bandwidth_in; bandwidth_out = n->primary_address.bandwidth_out; } else { bandwidth_in = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT; bandwidth_out = GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT; } ic->cb (ic->cb_cls, &n->id, n->primary_address.address, n->state, n->timeout, bandwidth_in, bandwidth_out); return GNUNET_OK; } /** * Iterate over all connected neighbours. * * @param cb function to call * @param cb_cls closure for cb */ void GST_neighbours_iterate (GST_NeighbourIterator cb, void *cb_cls) { struct IteratorContext ic; if (NULL == neighbours) return; /* can happen during shutdown */ ic.cb = cb; ic.cb_cls = cb_cls; GNUNET_CONTAINER_multipeermap_iterate (neighbours, &neighbours_iterate, &ic); } /** * If we have an active connection to the given target, it must be shutdown. * * @param target peer to disconnect from */ void GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target) { struct NeighbourMapEntry *n; if (NULL == (n = lookup_neighbour (target))) return; /* not active */ if (GNUNET_YES == test_connected (n)) GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# disconnected from peer upon explicit request"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Forced disconnect from peer %s\n", GNUNET_i2s (target)); disconnect_neighbour (n); } /** * Obtain current latency information for the given neighbour. * * @param peer to get the latency for * @return observed latency of the address, FOREVER if the * the connection is not up */ struct GNUNET_TIME_Relative GST_neighbour_get_latency (const struct GNUNET_PeerIdentity *peer) { struct NeighbourMapEntry *n; n = lookup_neighbour (peer); if (NULL == n) return GNUNET_TIME_UNIT_FOREVER_REL; switch (n->state) { case GNUNET_TRANSPORT_PS_CONNECTED: case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: case GNUNET_TRANSPORT_PS_RECONNECT_SENT: case GNUNET_TRANSPORT_PS_RECONNECT_ATS: return n->latency; case GNUNET_TRANSPORT_PS_NOT_CONNECTED: case GNUNET_TRANSPORT_PS_INIT_ATS: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: case GNUNET_TRANSPORT_PS_CONNECT_SENT: case GNUNET_TRANSPORT_PS_DISCONNECT: case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: return GNUNET_TIME_UNIT_FOREVER_REL; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s'\n", GNUNET_TRANSPORT_ps2s (n->state)); GNUNET_break (0); break; } return GNUNET_TIME_UNIT_FOREVER_REL; } /** * Obtain current address information for the given neighbour. * * @param peer * @return address currently used */ struct GNUNET_HELLO_Address * GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer) { struct NeighbourMapEntry *n; n = lookup_neighbour (peer); if (NULL == n) return NULL; return n->primary_address.address; } /** * Initialize the neighbours subsystem. * * @param cls closure for callbacks * @param connect_cb function to call if we connect to a peer * @param disconnect_cb function to call if we disconnect from a peer * @param peer_address_cb function to call if we change an active address * of a neighbour * @param max_fds maximum number of fds to use */ void GST_neighbours_start (void *cls, NotifyConnect connect_cb, GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb, GNUNET_TRANSPORT_NeighbourChangeCallback peer_address_cb, unsigned int max_fds) { callback_cls = cls; connect_notify_cb = connect_cb; disconnect_notify_cb = disconnect_cb; neighbour_change_cb = peer_address_cb; neighbours = GNUNET_CONTAINER_multipeermap_create (NEIGHBOUR_TABLE_SIZE, GNUNET_NO); registered_quota_notifications = GNUNET_CONTAINER_multipeermap_create (NEIGHBOUR_TABLE_SIZE, GNUNET_NO); util_transmission_tk = GNUNET_SCHEDULER_add_delayed (UTIL_TRANSMISSION_INTERVAL, utilization_transmission, NULL); } /** * Disconnect from the given neighbour. * * @param cls unused * @param key hash of neighbour's public key (not used) * @param value the 'struct NeighbourMapEntry' of the neighbour * @return #GNUNET_OK (continue to iterate) */ static int disconnect_all_neighbours (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct NeighbourMapEntry *n = value; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n", GNUNET_i2s (&n->id), "SHUTDOWN_TASK"); free_neighbour (n, GNUNET_NO); return GNUNET_OK; } /** * Cleanup the neighbours subsystem. */ void GST_neighbours_stop () { struct BlacklistCheckSwitchContext *cur; struct BlacklistCheckSwitchContext *next; if (NULL == neighbours) return; if (GNUNET_SCHEDULER_NO_TASK != util_transmission_tk) { GNUNET_SCHEDULER_cancel (util_transmission_tk); util_transmission_tk = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_multipeermap_iterate (neighbours, &disconnect_all_neighbours, NULL ); GNUNET_CONTAINER_multipeermap_destroy (neighbours); next = pending_bc_head; for (cur = next; NULL != cur; cur = next ) { next = cur->next; GNUNET_CONTAINER_DLL_remove (pending_bc_head, pending_bc_tail, cur); if (NULL != cur->blc) { GST_blacklist_test_cancel (cur->blc); cur->blc = NULL; } if (NULL != cur->address) GNUNET_HELLO_address_free (cur->address); GNUNET_free_non_null (cur->ats); GNUNET_free (cur); } GNUNET_CONTAINER_multipeermap_iterate (registered_quota_notifications, &free_notification_cb, NULL); GNUNET_CONTAINER_multipeermap_destroy (registered_quota_notifications); registered_quota_notifications = NULL; neighbours = NULL; callback_cls = NULL; connect_notify_cb = NULL; disconnect_notify_cb = NULL; neighbour_change_cb = NULL; } /* end of file gnunet-service-transport_neighbours.c */ gnunet-0.10.1/src/transport/test_quota_compliance_unix_peer2.conf0000644000175000017500000000124412225230043022220 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer2 [transport-unix] PORT = 12136 [arm] PORT = 3087 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_arm_peer2.sock [statistics] PORT = 3088 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_statistics_peer2.sock [resolver] PORT = 3089 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_resolver_peer2.sock [peerinfo] PORT = 3090 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_peerinfo_peer2.sock [transport] PORT = 3091 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_transport_peer2.sock [transport-unix] PORT = 3368 gnunet-0.10.1/src/transport/test_quota_compliance_wlan_peer2.conf0000644000175000017500000000112112225230043022170 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p2/ [transport-wlan] INTERFACE = mon1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/plugin_transport_http_common.h0000644000175000017500000001460112265232754021041 00000000000000/* This file is part of GNUnet (C) 2002-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_http_common.c * @brief functionality shared by http client and server transport service plugin * @author Matthias Wachs */ #include "platform.h" #include "gnunet_common.h" #include "gnunet_transport_plugin.h" /** * Timeout values for testing */ #define TESTING GNUNET_NO #if TESTING #define HTTP_SERVER_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) #define HTTP_CLIENT_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3) #define HTTP_CLIENT_SESSION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 7) #define SERVER_SESSION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 7) #define TIMEOUT_LOG GNUNET_ERROR_TYPE_DEBUG #else #if BUILD_HTTPS #define PROTOCOL "https" #else #define PROTOCOL "http" #endif #define HTTP_SERVER_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) #define HTTP_CLIENT_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) #define HTTP_CLIENT_SESSION_TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT #define HTTP_SERVER_SESSION_TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT #define TIMEOUT_LOG GNUNET_ERROR_TYPE_DEBUG #endif #define HTTP_DEFAULT_PORT 80 #define HTTPS_DEFAULT_PORT 443 enum HTTP_ADDRESS_OPTIONS { HTTP_OPTIONS_NONE = 0, HTTP_OPTIONS_VERIFY_CERTIFICATE = 1 }; GNUNET_NETWORK_STRUCT_BEGIN /** * HttpAddress */ struct HttpAddress { /** * Address options */ uint32_t options; /** * Length of URL located after struct */ uint32_t urlen; }; GNUNET_NETWORK_STRUCT_END struct SplittedHTTPAddress; struct SplittedHTTPAddress * http_split_address (const char * addr); /** * Convert the transports address to a nice, human-readable * format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the address * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for @a asc */ void http_common_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls); /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param plugin the plugin * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ const char * http_common_plugin_address_to_string (void *cls, const char *plugin, const void *addr, size_t addrlen); /** * Function called to convert a string address to * a binary address. * * @param cls closure (`struct Plugin*`) * @param addr string address * @param addrlen length of the address * @param buf location to store the buffer * If the function returns #GNUNET_SYSERR, its contents are undefined. * @param added length of created address * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int http_common_plugin_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added); /** * Create a HTTP address from a socketaddr * * @param protocol protocol * @param addr `sockaddr *` address * @param addrlen length of the @a addr * @return the string */ struct HttpAddress * http_common_address_from_socket (const char *protocol, const struct sockaddr *addr, socklen_t addrlen); /** * Create a socketaddr from a HTTP address * * @param addr a `sockaddr *` address * @param addrlen length of the @a addr * @param res the result: * #GNUNET_SYSERR, invalid input, * #GNUNET_YES: could convert to ip, * #GNUNET_NO: valid input but could not convert to ip (hostname?) * @return the string */ struct sockaddr * http_common_socket_from_address (const void *addr, size_t addrlen, int *res); const char * http_common_plugin_address_to_url (void *cls, const void *addr, size_t addrlen); /** * Get the length of an address * * @param addr address * @return the size */ size_t http_common_address_get_size (const struct HttpAddress * addr); /** * Compare addr1 to addr2 * * @param addr1 address1 * @param addrlen1 address 1 length * @param addr2 address2 * @param addrlen2 address 2 length * @return #GNUNET_YES if equal, #GNUNET_NO else */ size_t http_common_cmp_addresses (const void *addr1, size_t addrlen1, const void *addr2, size_t addrlen2); /* end of plugin_transport_http_common.h */ gnunet-0.10.1/src/transport/test_quota_compliance_wlan_asymmetric_peer1.conf0000644000175000017500000000110112225230043024422 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p1/ [transport-wlan] TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_bluetooth_peer2.conf0000644000175000017500000000161012225230043022601 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p2/ [transport-bluetooth] INTERFACE = hci1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock #PREFIX = xterm -T transport2 -e gdb --command=cmd --args #PREFIX = valgrind --leak-check=full --show-reachable=yes --main-stacksize=104857600 #PREFIX = valgrind --leak-check=full --show-reachable=yes #PREFIX = valgrind --leak-check=full #PREFIX = valgrind --tool=massif #PREFIX = gdbserver :2345 gnunet-0.10.1/src/transport/test_transport_api_timeout_unix_peer2.conf0000644000175000017500000000110012225230043023317 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-unix-p2/ [arm] PORT = 12135 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12134 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12133 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12132 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12131 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-unix] PORT = 12136 gnunet-0.10.1/src/transport/test_quota_compliance_bluetooth_asymmetric_peer1.conf0000644000175000017500000000114112225230043025472 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p1/ [transport-bluetooth] INTERFACE = hci0 TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_reliability_https_peer2.conf0000644000175000017500000000126012225230043024330 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-https-p2/ [transport-https_server] PORT = 12310 KEY_FILE = $GNUNET_TEST_HOME/https_key_p2.key CERT_FILE = $GNUNET_TEST_HOME/https_cert_p2.crt [arm] PORT = 12315 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12314 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12313 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12312 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12311 PLUGINS = https_server UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_reliability_tcp_nat_peer1.conf0000644000175000017500000000126312225230043024620 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-reliability-tcp-nat-p1/ [nat] BEHIND_NAT = YES ENABLE_NAT_SERVER = YES DISABLEV6 = YES [transport-tcp] PORT = 0 TIMEOUT = 5 s [arm] PORT = 1204 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12023 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12022 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12021 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 29542 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_manipulation_cfg_peer2.conf0000644000175000017500000000123712225230043024120 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock #MANIPULATE_DELAY_IN = 0 ms #MANIPULATE_DELAY_OUT = 0 ms gnunet-0.10.1/src/transport/test_transport_api_timeout_tcp_peer2.conf0000644000175000017500000000116012225230043023130 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [nat] ALLOW_NAT = NO [transport-tcp] PORT = 12100 [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_udp_peer1.conf0000644000175000017500000000127512225230043021372 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-p1/ [transport-udp] PORT = 0 BROADCAST = NO BROADCAST_INTERVAL = 30000 MAX_BPS = 50000000 BINDTO = 127.0.0.1 BINDTO6 = ::1 [arm] PORT = 12045 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12044 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12043 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12042 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] #PREFIX = valgrind --leak-check=full PORT = 12041 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_quota_compliance_http_asymmetric_peer2.conf0000644000175000017500000000126612225230043024455 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer2 [transport-http_server] PORT = 3010 USE_IPv6 = NO BINDTO = 127.0.0.1 [arm] PORT = 3015 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_arm_peer2.sock [statistics] PORT = 3014 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_statistics_peer2.sock [resolver] PORT = 3013 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_resolver_peer2.sock [peerinfo] PORT = 3012 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_peerinfo_peer2.sock [transport] PORT = 3011 PLUGINS = http_server UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_transport_peer2.sock gnunet-0.10.1/src/transport/test_transport_api_reliability_http_peer2.conf0000644000175000017500000000115712225230043024152 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-http-p2/ [transport-http_server] PORT = 12090 USE_IPv6 = NO BINDTO = 127.0.0.1 [arm] PORT = 12195 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12194 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12193 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12192 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12191 PLUGINS = http_server UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_limited_sockets_tcp_peer2.conf0000644000175000017500000000114312225230043024625 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 0 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/gnunet-service-transport_plugins.c0000644000175000017500000002770012316473377021555 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_plugins.c * @brief plugin management * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-transport.h" #include "gnunet-service-transport_hello.h" #include "gnunet-service-transport_plugins.h" /** * Entry in doubly-linked list of all of our plugins. */ struct TransportPlugin { /** * This is a doubly-linked list. */ struct TransportPlugin *next; /** * This is a doubly-linked list. */ struct TransportPlugin *prev; /** * API of the transport as returned by the plugin's * initialization function. */ struct GNUNET_TRANSPORT_PluginFunctions *api; /** * Short name for the plugin (i.e. "tcp"). */ char *short_name; /** * Name of the library (i.e. "gnunet_plugin_transport_tcp"). */ char *lib_name; /** * Environment this transport service is using * for this plugin. */ struct GNUNET_TRANSPORT_PluginEnvironment env; }; /** * Head of DLL of all loaded plugins. */ static struct TransportPlugin *plugins_head; /** * Head of DLL of all loaded plugins. */ static struct TransportPlugin *plugins_tail; /** * Load and initialize all plugins. The respective functions will be * invoked by the plugins when the respective events happen. The * closure will be set to a 'const char*' containing the name of the * plugin that caused the call. * * @param recv_cb function to call when data is received * @param register_quota_cb function to call to register a quota callback * @param unregister_quota_cb function to call to unregister a quota callback * @param address_cb function to call when our public addresses changed * @param session_start_cb function to call when a session was created * @param session_end_cb function to call when a session was terminated * @param address_type_cb function to call when a address type is requested * @param metric_update_cb function to call when address metrics change */ void GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, GNUNET_TRANSPORT_RegisterQuotaNotification register_quota_cb, GNUNET_TRANSPORT_UnregisterQuotaNotification unregister_quota_cb, GNUNET_TRANSPORT_AddressNotification address_cb, GNUNET_TRANSPORT_SessionStart session_start_cb, GNUNET_TRANSPORT_SessionEnd session_end_cb, GNUNET_TRANSPORT_AddressToType address_type_cb, GNUNET_TRANSPORT_UpdateAddressMetrics metric_update_cb) { struct TransportPlugin *plug; struct TransportPlugin *next; unsigned long long tneigh; char *libname; char *plugs; char *pos; int fail; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (GST_cfg, "TRANSPORT", "NEIGHBOUR_LIMIT", &tneigh)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Transport service is lacking NEIGHBOUR_LIMIT option.\n")); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (GST_cfg, "TRANSPORT", "PLUGINS", &plugs)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting transport plugins `%s'\n"), plugs); for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " ")) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' transport plugin\n"), pos); GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", pos); plug = GNUNET_new (struct TransportPlugin); plug->short_name = GNUNET_strdup (pos); plug->lib_name = libname; plug->env.cfg = GST_cfg; plug->env.my_identity = &GST_my_identity; plug->env.get_our_hello = &GST_hello_get; plug->env.cls = plug->short_name; plug->env.receive = recv_cb; plug->env.notify_address = address_cb; plug->env.session_start = session_start_cb; plug->env.session_end = session_end_cb; plug->env.get_address_type = address_type_cb; plug->env.update_address_metrics = metric_update_cb; plug->env.register_quota_notification = register_quota_cb; plug->env.unregister_quota_notification = unregister_quota_cb; plug->env.max_connections = tneigh; plug->env.stats = GST_stats; GNUNET_CONTAINER_DLL_insert (plugins_head, plugins_tail, plug); } GNUNET_free (plugs); next = plugins_head; while (next != NULL) { plug = next; next = plug->next; plug->api = GNUNET_PLUGIN_load (plug->lib_name, &plug->env); if (NULL == plug->api) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to load transport plugin for `%s'\n"), plug->lib_name); GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug); GNUNET_free (plug->short_name); GNUNET_free (plug->lib_name); GNUNET_free (plug); continue; } fail = GNUNET_NO; if (NULL == plug->api->address_pretty_printer) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "address_pretty_printer", plug->lib_name); } if (NULL == plug->api->address_to_string) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "address_to_string", plug->lib_name); } if (NULL == plug->api->string_to_address) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "string_to_address", plug->lib_name); } if (NULL == plug->api->check_address) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "check_address", plug->lib_name); } if (NULL == plug->api->get_session) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "get_session", plug->lib_name); } if (NULL == plug->api->get_network) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "get_network", plug->lib_name); } if (NULL == plug->api->send) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "send", plug->lib_name); } if (NULL == plug->api->disconnect_peer) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "disconnect_peer", plug->lib_name); } if (NULL == plug->api->disconnect_session) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "disconnect_session", plug->lib_name); } if (NULL == plug->api->query_keepalive_factor) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "query_keepalive_factor", plug->lib_name); } if (NULL == plug->api->update_session_timeout) { fail = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Missing function `%s' in transport plugin for `%s'\n"), "update_session_timeout", plug->lib_name); } if (GNUNET_YES == fail) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Did not load plugin `%s' due to missing functions\n"), plug->lib_name); GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api)); GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug); GNUNET_free (plug->short_name); GNUNET_free (plug->lib_name); GNUNET_free (plug); } } } /** * Unload all plugins */ void GST_plugins_unload () { struct TransportPlugin *plug; while (NULL != (plug = plugins_head)) { GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api)); GNUNET_free (plug->lib_name); GNUNET_free (plug->short_name); GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug); GNUNET_free (plug); } } /** * Obtain the plugin API based on a plugin name. * * @param name name of the plugin * @return the plugin's API, NULL if the plugin is not loaded */ struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_find (const char *name) { struct TransportPlugin *head = plugins_head; while ((head != NULL) && (0 != strcmp (name, head->short_name))) head = head->next; if (NULL == head) return NULL; return head->api; } /** * Obtain the plugin API based on a the stripped plugin name after the underscore. * * Example: GST_plugins_printer_find (http_client) will return all plugins * starting with the prefix "http": * http_client or server if loaded * * @param name name of the plugin * @return the plugin's API, NULL if the plugin is not loaded */ struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_printer_find (const char *name) { struct TransportPlugin *head = plugins_head; char *stripped = GNUNET_strdup (name); char *sep = strchr (stripped, '_'); if (NULL != sep) sep[0] = '\0'; while (head != NULL) { if (head->short_name == strstr (head->short_name, stripped)) break; head = head->next; } GNUNET_free (stripped); if (NULL == head) return NULL; return head->api; } /** * Convert a given address to a human-readable format. Note that the * return value will be overwritten on the next call to this function. * * @param address the address to convert * @return statically allocated (!) human-readable address */ const char * GST_plugins_a2s (const struct GNUNET_HELLO_Address *address) { struct GNUNET_TRANSPORT_PluginFunctions *api; static char unable_to_show[1024]; static const char *s; if (address == NULL) { GNUNET_break (0); /* a HELLO address cannot be NULL */ return ""; } if (0 == address->address_length) return TRANSPORT_SESSION_INBOUND_STRING; /* Addresse with length 0 are inbound, address->address itself may be NULL */ api = GST_plugins_printer_find (address->transport_name); if (NULL == api) return ""; if (0 == address->address_length) { GNUNET_snprintf (unable_to_show, sizeof (unable_to_show), "", (unsigned int) address->address_length, address->transport_name); return unable_to_show; } return (NULL != (s = api->address_to_string (NULL, address->address, address->address_length)) ? s : ""); } /* end of file gnunet-service-transport_plugins.c */ gnunet-0.10.1/src/transport/test_transport_api_wlan_peer2.conf0000644000175000017500000000157112225230043021543 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p2/ [transport-wlan] INTERFACE = mon1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock #PREFIX = xterm -T transport2 -e gdb --command=cmd --args #PREFIX = valgrind --leak-check=full --show-reachable=yes --main-stacksize=104857600 #PREFIX = valgrind --leak-check=full --show-reachable=yes #PREFIX = valgrind --leak-check=full #PREFIX = valgrind --tool=massif #PREFIX = gdbserver :2345 gnunet-0.10.1/src/transport/test_transport_api_unix_abstract_peer1.conf0000644000175000017500000000114612276375236023471 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-unix-p1/ [arm] PORT = 12125 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12124 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12123 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12122 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12121 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [transport-unix] PORT = 12120 [testing] USE_ABSTRACT_SOCKETS = YES gnunet-0.10.1/src/transport/transport.conf.in0000644000175000017500000000512012276375236016160 00000000000000[transport] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2091 HOSTNAME = localhost BINARY = gnunet-service-transport # PREFIX = valgrind NEIGHBOUR_LIMIT = 50 ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; PLUGINS = tcp udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport.sock BLACKLIST_FILE = $GNUNET_CONFIG_HOME/transport/blacklist UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = valgrind --leak-check=full # Configuration settings related to traffic manipulation for testing purposes # Distance # MANIPULATE_DISTANCE_IN = 1 # MANIPULATE_DISTANCE_OUT = 1 # Delay; WARNING: to large values may lead to peers not connecting! # MANIPULATE_DELAY_IN = 1 ms # MANIPULATE_DELAY_OUT = 1 ms [transport-unix] UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-transport-plugin-unix.sock TESTING_IGNORE_KEYS = ACCEPT_FROM; [transport-tcp] # Use 0 to ONLY advertise as a peer behind NAT (no port binding) PORT = 2086 ADVERTISED_PORT = 2086 TESTING_IGNORE_KEYS = ACCEPT_FROM; # Maximum number of open TCP connections allowed MAX_CONNECTIONS = 128 TIMEOUT = 5 s # ACCEPT_FROM = # ACCEPT_FROM6 = # REJECT_FROM = # REJECT_FROM6 = # BINDTO = MAX_CONNECTIONS = 128 [transport-udp] # Use PORT = 0 to autodetect a port available PORT = 2086 BROADCAST = YES BROADCAST_RECEIVE = YES BROADCAST_INTERVAL = 30 s MAX_BPS = 1000000 TESTING_IGNORE_KEYS = ACCEPT_FROM; [transport-http_client] MAX_CONNECTIONS = 128 TESTING_IGNORE_KEYS = ACCEPT_FROM; [transport-http_server] #EXTERNAL_HOSTNAME = PORT = 1080 ADVERTISED_PORT = 1080 MAX_CONNECTIONS = 128 TESTING_IGNORE_KEYS = ACCEPT_FROM; [transport-https_client] MAX_CONNECTIONS = 128 TESTING_IGNORE_KEYS = ACCEPT_FROM; [transport-https_server] # EXTERNAL_HOSTNAME = # EXTERNAL_HOSTNAME_ONLY = YES # If you have a valid SSL certificate for your external hostname tell, # clients to verify it # VERIFY_EXTERNAL_HOSTNAME = YES # Does the external hostname use the same port? # EXTERNAL_HOSTNAME_USE_PORT = YES PORT = 4433 ADVERTISED_PORT = 4433 CRYPTO_INIT = NORMAL KEY_FILE = $GNUNET_DATA_HOME/transport/https.key CERT_FILE = $GNUNET_DATA_HOME/transport/https.cert MAX_CONNECTIONS = 128 TESTING_IGNORE_KEYS = ACCEPT_FROM; [transport-wlan] # Name of the interface in monitor mode (typically monX) INTERFACE = mon0 # Real hardware, no testing TESTMODE = 0 TESTING_IGNORE_KEYS = ACCEPT_FROM; [transport-bluetooth] # Name of the interface (typically hciX) INTERFACE = hci0 # Real hardware, no testing TESTMODE = 0 TESTING_IGNORE_KEYS = ACCEPT_FROM; gnunet-0.10.1/src/transport/test_transport_api_http_reverse_peer2.conf0000644000175000017500000000156012225230043023312 00000000000000INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-http-p2/ [transport-http_client] [transport-http_server] PORT = 8080 EXTERNAL_HOSTNAME = fulcrum.net.in.tum.de/gnunet EXTERNAL_HOSTNAME_ONLY = YES #USE_IPV4 = YES #USE_IPV6 = YES #BINDTO = 127.0.0.1 #BINDTO6 = ::1 [arm] PORT = 12085 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12084 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12083 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12082 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12081 PLUGINS = http_server UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock PREFIX = valgrind --leak-check=full #PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args gnunet-0.10.1/src/transport/test_transport_api_manipulation_recv_tcp_peer1.conf0000644000175000017500000000114712225230043025165 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PLUGINS = tcp gnunet-0.10.1/src/transport/test_transport_blacklisting_cfg_blp_peer2_multiple_plugins.conf0000644000175000017500000000142512236654562027567 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] #PREFIX = valgrind --leak-check=full PORT = 12010 PLUGINS = tcp udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-blacklist-DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50] 6ULBJK6QQJ64FAG9DF0292AS5IA9CCAC04IQU0HF8THM635HMBBG = tcpgnunet-0.10.1/src/transport/test_transport_api.c0000644000175000017500000002602112274162761016736 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api.c * @brief base test case for transport implementations * * This test case serves as a base for tcp, udp, and udp-nat * transport test cases. Based on the executable being run * the correct test case will be performed. Conservation of * C code apparently. */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) #define TEST_MESSAGE_SIZE 2600 #define TEST_MESSAGE_TYPE 12345 static char *test_source; static char *test_plugin; static char *test_name; static int ok; static int s_started; static int s_connected; static int s_sending; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Fail! Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); if (s_started == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started \n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started \n")); if (s_connected == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not connected\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were connected\n")); if (s_sending == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were ready to send data\n")); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 1 was not started\n")); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 2 was not started\n")); ok = GNUNET_SYSERR; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if ((TEST_MESSAGE_TYPE == ntohs (message->type)) && (TEST_MESSAGE_SIZE == ntohs (message->size))) { ok = 0; end (); } else { GNUNET_break (0); ok = 1; end (); } } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= TEST_MESSAGE_SIZE); if (buf != NULL) { memset (buf, '\0', TEST_MESSAGE_SIZE); hdr = buf; hdr->size = htons (TEST_MESSAGE_SIZE); hdr->type = htons (TEST_MESSAGE_TYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return TEST_MESSAGE_SIZE; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); s_sending = GNUNET_YES; th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); s_connected = GNUNET_YES; send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; else s_started = GNUNET_YES; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); s_started = GNUNET_NO; s_connected = GNUNET_NO; s_sending = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); GNUNET_log_setup (test_name, "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of test_transport_api.c */ gnunet-0.10.1/src/transport/gnunet-service-transport.h0000644000175000017500000000777412267431203020015 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport.h * @brief globals * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_H #define GNUNET_SERVICE_TRANSPORT_H #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #define VERBOSE_VALIDATION GNUNET_YES /** * Statistics handle. */ extern struct GNUNET_STATISTICS_Handle *GST_stats; /** * Configuration handle. */ extern const struct GNUNET_CONFIGURATION_Handle *GST_cfg; /** * Configuration handle. */ extern struct GNUNET_PeerIdentity GST_my_identity; /** * Handle to peerinfo service. */ extern struct GNUNET_PEERINFO_Handle *GST_peerinfo; /** * Our private key. */ extern struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; /** * ATS handle. */ extern struct GNUNET_ATS_SchedulingHandle *GST_ats; /** * Function to call when a peer's address has changed * * @param cls closure * @param peer peer this update is about, * @param address address, NULL for disconnect notification */ typedef void (*GNUNET_TRANSPORT_NeighbourChangeCallback) (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out); /** * Function called by the transport for each received message. * * @param cls closure, const char* with the name of the plugin we received the message from * @param address address and (claimed) identity of the other peer * @param message the message, NULL if we only care about * learning about the delay until we should receive again * @param session identifier used for this session (NULL for plugins * that do not offer bi-directional communication to the sender * using the same "connection") * @return how long the plugin should wait until receiving more data * (plugins that do not support this, can ignore the return value) */ struct GNUNET_TIME_Relative GST_receive_callback (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message); /** * Notify ATS about the new address including the network this address is * located in. * * @param address the address * @param session the session * @param ats ats information * @param ats_count number of @a ats information */ void GST_ats_add_address (const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * Notify ATS about property changes to an address * * @param peer the peer * @param address the address * @param session the session * @param ats performance information * @param ats_count number of elements in @a ats */ void GST_ats_update_metrics (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); #endif /* end of file gnunet-service-transport_plugins.h */ gnunet-0.10.1/src/transport/test_quota_compliance.c0000644000175000017500000004147512274162761017406 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_quota_compliance.c * @brief base test case for transport implementations * * This test case tests quota compliance both on transport level */ #include "platform.h" #include "gnunet_transport_service.h" #include "gnunet_ats_service.h" #include "gauger.h" #include "transport-testing.h" /** * Testcase timeout */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) #define DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) static char *test_source; static char *test_plugin; static char *test_name; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier measure_task; struct PeerContext *p1; struct PeerContext *p2; struct PeerContext *sender; struct PeerContext *receiver; struct GNUNET_TRANSPORT_TransmitHandle *th; char *cfg_file_p1; char *gen_cfg_p2; unsigned long long quota_in_p1; unsigned long long quota_out_p1; char *cfg_file_p2; char *gen_cfg_p1; unsigned long long quota_in_p2; unsigned long long quota_out_p2; struct GNUNET_TRANSPORT_TESTING_handle *tth; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; /* * Testcase specific declarations */ /** * Note that this value must not significantly exceed * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise * messages may be dropped even for a reliable transport. */ #define TOTAL_MSGS (1024 * 2) #define MTYPE 12345 GNUNET_NETWORK_STRUCT_BEGIN struct TestMessage { struct GNUNET_MessageHeader header; uint32_t num; }; GNUNET_NETWORK_STRUCT_END static int msg_scheduled; static int msg_sent; static int msg_recv_expected; static int msg_recv; static int test_failed; static int test_connected; static unsigned long long total_bytes_sent; static struct GNUNET_TIME_Absolute start_time; /* * END Testcase specific declarations */ #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static void end () { unsigned long long delta; unsigned long long datarate; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; datarate = (total_bytes_sent * 1000 * 1000) / delta; FPRINTF (stderr, "Throughput was %llu b/s\n", datarate); test_failed = GNUNET_NO; if (datarate > quota_in_p2) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Datarate of %llu b/s higher than allowed inbound quota of %llu b/s\n", datarate, quota_in_p2); test_failed = GNUNET_YES; } if (datarate > quota_out_p1) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Datarate of %llu b/s higher than allowed outbound quota of %llu b/s\n", datarate, quota_out_p1); test_failed = GNUNET_YES; } if (test_failed == GNUNET_NO) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Datarate of %llu b/s complied to allowed outbound quota of %llu b/s and inbound quota of %llu b/s\n", datarate, quota_out_p1, quota_in_p2); } if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); } static void end_badly () { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (measure_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (measure_task); if (test_connected == GNUNET_YES) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers got connected\n"); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers got NOT connected\n"); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); test_failed = GNUNET_YES; } static unsigned int get_size (unsigned int iter) { unsigned int ret; ret = (iter * iter * iter); return sizeof (struct TestMessage) + (ret % 60000); } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { static int n; unsigned int s; char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; const struct TestMessage *hdr; hdr = (const struct TestMessage *) message; s = get_size (n); if (MTYPE != ntohs (message->type)) return; msg_recv_expected = n; msg_recv = ntohl (hdr->num); if (ntohs (message->size) != (s)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", n, s, ntohs (message->size), ntohl (hdr->num)); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } if (ntohl (hdr->num) != n) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", n, s, ntohs (message->size), ntohl (hdr->num)); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } memset (cbuf, n, s - sizeof (struct TestMessage)); if (0 != memcmp (cbuf, &hdr[1], s - sizeof (struct TestMessage))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u with bits %u, but body did not match\n", n, (unsigned char) n); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } #if VERBOSE if (ntohl (hdr->num) % 5000 == 0) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') got message %u of size %u from peer (`%s')\n", p->no, ps, ntohl (hdr->num), ntohs (message->size), GNUNET_i2s (peer)); GNUNET_free (ps); } #endif n++; } static size_t notify_ready (void *cls, size_t size, void *buf) { static int n; char *cbuf = buf; struct TestMessage hdr; unsigned int s; unsigned int ret; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready for message %u of %u\n", msg_scheduled, TOTAL_MSGS); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); test_failed = 1; return 0; } ret = 0; s = get_size (n); GNUNET_assert (size >= s); GNUNET_assert (buf != NULL); cbuf = buf; do { hdr.header.size = htons (s); hdr.header.type = htons (MTYPE); hdr.num = htonl (n); msg_sent = n; memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage)); ret += sizeof (struct TestMessage); memset (&cbuf[ret], n, s - sizeof (struct TestMessage)); ret += s - sizeof (struct TestMessage); #if VERBOSE if (n % 5000 == 0) { char *receiver_s = GNUNET_strdup (GNUNET_i2s (&receiver->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message of size %u from peer %u (`%4s') -> peer %u (`%s') !\n", n, sender->no, GNUNET_i2s (&sender->id), receiver->no, receiver_s); GNUNET_free (receiver_s); } #endif n++; s = get_size (n); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16)) break; /* sometimes pack buffer full, sometimes not */ } while (size - ret >= s); if (n < TOTAL_MSGS) { if (th == NULL) th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, s, TIMEOUT_TRANSMIT, ¬ify_ready, NULL); msg_scheduled = n; } if (n % 5000 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning total message block of size %u\n", ret); } total_bytes_sent += ret; if (n == TOTAL_MSGS) { FPRINTF (stderr, "%s", "\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All messages sent\n"); } return ret; } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') connected to us!\n", p->no, GNUNET_i2s (peer)); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') disconnected!\n", p->no, GNUNET_i2s (peer)); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void sendtask () { start_time = GNUNET_TIME_absolute_get (); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, get_size (0), TIMEOUT_TRANSMIT, ¬ify_ready, NULL); } static void measure (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static int counter; measure_task = GNUNET_SCHEDULER_NO_TASK; counter++; if ((DURATION.rel_value_us / 1000 / 1000LL) < counter) { FPRINTF (stderr, "%s", ".\n"); GNUNET_SCHEDULER_add_now (&end, NULL); } else { FPRINTF (stderr, "%s", "."); measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &measure, NULL); } } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); cc = NULL; test_connected = GNUNET_YES; measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &measure, NULL); GNUNET_SCHEDULER_add_now (&sendtask, NULL); } void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; test_connected = GNUNET_NO; sender = p2; receiver = p1; char *sender_c = GNUNET_strdup (GNUNET_i2s (&sender->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to send from %u (%s) -> peer %u (%s)\n", sender->no, sender_c, receiver->no, GNUNET_i2s (&receiver->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static char * generate_config (char *cfg_file, unsigned long long quota_in, unsigned long long quota_out) { char *networks[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; char *in_name; char *out_name; char *fname = NULL; struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create (); int c; GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (cfg, cfg_file)); GNUNET_asprintf (&fname, "q_in_%llu_q_out_%llu_%s", quota_in, quota_out, cfg_file); GNUNET_CONFIGURATION_set_value_string (cfg, "PATHS", "DEFAULTCONFIG", fname); for (c = 0; c < GNUNET_ATS_NetworkTypeCount; c++) { GNUNET_asprintf (&in_name, "%s_QUOTA_IN", networks[c]); GNUNET_asprintf (&out_name, "%s_QUOTA_OUT", networks[c]); GNUNET_CONFIGURATION_set_value_number (cfg, "ats", in_name, quota_in); GNUNET_CONFIGURATION_set_value_number (cfg, "ats", out_name, quota_out); GNUNET_free (in_name); GNUNET_free (out_name); } GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_write (cfg, fname)); GNUNET_CONFIGURATION_destroy (cfg); return fname; } static void run_measurement (unsigned long long p1_quota_in, unsigned long long p1_quota_out, unsigned long long p2_quota_in, unsigned long long p2_quota_out) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); /* setting ATS quota */ quota_out_p1 = p1_quota_out; gen_cfg_p1 = generate_config (cfg_file_p1, p1_quota_in, p1_quota_out); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Generated config file `%s'\n", gen_cfg_p1); quota_in_p2 = p2_quota_in; gen_cfg_p2 = generate_config (cfg_file_p2, p2_quota_in, p2_quota_out); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Generated config file `%s'\n", gen_cfg_p2); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, gen_cfg_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, gen_cfg_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { unsigned long long p1_quota_in = 10000; unsigned long long p1_quota_out = 10000; unsigned long long p2_quota_in = 10000; unsigned long long p2_quota_out = 10000; if (NULL != strstr (test_name, "asymmetric")) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running asymmetric test with sending peer unlimited, receiving peer (in/out): %llu/%llu b/s \n", p2_quota_in, p2_quota_out); p1_quota_out = 1024 * 1024 * 1024; p1_quota_in = 1024 * 1024 * 1024; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running symmetric test with (in/out) %llu/%llu b/s \n", p2_quota_in, p2_quota_out); } run_measurement (p1_quota_in, p1_quota_out, p2_quota_in, p2_quota_out); } static int check () { static char *argv[] = { "test_transport-quota-compliance", "-c", "test_quota_compliance_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, NULL); return test_failed; } int main (int argc, char *argv[]) { GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); if (GNUNET_YES == GNUNET_DISK_file_test (gen_cfg_p1)) { GNUNET_DISK_directory_remove (gen_cfg_p1); GNUNET_free (gen_cfg_p1); } if (GNUNET_YES == GNUNET_DISK_file_test (gen_cfg_p2)) { GNUNET_DISK_directory_remove (gen_cfg_p2); GNUNET_free (gen_cfg_p2); } GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return test_failed; } /* end of test_quota_compliance.c */ gnunet-0.10.1/src/transport/test_transport_api_data.conf0000644000175000017500000000015312225230043020411 00000000000000@INLINE@ test_transport_defaults.conf [PATHS] [transport-tcp] PORT = 2094 [transport-udp] PORT = 2094 gnunet-0.10.1/src/transport/test_transport_api_tcp_nat_peer2.conf0000644000175000017500000000123112225230043022223 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-nat-p2/ [nat] DISABLEV6 = YES ENABLE_NAT_CLIENT = YES [transport-tcp] PORT = 12030 TIMEOUT = 5 s [arm] PORT = 12034 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12033 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12032 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12031 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 45923 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_timeout_wlan_peer1.conf0000644000175000017500000000157212255010511023310 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p1/ [transport-wlan] INTERFACE = mon0 TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock #PREFIX = xterm -T transport2 -e gdb --command=cmd --args #PREFIX = valgrind --leak-check=full --show-reachable=yes --main-stacksize=104857600 #PREFIX = valgrind --leak-check=full --show-reachable=yes #PREFIX = valgrind --leak-check=full #PREFIX = valgrind --tool=massif #PREFIX = gdbserver :2345 gnunet-0.10.1/src/transport/test_transport_api_udp_nat_peer2.conf0000644000175000017500000000116512225230043022233 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-nat-p2/ [nat] ALLOW_NAT = YES [transport-udp] PORT = 12070 [arm] PORT = 12075 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12074 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12073 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12072 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12071 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/gnunet-service-transport_hello.h0000644000175000017500000000541312225777503021176 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_hello.h * @brief hello API * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_HELLO_H #define GNUNET_SERVICE_TRANSPORT_HELLO_H #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" /** * Signature of a function to call whenever our hello changes. * * @param cls closure * @param hello updated HELLO */ typedef void (*GST_HelloCallback) (void *cls, const struct GNUNET_MessageHeader * hello); /** * Initialize the HELLO module. * * @param friend_only use a friend only hello * @param cb function to call whenever our HELLO changes * @param cb_cls closure for cb */ void GST_hello_start (int friend_only, GST_HelloCallback cb, void *cb_cls); /** * Shutdown the HELLO module. */ void GST_hello_stop (void); /** * Obtain this peers HELLO message. * * @return our HELLO message */ const struct GNUNET_MessageHeader * GST_hello_get (void); /** * Add or remove an address from this peer's HELLO message. * * @param addremove GNUNET_YES to add, GNUNET_NO to remove * @param address address to add or remove */ void GST_hello_modify_addresses (int addremove, const struct GNUNET_HELLO_Address *address); /** * Test if a particular address is one of ours. * * @param address the address to test * @param sig location where to cache PONG signatures for this address [set] * @param sig_expiration how long until the current 'sig' expires? * (ZERO if sig was never created) [set] * @return GNUNET_YES if this is one of our addresses, * GNUNET_NO if not */ int GST_hello_test_address (const struct GNUNET_HELLO_Address *address, struct GNUNET_CRYPTO_EddsaSignature **sig, struct GNUNET_TIME_Absolute **sig_expiration); #endif /* end of file gnunet-service-transport_hello.h */ gnunet-0.10.1/src/transport/test_quota_compliance_https_peer2.conf0000644000175000017500000000131312225230043022374 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer2 [transport-https_server] PORT = 3001 KEY_FILE = https_key_quota_p2.key CERT_FILE = https_cert_qutoa_p2.crt [arm] PORT = 3006 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_arm_peer2.sock [statistics] PORT = 3005 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_statistics_peer2.sock [resolver] PORT = 3004 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_resolver_peer2.sock [peerinfo] PORT = 3003 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_peerinfo_peer2.sock [transport] PORT = 3002 PLUGINS = https_server UNIXPATH = $GNUNET_RUNTIME_DIR/https_transport_peer2.sock gnunet-0.10.1/src/transport/test_transport_api_unix_peer2.conf0000644000175000017500000000110012225230043021551 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-unix-p2/ [arm] PORT = 12135 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12134 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12133 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12132 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12131 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-unix] PORT = 12136 gnunet-0.10.1/src/transport/transport-testing.h0000644000175000017500000002123312225777503016530 00000000000000/* This file is part of GNUnet. (C) 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport-testing.h * @brief testing lib for transport service * * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" #include "gnunet_transport_service.h" #include "gnunet_testing_lib.h" #define GNUNET_TRANSPORT_TESTING_ConnectRequest void * /** * Context for a single peer */ struct PeerContext; /** * Callback when two peers are connected and both have called the connect callback * to notify clients about a new peer */ typedef void (*GNUNET_TRANSPORT_TESTING_start_cb) (struct PeerContext * p, void *cls); /** * Callback when two peers are connected and both have called the connect callback * to notify clients about a new peer */ typedef void (*GNUNET_TRANSPORT_TESTING_connect_cb) (struct PeerContext * p1, struct PeerContext * p2, void *cls); /** * Definition for a transport testing handle */ struct GNUNET_TRANSPORT_TESTING_handle; /** * Context for a single peer */ struct PeerContext { /** * Next element in the DLL */ struct PeerContext *next; /** * Previous element in the DLL */ struct PeerContext *prev; /** * Transport testing handle this peer belongs to */ struct GNUNET_TRANSPORT_TESTING_handle *tth; /** * Peer's configuration */ struct GNUNET_CONFIGURATION_Handle *cfg; /** * Peer's transport service handle */ struct GNUNET_TRANSPORT_Handle *th; /** * Peer's transport get hello handle to retrieve peer's HELLO message */ struct GNUNET_TRANSPORT_GetHelloHandle *ghh; /** * Peer's testing handle */ struct GNUNET_TESTING_Peer *peer; /** * Peer identity */ struct GNUNET_PeerIdentity id; /** * Handle for the peer's ARM process */ struct GNUNET_OS_Process *arm_proc; /** * Receive callback */ GNUNET_TRANSPORT_ReceiveCallback rec; /** * Notify connect callback */ GNUNET_TRANSPORT_NotifyConnect nc; /** * Notify disconnect callback */ GNUNET_TRANSPORT_NotifyDisconnect nd; /** * Startup completed callback */ GNUNET_TRANSPORT_TESTING_start_cb start_cb; /** * Peers HELLO Message */ struct GNUNET_HELLO_Message *hello; /** * Closure for the callbacks */ void *cb_cls; /** * An unique number to identify the peer */ unsigned int no; }; struct ConnectingContext { struct ConnectingContext *next; struct ConnectingContext *prev; struct PeerContext *p1; struct PeerContext *p2; GNUNET_SCHEDULER_TaskIdentifier tct; GNUNET_TRANSPORT_TESTING_connect_cb cb; void *cb_cls; struct GNUNET_TRANSPORT_Handle *th_p1; struct GNUNET_TRANSPORT_Handle *th_p2; int p1_c; int p2_c; }; struct GNUNET_TRANSPORT_TESTING_handle { /** * Testing library system handle */ struct GNUNET_TESTING_System *tl_system; /** * head DLL of connect contexts */ struct ConnectingContext *cc_head; /** * head DLL of connect contexts */ struct ConnectingContext *cc_tail; /** * head DLL of peers */ struct PeerContext *p_head; /** * tail DLL of peers */ struct PeerContext *p_tail; }; /** * Start a peer with the given configuration * @param tth the testing handle * @param cfgname configuration file * @param peer_id the peer_id * @param rec receive callback * @param nc connect callback * @param nd disconnect callback * @param start_cb start callback * @param cb_cls closure for callback * @return the peer context */ struct PeerContext * GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth, const char *cfgname, int peer_id, GNUNET_TRANSPORT_ReceiveCallback rec, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd, GNUNET_TRANSPORT_TESTING_start_cb start_cb, void *cb_cls); /** * shutdown the given peer * @param tth the testing handle * @param p the peer */ void GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *pc); /** * Restart the given peer * @param tth testing handle * @param p the peer * @param cfgname the cfg file used to restart * @param restart_cb restart callback * @param cb_cls callback closure * @return GNUNET_OK in success otherwise GNUNET_SYSERR */ int GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p, const char *cfgname, GNUNET_TRANSPORT_TESTING_start_cb restart_cb, void *cb_cls); /** * Connect the given peers and call the callback when both peers report the * inbound connection. Remarks: start_peer's notify_connect callback can be called * before. * * @param tth transport testing handle * @param p1 peer 1 * @param p2 peer 2 * @param cb the callback to call when both peers notified that they are connected * @param cls callback cls * @return a connect request handle */ GNUNET_TRANSPORT_TESTING_ConnectRequest GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p1, struct PeerContext *p2, GNUNET_TRANSPORT_TESTING_connect_cb cb, void *cls); /** * Cancel the request to connect two peers * Tou MUST cancel the request if you stop the peers before the peers connected succesfully * @param tth testing * @param ccr a connect request handle */ void GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct GNUNET_TRANSPORT_TESTING_handle *tth, GNUNET_TRANSPORT_TESTING_ConnectRequest ccr); /** * Clean up the transport testing * @param tth transport testing handle */ void GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_handle *tth); /** * Initialize the transport testing * @return transport testing handle */ struct GNUNET_TRANSPORT_TESTING_handle * GNUNET_TRANSPORT_TESTING_init (); /* * Some utility functions */ /** * Extracts the test filename from an absolute file name and removes the extension * @param file absolute file name * @param dest where to store result */ void GNUNET_TRANSPORT_TESTING_get_test_name (const char *file, char **dest); /** * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and * if existing ".exe"-prefix and adds the peer-number * * @param file filename of the test, e.g. argv[0] * @param dest where to write the filename * @param count peer number */ void GNUNET_TRANSPORT_TESTING_get_config_name (const char *file, char **dest, int count); /** * Extracts the plugin anme from an absolute file name and the test name * @param file absolute file name * @param test test name * @param dest where to store result */ void GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *executable, const char *testname, char **pluginname); /** * Extracts the filename from an absolute file name and removes the extenstion * @param file absolute file name * @param dest where to store result */ void GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file, char **testname); /* end of transport_testing.h */ gnunet-0.10.1/src/transport/test_quota_compliance_unix_peer1.conf0000644000175000017500000000120612225230043022215 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer1/ [transport-unix] PORT = 12120 [arm] PORT = 4087 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_arm_peer1.sock [statistics] PORT = 4088 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_statistics_peer1.sock [resolver] PORT = 4089 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_resolver_peer1.sock [peerinfo] PORT = 4090 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_peerinfo_peer1.sock [transport] PORT = 4091 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_transport_peer1.sock gnunet-0.10.1/src/transport/gnunet-service-transport_clients.h0000644000175000017500000000646412267431203021531 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_clients.h * @brief client management API * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_CLIENTS_H #define GNUNET_SERVICE_TRANSPORT_CLIENTS_H #include "gnunet_transport_service.h" #include "gnunet_statistics_service.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" /** * Start handling requests from clients. * * @param server server used to accept clients from. */ void GST_clients_start (struct GNUNET_SERVER_Handle *server); /** * Stop processing clients. */ void GST_clients_stop (void); /** * Broadcast the given message to all of our clients. * * @param msg message to broadcast * @param may_drop #GNUNET_YES if the message can be dropped / is payload */ void GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, int may_drop); /** * Send the given message to a particular client * * @param client target of the message * @param msg message to transmit * @param may_drop #GNUNET_YES if the message can be dropped */ void GST_clients_unicast (struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg, int may_drop); /** * Broadcast the new active address to all clients monitoring the peer. * * @param peer peer this update is about (never NULL) * @param address address, NULL on disconnect * @param state the current state of the peer * @param state_timeout the time out for the state */ void GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout); /** * Broadcast the new validation changes to all clients monitoring the peer. * * @param peer peer this update is about (never NULL) * @param address address, NULL on disconnect * @param last_validation point in time when last validation was performed * @param valid_until point in time how long address is valid * @param next_validation point in time when next validation will be performed * @param state state of validation notification */ void GST_clients_broadcast_validation_notification ( const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state); #endif /* end of file gnunet-service-transport_clients.h */ gnunet-0.10.1/src/transport/plugin_transport_http_common.c0000644000175000017500000003345012261236532021031 00000000000000/* This file is part of GNUnet (C) 2002-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_http_common.c * @brief functionality shared by http client and server transport service plugin * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_transport_plugin.h" #include "plugin_transport_http_common.h" struct SplittedHTTPAddress { char *protocol; char *host; char *path; int port; }; static void http_clean_splitted (struct SplittedHTTPAddress *spa) { if (NULL != spa) { GNUNET_free_non_null (spa->protocol); GNUNET_free_non_null (spa->host); GNUNET_free_non_null (spa->path); GNUNET_free_non_null (spa); } } struct SplittedHTTPAddress * http_split_address (const char * addr) { struct SplittedHTTPAddress *sp; char *src = GNUNET_strdup (addr); char *protocol_start = NULL; char *host_start = NULL; char *v6_end = NULL; char *port_start = NULL; char *path_start = NULL; protocol_start = src; sp = GNUNET_new (struct SplittedHTTPAddress); /* Address string consists of protocol://host[:port]path*/ host_start = strstr (src, "://"); if (NULL == host_start) { GNUNET_free (src); GNUNET_free (sp); return NULL; } host_start[0] = '\0'; sp->protocol = GNUNET_strdup (protocol_start); host_start += strlen ("://"); if (strlen (host_start) == 0) { GNUNET_free (src); GNUNET_free (sp->protocol); GNUNET_free (sp); return NULL; } /* Find path start */ path_start = strchr (host_start, '/'); if (NULL != path_start) { sp->path = GNUNET_strdup (path_start); path_start[0] = '\0'; } else sp->path = GNUNET_strdup (""); if (strlen(host_start) < 1) { GNUNET_free (src); GNUNET_free (sp->protocol); GNUNET_free (sp->path); GNUNET_free (sp); return NULL; } if (NULL != (port_start = strrchr (host_start, ':'))) { /* *We COULD have a port, but also an IPv6 address! */ if (NULL != (v6_end = strchr(host_start, ']'))) { if (v6_end < port_start) { /* IPv6 address + port */ port_start[0] = '\0'; port_start ++; sp->port = atoi (port_start); if ((0 == sp->port) || (65535 < sp->port)) { GNUNET_free (src); GNUNET_free (sp->protocol); GNUNET_free (sp->path); GNUNET_free (sp); return NULL; } } else { /* IPv6 address + no port */ if (0 == strcmp(sp->protocol, "https")) sp->port = HTTPS_DEFAULT_PORT; else if (0 == strcmp(sp->protocol, "http")) sp->port = HTTP_DEFAULT_PORT; } } else { /* No IPv6 address */ port_start[0] = '\0'; port_start ++; sp->port = atoi (port_start); if ((0 == sp->port) || (65535 < sp->port)) { GNUNET_free (src); GNUNET_free (sp->protocol); GNUNET_free (sp->path); GNUNET_free (sp); return NULL; } } } else { /* No ':' as port separator, default port for protocol */ if (0 == strcmp(sp->protocol, "https")) sp->port = HTTPS_DEFAULT_PORT; else if (0 == strcmp(sp->protocol, "http")) sp->port = HTTP_DEFAULT_PORT; else { GNUNET_break (0); GNUNET_free (src); GNUNET_free (sp->protocol); GNUNET_free (sp->path); GNUNET_free (sp); return NULL; } } if (strlen (host_start) > 0) sp->host = GNUNET_strdup (host_start); else { GNUNET_break (0); GNUNET_free (src); GNUNET_free (sp->protocol); GNUNET_free (sp->path); GNUNET_free (sp); return NULL; } GNUNET_free (src); return sp; } /** * Convert the transports address to a nice, human-readable * format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the @a addr * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for @a asc */ void http_common_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { const struct HttpAddress *address = addr; if (NULL == http_common_plugin_address_to_string (NULL, type, address, addrlen)) { asc (asc_cls, NULL); return; } asc (asc_cls, http_common_plugin_address_to_string (NULL, type, address, addrlen)); asc (asc_cls, NULL); } const char * http_common_plugin_address_to_url (void *cls, const void *addr, size_t addrlen) { static char rbuf[1024]; const struct HttpAddress *address = addr; const char * addr_str; if (NULL == addr) { GNUNET_break (0); return NULL; } if (0 >= addrlen) { GNUNET_break (0); return NULL; } if (addrlen != http_common_address_get_size (address)) { GNUNET_break (0); return NULL; } addr_str = (char *) &address[1]; if (addr_str[ntohl(address->urlen) -1] != '\0') return NULL; memcpy (rbuf, &address[1], ntohl(address->urlen)); return rbuf; } /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param plugin the plugin * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ const char * http_common_plugin_address_to_string (void *cls, const char *plugin, const void *addr, size_t addrlen) { static char rbuf[1024]; const struct HttpAddress *address = addr; const char * addr_str; char *res; GNUNET_assert (NULL != plugin); if (NULL == addr) return NULL; if (0 == addrlen) return TRANSPORT_SESSION_INBOUND_STRING; if (addrlen != http_common_address_get_size (address)) return NULL; addr_str = (char *) &address[1]; if (addr_str[ntohl(address->urlen) -1] != '\0') return NULL; GNUNET_asprintf (&res, "%s.%u.%s", plugin, ntohl(address->options), &address[1]); if (strlen(res) + 1 < 500) { memcpy (rbuf, res, strlen(res) + 1); GNUNET_free (res); return rbuf; } GNUNET_break (0); GNUNET_free (res); return NULL; } /** * Function called to convert a string address to * a binary address. * * @param cls closure ('struct Plugin*') * @param addr string address * @param addrlen length of the @a addr * @param buf location to store the buffer * If the function returns #GNUNET_SYSERR, its contents are undefined. * @param added length of created address * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int http_common_plugin_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added) { struct HttpAddress *a; char *address; char *plugin; char *optionstr; size_t urlen; uint32_t options; /* Format protocol.options.address:port */ address = NULL; plugin = NULL; optionstr = NULL; if ((NULL == addr) || (addrlen == 0)) { GNUNET_break (0); return GNUNET_SYSERR; } if ('\0' != addr[addrlen - 1]) { GNUNET_break (0); return GNUNET_SYSERR; } if (strlen (addr) != addrlen - 1) { GNUNET_break (0); return GNUNET_SYSERR; } plugin = GNUNET_strdup (addr); optionstr = strchr (plugin, '.'); if (NULL == optionstr) { GNUNET_break (0); GNUNET_free (plugin); return GNUNET_SYSERR; } optionstr[0] = '\0'; optionstr ++; options = atol (optionstr); /* 0 on conversion error, that's ok */ address = strchr (optionstr, '.'); if (NULL == address) { GNUNET_break (0); GNUNET_free (plugin); return GNUNET_SYSERR; } address[0] = '\0'; address ++; urlen = strlen (address) + 1; a = GNUNET_malloc (sizeof (struct HttpAddress) + urlen); a->options = htonl(options); a->urlen = htonl(urlen); memcpy (&a[1], address, urlen); (*buf) = a; (*added) = sizeof (struct HttpAddress) + urlen; GNUNET_free (plugin); return GNUNET_OK; } /** * Create a HTTP address from a socketaddr * * @param protocol protocol * @param addr sockaddr * address * @param addrlen length of the address * @return the HttpAddress */ struct HttpAddress * http_common_address_from_socket (const char *protocol, const struct sockaddr *addr, socklen_t addrlen) { struct HttpAddress *address = NULL; char *res; size_t len; GNUNET_asprintf(&res, "%s://%s", protocol, GNUNET_a2s (addr, addrlen)); len = strlen (res)+1; address = GNUNET_malloc (sizeof (struct HttpAddress) + len); address->options = htonl (HTTP_OPTIONS_NONE); address->urlen = htonl (len); memcpy (&address[1], res, len); GNUNET_free (res); return address; } /** * Create a socketaddr from a HTTP address * * @param addr a `sockaddr *` address * @param addrlen length of the @a addr * @param res the result: * #GNUNET_SYSERR, invalid input, * #GNUNET_YES: could convert to ip, * #GNUNET_NO: valid input but could not convert to ip (hostname?) * @return the string */ struct sockaddr * http_common_socket_from_address (const void *addr, size_t addrlen, int *res) { const struct HttpAddress *ha; struct SplittedHTTPAddress * spa; struct sockaddr_storage *s; char * to_conv; size_t urlen; (*res) = GNUNET_SYSERR; ha = (const struct HttpAddress *) addr; if (NULL == addr) { GNUNET_break(0); return NULL ; } if (0 >= addrlen) { GNUNET_break(0); return NULL ; } if (addrlen < sizeof(struct HttpAddress)) { GNUNET_break(0); return NULL ; } urlen = ntohl (ha->urlen); if (sizeof(struct HttpAddress) + urlen != addrlen) { /* This is a legacy addresses */ return NULL ; } if (addrlen < sizeof(struct HttpAddress) + urlen) { /* This is a legacy addresses */ return NULL ; } if (((char *) addr)[addrlen - 1] != '\0') { GNUNET_break(0); return NULL ; } spa = http_split_address ((const char *) &ha[1]); if (NULL == spa) { (*res) = GNUNET_SYSERR; return NULL; } s = GNUNET_new (struct sockaddr_storage); GNUNET_asprintf (&to_conv, "%s:%u", spa->host, spa->port); if (GNUNET_SYSERR == GNUNET_STRINGS_to_address_ip (to_conv, strlen(to_conv), s)) { /* could be a hostname */ GNUNET_free (s); (*res) = GNUNET_NO; s = NULL; } else if ((AF_INET != s->ss_family) && (AF_INET6 != s->ss_family)) { GNUNET_free (s); (*res) = GNUNET_SYSERR; s = NULL; } else { (*res) = GNUNET_YES; } http_clean_splitted (spa); GNUNET_free (to_conv); return (struct sockaddr *) s; } /** * Get the length of an address * * @param addr address * @return the size */ size_t http_common_address_get_size (const struct HttpAddress * addr) { return sizeof (struct HttpAddress) + ntohl(addr->urlen); } /** * Compare addr1 to addr2 * * @param addr1 address1 * @param addrlen1 address 1 length * @param addr2 address2 * @param addrlen2 address 2 length * @return #GNUNET_YES if equal, #GNUNET_NO if not, #GNUNET_SYSERR on error */ size_t http_common_cmp_addresses (const void *addr1, size_t addrlen1, const void *addr2, size_t addrlen2) { const char *a1 = addr1; const char *a2 = addr2; const struct HttpAddress *ha1; const struct HttpAddress *ha2; ha1 = (const struct HttpAddress *) a1; ha2 = (const struct HttpAddress *) a2; if (NULL == a1) return GNUNET_SYSERR; if (0 >= addrlen1) return GNUNET_SYSERR; if (a1[addrlen1-1] != '\0') return GNUNET_SYSERR; if (NULL == a2) return GNUNET_SYSERR; if (0 >= addrlen2) return GNUNET_SYSERR; if (a2[addrlen2-1] != '\0') return GNUNET_SYSERR; if (addrlen1 != addrlen2) return GNUNET_NO; if (ha1->urlen != ha2->urlen) return GNUNET_NO; if (0 == strcmp ((const char *) &ha1[1],(const char *) &ha2[1])) return GNUNET_YES; return GNUNET_NO; } /* end of plugin_transport_http_common.c */ gnunet-0.10.1/src/transport/gnunet-transport.c0000644000175000017500000012213212320530515016330 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/transport/gnunet-transport.c * @brief Tool to help configure, measure and control the transport subsystem. * @author Christian Grothoff * @author Nathan Evans * * This utility can be used to test if a transport mechanism for * GNUnet is properly configured. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #include "gnunet_protocols.h" #include "gnunet_transport_service.h" #include "gnunet_nat_lib.h" /** * How long do we wait for the NAT test to report success? * Should match NAT_SERVER_TIMEOUT in 'nat_test.c'. */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) #define RESOLUTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) #define OP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) /** * Benchmarking block size in KB */ #define BLOCKSIZE 4 /** * Which peer should we connect to? */ static char *cpid; /** * Handle to transport service. */ static struct GNUNET_TRANSPORT_Handle *handle; /** * Configuration handle */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * Try_connect handle */ struct GNUNET_TRANSPORT_TryConnectHandle * tc_handle; /** * Option -s. */ static int benchmark_send; /** * Option -b. */ static int benchmark_receive; /** * Option -l. */ static int benchmark_receive; /** * Option -i. */ static int iterate_connections; /** * Option -d. */ static int iterate_validation; /** * Option -a. */ static int iterate_all; /** * Option -t. */ static int test_configuration; /** * Option -c. */ static int monitor_connects; /** * Option -m. */ static int monitor_connections; /** * Option -f. */ static int monitor_validation; /** * Option -C. */ static int try_connect; /** * Option -D. */ static int try_disconnect; /** * Option -n. */ static int numeric; /** * Global return value (0 success). */ static int ret; /** * Current number of connections in monitor mode */ static int monitor_connect_counter; /** * Number of bytes of traffic we received so far. */ static unsigned long long traffic_received; /** * Number of bytes of traffic we sent so far. */ static unsigned long long traffic_sent; /** * Starting time of transmitting/receiving data. */ static struct GNUNET_TIME_Absolute start_time; /** * Handle for current transmission request. */ static struct GNUNET_TRANSPORT_TransmitHandle *th; /** * Map storing information about monitored peers */ static struct GNUNET_CONTAINER_MultiPeerMap *monitored_peers; /** * */ static struct GNUNET_TRANSPORT_PeerMonitoringContext *pic; static struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic; /** * Identity of the peer we transmit to / connect to. * (equivalent to 'cpid' string). */ static struct GNUNET_PeerIdentity pid; /** * Task scheduled for cleanup / termination of the process. */ static GNUNET_SCHEDULER_TaskIdentifier end; /** * Task for operation timeout */ static GNUNET_SCHEDULER_TaskIdentifier op_timeout; /** * Selected level of verbosity. */ static int verbosity; /** * Resolver process handle. */ struct GNUNET_OS_Process *resolver; /** * Number of address resolutions pending */ static unsigned int address_resolutions; /** * Address resolutions pending in progress */ static unsigned int address_resolution_in_progress; /** * DLL for NAT Test Contexts: head */ struct TestContext *head; /** * DLL for NAT Test Contexts: tail */ struct TestContext *tail; /** * Context for a plugin test. */ struct TestContext { /** * Previous in DLL */ struct TestContext *prev; /** * Next in DLL */ struct TestContext *next; /** * Handle to the active NAT test. */ struct GNUNET_NAT_Test *tst; /** * Task identifier for the timeout. */ GNUNET_SCHEDULER_TaskIdentifier tsk; /** * Name of plugin under test. */ char *name; /** * Bound port */ unsigned long long bnd_port; /** * Advertised ports */ unsigned long long adv_port; }; static struct ValidationResolutionContext *vc_head; static struct ValidationResolutionContext *vc_tail; struct ValidationResolutionContext { struct ValidationResolutionContext *next; struct ValidationResolutionContext *prev; struct GNUNET_PeerIdentity id; struct GNUNET_HELLO_Address *addrcp; struct GNUNET_TIME_Absolute last_validation; struct GNUNET_TIME_Absolute valid_until; struct GNUNET_TIME_Absolute next_validation; enum GNUNET_TRANSPORT_ValidationState state; struct GNUNET_TRANSPORT_AddressToStringContext *asc; char *transport; int printed; }; struct MonitoredPeer { enum GNUNET_TRANSPORT_PeerState state; struct GNUNET_TIME_Absolute state_timeout; struct GNUNET_HELLO_Address *address; }; int destroy_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct MonitoredPeer *m = value; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (monitored_peers, key, value)); GNUNET_free_non_null (m->address); GNUNET_free (value); return GNUNET_OK; } /** * Task run in monitor mode when the user presses CTRL-C to abort. * Stops monitoring activity. * * @param cls the 'struct GNUNET_TRANSPORT_PeerIterateContext *' * @param tc scheduler context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Relative duration; struct ValidationResolutionContext *cur; struct ValidationResolutionContext *next; end = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != op_timeout) { GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_NO_TASK; } if (NULL != tc_handle) { GNUNET_TRANSPORT_try_connect_cancel (tc_handle); tc_handle = NULL; } if (NULL != pic) { GNUNET_TRANSPORT_monitor_peers_cancel (pic); pic = NULL; } if (NULL != vic) { GNUNET_TRANSPORT_monitor_validation_entries_cancel (vic); vic = NULL; } next = vc_head; for (cur = next; NULL != cur; cur = next) { next = cur->next; GNUNET_TRANSPORT_address_to_string_cancel (cur->asc); GNUNET_CONTAINER_DLL_remove (vc_head, vc_tail, cur); GNUNET_free (cur->transport); GNUNET_HELLO_address_free (cur->addrcp); GNUNET_free (cur); } if (NULL != th) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } if (NULL != handle) { GNUNET_TRANSPORT_disconnect (handle); handle = NULL; } if (benchmark_send) { duration = GNUNET_TIME_absolute_get_duration (start_time); FPRINTF (stdout, _("Transmitted %llu bytes/s (%llu bytes in %s)\n"), 1000LL * 1000LL * traffic_sent / (1 + duration.rel_value_us), traffic_sent, GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); } if (benchmark_receive) { duration = GNUNET_TIME_absolute_get_duration (start_time); FPRINTF (stdout, _("Received %llu bytes/s (%llu bytes in %s)\n"), 1000LL * 1000LL * traffic_received / (1 + duration.rel_value_us), traffic_received, GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); } if (NULL != monitored_peers) { GNUNET_CONTAINER_multipeermap_iterate (monitored_peers, &destroy_it, NULL); GNUNET_CONTAINER_multipeermap_destroy (monitored_peers); monitored_peers = NULL; } } static struct PeerResolutionContext *rc_head; static struct PeerResolutionContext *rc_tail; struct PeerResolutionContext { struct PeerResolutionContext *next; struct PeerResolutionContext *prev; struct GNUNET_PeerIdentity id; struct GNUNET_HELLO_Address *addrcp; struct GNUNET_TRANSPORT_AddressToStringContext *asc; enum GNUNET_TRANSPORT_PeerState state; struct GNUNET_TIME_Absolute state_timeout; char *transport; int printed; }; static void operation_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerResolutionContext *cur; struct PeerResolutionContext *next; op_timeout = GNUNET_SCHEDULER_NO_TASK; if ((try_connect) || (benchmark_send) || (benchmark_receive)) { FPRINTF (stdout, _("Failed to connect to `%s'\n"), GNUNET_i2s_full (&pid)); if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); ret = 1; return; } if (iterate_connections) { next = rc_head; while (NULL != (cur = next)) { next = cur->next; FPRINTF (stdout, _("Failed to resolve address for peer `%s'\n"), GNUNET_i2s (&cur->addrcp->peer)); GNUNET_CONTAINER_DLL_remove(rc_head, rc_tail, cur); GNUNET_TRANSPORT_address_to_string_cancel (cur->asc); GNUNET_free(cur->transport); GNUNET_free(cur->addrcp); GNUNET_free(cur); } FPRINTF (stdout, "%s", _("Failed to list connections, timeout occured\n") ); if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); ret = 1; return; } } static void run_nat_test (); /** * Display the result of the test. * * @param tc test context * @param result #GNUNET_YES on success */ static void display_test_result (struct TestContext *tc, int result) { if (GNUNET_YES != result) { FPRINTF (stderr, "Configuration for plugin `%s' did not work!\n", tc->name); } else { FPRINTF (stderr, "Configuration for plugin `%s' is working!\n", tc->name); } if (GNUNET_SCHEDULER_NO_TASK != tc->tsk) { GNUNET_SCHEDULER_cancel (tc->tsk); tc->tsk = GNUNET_SCHEDULER_NO_TASK; } if (NULL != tc->tst) { GNUNET_NAT_test_stop (tc->tst); tc->tst = NULL; } GNUNET_CONTAINER_DLL_remove (head, tail, tc); GNUNET_free (tc->name); GNUNET_free (tc); if ((NULL == head) && (NULL != resolver)) { GNUNET_break(0 == GNUNET_OS_process_kill (resolver, GNUNET_TERM_SIG)); GNUNET_OS_process_destroy (resolver); resolver = NULL; } if (NULL != head) run_nat_test (); } /** * Function called by NAT on success. * Clean up and update GUI (with success). * * @param cls test context * @param success currently always #GNUNET_OK * @param emsg error message, NULL on success */ static void result_callback (void *cls, int success, const char *emsg) { struct TestContext *tc = cls; display_test_result (tc, success); } /** * Function called if NAT failed to confirm success. * Clean up and update GUI (with failure). * * @param cls test context * @param tc scheduler callback */ static void fail_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TestContext *tstc = cls; tstc->tsk = GNUNET_SCHEDULER_NO_TASK; display_test_result (tstc, GNUNET_NO); } static void resolve_validation_address (const struct GNUNET_PeerIdentity *id, const struct GNUNET_HELLO_Address *address, int numeric, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state); static void process_validation_string (void *cls, const char *address) { struct ValidationResolutionContext *vc = cls; char *s_valid; char *s_last; char *s_next; if (address != NULL ) { if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == vc->valid_until.abs_value_us) s_valid = GNUNET_strdup("never"); else s_valid = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string (vc->valid_until)); if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == vc->last_validation.abs_value_us) s_last = GNUNET_strdup("never"); else s_last = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string (vc->last_validation)); if (GNUNET_TIME_UNIT_ZERO_ABS.abs_value_us == vc->next_validation.abs_value_us) s_next = GNUNET_strdup("never"); else s_next = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string (vc->next_validation)); FPRINTF (stdout, _("Peer `%s' %s %s\n\t%s%s\n\t%s%s\n\t%s%s\n"), GNUNET_i2s (&vc->id), address, (monitor_validation) ? GNUNET_TRANSPORT_vs2s (vc->state) : "", "Valid until : ", s_valid, "Last validation: ",s_last, "Next validation: ", s_next); GNUNET_free (s_valid); GNUNET_free (s_last); GNUNET_free (s_next); vc->printed = GNUNET_YES; } else { /* done */ GNUNET_assert(address_resolutions > 0); address_resolutions--; if (GNUNET_NO == vc->printed) { if (numeric == GNUNET_NO) { /* Failed to resolve address, try numeric lookup */ resolve_validation_address (&vc->id, vc->addrcp, GNUNET_NO, vc->last_validation, vc->valid_until, vc->next_validation, vc->state); } else { FPRINTF (stdout, _("Peer `%s' %s `%s' \n"), GNUNET_i2s (&vc->id), "", GNUNET_TRANSPORT_vs2s (vc->state)); } } GNUNET_free (vc->transport); GNUNET_free (vc->addrcp); GNUNET_CONTAINER_DLL_remove(vc_head, vc_tail, vc); GNUNET_free(vc); if ((0 == address_resolutions) && (iterate_validation)) { if (GNUNET_SCHEDULER_NO_TASK != end) { GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != op_timeout) { GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_NO_TASK; } ret = 0; end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); } } } static void resolve_validation_address (const struct GNUNET_PeerIdentity *id, const struct GNUNET_HELLO_Address *address, int numeric, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state) { struct ValidationResolutionContext *vc; vc = GNUNET_new (struct ValidationResolutionContext); GNUNET_assert(NULL != vc); GNUNET_CONTAINER_DLL_insert(vc_head, vc_tail, vc); address_resolutions++; vc->id = (*id); vc->transport = GNUNET_strdup(address->transport_name); vc->addrcp = GNUNET_HELLO_address_copy (address); vc->printed = GNUNET_NO; vc->state = state; vc->last_validation = last_validation; vc->valid_until = valid_until; vc->next_validation = next_validation; /* Resolve address to string */ vc->asc = GNUNET_TRANSPORT_address_to_string (cfg, address, numeric, RESOLUTION_TIMEOUT, &process_validation_string, vc); } void process_validation_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state) { if ((NULL == peer) && (NULL == address)) { /* done */ vic = NULL; if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } if ((NULL == peer) || (NULL == address)) { /* invalid response */ vic = NULL; if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } resolve_validation_address (peer, address, numeric, last_validation, valid_until, next_validation, state); } static void run_nat_test () { head->tst = GNUNET_NAT_test_start (cfg, (0 == strcasecmp (head->name, "udp")) ? GNUNET_NO : GNUNET_YES, (uint16_t) head->bnd_port, (uint16_t) head->adv_port, &result_callback, head); if (NULL == head->tst) { display_test_result (head, GNUNET_SYSERR); return; } head->tsk = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &fail_timeout, head); } /** * Test our plugin's configuration (NAT traversal, etc.). * * @param cfg configuration to test */ static void do_test_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg) { char *plugins; char *tok; unsigned long long bnd_port; unsigned long long adv_port; struct TestContext *tc; char *binary; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "transport", "plugins", &plugins)) { FPRINTF (stderr, "%s", _ ("No transport plugins configured, peer will never communicate\n") ); ret = 4; return; } for (tok = strtok (plugins, " "); tok != NULL ; tok = strtok (NULL, " ")) { char section[12 + strlen (tok)]; GNUNET_snprintf (section, sizeof(section), "transport-%s", tok); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, section, "PORT", &bnd_port)) { FPRINTF (stderr, _("No port configured for plugin `%s', cannot test it\n"), tok); continue; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, section, "ADVERTISED_PORT", &adv_port)) adv_port = bnd_port; tc = GNUNET_new (struct TestContext); tc->name = GNUNET_strdup (tok); tc->adv_port = adv_port; tc->bnd_port = bnd_port; GNUNET_CONTAINER_DLL_insert_tail (head, tail, tc); } GNUNET_free(plugins); if ((NULL != head) && (NULL == resolver)) { binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver"); resolver = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-resolver", NULL ); GNUNET_free(binary); GNUNET_RESOLVER_connect (cfg); run_nat_test (); } } /** * Function called to notify a client about the socket * begin ready to queue more data. @a buf will be * NULL and @a size zero if the socket was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ static size_t transmit_data (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *m = buf; if ((NULL == buf) || (0 == size)) { th = NULL; return 0; } GNUNET_assert(size >= sizeof(struct GNUNET_MessageHeader)); GNUNET_assert(size < GNUNET_SERVER_MAX_MESSAGE_SIZE); m->size = ntohs (size); m->type = ntohs (GNUNET_MESSAGE_TYPE_DUMMY); memset (&m[1], 52, size - sizeof(struct GNUNET_MessageHeader)); traffic_sent += size; th = GNUNET_TRANSPORT_notify_transmit_ready (handle, &pid, BLOCKSIZE * 1024, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_data, NULL ); if (verbosity > 0) FPRINTF (stdout, _("Transmitting %u bytes to %s\n"), (unsigned int) size, GNUNET_i2s (&pid)); return size; } /** * Function called to notify transport users that another * peer connected to us. * * @param cls closure * @param peer the peer that connected */ static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity))) return; ret = 0; if (try_connect) { /* all done, terminate instantly */ FPRINTF (stdout, _("Successfully connected to `%s'\n"), GNUNET_i2s_full (peer)); ret = 0; if (GNUNET_SCHEDULER_NO_TASK != op_timeout) { GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } if (benchmark_send) { if (GNUNET_SCHEDULER_NO_TASK != op_timeout) { GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_NO_TASK; } if (verbosity > 0) FPRINTF (stdout, _("Successfully connected to `%s', starting to send benchmark data in %u Kb blocks\n"), GNUNET_i2s (&pid), BLOCKSIZE); start_time = GNUNET_TIME_absolute_get (); if (NULL == th) th = GNUNET_TRANSPORT_notify_transmit_ready (handle, peer, BLOCKSIZE * 1024, GNUNET_TIME_UNIT_FOREVER_REL, &transmit_data, NULL); else GNUNET_break(0); return; } } /** * Function called to notify transport users that another * peer disconnected from us. * * @param cls closure * @param peer the peer that disconnected */ static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { if (0 != memcmp (&pid, peer, sizeof(struct GNUNET_PeerIdentity))) return; if (try_disconnect) { /* all done, terminate instantly */ FPRINTF (stdout, _("Successfully disconnected from `%s'\n"), GNUNET_i2s_full (peer)); ret = 0; if (GNUNET_SCHEDULER_NO_TASK != op_timeout) { GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } if (NULL != th) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } if (benchmark_send) { FPRINTF (stdout, _("Disconnected from peer `%s' while benchmarking\n"), GNUNET_i2s (&pid)); if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); return; } } /** * Function called to notify transport users that another * peer connected to us. * * @param cls closure * @param peer the peer that connected */ static void monitor_notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { monitor_connect_counter++; struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); const char *now_str = GNUNET_STRINGS_absolute_time_to_string (now); FPRINTF (stdout, _("%24s: %-17s %4s (%u connections in total)\n"), now_str, _("Connected to"), GNUNET_i2s (peer), monitor_connect_counter); } /** * Function called to notify transport users that another * peer disconnected from us. * * @param cls closure * @param peer the peer that disconnected */ static void monitor_notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); const char *now_str = GNUNET_STRINGS_absolute_time_to_string (now); GNUNET_assert(monitor_connect_counter > 0); monitor_connect_counter--; FPRINTF (stdout, _("%24s: %-17s %4s (%u connections in total)\n"), now_str, _("Disconnected from"), GNUNET_i2s (peer), monitor_connect_counter); } /** * Function called by the transport for each received message. * * @param cls closure * @param peer (claimed) identity of the other peer * @param message the message */ static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { if (benchmark_receive) { if (GNUNET_MESSAGE_TYPE_DUMMY != ntohs (message->type)) return; if (verbosity > 0) FPRINTF (stdout, _("Received %u bytes from %s\n"), (unsigned int) ntohs (message->size), GNUNET_i2s (peer)); if (traffic_received == 0) start_time = GNUNET_TIME_absolute_get (); traffic_received += ntohs (message->size); return; } } static void resolve_peer_address (const struct GNUNET_PeerIdentity *id, const struct GNUNET_HELLO_Address *address, int numeric, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout); static void print_info (const struct GNUNET_PeerIdentity *id, const char *transport, const char *addr, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { if ( ((GNUNET_YES == iterate_connections) && (GNUNET_YES == iterate_all)) || (GNUNET_YES == monitor_connections) ) { FPRINTF (stdout, _("Peer `%s': %s %s in state `%s' until %s\n"), GNUNET_i2s (id), (NULL == transport) ? "" : transport, (NULL == transport) ? "" : addr, GNUNET_TRANSPORT_ps2s (state), GNUNET_STRINGS_absolute_time_to_string (state_timeout)); } else if ( (GNUNET_YES == iterate_connections) && (GNUNET_TRANSPORT_is_connected(state)) ) { /* Only connected peers, skip state */ FPRINTF (stdout, _("Peer `%s': %s %s\n"), GNUNET_i2s (id), transport, addr); } } static void process_peer_string (void *cls, const char *address) { struct PeerResolutionContext *rc = cls; if (address != NULL ) { print_info (&rc->id, rc->transport, address, rc->state, rc->state_timeout); rc->printed = GNUNET_YES; } else { /* done */ GNUNET_assert(address_resolutions > 0); address_resolutions--; if (GNUNET_NO == rc->printed) { if (numeric == GNUNET_NO) { /* Failed to resolve address, try numeric lookup */ resolve_peer_address (&rc->id, rc->addrcp, GNUNET_YES, rc->state, rc->state_timeout); } else { print_info (&rc->id, rc->transport, "", rc->state, rc->state_timeout); } } GNUNET_free (rc->transport); GNUNET_free (rc->addrcp); GNUNET_CONTAINER_DLL_remove(rc_head, rc_tail, rc); GNUNET_free(rc); if ((0 == address_resolutions) && (iterate_connections)) { if (GNUNET_SCHEDULER_NO_TASK != end) { GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != op_timeout) { GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_NO_TASK; } ret = 0; end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); } } } static void resolve_peer_address (const struct GNUNET_PeerIdentity *id, const struct GNUNET_HELLO_Address *address, int numeric, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { struct PeerResolutionContext *rc; rc = GNUNET_new (struct PeerResolutionContext); GNUNET_assert(NULL != rc); GNUNET_CONTAINER_DLL_insert(rc_head, rc_tail, rc); address_resolutions++; rc->id = (*id); rc->transport = GNUNET_strdup(address->transport_name); rc->addrcp = GNUNET_HELLO_address_copy (address); rc->printed = GNUNET_NO; rc->state = state; rc->state_timeout = state_timeout; /* Resolve address to string */ rc->asc = GNUNET_TRANSPORT_address_to_string (cfg, address, numeric, RESOLUTION_TIMEOUT, &process_peer_string, rc); } /** * Function called with information about a peers during a one shot iteration * * @param cls closure * @param peer identity of the peer, NULL for final callback when operation done * @param address binary address used to communicate with this peer, * NULL on disconnect or when done * @param state current state this peer is in * @param state_timeout time out for the current state * */ static void process_peer_iteration_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { if (peer == NULL ) { /* done */ address_resolution_in_progress = GNUNET_NO; pic = NULL; if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } if ((GNUNET_NO == iterate_all) && (GNUNET_NO == GNUNET_TRANSPORT_is_connected(state)) ) return; /* Display only connected peers */ if (GNUNET_SCHEDULER_NO_TASK != op_timeout) GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL ); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received address for peer `%s': %s\n", GNUNET_i2s (peer), address->transport_name); if (NULL != address) resolve_peer_address (peer, address, numeric, state, state_timeout); else print_info (peer, NULL, NULL, state, state_timeout); } /** * Function called with information about a peers * * @param cls closure * @param peer identity of the peer, NULL for final callback when operation done * @param address binary address used to communicate with this peer, * NULL on disconnect or when done * @param state current state this peer is in * @param state_timeout time out for the current state * */ static void process_peer_monitoring_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { struct MonitoredPeer *m; if (peer == NULL ) { /* done */ address_resolution_in_progress = GNUNET_NO; pic = NULL; if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } if (GNUNET_SCHEDULER_NO_TASK != op_timeout) GNUNET_SCHEDULER_cancel (op_timeout); op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL ); if (NULL == (m = GNUNET_CONTAINER_multipeermap_get (monitored_peers, peer))) { m = GNUNET_new (struct MonitoredPeer); GNUNET_CONTAINER_multipeermap_put (monitored_peers, peer, m, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); } else { if ( (m->state == state) && (m->state_timeout.abs_value_us == state_timeout.abs_value_us) && ((NULL == address) && (NULL == m->address)) ) { return; /* No real change */ } if ( (m->state == state) && ((NULL != address) && (NULL != m->address)) && (0 == GNUNET_HELLO_address_cmp(m->address, address)) ) return; /* No real change */ } if (NULL != m->address) { GNUNET_free (m->address); m->address = NULL; } if (NULL != address) m->address = GNUNET_HELLO_address_copy (address); m->state = state; m->state_timeout = state_timeout; if (NULL != address) resolve_peer_address (peer, m->address, numeric, m->state, m->state_timeout); else print_info (peer, NULL, NULL, m->state, m->state_timeout); } static void try_connect_cb (void *cls, const int result) { static int retries = 0; if (GNUNET_OK == result) { tc_handle = NULL; return; } retries++; if (retries < 10) tc_handle = GNUNET_TRANSPORT_try_connect (handle, &pid, try_connect_cb, NULL ); else { FPRINTF (stderr, "%s", _("Failed to send connect request to transport service\n") ); if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); ret = 1; end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } } static void try_disconnect_cb (void *cls, const int result) { static int retries = 0; if (GNUNET_OK == result) { tc_handle = NULL; return; } retries++; if (retries < 10) tc_handle = GNUNET_TRANSPORT_try_disconnect (handle, &pid, try_disconnect_cb, NULL ); else { FPRINTF (stderr, "%s", _("Failed to send connect request to transport service\n") ); if (GNUNET_SCHEDULER_NO_TASK != end) GNUNET_SCHEDULER_cancel (end); ret = 1; end = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL ); return; } } /** * Function called with the result of the check if the 'transport' * service is running. * * @param cls closure with our configuration * @param result #GNUNET_YES if transport is running */ static void testservice_task (void *cls, int result) { int counter = 0; ret = 1; if (GNUNET_YES != result) { FPRINTF (stderr, _("Service `%s' is not running\n"), "transport"); return; } if ((NULL != cpid) && (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (cpid, strlen (cpid), &pid.public_key))) { FPRINTF (stderr, _("Failed to parse peer identity `%s'\n"), cpid); return; } counter = benchmark_send + benchmark_receive + iterate_connections + monitor_connections + monitor_connects + try_connect + try_disconnect + + iterate_validation + monitor_validation; if (1 < counter) { FPRINTF (stderr, _("Multiple operations given. Please choose only one operation: %s, %s, %s, %s, %s, %s\n"), "connect", "benchmark send", "benchmark receive", "information", "monitor", "events"); return; } if (0 == counter) { FPRINTF (stderr, _("No operation given. Please choose one operation: %s, %s, %s, %s, %s, %s\n"), "connect", "benchmark send", "benchmark receive", "information", "monitor", "events"); return; } if (try_connect) /* -C: Connect to peer */ { if (NULL == cpid) { FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"), "-C", "-p"); ret = 1; return; } handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, ¬ify_receive, ¬ify_connect, ¬ify_disconnect); if (NULL == handle) { FPRINTF (stderr, "%s", _("Failed to connect to transport service\n") ); ret = 1; return; } tc_handle = GNUNET_TRANSPORT_try_connect (handle, &pid, try_connect_cb, NULL ); if (NULL == tc_handle) { FPRINTF (stderr, "%s", _("Failed to send request to transport service\n") ); ret = 1; return; } op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL ); } else if (try_disconnect) /* -D: Disconnect from peer */ { if (NULL == cpid) { FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"), "-D", "-p"); ret = 1; return; } handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, ¬ify_receive, ¬ify_connect, ¬ify_disconnect); if (NULL == handle) { FPRINTF (stderr, "%s", _("Failed to connect to transport service\n") ); ret = 1; return; } tc_handle = GNUNET_TRANSPORT_try_disconnect (handle, &pid, try_disconnect_cb, NULL ); if (NULL == tc_handle) { FPRINTF (stderr, "%s", _("Failed to send request to transport service\n") ); ret = 1; return; } op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL ); } else if (benchmark_send) /* -s: Benchmark sending */ { if (NULL == cpid) { FPRINTF (stderr, _("Option `%s' makes no sense without option `%s'.\n"), "-s", "-p"); ret = 1; return; } handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, ¬ify_receive, ¬ify_connect, ¬ify_disconnect); if (NULL == handle) { FPRINTF (stderr, "%s", _("Failed to connect to transport service\n") ); ret = 1; return; } tc_handle = GNUNET_TRANSPORT_try_connect (handle, &pid, try_connect_cb, NULL ); if (NULL == tc_handle) { FPRINTF (stderr, "%s", _("Failed to send request to transport service\n") ); ret = 1; return; } start_time = GNUNET_TIME_absolute_get (); op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL ); } else if (benchmark_receive) /* -b: Benchmark receiving */ { handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, ¬ify_receive, NULL, NULL ); if (NULL == handle) { FPRINTF (stderr, "%s", _("Failed to connect to transport service\n") ); ret = 1; return; } if (verbosity > 0) FPRINTF (stdout, "%s", _("Starting to receive benchmark data\n") ); start_time = GNUNET_TIME_absolute_get (); } else if (iterate_connections) /* -i: List information about peers once */ { address_resolution_in_progress = GNUNET_YES; pic = GNUNET_TRANSPORT_monitor_peers (cfg, (NULL == cpid) ? NULL : &pid, GNUNET_YES, TIMEOUT, &process_peer_iteration_cb, (void *) cfg); op_timeout = GNUNET_SCHEDULER_add_delayed (OP_TIMEOUT, &operation_timeout, NULL ); } else if (monitor_connections) /* -m: List information about peers continuously */ { monitored_peers = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); address_resolution_in_progress = GNUNET_YES; pic = GNUNET_TRANSPORT_monitor_peers (cfg, (NULL == cpid) ? NULL : &pid, GNUNET_NO, TIMEOUT, &process_peer_monitoring_cb, (void *) cfg); } else if (iterate_validation) /* -d: Print information about validations */ { vic = GNUNET_TRANSPORT_monitor_validation_entries (cfg, (NULL == cpid) ? NULL : &pid, GNUNET_YES, TIMEOUT, &process_validation_cb, (void *) cfg); } else if (monitor_validation) /* -f: Print information about validations continuously */ { vic = GNUNET_TRANSPORT_monitor_validation_entries (cfg, (NULL == cpid) ? NULL : &pid, GNUNET_NO, TIMEOUT, &process_validation_cb, (void *) cfg); } else if (monitor_connects) /* -e : Monitor (dis)connect events continuously */ { monitor_connect_counter = 0; handle = GNUNET_TRANSPORT_connect (cfg, NULL, NULL, NULL, &monitor_notify_connect, &monitor_notify_disconnect); if (NULL == handle) { FPRINTF (stderr, "%s", _("Failed to connect to transport service\n") ); ret = 1; return; } ret = 0; } else { GNUNET_break(0); return; } end = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL ); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param mycfg configuration */ static void run (void *cls, char * const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *mycfg) { cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg; if (test_configuration) { do_test_configuration (cfg); return; } GNUNET_CLIENT_service_test ("transport", cfg, GNUNET_TIME_UNIT_SECONDS, &testservice_task, (void *) cfg); } int main (int argc, char * const *argv) { int res; static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'a', "all", NULL, gettext_noop ("print information for all peers (instead of only connected peers )"), 0, &GNUNET_GETOPT_set_one, &iterate_all }, { 'b', "benchmark", NULL, gettext_noop ("measure how fast we are receiving data from all peers (until CTRL-C)"), 0, &GNUNET_GETOPT_set_one, &benchmark_receive }, { 'C', "connect", NULL, gettext_noop ("connect to a peer"), 0, &GNUNET_GETOPT_set_one, &try_connect }, { 'D', "disconnect", NULL, gettext_noop ("disconnect to a peer"), 0, &GNUNET_GETOPT_set_one, &try_disconnect }, { 'd', "validation", NULL, gettext_noop ("print information for all pending validations "), 0, &GNUNET_GETOPT_set_one, &iterate_validation }, { 'f', "monitorvalidation", NULL, gettext_noop ("print information for all pending validations continously"), 0, &GNUNET_GETOPT_set_one, &monitor_validation }, { 'i', "information", NULL, gettext_noop ("provide information about all current connections (once)"), 0, &GNUNET_GETOPT_set_one, &iterate_connections }, { 'm', "monitor", NULL, gettext_noop ("provide information about all current connections (continuously)"), 0, &GNUNET_GETOPT_set_one, &monitor_connections }, { 'e', "events", NULL, gettext_noop ("provide information about all connects and disconnect events (continuously)"), 0, &GNUNET_GETOPT_set_one, &monitor_connects }, { 'n', "numeric", NULL, gettext_noop ("do not resolve hostnames"), 0, &GNUNET_GETOPT_set_one, &numeric }, { 'p', "peer", "PEER", gettext_noop ("peer identity"), 1, &GNUNET_GETOPT_set_string, &cpid }, { 's', "send", NULL, gettext_noop ("send data for benchmarking to the other peer (until CTRL-C)"), 0, &GNUNET_GETOPT_set_one, &benchmark_send }, { 't', "test", NULL, gettext_noop ("test transport configuration (involves external server)"), 0, &GNUNET_GETOPT_set_one, &test_configuration }, GNUNET_GETOPT_OPTION_VERBOSE (&verbosity), GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; res = GNUNET_PROGRAM_run (argc, argv, "gnunet-transport", gettext_noop ("Direct access to transport service."), options, &run, NULL ); GNUNET_free((void * ) argv); if (GNUNET_OK == res) return ret; return 1; } /* end of gnunet-transport.c */ gnunet-0.10.1/src/transport/test_transport_blacklisting.c0000644000175000017500000002376312316473377020652 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/transport_api_blacklisting.c * @brief test for the blacklisting API * stage 0: init * stage 1: connect peers and stop * stage 2: blacklist whole peer and connect * stage 3: blacklist tcp and try connect * * @author Matthias Wachs * */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" char *test_name; struct PeerContext *p1; struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; struct GNUNET_TRANSPORT_TESTING_handle *tth; /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) #define CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) static int stage; static int ok; static int connected; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier timeout_task; static GNUNET_SCHEDULER_TaskIdentifier stage_task; #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static void run_stage(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void end(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Stopping\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (timeout_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (stage_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (stage_task); stage_task = GNUNET_SCHEDULER_NO_TASK; } if (cc != NULL ) { GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (p1 != NULL ) { GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); p1 = NULL; } if (p2 != NULL ) { GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); p2 = NULL; } } static void end_badly(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; if (timeout_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (stage_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (stage_task); stage_task = GNUNET_SCHEDULER_NO_TASK; } if (cc != NULL ) { GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (p1 != NULL ) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL ) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); ok = GNUNET_SYSERR; } static void testing_connect_cb(struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free(p1_c); connected = GNUNET_YES; stage_task = GNUNET_SCHEDULER_add_now (&run_stage, NULL ); } static void connect_timeout(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peers not connected, next stage\n"); timeout_task = GNUNET_SCHEDULER_NO_TASK; stage_task = GNUNET_SCHEDULER_add_now (&run_stage, NULL ); } static int started; void start_cb(struct PeerContext *p, void *cls) { started++; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free(sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL ); } static void run_stage(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { stage_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL ); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Running stage %u\n", stage); if (0 == stage) { started = GNUNET_NO; connected = GNUNET_NO; if (0 == strcmp (test_name, "test_transport_blacklisting_no_bl")) { /* Try to connect peers successfully */ p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_peer1.conf", 1, NULL, NULL, NULL, &start_cb, NULL ); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_peer2.conf", 2, NULL, NULL, NULL, &start_cb, NULL ); } else if (0 == strcmp (test_name, "test_transport_blacklisting_outbound_bl_full")) { p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_blp_peer1_full.conf", 1, NULL, NULL, NULL, &start_cb, NULL ); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_peer2.conf", 2, NULL, NULL, NULL, &start_cb, NULL ); } else if (0 == strcmp (test_name, "test_transport_blacklisting_outbound_bl_plugin")) { p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_blp_peer1_plugin.conf", 1, NULL, NULL, NULL, &start_cb, NULL ); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_peer2.conf", 2, NULL, NULL, NULL, &start_cb, NULL ); } else if (0 == strcmp (test_name, "test_transport_blacklisting_inbound_bl_full")) { p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_peer1.conf", 1, NULL, NULL, NULL, &start_cb, NULL ); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_blp_peer2_full.conf", 2, NULL, NULL, NULL, &start_cb, NULL ); } else if (0 == strcmp (test_name, "test_transport_blacklisting_inbound_bl_plugin")) { p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_peer1.conf", 1, NULL, NULL, NULL, &start_cb, NULL ); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_blp_peer2_plugin.conf", 2, NULL, NULL, NULL, &start_cb, NULL ); } else if (0 == strcmp (test_name, "test_transport_blacklisting_multiple_plugins")) { p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_blp_peer1_multiple_plugins.conf", 1, NULL, NULL, NULL, &start_cb, NULL ); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_blacklisting_cfg_blp_peer2_multiple_plugins.conf", 2, NULL, NULL, NULL, &start_cb, NULL ); } else { GNUNET_break (0); GNUNET_SCHEDULER_add_now (&end, NULL ); } if ((NULL == p1) || (NULL == p2)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to start peers\n"); ok = 1; GNUNET_SCHEDULER_add_now (&end, NULL ); } timeout_task = GNUNET_SCHEDULER_add_delayed (CONNECT_TIMEOUT, &connect_timeout, NULL ); stage++; return; } if (cc != NULL ) { GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (p1 != NULL ) { GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); p1 = NULL; } if (p2 != NULL ) { GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); p2 = NULL; } GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Done in stage %u: Peers %s and %s!\n", stage, (GNUNET_NO == started) ? "NOT STARTED" : "STARTED", (GNUNET_YES == connected) ? "CONNECTED" : "NOT CONNECTED"); if ((0 == strcmp (test_name, "test_transport_blacklisting_no_bl")) || (0 == strcmp (test_name, "test_transport_blacklisting_multiple_plugins"))) { if ((GNUNET_NO != started) && (GNUNET_YES == connected)) ok = 0; else { GNUNET_break(0); ok = 1; } } else { if ((GNUNET_NO != started) && (GNUNET_YES != connected)) ok = 0; else { ok = 1; } } GNUNET_SCHEDULER_add_now (&end, NULL ); } static void run(void *cls, char * const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { connected = GNUNET_NO; stage = 0; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Running test `%s'!\n", test_name); stage_task = GNUNET_SCHEDULER_add_now (&run_stage, NULL ); } int main(int argc, char *argv0[]) { ok = 1; GNUNET_TRANSPORT_TESTING_get_test_name (argv0[0], &test_name); GNUNET_log_setup ("test-transport-api-blacklisting", "WARNING", NULL ); static char * const argv[] = { "date", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1, argv, "test-transport-api-blacklisting", "nohelp", options, &run, NULL ); GNUNET_TRANSPORT_TESTING_done (tth); return ok; } /* end of transport_api_blacklisting.c */ gnunet-0.10.1/src/transport/plugin_transport_template.c0000644000175000017500000003013712254304366020317 00000000000000/* This file is part of GNUnet (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_template.c * @brief template for a new transport service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #define LOG(kind,...) GNUNET_log_from (kind, "transport-template",__VA_ARGS__) /** * After how long do we expire an address that we * learned from another peer if it is not reconfirmed * by anyone? */ #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6) #define PLUGIN_NAME "template" /** * Encapsulation of all of the state of the plugin. */ struct Plugin; /** * Session handle for connections. */ struct Session { /** * To whom are we talking to (set to our identity * if we are still waiting for the welcome message) */ struct GNUNET_PeerIdentity sender; /** * Stored in a linked list. */ struct Session *next; /** * Pointer to the global plugin struct. */ struct Plugin *plugin; /** * The client (used to identify this connection) */ /* void *client; */ /** * Continuation function to call once the transmission buffer * has again space available. NULL if there is no * continuation to call. */ GNUNET_TRANSPORT_TransmitContinuation transmit_cont; /** * Closure for transmit_cont. */ void *transmit_cont_cls; /** * At what time did we reset last_received last? */ struct GNUNET_TIME_Absolute last_quota_update; /** * How many bytes have we received since the "last_quota_update" * timestamp? */ uint64_t last_received; /** * Number of bytes per ms that this peer is allowed * to send to us. */ uint32_t quota; }; GNUNET_NETWORK_STRUCT_BEGIN struct TemplateAddress { /** * Address options in NBO */ uint32_t options GNUNET_PACKED; /* Add address here */ }; GNUNET_NETWORK_STRUCT_END /** * Encapsulation of all of the state of the plugin. */ struct Plugin { /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * List of open sessions. */ struct Session *sessions; /** * Options in HBO to be used with addresses */ }; /** * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param session which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in @a msgbuf * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for @a cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t template_plugin_send (void *cls, struct Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin *plugin = cls; int bytes_sent = 0; GNUNET_assert (plugin != NULL); GNUNET_assert (session != NULL); /* struct Plugin *plugin = cls; */ return bytes_sent; } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuationc). * * @param cls closure * @param target peer from which to disconnect */ static void template_plugin_disconnect_peer (void *cls, const struct GNUNET_PeerIdentity *target) { // struct Plugin *plugin = cls; // FIXME } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuationc). * * @param cls closure * @param session session from which to disconnect * @return #GNUNET_OK on success */ static int template_plugin_disconnect_session (void *cls, struct Session *session) { // struct Plugin *plugin = cls; // FIXME return GNUNET_SYSERR; } /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int template_plugin_query_keepalive_factor (void *cls) { return 3; } /** * Function obtain the network type for a session * * @param cls closure ('struct Plugin*') * @param session the session * @return the network type in HBO or GNUNET_SYSERR */ static enum GNUNET_ATS_Network_Type template_plugin_get_network (void *cls, struct Session *session) { GNUNET_assert (NULL != session); return GNUNET_ATS_NET_UNSPECIFIED; /* Change to correct network type */ } /** * Convert the transports address to a nice, human-readable * format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the address * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for asc */ static void template_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { if (0 == addrlen) { asc (asc_cls, TRANSPORT_SESSION_INBOUND_STRING); } asc (asc_cls, NULL); } /** * Another peer has suggested an address for this * peer and transport plugin. Check that this could be a valid * address. If so, consider adding it to the list * of addresses. * * @param cls closure * @param addr pointer to the address * @param addrlen length of addr * @return #GNUNET_OK if this is a plausible address for this peer * and transport */ static int template_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) { /* struct Plugin *plugin = cls; */ /* check if the address is belonging to the plugin*/ return GNUNET_OK; } /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ static const char * template_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) { /* * Print address in format template.options.address */ if (0 == addrlen) { return TRANSPORT_SESSION_INBOUND_STRING; } GNUNET_break (0); return NULL; } /** * Function called to convert a string address to * a binary address. * * @param cls closure ('struct Plugin*') * @param addr string address * @param addrlen length of the @a addr * @param buf location to store the buffer * @param added location to store the number of bytes in the buffer. * If the function returns #GNUNET_SYSERR, its contents are undefined. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static int template_plugin_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added) { /* * Parse string in format template.options.address */ GNUNET_break (0); return GNUNET_SYSERR; } /** * Create a new session to transmit data to the target * This session will used to send data to this peer and the plugin will * notify us by calling the env->session_end function * * @param cls closure * @param address pointer to the GNUNET_HELLO_Address * @return the session if the address is valid, NULL otherwise */ static struct Session * template_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { GNUNET_break (0); return NULL; } static void template_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { } /** * Entry point for the plugin. */ void * libgnunet_plugin_transport_template_init (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *plugin; if (NULL == env->receive) { /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully initialze the plugin or the API */ api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = NULL; api->address_to_string = &template_plugin_address_to_string; api->string_to_address = &template_plugin_string_to_address; api->address_pretty_printer = &template_plugin_address_pretty_printer; return api; } plugin = GNUNET_new (struct Plugin); plugin->env = env; api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = plugin; api->send = &template_plugin_send; api->disconnect_peer = &template_plugin_disconnect_peer; api->disconnect_session = &template_plugin_disconnect_session; api->query_keepalive_factor = &template_plugin_query_keepalive_factor; api->address_pretty_printer = &template_plugin_address_pretty_printer; api->check_address = &template_plugin_address_suggested; api->address_to_string = &template_plugin_address_to_string; api->string_to_address = &template_plugin_string_to_address; api->get_session = &template_plugin_get_session; api->get_network = &template_plugin_get_network; api->update_session_timeout = &template_plugin_update_session_timeout; LOG (GNUNET_ERROR_TYPE_INFO, "Template plugin successfully loaded\n"); return api; } /** * Exit point from the plugin. */ void * libgnunet_plugin_transport_template_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_transport_template.c */ gnunet-0.10.1/src/transport/test_transport_api_restart_1peer.c0000644000175000017500000003061512274162761021602 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_restart_1peer.c * @brief base test case for transport implementations * * This test case starts 2 peers, connects and exchanges a message * 1 peer is restarted and tested if peers reconnect * C code apparently. */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) #define MTYPE 12345 static char *test_name; static int ok; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static GNUNET_SCHEDULER_TaskIdentifier reconnect_task; static struct PeerContext *p1; static int p1_connected; static struct PeerContext *p2; static int p2_connected; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static int restarted; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; if (reconnect_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (reconnect_task); reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); p1 = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); p2 = NULL; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (restarted == GNUNET_YES) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer was restarted\n"); if (restarted == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer was NOT restarted\n"); if (reconnect_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (reconnect_task); reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); ok = GNUNET_SYSERR; } static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerContext *p = cls; reconnect_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_TRANSPORT_try_connect (p->th, &p2->id, NULL, NULL); /*FIXME TRY_CONNECT change */ reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect, p); } static void restart_cb (struct PeerContext *p, void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Restarted peer %u (`%4s'), issuing reconnect\n", p->no, GNUNET_i2s (&p->id)); reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, p); } static void restart (struct PeerContext *p, char *cfg_file) { GNUNET_assert (p != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Restarting peer %u (`%4s')\n", p->no, GNUNET_i2s (&p->id)); GNUNET_TRANSPORT_TESTING_restart_peer (tth, p, cfg_file, &restart_cb, p); return; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if ((MTYPE == ntohs (message->type)) && (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size))) { if (restarted == GNUNET_NO) { restarted = GNUNET_YES; restart (p1, cfg_file_p1); return; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Restarted peers connected and message was sent, stopping test...\n"); ok = 0; end (); } } else { GNUNET_break (0); ok = 1; if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); } } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= 256); if (buf != NULL) { hdr = buf; hdr->size = htons (sizeof (struct GNUNET_MessageHeader)); hdr->type = htons (MTYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return sizeof (struct GNUNET_MessageHeader); } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, 256, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) { p1_connected = GNUNET_YES; t = p1; } if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) { p2_connected = GNUNET_YES; t = p2; } GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); if ((restarted == GNUNET_YES) && ((p1_connected == GNUNET_YES) && (p2_connected == GNUNET_YES))) { /* Peer was restarted and we received 3 connect messages (2 from first connect, 1 from reconnect) */ send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; if ( (NULL != p1) && (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity)))) { p1_connected = GNUNET_NO; } if ( (NULL != p2) && (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity)))) { p2_connected = GNUNET_NO; } char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (GNUNET_SCHEDULER_NO_TASK != send_task) GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); p1_connected = GNUNET_NO; p2_connected = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_asprintf (&cfg_file_p1, "test_transport_api_tcp_peer1.conf"); GNUNET_asprintf (&cfg_file_p2, "test_transport_api_tcp_peer2.conf"); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of test_transport_api_restart_1peer.c */ gnunet-0.10.1/src/transport/test_transport_api_manipulation_send_tcp.c0000644000175000017500000003270612274162761023404 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_manipulation_send_tcp.c * @brief base test case for transport traffic manipulation implementation * * This test case will setup 2 peers and connect them, the first message * will be sent without manipulation, then a send delay of 1 second will * be configured and 1 more message will be sent. Time will be measured. * * In addition the distance on receiver side will be manipulated to be 10 */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) #define TEST_MESSAGE_SIZE 2600 #define TEST_MESSAGE_TYPE 12345 static char *test_source; static char *test_plugin; static char *test_name; static int ok; static int s_started; static int s_connected; static int s_sending; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static int messages_recv; static struct GNUNET_TIME_Absolute start_normal; static struct GNUNET_TIME_Relative dur_normal; static struct GNUNET_TIME_Absolute start_delayed; static struct GNUNET_TIME_Relative dur_delayed; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); if (s_started == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started \n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started \n")); if (s_connected == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not connected\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were connected\n")); if (s_sending == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were ready to send data\n")); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 1 was not started\n")); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 2 was not started\n")); ok = GNUNET_SYSERR; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if ((TEST_MESSAGE_TYPE == ntohs (message->type)) && (TEST_MESSAGE_SIZE == ntohs (message->size))) { ok = 0; } else { GNUNET_break (0); ok = 1; end (); return; } if (0 == messages_recv) { /* Received non-delayed message */ dur_normal = GNUNET_TIME_absolute_get_duration(start_normal); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received non-delayed message %u after %s\n", messages_recv, GNUNET_STRINGS_relative_time_to_string (dur_normal, GNUNET_YES)); send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } if (1 == messages_recv) { /* Received manipulated message */ dur_delayed = GNUNET_TIME_absolute_get_duration(start_delayed); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received delayed message %u after %s\n", messages_recv, GNUNET_STRINGS_relative_time_to_string (dur_delayed, GNUNET_YES)); if (dur_delayed.rel_value_us < 1000 * 1000LL) { GNUNET_break (0); ok += 1; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Delayed message was not delayed correctly: took only %s\n", GNUNET_STRINGS_relative_time_to_string (dur_delayed, GNUNET_YES)); } /* shutdown */ end (); } messages_recv ++; } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= TEST_MESSAGE_SIZE); if (buf != NULL) { memset (buf, '\0', TEST_MESSAGE_SIZE); hdr = buf; hdr->size = htons (TEST_MESSAGE_SIZE); hdr->type = htons (TEST_MESSAGE_TYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return TEST_MESSAGE_SIZE; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_ATS_Information ats[1]; send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); if (0 == messages_recv) { start_normal = GNUNET_TIME_absolute_get(); } if (1 == messages_recv) { ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); ats[0].value = htonl (1000LL * 1000LL); GNUNET_TRANSPORT_set_traffic_metric (p2->th, &p1->id, GNUNET_NO, GNUNET_YES, ats, 1); ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); ats[0].value = htonl (10); GNUNET_TRANSPORT_set_traffic_metric (p1->th, &p2->id, GNUNET_YES, GNUNET_YES, ats, 1); start_delayed = GNUNET_TIME_absolute_get(); } s_sending = GNUNET_YES; th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); s_connected = GNUNET_YES; send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; else s_started = GNUNET_YES; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); /* struct GNUNET_ATS_Information ats[2]; ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); ats[0].value = htonl (1000); ats[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); ats[1].value = htonl (10); GNUNET_TRANSPORT_set_traffic_metric (p1->th, &p2->id, TM_RECEIVE, ats, 2); */ cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); s_started = GNUNET_NO; s_connected = GNUNET_NO; s_sending = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api-manipulation", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); GNUNET_log_setup (test_name, "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of test_transport_api.c */ gnunet-0.10.1/src/transport/test_plugin_hostkey.ecc0000644000175000017500000000147312115605602017417 00000000000000;(8:key-data (10:public-key (5:ecdsa (1:p33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ) (1:a33:ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü) (1:b32:ZÆ5ت:“ç³ë½Uv˜†¼e°ÌS°ö;Î<>'Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:…ˆàÜ gæiÕœ3='Ò`K) (1:g65:kÑòá,BGø¼æåc¤@òw}-ë3 ô¡9Eؘ–OãBâþ›ŽçëJ|ž+Î3Wk1^Î˶@h7¿Qõ) (1:n33:ÿÿÿÿÿÿÿÿÿÿÿÿ¼æú­§ž„ó¹ÊÂüc%Q) (1:q65:…ˆàÜ gæiÕœ3=addrstring); GNUNET_CONTAINER_DLL_remove(head, tail, w); c++; GNUNET_HELLO_address_free(w->address); GNUNET_free(w->addrstring); GNUNET_free(w); } if (c > 0) { GNUNET_break(0); GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin did not remove %u addresses \n", c); ok = 1; } GNUNET_free(libname); libname = NULL; GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; if (NULL != suid_helper) { GNUNET_HELPER_stop (suid_helper, GNUNET_NO); suid_helper = NULL; } } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct AddressWrapper *w; int c = 0; timeout_endbadly = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != timeout_wait) { GNUNET_SCHEDULER_cancel (timeout_wait); timeout_wait = GNUNET_SCHEDULER_NO_TASK; } if (pretty_printers_running > 0) { timeout_endbadly = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &end_badly, &ok); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Have pending calls to pretty_printer ... deferring shutdown\n"); return; } if (NULL != cls) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Test took too long to execute, timeout .... \n"); } if (NULL != libname) { if (NULL != api) GNUNET_PLUGIN_unload (libname, api); GNUNET_free(libname); libname = NULL; } while (NULL != head) { w = head; GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin did not remove address `%s'\n", w->addrstring); GNUNET_CONTAINER_DLL_remove(head, tail, w); c++; GNUNET_HELLO_address_free(w->address); GNUNET_free(w->addrstring); GNUNET_free(w); } if (c > 0) { GNUNET_break(0); GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin did not remove %u addresses\n", c); } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } if (NULL != suid_helper) { GNUNET_HELPER_stop (suid_helper, GNUNET_NO); suid_helper = NULL; } ok = 1; } static void wait_end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { timeout_wait = GNUNET_SCHEDULER_NO_TASK; if (0 == addresses_reported) GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Plugin did not report any addresses, could not check address conversion functions\n"); end (); } static void end_badly_now () { if (GNUNET_SCHEDULER_NO_TASK != timeout_wait) { GNUNET_SCHEDULER_cancel (timeout_wait); timeout_wait = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != timeout_endbadly) { GNUNET_SCHEDULER_cancel (timeout_endbadly); timeout_endbadly = GNUNET_SCHEDULER_NO_TASK; } timeout_endbadly = GNUNET_SCHEDULER_add_now (&end_badly, NULL ); } static struct GNUNET_TIME_Relative env_receive (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message) { /* do nothing */ return GNUNET_TIME_relative_get_zero_ (); } static int got_reply; /** * Take the given address and append it to the set of results sent back to * the client. * * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*') * @param buf text to transmit */ static void address_pretty_printer_cb (void *cls, const char *buf) { if (NULL != buf) { got_reply = GNUNET_YES; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Pretty address : `%s'\n", buf); pretty_printers_running--; } else { if (GNUNET_NO == got_reply) { pretty_printers_running--; GNUNET_break(0); end_badly_now (); } } } static void env_notify_address (void *cls, int add_remove, const struct GNUNET_HELLO_Address *address) { struct AddressWrapper *w; struct AddressWrapper *wtmp; void *s2a; size_t s2a_len; if (GNUNET_YES == add_remove) { addresses_reported++; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Adding address of length %u\n", address->address_length); for (wtmp = head; NULL != wtmp; wtmp = wtmp->next) { if ((address->address_length == wtmp->address->address_length) && (0 == memcmp (address->address, wtmp->address->address, address->address_length))) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Duplicate address notification .... \n"); return; } } w = GNUNET_new (struct AddressWrapper); w->address = GNUNET_HELLO_address_copy (address); GNUNET_CONTAINER_DLL_insert(head, tail, w); got_reply = GNUNET_NO; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Testing: address_to_string \n"); w->addrstring = strdup ( api->address_to_string (api, w->address->address, w->address->address_length)); if (NULL == w->addrstring) { GNUNET_break(0); GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin cannot convert address to string!\n"); end_badly_now (); return; } else { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Plugin added address `%s'\n", w->addrstring); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Testing address_to_string: OK\n"); } GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Testing: string_to_address \n"); s2a = NULL; s2a_len = 0; if ((GNUNET_OK != api->string_to_address (api, w->addrstring, strlen (w->addrstring) + 1, &s2a, &s2a_len)) || (NULL == s2a)) { GNUNET_break(0); GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin cannot convert string to address!\n"); end_badly_now (); return; } /* GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Plugin creates `%s' %u\n",api->address_to_string (api, s2a, s2a_len), s2a_len); int c1; for (c1 = 0; c1 < s2a_len; c1++ ) fprintf (stderr, "%u == %u\n", ((char *) s2a)[c1], ((char *) w->addr)[c1]); */ if (s2a_len != w->address->address_length) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin creates different address length when converting address->string->address: %u != %u\n", w->address->address_length, s2a_len); } else if (0 != memcmp (s2a, w->address->address, s2a_len)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin creates different address length when converting back and forth %i!\n", memcmp (s2a, w->address->address, s2a_len)); } else { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Testing string_to_address: OK\n"); } GNUNET_free(s2a); pretty_printers_running++; api->address_pretty_printer (api->cls, address->transport_name, address->address, address->address_length, GNUNET_YES, GNUNET_TIME_UNIT_MINUTES, &address_pretty_printer_cb, w); if (GNUNET_OK != api->check_address (api->cls, w->address->address, w->address->address_length)) { GNUNET_break(0); GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin refuses added address!\n"); end_badly_now (); return; } if (GNUNET_SCHEDULER_NO_TASK != timeout_wait) { GNUNET_SCHEDULER_cancel (timeout_wait); timeout_wait = GNUNET_SCHEDULER_NO_TASK; } timeout_wait = GNUNET_SCHEDULER_add_delayed (WAIT, &wait_end, NULL ); } else if (GNUNET_NO == add_remove) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Removing address of length %u\n", address->address_length); w = head; while (NULL != w) { if ((address->address_length == w->address->address_length) && (0 == memcmp (w->address->address, address->address, address->address_length))) { break; } w = w->next; } if (w == NULL ) { GNUNET_break(0); GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Plugin removes address never added!\n"); end_badly_now (); return; } GNUNET_CONTAINER_DLL_remove(head, tail, w); GNUNET_HELLO_address_free (w->address); GNUNET_free(w->addrstring); GNUNET_free(w); } else { GNUNET_break(0); GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Invalid operation: %u\n", add_remove); end_badly_now (); return; } } static struct GNUNET_ATS_Information env_get_address_type (void *cls, const struct sockaddr *addr, size_t addrlen) { struct GNUNET_ATS_Information ats; ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.value = htonl (GNUNET_ATS_NET_LOOPBACK); return ats; } static const struct GNUNET_MessageHeader * env_get_our_hello () { return (const struct GNUNET_MessageHeader *) hello; } static void env_session_end (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session) { } static void env_update_metrics (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { } static void setup_plugin_environment () { env.cfg = cfg; env.cls = &env; env.my_identity = &my_identity; env.max_connections = max_connect_per_transport; env.stats = stats; env.receive = &env_receive; env.notify_address = &env_notify_address; env.get_address_type = &env_get_address_type; env.update_address_metrics = &env_update_metrics; env.get_our_hello = &env_get_our_hello; env.session_end = &env_session_end; } static int handle_helper_message (void *cls, void *client, const struct GNUNET_MessageHeader *hdr) { return GNUNET_OK; } /** * Runs the test. * * @param cls closure * @param c configuration to use */ static void run (void *cls, char * const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { char * const *argv = cls; unsigned long long tneigh; char *keyfile; char *plugin; char *sep; timeout_endbadly = GNUNET_SCHEDULER_add_delayed (TIMEOUT, end_badly, &ok); cfg = c; /* parse configuration */ if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "TRANSPORT", "NEIGHBOUR_LIMIT", &tneigh)) || (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY", &keyfile))) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Transport service is lacking key configuration settings. Exiting.\n"); return; } if (NULL == (stats = GNUNET_STATISTICS_create ("transport", cfg))) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not create statistics. Exiting.\n"); GNUNET_free(keyfile); end_badly_now (); return; } if (GNUNET_OK != GNUNET_DISK_file_test (HOSTKEY_FILE)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Hostkey `%s' missing. Exiting.\n", HOSTKEY_FILE); GNUNET_free(keyfile); end_badly_now (); return; } if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not create a directory for hostkey `%s'. Exiting.\n", keyfile); GNUNET_free(keyfile); end_badly_now (); return; } if (GNUNET_OK != GNUNET_DISK_file_copy (HOSTKEY_FILE, keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not copy hostkey `%s' to destination `%s'. Exiting.\n", HOSTKEY_FILE, keyfile); GNUNET_free(keyfile); end_badly_now (); return; } max_connect_per_transport = (uint32_t) tneigh; my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile); GNUNET_free(keyfile); if (NULL == my_private_key) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not access hostkey. Exiting.\n"); end_badly_now (); return; } GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key); hello = GNUNET_HELLO_create (&my_identity.public_key, NULL, NULL, GNUNET_NO); /* load plugins... */ setup_plugin_environment (); GNUNET_assert(strlen (argv[0]) > strlen ("test_plugin_")); plugin = strstr (argv[0], "test_plugin_"); sep = strrchr (argv[0], '.'); if (NULL == plugin) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Not a valid test name\n"); end_badly_now (); return; } plugin += strlen ("test_plugin_"); if (NULL != sep) sep[0] = '\0'; /* Hack for WLAN: start a second helper */ if (0 == strcmp (plugin, "wlan")) { char * helper_argv[3]; helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy"; helper_argv[1] = (char *) "2"; helper_argv[2] = NULL; suid_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-transport-wlan-dummy", helper_argv, &handle_helper_message, NULL, NULL ); } /* Loading plugin */ GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Loading transport plugin %s\n", plugin); GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", plugin); api = GNUNET_PLUGIN_load (libname, &env); if (api == NULL ) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to load transport plugin for %s\n", plugin); end_badly_now (); return; } timeout_wait = GNUNET_SCHEDULER_add_delayed (WAIT, &wait_end, NULL ); /* Check if all functions are implemented */ if (NULL == api->address_pretty_printer) { GNUNET_break(0); end_badly_now (); return; } if (NULL == api->address_to_string) { GNUNET_break(0); end_badly_now (); return; } GNUNET_assert(NULL != api->check_address); if (NULL == api->check_address) { GNUNET_break(0); end_badly_now (); return; } GNUNET_assert(NULL != api->disconnect_peer); if (NULL == api->disconnect_peer) { GNUNET_break(0); end_badly_now (); return; } GNUNET_assert(NULL != api->get_session); if (NULL == api->get_session) { GNUNET_break(0); end_badly_now (); return; } if (NULL == api->address_pretty_printer) { GNUNET_break(0); end_badly_now (); return; } if (NULL == api->string_to_address) { GNUNET_break(0); end_badly_now (); return; } } /** * The main function for the test * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char * const *argv) { static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-plugin-transport"); char * const argv_prog[] = { "test_plugin_transport", "-c", "test_plugin_transport_data.conf", NULL }; GNUNET_log_setup ("test-plugin-transport", "WARNING", NULL ); ok = 1; /* set to fail */ ret = (GNUNET_OK == GNUNET_PROGRAM_run (3, argv_prog, "test-plugin-transport", "testcase", options, &run, (void *) argv)) ? ok : 1; GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-plugin-transport"); return ret; } /* end of test_plugin_transport.c */ gnunet-0.10.1/src/transport/test_transport_startonly.c0000644000175000017500000001104112225777502020221 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api.c * @brief base test case for transport implementations * * This test case serves as a base for tcp, udp, and udp-nat * transport test cases. Based on the executable being run * the correct test case will be performed. Conservation of * C code apparently. */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90) #define ITERATIONS 10 GNUNET_SCHEDULER_TaskIdentifier timeout_task; static struct PeerContext *p1; struct GNUNET_TRANSPORT_TESTING_handle *tth; static int connected = GNUNET_NO; static int ret = 0; static int i; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_TRANSPORT_TESTING_done (tth); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exiting\n"); } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); timeout_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (NULL != tth) GNUNET_TRANSPORT_TESTING_done (tth); ret = GNUNET_SYSERR; } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected \n", GNUNET_i2s (peer)); connected++; } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' disconnected \n", GNUNET_i2s (peer)); } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving\n"); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { tth = GNUNET_TRANSPORT_TESTING_init (); timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); i = 1; FPRINTF (stderr, "%i", i); while (i <= ITERATIONS) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting peer\n"); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_startonly.conf", 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, NULL, p1); if (p1 != NULL) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer was successfully started\n"); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer1 was not started successfully\n"); GNUNET_assert (p1 != NULL); GNUNET_assert (p1->th != NULL); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); i++; if (i <= ITERATIONS) FPRINTF (stderr, "..%i", i); } FPRINTF (stderr, "%s", "\n"); end (); } int main (int argc, char *argv[]) { GNUNET_log_setup ("test_transport_testing", "WARNING", NULL); char *const argv_1[] = { "test_transport_testing", "-c", "test_transport_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run ((sizeof (argv_1) / sizeof (char *)) - 1, argv_1, "test_transport_testing", "nohelp", options, &run, &ret); return ret; } /* end of test_transport_api.c */ gnunet-0.10.1/src/transport/test_quota_compliance_http_asymmetric_peer1.conf0000644000175000017500000000121012225230043024441 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer1 [transport-http_client] [arm] PORT = 4015 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_arm_peer1.sock [statistics] PORT = 4014 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_statistics_peer1.sock [resolver] PORT = 4013 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_resolver_peer1.sock [peerinfo] PORT = 4012 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_peerinfo_peer1.sock [transport] PORT = 4011 PLUGINS = http_client UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_transport_peer1.sock gnunet-0.10.1/src/transport/test_transport_api_disconnect.c0000644000175000017500000002524012274162761021151 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_disconnect.c * @brief base test case for transport implementations * * This test case tests disconnect notifications in peer shutdown */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) #define MTYPE 12345 static char *test_source; static char *test_plugin; static char *test_name; static int ok; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; struct PeerContext *p1; struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; struct GNUNET_TRANSPORT_TransmitHandle *th; struct GNUNET_TRANSPORT_TESTING_handle *tth; int shutdown_; char *cfg_file_p1; char *cfg_file_p2; #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; } if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); p1 = NULL; if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); p2 = NULL; /* success */ ok = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (cc != NULL) { GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (send_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); ok = GNUNET_SYSERR; } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (shutdown_ == GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Complete, shutting down...\n"); GNUNET_SCHEDULER_add_now (&end, NULL); } } static void stop_peer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); shutdown_ = GNUNET_YES; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); p2 = NULL; GNUNET_assert (p2 == NULL); } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if ((MTYPE == ntohs (message->type)) && (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size))) { ok = 1; GNUNET_SCHEDULER_add_now (stop_peer, p2); return; } } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= 256); if (buf != NULL) { hdr = buf; hdr->size = htons (sizeof (struct GNUNET_MessageHeader)); hdr->type = htons (MTYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return sizeof (struct GNUNET_MessageHeader); } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, 256, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of test_transport_api.c */ gnunet-0.10.1/src/transport/Makefile.in0000644000175000017500000075666312320755170014733 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ noinst_PROGRAMS = $(am__EXEEXT_35) $(am__EXEEXT_36) libexec_PROGRAMS = $(am__EXEEXT_32) $(am__EXEEXT_33) $(am__EXEEXT_34) \ gnunet-service-transport$(EXEEXT) bin_PROGRAMS = gnunet-transport$(EXEEXT) \ gnunet-transport-certificate-creation$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = \ @HAVE_TESTING_TRUE@ test_transport_testing_startstop$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_testing_restart$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_testing$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_startonly$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_plugin_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_plugin_udp$(EXEEXT) $(am__EXEEXT_1) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_2) $(am__EXEEXT_3) \ @HAVE_TESTING_TRUE@ test_http_common$(EXEEXT) $(am__EXEEXT_4) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_5) $(am__EXEEXT_6) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_7) \ @HAVE_TESTING_TRUE@ test_transport_api_blacklisting$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_disconnect_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_bidirectional_connect$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_restart_1peer$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_restart_2peers$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_timeout_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_limited_sockets_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_tcp_nat$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_udp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_timeout_udp$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_8) $(am__EXEEXT_9) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_10) \ @HAVE_TESTING_TRUE@ test_transport_api_udp_nat$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_11) $(am__EXEEXT_12) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_13) $(am__EXEEXT_14) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_15) $(am__EXEEXT_16) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_17) $(am__EXEEXT_18) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_19) \ @HAVE_TESTING_TRUE@ test_transport_api_multi$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_monitoring$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_monitoring_validation$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_blacklisting_no_bl$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_blacklisting_outbound_bl_full$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_blacklisting_outbound_bl_plugin$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_blacklisting_inbound_bl_plugin$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_blacklisting_inbound_bl_full$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_blacklisting_multiple_plugins$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_manipulation_send_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_manipulation_recv_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_manipulation_cfg$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_reliability_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_reliability_tcp_nat$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_unreliability_udp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_api_unreliability_constant_udp$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_20) $(am__EXEEXT_21) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_22) $(am__EXEEXT_23) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_24) $(am__EXEEXT_25) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_26) \ @HAVE_TESTING_TRUE@ test_quota_compliance_tcp$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_quota_compliance_tcp_asymmetric$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_quota_compliance_udp$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_27) $(am__EXEEXT_28) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_29) $(am__EXEEXT_30) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_31) @ENABLE_TEST_RUN_TRUE@TESTS = test_transport_testing_startstop$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_testing_restart$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_testing$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_startonly$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_plugin_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_plugin_udp$(EXEEXT) $(am__EXEEXT_1) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_2) $(am__EXEEXT_3) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_blacklisting$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_disconnect_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_bidirectional_connect$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_restart_1peer$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_restart_2peers$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_timeout_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_limited_sockets_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_tcp_nat$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_udp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_timeout_udp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_8) $(am__EXEEXT_9) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_10) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_udp_nat$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_11) $(am__EXEEXT_13) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_14) $(am__EXEEXT_15) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_16) $(am__EXEEXT_17) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_18) $(am__EXEEXT_19) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_multi$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_monitoring$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_monitoring_validation$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_blacklisting_no_bl$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_blacklisting_outbound_bl_full$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_blacklisting_outbound_bl_plugin$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_blacklisting_inbound_bl_plugin$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_blacklisting_inbound_bl_full$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_blacklisting_multiple_plugins$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_manipulation_send_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_manipulation_recv_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_manipulation_cfg$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_reliability_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_reliability_tcp_nat$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_unreliability_udp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_transport_api_unreliability_constant_udp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_20) $(am__EXEEXT_21) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_22) $(am__EXEEXT_23) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_24) $(am__EXEEXT_25) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_26) \ @ENABLE_TEST_RUN_TRUE@ test_quota_compliance_tcp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_quota_compliance_tcp_asymmetric$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ test_quota_compliance_udp$(EXEEXT) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_27) $(am__EXEEXT_28) \ @ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_29) subdir = src/transport DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/transport.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = transport.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) libgnunet_plugin_transport_bluetooth_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunet_plugin_transport_bluetooth_la_OBJECTS = \ plugin_transport_bluetooth.lo libgnunet_plugin_transport_bluetooth_la_OBJECTS = \ $(am_libgnunet_plugin_transport_bluetooth_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_transport_bluetooth_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_bluetooth_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am_libgnunet_plugin_transport_bluetooth_la_rpath = \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ -rpath $(plugindir) @LINUX_FALSE@@MINGW_TRUE@am_libgnunet_plugin_transport_bluetooth_la_rpath = \ @LINUX_FALSE@@MINGW_TRUE@ -rpath $(plugindir) libgnunet_plugin_transport_http_client_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunet_plugin_transport_http_client_la_OBJECTS = libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.lo \ libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.lo libgnunet_plugin_transport_http_client_la_OBJECTS = \ $(am_libgnunet_plugin_transport_http_client_la_OBJECTS) libgnunet_plugin_transport_http_client_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(libgnunet_plugin_transport_http_client_la_CFLAGS) \ $(CFLAGS) $(libgnunet_plugin_transport_http_client_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_LIBGNURL_TRUE@am_libgnunet_plugin_transport_http_client_la_rpath = \ @HAVE_LIBGNURL_TRUE@ -rpath $(plugindir) libgnunet_plugin_transport_http_server_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunet_plugin_transport_http_server_la_OBJECTS = libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.lo \ libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.lo libgnunet_plugin_transport_http_server_la_OBJECTS = \ $(am_libgnunet_plugin_transport_http_server_la_OBJECTS) libgnunet_plugin_transport_http_server_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(libgnunet_plugin_transport_http_server_la_CFLAGS) \ $(CFLAGS) $(libgnunet_plugin_transport_http_server_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_MHD_TRUE@am_libgnunet_plugin_transport_http_server_la_rpath = \ @HAVE_MHD_TRUE@ -rpath $(plugindir) libgnunet_plugin_transport_https_client_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunet_plugin_transport_https_client_la_OBJECTS = libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.lo \ libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.lo libgnunet_plugin_transport_https_client_la_OBJECTS = \ $(am_libgnunet_plugin_transport_https_client_la_OBJECTS) libgnunet_plugin_transport_https_client_la_LINK = $(LIBTOOL) \ $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) \ $(libgnunet_plugin_transport_https_client_la_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_https_client_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_LIBGNURL_TRUE@am_libgnunet_plugin_transport_https_client_la_rpath = \ @HAVE_LIBGNURL_TRUE@ -rpath $(plugindir) libgnunet_plugin_transport_https_server_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunet_plugin_transport_https_server_la_OBJECTS = libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.lo \ libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.lo libgnunet_plugin_transport_https_server_la_OBJECTS = \ $(am_libgnunet_plugin_transport_https_server_la_OBJECTS) libgnunet_plugin_transport_https_server_la_LINK = $(LIBTOOL) \ $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) \ $(libgnunet_plugin_transport_https_server_la_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_https_server_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_MHD_TRUE@am_libgnunet_plugin_transport_https_server_la_rpath = \ @HAVE_MHD_TRUE@ -rpath $(plugindir) am__DEPENDENCIES_1 = libgnunet_plugin_transport_tcp_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunet_plugin_transport_tcp_la_OBJECTS = \ plugin_transport_tcp.lo libgnunet_plugin_transport_tcp_la_OBJECTS = \ $(am_libgnunet_plugin_transport_tcp_la_OBJECTS) libgnunet_plugin_transport_tcp_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_tcp_la_LDFLAGS) $(LDFLAGS) -o $@ libgnunet_plugin_transport_template_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunet_plugin_transport_template_la_OBJECTS = \ plugin_transport_template.lo libgnunet_plugin_transport_template_la_OBJECTS = \ $(am_libgnunet_plugin_transport_template_la_OBJECTS) libgnunet_plugin_transport_template_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_template_la_LDFLAGS) $(LDFLAGS) \ -o $@ libgnunet_plugin_transport_udp_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunet_plugin_transport_udp_la_OBJECTS = \ plugin_transport_udp.lo plugin_transport_udp_broadcasting.lo libgnunet_plugin_transport_udp_la_OBJECTS = \ $(am_libgnunet_plugin_transport_udp_la_OBJECTS) libgnunet_plugin_transport_udp_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_udp_la_LDFLAGS) $(LDFLAGS) -o $@ libgnunet_plugin_transport_unix_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunet_plugin_transport_unix_la_OBJECTS = \ plugin_transport_unix.lo libgnunet_plugin_transport_unix_la_OBJECTS = \ $(am_libgnunet_plugin_transport_unix_la_OBJECTS) libgnunet_plugin_transport_unix_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_unix_la_LDFLAGS) $(LDFLAGS) -o $@ @MINGW_FALSE@am_libgnunet_plugin_transport_unix_la_rpath = -rpath \ @MINGW_FALSE@ $(plugindir) libgnunet_plugin_transport_wlan_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunet_plugin_transport_wlan_la_OBJECTS = \ plugin_transport_wlan.lo libgnunet_plugin_transport_wlan_la_OBJECTS = \ $(am_libgnunet_plugin_transport_wlan_la_OBJECTS) libgnunet_plugin_transport_wlan_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_wlan_la_LDFLAGS) $(LDFLAGS) -o $@ @LINUX_TRUE@am_libgnunet_plugin_transport_wlan_la_rpath = -rpath \ @LINUX_TRUE@ $(plugindir) libgnunettransport_la_DEPENDENCIES = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunettransport_la_OBJECTS = transport_api.lo \ transport_api_blacklist.lo transport_api_address_to_string.lo \ transport_api_monitoring.lo libgnunettransport_la_OBJECTS = $(am_libgnunettransport_la_OBJECTS) libgnunettransport_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunettransport_la_LDFLAGS) \ $(LDFLAGS) -o $@ am_libgnunettransporttesting_la_OBJECTS = transport-testing.lo libgnunettransporttesting_la_OBJECTS = \ $(am_libgnunettransporttesting_la_OBJECTS) libgnunettransporttesting_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunettransporttesting_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_TESTING_TRUE@am_libgnunettransporttesting_la_rpath = -rpath \ @HAVE_TESTING_TRUE@ $(libdir) @MINGW_FALSE@am__EXEEXT_1 = test_plugin_unix$(EXEEXT) @LINUX_TRUE@am__EXEEXT_2 = test_plugin_wlan$(EXEEXT) @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am__EXEEXT_3 = test_plugin_bluetooth$(EXEEXT) @HAVE_LIBGNURL_TRUE@am__EXEEXT_4 = test_plugin_http_client$(EXEEXT) @HAVE_LIBGNURL_TRUE@am__EXEEXT_5 = test_plugin_https_client$(EXEEXT) @HAVE_MHD_TRUE@am__EXEEXT_6 = test_plugin_http_server$(EXEEXT) @HAVE_MHD_TRUE@am__EXEEXT_7 = test_plugin_https_server$(EXEEXT) @MINGW_FALSE@am__EXEEXT_8 = test_transport_api_unix$(EXEEXT) @MINGW_FALSE@am__EXEEXT_9 = test_transport_api_timeout_unix$(EXEEXT) @LINUX_TRUE@@MINGW_FALSE@am__EXEEXT_10 = test_transport_api_unix_abstract$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_11 = test_transport_api_http$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_12 = test_transport_api_http_reverse$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_13 = test_transport_api_timeout_http$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_14 = test_transport_api_https$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_15 = test_transport_api_timeout_https$(EXEEXT) @LINUX_TRUE@am__EXEEXT_16 = test_transport_api_wlan$(EXEEXT) @LINUX_TRUE@am__EXEEXT_17 = test_transport_api_timeout_wlan$(EXEEXT) @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am__EXEEXT_18 = test_transport_api_bluetooth$(EXEEXT) @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am__EXEEXT_19 = test_transport_api_timeout_bluetooth$(EXEEXT) @MINGW_FALSE@am__EXEEXT_20 = \ @MINGW_FALSE@ test_transport_api_unreliability_unix$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_21 = test_transport_api_reliability_http$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_22 = test_transport_api_reliability_https$(EXEEXT) @LINUX_TRUE@am__EXEEXT_23 = \ @LINUX_TRUE@ test_transport_api_reliability_wlan$(EXEEXT) @LINUX_TRUE@am__EXEEXT_24 = \ @LINUX_TRUE@ test_transport_api_unreliability_wlan$(EXEEXT) @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am__EXEEXT_25 = test_transport_api_reliability_bluetooth$(EXEEXT) @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am__EXEEXT_26 = test_transport_api_unreliability_bluetooth$(EXEEXT) @MINGW_FALSE@am__EXEEXT_27 = test_quota_compliance_unix$(EXEEXT) \ @MINGW_FALSE@ test_quota_compliance_unix_asymmetric$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_28 = test_quota_compliance_http$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@ test_quota_compliance_http_asymmetric$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@am__EXEEXT_29 = test_quota_compliance_https$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@ test_quota_compliance_https_asymmetric$(EXEEXT) @LINUX_TRUE@am__EXEEXT_30 = test_quota_compliance_wlan$(EXEEXT) \ @LINUX_TRUE@ test_quota_compliance_wlan_asymmetric$(EXEEXT) @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am__EXEEXT_31 = test_quota_compliance_bluetooth$(EXEEXT) \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ test_quota_compliance_bluetooth_asymmetric$(EXEEXT) @LINUX_TRUE@am__EXEEXT_32 = gnunet-helper-transport-wlan$(EXEEXT) @LINUX_TRUE@am__EXEEXT_33 = \ @LINUX_TRUE@ gnunet-helper-transport-wlan-dummy$(EXEEXT) @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am__EXEEXT_34 = gnunet-helper-transport-bluetooth$(EXEEXT) @LINUX_FALSE@@MINGW_TRUE@am__EXEEXT_34 = gnunet-helper-transport-bluetooth$(EXEEXT) @LINUX_TRUE@am__EXEEXT_35 = gnunet-transport-wlan-sender$(EXEEXT) @LINUX_TRUE@am__EXEEXT_36 = gnunet-transport-wlan-receiver$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_helper_transport_bluetooth_OBJECTS = \ gnunet-helper-transport-bluetooth.$(OBJEXT) gnunet_helper_transport_bluetooth_OBJECTS = \ $(am_gnunet_helper_transport_bluetooth_OBJECTS) @MINGW_TRUE@gnunet_helper_transport_bluetooth_DEPENDENCIES = \ @MINGW_TRUE@ $(top_builddir)/src/util/libgnunetutil.la gnunet_helper_transport_bluetooth_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(gnunet_helper_transport_bluetooth_LDFLAGS) $(LDFLAGS) -o $@ am_gnunet_helper_transport_wlan_OBJECTS = \ gnunet-helper-transport-wlan.$(OBJEXT) gnunet_helper_transport_wlan_OBJECTS = \ $(am_gnunet_helper_transport_wlan_OBJECTS) gnunet_helper_transport_wlan_LDADD = $(LDADD) am_gnunet_helper_transport_wlan_dummy_OBJECTS = \ gnunet-helper-transport-wlan-dummy.$(OBJEXT) gnunet_helper_transport_wlan_dummy_OBJECTS = \ $(am_gnunet_helper_transport_wlan_dummy_OBJECTS) gnunet_helper_transport_wlan_dummy_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_gnunet_service_transport_OBJECTS = \ gnunet_service_transport-gnunet-service-transport.$(OBJEXT) \ gnunet_service_transport-gnunet-service-transport_blacklist.$(OBJEXT) \ gnunet_service_transport-gnunet-service-transport_clients.$(OBJEXT) \ gnunet_service_transport-gnunet-service-transport_hello.$(OBJEXT) \ gnunet_service_transport-gnunet-service-transport_neighbours.$(OBJEXT) \ gnunet_service_transport-gnunet-service-transport_plugins.$(OBJEXT) \ gnunet_service_transport-gnunet-service-transport_validation.$(OBJEXT) \ gnunet_service_transport-gnunet-service-transport_manipulation.$(OBJEXT) gnunet_service_transport_OBJECTS = \ $(am_gnunet_service_transport_OBJECTS) gnunet_service_transport_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(gnunet_service_transport_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_gnunet_transport_OBJECTS = gnunet-transport.$(OBJEXT) gnunet_transport_OBJECTS = $(am_gnunet_transport_OBJECTS) am_gnunet_transport_certificate_creation_OBJECTS = \ gnunet-transport-certificate-creation.$(OBJEXT) gnunet_transport_certificate_creation_OBJECTS = \ $(am_gnunet_transport_certificate_creation_OBJECTS) gnunet_transport_certificate_creation_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_gnunet_transport_wlan_receiver_OBJECTS = \ gnunet-transport-wlan-receiver.$(OBJEXT) gnunet_transport_wlan_receiver_OBJECTS = \ $(am_gnunet_transport_wlan_receiver_OBJECTS) gnunet_transport_wlan_receiver_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_gnunet_transport_wlan_sender_OBJECTS = \ gnunet-transport-wlan-sender.$(OBJEXT) gnunet_transport_wlan_sender_OBJECTS = \ $(am_gnunet_transport_wlan_sender_OBJECTS) gnunet_transport_wlan_sender_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_http_common_OBJECTS = test_http_common.$(OBJEXT) \ plugin_transport_http_common.$(OBJEXT) test_http_common_OBJECTS = $(am_test_http_common_OBJECTS) test_http_common_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_bluetooth_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_bluetooth_OBJECTS = $(am_test_plugin_bluetooth_OBJECTS) test_plugin_bluetooth_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_http_client_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_http_client_OBJECTS = \ $(am_test_plugin_http_client_OBJECTS) test_plugin_http_client_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_http_server_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_http_server_OBJECTS = \ $(am_test_plugin_http_server_OBJECTS) test_plugin_http_server_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_https_client_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_https_client_OBJECTS = \ $(am_test_plugin_https_client_OBJECTS) test_plugin_https_client_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_https_server_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_https_server_OBJECTS = \ $(am_test_plugin_https_server_OBJECTS) test_plugin_https_server_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_tcp_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_tcp_OBJECTS = $(am_test_plugin_tcp_OBJECTS) test_plugin_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_udp_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_udp_OBJECTS = $(am_test_plugin_udp_OBJECTS) test_plugin_udp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_unix_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_unix_OBJECTS = $(am_test_plugin_unix_OBJECTS) test_plugin_unix_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_plugin_wlan_OBJECTS = test_plugin_transport.$(OBJEXT) test_plugin_wlan_OBJECTS = $(am_test_plugin_wlan_OBJECTS) test_plugin_wlan_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_bluetooth_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_bluetooth_OBJECTS = \ $(am_test_quota_compliance_bluetooth_OBJECTS) test_quota_compliance_bluetooth_DEPENDENCIES = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_bluetooth_asymmetric_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_bluetooth_asymmetric_OBJECTS = \ $(am_test_quota_compliance_bluetooth_asymmetric_OBJECTS) test_quota_compliance_bluetooth_asymmetric_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_http_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_http_OBJECTS = \ $(am_test_quota_compliance_http_OBJECTS) test_quota_compliance_http_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_http_asymmetric_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_http_asymmetric_OBJECTS = \ $(am_test_quota_compliance_http_asymmetric_OBJECTS) test_quota_compliance_http_asymmetric_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_https_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_https_OBJECTS = \ $(am_test_quota_compliance_https_OBJECTS) test_quota_compliance_https_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_https_asymmetric_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_https_asymmetric_OBJECTS = \ $(am_test_quota_compliance_https_asymmetric_OBJECTS) test_quota_compliance_https_asymmetric_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_tcp_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_tcp_OBJECTS = \ $(am_test_quota_compliance_tcp_OBJECTS) test_quota_compliance_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_tcp_asymmetric_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_tcp_asymmetric_OBJECTS = \ $(am_test_quota_compliance_tcp_asymmetric_OBJECTS) test_quota_compliance_tcp_asymmetric_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_udp_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_udp_OBJECTS = \ $(am_test_quota_compliance_udp_OBJECTS) test_quota_compliance_udp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_unix_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_unix_OBJECTS = \ $(am_test_quota_compliance_unix_OBJECTS) test_quota_compliance_unix_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_unix_asymmetric_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_unix_asymmetric_OBJECTS = \ $(am_test_quota_compliance_unix_asymmetric_OBJECTS) test_quota_compliance_unix_asymmetric_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_wlan_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_wlan_OBJECTS = \ $(am_test_quota_compliance_wlan_OBJECTS) test_quota_compliance_wlan_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_quota_compliance_wlan_asymmetric_OBJECTS = \ test_quota_compliance.$(OBJEXT) test_quota_compliance_wlan_asymmetric_OBJECTS = \ $(am_test_quota_compliance_wlan_asymmetric_OBJECTS) test_quota_compliance_wlan_asymmetric_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_bidirectional_connect_OBJECTS = \ test_transport_api_bidirectional_connect.$(OBJEXT) test_transport_api_bidirectional_connect_OBJECTS = \ $(am_test_transport_api_bidirectional_connect_OBJECTS) test_transport_api_bidirectional_connect_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_blacklisting_OBJECTS = \ test_transport_api_blacklisting.$(OBJEXT) test_transport_api_blacklisting_OBJECTS = \ $(am_test_transport_api_blacklisting_OBJECTS) test_transport_api_blacklisting_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am__test_transport_api_bluetooth_SOURCES_DIST = test_transport_api.c @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@am_test_transport_api_bluetooth_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_bluetooth_OBJECTS = \ $(am_test_transport_api_bluetooth_OBJECTS) @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@test_transport_api_bluetooth_DEPENDENCIES = $(top_builddir)/src/transport/libgnunettransport.la \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_disconnect_tcp_OBJECTS = \ test_transport_api_disconnect.$(OBJEXT) test_transport_api_disconnect_tcp_OBJECTS = \ $(am_test_transport_api_disconnect_tcp_OBJECTS) test_transport_api_disconnect_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_http_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_http_OBJECTS = \ $(am_test_transport_api_http_OBJECTS) test_transport_api_http_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_http_reverse_OBJECTS = \ test_transport_api.$(OBJEXT) test_transport_api_http_reverse_OBJECTS = \ $(am_test_transport_api_http_reverse_OBJECTS) test_transport_api_http_reverse_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_https_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_https_OBJECTS = \ $(am_test_transport_api_https_OBJECTS) test_transport_api_https_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_limited_sockets_tcp_OBJECTS = \ test_transport_api_limited_sockets.$(OBJEXT) test_transport_api_limited_sockets_tcp_OBJECTS = \ $(am_test_transport_api_limited_sockets_tcp_OBJECTS) test_transport_api_limited_sockets_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_manipulation_cfg_OBJECTS = \ test_transport_api_manipulation_cfg.$(OBJEXT) test_transport_api_manipulation_cfg_OBJECTS = \ $(am_test_transport_api_manipulation_cfg_OBJECTS) test_transport_api_manipulation_cfg_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_manipulation_recv_tcp_OBJECTS = \ test_transport_api_manipulation_recv_tcp.$(OBJEXT) test_transport_api_manipulation_recv_tcp_OBJECTS = \ $(am_test_transport_api_manipulation_recv_tcp_OBJECTS) test_transport_api_manipulation_recv_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_manipulation_send_tcp_OBJECTS = \ test_transport_api_manipulation_send_tcp.$(OBJEXT) test_transport_api_manipulation_send_tcp_OBJECTS = \ $(am_test_transport_api_manipulation_send_tcp_OBJECTS) test_transport_api_manipulation_send_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_monitoring_OBJECTS = \ test_transport_api_monitoring.$(OBJEXT) test_transport_api_monitoring_OBJECTS = \ $(am_test_transport_api_monitoring_OBJECTS) test_transport_api_monitoring_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_monitoring_validation_OBJECTS = \ test_transport_api_monitoring_validation.$(OBJEXT) test_transport_api_monitoring_validation_OBJECTS = \ $(am_test_transport_api_monitoring_validation_OBJECTS) test_transport_api_monitoring_validation_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_multi_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_multi_OBJECTS = \ $(am_test_transport_api_multi_OBJECTS) test_transport_api_multi_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_reliability_bluetooth_OBJECTS = \ test_transport_api_reliability.$(OBJEXT) test_transport_api_reliability_bluetooth_OBJECTS = \ $(am_test_transport_api_reliability_bluetooth_OBJECTS) test_transport_api_reliability_bluetooth_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_reliability_http_OBJECTS = \ test_transport_api_reliability.$(OBJEXT) test_transport_api_reliability_http_OBJECTS = \ $(am_test_transport_api_reliability_http_OBJECTS) test_transport_api_reliability_http_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_reliability_https_OBJECTS = \ test_transport_api_reliability.$(OBJEXT) test_transport_api_reliability_https_OBJECTS = \ $(am_test_transport_api_reliability_https_OBJECTS) test_transport_api_reliability_https_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_reliability_tcp_OBJECTS = \ test_transport_api_reliability.$(OBJEXT) test_transport_api_reliability_tcp_OBJECTS = \ $(am_test_transport_api_reliability_tcp_OBJECTS) test_transport_api_reliability_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_reliability_tcp_nat_OBJECTS = \ test_transport_api_reliability.$(OBJEXT) test_transport_api_reliability_tcp_nat_OBJECTS = \ $(am_test_transport_api_reliability_tcp_nat_OBJECTS) test_transport_api_reliability_tcp_nat_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_reliability_wlan_OBJECTS = \ test_transport_api_reliability.$(OBJEXT) test_transport_api_reliability_wlan_OBJECTS = \ $(am_test_transport_api_reliability_wlan_OBJECTS) test_transport_api_reliability_wlan_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_restart_1peer_OBJECTS = \ test_transport_api_restart_1peer.$(OBJEXT) test_transport_api_restart_1peer_OBJECTS = \ $(am_test_transport_api_restart_1peer_OBJECTS) test_transport_api_restart_1peer_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_restart_2peers_OBJECTS = \ test_transport_api_restart_2peers.$(OBJEXT) test_transport_api_restart_2peers_OBJECTS = \ $(am_test_transport_api_restart_2peers_OBJECTS) test_transport_api_restart_2peers_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_tcp_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_tcp_OBJECTS = $(am_test_transport_api_tcp_OBJECTS) test_transport_api_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_tcp_nat_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_tcp_nat_OBJECTS = \ $(am_test_transport_api_tcp_nat_OBJECTS) test_transport_api_tcp_nat_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_timeout_bluetooth_OBJECTS = \ test_transport_api_timeout.$(OBJEXT) test_transport_api_timeout_bluetooth_OBJECTS = \ $(am_test_transport_api_timeout_bluetooth_OBJECTS) test_transport_api_timeout_bluetooth_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_timeout_http_OBJECTS = \ test_transport_api_timeout.$(OBJEXT) test_transport_api_timeout_http_OBJECTS = \ $(am_test_transport_api_timeout_http_OBJECTS) test_transport_api_timeout_http_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_timeout_https_OBJECTS = \ test_transport_api_timeout.$(OBJEXT) test_transport_api_timeout_https_OBJECTS = \ $(am_test_transport_api_timeout_https_OBJECTS) test_transport_api_timeout_https_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_timeout_tcp_OBJECTS = \ test_transport_api_timeout.$(OBJEXT) test_transport_api_timeout_tcp_OBJECTS = \ $(am_test_transport_api_timeout_tcp_OBJECTS) test_transport_api_timeout_tcp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_timeout_udp_OBJECTS = \ test_transport_api_timeout.$(OBJEXT) test_transport_api_timeout_udp_OBJECTS = \ $(am_test_transport_api_timeout_udp_OBJECTS) test_transport_api_timeout_udp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_timeout_unix_OBJECTS = \ test_transport_api_timeout.$(OBJEXT) test_transport_api_timeout_unix_OBJECTS = \ $(am_test_transport_api_timeout_unix_OBJECTS) test_transport_api_timeout_unix_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_timeout_wlan_OBJECTS = \ test_transport_api_timeout.$(OBJEXT) test_transport_api_timeout_wlan_OBJECTS = \ $(am_test_transport_api_timeout_wlan_OBJECTS) test_transport_api_timeout_wlan_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_udp_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_udp_OBJECTS = $(am_test_transport_api_udp_OBJECTS) test_transport_api_udp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_udp_nat_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_udp_nat_OBJECTS = \ $(am_test_transport_api_udp_nat_OBJECTS) test_transport_api_udp_nat_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_unix_OBJECTS = test_transport_api.$(OBJEXT) test_transport_api_unix_OBJECTS = \ $(am_test_transport_api_unix_OBJECTS) test_transport_api_unix_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_unix_abstract_OBJECTS = \ test_transport_api.$(OBJEXT) test_transport_api_unix_abstract_OBJECTS = \ $(am_test_transport_api_unix_abstract_OBJECTS) test_transport_api_unix_abstract_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_unreliability_bluetooth_OBJECTS = \ test_transport_api_unreliability.$(OBJEXT) test_transport_api_unreliability_bluetooth_OBJECTS = \ $(am_test_transport_api_unreliability_bluetooth_OBJECTS) test_transport_api_unreliability_bluetooth_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_unreliability_constant_udp_OBJECTS = \ test_transport_api_unreliability_constant.$(OBJEXT) test_transport_api_unreliability_constant_udp_OBJECTS = \ $(am_test_transport_api_unreliability_constant_udp_OBJECTS) test_transport_api_unreliability_constant_udp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_unreliability_udp_OBJECTS = \ test_transport_api_unreliability.$(OBJEXT) test_transport_api_unreliability_udp_OBJECTS = \ $(am_test_transport_api_unreliability_udp_OBJECTS) test_transport_api_unreliability_udp_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_unreliability_unix_OBJECTS = \ test_transport_api_unreliability.$(OBJEXT) test_transport_api_unreliability_unix_OBJECTS = \ $(am_test_transport_api_unreliability_unix_OBJECTS) test_transport_api_unreliability_unix_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_api_unreliability_wlan_OBJECTS = \ test_transport_api_unreliability.$(OBJEXT) test_transport_api_unreliability_wlan_OBJECTS = \ $(am_test_transport_api_unreliability_wlan_OBJECTS) test_transport_api_unreliability_wlan_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am__test_transport_api_wlan_SOURCES_DIST = test_transport_api.c @LINUX_TRUE@am_test_transport_api_wlan_OBJECTS = \ @LINUX_TRUE@ test_transport_api.$(OBJEXT) test_transport_api_wlan_OBJECTS = \ $(am_test_transport_api_wlan_OBJECTS) @LINUX_TRUE@test_transport_api_wlan_DEPENDENCIES = $(top_builddir)/src/transport/libgnunettransport.la \ @LINUX_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @LINUX_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @LINUX_TRUE@ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_blacklisting_inbound_bl_full_OBJECTS = \ test_transport_blacklisting.$(OBJEXT) test_transport_blacklisting_inbound_bl_full_OBJECTS = \ $(am_test_transport_blacklisting_inbound_bl_full_OBJECTS) test_transport_blacklisting_inbound_bl_full_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_blacklisting_inbound_bl_plugin_OBJECTS = \ test_transport_blacklisting.$(OBJEXT) test_transport_blacklisting_inbound_bl_plugin_OBJECTS = \ $(am_test_transport_blacklisting_inbound_bl_plugin_OBJECTS) test_transport_blacklisting_inbound_bl_plugin_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_blacklisting_multiple_plugins_OBJECTS = \ test_transport_blacklisting.$(OBJEXT) test_transport_blacklisting_multiple_plugins_OBJECTS = \ $(am_test_transport_blacklisting_multiple_plugins_OBJECTS) test_transport_blacklisting_multiple_plugins_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_blacklisting_no_bl_OBJECTS = \ test_transport_blacklisting.$(OBJEXT) test_transport_blacklisting_no_bl_OBJECTS = \ $(am_test_transport_blacklisting_no_bl_OBJECTS) test_transport_blacklisting_no_bl_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_blacklisting_outbound_bl_full_OBJECTS = \ test_transport_blacklisting.$(OBJEXT) test_transport_blacklisting_outbound_bl_full_OBJECTS = \ $(am_test_transport_blacklisting_outbound_bl_full_OBJECTS) test_transport_blacklisting_outbound_bl_full_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_blacklisting_outbound_bl_plugin_OBJECTS = \ test_transport_blacklisting.$(OBJEXT) test_transport_blacklisting_outbound_bl_plugin_OBJECTS = \ $(am_test_transport_blacklisting_outbound_bl_plugin_OBJECTS) test_transport_blacklisting_outbound_bl_plugin_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_startonly_OBJECTS = \ test_transport_startonly.$(OBJEXT) test_transport_startonly_OBJECTS = \ $(am_test_transport_startonly_OBJECTS) test_transport_startonly_DEPENDENCIES = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_testing_OBJECTS = test_transport_testing.$(OBJEXT) test_transport_testing_OBJECTS = $(am_test_transport_testing_OBJECTS) test_transport_testing_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_testing_restart_OBJECTS = \ test_transport_testing_restart.$(OBJEXT) test_transport_testing_restart_OBJECTS = \ $(am_test_transport_testing_restart_OBJECTS) test_transport_testing_restart_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la am_test_transport_testing_startstop_OBJECTS = \ test_transport_testing_startstop.$(OBJEXT) test_transport_testing_startstop_OBJECTS = \ $(am_test_transport_testing_startstop_OBJECTS) test_transport_testing_startstop_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_transport_bluetooth_la_SOURCES) \ $(libgnunet_plugin_transport_http_client_la_SOURCES) \ $(libgnunet_plugin_transport_http_server_la_SOURCES) \ $(libgnunet_plugin_transport_https_client_la_SOURCES) \ $(libgnunet_plugin_transport_https_server_la_SOURCES) \ $(libgnunet_plugin_transport_tcp_la_SOURCES) \ $(libgnunet_plugin_transport_template_la_SOURCES) \ $(libgnunet_plugin_transport_udp_la_SOURCES) \ $(libgnunet_plugin_transport_unix_la_SOURCES) \ $(libgnunet_plugin_transport_wlan_la_SOURCES) \ $(libgnunettransport_la_SOURCES) \ $(libgnunettransporttesting_la_SOURCES) \ $(gnunet_helper_transport_bluetooth_SOURCES) \ $(gnunet_helper_transport_wlan_SOURCES) \ $(gnunet_helper_transport_wlan_dummy_SOURCES) \ $(gnunet_service_transport_SOURCES) \ $(gnunet_transport_SOURCES) \ $(gnunet_transport_certificate_creation_SOURCES) \ $(gnunet_transport_wlan_receiver_SOURCES) \ $(gnunet_transport_wlan_sender_SOURCES) \ $(test_http_common_SOURCES) $(test_plugin_bluetooth_SOURCES) \ $(test_plugin_http_client_SOURCES) \ $(test_plugin_http_server_SOURCES) \ $(test_plugin_https_client_SOURCES) \ $(test_plugin_https_server_SOURCES) $(test_plugin_tcp_SOURCES) \ $(test_plugin_udp_SOURCES) $(test_plugin_unix_SOURCES) \ $(test_plugin_wlan_SOURCES) \ $(test_quota_compliance_bluetooth_SOURCES) \ $(test_quota_compliance_bluetooth_asymmetric_SOURCES) \ $(test_quota_compliance_http_SOURCES) \ $(test_quota_compliance_http_asymmetric_SOURCES) \ $(test_quota_compliance_https_SOURCES) \ $(test_quota_compliance_https_asymmetric_SOURCES) \ $(test_quota_compliance_tcp_SOURCES) \ $(test_quota_compliance_tcp_asymmetric_SOURCES) \ $(test_quota_compliance_udp_SOURCES) \ $(test_quota_compliance_unix_SOURCES) \ $(test_quota_compliance_unix_asymmetric_SOURCES) \ $(test_quota_compliance_wlan_SOURCES) \ $(test_quota_compliance_wlan_asymmetric_SOURCES) \ $(test_transport_api_bidirectional_connect_SOURCES) \ $(test_transport_api_blacklisting_SOURCES) \ $(test_transport_api_bluetooth_SOURCES) \ $(test_transport_api_disconnect_tcp_SOURCES) \ $(test_transport_api_http_SOURCES) \ $(test_transport_api_http_reverse_SOURCES) \ $(test_transport_api_https_SOURCES) \ $(test_transport_api_limited_sockets_tcp_SOURCES) \ $(test_transport_api_manipulation_cfg_SOURCES) \ $(test_transport_api_manipulation_recv_tcp_SOURCES) \ $(test_transport_api_manipulation_send_tcp_SOURCES) \ $(test_transport_api_monitoring_SOURCES) \ $(test_transport_api_monitoring_validation_SOURCES) \ $(test_transport_api_multi_SOURCES) \ $(test_transport_api_reliability_bluetooth_SOURCES) \ $(test_transport_api_reliability_http_SOURCES) \ $(test_transport_api_reliability_https_SOURCES) \ $(test_transport_api_reliability_tcp_SOURCES) \ $(test_transport_api_reliability_tcp_nat_SOURCES) \ $(test_transport_api_reliability_wlan_SOURCES) \ $(test_transport_api_restart_1peer_SOURCES) \ $(test_transport_api_restart_2peers_SOURCES) \ $(test_transport_api_tcp_SOURCES) \ $(test_transport_api_tcp_nat_SOURCES) \ $(test_transport_api_timeout_bluetooth_SOURCES) \ $(test_transport_api_timeout_http_SOURCES) \ $(test_transport_api_timeout_https_SOURCES) \ $(test_transport_api_timeout_tcp_SOURCES) \ $(test_transport_api_timeout_udp_SOURCES) \ $(test_transport_api_timeout_unix_SOURCES) \ $(test_transport_api_timeout_wlan_SOURCES) \ $(test_transport_api_udp_SOURCES) \ $(test_transport_api_udp_nat_SOURCES) \ $(test_transport_api_unix_SOURCES) \ $(test_transport_api_unix_abstract_SOURCES) \ $(test_transport_api_unreliability_bluetooth_SOURCES) \ $(test_transport_api_unreliability_constant_udp_SOURCES) \ $(test_transport_api_unreliability_udp_SOURCES) \ $(test_transport_api_unreliability_unix_SOURCES) \ $(test_transport_api_unreliability_wlan_SOURCES) \ $(test_transport_api_wlan_SOURCES) \ $(test_transport_blacklisting_inbound_bl_full_SOURCES) \ $(test_transport_blacklisting_inbound_bl_plugin_SOURCES) \ $(test_transport_blacklisting_multiple_plugins_SOURCES) \ $(test_transport_blacklisting_no_bl_SOURCES) \ $(test_transport_blacklisting_outbound_bl_full_SOURCES) \ $(test_transport_blacklisting_outbound_bl_plugin_SOURCES) \ $(test_transport_startonly_SOURCES) \ $(test_transport_testing_SOURCES) \ $(test_transport_testing_restart_SOURCES) \ $(test_transport_testing_startstop_SOURCES) DIST_SOURCES = $(libgnunet_plugin_transport_bluetooth_la_SOURCES) \ $(libgnunet_plugin_transport_http_client_la_SOURCES) \ $(libgnunet_plugin_transport_http_server_la_SOURCES) \ $(libgnunet_plugin_transport_https_client_la_SOURCES) \ $(libgnunet_plugin_transport_https_server_la_SOURCES) \ $(libgnunet_plugin_transport_tcp_la_SOURCES) \ $(libgnunet_plugin_transport_template_la_SOURCES) \ $(libgnunet_plugin_transport_udp_la_SOURCES) \ $(libgnunet_plugin_transport_unix_la_SOURCES) \ $(libgnunet_plugin_transport_wlan_la_SOURCES) \ $(libgnunettransport_la_SOURCES) \ $(libgnunettransporttesting_la_SOURCES) \ $(gnunet_helper_transport_bluetooth_SOURCES) \ $(gnunet_helper_transport_wlan_SOURCES) \ $(gnunet_helper_transport_wlan_dummy_SOURCES) \ $(gnunet_service_transport_SOURCES) \ $(gnunet_transport_SOURCES) \ $(gnunet_transport_certificate_creation_SOURCES) \ $(gnunet_transport_wlan_receiver_SOURCES) \ $(gnunet_transport_wlan_sender_SOURCES) \ $(test_http_common_SOURCES) $(test_plugin_bluetooth_SOURCES) \ $(test_plugin_http_client_SOURCES) \ $(test_plugin_http_server_SOURCES) \ $(test_plugin_https_client_SOURCES) \ $(test_plugin_https_server_SOURCES) $(test_plugin_tcp_SOURCES) \ $(test_plugin_udp_SOURCES) $(test_plugin_unix_SOURCES) \ $(test_plugin_wlan_SOURCES) \ $(test_quota_compliance_bluetooth_SOURCES) \ $(test_quota_compliance_bluetooth_asymmetric_SOURCES) \ $(test_quota_compliance_http_SOURCES) \ $(test_quota_compliance_http_asymmetric_SOURCES) \ $(test_quota_compliance_https_SOURCES) \ $(test_quota_compliance_https_asymmetric_SOURCES) \ $(test_quota_compliance_tcp_SOURCES) \ $(test_quota_compliance_tcp_asymmetric_SOURCES) \ $(test_quota_compliance_udp_SOURCES) \ $(test_quota_compliance_unix_SOURCES) \ $(test_quota_compliance_unix_asymmetric_SOURCES) \ $(test_quota_compliance_wlan_SOURCES) \ $(test_quota_compliance_wlan_asymmetric_SOURCES) \ $(test_transport_api_bidirectional_connect_SOURCES) \ $(test_transport_api_blacklisting_SOURCES) \ $(am__test_transport_api_bluetooth_SOURCES_DIST) \ $(test_transport_api_disconnect_tcp_SOURCES) \ $(test_transport_api_http_SOURCES) \ $(test_transport_api_http_reverse_SOURCES) \ $(test_transport_api_https_SOURCES) \ $(test_transport_api_limited_sockets_tcp_SOURCES) \ $(test_transport_api_manipulation_cfg_SOURCES) \ $(test_transport_api_manipulation_recv_tcp_SOURCES) \ $(test_transport_api_manipulation_send_tcp_SOURCES) \ $(test_transport_api_monitoring_SOURCES) \ $(test_transport_api_monitoring_validation_SOURCES) \ $(test_transport_api_multi_SOURCES) \ $(test_transport_api_reliability_bluetooth_SOURCES) \ $(test_transport_api_reliability_http_SOURCES) \ $(test_transport_api_reliability_https_SOURCES) \ $(test_transport_api_reliability_tcp_SOURCES) \ $(test_transport_api_reliability_tcp_nat_SOURCES) \ $(test_transport_api_reliability_wlan_SOURCES) \ $(test_transport_api_restart_1peer_SOURCES) \ $(test_transport_api_restart_2peers_SOURCES) \ $(test_transport_api_tcp_SOURCES) \ $(test_transport_api_tcp_nat_SOURCES) \ $(test_transport_api_timeout_bluetooth_SOURCES) \ $(test_transport_api_timeout_http_SOURCES) \ $(test_transport_api_timeout_https_SOURCES) \ $(test_transport_api_timeout_tcp_SOURCES) \ $(test_transport_api_timeout_udp_SOURCES) \ $(test_transport_api_timeout_unix_SOURCES) \ $(test_transport_api_timeout_wlan_SOURCES) \ $(test_transport_api_udp_SOURCES) \ $(test_transport_api_udp_nat_SOURCES) \ $(test_transport_api_unix_SOURCES) \ $(test_transport_api_unix_abstract_SOURCES) \ $(test_transport_api_unreliability_bluetooth_SOURCES) \ $(test_transport_api_unreliability_constant_udp_SOURCES) \ $(test_transport_api_unreliability_udp_SOURCES) \ $(test_transport_api_unreliability_unix_SOURCES) \ $(test_transport_api_unreliability_wlan_SOURCES) \ $(am__test_transport_api_wlan_SOURCES_DIST) \ $(test_transport_blacklisting_inbound_bl_full_SOURCES) \ $(test_transport_blacklisting_inbound_bl_plugin_SOURCES) \ $(test_transport_blacklisting_multiple_plugins_SOURCES) \ $(test_transport_blacklisting_no_bl_SOURCES) \ $(test_transport_blacklisting_outbound_bl_full_SOURCES) \ $(test_transport_blacklisting_outbound_bl_plugin_SOURCES) \ $(test_transport_startonly_SOURCES) \ $(test_transport_testing_SOURCES) \ $(test_transport_testing_restart_SOURCES) \ $(test_transport_testing_startstop_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ transport.conf @HAVE_MHD_TRUE@GN_LIBMHD = -lmicrohttpd @HAVE_MHD_TRUE@HTTP_SERVER_PLUGIN_LA = libgnunet_plugin_transport_http_server.la @HAVE_MHD_TRUE@HTTPS_SERVER_PLUGIN_LA = libgnunet_plugin_transport_https_server.la @HAVE_MHD_TRUE@HTTP_SERVER_PLUGIN_TEST = test_plugin_http_server @HAVE_MHD_TRUE@HTTPS_SERVER_PLUGIN_TEST = test_plugin_https_server @HAVE_LIBGNURL_TRUE@HTTP_CLIENT_PLUGIN_TEST = test_plugin_http_client @HAVE_LIBGNURL_TRUE@HTTPS_CLIENT_PLUGIN_TEST = test_plugin_https_client @HAVE_LIBGNURL_TRUE@HTTP_CLIENT_PLUGIN_LA = libgnunet_plugin_transport_http_client.la @HAVE_LIBGNURL_TRUE@HTTPS_CLIENT_PLUGIN_LA = libgnunet_plugin_transport_https_client.la @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTP_API_TEST = test_transport_api_http @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTP_REVERSE_API_TEST = test_transport_api_http_reverse @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTP_API_TIMEOUT_TEST = test_transport_api_timeout_http @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTP_REL_TEST = test_transport_api_reliability_http @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTP_QUOTA_TEST = test_quota_compliance_http \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@ test_quota_compliance_http_asymmetric @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTPS_API_TEST = test_transport_api_https @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTPS_API_TIMEOUT_TEST = test_transport_api_timeout_https @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTPS_REL_TEST = test_transport_api_reliability_https @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@HTTPS_QUOTA_TEST = test_quota_compliance_https \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@ test_quota_compliance_https_asymmetric @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @LINUX_TRUE@WLAN_BIN = gnunet-helper-transport-wlan @LINUX_TRUE@WLAN_BIN_DUMMY = gnunet-helper-transport-wlan-dummy @LINUX_TRUE@WLAN_BIN_SENDER = gnunet-transport-wlan-sender @LINUX_TRUE@WLAN_BIN_RECEIVER = gnunet-transport-wlan-receiver @LINUX_TRUE@WLAN_PLUGIN_LA = libgnunet_plugin_transport_wlan.la @LINUX_TRUE@WLAN_PLUGIN_TEST = test_plugin_wlan @LINUX_TRUE@WLAN_API_TEST = test_transport_api_wlan @LINUX_TRUE@WLAN_TIMEOUT_TEST = test_transport_api_timeout_wlan @LINUX_TRUE@WLAN_REL_TEST = test_transport_api_reliability_wlan @LINUX_TRUE@WLAN_UREL_TEST = test_transport_api_unreliability_wlan @LINUX_TRUE@WLAN_QUOTA_TEST = test_quota_compliance_wlan \ @LINUX_TRUE@ test_quota_compliance_wlan_asymmetric @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@BT_BIN = gnunet-helper-transport-bluetooth @LINUX_FALSE@@MINGW_TRUE@BT_BIN = gnunet-helper-transport-bluetooth @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@BT_PLUGIN_LA = libgnunet_plugin_transport_bluetooth.la @LINUX_FALSE@@MINGW_TRUE@BT_PLUGIN_LA = libgnunet_plugin_transport_bluetooth.la @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@BT_PLUGIN_TEST = test_plugin_bluetooth @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@BT_API_TEST = test_transport_api_bluetooth @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@BT_TIMEOUT_TEST = test_transport_api_timeout_bluetooth @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@BT_REL_TEST = test_transport_api_reliability_bluetooth @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@BT_UREL_TEST = test_transport_api_unreliability_bluetooth @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@BT_QUOTA_TEST = test_quota_compliance_bluetooth \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ test_quota_compliance_bluetooth_asymmetric @MINGW_FALSE@UNIX_PLUGIN_LA = libgnunet_plugin_transport_unix.la @MINGW_FALSE@UNIX_PLUGIN_TEST = test_transport_api_unix @MINGW_FALSE@UNIX_TEST = test_plugin_unix @MINGW_FALSE@UNIX_PLUGIN_TIMEOUT_TEST = test_transport_api_timeout_unix @MINGW_FALSE@UNIX_REL_TEST = test_transport_api_unreliability_unix @MINGW_FALSE@UNIX_QUOTA_TEST = test_quota_compliance_unix \ @MINGW_FALSE@ test_quota_compliance_unix_asymmetric @LINUX_TRUE@@MINGW_FALSE@UNIX_API_ABSTRACT_TEST = test_transport_api_unix_abstract @HAVE_TESTING_TRUE@TESTING_LIBS = libgnunettransporttesting.la lib_LTLIBRARIES = \ libgnunettransport.la \ $(TESTING_LIBS) libgnunettransporttesting_la_SOURCES = \ transport-testing.c transport-testing.h libgnunettransporttesting_la_LIBADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(GN_LIBINTL) libgnunettransporttesting_la_DEPENDENCIES = \ libgnunettransport.la libgnunettransporttesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) libgnunettransport_la_SOURCES = \ transport_api.c transport.h \ transport_api_blacklist.c \ transport_api_address_to_string.c \ transport_api_monitoring.c libgnunettransport_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunettransport_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 4:0:2 #bin_SCRIPTS = \ # gnunet-transport-certificate-creation gnunet_transport_certificate_creation_SOURCES = \ gnunet-transport-certificate-creation.c gnunet_transport_certificate_creation_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_helper_transport_wlan_SOURCES = \ gnunet-helper-transport-wlan.c gnunet_helper_transport_wlan_dummy_SOURCES = \ gnunet-helper-transport-wlan-dummy.c gnunet_helper_transport_wlan_dummy_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_transport_wlan_sender_SOURCES = \ gnunet-transport-wlan-sender.c gnunet_transport_wlan_sender_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_transport_wlan_receiver_SOURCES = \ gnunet-transport-wlan-receiver.c gnunet_transport_wlan_receiver_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_helper_transport_bluetooth_SOURCES = \ gnunet-helper-transport-bluetooth.c @MINGW_TRUE@gnunet_helper_transport_bluetooth_LDADD = \ @MINGW_TRUE@ $(top_builddir)/src/util/libgnunetutil.la @MINGW_FALSE@gnunet_helper_transport_bluetooth_LDFLAGS = -lbluetooth @MINGW_TRUE@gnunet_helper_transport_bluetooth_LDFLAGS = -lws2_32 gnunet_transport_SOURCES = \ gnunet-transport.c gnunet_transport_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_transport_DEPENDENCIES = \ libgnunettransport.la gnunet_service_transport_SOURCES = \ gnunet-service-transport.c gnunet-service-transport.h \ gnunet-service-transport_blacklist.h gnunet-service-transport_blacklist.c \ gnunet-service-transport_clients.h gnunet-service-transport_clients.c \ gnunet-service-transport_hello.h gnunet-service-transport_hello.c \ gnunet-service-transport_neighbours.h gnunet-service-transport_neighbours.c \ gnunet-service-transport_plugins.h gnunet-service-transport_plugins.c \ gnunet-service-transport_validation.h gnunet-service-transport_validation.c \ gnunet-service-transport_manipulation.h gnunet-service-transport_manipulation.c # Note that while gnunet-service-transport does not use libgnunetnat # directly, we must link against it as GNUNET_NAT_mini_map_stop will # leave a 'dangling' task to process_unmap_output which will cause # a crash on unloading of a plugin unless the service links against # that library as well. gnunet_service_transport_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_GLPK) \ $(GN_LIBINTL) gnunet_service_transport_DEPENDENCIES = \ libgnunettransport.la gnunet_service_transport_CFLAGS = \ $(CFLAGS) # -DANALYZE plugin_LTLIBRARIES = \ libgnunet_plugin_transport_tcp.la \ libgnunet_plugin_transport_udp.la \ $(UNIX_PLUGIN_LA) \ $(HTTP_CLIENT_PLUGIN_LA) \ $(HTTPS_CLIENT_PLUGIN_LA) \ $(HTTP_SERVER_PLUGIN_LA) \ $(HTTPS_SERVER_PLUGIN_LA) \ $(WLAN_PLUGIN_LA) \ $(BT_PLUGIN_LA) \ libgnunet_plugin_transport_template.la libgnunet_plugin_transport_tcp_la_SOURCES = \ plugin_transport_tcp.c libgnunet_plugin_transport_tcp_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_transport_tcp_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_template_la_SOURCES = \ plugin_transport_template.c libgnunet_plugin_transport_template_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_transport_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_wlan_la_SOURCES = \ plugin_transport_wlan.c plugin_transport_wlan.h libgnunet_plugin_transport_wlan_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_wlan_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_bluetooth_la_SOURCES = \ plugin_transport_bluetooth.c plugin_transport_wlan.h libgnunet_plugin_transport_bluetooth_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_bluetooth_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_udp_la_SOURCES = \ plugin_transport_udp.c plugin_transport_udp.h \ plugin_transport_udp_broadcasting.c libgnunet_plugin_transport_udp_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_transport_udp_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_unix_la_SOURCES = \ plugin_transport_unix.c libgnunet_plugin_transport_unix_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_transport_unix_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_http_client_la_SOURCES = \ plugin_transport_http_client.c plugin_transport_http_common.c plugin_transport_http_common.h libgnunet_plugin_transport_http_client_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ @LIBGNURL@ \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_http_client_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_http_client_la_CFLAGS = \ $(CFLAGS) libgnunet_plugin_transport_http_client_la_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) libgnunet_plugin_transport_http_server_la_SOURCES = \ plugin_transport_http_server.c plugin_transport_http_common.c libgnunet_plugin_transport_http_server_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_http_server_la_LDFLAGS = \ $(GN_LIBMHD) \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_http_server_la_CFLAGS = \ $(CFLAGS) libgnunet_plugin_transport_https_client_la_SOURCES = \ plugin_transport_http_client.c plugin_transport_http_common.c libgnunet_plugin_transport_https_client_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ @LIBGNURL@ \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_https_client_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_https_client_la_CFLAGS = \ $(CFLAGS) -DBUILD_HTTPS libgnunet_plugin_transport_https_client_la_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) libgnunet_plugin_transport_https_server_la_SOURCES = \ plugin_transport_http_server.c plugin_transport_http_common.c libgnunet_plugin_transport_https_server_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_https_server_la_LDFLAGS = \ $(GN_LIBMHD) \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_https_server_la_CFLAGS = \ $(CFLAGS) -DBUILD_HTTPS @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; test_transport_testing_startstop_SOURCES = \ test_transport_testing_startstop.c test_transport_testing_startstop_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_testing_restart_SOURCES = \ test_transport_testing_restart.c test_transport_testing_restart_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_testing_SOURCES = \ test_transport_testing.c test_transport_testing_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_blacklisting_SOURCES = \ test_transport_api_blacklisting.c test_transport_api_blacklisting_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_no_bl_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_no_bl_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_outbound_bl_full_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_outbound_bl_full_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_outbound_bl_plugin_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_outbound_bl_plugin_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_inbound_bl_full_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_inbound_bl_full_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_inbound_bl_plugin_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_inbound_bl_plugin_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_multiple_plugins_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_multiple_plugins_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_disconnect_tcp_SOURCES = \ test_transport_api_disconnect.c test_transport_api_disconnect_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_startonly_SOURCES = \ test_transport_startonly.c test_transport_startonly_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_tcp_SOURCES = \ test_plugin_transport.c test_plugin_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_udp_SOURCES = \ test_plugin_transport.c test_plugin_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_unix_SOURCES = \ test_plugin_transport.c test_plugin_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_wlan_SOURCES = \ test_plugin_transport.c test_plugin_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_bluetooth_SOURCES = \ test_plugin_transport.c test_plugin_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_http_common_SOURCES = \ test_http_common.c plugin_transport_http_common.c test_http_common_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_http_server_SOURCES = \ test_plugin_transport.c test_plugin_http_server_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_https_server_SOURCES = \ test_plugin_transport.c test_plugin_https_server_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_http_client_SOURCES = \ test_plugin_transport.c test_plugin_http_client_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_https_client_SOURCES = \ test_plugin_transport.c test_plugin_https_client_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_tcp_SOURCES = \ test_transport_api.c test_transport_api_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_bidirectional_connect_SOURCES = \ test_transport_api_bidirectional_connect.c test_transport_api_bidirectional_connect_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_restart_1peer_SOURCES = \ test_transport_api_restart_1peer.c test_transport_api_restart_1peer_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_restart_2peers_SOURCES = \ test_transport_api_restart_2peers.c test_transport_api_restart_2peers_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_limited_sockets_tcp_SOURCES = \ test_transport_api_limited_sockets.c test_transport_api_limited_sockets_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_tcp_nat_SOURCES = \ test_transport_api.c test_transport_api_tcp_nat_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_manipulation_send_tcp_SOURCES = \ test_transport_api_manipulation_send_tcp.c test_transport_api_manipulation_send_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_manipulation_recv_tcp_SOURCES = \ test_transport_api_manipulation_recv_tcp.c test_transport_api_manipulation_recv_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_manipulation_cfg_SOURCES = \ test_transport_api_manipulation_cfg.c test_transport_api_manipulation_cfg_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_tcp_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_tcp_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_unix_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_wlan_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_bluetooth_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_tcp_nat_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_tcp_nat_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_wlan_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_bluetooth_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_wlan_SOURCES = \ test_transport_api_unreliability.c test_transport_api_unreliability_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_bluetooth_SOURCES = \ test_transport_api_unreliability.c test_transport_api_unreliability_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_udp_SOURCES = \ test_transport_api.c test_transport_api_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_udp_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_udp_nat_SOURCES = \ test_transport_api.c test_transport_api_udp_nat_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unix_SOURCES = \ test_transport_api.c test_transport_api_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unix_abstract_SOURCES = \ test_transport_api.c test_transport_api_unix_abstract_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la # HTTP tests test_transport_api_http_SOURCES = \ test_transport_api.c test_transport_api_http_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_http_reverse_SOURCES = \ test_transport_api.c test_transport_api_http_reverse_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_http_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_http_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_http_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_http_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_http_SOURCES = \ test_quota_compliance.c test_quota_compliance_http_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_http_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_http_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_https_SOURCES = \ test_quota_compliance.c test_quota_compliance_https_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_https_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_https_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la # HTTPS tests test_transport_api_https_SOURCES = \ test_transport_api.c test_transport_api_https_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_https_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_https_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_https_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_https_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_unix_SOURCES = \ test_transport_api_unreliability.c test_transport_api_unreliability_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_udp_SOURCES = \ test_transport_api_unreliability.c test_transport_api_unreliability_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_constant_udp_SOURCES = \ test_transport_api_unreliability_constant.c test_transport_api_unreliability_constant_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la @LINUX_TRUE@test_transport_api_wlan_SOURCES = \ @LINUX_TRUE@ test_transport_api.c @LINUX_TRUE@test_transport_api_wlan_LDADD = \ @LINUX_TRUE@ $(top_builddir)/src/transport/libgnunettransport.la \ @LINUX_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @LINUX_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @LINUX_TRUE@ $(top_builddir)/src/transport/libgnunettransporttesting.la @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@test_transport_api_bluetooth_SOURCES = \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ test_transport_api.c @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@test_transport_api_bluetooth_LDADD = \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ $(top_builddir)/src/transport/libgnunettransport.la \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ $(top_builddir)/src/hello/libgnunethello.la \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ $(top_builddir)/src/util/libgnunetutil.la \ @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_tcp_SOURCES = \ test_quota_compliance.c test_quota_compliance_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_tcp_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_tcp_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_udp_SOURCES = \ test_quota_compliance.c test_quota_compliance_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_unix_SOURCES = \ test_quota_compliance.c test_quota_compliance_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_unix_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_unix_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_wlan_SOURCES = \ test_quota_compliance.c test_quota_compliance_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_wlan_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_wlan_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_bluetooth_SOURCES = \ test_quota_compliance.c test_quota_compliance_bluetooth_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_bluetooth_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_bluetooth_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_multi_SOURCES = \ test_transport_api.c test_transport_api_multi_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_monitoring_SOURCES = \ test_transport_api_monitoring.c test_transport_api_monitoring_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_monitoring_validation_SOURCES = \ test_transport_api_monitoring_validation.c test_transport_api_monitoring_validation_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la EXTRA_DIST = \ test_plugin_hostkey \ test_plugin_hostkey.ecc \ template_cfg_peer1.conf\ template_cfg_peer2.conf\ test_plugin_transport_data.conf\ test_plugin_transport_data_udp.conf\ test_quota_compliance_data.conf\ test_quota_compliance_http_peer1.conf\ test_quota_compliance_http_peer2.conf\ test_quota_compliance_https_peer1.conf\ test_quota_compliance_https_peer2.conf\ test_quota_compliance_tcp_peer1.conf\ test_quota_compliance_tcp_peer2.conf\ test_quota_compliance_udp_peer1.conf\ test_quota_compliance_udp_peer2.conf\ test_quota_compliance_unix_peer1.conf\ test_quota_compliance_unix_peer2.conf\ test_quota_compliance_wlan_peer1.conf\ test_quota_compliance_wlan_peer2.conf\ test_quota_compliance_bluetooth_peer1.conf\ test_quota_compliance_bluetooth_peer2.conf\ test_quota_compliance_http_asymmetric_peer1.conf\ test_quota_compliance_http_asymmetric_peer2.conf\ test_quota_compliance_https_asymmetric_peer1.conf\ test_quota_compliance_https_asymmetric_peer2.conf\ test_quota_compliance_tcp_asymmetric_peer1.conf\ test_quota_compliance_tcp_asymmetric_peer2.conf\ test_quota_compliance_unix_asymmetric_peer1.conf\ test_quota_compliance_unix_asymmetric_peer2.conf\ test_quota_compliance_wlan_asymmetric_peer1.conf\ test_quota_compliance_wlan_asymmetric_peer2.conf\ test_quota_compliance_bluetooth_asymmetric_peer1.conf\ test_quota_compliance_bluetooth_asymmetric_peer2.conf\ test_transport_api_data.conf\ test_transport_api_http_peer1.conf\ test_transport_api_http_peer2.conf\ test_transport_api_https_peer1.conf\ test_transport_api_https_peer2.conf\ test_transport_api_limited_sockets_tcp_peer1.conf\ test_transport_api_limited_sockets_tcp_peer2.conf\ test_transport_api_timeout_tcp_peer1.conf\ test_transport_api_timeout_tcp_peer2.conf\ test_transport_api_multi_peer1.conf\ test_transport_api_multi_peer2.conf\ test_transport_api_reliability_http_peer1.conf\ test_transport_api_reliability_http_peer2.conf\ test_transport_api_reliability_https_peer1.conf\ test_transport_api_reliability_https_peer2.conf\ test_transport_api_reliability_tcp_nat_peer1.conf\ test_transport_api_reliability_tcp_nat_peer2.conf\ test_transport_api_reliability_tcp_peer1.conf\ test_transport_api_reliability_tcp_peer2.conf\ test_transport_api_reliability_wlan_peer1.conf\ test_transport_api_reliability_wlan_peer2.conf\ test_transport_api_reliability_bluetooth_peer1.conf\ test_transport_api_reliability_bluetooth_peer2.conf\ test_transport_api_bidirectional_connect_peer1.conf\ test_transport_api_bidirectional_connect_peer2.conf\ test_transport_api_manipulation_send_tcp_peer1.conf\ test_transport_api_manipulation_send_tcp_peer2.conf\ test_transport_api_manipulation_recv_tcp_peer1.conf\ test_transport_api_manipulation_recv_tcp_peer2.conf\ test_transport_api_manipulation_cfg_peer1.conf\ test_transport_api_manipulation_cfg_peer2.conf\ test_transport_api_tcp_nat_peer1.conf\ test_transport_api_tcp_nat_peer2.conf\ test_transport_api_tcp_peer1.conf\ test_transport_api_tcp_peer2.conf\ test_transport_api_udp_nat_peer1.conf\ test_transport_api_udp_nat_peer2.conf\ test_transport_api_udp_peer1.conf\ test_transport_api_udp_peer2.conf\ test_transport_api_timeout_udp_peer1.conf\ test_transport_api_timeout_udp_peer2.conf\ test_transport_api_unix_peer1.conf\ test_transport_api_unix_peer2.conf\ test_transport_api_unix_abstract_peer1.conf \ test_transport_api_unix_abstract_peer2.conf \ test_transport_api_timeout_unix_peer1.conf\ test_transport_api_timeout_unix_peer2.conf\ test_transport_api_timeout_wlan_peer1.conf \ test_transport_api_timeout_wlan_peer2.conf \ test_transport_api_timeout_bluetooth_peer1.conf\ test_transport_api_timeout_bluetooth_peer2.conf\ test_transport_api_unreliability_udp_peer1.conf\ test_transport_api_unreliability_udp_peer2.conf\ test_transport_api_unreliability_unix_peer1.conf\ test_transport_api_unreliability_unix_peer2.conf\ test_transport_api_unreliability_wlan_peer1.conf\ test_transport_api_unreliability_wlan_peer2.conf\ test_transport_api_unreliability_bluetooth_peer1.conf\ test_transport_api_unreliability_bluetooth_peer2.conf\ test_transport_api_wlan_peer1.conf\ test_transport_api_wlan_peer2.conf\ test_transport_api_bluetooth_peer1.conf\ test_transport_api_bluetooth_peer2.conf\ test_transport_api_monitoring_peer1.conf\ test_transport_api_monitoring_peer2.conf\ test_transport_api_monitoring_validation_peer1.conf\ test_transport_api_monitoring_validation_peer2.conf\ test_transport_defaults.conf\ test_transport_startonly.conf\ test_transport_api_disconnect_tcp_peer1.conf\ test_transport_api_disconnect_tcp_peer2.conf\ test_transport_api_timeout_http_peer1.conf\ test_transport_api_timeout_http_peer2.conf\ test_transport_api_timeout_https_peer1.conf\ test_transport_api_timeout_https_peer2.conf\ test_transport_api_unreliability_constant_udp_peer1.conf\ test_transport_api_unreliability_constant_udp_peer2.conf\ test_transport_blacklisting_cfg_peer1.conf \ test_transport_blacklisting_cfg_peer2.conf \ test_transport_blacklisting_cfg_blp_peer1_full.conf\ test_transport_blacklisting_cfg_blp_peer1_plugin.conf \ test_transport_blacklisting_cfg_blp_peer2_full.conf\ test_transport_blacklisting_cfg_blp_peer2_plugin.conf \ test_transport_blacklisting_cfg_blp_peer1_multiple_plugins.conf \ test_transport_blacklisting_cfg_blp_peer2_multiple_plugins.conf \ test_transport_api_http_reverse_peer1.conf \ test_transport_api_http_reverse_peer2.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/transport/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/transport/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): transport.conf: $(top_builddir)/config.status $(srcdir)/transport.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_transport_bluetooth.la: $(libgnunet_plugin_transport_bluetooth_la_OBJECTS) $(libgnunet_plugin_transport_bluetooth_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_bluetooth_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_bluetooth_la_LINK) $(am_libgnunet_plugin_transport_bluetooth_la_rpath) $(libgnunet_plugin_transport_bluetooth_la_OBJECTS) $(libgnunet_plugin_transport_bluetooth_la_LIBADD) $(LIBS) libgnunet_plugin_transport_http_client.la: $(libgnunet_plugin_transport_http_client_la_OBJECTS) $(libgnunet_plugin_transport_http_client_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_http_client_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_http_client_la_LINK) $(am_libgnunet_plugin_transport_http_client_la_rpath) $(libgnunet_plugin_transport_http_client_la_OBJECTS) $(libgnunet_plugin_transport_http_client_la_LIBADD) $(LIBS) libgnunet_plugin_transport_http_server.la: $(libgnunet_plugin_transport_http_server_la_OBJECTS) $(libgnunet_plugin_transport_http_server_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_http_server_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_http_server_la_LINK) $(am_libgnunet_plugin_transport_http_server_la_rpath) $(libgnunet_plugin_transport_http_server_la_OBJECTS) $(libgnunet_plugin_transport_http_server_la_LIBADD) $(LIBS) libgnunet_plugin_transport_https_client.la: $(libgnunet_plugin_transport_https_client_la_OBJECTS) $(libgnunet_plugin_transport_https_client_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_https_client_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_https_client_la_LINK) $(am_libgnunet_plugin_transport_https_client_la_rpath) $(libgnunet_plugin_transport_https_client_la_OBJECTS) $(libgnunet_plugin_transport_https_client_la_LIBADD) $(LIBS) libgnunet_plugin_transport_https_server.la: $(libgnunet_plugin_transport_https_server_la_OBJECTS) $(libgnunet_plugin_transport_https_server_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_https_server_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_https_server_la_LINK) $(am_libgnunet_plugin_transport_https_server_la_rpath) $(libgnunet_plugin_transport_https_server_la_OBJECTS) $(libgnunet_plugin_transport_https_server_la_LIBADD) $(LIBS) libgnunet_plugin_transport_tcp.la: $(libgnunet_plugin_transport_tcp_la_OBJECTS) $(libgnunet_plugin_transport_tcp_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_tcp_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_tcp_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_transport_tcp_la_OBJECTS) $(libgnunet_plugin_transport_tcp_la_LIBADD) $(LIBS) libgnunet_plugin_transport_template.la: $(libgnunet_plugin_transport_template_la_OBJECTS) $(libgnunet_plugin_transport_template_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_template_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_template_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_transport_template_la_OBJECTS) $(libgnunet_plugin_transport_template_la_LIBADD) $(LIBS) libgnunet_plugin_transport_udp.la: $(libgnunet_plugin_transport_udp_la_OBJECTS) $(libgnunet_plugin_transport_udp_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_udp_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_udp_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_transport_udp_la_OBJECTS) $(libgnunet_plugin_transport_udp_la_LIBADD) $(LIBS) libgnunet_plugin_transport_unix.la: $(libgnunet_plugin_transport_unix_la_OBJECTS) $(libgnunet_plugin_transport_unix_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_unix_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_unix_la_LINK) $(am_libgnunet_plugin_transport_unix_la_rpath) $(libgnunet_plugin_transport_unix_la_OBJECTS) $(libgnunet_plugin_transport_unix_la_LIBADD) $(LIBS) libgnunet_plugin_transport_wlan.la: $(libgnunet_plugin_transport_wlan_la_OBJECTS) $(libgnunet_plugin_transport_wlan_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_wlan_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_wlan_la_LINK) $(am_libgnunet_plugin_transport_wlan_la_rpath) $(libgnunet_plugin_transport_wlan_la_OBJECTS) $(libgnunet_plugin_transport_wlan_la_LIBADD) $(LIBS) libgnunettransport.la: $(libgnunettransport_la_OBJECTS) $(libgnunettransport_la_DEPENDENCIES) $(EXTRA_libgnunettransport_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunettransport_la_LINK) -rpath $(libdir) $(libgnunettransport_la_OBJECTS) $(libgnunettransport_la_LIBADD) $(LIBS) libgnunettransporttesting.la: $(libgnunettransporttesting_la_OBJECTS) $(libgnunettransporttesting_la_DEPENDENCIES) $(EXTRA_libgnunettransporttesting_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunettransporttesting_la_LINK) $(am_libgnunettransporttesting_la_rpath) $(libgnunettransporttesting_la_OBJECTS) $(libgnunettransporttesting_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-helper-transport-bluetooth$(EXEEXT): $(gnunet_helper_transport_bluetooth_OBJECTS) $(gnunet_helper_transport_bluetooth_DEPENDENCIES) $(EXTRA_gnunet_helper_transport_bluetooth_DEPENDENCIES) @rm -f gnunet-helper-transport-bluetooth$(EXEEXT) $(AM_V_CCLD)$(gnunet_helper_transport_bluetooth_LINK) $(gnunet_helper_transport_bluetooth_OBJECTS) $(gnunet_helper_transport_bluetooth_LDADD) $(LIBS) gnunet-helper-transport-wlan$(EXEEXT): $(gnunet_helper_transport_wlan_OBJECTS) $(gnunet_helper_transport_wlan_DEPENDENCIES) $(EXTRA_gnunet_helper_transport_wlan_DEPENDENCIES) @rm -f gnunet-helper-transport-wlan$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_helper_transport_wlan_OBJECTS) $(gnunet_helper_transport_wlan_LDADD) $(LIBS) gnunet-helper-transport-wlan-dummy$(EXEEXT): $(gnunet_helper_transport_wlan_dummy_OBJECTS) $(gnunet_helper_transport_wlan_dummy_DEPENDENCIES) $(EXTRA_gnunet_helper_transport_wlan_dummy_DEPENDENCIES) @rm -f gnunet-helper-transport-wlan-dummy$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_helper_transport_wlan_dummy_OBJECTS) $(gnunet_helper_transport_wlan_dummy_LDADD) $(LIBS) gnunet-service-transport$(EXEEXT): $(gnunet_service_transport_OBJECTS) $(gnunet_service_transport_DEPENDENCIES) $(EXTRA_gnunet_service_transport_DEPENDENCIES) @rm -f gnunet-service-transport$(EXEEXT) $(AM_V_CCLD)$(gnunet_service_transport_LINK) $(gnunet_service_transport_OBJECTS) $(gnunet_service_transport_LDADD) $(LIBS) gnunet-transport$(EXEEXT): $(gnunet_transport_OBJECTS) $(gnunet_transport_DEPENDENCIES) $(EXTRA_gnunet_transport_DEPENDENCIES) @rm -f gnunet-transport$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_transport_OBJECTS) $(gnunet_transport_LDADD) $(LIBS) gnunet-transport-certificate-creation$(EXEEXT): $(gnunet_transport_certificate_creation_OBJECTS) $(gnunet_transport_certificate_creation_DEPENDENCIES) $(EXTRA_gnunet_transport_certificate_creation_DEPENDENCIES) @rm -f gnunet-transport-certificate-creation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_transport_certificate_creation_OBJECTS) $(gnunet_transport_certificate_creation_LDADD) $(LIBS) gnunet-transport-wlan-receiver$(EXEEXT): $(gnunet_transport_wlan_receiver_OBJECTS) $(gnunet_transport_wlan_receiver_DEPENDENCIES) $(EXTRA_gnunet_transport_wlan_receiver_DEPENDENCIES) @rm -f gnunet-transport-wlan-receiver$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_transport_wlan_receiver_OBJECTS) $(gnunet_transport_wlan_receiver_LDADD) $(LIBS) gnunet-transport-wlan-sender$(EXEEXT): $(gnunet_transport_wlan_sender_OBJECTS) $(gnunet_transport_wlan_sender_DEPENDENCIES) $(EXTRA_gnunet_transport_wlan_sender_DEPENDENCIES) @rm -f gnunet-transport-wlan-sender$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_transport_wlan_sender_OBJECTS) $(gnunet_transport_wlan_sender_LDADD) $(LIBS) test_http_common$(EXEEXT): $(test_http_common_OBJECTS) $(test_http_common_DEPENDENCIES) $(EXTRA_test_http_common_DEPENDENCIES) @rm -f test_http_common$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_http_common_OBJECTS) $(test_http_common_LDADD) $(LIBS) test_plugin_bluetooth$(EXEEXT): $(test_plugin_bluetooth_OBJECTS) $(test_plugin_bluetooth_DEPENDENCIES) $(EXTRA_test_plugin_bluetooth_DEPENDENCIES) @rm -f test_plugin_bluetooth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_bluetooth_OBJECTS) $(test_plugin_bluetooth_LDADD) $(LIBS) test_plugin_http_client$(EXEEXT): $(test_plugin_http_client_OBJECTS) $(test_plugin_http_client_DEPENDENCIES) $(EXTRA_test_plugin_http_client_DEPENDENCIES) @rm -f test_plugin_http_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_http_client_OBJECTS) $(test_plugin_http_client_LDADD) $(LIBS) test_plugin_http_server$(EXEEXT): $(test_plugin_http_server_OBJECTS) $(test_plugin_http_server_DEPENDENCIES) $(EXTRA_test_plugin_http_server_DEPENDENCIES) @rm -f test_plugin_http_server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_http_server_OBJECTS) $(test_plugin_http_server_LDADD) $(LIBS) test_plugin_https_client$(EXEEXT): $(test_plugin_https_client_OBJECTS) $(test_plugin_https_client_DEPENDENCIES) $(EXTRA_test_plugin_https_client_DEPENDENCIES) @rm -f test_plugin_https_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_https_client_OBJECTS) $(test_plugin_https_client_LDADD) $(LIBS) test_plugin_https_server$(EXEEXT): $(test_plugin_https_server_OBJECTS) $(test_plugin_https_server_DEPENDENCIES) $(EXTRA_test_plugin_https_server_DEPENDENCIES) @rm -f test_plugin_https_server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_https_server_OBJECTS) $(test_plugin_https_server_LDADD) $(LIBS) test_plugin_tcp$(EXEEXT): $(test_plugin_tcp_OBJECTS) $(test_plugin_tcp_DEPENDENCIES) $(EXTRA_test_plugin_tcp_DEPENDENCIES) @rm -f test_plugin_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_tcp_OBJECTS) $(test_plugin_tcp_LDADD) $(LIBS) test_plugin_udp$(EXEEXT): $(test_plugin_udp_OBJECTS) $(test_plugin_udp_DEPENDENCIES) $(EXTRA_test_plugin_udp_DEPENDENCIES) @rm -f test_plugin_udp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_udp_OBJECTS) $(test_plugin_udp_LDADD) $(LIBS) test_plugin_unix$(EXEEXT): $(test_plugin_unix_OBJECTS) $(test_plugin_unix_DEPENDENCIES) $(EXTRA_test_plugin_unix_DEPENDENCIES) @rm -f test_plugin_unix$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_unix_OBJECTS) $(test_plugin_unix_LDADD) $(LIBS) test_plugin_wlan$(EXEEXT): $(test_plugin_wlan_OBJECTS) $(test_plugin_wlan_DEPENDENCIES) $(EXTRA_test_plugin_wlan_DEPENDENCIES) @rm -f test_plugin_wlan$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_wlan_OBJECTS) $(test_plugin_wlan_LDADD) $(LIBS) test_quota_compliance_bluetooth$(EXEEXT): $(test_quota_compliance_bluetooth_OBJECTS) $(test_quota_compliance_bluetooth_DEPENDENCIES) $(EXTRA_test_quota_compliance_bluetooth_DEPENDENCIES) @rm -f test_quota_compliance_bluetooth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_bluetooth_OBJECTS) $(test_quota_compliance_bluetooth_LDADD) $(LIBS) test_quota_compliance_bluetooth_asymmetric$(EXEEXT): $(test_quota_compliance_bluetooth_asymmetric_OBJECTS) $(test_quota_compliance_bluetooth_asymmetric_DEPENDENCIES) $(EXTRA_test_quota_compliance_bluetooth_asymmetric_DEPENDENCIES) @rm -f test_quota_compliance_bluetooth_asymmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_bluetooth_asymmetric_OBJECTS) $(test_quota_compliance_bluetooth_asymmetric_LDADD) $(LIBS) test_quota_compliance_http$(EXEEXT): $(test_quota_compliance_http_OBJECTS) $(test_quota_compliance_http_DEPENDENCIES) $(EXTRA_test_quota_compliance_http_DEPENDENCIES) @rm -f test_quota_compliance_http$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_http_OBJECTS) $(test_quota_compliance_http_LDADD) $(LIBS) test_quota_compliance_http_asymmetric$(EXEEXT): $(test_quota_compliance_http_asymmetric_OBJECTS) $(test_quota_compliance_http_asymmetric_DEPENDENCIES) $(EXTRA_test_quota_compliance_http_asymmetric_DEPENDENCIES) @rm -f test_quota_compliance_http_asymmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_http_asymmetric_OBJECTS) $(test_quota_compliance_http_asymmetric_LDADD) $(LIBS) test_quota_compliance_https$(EXEEXT): $(test_quota_compliance_https_OBJECTS) $(test_quota_compliance_https_DEPENDENCIES) $(EXTRA_test_quota_compliance_https_DEPENDENCIES) @rm -f test_quota_compliance_https$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_https_OBJECTS) $(test_quota_compliance_https_LDADD) $(LIBS) test_quota_compliance_https_asymmetric$(EXEEXT): $(test_quota_compliance_https_asymmetric_OBJECTS) $(test_quota_compliance_https_asymmetric_DEPENDENCIES) $(EXTRA_test_quota_compliance_https_asymmetric_DEPENDENCIES) @rm -f test_quota_compliance_https_asymmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_https_asymmetric_OBJECTS) $(test_quota_compliance_https_asymmetric_LDADD) $(LIBS) test_quota_compliance_tcp$(EXEEXT): $(test_quota_compliance_tcp_OBJECTS) $(test_quota_compliance_tcp_DEPENDENCIES) $(EXTRA_test_quota_compliance_tcp_DEPENDENCIES) @rm -f test_quota_compliance_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_tcp_OBJECTS) $(test_quota_compliance_tcp_LDADD) $(LIBS) test_quota_compliance_tcp_asymmetric$(EXEEXT): $(test_quota_compliance_tcp_asymmetric_OBJECTS) $(test_quota_compliance_tcp_asymmetric_DEPENDENCIES) $(EXTRA_test_quota_compliance_tcp_asymmetric_DEPENDENCIES) @rm -f test_quota_compliance_tcp_asymmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_tcp_asymmetric_OBJECTS) $(test_quota_compliance_tcp_asymmetric_LDADD) $(LIBS) test_quota_compliance_udp$(EXEEXT): $(test_quota_compliance_udp_OBJECTS) $(test_quota_compliance_udp_DEPENDENCIES) $(EXTRA_test_quota_compliance_udp_DEPENDENCIES) @rm -f test_quota_compliance_udp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_udp_OBJECTS) $(test_quota_compliance_udp_LDADD) $(LIBS) test_quota_compliance_unix$(EXEEXT): $(test_quota_compliance_unix_OBJECTS) $(test_quota_compliance_unix_DEPENDENCIES) $(EXTRA_test_quota_compliance_unix_DEPENDENCIES) @rm -f test_quota_compliance_unix$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_unix_OBJECTS) $(test_quota_compliance_unix_LDADD) $(LIBS) test_quota_compliance_unix_asymmetric$(EXEEXT): $(test_quota_compliance_unix_asymmetric_OBJECTS) $(test_quota_compliance_unix_asymmetric_DEPENDENCIES) $(EXTRA_test_quota_compliance_unix_asymmetric_DEPENDENCIES) @rm -f test_quota_compliance_unix_asymmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_unix_asymmetric_OBJECTS) $(test_quota_compliance_unix_asymmetric_LDADD) $(LIBS) test_quota_compliance_wlan$(EXEEXT): $(test_quota_compliance_wlan_OBJECTS) $(test_quota_compliance_wlan_DEPENDENCIES) $(EXTRA_test_quota_compliance_wlan_DEPENDENCIES) @rm -f test_quota_compliance_wlan$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_wlan_OBJECTS) $(test_quota_compliance_wlan_LDADD) $(LIBS) test_quota_compliance_wlan_asymmetric$(EXEEXT): $(test_quota_compliance_wlan_asymmetric_OBJECTS) $(test_quota_compliance_wlan_asymmetric_DEPENDENCIES) $(EXTRA_test_quota_compliance_wlan_asymmetric_DEPENDENCIES) @rm -f test_quota_compliance_wlan_asymmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_quota_compliance_wlan_asymmetric_OBJECTS) $(test_quota_compliance_wlan_asymmetric_LDADD) $(LIBS) test_transport_api_bidirectional_connect$(EXEEXT): $(test_transport_api_bidirectional_connect_OBJECTS) $(test_transport_api_bidirectional_connect_DEPENDENCIES) $(EXTRA_test_transport_api_bidirectional_connect_DEPENDENCIES) @rm -f test_transport_api_bidirectional_connect$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_bidirectional_connect_OBJECTS) $(test_transport_api_bidirectional_connect_LDADD) $(LIBS) test_transport_api_blacklisting$(EXEEXT): $(test_transport_api_blacklisting_OBJECTS) $(test_transport_api_blacklisting_DEPENDENCIES) $(EXTRA_test_transport_api_blacklisting_DEPENDENCIES) @rm -f test_transport_api_blacklisting$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_blacklisting_OBJECTS) $(test_transport_api_blacklisting_LDADD) $(LIBS) test_transport_api_bluetooth$(EXEEXT): $(test_transport_api_bluetooth_OBJECTS) $(test_transport_api_bluetooth_DEPENDENCIES) $(EXTRA_test_transport_api_bluetooth_DEPENDENCIES) @rm -f test_transport_api_bluetooth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_bluetooth_OBJECTS) $(test_transport_api_bluetooth_LDADD) $(LIBS) test_transport_api_disconnect_tcp$(EXEEXT): $(test_transport_api_disconnect_tcp_OBJECTS) $(test_transport_api_disconnect_tcp_DEPENDENCIES) $(EXTRA_test_transport_api_disconnect_tcp_DEPENDENCIES) @rm -f test_transport_api_disconnect_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_disconnect_tcp_OBJECTS) $(test_transport_api_disconnect_tcp_LDADD) $(LIBS) test_transport_api_http$(EXEEXT): $(test_transport_api_http_OBJECTS) $(test_transport_api_http_DEPENDENCIES) $(EXTRA_test_transport_api_http_DEPENDENCIES) @rm -f test_transport_api_http$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_http_OBJECTS) $(test_transport_api_http_LDADD) $(LIBS) test_transport_api_http_reverse$(EXEEXT): $(test_transport_api_http_reverse_OBJECTS) $(test_transport_api_http_reverse_DEPENDENCIES) $(EXTRA_test_transport_api_http_reverse_DEPENDENCIES) @rm -f test_transport_api_http_reverse$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_http_reverse_OBJECTS) $(test_transport_api_http_reverse_LDADD) $(LIBS) test_transport_api_https$(EXEEXT): $(test_transport_api_https_OBJECTS) $(test_transport_api_https_DEPENDENCIES) $(EXTRA_test_transport_api_https_DEPENDENCIES) @rm -f test_transport_api_https$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_https_OBJECTS) $(test_transport_api_https_LDADD) $(LIBS) test_transport_api_limited_sockets_tcp$(EXEEXT): $(test_transport_api_limited_sockets_tcp_OBJECTS) $(test_transport_api_limited_sockets_tcp_DEPENDENCIES) $(EXTRA_test_transport_api_limited_sockets_tcp_DEPENDENCIES) @rm -f test_transport_api_limited_sockets_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_limited_sockets_tcp_OBJECTS) $(test_transport_api_limited_sockets_tcp_LDADD) $(LIBS) test_transport_api_manipulation_cfg$(EXEEXT): $(test_transport_api_manipulation_cfg_OBJECTS) $(test_transport_api_manipulation_cfg_DEPENDENCIES) $(EXTRA_test_transport_api_manipulation_cfg_DEPENDENCIES) @rm -f test_transport_api_manipulation_cfg$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_manipulation_cfg_OBJECTS) $(test_transport_api_manipulation_cfg_LDADD) $(LIBS) test_transport_api_manipulation_recv_tcp$(EXEEXT): $(test_transport_api_manipulation_recv_tcp_OBJECTS) $(test_transport_api_manipulation_recv_tcp_DEPENDENCIES) $(EXTRA_test_transport_api_manipulation_recv_tcp_DEPENDENCIES) @rm -f test_transport_api_manipulation_recv_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_manipulation_recv_tcp_OBJECTS) $(test_transport_api_manipulation_recv_tcp_LDADD) $(LIBS) test_transport_api_manipulation_send_tcp$(EXEEXT): $(test_transport_api_manipulation_send_tcp_OBJECTS) $(test_transport_api_manipulation_send_tcp_DEPENDENCIES) $(EXTRA_test_transport_api_manipulation_send_tcp_DEPENDENCIES) @rm -f test_transport_api_manipulation_send_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_manipulation_send_tcp_OBJECTS) $(test_transport_api_manipulation_send_tcp_LDADD) $(LIBS) test_transport_api_monitoring$(EXEEXT): $(test_transport_api_monitoring_OBJECTS) $(test_transport_api_monitoring_DEPENDENCIES) $(EXTRA_test_transport_api_monitoring_DEPENDENCIES) @rm -f test_transport_api_monitoring$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_monitoring_OBJECTS) $(test_transport_api_monitoring_LDADD) $(LIBS) test_transport_api_monitoring_validation$(EXEEXT): $(test_transport_api_monitoring_validation_OBJECTS) $(test_transport_api_monitoring_validation_DEPENDENCIES) $(EXTRA_test_transport_api_monitoring_validation_DEPENDENCIES) @rm -f test_transport_api_monitoring_validation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_monitoring_validation_OBJECTS) $(test_transport_api_monitoring_validation_LDADD) $(LIBS) test_transport_api_multi$(EXEEXT): $(test_transport_api_multi_OBJECTS) $(test_transport_api_multi_DEPENDENCIES) $(EXTRA_test_transport_api_multi_DEPENDENCIES) @rm -f test_transport_api_multi$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_multi_OBJECTS) $(test_transport_api_multi_LDADD) $(LIBS) test_transport_api_reliability_bluetooth$(EXEEXT): $(test_transport_api_reliability_bluetooth_OBJECTS) $(test_transport_api_reliability_bluetooth_DEPENDENCIES) $(EXTRA_test_transport_api_reliability_bluetooth_DEPENDENCIES) @rm -f test_transport_api_reliability_bluetooth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_reliability_bluetooth_OBJECTS) $(test_transport_api_reliability_bluetooth_LDADD) $(LIBS) test_transport_api_reliability_http$(EXEEXT): $(test_transport_api_reliability_http_OBJECTS) $(test_transport_api_reliability_http_DEPENDENCIES) $(EXTRA_test_transport_api_reliability_http_DEPENDENCIES) @rm -f test_transport_api_reliability_http$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_reliability_http_OBJECTS) $(test_transport_api_reliability_http_LDADD) $(LIBS) test_transport_api_reliability_https$(EXEEXT): $(test_transport_api_reliability_https_OBJECTS) $(test_transport_api_reliability_https_DEPENDENCIES) $(EXTRA_test_transport_api_reliability_https_DEPENDENCIES) @rm -f test_transport_api_reliability_https$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_reliability_https_OBJECTS) $(test_transport_api_reliability_https_LDADD) $(LIBS) test_transport_api_reliability_tcp$(EXEEXT): $(test_transport_api_reliability_tcp_OBJECTS) $(test_transport_api_reliability_tcp_DEPENDENCIES) $(EXTRA_test_transport_api_reliability_tcp_DEPENDENCIES) @rm -f test_transport_api_reliability_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_reliability_tcp_OBJECTS) $(test_transport_api_reliability_tcp_LDADD) $(LIBS) test_transport_api_reliability_tcp_nat$(EXEEXT): $(test_transport_api_reliability_tcp_nat_OBJECTS) $(test_transport_api_reliability_tcp_nat_DEPENDENCIES) $(EXTRA_test_transport_api_reliability_tcp_nat_DEPENDENCIES) @rm -f test_transport_api_reliability_tcp_nat$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_reliability_tcp_nat_OBJECTS) $(test_transport_api_reliability_tcp_nat_LDADD) $(LIBS) test_transport_api_reliability_wlan$(EXEEXT): $(test_transport_api_reliability_wlan_OBJECTS) $(test_transport_api_reliability_wlan_DEPENDENCIES) $(EXTRA_test_transport_api_reliability_wlan_DEPENDENCIES) @rm -f test_transport_api_reliability_wlan$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_reliability_wlan_OBJECTS) $(test_transport_api_reliability_wlan_LDADD) $(LIBS) test_transport_api_restart_1peer$(EXEEXT): $(test_transport_api_restart_1peer_OBJECTS) $(test_transport_api_restart_1peer_DEPENDENCIES) $(EXTRA_test_transport_api_restart_1peer_DEPENDENCIES) @rm -f test_transport_api_restart_1peer$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_restart_1peer_OBJECTS) $(test_transport_api_restart_1peer_LDADD) $(LIBS) test_transport_api_restart_2peers$(EXEEXT): $(test_transport_api_restart_2peers_OBJECTS) $(test_transport_api_restart_2peers_DEPENDENCIES) $(EXTRA_test_transport_api_restart_2peers_DEPENDENCIES) @rm -f test_transport_api_restart_2peers$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_restart_2peers_OBJECTS) $(test_transport_api_restart_2peers_LDADD) $(LIBS) test_transport_api_tcp$(EXEEXT): $(test_transport_api_tcp_OBJECTS) $(test_transport_api_tcp_DEPENDENCIES) $(EXTRA_test_transport_api_tcp_DEPENDENCIES) @rm -f test_transport_api_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_tcp_OBJECTS) $(test_transport_api_tcp_LDADD) $(LIBS) test_transport_api_tcp_nat$(EXEEXT): $(test_transport_api_tcp_nat_OBJECTS) $(test_transport_api_tcp_nat_DEPENDENCIES) $(EXTRA_test_transport_api_tcp_nat_DEPENDENCIES) @rm -f test_transport_api_tcp_nat$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_tcp_nat_OBJECTS) $(test_transport_api_tcp_nat_LDADD) $(LIBS) test_transport_api_timeout_bluetooth$(EXEEXT): $(test_transport_api_timeout_bluetooth_OBJECTS) $(test_transport_api_timeout_bluetooth_DEPENDENCIES) $(EXTRA_test_transport_api_timeout_bluetooth_DEPENDENCIES) @rm -f test_transport_api_timeout_bluetooth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_timeout_bluetooth_OBJECTS) $(test_transport_api_timeout_bluetooth_LDADD) $(LIBS) test_transport_api_timeout_http$(EXEEXT): $(test_transport_api_timeout_http_OBJECTS) $(test_transport_api_timeout_http_DEPENDENCIES) $(EXTRA_test_transport_api_timeout_http_DEPENDENCIES) @rm -f test_transport_api_timeout_http$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_timeout_http_OBJECTS) $(test_transport_api_timeout_http_LDADD) $(LIBS) test_transport_api_timeout_https$(EXEEXT): $(test_transport_api_timeout_https_OBJECTS) $(test_transport_api_timeout_https_DEPENDENCIES) $(EXTRA_test_transport_api_timeout_https_DEPENDENCIES) @rm -f test_transport_api_timeout_https$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_timeout_https_OBJECTS) $(test_transport_api_timeout_https_LDADD) $(LIBS) test_transport_api_timeout_tcp$(EXEEXT): $(test_transport_api_timeout_tcp_OBJECTS) $(test_transport_api_timeout_tcp_DEPENDENCIES) $(EXTRA_test_transport_api_timeout_tcp_DEPENDENCIES) @rm -f test_transport_api_timeout_tcp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_timeout_tcp_OBJECTS) $(test_transport_api_timeout_tcp_LDADD) $(LIBS) test_transport_api_timeout_udp$(EXEEXT): $(test_transport_api_timeout_udp_OBJECTS) $(test_transport_api_timeout_udp_DEPENDENCIES) $(EXTRA_test_transport_api_timeout_udp_DEPENDENCIES) @rm -f test_transport_api_timeout_udp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_timeout_udp_OBJECTS) $(test_transport_api_timeout_udp_LDADD) $(LIBS) test_transport_api_timeout_unix$(EXEEXT): $(test_transport_api_timeout_unix_OBJECTS) $(test_transport_api_timeout_unix_DEPENDENCIES) $(EXTRA_test_transport_api_timeout_unix_DEPENDENCIES) @rm -f test_transport_api_timeout_unix$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_timeout_unix_OBJECTS) $(test_transport_api_timeout_unix_LDADD) $(LIBS) test_transport_api_timeout_wlan$(EXEEXT): $(test_transport_api_timeout_wlan_OBJECTS) $(test_transport_api_timeout_wlan_DEPENDENCIES) $(EXTRA_test_transport_api_timeout_wlan_DEPENDENCIES) @rm -f test_transport_api_timeout_wlan$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_timeout_wlan_OBJECTS) $(test_transport_api_timeout_wlan_LDADD) $(LIBS) test_transport_api_udp$(EXEEXT): $(test_transport_api_udp_OBJECTS) $(test_transport_api_udp_DEPENDENCIES) $(EXTRA_test_transport_api_udp_DEPENDENCIES) @rm -f test_transport_api_udp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_udp_OBJECTS) $(test_transport_api_udp_LDADD) $(LIBS) test_transport_api_udp_nat$(EXEEXT): $(test_transport_api_udp_nat_OBJECTS) $(test_transport_api_udp_nat_DEPENDENCIES) $(EXTRA_test_transport_api_udp_nat_DEPENDENCIES) @rm -f test_transport_api_udp_nat$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_udp_nat_OBJECTS) $(test_transport_api_udp_nat_LDADD) $(LIBS) test_transport_api_unix$(EXEEXT): $(test_transport_api_unix_OBJECTS) $(test_transport_api_unix_DEPENDENCIES) $(EXTRA_test_transport_api_unix_DEPENDENCIES) @rm -f test_transport_api_unix$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_unix_OBJECTS) $(test_transport_api_unix_LDADD) $(LIBS) test_transport_api_unix_abstract$(EXEEXT): $(test_transport_api_unix_abstract_OBJECTS) $(test_transport_api_unix_abstract_DEPENDENCIES) $(EXTRA_test_transport_api_unix_abstract_DEPENDENCIES) @rm -f test_transport_api_unix_abstract$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_unix_abstract_OBJECTS) $(test_transport_api_unix_abstract_LDADD) $(LIBS) test_transport_api_unreliability_bluetooth$(EXEEXT): $(test_transport_api_unreliability_bluetooth_OBJECTS) $(test_transport_api_unreliability_bluetooth_DEPENDENCIES) $(EXTRA_test_transport_api_unreliability_bluetooth_DEPENDENCIES) @rm -f test_transport_api_unreliability_bluetooth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_unreliability_bluetooth_OBJECTS) $(test_transport_api_unreliability_bluetooth_LDADD) $(LIBS) test_transport_api_unreliability_constant_udp$(EXEEXT): $(test_transport_api_unreliability_constant_udp_OBJECTS) $(test_transport_api_unreliability_constant_udp_DEPENDENCIES) $(EXTRA_test_transport_api_unreliability_constant_udp_DEPENDENCIES) @rm -f test_transport_api_unreliability_constant_udp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_unreliability_constant_udp_OBJECTS) $(test_transport_api_unreliability_constant_udp_LDADD) $(LIBS) test_transport_api_unreliability_udp$(EXEEXT): $(test_transport_api_unreliability_udp_OBJECTS) $(test_transport_api_unreliability_udp_DEPENDENCIES) $(EXTRA_test_transport_api_unreliability_udp_DEPENDENCIES) @rm -f test_transport_api_unreliability_udp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_unreliability_udp_OBJECTS) $(test_transport_api_unreliability_udp_LDADD) $(LIBS) test_transport_api_unreliability_unix$(EXEEXT): $(test_transport_api_unreliability_unix_OBJECTS) $(test_transport_api_unreliability_unix_DEPENDENCIES) $(EXTRA_test_transport_api_unreliability_unix_DEPENDENCIES) @rm -f test_transport_api_unreliability_unix$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_unreliability_unix_OBJECTS) $(test_transport_api_unreliability_unix_LDADD) $(LIBS) test_transport_api_unreliability_wlan$(EXEEXT): $(test_transport_api_unreliability_wlan_OBJECTS) $(test_transport_api_unreliability_wlan_DEPENDENCIES) $(EXTRA_test_transport_api_unreliability_wlan_DEPENDENCIES) @rm -f test_transport_api_unreliability_wlan$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_unreliability_wlan_OBJECTS) $(test_transport_api_unreliability_wlan_LDADD) $(LIBS) test_transport_api_wlan$(EXEEXT): $(test_transport_api_wlan_OBJECTS) $(test_transport_api_wlan_DEPENDENCIES) $(EXTRA_test_transport_api_wlan_DEPENDENCIES) @rm -f test_transport_api_wlan$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_api_wlan_OBJECTS) $(test_transport_api_wlan_LDADD) $(LIBS) test_transport_blacklisting_inbound_bl_full$(EXEEXT): $(test_transport_blacklisting_inbound_bl_full_OBJECTS) $(test_transport_blacklisting_inbound_bl_full_DEPENDENCIES) $(EXTRA_test_transport_blacklisting_inbound_bl_full_DEPENDENCIES) @rm -f test_transport_blacklisting_inbound_bl_full$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_blacklisting_inbound_bl_full_OBJECTS) $(test_transport_blacklisting_inbound_bl_full_LDADD) $(LIBS) test_transport_blacklisting_inbound_bl_plugin$(EXEEXT): $(test_transport_blacklisting_inbound_bl_plugin_OBJECTS) $(test_transport_blacklisting_inbound_bl_plugin_DEPENDENCIES) $(EXTRA_test_transport_blacklisting_inbound_bl_plugin_DEPENDENCIES) @rm -f test_transport_blacklisting_inbound_bl_plugin$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_blacklisting_inbound_bl_plugin_OBJECTS) $(test_transport_blacklisting_inbound_bl_plugin_LDADD) $(LIBS) test_transport_blacklisting_multiple_plugins$(EXEEXT): $(test_transport_blacklisting_multiple_plugins_OBJECTS) $(test_transport_blacklisting_multiple_plugins_DEPENDENCIES) $(EXTRA_test_transport_blacklisting_multiple_plugins_DEPENDENCIES) @rm -f test_transport_blacklisting_multiple_plugins$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_blacklisting_multiple_plugins_OBJECTS) $(test_transport_blacklisting_multiple_plugins_LDADD) $(LIBS) test_transport_blacklisting_no_bl$(EXEEXT): $(test_transport_blacklisting_no_bl_OBJECTS) $(test_transport_blacklisting_no_bl_DEPENDENCIES) $(EXTRA_test_transport_blacklisting_no_bl_DEPENDENCIES) @rm -f test_transport_blacklisting_no_bl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_blacklisting_no_bl_OBJECTS) $(test_transport_blacklisting_no_bl_LDADD) $(LIBS) test_transport_blacklisting_outbound_bl_full$(EXEEXT): $(test_transport_blacklisting_outbound_bl_full_OBJECTS) $(test_transport_blacklisting_outbound_bl_full_DEPENDENCIES) $(EXTRA_test_transport_blacklisting_outbound_bl_full_DEPENDENCIES) @rm -f test_transport_blacklisting_outbound_bl_full$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_blacklisting_outbound_bl_full_OBJECTS) $(test_transport_blacklisting_outbound_bl_full_LDADD) $(LIBS) test_transport_blacklisting_outbound_bl_plugin$(EXEEXT): $(test_transport_blacklisting_outbound_bl_plugin_OBJECTS) $(test_transport_blacklisting_outbound_bl_plugin_DEPENDENCIES) $(EXTRA_test_transport_blacklisting_outbound_bl_plugin_DEPENDENCIES) @rm -f test_transport_blacklisting_outbound_bl_plugin$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_blacklisting_outbound_bl_plugin_OBJECTS) $(test_transport_blacklisting_outbound_bl_plugin_LDADD) $(LIBS) test_transport_startonly$(EXEEXT): $(test_transport_startonly_OBJECTS) $(test_transport_startonly_DEPENDENCIES) $(EXTRA_test_transport_startonly_DEPENDENCIES) @rm -f test_transport_startonly$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_startonly_OBJECTS) $(test_transport_startonly_LDADD) $(LIBS) test_transport_testing$(EXEEXT): $(test_transport_testing_OBJECTS) $(test_transport_testing_DEPENDENCIES) $(EXTRA_test_transport_testing_DEPENDENCIES) @rm -f test_transport_testing$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_testing_OBJECTS) $(test_transport_testing_LDADD) $(LIBS) test_transport_testing_restart$(EXEEXT): $(test_transport_testing_restart_OBJECTS) $(test_transport_testing_restart_DEPENDENCIES) $(EXTRA_test_transport_testing_restart_DEPENDENCIES) @rm -f test_transport_testing_restart$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_testing_restart_OBJECTS) $(test_transport_testing_restart_LDADD) $(LIBS) test_transport_testing_startstop$(EXEEXT): $(test_transport_testing_startstop_OBJECTS) $(test_transport_testing_startstop_DEPENDENCIES) $(EXTRA_test_transport_testing_startstop_DEPENDENCIES) @rm -f test_transport_testing_startstop$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_testing_startstop_OBJECTS) $(test_transport_testing_startstop_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-transport-bluetooth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-transport-wlan-dummy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-transport-wlan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-transport-certificate-creation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-transport-wlan-receiver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-transport-wlan-sender.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-transport.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_transport-gnunet-service-transport.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_transport-gnunet-service-transport_blacklist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_transport-gnunet-service-transport_clients.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_transport-gnunet-service-transport_hello.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_transport-gnunet-service-transport_manipulation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_transport-gnunet-service-transport_neighbours.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_transport-gnunet-service-transport_plugins.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_transport-gnunet-service-transport_validation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_bluetooth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_http_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_tcp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_template.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_udp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_udp_broadcasting.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_wlan.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_http_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_transport.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_quota_compliance.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_bidirectional_connect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_blacklisting.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_disconnect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_limited_sockets.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_manipulation_cfg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_manipulation_recv_tcp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_manipulation_send_tcp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_monitoring.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_monitoring_validation.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_reliability.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_restart_1peer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_restart_2peers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_timeout.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_unreliability.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_api_unreliability_constant.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_blacklisting.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_startonly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_testing.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_testing_restart.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_testing_startstop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transport-testing.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transport_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transport_api_address_to_string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transport_api_blacklist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/transport_api_monitoring.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.lo: plugin_transport_http_client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_transport_http_client_la_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_http_client_la_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.Tpo -c -o libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.lo `test -f 'plugin_transport_http_client.c' || echo '$(srcdir)/'`plugin_transport_http_client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.Tpo $(DEPDIR)/libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_transport_http_client.c' object='libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_transport_http_client_la_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_http_client_la_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_transport_http_client_la-plugin_transport_http_client.lo `test -f 'plugin_transport_http_client.c' || echo '$(srcdir)/'`plugin_transport_http_client.c libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.lo: plugin_transport_http_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_transport_http_client_la_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_http_client_la_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.Tpo -c -o libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.lo `test -f 'plugin_transport_http_common.c' || echo '$(srcdir)/'`plugin_transport_http_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.Tpo $(DEPDIR)/libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_transport_http_common.c' object='libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_transport_http_client_la_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_http_client_la_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_transport_http_client_la-plugin_transport_http_common.lo `test -f 'plugin_transport_http_common.c' || echo '$(srcdir)/'`plugin_transport_http_common.c libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.lo: plugin_transport_http_server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_http_server_la_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.Tpo -c -o libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.lo `test -f 'plugin_transport_http_server.c' || echo '$(srcdir)/'`plugin_transport_http_server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.Tpo $(DEPDIR)/libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_transport_http_server.c' object='libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_http_server_la_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_transport_http_server_la-plugin_transport_http_server.lo `test -f 'plugin_transport_http_server.c' || echo '$(srcdir)/'`plugin_transport_http_server.c libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.lo: plugin_transport_http_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_http_server_la_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.Tpo -c -o libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.lo `test -f 'plugin_transport_http_common.c' || echo '$(srcdir)/'`plugin_transport_http_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.Tpo $(DEPDIR)/libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_transport_http_common.c' object='libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_http_server_la_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_transport_http_server_la-plugin_transport_http_common.lo `test -f 'plugin_transport_http_common.c' || echo '$(srcdir)/'`plugin_transport_http_common.c libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.lo: plugin_transport_http_client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_transport_https_client_la_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_https_client_la_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.Tpo -c -o libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.lo `test -f 'plugin_transport_http_client.c' || echo '$(srcdir)/'`plugin_transport_http_client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.Tpo $(DEPDIR)/libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_transport_http_client.c' object='libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_transport_https_client_la_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_https_client_la_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_transport_https_client_la-plugin_transport_http_client.lo `test -f 'plugin_transport_http_client.c' || echo '$(srcdir)/'`plugin_transport_http_client.c libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.lo: plugin_transport_http_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_transport_https_client_la_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_https_client_la_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.Tpo -c -o libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.lo `test -f 'plugin_transport_http_common.c' || echo '$(srcdir)/'`plugin_transport_http_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.Tpo $(DEPDIR)/libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_transport_http_common.c' object='libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_transport_https_client_la_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_https_client_la_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_transport_https_client_la-plugin_transport_http_common.lo `test -f 'plugin_transport_http_common.c' || echo '$(srcdir)/'`plugin_transport_http_common.c libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.lo: plugin_transport_http_server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_https_server_la_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.Tpo -c -o libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.lo `test -f 'plugin_transport_http_server.c' || echo '$(srcdir)/'`plugin_transport_http_server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.Tpo $(DEPDIR)/libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_transport_http_server.c' object='libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_https_server_la_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_transport_https_server_la-plugin_transport_http_server.lo `test -f 'plugin_transport_http_server.c' || echo '$(srcdir)/'`plugin_transport_http_server.c libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.lo: plugin_transport_http_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_https_server_la_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.Tpo -c -o libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.lo `test -f 'plugin_transport_http_common.c' || echo '$(srcdir)/'`plugin_transport_http_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.Tpo $(DEPDIR)/libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_transport_http_common.c' object='libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgnunet_plugin_transport_https_server_la_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_transport_https_server_la-plugin_transport_http_common.lo `test -f 'plugin_transport_http_common.c' || echo '$(srcdir)/'`plugin_transport_http_common.c gnunet_service_transport-gnunet-service-transport.o: gnunet-service-transport.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport.o -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport.Tpo -c -o gnunet_service_transport-gnunet-service-transport.o `test -f 'gnunet-service-transport.c' || echo '$(srcdir)/'`gnunet-service-transport.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport.c' object='gnunet_service_transport-gnunet-service-transport.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport.o `test -f 'gnunet-service-transport.c' || echo '$(srcdir)/'`gnunet-service-transport.c gnunet_service_transport-gnunet-service-transport.obj: gnunet-service-transport.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport.obj -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport.Tpo -c -o gnunet_service_transport-gnunet-service-transport.obj `if test -f 'gnunet-service-transport.c'; then $(CYGPATH_W) 'gnunet-service-transport.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport.c' object='gnunet_service_transport-gnunet-service-transport.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport.obj `if test -f 'gnunet-service-transport.c'; then $(CYGPATH_W) 'gnunet-service-transport.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport.c'; fi` gnunet_service_transport-gnunet-service-transport_blacklist.o: gnunet-service-transport_blacklist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_blacklist.o -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_blacklist.Tpo -c -o gnunet_service_transport-gnunet-service-transport_blacklist.o `test -f 'gnunet-service-transport_blacklist.c' || echo '$(srcdir)/'`gnunet-service-transport_blacklist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_blacklist.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_blacklist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_blacklist.c' object='gnunet_service_transport-gnunet-service-transport_blacklist.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_blacklist.o `test -f 'gnunet-service-transport_blacklist.c' || echo '$(srcdir)/'`gnunet-service-transport_blacklist.c gnunet_service_transport-gnunet-service-transport_blacklist.obj: gnunet-service-transport_blacklist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_blacklist.obj -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_blacklist.Tpo -c -o gnunet_service_transport-gnunet-service-transport_blacklist.obj `if test -f 'gnunet-service-transport_blacklist.c'; then $(CYGPATH_W) 'gnunet-service-transport_blacklist.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_blacklist.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_blacklist.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_blacklist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_blacklist.c' object='gnunet_service_transport-gnunet-service-transport_blacklist.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_blacklist.obj `if test -f 'gnunet-service-transport_blacklist.c'; then $(CYGPATH_W) 'gnunet-service-transport_blacklist.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_blacklist.c'; fi` gnunet_service_transport-gnunet-service-transport_clients.o: gnunet-service-transport_clients.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_clients.o -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_clients.Tpo -c -o gnunet_service_transport-gnunet-service-transport_clients.o `test -f 'gnunet-service-transport_clients.c' || echo '$(srcdir)/'`gnunet-service-transport_clients.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_clients.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_clients.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_clients.c' object='gnunet_service_transport-gnunet-service-transport_clients.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_clients.o `test -f 'gnunet-service-transport_clients.c' || echo '$(srcdir)/'`gnunet-service-transport_clients.c gnunet_service_transport-gnunet-service-transport_clients.obj: gnunet-service-transport_clients.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_clients.obj -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_clients.Tpo -c -o gnunet_service_transport-gnunet-service-transport_clients.obj `if test -f 'gnunet-service-transport_clients.c'; then $(CYGPATH_W) 'gnunet-service-transport_clients.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_clients.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_clients.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_clients.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_clients.c' object='gnunet_service_transport-gnunet-service-transport_clients.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_clients.obj `if test -f 'gnunet-service-transport_clients.c'; then $(CYGPATH_W) 'gnunet-service-transport_clients.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_clients.c'; fi` gnunet_service_transport-gnunet-service-transport_hello.o: gnunet-service-transport_hello.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_hello.o -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_hello.Tpo -c -o gnunet_service_transport-gnunet-service-transport_hello.o `test -f 'gnunet-service-transport_hello.c' || echo '$(srcdir)/'`gnunet-service-transport_hello.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_hello.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_hello.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_hello.c' object='gnunet_service_transport-gnunet-service-transport_hello.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_hello.o `test -f 'gnunet-service-transport_hello.c' || echo '$(srcdir)/'`gnunet-service-transport_hello.c gnunet_service_transport-gnunet-service-transport_hello.obj: gnunet-service-transport_hello.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_hello.obj -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_hello.Tpo -c -o gnunet_service_transport-gnunet-service-transport_hello.obj `if test -f 'gnunet-service-transport_hello.c'; then $(CYGPATH_W) 'gnunet-service-transport_hello.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_hello.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_hello.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_hello.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_hello.c' object='gnunet_service_transport-gnunet-service-transport_hello.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_hello.obj `if test -f 'gnunet-service-transport_hello.c'; then $(CYGPATH_W) 'gnunet-service-transport_hello.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_hello.c'; fi` gnunet_service_transport-gnunet-service-transport_neighbours.o: gnunet-service-transport_neighbours.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_neighbours.o -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_neighbours.Tpo -c -o gnunet_service_transport-gnunet-service-transport_neighbours.o `test -f 'gnunet-service-transport_neighbours.c' || echo '$(srcdir)/'`gnunet-service-transport_neighbours.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_neighbours.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_neighbours.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_neighbours.c' object='gnunet_service_transport-gnunet-service-transport_neighbours.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_neighbours.o `test -f 'gnunet-service-transport_neighbours.c' || echo '$(srcdir)/'`gnunet-service-transport_neighbours.c gnunet_service_transport-gnunet-service-transport_neighbours.obj: gnunet-service-transport_neighbours.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_neighbours.obj -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_neighbours.Tpo -c -o gnunet_service_transport-gnunet-service-transport_neighbours.obj `if test -f 'gnunet-service-transport_neighbours.c'; then $(CYGPATH_W) 'gnunet-service-transport_neighbours.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_neighbours.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_neighbours.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_neighbours.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_neighbours.c' object='gnunet_service_transport-gnunet-service-transport_neighbours.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_neighbours.obj `if test -f 'gnunet-service-transport_neighbours.c'; then $(CYGPATH_W) 'gnunet-service-transport_neighbours.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_neighbours.c'; fi` gnunet_service_transport-gnunet-service-transport_plugins.o: gnunet-service-transport_plugins.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_plugins.o -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_plugins.Tpo -c -o gnunet_service_transport-gnunet-service-transport_plugins.o `test -f 'gnunet-service-transport_plugins.c' || echo '$(srcdir)/'`gnunet-service-transport_plugins.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_plugins.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_plugins.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_plugins.c' object='gnunet_service_transport-gnunet-service-transport_plugins.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_plugins.o `test -f 'gnunet-service-transport_plugins.c' || echo '$(srcdir)/'`gnunet-service-transport_plugins.c gnunet_service_transport-gnunet-service-transport_plugins.obj: gnunet-service-transport_plugins.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_plugins.obj -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_plugins.Tpo -c -o gnunet_service_transport-gnunet-service-transport_plugins.obj `if test -f 'gnunet-service-transport_plugins.c'; then $(CYGPATH_W) 'gnunet-service-transport_plugins.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_plugins.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_plugins.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_plugins.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_plugins.c' object='gnunet_service_transport-gnunet-service-transport_plugins.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_plugins.obj `if test -f 'gnunet-service-transport_plugins.c'; then $(CYGPATH_W) 'gnunet-service-transport_plugins.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_plugins.c'; fi` gnunet_service_transport-gnunet-service-transport_validation.o: gnunet-service-transport_validation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_validation.o -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_validation.Tpo -c -o gnunet_service_transport-gnunet-service-transport_validation.o `test -f 'gnunet-service-transport_validation.c' || echo '$(srcdir)/'`gnunet-service-transport_validation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_validation.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_validation.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_validation.c' object='gnunet_service_transport-gnunet-service-transport_validation.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_validation.o `test -f 'gnunet-service-transport_validation.c' || echo '$(srcdir)/'`gnunet-service-transport_validation.c gnunet_service_transport-gnunet-service-transport_validation.obj: gnunet-service-transport_validation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_validation.obj -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_validation.Tpo -c -o gnunet_service_transport-gnunet-service-transport_validation.obj `if test -f 'gnunet-service-transport_validation.c'; then $(CYGPATH_W) 'gnunet-service-transport_validation.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_validation.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_validation.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_validation.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_validation.c' object='gnunet_service_transport-gnunet-service-transport_validation.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_validation.obj `if test -f 'gnunet-service-transport_validation.c'; then $(CYGPATH_W) 'gnunet-service-transport_validation.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_validation.c'; fi` gnunet_service_transport-gnunet-service-transport_manipulation.o: gnunet-service-transport_manipulation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_manipulation.o -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_manipulation.Tpo -c -o gnunet_service_transport-gnunet-service-transport_manipulation.o `test -f 'gnunet-service-transport_manipulation.c' || echo '$(srcdir)/'`gnunet-service-transport_manipulation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_manipulation.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_manipulation.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_manipulation.c' object='gnunet_service_transport-gnunet-service-transport_manipulation.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_manipulation.o `test -f 'gnunet-service-transport_manipulation.c' || echo '$(srcdir)/'`gnunet-service-transport_manipulation.c gnunet_service_transport-gnunet-service-transport_manipulation.obj: gnunet-service-transport_manipulation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -MT gnunet_service_transport-gnunet-service-transport_manipulation.obj -MD -MP -MF $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_manipulation.Tpo -c -o gnunet_service_transport-gnunet-service-transport_manipulation.obj `if test -f 'gnunet-service-transport_manipulation.c'; then $(CYGPATH_W) 'gnunet-service-transport_manipulation.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_manipulation.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_manipulation.Tpo $(DEPDIR)/gnunet_service_transport-gnunet-service-transport_manipulation.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-transport_manipulation.c' object='gnunet_service_transport-gnunet-service-transport_manipulation.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_transport_CFLAGS) $(CFLAGS) -c -o gnunet_service_transport-gnunet-service-transport_manipulation.obj `if test -f 'gnunet-service-transport_manipulation.c'; then $(CYGPATH_W) 'gnunet-service-transport_manipulation.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-transport_manipulation.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_transport_testing_startstop.log: test_transport_testing_startstop$(EXEEXT) @p='test_transport_testing_startstop$(EXEEXT)'; \ b='test_transport_testing_startstop'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_testing_restart.log: test_transport_testing_restart$(EXEEXT) @p='test_transport_testing_restart$(EXEEXT)'; \ b='test_transport_testing_restart'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_testing.log: test_transport_testing$(EXEEXT) @p='test_transport_testing$(EXEEXT)'; \ b='test_transport_testing'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_startonly.log: test_transport_startonly$(EXEEXT) @p='test_transport_startonly$(EXEEXT)'; \ b='test_transport_startonly'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_tcp.log: test_plugin_tcp$(EXEEXT) @p='test_plugin_tcp$(EXEEXT)'; \ b='test_plugin_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_udp.log: test_plugin_udp$(EXEEXT) @p='test_plugin_udp$(EXEEXT)'; \ b='test_plugin_udp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_unix.log: test_plugin_unix$(EXEEXT) @p='test_plugin_unix$(EXEEXT)'; \ b='test_plugin_unix'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_wlan.log: test_plugin_wlan$(EXEEXT) @p='test_plugin_wlan$(EXEEXT)'; \ b='test_plugin_wlan'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_bluetooth.log: test_plugin_bluetooth$(EXEEXT) @p='test_plugin_bluetooth$(EXEEXT)'; \ b='test_plugin_bluetooth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_blacklisting.log: test_transport_api_blacklisting$(EXEEXT) @p='test_transport_api_blacklisting$(EXEEXT)'; \ b='test_transport_api_blacklisting'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_disconnect_tcp.log: test_transport_api_disconnect_tcp$(EXEEXT) @p='test_transport_api_disconnect_tcp$(EXEEXT)'; \ b='test_transport_api_disconnect_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_bidirectional_connect.log: test_transport_api_bidirectional_connect$(EXEEXT) @p='test_transport_api_bidirectional_connect$(EXEEXT)'; \ b='test_transport_api_bidirectional_connect'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_tcp.log: test_transport_api_tcp$(EXEEXT) @p='test_transport_api_tcp$(EXEEXT)'; \ b='test_transport_api_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_restart_1peer.log: test_transport_api_restart_1peer$(EXEEXT) @p='test_transport_api_restart_1peer$(EXEEXT)'; \ b='test_transport_api_restart_1peer'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_restart_2peers.log: test_transport_api_restart_2peers$(EXEEXT) @p='test_transport_api_restart_2peers$(EXEEXT)'; \ b='test_transport_api_restart_2peers'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_timeout_tcp.log: test_transport_api_timeout_tcp$(EXEEXT) @p='test_transport_api_timeout_tcp$(EXEEXT)'; \ b='test_transport_api_timeout_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_limited_sockets_tcp.log: test_transport_api_limited_sockets_tcp$(EXEEXT) @p='test_transport_api_limited_sockets_tcp$(EXEEXT)'; \ b='test_transport_api_limited_sockets_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_tcp_nat.log: test_transport_api_tcp_nat$(EXEEXT) @p='test_transport_api_tcp_nat$(EXEEXT)'; \ b='test_transport_api_tcp_nat'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_udp.log: test_transport_api_udp$(EXEEXT) @p='test_transport_api_udp$(EXEEXT)'; \ b='test_transport_api_udp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_timeout_udp.log: test_transport_api_timeout_udp$(EXEEXT) @p='test_transport_api_timeout_udp$(EXEEXT)'; \ b='test_transport_api_timeout_udp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_unix.log: test_transport_api_unix$(EXEEXT) @p='test_transport_api_unix$(EXEEXT)'; \ b='test_transport_api_unix'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_timeout_unix.log: test_transport_api_timeout_unix$(EXEEXT) @p='test_transport_api_timeout_unix$(EXEEXT)'; \ b='test_transport_api_timeout_unix'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_unix_abstract.log: test_transport_api_unix_abstract$(EXEEXT) @p='test_transport_api_unix_abstract$(EXEEXT)'; \ b='test_transport_api_unix_abstract'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_udp_nat.log: test_transport_api_udp_nat$(EXEEXT) @p='test_transport_api_udp_nat$(EXEEXT)'; \ b='test_transport_api_udp_nat'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_http.log: test_transport_api_http$(EXEEXT) @p='test_transport_api_http$(EXEEXT)'; \ b='test_transport_api_http'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_timeout_http.log: test_transport_api_timeout_http$(EXEEXT) @p='test_transport_api_timeout_http$(EXEEXT)'; \ b='test_transport_api_timeout_http'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_https.log: test_transport_api_https$(EXEEXT) @p='test_transport_api_https$(EXEEXT)'; \ b='test_transport_api_https'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_timeout_https.log: test_transport_api_timeout_https$(EXEEXT) @p='test_transport_api_timeout_https$(EXEEXT)'; \ b='test_transport_api_timeout_https'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_wlan.log: test_transport_api_wlan$(EXEEXT) @p='test_transport_api_wlan$(EXEEXT)'; \ b='test_transport_api_wlan'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_timeout_wlan.log: test_transport_api_timeout_wlan$(EXEEXT) @p='test_transport_api_timeout_wlan$(EXEEXT)'; \ b='test_transport_api_timeout_wlan'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_bluetooth.log: test_transport_api_bluetooth$(EXEEXT) @p='test_transport_api_bluetooth$(EXEEXT)'; \ b='test_transport_api_bluetooth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_timeout_bluetooth.log: test_transport_api_timeout_bluetooth$(EXEEXT) @p='test_transport_api_timeout_bluetooth$(EXEEXT)'; \ b='test_transport_api_timeout_bluetooth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_multi.log: test_transport_api_multi$(EXEEXT) @p='test_transport_api_multi$(EXEEXT)'; \ b='test_transport_api_multi'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_monitoring.log: test_transport_api_monitoring$(EXEEXT) @p='test_transport_api_monitoring$(EXEEXT)'; \ b='test_transport_api_monitoring'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_monitoring_validation.log: test_transport_api_monitoring_validation$(EXEEXT) @p='test_transport_api_monitoring_validation$(EXEEXT)'; \ b='test_transport_api_monitoring_validation'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_blacklisting_no_bl.log: test_transport_blacklisting_no_bl$(EXEEXT) @p='test_transport_blacklisting_no_bl$(EXEEXT)'; \ b='test_transport_blacklisting_no_bl'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_blacklisting_outbound_bl_full.log: test_transport_blacklisting_outbound_bl_full$(EXEEXT) @p='test_transport_blacklisting_outbound_bl_full$(EXEEXT)'; \ b='test_transport_blacklisting_outbound_bl_full'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_blacklisting_outbound_bl_plugin.log: test_transport_blacklisting_outbound_bl_plugin$(EXEEXT) @p='test_transport_blacklisting_outbound_bl_plugin$(EXEEXT)'; \ b='test_transport_blacklisting_outbound_bl_plugin'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_blacklisting_inbound_bl_plugin.log: test_transport_blacklisting_inbound_bl_plugin$(EXEEXT) @p='test_transport_blacklisting_inbound_bl_plugin$(EXEEXT)'; \ b='test_transport_blacklisting_inbound_bl_plugin'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_blacklisting_inbound_bl_full.log: test_transport_blacklisting_inbound_bl_full$(EXEEXT) @p='test_transport_blacklisting_inbound_bl_full$(EXEEXT)'; \ b='test_transport_blacklisting_inbound_bl_full'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_blacklisting_multiple_plugins.log: test_transport_blacklisting_multiple_plugins$(EXEEXT) @p='test_transport_blacklisting_multiple_plugins$(EXEEXT)'; \ b='test_transport_blacklisting_multiple_plugins'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_manipulation_send_tcp.log: test_transport_api_manipulation_send_tcp$(EXEEXT) @p='test_transport_api_manipulation_send_tcp$(EXEEXT)'; \ b='test_transport_api_manipulation_send_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_manipulation_recv_tcp.log: test_transport_api_manipulation_recv_tcp$(EXEEXT) @p='test_transport_api_manipulation_recv_tcp$(EXEEXT)'; \ b='test_transport_api_manipulation_recv_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_manipulation_cfg.log: test_transport_api_manipulation_cfg$(EXEEXT) @p='test_transport_api_manipulation_cfg$(EXEEXT)'; \ b='test_transport_api_manipulation_cfg'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_reliability_tcp.log: test_transport_api_reliability_tcp$(EXEEXT) @p='test_transport_api_reliability_tcp$(EXEEXT)'; \ b='test_transport_api_reliability_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_reliability_tcp_nat.log: test_transport_api_reliability_tcp_nat$(EXEEXT) @p='test_transport_api_reliability_tcp_nat$(EXEEXT)'; \ b='test_transport_api_reliability_tcp_nat'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_unreliability_udp.log: test_transport_api_unreliability_udp$(EXEEXT) @p='test_transport_api_unreliability_udp$(EXEEXT)'; \ b='test_transport_api_unreliability_udp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_unreliability_constant_udp.log: test_transport_api_unreliability_constant_udp$(EXEEXT) @p='test_transport_api_unreliability_constant_udp$(EXEEXT)'; \ b='test_transport_api_unreliability_constant_udp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_unreliability_unix.log: test_transport_api_unreliability_unix$(EXEEXT) @p='test_transport_api_unreliability_unix$(EXEEXT)'; \ b='test_transport_api_unreliability_unix'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_reliability_http.log: test_transport_api_reliability_http$(EXEEXT) @p='test_transport_api_reliability_http$(EXEEXT)'; \ b='test_transport_api_reliability_http'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_reliability_https.log: test_transport_api_reliability_https$(EXEEXT) @p='test_transport_api_reliability_https$(EXEEXT)'; \ b='test_transport_api_reliability_https'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_reliability_wlan.log: test_transport_api_reliability_wlan$(EXEEXT) @p='test_transport_api_reliability_wlan$(EXEEXT)'; \ b='test_transport_api_reliability_wlan'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_unreliability_wlan.log: test_transport_api_unreliability_wlan$(EXEEXT) @p='test_transport_api_unreliability_wlan$(EXEEXT)'; \ b='test_transport_api_unreliability_wlan'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_reliability_bluetooth.log: test_transport_api_reliability_bluetooth$(EXEEXT) @p='test_transport_api_reliability_bluetooth$(EXEEXT)'; \ b='test_transport_api_reliability_bluetooth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_api_unreliability_bluetooth.log: test_transport_api_unreliability_bluetooth$(EXEEXT) @p='test_transport_api_unreliability_bluetooth$(EXEEXT)'; \ b='test_transport_api_unreliability_bluetooth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_tcp.log: test_quota_compliance_tcp$(EXEEXT) @p='test_quota_compliance_tcp$(EXEEXT)'; \ b='test_quota_compliance_tcp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_tcp_asymmetric.log: test_quota_compliance_tcp_asymmetric$(EXEEXT) @p='test_quota_compliance_tcp_asymmetric$(EXEEXT)'; \ b='test_quota_compliance_tcp_asymmetric'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_udp.log: test_quota_compliance_udp$(EXEEXT) @p='test_quota_compliance_udp$(EXEEXT)'; \ b='test_quota_compliance_udp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_unix.log: test_quota_compliance_unix$(EXEEXT) @p='test_quota_compliance_unix$(EXEEXT)'; \ b='test_quota_compliance_unix'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_unix_asymmetric.log: test_quota_compliance_unix_asymmetric$(EXEEXT) @p='test_quota_compliance_unix_asymmetric$(EXEEXT)'; \ b='test_quota_compliance_unix_asymmetric'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_http.log: test_quota_compliance_http$(EXEEXT) @p='test_quota_compliance_http$(EXEEXT)'; \ b='test_quota_compliance_http'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_http_asymmetric.log: test_quota_compliance_http_asymmetric$(EXEEXT) @p='test_quota_compliance_http_asymmetric$(EXEEXT)'; \ b='test_quota_compliance_http_asymmetric'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_https.log: test_quota_compliance_https$(EXEEXT) @p='test_quota_compliance_https$(EXEEXT)'; \ b='test_quota_compliance_https'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_quota_compliance_https_asymmetric.log: test_quota_compliance_https_asymmetric$(EXEEXT) @p='test_quota_compliance_https_asymmetric$(EXEEXT)'; \ b='test_quota_compliance_https_asymmetric'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstPROGRAMS clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-exec-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstPROGRAMS clean-pluginLTLIBRARIES cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-exec-hook install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES @LINUX_TRUE@install-exec-hook: @LINUX_TRUE@ $(top_srcdir)/src/transport/install-wlan-helper.sh $(libexecdir) $(SUDO_BINARY) || true @LINUX_FALSE@install-exec-hook: @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@install-exec-hook2: @HAVE_LIBBLUETOOTH_TRUE@@LINUX_TRUE@ $(top_srcdir)/src/transport/install-bluetooth-helper.sh $(libexecdir) $(SUDO_BINARY) || true @LINUX_FALSE@install-exec-hook2: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/transport/test_transport_blacklisting_cfg_blp_peer1_full.conf0000644000175000017500000000141712236654562025135 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] #PREFIX = valgrind --leak-check=full PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PLUGINS = tcp [transport-blacklist-6ULBJK6QQJ64FAG9DF0292AS5IA9CCAC04IQU0HF8THM635HMBBG] DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50 = gnunet-0.10.1/src/transport/test_transport_api_tcp_peer1.conf0000644000175000017500000000114712225230043021366 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PLUGINS = tcp gnunet-0.10.1/src/transport/template_cfg_peer1.conf0000644000175000017500000000165112225230043017226 00000000000000@INLINE@ test_transport_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [nat] RETURN_LOCAL_ADDRESSES = YES DISABLEV6 = NO [transport-tcp] PORT = 12000 TIMEOUT = 5 s [transport-udp] BROADCAST = NO [transport-unix] PORT = 12007 [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock USE_INCLUDED_HELLOS = NO [transport] #PREFIX = valgrind --leak-check=full PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [ats] WAN_QUOTA_IN = unlimited WAN_QUOTA_OUT = unlimited PORT = 12006 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-ats.sock [hostlist] SERVERS = dummygnunet-0.10.1/src/transport/test_transport_api_unreliability_bluetooth_peer1.conf0000644000175000017500000000114112225230043025533 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p1/ [transport-bluetooth] INTERFACE = hci0 TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/transport-testing.c0000644000175000017500000005175512255010511016515 00000000000000/* This file is part of GNUnet. (C) 2006, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport-testing.c * @brief testing lib for transport service * * @author Matthias Wachs */ #include "transport-testing.h" static struct PeerContext * find_peer_context (struct GNUNET_TRANSPORT_TESTING_handle *tth, const struct GNUNET_PeerIdentity *peer) { GNUNET_assert (tth != NULL); struct PeerContext *t = tth->p_head; while (t != NULL) { if (0 == memcmp (&t->id, peer, sizeof (struct GNUNET_PeerIdentity))) break; t = t->next; } return t; } static struct ConnectingContext * find_connecting_context (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p1, struct PeerContext *p2) { GNUNET_assert (tth != NULL); struct ConnectingContext *cc = tth->cc_head; while (cc != NULL) { if ((cc->p1 == p1) && (cc->p2 == p2)) break; if ((cc->p1 == p2) && (cc->p2 == p1)) break; cc = cc->next; } return cc; } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *p2_s; struct PeerContext *p2; GNUNET_assert (NULL != p); GNUNET_assert (NULL != p->tth); p2 = find_peer_context (p->tth, peer); if (p->nc != NULL) p->nc (p->cb_cls, peer); if (p2 != NULL) GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, GNUNET_i2s (&p2->id)); else GNUNET_asprintf (&p2_s, "`%s'", GNUNET_i2s (peer)); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Peers %s connected to peer %u (`%s')\n", p2_s, p->no, GNUNET_i2s (&p->id)); GNUNET_free (p2_s); /* Find ConnectingContext */ struct ConnectingContext *cc = find_connecting_context (p->tth, p, p2); if (cc == NULL) return; if (p == cc->p1) cc->p1_c = GNUNET_YES; if (p == cc->p2) cc->p2_c = GNUNET_YES; if ((cc->p1_c == GNUNET_YES) && (cc->p2_c == GNUNET_YES)) { cc->cb (cc->p1, cc->p2, cc->cb_cls); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (p->tth, cc); } } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; /* Find PeerContext */ int no = 0; struct PeerContext *p2 = NULL; if (p != NULL) { GNUNET_assert (p->tth != NULL); p2 = find_peer_context (p->tth, peer); no = p->no; } char *p2_s; if (p2 != NULL) GNUNET_asprintf (&p2_s, "%u (`%s')", p2->no, GNUNET_i2s (&p2->id)); else GNUNET_asprintf (&p2_s, "`%s'", GNUNET_i2s (peer)); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Peers %s disconnected from peer %u (`%s')\n", p2_s, no, GNUNET_i2s (&p->id)); GNUNET_free (p2_s); if (p == NULL) return; if (p->nd != NULL) p->nd (p->cb_cls, peer); } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; if (p == NULL) return; if (p->rec != NULL) p->rec (p->cb_cls, peer, message); } static void get_hello (void *cb_cls, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cb_cls; struct GNUNET_PeerIdentity hello_id; GNUNET_assert (message != NULL); GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) message, &hello_id)); GNUNET_assert (0 == memcmp (&hello_id, &p->id, sizeof (hello_id))); GNUNET_free_non_null (p->hello); p->hello = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (message); if (NULL != p->start_cb) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Peer %u (`%s') successfully started\n", p->no, GNUNET_i2s (&p->id)); p->start_cb (p, p->cb_cls); p->start_cb = NULL; } } static void try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ConnectingContext *cc = cls; struct PeerContext *p1 = cc->p1; struct PeerContext *p2 = cc->p2; cc->tct = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; GNUNET_assert (cc != NULL); GNUNET_assert (cc->p1 != NULL); GNUNET_assert (cc->p2 != NULL); char *p2_s = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Asking peer %u (`%s') to connect peer %u (`%s'), providing HELLO with %u bytes\n", p1->no, GNUNET_i2s (&p1->id), p2->no, p2_s, GNUNET_HELLO_size (cc->p2->hello)); GNUNET_free (p2_s); GNUNET_TRANSPORT_offer_hello (cc->th_p1, (const struct GNUNET_MessageHeader *) cc-> p2->hello, NULL, NULL); GNUNET_TRANSPORT_try_connect (cc->th_p1, &p2->id, NULL, NULL); /*FIXME TRY_CONNECT change */ cc->tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &try_connect, cc); } /** * Start a peer with the given configuration * @param tth the testing handle * @param cfgname configuration file * @param peer_id a unique number to identify the peer * @param rec receive callback * @param nc connect callback * @param nd disconnect callback * @param start_cb start callback * @param cb_cls closure for callback * @return the peer context */ struct PeerContext * GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth, const char *cfgname, int peer_id, GNUNET_TRANSPORT_ReceiveCallback rec, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd, GNUNET_TRANSPORT_TESTING_start_cb start_cb, void *cb_cls) { char *emsg = NULL; struct GNUNET_PeerIdentity *dummy; GNUNET_assert (NULL != tth); GNUNET_assert (NULL != tth->tl_system); if (GNUNET_DISK_file_test (cfgname) == GNUNET_NO) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "File not found: `%s' \n", cfgname); return NULL; } struct PeerContext *p = GNUNET_new (struct PeerContext); GNUNET_CONTAINER_DLL_insert (tth->p_head, tth->p_tail, p); /* Create configuration and call testing lib to modify it */ p->cfg = GNUNET_CONFIGURATION_create (); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); if (GNUNET_SYSERR == GNUNET_TESTING_configuration_create (tth->tl_system, p->cfg)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Testing library failed to create unique configuration based on `%s'\n", cfgname); GNUNET_free (p); return NULL; } p->no = peer_id; /* Configure peer with configuration */ p->peer = GNUNET_TESTING_peer_configure (tth->tl_system, p->cfg, p->no, NULL, &emsg); if (NULL == p->peer) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Testing library failed to create unique configuration based on `%s': `%s'\n", cfgname, emsg); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); GNUNET_free_non_null (emsg); return NULL; } GNUNET_free_non_null (emsg); if (GNUNET_OK != GNUNET_TESTING_peer_start (p->peer)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Testing library failed to create unique configuration based on `%s'\n", cfgname); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); return NULL; } memset(&dummy, '\0', sizeof (dummy)); GNUNET_TESTING_peer_get_identity (p->peer, &p->id); if (0 == memcmp (&dummy, &p->id, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Testing library failed to obtain peer identity for peer %u\n", p->no); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); return NULL; } else { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Peer %u configured with identity `%s'\n", p->no, GNUNET_i2s_full (&p->id)); } p->tth = tth; p->nc = nc; p->nd = nd; p->rec = rec; p->start_cb = start_cb; if (cb_cls != NULL) p->cb_cls = cb_cls; else p->cb_cls = p; p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, ¬ify_receive, ¬ify_connect, ¬ify_disconnect); if (NULL == p->th) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Failed to connect to transport service for peer `%s': `%s'\n", cfgname, emsg); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); return NULL; } p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &get_hello, p); GNUNET_assert (p->ghh != NULL); return p; } /** * Restart the given peer * @param tth testing handle * @param p the peer * @param cfgname the cfg file used to restart * @param restart_cb callback to call when restarted * @param cb_cls callback closure * @return GNUNET_OK in success otherwise GNUNET_SYSERR */ int GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p, const char *cfgname, GNUNET_TRANSPORT_TESTING_start_cb restart_cb, void *cb_cls) { GNUNET_assert (tth != NULL); GNUNET_assert (p != NULL); GNUNET_assert (NULL != p->peer); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Restarting peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); /* shutdown */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Stopping peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); if (NULL != p->ghh) GNUNET_TRANSPORT_get_hello_cancel (p->ghh); p->ghh = NULL; if (NULL != p->th) GNUNET_TRANSPORT_disconnect (p->th); if (GNUNET_SYSERR == GNUNET_TESTING_peer_stop(p->peer)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Failed to stop peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); return GNUNET_SYSERR; } sleep (5); /* restart */ if (GNUNET_SYSERR == GNUNET_TESTING_peer_start(p->peer)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Failed to restart peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id)); return GNUNET_SYSERR; } GNUNET_assert (p->th != NULL); GNUNET_assert (p->start_cb == NULL); p->start_cb = restart_cb; p->cb_cls = cb_cls; p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, ¬ify_receive, ¬ify_connect, ¬ify_disconnect); GNUNET_assert (NULL != p->th); p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &get_hello, p); GNUNET_assert (p->ghh != NULL); return GNUNET_OK; } /** * shutdown the given peer * @param tth testing handle * @param p the peer */ void GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p) { GNUNET_assert (p != NULL); if (p->ghh != NULL) { GNUNET_TRANSPORT_get_hello_cancel (p->ghh); p->ghh = NULL; } if (p->th != NULL) { GNUNET_TRANSPORT_disconnect (p->th); p->th = NULL; } if (p->peer != NULL) { if (GNUNET_OK != GNUNET_TESTING_peer_stop (p->peer)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Testing lib failed to stop peer %u (`%s') \n", p->no, GNUNET_i2s (&p->id)); } GNUNET_TESTING_peer_destroy (p->peer); p->peer = NULL; } if (p->hello != NULL) { GNUNET_free (p->hello); p->hello = NULL; } if (p->cfg != NULL) { GNUNET_CONFIGURATION_destroy (p->cfg); p->cfg = NULL; } GNUNET_CONTAINER_DLL_remove (tth->p_head, tth->p_tail, p); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Peer %u (`%s') stopped \n", p->no, GNUNET_i2s (&p->id)); GNUNET_free (p); } /** * Initiate a connection from p1 to p2 by offering p1 p2's HELLO message * * Remarks: start_peer's notify_connect callback can be called before. * * @param tth transport testing handle * @param p1 peer 1 * @param p2 peer 2 * @param cb the callback to call when both peers notified that they are connected * @param cls callback cls * @return a connect request handle */ GNUNET_TRANSPORT_TESTING_ConnectRequest GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_handle *tth, struct PeerContext *p1, struct PeerContext *p2, GNUNET_TRANSPORT_TESTING_connect_cb cb, void *cls) { GNUNET_assert (tth != NULL); struct ConnectingContext *cc = GNUNET_new (struct ConnectingContext); GNUNET_assert (p1 != NULL); GNUNET_assert (p2 != NULL); cc->p1 = p1; cc->p2 = p2; cc->cb = cb; if (cls != NULL) cc->cb_cls = cls; else cc->cb_cls = cc; cc->th_p1 = p1->th; cc->th_p2 = p2->th; GNUNET_assert (cc->th_p1 != NULL); GNUNET_assert (cc->th_p2 != NULL); GNUNET_CONTAINER_DLL_insert (tth->cc_head, tth->cc_tail, cc); cc->tct = GNUNET_SCHEDULER_add_now (&try_connect, cc); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "New connect request %p\n", cc); return cc; } /** * Cancel the request to connect two peers * Tou MUST cancel the request if you stop the peers before the peers connected succesfully * * @param tth transport testing handle * @param ccr a connect request handle */ void GNUNET_TRANSPORT_TESTING_connect_peers_cancel (struct GNUNET_TRANSPORT_TESTING_handle *tth, GNUNET_TRANSPORT_TESTING_ConnectRequest ccr) { struct ConnectingContext *cc = ccr; GNUNET_assert (tth != NULL); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing", "Canceling connect request %p!\n", cc); if (cc->tct != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (cc->tct); cc->tct = GNUNET_SCHEDULER_NO_TASK; GNUNET_CONTAINER_DLL_remove (tth->cc_head, tth->cc_tail, cc); GNUNET_free (cc); } /** * Clean up the transport testing * @param tth transport testing handle */ void GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_handle *tth) { struct ConnectingContext *cc = tth->cc_head; struct ConnectingContext *ct = NULL; struct PeerContext *p = tth->p_head; struct PeerContext *t = NULL; GNUNET_assert (tth != NULL); while (cc != tth->cc_tail) { ct = cc->next; GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Developer forgot to cancel connect request %p!\n", cc); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = ct; } while (p != NULL) { t = p->next; GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "transport-testing", "Developer forgot to stop peer!\n"); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); p = t; } GNUNET_TESTING_system_destroy (tth->tl_system, GNUNET_YES); GNUNET_free (tth); tth = NULL; } /** * Initialize the transport testing * @return transport testing handle */ struct GNUNET_TRANSPORT_TESTING_handle * GNUNET_TRANSPORT_TESTING_init () { struct GNUNET_TRANSPORT_TESTING_handle *tth; /* prepare hostkeys */ tth = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_handle); /* Init testing the testing lib */ tth->tl_system = GNUNET_TESTING_system_create ("transport-testing", NULL, NULL, NULL); if (NULL == tth->tl_system) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize testing library!\n")); GNUNET_free (tth); return NULL; } return tth; } /* * Some utility functions */ /** * Removes all directory separators from absolute filename * @param file the absolute file name, e.g. as found in argv[0] * @return extracted file name, has to be freed by caller */ static char * extract_filename (const char *file) { char *pch = GNUNET_strdup (file); char *backup = pch; char *filename = NULL; char *res; #if WINDOWS if ((strlen (pch) >= 3) && pch[1] == ':') { if (NULL != strstr (pch, "\\")) { pch = strtok (pch, "\\"); while (pch != NULL) { pch = strtok (NULL, "\\"); if (pch != NULL) filename = pch; } } } if (filename != NULL) pch = filename; /* If we miss the next condition, filename = pch will * not harm us. */ #endif if (NULL != strstr (pch, "/")) { pch = strtok (pch, "/"); while (pch != NULL) { pch = strtok (NULL, "/"); if (pch != NULL) { filename = pch; } } } else filename = pch; res = GNUNET_strdup (filename); GNUNET_free (backup); return res; } /** * Extracts the test filename from an absolute file name and removes the extension * @param file absolute file name * @param dest where to store result */ void GNUNET_TRANSPORT_TESTING_get_test_name (const char *file, char **dest) { char *filename = extract_filename (file); char *backup = filename; char *dotexe; if (filename == NULL) goto fail; /* remove "lt-" */ filename = strstr (filename, "tes"); if (filename == NULL) goto fail; /* remove ".exe" */ if (NULL != (dotexe = strstr (filename, ".exe"))) dotexe[0] = '\0'; goto suc; fail: (*dest) = NULL; return; suc: /* create filename */ GNUNET_asprintf (dest, "%s", filename); GNUNET_free (backup); } /** * Extracts the filename from an absolute file name and removes the extension * @param file absolute file name * @param dest where to store result */ void GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file, char **dest) { char *src = extract_filename (file); char *split; split = strstr (src, "."); if (split != NULL) { split[0] = '\0'; } GNUNET_asprintf (dest, "%s", src); GNUNET_free (src); } /** * Extracts the plugin name from an absolute file name and the test name * * @param file absolute file name * @param test test name * @param dest where to store result */ void GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *file, const char *test, char **dest) { char *filename; char *dotexe; char *e = extract_filename (file); char *t = extract_filename (test); if (NULL == e) goto fail; /* remove "lt-" */ filename = strstr (e, "tes"); if (NULL == filename) goto fail; /* remove ".exe" */ if (NULL != (dotexe = strstr (filename, ".exe"))) dotexe[0] = '\0'; /* find last _ */ filename = strstr (filename, t); if (NULL == filename) goto fail; /* copy plugin */ filename += strlen (t); if ('\0' != *filename) filename++; GNUNET_asprintf (dest, "%s", filename); goto suc; fail: (*dest) = NULL; suc: GNUNET_free (t); GNUNET_free (e); } /** * This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and * if existing ".exe"-prefix and adds the peer-number * * @param file filename of the test, e.g. argv[0] * @param dest where to write the filename * @param count peer number */ void GNUNET_TRANSPORT_TESTING_get_config_name (const char *file, char **dest, int count) { char *filename = extract_filename (file); char *backup = filename; char *dotexe; if (NULL == filename) goto fail; /* remove "lt-" */ filename = strstr (filename, "tes"); if (NULL == filename) goto fail; /* remove ".exe" */ if (NULL != (dotexe = strstr (filename, ".exe"))) dotexe[0] = '\0'; GNUNET_asprintf (dest, "%s_peer%u.conf", filename, count); GNUNET_free (backup); return; fail: (*dest) = NULL; GNUNET_free (backup); } /* end of transport-testing.c */ gnunet-0.10.1/src/transport/test_http_common.c0000644000175000017500000001505012225777502016401 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_http_common.c * @brief base test case for common http functionality */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" #include "plugin_transport_http_common.h" struct SplittedHTTPAddress { char *protocol; char *host; char *path; int port; }; void clean (struct SplittedHTTPAddress *addr) { if (NULL != addr) { GNUNET_free_non_null (addr->host); GNUNET_free_non_null (addr->path); GNUNET_free_non_null (addr->protocol); GNUNET_free_non_null (addr); } } int check (struct SplittedHTTPAddress *addr, char * protocol, char * host, int port, char * path) { if (NULL == addr) return GNUNET_NO; if (((NULL == addr->protocol) && (NULL != protocol)) || ((NULL != addr->protocol) && (NULL == protocol))) { GNUNET_break (0); return GNUNET_NO; } else if ((NULL != addr->protocol) && (NULL != protocol)) { if (0 != strcmp(addr->protocol, protocol)) { GNUNET_break (0); return GNUNET_NO; } } if (((NULL == addr->host) && (NULL != host)) || ((NULL != addr->host) && (NULL == host))) { GNUNET_break (0); return GNUNET_NO; } else if ((NULL != addr->host) && (NULL != host)) { if (0 != strcmp(addr->host, host)) { GNUNET_break (0); return GNUNET_NO; } } if (((NULL == addr->path) && (NULL != path)) || ((NULL != addr->path) && (NULL == path))) { GNUNET_break (0); return GNUNET_NO; } else if ((NULL != addr->path) && (NULL != path)) { if (0 != strcmp(addr->path, path)) { GNUNET_break (0); return GNUNET_NO; } } if ((addr->port != port)) { GNUNET_break (0); return GNUNET_NO; } return GNUNET_OK; } int check_pass (char *src, char * protocol, char * host, int port, char * path) { struct SplittedHTTPAddress * spa; spa = http_split_address (src); if (NULL == spa) { GNUNET_break (0); return GNUNET_SYSERR; } else { if (GNUNET_OK != check(spa, protocol, host, port, path)) { clean (spa); GNUNET_break (0); return GNUNET_SYSERR; } clean (spa); } return GNUNET_OK; } int check_fail (char *src) { struct SplittedHTTPAddress * spa; spa = http_split_address (src); if (NULL != spa) { GNUNET_break (0); clean (spa); return GNUNET_SYSERR; } return GNUNET_OK; } void test_pass_hostname () { check_pass("http://test.local", "http", "test.local", HTTP_DEFAULT_PORT, ""); check_pass("http://test.local/", "http", "test.local", HTTP_DEFAULT_PORT, "/"); check_pass("http://test.local/path", "http", "test.local", HTTP_DEFAULT_PORT, "/path"); check_pass("http://test.local/path/", "http", "test.local", HTTP_DEFAULT_PORT, "/path/"); check_pass("http://test.local/path/more", "http", "test.local", HTTP_DEFAULT_PORT, "/path/more"); check_pass("http://test.local:81", "http", "test.local", 81, ""); check_pass("http://test.local:81/", "http", "test.local", 81, "/"); check_pass("http://test.local:81/path", "http", "test.local", 81, "/path"); check_pass("http://test.local:81/path/", "http", "test.local", 81, "/path/"); check_pass("http://test.local:81/path/more", "http", "test.local", 81, "/path/more"); } void test_pass_ipv4 () { check_pass("http://127.0.0.1", "http", "127.0.0.1", HTTP_DEFAULT_PORT, ""); check_pass("http://127.0.0.1/", "http", "127.0.0.1", HTTP_DEFAULT_PORT, "/"); check_pass("http://127.0.0.1/path", "http", "127.0.0.1", HTTP_DEFAULT_PORT, "/path"); check_pass("http://127.0.0.1/path/", "http", "127.0.0.1", HTTP_DEFAULT_PORT, "/path/"); check_pass("http://127.0.0.1:81", "http", "127.0.0.1", 81, ""); check_pass("http://127.0.0.1:81/", "http", "127.0.0.1", 81, "/"); check_pass("http://127.0.0.1:81/path", "http", "127.0.0.1", 81, "/path"); check_pass("http://127.0.0.1:81/path/", "http", "127.0.0.1", 81, "/path/"); check_pass("http://127.0.0.1:81/path/more", "http", "127.0.0.1", 81, "/path/more"); } void test_fail_ipv6 () { check_pass("http://[::1]", "http", "[::1]", HTTP_DEFAULT_PORT, ""); check_pass("http://[::1]/", "http", "[::1]", HTTP_DEFAULT_PORT, "/"); check_pass("http://[::1]/path", "http", "[::1]", HTTP_DEFAULT_PORT, "/path"); check_pass("http://[::1]/path/", "http", "[::1]", HTTP_DEFAULT_PORT, "/path/"); check_pass("http://[::1]:81", "http", "[::1]", 81, ""); check_pass("http://[::1]:81/", "http", "[::1]", 81, "/"); check_pass("http://[::1]:81/path", "http", "[::1]", 81, "/path"); check_pass("http://[::1]:81/path/", "http", "[::1]", 81, "/path/"); check_pass("http://[::1]:81/path/more", "http", "[::1]", 81, "/path/more"); } void test_fail () { if (GNUNET_SYSERR == check_fail ("")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("http")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("://")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("http://")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("//localhost")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("//:80")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("//:80/")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("//:80:")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("http://localhost:a/")) GNUNET_break (0); if (GNUNET_SYSERR == check_fail ("http://127.0.0.1:a/")) GNUNET_break (0); } int main (int argc, char *argv[]) { int ret = 0; struct SplittedHTTPAddress * spa; GNUNET_log_setup ("test", "DEBUG", NULL); spa = http_split_address (""); if (NULL != spa) { clean (spa); GNUNET_break (0); } http_split_address ("http://"); if (NULL != spa) { clean (spa); GNUNET_break (0); } http_split_address ("://"); if (NULL != spa) { clean (spa); GNUNET_break (0); } test_pass_hostname (); test_pass_ipv4 (); test_fail_ipv6 (); test_fail (); return ret; } /* end of test_http_common.c */ gnunet-0.10.1/src/transport/test_transport_api_reliability_tcp_peer1.conf0000644000175000017500000000114712225230043023757 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_timeout_udp_peer2.conf0000644000175000017500000000114012225230043023130 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-p2/ [transport-udp] PORT = 12050 BROADCAST = NO MAX_BPS = 50000000 [arm] PORT = 12055 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12054 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12053 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12052 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12051 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_https_peer2.conf0000644000175000017500000000160012255010511021734 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-https-p2/ [transport-https_server] EXTERNAL_HOSTNAME = localhost EXTERNAL_HOSTNAME_ONLY = yes EXTERNAL_HOSTNAME_USE_PORT = YES #VERIFY_EXTERNAL_HOSTNAME = YES #PORT = 10000 # Does the external hostname use the same port? USE_IPv6 = YES #BINDTO = 127.0.0.1 KEY_FILE = $GNUNET_TEST_HOME/https_key_p2.key CERT_FILE = $GNUNET_TEST_HOME/https_cert_p2.crt [arm] PORT = 12115 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12114 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12113 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12112 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12111 PLUGINS = https_server UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/gnunet-service-transport_validation.h0000644000175000017500000001521112267431203022210 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_validation.h * @brief address validation API * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_VALIDATION_H #define GNUNET_SERVICE_TRANSPORT_VALIDATION_H #include "gnunet_statistics_service.h" #include "gnunet_transport_plugin.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" /** * Function called to notify transport users that a neighbour peer changed its * active address. * * @param cls closure * @param peer peer this update is about (never NULL) * @param address address (never NULL) * @param last_validation point in time when last validation was performed * @param valid_until point in time how long address is valid * @param next_validation point in time when next validation will be performed * @param state state of validation notification */ typedef void (*GST_ValidationChangedCallback) (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state); /** * Start the validation subsystem. * * @param cb callback to call with changes to valdidation entries * @param cb_cls cls for the callback * @param max_fds maximum number of fds to use */ void GST_validation_start (GST_ValidationChangedCallback cb, void *cb_cls, unsigned int max_fds); /** * Stop the validation subsystem. */ void GST_validation_stop (void); /** * Update if we are using an address for a connection actively right now. * Based on this, the validation module will measure latency for the * address more or less often. * * @param address the address * @param session the session * @param in_use GNUNET_YES if we are now using the address for a connection, * GNUNET_NO if we are no longer using the address for a connection */ void GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address, struct Session *session, int in_use); /** * Query validation about the latest observed latency on a given * address. * * @param sender peer * @param address the address * @param session session * @return observed latency of the address, FOREVER if the address was * never successfully validated */ struct GNUNET_TIME_Relative GST_validation_get_address_latency (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_HELLO_Address *address, struct Session *session); /** * Iterate over all iteration entries * * @param cb function to call * @param cb_cls closure for cb */ void GST_validation_iterate (GST_ValidationChangedCallback cb, void *cb_cls); /** * We've received a PING. If appropriate, generate a PONG. * * @param sender peer sending the PING * @param hdr the PING * @param sender_address address of the sender, NULL if we did not initiate * @param session session we got the PING from * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr, const struct GNUNET_HELLO_Address *sender_address, struct Session *session); /** * We've received a PONG. Check if it matches a pending PING and * mark the respective address as confirmed. * * @param sender peer sending the PONG * @param hdr the PONG * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr); /** * We've received a HELLO, check which addresses are new and trigger * validation. * * @param hello the HELLO we received * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello); /** * Function called for each address (or address status change) that * the validation module is aware of (for the given target). * * @param cls closure * @param public_key public key for the peer, never NULL * @param valid_until is ZERO if we never validated the address, * otherwise a time up to when we consider it (or was) valid * @param validation_block is FOREVER if the address is for an unsupported plugin (from PEERINFO) * is ZERO if the address is considered valid (no validation needed) * otherwise a time in the future if we're currently denying re-validation * @param address the address */ typedef void (*GST_ValidationAddressCallback) (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const struct GNUNET_HELLO_Address * address); /** * Call the given function for each address for the given target. * * @param target peer information is requested for * @param cb function to call; will not be called after this function returns * @param cb_cls closure for 'cb' */ void GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target, GST_ValidationAddressCallback cb, void *cb_cls); #endif /* end of file gnunet-service-transport_validation.h */ gnunet-0.10.1/src/transport/test_transport_api_timeout_wlan_peer2.conf0000644000175000017500000000157112255010511023310 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p2/ [transport-wlan] INTERFACE = mon1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock #PREFIX = xterm -T transport2 -e gdb --command=cmd --args #PREFIX = valgrind --leak-check=full --show-reachable=yes --main-stacksize=104857600 #PREFIX = valgrind --leak-check=full --show-reachable=yes #PREFIX = valgrind --leak-check=full #PREFIX = valgrind --tool=massif #PREFIX = gdbserver :2345 gnunet-0.10.1/src/transport/test_transport_api_bidirectional_connect_peer2.conf0000644000175000017500000000141412225230043025117 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [arm] PORT = 12010 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12014 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-tcp] PORT = 12015 TIMEOUT = 5 s [transport-udp] PORT = 12016 TIMEOUT = 5 s [transport-unix] PORT = 12017 TIMEOUT = 5 s [transport-http] PORT = 12018 TIMEOUT = 5 s [transport-https] PORT = 12019 TIMEOUT = 5 s gnunet-0.10.1/src/transport/test_transport_api_bidirectional_connect_peer1.conf0000644000175000017500000000141412225230043025116 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [arm] PORT = 12000 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [transport-tcp] PORT = 12005 TIMEOUT = 5 s [transport-udp] PORT = 12006 TIMEOUT = 5 s [transport-unix] PORT = 12007 TIMEOUT = 5 s [transport-http] PORT = 12008 TIMEOUT = 5 s [transport-https] PORT = 12009 TIMEOUT = 5 s gnunet-0.10.1/src/transport/gnunet-service-transport_hello.c0000644000175000017500000001775612255010511021164 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_hello.c * @brief hello management implementation * @author Christian Grothoff */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_hello_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_statistics_service.h" #include "gnunet-service-transport_hello.h" #include "gnunet-service-transport.h" #include "gnunet-service-transport_plugins.h" /** * How often do we refresh our HELLO (due to expiration concerns)? */ #define HELLO_REFRESH_PERIOD GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6) /** * Hello address expiration */ extern struct GNUNET_TIME_Relative hello_expiration; /** * Entry in linked list of network addresses for ourselves. Also * includes a cached signature for 'struct TransportPongMessage's. */ struct OwnAddressList { /** * This is a doubly-linked list. */ struct OwnAddressList *next; /** * This is a doubly-linked list. */ struct OwnAddressList *prev; /** * The address. */ struct GNUNET_HELLO_Address *address; /** * How long until the current signature expires? (ZERO if the * signature was never created). */ struct GNUNET_TIME_Absolute pong_sig_expires; /** * Signature for a 'struct TransportPongMessage' for this address. */ struct GNUNET_CRYPTO_EddsaSignature pong_signature; }; /** * Our HELLO message. */ static struct GNUNET_HELLO_Message *our_hello; /** * Function to call on HELLO changes. */ static GST_HelloCallback hello_cb; /** * Closure for 'hello_cb'. */ static void *hello_cb_cls; /** * Head of my addresses. */ struct OwnAddressList *oal_head; /** * Tail of my addresses. */ struct OwnAddressList *oal_tail; /** * Identifier of 'refresh_hello' task. */ static GNUNET_SCHEDULER_TaskIdentifier hello_task; /** * Closure for 'address_generator'. */ struct GeneratorContext { /** * Where are we in the DLL? */ struct OwnAddressList *addr_pos; /** * When do addresses expire? */ struct GNUNET_TIME_Absolute expiration; }; /** * Add an address from the 'OwnAddressList' to the buffer. * * @param cls the 'struct GeneratorContext' * @param max maximum number of bytes left * @param buf where to write the address */ static size_t address_generator (void *cls, size_t max, void *buf) { struct GeneratorContext *gc = cls; size_t ret; if (NULL == gc->addr_pos) return 0; ret = GNUNET_HELLO_add_address (gc->addr_pos->address, gc->expiration, buf, max); gc->addr_pos = gc->addr_pos->next; return ret; } /** * Construct our HELLO message from all of the addresses of * all of the transports. * * @param cls unused * @param tc scheduler context */ static void refresh_hello_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GeneratorContext gc; int friend_only; hello_task = GNUNET_SCHEDULER_NO_TASK; gc.addr_pos = oal_head; gc.expiration = GNUNET_TIME_relative_to_absolute (hello_expiration); friend_only = GNUNET_HELLO_is_friend_only (our_hello); GNUNET_free (our_hello); our_hello = GNUNET_HELLO_create (&GST_my_identity.public_key, &address_generator, &gc, friend_only); GNUNET_assert (NULL != our_hello); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Refreshed my %s `%s', new size is %d\n", (GNUNET_YES == GNUNET_HELLO_is_friend_only (our_hello)) ? "friend-only" : "public", "HELLO", GNUNET_HELLO_size (our_hello)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# refreshed my HELLO"), 1, GNUNET_NO); if (NULL != hello_cb) hello_cb (hello_cb_cls, GST_hello_get ()); GNUNET_PEERINFO_add_peer (GST_peerinfo, our_hello, NULL, NULL); hello_task = GNUNET_SCHEDULER_add_delayed (HELLO_REFRESH_PERIOD, &refresh_hello_task, NULL); } /** * Schedule task to refresh hello (unless such a * task exists already). */ static void refresh_hello () { if (hello_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (hello_task); hello_task = GNUNET_SCHEDULER_add_now (&refresh_hello_task, NULL); } /** * Initialize the HELLO module. * * @param friend_only use a friend only hello * @param cb function to call whenever our HELLO changes * @param cb_cls closure for cb */ void GST_hello_start (int friend_only, GST_HelloCallback cb, void *cb_cls) { hello_cb = cb; hello_cb_cls = cb_cls; our_hello = GNUNET_HELLO_create (&GST_my_identity.public_key, NULL, NULL, friend_only); GNUNET_assert (NULL != our_hello); refresh_hello (); } /** * Shutdown the HELLO module. */ void GST_hello_stop () { hello_cb = NULL; hello_cb_cls = NULL; if (GNUNET_SCHEDULER_NO_TASK != hello_task) { GNUNET_SCHEDULER_cancel (hello_task); hello_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != our_hello) { GNUNET_free (our_hello); our_hello = NULL; } } /** * Obtain this peers HELLO message. * * @return our HELLO message */ const struct GNUNET_MessageHeader * GST_hello_get () { return (struct GNUNET_MessageHeader *) our_hello; } /** * Add or remove an address from this peer's HELLO message. * * @param addremove GNUNET_YES to add, GNUNET_NO to remove * @param address address to add or remove */ void GST_hello_modify_addresses (int addremove, const struct GNUNET_HELLO_Address *address) { struct OwnAddressList *al; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, (addremove == GNUNET_YES) ? "Adding `%s' to the set of our addresses\n" : "Removing `%s' from the set of our addresses\n", GST_plugins_a2s (address)); GNUNET_assert (address != NULL); if (GNUNET_NO == addremove) { for (al = oal_head; al != NULL; al = al->next) if (0 == GNUNET_HELLO_address_cmp (address, al->address)) { GNUNET_CONTAINER_DLL_remove (oal_head, oal_tail, al); GNUNET_HELLO_address_free (al->address); GNUNET_free (al); refresh_hello (); return; } /* address to be removed not found!? */ GNUNET_break (0); return; } al = GNUNET_new (struct OwnAddressList); GNUNET_CONTAINER_DLL_insert (oal_head, oal_tail, al); al->address = GNUNET_HELLO_address_copy (address); refresh_hello (); } /** * Test if a particular address is one of ours. * * @param address address to test * @param sig location where to cache PONG signatures for this address [set] * @param sig_expiration how long until the current 'sig' expires? * (ZERO if sig was never created) [set] * @return GNUNET_YES if this is one of our addresses, * GNUNET_NO if not */ int GST_hello_test_address (const struct GNUNET_HELLO_Address *address, struct GNUNET_CRYPTO_EddsaSignature **sig, struct GNUNET_TIME_Absolute **sig_expiration) { struct OwnAddressList *al; for (al = oal_head; al != NULL; al = al->next) if (0 == GNUNET_HELLO_address_cmp (address, al->address)) { *sig = &al->pong_signature; *sig_expiration = &al->pong_sig_expires; return GNUNET_YES; } *sig = NULL; *sig_expiration = NULL; return GNUNET_NO; } /* end of file gnunet-service-transport_hello.c */ gnunet-0.10.1/src/transport/test_transport_api_tcp_peer2.conf0000644000175000017500000000114712225230043021367 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/transport_api_address_to_string.c0000644000175000017500000001333212263473436021477 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_transport_service.h" #include "transport.h" /** * Context for the address lookup. */ struct GNUNET_TRANSPORT_AddressToStringContext { /** * Function to call with the human-readable address. */ GNUNET_TRANSPORT_AddressToStringCallback cb; /** * Closure for cb. */ void *cb_cls; /** * Connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * When should this operation time out? */ struct GNUNET_TIME_Absolute timeout; }; /** * Function called with responses from the service. * * @param cls our 'struct GNUNET_TRANSPORT_AddressLookupContext*' * @param msg NULL on timeout or error, otherwise presumably a * message with the human-readable address */ static void address_response_processor (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_TRANSPORT_AddressToStringContext *alucb = cls; const char *address; uint16_t size; if (msg == NULL) { alucb->cb (alucb->cb_cls, NULL); GNUNET_CLIENT_disconnect (alucb->client); GNUNET_free (alucb); return; } GNUNET_break (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); size = ntohs (msg->size); if (size == sizeof (struct GNUNET_MessageHeader)) { /* done! */ alucb->cb (alucb->cb_cls, NULL); GNUNET_CLIENT_disconnect (alucb->client); GNUNET_free (alucb); return; } address = (const char *) &msg[1]; if (address[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0') { /* invalid reply */ GNUNET_break (0); alucb->cb (alucb->cb_cls, NULL); GNUNET_CLIENT_disconnect (alucb->client); GNUNET_free (alucb); return; } /* expect more replies */ GNUNET_CLIENT_receive (alucb->client, &address_response_processor, alucb, GNUNET_TIME_absolute_get_remaining (alucb->timeout)); alucb->cb (alucb->cb_cls, address); } /** * Convert a binary address into a human readable address. * * @param cfg configuration to use * @param address address to convert (binary format) * @param numeric should (IP) addresses be displayed in numeric form * (otherwise do reverse DNS lookup) * @param timeout how long is the lookup allowed to take at most * @param aluc function to call with the results * @param aluc_cls closure for aluc * @return handle to cancel the operation, NULL on error */ struct GNUNET_TRANSPORT_AddressToStringContext * GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_HELLO_Address *address, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressToStringCallback aluc, void *aluc_cls) { size_t len; size_t alen; size_t slen; struct AddressLookupMessage *msg; struct GNUNET_TRANSPORT_AddressToStringContext *alc; struct GNUNET_CLIENT_Connection *client; char *addrbuf; GNUNET_assert (address != NULL); alen = address->address_length; slen = strlen (address->transport_name) + 1; len = sizeof (struct AddressLookupMessage) + alen + slen; if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } client = GNUNET_CLIENT_connect ("transport", cfg); if (NULL == client) return NULL; msg = GNUNET_malloc (len); msg->header.size = htons (len); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING); msg->numeric_only = htons ((int16_t) numeric); msg->addrlen = htons ((uint16_t) alen); msg->timeout = GNUNET_TIME_relative_hton (timeout); addrbuf = (char *) &msg[1]; memcpy (addrbuf, address->address, alen); memcpy (&addrbuf[alen], address->transport_name, slen); alc = GNUNET_new (struct GNUNET_TRANSPORT_AddressToStringContext); alc->cb = aluc; alc->cb_cls = aluc_cls; alc->timeout = GNUNET_TIME_relative_to_absolute (timeout); alc->client = client; GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (client, &msg->header, timeout, GNUNET_YES, &address_response_processor, alc)); GNUNET_free (msg); return alc; } /** * Cancel request for address conversion. * * @param pic the context handle */ void GNUNET_TRANSPORT_address_to_string_cancel (struct GNUNET_TRANSPORT_AddressToStringContext *pic) { GNUNET_CLIENT_disconnect (pic->client); GNUNET_free (pic); } /* end of transport_api_address_to_string.c */ gnunet-0.10.1/src/transport/transport.h0000644000175000017500000002657212316473377015073 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/transport.h * @brief common internal definitions for transport service * @author Christian Grothoff */ #ifndef TRANSPORT_H #define TRANSPORT_H #include "gnunet_crypto_lib.h" #include "gnunet_time_lib.h" #include "gnunet_transport_service.h" #include "gnunet_constants.h" #define DEBUG_TRANSPORT GNUNET_EXTRA_LOGGING /** * For how long do we allow unused bandwidth * from the past to carry over into the future? (in seconds) */ #define MAX_BANDWIDTH_CARRY_S GNUNET_CONSTANTS_MAX_BANDWIDTH_CARRY_S /** * How often do we (at most) do a full quota * recalculation? (in ms) */ #define MIN_QUOTA_REFRESH_TIME 2000 /** * What's the maximum number of sockets transport uses for validation and * neighbors */ #define DEFAULT_MAX_FDS 256 /** * Maximum frequency for re-evaluating latencies for all transport addresses. */ #define LATENCY_EVALUATION_MAX_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1) /** * Maximum frequency for re-evaluating latencies for connected addresses. */ #define CONNECTED_LATENCY_EVALUATION_MAX_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1) /** * Similiar to GNUNET_TRANSPORT_NotifyDisconnect but in and out quotas are * included here. These values are not required outside transport_api * * @param cls closure * @param peer the peer that connected * @param bandwidth_in inbound bandwidth in NBO * @param bandwidth_out outbound bandwidth in NBO * */ typedef void (*NotifyConnect) (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out); GNUNET_NETWORK_STRUCT_BEGIN /** * Message from the transport service to the library * asking to check if both processes agree about this * peers identity. */ struct StartMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_START */ struct GNUNET_MessageHeader header; /** * 0: no options * 1: The 'self' field should be checked * 2: this client is interested in payload traffic */ uint32_t options; /** * Identity we think we have. If it does not match, the * receiver should print out an error message and disconnect. */ struct GNUNET_PeerIdentity self; }; /** * Message from the transport service to the library * informing about neighbors. */ struct ConnectInfoMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT */ struct GNUNET_MessageHeader header; /** * Identity of the new neighbour. */ struct GNUNET_PeerIdentity id; /** * Current inbound quota for this peer */ struct GNUNET_BANDWIDTH_Value32NBO quota_in; /** * Current outbound quota for this peer */ struct GNUNET_BANDWIDTH_Value32NBO quota_out; }; /** * Message from the transport service to the library * informing about disconnects. */ struct DisconnectInfoMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT */ struct GNUNET_MessageHeader header; /** * Reserved, always zero. */ uint32_t reserved GNUNET_PACKED; /** * Who got disconnected? */ struct GNUNET_PeerIdentity peer; }; /** * Message type for sending a request connect message * to the transport service. Must be done before transport * api will allow messages to be queued/sent to transport * service for transmission to a peer. */ struct TransportRequestConnectMessage { /** * Message header */ struct GNUNET_MessageHeader header; /** * Connect (GNUNET_YES) or connect (GNUNET_NO). */ uint32_t connect; /** * Identity of the peer we would like to connect to. */ struct GNUNET_PeerIdentity peer; }; /** * Message used to set a particular bandwidth quota. Sent TO the * service to set an incoming quota, sent FROM the service to update * an outgoing quota. */ struct QuotaSetMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA */ struct GNUNET_MessageHeader header; /** * Quota. */ struct GNUNET_BANDWIDTH_Value32NBO quota; /** * About which peer are we talking here? */ struct GNUNET_PeerIdentity peer; }; /** * Message used to notify the transport API about a message * received from the network. The actual message follows. */ struct InboundMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_RECV */ struct GNUNET_MessageHeader header; /** * Which peer sent the message? */ struct GNUNET_PeerIdentity peer; }; /** * Message used to notify the transport API that it can * send another message to the transport service. */ struct SendOkMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK */ struct GNUNET_MessageHeader header; /** * GNUNET_OK if the transmission succeeded, * GNUNET_SYSERR if it failed (i.e. network disconnect); * in either case, it is now OK for this client to * send us another message for the given peer. */ uint32_t success GNUNET_PACKED; /** * Size of message sent */ uint32_t bytes_msg GNUNET_PACKED; /** * Size of message sent over wire * Includes plugin and protocol specific overhead */ uint32_t bytes_physical GNUNET_PACKED; /** * Latency estimate. */ struct GNUNET_TIME_RelativeNBO latency; /** * Which peer can send more now? */ struct GNUNET_PeerIdentity peer; }; /** * Message used to notify the transport service about a message * to be transmitted to another peer. The actual message follows. */ struct OutboundMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Allowed delay. */ struct GNUNET_TIME_RelativeNBO timeout; /** * Which peer should receive the message? */ struct GNUNET_PeerIdentity peer; }; /** * Message from the library to the transport service * asking for converting a transport address to a * human-readable UTF-8 string. */ struct AddressLookupMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING */ struct GNUNET_MessageHeader header; /** * Should the conversion use numeric IP addresses (otherwise * a reverse DNS lookup is OK -- if applicable). */ int16_t numeric_only GNUNET_PACKED; /** * Length of the (binary) address in bytes, in big-endian. */ uint16_t addrlen GNUNET_PACKED; /** * timeout to give up. */ struct GNUNET_TIME_RelativeNBO timeout; /* followed by 'addrlen' bytes of the actual address, then * followed by the 0-terminated name of the transport */ }; /** * Message from the transport service to the library containing information * about a peer. Information contained are: * - current address used to communicate with this peer * - state * - state timeout * * Memory layout: * [AddressIterateResponseMessage][address[addrlen]][transportname[pluginlen]] */ struct ValidationIterateResponseMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE */ struct GNUNET_MessageHeader header; /** * For alignment. */ uint32_t reserved; /** * Peer identity */ struct GNUNET_PeerIdentity peer; /** * Local info about the address */ uint32_t local_address_info GNUNET_PACKED; /** * Address length */ uint32_t addrlen GNUNET_PACKED; /** * Length of the plugin name */ uint32_t pluginlen GNUNET_PACKED; /** * State */ uint32_t state GNUNET_PACKED; struct GNUNET_TIME_AbsoluteNBO last_validation; struct GNUNET_TIME_AbsoluteNBO valid_until; struct GNUNET_TIME_AbsoluteNBO next_validation; }; /** * Message from the library to the transport service * asking for binary addresses known for a peer. */ struct ValidationMonitorMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST */ struct GNUNET_MessageHeader header; /** * One shot call or continous replies? */ uint32_t one_shot; /** * The identity of the peer to look up. */ struct GNUNET_PeerIdentity peer; }; /** * Message from the library to the transport service * asking for binary addresses known for a peer. */ struct PeerMonitorMessage { /** * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST */ struct GNUNET_MessageHeader header; /** * One shot call or continous replies? */ uint32_t one_shot; /** * The identity of the peer to look up. */ struct GNUNET_PeerIdentity peer; }; /** * Message from the library to the transport service * asking for binary addresses known for a peer. */ struct TrafficMetricMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC */ struct GNUNET_MessageHeader header; /** * SEND, RECEIVE or BOTH? */ uint16_t direction; /** * Traffic metrics count */ uint16_t ats_count; /** * The identity of the peer to look up. */ struct GNUNET_PeerIdentity peer; }; /** * Message from the transport service to the library containing information * about a peer. Information contained are: * - current address used to communicate with this peer * - state * - state timeout * * Memory layout: * [AddressIterateResponseMessage][address[addrlen]][transportname[pluginlen]] */ struct PeerIterateResponseMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE */ struct GNUNET_MessageHeader header; /** * For alignment. */ uint32_t reserved; /** * Peer identity */ struct GNUNET_PeerIdentity peer; /** * Timeout for the state this peer is in */ struct GNUNET_TIME_AbsoluteNBO state_timeout; /** * Local info about the address */ uint32_t local_address_info GNUNET_PACKED; /** * State this peer is in as #GNUNET_TRANSPORT_PeerState enumeration element */ uint32_t state GNUNET_PACKED; /** * Address length */ uint32_t addrlen GNUNET_PACKED; /** * Length of the plugin name */ uint32_t pluginlen GNUNET_PACKED; }; /** * Change in blacklisting (either request or notification, * depending on which direction it is going). */ struct BlacklistMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY or * GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY. */ struct GNUNET_MessageHeader header; /** * 0 for the query, GNUNET_OK (allowed) or GNUNET_SYSERR (disallowed) * for the response. */ uint32_t is_allowed GNUNET_PACKED; /** * Which peer is being blacklisted or queried? */ struct GNUNET_PeerIdentity peer; }; GNUNET_NETWORK_STRUCT_END /* end of transport.h */ #endif gnunet-0.10.1/src/transport/test_transport_api_unreliability_constant_udp_peer1.conf0000644000175000017500000000112312225230043026227 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-p1/ [transport-udp] PORT = 12040 MAX_BPS = 1073741824 [arm] PORT = 12045 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12044 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12043 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12042 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12041 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_plugin_transport_data_udp.conf0000644000175000017500000000000112225230043021776 00000000000000 gnunet-0.10.1/src/transport/plugin_transport_udp_broadcasting.c0000644000175000017500000005426212274643447022031 00000000000000/* This file is part of GNUnet (C) 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_udp_broadcasting.c * @brief Neighbour discovery with UDP * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "plugin_transport_udp.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_fragmentation_lib.h" #include "gnunet_nat_lib.h" #include "gnunet_protocols.h" #include "gnunet_resolver_service.h" #include "gnunet_signatures.h" #include "gnunet_constants.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "transport.h" #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__) /* *********** Cryogenic ********** */ #if LINUX #include #include #include #include #include #define PM_MAGIC 'k' #define PM_SET_DELAY_AND_TIMEOUT _IOW(PM_MAGIC, 1, struct pm_times) struct pm_times { unsigned long delay_msecs; unsigned long timeout_msecs; }; #endif /************************************/ struct UDP_Beacon_Message { /** * Message header. */ struct GNUNET_MessageHeader header; /** * What is the identity of the sender */ struct GNUNET_PeerIdentity sender; }; struct BroadcastAddress { struct BroadcastAddress *next; struct BroadcastAddress *prev; /** * ID of select broadcast task */ GNUNET_SCHEDULER_TaskIdentifier broadcast_task; struct Plugin *plugin; void *addr; socklen_t addrlen; #if LINUX /** * Cryogenic handle. */ struct GNUNET_DISK_FileHandle *cryogenic_fd; /** * Time out for cryogenic. */ struct pm_times cryogenic_times; #endif }; struct Mstv4Context { struct Plugin *plugin; struct IPv4UdpAddress addr; /** * ATS network type in NBO */ uint32_t ats_address_network_type; }; struct Mstv6Context { struct Plugin *plugin; struct IPv6UdpAddress addr; /** * ATS network type in NBO */ uint32_t ats_address_network_type; }; static int broadcast_ipv6_mst_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct Plugin *plugin = cls; struct Mstv6Context *mc = client; struct GNUNET_HELLO_Address *address; const struct GNUNET_MessageHeader *hello; const struct UDP_Beacon_Message *msg; struct GNUNET_ATS_Information atsi; msg = (const struct UDP_Beacon_Message *) message; if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON != ntohs (msg->header.type)) return GNUNET_OK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received beacon with %u bytes from peer `%s' via address `%s'\n", ntohs (msg->header.size), GNUNET_i2s (&msg->sender), udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr))); /* setup ATS */ atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); atsi.value = mc->ats_address_network_type; GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); hello = (struct GNUNET_MessageHeader *) &msg[1]; address = GNUNET_HELLO_address_allocate (&msg->sender, PLUGIN_NAME, (const char *) &mc->addr, sizeof (mc->addr), GNUNET_HELLO_ADDRESS_INFO_INBOUND); plugin->env->receive (plugin->env->cls, address, NULL, hello); plugin->env->update_address_metrics (plugin->env->cls, address, NULL, &atsi, 1); GNUNET_HELLO_address_free (address); GNUNET_STATISTICS_update (plugin->env->stats, _ ("# IPv6 multicast HELLO beacons received via udp"), 1, GNUNET_NO); GNUNET_free (mc); return GNUNET_OK; } static int broadcast_ipv4_mst_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct Plugin *plugin = cls; struct Mstv4Context *mc = client; struct GNUNET_HELLO_Address *address; const struct GNUNET_MessageHeader *hello; const struct UDP_Beacon_Message *msg; struct GNUNET_ATS_Information atsi; msg = (const struct UDP_Beacon_Message *) message; if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON != ntohs (msg->header.type)) return GNUNET_OK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received beacon with %u bytes from peer `%s' via address `%s'\n", ntohs (msg->header.size), GNUNET_i2s (&msg->sender), udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr))); /* setup ATS */ atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); atsi.value = mc->ats_address_network_type; GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED); hello = (struct GNUNET_MessageHeader *) &msg[1]; address = GNUNET_HELLO_address_allocate (&msg->sender, PLUGIN_NAME, (const char *) &mc->addr, sizeof (mc->addr), GNUNET_HELLO_ADDRESS_INFO_INBOUND); plugin->env->receive (plugin->env->cls, address, NULL, hello); plugin->env->update_address_metrics (plugin->env->cls, address, NULL, &atsi, 1); GNUNET_HELLO_address_free (address); GNUNET_STATISTICS_update (plugin->env->stats, _("# IPv4 broadcast HELLO beacons received via udp"), 1, GNUNET_NO); GNUNET_free (mc); return GNUNET_OK; } void udp_broadcast_receive (struct Plugin *plugin, const char *buf, ssize_t size, const struct sockaddr *addr, size_t addrlen) { struct GNUNET_ATS_Information ats; if (addrlen == sizeof (struct sockaddr_in)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n", size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen)); struct Mstv4Context *mc; mc = GNUNET_new (struct Mstv4Context); struct sockaddr_in *av4 = (struct sockaddr_in *) addr; mc->addr.ipv4_addr = av4->sin_addr.s_addr; mc->addr.u4_port = av4->sin_port; ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen); mc->ats_address_network_type = ats.value; GNUNET_assert (NULL != plugin->broadcast_ipv4_mst); if (GNUNET_OK != GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, size, GNUNET_NO, GNUNET_NO)) GNUNET_free (mc); } if (addrlen == sizeof (struct sockaddr_in6)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n", size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen)); struct Mstv6Context *mc; mc = GNUNET_new (struct Mstv6Context); struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) addr; mc->addr.ipv6_addr = av6->sin6_addr; mc->addr.u6_port = av6->sin6_port; ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen); mc->ats_address_network_type = ats.value; GNUNET_assert (NULL != plugin->broadcast_ipv4_mst); if (GNUNET_OK != GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, size, GNUNET_NO, GNUNET_NO)) GNUNET_free (mc); } } static unsigned int prepare_beacon (struct Plugin *plugin, struct UDP_Beacon_Message *msg) { uint16_t hello_size; uint16_t msg_size; const struct GNUNET_MessageHeader *hello; hello = plugin->env->get_our_hello (); if (NULL == hello) return 0; hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello); msg_size = hello_size + sizeof (struct UDP_Beacon_Message); if (hello_size < (sizeof (struct GNUNET_MessageHeader)) || (msg_size > (UDP_MTU))) return 0; msg->sender = *(plugin->env->my_identity); msg->header.size = htons (msg_size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON); memcpy (&msg[1], hello, hello_size); return msg_size; } static void udp_ipv4_broadcast_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct BroadcastAddress *baddr = cls; struct Plugin *plugin = baddr->plugin; int sent; uint16_t msg_size; char buf[65536] GNUNET_ALIGN; baddr->broadcast_task = GNUNET_SCHEDULER_NO_TASK; msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); if (0 != msg_size) { struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr; addr->sin_port = htons (plugin->port); sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4, &buf, msg_size, (const struct sockaddr *) addr, baddr->addrlen); if (sent == GNUNET_SYSERR) { if ((ENETUNREACH == errno) || (ENETDOWN == errno)) { /* "Network unreachable" or "Network down" * * This indicates that we just do not have network connectivity */ GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING, "Network connectivity is down, cannot send beacon!\n"); } else GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto"); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent, GNUNET_a2s (baddr->addr, baddr->addrlen)); } } #if LINUX /* * Cryogenic */ if (NULL != baddr->cryogenic_fd) { baddr->cryogenic_times.delay_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*0.5; baddr->cryogenic_times.timeout_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*1.5; if (ioctl(baddr->cryogenic_fd->fd, PM_SET_DELAY_AND_TIMEOUT, &baddr->cryogenic_times) < 0) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl"); baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv4_broadcast_send, baddr); } else GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, baddr->cryogenic_fd, &udp_ipv4_broadcast_send, baddr); } else #endif baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv4_broadcast_send, baddr); } static void udp_ipv6_broadcast_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct BroadcastAddress *baddr = cls; struct Plugin *plugin = baddr->plugin; ssize_t sent; uint16_t msg_size; char buf[65536] GNUNET_ALIGN; const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) baddr->addr; baddr->broadcast_task = GNUNET_SCHEDULER_NO_TASK; msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf); /* Note: unclear if this actually works to limit the multicast to the specified interface as we're not (necessarily) using a link-local multicast group and the kernel suggests that the scope ID is only respected for link-local addresses; however, if the scope ID is ignored, the kernel should just multicast on ALL interfaces, which is merely slightly less efficient; in that case, we might want to revert to only doing this once, and not per interface (hard to test...) */ plugin->ipv6_multicast_address.sin6_scope_id = s6->sin6_scope_id; sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size, (const struct sockaddr *) &plugin->ipv6_multicast_address, sizeof (struct sockaddr_in6)); plugin->ipv6_multicast_address.sin6_scope_id = 0; if (sent == GNUNET_SYSERR) { if ((ENETUNREACH == errno) || (ENETDOWN == errno)) { /* "Network unreachable" or "Network down" * * This indicates that this system is IPv6 enabled, but does not * have a valid global IPv6 address assigned */ GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING, "Network connectivity is down, cannot send beacon!\n"); } else GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto"); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending IPv6 HELLO beacon broadcast with %d bytes to address %s\n", (int) sent, GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address, sizeof (struct sockaddr_in6))); } #if LINUX /* * Cryogenic */ if (NULL != baddr->cryogenic_fd) { baddr->cryogenic_times.delay_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*0.5; baddr->cryogenic_times.timeout_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*1.5; if (ioctl(baddr->cryogenic_fd->fd, PM_SET_DELAY_AND_TIMEOUT, &baddr->cryogenic_times) < 0) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl"); baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv6_broadcast_send, baddr); } else GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, baddr->cryogenic_fd, &udp_ipv4_broadcast_send, baddr); } else #endif baddr->broadcast_task = GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval, &udp_ipv6_broadcast_send, baddr); } /** * Callback function invoked for each interface found. * * @param cls closure with the `struct Plugin` * @param name name of the interface (can be NULL for unknown) * @param isDefault is this presumably the default interface * @param addr address of this interface (can be NULL for unknown or unassigned) * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) * @param netmask the network mask (can be NULL for unknown or unassigned) * @param addrlen length of the address * @return #GNUNET_OK to continue iteration, #GNUNET_SYSERR to abort */ static int iface_proc (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen) { struct Plugin *plugin = cls; struct BroadcastAddress *ba; struct GNUNET_ATS_Information network; if (NULL == addr) return GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ", GNUNET_a2s (addr, addrlen), name, addr); if (NULL == broadcast_addr) return GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "broadcast address %s for interface %s %p\n ", GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ", GNUNET_a2s (netmask, addrlen), name, netmask); network = plugin->env->get_address_type (plugin->env->cls, broadcast_addr, addrlen); if (GNUNET_ATS_NET_LOOPBACK == ntohl(network.value)) { /* Broadcasting on loopback does not make sense */ return GNUNET_YES; } ba = GNUNET_new (struct BroadcastAddress); ba->plugin = plugin; ba->addr = GNUNET_malloc (addrlen); memcpy (ba->addr, broadcast_addr, addrlen); ba->addrlen = addrlen; if ( (GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4) && (addrlen == sizeof (struct sockaddr_in)) ) { #if LINUX /* * setup Cryogenic FD for ipv4 broadcasting */ char *filename; GNUNET_asprintf (&filename, "/dev/cryogenic/%s", name); if (0 == ACCESS (name, R_OK)) { ba->cryogenic_fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_NONE); } GNUNET_free (filename); #endif ba->broadcast_task = GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, ba); } if ((GNUNET_YES == plugin->enable_ipv6) && (NULL != plugin->sockv6) && (addrlen == sizeof (struct sockaddr_in6))) { /* Create IPv6 multicast request */ struct ipv6_mreq multicastRequest; const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) broadcast_addr; multicastRequest.ipv6mr_multiaddr = plugin->ipv6_multicast_address.sin6_addr; /* http://tools.ietf.org/html/rfc2553#section-5.2: * * IPV6_JOIN_GROUP * * Join a multicast group on a specified local interface. If the * interface index is specified as 0, the kernel chooses the local * interface. For example, some kernels look up the multicast * group in the normal IPv6 routing table and using the resulting * interface; we do this for each interface, so no need to use * zero (anymore...). */ multicastRequest.ipv6mr_interface = s6->sin6_scope_id; /* Join the multicast group */ if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt (plugin->sockv6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &multicastRequest, sizeof (multicastRequest))) { LOG (GNUNET_ERROR_TYPE_WARNING, "Failed to join IPv6 multicast group: IPv6 broadcasting not running\n"); } else { #if LINUX /* * setup Cryogenic FD for ipv6 broadcasting */ char *filename; GNUNET_asprintf (&filename, "/dev/cryogenic/%s", name); if (0 == ACCESS (name, R_OK)) { ba->cryogenic_fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE, GNUNET_DISK_PERM_NONE); } GNUNET_free (filename); #endif ba->broadcast_task = GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, ba); } } GNUNET_CONTAINER_DLL_insert (plugin->broadcast_head, plugin->broadcast_tail, ba); return GNUNET_OK; } void setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4) { const struct GNUNET_MessageHeader *hello; hello = plugin->env->get_our_hello (); if (GNUNET_YES == GNUNET_HELLO_is_friend_only ((const struct GNUNET_HELLO_Message *) hello)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Disabling HELLO broadcasting due to friend-to-friend only configuration!\n")); return; } /* always create tokenizers */ plugin->broadcast_ipv4_mst = GNUNET_SERVER_mst_create (&broadcast_ipv4_mst_cb, plugin); plugin->broadcast_ipv6_mst = GNUNET_SERVER_mst_create (&broadcast_ipv6_mst_cb, plugin); if (GNUNET_YES != plugin->enable_broadcasting) return; /* We do not send, just receive */ /* create IPv4 broadcast socket */ if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4)) { static int yes = 1; if (GNUNET_NETWORK_socket_setsockopt (plugin->sockv4, SOL_SOCKET, SO_BROADCAST, &yes, sizeof (int)) != GNUNET_OK) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"), ntohs (server_addrv4->sin_port)); } } /* create IPv6 multicast socket */ if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL)) { memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6)); GNUNET_assert (1 == inet_pton (AF_INET6, "FF05::13B", &plugin->ipv6_multicast_address.sin6_addr)); plugin->ipv6_multicast_address.sin6_family = AF_INET6; plugin->ipv6_multicast_address.sin6_port = htons (plugin->port); } GNUNET_OS_network_interfaces_list (&iface_proc, plugin); } void stop_broadcast (struct Plugin *plugin) { if (GNUNET_YES == plugin->enable_broadcasting) { /* Disable broadcasting */ while (plugin->broadcast_head != NULL) { struct BroadcastAddress *p = plugin->broadcast_head; if (p->broadcast_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (p->broadcast_task); p->broadcast_task = GNUNET_SCHEDULER_NO_TASK; } if ((GNUNET_YES == plugin->enable_ipv6) && (NULL != plugin->sockv6) && (p->addrlen == sizeof (struct sockaddr_in6))) { /* Create IPv6 multicast request */ struct ipv6_mreq multicastRequest; const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr; multicastRequest.ipv6mr_multiaddr = plugin->ipv6_multicast_address.sin6_addr; multicastRequest.ipv6mr_interface = s6->sin6_scope_id; /* Leave the multicast group */ if (GNUNET_OK == GNUNET_NETWORK_socket_setsockopt (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &multicastRequest, sizeof (multicastRequest))) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, setsockopt); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n"); } } #if LINUX GNUNET_DISK_file_close(p->cryogenic_fd); #endif GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head, plugin->broadcast_tail, p); GNUNET_free (p->addr); GNUNET_free (p); } } /* Destroy MSTs */ if (NULL != plugin->broadcast_ipv4_mst) { GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst); plugin->broadcast_ipv4_mst = NULL; } if (NULL != plugin->broadcast_ipv6_mst) { GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst); plugin->broadcast_ipv6_mst = NULL; } } /* end of plugin_transport_udp_broadcasting.c */ gnunet-0.10.1/src/transport/test_transport_api_unreliability_udp_peer2.conf0000644000175000017500000000112012225230043024314 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-p2/ [transport-udp] PORT = 12050 MAX_BPS = 5000000 [arm] PORT = 12055 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12054 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12053 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12052 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12051 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_monitoring_validation_peer2.conf0000644000175000017500000000020112267431203025175 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-val-p2/ [TRANSPORT] PLUGINS=tcp gnunet-0.10.1/src/transport/test_transport_api_manipulation_recv_tcp_peer2.conf0000644000175000017500000000114712225230043025166 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_reliability_bluetooth_peer2.conf0000644000175000017500000000114012225230043025170 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p2/ [transport-bluetooth] INTERFACE = hci1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/gnunet-service-transport_neighbours.h0000644000175000017500000003016712316473377022247 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_neighbours.h * @brief neighbour management API * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_NEIGHBOURS_H #define GNUNET_SERVICE_TRANSPORT_NEIGHBOURS_H #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "gnunet-service-transport.h" #include "transport.h" #include "gnunet_util_lib.h" // TODO: // - ATS and similar info is a bit lacking in the API right now... /** * Initialize the neighbours subsystem. * * @param cls closure for callbacks * @param connect_cb function to call if we connect to a peer * @param disconnect_cb function to call if we disconnect from a peer * @param peer_address_cb function to call if a neighbour's active address changes * @param max_fds maximum number of fds to use */ void GST_neighbours_start (void *cls, NotifyConnect connect_cb, GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb, GNUNET_TRANSPORT_NeighbourChangeCallback peer_address_cb, unsigned int max_fds); /** * Cleanup the neighbours subsystem. */ void GST_neighbours_stop (void); /** * Try to create a connection to the given target (eventually). * * @param target peer to try to connect to */ void GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target); /** * Test if we're connected to the given peer. * * @param target peer to test * @return #GNUNET_YES if we are connected, #GNUNET_NO if not */ int GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target); /** * Function called after the transmission is done. * * @param cls closure * @param success #GNUNET_OK on success, #GNUNET_NO on failure, #GNUNET_SYSERR if we're not connected */ typedef void (*GST_NeighbourSendContinuation) (void *cls, int success, size_t bytes_payload, size_t bytes_on_wire); /** * Transmit a message to the given target using the active connection. * * @param target destination * @param msg message to send * @param msg_size number of bytes in @a msg * @param timeout when to fail with timeout * @param cont function to call when done * @param cont_cls closure for @a cont */ void GST_neighbours_send (const struct GNUNET_PeerIdentity *target, const void *msg, size_t msg_size, struct GNUNET_TIME_Relative timeout, GST_NeighbourSendContinuation cont, void *cont_cls); void GST_neighbours_register_quota_notification (void *cls, const struct GNUNET_PeerIdentity *peer, const char *plugin, struct Session *session); void GST_neighbours_unregister_quota_notification(void *cls, const struct GNUNET_PeerIdentity *peer, const char *plugin, struct Session *session); /** * We have received a message from the given sender. * How long should we delay before receiving more? * (Also used to keep the peer marked as live). * * @param sender sender of the message * @param size size of the message * @param do_forward set to #GNUNET_YES if the message should be forwarded to clients * #GNUNET_NO if the neighbour is not connected or violates the quota * @return how long to wait before reading more from this sender */ struct GNUNET_TIME_Relative GST_neighbours_calculate_receive_delay (const struct GNUNET_PeerIdentity *sender, ssize_t size, int *do_forward); /** * Keep the connection to the given neighbour alive longer, * we received a KEEPALIVE (or equivalent); send a response. * * @param neighbour neighbour to keep alive (by sending keep alive response) * @param m the keep alive message containing the nonce to respond to */ void GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m); /** * We received a KEEP_ALIVE_RESPONSE message and use this to calculate * latency to this peer. Pass the updated information (existing ats * plus calculated latency) to ATS. * * @param neighbour neighbour to keep alive * @param m the message containing the keep alive response */ void GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_MessageHeader *m); /** * Change the incoming quota for the given peer. * * @param neighbour identity of peer to change qutoa for * @param quota new quota */ void GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour, struct GNUNET_BANDWIDTH_Value32NBO quota); /** * If we have an active connection to the given target, it must be shutdown. * * @param target peer to disconnect from */ void GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target); /** * Function called for each neighbour. * * @param cls closure * @param neighbour identity of the neighbour * @param address the address (or NULL) * @param state current state the peer is in * @param state_timeout timeout for this state * @param bandwidth_in inbound quota in NBO * @param bandwidth_out outbound quota in NBO */ typedef void (*GST_NeighbourIterator) (void *cls, const struct GNUNET_PeerIdentity *neighbour, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out); /** * Iterate over all connected neighbours. * * @param cb function to call * @param cb_cls closure for @a cb */ void GST_neighbours_iterate (GST_NeighbourIterator cb, void *cb_cls); /** * A session was terminated. Take note. * * @param peer identity of the peer where the session died * @param session session that is gone * @return #GNUNET_YES if this was a session used, #GNUNET_NO if * this session was not in use */ int GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer, struct Session *session); void GST_neighbours_notify_data_recv (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message); void GST_neighbours_notify_payload_recv (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message); void GST_neighbours_notify_payload_sent (const struct GNUNET_PeerIdentity *peer, size_t size); void GST_neighbours_notify_data_sent (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, size_t size); /** * For an existing neighbour record, set the active connection to * use the given address. * * @param peer identity of the peer to switch the address for * @param address address of the other peer, NULL if other peer * connected to us * @param session session to use (or NULL) * @param ats performance data * @param ats_count number of entries in ats * @param bandwidth_in inbound quota to be used when connection is up * @param bandwidth_out outbound quota to be used when connection is up */ void GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out); /** * We received a 'SESSION_CONNECT' message from the other peer. * Consider switching to it. * * @param message possibly a 'struct SessionConnectMessage' (check format) * @param peer identity of the peer to switch the address for * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer); /** * We received a 'SESSION_CONNECT_ACK' message from the other peer. * Consider switching to it. * * @param message possibly a 'struct SessionConnectMessage' (check format) * @param peer identity of the peer to switch the address for * @param address address of the other peer, NULL if other peer * connected to us * @param session session to use (or NULL) * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_neighbours_handle_connect_ack (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session); /** * We received a 'SESSION_ACK' message from the other peer. * If we sent a 'CONNECT_ACK' last, this means we are now * connected. Otherwise, do nothing. * * @param message possibly a 'struct SessionConnectMessage' (check format) * @param peer identity of the peer to switch the address for * @param address address of the other peer, NULL if other peer * connected to us * @param session session to use (or NULL) * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session); /** * Obtain current latency information for the given neighbour. * * @param peer * @return observed latency of the address, FOREVER if the address was * never successfully validated */ struct GNUNET_TIME_Relative GST_neighbour_get_latency (const struct GNUNET_PeerIdentity *peer); /** * Obtain current address information for the given neighbour. * * @param peer * @return address currently used */ struct GNUNET_HELLO_Address * GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer); /** * We received a disconnect message from the given peer, * validate and process. * * @param peer sender of the message * @param msg the disconnect message */ void GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg); #endif /* end of file gnunet-service-transport_neighbours.h */ gnunet-0.10.1/src/transport/gnunet-service-transport.c0000644000175000017500000010731012316473377020010 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport.c * @brief * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_peerinfo_service.h" #include "gnunet_ats_service.h" #include "gnunet-service-transport.h" #include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_clients.h" #include "gnunet-service-transport_hello.h" #include "gnunet-service-transport_neighbours.h" #include "gnunet-service-transport_plugins.h" #include "gnunet-service-transport_validation.h" #include "gnunet-service-transport_manipulation.h" #include "transport.h" /** * Information we need for an asynchronous session kill. */ struct SessionKiller { /** * Kept in a DLL. */ struct SessionKiller *next; /** * Kept in a DLL. */ struct SessionKiller *prev; /** * Session to kill. */ struct Session *session; /** * Plugin for the session. */ struct GNUNET_TRANSPORT_PluginFunctions *plugin; /** * The kill task. */ GNUNET_SCHEDULER_TaskIdentifier task; }; struct BlacklistCheckContext { struct BlacklistCheckContext *prev; struct BlacklistCheckContext *next; struct GST_BlacklistCheck *blc; struct GNUNET_HELLO_Address *address; struct Session *session; struct GNUNET_MessageHeader *msg; struct GNUNET_ATS_Information *ats; uint32_t ats_count; }; /* globals */ /** * Statistics handle. */ struct GNUNET_STATISTICS_Handle *GST_stats; /** * Configuration handle. */ const struct GNUNET_CONFIGURATION_Handle *GST_cfg; /** * Configuration handle. */ struct GNUNET_PeerIdentity GST_my_identity; /** * Handle to peerinfo service. */ struct GNUNET_PEERINFO_Handle *GST_peerinfo; /** * Handle to our service's server. */ static struct GNUNET_SERVER_Handle *GST_server; /** * Our private key. */ struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; /** * ATS handle. */ struct GNUNET_ATS_SchedulingHandle *GST_ats; /** * Hello address expiration */ struct GNUNET_TIME_Relative hello_expiration; /** * DEBUGGING connection counter */ static int connections; /** * Head of DLL of asynchronous tasks to kill sessions. */ static struct SessionKiller *sk_head; /** * Tail of DLL of asynchronous tasks to kill sessions. */ static struct SessionKiller *sk_tail; struct BlacklistCheckContext *bc_head; struct BlacklistCheckContext *bc_tail; /** * Transmit our HELLO message to the given (connected) neighbour. * * @param cls the 'HELLO' message * @param target a connected neighbour * @param address the address * @param state current state this peer is in * @param state_timeout timeout for the current state of the peer * @param bandwidth_in inbound quota in NBO * @param bandwidth_out outbound quota in NBO */ static void transmit_our_hello (void *cls, const struct GNUNET_PeerIdentity *target, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { const struct GNUNET_MessageHeader *hello = cls; if (GNUNET_NO == GST_neighbours_test_connected (target)) return; GST_neighbours_send (target, hello, ntohs (hello->size), hello_expiration, NULL, NULL ); } /** * My HELLO has changed. Tell everyone who should know. * * @param cls unused * @param hello new HELLO */ static void process_hello_update (void *cls, const struct GNUNET_MessageHeader *hello) { GST_clients_broadcast (hello, GNUNET_NO); GST_neighbours_iterate (&transmit_our_hello, (void *) hello); } /** * We received some payload. Prepare to pass it on to our clients. * * @param peer (claimed) identity of the other peer * @param address the address * @param session session used * @param message the message to process * @return how long the plugin should wait until receiving more data */ static struct GNUNET_TIME_Relative process_payload (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message) { struct GNUNET_TIME_Relative ret; int do_forward; struct InboundMessage *im; size_t msg_size = ntohs (message->size); size_t size = sizeof(struct InboundMessage) + msg_size; char buf[size] GNUNET_ALIGN; do_forward = GNUNET_SYSERR; ret = GST_neighbours_calculate_receive_delay (peer, msg_size, &do_forward); if (!GST_neighbours_test_connected (peer)) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Discarded %u bytes type %u payload from peer `%s'\n", msg_size, ntohs (message->type), GNUNET_i2s (peer)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes payload discarded due to not connected peer"), msg_size, GNUNET_NO); return ret; } GST_ats_add_address (address, session, NULL, 0); if (GNUNET_YES != do_forward) return ret; im = (struct InboundMessage *) buf; im->header.size = htons (size); im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV); im->peer = *peer; memcpy (&im[1], message, ntohs (message->size)); GST_clients_broadcast (&im->header, GNUNET_YES); return ret; } /** * Task to asynchronously terminate a session. * * @param cls the `struct SessionKiller` with the information for the kill * @param tc scheduler context */ static void kill_session_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct SessionKiller *sk = cls; sk->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_CONTAINER_DLL_remove(sk_head, sk_tail, sk); sk->plugin->disconnect_session (sk->plugin->cls, sk->session); GNUNET_free(sk); } static void cancel_pending_blacklist_checks (const struct GNUNET_HELLO_Address *address, struct Session *session) { struct BlacklistCheckContext *blctx; struct BlacklistCheckContext *next; next = bc_head; for (blctx = next; NULL != blctx; blctx = next) { next = blctx->next; if ((NULL != blctx->address) && (0 == GNUNET_HELLO_address_cmp(blctx->address, address)) && (blctx->session == session)) { GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, blctx); if (NULL != blctx->blc) { GST_blacklist_test_cancel (blctx->blc); blctx->blc = NULL; } GNUNET_HELLO_address_free (blctx->address); GNUNET_free_non_null (blctx->msg); GNUNET_free_non_null (blctx->ats); GNUNET_free (blctx); } } } /** * Force plugin to terminate session due to communication * issue. * * @param plugin_name name of the plugin * @param session session to termiante */ static void kill_session (const char *plugin_name, struct Session *session) { struct GNUNET_TRANSPORT_PluginFunctions *plugin; struct SessionKiller *sk; for (sk = sk_head; NULL != sk; sk = sk->next) if (sk->session == session) return; plugin = GST_plugins_find (plugin_name); if (NULL == plugin) { GNUNET_break(0); return; } /* need to issue disconnect asynchronously */ sk = GNUNET_new (struct SessionKiller); sk->session = session; sk->plugin = plugin; sk->task = GNUNET_SCHEDULER_add_now (&kill_session_task, sk); GNUNET_CONTAINER_DLL_insert(sk_head, sk_tail, sk); } /** * Black list check result for try_connect call * If connection to the peer is allowed request adddress and * * @param cls blc_ctx bl context * @param peer the peer * @param result the result */ static void connect_bl_check_cont (void *cls, const struct GNUNET_PeerIdentity *peer, int result) { struct BlacklistCheckContext *blctx = cls; GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, blctx); blctx->blc = NULL; if (GNUNET_OK == result) { /* Blacklist allows to speak to this peer, forward CONNECT to neighbours */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received CONNECT message from peer `%s' with `%s' %p\n", GNUNET_i2s (peer), GST_plugins_a2s (blctx->address), blctx->session); if (GNUNET_OK != GST_neighbours_handle_connect (blctx->msg, &blctx->address->peer)) { cancel_pending_blacklist_checks (blctx->address, blctx->session); kill_session (blctx->address->transport_name, blctx->session); } } else { /* Blacklist denies to speak to this peer */ GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Discarding CONNECT message from `%s' due to denied blacklist check\n", GNUNET_i2s (peer)); cancel_pending_blacklist_checks (blctx->address, blctx->session); kill_session (blctx->address->transport_name, blctx->session); } if (NULL != blctx->address) GNUNET_HELLO_address_free (blctx->address); GNUNET_free (blctx->msg); GNUNET_free (blctx); } /** * Black list check result for try_connect call * If connection to the peer is allowed request adddress and * * @param cls blc_ctx bl context * @param peer the peer * @param result the result */ static void connect_transport_bl_check_cont (void *cls, const struct GNUNET_PeerIdentity *peer, int result) { struct BlacklistCheckContext *blctx = cls; GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, blctx); blctx->blc = NULL; if (GNUNET_OK == result) { /* Blacklist allows to speak to this transport */ GST_ats_add_address(blctx->address, blctx->session, blctx->ats, blctx->ats_count); } if (NULL != blctx->address) GNUNET_HELLO_address_free (blctx->address); GNUNET_free (blctx->msg); GNUNET_free (blctx); } /** * Function called by the transport for each received message. * * @param cls closure, const char* with the name of the plugin we received the message from * @param address address and (claimed) identity of the other peer * @param message the message, NULL if we only care about * learning about the delay until we should receive again * @param session identifier used for this session (NULL for plugins * that do not offer bi-directional communication to the sender * using the same "connection") * @return how long the plugin should wait until receiving more data * (plugins that do not support this, can ignore the return value) */ struct GNUNET_TIME_Relative GST_receive_callback (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message) { const char *plugin_name = cls; struct GNUNET_TIME_Relative ret; struct BlacklistCheckContext *blctx; struct GST_BlacklistCheck *blc; uint16_t type; ret = GNUNET_TIME_UNIT_ZERO; if (NULL == message) goto end; type = ntohs (message->type); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received Message with type %u from peer `%s'\n", type, GNUNET_i2s (&address->peer)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes total received"), ntohs (message->size), GNUNET_NO); GST_neighbours_notify_data_recv (&address->peer, address, session, message); switch (type) { case GNUNET_MESSAGE_TYPE_HELLO_LEGACY: /* Legacy HELLO message, discard */ return ret; case GNUNET_MESSAGE_TYPE_HELLO: if (GNUNET_OK != GST_validation_handle_hello (message)) { GNUNET_break_op(0); cancel_pending_blacklist_checks (address, session); } return ret; case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Processing `%s' from `%s'\n", "PING", GST_plugins_a2s (address)); if (GNUNET_OK != GST_validation_handle_ping (&address->peer, message, address, session)) { cancel_pending_blacklist_checks (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Processing `%s' from `%s'\n", "PONG", GST_plugins_a2s (address)); if (GNUNET_OK != GST_validation_handle_pong (&address->peer, message)) { GNUNET_break_op(0); cancel_pending_blacklist_checks (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT: /* Do blacklist check if communication with this peer is allowed */ blctx = GNUNET_new (struct BlacklistCheckContext); blctx->address = GNUNET_HELLO_address_copy (address); blctx->session = session; blctx->msg = GNUNET_malloc (ntohs(message->size)); memcpy (blctx->msg, message, ntohs(message->size)); GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, blctx); if (NULL != (blc = GST_blacklist_test_allowed (&address->peer, NULL, &connect_bl_check_cont, blctx))) { blctx->blc = blc; } blctx = GNUNET_new (struct BlacklistCheckContext); blctx->address = GNUNET_HELLO_address_copy (address); blctx->session = session; blctx->msg = GNUNET_malloc (ntohs(message->size)); memcpy (blctx->msg, message, ntohs(message->size)); GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, blctx); if (NULL != (blc = GST_blacklist_test_allowed (&address->peer, address->transport_name, &connect_transport_bl_check_cont, blctx))) { blctx->blc = blc; } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK: if (GNUNET_OK != GST_neighbours_handle_connect_ack (message, &address->peer, address, session)) { cancel_pending_blacklist_checks (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK: if (GNUNET_OK != GST_neighbours_handle_session_ack (message, &address->peer, address, session)) { GNUNET_break_op(0); cancel_pending_blacklist_checks (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT: GST_neighbours_handle_disconnect_message (&address->peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE: GST_neighbours_keepalive (&address->peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE: GST_neighbours_keepalive_response (&address->peer, message); break; default: /* should be payload */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes payload received"), ntohs (message->size), GNUNET_NO); GST_neighbours_notify_payload_recv (&address->peer, address, session, message); ret = process_payload (&address->peer, address, session, message); break; } end: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Allowing receive from peer %s to continue in %s\n", GNUNET_i2s (&address->peer), GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); return ret; } /** * Function that will be called for each address the transport * is aware that it might be reachable under. Update our HELLO. * * @param cls name of the plugin (const char*) * @param add_remove should the address added (YES) or removed (NO) from the * set of valid addresses? * @param address the address to add or remove */ static void plugin_env_address_change_notification (void *cls, int add_remove, const struct GNUNET_HELLO_Address *address) { GST_hello_modify_addresses (add_remove, address); } /** * Function that will be called whenever the plugin internally * cleans up a session pointer and hence the service needs to * discard all of those sessions as well. Plugins that do not * use sessions can simply omit calling this function and always * use NULL wherever a session pointer is needed. This function * should be called BEFORE a potential "TransmitContinuation" * from the "TransmitFunction". * * @param cls closure * @param address which address was the session for * @param session which session is being destoyed */ static void plugin_env_session_end (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session) { struct SessionKiller *sk; if (NULL == address) { GNUNET_break (0); return; } if (NULL == session) { GNUNET_break (0); return; } GNUNET_assert(strlen (address->transport_name) > 0); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Session %p to peer `%s' ended \n", session, GNUNET_i2s (&address->peer)); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Notification from plugin `%s' about terminated %s session %p from peer `%s' address `%s'\n", address->transport_name, GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? "inbound" : "outbound", session, GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); GST_neighbours_session_terminated (&address->peer, session); GNUNET_log_from(GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "transport-ats", "Telling ATS to destroy session %p from peer %s\n", session, GNUNET_i2s (&address->peer)); /* Tell ATS that session has ended */ GNUNET_ATS_address_destroyed (GST_ats, address, session); cancel_pending_blacklist_checks (address, session); for (sk = sk_head; NULL != sk; sk = sk->next) { if (sk->session == session) { GNUNET_CONTAINER_DLL_remove(sk_head, sk_tail, sk); GNUNET_SCHEDULER_cancel (sk->task); GNUNET_free(sk); break; } } } /** * Function that will be called to figure if an address is an loopback, * LAN, WAN etc. address * * @param cls closure * @param addr binary address * @param addrlen length of the address * @return ATS Information containing the network type */ static struct GNUNET_ATS_Information plugin_env_address_to_type (void *cls, const struct sockaddr *addr, size_t addrlen) { struct GNUNET_ATS_Information ats; ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.value = htonl (GNUNET_ATS_NET_UNSPECIFIED); if (NULL == GST_ats) { GNUNET_break(0); return ats; } if (((addr->sa_family != AF_INET) && (addrlen != sizeof(struct sockaddr_in))) && ((addr->sa_family != AF_INET6) && (addrlen != sizeof(struct sockaddr_in6))) && (addr->sa_family != AF_UNIX)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Malformed address with length %u `%s'\n", addrlen, GNUNET_a2s (addr, addrlen)); GNUNET_break(0); return ats; } return GNUNET_ATS_address_get_type (GST_ats, addr, addrlen); } /** * Notify ATS about the new address including the network this address is * located in. * * @param address the address * @param session the session * @param ats ats information * @param ats_count number of @a ats information */ void GST_ats_add_address (const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct GNUNET_TRANSPORT_PluginFunctions *papi; struct GNUNET_ATS_Information ats2[ats_count + 1]; uint32_t net; /* valid new address, let ATS know! */ if (NULL == address->transport_name) { GNUNET_break(0); return; } if (NULL == (papi = GST_plugins_find (address->transport_name))) { /* we don't have the plugin for this address */ GNUNET_break(0); return; } if (GNUNET_YES == GNUNET_ATS_session_known (GST_ats, address, session)) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "ATS already knows the address, not passing it on again\n"); return; } net = papi->get_network (papi->cls, session); if (GNUNET_ATS_NET_UNSPECIFIED == net) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not obtain a valid network for `%s' %s (%s)\n"), GNUNET_i2s (&address->peer), GST_plugins_a2s (address), address->transport_name); return; } ats2[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); ats2[0].value = htonl (net); memcpy (&ats2[1], ats, sizeof(struct GNUNET_ATS_Information) * ats_count); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Notifying ATS about peer `%s''s new address `%s' session %p in network %s\n", GNUNET_i2s (&address->peer), (0 == address->address_length) ? "" : GST_plugins_a2s (address), session, GNUNET_ATS_print_network_type (net)); GNUNET_ATS_address_add (GST_ats, address, session, ats2, ats_count + 1); } /** * Notify ATS about property changes to an address * * @param peer the peer * @param address the address * @param session the session * @param ats performance information * @param ats_count number of elements in @a ats */ void GST_ats_update_metrics (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct GNUNET_ATS_Information *ats_new; if (GNUNET_NO == GNUNET_ATS_session_known (GST_ats, address, session)) return; /* Call to manipulation to manipulate ATS information */ ats_new = GST_manipulation_manipulate_metrics (peer, address, session, ats, ats_count); if (NULL == ats_new) { GNUNET_break(0); return; } if (GNUNET_NO == GNUNET_ATS_address_update (GST_ats, address, session, ats_new, ats_count)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Address or session unknown: failed to update properties for peer `%s' plugin `%s' address `%s' session %p\n"), GNUNET_i2s (peer), address->transport_name, GST_plugins_a2s (address), session); } GNUNET_free(ats_new); } /** * Function that will be called to update metrics for an address * * @param cls closure * @param address address to update metrics for * @param session the session * @param ats the ats information to update * @param ats_count the number of @a ats elements */ static void plugin_env_update_metrics (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { if ((NULL == ats) || (0 == ats_count)) return; GNUNET_assert(NULL != GST_ats); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating metrics for peer `%s' address %s session %p\n", GNUNET_i2s (&address->peer), GST_plugins_a2s (address), session); GST_ats_update_metrics (&address->peer, address, session, ats, ats_count); } /** * Black list check result for try_connect call * If connection to the peer is allowed request adddress and * * @param cls blc_ctx bl context * @param peer the peer * @param result the result */ static void plugin_env_session_start_bl_check_cont (void *cls, const struct GNUNET_PeerIdentity *peer, int result) { struct BlacklistCheckContext *blctx = cls; GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, blctx); blctx->blc = NULL; if (GNUNET_OK == result) { GST_ats_add_address (blctx->address, blctx->session, blctx->ats, blctx->ats_count); } else { cancel_pending_blacklist_checks (blctx->address, blctx->session); kill_session (blctx->address->transport_name, blctx->session); } GNUNET_HELLO_address_free (blctx->address); GNUNET_free_non_null (blctx->ats); GNUNET_free (blctx); } /** * Plugin tells transport service about a new inbound session * * @param cls unused * @param address the address * @param session the new session * @param ats ats information * @param ats_count number of @a ats information */ static void plugin_env_session_start (void *cls, struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct BlacklistCheckContext *blctx; struct GST_BlacklistCheck *blc; int c; if (NULL == address) { GNUNET_break(0); return; } if (NULL == session) { GNUNET_break(0); return; } GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Notification from plugin `%s' about new %s session %p from peer `%s' address `%s'\n", address->transport_name, GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? "inbound" : "outbound", session, GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); /* Do blacklist check if communication with this peer is allowed */ blctx = GNUNET_new (struct BlacklistCheckContext); blctx->address = GNUNET_HELLO_address_copy (address); blctx->session = session; if (ats_count > 0) { blctx->ats = GNUNET_malloc (ats_count * sizeof (struct GNUNET_ATS_Information)); for (c = 0; c < ats_count; c++) { blctx->ats[c].type = ats[c].type; blctx->ats[c].value = ats[c].value; } } GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, blctx); if (NULL != (blc = GST_blacklist_test_allowed (&address->peer, address->transport_name, &plugin_env_session_start_bl_check_cont, blctx))) { blctx->blc = blc; } } /** * Function called by ATS to notify the callee that the * assigned bandwidth or address for a given peer was changed. If the * callback is called with address/bandwidth assignments of zero, the * ATS disconnect function will still be called once the disconnect * actually happened. * * @param cls closure * @param peer the peer this address is intended for * @param address address to use (for peer given in address) * @param session session to use (if available) * @param bandwidth_out assigned outbound bandwidth for the connection in NBO, * 0 to disconnect from peer * @param bandwidth_in assigned inbound bandwidth for the connection in NBO, * 0 to disconnect from peer * @param ats ATS information * @param ats_count number of @a ats elements */ static void ats_request_address_change (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { uint32_t bw_in = ntohl (bandwidth_in.value__); uint32_t bw_out = ntohl (bandwidth_out.value__); /* ATS tells me to disconnect from peer */ if ((0 == bw_in) && (0 == bw_out)) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "ATS tells me to disconnect from peer `%s'\n", GNUNET_i2s (&address->peer)); GST_neighbours_force_disconnect (&address->peer); return; } GST_neighbours_switch_to_address (&address->peer, address, session, ats, ats_count, bandwidth_in, bandwidth_out); } /** * Function called to notify transport users that another * peer connected to us. * * @param cls closure * @param peer the peer that connected * @param bandwidth_in inbound bandwidth in NBO * @param bandwidth_out outbound bandwidth in NBO */ static void neighbours_connect_notification (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { size_t len = sizeof(struct ConnectInfoMessage); char buf[len] GNUNET_ALIGN; struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf; connections++; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "We are now connected to peer `%s' and %u peers in total\n", GNUNET_i2s (peer), connections); connect_msg->header.size = htons (sizeof(buf)); connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); connect_msg->id = *peer; connect_msg->quota_in = bandwidth_in; connect_msg->quota_out = bandwidth_out; GST_clients_broadcast (&connect_msg->header, GNUNET_NO); } /** * Function called to notify transport users that another * peer disconnected from us. * * @param cls closure * @param peer the peer that disconnected */ static void neighbours_disconnect_notification (void *cls, const struct GNUNET_PeerIdentity *peer) { struct DisconnectInfoMessage disconnect_msg; connections--; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peer `%s' disconnected and we are connected to %u peers\n", GNUNET_i2s (peer), connections); GST_manipulation_peer_disconnect (peer); disconnect_msg.header.size = htons (sizeof(struct DisconnectInfoMessage)); disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT); disconnect_msg.reserved = htonl (0); disconnect_msg.peer = *peer; GST_clients_broadcast (&disconnect_msg.header, GNUNET_NO); } /** * Function called to notify transport users that a neighbour peer changed its * active address. * * @param cls closure * @param peer peer this update is about (never NULL) * @param address address, NULL on disconnect * @param state current state this peer is in * @param state_timeout timeout for the current state of the peer * @param bandwidth_in bandwidth assigned inbound * @param bandwidth_out bandwidth assigned outbound */ static void neighbours_changed_notification (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n", GNUNET_i2s (peer), (NULL != address) ? GST_plugins_a2s (address) : "", GNUNET_TRANSPORT_ps2s (state), GNUNET_STRINGS_absolute_time_to_string (state_timeout)); GST_clients_broadcast_peer_notification (peer, address, state, state_timeout); } /** * Function called to notify transport users that a neighbour peer changed its * active address. * * @param cls closure * @param peer peer this update is about (never NULL) * @param address address (never NULL) * @param last_validation point in time when last validation was performed * @param valid_until point in time how long address is valid * @param next_validation point in time when next validation will be performed * @param state state of validation notification */ static void validation_changed_notification (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying about change for for validation entry for peer `%s' with address `%s'\n", GNUNET_i2s (peer), (NULL != address) ? GST_plugins_a2s (address) : ""); GST_clients_broadcast_validation_notification (peer, address, last_validation, valid_until, next_validation, state); } /** * Function called when the service shuts down. Unloads our plugins * and cancels pending validations. * * @param cls closure, unused * @param tc task context (unused) */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GST_neighbours_stop (); GST_validation_stop (); GST_plugins_unload (); GNUNET_ATS_scheduling_done (GST_ats); GST_ats = NULL; GST_clients_stop (); GST_blacklist_stop (); GST_hello_stop (); GST_manipulation_stop (); if (NULL != GST_peerinfo) { GNUNET_PEERINFO_disconnect (GST_peerinfo); GST_peerinfo = NULL; } if (NULL != GST_stats) { GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO); GST_stats = NULL; } if (NULL != GST_my_private_key) { GNUNET_free(GST_my_private_key); GST_my_private_key = NULL; } GST_server = NULL; } /** * Initiate transport service. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { char *keyfile; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; long long unsigned int max_fd_cfg; int max_fd_rlimit; int max_fd; int friend_only; /* setup globals */ GST_cfg = c; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY", &keyfile)) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Transport service is lacking key configuration settings. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, "transport", "HELLO_EXPIRATION", &hello_expiration)) { hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; } GST_server = server; pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile); GNUNET_free(keyfile); GNUNET_assert(NULL != pk); GST_my_private_key = pk; GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg); GST_peerinfo = GNUNET_PEERINFO_connect (GST_cfg); GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key, &GST_my_identity.public_key); GNUNET_assert(NULL != GST_my_private_key); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "My identity is `%4s'\n", GNUNET_i2s (&GST_my_identity)); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL ); if (NULL == GST_peerinfo) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Could not access PEERINFO service. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } max_fd_rlimit = 0; max_fd_cfg = 0; #if HAVE_GETRLIMIT struct rlimit r_file; if (0 == getrlimit (RLIMIT_NOFILE, &r_file)) { max_fd_rlimit = r_file.rlim_cur; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Maximum number of open files was: %u/%u\n", r_file.rlim_cur, r_file.rlim_max); } max_fd_rlimit = (9 * max_fd_rlimit) / 10; /* Keep 10% for rest of transport */ #endif GNUNET_CONFIGURATION_get_value_number (GST_cfg, "transport", "MAX_FD", &max_fd_cfg); if (max_fd_cfg > max_fd_rlimit) max_fd = max_fd_cfg; else max_fd = max_fd_rlimit; if (max_fd < DEFAULT_MAX_FDS) max_fd = DEFAULT_MAX_FDS; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Limiting number of sockets to %u: validation %u, neighbors: %u\n", max_fd, (max_fd / 3), (max_fd / 3) * 2); friend_only = GNUNET_CONFIGURATION_get_value_yesno (GST_cfg, "topology", "FRIENDS-ONLY"); if (GNUNET_SYSERR == friend_only) friend_only = GNUNET_NO; /* According to topology defaults */ /* start subsystems */ GST_hello_start (friend_only, &process_hello_update, NULL ); GNUNET_assert(NULL != GST_hello_get()); GST_blacklist_start (GST_server, GST_cfg, &GST_my_identity); GST_ats = GNUNET_ATS_scheduling_init (GST_cfg, &ats_request_address_change, NULL ); GST_manipulation_init (GST_cfg); GST_plugins_load (&GST_manipulation_recv, &GST_neighbours_register_quota_notification, &GST_neighbours_unregister_quota_notification, &plugin_env_address_change_notification, &plugin_env_session_start, &plugin_env_session_end, &plugin_env_address_to_type, &plugin_env_update_metrics); GST_neighbours_start (NULL, &neighbours_connect_notification, &neighbours_disconnect_notification, &neighbours_changed_notification, (max_fd / 3) * 2); GST_clients_start (GST_server); GST_validation_start (&validation_changed_notification, NULL, (max_fd / 3)); } /** * The main function for the transport service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char * const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "transport", GNUNET_SERVICE_OPTION_NONE, &run, NULL )) ? 0 : 1; } /* end of file gnunet-service-transport.c */ gnunet-0.10.1/src/transport/test_transport_api_reliability.c0000644000175000017500000003267012274162761021336 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_reliability.c * @brief base test case for transport implementations * * This test case serves as a base for tcp and http * transport test cases to check that the transports * achieve reliable message delivery. */ #include "platform.h" #include "gnunet_transport_service.h" #include "gauger.h" #include "transport-testing.h" /** * Testcase timeout */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) static char *test_source; static char *test_plugin; static char *test_name; static int ok; static GNUNET_SCHEDULER_TaskIdentifier die_task; struct PeerContext *p1; struct PeerContext *p2; struct PeerContext *sender; struct PeerContext *receiver; struct GNUNET_TRANSPORT_TransmitHandle *th; char *cfg_file_p1; char *cfg_file_p2; struct GNUNET_TRANSPORT_TESTING_handle *tth; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; /* * Testcase specific declarations */ /** * Note that this value must not significantly exceed * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise * messages may be dropped even for a reliable transport. */ #define TOTAL_MSGS (1024 * 2) #define MTYPE 12345 GNUNET_NETWORK_STRUCT_BEGIN struct TestMessage { struct GNUNET_MessageHeader header; uint32_t num; }; GNUNET_NETWORK_STRUCT_END static int msg_scheduled; static int msg_sent; static int msg_recv_expected; static int msg_recv; static int test_failed; static int test_connected; static unsigned long long total_bytes; static struct GNUNET_TIME_Absolute start_time; /* * END Testcase specific declarations */ #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static void end () { unsigned long long delta; unsigned long long rate; char *value_name; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; rate = (1000LL * 1000LL * total_bytes) / (1024 * delta); FPRINTF (stderr, "\nThroughput was %llu KiBytes/s\n", rate); GNUNET_asprintf (&value_name, "reliable_%s", test_plugin); GAUGER ("TRANSPORT", value_name, (int) rate, "kb/s"); GNUNET_free (value_name); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); } static void end_badly () { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (test_connected == GNUNET_YES) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers got connected\n"); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers got NOT connected\n"); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); ok = GNUNET_SYSERR; } static unsigned int get_size (unsigned int iter) { unsigned int ret; ret = (iter * iter * iter); return sizeof (struct TestMessage) + (ret % 60000); } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { static int n; unsigned int s; char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; const struct TestMessage *hdr; hdr = (const struct TestMessage *) message; s = get_size (n); if (MTYPE != ntohs (message->type)) return; msg_recv_expected = n; msg_recv = ntohl (hdr->num); if (ntohs (message->size) != (s)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", n, s, ntohs (message->size), ntohl (hdr->num)); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } if (ntohl (hdr->num) != n) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", n, s, ntohs (message->size), ntohl (hdr->num)); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } memset (cbuf, n, s - sizeof (struct TestMessage)); if (0 != memcmp (cbuf, &hdr[1], s - sizeof (struct TestMessage))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u with bits %u, but body did not match at position %u\n", n, (unsigned char) n); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); test_failed = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } #if VERBOSE if (ntohl (hdr->num) % 5000 == 0) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') got message %u of size %u from peer (`%s')\n", p->no, ps, ntohl (hdr->num), ntohs (message->size), GNUNET_i2s (peer)); GNUNET_free (ps); } #endif n++; if (0 == (n % (TOTAL_MSGS / 100))) { FPRINTF (stderr, "%s", "."); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); } if (n == TOTAL_MSGS) { ok = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\nAll messages received\n"); end (); } } static size_t notify_ready (void *cls, size_t size, void *buf) { static int n; char *cbuf = buf; struct TestMessage hdr; unsigned int s; unsigned int ret; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready for message %u of %u\n", msg_scheduled, TOTAL_MSGS); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } ret = 0; s = get_size (n); GNUNET_assert (size >= s); GNUNET_assert (buf != NULL); cbuf = buf; do { hdr.header.size = htons (s); hdr.header.type = htons (MTYPE); hdr.num = htonl (n); msg_sent = n; memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage)); ret += sizeof (struct TestMessage); memset (&cbuf[ret], n, s - sizeof (struct TestMessage)); ret += s - sizeof (struct TestMessage); #if VERBOSE if (n % 5000 == 0) { char *receiver_s = GNUNET_strdup (GNUNET_i2s (&receiver->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message of size %u from peer %u (`%4s') -> peer %u (`%s') !\n", n, sender->no, GNUNET_i2s (&sender->id), receiver->no, receiver_s); GNUNET_free (receiver_s); } #endif n++; s = get_size (n); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16)) break; /* sometimes pack buffer full, sometimes not */ } while (size - ret >= s); if (n < TOTAL_MSGS) { if (th == NULL) th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, s, TIMEOUT_TRANSMIT, ¬ify_ready, NULL); msg_scheduled = n; } if (n % 5000 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning total message block of size %u\n", ret); } total_bytes += ret; if (n == TOTAL_MSGS) { FPRINTF (stderr, "%s", "\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All messages sent\n"); } return ret; } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') connected to us!\n", p->no, GNUNET_i2s (peer)); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') disconnected!\n", p->no, GNUNET_i2s (peer)); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void sendtask () { start_time = GNUNET_TIME_absolute_get (); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, get_size (0), TIMEOUT_TRANSMIT, ¬ify_ready, NULL); } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); test_connected = GNUNET_YES; cc = NULL; GNUNET_SCHEDULER_add_now (&sendtask, NULL); } void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; test_connected = GNUNET_NO; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u: `%s' using configuration file `%s'\n", p1->no, GNUNET_i2s (&p1->id), cfg_file_p1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u: `%s' using configuration file `%s'\n", p2->no, GNUNET_i2s (&p2->id), cfg_file_p2); sender = p2; receiver = p1; char *sender_c = GNUNET_strdup (GNUNET_i2s (&sender->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test triest to send from %u (%s) -> peer %u (%s)\n", sender->no, sender_c, receiver->no, GNUNET_i2s (&receiver->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *argv[] = { "test_transport", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); return ret; } /* end of test_transport_api_reliability.c */ gnunet-0.10.1/src/transport/gnunet-transport-certificate-creation.c0000644000175000017500000001000612301361474022413 00000000000000/* This file is part of GNUnet. (C) 2011, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-transport-certificate-creation.c * @brief create certificate for HTTPS transport * @author LRN */ #include "platform.h" #include "gnunet_util_lib.h" #ifndef WINDOWS /** * Turn the given file descriptor in to '/dev/null'. * * @param fd fd to bind to /dev/null * @param flags flags to use (O_RDONLY or O_WRONLY) */ static void make_dev_zero (int fd, int flags) { int z; GNUNET_assert (0 == close (fd)); z = open ("/dev/null", flags); GNUNET_assert (-1 != z); if (z == fd) return; dup2 (z, fd); GNUNET_assert (0 == close (z)); } #endif static void removecerts (const char *file1, const char *file2) { if (GNUNET_YES == GNUNET_DISK_file_test (file1)) { if (0 != CHMOD (file1, S_IWUSR | S_IRUSR)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "chmod", file1); if (0 != REMOVE (file1)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "remove", file1); } if (GNUNET_YES == GNUNET_DISK_file_test (file2)) { if (0 != CHMOD (file2, S_IWUSR | S_IRUSR)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "chmod", file2); if (0 != REMOVE (file2)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "remove", file2); } } int main (int argc, char **argv) { struct GNUNET_OS_Process *openssl; if (3 != argc) { fprintf (stderr, "Invalid arguments.\n"); return 1; } removecerts (argv[1], argv[2]); (void) GNUNET_DISK_directory_create_for_file (argv[1]); (void) GNUNET_DISK_directory_create_for_file (argv[2]); /* eliminate stderr */ #if WINDOWS (void) close (2); #else make_dev_zero (2, O_WRONLY); #endif /* Create RSA Private Key */ /* openssl genrsa -out $1 1024 2> /dev/null */ openssl = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, "openssl", "openssl", "genrsa", "-out", argv[1], "1024", NULL); if (NULL == openssl) { fprintf (stderr, "Failed to run openssl. Is openssl installed?\n"); return 2; } GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (openssl)); GNUNET_OS_process_destroy (openssl); /* Create a self-signed certificate in batch mode using rsa key */ /* openssl req -batch -days 365 -out $2 -new -x509 -key $1 2> /dev/null */ openssl = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, "openssl", "openssl", "req", "-batch", "-days", "365", "-out", argv[2], "-new", "-x509", "-key", argv[1], NULL); if (NULL == openssl) { fprintf (stderr, "Failed to create self-signed certificate with openssl.\n"); return 3; } GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (openssl)); GNUNET_OS_process_destroy (openssl); if (0 != CHMOD (argv[1], S_IRUSR)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "chmod", argv[1]); if (0 != CHMOD (argv[2], S_IRUSR)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "chmod", argv[2]); return 0; } /* end of gnunet-transport-certificate-creation.c */ gnunet-0.10.1/src/transport/test_transport_api_bidirectional_connect.c0000644000175000017500000002576412274162761023354 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_bidirectional_connect.c * @brief base test case for transport implementations * * Perform a 3-way handshake connection set up in both directions at * (almost) the same time */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) #define MTYPE 12345 static char *test_source; static char *test_plugin; static char *test_name; static int ok; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc1; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc2; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; } if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (NULL != th) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != cc2) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc2); cc2 = NULL; } if (NULL != cc1) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc1); cc1 = NULL; } if (NULL != th) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); ok = GNUNET_SYSERR; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if ((MTYPE == ntohs (message->type)) && (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size))) { ok = 0; end (); } else { GNUNET_break (0); ok = 1; end (); } } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= 256); if (buf != NULL) { hdr = buf; hdr->size = htons (sizeof (struct GNUNET_MessageHeader)); hdr->type = htons (MTYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return sizeof (struct GNUNET_MessageHeader); } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, 256, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; GNUNET_assert (NULL != cls); struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (GNUNET_SCHEDULER_NO_TASK != send_task) { GNUNET_SCHEDULER_cancel(send_task); GNUNET_break (0); send_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != th) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { static int connected = GNUNET_NO; if ((cls == cc1) && (NULL != cc2)) { GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc2); } if ((cls == cc2) && (NULL != cc1)) { GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc1); } cc1 = NULL; cc2 = NULL; if (connected > 0) return; connected ++; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); send_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') <-> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc1 = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p2, p1, &testing_connect_cb, cc1); cc2 = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, cc2); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; #if WRITECONFIG setTransportOptions ("test_transport_api_data.conf"); #endif send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of test_transport_api_bidirectional_connect.c */ gnunet-0.10.1/src/transport/test_quota_compliance_udp_peer2.conf0000644000175000017500000000122212225230043022021 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer2 [transport-udp] PORT = 3368 MAX_BPS = 50000000 [arm] PORT = 3087 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_arm_peer2.sock [statistics] PORT = 3088 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_statistics_peer2.sock [resolver] PORT = 3089 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_resolver_peer2.sock [peerinfo] PORT = 3090 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_peerinfo_peer2.sock [transport] PORT = 3091 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_transport_peer2.sock gnunet-0.10.1/src/transport/gnunet-service-transport_manipulation.c0000644000175000017500000005100612316473377022570 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_manipulation.c * @brief transport component manipulation traffic for simulation * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_clients.h" #include "gnunet-service-transport_hello.h" #include "gnunet-service-transport_neighbours.h" #include "gnunet-service-transport_plugins.h" #include "gnunet-service-transport_validation.h" #include "gnunet-service-transport.h" #include "transport.h" enum TRAFFIC_METRIC_DIRECTION { TM_SEND = 0, TM_RECEIVE = 1, TM_BOTH = 2 }; /** * Struct containing information about manipulations to a specific peer */ struct TM_Peer; /** * Manipulation entry */ struct PropManipulationEntry { /** * Next in DLL */ struct PropManipulationEntry *next; /** * Previous in DLL */ struct PropManipulationEntry *prev; /** * ATS type in HBO */ uint32_t type; /** * Value in HBO */ uint32_t metrics[TM_BOTH]; }; /** * Struct containing information about manipulations to a specific peer */ struct TM_Peer { /** * Peer ID */ struct GNUNET_PeerIdentity peer; struct PropManipulationEntry *head; struct PropManipulationEntry *tail; /** * Peer specific manipulation metrics */ uint32_t metrics[TM_BOTH][GNUNET_ATS_QualityPropertiesCount]; /** * Task to schedule delayed sendding */ GNUNET_SCHEDULER_TaskIdentifier send_delay_task; /** * Send queue DLL head */ struct DelayQueueEntry *send_head; /** * Send queue DLL tail */ struct DelayQueueEntry *send_tail; }; struct GST_ManipulationHandle { /** * Hashmap contain all peers currently manipulated */ struct GNUNET_CONTAINER_MultiPeerMap *peers; /** * Peer containing information for general manipulation */ struct TM_Peer general; }; /** * Entry in the delay queue for an outbound delayed message */ struct DelayQueueEntry { /** * Next in DLL */ struct DelayQueueEntry *prev; /** * Previous in DLL */ struct DelayQueueEntry *next; /** * Peer this entry is belonging to * if (NULL == tmp): enqueued in generic DLL and scheduled by generic_send_delay_task * else: enqueued in tmp->send_head and tmp->send_tail and scheduled by tmp->send_delay_task */ struct TM_Peer *tmp; /** * Peer ID */ struct GNUNET_PeerIdentity id; /** * Absolute time when to send */ struct GNUNET_TIME_Absolute sent_at; /** * The message */ void *msg; /** * The message size */ size_t msg_size; /** * Message timeout */ struct GNUNET_TIME_Relative timeout; /** * Transports send continuation */ GST_NeighbourSendContinuation cont; /** * Transports send continuation cls */ void *cont_cls; }; struct GST_ManipulationHandle man_handle; /** * DLL head for delayed messages based on general delay */ struct DelayQueueEntry *generic_dqe_head; /** * DLL tail for delayed messages based on general delay */ struct DelayQueueEntry *generic_dqe_tail; /** * Task to schedule delayed sending based on general delay */ GNUNET_SCHEDULER_TaskIdentifier generic_send_delay_task; static void set_metric(struct TM_Peer *dest, int direction, uint32_t type, uint32_t value) { struct PropManipulationEntry *cur; for (cur = dest->head; NULL != cur; cur = cur->next) { if (cur->type == type) break; } if (NULL == cur) { cur = GNUNET_new (struct PropManipulationEntry); GNUNET_CONTAINER_DLL_insert(dest->head, dest->tail, cur); cur->type = type; cur->metrics[TM_SEND] = UINT32_MAX; cur->metrics[TM_RECEIVE] = UINT32_MAX; } switch (direction) { case TM_BOTH: cur->metrics[TM_SEND] = value; cur->metrics[TM_RECEIVE] = value; break; case TM_SEND: cur->metrics[TM_SEND] = value; break; case TM_RECEIVE: cur->metrics[TM_RECEIVE] = value; break; default: break; } } static uint32_t find_metric(struct TM_Peer *dest, uint32_t type, int direction) { struct PropManipulationEntry *cur; for (cur = dest->head; NULL != cur; cur = cur->next) { if (cur->type == type) return cur->metrics[direction]; } return UINT32_MAX; } /** * Clean up metrics for a peer */ static void free_metric(struct TM_Peer *dest) { struct PropManipulationEntry *cur; struct PropManipulationEntry *next; for (cur = dest->head; NULL != cur; cur = next) { next = cur->next; GNUNET_CONTAINER_DLL_remove(dest->head, dest->tail, cur); GNUNET_free(cur); } } /** * Set traffic metric to manipulate * * @param cls closure * @param client client sending message * @param message containing information */ void GST_manipulation_set_metric(void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message; struct GNUNET_PeerIdentity dummy; struct GNUNET_ATS_Information *ats; struct TM_Peer *tmp; uint32_t type; uint32_t value; uint16_t direction; int c; int c2; if (0 == ntohs(tm->ats_count)) GNUNET_SERVER_receive_done(client, GNUNET_SYSERR); direction = TM_BOTH; switch (ntohs(tm->direction)) { case 1: direction = TM_SEND; break; case 2: direction = TM_RECEIVE; break; case 3: direction = TM_BOTH; break; default: break; } memset(&dummy, '\0', sizeof(struct GNUNET_PeerIdentity)); if (0 == memcmp(&tm->peer, &dummy, sizeof(struct GNUNET_PeerIdentity))) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for all peers \n"); ats = (struct GNUNET_ATS_Information *) &tm[1]; for (c = 0; c < ntohs(tm->ats_count); c++) { type = htonl(ats[c].type); value = htonl(ats[c].value); set_metric(&man_handle.general, direction, type, value); } return; } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for peer `%s'\n", GNUNET_i2s(&tm->peer)); if (NULL == (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, &tm->peer))) { tmp = GNUNET_new (struct TM_Peer); tmp->peer = (tm->peer); for (c = 0; c < TM_BOTH; c++) { for (c2 = 0; c2 < GNUNET_ATS_QualityPropertiesCount; c2++) { tmp->metrics[c][c2] = UINT32_MAX; } } GNUNET_CONTAINER_multipeermap_put(man_handle.peers, &tm->peer, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); } ats = (struct GNUNET_ATS_Information *) &tm[1]; for (c = 0; c < ntohs(tm->ats_count); c++) { type = htonl(ats[c].type); value = htonl(ats[c].value); set_metric(tmp, direction, type, value); } GNUNET_SERVER_receive_done(client, GNUNET_OK); } static void send_delayed(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct DelayQueueEntry *dqe = cls; struct DelayQueueEntry *next; struct TM_Peer *tmp = dqe->tmp; struct GNUNET_TIME_Relative delay; if (NULL != tmp) { GNUNET_break(GNUNET_YES == GST_neighbours_test_connected (&dqe->id)); tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_CONTAINER_DLL_remove(tmp->send_head, tmp->send_tail, dqe); GST_neighbours_send(&dqe->id, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls); next = tmp->send_head; if (NULL != next) { /* More delayed messages */ delay = GNUNET_TIME_absolute_get_remaining(next->sent_at); tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed(delay, &send_delayed, next); } } else { /* Remove from generic queue */ GNUNET_break(GNUNET_YES == GST_neighbours_test_connected (&dqe->id)); generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_CONTAINER_DLL_remove(generic_dqe_head, generic_dqe_tail, dqe); GST_neighbours_send(&dqe->id, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls); next = generic_dqe_head; if (NULL != next) { /* More delayed messages */ delay = GNUNET_TIME_absolute_get_remaining(next->sent_at); generic_send_delay_task = GNUNET_SCHEDULER_add_delayed(delay, &send_delayed, next); } } GNUNET_free(dqe); } /** * Adapter function between transport's send function and transport plugins * * @param target the peer the message to send to * @param msg the message received * @param msg_size message size * @param timeout timeout * @param cont the continuation to call after sending * @param cont_cls cls for continuation */ void GST_manipulation_send(const struct GNUNET_PeerIdentity *target, const void *msg, size_t msg_size, struct GNUNET_TIME_Relative timeout, GST_NeighbourSendContinuation cont, void *cont_cls) { struct TM_Peer *tmp; struct DelayQueueEntry *dqe; struct GNUNET_TIME_Relative delay; if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, target))) { GNUNET_break(GNUNET_YES == GST_neighbours_test_connected(target)); /* Manipulate here */ /* Delay */ if (UINT32_MAX != find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND)) { /* We have a delay */ delay.rel_value_us = find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND); dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size); dqe->id = *target; dqe->tmp = tmp; dqe->sent_at = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay); dqe->cont = cont; dqe->cont_cls = cont_cls; dqe->msg = &dqe[1]; dqe->msg_size = msg_size; dqe->timeout = timeout; memcpy(dqe->msg, msg, msg_size); GNUNET_CONTAINER_DLL_insert_tail(tmp->send_head, tmp->send_tail, dqe); if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task) tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed(delay, &send_delayed, dqe); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Delaying %u byte message to peer `%s' with generic delay for %ms\n", msg_size, GNUNET_i2s (target), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); return; } } else if (UINT32_MAX != find_metric(&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND)) { GNUNET_break(GNUNET_YES == GST_neighbours_test_connected(target)); /* We have a delay */ delay.rel_value_us = find_metric(&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND); dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size); dqe->id = *target; dqe->tmp = NULL; dqe->sent_at = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay); dqe->cont = cont; dqe->cont_cls = cont_cls; dqe->msg = &dqe[1]; dqe->msg_size = msg_size; dqe->timeout = timeout; memcpy(dqe->msg, msg, msg_size); GNUNET_CONTAINER_DLL_insert_tail(generic_dqe_head, generic_dqe_tail, dqe); if (GNUNET_SCHEDULER_NO_TASK == generic_send_delay_task) { generic_send_delay_task = GNUNET_SCHEDULER_add_delayed(delay, &send_delayed, dqe); } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Delaying %u byte message to peer `%s' with peer specific delay for %s\n", msg_size, GNUNET_i2s (target), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); return; } /* Normal sending */ GST_neighbours_send(target, msg, msg_size, timeout, cont, cont_cls); } /** * Function that will be called to manipulate ATS information according to * current manipulation settings * * @param peer the peer * @param address binary address * @param session the session * @param ats the ats information * @param ats_count the number of ats information */ struct GNUNET_ATS_Information * GST_manipulation_manipulate_metrics(const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct GNUNET_ATS_Information *ats_new = GNUNET_malloc (sizeof (struct GNUNET_ATS_Information) *ats_count); struct TM_Peer *tmp; uint32_t m_tmp; uint32_t g_tmp; int d; tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, peer); for (d = 0; d < ats_count; d++) { ats_new[d] = ats[d]; m_tmp = UINT32_MAX; if (NULL != tmp) m_tmp = find_metric(tmp, ntohl(ats[d].type), TM_RECEIVE); g_tmp = find_metric(&man_handle.general, ntohl(ats[d].type), TM_RECEIVE); if (UINT32_MAX != g_tmp) ats_new[d].value = htonl(g_tmp); if (UINT32_MAX != m_tmp) ats_new[d].value = htonl(m_tmp); } return ats_new; } /** * Adapter function between transport plugins and transport receive function * manipulation delays for next send. * * @param cls the closure for transport * @param address the address and the peer the message was received from * @param message the message received * @param session the session the message was received on * @return manipulated delay for next receive */ struct GNUNET_TIME_Relative GST_manipulation_recv (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message) { struct TM_Peer *tmp; uint32_t p_recv_delay; uint32_t g_recv_delay; struct GNUNET_TIME_Relative quota_delay; struct GNUNET_TIME_Relative m_delay; g_recv_delay = find_metric(&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE); if ((g_recv_delay >= GNUNET_TIME_UNIT_ZERO.rel_value_us) && (UINT32_MAX != g_recv_delay)) m_delay.rel_value_us = g_recv_delay; /* Global delay */ else m_delay = GNUNET_TIME_UNIT_ZERO; if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, &address->peer))) { /* Manipulate receive delay */ p_recv_delay = find_metric(tmp, GNUNET_ATS_QUALITY_NET_DELAY, TM_RECEIVE); if (UINT32_MAX != p_recv_delay) m_delay.rel_value_us = p_recv_delay; /* Peer specific delay */ } quota_delay = GST_receive_callback(cls, address, session, message); if (quota_delay.rel_value_us > m_delay.rel_value_us) m_delay = quota_delay; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Delaying next receive for peer `%s' for %s\n", GNUNET_i2s (&address->peer), GNUNET_STRINGS_relative_time_to_string (m_delay, GNUNET_YES)); return m_delay; } /** * Initialize traffic manipulation * * @param GST_cfg configuration handle */ void GST_manipulation_init(const struct GNUNET_CONFIGURATION_Handle *GST_cfg) { unsigned long long tmp; struct GNUNET_TIME_Relative delay; if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(GST_cfg, "transport", "MANIPULATE_DISTANCE_IN", &tmp)) && (tmp > 0)) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Setting inbound distance_in to %llu\n", (unsigned long long) tmp); set_metric(&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DISTANCE, tmp); } if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(GST_cfg, "transport", "MANIPULATE_DISTANCE_OUT", &tmp)) && (tmp > 0)) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Setting outbound distance_in to %llu\n", (unsigned long long) tmp); set_metric(&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DISTANCE, tmp); } if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_time(GST_cfg, "transport", "MANIPULATE_DELAY_IN", &delay)) && (delay.rel_value_us > 0)) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Delaying inbound traffic for %s\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); set_metric(&man_handle.general, TM_RECEIVE, GNUNET_ATS_QUALITY_NET_DELAY, delay.rel_value_us); } if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_time(GST_cfg, "transport", "MANIPULATE_DELAY_OUT", &delay)) && (delay.rel_value_us > 0)) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Delaying outbound traffic for %s\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); set_metric(&man_handle.general, TM_SEND, GNUNET_ATS_QUALITY_NET_DELAY, delay.rel_value_us); } man_handle.peers = GNUNET_CONTAINER_multipeermap_create(10, GNUNET_NO); } static int free_tmps(void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct DelayQueueEntry *dqe; struct DelayQueueEntry *next; if (NULL != value) { struct TM_Peer *tmp = (struct TM_Peer *) value; if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove(man_handle.peers, key, value)) GNUNET_break(0); free_metric(tmp); next = tmp->send_head; while (NULL != (dqe = next)) { next = dqe->next; GNUNET_CONTAINER_DLL_remove(tmp->send_head, tmp->send_tail, dqe); if (NULL != dqe->cont) dqe->cont(dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0); GNUNET_free(dqe); } if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task) { GNUNET_SCHEDULER_cancel(tmp->send_delay_task); tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free(tmp); } return GNUNET_OK; } /** * Notify manipulation about disconnect so it can discard queued messages * * @param peer the disconnecting peer */ void GST_manipulation_peer_disconnect(const struct GNUNET_PeerIdentity *peer) { struct TM_Peer *tmp; struct DelayQueueEntry *dqe; struct DelayQueueEntry *next; if (NULL != (tmp = GNUNET_CONTAINER_multipeermap_get(man_handle.peers, peer))) { next = tmp->send_head; while (NULL != (dqe = next)) { next = dqe->next; GNUNET_CONTAINER_DLL_remove(tmp->send_head, tmp->send_tail, dqe); if (NULL != dqe->cont) dqe->cont(dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0); GNUNET_free(dqe); } } else if (UINT32_MAX != find_metric(&man_handle.general, GNUNET_ATS_QUALITY_NET_DELAY, TM_SEND)) { next = generic_dqe_head; while (NULL != (dqe = next)) { next = dqe->next; if (0 == memcmp(peer, &dqe->id, sizeof(dqe->id))) { GNUNET_CONTAINER_DLL_remove(generic_dqe_head, generic_dqe_tail, dqe); if (NULL != dqe->cont) dqe->cont(dqe->cont_cls, GNUNET_SYSERR, dqe->msg_size, 0); GNUNET_free(dqe); } } if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task) { GNUNET_SCHEDULER_cancel(generic_send_delay_task); generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != generic_dqe_head) generic_send_delay_task = GNUNET_SCHEDULER_add_delayed( GNUNET_TIME_absolute_get_remaining(generic_dqe_head->sent_at), &send_delayed, generic_dqe_head); } } } /** * Stop traffic manipulation */ void GST_manipulation_stop() { struct DelayQueueEntry *cur; struct DelayQueueEntry *next; GNUNET_CONTAINER_multipeermap_iterate(man_handle.peers, &free_tmps, NULL); GNUNET_CONTAINER_multipeermap_destroy(man_handle.peers); next = generic_dqe_head; while (NULL != (cur = next)) { next = cur->next; GNUNET_CONTAINER_DLL_remove(generic_dqe_head, generic_dqe_tail, cur); if (NULL != cur->cont) cur->cont(cur->cont_cls, GNUNET_SYSERR, cur->msg_size, 0); GNUNET_free(cur); } if (GNUNET_SCHEDULER_NO_TASK != generic_send_delay_task) { GNUNET_SCHEDULER_cancel(generic_send_delay_task); generic_send_delay_task = GNUNET_SCHEDULER_NO_TASK; } free_metric(&man_handle.general); man_handle.peers = NULL; } /* end of file gnunet-service-transport_manipulation.c */ gnunet-0.10.1/src/transport/test_transport_api_unix_abstract_peer2.conf0000644000175000017500000000114612276375236023472 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-unix-p2/ [arm] PORT = 12135 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12134 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12133 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12132 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12131 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-unix] PORT = 12136 [testing] USE_ABSTRACT_SOCKETS = YES gnunet-0.10.1/src/transport/test_transport_api_unreliability.c0000644000175000017500000003563012274162761021700 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_unreliability.c * @brief test case for transports; ensures messages get * through, regardless of order * * This test case serves as a base for unreliable * transport test cases to check that the transports * achieve reliable message delivery. */ #include "platform.h" #include "gnunet_transport_service.h" #include "gauger.h" #include "transport-testing.h" /** * Testcase timeout */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 900) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) static char *test_source; static char *test_plugin; static char *test_name; static int ok; static GNUNET_SCHEDULER_TaskIdentifier die_task; struct PeerContext *p1; struct PeerContext *p2; struct GNUNET_TRANSPORT_TransmitHandle *th; char *cfg_file_p1; char *cfg_file_p2; uint32_t max_bps_p1; uint32_t max_bps_p2; struct GNUNET_TRANSPORT_TESTING_handle *tth; /* * Testcase specific declarations */ /** * Total number of messages to send * * Note that this value must not significantly exceed * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise * messages may be dropped even for a reliable transport. */ #define TOTAL_MSGS (1024 * 3) #define MTYPE 12345 GNUNET_NETWORK_STRUCT_BEGIN struct TestMessage { struct GNUNET_MessageHeader header; uint32_t num; }; GNUNET_NETWORK_STRUCT_END static char *test_name; static int msg_scheduled; static int msg_sent; static int msg_recv_expected; static int msg_recv; static int test_connected; static int test_sending; static int test_send_timeout; static unsigned long long total_bytes; static struct GNUNET_TIME_Absolute start_time; static char bitmap[TOTAL_MSGS / 8]; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; /* * END Testcase specific declarations */ #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static int get_bit (const char *map, unsigned int bit); static void end () { unsigned long long delta; unsigned long long rate; char *value_name; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; rate = (1000LL* 1000ll * total_bytes) / (1024 * delta); FPRINTF (stderr, "\nThroughput was %llu KiBytes/s\n", rate); GNUNET_asprintf (&value_name, "unreliable_%s", test_plugin); GAUGER ("TRANSPORT", value_name, (int) rate, "kb/s"); GNUNET_free (value_name); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); ok = 0; int i; for (i = 0; i < TOTAL_MSGS; i++) { if (get_bit (bitmap, i) == 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not receive message %d\n", i); ok = -1; } } } static void end_badly () { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (test_connected == GNUNET_YES) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers got connected\n"); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers got NOT connected\n"); if (test_sending == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Testcase did not send any messages before timeout\n"); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Reliability failed: Last message sent %u, Next message scheduled %u, Last message received %u, Message expected %u\n", msg_sent, msg_scheduled, msg_recv, msg_recv_expected); if (test_send_timeout == GNUNET_YES) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test had timeout while waiting to send data\n"); int i; for (i = 0; i < TOTAL_MSGS; i++) { if (get_bit (bitmap, i) == 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Did not receive message %d\n", i); ok = -1; } } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); ok = GNUNET_SYSERR; } static unsigned int get_size (unsigned int iter) { unsigned int ret; ret = (iter * iter * iter); #ifndef LINUX /* FreeBSD/OSX etc. Unix DGRAMs do not work * with large messages */ if (0 == strcmp ("unix", test_plugin)) return sizeof (struct TestMessage) + (ret % 1024); #endif return sizeof (struct TestMessage) + (ret % 60000); } /** * Sets a bit active in the bitmap. * * @param bitIdx which bit to set * @return GNUNET_SYSERR on error, GNUNET_OK on success */ static int set_bit (unsigned int bitIdx) { size_t arraySlot; unsigned int targetBit; if (bitIdx >= sizeof (bitmap) * 8) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "tried to set bit %d of %d(!?!?)\n", bitIdx, sizeof (bitmap) * 8); return GNUNET_SYSERR; } arraySlot = bitIdx / 8; targetBit = (1L << (bitIdx % 8)); bitmap[arraySlot] |= targetBit; return GNUNET_OK; } /** * Obtain a bit from bitmap. * @param map the bitmap * @param bit index from bitmap * * @return Bit \a bit from hashcode \a code */ static int get_bit (const char *map, unsigned int bit) { if (bit > TOTAL_MSGS) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "get bit %d of %d(!?!?)\n", bit, sizeof (bitmap) * 8); return 0; } return ((map)[bit >> 3] & (1 << (bit & 7))) > 0; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { static int n; unsigned int s; char cbuf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1]; const struct TestMessage *hdr; hdr = (const struct TestMessage *) message; if (MTYPE != ntohs (message->type)) return; msg_recv_expected = n; msg_recv = ntohl (hdr->num); s = get_size (ntohl (hdr->num)); if (ntohs (message->size) != s) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", ntohl (hdr->num), s, ntohs (message->size), ntohl (hdr->num)); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); test_sending = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } memset (cbuf, ntohl (hdr->num), s - sizeof (struct TestMessage)); if (0 != memcmp (cbuf, &hdr[1], s - sizeof (struct TestMessage))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u with bits %u, but body did not match\n", ntohl (hdr->num), (unsigned char) n); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); test_sending = GNUNET_YES; die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } #if VERBOSE if (ntohl (hdr->num) % 5 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got message %u of size %u\n", ntohl (hdr->num), ntohs (message->size)); } #endif n++; if (GNUNET_SYSERR == set_bit (ntohl (hdr->num))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Message id %u is bigger than maxmimum number of messages %u expected\n"), ntohl (hdr->num), TOTAL_MSGS); } test_sending = GNUNET_YES; if (0 == (n % (TOTAL_MSGS / 100))) { FPRINTF (stderr, "%s", "."); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); } if (n == TOTAL_MSGS) { end (); } } static size_t notify_ready (void *cls, size_t size, void *buf) { static int n; char *cbuf = buf; struct TestMessage hdr; unsigned int s; unsigned int ret; th = NULL; if (buf == NULL) { test_send_timeout = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready for msg %u of %u\n", msg_scheduled, TOTAL_MSGS); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } ret = 0; s = get_size (n); GNUNET_assert (size >= s); GNUNET_assert (buf != NULL); GNUNET_assert (n < TOTAL_MSGS); cbuf = buf; do { GNUNET_assert (n < TOTAL_MSGS); hdr.header.size = htons (s); hdr.header.type = htons (MTYPE); hdr.num = htonl (n); msg_sent = n; memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage)); ret += sizeof (struct TestMessage); memset (&cbuf[ret], n, s - sizeof (struct TestMessage)); ret += s - sizeof (struct TestMessage); #if VERBOSE if (n % 5000 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message %u of size %u\n", n, s); } #endif n++; s = get_size (n); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16)) break; /* sometimes pack buffer full, sometimes not */ } while ((size - ret >= s) && (n < TOTAL_MSGS)); if (n < TOTAL_MSGS) { th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, s, TIMEOUT_TRANSMIT, ¬ify_ready, NULL); msg_scheduled = n; } else { FPRINTF (stderr, "%s", "\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All messages scheduled to be sent\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); } if (n % 5000 == 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning total message block of size %u\n", ret); } total_bytes += ret; return ret; } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' disconnected (%p)!\n", GNUNET_i2s (peer), cls); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void sendtask () { start_time = GNUNET_TIME_absolute_get (); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to send %u messages\n", TOTAL_MSGS); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, get_size (0), TIMEOUT_TRANSMIT, ¬ify_ready, NULL); } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %s <-> %s\n", p1_c, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); test_connected = GNUNET_YES; cc = NULL; GNUNET_SCHEDULER_add_now (&sendtask, NULL); } void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; test_connected = GNUNET_NO; cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); test_send_timeout = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api-unreliability", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; #if WRITECONFIG setTransportOptions ("test_transport_api_data.conf"); #endif ok = GNUNET_SYSERR; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); return ret; } /* end of test_transport_api_unreliability.c */ gnunet-0.10.1/src/transport/test_transport_api_unreliability_unix_peer1.conf0000644000175000017500000000110012225230043024504 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-unix-p1/ [arm] PORT = 12125 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12124 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12123 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12122 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12121 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [transport-unix] PORT = 12120 gnunet-0.10.1/src/transport/test_transport_api_wlan_peer1.conf0000644000175000017500000000157212225230043021543 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p1/ [transport-wlan] INTERFACE = mon0 TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock #PREFIX = xterm -T transport2 -e gdb --command=cmd --args #PREFIX = valgrind --leak-check=full --show-reachable=yes --main-stacksize=104857600 #PREFIX = valgrind --leak-check=full --show-reachable=yes #PREFIX = valgrind --leak-check=full #PREFIX = valgrind --tool=massif #PREFIX = gdbserver :2345 gnunet-0.10.1/src/transport/test_transport_api_blacklisting.c0000644000175000017500000002741212274162761021471 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/transport_api_blacklisting.c * @brief test for the blacklisting API * @author Matthias Wachs * */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" struct PeerContext *p1; struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; struct GNUNET_TRANSPORT_TransmitHandle *th; struct GNUNET_TRANSPORT_TESTING_handle *tth; /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) #define TEST_MESSAGE_SIZE 2600 #define TEST_MESSAGE_TYPE 12345 static int ok; static int connected; static int blacklist_request_p1; static int blacklist_request_p2; struct GNUNET_TRANSPORT_Blacklist * blacklist_p1; struct GNUNET_TRANSPORT_Blacklist * blacklist_p2; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static void end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (cc != NULL) { GNUNET_TRANSPORT_TESTING_connect_peers_cancel(tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (blacklist_p1 != NULL) { GNUNET_TRANSPORT_blacklist_cancel (blacklist_p1); blacklist_p1 = NULL; } if (blacklist_p2 != NULL) { GNUNET_TRANSPORT_blacklist_cancel (blacklist_p2); blacklist_p2 = NULL; } if (p1 != NULL) { GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); p1 = NULL; } if (p2 != NULL) { GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); p2 = NULL; } if ((blacklist_request_p1 == GNUNET_YES) && (blacklist_request_p2 == GNUNET_YES) && (connected == GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Peers were not connected, success\n")); ok = 0; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Peers were not connected, fail\n")); ok = 1; } } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (send_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (send_task); send_task = GNUNET_SCHEDULER_NO_TASK; } if (shutdown_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (shutdown_task); shutdown_task = GNUNET_SCHEDULER_NO_TASK; } if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (blacklist_p1 != NULL) GNUNET_TRANSPORT_blacklist_cancel (blacklist_p1); if (blacklist_p2 != NULL) GNUNET_TRANSPORT_blacklist_cancel (blacklist_p2); if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); ok = GNUNET_SYSERR; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if ((TEST_MESSAGE_TYPE == ntohs (message->type)) && (TEST_MESSAGE_SIZE == ntohs (message->size))) { ok = 0; shutdown_task = GNUNET_SCHEDULER_add_now(&end, NULL); } else { GNUNET_break (0); ok = 1; shutdown_task = GNUNET_SCHEDULER_add_now(&end, NULL); } } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= TEST_MESSAGE_SIZE); if (buf != NULL) { hdr = buf; hdr->size = htons (TEST_MESSAGE_SIZE); hdr->type = htons (TEST_MESSAGE_TYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return TEST_MESSAGE_SIZE; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; connected = GNUNET_YES; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); connected = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } int blacklist_cb (void *cls, const struct GNUNET_PeerIdentity * pid) { struct PeerContext * p = cls; int res = GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u : Blacklist request for peer `%s'\n", p->no, GNUNET_i2s (pid)); if (p == p1) { blacklist_request_p1 = GNUNET_YES; res = GNUNET_OK; } else if (p == p2) { blacklist_request_p2 = GNUNET_YES; res = GNUNET_SYSERR; } if (((blacklist_request_p2 == GNUNET_YES) && (blacklist_request_p1 == GNUNET_YES)) && (shutdown_task == GNUNET_SCHEDULER_NO_TASK)) { shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3), &end, NULL); } return res; } void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); connected = GNUNET_NO; blacklist_request_p1 = GNUNET_NO; blacklist_request_p2 = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_api_tcp_peer1.conf", 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_api_tcp_peer2.conf", 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); blacklist_p1 = GNUNET_TRANSPORT_blacklist (p1->cfg, &blacklist_cb, p1); blacklist_p2 = GNUNET_TRANSPORT_blacklist (p2->cfg, &blacklist_cb, p2); GNUNET_assert (blacklist_p1 != NULL); GNUNET_assert (blacklist_p2 != NULL); } static int check () { static char *const argv[] = { "test-transport-api-blacklisting", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-transport-api-blacklisting", "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_log_setup ("test-transport-api-blacklisting", "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); ret = check (); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of transport_api_blacklisting.c */ gnunet-0.10.1/src/transport/Makefile.am0000644000175000017500000013551112320754733014705 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ transport.conf if HAVE_MHD GN_LIBMHD = -lmicrohttpd HTTP_SERVER_PLUGIN_LA = libgnunet_plugin_transport_http_server.la HTTPS_SERVER_PLUGIN_LA = libgnunet_plugin_transport_https_server.la HTTP_SERVER_PLUGIN_TEST = test_plugin_http_server HTTPS_SERVER_PLUGIN_TEST = test_plugin_https_server endif if HAVE_LIBGNURL HTTP_CLIENT_PLUGIN_TEST = test_plugin_http_client HTTPS_CLIENT_PLUGIN_TEST = test_plugin_https_client HTTP_CLIENT_PLUGIN_LA = libgnunet_plugin_transport_http_client.la HTTPS_CLIENT_PLUGIN_LA = libgnunet_plugin_transport_https_client.la endif if HAVE_MHD if HAVE_LIBGNURL HTTP_API_TEST = test_transport_api_http HTTP_REVERSE_API_TEST = test_transport_api_http_reverse HTTP_API_TIMEOUT_TEST = test_transport_api_timeout_http HTTP_REL_TEST = test_transport_api_reliability_http HTTP_QUOTA_TEST = test_quota_compliance_http \ test_quota_compliance_http_asymmetric HTTPS_API_TEST = test_transport_api_https HTTPS_API_TIMEOUT_TEST = test_transport_api_timeout_https HTTPS_REL_TEST = test_transport_api_reliability_https HTTPS_QUOTA_TEST = test_quota_compliance_https \ test_quota_compliance_https_asymmetric endif endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif if LINUX WLAN_BIN = gnunet-helper-transport-wlan WLAN_BIN_DUMMY = gnunet-helper-transport-wlan-dummy WLAN_BIN_SENDER = gnunet-transport-wlan-sender WLAN_BIN_RECEIVER = gnunet-transport-wlan-receiver WLAN_PLUGIN_LA = libgnunet_plugin_transport_wlan.la WLAN_PLUGIN_TEST = test_plugin_wlan WLAN_API_TEST = test_transport_api_wlan WLAN_TIMEOUT_TEST = test_transport_api_timeout_wlan WLAN_REL_TEST = test_transport_api_reliability_wlan WLAN_UREL_TEST = test_transport_api_unreliability_wlan WLAN_QUOTA_TEST = test_quota_compliance_wlan \ test_quota_compliance_wlan_asymmetric endif if LINUX install-exec-hook: $(top_srcdir)/src/transport/install-wlan-helper.sh $(libexecdir) $(SUDO_BINARY) || true else install-exec-hook: endif if LINUX if HAVE_LIBBLUETOOTH BT_BIN = gnunet-helper-transport-bluetooth BT_PLUGIN_LA = libgnunet_plugin_transport_bluetooth.la BT_PLUGIN_TEST = test_plugin_bluetooth BT_API_TEST = test_transport_api_bluetooth BT_TIMEOUT_TEST = test_transport_api_timeout_bluetooth BT_REL_TEST = test_transport_api_reliability_bluetooth BT_UREL_TEST = test_transport_api_unreliability_bluetooth BT_QUOTA_TEST = test_quota_compliance_bluetooth \ test_quota_compliance_bluetooth_asymmetric endif else if MINGW BT_BIN = gnunet-helper-transport-bluetooth BT_PLUGIN_LA = libgnunet_plugin_transport_bluetooth.la endif endif if LINUX if HAVE_LIBBLUETOOTH install-exec-hook2: $(top_srcdir)/src/transport/install-bluetooth-helper.sh $(libexecdir) $(SUDO_BINARY) || true endif else install-exec-hook2: endif if !MINGW UNIX_PLUGIN_LA = libgnunet_plugin_transport_unix.la UNIX_PLUGIN_TEST = test_transport_api_unix UNIX_TEST = test_plugin_unix UNIX_PLUGIN_TIMEOUT_TEST = test_transport_api_timeout_unix UNIX_REL_TEST = test_transport_api_unreliability_unix UNIX_QUOTA_TEST = test_quota_compliance_unix \ test_quota_compliance_unix_asymmetric if LINUX UNIX_API_ABSTRACT_TEST = test_transport_api_unix_abstract endif endif noinst_PROGRAMS = \ $(WLAN_BIN_SENDER) \ $(WLAN_BIN_RECEIVER) if HAVE_TESTING TESTING_LIBS = libgnunettransporttesting.la endif lib_LTLIBRARIES = \ libgnunettransport.la \ $(TESTING_LIBS) libgnunettransporttesting_la_SOURCES = \ transport-testing.c transport-testing.h libgnunettransporttesting_la_LIBADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(GN_LIBINTL) libgnunettransporttesting_la_DEPENDENCIES = \ libgnunettransport.la libgnunettransporttesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) libgnunettransport_la_SOURCES = \ transport_api.c transport.h \ transport_api_blacklist.c \ transport_api_address_to_string.c \ transport_api_monitoring.c libgnunettransport_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunettransport_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 4:0:2 libexec_PROGRAMS = \ $(WLAN_BIN) \ $(WLAN_BIN_DUMMY) \ $(BT_BIN) \ gnunet-service-transport bin_PROGRAMS = \ gnunet-transport \ gnunet-transport-certificate-creation #bin_SCRIPTS = \ # gnunet-transport-certificate-creation gnunet_transport_certificate_creation_SOURCES = \ gnunet-transport-certificate-creation.c gnunet_transport_certificate_creation_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_helper_transport_wlan_SOURCES = \ gnunet-helper-transport-wlan.c gnunet_helper_transport_wlan_dummy_SOURCES = \ gnunet-helper-transport-wlan-dummy.c gnunet_helper_transport_wlan_dummy_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_transport_wlan_sender_SOURCES = \ gnunet-transport-wlan-sender.c gnunet_transport_wlan_sender_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_transport_wlan_receiver_SOURCES = \ gnunet-transport-wlan-receiver.c gnunet_transport_wlan_receiver_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_helper_transport_bluetooth_SOURCES = \ gnunet-helper-transport-bluetooth.c if MINGW gnunet_helper_transport_bluetooth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_helper_transport_bluetooth_LDFLAGS = -lws2_32 else gnunet_helper_transport_bluetooth_LDFLAGS = -lbluetooth endif gnunet_transport_SOURCES = \ gnunet-transport.c gnunet_transport_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_transport_DEPENDENCIES = \ libgnunettransport.la gnunet_service_transport_SOURCES = \ gnunet-service-transport.c gnunet-service-transport.h \ gnunet-service-transport_blacklist.h gnunet-service-transport_blacklist.c \ gnunet-service-transport_clients.h gnunet-service-transport_clients.c \ gnunet-service-transport_hello.h gnunet-service-transport_hello.c \ gnunet-service-transport_neighbours.h gnunet-service-transport_neighbours.c \ gnunet-service-transport_plugins.h gnunet-service-transport_plugins.c \ gnunet-service-transport_validation.h gnunet-service-transport_validation.c \ gnunet-service-transport_manipulation.h gnunet-service-transport_manipulation.c # Note that while gnunet-service-transport does not use libgnunetnat # directly, we must link against it as GNUNET_NAT_mini_map_stop will # leave a 'dangling' task to process_unmap_output which will cause # a crash on unloading of a plugin unless the service links against # that library as well. gnunet_service_transport_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_GLPK) \ $(GN_LIBINTL) gnunet_service_transport_DEPENDENCIES = \ libgnunettransport.la gnunet_service_transport_CFLAGS = \ $(CFLAGS) # -DANALYZE plugin_LTLIBRARIES = \ libgnunet_plugin_transport_tcp.la \ libgnunet_plugin_transport_udp.la \ $(UNIX_PLUGIN_LA) \ $(HTTP_CLIENT_PLUGIN_LA) \ $(HTTPS_CLIENT_PLUGIN_LA) \ $(HTTP_SERVER_PLUGIN_LA) \ $(HTTPS_SERVER_PLUGIN_LA) \ $(WLAN_PLUGIN_LA) \ $(BT_PLUGIN_LA) \ libgnunet_plugin_transport_template.la libgnunet_plugin_transport_tcp_la_SOURCES = \ plugin_transport_tcp.c libgnunet_plugin_transport_tcp_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_transport_tcp_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_template_la_SOURCES = \ plugin_transport_template.c libgnunet_plugin_transport_template_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_transport_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_wlan_la_SOURCES = \ plugin_transport_wlan.c plugin_transport_wlan.h libgnunet_plugin_transport_wlan_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_wlan_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_bluetooth_la_SOURCES = \ plugin_transport_bluetooth.c plugin_transport_wlan.h libgnunet_plugin_transport_bluetooth_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_bluetooth_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_udp_la_SOURCES = \ plugin_transport_udp.c plugin_transport_udp.h \ plugin_transport_udp_broadcasting.c libgnunet_plugin_transport_udp_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/fragmentation/libgnunetfragmentation.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_transport_udp_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_unix_la_SOURCES = \ plugin_transport_unix.c libgnunet_plugin_transport_unix_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_transport_unix_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_http_client_la_SOURCES = \ plugin_transport_http_client.c plugin_transport_http_common.c plugin_transport_http_common.h libgnunet_plugin_transport_http_client_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ @LIBGNURL@ \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_http_client_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_http_client_la_CFLAGS = \ $(CFLAGS) libgnunet_plugin_transport_http_client_la_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) libgnunet_plugin_transport_http_server_la_SOURCES = \ plugin_transport_http_server.c plugin_transport_http_common.c libgnunet_plugin_transport_http_server_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_http_server_la_LDFLAGS = \ $(GN_LIBMHD) \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_http_server_la_CFLAGS = \ $(CFLAGS) libgnunet_plugin_transport_https_client_la_SOURCES = \ plugin_transport_http_client.c plugin_transport_http_common.c libgnunet_plugin_transport_https_client_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ @LIBGNURL@ \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_https_client_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_https_client_la_CFLAGS = \ $(CFLAGS) -DBUILD_HTTPS libgnunet_plugin_transport_https_client_la_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) libgnunet_plugin_transport_https_server_la_SOURCES = \ plugin_transport_http_server.c plugin_transport_http_common.c libgnunet_plugin_transport_https_server_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_https_server_la_LDFLAGS = \ $(GN_LIBMHD) \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_https_server_la_CFLAGS = \ $(CFLAGS) -DBUILD_HTTPS if HAVE_TESTING check_PROGRAMS = \ test_transport_testing_startstop \ test_transport_testing_restart \ test_transport_testing \ test_transport_startonly \ test_plugin_tcp \ test_plugin_udp \ $(UNIX_TEST) \ $(WLAN_PLUGIN_TEST) \ $(BT_PLUGIN_TEST) \ test_http_common \ $(HTTP_CLIENT_PLUGIN_TEST) \ $(HTTPS_CLIENT_PLUGIN_TEST) \ $(HTTP_SERVER_PLUGIN_TEST) \ $(HTTPS_SERVER_PLUGIN_TEST) \ test_transport_api_blacklisting \ test_transport_api_disconnect_tcp \ test_transport_api_bidirectional_connect \ test_transport_api_tcp \ test_transport_api_restart_1peer \ test_transport_api_restart_2peers \ test_transport_api_timeout_tcp \ test_transport_api_limited_sockets_tcp \ test_transport_api_tcp_nat \ test_transport_api_udp \ test_transport_api_timeout_udp \ $(UNIX_PLUGIN_TEST) \ $(UNIX_PLUGIN_TIMEOUT_TEST) \ $(UNIX_API_ABSTRACT_TEST) \ test_transport_api_udp_nat \ $(HTTP_API_TEST) \ $(HTTP_REVERSE_API_TEST) \ $(HTTP_API_TIMEOUT_TEST) \ $(HTTPS_API_TEST) \ $(HTTPS_API_TIMEOUT_TEST) \ $(WLAN_API_TEST) \ $(WLAN_TIMEOUT_TEST) \ $(BT_API_TEST) \ $(BT_TIMEOUT_TEST) \ test_transport_api_multi \ test_transport_api_monitoring \ test_transport_api_monitoring_validation \ test_transport_blacklisting_no_bl \ test_transport_blacklisting_outbound_bl_full \ test_transport_blacklisting_outbound_bl_plugin \ test_transport_blacklisting_inbound_bl_plugin \ test_transport_blacklisting_inbound_bl_full \ test_transport_blacklisting_multiple_plugins \ test_transport_api_manipulation_send_tcp \ test_transport_api_manipulation_recv_tcp \ test_transport_api_manipulation_cfg \ test_transport_api_reliability_tcp \ test_transport_api_reliability_tcp_nat \ test_transport_api_unreliability_udp \ test_transport_api_unreliability_constant_udp \ $(UNIX_REL_TEST) \ $(HTTP_REL_TEST) \ $(HTTPS_REL_TEST) \ $(WLAN_REL_TEST) \ $(WLAN_UREL_TEST) \ $(BT_REL_TEST) \ $(BT_UREL_TEST) \ test_quota_compliance_tcp \ test_quota_compliance_tcp_asymmetric \ test_quota_compliance_udp \ $(UNIX_QUOTA_TEST) \ $(HTTP_QUOTA_TEST) \ $(HTTPS_QUOTA_TEST) \ $(WLAN_QUOTA_TEST) \ $(BT_QUOTA_TEST) endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ test_transport_testing_startstop \ test_transport_testing_restart \ test_transport_testing \ test_transport_startonly \ test_plugin_tcp \ test_plugin_udp \ $(UNIX_TEST) \ $(WLAN_PLUGIN_TEST) \ $(BT_PLUGIN_TEST) \ test_transport_api_blacklisting \ test_transport_api_disconnect_tcp \ test_transport_api_bidirectional_connect \ test_transport_api_tcp \ test_transport_api_restart_1peer \ test_transport_api_restart_2peers \ test_transport_api_timeout_tcp \ test_transport_api_limited_sockets_tcp \ test_transport_api_tcp_nat \ test_transport_api_udp \ test_transport_api_timeout_udp \ $(UNIX_PLUGIN_TEST) \ $(UNIX_PLUGIN_TIMEOUT_TEST) \ $(UNIX_API_ABSTRACT_TEST) \ test_transport_api_udp_nat \ $(HTTP_API_TEST) \ $(HTTP_API_TIMEOUT_TEST) \ $(HTTPS_API_TEST) \ $(HTTPS_API_TIMEOUT_TEST) \ $(WLAN_API_TEST) \ $(WLAN_TIMEOUT_TEST) \ $(BT_API_TEST) \ $(BT_TIMEOUT_TEST) \ test_transport_api_multi \ test_transport_api_monitoring \ test_transport_api_monitoring_validation \ test_transport_blacklisting_no_bl \ test_transport_blacklisting_outbound_bl_full \ test_transport_blacklisting_outbound_bl_plugin \ test_transport_blacklisting_inbound_bl_plugin \ test_transport_blacklisting_inbound_bl_full \ test_transport_blacklisting_multiple_plugins \ test_transport_api_manipulation_send_tcp \ test_transport_api_manipulation_recv_tcp \ test_transport_api_manipulation_cfg \ test_transport_api_reliability_tcp \ test_transport_api_reliability_tcp_nat \ test_transport_api_unreliability_udp \ test_transport_api_unreliability_constant_udp \ $(UNIX_REL_TEST) \ $(HTTP_REL_TEST) \ $(HTTPS_REL_TEST) \ $(WLAN_REL_TEST) \ $(WLAN_UREL_TEST) \ $(BT_REL_TEST) \ $(BT_UREL_TEST) \ test_quota_compliance_tcp \ test_quota_compliance_tcp_asymmetric \ test_quota_compliance_udp \ $(UNIX_QUOTA_TEST) \ $(HTTP_QUOTA_TEST) \ $(HTTPS_QUOTA_TEST) endif test_transport_testing_startstop_SOURCES = \ test_transport_testing_startstop.c test_transport_testing_startstop_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_testing_restart_SOURCES = \ test_transport_testing_restart.c test_transport_testing_restart_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_testing_SOURCES = \ test_transport_testing.c test_transport_testing_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_blacklisting_SOURCES = \ test_transport_api_blacklisting.c test_transport_api_blacklisting_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_no_bl_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_no_bl_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_outbound_bl_full_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_outbound_bl_full_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_outbound_bl_plugin_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_outbound_bl_plugin_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_inbound_bl_full_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_inbound_bl_full_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_inbound_bl_plugin_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_inbound_bl_plugin_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_blacklisting_multiple_plugins_SOURCES = \ test_transport_blacklisting.c test_transport_blacklisting_multiple_plugins_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_disconnect_tcp_SOURCES = \ test_transport_api_disconnect.c test_transport_api_disconnect_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_startonly_SOURCES = \ test_transport_startonly.c test_transport_startonly_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_tcp_SOURCES = \ test_plugin_transport.c test_plugin_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_udp_SOURCES = \ test_plugin_transport.c test_plugin_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_unix_SOURCES = \ test_plugin_transport.c test_plugin_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_wlan_SOURCES = \ test_plugin_transport.c test_plugin_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_bluetooth_SOURCES = \ test_plugin_transport.c test_plugin_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_http_common_SOURCES = \ test_http_common.c plugin_transport_http_common.c test_http_common_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_http_server_SOURCES = \ test_plugin_transport.c test_plugin_http_server_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_https_server_SOURCES = \ test_plugin_transport.c test_plugin_https_server_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_http_client_SOURCES = \ test_plugin_transport.c test_plugin_http_client_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_plugin_https_client_SOURCES = \ test_plugin_transport.c test_plugin_https_client_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_tcp_SOURCES = \ test_transport_api.c test_transport_api_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_bidirectional_connect_SOURCES = \ test_transport_api_bidirectional_connect.c test_transport_api_bidirectional_connect_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_restart_1peer_SOURCES = \ test_transport_api_restart_1peer.c test_transport_api_restart_1peer_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_restart_2peers_SOURCES = \ test_transport_api_restart_2peers.c test_transport_api_restart_2peers_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_limited_sockets_tcp_SOURCES = \ test_transport_api_limited_sockets.c test_transport_api_limited_sockets_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_tcp_nat_SOURCES = \ test_transport_api.c test_transport_api_tcp_nat_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_manipulation_send_tcp_SOURCES = \ test_transport_api_manipulation_send_tcp.c test_transport_api_manipulation_send_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_manipulation_recv_tcp_SOURCES = \ test_transport_api_manipulation_recv_tcp.c test_transport_api_manipulation_recv_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_manipulation_cfg_SOURCES = \ test_transport_api_manipulation_cfg.c test_transport_api_manipulation_cfg_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_tcp_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_tcp_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_unix_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_wlan_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_bluetooth_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_tcp_nat_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_tcp_nat_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_wlan_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_bluetooth_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_wlan_SOURCES = \ test_transport_api_unreliability.c test_transport_api_unreliability_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_bluetooth_SOURCES = \ test_transport_api_unreliability.c test_transport_api_unreliability_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_udp_SOURCES = \ test_transport_api.c test_transport_api_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_udp_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_udp_nat_SOURCES = \ test_transport_api.c test_transport_api_udp_nat_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unix_SOURCES = \ test_transport_api.c test_transport_api_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unix_abstract_SOURCES = \ test_transport_api.c test_transport_api_unix_abstract_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la # HTTP tests test_transport_api_http_SOURCES = \ test_transport_api.c test_transport_api_http_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_http_reverse_SOURCES = \ test_transport_api.c test_transport_api_http_reverse_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_http_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_http_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_http_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_http_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_http_SOURCES = \ test_quota_compliance.c test_quota_compliance_http_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_http_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_http_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_https_SOURCES = \ test_quota_compliance.c test_quota_compliance_https_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_https_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_https_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la # HTTPS tests test_transport_api_https_SOURCES = \ test_transport_api.c test_transport_api_https_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_timeout_https_SOURCES = \ test_transport_api_timeout.c test_transport_api_timeout_https_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_reliability_https_SOURCES = \ test_transport_api_reliability.c test_transport_api_reliability_https_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_unix_SOURCES = \ test_transport_api_unreliability.c test_transport_api_unreliability_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_udp_SOURCES = \ test_transport_api_unreliability.c test_transport_api_unreliability_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_unreliability_constant_udp_SOURCES = \ test_transport_api_unreliability_constant.c test_transport_api_unreliability_constant_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la if LINUX test_transport_api_wlan_SOURCES = \ test_transport_api.c test_transport_api_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la endif if LINUX if HAVE_LIBBLUETOOTH test_transport_api_bluetooth_SOURCES = \ test_transport_api.c test_transport_api_bluetooth_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la endif endif test_quota_compliance_tcp_SOURCES = \ test_quota_compliance.c test_quota_compliance_tcp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_tcp_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_tcp_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_udp_SOURCES = \ test_quota_compliance.c test_quota_compliance_udp_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_unix_SOURCES = \ test_quota_compliance.c test_quota_compliance_unix_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_unix_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_unix_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_wlan_SOURCES = \ test_quota_compliance.c test_quota_compliance_wlan_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_wlan_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_wlan_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_bluetooth_SOURCES = \ test_quota_compliance.c test_quota_compliance_bluetooth_LDADD = \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_quota_compliance_bluetooth_asymmetric_SOURCES = \ test_quota_compliance.c test_quota_compliance_bluetooth_asymmetric_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_multi_SOURCES = \ test_transport_api.c test_transport_api_multi_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_monitoring_SOURCES = \ test_transport_api_monitoring.c test_transport_api_monitoring_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la test_transport_api_monitoring_validation_SOURCES = \ test_transport_api_monitoring_validation.c test_transport_api_monitoring_validation_LDADD = \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/transport/libgnunettransporttesting.la EXTRA_DIST = \ test_plugin_hostkey \ test_plugin_hostkey.ecc \ template_cfg_peer1.conf\ template_cfg_peer2.conf\ test_plugin_transport_data.conf\ test_plugin_transport_data_udp.conf\ test_quota_compliance_data.conf\ test_quota_compliance_http_peer1.conf\ test_quota_compliance_http_peer2.conf\ test_quota_compliance_https_peer1.conf\ test_quota_compliance_https_peer2.conf\ test_quota_compliance_tcp_peer1.conf\ test_quota_compliance_tcp_peer2.conf\ test_quota_compliance_udp_peer1.conf\ test_quota_compliance_udp_peer2.conf\ test_quota_compliance_unix_peer1.conf\ test_quota_compliance_unix_peer2.conf\ test_quota_compliance_wlan_peer1.conf\ test_quota_compliance_wlan_peer2.conf\ test_quota_compliance_bluetooth_peer1.conf\ test_quota_compliance_bluetooth_peer2.conf\ test_quota_compliance_http_asymmetric_peer1.conf\ test_quota_compliance_http_asymmetric_peer2.conf\ test_quota_compliance_https_asymmetric_peer1.conf\ test_quota_compliance_https_asymmetric_peer2.conf\ test_quota_compliance_tcp_asymmetric_peer1.conf\ test_quota_compliance_tcp_asymmetric_peer2.conf\ test_quota_compliance_unix_asymmetric_peer1.conf\ test_quota_compliance_unix_asymmetric_peer2.conf\ test_quota_compliance_wlan_asymmetric_peer1.conf\ test_quota_compliance_wlan_asymmetric_peer2.conf\ test_quota_compliance_bluetooth_asymmetric_peer1.conf\ test_quota_compliance_bluetooth_asymmetric_peer2.conf\ test_transport_api_data.conf\ test_transport_api_http_peer1.conf\ test_transport_api_http_peer2.conf\ test_transport_api_https_peer1.conf\ test_transport_api_https_peer2.conf\ test_transport_api_limited_sockets_tcp_peer1.conf\ test_transport_api_limited_sockets_tcp_peer2.conf\ test_transport_api_timeout_tcp_peer1.conf\ test_transport_api_timeout_tcp_peer2.conf\ test_transport_api_multi_peer1.conf\ test_transport_api_multi_peer2.conf\ test_transport_api_reliability_http_peer1.conf\ test_transport_api_reliability_http_peer2.conf\ test_transport_api_reliability_https_peer1.conf\ test_transport_api_reliability_https_peer2.conf\ test_transport_api_reliability_tcp_nat_peer1.conf\ test_transport_api_reliability_tcp_nat_peer2.conf\ test_transport_api_reliability_tcp_peer1.conf\ test_transport_api_reliability_tcp_peer2.conf\ test_transport_api_reliability_wlan_peer1.conf\ test_transport_api_reliability_wlan_peer2.conf\ test_transport_api_reliability_bluetooth_peer1.conf\ test_transport_api_reliability_bluetooth_peer2.conf\ test_transport_api_bidirectional_connect_peer1.conf\ test_transport_api_bidirectional_connect_peer2.conf\ test_transport_api_manipulation_send_tcp_peer1.conf\ test_transport_api_manipulation_send_tcp_peer2.conf\ test_transport_api_manipulation_recv_tcp_peer1.conf\ test_transport_api_manipulation_recv_tcp_peer2.conf\ test_transport_api_manipulation_cfg_peer1.conf\ test_transport_api_manipulation_cfg_peer2.conf\ test_transport_api_tcp_nat_peer1.conf\ test_transport_api_tcp_nat_peer2.conf\ test_transport_api_tcp_peer1.conf\ test_transport_api_tcp_peer2.conf\ test_transport_api_udp_nat_peer1.conf\ test_transport_api_udp_nat_peer2.conf\ test_transport_api_udp_peer1.conf\ test_transport_api_udp_peer2.conf\ test_transport_api_timeout_udp_peer1.conf\ test_transport_api_timeout_udp_peer2.conf\ test_transport_api_unix_peer1.conf\ test_transport_api_unix_peer2.conf\ test_transport_api_unix_abstract_peer1.conf \ test_transport_api_unix_abstract_peer2.conf \ test_transport_api_timeout_unix_peer1.conf\ test_transport_api_timeout_unix_peer2.conf\ test_transport_api_timeout_wlan_peer1.conf \ test_transport_api_timeout_wlan_peer2.conf \ test_transport_api_timeout_bluetooth_peer1.conf\ test_transport_api_timeout_bluetooth_peer2.conf\ test_transport_api_unreliability_udp_peer1.conf\ test_transport_api_unreliability_udp_peer2.conf\ test_transport_api_unreliability_unix_peer1.conf\ test_transport_api_unreliability_unix_peer2.conf\ test_transport_api_unreliability_wlan_peer1.conf\ test_transport_api_unreliability_wlan_peer2.conf\ test_transport_api_unreliability_bluetooth_peer1.conf\ test_transport_api_unreliability_bluetooth_peer2.conf\ test_transport_api_wlan_peer1.conf\ test_transport_api_wlan_peer2.conf\ test_transport_api_bluetooth_peer1.conf\ test_transport_api_bluetooth_peer2.conf\ test_transport_api_monitoring_peer1.conf\ test_transport_api_monitoring_peer2.conf\ test_transport_api_monitoring_validation_peer1.conf\ test_transport_api_monitoring_validation_peer2.conf\ test_transport_defaults.conf\ test_transport_startonly.conf\ test_transport_api_disconnect_tcp_peer1.conf\ test_transport_api_disconnect_tcp_peer2.conf\ test_transport_api_timeout_http_peer1.conf\ test_transport_api_timeout_http_peer2.conf\ test_transport_api_timeout_https_peer1.conf\ test_transport_api_timeout_https_peer2.conf\ test_transport_api_unreliability_constant_udp_peer1.conf\ test_transport_api_unreliability_constant_udp_peer2.conf\ test_transport_blacklisting_cfg_peer1.conf \ test_transport_blacklisting_cfg_peer2.conf \ test_transport_blacklisting_cfg_blp_peer1_full.conf\ test_transport_blacklisting_cfg_blp_peer1_plugin.conf \ test_transport_blacklisting_cfg_blp_peer2_full.conf\ test_transport_blacklisting_cfg_blp_peer2_plugin.conf \ test_transport_blacklisting_cfg_blp_peer1_multiple_plugins.conf \ test_transport_blacklisting_cfg_blp_peer2_multiple_plugins.conf \ test_transport_api_http_reverse_peer1.conf \ test_transport_api_http_reverse_peer2.conf gnunet-0.10.1/src/transport/test_transport_api_timeout_https_peer2.conf0000644000175000017500000000126012225230043023505 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-https-p2/ [transport-https_server] PORT = 12110 KEY_FILE = $GNUNET_TEST_HOME/https_key_p2.key CERT_FILE = $GNUNET_TEST_HOME/https_cert_p2.crt [arm] PORT = 12115 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12114 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12113 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12112 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12111 PLUGINS = https_server UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/plugin_transport_tcp.c0000644000175000017500000023066612320526612017275 00000000000000/* This file is part of GNUnet (C) 2002--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_tcp.c * @brief Implementation of the TCP transport service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_constants.h" #include "gnunet_util_lib.h" #include "gnunet_nat_lib.h" #include "gnunet_protocols.h" #include "gnunet_resolver_service.h" #include "gnunet_signatures.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "transport.h" #define LOG(kind,...) GNUNET_log_from (kind, "transport-tcp",__VA_ARGS__) #define PLUGIN_NAME "tcp" #define EXTRA_CHECKS ALLOW_EXTRA_CHECKS /** * How long until we give up on establishing an NAT connection? * Must be > 4 RTT */ #define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) GNUNET_NETWORK_STRUCT_BEGIN /** * Address options */ static uint32_t myoptions; /** * Initial handshake message for a session. */ struct WelcomeMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME. */ struct GNUNET_MessageHeader header; /** * Identity of the node connecting (TCP client) */ struct GNUNET_PeerIdentity clientIdentity; }; /** * Basically a WELCOME message, but with the purpose * of giving the waiting peer a client handle to use */ struct TCP_NAT_ProbeMessage { /** * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE. */ struct GNUNET_MessageHeader header; /** * Identity of the sender of the message. */ struct GNUNET_PeerIdentity clientIdentity; }; GNUNET_NETWORK_STRUCT_END /** * Context for sending a NAT probe via TCP. */ struct TCPProbeContext { /** * Active probes are kept in a DLL. */ struct TCPProbeContext *next; /** * Active probes are kept in a DLL. */ struct TCPProbeContext *prev; /** * Probe connection. */ struct GNUNET_CONNECTION_Handle *sock; /** * Message to be sent. */ struct TCP_NAT_ProbeMessage message; /** * Handle to the transmission. */ struct GNUNET_CONNECTION_TransmitHandle *transmit_handle; /** * Transport plugin handle. */ struct Plugin *plugin; }; GNUNET_NETWORK_STRUCT_BEGIN /** * Network format for IPv4 addresses. */ struct IPv4TcpAddress { /** * Optional options and flags for this address */ uint32_t options; /** * IPv4 address, in network byte order. */ uint32_t ipv4_addr GNUNET_PACKED; /** * Port number, in network byte order. */ uint16_t t4_port GNUNET_PACKED; }; /** * Network format for IPv6 addresses. */ struct IPv6TcpAddress { /** * Optional flags for this address */ uint32_t options; /** * IPv6 address. */ struct in6_addr ipv6_addr GNUNET_PACKED; /** * Port number, in network byte order. */ uint16_t t6_port GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /** * Encapsulation of all of the state of the plugin. */ struct Plugin; /** * Information kept for each message that is yet to * be transmitted. */ struct PendingMessage { /** * This is a doubly-linked list. */ struct PendingMessage *next; /** * This is a doubly-linked list. */ struct PendingMessage *prev; /** * The pending message */ const char *msg; /** * Continuation function to call once the message * has been sent. Can be NULL if there is no * continuation to call. */ GNUNET_TRANSPORT_TransmitContinuation transmit_cont; /** * Closure for transmit_cont. */ void *transmit_cont_cls; /** * Timeout value for the pending message. */ struct GNUNET_TIME_Absolute timeout; /** * So that the gnunet-service-transport can group messages together, * these pending messages need to accept a message buffer and size * instead of just a GNUNET_MessageHeader. */ size_t message_size; }; /** * Session handle for TCP connections. */ struct Session { /** * To whom are we talking to (set to our identity * if we are still waiting for the welcome message) */ struct GNUNET_PeerIdentity target; /** * API requirement. */ struct SessionHeader header; /** * Pointer to the global plugin struct. */ struct Plugin *plugin; /** * The client (used to identify this connection) */ struct GNUNET_SERVER_Client *client; /** * Task cleaning up a NAT client connection establishment attempt; */ GNUNET_SCHEDULER_TaskIdentifier nat_connection_timeout; /** * Messages currently pending for transmission * to this peer, if any. */ struct PendingMessage *pending_messages_head; /** * Messages currently pending for transmission * to this peer, if any. */ struct PendingMessage *pending_messages_tail; /** * Handle for pending transmission request. */ struct GNUNET_SERVER_TransmitHandle *transmit_handle; /** * ID of task used to delay receiving more to throttle sender. */ GNUNET_SCHEDULER_TaskIdentifier receive_delay_task; /** * Session timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; struct GNUNET_HELLO_Address *address; /** * Address of the other peer (either based on our 'connect' * call or on our 'accept' call). * * struct IPv4TcpAddress or struct IPv6TcpAddress */ //void *addr; /** * Length of @e addr. */ //size_t addrlen; /** * Last activity on this connection. Used to select preferred * connection. */ struct GNUNET_TIME_Absolute last_activity; /** * Are we still expecting the welcome message? (#GNUNET_YES/#GNUNET_NO) */ int expecting_welcome; /** * Was this session created using NAT traversal? */ int is_nat; /** * ATS network type in NBO */ enum GNUNET_ATS_Network_Type ats_address_network_type; }; /** * Encapsulation of all of the state of the plugin. */ struct Plugin { /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * The listen socket. */ struct GNUNET_CONNECTION_Handle *lsock; /** * Our handle to the NAT module. */ struct GNUNET_NAT_Handle *nat; /** * Map from peer identities to sessions for the given peer. */ struct GNUNET_CONTAINER_MultiPeerMap *sessionmap; /** * Handle to the network service. */ struct GNUNET_SERVICE_Context *service; /** * Handle to the server for this service. */ struct GNUNET_SERVER_Handle *server; /** * Copy of the handler array where the closures are * set to this struct's instance. */ struct GNUNET_SERVER_MessageHandler *handlers; /** * Map of peers we have tried to contact behind a NAT */ struct GNUNET_CONTAINER_MultiPeerMap *nat_wait_conns; /** * List of active TCP probes. */ struct TCPProbeContext *probe_head; /** * List of active TCP probes. */ struct TCPProbeContext *probe_tail; /** * Handle for (DYN)DNS lookup of our external IP. */ struct GNUNET_RESOLVER_RequestHandle *ext_dns; /** * How many more TCP sessions are we allowed to open right now? */ unsigned long long max_connections; /** * How many more TCP sessions do we have right now? */ unsigned long long cur_connections; /** * ID of task used to update our addresses when one expires. */ GNUNET_SCHEDULER_TaskIdentifier address_update_task; /** * Port that we are actually listening on. */ uint16_t open_port; /** * Port that the user said we would have visible to the * rest of the world. */ uint16_t adv_port; }; /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure ('struct Plugin*') * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ static const char * tcp_address_to_string (void *cls, const void *addr, size_t addrlen); /** * Function to check if an inbound connection is acceptable. * Mostly used to limit the total number of open connections * we can have. * * @param cls the `struct Plugin` * @param ucred credentials, if available, otherwise NULL * @param addr address * @param addrlen length of address * @return #GNUNET_YES to allow, #GNUNET_NO to deny, #GNUNET_SYSERR * for unknown address family (will be denied). */ static int plugin_tcp_access_check (void *cls, const struct GNUNET_CONNECTION_Credentials *ucred, const struct sockaddr *addr, socklen_t addrlen) { struct Plugin *plugin = cls; LOG(GNUNET_ERROR_TYPE_DEBUG, "Accepting new incoming TCP connection from `%s'\n", GNUNET_a2s (addr, addrlen)); if (plugin->cur_connections >= plugin->max_connections) return GNUNET_NO; plugin->cur_connections++; return GNUNET_YES; } /** * Our external IP address/port mapping has changed. * * @param cls closure, the 'struct Plugin' * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean * the previous (now invalid) one * @param addr either the previous or the new public IP address * @param addrlen actual lenght of the address */ static void tcp_nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { struct Plugin *plugin = cls; struct GNUNET_HELLO_Address *address; struct IPv4TcpAddress t4; struct IPv6TcpAddress t6; void *arg; size_t args; LOG(GNUNET_ERROR_TYPE_INFO, "NAT notification to %s address `%s'\n", (GNUNET_YES == add_remove) ? "add" : "remove", GNUNET_a2s (addr, addrlen)); /* convert 'addr' to our internal format */ switch (addr->sa_family) { case AF_INET: GNUNET_assert(addrlen == sizeof(struct sockaddr_in)); memset (&t4, 0, sizeof(t4)); t4.options = htonl (myoptions); t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; t4.t4_port = ((struct sockaddr_in *) addr)->sin_port; arg = &t4; args = sizeof (t4); break; case AF_INET6: GNUNET_assert(addrlen == sizeof(struct sockaddr_in6)); memset (&t6, 0, sizeof(t6)); memcpy (&t6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr, sizeof(struct in6_addr)); t6.options = htonl (myoptions); t6.t6_port = ((struct sockaddr_in6 *) addr)->sin6_port; arg = &t6; args = sizeof (t6); break; default: GNUNET_break(0); return; } /* modify our published address list */ GNUNET_assert ((args == sizeof (struct IPv4TcpAddress)) || (args == sizeof (struct IPv6TcpAddress))); address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, arg, args, GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->notify_address (plugin->env->cls, add_remove, address); GNUNET_HELLO_address_free(address); } /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure (`struct Plugin*`) * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ static const char * tcp_address_to_string (void *cls, const void *addr, size_t addrlen) { static char rbuf[INET6_ADDRSTRLEN + 12]; char buf[INET6_ADDRSTRLEN]; const void *sb; struct in_addr a4; struct in6_addr a6; const struct IPv4TcpAddress *t4; const struct IPv6TcpAddress *t6; int af; uint16_t port; uint32_t options; switch (addrlen) { case sizeof(struct IPv6TcpAddress): t6 = addr; af = AF_INET6; port = ntohs (t6->t6_port); options = ntohl (t6->options); memcpy (&a6, &t6->ipv6_addr, sizeof(a6)); sb = &a6; break; case sizeof(struct IPv4TcpAddress): t4 = addr; af = AF_INET; port = ntohs (t4->t4_port); options = ntohl (t4->options); memcpy (&a4, &t4->ipv4_addr, sizeof(a4)); sb = &a4; break; default: LOG(GNUNET_ERROR_TYPE_WARNING, _("Unexpected address length: %u bytes\n"), (unsigned int ) addrlen); return NULL ; } if (NULL == inet_ntop (af, sb, buf, INET6_ADDRSTRLEN)) { GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "inet_ntop"); return NULL ; } GNUNET_snprintf (rbuf, sizeof(rbuf), (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u", PLUGIN_NAME, options, buf, port); return rbuf; } /** * Function called to convert a string address to * a binary address. * * @param cls closure (`struct Plugin*`) * @param addr string address * @param addrlen length of the address * @param buf location to store the buffer * @param added location to store the number of bytes in the buffer. * If the function returns #GNUNET_SYSERR, its contents are undefined. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static int tcp_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added) { struct sockaddr_storage socket_address; char *address; char *plugin; char *optionstr; uint32_t options; /* Format tcp.options.address:port */ address = NULL; plugin = NULL; optionstr = NULL; if ((NULL == addr) || (addrlen == 0)) { GNUNET_break(0); return GNUNET_SYSERR; } if ('\0' != addr[addrlen - 1]) { GNUNET_break(0); return GNUNET_SYSERR; } if (strlen (addr) != addrlen - 1) { GNUNET_break(0); return GNUNET_SYSERR; } plugin = GNUNET_strdup (addr); optionstr = strchr (plugin, '.'); if (NULL == optionstr) { GNUNET_break(0); GNUNET_free(plugin); return GNUNET_SYSERR; } optionstr[0] = '\0'; optionstr++; options = atol (optionstr); address = strchr (optionstr, '.'); if (NULL == address) { GNUNET_break(0); GNUNET_free(plugin); return GNUNET_SYSERR; } address[0] = '\0'; address++; if (GNUNET_OK != GNUNET_STRINGS_to_address_ip (address, strlen (address), &socket_address)) { GNUNET_break(0); GNUNET_free(plugin); return GNUNET_SYSERR; } GNUNET_free(plugin); switch (socket_address.ss_family) { case AF_INET: { struct IPv4TcpAddress *t4; struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address; t4 = GNUNET_new (struct IPv4TcpAddress); t4->options = htonl (options); t4->ipv4_addr = in4->sin_addr.s_addr; t4->t4_port = in4->sin_port; *buf = t4; *added = sizeof(struct IPv4TcpAddress); return GNUNET_OK; } case AF_INET6: { struct IPv6TcpAddress *t6; struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address; t6 = GNUNET_new (struct IPv6TcpAddress); t6->options = htonl (options); t6->ipv6_addr = in6->sin6_addr; t6->t6_port = in6->sin6_port; *buf = t6; *added = sizeof(struct IPv6TcpAddress); return GNUNET_OK; } default: return GNUNET_SYSERR; } } /** * Closure for #session_lookup_by_client_it(). */ struct SessionClientCtx { /** * Client we are looking for. */ const struct GNUNET_SERVER_Client *client; /** * Session that was found. */ struct Session *ret; }; static int session_lookup_by_client_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct SessionClientCtx *sc_ctx = cls; struct Session *s = value; if (s->client == sc_ctx->client) { sc_ctx->ret = s; return GNUNET_NO; } return GNUNET_YES; } /** * Find the session handle for the given client. * Currently uses both the hashmap and the client * context, as the client context is new and the * logic still needs to be tested. * * @param plugin the plugin * @param client which client to find the session handle for * @return NULL if no matching session exists */ static struct Session * lookup_session_by_client (struct Plugin *plugin, struct GNUNET_SERVER_Client *client) { struct Session *ret; struct SessionClientCtx sc_ctx; ret = GNUNET_SERVER_client_get_user_context (client, struct Session); sc_ctx.client = client; sc_ctx.ret = NULL; GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap, &session_lookup_by_client_it, &sc_ctx); /* check both methods yield the same result */ GNUNET_break(ret == sc_ctx.ret); return sc_ctx.ret; } /** * Functions with this signature are called whenever we need * to close a session due to a disconnect or failure to * establish a connection. * * @param cls the `struct Plugin` * @param session session to close down * @return #GNUNET_OK on success */ static int tcp_disconnect_session (void *cls, struct Session *session) { struct Plugin *plugin = cls; struct PendingMessage *pm; LOG(GNUNET_ERROR_TYPE_DEBUG, "Disconnecting session of peer `%s' address `%s'\n", GNUNET_i2s (&session->target), tcp_address_to_string (NULL, session->address->address, session->address->address_length)); if (GNUNET_SCHEDULER_NO_TASK != session->timeout_task) { GNUNET_SCHEDULER_cancel (session->timeout_task); session->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (plugin->sessionmap, &session->target, session)) { GNUNET_STATISTICS_update (session->plugin->env->stats, gettext_noop ("# TCP sessions active"), -1, GNUNET_NO); } else { GNUNET_assert( GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns, &session->target, session)); } if (NULL != session->client) GNUNET_SERVER_client_set_user_context(session->client, (void *) NULL); /* clean up state */ if (NULL != session->transmit_handle) { GNUNET_SERVER_notify_transmit_ready_cancel (session->transmit_handle); session->transmit_handle = NULL; } plugin->env->unregister_quota_notification (plugin->env->cls, &session->target, PLUGIN_NAME, session); session->plugin->env->session_end (session->plugin->env->cls, session->address, session); if (GNUNET_SCHEDULER_NO_TASK != session->nat_connection_timeout) { GNUNET_SCHEDULER_cancel (session->nat_connection_timeout); session->nat_connection_timeout = GNUNET_SCHEDULER_NO_TASK; } while (NULL != (pm = session->pending_messages_head)) { LOG(GNUNET_ERROR_TYPE_DEBUG, pm->transmit_cont != NULL ? "Could not deliver message to `%4s'.\n" : "Could not deliver message to `%4s', notifying.\n", GNUNET_i2s (&session->target)); GNUNET_STATISTICS_update (session->plugin->env->stats, gettext_noop ("# bytes currently in TCP buffers"), -(int64_t) pm->message_size, GNUNET_NO); GNUNET_STATISTICS_update (session->plugin->env->stats, gettext_noop ("# bytes discarded by TCP (disconnect)"), pm->message_size, GNUNET_NO); GNUNET_CONTAINER_DLL_remove(session->pending_messages_head, session->pending_messages_tail, pm); if (NULL != pm->transmit_cont) pm->transmit_cont (pm->transmit_cont_cls, &session->target, GNUNET_SYSERR, pm->message_size, 0); GNUNET_free(pm); } if (session->receive_delay_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (session->receive_delay_task); if (NULL != session->client) GNUNET_SERVER_receive_done (session->client, GNUNET_SYSERR); } if (NULL != session->client) { GNUNET_SERVER_client_disconnect (session->client); GNUNET_SERVER_client_drop (session->client); session->client = NULL; } GNUNET_HELLO_address_free (session->address); GNUNET_assert(NULL == session->transmit_handle); GNUNET_free(session); return GNUNET_OK; } /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int tcp_query_keepalive_factor (void *cls) { return 3; } /** * Session was idle, so disconnect it * * @param cls the `struct Session` of the idle session * @param tc scheduler context */ static void session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *s = cls; s->timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Session %p was idle for %s, disconnecting\n", s, GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_YES)); /* call session destroy function */ tcp_disconnect_session (s->plugin, s); } /** * Increment session timeout due to activity * * @param s session to increment timeout for */ static void reschedule_session_timeout (struct Session *s) { GNUNET_assert(GNUNET_SCHEDULER_NO_TASK != s->timeout_task); GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, s); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p set to %s\n", s, GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_YES)); } /** * Create a new session. Also queues a welcome message. * * @param plugin the plugin * @param address the address to create the session for * @param client client to use, reference counter must have already been increased * @param is_nat this a NAT session, we should wait for a client to * connect to us from an address, then assign that to * the session * @return new session object */ static struct Session * create_session (struct Plugin *plugin, const struct GNUNET_HELLO_Address *address, struct GNUNET_SERVER_Client *client, int is_nat) { struct Session *session; struct PendingMessage *pm; struct WelcomeMessage welcome; if (GNUNET_YES != is_nat) GNUNET_assert(NULL != client); else GNUNET_assert(NULL == client); LOG(GNUNET_ERROR_TYPE_DEBUG, "Creating new session for peer `%4s'\n", GNUNET_i2s (&address->peer)); session = GNUNET_new (struct Session); session->last_activity = GNUNET_TIME_absolute_get (); session->plugin = plugin; session->is_nat = is_nat; session->client = client; session->address = GNUNET_HELLO_address_copy (address); session->target = address->peer; session->expecting_welcome = GNUNET_YES; session->ats_address_network_type = GNUNET_ATS_NET_UNSPECIFIED; pm = GNUNET_malloc (sizeof (struct PendingMessage) + sizeof (struct WelcomeMessage)); pm->msg = (const char *) &pm[1]; pm->message_size = sizeof(struct WelcomeMessage); welcome.header.size = htons (sizeof(struct WelcomeMessage)); welcome.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME); welcome.clientIdentity = *plugin->env->my_identity; memcpy (&pm[1], &welcome, sizeof(welcome)); pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# bytes currently in TCP buffers"), pm->message_size, GNUNET_NO); GNUNET_CONTAINER_DLL_insert(session->pending_messages_head, session->pending_messages_tail, pm); if (GNUNET_YES != is_nat) { GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# TCP sessions active"), 1, GNUNET_NO); } plugin->env->register_quota_notification (plugin->env->cls, &address->peer, PLUGIN_NAME, session); session->timeout_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session); return session; } /** * If we have pending messages, ask the server to * transmit them (schedule the respective tasks, etc.) * * @param session for which session should we do this */ static void process_pending_messages (struct Session *session); /** * Function called to notify a client about the socket * being ready to queue more data. "buf" will be * NULL and "size" zero if the socket was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t do_transmit (void *cls, size_t size, void *buf) { struct Session *session = cls; struct GNUNET_PeerIdentity pid; struct Plugin *plugin; struct PendingMessage *pos; struct PendingMessage *hd; struct PendingMessage *tl; struct GNUNET_TIME_Absolute now; char *cbuf; size_t ret; session->transmit_handle = NULL; plugin = session->plugin; if (NULL == buf) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Timeout trying to transmit to peer `%4s', discarding message queue.\n", GNUNET_i2s (&session->target)); /* timeout; cancel all messages that have already expired */ hd = NULL; tl = NULL; ret = 0; now = GNUNET_TIME_absolute_get (); while ((NULL != (pos = session->pending_messages_head)) && (pos->timeout.abs_value_us <= now.abs_value_us)) { GNUNET_CONTAINER_DLL_remove(session->pending_messages_head, session->pending_messages_tail, pos); LOG(GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit %u byte message to `%4s'.\n", pos->message_size, GNUNET_i2s (&session->target)); ret += pos->message_size; GNUNET_CONTAINER_DLL_insert_after(hd, tl, tl, pos); } /* do this call before callbacks (so that if callbacks destroy * session, they have a chance to cancel actions done by this * call) */ process_pending_messages (session); pid = session->target; /* no do callbacks and do not use session again since * the callbacks may abort the session */ while (NULL != (pos = hd)) { GNUNET_CONTAINER_DLL_remove(hd, tl, pos); if (pos->transmit_cont != NULL ) pos->transmit_cont (pos->transmit_cont_cls, &pid, GNUNET_SYSERR, pos->message_size, 0); GNUNET_free(pos); } GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# bytes currently in TCP buffers"), -(int64_t) ret, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# bytes discarded by TCP (timeout)"), ret, GNUNET_NO); return 0; } /* copy all pending messages that would fit */ ret = 0; cbuf = buf; hd = NULL; tl = NULL; while (NULL != (pos = session->pending_messages_head)) { if (ret + pos->message_size > size) break; GNUNET_CONTAINER_DLL_remove(session->pending_messages_head, session->pending_messages_tail, pos); GNUNET_assert(size >= pos->message_size); LOG(GNUNET_ERROR_TYPE_DEBUG, "Transmitting message of type %u\n", ntohs (((struct GNUNET_MessageHeader * ) pos->msg)->type)); /* FIXME: this memcpy can be up to 7% of our total runtime */ memcpy (cbuf, pos->msg, pos->message_size); cbuf += pos->message_size; ret += pos->message_size; size -= pos->message_size; GNUNET_CONTAINER_DLL_insert_tail(hd, tl, pos); } /* schedule 'continuation' before callbacks so that callbacks that * cancel everything don't cause us to use a session that no longer * exists... */ process_pending_messages (session); session->last_activity = GNUNET_TIME_absolute_get (); pid = session->target; /* we'll now call callbacks that may cancel the session; hence * we should not use 'session' after this point */ while (NULL != (pos = hd)) { GNUNET_CONTAINER_DLL_remove(hd, tl, pos); if (pos->transmit_cont != NULL ) pos->transmit_cont (pos->transmit_cont_cls, &pid, GNUNET_OK, pos->message_size, pos->message_size); /* FIXME: include TCP overhead */ GNUNET_free(pos); } GNUNET_assert(hd == NULL); GNUNET_assert(tl == NULL); LOG(GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes\n", ret); GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# bytes currently in TCP buffers"), -(int64_t) ret, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# bytes transmitted via TCP"), ret, GNUNET_NO); return ret; } /** * If we have pending messages, ask the server to * transmit them (schedule the respective tasks, etc.) * * @param session for which session should we do this */ static void process_pending_messages (struct Session *session) { struct PendingMessage *pm; GNUNET_assert(NULL != session->client); if (NULL != session->transmit_handle) return; if (NULL == (pm = session->pending_messages_head)) return; session->transmit_handle = GNUNET_SERVER_notify_transmit_ready ( session->client, pm->message_size, GNUNET_TIME_absolute_get_remaining (pm->timeout), &do_transmit, session); } #if EXTRA_CHECKS /** * Closure for #session_it(). */ struct FindSessionContext { /** * Session we are looking for. */ struct Session *s; /** * Set to #GNUNET_OK if we found the session. */ int res; }; /** * Function called to check if a session is in our maps. * * @param cls the `struct FindSessionContext` * @param key peer identity * @param value session in the map * @return #GNUNET_YES to continue looking, #GNUNET_NO if we found the session */ static int session_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct FindSessionContext *res = cls; struct Session *session = value; if (res->s == session) { res->res = GNUNET_OK; return GNUNET_NO; } return GNUNET_YES; } /** * Check that the given session is known to the plugin and * is in one of our maps. * * @param plugin the plugin to check against * @param session the session to check * @return #GNUNET_OK if all is well, #GNUNET_SYSERR if the session is invalid */ static int find_session (struct Plugin *plugin, struct Session *session) { struct FindSessionContext session_map_res; struct FindSessionContext nat_map_res; session_map_res.s = session; session_map_res.res = GNUNET_SYSERR; GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap, &session_it, &session_map_res); if (GNUNET_SYSERR != session_map_res.res) return GNUNET_OK; nat_map_res.s = session; nat_map_res.res = GNUNET_SYSERR; GNUNET_CONTAINER_multipeermap_iterate (plugin->nat_wait_conns, &session_it, &nat_map_res); if (GNUNET_SYSERR != nat_map_res.res) return GNUNET_OK; GNUNET_break(0); return GNUNET_SYSERR; } #endif /** * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param session which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in 'msgbuf' * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for @a cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t tcp_plugin_send (void *cls, struct Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin * plugin = cls; struct PendingMessage *pm; #if EXTRA_CHECKS if (GNUNET_SYSERR == find_session (plugin, session)) { LOG(GNUNET_ERROR_TYPE_ERROR, _("Trying to send with invalid session %p\n")); GNUNET_assert(0); return GNUNET_SYSERR; } #endif /* create new message entry */ pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size); pm->msg = (const char *) &pm[1]; memcpy (&pm[1], msgbuf, msgbuf_size); pm->message_size = msgbuf_size; pm->timeout = GNUNET_TIME_relative_to_absolute (to); pm->transmit_cont = cont; pm->transmit_cont_cls = cont_cls; LOG(GNUNET_ERROR_TYPE_DEBUG, "Asked to transmit %u bytes to `%s', added message to list.\n", msgbuf_size, GNUNET_i2s (&session->target)); if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessionmap, &session->target, session)) { GNUNET_assert(NULL != session->client); GNUNET_SERVER_client_set_timeout (session->client, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# bytes currently in TCP buffers"), msgbuf_size, GNUNET_NO); /* append pm to pending_messages list */ GNUNET_CONTAINER_DLL_insert_tail(session->pending_messages_head, session->pending_messages_tail, pm); process_pending_messages (session); return msgbuf_size; } else if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains_value (plugin->nat_wait_conns, &session->target, session)) { LOG(GNUNET_ERROR_TYPE_DEBUG, "This NAT WAIT session for peer `%s' is not yet ready!\n", GNUNET_i2s (&session->target)); GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# bytes currently in TCP buffers"), msgbuf_size, GNUNET_NO); /* append pm to pending_messages list */ GNUNET_CONTAINER_DLL_insert_tail(session->pending_messages_head, session->pending_messages_tail, pm); return msgbuf_size; } else { LOG(GNUNET_ERROR_TYPE_ERROR, "Invalid session %p\n", session); if (NULL != cont) cont (cont_cls, &session->target, GNUNET_SYSERR, pm->message_size, 0); GNUNET_break(0); GNUNET_free(pm); return GNUNET_SYSERR; /* session does not exist here */ } } /** * Closure for #session_lookup_it(). */ struct SessionItCtx { /** * Address we are looking for. */ const struct GNUNET_HELLO_Address *address; /** * Where to store the session (if we found it). */ struct Session *result; }; /** * Look for a session by address. * * @param cls the `struct SessionItCtx` * @param key unused * @param value a `struct Session` * @return #GNUNET_YES to continue looking, #GNUNET_NO if we found the session */ static int session_lookup_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct SessionItCtx * si_ctx = cls; struct Session * session = value; if (0 != GNUNET_HELLO_address_cmp (si_ctx->address, session->address)) return GNUNET_YES; /* Found existing session */ si_ctx->result = session; return GNUNET_NO; } /** * Task cleaning up a NAT connection attempt after timeout * * @param cls the `struct Session` * @param tc scheduler context (unused) */ static void nat_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *session = cls; session->nat_connection_timeout = GNUNET_SCHEDULER_NO_TASK; LOG(GNUNET_ERROR_TYPE_DEBUG, "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n", GNUNET_i2s (&session->target), tcp_address_to_string (NULL, session->address->address, session->address->address_length)); tcp_disconnect_session (session->plugin, session); } static void tcp_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { struct Plugin *plugin = cls; if (GNUNET_SYSERR == find_session (plugin, session)) return; reschedule_session_timeout (session); } /** * Task to signal the server that we can continue * receiving from the TCP client now. * * @param cls the `struct Session*` * @param tc task context (unused) */ static void delayed_done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *session = cls; session->receive_delay_task = GNUNET_SCHEDULER_NO_TASK; reschedule_session_timeout (session); GNUNET_SERVER_receive_done (session->client, GNUNET_OK); } static void tcp_plugin_update_inbound_delay (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session, struct GNUNET_TIME_Relative delay) { if (GNUNET_SCHEDULER_NO_TASK == session->receive_delay_task) return; LOG(GNUNET_ERROR_TYPE_DEBUG, "New inbound delay %llu us\n",delay.rel_value_us); GNUNET_SCHEDULER_cancel (session->receive_delay_task); session->receive_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &delayed_done, session); } /** * Create a new session to transmit data to the target * This session will used to send data to this peer and the plugin will * notify us by calling the env->session_end function * * @param cls closure * @param address the address to use * @return the session if the address is valid, NULL otherwise */ static struct Session * tcp_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct Plugin *plugin = cls; struct Session *session = NULL; int af; const void *sb; size_t sbs; struct GNUNET_CONNECTION_Handle *sa; struct sockaddr_in a4; struct sockaddr_in6 a6; const struct IPv4TcpAddress *t4; const struct IPv6TcpAddress *t6; struct GNUNET_ATS_Information ats; unsigned int is_natd = GNUNET_NO; size_t addrlen; addrlen = address->address_length; LOG(GNUNET_ERROR_TYPE_DEBUG, "Trying to get session for `%s' address of peer `%s'\n", tcp_address_to_string(NULL, address->address, address->address_length), GNUNET_i2s (&address->peer)); if (GNUNET_HELLO_address_check_option(address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)) { GNUNET_break (0); return NULL; } /* look for existing session */ if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (plugin->sessionmap, &address->peer)) { struct SessionItCtx si_ctx; si_ctx.address = address; si_ctx.result = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap, &address->peer, &session_lookup_it, &si_ctx); if (si_ctx.result != NULL ) { session = si_ctx.result; LOG(GNUNET_ERROR_TYPE_DEBUG, "Found existing session for `%s' address `%s' session %p\n", GNUNET_i2s (&address->peer), tcp_address_to_string(NULL, address->address, address->address_length), session); return session; } LOG(GNUNET_ERROR_TYPE_DEBUG, "Existing sessions did not match address `%s' or peer `%s'\n", tcp_address_to_string(NULL, address->address, address->address_length), GNUNET_i2s (&address->peer)); } if (addrlen == sizeof(struct IPv6TcpAddress)) { GNUNET_assert(NULL != address->address); /* make static analysis happy */ t6 = address->address; af = AF_INET6; memset (&a6, 0, sizeof(a6)); #if HAVE_SOCKADDR_IN_SIN_LEN a6.sin6_len = sizeof (a6); #endif a6.sin6_family = AF_INET6; a6.sin6_port = t6->t6_port; if (t6->t6_port == 0) is_natd = GNUNET_YES; memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr)); sb = &a6; sbs = sizeof(a6); } else if (addrlen == sizeof(struct IPv4TcpAddress)) { GNUNET_assert(NULL != address->address); /* make static analysis happy */ t4 = address->address; af = AF_INET; memset (&a4, 0, sizeof(a4)); #if HAVE_SOCKADDR_IN_SIN_LEN a4.sin_len = sizeof (a4); #endif a4.sin_family = AF_INET; a4.sin_port = t4->t4_port; if (t4->t4_port == 0) is_natd = GNUNET_YES; a4.sin_addr.s_addr = t4->ipv4_addr; sb = &a4; sbs = sizeof(a4); } else { GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# requests to create session with invalid address"), 1, GNUNET_NO); return NULL ; } ats = plugin->env->get_address_type (plugin->env->cls, sb, sbs); if ((is_natd == GNUNET_YES) && (addrlen == sizeof(struct IPv6TcpAddress))) { /* NAT client only works with IPv4 addresses */ return NULL ; } if (plugin->cur_connections >= plugin->max_connections) { /* saturated */ return NULL ; } if ((is_natd == GNUNET_YES) && (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns, &address->peer))) { /* Only do one NAT punch attempt per peer identity */ return NULL ; } if ((is_natd == GNUNET_YES) && (NULL != plugin->nat) && (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (plugin->nat_wait_conns, &address->peer))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Found valid IPv4 NAT address (creating session)!\n"); session = create_session (plugin, address, NULL, GNUNET_YES); session->ats_address_network_type = (enum GNUNET_ATS_Network_Type) ntohl ( ats.value); GNUNET_break( session->ats_address_network_type != GNUNET_ATS_NET_UNSPECIFIED); session->nat_connection_timeout = GNUNET_SCHEDULER_add_delayed (NAT_TIMEOUT, &nat_connect_timeout, session); GNUNET_assert(session != NULL); GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (plugin->nat_wait_conns, &session->target, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); LOG(GNUNET_ERROR_TYPE_DEBUG, "Created NAT WAIT connection to `%4s' at `%s'\n", GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs)); if (GNUNET_OK == GNUNET_NAT_run_client (plugin->nat, &a4)) return session; else { LOG(GNUNET_ERROR_TYPE_DEBUG, "Running NAT client for `%4s' at `%s' failed\n", GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs)); tcp_disconnect_session (plugin, session); return NULL ; } } /* create new outbound session */ GNUNET_assert(plugin->cur_connections <= plugin->max_connections); sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs); if (NULL == sa) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Failed to create connection to `%4s' at `%s'\n", GNUNET_i2s (&address->peer), GNUNET_a2s (sb, sbs)); return NULL ; } plugin->cur_connections++; if (plugin->cur_connections == plugin->max_connections) GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Asked to transmit to `%4s', creating fresh session using address `%s'.\n", GNUNET_i2s (&address->peer), GNUNET_a2s (sb, sbs)); session = create_session (plugin, address, GNUNET_SERVER_connect_socket (plugin->server, sa), GNUNET_NO); session->ats_address_network_type = (enum GNUNET_ATS_Network_Type) ntohl ( ats.value); GNUNET_break(session->ats_address_network_type != GNUNET_ATS_NET_UNSPECIFIED); GNUNET_SERVER_client_set_user_context(session->client, session); GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap, &session->target, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); LOG(GNUNET_ERROR_TYPE_DEBUG, "Creating new session for `%s' address `%s' session %p\n", GNUNET_i2s (&address->peer), tcp_address_to_string(NULL, address->address, address->address_length), session); /* Send TCP Welcome */ process_pending_messages (session); return session; } static int session_disconnect_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct Plugin *plugin = cls; struct Session *session = value; GNUNET_STATISTICS_update (session->plugin->env->stats, gettext_noop ("# transport-service disconnect requests for TCP"), 1, GNUNET_NO); tcp_disconnect_session (plugin, session); return GNUNET_YES; } /** * Function that can be called to force a disconnect from the * specified neighbour. This should also cancel all previously * scheduled transmissions. Obviously the transmission may have been * partially completed already, which is OK. The plugin is supposed * to close the connection (if applicable) and no longer call the * transmit continuation(s). * * Finally, plugin MUST NOT call the services's receive function to * notify the service that the connection to the specified target was * closed after a getting this call. * * @param cls closure * @param target peer for which the last transmission is * to be cancelled */ static void tcp_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) { struct Plugin *plugin = cls; LOG(GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s'\n", GNUNET_i2s (target)); GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessionmap, target, &session_disconnect_it, plugin); GNUNET_CONTAINER_multipeermap_get_multiple (plugin->nat_wait_conns, target, &session_disconnect_it, plugin); } /** * Running pretty printers: head */ static struct PrettyPrinterContext *ppc_dll_head; /** * Running pretty printers: tail */ static struct PrettyPrinterContext *ppc_dll_tail; /** * Context for address to string conversion. */ struct PrettyPrinterContext { /** * DLL */ struct PrettyPrinterContext *next; /** * DLL */ struct PrettyPrinterContext *prev; /** * Timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Resolver handle */ struct GNUNET_RESOLVER_RequestHandle *resolver_handle; /** * Function to call with the result. */ GNUNET_TRANSPORT_AddressStringCallback asc; /** * Clsoure for 'asc'. */ void *asc_cls; /** * Port to add after the IP address. */ uint16_t port; /** * IPv6 address */ int ipv6; /** * Options */ uint32_t options; }; static void ppc_cancel_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PrettyPrinterContext *ppc = cls; ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != ppc->resolver_handle) { GNUNET_RESOLVER_request_cancel (ppc->resolver_handle); ppc->resolver_handle = NULL; } GNUNET_CONTAINER_DLL_remove(ppc_dll_head, ppc_dll_tail, ppc); GNUNET_free(ppc); } /** * Append our port and forward the result. * * @param cls the 'struct PrettyPrinterContext*' * @param hostname hostname part of the address */ static void append_port (void *cls, const char *hostname) { struct PrettyPrinterContext *ppc = cls; struct PrettyPrinterContext *cur; char *ret; if (NULL == hostname) { ppc->asc (ppc->asc_cls, NULL ); GNUNET_CONTAINER_DLL_remove(ppc_dll_head, ppc_dll_tail, ppc); GNUNET_SCHEDULER_cancel (ppc->timeout_task); ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; ppc->resolver_handle = NULL; GNUNET_free(ppc); return; } for (cur = ppc_dll_head; (NULL != cur); cur = cur->next) if (cur == ppc) break; if (NULL == cur) { GNUNET_break(0); return; } if (GNUNET_YES == ppc->ipv6) GNUNET_asprintf (&ret, "%s.%u.[%s]:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port); else GNUNET_asprintf (&ret, "%s.%u.%s:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port); ppc->asc (ppc->asc_cls, ret); GNUNET_free(ret); } /** * Convert the transports address to a nice, human-readable * format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the address * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for asc */ static void tcp_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { struct PrettyPrinterContext *ppc; const void *sb; size_t sbs; struct sockaddr_in a4; struct sockaddr_in6 a6; const struct IPv4TcpAddress *t4; const struct IPv6TcpAddress *t6; uint16_t port; uint32_t options; if (addrlen == sizeof(struct IPv6TcpAddress)) { t6 = addr; memset (&a6, 0, sizeof(a6)); a6.sin6_family = AF_INET6; a6.sin6_port = t6->t6_port; memcpy (&a6.sin6_addr, &t6->ipv6_addr, sizeof(struct in6_addr)); port = ntohs (t6->t6_port); options = ntohl (t6->options); sb = &a6; sbs = sizeof(a6); } else if (addrlen == sizeof(struct IPv4TcpAddress)) { t4 = addr; memset (&a4, 0, sizeof(a4)); a4.sin_family = AF_INET; a4.sin_port = t4->t4_port; a4.sin_addr.s_addr = t4->ipv4_addr; port = ntohs (t4->t4_port); options = ntohl (t4->options); sb = &a4; sbs = sizeof(a4); } else { /* invalid address */ LOG (GNUNET_ERROR_TYPE_ERROR, "Trying to print invalid `%s' address with size %u\n", type, addrlen); asc (asc_cls, NULL ); return; } ppc = GNUNET_new (struct PrettyPrinterContext); if (addrlen == sizeof(struct IPv6TcpAddress)) ppc->ipv6 = GNUNET_YES; else ppc->ipv6 = GNUNET_NO; ppc->asc = asc; ppc->asc_cls = asc_cls; ppc->port = port; ppc->options = options; ppc->timeout_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_relative_multiply (timeout, 2), &ppc_cancel_task, ppc); ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc); if (NULL != ppc->resolver_handle) { //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Adding request %p\n", ppc); GNUNET_CONTAINER_DLL_insert(ppc_dll_head, ppc_dll_tail, ppc); } else { GNUNET_break(0); GNUNET_free(ppc); } } /** * Check if the given port is plausible (must be either our listen * port or our advertised port), or any port if we are behind NAT * and do not have a port open. If it is neither, we return * #GNUNET_SYSERR. * * @param plugin global variables * @param in_port port number to check * @return #GNUNET_OK if port is either open_port or adv_port */ static int check_port (struct Plugin *plugin, uint16_t in_port) { if ((in_port == plugin->adv_port) || (in_port == plugin->open_port)) return GNUNET_OK; return GNUNET_SYSERR; } /** * Function that will be called to check if a binary address for this * plugin is well-formed and corresponds to an address for THIS peer * (as per our configuration). Naturally, if absolutely necessary, * plugins can be a bit conservative in their answer, but in general * plugins should make sure that the address does not redirect * traffic to a 3rd party that might try to man-in-the-middle our * traffic. * * @param cls closure, our `struct Plugin *` * @param addr pointer to the address * @param addrlen length of addr * @return #GNUNET_OK if this is a plausible address for this peer * and transport, #GNUNET_SYSERR if not */ static int tcp_plugin_check_address (void *cls, const void *addr, size_t addrlen) { struct Plugin *plugin = cls; struct IPv4TcpAddress *v4; struct IPv6TcpAddress *v6; if ((addrlen != sizeof(struct IPv4TcpAddress)) && (addrlen != sizeof(struct IPv6TcpAddress))) { GNUNET_break_op(0); return GNUNET_SYSERR; } if (addrlen == sizeof(struct IPv4TcpAddress)) { v4 = (struct IPv4TcpAddress *) addr; if (0 != memcmp (&v4->options, &myoptions, sizeof(myoptions))) { GNUNET_break(0); return GNUNET_SYSERR; } if (GNUNET_OK != check_port (plugin, ntohs (v4->t4_port))) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr, sizeof(struct in_addr))) return GNUNET_SYSERR; } else { v6 = (struct IPv6TcpAddress *) addr; if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr)) { GNUNET_break_op(0); return GNUNET_SYSERR; } if (0 != memcmp (&v6->options, &myoptions, sizeof(myoptions))) { GNUNET_break(0); return GNUNET_SYSERR; } if (GNUNET_OK != check_port (plugin, ntohs (v6->t6_port))) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr, sizeof(struct in6_addr))) return GNUNET_SYSERR; } return GNUNET_OK; } /** * We've received a nat probe from this peer via TCP. Finish * creating the client session and resume sending of queued * messages. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_tcp_nat_probe (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct Plugin *plugin = cls; struct Session *session; const struct TCP_NAT_ProbeMessage *tcp_nat_probe; size_t alen; void *vaddr; struct IPv4TcpAddress *t4; struct IPv6TcpAddress *t6; const struct sockaddr_in *s4; const struct sockaddr_in6 *s6; LOG(GNUNET_ERROR_TYPE_DEBUG, "Received NAT probe\n"); /* We have received a TCP NAT probe, meaning we (hopefully) initiated * a connection to this peer by running gnunet-nat-client. This peer * received the punch message and now wants us to use the new connection * as the default for that peer. Do so and then send a WELCOME message * so we can really be connected! */ if (ntohs (message->size) != sizeof(struct TCP_NAT_ProbeMessage)) { GNUNET_break_op(0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *) message; if (0 == memcmp (&tcp_nat_probe->clientIdentity, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity))) { /* refuse connections from ourselves */ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } session = GNUNET_CONTAINER_multipeermap_get (plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity); if (session == NULL ) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Did NOT find session for NAT probe!\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } LOG(GNUNET_ERROR_TYPE_DEBUG, "Found session for NAT probe!\n"); if (session->nat_connection_timeout != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (session->nat_connection_timeout); session->nat_connection_timeout = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_OK != GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) { GNUNET_break(0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); tcp_disconnect_session (plugin, session); return; } GNUNET_assert( GNUNET_CONTAINER_multipeermap_remove (plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity, session) == GNUNET_YES); GNUNET_SERVER_client_set_user_context(client, session); GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap, &session->target, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); session->last_activity = GNUNET_TIME_absolute_get (); LOG(GNUNET_ERROR_TYPE_DEBUG, "Found address `%s' for incoming connection\n", GNUNET_a2s (vaddr, alen)); switch (((const struct sockaddr *) vaddr)->sa_family) { case AF_INET: s4 = vaddr; t4 = GNUNET_new (struct IPv4TcpAddress); t4->options = htonl(0); t4->t4_port = s4->sin_port; t4->ipv4_addr = s4->sin_addr.s_addr; session->address = GNUNET_HELLO_address_allocate ( &tcp_nat_probe->clientIdentity, PLUGIN_NAME, &t4, sizeof(struct IPv4TcpAddress), GNUNET_HELLO_ADDRESS_INFO_NONE); break; case AF_INET6: s6 = vaddr; t6 = GNUNET_new (struct IPv6TcpAddress); t6->options = htonl(0); t6->t6_port = s6->sin6_port; memcpy (&t6->ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr)); session->address = GNUNET_HELLO_address_allocate ( &tcp_nat_probe->clientIdentity, PLUGIN_NAME, &t6, sizeof(struct IPv6TcpAddress), GNUNET_HELLO_ADDRESS_INFO_NONE); break; default: GNUNET_break_op(0); LOG(GNUNET_ERROR_TYPE_DEBUG, "Bad address for incoming connection!\n"); GNUNET_free(vaddr); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); tcp_disconnect_session (plugin, session); return; } GNUNET_free(vaddr); GNUNET_break(NULL == session->client); GNUNET_SERVER_client_keep (client); session->client = client; GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# TCP sessions active"), 1, GNUNET_NO); process_pending_messages (session); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * We've received a welcome from this peer via TCP. Possibly create a * fresh client record and send back our welcome. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_tcp_welcome (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct Plugin *plugin = cls; const struct WelcomeMessage *wm = (const struct WelcomeMessage *) message; struct GNUNET_HELLO_Address *address; struct Session *session; size_t alen; void *vaddr; struct IPv4TcpAddress t4; struct IPv6TcpAddress t6; const struct sockaddr_in *s4; const struct sockaddr_in6 *s6; struct GNUNET_ATS_Information ats; if (0 == memcmp (&wm->clientIdentity, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity))) { /* refuse connections from ourselves */ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) { LOG(GNUNET_ERROR_TYPE_WARNING, "Received %s message from my own identity `%4s' on address `%s'\n", "WELCOME", GNUNET_i2s (&wm->clientIdentity), GNUNET_a2s (vaddr, alen)); GNUNET_free(vaddr); } GNUNET_break_op(0); return; } LOG(GNUNET_ERROR_TYPE_DEBUG, "Received %s message from `%4s' %p\n", "WELCOME", GNUNET_i2s (&wm->clientIdentity), client); GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# TCP WELCOME messages received"), 1, GNUNET_NO); session = lookup_session_by_client (plugin, client); if (NULL != session) { if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p for peer `%s'\n", session, GNUNET_a2s (vaddr, alen)); GNUNET_free(vaddr); } } else { GNUNET_SERVER_client_keep (client); if (NULL != plugin->service) /* Otherwise value is incremented in tcp_access_check */ plugin->cur_connections++; if (plugin->cur_connections == plugin->max_connections) GNUNET_SERVER_suspend (plugin->server); /* Maximum number of connections rechead */ if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) { if (alen == sizeof(struct sockaddr_in)) { s4 = vaddr; memset (&t4, '\0', sizeof (t4)); t4.options = htonl (0); t4.t4_port = s4->sin_port; t4.ipv4_addr = s4->sin_addr.s_addr; address = GNUNET_HELLO_address_allocate (&wm->clientIdentity, PLUGIN_NAME, &t4, sizeof(t4), GNUNET_HELLO_ADDRESS_INFO_INBOUND); } else if (alen == sizeof(struct sockaddr_in6)) { s6 = vaddr; memset (&t6, '\0', sizeof (t6)); t6.options = htonl (0); t6.t6_port = s6->sin6_port; memcpy (&t6.ipv6_addr, &s6->sin6_addr, sizeof(struct in6_addr)); address = GNUNET_HELLO_address_allocate (&wm->clientIdentity, PLUGIN_NAME, &t6, sizeof (t6), GNUNET_HELLO_ADDRESS_INFO_INBOUND); } else { GNUNET_break (0); GNUNET_free_non_null (vaddr); return; } session = create_session (plugin, address, client, GNUNET_NO); GNUNET_HELLO_address_free (address); ats = plugin->env->get_address_type (plugin->env->cls, vaddr, alen); session->ats_address_network_type = (enum GNUNET_ATS_Network_Type) ntohl ( ats.value); LOG(GNUNET_ERROR_TYPE_DEBUG, "Creating new%s session %p for peer `%s' client %p \n", GNUNET_HELLO_address_check_option (session->address, GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? " inbound" : "", session, tcp_address_to_string(NULL, (void *) session->address->address, session->address->address_length), client); GNUNET_free(vaddr); GNUNET_SERVER_client_set_user_context(session->client, session); GNUNET_CONTAINER_multipeermap_put (plugin->sessionmap, &session->target, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); /* Notify transport and ATS about new session */ plugin->env->session_start (NULL, session->address, session, &ats, 1); } else { LOG(GNUNET_ERROR_TYPE_DEBUG, "Did not obtain TCP socket address for incoming connection\n"); GNUNET_break(0); return; } } if (session->expecting_welcome != GNUNET_YES) { GNUNET_break_op(0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_break(0); return; } session->last_activity = GNUNET_TIME_absolute_get (); session->expecting_welcome = GNUNET_NO; process_pending_messages (session); GNUNET_SERVER_client_set_timeout (client, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * We've received data for this peer via TCP. Unbox, * compute latency and forward. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_tcp_data (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct Plugin *plugin = cls; struct Session *session; struct GNUNET_TIME_Relative delay; uint16_t type; type = ntohs (message->type); if ((GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == type) || (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE == type)) { /* We don't want to propagate WELCOME and NAT Probe messages up! */ GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } session = lookup_session_by_client (plugin, client); if (NULL == session) { /* No inbound session found */ void *vaddr; size_t alen; GNUNET_SERVER_client_get_address (client, &vaddr, &alen); LOG(GNUNET_ERROR_TYPE_ERROR, "Received unexpected %u bytes of type %u from `%s'\n", (unsigned int ) ntohs (message->size), (unsigned int ) ntohs (message->type), GNUNET_a2s (vaddr, alen)); GNUNET_break_op(0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_free_non_null(vaddr); return; } else if (GNUNET_YES == session->expecting_welcome) { /* Session is expecting WELCOME message */ void *vaddr; size_t alen; GNUNET_SERVER_client_get_address (client, &vaddr, &alen); LOG(GNUNET_ERROR_TYPE_ERROR, "Received unexpected %u bytes of type %u from `%s'\n", (unsigned int ) ntohs (message->size), (unsigned int ) ntohs (message->type), GNUNET_a2s (vaddr, alen)); GNUNET_break_op(0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_free_non_null(vaddr); return; } session->last_activity = GNUNET_TIME_absolute_get (); LOG(GNUNET_ERROR_TYPE_DEBUG, "Passing %u bytes of type %u from `%4s' to transport service.\n", (unsigned int ) ntohs (message->size), (unsigned int ) ntohs (message->type), GNUNET_i2s (&session->target)); GNUNET_STATISTICS_update (plugin->env->stats, gettext_noop ("# bytes received via TCP"), ntohs (message->size), GNUNET_NO); struct GNUNET_ATS_Information distance; distance.type = htonl (GNUNET_ATS_NETWORK_TYPE); distance.value = htonl ((uint32_t) session->ats_address_network_type); GNUNET_break(session->ats_address_network_type != GNUNET_ATS_NET_UNSPECIFIED); GNUNET_assert( GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessionmap, &session->target, session)); delay = plugin->env->receive (plugin->env->cls, session->address, session, message); plugin->env->update_address_metrics (plugin->env->cls, session->address, session, &distance, 1); reschedule_session_timeout (session); if (0 == delay.rel_value_us) { GNUNET_SERVER_receive_done (client, GNUNET_OK); } else { LOG(GNUNET_ERROR_TYPE_DEBUG, "Throttling receiving from `%s' for %s\n", GNUNET_i2s (&session->target), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); GNUNET_SERVER_disable_receive_done_warning (client); session->receive_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &delayed_done, session); } } /** * Functions with this signature are called whenever a peer * is disconnected on the network level. * * @param cls closure * @param client identification of the client */ static void disconnect_notify (void *cls, struct GNUNET_SERVER_Client *client) { struct Plugin *plugin = cls; struct Session *session; if (client == NULL ) return; session = lookup_session_by_client (plugin, client); if (session == NULL ) return; /* unknown, nothing to do */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Destroying session of `%4s' with %s due to network-level disconnect.\n", GNUNET_i2s (&session->target), tcp_address_to_string (session->plugin, session->address->address, session->address->address_length)); if (plugin->cur_connections == plugin->max_connections) GNUNET_SERVER_resume (plugin->server); /* Resume server */ if (plugin->cur_connections < 1) GNUNET_break(0); else plugin->cur_connections--; GNUNET_STATISTICS_update (session->plugin->env->stats, gettext_noop ("# network-level TCP disconnect events"), 1, GNUNET_NO); tcp_disconnect_session (plugin, session); } /** * We can now send a probe message, copy into buffer to really send. * * @param cls closure, a struct TCPProbeContext * @param size max size to copy * @param buf buffer to copy message to * @return number of bytes copied into buf */ static size_t notify_send_probe (void *cls, size_t size, void *buf) { struct TCPProbeContext *tcp_probe_ctx = cls; struct Plugin *plugin = tcp_probe_ctx->plugin; size_t ret; tcp_probe_ctx->transmit_handle = NULL; GNUNET_CONTAINER_DLL_remove(plugin->probe_head, plugin->probe_tail, tcp_probe_ctx); if (buf == NULL ) { GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock); GNUNET_free(tcp_probe_ctx); return 0; } GNUNET_assert(size >= sizeof(tcp_probe_ctx->message)); memcpy (buf, &tcp_probe_ctx->message, sizeof(tcp_probe_ctx->message)); GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server, tcp_probe_ctx->sock); ret = sizeof(tcp_probe_ctx->message); GNUNET_free(tcp_probe_ctx); return ret; } /** * Function called by the NAT subsystem suggesting another peer wants * to connect to us via connection reversal. Try to connect back to the * given IP. * * @param cls closure * @param addr address to try * @param addrlen number of bytes in @a addr */ static void try_connection_reversal (void *cls, const struct sockaddr *addr, socklen_t addrlen) { struct Plugin *plugin = cls; struct GNUNET_CONNECTION_Handle *sock; struct TCPProbeContext *tcp_probe_ctx; /** * We have received an ICMP response, ostensibly from a peer * that wants to connect to us! Send a message to establish a connection. */ sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, addr, addrlen); if (sock == NULL ) { /* failed for some odd reason (out of sockets?); ignore attempt */ return; } /* FIXME: do we need to track these probe context objects so that * we can clean them up on plugin unload? */ tcp_probe_ctx = GNUNET_new (struct TCPProbeContext); tcp_probe_ctx->message.header.size = htons ( sizeof(struct TCP_NAT_ProbeMessage)); tcp_probe_ctx->message.header.type = htons ( GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE); memcpy (&tcp_probe_ctx->message.clientIdentity, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)); tcp_probe_ctx->plugin = plugin; tcp_probe_ctx->sock = sock; GNUNET_CONTAINER_DLL_insert(plugin->probe_head, plugin->probe_tail, tcp_probe_ctx); tcp_probe_ctx->transmit_handle = GNUNET_CONNECTION_notify_transmit_ready ( sock, ntohs (tcp_probe_ctx->message.header.size), GNUNET_TIME_UNIT_FOREVER_REL, ¬ify_send_probe, tcp_probe_ctx); } /** * Function obtain the network type for a session * * @param cls closure ('struct Plugin*') * @param session the session * @return the network type in HBO or #GNUNET_SYSERR */ static enum GNUNET_ATS_Network_Type tcp_get_network (void *cls, struct Session *session) { struct Plugin * plugin = cls; GNUNET_assert (NULL != plugin); GNUNET_assert (NULL != session); if (GNUNET_SYSERR == find_session (plugin,session)) return GNUNET_ATS_NET_UNSPECIFIED; return session->ats_address_network_type; } /** * Entry point for the plugin. * * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*' * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error */ void * libgnunet_plugin_transport_tcp_init (void *cls) { static const struct GNUNET_SERVER_MessageHandler my_handlers[] = { { &handle_tcp_welcome, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME, sizeof(struct WelcomeMessage) }, { &handle_tcp_nat_probe, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE, sizeof(struct TCP_NAT_ProbeMessage) }, { &handle_tcp_data, NULL, GNUNET_MESSAGE_TYPE_ALL, 0 }, { NULL, NULL, 0, 0 } }; struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *plugin; struct GNUNET_SERVICE_Context *service; unsigned long long aport; unsigned long long bport; unsigned long long max_connections; unsigned int i; struct GNUNET_TIME_Relative idle_timeout; int ret; int ret_s; struct sockaddr **addrs; socklen_t *addrlens; if (NULL == env->receive) { /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully initialze the plugin or the API */ api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = NULL; api->address_pretty_printer = &tcp_plugin_address_pretty_printer; api->address_to_string = &tcp_address_to_string; api->string_to_address = &tcp_string_to_address; return api; } GNUNET_assert(NULL != env->cfg); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp", "MAX_CONNECTIONS", &max_connections)) max_connections = 128; aport = 0; if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp", "PORT", &bport)) || (bport > 65535) || ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp", "ADVERTISED-PORT", &aport)) && (aport > 65535))) { LOG(GNUNET_ERROR_TYPE_ERROR, _("Require valid port number for service `%s' in configuration!\n"), "transport-tcp"); return NULL ; } if (aport == 0) aport = bport; if (bport == 0) aport = 0; if (bport != 0) { service = GNUNET_SERVICE_start ("transport-tcp", env->cfg, GNUNET_SERVICE_OPTION_NONE); if (service == NULL ) { LOG(GNUNET_ERROR_TYPE_WARNING, _("Failed to start service.\n")); return NULL ; } } else service = NULL; /* Initialize my flags */ myoptions = 0; plugin = GNUNET_new (struct Plugin); plugin->sessionmap = GNUNET_CONTAINER_multipeermap_create (max_connections, GNUNET_YES); plugin->max_connections = max_connections; plugin->cur_connections = 0; plugin->open_port = bport; plugin->adv_port = aport; plugin->env = env; plugin->lsock = NULL; if ((service != NULL )&& (GNUNET_SYSERR != (ret_s = GNUNET_SERVICE_get_server_addresses ("transport-tcp", env->cfg, &addrs, &addrlens)))){ for (ret = ret_s-1; ret >= 0; ret--) LOG (GNUNET_ERROR_TYPE_INFO, "Binding to address `%s'\n", GNUNET_a2s (addrs[ret], addrlens[ret])); plugin->nat = GNUNET_NAT_register (env->cfg, GNUNET_YES, aport, (unsigned int) ret_s, (const struct sockaddr **) addrs, addrlens, &tcp_nat_port_map_callback, &try_connection_reversal, plugin); for (ret = ret_s -1; ret >= 0; ret--) { GNUNET_assert (addrs[ret] != NULL); GNUNET_free (addrs[ret]); } GNUNET_free_non_null (addrs); GNUNET_free_non_null (addrlens); } else { plugin->nat = GNUNET_NAT_register (plugin->env->cfg, GNUNET_YES, 0, 0, NULL, NULL, NULL, &try_connection_reversal, plugin); } api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = plugin; api->send = &tcp_plugin_send; api->get_session = &tcp_plugin_get_session; api->disconnect_session = &tcp_disconnect_session; api->query_keepalive_factor = &tcp_query_keepalive_factor; api->disconnect_peer = &tcp_plugin_disconnect; api->address_pretty_printer = &tcp_plugin_address_pretty_printer; api->check_address = &tcp_plugin_check_address; api->address_to_string = &tcp_address_to_string; api->string_to_address = &tcp_string_to_address; api->get_network = &tcp_get_network; api->update_session_timeout = &tcp_plugin_update_session_timeout; api->update_inbound_delay = &tcp_plugin_update_inbound_delay; plugin->service = service; if (NULL != service) { plugin->server = GNUNET_SERVICE_get_server (service); } else { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-tcp", "TIMEOUT", &idle_timeout)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "transport-tcp", "TIMEOUT"); if (plugin->nat != NULL ) GNUNET_NAT_unregister (plugin->nat); GNUNET_free(plugin); GNUNET_free(api); return NULL ; } plugin->server = GNUNET_SERVER_create_with_sockets ( &plugin_tcp_access_check, plugin, NULL, idle_timeout, GNUNET_YES); } plugin->handlers = GNUNET_malloc (sizeof (my_handlers)); memcpy (plugin->handlers, my_handlers, sizeof(my_handlers)); for (i = 0; i < sizeof(my_handlers) / sizeof(struct GNUNET_SERVER_MessageHandler); i++) plugin->handlers[i].callback_cls = plugin; GNUNET_SERVER_add_handlers (plugin->server, plugin->handlers); GNUNET_SERVER_disconnect_notify (plugin->server, &disconnect_notify, plugin); plugin->nat_wait_conns = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_YES); if (bport != 0) LOG(GNUNET_ERROR_TYPE_INFO, _("TCP transport listening on port %llu\n"), bport); else LOG(GNUNET_ERROR_TYPE_INFO, _("TCP transport not listening on any port (client only)\n")); if (aport != bport) LOG(GNUNET_ERROR_TYPE_INFO, _("TCP transport advertises itself as being on port %llu\n"), aport); /* Initially set connections to 0 */ GNUNET_assert(NULL != plugin->env->stats); GNUNET_STATISTICS_set (plugin->env->stats, gettext_noop ("# TCP sessions active"), 0, GNUNET_NO); return api; } /** * Exit point from the plugin. * * @param cls the `struct GNUNET_TRANSPORT_PluginFunctions` * @return NULL */ void * libgnunet_plugin_transport_tcp_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; struct TCPProbeContext *tcp_probe; struct PrettyPrinterContext *cur; struct PrettyPrinterContext *next; if (NULL == plugin) { GNUNET_free(api); return NULL ; } LOG(GNUNET_ERROR_TYPE_DEBUG, "Shutting down TCP plugin\n"); /* Removing leftover sessions */ GNUNET_CONTAINER_multipeermap_iterate (plugin->sessionmap, &session_disconnect_it, plugin); /* Removing leftover NAT sessions */ GNUNET_CONTAINER_multipeermap_iterate (plugin->nat_wait_conns, &session_disconnect_it, plugin); next = ppc_dll_head; for (cur = next; NULL != cur; cur = next) { next = cur->next; GNUNET_CONTAINER_DLL_remove(ppc_dll_head, ppc_dll_tail, cur); if (NULL != cur->resolver_handle) GNUNET_RESOLVER_request_cancel (cur->resolver_handle); GNUNET_SCHEDULER_cancel (cur->timeout_task); GNUNET_free(cur); GNUNET_break(0); } if (plugin->service != NULL ) GNUNET_SERVICE_stop (plugin->service); else GNUNET_SERVER_destroy (plugin->server); GNUNET_free(plugin->handlers); if (plugin->nat != NULL ) GNUNET_NAT_unregister (plugin->nat); while (NULL != (tcp_probe = plugin->probe_head)) { GNUNET_CONTAINER_DLL_remove(plugin->probe_head, plugin->probe_tail, tcp_probe); GNUNET_CONNECTION_destroy (tcp_probe->sock); GNUNET_free(tcp_probe); } GNUNET_CONTAINER_multipeermap_destroy (plugin->nat_wait_conns); GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap); GNUNET_free(plugin); GNUNET_free(api); return NULL ; } /* end of plugin_transport_tcp.c */ gnunet-0.10.1/src/transport/plugin_transport_http_client.c0000644000175000017500000015162512316473377021037 00000000000000/* This file is part of GNUnet (C) 2002-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_http_client.c * @brief HTTP/S client transport plugin * @author Matthias Wachs */ #if BUILD_HTTPS #define PLUGIN_NAME "https_client" #define HTTP_STAT_STR_CONNECTIONS "# HTTPS client connections" #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_client_init #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_client_done #else #define PLUGIN_NAME "http_client" #define HTTP_STAT_STR_CONNECTIONS "# HTTP client connections" #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_client_init #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_client_done #endif #define VERBOSE_CURL GNUNET_YES #define PUT_DISCONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) #define ENABLE_PUT GNUNET_YES #define ENABLE_GET GNUNET_YES #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_transport_plugin.h" #include "plugin_transport_http_common.h" #include /** * Encapsulation of all of the state of the plugin. */ struct HTTP_Client_Plugin; /** * Message to send using http */ struct HTTP_Message { /** * next pointer for double linked list */ struct HTTP_Message *next; /** * previous pointer for double linked list */ struct HTTP_Message *prev; /** * buffer containing data to send */ char *buf; /** * amount of data already sent */ size_t pos; /** * buffer length */ size_t size; /** * Continuation function to call once the transmission buffer * has again space available. NULL if there is no * continuation to call. */ GNUNET_TRANSPORT_TransmitContinuation transmit_cont; /** * Closure for transmit_cont. */ void *transmit_cont_cls; }; /** * Session handle for connections. */ struct Session; /** * A connection handle * */ struct ConnectionHandle { /** * The curl easy handle */ CURL *easyhandle; /** * The related session */ struct Session *s; }; /** * Session handle for connections. */ struct Session { /** * To whom are we talking to (set to our identity * if we are still waiting for the welcome message) */ struct GNUNET_PeerIdentity target; /** * Stored in a linked list. */ struct Session *next; /** * Stored in a linked list. */ struct Session *prev; /** * The URL to connect to */ char *url; /** * Address */ struct GNUNET_HELLO_Address *address; /** * ATS network type in NBO */ uint32_t ats_address_network_type; /** * Pointer to the global plugin struct. */ struct HTTP_Client_Plugin *plugin; /** * Client send handle */ void *client_put; struct ConnectionHandle put; struct ConnectionHandle get; /** * Is the client PUT handle currently paused */ int put_paused; /** * Is the client PUT handle disconnect in progress? */ int put_tmp_disconnecting; /** * Is the client PUT handle temporarily disconnected? */ int put_tmp_disconnected; /** * We received data to send while disconnecting, reconnect immediately */ int put_reconnect_required; /** * Client receive handle */ void *client_get; /** * Outbound overhead due to HTTP connection * Add to next message of this session when calling callback */ size_t overhead; /** * next pointer for double linked list */ struct HTTP_Message *msg_head; /** * previous pointer for double linked list */ struct HTTP_Message *msg_tail; /** * Message stream tokenizer for incoming data */ struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk; /** * Session timeout task */ GNUNET_SCHEDULER_TaskIdentifier put_disconnect_task; /** * Session timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Task to wake up client receive handle when receiving is allowed again */ GNUNET_SCHEDULER_TaskIdentifier recv_wakeup_task; /** * Absolute time when to receive data again * Used for receive throttling */ struct GNUNET_TIME_Absolute next_receive; }; /** * Encapsulation of all of the state of the plugin. */ struct HTTP_Client_Plugin { /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * Linked list head of open sessions. */ struct Session *head; /** * Linked list tail of open sessions. */ struct Session *tail; /** * Plugin name */ char *name; /** * Protocol */ char *protocol; /** * My options to be included in the address */ uint32_t options; /** * Maximum number of sockets the plugin can use * Each http inbound /outbound connections are two connections */ unsigned int max_connections; /** * Current number of sockets the plugin can use * Each http inbound /outbound connections are two connections */ unsigned int cur_connections; /** * Last used unique HTTP connection tag */ uint32_t last_tag; /** * use IPv6 */ uint16_t use_ipv6; /** * use IPv4 */ uint16_t use_ipv4; /** * cURL Multihandle */ CURLM *curl_multi_handle; /** * curl perform task */ GNUNET_SCHEDULER_TaskIdentifier client_perform_task; }; /** * Increment session timeout due to activity for a session * @param s the session */ static void client_reschedule_session_timeout (struct Session *s); /** * Function setting up file descriptors and scheduling task to run * * @param plugin plugin as closure * @param now schedule task in 1ms, regardless of what curl may say * @return GNUNET_SYSERR for hard failure, GNUNET_OK for ok */ static int client_schedule (struct HTTP_Client_Plugin *plugin, int now); /** * Connect a HTTP put connection * * @param s the session to connect * @return #GNUNET_SYSERR for hard failure, #GNUNET_OK for success */ static int client_connect_put (struct Session *s); /** * Does a session s exists? * * @param plugin the plugin * @param s desired session * @return #GNUNET_YES or #GNUNET_NO */ static int client_exist_session (struct HTTP_Client_Plugin *plugin, struct Session *s) { struct Session * head; for (head = plugin->head; head != NULL; head = head->next) if (head == s) return GNUNET_YES; return GNUNET_NO; } /** * Loggging function * * @param curl the curl easy handle * @param type message type * @param data data to log, NOT a 0-terminated string * @param size data length * @param cls the closure * @return always 0 */ static int client_log (CURL *curl, curl_infotype type, const char *data, size_t size, void *cls) { struct ConnectionHandle *ch = cls; const char *ttype = "UNSPECIFIED"; if ((type == CURLINFO_TEXT) || (type == CURLINFO_HEADER_IN) || (type == CURLINFO_HEADER_OUT)) { char text[size + 2]; switch (type) { case CURLINFO_TEXT: ttype = "TEXT"; break; case CURLINFO_HEADER_IN: ttype = "HEADER_IN"; break; case CURLINFO_HEADER_OUT: ttype = "HEADER_OUT"; /* Overhead*/ GNUNET_assert (NULL != ch); GNUNET_assert (NULL != ch->easyhandle); GNUNET_assert (NULL != ch->s); ch->s->overhead += size; break; default: ttype = "UNSPECIFIED"; break; } memcpy (text, data, size); if (text[size - 1] == '\n') text[size] = '\0'; else { text[size] = '\n'; text[size + 1] = '\0'; } #if BUILD_HTTPS GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-https_client", "Connection %p %s: %s", ch->easyhandle, ttype, text); #else GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-http_client", "Connection %p %s: %s", ch->easyhandle, ttype, text); #endif } return 0; } /** * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param s which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in 'msgbuf' * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t http_client_plugin_send (void *cls, struct Session *s, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct HTTP_Client_Plugin *plugin = cls; struct HTTP_Message *msg; char *stat_txt; /* lookup if session is really existing */ if (GNUNET_YES != client_exist_session (plugin, s)) { GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p/connection %p: Sending message with %u to peer `%s' \n", s, s->client_put, msgbuf_size, GNUNET_i2s (&s->target)); /* create new message and schedule */ msg = GNUNET_malloc (sizeof (struct HTTP_Message) + msgbuf_size); msg->next = NULL; msg->size = msgbuf_size; msg->pos = 0; msg->buf = (char *) &msg[1]; msg->transmit_cont = cont; msg->transmit_cont_cls = cont_cls; memcpy (msg->buf, msgbuf, msgbuf_size); GNUNET_CONTAINER_DLL_insert_tail (s->msg_head, s->msg_tail, msg); GNUNET_asprintf (&stat_txt, "# bytes currently in %s_client buffers", plugin->protocol); GNUNET_STATISTICS_update (plugin->env->stats, stat_txt, msgbuf_size, GNUNET_NO); GNUNET_free (stat_txt); if (GNUNET_YES == s->put_tmp_disconnecting) { /* PUT connection is currently getting disconnected */ s->put_reconnect_required = GNUNET_YES; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p/connection %jp: currently disconnecting, reconnecting immediately\n", s, s->client_put); return msgbuf_size; } else if (GNUNET_YES == s->put_paused) { /* PUT connection was paused, unpause */ GNUNET_assert (s->put_disconnect_task != GNUNET_SCHEDULER_NO_TASK); GNUNET_SCHEDULER_cancel (s->put_disconnect_task); s->put_disconnect_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p/connection %p: unpausing connection\n", s, s->client_put); s->put_paused = GNUNET_NO; if (NULL != s->client_put) curl_easy_pause (s->client_put, CURLPAUSE_CONT); } else if (GNUNET_YES == s->put_tmp_disconnected) { /* PUT connection was disconnected, reconnect */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p: Reconnecting PUT connection\n", s); s->put_tmp_disconnected = GNUNET_NO; GNUNET_break (s->client_put == NULL); if (GNUNET_SYSERR == client_connect_put (s)) { return GNUNET_SYSERR; } } client_schedule (s->plugin, GNUNET_YES); return msgbuf_size; } /** * Delete session s * * @param s the session to delete */ static void client_delete_session (struct Session *s) { struct HTTP_Client_Plugin *plugin = s->plugin; struct HTTP_Message *pos; struct HTTP_Message *next; if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task) { GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != s->put_disconnect_task) { GNUNET_SCHEDULER_cancel (s->put_disconnect_task); s->put_disconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); next = s->msg_head; while (NULL != (pos = next)) { next = pos->next; GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, pos); if (pos->transmit_cont != NULL) pos->transmit_cont (pos->transmit_cont_cls, &s->target, GNUNET_SYSERR, pos->size, pos->pos + s->overhead); s->overhead = 0; GNUNET_free (pos); } if (s->msg_tk != NULL) { GNUNET_SERVER_mst_destroy (s->msg_tk); s->msg_tk = NULL; } GNUNET_HELLO_address_free (s->address); GNUNET_free (s->url); GNUNET_free (s); } /** * Disconnect a session * * @param cls the `struct HTTP_Client_Plugin` * @param s session * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int http_client_session_disconnect (void *cls, struct Session *s) { struct HTTP_Client_Plugin *plugin = cls; struct HTTP_Message *msg; struct HTTP_Message *t; int res = GNUNET_OK; CURLMcode mret; if (GNUNET_YES != client_exist_session (plugin, s)) { GNUNET_break (0); return GNUNET_SYSERR; } if (NULL != s->client_put) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p/connection %p: disconnecting PUT connection to peer `%s'\n", s, s->client_put, GNUNET_i2s (&s->target)); /* remove curl handle from multi handle */ mret = curl_multi_remove_handle (plugin->curl_multi_handle, s->client_put); if (mret != CURLM_OK) { /* clean up easy handle, handle is now invalid and free'd */ res = GNUNET_SYSERR; GNUNET_break (0); } curl_easy_cleanup (s->client_put); s->client_put = NULL; } if (s->recv_wakeup_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (s->recv_wakeup_task); s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != s->client_get) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p/connection %p: disconnecting GET connection to peer `%s'\n", s, s->client_get, GNUNET_i2s (&s->target)); /* remove curl handle from multi handle */ mret = curl_multi_remove_handle (plugin->curl_multi_handle, s->client_get); if (mret != CURLM_OK) { /* clean up easy handle, handle is now invalid and free'd */ res = GNUNET_SYSERR; GNUNET_break (0); } curl_easy_cleanup (s->client_get); s->client_get = NULL; } msg = s->msg_head; while (NULL != msg) { t = msg->next; if (NULL != msg->transmit_cont) msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR, msg->size, msg->pos + s->overhead); s->overhead = 0; GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); GNUNET_free (msg); msg = t; } GNUNET_assert (plugin->cur_connections >= 2); plugin->cur_connections -= 2; GNUNET_STATISTICS_set (plugin->env->stats, HTTP_STAT_STR_CONNECTIONS, plugin->cur_connections, GNUNET_NO); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p: notifying transport about ending session\n",s); plugin->env->session_end (plugin->env->cls, s->address, s); client_delete_session (s); /* Re-schedule since handles have changed */ if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } client_schedule (plugin, GNUNET_YES); return res; } /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int http_client_query_keepalive_factor (void *cls) { return 3; } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuationc). * * @param cls closure * @param target peer from which to disconnect */ static void http_client_peer_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) { struct HTTP_Client_Plugin *plugin = cls; struct Session *next = NULL; struct Session *pos = NULL; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Transport tells me to disconnect `%s'\n", GNUNET_i2s (target)); next = plugin->head; while (NULL != (pos = next)) { next = pos->next; if (0 == memcmp (target, &pos->target, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Disconnecting session %p to `%pos'\n", pos, GNUNET_i2s (target)); GNUNET_assert (GNUNET_OK == http_client_session_disconnect (plugin, pos)); } } } /** * Check if a sessions exists for an specific address * * @param plugin the plugin * @param address the address * @return the session or NULL */ static struct Session * client_lookup_session (struct HTTP_Client_Plugin *plugin, const struct GNUNET_HELLO_Address *address) { struct Session *pos; for (pos = plugin->head; NULL != pos; pos = pos->next) { if ((0 == memcmp (&address->peer, &pos->target, sizeof (struct GNUNET_PeerIdentity))) && (0 == GNUNET_HELLO_address_cmp(address, pos->address))) return pos; } return NULL; } static void client_put_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *s = cls; s->put_disconnect_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p/connection %p: will be disconnected due to no activity\n", s, s->client_put); s->put_paused = GNUNET_NO; s->put_tmp_disconnecting = GNUNET_YES; if (NULL != s->client_put) curl_easy_pause (s->client_put, CURLPAUSE_CONT); client_schedule (s->plugin, GNUNET_YES); } /** * Callback method used with libcurl * Method is called when libcurl needs to read data during sending * * @param stream pointer where to write data * @param size size of an individual element * @param nmemb count of elements that can be written to the buffer * @param cls our `struct Session` * @return bytes written to stream, returning 0 will terminate connection! */ static size_t client_send_cb (void *stream, size_t size, size_t nmemb, void *cls) { struct Session *s = cls; struct HTTP_Client_Plugin *plugin = s->plugin; struct HTTP_Message *msg = s->msg_head; size_t len; char *stat_txt; if (GNUNET_YES != client_exist_session (plugin, s)) { GNUNET_break (0); return 0; } if (GNUNET_YES == s->put_tmp_disconnecting) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p/connection %p: disconnect due to inactivity\n", s, s->client_put); return 0; } if (NULL == msg) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p/connection %p: nothing to send, suspending\n", s, s->client_put); s->put_disconnect_task = GNUNET_SCHEDULER_add_delayed (PUT_DISCONNECT_TIMEOUT, &client_put_disconnect, s); s->put_paused = GNUNET_YES; return CURL_READFUNC_PAUSE; } /* data to send */ GNUNET_assert (msg->pos < msg->size); /* calculate how much fits in buffer */ len = GNUNET_MIN (msg->size - msg->pos, size * nmemb); memcpy (stream, &msg->buf[msg->pos], len); msg->pos += len; if (msg->pos == msg->size) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p/connection %p: sent message with %u bytes sent, removing message from queue\n", s, s->client_put, msg->size, msg->pos); /* Calling transmit continuation */ GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); if (NULL != msg->transmit_cont) msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK, msg->size, msg->size + s->overhead); s->overhead = 0; GNUNET_free (msg); } GNUNET_asprintf (&stat_txt, "# bytes currently in %s_client buffers", plugin->protocol); GNUNET_STATISTICS_update (plugin->env->stats, stat_txt, -len, GNUNET_NO); GNUNET_free (stat_txt); GNUNET_asprintf (&stat_txt, "# bytes transmitted via %s_client", plugin->protocol); GNUNET_STATISTICS_update (plugin->env->stats, stat_txt, len, GNUNET_NO); GNUNET_free (stat_txt); return len; } /** * Wake up a curl handle which was suspended * * @param cls the session * @param tc task context */ static void client_wake_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *s = cls; struct HTTP_Client_Plugin *p = s->plugin; if (GNUNET_YES != client_exist_session (p, s)) { GNUNET_break (0); return; } s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p/connection %p: Waking up GET handle\n", s, s->client_get); s->put_paused = GNUNET_NO; if (NULL != s->client_get) curl_easy_pause (s->client_get, CURLPAUSE_CONT); } /** * Callback for message stream tokenizer * * @param cls the session * @param client not used * @param message the message received * @return always #GNUNET_OK */ static int client_receive_mst_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct Session *s = cls; struct HTTP_Client_Plugin *plugin; struct GNUNET_TIME_Relative delay; struct GNUNET_ATS_Information atsi; char *stat_txt; plugin = s->plugin; if (GNUNET_YES != client_exist_session (plugin, s)) { GNUNET_break (0); return GNUNET_OK; } atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); atsi.value = s->ats_address_network_type; GNUNET_break (s->ats_address_network_type != ntohl (GNUNET_ATS_NET_UNSPECIFIED)); delay = s->plugin->env->receive (plugin->env->cls, s->address, s, message); plugin->env->update_address_metrics (plugin->env->cls, s->address, s, &atsi, 1); GNUNET_asprintf (&stat_txt, "# bytes received via %s_client", plugin->protocol); GNUNET_STATISTICS_update (plugin->env->stats, stat_txt, ntohs(message->size), GNUNET_NO); GNUNET_free (stat_txt); s->next_receive = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay); if (GNUNET_TIME_absolute_get ().abs_value_us < s->next_receive.abs_value_us) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Client: peer `%s' address `%s' next read delayed for %s\n", GNUNET_i2s (&s->target), http_common_plugin_address_to_string (NULL, s->plugin->protocol, s->address->address, s->address->address_length), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); } client_reschedule_session_timeout (s); return GNUNET_OK; } /** * Callback method used with libcurl when data for a PUT connection are * received. We do not expect data here, so we just dismiss it * * @param stream pointer where to write data * @param size size of an individual element * @param nmemb count of elements that can be written to the buffer * @param cls destination pointer, passed to the libcurl handle * @return bytes read from stream */ static size_t client_receive_put (void *stream, size_t size, size_t nmemb, void *cls) { return size * nmemb; } /** * Callback method used with libcurl when data for a GET connection are * received. Forward to MST * * @param stream pointer where to write data * @param size size of an individual element * @param nmemb count of elements that can be written to the buffer * @param cls destination pointer, passed to the libcurl handle * @return bytes read from stream */ static size_t client_receive (void *stream, size_t size, size_t nmemb, void *cls) { struct Session *s = cls; struct GNUNET_TIME_Absolute now; size_t len = size * nmemb; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p / connection %p: Received %u bytes from peer `%s'\n", s, s->client_get, len, GNUNET_i2s (&s->target)); now = GNUNET_TIME_absolute_get (); if (now.abs_value_us < s->next_receive.abs_value_us) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct GNUNET_TIME_Relative delta = GNUNET_TIME_absolute_get_difference (now, s->next_receive); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p / connection %p: No inbound bandwidth available! Next read was delayed for %s\n", s, s->client_get, GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES)); if (s->recv_wakeup_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (s->recv_wakeup_task); s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK; } s->recv_wakeup_task = GNUNET_SCHEDULER_add_delayed (delta, &client_wake_up, s); return CURL_WRITEFUNC_PAUSE; } if (NULL == s->msg_tk) s->msg_tk = GNUNET_SERVER_mst_create (&client_receive_mst_cb, s); GNUNET_SERVER_mst_receive (s->msg_tk, s, stream, len, GNUNET_NO, GNUNET_NO); return len; } /** * Task performing curl operations * * @param cls plugin as closure * @param tc gnunet scheduler task context */ static void client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Function setting up file descriptors and scheduling task to run * * @param plugin the plugin as closure * @param now schedule task in 1ms, regardless of what curl may say * @return #GNUNET_SYSERR for hard failure, #GNUNET_OK for ok */ static int client_schedule (struct HTTP_Client_Plugin *plugin, int now) { fd_set rs; fd_set ws; fd_set es; int max; struct GNUNET_NETWORK_FDSet *grs; struct GNUNET_NETWORK_FDSet *gws; long to; CURLMcode mret; struct GNUNET_TIME_Relative timeout; /* Cancel previous scheduled task */ if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } max = -1; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); mret = curl_multi_fdset (plugin->curl_multi_handle, &rs, &ws, &es, &max); if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_fdset", __FILE__, __LINE__, curl_multi_strerror (mret)); return GNUNET_SYSERR; } mret = curl_multi_timeout (plugin->curl_multi_handle, &to); if (to == -1) timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1); else timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, to); if (now == GNUNET_YES) timeout = GNUNET_TIME_UNIT_MILLISECONDS; if (mret != CURLM_OK) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), "curl_multi_timeout", __FILE__, __LINE__, curl_multi_strerror (mret)); return GNUNET_SYSERR; } grs = GNUNET_NETWORK_fdset_create (); gws = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); plugin->client_perform_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, timeout, grs, gws, &client_run, plugin); GNUNET_NETWORK_fdset_destroy (gws); GNUNET_NETWORK_fdset_destroy (grs); return GNUNET_OK; } /** * Task performing curl operations * * @param cls plugin as closure * @param tc gnunet scheduler task context */ static void client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct HTTP_Client_Plugin *plugin = cls; int running; long http_statuscode; CURLMcode mret; GNUNET_assert (cls != NULL); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; do { running = 0; mret = curl_multi_perform (plugin->curl_multi_handle, &running); CURLMsg *msg; int msgs_left; while ((msg = curl_multi_info_read (plugin->curl_multi_handle, &msgs_left))) { CURL *easy_h = msg->easy_handle; struct Session *s = NULL; char *d = (char *) s; if (easy_h == NULL) { GNUNET_break (0); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Client: connection to ended with reason %i: `%s', %i handles running\n", msg->data.result, curl_easy_strerror (msg->data.result), running); continue; } GNUNET_assert (CURLE_OK == curl_easy_getinfo (easy_h, CURLINFO_PRIVATE, &d)); s = (struct Session *) d; if (GNUNET_YES != client_exist_session(plugin, s)) { GNUNET_break (0); return; } GNUNET_assert (s != NULL); if (msg->msg == CURLMSG_DONE) { curl_easy_getinfo (easy_h, CURLINFO_RESPONSE_CODE, &http_statuscode); if (easy_h == s->client_put) { if ((0 != msg->data.result) || (http_statuscode != 200)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p/connection %p: PUT connection to `%s' ended with status %i reason %i: `%s'\n", s, msg->easy_handle, GNUNET_i2s (&s->target), http_statuscode, msg->data.result, curl_easy_strerror (msg->data.result)); } else GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p/connection %p: PUT connection to `%s' ended normal\n", s, msg->easy_handle, GNUNET_i2s (&s->target)); if (s->client_get == NULL) { /* Disconnect other transmission direction and tell transport */ } curl_multi_remove_handle (plugin->curl_multi_handle, easy_h); curl_easy_cleanup (easy_h); s->put_tmp_disconnecting = GNUNET_NO; s->put_tmp_disconnected = GNUNET_YES; s->client_put = NULL; s->put.easyhandle = NULL; s->put.s = NULL; /* * Handling a rare case: * plugin_send was called during temporary put disconnect, * reconnect required after connection was disconnected */ if (GNUNET_YES == s->put_reconnect_required) { s->put_reconnect_required = GNUNET_NO; if (GNUNET_SYSERR == client_connect_put(s)) { GNUNET_break (s->client_put == NULL); GNUNET_break (s->put_tmp_disconnected == GNUNET_NO); } } } if (easy_h == s->client_get) { if ((0 != msg->data.result) || (http_statuscode != 200)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p/connection %p: GET connection to `%s' ended with status %i reason %i: `%s'\n", s, msg->easy_handle, GNUNET_i2s (&s->target), http_statuscode, msg->data.result, curl_easy_strerror (msg->data.result)); } else GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p/connection %p: GET connection to `%s' ended normal\n", s, msg->easy_handle, GNUNET_i2s (&s->target)); /* Disconnect other transmission direction and tell transport */ s->get.easyhandle = NULL; s->get.s = NULL; http_client_session_disconnect (plugin, s); } } } } while (mret == CURLM_CALL_MULTI_PERFORM); client_schedule (plugin, GNUNET_NO); } /** * Connect GET connection for a session * * @param s the session to connect * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ static int client_connect_get (struct Session *s) { CURLMcode mret; /* create get connection */ s->client_get = curl_easy_init (); s->get.s = s; s->get.easyhandle = s->client_get; #if VERBOSE_CURL curl_easy_setopt (s->client_get, CURLOPT_VERBOSE, 1L); curl_easy_setopt (s->client_get, CURLOPT_DEBUGFUNCTION, &client_log); curl_easy_setopt (s->client_get, CURLOPT_DEBUGDATA, &s->get); #endif #if BUILD_HTTPS curl_easy_setopt (s->client_get, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); { struct HttpAddress *ha; ha = (struct HttpAddress *) s->address->address; if (HTTP_OPTIONS_VERIFY_CERTIFICATE == (ntohl (ha->options) & HTTP_OPTIONS_VERIFY_CERTIFICATE)) { curl_easy_setopt (s->client_get, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt (s->client_get, CURLOPT_SSL_VERIFYHOST, 2L); } else { curl_easy_setopt (s->client_get, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt (s->client_get, CURLOPT_SSL_VERIFYHOST, 0); } } curl_easy_setopt (s->client_get, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); curl_easy_setopt (s->client_get, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS); #else curl_easy_setopt (s->client_get, CURLOPT_PROTOCOLS, CURLPROTO_HTTP); curl_easy_setopt (s->client_get, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP); #endif curl_easy_setopt (s->client_get, CURLOPT_URL, s->url); //curl_easy_setopt (s->client_get, CURLOPT_HEADERFUNCTION, &curl_get_header_cb); //curl_easy_setopt (s->client_get, CURLOPT_WRITEHEADER, ps); curl_easy_setopt (s->client_get, CURLOPT_READFUNCTION, client_send_cb); curl_easy_setopt (s->client_get, CURLOPT_READDATA, s); curl_easy_setopt (s->client_get, CURLOPT_WRITEFUNCTION, client_receive); curl_easy_setopt (s->client_get, CURLOPT_WRITEDATA, s); /* No timeout by default, timeout done with session timeout */ curl_easy_setopt (s->client_get, CURLOPT_TIMEOUT, 0); curl_easy_setopt (s->client_get, CURLOPT_PRIVATE, s); curl_easy_setopt (s->client_get, CURLOPT_CONNECTTIMEOUT_MS, (long) (HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us / 1000LL)); curl_easy_setopt (s->client_get, CURLOPT_BUFFERSIZE, 2 * GNUNET_SERVER_MAX_MESSAGE_SIZE); #if CURL_TCP_NODELAY curl_easy_setopt (ps->recv_endpoint, CURLOPT_TCP_NODELAY, 1); #endif curl_easy_setopt (s->client_get, CURLOPT_FOLLOWLOCATION, 0); mret = curl_multi_add_handle (s->plugin->curl_multi_handle, s->client_get); if (mret != CURLM_OK) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, s->plugin->name, "Session %p : Failed to add GET handle to multihandle: `%s'\n", s, curl_multi_strerror (mret)); curl_easy_cleanup (s->client_get); s->client_get = NULL; s->get.s = NULL; s->get.easyhandle = NULL; GNUNET_break (0); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Connect a HTTP put connection * * @param s the session to connect * @return #GNUNET_SYSERR for hard failure, #GNUNET_OK for ok */ static int client_connect_put (struct Session *s) { CURLMcode mret; /* create put connection */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Session %p : Init PUT handle\n", s); s->client_put = curl_easy_init (); s->put.s = s; s->put.easyhandle = s->client_put; #if VERBOSE_CURL curl_easy_setopt (s->client_put, CURLOPT_VERBOSE, 1L); curl_easy_setopt (s->client_put, CURLOPT_DEBUGFUNCTION, &client_log); curl_easy_setopt (s->client_put, CURLOPT_DEBUGDATA, &s->put); #endif #if BUILD_HTTPS curl_easy_setopt (s->client_put, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); { struct HttpAddress *ha; ha = (struct HttpAddress *) s->address->address; if (HTTP_OPTIONS_VERIFY_CERTIFICATE == (ntohl (ha->options) & HTTP_OPTIONS_VERIFY_CERTIFICATE)) { curl_easy_setopt (s->client_put, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt (s->client_put, CURLOPT_SSL_VERIFYHOST, 2L); } else { curl_easy_setopt (s->client_put, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt (s->client_put, CURLOPT_SSL_VERIFYHOST, 0); } } curl_easy_setopt (s->client_get, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); curl_easy_setopt (s->client_get, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS); #else curl_easy_setopt (s->client_get, CURLOPT_PROTOCOLS, CURLPROTO_HTTP); curl_easy_setopt (s->client_get, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP); #endif curl_easy_setopt (s->client_put, CURLOPT_URL, s->url); curl_easy_setopt (s->client_put, CURLOPT_UPLOAD, 1L); //curl_easy_setopt (s->client_put, CURLOPT_HEADERFUNCTION, &client_curl_header); //curl_easy_setopt (s->client_put, CURLOPT_WRITEHEADER, ps); curl_easy_setopt (s->client_put, CURLOPT_READFUNCTION, client_send_cb); curl_easy_setopt (s->client_put, CURLOPT_READDATA, s); curl_easy_setopt (s->client_put, CURLOPT_WRITEFUNCTION, client_receive_put); curl_easy_setopt (s->client_put, CURLOPT_WRITEDATA, s); /* No timeout by default, timeout done with session timeout */ curl_easy_setopt (s->client_put, CURLOPT_TIMEOUT, 0); curl_easy_setopt (s->client_put, CURLOPT_PRIVATE, s); curl_easy_setopt (s->client_put, CURLOPT_CONNECTTIMEOUT_MS, (long) (HTTP_CLIENT_NOT_VALIDATED_TIMEOUT.rel_value_us / 1000LL)); curl_easy_setopt (s->client_put, CURLOPT_BUFFERSIZE, 2 * GNUNET_SERVER_MAX_MESSAGE_SIZE); #if CURL_TCP_NODELAY curl_easy_setopt (s->client_put, CURLOPT_TCP_NODELAY, 1); #endif mret = curl_multi_add_handle (s->plugin->curl_multi_handle, s->client_put); if (mret != CURLM_OK) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, s->plugin->name, "Session %p : Failed to add PUT handle to multihandle: `%s'\n", s, curl_multi_strerror (mret)); curl_easy_cleanup (s->client_put); s->client_put = NULL; s->put.easyhandle = NULL; s->put.s = NULL; s->put_tmp_disconnected = GNUNET_YES; return GNUNET_SYSERR; } s->put_tmp_disconnected = GNUNET_NO; return GNUNET_OK; } /** * Connect both PUT and GET connection for a session * * @param s the session to connect * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ static int client_connect (struct Session *s) { struct HTTP_Client_Plugin *plugin = s->plugin; int res = GNUNET_OK; /* create url */ if (NULL == http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Invalid address peer `%s'\n", GNUNET_i2s (&s->target)); return GNUNET_SYSERR; } GNUNET_asprintf (&s->url, "%s/%s;%u", http_common_plugin_address_to_url (NULL, s->address->address, s->address->address_length), GNUNET_i2s_full (plugin->env->my_identity), plugin->last_tag); plugin->last_tag++; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Initiating outbound session peer `%s' using address `%s'\n", GNUNET_i2s (&s->target), s->url); if ((GNUNET_SYSERR == client_connect_get (s)) || (GNUNET_SYSERR == client_connect_put (s))) { plugin->env->session_end (plugin->env->cls, s->address, s); client_delete_session (s); return GNUNET_SYSERR; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p: connected with connections GET %p and PUT %p\n", s, s->client_get, s->client_put); /* Perform connect */ plugin->cur_connections += 2; GNUNET_STATISTICS_set (plugin->env->stats, HTTP_STAT_STR_CONNECTIONS, plugin->cur_connections, GNUNET_NO); /* Re-schedule since handles have changed */ if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } plugin->client_perform_task = GNUNET_SCHEDULER_add_now (client_run, plugin); return res; } /** * Function obtain the network type for a session * * @param cls closure (`struct Plugin*`) * @param session the session * @return the network type */ static enum GNUNET_ATS_Network_Type http_client_get_network (void *cls, struct Session *session) { return ntohl (session->ats_address_network_type); } /** * Session was idle, so disconnect it * * @param cls the `struct Session` of the idle session * @param tc scheduler context */ static void client_session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *s = cls; s->timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (TIMEOUT_LOG, "Session %p was idle for %s, disconnecting\n", s, GNUNET_STRINGS_relative_time_to_string (HTTP_CLIENT_SESSION_TIMEOUT, GNUNET_YES)); /* call session destroy function */ GNUNET_assert (GNUNET_OK == http_client_session_disconnect (s->plugin, s)); } /** * Creates a new outbound session the transport service will use to * send data to the peer * * @param cls the plugin * @param address the address * @return the session or NULL of max connections exceeded */ static struct Session * http_client_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct HTTP_Client_Plugin *plugin = cls; struct Session * s = NULL; struct sockaddr *sa; struct GNUNET_ATS_Information ats; size_t salen = 0; int res; GNUNET_assert (address->address != NULL); /* find existing session */ s = client_lookup_session (plugin, address); if (s != NULL) return s; if (plugin->max_connections <= plugin->cur_connections) { GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name, "Maximum number of connections (%u) reached: " "cannot connect to peer `%s'\n", plugin->max_connections, GNUNET_i2s (&address->peer)); return NULL; } /* Determine network location */ ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.value = htonl (GNUNET_ATS_NET_UNSPECIFIED); sa = http_common_socket_from_address (address->address, address->address_length, &res); if (GNUNET_SYSERR == res) { return NULL; } else if (GNUNET_YES == res) { GNUNET_assert (NULL != sa); if (AF_INET == sa->sa_family) { salen = sizeof (struct sockaddr_in); } else if (AF_INET6 == sa->sa_family) { salen = sizeof (struct sockaddr_in6); } ats = plugin->env->get_address_type (plugin->env->cls, sa, salen); //fprintf (stderr, "Address %s is in %s\n", GNUNET_a2s (sa,salen), GNUNET_ATS_print_network_type(ntohl(ats.value))); GNUNET_free (sa); } else if (GNUNET_NO == res) { /* Cannot convert to sockaddr -> is external hostname */ ats.value = htonl (GNUNET_ATS_NET_WAN); } if (GNUNET_ATS_NET_UNSPECIFIED == ntohl (ats.value)) { GNUNET_break (0); return NULL; } s = GNUNET_new (struct Session); s->target = address->peer; s->plugin = plugin; s->address = GNUNET_HELLO_address_copy (address); s->ats_address_network_type = ats.value; s->put_paused = GNUNET_NO; s->put_tmp_disconnecting = GNUNET_NO; s->put_tmp_disconnected = GNUNET_NO; s->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_CLIENT_SESSION_TIMEOUT, &client_session_timeout, s); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Created new session %p for `%s' address `%s''\n", s, http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length), GNUNET_i2s (&s->target)); /* add new session */ GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); /* initiate new connection */ if (GNUNET_SYSERR == client_connect (s)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "Cannot connect to peer `%s' address `%s''\n", http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length), GNUNET_i2s (&s->target)); client_delete_session (s); return NULL; } return s; } /** * Setup http_client plugin * * @param plugin the plugin handle * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int client_start (struct HTTP_Client_Plugin *plugin) { curl_global_init (CURL_GLOBAL_ALL); plugin->curl_multi_handle = curl_multi_init (); if (NULL == plugin->curl_multi_handle) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _("Could not initialize curl multi handle, failed to start %s plugin!\n"), plugin->name); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Increment session timeout due to activity for session s * * param s the session */ static void client_reschedule_session_timeout (struct Session *s) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_CLIENT_SESSION_TIMEOUT, &client_session_timeout, s); GNUNET_log (TIMEOUT_LOG, "Timeout rescheduled for session %p set to %s\n", s, GNUNET_STRINGS_relative_time_to_string (HTTP_CLIENT_SESSION_TIMEOUT, GNUNET_YES)); } /** * Another peer has suggested an address for this * peer and transport plugin. Check that this could be a valid * address. If so, consider adding it to the list * of addresses. * * @param cls closure with the `struct Plugin` * @param addr pointer to the address * @param addrlen length of @a addr * @return #GNUNET_OK if this is a plausible address for this peer * and transport; always returns #GNUNET_NO (this is the client!) */ static int http_client_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) { /* struct Plugin *plugin = cls; */ /* A HTTP/S client does not have any valid address so:*/ return GNUNET_NO; } /** * Exit point from the plugin. * * @param cls api as closure * @return NULL */ void * LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct HTTP_Client_Plugin *plugin = api->cls; struct Session *pos; struct Session *next; if (NULL == api->cls) { /* Stub shutdown */ GNUNET_free (api); return NULL; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Shutting down plugin `%s'\n"), plugin->name); next = plugin->head; while (NULL != (pos = next)) { next = pos->next; http_client_session_disconnect (plugin, pos); } if (GNUNET_SCHEDULER_NO_TASK != plugin->client_perform_task) { GNUNET_SCHEDULER_cancel (plugin->client_perform_task); plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != plugin->curl_multi_handle) { curl_multi_cleanup (plugin->curl_multi_handle); plugin->curl_multi_handle = NULL; } curl_global_cleanup (); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Shutdown for plugin `%s' complete\n"), plugin->name); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /** * Configure plugin * * @param plugin the plugin handle * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static int client_configure_plugin (struct HTTP_Client_Plugin *plugin) { unsigned long long max_connections; /* Optional parameters */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name, "MAX_CONNECTIONS", &max_connections)) max_connections = 128; plugin->max_connections = max_connections; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Maximum number of connections is %u\n"), plugin->max_connections); return GNUNET_OK; } static const char * http_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) { return http_common_plugin_address_to_string (cls, PLUGIN_NAME, addr, addrlen); } static void http_client_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { struct HTTP_Client_Plugin *plugin = cls; /* lookup if session is really existing */ if (GNUNET_YES != client_exist_session (plugin, session)) { GNUNET_break (0); return; } client_reschedule_session_timeout (session); } /** * Entry point for the plugin. */ void * LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct HTTP_Client_Plugin *plugin; if (NULL == env->receive) { /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully initialze the plugin or the API */ api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = NULL; api->address_to_string = &http_plugin_address_to_string; api->string_to_address = &http_common_plugin_string_to_address; api->address_pretty_printer = &http_common_plugin_address_pretty_printer; return api; } plugin = GNUNET_new (struct HTTP_Client_Plugin); plugin->env = env; api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = plugin; api->send = &http_client_plugin_send; api->disconnect_session = &http_client_session_disconnect; api->query_keepalive_factor = &http_client_query_keepalive_factor; api->disconnect_peer = &http_client_peer_disconnect; api->check_address = &http_client_plugin_address_suggested; api->get_session = &http_client_plugin_get_session; api->address_to_string = &http_plugin_address_to_string; api->string_to_address = &http_common_plugin_string_to_address; api->address_pretty_printer = &http_common_plugin_address_pretty_printer; api->get_network = &http_client_get_network; api->update_session_timeout = &http_client_plugin_update_session_timeout; #if BUILD_HTTPS plugin->name = "transport-https_client"; plugin->protocol = "https"; #else plugin->name = "transport-http_client"; plugin->protocol = "http"; #endif plugin->last_tag = 1; plugin->options = 0; /* Setup options */ if (GNUNET_SYSERR == client_configure_plugin (plugin)) { LIBGNUNET_PLUGIN_TRANSPORT_DONE (api); return NULL; } /* Start client */ if (GNUNET_SYSERR == client_start (plugin)) { LIBGNUNET_PLUGIN_TRANSPORT_DONE (api); return NULL; } return api; } /* end of plugin_transport_http_client.c */ gnunet-0.10.1/src/transport/test_transport_api_https_peer1.conf0000644000175000017500000000116612225230043021743 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-https-p1/ [transport-https_client] PORT = 12100 KEY_FILE = $GNUNET_TEST_HOME/https_key_p1.key CERT_FILE = $GNUNET_TEST_HOME/https_cert_p1.crt [arm] PORT = 12105 [statistics] PORT = 12104 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12103 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12102 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12101 PLUGINS = https_client UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_reliability_https_peer1.conf0000644000175000017500000000110412225230043024324 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-https-p1/ [transport-https_client] [arm] PORT = 12305 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12304 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12303 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12302 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12301 PLUGINS = https_client UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_limited_sockets_tcp_peer1.conf0000644000175000017500000000115012225230043024622 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_quota_compliance_data.conf0000644000175000017500000000041012225230043021043 00000000000000@INLINE@ test_transport_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunetd-plugin-transport/ [transport-tcp] PORT = 2368 TIMEOUT = 5 s [arm] PORT = 2366 [statistics] PORT = 2367 [resolver] PORT = 2364 [peerinfo] PORT = 2369 [transport] PORT = 2365 gnunet-0.10.1/src/transport/test_transport_blacklisting_cfg_blp_peer1_plugin.conf0000644000175000017500000000142312236654562025466 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] #PREFIX = valgrind --leak-check=full PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PLUGINS = tcp [transport-blacklist-6ULBJK6QQJ64FAG9DF0292AS5IA9CCAC04IQU0HF8THM635HMBBG] DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50 = tcp gnunet-0.10.1/src/transport/test_transport_blacklisting_cfg_blp_peer2_full.conf0000644000175000017500000000141712236654562025136 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] #PREFIX = valgrind --leak-check=full PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-blacklist-DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50] 6ULBJK6QQJ64FAG9DF0292AS5IA9CCAC04IQU0HF8THM635HMBBG = gnunet-0.10.1/src/transport/plugin_transport_bluetooth.c0000644000175000017500000016076312316473377020532 00000000000000/* This file is part of GNUnet (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_bluetooth.c * @brief transport plugin for bluetooth * @author David Brodski * @author Christian Grothoff * * THIS IS A COPY OF plugin_transport_wlan.c */ #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "plugin_transport_wlan.h" #include "gnunet_common.h" #include "gnunet_crypto_lib.h" #include "gnunet_fragmentation_lib.h" #include "gnunet_constants.h" #ifdef MINGW #undef interface #endif #define LOG(kind,...) GNUNET_log_from (kind, "transport-bluetooth",__VA_ARGS__) #define PLUGIN_NAME "bluetooth" /** * Max size of packet (that we give to the WLAN driver for transmission) */ #define WLAN_MTU 1430 /** * time out of a mac endpoint */ #define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 60) /** * We reduce the frequence of HELLO beacons in relation to * the number of MAC addresses currently visible to us. * This is the multiplication factor. */ #define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * Maximum number of messages in defragmentation queue per MAC */ #define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 2 /** * Link layer control fields for better compatibility * (i.e. GNUnet over WLAN is not IP-over-WLAN). */ #define WLAN_LLC_DSAP_FIELD 0x1f #define WLAN_LLC_SSAP_FIELD 0x1f GNUNET_NETWORK_STRUCT_BEGIN /** * Header for messages which need fragmentation. This is the format of * a message we obtain AFTER defragmentation. We then need to check * the CRC and then tokenize the payload and pass it to the * 'receive' callback. */ struct WlanHeader { /** * Message type is GNUNET_MESSAGE_TYPE_WLAN_DATA. */ struct GNUNET_MessageHeader header; /** * CRC32 checksum (only over the payload), in NBO. */ uint32_t crc GNUNET_PACKED; /** * Sender of the message. */ struct GNUNET_PeerIdentity sender; /** * Target of the message. */ struct GNUNET_PeerIdentity target; /* followed by payload, possibly including multiple messages! */ }; struct WlanAddress { uint32_t options GNUNET_PACKED; struct GNUNET_TRANSPORT_WLAN_MacAddress mac; }; GNUNET_NETWORK_STRUCT_END /** * Information kept for each message that is yet to be fragmented and * transmitted. */ struct PendingMessage { /** * next entry in the DLL */ struct PendingMessage *next; /** * previous entry in the DLL */ struct PendingMessage *prev; /** * The pending message */ struct WlanHeader *msg; /** * Continuation function to call once the message * has been sent. Can be NULL if there is no * continuation to call. */ GNUNET_TRANSPORT_TransmitContinuation transmit_cont; /** * Cls for transmit_cont */ void *transmit_cont_cls; /** * Timeout task (for this message). */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; /** * Session handle for connections with other peers. */ struct Session { /** * To whom are we talking to (set to our identity * if we are still waiting for the welcome message) */ struct GNUNET_PeerIdentity target; /** * API requirement (must be first). */ struct SessionHeader header; /** * We keep all sessions in a DLL at their respective * 'struct MACEndpoint'. */ struct Session *next; /** * We keep all sessions in a DLL at their respective * 'struct MACEndpoint'. */ struct Session *prev; /** * MAC endpoint with the address of this peer. */ struct MacEndpoint *mac; /** * The address for this session */ struct GNUNET_HELLO_Address *address; /** * Head of messages currently pending for transmission to this peer. */ struct PendingMessage *pending_message_head; /** * Tail of messages currently pending for transmission to this peer. */ struct PendingMessage *pending_message_tail; /** * When should this session time out? */ struct GNUNET_TIME_Absolute timeout; /** * Timeout task (for the session). */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; /** * Struct for messages that are being fragmented in a MAC's transmission queue. */ struct FragmentMessage { /** * This is a doubly-linked list. */ struct FragmentMessage *next; /** * This is a doubly-linked list. */ struct FragmentMessage *prev; /** * MAC endpoint this message belongs to */ struct MacEndpoint *macendpoint; /** * Fragmentation context */ struct GNUNET_FRAGMENT_Context *fragcontext; /** * Transmission handle to helper (to cancel if the frag context * is destroyed early for some reason). */ struct GNUNET_HELPER_SendHandle *sh; /** * Intended recipient. */ struct GNUNET_PeerIdentity target; /** * Timeout value for the message. */ struct GNUNET_TIME_Absolute timeout; /** * Timeout task. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Continuation to call when we're done with this message. */ GNUNET_TRANSPORT_TransmitContinuation cont; /** * Closure for 'cont' */ void *cont_cls; /** * Size of original message */ size_t size_payload; /** * Number of bytes used to transmit message */ size_t size_on_wire; }; /** * Struct to represent one network card connection */ struct MacEndpoint { /** * We keep all MACs in a DLL in the plugin. */ struct MacEndpoint *next; /** * We keep all MACs in a DLL in the plugin. */ struct MacEndpoint *prev; /** * Pointer to the global plugin struct. */ struct Plugin *plugin; /** * Head of sessions that use this MAC. */ struct Session *sessions_head; /** * Tail of sessions that use this MAC. */ struct Session *sessions_tail; /** * Head of messages we are currently sending to this MAC. */ struct FragmentMessage *sending_messages_head; /** * Tail of messages we are currently sending to this MAC. */ struct FragmentMessage *sending_messages_tail; /** * Defrag context for this MAC */ struct GNUNET_DEFRAGMENT_Context *defrag; /** * When should this endpoint time out? */ struct GNUNET_TIME_Absolute timeout; /** * Timeout task. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * count of messages in the fragment out queue for this mac endpoint */ unsigned int fragment_messages_out_count; /** * peer mac address */ struct WlanAddress addr; /** * Message delay for fragmentation context */ struct GNUNET_TIME_Relative msg_delay; /** * ACK delay for fragmentation context */ struct GNUNET_TIME_Relative ack_delay; /** * Desired transmission power for this MAC */ uint16_t tx_power; /** * Desired transmission rate for this MAC */ uint8_t rate; /** * Antenna we should use for this MAC */ uint8_t antenna; }; /** * Encapsulation of all of the state of the plugin. */ struct Plugin { /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * Handle to helper process for priviledged operations. */ struct GNUNET_HELPER_Handle *suid_helper; /** * ARGV-vector for the helper (all helpers take only the binary * name, one actual argument, plus the NULL terminator for 'argv'). */ char * helper_argv[3]; /** * The interface of the wlan card given to us by the user. */ char *interface; /** * Tokenizer for demultiplexing of data packets resulting from defragmentation. */ struct GNUNET_SERVER_MessageStreamTokenizer *fragment_data_tokenizer; /** * Tokenizer for demultiplexing of data packets received from the suid helper */ struct GNUNET_SERVER_MessageStreamTokenizer *helper_payload_tokenizer; /** * Tokenizer for demultiplexing of data packets that follow the WLAN Header */ struct GNUNET_SERVER_MessageStreamTokenizer *wlan_header_payload_tokenizer; /** * Head of list of open connections. */ struct MacEndpoint *mac_head; /** * Tail of list of open connections. */ struct MacEndpoint *mac_tail; /** * Number of connections */ unsigned int mac_count; /** * Task that periodically sends a HELLO beacon via the helper. */ GNUNET_SCHEDULER_TaskIdentifier beacon_task; /** * Tracker for bandwidth limit */ struct GNUNET_BANDWIDTH_Tracker tracker; /** * The mac_address of the wlan card given to us by the helper. */ struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address; /** * Have we received a control message with our MAC address yet? */ int have_mac; /** * Options for addresses */ uint32_t options; }; /** * Information associated with a message. Can contain * the session or the MAC endpoint associated with the * message (or both). */ struct MacAndSession { /** * NULL if the identity of the other peer is not known. */ struct Session *session; /** * MAC address of the other peer, NULL if not known. */ struct MacEndpoint *endpoint; }; /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ static const char * bluetooth_plugin_address_to_string (void *cls, const void *addr, size_t addrlen); /** * Print MAC addresses nicely. * * @param mac the mac address * @return string to a static buffer with the human-readable mac, will be overwritten during the next call to this function */ static const char * mac_to_string (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac) { static char macstr[20]; GNUNET_snprintf (macstr, sizeof (macstr), "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", mac->mac[0], mac->mac[1], mac->mac[2], mac->mac[3], mac->mac[4], mac->mac[5]); return macstr; } /** * Fill the radiotap header * * @param endpoint pointer to the endpoint, can be NULL * @param header pointer to the radiotap header * @param size total message size */ static void get_radiotap_header (struct MacEndpoint *endpoint, struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header, uint16_t size) { header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER); header->header.size = ntohs (size); if (NULL != endpoint) { header->rate = endpoint->rate; header->tx_power = endpoint->tx_power; header->antenna = endpoint->antenna; } else { header->rate = 255; header->tx_power = 0; header->antenna = 0; } } /** * Generate the WLAN hardware header for one packet * * @param plugin the plugin handle * @param header address to write the header to * @param to_mac_addr address of the recipient * @param size size of the whole packet, needed to calculate the time to send the packet */ static void get_wlan_header (struct Plugin *plugin, struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *header, const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr, unsigned int size) { const int rate = 11000000; header->frame_control = htons (IEEE80211_FC0_TYPE_DATA); header->addr1 = *to_mac_addr; header->addr2 = plugin->mac_address; header->addr3 = mac_bssid_gnunet; header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290); header->sequence_control = 0; // FIXME? header->llc[0] = WLAN_LLC_DSAP_FIELD; header->llc[1] = WLAN_LLC_SSAP_FIELD; header->llc[2] = 0; // FIXME? header->llc[3] = 0; // FIXME? } /** * Send an ACK for a fragment we received. * * @param cls the 'struct MacEndpoint' the ACK must be sent to * @param msg_id id of the message * @param hdr pointer to the hdr where the ack is stored */ static void send_ack (void *cls, uint32_t msg_id, const struct GNUNET_MessageHeader *hdr) { struct MacEndpoint *endpoint = cls; struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage* radio_header; uint16_t msize = ntohs (hdr->size); size_t size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize; char buf[size]; if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK to helper\n"); radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf; get_radiotap_header (endpoint, radio_header, size); get_wlan_header (endpoint->plugin, &radio_header->frame, &endpoint->addr.mac, sizeof (endpoint->addr.mac)); memcpy (&radio_header[1], hdr, msize); if (NULL != GNUNET_HELPER_send (endpoint->plugin->suid_helper, &radio_header->header, GNUNET_NO /* dropping ACKs is bad */, NULL, NULL)) GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# Bluetooth ACKs sent"), 1, GNUNET_NO); } /** * Handles the data after all fragments are put together * * @param cls macendpoint this messages belongs to * @param hdr pointer to the data */ static void bluetooth_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr) { struct MacEndpoint *endpoint = cls; struct Plugin *plugin = endpoint->plugin; struct MacAndSession mas; GNUNET_STATISTICS_update (plugin->env->stats, _("# Bluetooth messages defragmented"), 1, GNUNET_NO); mas.session = NULL; mas.endpoint = endpoint; (void) GNUNET_SERVER_mst_receive (plugin->fragment_data_tokenizer, &mas, (const char *) hdr, ntohs (hdr->size), GNUNET_YES, GNUNET_NO); } /** * Free a session * * @param session the session free */ static void free_session (struct Session *session) { struct MacEndpoint *endpoint = session->mac; struct PendingMessage *pm; endpoint->plugin->env->session_end (endpoint->plugin->env->cls, session->address, session); while (NULL != (pm = session->pending_message_head)) { GNUNET_CONTAINER_DLL_remove (session->pending_message_head, session->pending_message_tail, pm); if (GNUNET_SCHEDULER_NO_TASK != pm->timeout_task) { GNUNET_SCHEDULER_cancel (pm->timeout_task); pm->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (pm->msg); GNUNET_free (pm); } GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, endpoint->sessions_tail, session); if (session->timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (session->timeout_task); session->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# Bluetooth sessions allocated"), -1, GNUNET_NO); GNUNET_HELLO_address_free (session->address); GNUNET_free (session); } /** * A session is timing out. Clean up. * * @param cls pointer to the Session * @param tc pointer to the GNUNET_SCHEDULER_TaskContext */ static void session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session * session = cls; struct GNUNET_TIME_Relative timeout; session->timeout_task = GNUNET_SCHEDULER_NO_TASK; timeout = GNUNET_TIME_absolute_get_remaining (session->timeout); if (0 == timeout.rel_value_us) { free_session (session); return; } session->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &session_timeout, session); } /** * Create a new session * * @param endpoint pointer to the mac endpoint of the peer * @param peer peer identity to use for this session * @return returns the session */ static struct Session * create_session (struct MacEndpoint *endpoint, const struct GNUNET_PeerIdentity *peer) { struct Session *session; for (session = endpoint->sessions_head; NULL != session; session = session->next) if (0 == memcmp (peer, &session->target, sizeof (struct GNUNET_PeerIdentity))) { session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); return session; } GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# Bluetooth sessions allocated"), 1, GNUNET_NO); session = GNUNET_new (struct Session); GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head, endpoint->sessions_tail, session); session->address = GNUNET_HELLO_address_allocate (peer, PLUGIN_NAME, &endpoint->addr, sizeof (endpoint->addr), GNUNET_HELLO_ADDRESS_INFO_NONE); session->mac = endpoint; session->target = *peer; session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); session->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session); LOG (GNUNET_ERROR_TYPE_DEBUG, "Created new session for peer `%s' with endpoint %s\n", GNUNET_i2s (peer), mac_to_string (&endpoint->addr.mac)); return session; } /** * Lookup a new session * * @param endpoint pointer to the mac endpoint of the peer * @param peer peer identity to use for this session * @return returns the session or NULL */ static struct Session * lookup_session (struct MacEndpoint *endpoint, const struct GNUNET_PeerIdentity *peer) { struct Session *session; for (session = endpoint->sessions_head; NULL != session; session = session->next) if (0 == memcmp (peer, &session->target, sizeof (struct GNUNET_PeerIdentity))) { session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); return session; } return NULL; } /** * Function called once we have successfully given the fragment * message to the SUID helper process and we are thus ready for * the next fragment. * * @param cls the 'struct FragmentMessage' * @param result result of the operation (GNUNET_OK on success, GNUNET_NO if the helper died, GNUNET_SYSERR * if the helper was stopped) */ static void fragment_transmission_done (void *cls, int result) { struct FragmentMessage *fm = cls; fm->sh = NULL; GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext); } /** * Transmit a fragment of a message. * * @param cls 'struct FragmentMessage' this fragment message belongs to * @param hdr pointer to the start of the fragment message */ static void transmit_fragment (void *cls, const struct GNUNET_MessageHeader *hdr) { struct FragmentMessage *fm = cls; struct MacEndpoint *endpoint = fm->macendpoint; size_t size; uint16_t msize; msize = ntohs (hdr->size); size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize; { char buf[size]; struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radio_header; radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf; get_radiotap_header (endpoint, radio_header, size); get_wlan_header (endpoint->plugin, &radio_header->frame, &endpoint->addr.mac, sizeof (endpoint->addr.mac)); memcpy (&radio_header[1], hdr, msize); GNUNET_assert (NULL == fm->sh); fm->sh = GNUNET_HELPER_send (endpoint->plugin->suid_helper, &radio_header->header, GNUNET_NO, &fragment_transmission_done, fm); fm->size_on_wire += size; if (NULL != fm->sh) GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# Bluetooth message fragments sent"), 1, GNUNET_NO); else GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext); GNUNET_STATISTICS_update (endpoint->plugin->env->stats, "# bytes currently in Bluetooth buffers", -msize, GNUNET_NO); GNUNET_STATISTICS_update (endpoint->plugin->env->stats, "# bytes transmitted via Bluetooth", msize, GNUNET_NO); } } /** * Frees the space of a message in the fragment queue (send queue) * * @param fm message to free */ static void free_fragment_message (struct FragmentMessage *fm) { struct MacEndpoint *endpoint = fm->macendpoint; GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# Bluetooth messages pending (with fragmentation)"), -1, GNUNET_NO); GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head, endpoint->sending_messages_tail, fm); if (NULL != fm->sh) { GNUNET_HELPER_send_cancel (fm->sh); fm->sh = NULL; } GNUNET_FRAGMENT_context_destroy (fm->fragcontext, &endpoint->msg_delay, &endpoint->ack_delay); if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (fm->timeout_task); fm->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (fm); } /** * A FragmentMessage has timed out. Remove it. * * @param cls pointer to the 'struct FragmentMessage' * @param tc pointer to the GNUNET_SCHEDULER_TaskContext */ static void fragmentmessage_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct FragmentMessage *fm = cls; fm->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != fm->cont) { fm->cont (fm->cont_cls, &fm->target, GNUNET_SYSERR, fm->size_payload, fm->size_on_wire); fm->cont = NULL; } free_fragment_message (fm); } /** * Transmit a message to the given destination with fragmentation. * * @param endpoint desired destination * @param timeout how long can the message wait? * @param target peer that should receive the message * @param msg message to transmit * @param payload_size bytes of payload * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for cont */ static void send_with_fragmentation (struct MacEndpoint *endpoint, struct GNUNET_TIME_Relative timeout, const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, size_t payload_size, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct FragmentMessage *fm; struct Plugin *plugin; plugin = endpoint->plugin; fm = GNUNET_new (struct FragmentMessage); fm->macendpoint = endpoint; fm->target = *target; fm->size_payload = payload_size; fm->size_on_wire = 0; fm->timeout = GNUNET_TIME_relative_to_absolute (timeout); fm->cont = cont; fm->cont_cls = cont_cls; /* 1 MBit/s typical data rate, 1430 byte fragments => ~100 ms per message */ fm->fragcontext = GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU, &plugin->tracker, endpoint->msg_delay, endpoint->ack_delay, msg, &transmit_fragment, fm); fm->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &fragmentmessage_timeout, fm); GNUNET_CONTAINER_DLL_insert_tail (endpoint->sending_messages_head, endpoint->sending_messages_tail, fm); } /** * Free a MAC endpoint. * * @param endpoint pointer to the MacEndpoint to free */ static void free_macendpoint (struct MacEndpoint *endpoint) { struct Plugin *plugin = endpoint->plugin; struct FragmentMessage *fm; struct Session *session; GNUNET_STATISTICS_update (plugin->env->stats, _("# Bluetooth MAC endpoints allocated"), -1, GNUNET_NO); while (NULL != (session = endpoint->sessions_head)) free_session (session); while (NULL != (fm = endpoint->sending_messages_head)) free_fragment_message (fm); GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint); if (NULL != endpoint->defrag) { GNUNET_DEFRAGMENT_context_destroy(endpoint->defrag); endpoint->defrag = NULL; } plugin->mac_count--; if (GNUNET_SCHEDULER_NO_TASK != endpoint->timeout_task) { GNUNET_SCHEDULER_cancel (endpoint->timeout_task); endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (endpoint); } /** * A MAC endpoint is timing out. Clean up. * * @param cls pointer to the MacEndpoint * @param tc pointer to the GNUNET_SCHEDULER_TaskContext */ static void macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct MacEndpoint *endpoint = cls; struct GNUNET_TIME_Relative timeout; endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK; timeout = GNUNET_TIME_absolute_get_remaining (endpoint->timeout); if (0 == timeout.rel_value_us) { free_macendpoint (endpoint); return; } endpoint->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &macendpoint_timeout, endpoint); } /** * Find (or create) a MacEndpoint with a specific MAC address * * @param plugin pointer to the plugin struct * @param addr the MAC address of the endpoint * @return handle to our data structure for this MAC */ static struct MacEndpoint * create_macendpoint (struct Plugin *plugin, struct WlanAddress *addr) { struct MacEndpoint *pos; for (pos = plugin->mac_head; NULL != pos; pos = pos->next) if (0 == memcmp (addr, &pos->addr, sizeof (struct WlanAddress))) return pos; pos = GNUNET_new (struct MacEndpoint); pos->addr = (*addr); pos->plugin = plugin; pos->defrag = GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU, MESSAGES_IN_DEFRAG_QUEUE_PER_MAC, pos, &bluetooth_data_message_handler, &send_ack); pos->msg_delay = GNUNET_TIME_UNIT_MILLISECONDS; pos->ack_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); pos->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT); pos->timeout_task = GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout, pos); GNUNET_CONTAINER_DLL_insert (plugin->mac_head, plugin->mac_tail, pos); plugin->mac_count++; GNUNET_STATISTICS_update (plugin->env->stats, _("# Bluetooth MAC endpoints allocated"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "New MAC endpoint `%s'\n", bluetooth_plugin_address_to_string(NULL, addr, sizeof (struct WlanAddress))); return pos; } /** * Function obtain the network type for a session * * @param cls closure ('struct Plugin*') * @param session the session * @return the network type in HBO or GNUNET_SYSERR */ static enum GNUNET_ATS_Network_Type bluetooth_get_network (void *cls, struct Session *session) { GNUNET_assert (NULL != session); return GNUNET_ATS_NET_BT; } /** * Look up a session for a peer and create a new session if none is found * * @param endpoint pointer to the mac endpoint of the peer * @param peer peer identity to use for this session * @return returns the session */ static struct Session * get_session (struct MacEndpoint *endpoint, const struct GNUNET_PeerIdentity *peer) { struct Session *session; if (NULL != (session = lookup_session (endpoint, peer))) return session; return create_session (endpoint, peer); } /** * Creates a new outbound session the transport service will use to send data to the * peer * * @param cls the plugin * @param address the address * @return the session or NULL of max connections exceeded */ static struct Session * bluetooth_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct Plugin *plugin = cls; struct MacEndpoint *endpoint; if (NULL == address) return NULL; if (sizeof (struct WlanAddress) != address->address_length) { GNUNET_break (0); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Service asked to create session for peer `%s' with MAC `%s'\n", GNUNET_i2s (&address->peer), bluetooth_plugin_address_to_string(NULL, address->address, address->address_length)); endpoint = create_macendpoint (plugin, (struct WlanAddress *) address->address); return get_session (endpoint, &address->peer); } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuation). * * @param cls closure * @param target peer from which to disconnect */ static void bluetooth_plugin_disconnect_peer (void *cls, const struct GNUNET_PeerIdentity *target) { struct Plugin *plugin = cls; struct Session *session; struct MacEndpoint *endpoint; for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = endpoint->next) for (session = endpoint->sessions_head; NULL != session; session = session->next) if (0 == memcmp (target, &session->target, sizeof (struct GNUNET_PeerIdentity))) { free_session (session); break; /* inner-loop only (in case peer has another MAC as well!) */ } } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuation). * * @param cls closure * @param session session to disconnect */ static int bluetooth_plugin_disconnect_session (void *cls, struct Session *session) { free_session (session); return GNUNET_OK; } /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int bluetooth_query_keepalive_factor (void *cls) { return 3; } /** * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param session which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in 'msgbuf' * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t bluetooth_plugin_send (void *cls, struct Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin *plugin = cls; struct WlanHeader *wlanheader; size_t size = msgbuf_size + sizeof (struct WlanHeader); char buf[size] GNUNET_ALIGN; LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes of payload to peer `%s' (starting with %u byte message of type %u)\n", msgbuf_size, GNUNET_i2s (&session->target), (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->size), (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->type)); wlanheader = (struct WlanHeader *) buf; wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader)); wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA); wlanheader->sender = *plugin->env->my_identity; wlanheader->target = session->target; wlanheader->crc = htonl (GNUNET_CRYPTO_crc32_n (msgbuf, msgbuf_size)); memcpy (&wlanheader[1], msgbuf, msgbuf_size); GNUNET_STATISTICS_update (plugin->env->stats, "# bytes currently in Bluetooth buffers", msgbuf_size, GNUNET_NO); send_with_fragmentation (session->mac, to, &session->target, &wlanheader->header, msgbuf_size, cont, cont_cls); return size; } /** * We have received data from the WLAN via some session. Process depending * on the message type (HELLO, DATA, FRAGMENTATION or FRAGMENTATION-ACK). * * @param cls pointer to the plugin * @param client pointer to the session this message belongs to * @param hdr start of the message */ static int process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr) { struct Plugin *plugin = cls; struct GNUNET_HELLO_Address *address; struct MacAndSession *mas = client; struct MacAndSession xmas; struct GNUNET_ATS_Information ats; struct FragmentMessage *fm; struct GNUNET_PeerIdentity tmpsource; const struct WlanHeader *wlanheader; int ret; uint16_t msize; ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.value = htonl (GNUNET_ATS_NET_BT); msize = ntohs (hdr->size); GNUNET_STATISTICS_update (plugin->env->stats, "# bytes received via Bluetooth", msize, GNUNET_NO); switch (ntohs (hdr->type)) { case GNUNET_MESSAGE_TYPE_HELLO: if (GNUNET_OK != GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource)) { GNUNET_break_op (0); break; } if (NULL == mas->endpoint) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing %u bytes of HELLO from peer `%s' at MAC %s\n", (unsigned int) msize, GNUNET_i2s (&tmpsource), bluetooth_plugin_address_to_string (NULL, &mas->endpoint->addr, sizeof (mas->endpoint->addr))); GNUNET_STATISTICS_update (plugin->env->stats, _("# HELLO messages received via Bluetooth"), 1, GNUNET_NO); address = GNUNET_HELLO_address_allocate (&tmpsource, PLUGIN_NAME, &mas->endpoint->addr, sizeof (mas->endpoint->addr), GNUNET_HELLO_ADDRESS_INFO_INBOUND); plugin->env->receive (plugin->env->cls, address, mas->session, hdr); plugin->env->update_address_metrics (plugin->env->cls, address, mas->session, &ats, 1); GNUNET_HELLO_address_free (address); break; case GNUNET_MESSAGE_TYPE_FRAGMENT: if (NULL == mas->endpoint) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing %u bytes of FRAGMENT from MAC %s\n", (unsigned int) msize, bluetooth_plugin_address_to_string (NULL, &mas->endpoint->addr, sizeof (mas->endpoint->addr))); GNUNET_STATISTICS_update (plugin->env->stats, _("# fragments received via Bluetooth"), 1, GNUNET_NO); (void) GNUNET_DEFRAGMENT_process_fragment (mas->endpoint->defrag, hdr); break; case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK: if (NULL == mas->endpoint) { GNUNET_break (0); break; } GNUNET_STATISTICS_update (plugin->env->stats, _("# ACKs received via Bluetooth"), 1, GNUNET_NO); for (fm = mas->endpoint->sending_messages_head; NULL != fm; fm = fm->next) { ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr); if (GNUNET_OK == ret) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Got last ACK, finished message transmission to `%s' (%p)\n", bluetooth_plugin_address_to_string (NULL, &mas->endpoint->addr, sizeof (mas->endpoint->addr)), fm); mas->endpoint->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT); if (NULL != fm->cont) { fm->cont (fm->cont_cls, &fm->target, GNUNET_OK, fm->size_payload, fm->size_on_wire); fm->cont = NULL; } free_fragment_message (fm); break; } if (GNUNET_NO == ret) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK, message transmission to `%s' not yet finished\n", bluetooth_plugin_address_to_string (NULL, &mas->endpoint->addr, sizeof (mas->endpoint->addr))); break; } } LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK not matched against any active fragmentation with MAC `%s'\n", bluetooth_plugin_address_to_string (NULL, &mas->endpoint->addr, sizeof (mas->endpoint->addr))); break; case GNUNET_MESSAGE_TYPE_WLAN_DATA: if (NULL == mas->endpoint) { GNUNET_break (0); break; } if (msize < sizeof (struct WlanHeader)) { GNUNET_break (0); break; } wlanheader = (const struct WlanHeader *) hdr; if (0 != memcmp (&wlanheader->target, plugin->env->my_identity, sizeof (struct GNUNET_PeerIdentity))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Bluetooth data for `%s', not for me, ignoring\n", GNUNET_i2s (&wlanheader->target)); break; } if (ntohl (wlanheader->crc) != GNUNET_CRYPTO_crc32_n (&wlanheader[1], msize - sizeof (struct WlanHeader))) { GNUNET_STATISTICS_update (plugin->env->stats, _("# Bluetooth DATA messages discarded due to CRC32 error"), 1, GNUNET_NO); break; } xmas.endpoint = mas->endpoint; xmas.session = create_session (mas->endpoint, &wlanheader->sender); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing %u bytes of BLUETOOTH DATA from peer `%s'\n", (unsigned int) msize, GNUNET_i2s (&wlanheader->sender)); (void) GNUNET_SERVER_mst_receive (plugin->wlan_header_payload_tokenizer, &xmas, (const char *) &wlanheader[1], msize - sizeof (struct WlanHeader), GNUNET_YES, GNUNET_NO); break; default: if (NULL == mas->endpoint) { GNUNET_break (0); break; } if (NULL == mas->session) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received packet with %u bytes of type %u from peer %s\n", (unsigned int) msize, (unsigned int) ntohs (hdr->type), GNUNET_i2s (&mas->session->target)); plugin->env->receive (plugin->env->cls, mas->session->address, mas->session, hdr); plugin->env->update_address_metrics (plugin->env->cls, mas->session->address, mas->session, &ats, 1); break; } return GNUNET_OK; } /** * Function used for to process the data from the suid process * * @param cls the plugin handle * @param client client that send the data (not used) * @param hdr header of the GNUNET_MessageHeader */ static int handle_helper_message (void *cls, void *client, const struct GNUNET_MessageHeader *hdr) { struct Plugin *plugin = cls; struct GNUNET_HELLO_Address *address; const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo; const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm; struct WlanAddress wa; struct MacAndSession mas; uint16_t msize; msize = ntohs (hdr->size); switch (ntohs (hdr->type)) { case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL: if (msize != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage)) { GNUNET_break (0); break; } cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr; if (GNUNET_YES == plugin->have_mac) { if (0 == memcmp (&plugin->mac_address, &cm->mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) break; /* no change */ /* remove old address */ memset (&wa, 0, sizeof (struct WlanAddress)); wa.mac = plugin->mac_address; wa.options = htonl(plugin->options); address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, &wa, sizeof (wa), GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->notify_address (plugin->env->cls, GNUNET_NO, address); GNUNET_HELLO_address_free (address); } plugin->mac_address = cm->mac; plugin->have_mac = GNUNET_YES; memset (&wa, 0, sizeof (struct WlanAddress)); wa.mac = plugin->mac_address; wa.options = htonl(plugin->options); address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, &wa, sizeof (wa), GNUNET_HELLO_ADDRESS_INFO_NONE); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received BT_HELPER_CONTROL message with MAC address `%s' for peer `%s'\n", mac_to_string (&cm->mac), GNUNET_i2s (plugin->env->my_identity)); plugin->env->notify_address (plugin->env->cls, GNUNET_YES, address); GNUNET_HELLO_address_free (address); break; case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER: LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data message from helper with %u bytes\n", msize); GNUNET_STATISTICS_update (plugin->env->stats, _("# DATA messages received via Bluetooth"), 1, GNUNET_NO); if (msize < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Size of packet is too small (%u bytes)\n", msize); break; } rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr; /* check if message is actually for us */ if (0 != memcmp (&rxinfo->frame.addr3, &mac_bssid_gnunet, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) { /* Not the GNUnet BSSID */ break; } if ( (0 != memcmp (&rxinfo->frame.addr1, &bc_all_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) && (0 != memcmp (&rxinfo->frame.addr1, &plugin->mac_address, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) ) { /* Neither broadcast nor specifically for us */ break; } if (0 == memcmp (&rxinfo->frame.addr2, &plugin->mac_address, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) { /* packet is FROM us, thus not FOR us */ break; } GNUNET_STATISTICS_update (plugin->env->stats, _("# Bluetooth DATA messages processed"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving %u bytes of data from MAC `%s'\n", (unsigned int) (msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)), mac_to_string (&rxinfo->frame.addr2)); wa.mac = rxinfo->frame.addr2; wa.options = htonl (0); mas.endpoint = create_macendpoint (plugin, &wa); mas.session = NULL; (void) GNUNET_SERVER_mst_receive (plugin->helper_payload_tokenizer, &mas, (const char*) &rxinfo[1], msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage), GNUNET_YES, GNUNET_NO); break; default: GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Unexpected message of type %u (%u bytes)", ntohs (hdr->type), ntohs (hdr->size)); break; } return GNUNET_OK; } /** * Task to (periodically) send a HELLO beacon * * @param cls pointer to the plugin struct * @param tc scheduler context */ static void send_hello_beacon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Plugin *plugin = cls; uint16_t size; uint16_t hello_size; struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader; const struct GNUNET_MessageHeader *hello; hello = plugin->env->get_our_hello (); hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello); GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU); size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + hello_size; { char buf[size] GNUNET_ALIGN; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending %u byte HELLO beacon\n", (unsigned int) size); radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) buf; get_radiotap_header (NULL, radioHeader, size); get_wlan_header (plugin, &radioHeader->frame, &bc_all_mac, size); memcpy (&radioHeader[1], hello, hello_size); if (NULL != GNUNET_HELPER_send (plugin->suid_helper, &radioHeader->header, GNUNET_YES /* can drop */, NULL, NULL)) GNUNET_STATISTICS_update (plugin->env->stats, _("# HELLO beacons sent via Bluetooth"), 1, GNUNET_NO); } plugin->beacon_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (HELLO_BEACON_SCALING_FACTOR, plugin->mac_count + 1), &send_hello_beacon, plugin); } /** * Another peer has suggested an address for this * peer and transport plugin. Check that this could be a valid * address. If so, consider adding it to the list * of addresses. * * @param cls closure * @param addr pointer to the address * @param addrlen length of addr * @return GNUNET_OK if this is a plausible address for this peer * and transport */ static int bluetooth_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) { struct Plugin *plugin = cls; struct WlanAddress *wa = (struct WlanAddress *) addr; if (addrlen != sizeof (struct WlanAddress)) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_YES != plugin->have_mac) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Rejecting MAC `%s': I don't know my MAC!\n", mac_to_string (addr)); return GNUNET_NO; /* don't know my MAC */ } if (0 != memcmp (&wa->mac, &plugin->mac_address, sizeof (wa->mac))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Rejecting MAC `%s': not my MAC!\n", mac_to_string (addr)); return GNUNET_NO; /* not my MAC */ } return GNUNET_OK; } /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ static const char * bluetooth_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) { const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac; static char macstr[36]; if (sizeof (struct WlanAddress) != addrlen) { GNUNET_break (0); return NULL; } mac = &((struct WlanAddress *) addr)->mac; GNUNET_snprintf (macstr, sizeof (macstr), "%s.%u.%s", PLUGIN_NAME, ntohl (((struct WlanAddress *) addr)->options), mac_to_string (mac)); return macstr; } /** * Convert the transports address to a nice, human-readable format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the address * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for asc */ static void bluetooth_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { char *ret; if (sizeof (struct WlanAddress) != addrlen) { /* invalid address */ LOG (GNUNET_ERROR_TYPE_WARNING, _("Bluetooth address with invalid size encountered\n")); asc (asc_cls, NULL); return; } ret = GNUNET_strdup (bluetooth_plugin_address_to_string(NULL, addr, addrlen)); asc (asc_cls, ret); GNUNET_free (ret); asc (asc_cls, NULL); } /** * Exit point from the plugin. * * @param cls pointer to the api struct */ void * libgnunet_plugin_transport_bluetooth_done (void *cls) { struct WlanAddress wa; struct GNUNET_HELLO_Address *address; struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; struct MacEndpoint *endpoint; struct MacEndpoint *endpoint_next; if (NULL == plugin) { GNUNET_free (api); return NULL; } if (GNUNET_YES == plugin->have_mac) { memset (&wa, 0, sizeof(wa)); wa.options = htonl (plugin->options); wa.mac = plugin->mac_address; address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, &wa, sizeof (struct WlanAddress), GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->notify_address (plugin->env->cls, GNUNET_NO, address); plugin->have_mac = GNUNET_NO; GNUNET_HELLO_address_free (address); } if (GNUNET_SCHEDULER_NO_TASK != plugin->beacon_task) { GNUNET_SCHEDULER_cancel (plugin->beacon_task); plugin->beacon_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != plugin->suid_helper) { GNUNET_HELPER_stop (plugin->suid_helper, GNUNET_NO); plugin->suid_helper = NULL; } endpoint_next = plugin->mac_head; while (NULL != (endpoint = endpoint_next)) { endpoint_next = endpoint->next; free_macendpoint (endpoint); } if (NULL != plugin->fragment_data_tokenizer) { GNUNET_SERVER_mst_destroy (plugin->fragment_data_tokenizer); plugin->fragment_data_tokenizer = NULL; } if (NULL != plugin->wlan_header_payload_tokenizer) { GNUNET_SERVER_mst_destroy (plugin->wlan_header_payload_tokenizer); plugin->wlan_header_payload_tokenizer = NULL; } if (NULL != plugin->helper_payload_tokenizer) { GNUNET_SERVER_mst_destroy (plugin->helper_payload_tokenizer); plugin->helper_payload_tokenizer = NULL; } GNUNET_free_non_null (plugin->interface); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /** * Function called to convert a string address to * a binary address. * * @param cls closure ('struct Plugin*') * @param addr string address * @param addrlen length of the address * @param buf location to store the buffer * @param added location to store the number of bytes in the buffer. * If the function returns GNUNET_SYSERR, its contents are undefined. * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ static int bluetooth_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added) { struct WlanAddress *wa; unsigned int a[6]; unsigned int i; char plugin[10]; uint32_t options; if ((NULL == addr) || (addrlen == 0)) { GNUNET_break (0); return GNUNET_SYSERR; } if ('\0' != addr[addrlen - 1]) { GNUNET_break (0); return GNUNET_SYSERR; } if (strlen (addr) != addrlen - 1) { GNUNET_break (0); return GNUNET_SYSERR; } if (8 != SSCANF (addr, "%9s.%u.%X:%X:%X:%X:%X:%X", plugin, &options, &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])) { GNUNET_break (0); return GNUNET_SYSERR; } wa = GNUNET_new (struct WlanAddress); for (i=0;i<6;i++) wa->mac.mac[i] = a[i]; wa->options = htonl (0); *buf = wa; *added = sizeof (struct WlanAddress); return GNUNET_OK; } static void bluetooth_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { if (GNUNET_SCHEDULER_NO_TASK != session->timeout_task) GNUNET_SCHEDULER_cancel (session->timeout_task); session->timeout_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session); } /** * Entry point for the plugin. * * @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*' * @return the 'struct GNUNET_TRANSPORT_PluginFunctions*' or NULL on error */ void * libgnunet_plugin_transport_bluetooth_init (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *plugin; char *interface; unsigned long long testmode; char *binary; /* check for 'special' mode */ if (NULL == env->receive) { /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully initialze the plugin or the API */ api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = NULL; api->address_pretty_printer = &bluetooth_plugin_address_pretty_printer; api->address_to_string = &bluetooth_plugin_address_to_string; api->string_to_address = &bluetooth_string_to_address; return api; } testmode = 0; /* check configuration */ if ( (GNUNET_YES == GNUNET_CONFIGURATION_have_value (env->cfg, "transport-bluetooth", "TESTMODE")) && ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-bluetooth", "TESTMODE", &testmode)) || (testmode > 2) ) ) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "transport-bluetooth", "TESTMODE"); return NULL; } binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-transport-bluetooth"); if ( (0 == testmode) && (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, NULL)) ) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Helper binary `%s' not SUID, cannot run bluetooth transport\n"), "gnunet-helper-transport-bluetooth"); GNUNET_free (binary); return NULL; } GNUNET_free (binary); if (GNUNET_YES != GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-bluetooth", "INTERFACE", &interface)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "transport-bluetooth", "INTERFACE"); return NULL; } plugin = GNUNET_new (struct Plugin); plugin->interface = interface; plugin->env = env; GNUNET_STATISTICS_set (plugin->env->stats, _("# Bluetooth sessions allocated"), 0, GNUNET_NO); GNUNET_STATISTICS_set (plugin->env->stats, _("# Bluetooth MAC endpoints allocated"), 0, 0); GNUNET_BANDWIDTH_tracker_init (&plugin->tracker, NULL, NULL, GNUNET_BANDWIDTH_value_init (100 * 1024 * 1024 / 8), 100); plugin->fragment_data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin); plugin->wlan_header_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin); plugin->helper_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin); plugin->beacon_task = GNUNET_SCHEDULER_add_now (&send_hello_beacon, plugin); plugin->options = 0; /* some compilers do not like switch on 'long long'... */ switch ((unsigned int) testmode) { case 0: /* normal */ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-bluetooth"; plugin->helper_argv[1] = interface; plugin->helper_argv[2] = NULL; plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-transport-bluetooth", plugin->helper_argv, &handle_helper_message, NULL, plugin); break; case 1: /* testmode, peer 1 */ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy"; plugin->helper_argv[1] = (char *) "1"; plugin->helper_argv[2] = NULL; plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-transport-wlan-dummy", plugin->helper_argv, &handle_helper_message, NULL, plugin); break; case 2: /* testmode, peer 2 */ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy"; plugin->helper_argv[1] = (char *) "2"; plugin->helper_argv[2] = NULL; plugin->suid_helper = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-transport-wlan-dummy", plugin->helper_argv, &handle_helper_message, NULL, plugin); break; default: GNUNET_assert (0); } api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = plugin; api->send = &bluetooth_plugin_send; api->get_session = &bluetooth_plugin_get_session; api->disconnect_peer = &bluetooth_plugin_disconnect_peer; api->disconnect_session = &bluetooth_plugin_disconnect_session; api->query_keepalive_factor = &bluetooth_query_keepalive_factor; api->address_pretty_printer = &bluetooth_plugin_address_pretty_printer; api->check_address = &bluetooth_plugin_address_suggested; api->address_to_string = &bluetooth_plugin_address_to_string;; api->string_to_address = &bluetooth_string_to_address; api->get_network = &bluetooth_get_network; api->update_session_timeout = &bluetooth_plugin_update_session_timeout; return api; } /* end of plugin_transport_bluetooth.c */ gnunet-0.10.1/src/transport/test_transport_api_monitoring_validation_peer1.conf0000644000175000017500000000020012267431203025173 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-val-p1/ [transport] PLUGINS=tcp gnunet-0.10.1/src/transport/test_transport_api_monitoring_peer1.conf0000644000175000017500000000014412263473436023002 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-p1/ gnunet-0.10.1/src/transport/test_quota_compliance_https_asymmetric_peer2.conf0000644000175000017500000000131312225230043024631 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer2 [transport-https_server] PORT = 3001 KEY_FILE = https_key_quota_p2.key CERT_FILE = https_cert_qutoa_p2.crt [arm] PORT = 3006 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_arm_peer2.sock [statistics] PORT = 3005 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_statistics_peer2.sock [resolver] PORT = 3004 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_resolver_peer2.sock [peerinfo] PORT = 3003 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_peerinfo_peer2.sock [transport] PORT = 3002 PLUGINS = https_server UNIXPATH = $GNUNET_RUNTIME_DIR/https_transport_peer2.sock gnunet-0.10.1/src/transport/test_quota_compliance_unix_asymmetric_peer2.conf0000644000175000017500000000120512225230043024452 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer2 [arm] PORT = 3087 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_arm_peer2.sock [statistics] PORT = 3088 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_statistics_peer2.sock [resolver] PORT = 3089 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_resolver_peer2.sock [peerinfo] PORT = 3090 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_peerinfo_peer2.sock [transport] PORT = 3091 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_transport_peer2.sock [transport-unix] PORT = 3368 gnunet-0.10.1/src/transport/test_transport_api_timeout_bluetooth_peer2.conf0000644000175000017500000000161012255010511024346 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p2/ [transport-bluetooth] INTERFACE = hci1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock #PREFIX = xterm -T transport2 -e gdb --command=cmd --args #PREFIX = valgrind --leak-check=full --show-reachable=yes --main-stacksize=104857600 #PREFIX = valgrind --leak-check=full --show-reachable=yes #PREFIX = valgrind --leak-check=full #PREFIX = valgrind --tool=massif #PREFIX = gdbserver :2345 gnunet-0.10.1/src/transport/test_transport_api_reliability_bluetooth_peer1.conf0000644000175000017500000000114112225230043025170 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p1/ [transport-bluetooth] INTERFACE = hci0 TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_plugin_hostkey0000644000175000017500000000162212040236222016655 00000000000000’€€Û±u¦Z)„‚žŒè+SàŒÓmB,•~¤)õÁ]…-náÏ›U¸á'S³1ø\à Äû‘ÓX¨­£Ñn`zTËeˆ…ëw†Ò1ÄÆƒëN¶Tn*;Ûu²-?…-m͇°Ô« „·-Ê€š…jäN&EA`þM/ÑÈX{á±%–“wh}· ÷LÂ`N™g1ÒÕ×¶rš¸Ÿ¦¦uF¯ý: ô“pÒæU$| m÷±hÒínT0ùu¨ãièxÐ' ¿ÉñT(^‹;âò¥XøéÀG>†(8$K.乜FVªÌ[;X@9ŽúÉA?a³PÙðjüülVÙv œÕׂS¤ÌBï@øû¸ â$9ËnOøw¤íõtðR”jñKG 4€kZÞˆÒÌi¾ò‡\~4Ýÿ±ú†ÌE„“ 3—,£~ÿ† ‚Œè¨[²’·¶´¼™C?}Kít$˜Úî07,\ÔDï½™gèE`ÂÈëå©©s±rT}1©î ÂoøCTõG=¾£ÚQ‚”¹Ö¸‘/xì+j+ðÖBôãIèÍ]õ`‰4´â5:wÜ¥"cÛT`±Ûû†AñLoÛÇ%RN=[Wø#}ŸÌ7ÁIXÙ=ÚoX9G(ÜCÑIP±)ÎÝ~$Ýè=Û’¦¹EÆÝÚÛ«J¸B%u>ƒTg¼µ›ÕúèüÈ3rËÙ¼Nÿ+øzÕÙí¶ÔŒHËäI/·?Õ°³Yl¢fÚä•H¡ïú/wè‹ ¹'jë@úÇ—v?†÷ §Þ8/ @uêÄ;ÝŒKH æü¦Î;'ñ&›(Nh<ô'lqç‰ë%yÍ0„»Ûæ*9dy‹–QYÞJÀ&âßäð?*àxé®?Êù¹T2y~Ê[,ªFÊÐö¸'„§þ2‚ÖªAKòÜ֘ȩKVd´_qh>°Ìý²type), GNUNET_i2s (peer)); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { if (shutdown_flag != GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAIL! Peer `%4s' disconnected during waiting period!\n", GNUNET_i2s (peer)); disconnects++; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void timer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static int percentage; timer_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; percentage += 10; time_running = GNUNET_TIME_relative_add (time_running, GNUNET_TIME_relative_divide (WAIT, 10)); if (time_running.rel_value_us == GNUNET_TIME_relative_max (time_running, WAIT).rel_value_us) { FPRINTF (stderr, "%s", "100%%\n"); shutdown_flag = GNUNET_YES; GNUNET_SCHEDULER_add_now (&end, NULL); } else { FPRINTF (stderr, "%u%%..", percentage); timer_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (WAIT, 10), &timer, NULL); } } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %s <-> %s\n", p1_c, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); shutdown_flag = GNUNET_NO; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for %s\n", GNUNET_STRINGS_relative_time_to_string (WAIT, GNUNET_YES)); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_delayed (WAIT, &end_badly, NULL); timer_task = GNUNET_SCHEDULER_add_now (&timer, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api-timeout", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; timer_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-transport-api-timeout", "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); return ret; } /* end of test_transport_api_timeout.c*/ gnunet-0.10.1/src/transport/test_transport_api_disconnect_tcp_peer1.conf0000644000175000017500000000114712225230043023577 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_timeout_bluetooth_peer1.conf0000644000175000017500000000161112255010511024346 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p1/ [transport-bluetooth] INTERFACE = hci0 TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock #PREFIX = xterm -T transport2 -e gdb --command=cmd --args #PREFIX = valgrind --leak-check=full --show-reachable=yes --main-stacksize=104857600 #PREFIX = valgrind --leak-check=full --show-reachable=yes #PREFIX = valgrind --leak-check=full #PREFIX = valgrind --tool=massif #PREFIX = gdbserver :2345 gnunet-0.10.1/src/transport/test_transport_api_monitoring_peer2.conf0000644000175000017500000000014512263473436023004 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-p2/ gnunet-0.10.1/src/transport/test_transport_blacklisting_cfg_peer2.conf0000644000175000017500000000114612225230043023234 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/gnunet-service-transport_validation.c0000644000175000017500000015114012316473377022222 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_validation.c * @brief address validation subsystem * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-transport_validation.h" #include "gnunet-service-transport_plugins.h" #include "gnunet-service-transport_hello.h" #include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_neighbours.h" #include "gnunet-service-transport.h" #include "gnunet_hello_lib.h" #include "gnunet_ats_service.h" #include "gnunet_peerinfo_service.h" #include "gnunet_signatures.h" /** * How long is a PONG signature valid? We'll recycle a signature until * 1/4 of this time is remaining. PONGs should expire so that if our * external addresses change an adversary cannot replay them indefinitely. * OTOH, we don't want to spend too much time generating PONG signatures, * so they must have some lifetime to reduce our CPU usage. */ #define PONG_SIGNATURE_LIFETIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 1) /** * After how long do we expire an address in a HELLO that we just * validated? This value is also used for our own addresses when we * create a HELLO. */ #define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) /** * How often do we allow PINGing an address that we have not yet * validated? This also determines how long we track an address that * we cannot validate (because after this time we can destroy the * validation record). */ #define UNVALIDATED_PING_KEEPALIVE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) /** * How often do we PING an address that we have successfully validated * in the past but are not actively using? Should be (significantly) * smaller than HELLO_ADDRESS_EXPIRATION. */ #define VALIDATED_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) /** * How often do we PING an address that we are currently using? */ #define CONNECTED_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2) /** * How much delay is acceptable for sending the PING or PONG? */ #define ACCEPTABLE_PING_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * Size of the validation map hashmap. */ #define VALIDATION_MAP_SIZE 256 /** * Priority to use for PINGs */ #define PING_PRIORITY 2 /** * Priority to use for PONGs */ #define PONG_PRIORITY 4 GNUNET_NETWORK_STRUCT_BEGIN /** * Message used to ask a peer to validate receipt (to check an address * from a HELLO). Followed by the address we are trying to validate, * or an empty address if we are just sending a PING to confirm that a * connection which the receiver (of the PING) initiated is still valid. */ struct TransportPingMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PING */ struct GNUNET_MessageHeader header; /** * Challenge code (to ensure fresh reply). */ uint32_t challenge GNUNET_PACKED; /** * Who is the intended recipient? */ struct GNUNET_PeerIdentity target; }; /** * Message used to validate a HELLO. The challenge is included in the * confirmation to make matching of replies to requests possible. The * signature signs our public key, an expiration time and our address.

* * This message is followed by our transport address that the PING tried * to confirm (if we liked it). The address can be empty (zero bytes) * if the PING had not address either (and we received the request via * a connection that we initiated). */ struct TransportPongMessage { /** * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PONG */ struct GNUNET_MessageHeader header; /** * Challenge code from PING (showing freshness). Not part of what * is signed so that we can re-use signatures. */ uint32_t challenge GNUNET_PACKED; /** * Signature. */ struct GNUNET_CRYPTO_EddsaSignature signature; /** * GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN to confirm that this is a * plausible address for the signing peer. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * When does this signature expire? */ struct GNUNET_TIME_AbsoluteNBO expiration; /** * Size of address appended to this message (part of what is * being signed, hence not redundant). */ uint32_t addrlen GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /** * Information about an address under validation */ struct ValidationEntry { /** * The address. */ struct GNUNET_HELLO_Address *address; /** * Handle to the blacklist check (if we're currently in it). */ struct GST_BlacklistCheck *bc; /** * Public key of the peer. */ struct GNUNET_CRYPTO_EddsaPublicKey public_key; /** * The identity of the peer. FIXME: duplicated (also in 'address') */ struct GNUNET_PeerIdentity pid; /** * Cached PONG signature */ struct GNUNET_CRYPTO_EddsaSignature pong_sig_cache; /** * ID of task that will clean up this entry if nothing happens. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * ID of task that will trigger address revalidation. */ GNUNET_SCHEDULER_TaskIdentifier revalidation_task; /** * At what time did we send the latest validation request (PING)? */ struct GNUNET_TIME_Absolute send_time; /** * At what time do we send the next validation request (PING)? */ struct GNUNET_TIME_Absolute next_validation; /** * Until when is this address valid? * ZERO if it is not currently considered valid. */ struct GNUNET_TIME_Absolute valid_until; /** * Until when is the cached PONG signature valid? * ZERO if it is not currently considered valid. */ struct GNUNET_TIME_Absolute pong_sig_valid_until; /** * How long until we can try to validate this address again? * FOREVER if the address is for an unsupported plugin (from PEERINFO) * ZERO if the address is considered valid (no validation needed) * otherwise a time in the future if we're currently denying re-validation */ struct GNUNET_TIME_Absolute revalidation_block; /** * Last observed latency for this address (round-trip), delay between * last PING sent and PONG received; FOREVER if we never got a PONG. */ struct GNUNET_TIME_Relative latency; /** * Current state of this validation entry */ enum GNUNET_TRANSPORT_ValidationState state; /** * Challenge number we used. */ uint32_t challenge; /** * When passing the address in 'add_valid_peer_address', did we * copy the address to the HELLO yet? */ int copied; /** * Are we currently using this address for a connection? */ int in_use; /** * Are we expecting a PONG message for this validation entry? */ int expecting_pong; enum GNUNET_ATS_Network_Type network; }; /** * Context of currently active requests to peerinfo * for validation of HELLOs. */ struct CheckHelloValidatedContext { /** * This is a doubly-linked list. */ struct CheckHelloValidatedContext *next; /** * This is a doubly-linked list. */ struct CheckHelloValidatedContext *prev; /** * Hello that we are validating. */ const struct GNUNET_HELLO_Message *hello; }; /** * Head of linked list of HELLOs awaiting validation. */ static struct CheckHelloValidatedContext *chvc_head; /** * Tail of linked list of HELLOs awaiting validation */ static struct CheckHelloValidatedContext *chvc_tail; /** * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses * of the given peer that we are currently validating, have validated * or are blocked from re-validation for a while). */ static struct GNUNET_CONTAINER_MultiPeerMap *validation_map; /** * Context for peerinfo iteration. */ static struct GNUNET_PEERINFO_NotifyContext *pnc; /** * Minimum delay between to validations */ static struct GNUNET_TIME_Relative validation_delay; /** * Number of validations running */ static unsigned int validations_running; /** * Validition fast start threshold */ static unsigned int validations_fast_start_threshold; /** * When is next validation allowed */ static struct GNUNET_TIME_Absolute validation_next; static GST_ValidationChangedCallback validation_entry_changed_cb; static void *validation_entry_changed_cb_cls; /** * Context for the validation entry match function. */ struct ValidationEntryMatchContext { /** * Where to store the result? */ struct ValidationEntry *ve; /** * Address we're interested in. */ const struct GNUNET_HELLO_Address *address; }; /** * Iterate over validation entries until a matching one is found. * * @param cls the 'struct ValidationEntryMatchContext' * @param key peer identity (unused) * @param value a 'struct ValidationEntry' to match * @return GNUNET_YES if the entry does not match, * GNUNET_NO if the entry does match */ static int validation_entry_match (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct ValidationEntryMatchContext *vemc = cls; struct ValidationEntry *ve = value; if (0 == GNUNET_HELLO_address_cmp (ve->address, vemc->address)) { vemc->ve = ve; return GNUNET_NO; } return GNUNET_YES; } static void validation_entry_changed (struct ValidationEntry *ve, enum GNUNET_TRANSPORT_ValidationState state) { char *t_sent = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->send_time)); char *t_valid = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->valid_until)); char *t_next = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->next_validation)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation entry changed for peer `%s' address `%s':\n\tSent: %s\n\tValid: %s\n\tNext: %s\n", GNUNET_i2s(&ve->pid), GST_plugins_a2s(ve->address), t_sent, t_valid, t_next); ve->state = state; GNUNET_free (t_sent); GNUNET_free (t_valid); GNUNET_free (t_next); validation_entry_changed_cb (validation_entry_changed_cb_cls, &ve->pid, ve->address, ve->send_time, ve->valid_until, ve->next_validation, state); } /** * Iterate over validation entries and free them. * * @param cls (unused) * @param key peer identity (unused) * @param value a 'struct ValidationEntry' to clean up * @return GNUNET_YES (continue to iterate) */ static int cleanup_validation_entry (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct ValidationEntry *ve = value; ve->next_validation = GNUNET_TIME_absolute_get_zero_(); ve->valid_until = GNUNET_TIME_UNIT_ZERO_ABS; /* Notify about deleted entry */ validation_entry_changed (ve, GNUNET_TRANSPORT_VS_REMOVE); if (NULL != ve->bc) { GST_blacklist_test_cancel (ve->bc); ve->bc = NULL; } GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (validation_map, &ve->pid, ve)); GNUNET_HELLO_address_free (ve->address); if (GNUNET_SCHEDULER_NO_TASK != ve->timeout_task) { GNUNET_SCHEDULER_cancel (ve->timeout_task); ve->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != ve->revalidation_task) { GNUNET_SCHEDULER_cancel (ve->revalidation_task); ve->revalidation_task = GNUNET_SCHEDULER_NO_TASK; } if ((GNUNET_YES == ve->expecting_pong) && (validations_running > 0)) { validations_running --; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation finished, %u validation processes running\n", validations_running); } GNUNET_free (ve); return GNUNET_OK; } /** * Address validation cleanup task. Assesses if the record is no * longer valid and then possibly triggers its removal. * * @param cls the 'struct ValidationEntry' * @param tc scheduler context (unused) */ static void timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ValidationEntry *ve = cls; struct GNUNET_TIME_Absolute max; struct GNUNET_TIME_Relative left; ve->timeout_task = GNUNET_SCHEDULER_NO_TASK; max = GNUNET_TIME_absolute_max (ve->valid_until, ve->revalidation_block); left = GNUNET_TIME_absolute_get_remaining (max); if (left.rel_value_us > 0) { /* should wait a bit longer */ ve->timeout_task = GNUNET_SCHEDULER_add_delayed (left, &timeout_hello_validation, ve); return; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# address records discarded"), 1, GNUNET_NO); cleanup_validation_entry (NULL, &ve->pid, ve); } /** * Function called with the result from blacklisting. * Send a PING to the other peer if a communication is allowed. * * @param cls our 'struct ValidationEntry' * @param pid identity of the other peer * @param result #GNUNET_OK if the connection is allowed, #GNUNET_NO if not */ static void transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid, int result) { struct ValidationEntry *ve = cls; struct TransportPingMessage ping; struct GNUNET_TRANSPORT_PluginFunctions *papi; struct GNUNET_TIME_Absolute next; const struct GNUNET_MessageHeader *hello; enum GNUNET_ATS_Network_Type network; ssize_t ret; size_t tsize; size_t slen; uint16_t hsize; ve->bc = NULL; if (GNUNET_NO == result) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist denies to send PING to `%s' `%s' `%s'\n", GNUNET_i2s (pid), GST_plugins_a2s (ve->address), ve->address->transport_name); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting plain PING to `%s' `%s' `%s'\n", GNUNET_i2s (pid), GST_plugins_a2s (ve->address), ve->address->transport_name); next = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), validation_delay); if (next.abs_value_us > validation_next.abs_value_us) validation_next = next; /* We're going to send a PING so delay next validation */ slen = strlen (ve->address->transport_name) + 1; hello = GST_hello_get (); hsize = ntohs (hello->size); tsize = sizeof (struct TransportPingMessage) + ve->address->address_length + slen + hsize; ping.header.size = htons (sizeof (struct TransportPingMessage) + ve->address->address_length + slen); ping.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING); ping.challenge = htonl (ve->challenge); ping.target = *pid; if (tsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Not transmitting `%s' with `%s', message too big (%u bytes!). This should not happen.\n"), "HELLO", "PING", (unsigned int) tsize); /* message too big (!?), get rid of HELLO */ hsize = 0; tsize = sizeof (struct TransportPingMessage) + ve->address->address_length + slen + hsize; } { char message_buf[tsize]; /* build message with structure: * [HELLO][TransportPingMessage][Transport name][Address] */ memcpy (message_buf, hello, hsize); memcpy (&message_buf[hsize], &ping, sizeof (struct TransportPingMessage)); memcpy (&message_buf[sizeof (struct TransportPingMessage) + hsize], ve->address->transport_name, slen); memcpy (&message_buf[sizeof (struct TransportPingMessage) + slen + hsize], ve->address->address, ve->address->address_length); papi = GST_plugins_find (ve->address->transport_name); if (papi == NULL) ret = -1; else { GNUNET_assert (papi->send != NULL); GNUNET_assert (papi->get_session != NULL); struct Session * session = papi->get_session(papi->cls, ve->address); if (session != NULL) { ret = papi->send (papi->cls, session, message_buf, tsize, PING_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); network = papi->get_network (papi->cls, session); if (GNUNET_ATS_NET_UNSPECIFIED == network) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Could not obtain a valid network for `%s' `%s'\n", GNUNET_i2s (pid), GST_plugins_a2s (ve->address)); GNUNET_break(0); } GST_neighbours_notify_data_sent (pid, ve->address, session, tsize); } else { /* Could not get a valid session */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not get a valid session for `%s' `%s'\n", GNUNET_i2s (pid), GST_plugins_a2s (ve->address)); ret = -1; } } } if (-1 != ret) { ve->send_time = GNUNET_TIME_absolute_get (); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PING without HELLO messages sent"), 1, GNUNET_NO); ve->network = network; ve->expecting_pong = GNUNET_YES; validations_running ++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation started, %u validation processes running\n", validations_running); /* Notify about PING sent */ validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE); } } /** * Do address validation again to keep address valid. * * @param cls the 'struct ValidationEntry' * @param tc scheduler context (unused) */ static void revalidate_address (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ValidationEntry *ve = cls; struct GNUNET_TIME_Relative canonical_delay; struct GNUNET_TIME_Relative delay; struct GNUNET_TIME_Relative blocked_for; struct GST_BlacklistCheck *bc; uint32_t rdelay; ve->revalidation_task = GNUNET_SCHEDULER_NO_TASK; delay = GNUNET_TIME_absolute_get_remaining (ve->revalidation_block); /* How long until we can possibly permit the next PING? */ canonical_delay = (ve->in_use == GNUNET_YES) ? CONNECTED_PING_FREQUENCY : ((GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value_us > 0) ? VALIDATED_PING_FREQUENCY : UNVALIDATED_PING_KEEPALIVE); if (delay.rel_value_us > canonical_delay.rel_value_us * 2) { /* situation changed, recalculate delay */ delay = canonical_delay; ve->revalidation_block = GNUNET_TIME_relative_to_absolute (delay); } if (delay.rel_value_us > 0) { /* should wait a bit longer */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for %s longer before validating address `%s'\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES), GST_plugins_a2s (ve->address)); ve->revalidation_task = GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve); ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay); return; } blocked_for = GNUNET_TIME_absolute_get_remaining(validation_next); if ((validations_running > validations_fast_start_threshold) && (blocked_for.rel_value_us > 0)) { /* Validations are blocked, have to wait for blocked_for time */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validations blocked for another %s, delaying validating address `%s'\n", GNUNET_STRINGS_relative_time_to_string (blocked_for, GNUNET_YES), GST_plugins_a2s (ve->address)); ve->revalidation_task = GNUNET_SCHEDULER_add_delayed (blocked_for, &revalidate_address, ve); ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), blocked_for); return; } ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay); /* schedule next PINGing with some extra random delay to avoid synchronous re-validations */ rdelay = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, canonical_delay.rel_value_us); /* Debug code for mantis 0002726 */ if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, rdelay).rel_value_us) { GNUNET_break (0); delay = canonical_delay; } else { delay = GNUNET_TIME_relative_add (canonical_delay, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, rdelay)); } /* End debug code for mantis 0002726*/ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validating now, next scheduled for %s, now validating address `%s'\n", GNUNET_STRINGS_relative_time_to_string (blocked_for, GNUNET_YES), GST_plugins_a2s (ve->address)); ve->revalidation_task = GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve); ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay); /* start PINGing by checking blacklist */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# address revalidations started"), 1, GNUNET_NO); bc = GST_blacklist_test_allowed (&ve->pid, ve->address->transport_name, &transmit_ping_if_allowed, ve); if (NULL != bc) ve->bc = bc; /* only set 'bc' if 'transmit_ping_if_allowed' was not already * called... */ } /** * Find a ValidationEntry entry for the given neighbour that matches * the given address and transport. If none exists, create one (but * without starting any validation). * * @param public_key public key of the peer, NULL for unknown * @param address address to find * @return validation entry matching the given specifications, NULL * if we don't have an existing entry and no public key was given */ static struct ValidationEntry * find_validation_entry (const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, const struct GNUNET_HELLO_Address *address) { struct ValidationEntryMatchContext vemc; struct ValidationEntry *ve; vemc.ve = NULL; vemc.address = address; GNUNET_CONTAINER_multipeermap_get_multiple (validation_map, &address->peer, &validation_entry_match, &vemc); if (NULL != (ve = vemc.ve)) return ve; if (public_key == NULL) return NULL; ve = GNUNET_new (struct ValidationEntry); ve->in_use = GNUNET_SYSERR; /* not defined */ ve->address = GNUNET_HELLO_address_copy (address); ve->public_key = *public_key; ve->pid = address->peer; ve->pong_sig_valid_until = GNUNET_TIME_absolute_get_zero_(); memset (&ve->pong_sig_cache, '\0', sizeof (struct GNUNET_CRYPTO_EddsaSignature)); ve->latency = GNUNET_TIME_UNIT_FOREVER_REL; ve->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); ve->timeout_task = GNUNET_SCHEDULER_add_delayed (UNVALIDATED_PING_KEEPALIVE, &timeout_hello_validation, ve); GNUNET_CONTAINER_multipeermap_put (validation_map, &address->peer, ve, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); validation_entry_changed (ve, GNUNET_TRANSPORT_VS_NEW); ve->expecting_pong = GNUNET_NO; return ve; } /** * Iterator which adds the given address to the set of validated * addresses. * * @param cls original HELLO message * @param address the address * @param expiration expiration time * @return #GNUNET_OK (keep the address) */ static int add_valid_address (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { const struct GNUNET_HELLO_Message *hello = cls; struct ValidationEntry *ve; struct GNUNET_PeerIdentity pid; struct GNUNET_ATS_Information ats; struct GNUNET_CRYPTO_EddsaPublicKey public_key; if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) return GNUNET_OK; /* expired */ if ((GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid)) || (GNUNET_OK != GNUNET_HELLO_get_key (hello, &public_key))) { GNUNET_break (0); return GNUNET_OK; /* invalid HELLO !? */ } if (0 == memcmp (&GST_my_identity, &pid, sizeof (struct GNUNET_PeerIdentity))) { /* Peerinfo returned own identity, skip validation */ return GNUNET_OK; } ve = find_validation_entry (&public_key, address); ve->valid_until = GNUNET_TIME_absolute_max (ve->valid_until, expiration); if (GNUNET_SCHEDULER_NO_TASK == ve->revalidation_task) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting revalidations for valid address `%s'\n", GST_plugins_a2s (ve->address)); ve->next_validation = GNUNET_TIME_absolute_get(); ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve); } validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE); ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.value = htonl (ve->network); GNUNET_ATS_address_add (GST_ats, address, NULL, &ats, 1); return GNUNET_OK; } /** * Function called for any HELLO known to PEERINFO. * * @param cls unused * @param peer id of the peer, NULL for last call * @param hello hello message for the peer (can be NULL) * @param err_msg error message */ static void process_peerinfo_hello (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { GNUNET_assert (NULL != peer); if (NULL == hello) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handling HELLO for peer `%s'\n", GNUNET_i2s (peer)); GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &add_valid_address, (void *) hello)); } /** * Start the validation subsystem. * * @param cb callback to call with changes to valdidation entries * @param cb_cls cls for the callback * @param max_fds maximum number of fds to use */ void GST_validation_start (GST_ValidationChangedCallback cb, void *cb_cls, unsigned int max_fds) { /** * Initialization for validation throttling * * We have a maximum number max_fds of connections we can use for validation * We monitor the number of validations in parallel and start to throttle it * when doing to many validations in parallel: * if (running validations < (max_fds / 2)) * - "fast start": run validation immediately * - have delay of (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2) * (300 sec / ~150 == ~2 sec.) between two validations */ validation_next = GNUNET_TIME_absolute_get(); validation_delay.rel_value_us = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2); validations_fast_start_threshold = (max_fds / 2); validations_running = 0; validation_entry_changed_cb = cb; validation_entry_changed_cb_cls = cb_cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation uses a fast start threshold of %u connections and a delay between of %s\n ", validations_fast_start_threshold, GNUNET_STRINGS_relative_time_to_string (validation_delay, GNUNET_YES)); validation_map = GNUNET_CONTAINER_multipeermap_create (VALIDATION_MAP_SIZE, GNUNET_NO); pnc = GNUNET_PEERINFO_notify (GST_cfg, GNUNET_YES, &process_peerinfo_hello, NULL); } /** * Stop the validation subsystem. */ void GST_validation_stop () { struct CheckHelloValidatedContext *chvc; GNUNET_CONTAINER_multipeermap_iterate (validation_map, &cleanup_validation_entry, NULL); GNUNET_CONTAINER_multipeermap_destroy (validation_map); validation_map = NULL; while (NULL != (chvc = chvc_head)) { GNUNET_CONTAINER_DLL_remove (chvc_head, chvc_tail, chvc); GNUNET_free (chvc); } GNUNET_PEERINFO_notify_cancel (pnc); } /** * Send the given PONG to the given address. * * @param cls the PONG message * @param public_key public key for the peer, never NULL * @param valid_until is ZERO if we never validated the address, * otherwise a time up to when we consider it (or was) valid * @param validation_block is FOREVER if the address is for an unsupported plugin (from PEERINFO) * is ZERO if the address is considered valid (no validation needed) * otherwise a time in the future if we're currently denying re-validation * @param address target address */ static void multicast_pong (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const struct GNUNET_HELLO_Address *address) { struct TransportPongMessage *pong = cls; struct GNUNET_TRANSPORT_PluginFunctions *papi; papi = GST_plugins_find (address->transport_name); if (papi == NULL) return; GNUNET_assert (papi->send != NULL); GNUNET_assert (papi->get_session != NULL); struct Session * session = papi->get_session(papi->cls, address); if (session == NULL) { GNUNET_break (0); return; } papi->send (papi->cls, session, (const char *) pong, ntohs (pong->header.size), PONG_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); GST_neighbours_notify_data_sent (&address->peer, address, session, pong->header.size); } /** * We've received a PING. If appropriate, generate a PONG. * * @param sender peer sending the PING * @param hdr the PING * @param sender_address the sender address as we got it * @param session session we got the PING from * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr, const struct GNUNET_HELLO_Address *sender_address, struct Session *session) { const struct TransportPingMessage *ping; struct TransportPongMessage *pong; struct GNUNET_TRANSPORT_PluginFunctions *papi; struct GNUNET_CRYPTO_EddsaSignature *sig_cache; struct GNUNET_TIME_Absolute *sig_cache_exp; const char *addr; const char *addrend; char *plugin_name; char *pos; size_t alen; size_t slen; ssize_t ret; int buggy = GNUNET_NO; struct GNUNET_HELLO_Address address; if (ntohs (hdr->size) < sizeof (struct TransportPingMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } ping = (const struct TransportPingMessage *) hdr; if (0 != memcmp (&ping->target, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PING message for different peer received"), 1, GNUNET_NO); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PING messages received"), 1, GNUNET_NO); addr = (const char *) &ping[1]; alen = ntohs (hdr->size) - sizeof (struct TransportPingMessage); /* peer wants to confirm that this is one of our addresses, this is what is * used for address validation */ sig_cache = NULL; sig_cache_exp = NULL; papi = NULL; if (alen > 0) { addrend = memchr (addr, '\0', alen); if (NULL == addrend) { GNUNET_break_op (0); return GNUNET_SYSERR; } addrend++; slen = strlen (addr) + 1; alen -= slen; address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE; address.address = addrend; address.address_length = alen; address.transport_name = addr; address.peer = GST_my_identity; if (NULL == address.transport_name) { GNUNET_break (0); } if (0 != strstr (address.transport_name, "_client")) { plugin_name = GNUNET_strdup (address.transport_name); pos = strstr (plugin_name, "_client"); GNUNET_assert (NULL != pos); GNUNET_snprintf (pos, strlen ("_server") + 1, "%s", "_server"); } else plugin_name = GNUNET_strdup (address.transport_name); if (NULL == (papi = GST_plugins_find (plugin_name))) { /* we don't have the plugin for this address */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Plugin `%s' not available, cannot confirm having this address\n"), plugin_name); GNUNET_free (plugin_name); return GNUNET_SYSERR; } GNUNET_free (plugin_name); if (GNUNET_OK != papi->check_address (papi->cls, addrend, alen)) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# failed address checks during validation"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Address `%s' is not one of my addresses, not confirming PING\n"), GST_plugins_a2s (&address)); return GNUNET_SYSERR; } else { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# successful address checks during validation"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Address `%s' is one of my addresses, confirming PING\n", GST_plugins_a2s (&address)); } if (GNUNET_YES != GST_hello_test_address (&address, &sig_cache, &sig_cache_exp)) { if (GNUNET_NO == buggy) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Not confirming PING from peer `%s' with address `%s' since I cannot confirm having this address.\n"), GNUNET_i2s (sender), GST_plugins_a2s (&address)); return GNUNET_SYSERR; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Received a PING message with validation bug from `%s'\n"), GNUNET_i2s (sender)); } } } else { addrend = NULL; /* make gcc happy */ slen = 0; static struct GNUNET_CRYPTO_EddsaSignature no_address_signature; static struct GNUNET_TIME_Absolute no_address_signature_expiration; sig_cache = &no_address_signature; sig_cache_exp = &no_address_signature_expiration; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am `%s', sending PONG to peer `%s'\n", GNUNET_i2s_full (&GST_my_identity), GNUNET_i2s (sender)); /* message with structure: * [TransportPongMessage][Transport name][Address] */ pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + alen + slen); pong->header.size = htons (sizeof (struct TransportPongMessage) + alen + slen); pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG); pong->purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + alen + slen); pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN); memcpy (&pong->challenge, &ping->challenge, sizeof (ping->challenge)); pong->addrlen = htonl (alen + slen); memcpy (&pong[1], addr, slen); /* Copy transport plugin */ if (alen > 0) { GNUNET_assert (NULL != addrend); memcpy (&((char *) &pong[1])[slen], addrend, alen); } if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value_us < PONG_SIGNATURE_LIFETIME.rel_value_us / 4) { /* create / update cached sig */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating PONG signature to indicate ownership.\n"); *sig_cache_exp = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME); pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_sign (GST_my_private_key, &pong->purpose, sig_cache)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to create PONG signature for peer `%s'\n"), GNUNET_i2s (sender)); } } else { pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp); } pong->signature = *sig_cache; GNUNET_assert (sender_address != NULL); /* first see if the session we got this PING from can be used to transmit * a response reliably */ if (papi == NULL) ret = -1; else { GNUNET_assert (papi->send != NULL); GNUNET_assert (papi->get_session != NULL); if (session == NULL) { session = papi->get_session (papi->cls, sender_address); } if (session == NULL) { GNUNET_break (0); ret = -1; } else { ret = papi->send (papi->cls, session, (const char *) pong, ntohs (pong->header.size), PONG_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); if (-1 != ret) GST_neighbours_notify_data_sent (sender, sender_address, session, pong->header.size); } } if (ret != -1) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted PONG to `%s' via reliable mechanism\n", GNUNET_i2s (sender)); /* done! */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PONGs unicast via reliable transport"), 1, GNUNET_NO); GNUNET_free (pong); return GNUNET_OK; } /* no reliable method found, try transmission via all known addresses */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PONGs multicast to all available addresses"), 1, GNUNET_NO); GST_validation_get_addresses (sender, &multicast_pong, pong); GNUNET_free (pong); return GNUNET_OK; } /** * Context for the #validate_address_iterator() function */ struct ValidateAddressContext { /** * Hash of the public key of the peer whose address is being validated. */ struct GNUNET_PeerIdentity pid; /** * Public key of the peer whose address is being validated. */ struct GNUNET_CRYPTO_EddsaPublicKey public_key; }; /** * Iterator callback to go over all addresses and try to validate them * (unless blocked or already validated). * * @param cls pointer to a `struct ValidateAddressContext` * @param address the address * @param expiration expiration time * @return #GNUNET_OK (keep the address) */ static int validate_address_iterator (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { const struct ValidateAddressContext *vac = cls; struct ValidationEntry *ve; if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping expired address from HELLO\n"); return GNUNET_OK; /* expired */ } ve = find_validation_entry (&vac->public_key, address); if (GNUNET_SCHEDULER_NO_TASK == ve->revalidation_task) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Validation process started for fresh address `%s'\n", GST_plugins_a2s (ve->address)); ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve); } return GNUNET_OK; } /** * Add the validated peer address to the HELLO. * * @param cls the 'struct ValidationEntry' with the validated address * @param max space in buf * @param buf where to add the address * @return number of bytes written, 0 to signal the * end of the iteration. */ static size_t add_valid_peer_address (void *cls, size_t max, void *buf) { struct ValidationEntry *ve = cls; if (GNUNET_YES == ve->copied) return 0; /* terminate */ ve->copied = GNUNET_YES; return GNUNET_HELLO_add_address (ve->address, ve->valid_until, buf, max); } /** * We've received a PONG. Check if it matches a pending PING and * mark the respective address as confirmed. * * @param sender peer sending the PONG * @param hdr the PONG * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr) { const struct TransportPongMessage *pong; struct ValidationEntry *ve; const char *tname; const char *addr; size_t addrlen; size_t slen; size_t size; struct GNUNET_HELLO_Message *hello; struct GNUNET_HELLO_Address address; int sig_res; int do_verify; if (ntohs (hdr->size) < sizeof (struct TransportPongMessage)) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PONG messages received"), 1, GNUNET_NO); /* message with structure: * [TransportPongMessage][Transport name][Address] */ pong = (const struct TransportPongMessage *) hdr; tname = (const char *) &pong[1]; size = ntohs (hdr->size) - sizeof (struct TransportPongMessage); addr = memchr (tname, '\0', size); if (NULL == addr) { GNUNET_break_op (0); return GNUNET_SYSERR; } addr++; slen = strlen (tname) + 1; addrlen = size - slen; address.peer = *sender; address.address = addr; address.address_length = addrlen; address.transport_name = tname; address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE; ve = find_validation_entry (NULL, &address); if ((NULL == ve) || (GNUNET_NO == ve->expecting_pong)) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PONGs dropped, no matching pending validation"), 1, GNUNET_NO); return GNUNET_OK; } /* now check that PONG is well-formed */ if (0 != memcmp (&ve->pid, sender, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (pong->expiration)).rel_value_us == 0) { GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PONGs dropped, signature expired"), 1, GNUNET_NO); return GNUNET_SYSERR; } sig_res = GNUNET_SYSERR; do_verify = GNUNET_YES; if (0 != GNUNET_TIME_absolute_get_remaining(ve->pong_sig_valid_until).rel_value_us) { /* We have a cached and valid signature for this peer, * try to compare instead of verify */ if (0 == memcmp (&ve->pong_sig_cache, &pong->signature, sizeof (struct GNUNET_CRYPTO_EddsaSignature))) { /* signatures are identical, we can skip verification */ sig_res = GNUNET_OK; do_verify = GNUNET_NO; } else { sig_res = GNUNET_SYSERR; /* signatures do not match, we have to verify */ } } if (GNUNET_YES == do_verify) { /* Do expensive verification */ sig_res = GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, &pong->purpose, &pong->signature, &ve->public_key); if (sig_res == GNUNET_SYSERR) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to verify: invalid signature on address `%s':%s from peer `%s'\n", tname, GST_plugins_a2s (ve->address), GNUNET_i2s (sender)); } } if (sig_res == GNUNET_SYSERR) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Validation process successful for peer `%s' with plugin `%s' address `%s'\n", GNUNET_i2s (sender), tname, GST_plugins_a2s (ve->address)); /* validity achieved, remember it! */ ve->expecting_pong = GNUNET_NO; ve->valid_until = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION); ve->pong_sig_cache = pong->signature; ve->pong_sig_valid_until = GNUNET_TIME_absolute_ntoh (pong->expiration); ve->latency = GNUNET_TIME_absolute_get_duration (ve->send_time); { struct GNUNET_ATS_Information ats[2]; ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); ats[0].value = htonl ((uint32_t) ve->latency.rel_value_us); ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE); ats[1].value = htonl ((uint32_t) ve->network); GNUNET_ATS_address_add (GST_ats, ve->address, NULL, ats, 2); } if (validations_running > 0) { validations_running --; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation finished, %u validation processes running\n", validations_running); } else { GNUNET_break (0); } /* Notify about new validity */ validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE); /* build HELLO to store in PEERINFO */ ve->copied = GNUNET_NO; hello = GNUNET_HELLO_create (&ve->public_key, &add_valid_peer_address, ve, GNUNET_NO); GNUNET_PEERINFO_add_peer (GST_peerinfo, hello, NULL, NULL); GNUNET_free (hello); return GNUNET_OK; } /** * We've received a HELLO, check which addresses are new and trigger * validation. * * @param hello the HELLO we received * @return #GNUNET_OK if the message was fine, #GNUNET_SYSERR on serious error */ int GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello) { const struct GNUNET_HELLO_Message *hm = (const struct GNUNET_HELLO_Message *) hello; struct ValidateAddressContext vac; struct GNUNET_HELLO_Message *h; int friend; friend = GNUNET_HELLO_is_friend_only (hm); if ( ( (GNUNET_YES != friend) && (GNUNET_NO != friend) ) || (GNUNET_OK != GNUNET_HELLO_get_id (hm, &vac.pid)) || (GNUNET_OK != GNUNET_HELLO_get_key (hm, &vac.public_key))) { /* malformed HELLO */ GNUNET_break_op (0); return GNUNET_SYSERR; } if (0 == memcmp (&GST_my_identity, &vac.pid, sizeof (struct GNUNET_PeerIdentity))) return GNUNET_OK; /* Add peer identity without addresses to peerinfo service */ h = GNUNET_HELLO_create (&vac.public_key, NULL, NULL, friend); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Validation received new %s message for peer `%s' with size %u\n"), "HELLO", GNUNET_i2s (&vac.pid), ntohs (hello->size)); GNUNET_PEERINFO_add_peer (GST_peerinfo, h, NULL, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Adding `%s' without addresses for peer `%s'\n"), "HELLO", GNUNET_i2s (&vac.pid)); GNUNET_free (h); GNUNET_assert (NULL == GNUNET_HELLO_iterate_addresses (hm, GNUNET_NO, &validate_address_iterator, &vac)); return GNUNET_OK; } /** * Closure for #iterate_addresses(). */ struct IteratorContext { /** * Function to call on each address. */ GST_ValidationAddressCallback cb; /** * Closure for @e cb. */ void *cb_cls; }; /** * Call the callback in the closure for each validation entry. * * @param cls the `struct IteratorContext` * @param key the peer's identity * @param value the `struct ValidationEntry` * @return #GNUNET_OK (continue to iterate) */ static int iterate_addresses (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct IteratorContext *ic = cls; struct ValidationEntry *ve = value; ic->cb (ic->cb_cls, &ve->public_key, ve->valid_until, ve->revalidation_block, ve->address); return GNUNET_OK; } /** * Call the given function for each address for the given target. * Can either give a snapshot (synchronous API) or be continuous. * * @param target peer information is requested for * @param cb function to call; will not be called after this function returns * @param cb_cls closure for 'cb' */ void GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target, GST_ValidationAddressCallback cb, void *cb_cls) { struct IteratorContext ic; ic.cb = cb; ic.cb_cls = cb_cls; GNUNET_CONTAINER_multipeermap_get_multiple (validation_map, target, &iterate_addresses, &ic); } /** * Update if we are using an address for a connection actively right now. * Based on this, the validation module will measure latency for the * address more or less often. * * @param address the address * @param session the session * @param in_use #GNUNET_YES if we are now using the address for a connection, * #GNUNET_NO if we are no longer using the address for a connection */ void GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address, struct Session *session, int in_use) { struct ValidationEntry *ve; if (NULL != address) ve = find_validation_entry (NULL, address); else ve = NULL; /* FIXME: lookup based on session... */ if (NULL == ve) { /* this can happen for inbound connections (sender_address_len == 0); */ return; } if (ve->in_use == in_use) { if (GNUNET_YES == in_use) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error setting address in use for peer `%s' `%s' to USED\n", GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); } if (GNUNET_NO == in_use) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error setting address in use for peer `%s' `%s' to NOT_USED\n", GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); } } GNUNET_break (ve->in_use != in_use); /* should be different... */ ve->in_use = in_use; if (in_use == GNUNET_YES) { /* from now on, higher frequeny, so reschedule now */ GNUNET_SCHEDULER_cancel (ve->revalidation_task); ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve); } } /** * Query validation about the latest observed latency on a given * address. * * @param sender peer * @param address the address * @param session session * @return observed latency of the address, FOREVER if the address was * never successfully validated */ struct GNUNET_TIME_Relative GST_validation_get_address_latency (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_HELLO_Address *address, struct Session *session) { struct ValidationEntry *ve; if (NULL == address) { GNUNET_break (0); // FIXME: support having latency only with session... return GNUNET_TIME_UNIT_FOREVER_REL; } ve = find_validation_entry (NULL, address); if (NULL == ve) return GNUNET_TIME_UNIT_FOREVER_REL; return ve->latency; } /** * Closure for the validation_entries_iterate function. */ struct ValidationIteratorContext { /** * Function to call on each validation entry */ GST_ValidationChangedCallback cb; /** * Closure for 'cb'. */ void *cb_cls; }; static int validation_entries_iterate (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct ValidationIteratorContext *ic = cls; struct ValidationEntry *ve = value; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying about validation entry for peer `%s' address `%s' \n", GNUNET_i2s (&ve->pid), GST_plugins_a2s (ve->address)); ic->cb (ic->cb_cls, &ve->pid, ve->address, ve->send_time, ve->valid_until, ve->next_validation, ve->state); return GNUNET_OK; } /** * Iterate over all iteration entries * * @param cb function to call * @param cb_cls closure for cb */ void GST_validation_iterate (GST_ValidationChangedCallback cb, void *cb_cls) { struct ValidationIteratorContext ic; if (NULL == validation_map) return; /* can happen during shutdown */ ic.cb = cb; ic.cb_cls = cb_cls; GNUNET_CONTAINER_multipeermap_iterate (validation_map, &validation_entries_iterate, &ic); } /* end of file gnunet-service-transport_validation.c */ gnunet-0.10.1/src/transport/test_transport_testing.c0000644000175000017500000001363012225777502017645 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api.c * @brief base test case for transport implementations * * This test case serves as a base for tcp, udp, and udp-nat * transport test cases. Based on the executable being run * the correct test case will be performed. Conservation of * C code apparently. */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) GNUNET_SCHEDULER_TaskIdentifier timeout_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; struct GNUNET_TRANSPORT_TESTING_handle *tth; static int connected = GNUNET_NO; static int ret = 0; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (timeout_task); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); } static void end_badly () { timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (NULL != cc) { GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); if (NULL != tth) GNUNET_TRANSPORT_TESTING_done (tth); ret = GNUNET_SYSERR; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { char *ps = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') connected to peer %u (`%s')!\n", p1->no, ps, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (ps); GNUNET_SCHEDULER_add_now (&end, NULL); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected \n", GNUNET_i2s (peer)); connected++; } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' disconnected \n", GNUNET_i2s (peer)); } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving\n"); } void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { tth = GNUNET_TRANSPORT_TESTING_init (); timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &end_badly, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting peer\n"); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_api_tcp_peer1.conf", 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, p1); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, "test_transport_api_tcp_peer2.conf", 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, p2); if (p1 == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer1 was not started successfully\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); } if (p2 == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer2 was not started successfully\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); } } int main (int argc, char *argv[]) { GNUNET_log_setup ("test_transport_testing", "WARNING", NULL); char *const argv_1[] = { "test_transport_testing", "-c", "test_transport_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run ((sizeof (argv_1) / sizeof (char *)) - 1, argv_1, "test_transport_testing", "nohelp", options, &run, &ret); return ret; } /* end of test_transport_api.c */ gnunet-0.10.1/src/transport/test_transport_api_timeout_udp_peer1.conf0000644000175000017500000000124012225230043023130 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-p1/ [transport-udp] PORT = 12040 BROADCAST = NO BROADCAST_INTERVAL = 30000 MAX_BPS = 50000000 [arm] PORT = 12045 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12044 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12043 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12042 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] #PREFIX = valgrind --leak-check=full PORT = 12041 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/gnunet-transport-wlan-sender.c0000644000175000017500000001667012225777502020573 00000000000000/* This file is part of GNUnet (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-transport-wlan-sender.c * @brief program to send via WLAN as much as possible (to test physical/theoretical throughput) * @author David Brodski */ #include "platform.h" #include "plugin_transport_wlan.h" #include "gnunet_protocols.h" #define WLAN_MTU 1500 /** * LLC fields for better compatibility */ #define WLAN_LLC_DSAP_FIELD 0x1f #define WLAN_LLC_SSAP_FIELD 0x1f #define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ #define IEEE80211_FC0_VERSION_MASK 0x03 #define IEEE80211_FC0_VERSION_SHIFT 0 #define IEEE80211_FC0_VERSION_0 0x00 #define IEEE80211_FC0_TYPE_MASK 0x0c #define IEEE80211_FC0_TYPE_SHIFT 2 #define IEEE80211_FC0_TYPE_MGT 0x00 #define IEEE80211_FC0_TYPE_CTL 0x04 #define IEEE80211_FC0_TYPE_DATA 0x08 /** * function to fill the radiotap header * @param header pointer to the radiotap header * @param size total message size * @return GNUNET_YES at success */ static int getRadiotapHeader (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header, uint16_t size) { header->header.size = htons (size); header->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER); header->rate = 255; header->tx_power = 0; header->antenna = 0; return GNUNET_YES; } /** * function to generate the wlan hardware header for one packet * @param Header address to write the header to * @param to_mac_addr pointer to the address of the recipient * @param mac pointer to the mac address to send from (normally overwritten over by helper) * @param size size of the whole packet, needed to calculate the time to send the packet * @return GNUNET_YES if there was no error */ static int getWlanHeader (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *Header, const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr, const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac, unsigned int size) { const int rate = 11000000; Header->frame_control = htons (IEEE80211_FC0_TYPE_DATA); Header->addr3 = mac_bssid_gnunet; Header->addr2 = *mac; Header->addr1 = *to_mac_addr; Header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290); Header->llc[0] = WLAN_LLC_DSAP_FIELD; Header->llc[1] = WLAN_LLC_SSAP_FIELD; Header->llc[2] = 0; // FIXME Header->llc[3] = 0; // FIXME return GNUNET_YES; } int main (int argc, char *argv[]) { char msg_buf[WLAN_MTU]; struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radiotap; unsigned int temp[6]; struct GNUNET_TRANSPORT_WLAN_MacAddress inmac; struct GNUNET_TRANSPORT_WLAN_MacAddress outmac; struct GNUNET_TRANSPORT_WLAN_HelperControlMessage hcm; unsigned long long count; double bytes_per_s; time_t start; time_t akt; int i; ssize_t ret; pid_t pid; int commpipe[2]; /* This holds the fd for the input & output of the pipe */ int macpipe[2]; /* This holds the fd for the input & output of the pipe */ if (4 != argc) { fprintf (stderr, "This program must be started with the interface and the targets and source mac as argument.\n"); fprintf (stderr, "Usage: interface-name mac-DST mac-SRC\n" "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n"); return 1; } if (6 != SSCANF (argv[2], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], &temp[5])) { fprintf (stderr, "Usage: interface-name mac-DST mac-SRC\n" "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n"); return 1; } for (i = 0; i < 6; i++) outmac.mac[i] = temp[i]; if (6 != SSCANF (argv[3], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], &temp[5])) { fprintf (stderr, "Usage: interface-name mac-DST mac-SRC\n" "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n"); return 1; } for (i = 0; i < 6; i++) inmac.mac[i] = temp[i]; /* Setup communication pipeline first */ if (pipe (commpipe)) { fprintf (stderr, "Failed to create pipe: %s\n", STRERROR (errno)); exit (1); } if (pipe (macpipe)) { fprintf (stderr, "Failed to create pipe: %s\n", STRERROR (errno)); exit (1); } /* Attempt to fork and check for errors */ if ((pid = fork ()) == -1) { fprintf (stderr, "Failed to fork: %s\n", STRERROR (errno)); exit (1); } memset (msg_buf, 0x42, sizeof (msg_buf)); if (pid) { /* A positive (non-negative) PID indicates the parent process */ if (0 != close (commpipe[0])) /* Close unused side of pipe (in side) */ fprintf (stderr, "Failed to close fd: %s\n", strerror (errno)); setvbuf (stdout, (char *) NULL, _IONBF, 0); /* Set non-buffered output on stdout */ if (0 != close (macpipe[1])) fprintf (stderr, "Failed to close fd: %s\n", strerror (errno)); if (sizeof (hcm) != read (macpipe[0], &hcm, sizeof (hcm))) fprintf (stderr, "Failed to read hcm...\n"); fprintf (stderr, "Got MAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", hcm.mac.mac[0], hcm.mac.mac[1], hcm.mac.mac[2], hcm.mac.mac[3], hcm.mac.mac[4], hcm.mac.mac[5]); radiotap = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) msg_buf; getRadiotapHeader (radiotap, WLAN_MTU); getWlanHeader (&radiotap->frame, &outmac, &inmac, WLAN_MTU); start = time (NULL); count = 0; while (1) { ret = write (commpipe[1], msg_buf, WLAN_MTU); if (0 > ret) { fprintf (stderr, "write failed: %s\n", strerror (errno)); break; } count += ret; akt = time (NULL); if (akt - start > 30) { bytes_per_s = count / (akt - start); bytes_per_s /= 1024; printf ("send %f kbytes/s\n", bytes_per_s); start = akt; count = 0; } } } else { /* A zero PID indicates that this is the child process */ (void) close (0); (void) close (1); if (-1 == dup2 (commpipe[0], 0)) /* Replace stdin with the in side of the pipe */ fprintf (stderr, "dup2 failed: %s\n", strerror (errno)); if (-1 == dup2 (macpipe[1], 1)) /* Replace stdout with the out side of the pipe */ fprintf (stderr, "dup2 failed: %s\n", strerror (errno)); (void) close (commpipe[1]); /* Close unused side of pipe (out side) */ (void) close (macpipe[0]); /* Close unused side of pipe (in side) */ /* Replace the child fork with a new process */ if (execlp ("gnunet-helper-transport-wlan", "gnunet-helper-transport-wlan", argv[1], NULL) == -1) { fprintf (stderr, "Could not start gnunet-helper-transport-wlan!"); _exit (1); } } return 0; } gnunet-0.10.1/src/transport/test_transport_startonly.conf0000644000175000017500000000021612225230043020706 00000000000000@INLINE@ test_transport_defaults.conf [PATHS] [arm] DEFAULTSERVICES = transport [transport-tcp] PORT = 2094 [transport-udp] PORT = 2094 gnunet-0.10.1/src/transport/test_transport_api_udp_peer2.conf0000644000175000017500000000120112225230043021360 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-p2/ [transport-udp] PORT = 12050 BROADCAST = NO MAX_BPS = 50000000 BINDTO = 127.0.0.1 BINDTO6 = ::1 [arm] PORT = 12055 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12054 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12053 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12052 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12051 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_manipulation_recv_tcp.c0000644000175000017500000003211412274162761023403 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_manipulation_recv_tcp.c * @brief base test case for transport traffic manipulation implementation * * This test case will setup 2 peers and connect them, the first message * will be sent without manipulation, then a receive delay of 1 second will * be configured and 2 more message will be sent. Time will be measured * * In addition the distance on receiver side will be manipulated to be 10 */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) #define TEST_MESSAGE_SIZE 2600 #define TEST_MESSAGE_TYPE 12345 static char *test_source; static char *test_plugin; static char *test_name; static int ok; static int s_started; static int s_connected; static int s_sending; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static int messages_recv; static struct GNUNET_TIME_Absolute start_normal; static struct GNUNET_TIME_Relative dur_normal; static struct GNUNET_TIME_Absolute start_delayed; static struct GNUNET_TIME_Relative dur_delayed; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); if (s_started == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started \n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started \n")); if (s_connected == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not connected\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were connected\n")); if (s_sending == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were ready to send data\n")); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 1 was not started\n")); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 2 was not started\n")); ok = GNUNET_SYSERR; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if ((TEST_MESSAGE_TYPE == ntohs (message->type)) && (TEST_MESSAGE_SIZE == ntohs (message->size))) { ok = 0; } else { GNUNET_break (0); ok = 1; end (); return; } if (messages_recv <= 1) { /* Received non-delayed message */ dur_normal = GNUNET_TIME_absolute_get_duration(start_normal); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received non-delayed message %u after %s\n", messages_recv, GNUNET_STRINGS_relative_time_to_string (dur_normal, GNUNET_YES)); struct GNUNET_ATS_Information ats[2]; ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY); ats[0].value = htonl (1000 * 1000LL); ats[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); ats[1].value = htonl (10); GNUNET_TRANSPORT_set_traffic_metric (p1->th, &p2->id, GNUNET_YES, GNUNET_NO, ats, 2); send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } if (2 == messages_recv) { /* Received manipulated message */ dur_delayed = GNUNET_TIME_absolute_get_duration(start_delayed); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received delayed message %u after %s\n", messages_recv, GNUNET_STRINGS_relative_time_to_string (dur_delayed, GNUNET_YES)); if (dur_delayed.rel_value_us < 1000 * 1000LL) { GNUNET_break (0); ok += 1; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Delayed message was not delayed correctly: took only %s\n", GNUNET_STRINGS_relative_time_to_string (dur_delayed, GNUNET_YES)); } /* shutdown */ end (); } messages_recv ++; } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= TEST_MESSAGE_SIZE); if (buf != NULL) { memset (buf, '\0', TEST_MESSAGE_SIZE); hdr = buf; hdr->size = htons (TEST_MESSAGE_SIZE); hdr->type = htons (TEST_MESSAGE_TYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return TEST_MESSAGE_SIZE; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); if (0 == messages_recv) { start_normal = GNUNET_TIME_absolute_get(); } if (1 == messages_recv) { start_delayed = GNUNET_TIME_absolute_get(); } s_sending = GNUNET_YES; th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); s_connected = GNUNET_YES; send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; else s_started = GNUNET_YES; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); s_started = GNUNET_NO; s_connected = GNUNET_NO; s_sending = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api-manipulation", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); GNUNET_log_setup (test_name, "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of test_transport_api_manipulation_recv_tcp.c */ gnunet-0.10.1/src/transport/test_quota_compliance_tcp_asymmetric_peer2.conf0000644000175000017500000000115112225230043024255 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/quota-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/gnunet-helper-transport-wlan-dummy.c0000644000175000017500000003065012261236532021706 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-helper-transport-wlan-dummy.c * @brief helper for the testcases for plugin_transport_wlan.c * @author David Brodski */ #include "platform.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" #include "plugin_transport_wlan.h" /** * Name of the fifo to use for IPC with the other dummy process. */ #define FIFO_FILE1 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_in" /** * Name of the fifo to use for IPC with the other dummy process. */ #define FIFO_FILE2 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_out" /** * Maximum size of a message allowed in either direction * (used for our receive and sent buffers). */ #define MAXLINE 4096 /** * IO buffer used for buffering data in transit. */ struct SendBuffer { /** * How many bytes that were stored in 'buf' did we already write to the * destination? Always smaller than 'size'. */ size_t pos; /** * How many bytes of data are stored in 'buf' for transmission right now? * Data always starts at offset 0 and extends to 'size'. */ size_t size; /** * Buffered data; twice the maximum allowed message size as we add some * headers. */ char buf[MAXLINE * 2]; }; /** * Flag set to 1 if we are to terminate, otherwise 0. */ static int closeprog; /** * We're being killed, clean up. * * @param sig killing signal */ static void sigfunc (int sig) { closeprog = 1; (void) unlink (FIFO_FILE1); (void) unlink (FIFO_FILE2); } /** * Create control message for plugin * * @param buffer pointer to buffer for the message * @param mac pointer to the mac address * @return number of bytes written */ static int send_mac_to_plugin (char *buffer, struct GNUNET_TRANSPORT_WLAN_MacAddress *mac) { struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg; memcpy (&macmsg.mac, (char *) mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)); macmsg.hdr.size = htons (sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage)); macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL); memcpy (buffer, &macmsg, sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage)); return sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage); } /** * We got a message from the FIFO, check it, convert the message * type to the output forward and copy it to the buffer for stdout. * * @param cls the 'struct SendBuffer' to copy the converted message to * @param client unused * @param hdr inbound message from the FIFO */ static int stdin_send (void *cls, void *client, const struct GNUNET_MessageHeader *hdr) { struct SendBuffer *write_pout = cls; const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *in; size_t payload_size; struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage newheader; uint16_t sendsize; sendsize = ntohs (hdr->size); in = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr; if ( (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) || (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) > sendsize) ) { FPRINTF (stderr, "%s", "Received malformed message\n"); exit (1); } payload_size = sendsize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage); if ((payload_size + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + write_pout->size) > MAXLINE * 2) { FPRINTF (stderr, "%s", "Packet too big for buffer\n"); exit (1); } memset (&newheader, 0, sizeof (newheader)); newheader.header.size = htons (payload_size + sizeof (newheader)); newheader.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER); newheader.frame = in->frame; memcpy (write_pout->buf + write_pout->size, &newheader, sizeof (newheader)); write_pout->size += sizeof (newheader); memcpy (write_pout->buf + write_pout->size, &in[1], payload_size); write_pout->size += payload_size; return GNUNET_OK; } /** * We read a full message from stdin. Copy it to our send buffer. * * @param cls the 'struct SendBuffer' to copy to * @param client unused * @param hdr the message we received to copy to the buffer */ static int file_in_send (void *cls, void *client, const struct GNUNET_MessageHeader *hdr) { struct SendBuffer *write_std = cls; uint16_t sendsize; sendsize = ntohs (hdr->size); if ((sendsize + write_std->size) > MAXLINE * 2) { FPRINTF (stderr, "%s", "Packet too big for buffer\n"); exit (1); } memcpy (write_std->buf + write_std->size, hdr, sendsize); write_std->size += sendsize; return GNUNET_OK; } /** * Main function of a program that pretends to be a WLAN card. * * @param argc should be 2 * @param argv either '1' or '2', depending on which of the two cards this dummy is to emulate * @return 1 on error, 0 if terminated normally via signal */ int main (int argc, char *argv[]) { struct stat st; int erg; FILE *fpin = NULL; FILE *fpout = NULL; int fdpin; int fdpout; char readbuf[MAXLINE]; int readsize; struct SendBuffer write_std; struct SendBuffer write_pout; int ret; int maxfd; fd_set rfds; fd_set wfds; struct timeval tv; int retval; struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst = NULL; struct GNUNET_SERVER_MessageStreamTokenizer *file_in_mst = NULL; struct GNUNET_TRANSPORT_WLAN_MacAddress macaddr; int first; if ( (2 != argc) || ((0 != strcmp (argv[1], "1")) && (0 != strcmp (argv[1], "2"))) ) { FPRINTF (stderr, "%s", "This program must be started with the operating mode (1 or 2) as the only argument.\n"); return 1; } /* make the fifos if needed */ umask (0); if ( (GNUNET_OK != GNUNET_DISK_directory_create_for_file (FIFO_FILE1)) || (GNUNET_OK != GNUNET_DISK_directory_create_for_file (FIFO_FILE2)) ) { FPRINTF (stderr, "Failed to create directory for file `%s'\n", FIFO_FILE1); return 1; } if (0 == strcmp (argv[1], "1") ) { if (0 != stat (FIFO_FILE1, &st)) { erg = mkfifo (FIFO_FILE1, 0666); if ( (0 != erg) && (EEXIST != errno) ) FPRINTF (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE1, strerror (errno)); } } else { if (0 != stat (FIFO_FILE2, &st)) { GNUNET_break (0 == (erg = mkfifo (FIFO_FILE2, 0666))); if ( (0 != erg) && (EEXIST != errno) ) FPRINTF (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE2, strerror (errno)); } } if (0 == strcmp (argv[1], "1")) { first = 1; fpin = fopen (FIFO_FILE1, "r"); if (NULL == fpin) { FPRINTF (stderr, "fopen of read FIFO_FILE1 failed: %s\n", STRERROR (errno)); goto end; } if (NULL == (fpout = fopen (FIFO_FILE2, "w"))) { GNUNET_break (0 == mkfifo (FIFO_FILE2, 0666)); fpout = fopen (FIFO_FILE2, "w"); } if (NULL == fpout) { FPRINTF (stderr, "fopen of write FIFO_FILE2 failed: %s\n", STRERROR (errno)); goto end; } } else { first = 0; if (NULL == (fpout = fopen (FIFO_FILE1, "w"))) { GNUNET_break (0 == mkfifo (FIFO_FILE1, 0666)); fpout = fopen (FIFO_FILE1, "w"); } if (NULL == fpout) { FPRINTF (stderr, "fopen of write FIFO_FILE1 failed: %s\n", STRERROR (errno)); goto end; } fpin = fopen (FIFO_FILE2, "r"); if (NULL == fpin) { FPRINTF (stderr, "fopen of read FIFO_FILE2 failed: %s\n", STRERROR (errno)); goto end; } } fdpin = fileno (fpin); GNUNET_assert (fpin >= 0); if (fdpin >= FD_SETSIZE) { FPRINTF (stderr, "File fdpin number too large (%d > %u)\n", fdpin, (unsigned int) FD_SETSIZE); goto end; } fdpout = fileno (fpout); GNUNET_assert (fdpout >= 0); if (fdpout >= FD_SETSIZE) { FPRINTF (stderr, "File fdpout number too large (%d > %u)\n", fdpout, (unsigned int) FD_SETSIZE); goto end; } signal (SIGINT, &sigfunc); signal (SIGTERM, &sigfunc); signal (GNUNET_TERM_SIG, &sigfunc); write_std.size = 0; write_std.pos = 0; write_pout.size = 0; write_pout.pos = 0; stdin_mst = GNUNET_SERVER_mst_create (&stdin_send, &write_pout); file_in_mst = GNUNET_SERVER_mst_create (&file_in_send, &write_std); /* Send 'random' mac address */ macaddr.mac[0] = 0x13; macaddr.mac[1] = 0x22; macaddr.mac[2] = 0x33; macaddr.mac[3] = 0x44; macaddr.mac[4] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 256); macaddr.mac[5] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 256); write_std.size = send_mac_to_plugin (write_std.buf, &macaddr); while (0 == closeprog) { maxfd = -1; tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO (&rfds); FD_ZERO (&wfds); /* if output queue is empty, read */ if (0 == write_pout.size) { FD_SET (STDIN_FILENO, &rfds); maxfd = MAX (STDIN_FILENO, maxfd); } if (0 == write_std.size) { FD_SET (fdpin, &rfds); maxfd = MAX (fdpin, maxfd); } /* if there is something to write, try to write */ if (0 < write_std.size) { FD_SET (STDOUT_FILENO, &wfds); maxfd = MAX (maxfd, STDOUT_FILENO); } if (0 < write_pout.size) { FD_SET (fdpout, &wfds); maxfd = MAX (maxfd, fdpout); } retval = select (maxfd + 1, &rfds, &wfds, NULL, &tv); if ((-1 == retval) && (EINTR == errno)) continue; if (0 > retval) { FPRINTF (stderr, "select failed: %s\n", STRERROR (errno)); closeprog = 1; break; } if (FD_ISSET (STDOUT_FILENO, &wfds)) { ret = write (STDOUT_FILENO, write_std.buf + write_std.pos, write_std.size - write_std.pos); if (0 > ret) { closeprog = 1; FPRINTF (stderr, "Write ERROR to STDOUT_FILENO: %s\n", STRERROR (errno)); break; } else { write_std.pos += ret; /* check if finished writing */ if (write_std.pos == write_std.size) { write_std.pos = 0; write_std.size = 0; } } } if (FD_ISSET (fdpout, &wfds)) { ret = write (fdpout, write_pout.buf + write_pout.pos, write_pout.size - write_pout.pos); if (0 > ret) { closeprog = 1; FPRINTF (stderr, "Write ERROR to fdpout failed: %s\n", STRERROR (errno)); } else { write_pout.pos += ret; /* check if finished writing */ if (write_pout.pos == write_pout.size) { write_pout.pos = 0; write_pout.size = 0; } } } if (FD_ISSET (STDIN_FILENO, &rfds)) { readsize = read (STDIN_FILENO, readbuf, sizeof (readbuf)); if (0 > readsize) { closeprog = 1; FPRINTF (stderr, "Error reading from STDIN_FILENO: %s\n", STRERROR (errno)); } else if (0 < readsize) { GNUNET_SERVER_mst_receive (stdin_mst, NULL, readbuf, readsize, GNUNET_NO, GNUNET_NO); } else { /* eof */ closeprog = 1; } } if (FD_ISSET (fdpin, &rfds)) { readsize = read (fdpin, readbuf, sizeof (readbuf)); if (0 > readsize) { closeprog = 1; FPRINTF (stderr, "Error reading from fdpin: %s\n", STRERROR (errno)); break; } else if (0 < readsize) { GNUNET_SERVER_mst_receive (file_in_mst, NULL, readbuf, readsize, GNUNET_NO, GNUNET_NO); } else { /* eof */ closeprog = 1; } } } end: /* clean up */ if (NULL != stdin_mst) GNUNET_SERVER_mst_destroy (stdin_mst); if (NULL != file_in_mst) GNUNET_SERVER_mst_destroy (file_in_mst); if (NULL != fpout) fclose (fpout); if (NULL != fpin) fclose (fpin); if (1 == first) { (void) unlink (FIFO_FILE1); (void) unlink (FIFO_FILE2); } return 0; } gnunet-0.10.1/src/transport/test_transport_api_bluetooth_peer1.conf0000644000175000017500000000161112225230043022601 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p1/ [transport-bluetooth] INTERFACE = hci0 TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock #PREFIX = xterm -T transport2 -e gdb --command=cmd --args #PREFIX = valgrind --leak-check=full --show-reachable=yes --main-stacksize=104857600 #PREFIX = valgrind --leak-check=full --show-reachable=yes #PREFIX = valgrind --leak-check=full #PREFIX = valgrind --tool=massif #PREFIX = gdbserver :2345 gnunet-0.10.1/src/transport/test_quota_compliance_bluetooth_peer2.conf0000644000175000017500000000114012225230043023235 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p2/ [transport-bluetooth] INTERFACE = hci1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/plugin_transport_http_server.c0000644000175000017500000027365512316473377021077 00000000000000/* This file is part of GNUnet (C) 2002-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_http_server.c * @brief HTTP/S server transport plugin * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_plugin.h" #include "gnunet_nat_lib.h" #include "plugin_transport_http_common.h" #include #if BUILD_HTTPS #define PLUGIN_NAME "https_server" #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_server_init #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_server_done #else #define PLUGIN_NAME "http_server" #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_server_init #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_server_done #endif #define HTTP_ERROR_RESPONSE "404 Not Found

Not Found

The requested URL was not found on this server.


" #define _RECEIVE 0 #define _SEND 1 /** * Enable output for debbuging URL's of incoming requests */ #define DEBUG_URL_PARSE GNUNET_NO /** * Encapsulation of all of the state of the plugin. */ struct Plugin; /** * Session handle for connections. */ struct Session { /** * Stored in a linked list. */ struct Session *next; /** * Stored in a linked list. */ struct Session *prev; /** * To whom are we talking to (set to our identity * if we are still waiting for the welcome message) */ struct GNUNET_PeerIdentity target; /** * Pointer to the global plugin struct. */ struct HTTP_Server_Plugin *plugin; /** * next pointer for double linked list */ struct HTTP_Message *msg_head; /** * previous pointer for double linked list */ struct HTTP_Message *msg_tail; /** * Message stream tokenizer for incoming data */ struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk; /** * Client send handle */ struct ServerConnection *server_recv; /** * Client send handle */ struct ServerConnection *server_send; /** * Address */ struct GNUNET_HELLO_Address *address; /** * Unique HTTP/S connection tag for this connection */ uint32_t tag; /** * ATS network type in NBO */ uint32_t ats_address_network_type; /** * Was session given to transport service? */ int session_passed; /** * Did we immediately end the session in disconnect_cb */ int session_ended; /** * Are incoming connection established at the moment */ int connect_in_progress; /** * Absolute time when to receive data again * Used for receive throttling */ struct GNUNET_TIME_Absolute next_receive; /** * Session timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; struct ServerConnection { /** * _RECV or _SEND */ int direction; /** * Should this connection get disconnected? GNUNET_YES/NO */ int disconnect; /** * For PUT connections: Is this the first or last callback with size 0 */ int connected; /** * The session this server connection belongs to */ struct Session *session; /** * The MHD connection */ struct MHD_Connection *mhd_conn; /** * The MHD daemon */ struct MHD_Daemon *mhd_daemon; }; /** * Encapsulation of all of the state of the plugin. */ struct HTTP_Server_Plugin { /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * Linked list head of open sessions. */ struct Session *head; /** * Linked list tail of open sessions. */ struct Session *tail; /** * Plugin name */ char *name; /** * Protocol */ char *protocol; /** * My options to be included in the address */ uint32_t options; /** * External address */ char *external_hostname; /** * Verify external address */ int verify_external_hostname; /** * Maximum number of sockets the plugin can use * Each http inbound /outbound connections are two connections */ unsigned int max_connections; /** * Current number of sockets the plugin can use * Each http inbound /outbound connections are two connections */ unsigned int cur_connections; /** * Did we immediately end the session in disconnect_cb */ int in_shutdown; /** * Length of peer id */ int peer_id_length; /** * External hostname the plugin can be connected to, can be different to * the host's FQDN, used e.g. for reverse proxying */ struct GNUNET_HELLO_Address *ext_addr; /** * Notify transport only about external address */ unsigned int external_only; /** * use IPv6 */ uint16_t use_ipv6; /** * use IPv4 */ uint16_t use_ipv4; /** * Port used */ uint16_t port; /** * Task calling transport service about external address */ GNUNET_SCHEDULER_TaskIdentifier notify_ext_task; /** * NAT handle & address management */ struct GNUNET_NAT_Handle *nat; /** * List of own addresses */ /** * IPv4 addresses DLL head */ struct HttpAddressWrapper *addr_head; /** * IPv4 addresses DLL tail */ struct HttpAddressWrapper *addr_tail; /** * IPv4 server socket to bind to */ struct sockaddr_in *server_addr_v4; /** * IPv6 server socket to bind to */ struct sockaddr_in6 *server_addr_v6; /** * MHD IPv4 task */ GNUNET_SCHEDULER_TaskIdentifier server_v4_task; /** * MHD IPv6 task */ GNUNET_SCHEDULER_TaskIdentifier server_v6_task; /** * The IPv4 server is scheduled to run asap */ int server_v4_immediately; /** * The IPv6 server is scheduled to run asap */ int server_v6_immediately; /** * MHD IPv4 daemon */ struct MHD_Daemon *server_v4; /** * MHD IPv4 daemon */ struct MHD_Daemon *server_v6; #if BUILD_HTTPS /** * Crypto related * * Example: * * Use RC4-128 instead of AES: * NONE:+VERS-TLS1.0:+ARCFOUR-128:+SHA1:+RSA:+COMP-NULL * */ char *crypto_init; /** * TLS key */ char *key; /** * TLS certificate */ char *cert; #endif }; /** * Wrapper to manage addresses */ struct HttpAddressWrapper { /** * Linked list next */ struct HttpAddressWrapper *next; /** * Linked list previous */ struct HttpAddressWrapper *prev; struct HttpAddress *address; size_t addrlen; }; /** * Message to send using http */ struct HTTP_Message { /** * next pointer for double linked list */ struct HTTP_Message *next; /** * previous pointer for double linked list */ struct HTTP_Message *prev; /** * buffer containing data to send */ char *buf; /** * amount of data already sent */ size_t pos; /** * buffer length */ size_t size; /** * HTTP/S specific overhead */ size_t overhead; /** * Continuation function to call once the transmission buffer * has again space available. NULL if there is no * continuation to call. */ GNUNET_TRANSPORT_TransmitContinuation transmit_cont; /** * Closure for transmit_cont. */ void *transmit_cont_cls; }; /** * Start session timeout for session s * @param s the session */ static void server_start_session_timeout (struct Session *s); /** * Increment session timeout due to activity for session s * @param s the session */ static void server_reschedule_session_timeout (struct Session *s); /** * Cancel timeout for session s * @param s the session */ static void server_stop_session_timeout (struct Session *s); /** * Disconnect session @a s * * @param cls closure with the `struct HTTP_Server_Plugin` * @param s the session * @return #GNUNET_OK on success */ static int http_server_plugin_disconnect_session (void *cls, struct Session *s); /** * Does session s exist? * * @param plugin the plugin handle * @param s the session * @return #GNUNET_YES on success, #GNUNET_NO on error */ static int server_exist_session (struct HTTP_Server_Plugin *plugin, struct Session *s); /** * Reschedule the execution of both IPv4 and IPv6 server * @param plugin the plugin * @param server which server to schedule v4 or v6? * @param now #GNUNET_YES to schedule execution immediately, #GNUNET_NO to wait * until timeout */ static void server_reschedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *server, int now); /** * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param session which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in @a msgbuf * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for @a cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t http_server_plugin_send (void *cls, struct Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct HTTP_Server_Plugin *plugin = cls; struct HTTP_Message *msg; int bytes_sent = 0; char *stat_txt; GNUNET_assert (plugin != NULL); GNUNET_assert (session != NULL); if (GNUNET_NO == server_exist_session (plugin, session)) { GNUNET_break (0); return GNUNET_SYSERR; } if (NULL == session->server_send) { if (GNUNET_NO == session->connect_in_progress) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, session->plugin->name, "Session %p/connection %p: Sending message with %u bytes to peer `%s' with FAILED\n", session, session->server_send, msgbuf_size, GNUNET_i2s (&session->target)); GNUNET_break (0); return GNUNET_SYSERR; } } else { if (GNUNET_YES == session->server_send->disconnect) return GNUNET_SYSERR; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, session->plugin->name, "Session %p/connection %p: Sending message with %u to peer `%s' with \n", session, session->server_send, msgbuf_size, GNUNET_i2s (&session->target)); /* create new message and schedule */ bytes_sent = sizeof (struct HTTP_Message) + msgbuf_size; msg = GNUNET_malloc (bytes_sent); msg->next = NULL; msg->size = msgbuf_size; msg->pos = 0; msg->buf = (char *) &msg[1]; msg->transmit_cont = cont; msg->transmit_cont_cls = cont_cls; memcpy (msg->buf, msgbuf, msgbuf_size); GNUNET_CONTAINER_DLL_insert_tail (session->msg_head, session->msg_tail, msg); GNUNET_asprintf (&stat_txt, "# bytes currently in %s_server buffers", plugin->protocol); GNUNET_STATISTICS_update (plugin->env->stats, stat_txt, msgbuf_size, GNUNET_NO); GNUNET_free (stat_txt); if (NULL != session->server_send) { server_reschedule (session->plugin, session->server_send->mhd_daemon, GNUNET_YES); } return bytes_sent; } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuationc). * * @param cls closure * @param target peer from which to disconnect */ static void http_server_plugin_disconnect_peer (void *cls, const struct GNUNET_PeerIdentity *target) { struct HTTP_Server_Plugin *plugin = cls; struct Session *next; struct Session *pos; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Transport tells me to disconnect `%s'\n", GNUNET_i2s (target)); next = plugin->head; while (NULL != (pos = next)) { next = pos->next; if (0 == memcmp (target, &pos->target, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Disconnecting session %p to `%s'\n", pos, GNUNET_i2s (target)); http_server_plugin_disconnect_session (plugin, pos); } } } /** * Another peer has suggested an address for this * peer and transport plugin. Check that this could be a valid * address. If so, consider adding it to the list * of addresses. * * @param cls closure * @param addr pointer to the address * @param addrlen length of @a addr * @return #GNUNET_OK if this is a plausible address for this peer * and transport */ static int http_server_plugin_address_suggested (void *cls, const void *addr, size_t addrlen) { struct HTTP_Server_Plugin *plugin = cls; struct HttpAddressWrapper *next; struct HttpAddressWrapper *pos; const struct HttpAddress *haddr = addr; if ((NULL != plugin->ext_addr) && GNUNET_YES == (http_common_cmp_addresses (addr, addrlen, plugin->ext_addr->address, plugin->ext_addr->address_length))) { /* Checking HTTP_OPTIONS_VERIFY_CERTIFICATE option for external hostname */ if ((ntohl (haddr->options) & HTTP_OPTIONS_VERIFY_CERTIFICATE) != (plugin->options & HTTP_OPTIONS_VERIFY_CERTIFICATE)) return GNUNET_NO; /* VERIFY option not set as required! */ return GNUNET_OK; } next = plugin->addr_head; while (NULL != (pos = next)) { next = pos->next; if (GNUNET_YES == (http_common_cmp_addresses(addr, addrlen, pos->address, pos->addrlen))) return GNUNET_OK; } return GNUNET_NO; } /** * Creates a new outbound session the transport * service will use to send data to the peer * * Since HTTP/S server cannot create sessions, always return NULL * * @param cls the plugin * @param address the address * @return always NULL */ static struct Session * http_server_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { return NULL; } /** * Deleting the session * Must not be used afterwards * * @param cls closure with the `struct HTTP_ServerPlugin` * @param s the session to delete * @return #GNUNET_OK on success */ static int server_delete_session (void *cls, struct Session *s) { struct HTTP_Server_Plugin *plugin = cls; struct HTTP_Message *msg; struct HTTP_Message *tmp; server_stop_session_timeout(s); GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s); msg = s->msg_head; while (NULL != msg) { tmp = msg->next; GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); if (NULL != msg->transmit_cont) msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR, msg->size, msg->pos + msg->overhead); GNUNET_free (msg); msg = tmp; } if (NULL != s->msg_tk) { GNUNET_SERVER_mst_destroy (s->msg_tk); s->msg_tk = NULL; } GNUNET_HELLO_address_free (s->address); GNUNET_free_non_null (s->server_recv); GNUNET_free_non_null (s->server_send); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p destroyed\n", s); GNUNET_free (s); return GNUNET_OK; } /** * Cancel timeout for session s * * @param s the session */ static void server_stop_session_timeout (struct Session *s) { GNUNET_assert (NULL != s); if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task) { GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (TIMEOUT_LOG, "Timeout stopped for session %p\n", s); } } /** * Function that queries MHD's select sets and * starts the task waiting for them. * @param plugin plugin * @param daemon_handle the MHD daemon handle * @param now schedule immediately * @return task identifier */ static GNUNET_SCHEDULER_TaskIdentifier server_schedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *daemon_handle, int now); /** * Reschedule the execution of both IPv4 and IPv6 server * @param plugin the plugin * @param server which server to schedule v4 or v6? * @param now #GNUNET_YES to schedule execution immediately, #GNUNET_NO to wait * until timeout */ static void server_reschedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *server, int now) { if ((server == plugin->server_v4) && (plugin->server_v4 != NULL)) { if (GNUNET_YES == plugin->server_v4_immediately) return; /* No rescheduling, server will run asap */ if (GNUNET_YES == now) plugin->server_v4_immediately = GNUNET_YES; if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->server_v4_task); plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK; } plugin->server_v4_task = server_schedule (plugin, plugin->server_v4, now); } if ((server == plugin->server_v6) && (plugin->server_v6 != NULL)) { if (GNUNET_YES == plugin->server_v6_immediately) return; /* No rescheduling, server will run asap */ if (GNUNET_YES == now) plugin->server_v6_immediately = GNUNET_YES; if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->server_v6_task); plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK; } plugin->server_v6_task = server_schedule (plugin, plugin->server_v6, now); } } /** * Disconnect session @a s * * @param cls closure with the `struct HTTP_Server_Plugin` * @param s the session * @return #GNUNET_OK on success */ static int http_server_plugin_disconnect_session (void *cls, struct Session *s) { struct HTTP_Server_Plugin *plugin = cls; struct ServerConnection * send; struct ServerConnection * recv; if (GNUNET_NO == server_exist_session (plugin, s)) { GNUNET_break (0); return GNUNET_SYSERR; } send = (struct ServerConnection *) s->server_send; if (s->server_send != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Server: %p / %p Terminating inbound PUT session to peer `%s'\n", s, s->server_send, GNUNET_i2s (&s->target)); send->disconnect = GNUNET_YES; MHD_set_connection_option (send->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, 1); server_reschedule (s->plugin, send->mhd_daemon, GNUNET_YES); } recv = (struct ServerConnection *) s->server_recv; if (recv != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Server: %p / %p Terminating inbound GET session to peer `%s'\n", s, s->server_recv, GNUNET_i2s (&s->target)); recv->disconnect = GNUNET_YES; MHD_set_connection_option (recv->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, 1); server_reschedule (s->plugin, recv->mhd_daemon, GNUNET_YES); } return GNUNET_OK; } /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int http_server_query_keepalive_factor (void *cls) { return 3; } static void http_server_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { struct HTTP_Server_Plugin *plugin = cls; if (GNUNET_NO == server_exist_session (plugin, session)) return; server_reschedule_session_timeout (session); } /** * Tell MHD that the connection should timeout after @a to seconds. * * @param plugin our plugin * @param s session for which the timeout changes * @param to timeout in seconds */ static void server_mhd_connection_timeout (struct HTTP_Server_Plugin *plugin, struct Session *s, unsigned int to) { /* Setting timeouts for other connections */ if (NULL != s->server_recv) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Setting timeout for %p to %u sec.\n", s->server_recv, to); MHD_set_connection_option (s->server_recv->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, to); server_reschedule (plugin, s->server_recv->mhd_daemon, GNUNET_NO); } if (NULL != s->server_send) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Setting timeout for %p to %u sec.\n", s->server_send, to); MHD_set_connection_option (s->server_send->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, to); server_reschedule (plugin, s->server_send->mhd_daemon, GNUNET_NO); } } /** * Parse incoming URL for tag and target * * @param plugin plugin * @param url incoming url * @param target where to store the target * @param tag where to store the tag * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int server_parse_url (struct HTTP_Server_Plugin *plugin, const char *url, struct GNUNET_PeerIdentity *target, uint32_t *tag) { char * tag_start = NULL; char * tag_end = NULL; char * target_start = NULL; char * separator = NULL; unsigned int hash_length; unsigned long int ctag; /* URL parsing * URL is valid if it is in the form [prefix with (multiple) '/'][peerid[103];tag]*/ if (NULL == url) { GNUNET_break (0); return GNUNET_SYSERR; } /* convert tag */ /* find separator */ separator = strrchr (url, ';'); if (NULL == separator) { if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } tag_start = separator + 1; if (strlen (tag_start) == 0) { /* No tag after separator */ if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } ctag = strtoul (tag_start, &tag_end, 10); if (ctag == 0) { /* tag == 0 , invalid */ if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } if ((ctag == ULONG_MAX) && (ERANGE == errno)) { /* out of range: > ULONG_MAX */ if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } if (ctag > UINT32_MAX) { /* out of range: > UINT32_MAX */ if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } (*tag) = (uint32_t) ctag; if (NULL == tag_end) { /* no char after tag */ if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } if (url[strlen(url)] != tag_end[0]) { /* there are more not converted chars after tag */ if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } if (DEBUG_URL_PARSE) GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Found tag `%u' in url\n", (*tag)); /* convert peer id */ target_start = strrchr (url, '/'); if (NULL == target_start) { /* no leading '/' */ target_start = (char *) url; } target_start++; hash_length = separator - target_start; if (hash_length != plugin->peer_id_length) { /* no char after tag */ if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (target_start, hash_length, &target->public_key)) { /* hash conversion failed */ if (DEBUG_URL_PARSE) GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Found target `%s' in URL\n", GNUNET_i2s_full (target)); return GNUNET_OK; } /** * Lookup a mhd connection and create one if none is found * * @param plugin the plugin handle * @param mhd_connection the incoming mhd_connection * @param url incoming requested URL * @param method PUT or GET * @return the server connecetion */ static struct ServerConnection * server_lookup_connection (struct HTTP_Server_Plugin *plugin, struct MHD_Connection *mhd_connection, const char *url, const char *method) { struct Session *s = NULL; struct ServerConnection *sc = NULL; const union MHD_ConnectionInfo *conn_info; struct HttpAddress *addr; struct GNUNET_ATS_Information ats; struct GNUNET_PeerIdentity target; size_t addr_len; uint32_t tag = 0; int direction = GNUNET_SYSERR; unsigned int to; conn_info = MHD_get_connection_info (mhd_connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS); if ((conn_info->client_addr->sa_family != AF_INET) && (conn_info->client_addr->sa_family != AF_INET6)) return NULL; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "New %s connection from %s\n", method, url); if (GNUNET_SYSERR == server_parse_url (plugin, url, &target, &tag)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Invalid url %s\n", url); return NULL; } if (0 == strcmp (MHD_HTTP_METHOD_PUT, method)) direction = _RECEIVE; else if (0 == strcmp (MHD_HTTP_METHOD_GET, method)) direction = _SEND; else { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Invalid method %s connection from %s\n", method, url); return NULL; } plugin->cur_connections++; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "New %s connection from %s with tag %u (%u of %u)\n", method, GNUNET_i2s (&target), tag, plugin->cur_connections, plugin->max_connections); /* find duplicate session */ s = plugin->head; while (s != NULL) { if ((0 == memcmp (&s->target, &target, sizeof (struct GNUNET_PeerIdentity))) && (s->tag == tag)) break; s = s->next; } if (s != NULL) { if ((_RECEIVE == direction) && (NULL != s->server_recv)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Duplicate PUT connection from `%s' tag %u, dismissing new connection\n", GNUNET_i2s (&target), tag); return NULL; } if ((_SEND == direction) && (NULL != s->server_send)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Duplicate GET connection from `%s' tag %u, dismissing new connection\n", GNUNET_i2s (&target), tag); return NULL; } } else { /* create new session */ addr = NULL; switch (conn_info->client_addr->sa_family) { case (AF_INET): addr = http_common_address_from_socket (plugin->protocol, conn_info->client_addr, sizeof (struct sockaddr_in)); addr_len = http_common_address_get_size (addr); ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in)); break; case (AF_INET6): addr = http_common_address_from_socket (plugin->protocol, conn_info->client_addr, sizeof (struct sockaddr_in6)); addr_len = http_common_address_get_size (addr); ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in6)); break; default: /* external host name */ ats.type = htonl (GNUNET_ATS_NETWORK_TYPE); ats.type = htonl (GNUNET_ATS_NET_WAN); return NULL; } s = GNUNET_new (struct Session); memcpy (&s->target, &target, sizeof (struct GNUNET_PeerIdentity)); s->plugin = plugin; s->address = GNUNET_HELLO_address_allocate (&s->target, PLUGIN_NAME, addr, addr_len, GNUNET_HELLO_ADDRESS_INFO_INBOUND); s->ats_address_network_type = ats.value; s->next_receive = GNUNET_TIME_UNIT_ZERO_ABS; s->tag = tag; s->server_recv = NULL; s->server_send = NULL; s->session_passed = GNUNET_NO; s->session_ended = GNUNET_NO; s->connect_in_progress = GNUNET_YES; server_start_session_timeout(s); GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Creating new session %p for peer `%s' connecting from `%s'\n", s, GNUNET_i2s (&target), http_common_plugin_address_to_string (NULL, plugin->protocol, addr, addr_len)); GNUNET_free_non_null (addr); } sc = GNUNET_new (struct ServerConnection); if (conn_info->client_addr->sa_family == AF_INET) sc->mhd_daemon = plugin->server_v4; if (conn_info->client_addr->sa_family == AF_INET6) sc->mhd_daemon = plugin->server_v6; sc->mhd_conn = mhd_connection; sc->direction = direction; sc->connected = GNUNET_NO; sc->session = s; if (direction == _SEND) s->server_send = sc; if (direction == _RECEIVE) s->server_recv = sc; if ((NULL != s->server_send) && (NULL != s->server_recv)) { s->connect_in_progress = GNUNET_NO; /* PUT and GET are connected */ plugin->env->session_start (NULL, s->address ,s, NULL, 0); } if ((NULL == s->server_recv) || (NULL == s->server_send)) { to = (HTTP_SERVER_NOT_VALIDATED_TIMEOUT.rel_value_us / 1000LL / 1000LL); MHD_set_connection_option (mhd_connection, MHD_CONNECTION_OPTION_TIMEOUT, to); server_reschedule (plugin, sc->mhd_daemon, GNUNET_NO); } else { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p for peer `%s' fully connected\n", s, GNUNET_i2s (&target)); to = (HTTP_SERVER_SESSION_TIMEOUT.rel_value_us / 1000LL / 1000LL); server_mhd_connection_timeout (plugin, s, to); } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Setting timeout for %p to %u sec.\n", sc, to); return sc; } /** * Lookup a session for a server connection * * @param plugin the plugin * @param sc the server connection * @return the session found or NULL */ static struct Session * server_lookup_session (struct HTTP_Server_Plugin *plugin, struct ServerConnection * sc) { struct Session *s; for (s = plugin->head; NULL != s; s = s->next) if ((s->server_recv == sc) || (s->server_send == sc)) return s; return NULL; } static int server_exist_session (struct HTTP_Server_Plugin *plugin, struct Session *s) { struct Session * head; for (head = plugin->head; head != NULL; head = head->next) if (head == s) return GNUNET_YES; return GNUNET_NO; } /** * Callback called by MHD when it needs data to send * * @param cls current session * @param pos position in buffer * @param buf the buffer to write data to * @param max max number of bytes available in buffer * @return bytes written to buffer */ static ssize_t server_send_callback (void *cls, uint64_t pos, char *buf, size_t max) { struct Session *s = cls; ssize_t bytes_read = 0; struct HTTP_Message *msg; char *stat_txt; if (GNUNET_NO == server_exist_session (s->plugin, s)) return 0; msg = s->msg_head; if (NULL != msg) { /* sending */ bytes_read = GNUNET_MIN (msg->size - msg->pos, max); memcpy (buf, &msg->buf[msg->pos], bytes_read); msg->pos += bytes_read; /* removing message */ if (msg->pos == msg->size) { GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg); if (NULL != msg->transmit_cont) msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK, msg->size, msg->size + msg->overhead); GNUNET_free (msg); } } if (0 < bytes_read) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name, "Sent %u bytes to peer `%s' with session %p \n", bytes_read, GNUNET_i2s (&s->target), s); GNUNET_asprintf (&stat_txt, "# bytes currently in %s_server buffers", s->plugin->protocol); GNUNET_STATISTICS_update (s->plugin->env->stats, stat_txt, -bytes_read, GNUNET_NO); GNUNET_free (stat_txt); GNUNET_asprintf (&stat_txt, "# bytes transmitted via %s_server", s->plugin->protocol); GNUNET_STATISTICS_update (s->plugin->env->stats, stat_txt, bytes_read, GNUNET_NO); GNUNET_free (stat_txt); } return bytes_read; } /** * Callback called by MessageStreamTokenizer when a message has arrived * * @param cls current session as closure * @param client client * @param message the message to be forwarded to transport service * @return #GNUNET_OK */ static int server_receive_mst_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct Session *s = cls; struct HTTP_Server_Plugin *plugin = s->plugin; struct GNUNET_ATS_Information atsi; struct GNUNET_TIME_Relative delay; char *stat_txt; if (GNUNET_NO == server_exist_session (s->plugin, s)) return GNUNET_OK; atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE); atsi.value = s->ats_address_network_type; GNUNET_break (s->ats_address_network_type != ntohl (GNUNET_ATS_NET_UNSPECIFIED)); delay = plugin->env->receive (plugin->env->cls, s->address, s, message); plugin->env->update_address_metrics (plugin->env->cls, s->address, s, &atsi, 1); GNUNET_asprintf (&stat_txt, "# bytes received via %s_server", plugin->protocol); GNUNET_STATISTICS_update (plugin->env->stats, stat_txt, ntohs (message->size), GNUNET_NO); GNUNET_free (stat_txt); s->session_passed = GNUNET_YES; s->next_receive = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay); if (delay.rel_value_us > 0) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Peer `%s' address `%s' next read delayed for %s\n", GNUNET_i2s (&s->target), http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); } server_reschedule_session_timeout (s); return GNUNET_OK; } /** * MHD callback for a new incoming connection * * @param cls the plugin handle * @param mhd_connection the mhd connection * @param url the requested URL * @param method GET or PUT * @param version HTTP version * @param upload_data upload data * @param upload_data_size sizeof upload data * @param httpSessionCache the session cache to remember the connection * @return MHD_YES if connection is accepted, MHD_NO on reject */ static int server_access_cb (void *cls, struct MHD_Connection *mhd_connection, const char *url, const char *method, const char *version, const char *upload_data, size_t * upload_data_size, void **httpSessionCache) { struct HTTP_Server_Plugin *plugin = cls; int res = MHD_YES; struct ServerConnection *sc = *httpSessionCache; struct Session *s; struct MHD_Response *response; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Access from connection %p (%u of %u) for `%s' `%s' url `%s' with upload data size %u\n"), sc, plugin->cur_connections, plugin->max_connections, method, version, url, (*upload_data_size)); GNUNET_assert (cls != NULL); if (sc == NULL) { /* new connection */ sc = server_lookup_connection (plugin, mhd_connection, url, method); if (sc != NULL) { (*httpSessionCache) = sc; } else { response = MHD_create_response_from_data (strlen (HTTP_ERROR_RESPONSE), HTTP_ERROR_RESPONSE, MHD_NO, MHD_NO); MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); res = MHD_queue_response (mhd_connection, MHD_HTTP_NOT_FOUND, response); MHD_destroy_response (response); return res; } } else { /* 'old' connection */ if (NULL == server_lookup_session (plugin, sc)) { /* Session was already disconnected */ return MHD_NO; } } /* existing connection */ sc = (*httpSessionCache); s = sc->session; GNUNET_assert (NULL != s); /* connection is to be disconnected */ if (sc->disconnect == GNUNET_YES) { /* Sent HTTP/1.1: 200 OK as response */ response = MHD_create_response_from_data (strlen ("Thank you!"), "Thank you!", MHD_NO, MHD_NO); MHD_queue_response (mhd_connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return MHD_YES; } GNUNET_assert (s != NULL); if (sc->direction == _SEND) { response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 32 * 1024, &server_send_callback, s, NULL); MHD_queue_response (mhd_connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return MHD_YES; } if (sc->direction == _RECEIVE) { if ((*upload_data_size == 0) && (sc->connected == GNUNET_NO)) { /* (*upload_data_size == 0) first callback when header are passed */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p / Connection %p: Peer `%s' PUT on address `%s' connected\n", s, sc, GNUNET_i2s (&s->target), http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length)); sc->connected = GNUNET_YES; return MHD_YES; } else if ((*upload_data_size == 0) && (sc->connected == GNUNET_YES)) { /* (*upload_data_size == 0) when upload is complete */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p / Connection %p: Peer `%s' PUT on address `%s' finished upload\n", s, sc, GNUNET_i2s (&s->target), http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length)); sc->connected = GNUNET_NO; /* Sent HTTP/1.1: 200 OK as PUT Response\ */ response = MHD_create_response_from_data (strlen ("Thank you!"), "Thank you!", MHD_NO, MHD_NO); MHD_queue_response (mhd_connection, MHD_HTTP_OK, response); MHD_destroy_response (response); return MHD_YES; } else if ((*upload_data_size > 0) && (sc->connected == GNUNET_YES)) { /* (*upload_data_size > 0) for every segment received */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Session %p / Connection %p: Peer `%s' PUT on address `%s' received %u bytes\n", s, sc, GNUNET_i2s (&s->target), http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length), *upload_data_size); struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); if ((s->next_receive.abs_value_us <= now.abs_value_us)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "PUT with %u bytes forwarded to MST\n", *upload_data_size); if (s->msg_tk == NULL) { s->msg_tk = GNUNET_SERVER_mst_create (&server_receive_mst_cb, s); } GNUNET_SERVER_mst_receive (s->msg_tk, s, upload_data, *upload_data_size, GNUNET_NO, GNUNET_NO); server_mhd_connection_timeout (plugin, s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us / 1000LL / 1000LL); (*upload_data_size) = 0; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %p / Connection %p: no inbound bandwidth available! Next read was delayed by %s\n", s, sc, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (s->next_receive), GNUNET_YES)); } return MHD_YES; } else { GNUNET_break (0); return MHD_NO; } } return res; } /** * Callback from MHD when a connection disconnects * * @param cls closure with the `struct HTTP_Server_Plugin *` * @param connection the disconnected MHD connection * @param httpSessionCache the pointer to distinguish */ static void server_disconnect_cb (void *cls, struct MHD_Connection *connection, void **httpSessionCache) { struct HTTP_Server_Plugin *plugin = cls; struct ServerConnection *sc = *httpSessionCache; struct Session *s = NULL; struct Session *t = NULL; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Disconnect for connection %p \n", sc); if (sc == NULL) return; if (NULL == (s = server_lookup_session (plugin, sc))) return; for (t = plugin->head; t != NULL; t = t->next) if (t == s) break; if (NULL == t) return; if (sc->direction == _SEND) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Peer `%s' connection %p, GET on address `%s' disconnected\n", GNUNET_i2s (&s->target), s->server_send, http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length)); s->server_send = NULL; if (NULL != (s->server_recv)) { s->server_recv->disconnect = GNUNET_YES; GNUNET_assert (NULL != s->server_recv->mhd_conn); #if MHD_VERSION >= 0x00090E00 MHD_set_connection_option (s->server_recv->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, 1); #endif server_reschedule (plugin, s->server_recv->mhd_daemon, GNUNET_NO); } } if (sc->direction == _RECEIVE) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Peer `%s' connection %p PUT on address `%s' disconnected\n", GNUNET_i2s (&s->target), s->server_recv, http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length)); s->server_recv = NULL; /* Do not terminate session when PUT disconnects if (NULL != (s->server_send)) { s->server_send->disconnect = GNUNET_YES; GNUNET_assert (NULL != s->server_send->mhd_conn); #if MHD_VERSION >= 0x00090E00 MHD_set_connection_option (s->server_send->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT, 1); #endif server_reschedule (plugin, s->server_send->mhd_daemon, GNUNET_NO); }*/ if (s->msg_tk != NULL) { GNUNET_SERVER_mst_destroy (s->msg_tk); s->msg_tk = NULL; } } GNUNET_free (sc); plugin->cur_connections--; if ((s->server_send == NULL) && (s->server_recv == NULL)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Peer `%s' on address `%s' disconnected\n", GNUNET_i2s (&s->target), http_common_plugin_address_to_string (NULL, plugin->protocol, s->address->address, s->address->address_length)); if ((GNUNET_YES == s->session_passed) && (GNUNET_NO == s->session_ended)) { /* Notify transport immediately that this session is invalid */ s->session_ended = GNUNET_YES; plugin->env->session_end (plugin->env->cls, s->address, s); } server_delete_session (plugin, s); } } /** * Check if incoming connection is accepted. * * @param cls plugin as closure * @param addr address of incoming connection * @param addr_len address length of incoming connection * @return MHD_YES if connection is accepted, MHD_NO if connection is rejected */ static int server_accept_cb (void *cls, const struct sockaddr *addr, socklen_t addr_len) { struct HTTP_Server_Plugin *plugin = cls; if (plugin->cur_connections <= plugin->max_connections) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Accepting connection (%u of %u) from `%s'\n"), plugin->cur_connections, plugin->max_connections, GNUNET_a2s (addr, addr_len)); return MHD_YES; } else { GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name, _("Server reached maximum number connections (%u), rejecting new connection\n"), plugin->max_connections); return MHD_NO; } } static void server_log (void *arg, const char *fmt, va_list ap) { char text[1024]; vsnprintf (text, sizeof (text), fmt, ap); va_end (ap); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server: %s\n", text); } /** * Call MHD IPv4 to process pending requests and then go back * and schedule the next run. * @param cls plugin as closure * @param tc task context */ static void server_v4_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct HTTP_Server_Plugin *plugin = cls; GNUNET_assert (cls != NULL); plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; #if 0 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Running IPv4 server\n"); #endif plugin->server_v4_immediately = GNUNET_NO; GNUNET_assert (MHD_YES == MHD_run (plugin->server_v4)); server_reschedule (plugin, plugin->server_v4, GNUNET_NO); } /** * Call MHD IPv6 to process pending requests and then go back * and schedule the next run. * @param cls plugin as closure * @param tc task context */ static void server_v6_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct HTTP_Server_Plugin *plugin = cls; GNUNET_assert (cls != NULL); plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; #if 0 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Running IPv6 server\n"); #endif plugin->server_v6_immediately = GNUNET_NO; GNUNET_assert (MHD_YES == MHD_run (plugin->server_v6)); server_reschedule (plugin, plugin->server_v6, GNUNET_NO); } /** * Function that queries MHD's select sets and * starts the task waiting for them. * * @param plugin plugin * @param daemon_handle the MHD daemon handle * @return gnunet task identifier */ static GNUNET_SCHEDULER_TaskIdentifier server_schedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon *daemon_handle, int now) { GNUNET_SCHEDULER_TaskIdentifier ret; fd_set rs; fd_set ws; fd_set es; struct GNUNET_NETWORK_FDSet *wrs; struct GNUNET_NETWORK_FDSet *wws; struct GNUNET_NETWORK_FDSet *wes; int max; MHD_UNSIGNED_LONG_LONG timeout; static unsigned long long last_timeout = 0; int haveto; struct GNUNET_TIME_Relative tv; if (GNUNET_YES == plugin->in_shutdown) return GNUNET_SCHEDULER_NO_TASK; ret = GNUNET_SCHEDULER_NO_TASK; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); wrs = GNUNET_NETWORK_fdset_create (); wes = GNUNET_NETWORK_fdset_create (); wws = GNUNET_NETWORK_fdset_create (); max = -1; GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max)); haveto = MHD_get_timeout (daemon_handle, &timeout); if (haveto == MHD_YES) { if (timeout != last_timeout) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "SELECT Timeout changed from %llu to %llu (ms)\n", last_timeout, timeout); last_timeout = timeout; } if (timeout <= GNUNET_TIME_UNIT_SECONDS.rel_value_us / 1000LL) tv.rel_value_us = (uint64_t) timeout * 1000LL; else tv = GNUNET_TIME_UNIT_SECONDS; } else tv = GNUNET_TIME_UNIT_SECONDS; /* Force immediate run, since we have outbound data to send */ if (now == GNUNET_YES) tv = GNUNET_TIME_UNIT_MILLISECONDS; GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1); if (daemon_handle == plugin->server_v4) { if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->server_v4_task); plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK; } #if 0 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Scheduling IPv4 server task in %llu ms\n", tv); #endif ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, tv, wrs, wws, &server_v4_run, plugin); } if (daemon_handle == plugin->server_v6) { if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->server_v6_task); plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK; } #if 0 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Scheduling IPv6 server task in %llu ms\n", tv); #endif ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, tv, wrs, wws, &server_v6_run, plugin); } GNUNET_NETWORK_fdset_destroy (wrs); GNUNET_NETWORK_fdset_destroy (wws); GNUNET_NETWORK_fdset_destroy (wes); return ret; } #if BUILD_HTTPS /** * Load ssl certificate from file * * @param file filename * @return content of the file */ static char * server_load_file (const char *file) { struct GNUNET_DISK_FileHandle *gn_file; uint64_t fsize; char *text = NULL; if (GNUNET_OK != GNUNET_DISK_file_size (file, &fsize, GNUNET_NO, GNUNET_YES)) return NULL; text = GNUNET_malloc (fsize + 1); gn_file = GNUNET_DISK_file_open (file, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_USER_READ); if (gn_file == NULL) { GNUNET_free (text); return NULL; } if (GNUNET_SYSERR == GNUNET_DISK_file_read (gn_file, text, fsize)) { GNUNET_free (text); GNUNET_DISK_file_close (gn_file); return NULL; } text[fsize] = '\0'; GNUNET_DISK_file_close (gn_file); return text; } #endif #if BUILD_HTTPS /** * Load ssl certificate * * @param plugin the plugin * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static int server_load_certificate (struct HTTP_Server_Plugin *plugin) { int res = GNUNET_OK; char *key_file; char *cert_file; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name, "KEY_FILE", &key_file)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, plugin->name, "CERT_FILE"); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name, "CERT_FILE", &cert_file)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, plugin->name, "CERT_FILE"); GNUNET_free (key_file); return GNUNET_SYSERR; } /* Get crypto init string from config. If not present, use * default values */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name, "CRYPTO_INIT", &plugin->crypto_init)) GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Using crypto init string `%s'\n", plugin->crypto_init); else GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Using default crypto init string \n"); /* read key & certificates from file */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to loading TLS certificate from key-file `%s' cert-file`%s'\n", key_file, cert_file); plugin->key = server_load_file (key_file); plugin->cert = server_load_file (cert_file); if ((plugin->key == NULL) || (plugin->cert == NULL)) { struct GNUNET_OS_Process *cert_creation; GNUNET_free_non_null (plugin->key); plugin->key = NULL; GNUNET_free_non_null (plugin->cert); plugin->cert = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No usable TLS certificate found, creating certificate\n"); errno = 0; cert_creation = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, "gnunet-transport-certificate-creation", "gnunet-transport-certificate-creation", key_file, cert_file, NULL); if (cert_creation == NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _ ("Could not create a new TLS certificate, program `gnunet-transport-certificate-creation' could not be started!\n")); GNUNET_free (key_file); GNUNET_free (cert_file); GNUNET_free_non_null (plugin->key); plugin->key = NULL; GNUNET_free_non_null (plugin->cert); plugin->cert = NULL; GNUNET_free_non_null (plugin->crypto_init); plugin->crypto_init = NULL; return GNUNET_SYSERR; } GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (cert_creation)); GNUNET_OS_process_destroy (cert_creation); plugin->key = server_load_file (key_file); plugin->cert = server_load_file (cert_file); } if ((plugin->key == NULL) || (plugin->cert == NULL)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _("No usable TLS certificate found and creating one at `%s/%s' failed!\n"), key_file, cert_file); GNUNET_free (key_file); GNUNET_free (cert_file); GNUNET_free_non_null (plugin->key); plugin->key = NULL; GNUNET_free_non_null (plugin->cert); plugin->cert = NULL; GNUNET_free_non_null (plugin->crypto_init); plugin->crypto_init = NULL; return GNUNET_SYSERR; } GNUNET_free (key_file); GNUNET_free (cert_file); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLS certificate loaded\n"); return res; } #endif /** * Start the HTTP server * * @param plugin the plugin handle * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ static int server_start (struct HTTP_Server_Plugin *plugin) { unsigned int timeout; char *msg; GNUNET_assert (NULL != plugin); #if BUILD_HTTPS if (GNUNET_SYSERR == server_load_certificate (plugin)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "Could not load or create server certificate! Loading plugin failed!\n"); return GNUNET_SYSERR; } #endif #if MHD_VERSION >= 0x00090E00 timeout = HTTP_SERVER_NOT_VALIDATED_TIMEOUT.rel_value_us / 1000LL / 1000LL; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "MHD can set timeout per connection! Default time out %u sec.\n", timeout); #else timeout = HTTP_SERVER_SESSION_TIMEOUT.rel_value_us / 1000LL / 1000LL; GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name, "MHD cannot set timeout per connection! Default time out %u sec.\n", timeout); #endif plugin->server_v4 = NULL; if (plugin->use_ipv4 == GNUNET_YES) { plugin->server_v4 = MHD_start_daemon ( #if VERBOSE_SERVER MHD_USE_DEBUG | #endif #if BUILD_HTTPS MHD_USE_SSL | #endif MHD_NO_FLAG, plugin->port, &server_accept_cb, plugin, &server_access_cb, plugin, MHD_OPTION_SOCK_ADDR, (struct sockaddr_in *) plugin->server_addr_v4, MHD_OPTION_CONNECTION_LIMIT, (unsigned int) plugin->max_connections, #if BUILD_HTTPS MHD_OPTION_HTTPS_PRIORITIES, plugin->crypto_init, MHD_OPTION_HTTPS_MEM_KEY, plugin->key, MHD_OPTION_HTTPS_MEM_CERT, plugin->cert, #endif MHD_OPTION_CONNECTION_TIMEOUT, timeout, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (2 * GNUNET_SERVER_MAX_MESSAGE_SIZE), MHD_OPTION_NOTIFY_COMPLETED, &server_disconnect_cb, plugin, MHD_OPTION_EXTERNAL_LOGGER, server_log, NULL, MHD_OPTION_END); if (plugin->server_v4 == NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "Failed to start %s IPv4 server component on port %u\n", plugin->name, plugin->port); } else server_reschedule (plugin, plugin->server_v4, GNUNET_NO); } plugin->server_v6 = NULL; if (plugin->use_ipv6 == GNUNET_YES) { plugin->server_v6 = MHD_start_daemon ( #if VERBOSE_SERVER MHD_USE_DEBUG | #endif #if BUILD_HTTPS MHD_USE_SSL | #endif MHD_USE_IPv6, plugin->port, &server_accept_cb, plugin, &server_access_cb, plugin, MHD_OPTION_SOCK_ADDR, (struct sockaddr_in6 *) plugin->server_addr_v6, MHD_OPTION_CONNECTION_LIMIT, (unsigned int) plugin->max_connections, #if BUILD_HTTPS MHD_OPTION_HTTPS_PRIORITIES, plugin->crypto_init, MHD_OPTION_HTTPS_MEM_KEY, plugin->key, MHD_OPTION_HTTPS_MEM_CERT, plugin->cert, #endif MHD_OPTION_CONNECTION_TIMEOUT, timeout, MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (2 * GNUNET_SERVER_MAX_MESSAGE_SIZE), MHD_OPTION_NOTIFY_COMPLETED, &server_disconnect_cb, plugin, MHD_OPTION_EXTERNAL_LOGGER, server_log, NULL, MHD_OPTION_END); if (plugin->server_v6 == NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "Failed to start %s IPv6 server component on port %u\n", plugin->name, plugin->port); } else server_reschedule (plugin, plugin->server_v6, GNUNET_NO); } msg = "No"; if ((plugin->server_v6 == NULL) && (plugin->server_v4 == NULL)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "%s %s server component started on port %u\n", msg, plugin->name, plugin->port); sleep (10); return GNUNET_SYSERR; } else if ((plugin->server_v6 != NULL) && (plugin->server_v4 != NULL)) msg = "IPv4 and IPv6"; else if (plugin->server_v6 != NULL) msg = "IPv6"; else if (plugin->server_v4 != NULL) msg = "IPv4"; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "%s %s server component started on port %u\n", msg, plugin->name, plugin->port); return GNUNET_OK; } void server_stop (struct HTTP_Server_Plugin *plugin) { if (plugin->server_v4 != NULL) { MHD_stop_daemon (plugin->server_v4); plugin->server_v4 = NULL; } if ( plugin->server_v6 != NULL) { MHD_stop_daemon (plugin->server_v6); plugin->server_v6 = NULL; } if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->server_v4_task); plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK; } if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->server_v6_task); plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK; } #if BUILD_HTTPS GNUNET_free_non_null (plugin->crypto_init); GNUNET_free_non_null (plugin->cert); GNUNET_free_non_null (plugin->key); #endif GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "%s server component stopped\n", plugin->name); } /** * Add an address to the server's set of addresses and notify transport * * @param cls the plugin handle * @param add_remove GNUNET_YES on add, GNUNET_NO on remove * @param addr the address * @param addrlen address length */ static void server_add_address (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { struct HTTP_Server_Plugin *plugin = cls; struct GNUNET_HELLO_Address *address; struct HttpAddressWrapper *w = NULL; w = GNUNET_new (struct HttpAddressWrapper); w->address = http_common_address_from_socket (plugin->protocol, addr, addrlen); if (NULL == w->address) { GNUNET_free (w); return; } w->addrlen = http_common_address_get_size (w->address); GNUNET_CONTAINER_DLL_insert(plugin->addr_head, plugin->addr_tail, w); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to add address `%s'\n", http_common_plugin_address_to_string (NULL, plugin->protocol, w->address, w->addrlen)); /* modify our published address list */ #if BUILD_HTTPS address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, "https_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE); #else address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, "http_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE); #endif plugin->env->notify_address (plugin->env->cls, add_remove, address); GNUNET_HELLO_address_free (address); } /** * Remove an address from the server's set of addresses and notify transport * * @param cls the plugin handle * @param add_remove GNUNET_YES on add, GNUNET_NO on remove * @param addr the address * @param addrlen address length */ static void server_remove_address (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { struct HTTP_Server_Plugin *plugin = cls; struct GNUNET_HELLO_Address *address; struct HttpAddressWrapper *w = plugin->addr_head; size_t saddr_len; void * saddr = http_common_address_from_socket (plugin->protocol, addr, addrlen); if (NULL == saddr) return; saddr_len = http_common_address_get_size (saddr); while (NULL != w) { if (GNUNET_YES == http_common_cmp_addresses(w->address, w->addrlen, saddr, saddr_len)) break; w = w->next; } GNUNET_free (saddr); if (NULL == w) return; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to remove address `%s'\n", http_common_plugin_address_to_string (NULL, plugin->protocol, w->address, w->addrlen)); GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w); /* modify our published address list */ #if BUILD_HTTPS address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, "https_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE); #else address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, "http_client", w->address, w->addrlen, GNUNET_HELLO_ADDRESS_INFO_NONE); #endif plugin->env->notify_address (plugin->env->cls, add_remove, address); GNUNET_HELLO_address_free (address); GNUNET_free (w->address); GNUNET_free (w); } /** * Our external IP address/port mapping has changed. * * @param cls closure, the 'struct LocalAddrList' * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean * the previous (now invalid) one * @param addr either the previous or the new public IP address * @param addrlen actual lenght of the address */ static void server_nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { GNUNET_assert (cls != NULL); struct HTTP_Server_Plugin *plugin = cls; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "NAT called to %s address `%s'\n", (add_remove == GNUNET_NO) ? "remove" : "add", GNUNET_a2s (addr, addrlen)); if (AF_INET == addr->sa_family) { struct sockaddr_in *s4 = (struct sockaddr_in *) addr; if (GNUNET_NO == plugin->use_ipv4) return; if ((NULL != plugin->server_addr_v4) && (0 != memcmp (&plugin->server_addr_v4->sin_addr, &s4->sin_addr, sizeof (struct in_addr)))) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Skipping address `%s' (not bindto address)\n", GNUNET_a2s (addr, addrlen)); return; } } if (AF_INET6 == addr->sa_family) { struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) addr; if (GNUNET_NO == plugin->use_ipv6) return; if ((NULL != plugin->server_addr_v6) && (0 != memcmp (&plugin->server_addr_v6->sin6_addr, &s6->sin6_addr, sizeof (struct in6_addr)))) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Skipping address `%s' (not bindto address)\n", GNUNET_a2s (addr, addrlen)); return; } } switch (add_remove) { case GNUNET_YES: server_add_address (cls, add_remove, addr, addrlen); break; case GNUNET_NO: server_remove_address (cls, add_remove, addr, addrlen); break; } } /** * Get valid server addresses * * @param plugin the plugin handle * @param service_name the servicename * @param cfg configuration handle * @param addrs addresses * @param addr_lens address length * @return number of addresses */ static int server_get_addresses (struct HTTP_Server_Plugin *plugin, const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg, struct sockaddr ***addrs, socklen_t ** addr_lens) { int disablev6; unsigned long long port; struct addrinfo hints; struct addrinfo *res; struct addrinfo *pos; struct addrinfo *next; unsigned int i; int resi; int ret; struct sockaddr **saddrs; socklen_t *saddrlens; char *hostname; *addrs = NULL; *addr_lens = NULL; disablev6 = !plugin->use_ipv6; port = 0; if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) { GNUNET_break (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port)); if (port > 65535) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Require valid port number for service in configuration!\n")); return GNUNET_SYSERR; } } if (0 == port) { GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name, "Starting in listen only mode\n"); return -1; /* listen only */ } if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO")) { GNUNET_break (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "BINDTO", &hostname)); } else hostname = NULL; if (hostname != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Resolving `%s' since that is where `%s' will bind to.\n", hostname, service_name); memset (&hints, 0, sizeof (struct addrinfo)); if (disablev6) hints.ai_family = AF_INET; if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) || (res == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to resolve `%s': %s\n"), hostname, gai_strerror (ret)); GNUNET_free (hostname); return GNUNET_SYSERR; } next = res; i = 0; while (NULL != (pos = next)) { next = pos->ai_next; if ((disablev6) && (pos->ai_family == AF_INET6)) continue; i++; } if (0 == i) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to find %saddress for `%s'.\n"), disablev6 ? "IPv4 " : "", hostname); freeaddrinfo (res); GNUNET_free (hostname); return GNUNET_SYSERR; } resi = i; saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); i = 0; next = res; while (NULL != (pos = next)) { next = pos->ai_next; if ((disablev6) && (pos->ai_family == AF_INET6)) continue; if ((pos->ai_protocol != IPPROTO_TCP) && (pos->ai_protocol != 0)) continue; /* not TCP */ if ((pos->ai_socktype != SOCK_STREAM) && (pos->ai_socktype != 0)) continue; /* huh? */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Service will bind to `%s'\n", GNUNET_a2s (pos->ai_addr, pos->ai_addrlen)); if (pos->ai_family == AF_INET) { GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in)); saddrlens[i] = pos->ai_addrlen; saddrs[i] = GNUNET_malloc (saddrlens[i]); memcpy (saddrs[i], pos->ai_addr, saddrlens[i]); ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); } else { GNUNET_assert (pos->ai_family == AF_INET6); GNUNET_assert (pos->ai_addrlen == sizeof (struct sockaddr_in6)); saddrlens[i] = pos->ai_addrlen; saddrs[i] = GNUNET_malloc (saddrlens[i]); memcpy (saddrs[i], pos->ai_addr, saddrlens[i]); ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); } i++; } GNUNET_free (hostname); freeaddrinfo (res); resi = i; } else { /* will bind against everything, just set port */ if (disablev6) { /* V4-only */ resi = 1; i = 0; saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); saddrlens[i] = sizeof (struct sockaddr_in); saddrs[i] = GNUNET_malloc (saddrlens[i]); #if HAVE_SOCKADDR_IN_SIN_LEN ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i]; #endif ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); } else { /* dual stack */ resi = 2; saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); i = 0; saddrlens[i] = sizeof (struct sockaddr_in6); saddrs[i] = GNUNET_malloc (saddrlens[i]); #if HAVE_SOCKADDR_IN_SIN_LEN ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0]; #endif ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6; ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); i++; saddrlens[i] = sizeof (struct sockaddr_in); saddrs[i] = GNUNET_malloc (saddrlens[i]); #if HAVE_SOCKADDR_IN_SIN_LEN ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1]; #endif ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); } } *addrs = saddrs; *addr_lens = saddrlens; return resi; } /** * Ask NAT for addresses * * @param plugin the plugin handle */ static void server_start_report_addresses (struct HTTP_Server_Plugin *plugin) { int res = GNUNET_OK; struct sockaddr **addrs; socklen_t *addrlens; res = server_get_addresses (plugin, plugin->name, plugin->env->cfg, &addrs, &addrlens); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Found %u addresses to report to NAT service\n"), res); if (GNUNET_SYSERR == res) { plugin->nat = NULL; return; } plugin->nat = GNUNET_NAT_register (plugin->env->cfg, GNUNET_YES, plugin->port, (unsigned int) res, (const struct sockaddr **) addrs, addrlens, &server_nat_port_map_callback, NULL, plugin); while (res > 0) { res--; GNUNET_assert (addrs[res] != NULL); GNUNET_free (addrs[res]); } GNUNET_free_non_null (addrs); GNUNET_free_non_null (addrlens); } /** * Stop NAT for addresses * * @param plugin the plugin handle */ static void server_stop_report_addresses (struct HTTP_Server_Plugin *plugin) { /* Stop NAT handle */ if (NULL != plugin->nat) GNUNET_NAT_unregister (plugin->nat); /* Clean up addresses */ struct HttpAddressWrapper *w; while (plugin->addr_head != NULL) { w = plugin->addr_head; GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w); GNUNET_free (w->address); GNUNET_free (w); } } /** * Check if IPv6 supported on this system * * @param plugin the plugin handle * @return GNUNET_YES on success, else GNUNET_NO */ static int server_check_ipv6_support (struct HTTP_Server_Plugin *plugin) { struct GNUNET_NETWORK_Handle *desc = NULL; int res = GNUNET_NO; /* Probe IPv6 support */ desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); if (NULL == desc) { if ((errno == ENOBUFS) || (errno == ENOMEM) || (errno == ENFILE) || (errno == EACCES)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); } GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name, _ ("Disabling IPv6 since it is not supported on this system!\n")); res = GNUNET_NO; } else { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); desc = NULL; res = GNUNET_YES; } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Testing IPv6 on this system: %s\n", (res == GNUNET_YES) ? "successful" : "failed"); return res; } /** * Notify server about our external hostname * * @param cls plugin * @param tc task context (unused) */ static void server_notify_external_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct HTTP_Server_Plugin *plugin = cls; struct HttpAddress *ext_addr; size_t ext_addr_len; unsigned int urlen; char *url; plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_asprintf(&url, "%s://%s", plugin->protocol, plugin->external_hostname); urlen = strlen (url) + 1; ext_addr = GNUNET_malloc (sizeof (struct HttpAddress) + urlen); ext_addr->options = htonl(plugin->options); ext_addr->urlen = htonl (urlen); ext_addr_len = sizeof (struct HttpAddress) + urlen; memcpy (&ext_addr[1], url, urlen); GNUNET_free (url); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport about external hostname address `%s'\n", plugin->external_hostname); #if BUILD_HTTPS if (GNUNET_YES == plugin->verify_external_hostname) GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name, "Enabling SSL verification for external hostname address `%s'\n", plugin->external_hostname); plugin->ext_addr = GNUNET_HELLO_address_allocate (plugin->env->my_identity, "https_client", ext_addr, ext_addr_len, GNUNET_HELLO_ADDRESS_INFO_NONE ); plugin->env->notify_address (plugin->env->cls, GNUNET_YES, plugin->ext_addr); GNUNET_free (ext_addr); #else plugin->ext_addr = GNUNET_HELLO_address_allocate (plugin->env->my_identity, "http_client", ext_addr, ext_addr_len, GNUNET_HELLO_ADDRESS_INFO_NONE ); plugin->env->notify_address (plugin->env->cls, GNUNET_YES, plugin->ext_addr); GNUNET_free (ext_addr); #endif } /** * Configure the plugin * * @param plugin plugin handle * @return GNUNET_OK on success, GNUNET_SYSERR on failure */ static int server_configure_plugin (struct HTTP_Server_Plugin *plugin) { unsigned long long port; unsigned long long max_connections; char *bind4_address = NULL; char *bind6_address = NULL; char *eh_tmp = NULL; int external_hostname_use_port; /* Use IPv4? */ if (GNUNET_CONFIGURATION_have_value (plugin->env->cfg, plugin->name, "USE_IPv4")) { plugin->use_ipv4 = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, "USE_IPv4"); } else plugin->use_ipv4 = GNUNET_YES; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("IPv4 support is %s\n"), (plugin->use_ipv4 == GNUNET_YES) ? "enabled" : "disabled"); /* Use IPv6? */ if (GNUNET_CONFIGURATION_have_value (plugin->env->cfg, plugin->name, "USE_IPv6")) { plugin->use_ipv6 = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, "USE_IPv6"); } else plugin->use_ipv6 = GNUNET_YES; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("IPv6 support is %s\n"), (plugin->use_ipv6 == GNUNET_YES) ? "enabled" : "disabled"); if ((plugin->use_ipv4 == GNUNET_NO) && (plugin->use_ipv6 == GNUNET_NO)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _ ("Neither IPv4 nor IPv6 are enabled! Fix in configuration\n"), plugin->name); return GNUNET_SYSERR; } /* Reading port number from config file */ if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name, "PORT", &port)) || (port > 65535)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _("Port is required! Fix in configuration\n"), plugin->name); return GNUNET_SYSERR; } plugin->port = port; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name, _("Using port %u\n"), plugin->port); if ((plugin->use_ipv4 == GNUNET_YES) && (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name, "BINDTO", &bind4_address))) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Binding %s plugin to specific IPv4 address: `%s'\n", plugin->protocol, bind4_address); plugin->server_addr_v4 = GNUNET_new (struct sockaddr_in); if (1 != inet_pton (AF_INET, bind4_address, &plugin->server_addr_v4->sin_addr)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _ ("Specific IPv4 address `%s' in configuration file is invalid!\n"), bind4_address); GNUNET_free (bind4_address); GNUNET_free (plugin->server_addr_v4); plugin->server_addr_v4 = NULL; return GNUNET_SYSERR; } else { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Binding to IPv4 address %s\n"), bind4_address); plugin->server_addr_v4->sin_family = AF_INET; plugin->server_addr_v4->sin_port = htons (plugin->port); } GNUNET_free (bind4_address); } if ((plugin->use_ipv6 == GNUNET_YES) && (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name, "BINDTO6", &bind6_address))) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Binding %s plugin to specific IPv6 address: `%s'\n", plugin->protocol, bind6_address); plugin->server_addr_v6 = GNUNET_new (struct sockaddr_in6); if (1 != inet_pton (AF_INET6, bind6_address, &plugin->server_addr_v6->sin6_addr)) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, _ ("Specific IPv6 address `%s' in configuration file is invalid!\n"), bind6_address); GNUNET_free (bind6_address); GNUNET_free (plugin->server_addr_v6); plugin->server_addr_v6 = NULL; return GNUNET_SYSERR; } else { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Binding to IPv6 address %s\n"), bind6_address); plugin->server_addr_v6->sin6_family = AF_INET6; plugin->server_addr_v6->sin6_port = htons (plugin->port); } GNUNET_free (bind6_address); } plugin->verify_external_hostname = GNUNET_NO; #if BUILD_HTTPS plugin->verify_external_hostname = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, "VERIFY_EXTERNAL_HOSTNAME"); if (GNUNET_SYSERR == plugin->verify_external_hostname) plugin->verify_external_hostname = GNUNET_NO; if (GNUNET_YES == plugin->verify_external_hostname) plugin->options |= HTTP_OPTIONS_VERIFY_CERTIFICATE; #endif external_hostname_use_port = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, "EXTERNAL_HOSTNAME_USE_PORT"); if (GNUNET_SYSERR == external_hostname_use_port) external_hostname_use_port = GNUNET_NO; if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name, "EXTERNAL_HOSTNAME", &eh_tmp)) { char * tmp = NULL; char * pos = NULL; char * pos_url = NULL; if (NULL != strstr(eh_tmp, "://")) { tmp = &strstr(eh_tmp, "://")[3]; } else tmp = eh_tmp; if (GNUNET_YES == external_hostname_use_port) { if ( (strlen (tmp) > 1) && (NULL != (pos = strchr(tmp, '/'))) ) { pos_url = pos + 1; pos[0] = '\0'; GNUNET_asprintf (&plugin->external_hostname, "%s:%u/%s", tmp, (uint16_t) port, (NULL == pos_url) ? "" : pos_url); } else GNUNET_asprintf (&plugin->external_hostname, "%s:%u", tmp, (uint16_t) port); } else plugin->external_hostname = GNUNET_strdup (tmp); GNUNET_free (eh_tmp); GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name, _("Using external hostname `%s'\n"), plugin->external_hostname); plugin->notify_ext_task = GNUNET_SCHEDULER_add_now (&server_notify_external_hostname, plugin); /* Use only configured external hostname */ if (GNUNET_CONFIGURATION_have_value (plugin->env->cfg, plugin->name, "EXTERNAL_HOSTNAME_ONLY")) { plugin->external_only = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name, "EXTERNAL_HOSTNAME_ONLY"); } else plugin->external_only = GNUNET_NO; if (GNUNET_YES == plugin->external_only) GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Notifying transport only about hostname `%s'\n"), plugin->external_hostname); } else GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "No external hostname configured\n"); /* Optional parameters */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (plugin->env->cfg, plugin->name, "MAX_CONNECTIONS", &max_connections)) max_connections = 128; plugin->max_connections = max_connections; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Maximum number of connections is %u\n"), plugin->max_connections); plugin->peer_id_length = strlen (GNUNET_i2s_full (plugin->env->my_identity)); return GNUNET_OK; } /** * Session was idle, so disconnect it * * @param cls the session * @param tc task context */ static void server_session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *s = cls; s->timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (TIMEOUT_LOG, "Session %p was idle for %s, disconnecting\n", s, GNUNET_STRINGS_relative_time_to_string (HTTP_SERVER_SESSION_TIMEOUT, GNUNET_YES)); /* call session destroy function */ GNUNET_assert (GNUNET_OK == http_server_plugin_disconnect_session (s->plugin, s)); } /** * Start session timeout for session s * * @param s the session */ static void server_start_session_timeout (struct Session *s) { GNUNET_assert (NULL != s); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_SERVER_SESSION_TIMEOUT, &server_session_timeout, s); GNUNET_log (TIMEOUT_LOG, "Timeout for session %p set to %s\n", s, GNUNET_STRINGS_relative_time_to_string (HTTP_SERVER_SESSION_TIMEOUT, GNUNET_YES)); } /** * Increment session timeout due to activity session s * * @param s the session */ static void server_reschedule_session_timeout (struct Session *s) { GNUNET_assert (NULL != s); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_add_delayed (HTTP_SERVER_SESSION_TIMEOUT, &server_session_timeout, s); GNUNET_log (TIMEOUT_LOG, "Timeout rescheduled for session %p set to %s\n", s, GNUNET_STRINGS_relative_time_to_string (HTTP_SERVER_SESSION_TIMEOUT, GNUNET_YES)); } /** * Exit point from the plugin. * * @param cls api * @return NULL */ void * LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct HTTP_Server_Plugin *plugin = api->cls; struct Session *pos; struct Session *next; if (NULL == api->cls) { /* Free for stub mode */ GNUNET_free (api); return NULL; } plugin->in_shutdown = GNUNET_YES; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Shutting down plugin `%s'\n"), plugin->name); if (GNUNET_SCHEDULER_NO_TASK != plugin->notify_ext_task) { GNUNET_SCHEDULER_cancel (plugin->notify_ext_task); plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != plugin->ext_addr) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Notifying transport to remove address `%s'\n", http_common_plugin_address_to_string (NULL, plugin->protocol, plugin->ext_addr->address, plugin->ext_addr->address_length)); #if BUILD_HTTPS plugin->env->notify_address (plugin->env->cls, GNUNET_NO, plugin->ext_addr); #else plugin->env->notify_address (plugin->env->cls, GNUNET_NO, plugin->ext_addr); #endif GNUNET_HELLO_address_free (plugin->ext_addr); plugin->ext_addr = NULL; } /* Stop to report addresses to transport service */ server_stop_report_addresses (plugin); server_stop (plugin); next = plugin->head; while (NULL != (pos = next)) { next = pos->next; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Removing left over session %p\n", pos); if ((GNUNET_YES == pos->session_passed) && (GNUNET_NO == pos->session_ended)) { /* Notify transport immediately that this session is invalid */ pos->session_ended = GNUNET_YES; plugin->env->session_end (plugin->env->cls, pos->address, pos); } server_delete_session (plugin, pos); } /* Clean up */ GNUNET_free_non_null (plugin->external_hostname); GNUNET_free_non_null (plugin->ext_addr); GNUNET_free_non_null (plugin->server_addr_v4); GNUNET_free_non_null (plugin->server_addr_v6); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, _("Shutdown for plugin `%s' complete\n"), plugin->name); GNUNET_free (plugin); GNUNET_free (api); return NULL; } static const char * http_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) { #if BUILD_HTTPS return http_common_plugin_address_to_string (cls, PLUGIN_NAME, addr, addrlen); #else return http_common_plugin_address_to_string (cls, PLUGIN_NAME, addr, addrlen); #endif } /** * Function obtain the network type for a session * * @param cls closure ('struct Plugin*') * @param session the session * @return the network type in HBO or GNUNET_SYSERR */ static enum GNUNET_ATS_Network_Type http_server_get_network (void *cls, struct Session *session) { GNUNET_assert (NULL != session); return ntohl (session->ats_address_network_type); } /** * Entry point for the plugin. * * @param cls env * @return api */ void * LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct HTTP_Server_Plugin *plugin; if (NULL == env->receive) { /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully initialze the plugin or the API */ api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = NULL; api->address_to_string = &http_plugin_address_to_string; api->string_to_address = &http_common_plugin_string_to_address; api->address_pretty_printer = &http_common_plugin_address_pretty_printer; return api; } plugin = GNUNET_new (struct HTTP_Server_Plugin); plugin->env = env; api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = plugin; api->send = &http_server_plugin_send; api->disconnect_peer = &http_server_plugin_disconnect_peer; api->disconnect_session = &http_server_plugin_disconnect_session; api->query_keepalive_factor = &http_server_query_keepalive_factor; api->check_address = &http_server_plugin_address_suggested; api->get_session = &http_server_plugin_get_session; api->address_to_string = &http_plugin_address_to_string; api->string_to_address = &http_common_plugin_string_to_address; api->address_pretty_printer = &http_common_plugin_address_pretty_printer; api->get_network = &http_server_get_network; api->update_session_timeout = &http_server_plugin_update_session_timeout; #if BUILD_HTTPS plugin->name = "transport-https_server"; plugin->protocol = "https"; #else plugin->name = "transport-http_server"; plugin->protocol = "http"; #endif /* Configure plugin */ if (GNUNET_SYSERR == server_configure_plugin (plugin)) { LIBGNUNET_PLUGIN_TRANSPORT_DONE (api); return NULL; } /* Check IPv6 support */ if (GNUNET_YES == plugin->use_ipv6) plugin->use_ipv6 = server_check_ipv6_support (plugin); /* Report addresses to transport service */ if (GNUNET_NO == plugin->external_only) server_start_report_addresses (plugin); if (GNUNET_SYSERR == server_start (plugin)) { LIBGNUNET_PLUGIN_TRANSPORT_DONE (api); return NULL; } return api; } /* end of plugin_transport_http_server.c */ gnunet-0.10.1/src/transport/transport_api_monitoring.c0000644000175000017500000005603612316473377020162 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/transport_api_monitoring.c * @brief montoring api for transport peer status and validation entries * * This api provides the ability to query the transport service about * the status of a specific or all peers as well as address validation entries. * * Calls back with information about peer(s) including address used, state and * state timeout for peer requests and address, address lifetime and next revalidation * for validation entries. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_transport_service.h" #include "transport.h" /** * Context for iterating validation entries. */ struct GNUNET_TRANSPORT_PeerMonitoringContext { /** * Function to call with the binary address. */ GNUNET_TRANSPORT_PeerIterateCallback cb; /** * Closure for cb. */ void *cb_cls; /** * Connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * Configuration we use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * When should this operation time out? */ struct GNUNET_TIME_Absolute timeout; /** * Backoff for reconnect. */ struct GNUNET_TIME_Relative backoff; /** * Task ID for reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Identity of the peer to monitor. */ struct GNUNET_PeerIdentity peer; /** * Was this a one-shot request? */ int one_shot; }; /** * Context for the address lookup. */ struct GNUNET_TRANSPORT_ValidationMonitoringContext { /** * Function to call with the binary address. */ GNUNET_TRANSPORT_ValidationIterateCallback cb; /** * Closure for cb. */ void *cb_cls; /** * Connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * Configuration we use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * When should this operation time out? */ struct GNUNET_TIME_Absolute timeout; /** * Backoff for reconnect. */ struct GNUNET_TIME_Relative backoff; /** * Task ID for reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Identity of the peer to monitor. */ struct GNUNET_PeerIdentity peer; /** * Was this a one-shot request? */ int one_shot; }; /** * Check if a state is defined as connected * * @param state the state value * @return GNUNET_YES or GNUNET_NO */ int GNUNET_TRANSPORT_is_connected (enum GNUNET_TRANSPORT_PeerState state) { switch (state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: case GNUNET_TRANSPORT_PS_INIT_ATS: case GNUNET_TRANSPORT_PS_CONNECT_SENT: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: return GNUNET_NO; case GNUNET_TRANSPORT_PS_CONNECTED: case GNUNET_TRANSPORT_PS_RECONNECT_ATS: case GNUNET_TRANSPORT_PS_RECONNECT_SENT: case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: return GNUNET_YES; case GNUNET_TRANSPORT_PS_DISCONNECT: case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: return GNUNET_NO; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n", GNUNET_TRANSPORT_ps2s (state)); GNUNET_break (0); break; } return GNUNET_SYSERR; } /** * Convert peer state to human-readable string. * * @param state the state value * @return corresponding string */ const char * GNUNET_TRANSPORT_ps2s (enum GNUNET_TRANSPORT_PeerState state) { switch (state) { case GNUNET_TRANSPORT_PS_NOT_CONNECTED: return "S_NOT_CONNECTED"; case GNUNET_TRANSPORT_PS_INIT_ATS: return "S_INIT_ATS"; case GNUNET_TRANSPORT_PS_CONNECT_SENT: return "S_CONNECT_SENT"; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS: return "S_CONNECT_RECV_ATS"; case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK: return "S_CONNECT_RECV_ACK"; case GNUNET_TRANSPORT_PS_CONNECTED: return "S_CONNECTED"; case GNUNET_TRANSPORT_PS_RECONNECT_ATS: return "S_RECONNECT_ATS"; case GNUNET_TRANSPORT_PS_RECONNECT_SENT: return "S_RECONNECT_SENT"; case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT: return "S_CONNECTED_SWITCHING_CONNECT_SENT"; case GNUNET_TRANSPORT_PS_DISCONNECT: return "S_DISCONNECT"; case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED: return "S_DISCONNECT_FINISHED"; default: GNUNET_break (0); return "UNDEFINED"; } } /** * Convert validation state to human-readable string. * * @param state the state value * @return corresponding string */ const char * GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state) { switch (state) { case GNUNET_TRANSPORT_VS_NONE: return "NONE"; case GNUNET_TRANSPORT_VS_NEW: return "NEW"; case GNUNET_TRANSPORT_VS_REMOVE: return "REMOVE"; case GNUNET_TRANSPORT_VS_TIMEOUT: return "TIMEOUT"; case GNUNET_TRANSPORT_VS_UPDATE: return "UPDATE"; default: GNUNET_break (0); return "UNDEFINED"; } } /** * Function called with responses from the service. * * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*' * @param msg NULL on timeout or error, otherwise presumably a * message with the human-readable address */ static void peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg); /** * Function called with responses from the service. * * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*' * @param msg NULL on timeout or error, otherwise presumably a * message with the human-readable address */ static void val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg); /** * Send our subscription request to the service. * * @param pal_ctx our context */ static void send_peer_mon_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx) { struct PeerMonitorMessage msg; msg.header.size = htons (sizeof (struct PeerMonitorMessage)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST); msg.one_shot = htonl (pal_ctx->one_shot); msg.peer = pal_ctx->peer; GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (pal_ctx->client, &msg.header, GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout), GNUNET_YES, &peer_response_processor, pal_ctx)); } /** * Send our subscription request to the service. * * @param val_ctx our context */ static void send_val_mon_request (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx) { struct ValidationMonitorMessage msg; msg.header.size = htons (sizeof (struct ValidationMonitorMessage)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST); msg.one_shot = htonl (val_ctx->one_shot); msg.peer = val_ctx->peer; GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (val_ctx->client, &msg.header, GNUNET_TIME_absolute_get_remaining (val_ctx->timeout), GNUNET_YES, &val_response_processor, val_ctx)); } /** * Task run to re-establish the connection. * * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*' * @param tc scheduler context, unused */ static void do_peer_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls; pal_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK; pal_ctx->client = GNUNET_CLIENT_connect ("transport", pal_ctx->cfg); GNUNET_assert (NULL != pal_ctx->client); send_peer_mon_request (pal_ctx); } /** * Cut the existing connection and reconnect. * * @param pal_ctx our context */ static void reconnect_peer_ctx (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx) { GNUNET_assert (GNUNET_NO == pal_ctx->one_shot); GNUNET_CLIENT_disconnect (pal_ctx->client); pal_ctx->client = NULL; pal_ctx->backoff = GNUNET_TIME_STD_BACKOFF (pal_ctx->backoff); pal_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (pal_ctx->backoff, &do_peer_connect, pal_ctx); } /** * Task run to re-establish the connection. * * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*' * @param tc scheduler context, unused */ static void do_val_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls; val_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK; val_ctx->client = GNUNET_CLIENT_connect ("transport", val_ctx->cfg); GNUNET_assert (NULL != val_ctx->client); send_val_mon_request (val_ctx); } /** * Cut the existing connection and reconnect. * * @param val_ctx our context */ static void reconnect_val_ctx (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx) { GNUNET_assert (GNUNET_NO == val_ctx->one_shot); GNUNET_CLIENT_disconnect (val_ctx->client); val_ctx->client = NULL; val_ctx->backoff = GNUNET_TIME_STD_BACKOFF (val_ctx->backoff); val_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (val_ctx->backoff, &do_val_connect, val_ctx); } /** * Function called with responses from the service. * * @param cls our 'struct GNUNET_TRANSPORT_PeerMonitoringContext*' * @param msg NULL on timeout or error, otherwise presumably a * message with the human-readable address */ static void val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls; struct ValidationIterateResponseMessage *vr_msg; struct GNUNET_HELLO_Address *address; const char *addr; const char *transport_name; size_t size; size_t tlen; size_t alen; if (msg == NULL) { if (val_ctx->one_shot) { /* Disconnect */ val_ctx->cb (val_ctx->cb_cls, NULL, NULL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT); GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx); } else { reconnect_val_ctx (val_ctx); } return; } size = ntohs (msg->size); GNUNET_break (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE); if (size == sizeof (struct GNUNET_MessageHeader)) { /* Done! */ if (val_ctx->one_shot) { val_ctx->cb (val_ctx->cb_cls, NULL, NULL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE); GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx); } else { reconnect_val_ctx (val_ctx); } return; } if ((size < sizeof (struct ValidationIterateResponseMessage)) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE)) { GNUNET_break (0); if (val_ctx->one_shot) { val_ctx->cb (val_ctx->cb_cls, NULL, NULL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE); GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx); } else { reconnect_val_ctx (val_ctx); } return; } vr_msg = (struct ValidationIterateResponseMessage *) msg; tlen = ntohl (vr_msg->pluginlen); alen = ntohl (vr_msg->addrlen); if (size != sizeof (struct ValidationIterateResponseMessage) + tlen + alen) { GNUNET_break (0); if (val_ctx->one_shot) { val_ctx->cb (val_ctx->cb_cls, NULL, NULL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE); GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx); } else { reconnect_val_ctx (val_ctx); } return; } if ( (0 == tlen) && (0 == alen) ) { GNUNET_break (0); if (val_ctx->one_shot) { val_ctx->cb (val_ctx->cb_cls, NULL, NULL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE); GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx); } else { reconnect_val_ctx (val_ctx); } return; } else { if (0 == tlen) { GNUNET_break (0); /* This must not happen: address without plugin */ return; } addr = (const char *) &vr_msg[1]; transport_name = &addr[alen]; if (transport_name[tlen - 1] != '\0') { /* Corrupt plugin name */ GNUNET_break (0); if (val_ctx->one_shot) { val_ctx->cb (val_ctx->cb_cls, NULL, NULL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE); GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx); } else { reconnect_val_ctx (val_ctx); } return; } /* notify client */ address = GNUNET_HELLO_address_allocate (&vr_msg->peer, transport_name, addr, alen, ntohl(vr_msg->local_address_info)); val_ctx->cb (val_ctx->cb_cls, &vr_msg->peer, address, GNUNET_TIME_absolute_ntoh(vr_msg->last_validation), GNUNET_TIME_absolute_ntoh(vr_msg->valid_until), GNUNET_TIME_absolute_ntoh(vr_msg->next_validation), ntohl(vr_msg->state)); GNUNET_HELLO_address_free (address); } /* expect more replies */ GNUNET_CLIENT_receive (val_ctx->client, &val_response_processor, val_ctx, GNUNET_TIME_absolute_get_remaining (val_ctx->timeout)); } /** * Function called with responses from the service. * * @param cls our 'struct GNUNET_TRANSPORT_PeerMonitoringContext*' * @param msg NULL on timeout or error, otherwise presumably a * message with the human-readable address */ static void peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls; struct PeerIterateResponseMessage *pir_msg; struct GNUNET_HELLO_Address *address; const char *addr; const char *transport_name; uint16_t size; size_t alen; size_t tlen; if (msg == NULL) { if (pal_ctx->one_shot) { /* Disconnect */ pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL, GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS); GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx); } else { reconnect_peer_ctx (pal_ctx); } return; } size = ntohs (msg->size); GNUNET_break (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE); if (size == sizeof (struct GNUNET_MessageHeader)) { /* Done! */ if (pal_ctx->one_shot) { pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL, GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS); GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx); } else { reconnect_peer_ctx (pal_ctx); } return; } if ((size < sizeof (struct PeerIterateResponseMessage)) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE)) { GNUNET_break (0); if (pal_ctx->one_shot) { pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL, GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS); GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx); } else { reconnect_peer_ctx (pal_ctx); } return; } pir_msg = (struct PeerIterateResponseMessage *) msg; tlen = ntohl (pir_msg->pluginlen); alen = ntohl (pir_msg->addrlen); if (size != sizeof (struct PeerIterateResponseMessage) + tlen + alen) { GNUNET_break (0); if (pal_ctx->one_shot) { pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL, GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS); GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx); } else { reconnect_peer_ctx (pal_ctx); } return; } if ( (0 == tlen) && (0 == alen) ) { /* No address available */ pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, NULL, ntohl(pir_msg->state), GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout)); } else { if (0 == tlen) { GNUNET_break (0); /* This must not happen: address without plugin */ return; } addr = (const char *) &pir_msg[1]; transport_name = &addr[alen]; if (transport_name[tlen - 1] != '\0') { /* Corrupt plugin name */ GNUNET_break (0); if (pal_ctx->one_shot) { pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL, GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS); GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx); } else { reconnect_peer_ctx (pal_ctx); } return; } /* notify client */ address = GNUNET_HELLO_address_allocate (&pir_msg->peer, transport_name, addr, alen, ntohl(pir_msg->local_address_info)); pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, address, ntohl(pir_msg->state), GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout)); GNUNET_HELLO_address_free (address); } /* expect more replies */ GNUNET_CLIENT_receive (pal_ctx->client, &peer_response_processor, pal_ctx, GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout)); } /** * Return information about a specific peer or all peers currently known to * transport service once or in monitoring mode. To obtain information about * a specific peer, a peer identity can be passed. To obtain information about * all peers currently known to transport service, NULL can be passed as peer * identity. * * For each peer, the callback is called with information about the address used * to communicate with this peer, the state this peer is currently in and the * the current timeout for this state. * * Upon completion, the 'GNUNET_TRANSPORT_PeerIterateCallback' is called one * more time with 'NULL'. After this, the operation must no longer be * explicitly canceled. * * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the * the peer_callback! * * @param cfg configuration to use * @param peer a specific peer identity to obtain information for, * NULL for all peers * @param one_shot GNUNET_YES to return the current state and then end (with NULL+NULL), * GNUNET_NO to monitor peers continuously * @param timeout how long is the lookup allowed to take at most * @param peer_callback function to call with the results * @param peer_callback_cls closure for peer_address_callback */ struct GNUNET_TRANSPORT_PeerMonitoringContext * GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *peer, int one_shot, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_PeerIterateCallback peer_callback, void *peer_callback_cls) { struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx; struct GNUNET_CLIENT_Connection *client; client = GNUNET_CLIENT_connect ("transport", cfg); if (client == NULL) return NULL; if (GNUNET_YES != one_shot) timeout = GNUNET_TIME_UNIT_FOREVER_REL; pal_ctx = GNUNET_new (struct GNUNET_TRANSPORT_PeerMonitoringContext); pal_ctx->cb = peer_callback; pal_ctx->cb_cls = peer_callback_cls; pal_ctx->cfg = cfg; pal_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); if (NULL != peer) pal_ctx->peer = *peer; pal_ctx->one_shot = one_shot; pal_ctx->client = client; send_peer_mon_request (pal_ctx); return pal_ctx; } /** * Cancel request to monitor peers * * @param pic handle for the request to cancel */ void GNUNET_TRANSPORT_monitor_peers_cancel (struct GNUNET_TRANSPORT_PeerMonitoringContext *pic) { if (NULL != pic->client) { GNUNET_CLIENT_disconnect (pic->client); pic->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != pic->reconnect_task) { GNUNET_SCHEDULER_cancel (pic->reconnect_task); pic->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (pic); } /** * Return information about pending address validation operations for a specific * or all peers * * @param cfg configuration to use * @param peer a specific peer identity to obtain validation entries for, * NULL for all peers * @param one_shot GNUNET_YES to return all entries and then end (with NULL+NULL), * GNUNET_NO to monitor validation entries continuously * @param timeout how long is the lookup allowed to take at most * @param validation_callback function to call with the results * @param validation_callback_cls closure for peer_address_callback */ struct GNUNET_TRANSPORT_ValidationMonitoringContext * GNUNET_TRANSPORT_monitor_validation_entries (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *peer, int one_shot, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_ValidationIterateCallback validation_callback, void *validation_callback_cls) { struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx; struct GNUNET_CLIENT_Connection *client; client = GNUNET_CLIENT_connect ("transport", cfg); if (client == NULL) return NULL; if (GNUNET_YES != one_shot) timeout = GNUNET_TIME_UNIT_FOREVER_REL; val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext); val_ctx->cb = validation_callback; val_ctx->cb_cls = validation_callback_cls; val_ctx->cfg = cfg; val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout); if (NULL != peer) val_ctx->peer = *peer; val_ctx->one_shot = one_shot; val_ctx->client = client; send_val_mon_request (val_ctx); return val_ctx; } /** * Return information about all current pending validation operations * * @param vic handle for the request to cancel */ void GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic) { if (NULL != vic->client) { GNUNET_CLIENT_disconnect (vic->client); vic->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != vic->reconnect_task) { GNUNET_SCHEDULER_cancel (vic->reconnect_task); vic->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (vic); } /* end of transport_api_monitoring.c */ gnunet-0.10.1/src/transport/test_transport_api_unix_peer1.conf0000644000175000017500000000110012225230043021550 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-unix-p1/ [arm] PORT = 12125 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12124 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12123 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12122 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12121 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [transport-unix] PORT = 12120 gnunet-0.10.1/src/transport/plugin_transport_wlan.h0000644000175000017500000001477512225777503017471 00000000000000/* This file is part of GNUnet (C) 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_wlan.h * @brief header for transport plugin and the helper for wlan * @author David Brodski */ #ifndef PLUGIN_TRANSPORT_WLAN #define PLUGIN_TRANSPORT_WLAN #include "gnunet_crypto_lib.h" #include "gnunet_common.h" /** * Number fo bytes in a mac address. */ #ifdef MINGW #define MAC_ADDR_SIZE 8 typedef uint8_t u_int8_t; #else #define MAC_ADDR_SIZE 6 #endif /** * Value for "Management" in the 'frame_control' field of the * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame. */ #define IEEE80211_FC0_TYPE_MGT 0x00 /** * Value for "Control" in the 'frame_control' field of the * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame. */ #define IEEE80211_FC0_TYPE_CTL 0x04 /** * Value for DATA in the 'frame_control' field of the * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame. */ #define IEEE80211_FC0_TYPE_DATA 0x08 GNUNET_NETWORK_STRUCT_BEGIN /** * A MAC Address. */ struct GNUNET_TRANSPORT_WLAN_MacAddress { uint8_t mac[MAC_ADDR_SIZE]; }; /** * Format of a WLAN Control Message. */ struct GNUNET_TRANSPORT_WLAN_HelperControlMessage { /** * Message header. Type is * GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL */ struct GNUNET_MessageHeader hdr; /** * MAC Address of the local WLAN interface. */ struct GNUNET_TRANSPORT_WLAN_MacAddress mac; }; /** * generic definitions for IEEE 802.3 frames */ struct GNUNET_TRANSPORT_WLAN_Ieee8023Frame { /** * Address 1: destination address in ad-hoc mode or AP, BSSID if station, */ struct GNUNET_TRANSPORT_WLAN_MacAddress dst; /** * Address 2: source address if in ad-hoc-mode or station, BSSID if AP */ struct GNUNET_TRANSPORT_WLAN_MacAddress src; /** * Packet type ID. */ uint16_t type; }; /** * generic definitions for IEEE 802.11 frames */ struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame { /** * 802.11 Frame Control field. A bitmask. The overall field is a * 16-bit mask of the respecitve fields. The lowest two bits should * be 0, then comes the "type" (2 bits, see IEEE80211_FC0_TYPE_* * constants), followed by 4-bit subtype (all zeros for ad-hoc), * followed by various flags (to DS, from DS, more frag, retry, * power management, more data, WEP, strict), all of which we also * keep at zero. */ uint16_t frame_control GNUNET_PACKED; /** * Microseconds to reserve link (duration), 0 by default */ uint16_t duration GNUNET_PACKED; /** * Address 1: destination address in ad-hoc mode or AP, BSSID if station, */ struct GNUNET_TRANSPORT_WLAN_MacAddress addr1; /** * Address 2: source address if in ad-hoc-mode or station, BSSID if AP */ struct GNUNET_TRANSPORT_WLAN_MacAddress addr2; /** * Address 3: BSSID in ad-hoc mode, Destination if station, source if AP */ struct GNUNET_TRANSPORT_WLAN_MacAddress addr3; /** * 802.11 sequence control field; contains fragment number an sequence * number (we set this to all zeros). */ uint16_t sequence_control GNUNET_PACKED; /** * Link layer control (LLC). Set to a GNUnet-specific value. */ u_int8_t llc[4]; /* payload */ } GNUNET_PACKED; /** * Message from the plugin to the WLAN helper: send the given message with the * given connection parameters. */ struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage { /** * Type is 'GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER'. */ struct GNUNET_MessageHeader header; /** * wlan send rate */ uint8_t rate; /** * Antenna; the first antenna is 0. */ uint8_t antenna; /** * Transmit power expressed as unitless distance from max power set at factory calibration. * 0 is max power. Monotonically nondecreasing with lower power levels. */ uint16_t tx_power GNUNET_PACKED; /** * IEEE Frame to transmit (the sender MAC address will be overwritten by the helper as it does not * trust the plugin to set it correctly). */ struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame frame; /* actual payload follows */ }; /** * Message from the WLAN helper to the plugin: we have received the given message with the * given performance characteristics. */ /** * struct to represent infos gathered form the radiotap fields, see RadiotapHeader for more Infos */ struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage { /** * Type is 'GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER'. */ struct GNUNET_MessageHeader header; /** * Information about which of the fields below are actually valid. * 0 for none. FIXME: not properly initialized so far (always zero). */ uint32_t ri_present GNUNET_PACKED; /** * IEEE80211_RADIOTAP_TSFT, 0 if unknown. */ uint64_t ri_mactime GNUNET_PACKED; /** * from radiotap * either IEEE80211_RADIOTAP_DBM_ANTSIGNAL * or IEEE80211_RADIOTAP_DB_ANTSIGNAL, 0 if unknown. */ int32_t ri_power GNUNET_PACKED; /** * either IEEE80211_RADIOTAP_DBM_ANTNOISE * or IEEE80211_RADIOTAP_DB_ANTNOISE, 0 if unknown. */ int32_t ri_noise GNUNET_PACKED; /** * IEEE80211_RADIOTAP_CHANNEL, 0 if unknown. */ uint32_t ri_channel GNUNET_PACKED; /** * Frequency we use. 0 if unknown. */ uint32_t ri_freq GNUNET_PACKED; /** * IEEE80211_RADIOTAP_RATE * 50000, 0 if unknown. */ uint32_t ri_rate GNUNET_PACKED; /** * IEEE80211_RADIOTAP_ANTENNA, 0 if unknown. */ uint32_t ri_antenna GNUNET_PACKED; /** * IEEE Frame. */ struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame frame; /* followed by payload */ }; GNUNET_NETWORK_STRUCT_END /** * GNUnet bssid */ static const struct GNUNET_TRANSPORT_WLAN_MacAddress mac_bssid_gnunet = { {0x13, 0x22, 0x33, 0x44, 0x55, 0x66} }; /** * Broadcast MAC */ static const struct GNUNET_TRANSPORT_WLAN_MacAddress bc_all_mac = { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} }; #endif gnunet-0.10.1/src/transport/test_transport_api_reliability_wlan_peer1.conf0000644000175000017500000000110112225230043024120 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p1/ [transport-wlan] TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_http_reverse_peer1.conf0000644000175000017500000000156212225230043023313 00000000000000INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-http-p1/ [transport-http_client] [arm] PORT = 12095 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12094 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12093 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12092 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12091 PLUGINS = http_client #BINARY = .libs/gnunet-service-transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PREFIX = valgrind --leak-check=full #PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args [ats] WAN_QUOTA_IN = unlimited WAN_QUOTA_OUT = unlimited PORT = 12006 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-http_reserver_p1-service-ats.sock gnunet-0.10.1/src/transport/test_transport_api_timeout_http_peer2.conf0000644000175000017500000000126712225230043023331 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-http-p2/ [nat] [transport-http_server] PORT = 12090 USE_IPv6 = NO BINDTO = 127.0.0.1 [arm] PORT = 12095 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12094 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12093 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12092 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12091 PLUGINS = http_server UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock #PREFIX = valgrind --leak-check=full gnunet-0.10.1/src/transport/test_transport_api_http_peer2.conf0000644000175000017500000000126112225230043021555 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-http-p2/ [transport-http_server] PORT = 12090 USE_IPv6 = YES #BINDTO = 127.0.0.1 [arm] PORT = 12095 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12094 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12093 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12092 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12091 PLUGINS = http_server UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock #PREFIX = valgrind --leak-check=full gnunet-0.10.1/src/transport/test_transport_api_tcp_nat_peer1.conf0000644000175000017500000000124612225230043022230 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-nat-p1/ [nat] BEHIND_NAT = YES ENABLE_NAT_SERVER = YES DISABLEV6 = YES [transport-tcp] PORT = 0 TIMEOUT = 5 s [arm] PORT = 1204 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12023 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12022 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12021 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 29542 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/gnunet-helper-transport-bluetooth.c0000644000175000017500000022206212316473377021634 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors) Copyright (c) 2007, 2008, Andy Green Copyright (C) 2009 Thomas d'Otreppe GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gnunet_config.h" #ifdef MINGW #include "platform.h" #include "gnunet_util_lib.h" #include #include #else #define SOCKTYPE int #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #include "plugin_transport_wlan.h" #include "gnunet_protocols.h" /** * Maximum number of ports assignable for RFCOMMM protocol. */ #define MAX_PORTS 30 /** * Maximum size of a message allowed in either direction * (used for our receive and sent buffers). */ #define MAXLINE 4096 /** * Maximum number of loops without inquiring for new devices. */ #define MAX_LOOPS 5 #ifdef MINGW /* Maximum size of the interface's name */ #define IFNAMSIZ 16 #ifndef NS_BTH #define NS_BTH 16 #endif /** * A copy of the MAC Address. */ struct GNUNET_TRANSPORT_WLAN_MacAddress_Copy { UINT8 mac[MAC_ADDR_SIZE]; }; /** * The UUID used for the SDP service. * {31191E56-FA7E-4517-870E-71B86BBCC52F} */ #define GNUNET_BLUETOOTH_SDP_UUID \ { \ 0x31, 0x19, 0x1E, 0x56, \ 0xFA, 0x7E, \ 0x45, 0x17, \ 0x87, 0x0E, \ 0x71, 0xB8, 0x6B, 0xBC, 0xC5, 0x2F \ } #endif /** * In bluez library, the maximum name length of a device is 8 */ #define BLUEZ_DEVNAME_SIZE 8 /** * struct for storing the information of the hardware. There is only * one of these. */ struct HardwareInfos { /** * Name of the interface, not necessarily 0-terminated (!). */ char iface[IFNAMSIZ]; #ifdef MINGW /** * socket handle */ struct GNUNET_NETWORK_Handle *handle; /** * MAC address of our own bluetooth interface. */ struct GNUNET_TRANSPORT_WLAN_MacAddress_Copy pl_mac; #else /** * file descriptor for the rfcomm socket */ int fd_rfcomm; /** * MAC address of our own bluetooth interface. */ struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac; /** * SDP session */ sdp_session_t *session ; #endif }; /** * IO buffer used for buffering data in transit (to wireless or to stdout). */ struct SendBuffer { /** * How many bytes of data are stored in 'buf' for transmission right now? * Data always starts at offset 0 and extends to 'size'. */ size_t size; /** * How many bytes that were stored in 'buf' did we already write to the * destination? Always smaller than 'size'. */ size_t pos; /** * Buffered data; twice the maximum allowed message size as we add some * headers. */ char buf[MAXLINE * 2]; }; #ifdef LINUX /** * Devices buffer used to keep a list with all the discoverable devices in * order to send them HELLO messages one by one when it receive a broadcast message. */ struct BroadcastMessages { /* List with the discoverable devices' addresses */ bdaddr_t devices[MAX_PORTS]; /* List with the open sockets */ int fds[MAX_PORTS]; /* The number of the devices */ int size; /* The current position */ int pos; /* The device id */ int dev_id; }; /** * Address used to identify the broadcast messages. */ static struct GNUNET_TRANSPORT_WLAN_MacAddress broadcast_address = {{255, 255, 255, 255, 255, 255}}; /** * Buffer with the discoverable devices. */ static struct BroadcastMessages neighbours; static int searching_devices_count = 0; #endif /** * Buffer for data read from stdin to be transmitted to the bluetooth device */ static struct SendBuffer write_pout; /** * Buffer for data read from the bluetooth device to be transmitted to stdout. */ static struct SendBuffer write_std; /* ****** this are the same functions as the ones used in gnunet-helper-transport-wlan.c ****** */ /** * To what multiple do we align messages? 8 byte should suffice for everyone * for now. */ #define ALIGN_FACTOR 8 /** * Smallest supported message. */ #define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader) /** * Functions with this signature are called whenever a * complete message is received by the tokenizer. * * @param cls closure * @param message the actual message */ typedef void (*MessageTokenizerCallback) (void *cls, const struct GNUNET_MessageHeader * message); /** * Handle to a message stream tokenizer. */ struct MessageStreamTokenizer { /** * Function to call on completed messages. */ MessageTokenizerCallback cb; /** * Closure for cb. */ void *cb_cls; /** * Size of the buffer (starting at 'hdr'). */ size_t curr_buf; /** * How many bytes in buffer have we already processed? */ size_t off; /** * How many bytes in buffer are valid right now? */ size_t pos; /** * Beginning of the buffer. Typed like this to force alignment. */ struct GNUNET_MessageHeader *hdr; }; /** * Create a message stream tokenizer. * * @param cb function to call on completed messages * @param cb_cls closure for cb * @return handle to tokenizer */ static struct MessageStreamTokenizer * mst_create (MessageTokenizerCallback cb, void *cb_cls) { struct MessageStreamTokenizer *ret; ret = malloc (sizeof (struct MessageStreamTokenizer)); if (NULL == ret) { fprintf (stderr, "Failed to allocate buffer for tokenizer\n"); exit (1); } ret->hdr = malloc (MIN_BUFFER_SIZE); if (NULL == ret->hdr) { fprintf (stderr, "Failed to allocate buffer for alignment\n"); exit (1); } ret->curr_buf = MIN_BUFFER_SIZE; ret->cb = cb; ret->cb_cls = cb_cls; ret->pos = 0; return ret; } /** * Add incoming data to the receive buffer and call the * callback for all complete messages. * * @param mst tokenizer to use * @param buf input data to add * @param size number of bytes in buf * @return GNUNET_OK if we are done processing (need more data) * GNUNET_SYSERR if the data stream is corrupt */ static int mst_receive (struct MessageStreamTokenizer *mst, const char *buf, size_t size) { const struct GNUNET_MessageHeader *hdr; size_t delta; uint16_t want; char *ibuf; int need_align; unsigned long offset; int ret; ret = GNUNET_OK; ibuf = (char *) mst->hdr; while (mst->pos > 0) { do_align: if (mst->pos < mst->off) { //fprintf (stderr, "We processed too many bytes!\n"); return GNUNET_SYSERR; } if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) || (0 != (mst->off % ALIGN_FACTOR))) { /* need to align or need more space */ mst->pos -= mst->off; memmove (ibuf, &ibuf[mst->off], mst->pos); mst->off = 0; } if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) { delta = GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) - (mst->pos - mst->off), size); memcpy (&ibuf[mst->pos], buf, delta); mst->pos += delta; buf += delta; size -= delta; } if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader)) { //FIXME should I reset ?? // mst->off = 0; // mst->pos = 0; return GNUNET_OK; } hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; want = ntohs (hdr->size); if (want < sizeof (struct GNUNET_MessageHeader)) { fprintf (stderr, "Received invalid message from stdin\n"); return GNUNET_SYSERR; } if ((mst->curr_buf - mst->off < want) && (mst->off > 0)) { /* need more space */ mst->pos -= mst->off; memmove (ibuf, &ibuf[mst->off], mst->pos); mst->off = 0; } if (want > mst->curr_buf) { if (mst->off != 0) { fprintf (stderr, "Error! We should proceeded 0 bytes\n"); return GNUNET_SYSERR; } mst->hdr = realloc (mst->hdr, want); if (NULL == mst->hdr) { fprintf (stderr, "Failed to allocate buffer for alignment\n"); exit (1); } ibuf = (char *) mst->hdr; mst->curr_buf = want; } hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off]; if (mst->pos - mst->off < want) { delta = GNUNET_MIN (want - (mst->pos - mst->off), size); if (mst->pos + delta > mst->curr_buf) { fprintf (stderr, "The size of the buffer will be exceeded!\n"); return GNUNET_SYSERR; } memcpy (&ibuf[mst->pos], buf, delta); mst->pos += delta; buf += delta; size -= delta; } if (mst->pos - mst->off < want) { //FIXME should I use this? // mst->off = 0; // mst->pos = 0; return GNUNET_OK; } mst->cb (mst->cb_cls, hdr); mst->off += want; if (mst->off == mst->pos) { /* reset to beginning of buffer, it's free right now! */ mst->off = 0; mst->pos = 0; } } if (0 != mst->pos) { fprintf (stderr, "There should some valid bytes in the buffer on this stage\n"); return GNUNET_SYSERR; } while (size > 0) { if (size < sizeof (struct GNUNET_MessageHeader)) break; offset = (unsigned long) buf; need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO; if (GNUNET_NO == need_align) { /* can try to do zero-copy and process directly from original buffer */ hdr = (const struct GNUNET_MessageHeader *) buf; want = ntohs (hdr->size); if (want < sizeof (struct GNUNET_MessageHeader)) { fprintf (stderr, "Received invalid message from stdin\n"); //exit (1); mst->off = 0; return GNUNET_SYSERR; } if (size < want) break; /* or not, buffer incomplete, so copy to private buffer... */ mst->cb (mst->cb_cls, hdr); buf += want; size -= want; } else { /* need to copy to private buffer to align; * yes, we go a bit more spagetti than usual here */ goto do_align; } } if (size > 0) { if (size + mst->pos > mst->curr_buf) { mst->hdr = realloc (mst->hdr, size + mst->pos); if (NULL == mst->hdr) { fprintf (stderr, "Failed to allocate buffer for alignment\n"); exit (1); } ibuf = (char *) mst->hdr; mst->curr_buf = size + mst->pos; } if (mst->pos + size > mst->curr_buf) { fprintf (stderr, "Assertion failed\n"); exit (1); } memcpy (&ibuf[mst->pos], buf, size); mst->pos += size; } return ret; } /** * Destroys a tokenizer. * * @param mst tokenizer to destroy */ static void mst_destroy (struct MessageStreamTokenizer *mst) { free (mst->hdr); free (mst); } /** * Calculate crc32, the start of the calculation * * @param buf buffer to calc the crc * @param len len of the buffer * @return crc sum */ static unsigned long calc_crc_osdep (const unsigned char *buf, size_t len) { static const unsigned long int crc_tbl_osdep[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; unsigned long crc = 0xFFFFFFFF; for (; len > 0; len--, buf++) crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8); return (~crc); } /** * Calculate and check crc of the bluetooth packet * * @param buf buffer of the packet, with len + 4 bytes of data, * the last 4 bytes being the checksum * @param len length of the payload in data * @return 0 on success (checksum matches), 1 on error */ static int check_crc_buf_osdep (const unsigned char *buf, size_t len) { unsigned long crc; crc = calc_crc_osdep (buf, len); buf += len; if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] && ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3]) return 0; return 1; } /* ************** end of clone ***************** */ #ifdef MINGW /** * Function used to get the code of last error and to print the type of error. */ static void print_last_error() { LPVOID lpMsgBuf = NULL; if (FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, (LPTSTR) &lpMsgBuf, 0, NULL)) fprintf (stderr, "%s\n", (char *)lpMsgBuf); else fprintf (stderr, "Failed to format the message for the last error! Error number : %d\n", GetLastError()); } /** * Function used to initialize the Windows Sockets */ static void initialize_windows_sockets() { WSADATA wsaData ; WORD wVersionRequested = MAKEWORD (2, 0); if (WSAStartup (wVersionRequested, &wsaData) != NO_ERROR) { fprintf (stderr , "Error initializing window sockets!\n"); print_last_error(); ExitProcess (2) ; } } /** * Function used to convert the GUID. * @param bytes the GUID represented as a char array * @param uuid pointer to the GUID */ static void convert_guid(char *bytes, GUID * uuid) { int i; uuid->Data1 = ((bytes[0] << 24) & 0xff000000) | ((bytes[1] << 16) & 0x00ff0000) | ((bytes[2] << 8) & 0x0000ff00) | (bytes[3] & 0x000000ff); uuid->Data2 = ((bytes[4] << 8) & 0xff00) | (bytes[5] & 0x00ff); uuid->Data3 = ((bytes[6] << 8) & 0xff00) | (bytes[7] & 0x00ff); for (i = 0; i < 8; i++) { uuid->Data4[i] = bytes[i + 8]; } } #endif #ifdef LINUX /** * Function for assigning a port number * * @param socket the socket used to bind * @param addr pointer to the rfcomm address * @return 0 on success */ static int bind_socket (int socket, struct sockaddr_rc *addr) { int port, status; /* Bind every possible port (from 0 to 30) and stop when binding doesn't fail */ //FIXME : it should start from port 1, but on my computer it doesn't work :) for (port = 3; port <= 30; port++) { addr->rc_channel = port; status = bind (socket, (struct sockaddr *) addr, sizeof (struct sockaddr_rc)); if (status == 0) return 0; } return -1; } #endif #ifdef MINGW /** * Function used for creating the service record and registering it. * * @param dev pointer to the device struct * @return 0 on success */ static int register_service (struct HardwareInfos *dev) { /* advertise the service */ CSADDR_INFO addr_info; WSAQUERYSET wqs; GUID guid; unsigned char uuid[] = GNUNET_BLUETOOTH_SDP_UUID; SOCKADDR_BTH addr; int addr_len = sizeof (SOCKADDR_BTH); int fd; /* get the port on which we are listening on */ memset (& addr, 0, sizeof (SOCKADDR_BTH)); fd = GNUNET_NETWORK_get_fd (dev->handle); if (fd <= 0) { fprintf (stderr, "Failed to get the file descriptor\n"); return -1; } if (SOCKET_ERROR == getsockname (fd, (SOCKADDR*)&addr, &addr_len)) { fprintf (stderr, "Failed to get the port on which we are listening on: \n"); print_last_error(); return -1; } /* save the device address */ memcpy (&dev->pl_mac, &addr.btAddr, sizeof (BTH_ADDR)); /* set the address information */ memset (&addr_info, 0, sizeof (CSADDR_INFO)); addr_info.iProtocol = BTHPROTO_RFCOMM; addr_info.iSocketType = SOCK_STREAM; addr_info.LocalAddr.lpSockaddr = (LPSOCKADDR)&addr; addr_info.LocalAddr.iSockaddrLength = sizeof (addr); addr_info.RemoteAddr.lpSockaddr = (LPSOCKADDR)&addr; addr_info.RemoteAddr.iSockaddrLength = sizeof (addr); convert_guid((char *) uuid, &guid); /* register the service */ memset (&wqs, 0, sizeof (WSAQUERYSET)); wqs.dwSize = sizeof (WSAQUERYSET); wqs.dwNameSpace = NS_BTH; wqs.lpszServiceInstanceName = "GNUnet Bluetooth Service"; wqs.lpszComment = "This is the service used by the GNUnnet plugin transport"; wqs.lpServiceClassId = &guid; wqs.dwNumberOfCsAddrs = 1; wqs.lpcsaBuffer = &addr_info ; wqs.lpBlob = 0; if (SOCKET_ERROR == WSASetService (&wqs , RNRSERVICE_REGISTER, 0)) { fprintf (stderr, "Failed to register the SDP service: "); print_last_error(); return -1; } else { fprintf (stderr, "The SDP service was registered\n"); } return 0; } #else /** * Function used for creating the service record and registering it. * * @param dev pointer to the device struct * @param rc_channel the rfcomm channel * @return 0 on success */ static int register_service (struct HardwareInfos *dev, int rc_channel) { /** * 1. initializations * 2. set the service ID, class, profile information * 3. make the service record publicly browsable * 4. register the RFCOMM channel * 5. set the name, provider and description * 6. register the service record to the local SDP server * 7. cleanup */ uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dev->pl_mac.mac[5], dev->pl_mac.mac[4], dev->pl_mac.mac[3], dev->pl_mac.mac[2], dev->pl_mac.mac[1], dev->pl_mac.mac[0]}; const char *service_dsc = "Bluetooth plugin services"; const char *service_prov = "GNUnet provider"; uuid_t root_uuid, rfcomm_uuid, svc_uuid; sdp_list_t *root_list = 0, *rfcomm_list = 0, *proto_list = 0, *access_proto_list = 0, *svc_list = 0; sdp_record_t *record = 0; sdp_data_t *channel = 0; record = sdp_record_alloc(); /* Set the general service ID */ sdp_uuid128_create (&svc_uuid, &svc_uuid_int); svc_list = sdp_list_append (0, &svc_uuid); sdp_set_service_classes (record, svc_list); sdp_set_service_id (record, svc_uuid); /* Make the service record publicly browsable */ sdp_uuid16_create (&root_uuid, PUBLIC_BROWSE_GROUP); root_list = sdp_list_append (0, &root_uuid); sdp_set_browse_groups (record, root_list); /* Register the RFCOMM channel */ sdp_uuid16_create (&rfcomm_uuid, RFCOMM_UUID); channel = sdp_data_alloc (SDP_UINT8, &rc_channel); rfcomm_list = sdp_list_append (0, &rfcomm_uuid); sdp_list_append (rfcomm_list, channel); proto_list = sdp_list_append (0, rfcomm_list); /* Set protocol information */ access_proto_list = sdp_list_append (0, proto_list); sdp_set_access_protos (record, access_proto_list); /* Set the name, provider, and description */ sdp_set_info_attr (record, dev->iface, service_prov, service_dsc); /* Connect to the local SDP server */ dev->session = sdp_connect (BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); if (!dev->session) { fprintf (stderr, "Failed to connect to the SDP server on interface `%.*s': %s\n", IFNAMSIZ, dev->iface, strerror (errno)); //FIXME exit? return 1; } /* Register the service record */ if (sdp_record_register (dev->session, record, 0) < 0) { fprintf (stderr, "Failed to register a service record on interface `%.*s': %s\n", IFNAMSIZ, dev->iface, strerror (errno)); //FIXME exit? return 1; } /* Cleanup */ sdp_data_free (channel); sdp_list_free (root_list, 0); sdp_list_free (rfcomm_list, 0); sdp_list_free (proto_list, 0); sdp_list_free (access_proto_list, 0); sdp_list_free (svc_list, 0); sdp_record_free (record); return 0; } #endif #ifdef MINGW /** * Function for searching and browsing for a service. This will return the * port number on which the service is running. * * @param dest target address * @return channel */ static int get_channel(const char *dest) { HANDLE h; WSAQUERYSET *wqs; DWORD wqs_len = sizeof (WSAQUERYSET); int done = 0; int channel = -1; GUID guid; unsigned char uuid[] = GNUNET_BLUETOOTH_SDP_UUID; convert_guid ((char *) uuid, &guid); wqs = (WSAQUERYSET*)malloc (wqs_len); ZeroMemory (wqs, wqs_len); wqs->dwSize = sizeof (WSAQUERYSET) ; wqs->lpServiceClassId = &guid; wqs->dwNameSpace = NS_BTH; wqs->dwNumberOfCsAddrs = 0; wqs->lpszContext = (LPSTR)dest; if (SOCKET_ERROR == WSALookupServiceBegin (wqs, LUP_FLUSHCACHE | LUP_RETURN_ALL, &h)) { if (GetLastError() == WSASERVICE_NOT_FOUND) { fprintf (stderr, "WARNING! The device with address %s wasn't found. Skipping the message!", dest); return -1; } else { fprintf (stderr, "Failed to find the port number: "); print_last_error(); ExitProcess (2); return -1; } } /* search the sdp service */ while (!done) { if (SOCKET_ERROR == WSALookupServiceNext (h, LUP_FLUSHCACHE | LUP_RETURN_ALL, &wqs_len, wqs)) { int error = WSAGetLastError(); switch (error) { case WSAEFAULT: free (wqs); wqs = (WSAQUERYSET*)malloc (wqs_len); break; case WSANO_DATA: fprintf (stderr, "Failed! The address was valid but there was no data record of requested type\n"); done = 1; break; case WSA_E_NO_MORE: done = 1; break; default: fprintf (stderr, "Failed to look over the services: "); print_last_error(); WSALookupServiceEnd (h); ExitProcess (2); } } else { channel = ((SOCKADDR_BTH*)wqs->lpcsaBuffer->RemoteAddr.lpSockaddr)->port; } } free (wqs) ; WSALookupServiceEnd (h); return channel; } #else /** * Function used for searching and browsing for a service. This will return the * port number on which the service is running. * * @param dev pointer to the device struct * @param dest target address * @return channel */ static int get_channel(struct HardwareInfos *dev, bdaddr_t dest) { /** * 1. detect all nearby devices * 2. for each device: * 2.1. connect to the SDP server running * 2.2. get a list of service records with the specific UUID * 2.3. for each service record get a list of the protocol sequences and get * the port number */ uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dest.b[5], dest.b[4], dest.b[3], dest.b[2], dest.b[1], dest.b[0]}; sdp_session_t *session = 0; sdp_list_t *search_list = 0, *attrid_list = 0, *response_list = 0, *it = 0; uuid_t svc_uuid; uint32_t range = 0x0000ffff; uint8_t channel = -1; /* Connect to the local SDP server */ session = sdp_connect (BDADDR_ANY, &dest, 0); if (!session) { fprintf (stderr, "Failed to connect to the SDP server on interface `%.*s': %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return -1; } sdp_uuid128_create (&svc_uuid, &svc_uuid_int); search_list = sdp_list_append (0, &svc_uuid); attrid_list = sdp_list_append (0, &range); if (sdp_service_search_attr_req (session, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list) == 0) { for (it = response_list; it; it = it->next) { sdp_record_t *record = (sdp_record_t*) it->data; sdp_list_t *proto_list = 0; if (sdp_get_access_protos (record, &proto_list) == 0) { channel = sdp_get_proto_port (proto_list, RFCOMM_UUID); sdp_list_free (proto_list, 0); } sdp_record_free (record); } } sdp_list_free (search_list, 0); sdp_list_free (attrid_list, 0); sdp_list_free (response_list, 0); sdp_close (session); if (channel == -1) fprintf (stderr, "Failed to find the listening channel for interface `%.*s': %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return channel; } #endif /** * Read from the socket and put the result into the buffer for transmission to 'stdout'. * * @param sock file descriptor for reading * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame', * followed by the actual payload * @param buf_size size of the buffer * @param ri where to write radiotap_rx info * @return number of bytes written to 'buf' */ static ssize_t read_from_the_socket (void *sock, unsigned char *buf, size_t buf_size, struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri) { unsigned char tmpbuf[buf_size]; ssize_t count; #ifdef MINGW count = GNUNET_NETWORK_socket_recv ((struct GNUNET_NETWORK_Handle *)sock, tmpbuf, buf_size); #else count = read (*((int *)sock), tmpbuf, buf_size); #endif if (0 > count) { if (EAGAIN == errno) return 0; #if MINGW print_last_error(); #else fprintf (stderr, "Failed to read from the HCI socket: %s\n", strerror (errno)); #endif return -1; } #ifdef LINUX /* Get the channel used */ int len; struct sockaddr_rc rc_addr = { 0 }; memset (&rc_addr, 0, sizeof (rc_addr)); len = sizeof (rc_addr); if (0 > getsockname (*((int *)sock), (struct sockaddr *) &rc_addr, (socklen_t *) &len)) { fprintf (stderr, "getsockname() call failed : %s\n", strerror (errno)); return -1; } memset (ri, 0, sizeof (*ri)); ri->ri_channel = rc_addr.rc_channel; #endif /* Detect CRC32 at the end */ if (0 == check_crc_buf_osdep (tmpbuf, count - sizeof (uint32_t))) { count -= sizeof(uint32_t); } memcpy (buf, tmpbuf, count); return count; } /** * Open the bluetooth interface for reading/writing * * @param dev pointer to the device struct * @return 0 on success */ static int open_device (struct HardwareInfos *dev) { #ifdef MINGW SOCKADDR_BTH addr; /* bind the RFCOMM socket to the interface */ addr.addressFamily = AF_BTH; addr.btAddr = 0; addr.port = BT_PORT_ANY; if (GNUNET_OK != GNUNET_NETWORK_socket_bind (dev->handle, (const SOCKADDR*)&addr, sizeof (SOCKADDR_BTH))) { fprintf (stderr, "Failed to bind the socket: "); if (GetLastError() == WSAENETDOWN) { fprintf (stderr, "Please make sure that your Bluetooth device is ON!\n"); ExitProcess (2); } print_last_error(); return -1; } /* start listening on the socket */ if (GNUNET_NETWORK_socket_listen (dev->handle, 4) != GNUNET_OK) { fprintf (stderr, "Failed to listen on the socket: "); print_last_error(); return -1; } /* register the sdp service */ if (register_service(dev) != 0) { fprintf (stderr, "Failed to register a service: "); print_last_error(); return 1; } #else int i, dev_id = -1, fd_hci; struct { struct hci_dev_list_req list; struct hci_dev_req dev[HCI_MAX_DEV]; } request; //used for detecting the local devices struct sockaddr_rc rc_addr = { 0 }; //used for binding /* Initialize the neighbour structure */ neighbours.dev_id = -1; for (i = 0; i < MAX_PORTS; i++) neighbours.fds[i] = -1; /* Open a HCI socket */ fd_hci = socket (AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (fd_hci < 0) { fprintf (stderr, "Failed to create HCI socket: %s\n", strerror (errno)); return -1; } memset (&request, 0, sizeof(request)); request.list.dev_num = HCI_MAX_DEV; if (ioctl (fd_hci, HCIGETDEVLIST, (void *) &request) < 0) { fprintf (stderr, "ioctl(HCIGETDEVLIST) on interface `%.*s' failed: %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } /* Search for a device with dev->iface name */ for (i = 0; i < request.list.dev_num; i++) { struct hci_dev_info dev_info; memset (&dev_info, 0, sizeof(struct hci_dev_info)); dev_info.dev_id = request.dev[i].dev_id; strncpy (dev_info.name, dev->iface, BLUEZ_DEVNAME_SIZE); if (ioctl (fd_hci, HCIGETDEVINFO, (void *) &dev_info)) { fprintf (stderr, "ioctl(HCIGETDEVINFO) on interface `%.*s' failed: %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } if (strncmp (dev_info.name, dev->iface, BLUEZ_DEVNAME_SIZE) == 0) { dev_id = dev_info.dev_id; //the device was found /** * Copy the MAC address to the device structure */ memcpy (&dev->pl_mac, &dev_info.bdaddr, sizeof (bdaddr_t)); /* Check if the interface is up */ if (hci_test_bit (HCI_UP, (void *) &dev_info.flags) == 0) { /* Bring the interface up */ if (ioctl (fd_hci, HCIDEVUP, dev_info.dev_id)) { fprintf (stderr, "ioctl(HCIDEVUP) on interface `%.*s' failed: %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } } /* Check if the device is discoverable */ if (hci_test_bit (HCI_PSCAN, (void *) &dev_info.flags) == 0 || hci_test_bit (HCI_ISCAN, (void *) &dev_info.flags) == 0) { /* Set interface Page Scan and Inqury Scan ON */ struct hci_dev_req dev_req; memset (&dev_req, 0, sizeof (dev_req)); dev_req.dev_id = dev_info.dev_id; dev_req.dev_opt = SCAN_PAGE | SCAN_INQUIRY; if (ioctl (fd_hci, HCISETSCAN, (unsigned long) &dev_req)) { fprintf (stderr, "ioctl(HCISETSCAN) on interface `%.*s' failed: %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } } break; } } /* Check if the interface was not found */ if (dev_id == -1) { fprintf (stderr, "The interface %s was not found\n", dev->iface); return 1; } /* Close the hci socket */ (void) close(fd_hci); /* Bind the rfcomm socket to the interface */ memset (&rc_addr, 0, sizeof (rc_addr)); rc_addr.rc_family = AF_BLUETOOTH; rc_addr.rc_bdaddr = *BDADDR_ANY; if (bind_socket (dev->fd_rfcomm, &rc_addr) != 0) { fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } /* Register a SDP service */ if (register_service (dev, rc_addr.rc_channel) != 0) { fprintf (stderr, "Failed to register a service on interface `%.*s': %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } /* Switch socket in listening mode */ if (listen (dev->fd_rfcomm, 5) == -1) //FIXME: probably we need a bigger number { fprintf (stderr, "Failed to listen on socket for interface `%.*s': %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } #endif return 0; } /** * Set the header to sane values to make attacks more difficult * * @param taIeeeHeader pointer to the header of the packet * @param dev pointer to the Hardware_Infos struct * **** copy from gnunet-helper-transport-wlan.c **** */ static void mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader, const struct HardwareInfos *dev) { taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA); taIeeeHeader->addr3 = mac_bssid_gnunet; #ifdef MINGW memcpy (&taIeeeHeader->addr2, &dev->pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)); #else taIeeeHeader->addr2 = dev->pl_mac; #endif } #ifdef LINUX /** * Test if the given interface name really corresponds to a bluetooth * device. * * @param iface name of the interface * @return 0 on success, 1 on error **** similar with the one from gnunet-helper-transport-wlan.c **** */ static int test_bluetooth_interface (const char *iface) { char strbuf[512]; struct stat sbuf; int ret; ret = snprintf (strbuf, sizeof (strbuf), "/sys/class/bluetooth/%s/subsystem", iface); if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf))) { fprintf (stderr, "Did not find 802.15.1 interface `%s'. Exiting.\n", iface); exit (1); } return 0; } #endif /** * Test incoming packets mac for being our own. * * @param taIeeeHeader buffer of the packet * @param dev the Hardware_Infos struct * @return 0 if mac belongs to us, 1 if mac is for another target * **** same as the one from gnunet-helper-transport-wlan.c **** */ static int mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader, const struct HardwareInfos *dev) { static struct GNUNET_TRANSPORT_WLAN_MacAddress all_zeros; if ( (0 == memcmp (&taIeeeHeader->addr3, &all_zeros, MAC_ADDR_SIZE)) || (0 == memcmp (&taIeeeHeader->addr1, &all_zeros, MAC_ADDR_SIZE)) ) return 0; /* some drivers set no Macs, then assume it is all for us! */ if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE)) return 1; /* not a GNUnet ad-hoc package */ if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) || (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) ) return 0; /* for us, or broadcast */ return 1; /* not for us */ } /** * Process data from the stdin. Takes the message, forces the sender MAC to be correct * and puts it into our buffer for transmission to the receiver. * * @param cls pointer to the device struct ('struct HardwareInfos*') * @param hdr pointer to the start of the packet * **** same as the one from gnunet-helper-transport-wlan.c **** */ static void stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr) { struct HardwareInfos *dev = cls; const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header; struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *blueheader; size_t sendsize; sendsize = ntohs (hdr->size); if ( (sendsize < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) || (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) ) { fprintf (stderr, "Received malformed message\n"); exit (1); } sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame)); if (MAXLINE < sendsize) { fprintf (stderr, "Packet too big for buffer\n"); exit (1); } header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr; memcpy (&write_pout.buf, &header->frame, sendsize); blueheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf; /* payload contains MAC address, but we don't trust it, so we'll * overwrite it with OUR MAC address to prevent mischief */ mac_set (blueheader, dev); memcpy (&blueheader->addr1, &header->frame.addr1, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)); write_pout.size = sendsize; } #ifdef LINUX /** * Broadcast a HELLO message for peer discovery * * @param dev pointer to the device struct * @param dev pointer to the socket which was added to the set * @return 0 on success */ static int send_broadcast (struct HardwareInfos *dev, int *sendsocket) { int new_device = 0; int loops = 0; search_for_devices: if ((neighbours.size == neighbours.pos && new_device == 1) || neighbours.size == 0) { inquiry_devices: //skip the conditions and force a inquiry for new devices { /** * It means that I sent HELLO messages to all the devices from the list and I should search * for new ones or that this is the first time when I do a search. */ inquiry_info *devices = NULL; int i, responses, max_responses = MAX_PORTS; /* sanity checks */ if (neighbours.size >= MAX_PORTS) { fprintf (stderr, "%.*s reached the top limit for the discovarable devices\n", IFNAMSIZ, dev->iface); return 2; } /* Get the device id */ if (neighbours.dev_id == -1) { char addr[19] = { 0 }; //the device MAC address ba2str ((bdaddr_t *) &dev->pl_mac, addr); neighbours.dev_id = hci_devid (addr); if (neighbours.dev_id < 0) { fprintf (stderr, "Failed to get the device id for interface %.*s : %s\n", IFNAMSIZ, dev->iface, strerror (errno)); return 1; } } devices = malloc (max_responses * sizeof (inquiry_info)); if (devices == NULL) { fprintf (stderr, "Failed to allocate memory for inquiry info list on interface %.*s\n", IFNAMSIZ, dev->iface); return 1; } responses = hci_inquiry (neighbours.dev_id, 8, max_responses, NULL, &devices, IREQ_CACHE_FLUSH); if (responses < 0) { fprintf (stderr, "Failed to inquiry on interface %.*s\n", IFNAMSIZ, dev->iface); return 1; } fprintf (stderr, "LOG : Found %d devices\n", responses); //FIXME delete it after debugging stage if (responses == 0) { fprintf (stderr, "LOG : No devices discoverable\n"); return 1; } for (i = 0; i < responses; i++) { int j; int found = 0; /* sanity check */ if (i >= MAX_PORTS) { fprintf (stderr, "%.*s reached the top limit for the discoverable devices (after inquiry)\n", IFNAMSIZ, dev->iface); return 2; } /* Search if the address already exists on the list */ for (j = 0; j < neighbours.size; j++) { if (memcmp (&(devices + i)->bdaddr, &(neighbours.devices[j]), sizeof (bdaddr_t)) == 0) { found = 1; fprintf (stderr, "LOG : the device already exists on the list\n"); //FIXME debugging message break; } } if (found == 0) { char addr[19] = { 0 }; ba2str (&(devices +i)->bdaddr, addr); fprintf (stderr, "LOG : %s was added to the list\n", addr); //FIXME debugging message memcpy (&(neighbours.devices[neighbours.size++]), &(devices + i)->bdaddr, sizeof (bdaddr_t)); } } free (devices); } } int connection_successful = 0; struct sockaddr_rc addr_rc = { 0 }; int errno_copy = 0; addr_rc.rc_family = AF_BLUETOOTH; /* Try to connect to a new device from the list */ while (neighbours.pos < neighbours.size) { /* Check if we are already connected to this device */ if (neighbours.fds[neighbours.pos] == -1) { memset (&addr_rc.rc_bdaddr, 0, sizeof (addr_rc.rc_bdaddr)); memcpy (&addr_rc.rc_bdaddr, &(neighbours.devices[neighbours.pos]), sizeof (addr_rc.rc_bdaddr)); addr_rc.rc_channel = get_channel (dev, addr_rc.rc_bdaddr); *sendsocket = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (connect (*sendsocket, (struct sockaddr *)&addr_rc, sizeof (addr_rc)) == 0) { neighbours.fds[neighbours.pos++] = *sendsocket; connection_successful = 1; char addr[19] = { 0 }; ba2str (&(neighbours.devices[neighbours.pos - 1]), addr); fprintf (stderr, "LOG : Connected to %s\n", addr); break; } else { char addr[19] = { 0 }; errno_copy = errno; //Save a copy for later ba2str (&(neighbours.devices[neighbours.pos]), addr); fprintf (stderr, "LOG : Couldn't connect on device %s, error : %s\n", addr, strerror(errno)); if (errno != ECONNREFUSED) //FIXME be sure that this works { fprintf (stderr, "LOG : Removes %d device from the list\n", neighbours.pos); /* Remove the device from the list */ memcpy (&neighbours.devices[neighbours.pos], &neighbours.devices[neighbours.size - 1], sizeof (bdaddr_t)); memset (&neighbours.devices[neighbours.size - 1], 0, sizeof (bdaddr_t)); neighbours.fds[neighbours.pos] = neighbours.fds[neighbours.size - 1]; neighbours.fds[neighbours.size - 1] = -1; neighbours.size -= 1; } neighbours.pos += 1; if (neighbours.pos >= neighbours.size) neighbours.pos = 0; loops += 1; if (loops == MAX_LOOPS) //don't get stuck trying to connect to one device return 1; } } else { fprintf (stderr, "LOG : Search for a new device\n"); //FIXME debugging message neighbours.pos += 1; } } /* Cycle on the list */ if (neighbours.pos == neighbours.size) { neighbours.pos = 0; searching_devices_count += 1; if (searching_devices_count == MAX_LOOPS) { fprintf (stderr, "LOG : Force to inquiry for new devices\n"); searching_devices_count = 0; goto inquiry_devices; } } /* If a new device wasn't found, search an old one */ if (connection_successful == 0) { int loop_check = neighbours.pos; while (neighbours.fds[neighbours.pos] == -1) { if (neighbours.pos == neighbours.size) neighbours.pos = 0; if (neighbours.pos == loop_check) { if (errno_copy == ECONNREFUSED) { fprintf (stderr, "LOG : No device found. Go back and search again\n"); //FIXME debugging message new_device = 1; loops += 1; goto search_for_devices; } else { return 1; // Skip the broadcast message } } neighbours.pos += 1; } *sendsocket = neighbours.fds[neighbours.pos++]; } return 0; } #endif /** * Main function of the helper. This code accesses a bluetooth interface * forwards traffic in both directions between the bluetooth interface and * stdin/stdout of this process. Error messages are written to stderr. * * @param argc number of arguments, must be 2 * @param argv arguments only argument is the name of the interface (i.e. 'hci0') * @return 0 on success (never happens, as we don't return unless aborted), 1 on error * **** similar to gnunet-helper-transport-wlan.c **** */ int main (int argc, char *argv[]) { #ifdef LINUX struct HardwareInfos dev; char readbuf[MAXLINE]; int maxfd; fd_set rfds; fd_set wfds; int stdin_open; struct MessageStreamTokenizer *stdin_mst; int raw_eno, i; uid_t uid; int crt_rfds = 0, rfds_list[MAX_PORTS]; int broadcast, sendsocket; /* Assert privs so we can modify the firewall rules! */ uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, 0, 0)) { fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno)); return 254; } #else if (0 != seteuid (0)) { fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); return 254; } #endif /* Make use of SGID capabilities on POSIX */ memset (&dev, 0, sizeof (dev)); dev.fd_rfcomm = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); raw_eno = errno; /* remember for later */ /* Now that we've dropped root rights, we can do error checking */ if (2 != argc) { fprintf (stderr, "You must specify the name of the interface as the first \ and only argument to this program.\n"); if (-1 != dev.fd_rfcomm) (void) close (dev.fd_rfcomm); return 1; } if (-1 == dev.fd_rfcomm) { fprintf (stderr, "Failed to create a RFCOMM socket: %s\n", strerror (raw_eno)); return 1; } if (dev.fd_rfcomm >= FD_SETSIZE) { fprintf (stderr, "File descriptor too large for select (%d > %d)\n", dev.fd_rfcomm, FD_SETSIZE); (void) close (dev.fd_rfcomm); return 1; } if (0 != test_bluetooth_interface (argv[1])) { (void) close (dev.fd_rfcomm); return 1; } strncpy (dev.iface, argv[1], IFNAMSIZ); if (0 != open_device (&dev)) { (void) close (dev.fd_rfcomm); return 1; } /* Drop privs */ { uid_t uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, uid)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); if (-1 != dev.fd_rfcomm) (void) close (dev.fd_rfcomm); return 1; } #else if (0 != (setuid (uid) | seteuid (uid))) { fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); if (-1 != dev.fd_rfcomm) (void) close (dev.fd_rfcomm); return 1; } #endif } /* Send MAC address of the bluetooth interface to STDOUT first */ { struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg; macmsg.hdr.size = htons (sizeof (macmsg)); macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL); memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)); memcpy (write_std.buf, &macmsg, sizeof (macmsg)); write_std.size = sizeof (macmsg); } stdin_mst = mst_create (&stdin_send_hw, &dev); stdin_open = 1; /** * TODO : I should make the time out of a mac endpoint smaller and check if the rate * from get_wlan_header (plugin_transport_bluetooth.c) is correct. */ while (1) { maxfd = -1; broadcast = 0; sendsocket = -1; FD_ZERO (&rfds); if ((0 == write_pout.size) && (1 == stdin_open)) { FD_SET (STDIN_FILENO, &rfds); maxfd = MAX (maxfd, STDIN_FILENO); } if (0 == write_std.size) { FD_SET (dev.fd_rfcomm, &rfds); maxfd = MAX (maxfd, dev.fd_rfcomm); } for (i = 0; i < crt_rfds; i++) // it can receive messages from multiple devices { FD_SET (rfds_list[i], &rfds); maxfd = MAX (maxfd, rfds_list[i]); } FD_ZERO (&wfds); if (0 < write_std.size) { FD_SET (STDOUT_FILENO, &wfds); maxfd = MAX (maxfd, STDOUT_FILENO); } if (0 < write_pout.size) //it can send messages only to one device per loop { struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *frame; /* Get the destination address */ frame = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) write_pout.buf; if (memcmp (&frame->addr1, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0) { broadcast = 1; memset (&write_pout, 0, sizeof (write_pout)); //clear the buffer } else if (memcmp (&frame->addr1, &broadcast_address, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0) { fprintf (stderr, "LOG : %s has a broadcast message (pos %d, size %d)\n", dev.iface, neighbours.pos, neighbours.size); //FIXME: debugging message if (send_broadcast(&dev, &sendsocket) != 0) //if the searching wasn't successful don't get stuck on the select stage { broadcast = 1; memset (&write_pout, 0, sizeof (write_pout)); //remove the message fprintf (stderr, "LOG : Skipping the broadcast message (pos %d, size %d)\n", neighbours.pos, neighbours.size); } else { FD_SET (sendsocket, &wfds); maxfd = MAX (maxfd, sendsocket); } } else { int found = 0; int pos = 0; /* Search if the address already exists on the list */ for (i = 0; i < neighbours.size; i++) { if (memcmp (&frame->addr1, &(neighbours.devices[i]), sizeof (bdaddr_t)) == 0) { pos = i; if (neighbours.fds[i] != -1) { found = 1; //save the position where it was found FD_SET (neighbours.fds[i], &wfds); maxfd = MAX (maxfd, neighbours.fds[i]); sendsocket = neighbours.fds[i]; fprintf (stderr, "LOG: the address was found in the list\n"); break; } } } if (found == 0) { int status; struct sockaddr_rc addr = { 0 }; fprintf (stderr, "LOG : %s has a new message for %.2X:%.2X:%.2X:%.2X:%.2X:%.2X which isn't on the broadcast list\n", dev.iface, frame->addr1.mac[5], frame->addr1.mac[4], frame->addr1.mac[3], frame->addr1.mac[2], frame->addr1.mac[1], frame->addr1.mac[0]); //FIXME: debugging message sendsocket = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (sendsocket < 0) { fprintf (stderr, "Failed to create a RFCOMM socket (sending stage): %s\n", strerror (errno)); return -1; } memcpy (&addr.rc_bdaddr, &frame->addr1, sizeof (bdaddr_t)); addr.rc_family = AF_BLUETOOTH; addr.rc_channel = get_channel (&dev, addr.rc_bdaddr); int tries = 0; connect_retry: status = connect (sendsocket, (struct sockaddr *) &addr, sizeof (addr)); if (0 != status && errno != EAGAIN) { if (errno == ECONNREFUSED && tries < 2) { fprintf (stderr, "LOG : %.*s failed to connect. Trying again!\n", IFNAMSIZ, dev.iface); tries++; goto connect_retry; } else if (errno == EBADF) { fprintf (stderr, "LOG : %s failed to connect : %s. Skip it!\n", dev.iface, strerror (errno)); memset (&write_pout, 0, sizeof (write_pout)); broadcast = 1; } else { fprintf (stderr, "LOG : %s failed to connect : %s. Try again later!\n", dev.iface, strerror (errno)); memset (&write_pout, 0, sizeof (write_pout)); broadcast = 1; } } else { FD_SET (sendsocket, &wfds); maxfd = MAX (maxfd, sendsocket); fprintf (stderr, "LOG : Connection successful\n"); if (pos != 0) // save the socket { neighbours.fds[pos] = sendsocket; } else { /* Add the new device to the discovered devices list */ if (neighbours.size < MAX_PORTS) { neighbours.fds[neighbours.size] = sendsocket; memcpy (&(neighbours.devices[neighbours.size++]), &addr.rc_bdaddr, sizeof (bdaddr_t)); } else { fprintf (stderr, "The top limit for the discovarable devices' list was reached\n"); } } } } } } if (broadcast == 0) { /* Select a fd which is ready for action :) */ { int retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL); if ((-1 == retval) && (EINTR == errno)) continue; if (0 > retval && errno != EBADF) // we handle BADF errors later { fprintf (stderr, "select failed: %s\n", strerror (errno)); break; } } if (FD_ISSET (STDOUT_FILENO , &wfds)) { ssize_t ret = write (STDOUT_FILENO, write_std.buf + write_std.pos, write_std.size - write_std.pos); if (0 > ret) { fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno)); break; } write_std.pos += ret; if (write_std.pos == write_std.size) { write_std.pos = 0; write_std.size = 0; } fprintf (stderr, "LOG : %s sends a message to STDOUT\n", dev.iface); //FIXME: debugging message } if (sendsocket != -1) { if (FD_ISSET (sendsocket , &wfds)) { ssize_t ret = write (sendsocket, write_pout.buf + write_std.pos, write_pout.size - write_pout.pos); if (0 > ret) //FIXME should I first check the error type? { fprintf (stderr, "Failed to write to bluetooth device: %s. Closing the socket!\n", strerror (errno)); for (i = 0; i < neighbours.size; i++) { if (neighbours.fds[i] == sendsocket) { (void) close(sendsocket); neighbours.fds[i] = -1; break; } } /* Remove the message */ memset (&write_pout.buf + write_std.pos, 0, (write_pout.size - write_pout.pos)); write_pout.pos = 0 ; write_pout.size = 0; } else { write_pout.pos += ret; if ((write_pout.pos != write_pout.size) && (0 != ret)) { /* We should not get partial sends with packet-oriented devices... */ fprintf (stderr, "Write error, partial send: %u/%u\n", (unsigned int) write_pout.pos, (unsigned int) write_pout.size); break; } if (write_pout.pos == write_pout.size) { write_pout.pos = 0; write_pout.size = 0; } fprintf (stderr, "LOG : %s sends a message to a DEVICE\n", dev.iface); //FIXME: debugging message } } } for (i = 0; i <= maxfd; i++) { if (FD_ISSET (i, &rfds)) { if (i == STDIN_FILENO) { ssize_t ret = read (i, readbuf, sizeof (readbuf)); if (0 > ret) { fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno)); break; } if (0 == ret) { /* stop reading... */ stdin_open = 0; } else { mst_receive (stdin_mst, readbuf, ret); fprintf (stderr, "LOG : %s receives a message from STDIN\n", dev.iface); //FIXME: debugging message } } else if (i == dev.fd_rfcomm) { int readsocket; struct sockaddr_rc addr = { 0 }; unsigned int opt = sizeof (addr); readsocket = accept (dev.fd_rfcomm, (struct sockaddr *) &addr, &opt); fprintf(stderr, "LOG : %s accepts a message\n", dev.iface); //FIXME: debugging message if (readsocket == -1) { fprintf (stderr, "Failed to accept a connection on interface: %.*s\n", IFNAMSIZ, strerror (errno)); break; } else { FD_SET (readsocket, &rfds); maxfd = MAX (maxfd, readsocket); if (crt_rfds < MAX_PORTS) rfds_list[crt_rfds++] = readsocket; else { fprintf (stderr, "The limit for the read file descriptors list was \ reached\n"); break; } } } else { struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm; ssize_t ret; fprintf (stderr, "LOG : %s reads something from the socket\n", dev.iface);//FIXME : debugging message rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf; ret = read_from_the_socket ((void *)&i, (unsigned char *) &rrm->frame, sizeof (write_std.buf) - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame), rrm); if (0 >= ret) { int j; FD_CLR (i, &rfds); close (i); /* Remove the socket from the list */ for (j = 0; j < crt_rfds; j++) { if (rfds_list[j] == i) { rfds_list[j] ^= rfds_list[crt_rfds - 1]; rfds_list[crt_rfds - 1] ^= rfds_list[j]; rfds_list[j] ^= rfds_list[crt_rfds - 1]; crt_rfds -= 1; break; } } fprintf (stderr, "Read error from raw socket: %s\n", strerror (errno)); break; } if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev))) { write_std.size = ret + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame); rrm->header.size = htons (write_std.size); rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER); } } } } } } /* Error handling, try to clean up a bit at least */ mst_destroy (stdin_mst); stdin_mst = NULL; sdp_close (dev.session); (void) close (dev.fd_rfcomm); (void) close (sendsocket); for (i = 0; i < crt_rfds; i++) (void) close (rfds_list[i]); for (i = 0; i < neighbours.size; i++) (void) close (neighbours.fds[i]); #else struct HardwareInfos dev; struct GNUNET_NETWORK_Handle *sendsocket; struct GNUNET_NETWORK_FDSet *rfds; struct GNUNET_NETWORK_FDSet *wfds; struct GNUNET_NETWORK_Handle *rfds_list[MAX_PORTS]; char readbuf[MAXLINE] = { 0 }; SOCKADDR_BTH acc_addr = { 0 }; int addr_len = sizeof (SOCKADDR_BTH); int broadcast, i, stdin_open, crt_rfds = 0; HANDLE stdin_handle = GetStdHandle (STD_INPUT_HANDLE); HANDLE stdout_handle = GetStdHandle (STD_OUTPUT_HANDLE); struct MessageStreamTokenizer *stdin_mst; /* check the handles */ if (stdin_handle == INVALID_HANDLE_VALUE) { fprintf (stderr, "Failed to get the stdin handle\n"); ExitProcess (2); } if (stdout_handle == INVALID_HANDLE_VALUE) { fprintf (stderr, "Failed to get the stdout handle\n"); ExitProcess (2); } /* initialize windows sockets */ initialize_windows_sockets(); // /* test bluetooth socket family support */ --> it return false because the GNUNET_NETWORK_test_pf should also receive the type of socket (BTHPROTO_RFCOMM) // if (GNUNET_NETWORK_test_pf (AF_BTH) != GNUNET_OK) // { // fprintf (stderr, "AF_BTH family is not supported\n"); // ExitProcess (2); // } /* create the socket */ dev.handle = GNUNET_NETWORK_socket_create (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); if (dev.handle == NULL) { fprintf (stderr, "Failed to create RFCOMM socket: "); print_last_error(); ExitProcess (2); } if (open_device (&dev) == -1) { fprintf (stderr, "Failed to open the device\n"); print_last_error(); if (GNUNET_NETWORK_socket_close (dev.handle) != GNUNET_OK) { fprintf (stderr, "Failed to close the socket!\n"); print_last_error(); } ExitProcess (2); } if (GNUNET_OK != GNUNET_NETWORK_socket_set_blocking (dev.handle, 1) ) { fprintf (stderr, "Failed to change the socket mode\n"); ExitProcess (2); } memset (&write_std, 0, sizeof (write_std)); memset (&write_pout, 0, sizeof (write_pout)); stdin_open = 1; rfds = GNUNET_NETWORK_fdset_create (); wfds = GNUNET_NETWORK_fdset_create (); /* Send MAC address of the bluetooth interface to STDOUT first */ { struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg; macmsg.hdr.size = htons (sizeof (macmsg)); macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL); memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress_Copy)); memcpy (write_std.buf, &macmsg, sizeof (macmsg)); write_std.size = sizeof (macmsg); } stdin_mst = mst_create (&stdin_send_hw, &dev); stdin_open = 1; int pos = 0; int stdin_pos = -1; int stdout_pos = -1; while (1) { broadcast = 0; pos = 0; stdin_pos = -1; stdout_pos = -1; sendsocket = NULL; //FIXME ???memleaks GNUNET_NETWORK_fdset_zero (rfds); if ((0 == write_pout.size) && (1 == stdin_open)) { stdin_pos = pos; pos +=1; GNUNET_NETWORK_fdset_handle_set (rfds, (struct GNUNET_DISK_FileHandle*) &stdin_handle); } if (0 == write_std.size) { pos += 1; GNUNET_NETWORK_fdset_set (rfds, dev.handle); } for (i = 0; i < crt_rfds; i++) { pos += 1; GNUNET_NETWORK_fdset_set (rfds, rfds_list[i]); } GNUNET_NETWORK_fdset_zero (wfds); if (0 < write_std.size) { stdout_pos = pos; GNUNET_NETWORK_fdset_handle_set (wfds, (struct GNUNET_DISK_FileHandle*) &stdout_handle); // printf ("%s\n", write_std.buf); // memset (write_std.buf, 0, write_std.size); // write_std.size = 0; } if (0 < write_pout.size) { if (strcmp (argv[1], "ff:ff:ff:ff:ff:ff") == 0) { fprintf(stderr, "LOG: BROADCAST! Skipping the message\n"); // skip the message broadcast = 1; memset (write_pout.buf, 0, write_pout.size); write_pout.size = 0; } else { SOCKADDR_BTH addr; fprintf (stderr, "LOG : has a new message for %s\n", argv[1]); sendsocket = GNUNET_NETWORK_socket_create (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); if (sendsocket == NULL) { fprintf (stderr, "Failed to create RFCOMM socket: \n"); print_last_error(); ExitProcess (2); } memset (&addr, 0, sizeof (addr)); //addr.addressFamily = AF_BTH; if (SOCKET_ERROR == WSAStringToAddress (argv[1], AF_BTH, NULL, (LPSOCKADDR) &addr, &addr_len)) { fprintf (stderr, "Failed to translate the address: "); print_last_error(); ExitProcess ( 2 ) ; } addr.port = get_channel (argv[1]); if (addr.port == -1) { fprintf (stderr, "Couldn't find the sdp service for the address: %s\n", argv[1]); memset (write_pout.buf, 0, write_pout.size); write_pout.size = 0; broadcast = 1; //skipping the select part } else { if (GNUNET_OK != GNUNET_NETWORK_socket_connect (sendsocket, (LPSOCKADDR)&addr, addr_len)) { fprintf (stderr, "Failed to connect: "); print_last_error(); ExitProcess (2); } if (GNUNET_OK != GNUNET_NETWORK_socket_set_blocking (sendsocket, 1) ) { fprintf (stderr, "Failed to change the socket mode\n"); ExitProcess (2); } GNUNET_NETWORK_fdset_set (wfds, sendsocket); } } } if (broadcast == 0) { int retval = GNUNET_NETWORK_socket_select (rfds, wfds, NULL, GNUNET_TIME_relative_get_forever_()); if (retval < 0) { fprintf (stderr, "Select error\n"); ExitProcess (2); } //if (GNUNET_NETWORK_fdset_isset (wfds, (struct GNUNET_NETWORK_Handle*)&stdout_handle)) if (retval == stdout_pos) { fprintf(stderr, "LOG : sends a message to STDOUT\n"); //FIXME: debugging message //ssize_t ret; //ret = GNUNET_NETWORK_socket_send ((struct GNUNET_NETWORK_Handle *)&stdout_handle, write_std.buf + write_std.pos, write_std.size - write_std.pos); //ret = write (STDOUT_FILENO, write_std.buf + write_std.pos, write_std.size - write_std.pos); DWORD ret; if (FALSE == WriteFile (stdout_handle, write_std.buf + write_std.pos, write_std.size - write_std.pos, &ret, NULL)) { fprintf (stderr, "Failed to write to STDOUT: "); print_last_error(); break; } if (ret <= 0) { fprintf (stderr, "Failed to write to STDOUT\n"); ExitProcess (2); } write_std.pos += ret; if (write_std.pos == write_std.size) { write_std.pos = 0; write_std.size = 0; } } if (sendsocket != NULL) { if (GNUNET_NETWORK_fdset_isset (wfds, sendsocket)) { ssize_t ret; ret = GNUNET_NETWORK_socket_send (sendsocket, write_pout.buf + write_pout.pos, write_pout.size - write_pout.pos); if (GNUNET_SYSERR == ret) { fprintf (stderr, "Failed to send to the socket. Closing the socket. Error: \n"); print_last_error(); if (GNUNET_NETWORK_socket_close (sendsocket) != GNUNET_OK) { fprintf (stderr, "Failed to close the sendsocket!\n"); print_last_error(); } ExitProcess (2); } else { write_pout.pos += ret; if ((write_pout.pos != write_pout.size) && (0 != ret)) { /* we should not get partial sends with packet-oriented devices... */ fprintf (stderr, "Write error, partial send: %u/%u\n", (unsigned int) write_pout.pos, (unsigned int) write_pout.size); break; } if (write_pout.pos == write_pout.size) { write_pout.pos = 0; write_pout.size = 0; } fprintf(stderr, "LOG : sends a message to a DEVICE\n"); //FIXME: debugging message } } } //if (GNUNET_NETWORK_fdset_isset (rfds, (struct GNUNET_NETWORK_Handle*)&stdin_handle)) if (retval == stdin_pos) { //ssize_t ret; //ret = GNUNET_NETWORK_socket_recv ((struct GNUNET_NETWORK_Handle *)&stdin_handle, readbuf, sizeof (write_pout.buf)); //ret = read (STDIN_FILENO, readbuf, sizeof (readbuf)); DWORD ret; if (FALSE == ReadFile (stdin_handle, readbuf, sizeof (readbuf), &ret, NULL)) /* do nothing asynchronous */ { fprintf (stderr, "Read error from STDIN: "); print_last_error(); break; } if (0 == ret) { /* stop reading... */ stdin_open = 0; } else { mst_receive (stdin_mst, readbuf, ret); fprintf (stderr, "LOG : receives a message from STDIN\n"); //FIXME: debugging message } } else if (GNUNET_NETWORK_fdset_isset (rfds, dev.handle)) { fprintf (stderr, "LOG: accepting connection\n"); struct GNUNET_NETWORK_Handle *readsocket; readsocket = GNUNET_NETWORK_socket_accept (dev.handle, (LPSOCKADDR)&acc_addr, &addr_len); if (readsocket == NULL) { fprintf (stderr, "Accept error %d: ", GetLastError()); print_last_error(); ExitProcess (2); } else { if (GNUNET_OK != GNUNET_NETWORK_socket_set_blocking (readsocket, 1) ) { fprintf (stderr, "Failed to change the socket mode\n"); ExitProcess (2); } GNUNET_NETWORK_fdset_set (rfds, readsocket); if (crt_rfds < MAX_PORTS) rfds_list[crt_rfds++] = readsocket; else { fprintf (stderr, "The limit for the read file descriptors list was reached\n"); break; } } } else for (i = 0; i < crt_rfds; i++) { if (GNUNET_NETWORK_fdset_isset (rfds, rfds_list[i])) { struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm; ssize_t ret; fprintf (stderr, "LOG: reading something from the socket\n");//FIXME : debugging message rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf; ret = read_from_the_socket (rfds_list[i], (unsigned char *) &rrm->frame, sizeof (write_std.buf) - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame), rrm); if (0 >= ret) { //TODO remove the socket from the list if (GNUNET_NETWORK_socket_close (rfds_list[i]) != GNUNET_OK) { fprintf (stderr, "Failed to close the sendsocket!\n"); print_last_error(); } fprintf (stderr, "Read error from raw socket: "); print_last_error(); break; } if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev))) { write_std.size = ret + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame); rrm->header.size = htons (write_std.size); rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER); } break; } } } } mst_destroy (stdin_mst); stdin_mst = NULL; if (GNUNET_NETWORK_socket_close (dev.handle) != GNUNET_OK) { fprintf (stderr, "Failed to close the socket!\n"); print_last_error(); } for (i = 0; i < crt_rfds; i++) { if (GNUNET_NETWORK_socket_close (rfds_list[i]) != GNUNET_OK) { fprintf (stderr, "Failed to close the socket!\n"); print_last_error(); } } WSACleanup(); #endif return 1; /* we never exit 'normally' */ } gnunet-0.10.1/src/transport/test_quota_compliance_bluetooth_peer1.conf0000644000175000017500000000114112225230043023235 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p1/ [transport-bluetooth] INTERFACE = hci0 TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_quota_compliance_wlan_peer1.conf0000644000175000017500000000110112225230043022165 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p1/ [transport-wlan] TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/gnunet-service-transport_manipulation.h0000644000175000017500000000745412267431203022570 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_neighbours.h * @brief neighbour management API * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_MANIPULATION_H #define GNUNET_SERVICE_TRANSPORT_MANIPULATION_H #include "platform.h" #include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_clients.h" #include "gnunet-service-transport_hello.h" #include "gnunet-service-transport_neighbours.h" #include "gnunet-service-transport_plugins.h" #include "gnunet-service-transport_validation.h" #include "gnunet-service-transport.h" #include "transport.h" /** * Set traffic metric to manipulate * * @param cls closure * @param client client sending message * @param message containing information */ void GST_manipulation_set_metric (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Adapter function between transport's send function and transport plugins * * @param target the peer the message to send to * @param msg the message received * @param msg_size message size * @param timeout timeout * @param cont the continuation to call after sending * @param cont_cls cls for continuation */ void GST_manipulation_send (const struct GNUNET_PeerIdentity *target, const void *msg, size_t msg_size, struct GNUNET_TIME_Relative timeout, GST_NeighbourSendContinuation cont, void *cont_cls); /** * Adapter function between transport plugins and transport receive function * manipulation delays for next send. * * @param cls the closure for transport * @param address the address and the peer the message was received from * @param message the message received * @param session the session the message was received on * @return manipulated delay for next receive */ struct GNUNET_TIME_Relative GST_manipulation_recv (void *cls, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_MessageHeader *message); /** * Function that will be called to manipulate ATS information according to * current manipulation settings * * @param peer the peer * @param address binary address * @param session the session * @param ats the ats information * @param ats_count the number of ats information */ struct GNUNET_ATS_Information * GST_manipulation_manipulate_metrics (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct Session *session, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * Notify manipulation about disconnect so it can discard queued messages * * @param peer the disconnecting peer */ void GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer); /** * Initialize traffic manipulation * * @param GST_cfg configuration handle */ void GST_manipulation_init (const struct GNUNET_CONFIGURATION_Handle *GST_cfg); /** * Stop traffic manipulation */ void GST_manipulation_stop (); #endif /* end of file gnunet-service-transport_neighbours.h */ gnunet-0.10.1/src/transport/test_transport_api_reliability_wlan_peer2.conf0000644000175000017500000000112112225230043024123 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p2/ [transport-wlan] INTERFACE = mon1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_unreliability_wlan_peer2.conf0000644000175000017500000000112112225230043024466 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p2/ [transport-wlan] INTERFACE = mon1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_manipulation_send_tcp_peer1.conf0000644000175000017500000000114712225230043025157 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PLUGINS = tcp gnunet-0.10.1/src/transport/test_transport_api_unreliability_bluetooth_peer2.conf0000644000175000017500000000114012225230043025533 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p2/ [transport-bluetooth] INTERFACE = hci1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/gnunet-service-transport_blacklist.h0000644000175000017500000000750512225777503022047 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_blacklist.h * @brief blacklisting API * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_BLACKLIST_H #define GNUNET_SERVICE_TRANSPORT_BLACKLIST_H #include "gnunet_statistics_service.h" #include "gnunet_util_lib.h" /** * Start blacklist subsystem. * * @param server server used to accept clients from * @param cfg configuration handle * @param my_id my peer id */ void GST_blacklist_start (struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *my_id); /** * Stop blacklist subsystem. */ void GST_blacklist_stop (void); /** * Initialize a blacklisting client. We got a blacklist-init * message from this client, add him to the list of clients * to query for blacklisting. * * @param cls unused * @param client the client * @param message the blacklist-init message that was sent */ void GST_blacklist_handle_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * A blacklisting client has sent us reply. Process it. * * @param cls unused * @param client the client * @param message the blacklist-init message that was sent */ void GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Add the given peer to the blacklist (for the given transport). * * @param peer peer to blacklist * @param transport_name transport to blacklist for this peer, NULL for all */ void GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, const char *transport_name); /** * Handle to an active blacklist check. */ struct GST_BlacklistCheck; /** * Continuation called from a blacklist test. * * @param cls closure * @param peer identity of peer that was tested * @param result GNUNET_OK if the connection is allowed, * GNUNET_NO if not */ typedef void (*GST_BlacklistTestContinuation) (void *cls, const struct GNUNET_PeerIdentity * peer, int result); /** * Test if a peer/transport combination is blacklisted. * * @param peer the identity of the peer to test * @param transport_name name of the transport to test, never NULL * @param cont function to call with result * @param cont_cls closure for 'cont' * @return handle to the blacklist check, NULL if the decision * was made instantly and 'cont' was already called */ struct GST_BlacklistCheck * GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer, const char *transport_name, GST_BlacklistTestContinuation cont, void *cont_cls); /** * Cancel a blacklist check. * * @param bc check to cancel */ void GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc); #endif /* end of file gnunet-service-transport_blacklist.h */ gnunet-0.10.1/src/transport/test_transport_api_manipulation_cfg.c0000644000175000017500000003472712274162761022351 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_manipulation_send_tcp.c * @brief base test case for transport traffic manipulation implementation * based onf cfg * * Peer 1 has inbound and outbound delay of 100ms * Peer 2 has no inbound and outbound delay * * We send a request from P1 to P2 and expect delay of >= TEST_DELAY us * Then we send response from P2 to P1 and expect delay of >= TEST_DELAY us */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) #define TEST_MESSAGE_SIZE 2600 #define TEST_REQUEST_MESSAGE_TYPE 12345 #define TEST_RESPONSE_MESSAGE_TYPE 12346 /** * Test delay, in microseconds. */ #define TEST_DELAY 100 * 1000LL static char *test_source; static char *test_plugin; static char *test_name; static int ok; static int s_started; static int s_connected; static int s_sending; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static struct GNUNET_TIME_Absolute start_request; static struct GNUNET_TIME_Absolute start_response; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); if (s_started == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started \n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started \n")); if (s_connected == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not connected\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were connected\n")); if (s_sending == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were ready to send data\n")); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 1 was not started\n")); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 2 was not started\n")); ok = GNUNET_SYSERR; } static size_t notify_request_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= TEST_MESSAGE_SIZE); if (buf != NULL) { memset (buf, '\0', TEST_MESSAGE_SIZE); hdr = buf; hdr->size = htons (TEST_MESSAGE_SIZE); hdr->type = htons (TEST_REQUEST_MESSAGE_TYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending request message from peer %u (`%4s') with type %u and size %u bytes to peer %u (`%4s')\n", p1->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return TEST_MESSAGE_SIZE; } static void sendtask_request_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p1->no, GNUNET_i2s (&p1->id), p2->no, receiver_s); GNUNET_free (receiver_s); s_sending = GNUNET_YES; start_request = GNUNET_TIME_absolute_get(); th = GNUNET_TRANSPORT_notify_transmit_ready (p1->th, &p2->id, TEST_MESSAGE_SIZE, TIMEOUT_TRANSMIT, ¬ify_request_ready, p2); } static size_t notify_response_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= TEST_MESSAGE_SIZE); if (buf != NULL) { memset (buf, '\0', TEST_MESSAGE_SIZE); hdr = buf; hdr->size = htons (TEST_MESSAGE_SIZE); hdr->type = htons (TEST_RESPONSE_MESSAGE_TYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending response message from peer %u (`%4s') with type %u and size %u bytes to peer %u (`%4s')\n", p1->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return TEST_MESSAGE_SIZE; } static void sendtask_response_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); s_sending = GNUNET_YES; start_response = GNUNET_TIME_absolute_get(); th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, TIMEOUT_TRANSMIT, ¬ify_response_ready, p1); } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; struct GNUNET_TIME_Relative duration; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); switch (ntohs (message->type)) { case TEST_REQUEST_MESSAGE_TYPE: duration = GNUNET_TIME_absolute_get_difference(start_request, GNUNET_TIME_absolute_get()); if (duration.rel_value_us >= TEST_DELAY) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Request message was delayed for %s\n", GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Request message was delayed for unexpected duration %s\n", GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); ok = 1; } /* Send response */ send_task = GNUNET_SCHEDULER_add_now (&sendtask_response_task, NULL); return; break; case TEST_RESPONSE_MESSAGE_TYPE: duration = GNUNET_TIME_absolute_get_difference(start_response, GNUNET_TIME_absolute_get()); if (duration.rel_value_us >= TEST_DELAY) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Response message was delayed for %s\n", GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Response message was delayed for unexpected duration %s\n", GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); ok = 1; } /* Done */ ok = 0; end(); break; default: break; } } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); GNUNET_free (ps); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); s_connected = GNUNET_YES; send_task = GNUNET_SCHEDULER_add_now (&sendtask_request_task, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; else s_started = GNUNET_YES; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); s_started = GNUNET_NO; s_connected = GNUNET_NO; s_sending = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api-manipulation", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); GNUNET_log_setup (test_name, "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); return ret; } /* end of test_transport_api.c */ gnunet-0.10.1/src/transport/test_transport_defaults.conf0000644000175000017500000000115212255010511020455 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-transport-api/ [transport-tcp] TIMEOUT = 300 s [arm] DEFAULTSERVICES = [transport] #PREFIX = valgrind -v --gen-suppressions=yes [core] AUTOSTART = NO [datastore] AUTOSTART = NO [fs] AUTOSTART = NO [dht] AUTOSTART = NO [mesh] AUTOSTART = NO [nse] AUTOSTART = NO [dns] AUTOSTART = NO [dv] AUTOSTART = NO [gns] AUTOSTART = NO [namestore] AUTOSTART = NO [vpn] AUTOSTART = NO [consensus] AUTOSTART = NO [nat] DISABLEV6 = YES BINDTO = 127.0.0.1 INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 [TESTING] WEAKRANDOM = YES [transport-udp] BROADCAST_RECEIVE = nognunet-0.10.1/src/transport/test_transport_api_timeout_tcp_peer1.conf0000644000175000017500000000115012225230043023126 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_blacklisting_cfg_blp_peer2_plugin.conf0000644000175000017500000000142212236654562025466 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] #PREFIX = valgrind --leak-check=full PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [transport-blacklist-DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50] 6ULBJK6QQJ64FAG9DF0292AS5IA9CCAC04IQU0HF8THM635HMBBG = tcp gnunet-0.10.1/src/transport/test_transport_api_reliability_tcp_nat_peer2.conf0000644000175000017500000000124712225230043024623 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-reliability-tcp-nat-p2/ [nat] DISABLEV6 = YES ENABLE_NAT_CLIENT = YES [transport-tcp] PORT = 12030 TIMEOUT = 5 s [arm] PORT = 12034 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12033 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12032 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12031 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 45923 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/gnunet-transport-wlan-receiver.c0000644000175000017500000000622712225777502021114 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-transport-wlan-receiver.c * @brief program to send via WLAN as much as possible (to test physical/theoretical throughput) * @author David Brodski */ #include "platform.h" #include "gnunet_protocols.h" #include "plugin_transport_wlan.h" int main (int argc, char *argv[]) { char msg_buf[65536]; unsigned long long count; double bytes_per_s; time_t start; time_t akt; ssize_t ret; pid_t pid; int commpipe[2]; /* This holds the fd for the input & output of the pipe */ if (2 != argc) { fprintf (stderr, "This program must be started with the interface name as argument.\n"); fprintf (stderr, "Usage: %s interface-name\n" "e.g. %s mon0\n", argv[0], argv[0]); return 1; } /* Setup communication pipeline first */ if (pipe (commpipe)) { fprintf (stderr, "Failed to create pipe: %s\n", STRERROR (errno)); exit (1); } /* Attempt to fork and check for errors */ if ((pid = fork ()) == -1) { fprintf (stderr, "Failed to fork: %s\n", STRERROR (errno)); exit (1); } if (pid) { /* A positive (non-negative) PID indicates the parent process */ if (0 != close (commpipe[1])) /* Close unused side of pipe (in side) */ fprintf (stderr, "Failed to close fd: %s\n", strerror (errno)); start = time (NULL); count = 0; while (1) { ret = read (commpipe[0], msg_buf, sizeof (msg_buf)); if (0 > ret) { fprintf (stderr, "read failed: %s\n", strerror (errno)); break; } count += ret; akt = time (NULL); if (akt - start > 30) { bytes_per_s = count / (akt - start); bytes_per_s /= 1024; printf ("recv %f kb/s\n", bytes_per_s); start = akt; count = 0; } } } else { /* A zero PID indicates that this is the child process */ (void) close (1); if (-1 == dup2 (commpipe[1], 1)) /* Replace stdin with the in side of the pipe */ fprintf (stderr, "dup2 failed: %s\n", strerror (errno)); (void) close (commpipe[0]); /* Close unused side of pipe (in side) */ /* Replace the child fork with a new process */ if (execlp ("gnunet-helper-transport-wlan", "gnunet-helper-transport-wlan", argv[1], NULL) == -1) { fprintf (stderr, "Could not start gnunet-helper-transport-wlan!"); _exit (1); } } return 0; } gnunet-0.10.1/src/transport/test_transport_api_limited_sockets.c0000644000175000017500000002221412274162761022200 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_limited_sockets.c * @brief base test case for transport implementations * * This test case serves as a base for tcp, udp, and udp-nat * transport test cases. Based on the executable being run * the correct test case will be performed. Conservation of * C code apparently. */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) #define MTYPE 12345 #define MAX_FILES 50 #if HAVE_SETRLIMIT static char *test_source; static char *test_plugin; static char *test_name; static int ok; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); GNUNET_TRANSPORT_TESTING_done (tth); } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (cc != NULL) GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); if (NULL != th) GNUNET_TRANSPORT_TESTING_done (tth); ok = GNUNET_SYSERR; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %d from peer %s!\n", ntohs (message->type), GNUNET_i2s (peer)); if ((MTYPE == ntohs (message->type)) && (sizeof (struct GNUNET_MessageHeader) == ntohs (message->size))) { ok = 0; end (); } else { GNUNET_break (0); ok = 1; end (); } } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting message with %u bytes to peer %s\n", sizeof (struct GNUNET_MessageHeader), GNUNET_i2s (&p->id)); GNUNET_assert (size >= 256); if (buf != NULL) { hdr = buf; hdr->size = htons (sizeof (struct GNUNET_MessageHeader)); hdr->type = htons (MTYPE); } return sizeof (struct GNUNET_MessageHeader); } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' connected to us (%p)!\n", GNUNET_i2s (peer), cls); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' disconnected (%p)!\n", GNUNET_i2s (peer), cls); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; th = GNUNET_TRANSPORT_notify_transmit_ready (p1->th, &p2->id, 256, TIMEOUT, ¬ify_ready, &p1); } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peers connected: %s <-> %s\n", p1_c, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); // FIXME: THIS IS REQUIRED! SEEMS TO BE A BUG! send_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p2, p1, &testing_connect_cb, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); tth = GNUNET_TRANSPORT_TESTING_init (); p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; #if WRITECONFIG setTransportOptions ("test_transport_api_data.conf"); #endif send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { struct rlimit r_file_old; struct rlimit r_file_new; int res; int ret = 0; test_plugin = NULL; GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_log_setup (test_name, "WARNING", NULL); res = getrlimit (RLIMIT_NOFILE, &r_file_old); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Maximum number of open files was: %u/%u\n", r_file_old.rlim_cur, r_file_old.rlim_max); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting maximum number of open files to: %u\n", MAX_FILES); r_file_new.rlim_cur = MAX_FILES; r_file_new.rlim_max = r_file_old.rlim_max; res = setrlimit (RLIMIT_NOFILE, &r_file_new); if (res != 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Setting limit failed!\n"); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); return 0; } GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); return ret; } #else /* cannot setrlimit */ int main (int argc, char *argv[]) { fprintf (stderr, "Cannot run test on this system\n"); return 0; } #endif /* end of test_transport_api_limited_sockets.c */ gnunet-0.10.1/src/transport/plugin_transport_udp.c0000644000175000017500000030206512320530515017265 00000000000000/* This file is part of GNUnet (C) 2010-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_udp.c * @brief Implementation of the UDP transport protocol * @author Christian Grothoff * @author Nathan Evans * @author Matthias Wachs */ #include "platform.h" #include "plugin_transport_udp.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_fragmentation_lib.h" #include "gnunet_nat_lib.h" #include "gnunet_protocols.h" #include "gnunet_resolver_service.h" #include "gnunet_signatures.h" #include "gnunet_constants.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "transport.h" #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__) #define UDP_SESSION_TIME_OUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * Number of messages we can defragment in parallel. We only really * defragment 1 message at a time, but if messages get re-ordered, we * may want to keep knowledge about the previous message to avoid * discarding the current message in favor of a single fragment of a * previous message. 3 should be good since we don't expect massive * message reorderings with UDP. */ #define UDP_MAX_MESSAGES_IN_DEFRAG 3 /** * We keep a defragmentation queue per sender address. How many * sender addresses do we support at the same time? Memory consumption * is roughly a factor of 32k * UDP_MAX_MESSAGES_IN_DEFRAG times this * value. (So 128 corresponds to 12 MB and should suffice for * connecting to roughly 128 peers via UDP). */ #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128 /** * Running pretty printers: head */ static struct PrettyPrinterContext *ppc_dll_head; /** * Running pretty printers: tail */ static struct PrettyPrinterContext *ppc_dll_tail; /** * Closure for 'append_port'. */ struct PrettyPrinterContext { /** * DLL */ struct PrettyPrinterContext *next; /** * DLL */ struct PrettyPrinterContext *prev; /** * Timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Resolver handle */ struct GNUNET_RESOLVER_RequestHandle *resolver_handle; /** * Function to call with the result. */ GNUNET_TRANSPORT_AddressStringCallback asc; /** * Clsoure for 'asc'. */ void *asc_cls; /** * Port to add after the IP address. */ uint16_t port; /** * IPv6 address */ int ipv6; /** * Options */ uint32_t options; }; struct Session { /** * Which peer is this session for? */ struct GNUNET_PeerIdentity target; /** * Plugin this session belongs to. */ struct Plugin *plugin; /** * Context for dealing with fragments. */ struct UDP_FragmentationContext *frag_ctx; /** * Desired delay for next sending we send to other peer */ struct GNUNET_TIME_Relative flow_delay_for_other_peer; /** * Desired delay for next sending we received from other peer */ struct GNUNET_TIME_Absolute flow_delay_from_other_peer; /** * Session timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * expected delay for ACKs */ struct GNUNET_TIME_Relative last_expected_ack_delay; /** * desired delay between UDP messages */ struct GNUNET_TIME_Relative last_expected_msg_delay; struct GNUNET_ATS_Information ats; struct GNUNET_HELLO_Address *address; /** * Reference counter to indicate that this session is * currently being used and must not be destroyed; * setting @e in_destroy will destroy it as soon as * possible. */ unsigned int rc; /** * Is this session about to be destroyed (sometimes we cannot * destroy a session immediately as below us on the stack * there might be code that still uses it; in this case, * @e rc is non-zero). */ int in_destroy; }; /** * Closure for #session_cmp_it(). */ struct SessionCompareContext { struct Session *res; const struct GNUNET_HELLO_Address *address; }; /** * Closure for #process_inbound_tokenized_messages(). */ struct SourceInformation { /** * Sender identity. */ struct GNUNET_PeerIdentity sender; /** * Source address. */ const void *arg; /** * Associated session. */ struct Session *session; /** * Number of bytes in source address. */ size_t args; }; /** * Closure for #find_receive_context(). */ struct FindReceiveContext { /** * Where to store the result. */ struct DefragContext *rc; /** * Address to find. */ const struct sockaddr *addr; struct Session *session; /** * Number of bytes in @e addr. */ socklen_t addr_len; }; /** * Data structure to track defragmentation contexts based * on the source of the UDP traffic. */ struct DefragContext { /** * Defragmentation context. */ struct GNUNET_DEFRAGMENT_Context *defrag; /** * Source address this receive context is for (allocated at the * end of the struct). */ const struct sockaddr *src_addr; /** * Reference to master plugin struct. */ struct Plugin *plugin; /** * Node in the defrag heap. */ struct GNUNET_CONTAINER_HeapNode *hnode; /** * Length of 'src_addr' */ size_t addr_len; }; /** * Context to send fragmented messages */ struct UDP_FragmentationContext { /** * Next in linked list */ struct UDP_FragmentationContext *next; /** * Previous in linked list */ struct UDP_FragmentationContext *prev; /** * The plugin */ struct Plugin *plugin; /** * Handle for GNUNET_FRAGMENT context */ struct GNUNET_FRAGMENT_Context *frag; /** * The session this fragmentation context belongs to */ struct Session *session; /** * Function to call upon completion of the transmission. */ GNUNET_TRANSPORT_TransmitContinuation cont; /** * Closure for @e cont. */ void *cont_cls; /** * Message timeout */ struct GNUNET_TIME_Absolute timeout; /** * Payload size of original unfragmented message */ size_t payload_size; /** * Bytes used to send all fragments on wire including UDP overhead */ size_t on_wire_size; unsigned int fragments_used; }; /** * Message types included in a `struct UDP_MessageWrapper` */ enum UDP_MessageType { /** * Uninitialized (error) */ UMT_UNDEFINED = 0, /** * Fragment of a message. */ UMT_MSG_FRAGMENTED = 1, /** * */ UMT_MSG_FRAGMENTED_COMPLETE = 2, /** * Unfragmented message. */ UMT_MSG_UNFRAGMENTED = 3, /** * Receipt confirmation. */ UMT_MSG_ACK = 4 }; struct UDP_MessageWrapper { /** * Session this message belongs to */ struct Session *session; /** * DLL of messages * previous element */ struct UDP_MessageWrapper *prev; /** * DLL of messages * previous element */ struct UDP_MessageWrapper *next; /** * Message type */ enum UDP_MessageType msg_type; /** * Message with size msg_size including UDP specific overhead */ char *msg_buf; /** * Size of UDP message to send including UDP specific overhead */ size_t msg_size; /** * Payload size of original message */ size_t payload_size; /** * Message timeout */ struct GNUNET_TIME_Absolute timeout; /** * Function to call upon completion of the transmission. */ GNUNET_TRANSPORT_TransmitContinuation cont; /** * Closure for @e cont. */ void *cont_cls; /** * Fragmentation context * frag_ctx == NULL if transport <= MTU * frag_ctx != NULL if transport > MTU */ struct UDP_FragmentationContext *frag_ctx; }; /** * UDP ACK Message-Packet header (after defragmentation). */ struct UDP_ACK_Message { /** * Message header. */ struct GNUNET_MessageHeader header; /** * Desired delay for flow control */ uint32_t delay; /** * What is the identity of the sender */ struct GNUNET_PeerIdentity sender; }; /** * Address options */ static uint32_t myoptions; /** * Encapsulation of all of the state of the plugin. */ struct Plugin * plugin; /** * We have been notified that our readset has something to read. We don't * know which socket needs to be read, so we have to check each one * Then reschedule this function to be called again once more is available. * * @param cls the plugin handle * @param tc the scheduling context (for rescheduling this function again) */ static void udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * We have been notified that our readset has something to read. We don't * know which socket needs to be read, so we have to check each one * Then reschedule this function to be called again once more is available. * * @param cls the plugin handle * @param tc the scheduling context (for rescheduling this function again) */ static void udp_plugin_select_v6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * (re)schedule select tasks for this plugin. * * @param plugin plugin to reschedule */ static void schedule_select (struct Plugin *plugin) { struct GNUNET_TIME_Relative min_delay; struct UDP_MessageWrapper *udpw; if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4)) { /* Find a message ready to send: * Flow delay from other peer is expired or not set (0) */ min_delay = GNUNET_TIME_UNIT_FOREVER_REL; for (udpw = plugin->ipv4_queue_head; NULL != udpw; udpw = udpw->next) min_delay = GNUNET_TIME_relative_min (min_delay, GNUNET_TIME_absolute_get_remaining ( udpw->session->flow_delay_from_other_peer)); if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK ) GNUNET_SCHEDULER_cancel (plugin->select_task); /* Schedule with: * - write active set if message is ready * - timeout minimum delay */ plugin->select_task = GNUNET_SCHEDULER_add_select ( GNUNET_SCHEDULER_PRIORITY_DEFAULT, (0 == min_delay.rel_value_us) ? GNUNET_TIME_UNIT_FOREVER_REL : min_delay, plugin->rs_v4, (0 == min_delay.rel_value_us) ? plugin->ws_v4 : NULL, &udp_plugin_select, plugin); } if ((GNUNET_YES == plugin->enable_ipv6) && (NULL != plugin->sockv6)) { min_delay = GNUNET_TIME_UNIT_FOREVER_REL; for (udpw = plugin->ipv6_queue_head; NULL != udpw; udpw = udpw->next) min_delay = GNUNET_TIME_relative_min (min_delay, GNUNET_TIME_absolute_get_remaining ( udpw->session->flow_delay_from_other_peer)); if (GNUNET_SCHEDULER_NO_TASK != plugin->select_task_v6) GNUNET_SCHEDULER_cancel (plugin->select_task_v6); plugin->select_task_v6 = GNUNET_SCHEDULER_add_select ( GNUNET_SCHEDULER_PRIORITY_DEFAULT, (0 == min_delay.rel_value_us) ? GNUNET_TIME_UNIT_FOREVER_REL : min_delay, plugin->rs_v6, (0 == min_delay.rel_value_us) ? plugin->ws_v6 : NULL, &udp_plugin_select_v6, plugin); } } /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ const char * udp_address_to_string (void *cls, const void *addr, size_t addrlen) { static char rbuf[INET6_ADDRSTRLEN + 10]; char buf[INET6_ADDRSTRLEN]; const void *sb; struct in_addr a4; struct in6_addr a6; const struct IPv4UdpAddress *t4; const struct IPv6UdpAddress *t6; int af; uint16_t port; uint32_t options; if ((NULL != addr) && (addrlen == sizeof(struct IPv6UdpAddress))) { t6 = addr; af = AF_INET6; options = ntohl (t6->options); port = ntohs (t6->u6_port); memcpy (&a6, &t6->ipv6_addr, sizeof(a6)); sb = &a6; } else if ((NULL != addr) && (addrlen == sizeof(struct IPv4UdpAddress))) { t4 = addr; af = AF_INET; options = ntohl (t4->options); port = ntohs (t4->u4_port); memcpy (&a4, &t4->ipv4_addr, sizeof(a4)); sb = &a4; } else { return NULL; } inet_ntop (af, sb, buf, INET6_ADDRSTRLEN); GNUNET_snprintf (rbuf, sizeof(rbuf), (af == AF_INET6) ? "%s.%u.[%s]:%u" : "%s.%u.%s:%u", PLUGIN_NAME, options, buf, port); return rbuf; } /** * Function called to convert a string address to * a binary address. * * @param cls closure ('struct Plugin*') * @param addr string address * @param addrlen length of the address * @param buf location to store the buffer * @param added location to store the number of bytes in the buffer. * If the function returns #GNUNET_SYSERR, its contents are undefined. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static int udp_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added) { struct sockaddr_storage socket_address; char *address; char *plugin; char *optionstr; uint32_t options; /* Format tcp.options.address:port */ address = NULL; plugin = NULL; optionstr = NULL; if ((NULL == addr) || (addrlen == 0)) { GNUNET_break(0); return GNUNET_SYSERR; } if ('\0' != addr[addrlen - 1]) { GNUNET_break(0); return GNUNET_SYSERR; } if (strlen (addr) != addrlen - 1) { GNUNET_break(0); return GNUNET_SYSERR; } plugin = GNUNET_strdup (addr); optionstr = strchr (plugin, '.'); if (NULL == optionstr) { GNUNET_break(0); GNUNET_free(plugin); return GNUNET_SYSERR; } optionstr[0] = '\0'; optionstr++; options = atol (optionstr); address = strchr (optionstr, '.'); if (NULL == address) { GNUNET_break(0); GNUNET_free(plugin); return GNUNET_SYSERR; } address[0] = '\0'; address++; if (GNUNET_OK != GNUNET_STRINGS_to_address_ip (address, strlen (address), &socket_address)) { GNUNET_break(0); GNUNET_free(plugin); return GNUNET_SYSERR; } GNUNET_free(plugin); switch (socket_address.ss_family) { case AF_INET: { struct IPv4UdpAddress *u4; struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address; u4 = GNUNET_new (struct IPv4UdpAddress); u4->options = htonl (options); u4->ipv4_addr = in4->sin_addr.s_addr; u4->u4_port = in4->sin_port; *buf = u4; *added = sizeof(struct IPv4UdpAddress); return GNUNET_OK; } case AF_INET6: { struct IPv6UdpAddress *u6; struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address; u6 = GNUNET_new (struct IPv6UdpAddress); u6->options = htonl (options); u6->ipv6_addr = in6->sin6_addr; u6->u6_port = in6->sin6_port; *buf = u6; *added = sizeof(struct IPv6UdpAddress); return GNUNET_OK; } default: GNUNET_break(0); return GNUNET_SYSERR; } } static void ppc_cancel_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PrettyPrinterContext *ppc = cls; ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != ppc->resolver_handle) { GNUNET_RESOLVER_request_cancel (ppc->resolver_handle); ppc->resolver_handle = NULL; } GNUNET_CONTAINER_DLL_remove(ppc_dll_head, ppc_dll_tail, ppc); GNUNET_free(ppc); } /** * Append our port and forward the result. * * @param cls a 'struct PrettyPrinterContext' * @param hostname result from DNS resolver */ static void append_port (void *cls, const char *hostname) { struct PrettyPrinterContext *ppc = cls; struct PrettyPrinterContext *cur; char *ret; if (hostname == NULL ) { ppc->asc (ppc->asc_cls, NULL ); GNUNET_CONTAINER_DLL_remove(ppc_dll_head, ppc_dll_tail, ppc); GNUNET_SCHEDULER_cancel (ppc->timeout_task); ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; ppc->resolver_handle = NULL; GNUNET_free(ppc); return; } for (cur = ppc_dll_head; (NULL != cur); cur = cur->next) { if (cur == ppc) break; } if (NULL == cur) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Invalid callback for PPC %p \n", ppc); return; } if (GNUNET_YES == ppc->ipv6) GNUNET_asprintf (&ret, "%s.%u.[%s]:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port); else GNUNET_asprintf (&ret, "%s.%u.%s:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port); ppc->asc (ppc->asc_cls, ret); GNUNET_free(ret); } /** * Convert the transports address to a nice, human-readable * format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the address * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for @a asc */ static void udp_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { struct PrettyPrinterContext *ppc; const void *sb; size_t sbs; struct sockaddr_in a4; struct sockaddr_in6 a6; const struct IPv4UdpAddress *u4; const struct IPv6UdpAddress *u6; uint16_t port; uint32_t options; if (addrlen == sizeof(struct IPv6UdpAddress)) { u6 = addr; memset (&a6, 0, sizeof(a6)); a6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN a6.sin6_len = sizeof (a6); #endif a6.sin6_port = u6->u6_port; memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof(struct in6_addr)); port = ntohs (u6->u6_port); options = ntohl (u6->options); sb = &a6; sbs = sizeof(a6); } else if (addrlen == sizeof(struct IPv4UdpAddress)) { u4 = addr; memset (&a4, 0, sizeof(a4)); a4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN a4.sin_len = sizeof (a4); #endif a4.sin_port = u4->u4_port; a4.sin_addr.s_addr = u4->ipv4_addr; port = ntohs (u4->u4_port); options = ntohl (u4->options); sb = &a4; sbs = sizeof(a4); } else { /* invalid address */ GNUNET_break_op(0); asc (asc_cls, NULL ); return; } ppc = GNUNET_new (struct PrettyPrinterContext); ppc->asc = asc; ppc->asc_cls = asc_cls; ppc->port = port; ppc->options = options; if (addrlen == sizeof(struct IPv6UdpAddress)) ppc->ipv6 = GNUNET_YES; else ppc->ipv6 = GNUNET_NO; ppc->timeout_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_relative_multiply (timeout, 2), &ppc_cancel_task, ppc); GNUNET_CONTAINER_DLL_insert(ppc_dll_head, ppc_dll_tail, ppc); ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc); } static void call_continuation (struct UDP_MessageWrapper *udpw, int result) { size_t overhead; LOG (GNUNET_ERROR_TYPE_DEBUG, "Calling continuation for %u byte message to `%s' with result %s\n", udpw->payload_size, GNUNET_i2s (&udpw->session->target), (GNUNET_OK == result) ? "OK" : "SYSERR"); if (udpw->msg_size >= udpw->payload_size) overhead = udpw->msg_size - udpw->payload_size; else overhead = udpw->msg_size; switch (result) { case GNUNET_OK: switch (udpw->msg_type) { case UMT_MSG_UNFRAGMENTED: if (NULL != udpw->cont) { /* Transport continuation */ udpw->cont (udpw->cont_cls, &udpw->session->target, result, udpw->payload_size, udpw->msg_size); } GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, messages, sent, success", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, bytes payload, sent, success", udpw->payload_size, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, bytes overhead, sent, success", overhead, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes overhead, sent", overhead, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes payload, sent", udpw->payload_size, GNUNET_NO); break; case UMT_MSG_FRAGMENTED_COMPLETE: GNUNET_assert(NULL != udpw->frag_ctx); if (udpw->frag_ctx->cont != NULL ) udpw->frag_ctx->cont (udpw->frag_ctx->cont_cls, &udpw->session->target, GNUNET_OK, udpw->frag_ctx->payload_size, udpw->frag_ctx->on_wire_size); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, messages, sent, success", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, bytes payload, sent, success", udpw->payload_size, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, bytes overhead, sent, success", overhead, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes overhead, sent", overhead, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes payload, sent", udpw->payload_size, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, messages, pending", -1, GNUNET_NO); break; case UMT_MSG_FRAGMENTED: /* Fragmented message: enqueue next fragment */ if (NULL != udpw->cont) udpw->cont (udpw->cont_cls, &udpw->session->target, result, udpw->payload_size, udpw->msg_size); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, fragments, sent, success", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, fragments bytes, sent, success", udpw->msg_size, GNUNET_NO); break; case UMT_MSG_ACK: /* No continuation */ GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, ACK msgs, messages, sent, success", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, ACK msgs, bytes overhead, sent, success", overhead, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes overhead, sent", overhead, GNUNET_NO); break; default: GNUNET_break(0); break; } break; case GNUNET_SYSERR: switch (udpw->msg_type) { case UMT_MSG_UNFRAGMENTED: /* Unfragmented message: failed to send */ if (NULL != udpw->cont) udpw->cont (udpw->cont_cls, &udpw->session->target, result, udpw->payload_size, overhead); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, messages, sent, failure", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, bytes payload, sent, failure", udpw->payload_size, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, bytes overhead, sent, failure", overhead, GNUNET_NO); break; case UMT_MSG_FRAGMENTED_COMPLETE: GNUNET_assert(NULL != udpw->frag_ctx); if (udpw->frag_ctx->cont != NULL ) udpw->frag_ctx->cont (udpw->frag_ctx->cont_cls, &udpw->session->target, GNUNET_SYSERR, udpw->frag_ctx->payload_size, udpw->frag_ctx->on_wire_size); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, messages, sent, failure", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, bytes payload, sent, failure", udpw->payload_size, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, bytes payload, sent, failure", overhead, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, bytes payload, sent, failure", overhead, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, messages, pending", -1, GNUNET_NO); break; case UMT_MSG_FRAGMENTED: GNUNET_assert(NULL != udpw->frag_ctx); /* Fragmented message: failed to send */ GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, fragments, sent, failure", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, fragments bytes, sent, failure", udpw->msg_size, GNUNET_NO); break; case UMT_MSG_ACK: /* ACK message: failed to send */ GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, ACK msgs, messages, sent, failure", 1, GNUNET_NO); break; default: GNUNET_break(0); break; } break; default: GNUNET_break(0); break; } } /** * Check if the given port is plausible (must be either our listen * port or our advertised port). If it is neither, we return * #GNUNET_SYSERR. * * @param plugin global variables * @param in_port port number to check * @return #GNUNET_OK if port is either open_port or adv_port */ static int check_port (struct Plugin *plugin, uint16_t in_port) { if ((in_port == plugin->port) || (in_port == plugin->aport)) return GNUNET_OK; return GNUNET_SYSERR; } /** * Function that will be called to check if a binary address for this * plugin is well-formed and corresponds to an address for THIS peer * (as per our configuration). Naturally, if absolutely necessary, * plugins can be a bit conservative in their answer, but in general * plugins should make sure that the address does not redirect * traffic to a 3rd party that might try to man-in-the-middle our * traffic. * * @param cls closure, should be our handle to the Plugin * @param addr pointer to the address * @param addrlen length of @a addr * @return #GNUNET_OK if this is a plausible address for this peer * and transport, #GNUNET_SYSERR if not * */ static int udp_plugin_check_address (void *cls, const void *addr, size_t addrlen) { struct Plugin *plugin = cls; struct IPv4UdpAddress *v4; struct IPv6UdpAddress *v6; if ((addrlen != sizeof(struct IPv4UdpAddress)) && (addrlen != sizeof(struct IPv6UdpAddress))) { GNUNET_break_op(0); return GNUNET_SYSERR; } if (addrlen == sizeof(struct IPv4UdpAddress)) { v4 = (struct IPv4UdpAddress *) addr; if (GNUNET_OK != check_port (plugin, ntohs (v4->u4_port))) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_NAT_test_address (plugin->nat, &v4->ipv4_addr, sizeof(struct in_addr))) return GNUNET_SYSERR; } else { v6 = (struct IPv6UdpAddress *) addr; if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr)) { GNUNET_break_op(0); return GNUNET_SYSERR; } if (GNUNET_OK != check_port (plugin, ntohs (v6->u6_port))) return GNUNET_SYSERR; if (GNUNET_OK != GNUNET_NAT_test_address (plugin->nat, &v6->ipv6_addr, sizeof(struct in6_addr))) return GNUNET_SYSERR; } return GNUNET_OK; } /** * Function to free last resources associated with a session. * * @param s session to free */ static void free_session (struct Session *s) { if (NULL != s->frag_ctx) { GNUNET_FRAGMENT_context_destroy (s->frag_ctx->frag, NULL, NULL ); GNUNET_free(s->frag_ctx); s->frag_ctx = NULL; } GNUNET_free(s); } static void dequeue (struct Plugin *plugin, struct UDP_MessageWrapper * udpw) { if (plugin->bytes_in_buffer < udpw->msg_size) GNUNET_break(0); else { GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes in buffers", -(long long) udpw->msg_size, GNUNET_NO); plugin->bytes_in_buffer -= udpw->msg_size; } GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, msgs in buffers", -1, GNUNET_NO); if (udpw->session->address->address_length == sizeof(struct IPv4UdpAddress)) GNUNET_CONTAINER_DLL_remove(plugin->ipv4_queue_head, plugin->ipv4_queue_tail, udpw); else if (udpw->session->address->address_length == sizeof(struct IPv6UdpAddress)) GNUNET_CONTAINER_DLL_remove(plugin->ipv6_queue_head, plugin->ipv6_queue_tail, udpw); else GNUNET_break (0); } static void fragmented_message_done (struct UDP_FragmentationContext *fc, int result) { struct UDP_MessageWrapper *udpw; struct UDP_MessageWrapper *tmp; struct UDP_MessageWrapper dummy; struct Session *s = fc->session; LOG(GNUNET_ERROR_TYPE_DEBUG, "%p : Fragmented message removed with result %s\n", fc, (result == GNUNET_SYSERR) ? "FAIL" : "SUCCESS"); /* Call continuation for fragmented message */ memset (&dummy, 0, sizeof(dummy)); dummy.msg_type = UMT_MSG_FRAGMENTED_COMPLETE; dummy.msg_size = s->frag_ctx->on_wire_size; dummy.payload_size = s->frag_ctx->payload_size; dummy.frag_ctx = s->frag_ctx; dummy.cont = NULL; dummy.cont_cls = NULL; dummy.session = s; call_continuation (&dummy, result); /* Remove leftover fragments from queue */ if (s->address->address_length == sizeof(struct IPv6UdpAddress)) { udpw = plugin->ipv6_queue_head; while (NULL != udpw) { tmp = udpw->next; if ((udpw->frag_ctx != NULL )&& (udpw->frag_ctx == s->frag_ctx)){ dequeue (plugin, udpw); call_continuation (udpw, GNUNET_SYSERR); GNUNET_free (udpw); } udpw = tmp; } } if (s->address->address_length == sizeof(struct IPv4UdpAddress)) { udpw = plugin->ipv4_queue_head; while (udpw != NULL ) { tmp = udpw->next; if ((NULL != udpw->frag_ctx) && (udpw->frag_ctx == s->frag_ctx)) { dequeue (plugin, udpw); call_continuation (udpw, GNUNET_SYSERR); GNUNET_free(udpw); } udpw = tmp; } } /* Destroy fragmentation context */ GNUNET_FRAGMENT_context_destroy (fc->frag, &s->last_expected_msg_delay, &s->last_expected_ack_delay); s->frag_ctx = NULL; GNUNET_free(fc); } /** * Scan the heap for a receive context with the given address. * * @param cls the `struct FindReceiveContext` * @param node internal node of the heap * @param element value stored at the node (a 'struct ReceiveContext') * @param cost cost associated with the node * @return #GNUNET_YES if we should continue to iterate, * #GNUNET_NO if not. */ static int find_receive_context (void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost) { struct FindReceiveContext *frc = cls; struct DefragContext *e = element; if ((frc->addr_len == e->addr_len) && (0 == memcmp (frc->addr, e->src_addr, frc->addr_len))) { frc->rc = e; return GNUNET_NO; } return GNUNET_YES; } /** * Functions with this signature are called whenever we need * to close a session due to a disconnect or failure to * establish a connection. * * @param cls closure with the `struct Plugin` * @param s session to close down * @return #GNUNET_OK on success */ static int udp_disconnect_session (void *cls, struct Session *s) { struct Plugin *plugin = cls; struct UDP_MessageWrapper *udpw; struct UDP_MessageWrapper *next; struct FindReceiveContext frc; GNUNET_assert(GNUNET_YES != s->in_destroy); LOG(GNUNET_ERROR_TYPE_DEBUG, "Session %p to peer `%s' address ended\n", s, GNUNET_i2s (&s->target), udp_address_to_string (NULL, s->address->address, s->address->address_length)); /* stop timeout task */ if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task) { GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != s->frag_ctx) { /* Remove fragmented message due to disconnect */ fragmented_message_done (s->frag_ctx, GNUNET_SYSERR); } frc.rc = NULL; frc.addr = s->address->address; frc.addr_len = s->address->address_length; /* Lookup existing receive context for this address */ if (NULL != plugin->defrag_ctxs) { GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs, &find_receive_context, &frc); if (NULL != frc.rc) { struct DefragContext *d_ctx = frc.rc; GNUNET_CONTAINER_heap_remove_node (d_ctx->hnode); GNUNET_DEFRAGMENT_context_destroy (d_ctx->defrag); GNUNET_free (d_ctx); } } next = plugin->ipv4_queue_head; while (NULL != (udpw = next)) { next = udpw->next; if (udpw->session == s) { dequeue (plugin, udpw); call_continuation (udpw, GNUNET_SYSERR); GNUNET_free(udpw); } } next = plugin->ipv6_queue_head; while (NULL != (udpw = next)) { next = udpw->next; if (udpw->session == s) { dequeue (plugin, udpw); call_continuation (udpw, GNUNET_SYSERR); GNUNET_free(udpw); } } plugin->env->session_end (plugin->env->cls, s->address, s); if (NULL != s->frag_ctx) { if (NULL != s->frag_ctx->cont) { s->frag_ctx->cont (s->frag_ctx->cont_cls, &s->target, GNUNET_SYSERR, s->frag_ctx->payload_size, s->frag_ctx->on_wire_size); LOG(GNUNET_ERROR_TYPE_DEBUG, "Calling continuation for fragemented message to `%s' with result SYSERR\n", GNUNET_i2s (&s->target)); } } GNUNET_assert( GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (plugin->sessions, &s->target, s)); GNUNET_STATISTICS_set (plugin->env->stats, "# UDP, sessions active", GNUNET_CONTAINER_multipeermap_size (plugin->sessions), GNUNET_NO); if (s->rc > 0) s->in_destroy = GNUNET_YES; else { GNUNET_HELLO_address_free (s->address); free_session (s); } return GNUNET_OK; } /** * Function that is called to get the keepalive factor. * #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int udp_query_keepalive_factor (void *cls) { return 15; } /** * Destroy a session, plugin is being unloaded. * * @param cls the `struct Plugin` * @param key hash of public key of target peer * @param value a `struct PeerSession *` to clean up * @return #GNUNET_OK (continue to iterate) */ static int disconnect_and_free_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct Plugin *plugin = cls; udp_disconnect_session (plugin, value); return GNUNET_OK; } /** * Disconnect from a remote node. Clean up session if we have one for * this peer. * * @param cls closure for this call (should be handle to Plugin) * @param target the peeridentity of the peer to disconnect * @return #GNUNET_OK on success, #GNUNET_SYSERR if the operation failed */ static void udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) { struct Plugin *plugin = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer `%s'\n", GNUNET_i2s (target)); /* Clean up sessions */ GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessions, target, &disconnect_and_free_it, plugin); } /** * Session was idle, so disconnect it * * @param cls the `struct Session` to time out * @param tc scheduler context */ static void session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *s = cls; s->timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %p was idle for %s, disconnecting\n", s, GNUNET_STRINGS_relative_time_to_string (UDP_SESSION_TIME_OUT, GNUNET_YES)); /* call session destroy function */ udp_disconnect_session (plugin, s); } /** * Increment session timeout due to activity * * @param s session to reschedule timeout activity for */ static void reschedule_session_timeout (struct Session *s) { if (GNUNET_YES == s->in_destroy) return; GNUNET_assert(GNUNET_SCHEDULER_NO_TASK != s->timeout_task); GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_add_delayed (UDP_SESSION_TIME_OUT, &session_timeout, s); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Timeout restarted for session %p\n", s); } static struct Session * create_session (struct Plugin *plugin, const struct GNUNET_HELLO_Address *address) { struct Session *s; s = GNUNET_new (struct Session); s->address = GNUNET_HELLO_address_copy (address); s->target = address->peer; s->last_expected_ack_delay = GNUNET_TIME_relative_multiply ( GNUNET_TIME_UNIT_MILLISECONDS, 250); s->last_expected_msg_delay = GNUNET_TIME_UNIT_MILLISECONDS; s->flow_delay_from_other_peer = GNUNET_TIME_UNIT_ZERO_ABS; s->flow_delay_for_other_peer = GNUNET_TIME_UNIT_ZERO; s->timeout_task = GNUNET_SCHEDULER_add_delayed (UDP_SESSION_TIME_OUT, &session_timeout, s); return s; } static int session_cmp_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct SessionCompareContext *cctx = cls; const struct GNUNET_HELLO_Address *address = cctx->address; struct Session *s = value; LOG (GNUNET_ERROR_TYPE_DEBUG, "Comparing address %s <-> %s\n", udp_address_to_string (NULL, address->address, address->address_length), udp_address_to_string (NULL, s->address->address, s->address->address_length)); if (0 == GNUNET_HELLO_address_cmp(s->address, cctx->address)) { cctx->res = s; return GNUNET_NO; } return GNUNET_YES; } /** * Function obtain the network type for a session * * @param cls closure ('struct Plugin*') * @param session the session * @return the network type */ static enum GNUNET_ATS_Network_Type udp_get_network (void *cls, struct Session *session) { return ntohl (session->ats.value); } /** * Creates a new outbound session the transport service will use to * send data to the peer * * @param cls the plugin * @param address the address * @return the session or NULL of max connections exceeded */ static struct Session * udp_plugin_lookup_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct Plugin * plugin = cls; struct IPv6UdpAddress * udp_a6; struct IPv4UdpAddress * udp_a4; GNUNET_assert(plugin != NULL); GNUNET_assert(address != NULL); if ( (address->address == NULL )|| ((address->address_length != sizeof (struct IPv4UdpAddress)) && (address->address_length != sizeof (struct IPv6UdpAddress)))) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Trying to create session for address of unexpected length %u (should be %u or %u)\n"), address->address_length, sizeof (struct IPv4UdpAddress), sizeof (struct IPv6UdpAddress)); return NULL; } if (address->address_length == sizeof(struct IPv4UdpAddress)) { if (plugin->sockv4 == NULL) return NULL; udp_a4 = (struct IPv4UdpAddress *) address->address; if (udp_a4->u4_port == 0) return NULL; } if (address->address_length == sizeof(struct IPv6UdpAddress)) { if (plugin->sockv6 == NULL) return NULL; udp_a6 = (struct IPv6UdpAddress *) address->address; if (udp_a6->u6_port == 0) return NULL; } /* check if session already exists */ struct SessionCompareContext cctx; cctx.address = address; cctx.res = NULL; LOG(GNUNET_ERROR_TYPE_DEBUG, "Looking for existing session for peer `%s' `%s' \n", GNUNET_i2s (&address->peer), udp_address_to_string(NULL, address->address, address->address_length)); GNUNET_CONTAINER_multipeermap_get_multiple (plugin->sessions, &address->peer, session_cmp_it, &cctx); if (cctx.res != NULL ) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res); return cctx.res; } return NULL; } static struct Session * udp_plugin_create_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct Session *s; struct IPv4UdpAddress *udp_v4; struct IPv6UdpAddress *udp_v6; s = create_session (plugin, address); if (sizeof (struct IPv4UdpAddress) == address->address_length) { struct sockaddr_in v4; udp_v4 = (struct IPv4UdpAddress *) address->address; memset (&v4, '\0', sizeof (v4)); v4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = sizeof (struct sockaddr_in); #endif v4.sin_port = udp_v4->u4_port; v4.sin_addr.s_addr = udp_v4->ipv4_addr; s->ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &v4, sizeof (v4)); } else if (sizeof (struct IPv6UdpAddress) == address->address_length) { struct sockaddr_in6 v6; udp_v6 = (struct IPv6UdpAddress *) address->address; memset (&v6, '\0', sizeof (v6)); v6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = sizeof (struct sockaddr_in6); #endif v6.sin6_port = udp_v6->u6_port; v6.sin6_addr = udp_v6->ipv6_addr; s->ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) &v6, sizeof (v6)); } if (NULL == s) return NULL; /* protocol not supported or address invalid */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Creating new %s session %p for peer `%s' address `%s'\n", GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND) ? "inbound" : "outbound", s, GNUNET_i2s (&address->peer), udp_address_to_string( NULL,address->address,address->address_length)); GNUNET_assert( GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (plugin->sessions, &s->target, s, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); GNUNET_STATISTICS_set (plugin->env->stats, "# UDP, sessions active", GNUNET_CONTAINER_multipeermap_size (plugin->sessions), GNUNET_NO); return s; } static void udp_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessions, peer, session)) { GNUNET_break(0); return; } /* Reschedule session timeout */ reschedule_session_timeout (session); } /** * Creates a new outbound session the transport service will use to send data to the * peer * * @param cls the plugin * @param address the address * @return the session or NULL of max connections exceeded */ static struct Session * udp_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct Session *s; if (NULL == address) { GNUNET_break(0); return NULL; } if ( (address->address_length != sizeof(struct IPv4UdpAddress)) && (address->address_length != sizeof(struct IPv6UdpAddress)) ) return NULL; /* otherwise create new */ if (NULL != (s = udp_plugin_lookup_session (cls, address))) return s; return udp_plugin_create_session (cls, address); } static void enqueue (struct Plugin *plugin, struct UDP_MessageWrapper *udpw) { if (plugin->bytes_in_buffer + udpw->msg_size > INT64_MAX) GNUNET_break(0); else { GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes in buffers", udpw->msg_size, GNUNET_NO); plugin->bytes_in_buffer += udpw->msg_size; } GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, msgs in buffers", 1, GNUNET_NO); if (udpw->session->address->address_length == sizeof (struct IPv4UdpAddress)) GNUNET_CONTAINER_DLL_insert(plugin->ipv4_queue_head, plugin->ipv4_queue_tail, udpw); else if (udpw->session->address->address_length == sizeof (struct IPv6UdpAddress)) GNUNET_CONTAINER_DLL_insert(plugin->ipv6_queue_head, plugin->ipv6_queue_tail, udpw); else GNUNET_break (0); } /** * Fragment message was transmitted via UDP, let fragmentation know * to send the next fragment now. * * @param cls the 'struct UDPMessageWrapper' of the fragment * @param target destination peer (ignored) * @param result GNUNET_OK on success (ignored) * @param payload bytes payload sent * @param physical bytes physical sent */ static void send_next_fragment (void *cls, const struct GNUNET_PeerIdentity *target, int result, size_t payload, size_t physical) { struct UDP_MessageWrapper *udpw = cls; GNUNET_FRAGMENT_context_transmission_done (udpw->frag_ctx->frag); } /** * Function that is called with messages created by the fragmentation * module. In the case of the 'proc' callback of the * GNUNET_FRAGMENT_context_create function, this function must * eventually call 'GNUNET_FRAGMENT_context_transmission_done'. * * @param cls closure, the 'struct FragmentationContext' * @param msg the message that was created */ static void enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg) { struct UDP_FragmentationContext *frag_ctx = cls; struct Plugin *plugin = frag_ctx->plugin; struct UDP_MessageWrapper * udpw; size_t msg_len = ntohs (msg->size); LOG(GNUNET_ERROR_TYPE_DEBUG, "Enqueuing fragment with %u bytes\n", msg_len); frag_ctx->fragments_used++; udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + msg_len); udpw->session = frag_ctx->session; udpw->msg_buf = (char *) &udpw[1]; udpw->msg_size = msg_len; udpw->payload_size = msg_len; /*FIXME: minus fragment overhead */ udpw->cont = &send_next_fragment; udpw->cont_cls = udpw; udpw->timeout = frag_ctx->timeout; udpw->frag_ctx = frag_ctx; udpw->msg_type = UMT_MSG_FRAGMENTED; memcpy (udpw->msg_buf, msg, msg_len); enqueue (plugin, udpw); schedule_select (plugin); } /** * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param s which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in 'msgbuf' * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t udp_plugin_send (void *cls, struct Session *s, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin *plugin = cls; size_t udpmlen = msgbuf_size + sizeof(struct UDPMessage); struct UDP_FragmentationContext * frag_ctx; struct UDP_MessageWrapper * udpw; struct UDPMessage *udp; char mbuf[udpmlen]; GNUNET_assert(plugin != NULL); GNUNET_assert(s != NULL); if ( (s->address->address_length == sizeof(struct IPv6UdpAddress)) && (plugin->sockv6 == NULL) ) return GNUNET_SYSERR; if ( (s->address->address_length == sizeof(struct IPv4UdpAddress)) && (plugin->sockv4 == NULL) ) return GNUNET_SYSERR; if (udpmlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break(0); return GNUNET_SYSERR; } if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_contains_value (plugin->sessions, &s->target, s)) { GNUNET_break(0); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "UDP transmits %u-byte message to `%s' using address `%s'\n", udpmlen, GNUNET_i2s (&s->target), udp_address_to_string (NULL, s->address->address, s->address->address_length)); /* Message */ udp = (struct UDPMessage *) mbuf; udp->header.size = htons (udpmlen); udp->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE); udp->reserved = htonl (0); udp->sender = *plugin->env->my_identity; /* We do not update the session time out here! * Otherwise this session will not timeout since we send keep alive before * session can timeout * * For UDP we update session timeout only on receive, this will cover keep * alives, since remote peer will reply with keep alive response! */ if (udpmlen <= UDP_MTU) { /* unfragmented message */ udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + udpmlen); udpw->session = s; udpw->msg_buf = (char *) &udpw[1]; udpw->msg_size = udpmlen; /* message size with UDP overhead */ udpw->payload_size = msgbuf_size; /* message size without UDP overhead */ udpw->timeout = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), to); udpw->cont = cont; udpw->cont_cls = cont_cls; udpw->frag_ctx = NULL; udpw->msg_type = UMT_MSG_UNFRAGMENTED; memcpy (udpw->msg_buf, udp, sizeof(struct UDPMessage)); memcpy (&udpw->msg_buf[sizeof(struct UDPMessage)], msgbuf, msgbuf_size); enqueue (plugin, udpw); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, messages, attempt", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, bytes payload, attempt", udpw->payload_size, GNUNET_NO); } else { /* fragmented message */ if (s->frag_ctx != NULL) return GNUNET_SYSERR; memcpy (&udp[1], msgbuf, msgbuf_size); frag_ctx = GNUNET_new (struct UDP_FragmentationContext); frag_ctx->plugin = plugin; frag_ctx->session = s; frag_ctx->cont = cont; frag_ctx->cont_cls = cont_cls; frag_ctx->timeout = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), to); frag_ctx->payload_size = msgbuf_size; /* unfragmented message size without UDP overhead */ frag_ctx->on_wire_size = 0; /* bytes with UDP and fragmentation overhead */ frag_ctx->frag = GNUNET_FRAGMENT_context_create (plugin->env->stats, UDP_MTU, &plugin->tracker, s->last_expected_msg_delay, s->last_expected_ack_delay, &udp->header, &enqueue_fragment, frag_ctx); s->frag_ctx = frag_ctx; GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, messages, pending", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, messages, attempt", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, bytes payload, attempt", frag_ctx->payload_size, GNUNET_NO); } schedule_select (plugin); return udpmlen; } /** * Our external IP address/port mapping has changed. * * @param cls closure, the `struct LocalAddrList` * @param add_remove #GNUNET_YES to mean the new public IP address, #GNUNET_NO to mean * the previous (now invalid) one * @param addr either the previous or the new public IP address * @param addrlen actual lenght of the address */ static void udp_nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen) { struct Plugin *plugin = cls; struct GNUNET_HELLO_Address *address; struct IPv4UdpAddress u4; struct IPv6UdpAddress u6; void *arg; size_t args; LOG(GNUNET_ERROR_TYPE_INFO, "NAT notification to %s address `%s'\n", (GNUNET_YES == add_remove) ? "add" : "remove", GNUNET_a2s (addr, addrlen)); /* convert 'address' to our internal format */ switch (addr->sa_family) { case AF_INET: GNUNET_assert(addrlen == sizeof(struct sockaddr_in)); memset (&u4, 0, sizeof(u4)); u4.options = htonl (myoptions); u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; u4.u4_port = ((struct sockaddr_in *) addr)->sin_port; if (0 == ((struct sockaddr_in *) addr)->sin_port) return; arg = &u4; args = sizeof(struct IPv4UdpAddress); break; case AF_INET6: GNUNET_assert(addrlen == sizeof(struct sockaddr_in6)); memset (&u6, 0, sizeof(u6)); u6.options = htonl (myoptions); if (0 == ((struct sockaddr_in6 *) addr)->sin6_port) return; memcpy (&u6.ipv6_addr, &((struct sockaddr_in6 *) addr)->sin6_addr, sizeof(struct in6_addr)); u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port; arg = &u6; args = sizeof(struct IPv6UdpAddress); break; default: GNUNET_break(0); return; } /* modify our published address list */ address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, arg, args, GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->notify_address (plugin->env->cls, add_remove, address); GNUNET_HELLO_address_free (address); } /** * Message tokenizer has broken up an incomming message. Pass it on * to the service. * * @param cls the 'struct Plugin' * @param client the `struct SourceInformation` * @param hdr the actual message * @return #GNUNET_OK (always) */ static int process_inbound_tokenized_messages (void *cls, void *client, const struct GNUNET_MessageHeader *hdr) { struct Plugin *plugin = cls; struct SourceInformation *si = client; struct GNUNET_TIME_Relative delay; GNUNET_assert(si->session != NULL); if (GNUNET_YES == si->session->in_destroy) return GNUNET_OK; /* setup ATS */ GNUNET_break(ntohl (si->session->ats.value) != GNUNET_ATS_NET_UNSPECIFIED); reschedule_session_timeout (si->session); delay = plugin->env->receive (plugin->env->cls, si->session->address, si->session, hdr); plugin->env->update_address_metrics (plugin->env->cls, si->session->address, si->session, &si->session->ats, 1); si->session->flow_delay_for_other_peer = delay; return GNUNET_OK; } /** * We've received a UDP Message. Process it (pass contents to main service). * * @param plugin plugin context * @param msg the message * @param sender_addr sender address * @param sender_addr_len number of bytes in sender_addr */ static void process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg, const struct sockaddr *sender_addr, socklen_t sender_addr_len) { struct SourceInformation si; struct Session * s; struct GNUNET_HELLO_Address *address; struct IPv4UdpAddress u4; struct IPv6UdpAddress u6; const void *arg; size_t args; if (0 != ntohl (msg->reserved)) { GNUNET_break_op(0); return; } if (ntohs (msg->header.size) < sizeof(struct GNUNET_MessageHeader) + sizeof(struct UDPMessage)) { GNUNET_break_op(0); return; } /* convert address */ switch (sender_addr->sa_family) { case AF_INET: GNUNET_assert(sender_addr_len == sizeof(struct sockaddr_in)); memset (&u4, 0, sizeof(u4)); u6.options = htonl (0); u4.ipv4_addr = ((struct sockaddr_in *) sender_addr)->sin_addr.s_addr; u4.u4_port = ((struct sockaddr_in *) sender_addr)->sin_port; arg = &u4; args = sizeof(u4); break; case AF_INET6: GNUNET_assert(sender_addr_len == sizeof(struct sockaddr_in6)); memset (&u6, 0, sizeof(u6)); u6.options = htonl (0); u6.ipv6_addr = ((struct sockaddr_in6 *) sender_addr)->sin6_addr; u6.u6_port = ((struct sockaddr_in6 *) sender_addr)->sin6_port; arg = &u6; args = sizeof(u6); break; default: GNUNET_break(0); return; } LOG(GNUNET_ERROR_TYPE_DEBUG, "Received message with %u bytes from peer `%s' at `%s'\n", (unsigned int ) ntohs (msg->header.size), GNUNET_i2s (&msg->sender), GNUNET_a2s (sender_addr, sender_addr_len)); address = GNUNET_HELLO_address_allocate ( &msg->sender, PLUGIN_NAME, arg, args, GNUNET_HELLO_ADDRESS_INFO_INBOUND); if (NULL == (s = udp_plugin_lookup_session (plugin, address))) { s = udp_plugin_create_session (plugin, address); plugin->env->session_start (NULL, address, s, NULL, 0); } GNUNET_free(address); /* iterate over all embedded messages */ si.session = s; si.sender = msg->sender; si.arg = arg; si.args = args; s->rc++; GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1], ntohs (msg->header.size) - sizeof(struct UDPMessage), GNUNET_YES, GNUNET_NO); s->rc--; if ((0 == s->rc) && (GNUNET_YES == s->in_destroy)) free_session (s); } /** * Process a defragmented message. * * @param cls the 'struct ReceiveContext' * @param msg the message */ static void fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg) { struct DefragContext *rc = cls; if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE) { GNUNET_break(0); return; } if (ntohs (msg->size) < sizeof(struct UDPMessage)) { GNUNET_break(0); return; } process_udp_message (rc->plugin, (const struct UDPMessage *) msg, rc->src_addr, rc->addr_len); } /** * Context to lookup a session based on a IP address */ struct LookupContext { /** * The result */ struct Session *res; /** * The socket address */ const struct sockaddr *address; /** * The socket address length */ size_t addr_len; /** * Is a fragmentation context required for the session */ int must_have_frag_ctx; }; static int lookup_session_by_sockaddr_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct LookupContext *l_ctx = cls; struct Session * s = value; struct IPv4UdpAddress u4; struct IPv6UdpAddress u6; void *arg; size_t args; /* convert address */ switch (l_ctx->address->sa_family) { case AF_INET: GNUNET_assert(l_ctx->addr_len == sizeof(struct sockaddr_in)); memset (&u4, 0, sizeof(u4)); u6.options = htonl (0); u4.ipv4_addr = ((struct sockaddr_in *) l_ctx->address)->sin_addr.s_addr; u4.u4_port = ((struct sockaddr_in *) l_ctx->address)->sin_port; arg = &u4; args = sizeof(u4); break; case AF_INET6: GNUNET_assert(l_ctx->addr_len == sizeof(struct sockaddr_in6)); memset (&u6, 0, sizeof(u6)); u6.options = htonl (0); u6.ipv6_addr = ((struct sockaddr_in6 *) l_ctx->address)->sin6_addr; u6.u6_port = ((struct sockaddr_in6 *) l_ctx->address)->sin6_port; arg = &u6; args = sizeof(u6); break; default: GNUNET_break(0); return GNUNET_YES; } if ((GNUNET_YES == l_ctx->must_have_frag_ctx) && (NULL == s->frag_ctx)) return GNUNET_YES; /* Does not compare peer identities but addresses */ if ((args == s->address->address_length) && (0 == memcmp (arg, s->address->address, args))) { l_ctx->res = s; return GNUNET_YES; } return GNUNET_YES; } /** * Transmit an acknowledgement. * * @param cls the 'struct ReceiveContext' * @param id message ID (unused) * @param msg ack to transmit */ static void ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg) { struct DefragContext *rc = cls; size_t msize = sizeof(struct UDP_ACK_Message) + ntohs (msg->size); struct UDP_ACK_Message *udp_ack; uint32_t delay = 0; struct UDP_MessageWrapper *udpw; struct Session *s; struct LookupContext l_ctx; l_ctx.address = rc->src_addr; l_ctx.addr_len = rc->addr_len; l_ctx.must_have_frag_ctx = GNUNET_NO; l_ctx.res = NULL; GNUNET_CONTAINER_multipeermap_iterate (rc->plugin->sessions, &lookup_session_by_sockaddr_it, &l_ctx); s = l_ctx.res; if (NULL == s) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Trying to transmit ACK to peer `%s' but not session found!\n", GNUNET_a2s(rc->src_addr, rc->addr_len)); GNUNET_CONTAINER_heap_remove_node (rc->hnode); GNUNET_DEFRAGMENT_context_destroy (rc->defrag); GNUNET_free (rc); return; } if (s->flow_delay_for_other_peer.rel_value_us <= UINT32_MAX) delay = s->flow_delay_for_other_peer.rel_value_us; LOG(GNUNET_ERROR_TYPE_DEBUG, "Sending ACK to `%s' including delay of %s\n", GNUNET_a2s (rc->src_addr, (rc->src_addr->sa_family == AF_INET) ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6)), GNUNET_STRINGS_relative_time_to_string (s->flow_delay_for_other_peer, GNUNET_YES)); udpw = GNUNET_malloc (sizeof (struct UDP_MessageWrapper) + msize); udpw->msg_size = msize; udpw->payload_size = 0; udpw->session = s; udpw->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; udpw->msg_buf = (char *) &udpw[1]; udpw->msg_type = UMT_MSG_ACK; udp_ack = (struct UDP_ACK_Message *) udpw->msg_buf; udp_ack->header.size = htons ((uint16_t) msize); udp_ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK); udp_ack->delay = htonl (delay); udp_ack->sender = *rc->plugin->env->my_identity; memcpy (&udp_ack[1], msg, ntohs (msg->size)); enqueue (rc->plugin, udpw); schedule_select (rc->plugin); } static void read_process_msg (struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const struct sockaddr *addr, socklen_t fromlen) { if (ntohs (msg->size) < sizeof(struct UDPMessage)) { GNUNET_break_op(0); return; } process_udp_message (plugin, (const struct UDPMessage *) msg, addr, fromlen); } static void read_process_ack (struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const struct sockaddr *addr, socklen_t fromlen) { const struct GNUNET_MessageHeader *ack; const struct UDP_ACK_Message *udp_ack; struct LookupContext l_ctx; struct Session *s; struct GNUNET_TIME_Relative flow_delay; if (ntohs (msg->size) < sizeof(struct UDP_ACK_Message) + sizeof(struct GNUNET_MessageHeader)) { GNUNET_break_op(0); return; } udp_ack = (const struct UDP_ACK_Message *) msg; /* Lookup session based on sockaddr */ l_ctx.address = addr; l_ctx.addr_len = fromlen; l_ctx.res = NULL; l_ctx.must_have_frag_ctx = GNUNET_YES; GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, &lookup_session_by_sockaddr_it, &l_ctx); s = l_ctx.res; if ((NULL == s) || (NULL == s->frag_ctx)) { return; } flow_delay.rel_value_us = (uint64_t) ntohl (udp_ack->delay); LOG(GNUNET_ERROR_TYPE_DEBUG, "We received a sending delay of %s\n", GNUNET_STRINGS_relative_time_to_string (flow_delay, GNUNET_YES)); s->flow_delay_from_other_peer = GNUNET_TIME_relative_to_absolute (flow_delay); ack = (const struct GNUNET_MessageHeader *) &udp_ack[1]; if (ntohs (ack->size) != ntohs (msg->size) - sizeof(struct UDP_ACK_Message)) { GNUNET_break_op(0); return; } if (0 != memcmp (&l_ctx.res->target, &udp_ack->sender, sizeof(struct GNUNET_PeerIdentity))) GNUNET_break(0); if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (s->frag_ctx->frag, ack)) { LOG(GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte acknowledgement from `%s' at `%s'\n", (unsigned int ) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender), GNUNET_a2s (addr, fromlen)); /* Expect more ACKs to arrive */ return; } LOG(GNUNET_ERROR_TYPE_DEBUG, "Message full ACK'ed\n", (unsigned int ) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender), GNUNET_a2s (addr, fromlen)); /* Remove fragmented message after successful sending */ fragmented_message_done (s->frag_ctx, GNUNET_OK); } static void read_process_fragment (struct Plugin *plugin, const struct GNUNET_MessageHeader *msg, const struct sockaddr *addr, socklen_t fromlen) { struct DefragContext *d_ctx; struct GNUNET_TIME_Absolute now; struct FindReceiveContext frc; frc.rc = NULL; frc.addr = addr; frc.addr_len = fromlen; LOG(GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte fragment from `%s'\n", (unsigned int ) ntohs (msg->size), GNUNET_a2s (addr, fromlen)); /* Lookup existing receive context for this address */ GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs, &find_receive_context, &frc); now = GNUNET_TIME_absolute_get (); d_ctx = frc.rc; if (d_ctx == NULL ) { /* Create a new defragmentation context */ d_ctx = GNUNET_malloc (sizeof (struct DefragContext) + fromlen); memcpy (&d_ctx[1], addr, fromlen); d_ctx->src_addr = (const struct sockaddr *) &d_ctx[1]; d_ctx->addr_len = fromlen; d_ctx->plugin = plugin; d_ctx->defrag = GNUNET_DEFRAGMENT_context_create (plugin->env->stats, UDP_MTU, UDP_MAX_MESSAGES_IN_DEFRAG, d_ctx, &fragment_msg_proc, &ack_proc); d_ctx->hnode = GNUNET_CONTAINER_heap_insert (plugin->defrag_ctxs, d_ctx, (GNUNET_CONTAINER_HeapCostType) now.abs_value_us); LOG(GNUNET_ERROR_TYPE_DEBUG, "Created new defragmentation context for %u-byte fragment from `%s'\n", (unsigned int ) ntohs (msg->size), GNUNET_a2s (addr, fromlen)); } else { LOG(GNUNET_ERROR_TYPE_DEBUG, "Found existing defragmentation context for %u-byte fragment from `%s'\n", (unsigned int ) ntohs (msg->size), GNUNET_a2s (addr, fromlen)); } if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (d_ctx->defrag, msg)) { /* keep this 'rc' from expiring */ GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs, d_ctx->hnode, (GNUNET_CONTAINER_HeapCostType) now.abs_value_us); } if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) > UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG) { /* remove 'rc' that was inactive the longest */ d_ctx = GNUNET_CONTAINER_heap_remove_root (plugin->defrag_ctxs); GNUNET_assert(NULL != d_ctx); GNUNET_DEFRAGMENT_context_destroy (d_ctx->defrag); GNUNET_free(d_ctx); } } /** * Read and process a message from the given socket. * * @param plugin the overall plugin * @param rsock socket to read from */ static void udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock) { socklen_t fromlen; struct sockaddr_storage addr; char buf[65536] GNUNET_ALIGN; ssize_t size; const struct GNUNET_MessageHeader *msg; fromlen = sizeof(addr); memset (&addr, 0, sizeof(addr)); size = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof(buf), (struct sockaddr *) &addr, &fromlen); #if MINGW /* On SOCK_DGRAM UDP sockets recvfrom might fail with a * WSAECONNRESET error to indicate that previous sendto() (yes, sendto!) * on this socket has failed. * Quote from MSDN: * WSAECONNRESET - The virtual circuit was reset by the remote side * executing a hard or abortive close. The application should close * the socket; it is no longer usable. On a UDP-datagram socket this * error indicates a previous send operation resulted in an ICMP Port * Unreachable message. */ if ( (-1 == size) && (ECONNRESET == errno) ) return; #endif if (-1 == size) { LOG(GNUNET_ERROR_TYPE_DEBUG, "UDP failed to receive data: %s\n", STRERROR (errno)); /* Connection failure or something. Not a protocol violation. */ return; } if (size < sizeof(struct GNUNET_MessageHeader)) { LOG(GNUNET_ERROR_TYPE_WARNING, "UDP got %u bytes, which is not enough for a GNUnet message header\n", (unsigned int ) size); /* _MAY_ be a connection failure (got partial message) */ /* But it _MAY_ also be that the other side uses non-GNUnet protocol. */ GNUNET_break_op(0); return; } msg = (const struct GNUNET_MessageHeader *) buf; LOG(GNUNET_ERROR_TYPE_DEBUG, "UDP received %u-byte message from `%s' type %u\n", (unsigned int ) size, GNUNET_a2s ((const struct sockaddr * ) &addr, fromlen), ntohs (msg->type)); if (size != ntohs (msg->size)) { GNUNET_break_op(0); return; } GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes, received", size, GNUNET_NO); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON: if (GNUNET_YES == plugin->enable_broadcasting_receiving) udp_broadcast_receive (plugin, buf, size, (const struct sockaddr *) &addr, fromlen); return; case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_MESSAGE: read_process_msg (plugin, msg, (const struct sockaddr *) &addr, fromlen); return; case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK: read_process_ack (plugin, msg, (const struct sockaddr *) &addr, fromlen); return; case GNUNET_MESSAGE_TYPE_FRAGMENT: read_process_fragment (plugin, msg, (const struct sockaddr *) &addr, fromlen); return; default: GNUNET_break_op(0); return; } } static struct UDP_MessageWrapper * remove_timeout_messages_and_select (struct UDP_MessageWrapper *head, struct GNUNET_NETWORK_Handle *sock) { struct UDP_MessageWrapper *udpw = NULL; struct GNUNET_TIME_Relative remaining; udpw = head; while (udpw != NULL ) { /* Find messages with timeout */ remaining = GNUNET_TIME_absolute_get_remaining (udpw->timeout); if (GNUNET_TIME_UNIT_ZERO.rel_value_us == remaining.rel_value_us) { /* Message timed out */ switch (udpw->msg_type) { case UMT_MSG_UNFRAGMENTED: GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes, sent, timeout", udpw->msg_size, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, messages, sent, timeout", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, messages, sent, timeout", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, unfragmented msgs, bytes, sent, timeout", udpw->payload_size, GNUNET_NO); /* Not fragmented message */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' with size %u timed out\n", GNUNET_i2s (&udpw->session->target), udpw->payload_size); call_continuation (udpw, GNUNET_SYSERR); /* Remove message */ dequeue (plugin, udpw); GNUNET_free(udpw); break; case UMT_MSG_FRAGMENTED: /* Fragmented message */ GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes, sent, timeout", udpw->frag_ctx->on_wire_size, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, messages, sent, timeout", 1, GNUNET_NO); call_continuation (udpw, GNUNET_SYSERR); LOG(GNUNET_ERROR_TYPE_DEBUG, "Fragment for message for peer `%s' with size %u timed out\n", GNUNET_i2s (&udpw->session->target), udpw->frag_ctx->payload_size); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, messages, sent, timeout", 1, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, fragmented msgs, bytes, sent, timeout", udpw->frag_ctx->payload_size, GNUNET_NO); /* Remove fragmented message due to timeout */ fragmented_message_done (udpw->frag_ctx, GNUNET_SYSERR); break; case UMT_MSG_ACK: GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes, sent, timeout", udpw->msg_size, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, messages, sent, timeout", 1, GNUNET_NO); LOG(GNUNET_ERROR_TYPE_DEBUG, "ACK Message for peer `%s' with size %u timed out\n", GNUNET_i2s (&udpw->session->target), udpw->payload_size); call_continuation (udpw, GNUNET_SYSERR); dequeue (plugin, udpw); GNUNET_free(udpw); break; default: break; } if (sock == plugin->sockv4) udpw = plugin->ipv4_queue_head; else if (sock == plugin->sockv6) udpw = plugin->ipv6_queue_head; else { GNUNET_break(0); /* should never happen */ udpw = NULL; } GNUNET_STATISTICS_update (plugin->env->stats, "# messages dismissed due to timeout", 1, GNUNET_NO); } else { /* Message did not time out, check flow delay */ remaining = GNUNET_TIME_absolute_get_remaining ( udpw->session->flow_delay_from_other_peer); if (GNUNET_TIME_UNIT_ZERO.rel_value_us == remaining.rel_value_us) { /* this message is not delayed */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' (%u bytes) is not delayed \n", GNUNET_i2s (&udpw->session->target), udpw->payload_size); break; /* Found message to send, break */ } else { /* Message is delayed, try next */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' (%u bytes) is delayed for %s\n", GNUNET_i2s (&udpw->session->target), udpw->payload_size, GNUNET_STRINGS_relative_time_to_string (remaining, GNUNET_YES)); udpw = udpw->next; } } } return udpw; } static void analyze_send_error (struct Plugin *plugin, const struct sockaddr *sa, socklen_t slen, int error) { static int network_down_error; struct GNUNET_ATS_Information type; type = plugin->env->get_address_type (plugin->env->cls, sa, slen); if (((GNUNET_ATS_NET_LAN == ntohl (type.value)) || (GNUNET_ATS_NET_WAN == ntohl (type.value))) && ((ENETUNREACH == errno)|| (ENETDOWN == errno))) { if ((network_down_error == GNUNET_NO) && (slen == sizeof (struct sockaddr_in))) { /* IPv4: "Network unreachable" or "Network down" * * This indicates we do not have connectivity */ LOG (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, _("UDP could not transmit message to `%s': " "Network seems down, please check your network configuration\n"), GNUNET_a2s (sa, slen)); } if ((network_down_error == GNUNET_NO) && (slen == sizeof (struct sockaddr_in6))) { /* IPv6: "Network unreachable" or "Network down" * * This indicates that this system is IPv6 enabled, but does not * have a valid global IPv6 address assigned or we do not have * connectivity */ LOG (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, _("UDP could not transmit IPv6 message! " "Please check your network configuration and disable IPv6 if your " "connection does not have a global IPv6 address\n")); } } else { LOG (GNUNET_ERROR_TYPE_WARNING, "UDP could not transmit message to `%s': `%s'\n", GNUNET_a2s (sa, slen), STRERROR (error)); } } static size_t udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock) { ssize_t sent; socklen_t slen; struct sockaddr *a; const struct IPv4UdpAddress *u4; struct sockaddr_in a4; const struct IPv6UdpAddress *u6; struct sockaddr_in6 a6; struct UDP_MessageWrapper *udpw; /* Find message to send */ udpw = remove_timeout_messages_and_select ((sock == plugin->sockv4) ? plugin->ipv4_queue_head : plugin->ipv6_queue_head, sock); if (NULL == udpw) return 0; /* No message to send */ if (sizeof (struct IPv4UdpAddress) == udpw->session->address->address_length) { u4 = udpw->session->address->address; memset (&a4, 0, sizeof(a4)); a4.sin_family = AF_INET; #if HAVE_SOCKADDR_IN_SIN_LEN a4.sin_len = sizeof (a4); #endif a4.sin_port = u4->u4_port; memcpy (&a4.sin_addr, &u4->ipv4_addr, sizeof(struct in_addr)); a = (struct sockaddr *) &a4; slen = sizeof (a4); } else if (sizeof (struct IPv6UdpAddress) == udpw->session->address->address_length) { u6 = udpw->session->address->address; memset (&a6, 0, sizeof(a6)); a6.sin6_family = AF_INET6; #if HAVE_SOCKADDR_IN_SIN_LEN a6.sin6_len = sizeof (a6); #endif a6.sin6_port = u6->u6_port; memcpy (&a6.sin6_addr, &u6->ipv6_addr, sizeof(struct in6_addr)); a = (struct sockaddr *) &a6; slen = sizeof (a6); } else { call_continuation (udpw, GNUNET_OK); dequeue (plugin, udpw); GNUNET_free (udpw); return GNUNET_SYSERR; } sent = GNUNET_NETWORK_socket_sendto (sock, udpw->msg_buf, udpw->msg_size, a, slen); if (GNUNET_SYSERR == sent) { /* Failure */ analyze_send_error (plugin, a, slen, errno); call_continuation (udpw, GNUNET_SYSERR); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes, sent, failure", sent, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, messages, sent, failure", 1, GNUNET_NO); } else { /* Success */ LOG(GNUNET_ERROR_TYPE_DEBUG, "UDP transmitted %u-byte message to `%s' `%s' (%d: %s)\n", (unsigned int ) (udpw->msg_size), GNUNET_i2s (&udpw->session->target), GNUNET_a2s (a, slen), (int ) sent, (sent < 0) ? STRERROR (errno) : "ok"); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, bytes, sent, success", sent, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UDP, total, messages, sent, success", 1, GNUNET_NO); if (NULL != udpw->frag_ctx) udpw->frag_ctx->on_wire_size += udpw->msg_size; call_continuation (udpw, GNUNET_OK); } dequeue (plugin, udpw); GNUNET_free(udpw); udpw = NULL; return sent; } /** * We have been notified that our readset has something to read. We don't * know which socket needs to be read, so we have to check each one * Then reschedule this function to be called again once more is available. * * @param cls the plugin handle * @param tc the scheduling context (for rescheduling this function again) */ static void udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Plugin *plugin = cls; plugin->select_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) && (NULL != plugin->sockv4) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv4))) udp_select_read (plugin, plugin->sockv4); if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && (NULL != plugin->sockv4) && (NULL != plugin->ipv4_queue_head) && (GNUNET_NETWORK_fdset_isset (tc->write_ready, plugin->sockv4))) udp_select_send (plugin, plugin->sockv4); schedule_select (plugin); } /** * We have been notified that our readset has something to read. We don't * know which socket needs to be read, so we have to check each one * Then reschedule this function to be called again once more is available. * * @param cls the plugin handle * @param tc the scheduling context (for rescheduling this function again) */ static void udp_plugin_select_v6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Plugin *plugin = cls; plugin->select_task_v6 = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; if (((tc->reason & GNUNET_SCHEDULER_REASON_READ_READY) != 0) && (NULL != plugin->sockv6) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->sockv6))) udp_select_read (plugin, plugin->sockv6); if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && (NULL != plugin->sockv6) && (plugin->ipv6_queue_head != NULL )&& (GNUNET_NETWORK_fdset_isset (tc->write_ready, plugin->sockv6)) )udp_select_send (plugin, plugin->sockv6); schedule_select (plugin); } /** * Setup the UDP sockets (for IPv4 and IPv6) for the plugin. * * @param plugin the plugin to initialize * @param bind_v6 IPv6 address to bind to (can be NULL, for 'any') * @param bind_v4 IPv4 address to bind to (can be NULL, for 'any') * @return number of sockets that were successfully bound */ static int setup_sockets (struct Plugin *plugin, const struct sockaddr_in6 *bind_v6, const struct sockaddr_in *bind_v4) { int tries; int sockets_created = 0; struct sockaddr_in6 server_addrv6; struct sockaddr_in server_addrv4; struct sockaddr *server_addr; struct sockaddr *addrs[2]; socklen_t addrlens[2]; socklen_t addrlen; int eno; /* Create IPv6 socket */ eno = EINVAL; if (GNUNET_YES == plugin->enable_ipv6) { plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0); if (NULL == plugin->sockv6) { LOG(GNUNET_ERROR_TYPE_WARNING, "Disabling IPv6 since it is not supported on this system!\n"); plugin->enable_ipv6 = GNUNET_NO; } else { memset (&server_addrv6, '\0', sizeof(struct sockaddr_in6)); #if HAVE_SOCKADDR_IN_SIN_LEN server_addrv6.sin6_len = sizeof (struct sockaddr_in6); #endif server_addrv6.sin6_family = AF_INET6; if (NULL != bind_v6) server_addrv6.sin6_addr = bind_v6->sin6_addr; else server_addrv6.sin6_addr = in6addr_any; if (0 == plugin->port) /* autodetect */ server_addrv6.sin6_port = htons ( GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); else server_addrv6.sin6_port = htons (plugin->port); addrlen = sizeof(struct sockaddr_in6); server_addr = (struct sockaddr *) &server_addrv6; tries = 0; while (tries < 10) { LOG(GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 `%s'\n", GNUNET_a2s (server_addr, addrlen)); /* binding */ if (GNUNET_OK == GNUNET_NETWORK_socket_bind (plugin->sockv6, server_addr, addrlen)) break; eno = errno; if (0 != plugin->port) { tries = 10; /* fail */ break; /* bind failed on specific port */ } /* autodetect */ server_addrv6.sin6_port = htons ( GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); tries++; } if (tries >= 10) { GNUNET_NETWORK_socket_close (plugin->sockv6); plugin->enable_ipv6 = GNUNET_NO; plugin->sockv6 = NULL; } if (plugin->sockv6 != NULL ) { LOG(GNUNET_ERROR_TYPE_DEBUG, "IPv6 socket created on port %s\n", GNUNET_a2s (server_addr, addrlen)); addrs[sockets_created] = (struct sockaddr *) &server_addrv6; addrlens[sockets_created] = sizeof(struct sockaddr_in6); sockets_created++; } else { LOG(GNUNET_ERROR_TYPE_ERROR, "Failed to bind UDP socket to %s: %s\n", GNUNET_a2s (server_addr, addrlen), STRERROR (eno)); } } } /* Create IPv4 socket */ eno = EINVAL; plugin->sockv4 = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0); if (NULL == plugin->sockv4) { GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "socket"); LOG(GNUNET_ERROR_TYPE_WARNING, "Disabling IPv4 since it is not supported on this system!\n"); plugin->enable_ipv4 = GNUNET_NO; } else { memset (&server_addrv4, '\0', sizeof(struct sockaddr_in)); #if HAVE_SOCKADDR_IN_SIN_LEN server_addrv4.sin_len = sizeof (struct sockaddr_in); #endif server_addrv4.sin_family = AF_INET; if (NULL != bind_v4) server_addrv4.sin_addr = bind_v4->sin_addr; else server_addrv4.sin_addr.s_addr = INADDR_ANY; if (0 == plugin->port) /* autodetect */ server_addrv4.sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); else server_addrv4.sin_port = htons (plugin->port); addrlen = sizeof(struct sockaddr_in); server_addr = (struct sockaddr *) &server_addrv4; tries = 0; while (tries < 10) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 `%s'\n", GNUNET_a2s (server_addr, addrlen)); /* binding */ if (GNUNET_OK == GNUNET_NETWORK_socket_bind (plugin->sockv4, server_addr, addrlen)) break; eno = errno; if (0 != plugin->port) { tries = 10; /* fail */ break; /* bind failed on specific port */ } /* autodetect */ server_addrv4.sin_port = htons ( GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); tries++; } if (tries >= 10) { GNUNET_NETWORK_socket_close (plugin->sockv4); plugin->enable_ipv4 = GNUNET_NO; plugin->sockv4 = NULL; } if (NULL != plugin->sockv4) { LOG(GNUNET_ERROR_TYPE_DEBUG, "IPv4 socket created on port %s\n", GNUNET_a2s (server_addr, addrlen)); addrs[sockets_created] = (struct sockaddr *) &server_addrv4; addrlens[sockets_created] = sizeof(struct sockaddr_in); sockets_created++; } else { LOG(GNUNET_ERROR_TYPE_ERROR, "Failed to bind UDP socket to %s: %s\n", GNUNET_a2s (server_addr, addrlen), STRERROR (eno)); } } if (0 == sockets_created) { LOG(GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n")); return 0; /* No sockets created, return */ } /* Create file descriptors */ if (plugin->enable_ipv4 == GNUNET_YES) { plugin->rs_v4 = GNUNET_NETWORK_fdset_create (); plugin->ws_v4 = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_zero (plugin->rs_v4); GNUNET_NETWORK_fdset_zero (plugin->ws_v4); if (NULL != plugin->sockv4) { GNUNET_NETWORK_fdset_set (plugin->rs_v4, plugin->sockv4); GNUNET_NETWORK_fdset_set (plugin->ws_v4, plugin->sockv4); } } if (plugin->enable_ipv6 == GNUNET_YES) { plugin->rs_v6 = GNUNET_NETWORK_fdset_create (); plugin->ws_v6 = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_zero (plugin->rs_v6); GNUNET_NETWORK_fdset_zero (plugin->ws_v6); if (NULL != plugin->sockv6) { GNUNET_NETWORK_fdset_set (plugin->rs_v6, plugin->sockv6); GNUNET_NETWORK_fdset_set (plugin->ws_v6, plugin->sockv6); } } schedule_select (plugin); plugin->nat = GNUNET_NAT_register (plugin->env->cfg, GNUNET_NO, plugin->port, sockets_created, (const struct sockaddr **) addrs, addrlens, &udp_nat_port_map_callback, NULL, plugin); return sockets_created; } /** * The exported method. Makes the core api available via a global and * returns the udp transport API. * * @param cls our `struct GNUNET_TRANSPORT_PluginEnvironment` * @return our `struct GNUNET_TRANSPORT_PluginFunctions` */ void * libgnunet_plugin_transport_udp_init (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *p; unsigned long long port; unsigned long long aport; unsigned long long udp_max_bps; unsigned long long enable_v6; unsigned long long enable_broadcasting; unsigned long long enable_broadcasting_recv; char *bind4_address; char *bind6_address; char *fancy_interval; struct GNUNET_TIME_Relative interval; struct sockaddr_in server_addrv4; struct sockaddr_in6 server_addrv6; int res; int have_bind4; int have_bind6; if (NULL == env->receive) { /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully initialze the plugin or the API */ api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = NULL; api->address_pretty_printer = &udp_plugin_address_pretty_printer; api->address_to_string = &udp_address_to_string; api->string_to_address = &udp_string_to_address; return api; } /* Get port number: port == 0 : autodetect a port, * > 0 : use this port, not given : 2086 default */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT", &port)) port = 2086; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "ADVERTISED_PORT", &aport)) aport = port; if (port > 65535) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Given `%s' option is out of range: %llu > %u\n"), "PORT", port, 65535); return NULL; } /* Protocols */ if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "nat", "DISABLEV6")) enable_v6 = GNUNET_NO; else enable_v6 = GNUNET_YES; /* Addresses */ have_bind4 = GNUNET_NO; memset (&server_addrv4, 0, sizeof(server_addrv4)); if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp", "BINDTO", &bind4_address)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding udp plugin to specific address: `%s'\n", bind4_address); if (1 != inet_pton (AF_INET, bind4_address, &server_addrv4.sin_addr)) { GNUNET_free (bind4_address); return NULL; } have_bind4 = GNUNET_YES; } GNUNET_free_non_null(bind4_address); have_bind6 = GNUNET_NO; memset (&server_addrv6, 0, sizeof(server_addrv6)); if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp", "BINDTO6", &bind6_address)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding udp plugin to specific address: `%s'\n", bind6_address); if (1 != inet_pton (AF_INET6, bind6_address, &server_addrv6.sin6_addr)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid IPv6 address: `%s'\n"), bind6_address); GNUNET_free (bind6_address); return NULL; } have_bind6 = GNUNET_YES; } GNUNET_free_non_null (bind6_address); /* Initialize my flags */ myoptions = 0; /* Enable neighbour discovery */ enable_broadcasting = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp", "BROADCAST"); if (enable_broadcasting == GNUNET_SYSERR) enable_broadcasting = GNUNET_NO; enable_broadcasting_recv = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp", "BROADCAST_RECEIVE"); if (enable_broadcasting_recv == GNUNET_SYSERR) enable_broadcasting_recv = GNUNET_YES; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp", "BROADCAST_INTERVAL", &fancy_interval)) { interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10); } else { if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_time_to_relative (fancy_interval, &interval)) { interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); } GNUNET_free(fancy_interval); } /* Maximum datarate */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "MAX_BPS", &udp_max_bps)) { udp_max_bps = 1024 * 1024 * 50; /* 50 MB/s == infinity for practical purposes */ } p = GNUNET_new (struct Plugin); p->port = port; p->aport = aport; p->broadcast_interval = interval; p->enable_ipv6 = enable_v6; p->enable_ipv4 = GNUNET_YES; /* default */ p->enable_broadcasting = enable_broadcasting; p->enable_broadcasting_receiving = enable_broadcasting_recv; p->env = env; p->sessions = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); p->defrag_ctxs = GNUNET_CONTAINER_heap_create ( GNUNET_CONTAINER_HEAP_ORDER_MIN); p->mst = GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, p); GNUNET_BANDWIDTH_tracker_init (&p->tracker, NULL, NULL, GNUNET_BANDWIDTH_value_init ((uint32_t) udp_max_bps), 30); plugin = p; LOG(GNUNET_ERROR_TYPE_DEBUG, "Setting up sockets\n"); res = setup_sockets (p, (GNUNET_YES == have_bind6) ? &server_addrv6 : NULL, (GNUNET_YES == have_bind4) ? &server_addrv4 : NULL); if ((res == 0) || ((p->sockv4 == NULL )&& (p->sockv6 == NULL))) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to create network sockets, plugin failed\n")); GNUNET_CONTAINER_multipeermap_destroy (p->sessions); GNUNET_CONTAINER_heap_destroy (p->defrag_ctxs); GNUNET_SERVER_mst_destroy (p->mst); GNUNET_free (p); return NULL; } /* Setup broadcasting and receiving beacons */ setup_broadcast (p, &server_addrv6, &server_addrv4); api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = p; api->send = NULL; api->disconnect_session = &udp_disconnect_session; api->query_keepalive_factor = &udp_query_keepalive_factor; api->disconnect_peer = &udp_disconnect; api->address_pretty_printer = &udp_plugin_address_pretty_printer; api->address_to_string = &udp_address_to_string; api->string_to_address = &udp_string_to_address; api->check_address = &udp_plugin_check_address; api->get_session = &udp_plugin_get_session; api->send = &udp_plugin_send; api->get_network = &udp_get_network; api->update_session_timeout = &udp_plugin_update_session_timeout; return api; } /** * Function called on each entry in the defragmentation heap to * clean it up. * * @param cls NULL * @param node node in the heap (to be removed) * @param element a `struct DefragContext` to be cleaned up * @param cost unused * @return #GNUNET_YES */ static int heap_cleanup_iterator (void *cls, struct GNUNET_CONTAINER_HeapNode *node, void *element, GNUNET_CONTAINER_HeapCostType cost) { struct DefragContext *d_ctx = element; GNUNET_CONTAINER_heap_remove_node (node); GNUNET_DEFRAGMENT_context_destroy (d_ctx->defrag); GNUNET_free (d_ctx); return GNUNET_YES; } /** * The exported method. Makes the core api available via a global and * returns the udp transport API. * * @param cls our `struct GNUNET_TRANSPORT_PluginEnvironment` * @return NULL */ void * libgnunet_plugin_transport_udp_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; struct PrettyPrinterContext *cur; struct PrettyPrinterContext *next; struct UDP_MessageWrapper *udpw; if (NULL == plugin) { GNUNET_free(api); return NULL; } stop_broadcast (plugin); if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (plugin->select_task); plugin->select_task = GNUNET_SCHEDULER_NO_TASK; } if (plugin->select_task_v6 != GNUNET_SCHEDULER_NO_TASK ) { GNUNET_SCHEDULER_cancel (plugin->select_task_v6); plugin->select_task_v6 = GNUNET_SCHEDULER_NO_TASK; } /* Closing sockets */ if (GNUNET_YES == plugin->enable_ipv4) { if (NULL != plugin->sockv4) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv4)); plugin->sockv4 = NULL; } GNUNET_NETWORK_fdset_destroy (plugin->rs_v4); GNUNET_NETWORK_fdset_destroy (plugin->ws_v4); } if (GNUNET_YES == plugin->enable_ipv6) { if (NULL != plugin->sockv6) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->sockv6)); plugin->sockv6 = NULL; GNUNET_NETWORK_fdset_destroy (plugin->rs_v6); GNUNET_NETWORK_fdset_destroy (plugin->ws_v6); } } if (NULL != plugin->nat) { GNUNET_NAT_unregister (plugin->nat); plugin->nat = NULL; } if (NULL != plugin->defrag_ctxs) { GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs, &heap_cleanup_iterator, NULL); GNUNET_CONTAINER_heap_destroy (plugin->defrag_ctxs); plugin->defrag_ctxs = NULL; } if (NULL != plugin->mst) { GNUNET_SERVER_mst_destroy (plugin->mst); plugin->mst = NULL; } /* Clean up leftover messages */ udpw = plugin->ipv4_queue_head; while (NULL != udpw) { struct UDP_MessageWrapper *tmp = udpw->next; dequeue (plugin, udpw); call_continuation (udpw, GNUNET_SYSERR); GNUNET_free(udpw); udpw = tmp; } udpw = plugin->ipv6_queue_head; while (NULL != udpw) { struct UDP_MessageWrapper *tmp = udpw->next; dequeue (plugin, udpw); call_continuation (udpw, GNUNET_SYSERR); GNUNET_free(udpw); udpw = tmp; } /* Clean up sessions */ LOG(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up sessions\n"); GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, &disconnect_and_free_it, plugin); GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions); next = ppc_dll_head; for (cur = next; NULL != cur; cur = next) { next = cur->next; GNUNET_CONTAINER_DLL_remove(ppc_dll_head, ppc_dll_tail, cur); GNUNET_RESOLVER_request_cancel (cur->resolver_handle); GNUNET_SCHEDULER_cancel (cur->timeout_task); GNUNET_free(cur); GNUNET_break(0); } GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_transport_udp.c */ gnunet-0.10.1/src/transport/test_quota_compliance_udp_peer1.conf0000644000175000017500000000122212225230043022020 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer1/ [transport-udp] PORT = 4368 MAX_BPS = 50000000 [arm] PORT = 4087 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_arm_peer1.sock [statistics] PORT = 4088 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_statistics_peer1.sock [resolver] PORT = 4089 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_resolver_peer1.sock [peerinfo] PORT = 4090 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_peerinfo_peer1.sock [transport] PORT = 4091 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_udp_transport_peer1.sock gnunet-0.10.1/src/transport/test_transport_api_monitoring_validation.c0000644000175000017500000003354112274162761023422 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api_monitoring_validation.c * @brief base test case for transport validation monitorung * * This test case connects two peers and monitors validation monitoring * callbacks */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) #define TEST_MESSAGE_SIZE 2600 #define TEST_MESSAGE_TYPE 12345 static char *test_source; static char *test_plugin; static char *test_name; static int ok; static int s_started; static int s_connected; static int s_sending; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static struct GNUNET_TRANSPORT_ValidationMonitoringContext *vmc_p1; static struct GNUNET_TRANSPORT_ValidationMonitoringContext *vmc_p2; static int p1_c = GNUNET_NO; static int p2_c = GNUNET_NO; static int p1_c_notify = GNUNET_NO; static int p2_c_notify = GNUNET_NO; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); p1 = NULL; GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); p2 = NULL; if (NULL != vmc_p1) { GNUNET_TRANSPORT_monitor_validation_entries_cancel (vmc_p1); vmc_p1 = NULL; } if (NULL != vmc_p2) { GNUNET_TRANSPORT_monitor_validation_entries_cancel (vmc_p2); vmc_p2 = NULL; } ok = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Fail! Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); if (s_started == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started \n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started \n")); if (s_connected == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not connected\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were connected\n")); if (s_sending == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were ready to send data\n")); th = NULL; if (NULL != vmc_p1) { GNUNET_TRANSPORT_monitor_validation_entries_cancel (vmc_p1); vmc_p1 = NULL; } if (NULL != vmc_p2) { GNUNET_TRANSPORT_monitor_validation_entries_cancel (vmc_p2); vmc_p2 = NULL; } if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 1 was not started\n")); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 2 was not started\n")); ok = GNUNET_SYSERR; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); if (0 >= p1_c) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer 1 did not receive validation callbacks for peer 2\n"); } if (0 >= p2_c) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer 2 did not receive validation callbacks for peer 1\n"); } if ((0 >= p1_c) || (0 >= p2_c)) { if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); } else end (); } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= TEST_MESSAGE_SIZE); if (buf != NULL) { memset (buf, '\0', TEST_MESSAGE_SIZE); hdr = buf; hdr->size = htons (TEST_MESSAGE_SIZE); hdr->type = htons (TEST_MESSAGE_TYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return TEST_MESSAGE_SIZE; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); s_sending = GNUNET_YES; th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void done () { if ((GNUNET_YES == p1_c) && (GNUNET_YES == p2_c) && p1_c_notify && p2_c_notify) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Both peers state to be connected\n"); ok = 0; end(); } } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) { p1_c_notify = GNUNET_YES; t = p1; } if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) { p2_c_notify = GNUNET_YES; t = p2; } GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); if (p1_c_notify && p2_c_notify) GNUNET_SCHEDULER_add_now(&done, NULL); GNUNET_free (ps); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); s_connected = GNUNET_YES; send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; else s_started = GNUNET_YES; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void monitor1_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state) { if ((NULL == peer) || (NULL == p1)) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor 1: %s %s %s\n", GNUNET_i2s (peer), GNUNET_TRANSPORT_vs2s(state), GNUNET_STRINGS_absolute_time_to_string(valid_until)); if (0 == memcmp (peer, &p2->id, sizeof (p2->id))) p1_c++; } static void monitor2_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute last_validation, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute next_validation, enum GNUNET_TRANSPORT_ValidationState state) { if ((NULL == peer) || (NULL == p2)) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor 2: %s %s %s\n", GNUNET_i2s (peer), GNUNET_TRANSPORT_vs2s(state), GNUNET_STRINGS_absolute_time_to_string(valid_until)); if (0 == memcmp (peer, &p1->id, sizeof (p1->id))) p2_c++; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); s_started = GNUNET_NO; s_connected = GNUNET_NO; s_sending = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); vmc_p1 = GNUNET_TRANSPORT_monitor_validation_entries (p1->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor1_cb, NULL); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); vmc_p2 = GNUNET_TRANSPORT_monitor_validation_entries (p2->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor2_cb, NULL); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; ok = 1; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); GNUNET_log_setup (test_name, "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); if (0 != ret) return ret; else return ok; } /* end of test_transport_api_monitoring_validation.c */ gnunet-0.10.1/src/transport/test_transport_blacklisting_cfg_peer1.conf0000644000175000017500000000114712225230043023234 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PLUGINS = tcp gnunet-0.10.1/src/transport/test_transport_api_unreliability_constant_udp_peer2.conf0000644000175000017500000000112312225230043026230 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-udp-p2/ [transport-udp] PORT = 12050 MAX_BPS = 1073741824 [arm] PORT = 12055 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12054 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12053 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12052 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12051 PLUGINS = udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_quota_compliance_http_peer1.conf0000644000175000017500000000121012225230043022204 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer1 [transport-http_client] [arm] PORT = 4015 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_arm_peer1.sock [statistics] PORT = 4014 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_statistics_peer1.sock [resolver] PORT = 4013 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_resolver_peer1.sock [peerinfo] PORT = 4012 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_peerinfo_peer1.sock [transport] PORT = 4011 PLUGINS = http_client UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_transport_peer1.sock gnunet-0.10.1/src/transport/test_quota_compliance_tcp_peer2.conf0000644000175000017500000000114712225230043022025 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/transport_api_blacklist.c0000644000175000017500000001727212255010511017717 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/transport_api_blacklist.c * @brief library to access the blacklisting functions of the transport service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_arm_service.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_transport_service.h" #include "transport.h" /** * Handle for blacklisting requests. */ struct GNUNET_TRANSPORT_Blacklist { /** * Connection to transport service. */ struct GNUNET_CLIENT_Connection *client; /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Pending handle for the current request. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Function to call for determining if a peer is allowed * to communicate with us. */ GNUNET_TRANSPORT_BlacklistCallback cb; /** * Closure for 'cb'. */ void *cb_cls; /** * Peer currently under consideration. */ struct GNUNET_PeerIdentity peer; }; /** * Establish blacklist connection to transport service. * * @param br overall handle */ static void reconnect (struct GNUNET_TRANSPORT_Blacklist *br); /** * Send our reply to a blacklisting request. * * @param br our overall context */ static void reply (struct GNUNET_TRANSPORT_Blacklist *br); /** * Handle blacklist queries. * * @param cls our overall handle * @param msg query */ static void query_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_TRANSPORT_Blacklist *br = cls; const struct BlacklistMessage *bm; GNUNET_assert (br != NULL); if ((NULL == msg) || (ntohs (msg->size) != sizeof (struct BlacklistMessage)) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY)) { reconnect (br); return; } bm = (const struct BlacklistMessage *) msg; GNUNET_break (0 == ntohl (bm->is_allowed)); br->peer = bm->peer; reply (br); } /** * Receive blacklist queries from transport service. * * @param br overall handle */ static void receive (struct GNUNET_TRANSPORT_Blacklist *br) { GNUNET_CLIENT_receive (br->client, &query_handler, br, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Transmit the blacklist initialization request to the service. * * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*) * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_blacklist_init (void *cls, size_t size, void *buf) { struct GNUNET_TRANSPORT_Blacklist *br = cls; struct GNUNET_MessageHeader req; br->th = NULL; if (buf == NULL) { reconnect (br); return 0; } req.size = htons (sizeof (struct GNUNET_MessageHeader)); req.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT); memcpy (buf, &req, sizeof (req)); receive (br); return sizeof (req); } /** * Establish blacklist connection to transport service. * * @param br overall handle */ static void reconnect (struct GNUNET_TRANSPORT_Blacklist *br) { if (br->client != NULL) GNUNET_CLIENT_disconnect (br->client); br->client = GNUNET_CLIENT_connect ("transport", br->cfg); GNUNET_assert (br->client != NULL); br->th = GNUNET_CLIENT_notify_transmit_ready (br->client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_blacklist_init, br); } /** * Transmit the blacklist response to the service. * * @param cls closure (struct GNUNET_TRANSPORT_Blacklist*) * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_blacklist_reply (void *cls, size_t size, void *buf) { struct GNUNET_TRANSPORT_Blacklist *br = cls; struct BlacklistMessage req; br->th = NULL; if (buf == NULL) { reconnect (br); return 0; } req.header.size = htons (sizeof (req)); req.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY); req.is_allowed = htonl (br->cb (br->cb_cls, &br->peer)); req.peer = br->peer; memcpy (buf, &req, sizeof (req)); br->th = NULL; receive (br); return sizeof (req); } /** * Send our reply to a blacklisting request. * * @param br our overall context */ static void reply (struct GNUNET_TRANSPORT_Blacklist *br) { GNUNET_assert (br->th == NULL); br->th = GNUNET_CLIENT_notify_transmit_ready (br->client, sizeof (struct BlacklistMessage), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_blacklist_reply, br); if (br->th == NULL) { reconnect (br); return; } } /** * Install a blacklist callback. The service will be queried for all * existing connections as well as any fresh connections to check if * they are permitted. If the blacklisting callback is unregistered, * all hosts that were denied in the past will automatically be * whitelisted again. Cancelling the blacklist handle is also the * only way to re-enable connections from peers that were previously * blacklisted. * * @param cfg configuration to use * @param cb callback to invoke to check if connections are allowed * @param cb_cls closure for cb * @return NULL on error, otherwise handle for cancellation */ struct GNUNET_TRANSPORT_Blacklist * GNUNET_TRANSPORT_blacklist (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_TRANSPORT_BlacklistCallback cb, void *cb_cls) { struct GNUNET_CLIENT_Connection *client; struct GNUNET_TRANSPORT_Blacklist *ret; client = GNUNET_CLIENT_connect ("transport", cfg); if (NULL == client) return NULL; ret = GNUNET_new (struct GNUNET_TRANSPORT_Blacklist); ret->client = client; ret->cfg = cfg; ret->cb = cb; ret->cb_cls = cb_cls; GNUNET_assert (ret->th == NULL); ret->th = GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_blacklist_init, ret); return ret; } /** * Abort the blacklist. Note that this function is the only way for * removing a peer from the blacklist. * * @param br handle of the request that is to be cancelled */ void GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br) { if (br->th != NULL) { GNUNET_CLIENT_notify_transmit_ready_cancel (br->th); br->th = NULL; } GNUNET_CLIENT_disconnect (br->client); GNUNET_free (br); } /* end of transport_api_blacklist.c */ gnunet-0.10.1/src/transport/test_transport_api_disconnect_tcp_peer2.conf0000644000175000017500000000114712225230043023600 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_multi_peer1.conf0000644000175000017500000000135112225230043021727 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-multi-p1/ [transport-tcp] PORT = 12140 TIMEOUT = 5 s [transport-udp] PORT = 12141 [transport-http] PORT = 12142 [transport-https] PORT = 12143 [arm] PORT = 12149 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12148 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12147 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12146 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12145 PLUGINS = tcp udp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [transport-unix] PORT = 12144 gnunet-0.10.1/src/transport/plugin_transport_udp.h0000644000175000017500000001430212307322113017262 00000000000000/* This file is part of GNUnet (C) 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_udp.h * @brief Implementation of the UDP transport protocol * @author Christian Grothoff * @author Nathan Evans * @author Matthias Wachs */ #ifndef PLUGIN_TRANSPORT_UDP_H #define PLUGIN_TRANSPORT_UDP_H #include "platform.h" #include "gnunet_hello_lib.h" #include "gnunet_util_lib.h" #include "gnunet_fragmentation_lib.h" #include "gnunet_nat_lib.h" #include "gnunet_protocols.h" #include "gnunet_resolver_service.h" #include "gnunet_signatures.h" #include "gnunet_constants.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "transport.h" #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__) #define PLUGIN_NAME "udp" #define DEBUG_UDP GNUNET_NO #define DEBUG_UDP_BROADCASTING GNUNET_NO /** * MTU for fragmentation subsystem. Should be conservative since * all communicating peers MUST work with this MTU. */ #define UDP_MTU 1400 GNUNET_NETWORK_STRUCT_BEGIN /** * Network format for IPv4 addresses. */ struct IPv4UdpAddress { /** * Optional options and flags for this address */ uint32_t options GNUNET_PACKED; /** * IPv4 address, in network byte order. */ uint32_t ipv4_addr GNUNET_PACKED; /** * Port number, in network byte order. */ uint16_t u4_port GNUNET_PACKED; }; /** * Network format for IPv6 addresses. */ struct IPv6UdpAddress { /** * Optional options and flags for this address */ uint32_t options GNUNET_PACKED; /** * IPv6 address. */ struct in6_addr ipv6_addr GNUNET_PACKED; /** * Port number, in network byte order. */ uint16_t u6_port GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /** * UDP Message-Packet header (after defragmentation). */ struct UDPMessage { /** * Message header. */ struct GNUNET_MessageHeader header; /** * Always zero for now. */ uint32_t reserved; /** * What is the identity of the sender */ struct GNUNET_PeerIdentity sender; }; struct UDP_MessageWrapper; /** * Encapsulation of all of the state of the plugin. */ struct Plugin { /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * Session of peers with whom we are currently connected, * map of peer identity to 'struct PeerSession'. */ struct GNUNET_CONTAINER_MultiPeerMap *sessions; /** * Heap with all of our defragmentation activities. */ struct GNUNET_CONTAINER_Heap *defrag_ctxs; /** * ID of select task */ GNUNET_SCHEDULER_TaskIdentifier select_task; GNUNET_SCHEDULER_TaskIdentifier select_task_v6; /** * Tokenizer for inbound messages. */ struct GNUNET_SERVER_MessageStreamTokenizer *mst; /** * Bandwidth tracker to limit global UDP traffic. */ struct GNUNET_BANDWIDTH_Tracker tracker; /** * Address we were told to bind to exclusively (IPv4). */ char *bind4_address; /** * Address we were told to bind to exclusively (IPv6). */ char *bind6_address; /** * Bytes currently in buffer */ int64_t bytes_in_buffer; /** * Handle to NAT traversal support. */ struct GNUNET_NAT_Handle *nat; /** * FD Read set */ struct GNUNET_NETWORK_FDSet *rs_v4; /** * FD Write set */ struct GNUNET_NETWORK_FDSet *ws_v4; /** * The read socket for IPv4 */ struct GNUNET_NETWORK_Handle *sockv4; /** * FD Read set */ struct GNUNET_NETWORK_FDSet *rs_v6; /** * FD Write set */ struct GNUNET_NETWORK_FDSet *ws_v6; /** * The read socket for IPv6 */ struct GNUNET_NETWORK_Handle *sockv6; /** * Beacon broadcasting * ------------------- */ /** * Broadcast interval */ struct GNUNET_TIME_Relative broadcast_interval; /** * Tokenizer for inbound messages. */ struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_ipv6_mst; struct GNUNET_SERVER_MessageStreamTokenizer *broadcast_ipv4_mst; /** * IPv6 multicast address */ struct sockaddr_in6 ipv6_multicast_address; /** * DLL of broadcast addresses */ struct BroadcastAddress *broadcast_tail; struct BroadcastAddress *broadcast_head; /** * Is IPv6 enabled: GNUNET_YES or GNUNET_NO */ int enable_ipv6; /** * Is IPv4 enabled: GNUNET_YES or GNUNET_NO */ int enable_ipv4; /** * Is broadcasting enabled: GNUNET_YES or GNUNET_NO */ int enable_broadcasting; /** * Is receiving broadcasts enabled: GNUNET_YES or GNUNET_NO */ int enable_broadcasting_receiving; /** * Port we broadcasting on. */ uint16_t broadcast_port; /** * Port we listen on. */ uint16_t port; /** * Port we advertise on. */ uint16_t aport; struct UDP_MessageWrapper *ipv4_queue_head; struct UDP_MessageWrapper *ipv4_queue_tail; struct UDP_MessageWrapper *ipv6_queue_head; struct UDP_MessageWrapper *ipv6_queue_tail; }; const char * udp_address_to_string (void *cls, const void *addr, size_t addrlen); void udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, const struct sockaddr *addr, size_t addrlen); void setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4); void stop_broadcast (struct Plugin *plugin); /*#ifndef PLUGIN_TRANSPORT_UDP_H*/ #endif /* end of plugin_transport_udp.h */ gnunet-0.10.1/src/transport/test_quota_compliance_http_peer2.conf0000644000175000017500000000126612225230043022220 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer2 [transport-http_server] PORT = 3010 USE_IPv6 = NO BINDTO = 127.0.0.1 [arm] PORT = 3015 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_arm_peer2.sock [statistics] PORT = 3014 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_statistics_peer2.sock [resolver] PORT = 3013 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_resolver_peer2.sock [peerinfo] PORT = 3012 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_peerinfo_peer2.sock [transport] PORT = 3011 PLUGINS = http_server UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_http_transport_peer2.sock gnunet-0.10.1/src/transport/gnunet-service-transport_plugins.h0000644000175000017500000000722412316473377021561 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_plugins.h * @brief plugin management API * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_TRANSPORT_PLUGINS_H #define GNUNET_SERVICE_TRANSPORT_PLUGINS_H #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" /** * Load and initialize all plugins. The respective functions will be * invoked by the plugins when the respective events happen. The * closure will be set to a 'const char*' containing the name of the * plugin that caused the call. * * @param recv_cb function to call when data is received * @param register_quota_cb function to call to register a quota callback * @param unregister_quota_cb function to call to unregister a quota callback * @param address_cb function to call when our public addresses changed * @param session_start_cb function to call when a session was created * @param session_end_cb function to call when a session was terminated * @param address_type_cb function to call when a address type is requested * @param metric_update_cb function to call when address metrics change */ void GST_plugins_load (GNUNET_TRANSPORT_PluginReceiveCallback recv_cb, GNUNET_TRANSPORT_RegisterQuotaNotification register_quota_cb, GNUNET_TRANSPORT_UnregisterQuotaNotification unregister_quota_cb, GNUNET_TRANSPORT_AddressNotification address_cb, GNUNET_TRANSPORT_SessionStart session_start_cb, GNUNET_TRANSPORT_SessionEnd session_end_cb, GNUNET_TRANSPORT_AddressToType address_type_cb, GNUNET_TRANSPORT_UpdateAddressMetrics metric_update_cb); /** * Unload all plugins */ void GST_plugins_unload (void); /** * Obtain the plugin API based on a plugin name. * * @param name name of the plugin * @return the plugin's API, NULL if the plugin is not loaded */ struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_find (const char *name); /** * Obtain the plugin API based on a the stripped plugin name after the underscore. * * Example: GST_plugins_printer_find (http_client) will return all plugins * starting with the prefix "http": * http_client or server if loaded * * @param name name of the plugin * @return the plugin's API, NULL if the plugin is not loaded */ struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_printer_find (const char *name); /** * Convert a given address to a human-readable format. Note that the * return value will be overwritten on the next call to this function. * * @param address address to convert * @return statically allocated (!) human-readable address */ const char * GST_plugins_a2s (const struct GNUNET_HELLO_Address *address); #endif /* end of file gnunet-service-transport_plugins.h */ gnunet-0.10.1/src/transport/template_cfg_peer2.conf0000644000175000017500000000165112225230043017227 00000000000000@INLINE@ test_transport_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [nat] RETURN_LOCAL_ADDRESSES = YES DISABLEV6 = NO [transport-tcp] PORT = 12100 TIMEOUT = 5 s [transport-udp] BROADCAST = NO [transport-unix] PORT = 12017 [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock USE_INCLUDED_HELLOS = NO [transport] #PREFIX = valgrind --leak-check=full PORT = 12010 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [ats] WAN_QUOTA_IN = unlimited WAN_QUOTA_OUT = unlimited PORT = 12016 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-ats.sock [hostlist] SERVERS = dummygnunet-0.10.1/src/transport/test_transport_api_manipulation_cfg_peer1.conf0000644000175000017500000000124012225230043024111 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p1/ [transport-tcp] PORT = 12000 TIMEOUT = 5 s [arm] PORT = 12005 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12004 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12003 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12002 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12001 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock PLUGINS = tcp MANIPULATE_DELAY_IN = 100 ms MANIPULATE_DELAY_OUT = 100 msgnunet-0.10.1/src/transport/test_quota_compliance_tcp_peer1.conf0000644000175000017500000000123512225230043022022 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/quota-tcp-p1/ [transport-tcp] PORT = 4094 [transport-udp] PORT = 4094 [arm] PORT = 4087 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_arm_peer1.sock [statistics] PORT = 4088 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_statistics_peer1.sock [resolver] PORT = 4089 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_resolver_peer1.sock [peerinfo] PORT = 4090 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_peerinfo_peer1.sock [transport] PORT = 4091 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_tcp_transport_peer1.sock gnunet-0.10.1/src/transport/test_quota_compliance_unix_asymmetric_peer1.conf0000644000175000017500000000120612225230043024452 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer1/ [arm] PORT = 4087 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_arm_peer1.sock [statistics] PORT = 4088 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_statistics_peer1.sock [resolver] PORT = 4089 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_resolver_peer1.sock [peerinfo] PORT = 4090 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_peerinfo_peer1.sock [transport] PORT = 4091 PLUGINS = unix UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_unix_transport_peer1.sock [transport-unix] PORT = 4092 gnunet-0.10.1/src/transport/transport_api.c0000644000175000017500000014766312316473377015724 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/transport_api.c * @brief library to access the low-level P2P IO service * @author Christian Grothoff * * TODO: * - test test test */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_arm_service.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_transport_service.h" #include "transport.h" #define LOG(kind,...) GNUNET_log_from (kind, "transport-api",__VA_ARGS__) /** * How large to start with for the hashmap of neighbours. */ #define STARTING_NEIGHBOURS_SIZE 16 /** * Handle for a message that should be transmitted to the service. * Used for both control messages and normal messages. */ struct GNUNET_TRANSPORT_TransmitHandle { /** * We keep all requests in a DLL. */ struct GNUNET_TRANSPORT_TransmitHandle *next; /** * We keep all requests in a DLL. */ struct GNUNET_TRANSPORT_TransmitHandle *prev; /** * Neighbour for this handle, NULL for control messages. */ struct Neighbour *neighbour; /** * Function to call when notify_size bytes are available * for transmission. */ GNUNET_TRANSPORT_TransmitReadyNotify notify; /** * Closure for notify. */ void *notify_cls; /** * Timeout for this request, 0 for control messages. */ struct GNUNET_TIME_Absolute timeout; /** * Task to trigger request timeout if the request is stalled due to * congestion. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * How many bytes is our notify callback waiting for? */ size_t notify_size; }; /** * Entry in hash table of all of our current neighbours. */ struct Neighbour { /** * Overall transport handle. */ struct GNUNET_TRANSPORT_Handle *h; /** * Active transmit handle or NULL. */ struct GNUNET_TRANSPORT_TransmitHandle *th; /** * Identity of this neighbour. */ struct GNUNET_PeerIdentity id; /** * Outbound bandwidh tracker. */ struct GNUNET_BANDWIDTH_Tracker out_tracker; /** * Entry in our readyness heap (which is sorted by 'next_ready' * value). NULL if there is no pending transmission request for * this neighbour or if we're waiting for 'is_ready' to become * true AFTER the 'out_tracker' suggested that this peer's quota * has been satisfied (so once 'is_ready' goes to GNUNET_YES, * we should immediately go back into the heap). */ struct GNUNET_CONTAINER_HeapNode *hn; /** * Is this peer currently ready to receive a message? */ int is_ready; /** * Sending consumed more bytes on wire than payload was announced * This overhead is added to the delay of next sending operation */ size_t traffic_overhead; }; /** * Linked list of functions to call whenever our HELLO is updated. */ struct GNUNET_TRANSPORT_GetHelloHandle { /** * This is a doubly linked list. */ struct GNUNET_TRANSPORT_GetHelloHandle *next; /** * This is a doubly linked list. */ struct GNUNET_TRANSPORT_GetHelloHandle *prev; /** * Transport handle. */ struct GNUNET_TRANSPORT_Handle *handle; /** * Callback to call once we got our HELLO. */ GNUNET_TRANSPORT_HelloUpdateCallback rec; /** * Task for calling the HelloUpdateCallback when we already have a HELLO */ GNUNET_SCHEDULER_TaskIdentifier notify_task; /** * Closure for @e rec. */ void *rec_cls; }; /** * Linked list for all try-connect requests */ struct GNUNET_TRANSPORT_TryConnectHandle { /** * For the DLL. */ struct GNUNET_TRANSPORT_TryConnectHandle *prev; /** * For the DLL. */ struct GNUNET_TRANSPORT_TryConnectHandle *next; struct GNUNET_PeerIdentity pid; struct GNUNET_TRANSPORT_Handle *th; struct GNUNET_TRANSPORT_TransmitHandle *tth; GNUNET_TRANSPORT_TryConnectCallback cb; int connect; /** * Closure for @e cb. */ void *cb_cls; }; /** * Linked list for all try-connect requests */ struct GNUNET_TRANSPORT_OfferHelloHandle { /** * For the DLL. */ struct GNUNET_TRANSPORT_OfferHelloHandle *prev; /** * For the DLL. */ struct GNUNET_TRANSPORT_OfferHelloHandle *next; struct GNUNET_TRANSPORT_Handle *th; struct GNUNET_TRANSPORT_TransmitHandle *tth; GNUNET_SCHEDULER_Task cont; /** * Closure for @e cont */ void *cls; struct GNUNET_MessageHeader *msg; }; /** * Handle for the transport service (includes all of the * state for the transport service). */ struct GNUNET_TRANSPORT_Handle { /** * Closure for the callbacks. */ void *cls; /** * Function to call for received data. */ GNUNET_TRANSPORT_ReceiveCallback rec; /** * function to call on connect events */ GNUNET_TRANSPORT_NotifyConnect nc_cb; /** * function to call on disconnect events */ GNUNET_TRANSPORT_NotifyDisconnect nd_cb; /** * function to call on excess bandwidth events */ GNUNET_TRANSPORT_NotifyExcessBandwidth neb_cb; /** * Head of DLL of control messages. */ struct GNUNET_TRANSPORT_TransmitHandle *control_head; /** * Tail of DLL of control messages. */ struct GNUNET_TRANSPORT_TransmitHandle *control_tail; /** * The current HELLO message for this peer. Updated * whenever transports change their addresses. */ struct GNUNET_HELLO_Message *my_hello; /** * My client connection to the transport service. */ struct GNUNET_CLIENT_Connection *client; /** * Handle to our registration with the client for notification. */ struct GNUNET_CLIENT_TransmitHandle *cth; /** * Linked list of pending requests for our HELLO. */ struct GNUNET_TRANSPORT_GetHelloHandle *hwl_head; /** * Linked list of pending requests for our HELLO. */ struct GNUNET_TRANSPORT_GetHelloHandle *hwl_tail; /** * Linked list of pending try connect requests head */ struct GNUNET_TRANSPORT_TryConnectHandle *tc_head; /** * Linked list of pending try connect requests tail */ struct GNUNET_TRANSPORT_TryConnectHandle *tc_tail; /** * Linked list of pending offer HELLO requests head */ struct GNUNET_TRANSPORT_OfferHelloHandle *oh_head; /** * Linked list of pending offer HELLO requests tail */ struct GNUNET_TRANSPORT_OfferHelloHandle *oh_tail; /** * My configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Hash map of the current connected neighbours of this peer. * Maps peer identities to 'struct Neighbour' entries. */ struct GNUNET_CONTAINER_MultiPeerMap *neighbours; /** * Heap sorting peers with pending messages by the timestamps that * specify when we could next send a message to the respective peer. * Excludes control messages (which can always go out immediately). * Maps time stamps to 'struct Neighbour' entries. */ struct GNUNET_CONTAINER_Heap *ready_heap; /** * Peer identity as assumed by this process, or all zeros. */ struct GNUNET_PeerIdentity self; /** * ID of the task trying to reconnect to the service. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * ID of the task trying to trigger transmission for a peer while * maintaining bandwidth quotas. In use if there are no control * messages and the smallest entry in the 'ready_heap' has a time * stamp in the future. */ GNUNET_SCHEDULER_TaskIdentifier quota_task; /** * Delay until we try to reconnect. */ struct GNUNET_TIME_Relative reconnect_delay; /** * Should we check that @e self matches what the service thinks? * (if #GNUNET_NO, then @e self is all zeros!). */ int check_self; /** * Reconnect in progress */ int reconnecting; }; /** * Schedule the task to send one message, either from the control * list or the peer message queues to the service. * * @param h transport service to schedule a transmission for */ static void schedule_transmission (struct GNUNET_TRANSPORT_Handle *h); /** * Function that will schedule the job that will try * to connect us again to the client. * * @param h transport service to reconnect */ static void disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h); /** * Get the neighbour list entry for the given peer * * @param h our context * @param peer peer to look up * @return NULL if no such peer entry exists */ static struct Neighbour * neighbour_find (struct GNUNET_TRANSPORT_Handle *h, const struct GNUNET_PeerIdentity *peer) { return GNUNET_CONTAINER_multipeermap_get (h->neighbours, peer); } /** * The outbound quota has changed in a way that may require * us to reset the timeout. Update the timeout. * * @param cls the `struct Neighbour` for which the timeout changed */ static void outbound_bw_tracker_update (void *cls) { struct Neighbour *n = cls; struct GNUNET_TIME_Relative delay; if (NULL == n->hn) return; delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, n->th->notify_size + n->traffic_overhead); LOG (GNUNET_ERROR_TYPE_DEBUG, "New outbound delay %llu us\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_NO)); GNUNET_CONTAINER_heap_update_cost (n->h->ready_heap, n->hn, delay.rel_value_us); schedule_transmission (n->h); } /** * Function called by the bandwidth tracker if we have excess * bandwidth. * * @param cls the `struct Neighbour` that has excess bandwidth */ static void notify_excess_cb (void *cls) { struct Neighbour *n = cls; struct GNUNET_TRANSPORT_Handle *h = n->h; if (NULL != h->neb_cb) h->neb_cb (h->cls, &n->id); } /** * Add neighbour to our list * * @return NULL if this API is currently disconnecting from the service */ static struct Neighbour * neighbour_add (struct GNUNET_TRANSPORT_Handle *h, const struct GNUNET_PeerIdentity *pid) { struct Neighbour *n; LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating entry for neighbour `%4s'.\n", GNUNET_i2s (pid)); n = GNUNET_new (struct Neighbour); n->id = *pid; n->h = h; n->is_ready = GNUNET_YES; n->traffic_overhead = 0; GNUNET_BANDWIDTH_tracker_init2 (&n->out_tracker, &outbound_bw_tracker_update, n, GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, MAX_BANDWIDTH_CARRY_S, ¬ify_excess_cb, n); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (h->neighbours, &n->id, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return n; } /** * Iterator over hash map entries, for deleting state of a neighbour. * * @param cls the `struct GNUNET_TRANSPORT_Handle *` * @param key peer identity * @param value value in the hash map, the neighbour entry to delete * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int neighbour_delete (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_TRANSPORT_Handle *handle = cls; struct Neighbour *n = value; if (NULL != handle->nd_cb) handle->nd_cb (handle->cls, &n->id); GNUNET_assert (NULL == n->th); GNUNET_assert (NULL == n->hn); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (handle->neighbours, key, n)); GNUNET_BANDWIDTH_tracker_notification_stop (&n->out_tracker); GNUNET_free (n); return GNUNET_YES; } /** * Function we use for handling incoming messages. * * @param cls closure, a `struct GNUNET_TRANSPORT_Handle *` * @param msg message received, NULL on timeout or fatal error */ static void demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_TRANSPORT_Handle *h = cls; const struct DisconnectInfoMessage *dim; const struct ConnectInfoMessage *cim; const struct InboundMessage *im; const struct GNUNET_MessageHeader *imm; const struct SendOkMessage *okm; const struct QuotaSetMessage *qm; struct GNUNET_TRANSPORT_GetHelloHandle *hwl; struct GNUNET_TRANSPORT_GetHelloHandle *next_hwl; struct Neighbour *n; struct GNUNET_PeerIdentity me; uint16_t size; uint32_t bytes_msg; uint32_t bytes_physical; GNUNET_assert (NULL != h->client); if (GNUNET_YES == h->reconnecting) { return; } if (NULL == msg) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Error receiving from transport service, disconnecting temporarily.\n"); h->reconnecting = GNUNET_YES; disconnect_and_schedule_reconnect (h); return; } GNUNET_CLIENT_receive (h->client, &demultiplexer, h, GNUNET_TIME_UNIT_FOREVER_REL); size = ntohs (msg->size); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_HELLO: if (GNUNET_OK != GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) msg, &me)) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving (my own) `%s' message, I am `%4s'.\n", "HELLO", GNUNET_i2s (&me)); GNUNET_free_non_null (h->my_hello); h->my_hello = NULL; if (size < sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); break; } h->my_hello = GNUNET_malloc (size); memcpy (h->my_hello, msg, size); hwl = h->hwl_head; while (NULL != hwl) { next_hwl = hwl->next; hwl->rec (hwl->rec_cls, (const struct GNUNET_MessageHeader *) h->my_hello); hwl = next_hwl; } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT: if (size < sizeof (struct ConnectInfoMessage)) { GNUNET_break (0); break; } cim = (const struct ConnectInfoMessage *) msg; if (size != sizeof (struct ConnectInfoMessage)) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message for `%4s'.\n", "CONNECT", GNUNET_i2s (&cim->id)); n = neighbour_find (h, &cim->id); if (NULL != n) { GNUNET_break (0); break; } n = neighbour_add (h, &cim->id); LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message for `%4s' with quota %u\n", "CONNECT", GNUNET_i2s (&cim->id), ntohl (cim->quota_out.value__)); GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker, cim->quota_out); if (h->nc_cb != NULL) h->nc_cb (h->cls, &n->id); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT: if (size != sizeof (struct DisconnectInfoMessage)) { GNUNET_break (0); break; } dim = (const struct DisconnectInfoMessage *) msg; GNUNET_break (ntohl (dim->reserved) == 0); LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message for `%4s'.\n", "DISCONNECT", GNUNET_i2s (&dim->peer)); n = neighbour_find (h, &dim->peer); if (NULL == n) { GNUNET_break (0); break; } neighbour_delete (h, &dim->peer, n); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK: if (size != sizeof (struct SendOkMessage)) { GNUNET_break (0); break; } okm = (const struct SendOkMessage *) msg; bytes_msg = ntohl (okm->bytes_msg); bytes_physical = ntohl (okm->bytes_physical); LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving SEND_OK message, transmission %s.\n", ntohl (okm->success) == GNUNET_OK ? "succeeded" : "failed"); n = neighbour_find (h, &okm->peer); if (NULL == n) break; if (bytes_physical >= bytes_msg) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Overhead for %u byte message: %u\n", bytes_msg, bytes_physical - bytes_msg); n->traffic_overhead += bytes_physical - bytes_msg; } GNUNET_break (GNUNET_NO == n->is_ready); n->is_ready = GNUNET_YES; if ((NULL != n->th) && (NULL == n->hn)) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->th->timeout_task); GNUNET_SCHEDULER_cancel (n->th->timeout_task); n->th->timeout_task = GNUNET_SCHEDULER_NO_TASK; /* we've been waiting for this (congestion, not quota, * caused delayed transmission) */ n->hn = GNUNET_CONTAINER_heap_insert (h->ready_heap, n, 0); schedule_transmission (h); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_RECV: LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message.\n", "RECV"); if (size < sizeof (struct InboundMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); break; } im = (const struct InboundMessage *) msg; imm = (const struct GNUNET_MessageHeader *) &im[1]; if (ntohs (imm->size) + sizeof (struct InboundMessage) != size) { GNUNET_break (0); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u from `%4s'.\n", ntohs (imm->type), GNUNET_i2s (&im->peer)); n = neighbour_find (h, &im->peer); if (NULL == n) { GNUNET_break (0); break; } if (NULL != h->rec) h->rec (h->cls, &im->peer, imm); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA: LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message.\n", "SET_QUOTA"); if (size != sizeof (struct QuotaSetMessage)) { GNUNET_break (0); break; } qm = (const struct QuotaSetMessage *) msg; n = neighbour_find (h, &qm->peer); if (NULL == n) break; LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message for `%4s' with quota %u\n", "SET_QUOTA", GNUNET_i2s (&qm->peer), ntohl (qm->quota.value__)); GNUNET_BANDWIDTH_tracker_update_quota (&n->out_tracker, qm->quota); break; default: LOG (GNUNET_ERROR_TYPE_ERROR, _("Received unexpected message of type %u in %s:%u\n"), ntohs (msg->type), __FILE__, __LINE__); GNUNET_break (0); break; } } /** * A transmission request could not be satisfied because of * network congestion. Notify the initiator and clean up. * * @param cls the `struct GNUNET_TRANSPORT_TransmitHandle` * @param tc scheduler context */ static void timeout_request_due_to_congestion (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TRANSPORT_TransmitHandle *th = cls; struct Neighbour *n = th->neighbour; n->th->timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (th == n->th); GNUNET_assert (NULL == n->hn); n->th = NULL; th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); } /** * Transmit message(s) to service. * * @param cls handle to transport * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to @a buf */ static size_t transport_notify_ready (void *cls, size_t size, void *buf) { struct GNUNET_TRANSPORT_Handle *h = cls; struct GNUNET_TRANSPORT_TransmitHandle *th; struct Neighbour *n; char *cbuf; struct OutboundMessage obm; size_t ret; size_t nret; size_t mret; GNUNET_assert (NULL != h->client); h->cth = NULL; if (NULL == buf) { /* transmission failed */ disconnect_and_schedule_reconnect (h); return 0; } cbuf = buf; ret = 0; /* first send control messages */ while ((NULL != (th = h->control_head)) && (th->notify_size <= size)) { GNUNET_CONTAINER_DLL_remove (h->control_head, h->control_tail, th); nret = th->notify (th->notify_cls, size, &cbuf[ret]); LOG (GNUNET_ERROR_TYPE_DEBUG, "Added %u bytes of control message at %u\n", nret, ret); GNUNET_free (th); ret += nret; size -= nret; } /* then, if possible and no control messages pending, send data messages */ while ((NULL == h->control_head) && (NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap)))) { if (GNUNET_YES != n->is_ready) { /* peer not ready, wait for notification! */ GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); n->hn = NULL; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == n->th->timeout_task); n->th->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (n->th->timeout), &timeout_request_due_to_congestion, n->th); continue; } th = n->th; if (th->notify_size + sizeof (struct OutboundMessage) > size) break; /* does not fit */ if (GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, th->notify_size).rel_value_us > 0) break; /* too early */ GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); n->hn = NULL; n->th = NULL; n->is_ready = GNUNET_NO; GNUNET_assert (size >= sizeof (struct OutboundMessage)); mret = th->notify (th->notify_cls, size - sizeof (struct OutboundMessage), &cbuf[ret + sizeof (struct OutboundMessage)]); GNUNET_assert (mret <= size - sizeof (struct OutboundMessage)); if (mret != 0) { GNUNET_assert (mret + sizeof (struct OutboundMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); obm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND); obm.header.size = htons (mret + sizeof (struct OutboundMessage)); obm.reserved = htonl (0); obm.timeout = GNUNET_TIME_relative_hton (GNUNET_TIME_absolute_get_remaining (th->timeout)); obm.peer = n->id; memcpy (&cbuf[ret], &obm, sizeof (struct OutboundMessage)); ret += (mret + sizeof (struct OutboundMessage)); size -= (mret + sizeof (struct OutboundMessage)); GNUNET_BANDWIDTH_tracker_consume (&n->out_tracker, mret); } GNUNET_free (th); } /* if there are more pending messages, try to schedule those */ schedule_transmission (h); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes to transport service\n", ret); return ret; } /** * Schedule the task to send one message, either from the control * list or the peer message queues to the service. * * @param cls transport service to schedule a transmission for * @param tc scheduler context */ static void schedule_transmission_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TRANSPORT_Handle *h = cls; size_t size; struct GNUNET_TRANSPORT_TransmitHandle *th; struct Neighbour *n; h->quota_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (NULL != h->client); /* destroy all requests that have timed out */ while ((NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap))) && (0 == GNUNET_TIME_absolute_get_remaining (n->th->timeout).rel_value_us)) { /* notify client that the request could not be satisfied within * the given time constraints */ th = n->th; n->th = NULL; GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap)); n->hn = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "Signalling timeout for transmission to peer %s due to congestion\n", GNUNET_i2s (&n->id)); GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); GNUNET_free (th); } if (NULL != h->cth) return; if (NULL != h->control_head) { size = h->control_head->notify_size; } else { n = GNUNET_CONTAINER_heap_peek (h->ready_heap); if (NULL == n) return; /* no pending messages */ size = n->th->notify_size + sizeof (struct OutboundMessage); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Calling notify_transmit_ready\n"); h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client, size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transport_notify_ready, h); GNUNET_assert (NULL != h->cth); } /** * Schedule the task to send one message, either from the control * list or the peer message queues to the service. * * @param h transport service to schedule a transmission for */ static void schedule_transmission (struct GNUNET_TRANSPORT_Handle *h) { struct GNUNET_TIME_Relative delay; struct Neighbour *n; GNUNET_assert (NULL != h->client); if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (h->quota_task); h->quota_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != h->control_head) delay = GNUNET_TIME_UNIT_ZERO; else if (NULL != (n = GNUNET_CONTAINER_heap_peek (h->ready_heap))) { delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, n->th->notify_size + n->traffic_overhead); n->traffic_overhead = 0; } else return; /* no work to be done */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling next transmission to service in %s\n", GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); h->quota_task = GNUNET_SCHEDULER_add_delayed (delay, &schedule_transmission_task, h); } /** * Queue control request for transmission to the transport * service. * * @param h handle to the transport service * @param size number of bytes to be transmitted * @param notify function to call to get the content * @param notify_cls closure for @a notify * @return a `struct GNUNET_TRANSPORT_TransmitHandle` */ static struct GNUNET_TRANSPORT_TransmitHandle * schedule_control_transmit (struct GNUNET_TRANSPORT_Handle *h, size_t size, GNUNET_TRANSPORT_TransmitReadyNotify notify, void *notify_cls) { struct GNUNET_TRANSPORT_TransmitHandle *th; LOG (GNUNET_ERROR_TYPE_DEBUG, "Control transmit of %u bytes requested\n", size); th = GNUNET_new (struct GNUNET_TRANSPORT_TransmitHandle); th->notify = notify; th->notify_cls = notify_cls; th->notify_size = size; GNUNET_CONTAINER_DLL_insert_tail (h->control_head, h->control_tail, th); schedule_transmission (h); return th; } /** * Transmit START message to service. * * @param cls unused * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to @a buf */ static size_t send_start (void *cls, size_t size, void *buf) { struct GNUNET_TRANSPORT_Handle *h = cls; struct StartMessage s; uint32_t options; if (NULL == buf) { /* Can only be shutdown, just give up */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutdown while trying to transmit `%s' request.\n", "START"); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "START"); GNUNET_assert (size >= sizeof (struct StartMessage)); s.header.size = htons (sizeof (struct StartMessage)); s.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_START); options = 0; if (h->check_self) options |= 1; if (h->rec != NULL) options |= 2; s.options = htonl (options); s.self = h->self; memcpy (buf, &s, sizeof (struct StartMessage)); GNUNET_CLIENT_receive (h->client, &demultiplexer, h, GNUNET_TIME_UNIT_FOREVER_REL); return sizeof (struct StartMessage); } /** * Try again to connect to transport service. * * @param cls the handle to the transport service * @param tc scheduler context */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TRANSPORT_Handle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* shutdown, just give up */ return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to transport service.\n"); GNUNET_assert (NULL == h->client); GNUNET_assert (NULL == h->control_head); GNUNET_assert (NULL == h->control_tail); h->reconnecting = GNUNET_NO; h->client = GNUNET_CLIENT_connect ("transport", h->cfg); GNUNET_assert (NULL != h->client); schedule_control_transmit (h, sizeof (struct StartMessage), &send_start, h); } /** * Function that will schedule the job that will try * to connect us again to the client. * * @param h transport service to reconnect */ static void disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h) { struct GNUNET_TRANSPORT_TransmitHandle *th; GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; /* LOG (GNUNET_ERROR_TYPE_ERROR, "Client disconnect done \n");*/ } /* Forget about all neighbours that we used to be connected to */ GNUNET_CONTAINER_multipeermap_iterate (h->neighbours, &neighbour_delete, h); if (h->quota_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (h->quota_task); h->quota_task = GNUNET_SCHEDULER_NO_TASK; } while ((NULL != (th = h->control_head))) { GNUNET_CONTAINER_DLL_remove (h->control_head, h->control_tail, th); th->notify (th->notify_cls, 0, NULL); GNUNET_free (th); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task to reconnect to transport service in %s.\n", GNUNET_STRINGS_relative_time_to_string(h->reconnect_delay, GNUNET_YES)); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); } /** * Cancel control request for transmission to the transport service. * * @param th handle to the transport service * @param tth transmit handle to cancel */ static void cancel_control_transmit (struct GNUNET_TRANSPORT_Handle *th, struct GNUNET_TRANSPORT_TransmitHandle *tth) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Canceling transmit of contral transmission requested\n"); GNUNET_CONTAINER_DLL_remove (th->control_head, th->control_tail, tth); GNUNET_free (tth); } /** * Send REQUEST_CONNECT message to the service. * * @param cls the `struct GNUNET_PeerIdentity` * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to @a buf */ static size_t send_try_connect (void *cls, size_t size, void *buf) { struct GNUNET_TRANSPORT_TryConnectHandle *tch = cls; struct TransportRequestConnectMessage msg; if (NULL == buf) { if (NULL != tch->cb) tch->cb (tch->cb_cls, GNUNET_SYSERR); GNUNET_CONTAINER_DLL_remove (tch->th->tc_head, tch->th->tc_tail, tch); LOG (GNUNET_ERROR_TYPE_DEBUG, "Discarding `%s' request to `%4s' due to error in transport service connection.\n", "REQUEST_CONNECT", GNUNET_i2s (&tch->pid)); GNUNET_free (tch); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request with respect to `%4s'.\n", "REQUEST_CONNECT", GNUNET_i2s (&tch->pid)); GNUNET_assert (size >= sizeof (struct TransportRequestConnectMessage)); msg.header.size = htons (sizeof (struct TransportRequestConnectMessage)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT); msg.connect = htonl (tch->connect); msg.peer = tch->pid; memcpy (buf, &msg, sizeof (msg)); if (NULL != tch->cb) tch->cb (tch->cb_cls, GNUNET_OK); GNUNET_CONTAINER_DLL_remove (tch->th->tc_head, tch->th->tc_tail, tch); GNUNET_free (tch); return sizeof (struct TransportRequestConnectMessage); } /** * Ask the transport service to establish a connection to * the given peer. * * @param handle connection to transport service * @param target who we should try to connect to * @param cb callback to be called when request was transmitted to transport * service * @param cb_cls closure for the callback * @return a `struct GNUNET_TRANSPORT_TryConnectHandle` handle or * NULL on failure (cb will not be called) */ struct GNUNET_TRANSPORT_TryConnectHandle * GNUNET_TRANSPORT_try_connect (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *target, GNUNET_TRANSPORT_TryConnectCallback cb, void *cb_cls) { struct GNUNET_TRANSPORT_TryConnectHandle *tch = NULL; if (NULL == handle->client) return NULL; tch = GNUNET_new (struct GNUNET_TRANSPORT_TryConnectHandle); tch->th = handle; tch->pid = *(target); tch->cb = cb; tch->cb_cls = cb_cls; tch->connect = GNUNET_YES; tch->tth = schedule_control_transmit (handle, sizeof (struct TransportRequestConnectMessage), &send_try_connect, tch); GNUNET_CONTAINER_DLL_insert(handle->tc_head, handle->tc_tail, tch); return tch; } /** * Cancel the request to transport to try a connect * Callback will not be called * * @param tch the handle to cancel */ void GNUNET_TRANSPORT_try_connect_cancel (struct GNUNET_TRANSPORT_TryConnectHandle *tch) { struct GNUNET_TRANSPORT_Handle *th; GNUNET_assert (GNUNET_YES == tch->connect); th = tch->th; cancel_control_transmit (th, tch->tth); GNUNET_CONTAINER_DLL_remove (th->tc_head, th->tc_tail, tch); GNUNET_free (tch); } /** * Ask the transport service to shutdown a connection to * the given peer. * * @param handle connection to transport service * @param target who we should try to connect to * @param cb callback to be called when request was transmitted to transport * service * @param cb_cls closure for the callback * @return a `struct GNUNET_TRANSPORT_TryConnectHandle` handle or * NULL on failure (cb will not be called) */ struct GNUNET_TRANSPORT_TryConnectHandle * GNUNET_TRANSPORT_try_disconnect (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *target, GNUNET_TRANSPORT_TryConnectCallback cb, void *cb_cls) { struct GNUNET_TRANSPORT_TryConnectHandle *tch = NULL; if (NULL == handle->client) return NULL; tch = GNUNET_new (struct GNUNET_TRANSPORT_TryConnectHandle); tch->th = handle; tch->pid = *(target); tch->cb = cb; tch->cb_cls = cb_cls; tch->connect = GNUNET_NO; tch->tth = schedule_control_transmit (handle, sizeof (struct TransportRequestConnectMessage), &send_try_connect, tch); GNUNET_CONTAINER_DLL_insert(handle->tc_head, handle->tc_tail, tch); return tch; } /** * Cancel the request to transport to try a disconnect * Callback will not be called * * @param tch the handle to cancel */ void GNUNET_TRANSPORT_try_disconnect_cancel (struct GNUNET_TRANSPORT_TryConnectHandle *tch) { struct GNUNET_TRANSPORT_Handle *th; GNUNET_assert (GNUNET_NO == tch->connect); th = tch->th; cancel_control_transmit (th, tch->tth); GNUNET_CONTAINER_DLL_remove (th->tc_head, th->tc_tail, tch); GNUNET_free (tch); } /** * Send HELLO message to the service. * * @param cls the HELLO message to send * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to @a buf */ static size_t send_hello (void *cls, size_t size, void *buf) { struct GNUNET_TRANSPORT_OfferHelloHandle *ohh = cls; struct GNUNET_MessageHeader *msg = ohh->msg; uint16_t ssize; struct GNUNET_SCHEDULER_TaskContext tc; tc.read_ready = NULL; tc.write_ready = NULL; tc.reason = GNUNET_SCHEDULER_REASON_TIMEOUT; if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout while trying to transmit `%s' request.\n", "HELLO"); if (NULL != ohh->cont) ohh->cont (ohh->cls, &tc); GNUNET_free (msg); GNUNET_CONTAINER_DLL_remove (ohh->th->oh_head, ohh->th->oh_tail, ohh); GNUNET_free (ohh); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "HELLO"); ssize = ntohs (msg->size); GNUNET_assert (size >= ssize); memcpy (buf, msg, ssize); GNUNET_free (msg); tc.reason = GNUNET_SCHEDULER_REASON_READ_READY; if (NULL != ohh->cont) ohh->cont (ohh->cls, &tc); GNUNET_CONTAINER_DLL_remove (ohh->th->oh_head, ohh->th->oh_tail, ohh); GNUNET_free (ohh); return ssize; } /** * Send traffic metric message to the service. * * @param cls the message to send * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to @a buf */ static size_t send_metric (void *cls, size_t size, void *buf) { struct TrafficMetricMessage *msg = cls; uint16_t ssize; if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout while trying to transmit `%s' request.\n", "TRAFFIC_METRIC"); GNUNET_free (msg); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "TRAFFIC_METRIC"); ssize = ntohs (msg->header.size); GNUNET_assert (size >= ssize); memcpy (buf, msg, ssize); GNUNET_free (msg); return ssize; } /** * Set transport metrics for a peer and a direction * * @param handle transport handle * @param peer the peer to set the metric for * @param inbound set inbound direction (#GNUNET_YES or #GNUNET_NO) * @param outbound set outbound direction (#GNUNET_YES or #GNUNET_NO) * @param ats the metric as ATS information * @param ats_count the number of metrics * * Supported ATS values: * #GNUNET_ATS_QUALITY_NET_DELAY (value in ms) * #GNUNET_ATS_QUALITY_NET_DISTANCE (value in count(hops)) * * Example: * To enforce a delay of 10 ms for peer p1 in sending direction use: * * struct GNUNET_ATS_Information ats; * ats.type = ntohl (GNUNET_ATS_QUALITY_NET_DELAY); * ats.value = ntohl (10); * GNUNET_TRANSPORT_set_traffic_metric (th, p1, TM_SEND, &ats, 1); * * Note: * Delay restrictions in receiving direction will be enforced with * 1 message delay. */ void GNUNET_TRANSPORT_set_traffic_metric (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *peer, int inbound, int outbound, const struct GNUNET_ATS_Information *ats, size_t ats_count) { struct TrafficMetricMessage *msg; GNUNET_assert ((outbound == GNUNET_YES) || (outbound == GNUNET_NO)); GNUNET_assert ((inbound == GNUNET_YES) || (inbound == GNUNET_NO)); if ((GNUNET_NO == inbound) && (GNUNET_NO == outbound)) return; if (0 == ats_count) return; size_t len = sizeof (struct TrafficMetricMessage) + ats_count * sizeof (struct GNUNET_ATS_Information); msg = GNUNET_malloc (len); msg->header.size = htons (len); msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC); msg->direction = htons (0 + outbound + 2 * inbound); msg->ats_count = htons (ats_count); msg->peer = (*peer); memcpy (&msg[1], ats, ats_count * sizeof (struct GNUNET_ATS_Information)); schedule_control_transmit (handle, len, &send_metric, msg); } /** * Offer the transport service the HELLO of another peer. Note that * the transport service may just ignore this message if the HELLO is * malformed or useless due to our local configuration. * * @param handle connection to transport service * @param hello the hello message * @param cont continuation to call when HELLO has been sent, * tc reason #GNUNET_SCHEDULER_REASON_TIMEOUT for fail * tc reasong #GNUNET_SCHEDULER_REASON_READ_READY for success * @param cls closure for continuation * @return a `struct GNUNET_TRANSPORT_OfferHelloHandle` handle or NULL on failure, * in case of failure cont will not be called * */ struct GNUNET_TRANSPORT_OfferHelloHandle * GNUNET_TRANSPORT_offer_hello (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_MessageHeader *hello, GNUNET_SCHEDULER_Task cont, void *cls) { struct GNUNET_TRANSPORT_OfferHelloHandle *ohh; struct GNUNET_MessageHeader *msg; struct GNUNET_PeerIdentity peer; uint16_t size; if (NULL == handle->client) return NULL; GNUNET_break (ntohs (hello->type) == GNUNET_MESSAGE_TYPE_HELLO); size = ntohs (hello->size); GNUNET_break (size >= sizeof (struct GNUNET_MessageHeader)); if (GNUNET_OK != GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hello, &peer)) { GNUNET_break (0); return NULL; } msg = GNUNET_malloc (size); memcpy (msg, hello, size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Offering `%s' message of `%4s' to transport for validation.\n", "HELLO", GNUNET_i2s (&peer)); ohh = GNUNET_new (struct GNUNET_TRANSPORT_OfferHelloHandle); ohh->th = handle; ohh->cont = cont; ohh->cls = cls; ohh->msg = msg; ohh->tth = schedule_control_transmit (handle, size, &send_hello, ohh); GNUNET_CONTAINER_DLL_insert (handle->oh_head, handle->oh_tail, ohh); return ohh; } /** * Cancel the request to transport to offer the HELLO message * * @param ohh the GNUNET_TRANSPORT_OfferHelloHandle to cancel */ void GNUNET_TRANSPORT_offer_hello_cancel (struct GNUNET_TRANSPORT_OfferHelloHandle *ohh) { struct GNUNET_TRANSPORT_Handle *th = ohh->th; cancel_control_transmit (ohh->th, ohh->tth); GNUNET_CONTAINER_DLL_remove (th->oh_head, th->oh_tail, ohh); GNUNET_free (ohh->msg); GNUNET_free (ohh); } /** * Checks if a given peer is connected to us * * @param handle connection to transport service * @param peer the peer to check * @return #GNUNET_YES (connected) or #GNUNET_NO (disconnected) */ int GNUNET_TRANSPORT_check_peer_connected (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *peer) { if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (handle->neighbours, peer)) return GNUNET_YES; return GNUNET_NO; } /** * Task to call the HelloUpdateCallback of the GetHelloHandle * * @param cls the `struct GNUNET_TRANSPORT_GetHelloHandle` * @param tc the scheduler task context */ static void call_hello_update_cb_async (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TRANSPORT_GetHelloHandle *ghh = cls; GNUNET_assert (NULL != ghh->handle->my_hello); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != ghh->notify_task); ghh->notify_task = GNUNET_SCHEDULER_NO_TASK; ghh->rec (ghh->rec_cls, (const struct GNUNET_MessageHeader *) ghh->handle->my_hello); } /** * Obtain the HELLO message for this peer. The callback given in this function * is never called synchronously. * * @param handle connection to transport service * @param rec function to call with the HELLO, sender will be our peer * identity; message and sender will be NULL on timeout * (handshake with transport service pending/failed). * cost estimate will be 0. * @param rec_cls closure for @a rec * @return handle to cancel the operation */ struct GNUNET_TRANSPORT_GetHelloHandle * GNUNET_TRANSPORT_get_hello (struct GNUNET_TRANSPORT_Handle *handle, GNUNET_TRANSPORT_HelloUpdateCallback rec, void *rec_cls) { struct GNUNET_TRANSPORT_GetHelloHandle *hwl; hwl = GNUNET_new (struct GNUNET_TRANSPORT_GetHelloHandle); hwl->rec = rec; hwl->rec_cls = rec_cls; hwl->handle = handle; GNUNET_CONTAINER_DLL_insert (handle->hwl_head, handle->hwl_tail, hwl); if (handle->my_hello != NULL) hwl->notify_task = GNUNET_SCHEDULER_add_now (&call_hello_update_cb_async, hwl); return hwl; } /** * Stop receiving updates about changes to our HELLO message. * * @param ghh handle to cancel */ void GNUNET_TRANSPORT_get_hello_cancel (struct GNUNET_TRANSPORT_GetHelloHandle *ghh) { struct GNUNET_TRANSPORT_Handle *handle = ghh->handle; if (GNUNET_SCHEDULER_NO_TASK != ghh->notify_task) GNUNET_SCHEDULER_cancel (ghh->notify_task); GNUNET_CONTAINER_DLL_remove (handle->hwl_head, handle->hwl_tail, ghh); GNUNET_free (ghh); } /** * Connect to the transport service. Note that the connection may * complete (or fail) asynchronously. * * @param cfg configuration to use * @param self our own identity (API should check that it matches * the identity found by transport), or NULL (no check) * @param cls closure for the callbacks * @param rec receive function to call * @param nc function to call on connect events * @param nd function to call on disconnect events * @return NULL on error */ struct GNUNET_TRANSPORT_Handle * GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, void *cls, GNUNET_TRANSPORT_ReceiveCallback rec, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd) { return GNUNET_TRANSPORT_connect2 (cfg, self, cls, rec, nc, nd, NULL); } /** * Connect to the transport service. Note that the connection may * complete (or fail) asynchronously. * * @param cfg configuration to use * @param self our own identity (API should check that it matches * the identity found by transport), or NULL (no check) * @param cls closure for the callbacks * @param rec receive function to call * @param nc function to call on connect events * @param nd function to call on disconnect events * @param neb function to call if we have excess bandwidth to a peer * @return NULL on error */ struct GNUNET_TRANSPORT_Handle * GNUNET_TRANSPORT_connect2 (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, void *cls, GNUNET_TRANSPORT_ReceiveCallback rec, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd, GNUNET_TRANSPORT_NotifyExcessBandwidth neb) { struct GNUNET_TRANSPORT_Handle *ret; ret = GNUNET_new (struct GNUNET_TRANSPORT_Handle); if (NULL != self) { ret->self = *self; ret->check_self = GNUNET_YES; } ret->cfg = cfg; ret->cls = cls; ret->rec = rec; ret->nc_cb = nc; ret->nd_cb = nd; ret->neb_cb = neb; ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to transport service.\n"); ret->client = GNUNET_CLIENT_connect ("transport", cfg); if (NULL == ret->client) { GNUNET_free (ret); return NULL; } ret->neighbours = GNUNET_CONTAINER_multipeermap_create (STARTING_NEIGHBOURS_SIZE, GNUNET_YES); ret->ready_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); schedule_control_transmit (ret, sizeof (struct StartMessage), &send_start, ret); return ret; } /** * Disconnect from the transport service. * * @param handle handle to the service as returned from #GNUNET_TRANSPORT_connect() */ void GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n"); /* this disconnects all neighbours... */ if (handle->reconnect_task == GNUNET_SCHEDULER_NO_TASK) disconnect_and_schedule_reconnect (handle); /* and now we stop trying to connect again... */ if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (handle->reconnect_task); handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_multipeermap_destroy (handle->neighbours); handle->neighbours = NULL; if (handle->quota_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (handle->quota_task); handle->quota_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free_non_null (handle->my_hello); handle->my_hello = NULL; GNUNET_assert (NULL == handle->tc_head); GNUNET_assert (NULL == handle->tc_tail); GNUNET_assert (NULL == handle->hwl_head); GNUNET_assert (NULL == handle->hwl_tail); GNUNET_CONTAINER_heap_destroy (handle->ready_heap); handle->ready_heap = NULL; GNUNET_free (handle); } /** * Check if we could queue a message of the given size for * transmission. The transport service will take both its * internal buffers and bandwidth limits imposed by the * other peer into consideration when answering this query. * * @param handle connection to transport service * @param target who should receive the message * @param size how big is the message we want to transmit? * @param timeout after how long should we give up (and call * notify with buf NULL and size 0)? * @param notify function to call when we are ready to * send such a message * @param notify_cls closure for @a notify * @return NULL if someone else is already waiting to be notified * non-NULL if the notify callback was queued (can be used to cancel * using #GNUNET_TRANSPORT_notify_transmit_ready_cancel) */ struct GNUNET_TRANSPORT_TransmitHandle * GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle *handle, const struct GNUNET_PeerIdentity *target, size_t size, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_TransmitReadyNotify notify, void *notify_cls) { struct Neighbour *n; struct GNUNET_TRANSPORT_TransmitHandle *th; struct GNUNET_TIME_Relative delay; n = neighbour_find (handle, target); if (NULL == n) { /* use GNUNET_TRANSPORT_try_connect first, only use this function * once a connection has been established */ GNUNET_assert (0); return NULL; } if (NULL != n->th) { /* attempt to send two messages at the same time to the same peer */ GNUNET_assert (0); return NULL; } GNUNET_assert (NULL == n->hn); th = GNUNET_new (struct GNUNET_TRANSPORT_TransmitHandle); th->neighbour = n; th->notify = notify; th->notify_cls = notify_cls; th->timeout = GNUNET_TIME_relative_to_absolute (timeout); th->notify_size = size; n->th = th; /* calculate when our transmission should be ready */ delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, size + n->traffic_overhead); n->traffic_overhead = 0; if (delay.rel_value_us > timeout.rel_value_us) delay.rel_value_us = 0; /* notify immediately (with failure) */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Bandwidth tracker allows next transmission to peer %s in %s\n", GNUNET_i2s (target), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); n->hn = GNUNET_CONTAINER_heap_insert (handle->ready_heap, n, delay.rel_value_us); schedule_transmission (handle); return th; } /** * Cancel the specified transmission-ready notification. * * @param th handle returned from #GNUNET_TRANSPORT_notify_transmit_ready() */ void GNUNET_TRANSPORT_notify_transmit_ready_cancel (struct GNUNET_TRANSPORT_TransmitHandle *th) { struct Neighbour *n; GNUNET_assert (NULL == th->next); GNUNET_assert (NULL == th->prev); n = th->neighbour; GNUNET_assert (th == n->th); n->th = NULL; if (NULL != n->hn) { GNUNET_CONTAINER_heap_remove_node (n->hn); n->hn = NULL; } else { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != th->timeout_task); GNUNET_SCHEDULER_cancel (th->timeout_task); th->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (th); } /* end of transport_api.c */ gnunet-0.10.1/src/transport/plugin_transport_unix.c0000644000175000017500000013742512320724370017472 00000000000000/* This file is part of GNUnet (C) 2010, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/plugin_transport_unix.c * @brief Transport plugin using unix domain sockets (!) * Clearly, can only be used locally on Unix/Linux hosts... * ONLY INTENDED FOR TESTING!!! * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "transport.h" /** * Return code we give on 'send' if we failed to send right now * but it makes sense to retry later. (Note: we might want to * move this to the plugin API!?). */ #define RETRY 0 #define PLUGIN_NAME "unix" enum UNIX_ADDRESS_OPTIONS { UNIX_OPTIONS_NONE = 0, UNIX_OPTIONS_USE_ABSTRACT_SOCKETS = 1 }; /** * How long until we give up on transmitting the welcome message? */ #define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) #define LOG(kind,...) GNUNET_log_from (kind, "transport-unix",__VA_ARGS__) GNUNET_NETWORK_STRUCT_BEGIN struct UnixAddress { uint32_t options GNUNET_PACKED; uint32_t addrlen GNUNET_PACKED; }; /** * UNIX Message-Packet header. */ struct UNIXMessage { /** * Message header. */ struct GNUNET_MessageHeader header; /** * What is the identity of the sender (GNUNET_hash of public key) */ struct GNUNET_PeerIdentity sender; }; GNUNET_NETWORK_STRUCT_END /** * Handle for a session. */ struct Session { struct GNUNET_PeerIdentity target; struct Plugin * plugin; struct GNUNET_HELLO_Address *address; /** * Session timeout task */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; struct UNIXMessageWrapper { /** * We keep messages in a doubly linked list. */ struct UNIXMessageWrapper *next; /** * We keep messages in a doubly linked list. */ struct UNIXMessageWrapper *prev; /** * The actual payload (allocated separately right now). */ struct UNIXMessage * msg; /** * Session this message belongs to. */ struct Session *session; /** * Function to call upon transmission. */ GNUNET_TRANSPORT_TransmitContinuation cont; /** * Closure for 'cont'. */ void *cont_cls; /** * Timeout for this message. */ struct GNUNET_TIME_Absolute timeout; /** * Number of bytes in 'msg'. */ size_t msgsize; /** * Number of bytes of payload encapsulated in 'msg'. */ size_t payload; /** * Priority of the message (ignored, just dragged along in UNIX). */ unsigned int priority; }; /** * Encapsulation of all of the state of the plugin. */ struct Plugin; /** * UNIX "Session" */ struct PeerSession { /** * Stored in a linked list. */ struct PeerSession *next; /** * Pointer to the global plugin struct. */ struct Plugin *plugin; /** * To whom are we talking to (set to our identity * if we are still waiting for the welcome message) */ struct GNUNET_PeerIdentity target; /** * Address of the other peer (either based on our 'connect' * call or on our 'accept' call). */ void *connect_addr; /** * Length of connect_addr. */ size_t connect_alen; /** * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO) */ int expecting_welcome; /** * From which socket do we need to send to this peer? */ struct GNUNET_NETWORK_Handle *sock; /* * Queue of messages for this peer, in the case that * we have to await a connection... */ struct MessageQueue *messages; }; /** * Information we keep for each of our listen sockets. */ struct UNIX_Sock_Info { /** * The network handle */ struct GNUNET_NETWORK_Handle *desc; /** * The port we bound to (not an actual PORT, as UNIX domain sockets * don't have ports, but rather a number in the path name to make this * one unique). */ uint16_t port; }; /** * Encapsulation of all of the state of the plugin. */ struct Plugin { /** * ID of task used to update our addresses when one expires. */ GNUNET_SCHEDULER_TaskIdentifier address_update_task; /** * ID of select task */ GNUNET_SCHEDULER_TaskIdentifier select_task; /** * Number of bytes we currently have in our write queue. */ unsigned long long bytes_in_queue; /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * Sessions */ struct GNUNET_CONTAINER_MultiPeerMap *session_map; /** * FD Read set */ struct GNUNET_NETWORK_FDSet *rs; /** * FD Write set */ struct GNUNET_NETWORK_FDSet *ws; /** * Path of our unix domain socket (/tmp/unix-plugin-PORT) */ char *unix_socket_path; /** * Head of queue of messages to transmit. */ struct UNIXMessageWrapper *msg_head; /** * Tail of queue of messages to transmit. */ struct UNIXMessageWrapper *msg_tail; /** * socket that we transmit all data with */ struct UNIX_Sock_Info unix_sock; /** * Address options in HBO */ uint32_t myoptions; /** * ATS network */ struct GNUNET_ATS_Information ats_network; /** * Is the write set in the current 'select' task? GNUNET_NO if the * write queue was empty when the main task was scheduled, * GNUNET_YES if we're already waiting for being allowed to write. */ int with_ws; int abstract; }; /** * Increment session timeout due to activity * * @param s session for which the timeout should be moved */ static void reschedule_session_timeout (struct Session *s); /** * We have been notified that our writeset has something to read. We don't * know which socket needs to be read, so we have to check each one * Then reschedule this function to be called again once more is available. * * @param cls the plugin handle * @param tc the scheduling context (for rescheduling this function again) */ static void unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static struct sockaddr_un * unix_address_to_sockaddr (const char *unixpath, socklen_t *sock_len) { struct sockaddr_un *un; size_t slen; GNUNET_assert (0 < strlen (unixpath)); /* sanity check */ un = GNUNET_new (struct sockaddr_un); un->sun_family = AF_UNIX; slen = strlen (unixpath); if (slen >= sizeof (un->sun_path)) slen = sizeof (un->sun_path) - 1; memcpy (un->sun_path, unixpath, slen); un->sun_path[slen] = '\0'; slen = sizeof (struct sockaddr_un); #if HAVE_SOCKADDR_IN_SIN_LEN un->sun_len = (u_char) slen; #endif (*sock_len) = slen; return un; } /** * Function called for a quick conversion of the binary address to * a numeric address. Note that the caller must not free the * address and that the next call to this function is allowed * to override the address again. * * @param cls closure * @param addr binary address * @param addrlen length of the address * @return string representing the same address */ static const char * unix_address_to_string (void *cls, const void *addr, size_t addrlen) { static char rbuf[1024]; struct UnixAddress *ua = (struct UnixAddress *) addr; char *addrstr; size_t addr_str_len; unsigned int off; if ((NULL == addr) || (sizeof (struct UnixAddress) > addrlen)) { GNUNET_break(0); return NULL ; } addrstr = (char *) &ua[1]; addr_str_len = ntohl (ua->addrlen); if (addr_str_len != addrlen - sizeof(struct UnixAddress)) { GNUNET_break(0); return NULL ; } if ('\0' != addrstr[addr_str_len - 1]) { GNUNET_break(0); return NULL ; } if (strlen (addrstr) + 1 != addr_str_len) { GNUNET_break(0); return NULL ; } off = 0; if ('\0' == addrstr[0]) off++; memset (rbuf, 0, sizeof (rbuf)); GNUNET_snprintf (rbuf, sizeof (rbuf) - 1, "%s.%u.%s%.*s", PLUGIN_NAME, ntohl (ua->options), (off == 1) ? "@" : "", (int) (addr_str_len - off), &addrstr[off]); /* GNUNET_snprintf (rbuf, sizeof(rbuf), "%s.%u.%s", PLUGIN_NAME, ntohl (ua->options), addrstr);*/ return rbuf; } /** * Re-schedule the main 'select' callback (unix_plugin_select) * for this plugin. * * @param plugin the plugin context */ static void reschedule_select (struct Plugin * plugin) { if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (plugin->select_task); plugin->select_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != plugin->msg_head) { plugin->select_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, plugin->ws, &unix_plugin_select, plugin); plugin->with_ws = GNUNET_YES; } else { plugin->select_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs, NULL, &unix_plugin_select, plugin); plugin->with_ws = GNUNET_NO; } } /** * Closure to #lookup_session_it. */ struct LookupCtx { /** * Location to store the session, if found. */ struct Session *res; struct GNUNET_HELLO_Address *address; }; /** * Function called to find a session by address. * * @param cls the 'struct LookupCtx' * @param key peer we are looking for (unused) * @param value a session * @return #GNUNET_YES if not found (continue looking), #GNUNET_NO on success */ static int lookup_session_it (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct LookupCtx *lctx = cls; struct Session *s = value; if (0 == GNUNET_HELLO_address_cmp (lctx->address, s->address)) { lctx->res = s; return GNUNET_NO; } return GNUNET_YES; } /** * Find an existing session by address. * * @param plugin the plugin * @param address the address to find * @return NULL if session was not found */ static struct Session * lookup_session (struct Plugin *plugin, struct GNUNET_HELLO_Address *address) { struct LookupCtx lctx; lctx.address = address; lctx.res = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (plugin->session_map, &address->peer, &lookup_session_it, &lctx); return lctx.res; } /** * Functions with this signature are called whenever we need * to close a session due to a disconnect or failure to * establish a connection. * * @param cls closure with the `struct Plugin` * @param s session to close down * @return #GNUNET_OK on success */ static int unix_session_disconnect (void *cls, struct Session *s) { struct Plugin *plugin = cls; struct UNIXMessageWrapper *msgw; struct UNIXMessageWrapper *next; int removed; LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting session for peer `%s' `%s'\n", GNUNET_i2s (&s->target), unix_address_to_string (NULL, s->address->address, s->address->address_length) ); plugin->env->session_end (plugin->env->cls, s->address, s); removed = GNUNET_NO; next = plugin->msg_head; while (NULL != next) { msgw = next; next = msgw->next; if (msgw->session != s) continue; GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw); if (NULL != msgw->cont) msgw->cont (msgw->cont_cls, &msgw->session->target, GNUNET_SYSERR, msgw->payload, 0); GNUNET_free (msgw->msg); GNUNET_free (msgw); removed = GNUNET_YES; } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (plugin->session_map, &s->target, s)); GNUNET_STATISTICS_set (plugin->env->stats, "# UNIX sessions active", GNUNET_CONTAINER_multipeermap_size (plugin->session_map), GNUNET_NO); if ((GNUNET_YES == removed) && (NULL == plugin->msg_head)) reschedule_select (plugin); if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task) { GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_HELLO_address_free (s->address); GNUNET_free (s); return GNUNET_OK; } /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int unix_query_keepalive_factor (void *cls) { return 3; } /** * Actually send out the message, assume we've got the address and * send_handle squared away! * * @param cls closure * @param send_handle which handle to send message on * @param target who should receive this message (ignored by UNIX) * @param msgbuf one or more GNUNET_MessageHeader(s) strung together * @param msgbuf_size the size of the msgbuf to send * @param priority how important is the message (ignored by UNIX) * @param timeout when should we time out (give up) if we can not transmit? * @param addr the addr to send the message to, needs to be a sockaddr for us * @param addrlen the len of @a addr * @param payload bytes payload to send * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...) * @param cont_cls closure for @a cont * @return on success the number of bytes written, RETRY for retry, -1 on errors */ static ssize_t unix_real_send (void *cls, struct GNUNET_NETWORK_Handle *send_handle, const struct GNUNET_PeerIdentity *target, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Absolute timeout, const struct UnixAddress *addr, size_t addrlen, size_t payload, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin *plugin = cls; ssize_t sent; struct sockaddr_un *un; socklen_t un_len; const char *unixpath; GNUNET_assert (NULL != plugin); if (NULL == send_handle) { GNUNET_break (0); /* We do not have a send handle */ return GNUNET_SYSERR; } if ((NULL == addr) || (0 == addrlen)) { GNUNET_break (0); /* Can never send if we don't have an address */ return GNUNET_SYSERR; } /* Prepare address */ unixpath = (const char *) &addr[1]; if (NULL == (un = unix_address_to_sockaddr (unixpath, &un_len))) { GNUNET_break (0); return -1; } if ((GNUNET_YES == plugin->abstract) && (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & ntohl(addr->options) )) ) { un->sun_path[0] = '\0'; } resend: /* Send the data */ sent = GNUNET_NETWORK_socket_sendto (send_handle, msgbuf, msgbuf_size, (const struct sockaddr *) un, un_len); if (GNUNET_SYSERR == sent) { if ( (EAGAIN == errno) || (ENOBUFS == errno) ) { GNUNET_free (un); return RETRY; /* We have to retry later */ } if (EMSGSIZE == errno) { socklen_t size = 0; socklen_t len = sizeof (size); GNUNET_NETWORK_socket_getsockopt ((struct GNUNET_NETWORK_Handle *) send_handle, SOL_SOCKET, SO_SNDBUF, &size, &len); if (size < msgbuf_size) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to increase socket buffer size from %i to %i for message size %i\n", size, ((msgbuf_size / 1000) + 2) * 1000, msgbuf_size); size = ((msgbuf_size / 1000) + 2) * 1000; if (GNUNET_OK == GNUNET_NETWORK_socket_setsockopt ((struct GNUNET_NETWORK_Handle *) send_handle, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size))) goto resend; /* Increased buffer size, retry sending */ else { /* Could not increase buffer size: error, no retry */ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt"); GNUNET_free (un); return GNUNET_SYSERR; } } else { /* Buffer is bigger than message: error, no retry * This should never happen!*/ GNUNET_break (0); GNUNET_free (un); return GNUNET_SYSERR; } } } LOG (GNUNET_ERROR_TYPE_DEBUG, "UNIX transmit %u-byte message to %s (%d: %s)\n", (unsigned int) msgbuf_size, GNUNET_a2s ((const struct sockaddr *)un, un_len), (int) sent, (sent < 0) ? STRERROR (errno) : "ok"); GNUNET_free (un); return sent; } /** * Closure for 'get_session_it'. */ struct GetSessionIteratorContext { /** * Location to store the session, if found. */ struct Session *res; /** * Address information. */ const struct GNUNET_HELLO_Address *address; }; /** * Function called to find a session by address. * * @param cls the 'struct LookupCtx' * @param key peer we are looking for (unused) * @param value a session * @return #GNUNET_YES if not found (continue looking), #GNUNET_NO on success */ static int get_session_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GetSessionIteratorContext *gsi = cls; struct Session *s = value; if (0 == GNUNET_HELLO_address_cmp(s->address, gsi->address)) { gsi->res = s; return GNUNET_NO; } return GNUNET_YES; } /** * Session was idle for too long, so disconnect it * * @param cls the 'struct Session' to disconnect * @param tc scheduler context */ static void session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *s = cls; s->timeout_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Session %p was idle for %s, disconnecting\n", s, GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_YES)); unix_session_disconnect (s->plugin, s); } /** * Function obtain the network type for a session * * @param cls closure ('struct Plugin*') * @param session the session * @return the network type in HBO or #GNUNET_SYSERR */ static enum GNUNET_ATS_Network_Type unix_get_network (void *cls, struct Session *session) { GNUNET_assert (NULL != session); return GNUNET_ATS_NET_LOOPBACK; } /** * Creates a new outbound session the transport service will use to send data to the * peer * * @param cls the plugin * @param address the address * @return the session or NULL of max connections exceeded */ static struct Session * unix_plugin_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct Plugin *plugin = cls; struct Session *s; struct GetSessionIteratorContext gsi; struct UnixAddress *ua; char * addrstr; uint32_t addr_str_len; uint32_t addr_option; GNUNET_assert (NULL != plugin); GNUNET_assert (NULL != address); ua = (struct UnixAddress *) address->address; if ((NULL == address->address) || (0 == address->address_length) || (sizeof (struct UnixAddress) > address->address_length)) { GNUNET_break (0); return NULL; } addrstr = (char *) &ua[1]; addr_str_len = ntohl (ua->addrlen); addr_option = ntohl (ua->options); if ( (0 != (UNIX_OPTIONS_USE_ABSTRACT_SOCKETS & addr_option)) && (GNUNET_NO == plugin->abstract)) { return NULL; } if (addr_str_len != address->address_length - sizeof (struct UnixAddress)) { return NULL; /* This can be a legacy address */ } if ('\0' != addrstr[addr_str_len - 1]) { GNUNET_break (0); return NULL; } if (strlen (addrstr) + 1 != addr_str_len) { GNUNET_break (0); return NULL; } /* Check if already existing */ gsi.address = address; gsi.res = NULL; GNUNET_CONTAINER_multipeermap_get_multiple (plugin->session_map, &address->peer, &get_session_it, &gsi); if (NULL != gsi.res) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p for address `%s'\n", gsi.res, unix_address_to_string (NULL, address->address, address->address_length)); return gsi.res; } /* create a new session */ s = GNUNET_new (struct Session); s->target = address->peer; s->address = GNUNET_HELLO_address_copy (address); s->plugin = plugin; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, s); LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating a new session %p for address `%s'\n", s, unix_address_to_string (NULL, address->address, address->address_length)); (void) GNUNET_CONTAINER_multipeermap_put (plugin->session_map, &address->peer, s, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GNUNET_STATISTICS_set (plugin->env->stats, "# UNIX sessions active", GNUNET_CONTAINER_multipeermap_size (plugin->session_map), GNUNET_NO); return s; } static void unix_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { struct Plugin *plugin = cls; if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_contains_value (plugin->session_map, &session->target, session)) return; reschedule_session_timeout (session); } /** * Function that can be used by the transport service to transmit * a message using the plugin. Note that in the case of a * peer disconnecting, the continuation MUST be called * prior to the disconnect notification itself. This function * will be called with this peer's HELLO message to initiate * a fresh connection to another peer. * * @param cls closure * @param session which session must be used * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in @a msgbuf * @param priority how important is the message (most plugins will * ignore message priority and just FIFO) * @param to how long to wait at most for the transmission (does not * require plugins to discard the message after the timeout, * just advisory for the desired delay; most plugins will ignore * this as well) * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...); can be NULL * @param cont_cls closure for @a cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t unix_plugin_send (void *cls, struct Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative to, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin *plugin = cls; struct UNIXMessageWrapper *wrapper; struct UNIXMessage *message; int ssize; if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_contains_value (plugin->session_map, &session->target, session)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Invalid session for peer `%s' `%s'\n", GNUNET_i2s (&session->target), unix_address_to_string(NULL, session->address->address, session->address->address_length)); GNUNET_break (0); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending %u bytes with session for peer `%s' `%s'\n", msgbuf_size, GNUNET_i2s (&session->target), unix_address_to_string(NULL, session->address->address, session->address->address_length)); ssize = sizeof (struct UNIXMessage) + msgbuf_size; message = GNUNET_malloc (sizeof (struct UNIXMessage) + msgbuf_size); message->header.size = htons (ssize); message->header.type = htons (0); memcpy (&message->sender, plugin->env->my_identity, sizeof (struct GNUNET_PeerIdentity)); memcpy (&message[1], msgbuf, msgbuf_size); wrapper = GNUNET_new (struct UNIXMessageWrapper); wrapper->msg = message; wrapper->msgsize = ssize; wrapper->payload = msgbuf_size; wrapper->priority = priority; wrapper->timeout = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), to); wrapper->cont = cont; wrapper->cont_cls = cont_cls; wrapper->session = session; GNUNET_CONTAINER_DLL_insert (plugin->msg_head, plugin->msg_tail, wrapper); plugin->bytes_in_queue += ssize; GNUNET_STATISTICS_set (plugin->env->stats, "# bytes currently in UNIX buffers", plugin->bytes_in_queue, GNUNET_NO); if (GNUNET_NO == plugin->with_ws) reschedule_select (plugin); return ssize; } /** * Demultiplexer for UNIX messages * * @param plugin the main plugin for this transport * @param sender from which peer the message was received * @param currhdr pointer to the header of the message * @param ua address to look for * @param ua_len length of the address @a ua */ static void unix_demultiplexer (struct Plugin *plugin, struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *currhdr, const struct UnixAddress *ua, size_t ua_len) { struct Session *s = NULL; struct GNUNET_HELLO_Address *address; GNUNET_break (ntohl(plugin->ats_network.value) != GNUNET_ATS_NET_UNSPECIFIED); GNUNET_assert (ua_len >= sizeof (struct UnixAddress)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message from %s\n", unix_address_to_string(NULL, ua, ua_len)); GNUNET_STATISTICS_update (plugin->env->stats, "# bytes received via UNIX", ntohs (currhdr->size), GNUNET_NO); /* Look for existing session */ address = GNUNET_HELLO_address_allocate (sender, PLUGIN_NAME, ua, ua_len, GNUNET_HELLO_ADDRESS_INFO_NONE); /* UNIX does not have "inbound" sessions */ s = lookup_session (plugin, address); if (NULL == s) { s = unix_plugin_get_session (plugin, address); /* Notify transport and ATS about new inbound session */ plugin->env->session_start (NULL, s->address, s, &plugin->ats_network, 1); } GNUNET_HELLO_address_free (address); reschedule_session_timeout (s); plugin->env->receive (plugin->env->cls, s->address, s, currhdr); plugin->env->update_address_metrics (plugin->env->cls, s->address, s, &plugin->ats_network, 1); } /** * Read from UNIX domain socket (it is ready). * * @param plugin the plugin */ static void unix_plugin_select_read (struct Plugin *plugin) { char buf[65536] GNUNET_ALIGN; struct UnixAddress *ua; struct UNIXMessage *msg; struct GNUNET_PeerIdentity sender; struct sockaddr_un un; socklen_t addrlen; ssize_t ret; int offset; int tsize; int is_abstract; char *msgbuf; const struct GNUNET_MessageHeader *currhdr; uint16_t csize; size_t ua_len; addrlen = sizeof (un); memset (&un, 0, sizeof (un)); ret = GNUNET_NETWORK_socket_recvfrom (plugin->unix_sock.desc, buf, sizeof (buf), (struct sockaddr *) &un, &addrlen); if ((GNUNET_SYSERR == ret) && ((errno == EAGAIN) || (errno == ENOBUFS))) return; if (ret == GNUNET_SYSERR) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom"); return; } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Read %d bytes from socket %s\n", (int) ret, un.sun_path); } GNUNET_assert (AF_UNIX == (un.sun_family)); is_abstract = GNUNET_NO; if ('\0' == un.sun_path[0]) { un.sun_path[0] = '@'; is_abstract = GNUNET_YES; } ua_len = sizeof (struct UnixAddress) + strlen (un.sun_path) + 1; ua = GNUNET_malloc (ua_len); ua->addrlen = htonl (strlen (&un.sun_path[0]) +1); memcpy (&ua[1], &un.sun_path[0], strlen (un.sun_path) + 1); if (is_abstract) ua->options = htonl(UNIX_OPTIONS_USE_ABSTRACT_SOCKETS); else ua->options = htonl(UNIX_OPTIONS_NONE); msg = (struct UNIXMessage *) buf; csize = ntohs (msg->header.size); if ((csize < sizeof (struct UNIXMessage)) || (csize > ret)) { GNUNET_break_op (0); GNUNET_free (ua); return; } msgbuf = (char *) &msg[1]; memcpy (&sender, &msg->sender, sizeof (struct GNUNET_PeerIdentity)); offset = 0; tsize = csize - sizeof (struct UNIXMessage); while (offset + sizeof (struct GNUNET_MessageHeader) <= tsize) { currhdr = (struct GNUNET_MessageHeader *) &msgbuf[offset]; csize = ntohs (currhdr->size); if ((csize < sizeof (struct GNUNET_MessageHeader)) || (csize > tsize - offset)) { GNUNET_break_op (0); break; } unix_demultiplexer (plugin, &sender, currhdr, ua, ua_len); offset += csize; } GNUNET_free (ua); } /** * Write to UNIX domain socket (it is ready). * * @param plugin the plugin */ static void unix_plugin_select_write (struct Plugin *plugin) { int sent = 0; struct UNIXMessageWrapper * msgw; while (NULL != (msgw = plugin->msg_tail)) { if (GNUNET_TIME_absolute_get_remaining (msgw->timeout).rel_value_us > 0) break; /* Message is ready for sending */ /* Message has a timeout */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout for message with %u bytes \n", (unsigned int) msgw->msgsize); GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw); plugin->bytes_in_queue -= msgw->msgsize; GNUNET_STATISTICS_set (plugin->env->stats, "# bytes currently in UNIX buffers", plugin->bytes_in_queue, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UNIX bytes discarded", msgw->msgsize, GNUNET_NO); if (NULL != msgw->cont) msgw->cont (msgw->cont_cls, &msgw->session->target, GNUNET_SYSERR, msgw->payload, 0); GNUNET_free (msgw->msg); GNUNET_free (msgw); } if (NULL == msgw) return; /* Nothing to send at the moment */ sent = unix_real_send (plugin, plugin->unix_sock.desc, &msgw->session->target, (const char *) msgw->msg, msgw->msgsize, msgw->priority, msgw->timeout, msgw->session->address->address, msgw->session->address->address_length, msgw->payload, msgw->cont, msgw->cont_cls); if (RETRY == sent) { GNUNET_STATISTICS_update (plugin->env->stats, "# UNIX retry attempts", 1, GNUNET_NO); return; } if (GNUNET_SYSERR == sent) { /* failed and no retry */ if (NULL != msgw->cont) msgw->cont (msgw->cont_cls, &msgw->session->target, GNUNET_SYSERR, msgw->payload, 0); GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, msgw); GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize); plugin->bytes_in_queue -= msgw->msgsize; GNUNET_STATISTICS_set (plugin->env->stats, "# bytes currently in UNIX buffers", plugin->bytes_in_queue, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# UNIX bytes discarded", msgw->msgsize, GNUNET_NO); GNUNET_free (msgw->msg); GNUNET_free (msgw); return; } /* successfully sent bytes */ GNUNET_break (sent > 0); GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw); GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize); plugin->bytes_in_queue -= msgw->msgsize; GNUNET_STATISTICS_set (plugin->env->stats, "# bytes currently in UNIX buffers", plugin->bytes_in_queue, GNUNET_NO); GNUNET_STATISTICS_update (plugin->env->stats, "# bytes transmitted via UNIX", msgw->msgsize, GNUNET_NO); if (NULL != msgw->cont) msgw->cont (msgw->cont_cls, &msgw->session->target, GNUNET_OK, msgw->payload, msgw->msgsize); GNUNET_free (msgw->msg); GNUNET_free (msgw); } /** * We have been notified that our writeset has something to read. We don't * know which socket needs to be read, so we have to check each one * Then reschedule this function to be called again once more is available. * * @param cls the plugin handle * @param tc the scheduling context (for rescheduling this function again) */ static void unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Plugin *plugin = cls; plugin->select_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; if ((tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY) != 0) { /* Ready to send data */ GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->write_ready, plugin->unix_sock.desc)); if (NULL != plugin->msg_head) unix_plugin_select_write (plugin); } if ((tc->reason & GNUNET_SCHEDULER_REASON_READ_READY) != 0) { /* Ready to receive data */ GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, plugin->unix_sock.desc)); unix_plugin_select_read (plugin); } reschedule_select (plugin); } /** * Create a slew of UNIX sockets. If possible, use IPv6 and IPv4. * * @param cls closure for server start, should be a struct Plugin * * @return number of sockets created or #GNUNET_SYSERR on error */ static int unix_transport_server_start (void *cls) { struct Plugin *plugin = cls; struct sockaddr_un *un; socklen_t un_len; un = unix_address_to_sockaddr (plugin->unix_socket_path, &un_len); if (GNUNET_YES == plugin->abstract) { plugin->unix_socket_path[0] = '@'; un->sun_path[0] = '\0'; } plugin->ats_network = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) un, un_len); plugin->unix_sock.desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0); if (NULL == plugin->unix_sock.desc) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); return GNUNET_SYSERR; } if ('\0' != un->sun_path[0]) { if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (un->sun_path)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot create path to `%s'\n"), un->sun_path); GNUNET_NETWORK_socket_close (plugin->unix_sock.desc); plugin->unix_sock.desc = NULL; GNUNET_free (un); return GNUNET_SYSERR; } } if (GNUNET_OK != GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc, (const struct sockaddr *) un, un_len)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); GNUNET_NETWORK_socket_close (plugin->unix_sock.desc); plugin->unix_sock.desc = NULL; GNUNET_free (un); return GNUNET_SYSERR; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", plugin->unix_socket_path); plugin->rs = GNUNET_NETWORK_fdset_create (); plugin->ws = GNUNET_NETWORK_fdset_create (); GNUNET_NETWORK_fdset_zero (plugin->rs); GNUNET_NETWORK_fdset_zero (plugin->ws); GNUNET_NETWORK_fdset_set (plugin->rs, plugin->unix_sock.desc); GNUNET_NETWORK_fdset_set (plugin->ws, plugin->unix_sock.desc); reschedule_select (plugin); GNUNET_free (un); return 1; } /** * Function that will be called to check if a binary address for this * plugin is well-formed and corresponds to an address for THIS peer * (as per our configuration). Naturally, if absolutely necessary, * plugins can be a bit conservative in their answer, but in general * plugins should make sure that the address does not redirect * traffic to a 3rd party that might try to man-in-the-middle our * traffic. * * @param cls closure, should be our handle to the Plugin * @param addr pointer to the address * @param addrlen length of addr * @return GNUNET_OK if this is a plausible address for this peer * and transport, GNUNET_SYSERR if not * */ static int unix_check_address (void *cls, const void *addr, size_t addrlen) { struct Plugin* plugin = cls; struct UnixAddress *ua = (struct UnixAddress *) addr; char *addrstr; size_t addr_str_len; if ((NULL == addr) || (0 == addrlen) || (sizeof (struct UnixAddress) > addrlen)) { GNUNET_break (0); return GNUNET_SYSERR; } addrstr = (char *) &ua[1]; addr_str_len = ntohl (ua->addrlen); if ('\0' != addrstr[addr_str_len - 1]) { GNUNET_break (0); return GNUNET_SYSERR; } if (strlen (addrstr) + 1 != addr_str_len) { GNUNET_break (0); return GNUNET_SYSERR; } if (0 == strcmp (plugin->unix_socket_path, addrstr)) return GNUNET_OK; return GNUNET_SYSERR; } /** * Convert the transports address to a nice, human-readable * format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the @a addr * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for @a asc */ static void unix_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { if ((NULL != addr) && (addrlen > 0)) { asc (asc_cls, unix_address_to_string (NULL, addr, addrlen)); } else if (0 == addrlen) { asc (asc_cls, TRANSPORT_SESSION_INBOUND_STRING); } else { GNUNET_break (0); asc (asc_cls, ""); } asc (asc_cls, NULL); } /** * Function called to convert a string address to * a binary address. * * @param cls closure ('struct Plugin*') * @param addr string address * @param addrlen length of the @a addr (strlen(addr) + '\0') * @param buf location to store the buffer * If the function returns #GNUNET_SYSERR, its contents are undefined. * @param added length of created address * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static int unix_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added) { struct UnixAddress *ua; char *address; char *plugin; char *optionstr; uint32_t options; size_t ua_size; /* Format unix.options.address */ address = NULL; plugin = NULL; optionstr = NULL; if ((NULL == addr) || (addrlen == 0)) { GNUNET_break (0); return GNUNET_SYSERR; } if ('\0' != addr[addrlen - 1]) { GNUNET_break (0); return GNUNET_SYSERR; } if (strlen (addr) != addrlen - 1) { GNUNET_break (0); return GNUNET_SYSERR; } plugin = GNUNET_strdup (addr); optionstr = strchr (plugin, '.'); if (NULL == optionstr) { GNUNET_break (0); GNUNET_free (plugin); return GNUNET_SYSERR; } optionstr[0] = '\0'; optionstr++; options = atol (optionstr); address = strchr (optionstr, '.'); if (NULL == address) { GNUNET_break (0); GNUNET_free (plugin); return GNUNET_SYSERR; } address[0] = '\0'; address++; if (0 != strcmp(plugin, PLUGIN_NAME)) { GNUNET_break (0); GNUNET_free (plugin); return GNUNET_SYSERR; } ua_size = sizeof (struct UnixAddress) + strlen (address) + 1; ua = GNUNET_malloc (ua_size); ua->options = htonl (options); ua->addrlen = htonl (strlen (address) + 1); memcpy (&ua[1], address, strlen (address) + 1); GNUNET_free (plugin); (*buf) = ua; (*added) = ua_size; return GNUNET_OK; } /** * Notify transport service about address * * @param cls the plugin * @param tc unused */ static void address_notification (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Plugin *plugin = cls; struct GNUNET_HELLO_Address *address; size_t len; struct UnixAddress *ua; char *unix_path; len = sizeof (struct UnixAddress) + strlen (plugin->unix_socket_path) + 1; ua = GNUNET_malloc (len); ua->options = htonl (plugin->myoptions); ua->addrlen = htonl(strlen (plugin->unix_socket_path) + 1); unix_path = (char *) &ua[1]; memcpy (unix_path, plugin->unix_socket_path, strlen (plugin->unix_socket_path) + 1); plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK; address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, ua, len, GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->notify_address (plugin->env->cls, GNUNET_YES, address); GNUNET_free (ua); GNUNET_free (address); } /** * Increment session timeout due to activity * * @param s session for which the timeout should be rescheduled */ static void reschedule_session_timeout (struct Session *s) { GNUNET_assert (NULL != s); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task); GNUNET_SCHEDULER_cancel (s->timeout_task); s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, s); LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p set to %s\n", s, GNUNET_STRINGS_relative_time_to_string (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_YES)); } /** * Function called on sessions to disconnect * * @param cls the plugin * @param key peer identity (unused) * @param value the 'struct Session' to disconnect * @return #GNUNET_YES (always, continue to iterate) */ static int get_session_delete_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct Plugin *plugin = cls; struct Session *s = value; unix_session_disconnect (plugin, s); return GNUNET_YES; } /** * Disconnect from a remote node. Clean up session if we have one for this peer * * @param cls closure for this call (should be handle to Plugin) * @param target the peeridentity of the peer to disconnect * @return #GNUNET_OK on success, #GNUNET_SYSERR if the operation failed */ static void unix_peer_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) { struct Plugin *plugin = cls; GNUNET_assert (plugin != NULL); GNUNET_CONTAINER_multipeermap_get_multiple (plugin->session_map, target, &get_session_delete_it, plugin); } /** * The exported method. Initializes the plugin and returns a * struct with the callbacks. * * @param cls the plugin's execution environment * @return NULL on error, plugin functions otherwise */ void * libgnunet_plugin_transport_unix_init (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *plugin; int sockets_created; if (NULL == env->receive) { /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully initialze the plugin or the API */ api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = NULL; api->address_pretty_printer = &unix_plugin_address_pretty_printer; api->address_to_string = &unix_address_to_string; api->string_to_address = &unix_string_to_address; return api; } plugin = GNUNET_new (struct Plugin); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(env->cfg, "transport-unix", "UNIXPATH", &plugin->unix_socket_path)) { LOG (GNUNET_ERROR_TYPE_ERROR, _("No UNIXPATH given in configuration!\n")); GNUNET_free (plugin); return NULL; } plugin->env = env; /* Initialize my flags */ #ifdef LINUX plugin->abstract = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "testing", "USE_ABSTRACT_SOCKETS"); #endif plugin->myoptions = UNIX_OPTIONS_NONE; if (GNUNET_YES == plugin->abstract) { plugin->myoptions = UNIX_OPTIONS_USE_ABSTRACT_SOCKETS; } api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = plugin; api->get_session = &unix_plugin_get_session; api->send = &unix_plugin_send; api->disconnect_peer = &unix_peer_disconnect; api->disconnect_session = &unix_session_disconnect; api->query_keepalive_factor = &unix_query_keepalive_factor; api->address_pretty_printer = &unix_plugin_address_pretty_printer; api->address_to_string = &unix_address_to_string; api->check_address = &unix_check_address; api->string_to_address = &unix_string_to_address; api->get_network = &unix_get_network; api->update_session_timeout = &unix_plugin_update_session_timeout; sockets_created = unix_transport_server_start (plugin); if ((0 == sockets_created) || (GNUNET_SYSERR == sockets_created)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UNIX listen socket\n")); GNUNET_free (api); GNUNET_free (plugin->unix_socket_path); GNUNET_free (plugin); return NULL; } plugin->session_map = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); plugin->address_update_task = GNUNET_SCHEDULER_add_now (&address_notification, plugin); return api; } /** * Shutdown the plugin. * * @param cls the plugin API returned from the initialization function * @return NULL (always) */ void * libgnunet_plugin_transport_unix_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; struct GNUNET_HELLO_Address *address; struct UNIXMessageWrapper * msgw; struct UnixAddress *ua; size_t len; if (NULL == plugin) { GNUNET_free (api); return NULL; } len = sizeof (struct UnixAddress) + strlen (plugin->unix_socket_path) + 1; ua = GNUNET_malloc (len); ua->options = htonl (plugin->myoptions); ua->addrlen = htonl(strlen (plugin->unix_socket_path) + 1); memcpy (&ua[1], plugin->unix_socket_path, strlen (plugin->unix_socket_path) + 1); address = GNUNET_HELLO_address_allocate (plugin->env->my_identity, PLUGIN_NAME, ua, len, GNUNET_HELLO_ADDRESS_INFO_NONE); plugin->env->notify_address (plugin->env->cls, GNUNET_NO, address); GNUNET_free (address); GNUNET_free (ua); while (NULL != (msgw = plugin->msg_head)) { GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw); if (msgw->cont != NULL) msgw->cont (msgw->cont_cls, &msgw->session->target, GNUNET_SYSERR, msgw->payload, 0); GNUNET_free (msgw->msg); GNUNET_free (msgw); } if (GNUNET_SCHEDULER_NO_TASK != plugin->select_task) { GNUNET_SCHEDULER_cancel (plugin->select_task); plugin->select_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != plugin->address_update_task) { GNUNET_SCHEDULER_cancel (plugin->address_update_task); plugin->address_update_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != plugin->unix_sock.desc) { GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->unix_sock.desc)); plugin->unix_sock.desc = NULL; plugin->with_ws = GNUNET_NO; } GNUNET_CONTAINER_multipeermap_iterate (plugin->session_map, &get_session_delete_it, plugin); GNUNET_CONTAINER_multipeermap_destroy (plugin->session_map); if (NULL != plugin->rs) GNUNET_NETWORK_fdset_destroy (plugin->rs); if (NULL != plugin->ws) GNUNET_NETWORK_fdset_destroy (plugin->ws); GNUNET_free (plugin->unix_socket_path); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_transport_unix.c */ gnunet-0.10.1/src/transport/test_transport_api_timeout_http_peer1.conf0000644000175000017500000000135212225230043023323 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-http-p1/ [nat] [transport-http_client] [arm] PORT = 12085 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12084 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12083 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12082 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12081 PLUGINS = http_client #BINARY = .libs/gnunet-service-transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock #PREFIX = valgrind --leak-check=full #PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args gnunet-0.10.1/src/transport/test_transport_api_unreliability_wlan_peer1.conf0000644000175000017500000000110112225230043024463 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-wlan-p1/ [transport-wlan] TESTMODE = 1 [arm] PORT = 12164 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12163 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12162 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12161 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12160 PLUGINS = wlan UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_manipulation_send_tcp_peer2.conf0000644000175000017500000000114712225230043025160 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-tcp-p2/ [transport-tcp] PORT = 12015 TIMEOUT = 5 s [arm] PORT = 12014 DEFAULTSERVICES = transport UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12013 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12012 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12011 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12010 PLUGINS = tcp UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_testing_restart.c0000644000175000017500000001021012225777502021400 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_testing_restart.c * @brief test case for transport testing library: * start the peer, get the HELLO message, restart and stop the peer * */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) GNUNET_SCHEDULER_TaskIdentifier timeout_task; static struct PeerContext *p; struct GNUNET_TRANSPORT_TESTING_handle *tth; static int ret = 0; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (timeout_task); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); GNUNET_TRANSPORT_TESTING_done (tth); } static void end_badly () { timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (NULL != p) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); if (NULL != tth) GNUNET_TRANSPORT_TESTING_done (tth); ret = GNUNET_SYSERR; } static void restart_cb (struct PeerContext *p, void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') successfully restarted\n", p->no, GNUNET_i2s (&p->id)); ret = 0; GNUNET_SCHEDULER_add_now (&end, NULL); } static void restart_task () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') restarting, \n", p->no, GNUNET_i2s (&p->id)); GNUNET_TRANSPORT_TESTING_restart_peer (tth, p, NULL, restart_cb, p); } static void start_cb (struct PeerContext *p, void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') successfully started\n", p->no, GNUNET_i2s (&p->id)); GNUNET_SCHEDULER_add_now (&restart_task, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { ret = 1; tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_assert (NULL != tth); timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &end_badly, NULL); p = GNUNET_TRANSPORT_TESTING_start_peer(tth, cfgfile, 1, NULL, /* receive cb */ NULL, /* connect cb */ NULL, /* disconnect cb */ start_cb, /* startup cb */ NULL); /* closure */ if (NULL == p) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to start peer\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); } } int main (int argc, char *argv[]) { GNUNET_log_setup ("test_transport_testing_restart", "WARNING", NULL); char *const argv_1[] = { "test_transport_testing_restart", "-c", "test_transport_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run ((sizeof (argv_1) / sizeof (char *)) - 1, argv_1, "test_transport_testing_restart", "nohelp", options, &run, &ret); return ret; } /* end of test_transport_testing_restart.c */ gnunet-0.10.1/src/transport/test_transport_api_reliability_http_peer1.conf0000644000175000017500000000117712225230043024153 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-http-p1/ [transport-http_client] [transport-tcp] TIMEOUT = 5 s [transport-http] PORT = 12180 [arm] PORT = 12185 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12184 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-statistics.sock [resolver] PORT = 12183 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12182 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12181 PLUGINS = http_client UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock gnunet-0.10.1/src/transport/test_transport_testing_startstop.c0000644000175000017500000000723112225777502021770 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_testing_startstop.c * @brief test case for transport testing library: * start the peer, get the HELLO message and stop the peer * */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) GNUNET_SCHEDULER_TaskIdentifier timeout_task; static struct PeerContext *p; struct GNUNET_TRANSPORT_TESTING_handle *tth; static int ret = 0; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (timeout_task); GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); GNUNET_TRANSPORT_TESTING_done (tth); } static void end_badly () { timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n"); if (NULL != p) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p); if (NULL != tth) GNUNET_TRANSPORT_TESTING_done (tth); ret = GNUNET_SYSERR; } static void start_cb (struct PeerContext *p, void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') successfully started\n", p->no, GNUNET_i2s (&p->id)); ret = 0; GNUNET_SCHEDULER_add_now (&end, NULL); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { ret = 1; tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_assert (NULL != tth); timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &end_badly, NULL); p = GNUNET_TRANSPORT_TESTING_start_peer(tth, cfgfile, 1, NULL, /* receive cb */ NULL, /* connect cb */ NULL, /* disconnect cb */ start_cb, /* startup cb */ NULL); /* closure */ if (NULL == p) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to start peer\n"); if (timeout_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); } } int main (int argc, char *argv[]) { GNUNET_log_setup ("test_transport_testing_startstop", "WARNING", NULL); char *const argv_1[] = { "test_transport_testing", "-c", "test_transport_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run ((sizeof (argv_1) / sizeof (char *)) - 1, argv_1, "test_transport_testing_startstop", "nohelp", options, &run, &ret); return ret; } /* end of test_transport_testing_startstop.c */ gnunet-0.10.1/src/transport/test_quota_compliance_bluetooth_asymmetric_peer2.conf0000644000175000017500000000114012225230043025472 00000000000000@INLINE@ template_cfg_peer2.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-transport/api-bluetooth-p2/ [transport-bluetooth] INTERFACE = hci1 TESTMODE = 2 [arm] PORT = 12174 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 12173 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 12172 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 12171 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 12170 PLUGINS = bluetooth UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock gnunet-0.10.1/src/transport/test_transport_api_monitoring.c0000644000175000017500000003351412274162761021210 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_transport_api.c * @brief base test case for transport implementations * * This test case serves as a base for tcp, udp, and udp-nat * transport test cases. Based on the executable being run * the correct test case will be performed. Conservation of * C code apparently. */ #include "platform.h" #include "gnunet_transport_service.h" #include "transport-testing.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) /** * How long until we give up on transmitting the message? */ #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) #define TEST_MESSAGE_SIZE 2600 #define TEST_MESSAGE_TYPE 12345 static char *test_source; static char *test_plugin; static char *test_name; static int ok; static int s_started; static int s_connected; static int s_sending; static GNUNET_SCHEDULER_TaskIdentifier die_task; static GNUNET_SCHEDULER_TaskIdentifier send_task; static struct PeerContext *p1; static struct PeerContext *p2; static GNUNET_TRANSPORT_TESTING_ConnectRequest cc; static struct GNUNET_TRANSPORT_TransmitHandle *th; static struct GNUNET_TRANSPORT_TESTING_handle *tth; static char *cfg_file_p1; static char *cfg_file_p2; static struct GNUNET_TRANSPORT_PeerMonitoringContext *pmc_p1; static struct GNUNET_TRANSPORT_PeerMonitoringContext *pmc_p2; static int p1_c = GNUNET_NO; static int p2_c = GNUNET_NO; static int p1_c_notify = GNUNET_NO; static int p2_c_notify = GNUNET_NO; static void end () { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (die_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_NO_TASK; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; if (NULL != p1) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); p1 = NULL; if (NULL != p2) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); p2 = NULL; if (NULL != pmc_p1) { GNUNET_TRANSPORT_monitor_peers_cancel (pmc_p1); pmc_p1 = NULL; } if (NULL != pmc_p2) { GNUNET_TRANSPORT_monitor_peers_cancel (pmc_p2); pmc_p2 = NULL; } ok = 0; } static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { die_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Fail! Stopping peers\n"); if (send_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (send_task); if (cc != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n")); GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc); cc = NULL; } if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); if (s_started == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started \n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started \n")); if (s_connected == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not connected\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were connected\n")); if (s_sending == GNUNET_NO) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n")); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were ready to send data\n")); th = NULL; if (NULL != pmc_p1) { GNUNET_TRANSPORT_monitor_peers_cancel (pmc_p1); pmc_p1 = NULL; } if (NULL != pmc_p2) { GNUNET_TRANSPORT_monitor_peers_cancel (pmc_p2); pmc_p2 = NULL; } if (p1 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 1 was not started\n")); if (p2 != NULL) GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer 2 was not started\n")); ok = GNUNET_SYSERR; } static void notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) t = p1; if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) t = p2; GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s') received message of type %d and size %u size from peer %u (`%4s')!\n", p->no, ps, ntohs (message->type), ntohs (message->size), t->no, GNUNET_i2s (&t->id)); GNUNET_free (ps); } static size_t notify_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *hdr; th = NULL; if (buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout occurred while waiting for transmit_ready\n"); if (GNUNET_SCHEDULER_NO_TASK != die_task) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); ok = 42; return 0; } GNUNET_assert (size >= TEST_MESSAGE_SIZE); if (buf != NULL) { memset (buf, '\0', TEST_MESSAGE_SIZE); hdr = buf; hdr->size = htons (TEST_MESSAGE_SIZE); hdr->type = htons (TEST_MESSAGE_TYPE); } char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s') sending message with type %u and size %u bytes to peer %u (`%4s')\n", p2->no, ps, ntohs (hdr->type), ntohs (hdr->size), p->no, GNUNET_i2s (&p->id)); GNUNET_free (ps); return TEST_MESSAGE_SIZE; } static void sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { send_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; char *receiver_s = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending message from peer %u (`%4s') -> peer %u (`%s') !\n", p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s); GNUNET_free (receiver_s); s_sending = GNUNET_YES; th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, TIMEOUT_TRANSMIT, ¬ify_ready, p1); } static void done () { if ((GNUNET_YES == p1_c) && (GNUNET_YES == p2_c) && p1_c_notify && p2_c_notify) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Both peers state to be connected\n"); ok = 0; end(); } } static void notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { static int c; c++; struct PeerContext *p = cls; struct PeerContext *t = NULL; if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))) { p1_c_notify = GNUNET_YES; t = p1; } if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))) { p2_c_notify = GNUNET_YES; t = p2; } GNUNET_assert (t != NULL); char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s'): peer %u (`%s') connected to me!\n", p->no, ps, t->no, GNUNET_i2s (peer)); if (p1_c_notify && p2_c_notify) GNUNET_SCHEDULER_add_now(&done, NULL); GNUNET_free (ps); } static void notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *p = cls; char *ps = GNUNET_strdup (GNUNET_i2s (&p->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%4s'): peer (`%s') disconnected from me!\n", p->no, ps, GNUNET_i2s (peer)); GNUNET_free (ps); if (th != NULL) GNUNET_TRANSPORT_notify_transmit_ready_cancel (th); th = NULL; } static void testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls) { cc = NULL; char *p1_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peers connected: %u (%s) <-> %u (%s)\n", p1->no, p1_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (p1_c); s_connected = GNUNET_YES; send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL); } static void start_cb (struct PeerContext *p, void *cls) { static int started; started++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u (`%s') started\n", p->no, GNUNET_i2s (&p->id)); if (started != 2) return; else s_started = GNUNET_YES; char *sender_c = GNUNET_strdup (GNUNET_i2s (&p1->id)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n", p1->no, sender_c, p2->no, GNUNET_i2s (&p2->id)); GNUNET_free (sender_c); cc = GNUNET_TRANSPORT_TESTING_connect_peers (tth, p1, p2, &testing_connect_cb, NULL); } static void monitor1_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { if ((NULL == peer) || (NULL == p1)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Monitor 1: %s %s %s\n", GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s(state), GNUNET_STRINGS_absolute_time_to_string(state_timeout)); if ((0 == memcmp (peer, &p2->id, sizeof (p2->id)) && (GNUNET_YES == GNUNET_TRANSPORT_is_connected(state)) && GNUNET_NO == p1_c) ) { p1_c = GNUNET_YES; GNUNET_SCHEDULER_add_now (&done, NULL); } } static void monitor2_cb (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout) { if ((NULL == peer) || (NULL == p2)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Monitor 2: %s %s %s\n", GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s (state), GNUNET_STRINGS_absolute_time_to_string(state_timeout)); if ((0 == memcmp (peer, &p1->id, sizeof (p1->id)) && (GNUNET_YES == GNUNET_TRANSPORT_is_connected(state)) && GNUNET_NO == p2_c) ) { p2_c = GNUNET_YES; GNUNET_SCHEDULER_add_now (&done, NULL); } } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); s_started = GNUNET_NO; s_connected = GNUNET_NO; s_sending = GNUNET_NO; p1 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p1, 1, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); pmc_p1 = GNUNET_TRANSPORT_monitor_peers (p1->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor1_cb, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 started\n"); p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2, ¬ify_receive, ¬ify_connect, ¬ify_disconnect, &start_cb, NULL); pmc_p2 = GNUNET_TRANSPORT_monitor_peers (p2->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor2_cb, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 started\n"); if ((p1 == NULL) || (p2 == NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n"); if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL); return; } } static int check () { static char *const argv[] = { "test-transport-api", "-c", "test_transport_api_data.conf", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; send_task = GNUNET_SCHEDULER_NO_TASK; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name, "nohelp", options, &run, &ok); return ok; } int main (int argc, char *argv[]) { int ret; ok = 1; GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name); GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source); GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv[0], test_source, &test_plugin); GNUNET_log_setup (test_name, "WARNING", NULL); tth = GNUNET_TRANSPORT_TESTING_init (); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1); GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p2, 2); ret = check (); GNUNET_free (cfg_file_p1); GNUNET_free (cfg_file_p2); GNUNET_free (test_source); GNUNET_free (test_plugin); GNUNET_free (test_name); GNUNET_TRANSPORT_TESTING_done (tth); if (0 != ret) return ret; else return ok; } /* end of test_transport_api.c */ gnunet-0.10.1/src/transport/test_quota_compliance_https_peer1.conf0000644000175000017500000000122012225230043022370 00000000000000@INLINE@ template_cfg_peer1.conf [PATHS] GNUNET_TEST_HOME = /tmp/test_quota_compliance_peer1/ [transport-https_client] [arm] PORT = 4006 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_arm_peer1.sock [statistics] PORT = 4005 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_statistics_peer1.sock [resolver] PORT = 4004 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_resolver_peer1.sock [peerinfo] PORT = 4003 UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_peerinfo_peer1.sock [transport] PORT = 4002 PLUGINS = https_client UNIXPATH = $GNUNET_RUNTIME_DIR/test_quota_compliance_https_transport_peer1.sock gnunet-0.10.1/src/transport/test_plugin_transport_data.conf0000644000175000017500000000154712255010511021145 00000000000000@INLINE@ test_transport_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunetd-plugin-transport/ [transport-tcp] PORT = 2400 [transport-udp] PORT = 2401 [transport-unix] [transport-wlan] INTERFACE = mon0 TESTMODE = 1 [transport-bluetooth] INTERFACE = hci0 TESTMODE = 1 [transport-http_client] [transport-http_server] PORT = 2402 [transport-https_client] [transport-https_server] PORT = 2403 [arm] PORT = 2360 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-arm.sock [statistics] PORT = 2361 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-statistics.sock [resolver] PORT = 2362 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-resolver.sock [peerinfo] PORT = 2363 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-peerinfo.sock [transport] PORT = 2364 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-transport.sock [nat] RETURN_LOCAL_ADDRESSES = YES DISABLEV6 = NO gnunet-0.10.1/src/transport/gnunet-service-transport_blacklist.c0000644000175000017500000005431012316473377022041 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/gnunet-service-transport_blacklist.c * @brief blacklisting implementation * @author Christian Grothoff, Matthias Wachs * @details This is the blacklisting component of transport service. With * blacklisting it is possible to deny connections to specific peers of * to use a specific plugin to a specific peer. Peers can be blacklisted using * the configuration or a blacklist client can be asked. * * To blacklist peers using the configuration you have to add a section to your * configuration containing the peer id of the peer to blacklist and the plugin * if required. * * Example: * To blacklist connections to P565... on peer AG2P... using tcp add: * [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520] * P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G = tcp * * To blacklist connections to P565... on peer AG2P... using all plugins add: * [transport-blacklist-AG2PHES1BARB9IJCPAMJTFPVJ5V3A72S3F2A8SBUB8DAQ2V0O3V8G6G2JU56FHGFOHMQVKBSQFV98TCGTC3RJ1NINP82G0RC00N1520] * P565723JO1C2HSN6J29TAQ22MN6CI8HTMUU55T0FUQG4CMDGGEQ8UCNBKUMB94GC8R9G4FB2SF9LDOBAJ6AMINBP4JHHDD6L7VD801G = * * You can also add a blacklist client usign the blacklist api. On a blacklist * check, blacklisting first checks internally if the peer is blacklisted and * if not, it asks the blacklisting clients. Clients are asked if it is OK to * connect to a peer ID, the plugin is omitted. * * On blacklist check for (peer, plugin) * - Do we have a local blacklist entry for this peer and this plugin? * - YES: disallow connection * - Do we have a local blacklist entry for this peer and all plugins? * - YES: disallow connection * - Does one of the clients disallow? * - YES: disallow connection * */ #include "platform.h" #include "gnunet-service-transport.h" #include "gnunet-service-transport_blacklist.h" #include "gnunet-service-transport_neighbours.h" #include "transport.h" /** * Size of the blacklist hash map. */ #define TRANSPORT_BLACKLIST_HT_SIZE 64 /** * Context we use when performing a blacklist check. */ struct GST_BlacklistCheck; /** * Information kept for each client registered to perform * blacklisting. */ struct Blacklisters { /** * This is a linked list. */ struct Blacklisters *next; /** * This is a linked list. */ struct Blacklisters *prev; /** * Client responsible for this entry. */ struct GNUNET_SERVER_Client *client; /** * Blacklist check that we're currently performing (or NULL * if we're performing one that has been cancelled). */ struct GST_BlacklistCheck *bc; /** * Set to GNUNET_YES if we're currently waiting for a reply. */ int waiting_for_reply; /** * GNUNET_YES if we have to call receive_done for this client */ int call_receive_done; }; /** * Context we use when performing a blacklist check. */ struct GST_BlacklistCheck { /** * This is a linked list. */ struct GST_BlacklistCheck *next; /** * This is a linked list. */ struct GST_BlacklistCheck *prev; /** * Peer being checked. */ struct GNUNET_PeerIdentity peer; /** * Continuation to call with the result. */ GST_BlacklistTestContinuation cont; /** * Closure for cont. */ void *cont_cls; /** * Current transmission request handle for this client, or NULL if no * request is pending. */ struct GNUNET_SERVER_TransmitHandle *th; /** * Our current position in the blacklisters list. */ struct Blacklisters *bl_pos; /** * Current task performing the check. */ GNUNET_SCHEDULER_TaskIdentifier task; }; /** * Head of DLL of active blacklisting queries. */ static struct GST_BlacklistCheck *bc_head; /** * Tail of DLL of active blacklisting queries. */ static struct GST_BlacklistCheck *bc_tail; /** * Head of DLL of blacklisting clients. */ static struct Blacklisters *bl_head; /** * Tail of DLL of blacklisting clients. */ static struct Blacklisters *bl_tail; /** * Hashmap of blacklisted peers. Values are of type 'char *' (transport names), * can be NULL if we have no static blacklist. */ static struct GNUNET_CONTAINER_MultiPeerMap *blacklist; /** * Perform next action in the blacklist check. * * @param cls the 'struct BlacklistCheck*' * @param tc unused */ static void do_blacklist_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Called whenever a client is disconnected. Frees our * resources associated with that client. * * @param cls closure (unused) * @param client identification of the client */ static void client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) { struct Blacklisters *bl; struct GST_BlacklistCheck *bc; if (client == NULL) return; for (bl = bl_head; bl != NULL; bl = bl->next) { if (bl->client != client) continue; for (bc = bc_head; bc != NULL; bc = bc->next) { if (bc->bl_pos != bl) continue; bc->bl_pos = bl->next; if (bc->th != NULL) { GNUNET_SERVER_notify_transmit_ready_cancel (bc->th); bc->th = NULL; } if (bc->task == GNUNET_SCHEDULER_NO_TASK) bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); } GNUNET_CONTAINER_DLL_remove (bl_head, bl_tail, bl); GNUNET_SERVER_client_drop (bl->client); GNUNET_free (bl); break; } } /** * Function to iterate over options in the blacklisting section for a peer. * * @param cls closure * @param section name of the section * @param option name of the option * @param value value of the option */ static void blacklist_cfg_iter (void *cls, const char *section, const char *option, const char *value) { unsigned int *res = cls; struct GNUNET_PeerIdentity peer; char *plugs; char *pos; if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (option, strlen (option), &peer.public_key)) return; if ((NULL == value) || (0 == strcmp(value, ""))) { /* Blacklist whole peer */ GST_blacklist_add_peer (&peer, NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Adding blacklisting entry for peer `%s'\n"), GNUNET_i2s (&peer)); } else { plugs = GNUNET_strdup (value); for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " ")) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Adding blacklisting entry for peer `%s':`%s'\n"), GNUNET_i2s (&peer), pos); GST_blacklist_add_peer (&peer, pos); } GNUNET_free (plugs); } (*res)++; } /** * Read blacklist configuration * * @param cfg the configuration handle * @param my_id my peer identity */ static void read_blacklist_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *my_id) { char cfg_sect[512]; unsigned int res = 0; GNUNET_snprintf (cfg_sect, sizeof (cfg_sect), "transport-blacklist-%s", GNUNET_i2s_full (my_id)); GNUNET_CONFIGURATION_iterate_section_values (cfg, cfg_sect, &blacklist_cfg_iter, &res); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded %u blacklisting entries from configuration\n", res); } /** * Start blacklist subsystem. * * @param server server used to accept clients from * @param cfg configuration handle * @param my_id my peer id */ void GST_blacklist_start (struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *my_id) { GNUNET_assert (NULL != cfg); GNUNET_assert (NULL != my_id); read_blacklist_configuration (cfg, my_id); GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification, NULL); } /** * Free the given entry in the blacklist. * * @param cls unused * @param key host identity (unused) * @param value the blacklist entry * @return GNUNET_OK (continue to iterate) */ static int free_blacklist_entry (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { char *be = value; GNUNET_free_non_null (be); return GNUNET_OK; } /** * Stop blacklist subsystem. */ void GST_blacklist_stop () { if (NULL != blacklist) { GNUNET_CONTAINER_multipeermap_iterate (blacklist, &free_blacklist_entry, NULL); GNUNET_CONTAINER_multipeermap_destroy (blacklist); blacklist = NULL; } } /** * Transmit blacklist query to the client. * * @param cls the 'struct GST_BlacklistCheck' * @param size number of bytes allowed * @param buf where to copy the message * @return number of bytes copied to buf */ static size_t transmit_blacklist_message (void *cls, size_t size, void *buf) { struct GST_BlacklistCheck *bc = cls; struct Blacklisters *bl; struct BlacklistMessage bm; bc->th = NULL; if (size == 0) { GNUNET_assert (bc->task == GNUNET_SCHEDULER_NO_TASK); bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to send blacklist test for peer `%s' to client\n", GNUNET_i2s (&bc->peer)); return 0; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending blacklist test for peer `%s' to client %p\n", GNUNET_i2s (&bc->peer), bc->bl_pos->client); bl = bc->bl_pos; bm.header.size = htons (sizeof (struct BlacklistMessage)); bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY); bm.is_allowed = htonl (0); bm.peer = bc->peer; memcpy (buf, &bm, sizeof (bm)); if (GNUNET_YES == bl->call_receive_done) { GNUNET_SERVER_receive_done (bl->client, GNUNET_OK); bl->call_receive_done = GNUNET_NO; } bl->waiting_for_reply = GNUNET_YES; return sizeof (bm); } /** * Perform next action in the blacklist check. * * @param cls the 'struct GST_BlacklistCheck*' * @param tc unused */ static void do_blacklist_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GST_BlacklistCheck *bc = cls; struct Blacklisters *bl; bc->task = GNUNET_SCHEDULER_NO_TASK; bl = bc->bl_pos; if (bl == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No other blacklist clients active, will allow neighbour `%s'\n", GNUNET_i2s (&bc->peer)); bc->cont (bc->cont_cls, &bc->peer, GNUNET_OK); GNUNET_CONTAINER_DLL_remove(bc_head, bc_tail, bc); GNUNET_free (bc); return; } if ((bl->bc != NULL) || (bl->waiting_for_reply != GNUNET_NO)) return; /* someone else busy with this client */ bl->bc = bc; bc->th = GNUNET_SERVER_notify_transmit_ready (bl->client, sizeof (struct BlacklistMessage), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_blacklist_message, bc); } /** * Got the result about an existing connection from a new blacklister. * Shutdown the neighbour if necessary. * * @param cls unused * @param peer the neighbour that was investigated * @param allowed GNUNET_OK if we can keep it, * GNUNET_NO if we must shutdown the connection */ static void confirm_or_drop_neighbour (void *cls, const struct GNUNET_PeerIdentity *peer, int allowed) { if (GNUNET_OK == allowed) return; /* we're done */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# disconnects due to blacklist"), 1, GNUNET_NO); GST_neighbours_force_disconnect (peer); } /** * Closure for 'test_connection_ok'. */ struct TestConnectionContext { /** * Is this the first neighbour we're checking? */ int first; /** * Handle to the blacklisting client we need to ask. */ struct Blacklisters *bl; }; /** * Test if an existing connection is still acceptable given a new * blacklisting client. * * @param cls the 'struct TestConnectionContest' * @param peer neighbour's identity * @param address the address * @param state current state this peer is in * @param state_timeout timeout for the current state of the peer * @param bandwidth_in bandwidth assigned inbound * @param bandwidth_out bandwidth assigned outbound */ static void test_connection_ok (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Address *address, enum GNUNET_TRANSPORT_PeerState state, struct GNUNET_TIME_Absolute state_timeout, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) { struct TestConnectionContext *tcc = cls; struct GST_BlacklistCheck *bc; bc = GNUNET_new (struct GST_BlacklistCheck); GNUNET_CONTAINER_DLL_insert(bc_head, bc_tail, bc); bc->peer = *peer; bc->cont = &confirm_or_drop_neighbour; bc->cont_cls = NULL; bc->bl_pos = tcc->bl; if (GNUNET_YES == tcc->first) { /* all would wait for the same client, no need to * create more than just the first task right now */ bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); tcc->first = GNUNET_NO; } } /** * Initialize a blacklisting client. We got a blacklist-init * message from this client, add him to the list of clients * to query for blacklisting. * * @param cls unused * @param client the client * @param message the blacklist-init message that was sent */ void GST_blacklist_handle_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct Blacklisters *bl; struct TestConnectionContext tcc; bl = bl_head; while (bl != NULL) { if (bl->client == client) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } bl = bl->next; } GNUNET_SERVER_client_mark_monitor (client); bl = GNUNET_new (struct Blacklisters); bl->client = client; bl->call_receive_done = GNUNET_YES; GNUNET_SERVER_client_keep (client); GNUNET_CONTAINER_DLL_insert_after (bl_head, bl_tail, bl_tail, bl); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New blacklist client %p\n", client); /* confirm that all existing connections are OK! */ tcc.bl = bl; tcc.first = GNUNET_YES; GST_neighbours_iterate (&test_connection_ok, &tcc); } /** * A blacklisting client has sent us reply. Process it. * * @param cls unused * @param client the client * @param message the blacklist-init message that was sent */ void GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct BlacklistMessage *msg = (const struct BlacklistMessage *) message; struct Blacklisters *bl; struct GST_BlacklistCheck *bc; bl = bl_head; while ((bl != NULL) && (bl->client != client)) bl = bl->next; if (bl == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist client disconnected\n"); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist client %p sent reply for `%s'\n", client, GNUNET_i2s(&msg->peer)); bc = bl->bc; bl->bc = NULL; bl->waiting_for_reply = GNUNET_NO; bl->call_receive_done = GNUNET_YES; /* Remember to call receive_done */ if (NULL != bc) { /* only run this if the blacklist check has not been * cancelled in the meantime... */ if (ntohl (msg->is_allowed) == GNUNET_SYSERR) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist check failed, peer not allowed\n"); bc->cont (bc->cont_cls, &bc->peer, GNUNET_NO); GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc); GNUNET_SERVER_receive_done (bl->client, GNUNET_OK); bl->call_receive_done = GNUNET_NO; GNUNET_free (bc); return; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist check succeeded, continuing with checks\n"); bc->bl_pos = bc->bl_pos->next; bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); } } /* check if any other blacklist checks are waiting for this blacklister */ for (bc = bc_head; bc != NULL; bc = bc->next) if ((bc->bl_pos == bl) && (GNUNET_SCHEDULER_NO_TASK == bc->task)) { bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); break; } } /** * Add the given peer to the blacklist (for the given transport). * * @param peer peer to blacklist * @param transport_name transport to blacklist for this peer, NULL for all */ void GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, const char *transport_name) { char * transport = NULL; if (NULL != transport_name) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding peer `%s' with plugin `%s' to blacklist\n", GNUNET_i2s (peer), transport_name); transport = GNUNET_strdup (transport_name); } else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Adding peer `%s' with all plugins to blacklist\n", GNUNET_i2s (peer)); if (blacklist == NULL) blacklist = GNUNET_CONTAINER_multipeermap_create (TRANSPORT_BLACKLIST_HT_SIZE, GNUNET_NO); GNUNET_CONTAINER_multipeermap_put (blacklist, peer, transport, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } /** * Test if the given blacklist entry matches. If so, * abort the iteration. * * @param cls the transport name to match (const char*) * @param key the key (unused) * @param value the 'char *' (name of a blacklisted transport) * @return #GNUNET_OK if the entry does not match, #GNUNET_NO if it matches */ static int test_blacklisted (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { const char *transport_name = cls; char *be = value; /* Blacklist entry be: * (NULL == be): peer is blacklisted with all plugins * (NULL != be): peer is blacklisted for a specific plugin * * If (NULL != transport_name) we look for a transport specific entry: * if (transport_name == be) forbidden * */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing BL request for peer `%4s':`%s' with BL entry: `%s'\n", GNUNET_i2s (key), (NULL == transport_name) ? "unspecified" : transport_name, (NULL == be) ? "all plugins" : be); /* all plugins for this peer were blacklisted: disallow */ if (NULL == value) return GNUNET_NO; /* blacklist check for specific transport */ if ((NULL != transport_name) && (NULL != value)) { if (0 == strcmp (transport_name, be)) return GNUNET_NO; /* plugin is blacklisted! */ } return GNUNET_OK; } /** * Test if a peer/transport combination is blacklisted. * * @param peer the identity of the peer to test * @param transport_name name of the transport to test, never NULL * @param cont function to call with result * @param cont_cls closure for 'cont' * @return handle to the blacklist check, NULL if the decision * was made instantly and 'cont' was already called */ struct GST_BlacklistCheck * GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer, const char *transport_name, GST_BlacklistTestContinuation cont, void *cont_cls) { struct GST_BlacklistCheck *bc; GNUNET_assert (peer != NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist check for peer `%s':%s\n", GNUNET_i2s (peer), (NULL != transport_name) ? transport_name : "unspecified"); /* Check local blacklist by iterating over hashmap * If iteration is aborted, we found a matching blacklist entry */ if ((blacklist != NULL) && (GNUNET_SYSERR == GNUNET_CONTAINER_multipeermap_get_multiple (blacklist, peer, &test_blacklisted, (void *) transport_name))) { /* Disallowed by config, disapprove instantly */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# disconnects due to blacklist"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disallowing connection to peer `%s' on transport %s\n", GNUNET_i2s (peer), (NULL != transport_name) ? transport_name : "unspecified"); if (cont != NULL) cont (cont_cls, peer, GNUNET_NO); return NULL; } if (bl_head == NULL) { /* no blacklist clients, approve instantly */ if (cont != NULL) cont (cont_cls, peer, GNUNET_OK); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Allowing connection to peer `%s' %s\n", GNUNET_i2s (peer), (NULL != transport_name) ? transport_name : ""); return NULL; } /* need to query blacklist clients */ bc = GNUNET_new (struct GST_BlacklistCheck); GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc); bc->peer = *peer; bc->cont = cont; bc->cont_cls = cont_cls; bc->bl_pos = bl_head; bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); return bc; } /** * Cancel a blacklist check. * * @param bc check to cancel */ void GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc) { GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc); if (bc->bl_pos != NULL) { if (bc->bl_pos->bc == bc) { /* we're at the head of the queue, remove us! */ bc->bl_pos->bc = NULL; } } if (GNUNET_SCHEDULER_NO_TASK != bc->task) { GNUNET_SCHEDULER_cancel (bc->task); bc->task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != bc->th) { GNUNET_SERVER_notify_transmit_ready_cancel (bc->th); bc->th = NULL; } GNUNET_free (bc); } /* end of file gnunet-service-transport_blacklist.c */ gnunet-0.10.1/src/set/0000755000175000017500000000000012320755626011464 500000000000000gnunet-0.10.1/src/set/gnunet-set-ibf-profiler.c0000644000175000017500000001745012225777502016227 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/gnunet-set-ibf-profiler.c * @brief tool for profiling the invertible bloom filter implementation * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "ibf.h" static unsigned int asize = 10; static unsigned int bsize = 10; static unsigned int csize = 10; static unsigned int hash_num = 4; static unsigned int ibf_size = 80; /* FIXME: add parameter for this */ static enum GNUNET_CRYPTO_Quality random_quality = GNUNET_CRYPTO_QUALITY_WEAK; static struct GNUNET_CONTAINER_MultiHashMap *set_a; static struct GNUNET_CONTAINER_MultiHashMap *set_b; /* common elements in a and b */ static struct GNUNET_CONTAINER_MultiHashMap *set_c; static struct GNUNET_CONTAINER_MultiHashMap *key_to_hashcode; static struct InvertibleBloomFilter *ibf_a; static struct InvertibleBloomFilter *ibf_b; static void register_hashcode (struct GNUNET_HashCode *hash) { struct GNUNET_HashCode replicated; struct IBF_Key key; key = ibf_key_from_hashcode (hash); ibf_hashcode_from_key (key, &replicated); GNUNET_CONTAINER_multihashmap_put (key_to_hashcode, &replicated, GNUNET_memdup (hash, sizeof *hash), GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } static void iter_hashcodes (struct IBF_Key key, GNUNET_CONTAINER_HashMapIterator iter, void *cls) { struct GNUNET_HashCode replicated; ibf_hashcode_from_key (key, &replicated); GNUNET_CONTAINER_multihashmap_get_multiple (key_to_hashcode, &replicated, iter, cls); } static int insert_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct InvertibleBloomFilter *ibf = (struct InvertibleBloomFilter *) cls; ibf_insert (ibf, ibf_key_from_hashcode (key)); return GNUNET_YES; } static int remove_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_CONTAINER_MultiHashMap *hashmap = cls; /* if remove fails, there just was a collision with another key */ (void) GNUNET_CONTAINER_multihashmap_remove (hashmap, value, NULL); return GNUNET_YES; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_HashCode id; struct IBF_Key ibf_key; int i; int side; int res; struct GNUNET_TIME_Absolute start_time; struct GNUNET_TIME_Relative delta_time; set_a = GNUNET_CONTAINER_multihashmap_create (((asize == 0) ? 1 : (asize + csize)), GNUNET_NO); set_b = GNUNET_CONTAINER_multihashmap_create (((bsize == 0) ? 1 : (bsize + csize)), GNUNET_NO); set_c = GNUNET_CONTAINER_multihashmap_create (((csize == 0) ? 1 : csize), GNUNET_NO); key_to_hashcode = GNUNET_CONTAINER_multihashmap_create (((asize+bsize+csize == 0) ? 1 : (asize+bsize+csize)), GNUNET_NO); printf ("hash-num=%u, size=%u, #(A-B)=%u, #(B-A)=%u, #(A&B)=%u\n", hash_num, ibf_size, asize, bsize, csize); i = 0; while (i < asize) { GNUNET_CRYPTO_hash_create_random (random_quality, &id); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id)) continue; GNUNET_CONTAINER_multihashmap_put ( set_a, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); register_hashcode (&id); i++; } i = 0; while (i < bsize) { GNUNET_CRYPTO_hash_create_random (random_quality, &id); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id)) continue; if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id)) continue; GNUNET_CONTAINER_multihashmap_put ( set_b, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); register_hashcode (&id); i++; } i = 0; while (i < csize) { GNUNET_CRYPTO_hash_create_random (random_quality, &id); if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_a, &id)) continue; if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_b, &id)) continue; if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (set_c, &id)) continue; GNUNET_CONTAINER_multihashmap_put ( set_c, &id, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); register_hashcode (&id); i++; } ibf_a = ibf_create (ibf_size, hash_num); ibf_b = ibf_create (ibf_size, hash_num); printf ("generated sets\n"); start_time = GNUNET_TIME_absolute_get (); GNUNET_CONTAINER_multihashmap_iterate (set_a, &insert_iterator, ibf_a); GNUNET_CONTAINER_multihashmap_iterate (set_b, &insert_iterator, ibf_b); GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_a); GNUNET_CONTAINER_multihashmap_iterate (set_c, &insert_iterator, ibf_b); delta_time = GNUNET_TIME_absolute_get_duration (start_time); printf ("encoded in: %s\n", GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO)); ibf_subtract (ibf_a, ibf_b); start_time = GNUNET_TIME_absolute_get (); for (i = 0; i <= asize + bsize; i++) { res = ibf_decode (ibf_a, &side, &ibf_key); if (GNUNET_SYSERR == res) { printf ("decode failed, %u/%u elements left\n", GNUNET_CONTAINER_multihashmap_size (set_a) + GNUNET_CONTAINER_multihashmap_size (set_b), asize + bsize); return; } if (GNUNET_NO == res) { if ((0 == GNUNET_CONTAINER_multihashmap_size (set_b)) && (0 == GNUNET_CONTAINER_multihashmap_size (set_a))) { delta_time = GNUNET_TIME_absolute_get_duration (start_time); printf ("decoded successfully in: %s\n", GNUNET_STRINGS_relative_time_to_string (delta_time, GNUNET_NO)); } else { printf ("decode missed elements (should never happen)\n"); } return; } if (side == 1) iter_hashcodes (ibf_key, remove_iterator, set_a); if (side == -1) iter_hashcodes (ibf_key, remove_iterator, set_b); } printf("cyclic IBF, %u/%u elements left\n", GNUNET_CONTAINER_multihashmap_size (set_a) + GNUNET_CONTAINER_multihashmap_size (set_b), asize + bsize); } int main (int argc, char **argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'A', "asize", NULL, gettext_noop ("number of element in set A-B"), 1, &GNUNET_GETOPT_set_uint, &asize}, {'B', "bsize", NULL, gettext_noop ("number of element in set B-A"), 1, &GNUNET_GETOPT_set_uint, &bsize}, {'C', "csize", NULL, gettext_noop ("number of common elements in A and B"), 1, &GNUNET_GETOPT_set_uint, &csize}, {'k', "hash-num", NULL, gettext_noop ("hash num"), 1, &GNUNET_GETOPT_set_uint, &hash_num}, {'s', "ibf-size", NULL, gettext_noop ("ibf size"), 1, &GNUNET_GETOPT_set_uint, &ibf_size}, GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run2 (argc, argv, "gnunet-consensus-ibf", "help", options, &run, NULL, GNUNET_YES); return 0; } gnunet-0.10.1/src/set/set.h0000644000175000017500000001141612234007007012336 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Florian Dold * @file set/set.h * @brief messages used for the set api */ #ifndef SET_H #define SET_H #include "platform.h" #include "gnunet_common.h" #define GNUNET_SET_ACK_WINDOW 10 GNUNET_NETWORK_STRUCT_BEGIN struct GNUNET_SET_CreateMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_CREATE */ struct GNUNET_MessageHeader header; /** * Operation type, values of enum GNUNET_SET_OperationType */ // FIXME: use 32_t for 'enum'. uint16_t operation GNUNET_PACKED; }; struct GNUNET_SET_ListenMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_LISTEN */ struct GNUNET_MessageHeader header; /** * Operation type, values of enum GNUNET_SET_OperationType */ uint32_t operation GNUNET_PACKED; /** * application id */ struct GNUNET_HashCode app_id; }; struct GNUNET_SET_AcceptRejectMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_ACCEPT or * GNUNET_MESSAGE_TYPE_SET_REJECT */ struct GNUNET_MessageHeader header; /** * ID of the incoming request we want to accept / reject. */ uint32_t accept_reject_id GNUNET_PACKED; /** * Request ID to identify responses, * must be 0 if we don't accept the request. */ uint32_t request_id GNUNET_PACKED; /** * How should results be sent to us? * See enum GNUNET_SET_ResultMode. */ uint16_t result_mode GNUNET_PACKED; }; /** * A request for an operation with another client. */ struct GNUNET_SET_RequestMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_Request. */ struct GNUNET_MessageHeader header; /** * Identity of the requesting peer. */ struct GNUNET_PeerIdentity peer_id; /** * ID of the to identify the request when accepting or * rejecting it. */ uint32_t accept_id GNUNET_PACKED; /* rest: nested context message */ }; struct GNUNET_SET_EvaluateMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_EVALUATE */ struct GNUNET_MessageHeader header; /** * id of our evaluate, chosen by the client */ uint32_t request_id GNUNET_PACKED; /** * Peer to evaluate the operation with */ struct GNUNET_PeerIdentity target_peer; /** * Application id */ struct GNUNET_HashCode app_id; /** * Salt to use for the operation */ uint16_t salt GNUNET_PACKED; /** * How should results be sent to us? * See enum GNUNET_SET_ResultMode. */ uint16_t result_mode GNUNET_PACKED; /* rest: inner message */ }; struct GNUNET_SET_ResultMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_RESULT */ struct GNUNET_MessageHeader header; /** * id the result belongs to */ uint32_t request_id GNUNET_PACKED; /** * Was the evaluation successful? */ uint16_t result_status GNUNET_PACKED; /** * Type of the element attachted to the message, * if any. */ uint16_t element_type GNUNET_PACKED; /* rest: the actual element */ }; struct GNUNET_SET_ElementMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_ADD or * GNUNET_MESSAGE_TYPE_SET_REMOVE */ struct GNUNET_MessageHeader header; uint16_t element_type GNUNET_PACKED; uint16_t reserved GNUNET_PACKED; /* rest: the actual element */ }; /** * Sent to the service by the client * in order to cancel a set operation. */ struct GNUNET_SET_CancelMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_CANCEL */ struct GNUNET_MessageHeader header; /** * ID of the request we want to cancel. */ uint32_t request_id GNUNET_PACKED; }; struct GNUNET_SET_IterResponseMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_ITER_RESPONSE */ struct GNUNET_MessageHeader header; /** * Type of the element attachted to the message, * if any. */ uint16_t element_type GNUNET_PACKED; /* rest: element */ }; struct GNUNET_SET_IterAckMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_ITER_ACK */ struct GNUNET_MessageHeader header; /** * Non-zero if the service should continue sending elements. */ uint32_t send_more; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/set/gnunet-service-set_union.c0000644000175000017500000011124212251551532016501 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/gnunet-service-set.c * @brief two-peer set operations * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet-service-set.h" #include "ibf.h" #include "strata_estimator.h" #include "set_protocol.h" #include /** * Number of IBFs in a strata estimator. */ #define SE_STRATA_COUNT 32 /** * Size of the IBFs in the strata estimator. */ #define SE_IBF_SIZE 80 /** * hash num parameter for the difference digests and strata estimators */ #define SE_IBF_HASH_NUM 4 /** * Number of buckets that can be transmitted in one message. */ #define MAX_BUCKETS_PER_MESSAGE ((1<<15) / IBF_BUCKET_SIZE) /** * The maximum size of an ibf we use is 2^(MAX_IBF_ORDER). * Choose this value so that computing the IBF is still cheaper * than transmitting all values. */ #define MAX_IBF_ORDER (16) /** * Number of buckets used in the ibf per estimated * difference. */ #define IBF_ALPHA 4 /** * Current phase we are in for a union operation. */ enum UnionOperationPhase { /** * We sent the request message, and expect a strata estimator */ PHASE_EXPECT_SE, /** * We sent the strata estimator, and expect an IBF. This phase is entered once * upon initialization and later via PHASE_EXPECT_ELEMENTS_AND_REQUESTS. * * After receiving the complete IBF, we enter PHASE_EXPECT_ELEMENTS */ PHASE_EXPECT_IBF, /** * Continuation for multi part IBFs. */ PHASE_EXPECT_IBF_CONT, /** * We are sending request and elements, * and thus only expect elements from the other peer. * * We are currently decoding an IBF until it can no longer be decoded, * we currently send requests and expect elements * The remote peer is in PHASE_EXPECT_ELEMENTS_AND_REQUESTS */ PHASE_EXPECT_ELEMENTS, /** * We are expecting elements and requests, and send * requested elements back to the other peer. * * We are in this phase if we have SENT an IBF for the remote peer to decode. * We expect requests, send elements or could receive an new IBF, which takes * us via PHASE_EXPECT_IBF to phase PHASE_EXPECT_ELEMENTS * * The remote peer is thus in: * PHASE_EXPECT_ELEMENTS */ PHASE_EXPECT_ELEMENTS_AND_REQUESTS, /** * The protocol is over. * Results may still have to be sent to the client. */ PHASE_FINISHED }; /** * State of an evaluate operation * with another peer. */ struct OperationState { /** * Number of ibf buckets received */ unsigned int ibf_buckets_received; /** * Copy of the set's strata estimator at the time of * creation of this operation */ struct StrataEstimator *se; /** * The ibf we currently receive */ struct InvertibleBloomFilter *remote_ibf; /** * IBF of the set's element. */ struct InvertibleBloomFilter *local_ibf; /** * Maps IBF-Keys (specific to the current salt) to elements. * Used as a multihashmap, the keys being the lower 32bit of the IBF-Key. * Colliding IBF-Keys are linked. */ struct GNUNET_CONTAINER_MultiHashMap32 *key_to_element; /** * Iterator for sending elements on the key to element mapping to the client. */ struct GNUNET_CONTAINER_MultiHashMap32Iterator *full_result_iter; /** * Current state of the operation. */ enum UnionOperationPhase phase; /** * Did we send the client that we are done? */ int client_done_sent; }; /** * The key entry is used to associate an ibf key with * an element. */ struct KeyEntry { /** * IBF key for the entry, derived from the current salt. */ struct IBF_Key ibf_key; /** * The actual element associated with the key. */ struct ElementEntry *element; /** * Element that collides with this element * on the ibf key. All colliding entries must have the same ibf key. */ struct KeyEntry *next_colliding; }; /** * Used as a closure for sending elements * with a specific IBF key. */ struct SendElementClosure { /** * The IBF key whose matching elements should be * sent. */ struct IBF_Key ibf_key; /** * Operation for which the elements * should be sent. */ struct Operation *op; }; /** * Extra state required for efficient set union. */ struct SetState { /** * The strata estimator is only generated once for * each set. * The IBF keys are derived from the element hashes with * salt=0. */ struct StrataEstimator *se; }; /** * Iterator over hash map entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int destroy_key_to_element_iter (void *cls, uint32_t key, void *value) { struct KeyEntry *k = value; /* destroy the linked list of colliding ibf key entries */ while (NULL != k) { struct KeyEntry *k_tmp = k; k = k->next_colliding; if (GNUNET_YES == k_tmp->element->remote) { GNUNET_free (k_tmp->element); k_tmp->element = NULL; } GNUNET_free (k_tmp); } return GNUNET_YES; } /** * Destroy the union operation. Only things specific to the union operation are destroyed. * * @param op union operation to destroy */ static void union_op_cancel (struct Operation *op) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying union op\n"); /* check if the op was canceled twice */ GNUNET_assert (NULL != op->state); if (NULL != op->state->remote_ibf) { ibf_destroy (op->state->remote_ibf); op->state->remote_ibf = NULL; } if (NULL != op->state->local_ibf) { ibf_destroy (op->state->local_ibf); op->state->local_ibf = NULL; } if (NULL != op->state->se) { strata_estimator_destroy (op->state->se); op->state->se = NULL; } if (NULL != op->state->key_to_element) { GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element, destroy_key_to_element_iter, NULL); GNUNET_CONTAINER_multihashmap32_destroy (op->state->key_to_element); op->state->key_to_element = NULL; } GNUNET_free (op->state); op->state = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying union op done\n"); } /** * Inform the client that the union operation has failed, * and proceed to destroy the evaluate operation. * * @param op the union operation to fail */ static void fail_union_operation (struct Operation *op) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *msg; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "union operation failed\n"); ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); msg->request_id = htonl (op->spec->client_request_id); msg->element_type = htons (0); GNUNET_MQ_send (op->spec->set->client_mq, ev); _GSS_operation_destroy (op); } /** * Derive the IBF key from a hash code and * a salt. * * @param src the hash code * @param salt salt to use * @return the derived IBF key */ static struct IBF_Key get_ibf_key (const struct GNUNET_HashCode *src, uint16_t salt) { struct IBF_Key key; GNUNET_CRYPTO_hkdf (&key, sizeof (key), GCRY_MD_SHA512, GCRY_MD_SHA256, src, sizeof *src, &salt, sizeof (salt), NULL, 0); return key; } /** * Send a request for the evaluate operation to a remote peer * * @param op operation with the other peer */ static void send_operation_request (struct Operation *op) { struct GNUNET_MQ_Envelope *ev; struct OperationRequestMessage *msg; ev = GNUNET_MQ_msg_nested_mh (msg, GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST, op->spec->context_msg); if (NULL == ev) { /* the context message is too large */ GNUNET_break (0); GNUNET_SERVER_client_disconnect (op->spec->set->client); return; } msg->operation = htonl (GNUNET_SET_OPERATION_UNION); msg->app_id = op->spec->app_id; msg->salt = htonl (op->spec->salt); GNUNET_MQ_send (op->mq, ev); if (NULL != op->spec->context_msg) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent op request with context message\n"); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent op request without context message\n"); if (NULL != op->spec->context_msg) { GNUNET_free (op->spec->context_msg); op->spec->context_msg = NULL; } } /** * Iterator to create the mapping between ibf keys * and element entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int op_register_element_iterator (void *cls, uint32_t key, void *value) { struct KeyEntry *const new_k = cls; struct KeyEntry *old_k = value; GNUNET_assert (NULL != old_k); /* check if our ibf key collides with the ibf key in the existing entry */ if (old_k->ibf_key.key_val == new_k->ibf_key.key_val) { /* insert the the new key in the collision chain */ new_k->next_colliding = old_k->next_colliding; old_k->next_colliding = new_k; /* signal to the caller that we were able to insert into a colliding bucket */ return GNUNET_NO; } return GNUNET_YES; } /** * Iterator to create the mapping between ibf keys * and element entries. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int op_has_element_iterator (void *cls, uint32_t key, void *value) { struct GNUNET_HashCode *element_hash = cls; struct KeyEntry *k = value; GNUNET_assert (NULL != k); while (NULL != k) { if (0 == GNUNET_CRYPTO_hash_cmp (&k->element->element_hash, element_hash)) return GNUNET_NO; k = k->next_colliding; } return GNUNET_YES; } /** * Determine whether the given element is already in the operation's element * set. * * @param op operation that should be tested for 'element_hash' * @param element_hash hash of the element to look for * @return #GNUNET_YES if the element has been found, #GNUNET_NO otherwise */ static int op_has_element (struct Operation *op, const struct GNUNET_HashCode *element_hash) { int ret; struct IBF_Key ibf_key; ibf_key = get_ibf_key (element_hash, op->spec->salt); ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->state->key_to_element, (uint32_t) ibf_key.key_val, op_has_element_iterator, (void *) element_hash); /* was the iteration aborted because we found the element? */ if (GNUNET_SYSERR == ret) return GNUNET_YES; return GNUNET_NO; } /** * Insert an element into the union operation's * key-to-element mapping. Takes ownership of 'ee'. * Note that this does not insert the element in the set, * only in the operation's key-element mapping. * This is done to speed up re-tried operations, if some elements * were transmitted, and then the IBF fails to decode. * * @param op the union operation * @param ee the element entry */ static void op_register_element (struct Operation *op, struct ElementEntry *ee) { int ret; struct IBF_Key ibf_key; struct KeyEntry *k; ibf_key = get_ibf_key (&ee->element_hash, op->spec->salt); k = GNUNET_new (struct KeyEntry); k->element = ee; k->ibf_key = ibf_key; ret = GNUNET_CONTAINER_multihashmap32_get_multiple (op->state->key_to_element, (uint32_t) ibf_key.key_val, op_register_element_iterator, k); /* was the element inserted into a colliding bucket? */ if (GNUNET_SYSERR == ret) return; GNUNET_CONTAINER_multihashmap32_put (op->state->key_to_element, (uint32_t) ibf_key.key_val, k, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } /** * Insert a key into an ibf. * * @param cls the ibf * @param key unused * @param value the key entry to get the key from */ static int prepare_ibf_iterator (void *cls, uint32_t key, void *value) { struct InvertibleBloomFilter *ibf = cls; struct KeyEntry *ke = value; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "inserting %x into ibf\n", ke->ibf_key.key_val); ibf_insert (ibf, ke->ibf_key); return GNUNET_YES; } /** * Iterator for initializing the * key-to-element mapping of a union operation * * @param cls the union operation * @param key unised * @param value the element entry to insert * into the key-to-element mapping * @return GNUNET_YES to continue iterating, * GNUNET_NO to stop */ static int init_key_to_element_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct Operation *op = cls; struct ElementEntry *e = value; /* make sure that the element belongs to the set at the time * of creating the operation */ if ( (e->generation_added > op->generation_created) || ( (GNUNET_YES == e->removed) && (e->generation_removed < op->generation_created))) return GNUNET_YES; GNUNET_assert (GNUNET_NO == e->remote); op_register_element (op, e); return GNUNET_YES; } /** * Create an ibf with the operation's elements * of the specified size * * @param op the union operation * @param size size of the ibf to create */ static void prepare_ibf (struct Operation *op, uint16_t size) { if (NULL == op->state->key_to_element) { unsigned int len; len = GNUNET_CONTAINER_multihashmap_size (op->spec->set->elements); op->state->key_to_element = GNUNET_CONTAINER_multihashmap32_create (len + 1); GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, init_key_to_element_iterator, op); } if (NULL != op->state->local_ibf) ibf_destroy (op->state->local_ibf); op->state->local_ibf = ibf_create (size, SE_IBF_HASH_NUM); GNUNET_CONTAINER_multihashmap32_iterate (op->state->key_to_element, prepare_ibf_iterator, op->state->local_ibf); } /** * Send an ibf of appropriate size. * * @param op the union operation * @param ibf_order order of the ibf to send, size=2^order */ static void send_ibf (struct Operation *op, uint16_t ibf_order) { unsigned int buckets_sent = 0; struct InvertibleBloomFilter *ibf; prepare_ibf (op, 1<state->local_ibf; while (buckets_sent < (1 << ibf_order)) { unsigned int buckets_in_message; struct GNUNET_MQ_Envelope *ev; struct IBFMessage *msg; buckets_in_message = (1 << ibf_order) - buckets_sent; /* limit to maximum */ if (buckets_in_message > MAX_BUCKETS_PER_MESSAGE) buckets_in_message = MAX_BUCKETS_PER_MESSAGE; ev = GNUNET_MQ_msg_extra (msg, buckets_in_message * IBF_BUCKET_SIZE, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF); msg->reserved = 0; msg->order = ibf_order; msg->offset = htons (buckets_sent); ibf_write_slice (ibf, buckets_sent, buckets_in_message, &msg[1]); buckets_sent += buckets_in_message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ibf chunk size %u, %u/%u sent\n", buckets_in_message, buckets_sent, 1<mq, ev); } op->state->phase = PHASE_EXPECT_ELEMENTS_AND_REQUESTS; } /** * Send a strata estimator to the remote peer. * * @param op the union operation with the remote peer */ static void send_strata_estimator (struct Operation *op) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_MessageHeader *strata_msg; ev = GNUNET_MQ_msg_header_extra (strata_msg, SE_STRATA_COUNT * IBF_BUCKET_SIZE * SE_IBF_SIZE, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE); strata_estimator_write (op->state->se, &strata_msg[1]); GNUNET_MQ_send (op->mq, ev); op->state->phase = PHASE_EXPECT_IBF; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent SE, expecting IBF\n"); } /** * Compute the necessary order of an ibf * from the size of the symmetric set difference. * * @param diff the difference * @return the required size of the ibf */ static unsigned int get_order_from_difference (unsigned int diff) { unsigned int ibf_order; ibf_order = 2; while ((1< MAX_IBF_ORDER) ibf_order = MAX_IBF_ORDER; return ibf_order; } /** * Handle a strata estimator from a remote peer * * @param cls the union operation * @param mh the message */ static void handle_p2p_strata_estimator (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; struct StrataEstimator *remote_se; int diff; if (op->state->phase != PHASE_EXPECT_SE) { fail_union_operation (op); GNUNET_break (0); return; } remote_se = strata_estimator_create (SE_STRATA_COUNT, SE_IBF_SIZE, SE_IBF_HASH_NUM); strata_estimator_read (&mh[1], remote_se); GNUNET_assert (NULL != op->state->se); diff = strata_estimator_difference (remote_se, op->state->se); strata_estimator_destroy (remote_se); strata_estimator_destroy (op->state->se); op->state->se = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got se diff=%d, using ibf size %d\n", diff, 1<ibf_key; struct Operation *op = sec->op; struct KeyEntry *ke = value; if (ke->ibf_key.key_val != ibf_key.key_val) return GNUNET_YES; while (NULL != ke) { const struct GNUNET_SET_Element *const element = &ke->element->element; struct GNUNET_MQ_Envelope *ev; struct GNUNET_MessageHeader *mh; GNUNET_assert (ke->ibf_key.key_val == ibf_key.key_val); ev = GNUNET_MQ_msg_header_extra (mh, element->size, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS); if (NULL == ev) { /* element too large */ GNUNET_break (0); continue; } memcpy (&mh[1], element->data, element->size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending element (%s) to peer\n", GNUNET_h2s (&ke->element->element_hash)); GNUNET_MQ_send (op->mq, ev); ke = ke->next_colliding; } return GNUNET_NO; } /** * Send all elements that have the specified IBF key * to the remote peer of the union operation * * @param op union operation * @param ibf_key IBF key of interest */ static void send_elements_for_key (struct Operation *op, struct IBF_Key ibf_key) { struct SendElementClosure send_cls; send_cls.ibf_key = ibf_key; send_cls.op = op; (void) GNUNET_CONTAINER_multihashmap32_get_multiple (op->state->key_to_element, (uint32_t) ibf_key.key_val, &send_element_iterator, &send_cls); } /** * Decode which elements are missing on each side, and * send the appropriate elemens and requests * * @param op union operation */ static void decode_and_send (struct Operation *op) { struct IBF_Key key; struct IBF_Key last_key; int side; unsigned int num_decoded; struct InvertibleBloomFilter *diff_ibf; GNUNET_assert (PHASE_EXPECT_ELEMENTS == op->state->phase); prepare_ibf (op, op->state->remote_ibf->size); diff_ibf = ibf_dup (op->state->local_ibf); ibf_subtract (diff_ibf, op->state->remote_ibf); ibf_destroy (op->state->remote_ibf); op->state->remote_ibf = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "decoding IBF (size=%u)\n", diff_ibf->size); num_decoded = 0; last_key.key_val = 0; while (1) { int res; int cycle_detected = GNUNET_NO; last_key = key; res = ibf_decode (diff_ibf, &side, &key); if (res == GNUNET_OK) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "decoded ibf key %lx\n", key.key_val); num_decoded += 1; if (num_decoded > diff_ibf->size || (num_decoded > 1 && last_key.key_val == key.key_val)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "detected cyclic ibf (decoded %u/%u)\n", num_decoded, diff_ibf->size); cycle_detected = GNUNET_YES; } } if ((GNUNET_SYSERR == res) || (GNUNET_YES == cycle_detected)) { int next_order; next_order = 0; while (1<size) next_order++; next_order++; if (next_order <= MAX_IBF_ORDER) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "decoding failed, sending larger ibf (size %u)\n", 1<mq, ev); break; } if (1 == side) { send_elements_for_key (op, key); } else if (-1 == side) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_MessageHeader *msg; /* It may be nice to merge multiple requests, but with mesh's corking it is not worth * the effort additional complexity. */ ev = GNUNET_MQ_msg_header_extra (msg, sizeof (struct IBF_Key), GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS); *(struct IBF_Key *) &msg[1] = key; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending element request\n"); GNUNET_MQ_send (op->mq, ev); } else { GNUNET_assert (0); } } ibf_destroy (diff_ibf); } /** * Handle an IBF message from a remote peer. * * @param cls the union operation * @param mh the header of the message */ static void handle_p2p_ibf (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; struct IBFMessage *msg = (struct IBFMessage *) mh; unsigned int buckets_in_message; if ( (op->state->phase == PHASE_EXPECT_ELEMENTS_AND_REQUESTS) || (op->state->phase == PHASE_EXPECT_IBF) ) { op->state->phase = PHASE_EXPECT_IBF_CONT; GNUNET_assert (NULL == op->state->remote_ibf); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "creating new ibf of size %u\n", 1<order); op->state->remote_ibf = ibf_create (1<order, SE_IBF_HASH_NUM); op->state->ibf_buckets_received = 0; if (0 != ntohs (msg->offset)) { GNUNET_break (0); fail_union_operation (op); return; } } else if (op->state->phase == PHASE_EXPECT_IBF_CONT) { if ( (ntohs (msg->offset) != op->state->ibf_buckets_received) || (1<order != op->state->remote_ibf->size) ) { GNUNET_break (0); fail_union_operation (op); return; } } buckets_in_message = (ntohs (msg->header.size) - sizeof *msg) / IBF_BUCKET_SIZE; if (0 == buckets_in_message) { GNUNET_break_op (0); fail_union_operation (op); return; } if ((ntohs (msg->header.size) - sizeof *msg) != buckets_in_message * IBF_BUCKET_SIZE) { GNUNET_break (0); fail_union_operation (op); return; } ibf_read_slice (&msg[1], op->state->ibf_buckets_received, buckets_in_message, op->state->remote_ibf); op->state->ibf_buckets_received += buckets_in_message; if (op->state->ibf_buckets_received == op->state->remote_ibf->size) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received full ibf\n"); op->state->phase = PHASE_EXPECT_ELEMENTS; decode_and_send (op); } } /** * Send a result message to the client indicating * that there is a new element. * * @param op union operation * @param element element to send */ static void send_client_element (struct Operation *op, struct GNUNET_SET_Element *element) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *rm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending element (size %u) to client\n", element->size); GNUNET_assert (0 != op->spec->client_request_id); ev = GNUNET_MQ_msg_extra (rm, element->size, GNUNET_MESSAGE_TYPE_SET_RESULT); if (NULL == ev) { GNUNET_MQ_discard (ev); GNUNET_break (0); return; } rm->result_status = htons (GNUNET_SET_STATUS_OK); rm->request_id = htonl (op->spec->client_request_id); rm->element_type = element->type; memcpy (&rm[1], element->data, element->size); GNUNET_MQ_send (op->spec->set->client_mq, ev); } /** * Signal to the client that the operation has finished and * destroy the operation. * * @param cls operation to destroy */ static void send_done_and_destroy (void *cls) { struct Operation *op = cls; struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *rm; int keep = op->keep; ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); rm->request_id = htonl (op->spec->client_request_id); rm->result_status = htons (GNUNET_SET_STATUS_DONE); rm->element_type = htons (0); GNUNET_MQ_send (op->spec->set->client_mq, ev); _GSS_operation_destroy (op); if (GNUNET_YES == keep) GNUNET_free (op); } /** * Send all remaining elements in the full result iterator. * * @param cls operation */ static void send_remaining_elements (void *cls) { struct Operation *op = cls; struct KeyEntry *ke; int res; res = GNUNET_CONTAINER_multihashmap32_iterator_next (op->state->full_result_iter, NULL, (const void **) &ke); if (GNUNET_NO == res) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending done and destroy because iterator ran out\n"); send_done_and_destroy (op); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending elements from key entry\n"); while (1) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *rm; struct GNUNET_SET_Element *element; element = &ke->element->element; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending element (size %u) to client (full set)\n", element->size); GNUNET_assert (0 != op->spec->client_request_id); ev = GNUNET_MQ_msg_extra (rm, element->size, GNUNET_MESSAGE_TYPE_SET_RESULT); if (NULL == ev) { GNUNET_MQ_discard (ev); GNUNET_break (0); continue; } rm->result_status = htons (GNUNET_SET_STATUS_OK); rm->request_id = htonl (op->spec->client_request_id); rm->element_type = element->type; memcpy (&rm[1], element->data, element->size); if (ke->next_colliding == NULL) { GNUNET_MQ_notify_sent (ev, send_remaining_elements, op); GNUNET_MQ_send (op->spec->set->client_mq, ev); break; } GNUNET_MQ_send (op->spec->set->client_mq, ev); ke = ke->next_colliding; } } /** * Send a result message to the client indicating * that the operation is over. * After the result done message has been sent to the client, * destroy the evaluate operation. * * @param op union operation */ static void finish_and_destroy (struct Operation *op) { GNUNET_assert (GNUNET_NO == op->state->client_done_sent); if (GNUNET_SET_RESULT_FULL == op->spec->result_mode) { /* prevent that the op is free'd by the tunnel end handler */ op->keep = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending full result set\n"); GNUNET_assert (NULL == op->state->full_result_iter); op->state->full_result_iter = GNUNET_CONTAINER_multihashmap32_iterator_create (op->state->key_to_element); send_remaining_elements (op); return; } send_done_and_destroy (op); } /** * Handle an element message from a remote peer. * * @param cls the union operation * @param mh the message */ static void handle_p2p_elements (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; struct ElementEntry *ee; uint16_t element_size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got element from peer\n"); if ( (op->state->phase != PHASE_EXPECT_ELEMENTS) && (op->state->phase != PHASE_EXPECT_ELEMENTS_AND_REQUESTS) ) { fail_union_operation (op); GNUNET_break (0); return; } element_size = ntohs (mh->size) - sizeof (struct GNUNET_MessageHeader); ee = GNUNET_malloc (sizeof *ee + element_size); memcpy (&ee[1], &mh[1], element_size); ee->element.size = element_size; ee->element.data = &ee[1]; ee->remote = GNUNET_YES; GNUNET_CRYPTO_hash (ee->element.data, ee->element.size, &ee->element_hash); if (GNUNET_YES == op_has_element (op, &ee->element_hash)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got existing element from peer\n"); GNUNET_free (ee); return; } op_register_element (op, ee); /* only send results immediately if the client wants it */ if (GNUNET_SET_RESULT_ADDED == op->spec->result_mode) send_client_element (op, &ee->element); } /** * Handle an element request from a remote peer. * * @param cls the union operation * @param mh the message */ static void handle_p2p_element_requests (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; struct IBF_Key *ibf_key; unsigned int num_keys; /* look up elements and send them */ if (op->state->phase != PHASE_EXPECT_ELEMENTS_AND_REQUESTS) { GNUNET_break (0); fail_union_operation (op); return; } num_keys = (ntohs (mh->size) - sizeof *mh) / sizeof (struct IBF_Key); if ((ntohs (mh->size) - sizeof *mh) != num_keys * sizeof (struct IBF_Key)) { GNUNET_break (0); fail_union_operation (op); return; } ibf_key = (struct IBF_Key *) &mh[1]; while (0 != num_keys--) { send_elements_for_key (op, *ibf_key); ibf_key++; } } /** * Handle a done message from a remote peer * * @param cls the union operation * @param mh the message */ static void handle_p2p_done (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; struct GNUNET_MQ_Envelope *ev; if (op->state->phase == PHASE_EXPECT_ELEMENTS_AND_REQUESTS) { /* we got all requests, but still have to send our elements as response */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got DONE, sending final DONE after elements\n"); op->state->phase = PHASE_FINISHED; ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_P2P_DONE); GNUNET_MQ_send (op->mq, ev); return; } if (op->state->phase == PHASE_EXPECT_ELEMENTS) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got final DONE\n"); op->state->phase = PHASE_FINISHED; finish_and_destroy (op); return; } GNUNET_break (0); fail_union_operation (op); } /** * Evaluate a union operation with * a remote peer. * * @param op operation to evaluate */ static void union_evaluate (struct Operation *op) { op->state = GNUNET_new (struct OperationState); // copy the current generation's strata estimator for this operation op->state->se = strata_estimator_dup (op->spec->set->state->se); /* we started the operation, thus we have to send the operation request */ op->state->phase = PHASE_EXPECT_SE; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "evaluating union operation\n"); send_operation_request (op); } /** * Accept an union operation request from a remote peer. * Only initializes the private operation state. * * @param op operation that will be accepted as a union operation */ static void union_accept (struct Operation *op) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "accepting set union operation\n"); op->state = GNUNET_new (struct OperationState); op->state->se = strata_estimator_dup (op->spec->set->state->se); /* kick off the operation */ send_strata_estimator (op); } /** * Create a new set supporting the union operation * * We maintain one strata estimator per set and then manipulate it over the * lifetime of the set, as recreating a strata estimator would be expensive. * * @return the newly created set */ static struct SetState * union_set_create (void) { struct SetState *set_state; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "union set created\n"); set_state = GNUNET_new (struct SetState); set_state->se = strata_estimator_create (SE_STRATA_COUNT, SE_IBF_SIZE, SE_IBF_HASH_NUM); return set_state; } /** * Add the element from the given element message to the set. * * @param set_state state of the set want to add to * @param ee the element to add to the set */ static void union_add (struct SetState *set_state, struct ElementEntry *ee) { strata_estimator_insert (set_state->se, get_ibf_key (&ee->element_hash, 0)); } /** * Remove the element given in the element message from the set. * Only marks the element as removed, so that older set operations can still exchange it. * * @param set_state state of the set to remove from * @param ee set element to remove */ static void union_remove (struct SetState *set_state, struct ElementEntry *ee) { strata_estimator_remove (set_state->se, get_ibf_key (&ee->element_hash, 0)); } /** * Destroy a set that supports the union operation. * * @param set_state the set to destroy */ static void union_set_destroy (struct SetState *set_state) { if (NULL != set_state->se) { strata_estimator_destroy (set_state->se); set_state->se = NULL; } GNUNET_free (set_state); } /** * Dispatch messages for a union operation. * * @param op the state of the union evaluate operation * @param mh the received message * @return GNUNET_SYSERR if the tunnel should be disconnected, * GNUNET_OK otherwise */ int union_handle_p2p_message (struct Operation *op, const struct GNUNET_MessageHeader *mh) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received p2p message (t: %u, s: %u)\n", ntohs (mh->type), ntohs (mh->size)); switch (ntohs (mh->type)) { case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF: handle_p2p_ibf (op, mh); break; case GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE: handle_p2p_strata_estimator (op, mh); break; case GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS: handle_p2p_elements (op, mh); break; case GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS: handle_p2p_element_requests (op, mh); break; case GNUNET_MESSAGE_TYPE_SET_P2P_DONE: handle_p2p_done (op, mh); break; default: /* something wrong with mesh's message handlers? */ GNUNET_assert (0); } return GNUNET_OK; } /** * handler for peer-disconnects, notifies the client * about the aborted operation in case the op was not concluded * * @param op the destroyed operation */ static void union_peer_disconnect (struct Operation *op) { if (PHASE_FINISHED != op->state->phase) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *msg; ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); msg->request_id = htonl (op->spec->client_request_id); msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); msg->element_type = htons (0); GNUNET_MQ_send (op->spec->set->client_mq, ev); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "other peer disconnected prematurely\n"); _GSS_operation_destroy (op); return; } // else: the session has already been concluded GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "other peer disconnected (finished)\n"); if (GNUNET_NO == op->state->client_done_sent) finish_and_destroy (op); } /** * Get the table with implementing functions for * set union. * * @return the operation specific VTable */ const struct SetVT * _GSS_union_vt () { static const struct SetVT union_vt = { .create = &union_set_create, .msg_handler = &union_handle_p2p_message, .add = &union_add, .remove = &union_remove, .destroy_set = &union_set_destroy, .evaluate = &union_evaluate, .accept = &union_accept, .peer_disconnect = &union_peer_disconnect, .cancel = &union_op_cancel, }; return &union_vt; } gnunet-0.10.1/src/set/set_api.c0000644000175000017500000006004512276375236013206 00000000000000/* This file is part of GNUnet. (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/set_api.c * @brief api for the set service * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_client_lib.h" #include "gnunet_set_service.h" #include "set.h" #define LOG(kind,...) GNUNET_log_from (kind, "set-api",__VA_ARGS__) /** * Opaque handle to a set. */ struct GNUNET_SET_Handle { /** * Client connected to the set service. */ struct GNUNET_CLIENT_Connection *client; /** * Message queue for 'client'. */ struct GNUNET_MQ_Handle *mq; /** * Linked list of operations on the set. */ struct GNUNET_SET_OperationHandle *ops_head; /** * Linked list of operations on the set. */ struct GNUNET_SET_OperationHandle *ops_tail; /** * Should the set be destroyed once all operations are gone? */ int destroy_requested; /** * Has the set become invalid (e.g. service died)? */ int invalid; /** * Callback for the current iteration over the set, * NULL if no iterator is active. */ GNUNET_SET_ElementIterator iterator; /** * Closure for 'iterator' */ void *iterator_cls; }; /** * Opaque handle to a set operation request from another peer. */ struct GNUNET_SET_Request { /** * Id of the request, used to identify the request when * accepting/rejecting it. */ uint32_t accept_id; /** * Has the request been accepted already? * GNUNET_YES/GNUNET_NO */ int accepted; }; /** * Handle to an operation. * Only known to the service after commiting * the handle with a set. */ struct GNUNET_SET_OperationHandle { /** * Function to be called when we have a result, * or an error. */ GNUNET_SET_ResultIterator result_cb; /** * Closure for result_cb. */ void *result_cls; /** * Local set used for the operation, * NULL if no set has been provided by conclude yet. */ struct GNUNET_SET_Handle *set; /** * Request ID to identify the operation within the set. */ uint32_t request_id; /** * Message sent to the server on calling conclude, * NULL if conclude has been called. */ struct GNUNET_MQ_Envelope *conclude_mqm; /** * Address of the request if in the conclude message, * used to patch the request id into the message when the set is known. */ uint32_t *request_id_addr; /** * Handles are kept in a linked list. */ struct GNUNET_SET_OperationHandle *prev; /** * Handles are kept in a linked list. */ struct GNUNET_SET_OperationHandle *next; }; /** * Opaque handle to a listen operation. */ struct GNUNET_SET_ListenHandle { /** * Connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * Message queue for the client. */ struct GNUNET_MQ_Handle* mq; /** * Configuration handle for the listener, stored * here to be able to reconnect transparently on * connection failure. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Function to call on a new incoming request, * or on error. */ GNUNET_SET_ListenCallback listen_cb; /** * Closure for listen_cb. */ void *listen_cls; /** * Operation we listen for. */ enum GNUNET_SET_OperationType operation; /** * Application ID we listen for. */ struct GNUNET_HashCode app_id; /** * Time to wait until we try to reconnect on failure. */ struct GNUNET_TIME_Relative reconnect_backoff; /** * Task for reconnecting when the listener fails. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; }; /* forward declaration */ static void listen_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Handle element for iteration over the set. * * @param cls the set * @param mh the message */ static void handle_iter_element (void *cls, const struct GNUNET_MessageHeader *mh) { struct GNUNET_SET_Handle *set = cls; struct GNUNET_SET_Element element; const struct GNUNET_SET_IterResponseMessage *msg = (const struct GNUNET_SET_IterResponseMessage *) mh; struct GNUNET_SET_IterAckMessage *ack_msg; struct GNUNET_MQ_Envelope *ev; if (NULL == set->iterator) return; element.size = ntohs (mh->size) - sizeof (struct GNUNET_SET_IterResponseMessage); element.type = htons (msg->element_type); element.data = &msg[1]; set->iterator (set->iterator_cls, &element); ev = GNUNET_MQ_msg (ack_msg, GNUNET_MESSAGE_TYPE_SET_ITER_ACK); ack_msg->send_more = htonl (1); GNUNET_MQ_send (set->mq, ev); } /** * Handle element for iteration over the set. * * @param cls the set * @param mh the message */ static void handle_iter_done (void *cls, const struct GNUNET_MessageHeader *mh) { struct GNUNET_SET_Handle *set = cls; if (NULL == set->iterator) return; set->iterator (set->iterator_cls, NULL); } /** * Handle result message for a set operation. * * @param cls the set * @param mh the message */ static void handle_result (void *cls, const struct GNUNET_MessageHeader *mh) { const struct GNUNET_SET_ResultMessage *msg; struct GNUNET_SET_Handle *set = cls; struct GNUNET_SET_OperationHandle *oh; struct GNUNET_SET_Element e; enum GNUNET_SET_Status result_status; msg = (const struct GNUNET_SET_ResultMessage *) mh; GNUNET_assert (NULL != set); GNUNET_assert (NULL != set->mq); result_status = ntohs (msg->result_status); oh = GNUNET_MQ_assoc_get (set->mq, ntohl (msg->request_id)); // 'oh' can be NULL if we canceled the operation, but the service // did not get the cancel message yet. if (NULL == oh) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ignoring result from canceled operation\n"); return; } /* status is not STATUS_OK => there's no attached element, * and this is the last result message we get */ if (GNUNET_SET_STATUS_OK != result_status) { GNUNET_MQ_assoc_remove (set->mq, ntohl (msg->request_id)); GNUNET_CONTAINER_DLL_remove (oh->set->ops_head, oh->set->ops_tail, oh); if (GNUNET_YES == oh->set->destroy_requested) GNUNET_SET_destroy (oh->set); if (NULL != oh->result_cb) oh->result_cb (oh->result_cls, NULL, result_status); GNUNET_free (oh); return; } e.data = &msg[1]; e.size = ntohs (mh->size) - sizeof (struct GNUNET_SET_ResultMessage); e.type = msg->element_type; if (NULL != oh->result_cb) oh->result_cb (oh->result_cls, &e, result_status); } /** * Handle request message for a listen operation * * @param cls the listen handle * @param mh the message */ static void handle_request (void *cls, const struct GNUNET_MessageHeader *mh) { const struct GNUNET_SET_RequestMessage *msg = (const struct GNUNET_SET_RequestMessage *) mh; struct GNUNET_SET_ListenHandle *lh = cls; struct GNUNET_SET_Request *req; struct GNUNET_MessageHeader *context_msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "processing operation request\n"); req = GNUNET_new (struct GNUNET_SET_Request); req->accept_id = ntohl (msg->accept_id); context_msg = GNUNET_MQ_extract_nested_mh (msg); /* calling GNUNET_SET_accept in the listen cb will set req->accepted */ lh->listen_cb (lh->listen_cls, &msg->peer_id, context_msg, req); /* we got another request => reset the backoff */ lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS; if (GNUNET_NO == req->accepted) { struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_AcceptRejectMessage *amsg; mqm = GNUNET_MQ_msg (amsg, GNUNET_MESSAGE_TYPE_SET_REJECT); /* no request id, as we refused */ amsg->request_id = htonl (0); amsg->accept_reject_id = msg->accept_id; GNUNET_MQ_send (lh->mq, mqm); LOG (GNUNET_ERROR_TYPE_DEBUG, "rejecting request\n"); } GNUNET_free (req); LOG (GNUNET_ERROR_TYPE_DEBUG, "processed op request from service\n"); /* the accept-case is handled in GNUNET_SET_accept, * as we have the accept message available there */ } static void handle_client_listener_error (void *cls, enum GNUNET_MQ_Error error) { struct GNUNET_SET_ListenHandle *lh = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "listener broke down, re-connecting\n"); GNUNET_CLIENT_disconnect (lh->client); lh->client = NULL; GNUNET_MQ_destroy (lh->mq); lh->mq = NULL; lh->reconnect_task = GNUNET_SCHEDULER_add_delayed (lh->reconnect_backoff, listen_connect, lh); lh->reconnect_backoff = GNUNET_TIME_STD_BACKOFF (lh->reconnect_backoff); } /** * Destroy the set handle if no operations are left, mark the set * for destruction otherwise. * * @param set set handle to destroy */ static int set_destroy (struct GNUNET_SET_Handle *set) { if (NULL != set->ops_head) { set->destroy_requested = GNUNET_YES; return GNUNET_NO; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Really destroying set\n"); GNUNET_CLIENT_disconnect (set->client); set->client = NULL; GNUNET_MQ_destroy (set->mq); set->mq = NULL; GNUNET_free (set); return GNUNET_YES; } /** * Cancel the given set operation. We need to send an explicit cancel message, * as all operations one one set communicate using one handle. * * In contrast to GNUNET_SET_operation_cancel, this function indicates whether * the set of the operation has been destroyed because all operations are done and * the set's destruction was requested before. * * @param oh set operation to cancel * @return GNUNET_YES if the set of the operation was destroyed */ static int set_operation_cancel (struct GNUNET_SET_OperationHandle *oh) { int ret = GNUNET_NO; if (NULL != oh->conclude_mqm) GNUNET_MQ_discard (oh->conclude_mqm); /* is the operation already commited? */ if (NULL != oh->set) { struct GNUNET_SET_OperationHandle *h_assoc; struct GNUNET_SET_CancelMessage *m; struct GNUNET_MQ_Envelope *mqm; GNUNET_CONTAINER_DLL_remove (oh->set->ops_head, oh->set->ops_tail, oh); h_assoc = GNUNET_MQ_assoc_remove (oh->set->mq, oh->request_id); GNUNET_assert ((h_assoc == NULL) || (h_assoc == oh)); mqm = GNUNET_MQ_msg (m, GNUNET_MESSAGE_TYPE_SET_CANCEL); m->request_id = htonl (oh->request_id); GNUNET_MQ_send (oh->set->mq, mqm); if (GNUNET_YES == oh->set->destroy_requested) { LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying set after operation cancel\n"); ret = set_destroy (oh->set); } } GNUNET_free (oh); return ret; } /** * Cancel the given set operation. We need to send an explicit cancel message, * as all operations one one set communicate using one handle. * * @param oh set operation to cancel */ void GNUNET_SET_operation_cancel (struct GNUNET_SET_OperationHandle *oh) { (void) set_operation_cancel (oh); } static void handle_client_set_error (void *cls, enum GNUNET_MQ_Error error) { struct GNUNET_SET_Handle *set = cls; LOG (GNUNET_ERROR_TYPE_DEBUG, "handling client set error\n"); while (NULL != set->ops_head) { if (NULL != set->ops_head->result_cb) set->ops_head->result_cb (set->ops_head->result_cls, NULL, GNUNET_SET_STATUS_FAILURE); if (GNUNET_YES == set_operation_cancel (set->ops_head)) return; /* stop if the set is destroyed */ } set->invalid = GNUNET_YES; } /** * Create an empty set, supporting the specified operation. * * @param cfg configuration to use for connecting to the * set service * @param op operation supported by the set * Note that the operation has to be specified * beforehand, as certain set operations need to maintain * data structures spefific to the operation * @return a handle to the set */ struct GNUNET_SET_Handle * GNUNET_SET_create (const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType op) { struct GNUNET_SET_Handle *set; struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_CreateMessage *msg; static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { {handle_result, GNUNET_MESSAGE_TYPE_SET_RESULT, 0}, {handle_iter_element, GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT, 0}, {handle_iter_done, GNUNET_MESSAGE_TYPE_SET_ITER_DONE, 0}, GNUNET_MQ_HANDLERS_END }; set = GNUNET_new (struct GNUNET_SET_Handle); set->client = GNUNET_CLIENT_connect ("set", cfg); LOG (GNUNET_ERROR_TYPE_DEBUG, "set client created\n"); GNUNET_assert (NULL != set->client); set->mq = GNUNET_MQ_queue_for_connection_client (set->client, mq_handlers, handle_client_set_error, set); GNUNET_assert (NULL != set->mq); mqm = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_CREATE); msg->operation = htons (op); GNUNET_MQ_send (set->mq, mqm); return set; } /** * Add an element to the given set. * After the element has been added (in the sense of being * transmitted to the set service), cont will be called. * Calls to add_element can be queued * * @param set set to add element to * @param element element to add to the set * @param cont continuation called after the element has been added * @param cont_cls closure for @a cont * @return #GNUNET_OK on success, #GNUNET_SYSERR if the * set is invalid (e.g. the set service crashed) */ int GNUNET_SET_add_element (struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls) { struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_ElementMessage *msg; if (GNUNET_YES == set->invalid) { if (NULL != cont) cont (cont_cls); return GNUNET_SYSERR; } mqm = GNUNET_MQ_msg_extra (msg, element->size, GNUNET_MESSAGE_TYPE_SET_ADD); msg->element_type = element->type; memcpy (&msg[1], element->data, element->size); GNUNET_MQ_notify_sent (mqm, cont, cont_cls); GNUNET_MQ_send (set->mq, mqm); return GNUNET_OK; } /** * Remove an element to the given set. * After the element has been removed (in the sense of the * request being transmitted to the set service), cont will be called. * Calls to remove_element can be queued * * @param set set to remove element from * @param element element to remove from the set * @param cont continuation called after the element has been removed * @param cont_cls closure for cont * @return GNUNET_OK on success, GNUNET_SYSERR if the * set is invalid (e.g. the set service crashed) */ int GNUNET_SET_remove_element (struct GNUNET_SET_Handle *set, const struct GNUNET_SET_Element *element, GNUNET_SET_Continuation cont, void *cont_cls) { struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_ElementMessage *msg; if (GNUNET_YES == set->invalid) { if (NULL != cont) cont (cont_cls); return GNUNET_SYSERR; } mqm = GNUNET_MQ_msg_extra (msg, element->size, GNUNET_MESSAGE_TYPE_SET_REMOVE); msg->element_type = element->type; memcpy (&msg[1], element->data, element->size); GNUNET_MQ_notify_sent (mqm, cont, cont_cls); GNUNET_MQ_send (set->mq, mqm); return GNUNET_OK; } /** * Destroy the set handle, and free all associated resources. * * @param set set handle to destroy */ void GNUNET_SET_destroy (struct GNUNET_SET_Handle *set) { (void) set_destroy (set); } /** * Prepare a set operation to be evaluated with another peer. * The evaluation will not start until the client provides * a local set with GNUNET_SET_commit. * * @param other_peer peer with the other set * @param app_id hash for the application using the set * @param context_msg additional information for the request * @param salt salt used for the set operation; sometimes set operations * fail due to hash collisions, using a different salt for each operation * makes it harder for an attacker to exploit this * @param result_mode specified how results will be returned, * see 'GNUNET_SET_ResultMode'. * @param result_cb called on error or success * @param result_cls closure for result_cb * @return a handle to cancel the operation */ struct GNUNET_SET_OperationHandle * GNUNET_SET_prepare (const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_HashCode *app_id, const struct GNUNET_MessageHeader *context_msg, uint16_t salt, enum GNUNET_SET_ResultMode result_mode, GNUNET_SET_ResultIterator result_cb, void *result_cls) { struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_OperationHandle *oh; struct GNUNET_SET_EvaluateMessage *msg; oh = GNUNET_new (struct GNUNET_SET_OperationHandle); oh->result_cb = result_cb; oh->result_cls = result_cls; mqm = GNUNET_MQ_msg_nested_mh (msg, GNUNET_MESSAGE_TYPE_SET_EVALUATE, context_msg); msg->app_id = *app_id; msg->result_mode = htons (result_mode); msg->target_peer = *other_peer; msg->salt = salt; oh->conclude_mqm = mqm; oh->request_id_addr = &msg->request_id; return oh; } /** * Connect to the set service in order to listen * for request. * * @param cls the listen handle to connect * @param tc task context if invoked as a task, NULL otherwise */ static void listen_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_ListenMessage *msg; struct GNUNET_SET_ListenHandle *lh = cls; static const struct GNUNET_MQ_MessageHandler mq_handlers[] = { {handle_request, GNUNET_MESSAGE_TYPE_SET_REQUEST}, GNUNET_MQ_HANDLERS_END }; if ((tc != NULL) &&(tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) { LOG (GNUNET_ERROR_TYPE_DEBUG, "listener not reconnecting due to shutdown\n"); return; } lh->reconnect_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (NULL == lh->client); lh->client = GNUNET_CLIENT_connect ("set", lh->cfg); if (NULL == lh->client) { LOG (GNUNET_ERROR_TYPE_ERROR, "could not connect to set (wrong configuration?), giving up listening\n"); return; } GNUNET_assert (NULL == lh->mq); lh->mq = GNUNET_MQ_queue_for_connection_client (lh->client, mq_handlers, handle_client_listener_error, lh); mqm = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_LISTEN); msg->operation = htonl (lh->operation); msg->app_id = lh->app_id; GNUNET_MQ_send (lh->mq, mqm); } /** * Wait for set operation requests for the given application id * * @param cfg configuration to use for connecting to * the set service, needs to be valid for the lifetime of the listen handle * @param operation operation we want to listen for * @param app_id id of the application that handles set operation requests * @param listen_cb called for each incoming request matching the operation * and application id * @param listen_cls handle for listen_cb * @return a handle that can be used to cancel the listen operation */ struct GNUNET_SET_ListenHandle * GNUNET_SET_listen (const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_SET_OperationType operation, const struct GNUNET_HashCode *app_id, GNUNET_SET_ListenCallback listen_cb, void *listen_cls) { struct GNUNET_SET_ListenHandle *lh; lh = GNUNET_new (struct GNUNET_SET_ListenHandle); lh->listen_cb = listen_cb; lh->listen_cls = listen_cls; lh->cfg = cfg; lh->operation = operation; lh->app_id = *app_id; lh->reconnect_backoff = GNUNET_TIME_UNIT_MILLISECONDS; listen_connect (lh, NULL); return lh; } /** * Cancel the given listen operation. * * @param lh handle for the listen operation */ void GNUNET_SET_listen_cancel (struct GNUNET_SET_ListenHandle *lh) { LOG (GNUNET_ERROR_TYPE_DEBUG, "canceling listener\n"); /* listener's connection may have failed, thus mq/client could be NULL */ if (NULL != lh->mq) { GNUNET_MQ_destroy (lh->mq); lh->mq = NULL; } if (NULL != lh->client) { GNUNET_CLIENT_disconnect (lh->client); lh->client = NULL; } if (GNUNET_SCHEDULER_NO_TASK != lh->reconnect_task) { GNUNET_SCHEDULER_cancel (lh->reconnect_task); lh->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (lh); } /** * Accept a request we got via #GNUNET_SET_listen. Must be called during * #GNUNET_SET_listen, as the 'struct GNUNET_SET_Request' becomes invalid * afterwards. * Call #GNUNET_SET_commit to provide the local set to use for the operation, * and to begin the exchange with the remote peer. * * @param request request to accept * @param result_mode specified how results will be returned, * see 'GNUNET_SET_ResultMode'. * @param result_cb callback for the results * @param result_cls closure for result_cb * @return a handle to cancel the operation */ struct GNUNET_SET_OperationHandle * GNUNET_SET_accept (struct GNUNET_SET_Request *request, enum GNUNET_SET_ResultMode result_mode, GNUNET_SET_ResultIterator result_cb, void *result_cls) { struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_OperationHandle *oh; struct GNUNET_SET_AcceptRejectMessage *msg; GNUNET_assert (NULL != request); GNUNET_assert (GNUNET_NO == request->accepted); request->accepted = GNUNET_YES; oh = GNUNET_new (struct GNUNET_SET_OperationHandle); oh->result_cb = result_cb; oh->result_cls = result_cls; mqm = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_ACCEPT); msg->accept_reject_id = htonl (request->accept_id); msg->result_mode = htons (result_mode); oh->conclude_mqm = mqm; oh->request_id_addr = &msg->request_id; return oh; } /** * Commit a set to be used with a set operation. * This function is called once we have fully constructed * the set that we want to use for the operation. At this * time, the P2P protocol can then begin to exchange the * set information and call the result callback with the * result information. * * @param oh handle to the set operation * @param set the set to use for the operation * @return #GNUNET_OK on success, #GNUNET_SYSERR if the * set is invalid (e.g. the set service crashed) */ int GNUNET_SET_commit (struct GNUNET_SET_OperationHandle *oh, struct GNUNET_SET_Handle *set) { GNUNET_assert (NULL == oh->set); if (GNUNET_YES == set->invalid) return GNUNET_SYSERR; GNUNET_assert (NULL != oh->conclude_mqm); oh->set = set; GNUNET_CONTAINER_DLL_insert (set->ops_head, set->ops_tail, oh); oh->request_id = GNUNET_MQ_assoc_add (set->mq, oh); *oh->request_id_addr = htonl (oh->request_id); GNUNET_MQ_send (set->mq, oh->conclude_mqm); oh->conclude_mqm = NULL; oh->request_id_addr = NULL; return GNUNET_OK; } /** * Iterate over all elements in the given set. * Note that this operation involves transferring every element of the set * from the service to the client, and is thus costly. * * @param set the set to iterate over * @param iter the iterator to call for each element * @param cls closure for @a iter * @return #GNUNET_YES if the iteration started successfuly, * #GNUNET_NO if another iteration is active * #GNUNET_SYSERR if the set is invalid (e.g. the server crashed, disconnected) */ int GNUNET_SET_iterate (struct GNUNET_SET_Handle *set, GNUNET_SET_ElementIterator iter, void *cls) { struct GNUNET_MQ_Envelope *ev; GNUNET_assert (NULL != iter); if (GNUNET_YES == set->invalid) return GNUNET_SYSERR; if (NULL != set->iterator) return GNUNET_NO; LOG (GNUNET_ERROR_TYPE_DEBUG, "iterating set\n"); set->iterator = iter; set->iterator_cls = cls; ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST); GNUNET_MQ_send (set->mq, ev); return GNUNET_YES; } /* end of set_api.c */ gnunet-0.10.1/src/set/ibf.h0000644000175000017500000001324112236140650012305 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/ibf.h * @brief invertible bloom filter * @author Florian Dold */ #ifndef GNUNET_CONSENSUS_IBF_H #define GNUNET_CONSENSUS_IBF_H #include "platform.h" #include "gnunet_util_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * Keys that can be inserted into and removed from an IBF. */ struct IBF_Key { uint64_t key_val; }; /** * Hash of an IBF key. */ struct IBF_KeyHash { uint32_t key_hash_val; }; /** * Type of the count field of IBF buckets. */ struct IBF_Count { int8_t count_val; }; /** * Size of one ibf bucket in bytes */ #define IBF_BUCKET_SIZE (sizeof (struct IBF_Count) + sizeof (struct IBF_Key) + \ sizeof (struct IBF_KeyHash)) /** * Invertible bloom filter (IBF). * * An IBF is a counting bloom filter that has the ability to restore * the hashes of its stored elements with high probability. */ struct InvertibleBloomFilter { /** * How many cells does this IBF have? */ uint32_t size; /** * In how many cells do we hash one element? * Usually 4 or 3. */ uint8_t hash_num; /** * Xor sums of the elements' keys, used to identify the elements. * Array of 'size' elements. */ struct IBF_Key *key_sum; /** * Xor sums of the hashes of the keys of inserted elements. * Array of 'size' elements. */ struct IBF_KeyHash *key_hash_sum; /** * How many times has a bucket been hit? * Can be negative, as a result of IBF subtraction. * Array of 'size' elements. */ struct IBF_Count *count; }; /** * Write buckets from an ibf to a buffer. * Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf. * * @param ibf the ibf to write * @param start with which bucket to start * @param count how many buckets to write * @param buf buffer to write the data to */ void ibf_write_slice (const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf); /** * Read buckets from a buffer into an ibf. * * @param buf pointer to the buffer to read from * @param start which bucket to start at * @param count how many buckets to read * @param ibf the ibf to read from */ void ibf_read_slice (const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf); /** * Create a key from a hashcode. * * @param hash the hashcode * @return a key */ struct IBF_Key ibf_key_from_hashcode (const struct GNUNET_HashCode *hash); /** * Create a hashcode from a key, by replicating the key * until the hascode is filled * * @param key the key * @param dst hashcode to store the result in */ void ibf_hashcode_from_key (struct IBF_Key key, struct GNUNET_HashCode *dst); /** * Create an invertible bloom filter. * * @param size number of IBF buckets * @param hash_num number of buckets one element is hashed in, usually 3 or 4 * @return the newly created invertible bloom filter */ struct InvertibleBloomFilter * ibf_create (uint32_t size, uint8_t hash_num); /** * Insert a key into an IBF. * * @param ibf the IBF * @param key the element's hash code */ void ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key); /** * Remove a key from an IBF. * * @param ibf the IBF * @param key the element's hash code */ void ibf_remove (struct InvertibleBloomFilter *ibf, struct IBF_Key key); /** * Subtract ibf2 from ibf1, storing the result in ibf1. * The two IBF's must have the same parameters size and hash_num. * * @param ibf1 IBF that is subtracted from * @param ibf2 IBF that will be subtracted from ibf1 */ void ibf_subtract (struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2); /** * Decode and remove an element from the IBF, if possible. * * @param ibf the invertible bloom filter to decode * @param ret_side sign of the cell's count where the decoded element came from. * A negative sign indicates that the element was recovered * resides in an IBF that was previously subtracted from. * @param ret_id receives the hash code of the decoded element, if successful * @return GNUNET_YES if decoding an element was successful, * GNUNET_NO if the IBF is empty, * GNUNET_SYSERR if the decoding has failed */ int ibf_decode (struct InvertibleBloomFilter *ibf, int *ret_side, struct IBF_Key *ret_id); /** * Create a copy of an IBF, the copy has to be destroyed properly. * * @param ibf the IBF to copy */ struct InvertibleBloomFilter * ibf_dup (const struct InvertibleBloomFilter *ibf); /** * Destroy all resources associated with the invertible bloom filter. * No more ibf_*-functions may be called on ibf after calling destroy. * * @param ibf the intertible bloom filter to destroy */ void ibf_destroy (struct InvertibleBloomFilter *ibf); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/set/test_set_intersection_result_full.c0000644000175000017500000001504512272425070020606 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/test_set_intersection_result_full.c * @brief testcase for full result mode of the intersection set operation */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_set_service.h" static int ret; static struct GNUNET_PeerIdentity local_id; static struct GNUNET_HashCode app_id; static struct GNUNET_SET_Handle *set1; static struct GNUNET_SET_Handle *set2; static struct GNUNET_SET_ListenHandle *listen_handle; const static struct GNUNET_CONFIGURATION_Handle *config; static int iter_count; static void result_cb_set1 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { switch (status) { case GNUNET_SET_STATUS_OK: printf ("set 1: got element\n"); break; case GNUNET_SET_STATUS_FAILURE: printf ("set 1: failure\n"); ret = 1; break; case GNUNET_SET_STATUS_DONE: printf ("set 1: done\n"); GNUNET_SET_destroy (set1); break; default: GNUNET_assert (0); } } static void result_cb_set2 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { switch (status) { case GNUNET_SET_STATUS_OK: printf ("set 2: got element\n"); break; case GNUNET_SET_STATUS_FAILURE: printf ("set 2: failure\n"); ret = 1; break; case GNUNET_SET_STATUS_DONE: printf ("set 2: done\n"); GNUNET_SET_destroy (set2); break; default: GNUNET_assert (0); } } static void listen_cb (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request) { struct GNUNET_SET_OperationHandle *oh; GNUNET_assert (NULL != context_msg); GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_TEST); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "listen cb called\n"); GNUNET_SET_listen_cancel (listen_handle); oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_FULL, result_cb_set2, NULL); GNUNET_SET_commit (oh, set2); } /** * Start the set operation. * * @param cls closure, unused */ static void start (void *cls) { struct GNUNET_SET_OperationHandle *oh; struct GNUNET_MessageHeader context_msg; context_msg.size = htons (sizeof context_msg); context_msg.type = htons (GNUNET_MESSAGE_TYPE_TEST); listen_handle = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_INTERSECTION, &app_id, listen_cb, NULL); oh = GNUNET_SET_prepare (&local_id, &app_id, &context_msg, 42, GNUNET_SET_RESULT_FULL, result_cb_set1, NULL); GNUNET_SET_commit (oh, set1); } /** * Initialize the second set, continue * * @param cls closure, unused */ static void init_set2 (void *cls) { struct GNUNET_SET_Element element; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initializing set 2\n"); element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, NULL, NULL); element.data = "quux"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, NULL, NULL); element.data = "baz"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, start, NULL); } /** * Initialize the first set, continue. */ static void init_set1 (void) { struct GNUNET_SET_Element element; element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (set1, &element, NULL, NULL); element.data = "bar"; element.size = strlen(element.data); GNUNET_SET_add_element (set1, &element, init_set2, NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized set 1\n"); } static int iter_cb (void *cls, const struct GNUNET_SET_Element *element) { if (NULL == element) { GNUNET_assert (iter_count == 3); GNUNET_SET_destroy (cls); return GNUNET_YES; } printf ("iter: got element\n"); iter_count++; return GNUNET_YES; } static void test_iter () { struct GNUNET_SET_Element element; struct GNUNET_SET_Handle *iter_set; iter_set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_INTERSECTION); element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); element.data = "bar"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); element.data = "quux"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); GNUNET_SET_iterate (iter_set, iter_cb, iter_set); } /** * Signature of the 'main' function for a (single-peer) testcase that * is run using 'GNUNET_TESTING_peer_run'. * * @param cls closure * @param cfg configuration of the peer that was started * @param peer identity of the peer that was created */ static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { config = cfg; GNUNET_CRYPTO_get_peer_identity (cfg, &local_id); printf ("my id (from CRYPTO): %s\n", GNUNET_i2s (&local_id)); GNUNET_TESTING_peer_get_identity (peer, &local_id); printf ("my id (from TESTING): %s\n", GNUNET_i2s (&local_id)); test_iter (); set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION); set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_INTERSECTION); GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id); /* test the real set reconciliation */ init_set1 (); } int main (int argc, char **argv) { if (0 != GNUNET_TESTING_peer_run ("test_set_api", "test_set.conf", &run, NULL)) { return 0; } return ret; } gnunet-0.10.1/src/set/Makefile.in0000644000175000017500000013762212320752064013455 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-set-profiler$(EXEEXT) \ gnunet-set-ibf-profiler$(EXEEXT) libexec_PROGRAMS = gnunet-service-set$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = test_set_api$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_set_union_result_full$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_set_intersection_result_full$(EXEEXT) subdir = src/set DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/set.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = set.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetset_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetset_la_OBJECTS = set_api.lo libgnunetset_la_OBJECTS = $(am_libgnunetset_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetset_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetset_la_LDFLAGS) $(LDFLAGS) \ -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_service_set_OBJECTS = gnunet-service-set.$(OBJEXT) \ gnunet-service-set_union.$(OBJEXT) \ gnunet-service-set_intersection.$(OBJEXT) ibf.$(OBJEXT) \ strata_estimator.$(OBJEXT) gnunet_service_set_OBJECTS = $(am_gnunet_service_set_OBJECTS) gnunet_service_set_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(am__DEPENDENCIES_1) am_gnunet_set_ibf_profiler_OBJECTS = \ gnunet-set-ibf-profiler.$(OBJEXT) ibf.$(OBJEXT) gnunet_set_ibf_profiler_OBJECTS = \ $(am_gnunet_set_ibf_profiler_OBJECTS) gnunet_set_ibf_profiler_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_gnunet_set_profiler_OBJECTS = gnunet-set-profiler.$(OBJEXT) gnunet_set_profiler_OBJECTS = $(am_gnunet_set_profiler_OBJECTS) am_test_set_api_OBJECTS = test_set_api.$(OBJEXT) test_set_api_OBJECTS = $(am_test_set_api_OBJECTS) am_test_set_intersection_result_full_OBJECTS = \ test_set_intersection_result_full.$(OBJEXT) test_set_intersection_result_full_OBJECTS = \ $(am_test_set_intersection_result_full_OBJECTS) am_test_set_union_result_full_OBJECTS = \ test_set_union_result_full.$(OBJEXT) test_set_union_result_full_OBJECTS = \ $(am_test_set_union_result_full_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetset_la_SOURCES) $(gnunet_service_set_SOURCES) \ $(gnunet_set_ibf_profiler_SOURCES) \ $(gnunet_set_profiler_SOURCES) $(test_set_api_SOURCES) \ $(test_set_intersection_result_full_SOURCES) \ $(test_set_union_result_full_SOURCES) DIST_SOURCES = $(libgnunetset_la_SOURCES) \ $(gnunet_service_set_SOURCES) \ $(gnunet_set_ibf_profiler_SOURCES) \ $(gnunet_set_profiler_SOURCES) $(test_set_api_SOURCES) \ $(test_set_intersection_result_full_SOURCES) \ $(test_set_union_result_full_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ set.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage lib_LTLIBRARIES = \ libgnunetset.la gnunet_set_profiler_SOURCES = \ gnunet-set-profiler.c gnunet_set_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/set/libgnunetset.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(GN_LIBINTL) gnunet_set_profiler_DEPENDENCIES = \ libgnunetset.la gnunet_set_ibf_profiler_SOURCES = \ gnunet-set-ibf-profiler.c \ ibf.c gnunet_set_ibf_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_set_SOURCES = \ gnunet-service-set.c gnunet-service-set.h \ gnunet-service-set_union.c \ gnunet-service-set_intersection.c \ ibf.c ibf.h \ strata_estimator.c strata_estimator.h \ set_protocol.h gnunet_service_set_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(GN_LIBINTL) libgnunetset_la_SOURCES = \ set_api.c set.h libgnunetset_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetset_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_set_api_SOURCES = \ test_set_api.c test_set_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/set/libgnunetset.la test_set_api_DEPENDENCIES = \ libgnunetset.la test_set_union_result_full_SOURCES = \ test_set_union_result_full.c test_set_union_result_full_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/set/libgnunetset.la test_set_union_result_full_DEPENDENCIES = \ libgnunetset.la test_set_intersection_result_full_SOURCES = \ test_set_intersection_result_full.c test_set_intersection_result_full_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/set/libgnunetset.la test_set_intersection_result_full_DEPENDENCIES = \ libgnunetset.la EXTRA_DIST = \ test_set.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/set/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/set/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): set.conf: $(top_builddir)/config.status $(srcdir)/set.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetset.la: $(libgnunetset_la_OBJECTS) $(libgnunetset_la_DEPENDENCIES) $(EXTRA_libgnunetset_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetset_la_LINK) -rpath $(libdir) $(libgnunetset_la_OBJECTS) $(libgnunetset_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-service-set$(EXEEXT): $(gnunet_service_set_OBJECTS) $(gnunet_service_set_DEPENDENCIES) $(EXTRA_gnunet_service_set_DEPENDENCIES) @rm -f gnunet-service-set$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_set_OBJECTS) $(gnunet_service_set_LDADD) $(LIBS) gnunet-set-ibf-profiler$(EXEEXT): $(gnunet_set_ibf_profiler_OBJECTS) $(gnunet_set_ibf_profiler_DEPENDENCIES) $(EXTRA_gnunet_set_ibf_profiler_DEPENDENCIES) @rm -f gnunet-set-ibf-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_set_ibf_profiler_OBJECTS) $(gnunet_set_ibf_profiler_LDADD) $(LIBS) gnunet-set-profiler$(EXEEXT): $(gnunet_set_profiler_OBJECTS) $(gnunet_set_profiler_DEPENDENCIES) $(EXTRA_gnunet_set_profiler_DEPENDENCIES) @rm -f gnunet-set-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_set_profiler_OBJECTS) $(gnunet_set_profiler_LDADD) $(LIBS) test_set_api$(EXEEXT): $(test_set_api_OBJECTS) $(test_set_api_DEPENDENCIES) $(EXTRA_test_set_api_DEPENDENCIES) @rm -f test_set_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_set_api_OBJECTS) $(test_set_api_LDADD) $(LIBS) test_set_intersection_result_full$(EXEEXT): $(test_set_intersection_result_full_OBJECTS) $(test_set_intersection_result_full_DEPENDENCIES) $(EXTRA_test_set_intersection_result_full_DEPENDENCIES) @rm -f test_set_intersection_result_full$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_set_intersection_result_full_OBJECTS) $(test_set_intersection_result_full_LDADD) $(LIBS) test_set_union_result_full$(EXEEXT): $(test_set_union_result_full_OBJECTS) $(test_set_union_result_full_DEPENDENCIES) $(EXTRA_test_set_union_result_full_DEPENDENCIES) @rm -f test_set_union_result_full$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_set_union_result_full_OBJECTS) $(test_set_union_result_full_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-set.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-set_intersection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-set_union.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-set-ibf-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-set-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ibf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strata_estimator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_set_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_set_intersection_result_full.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_set_union_result_full.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_set_api.log: test_set_api$(EXEEXT) @p='test_set_api$(EXEEXT)'; \ b='test_set_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_set_union_result_full.log: test_set_union_result_full$(EXEEXT) @p='test_set_union_result_full$(EXEEXT)'; \ b='test_set_union_result_full'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_set_intersection_result_full.log: test_set_intersection_result_full$(EXEEXT) @p='test_set_intersection_result_full$(EXEEXT)'; \ b='test_set_intersection_result_full'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/set/gnunet-service-set.c0000644000175000017500000012234212276375236015310 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/gnunet-service-set.c * @brief two-peer set operations * @author Florian Dold */ #include "gnunet-service-set.h" #include "set_protocol.h" /** * State of an operation where the peer has connected to us, but is not yet * evaluating a set operation. Once the peer has sent a concrete request, and * the client has accepted or rejected it, this information will be deleted * and replaced by the real set operation state. */ struct OperationState { /** * The identity of the requesting peer. Needs to * be stored here as the op spec might not have been created yet. */ struct GNUNET_PeerIdentity peer; /** * Unique request id for the request from * a remote peer, sent to the client, which will * accept or reject the request. * Set to '0' iff the request has not been * suggested yet. */ uint32_t suggest_id; /** * Timeout task, if the incoming peer has not been accepted * after the timeout, it will be disconnected. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; /** * A listener is inhabited by a client, and * waits for evaluation requests from remote peers. */ struct Listener { /** * Listeners are held in a doubly linked list. */ struct Listener *next; /** * Listeners are held in a doubly linked list. */ struct Listener *prev; /** * Client that owns the listener. * Only one client may own a listener. */ struct GNUNET_SERVER_Client *client; /** * Message queue for the client */ struct GNUNET_MQ_Handle *client_mq; /** * The type of the operation. */ enum GNUNET_SET_OperationType operation; /** * Application ID for the operation, used to distinguish * multiple operations of the same type with the same peer. */ struct GNUNET_HashCode app_id; }; /** * Configuration of our local peer. */ static const struct GNUNET_CONFIGURATION_Handle *configuration; /** * Handle to the mesh service, used * to listen for and connect to remote peers. */ static struct GNUNET_MESH_Handle *mesh; /** * Sets are held in a doubly linked list. */ static struct Set *sets_head; /** * Sets are held in a doubly linked list. */ static struct Set *sets_tail; /** * Listeners are held in a doubly linked list. */ static struct Listener *listeners_head; /** * Listeners are held in a doubly linked list. */ static struct Listener *listeners_tail; /** * Incoming sockets from remote peers are * held in a doubly linked list. */ static struct Operation *incoming_head; /** * Incoming sockets from remote peers are * held in a doubly linked list. */ static struct Operation *incoming_tail; /** * Counter for allocating unique IDs for clients, * used to identify incoming operation requests from remote peers, * that the client can choose to accept or refuse. */ static uint32_t suggest_id = 1; /** * Get set that is owned by the given client, if any. * * @param client client to look for * @return set that the client owns, NULL if the client * does not own a set */ static struct Set * set_get (struct GNUNET_SERVER_Client *client) { struct Set *set; for (set = sets_head; NULL != set; set = set->next) if (set->client == client) return set; return NULL; } /** * Get the listener associated with the given client, if any. * * @param client the client * @return listener associated with the client, NULL * if there isn't any */ static struct Listener * listener_get (struct GNUNET_SERVER_Client *client) { struct Listener *listener; for (listener = listeners_head; NULL != listener; listener = listener->next) if (listener->client == client) return listener; return NULL; } /** * Get the incoming socket associated with the given id. * * @param id id to look for * @return the incoming socket associated with the id, * or NULL if there is none */ static struct Operation * get_incoming (uint32_t id) { struct Operation *op; for (op = incoming_head; NULL != op; op = op->next) if (op->state->suggest_id == id) { // FIXME: remove this assertion once the corresponding bug is gone! GNUNET_assert (GNUNET_YES == op->is_incoming); return op; } return NULL; } /** * Destroy a listener, free all resources associated with it. * * @param listener listener to destroy */ static void listener_destroy (struct Listener *listener) { /* If the client is not dead yet, destroy it. * The client's destroy callback will destroy the listener again. */ if (NULL != listener->client) { struct GNUNET_SERVER_Client *client = listener->client; listener->client = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting listener client\n"); GNUNET_SERVER_client_disconnect (client); return; } if (NULL != listener->client_mq) { GNUNET_MQ_destroy (listener->client_mq); listener->client_mq = NULL; } GNUNET_CONTAINER_DLL_remove (listeners_head, listeners_tail, listener); GNUNET_free (listener); } /** * Collect and destroy elements that are not needed anymore, because * their lifetime (as determined by their generation) does not overlap with any active * set operation. * * We hereby replace the old element hashmap with a new one, instead of removing elements. */ void collect_generation_garbage (struct Set *set) { struct GNUNET_CONTAINER_MultiHashMapIterator *iter; struct ElementEntry *ee; struct GNUNET_CONTAINER_MultiHashMap *new_elements; int res; struct Operation *op; new_elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); iter = GNUNET_CONTAINER_multihashmap_iterator_create (set->elements); while (GNUNET_OK == (res = GNUNET_CONTAINER_multihashmap_iterator_next (iter, NULL, (const void **) &ee))) { if (GNUNET_NO == ee->removed) goto still_needed; for (op = set->ops_head; NULL != op; op = op->next) if ((op->generation_created >= ee->generation_added) && (op->generation_created < ee->generation_removed)) goto still_needed; GNUNET_free (ee); continue; still_needed: // we don't expect collisions, thus the replace option GNUNET_CONTAINER_multihashmap_put (new_elements, &ee->element_hash, ee, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); } GNUNET_CONTAINER_multihashmap_iterator_destroy (iter); GNUNET_CONTAINER_multihashmap_destroy (set->elements); set->elements = new_elements; } /** * Destroy the given operation. Call the implementation-specific cancel function * of the operation. Disconnects from the remote peer. * Does not disconnect the client, as there may be multiple operations per set. * * @param op operation to destroy */ void _GSS_operation_destroy (struct Operation *op) { struct Set *set; struct GNUNET_MESH_Channel *channel; if (NULL == op->vt) return; set = op->spec->set; GNUNET_assert (GNUNET_NO == op->is_incoming); GNUNET_assert (NULL != op->spec); GNUNET_CONTAINER_DLL_remove (op->spec->set->ops_head, op->spec->set->ops_tail, op); op->vt->cancel (op); op->vt = NULL; if (NULL != op->spec) { if (NULL != op->spec->context_msg) { GNUNET_free (op->spec->context_msg); op->spec->context_msg = NULL; } GNUNET_free (op->spec); op->spec = NULL; } if (NULL != op->mq) { GNUNET_MQ_destroy (op->mq); op->mq = NULL; } if (NULL != (channel = op->channel)) { op->channel = NULL; GNUNET_MESH_channel_destroy (channel); } collect_generation_garbage (set); /* We rely on the channel end handler to free 'op'. When 'op->channel' was NULL, * there was a channel end handler that will free 'op' on the call stack. */ } /** * Iterator over hash map entries to free * element entries. * * @param cls closure * @param key current key code * @param value a `struct ElementEntry *` to be free'd * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int destroy_elements_iterator (void *cls, const struct GNUNET_HashCode * key, void *value) { struct ElementEntry *ee = value; GNUNET_free (ee); return GNUNET_YES; } /** * Destroy a set, and free all resources associated with it. * * @param set the set to destroy */ static void set_destroy (struct Set *set) { /* If the client is not dead yet, destroy it. * The client's destroy callback will destroy the set again. * We do this so that the channel end handler still has a valid set handle * to destroy. */ if (NULL != set->client) { struct GNUNET_SERVER_Client *client = set->client; set->client = NULL; GNUNET_SERVER_client_disconnect (client); return; } GNUNET_assert (NULL != set->state); while (NULL != set->ops_head) _GSS_operation_destroy (set->ops_head); set->vt->destroy_set (set->state); set->state = NULL; if (NULL != set->client_mq) { GNUNET_MQ_destroy (set->client_mq); set->client_mq = NULL; } if (NULL != set->iter) { GNUNET_CONTAINER_multihashmap_iterator_destroy (set->iter); set->iter = NULL; } GNUNET_CONTAINER_DLL_remove (sets_head, sets_tail, set); if (NULL != set->elements) { // free all elements in the hashtable, before destroying the table GNUNET_CONTAINER_multihashmap_iterate (set->elements, destroy_elements_iterator, NULL); GNUNET_CONTAINER_multihashmap_destroy (set->elements); set->elements = NULL; } GNUNET_free (set); } /** * Clean up after a client has disconnected * * @param cls closure, unused * @param client the client to clean up after */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct Set *set; struct Listener *listener; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected, cleaning up\n"); set = set_get (client); if (NULL != set) { set->client = NULL; set_destroy (set); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(client's set destroyed)\n"); } listener = listener_get (client); if (NULL != listener) { listener->client = NULL; listener_destroy (listener); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "(client's listener destroyed)\n"); } } /** * Destroy an incoming request from a remote peer * * @param incoming remote request to destroy */ static void incoming_destroy (struct Operation *incoming) { GNUNET_assert (GNUNET_YES == incoming->is_incoming); GNUNET_CONTAINER_DLL_remove (incoming_head, incoming_tail, incoming); if (GNUNET_SCHEDULER_NO_TASK != incoming->state->timeout_task) { GNUNET_SCHEDULER_cancel (incoming->state->timeout_task); incoming->state->timeout_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_assert (NULL != incoming->state); GNUNET_free (incoming->state); // make sure that the tunnel end handler will not // destroy us again incoming->vt = NULL; incoming->state = NULL; if (NULL != incoming->mq) { GNUNET_MQ_destroy (incoming->mq); incoming->mq = NULL; } if (NULL != incoming->channel) { GNUNET_MESH_channel_destroy (incoming->channel); incoming->channel = NULL; } } /** * remove & free state of the operation from the incoming list * * @param incoming the element to remove */ static void incoming_retire (struct Operation *incoming) { GNUNET_assert (GNUNET_YES == incoming->is_incoming); incoming->is_incoming = GNUNET_NO; GNUNET_assert (NULL != incoming->state); GNUNET_free (incoming->state); incoming->state = NULL; GNUNET_CONTAINER_DLL_remove (incoming_head, incoming_tail, incoming); } /** * Find a listener that is interested in the given operation type * and application id. * * @param op operation type to look for * @param app_id application id to look for * @return a matching listener, or NULL if no listener matches the * given operation and application id */ static struct Listener * listener_get_by_target (enum GNUNET_SET_OperationType op, const struct GNUNET_HashCode *app_id) { struct Listener *l; for (l = listeners_head; NULL != l; l = l->next) { if (l->operation != op) continue; if (0 != GNUNET_CRYPTO_hash_cmp (app_id, &l->app_id)) continue; return l; } return NULL; } /** * Suggest the given request to the listener. The listening client can then * accept or reject the remote request. * * @param incoming the incoming peer with the request to suggest * @param listener the listener to suggest the request to */ static void incoming_suggest (struct Operation *incoming, struct Listener *listener) { struct GNUNET_MQ_Envelope *mqm; struct GNUNET_SET_RequestMessage *cmsg; GNUNET_assert (GNUNET_YES == incoming->is_incoming); GNUNET_assert (NULL != incoming->state); GNUNET_assert (NULL != incoming->spec); GNUNET_assert (0 == incoming->state->suggest_id); incoming->state->suggest_id = suggest_id++; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != incoming->state->timeout_task); GNUNET_SCHEDULER_cancel (incoming->state->timeout_task); incoming->state->timeout_task = GNUNET_SCHEDULER_NO_TASK; mqm = GNUNET_MQ_msg_nested_mh (cmsg, GNUNET_MESSAGE_TYPE_SET_REQUEST, incoming->spec->context_msg); GNUNET_assert (NULL != mqm); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "suggesting request with accept id %u\n", incoming->state->suggest_id); cmsg->accept_id = htonl (incoming->state->suggest_id); cmsg->peer_id = incoming->spec->peer; GNUNET_MQ_send (listener->client_mq, mqm); } /** * Handle a request for a set operation from * another peer. * * This msg is expected as the first and only msg handled through the * non-operation bound virtual table, acceptance of this operation replaces * our virtual table and subsequent msgs would be routed differently. * * @param op the operation state * @param mh the received message * @return #GNUNET_OK if the channel should be kept alive, * #GNUNET_SYSERR to destroy the channel */ static int handle_incoming_msg (struct Operation *op, const struct GNUNET_MessageHeader *mh) { const struct OperationRequestMessage *msg = (const struct OperationRequestMessage *) mh; struct Listener *listener; struct OperationSpecification *spec; GNUNET_assert (GNUNET_YES == op->is_incoming); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got op request\n"); if (GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST != ntohs (mh->type)) { GNUNET_break_op (0); return GNUNET_SYSERR; } /* double operation request */ if (NULL != op->spec) { GNUNET_break_op (0); return GNUNET_SYSERR; } spec = GNUNET_new (struct OperationSpecification); spec->context_msg = GNUNET_MQ_extract_nested_mh (msg); // for simplicity we just backup the context msg instead of rebuilding it later on if (NULL != spec->context_msg) spec->context_msg = GNUNET_copy_message (spec->context_msg); spec->operation = ntohl (msg->operation); spec->app_id = msg->app_id; spec->salt = ntohl (msg->salt); spec->peer = op->state->peer; spec->remote_element_count = ntohl (msg->element_count); op->spec = spec; if ( (NULL != spec->context_msg) && (ntohs (spec->context_msg->size) > GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received P2P operation request (op %u, app %s)\n", ntohl (msg->operation), GNUNET_h2s (&msg->app_id)); listener = listener_get_by_target (ntohl (msg->operation), &msg->app_id); if (NULL == listener) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "no listener matches incoming request, waiting with timeout\n"); return GNUNET_OK; } incoming_suggest (op, listener); return GNUNET_OK; } /** * Send the next element of a set to the set's client. The next element is given by * the set's current hashmap iterator. The set's iterator will be set to NULL if there * are no more elements in the set. The caller must ensure that the set's iterator is * valid. * * @param set set that should send its next element to its client */ static void send_client_element (struct Set *set) { int ret; struct ElementEntry *ee; struct GNUNET_MQ_Envelope *ev; GNUNET_assert (NULL != set->iter); ret = GNUNET_CONTAINER_multihashmap_iterator_next (set->iter, NULL, (const void **) &ee); if (GNUNET_NO == ret) { ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_ITER_DONE); GNUNET_CONTAINER_multihashmap_iterator_destroy (set->iter); set->iter = NULL; } else { struct GNUNET_SET_IterResponseMessage *msg; GNUNET_assert (NULL != ee); ev = GNUNET_MQ_msg_extra (msg, ee->element.size, GNUNET_MESSAGE_TYPE_SET_ITER_ELEMENT); memcpy (&msg[1], ee->element.data, ee->element.size); msg->element_type = ee->element.type; } GNUNET_MQ_send (set->client_mq, ev); } /** * Called when a client wants to iterate the elements of a set. * * @param cls unused * @param client client that sent the message * @param m message sent by the client */ static void handle_client_iterate (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { struct Set *set; // iterate over a non existing set set = set_get (client); if (NULL == set) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } // only one concurrent iterate-action per set if (NULL != set->iter) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "iterating union set with %u elements\n", GNUNET_CONTAINER_multihashmap_size (set->elements)); GNUNET_SERVER_receive_done (client, GNUNET_OK); set->iter = GNUNET_CONTAINER_multihashmap_iterator_create (set->elements); send_client_element (set); } /** * Called when a client wants to create a new set. * * @param cls unused * @param client client that sent the message * @param m message sent by the client */ static void handle_client_create_set (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { const struct GNUNET_SET_CreateMessage *msg; struct Set *set; msg = (const struct GNUNET_SET_CreateMessage *) m; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client created new set (operation %u)\n", ntohs (msg->operation)); // max. one set per client! if (NULL != set_get (client)) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } set = GNUNET_new (struct Set); switch (ntohs (msg->operation)) { case GNUNET_SET_OPERATION_INTERSECTION: set->vt = _GSS_intersection_vt (); break; case GNUNET_SET_OPERATION_UNION: set->vt = _GSS_union_vt (); break; default: GNUNET_free (set); GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } set->state = set->vt->create (); set->elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); set->client = client; set->client_mq = GNUNET_MQ_queue_for_server_client (client); GNUNET_CONTAINER_DLL_insert (sets_head, sets_tail, set); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Called when a client wants to create a new listener. * * @param cls unused * @param client client that sent the message * @param m message sent by the client */ static void handle_client_listen (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { const struct GNUNET_SET_ListenMessage *msg; struct Listener *listener; struct Operation *op; msg = (const struct GNUNET_SET_ListenMessage *) m; /* max. one per client! */ if (NULL != listener_get (client)) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } listener = GNUNET_new (struct Listener); listener->client = client; listener->client_mq = GNUNET_MQ_queue_for_server_client (client); listener->app_id = msg->app_id; listener->operation = ntohl (msg->operation); GNUNET_CONTAINER_DLL_insert_tail (listeners_head, listeners_tail, listener); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new listener created (op %u, app %s)\n", listener->operation, GNUNET_h2s (&listener->app_id)); /* check for incoming requests the listener is interested in */ for (op = incoming_head; NULL != op; op = op->next) { if (NULL == op->spec) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "request has no spec yet\n"); continue; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "considering (op: %u, app: %s, suggest: %u)\n", op->spec->operation, GNUNET_h2s (&op->spec->app_id), op->state->suggest_id); /* don't consider the incoming request if it has been already suggested to a listener */ if (0 != op->state->suggest_id) continue; if (listener->operation != op->spec->operation) continue; if (0 != GNUNET_CRYPTO_hash_cmp (&listener->app_id, &op->spec->app_id)) continue; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "request suggested\n"); incoming_suggest (op, listener); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "considered all incoming requests\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Called when the listening client rejects an operation * request by another peer. * * @param cls unused * @param client client that sent the message * @param m message sent by the client */ static void handle_client_reject (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { struct Operation *incoming; const struct GNUNET_SET_AcceptRejectMessage *msg; msg = (const struct GNUNET_SET_AcceptRejectMessage *) m; GNUNET_break (0 == ntohl (msg->request_id)); // no matching incoming operation for this reject incoming = get_incoming (ntohl (msg->accept_reject_id)); if (NULL == incoming) { GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer request rejected by client\n"); GNUNET_MESH_channel_destroy (incoming->channel); //channel destruction handler called immediately upon destruction GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Called when a client wants to add/remove an element to/from a * set it inhabits. * * @param cls unused * @param client client that sent the message * @param m message sent by the client */ static void handle_client_add_remove (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { struct Set *set; const struct GNUNET_SET_ElementMessage *msg; struct GNUNET_SET_Element el; struct ElementEntry *ee; // client without a set requested an operation set = set_get (client); if (NULL == set) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); msg = (const struct GNUNET_SET_ElementMessage *) m; el.size = ntohs (m->size) - sizeof *msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client ins/rem element of size %u\n", el.size); el.data = &msg[1]; if (GNUNET_MESSAGE_TYPE_SET_REMOVE == ntohs (m->type)) { struct GNUNET_HashCode hash; GNUNET_CRYPTO_hash (el.data, el.size, &hash); ee = GNUNET_CONTAINER_multihashmap_get (set->elements, &hash); if (NULL == ee) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "client tried to remove non-existing element\n"); return; } if (GNUNET_YES == ee->removed) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "client tried to remove element twice\n"); return; } ee->removed = GNUNET_YES; ee->generation_removed = set->current_generation; set->vt->remove (set->state, ee); } else { struct ElementEntry *ee_dup; ee = GNUNET_malloc (el.size + sizeof *ee); ee->element.size = el.size; memcpy (&ee[1], el.data, el.size); ee->element.data = &ee[1]; ee->generation_added = set->current_generation; ee->remote = GNUNET_NO; GNUNET_CRYPTO_hash (ee->element.data, el.size, &ee->element_hash); ee_dup = GNUNET_CONTAINER_multihashmap_get (set->elements, &ee->element_hash); if (NULL != ee_dup) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "element inserted twice, ignoring\n"); GNUNET_free (ee); return; } GNUNET_CONTAINER_multihashmap_put (set->elements, &ee->element_hash, ee, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); set->vt->add (set->state, ee); } } /** * Called when a client wants to evaluate a set operation with another peer. * * @param cls unused * @param client client that sent the message * @param m message sent by the client */ static void handle_client_evaluate (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { struct Set *set; const struct GNUNET_SET_EvaluateMessage *msg; struct OperationSpecification *spec; struct Operation *op; set = set_get (client); if (NULL == set) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } msg = (const struct GNUNET_SET_EvaluateMessage *) m; spec = GNUNET_new (struct OperationSpecification); spec->operation = set->operation; spec->app_id = msg->app_id; spec->salt = ntohl (msg->salt); spec->peer = msg->target_peer; spec->set = set; spec->result_mode = ntohs (msg->result_mode); spec->client_request_id = ntohl (msg->request_id); spec->context_msg = GNUNET_MQ_extract_nested_mh (msg); // for simplicity we just backup the context msg instead of rebuilding it later on if (NULL != spec->context_msg) spec->context_msg = GNUNET_copy_message (spec->context_msg); op = GNUNET_new (struct Operation); op->spec = spec; op->generation_created = set->current_generation++; op->vt = set->vt; GNUNET_CONTAINER_DLL_insert (set->ops_head, set->ops_tail, op); op->channel = GNUNET_MESH_channel_create (mesh, op, &msg->target_peer, GNUNET_APPLICATION_TYPE_SET, GNUNET_MESH_OPTION_RELIABLE); op->mq = GNUNET_MESH_mq_create (op->channel); set->vt->evaluate (op); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle an ack from a client, and send the next element. * * @param cls unused * @param client the client * @param m the message */ static void handle_client_iter_ack (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { struct Set *set; // client without a set requested an operation set = set_get (client); if (NULL == set) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } // client sent an ack, but we were not expecting one if (NULL == set->iter) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } GNUNET_SERVER_receive_done (client, GNUNET_OK); send_client_element (set); } /** * Handle a request from the client to * cancel a running set operation. * * @param cls unused * @param client the client * @param mh the message */ static void handle_client_cancel (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *mh) { const struct GNUNET_SET_CancelMessage *msg = (const struct GNUNET_SET_CancelMessage *) mh; struct Set *set; struct Operation *op; int found; // client without a set requested an operation set = set_get (client); if (NULL == set) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client requested cancel for op %u\n", ntohl (msg->request_id)); found = GNUNET_NO; for (op = set->ops_head; NULL != op; op = op->next) { if (op->spec->client_request_id == ntohl (msg->request_id)) { found = GNUNET_YES; break; } } /* It may happen that the operation was destroyed due to * the other peer disconnecting. The client may not know about this * yet and try to cancel the (non non-existent) operation. */ if (GNUNET_NO != found) _GSS_operation_destroy (op); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client canceled non-existent op\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle a request from the client to accept * a set operation that came from a remote peer. * We forward the accept to the associated operation for handling * * @param cls unused * @param client the client * @param mh the message */ static void handle_client_accept (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *mh) { struct Set *set; const struct GNUNET_SET_AcceptRejectMessage *msg; struct Operation *op; msg = (const struct GNUNET_SET_AcceptRejectMessage *) mh; // client without a set requested an operation set = set_get (client); if (NULL == set) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } op = get_incoming (ntohl (msg->accept_reject_id)); /* it is not an error if the set op does not exist -- it may * have been destroyed when the partner peer disconnected. */ if (NULL == op) { struct GNUNET_SET_ResultMessage *result_message; struct GNUNET_MQ_Envelope *ev; ev = GNUNET_MQ_msg (result_message, GNUNET_MESSAGE_TYPE_SET_RESULT); result_message->request_id = msg->request_id; result_message->element_type = 0; result_message->result_status = htons (GNUNET_SET_STATUS_FAILURE); GNUNET_MQ_send (set->client_mq, ev); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client accepting %u\n", ntohl (msg->accept_reject_id)); GNUNET_assert (GNUNET_YES == op->is_incoming); op->spec->set = set; incoming_retire (op); GNUNET_assert (NULL != op->spec->set); GNUNET_assert (NULL != op->spec->set->vt); GNUNET_CONTAINER_DLL_insert (set->ops_head, set->ops_tail, op); op->spec->client_request_id = ntohl (msg->request_id); op->spec->result_mode = ntohs (msg->result_mode); op->generation_created = set->current_generation++; op->vt = op->spec->set->vt; GNUNET_assert (NULL != op->vt->accept); set->vt->accept (op); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Called to clean up, after a shutdown has been requested. * * @param cls closure * @param tc context information (why was this task triggered now) */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { while (NULL != incoming_head) incoming_destroy (incoming_head); while (NULL != listeners_head) listener_destroy (listeners_head); while (NULL != sets_head) set_destroy (sets_head); /* it's important to destroy mesh at the end, as all channels * must be destroyed before the mesh handle! */ if (NULL != mesh) { GNUNET_MESH_disconnect (mesh); mesh = NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handled shutdown request\n"); } /** * Timeout happens iff: * - we suggested an operation to our listener, * but did not receive a response in time * - we got the channel from a peer but no #GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST * - shutdown (obviously) * * @param cls channel context * @param tc context information (why was this task triggered now) */ static void incoming_timeout_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Operation *incoming = cls; incoming->state->timeout_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_YES == incoming->is_incoming); if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "remote peer timed out\n"); incoming_destroy (incoming); } /** * Terminates an incoming operation in case we have not yet received an * operation request. Called by the channel destruction handler. * * @param op the channel context */ static void handle_incoming_disconnect (struct Operation *op) { GNUNET_assert (GNUNET_YES == op->is_incoming); /* channel is already dead, incoming_destroy must not * destroy it ... */ op->channel = NULL; incoming_destroy (op); op->vt = NULL; } /** * Method called whenever another peer has added us to a channel * the other peer initiated. * Only called (once) upon reception of data with a message type which was * subscribed to in GNUNET_MESH_connect(). * * The channel context represents the operation itself and gets added to a DLL, * from where it gets looked up when our local listener client responds * to a proposed/suggested operation or connects and associates with this operation. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel * @param port Port this channel is for. * @param options Unused. * @return initial channel context for the channel * (can be NULL -- that's not an error) */ static void * channel_new_cb (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { struct Operation *incoming; static const struct SetVT incoming_vt = { .msg_handler = handle_incoming_msg, .peer_disconnect = handle_incoming_disconnect }; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new incoming channel\n"); if (GNUNET_APPLICATION_TYPE_SET != port) { GNUNET_break (0); GNUNET_MESH_channel_destroy (channel); return NULL; } incoming = GNUNET_new (struct Operation); incoming->is_incoming = GNUNET_YES; incoming->state = GNUNET_new (struct OperationState); incoming->state->peer = *initiator; incoming->channel = channel; incoming->mq = GNUNET_MESH_mq_create (incoming->channel); incoming->vt = &incoming_vt; incoming->state->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &incoming_timeout_cb, incoming); GNUNET_CONTAINER_DLL_insert_tail (incoming_head, incoming_tail, incoming); return incoming; } /** * Function called whenever a channel is destroyed. Should clean up * any associated state. It must NOT call * GNUNET_MESH_channel_destroy() on the channel. * * The peer_disconnect function is part of a a virtual table set initially either * when a peer creates a new channel with us (channel_new_cb), or once we create * a new channel ourselves (evaluate). * * Once we know the exact type of operation (union/intersection), the vt is * replaced with an operation specific instance (_GSS_[op]_vt). * * @param cls closure (set from GNUNET_MESH_connect()) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void channel_end_cb (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { struct Operation *op = channel_ctx; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "channel end cb called\n"); op->channel = NULL; /* the vt can be null if a client already requested canceling op. */ if (NULL != op->vt) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "calling peer disconnect due to channel end\n"); op->vt->peer_disconnect (op); } if (GNUNET_YES == op->keep) return; /* mesh will never call us with the context again! */ GNUNET_free (channel_ctx); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "channel end cb finished\n"); } /** * Functions with this signature are called whenever a message is * received via a mesh channel. * * The msg_handler is a virtual table set in initially either when a peer * creates a new channel with us (channel_new_cb), or once we create a new channel * ourselves (evaluate). * * Once we know the exact type of operation (union/intersection), the vt is * replaced with an operation specific instance (_GSS_[op]_vt). * * @param cls Closure (set from GNUNET_MESH_connect()). * @param channel Connection to the other end. * @param channel_ctx Place to store local state associated with the channel. * @param message The actual message. * @return #GNUNET_OK to keep the channel open, * #GNUNET_SYSERR to close it (signal serious error). */ static int dispatch_p2p_message (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct Operation *op = *channel_ctx; int ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "dispatching mesh message (type: %u)\n", ntohs (message->type)); /* do this before the handler, as the handler might kill the channel */ GNUNET_MESH_receive_done (channel); if (NULL != op->vt) ret = op->vt->msg_handler (op, message); else ret = GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handled mesh message (type: %u)\n", ntohs (message->type)); return ret; } /** * Function called by the service's run * method to run service-specific setup code. * * @param cls closure * @param server the initialized server * @param cfg configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg) { static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { {handle_client_accept, NULL, GNUNET_MESSAGE_TYPE_SET_ACCEPT, sizeof (struct GNUNET_SET_AcceptRejectMessage)}, {handle_client_iter_ack, NULL, GNUNET_MESSAGE_TYPE_SET_ITER_ACK, 0}, {handle_client_add_remove, NULL, GNUNET_MESSAGE_TYPE_SET_ADD, 0}, {handle_client_create_set, NULL, GNUNET_MESSAGE_TYPE_SET_CREATE, sizeof (struct GNUNET_SET_CreateMessage)}, {handle_client_iterate, NULL, GNUNET_MESSAGE_TYPE_SET_ITER_REQUEST, sizeof (struct GNUNET_MessageHeader)}, {handle_client_evaluate, NULL, GNUNET_MESSAGE_TYPE_SET_EVALUATE, 0}, {handle_client_listen, NULL, GNUNET_MESSAGE_TYPE_SET_LISTEN, sizeof (struct GNUNET_SET_ListenMessage)}, {handle_client_reject, NULL, GNUNET_MESSAGE_TYPE_SET_REJECT, sizeof (struct GNUNET_SET_AcceptRejectMessage)}, {handle_client_add_remove, NULL, GNUNET_MESSAGE_TYPE_SET_REMOVE, 0}, {handle_client_cancel, NULL, GNUNET_MESSAGE_TYPE_SET_CANCEL, sizeof (struct GNUNET_SET_CancelMessage)}, {NULL, NULL, 0, 0} }; static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = { {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST, 0}, {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_IBF, 0}, {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS, 0}, {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_DONE, 0}, {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS, 0}, {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_UNION_P2P_SE, 0}, {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO, 0}, {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF, 0}, {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF_PART, 0}, {NULL, 0, 0} }; static const uint32_t mesh_ports[] = {GNUNET_APPLICATION_TYPE_SET, 0}; configuration = cfg; GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); GNUNET_SERVER_add_handlers (server, server_handlers); mesh = GNUNET_MESH_connect (cfg, NULL, channel_new_cb, channel_end_cb, mesh_handlers, mesh_ports); if (NULL == mesh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not connect to mesh service\n")); return; } } /** * The main function for the set service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; ret = GNUNET_SERVICE_run (argc, argv, "set", GNUNET_SERVICE_OPTION_NONE, &run, NULL); return (GNUNET_OK == ret) ? 0 : 1; } /* end of gnunet-service-set.c */ gnunet-0.10.1/src/set/Makefile.am0000644000175000017500000000527312320751517013442 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ set.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif bin_PROGRAMS = \ gnunet-set-profiler gnunet-set-ibf-profiler libexec_PROGRAMS = \ gnunet-service-set lib_LTLIBRARIES = \ libgnunetset.la gnunet_set_profiler_SOURCES = \ gnunet-set-profiler.c gnunet_set_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/set/libgnunetset.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(GN_LIBINTL) gnunet_set_profiler_DEPENDENCIES = \ libgnunetset.la gnunet_set_ibf_profiler_SOURCES = \ gnunet-set-ibf-profiler.c \ ibf.c gnunet_set_ibf_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_set_SOURCES = \ gnunet-service-set.c gnunet-service-set.h \ gnunet-service-set_union.c \ gnunet-service-set_intersection.c \ ibf.c ibf.h \ strata_estimator.c strata_estimator.h \ set_protocol.h gnunet_service_set_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/block/libgnunetblock.la \ $(GN_LIBINTL) libgnunetset_la_SOURCES = \ set_api.c set.h libgnunetset_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetset_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) if HAVE_TESTING check_PROGRAMS = \ test_set_api test_set_union_result_full test_set_intersection_result_full endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_set_api_SOURCES = \ test_set_api.c test_set_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/set/libgnunetset.la test_set_api_DEPENDENCIES = \ libgnunetset.la test_set_union_result_full_SOURCES = \ test_set_union_result_full.c test_set_union_result_full_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/set/libgnunetset.la test_set_union_result_full_DEPENDENCIES = \ libgnunetset.la test_set_intersection_result_full_SOURCES = \ test_set_intersection_result_full.c test_set_intersection_result_full_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/set/libgnunetset.la test_set_intersection_result_full_DEPENDENCIES = \ libgnunetset.la EXTRA_DIST = \ test_set.conf gnunet-0.10.1/src/set/strata_estimator.h0000644000175000017500000000704312236140650015135 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/strata_estimator.h * @brief estimator of set difference * @author Florian Dold */ #ifndef GNUNET_CONSENSUS_STRATA_ESTIMATOR_H #define GNUNET_CONSENSUS_STRATA_ESTIMATOR_H #include "platform.h" #include "gnunet_common.h" #include "gnunet_util_lib.h" #ifdef __cplusplus extern "C" { #if 0 /* keep Emacsens' auto-indent happy */ } #endif #endif /** * A handle to a strata estimator. */ struct StrataEstimator { struct InvertibleBloomFilter **strata; unsigned int strata_count; unsigned int ibf_size; }; /** * Write the given strata estimator to the buffer. * * @param se strata estimator to serialize * @param buf buffer to write to, must be of appropriate size */ void strata_estimator_write (const struct StrataEstimator *se, void *buf); /** * Read strata from the buffer into the given strata * estimator. The strata estimator must already be allocated. * * @param buf buffer to read from * @param se strata estimator to write to */ void strata_estimator_read (const void *buf, struct StrataEstimator *se); /** * Create a new strata estimator with the given parameters. * * @param strata_count number of stratas, that is, number of ibfs in the estimator * @param ibf_size size of each ibf stratum * @param ibf_hashnum hashnum parameter of each ibf * @return a freshly allocated, empty strata estimator */ struct StrataEstimator * strata_estimator_create (unsigned int strata_count, uint32_t ibf_size, uint8_t ibf_hashnum); /** * Get an estimation of the symmetric difference of the elements * contained in both strata estimators. * * @param se1 first strata estimator * @param se2 second strata estimator * @return abs(|se1| - |se2|) */ unsigned int strata_estimator_difference (const struct StrataEstimator *se1, const struct StrataEstimator *se2); /** * Add a key to the strata estimator. * * @param se strata estimator to add the key to * @param key key to add */ void strata_estimator_insert (struct StrataEstimator *se, struct IBF_Key key); /** * Remove a key from the strata estimator. * * @param se strata estimator to remove the key from * @param key key to remove */ void strata_estimator_remove (struct StrataEstimator *se, struct IBF_Key key); /** * Destroy a strata estimator, free all of its resources. * * @param se strata estimator to destroy. */ void strata_estimator_destroy (struct StrataEstimator *se); /** * Make a copy of a strata estimator. * * @param se the strata estimator to copy * @return the copy */ struct StrataEstimator * strata_estimator_dup (struct StrataEstimator *se); #if 0 /* keep Emacsens' auto-indent happy */ { #endif #ifdef __cplusplus } #endif #endif gnunet-0.10.1/src/set/gnunet-service-set.h0000644000175000017500000002372712251551532015310 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/gnunet-service-set.h * @brief common components for the implementation the different set operations * @author Florian Dold */ #ifndef GNUNET_SERVICE_SET_H_PRIVATE #define GNUNET_SERVICE_SET_H_PRIVATE #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet_core_service.h" #include "gnunet_mesh_service.h" #include "gnunet_set_service.h" #include "set.h" /** * Implementation-specific set state. * Used as opaque pointer, and specified further * in the respective implementation. */ struct SetState; /** * Implementation-specific set operation. * Used as opaque pointer, and specified further * in the respective implementation. */ struct OperationState; /* forward declarations */ struct Set; struct ElementEntry; struct Operation; /** * Detail information about an operation. */ struct OperationSpecification { /** * The type of the operation. */ enum GNUNET_SET_OperationType operation; /** * The remove peer we evaluate the operation with */ struct GNUNET_PeerIdentity peer; /** * Application ID for the operation, used to distinguish * multiple operations of the same type with the same peer. */ struct GNUNET_HashCode app_id; /** * Context message, may be NULL. */ struct GNUNET_MessageHeader *context_msg; /** * Salt to use for the operation. */ uint32_t salt; /** * Remote peers element count */ uint32_t remote_element_count; /** * ID used to identify an operation between service and client */ uint32_t client_request_id; /** * Set associated with the operation, NULL until the spec has been associated * with a set. */ struct Set *set; /** * When are elements sent to the client, and which elements are sent? */ enum GNUNET_SET_ResultMode result_mode; }; /** * Signature of functions that create the implementation-specific * state for a set supporting a specific operation. * * @return a set state specific to the supported operation */ typedef struct SetState *(*CreateImpl) (void); /** * Signature of functions that implement the add/remove functionality * for a set supporting a specific operation. * * @param set implementation-specific set state * @param msg element message from the client */ typedef void (*AddRemoveImpl) (struct SetState *state, struct ElementEntry *ee); /** * Signature of functions that handle disconnection * of the remote peer. * * @param op the set operation, contains implementation-specific data */ typedef void (*PeerDisconnectImpl) (struct Operation *op); /** * Signature of functions that implement the destruction of the * implementation-specific set state. * * @param state the set state, contains implementation-specific data */ typedef void (*DestroySetImpl) (struct SetState *state); /** * Signature of functions that implement the creation of set operations * (currently evaluate and accept). * * @param op operation that is created, should be initialized by the implementation */ typedef void (*OpCreateImpl) (struct Operation *op); /** * Signature of functions that implement the message handling for * the different set operations. * * @param op operation state * @param msg received message * @return GNUNET_OK on success, GNUNET_SYSERR to * destroy the operation and the tunnel */ typedef int (*MsgHandlerImpl) (struct Operation *op, const struct GNUNET_MessageHeader *msg); /** * Signature of functions that implement operation cancellation * * @param op operation state */ typedef void (*CancelImpl) (struct Operation *op); /** * Dispatch table for a specific set operation. * Every set operation has to implement the callback * in this struct. */ struct SetVT { /** * Callback for the set creation. */ CreateImpl create; /** * Callback for element insertion */ AddRemoveImpl add; /** * Callback for element removal. */ AddRemoveImpl remove; /** * Callback for accepting a set operation request */ OpCreateImpl accept; /** * Callback for starting evaluation with a remote peer. */ OpCreateImpl evaluate; /** * Callback for destruction of the set state. */ DestroySetImpl destroy_set; /** * Callback for handling operation-specific messages. */ MsgHandlerImpl msg_handler; /** * Callback for handling the remote peer's * disconnect. */ PeerDisconnectImpl peer_disconnect; /** * Callback for canceling an operation by * its ID. */ CancelImpl cancel; }; /** * Information about an element element in the set. * All elements are stored in a hash-table * from their hash-code to their 'struct Element', * so that the remove and add operations are reasonably * fast. */ struct ElementEntry { /** * The actual element. The data for the element * should be allocated at the end of this struct. */ struct GNUNET_SET_Element element; /** * Hash of the element. * For set union: * Will be used to derive the different IBF keys * for different salts. */ struct GNUNET_HashCode element_hash; /** * Generation the element was added by the client. * Operations of earlier generations will not consider the element. */ unsigned int generation_added; /** * GNUNET_YES if the element has been removed in some generation. */ int removed; /** * Generation the element was removed by the client. * Operations of later generations will not consider the element. * Only valid if is_removed is GNUNET_YES. */ unsigned int generation_removed; /** * GNUNET_YES if the element is a remote element, and does not belong * to the operation's set. * * //TODO: Move to Union, unless additional set-operations are implemented ever */ int remote; }; struct Operation { /** * V-Table for the operation belonging * to the tunnel contest. * * Used for all operation specific operations after receiving the ops request */ const struct SetVT *vt; /** * Tunnel to the peer. */ struct GNUNET_MESH_Channel *channel; /** * Message queue for the tunnel. */ struct GNUNET_MQ_Handle *mq; /** * GNUNET_YES if this is not a "real" set operation yet, and we still * need to wait for the other peer to give us more details. */ int is_incoming; /** * Generation in which the operation handle * was created. */ unsigned int generation_created; /** * Detail information about the set operation, * including the set to use. * When 'spec' is NULL, the operation is not yet entirely * initialized. */ struct OperationSpecification *spec; /** * Operation-specific operation state. */ struct OperationState *state; /** * Evaluate operations are held in * a linked list. */ struct Operation *next; /** * Evaluate operations are held in * a linked list. */ struct Operation *prev; /** * Set to GNUNET_YES if the set service should not free * the operation, as it is still needed (e.g. in some scheduled task). */ int keep; }; /** * A set that supports a specific operation * with other peers. */ struct Set { /** * Client that owns the set. * Only one client may own a set. */ struct GNUNET_SERVER_Client *client; /** * Message queue for the client */ struct GNUNET_MQ_Handle *client_mq; /** * Type of operation supported for this set */ enum GNUNET_SET_OperationType operation; /** * Virtual table for this set. * Determined by the operation type of this set. * * Used only for Add/remove of elements and when receiving an incoming * operation from a remote peer. */ const struct SetVT *vt; /** * Sets are held in a doubly linked list. */ struct Set *next; /** * Sets are held in a doubly linked list. */ struct Set *prev; /** * Implementation-specific state. */ struct SetState *state; /** * Current state of iterating elements for the client. * NULL if we are not currently iterating. */ struct GNUNET_CONTAINER_MultiHashMapIterator *iter; /** * Maps 'struct GNUNET_HashCode' to 'struct ElementEntry'. */ struct GNUNET_CONTAINER_MultiHashMap *elements; /** * Current generation, that is, number of * previously executed operations on this set */ unsigned int current_generation; /** * Evaluate operations are held in * a linked list. */ struct Operation *ops_head; /** * Evaluate operations are held in * a linked list. */ struct Operation *ops_tail; }; /** * Destroy the given operation. Call the implementation-specific cancel function * of the operation. Disconnects from the remote peer. * Does not disconnect the client, as there may be multiple operations per set. * * @param op operation to destroy */ void _GSS_operation_destroy (struct Operation *op); /** * Get the table with implementing functions for * set union. * * @return the operation specific VTable */ const struct SetVT * _GSS_union_vt (void); /** * Get the table with implementing functions for * set intersection. * * @return the operation specific VTable */ const struct SetVT * _GSS_intersection_vt (void); #endif gnunet-0.10.1/src/set/test_set.conf0000644000175000017500000000074412236140650014101 00000000000000# @INLINE@ test_set_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-set/ [set] AUTOSTART = YES PORT = 2106 HOSTNAME = localhost BINARY = gnunet-service-set #PREFIX = valgrind #PREFIX = valgrind -v --leak-check=full #PREFIX = gdbserver :1234 ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-set.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES OPTIONS = -L INFO [transport] OPTIONS = -LERROR [testbed] OVERLAY_TOPOLOGY = CLIQUE gnunet-0.10.1/src/set/gnunet-service-set_intersection.c0000644000175000017500000007554412272425070020075 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/gnunet-service-set_intersection.c * @brief two-peer set intersection * @author Christian Fuchs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet-service-set.h" #include "gnunet_block_lib.h" #include "set_protocol.h" #include #define BLOOMFILTER_SIZE GNUNET_CRYPTO_HASH_LENGTH #define CALCULATE_BF_SIZE(A, B, s, k) \ do { \ k = ceil(1 + log2((double) (2*B / (double) A)));\ s = ceil((double) (A * k / log(2))); \ } while (0) /** * Current phase we are in for a intersection operation. */ enum IntersectionOperationPhase { /** * Alices has suggested an operation to bob, * and is waiting for a bf or session end. */ PHASE_INITIAL, /** * Bob has accepted the operation, Bob and Alice are now exchanging bfs * until one notices the their element count is equal */ PHASE_BF_EXCHANGE, /** * if both peers have an equal peercount, they enter this state for * one more turn, to see if they actually have agreed on a correct set. * if a peer finds the same element count after the next iteration, * it ends the the session */ PHASE_MAYBE_FINISHED, /** * The protocol is over. * Results may still have to be sent to the client. */ PHASE_FINISHED }; /** * State of an evaluate operation * with another peer. */ struct OperationState { /** * The bf we currently receive */ struct GNUNET_CONTAINER_BloomFilter *remote_bf; /** * BF of the set's element. */ struct GNUNET_CONTAINER_BloomFilter *local_bf; /** * for multipart msgs we have to store the bloomfilter-data until we fully sent it. */ char * bf_data; /** * size of the bloomfilter */ uint32_t bf_data_size; /** * size of the bloomfilter */ uint32_t bf_bits_per_element; /** * Current state of the operation. */ enum IntersectionOperationPhase phase; /** * Generation in which the operation handle * was created. */ unsigned int generation_created; /** * Maps element-id-hashes to 'elements in our set'. */ struct GNUNET_CONTAINER_MultiHashMap *my_elements; /** * Current element count contained within contained_elements */ uint32_t my_element_count; /** * Iterator for sending elements on the key to element mapping to the client. */ struct GNUNET_CONTAINER_MultiHashMapIterator *full_result_iter; /** * Evaluate operations are held in * a linked list. */ struct OperationState *next; /** * Evaluate operations are held in * a linked list. */ struct OperationState *prev; /** * Did we send the client that we are done? */ int client_done_sent; }; /** * Extra state required for efficient set intersection. */ struct SetState { /** * Number of currently valid elements in the set which have not been removed */ uint32_t current_set_element_count; }; /** * Send a result message to the client indicating * we removed an element * * @param op union operation * @param element element to send */ static void send_client_element (struct Operation *op, struct GNUNET_SET_Element *element) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *rm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending removed element (size %u) to client\n", element->size); GNUNET_assert (0 != op->spec->client_request_id); ev = GNUNET_MQ_msg_extra (rm, element->size, GNUNET_MESSAGE_TYPE_SET_RESULT); if (NULL == ev) { GNUNET_MQ_discard (ev); GNUNET_break (0); return; } rm->result_status = htons (GNUNET_SET_STATUS_OK); rm->request_id = htonl (op->spec->client_request_id); rm->element_type = element->type; memcpy (&rm[1], element->data, element->size); GNUNET_MQ_send (op->spec->set->client_mq, ev); } /** * Alice's version: * * fills the contained-elements hashmap with all relevant * elements and adds their mutated hashes to our local bloomfilter with mutator+1 * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int iterator_initialization_by_alice (void *cls, const struct GNUNET_HashCode *key, void *value) { struct ElementEntry *ee = value; struct Operation *op = cls; struct GNUNET_HashCode mutated_hash; //only consider this element, if it is valid for us if ((op->generation_created < ee->generation_removed) && (op->generation_created >= ee->generation_added)) return GNUNET_YES; // not contained according to bob's bloomfilter GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, &mutated_hash)){ if (GNUNET_SET_RESULT_REMOVED == op->spec->result_mode) send_client_element (op, &ee->element); return GNUNET_YES; } op->state->my_element_count++; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (op->state->my_elements, &ee->element_hash, ee, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return GNUNET_YES; } /** * fills the contained-elements hashmap with all relevant * elements and adds their mutated hashes to our local bloomfilter * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int iterator_initialization (void *cls, const struct GNUNET_HashCode *key, void *value) { struct ElementEntry *ee = value; struct Operation *op = cls; //only consider this element, if it is valid for us if ((op->generation_created < ee->generation_removed) && (op->generation_created >= ee->generation_added)) return GNUNET_YES; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (op->state->my_elements, &ee->element_hash, ee, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return GNUNET_YES; } /** * removes element from a hashmap if it is not contained within the * provided remote bloomfilter. Then, fill our new bloomfilter. * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int iterator_bf_reduce (void *cls, const struct GNUNET_HashCode *key, void *value) { struct ElementEntry *ee = value; struct Operation *op = cls; struct GNUNET_HashCode mutated_hash; GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (op->state->remote_bf, &mutated_hash)) { op->state->my_element_count--; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (op->state->my_elements, &ee->element_hash, ee)); if (GNUNET_SET_RESULT_REMOVED == op->spec->result_mode) send_client_element (op, &ee->element); } return GNUNET_YES; } /** * create a bloomfilter based on the elements given * * @param cls closure * @param key current key code * @param value value in the hash map * @return #GNUNET_YES if we should continue to * iterate, * #GNUNET_NO if not. */ static int iterator_bf_create (void *cls, const struct GNUNET_HashCode *key, void *value) { struct ElementEntry *ee = value; struct Operation *op = cls; struct GNUNET_HashCode mutated_hash; GNUNET_BLOCK_mingle_hash(&ee->element_hash, op->spec->salt, &mutated_hash); GNUNET_CONTAINER_bloomfilter_add (op->state->local_bf, &mutated_hash); return GNUNET_YES; } /** * Inform the client that the union operation has failed, * and proceed to destroy the evaluate operation. * * @param op the intersection operation to fail */ static void fail_intersection_operation (struct Operation *op) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *msg; if (op->state->my_elements) GNUNET_CONTAINER_multihashmap_destroy(op->state->my_elements); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "intersection operation failed\n"); ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); msg->request_id = htonl (op->spec->client_request_id); msg->element_type = htons (0); GNUNET_MQ_send (op->spec->set->client_mq, ev); _GSS_operation_destroy (op); } /** * Send a request for the evaluate operation to a remote peer * * @param op operation with the other peer */ static void send_operation_request (struct Operation *op) { struct GNUNET_MQ_Envelope *ev; struct OperationRequestMessage *msg; ev = GNUNET_MQ_msg_nested_mh (msg, GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST, op->spec->context_msg); if (NULL == ev) { /* the context message is too large */ GNUNET_break (0); GNUNET_SERVER_client_disconnect (op->spec->set->client); return; } msg->operation = htonl (GNUNET_SET_OPERATION_INTERSECTION); msg->app_id = op->spec->app_id; msg->salt = htonl (op->spec->salt); msg->element_count = htonl(op->state->my_element_count); GNUNET_MQ_send (op->mq, ev); if (NULL != op->spec->context_msg) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent op request with context message\n"); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sent op request without context message\n"); if (NULL != op->spec->context_msg) { GNUNET_free (op->spec->context_msg); op->spec->context_msg = NULL; } } static void send_bloomfilter_multipart (struct Operation *op, uint32_t offset) { struct GNUNET_MQ_Envelope *ev; struct BFPart *msg; uint32_t chunk_size = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof(struct BFPart)); uint32_t todo_size = op->state->bf_data_size - offset; if (todo_size < chunk_size) chunk_size = todo_size; ev = GNUNET_MQ_msg_extra (msg, chunk_size, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF_PART); msg->chunk_length = htonl (chunk_size); msg->chunk_offset = htonl (offset); memcpy(&msg[1], &op->state->bf_data[offset], chunk_size); GNUNET_MQ_send (op->mq, ev); if (op->state->bf_data_size == offset + chunk_size) { // done GNUNET_free(op->state->bf_data); op->state->bf_data = NULL; return; } send_bloomfilter_multipart (op, offset + chunk_size); } /** * Send a bloomfilter to our peer. * that the operation is over. * After the result done message has been sent to the client, * destroy the evaluate operation. * * @param op intersection operation */ static void send_bloomfilter (struct Operation *op) { struct GNUNET_MQ_Envelope *ev; struct BFMessage *msg; uint32_t bf_size; uint32_t bf_elementbits; uint32_t chunk_size; struct GNUNET_CONTAINER_BloomFilter * local_bf; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending bf of size %u\n"); CALCULATE_BF_SIZE(op->state->my_element_count, op->spec->remote_element_count, bf_size, bf_elementbits); local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, bf_size, bf_elementbits); op->spec->salt++; GNUNET_CONTAINER_multihashmap_iterate (op->state->my_elements, &iterator_bf_create, op); // send our bloomfilter if (GNUNET_SERVER_MAX_MESSAGE_SIZE > bf_size + sizeof (struct BFMessage)) { // singlepart chunk_size = bf_size; ev = GNUNET_MQ_msg_extra (msg, chunk_size, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_bloomfilter_get_raw_data (local_bf, (char*)&msg[1], bf_size)); } else { //multipart chunk_size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct BFMessage); ev = GNUNET_MQ_msg_extra (msg, chunk_size, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF); op->state->bf_data = (char *) GNUNET_malloc (bf_size); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONTAINER_bloomfilter_get_raw_data (local_bf, op->state->bf_data, bf_size)); memcpy (&msg[1], op->state->bf_data, chunk_size); op->state->bf_data_size = bf_size; } GNUNET_CONTAINER_bloomfilter_free (local_bf); msg->sender_element_count = htonl (op->state->my_element_count); msg->bloomfilter_total_length = htonl (bf_size); msg->bloomfilter_length = htonl (chunk_size); msg->bits_per_element = htonl (bf_elementbits); msg->sender_mutator = htonl (op->spec->salt); GNUNET_MQ_send (op->mq, ev); if (op->state->bf_data) send_bloomfilter_multipart (op, chunk_size); } /** * Signal to the client that the operation has finished and * destroy the operation. * * @param cls operation to destroy */ static void send_client_done_and_destroy (void *cls) { struct Operation *op = cls; struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *rm; ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); rm->request_id = htonl (op->spec->client_request_id); rm->result_status = htons (GNUNET_SET_STATUS_DONE); rm->element_type = htons (0); GNUNET_MQ_send (op->spec->set->client_mq, ev); _GSS_operation_destroy (op); } /** * Send all elements in the full result iterator. * * @param cls operation */ static void send_remaining_elements (void *cls) { struct Operation *op = cls; struct ElementEntry *remaining; //TODO rework this, key entry does not exist here struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *rm; struct GNUNET_SET_Element *element; int res; res = GNUNET_CONTAINER_multihashmap_iterator_next (op->state->full_result_iter, NULL, (const void **) &remaining); if (GNUNET_NO == res) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending done and destroy because iterator ran out\n"); send_client_done_and_destroy (op); return; } element = &remaining->element; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending element (size %u) to client (full set)\n", element->size); GNUNET_assert (0 != op->spec->client_request_id); ev = GNUNET_MQ_msg_extra (rm, element->size, GNUNET_MESSAGE_TYPE_SET_RESULT); GNUNET_assert (NULL != ev); rm->result_status = htons (GNUNET_SET_STATUS_OK); rm->request_id = htonl (op->spec->client_request_id); rm->element_type = element->type; memcpy (&rm[1], element->data, element->size); GNUNET_MQ_notify_sent (ev, send_remaining_elements, op); GNUNET_MQ_send (op->spec->set->client_mq, ev); } /** * Inform the peer that this operation is complete. * * @param op the intersection operation to fail */ static void send_peer_done (struct Operation *op) { struct GNUNET_MQ_Envelope *ev; op->state->phase = PHASE_FINISHED; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Intersection succeeded, sending DONE\n"); GNUNET_CONTAINER_bloomfilter_free (op->state->local_bf); op->state->local_bf = NULL; ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_P2P_DONE); GNUNET_MQ_send (op->mq, ev); } /** * Process a Bloomfilter once we got all the chunks * * @param op the intersection operation */ static void process_bf (struct Operation *op){ uint32_t old_elements; uint32_t peer_elements; old_elements = op->state->my_element_count; peer_elements = op->spec->remote_element_count; switch (op->state->phase) { case PHASE_INITIAL: // If we are ot our first msg op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (op->state->my_element_count, GNUNET_YES); GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, &iterator_initialization_by_alice, op); break; case PHASE_BF_EXCHANGE: case PHASE_MAYBE_FINISHED: // if we are bob or alice and are continuing operation GNUNET_CONTAINER_multihashmap_iterate (op->state->my_elements, &iterator_bf_reduce, op); break; default: GNUNET_break_op (0); fail_intersection_operation(op); } // the iterators created a new BF with salt+1 // the peer needs this information for decoding the next BF // this behavior can be modified at will later on. op->spec->salt++; GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); op->state->remote_bf = NULL; if ((0 == op->state->my_element_count) // fully disjoint || ((op->state->phase == PHASE_MAYBE_FINISHED) // we agree on a shared set of elements && (old_elements == op->state->my_element_count) && (op->state->my_element_count == peer_elements))) { // In the last round we though we were finished, we now know this is correct send_peer_done (op); return; } op->state->phase = PHASE_BF_EXCHANGE; if (op->state->my_element_count == peer_elements) // maybe we are finished, but we do one more round to make certain // we don't have false positives ... op->state->phase = PHASE_MAYBE_FINISHED; send_bloomfilter (op); } /** * Handle an BF multipart message from a remote peer. * * @param cls the intersection operation * @param mh the header of the message */ static void handle_p2p_bf_part (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; const struct BFPart *msg = (const struct BFPart *) mh; uint32_t chunk_size; uint32_t chunk_offset; chunk_size = ntohl(msg->chunk_length); chunk_offset = ntohl(msg->chunk_offset); if ((NULL == op->state->bf_data) || (op->state->bf_data_size < chunk_size + chunk_offset)){ // unexpected multipart chunk GNUNET_break_op (0); fail_intersection_operation(op); return; } memcpy (&op->state->bf_data[chunk_offset], (const char*) &msg[1], chunk_size); if (op->state->bf_data_size != chunk_offset + chunk_size) // wait for next chunk return; op->state->remote_bf = GNUNET_CONTAINER_bloomfilter_init ((const char*) &msg[1], op->state->bf_data_size, op->state->bf_bits_per_element); GNUNET_free (op->state->bf_data); op->state->bf_data = NULL; process_bf (op); } /** * Handle an BF message from a remote peer. * * @param cls the intersection operation * @param mh the header of the message */ static void handle_p2p_bf (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; const struct BFMessage *msg = (const struct BFMessage *) mh; uint32_t bf_size; uint32_t chunk_size; uint32_t bf_bits_per_element; switch (op->state->phase) { case PHASE_INITIAL: case PHASE_BF_EXCHANGE: case PHASE_MAYBE_FINISHED: if (NULL == op->state->bf_data) { // no colliding multipart transaction going on currently op->spec->salt = ntohl (msg->sender_mutator); bf_size = ntohl (msg->bloomfilter_total_length); bf_bits_per_element = ntohl (msg->bits_per_element); chunk_size = ntohl (msg->bloomfilter_length); op->spec->remote_element_count = ntohl(msg->sender_element_count); if (bf_size == chunk_size) { // single part, done here op->state->remote_bf = GNUNET_CONTAINER_bloomfilter_init ((const char*) &msg[1], bf_size, bf_bits_per_element); process_bf (op); return; } //first multipart chunk op->state->bf_data = GNUNET_malloc (bf_size); op->state->bf_data_size = bf_size; op->state->bf_bits_per_element = bf_bits_per_element; memcpy (op->state->bf_data, (const char*) &msg[1], chunk_size); return; } default: GNUNET_break_op (0); fail_intersection_operation (op); } } /** * Handle an BF message from a remote peer. * * @param cls the intersection operation * @param mh the header of the message */ static void handle_p2p_element_info (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; struct BFMessage *msg = (struct BFMessage *) mh; op->spec->remote_element_count = ntohl(msg->sender_element_count); if ((op->state->phase != PHASE_INITIAL) || (op->state->my_element_count > op->spec->remote_element_count)){ GNUNET_break_op (0); fail_intersection_operation(op); } op->state->phase = PHASE_BF_EXCHANGE; op->state->my_elements = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, &iterator_initialization, op); GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); op->state->remote_bf = NULL; if (op->state->my_element_count == ntohl (msg->sender_element_count)) op->state->phase = PHASE_MAYBE_FINISHED; send_bloomfilter (op); } /** * Send our element to the peer, in case our element count is lower than his * * @param op intersection operation */ static void send_element_count (struct Operation *op) { struct GNUNET_MQ_Envelope *ev; struct BFMessage *msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending element count (bf_msg)\n"); // just send our element count, as the other peer must start ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO); msg->sender_element_count = htonl (op->state->my_element_count); msg->bloomfilter_length = htonl (0); msg->sender_mutator = htonl (0); GNUNET_MQ_send (op->mq, ev); } /** * Send a result message to the client indicating * that the operation is over. * After the result done message has been sent to the client, * destroy the evaluate operation. * * @param op intersection operation */ static void finish_and_destroy (struct Operation *op) { GNUNET_assert (GNUNET_NO == op->state->client_done_sent); if (GNUNET_SET_RESULT_FULL == op->spec->result_mode) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending full result set\n"); op->state->full_result_iter = GNUNET_CONTAINER_multihashmap_iterator_create (op->state->my_elements); send_remaining_elements (op); return; } send_client_done_and_destroy (op); } /** * Handle a done message from a remote peer * * @param cls the union operation * @param mh the message */ static void handle_p2p_done (void *cls, const struct GNUNET_MessageHeader *mh) { struct Operation *op = cls; if ((op->state->phase = PHASE_FINISHED) || (op->state->phase = PHASE_MAYBE_FINISHED)){ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got final DONE\n"); finish_and_destroy (op); return; } GNUNET_break_op (0); fail_intersection_operation (op); } /** * Evaluate a union operation with * a remote peer. * * @param op operation to evaluate */ static void intersection_evaluate (struct Operation *op) { op->state = GNUNET_new (struct OperationState); /* we started the operation, thus we have to send the operation request */ op->state->phase = PHASE_INITIAL; op->state->my_elements = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_YES); op->state->my_element_count = op->spec->set->state->current_set_element_count; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "evaluating intersection operation"); send_operation_request (op); } /** * Accept an union operation request from a remote peer. * Only initializes the private operation state. * * @param op operation that will be accepted as a union operation */ static void intersection_accept (struct Operation *op) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "accepting set union operation\n"); op->state = GNUNET_new (struct OperationState); op->state->my_elements = GNUNET_CONTAINER_multihashmap_create(1, GNUNET_YES); op->state->my_element_count = op->spec->set->state->current_set_element_count; // if Alice (the peer) has more elements than Bob (us), she should start if (op->spec->remote_element_count < op->state->my_element_count){ op->state->phase = PHASE_INITIAL; send_element_count(op); return; } // create a new bloomfilter in case we have fewer elements op->state->phase = PHASE_BF_EXCHANGE; op->state->local_bf = GNUNET_CONTAINER_bloomfilter_init (NULL, BLOOMFILTER_SIZE, GNUNET_CONSTANTS_BLOOMFILTER_K); GNUNET_CONTAINER_multihashmap_iterate (op->spec->set->elements, &iterator_initialization, op); send_bloomfilter (op); } /** * Create a new set supporting the intersection operation * * @return the newly created set */ static struct SetState * intersection_set_create () { struct SetState *set_state; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "intersection set created\n"); set_state = GNUNET_new (struct SetState); set_state->current_set_element_count = 0; return set_state; } /** * Add the element from the given element message to the set. * * @param set_state state of the set want to add to * @param ee the element to add to the set */ static void intersection_add (struct SetState *set_state, struct ElementEntry *ee) { set_state->current_set_element_count++; } /** * Destroy a set that supports the intersection operation * * @param set_state the set to destroy */ static void intersection_set_destroy (struct SetState *set_state) { GNUNET_free (set_state); } /** * Remove the element given in the element message from the set. * * @param set_state state of the set to remove from * @param element set element to remove */ static void intersection_remove (struct SetState *set_state, struct ElementEntry *element) { GNUNET_assert(0 < set_state->current_set_element_count); set_state->current_set_element_count--; } /** * Dispatch messages for a intersection operation. * * @param op the state of the intersection evaluate operation * @param mh the received message * @return #GNUNET_SYSERR if the tunnel should be disconnected, * #GNUNET_OK otherwise */ static int intersection_handle_p2p_message (struct Operation *op, const struct GNUNET_MessageHeader *mh) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received p2p message (t: %u, s: %u)\n", ntohs (mh->type), ntohs (mh->size)); switch (ntohs (mh->type)) { /* this message handler is not active until after we received an * operation request message, thus the ops request is not handled here */ case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_ELEMENT_INFO: handle_p2p_element_info (op, mh); break; case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF: handle_p2p_bf (op, mh); break; case GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF_PART: handle_p2p_bf_part (op, mh); break; case GNUNET_MESSAGE_TYPE_SET_P2P_DONE: handle_p2p_done (op, mh); break; default: /* something wrong with mesh's message handlers? */ GNUNET_assert (0); } return GNUNET_OK; } /** * handler for peer-disconnects, notifies the client about the aborted operation * * @param op the destroyed operation */ static void intersection_peer_disconnect (struct Operation *op) { if (PHASE_FINISHED != op->state->phase) { struct GNUNET_MQ_Envelope *ev; struct GNUNET_SET_ResultMessage *msg; ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); msg->request_id = htonl (op->spec->client_request_id); msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); msg->element_type = htons (0); GNUNET_MQ_send (op->spec->set->client_mq, ev); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "other peer disconnected prematurely\n"); _GSS_operation_destroy (op); return; } // else: the session has already been concluded GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "other peer disconnected (finished)\n"); if (GNUNET_NO == op->state->client_done_sent) finish_and_destroy (op); } /** * Destroy the union operation. Only things specific to the union operation are destroyed. * * @param op union operation to destroy */ static void intersection_op_cancel (struct Operation *op) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying intersection op\n"); /* check if the op was canceled twice */ GNUNET_assert (NULL != op->state); if (NULL != op->state->remote_bf) { GNUNET_CONTAINER_bloomfilter_free (op->state->remote_bf); op->state->remote_bf = NULL; } if (NULL != op->state->local_bf) { GNUNET_CONTAINER_bloomfilter_free (op->state->local_bf); op->state->local_bf = NULL; } if (NULL != op->state->my_elements) { // no need to free the elements, they are still part of the set GNUNET_CONTAINER_multihashmap_destroy (op->state->my_elements); op->state->my_elements = NULL; } GNUNET_free (op->state); op->state = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying intersection op done\n"); } const struct SetVT * _GSS_intersection_vt () { static const struct SetVT intersection_vt = { .create = &intersection_set_create, .msg_handler = &intersection_handle_p2p_message, .add = &intersection_add, .remove = &intersection_remove, .destroy_set = &intersection_set_destroy, .evaluate = &intersection_evaluate, .accept = &intersection_accept, .peer_disconnect = &intersection_peer_disconnect, .cancel = &intersection_op_cancel, }; return &intersection_vt; } gnunet-0.10.1/src/set/test_set_union_result_full.c0000644000175000017500000001477312251551532017237 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/test_set_union_result_full.c * @brief testcase for full result mode of the union set operation */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_set_service.h" static int ret; static struct GNUNET_PeerIdentity local_id; static struct GNUNET_HashCode app_id; static struct GNUNET_SET_Handle *set1; static struct GNUNET_SET_Handle *set2; static struct GNUNET_SET_ListenHandle *listen_handle; const static struct GNUNET_CONFIGURATION_Handle *config; static int iter_count; static void result_cb_set1 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { switch (status) { case GNUNET_SET_STATUS_OK: printf ("set 1: got element\n"); break; case GNUNET_SET_STATUS_FAILURE: printf ("set 1: failure\n"); ret = 1; break; case GNUNET_SET_STATUS_DONE: printf ("set 1: done\n"); GNUNET_SET_destroy (set1); break; default: GNUNET_assert (0); } } static void result_cb_set2 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { switch (status) { case GNUNET_SET_STATUS_OK: printf ("set 2: got element\n"); break; case GNUNET_SET_STATUS_FAILURE: printf ("set 2: failure\n"); ret = 1; break; case GNUNET_SET_STATUS_DONE: printf ("set 2: done\n"); GNUNET_SET_destroy (set2); break; default: GNUNET_assert (0); } } static void listen_cb (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request) { struct GNUNET_SET_OperationHandle *oh; GNUNET_assert (NULL != context_msg); GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_TEST); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "listen cb called\n"); GNUNET_SET_listen_cancel (listen_handle); oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_FULL, result_cb_set2, NULL); GNUNET_SET_commit (oh, set2); } /** * Start the set operation. * * @param cls closure, unused */ static void start (void *cls) { struct GNUNET_SET_OperationHandle *oh; struct GNUNET_MessageHeader context_msg; context_msg.size = htons (sizeof context_msg); context_msg.type = htons (GNUNET_MESSAGE_TYPE_TEST); listen_handle = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION, &app_id, listen_cb, NULL); oh = GNUNET_SET_prepare (&local_id, &app_id, &context_msg, 42, GNUNET_SET_RESULT_FULL, result_cb_set1, NULL); GNUNET_SET_commit (oh, set1); } /** * Initialize the second set, continue * * @param cls closure, unused */ static void init_set2 (void *cls) { struct GNUNET_SET_Element element; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initializing set 2\n"); element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, NULL, NULL); element.data = "quux"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, NULL, NULL); element.data = "baz"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, start, NULL); } /** * Initialize the first set, continue. */ static void init_set1 (void) { struct GNUNET_SET_Element element; element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (set1, &element, NULL, NULL); element.data = "bar"; element.size = strlen(element.data); GNUNET_SET_add_element (set1, &element, init_set2, NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized set 1\n"); } static int iter_cb (void *cls, const struct GNUNET_SET_Element *element) { if (NULL == element) { GNUNET_assert (iter_count == 3); GNUNET_SET_destroy (cls); return GNUNET_YES; } printf ("iter: got element\n"); iter_count++; return GNUNET_YES; } static void test_iter () { struct GNUNET_SET_Element element; struct GNUNET_SET_Handle *iter_set; iter_set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION); element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); element.data = "bar"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); element.data = "quux"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); GNUNET_SET_iterate (iter_set, iter_cb, iter_set); } /** * Signature of the 'main' function for a (single-peer) testcase that * is run using 'GNUNET_TESTING_peer_run'. * * @param cls closure * @param cfg configuration of the peer that was started * @param peer identity of the peer that was created */ static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { config = cfg; GNUNET_CRYPTO_get_peer_identity (cfg, &local_id); printf ("my id (from CRYPTO): %s\n", GNUNET_i2s (&local_id)); GNUNET_TESTING_peer_get_identity (peer, &local_id); printf ("my id (from TESTING): %s\n", GNUNET_i2s (&local_id)); test_iter (); set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id); /* test the real set reconciliation */ init_set1 (); } int main (int argc, char **argv) { if (0 != GNUNET_TESTING_peer_run ("test_set_api", "test_set.conf", &run, NULL)) { return 0; } return ret; } gnunet-0.10.1/src/set/strata_estimator.c0000644000175000017500000001064312255010512015122 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/ibf.h * @brief invertible bloom filter * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "ibf.h" #include "strata_estimator.h" void strata_estimator_write (const struct StrataEstimator *se, void *buf) { int i; GNUNET_assert (NULL != se); for (i = 0; i < se->strata_count; i++) { ibf_write_slice (se->strata[i], 0, se->ibf_size, buf); buf += se->ibf_size * IBF_BUCKET_SIZE; } } void strata_estimator_read (const void *buf, struct StrataEstimator *se) { int i; for (i = 0; i < se->strata_count; i++) { ibf_read_slice (buf, 0, se->ibf_size, se->strata[i]); buf += se->ibf_size * IBF_BUCKET_SIZE; } } void strata_estimator_insert (struct StrataEstimator *se, struct IBF_Key key) { uint64_t v; int i; v = key.key_val; /* count trailing '1'-bits of v */ for (i = 0; v & 1; v>>=1, i++) /* empty */; ibf_insert (se->strata[i], key); } void strata_estimator_remove (struct StrataEstimator *se, struct IBF_Key key) { uint64_t v; int i; v = key.key_val; /* count trailing '1'-bits of v */ for (i = 0; v & 1; v>>=1, i++) /* empty */; ibf_remove (se->strata[i], key); } struct StrataEstimator * strata_estimator_create (unsigned int strata_count, uint32_t ibf_size, uint8_t ibf_hashnum) { struct StrataEstimator *se; int i; /* fixme: allocate everything in one chunk */ se = GNUNET_new (struct StrataEstimator); se->strata_count = strata_count; se->ibf_size = ibf_size; se->strata = GNUNET_malloc (sizeof (struct InvertibleBloomFilter *) * strata_count); for (i = 0; i < strata_count; i++) se->strata[i] = ibf_create (ibf_size, ibf_hashnum); return se; } /** * Estimate set difference with two strata estimators, * i.e. arrays of IBFs. * Does not not modify its arguments. * * @param se1 first strata estimator * @param se2 second strata estimator * @return the estimated difference */ unsigned int strata_estimator_difference (const struct StrataEstimator *se1, const struct StrataEstimator *se2) { int i; int count; GNUNET_assert (se1->strata_count == se2->strata_count); count = 0; for (i = se1->strata_count - 1; i >= 0; i--) { struct InvertibleBloomFilter *diff; /* number of keys decoded from the ibf */ int ibf_count; /* FIXME: implement this without always allocating new IBFs */ diff = ibf_dup (se1->strata[i]); ibf_subtract (diff, se2->strata[i]); for (ibf_count = 0; GNUNET_YES; ibf_count++) { int more; more = ibf_decode (diff, NULL, NULL); if (GNUNET_NO == more) { count += ibf_count; break; } /* Estimate if decoding fails or would not terminate */ if ((GNUNET_SYSERR == more) || (ibf_count > diff->size)) { ibf_destroy (diff); return count * (1 << (i + 1)); } } ibf_destroy (diff); } return count; } /** * Make a copy of a strata estimator. * * @param se the strata estimator to copy * @return the copy */ struct StrataEstimator * strata_estimator_dup (struct StrataEstimator *se) { struct StrataEstimator *c; int i; c = GNUNET_new (struct StrataEstimator); c->strata_count = se->strata_count; c->ibf_size = se->ibf_size; c->strata = GNUNET_malloc (sizeof (struct InvertibleBloomFilter *) * se->strata_count); for (i = 0; i < se->strata_count; i++) c->strata[i] = ibf_dup (se->strata[i]); return c; } void strata_estimator_destroy (struct StrataEstimator *se) { int i; for (i = 0; i < se->strata_count; i++) ibf_destroy (se->strata[i]); GNUNET_free (se->strata); GNUNET_free (se); } gnunet-0.10.1/src/set/ibf.c0000644000175000017500000002367112255010512012302 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/ibf.c * @brief implementation of the invertible bloom filter * @author Florian Dold */ #include "ibf.h" /** * Compute the key's hash from the key. * Redefine to use a different hash function. */ #define IBF_KEY_HASH_VAL(k) (GNUNET_CRYPTO_crc32_n (&(k), sizeof (struct IBF_KeyHash))) /** * Create a key from a hashcode. * * @param hash the hashcode * @return a key */ struct IBF_Key ibf_key_from_hashcode (const struct GNUNET_HashCode *hash) { /* FIXME: endianess */ return *(struct IBF_Key *) hash; } /** * Create a hashcode from a key, by replicating the key * until the hascode is filled * * @param key the key * @param dst hashcode to store the result in */ void ibf_hashcode_from_key (struct IBF_Key key, struct GNUNET_HashCode *dst) { struct IBF_Key *p; unsigned int i; const unsigned int keys_per_hashcode = sizeof (struct GNUNET_HashCode) / sizeof (struct IBF_Key); p = (struct IBF_Key *) dst; for (i = 0; i < keys_per_hashcode; i++) *p++ = key; } /** * Create an invertible bloom filter. * * @param size number of IBF buckets * @param hash_num number of buckets one element is hashed in * @return the newly created invertible bloom filter */ struct InvertibleBloomFilter * ibf_create (uint32_t size, uint8_t hash_num) { struct InvertibleBloomFilter *ibf; /* TODO: use malloc_large */ ibf = GNUNET_new (struct InvertibleBloomFilter); ibf->count = GNUNET_malloc (size * sizeof (uint8_t)); ibf->key_sum = GNUNET_malloc (size * sizeof (struct IBF_Key)); ibf->key_hash_sum = GNUNET_malloc (size * sizeof (struct IBF_KeyHash)); ibf->size = size; ibf->hash_num = hash_num; return ibf; } /** * Store unique bucket indices for the specified key in dst. */ static inline void ibf_get_indices (const struct InvertibleBloomFilter *ibf, struct IBF_Key key, int *dst) { uint32_t filled; uint32_t i; uint32_t bucket; bucket = GNUNET_CRYPTO_crc32_n (&key, sizeof key); for (i = 0, filled=0; filled < ibf->hash_num; i++) { unsigned int j; uint64_t x; for (j = 0; j < filled; j++) if (dst[j] == bucket) goto try_next; dst[filled++] = bucket % ibf->size; try_next: ; x = ((uint64_t) bucket << 32) | i; bucket = GNUNET_CRYPTO_crc32_n (&x, sizeof x); } } static void ibf_insert_into (struct InvertibleBloomFilter *ibf, struct IBF_Key key, const int *buckets, int side) { int i; for (i = 0; i < ibf->hash_num; i++) { const int bucket = buckets[i]; ibf->count[bucket].count_val += side; ibf->key_sum[bucket].key_val ^= key.key_val; ibf->key_hash_sum[bucket].key_hash_val ^= IBF_KEY_HASH_VAL (key); } } /** * Insert a key into an IBF. * * @param ibf the IBF * @param key the element's hash code */ void ibf_insert (struct InvertibleBloomFilter *ibf, struct IBF_Key key) { int buckets[ibf->hash_num]; GNUNET_assert (ibf->hash_num <= ibf->size); ibf_get_indices (ibf, key, buckets); ibf_insert_into (ibf, key, buckets, 1); } /** * Remove a key from an IBF. * * @param ibf the IBF * @param key the element's hash code */ void ibf_remove (struct InvertibleBloomFilter *ibf, struct IBF_Key key) { int buckets[ibf->hash_num]; GNUNET_assert (ibf->hash_num <= ibf->size); ibf_get_indices (ibf, key, buckets); ibf_insert_into (ibf, key, buckets, -1); } /** * Test is the IBF is empty, i.e. all counts, keys and key hashes are zero. */ static int ibf_is_empty (struct InvertibleBloomFilter *ibf) { int i; for (i = 0; i < ibf->size; i++) { if (0 != ibf->count[i].count_val) return GNUNET_NO; if (0 != ibf->key_hash_sum[i].key_hash_val) return GNUNET_NO; if (0 != ibf->key_sum[i].key_val) return GNUNET_NO; } return GNUNET_YES; } /** * Decode and remove an element from the IBF, if possible. * * @param ibf the invertible bloom filter to decode * @param ret_side sign of the cell's count where the decoded element came from. * A negative sign indicates that the element was recovered * resides in an IBF that was previously subtracted from. * @param ret_id receives the hash code of the decoded element, if successful * @return GNUNET_YES if decoding an element was successful, * GNUNET_NO if the IBF is empty, * GNUNET_SYSERR if the decoding has failed */ int ibf_decode (struct InvertibleBloomFilter *ibf, int *ret_side, struct IBF_Key *ret_id) { struct IBF_KeyHash hash; int i; int buckets[ibf->hash_num]; GNUNET_assert (NULL != ibf); for (i = 0; i < ibf->size; i++) { int j; int hit; /* we can only decode from pure buckets */ if ((1 != ibf->count[i].count_val) && (-1 != ibf->count[i].count_val)) continue; hash.key_hash_val = IBF_KEY_HASH_VAL (ibf->key_sum[i]); /* test if the hash matches the key */ if (hash.key_hash_val != ibf->key_hash_sum[i].key_hash_val) continue; /* test if key in bucket hits its own location, * if not, the key hash was subject to collision */ hit = GNUNET_NO; ibf_get_indices (ibf, ibf->key_sum[i], buckets); for (j = 0; j < ibf->hash_num; j++) if (buckets[j] == i) hit = GNUNET_YES; if (GNUNET_NO == hit) continue; if (NULL != ret_side) *ret_side = ibf->count[i].count_val; if (NULL != ret_id) *ret_id = ibf->key_sum[i]; /* insert on the opposite side, effectively removing the element */ ibf_insert_into (ibf, ibf->key_sum[i], buckets, -ibf->count[i].count_val); return GNUNET_YES; } if (GNUNET_YES == ibf_is_empty (ibf)) return GNUNET_NO; return GNUNET_SYSERR; } /** * Write buckets from an ibf to a buffer. * Exactly (IBF_BUCKET_SIZE*ibf->size) bytes are written to buf. * * @param ibf the ibf to write * @param start with which bucket to start * @param count how many buckets to write * @param buf buffer to write the data to */ void ibf_write_slice (const struct InvertibleBloomFilter *ibf, uint32_t start, uint32_t count, void *buf) { struct IBF_Key *key_dst; struct IBF_KeyHash *key_hash_dst; struct IBF_Count *count_dst; GNUNET_assert (start + count <= ibf->size); /* copy keys */ key_dst = (struct IBF_Key *) buf; memcpy (key_dst, ibf->key_sum + start, count * sizeof *key_dst); key_dst += count; /* copy key hashes */ key_hash_dst = (struct IBF_KeyHash *) key_dst; memcpy (key_hash_dst, ibf->key_hash_sum + start, count * sizeof *key_hash_dst); key_hash_dst += count; /* copy counts */ count_dst = (struct IBF_Count *) key_hash_dst; memcpy (count_dst, ibf->count + start, count * sizeof *count_dst); } /** * Read buckets from a buffer into an ibf. * * @param buf pointer to the buffer to read from * @param start which bucket to start at * @param count how many buckets to read * @param ibf the ibf to read from */ void ibf_read_slice (const void *buf, uint32_t start, uint32_t count, struct InvertibleBloomFilter *ibf) { struct IBF_Key *key_src; struct IBF_KeyHash *key_hash_src; struct IBF_Count *count_src; GNUNET_assert (count > 0); GNUNET_assert (start + count <= ibf->size); /* copy keys */ key_src = (struct IBF_Key *) buf; memcpy (ibf->key_sum + start, key_src, count * sizeof *key_src); key_src += count; /* copy key hashes */ key_hash_src = (struct IBF_KeyHash *) key_src; memcpy (ibf->key_hash_sum + start, key_hash_src, count * sizeof *key_hash_src); key_hash_src += count; /* copy counts */ count_src = (struct IBF_Count *) key_hash_src; memcpy (ibf->count + start, count_src, count * sizeof *count_src); } /** * Subtract ibf2 from ibf1, storing the result in ibf1. * The two IBF's must have the same parameters size and hash_num. * * @param ibf1 IBF that is subtracted from * @param ibf2 IBF that will be subtracted from ibf1 */ void ibf_subtract (struct InvertibleBloomFilter *ibf1, const struct InvertibleBloomFilter *ibf2) { int i; GNUNET_assert (ibf1->size == ibf2->size); GNUNET_assert (ibf1->hash_num == ibf2->hash_num); for (i = 0; i < ibf1->size; i++) { ibf1->count[i].count_val -= ibf2->count[i].count_val; ibf1->key_hash_sum[i].key_hash_val ^= ibf2->key_hash_sum[i].key_hash_val; ibf1->key_sum[i].key_val ^= ibf2->key_sum[i].key_val; } } /** * Create a copy of an IBF, the copy has to be destroyed properly. * * @param ibf the IBF to copy */ struct InvertibleBloomFilter * ibf_dup (const struct InvertibleBloomFilter *ibf) { struct InvertibleBloomFilter *copy; copy = GNUNET_malloc (sizeof *copy); copy->hash_num = ibf->hash_num; copy->size = ibf->size; copy->key_hash_sum = GNUNET_memdup (ibf->key_hash_sum, ibf->size * sizeof (struct IBF_KeyHash)); copy->key_sum = GNUNET_memdup (ibf->key_sum, ibf->size * sizeof (struct IBF_Key)); copy->count = GNUNET_memdup (ibf->count, ibf->size * sizeof (struct IBF_Count)); return copy; } /** * Destroy all resources associated with the invertible bloom filter. * No more ibf_*-functions may be called on ibf after calling destroy. * * @param ibf the intertible bloom filter to destroy */ void ibf_destroy (struct InvertibleBloomFilter *ibf) { GNUNET_free (ibf->key_sum); GNUNET_free (ibf->key_hash_sum); GNUNET_free (ibf->count); GNUNET_free (ibf); } gnunet-0.10.1/src/set/test_set_api.c0000644000175000017500000001523412276375236014245 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/test_set_api.c * @brief testcase for set_api.c */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_set_service.h" static struct GNUNET_PeerIdentity local_id; static struct GNUNET_HashCode app_id; static struct GNUNET_SET_Handle *set1; static struct GNUNET_SET_Handle *set2; static struct GNUNET_SET_ListenHandle *listen_handle; const static struct GNUNET_CONFIGURATION_Handle *config; static int iter_count; static void result_cb_set1 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { switch (status) { case GNUNET_SET_STATUS_OK: printf ("set 1: got element\n"); break; case GNUNET_SET_STATUS_FAILURE: printf ("set 1: failure\n"); break; case GNUNET_SET_STATUS_DONE: printf ("set 1: done\n"); GNUNET_SET_destroy (set1); break; default: GNUNET_assert (0); } } static void result_cb_set2 (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { switch (status) { case GNUNET_SET_STATUS_OK: printf ("set 2: got element\n"); break; case GNUNET_SET_STATUS_FAILURE: printf ("set 2: failure\n"); break; case GNUNET_SET_STATUS_DONE: printf ("set 2: done\n"); GNUNET_SET_destroy (set2); break; default: GNUNET_assert (0); } } static void listen_cb (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request) { struct GNUNET_SET_OperationHandle *oh; GNUNET_assert (NULL != context_msg); GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_TEST); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "listen cb called\n"); GNUNET_SET_listen_cancel (listen_handle); oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_ADDED, result_cb_set2, NULL); GNUNET_SET_commit (oh, set2); } /** * Start the set operation. * * @param cls closure, unused */ static void start (void *cls) { struct GNUNET_SET_OperationHandle *oh; struct GNUNET_MessageHeader context_msg; context_msg.size = htons (sizeof context_msg); context_msg.type = htons (GNUNET_MESSAGE_TYPE_TEST); listen_handle = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION, &app_id, listen_cb, NULL); oh = GNUNET_SET_prepare (&local_id, &app_id, &context_msg, 42, GNUNET_SET_RESULT_ADDED, result_cb_set1, NULL); GNUNET_SET_commit (oh, set1); } /** * Initialize the second set, continue * * @param cls closure, unused */ static void init_set2 (void *cls) { struct GNUNET_SET_Element element; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initializing set 2\n"); element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, NULL, NULL); element.data = "quux"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, NULL, NULL); element.data = "baz"; element.size = strlen(element.data); GNUNET_SET_add_element (set2, &element, start, NULL); } /** * Initialize the first set, continue. */ static void init_set1 (void) { struct GNUNET_SET_Element element; element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (set1, &element, NULL, NULL); element.data = "bar"; element.size = strlen(element.data); GNUNET_SET_add_element (set1, &element, init_set2, NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "initialized set 1\n"); } static int iter_cb (void *cls, const struct GNUNET_SET_Element *element) { if (NULL == element) { GNUNET_assert (iter_count == 3); GNUNET_SET_destroy (cls); return GNUNET_YES; } printf ("iter: got element\n"); iter_count++; return GNUNET_YES; } static void test_iter () { struct GNUNET_SET_Element element; struct GNUNET_SET_Handle *iter_set; iter_set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION); element.type = 0; element.data = "hello"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); element.data = "bar"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); element.data = "quux"; element.size = strlen(element.data); GNUNET_SET_add_element (iter_set, &element, NULL, NULL); GNUNET_SET_iterate (iter_set, iter_cb, iter_set); } /** * Signature of the 'main' function for a (single-peer) testcase that * is run using 'GNUNET_TESTING_peer_run'. * * @param cls closure * @param cfg configuration of the peer that was started * @param peer identity of the peer that was created */ static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct GNUNET_SET_OperationHandle *my_oh; config = cfg; GNUNET_CRYPTO_get_peer_identity (cfg, &local_id); printf ("my id (from CRYPTO): %s\n", GNUNET_i2s (&local_id)); GNUNET_TESTING_peer_get_identity (peer, &local_id); printf ("my id (from TESTING): %s\n", GNUNET_i2s (&local_id)); test_iter (); set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id); ///* test if canceling an uncommited request works! */ my_oh = GNUNET_SET_prepare (&local_id, &app_id, NULL, 0, GNUNET_SET_RESULT_ADDED, NULL, NULL); GNUNET_SET_operation_cancel (my_oh); /* test the real set reconciliation */ init_set1 (); } int main (int argc, char **argv) { int ret; ret = GNUNET_TESTING_peer_run ("test_set_api", "test_set.conf", &run, NULL); return ret; } gnunet-0.10.1/src/set/gnunet-set-profiler.c0000644000175000017500000002135012225777502015463 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file set/gnunet-set-profiler.c * @brief profiling tool for set * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_set_service.h" #include "gnunet_testbed_service.h" static int ret; static unsigned int num_a = 5; static unsigned int num_b = 5; static unsigned int num_c = 20; static unsigned int salt = 42; static char *op_str = "union"; const static struct GNUNET_CONFIGURATION_Handle *config; struct SetInfo { char *id; struct GNUNET_SET_Handle *set; struct GNUNET_SET_OperationHandle *oh; struct GNUNET_CONTAINER_MultiHashMap *sent; struct GNUNET_CONTAINER_MultiHashMap *received; int done; } info1, info2; struct GNUNET_CONTAINER_MultiHashMap *common_sent; struct GNUNET_HashCode app_id; struct GNUNET_PeerIdentity local_peer; struct GNUNET_SET_ListenHandle *set_listener; static int map_remove_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_CONTAINER_MultiHashMap *m = cls; int ret; GNUNET_assert (NULL != key); ret = GNUNET_CONTAINER_multihashmap_remove (m, key, NULL); if (GNUNET_OK != ret) printf ("spurious element\n"); return GNUNET_YES; } static void check_all_done (void) { if (info1.done == GNUNET_NO || info2.done == GNUNET_NO) return; GNUNET_CONTAINER_multihashmap_iterate (info1.received, map_remove_iterator, info2.sent); GNUNET_CONTAINER_multihashmap_iterate (info2.received, map_remove_iterator, info1.sent); printf ("set a: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (info1.sent)); printf ("set b: %d missing elements\n", GNUNET_CONTAINER_multihashmap_size (info2.sent)); GNUNET_SCHEDULER_shutdown (); } static void set_result_cb (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { struct SetInfo *info = cls; GNUNET_assert (GNUNET_NO == info->done); switch (status) { case GNUNET_SET_STATUS_DONE: case GNUNET_SET_STATUS_HALF_DONE: info->done = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s done\n", info->id); check_all_done (); info->oh = NULL; return; case GNUNET_SET_STATUS_FAILURE: info->oh = NULL; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "failure\n"); GNUNET_SCHEDULER_shutdown (); return; case GNUNET_SET_STATUS_OK: break; default: GNUNET_assert (0); } if (element->size != sizeof (struct GNUNET_HashCode)) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "wrong element size: %u\n", element->size); GNUNET_assert (0); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set %s: got element (%s)\n", info->id, GNUNET_h2s (element->data)); GNUNET_assert (NULL != element->data); GNUNET_CONTAINER_multihashmap_put (info->received, element->data, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); } static void set_listen_cb (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request) { if (NULL == request) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "listener failed\n"); return; } GNUNET_assert (NULL == info2.oh); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "set listen cb called\n"); info2.oh = GNUNET_SET_accept (request, GNUNET_SET_RESULT_ADDED, set_result_cb, &info2); GNUNET_SET_commit (info2.oh, info2.set); } static int set_insert_iterator (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_SET_Handle *set = cls; struct GNUNET_SET_Element *el; el = GNUNET_malloc (sizeof *el + sizeof *key); el->type = 0; memcpy (&el[1], key, sizeof *key); el->data = &el[1]; el->size = sizeof *key; GNUNET_SET_add_element (set, el, NULL, NULL); GNUNET_free (el); return GNUNET_YES; } static void handle_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != set_listener) { GNUNET_SET_listen_cancel (set_listener); set_listener = NULL; } if (NULL != info1.oh) { GNUNET_SET_operation_cancel (info1.oh); info1.oh = NULL; } if (NULL != info2.oh) { GNUNET_SET_operation_cancel (info2.oh); info2.oh = NULL; } if (NULL != info1.set) { GNUNET_SET_destroy (info1.set); info1.set = NULL; } if (NULL != info2.set) { GNUNET_SET_destroy (info2.set); info2.set = NULL; } } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { unsigned int i; struct GNUNET_HashCode hash; config = cfg; if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &local_peer)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n"); ret = 0; return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, handle_shutdown, NULL); info1.id = "a"; info2.id = "b"; info1.sent = GNUNET_CONTAINER_multihashmap_create (num_a+1, GNUNET_NO); info2.sent = GNUNET_CONTAINER_multihashmap_create (num_b+1, GNUNET_NO); common_sent = GNUNET_CONTAINER_multihashmap_create (num_c+1, GNUNET_NO); info1.received = GNUNET_CONTAINER_multihashmap_create (num_a+1, GNUNET_NO); info2.received = GNUNET_CONTAINER_multihashmap_create (num_b+1, GNUNET_NO); for (i = 0; i < num_a; i++) { GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &hash); GNUNET_CONTAINER_multihashmap_put (info1.sent, &hash, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); } for (i = 0; i < num_b; i++) { GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &hash); GNUNET_CONTAINER_multihashmap_put (info2.sent, &hash, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); } for (i = 0; i < num_c; i++) { GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG, &hash); GNUNET_CONTAINER_multihashmap_put (common_sent, &hash, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); } /* use last hash for app id */ app_id = hash; /* FIXME: also implement intersection etc. */ info1.set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION); info2.set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION); GNUNET_CONTAINER_multihashmap_iterate (info1.sent, set_insert_iterator, info1.set); GNUNET_CONTAINER_multihashmap_iterate (info2.sent, set_insert_iterator, info2.set); GNUNET_CONTAINER_multihashmap_iterate (common_sent, set_insert_iterator, info1.set); GNUNET_CONTAINER_multihashmap_iterate (common_sent, set_insert_iterator, info2.set); set_listener = GNUNET_SET_listen (config, GNUNET_SET_OPERATION_UNION, &app_id, set_listen_cb, NULL); info1.oh = GNUNET_SET_prepare (&local_peer, &app_id, NULL, salt, GNUNET_SET_RESULT_ADDED, set_result_cb, &info1); GNUNET_SET_commit (info1.oh, info1.set); GNUNET_SET_destroy (info1.set); info1.set = NULL; } int main (int argc, char **argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'A', "num-first", NULL, gettext_noop ("number of values"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_a }, { 'B', "num-second", NULL, gettext_noop ("number of values"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_b }, { 'C', "num-common", NULL, gettext_noop ("number of values"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_c }, { 'x', "operation", NULL, gettext_noop ("oeration to execute"), GNUNET_YES, &GNUNET_GETOPT_set_string, &op_str }, GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run (argc, argv, "gnunet-set-profiler", "help", options, &run, NULL); return ret; } gnunet-0.10.1/src/set/set.conf.in0000644000175000017500000000036312255426423013452 00000000000000[set] AUTOSTART = @AUTOSTART@ @UNIXONLY@PORT = 2106 HOSTNAME = localhost BINARY = gnunet-service-set ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-set.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES gnunet-0.10.1/src/set/set_protocol.h0000644000175000017500000000615412261236531014270 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Florian Dold * @file set/set_protocol.h * @brief Peer-to-Peer messages for gnunet set */ #ifndef SET_PROTOCOL_H #define SET_PROTOCOL_H #include "platform.h" #include "gnunet_common.h" GNUNET_NETWORK_STRUCT_BEGIN struct OperationRequestMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_P2P_OPERATION_REQUEST */ struct GNUNET_MessageHeader header; /** * Operation to request, values from 'enum GNUNET_SET_OperationType' */ uint32_t operation GNUNET_PACKED; /** * Salt to use for this operation. */ uint32_t salt; /** * For Intersection: my element count */ uint32_t element_count; /** * Application-specific identifier of the request. */ struct GNUNET_HashCode app_id; /* rest: optional message */ }; struct IBFMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_P2P_IBF */ struct GNUNET_MessageHeader header; /** * Order of the whole ibf, where * num_buckets = 2^order */ uint8_t order; /** * Padding, must be 0. */ uint8_t reserved; /** * Offset of the strata in the rest of the message */ uint16_t offset GNUNET_PACKED; /** * Salt used when hashing elements for this IBF. */ uint32_t salt; /* rest: strata */ }; struct BFMessage { /** * Type: GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF */ struct GNUNET_MessageHeader header; /** * mutator used with this bloomfilter. */ uint32_t sender_element_count GNUNET_PACKED; /** * mutator used with this bloomfilter. */ uint32_t sender_mutator GNUNET_PACKED; /** * Length of the bloomfilter data */ uint32_t bloomfilter_total_length GNUNET_PACKED; /** * Length of the appended bloomfilter data block */ uint32_t bloomfilter_length GNUNET_PACKED; /** * Length of the bloomfilter data */ uint32_t bits_per_element GNUNET_PACKED; /** * rest: the sender's bloomfilter */ }; struct BFPart { /** * Type: GNUNET_MESSAGE_TYPE_SET_INTERSECTION_P2P_BF */ struct GNUNET_MessageHeader header; /** * Length of the appended bloomfilter data block */ uint32_t chunk_length GNUNET_PACKED; /** * offset in the bloolfilter data block, if multipart message */ uint32_t chunk_offset GNUNET_PACKED; /** * rest: the sender's bloomfilter */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/postgres/0000755000175000017500000000000012320755623012534 500000000000000gnunet-0.10.1/src/postgres/Makefile.in0000644000175000017500000005521012320752063014517 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = src/postgres DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libgnunetpostgres_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetpostgres_la_OBJECTS = postgres.lo libgnunetpostgres_la_OBJECTS = $(am_libgnunetpostgres_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetpostgres_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetpostgres_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_POSTGRES_TRUE@am_libgnunetpostgres_la_rpath = -rpath $(libdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetpostgres_la_SOURCES) DIST_SOURCES = $(libgnunetpostgres_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage @HAVE_POSTGRES_TRUE@lib_LTLIBRARIES = libgnunetpostgres.la libgnunetpostgres_la_SOURCES = \ postgres.c libgnunetpostgres_la_LIBADD = -lpq \ $(top_builddir)/src/util/libgnunetutil.la libgnunetpostgres_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/postgres/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/postgres/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetpostgres.la: $(libgnunetpostgres_la_OBJECTS) $(libgnunetpostgres_la_DEPENDENCIES) $(EXTRA_libgnunetpostgres_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetpostgres_la_LINK) $(am_libgnunetpostgres_la_rpath) $(libgnunetpostgres_la_OBJECTS) $(libgnunetpostgres_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/postgres.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/postgres/Makefile.am0000644000175000017500000000065612320751517014515 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage endif if HAVE_POSTGRES lib_LTLIBRARIES = libgnunetpostgres.la endif libgnunetpostgres_la_SOURCES = \ postgres.c libgnunetpostgres_la_LIBADD = -lpq \ $(top_builddir)/src/util/libgnunetutil.la libgnunetpostgres_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 gnunet-0.10.1/src/postgres/postgres.c0000644000175000017500000001310012225777502014465 00000000000000/* This file is part of GNUnet (C) 2009, 2010, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file postgres/postgres.c * @brief library to help with access to a Postgres database * @author Christian Grothoff */ #include "platform.h" #include "gnunet_postgres_lib.h" /** * Check if the result obtained from Postgres has * the desired status code. If not, log an error, clear the * result and return GNUNET_SYSERR. * * @param dbh database handle * @param ret return value from database operation to check * @param expected_status desired status * @param command description of the command that was run * @param args arguments given to the command * @param filename name of the source file where the command was run * @param line line number in the source file * @return GNUNET_OK if the result is acceptable */ int GNUNET_POSTGRES_check_result_ (PGconn * dbh, PGresult * ret, int expected_status, const char *command, const char *args, const char *filename, int line) { if (ret == NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "postgres", "Postgres failed to allocate result for `%s:%s' at %s:%d\n", command, args, filename, line); return GNUNET_SYSERR; } if (PQresultStatus (ret) != expected_status) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "postgres", _("`%s:%s' failed at %s:%d with error: %s"), command, args, filename, line, PQerrorMessage (dbh)); PQclear (ret); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Run simple SQL statement (without results). * * @param dbh database handle * @param sql statement to run * @param filename filename for error reporting * @param line code line for error reporting * @return GNUNET_OK on success */ int GNUNET_POSTGRES_exec_ (PGconn * dbh, const char *sql, const char *filename, int line) { PGresult *ret; ret = PQexec (dbh, sql); if (GNUNET_OK != GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQexec", sql, filename, line)) return GNUNET_SYSERR; PQclear (ret); return GNUNET_OK; } /** * Prepare SQL statement. * * @param dbh database handle * @param name name for the prepared SQL statement * @param sql SQL code to prepare * @param nparams number of parameters in sql * @param filename filename for error reporting * @param line code line for error reporting * @return GNUNET_OK on success */ int GNUNET_POSTGRES_prepare_ (PGconn * dbh, const char *name, const char *sql, int nparams, const char *filename, int line) { PGresult *ret; ret = PQprepare (dbh, name, sql, nparams, NULL); if (GNUNET_OK != GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQprepare", sql, filename, line)) return GNUNET_SYSERR; PQclear (ret); return GNUNET_OK; } /** * Connect to a postgres database * * @param cfg configuration * @param section configuration section to use to get Postgres configuration options * @return the postgres handle */ PGconn * GNUNET_POSTGRES_connect (const struct GNUNET_CONFIGURATION_Handle * cfg, const char *section) { PGconn *dbh; char *conninfo; /* Open database and precompile statements */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, "CONFIG", &conninfo)) conninfo = NULL; dbh = PQconnectdb (conninfo == NULL ? "" : conninfo); GNUNET_free_non_null (conninfo); if (NULL == dbh) { /* FIXME: warn about out-of-memory? */ return NULL; } if (PQstatus (dbh) != CONNECTION_OK) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "postgres", _("Unable to initialize Postgres: %s"), PQerrorMessage (dbh)); PQfinish (dbh); return NULL; } return dbh; } /** * Delete the row identified by the given rowid (qid * in postgres). * * @param dbh database handle * @param stmt name of the prepared statement * @param rowid which row to delete * @return GNUNET_OK on success */ int GNUNET_POSTGRES_delete_by_rowid (PGconn * dbh, const char *stmt, uint32_t rowid) { uint32_t brow = htonl (rowid); const char *paramValues[] = { (const char *) &brow }; int paramLengths[] = { sizeof (brow) }; const int paramFormats[] = { 1 }; PGresult *ret; ret = PQexecPrepared (dbh, stmt, 1, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "delrow", __FILE__, __LINE__)) { return GNUNET_SYSERR; } PQclear (ret); return GNUNET_OK; } /* end of postgres.c */ gnunet-0.10.1/src/consensus/0000755000175000017500000000000012320755627012712 500000000000000gnunet-0.10.1/src/consensus/consensus_api.c0000644000175000017500000002270212276375236015656 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file consensus/consensus_api.c * @brief * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_client_lib.h" #include "gnunet_consensus_service.h" #include "consensus.h" #define LOG(kind,...) GNUNET_log_from (kind, "consensus-api",__VA_ARGS__) /** * Handle for the service. */ struct GNUNET_CONSENSUS_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Client connected to the consensus service, may be NULL if not connected. */ struct GNUNET_CLIENT_Connection *client; /** * Callback for new elements. Not called for elements added locally. */ GNUNET_CONSENSUS_ElementCallback new_element_cb; /** * Closure for new_element_cb */ void *new_element_cls; /** * The (local) session identifier for the consensus session. */ struct GNUNET_HashCode session_id; /** * GNUNES_YES iff the join message has been sent to the service. */ int joined; /** * Called when the conclude operation finishes or fails. */ GNUNET_CONSENSUS_ConcludeCallback conclude_cb; /** * Closure for the conclude callback. */ void *conclude_cls; /** * Deadline for the conclude operation. */ struct GNUNET_TIME_Absolute conclude_deadline; /** * Message queue for the client. */ struct GNUNET_MQ_Handle *mq; }; /** * FIXME: this should not bee necessary when the API * issue has been fixed */ struct InsertDoneInfo { GNUNET_CONSENSUS_InsertDoneCallback idc; void *cls; }; /** * Called when the server has sent is a new element * * @param cls consensus handle * @param mh element message */ static void handle_new_element (void *cls, const struct GNUNET_MessageHeader *mh) { struct GNUNET_CONSENSUS_Handle *consensus = cls; const struct GNUNET_CONSENSUS_ElementMessage *msg = (const struct GNUNET_CONSENSUS_ElementMessage *) mh; struct GNUNET_SET_Element element; LOG (GNUNET_ERROR_TYPE_DEBUG, "received new element\n"); element.type = msg->element_type; element.size = ntohs (msg->header.size) - sizeof (struct GNUNET_CONSENSUS_ElementMessage); element.data = &msg[1]; consensus->new_element_cb (consensus->new_element_cls, &element); } /** * Called when the server has announced * that the conclusion is over. * * @param cls consensus handle * @param msg conclude done message */ static void handle_conclude_done (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CONSENSUS_Handle *consensus = cls; GNUNET_CONSENSUS_ConcludeCallback cc; GNUNET_MQ_destroy (consensus->mq); consensus->mq = NULL; GNUNET_CLIENT_disconnect (consensus->client); consensus->client = NULL; GNUNET_assert (NULL != (cc = consensus->conclude_cb)); consensus->conclude_cb = NULL; cc (consensus->conclude_cls); } /** * Generic error handler, called with the appropriate * error code and the same closure specified at the creation of * the message queue. * Not every message queue implementation supports an error handler. * * @param cls closure, same closure as for the message handlers * @param error error code */ static void mq_error_handler (void *cls, enum GNUNET_MQ_Error error) { LOG (GNUNET_ERROR_TYPE_WARNING, "consensus service disconnected us\n"); } /** * Create a consensus session. * * @param cfg configuration to use for connecting to the consensus service * @param num_peers number of peers in the peers array * @param peers array of peers participating in this consensus session * Inclusion of the local peer is optional. * @param session_id session identifier * Allows a group of peers to have more than consensus session. * @param start start time of the consensus, conclude should be called before * the start time. * @param deadline time when the consensus should have concluded * @param new_element_cb callback, called when a new element is added to the set by * another peer * @param new_element_cls closure for new_element * @return handle to use, NULL on error */ struct GNUNET_CONSENSUS_Handle * GNUNET_CONSENSUS_create (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int num_peers, const struct GNUNET_PeerIdentity *peers, const struct GNUNET_HashCode *session_id, struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute deadline, GNUNET_CONSENSUS_ElementCallback new_element_cb, void *new_element_cls) { struct GNUNET_CONSENSUS_Handle *consensus; struct GNUNET_CONSENSUS_JoinMessage *join_msg; struct GNUNET_MQ_Envelope *ev; const static struct GNUNET_MQ_MessageHandler mq_handlers[] = { {handle_new_element, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT, 0}, {handle_conclude_done, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE, 0}, GNUNET_MQ_HANDLERS_END }; consensus = GNUNET_new (struct GNUNET_CONSENSUS_Handle); consensus->cfg = cfg; consensus->new_element_cb = new_element_cb; consensus->new_element_cls = new_element_cls; consensus->session_id = *session_id; consensus->client = GNUNET_CLIENT_connect ("consensus", cfg); consensus->mq = GNUNET_MQ_queue_for_connection_client (consensus->client, mq_handlers, mq_error_handler, consensus); GNUNET_assert (consensus->client != NULL); ev = GNUNET_MQ_msg_extra (join_msg, (num_peers * sizeof (struct GNUNET_PeerIdentity)), GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN); join_msg->session_id = consensus->session_id; join_msg->start = GNUNET_TIME_absolute_hton (start); join_msg->deadline = GNUNET_TIME_absolute_hton (deadline); join_msg->num_peers = htonl (num_peers); memcpy(&join_msg[1], peers, num_peers * sizeof (struct GNUNET_PeerIdentity)); GNUNET_MQ_send (consensus->mq, ev); return consensus; } static void idc_adapter (void *cls) { struct InsertDoneInfo *i = cls; i->idc (i->cls, GNUNET_OK); GNUNET_free (i); } /** * Insert an element in the set being reconsiled. Must not be called after * "GNUNET_CONSENSUS_conclude". * * @param consensus handle for the consensus session * @param element the element to be inserted * @param idc function called when we are done with this element and it * is thus allowed to call GNUNET_CONSENSUS_insert again * @param idc_cls closure for 'idc' */ void GNUNET_CONSENSUS_insert (struct GNUNET_CONSENSUS_Handle *consensus, const struct GNUNET_SET_Element *element, GNUNET_CONSENSUS_InsertDoneCallback idc, void *idc_cls) { struct GNUNET_CONSENSUS_ElementMessage *element_msg; struct GNUNET_MQ_Envelope *ev; struct InsertDoneInfo *i; LOG (GNUNET_ERROR_TYPE_DEBUG, "inserting, size=%llu\n", element->size); ev = GNUNET_MQ_msg_extra (element_msg, element->size, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT); memcpy (&element_msg[1], element->data, element->size); if (NULL != idc) { i = GNUNET_new (struct InsertDoneInfo); i->idc = idc; i->cls = idc_cls; GNUNET_MQ_notify_sent (ev, idc_adapter, i); } GNUNET_MQ_send (consensus->mq, ev); } /** * We are done with inserting new elements into the consensus; * try to conclude the consensus within a given time window. * After conclude has been called, no further elements may be * inserted by the client. * * @param consensus consensus session * @param deadline deadline after which the conculde callback * must be called * @param conclude called when the conclusion was successful * @param conclude_cls closure for the conclude callback */ void GNUNET_CONSENSUS_conclude (struct GNUNET_CONSENSUS_Handle *consensus, GNUNET_CONSENSUS_ConcludeCallback conclude, void *conclude_cls) { struct GNUNET_MQ_Envelope *ev; GNUNET_assert (NULL != conclude); GNUNET_assert (NULL == consensus->conclude_cb); consensus->conclude_cls = conclude_cls; consensus->conclude_cb = conclude; ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE); GNUNET_MQ_send (consensus->mq, ev); } /** * Destroy a consensus handle (free all state associated with * it, no longer call any of the callbacks). * * @param consensus handle to destroy */ void GNUNET_CONSENSUS_destroy (struct GNUNET_CONSENSUS_Handle *consensus) { if (NULL != consensus->mq) { GNUNET_MQ_destroy (consensus->mq); consensus->mq = NULL; } if (NULL != consensus->client) { GNUNET_CLIENT_disconnect (consensus->client); consensus->client = NULL; } GNUNET_free (consensus); } gnunet-0.10.1/src/consensus/Makefile.in0000644000175000017500000014043212320752060014667 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-consensus-profiler$(EXEEXT) libexec_PROGRAMS = gnunet-service-consensus$(EXEEXT) $(am__EXEEXT_1) # FIXME: add option "configure --with-evil"? @HAVE_EXPERIMENTAL_TRUE@am__append_1 = \ @HAVE_EXPERIMENTAL_TRUE@ gnunet-service-evil-consensus check_PROGRAMS = test_consensus_api$(EXEEXT) subdir = src/consensus DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/consensus.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = consensus.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetconsensus_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetconsensus_la_OBJECTS = consensus_api.lo libgnunetconsensus_la_OBJECTS = $(am_libgnunetconsensus_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetconsensus_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetconsensus_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_EXPERIMENTAL_TRUE@am__EXEEXT_1 = gnunet-service-evil-consensus$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_consensus_profiler_OBJECTS = \ gnunet-consensus-profiler.$(OBJEXT) gnunet_consensus_profiler_OBJECTS = \ $(am_gnunet_consensus_profiler_OBJECTS) am_gnunet_service_consensus_OBJECTS = \ gnunet-service-consensus.$(OBJEXT) gnunet_service_consensus_OBJECTS = \ $(am_gnunet_service_consensus_OBJECTS) am_gnunet_service_evil_consensus_OBJECTS = gnunet_service_evil_consensus-gnunet-service-consensus.$(OBJEXT) gnunet_service_evil_consensus_OBJECTS = \ $(am_gnunet_service_evil_consensus_OBJECTS) gnunet_service_evil_consensus_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(gnunet_service_evil_consensus_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_test_consensus_api_OBJECTS = test_consensus_api.$(OBJEXT) test_consensus_api_OBJECTS = $(am_test_consensus_api_OBJECTS) test_consensus_api_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/consensus/libgnunetconsensus.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetconsensus_la_SOURCES) \ $(gnunet_consensus_profiler_SOURCES) \ $(gnunet_service_consensus_SOURCES) \ $(gnunet_service_evil_consensus_SOURCES) \ $(test_consensus_api_SOURCES) DIST_SOURCES = $(libgnunetconsensus_la_SOURCES) \ $(gnunet_consensus_profiler_SOURCES) \ $(gnunet_service_consensus_SOURCES) \ $(gnunet_service_evil_consensus_SOURCES) \ $(test_consensus_api_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ consensus.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage lib_LTLIBRARIES = \ libgnunetconsensus.la gnunet_consensus_profiler_SOURCES = \ gnunet-consensus-profiler.c gnunet_consensus_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/consensus/libgnunetconsensus.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(GN_LIBINTL) gnunet_consensus_profiler_DEPENDENCIES = \ libgnunetconsensus.la gnunet_service_consensus_SOURCES = \ gnunet-service-consensus.c gnunet_service_consensus_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/set/libgnunetset.la \ $(GN_LIBINTL) gnunet_service_consensus_DEPENDENCIES = \ $(top_builddir)/src/set/libgnunetset.la gnunet_service_evil_consensus_SOURCES = \ gnunet-service-consensus.c \ consensus_protocol.h gnunet_service_evil_consensus_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/set/libgnunetset.la \ $(GN_LIBINTL) gnunet_service_evil_consensus_DEPENDENCIES = \ $(top_builddir)/src/set/libgnunetset.la gnunet_service_evil_consensus_CFLAGS = -DEVIL libgnunetconsensus_la_SOURCES = \ consensus_api.c \ consensus.h libgnunetconsensus_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetconsensus_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_consensus_api_SOURCES = \ test_consensus_api.c test_consensus_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/consensus/libgnunetconsensus.la EXTRA_DIST = \ test_consensus.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/consensus/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/consensus/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): consensus.conf: $(top_builddir)/config.status $(srcdir)/consensus.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetconsensus.la: $(libgnunetconsensus_la_OBJECTS) $(libgnunetconsensus_la_DEPENDENCIES) $(EXTRA_libgnunetconsensus_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetconsensus_la_LINK) -rpath $(libdir) $(libgnunetconsensus_la_OBJECTS) $(libgnunetconsensus_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-consensus-profiler$(EXEEXT): $(gnunet_consensus_profiler_OBJECTS) $(gnunet_consensus_profiler_DEPENDENCIES) $(EXTRA_gnunet_consensus_profiler_DEPENDENCIES) @rm -f gnunet-consensus-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_consensus_profiler_OBJECTS) $(gnunet_consensus_profiler_LDADD) $(LIBS) gnunet-service-consensus$(EXEEXT): $(gnunet_service_consensus_OBJECTS) $(gnunet_service_consensus_DEPENDENCIES) $(EXTRA_gnunet_service_consensus_DEPENDENCIES) @rm -f gnunet-service-consensus$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_consensus_OBJECTS) $(gnunet_service_consensus_LDADD) $(LIBS) gnunet-service-evil-consensus$(EXEEXT): $(gnunet_service_evil_consensus_OBJECTS) $(gnunet_service_evil_consensus_DEPENDENCIES) $(EXTRA_gnunet_service_evil_consensus_DEPENDENCIES) @rm -f gnunet-service-evil-consensus$(EXEEXT) $(AM_V_CCLD)$(gnunet_service_evil_consensus_LINK) $(gnunet_service_evil_consensus_OBJECTS) $(gnunet_service_evil_consensus_LDADD) $(LIBS) test_consensus_api$(EXEEXT): $(test_consensus_api_OBJECTS) $(test_consensus_api_DEPENDENCIES) $(EXTRA_test_consensus_api_DEPENDENCIES) @rm -f test_consensus_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_consensus_api_OBJECTS) $(test_consensus_api_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/consensus_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-consensus-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-consensus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_evil_consensus-gnunet-service-consensus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_consensus_api.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< gnunet_service_evil_consensus-gnunet-service-consensus.o: gnunet-service-consensus.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_evil_consensus_CFLAGS) $(CFLAGS) -MT gnunet_service_evil_consensus-gnunet-service-consensus.o -MD -MP -MF $(DEPDIR)/gnunet_service_evil_consensus-gnunet-service-consensus.Tpo -c -o gnunet_service_evil_consensus-gnunet-service-consensus.o `test -f 'gnunet-service-consensus.c' || echo '$(srcdir)/'`gnunet-service-consensus.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_evil_consensus-gnunet-service-consensus.Tpo $(DEPDIR)/gnunet_service_evil_consensus-gnunet-service-consensus.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-consensus.c' object='gnunet_service_evil_consensus-gnunet-service-consensus.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_evil_consensus_CFLAGS) $(CFLAGS) -c -o gnunet_service_evil_consensus-gnunet-service-consensus.o `test -f 'gnunet-service-consensus.c' || echo '$(srcdir)/'`gnunet-service-consensus.c gnunet_service_evil_consensus-gnunet-service-consensus.obj: gnunet-service-consensus.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_evil_consensus_CFLAGS) $(CFLAGS) -MT gnunet_service_evil_consensus-gnunet-service-consensus.obj -MD -MP -MF $(DEPDIR)/gnunet_service_evil_consensus-gnunet-service-consensus.Tpo -c -o gnunet_service_evil_consensus-gnunet-service-consensus.obj `if test -f 'gnunet-service-consensus.c'; then $(CYGPATH_W) 'gnunet-service-consensus.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-consensus.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_evil_consensus-gnunet-service-consensus.Tpo $(DEPDIR)/gnunet_service_evil_consensus-gnunet-service-consensus.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-consensus.c' object='gnunet_service_evil_consensus-gnunet-service-consensus.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_evil_consensus_CFLAGS) $(CFLAGS) -c -o gnunet_service_evil_consensus-gnunet-service-consensus.obj `if test -f 'gnunet-service-consensus.c'; then $(CYGPATH_W) 'gnunet-service-consensus.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-consensus.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_consensus_api.log: test_consensus_api$(EXEEXT) @p='test_consensus_api$(EXEEXT)'; \ b='test_consensus_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/consensus/test_consensus.conf0000644000175000017500000000144512276375236016570 00000000000000[consensus] AUTOSTART = YES PORT = 2110 HOSTNAME = localhost BINARY = gnunet-service-consensus #PREFIX = gdbserver :12345 #PREFIX = valgrind ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-consensus.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES OPTIONS = -L INFO [transport] OPTIONS = -LERROR [arm] DEFAULTSERVICES = core consensus set [set] OPTIONS = -L INFO #PREFIX = valgrind --leak-check=full #PREFIX = valgrind [testbed] OVERLAY_TOPOLOGY = CLIQUE [hostlist] SERVERS = [nat] # Use addresses from the local network interfaces (inluding loopback, but also others) USE_LOCALADDR = YES # Disable IPv6 support DISABLEV6 = NO # Do we use addresses from localhost address ranges? (::1, 127.0.0.0/8) RETURN_LOCAL_ADDRESSES = YES [nse] AUTOSTART = NO gnunet-0.10.1/src/consensus/Makefile.am0000644000175000017500000000446412320751517014670 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ consensus.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif bin_PROGRAMS = \ gnunet-consensus-profiler libexec_PROGRAMS = \ gnunet-service-consensus # FIXME: add option "configure --with-evil"? if HAVE_EXPERIMENTAL libexec_PROGRAMS += \ gnunet-service-evil-consensus endif lib_LTLIBRARIES = \ libgnunetconsensus.la gnunet_consensus_profiler_SOURCES = \ gnunet-consensus-profiler.c gnunet_consensus_profiler_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/consensus/libgnunetconsensus.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(GN_LIBINTL) gnunet_consensus_profiler_DEPENDENCIES = \ libgnunetconsensus.la gnunet_service_consensus_SOURCES = \ gnunet-service-consensus.c gnunet_service_consensus_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/set/libgnunetset.la \ $(GN_LIBINTL) gnunet_service_consensus_DEPENDENCIES = \ $(top_builddir)/src/set/libgnunetset.la gnunet_service_evil_consensus_SOURCES = \ gnunet-service-consensus.c \ consensus_protocol.h gnunet_service_evil_consensus_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/set/libgnunetset.la \ $(GN_LIBINTL) gnunet_service_evil_consensus_DEPENDENCIES = \ $(top_builddir)/src/set/libgnunetset.la gnunet_service_evil_consensus_CFLAGS = -DEVIL libgnunetconsensus_la_SOURCES = \ consensus_api.c \ consensus.h libgnunetconsensus_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunetconsensus_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) check_PROGRAMS = \ test_consensus_api if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_consensus_api_SOURCES = \ test_consensus_api.c test_consensus_api_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/consensus/libgnunetconsensus.la EXTRA_DIST = \ test_consensus.conf gnunet-0.10.1/src/consensus/test_consensus_api.c0000644000175000017500000000636712274707232016717 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file consensus/test_consensus_api.c * @brief testcase for consensus_api.c */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_consensus_service.h" #include "gnunet_testing_lib.h" static struct GNUNET_CONSENSUS_Handle *consensus; static struct GNUNET_HashCode session_id; static unsigned int elements_received; static void conclude_done (void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "conclude over\n"); if (2 != elements_received) GNUNET_abort (); GNUNET_SCHEDULER_shutdown (); } static void on_new_element (void *cls, const struct GNUNET_SET_Element *element) { elements_received++; } static void insert_done (void *cls, int success) { /* make sure cb is only called once */ static int called = GNUNET_NO; GNUNET_assert (GNUNET_NO == called); called = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "insert done\n"); GNUNET_CONSENSUS_conclude (consensus, &conclude_done, NULL); } /** * Signature of the main function of a task. * * @param cls closure * @param tc context information (why was this task triggered now) */ static void on_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != consensus) { GNUNET_CONSENSUS_destroy (consensus); consensus = NULL; } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { char *str = "foo"; struct GNUNET_SET_Element el1 = {4, 0, "foo"}; struct GNUNET_SET_Element el2 = {5, 0, "quux"}; GNUNET_log_setup ("test_consensus_api", "INFO", NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "testing consensus api\n"); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &on_shutdown, NULL); GNUNET_CRYPTO_hash (str, strlen (str), &session_id); consensus = GNUNET_CONSENSUS_create (cfg, 0, NULL, &session_id, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_SECONDS), GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES), on_new_element, &consensus); GNUNET_assert (consensus != NULL); GNUNET_CONSENSUS_insert (consensus, &el1, NULL, &consensus); GNUNET_CONSENSUS_insert (consensus, &el2, &insert_done, &consensus); } int main (int argc, char **argv) { int ret; ret = GNUNET_TESTING_peer_run ("test_consensus_api", "test_consensus.conf", &run, NULL); return ret; } gnunet-0.10.1/src/consensus/consensus_protocol.h0000644000175000017500000000270312276375236016752 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file consensus/consensus_protocol.h * @brief p2p message definitions for consensus * @author Florian Dold */ #ifndef GNUNET_CONSENSUS_PROTOCOL_H #define GNUNET_CONSENSUS_PROTOCOL_H #include "platform.h" #include "gnunet_common.h" #include "gnunet_protocols.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Sent as context message for set reconciliation. */ struct GNUNET_CONSENSUS_RoundContextMessage { /** * Type: GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT */ struct GNUNET_MessageHeader header; uint32_t round; uint32_t exp_repetition; uint32_t exp_subround; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/consensus/gnunet-consensus-profiler.c0000644000175000017500000003112512276375236020142 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file consensus/gnunet-consensus-profiler.c * @brief profiling tool for gnunet-consensus * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_time_lib.h" #include "gnunet_consensus_service.h" #include "gnunet_testbed_service.h" static unsigned int num_peers = 2; static unsigned int replication = 1; static unsigned int num_values = 5; static struct GNUNET_TIME_Relative conclude_timeout; static struct GNUNET_TIME_Relative consensus_delay; static struct GNUNET_CONSENSUS_Handle **consensus_handles; static struct GNUNET_TESTBED_Operation **testbed_operations; static unsigned int num_connected_handles; static struct GNUNET_TESTBED_Peer **peers; static struct GNUNET_PeerIdentity *peer_ids; static unsigned int num_retrieved_peer_ids; static struct GNUNET_HashCode session_id; static unsigned int peers_done = 0; static unsigned *results_for_peer; static int verbose; /** * Start time for all consensuses. */ static struct GNUNET_TIME_Absolute start; /** * Deadline for all consensuses. */ static struct GNUNET_TIME_Absolute deadline; /** * Signature of the event handler function called by the * respective event controller. * * @param cls closure * @param event information about the event */ static void controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { GNUNET_assert (0); } static void destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *ctx) { struct GNUNET_CONSENSUS_Handle *consensus = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "destroying consensus\n"); GNUNET_CONSENSUS_destroy (consensus); peers_done++; if (peers_done == num_peers) { unsigned int i; for (i = 0; i < num_peers; i++) GNUNET_TESTBED_operation_done (testbed_operations[i]); for (i = 0; i < num_peers; i++) printf ("P%u got %u of %u elements\n", i, results_for_peer[i], num_values); GNUNET_SCHEDULER_shutdown (); } } /** * Called when a conclusion was successful. * * @param cls closure, the consensus handle * @return #GNUNET_YES if more consensus groups should be offered, * #GNUNET_NO if not */ static void conclude_cb (void *cls) { struct GNUNET_CONSENSUS_Handle **chp = cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "consensus %d done\n", chp - consensus_handles); GNUNET_SCHEDULER_add_now (destroy, *chp); } static void generate_indices (int *indices) { int j; j = 0; while (j < replication) { int n; int k; int repeat; n = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, num_peers); repeat = GNUNET_NO; for (k = 0; k < j; k++) if (indices[k] == n) { repeat = GNUNET_YES; break; } if (GNUNET_NO == repeat) indices[j++] = n; } } static void do_consensus () { int unique_indices[replication]; unsigned int i; for (i = 0; i < num_values; i++) { unsigned int j; struct GNUNET_HashCode val; struct GNUNET_SET_Element element; generate_indices (unique_indices); GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &val); element.data = &val; element.size = sizeof (val); for (j = 0; j < replication; j++) { int cid; cid = unique_indices[j]; GNUNET_CONSENSUS_insert (consensus_handles[cid], &element, NULL, NULL); } } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "all elements inserted, calling conclude\n"); for (i = 0; i < num_peers; i++) GNUNET_CONSENSUS_conclude (consensus_handles[i], conclude_cb, &consensus_handles[i]); } /** * Callback to be called when a service connect operation is completed * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void connect_complete (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "testbed connect emsg: %s\n", emsg); GNUNET_assert (0); } num_connected_handles++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "connect complete\n"); if (num_connected_handles == num_peers) { do_consensus (); } } static void new_element_cb (void *cls, const struct GNUNET_SET_Element *element) { struct GNUNET_CONSENSUS_Handle **chp = cls; int idx = chp - consensus_handles; GNUNET_assert (NULL != cls); results_for_peer[idx]++; GNUNET_assert (sizeof (struct GNUNET_HashCode) == element->size); if (GNUNET_YES == verbose) { printf ("P%d received %s\n", idx, GNUNET_h2s ((struct GNUNET_HashCode *) element->data)); } } /** * Adapter function called to establish a connection to * a service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_CONSENSUS_Handle **chp = cls; struct GNUNET_CONSENSUS_Handle *consensus; chp = (struct GNUNET_CONSENSUS_Handle **) cls; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "connect adapter, %d peers\n", num_peers); consensus = GNUNET_CONSENSUS_create (cfg, num_peers, peer_ids, &session_id, start, deadline, &new_element_cb, chp); *chp = (struct GNUNET_CONSENSUS_Handle *) consensus; return consensus; } /** * Adapter function called to destroy a connection to * a service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void disconnect_adapter(void *cls, void *op_result) { /* FIXME: what to do here? */ } /** * Callback to be called when the requested peer information is available * * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() * @param op the operation this callback corresponds to * @param pinfo the result; will be NULL if the operation has failed * @param emsg error message if the operation has failed; will be NULL if the * operation is successfull */ static void peer_info_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) { struct GNUNET_PeerIdentity *p; int i; GNUNET_assert (NULL == emsg); p = (struct GNUNET_PeerIdentity *) cb_cls; if (pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY) { *p = *pinfo->result.id; num_retrieved_peer_ids++; if (num_retrieved_peer_ids == num_peers) for (i = 0; i < num_peers; i++) testbed_operations[i] = GNUNET_TESTBED_service_connect (NULL, peers[i], "consensus", connect_complete, NULL, connect_adapter, disconnect_adapter, &consensus_handles[i]); } else { GNUNET_assert (0); } GNUNET_TESTBED_operation_done (op); } /** * Signature of a main function for a testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param started_peers handle to peers run in the testbed. NULL upon timeout (see * GNUNET_TESTBED_test_run()). * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **started_peers, unsigned int links_succeeded, unsigned int links_failed) { int i; GNUNET_log_setup ("gnunet-consensus", "INFO", NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "test master\n"); peers = started_peers; peer_ids = GNUNET_malloc (num_peers * sizeof (struct GNUNET_PeerIdentity)); results_for_peer = GNUNET_malloc (num_peers * sizeof (unsigned int)); consensus_handles = GNUNET_malloc (num_peers * sizeof (struct ConsensusHandle *)); testbed_operations = GNUNET_malloc (num_peers * sizeof (struct ConsensusHandle *)); for (i = 0; i < num_peers; i++) GNUNET_TESTBED_peer_get_information (peers[i], GNUNET_TESTBED_PIT_IDENTITY, peer_info_cb, &peer_ids[i]); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { static char *session_str = "gnunet-consensus/test"; char *topology; int topology_cmp_result; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "testbed", "OVERLAY_TOPOLOGY", &topology)) { fprintf (stderr, "'OVERLAY_TOPOLOGY' not found in 'testbed' config section, " "seems like you passed the wrong configuration file\n"); return; } topology_cmp_result = strcasecmp (topology, "NONE"); GNUNET_free (topology); if (0 == topology_cmp_result) { fprintf (stderr, "'OVERLAY_TOPOLOGY' set to 'NONE', " "seems like you passed the wrong configuration file\n"); return; } if (num_peers < replication) { fprintf (stderr, "k must be <=n\n"); return; } start = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), consensus_delay); deadline = GNUNET_TIME_absolute_add (start, conclude_timeout); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "running gnunet-consensus\n"); GNUNET_CRYPTO_hash (session_str, strlen(session_str), &session_id); (void) GNUNET_TESTBED_test_run ("gnunet-consensus", cfgfile, num_peers, 0, controller_cb, NULL, test_master, NULL); } int main (int argc, char **argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'n', "num-peers", NULL, gettext_noop ("number of peers in consensus"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_peers }, { 'k', "value-replication", NULL, gettext_noop ("how many peers receive one value?"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &replication }, { 'x', "num-values", NULL, gettext_noop ("number of values"), GNUNET_YES, &GNUNET_GETOPT_set_uint, &num_values }, { 't', "timeout", NULL, gettext_noop ("consensus timeout"), GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &conclude_timeout }, { 'd', "delay", NULL, gettext_noop ("delay until consensus starts"), GNUNET_YES, &GNUNET_GETOPT_set_relative_time, &consensus_delay }, { 'V', "verbose", NULL, gettext_noop ("be more verbose (print received values)"), GNUNET_NO, &GNUNET_GETOPT_set_one, &verbose }, GNUNET_GETOPT_OPTION_END }; conclude_timeout = GNUNET_TIME_UNIT_SECONDS; GNUNET_PROGRAM_run2 (argc, argv, "gnunet-consensus-profiler", "help", options, &run, NULL, GNUNET_YES); return 0; } gnunet-0.10.1/src/consensus/consensus.h0000644000175000017500000000421212274162760015020 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Florian Dold * @file consensus/consensus.h * @brief */ #ifndef CONSENSUS_H #define CONSENSUS_H #include "gnunet_common.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Sent by the client to the service, * when the client wants the service to join a consensus session. */ struct GNUNET_CONSENSUS_JoinMessage { /** * Type: GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN */ struct GNUNET_MessageHeader header; /** * Number of peers (at the end of this message) that want to * participate in the consensus. */ uint32_t num_peers GNUNET_PACKED; /** * Session id of the consensus. */ struct GNUNET_HashCode session_id; /** * Start time for the consensus. */ struct GNUNET_TIME_AbsoluteNBO start; /** * Deadline for conclude. */ struct GNUNET_TIME_AbsoluteNBO deadline; /* GNUNET_PeerIdentity[num_peers] */ }; /** * Message with an element */ struct GNUNET_CONSENSUS_ElementMessage { /** * Type: * Either GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT * or GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT_ELEMENT */ struct GNUNET_MessageHeader header; /** * Type: GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_NEW_ELEMENT */ uint16_t element_type GNUNET_PACKED; /* FIXME: alignment? => uint32_t */ /* rest: element data */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/consensus/consensus.conf.in0000644000175000017500000000040512250373167016122 00000000000000[consensus] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2103 HOSTNAME = localhost BINARY = gnunet-service-consensus ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-consensus.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES gnunet-0.10.1/src/consensus/gnunet-service-consensus.c0000644000175000017500000012134712276375236017766 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file consensus/gnunet-service-consensus.c * @brief multi-peer set reconciliation * @author Florian Dold */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet_set_service.h" #include "gnunet_consensus_service.h" #include "consensus_protocol.h" #include "consensus.h" /** * Log macro that prefixes the local peer and the peer we are in contact with. * * @param kind log level * @param cpi ConsensusPeerInformation of the partner peer * @param m log message */ #define LOG_PP(kind, cpi, m,...) GNUNET_log (kind, "P%d for P%d: " m, \ cpi->session->local_peer_idx, (int) (cpi - cpi->session->info),##__VA_ARGS__) /** * Number of exponential rounds, used in the exp and completion round. */ #define NUM_EXP_REPETITIONS 4 /* forward declarations */ /* mutual recursion with struct ConsensusSession */ struct ConsensusPeerInformation; /* mutual recursion with round_over */ static void subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Describes the current round a consensus session is in. */ enum ConsensusRound { /** * Not started the protocol yet. */ CONSENSUS_ROUND_BEGIN=0, /** * Distribution of elements with the exponential scheme. */ CONSENSUS_ROUND_EXCHANGE, /** * Collect and distribute missing values. */ CONSENSUS_ROUND_COMPLETION, /** * Consensus concluded. After timeout and finished communication with client, * consensus session will be destroyed. */ CONSENSUS_ROUND_FINISH }; /** * Information about the current round. */ struct RoundInfo { /** * The current main round. */ enum ConsensusRound round; /** * The current exp round repetition, valid if * the main round is an exp round. */ uint32_t exp_repetition; /** * The current exp subround, valid if * the main round is an exp round. */ uint32_t exp_subround; }; /** * A consensus session consists of one local client and the remote authorities. */ struct ConsensusSession { /** * Consensus sessions are kept in a DLL. */ struct ConsensusSession *next; /** * Consensus sessions are kept in a DLL. */ struct ConsensusSession *prev; /** * Global consensus identification, computed * from the session id and participating authorities. */ struct GNUNET_HashCode global_id; /** * Client that inhabits the session */ struct GNUNET_SERVER_Client *client; /** * Queued messages to the client. */ struct GNUNET_MQ_Handle *client_mq; /** * Time when the conclusion of the consensus should begin. */ struct GNUNET_TIME_Absolute conclude_start; /** * Timeout for all rounds together, single rounds will schedule a timeout task * with a fraction of the conclude timeout. * Only valid once the current round is not CONSENSUS_ROUND_BEGIN. */ struct GNUNET_TIME_Absolute conclude_deadline; /** * Timeout task identifier for the current round or subround. */ GNUNET_SCHEDULER_TaskIdentifier round_timeout_tid; /** * Number of other peers in the consensus. */ unsigned int num_peers; /** * Information about the other peers, * their state, etc. */ struct ConsensusPeerInformation *info; /** * Index of the local peer in the peers array */ unsigned int local_peer_idx; /** * Current round */ enum ConsensusRound current_round; /** * Permutation of peers for the current round, */ uint32_t *shuffle; /** * Inverse permutation of peers for the current round, */ uint32_t *shuffle_inv; /** * Current round of the exponential scheme. */ uint32_t exp_repetition; /** * Current sub-round of the exponential scheme. */ uint32_t exp_subround; /** * The partner for the current exp-round. * The local peer will initiate the set reconciliation with the * outgoing peer. */ struct ConsensusPeerInformation *partner_outgoing; /** * The partner for the current exp-round * The incoming peer will initiate the set reconciliation with * the incoming peer. */ struct ConsensusPeerInformation *partner_incoming; /** * The consensus set of this session. */ struct GNUNET_SET_Handle *element_set; /** * Listener for requests from other peers. * Uses the session's global id as app id. */ struct GNUNET_SET_ListenHandle *set_listener; }; /** * Information about a peer that is in a consensus session. */ struct ConsensusPeerInformation { /** * Peer identitty of the peer in the consensus session */ struct GNUNET_PeerIdentity peer_id; /** * Back-reference to the consensus session, * to that ConsensusPeerInformation can be used as a closure */ struct ConsensusSession *session; /** * Have we finished the set operation for this (sub-)round? */ int set_op_finished; /** * Set operation we are currently executing with this peer. */ struct GNUNET_SET_OperationHandle *set_op; /** * Set operation we are planning on executing with this peer. */ struct GNUNET_SET_OperationHandle *delayed_set_op; /** * Info about the round of the delayed set operation. */ struct RoundInfo delayed_round_info; }; /** * Linked list of sessions this peer participates in. */ static struct ConsensusSession *sessions_head; /** * Linked list of sessions this peer participates in. */ static struct ConsensusSession *sessions_tail; /** * Configuration of the consensus service. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the server for this service. */ static struct GNUNET_SERVER_Handle *srv; /** * Peer that runs this service. */ static struct GNUNET_PeerIdentity my_peer; /** * Check if the current subround has finished. * Must only be called when an exp-round is the current round. * * @param session session to check for exp-round completion * @return GNUNET_YES if the subround has finished, * GNUNET_NO if not */ static int have_exp_subround_finished (const struct ConsensusSession *session) { int not_finished; GNUNET_assert (CONSENSUS_ROUND_EXCHANGE == session->current_round); not_finished = 0; if ( (NULL != session->partner_outgoing) && (GNUNET_NO == session->partner_outgoing->set_op_finished) ) not_finished++; if ( (NULL != session->partner_incoming) && (GNUNET_NO == session->partner_incoming->set_op_finished) ) not_finished++; if (0 == not_finished) return GNUNET_YES; return GNUNET_NO; } /** * Destroy a session, free all resources associated with it. * * @param session the session to destroy */ static void destroy_session (struct ConsensusSession *session) { int i; GNUNET_CONTAINER_DLL_remove (sessions_head, sessions_tail, session); if (NULL != session->element_set) { GNUNET_SET_destroy (session->element_set); session->element_set = NULL; } if (NULL != session->set_listener) { GNUNET_SET_listen_cancel (session->set_listener); session->set_listener = NULL; } if (NULL != session->client_mq) { GNUNET_MQ_destroy (session->client_mq); session->client_mq = NULL; } if (NULL != session->client) { GNUNET_SERVER_client_disconnect (session->client); session->client = NULL; } if (NULL != session->shuffle) { GNUNET_free (session->shuffle); session->shuffle = NULL; } if (NULL != session->shuffle_inv) { GNUNET_free (session->shuffle_inv); session->shuffle_inv = NULL; } if (NULL != session->info) { for (i = 0; i < session->num_peers; i++) { struct ConsensusPeerInformation *cpi; cpi = &session->info[i]; if (NULL != cpi->set_op) { GNUNET_SET_operation_cancel (cpi->set_op); cpi->set_op = NULL; } } GNUNET_free (session->info); session->info = NULL; } GNUNET_free (session); } /** * Iterator for set elements. * * @param cls closure * @param element the current element, NULL if all elements have been * iterated over * @return GNUNET_YES to continue iterating, GNUNET_NO to stop. */ static int send_to_client_iter (void *cls, const struct GNUNET_SET_Element *element) { struct ConsensusSession *session = cls; struct GNUNET_MQ_Envelope *ev; if (NULL != element) { struct GNUNET_CONSENSUS_ElementMessage *m; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: got element for client\n", session->local_peer_idx); ev = GNUNET_MQ_msg_extra (m, element->size, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_RECEIVED_ELEMENT); m->element_type = htons (element->type); memcpy (&m[1], element->data, element->size); GNUNET_MQ_send (session->client_mq, ev); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: finished iterating elements for client\n", session->local_peer_idx); ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE_DONE); GNUNET_MQ_send (session->client_mq, ev); } return GNUNET_YES; } /** * Start the next round. * This function can be invoked as a timeout task, or called manually (tc will be NULL then). * * @param cls the session * @param tc task context, for when this task is invoked by the scheduler, * NULL if invoked for another reason */ static void round_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ConsensusSession *session; unsigned int i; int res; /* don't kick off next round if we're shutting down */ if ((NULL != tc) && (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; session = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: round over\n", session->local_peer_idx); if (tc != NULL) session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK; if (session->round_timeout_tid != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (session->round_timeout_tid); session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK; } for (i = 0; i < session->num_peers; i++) { if (NULL != session->info[i].set_op) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: canceling stray op with P%d\n", session->local_peer_idx, i); GNUNET_SET_operation_cancel (session->info[i].set_op); session->info[i].set_op = NULL; } /* we're in the new round, nothing finished yet */ session->info[i].set_op_finished = GNUNET_NO; } switch (session->current_round) { case CONSENSUS_ROUND_BEGIN: session->current_round = CONSENSUS_ROUND_EXCHANGE; session->exp_repetition = 0; subround_over (session, NULL); break; case CONSENSUS_ROUND_EXCHANGE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: finished, sending elements to client\n", session->local_peer_idx); session->current_round = CONSENSUS_ROUND_FINISH; res = GNUNET_SET_iterate (session->element_set, send_to_client_iter, session); if (GNUNET_SYSERR == res) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "can't iterate set: set invalid\n"); } else if (GNUNET_NO == res) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "can't iterate set: iterator already active\n"); } break; default: GNUNET_assert (0); } } /** * Create a new permutation for the session's peers in session->shuffle. * Uses a Fisher-Yates shuffle with pseudo-randomness coming from * both the global session id and the current round index. * * @param session the session to create the new permutation for */ static void shuffle (struct ConsensusSession *session) { uint32_t i; uint32_t randomness[session->num_peers-1]; if (NULL == session->shuffle) session->shuffle = GNUNET_malloc (session->num_peers * sizeof (*session->shuffle)); if (NULL == session->shuffle_inv) session->shuffle_inv = GNUNET_malloc (session->num_peers * sizeof (*session->shuffle_inv)); GNUNET_CRYPTO_kdf (randomness, sizeof (randomness), &session->exp_repetition, sizeof (uint32_t), &session->global_id, sizeof (struct GNUNET_HashCode), NULL); for (i = 0; i < session->num_peers; i++) session->shuffle[i] = i; for (i = session->num_peers - 1; i > 0; i--) { uint32_t x; uint32_t tmp; x = randomness[i-1] % session->num_peers; tmp = session->shuffle[x]; session->shuffle[x] = session->shuffle[i]; session->shuffle[i] = tmp; } /* create the inverse */ for (i = 0; i < session->num_peers; i++) session->shuffle_inv[session->shuffle[i]] = i; } /** * Find and set the partner_incoming and partner_outgoing of our peer, * one of them may not exist (and thus set to NULL) if the number of peers * in the session is not a power of two. * * @param session the consensus session */ static void find_partners (struct ConsensusSession *session) { unsigned int arc; unsigned int num_ghosts; unsigned int largest_arc; int partner_idx; /* shuffled local index */ int my_idx = session->shuffle[session->local_peer_idx]; /* distance to neighboring peer in current subround */ arc = 1 << session->exp_subround; largest_arc = 1; while (largest_arc < session->num_peers) largest_arc <<= 1; num_ghosts = largest_arc - session->num_peers; // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "largest arc: %u\n", largest_arc); // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "arc: %u\n", arc); // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "num ghosts: %u\n", num_ghosts); if (0 == (my_idx & arc)) { /* we are outgoing */ partner_idx = (my_idx + arc) % session->num_peers; session->partner_outgoing = &session->info[session->shuffle_inv[partner_idx]]; GNUNET_assert (GNUNET_NO == session->partner_outgoing->set_op_finished); /* are we a 'ghost' of a peer that would exist if * the number of peers was a power of two, and thus have to partner * with an additional peer? */ if (my_idx < num_ghosts) { int ghost_partner_idx; // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "my index %d, arc %d, peers %u\n", my_idx, arc, session->num_peers); ghost_partner_idx = (my_idx - (int) arc) % (int) session->num_peers; /* platform dependent; modulo sometimes returns negative values */ if (ghost_partner_idx < 0) ghost_partner_idx += session->num_peers; /* we only need to have a ghost partner if the partner is outgoing */ if (0 == (ghost_partner_idx & arc)) { // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ghost partner is %d\n", ghost_partner_idx); session->partner_incoming = &session->info[session->shuffle_inv[ghost_partner_idx]]; GNUNET_assert (GNUNET_NO == session->partner_incoming->set_op_finished); return; } } session->partner_incoming = NULL; return; } /* we only have an incoming connection */ partner_idx = (my_idx - (int) arc) % (int) session->num_peers; if (partner_idx < 0) partner_idx += session->num_peers; session->partner_outgoing = NULL; session->partner_incoming = &session->info[session->shuffle_inv[partner_idx]]; GNUNET_assert (GNUNET_NO == session->partner_incoming->set_op_finished); } /** * Callback for set operation results. Called for each element * in the result set. * * @param cls closure * @param element a result element, only valid if status is GNUNET_SET_STATUS_OK * @param status see enum GNUNET_SET_Status */ static void set_result_cb (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { struct ConsensusPeerInformation *cpi = cls; unsigned int remote_idx = cpi - cpi->session->info; unsigned int local_idx = cpi->session->local_peer_idx; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: set result from P%u with status %u\n", local_idx, remote_idx, (unsigned int) status); GNUNET_assert ((cpi == cpi->session->partner_outgoing) || (cpi == cpi->session->partner_incoming)); switch (status) { case GNUNET_SET_STATUS_OK: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: set result from P%u: element\n", local_idx, remote_idx); break; case GNUNET_SET_STATUS_FAILURE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: set result from P%u: failure\n", local_idx, remote_idx); cpi->set_op = NULL; return; case GNUNET_SET_STATUS_HALF_DONE: case GNUNET_SET_STATUS_DONE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: set result from P%u: done\n", local_idx, remote_idx); cpi->set_op_finished = GNUNET_YES; cpi->set_op = NULL; if (have_exp_subround_finished (cpi->session) == GNUNET_YES) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: all reconciliations of subround done\n", local_idx); subround_over (cpi->session, NULL); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: waiting for further set results\n", local_idx); } return; default: GNUNET_break (0); return; } switch (cpi->session->current_round) { case CONSENSUS_ROUND_COMPLETION: case CONSENSUS_ROUND_EXCHANGE: GNUNET_SET_add_element (cpi->session->element_set, element, NULL, NULL); break; default: GNUNET_break (0); return; } } /** * Compare the round the session is in with the round of the given context message. * * @param session a consensus session * @param ri a round context message * @return 0 if it's the same round, -1 if the session is in an earlier round, * 1 if the session is in a later round */ static int rounds_compare (struct ConsensusSession *session, struct RoundInfo* ri) { if (session->current_round < ri->round) return -1; if (session->current_round > ri->round) return 1; if (session->current_round == CONSENSUS_ROUND_EXCHANGE) { if (session->exp_repetition < ri->exp_repetition) return -1; if (session->exp_repetition > ri->exp_repetition) return 1; if (session->exp_subround < ri->exp_subround) return -1; if (session->exp_subround > ri->exp_subround) return 1; return 0; } /* other rounds have no subrounds / repetitions to compare */ return 0; } /** * Do the next subround in the exp-scheme. * This function can be invoked as a timeout task, or called manually (tc will be NULL then). * * @param cls the session * @param tc task context, for when this task is invoked by the scheduler, * NULL if invoked for another reason */ static void subround_over (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ConsensusSession *session; struct GNUNET_TIME_Relative subround_timeout; int i; /* don't kick off next subround if we're shutting down */ if ((NULL != tc) && (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; session = cls; GNUNET_assert (CONSENSUS_ROUND_EXCHANGE == session->current_round); if (tc != NULL) { session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "P%u: consensus subround timed out\n", session->local_peer_idx); } /* cancel timeout */ if (session->round_timeout_tid != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (session->round_timeout_tid); session->round_timeout_tid = GNUNET_SCHEDULER_NO_TASK; } for (i = 0; i < session->num_peers; i++) { if (NULL != session->info[i].set_op) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d: canceling stray op with P%d\n", session->local_peer_idx, i); GNUNET_SET_operation_cancel (session->info[i].set_op); session->info[i].set_op = NULL; } /* we're in the new round, nothing finished yet */ session->info[i].set_op_finished = GNUNET_NO; } if (session->exp_repetition >= NUM_EXP_REPETITIONS) { round_over (session, NULL); return; } if (session->exp_repetition == 0) { /* initialize everything for the log-rounds */ session->exp_repetition = 1; session->exp_subround = 0; if (NULL == session->shuffle) session->shuffle = GNUNET_malloc ((sizeof (int)) * session->num_peers); if (NULL == session->shuffle_inv) session->shuffle_inv = GNUNET_malloc ((sizeof (int)) * session->num_peers); for (i = 0; i < session->num_peers; i++) session->shuffle[i] = session->shuffle_inv[i] = i; } else if (session->exp_subround + 1 >= (int) ceil (log2 (session->num_peers))) { /* subrounds done, start new log-round */ session->exp_repetition++; session->exp_subround = 0; shuffle (session); } else { session->exp_subround++; } subround_timeout = GNUNET_TIME_relative_divide (GNUNET_TIME_absolute_get_difference (session->conclude_start, session->conclude_deadline), 2 * NUM_EXP_REPETITIONS * ((int) ceil (log2 (session->num_peers)))); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "subround timeout: %u ms\n", subround_timeout.rel_value_us / 1000); session->round_timeout_tid = GNUNET_SCHEDULER_add_delayed (subround_timeout, subround_over, session); /* determine the incoming and outgoing partner */ find_partners (session); GNUNET_assert (session->partner_outgoing != &session->info[session->local_peer_idx]); GNUNET_assert (session->partner_incoming != &session->info[session->local_peer_idx]); /* initiate set operation with the outgoing partner */ if (NULL != session->partner_outgoing) { struct GNUNET_CONSENSUS_RoundContextMessage *msg; msg = GNUNET_new (struct GNUNET_CONSENSUS_RoundContextMessage); msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONSENSUS_P2P_ROUND_CONTEXT); msg->header.size = htons (sizeof *msg); msg->round = htonl (session->current_round); msg->exp_repetition = htonl (session->exp_repetition); msg->exp_subround = htonl (session->exp_subround); if (NULL != session->partner_outgoing->set_op) { GNUNET_break (0); GNUNET_SET_operation_cancel (session->partner_outgoing->set_op); } session->partner_outgoing->set_op = GNUNET_SET_prepare (&session->partner_outgoing->peer_id, &session->global_id, (struct GNUNET_MessageHeader *) msg, 0, /* FIXME: salt */ GNUNET_SET_RESULT_ADDED, set_result_cb, session->partner_outgoing); GNUNET_free (msg); if (GNUNET_OK != GNUNET_SET_commit (session->partner_outgoing->set_op, session->element_set)) { GNUNET_break (0); session->partner_outgoing->set_op = NULL; session->partner_outgoing->set_op_finished = GNUNET_YES; } } /* commit to the delayed set operation */ if ((NULL != session->partner_incoming) && (NULL != session->partner_incoming->delayed_set_op)) { int cmp = rounds_compare (session, &session->partner_incoming->delayed_round_info); if (NULL != session->partner_incoming->set_op) { GNUNET_break (0); GNUNET_SET_operation_cancel (session->partner_incoming->set_op); session->partner_incoming->set_op = NULL; } if (cmp == 0) { if (GNUNET_OK != GNUNET_SET_commit (session->partner_incoming->delayed_set_op, session->element_set)) { GNUNET_break (0); } session->partner_incoming->set_op = session->partner_incoming->delayed_set_op; session->partner_incoming->delayed_set_op = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d resumed delayed round with P%d\n", session->local_peer_idx, (int) (session->partner_incoming - session->info)); } else { /* this should not happen -- a round has been skipped! */ GNUNET_break_op (0); } } #ifdef GNUNET_EXTRA_LOGGING { int in; int out; if (session->partner_outgoing == NULL) out = -1; else out = (int) (session->partner_outgoing - session->info); if (session->partner_incoming == NULL) in = -1; else in = (int) (session->partner_incoming - session->info); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: doing exp-round, r=%d, sub=%d, in: %d, out: %d\n", session->local_peer_idx, session->exp_repetition, session->exp_subround, in, out); } #endif /* GNUNET_EXTRA_LOGGING */ } /** * Search peer in the list of peers in session. * * @param peer peer to find * @param session session with peer * @return index of peer, -1 if peer is not in session */ static int get_peer_idx (const struct GNUNET_PeerIdentity *peer, const struct ConsensusSession *session) { int i; for (i = 0; i < session->num_peers; i++) if (0 == memcmp (peer, &session->info[i].peer_id, sizeof *peer)) return i; return -1; } /** * Compute a global, (hopefully) unique consensus session id, * from the local id of the consensus session, and the identities of all participants. * Thus, if the local id of two consensus sessions coincide, but are not comprised of * exactly the same peers, the global id will be different. * * @param session session to generate the global id for * @param session_id local id of the consensus session */ static void compute_global_id (struct ConsensusSession *session, const struct GNUNET_HashCode *session_id) { int i; struct GNUNET_HashCode tmp; struct GNUNET_HashCode phash; /* FIXME: use kdf? */ session->global_id = *session_id; for (i = 0; i < session->num_peers; ++i) { GNUNET_CRYPTO_hash (&session->info[i].peer_id, sizeof (struct GNUNET_PeerIdentity), &phash); GNUNET_CRYPTO_hash_xor (&session->global_id, &phash, &tmp); session->global_id = tmp; GNUNET_CRYPTO_hash (&session->global_id, sizeof (struct GNUNET_PeerIdentity), &tmp); session->global_id = tmp; } } /** * Compare two peer identities. * * @param h1 some peer identity * @param h2 some peer identity * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2. */ static int peer_id_cmp (const void *h1, const void *h2) { return memcmp (h1, h2, sizeof (struct GNUNET_PeerIdentity)); } /** * Create the sorted list of peers for the session, * add the local peer if not in the join message. */ static void initialize_session_peer_list (struct ConsensusSession *session, struct GNUNET_CONSENSUS_JoinMessage *join_msg) { unsigned int local_peer_in_list; uint32_t listed_peers; const struct GNUNET_PeerIdentity *msg_peers; struct GNUNET_PeerIdentity *peers; unsigned int i; GNUNET_assert (NULL != join_msg); /* peers in the join message, may or may not include the local peer */ listed_peers = ntohl (join_msg->num_peers); session->num_peers = listed_peers; msg_peers = (struct GNUNET_PeerIdentity *) &join_msg[1]; local_peer_in_list = GNUNET_NO; for (i = 0; i < listed_peers; i++) { if (0 == memcmp (&msg_peers[i], &my_peer, sizeof (struct GNUNET_PeerIdentity))) { local_peer_in_list = GNUNET_YES; break; } } if (GNUNET_NO == local_peer_in_list) session->num_peers++; peers = GNUNET_malloc (session->num_peers * sizeof (struct GNUNET_PeerIdentity)); if (GNUNET_NO == local_peer_in_list) peers[session->num_peers - 1] = my_peer; memcpy (peers, msg_peers, listed_peers * sizeof (struct GNUNET_PeerIdentity)); qsort (peers, session->num_peers, sizeof (struct GNUNET_PeerIdentity), &peer_id_cmp); session->info = GNUNET_malloc (session->num_peers * sizeof (struct ConsensusPeerInformation)); for (i = 0; i < session->num_peers; ++i) { /* initialize back-references, so consensus peer information can * be used as closure */ session->info[i].session = session; session->info[i].peer_id = peers[i]; } GNUNET_free (peers); } /** * Called when another peer wants to do a set operation with the * local peer. * * @param cls closure * @param other_peer the other peer * @param context_msg message with application specific information from * the other peer * @param request request from the other peer, use GNUNET_SET_accept * to accept it, otherwise the request will be refused * Note that we don't use a return value here, as it is also * necessary to specify the set we want to do the operation with, * whith sometimes can be derived from the context message. * Also necessary to specify the timeout. */ static void set_listen_cb (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request) { struct ConsensusSession *session = cls; struct GNUNET_CONSENSUS_RoundContextMessage *msg = (struct GNUNET_CONSENSUS_RoundContextMessage *) context_msg; struct ConsensusPeerInformation *cpi; struct GNUNET_SET_OperationHandle *set_op; struct RoundInfo round_info; int index; int cmp; if (NULL == context_msg) { GNUNET_break_op (0); return; } index = get_peer_idx (other_peer, session); if (index < 0) { GNUNET_break_op (0); return; } round_info.round = ntohl (msg->round); round_info.exp_repetition = ntohl (msg->exp_repetition); round_info.exp_subround = ntohl (msg->exp_subround); cpi = &session->info[index]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d got set request from P%d\n", session->local_peer_idx, index); switch (session->current_round) { case CONSENSUS_ROUND_BEGIN: /* we're in the begin round, so requests for the exchange round may * come in, they will be delayed for now! */ case CONSENSUS_ROUND_EXCHANGE: cmp = rounds_compare (session, &round_info); if (cmp > 0) { /* the other peer is too late */ LOG_PP (GNUNET_ERROR_TYPE_DEBUG, cpi, "too late for the current round\n"); return; } /* kill old request, if any. this is legal, * as the other peer would not make a new request if it would want to * complete the old one! */ if (NULL != cpi->set_op) { LOG_PP (GNUNET_ERROR_TYPE_INFO, cpi, "got new request from same peer, canceling old one\n"); GNUNET_SET_operation_cancel (cpi->set_op); cpi->set_op = NULL; } set_op = GNUNET_SET_accept (request, GNUNET_SET_RESULT_ADDED, set_result_cb, &session->info[index]); if (cmp == 0) { /* we're in exactly the right round for the incoming request */ if (cpi != cpi->session->partner_incoming) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "P%u: got request from %u (with matching round), " "but incoming partner is %d\n", cpi->session->local_peer_idx, cpi - cpi->session->info, ((NULL == cpi->session->partner_incoming) ? -1 : (cpi->session->partner_incoming - cpi->session->info))); GNUNET_SET_operation_cancel (set_op); return; } cpi->set_op = set_op; if (GNUNET_OK != GNUNET_SET_commit (set_op, session->element_set)) { GNUNET_break (0); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d commited to set request from P%d\n", session->local_peer_idx, index); } else { /* we still have wait until we have finished the current round, * as the other peer's round is larger */ cpi->delayed_set_op = set_op; cpi->delayed_round_info = round_info; /* The current setop is finished, as we canceled the current setop above. */ cpi->set_op_finished = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%d delaying set request from P%d\n", session->local_peer_idx, index); } break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "P%d got unexpected set request in round %d from P%d\n", session->local_peer_idx, session->current_round, index); GNUNET_break_op (0); return; } } /** * Initialize the session, continue receiving messages from the owning client * * @param session the session to initialize * @param join_msg the join message from the client */ static void initialize_session (struct ConsensusSession *session, struct GNUNET_CONSENSUS_JoinMessage *join_msg) { struct ConsensusSession *other_session; initialize_session_peer_list (session, join_msg); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "session with %u peers\n", session->num_peers); compute_global_id (session, &join_msg->session_id); /* check if some local client already owns the session. * it is only legal to have a session with an existing global id * if all other sessions with this global id are finished.*/ other_session = sessions_head; while (NULL != other_session) { if ((other_session != session) && (0 == GNUNET_CRYPTO_hash_cmp (&session->global_id, &other_session->global_id))) { if (CONSENSUS_ROUND_FINISH != other_session->current_round) { GNUNET_break (0); destroy_session (session); return; } break; } other_session = other_session->next; } session->conclude_deadline = GNUNET_TIME_absolute_ntoh (join_msg->deadline); session->conclude_start = GNUNET_TIME_absolute_ntoh (join_msg->start); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "consensus with timeout %ums created\n", (GNUNET_TIME_absolute_get_difference (session->conclude_start, session->conclude_deadline)).rel_value_us / 1000); session->local_peer_idx = get_peer_idx (&my_peer, session); GNUNET_assert (-1 != session->local_peer_idx); session->element_set = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); GNUNET_assert (NULL != session->element_set); session->set_listener = GNUNET_SET_listen (cfg, GNUNET_SET_OPERATION_UNION, &session->global_id, set_listen_cb, session); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%d is the local peer\n", session->local_peer_idx); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "session %s initialized\n", GNUNET_h2s (&session->global_id)); } static struct ConsensusSession * get_session_by_client (struct GNUNET_SERVER_Client *client) { struct ConsensusSession *session; session = sessions_head; while (NULL != session) { if (session->client == client) return session; session = session->next; } return NULL; } /** * Called when a client wants to join a consensus session. * * @param cls unused * @param client client that sent the message * @param m message sent by the client */ static void client_join (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { struct ConsensusSession *session; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "join message sent by client\n"); session = get_session_by_client (client); if (NULL != session) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } session = GNUNET_new (struct ConsensusSession); session->client = client; session->client_mq = GNUNET_MQ_queue_for_server_client (client); GNUNET_CONTAINER_DLL_insert (sessions_head, sessions_tail, session); initialize_session (session, (struct GNUNET_CONSENSUS_JoinMessage *) m); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "join done\n"); } /** * Called when a client performs an insert operation. * * @param cls (unused) * @param client client handle * @param m message sent by the client */ void client_insert (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *m) { struct ConsensusSession *session; struct GNUNET_CONSENSUS_ElementMessage *msg; struct GNUNET_SET_Element *element; ssize_t element_size; session = get_session_by_client (client); if (NULL == session) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } if (CONSENSUS_ROUND_BEGIN != session->current_round) { GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } msg = (struct GNUNET_CONSENSUS_ElementMessage *) m; element_size = ntohs (msg->header.size) - sizeof (struct GNUNET_CONSENSUS_ElementMessage); if (element_size < 0) { GNUNET_break (0); return; } element = GNUNET_malloc (sizeof (struct GNUNET_SET_Element) + element_size); element->type = msg->element_type; element->size = element_size; memcpy (&element[1], &msg[1], element_size); element->data = &element[1]; GNUNET_SET_add_element (session->element_set, element, NULL, NULL); GNUNET_free (element); GNUNET_SERVER_receive_done (client, GNUNET_OK); // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "P%u: element added\n", session->local_peer_idx); } /** * Called when a client performs the conclude operation. * * @param cls (unused) * @param client client handle * @param message message sent by the client */ static void client_conclude (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct ConsensusSession *session; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "conclude requested\n"); session = get_session_by_client (client); if (NULL == session) { /* client not found */ GNUNET_break (0); GNUNET_SERVER_client_disconnect (client); return; } if (CONSENSUS_ROUND_BEGIN != session->current_round) { /* client requested conclude twice */ GNUNET_break (0); return; } if (session->num_peers <= 1) { session->current_round = CONSENSUS_ROUND_FINISH; GNUNET_SET_iterate (session->element_set, send_to_client_iter, session); } else { /* the 'begin' round is over, start with the next, actual round */ round_over (session, NULL); } GNUNET_assert (CONSENSUS_ROUND_BEGIN != session->current_round); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Called to clean up, after a shutdown has been requested. * * @param cls closure * @param tc context information (why was this task triggered now) */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { while (NULL != sessions_head) destroy_session (sessions_head); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handled shutdown request\n"); } /** * Clean up after a client after it is * disconnected (either by us or by itself) * * @param cls closure, unused * @param client the client to clean up after */ void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ConsensusSession *session; session = get_session_by_client (client); if (NULL == session) return; if ((CONSENSUS_ROUND_BEGIN == session->current_round) || (CONSENSUS_ROUND_FINISH == session->current_round)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected, destroying session\n"); destroy_session (session); } else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected, but waiting for consensus to finish\n"); } /** * Start processing consensus requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { {&client_conclude, NULL, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_CONCLUDE, sizeof (struct GNUNET_MessageHeader)}, {&client_insert, NULL, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_INSERT, 0}, {&client_join, NULL, GNUNET_MESSAGE_TYPE_CONSENSUS_CLIENT_JOIN, 0}, {NULL, NULL, 0, 0} }; cfg = c; srv = server; if (GNUNET_OK != GNUNET_CRYPTO_get_peer_identity (cfg, &my_peer)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "could not retrieve host identity\n"); GNUNET_break (0); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_SERVER_add_handlers (server, server_handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); GNUNET_SERVER_disconnect_notify (server, handle_client_disconnect, NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "consensus running\n"); } /** * The main function for the consensus service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; ret = GNUNET_SERVICE_run (argc, argv, "consensus", GNUNET_SERVICE_OPTION_NONE, &run, NULL); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "exit (%d)\n", GNUNET_OK != ret); return (GNUNET_OK == ret) ? 0 : 1; } gnunet-0.10.1/src/peerinfo-tool/0000755000175000017500000000000012320755625013452 500000000000000gnunet-0.10.1/src/peerinfo-tool/gnunet-peerinfo_plugins.h0000644000175000017500000000302412225777503020413 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo-tool/gnunet-peerinfo_plugins.h * @brief plugin management API * @author Christian Grothoff */ #ifndef GNUNET_PEERINFO_PLUGINS_H #define GNUNET_PEERINFO_PLUGINS_H #include "gnunet_util_lib.h" /** * Load transport plugins. * * @param cfg configuration to use */ void GPI_plugins_load (const struct GNUNET_CONFIGURATION_Handle *cfg); /** * Unload all plugins */ void GPI_plugins_unload (void); /** * Obtain the plugin API based on a plugin name. * * @param name name of the plugin * @return the plugin's API, NULL if the plugin is not loaded */ struct GNUNET_TRANSPORT_PluginFunctions * GPI_plugins_find (const char *name); #endif /* end of file gnunet-peerinfo_plugins.h */ gnunet-0.10.1/src/peerinfo-tool/test_gnunet_peerinfo_data.conf0000644000175000017500000000060112225230043021437 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-peerinfo/ [gnunetd] #HOSTKEY = test_gnunet_peerinfo.hostkey [peerinfo] PORT = 24354 [resolver] PORT = 24355 [arm] DEFAULTSERVICES = [testing] WEAKRANDOM = YES [transport] plugins = tcp PORT = 24356 [transport-tcp] PORT = 24357 [dns] AUTOSTART = NO [mesh] AUTOSTART = NO [nse] AUTOSTART = NO [nat] RETURN_LOCAL_ADDRESSES = YES gnunet-0.10.1/src/peerinfo-tool/Makefile.in0000644000175000017500000011111412320752063015427 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-peerinfo$(EXEEXT) subdir = src/peerinfo-tool DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_gnunet_peerinfo_OBJECTS = gnunet-peerinfo.$(OBJEXT) \ gnunet-peerinfo_plugins.$(OBJEXT) gnunet_peerinfo_OBJECTS = $(am_gnunet_peerinfo_OBJECTS) gnunet_peerinfo_DEPENDENCIES = \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gnunet_peerinfo_SOURCES) DIST_SOURCES = $(gnunet_peerinfo_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov gnunet_peerinfo_SOURCES = \ gnunet-peerinfo.c \ gnunet-peerinfo_plugins.c gnunet-peerinfo_plugins.h gnunet_peerinfo_LDADD = \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la @HAVE_PYTHON_TRUE@check_SCRIPTS = \ @HAVE_PYTHON_TRUE@ test_gnunet_peerinfo.py @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_SCRIPTS) do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' EXTRA_DIST = \ test_gnunet_peerinfo.py.in \ test_gnunet_peerinfo_data.conf CLEANFILES = $(check_SCRIPTS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/peerinfo-tool/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/peerinfo-tool/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-peerinfo$(EXEEXT): $(gnunet_peerinfo_OBJECTS) $(gnunet_peerinfo_DEPENDENCIES) $(EXTRA_gnunet_peerinfo_DEPENDENCIES) @rm -f gnunet-peerinfo$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_peerinfo_OBJECTS) $(gnunet_peerinfo_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-peerinfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-peerinfo_plugins.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_gnunet_peerinfo.py.log: test_gnunet_peerinfo.py @p='test_gnunet_peerinfo.py'; \ b='test_gnunet_peerinfo.py'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS test_gnunet_peerinfo.py: test_gnunet_peerinfo.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_peerinfo.py.in > test_gnunet_peerinfo.py chmod +x test_gnunet_peerinfo.py # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/peerinfo-tool/gnunet-peerinfo.c0000644000175000017500000004672612272425070016654 00000000000000/* This file is part of GNUnet. (C) 2001-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo-tool/gnunet-peerinfo.c * @brief Print information about other known peers. * @author Christian Grothoff */ #include "platform.h" #include "gnunet_crypto_lib.h" #include "gnunet_configuration_lib.h" #include "gnunet_getopt_lib.h" #include "gnunet_program_lib.h" #include "gnunet_hello_lib.h" #include "gnunet_transport_service.h" #include "gnunet_peerinfo_service.h" #include "gnunet-peerinfo_plugins.h" /** * How long until we time out during peerinfo iterations? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Structure we use to collect printable address information. */ struct PrintContext; /** * Record we keep for each printable address. */ struct AddressRecord { /** * Current address-to-string context (if active, otherwise NULL). */ struct GNUNET_TRANSPORT_AddressToStringContext *atsc; /** * Address expiration time */ struct GNUNET_TIME_Absolute expiration; /** * Printable address. */ char *result; /** * Print context this address record belongs to. */ struct PrintContext *pc; }; /** * Structure we use to collect printable address information. */ struct PrintContext { /** * Kept in DLL. */ struct PrintContext *next; /** * Kept in DLL. */ struct PrintContext *prev; /** * Identity of the peer. */ struct GNUNET_PeerIdentity peer; /** * List of printable addresses. */ struct AddressRecord *address_list; /** * Number of completed addresses in 'address_list'. */ unsigned int num_addresses; /** * Number of addresses allocated in 'address_list'. */ unsigned int address_list_size; /** * Current offset in 'address_list' (counted down). */ unsigned int off; /** * Hello was friend only, GNUNET_YES or GNUNET_NO */ int friend_only; }; /** * Option '-n' */ static int no_resolve; /** * Option '-q' */ static int be_quiet; /** * Option '-f' */ static int include_friend_only; /** * Option '-s' */ static int get_self; /** * Option */ static int get_uri; /** * Option */ static int default_operation; /** * Option '-i' */ static int get_info; /** * Option */ static char *put_uri; /** * Option -d */ static char *dump_hello; /** * Handle to peerinfo service. */ static struct GNUNET_PEERINFO_Handle *peerinfo; /** * Configuration handle. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Main state machine task (if active). */ static GNUNET_SCHEDULER_TaskIdentifier tt; /** * Current iterator context (if active, otherwise NULL). */ static struct GNUNET_PEERINFO_IteratorContext *pic; /** * My peer identity. */ static struct GNUNET_PeerIdentity my_peer_identity; /** * Head of list of print contexts. */ static struct PrintContext *pc_head; /** * Tail of list of print contexts. */ static struct PrintContext *pc_tail; /** * Handle to current 'GNUNET_PEERINFO_add_peer' operation. */ static struct GNUNET_PEERINFO_AddContext *ac; /** * Main state machine that goes over all options and * runs the next requested function. * * @param cls unused * @param tc unused */ static void state_machine (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /* ********************* 'get_info' ******************* */ /** * Print the collected address information to the console and free 'pc'. * * @param pc printing context */ static void dump_pc (struct PrintContext *pc) { unsigned int i; printf (_("%sPeer `%s'\n"), (GNUNET_YES == pc->friend_only) ? "F2F: " : "", GNUNET_i2s_full (&pc->peer)); for (i = 0; i < pc->num_addresses; i++) { if (NULL != pc->address_list[i].result) { printf (_("\tExpires: %s \t %s\n"), GNUNET_STRINGS_absolute_time_to_string(pc->address_list[i].expiration), pc->address_list[i].result); GNUNET_free (pc->address_list[i].result); } } printf ("\n"); GNUNET_free_non_null (pc->address_list); GNUNET_CONTAINER_DLL_remove (pc_head, pc_tail, pc); GNUNET_free (pc); if ( (NULL == pc_head) && (NULL == pic) ) tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); } /* ************************* list all known addresses **************** */ /** * Function to call with a human-readable format of an address * * @param cls closure * @param address NULL on error, otherwise 0-terminated printable UTF-8 string */ static void process_resolved_address (void *cls, const char *address) { struct AddressRecord * ar = cls; struct PrintContext *pc = ar->pc; if (NULL != address) { if (NULL == ar->result) ar->result = GNUNET_strdup (address); return; } ar->atsc = NULL; pc->num_addresses++; if (pc->num_addresses == pc->address_list_size) dump_pc (pc); } /** * Iterator callback to go over all addresses and count them. * * @param cls 'struct PrintContext' with 'off' to increment * @param address the address * @param expiration expiration time * @return GNUNET_OK to keep the address and continue */ static int count_address (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct PrintContext *pc = cls; pc->off++; return GNUNET_OK; } /** * Iterator callback to go over all addresses. * * @param cls closure * @param address the address * @param expiration expiration time * @return GNUNET_OK to keep the address and continue */ static int print_address (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { struct PrintContext *pc = cls; struct AddressRecord *ar; GNUNET_assert (0 < pc->off); ar = &pc->address_list[--pc->off]; ar->pc = pc; ar->expiration = expiration; ar->atsc = GNUNET_TRANSPORT_address_to_string (cfg, address, no_resolve, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), &process_resolved_address, ar); return GNUNET_OK; } /** * Print information about the peer. * Currently prints the GNUNET_PeerIdentity and the transport address. * * @param cls the 'struct PrintContext' * @param peer identity of the peer * @param hello addresses of the peer * @param err_msg error message */ static void print_peer_info (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { struct PrintContext *pc; int friend_only; if (NULL == peer) { pic = NULL; /* end of iteration */ if (NULL != err_msg) { FPRINTF (stderr, _("Error in communication with PEERINFO service: %s\n"), err_msg); } if (NULL == pc_head) tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); return; } friend_only = GNUNET_NO; if (NULL != hello) friend_only = GNUNET_HELLO_is_friend_only (hello); if ((GNUNET_YES == be_quiet) || (NULL == hello)) { printf ("%s%s\n", (GNUNET_YES == friend_only) ? "F2F: " : "", GNUNET_i2s_full (peer)); return; } pc = GNUNET_new (struct PrintContext); GNUNET_CONTAINER_DLL_insert (pc_head, pc_tail, pc); pc->peer = *peer; pc->friend_only = friend_only; GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &count_address, pc); if (0 == pc->off) { dump_pc (pc); return; } pc->address_list_size = pc->off; pc->address_list = GNUNET_malloc (sizeof (struct AddressRecord) * pc->off); GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &print_address, pc); } /* ************************* DUMP Hello ************************** */ static int count_addr(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration) { int *c = cls; (*c) ++; return GNUNET_OK; } /** * Write Hello of my peer to a file. * * @param cls the 'struct GetUriContext' * @param peer identity of the peer (unused) * @param hello addresses of the peer * @param err_msg error message */ static void dump_my_hello (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { unsigned int size; unsigned int c_addr; if (peer == NULL) { pic = NULL; if (err_msg != NULL) FPRINTF (stderr, _("Error in communication with PEERINFO service: %s\n"), err_msg); tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); return; } if (NULL == hello) { FPRINTF (stderr, _("Failure: Did not receive %s\n"), "HELLO"); return; } size = GNUNET_HELLO_size (hello); if (0 == size) { FPRINTF (stderr, _("Failure: Received invalid %s\n"), "HELLO"); return; } if (GNUNET_SYSERR == GNUNET_DISK_fn_write (dump_hello, hello, size, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ)) { FPRINTF (stderr, _("Failed to write HELLO with %u bytes to file `%s'\n"), size, dump_hello); if (0 != UNLINK (dump_hello)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "unlink", dump_hello); } c_addr = 0; GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, count_addr, &c_addr); if (!be_quiet) { FPRINTF (stderr, _("Wrote %s HELLO containing %u addresses with %u bytes to file `%s'\n"), (GNUNET_YES == GNUNET_HELLO_is_friend_only(hello)) ? "friend-only": "public", c_addr, size, dump_hello); } GNUNET_free (dump_hello); dump_hello = NULL; } /* ************************* GET URI ************************** */ /** * Print URI of the peer. * * @param cls the 'struct GetUriContext' * @param peer identity of the peer (unused) * @param hello addresses of the peer * @param err_msg error message */ static void print_my_uri (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg) { if (peer == NULL) { pic = NULL; if (err_msg != NULL) FPRINTF (stderr, _("Error in communication with PEERINFO service: %s\n"), err_msg); tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); return; } if (NULL == hello) return; char *uri = GNUNET_HELLO_compose_uri(hello, &GPI_plugins_find); if (NULL != uri) { printf ("%s\n", (const char *) uri); GNUNET_free (uri); } } /* ************************* import HELLO by URI ********************* */ /** * Continuation called from 'GNUNET_PEERINFO_add_peer' * * @param cls closure, NULL * @param emsg error message, NULL on success */ static void add_continuation (void *cls, const char *emsg) { ac = NULL; if (NULL != emsg) fprintf (stderr, _("Failure adding HELLO: %s\n"), emsg); tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); } /** * Parse the PUT URI given at the command line and add it to our peerinfo * database. * * @param put_uri URI string to parse * @return GNUNET_OK on success, GNUNET_SYSERR if the URI was invalid, GNUNET_NO on other errors */ static int parse_hello_uri (const char *put_uri) { struct GNUNET_HELLO_Message *hello = NULL; int ret = GNUNET_HELLO_parse_uri(put_uri, &my_peer_identity.public_key, &hello, &GPI_plugins_find); if (NULL != hello) { /* WARNING: this adds the address from URI WITHOUT verification! */ if (GNUNET_OK == ret) ac = GNUNET_PEERINFO_add_peer (peerinfo, hello, &add_continuation, NULL); else tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); GNUNET_free (hello); } /* wait 1s to give peerinfo operation a chance to succeed */ /* FIXME: current peerinfo API sucks to require this; not to mention that we get no feedback to determine if the operation actually succeeded */ return ret; } /* ************************ Main state machine ********************* */ /** * Main state machine that goes over all options and * runs the next requested function. * * @param cls unused * @param tc scheduler context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PrintContext *pc; struct AddressRecord *ar; unsigned int i; if (NULL != ac) { GNUNET_PEERINFO_add_peer_cancel (ac); ac = NULL; } if (GNUNET_SCHEDULER_NO_TASK != tt) { GNUNET_SCHEDULER_cancel (tt); tt = GNUNET_SCHEDULER_NO_TASK; } if (NULL != pic) { GNUNET_PEERINFO_iterate_cancel (pic); pic = NULL; } while (NULL != (pc = pc_head)) { GNUNET_CONTAINER_DLL_remove (pc_head, pc_tail, pc); for (i=0;iaddress_list_size;i++) { ar = &pc->address_list[i]; GNUNET_free_non_null (ar->result); if (NULL != ar->atsc) { GNUNET_TRANSPORT_address_to_string_cancel (ar->atsc); ar->atsc = NULL; } } GNUNET_free_non_null (pc->address_list); GNUNET_free (pc); } GPI_plugins_unload (); if (NULL != peerinfo) { GNUNET_PEERINFO_disconnect (peerinfo); peerinfo = NULL; } } /** * Function called with the result of the check if the 'peerinfo' * service is running. * * @param cls closure with our configuration * @param result #GNUNET_YES if transport is running */ static void testservice_task (void *cls, int result) { struct GNUNET_CRYPTO_EddsaPrivateKey *priv; char *fn; if (GNUNET_YES != result) { FPRINTF (stderr, _("Service `%s' is not running, please start GNUnet\n"), "peerinfo"); return; } if (NULL == (peerinfo = GNUNET_PEERINFO_connect (cfg))) { FPRINTF (stderr, "%s", _("Could not access PEERINFO service. Exiting.\n")); return; } if ( (GNUNET_YES == get_self) || (GNUNET_YES == get_uri) || (NULL != dump_hello) ) { /* load private key */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "PEER", "PRIVATE_KEY"); return; } if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_file (fn))) { FPRINTF (stderr, _("Loading hostkey from `%s' failed.\n"), fn); GNUNET_free (fn); return; } GNUNET_free (fn); GNUNET_CRYPTO_eddsa_key_get_public (priv, &my_peer_identity.public_key); GNUNET_free (priv); } tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param c configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { cfg = c; if ( (NULL != args[0]) && (NULL == put_uri) && (args[0] == strcasestr (args[0], "gnunet://hello/")) ) { put_uri = GNUNET_strdup (args[0]); args++; } if (NULL != args[0]) { FPRINTF (stderr, _("Invalid command line argument `%s'\n"), args[0]); return; } GNUNET_CLIENT_service_test ("peerinfo", cfg, GNUNET_TIME_UNIT_SECONDS, &testservice_task, (void *) cfg); } /** * Main state machine that goes over all options and * runs the next requested function. * * @param cls unused * @param tc scheduler context */ static void state_machine (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { tt = GNUNET_SCHEDULER_NO_TASK; if (NULL != put_uri) { GPI_plugins_load (cfg); if (GNUNET_SYSERR == parse_hello_uri (put_uri)) { fprintf (stderr, _("Invalid URI `%s'\n"), put_uri); GNUNET_SCHEDULER_shutdown (); } GNUNET_free (put_uri); put_uri = NULL; } else if (GNUNET_YES == get_info) { get_info = GNUNET_NO; GPI_plugins_load (cfg); pic = GNUNET_PEERINFO_iterate (peerinfo, include_friend_only, NULL, TIMEOUT, &print_peer_info, NULL); } else if (GNUNET_YES == get_self) { get_self = GNUNET_NO; if (be_quiet) printf ("%s\n", GNUNET_i2s_full (&my_peer_identity)); else printf (_("I am peer `%s'.\n"), GNUNET_i2s_full (&my_peer_identity)); tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); } else if (GNUNET_YES == get_uri) { GPI_plugins_load (cfg); pic = GNUNET_PEERINFO_iterate (peerinfo, include_friend_only, &my_peer_identity, TIMEOUT, &print_my_uri, NULL); get_uri = GNUNET_NO; } else if (NULL != dump_hello) { pic = GNUNET_PEERINFO_iterate (peerinfo, include_friend_only, &my_peer_identity, TIMEOUT, &dump_my_hello, NULL); } else if (GNUNET_YES == default_operation) { /* default operation list all */ default_operation = GNUNET_NO; get_info = GNUNET_YES; tt = GNUNET_SCHEDULER_add_now (&state_machine, NULL); } else { GNUNET_SCHEDULER_shutdown (); } default_operation = GNUNET_NO; } /** * The main function to obtain peer information. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { default_operation = GNUNET_YES; static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'n', "numeric", NULL, gettext_noop ("don't resolve host names"), 0, &GNUNET_GETOPT_set_one, &no_resolve}, {'q', "quiet", NULL, gettext_noop ("output only the identity strings"), 0, &GNUNET_GETOPT_set_one, &be_quiet}, {'f', "friends", NULL, gettext_noop ("include friend-only information"), 0, &GNUNET_GETOPT_set_one, &include_friend_only}, {'s', "self", NULL, gettext_noop ("output our own identity only"), 0, &GNUNET_GETOPT_set_one, &get_self}, {'i', "info", NULL, gettext_noop ("list all known peers"), 0, &GNUNET_GETOPT_set_one, &get_info}, {'d', "dump-hello", NULL, gettext_noop ("dump hello to file"), 1, &GNUNET_GETOPT_set_string, &dump_hello}, {'g', "get-hello", NULL, gettext_noop ("also output HELLO uri(s)"), 0, &GNUNET_GETOPT_set_one, &get_uri}, {'p', "put-hello", "HELLO", gettext_noop ("add given HELLO uri to the database"), 1, &GNUNET_GETOPT_set_string, &put_uri}, GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-peerinfo", gettext_noop ("Print information about peers."), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-peerinfo.c */ gnunet-0.10.1/src/peerinfo-tool/gnunet-peerinfo_plugins.c0000644000175000017500000001173312255010512020373 00000000000000/* This file is part of GNUnet. (C) 2010,2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file peerinfo-tool/gnunet-peerinfo_plugins.c * @brief plugin management * @author Christian Grothoff */ #include "platform.h" #include "gnunet-peerinfo_plugins.h" #include "gnunet_transport_plugin.h" #include "gnunet_hello_lib.h" /** * Entry in doubly-linked list of all of our plugins. */ struct TransportPlugin { /** * This is a doubly-linked list. */ struct TransportPlugin *next; /** * This is a doubly-linked list. */ struct TransportPlugin *prev; /** * API of the transport as returned by the plugin's * initialization function. */ struct GNUNET_TRANSPORT_PluginFunctions *api; /** * Short name for the plugin (i.e. "tcp"). */ char *short_name; /** * Name of the library (i.e. "gnunet_plugin_transport_tcp"). */ char *lib_name; /** * Environment this transport service is using * for this plugin. */ struct GNUNET_TRANSPORT_PluginEnvironment env; }; /** * Head of DLL of all loaded plugins. */ static struct TransportPlugin *plugins_head; /** * Head of DLL of all loaded plugins. */ static struct TransportPlugin *plugins_tail; /** * Load and initialize all plugins. The respective functions will be * invoked by the plugins when the respective events happen. The * closure will be set to a 'const char*' containing the name of the * plugin that caused the call. * * @param cfg configuration to use */ void GPI_plugins_load (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TransportPlugin *plug; struct TransportPlugin *next; char *libname; char *plugs; char *pos; if (NULL != plugins_head) return; /* already loaded */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "TRANSPORT", "PLUGINS", &plugs)) return; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting transport plugins `%s'\n"), plugs); for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " ")) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' transport plugin\n"), pos); GNUNET_asprintf (&libname, "libgnunet_plugin_transport_%s", pos); plug = GNUNET_new (struct TransportPlugin); plug->short_name = GNUNET_strdup (pos); plug->lib_name = libname; plug->env.cfg = cfg; plug->env.cls = plug->short_name; GNUNET_CONTAINER_DLL_insert (plugins_head, plugins_tail, plug); } GNUNET_free (plugs); next = plugins_head; while (next != NULL) { plug = next; next = plug->next; plug->api = GNUNET_PLUGIN_load (plug->lib_name, &plug->env); if (plug->api == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to load transport plugin for `%s'\n"), plug->lib_name); GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug); GNUNET_free (plug->short_name); GNUNET_free (plug->lib_name); GNUNET_free (plug); } } } /** * Unload all plugins */ void GPI_plugins_unload () { struct TransportPlugin *plug; while (NULL != (plug = plugins_head)) { GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api)); GNUNET_free (plug->lib_name); GNUNET_free (plug->short_name); GNUNET_CONTAINER_DLL_remove (plugins_head, plugins_tail, plug); GNUNET_free (plug); } } /** * Obtain the plugin API based on a plugin name. * * @param name name of the plugin * @return the plugin's API, NULL if the plugin is not loaded */ struct GNUNET_TRANSPORT_PluginFunctions * GPI_plugins_find (const char *name) { struct TransportPlugin *head = plugins_head; char *stripped = GNUNET_strdup (name); char *head_stripped; char *sep = strchr (stripped, '_'); if (NULL != sep) sep[0] = '\0'; while (head != NULL) { head_stripped = GNUNET_strdup(head->short_name); char *head_sep = strchr (head_stripped, '_'); if (NULL != head_sep) head_sep[0] = '\0'; if (0 == strcmp (head_stripped, stripped)) { GNUNET_free (head_stripped); break; } GNUNET_free (head_stripped); head = head->next; } GNUNET_free (stripped); if (NULL == head) return NULL; return head->api; } /* end of file gnunet-peerinfo_plugins.c */ gnunet-0.10.1/src/peerinfo-tool/Makefile.am0000644000175000017500000000237712320751520015425 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols -lole32 -lshell32 -liconv -lstdc++ -lcomdlg32 -lgdi32 endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif bin_PROGRAMS = \ gnunet-peerinfo gnunet_peerinfo_SOURCES = \ gnunet-peerinfo.c \ gnunet-peerinfo_plugins.c gnunet-peerinfo_plugins.h gnunet_peerinfo_LDADD = \ $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ $(top_builddir)/src/nat/libgnunetnat.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la if HAVE_PYTHON check_SCRIPTS = \ test_gnunet_peerinfo.py endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_SCRIPTS) endif do_subst = $(SED) -e 's,[@]PYTHON[@],$(PYTHON),g' test_gnunet_peerinfo.py: test_gnunet_peerinfo.py.in Makefile $(do_subst) < $(srcdir)/test_gnunet_peerinfo.py.in > test_gnunet_peerinfo.py chmod +x test_gnunet_peerinfo.py EXTRA_DIST = \ test_gnunet_peerinfo.py.in \ test_gnunet_peerinfo_data.conf CLEANFILES = $(check_SCRIPTS) gnunet-0.10.1/src/peerinfo-tool/test_gnunet_peerinfo.py.in0000755000175000017500000000774412274707232020615 00000000000000#!@PYTHON@ # This file is part of GNUnet. # (C) 2010 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 3, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # Testcase for gnunet-peerinfo import sys import os import subprocess import re import shutil import time srcdir = "../.." gnunet_pyexpect_dir = os.path.join (srcdir, "contrib") if gnunet_pyexpect_dir not in sys.path: sys.path.append (gnunet_pyexpect_dir) from gnunet_pyexpect import pexpect if os.name == 'posix': peerinfo = './gnunet-peerinfo' gnunetarm = 'gnunet-arm' gnunettesting = 'gnunet-testing' elif os.name == 'nt': peerinfo = './gnunet-peerinfo.exe' gnunetarm = 'gnunet-arm.exe' gnunettesting = 'gnunet-testing.exe' pinfo = pexpect () pinfo.spawn (None, [peerinfo, '-i', '-c', 'test_gnunet_peerinfo_data.conf', '-L', 'ERROR'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pinfo.expect ("stdout", re.compile (r'Service `peerinfo\' is not running, please start GNUnet\r?\n')) pinfo.expect ("stdout", "EOF") if os.name == "nt": shutil.rmtree (os.path.join (os.getenv ("TEMP"), "gnunet-test-peerinfo"), True) else: shutil.rmtree ("/tmp/gnunet-test-peerinfo", True) # create hostkey via testing lib hkk = subprocess.Popen ([gnunettesting, '-n 1', '-k', '/tmp/gnunet-test-peerinfo/.hostkey']) hkk.communicate () arm = subprocess.Popen ([gnunetarm, '-sq', '-c', 'test_gnunet_peerinfo_data.conf']) arm.communicate () try: pinfo.spawn (None, [peerinfo, '-c', 'test_gnunet_peerinfo_data.conf', '-s'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pinfo.expect ("stdout", re.compile (r'I am peer `.*\'.\r?\n')) pinfo.spawn (None, [peerinfo, '-c', 'test_gnunet_peerinfo_data.conf', '-qs'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pinfo.expect ("stdout", re.compile (r'....................................................\r?\n')) pinfo.spawn (None, [peerinfo, '-c', 'test_gnunet_peerinfo_data.conf', 'invalid'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pinfo.expect ("stdout", re.compile (r'Invalid command line argument `invalid\'\r?\n')) arm = subprocess.Popen ([gnunetarm, '-q', '-i', 'transport', '-c', 'test_gnunet_peerinfo_data.conf']) arm.communicate () time.sleep (1) pinfo.spawn (None, [peerinfo, '-i', '-c', 'test_gnunet_peerinfo_data.conf'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pinfo.expect ("stdout", re.compile ("Peer `.*'\r?\n")) m = pinfo.expect ("stdout", re.compile ("\s.*:24357\r?\n")) while len (m.group (0)) > 0: m = pinfo.expect ("stdout", re.compile ("(\s.*:24357\r?\n|\r?\n|)")) pinfo.spawn (None, [peerinfo, '-i', '-c', 'test_gnunet_peerinfo_data.conf', '-n'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pinfo.expect ("stdout", re.compile ("Peer `.*'\r?\n")) m = pinfo.expect ("stdout", re.compile ("\s.*:24357\r?\n")) while len (m.group (0)) > 0: m = pinfo.expect ("stdout", re.compile ("(\s.*:24357\r?\n|\r?\n|)")) pinfo.spawn (None, [peerinfo, '-c', 'test_gnunet_peerinfo_data.conf', '-qs'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) pid = pinfo.read ("stdout") pid.strip () finally: arm = subprocess.Popen ([gnunetarm, '-eq', '-c', 'test_gnunet_peerinfo_data.conf']) arm.communicate () if os.name == "nt": shutil.rmtree (os.path.join (os.getenv ("TEMP"), "gnunet-test-peerinfo"), True) else: shutil.rmtree ("/tmp/gnunet-test-peerinfo", True) gnunet-0.10.1/src/datastore/0000755000175000017500000000000012320755623012654 500000000000000gnunet-0.10.1/src/datastore/test_plugin_datastore_data_mysql.conf0000644000175000017500000000025112225230043022246 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-datastore-plugin-mysql/ [datastore] DATABASE = mysql [datastore-mysql] DATABASE = gnunetcheck gnunet-0.10.1/src/datastore/perf_plugin_datastore_data_mysql.conf0000644000175000017500000000024212225230043022223 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/perf-gnunet-datastore-mysql/ [datastore] DATABASE = mysql [datastore-mysql] DATABASE = gnunetcheck gnunet-0.10.1/src/datastore/plugin_datastore_sqlite.c0000644000175000017500000011732312320724262017667 00000000000000 /* * This file is part of GNUnet * (C) 2009, 2011 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file datastore/plugin_datastore_sqlite.c * @brief sqlite-based datastore backend * @author Christian Grothoff */ #include "platform.h" #include "gnunet_datastore_plugin.h" #include /** * We allocate items on the stack at times. To prevent a stack * overflow, we impose a limit on the maximum size for the data per * item. 64k should be enough. */ #define MAX_ITEM_SIZE 65536 /** * After how many ms "busy" should a DB operation fail for good? * A low value makes sure that we are more responsive to requests * (especially PUTs). A high value guarantees a higher success * rate (SELECTs in iterate can take several seconds despite LIMIT=1). * * The default value of 250ms should ensure that users do not experience * huge latencies while at the same time allowing operations to succeed * with reasonable probability. */ #define BUSY_TIMEOUT_MS 250 /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' on file 'filename' * with the message given by strerror(errno). */ #define LOG_SQLITE(db, msg, level, cmd) do { GNUNET_log_from (level, "sqlite", _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); if (msg != NULL) GNUNET_asprintf(msg, _("`%s' failed at %s:%u with error: %s"), cmd, __FILE__, __LINE__, sqlite3_errmsg(db->dbh)); } while(0) /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATASTORE_PluginEnvironment *env; /** * Database filename. */ char *fn; /** * Native SQLite database handle. */ sqlite3 *dbh; /** * Precompiled SQL for deletion. */ sqlite3_stmt *delRow; /** * Precompiled SQL for update. */ sqlite3_stmt *updPrio; /** * Get maximum repl value in database. */ sqlite3_stmt *maxRepl; /** * Precompiled SQL for replication decrement. */ sqlite3_stmt *updRepl; /** * Precompiled SQL for replication selection. */ sqlite3_stmt *selRepl; /** * Precompiled SQL for expiration selection. */ sqlite3_stmt *selExpi; /** * Precompiled SQL for expiration selection. */ sqlite3_stmt *selZeroAnon; /** * Precompiled SQL for insertion. */ sqlite3_stmt *insertContent; /** * Should the database be dropped on shutdown? */ int drop_on_shutdown; }; /** * @brief Prepare a SQL statement * * @param dbh handle to the database * @param zSql SQL statement, UTF-8 encoded * @param ppStmt set to the prepared statement * @return 0 on success */ static int sq_prepare (sqlite3 *dbh, const char *zSql, sqlite3_stmt **ppStmt) { char *dummy; int result; result = sqlite3_prepare_v2 (dbh, zSql, strlen (zSql), ppStmt, (const char **) &dummy); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Prepared `%s' / %p: %d\n", zSql, *ppStmt, result); return result; } /** * Create our database indices. * * @param dbh handle to the database */ static void create_indices (sqlite3 * dbh) { /* create indices */ if ((SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_hash ON gn090 (hash)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_hash_vhash ON gn090 (hash,vhash)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_expire_repl ON gn090 (expire ASC,repl DESC)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_comb ON gn090 (anonLevel ASC,expire ASC,prio,type,hash)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_anon_type_hash ON gn090 (anonLevel ASC,type,hash)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_expire ON gn090 (expire ASC)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_repl_rvalue ON gn090 (repl,rvalue)", NULL, NULL, NULL)) || (SQLITE_OK != sqlite3_exec (dbh, "CREATE INDEX IF NOT EXISTS idx_repl ON gn090 (repl DESC)", NULL, NULL, NULL))) GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite", "Failed to create indices: %s\n", sqlite3_errmsg (dbh)); } #if 0 #define CHECK(a) GNUNET_break(a) #define ENULL NULL #else #define ENULL &e #define ENULL_DEFINED 1 #define CHECK(a) if (! a) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", e); sqlite3_free(e); } #endif /** * Initialize the database connections and associated * data structures (create tables and indices * as needed as well). * * @param cfg our configuration * @param plugin the plugin context (state for this module) * @return #GNUNET_OK on success */ static int database_setup (const struct GNUNET_CONFIGURATION_Handle *cfg, struct Plugin *plugin) { sqlite3_stmt *stmt; char *afsdir; #if ENULL_DEFINED char *e; #endif if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "datastore-sqlite", "FILENAME", &afsdir)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "datastore-sqlite", "FILENAME"); return GNUNET_SYSERR; } if (GNUNET_OK != GNUNET_DISK_file_test (afsdir)) { if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir)) { GNUNET_break (0); GNUNET_free (afsdir); return GNUNET_SYSERR; } /* database is new or got deleted, reset payload to zero! */ plugin->env->duc (plugin->env->cls, 0); } /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ plugin->fn = afsdir; /* Open database and precompile statements */ if (sqlite3_open (plugin->fn, &plugin->dbh) != SQLITE_OK) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "sqlite", _("Unable to initialize SQLite: %s.\n"), sqlite3_errmsg (plugin->dbh)); return GNUNET_SYSERR; } CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA temp_store=MEMORY", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA synchronous=OFF", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA legacy_file_format=OFF", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA locking_mode=EXCLUSIVE", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA count_changes=OFF", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA page_size=4092", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_busy_timeout (plugin->dbh, BUSY_TIMEOUT_MS)); /* We have to do it here, because otherwise precompiling SQL might fail */ CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "SELECT 1 FROM sqlite_master WHERE tbl_name = 'gn090'", &stmt)); if ((sqlite3_step (stmt) == SQLITE_DONE) && (sqlite3_exec (plugin->dbh, "CREATE TABLE gn090 (" " repl INT4 NOT NULL DEFAULT 0," " type INT4 NOT NULL DEFAULT 0," " prio INT4 NOT NULL DEFAULT 0," " anonLevel INT4 NOT NULL DEFAULT 0," " expire INT8 NOT NULL DEFAULT 0," " rvalue INT8 NOT NULL," " hash TEXT NOT NULL DEFAULT ''," " vhash TEXT NOT NULL DEFAULT ''," " value BLOB NOT NULL DEFAULT '')", NULL, NULL, NULL) != SQLITE_OK)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_exec"); sqlite3_finalize (stmt); return GNUNET_SYSERR; } sqlite3_finalize (stmt); create_indices (plugin->dbh); if ((sq_prepare (plugin->dbh, "UPDATE gn090 " "SET prio = prio + ?, expire = MAX(expire,?) WHERE _ROWID_ = ?", &plugin->updPrio) != SQLITE_OK) || (sq_prepare (plugin->dbh, "UPDATE gn090 " "SET repl = MAX (0, repl - 1) WHERE _ROWID_ = ?", &plugin->updRepl) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " #if SQLITE_VERSION_NUMBER >= 3007000 "INDEXED BY idx_repl_rvalue " #endif "WHERE repl=?2 AND " " (rvalue>=?1 OR " " NOT EXISTS (SELECT 1 FROM gn090 " #if SQLITE_VERSION_NUMBER >= 3007000 "INDEXED BY idx_repl_rvalue " #endif "WHERE repl=?2 AND rvalue>=?1 LIMIT 1) ) " "ORDER BY rvalue ASC LIMIT 1", &plugin->selRepl) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT MAX(repl) FROM gn090" #if SQLITE_VERSION_NUMBER >= 3007000 " INDEXED BY idx_repl_rvalue" #endif "", &plugin->maxRepl) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " #if SQLITE_VERSION_NUMBER >= 3007000 "INDEXED BY idx_expire " #endif "WHERE NOT EXISTS (SELECT 1 FROM gn090 WHERE expire < ?1 LIMIT 1) OR (expire < ?1) " "ORDER BY expire ASC LIMIT 1", &plugin->selExpi) != SQLITE_OK) || (sq_prepare (plugin->dbh, "SELECT type,prio,anonLevel,expire,hash,value,_ROWID_ " "FROM gn090 " #if SQLITE_VERSION_NUMBER >= 3007000 "INDEXED BY idx_anon_type_hash " #endif "WHERE (anonLevel = 0 AND type=?1) " "ORDER BY hash DESC LIMIT 1 OFFSET ?2", &plugin->selZeroAnon) != SQLITE_OK) || (sq_prepare (plugin->dbh, "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", &plugin->insertContent) != SQLITE_OK) || (sq_prepare (plugin->dbh, "DELETE FROM gn090 WHERE _ROWID_ = ?", &plugin->delRow) != SQLITE_OK)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR, "precompiling"); return GNUNET_SYSERR; } return GNUNET_OK; } /** * Shutdown database connection and associate data * structures. * * @param plugin the plugin context (state for this module) */ static void database_shutdown (struct Plugin *plugin) { int result; #if SQLITE_VERSION_NUMBER >= 3007000 sqlite3_stmt *stmt; #endif if (plugin->delRow != NULL) sqlite3_finalize (plugin->delRow); if (plugin->updPrio != NULL) sqlite3_finalize (plugin->updPrio); if (plugin->updRepl != NULL) sqlite3_finalize (plugin->updRepl); if (plugin->selRepl != NULL) sqlite3_finalize (plugin->selRepl); if (plugin->maxRepl != NULL) sqlite3_finalize (plugin->maxRepl); if (plugin->selExpi != NULL) sqlite3_finalize (plugin->selExpi); if (plugin->selZeroAnon != NULL) sqlite3_finalize (plugin->selZeroAnon); if (plugin->insertContent != NULL) sqlite3_finalize (plugin->insertContent); result = sqlite3_close (plugin->dbh); #if SQLITE_VERSION_NUMBER >= 3007000 if (result == SQLITE_BUSY) { GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", _ ("Tried to close sqlite without finalizing all prepared statements.\n")); stmt = sqlite3_next_stmt (plugin->dbh, NULL); while (stmt != NULL) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Closing statement %p\n", stmt); result = sqlite3_finalize (stmt); if (result != SQLITE_OK) GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", "Failed to close statement %p: %d\n", stmt, result); stmt = sqlite3_next_stmt (plugin->dbh, NULL); } result = sqlite3_close (plugin->dbh); } #endif if (SQLITE_OK != result) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite3_close"); GNUNET_free_non_null (plugin->fn); } /** * Delete the database entry with the given * row identifier. * * @param plugin the plugin context (state for this module) * @param rid the ID of the row to delete */ static int delete_by_rowid (struct Plugin *plugin, unsigned long long rid) { if (SQLITE_OK != sqlite3_bind_int64 (plugin->delRow, 1, rid)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->delRow)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } if (SQLITE_DONE != sqlite3_step (plugin->delRow)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); if (SQLITE_OK != sqlite3_reset (plugin->delRow)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } if (SQLITE_OK != sqlite3_reset (plugin->delRow)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_OK; } /** * Store an item in the datastore. * * @param cls closure * @param key key for the item * @param size number of bytes in @a data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param msg set to an error message * @return #GNUNET_OK on success */ static int sqlite_plugin_put (void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, char **msg) { struct Plugin *plugin = cls; int n; int ret; sqlite3_stmt *stmt; struct GNUNET_HashCode vhash; uint64_t rvalue; if (size > MAX_ITEM_SIZE) return GNUNET_SYSERR; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Storing in database block with type %u/key `%s'/priority %u/expiration in %s (%s).\n", type, GNUNET_h2s (key), priority, (unsigned long long) GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration), GNUNET_YES), GNUNET_STRINGS_absolute_time_to_string (expiration)); GNUNET_CRYPTO_hash (data, size, &vhash); stmt = plugin->insertContent; rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, replication)) || (SQLITE_OK != sqlite3_bind_int (stmt, 2, type)) || (SQLITE_OK != sqlite3_bind_int (stmt, 3, priority)) || (SQLITE_OK != sqlite3_bind_int (stmt, 4, anonymity)) || (SQLITE_OK != sqlite3_bind_int64 (stmt, 5, expiration.abs_value_us)) || (SQLITE_OK != sqlite3_bind_int64 (stmt, 6, rvalue)) || (SQLITE_OK != sqlite3_bind_blob (stmt, 7, key, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT)) || (SQLITE_OK != sqlite3_bind_blob (stmt, 8, &vhash, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT)) || (SQLITE_OK != sqlite3_bind_blob (stmt, 9, data, size, SQLITE_TRANSIENT))) { LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } n = sqlite3_step (stmt); switch (n) { case SQLITE_DONE: plugin->env->duc (plugin->env->cls, size + GNUNET_DATASTORE_ENTRY_OVERHEAD); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Stored new entry (%u bytes)\n", size + GNUNET_DATASTORE_ENTRY_OVERHEAD); ret = GNUNET_OK; break; case SQLITE_BUSY: GNUNET_break (0); LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); ret = GNUNET_SYSERR; break; default: LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); database_shutdown (plugin); database_setup (plugin->env->cfg, plugin); return GNUNET_SYSERR; } if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return ret; } /** * Update the priority for a particular key in the datastore. If * the expiration time in value is different than the time found in * the datastore, the higher value should be kept. For the * anonymity level, the lower value is to be used. The specified * priority should be added to the existing priority, ignoring the * priority in value. * * Note that it is possible for multiple values to match this put. * In that case, all of the respective values are updated. * * @param cls the plugin context (state for this module) * @param uid unique identifier of the datum * @param delta by how much should the priority * change? If priority + delta < 0 the * priority should be set to 0 (never go * negative). * @param expire new expiration time should be the * MAX of any existing expiration time and * this value * @param msg set to an error message * @return #GNUNET_OK on success */ static int sqlite_plugin_update (void *cls, uint64_t uid, int delta, struct GNUNET_TIME_Absolute expire, char **msg) { struct Plugin *plugin = cls; int n; if ((SQLITE_OK != sqlite3_bind_int (plugin->updPrio, 1, delta)) || (SQLITE_OK != sqlite3_bind_int64 (plugin->updPrio, 2, expire.abs_value_us)) || (SQLITE_OK != sqlite3_bind_int64 (plugin->updPrio, 3, uid))) { LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->updPrio)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return GNUNET_SYSERR; } n = sqlite3_step (plugin->updPrio); if (SQLITE_OK != sqlite3_reset (plugin->updPrio)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); switch (n) { case SQLITE_DONE: GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Block updated\n"); return GNUNET_OK; case SQLITE_BUSY: LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return GNUNET_NO; default: LOG_SQLITE (plugin, msg, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); return GNUNET_SYSERR; } } /** * Execute statement that gets a row and call the callback * with the result. Resets the statement afterwards. * * @param plugin the plugin * @param stmt the statement * @param proc processor to call * @param proc_cls closure for @a proc */ static void execute_get (struct Plugin *plugin, sqlite3_stmt *stmt, PluginDatumProcessor proc, void *proc_cls) { int n; struct GNUNET_TIME_Absolute expiration; unsigned long long rowid; unsigned int size; int ret; n = sqlite3_step (stmt); switch (n) { case SQLITE_ROW: size = sqlite3_column_bytes (stmt, 5); rowid = sqlite3_column_int64 (stmt, 6); if (sqlite3_column_bytes (stmt, 4) != sizeof (struct GNUNET_HashCode)) { GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "sqlite", _("Invalid data in database. Trying to fix (by deletion).\n")); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); if (GNUNET_OK == delete_by_rowid (plugin, rowid)) plugin->env->duc (plugin->env->cls, -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); break; } expiration.abs_value_us = sqlite3_column_int64 (stmt, 3); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Found reply in database with expiration %s\n", GNUNET_STRINGS_absolute_time_to_string (expiration)); ret = proc (proc_cls, sqlite3_column_blob (stmt, 4) /* key */ , size, sqlite3_column_blob (stmt, 5) /* data */ , sqlite3_column_int (stmt, 0) /* type */ , sqlite3_column_int (stmt, 1) /* priority */ , sqlite3_column_int (stmt, 2) /* anonymity */ , expiration, rowid); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); if ((GNUNET_NO == ret) && (GNUNET_OK == delete_by_rowid (plugin, rowid))) plugin->env->duc (plugin->env->cls, -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); return; case SQLITE_DONE: /* database must be empty */ if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); break; case SQLITE_BUSY: case SQLITE_ERROR: case SQLITE_MISUSE: default: LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); GNUNET_break (0); database_shutdown (plugin); database_setup (plugin->env->cfg, plugin); break; } if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); } /** * Select a subset of the items in the datastore and call * the given processor for the item. * * @param cls our plugin context * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param type entries of which type should be considered? * Use 0 for any type. * @param proc function to call on each matching value; * will be called once with a NULL value at the end * @param proc_cls closure for @a proc */ static void sqlite_plugin_get_zero_anonymity (void *cls, uint64_t offset, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; GNUNET_assert (type != GNUNET_BLOCK_TYPE_ANY); stmt = plugin->selZeroAnon; if ((SQLITE_OK != sqlite3_bind_int (stmt, 1, type)) || (SQLITE_OK != sqlite3_bind_int64 (stmt, 2, offset))) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } execute_get (plugin, stmt, proc, proc_cls); } /** * Get results for a particular key in the datastore. * * @param cls closure * @param offset offset (mod count). * @param key key to match, never NULL * @param vhash hash of the value, maybe NULL (to * match all values that have the right key). * Note that for DBlocks there is no difference * betwen key and vhash, but for other blocks * there may be! * @param type entries of which type are relevant? * Use 0 for any type. * @param proc function to call on each matching value; * will be called once with a NULL value at the end * @param proc_cls closure for @a proc */ static void sqlite_plugin_get_key (void *cls, uint64_t offset, const struct GNUNET_HashCode *key, const struct GNUNET_HashCode *vhash, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; int ret; int total; int limit_off; unsigned int sqoff; sqlite3_stmt *stmt; char scratch[256]; GNUNET_assert (proc != NULL); GNUNET_assert (key != NULL); GNUNET_snprintf (scratch, sizeof (scratch), "SELECT count(*) FROM gn090 WHERE hash=?%s%s", vhash == NULL ? "" : " AND vhash=?", type == 0 ? "" : " AND type=?"); if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite_prepare"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } sqoff = 1; ret = sqlite3_bind_blob (stmt, sqoff++, key, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT); if ((vhash != NULL) && (ret == SQLITE_OK)) ret = sqlite3_bind_blob (stmt, sqoff++, vhash, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT); if ((type != 0) && (ret == SQLITE_OK)) ret = sqlite3_bind_int (stmt, sqoff++, type); if (SQLITE_OK != ret) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_bind"); sqlite3_finalize (stmt); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } ret = sqlite3_step (stmt); if (ret != SQLITE_ROW) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite_step"); sqlite3_finalize (stmt); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } total = sqlite3_column_int (stmt, 0); sqlite3_finalize (stmt); if (0 == total) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } limit_off = (int) (offset % total); if (limit_off < 0) limit_off += total; GNUNET_snprintf (scratch, sizeof (scratch), "SELECT type, prio, anonLevel, expire, hash, value, _ROWID_ " "FROM gn090 WHERE hash=?%s%s " "ORDER BY _ROWID_ ASC LIMIT 1 OFFSET ?", vhash == NULL ? "" : " AND vhash=?", type == 0 ? "" : " AND type=?"); if (sq_prepare (plugin->dbh, scratch, &stmt) != SQLITE_OK) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite_prepare"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } sqoff = 1; ret = sqlite3_bind_blob (stmt, sqoff++, key, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT); if ((vhash != NULL) && (ret == SQLITE_OK)) ret = sqlite3_bind_blob (stmt, sqoff++, vhash, sizeof (struct GNUNET_HashCode), SQLITE_TRANSIENT); if ((type != 0) && (ret == SQLITE_OK)) ret = sqlite3_bind_int (stmt, sqoff++, type); if (ret == SQLITE_OK) ret = sqlite3_bind_int64 (stmt, sqoff++, limit_off); if (ret != SQLITE_OK) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite_bind"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } execute_get (plugin, stmt, proc, proc_cls); sqlite3_finalize (stmt); } /** * Context for #repl_proc() function. */ struct ReplCtx { /** * Function to call for the result (or the NULL). */ PluginDatumProcessor proc; /** * Closure for @e proc. */ void *proc_cls; /** * UID to use. */ uint64_t uid; /** * Yes if UID was set. */ int have_uid; }; /** * Wrapper for the processor for #sqlite_plugin_get_replication(). * Decrements the replication counter and calls the original * processor. * * @param cls closure * @param key key for the content * @param size number of bytes in @a data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * @return #GNUNET_OK for normal return, * #GNUNET_NO to delete the item */ static int repl_proc (void *cls, const struct GNUNET_HashCode *key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct ReplCtx *rc = cls; int ret; ret = rc->proc (rc->proc_cls, key, size, data, type, priority, anonymity, expiration, uid); if (NULL != key) { rc->uid = uid; rc->have_uid = GNUNET_YES; } return ret; } /** * Get a random item for replication. Returns a single random item * from those with the highest replication counters. The item's * replication counter is decremented by one IF it was positive before. * Call @a proc with all values ZERO or NULL if the datastore is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for @a proc */ static void sqlite_plugin_get_replication (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; struct ReplCtx rc; uint64_t rvalue; uint32_t repl; sqlite3_stmt *stmt; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Getting random block based on replication order.\n"); rc.have_uid = GNUNET_NO; rc.proc = proc; rc.proc_cls = proc_cls; stmt = plugin->maxRepl; if (SQLITE_ROW != sqlite3_step (stmt)) { if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); /* DB empty */ proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } repl = sqlite3_column_int (stmt, 0); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); stmt = plugin->selRepl; rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, rvalue)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } if (SQLITE_OK != sqlite3_bind_int (stmt, 2, repl)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } execute_get (plugin, stmt, &repl_proc, &rc); if (GNUNET_YES == rc.have_uid) { if (SQLITE_OK != sqlite3_bind_int64 (plugin->updRepl, 1, rc.uid)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (plugin->updRepl)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); return; } if (SQLITE_DONE != sqlite3_step (plugin->updRepl)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_step"); if (SQLITE_OK != sqlite3_reset (plugin->updRepl)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); } } /** * Get a random item that has expired or has low priority. * Call @a proc with all values ZERO or NULL if the datastore is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for @a proc */ static void sqlite_plugin_get_expiration (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; struct GNUNET_TIME_Absolute now; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Getting random block based on expiration and priority order.\n"); now = GNUNET_TIME_absolute_get (); stmt = plugin->selExpi; if (SQLITE_OK != sqlite3_bind_int64 (stmt, 1, now.abs_value_us)) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_bind_XXXX"); if (SQLITE_OK != sqlite3_reset (stmt)) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite3_reset"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } execute_get (plugin, stmt, proc, proc_cls); } /** * Get all of the keys in the datastore. * * @param cls closure * @param proc function to call on each key * @param proc_cls closure for @a proc */ static void sqlite_plugin_get_keys (void *cls, PluginKeyProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; const struct GNUNET_HashCode *key; sqlite3_stmt *stmt; int ret; GNUNET_assert (proc != NULL); if (sq_prepare (plugin->dbh, "SELECT hash FROM gn090", &stmt) != SQLITE_OK) { LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "sqlite_prepare"); return; } while (SQLITE_ROW == (ret = sqlite3_step (stmt))) { key = sqlite3_column_blob (stmt, 0); if (sizeof (struct GNUNET_HashCode) == sqlite3_column_bytes (stmt, 0)) proc (proc_cls, key, 1); else GNUNET_break (0); } if (SQLITE_DONE != ret) LOG_SQLITE (plugin, NULL, GNUNET_ERROR_TYPE_ERROR, "sqlite_step"); sqlite3_finalize (stmt); } /** * Drop database. * * @param cls our plugin context */ static void sqlite_plugin_drop (void *cls) { struct Plugin *plugin = cls; plugin->drop_on_shutdown = GNUNET_YES; } /** * Get an estimate of how much space the database is * currently using. * * @param cls the `struct Plugin` * @return the size of the database on disk (estimate) */ static unsigned long long sqlite_plugin_estimate_size (void *cls) { struct Plugin *plugin = cls; sqlite3_stmt *stmt; uint64_t pages; uint64_t page_size; #if ENULL_DEFINED char *e; #endif if (SQLITE_VERSION_NUMBER < 3006000) { GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "datastore-sqlite", _ ("sqlite version to old to determine size, assuming zero\n")); return 0; } CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "VACUUM", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sqlite3_exec (plugin->dbh, "PRAGMA auto_vacuum=INCREMENTAL", NULL, NULL, ENULL)); CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_count", &stmt)); if (SQLITE_ROW == sqlite3_step (stmt)) pages = sqlite3_column_int64 (stmt, 0); else pages = 0; sqlite3_finalize (stmt); CHECK (SQLITE_OK == sq_prepare (plugin->dbh, "PRAGMA page_size", &stmt)); CHECK (SQLITE_ROW == sqlite3_step (stmt)); page_size = sqlite3_column_int64 (stmt, 0); sqlite3_finalize (stmt); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Using sqlite page utilization to estimate payload (%llu pages of size %llu bytes)\n"), (unsigned long long) pages, (unsigned long long) page_size); return pages * page_size; } /** * Entry point for the plugin. * * @param cls the `struct GNUNET_DATASTORE_PluginEnvironment *` * @return NULL on error, othrewise the plugin context */ void * libgnunet_plugin_datastore_sqlite_init (void *cls) { static struct Plugin plugin; struct GNUNET_DATASTORE_PluginEnvironment *env = cls; struct GNUNET_DATASTORE_PluginFunctions *api; if (plugin.env != NULL) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); plugin.env = env; if (GNUNET_OK != database_setup (env->cfg, &plugin)) { database_shutdown (&plugin); return NULL; } api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions); api->cls = &plugin; api->estimate_size = &sqlite_plugin_estimate_size; api->put = &sqlite_plugin_put; api->update = &sqlite_plugin_update; api->get_key = &sqlite_plugin_get_key; api->get_replication = &sqlite_plugin_get_replication; api->get_expiration = &sqlite_plugin_get_expiration; api->get_zero_anonymity = &sqlite_plugin_get_zero_anonymity; api->get_keys = &sqlite_plugin_get_keys; api->drop = &sqlite_plugin_drop; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "sqlite", _("Sqlite database running\n")); return api; } /** * Exit point from the plugin. * * @param cls the plugin context (as returned by "init") * @return always NULL */ void * libgnunet_plugin_datastore_sqlite_done (void *cls) { char *fn; struct GNUNET_DATASTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "sqlite plugin is done\n"); fn = NULL; if (plugin->drop_on_shutdown) fn = GNUNET_strdup (plugin->fn); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "Shutting down database\n"); database_shutdown (plugin); plugin->env = NULL; GNUNET_free (api); if (fn != NULL) { if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); GNUNET_free (fn); } GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "sqlite", "sqlite plugin is finished\n"); return NULL; } /* end of plugin_datastore_sqlite.c */ gnunet-0.10.1/src/datastore/gnunet-service-datastore.c0000644000175000017500000013673612255010512017666 00000000000000/* This file is part of GNUnet (C) 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datastore/gnunet-service-datastore.c * @brief Management for the datastore for files stored on a GNUnet node * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet_datastore_plugin.h" #include "datastore.h" /** * How many messages do we queue at most per client? */ #define MAX_PENDING 1024 /** * How long are we at most keeping "expired" content * past the expiration date in the database? */ #define MAX_EXPIRE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) /** * How fast are we allowed to query the database for deleting * expired content? (1 item per second). */ #define MIN_EXPIRE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) /** * Name under which we store current space consumption. */ static char *quota_stat_name; /** * After how many payload-changing operations * do we sync our statistics? */ #define MAX_STAT_SYNC_LAG 50 /** * Our datastore plugin. */ struct DatastorePlugin { /** * API of the transport as returned by the plugin's * initialization function. */ struct GNUNET_DATASTORE_PluginFunctions *api; /** * Short name for the plugin (i.e. "sqlite"). */ char *short_name; /** * Name of the library (i.e. "gnunet_plugin_datastore_sqlite"). */ char *lib_name; /** * Environment this transport service is using * for this plugin. */ struct GNUNET_DATASTORE_PluginEnvironment env; }; /** * Linked list of active reservations. */ struct ReservationList { /** * This is a linked list. */ struct ReservationList *next; /** * Client that made the reservation. */ struct GNUNET_SERVER_Client *client; /** * Number of bytes (still) reserved. */ uint64_t amount; /** * Number of items (still) reserved. */ uint64_t entries; /** * Reservation identifier. */ int32_t rid; }; /** * Our datastore plugin (NULL if not available). */ static struct DatastorePlugin *plugin; /** * Linked list of space reservations made by clients. */ static struct ReservationList *reservations; /** * Bloomfilter to quickly tell if we don't have the content. */ static struct GNUNET_CONTAINER_BloomFilter *filter; /** * How much space are we allowed to use? */ static unsigned long long quota; /** * Should the database be dropped on exit? */ static int do_drop; /** * Name of our plugin. */ static char *plugin_name; /** * How much space are we using for the cache? (space available for * insertions that will be instantly reclaimed by discarding less * important content --- or possibly whatever we just inserted into * the "cache"). */ static unsigned long long cache_size; /** * How much space have we currently reserved? */ static unsigned long long reserved; /** * How much data are we currently storing * in the database? */ static unsigned long long payload; /** * Number of updates that were made to the * payload value since we last synchronized * it with the statistics service. */ static unsigned int lastSync; /** * Did we get an answer from statistics? */ static int stats_worked; /** * Identity of the task that is used to delete * expired content. */ static GNUNET_SCHEDULER_TaskIdentifier expired_kill_task; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Minimum time that content should have to not be discarded instantly * (time stamp of any content that we've been discarding recently to * stay below the quota). FOREVER if we had to expire content with * non-zero priority. */ static struct GNUNET_TIME_Absolute min_expiration; /** * Handle for reporting statistics. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Synchronize our utilization statistics with the * statistics service. */ static void sync_stats () { GNUNET_STATISTICS_set (stats, quota_stat_name, payload, GNUNET_YES); GNUNET_STATISTICS_set (stats, "# utilization by current datastore", payload, GNUNET_NO); lastSync = 0; } /** * Context for transmitting replies to clients. */ struct TransmitCallbackContext { /** * We keep these in a doubly-linked list (for cleanup). */ struct TransmitCallbackContext *next; /** * We keep these in a doubly-linked list (for cleanup). */ struct TransmitCallbackContext *prev; /** * The message that we're asked to transmit. */ struct GNUNET_MessageHeader *msg; /** * Handle for the transmission request. */ struct GNUNET_SERVER_TransmitHandle *th; /** * Client that we are transmitting to. */ struct GNUNET_SERVER_Client *client; }; /** * Head of the doubly-linked list (for cleanup). */ static struct TransmitCallbackContext *tcc_head; /** * Tail of the doubly-linked list (for cleanup). */ static struct TransmitCallbackContext *tcc_tail; /** * Have we already cleaned up the TCCs and are hence no longer * willing (or able) to transmit anything to anyone? */ static int cleaning_done; /** * Handle for pending get request. */ static struct GNUNET_STATISTICS_GetHandle *stat_get; /** * Task that is used to remove expired entries from * the datastore. This task will schedule itself * again automatically to always delete all expired * content quickly. * * @param cls not used * @param tc task context */ static void delete_expired (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Iterate over the expired items stored in the datastore. * Delete all expired items; once we have processed all * expired items, re-schedule the "delete_expired" task. * * @param cls not used * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue * (continue on call to "next", of course), * GNUNET_NO to delete the item and continue (if supported) */ static int expired_processor (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct GNUNET_TIME_Absolute now; if (key == NULL) { expired_kill_task = GNUNET_SCHEDULER_add_delayed_with_priority (MAX_EXPIRE_DELAY, GNUNET_SCHEDULER_PRIORITY_IDLE, &delete_expired, NULL); return GNUNET_SYSERR; } now = GNUNET_TIME_absolute_get (); if (expiration.abs_value_us > now.abs_value_us) { /* finished processing */ expired_kill_task = GNUNET_SCHEDULER_add_delayed_with_priority (MAX_EXPIRE_DELAY, GNUNET_SCHEDULER_PRIORITY_IDLE, &delete_expired, NULL); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting content `%s' of type %u that expired %s ago\n", GNUNET_h2s (key), type, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (expiration, now), GNUNET_YES)); min_expiration = now; GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes expired"), size, GNUNET_YES); GNUNET_CONTAINER_bloomfilter_remove (filter, key); expired_kill_task = GNUNET_SCHEDULER_add_delayed_with_priority (MIN_EXPIRE_DELAY, GNUNET_SCHEDULER_PRIORITY_IDLE, &delete_expired, NULL); return GNUNET_NO; } /** * Task that is used to remove expired entries from * the datastore. This task will schedule itself * again automatically to always delete all expired * content quickly. * * @param cls not used * @param tc task context */ static void delete_expired (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { expired_kill_task = GNUNET_SCHEDULER_NO_TASK; plugin->api->get_expiration (plugin->api->cls, &expired_processor, NULL); } /** * An iterator over a set of items stored in the datastore * that deletes until we're happy with respect to our quota. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue * (continue on call to "next", of course), * GNUNET_NO to delete the item and continue (if supported) */ static int quota_processor (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { unsigned long long *need = cls; if (NULL == key) return GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting %llu bytes of low-priority (%u) content `%s' of type %u at %s prior to expiration (still trying to free another %llu bytes)\n", (unsigned long long) (size + GNUNET_DATASTORE_ENTRY_OVERHEAD), (unsigned int) priority, GNUNET_h2s (key), type, GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration), GNUNET_YES), *need); if (size + GNUNET_DATASTORE_ENTRY_OVERHEAD > *need) *need = 0; else *need -= size + GNUNET_DATASTORE_ENTRY_OVERHEAD; if (priority > 0) min_expiration = GNUNET_TIME_UNIT_FOREVER_ABS; else min_expiration = expiration; GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes purged (low-priority)"), size, GNUNET_YES); GNUNET_CONTAINER_bloomfilter_remove (filter, key); return GNUNET_NO; } /** * Manage available disk space by running tasks * that will discard content if necessary. This * function will be run whenever a request for * "need" bytes of storage could only be satisfied * by eating into the "cache" (and we want our cache * space back). * * @param need number of bytes of content that were * placed into the "cache" (and hence the * number of bytes that should be removed). */ static void manage_space (unsigned long long need) { unsigned long long last; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked to free up %llu bytes of cache space\n", need); last = 0; while ((need > 0) && (last != need)) { last = need; plugin->api->get_expiration (plugin->api->cls, "a_processor, &need); } } /** * Function called to notify a client about the socket * begin ready to queue more data. "buf" will be * NULL and "size" zero if the socket was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_callback (void *cls, size_t size, void *buf) { struct TransmitCallbackContext *tcc = cls; size_t msize; tcc->th = NULL; GNUNET_CONTAINER_DLL_remove (tcc_head, tcc_tail, tcc); msize = ntohs (tcc->msg->size); if (size == 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Transmission to client failed!\n")); GNUNET_SERVER_receive_done (tcc->client, GNUNET_SYSERR); GNUNET_SERVER_client_drop (tcc->client); GNUNET_free (tcc->msg); GNUNET_free (tcc); return 0; } GNUNET_assert (size >= msize); memcpy (buf, tcc->msg, msize); GNUNET_SERVER_receive_done (tcc->client, GNUNET_OK); GNUNET_SERVER_client_drop (tcc->client); GNUNET_free (tcc->msg); GNUNET_free (tcc); return msize; } /** * Transmit the given message to the client. * * @param client target of the message * @param msg message to transmit, will be freed! */ static void transmit (struct GNUNET_SERVER_Client *client, struct GNUNET_MessageHeader *msg) { struct TransmitCallbackContext *tcc; if (GNUNET_YES == cleaning_done) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Shutdown in progress, aborting transmission.\n")); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_free (msg); return; } tcc = GNUNET_new (struct TransmitCallbackContext); tcc->msg = msg; tcc->client = client; if (NULL == (tcc->th = GNUNET_SERVER_notify_transmit_ready (client, ntohs (msg->size), GNUNET_TIME_UNIT_FOREVER_REL, &transmit_callback, tcc))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); GNUNET_free (msg); GNUNET_free (tcc); return; } GNUNET_SERVER_client_keep (client); GNUNET_CONTAINER_DLL_insert (tcc_head, tcc_tail, tcc); } /** * Transmit a status code to the client. * * @param client receiver of the response * @param code status code * @param msg optional error message (can be NULL) */ static void transmit_status (struct GNUNET_SERVER_Client *client, int code, const char *msg) { struct StatusMessage *sm; size_t slen; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' message with value %d and message `%s'\n", "STATUS", code, msg != NULL ? msg : "(none)"); slen = (msg == NULL) ? 0 : strlen (msg) + 1; sm = GNUNET_malloc (sizeof (struct StatusMessage) + slen); sm->header.size = htons (sizeof (struct StatusMessage) + slen); sm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_STATUS); sm->status = htonl (code); sm->min_expiration = GNUNET_TIME_absolute_hton (min_expiration); if (slen > 0) memcpy (&sm[1], msg, slen); transmit (client, &sm->header); } /** * Function that will transmit the given datastore entry * to the client. * * @param cls closure, pointer to the client (of type GNUNET_SERVER_Client). * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue, * GNUNET_NO to delete the item and continue (if supported) */ static int transmit_item (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct GNUNET_SERVER_Client *client = cls; struct GNUNET_MessageHeader *end; struct DataMessage *dm; if (key == NULL) { /* transmit 'DATA_END' */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' message\n", "DATA_END"); end = GNUNET_new (struct GNUNET_MessageHeader); end->size = htons (sizeof (struct GNUNET_MessageHeader)); end->type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END); transmit (client, end); GNUNET_SERVER_client_drop (client); return GNUNET_OK; } GNUNET_assert (sizeof (struct DataMessage) + size < GNUNET_SERVER_MAX_MESSAGE_SIZE); dm = GNUNET_malloc (sizeof (struct DataMessage) + size); dm->header.size = htons (sizeof (struct DataMessage) + size); dm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_DATA); dm->rid = htonl (0); dm->size = htonl (size); dm->type = htonl (type); dm->priority = htonl (priority); dm->anonymity = htonl (anonymity); dm->replication = htonl (0); dm->reserved = htonl (0); dm->expiration = GNUNET_TIME_absolute_hton (expiration); dm->uid = GNUNET_htonll (uid); dm->key = *key; memcpy (&dm[1], data, size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' message for `%s' of type %u with expiration %s (in: %s)\n", "DATA", GNUNET_h2s (key), type, GNUNET_STRINGS_absolute_time_to_string (expiration), GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration), GNUNET_YES)); GNUNET_STATISTICS_update (stats, gettext_noop ("# results found"), 1, GNUNET_NO); transmit (client, &dm->header); GNUNET_SERVER_client_drop (client); return GNUNET_OK; } /** * Handle RESERVE-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_reserve (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { /** * Static counter to produce reservation identifiers. */ static int reservation_gen; const struct ReserveMessage *msg = (const struct ReserveMessage *) message; struct ReservationList *e; unsigned long long used; unsigned long long req; uint64_t amount; uint32_t entries; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request\n", "RESERVE"); amount = GNUNET_ntohll (msg->amount); entries = ntohl (msg->entries); used = payload + reserved; req = amount + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * entries; if (used + req > quota) { if (quota < used) used = quota; /* cheat a bit for error message (to avoid negative numbers) */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Insufficient space (%llu bytes are available) to satisfy `%s' request for %llu bytes\n"), quota - used, "RESERVE", req); if (cache_size < req) { /* TODO: document this in the FAQ; essentially, if this * message happens, the insertion request could be blocked * by less-important content from migration because it is * larger than 1/8th of the overall available space, and * we only reserve 1/8th for "fresh" insertions */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("The requested amount (%llu bytes) is larger than the cache size (%llu bytes)\n"), req, cache_size); transmit_status (client, 0, gettext_noop ("Insufficient space to satisfy request and " "requested amount is larger than cache size")); } else { transmit_status (client, 0, gettext_noop ("Insufficient space to satisfy request")); } return; } reserved += req; GNUNET_STATISTICS_set (stats, gettext_noop ("# reserved"), reserved, GNUNET_NO); e = GNUNET_new (struct ReservationList); e->next = reservations; reservations = e; e->client = client; e->amount = amount; e->entries = entries; e->rid = ++reservation_gen; if (reservation_gen < 0) reservation_gen = 0; /* wrap around */ transmit_status (client, e->rid, NULL); } /** * Handle RELEASE_RESERVE-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_release_reserve (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct ReleaseReserveMessage *msg = (const struct ReleaseReserveMessage *) message; struct ReservationList *pos; struct ReservationList *prev; struct ReservationList *next; int rid = ntohl (msg->rid); unsigned long long rem; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request\n", "RELEASE_RESERVE"); next = reservations; prev = NULL; while (NULL != (pos = next)) { next = pos->next; if (rid == pos->rid) { if (prev == NULL) reservations = next; else prev->next = next; rem = pos->amount + ((unsigned long long) GNUNET_DATASTORE_ENTRY_OVERHEAD) * pos->entries; GNUNET_assert (reserved >= rem); reserved -= rem; GNUNET_STATISTICS_set (stats, gettext_noop ("# reserved"), reserved, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning %llu remaining reserved bytes to storage pool\n", rem); GNUNET_free (pos); transmit_status (client, GNUNET_OK, NULL); return; } prev = pos; } GNUNET_break (0); transmit_status (client, GNUNET_SYSERR, gettext_noop ("Could not find matching reservation")); } /** * Check that the given message is a valid data message. * * @return NULL if the message is not well-formed, otherwise the message */ static const struct DataMessage * check_data (const struct GNUNET_MessageHeader *message) { uint16_t size; uint32_t dsize; const struct DataMessage *dm; size = ntohs (message->size); if (size < sizeof (struct DataMessage)) { GNUNET_break (0); return NULL; } dm = (const struct DataMessage *) message; dsize = ntohl (dm->size); if (size != dsize + sizeof (struct DataMessage)) { GNUNET_break (0); return NULL; } return dm; } /** * Context for a PUT request used to see if the content is * already present. */ struct PutContext { /** * Client to notify on completion. */ struct GNUNET_SERVER_Client *client; #if ! HAVE_UNALIGNED_64_ACCESS void *reserved; #endif /* followed by the 'struct DataMessage' */ }; /** * Actually put the data message. * * @param client sender of the message * @param dm message with the data to store */ static void execute_put (struct GNUNET_SERVER_Client *client, const struct DataMessage *dm) { uint32_t size; char *msg; int ret; size = ntohl (dm->size); msg = NULL; ret = plugin->api->put (plugin->api->cls, &dm->key, size, &dm[1], ntohl (dm->type), ntohl (dm->priority), ntohl (dm->anonymity), ntohl (dm->replication), GNUNET_TIME_absolute_ntoh (dm->expiration), &msg); if (GNUNET_OK == ret) { GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes stored"), size, GNUNET_YES); GNUNET_CONTAINER_bloomfilter_add (filter, &dm->key); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully stored %u bytes of type %u under key `%s'\n", size, ntohl (dm->type), GNUNET_h2s (&dm->key)); } transmit_status (client, ret, msg); GNUNET_free_non_null (msg); if (quota - reserved - cache_size < payload) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Need %llu bytes more space (%llu allowed, using %llu)\n"), (unsigned long long) size + GNUNET_DATASTORE_ENTRY_OVERHEAD, (unsigned long long) (quota - reserved - cache_size), (unsigned long long) payload); manage_space (size + GNUNET_DATASTORE_ENTRY_OVERHEAD); } } /** * Function that will check if the given datastore entry * matches the put and if none match executes the put. * * @param cls closure, pointer to the client (of type 'struct PutContext'). * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * * @return GNUNET_OK usually * GNUNET_NO to delete the item */ static int check_present (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct PutContext *pc = cls; const struct DataMessage *dm; dm = (const struct DataMessage *) &pc[1]; if (key == NULL) { execute_put (pc->client, dm); GNUNET_SERVER_client_drop (pc->client); GNUNET_free (pc); return GNUNET_OK; } if ((GNUNET_BLOCK_TYPE_FS_DBLOCK == type) || (GNUNET_BLOCK_TYPE_FS_IBLOCK == type) || ((size == ntohl (dm->size)) && (0 == memcmp (&dm[1], data, size)))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result already present in datastore\n"); /* FIXME: change API to allow increasing 'replication' counter */ if ((ntohl (dm->priority) > 0) || (GNUNET_TIME_absolute_ntoh (dm->expiration).abs_value_us > expiration.abs_value_us)) plugin->api->update (plugin->api->cls, uid, (int32_t) ntohl (dm->priority), GNUNET_TIME_absolute_ntoh (dm->expiration), NULL); transmit_status (pc->client, GNUNET_NO, NULL); GNUNET_SERVER_client_drop (pc->client); GNUNET_free (pc); } else { execute_put (pc->client, dm); GNUNET_SERVER_client_drop (pc->client); GNUNET_free (pc); } return GNUNET_OK; } /** * Handle PUT-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_put (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct DataMessage *dm = check_data (message); int rid; struct ReservationList *pos; struct PutContext *pc; struct GNUNET_HashCode vhash; uint32_t size; if ((dm == NULL) || (ntohl (dm->type) == 0)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request for `%s' of type %u\n", "PUT", GNUNET_h2s (&dm->key), ntohl (dm->type)); rid = ntohl (dm->rid); size = ntohl (dm->size); if (rid > 0) { pos = reservations; while ((NULL != pos) && (rid != pos->rid)) pos = pos->next; GNUNET_break (pos != NULL); if (NULL != pos) { GNUNET_break (pos->entries > 0); GNUNET_break (pos->amount >= size); pos->entries--; pos->amount -= size; reserved -= (size + GNUNET_DATASTORE_ENTRY_OVERHEAD); GNUNET_STATISTICS_set (stats, gettext_noop ("# reserved"), reserved, GNUNET_NO); } } if (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (filter, &dm->key)) { GNUNET_CRYPTO_hash (&dm[1], size, &vhash); pc = GNUNET_malloc (sizeof (struct PutContext) + size + sizeof (struct DataMessage)); pc->client = client; GNUNET_SERVER_client_keep (client); memcpy (&pc[1], dm, size + sizeof (struct DataMessage)); plugin->api->get_key (plugin->api->cls, 0, &dm->key, &vhash, ntohl (dm->type), &check_present, pc); return; } execute_put (client, dm); } /** * Handle GET-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GetMessage *msg; uint16_t size; size = ntohs (message->size); if ((size != sizeof (struct GetMessage)) && (size != sizeof (struct GetMessage) - sizeof (struct GNUNET_HashCode))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GetMessage *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request for `%s' of type %u\n", "GET", GNUNET_h2s (&msg->key), ntohl (msg->type)); GNUNET_STATISTICS_update (stats, gettext_noop ("# GET requests received"), 1, GNUNET_NO); GNUNET_SERVER_client_keep (client); if ((size == sizeof (struct GetMessage)) && (GNUNET_YES != GNUNET_CONTAINER_bloomfilter_test (filter, &msg->key))) { /* don't bother database... */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Empty result set for `%s' request for `%s' (bloomfilter).\n", "GET", GNUNET_h2s (&msg->key)); GNUNET_STATISTICS_update (stats, gettext_noop ("# requests filtered by bloomfilter"), 1, GNUNET_NO); transmit_item (client, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } plugin->api->get_key (plugin->api->cls, GNUNET_ntohll (msg->offset), ((size == sizeof (struct GetMessage)) ? &msg->key : NULL), NULL, ntohl (msg->type), &transmit_item, client); } /** * Handle UPDATE-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_update (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct UpdateMessage *msg; int ret; char *emsg; GNUNET_STATISTICS_update (stats, gettext_noop ("# UPDATE requests received"), 1, GNUNET_NO); msg = (const struct UpdateMessage *) message; emsg = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request for %llu\n", "UPDATE", (unsigned long long) GNUNET_ntohll (msg->uid)); ret = plugin->api->update (plugin->api->cls, GNUNET_ntohll (msg->uid), (int32_t) ntohl (msg->priority), GNUNET_TIME_absolute_ntoh (msg->expiration), &emsg); transmit_status (client, ret, emsg); GNUNET_free_non_null (emsg); } /** * Handle GET_REPLICATION-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get_replication (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request\n", "GET_REPLICATION"); GNUNET_STATISTICS_update (stats, gettext_noop ("# GET REPLICATION requests received"), 1, GNUNET_NO); GNUNET_SERVER_client_keep (client); plugin->api->get_replication (plugin->api->cls, &transmit_item, client); } /** * Handle GET_ZERO_ANONYMITY-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_get_zero_anonymity (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GetZeroAnonymityMessage *msg = (const struct GetZeroAnonymityMessage *) message; enum GNUNET_BLOCK_Type type; type = (enum GNUNET_BLOCK_Type) ntohl (msg->type); if (type == GNUNET_BLOCK_TYPE_ANY) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request\n", "GET_ZERO_ANONYMITY"); GNUNET_STATISTICS_update (stats, gettext_noop ("# GET ZERO ANONYMITY requests received"), 1, GNUNET_NO); GNUNET_SERVER_client_keep (client); plugin->api->get_zero_anonymity (plugin->api->cls, GNUNET_ntohll (msg->offset), type, &transmit_item, client); } /** * Callback function that will cause the item that is passed * in to be deleted (by returning GNUNET_NO). */ static int remove_callback (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct GNUNET_SERVER_Client *client = cls; if (key == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No further matches for `%s' request.\n", "REMOVE"); transmit_status (client, GNUNET_NO, _("Content not found")); GNUNET_SERVER_client_drop (client); return GNUNET_OK; /* last item */ } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Item %llu matches `%s' request for key `%s' and type %u.\n", (unsigned long long) uid, "REMOVE", GNUNET_h2s (key), type); GNUNET_STATISTICS_update (stats, gettext_noop ("# bytes removed (explicit request)"), size, GNUNET_YES); GNUNET_CONTAINER_bloomfilter_remove (filter, key); transmit_status (client, GNUNET_OK, NULL); GNUNET_SERVER_client_drop (client); return GNUNET_NO; } /** * Handle REMOVE-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_remove (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct DataMessage *dm = check_data (message); struct GNUNET_HashCode vhash; if (dm == NULL) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request for `%s' of type %u\n", "REMOVE", GNUNET_h2s (&dm->key), ntohl (dm->type)); GNUNET_STATISTICS_update (stats, gettext_noop ("# REMOVE requests received"), 1, GNUNET_NO); GNUNET_SERVER_client_keep (client); GNUNET_CRYPTO_hash (&dm[1], ntohl (dm->size), &vhash); plugin->api->get_key (plugin->api->cls, 0, &dm->key, &vhash, (enum GNUNET_BLOCK_Type) ntohl (dm->type), &remove_callback, client); } /** * Handle DROP-message. * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_drop (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing `%s' request\n", "DROP"); do_drop = GNUNET_YES; GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Function called by plugins to notify us about a * change in their disk utilization. * * @param cls closure (NULL) * @param delta change in disk utilization, * 0 for "reset to empty" */ static void disk_utilization_change_cb (void *cls, int delta) { if ((delta < 0) && (payload < -delta)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Datastore payload inaccurate (%lld < %lld). Trying to fix.\n"), (long long) payload, (long long) -delta); payload = plugin->api->estimate_size (plugin->api->cls); sync_stats (); return; } payload += delta; lastSync++; if (lastSync >= MAX_STAT_SYNC_LAG) sync_stats (); } /** * Callback function to process statistic values. * * @param cls closure (struct Plugin*) * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int process_stat_in (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { GNUNET_assert (stats_worked == GNUNET_NO); stats_worked = GNUNET_YES; payload += value; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notification from statistics about existing payload (%llu), new payload is %llu\n", value, payload); return GNUNET_OK; } static void process_stat_done (void *cls, int success) { struct DatastorePlugin *plugin = cls; stat_get = NULL; if (stats_worked == GNUNET_NO) payload = plugin->api->estimate_size (plugin->api->cls); } /** * Load the datastore plugin. */ static struct DatastorePlugin * load_plugin () { struct DatastorePlugin *ret; char *libname; ret = GNUNET_new (struct DatastorePlugin); ret->env.cfg = cfg; ret->env.duc = &disk_utilization_change_cb; ret->env.cls = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' datastore plugin\n"), plugin_name); GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", plugin_name); ret->short_name = GNUNET_strdup (plugin_name); ret->lib_name = libname; ret->api = GNUNET_PLUGIN_load (libname, &ret->env); if (ret->api == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to load datastore plugin for `%s'\n"), plugin_name); GNUNET_free (ret->short_name); GNUNET_free (libname); GNUNET_free (ret); return NULL; } return ret; } /** * Function called when the service shuts * down. Unloads our datastore plugin. * * @param plug plugin to unload */ static void unload_plugin (struct DatastorePlugin *plug) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Datastore service is unloading plugin...\n"); GNUNET_break (NULL == GNUNET_PLUGIN_unload (plug->lib_name, plug->api)); GNUNET_free (plug->lib_name); GNUNET_free (plug->short_name); GNUNET_free (plug); GNUNET_free (quota_stat_name); quota_stat_name = NULL; } /** * Final task run after shutdown. Unloads plugins and disconnects us from * statistics. */ static void unload_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (lastSync > 0) sync_stats (); if (GNUNET_YES == do_drop) plugin->api->drop (plugin->api->cls); unload_plugin (plugin); plugin = NULL; if (filter != NULL) { GNUNET_CONTAINER_bloomfilter_free (filter); filter = NULL; } if (stat_get != NULL) { GNUNET_STATISTICS_get_cancel (stat_get); stat_get = NULL; } if (stats != NULL) { GNUNET_STATISTICS_destroy (stats, GNUNET_YES); stats = NULL; } GNUNET_free_non_null (plugin_name); plugin_name = NULL; } /** * Last task run during shutdown. Disconnects us from * the transport and core. */ static void cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct TransmitCallbackContext *tcc; cleaning_done = GNUNET_YES; while (NULL != (tcc = tcc_head)) { GNUNET_CONTAINER_DLL_remove (tcc_head, tcc_tail, tcc); if (tcc->th != NULL) { GNUNET_SERVER_notify_transmit_ready_cancel (tcc->th); GNUNET_SERVER_client_drop (tcc->client); } GNUNET_free (tcc->msg); GNUNET_free (tcc); } if (expired_kill_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (expired_kill_task); expired_kill_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_continuation (&unload_task, NULL, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } /** * Function that removes all active reservations made * by the given client and releases the space for other * requests. * * @param cls closure * @param client identification of the client */ static void cleanup_reservations (void *cls, struct GNUNET_SERVER_Client *client) { struct ReservationList *pos; struct ReservationList *prev; struct ReservationList *next; if (client == NULL) return; prev = NULL; pos = reservations; while (NULL != pos) { next = pos->next; if (pos->client == client) { if (prev == NULL) reservations = next; else prev->next = next; reserved -= pos->amount + pos->entries * GNUNET_DATASTORE_ENTRY_OVERHEAD; GNUNET_free (pos); } else { prev = pos; } pos = next; } GNUNET_STATISTICS_set (stats, gettext_noop ("# reserved"), reserved, GNUNET_NO); } /** * Adds a given key to the bloomfilter 'count' times. * * @param cls the bloomfilter * @param key key to add * @param count number of times to add key */ static void add_key_to_bloomfilter (void *cls, const struct GNUNET_HashCode *key, unsigned int count) { struct GNUNET_CONTAINER_BloomFilter *bf = cls; while (0 < count--) GNUNET_CONTAINER_bloomfilter_add (bf, key); } /** * Process datastore requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_reserve, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE, sizeof (struct ReserveMessage)}, {&handle_release_reserve, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE, sizeof (struct ReleaseReserveMessage)}, {&handle_put, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_PUT, 0}, {&handle_update, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE, sizeof (struct UpdateMessage)}, {&handle_get, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_GET, 0}, {&handle_get_replication, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_GET_REPLICATION, sizeof (struct GNUNET_MessageHeader)}, {&handle_get_zero_anonymity, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_GET_ZERO_ANONYMITY, sizeof (struct GetZeroAnonymityMessage)}, {&handle_remove, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE, 0}, {&handle_drop, NULL, GNUNET_MESSAGE_TYPE_DATASTORE_DROP, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; char *fn; char *pfn; unsigned int bf_size; int refresh_bf; cfg = c; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "DATASTORE", "DATABASE", &plugin_name)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No `%s' specified for `%s' in configuration!\n"), "DATABASE", "DATASTORE"); return; } GNUNET_asprintf ("a_stat_name, _("# bytes used in file-sharing datastore `%s'"), plugin_name); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_size (cfg, "DATASTORE", "QUOTA", "a)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No `%s' specified for `%s' in configuration!\n"), "QUOTA", "DATASTORE"); return; } stats = GNUNET_STATISTICS_create ("datastore", cfg); GNUNET_STATISTICS_set (stats, gettext_noop ("# quota"), quota, GNUNET_NO); cache_size = quota / 8; /* Or should we make this an option? */ GNUNET_STATISTICS_set (stats, gettext_noop ("# cache size"), cache_size, GNUNET_NO); if (quota / (32 * 1024LL) > (1 << 31)) bf_size = (1 << 31); /* absolute limit: ~2 GB, beyond that BF just won't help anyway */ else bf_size = quota / (32 * 1024LL); /* 8 bit per entry, 1 bit per 32 kb in DB */ fn = NULL; if ((GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "DATASTORE", "BLOOMFILTER", &fn)) || (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Could not use specified filename `%s' for bloomfilter.\n"), fn != NULL ? fn : ""); GNUNET_free_non_null (fn); fn = NULL; } if (fn != NULL) { GNUNET_asprintf (&pfn, "%s.%s", fn, plugin_name); if (GNUNET_YES == GNUNET_DISK_file_test (pfn)) { filter = GNUNET_CONTAINER_bloomfilter_load (pfn, bf_size, 5); /* approx. 3% false positives at max use */ if (NULL == filter) { /* file exists but not valid, remove and try again, but refresh */ if (0 != UNLINK (pfn)) { /* failed to remove, run without file */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to remove bogus bloomfilter file `%s'\n"), pfn); GNUNET_free (pfn); pfn = NULL; filter = GNUNET_CONTAINER_bloomfilter_load (NULL, bf_size, 5); /* approx. 3% false positives at max use */ refresh_bf = GNUNET_YES; } else { /* try again after remove */ filter = GNUNET_CONTAINER_bloomfilter_load (pfn, bf_size, 5); /* approx. 3% false positives at max use */ refresh_bf = GNUNET_YES; if (NULL == filter) { /* failed yet again, give up on using file */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to remove bogus bloomfilter file `%s'\n"), pfn); GNUNET_free (pfn); pfn = NULL; filter = GNUNET_CONTAINER_bloomfilter_init (NULL, bf_size, 5); /* approx. 3% false positives at max use */ } } } else { /* normal case: have an existing valid bf file, no need to refresh */ refresh_bf = GNUNET_NO; } } else { filter = GNUNET_CONTAINER_bloomfilter_load (pfn, bf_size, 5); /* approx. 3% false positives at max use */ refresh_bf = GNUNET_YES; } GNUNET_free (pfn); } else { filter = GNUNET_CONTAINER_bloomfilter_init (NULL, bf_size, 5); /* approx. 3% false positives at max use */ refresh_bf = GNUNET_YES; } GNUNET_free_non_null (fn); if (filter == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to initialize bloomfilter.\n")); if (stats != NULL) { GNUNET_STATISTICS_destroy (stats, GNUNET_YES); stats = NULL; } return; } plugin = load_plugin (); if (NULL == plugin) { GNUNET_CONTAINER_bloomfilter_free (filter); filter = NULL; if (stats != NULL) { GNUNET_STATISTICS_destroy (stats, GNUNET_YES); stats = NULL; } return; } stat_get = GNUNET_STATISTICS_get (stats, "datastore", quota_stat_name, GNUNET_TIME_UNIT_SECONDS, &process_stat_done, &process_stat_in, plugin); GNUNET_SERVER_disconnect_notify (server, &cleanup_reservations, NULL); GNUNET_SERVER_add_handlers (server, handlers); if (GNUNET_YES == refresh_bf) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Rebuilding bloomfilter. Please be patient.\n")); if (NULL != plugin->api->get_keys) plugin->api->get_keys (plugin->api->cls, &add_key_to_bloomfilter, filter); else GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Plugin does not support get_keys function. Please fix!\n")); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Bloomfilter construction complete.\n")); } expired_kill_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &delete_expired, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleaning_task, NULL); } /** * The main function for the datastore service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int ret; ret = (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "datastore", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; return ret; } /* end of gnunet-service-datastore.c */ gnunet-0.10.1/src/datastore/test_datastore_api_data_heap.conf0000644000175000017500000000037212225230043021275 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-datastore-heap/ [TESTING] WEAKRANDOM = YES [arm] PORT = 42466 DEFAULTSERVICES = [statistics] PORT = 22667 [resolver] PORT = 42464 [datastore] QUOTA = 10 MB DATABASE = heap gnunet-0.10.1/src/datastore/datastore.h0000644000175000017500000001256412225777503014750 00000000000000/* This file is part of GNUnet (C) 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datastore/datastore.h * @brief structs for communication between datastore service and API * @author Christian Grothoff */ #ifndef DATASTORE_H #define DATASTORE_H #include "gnunet_util_lib.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Message from datastore service informing client about * the current size of the datastore. */ struct ReserveMessage { /** * Type is GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE. */ struct GNUNET_MessageHeader header; /** * Number of items to reserve. */ uint32_t entries GNUNET_PACKED; /** * Number of bytes to reserve. */ uint64_t amount GNUNET_PACKED; }; /** * Message from datastore service informing client about * the success or failure of a requested operation. * This header is optionally followed by a variable-size, * 0-terminated error message. */ struct StatusMessage { /** * Type is GNUNET_MESSAGE_TYPE_DATASTORE_STATUS. */ struct GNUNET_MessageHeader header; /** * Status code, -1 for errors. */ int32_t status GNUNET_PACKED; /** * Minimum expiration time required for content to be stored * by the datacache at this time, zero for unknown or no limit. */ struct GNUNET_TIME_AbsoluteNBO min_expiration; }; /** * Message from datastore client informing service that * the remainder of the reserved bytes can now be released * for other requests. */ struct ReleaseReserveMessage { /** * Type is GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE. */ struct GNUNET_MessageHeader header; /** * Reservation id. */ int32_t rid GNUNET_PACKED; }; /** * Message to the datastore service asking about specific * content. */ struct GetMessage { /** * Type is GNUNET_MESSAGE_TYPE_DATASTORE_GET. Size * can either be "sizeof(struct GetMessage)" or * "sizeof(struct GetMessage) - sizeof(struct GNUNET_HashCode)"! */ struct GNUNET_MessageHeader header; /** * Desired content type. (actually an enum GNUNET_BLOCK_Type) */ uint32_t type GNUNET_PACKED; /** * Offset of the result. */ uint64_t offset GNUNET_PACKED; /** * Desired key (optional). Check the "size" of the * header to see if the key is actually present. */ struct GNUNET_HashCode key; }; /** * Message to the datastore service asking about zero * anonymity content. */ struct GetZeroAnonymityMessage { /** * Type is GNUNET_MESSAGE_TYPE_DATASTORE_GET_ZERO_ANONYMITY. */ struct GNUNET_MessageHeader header; /** * Desired content type (actually an enum GNUNET_BLOCK_Type) */ uint32_t type GNUNET_PACKED; /** * Offset of the result. */ uint64_t offset GNUNET_PACKED; }; /** * Message to the datastore service requesting an update * to the priority or expiration for some content. */ struct UpdateMessage { /** * Type is GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE. */ struct GNUNET_MessageHeader header; /** * Desired priority increase. */ int32_t priority GNUNET_PACKED; /** * Desired new expiration time. */ struct GNUNET_TIME_AbsoluteNBO expiration; /** * Unique ID for the content. */ uint64_t uid; }; /** * Message transmitting content from or to the datastore * service. */ struct DataMessage { /** * Type is either GNUNET_MESSAGE_TYPE_DATASTORE_PUT, * GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE or * GNUNET_MESSAGE_TYPE_DATASTORE_DATA. Depending on the message * type, some fields may simply have values of zero. */ struct GNUNET_MessageHeader header; /** * Reservation ID to use; use zero for none. */ uint32_t rid GNUNET_PACKED; /** * Number of bytes in the item (NBO). */ uint32_t size GNUNET_PACKED; /** * Type of the item (NBO), zero for remove, (actually an enum GNUNET_BLOCK_Type) */ uint32_t type GNUNET_PACKED; /** * Priority of the item (NBO), zero for remove. */ uint32_t priority GNUNET_PACKED; /** * Desired anonymity level (NBO), zero for remove. */ uint32_t anonymity GNUNET_PACKED; /** * Desired replication level. 0 from service to API. */ uint32_t replication GNUNET_PACKED; /** * For alignment. */ uint32_t reserved GNUNET_PACKED; /** * Unique ID for the content (can be used for UPDATE); * can be zero for remove (which indicates that * the datastore should use whatever UID matches * the key and content). */ uint64_t uid; /** * Expiration time (NBO); zero for remove. */ struct GNUNET_TIME_AbsoluteNBO expiration; /** * Key under which the item can be found. */ struct GNUNET_HashCode key; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/datastore/test_plugin_datastore_data_sqlite.conf0000644000175000017500000000014212225230043022401 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-datastore-plugin-sqlite/ gnunet-0.10.1/src/datastore/perf_plugin_datastore_data_heap.conf0000644000175000017500000000016612225230043022000 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/perf-gnunet-datastore-heap/ [datastore] DATABASE = heap gnunet-0.10.1/src/datastore/plugin_datastore_template.c0000644000175000017500000001747312255010512020177 00000000000000/* This file is part of GNUnet (C) 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datastore/plugin_datastore_template.c * @brief template-based datastore backend * @author Christian Grothoff */ #include "platform.h" #include "gnunet_datastore_plugin.h" /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATASTORE_PluginEnvironment *env; }; /** * Get an estimate of how much space the database is * currently using. * * @param cls our "struct Plugin*" * @return number of bytes used on disk */ static unsigned long long template_plugin_estimate_size (void *cls) { GNUNET_break (0); return 0; } /** * Store an item in the datastore. * * @param cls closure * @param key key for the item * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param msg set to error message * @return GNUNET_OK on success */ static int template_plugin_put (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, char **msg) { GNUNET_break (0); *msg = GNUNET_strdup ("not implemented"); return GNUNET_SYSERR; } /** * Get one of the results for a particular key in the datastore. * * @param cls closure * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param key maybe NULL (to match all entries) * @param vhash hash of the value, maybe NULL (to * match all values that have the right key). * Note that for DBlocks there is no difference * betwen key and vhash, but for other blocks * there may be! * @param type entries of which type are relevant? * Use 0 for any type. * @param proc function to call on each matching value; * will be called with NULL if nothing matches * @param proc_cls closure for proc */ static void template_plugin_get_key (void *cls, uint64_t offset, const struct GNUNET_HashCode * key, const struct GNUNET_HashCode * vhash, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { GNUNET_break (0); } /** * Get a random item for replication. Returns a single, not expired, * random item from those with the highest replication counters. The * item's replication counter is decremented by one IF it was positive * before. Call 'proc' with all values ZERO or NULL if the datastore * is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void template_plugin_get_replication (void *cls, PluginDatumProcessor proc, void *proc_cls) { GNUNET_break (0); } /** * Get a random item for expiration. Call 'proc' with all values ZERO * or NULL if the datastore is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void template_plugin_get_expiration (void *cls, PluginDatumProcessor proc, void *proc_cls) { GNUNET_break (0); } /** * Update the priority for a particular key in the datastore. If * the expiration time in value is different than the time found in * the datastore, the higher value should be kept. For the * anonymity level, the lower value is to be used. The specified * priority should be added to the existing priority, ignoring the * priority in value. * * Note that it is possible for multiple values to match this put. * In that case, all of the respective values are updated. * * @param cls our "struct Plugin*" * @param uid unique identifier of the datum * @param delta by how much should the priority * change? If priority + delta < 0 the * priority should be set to 0 (never go * negative). * @param expire new expiration time should be the * MAX of any existing expiration time and * this value * @param msg set to error message * @return GNUNET_OK on success */ static int template_plugin_update (void *cls, uint64_t uid, int delta, struct GNUNET_TIME_Absolute expire, char **msg) { GNUNET_break (0); *msg = GNUNET_strdup ("not implemented"); return GNUNET_SYSERR; } /** * Call the given processor on an item with zero anonymity. * * @param cls our "struct Plugin*" * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param type entries of which type should be considered? * Use 0 for any type. * @param proc function to call on each matching value; * will be called with NULL if no value matches * @param proc_cls closure for proc */ static void template_plugin_get_zero_anonymity (void *cls, uint64_t offset, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { GNUNET_break (0); } /** * Drop database. */ static void template_plugin_drop (void *cls) { GNUNET_break (0); } /** * Get all of the keys in the datastore. * * @param cls closure * @param proc function to call on each key * @param proc_cls closure for proc */ static void template_get_keys (void *cls, PluginKeyProcessor proc, void *proc_cls) { } /** * Entry point for the plugin. * * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*" * @return our "struct Plugin*" */ void * libgnunet_plugin_datastore_template_init (void *cls) { struct GNUNET_DATASTORE_PluginEnvironment *env = cls; struct GNUNET_DATASTORE_PluginFunctions *api; struct Plugin *plugin; plugin = GNUNET_new (struct Plugin); plugin->env = env; api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions); api->cls = plugin; api->estimate_size = &template_plugin_estimate_size; api->put = &template_plugin_put; api->update = &template_plugin_update; api->get_key = &template_plugin_get_key; api->get_replication = &template_plugin_get_replication; api->get_expiration = &template_plugin_get_expiration; api->get_zero_anonymity = &template_plugin_get_zero_anonymity; api->drop = &template_plugin_drop; api->get_keys = &template_get_keys; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "template", _("Template database running\n")); return api; } /** * Exit point from the plugin. * @param cls our "struct Plugin*" * @return always NULL */ void * libgnunet_plugin_datastore_template_done (void *cls) { struct GNUNET_DATASTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_datastore_template.c */ gnunet-0.10.1/src/datastore/perf_datastore_api.c0000644000175000017500000002367412255010512016573 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2007, 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file datastore/perf_datastore_api.c * @brief performance measurement for the datastore implementation * @author Christian Grothoff * * This testcase inserts a bunch of (variable size) data and then * deletes data until the (reported) database size drops below a given * threshold. This is iterated 10 times, with the actual size of the * content stored and the number of operations performed being printed * for each iteration. The code also prints a "I" for every 40 blocks * inserted and a "D" for every 40 blocks deleted. The deletion * strategy uses the "random" iterator. Priorities and expiration * dates are set using a pseudo-random value within a realistic range. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_datastore_service.h" #include "gnunet_testing_lib.h" #include /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) /** * Target datastore size (in bytes). */ #define MAX_SIZE 1024LL * 1024 * 4 /** * Report progress outside of major reports? Should probably be GNUNET_YES if * size is > 16 MB. */ #define REPORT_ID GNUNET_YES /** * Number of put operations equivalent to 1/3rd of MAX_SIZE */ #define PUT_10 MAX_SIZE / 32 / 1024 / 3 /** * Total number of iterations (each iteration doing * PUT_10 put operations); we report full status every * 10 iterations. Abort with CTRL-C. */ #define ITERATIONS 8 static unsigned long long stored_bytes; static unsigned long long stored_entries; static unsigned long long stored_ops; static struct GNUNET_TIME_Absolute start_time; static const char *plugin_name; static struct GNUNET_DATASTORE_Handle *datastore; static int ok; enum RunPhase { RP_DONE = 0, RP_PUT, RP_CUT, RP_REPORT, RP_ERROR }; struct CpsRunContext { const struct GNUNET_CONFIGURATION_Handle *cfg; enum RunPhase phase; int j; unsigned long long size; int i; }; static void run_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void check_success (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct CpsRunContext *crc = cls; if (GNUNET_OK != success) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Check success failed: `%s'\n", msg); crc->phase = RP_ERROR; GNUNET_SCHEDULER_add_now (&run_continuation, crc); return; } #if REPORT_ID FPRINTF (stderr, "%s", "I"); #endif stored_bytes += crc->size; stored_ops++; stored_entries++; crc->j++; if (crc->j >= PUT_10) { crc->j = 0; crc->i++; if (crc->i == ITERATIONS) crc->phase = RP_DONE; else crc->phase = RP_CUT; } GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } /** * Continuation called to notify client about result of the * operation. * * @param cls closure * @param success GNUNET_SYSERR on failure * @param min_expiration minimum expiration time required for content to be stored * by the datacache at this time, zero for unknown * @param msg NULL on success, otherwise an error message */ static void remove_next (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct CpsRunContext *crc = cls; if (GNUNET_OK != success) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "remove_next failed: `%s'\n", msg); crc->phase = RP_ERROR; GNUNET_SCHEDULER_add_now (&run_continuation, crc); return; } #if REPORT_ID FPRINTF (stderr, "%s", "D"); #endif GNUNET_assert (GNUNET_OK == success); GNUNET_SCHEDULER_add_now (&run_continuation, crc); } static void delete_value (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; GNUNET_assert (NULL != key); stored_ops++; stored_bytes -= size; stored_entries--; stored_ops++; if (stored_bytes < MAX_SIZE) crc->phase = RP_PUT; GNUNET_assert (NULL != GNUNET_DATASTORE_remove (datastore, key, size, data, 1, 1, TIMEOUT, &remove_next, crc)); } static void run_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CpsRunContext *crc = cls; size_t size; static struct GNUNET_HashCode key; static char data[65536]; int i; int k; char gstr[128]; ok = (int) crc->phase; switch (crc->phase) { case RP_PUT: memset (&key, 256 - crc->i, sizeof (struct GNUNET_HashCode)); i = crc->j; k = crc->i; /* most content is 32k */ size = 32 * 1024; if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16) == 0) /* but some of it is less! */ size = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 32 * 1024); crc->size = size = size - (size & 7); /* always multiple of 8 */ GNUNET_CRYPTO_hash (&key, sizeof (struct GNUNET_HashCode), &key); memset (data, i, size); if (i > 255) memset (data, i - 255, size / 2); data[0] = k; GNUNET_assert (NULL != GNUNET_DATASTORE_put (datastore, 0, &key, size, data, i + 1, GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100), i, 0, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000))), 1, 1, TIMEOUT, &check_success, crc)); break; case RP_CUT: /* trim down below MAX_SIZE again */ GNUNET_assert (NULL != GNUNET_DATASTORE_get_for_replication (datastore, 1, 1, TIMEOUT, &delete_value, crc)); break; case RP_REPORT: printf ( #if REPORT_ID "\n" #endif "Stored %llu kB / %lluk ops / %llu ops/s\n", stored_bytes / 1024, /* used size in k */ stored_ops / 1024, /* total operations (in k) */ 1000LL * 1000LL * stored_ops / (1 + GNUNET_TIME_absolute_get_duration (start_time).rel_value_us)); crc->phase = RP_PUT; crc->j = 0; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); break; case RP_DONE: GNUNET_snprintf (gstr, sizeof (gstr), "DATASTORE-%s", plugin_name); if ((crc->i == ITERATIONS) && (stored_ops > 0)) GAUGER (gstr, "PUT operation duration", GNUNET_TIME_absolute_get_duration (start_time).rel_value_us / 1000LL / stored_ops, "ms/operation"); GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); ok = 0; break; case RP_ERROR: GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); ok = 1; break; default: GNUNET_assert (0); } } static void run_tests (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct CpsRunContext *crc = cls; if (success != GNUNET_YES) { FPRINTF (stderr, "Test 'put' operation failed with error `%s' database likely not setup, skipping test.\n", msg); GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); return; } GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct CpsRunContext *crc; static struct GNUNET_HashCode zkey; datastore = GNUNET_DATASTORE_connect (cfg); start_time = GNUNET_TIME_absolute_get (); crc = GNUNET_new (struct CpsRunContext); crc->cfg = cfg; crc->phase = RP_PUT; if (NULL == GNUNET_DATASTORE_put (datastore, 0, &zkey, 4, "TEST", GNUNET_BLOCK_TYPE_TEST, 0, 0, 0, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_SECONDS), 0, 1, GNUNET_TIME_UNIT_MINUTES, &run_tests, crc)) { FPRINTF (stderr, "%s", "Test 'put' operation failed.\n"); ok = 1; GNUNET_free (crc); } } int main (int argc, char *argv[]) { char cfg_name[128]; plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_datastore_api_data_%s.conf", plugin_name); if (0 != GNUNET_TESTING_peer_run ("perf-gnunet-datastore", cfg_name, &run, NULL)) return 1; FPRINTF (stderr, "%s", "\n"); return ok; } /* end of perf_datastore_api.c */ gnunet-0.10.1/src/datastore/test_datastore_api_data_mysql.conf0000644000175000017500000000047412225230043021530 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-datastore-mysql/ [TESTING] WEAKRANDOM = YES [arm] PORT = 42466 DEFAULTSERVICES = [statistics] PORT = 22667 [resolver] PORT = 42464 [datastore] QUOTA = 10 MB DATABASE = mysql [datastore-mysql] DATABASE = gnunetcheck [fs] AUTOSTART = NO gnunet-0.10.1/src/datastore/datastore_api.c0000644000175000017500000013471512242623710015564 00000000000000/* This file is part of GNUnet (C) 2004-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datastore/datastore_api.c * @brief Management for the datastore for files stored on a GNUnet node. Implements * a priority queue for requests (with timeouts). * @author Christian Grothoff */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_constants.h" #include "gnunet_datastore_service.h" #include "gnunet_statistics_service.h" #include "datastore.h" #define LOG(kind,...) GNUNET_log_from (kind, "datastore-api",__VA_ARGS__) /** * Collect an instane number of statistics? May cause excessive IPC. */ #define INSANE_STATISTICS GNUNET_NO /** * If a client stopped asking for more results, how many more do * we receive from the DB before killing the connection? Trade-off * between re-doing TCP handshakes and (needlessly) receiving * useless results. */ #define MAX_EXCESS_RESULTS 8 /** * Context for processing status messages. */ struct StatusContext { /** * Continuation to call with the status. */ GNUNET_DATASTORE_ContinuationWithStatus cont; /** * Closure for cont. */ void *cont_cls; }; /** * Context for processing result messages. */ struct ResultContext { /** * Function to call with the result. */ GNUNET_DATASTORE_DatumProcessor proc; /** * Closure for proc. */ void *proc_cls; }; /** * Context for a queue operation. */ union QueueContext { struct StatusContext sc; struct ResultContext rc; }; /** * Entry in our priority queue. */ struct GNUNET_DATASTORE_QueueEntry { /** * This is a linked list. */ struct GNUNET_DATASTORE_QueueEntry *next; /** * This is a linked list. */ struct GNUNET_DATASTORE_QueueEntry *prev; /** * Handle to the master context. */ struct GNUNET_DATASTORE_Handle *h; /** * Response processor (NULL if we are not waiting for a response). * This struct should be used for the closure, function-specific * arguments can be passed via 'qc'. */ GNUNET_CLIENT_MessageHandler response_proc; /** * Function to call after transmission of the request. */ GNUNET_DATASTORE_ContinuationWithStatus cont; /** * Closure for 'cont'. */ void *cont_cls; /** * Context for the operation. */ union QueueContext qc; /** * Task for timeout signalling. */ GNUNET_SCHEDULER_TaskIdentifier task; /** * Timeout for the current operation. */ struct GNUNET_TIME_Absolute timeout; /** * Priority in the queue. */ unsigned int priority; /** * Maximum allowed length of queue (otherwise * this request should be discarded). */ unsigned int max_queue; /** * Number of bytes in the request message following * this struct. 32-bit value for nicer memory * access (and overall struct alignment). */ uint32_t message_size; /** * Has this message been transmitted to the service? * Only ever GNUNET_YES for the head of the queue. * Note that the overall struct should end at a * multiple of 64 bits. */ int was_transmitted; }; /** * Handle to the datastore service. */ struct GNUNET_DATASTORE_Handle { /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Current connection to the datastore service. */ struct GNUNET_CLIENT_Connection *client; /** * Handle for statistics. */ struct GNUNET_STATISTICS_Handle *stats; /** * Current transmit handle. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Current head of priority queue. */ struct GNUNET_DATASTORE_QueueEntry *queue_head; /** * Current tail of priority queue. */ struct GNUNET_DATASTORE_QueueEntry *queue_tail; /** * Task for trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * How quickly should we retry? Used for exponential back-off on * connect-errors. */ struct GNUNET_TIME_Relative retry_time; /** * Number of entries in the queue. */ unsigned int queue_size; /** * Number of results we're receiving for the current query * after application stopped to care. Used to determine when * to reset the connection. */ unsigned int result_count; /** * Are we currently trying to receive from the service? */ int in_receive; /** * We should ignore the next message(s) from the service. */ unsigned int skip_next_messages; }; /** * Connect to the datastore service. * * @param cfg configuration to use * @return handle to use to access the service */ struct GNUNET_DATASTORE_Handle * GNUNET_DATASTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_CLIENT_Connection *c; struct GNUNET_DATASTORE_Handle *h; c = GNUNET_CLIENT_connect ("datastore", cfg); if (c == NULL) return NULL; /* oops */ h = GNUNET_malloc (sizeof (struct GNUNET_DATASTORE_Handle) + GNUNET_SERVER_MAX_MESSAGE_SIZE - 1); h->client = c; h->cfg = cfg; h->stats = GNUNET_STATISTICS_create ("datastore-api", cfg); return h; } /** * Task used by 'transmit_drop' to disconnect the datastore. * * @param cls the datastore handle * @param tc scheduler context */ static void disconnect_after_drop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DATASTORE_Handle *h = cls; GNUNET_DATASTORE_disconnect (h, GNUNET_NO); } /** * Transmit DROP message to datastore service. * * @param cls the `struct GNUNET_DATASTORE_Handle` * @param size number of bytes that can be copied to @a buf * @param buf where to copy the drop message * @return number of bytes written to @a buf */ static size_t transmit_drop (void *cls, size_t size, void *buf) { struct GNUNET_DATASTORE_Handle *h = cls; struct GNUNET_MessageHeader *hdr; if (buf == NULL) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to transmit request to drop database.\n")); GNUNET_SCHEDULER_add_continuation (&disconnect_after_drop, h, GNUNET_SCHEDULER_REASON_PREREQ_DONE); return 0; } GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); hdr = buf; hdr->size = htons (sizeof (struct GNUNET_MessageHeader)); hdr->type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_DROP); GNUNET_SCHEDULER_add_continuation (&disconnect_after_drop, h, GNUNET_SCHEDULER_REASON_PREREQ_DONE); return sizeof (struct GNUNET_MessageHeader); } /** * Disconnect from the datastore service (and free * associated resources). * * @param h handle to the datastore * @param drop set to #GNUNET_YES to delete all data in datastore (!) */ void GNUNET_DATASTORE_disconnect (struct GNUNET_DATASTORE_Handle *h, int drop) { struct GNUNET_DATASTORE_QueueEntry *qe; LOG (GNUNET_ERROR_TYPE_DEBUG, "Datastore disconnect\n"); if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (h->client != NULL) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } while (NULL != (qe = h->queue_head)) { GNUNET_assert (NULL != qe->response_proc); qe->response_proc (h, NULL); } if (GNUNET_YES == drop) { h->client = GNUNET_CLIENT_connect ("datastore", h->cfg); if (h->client != NULL) { if (NULL != GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_MINUTES, GNUNET_YES, &transmit_drop, h)) return; GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } GNUNET_break (0); } GNUNET_STATISTICS_destroy (h->stats, GNUNET_NO); h->stats = NULL; GNUNET_free (h); } /** * A request has timed out (before being transmitted to the service). * * @param cls the `struct GNUNET_DATASTORE_QueueEntry` * @param tc scheduler context */ static void timeout_queue_entry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DATASTORE_QueueEntry *qe = cls; struct GNUNET_DATASTORE_Handle *h = qe->h; GNUNET_STATISTICS_update (h->stats, gettext_noop ("# queue entry timeouts"), 1, GNUNET_NO); qe->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_NO == qe->was_transmitted); LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout of request in datastore queue\n"); /* response_proc's expect request at the head of the queue! */ GNUNET_CONTAINER_DLL_remove (h->queue_head, h->queue_tail, qe); GNUNET_CONTAINER_DLL_insert (h->queue_head, h->queue_tail, qe); GNUNET_assert (h->queue_head == qe); qe->response_proc (qe->h, NULL); } /** * Create a new entry for our priority queue (and possibly discard other entires if * the queue is getting too long). * * @param h handle to the datastore * @param msize size of the message to queue * @param queue_priority priority of the entry * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout timeout for the operation * @param response_proc function to call with replies (can be NULL) * @param qc client context (NOT a closure for @a response_proc) * @return NULL if the queue is full */ static struct GNUNET_DATASTORE_QueueEntry * make_queue_entry (struct GNUNET_DATASTORE_Handle *h, size_t msize, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_CLIENT_MessageHandler response_proc, const union QueueContext *qc) { struct GNUNET_DATASTORE_QueueEntry *ret; struct GNUNET_DATASTORE_QueueEntry *pos; unsigned int c; c = 0; pos = h->queue_head; while ((pos != NULL) && (c < max_queue_size) && (pos->priority >= queue_priority)) { c++; pos = pos->next; } if (c >= max_queue_size) { GNUNET_STATISTICS_update (h->stats, gettext_noop ("# queue overflows"), 1, GNUNET_NO); return NULL; } ret = GNUNET_malloc (sizeof (struct GNUNET_DATASTORE_QueueEntry) + msize); ret->h = h; ret->response_proc = response_proc; ret->qc = *qc; ret->timeout = GNUNET_TIME_relative_to_absolute (timeout); ret->priority = queue_priority; ret->max_queue = max_queue_size; ret->message_size = msize; ret->was_transmitted = GNUNET_NO; if (pos == NULL) { /* append at the tail */ pos = h->queue_tail; } else { pos = pos->prev; /* do not insert at HEAD if HEAD query was already * transmitted and we are still receiving replies! */ if ((pos == NULL) && (h->queue_head->was_transmitted)) pos = h->queue_head; } c++; #if INSANE_STATISTICS GNUNET_STATISTICS_update (h->stats, gettext_noop ("# queue entries created"), 1, GNUNET_NO); #endif GNUNET_CONTAINER_DLL_insert_after (h->queue_head, h->queue_tail, pos, ret); h->queue_size++; ret->task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_queue_entry, ret); for (pos = ret->next; NULL != pos; pos = pos->next) { if ((pos->max_queue < h->queue_size) && (pos->was_transmitted == GNUNET_NO)) { GNUNET_assert (NULL != pos->response_proc); /* move 'pos' element to head so that it will be * killed on 'NULL' call below */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Dropping request from datastore queue\n"); /* response_proc's expect request at the head of the queue! */ GNUNET_CONTAINER_DLL_remove (h->queue_head, h->queue_tail, pos); GNUNET_CONTAINER_DLL_insert (h->queue_head, h->queue_tail, pos); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# Requests dropped from datastore queue"), 1, GNUNET_NO); GNUNET_assert (h->queue_head == pos); pos->response_proc (h, NULL); break; } } return ret; } /** * Process entries in the queue (or do nothing if we are already * doing so). * * @param h handle to the datastore */ static void process_queue (struct GNUNET_DATASTORE_Handle *h); /** * Try reconnecting to the datastore service. * * @param cls the `struct GNUNET_DATASTORE_Handle` * @param tc scheduler context */ static void try_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DATASTORE_Handle *h = cls; h->retry_time = GNUNET_TIME_STD_BACKOFF (h->retry_time); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; h->client = GNUNET_CLIENT_connect ("datastore", h->cfg); if (h->client == NULL) { LOG (GNUNET_ERROR_TYPE_ERROR, "DATASTORE reconnect failed (fatally)\n"); return; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# datastore connections (re)created"), 1, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_DEBUG, "Reconnected to DATASTORE\n"); process_queue (h); } /** * Disconnect from the service and then try reconnecting to the datastore service * after some delay. * * @param h handle to datastore to disconnect and reconnect */ static void do_disconnect (struct GNUNET_DATASTORE_Handle *h) { if (h->client == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "client NULL in disconnect, will not try to reconnect\n"); return; } GNUNET_CLIENT_disconnect (h->client); h->skip_next_messages = 0; h->client = NULL; h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->retry_time, &try_reconnect, h); } /** * Function called whenever we receive a message from * the service. Calls the appropriate handler. * * @param cls the 'struct GNUNET_DATASTORE_Handle' * @param msg the received message */ static void receive_cb (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_DATASTORE_Handle *h = cls; struct GNUNET_DATASTORE_QueueEntry *qe; h->in_receive = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving reply from datastore\n"); if (h->skip_next_messages > 0) { h->skip_next_messages--; process_queue (h); return; } if (NULL == (qe = h->queue_head)) { GNUNET_break (0); process_queue (h); return; } qe->response_proc (h, msg); } /** * Transmit request from queue to datastore service. * * @param cls the `struct GNUNET_DATASTORE_Handle` * @param size number of bytes that can be copied to @a buf * @param buf where to copy the drop message * @return number of bytes written to @a buf */ static size_t transmit_request (void *cls, size_t size, void *buf) { struct GNUNET_DATASTORE_Handle *h = cls; struct GNUNET_DATASTORE_QueueEntry *qe; size_t msize; h->th = NULL; if (NULL == (qe = h->queue_head)) return 0; /* no entry in queue */ if (buf == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to DATASTORE.\n"); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# transmission request failures"), 1, GNUNET_NO); do_disconnect (h); return 0; } if (size < (msize = qe->message_size)) { process_queue (h); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u byte request to DATASTORE\n", msize); memcpy (buf, &qe[1], msize); qe->was_transmitted = GNUNET_YES; GNUNET_SCHEDULER_cancel (qe->task); qe->task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_NO == h->in_receive); h->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &receive_cb, h, GNUNET_TIME_absolute_get_remaining (qe->timeout)); #if INSANE_STATISTICS GNUNET_STATISTICS_update (h->stats, gettext_noop ("# bytes sent to datastore"), 1, GNUNET_NO); #endif return msize; } /** * Process entries in the queue (or do nothing if we are already * doing so). * * @param h handle to the datastore */ static void process_queue (struct GNUNET_DATASTORE_Handle *h) { struct GNUNET_DATASTORE_QueueEntry *qe; if (NULL == (qe = h->queue_head)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue empty\n"); return; /* no entry in queue */ } if (qe->was_transmitted == GNUNET_YES) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Head request already transmitted\n"); return; /* waiting for replies */ } if (h->th != NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Pending transmission request\n"); return; /* request pending */ } if (h->client == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Not connected\n"); return; /* waiting for reconnect */ } if (GNUNET_YES == h->in_receive) { /* wait for response to previous query */ return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing %u byte request to DATASTORE\n", qe->message_size); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, qe->message_size, GNUNET_TIME_absolute_get_remaining (qe->timeout), GNUNET_YES, &transmit_request, h); GNUNET_assert (GNUNET_NO == h->in_receive); GNUNET_break (NULL != h->th); } /** * Dummy continuation used to do nothing (but be non-zero). * * @param cls closure * @param result result * @param min_expiration expiration time * @param emsg error message */ static void drop_status_cont (void *cls, int32_t result, struct GNUNET_TIME_Absolute min_expiration, const char *emsg) { /* do nothing */ } /** * Free a queue entry. Removes the given entry from the * queue and releases associated resources. Does NOT * call the callback. * * @param qe entry to free. */ static void free_queue_entry (struct GNUNET_DATASTORE_QueueEntry *qe) { struct GNUNET_DATASTORE_Handle *h = qe->h; GNUNET_CONTAINER_DLL_remove (h->queue_head, h->queue_tail, qe); if (qe->task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (qe->task); qe->task = GNUNET_SCHEDULER_NO_TASK; } h->queue_size--; qe->was_transmitted = GNUNET_SYSERR; /* use-after-free warning */ GNUNET_free (qe); } /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void process_status_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_DATASTORE_Handle *h = cls; struct GNUNET_DATASTORE_QueueEntry *qe; struct StatusContext rc; const struct StatusMessage *sm; const char *emsg; int32_t status; int was_transmitted; if (NULL == (qe = h->queue_head)) { GNUNET_break (0); do_disconnect (h); return; } rc = qe->qc.sc; if (msg == NULL) { was_transmitted = qe->was_transmitted; free_queue_entry (qe); if (was_transmitted == GNUNET_YES) do_disconnect (h); else process_queue (h); if (rc.cont != NULL) rc.cont (rc.cont_cls, GNUNET_SYSERR, GNUNET_TIME_UNIT_ZERO_ABS, _("Failed to receive status response from database.")); return; } GNUNET_assert (GNUNET_YES == qe->was_transmitted); free_queue_entry (qe); if ((ntohs (msg->size) < sizeof (struct StatusMessage)) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_STATUS)) { GNUNET_break (0); h->retry_time = GNUNET_TIME_UNIT_ZERO; do_disconnect (h); if (rc.cont != NULL) rc.cont (rc.cont_cls, GNUNET_SYSERR, GNUNET_TIME_UNIT_ZERO_ABS, _("Error reading response from datastore service")); return; } sm = (const struct StatusMessage *) msg; status = ntohl (sm->status); emsg = NULL; if (ntohs (msg->size) > sizeof (struct StatusMessage)) { emsg = (const char *) &sm[1]; if (emsg[ntohs (msg->size) - sizeof (struct StatusMessage) - 1] != '\0') { GNUNET_break (0); emsg = _("Invalid error message received from datastore service"); } } if ((status == GNUNET_SYSERR) && (emsg == NULL)) { GNUNET_break (0); emsg = _("Invalid error message received from datastore service"); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received status %d/%s\n", (int) status, emsg); GNUNET_STATISTICS_update (h->stats, gettext_noop ("# status messages received"), 1, GNUNET_NO); h->retry_time = GNUNET_TIME_UNIT_ZERO; process_queue (h); if (rc.cont != NULL) rc.cont (rc.cont_cls, status, GNUNET_TIME_absolute_ntoh (sm->min_expiration), emsg); } /** * Store an item in the datastore. If the item is already present, * the priorities are summed up and the higher expiration time and * lower anonymity level is used. * * @param h handle to the datastore * @param rid reservation ID to use (from "reserve"); use 0 if no * prior reservation was made * @param key key for the value * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication how often should the content be replicated to other peers? * @param expiration expiration time for the content * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout timeout for the operation * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_put (struct GNUNET_DATASTORE_Handle *h, uint32_t rid, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct DataMessage *dm; size_t msize; union QueueContext qc; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to put %u bytes of data under key `%s' for %s\n", size, GNUNET_h2s (key), GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (expiration), GNUNET_YES)); msize = sizeof (struct DataMessage) + size; GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); qc.sc.cont = cont; qc.sc.cont_cls = cont_cls; qe = make_queue_entry (h, msize, queue_priority, max_queue_size, timeout, &process_status_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for PUT\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# PUT requests executed"), 1, GNUNET_NO); dm = (struct DataMessage *) &qe[1]; dm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_PUT); dm->header.size = htons (msize); dm->rid = htonl (rid); dm->size = htonl ((uint32_t) size); dm->type = htonl (type); dm->priority = htonl (priority); dm->anonymity = htonl (anonymity); dm->replication = htonl (replication); dm->reserved = htonl (0); dm->uid = GNUNET_htonll (0); dm->expiration = GNUNET_TIME_absolute_hton (expiration); dm->key = *key; memcpy (&dm[1], data, size); process_queue (h); return qe; } /** * Reserve space in the datastore. This function should be used * to avoid "out of space" failures during a longer sequence of "put" * operations (for example, when a file is being inserted). * * @param h handle to the datastore * @param amount how much space (in bytes) should be reserved (for content only) * @param entries how many entries will be created (to calculate per-entry overhead) * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response (or before dying in queue) * @param cont continuation to call when done; "success" will be set to * a positive reservation value if space could be reserved. * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_reserve (struct GNUNET_DATASTORE_Handle *h, uint64_t amount, uint32_t entries, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct ReserveMessage *rm; union QueueContext qc; if (cont == NULL) cont = &drop_status_cont; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to reserve %llu bytes of data and %u entries\n", (unsigned long long) amount, (unsigned int) entries); qc.sc.cont = cont; qc.sc.cont_cls = cont_cls; qe = make_queue_entry (h, sizeof (struct ReserveMessage), queue_priority, max_queue_size, timeout, &process_status_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry to reserve\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# RESERVE requests executed"), 1, GNUNET_NO); rm = (struct ReserveMessage *) &qe[1]; rm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_RESERVE); rm->header.size = htons (sizeof (struct ReserveMessage)); rm->entries = htonl (entries); rm->amount = GNUNET_htonll (amount); process_queue (h); return qe; } /** * Signal that all of the data for which a reservation was made has * been stored and that whatever excess space might have been reserved * can now be released. * * @param h handle to the datastore * @param rid reservation ID (value of "success" in original continuation * from the "reserve" function). * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_release_reserve (struct GNUNET_DATASTORE_Handle *h, uint32_t rid, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct ReleaseReserveMessage *rrm; union QueueContext qc; if (cont == NULL) cont = &drop_status_cont; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to release reserve %d\n", rid); qc.sc.cont = cont; qc.sc.cont_cls = cont_cls; qe = make_queue_entry (h, sizeof (struct ReleaseReserveMessage), queue_priority, max_queue_size, timeout, &process_status_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry to release reserve\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# RELEASE RESERVE requests executed"), 1, GNUNET_NO); rrm = (struct ReleaseReserveMessage *) &qe[1]; rrm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_RELEASE_RESERVE); rrm->header.size = htons (sizeof (struct ReleaseReserveMessage)); rrm->rid = htonl (rid); process_queue (h); return qe; } /** * Update a value in the datastore. * * @param h handle to the datastore * @param uid identifier for the value * @param priority how much to increase the priority of the value * @param expiration new expiration value should be MAX of existing and this argument * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_update (struct GNUNET_DATASTORE_Handle *h, uint64_t uid, uint32_t priority, struct GNUNET_TIME_Absolute expiration, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct UpdateMessage *um; union QueueContext qc; if (cont == NULL) cont = &drop_status_cont; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to update entry %llu raising priority by %u and expiration to %s\n", uid, (unsigned int) priority, GNUNET_STRINGS_absolute_time_to_string (expiration)); qc.sc.cont = cont; qc.sc.cont_cls = cont_cls; qe = make_queue_entry (h, sizeof (struct UpdateMessage), queue_priority, max_queue_size, timeout, &process_status_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for UPDATE\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# UPDATE requests executed"), 1, GNUNET_NO); um = (struct UpdateMessage *) &qe[1]; um->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_UPDATE); um->header.size = htons (sizeof (struct UpdateMessage)); um->priority = htonl (priority); um->expiration = GNUNET_TIME_absolute_hton (expiration); um->uid = GNUNET_htonll (uid); process_queue (h); return qe; } /** * Explicitly remove some content from the database. * The @a cont continuation will be called with `status` * #GNUNET_OK" if content was removed, #GNUNET_NO * if no matching entry was found and #GNUNET_SYSERR * on all other types of errors. * * @param h handle to the datastore * @param key key for the value * @param size number of bytes in data * @param data content stored * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param cont continuation to call when done * @param cont_cls closure for @a cont * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel; note that even if NULL is returned, the callback will be invoked * (or rather, will already have been invoked) */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_remove (struct GNUNET_DATASTORE_Handle *h, const struct GNUNET_HashCode * key, size_t size, const void *data, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_ContinuationWithStatus cont, void *cont_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct DataMessage *dm; size_t msize; union QueueContext qc; if (cont == NULL) cont = &drop_status_cont; LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to remove %u bytes under key `%s'\n", size, GNUNET_h2s (key)); qc.sc.cont = cont; qc.sc.cont_cls = cont_cls; msize = sizeof (struct DataMessage) + size; GNUNET_assert (msize < GNUNET_SERVER_MAX_MESSAGE_SIZE); qe = make_queue_entry (h, msize, queue_priority, max_queue_size, timeout, &process_status_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for REMOVE\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# REMOVE requests executed"), 1, GNUNET_NO); dm = (struct DataMessage *) &qe[1]; dm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_REMOVE); dm->header.size = htons (msize); dm->rid = htonl (0); dm->size = htonl (size); dm->type = htonl (0); dm->priority = htonl (0); dm->anonymity = htonl (0); dm->uid = GNUNET_htonll (0); dm->expiration = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_ZERO_ABS); dm->key = *key; memcpy (&dm[1], data, size); process_queue (h); return qe; } /** * Type of a function to call when we receive a message * from the service. * * @param cls closure with the `struct GNUNET_DATASTORE_Handle *` * @param msg message received, NULL on timeout or fatal error */ static void process_result_message (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_DATASTORE_Handle *h = cls; struct GNUNET_DATASTORE_QueueEntry *qe; struct ResultContext rc; const struct DataMessage *dm; int was_transmitted; if (NULL == msg) { qe = h->queue_head; GNUNET_assert (NULL != qe); rc = qe->qc.rc; was_transmitted = qe->was_transmitted; free_queue_entry (qe); if (GNUNET_YES == was_transmitted) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to receive response from database.\n")); do_disconnect (h); } else { process_queue (h); } if (NULL != rc.proc) rc.proc (rc.proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_DATASTORE_DATA_END) { GNUNET_break (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader)); qe = h->queue_head; rc = qe->qc.rc; GNUNET_assert (GNUNET_YES == qe->was_transmitted); free_queue_entry (qe); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received end of result set, new queue size is %u\n", h->queue_size); h->retry_time = GNUNET_TIME_UNIT_ZERO; h->result_count = 0; process_queue (h); if (NULL != rc.proc) rc.proc (rc.proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } qe = h->queue_head; GNUNET_assert (NULL != qe); rc = qe->qc.rc; if (GNUNET_YES != qe->was_transmitted) { GNUNET_break (0); free_queue_entry (qe); h->retry_time = GNUNET_TIME_UNIT_ZERO; do_disconnect (h); if (rc.proc != NULL) rc.proc (rc.proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } if ((ntohs (msg->size) < sizeof (struct DataMessage)) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_DATASTORE_DATA) || (ntohs (msg->size) != sizeof (struct DataMessage) + ntohl (((const struct DataMessage *) msg)->size))) { GNUNET_break (0); free_queue_entry (qe); h->retry_time = GNUNET_TIME_UNIT_ZERO; do_disconnect (h); if (rc.proc != NULL) rc.proc (rc.proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } #if INSANE_STATISTICS GNUNET_STATISTICS_update (h->stats, gettext_noop ("# Results received"), 1, GNUNET_NO); #endif dm = (const struct DataMessage *) msg; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received result %llu with type %u and size %u with key %s\n", (unsigned long long) GNUNET_ntohll (dm->uid), ntohl (dm->type), ntohl (dm->size), GNUNET_h2s (&dm->key)); free_queue_entry (qe); h->retry_time = GNUNET_TIME_UNIT_ZERO; process_queue (h); if (rc.proc != NULL) rc.proc (rc.proc_cls, &dm->key, ntohl (dm->size), &dm[1], ntohl (dm->type), ntohl (dm->priority), ntohl (dm->anonymity), GNUNET_TIME_absolute_ntoh (dm->expiration), GNUNET_ntohll (dm->uid)); } /** * Get a random value from the datastore for content replication. * Returns a single, random value among those with the highest * replication score, lowering positive replication scores by one for * the chosen value (if only content with a replication score exists, * a random value is returned and replication scores are not changed). * * @param h handle to the datastore * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param proc function to call on a random value; it * will be called once with a value (if available) * and always once with a value of NULL. * @param proc_cls closure for @a proc * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_for_replication (struct GNUNET_DATASTORE_Handle *h, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct GNUNET_MessageHeader *m; union QueueContext qc; GNUNET_assert (NULL != proc); LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to get replication entry in %s\n", GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_YES)); qc.rc.proc = proc; qc.rc.proc_cls = proc_cls; qe = make_queue_entry (h, sizeof (struct GNUNET_MessageHeader), queue_priority, max_queue_size, timeout, &process_result_message, &qc); if (NULL == qe) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for GET REPLICATION\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# GET REPLICATION requests executed"), 1, GNUNET_NO); m = (struct GNUNET_MessageHeader *) &qe[1]; m->type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_GET_REPLICATION); m->size = htons (sizeof (struct GNUNET_MessageHeader)); process_queue (h); return qe; } /** * Get a single zero-anonymity value from the datastore. * * @param h handle to the datastore * @param offset offset of the result (modulo num-results); set to * a random 64-bit value initially; then increment by * one each time; detect that all results have been found by uid * being again the first uid ever returned. * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param type allowed type for the operation (never zero) * @param proc function to call on a random value; it * will be called once with a value (if available) * or with NULL if none value exists. * @param proc_cls closure for @a proc * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_zero_anonymity (struct GNUNET_DATASTORE_Handle *h, uint64_t offset, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, enum GNUNET_BLOCK_Type type, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct GetZeroAnonymityMessage *m; union QueueContext qc; GNUNET_assert (NULL != proc); GNUNET_assert (type != GNUNET_BLOCK_TYPE_ANY); LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to get %llu-th zero-anonymity entry of type %d in %s\n", (unsigned long long) offset, type, GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_YES)); qc.rc.proc = proc; qc.rc.proc_cls = proc_cls; qe = make_queue_entry (h, sizeof (struct GetZeroAnonymityMessage), queue_priority, max_queue_size, timeout, &process_result_message, &qc); if (NULL == qe) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not create queue entry for zero-anonymity procation\n"); return NULL; } GNUNET_STATISTICS_update (h->stats, gettext_noop ("# GET ZERO ANONYMITY requests executed"), 1, GNUNET_NO); m = (struct GetZeroAnonymityMessage *) &qe[1]; m->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_GET_ZERO_ANONYMITY); m->header.size = htons (sizeof (struct GetZeroAnonymityMessage)); m->type = htonl ((uint32_t) type); m->offset = GNUNET_htonll (offset); process_queue (h); return qe; } /** * Get a result for a particular key from the datastore. The processor * will only be called once. * * @param h handle to the datastore * @param offset offset of the result (modulo num-results); set to * a random 64-bit value initially; then increment by * one each time; detect that all results have been found by uid * being again the first uid ever returned. * @param key maybe NULL (to match all entries) * @param type desired type, 0 for any * @param queue_priority ranking of this request in the priority queue * @param max_queue_size at what queue size should this request be dropped * (if other requests of higher priority are in the queue) * @param timeout how long to wait at most for a response * @param proc function to call on each matching value; * will be called once with a NULL value at the end * @param proc_cls closure for @a proc * @return NULL if the entry was not queued, otherwise a handle that can be used to * cancel */ struct GNUNET_DATASTORE_QueueEntry * GNUNET_DATASTORE_get_key (struct GNUNET_DATASTORE_Handle *h, uint64_t offset, const struct GNUNET_HashCode * key, enum GNUNET_BLOCK_Type type, unsigned int queue_priority, unsigned int max_queue_size, struct GNUNET_TIME_Relative timeout, GNUNET_DATASTORE_DatumProcessor proc, void *proc_cls) { struct GNUNET_DATASTORE_QueueEntry *qe; struct GetMessage *gm; union QueueContext qc; GNUNET_assert (NULL != proc); LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to look for data of type %u under key `%s'\n", (unsigned int) type, GNUNET_h2s (key)); qc.rc.proc = proc; qc.rc.proc_cls = proc_cls; qe = make_queue_entry (h, sizeof (struct GetMessage), queue_priority, max_queue_size, timeout, &process_result_message, &qc); if (qe == NULL) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Could not queue request for `%s'\n", GNUNET_h2s (key)); return NULL; } #if INSANE_STATISTICS GNUNET_STATISTICS_update (h->stats, gettext_noop ("# GET requests executed"), 1, GNUNET_NO); #endif gm = (struct GetMessage *) &qe[1]; gm->header.type = htons (GNUNET_MESSAGE_TYPE_DATASTORE_GET); gm->type = htonl (type); gm->offset = GNUNET_htonll (offset); if (key != NULL) { gm->header.size = htons (sizeof (struct GetMessage)); gm->key = *key; } else { gm->header.size = htons (sizeof (struct GetMessage) - sizeof (struct GNUNET_HashCode)); } process_queue (h); return qe; } /** * Cancel a datastore operation. The final callback from the * operation must not have been done yet. * * @param qe operation to cancel */ void GNUNET_DATASTORE_cancel (struct GNUNET_DATASTORE_QueueEntry *qe) { struct GNUNET_DATASTORE_Handle *h; GNUNET_assert (GNUNET_SYSERR != qe->was_transmitted); h = qe->h; LOG (GNUNET_ERROR_TYPE_DEBUG, "Pending DATASTORE request %p cancelled (%d, %d)\n", qe, qe->was_transmitted, h->queue_head == qe); if (GNUNET_YES == qe->was_transmitted) { free_queue_entry (qe); h->skip_next_messages++; return; } free_queue_entry (qe); process_queue (h); } /* end of datastore_api.c */ gnunet-0.10.1/src/datastore/test_plugin_datastore_data_heap.conf0000644000175000017500000000017412225230043022022 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-datastore-plugin-heap/ [datastore] DATABASE = heap gnunet-0.10.1/src/datastore/test_plugin_datastore.c0000644000175000017500000002426312255010512017336 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file test_plugin_datastore.c * @brief Test database plugin directly, calling each API function once * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_datastore_plugin.h" #include "gnunet_testing_lib.h" /** * Number of put operations to perform. */ #define PUT_10 10 static unsigned long long stored_bytes; static unsigned long long stored_entries; static unsigned long long stored_ops; static const char *plugin_name; static int ok; enum RunPhase { RP_ERROR = 0, RP_PUT, RP_GET, RP_UPDATE, RP_ITER_ZERO, RP_REPL_GET, RP_EXPI_GET, RP_DROP }; struct CpsRunContext { const struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_DATASTORE_PluginFunctions *api; enum RunPhase phase; unsigned int cnt; unsigned int i; uint64_t offset; }; /** * Function called by plugins to notify us about a * change in their disk utilization. * * @param cls closure (NULL) * @param delta change in disk utilization, * 0 for "reset to empty" */ static void disk_utilization_change_cb (void *cls, int delta) { /* do nothing */ } static void gen_key (int i, struct GNUNET_HashCode * key) { memset (key, 0, sizeof (struct GNUNET_HashCode)); key->bits[0] = (unsigned int) i; GNUNET_CRYPTO_hash (key, sizeof (struct GNUNET_HashCode), key); } static void put_value (struct GNUNET_DATASTORE_PluginFunctions *api, int i, int k) { char value[65536]; size_t size; struct GNUNET_HashCode key; char *msg; unsigned int prio; /* most content is 32k */ size = 32 * 1024; if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16) == 0) /* but some of it is less! */ size = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 32 * 1024); size = size - (size & 7); /* always multiple of 8 */ /* generate random key */ gen_key (i, &key); memset (value, i, size); if (i > 255) memset (value, i - 255, size / 2); value[0] = k; msg = NULL; prio = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "putting type %u, anon %u under key %s\n", i + 1, i, GNUNET_h2s (&key)); if (GNUNET_OK != api->put (api->cls, &key, size, value, i + 1 /* type */ , prio, i /* anonymity */ , 0 /* replication */ , GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 60 * 60 * 60 * 1000 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000))), &msg)) { FPRINTF (stderr, "ERROR: `%s'\n", msg); GNUNET_free_non_null (msg); return; } stored_bytes += size; stored_ops++; stored_entries++; } static void test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static uint64_t guid; static int iterate_one_shot (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; GNUNET_assert (key != NULL); guid = uid; crc->phase++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found result type=%u, priority=%u, size=%u, expire=%s, key %s\n", type, priority, size, GNUNET_STRINGS_absolute_time_to_string (expiration), GNUNET_h2s (key)); GNUNET_SCHEDULER_add_now (&test, crc); return GNUNET_OK; } /** * Function called when the service shuts * down. Unloads our datastore plugin. * * @param api api to unload * @param cfg configuration to use */ static void unload_plugin (struct GNUNET_DATASTORE_PluginFunctions *api, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *name; char *libname; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "DATASTORE", "DATABASE", &name)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No `%s' specified for `%s' in configuration!\n"), "DATABASE", "DATASTORE"); return; } GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", name); GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api)); GNUNET_free (libname); GNUNET_free (name); } /** * Last task run during shutdown. Disconnects us from * the transport and core. */ static void cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CpsRunContext *crc = cls; unload_plugin (crc->api, crc->cfg); GNUNET_free (crc); } static void test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CpsRunContext *crc = cls; int j; unsigned long long os; unsigned long long cs; struct GNUNET_HashCode key; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test aborted.\n"); crc->phase = RP_ERROR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In phase %d, iteration %u\n", crc->phase, crc->cnt); switch (crc->phase) { case RP_ERROR: ok = 1; GNUNET_break (0); crc->api->drop (crc->api->cls); GNUNET_SCHEDULER_add_now (&cleaning_task, crc); break; case RP_PUT: os = 0; for (j = 0; j < PUT_10; j++) { put_value (crc->api, j, crc->i); cs = crc->api->estimate_size (crc->api->cls); GNUNET_assert (os <= cs); os = cs; } crc->phase++; GNUNET_SCHEDULER_add_now (&test, crc); break; case RP_GET: if (crc->cnt == 1) { crc->cnt = 0; crc->phase++; GNUNET_SCHEDULER_add_now (&test, crc); break; } gen_key (5, &key); crc->api->get_key (crc->api->cls, crc->offset++, &key, NULL, GNUNET_BLOCK_TYPE_ANY, &iterate_one_shot, crc); break; case RP_UPDATE: GNUNET_assert (GNUNET_OK == crc->api->update (crc->api->cls, guid, 1, GNUNET_TIME_UNIT_ZERO_ABS, NULL)); crc->phase++; GNUNET_SCHEDULER_add_now (&test, crc); break; case RP_ITER_ZERO: if (crc->cnt == 1) { crc->cnt = 0; crc->phase++; GNUNET_SCHEDULER_add_now (&test, crc); break; } crc->api->get_zero_anonymity (crc->api->cls, 0, 1, &iterate_one_shot, crc); break; case RP_REPL_GET: crc->api->get_replication (crc->api->cls, &iterate_one_shot, crc); break; case RP_EXPI_GET: crc->api->get_expiration (crc->api->cls, &iterate_one_shot, crc); break; case RP_DROP: crc->api->drop (crc->api->cls); GNUNET_SCHEDULER_add_now (&cleaning_task, crc); break; } } /** * Load the datastore plugin. */ static struct GNUNET_DATASTORE_PluginFunctions * load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg) { static struct GNUNET_DATASTORE_PluginEnvironment env; struct GNUNET_DATASTORE_PluginFunctions *ret; char *name; char *libname; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "DATASTORE", "DATABASE", &name)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No `%s' specified for `%s' in configuration!\n"), "DATABASE", "DATASTORE"); return NULL; } env.cfg = cfg; env.duc = &disk_utilization_change_cb; env.cls = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' datastore plugin\n"), name); GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", name); if (NULL == (ret = GNUNET_PLUGIN_load (libname, &env))) { FPRINTF (stderr, "Failed to load plugin `%s'!\n", name); GNUNET_free (libname); GNUNET_free (name); return NULL; } GNUNET_free (libname); GNUNET_free (name); return ret; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_DATASTORE_PluginFunctions *api; struct CpsRunContext *crc; api = load_plugin (c); if (api == NULL) { FPRINTF (stderr, "%s", "Could not initialize plugin, assuming database not configured. Test not run!\n"); return; } crc = GNUNET_new (struct CpsRunContext); crc->api = api; crc->cfg = c; crc->phase = RP_PUT; GNUNET_SCHEDULER_add_now (&test, crc); } int main (int argc, char *argv[]) { char dir_name[128]; char cfg_name[128]; char *const xargv[] = { "test-plugin-datastore", "-c", cfg_name, NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; /* determine name of plugin to use */ plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (dir_name, sizeof (dir_name), "/tmp/test-gnunet-datastore-plugin-%s", plugin_name); GNUNET_DISK_directory_remove (dir_name); GNUNET_log_setup ("test-plugin-datastore", "WARNING", NULL); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_plugin_datastore_data_%s.conf", plugin_name); GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "test-plugin-datastore", "nohelp", options, &run, NULL); if (0 != ok) FPRINTF (stderr, "Missed some testcases: %u\n", ok); GNUNET_DISK_directory_remove (dir_name); return ok; } /* end of test_plugin_datastore.c */ gnunet-0.10.1/src/datastore/Makefile.in0000644000175000017500000025557512320752060014654 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-datastore$(EXEEXT) libexec_PROGRAMS = gnunet-service-datastore$(EXEEXT) check_PROGRAMS = test_datastore_api_heap$(EXEEXT) \ test_datastore_api_management_heap$(EXEEXT) \ perf_datastore_api_heap$(EXEEXT) \ perf_plugin_datastore_heap$(EXEEXT) \ test_plugin_datastore_heap$(EXEEXT) $(am__EXEEXT_2) \ $(am__EXEEXT_4) $(am__EXEEXT_6) subdir = src/datastore DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/datastore.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = datastore.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunet_plugin_datastore_heap_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunet_plugin_datastore_heap_la_OBJECTS = \ plugin_datastore_heap.lo libgnunet_plugin_datastore_heap_la_OBJECTS = \ $(am_libgnunet_plugin_datastore_heap_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_datastore_heap_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datastore_heap_la_LDFLAGS) $(LDFLAGS) -o $@ libgnunet_plugin_datastore_mysql_la_DEPENDENCIES = \ $(top_builddir)/src/mysql/libgnunetmysql.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunet_plugin_datastore_mysql_la_OBJECTS = \ libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.lo libgnunet_plugin_datastore_mysql_la_OBJECTS = \ $(am_libgnunet_plugin_datastore_mysql_la_OBJECTS) libgnunet_plugin_datastore_mysql_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datastore_mysql_la_LDFLAGS) $(LDFLAGS) -o \ $@ @HAVE_MYSQL_TRUE@am_libgnunet_plugin_datastore_mysql_la_rpath = \ @HAVE_MYSQL_TRUE@ -rpath $(plugindir) libgnunet_plugin_datastore_postgres_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunet_plugin_datastore_postgres_la_OBJECTS = libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.lo libgnunet_plugin_datastore_postgres_la_OBJECTS = \ $(am_libgnunet_plugin_datastore_postgres_la_OBJECTS) libgnunet_plugin_datastore_postgres_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datastore_postgres_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_POSTGRES_TRUE@am_libgnunet_plugin_datastore_postgres_la_rpath = \ @HAVE_POSTGRES_TRUE@ -rpath $(plugindir) libgnunet_plugin_datastore_sqlite_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunet_plugin_datastore_sqlite_la_OBJECTS = \ plugin_datastore_sqlite.lo libgnunet_plugin_datastore_sqlite_la_OBJECTS = \ $(am_libgnunet_plugin_datastore_sqlite_la_OBJECTS) libgnunet_plugin_datastore_sqlite_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datastore_sqlite_la_LDFLAGS) $(LDFLAGS) -o \ $@ @HAVE_SQLITE_TRUE@am_libgnunet_plugin_datastore_sqlite_la_rpath = \ @HAVE_SQLITE_TRUE@ -rpath $(plugindir) libgnunet_plugin_datastore_template_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunet_plugin_datastore_template_la_OBJECTS = \ plugin_datastore_template.lo libgnunet_plugin_datastore_template_la_OBJECTS = \ $(am_libgnunet_plugin_datastore_template_la_OBJECTS) libgnunet_plugin_datastore_template_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_datastore_template_la_LDFLAGS) $(LDFLAGS) \ -o $@ libgnunetdatastore_la_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetdatastore_la_OBJECTS = datastore_api.lo libgnunetdatastore_la_OBJECTS = $(am_libgnunetdatastore_la_OBJECTS) libgnunetdatastore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetdatastore_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_BENCHMARKS_TRUE@@HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_1 = perf_datastore_api_sqlite$(EXEEXT) \ @HAVE_BENCHMARKS_TRUE@@HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ perf_plugin_datastore_sqlite$(EXEEXT) @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_2 = test_datastore_api_sqlite$(EXEEXT) \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_management_sqlite$(EXEEXT) \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ test_plugin_datastore_sqlite$(EXEEXT) \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ $(am__EXEEXT_1) @HAVE_BENCHMARKS_TRUE@@HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_3 = perf_datastore_api_mysql$(EXEEXT) \ @HAVE_BENCHMARKS_TRUE@@HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ perf_plugin_datastore_mysql$(EXEEXT) @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_4 = test_datastore_api_mysql$(EXEEXT) \ @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_management_mysql$(EXEEXT) \ @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ test_plugin_datastore_mysql$(EXEEXT) \ @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ $(am__EXEEXT_3) @HAVE_BENCHMARKS_TRUE@@HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_5 = perf_datastore_api_postgres$(EXEEXT) \ @HAVE_BENCHMARKS_TRUE@@HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ perf_plugin_datastore_postgres$(EXEEXT) @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@am__EXEEXT_6 = test_datastore_api_postgres$(EXEEXT) \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_management_postgres$(EXEEXT) \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ test_plugin_datastore_postgres$(EXEEXT) \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ $(am__EXEEXT_5) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_datastore_OBJECTS = gnunet-datastore.$(OBJEXT) gnunet_datastore_OBJECTS = $(am_gnunet_datastore_OBJECTS) am_gnunet_service_datastore_OBJECTS = \ gnunet-service-datastore.$(OBJEXT) gnunet_service_datastore_OBJECTS = \ $(am_gnunet_service_datastore_OBJECTS) gnunet_service_datastore_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_perf_datastore_api_heap_OBJECTS = perf_datastore_api.$(OBJEXT) perf_datastore_api_heap_OBJECTS = \ $(am_perf_datastore_api_heap_OBJECTS) perf_datastore_api_heap_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_datastore_api_mysql_OBJECTS = perf_datastore_api.$(OBJEXT) perf_datastore_api_mysql_OBJECTS = \ $(am_perf_datastore_api_mysql_OBJECTS) perf_datastore_api_mysql_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_datastore_api_postgres_OBJECTS = perf_datastore_api.$(OBJEXT) perf_datastore_api_postgres_OBJECTS = \ $(am_perf_datastore_api_postgres_OBJECTS) perf_datastore_api_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_datastore_api_sqlite_OBJECTS = perf_datastore_api.$(OBJEXT) perf_datastore_api_sqlite_OBJECTS = \ $(am_perf_datastore_api_sqlite_OBJECTS) perf_datastore_api_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_plugin_datastore_heap_OBJECTS = \ perf_plugin_datastore.$(OBJEXT) perf_plugin_datastore_heap_OBJECTS = \ $(am_perf_plugin_datastore_heap_OBJECTS) perf_plugin_datastore_heap_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_plugin_datastore_mysql_OBJECTS = \ perf_plugin_datastore.$(OBJEXT) perf_plugin_datastore_mysql_OBJECTS = \ $(am_perf_plugin_datastore_mysql_OBJECTS) perf_plugin_datastore_mysql_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_plugin_datastore_postgres_OBJECTS = \ perf_plugin_datastore.$(OBJEXT) perf_plugin_datastore_postgres_OBJECTS = \ $(am_perf_plugin_datastore_postgres_OBJECTS) perf_plugin_datastore_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_perf_plugin_datastore_sqlite_OBJECTS = \ perf_plugin_datastore.$(OBJEXT) perf_plugin_datastore_sqlite_OBJECTS = \ $(am_perf_plugin_datastore_sqlite_OBJECTS) perf_plugin_datastore_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datastore_api_heap_OBJECTS = test_datastore_api.$(OBJEXT) test_datastore_api_heap_OBJECTS = \ $(am_test_datastore_api_heap_OBJECTS) test_datastore_api_heap_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datastore_api_management_heap_OBJECTS = \ test_datastore_api_management.$(OBJEXT) test_datastore_api_management_heap_OBJECTS = \ $(am_test_datastore_api_management_heap_OBJECTS) test_datastore_api_management_heap_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datastore_api_management_mysql_OBJECTS = \ test_datastore_api_management.$(OBJEXT) test_datastore_api_management_mysql_OBJECTS = \ $(am_test_datastore_api_management_mysql_OBJECTS) test_datastore_api_management_mysql_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datastore_api_management_postgres_OBJECTS = \ test_datastore_api_management.$(OBJEXT) test_datastore_api_management_postgres_OBJECTS = \ $(am_test_datastore_api_management_postgres_OBJECTS) test_datastore_api_management_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datastore_api_management_sqlite_OBJECTS = \ test_datastore_api_management.$(OBJEXT) test_datastore_api_management_sqlite_OBJECTS = \ $(am_test_datastore_api_management_sqlite_OBJECTS) test_datastore_api_management_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datastore_api_mysql_OBJECTS = test_datastore_api.$(OBJEXT) test_datastore_api_mysql_OBJECTS = \ $(am_test_datastore_api_mysql_OBJECTS) test_datastore_api_mysql_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datastore_api_postgres_OBJECTS = test_datastore_api.$(OBJEXT) test_datastore_api_postgres_OBJECTS = \ $(am_test_datastore_api_postgres_OBJECTS) test_datastore_api_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_datastore_api_sqlite_OBJECTS = test_datastore_api.$(OBJEXT) test_datastore_api_sqlite_OBJECTS = \ $(am_test_datastore_api_sqlite_OBJECTS) test_datastore_api_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_datastore_heap_OBJECTS = \ test_plugin_datastore.$(OBJEXT) test_plugin_datastore_heap_OBJECTS = \ $(am_test_plugin_datastore_heap_OBJECTS) test_plugin_datastore_heap_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_datastore_mysql_OBJECTS = \ test_plugin_datastore.$(OBJEXT) test_plugin_datastore_mysql_OBJECTS = \ $(am_test_plugin_datastore_mysql_OBJECTS) test_plugin_datastore_mysql_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_datastore_postgres_OBJECTS = \ test_plugin_datastore.$(OBJEXT) test_plugin_datastore_postgres_OBJECTS = \ $(am_test_plugin_datastore_postgres_OBJECTS) test_plugin_datastore_postgres_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_plugin_datastore_sqlite_OBJECTS = \ test_plugin_datastore.$(OBJEXT) test_plugin_datastore_sqlite_OBJECTS = \ $(am_test_plugin_datastore_sqlite_OBJECTS) test_plugin_datastore_sqlite_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_datastore_heap_la_SOURCES) \ $(libgnunet_plugin_datastore_mysql_la_SOURCES) \ $(libgnunet_plugin_datastore_postgres_la_SOURCES) \ $(libgnunet_plugin_datastore_sqlite_la_SOURCES) \ $(libgnunet_plugin_datastore_template_la_SOURCES) \ $(libgnunetdatastore_la_SOURCES) $(gnunet_datastore_SOURCES) \ $(gnunet_service_datastore_SOURCES) \ $(perf_datastore_api_heap_SOURCES) \ $(perf_datastore_api_mysql_SOURCES) \ $(perf_datastore_api_postgres_SOURCES) \ $(perf_datastore_api_sqlite_SOURCES) \ $(perf_plugin_datastore_heap_SOURCES) \ $(perf_plugin_datastore_mysql_SOURCES) \ $(perf_plugin_datastore_postgres_SOURCES) \ $(perf_plugin_datastore_sqlite_SOURCES) \ $(test_datastore_api_heap_SOURCES) \ $(test_datastore_api_management_heap_SOURCES) \ $(test_datastore_api_management_mysql_SOURCES) \ $(test_datastore_api_management_postgres_SOURCES) \ $(test_datastore_api_management_sqlite_SOURCES) \ $(test_datastore_api_mysql_SOURCES) \ $(test_datastore_api_postgres_SOURCES) \ $(test_datastore_api_sqlite_SOURCES) \ $(test_plugin_datastore_heap_SOURCES) \ $(test_plugin_datastore_mysql_SOURCES) \ $(test_plugin_datastore_postgres_SOURCES) \ $(test_plugin_datastore_sqlite_SOURCES) DIST_SOURCES = $(libgnunet_plugin_datastore_heap_la_SOURCES) \ $(libgnunet_plugin_datastore_mysql_la_SOURCES) \ $(libgnunet_plugin_datastore_postgres_la_SOURCES) \ $(libgnunet_plugin_datastore_sqlite_la_SOURCES) \ $(libgnunet_plugin_datastore_template_la_SOURCES) \ $(libgnunetdatastore_la_SOURCES) $(gnunet_datastore_SOURCES) \ $(gnunet_service_datastore_SOURCES) \ $(perf_datastore_api_heap_SOURCES) \ $(perf_datastore_api_mysql_SOURCES) \ $(perf_datastore_api_postgres_SOURCES) \ $(perf_datastore_api_sqlite_SOURCES) \ $(perf_plugin_datastore_heap_SOURCES) \ $(perf_plugin_datastore_mysql_SOURCES) \ $(perf_plugin_datastore_postgres_SOURCES) \ $(perf_plugin_datastore_sqlite_SOURCES) \ $(test_datastore_api_heap_SOURCES) \ $(test_datastore_api_management_heap_SOURCES) \ $(test_datastore_api_management_mysql_SOURCES) \ $(test_datastore_api_management_postgres_SOURCES) \ $(test_datastore_api_management_sqlite_SOURCES) \ $(test_datastore_api_mysql_SOURCES) \ $(test_datastore_api_postgres_SOURCES) \ $(test_datastore_api_sqlite_SOURCES) \ $(test_plugin_datastore_heap_SOURCES) \ $(test_plugin_datastore_mysql_SOURCES) \ $(test_plugin_datastore_postgres_SOURCES) \ $(test_plugin_datastore_sqlite_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ datastore.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIBS = -lgcov lib_LTLIBRARIES = \ libgnunetdatastore.la libgnunetdatastore_la_SOURCES = \ datastore_api.c datastore.h libgnunetdatastore_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetdatastore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:0:0 gnunet_service_datastore_SOURCES = \ gnunet-service-datastore.c gnunet_service_datastore_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_datastore_SOURCES = \ gnunet-datastore.c gnunet_datastore_LDADD = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_datastore_DEPENDENCIES = \ libgnunetdatastore.la @HAVE_MYSQL_TRUE@MYSQL_PLUGIN = libgnunet_plugin_datastore_mysql.la @HAVE_BENCHMARKS_TRUE@@HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@MYSQL_BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@@HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ perf_datastore_api_mysql \ @HAVE_BENCHMARKS_TRUE@@HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ perf_plugin_datastore_mysql @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@MYSQL_TESTS = \ @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_mysql \ @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_management_mysql \ @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ test_plugin_datastore_mysql \ @HAVE_MYSQL_TRUE@@HAVE_TESTING_TRUE@ $(MYSQL_BENCHMARKS) @HAVE_SQLITE_TRUE@SQLITE_PLUGIN = libgnunet_plugin_datastore_sqlite.la @HAVE_BENCHMARKS_TRUE@@HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@SQLITE_BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@@HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ perf_datastore_api_sqlite \ @HAVE_BENCHMARKS_TRUE@@HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ perf_plugin_datastore_sqlite @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@SQLITE_TESTS = \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_sqlite \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_management_sqlite \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ test_plugin_datastore_sqlite \ @HAVE_SQLITE_TRUE@@HAVE_TESTING_TRUE@ $(SQLITE_BENCHMARKS) @HAVE_POSTGRES_TRUE@POSTGRES_PLUGIN = libgnunet_plugin_datastore_postgres.la @HAVE_BENCHMARKS_TRUE@@HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@POSTGRES_BENCHMARKS = \ @HAVE_BENCHMARKS_TRUE@@HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ perf_datastore_api_postgres \ @HAVE_BENCHMARKS_TRUE@@HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ perf_plugin_datastore_postgres @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@POSTGRES_TESTS = \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_postgres \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ test_datastore_api_management_postgres \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ test_plugin_datastore_postgres \ @HAVE_POSTGRES_TRUE@@HAVE_TESTING_TRUE@ $(POSTGRES_BENCHMARKS) plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ $(MYSQL_PLUGIN) \ $(POSTGRES_PLUGIN) \ libgnunet_plugin_datastore_heap.la \ libgnunet_plugin_datastore_template.la libgnunet_plugin_datastore_sqlite_la_SOURCES = \ plugin_datastore_sqlite.c libgnunet_plugin_datastore_sqlite_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_datastore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_datastore_heap_la_SOURCES = \ plugin_datastore_heap.c libgnunet_plugin_datastore_heap_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) libgnunet_plugin_datastore_heap_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_datastore_mysql_la_SOURCES = \ plugin_datastore_mysql.c libgnunet_plugin_datastore_mysql_la_LIBADD = \ $(top_builddir)/src/mysql/libgnunetmysql.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) $(Z_LIBS) -lmysqlclient libgnunet_plugin_datastore_mysql_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient libgnunet_plugin_datastore_mysql_la_CPPFLAGS = \ $(MYSQL_CPPFLAGS) $(AM_CPPFLAGS) libgnunet_plugin_datastore_postgres_la_SOURCES = \ plugin_datastore_postgres.c libgnunet_plugin_datastore_postgres_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq libgnunet_plugin_datastore_postgres_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) $(POSTGRES_LDFLAGS) -lpq libgnunet_plugin_datastore_postgres_la_CPPFLAGS = \ $(POSTGRES_CPPFLAGS) $(AM_CPPFLAGS) libgnunet_plugin_datastore_template_la_SOURCES = \ plugin_datastore_template.c libgnunet_plugin_datastore_template_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) libgnunet_plugin_datastore_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_datastore_api_heap_SOURCES = \ test_datastore_api.c test_datastore_api_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_management_heap_SOURCES = \ test_datastore_api_management.c test_datastore_api_management_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datastore_api_heap_SOURCES = \ perf_datastore_api.c perf_datastore_api_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_plugin_datastore_heap_SOURCES = \ perf_plugin_datastore.c perf_plugin_datastore_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_datastore_heap_SOURCES = \ test_plugin_datastore.c test_plugin_datastore_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_sqlite_SOURCES = \ test_datastore_api.c test_datastore_api_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_management_sqlite_SOURCES = \ test_datastore_api_management.c test_datastore_api_management_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datastore_api_sqlite_SOURCES = \ perf_datastore_api.c perf_datastore_api_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_plugin_datastore_sqlite_SOURCES = \ perf_plugin_datastore.c perf_plugin_datastore_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_datastore_sqlite_SOURCES = \ test_plugin_datastore.c test_plugin_datastore_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_mysql_SOURCES = \ test_datastore_api.c test_datastore_api_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_management_mysql_SOURCES = \ test_datastore_api_management.c test_datastore_api_management_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datastore_api_mysql_SOURCES = \ perf_datastore_api.c perf_datastore_api_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_datastore_mysql_SOURCES = \ test_plugin_datastore.c test_plugin_datastore_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_plugin_datastore_mysql_SOURCES = \ perf_plugin_datastore.c perf_plugin_datastore_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_postgres_SOURCES = \ test_datastore_api.c test_datastore_api_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_management_postgres_SOURCES = \ test_datastore_api_management.c test_datastore_api_management_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datastore_api_postgres_SOURCES = \ perf_datastore_api.c perf_datastore_api_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_datastore_postgres_SOURCES = \ test_plugin_datastore.c test_plugin_datastore_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_plugin_datastore_postgres_SOURCES = \ perf_plugin_datastore.c perf_plugin_datastore_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_defaults.conf \ test_datastore_api_data_sqlite.conf \ perf_plugin_datastore_data_sqlite.conf \ test_plugin_datastore_data_sqlite.conf \ test_datastore_api_data_heap.conf \ perf_plugin_datastore_data_heap.conf \ test_plugin_datastore_data_heap.conf \ test_datastore_api_data_mysql.conf \ perf_plugin_datastore_data_mysql.conf \ test_plugin_datastore_data_mysql.conf \ test_datastore_api_data_postgres.conf \ perf_plugin_datastore_data_postgres.conf \ test_plugin_datastore_data_postgres.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/datastore/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/datastore/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): datastore.conf: $(top_builddir)/config.status $(srcdir)/datastore.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_datastore_heap.la: $(libgnunet_plugin_datastore_heap_la_OBJECTS) $(libgnunet_plugin_datastore_heap_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datastore_heap_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datastore_heap_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_datastore_heap_la_OBJECTS) $(libgnunet_plugin_datastore_heap_la_LIBADD) $(LIBS) libgnunet_plugin_datastore_mysql.la: $(libgnunet_plugin_datastore_mysql_la_OBJECTS) $(libgnunet_plugin_datastore_mysql_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datastore_mysql_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datastore_mysql_la_LINK) $(am_libgnunet_plugin_datastore_mysql_la_rpath) $(libgnunet_plugin_datastore_mysql_la_OBJECTS) $(libgnunet_plugin_datastore_mysql_la_LIBADD) $(LIBS) libgnunet_plugin_datastore_postgres.la: $(libgnunet_plugin_datastore_postgres_la_OBJECTS) $(libgnunet_plugin_datastore_postgres_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datastore_postgres_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datastore_postgres_la_LINK) $(am_libgnunet_plugin_datastore_postgres_la_rpath) $(libgnunet_plugin_datastore_postgres_la_OBJECTS) $(libgnunet_plugin_datastore_postgres_la_LIBADD) $(LIBS) libgnunet_plugin_datastore_sqlite.la: $(libgnunet_plugin_datastore_sqlite_la_OBJECTS) $(libgnunet_plugin_datastore_sqlite_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datastore_sqlite_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datastore_sqlite_la_LINK) $(am_libgnunet_plugin_datastore_sqlite_la_rpath) $(libgnunet_plugin_datastore_sqlite_la_OBJECTS) $(libgnunet_plugin_datastore_sqlite_la_LIBADD) $(LIBS) libgnunet_plugin_datastore_template.la: $(libgnunet_plugin_datastore_template_la_OBJECTS) $(libgnunet_plugin_datastore_template_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_datastore_template_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_datastore_template_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_datastore_template_la_OBJECTS) $(libgnunet_plugin_datastore_template_la_LIBADD) $(LIBS) libgnunetdatastore.la: $(libgnunetdatastore_la_OBJECTS) $(libgnunetdatastore_la_DEPENDENCIES) $(EXTRA_libgnunetdatastore_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetdatastore_la_LINK) -rpath $(libdir) $(libgnunetdatastore_la_OBJECTS) $(libgnunetdatastore_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-datastore$(EXEEXT): $(gnunet_datastore_OBJECTS) $(gnunet_datastore_DEPENDENCIES) $(EXTRA_gnunet_datastore_DEPENDENCIES) @rm -f gnunet-datastore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_datastore_OBJECTS) $(gnunet_datastore_LDADD) $(LIBS) gnunet-service-datastore$(EXEEXT): $(gnunet_service_datastore_OBJECTS) $(gnunet_service_datastore_DEPENDENCIES) $(EXTRA_gnunet_service_datastore_DEPENDENCIES) @rm -f gnunet-service-datastore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_datastore_OBJECTS) $(gnunet_service_datastore_LDADD) $(LIBS) perf_datastore_api_heap$(EXEEXT): $(perf_datastore_api_heap_OBJECTS) $(perf_datastore_api_heap_DEPENDENCIES) $(EXTRA_perf_datastore_api_heap_DEPENDENCIES) @rm -f perf_datastore_api_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_datastore_api_heap_OBJECTS) $(perf_datastore_api_heap_LDADD) $(LIBS) perf_datastore_api_mysql$(EXEEXT): $(perf_datastore_api_mysql_OBJECTS) $(perf_datastore_api_mysql_DEPENDENCIES) $(EXTRA_perf_datastore_api_mysql_DEPENDENCIES) @rm -f perf_datastore_api_mysql$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_datastore_api_mysql_OBJECTS) $(perf_datastore_api_mysql_LDADD) $(LIBS) perf_datastore_api_postgres$(EXEEXT): $(perf_datastore_api_postgres_OBJECTS) $(perf_datastore_api_postgres_DEPENDENCIES) $(EXTRA_perf_datastore_api_postgres_DEPENDENCIES) @rm -f perf_datastore_api_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_datastore_api_postgres_OBJECTS) $(perf_datastore_api_postgres_LDADD) $(LIBS) perf_datastore_api_sqlite$(EXEEXT): $(perf_datastore_api_sqlite_OBJECTS) $(perf_datastore_api_sqlite_DEPENDENCIES) $(EXTRA_perf_datastore_api_sqlite_DEPENDENCIES) @rm -f perf_datastore_api_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_datastore_api_sqlite_OBJECTS) $(perf_datastore_api_sqlite_LDADD) $(LIBS) perf_plugin_datastore_heap$(EXEEXT): $(perf_plugin_datastore_heap_OBJECTS) $(perf_plugin_datastore_heap_DEPENDENCIES) $(EXTRA_perf_plugin_datastore_heap_DEPENDENCIES) @rm -f perf_plugin_datastore_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_plugin_datastore_heap_OBJECTS) $(perf_plugin_datastore_heap_LDADD) $(LIBS) perf_plugin_datastore_mysql$(EXEEXT): $(perf_plugin_datastore_mysql_OBJECTS) $(perf_plugin_datastore_mysql_DEPENDENCIES) $(EXTRA_perf_plugin_datastore_mysql_DEPENDENCIES) @rm -f perf_plugin_datastore_mysql$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_plugin_datastore_mysql_OBJECTS) $(perf_plugin_datastore_mysql_LDADD) $(LIBS) perf_plugin_datastore_postgres$(EXEEXT): $(perf_plugin_datastore_postgres_OBJECTS) $(perf_plugin_datastore_postgres_DEPENDENCIES) $(EXTRA_perf_plugin_datastore_postgres_DEPENDENCIES) @rm -f perf_plugin_datastore_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_plugin_datastore_postgres_OBJECTS) $(perf_plugin_datastore_postgres_LDADD) $(LIBS) perf_plugin_datastore_sqlite$(EXEEXT): $(perf_plugin_datastore_sqlite_OBJECTS) $(perf_plugin_datastore_sqlite_DEPENDENCIES) $(EXTRA_perf_plugin_datastore_sqlite_DEPENDENCIES) @rm -f perf_plugin_datastore_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_plugin_datastore_sqlite_OBJECTS) $(perf_plugin_datastore_sqlite_LDADD) $(LIBS) test_datastore_api_heap$(EXEEXT): $(test_datastore_api_heap_OBJECTS) $(test_datastore_api_heap_DEPENDENCIES) $(EXTRA_test_datastore_api_heap_DEPENDENCIES) @rm -f test_datastore_api_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datastore_api_heap_OBJECTS) $(test_datastore_api_heap_LDADD) $(LIBS) test_datastore_api_management_heap$(EXEEXT): $(test_datastore_api_management_heap_OBJECTS) $(test_datastore_api_management_heap_DEPENDENCIES) $(EXTRA_test_datastore_api_management_heap_DEPENDENCIES) @rm -f test_datastore_api_management_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datastore_api_management_heap_OBJECTS) $(test_datastore_api_management_heap_LDADD) $(LIBS) test_datastore_api_management_mysql$(EXEEXT): $(test_datastore_api_management_mysql_OBJECTS) $(test_datastore_api_management_mysql_DEPENDENCIES) $(EXTRA_test_datastore_api_management_mysql_DEPENDENCIES) @rm -f test_datastore_api_management_mysql$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datastore_api_management_mysql_OBJECTS) $(test_datastore_api_management_mysql_LDADD) $(LIBS) test_datastore_api_management_postgres$(EXEEXT): $(test_datastore_api_management_postgres_OBJECTS) $(test_datastore_api_management_postgres_DEPENDENCIES) $(EXTRA_test_datastore_api_management_postgres_DEPENDENCIES) @rm -f test_datastore_api_management_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datastore_api_management_postgres_OBJECTS) $(test_datastore_api_management_postgres_LDADD) $(LIBS) test_datastore_api_management_sqlite$(EXEEXT): $(test_datastore_api_management_sqlite_OBJECTS) $(test_datastore_api_management_sqlite_DEPENDENCIES) $(EXTRA_test_datastore_api_management_sqlite_DEPENDENCIES) @rm -f test_datastore_api_management_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datastore_api_management_sqlite_OBJECTS) $(test_datastore_api_management_sqlite_LDADD) $(LIBS) test_datastore_api_mysql$(EXEEXT): $(test_datastore_api_mysql_OBJECTS) $(test_datastore_api_mysql_DEPENDENCIES) $(EXTRA_test_datastore_api_mysql_DEPENDENCIES) @rm -f test_datastore_api_mysql$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datastore_api_mysql_OBJECTS) $(test_datastore_api_mysql_LDADD) $(LIBS) test_datastore_api_postgres$(EXEEXT): $(test_datastore_api_postgres_OBJECTS) $(test_datastore_api_postgres_DEPENDENCIES) $(EXTRA_test_datastore_api_postgres_DEPENDENCIES) @rm -f test_datastore_api_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datastore_api_postgres_OBJECTS) $(test_datastore_api_postgres_LDADD) $(LIBS) test_datastore_api_sqlite$(EXEEXT): $(test_datastore_api_sqlite_OBJECTS) $(test_datastore_api_sqlite_DEPENDENCIES) $(EXTRA_test_datastore_api_sqlite_DEPENDENCIES) @rm -f test_datastore_api_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_datastore_api_sqlite_OBJECTS) $(test_datastore_api_sqlite_LDADD) $(LIBS) test_plugin_datastore_heap$(EXEEXT): $(test_plugin_datastore_heap_OBJECTS) $(test_plugin_datastore_heap_DEPENDENCIES) $(EXTRA_test_plugin_datastore_heap_DEPENDENCIES) @rm -f test_plugin_datastore_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_datastore_heap_OBJECTS) $(test_plugin_datastore_heap_LDADD) $(LIBS) test_plugin_datastore_mysql$(EXEEXT): $(test_plugin_datastore_mysql_OBJECTS) $(test_plugin_datastore_mysql_DEPENDENCIES) $(EXTRA_test_plugin_datastore_mysql_DEPENDENCIES) @rm -f test_plugin_datastore_mysql$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_datastore_mysql_OBJECTS) $(test_plugin_datastore_mysql_LDADD) $(LIBS) test_plugin_datastore_postgres$(EXEEXT): $(test_plugin_datastore_postgres_OBJECTS) $(test_plugin_datastore_postgres_DEPENDENCIES) $(EXTRA_test_plugin_datastore_postgres_DEPENDENCIES) @rm -f test_plugin_datastore_postgres$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_datastore_postgres_OBJECTS) $(test_plugin_datastore_postgres_LDADD) $(LIBS) test_plugin_datastore_sqlite$(EXEEXT): $(test_plugin_datastore_sqlite_OBJECTS) $(test_plugin_datastore_sqlite_DEPENDENCIES) $(EXTRA_test_plugin_datastore_sqlite_DEPENDENCIES) @rm -f test_plugin_datastore_sqlite$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_datastore_sqlite_OBJECTS) $(test_plugin_datastore_sqlite_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datastore_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-datastore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-datastore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_datastore_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_plugin_datastore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_datastore_heap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_datastore_sqlite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_datastore_template.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_datastore_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_datastore_api_management.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_plugin_datastore.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.lo: plugin_datastore_mysql.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_datastore_mysql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.Tpo -c -o libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.lo `test -f 'plugin_datastore_mysql.c' || echo '$(srcdir)/'`plugin_datastore_mysql.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.Tpo $(DEPDIR)/libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_datastore_mysql.c' object='libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_datastore_mysql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_datastore_mysql_la-plugin_datastore_mysql.lo `test -f 'plugin_datastore_mysql.c' || echo '$(srcdir)/'`plugin_datastore_mysql.c libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.lo: plugin_datastore_postgres.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_datastore_postgres_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.lo -MD -MP -MF $(DEPDIR)/libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.Tpo -c -o libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.lo `test -f 'plugin_datastore_postgres.c' || echo '$(srcdir)/'`plugin_datastore_postgres.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.Tpo $(DEPDIR)/libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='plugin_datastore_postgres.c' object='libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgnunet_plugin_datastore_postgres_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgnunet_plugin_datastore_postgres_la-plugin_datastore_postgres.lo `test -f 'plugin_datastore_postgres.c' || echo '$(srcdir)/'`plugin_datastore_postgres.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_datastore_api_heap.log: test_datastore_api_heap$(EXEEXT) @p='test_datastore_api_heap$(EXEEXT)'; \ b='test_datastore_api_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datastore_api_management_heap.log: test_datastore_api_management_heap$(EXEEXT) @p='test_datastore_api_management_heap$(EXEEXT)'; \ b='test_datastore_api_management_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_datastore_api_heap.log: perf_datastore_api_heap$(EXEEXT) @p='perf_datastore_api_heap$(EXEEXT)'; \ b='perf_datastore_api_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_plugin_datastore_heap.log: perf_plugin_datastore_heap$(EXEEXT) @p='perf_plugin_datastore_heap$(EXEEXT)'; \ b='perf_plugin_datastore_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_datastore_heap.log: test_plugin_datastore_heap$(EXEEXT) @p='test_plugin_datastore_heap$(EXEEXT)'; \ b='test_plugin_datastore_heap'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datastore_api_sqlite.log: test_datastore_api_sqlite$(EXEEXT) @p='test_datastore_api_sqlite$(EXEEXT)'; \ b='test_datastore_api_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datastore_api_management_sqlite.log: test_datastore_api_management_sqlite$(EXEEXT) @p='test_datastore_api_management_sqlite$(EXEEXT)'; \ b='test_datastore_api_management_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_datastore_sqlite.log: test_plugin_datastore_sqlite$(EXEEXT) @p='test_plugin_datastore_sqlite$(EXEEXT)'; \ b='test_plugin_datastore_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_datastore_api_sqlite.log: perf_datastore_api_sqlite$(EXEEXT) @p='perf_datastore_api_sqlite$(EXEEXT)'; \ b='perf_datastore_api_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_plugin_datastore_sqlite.log: perf_plugin_datastore_sqlite$(EXEEXT) @p='perf_plugin_datastore_sqlite$(EXEEXT)'; \ b='perf_plugin_datastore_sqlite'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datastore_api_mysql.log: test_datastore_api_mysql$(EXEEXT) @p='test_datastore_api_mysql$(EXEEXT)'; \ b='test_datastore_api_mysql'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datastore_api_management_mysql.log: test_datastore_api_management_mysql$(EXEEXT) @p='test_datastore_api_management_mysql$(EXEEXT)'; \ b='test_datastore_api_management_mysql'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_datastore_mysql.log: test_plugin_datastore_mysql$(EXEEXT) @p='test_plugin_datastore_mysql$(EXEEXT)'; \ b='test_plugin_datastore_mysql'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_datastore_api_mysql.log: perf_datastore_api_mysql$(EXEEXT) @p='perf_datastore_api_mysql$(EXEEXT)'; \ b='perf_datastore_api_mysql'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_plugin_datastore_mysql.log: perf_plugin_datastore_mysql$(EXEEXT) @p='perf_plugin_datastore_mysql$(EXEEXT)'; \ b='perf_plugin_datastore_mysql'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datastore_api_postgres.log: test_datastore_api_postgres$(EXEEXT) @p='test_datastore_api_postgres$(EXEEXT)'; \ b='test_datastore_api_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_datastore_api_management_postgres.log: test_datastore_api_management_postgres$(EXEEXT) @p='test_datastore_api_management_postgres$(EXEEXT)'; \ b='test_datastore_api_management_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_plugin_datastore_postgres.log: test_plugin_datastore_postgres$(EXEEXT) @p='test_plugin_datastore_postgres$(EXEEXT)'; \ b='test_plugin_datastore_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_datastore_api_postgres.log: perf_datastore_api_postgres$(EXEEXT) @p='perf_datastore_api_postgres$(EXEEXT)'; \ b='perf_datastore_api_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_plugin_datastore_postgres.log: perf_plugin_datastore_postgres$(EXEEXT) @p='perf_plugin_datastore_postgres$(EXEEXT)'; \ b='perf_plugin_datastore_postgres'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/datastore/plugin_datastore_mysql.c0000644000175000017500000010530612255010512017522 00000000000000/* This file is part of GNUnet (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datastore/plugin_datastore_mysql.c * @brief mysql-based datastore backend * @author Igor Wronsky * @author Christian Grothoff * * NOTE: This db module does NOT work with mysql prior to 4.1 since * it uses prepared statements. MySQL 5.0.46 promises to fix a bug * in MyISAM that is causing us grief. At the time of this writing, * that version is yet to be released. In anticipation, the code * will use MyISAM with 5.0.46 (and higher). If you run such a * version, please run "make check" to verify that the MySQL bug * was actually fixed in your version (and if not, change the * code below to use MyISAM for gn071). * * HIGHLIGHTS * * Pros * + On up-to-date hardware where mysql can be used comfortably, this * module will have better performance than the other db choices * (according to our tests). * + Its often possible to recover the mysql database from internal * inconsistencies. The other db choices do not support repair! * Cons * - Memory usage (Comment: "I have 1G and it never caused me trouble") * - Manual setup * * MANUAL SETUP INSTRUCTIONS * * 1) in gnunet.conf, set * @verbatim [datastore] DATABASE = "mysql" @endverbatim * 2) Then access mysql as root, * @verbatim $ mysql -u root -p @endverbatim * and do the following. [You should replace $USER with the username * that will be running the gnunetd process]. * @verbatim CREATE DATABASE gnunet; GRANT select,insert,update,delete,create,alter,drop,create temporary tables ON gnunet.* TO $USER@localhost; SET PASSWORD FOR $USER@localhost=PASSWORD('$the_password_you_like'); FLUSH PRIVILEGES; @endverbatim * 3) In the $HOME directory of $USER, create a ".my.cnf" file * with the following lines * @verbatim [client] user=$USER password=$the_password_you_like @endverbatim * * Thats it. Note that .my.cnf file is a security risk unless its on * a safe partition etc. The $HOME/.my.cnf can of course be a symbolic * link. Even greater security risk can be achieved by setting no * password for $USER. Luckily $USER has only priviledges to mess * up GNUnet's tables, nothing else (unless you give him more, * of course).

* * 4) Still, perhaps you should briefly try if the DB connection * works. First, login as $USER. Then use, * * @verbatim $ mysql -u $USER -p $the_password_you_like mysql> use gnunet; @endverbatim * * If you get the message "Database changed" it probably works. * * [If you get "ERROR 2002: Can't connect to local MySQL server * through socket '/tmp/mysql.sock' (2)" it may be resolvable by * "ln -s /var/run/mysqld/mysqld.sock /tmp/mysql.sock" * so there may be some additional trouble depending on your mysql setup.] * * REPAIRING TABLES * * - Its probably healthy to check your tables for inconsistencies * every now and then. * - If you get odd SEGVs on gnunetd startup, it might be that the mysql * databases have been corrupted. * - The tables can be verified/fixed in two ways; * 1) by running mysqlcheck -A, or * 2) by executing (inside of mysql using the GNUnet database): * @verbatim mysql> REPAIR TABLE gn090; @endverbatim * * PROBLEMS? * * If you have problems related to the mysql module, your best * friend is probably the mysql manual. The first thing to check * is that mysql is basically operational, that you can connect * to it, create tables, issue queries etc. */ #include "platform.h" #include "gnunet_datastore_plugin.h" #include "gnunet_util_lib.h" #include "gnunet_mysql_lib.h" #define MAX_DATUM_SIZE 65536 /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATASTORE_PluginEnvironment *env; /** * Handle to talk to MySQL. */ struct GNUNET_MYSQL_Context *mc; /** * Prepared statements. */ #define INSERT_ENTRY "INSERT INTO gn090 (repl,type,prio,anonLevel,expire,rvalue,hash,vhash,value) VALUES (?,?,?,?,?,?,?,?,?)" struct GNUNET_MYSQL_StatementHandle *insert_entry; #define DELETE_ENTRY_BY_UID "DELETE FROM gn090 WHERE uid=?" struct GNUNET_MYSQL_StatementHandle *delete_entry_by_uid; #define COUNT_ENTRY_BY_HASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash) WHERE hash=?" struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash; #define SELECT_ENTRY_BY_HASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash) WHERE hash=? ORDER BY uid LIMIT 1 OFFSET ?" struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash; #define COUNT_ENTRY_BY_HASH_AND_VHASH "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=?" struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_and_vhash; #define SELECT_ENTRY_BY_HASH_AND_VHASH "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? ORDER BY uid LIMIT 1 OFFSET ?" struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_vhash; #define COUNT_ENTRY_BY_HASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=?" struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_and_type; #define SELECT_ENTRY_BY_HASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_type_uid) WHERE hash=? AND type=? ORDER BY uid LIMIT 1 OFFSET ?" struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_and_type; #define COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT count(*) FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=?" struct GNUNET_MYSQL_StatementHandle *count_entry_by_hash_vhash_and_type; #define SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_hash_vhash) WHERE hash=? AND vhash=? AND type=? ORDER BY uid ASC LIMIT 1 OFFSET ?" struct GNUNET_MYSQL_StatementHandle *select_entry_by_hash_vhash_and_type; #define UPDATE_ENTRY "UPDATE gn090 SET prio=prio+?,expire=IF(expire>=?,expire,?) WHERE uid=?" struct GNUNET_MYSQL_StatementHandle *update_entry; #define DEC_REPL "UPDATE gn090 SET repl=GREATEST (1, repl) - 1 WHERE uid=?" struct GNUNET_MYSQL_StatementHandle *dec_repl; #define SELECT_SIZE "SELECT SUM(BIT_LENGTH(value) DIV 8) FROM gn090" struct GNUNET_MYSQL_StatementHandle *get_size; #define SELECT_IT_NON_ANONYMOUS "SELECT type,prio,anonLevel,expire,hash,value,uid "\ "FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) "\ "WHERE anonLevel=0 AND type=? AND "\ "(rvalue >= ? OR"\ " NOT EXISTS (SELECT 1 FROM gn090 FORCE INDEX (idx_anonLevel_type_rvalue) WHERE anonLevel=0 AND type=? AND rvalue>=?)) "\ "ORDER BY rvalue ASC LIMIT 1" struct GNUNET_MYSQL_StatementHandle *zero_iter; #define SELECT_IT_EXPIRATION "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_expire) WHERE expire < ? ORDER BY expire ASC LIMIT 1" struct GNUNET_MYSQL_StatementHandle *select_expiration; #define SELECT_IT_PRIORITY "SELECT type,prio,anonLevel,expire,hash,value,uid FROM gn090 FORCE INDEX (idx_prio) ORDER BY prio ASC LIMIT 1" struct GNUNET_MYSQL_StatementHandle *select_priority; #define SELECT_IT_REPLICATION "SELECT type,prio,anonLevel,expire,hash,value,uid "\ "FROM gn090 FORCE INDEX (idx_repl_rvalue) "\ "WHERE repl=? AND "\ " (rvalue>=? OR"\ " NOT EXISTS (SELECT 1 FROM gn090 FORCE INDEX (idx_repl_rvalue) WHERE repl=? AND rvalue>=?)) "\ "ORDER BY rvalue ASC "\ "LIMIT 1" struct GNUNET_MYSQL_StatementHandle *select_replication; #define SELECT_MAX_REPL "SELECT MAX(repl) FROM gn090" struct GNUNET_MYSQL_StatementHandle *max_repl; #define GET_ALL_KEYS "SELECT hash from gn090" struct GNUNET_MYSQL_StatementHandle *get_all_keys; }; /** * Delete an entry from the gn090 table. * * @param plugin plugin context * @param uid unique ID of the entry to delete * @return GNUNET_OK on success, GNUNET_NO if no such value exists, GNUNET_SYSERR on error */ static int do_delete_entry (struct Plugin *plugin, unsigned long long uid) { int ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting value %llu from gn090 table\n", uid); ret = GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->delete_entry_by_uid, NULL, MYSQL_TYPE_LONGLONG, &uid, GNUNET_YES, -1); if (ret >= 0) return GNUNET_OK; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Deleting value %llu from gn090 table failed\n", uid); return ret; } /** * Get an estimate of how much space the database is * currently using. * * @param cls our "struct Plugin *" * @return number of bytes used on disk */ static unsigned long long mysql_plugin_estimate_size (void *cls) { struct Plugin *plugin = cls; MYSQL_BIND cbind[1]; long long total; memset (cbind, 0, sizeof (cbind)); total = 0; cbind[0].buffer_type = MYSQL_TYPE_LONGLONG; cbind[0].buffer = &total; cbind[0].is_unsigned = GNUNET_NO; if (GNUNET_OK != GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->get_size, 1, cbind, NULL, NULL, -1)) return 0; return total; } /** * Store an item in the datastore. * * @param cls closure * @param key key for the item * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param msg set to error message * @return GNUNET_OK on success */ static int mysql_plugin_put (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, char **msg) { struct Plugin *plugin = cls; unsigned int irepl = replication; unsigned int ipriority = priority; unsigned int ianonymity = anonymity; unsigned long long lexpiration = expiration.abs_value_us; unsigned long long lrvalue = (unsigned long long) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); unsigned long hashSize; unsigned long hashSize2; unsigned long lsize; struct GNUNET_HashCode vhash; if (size > MAX_DATUM_SIZE) { GNUNET_break (0); return GNUNET_SYSERR; } hashSize = sizeof (struct GNUNET_HashCode); hashSize2 = sizeof (struct GNUNET_HashCode); lsize = size; GNUNET_CRYPTO_hash (data, size, &vhash); if (GNUNET_OK != GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->insert_entry, NULL, MYSQL_TYPE_LONG, &irepl, GNUNET_YES, MYSQL_TYPE_LONG, &type, GNUNET_YES, MYSQL_TYPE_LONG, &ipriority, GNUNET_YES, MYSQL_TYPE_LONG, &ianonymity, GNUNET_YES, MYSQL_TYPE_LONGLONG, &lexpiration, GNUNET_YES, MYSQL_TYPE_LONGLONG, &lrvalue, GNUNET_YES, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, &vhash, hashSize2, &hashSize2, MYSQL_TYPE_BLOB, data, lsize, &lsize, -1)) return GNUNET_SYSERR; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Inserted value `%s' with size %u into gn090 table\n", GNUNET_h2s (key), (unsigned int) size); if (size > 0) plugin->env->duc (plugin->env->cls, size); return GNUNET_OK; } /** * Update the priority for a particular key in the datastore. If * the expiration time in value is different than the time found in * the datastore, the higher value should be kept. For the * anonymity level, the lower value is to be used. The specified * priority should be added to the existing priority, ignoring the * priority in value. * * Note that it is possible for multiple values to match this put. * In that case, all of the respective values are updated. * * @param cls our "struct Plugin*" * @param uid unique identifier of the datum * @param delta by how much should the priority * change? If priority + delta < 0 the * priority should be set to 0 (never go * negative). * @param expire new expiration time should be the * MAX of any existing expiration time and * this value * @param msg set to error message * @return GNUNET_OK on success */ static int mysql_plugin_update (void *cls, uint64_t uid, int delta, struct GNUNET_TIME_Absolute expire, char **msg) { struct Plugin *plugin = cls; unsigned long long vkey = uid; unsigned long long lexpire = expire.abs_value_us; int ret; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating value %llu adding %d to priority and maxing exp at %s\n", vkey, delta, GNUNET_STRINGS_absolute_time_to_string (expire)); ret = GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->update_entry, NULL, MYSQL_TYPE_LONG, &delta, GNUNET_NO, MYSQL_TYPE_LONGLONG, &lexpire, GNUNET_YES, MYSQL_TYPE_LONGLONG, &lexpire, GNUNET_YES, MYSQL_TYPE_LONGLONG, &vkey, GNUNET_YES, -1); if (ret != GNUNET_OK) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to update value %llu\n", vkey); } return ret; } /** * Run the given select statement and call 'proc' on the resulting * values (which must be in particular positions). * * @param plugin the plugin handle * @param stmt select statement to run * @param proc function to call on result * @param proc_cls closure for proc * @param ... arguments to initialize stmt */ static void execute_select (struct Plugin *plugin, struct GNUNET_MYSQL_StatementHandle *stmt, PluginDatumProcessor proc, void *proc_cls, ...) { va_list ap; int ret; unsigned int type; unsigned int priority; unsigned int anonymity; unsigned long long exp; unsigned long hashSize; unsigned long size; unsigned long long uid; char value[GNUNET_DATASTORE_MAX_VALUE_SIZE]; struct GNUNET_HashCode key; struct GNUNET_TIME_Absolute expiration; MYSQL_BIND rbind[7]; hashSize = sizeof (struct GNUNET_HashCode); memset (rbind, 0, sizeof (rbind)); rbind[0].buffer_type = MYSQL_TYPE_LONG; rbind[0].buffer = &type; rbind[0].is_unsigned = 1; rbind[1].buffer_type = MYSQL_TYPE_LONG; rbind[1].buffer = &priority; rbind[1].is_unsigned = 1; rbind[2].buffer_type = MYSQL_TYPE_LONG; rbind[2].buffer = &anonymity; rbind[2].is_unsigned = 1; rbind[3].buffer_type = MYSQL_TYPE_LONGLONG; rbind[3].buffer = &exp; rbind[3].is_unsigned = 1; rbind[4].buffer_type = MYSQL_TYPE_BLOB; rbind[4].buffer = &key; rbind[4].buffer_length = hashSize; rbind[4].length = &hashSize; rbind[5].buffer_type = MYSQL_TYPE_BLOB; rbind[5].buffer = value; rbind[5].buffer_length = size = sizeof (value); rbind[5].length = &size; rbind[6].buffer_type = MYSQL_TYPE_LONGLONG; rbind[6].buffer = &uid; rbind[6].is_unsigned = 1; va_start (ap, proc_cls); ret = GNUNET_MYSQL_statement_run_prepared_select_va (plugin->mc, stmt, 7, rbind, NULL, NULL, ap); va_end (ap); if (ret <= 0) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } GNUNET_assert (size <= sizeof (value)); if ((rbind[4].buffer_length != sizeof (struct GNUNET_HashCode)) || (hashSize != sizeof (struct GNUNET_HashCode))) { GNUNET_break (0); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } expiration.abs_value_us = exp; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u-byte value under key `%s' with prio %u, anon %u, expire %s selecting from gn090 table\n", (unsigned int) size, GNUNET_h2s (&key), priority, anonymity, GNUNET_STRINGS_absolute_time_to_string (expiration)); GNUNET_assert (size < MAX_DATUM_SIZE); ret = proc (proc_cls, &key, size, value, type, priority, anonymity, expiration, uid); if (ret == GNUNET_NO) { do_delete_entry (plugin, uid); if (size != 0) plugin->env->duc (plugin->env->cls, -size); } } /** * Get one of the results for a particular key in the datastore. * * @param cls closure * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param key key to match, never NULL * @param vhash hash of the value, maybe NULL (to * match all values that have the right key). * Note that for DBlocks there is no difference * betwen key and vhash, but for other blocks * there may be! * @param type entries of which type are relevant? * Use 0 for any type. * @param proc function to call on the matching value, * with NULL for if no value matches * @param proc_cls closure for proc */ static void mysql_plugin_get_key (void *cls, uint64_t offset, const struct GNUNET_HashCode * key, const struct GNUNET_HashCode * vhash, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; int ret; MYSQL_BIND cbind[1]; long long total; unsigned long hashSize; unsigned long hashSize2; unsigned long long off; GNUNET_assert (key != NULL); GNUNET_assert (NULL != proc); hashSize = sizeof (struct GNUNET_HashCode); hashSize2 = sizeof (struct GNUNET_HashCode); memset (cbind, 0, sizeof (cbind)); total = -1; cbind[0].buffer_type = MYSQL_TYPE_LONGLONG; cbind[0].buffer = &total; cbind[0].is_unsigned = GNUNET_NO; if (type != 0) { if (vhash != NULL) { ret = GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin-> count_entry_by_hash_vhash_and_type, 1, cbind, NULL, NULL, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, vhash, hashSize2, &hashSize2, MYSQL_TYPE_LONG, &type, GNUNET_YES, -1); } else { ret = GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->count_entry_by_hash_and_type, 1, cbind, NULL, NULL, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_LONG, &type, GNUNET_YES, -1); } } else { if (vhash != NULL) { ret = GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->count_entry_by_hash_and_vhash, 1, cbind, NULL, NULL, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, vhash, hashSize2, &hashSize2, -1); } else { ret = GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->count_entry_by_hash, 1, cbind, NULL, NULL, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, -1); } } if ((ret != GNUNET_OK) || (0 >= total)) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } offset = offset % total; off = (unsigned long long) offset; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Obtaining %llu/%lld result for GET `%s'\n", off, total, GNUNET_h2s (key)); if (type != GNUNET_BLOCK_TYPE_ANY) { if (NULL != vhash) { execute_select (plugin, plugin->select_entry_by_hash_vhash_and_type, proc, proc_cls, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, vhash, hashSize, &hashSize, MYSQL_TYPE_LONG, &type, GNUNET_YES, MYSQL_TYPE_LONGLONG, &off, GNUNET_YES, -1); } else { execute_select (plugin, plugin->select_entry_by_hash_and_type, proc, proc_cls, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_LONG, &type, GNUNET_YES, MYSQL_TYPE_LONGLONG, &off, GNUNET_YES, -1); } } else { if (NULL != vhash) { execute_select (plugin, plugin->select_entry_by_hash_and_vhash, proc, proc_cls, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_BLOB, vhash, hashSize, &hashSize, MYSQL_TYPE_LONGLONG, &off, GNUNET_YES, -1); } else { execute_select (plugin, plugin->select_entry_by_hash, proc, proc_cls, MYSQL_TYPE_BLOB, key, hashSize, &hashSize, MYSQL_TYPE_LONGLONG, &off, GNUNET_YES, -1); } } } /** * Get a zero-anonymity datum from the datastore. * * @param cls our "struct Plugin*" * @param offset offset of the result * @param type entries of which type should be considered? * Use 0 for any type. * @param proc function to call on a matching value or NULL * @param proc_cls closure for iter */ static void mysql_plugin_get_zero_anonymity (void *cls, uint64_t offset, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; unsigned long long rvalue = (unsigned long long) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); execute_select (plugin, plugin->zero_iter, proc, proc_cls, MYSQL_TYPE_LONG, &type, GNUNET_YES, MYSQL_TYPE_LONGLONG, &rvalue, GNUNET_YES, MYSQL_TYPE_LONG, &type, GNUNET_YES, MYSQL_TYPE_LONGLONG, &rvalue, GNUNET_YES, -1); } /** * Context for 'repl_proc' function. */ struct ReplCtx { /** * Plugin handle. */ struct Plugin *plugin; /** * Function to call for the result (or the NULL). */ PluginDatumProcessor proc; /** * Closure for proc. */ void *proc_cls; }; /** * Wrapper for the processor for 'mysql_plugin_get_replication'. * Decrements the replication counter and calls the original * iterator. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue * (continue on call to "next", of course), * GNUNET_NO to delete the item and continue (if supported) */ static int repl_proc (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct ReplCtx *rc = cls; struct Plugin *plugin = rc->plugin; unsigned long long oid; int ret; int iret; ret = rc->proc (rc->proc_cls, key, size, data, type, priority, anonymity, expiration, uid); if (NULL != key) { oid = (unsigned long long) uid; iret = GNUNET_MYSQL_statement_run_prepared (plugin->mc, plugin->dec_repl, NULL, MYSQL_TYPE_LONGLONG, &oid, GNUNET_YES, -1); if (iret == GNUNET_SYSERR) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to reduce replication counter\n"); return GNUNET_SYSERR; } } return ret; } /** * Get a random item for replication. Returns a single, not expired, * random item from those with the highest replication counters. The * item's replication counter is decremented by one IF it was positive * before. Call 'proc' with all values ZERO or NULL if the datastore * is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void mysql_plugin_get_replication (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; struct ReplCtx rc; unsigned long long rvalue; unsigned long repl; MYSQL_BIND results; rc.plugin = plugin; rc.proc = proc; rc.proc_cls = proc_cls; memset (&results, 0, sizeof (results)); results.buffer_type = MYSQL_TYPE_LONG; results.buffer = &repl; results.is_unsigned = GNUNET_YES; if (1 != GNUNET_MYSQL_statement_run_prepared_select (plugin->mc, plugin->max_repl, 1, &results, NULL, NULL, -1)) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } rvalue = (unsigned long long) GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); execute_select (plugin, plugin->select_replication, &repl_proc, &rc, MYSQL_TYPE_LONG, &repl, GNUNET_YES, MYSQL_TYPE_LONGLONG, &rvalue, GNUNET_YES, MYSQL_TYPE_LONG, &repl, GNUNET_YES, MYSQL_TYPE_LONGLONG, &rvalue, GNUNET_YES, -1); } /** * Get all of the keys in the datastore. * * @param cls closure * @param proc function to call on each key * @param proc_cls closure for proc */ static void mysql_plugin_get_keys (void *cls, PluginKeyProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; const char *query = "SELECT hash FROM gn090"; int ret; MYSQL_STMT *statement; struct GNUNET_HashCode key; MYSQL_BIND cbind[1]; unsigned long length; statement = GNUNET_MYSQL_statement_get_stmt (plugin->mc, plugin->get_all_keys); if (statement == NULL) { GNUNET_MYSQL_statements_invalidate (plugin->mc); return; } if (mysql_stmt_prepare (statement, query, strlen (query))) { GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "mysql", _("Failed to prepare statement `%s'\n"), query); GNUNET_MYSQL_statements_invalidate (plugin->mc); return; } GNUNET_assert (proc != NULL); if (mysql_stmt_execute (statement)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("`%s' for `%s' failed at %s:%d with error: %s\n"), "mysql_stmt_execute", query, __FILE__, __LINE__, mysql_stmt_error (statement)); GNUNET_MYSQL_statements_invalidate (plugin->mc); return; } memset (cbind, 0, sizeof (cbind)); cbind[0].buffer_type = MYSQL_TYPE_BLOB; cbind[0].buffer = &key; cbind[0].buffer_length = sizeof (key); cbind[0].length = &length; cbind[0].is_unsigned = GNUNET_NO; if (mysql_stmt_bind_result (statement, cbind)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_bind_result", __FILE__, __LINE__, mysql_stmt_error (statement)); GNUNET_MYSQL_statements_invalidate (plugin->mc); return; } while (0 == (ret = mysql_stmt_fetch (statement))) { if (sizeof (struct GNUNET_HashCode) == length) proc (proc_cls, &key, 1); } if (ret != MYSQL_NO_DATA) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("`%s' failed at %s:%d with error: %s\n"), "mysql_stmt_fetch", __FILE__, __LINE__, mysql_stmt_error (statement)); GNUNET_MYSQL_statements_invalidate (plugin->mc); return; } mysql_stmt_reset (statement); } /** * Context for 'expi_proc' function. */ struct ExpiCtx { /** * Plugin handle. */ struct Plugin *plugin; /** * Function to call for the result (or the NULL). */ PluginDatumProcessor proc; /** * Closure for proc. */ void *proc_cls; }; /** * Wrapper for the processor for 'mysql_plugin_get_expiration'. * If no expired value was found, we do a second query for * low-priority content. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue * (continue on call to "next", of course), * GNUNET_NO to delete the item and continue (if supported) */ static int expi_proc (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct ExpiCtx *rc = cls; struct Plugin *plugin = rc->plugin; if (NULL == key) { execute_select (plugin, plugin->select_priority, rc->proc, rc->proc_cls, -1); return GNUNET_SYSERR; } return rc->proc (rc->proc_cls, key, size, data, type, priority, anonymity, expiration, uid); } /** * Get a random item for expiration. * Call 'proc' with all values ZERO or NULL if the datastore is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void mysql_plugin_get_expiration (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; long long nt; struct ExpiCtx rc; rc.plugin = plugin; rc.proc = proc; rc.proc_cls = proc_cls; nt = (long long) GNUNET_TIME_absolute_get ().abs_value_us; execute_select (plugin, plugin->select_expiration, expi_proc, &rc, MYSQL_TYPE_LONGLONG, &nt, GNUNET_YES, -1); } /** * Drop database. * * @param cls the "struct Plugin*" */ static void mysql_plugin_drop (void *cls) { struct Plugin *plugin = cls; if (GNUNET_OK != GNUNET_MYSQL_statement_run (plugin->mc, "DROP TABLE gn090")) return; /* error */ plugin->env->duc (plugin->env->cls, 0); } /** * Entry point for the plugin. * * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*" * @return our "struct Plugin*" */ void * libgnunet_plugin_datastore_mysql_init (void *cls) { struct GNUNET_DATASTORE_PluginEnvironment *env = cls; struct GNUNET_DATASTORE_PluginFunctions *api; struct Plugin *plugin; plugin = GNUNET_new (struct Plugin); plugin->env = env; plugin->mc = GNUNET_MYSQL_context_create (env->cfg, "datastore-mysql"); if (NULL == plugin->mc) { GNUNET_free (plugin); return NULL; } #define MRUNS(a) (GNUNET_OK != GNUNET_MYSQL_statement_run (plugin->mc, a) ) #define PINIT(a,b) (NULL == (a = GNUNET_MYSQL_statement_prepare (plugin->mc, b))) if (MRUNS ("CREATE TABLE IF NOT EXISTS gn090 (" " repl INT(11) UNSIGNED NOT NULL DEFAULT 0," " type INT(11) UNSIGNED NOT NULL DEFAULT 0," " prio INT(11) UNSIGNED NOT NULL DEFAULT 0," " anonLevel INT(11) UNSIGNED NOT NULL DEFAULT 0," " expire BIGINT UNSIGNED NOT NULL DEFAULT 0," " rvalue BIGINT UNSIGNED NOT NULL," " hash BINARY(64) NOT NULL DEFAULT ''," " vhash BINARY(64) NOT NULL DEFAULT ''," " value BLOB NOT NULL DEFAULT ''," " uid BIGINT NOT NULL AUTO_INCREMENT," " PRIMARY KEY (uid)," " INDEX idx_hash (hash(64))," " INDEX idx_hash_uid (hash(64),uid)," " INDEX idx_hash_vhash (hash(64),vhash(64))," " INDEX idx_hash_type_uid (hash(64),type,rvalue)," " INDEX idx_prio (prio)," " INDEX idx_repl_rvalue (repl,rvalue)," " INDEX idx_expire (expire)," " INDEX idx_anonLevel_type_rvalue (anonLevel,type,rvalue)" ") ENGINE=InnoDB") || MRUNS ("SET AUTOCOMMIT = 1") || PINIT (plugin->insert_entry, INSERT_ENTRY) || PINIT (plugin->delete_entry_by_uid, DELETE_ENTRY_BY_UID) || PINIT (plugin->select_entry_by_hash, SELECT_ENTRY_BY_HASH) || PINIT (plugin->select_entry_by_hash_and_vhash, SELECT_ENTRY_BY_HASH_AND_VHASH) || PINIT (plugin->select_entry_by_hash_and_type, SELECT_ENTRY_BY_HASH_AND_TYPE) || PINIT (plugin->select_entry_by_hash_vhash_and_type, SELECT_ENTRY_BY_HASH_VHASH_AND_TYPE) || PINIT (plugin->count_entry_by_hash, COUNT_ENTRY_BY_HASH) || PINIT (plugin->get_size, SELECT_SIZE) || PINIT (plugin->count_entry_by_hash_and_vhash, COUNT_ENTRY_BY_HASH_AND_VHASH) || PINIT (plugin->count_entry_by_hash_and_type, COUNT_ENTRY_BY_HASH_AND_TYPE) || PINIT (plugin->count_entry_by_hash_vhash_and_type, COUNT_ENTRY_BY_HASH_VHASH_AND_TYPE) || PINIT (plugin->update_entry, UPDATE_ENTRY) || PINIT (plugin->dec_repl, DEC_REPL) || PINIT (plugin->zero_iter, SELECT_IT_NON_ANONYMOUS) || PINIT (plugin->select_expiration, SELECT_IT_EXPIRATION) || PINIT (plugin->select_priority, SELECT_IT_PRIORITY) || PINIT (plugin->max_repl, SELECT_MAX_REPL) || PINIT (plugin->get_all_keys, GET_ALL_KEYS) || PINIT (plugin->select_replication, SELECT_IT_REPLICATION)) { GNUNET_MYSQL_context_destroy (plugin->mc); GNUNET_free (plugin); return NULL; } #undef PINIT #undef MRUNS api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions); api->cls = plugin; api->estimate_size = &mysql_plugin_estimate_size; api->put = &mysql_plugin_put; api->update = &mysql_plugin_update; api->get_key = &mysql_plugin_get_key; api->get_replication = &mysql_plugin_get_replication; api->get_expiration = &mysql_plugin_get_expiration; api->get_zero_anonymity = &mysql_plugin_get_zero_anonymity; api->get_keys = &mysql_plugin_get_keys; api->drop = &mysql_plugin_drop; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "mysql", _("Mysql database running\n")); return api; } /** * Exit point from the plugin. * @param cls our "struct Plugin*" * @return always NULL */ void * libgnunet_plugin_datastore_mysql_done (void *cls) { struct GNUNET_DATASTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; GNUNET_MYSQL_context_destroy (plugin->mc); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_datastore_mysql.c */ gnunet-0.10.1/src/datastore/perf_plugin_datastore_data_postgres.conf0000644000175000017500000000026012225230043022724 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/perf-gnunet-datastore-postgres/ [datastore] DATABASE = postgres [datastore-postgres] CONFIG = dbname=gnunetcheck gnunet-0.10.1/src/datastore/plugin_datastore_heap.c0000644000175000017500000005005012255010512017265 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datastore/plugin_datastore_heap.c * @brief heap-based datastore backend; usually we want the datastore * to be persistent, and storing data in the heap is obviously * NOT going to be persistent; still, this plugin is useful for * testing/benchmarking --- but never for production! * @author Christian Grothoff */ #include "platform.h" #include "gnunet_datastore_plugin.h" /** * A value that we are storing. */ struct Value { /** * Key for the value. */ struct GNUNET_HashCode key; /** * Pointer to the value's data (allocated at the end of this struct). */ const void *data; /** * Entry for this value in the 'expire' heap. */ struct GNUNET_CONTAINER_HeapNode *expire_heap; /** * Entry for this value in the 'replication' heap. */ struct GNUNET_CONTAINER_HeapNode *replication_heap; /** * Expiration time for this value. */ struct GNUNET_TIME_Absolute expiration; /** * Offset of this value in the array of the 'struct ZeroAnonByType'; * only used if anonymity is zero. */ unsigned int zero_anon_offset; /** * Number of bytes in 'data'. */ uint32_t size; /** * Priority of the value. */ uint32_t priority; /** * Anonymity level for the value. */ uint32_t anonymity; /** * Replication level for the value. */ uint32_t replication; /** * Type of 'data'. */ enum GNUNET_BLOCK_Type type; }; /** * We organize 0-anonymity values in arrays "by type". */ struct ZeroAnonByType { /** * We keep these in a DLL. */ struct ZeroAnonByType *next; /** * We keep these in a DLL. */ struct ZeroAnonByType *prev; /** * Array of 0-anonymity items of the given type. */ struct Value **array; /** * Allocated size of the array. */ unsigned int array_size; /** * First unused offset in 'array'. */ unsigned int array_pos; /** * Type of all of the values in 'array'. */ enum GNUNET_BLOCK_Type type; }; /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATASTORE_PluginEnvironment *env; /** * Mapping from keys to 'struct Value's. */ struct GNUNET_CONTAINER_MultiHashMap *keyvalue; /** * Heap organized by minimum expiration time. */ struct GNUNET_CONTAINER_Heap *by_expiration; /** * Heap organized by maximum replication value. */ struct GNUNET_CONTAINER_Heap *by_replication; /** * Head of list of arrays containing zero-anonymity values by type. */ struct ZeroAnonByType *zero_head; /** * Tail of list of arrays containing zero-anonymity values by type. */ struct ZeroAnonByType *zero_tail; /** * Size of all values we're storing. */ unsigned long long size; }; /** * Get an estimate of how much space the database is * currently using. * * @param cls our "struct Plugin*" * @return number of bytes used on disk */ static unsigned long long heap_plugin_estimate_size (void *cls) { struct Plugin *plugin = cls; return plugin->size; } /** * Store an item in the datastore. * * @param cls closure * @param key key for the item * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param msg set to error message * @return GNUNET_OK on success */ static int heap_plugin_put (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, char **msg) { struct Plugin *plugin = cls; struct Value *value; value = GNUNET_malloc (sizeof (struct Value) + size); value->key = *key; value->data = &value[1]; value->expire_heap = GNUNET_CONTAINER_heap_insert (plugin->by_expiration, value, expiration.abs_value_us); value->replication_heap = GNUNET_CONTAINER_heap_insert (plugin->by_replication, value, replication); value->expiration = expiration; if (0 == anonymity) { struct ZeroAnonByType *zabt; for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next) if (zabt->type == type) break; if (NULL == zabt) { zabt = GNUNET_new (struct ZeroAnonByType); zabt->type = type; GNUNET_CONTAINER_DLL_insert (plugin->zero_head, plugin->zero_tail, zabt); } if (zabt->array_size == zabt->array_pos) { GNUNET_array_grow (zabt->array, zabt->array_size, zabt->array_size * 2 + 4); } value->zero_anon_offset = zabt->array_pos; zabt->array[zabt->array_pos++] = value; } value->size = size; value->priority = priority; value->anonymity = anonymity; value->replication = replication; value->type = type; memcpy (&value[1], data, size); GNUNET_CONTAINER_multihashmap_put (plugin->keyvalue, &value->key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); plugin->size += size; return GNUNET_OK; } /** * Delete the given value, removing it from the plugin's data * structures. * * @param plugin the plugin * @param value value to delete */ static void delete_value (struct Plugin *plugin, struct Value *value) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (plugin->keyvalue, &value->key, value)); GNUNET_assert (value == GNUNET_CONTAINER_heap_remove_node (value->expire_heap)); GNUNET_assert (value == GNUNET_CONTAINER_heap_remove_node (value->replication_heap)); if (0 == value->anonymity) { struct ZeroAnonByType *zabt; for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next) if (zabt->type == value->type) break; GNUNET_assert (NULL != zabt); zabt->array[value->zero_anon_offset] = zabt->array[--zabt->array_pos]; zabt->array[value->zero_anon_offset]->zero_anon_offset = value->zero_anon_offset; if (0 == zabt->array_pos) { GNUNET_array_grow (zabt->array, zabt->array_size, 0); GNUNET_CONTAINER_DLL_remove (plugin->zero_head, plugin->zero_tail, zabt); GNUNET_free (zabt); } } plugin->size -= value->size; GNUNET_free (value); } /** * Closure for iterator called during 'get_key'. */ struct GetContext { /** * Desired result offset / number of results. */ uint64_t offset; /** * The plugin. */ struct Plugin *plugin; /** * Requested value hash. */ const struct GNUNET_HashCode * vhash; /** * Requested type. */ enum GNUNET_BLOCK_Type type; /** * Function to call with the result. */ PluginDatumProcessor proc; /** * Closure for 'proc'. */ void *proc_cls; }; /** * Test if a value matches the specification from the 'get' context * * @param gc query * @param value the value to check against the query * @return GNUNET_YES if the value matches */ static int match (const struct GetContext *gc, struct Value *value) { struct GNUNET_HashCode vh; if ( (gc->type != GNUNET_BLOCK_TYPE_ANY) && (gc->type != value->type) ) return GNUNET_NO; if (NULL != gc->vhash) { GNUNET_CRYPTO_hash (&value[1], value->size, &vh); if (0 != memcmp (&vh, gc->vhash, sizeof (struct GNUNET_HashCode))) return GNUNET_NO; } return GNUNET_YES; } /** * Count number of matching values. * * @param cls the 'struct GetContext' * @param key unused * @param val the 'struct Value' * @return GNUNET_YES (continue iteration) */ static int count_iterator (void *cls, const struct GNUNET_HashCode *key, void *val) { struct GetContext *gc = cls; struct Value *value = val; if (GNUNET_NO == match (gc, value)) return GNUNET_OK; gc->offset++; return GNUNET_OK; } /** * Obtain matching value at 'offset'. * * @param cls the 'struct GetContext' * @param key unused * @param val the 'struct Value' * @return GNUNET_YES (continue iteration), GNUNET_NO if result was found */ static int get_iterator (void *cls, const struct GNUNET_HashCode *key, void *val) { struct GetContext *gc = cls; struct Value *value = val; if (GNUNET_NO == match (gc, value)) return GNUNET_OK; if (0 != gc->offset--) return GNUNET_OK; if (GNUNET_NO == gc->proc (gc->proc_cls, key, value->size, &value[1], value->type, value->priority, value->anonymity, value->expiration, (uint64_t) (long) value)) delete_value (gc->plugin, value); return GNUNET_NO; } /** * Get one of the results for a particular key in the datastore. * * @param cls closure * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param key maybe NULL (to match all entries) * @param vhash hash of the value, maybe NULL (to * match all values that have the right key). * Note that for DBlocks there is no difference * betwen key and vhash, but for other blocks * there may be! * @param type entries of which type are relevant? * Use 0 for any type. * @param proc function to call on each matching value; * will be called with NULL if nothing matches * @param proc_cls closure for proc */ static void heap_plugin_get_key (void *cls, uint64_t offset, const struct GNUNET_HashCode *key, const struct GNUNET_HashCode *vhash, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; struct GetContext gc; gc.plugin = plugin; gc.offset = 0; gc.vhash = vhash; gc.type = type; gc.proc = proc; gc.proc_cls = proc_cls; if (NULL == key) { GNUNET_CONTAINER_multihashmap_iterate (plugin->keyvalue, &count_iterator, &gc); if (0 == gc.offset) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } gc.offset = offset % gc.offset; GNUNET_CONTAINER_multihashmap_iterate (plugin->keyvalue, &get_iterator, &gc); } else { GNUNET_CONTAINER_multihashmap_get_multiple (plugin->keyvalue, key, &count_iterator, &gc); if (0 == gc.offset) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } gc.offset = offset % gc.offset; GNUNET_CONTAINER_multihashmap_get_multiple (plugin->keyvalue, key, &get_iterator, &gc); } } /** * Get a random item for replication. Returns a single, not expired, * random item from those with the highest replication counters. The * item's replication counter is decremented by one IF it was positive * before. Call 'proc' with all values ZERO or NULL if the datastore * is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void heap_plugin_get_replication (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; struct Value *value; value = GNUNET_CONTAINER_heap_remove_root (plugin->by_replication); if (NULL == value) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } if (value->replication > 0) { value->replication--; value->replication_heap = GNUNET_CONTAINER_heap_insert (plugin->by_replication, value, value->replication); } else { /* need a better way to pick a random item, replication level is always 0 */ value->replication_heap = GNUNET_CONTAINER_heap_insert (plugin->by_replication, value, value->replication); value = GNUNET_CONTAINER_heap_walk_get_next (plugin->by_replication); } if (GNUNET_NO == proc (proc_cls, &value->key, value->size, &value[1], value->type, value->priority, value->anonymity, value->expiration, (uint64_t) (long) value)) delete_value (plugin, value); } /** * Get a random item for expiration. Call 'proc' with all values ZERO * or NULL if the datastore is empty. * * @param cls closure * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void heap_plugin_get_expiration (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; struct Value *value; value = GNUNET_CONTAINER_heap_peek (plugin->by_expiration); if (NULL == value) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } if (GNUNET_NO == proc (proc_cls, &value->key, value->size, &value[1], value->type, value->priority, value->anonymity, value->expiration, (uint64_t) (long) value)) delete_value (plugin, value); } /** * Update the priority for a particular key in the datastore. If * the expiration time in value is different than the time found in * the datastore, the higher value should be kept. For the * anonymity level, the lower value is to be used. The specified * priority should be added to the existing priority, ignoring the * priority in value. * * @param cls our "struct Plugin*" * @param uid unique identifier of the datum * @param delta by how much should the priority * change? If priority + delta < 0 the * priority should be set to 0 (never go * negative). * @param expire new expiration time should be the * MAX of any existing expiration time and * this value * @param msg set to error message * @return GNUNET_OK on success */ static int heap_plugin_update (void *cls, uint64_t uid, int delta, struct GNUNET_TIME_Absolute expire, char **msg) { struct Plugin *plugin = cls; struct Value *value; value = (struct Value*) (long) uid; GNUNET_assert (NULL != value); if (value->expiration.abs_value_us != expire.abs_value_us) { value->expiration = expire; GNUNET_CONTAINER_heap_update_cost (plugin->by_expiration, value->expire_heap, expire.abs_value_us); } if ( (delta < 0) && (value->priority < - delta) ) value->priority = 0; else value->priority += delta; return GNUNET_OK; } /** * Call the given processor on an item with zero anonymity. * * @param cls our "struct Plugin*" * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param type entries of which type should be considered? * Use 0 for any type. * @param proc function to call on each matching value; * will be called with NULL if no value matches * @param proc_cls closure for proc */ static void heap_plugin_get_zero_anonymity (void *cls, uint64_t offset, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; struct ZeroAnonByType *zabt; struct Value *value; uint64_t count; count = 0; for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next) { if ( (type != GNUNET_BLOCK_TYPE_ANY) && (type != zabt->type) ) continue; count += zabt->array_pos; } if (0 == count) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } offset = offset % count; for (zabt = plugin->zero_head; NULL != zabt; zabt = zabt->next) { if ( (type != GNUNET_BLOCK_TYPE_ANY) && (type != zabt->type) ) continue; if (offset >= zabt->array_pos) { offset -= zabt->array_pos; continue; } break; } GNUNET_assert (NULL != zabt); value = zabt->array[offset]; if (GNUNET_NO == proc (proc_cls, &value->key, value->size, &value[1], value->type, value->priority, value->anonymity, value->expiration, (uint64_t) (long) value)) delete_value (plugin, value); } /** * Drop database. */ static void heap_plugin_drop (void *cls) { /* nothing needs to be done */ } /** * Closure for the 'return_value' function. */ struct GetAllContext { /** * Function to call. */ PluginKeyProcessor proc; /** * Closure for 'proc'. */ void *proc_cls; }; /** * Callback invoked to call callback on each value. * * @param cls the plugin * @param key unused * @param val the value * @return GNUNET_OK (continue to iterate) */ static int return_value (void *cls, const struct GNUNET_HashCode *key, void *val) { struct GetAllContext *gac = cls; gac->proc (gac->proc_cls, key, 1); return GNUNET_OK; } /** * Get all of the keys in the datastore. * * @param cls closure * @param proc function to call on each key * @param proc_cls closure for proc */ static void heap_get_keys (void *cls, PluginKeyProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; struct GetAllContext gac; gac.proc = proc; gac.proc_cls = proc_cls; GNUNET_CONTAINER_multihashmap_iterate (plugin->keyvalue, &return_value, &gac); } /** * Entry point for the plugin. * * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*" * @return our "struct Plugin*" */ void * libgnunet_plugin_datastore_heap_init (void *cls) { struct GNUNET_DATASTORE_PluginEnvironment *env = cls; struct GNUNET_DATASTORE_PluginFunctions *api; struct Plugin *plugin; unsigned long long esize; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "datastore-heap", "HASHMAPSIZE", &esize)) esize = 128 * 1024; plugin = GNUNET_new (struct Plugin); plugin->env = env; plugin->keyvalue = GNUNET_CONTAINER_multihashmap_create (esize, GNUNET_YES); plugin->by_expiration = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); plugin->by_replication = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX); api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions); api->cls = plugin; api->estimate_size = &heap_plugin_estimate_size; api->put = &heap_plugin_put; api->update = &heap_plugin_update; api->get_key = &heap_plugin_get_key; api->get_replication = &heap_plugin_get_replication; api->get_expiration = &heap_plugin_get_expiration; api->get_zero_anonymity = &heap_plugin_get_zero_anonymity; api->drop = &heap_plugin_drop; api->get_keys = &heap_get_keys; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "heap", _("Heap database running\n")); return api; } /** * Callback invoked to free all value. * * @param cls the plugin * @param key unused * @param val the value * @return GNUNET_OK (continue to iterate) */ static int free_value (void *cls, const struct GNUNET_HashCode *key, void *val) { struct Plugin *plugin = cls; struct Value *value = val; delete_value (plugin, value); return GNUNET_OK; } /** * Exit point from the plugin. * @param cls our "struct Plugin*" * @return always NULL */ void * libgnunet_plugin_datastore_heap_done (void *cls) { struct GNUNET_DATASTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; GNUNET_CONTAINER_multihashmap_iterate (plugin->keyvalue, &free_value, plugin); GNUNET_CONTAINER_multihashmap_destroy (plugin->keyvalue); GNUNET_CONTAINER_heap_destroy (plugin->by_expiration); GNUNET_CONTAINER_heap_destroy (plugin->by_replication); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_datastore_heap.c */ gnunet-0.10.1/src/datastore/test_plugin_datastore_data_postgres.conf0000644000175000017500000000026712225230043022756 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-datastore-plugin-postgres/ [datastore] DATABASE = postgres [datastore-postgres] CONFIG = dbname=gnunetcheck gnunet-0.10.1/src/datastore/Makefile.am0000644000175000017500000002340012320751517014625 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ datastore.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIBS = -lgcov endif lib_LTLIBRARIES = \ libgnunetdatastore.la libgnunetdatastore_la_SOURCES = \ datastore_api.c datastore.h libgnunetdatastore_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetdatastore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 1:0:0 bin_PROGRAMS = \ gnunet-datastore libexec_PROGRAMS = \ gnunet-service-datastore gnunet_service_datastore_SOURCES = \ gnunet-service-datastore.c gnunet_service_datastore_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_datastore_SOURCES = \ gnunet-datastore.c gnunet_datastore_LDADD = \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_datastore_DEPENDENCIES = \ libgnunetdatastore.la if HAVE_MYSQL MYSQL_PLUGIN = libgnunet_plugin_datastore_mysql.la if HAVE_TESTING if HAVE_BENCHMARKS MYSQL_BENCHMARKS = \ perf_datastore_api_mysql \ perf_plugin_datastore_mysql endif MYSQL_TESTS = \ test_datastore_api_mysql \ test_datastore_api_management_mysql \ test_plugin_datastore_mysql \ $(MYSQL_BENCHMARKS) endif endif if HAVE_SQLITE SQLITE_PLUGIN = libgnunet_plugin_datastore_sqlite.la if HAVE_TESTING if HAVE_BENCHMARKS SQLITE_BENCHMARKS = \ perf_datastore_api_sqlite \ perf_plugin_datastore_sqlite endif SQLITE_TESTS = \ test_datastore_api_sqlite \ test_datastore_api_management_sqlite \ test_plugin_datastore_sqlite \ $(SQLITE_BENCHMARKS) endif endif if HAVE_POSTGRES POSTGRES_PLUGIN = libgnunet_plugin_datastore_postgres.la if HAVE_TESTING if HAVE_BENCHMARKS POSTGRES_BENCHMARKS = \ perf_datastore_api_postgres \ perf_plugin_datastore_postgres endif POSTGRES_TESTS = \ test_datastore_api_postgres \ test_datastore_api_management_postgres \ test_plugin_datastore_postgres \ $(POSTGRES_BENCHMARKS) endif endif plugin_LTLIBRARIES = \ $(SQLITE_PLUGIN) \ $(MYSQL_PLUGIN) \ $(POSTGRES_PLUGIN) \ libgnunet_plugin_datastore_heap.la \ libgnunet_plugin_datastore_template.la libgnunet_plugin_datastore_sqlite_la_SOURCES = \ plugin_datastore_sqlite.c libgnunet_plugin_datastore_sqlite_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \ $(LTLIBINTL) libgnunet_plugin_datastore_sqlite_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_datastore_heap_la_SOURCES = \ plugin_datastore_heap.c libgnunet_plugin_datastore_heap_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) libgnunet_plugin_datastore_heap_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_datastore_mysql_la_SOURCES = \ plugin_datastore_mysql.c libgnunet_plugin_datastore_mysql_la_LIBADD = \ $(top_builddir)/src/mysql/libgnunetmysql.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) $(Z_LIBS) -lmysqlclient libgnunet_plugin_datastore_mysql_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) $(MYSQL_LDFLAGS) -lmysqlclient libgnunet_plugin_datastore_mysql_la_CPPFLAGS = \ $(MYSQL_CPPFLAGS) $(AM_CPPFLAGS) libgnunet_plugin_datastore_postgres_la_SOURCES = \ plugin_datastore_postgres.c libgnunet_plugin_datastore_postgres_la_LIBADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/postgres/libgnunetpostgres.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq libgnunet_plugin_datastore_postgres_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) $(POSTGRES_LDFLAGS) -lpq libgnunet_plugin_datastore_postgres_la_CPPFLAGS = \ $(POSTGRES_CPPFLAGS) $(AM_CPPFLAGS) libgnunet_plugin_datastore_template_la_SOURCES = \ plugin_datastore_template.c libgnunet_plugin_datastore_template_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) libgnunet_plugin_datastore_template_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) check_PROGRAMS = \ test_datastore_api_heap \ test_datastore_api_management_heap \ perf_datastore_api_heap \ perf_plugin_datastore_heap \ test_plugin_datastore_heap \ $(SQLITE_TESTS) \ $(MYSQL_TESTS) \ $(POSTGRES_TESTS) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_datastore_api_heap_SOURCES = \ test_datastore_api.c test_datastore_api_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_management_heap_SOURCES = \ test_datastore_api_management.c test_datastore_api_management_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datastore_api_heap_SOURCES = \ perf_datastore_api.c perf_datastore_api_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_plugin_datastore_heap_SOURCES = \ perf_plugin_datastore.c perf_plugin_datastore_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_datastore_heap_SOURCES = \ test_plugin_datastore.c test_plugin_datastore_heap_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_sqlite_SOURCES = \ test_datastore_api.c test_datastore_api_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_management_sqlite_SOURCES = \ test_datastore_api_management.c test_datastore_api_management_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datastore_api_sqlite_SOURCES = \ perf_datastore_api.c perf_datastore_api_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_plugin_datastore_sqlite_SOURCES = \ perf_plugin_datastore.c perf_plugin_datastore_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_datastore_sqlite_SOURCES = \ test_plugin_datastore.c test_plugin_datastore_sqlite_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_mysql_SOURCES = \ test_datastore_api.c test_datastore_api_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_management_mysql_SOURCES = \ test_datastore_api_management.c test_datastore_api_management_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datastore_api_mysql_SOURCES = \ perf_datastore_api.c perf_datastore_api_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_datastore_mysql_SOURCES = \ test_plugin_datastore.c test_plugin_datastore_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_plugin_datastore_mysql_SOURCES = \ perf_plugin_datastore.c perf_plugin_datastore_mysql_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_postgres_SOURCES = \ test_datastore_api.c test_datastore_api_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_datastore_api_management_postgres_SOURCES = \ test_datastore_api_management.c test_datastore_api_management_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la perf_datastore_api_postgres_SOURCES = \ perf_datastore_api.c perf_datastore_api_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/datastore/libgnunetdatastore.la \ $(top_builddir)/src/util/libgnunetutil.la test_plugin_datastore_postgres_SOURCES = \ test_plugin_datastore.c test_plugin_datastore_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_plugin_datastore_postgres_SOURCES = \ perf_plugin_datastore.c perf_plugin_datastore_postgres_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_defaults.conf \ test_datastore_api_data_sqlite.conf \ perf_plugin_datastore_data_sqlite.conf \ test_plugin_datastore_data_sqlite.conf \ test_datastore_api_data_heap.conf \ perf_plugin_datastore_data_heap.conf \ test_plugin_datastore_data_heap.conf \ test_datastore_api_data_mysql.conf \ perf_plugin_datastore_data_mysql.conf \ test_plugin_datastore_data_mysql.conf \ test_datastore_api_data_postgres.conf \ perf_plugin_datastore_data_postgres.conf \ test_plugin_datastore_data_postgres.conf gnunet-0.10.1/src/datastore/plugin_datastore_postgres.c0000644000175000017500000007100612255010512020222 00000000000000/* This file is part of GNUnet (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datastore/plugin_datastore_postgres.c * @brief postgres-based datastore backend * @author Christian Grothoff */ #include "platform.h" #include "gnunet_datastore_plugin.h" #include "gnunet_postgres_lib.h" #include /** * After how many ms "busy" should a DB operation fail for good? * A low value makes sure that we are more responsive to requests * (especially PUTs). A high value guarantees a higher success * rate (SELECTs in iterate can take several seconds despite LIMIT=1). * * The default value of 1s should ensure that users do not experience * huge latencies while at the same time allowing operations to succeed * with reasonable probability. */ #define BUSY_TIMEOUT GNUNET_TIME_UNIT_SECONDS /** * Context for all functions in this plugin. */ struct Plugin { /** * Our execution environment. */ struct GNUNET_DATASTORE_PluginEnvironment *env; /** * Native Postgres database handle. */ PGconn *dbh; }; /** * @brief Get a database handle * * @param plugin global context * @return GNUNET_OK on success, GNUNET_SYSERR on error */ static int init_connection (struct Plugin *plugin) { PGresult *ret; plugin->dbh = GNUNET_POSTGRES_connect (plugin->env->cfg, "datastore-postgres"); if (NULL == plugin->dbh) return GNUNET_SYSERR; ret = PQexec (plugin->dbh, "CREATE TABLE gn090 (" " repl INTEGER NOT NULL DEFAULT 0," " type INTEGER NOT NULL DEFAULT 0," " prio INTEGER NOT NULL DEFAULT 0," " anonLevel INTEGER NOT NULL DEFAULT 0," " expire BIGINT NOT NULL DEFAULT 0," " rvalue BIGINT NOT NULL DEFAULT 0," " hash BYTEA NOT NULL DEFAULT ''," " vhash BYTEA NOT NULL DEFAULT ''," " value BYTEA NOT NULL DEFAULT '')" "WITH OIDS"); if ((ret == NULL) || ((PQresultStatus (ret) != PGRES_COMMAND_OK) && (0 != strcmp ("42P07", /* duplicate table */ PQresultErrorField (ret, PG_DIAG_SQLSTATE))))) { (void) GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "CREATE TABLE", "gn090"); PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } if (PQresultStatus (ret) == PGRES_COMMAND_OK) { if ((GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_hash ON gn090 (hash)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_hash_vhash ON gn090 (hash,vhash)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_prio ON gn090 (prio)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_expire ON gn090 (expire)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_prio_anon ON gn090 (prio,anonLevel)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_prio_hash_anon ON gn090 (prio,hash,anonLevel)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_repl_rvalue ON gn090 (repl,rvalue)")) || (GNUNET_OK != GNUNET_POSTGRES_exec (plugin->dbh, "CREATE INDEX idx_expire_hash ON gn090 (expire,hash)"))) { PQclear (ret); PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } } PQclear (ret); ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER value SET STORAGE EXTERNAL"); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } PQclear (ret); ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER hash SET STORAGE PLAIN"); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } PQclear (ret); ret = PQexec (plugin->dbh, "ALTER TABLE gn090 ALTER vhash SET STORAGE PLAIN"); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "ALTER TABLE", "gn090")) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } PQclear (ret); if ((GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "getvt", "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " "WHERE hash=$1 AND vhash=$2 AND type=$3 " "ORDER BY oid ASC LIMIT 1 OFFSET $4", 4)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "gett", "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " "WHERE hash=$1 AND type=$2 " "ORDER BY oid ASC LIMIT 1 OFFSET $3", 3)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "getv", "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " "WHERE hash=$1 AND vhash=$2 " "ORDER BY oid ASC LIMIT 1 OFFSET $3", 3)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "get", "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " "WHERE hash=$1 " "ORDER BY oid ASC LIMIT 1 OFFSET $2", 2)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "put", "INSERT INTO gn090 (repl, type, prio, anonLevel, expire, rvalue, hash, vhash, value) " "VALUES ($1, $2, $3, $4, $5, RANDOM(), $6, $7, $8)", 9)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "update", "UPDATE gn090 SET prio = prio + $1, expire = CASE WHEN expire < $2 THEN $2 ELSE expire END " "WHERE oid = $3", 3)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "decrepl", "UPDATE gn090 SET repl = GREATEST (repl - 1, 0) " "WHERE oid = $1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "select_non_anonymous", "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " "WHERE anonLevel = 0 AND type = $1 ORDER BY oid DESC LIMIT 1 OFFSET $2", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "select_expiration_order", "(SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " "WHERE expire < $1 ORDER BY prio ASC LIMIT 1) " "UNION " "(SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " "ORDER BY prio ASC LIMIT 1) " "ORDER BY expire ASC LIMIT 1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "select_replication_order", "SELECT type, prio, anonLevel, expire, hash, value, oid FROM gn090 " "ORDER BY repl DESC,RANDOM() LIMIT 1", 0)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "delrow", "DELETE FROM gn090 " "WHERE oid=$1", 1)) || (GNUNET_OK != GNUNET_POSTGRES_prepare (plugin->dbh, "get_keys", "SELECT hash FROM gn090", 0))) { PQfinish (plugin->dbh); plugin->dbh = NULL; return GNUNET_SYSERR; } return GNUNET_OK; } /** * Get an estimate of how much space the database is * currently using. * * @param cls our "struct Plugin*" * @return number of bytes used on disk */ static unsigned long long postgres_plugin_estimate_size (void *cls) { struct Plugin *plugin = cls; unsigned long long total; PGresult *ret; ret = PQexecParams (plugin->dbh, "SELECT SUM(LENGTH(value))+256*COUNT(*) FROM gn090", 0, NULL, NULL, NULL, NULL, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_TUPLES_OK, "PQexecParams", "get_size")) { return 0; } if ((PQntuples (ret) != 1) || (PQnfields (ret) != 1) ) { GNUNET_break (0); PQclear (ret); return 0; } if (PQgetlength (ret, 0, 0) != sizeof (unsigned long long)) { GNUNET_break (0 == PQgetlength (ret, 0, 0)); PQclear (ret); return 0; } total = GNUNET_ntohll (*(const unsigned long long *) PQgetvalue (ret, 0, 0)); PQclear (ret); return total; } /** * Store an item in the datastore. * * @param cls closure with the 'struct Plugin' * @param key key for the item * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param replication replication-level for the content * @param expiration expiration time for the content * @param msg set to error message * @return GNUNET_OK on success */ static int postgres_plugin_put (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, uint32_t replication, struct GNUNET_TIME_Absolute expiration, char **msg) { struct Plugin *plugin = cls; struct GNUNET_HashCode vhash; PGresult *ret; uint32_t btype = htonl (type); uint32_t bprio = htonl (priority); uint32_t banon = htonl (anonymity); uint32_t brepl = htonl (replication); uint64_t bexpi = GNUNET_TIME_absolute_hton (expiration).abs_value_us__; const char *paramValues[] = { (const char *) &brepl, (const char *) &btype, (const char *) &bprio, (const char *) &banon, (const char *) &bexpi, (const char *) key, (const char *) &vhash, (const char *) data }; int paramLengths[] = { sizeof (brepl), sizeof (btype), sizeof (bprio), sizeof (banon), sizeof (bexpi), sizeof (struct GNUNET_HashCode), sizeof (struct GNUNET_HashCode), size }; const int paramFormats[] = { 1, 1, 1, 1, 1, 1, 1, 1 }; GNUNET_CRYPTO_hash (data, size, &vhash); ret = PQexecPrepared (plugin->dbh, "put", 8, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "put")) return GNUNET_SYSERR; PQclear (ret); plugin->env->duc (plugin->env->cls, size + GNUNET_DATASTORE_ENTRY_OVERHEAD); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", "Stored %u bytes in database\n", (unsigned int) size); return GNUNET_OK; } /** * Function invoked to process the result and call * the processor. * * @param plugin global plugin data * @param proc function to call the value (once only). * @param proc_cls closure for proc * @param res result from exec * @param filename filename for error messages * @param line line number for error messages */ static void process_result (struct Plugin *plugin, PluginDatumProcessor proc, void *proc_cls, PGresult * res, const char *filename, int line) { int iret; enum GNUNET_BLOCK_Type type; uint32_t anonymity; uint32_t priority; uint32_t size; unsigned int rowid; struct GNUNET_TIME_Absolute expiration_time; struct GNUNET_HashCode key; if (GNUNET_OK != GNUNET_POSTGRES_check_result_ (plugin->dbh, res, PGRES_TUPLES_OK, "PQexecPrepared", "select", filename, line)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", "Ending iteration (postgres error)\n"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } if (0 == PQntuples (res)) { /* no result */ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", "Ending iteration (no more results)\n"); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); PQclear (res); return; } if ((1 != PQntuples (res)) || (7 != PQnfields (res)) || (sizeof (uint32_t) != PQfsize (res, 0)) || (sizeof (uint32_t) != PQfsize (res, 6))) { GNUNET_break (0); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); PQclear (res); return; } rowid = ntohl (*(uint32_t *) PQgetvalue (res, 0, 6)); if ((sizeof (uint32_t) != PQfsize (res, 0)) || (sizeof (uint32_t) != PQfsize (res, 1)) || (sizeof (uint32_t) != PQfsize (res, 2)) || (sizeof (uint64_t) != PQfsize (res, 3)) || (sizeof (struct GNUNET_HashCode) != PQgetlength (res, 0, 4))) { GNUNET_break (0); PQclear (res); GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, "delrow", rowid); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } type = ntohl (*(uint32_t *) PQgetvalue (res, 0, 0)); priority = ntohl (*(uint32_t *) PQgetvalue (res, 0, 1)); anonymity = ntohl (*(uint32_t *) PQgetvalue (res, 0, 2)); expiration_time.abs_value_us = GNUNET_ntohll (*(uint64_t *) PQgetvalue (res, 0, 3)); memcpy (&key, PQgetvalue (res, 0, 4), sizeof (struct GNUNET_HashCode)); size = PQgetlength (res, 0, 5); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", "Found result of size %u bytes and type %u in database\n", (unsigned int) size, (unsigned int) type); iret = proc (proc_cls, &key, size, PQgetvalue (res, 0, 5), (enum GNUNET_BLOCK_Type) type, priority, anonymity, expiration_time, rowid); PQclear (res); if (iret == GNUNET_NO) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processor asked for item %u to be removed.\n", rowid); if (GNUNET_OK == GNUNET_POSTGRES_delete_by_rowid (plugin->dbh, "delrow", rowid)) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", "Deleting %u bytes from database\n", (unsigned int) size); plugin->env->duc (plugin->env->cls, -(size + GNUNET_DATASTORE_ENTRY_OVERHEAD)); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "datastore-postgres", "Deleted %u bytes from database\n", (unsigned int) size); } } } /** * Iterate over the results for a particular key * in the datastore. * * @param cls closure with the 'struct Plugin' * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param key maybe NULL (to match all entries) * @param vhash hash of the value, maybe NULL (to * match all values that have the right key). * Note that for DBlocks there is no difference * betwen key and vhash, but for other blocks * there may be! * @param type entries of which type are relevant? * Use 0 for any type. * @param proc function to call on the matching value; * will be called once with a NULL if no value matches * @param proc_cls closure for iter */ static void postgres_plugin_get_key (void *cls, uint64_t offset, const struct GNUNET_HashCode * key, const struct GNUNET_HashCode * vhash, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; const int paramFormats[] = { 1, 1, 1, 1, 1 }; int paramLengths[4]; const char *paramValues[4]; int nparams; const char *pname; PGresult *ret; uint64_t total; uint64_t blimit_off; uint32_t btype; GNUNET_assert (key != NULL); paramValues[0] = (const char *) key; paramLengths[0] = sizeof (struct GNUNET_HashCode); btype = htonl (type); if (type != 0) { if (vhash != NULL) { paramValues[1] = (const char *) vhash; paramLengths[1] = sizeof (struct GNUNET_HashCode); paramValues[2] = (const char *) &btype; paramLengths[2] = sizeof (btype); paramValues[3] = (const char *) &blimit_off; paramLengths[3] = sizeof (blimit_off); nparams = 4; pname = "getvt"; ret = PQexecParams (plugin->dbh, "SELECT count(*) FROM gn090 WHERE hash=$1 AND vhash=$2 AND type=$3", 3, NULL, paramValues, paramLengths, paramFormats, 1); } else { paramValues[1] = (const char *) &btype; paramLengths[1] = sizeof (btype); paramValues[2] = (const char *) &blimit_off; paramLengths[2] = sizeof (blimit_off); nparams = 3; pname = "gett"; ret = PQexecParams (plugin->dbh, "SELECT count(*) FROM gn090 WHERE hash=$1 AND type=$2", 2, NULL, paramValues, paramLengths, paramFormats, 1); } } else { if (vhash != NULL) { paramValues[1] = (const char *) vhash; paramLengths[1] = sizeof (struct GNUNET_HashCode); paramValues[2] = (const char *) &blimit_off; paramLengths[2] = sizeof (blimit_off); nparams = 3; pname = "getv"; ret = PQexecParams (plugin->dbh, "SELECT count(*) FROM gn090 WHERE hash=$1 AND vhash=$2", 2, NULL, paramValues, paramLengths, paramFormats, 1); } else { paramValues[1] = (const char *) &blimit_off; paramLengths[1] = sizeof (blimit_off); nparams = 2; pname = "get"; ret = PQexecParams (plugin->dbh, "SELECT count(*) FROM gn090 WHERE hash=$1", 1, NULL, paramValues, paramLengths, paramFormats, 1); } } if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_TUPLES_OK, "PQexecParams", pname)) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } if ((PQntuples (ret) != 1) || (PQnfields (ret) != 1) || (PQgetlength (ret, 0, 0) != sizeof (unsigned long long))) { GNUNET_break (0); PQclear (ret); proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } total = GNUNET_ntohll (*(const unsigned long long *) PQgetvalue (ret, 0, 0)); PQclear (ret); if (total == 0) { proc (proc_cls, NULL, 0, NULL, 0, 0, 0, GNUNET_TIME_UNIT_ZERO_ABS, 0); return; } blimit_off = GNUNET_htonll (offset % total); ret = PQexecPrepared (plugin->dbh, pname, nparams, paramValues, paramLengths, paramFormats, 1); process_result (plugin, proc, proc_cls, ret, __FILE__, __LINE__); } /** * Select a subset of the items in the datastore and call * the given iterator for each of them. * * @param cls our "struct Plugin*" * @param offset offset of the result (modulo num-results); * specific ordering does not matter for the offset * @param type entries of which type should be considered? * Use 0 for any type. * @param proc function to call on the matching value; * will be called with a NULL if no value matches * @param proc_cls closure for proc */ static void postgres_plugin_get_zero_anonymity (void *cls, uint64_t offset, enum GNUNET_BLOCK_Type type, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; uint32_t btype; uint64_t boff; const int paramFormats[] = { 1, 1 }; int paramLengths[] = { sizeof (btype), sizeof (boff) }; const char *paramValues[] = { (const char *) &btype, (const char *) &boff }; PGresult *ret; btype = htonl ((uint32_t) type); boff = GNUNET_htonll (offset); ret = PQexecPrepared (plugin->dbh, "select_non_anonymous", 2, paramValues, paramLengths, paramFormats, 1); process_result (plugin, proc, proc_cls, ret, __FILE__, __LINE__); } /** * Context for 'repl_iter' function. */ struct ReplCtx { /** * Plugin handle. */ struct Plugin *plugin; /** * Function to call for the result (or the NULL). */ PluginDatumProcessor proc; /** * Closure for proc. */ void *proc_cls; }; /** * Wrapper for the iterator for 'sqlite_plugin_replication_get'. * Decrements the replication counter and calls the original * iterator. * * @param cls closure with the 'struct ReplCtx*' * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available * * @return GNUNET_SYSERR to abort the iteration, GNUNET_OK to continue * (continue on call to "next", of course), * GNUNET_NO to delete the item and continue (if supported) */ static int repl_proc (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct ReplCtx *rc = cls; struct Plugin *plugin = rc->plugin; int ret; PGresult *qret; uint32_t boid; ret = rc->proc (rc->proc_cls, key, size, data, type, priority, anonymity, expiration, uid); if (NULL != key) { boid = htonl ((uint32_t) uid); const char *paramValues[] = { (const char *) &boid, }; int paramLengths[] = { sizeof (boid), }; const int paramFormats[] = { 1 }; qret = PQexecPrepared (plugin->dbh, "decrepl", 1, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, qret, PGRES_COMMAND_OK, "PQexecPrepared", "decrepl")) return GNUNET_SYSERR; PQclear (qret); } return ret; } /** * Get a random item for replication. Returns a single, not expired, random item * from those with the highest replication counters. The item's * replication counter is decremented by one IF it was positive before. * Call 'proc' with all values ZERO or NULL if the datastore is empty. * * @param cls closure with the 'struct Plugin' * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void postgres_plugin_get_replication (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; struct ReplCtx rc; PGresult *ret; rc.plugin = plugin; rc.proc = proc; rc.proc_cls = proc_cls; ret = PQexecPrepared (plugin->dbh, "select_replication_order", 0, NULL, NULL, NULL, 1); process_result (plugin, &repl_proc, &rc, ret, __FILE__, __LINE__); } /** * Get a random item for expiration. * Call 'proc' with all values ZERO or NULL if the datastore is empty. * * @param cls closure with the 'struct Plugin' * @param proc function to call the value (once only). * @param proc_cls closure for proc */ static void postgres_plugin_get_expiration (void *cls, PluginDatumProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; uint64_t btime; const int paramFormats[] = { 1 }; int paramLengths[] = { sizeof (btime) }; const char *paramValues[] = { (const char *) &btime }; PGresult *ret; btime = GNUNET_htonll (GNUNET_TIME_absolute_get ().abs_value_us); ret = PQexecPrepared (plugin->dbh, "select_expiration_order", 1, paramValues, paramLengths, paramFormats, 1); process_result (plugin, proc, proc_cls, ret, __FILE__, __LINE__); } /** * Update the priority for a particular key in the datastore. If * the expiration time in value is different than the time found in * the datastore, the higher value should be kept. For the * anonymity level, the lower value is to be used. The specified * priority should be added to the existing priority, ignoring the * priority in value. * * Note that it is possible for multiple values to match this put. * In that case, all of the respective values are updated. * * @param cls our "struct Plugin*" * @param uid unique identifier of the datum * @param delta by how much should the priority * change? If priority + delta < 0 the * priority should be set to 0 (never go * negative). * @param expire new expiration time should be the * MAX of any existing expiration time and * this value * @param msg set to error message * @return GNUNET_OK on success */ static int postgres_plugin_update (void *cls, uint64_t uid, int delta, struct GNUNET_TIME_Absolute expire, char **msg) { struct Plugin *plugin = cls; PGresult *ret; int32_t bdelta = (int32_t) htonl ((uint32_t) delta); uint32_t boid = htonl ((uint32_t) uid); uint64_t bexpire = GNUNET_TIME_absolute_hton (expire).abs_value_us__; const char *paramValues[] = { (const char *) &bdelta, (const char *) &bexpire, (const char *) &boid, }; int paramLengths[] = { sizeof (bdelta), sizeof (bexpire), sizeof (boid), }; const int paramFormats[] = { 1, 1, 1 }; ret = PQexecPrepared (plugin->dbh, "update", 3, paramValues, paramLengths, paramFormats, 1); if (GNUNET_OK != GNUNET_POSTGRES_check_result (plugin->dbh, ret, PGRES_COMMAND_OK, "PQexecPrepared", "update")) return GNUNET_SYSERR; PQclear (ret); return GNUNET_OK; } /** * Get all of the keys in the datastore. * * @param cls closure with the 'struct Plugin' * @param proc function to call on each key * @param proc_cls closure for proc */ static void postgres_plugin_get_keys (void *cls, PluginKeyProcessor proc, void *proc_cls) { struct Plugin *plugin = cls; int ret; int i; struct GNUNET_HashCode key; PGresult * res; res = PQexecPrepared (plugin->dbh, "get_keys", 0, NULL, NULL, NULL, 1); ret = PQntuples (res); for (i=0;idbh, "DROP TABLE gn090")) GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "postgres", _("Failed to drop table from database.\n")); } /** * Entry point for the plugin. * * @param cls the "struct GNUNET_DATASTORE_PluginEnvironment*" * @return our "struct Plugin*" */ void * libgnunet_plugin_datastore_postgres_init (void *cls) { struct GNUNET_DATASTORE_PluginEnvironment *env = cls; struct GNUNET_DATASTORE_PluginFunctions *api; struct Plugin *plugin; plugin = GNUNET_new (struct Plugin); plugin->env = env; if (GNUNET_OK != init_connection (plugin)) { GNUNET_free (plugin); return NULL; } api = GNUNET_new (struct GNUNET_DATASTORE_PluginFunctions); api->cls = plugin; api->estimate_size = &postgres_plugin_estimate_size; api->put = &postgres_plugin_put; api->update = &postgres_plugin_update; api->get_key = &postgres_plugin_get_key; api->get_replication = &postgres_plugin_get_replication; api->get_expiration = &postgres_plugin_get_expiration; api->get_zero_anonymity = &postgres_plugin_get_zero_anonymity; api->get_keys = &postgres_plugin_get_keys; api->drop = &postgres_plugin_drop; GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "datastore-postgres", _("Postgres database running\n")); return api; } /** * Exit point from the plugin. * @param cls our "struct Plugin*" * @return always NULL */ void * libgnunet_plugin_datastore_postgres_done (void *cls) { struct GNUNET_DATASTORE_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; PQfinish (plugin->dbh); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_datastore_postgres.c */ gnunet-0.10.1/src/datastore/test_datastore_api_management.c0000644000175000017500000002000612255010512020774 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2007, 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file datastore/test_datastore_api_management.c * @brief Test for the space management functions of the datastore implementation. * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_datastore_service.h" #include "gnunet_testing_lib.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) /** * Number of iterations to run; must be large enough * so that the quota will be exceeded! */ #define ITERATIONS 5000 enum RunPhase { RP_PUT, RP_GET, RP_DONE, RP_GET_FAIL }; struct CpsRunContext { struct GNUNET_HashCode key; int i; int found; const struct GNUNET_CONFIGURATION_Handle *cfg; void *data; enum RunPhase phase; uint64_t offset; }; static struct GNUNET_DATASTORE_Handle *datastore; static struct GNUNET_TIME_Absolute now; static int ok; static const char *plugin_name; static size_t get_size (int i) { return 8 + 8 * (i % 256); } static const void * get_data (int i) { static char buf[60000]; memset (buf, i, 8 + 8 * (i % 256)); return buf; } static int get_type (int i) { return 1; } static int get_priority (int i) { return i + 1; } static int get_anonymity (int i) { return i; } static struct GNUNET_TIME_Absolute get_expiration (int i) { struct GNUNET_TIME_Absolute av; av.abs_value_us = now.abs_value_us + i * 1000 * 1000LL; return av; } static void run_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void check_success (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct CpsRunContext *crc = cls; if (GNUNET_OK != success) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", msg); GNUNET_assert (GNUNET_OK == success); GNUNET_free_non_null (crc->data); crc->data = NULL; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void check_value (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; int i; if (NULL == key) { crc->phase = RP_GET_FAIL; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); return; } i = crc->i; GNUNET_assert (size == get_size (i)); GNUNET_assert (0 == memcmp (data, get_data (i), size)); GNUNET_assert (type == get_type (i)); GNUNET_assert (priority == get_priority (i)); GNUNET_assert (anonymity == get_anonymity (i)); GNUNET_assert (expiration.abs_value_us == get_expiration (i).abs_value_us); crc->offset++; crc->i--; if (crc->i == 0) crc->phase = RP_DONE; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void check_nothing (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; GNUNET_assert (key == NULL); if (0 == --crc->i) crc->phase = RP_DONE; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void run_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CpsRunContext *crc = cls; ok = (int) crc->phase; switch (crc->phase) { case RP_PUT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "PUT", crc->i); GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); GNUNET_DATASTORE_put (datastore, 0, &crc->key, get_size (crc->i), get_data (crc->i), get_type (crc->i), get_priority (crc->i), get_anonymity (crc->i), 0, get_expiration (crc->i), 1, 1, TIMEOUT, &check_success, crc); crc->i++; if (crc->i == ITERATIONS) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sleeping to give datastore time to clean up\n"); sleep (1); crc->phase = RP_GET; crc->i--; } break; case RP_GET: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "GET", crc->i); GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); GNUNET_DATASTORE_get_key (datastore, crc->offset++, &crc->key, get_type (crc->i), 1, 1, TIMEOUT, &check_value, crc); break; case RP_GET_FAIL: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "GET(f)", crc->i); GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); GNUNET_DATASTORE_get_key (datastore, crc->offset++, &crc->key, get_type (crc->i), 1, 1, TIMEOUT, &check_nothing, crc); break; case RP_DONE: GNUNET_assert (0 == crc->i); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished, disconnecting\n"); GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); ok = 0; } } static void run_tests (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct CpsRunContext *crc = cls; if (success != GNUNET_YES) { FPRINTF (stderr, "Test 'put' operation failed with error `%s' database likely not setup, skipping test.\n", msg); GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); return; } GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct CpsRunContext *crc; static struct GNUNET_HashCode zkey; crc = GNUNET_new (struct CpsRunContext); crc->cfg = cfg; crc->phase = RP_PUT; now = GNUNET_TIME_absolute_get (); datastore = GNUNET_DATASTORE_connect (cfg); if (NULL == GNUNET_DATASTORE_put (datastore, 0, &zkey, 4, "TEST", GNUNET_BLOCK_TYPE_TEST, 0, 0, 0, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_SECONDS), 0, 1, GNUNET_TIME_UNIT_MINUTES, &run_tests, crc)) { FPRINTF (stderr, "%s", "Test 'put' operation failed.\n"); GNUNET_free (crc); ok = 1; } } int main (int argc, char *argv[]) { char cfg_name[128]; plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_datastore_api_data_%s.conf", plugin_name); if (0 != GNUNET_TESTING_peer_run ("test-gnunet-datastore-management", cfg_name, &run, NULL)) return 1; return ok; } /* end of test_datastore_api_management.c */ gnunet-0.10.1/src/datastore/test_datastore_api_data_sqlite.conf0000644000175000017500000000035612225230043021663 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-datastore-sqlite/ [TESTING] WEAKRANDOM = YES [arm] PORT = 42466 DEFAULTSERVICES = [statistics] PORT = 22667 [resolver] PORT = 42464 [datastore] QUOTA = 10 MB gnunet-0.10.1/src/datastore/perf_plugin_datastore.c0000644000175000017500000003410412255010512017306 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2007, 2009, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file perf_plugin_datastore.c * @brief Profile database plugin directly, focusing on iterators. * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_datastore_plugin.h" #include "gnunet_testing_lib.h" #include /** * Target datastore size (in bytes). Realistic sizes are * more like 16 GB (not the default of 16 MB); however, * those take too long to run them in the usual "make check" * sequence. Hence the value used for shipping is tiny. */ #define MAX_SIZE 1024LL * 1024 * 16 * 1 #define ITERATIONS 2 /** * Number of put operations equivalent to 1/10th of MAX_SIZE */ #define PUT_10 (MAX_SIZE / 32 / 1024 / ITERATIONS) static char category[256]; static unsigned int hits[PUT_10 / 8 + 1]; static unsigned long long stored_bytes; static unsigned long long stored_entries; static unsigned long long stored_ops; static const char *plugin_name; static int ok; enum RunPhase { RP_ERROR = 0, RP_PUT, RP_REP_GET, RP_ZA_GET, RP_EXP_GET, RP_DONE }; struct CpsRunContext { unsigned int i; struct GNUNET_TIME_Absolute start; struct GNUNET_TIME_Absolute end; const struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_DATASTORE_PluginFunctions *api; enum RunPhase phase; unsigned int cnt; unsigned int iter; uint64_t offset; }; /** * Function called by plugins to notify us about a * change in their disk utilization. * * @param cls closure (NULL) * @param delta change in disk utilization, * 0 for "reset to empty" */ static void disk_utilization_change_cb (void *cls, int delta) { } static void putValue (struct GNUNET_DATASTORE_PluginFunctions *api, int i, int k) { char value[65536]; size_t size; static struct GNUNET_HashCode key; static int ic; char *msg; unsigned int prio; /* most content is 32k */ size = 32 * 1024; if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16) == 0) /* but some of it is less! */ size = 8 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 32 * 1024); size = size - (size & 7); /* always multiple of 8 */ /* generate random key */ key.bits[0] = (unsigned int) GNUNET_TIME_absolute_get ().abs_value_us; GNUNET_CRYPTO_hash (&key, sizeof (struct GNUNET_HashCode), &key); memset (value, i, size); if (i > 255) memset (value, i - 255, size / 2); value[0] = k; memcpy (&value[4], &i, sizeof (i)); msg = NULL; prio = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 100); if (GNUNET_OK != api->put (api->cls, &key, size, value, 1 + i % 4 /* type */ , prio, i % 4 /* anonymity */ , 0 /* replication */ , GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 60 * 60 * 60 * 1000 + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000))), &msg)) { FPRINTF (stderr, "ERROR: `%s'\n", msg); GNUNET_free_non_null (msg); return; } ic++; stored_bytes += size; stored_ops++; stored_entries++; } static void test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static int iterate_zeros (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; int i; const char *cdata = data; GNUNET_assert (key != NULL); GNUNET_assert (size >= 8); memcpy (&i, &cdata[4], sizeof (i)); hits[i / 8] |= (1 << (i % 8)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found result %d type=%u, priority=%u, size=%u, expire=%s\n", i, type, priority, size, GNUNET_STRINGS_absolute_time_to_string (expiration)); crc->cnt++; if (crc->cnt == PUT_10 / 4 - 1) { unsigned int bc; bc = 0; for (i = 0; i < PUT_10; i++) if (0 != (hits[i / 8] & (1 << (i % 8)))) bc++; crc->end = GNUNET_TIME_absolute_get (); printf ("%s took %s yielding %u/%u items\n", "Select random zero-anonymity item", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (crc->start, crc->end), GNUNET_YES), bc, crc->cnt); if (crc->cnt > 0) GAUGER (category, "Select random zero-anonymity item", (crc->end.abs_value_us - crc->start.abs_value_us) / 1000LL / crc->cnt, "ms/item"); memset (hits, 0, sizeof (hits)); crc->phase++; crc->cnt = 0; crc->start = GNUNET_TIME_absolute_get (); } GNUNET_SCHEDULER_add_now (&test, crc); return GNUNET_OK; } static int expiration_get (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; int i; const char *cdata = data; GNUNET_assert (size >= 8); memcpy (&i, &cdata[4], sizeof (i)); hits[i / 8] |= (1 << (i % 8)); crc->cnt++; if (PUT_10 <= crc->cnt) { unsigned int bc; bc = 0; for (i = 0; i < PUT_10; i++) if (0 != (hits[i / 8] & (1 << (i % 8)))) bc++; crc->end = GNUNET_TIME_absolute_get (); printf ("%s took %s yielding %u/%u items\n", "Selecting and deleting by expiration", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (crc->start, crc->end), GNUNET_YES), bc, (unsigned int) PUT_10); if (crc->cnt > 0) GAUGER (category, "Selecting and deleting by expiration", (crc->end.abs_value_us - crc->start.abs_value_us) / 1000LL / crc->cnt, "ms/item"); memset (hits, 0, sizeof (hits)); if (++crc->iter == ITERATIONS) crc->phase++; else crc->phase = RP_PUT; crc->cnt = 0; crc->start = GNUNET_TIME_absolute_get (); } GNUNET_SCHEDULER_add_now (&test, crc); return GNUNET_NO; } static int replication_get (void *cls, const struct GNUNET_HashCode * key, uint32_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; int i; const char *cdata = data; GNUNET_assert (NULL != key); GNUNET_assert (size >= 8); memcpy (&i, &cdata[4], sizeof (i)); hits[i / 8] |= (1 << (i % 8)); crc->cnt++; if (PUT_10 <= crc->cnt) { unsigned int bc; bc = 0; for (i = 0; i < PUT_10; i++) if (0 != (hits[i / 8] & (1 << (i % 8)))) bc++; crc->end = GNUNET_TIME_absolute_get (); printf ("%s took %s yielding %u/%u items\n", "Selecting random item for replication", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (crc->start, crc->end), GNUNET_YES), bc, (unsigned int) PUT_10); if (crc->cnt > 0) GAUGER (category, "Selecting random item for replication", (crc->end.abs_value_us - crc->start.abs_value_us) / 1000LL / crc->cnt, "ms/item"); memset (hits, 0, sizeof (hits)); crc->phase++; crc->offset = 0; crc->cnt = 0; crc->start = GNUNET_TIME_absolute_get (); } GNUNET_SCHEDULER_add_now (&test, crc); return GNUNET_OK; } /** * Function called when the service shuts * down. Unloads our datastore plugin. * * @param api api to unload * @param cfg configuration to use */ static void unload_plugin (struct GNUNET_DATASTORE_PluginFunctions *api, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *name; char *libname; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "DATASTORE", "DATABASE", &name)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No `%s' specified for `%s' in configuration!\n"), "DATABASE", "DATASTORE"); return; } GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", name); GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api)); GNUNET_free (libname); GNUNET_free (name); } /** * Last task run during shutdown. Disconnects us from * the transport and core. */ static void cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CpsRunContext *crc = cls; unload_plugin (crc->api, crc->cfg); GNUNET_free (crc); } static void test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CpsRunContext *crc = cls; int j; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { GNUNET_break (0); crc->phase = RP_ERROR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In phase %d, iteration %u\n", crc->phase, crc->cnt); switch (crc->phase) { case RP_ERROR: GNUNET_break (0); crc->api->drop (crc->api->cls); ok = 1; GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &cleaning_task, crc); break; case RP_PUT: crc->start = GNUNET_TIME_absolute_get (); for (j = 0; j < PUT_10; j++) putValue (crc->api, j, crc->i); crc->end = GNUNET_TIME_absolute_get (); { printf ("%s took %s for %llu items\n", "Storing an item", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_difference (crc->start, crc->end), GNUNET_YES), PUT_10); if (PUT_10 > 0) GAUGER (category, "Storing an item", (crc->end.abs_value_us - crc->start.abs_value_us) / 1000LL / PUT_10, "ms/item"); } crc->i++; crc->start = GNUNET_TIME_absolute_get (); crc->phase++; GNUNET_SCHEDULER_add_now (&test, crc); break; case RP_REP_GET: crc->api->get_replication (crc->api->cls, &replication_get, crc); break; case RP_ZA_GET: crc->api->get_zero_anonymity (crc->api->cls, crc->offset++, 1, &iterate_zeros, crc); break; case RP_EXP_GET: crc->api->get_expiration (crc->api->cls, &expiration_get, crc); break; case RP_DONE: crc->api->drop (crc->api->cls); ok = 0; GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &cleaning_task, crc); break; } } /** * Load the datastore plugin. */ static struct GNUNET_DATASTORE_PluginFunctions * load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg) { static struct GNUNET_DATASTORE_PluginEnvironment env; struct GNUNET_DATASTORE_PluginFunctions *ret; char *name; char *libname; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "DATASTORE", "DATABASE", &name)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No `%s' specified for `%s' in configuration!\n"), "DATABASE", "DATASTORE"); return NULL; } env.cfg = cfg; env.duc = &disk_utilization_change_cb; env.cls = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading `%s' datastore plugin\n"), name); GNUNET_asprintf (&libname, "libgnunet_plugin_datastore_%s", name); if (NULL == (ret = GNUNET_PLUGIN_load (libname, &env))) { FPRINTF (stderr, "Failed to load plugin `%s'!\n", name); GNUNET_free (name); GNUNET_free (libname); return NULL; } GNUNET_free (libname); GNUNET_free (name); return ret; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_DATASTORE_PluginFunctions *api; struct CpsRunContext *crc; if (NULL == c) { GNUNET_break (0); return; } api = load_plugin (c); if (api == NULL) { FPRINTF (stderr, "%s", "Could not initialize plugin, assuming database not configured. Test not run!\n"); return; } crc = GNUNET_new (struct CpsRunContext); crc->api = api; crc->cfg = c; crc->phase = RP_PUT; ok = 2; GNUNET_SCHEDULER_add_now (&test, crc); } int main (int argc, char *argv[]) { char dir_name[128]; char cfg_name[128]; char *const xargv[] = { "perf-plugin-datastore", "-c", cfg_name, NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (dir_name, sizeof (dir_name), "/tmp/perf-gnunet-datastore-%s", plugin_name); GNUNET_DISK_directory_remove (dir_name); GNUNET_log_setup ("perf-plugin-datastore", "WARNING", NULL); GNUNET_snprintf (category, sizeof (category), "DATASTORE-%s", plugin_name); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "perf_plugin_datastore_data_%s.conf", plugin_name); GNUNET_PROGRAM_run ((sizeof (xargv) / sizeof (char *)) - 1, xargv, "perf-plugin-datastore", "nohelp", options, &run, NULL); if (ok != 0) FPRINTF (stderr, "Missed some testcases: %u\n", ok); GNUNET_DISK_directory_remove (dir_name); return ok; } /* end of perf_plugin_datastore.c */ gnunet-0.10.1/src/datastore/datastore.conf.in0000644000175000017500000000123512250373167016040 00000000000000[datastore] AUTOSTART = @AUTOSTART@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-datastore.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES @UNIXONLY@ PORT = 2093 HOSTNAME = localhost BINARY = gnunet-service-datastore ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; QUOTA = 5 GB BLOOMFILTER = $GNUNET_DATA_HOME/datastore/bloomfilter DATABASE = sqlite # DISABLE_SOCKET_FORWARDING = NO [datastore-sqlite] FILENAME = $GNUNET_DATA_HOME/datastore/sqlite.db [datastore-postgres] CONFIG = connect_timeout=10; dbname=gnunet [datastore-mysql] DATABASE = gnunet CONFIG = ~/.my.cnf # USER = gnunet # PASSWORD = # HOST = localhost # PORT = 3306 [datastore-heap] HASHMAPSIZE = 1024 gnunet-0.10.1/src/datastore/test_datastore_api.c0000644000175000017500000003544012255010512016610 00000000000000/* This file is part of GNUnet. (C) 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * @file datastore/test_datastore_api.c * @brief Test for the basic datastore API. * @author Christian Grothoff * * TODO: * - test reservation failure */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_datastore_service.h" #include "gnunet_testing_lib.h" /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15) #define ITERATIONS 256 static struct GNUNET_DATASTORE_Handle *datastore; static struct GNUNET_TIME_Absolute now; static int ok; /** * Name of plugin under test. */ static const char *plugin_name; static size_t get_size (int i) { return 8 * i; } static const void * get_data (int i) { static char buf[60000]; memset (buf, i, 8 * i); return buf; } static int get_type (int i) { return i + 1; } static int get_priority (int i) { return i + 1; } static int get_anonymity (int i) { return i; } static struct GNUNET_TIME_Absolute get_expiration (int i) { struct GNUNET_TIME_Absolute av; av.abs_value_us = now.abs_value_us + 20000000000LL - i * 1000 * 1000LL; return av; } enum RunPhase { RP_DONE = 0, RP_PUT = 1, RP_GET = 2, RP_DEL = 3, RP_DO_DEL = 4, RP_DELVALIDATE = 5, RP_RESERVE = 6, RP_PUT_MULTIPLE = 7, RP_PUT_MULTIPLE_NEXT = 8, RP_GET_MULTIPLE = 9, RP_GET_MULTIPLE_NEXT = 10, RP_UPDATE = 11, RP_UPDATE_VALIDATE = 12, RP_ERROR }; struct CpsRunContext { struct GNUNET_HashCode key; int i; int rid; const struct GNUNET_CONFIGURATION_Handle *cfg; void *data; size_t size; enum RunPhase phase; uint64_t uid; uint64_t offset; uint64_t first_uid; }; static void run_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void check_success (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct CpsRunContext *crc = cls; if (GNUNET_OK != success) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Operation %d/%d not successfull: `%s'\n", crc->phase, crc->i, msg); crc->phase = RP_ERROR; } GNUNET_free_non_null (crc->data); crc->data = NULL; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void get_reserved (void *cls, int success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct CpsRunContext *crc = cls; if (0 >= success) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error obtaining reservation: `%s'\n", msg); GNUNET_assert (0 < success); crc->rid = success; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void check_value (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; int i; i = crc->i; if (NULL == key) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value check failed (got NULL key) in %d/%d\n", crc->phase, crc->i); crc->phase = RP_ERROR; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); return; } #if 0 FPRINTF (stderr, "Check value got `%s' of size %u, type %d, expire %s\n", GNUNET_h2s (key), (unsigned int) size, type, GNUNET_STRINGS_absolute_time_to_string (expiration)); FPRINTF (stderr, "Check value iteration %d wants size %u, type %d, expire %s\n", i, (unsigned int) get_size (i), get_type (i), GNUNET_STRINGS_absolute_time_to_string (get_expiration(i))); #endif GNUNET_assert (size == get_size (i)); GNUNET_assert (0 == memcmp (data, get_data (i), size)); GNUNET_assert (type == get_type (i)); GNUNET_assert (priority == get_priority (i)); GNUNET_assert (anonymity == get_anonymity (i)); GNUNET_assert (expiration.abs_value_us == get_expiration (i).abs_value_us); crc->offset++; if (crc->i == 0) { crc->phase = RP_DEL; crc->i = ITERATIONS; } GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void delete_value (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; GNUNET_assert (crc->data == NULL); GNUNET_assert (NULL != key); crc->size = size; crc->key = *key; crc->data = GNUNET_malloc (size); memcpy (crc->data, data, size); crc->phase = RP_DO_DEL; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void check_nothing (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; GNUNET_assert (key == NULL); if (crc->i == 0) crc->phase = RP_RESERVE; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void check_multiple (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; GNUNET_assert (key != NULL); switch (crc->phase) { case RP_GET_MULTIPLE: crc->phase = RP_GET_MULTIPLE_NEXT; crc->first_uid = uid; crc->offset++; break; case RP_GET_MULTIPLE_NEXT: GNUNET_assert (uid != crc->first_uid); crc->phase = RP_UPDATE; break; default: GNUNET_break (0); crc->phase = RP_ERROR; break; } if (priority == get_priority (42)) crc->uid = uid; GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void check_update (void *cls, const struct GNUNET_HashCode * key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { struct CpsRunContext *crc = cls; GNUNET_assert (key != NULL); if ((anonymity == get_anonymity (42)) && (size == get_size (42)) && (priority == get_priority (42) + 100)) crc->phase = RP_DONE; else { GNUNET_assert (size == get_size (43)); crc->offset++; } GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } static void run_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CpsRunContext *crc = cls; ok = (int) crc->phase; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test in phase %u\n", crc->phase); switch (crc->phase) { case RP_PUT: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "PUT", crc->i); GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); GNUNET_DATASTORE_put (datastore, 0, &crc->key, get_size (crc->i), get_data (crc->i), get_type (crc->i), get_priority (crc->i), get_anonymity (crc->i), 0, get_expiration (crc->i), 1, 1, TIMEOUT, &check_success, crc); crc->i++; if (crc->i == ITERATIONS) crc->phase = RP_GET; break; case RP_GET: crc->i--; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "GET", crc->i); GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); GNUNET_DATASTORE_get_key (datastore, crc->offset, &crc->key, get_type (crc->i), 1, 1, TIMEOUT, &check_value, crc); break; case RP_DEL: crc->i--; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "DEL", crc->i); crc->data = NULL; GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); GNUNET_assert (NULL != GNUNET_DATASTORE_get_key (datastore, crc->offset, &crc->key, get_type (crc->i), 1, 1, TIMEOUT, &delete_value, crc)); break; case RP_DO_DEL: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "DO_DEL", crc->i); if (crc->i == 0) { crc->i = ITERATIONS; crc->phase = RP_DELVALIDATE; } else { crc->phase = RP_DEL; } GNUNET_assert (NULL != GNUNET_DATASTORE_remove (datastore, &crc->key, crc->size, crc->data, 1, 1, TIMEOUT, &check_success, crc)); break; case RP_DELVALIDATE: crc->i--; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Executing `%s' number %u\n", "DEL-VALIDATE", crc->i); GNUNET_CRYPTO_hash (&crc->i, sizeof (int), &crc->key); GNUNET_assert (NULL != GNUNET_DATASTORE_get_key (datastore, crc->offset, &crc->key, get_type (crc->i), 1, 1, TIMEOUT, &check_nothing, crc)); break; case RP_RESERVE: crc->phase = RP_PUT_MULTIPLE; GNUNET_DATASTORE_reserve (datastore, 128 * 1024, 2, 1, 1, TIMEOUT, &get_reserved, crc); break; case RP_PUT_MULTIPLE: crc->phase = RP_PUT_MULTIPLE_NEXT; GNUNET_DATASTORE_put (datastore, crc->rid, &crc->key, get_size (42), get_data (42), get_type (42), get_priority (42), get_anonymity (42), 0, get_expiration (42), 1, 1, TIMEOUT, &check_success, crc); break; case RP_PUT_MULTIPLE_NEXT: crc->phase = RP_GET_MULTIPLE; GNUNET_DATASTORE_put (datastore, crc->rid, &crc->key, get_size (43), get_data (43), get_type (42), get_priority (43), get_anonymity (43), 0, get_expiration (43), 1, 1, TIMEOUT, &check_success, crc); break; case RP_GET_MULTIPLE: GNUNET_assert (NULL != GNUNET_DATASTORE_get_key (datastore, crc->offset, &crc->key, get_type (42), 1, 1, TIMEOUT, &check_multiple, crc)); break; case RP_GET_MULTIPLE_NEXT: GNUNET_assert (NULL != GNUNET_DATASTORE_get_key (datastore, crc->offset, &crc->key, get_type (42), 1, 1, TIMEOUT, &check_multiple, crc)); break; case RP_UPDATE: GNUNET_assert (crc->uid > 0); crc->phase = RP_UPDATE_VALIDATE; GNUNET_DATASTORE_update (datastore, crc->uid, 100, get_expiration (42), 1, 1, TIMEOUT, &check_success, crc); break; case RP_UPDATE_VALIDATE: GNUNET_assert (NULL != GNUNET_DATASTORE_get_key (datastore, crc->offset, &crc->key, get_type (42), 1, 1, TIMEOUT, &check_update, crc)); break; case RP_DONE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished, disconnecting\n"); GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); ok = 0; break; case RP_ERROR: GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); ok = 43; break; } } static void run_tests (void *cls, int32_t success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { struct CpsRunContext *crc = cls; switch (success) { case GNUNET_YES: GNUNET_SCHEDULER_add_continuation (&run_continuation, crc, GNUNET_SCHEDULER_REASON_PREREQ_DONE); return; case GNUNET_NO: FPRINTF (stderr, "%s", "Test 'put' operation failed, key already exists (!?)\n"); GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); return; case GNUNET_SYSERR: FPRINTF (stderr, "Test 'put' operation failed with error `%s' database likely not setup, skipping test.\n", msg); GNUNET_DATASTORE_disconnect (datastore, GNUNET_YES); GNUNET_free (crc); return; default: GNUNET_assert (0); } } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct CpsRunContext *crc; static struct GNUNET_HashCode zkey; crc = GNUNET_new (struct CpsRunContext); crc->cfg = cfg; crc->phase = RP_PUT; now = GNUNET_TIME_absolute_get (); datastore = GNUNET_DATASTORE_connect (cfg); if (NULL == GNUNET_DATASTORE_put (datastore, 0, &zkey, 4, "TEST", GNUNET_BLOCK_TYPE_TEST, 0, 0, 0, GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_SECONDS), 0, 1, GNUNET_TIME_UNIT_MINUTES, &run_tests, crc)) { FPRINTF (stderr, "%s", "Test 'put' operation failed.\n"); ok = 1; GNUNET_free (crc); } } int main (int argc, char *argv[]) { char cfg_name[128]; plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); GNUNET_snprintf (cfg_name, sizeof (cfg_name), "test_datastore_api_data_%s.conf", plugin_name); if (0 != GNUNET_TESTING_peer_run ("test-gnunet-datastore", cfg_name, &run, NULL)) return 1; return ok; } /* end of test_datastore_api.c */ gnunet-0.10.1/src/datastore/gnunet-datastore.c0000644000175000017500000001441612225777502016236 00000000000000/* This file is part of GNUnet. (C) 2010, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file datastore/gnunet-datastore.c * @brief tool to manipulate datastores * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_datastore_service.h" /** * Name of the second configuration file. */ static char *alternative_cfg; /** * Global return value. */ static int ret; /** * Our offset on 'get'. */ static uint64_t offset; /** * First UID ever returned. */ static uint64_t first_uid; /** * Configuration for the source database. */ static struct GNUNET_CONFIGURATION_Handle *scfg; /** * Handle for database source. */ static struct GNUNET_DATASTORE_Handle *db_src; /** * Handle for database destination. */ static struct GNUNET_DATASTORE_Handle *db_dst; /** * Current operation. */ static struct GNUNET_DATASTORE_QueueEntry *qe; static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != qe) GNUNET_DATASTORE_cancel (qe); GNUNET_DATASTORE_disconnect (db_src, GNUNET_NO); GNUNET_DATASTORE_disconnect (db_dst, GNUNET_NO); GNUNET_CONFIGURATION_destroy (scfg); } /** * Perform next GET operation. */ static void do_get (void); /** * Continuation called to notify client about result of the * operation. * * @param cls closure * @param success GNUNET_SYSERR on failure (including timeout/queue drop) * GNUNET_NO if content was already there * GNUNET_YES (or other positive value) on success * @param min_expiration minimum expiration time required for 0-priority content to be stored * by the datacache at this time, zero for unknown, forever if we have no * space for 0-priority content * @param msg NULL on success, otherwise an error message */ static void do_finish (void *cls, int32_t success, struct GNUNET_TIME_Absolute min_expiration, const char *msg) { qe = NULL; if (GNUNET_SYSERR == success) { fprintf (stderr, _("Failed to store item: %s, aborting\n"), msg); ret = 1; GNUNET_SCHEDULER_shutdown (); return; } do_get (); } /** * Process a datum that was stored in the datastore. * * @param cls closure * @param key key for the content * @param size number of bytes in data * @param data content stored * @param type type of the content * @param priority priority of the content * @param anonymity anonymity-level for the content * @param expiration expiration time for the content * @param uid unique identifier for the datum; * maybe 0 if no unique identifier is available */ static void do_put (void *cls, const struct GNUNET_HashCode *key, size_t size, const void *data, enum GNUNET_BLOCK_Type type, uint32_t priority, uint32_t anonymity, struct GNUNET_TIME_Absolute expiration, uint64_t uid) { qe = NULL; if ( (0 != offset) && (uid == first_uid) ) { GNUNET_SCHEDULER_shutdown (); return; } if (0 == offset) first_uid = uid; qe = GNUNET_DATASTORE_put (db_dst, 0, key, size, data, type, priority, anonymity, 0 /* FIXME: replication is lost... */, expiration, 0, 1, GNUNET_TIME_UNIT_FOREVER_REL, &do_finish, NULL); } /** * Perform next GET operation. */ static void do_get () { qe = GNUNET_DATASTORE_get_key (db_src, offset, NULL, GNUNET_BLOCK_TYPE_ANY, 0, 1, GNUNET_TIME_UNIT_FOREVER_REL, &do_put, NULL); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used * @param cfg configuration -- for destination datastore */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { if (NULL == alternative_cfg) return; /* nothing to be done */ if (0 == strcmp (cfgfile, alternative_cfg)) { fprintf (stderr, _("Cannot use the same configuration for source and destination\n")); ret = 1; return; } scfg = GNUNET_CONFIGURATION_create (); if (GNUNET_OK != GNUNET_CONFIGURATION_load (scfg, alternative_cfg)) { GNUNET_CONFIGURATION_destroy (scfg); ret = 1; return; } db_src = GNUNET_DATASTORE_connect (scfg); if (NULL == db_src) { GNUNET_CONFIGURATION_destroy (scfg); ret = 1; return; } db_dst = GNUNET_DATASTORE_connect (cfg); if (NULL == db_dst) { GNUNET_DATASTORE_disconnect (db_src, GNUNET_NO); GNUNET_CONFIGURATION_destroy (scfg); ret = 1; return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); do_get (); } /** * The main function to manipulate datastores. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 's', "sourcecfg", "FILENAME", gettext_noop ("specifies the configuration to use to access an alternative datastore; will merge that datastore into our current datastore"), 1, &GNUNET_GETOPT_set_filename, &alternative_cfg }, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "gnunet-datastore", gettext_noop ("Manipulate GNUnet datastore"), options, &run, NULL)) ret = 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-datastore.c */ gnunet-0.10.1/src/datastore/test_datastore_api_data_postgres.conf0000644000175000017500000000051212225230043022222 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-datastore-postgres/ [TESTING] WEAKRANDOM = YES [arm] PORT = 42466 DEFAULTSERVICES = [statistics] PORT = 22667 [resolver] PORT = 42464 [datastore] QUOTA = 10 MB DATABASE = postgres [datastore-postgres] CONFIG = dbname=gnunetcheck [fs] AUTOSTART = NO gnunet-0.10.1/src/datastore/test_defaults.conf0000644000175000017500000000047112225230043016277 00000000000000[datastore] PORT = 22654 QUOTA = 1 MB [dht] AUTOSTART = NO [dns] AUTOSTART = NO [mesh] AUTOSTART = NO [nse] AUTOSTART = NO [dv] AUTOSTART = NO [chat] AUTOSTART = NO [vpn] AUTOSTART = NO [gns] AUTOSTART = NO [dv] AUTOSTART = NO [namestore] AUTOSTART = NO [fs] AUTOSTART = NO [consensus] AUTOSTART = NO gnunet-0.10.1/src/datastore/perf_plugin_datastore_data_sqlite.conf0000644000175000017500000000013312225230043022356 00000000000000@INLINE@ test_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/perf-gnunet-datastore-sqlite/ gnunet-0.10.1/src/pt/0000755000175000017500000000000012320755627011315 500000000000000gnunet-0.10.1/src/pt/Makefile.in0000644000175000017500000016236012320752063013301 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-daemon-pt$(EXEEXT) check_PROGRAMS = $(am__EXEEXT_1) subdir = src/pt DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(dist_pkgcfg_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_FALSE@@MINGW_TRUE@am__EXEEXT_1 = test_gnunet_vpn-4_to_6$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_FALSE@@MINGW_TRUE@ test_gnunet_vpn-6_to_4$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_FALSE@@MINGW_TRUE@ test_gnunet_vpn-6_over$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_FALSE@@MINGW_TRUE@ test_gnunet_vpn-4_over$(EXEEXT) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@am__EXEEXT_1 = test_gnunet_vpn-4_to_6$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gnunet_vpn-6_to_4$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gnunet_vpn-6_over$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gnunet_vpn-4_over$(EXEEXT) \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gns_vpn$(EXEEXT) am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" PROGRAMS = $(libexec_PROGRAMS) am_gnunet_daemon_pt_OBJECTS = gnunet-daemon-pt.$(OBJEXT) gnunet_daemon_pt_OBJECTS = $(am_gnunet_daemon_pt_OBJECTS) am__DEPENDENCIES_1 = gnunet_daemon_pt_DEPENDENCIES = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_test_gns_vpn_OBJECTS = test_gns_vpn-test_gns_vpn.$(OBJEXT) test_gns_vpn_OBJECTS = $(am_test_gns_vpn_OBJECTS) test_gns_vpn_DEPENDENCIES = \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_vpn_4_over_OBJECTS = \ test_gnunet_vpn_4_over-test_gnunet_vpn.$(OBJEXT) test_gnunet_vpn_4_over_OBJECTS = $(am_test_gnunet_vpn_4_over_OBJECTS) test_gnunet_vpn_4_over_DEPENDENCIES = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_vpn_4_to_6_OBJECTS = \ test_gnunet_vpn_4_to_6-test_gnunet_vpn.$(OBJEXT) test_gnunet_vpn_4_to_6_OBJECTS = $(am_test_gnunet_vpn_4_to_6_OBJECTS) test_gnunet_vpn_4_to_6_DEPENDENCIES = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_vpn_6_over_OBJECTS = \ test_gnunet_vpn_6_over-test_gnunet_vpn.$(OBJEXT) test_gnunet_vpn_6_over_OBJECTS = $(am_test_gnunet_vpn_6_over_OBJECTS) test_gnunet_vpn_6_over_DEPENDENCIES = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnunet_vpn_6_to_4_OBJECTS = \ test_gnunet_vpn_6_to_4-test_gnunet_vpn.$(OBJEXT) test_gnunet_vpn_6_to_4_OBJECTS = $(am_test_gnunet_vpn_6_to_4_OBJECTS) test_gnunet_vpn_6_to_4_DEPENDENCIES = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gnunet_daemon_pt_SOURCES) $(test_gns_vpn_SOURCES) \ $(test_gnunet_vpn_4_over_SOURCES) \ $(test_gnunet_vpn_4_to_6_SOURCES) \ $(test_gnunet_vpn_6_over_SOURCES) \ $(test_gnunet_vpn_6_to_4_SOURCES) DIST_SOURCES = $(gnunet_daemon_pt_SOURCES) $(test_gns_vpn_SOURCES) \ $(test_gnunet_vpn_4_over_SOURCES) \ $(test_gnunet_vpn_4_to_6_SOURCES) \ $(test_gnunet_vpn_6_over_SOURCES) \ $(test_gnunet_vpn_6_to_4_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } DATA = $(dist_pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 pkgcfgdir = $(pkgdatadir)/config.d/ plugindir = $(libdir)/gnunet dist_pkgcfg_DATA = \ pt.conf gnunet_daemon_pt_SOURCES = \ gnunet-daemon-pt.c gnunet_daemon_pt_LDADD = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@VPN_TEST = \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gnunet_vpn-4_to_6 \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gnunet_vpn-6_to_4 \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gnunet_vpn-6_over \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gnunet_vpn-4_over \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@LINUX_TRUE@ test_gns_vpn @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@MINGW_TRUE@VPN_TEST = \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@MINGW_TRUE@ test_gnunet_vpn-4_to_6 \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@MINGW_TRUE@ test_gnunet_vpn-6_to_4 \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@MINGW_TRUE@ test_gnunet_vpn-6_over \ @HAVE_LIBGNURL_TRUE@@HAVE_MHD_TRUE@@HAVE_TESTING_TRUE@@MINGW_TRUE@ test_gnunet_vpn-4_over @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) EXTRA_DIST = \ test_gnunet_vpn.conf \ test_gns_vpn.conf test_gns_vpn_SOURCES = \ test_gns_vpn.c test_gns_vpn_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gns_vpn_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) test_gnunet_vpn_4_over_SOURCES = \ test_gnunet_vpn.c test_gnunet_vpn_4_over_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_vpn_4_over_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) test_gnunet_vpn_6_over_SOURCES = \ test_gnunet_vpn.c test_gnunet_vpn_6_over_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_vpn_6_over_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) test_gnunet_vpn_4_to_6_SOURCES = \ test_gnunet_vpn.c test_gnunet_vpn_4_to_6_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_vpn_4_to_6_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) test_gnunet_vpn_6_to_4_SOURCES = \ test_gnunet_vpn.c test_gnunet_vpn_6_to_4_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_vpn_6_to_4_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/pt/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/pt/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-daemon-pt$(EXEEXT): $(gnunet_daemon_pt_OBJECTS) $(gnunet_daemon_pt_DEPENDENCIES) $(EXTRA_gnunet_daemon_pt_DEPENDENCIES) @rm -f gnunet-daemon-pt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_daemon_pt_OBJECTS) $(gnunet_daemon_pt_LDADD) $(LIBS) test_gns_vpn$(EXEEXT): $(test_gns_vpn_OBJECTS) $(test_gns_vpn_DEPENDENCIES) $(EXTRA_test_gns_vpn_DEPENDENCIES) @rm -f test_gns_vpn$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gns_vpn_OBJECTS) $(test_gns_vpn_LDADD) $(LIBS) test_gnunet_vpn-4_over$(EXEEXT): $(test_gnunet_vpn_4_over_OBJECTS) $(test_gnunet_vpn_4_over_DEPENDENCIES) $(EXTRA_test_gnunet_vpn_4_over_DEPENDENCIES) @rm -f test_gnunet_vpn-4_over$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_vpn_4_over_OBJECTS) $(test_gnunet_vpn_4_over_LDADD) $(LIBS) test_gnunet_vpn-4_to_6$(EXEEXT): $(test_gnunet_vpn_4_to_6_OBJECTS) $(test_gnunet_vpn_4_to_6_DEPENDENCIES) $(EXTRA_test_gnunet_vpn_4_to_6_DEPENDENCIES) @rm -f test_gnunet_vpn-4_to_6$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_vpn_4_to_6_OBJECTS) $(test_gnunet_vpn_4_to_6_LDADD) $(LIBS) test_gnunet_vpn-6_over$(EXEEXT): $(test_gnunet_vpn_6_over_OBJECTS) $(test_gnunet_vpn_6_over_DEPENDENCIES) $(EXTRA_test_gnunet_vpn_6_over_DEPENDENCIES) @rm -f test_gnunet_vpn-6_over$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_vpn_6_over_OBJECTS) $(test_gnunet_vpn_6_over_LDADD) $(LIBS) test_gnunet_vpn-6_to_4$(EXEEXT): $(test_gnunet_vpn_6_to_4_OBJECTS) $(test_gnunet_vpn_6_to_4_DEPENDENCIES) $(EXTRA_test_gnunet_vpn_6_to_4_DEPENDENCIES) @rm -f test_gnunet_vpn-6_to_4$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnunet_vpn_6_to_4_OBJECTS) $(test_gnunet_vpn_6_to_4_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-daemon-pt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gns_vpn-test_gns_vpn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_vpn_4_over-test_gnunet_vpn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_vpn_4_to_6-test_gnunet_vpn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_vpn_6_over-test_gnunet_vpn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnunet_vpn_6_to_4-test_gnunet_vpn.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< test_gns_vpn-test_gns_vpn.o: test_gns_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gns_vpn_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gns_vpn-test_gns_vpn.o -MD -MP -MF $(DEPDIR)/test_gns_vpn-test_gns_vpn.Tpo -c -o test_gns_vpn-test_gns_vpn.o `test -f 'test_gns_vpn.c' || echo '$(srcdir)/'`test_gns_vpn.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gns_vpn-test_gns_vpn.Tpo $(DEPDIR)/test_gns_vpn-test_gns_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gns_vpn.c' object='test_gns_vpn-test_gns_vpn.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gns_vpn_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gns_vpn-test_gns_vpn.o `test -f 'test_gns_vpn.c' || echo '$(srcdir)/'`test_gns_vpn.c test_gns_vpn-test_gns_vpn.obj: test_gns_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gns_vpn_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gns_vpn-test_gns_vpn.obj -MD -MP -MF $(DEPDIR)/test_gns_vpn-test_gns_vpn.Tpo -c -o test_gns_vpn-test_gns_vpn.obj `if test -f 'test_gns_vpn.c'; then $(CYGPATH_W) 'test_gns_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gns_vpn.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gns_vpn-test_gns_vpn.Tpo $(DEPDIR)/test_gns_vpn-test_gns_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gns_vpn.c' object='test_gns_vpn-test_gns_vpn.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gns_vpn_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gns_vpn-test_gns_vpn.obj `if test -f 'test_gns_vpn.c'; then $(CYGPATH_W) 'test_gns_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gns_vpn.c'; fi` test_gnunet_vpn_4_over-test_gnunet_vpn.o: test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_4_over_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_vpn_4_over-test_gnunet_vpn.o -MD -MP -MF $(DEPDIR)/test_gnunet_vpn_4_over-test_gnunet_vpn.Tpo -c -o test_gnunet_vpn_4_over-test_gnunet_vpn.o `test -f 'test_gnunet_vpn.c' || echo '$(srcdir)/'`test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_vpn_4_over-test_gnunet_vpn.Tpo $(DEPDIR)/test_gnunet_vpn_4_over-test_gnunet_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_vpn.c' object='test_gnunet_vpn_4_over-test_gnunet_vpn.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_4_over_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_vpn_4_over-test_gnunet_vpn.o `test -f 'test_gnunet_vpn.c' || echo '$(srcdir)/'`test_gnunet_vpn.c test_gnunet_vpn_4_over-test_gnunet_vpn.obj: test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_4_over_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_vpn_4_over-test_gnunet_vpn.obj -MD -MP -MF $(DEPDIR)/test_gnunet_vpn_4_over-test_gnunet_vpn.Tpo -c -o test_gnunet_vpn_4_over-test_gnunet_vpn.obj `if test -f 'test_gnunet_vpn.c'; then $(CYGPATH_W) 'test_gnunet_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_vpn.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_vpn_4_over-test_gnunet_vpn.Tpo $(DEPDIR)/test_gnunet_vpn_4_over-test_gnunet_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_vpn.c' object='test_gnunet_vpn_4_over-test_gnunet_vpn.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_4_over_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_vpn_4_over-test_gnunet_vpn.obj `if test -f 'test_gnunet_vpn.c'; then $(CYGPATH_W) 'test_gnunet_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_vpn.c'; fi` test_gnunet_vpn_4_to_6-test_gnunet_vpn.o: test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_4_to_6_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_vpn_4_to_6-test_gnunet_vpn.o -MD -MP -MF $(DEPDIR)/test_gnunet_vpn_4_to_6-test_gnunet_vpn.Tpo -c -o test_gnunet_vpn_4_to_6-test_gnunet_vpn.o `test -f 'test_gnunet_vpn.c' || echo '$(srcdir)/'`test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_vpn_4_to_6-test_gnunet_vpn.Tpo $(DEPDIR)/test_gnunet_vpn_4_to_6-test_gnunet_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_vpn.c' object='test_gnunet_vpn_4_to_6-test_gnunet_vpn.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_4_to_6_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_vpn_4_to_6-test_gnunet_vpn.o `test -f 'test_gnunet_vpn.c' || echo '$(srcdir)/'`test_gnunet_vpn.c test_gnunet_vpn_4_to_6-test_gnunet_vpn.obj: test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_4_to_6_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_vpn_4_to_6-test_gnunet_vpn.obj -MD -MP -MF $(DEPDIR)/test_gnunet_vpn_4_to_6-test_gnunet_vpn.Tpo -c -o test_gnunet_vpn_4_to_6-test_gnunet_vpn.obj `if test -f 'test_gnunet_vpn.c'; then $(CYGPATH_W) 'test_gnunet_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_vpn.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_vpn_4_to_6-test_gnunet_vpn.Tpo $(DEPDIR)/test_gnunet_vpn_4_to_6-test_gnunet_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_vpn.c' object='test_gnunet_vpn_4_to_6-test_gnunet_vpn.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_4_to_6_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_vpn_4_to_6-test_gnunet_vpn.obj `if test -f 'test_gnunet_vpn.c'; then $(CYGPATH_W) 'test_gnunet_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_vpn.c'; fi` test_gnunet_vpn_6_over-test_gnunet_vpn.o: test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_6_over_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_vpn_6_over-test_gnunet_vpn.o -MD -MP -MF $(DEPDIR)/test_gnunet_vpn_6_over-test_gnunet_vpn.Tpo -c -o test_gnunet_vpn_6_over-test_gnunet_vpn.o `test -f 'test_gnunet_vpn.c' || echo '$(srcdir)/'`test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_vpn_6_over-test_gnunet_vpn.Tpo $(DEPDIR)/test_gnunet_vpn_6_over-test_gnunet_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_vpn.c' object='test_gnunet_vpn_6_over-test_gnunet_vpn.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_6_over_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_vpn_6_over-test_gnunet_vpn.o `test -f 'test_gnunet_vpn.c' || echo '$(srcdir)/'`test_gnunet_vpn.c test_gnunet_vpn_6_over-test_gnunet_vpn.obj: test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_6_over_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_vpn_6_over-test_gnunet_vpn.obj -MD -MP -MF $(DEPDIR)/test_gnunet_vpn_6_over-test_gnunet_vpn.Tpo -c -o test_gnunet_vpn_6_over-test_gnunet_vpn.obj `if test -f 'test_gnunet_vpn.c'; then $(CYGPATH_W) 'test_gnunet_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_vpn.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_vpn_6_over-test_gnunet_vpn.Tpo $(DEPDIR)/test_gnunet_vpn_6_over-test_gnunet_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_vpn.c' object='test_gnunet_vpn_6_over-test_gnunet_vpn.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_6_over_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_vpn_6_over-test_gnunet_vpn.obj `if test -f 'test_gnunet_vpn.c'; then $(CYGPATH_W) 'test_gnunet_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_vpn.c'; fi` test_gnunet_vpn_6_to_4-test_gnunet_vpn.o: test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_6_to_4_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_vpn_6_to_4-test_gnunet_vpn.o -MD -MP -MF $(DEPDIR)/test_gnunet_vpn_6_to_4-test_gnunet_vpn.Tpo -c -o test_gnunet_vpn_6_to_4-test_gnunet_vpn.o `test -f 'test_gnunet_vpn.c' || echo '$(srcdir)/'`test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_vpn_6_to_4-test_gnunet_vpn.Tpo $(DEPDIR)/test_gnunet_vpn_6_to_4-test_gnunet_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_vpn.c' object='test_gnunet_vpn_6_to_4-test_gnunet_vpn.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_6_to_4_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_vpn_6_to_4-test_gnunet_vpn.o `test -f 'test_gnunet_vpn.c' || echo '$(srcdir)/'`test_gnunet_vpn.c test_gnunet_vpn_6_to_4-test_gnunet_vpn.obj: test_gnunet_vpn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_6_to_4_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_gnunet_vpn_6_to_4-test_gnunet_vpn.obj -MD -MP -MF $(DEPDIR)/test_gnunet_vpn_6_to_4-test_gnunet_vpn.Tpo -c -o test_gnunet_vpn_6_to_4-test_gnunet_vpn.obj `if test -f 'test_gnunet_vpn.c'; then $(CYGPATH_W) 'test_gnunet_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_vpn.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gnunet_vpn_6_to_4-test_gnunet_vpn.Tpo $(DEPDIR)/test_gnunet_vpn_6_to_4-test_gnunet_vpn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_gnunet_vpn.c' object='test_gnunet_vpn_6_to_4-test_gnunet_vpn.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_gnunet_vpn_6_to_4_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_gnunet_vpn_6_to_4-test_gnunet_vpn.obj `if test -f 'test_gnunet_vpn.c'; then $(CYGPATH_W) 'test_gnunet_vpn.c'; else $(CYGPATH_W) '$(srcdir)/test_gnunet_vpn.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_gnunet_vpn-4_to_6.log: test_gnunet_vpn-4_to_6$(EXEEXT) @p='test_gnunet_vpn-4_to_6$(EXEEXT)'; \ b='test_gnunet_vpn-4_to_6'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_vpn-6_to_4.log: test_gnunet_vpn-6_to_4$(EXEEXT) @p='test_gnunet_vpn-6_to_4$(EXEEXT)'; \ b='test_gnunet_vpn-6_to_4'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_vpn-6_over.log: test_gnunet_vpn-6_over$(EXEEXT) @p='test_gnunet_vpn-6_over$(EXEEXT)'; \ b='test_gnunet_vpn-6_over'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnunet_vpn-4_over.log: test_gnunet_vpn-4_over$(EXEEXT) @p='test_gnunet_vpn-4_over$(EXEEXT)'; \ b='test_gnunet_vpn-4_over'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gns_vpn.log: test_gns_vpn$(EXEEXT) @p='test_gns_vpn$(EXEEXT)'; \ b='test_gns_vpn'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_pkgcfgDATA uninstall-libexecPROGRAMS .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libexecPROGRAMS \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-dist_pkgcfgDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-dist_pkgcfgDATA \ uninstall-libexecPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/pt/pt.conf0000644000175000017500000000036312225230043012511 00000000000000[pt] BINARY = gnunet-daemon-pt # Set this to YES to tunnel IPv4 traffic over GNUnet TUNNEL_IPV4 = NO # Set this to YES to tunnel IPv6 traffic over GNUnet TUNNEL_IPV6 = NO # Set this to YES to tunnel DNS traffic over GNUnet TUNNEL_DNS = NO gnunet-0.10.1/src/pt/test_gns_vpn.c0000644000175000017500000003565112252673741014124 00000000000000/* This file is part of GNUnet (C) 2007, 2009, 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file test_gns_vpn.c * @brief testcase for accessing VPN services via GNS * @author Martin Schanzenbach */ #include "platform.h" #include #include #include "gnunet_namestore_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gns_service.h" #include "gnunet_testing_lib.h" #define PORT 8080 #define TEST_DOMAIN "www.gnu" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) /** * Return value for 'main'. */ static int global_ret; static struct GNUNET_NAMESTORE_Handle *namestore; static struct MHD_Daemon *mhd; static GNUNET_SCHEDULER_TaskIdentifier mhd_task_id; static GNUNET_SCHEDULER_TaskIdentifier curl_task_id; static CURL *curl; static CURLM *multi; static char *url; /** * IP address of the ultimate destination. */ static const char *dest_ip; /** * Address family of the dest_ip. */ static int dest_af; /** * Address family to use by the curl client. */ static int src_af; static int use_v6; struct CBC { char buf[1024]; size_t pos; }; static struct CBC cbc; static size_t copy_buffer (void *ptr, size_t size, size_t nmemb, void *ctx) { struct CBC *cbc = ctx; if (cbc->pos + size * nmemb > sizeof(cbc->buf)) return 0; /* overflow */ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); cbc->pos += size * nmemb; return size * nmemb; } static int mhd_ahc (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **unused) { static int ptr; struct MHD_Response *response; int ret; if (0 != strcmp ("GET", method)) return MHD_NO; /* unexpected method */ if (&ptr != *unused) { *unused = &ptr; return MHD_YES; } *unused = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MHD sends respose for request to URL `%s'\n", url); response = MHD_create_response_from_buffer (strlen (url), (void *) url, MHD_RESPMEM_MUST_COPY); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); if (ret == MHD_NO) abort (); return ret; } static void do_shutdown () { if (mhd_task_id != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (mhd_task_id); mhd_task_id = GNUNET_SCHEDULER_NO_TASK; } if (curl_task_id != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (curl_task_id); curl_task_id = GNUNET_SCHEDULER_NO_TASK; } if (NULL != mhd) { MHD_stop_daemon (mhd); mhd = NULL; } GNUNET_free_non_null (url); url = NULL; } /** * Function to run the HTTP client. */ static void curl_main (void); static void curl_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { curl_task_id = GNUNET_SCHEDULER_NO_TASK; curl_main (); } static void curl_main () { fd_set rs; fd_set ws; fd_set es; int max; struct GNUNET_NETWORK_FDSet nrs; struct GNUNET_NETWORK_FDSet nws; struct GNUNET_TIME_Relative delay; long timeout; int running; struct CURLMsg *msg; max = 0; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); curl_multi_perform (multi, &running); if (running == 0) { GNUNET_assert (NULL != (msg = curl_multi_info_read (multi, &running))); if (msg->msg == CURLMSG_DONE) { if (msg->data.result != CURLE_OK) { fprintf (stderr, "%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); global_ret = 1; } } curl_multi_remove_handle (multi, curl); curl_multi_cleanup (multi); curl_easy_cleanup (curl); curl = NULL; multi = NULL; if (cbc.pos != strlen ("/hello_world")) { GNUNET_break (0); global_ret = 2; } if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) { GNUNET_break (0); global_ret = 3; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download complete, shutting down!\n"); do_shutdown (); return; } GNUNET_assert (CURLM_OK == curl_multi_fdset (multi, &rs, &ws, &es, &max)); if ( (CURLM_OK != curl_multi_timeout (multi, &timeout)) || (-1 == timeout) ) delay = GNUNET_TIME_UNIT_SECONDS; else delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout); GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max + 1); curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, &nrs, &nws, &curl_task, NULL); } static void start_curl (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_asprintf (&url, "http://%s/hello_world", TEST_DOMAIN); curl = curl_easy_init (); curl_easy_setopt (curl, CURLOPT_URL, url); curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ©_buffer); curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 15L); curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1); multi = curl_multi_init (); GNUNET_assert (multi != NULL); GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Beginning HTTP download from `%s'\n", url); curl_main (); } static void disco_ns (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_NAMESTORE_disconnect (namestore); namestore = NULL; } /** * Callback invoked from the namestore service once record is * created. * * @param cls closure * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; * will match 'result_af' from the request * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') * that the VPN allocated for the redirection; * traffic to this IP will now be redirected to the * specified target peer; NULL on error */ static void commence_testing (void *cls, int32_t success, const char *emsg) { GNUNET_SCHEDULER_add_now (&disco_ns, NULL); if ((emsg != NULL) && (GNUNET_YES != success)) { fprintf (stderr, "NS failed to create record %s\n", emsg); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), &start_curl, NULL); } /** * Function to keep the HTTP server running. */ static void mhd_main (void); static void mhd_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { mhd_task_id = GNUNET_SCHEDULER_NO_TASK; MHD_run (mhd); mhd_main (); } static void mhd_main () { struct GNUNET_NETWORK_FDSet nrs; struct GNUNET_NETWORK_FDSet nws; fd_set rs; fd_set ws; fd_set es; int max_fd; unsigned MHD_LONG_LONG timeout; struct GNUNET_TIME_Relative delay; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == mhd_task_id); FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); max_fd = -1; GNUNET_assert (MHD_YES == MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd)); if (MHD_YES == MHD_get_timeout (mhd, &timeout)) delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout); else delay = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max_fd + 1); GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max_fd + 1); mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, &nrs, &nws, &mhd_task, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { enum MHD_FLAG flags; struct GNUNET_PeerIdentity id; struct GNUNET_CRYPTO_HashAsciiEncoded peername; struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key; struct GNUNET_GNSRECORD_Data rd; char *rd_string; char *zone_keyfile; GNUNET_TESTING_peer_get_identity (peer, &id); GNUNET_CRYPTO_hash_to_enc ((struct GNUNET_HashCode*)&id, &peername); namestore = GNUNET_NAMESTORE_connect (cfg); GNUNET_assert (NULL != namestore); flags = MHD_USE_DEBUG; //if (GNUNET_YES == use_v6) // flags |= MHD_USE_IPv6; mhd = MHD_start_daemon (flags, PORT, NULL, NULL, &mhd_ahc, NULL, MHD_OPTION_END); GNUNET_assert (NULL != mhd); mhd_main (); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", "ZONEKEY", &zone_keyfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n"); return; } zone_key = GNUNET_CRYPTO_ecdsa_key_create_from_file (zone_keyfile); rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; GNUNET_asprintf (&rd_string, "6 %s %s", (char*) &peername, "www.gnu."); GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_string_to_value (GNUNET_GNSRECORD_TYPE_VPN, rd_string, (void**)&rd.data, &rd.data_size)); rd.record_type = GNUNET_GNSRECORD_TYPE_VPN; GNUNET_NAMESTORE_records_store (namestore, zone_key, "www", 1, &rd, &commence_testing, NULL); GNUNET_free ((void**)rd.data); GNUNET_free (rd_string); GNUNET_free (zone_keyfile); GNUNET_free (zone_key); } /** * Open '/dev/null' and make the result the given * file descriptor. * * @param target_fd desired FD to point to /dev/null * @param flags open flags (O_RDONLY, O_WRONLY) */ static void open_dev_null (int target_fd, int flags) { int fd; fd = open ("/dev/null", flags); if (-1 == fd) abort (); if (fd == target_fd) return; if (-1 == dup2 (fd, target_fd)) { (void) close (fd); abort (); } (void) close (fd); } /** * Run the given command and wait for it to complete. * * @param file name of the binary to run * @param cmd command line arguments (as given to 'execv') * @return 0 on success, 1 on any error */ static int fork_and_exec (const char *file, char *const cmd[]) { int status; pid_t pid; pid_t ret; pid = fork (); if (-1 == pid) { fprintf (stderr, "fork failed: %s\n", strerror (errno)); return 1; } if (0 == pid) { /* we are the child process */ /* close stdin/stdout to not cause interference with the helper's main protocol! */ (void) close (0); open_dev_null (0, O_RDONLY); (void) close (1); open_dev_null (1, O_WRONLY); (void) execv (file, cmd); /* can only get here on error */ fprintf (stderr, "exec `%s' failed: %s\n", file, strerror (errno)); _exit (1); } /* keep running waitpid as long as the only error we get is 'EINTR' */ while ( (-1 == (ret = waitpid (pid, &status, 0))) && (errno == EINTR) ); if (-1 == ret) { fprintf (stderr, "waitpid failed: %s\n", strerror (errno)); return 1; } if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)))) return 1; /* child process completed and returned success, we're happy */ return 0; } int main (int argc, char *const *argv) { char *sbin_iptables; char *bin_vpn; char *bin_exit; char *bin_dns; char *const iptables_args[] = { "iptables", "-t", "mangle", "-L", "-v", NULL }; if (0 == access ("/sbin/iptables", X_OK)) sbin_iptables = "/sbin/iptables"; else if (0 == access ("/usr/sbin/iptables", X_OK)) sbin_iptables = "/usr/sbin/iptables"; else { fprintf (stderr, "Executable iptables not found in approved directories: %s, skipping\n", strerror (errno)); return 0; } if (0 != fork_and_exec (sbin_iptables, iptables_args)) { fprintf (stderr, "Failed to run `iptables -t mangle -L -v'. Skipping test.\n"); return 0; } if (0 != ACCESS ("/dev/net/tun", R_OK)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "access", "/dev/net/tun"); fprintf (stderr, "WARNING: System unable to run test, skipping.\n"); return 0; } bin_vpn = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn"); bin_exit = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit"); bin_dns = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns"); if ( (0 != geteuid ()) && ( (GNUNET_YES != GNUNET_OS_check_helper_binary (bin_vpn, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) || //ipv4 only please! (GNUNET_YES != GNUNET_OS_check_helper_binary (bin_exit, GNUNET_YES, "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")) || //no nat, ipv4 only (GNUNET_YES != GNUNET_OS_check_helper_binary (bin_dns, GNUNET_YES, NULL))) ) // TODO: once we have a windows-testcase, add test parameters here { fprintf (stderr, "WARNING: gnunet-helper-{exit,vpn,dns} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n"); fprintf (stderr, "Change $PATH ('.' in $PATH before $GNUNET_PREFIX/bin is problematic) or permissions (run 'make install' as root) to fix this!\n"); GNUNET_free (bin_vpn); GNUNET_free (bin_exit); GNUNET_free (bin_dns); return 0; } GNUNET_free (bin_vpn); GNUNET_free (bin_exit); GNUNET_free (bin_dns); dest_ip = "169.254.86.1"; dest_af = AF_INET; src_af = AF_INET; if (GNUNET_OK == GNUNET_NETWORK_test_pf (PF_INET6)) use_v6 = GNUNET_YES; else use_v6 = GNUNET_NO; if ( (GNUNET_OK != GNUNET_NETWORK_test_pf (src_af)) || (GNUNET_OK != GNUNET_NETWORK_test_pf (dest_af)) ) { fprintf (stderr, "Required address families not supported by this system, skipping test.\n"); return 0; } if (0 != curl_global_init (CURL_GLOBAL_WIN32)) { fprintf (stderr, "failed to initialize curl\n"); return 2; } if (0 != GNUNET_TESTING_peer_run ("test-gnunet-vpn", "test_gns_vpn.conf", &run, NULL)) return 1; GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn"); return global_ret; } /* end of test_gns_vpn.c */ gnunet-0.10.1/src/pt/gnunet-daemon-pt.c0000644000175000017500000010335012250315331014547 00000000000000/* This file is part of GNUnet. (C) 2010, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file pt/gnunet-daemon-pt.c * @brief tool to manipulate DNS and VPN services to perform protocol translation (IPvX over GNUnet) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dns_service.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_mesh_service.h" #include "gnunet_tun_lib.h" #include "gnunet_dht_service.h" #include "gnunet_vpn_service.h" #include "gnunet_statistics_service.h" #include "gnunet_applications.h" #include "block_dns.h" /** * After how long do we time out if we could not get an IP from VPN or MESH? */ #define TIMEOUT GNUNET_TIME_UNIT_MINUTES /** * How many bytes of payload do we allow at most for a DNS reply? * Given that this is pretty much limited to loopback, we can be * pretty high (Linux loopback defaults to 16k, most local UDP packets * should survive up to 9k (NFS), so 8k should be pretty safe in * general). */ #define MAX_DNS_SIZE (8 * 1024) /** * How many channels do we open at most at the same time? */ #define MAX_OPEN_TUNNELS 4 /** * Which group of DNS records are we currently processing? */ enum RequestGroup { /** * DNS answers */ ANSWERS = 0, /** * DNS authority records */ AUTHORITY_RECORDS = 1, /** * DNS additional records */ ADDITIONAL_RECORDS = 2, /** * We're done processing. */ END = 3 }; /** * Information tracked per DNS reply that we are processing. */ struct ReplyContext { /** * Handle to submit the final result. */ struct GNUNET_DNS_RequestHandle *rh; /** * DNS packet that is being modified. */ struct GNUNET_DNSPARSER_Packet *dns; /** * Active redirection request with the VPN. */ struct GNUNET_VPN_RedirectionRequest *rr; /** * Record for which we have an active redirection request. */ struct GNUNET_DNSPARSER_Record *rec; /** * Offset in the current record group that is being modified. */ unsigned int offset; /** * Group that is being modified */ enum RequestGroup group; }; /** * Handle to a peer that advertised that it is willing to serve * as a DNS exit. We try to keep a few channels open and a few * peers in reserve. */ struct MeshExit { /** * Kept in a DLL. */ struct MeshExit *next; /** * Kept in a DLL. */ struct MeshExit *prev; /** * Channel we use for DNS requests over MESH, NULL if we did * not initialze a channel to this peer yet. */ struct GNUNET_MESH_Channel *mesh_channel; /** * At what time did the peer's advertisement expire? */ struct GNUNET_TIME_Absolute expiration; /** * Head of DLL of requests waiting for a response. */ struct RequestContext *receive_queue_head; /** * Tail of DLL of requests waiting for a response. */ struct RequestContext *receive_queue_tail; /** * Head of DLL of requests to be transmitted to a mesh_channel. */ struct RequestContext *transmit_queue_head; /** * Tail of DLL of requests to be transmitted to a mesh_channel. */ struct RequestContext *transmit_queue_tail; /** * Active transmission request for this channel (or NULL). */ struct GNUNET_MESH_TransmitHandle *mesh_th; /** * Identity of the peer that is providing the exit for us. */ struct GNUNET_PeerIdentity peer; /** * How many DNS requests did we transmit via this channel? */ unsigned int num_transmitted; /** * How many DNS requests were answered via this channel? */ unsigned int num_answered; }; /** * State we keep for a request that is going out via MESH. */ struct RequestContext { /** * We keep these in a DLL. */ struct RequestContext *next; /** * We keep these in a DLL. */ struct RequestContext *prev; /** * Exit that was chosen for this request. */ struct MeshExit *exit; /** * Handle for interaction with DNS service. */ struct GNUNET_DNS_RequestHandle *rh; /** * Message we're sending out via MESH, allocated at the * end of this struct. */ const struct GNUNET_MessageHeader *mesh_message; /** * Task used to abort this operation with timeout. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * Length of the request message that follows this struct. */ uint16_t mlen; /** * ID of the original DNS request (used to match the reply). */ uint16_t dns_id; /** * #GNUNET_NO if this request is still in the transmit_queue, * #GNUNET_YES if we are in the receive_queue. */ int16_t was_transmitted; }; /** * Head of DLL of mesh exits. Mesh exits with an open channel are * always at the beginning (so we do not have to traverse the entire * list to find them). */ static struct MeshExit *exit_head; /** * Tail of DLL of mesh exits. */ static struct MeshExit *exit_tail; /** * The handle to the configuration used throughout the process */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * The handle to the VPN */ static struct GNUNET_VPN_Handle *vpn_handle; /** * The handle to the MESH service */ static struct GNUNET_MESH_Handle *mesh_handle; /** * Statistics. */ static struct GNUNET_STATISTICS_Handle *stats; /** * The handle to DNS post-resolution modifications. */ static struct GNUNET_DNS_Handle *dns_post_handle; /** * The handle to DNS pre-resolution modifications. */ static struct GNUNET_DNS_Handle *dns_pre_handle; /** * Handle to access the DHT. */ static struct GNUNET_DHT_Handle *dht; /** * Our DHT GET operation to find DNS exits. */ static struct GNUNET_DHT_GetHandle *dht_get; /** * Are we doing IPv4-pt? */ static int ipv4_pt; /** * Are we doing IPv6-pt? */ static int ipv6_pt; /** * Are we channeling DNS queries? */ static int dns_channel; /** * Number of DNS exit peers we currently have in the mesh channel. * Used to see if using the mesh channel makes any sense right now, * as well as to decide if we should open new channels. */ static unsigned int dns_exit_available; /** * We are short on mesh exits, try to open another one. */ static void try_open_exit () { struct MeshExit *pos; uint32_t candidate_count; uint32_t candidate_selected; candidate_count = 0; for (pos = exit_head; NULL != pos; pos = pos->next) if (NULL == pos->mesh_channel) candidate_count++; candidate_selected = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, candidate_count); candidate_count = 0; for (pos = exit_head; NULL != pos; pos = pos->next) if (NULL == pos->mesh_channel) { candidate_count++; if (candidate_selected < candidate_count) { /* move to the head of the DLL */ pos->mesh_channel = GNUNET_MESH_channel_create (mesh_handle, pos, &pos->peer, GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER, GNUNET_MESH_OPTION_DEFAULT); if (NULL == pos->mesh_channel) { GNUNET_break (0); continue; } GNUNET_CONTAINER_DLL_remove (exit_head, exit_tail, pos); GNUNET_CONTAINER_DLL_insert (exit_head, exit_tail, pos); dns_exit_available++; return; } } GNUNET_assert (NULL == exit_head); } /** * Compute the weight of the given exit. The higher the weight, * the more likely it will be that the channel will be chosen. * A weigt of zero means that we should close the channel as it * is so bad, that we should not use it. * * @param exit exit to calculate the weight for * @return weight of the channel */ static uint32_t get_channel_weight (struct MeshExit *exit) { uint32_t dropped; uint32_t drop_percent; uint32_t good_percent; GNUNET_assert (exit->num_transmitted >= exit->num_answered); dropped = exit->num_transmitted - exit->num_answered; if (exit->num_transmitted > 0) drop_percent = (uint32_t) ((100LL * dropped) / exit->num_transmitted); else drop_percent = 50; /* no data */ if ( (exit->num_transmitted > 20) && (drop_percent > 25) ) return 0; /* statistically significant, and > 25% loss, die */ good_percent = 100 - drop_percent; GNUNET_assert (0 != good_percent); if ( UINT32_MAX / good_percent / good_percent < exit->num_transmitted) return UINT32_MAX; /* formula below would overflow */ return 1 + good_percent * good_percent * exit->num_transmitted; } /** * Choose a mesh exit for a DNS request. We try to use a channel * that is reliable and currently available. All existing * channels are given a base weight of 1, plus a score relating * to the total number of queries answered in relation to the * total number of queries we sent to that channel. That * score is doubled if the channel is currently idle. * * @return NULL if no exit is known, otherwise the * exit that we should use to queue a message with */ static struct MeshExit * choose_exit () { struct MeshExit *pos; uint64_t total_transmitted; uint64_t selected_offset; uint32_t channel_weight; total_transmitted = 0; for (pos = exit_head; NULL != pos; pos = pos->next) { if (NULL == pos->mesh_channel) break; channel_weight = get_channel_weight (pos); total_transmitted += channel_weight; /* double weight for idle channels */ if (NULL == pos->mesh_th) total_transmitted += channel_weight; } if (0 == total_transmitted) { /* no channels available, or only a very bad one... */ return exit_head; } selected_offset = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, total_transmitted); total_transmitted = 0; for (pos = exit_head; NULL != pos; pos = pos->next) { if (NULL == pos->mesh_channel) break; channel_weight = get_channel_weight (pos); total_transmitted += channel_weight; /* double weight for idle channels */ if (NULL == pos->mesh_th) total_transmitted += channel_weight; if (total_transmitted > selected_offset) return pos; } GNUNET_break (0); return NULL; } /** * We're done modifying all records in the response. Submit the reply * and free the resources of the rc. * * @param rc context to process */ static void finish_request (struct ReplyContext *rc) { char *buf; size_t buf_len; if (GNUNET_SYSERR == GNUNET_DNSPARSER_pack (rc->dns, MAX_DNS_SIZE, &buf, &buf_len)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to pack DNS request. Dropping.\n")); GNUNET_DNS_request_drop (rc->rh); } else { GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests mapped to VPN"), 1, GNUNET_NO); GNUNET_DNS_request_answer (rc->rh, buf_len, buf); GNUNET_free (buf); } GNUNET_DNSPARSER_free_packet (rc->dns); GNUNET_free (rc); } /** * Process the next record of the given request context. * When done, submit the reply and free the resources of * the rc. * * @param rc context to process */ static void submit_request (struct ReplyContext *rc); /** * Callback invoked from the VPN service once a redirection is * available. Provides the IP address that can now be used to * reach the requested destination. We substitute the active * record and then continue with 'submit_request' to look at * the other records. * * @param cls our `struct ReplyContext` * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; * will match 'result_af' from the request * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') * that the VPN allocated for the redirection; * traffic to this IP will now be redirected to the * specified target peer; NULL on error */ static void vpn_allocation_callback (void *cls, int af, const void *address) { struct ReplyContext *rc = cls; rc->rr = NULL; if (af == AF_UNSPEC) { GNUNET_DNS_request_drop (rc->rh); GNUNET_DNSPARSER_free_packet (rc->dns); GNUNET_free (rc); return; } GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS records modified"), 1, GNUNET_NO); switch (rc->rec->type) { case GNUNET_DNSPARSER_TYPE_A: GNUNET_assert (AF_INET == af); memcpy (rc->rec->data.raw.data, address, sizeof (struct in_addr)); break; case GNUNET_DNSPARSER_TYPE_AAAA: GNUNET_assert (AF_INET6 == af); memcpy (rc->rec->data.raw.data, address, sizeof (struct in6_addr)); break; default: GNUNET_assert (0); return; } rc->rec = NULL; submit_request (rc); } /** * Modify the given DNS record by asking VPN to create a channel * to the given address. When done, continue with submitting * other records from the request context ('submit_request' is * our continuation). * * @param rc context to process * @param rec record to modify */ static void modify_address (struct ReplyContext *rc, struct GNUNET_DNSPARSER_Record *rec) { int af; switch (rec->type) { case GNUNET_DNSPARSER_TYPE_A: af = AF_INET; GNUNET_assert (rec->data.raw.data_len == sizeof (struct in_addr)); break; case GNUNET_DNSPARSER_TYPE_AAAA: af = AF_INET6; GNUNET_assert (rec->data.raw.data_len == sizeof (struct in6_addr)); break; default: GNUNET_assert (0); return; } rc->rec = rec; rc->rr = GNUNET_VPN_redirect_to_ip (vpn_handle, af, af, rec->data.raw.data, GNUNET_TIME_relative_to_absolute (TIMEOUT), &vpn_allocation_callback, rc); } /** * Process the next record of the given request context. * When done, submit the reply and free the resources of * the rc. * * @param rc context to process */ static void submit_request (struct ReplyContext *rc) { struct GNUNET_DNSPARSER_Record *ra; unsigned int ra_len; unsigned int i; while (1) { switch (rc->group) { case ANSWERS: ra = rc->dns->answers; ra_len = rc->dns->num_answers; break; case AUTHORITY_RECORDS: ra = rc->dns->authority_records; ra_len = rc->dns->num_authority_records; break; case ADDITIONAL_RECORDS: ra = rc->dns->additional_records; ra_len = rc->dns->num_additional_records; break; case END: finish_request (rc); return; default: GNUNET_assert (0); } for (i=rc->offset;ioffset = i + 1; modify_address (rc, &ra[i]); return; } break; case GNUNET_DNSPARSER_TYPE_AAAA: if (ipv6_pt) { rc->offset = i + 1; modify_address (rc, &ra[i]); return; } break; } } rc->group++; } } /** * Test if any of the given records need protocol-translation work. * * @param ra array of records * @param ra_len number of entries in @a ra * @return #GNUNET_YES if any of the given records require protocol-translation */ static int work_test (const struct GNUNET_DNSPARSER_Record *ra, unsigned int ra_len) { unsigned int i; for (i=0;ianswers, dns->num_answers); work |= work_test (dns->authority_records, dns->num_authority_records); work |= work_test (dns->additional_records, dns->num_additional_records); if (! work) { GNUNET_DNS_request_forward (rh); GNUNET_DNSPARSER_free_packet (dns); return; } rc = GNUNET_new (struct ReplyContext); rc->rh = rh; rc->dns = dns; rc->offset = 0; rc->group = ANSWERS; submit_request (rc); } /** * Transmit a DNS request via MESH and move the request * handle to the receive queue. * * @param cls the `struct MeshExit` * @param size number of bytes available in buf * @param buf where to copy the message * @return number of bytes written to buf */ static size_t transmit_dns_request_to_mesh (void *cls, size_t size, void *buf) { struct MeshExit *exit = cls; struct RequestContext *rc; size_t mlen; exit->mesh_th = NULL; if (NULL == (rc = exit->transmit_queue_head)) return 0; mlen = rc->mlen; if (mlen > size) { exit->mesh_th = GNUNET_MESH_notify_transmit_ready (exit->mesh_channel, GNUNET_NO, TIMEOUT, mlen, &transmit_dns_request_to_mesh, exit); return 0; } GNUNET_assert (GNUNET_NO == rc->was_transmitted); memcpy (buf, rc->mesh_message, mlen); GNUNET_CONTAINER_DLL_remove (exit->transmit_queue_head, exit->transmit_queue_tail, rc); rc->was_transmitted = GNUNET_YES; GNUNET_CONTAINER_DLL_insert (exit->receive_queue_head, exit->receive_queue_tail, rc); rc = exit->transmit_queue_head; if (NULL != rc) exit->mesh_th = GNUNET_MESH_notify_transmit_ready (exit->mesh_channel, GNUNET_NO, TIMEOUT, rc->mlen, &transmit_dns_request_to_mesh, exit); return mlen; } /** * Task run if the time to answer a DNS request via MESH is over. * * @param cls the `struct RequestContext` to abort * @param tc scheduler context */ static void timeout_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct RequestContext *rc = cls; struct MeshExit *exit = rc->exit; if (rc->was_transmitted) { exit->num_transmitted++; GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head, exit->receive_queue_tail, rc); } else { GNUNET_CONTAINER_DLL_remove (exit->transmit_queue_head, exit->transmit_queue_tail, rc); } GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests dropped (timeout)"), 1, GNUNET_NO); GNUNET_DNS_request_drop (rc->rh); GNUNET_free (rc); if ( (0 == get_channel_weight (exit)) && (NULL == exit->receive_queue_head) && (NULL == exit->transmit_queue_head) ) { /* this straw broke the camel's back: this channel now has such a low score that it will not be used; close it! */ GNUNET_assert (NULL == exit->mesh_th); GNUNET_MESH_channel_destroy (exit->mesh_channel); exit->mesh_channel = NULL; GNUNET_CONTAINER_DLL_remove (exit_head, exit_tail, exit); GNUNET_CONTAINER_DLL_insert_tail (exit_head, exit_tail, exit); /* go back to semi-innocent: mark as not great, but avoid a prohibitively negative score (see #get_channel_weight, which checks for a certain minimum number of transmissions before making up an opinion) */ exit->num_transmitted = 5; exit->num_answered = 0; dns_exit_available--; /* now try to open an alternative exit */ try_open_exit (); } } /** * This function is called *before* the DNS request has been * given to a "local" DNS resolver. Channeling for DNS requests * was enabled, so we now need to send the request via some MESH * channel to a DNS EXIT for resolution. * * @param cls closure * @param rh request handle to user for reply * @param request_length number of bytes in request * @param request udp payload of the DNS request */ static void dns_pre_request_handler (void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request) { struct RequestContext *rc; size_t mlen; struct GNUNET_MessageHeader hdr; struct GNUNET_TUN_DnsHeader dns; struct MeshExit *exit; GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests intercepted"), 1, GNUNET_NO); if (0 == dns_exit_available) { GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests dropped (DNS mesh channel down)"), 1, GNUNET_NO); GNUNET_DNS_request_drop (rh); return; } if (request_length < sizeof (dns)) { GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests dropped (malformed)"), 1, GNUNET_NO); GNUNET_DNS_request_drop (rh); return; } memcpy (&dns, request, sizeof (dns)); mlen = sizeof (struct GNUNET_MessageHeader) + request_length; exit = choose_exit (); GNUNET_assert (NULL != exit); GNUNET_assert (NULL != exit->mesh_channel); rc = GNUNET_malloc (sizeof (struct RequestContext) + mlen); rc->exit = exit; rc->rh = rh; rc->mesh_message = (const struct GNUNET_MessageHeader*) &rc[1]; rc->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_request, rc); rc->dns_id = dns.id; rc->mlen = mlen; hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_TO_INTERNET); hdr.size = htons (mlen); memcpy (&rc[1], &hdr, sizeof (struct GNUNET_MessageHeader)); memcpy (&(((char*)&rc[1])[sizeof (struct GNUNET_MessageHeader)]), request, request_length); GNUNET_CONTAINER_DLL_insert_tail (exit->transmit_queue_head, exit->transmit_queue_tail, rc); if (NULL == exit->mesh_th) exit->mesh_th = GNUNET_MESH_notify_transmit_ready (exit->mesh_channel, GNUNET_NO, TIMEOUT, mlen, &transmit_dns_request_to_mesh, exit); } /** * Process a request via mesh to perform a DNS query. * * @param cls NULL * @param channel connection to the other end * @param channel_ctx pointer to our `struct MeshExit` * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int receive_dns_response (void *cls, struct GNUNET_MESH_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct MeshExit *exit = *channel_ctx; struct GNUNET_TUN_DnsHeader dns; size_t mlen; struct RequestContext *rc; mlen = ntohs (message->size); mlen -= sizeof (struct GNUNET_MessageHeader); if (mlen < sizeof (struct GNUNET_TUN_DnsHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } memcpy (&dns, &message[1], sizeof (dns)); for (rc = exit->receive_queue_head; NULL != rc; rc = rc->next) { GNUNET_assert (GNUNET_YES == rc->was_transmitted); if (dns.id == rc->dns_id) { GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS replies received"), 1, GNUNET_NO); GNUNET_DNS_request_answer (rc->rh, mlen, (const void*) &message[1]); GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head, exit->receive_queue_tail, rc); GNUNET_SCHEDULER_cancel (rc->timeout_task); GNUNET_free (rc); exit->num_answered++; exit->num_transmitted++; return GNUNET_OK; } } GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS replies dropped (too late?)"), 1, GNUNET_NO); return GNUNET_OK; } /** * Abort all pending DNS requests with the given mesh exit. * * @param exit mesh exit to abort requests for */ static void abort_all_requests (struct MeshExit *exit) { struct RequestContext *rc; while (NULL != (rc = exit->receive_queue_head)) { GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head, exit->receive_queue_tail, rc); GNUNET_DNS_request_drop (rc->rh); GNUNET_SCHEDULER_cancel (rc->timeout_task); GNUNET_free (rc); } while (NULL != (rc = exit->transmit_queue_head)) { GNUNET_CONTAINER_DLL_remove (exit->transmit_queue_head, exit->transmit_queue_tail, rc); GNUNET_DNS_request_drop (rc->rh); GNUNET_SCHEDULER_cancel (rc->timeout_task); GNUNET_free (rc); } } /** * Function scheduled as very last function, cleans up after us * * @param cls closure, NULL * @param tskctx scheduler context, unused */ static void cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tskctx) { struct MeshExit *exit; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Protocol translation daemon is shutting down now\n"); if (NULL != vpn_handle) { GNUNET_VPN_disconnect (vpn_handle); vpn_handle = NULL; } while (NULL != (exit = exit_head)) { GNUNET_CONTAINER_DLL_remove (exit_head, exit_tail, exit); if (NULL != exit->mesh_th) { GNUNET_MESH_notify_transmit_ready_cancel (exit->mesh_th); exit->mesh_th = NULL; } if (NULL != exit->mesh_channel) { GNUNET_MESH_channel_destroy (exit->mesh_channel); exit->mesh_channel = NULL; } abort_all_requests (exit); GNUNET_free (exit); } if (NULL != mesh_handle) { GNUNET_MESH_disconnect (mesh_handle); mesh_handle = NULL; } if (NULL != dns_post_handle) { GNUNET_DNS_disconnect (dns_post_handle); dns_post_handle = NULL; } if (NULL != dns_pre_handle) { GNUNET_DNS_disconnect (dns_pre_handle); dns_pre_handle = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_YES); stats = NULL; } if (NULL != dht_get) { GNUNET_DHT_get_stop (dht_get); dht_get = NULL; } if (NULL != dht) { GNUNET_DHT_disconnect (dht); dht = NULL; } } /** * Function called whenever a channel is destroyed. Should clean up * the associated state and attempt to build a new one. * * It must NOT call #GNUNET_MESH_channel_destroy on the channel. * * @param cls closure (the `struct MeshExit` set from #GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void mesh_channel_end_cb (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { struct MeshExit *exit = channel_ctx; struct MeshExit *alt; struct RequestContext *rc; if (NULL != exit->mesh_th) { GNUNET_MESH_notify_transmit_ready_cancel (exit->mesh_th); exit->mesh_th = NULL; } exit->mesh_channel = NULL; dns_exit_available--; /* open alternative channels */ try_open_exit (); if (NULL == exit->mesh_channel) { /* our channel is now closed, move our requests to an alternative channel */ alt = choose_exit (); while (NULL != (rc = exit->transmit_queue_head)) { GNUNET_CONTAINER_DLL_remove (exit->transmit_queue_head, exit->transmit_queue_tail, rc); rc->exit = alt; GNUNET_CONTAINER_DLL_insert (alt->transmit_queue_head, alt->transmit_queue_tail, rc); } while (NULL != (rc = exit->receive_queue_head)) { GNUNET_CONTAINER_DLL_remove (exit->receive_queue_head, exit->receive_queue_tail, rc); rc->was_transmitted = GNUNET_NO; rc->exit = alt; GNUNET_CONTAINER_DLL_insert (alt->transmit_queue_head, alt->transmit_queue_tail, rc); } } else { /* the same peer was chosen, just make sure the queue processing is restarted */ alt = exit; } if ( (NULL == alt->mesh_th) && (NULL != (rc = alt->transmit_queue_head)) ) alt->mesh_th = GNUNET_MESH_notify_transmit_ready (alt->mesh_channel, GNUNET_NO, TIMEOUT, rc->mlen, &transmit_dns_request_to_mesh, alt); } /** * Function called whenever we find an advertisement for a * DNS exit in the DHT. If we don't have a mesh channel, * we should build one; otherwise, we should save the * advertisement for later use. * * @param cls closure * @param exp when will this value expire * @param key key of the result * @param get_path peers on reply path (or NULL if not recorded) * [0] = datastore's first neighbor, [length - 1] = local peer * @param get_path_length number of entries in @a get_path * @param put_path peers on the PUT path (or NULL if not recorded) * [0] = origin, [length - 1] = datastore * @param put_path_length number of entries in @a put_path * @param type type of the result * @param size number of bytes in @a data * @param data pointer to the result data */ static void handle_dht_result (void *cls, struct GNUNET_TIME_Absolute exp, const struct GNUNET_HashCode *key, const struct GNUNET_PeerIdentity *get_path, unsigned int get_path_length, const struct GNUNET_PeerIdentity *put_path, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { const struct GNUNET_DNS_Advertisement *ad; struct MeshExit *exit; if (sizeof (struct GNUNET_DNS_Advertisement) != size) { GNUNET_break (0); return; } ad = data; for (exit = exit_head; NULL != exit; exit = exit->next) if (0 == memcmp (&ad->peer, &exit->peer, sizeof (struct GNUNET_PeerIdentity))) break; if (NULL == exit) { exit = GNUNET_new (struct MeshExit); exit->peer = ad->peer; /* channel is closed, so insert at the end */ GNUNET_CONTAINER_DLL_insert_tail (exit_head, exit_tail, exit); } exit->expiration = GNUNET_TIME_absolute_max (exit->expiration, GNUNET_TIME_absolute_ntoh (ad->expiration_time)); if (dns_exit_available < MAX_OPEN_TUNNELS) try_open_exit (); } /** * @brief Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg_ configuration */ static void run (void *cls, char *const *args GNUNET_UNUSED, const char *cfgfile GNUNET_UNUSED, const struct GNUNET_CONFIGURATION_Handle *cfg_) { struct GNUNET_HashCode dns_key; cfg = cfg_; stats = GNUNET_STATISTICS_create ("pt", cfg); ipv4_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg, "pt", "TUNNEL_IPV4"); ipv6_pt = GNUNET_CONFIGURATION_get_value_yesno (cfg, "pt", "TUNNEL_IPV6"); dns_channel = GNUNET_CONFIGURATION_get_value_yesno (cfg, "pt", "TUNNEL_DNS"); if (! (ipv4_pt || ipv6_pt || dns_channel)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No useful service enabled. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup, cls); if (ipv4_pt || ipv6_pt) { dns_post_handle = GNUNET_DNS_connect (cfg, GNUNET_DNS_FLAG_POST_RESOLUTION, &dns_post_request_handler, NULL); if (NULL == dns_post_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to %s service. Exiting.\n"), "DNS"); GNUNET_SCHEDULER_shutdown (); return; } vpn_handle = GNUNET_VPN_connect (cfg); if (NULL == vpn_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to %s service. Exiting.\n"), "VPN"); GNUNET_SCHEDULER_shutdown (); return; } } if (dns_channel) { static struct GNUNET_MESH_MessageHandler mesh_handlers[] = { {&receive_dns_response, GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET, 0}, {NULL, 0, 0} }; dns_pre_handle = GNUNET_DNS_connect (cfg, GNUNET_DNS_FLAG_PRE_RESOLUTION, &dns_pre_request_handler, NULL); if (NULL == dns_pre_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to %s service. Exiting.\n"), "DNS"); GNUNET_SCHEDULER_shutdown (); return; } mesh_handle = GNUNET_MESH_connect (cfg, NULL, NULL, &mesh_channel_end_cb, mesh_handlers, NULL); if (NULL == mesh_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to %s service. Exiting.\n"), "MESH"); GNUNET_SCHEDULER_shutdown (); return; } dht = GNUNET_DHT_connect (cfg, 1); if (NULL == dht) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to %s service. Exiting.\n"), "DHT"); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_CRYPTO_hash ("dns", strlen ("dns"), &dns_key); dht_get = GNUNET_DHT_get_start (dht, GNUNET_BLOCK_TYPE_DNS, &dns_key, 1, GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, 0, &handle_dht_result, NULL); } } /** * The main function * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; int ret; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-daemon-pt", gettext_noop ("Daemon to run to perform IP protocol translation to GNUnet"), options, &run, NULL)) ? 0 : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-daemon-pt.c */ gnunet-0.10.1/src/pt/Makefile.am0000644000175000017500000000570612320751517013273 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ plugindir = $(libdir)/gnunet dist_pkgcfg_DATA = \ pt.conf libexec_PROGRAMS = \ gnunet-daemon-pt gnunet_daemon_pt_SOURCES = \ gnunet-daemon-pt.c gnunet_daemon_pt_LDADD = \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) if HAVE_TESTING if HAVE_MHD if HAVE_LIBGNURL if LINUX VPN_TEST = \ test_gnunet_vpn-4_to_6 \ test_gnunet_vpn-6_to_4 \ test_gnunet_vpn-6_over \ test_gnunet_vpn-4_over \ test_gns_vpn endif if MINGW VPN_TEST = \ test_gnunet_vpn-4_to_6 \ test_gnunet_vpn-6_to_4 \ test_gnunet_vpn-6_over \ test_gnunet_vpn-4_over endif endif endif endif check_PROGRAMS = $(VPN_TEST) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif EXTRA_DIST = \ test_gnunet_vpn.conf \ test_gns_vpn.conf test_gns_vpn_SOURCES = \ test_gns_vpn.c test_gns_vpn_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/namestore/libgnunetnamestore.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gns_vpn_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) test_gnunet_vpn_4_over_SOURCES = \ test_gnunet_vpn.c test_gnunet_vpn_4_over_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_vpn_4_over_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) test_gnunet_vpn_6_over_SOURCES = \ test_gnunet_vpn.c test_gnunet_vpn_6_over_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_vpn_6_over_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) test_gnunet_vpn_4_to_6_SOURCES = \ test_gnunet_vpn.c test_gnunet_vpn_4_to_6_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_vpn_4_to_6_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) test_gnunet_vpn_6_to_4_SOURCES = \ test_gnunet_vpn.c test_gnunet_vpn_6_to_4_LDADD = -lmicrohttpd @LIBGNURL@ \ $(top_builddir)/src/vpn/libgnunetvpn.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnunet_vpn_6_to_4_CPPFLAGS = \ @LIBGNURL_CPPFLAGS@ $(AM_CPPFLAGS) gnunet-0.10.1/src/pt/test_gns_vpn.conf0000644000175000017500000000171012225230043014574 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-gns-vpn/ [transport] PLUGINS = tcp [arm] DEFAULTSERVICES = statistics exit mesh vpn namestore gns PORT = 0 ALLOW_SHUTDOWN = YES [exit] EXIT_IPV4 = YES EXIT_IPV6 = YES # FIXME: can we use 'lo'? EXIT_IFNAME = eth1 [dns] DNS_EXIT = 8.8.8.8 [testing] WEAKRANDOM = YES HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat [nse] WORKBITS = 1 # repeating some values from the default configurations # here as the respective network addresses are also # hard-wired in the tests and the MUST match (!) [vpn] IPV6ADDR = FC2D:FDAA:6A26::1 IPV6PREFIX = 64 IPV4ADDR = 169.254.20.1 IPV4MASK = 255.255.255.0 [exit] IPV6ADDR = FC5A:04E1:C2BA::1 IPV6PREFIX = 96 IPV4ADDR = 169.254.86.1 IPV4MASK = 255.255.255.0 [www.gads.] TCP_REDIRECTS = 80:localhost4:8080 TTL = 3600000 [gns] AUTOSTART = YES ZONEKEY = $GNUNET_TEST_HOME/.hostkey HIJACK_DNS = YES [namestore] AUTOSTART = YES [nat] USE_LOCALADDR = YES RETURN_LOCAL_ADDRESSES = YES gnunet-0.10.1/src/pt/test_gnunet_vpn.c0000644000175000017500000003113112226031536014611 00000000000000/* This file is part of GNUnet (C) 2007, 2009, 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file test_gnunet_vpn.c * @brief testcase for tunneling HTTP over the GNUnet VPN * @author Christian Grothoff */ #include "platform.h" #include #include #include "gnunet_vpn_service.h" #include "gnunet_testing_lib.h" #define PORT 48080 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) /** * Return value for 'main'. */ static int global_ret; static struct GNUNET_VPN_Handle *vpn; static struct MHD_Daemon *mhd; static GNUNET_SCHEDULER_TaskIdentifier mhd_task_id; static GNUNET_SCHEDULER_TaskIdentifier curl_task_id; static GNUNET_SCHEDULER_TaskIdentifier ctrl_c_task_id; static struct GNUNET_VPN_RedirectionRequest *rr; static CURL *curl; static CURLM *multi; static char *url; /** * IP address of the ultimate destination. */ static const char *dest_ip; /** * Address family of the dest_ip. */ static int dest_af; /** * Address family to use by the curl client. */ static int src_af; struct CBC { char buf[1024]; size_t pos; }; static struct CBC cbc; static size_t copy_buffer (void *ptr, size_t size, size_t nmemb, void *ctx) { struct CBC *cbc = ctx; if (cbc->pos + size * nmemb > sizeof (cbc->buf)) return 0; /* overflow */ memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); cbc->pos += size * nmemb; return size * nmemb; } static int mhd_ahc (void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t * upload_data_size, void **unused) { static int ptr; struct MHD_Response *response; int ret; if (0 != strcmp ("GET", method)) return MHD_NO; /* unexpected method */ if (&ptr != *unused) { *unused = &ptr; return MHD_YES; } *unused = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MHD sends respose for request to URL `%s'\n", url); response = MHD_create_response_from_buffer (strlen (url), (void *) url, MHD_RESPMEM_MUST_COPY); ret = MHD_queue_response (connection, MHD_HTTP_OK, response); MHD_destroy_response (response); if (ret == MHD_NO) abort (); return ret; } static void do_shutdown () { if (mhd_task_id != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (mhd_task_id); mhd_task_id = GNUNET_SCHEDULER_NO_TASK; } if (curl_task_id != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (curl_task_id); curl_task_id = GNUNET_SCHEDULER_NO_TASK; } if (ctrl_c_task_id != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ctrl_c_task_id); ctrl_c_task_id = GNUNET_SCHEDULER_NO_TASK; } if (NULL != mhd) { MHD_stop_daemon (mhd); mhd = NULL; } if (NULL != rr) { GNUNET_VPN_cancel_request (rr); rr = NULL; } if (NULL != vpn) { GNUNET_VPN_disconnect (vpn); vpn = NULL; } GNUNET_free_non_null (url); url = NULL; } /** * Function to run the HTTP client. */ static void curl_main (void); static void curl_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { curl_task_id = GNUNET_SCHEDULER_NO_TASK; curl_main (); } static void curl_main () { fd_set rs; fd_set ws; fd_set es; int max; struct GNUNET_NETWORK_FDSet nrs; struct GNUNET_NETWORK_FDSet nws; struct GNUNET_TIME_Relative delay; long timeout; int running; struct CURLMsg *msg; max = 0; FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); curl_multi_perform (multi, &running); if (running == 0) { GNUNET_assert (NULL != (msg = curl_multi_info_read (multi, &running))); if (msg->msg == CURLMSG_DONE) { if (msg->data.result != CURLE_OK) { fprintf (stderr, "%s failed at %s:%d: `%s'\n", "curl_multi_perform", __FILE__, __LINE__, curl_easy_strerror (msg->data.result)); global_ret = 1; } } curl_multi_remove_handle (multi, curl); curl_multi_cleanup (multi); curl_easy_cleanup (curl); curl = NULL; multi = NULL; if (cbc.pos != strlen ("/hello_world")) { GNUNET_break (0); global_ret = 2; } if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world"))) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "You might want to check if your host-based firewall is blocking the connections.\n"); global_ret = 3; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Download complete, shutting down!\n"); do_shutdown (); return; } GNUNET_assert (CURLM_OK == curl_multi_fdset (multi, &rs, &ws, &es, &max)); if ((CURLM_OK != curl_multi_timeout (multi, &timeout)) || (-1 == timeout)) delay = GNUNET_TIME_UNIT_SECONDS; else delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout); GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max + 1); GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max + 1); curl_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, &nrs, &nws, &curl_task, NULL); } /** * Callback invoked from the VPN service once a redirection is * available. Provides the IP address that can now be used to * reach the requested destination (in our case, the MHD server) * * @param cls closure * @param af address family, AF_INET or AF_INET6; AF_UNSPEC on error; * will match 'result_af' from the request * @param address IP address (struct in_addr or struct in_addr6, depending on 'af') * that the VPN allocated for the redirection; * traffic to this IP will now be redirected to the * specified target peer; NULL on error */ static void allocation_cb (void *cls, int af, const void *address) { char ips[INET6_ADDRSTRLEN]; rr = NULL; if (src_af != af) { fprintf (stderr, "VPN failed to allocate appropriate address\n"); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_asprintf (&url, "http://%s:%u/hello_world", inet_ntop (af, address, ips, sizeof (ips)), (unsigned int) PORT); curl = curl_easy_init (); curl_easy_setopt (curl, CURLOPT_URL, url); curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ©_buffer); curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbc); curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt (curl, CURLOPT_TIMEOUT, 150L); curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, 15L); curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1); multi = curl_multi_init (); GNUNET_assert (multi != NULL); GNUNET_assert (CURLM_OK == curl_multi_add_handle (multi, curl)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Beginning HTTP download from `%s'\n", url); curl_main (); } /** * Function to keep the HTTP server running. */ static void mhd_main (void); static void mhd_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { mhd_task_id = GNUNET_SCHEDULER_NO_TASK; MHD_run (mhd); mhd_main (); } static void ctrl_c_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { ctrl_c_task_id = GNUNET_SCHEDULER_NO_TASK; do_shutdown (); GNUNET_break (0); global_ret = 1; } static void mhd_main () { struct GNUNET_NETWORK_FDSet nrs; struct GNUNET_NETWORK_FDSet nws; fd_set rs; fd_set ws; fd_set es; int max_fd; unsigned MHD_LONG_LONG timeout; struct GNUNET_TIME_Relative delay; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == mhd_task_id); FD_ZERO (&rs); FD_ZERO (&ws); FD_ZERO (&es); max_fd = -1; GNUNET_assert (MHD_YES == MHD_get_fdset (mhd, &rs, &ws, &es, &max_fd)); if (MHD_YES == MHD_get_timeout (mhd, &timeout)) delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, (unsigned int) timeout); else delay = GNUNET_TIME_UNIT_FOREVER_REL; GNUNET_NETWORK_fdset_copy_native (&nrs, &rs, max_fd + 1); GNUNET_NETWORK_fdset_copy_native (&nws, &ws, max_fd + 1); mhd_task_id = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, delay, &nrs, &nws, &mhd_task, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { struct in_addr v4; struct in6_addr v6; void *addr; enum MHD_FLAG flags; vpn = GNUNET_VPN_connect (cfg); GNUNET_assert (NULL != vpn); flags = MHD_USE_DEBUG; if (AF_INET6 == dest_af) flags |= MHD_USE_IPv6; mhd = MHD_start_daemon (flags, PORT, NULL, NULL, &mhd_ahc, NULL, MHD_OPTION_END); GNUNET_assert (NULL != mhd); mhd_main (); addr = NULL; switch (dest_af) { case AF_INET: GNUNET_assert (1 == inet_pton (dest_af, dest_ip, &v4)); addr = &v4; break; case AF_INET6: GNUNET_assert (1 == inet_pton (dest_af, dest_ip, &v6)); addr = &v6; break; default: GNUNET_assert (0); } rr = GNUNET_VPN_redirect_to_ip (vpn, src_af, dest_af, addr, GNUNET_TIME_UNIT_FOREVER_ABS, &allocation_cb, NULL); ctrl_c_task_id = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &ctrl_c_shutdown, NULL); } int main (int argc, char *const *argv) { const char *type; const char *bin; char *vpn_binary; char *exit_binary; int ret=0; #ifndef MINGW if (0 != ACCESS ("/dev/net/tun", R_OK)) { GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "access", "/dev/net/tun"); fprintf (stderr, "WARNING: System unable to run test, skipping.\n"); return 0; } #endif vpn_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn"); exit_binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-exit"); fprintf (stderr,"%s\n", vpn_binary); fprintf (stderr,"%s\n", exit_binary); if ((GNUNET_YES != (ret = GNUNET_OS_check_helper_binary (vpn_binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0"))) || //ipv4 only please! (GNUNET_YES != (ret = GNUNET_OS_check_helper_binary (exit_binary, GNUNET_YES, "-d gnunet-vpn - - - 169.1.3.3.7 255.255.255.0")))) //no nat, ipv4 only { GNUNET_free (vpn_binary); GNUNET_free (exit_binary); fprintf (stderr, "WARNING: gnunet-helper-{exit,vpn} binaries are not SUID, refusing to run test (as it would have to fail). %d\n", ret); return 0; } GNUNET_free (vpn_binary); GNUNET_free (exit_binary); bin = argv[0]; if (NULL != strstr (bin, "lt-")) bin = strstr (bin, "lt-") + 4; type = strstr (bin, "-"); if (NULL == type) { fprintf (stderr, "invalid binary name\n"); return 1; } type++; /* on Windows, .exe is suffixed to these binaries, * thus cease comparison after the 6th char. */ if (0 == strncmp (type, "4_to_6",6)) { dest_ip = "FC5A:04E1:C2BA::1"; dest_af = AF_INET6; src_af = AF_INET; } else if (0 == strncmp (type, "6_to_4",6)) { dest_ip = "169.254.86.1"; dest_af = AF_INET; src_af = AF_INET6; } else if (0 == strncmp (type, "4_over",6)) { dest_ip = "169.254.86.1"; dest_af = AF_INET; src_af = AF_INET; } else if (0 == strncmp (type, "6_over",6)) { dest_ip = "FC5A:04E1:C2BA::1"; dest_af = AF_INET6; src_af = AF_INET6; } else { fprintf (stderr, "invalid binary suffix `%s'\n", type); return 1; } if ((GNUNET_OK != GNUNET_NETWORK_test_pf (src_af)) || (GNUNET_OK != GNUNET_NETWORK_test_pf (dest_af))) { fprintf (stderr, "Required address families not supported by this system, skipping test.\n"); return 0; } if (0 != curl_global_init (CURL_GLOBAL_WIN32)) { fprintf (stderr, "failed to initialize curl\n"); return 2; } if (0 != GNUNET_TESTING_peer_run ("test-gnunet-vpn", "test_gnunet_vpn.conf", &run, NULL)) return 1; GNUNET_DISK_directory_remove ("/tmp/gnunet-test-vpn"); return global_ret; } /* end of test_gnunet_vpn.c */ gnunet-0.10.1/src/pt/test_gnunet_vpn.conf0000644000175000017500000000144112225230043015306 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/gnunet-test-vpn/ [transport] PLUGINS = tcp [arm] DEFAULTSERVICES = statistics exit vpn PORT = 0 ALLOW_SHUTDOWN = YES [exit] EXIT_IPV4 = YES EXIT_IPV6 = YES # FIXME: can we use 'lo'? EXIT_IFNAME = eth1 [testing] WEAKRANDOM = YES HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat [nse] WORKBITS = 1 # repeating some values from the default configurations # here as the respective network addresses are also # hard-wired in the tests and the MUST match (!) [vpn] IPV6ADDR = FC2D:FDAA:6A26::1 IPV6PREFIX = 64 IPV4ADDR = 169.254.20.1 IPV4MASK = 255.255.255.0 [exit] IPV6ADDR = FC5A:04E1:C2BA::1 IPV6PREFIX = 96 IPV4ADDR = 169.254.86.1 IPV4MASK = 255.255.255.0 [gns] AUTOSTART = NO [nat] USE_LOCALADDR = YES RETURN_LOCAL_ADDRESSES = YES [consensus] AUTOSTART = NO gnunet-0.10.1/src/dv/0000755000175000017500000000000012320755627011303 500000000000000gnunet-0.10.1/src/dv/dv.conf.in0000644000175000017500000000047612250373167013114 00000000000000[dv] AUTOSTART = @AUTOSTART@ ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; BINARY = gnunet-service-dv HOSTNAME = localhost @UNIXONLY@ PORT = 2571 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-dv.sock UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # ACCEPT_FROM = # ACCEPT_FROM6 = # REJECT_FROM = # REJECT_FROM6 = # BINDTO = gnunet-0.10.1/src/dv/template_dv.conf0000644000175000017500000000247112255010511014361 00000000000000# Peers: # # 6DER - 6DERP8U51AQ0QGLLHO7A75H47TTUIEFOVTT5ORN9N6P7V49PUTQ0 # 6ULB - 6ULBJK6QQJ64FAG9DF0292AS5IA9CCAC04IQU0HF8THM635HMBBG # DJ5S - DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50 # G3FJ - G3FJ2Q8AKMI0H556NTEURQES409BM3JHMCG99QR66R8LUAP1JESG # # Topology: # # Allowed connections: # 6DER - 6ULB # 6DER - DJ5S # 6DER - G3FJ # 6ULB - DJ5S # 6ULB - G3FJ # # Disallowed connections: # DJ5S - G3FJ [testbed] OVERLAY_TOPOLOGY = CLIQUE SETUP_TIMEOUT = 3 m OPERATION_TIMEOUT = 30 s CACHE_SIZE = 0 [transport-blacklist-G3FJ2Q8AKMI0H556NTEURQES409BM3JHMCG99QR66R8LUAP1JESG] DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50 = tcp [transport-blacklist-6DERP8U51AQ0QGLLHO7A75H47TTUIEFOVTT5ORN9N6P7V49PUTQ0] [transport-blacklist-DJ5SVJJDHH06BH1H0DE0V8CMBQG9AD8M85PF02SS3285AQ3R0R50] G3FJ2Q8AKMI0H556NTEURQES409BM3JHMCG99QR66R8LUAP1JESG = tcp [transport-blacklist-6ULBJK6QQJ64FAG9DF0292AS5IA9CCAC04IQU0HF8THM635HMBBG] [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-dv-testing/ [peerinfo] USE_INCLUDED_HELLOS = NO [arm] DEFAULTSERVICES = core [fs] AUTOSTART = NO [datastore] AUTOSTART = NO [dns] AUTOSTART = NO [nse] AUTOSTART = NO [chat] AUTOSTART = NO [gns] AUTOSTART = NO [vpn] AUTOSTART = NO [namestore] AUTOSTART = NO [lockmanager] AUTOSTART = NO [consensus] AUTOSTART = NO [nat] RETURN_LOCAL_ADDRESSES = YES gnunet-0.10.1/src/dv/dv.h0000644000175000017500000000762312253574266012020 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file dv/dv.h * @brief IPC messages between DV service and DV plugin */ #ifndef DV_H #define DV_H #include "gnunet_common.h" GNUNET_NETWORK_STRUCT_BEGIN /** * DV service tells plugin about a DV-connection being * now available. */ struct GNUNET_DV_ConnectMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DV_CONNECT */ struct GNUNET_MessageHeader header; /** * The distance to the peer that we are now connected to */ uint32_t distance GNUNET_PACKED; /** * The other peer (at the given distance). */ struct GNUNET_PeerIdentity peer; /** * The network the peer is in */ uint32_t network GNUNET_PACKED; }; /** * DV service tells plugin about a DV-connection being * no longer available. * * Sender address is copied to the end of this struct, * followed by the actual message received. */ struct GNUNET_DV_DisconnectMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DV_DISCONNECT */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * The peer that is no longer available. */ struct GNUNET_PeerIdentity peer; }; /** * DV Message, contains a message that was received via DV for this * peer. Send from the DV service to the DV plugin. * * Sender address is copied to the end of this struct, * followed by the actual message received. */ struct GNUNET_DV_ReceivedMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DV_RECV */ struct GNUNET_MessageHeader header; /** * The distance to the peer that we received the message from */ uint32_t distance GNUNET_PACKED; /** * The (actual) sender of the message */ struct GNUNET_PeerIdentity sender; /* payload follows */ }; /** * Message from plugin to DV service, requesting a * message to be routed. */ struct GNUNET_DV_SendMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DV_SEND */ struct GNUNET_MessageHeader header; /** * Unique ID for this message, for confirm callback, must never be zero. */ uint32_t uid GNUNET_PACKED; /** * The (actual) target of the message */ struct GNUNET_PeerIdentity target; }; /** * Message from service to DV plugin, saying that a * SEND request was handled. */ struct GNUNET_DV_AckMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DV_SEND_ACK or * #GNUNET_MESSAGE_TYPE_DV_SEND_NACK. */ struct GNUNET_MessageHeader header; /** * Which message is being acknowledged? */ uint32_t uid GNUNET_PACKED; /** * The (actual) target of the message */ struct GNUNET_PeerIdentity target; }; /** * Message from service to DV plugin, saying that our * distance to another peer changed. */ struct GNUNET_DV_DistanceUpdateMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED. */ struct GNUNET_MessageHeader header; /** * What is the new distance? */ uint32_t distance GNUNET_PACKED; /** * The peer for which the distance changed. */ struct GNUNET_PeerIdentity peer; /** * The network the peer is in */ uint32_t network GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/dv/plugin_transport_dv.c0000644000175000017500000005763512316473376015515 00000000000000/* This file is part of GNUnet (C) 2002--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dv/plugin_transport_dv.c * @brief DV transport service, takes incoming DV requests and deals with * the DV service * @author Nathan Evans * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet_dv_service.h" #include "gnunet_transport_service.h" #include "gnunet_transport_plugin.h" #include "dv.h" #define LOG(kind,...) GNUNET_log_from (kind, "transport-dv",__VA_ARGS__) #define PLUGIN_NAME "dv" /** * Encapsulation of all of the state of the plugin. */ struct Plugin; /** * An active request for transmission via DV. */ struct PendingRequest { /** * This is a DLL. */ struct PendingRequest *next; /** * This is a DLL. */ struct PendingRequest *prev; /** * Continuation function to call once the transmission buffer * has again space available. NULL if there is no * continuation to call. */ GNUNET_TRANSPORT_TransmitContinuation transmit_cont; /** * Closure for @e transmit_cont. */ void *transmit_cont_cls; /** * Transmission handle from DV client library. */ struct GNUNET_DV_TransmitHandle *th; /** * Session of this request. */ struct Session *session; /** * Number of bytes to transmit. */ size_t size; }; /** * Session handle for connections. */ struct Session { /** * Mandatory session header. */ struct SessionHeader header; /** * Pointer to the global plugin struct. */ struct Plugin *plugin; /** * Head of pending requests. */ struct PendingRequest *pr_head; /** * Tail of pending requests. */ struct PendingRequest *pr_tail; struct GNUNET_HELLO_Address *address; /** * To whom are we talking to. */ struct GNUNET_PeerIdentity sender; /** * Current distance to the given peer. */ uint32_t distance; /** * Current network the next hop peer is located in */ enum GNUNET_ATS_Network_Type network; /** * Does the transport service know about this session (and we thus * need to call `session_end` when it is released?) */ int active; }; /** * Encapsulation of all of the state of the plugin. */ struct Plugin { /** * Our environment. */ struct GNUNET_TRANSPORT_PluginEnvironment *env; /** * Hash map of sessions (active and inactive). */ struct GNUNET_CONTAINER_MultiPeerMap *sessions; /** * Copy of the handler array where the closures are * set to this struct's instance. */ struct GNUNET_SERVER_MessageHandler *handlers; /** * Handle to the DV service */ struct GNUNET_DV_ServiceHandle *dvh; /** * Tokenizer for boxed messages. */ struct GNUNET_SERVER_MessageStreamTokenizer *mst; }; /** * Notify transport service about the change in distance. * * @param session session where the distance changed */ static void notify_distance_change (struct Session *session) { struct Plugin *plugin = session->plugin; struct GNUNET_ATS_Information ats; if (GNUNET_YES != session->active) return; ats.type = htonl ((uint32_t) GNUNET_ATS_QUALITY_NET_DISTANCE); ats.value = htonl (session->distance); plugin->env->update_address_metrics (plugin->env->cls, session->address, session, &ats, 1); } /** * Function called by MST on each message from the box. * * @param cls closure with the `struct Plugin *` * @param client identification of the client (with the 'struct Session') * @param message the actual message * @return #GNUNET_OK on success */ static int unbox_cb (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct Plugin *plugin = cls; struct Session *session = client; struct GNUNET_ATS_Information ats; ats.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); ats.value = htonl (session->distance); session->active = GNUNET_YES; LOG (GNUNET_ERROR_TYPE_DEBUG, "Delivering message of type %u with %u bytes from peer `%s'\n", ntohs (message->type), ntohs (message->size), GNUNET_i2s (&session->sender)); plugin->env->receive (plugin->env->cls, session->address, session, message); plugin->env->update_address_metrics (plugin->env->cls, session->address, session, &ats, 1); return GNUNET_OK; } /** * Handler for messages received from the DV service. * * @param cls closure with the plugin * @param sender sender of the message * @param distance how far did the message travel * @param msg actual message payload */ static void handle_dv_message_received (void *cls, const struct GNUNET_PeerIdentity *sender, uint32_t distance, const struct GNUNET_MessageHeader *msg) { struct Plugin *plugin = cls; struct GNUNET_ATS_Information ats; struct Session *session; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received DV_MESSAGE_RECEIVED message for peer `%s': new distance %u\n", GNUNET_i2s (sender), distance); session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, sender); if (NULL == session) { GNUNET_break (0); return; } if (GNUNET_MESSAGE_TYPE_DV_BOX == ntohs (msg->type)) { /* need to unbox using MST */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Unboxing DV message using MST\n"); GNUNET_SERVER_mst_receive (plugin->mst, session, (const char *) &msg[1], ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader), GNUNET_YES, GNUNET_NO); return; } ats.type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); ats.value = htonl (distance); session->active = GNUNET_YES; LOG (GNUNET_ERROR_TYPE_DEBUG, "Delivering message of type %u with %u bytes from peer `%s'\n", ntohs (msg->type), ntohs (msg->size), GNUNET_i2s (sender)); plugin->env->receive (plugin->env->cls, session->address, session, msg); plugin->env->update_address_metrics (plugin->env->cls, session->address, session, &ats, 1); } /** * Function called if DV starts to be able to talk to a peer. * * @param cls closure with `struct Plugin *` * @param peer newly connected peer * @param distance distance to the peer * @param network the network the next hop is located in */ static void handle_dv_connect (void *cls, const struct GNUNET_PeerIdentity *peer, uint32_t distance, enum GNUNET_ATS_Network_Type network) { struct Plugin *plugin = cls; struct Session *session; struct GNUNET_ATS_Information ats[2]; GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != network); /** * This requires transport plugin to be linked to libgnunetats. * If you remove it, also remove libgnunetats linkage from Makefile.am */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message for peer `%s' with next hop in network %s\n", "DV_CONNECT", GNUNET_i2s (peer), GNUNET_ATS_print_network_type (network)); session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, peer); if (NULL != session) { GNUNET_break (0); session->distance = distance; notify_distance_change (session); return; /* nothing to do */ } session = GNUNET_new (struct Session); session->address = GNUNET_HELLO_address_allocate (peer, PLUGIN_NAME, NULL, 0, GNUNET_HELLO_ADDRESS_INFO_NONE); session->sender = *peer; session->plugin = plugin; session->distance = distance; session->network = network; GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (plugin->sessions, &session->sender, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new DV session %p for peer `%s' at distance %u\n", session, GNUNET_i2s (peer), distance); /* Notify transport and ats about new connection */ ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE); ats[0].value = htonl (distance); ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE); ats[1].value = htonl ((uint32_t) network); session->active = GNUNET_YES; plugin->env->session_start (plugin->env->cls, session->address, session, ats, 2); } /** * Function called if DV distance to a peer is changed. * * @param cls closure with `struct Plugin *` * @param peer connected peer * @param distance new distance to the peer * @param network network type used for the connection */ static void handle_dv_distance_changed (void *cls, const struct GNUNET_PeerIdentity *peer, uint32_t distance, enum GNUNET_ATS_Network_Type network) { struct Plugin *plugin = cls; struct Session *session; GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != network); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message for peer `%s': new distance %u\n", "DV_DISTANCE_CHANGED", GNUNET_i2s (peer), distance); session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, peer); if (NULL == session) { GNUNET_break (0); handle_dv_connect (plugin, peer, distance, network); return; } session->distance = distance; notify_distance_change (session); } /** * Release session object and clean up associated resources. * * @param session session to clean up */ static void free_session (struct Session *session) { struct Plugin *plugin = session->plugin; struct PendingRequest *pr; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (plugin->sessions, &session->sender, session)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Freeing session %p for peer `%s'\n", session, GNUNET_i2s (&session->sender)); if (GNUNET_YES == session->active) { plugin->env->session_end (plugin->env->cls, session->address, session); session->active = GNUNET_NO; } while (NULL != (pr = session->pr_head)) { GNUNET_CONTAINER_DLL_remove (session->pr_head, session->pr_tail, pr); GNUNET_DV_send_cancel (pr->th); pr->th = NULL; if (NULL != pr->transmit_cont) pr->transmit_cont (pr->transmit_cont_cls, &session->sender, GNUNET_SYSERR, pr->size, 0); GNUNET_free (pr); } GNUNET_HELLO_address_free (session->address); GNUNET_free (session); } /** * Function called if DV is no longer able to talk to a peer. * * @param cls closure with `struct Plugin *` * @param peer peer that disconnected */ static void handle_dv_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct Plugin *plugin = cls; struct Session *session; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message for peer `%s'\n", "DV_DISCONNECT", GNUNET_i2s (peer)); session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, peer); if (NULL == session) return; /* nothing to do */ free_session (session); } /** * Function called once the delivery of a message has been successful. * Clean up the pending request, and call continuations. * * @param cls closure * @param ok #GNUNET_OK on success, #GNUNET_SYSERR on error */ static void send_finished (void *cls, int ok) { struct PendingRequest *pr = cls; struct Session *session = pr->session; pr->th = NULL; GNUNET_CONTAINER_DLL_remove (session->pr_head, session->pr_tail, pr); if (NULL != pr->transmit_cont) pr->transmit_cont (pr->transmit_cont_cls, &session->sender, ok, pr->size, 0); GNUNET_free (pr); } /** * Function that can be used by the transport service to transmit * a message using the plugin. * * @param cls closure * @param session the session used * @param priority how important is the message * @param msgbuf the message to transmit * @param msgbuf_size number of bytes in 'msgbuf' * @param timeout when should we time out * @param cont continuation to call once the message has * been transmitted (or if the transport is ready * for the next transmission call; or if the * peer disconnected...) * @param cont_cls closure for @a cont * @return number of bytes used (on the physical network, with overheads); * -1 on hard errors (i.e. address invalid); 0 is a legal value * and does NOT mean that the message was not transmitted (DV) */ static ssize_t dv_plugin_send (void *cls, struct Session *session, const char *msgbuf, size_t msgbuf_size, unsigned int priority, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) { struct Plugin *plugin = cls; struct PendingRequest *pr; const struct GNUNET_MessageHeader *msg; struct GNUNET_MessageHeader *box; box = NULL; msg = (const struct GNUNET_MessageHeader *) msgbuf; if (ntohs (msg->size) != msgbuf_size) { /* need to box */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Boxing DV message\n"); box = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader) + msgbuf_size); box->type = htons (GNUNET_MESSAGE_TYPE_DV_BOX); box->size = htons (sizeof (struct GNUNET_MessageHeader) + msgbuf_size); memcpy (&box[1], msgbuf, msgbuf_size); msg = box; } pr = GNUNET_new (struct PendingRequest); pr->transmit_cont = cont; pr->transmit_cont_cls = cont_cls; pr->session = session; pr->size = msgbuf_size; GNUNET_CONTAINER_DLL_insert_tail (session->pr_head, session->pr_tail, pr); pr->th = GNUNET_DV_send (plugin->dvh, &session->sender, msg, &send_finished, pr); GNUNET_free_non_null (box); return 0; /* DV */ } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuations). * * @param cls closure with the `struct Plugin *` * @param target peer from which to disconnect */ static void dv_plugin_disconnect_peer (void *cls, const struct GNUNET_PeerIdentity *target) { struct Plugin *plugin = cls; struct Session *session; struct PendingRequest *pr; session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, target); if (NULL == session) return; /* nothing to do */ while (NULL != (pr = session->pr_head)) { GNUNET_CONTAINER_DLL_remove (session->pr_head, session->pr_tail, pr); GNUNET_DV_send_cancel (pr->th); pr->th = NULL; if (NULL != pr->transmit_cont) pr->transmit_cont (pr->transmit_cont_cls, &session->sender, GNUNET_SYSERR, pr->size, 0); GNUNET_free (pr); } session->active = GNUNET_NO; } /** * Function that can be used to force the plugin to disconnect * from the given peer and cancel all previous transmissions * (and their continuations). * * @param cls closure with the `struct Plugin *` * @param session which session to disconnect * @return #GNUNET_OK */ static int dv_plugin_disconnect_session (void *cls, struct Session *session) { struct PendingRequest *pr; while (NULL != (pr = session->pr_head)) { GNUNET_CONTAINER_DLL_remove (session->pr_head, session->pr_tail, pr); GNUNET_DV_send_cancel (pr->th); pr->th = NULL; if (NULL != pr->transmit_cont) pr->transmit_cont (pr->transmit_cont_cls, &session->sender, GNUNET_SYSERR, pr->size, 0); GNUNET_free (pr); } session->active = GNUNET_NO; return GNUNET_OK; } /** * Convert the transports address to a nice, human-readable * format. * * @param cls closure * @param type name of the transport that generated the address * @param addr one of the addresses of the host, NULL for the last address * the specific address format depends on the transport * @param addrlen length of the address * @param numeric should (IP) addresses be displayed in numeric form? * @param timeout after how long should we give up? * @param asc function to call on each string * @param asc_cls closure for @a asc */ static void dv_plugin_address_pretty_printer (void *cls, const char *type, const void *addr, size_t addrlen, int numeric, struct GNUNET_TIME_Relative timeout, GNUNET_TRANSPORT_AddressStringCallback asc, void *asc_cls) { if ( (0 == addrlen) && (0 == strcmp (type, "dv")) ) asc (asc_cls, "dv"); asc (asc_cls, NULL); } /** * Convert the DV address to a pretty string. * * @param cls closure * @param addr the (hopefully) DV address * @param addrlen the length of the @a addr * @return string representing the DV address */ static const char * dv_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) { if (0 != addrlen) { GNUNET_break (0); /* malformed */ return NULL; } return "dv"; } /** * Another peer has suggested an address for this peer and transport * plugin. Check that this could be a valid address. This function * is not expected to 'validate' the address in the sense of trying to * connect to it but simply to see if the binary format is technically * legal for establishing a connection to this peer (and make sure that * the address really corresponds to our network connection/settings * and not some potential man-in-the-middle). * * @param cls closure * @param addr pointer to the address * @param addrlen length of @a addr * @return #GNUNET_OK if this is a plausible address for this peer * and transport, #GNUNET_SYSERR if not * */ static int dv_plugin_check_address (void *cls, const void *addr, size_t addrlen) { if (0 != addrlen) return GNUNET_SYSERR; return GNUNET_OK; } /** * Create a new session to transmit data to the target * This session will used to send data to this peer and the plugin will * notify us by calling the env->session_end function * * @param cls the plugin * @param address the address * @return the session if the address is valid, NULL otherwise */ static struct Session * dv_get_session (void *cls, const struct GNUNET_HELLO_Address *address) { struct Plugin *plugin = cls; struct Session *session; if (0 != address->address_length) return NULL; session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, &address->peer); if (NULL == session) return NULL; /* not valid right now */ session->active = GNUNET_YES; return session; } /** * Function called to convert a string address to * a binary address. * * @param cls closure ('struct Plugin*') * @param addr string address * @param addrlen length of the @a addr including \0 termination * @param buf location to store the buffer * If the function returns #GNUNET_SYSERR, its contents are undefined. * @param added length of created address * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static int dv_plugin_string_to_address (void *cls, const char *addr, uint16_t addrlen, void **buf, size_t *added) { if ( (addrlen == 3) && (0 == strcmp ("dv", addr)) ) { *added = 0; return GNUNET_OK; } return GNUNET_SYSERR; } /** * Function that will be called whenever the transport service wants to * notify the plugin that a session is still active and in use and * therefore the session timeout for this session has to be updated * * @param cls closure (`struct Plugin *`) * @param peer which peer was the session for * @param session which session is being updated */ static void dv_plugin_update_session_timeout (void *cls, const struct GNUNET_PeerIdentity *peer, struct Session *session) { /* DV currently doesn't time out like "normal" plugins, so it should be safe to do nothing, right? (or should we add an internal timeout?) */ } /** * Function to obtain the network type for a session * FIXME: we should probably look at the network type * used by the next hop here. Or find some other way * to properly allow ATS-DV resource allocation. * * @param cls closure (`struct Plugin *`) * @param session the session * @return the network type */ static enum GNUNET_ATS_Network_Type dv_get_network (void *cls, struct Session *session) { GNUNET_assert (NULL != session); return session->network; } /** * Function that is called to get the keepalive factor. * GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to * calculate the interval between keepalive packets. * * @param cls closure with the `struct Plugin` * @return keepalive factor */ static unsigned int dv_plugin_query_keepalive_factor (void *cls) { return 3; } /** * Entry point for the plugin. * * @param cls closure with the plugin environment * @return plugin API */ void * libgnunet_plugin_transport_dv_init (void *cls) { struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; struct GNUNET_TRANSPORT_PluginFunctions *api; struct Plugin *plugin; plugin = GNUNET_new (struct Plugin); plugin->env = env; plugin->sessions = GNUNET_CONTAINER_multipeermap_create (1024 * 8, GNUNET_YES); plugin->mst = GNUNET_SERVER_mst_create (&unbox_cb, plugin); plugin->dvh = GNUNET_DV_service_connect (env->cfg, plugin, &handle_dv_connect, &handle_dv_distance_changed, &handle_dv_disconnect, &handle_dv_message_received); if (NULL == plugin->dvh) { GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions); GNUNET_SERVER_mst_destroy (plugin->mst); GNUNET_free (plugin); return NULL; } api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); api->cls = plugin; api->send = &dv_plugin_send; api->disconnect_peer = &dv_plugin_disconnect_peer; api->disconnect_session = &dv_plugin_disconnect_session; api->address_pretty_printer = &dv_plugin_address_pretty_printer; api->check_address = &dv_plugin_check_address; api->address_to_string = &dv_plugin_address_to_string; api->string_to_address = &dv_plugin_string_to_address; api->query_keepalive_factor = &dv_plugin_query_keepalive_factor; api->get_session = &dv_get_session; api->get_network = &dv_get_network; api->update_session_timeout = &dv_plugin_update_session_timeout; return api; } /** * Function called to free a session. * * @param cls NULL * @param key unused * @param value session to free * @return #GNUNET_OK (continue to iterate) */ static int free_session_iterator (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct Session *session = value; free_session (session); return GNUNET_OK; } /** * Exit point from the plugin. * * @param cls plugin API * @return NULL */ void * libgnunet_plugin_transport_dv_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; GNUNET_DV_service_disconnect (plugin->dvh); GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, &free_session_iterator, NULL); GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions); GNUNET_SERVER_mst_destroy (plugin->mst); GNUNET_free (plugin); GNUNET_free (api); return NULL; } /* end of plugin_transport_dv.c */ gnunet-0.10.1/src/dv/Makefile.in0000644000175000017500000013521412320752061013263 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ noinst_PROGRAMS = gnunet-dv$(EXEEXT) libexec_PROGRAMS = gnunet-service-dv$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = test_transport_blacklist$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_transport_dv$(EXEEXT) subdir = src/dv DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/dv.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = dv.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am_libgnunet_plugin_transport_dv_la_OBJECTS = plugin_transport_dv.lo libgnunet_plugin_transport_dv_la_OBJECTS = \ $(am_libgnunet_plugin_transport_dv_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_transport_dv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_transport_dv_la_LDFLAGS) $(LDFLAGS) -o $@ am__DEPENDENCIES_1 = libgnunetdv_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetdv_la_OBJECTS = dv_api.lo libgnunetdv_la_OBJECTS = $(am_libgnunetdv_la_OBJECTS) libgnunetdv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetdv_la_LDFLAGS) $(LDFLAGS) -o \ $@ PROGRAMS = $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_dv_OBJECTS = gnunet-dv.$(OBJEXT) gnunet_dv_OBJECTS = $(am_gnunet_dv_OBJECTS) gnunet_dv_DEPENDENCIES = libgnunetdv.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_gnunet_service_dv_OBJECTS = gnunet-service-dv.$(OBJEXT) gnunet_service_dv_OBJECTS = $(am_gnunet_service_dv_OBJECTS) gnunet_service_dv_DEPENDENCIES = \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/set/libgnunetset.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_transport_blacklist_OBJECTS = \ test_transport_blacklist.$(OBJEXT) test_transport_blacklist_OBJECTS = \ $(am_test_transport_blacklist_OBJECTS) test_transport_blacklist_DEPENDENCIES = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_transport_dv_OBJECTS = test_transport_dv.$(OBJEXT) test_transport_dv_OBJECTS = $(am_test_transport_dv_OBJECTS) test_transport_dv_DEPENDENCIES = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_transport_dv_la_SOURCES) \ $(libgnunetdv_la_SOURCES) $(gnunet_dv_SOURCES) \ $(gnunet_service_dv_SOURCES) \ $(test_transport_blacklist_SOURCES) \ $(test_transport_dv_SOURCES) DIST_SOURCES = $(libgnunet_plugin_transport_dv_la_SOURCES) \ $(libgnunetdv_la_SOURCES) $(gnunet_dv_SOURCES) \ $(gnunet_service_dv_SOURCES) \ $(test_transport_blacklist_SOURCES) \ $(test_transport_dv_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ dv.conf lib_LTLIBRARIES = libgnunetdv.la plugin_LTLIBRARIES = libgnunet_plugin_transport_dv.la libgnunetdv_la_SOURCES = \ dv_api.c dv.h libgnunetdv_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetdv_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 gnunet_service_dv_SOURCES = \ gnunet-service-dv.c dv.h gnunet_service_dv_LDADD = \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/set/libgnunetset.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_dv_SOURCES = \ gnunet-dv.c dv.h gnunet_dv_LDADD = \ libgnunetdv.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunet_plugin_transport_dv_la_SOURCES = \ plugin_transport_dv.c libgnunet_plugin_transport_dv_la_LIBADD = \ libgnunetdv.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_dv_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_dv_la_DEPENDENCIES = \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/hello/libgnunethello.la \ libgnunetdv.la @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_transport_dv_SOURCES = \ test_transport_dv.c test_transport_dv_LDADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_transport_blacklist_SOURCES = \ test_transport_blacklist.c test_transport_blacklist_LDADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_transport_dv_data.conf \ test_transport_blacklist_data.conf \ template_dv.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/dv/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/dv/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): dv.conf: $(top_builddir)/config.status $(srcdir)/dv.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_transport_dv.la: $(libgnunet_plugin_transport_dv_la_OBJECTS) $(libgnunet_plugin_transport_dv_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_transport_dv_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_transport_dv_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_transport_dv_la_OBJECTS) $(libgnunet_plugin_transport_dv_la_LIBADD) $(LIBS) libgnunetdv.la: $(libgnunetdv_la_OBJECTS) $(libgnunetdv_la_DEPENDENCIES) $(EXTRA_libgnunetdv_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetdv_la_LINK) -rpath $(libdir) $(libgnunetdv_la_OBJECTS) $(libgnunetdv_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-dv$(EXEEXT): $(gnunet_dv_OBJECTS) $(gnunet_dv_DEPENDENCIES) $(EXTRA_gnunet_dv_DEPENDENCIES) @rm -f gnunet-dv$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_dv_OBJECTS) $(gnunet_dv_LDADD) $(LIBS) gnunet-service-dv$(EXEEXT): $(gnunet_service_dv_OBJECTS) $(gnunet_service_dv_DEPENDENCIES) $(EXTRA_gnunet_service_dv_DEPENDENCIES) @rm -f gnunet-service-dv$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_dv_OBJECTS) $(gnunet_service_dv_LDADD) $(LIBS) test_transport_blacklist$(EXEEXT): $(test_transport_blacklist_OBJECTS) $(test_transport_blacklist_DEPENDENCIES) $(EXTRA_test_transport_blacklist_DEPENDENCIES) @rm -f test_transport_blacklist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_blacklist_OBJECTS) $(test_transport_blacklist_LDADD) $(LIBS) test_transport_dv$(EXEEXT): $(test_transport_dv_OBJECTS) $(test_transport_dv_DEPENDENCIES) $(EXTRA_test_transport_dv_DEPENDENCIES) @rm -f test_transport_dv$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_transport_dv_OBJECTS) $(test_transport_dv_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dv_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-dv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_transport_dv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_blacklist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_transport_dv.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_transport_blacklist.log: test_transport_blacklist$(EXEEXT) @p='test_transport_blacklist$(EXEEXT)'; \ b='test_transport_blacklist'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_transport_dv.log: test_transport_dv$(EXEEXT) @p='test_transport_dv$(EXEEXT)'; \ b='test_transport_dv'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-noinstPROGRAMS \ clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool clean-noinstPROGRAMS \ clean-pluginLTLIBRARIES cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/dv/test_transport_dv_data.conf0000644000175000017500000000065612255066642016655 00000000000000@INLINE@ template_dv.conf [transport] PORT = 2565 PLUGINS = tcp dv #PREFIX = valgrind --leak-check=full --track-fds=yes --leak-resolution=high [dv] AUTOSTART = YES # PREFIX = valgrind --leak-check=full --track-fds=yes --leak-resolution=high [set] AUTOSTART = YES # PREFIX = valgrind --leak-check=full --track-fds=yes --leak-resolution=high [core] # PREFIX = valgrind --leak-check=full --track-fds=yes --leak-resolution=high gnunet-0.10.1/src/dv/gnunet-dv.c0000644000175000017500000001072212252673741013300 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dv/gnunet-dv.c * @brief DV monitoring command line tool * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dv_service.h" /** * Handle to DV service. */ static struct GNUNET_DV_ServiceHandle *sh; /** * Was verbose specified? */ static int verbose; /** * Function called if DV starts to be able to talk to a peer. * * @param cls closure * @param peer newly connected peer * @param distance distance to the peer * @param network the network the next hop is located in */ static void connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer, uint32_t distance, enum GNUNET_ATS_Network_Type network) { fprintf (stderr, "Connect: %s at %u\n", GNUNET_i2s (peer), (unsigned int) distance); } /** * Function called if DV distance to a peer is changed. * * @param cls closure * @param peer connected peer * @param distance new distance to the peer * @param network network used on first hop to peer */ static void change_cb (void *cls, const struct GNUNET_PeerIdentity *peer, uint32_t distance, enum GNUNET_ATS_Network_Type network) { fprintf (stderr, "Change: %s at %u\n", GNUNET_i2s (peer), (unsigned int) distance); } /** * Function called if DV is no longer able to talk to a peer. * * @param cls closure * @param peer peer that disconnected */ static void disconnect_cb (void *cls, const struct GNUNET_PeerIdentity *peer) { fprintf (stderr, "Disconnect: %s\n", GNUNET_i2s (peer)); } /** * Function called if DV receives a message for this peer. * * @param cls closure * @param sender sender of the message * @param distance how far did the message travel * @param msg actual message payload */ static void message_cb (void *cls, const struct GNUNET_PeerIdentity *sender, uint32_t distance, const struct GNUNET_MessageHeader *msg) { if (verbose) fprintf (stderr, "Message: %s at %u sends %u bytes of type %u\n", GNUNET_i2s (sender), (unsigned int) distance, (unsigned int) ntohs (msg->size), (unsigned int) ntohs (msg->type)); } /** * Task run on shutdown. * * @param cls NULL * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_DV_service_disconnect (sh); sh = NULL; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { sh = GNUNET_DV_service_connect (cfg, NULL, &connect_cb, &change_cb, &disconnect_cb, &message_cb); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int res; static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'V', "verbose", NULL, gettext_noop ("verbose output"), 0, &GNUNET_GETOPT_set_one, &verbose}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; res = GNUNET_PROGRAM_run (argc, argv, "gnunet-dv", gettext_noop ("Print information about DV state"), options, &run, NULL); GNUNET_free ((void *) argv); if (GNUNET_OK != res) return 1; return 0; } /* end of gnunet-dv.c */ gnunet-0.10.1/src/dv/test_transport_dv.c0000644000175000017500000000660312255010511015137 00000000000000/* This file is part of GNUnet. (C) 2009, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dv/test_transport_dv.c * @brief base testcase for testing distance vector transport */ #include "platform.h" #include "gnunet_core_service.h" #include "gnunet_testbed_service.h" /** * Return value from main, set to 0 on success. */ static int ok; struct GNUNET_TESTBED_Operation *topology_op; static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != topology_op) { GNUNET_TESTBED_operation_done (topology_op); topology_op = NULL; } } static void topology_completed (void *cls, unsigned int nsuccess, unsigned int nfailures) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Links successful %u / %u failed\n", nsuccess, nfailures); GNUNET_TESTBED_operation_done (topology_op); topology_op = NULL; if (nfailures > 0) { fprintf (stderr, "Error: links successful %u but %u failed\n", nsuccess, nfailures); ok = 1; } else ok = 0; GNUNET_SCHEDULER_shutdown (); } static void test_connection (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); if (4 != num_peers) { ok = 1; fprintf (stderr, "Only %u out of 4 peers were started ...\n", num_peers); } if (0 != links_failed) { /* All peers except DV peers are connected */ fprintf (stderr, "Testbed failed to connect peers (%u links OK, %u links failed)\n", links_succeeded, links_failed); topology_op = GNUNET_TESTBED_overlay_configure_topology (NULL, num_peers, peers, NULL, &topology_completed, NULL, GNUNET_TESTBED_TOPOLOGY_CLIQUE, GNUNET_TESTBED_TOPOLOGY_OPTION_END); return; } ok = 1; fprintf (stderr, "Testbed connected peers, should not happen...\n"); GNUNET_SCHEDULER_shutdown (); } int main (int argc, char *argv[]) { ok = 1; /* Connecting initial topology */ (void) GNUNET_TESTBED_test_run ("test-transport-dv", "test_transport_dv_data.conf", 4, 0, NULL, NULL, &test_connection, NULL); return ok; } /* end of test_transport_dv.c */ gnunet-0.10.1/src/dv/Makefile.am0000644000175000017500000000510212320751517013247 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif plugindir = $(libdir)/gnunet libexecdir= $(pkglibdir)/libexec/ pkgcfgdir= $(pkgdatadir)/config.d/ pkgcfg_DATA = \ dv.conf lib_LTLIBRARIES = libgnunetdv.la plugin_LTLIBRARIES = libgnunet_plugin_transport_dv.la libgnunetdv_la_SOURCES = \ dv_api.c dv.h libgnunetdv_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetdv_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 noinst_PROGRAMS = \ gnunet-dv libexec_PROGRAMS = \ gnunet-service-dv gnunet_service_dv_SOURCES = \ gnunet-service-dv.c dv.h gnunet_service_dv_LDADD = \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/set/libgnunetset.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_dv_SOURCES = \ gnunet-dv.c dv.h gnunet_dv_LDADD = \ libgnunetdv.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunet_plugin_transport_dv_la_SOURCES = \ plugin_transport_dv.c libgnunet_plugin_transport_dv_la_LIBADD = \ libgnunetdv.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_transport_dv_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) libgnunet_plugin_transport_dv_la_DEPENDENCIES = \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/hello/libgnunethello.la \ libgnunetdv.la if HAVE_TESTING check_PROGRAMS = \ test_transport_blacklist \ test_transport_dv endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_transport_dv_SOURCES = \ test_transport_dv.c test_transport_dv_LDADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_transport_blacklist_SOURCES = \ test_transport_blacklist.c test_transport_blacklist_LDADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_transport_dv_data.conf \ test_transport_blacklist_data.conf \ template_dv.conf gnunet-0.10.1/src/dv/dv_api.c0000644000175000017500000004434312255010511012620 00000000000000/* This file is part of GNUnet. (C) 2009--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dv/dv_api.c * @brief library to access the DV service * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dv_service.h" #include "gnunet_protocols.h" #include "dv.h" #include "gnunet_transport_plugin.h" #define LOG(kind,...) GNUNET_log_from (kind, "dv-api",__VA_ARGS__) /** * Information we track for each peer. */ struct ConnectedPeer; /** * Handle for a send operation. */ struct GNUNET_DV_TransmitHandle { /** * Kept in a DLL. */ struct GNUNET_DV_TransmitHandle *next; /** * Kept in a DLL. */ struct GNUNET_DV_TransmitHandle *prev; /** * Handle to the service. */ struct GNUNET_DV_ServiceHandle *sh; /** * Function to call upon completion. */ GNUNET_DV_MessageSentCallback cb; /** * Closure for @a cb. */ void *cb_cls; /** * The actual message (allocated at the end of this struct). */ const struct GNUNET_MessageHeader *msg; /** * Destination for the message. */ struct ConnectedPeer *target; /** * UID of our message, if any. */ uint32_t uid; }; /** * Information we track for each peer. */ struct ConnectedPeer { /** * Identity of the peer. */ struct GNUNET_PeerIdentity pid; /** * Head of DLL of transmission handles where we need * to invoke a continuation when we are informed about * successful transmission. The respective request * has already been sent to the DV service. */ struct GNUNET_DV_TransmitHandle *head; /** * Tail of DLL of transmission handles where we need * to invoke a continuation when we are informed about * successful transmission. The respective request * has already been sent to the DV service. */ struct GNUNET_DV_TransmitHandle *tail; }; /** * Handle to the DV service. */ struct GNUNET_DV_ServiceHandle { /** * Connection to DV service. */ struct GNUNET_CLIENT_Connection *client; /** * Active request for transmission to DV service. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Closure for the callbacks. */ void *cls; /** * Function to call on connect events. */ GNUNET_DV_ConnectCallback connect_cb; /** * Function to call on distance change events. */ GNUNET_DV_DistanceChangedCallback distance_cb; /** * Function to call on disconnect events. */ GNUNET_DV_DisconnectCallback disconnect_cb; /** * Function to call on receiving messages events. */ GNUNET_DV_MessageReceivedCallback message_cb; /** * Head of messages to transmit. */ struct GNUNET_DV_TransmitHandle *th_head; /** * Tail of messages to transmit. */ struct GNUNET_DV_TransmitHandle *th_tail; /** * Information tracked per connected peer. Maps peer * identities to `struct ConnectedPeer` entries. */ struct GNUNET_CONTAINER_MultiPeerMap *peers; /** * Current unique ID */ uint32_t uid_gen; }; /** * Disconnect and then reconnect to the DV service. * * @param sh service handle */ static void reconnect (struct GNUNET_DV_ServiceHandle *sh); /** * Start sending messages from our queue to the service. * * @param sh service handle */ static void start_transmit (struct GNUNET_DV_ServiceHandle *sh); /** * Gives a message from our queue to the DV service. * * @param cls handle to the dv service (`struct GNUNET_DV_ServiceHandle`) * @param size how many bytes can we send * @param buf where to copy the message to send * @return how many bytes we copied to @a buf */ static size_t transmit_pending (void *cls, size_t size, void *buf) { struct GNUNET_DV_ServiceHandle *sh = cls; char *cbuf = buf; struct GNUNET_DV_TransmitHandle *th; size_t ret; size_t tsize; sh->th = NULL; if (NULL == buf) { reconnect (sh); return 0; } ret = 0; while ( (NULL != (th = sh->th_head)) && (size - ret >= (tsize = ntohs (th->msg->size)) )) { GNUNET_CONTAINER_DLL_remove (sh->th_head, sh->th_tail, th); memcpy (&cbuf[ret], th->msg, tsize); LOG (GNUNET_ERROR_TYPE_DEBUG, "Passing %u bytes of type %u to DV service\n", tsize, ntohs (th->msg->type)); th->msg = NULL; ret += tsize; if (NULL != th->cb) { GNUNET_CONTAINER_DLL_insert_tail (th->target->head, th->target->tail, th); } else { GNUNET_free (th); } } if (NULL != sh->th_head) start_transmit (sh); return ret; } /** * Start sending messages from our queue to the service. * * @param sh service handle */ static void start_transmit (struct GNUNET_DV_ServiceHandle *sh) { if (NULL != sh->th) return; if (NULL == sh->th_head) return; sh->th = GNUNET_CLIENT_notify_transmit_ready (sh->client, ntohs (sh->th_head->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_pending, sh); } /** * We got disconnected from the service and thus all of the * pending send callbacks will never be confirmed. Clean up. * * @param cls the 'struct GNUNET_DV_ServiceHandle' * @param key a peer identity * @param value a `struct ConnectedPeer` to clean up * @return #GNUNET_OK (continue to iterate) */ static int cleanup_send_cb (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_DV_ServiceHandle *sh = cls; struct ConnectedPeer *peer = value; struct GNUNET_DV_TransmitHandle *th; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (sh->peers, key, peer)); sh->disconnect_cb (sh->cls, key); while (NULL != (th = peer->head)) { GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, th); th->cb (th->cb_cls, GNUNET_SYSERR); GNUNET_free (th); } GNUNET_free (peer); return GNUNET_OK; } /** * Handles a message sent from the DV service to us. * Parse it out and give it to the plugin. * * @param cls the handle to the DV API * @param msg the message that was received */ static void handle_message_receipt (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_DV_ServiceHandle *sh = cls; const struct GNUNET_DV_ConnectMessage *cm; const struct GNUNET_DV_DistanceUpdateMessage *dum; const struct GNUNET_DV_DisconnectMessage *dm; const struct GNUNET_DV_ReceivedMessage *rm; const struct GNUNET_MessageHeader *payload; const struct GNUNET_DV_AckMessage *ack; struct GNUNET_DV_TransmitHandle *th; struct GNUNET_DV_TransmitHandle *tn; struct ConnectedPeer *peer; if (NULL == msg) { /* Connection closed */ reconnect (sh); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u with %u bytes from DV service\n", (unsigned int) ntohs (msg->type), (unsigned int) ntohs (msg->size)); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_DV_CONNECT: if (ntohs (msg->size) != sizeof (struct GNUNET_DV_ConnectMessage)) { GNUNET_break (0); reconnect (sh); return; } cm = (const struct GNUNET_DV_ConnectMessage *) msg; peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, &cm->peer); if (NULL != peer) { GNUNET_break (0); reconnect (sh); return; } peer = GNUNET_new (struct ConnectedPeer); peer->pid = cm->peer; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (sh->peers, &peer->pid, peer, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); sh->connect_cb (sh->cls, &cm->peer, ntohl (cm->distance), (enum GNUNET_ATS_Network_Type) ntohl (cm->network)); break; case GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED: if (ntohs (msg->size) != sizeof (struct GNUNET_DV_DistanceUpdateMessage)) { GNUNET_break (0); reconnect (sh); return; } dum = (const struct GNUNET_DV_DistanceUpdateMessage *) msg; sh->distance_cb (sh->cls, &dum->peer, ntohl (dum->distance), (enum GNUNET_ATS_Network_Type) ntohl (dum->network)); break; case GNUNET_MESSAGE_TYPE_DV_DISCONNECT: if (ntohs (msg->size) != sizeof (struct GNUNET_DV_DisconnectMessage)) { GNUNET_break (0); reconnect (sh); return; } dm = (const struct GNUNET_DV_DisconnectMessage *) msg; peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, &dm->peer); if (NULL == peer) { GNUNET_break (0); reconnect (sh); return; } tn = sh->th_head; while (NULL != (th = tn)) { tn = th->next; if (peer == th->target) { GNUNET_CONTAINER_DLL_remove (sh->th_head, sh->th_tail, th); th->cb (th->cb_cls, GNUNET_SYSERR); GNUNET_free (th); } } cleanup_send_cb (sh, &dm->peer, peer); break; case GNUNET_MESSAGE_TYPE_DV_RECV: if (ntohs (msg->size) < sizeof (struct GNUNET_DV_ReceivedMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); reconnect (sh); return; } rm = (const struct GNUNET_DV_ReceivedMessage *) msg; payload = (const struct GNUNET_MessageHeader *) &rm[1]; if (ntohs (msg->size) != sizeof (struct GNUNET_DV_ReceivedMessage) + ntohs (payload->size)) { GNUNET_break (0); reconnect (sh); return; } if (NULL == GNUNET_CONTAINER_multipeermap_get (sh->peers, &rm->sender)) { GNUNET_break (0); reconnect (sh); return; } sh->message_cb (sh->cls, &rm->sender, ntohl (rm->distance), payload); break; case GNUNET_MESSAGE_TYPE_DV_SEND_ACK: case GNUNET_MESSAGE_TYPE_DV_SEND_NACK: if (ntohs (msg->size) != sizeof (struct GNUNET_DV_AckMessage)) { GNUNET_break (0); reconnect (sh); return; } ack = (const struct GNUNET_DV_AckMessage *) msg; peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, &ack->target); if (NULL == peer) break; /* this happens, just ignore */ for (th = peer->head; NULL != th; th = th->next) { if (th->uid != ntohl (ack->uid)) continue; LOG (GNUNET_ERROR_TYPE_DEBUG, "Matched ACK for message to peer %s\n", GNUNET_i2s (&ack->target)); GNUNET_CONTAINER_DLL_remove (peer->head, peer->tail, th); th->cb (th->cb_cls, (ntohs (ack->header.type) == GNUNET_MESSAGE_TYPE_DV_SEND_ACK) ? GNUNET_OK : GNUNET_SYSERR); GNUNET_free (th); break; } break; default: reconnect (sh); break; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message, continuing receive loop for %p\n", sh->client); GNUNET_CLIENT_receive (sh->client, &handle_message_receipt, sh, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Transmit the start message to the DV service. * * @param cls the `struct GNUNET_DV_ServiceHandle *` * @param size number of bytes available in buf * @param buf where to copy the message * @return number of bytes written to buf */ static size_t transmit_start (void *cls, size_t size, void *buf) { struct GNUNET_DV_ServiceHandle *sh = cls; struct GNUNET_MessageHeader start_message; sh->th = NULL; if (NULL == buf) { GNUNET_break (0); reconnect (sh); return 0; } GNUNET_assert (size >= sizeof (start_message)); start_message.size = htons (sizeof (struct GNUNET_MessageHeader)); start_message.type = htons (GNUNET_MESSAGE_TYPE_DV_START); memcpy (buf, &start_message, sizeof (start_message)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting START request, starting receive loop for %p\n", sh->client); GNUNET_CLIENT_receive (sh->client, &handle_message_receipt, sh, GNUNET_TIME_UNIT_FOREVER_REL); start_transmit (sh); return sizeof (start_message); } /** * Disconnect and then reconnect to the DV service. * * @param sh service handle */ static void reconnect (struct GNUNET_DV_ServiceHandle *sh) { if (NULL != sh->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (sh->th); sh->th = NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from DV service at %p\n", sh->client); if (NULL != sh->client) { GNUNET_CLIENT_disconnect (sh->client); sh->client = NULL; } GNUNET_CONTAINER_multipeermap_iterate (sh->peers, &cleanup_send_cb, sh); LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to DV service\n"); sh->client = GNUNET_CLIENT_connect ("dv", sh->cfg); if (NULL == sh->client) { GNUNET_break (0); return; } sh->th = GNUNET_CLIENT_notify_transmit_ready (sh->client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_start, sh); } /** * Connect to the DV service. * * @param cfg configuration * @param cls closure for callbacks * @param connect_cb function to call on connects * @param distance_cb function to call if distances change * @param disconnect_cb function to call on disconnects * @param message_cb function to call if we receive messages * @return handle to access the service */ struct GNUNET_DV_ServiceHandle * GNUNET_DV_service_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_DV_ConnectCallback connect_cb, GNUNET_DV_DistanceChangedCallback distance_cb, GNUNET_DV_DisconnectCallback disconnect_cb, GNUNET_DV_MessageReceivedCallback message_cb) { struct GNUNET_DV_ServiceHandle *sh; sh = GNUNET_new (struct GNUNET_DV_ServiceHandle); sh->cfg = cfg; sh->cls = cls; sh->connect_cb = connect_cb; sh->distance_cb = distance_cb; sh->disconnect_cb = disconnect_cb; sh->message_cb = message_cb; sh->peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES); reconnect (sh); return sh; } /** * Disconnect from DV service. * * @param sh service handle */ void GNUNET_DV_service_disconnect (struct GNUNET_DV_ServiceHandle *sh) { struct GNUNET_DV_TransmitHandle *pos; if (NULL == sh) return; if (NULL != sh->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (sh->th); sh->th = NULL; } while (NULL != (pos = sh->th_head)) { GNUNET_CONTAINER_DLL_remove (sh->th_head, sh->th_tail, pos); GNUNET_free (pos); } if (NULL != sh->client) { GNUNET_CLIENT_disconnect (sh->client); sh->client = NULL; } GNUNET_CONTAINER_multipeermap_iterate (sh->peers, &cleanup_send_cb, sh); GNUNET_CONTAINER_multipeermap_destroy (sh->peers); GNUNET_free (sh); } /** * Send a message via DV service. * * @param sh service handle * @param target intended recpient * @param msg message payload * @param cb function to invoke when done * @param cb_cls closure for @a cb * @return handle to cancel the operation */ struct GNUNET_DV_TransmitHandle * GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh, const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, GNUNET_DV_MessageSentCallback cb, void *cb_cls) { struct GNUNET_DV_TransmitHandle *th; struct GNUNET_DV_SendMessage *sm; struct ConnectedPeer *peer; if (ntohs (msg->size) + sizeof (struct GNUNET_DV_SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to send %u bytes of type %u to %s via %p\n", (unsigned int) ntohs (msg->size), (unsigned int) ntohs (msg->type), GNUNET_i2s (target), sh->client); peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, target); if (NULL == peer) { GNUNET_break (0); return NULL; } th = GNUNET_malloc (sizeof (struct GNUNET_DV_TransmitHandle) + sizeof (struct GNUNET_DV_SendMessage) + ntohs (msg->size)); th->sh = sh; th->target = peer; th->cb = cb; th->cb_cls = cb_cls; th->msg = (const struct GNUNET_MessageHeader *) &th[1]; sm = (struct GNUNET_DV_SendMessage *) &th[1]; sm->header.type = htons (GNUNET_MESSAGE_TYPE_DV_SEND); sm->header.size = htons (sizeof (struct GNUNET_DV_SendMessage) + ntohs (msg->size)); if (0 == sh->uid_gen) sh->uid_gen = 1; th->uid = sh->uid_gen; sm->uid = htonl (sh->uid_gen++); /* use memcpy here as 'target' may not be sufficiently aligned */ memcpy (&sm->target, target, sizeof (struct GNUNET_PeerIdentity)); memcpy (&sm[1], msg, ntohs (msg->size)); GNUNET_CONTAINER_DLL_insert_tail (sh->th_head, sh->th_tail, th); start_transmit (sh); return th; } /** * Abort send operation (naturally, the message may have * already been transmitted; this only stops the 'cb' * from being called again). * * @param th send operation to cancel */ void GNUNET_DV_send_cancel (struct GNUNET_DV_TransmitHandle *th) { struct GNUNET_DV_ServiceHandle *sh = th->sh; if (NULL == th->msg) GNUNET_CONTAINER_DLL_remove (th->target->head, th->target->tail, th); else GNUNET_CONTAINER_DLL_remove (sh->th_head, sh->th_tail, th); GNUNET_free (th); } /* end of dv_api.c */ gnunet-0.10.1/src/dv/test_transport_blacklist.c0000644000175000017500000000401312225777502016510 00000000000000/* This file is part of GNUnet. (C) 2009, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dv/test_transport_blacklist.c * @brief base testcase for testing blacklist */ #include "platform.h" #include "gnunet_core_service.h" #include "gnunet_testbed_service.h" /** * Return value from main, set to 0 on success. */ static int ok; static void test_connection (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Links successful %u / %u failed\n", links_succeeded, links_failed); if ( (4 == num_peers) && (0 == links_failed) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Testbed connect peers despite blacklist!\n"); ok = 1; } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Note that getting a message about a timeout during setup is expected for this test.\n"); } GNUNET_SCHEDULER_shutdown (); } int main (int argc, char *argv[]) { (void) GNUNET_TESTBED_test_run ("test-transport-blacklist", "test_transport_blacklist_data.conf", 4, 0, NULL, NULL, &test_connection, NULL); return ok; } /* end of test_transport_blacklist.c */ gnunet-0.10.1/src/dv/gnunet-service-dv.c0000644000175000017500000020606512272513663014743 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dv/gnunet-service-dv.c * @brief the distance vector service, primarily handles gossip of nearby * peers and sending/receiving DV messages from core and decapsulating * them * * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_protocols.h" #include "gnunet_core_service.h" #include "gnunet_hello_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_statistics_service.h" #include "gnunet_set_service.h" #include "gnunet_ats_service.h" #include "dv.h" #include /** * How often do we establish the consensu? */ #define GNUNET_DV_CONSENSUS_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) /** * Maximum number of messages we queue per peer. */ #define MAX_QUEUE_SIZE 16 /** * Maximum number of messages we queue towards the clients/plugin. */ #define MAX_QUEUE_SIZE_PLUGIN 1024 /** * The default fisheye depth, from how many hops away will * we keep peers? */ #define DEFAULT_FISHEYE_DEPTH 3 /** * How many hops is a direct neighbor away? */ #define DIRECT_NEIGHBOR_COST 1 GNUNET_NETWORK_STRUCT_BEGIN /** * Information about a peer DV can route to. These entries are what * we use as the binary format to establish consensus to create our * routing table and as the address format in the HELLOs. */ struct Target { /** * Identity of the peer we can reach. */ struct GNUNET_PeerIdentity peer; /** * How many hops (1-3) is this peer away? in network byte order */ uint32_t distance GNUNET_PACKED; }; /** * Message exchanged between DV services (via core), requesting a * message to be routed. */ struct RouteMessage { /** * Type: #GNUNET_MESSAGE_TYPE_DV_ROUTE */ struct GNUNET_MessageHeader header; /** * Expected (remaining) distance. Must be always smaller than * #DEFAULT_FISHEYE_DEPTH, should be zero at the target. Must * be decremented by one at each hop. Peers must not forward * these messages further once the counter has reached zero. */ uint32_t distance GNUNET_PACKED; /** * The (actual) target of the message (this peer, if distance is zero). */ struct GNUNET_PeerIdentity target; /** * The (actual) sender of the message. */ struct GNUNET_PeerIdentity sender; }; GNUNET_NETWORK_STRUCT_END /** * Linked list of messages to send to clients. */ struct PendingMessage { /** * Pointer to next item in the list */ struct PendingMessage *next; /** * Pointer to previous item in the list */ struct PendingMessage *prev; /** * Actual message to be sent, allocated after this struct. */ const struct GNUNET_MessageHeader *msg; /** * Next target for the message (a neighbour of ours). */ struct GNUNET_PeerIdentity next_target; /** * Unique ID of the message. */ uint32_t uid; }; /** * Information about a direct neighbor (core-level, excluding * DV-links, only DV-enabled peers). */ struct DirectNeighbor { /** * Identity of the peer. */ struct GNUNET_PeerIdentity peer; /** * Session ID we use whenever we create a set union with * this neighbor; constructed from the XOR of our peer * IDs and then salted with "DV-SALT" to avoid conflicts * with other applications. */ struct GNUNET_HashCode real_session_id; /** * Head of linked list of messages to send to this peer. */ struct PendingMessage *pm_head; /** * Tail of linked list of messages to send to this peer. */ struct PendingMessage *pm_tail; /** * Transmit handle to core service. */ struct GNUNET_CORE_TransmitHandle *cth; /** * Routing table of the neighbor, NULL if not yet established. * Keys are peer identities, values are 'struct Target' entries. * Note that the distances in the targets are from the point-of-view * of the peer, not from us! */ struct GNUNET_CONTAINER_MultiPeerMap *neighbor_table; /** * Updated routing table of the neighbor, under construction, * NULL if we are not currently building it. * Keys are peer identities, values are 'struct Target' entries. * Note that the distances in the targets are from the point-of-view * of the other peer, not from us! */ struct GNUNET_CONTAINER_MultiPeerMap *neighbor_table_consensus; /** * Our current (exposed) routing table as a set. */ struct GNUNET_SET_Handle *my_set; /** * Handle for our current active set union operation. */ struct GNUNET_SET_OperationHandle *set_op; /** * Handle used if we are listening for this peer, waiting for the * other peer to initiate construction of the set union. NULL if * we ar the initiating peer. */ struct GNUNET_SET_ListenHandle *listen_handle; /** * ID of the task we use to (periodically) update our consensus * with this peer. Used if we are the initiating peer. */ GNUNET_SCHEDULER_TaskIdentifier initiate_task; /** * At what offset are we, with respect to inserting our own routes * into the consensus? */ unsigned int consensus_insertion_offset; /** * At what distance are we, with respect to inserting our own routes * into the consensus? */ unsigned int consensus_insertion_distance; /** * Number of messages currently in the 'pm_XXXX'-DLL. */ unsigned int pm_queue_size; /** * Elements in consensus */ unsigned int consensus_elements; /** * Direct one hop route */ struct Route *direct_route; /** * Flag set within 'check_target_removed' to trigger full global route refresh. */ int target_removed; /** * Our distance to this peer, 0 for unknown. */ uint32_t distance; /** * The network this peer is in */ enum GNUNET_ATS_Network_Type network; /** * Is this neighbor connected at the core level? */ int connected; }; /** * A route includes information about the next hop, * the target, and the ultimate distance to the * target. */ struct Route { /** * Which peer do we need to forward the message to? */ struct DirectNeighbor *next_hop; /** * What would be the target, and how far is it away? */ struct Target target; /** * Offset of this target in the respective consensus set. */ unsigned int set_offset; }; /** * Set of targets we bring to a consensus; all targets in a set have a * distance equal to the sets distance (which is implied by the array * index of the set). */ struct ConsensusSet { /** * Array of targets in the set, may include NULL entries if a * neighbor has disconnected; the targets are allocated with the * respective container (all_routes), not here. */ struct Route **targets; /** * Size of the @e targets array. */ unsigned int array_length; }; /** * Peermap of all of our neighbors; processing these usually requires * first checking to see if the peer is core-connected and if the * distance is 1, in which case they are direct neighbors. */ static struct GNUNET_CONTAINER_MultiPeerMap *direct_neighbors; /** * Hashmap with all routes that we currently support; contains * routing information for all peers from distance 2 * up to distance #DEFAULT_FISHEYE_DEPTH. */ static struct GNUNET_CONTAINER_MultiPeerMap *all_routes; /** * Array of consensus sets we expose to the outside world. Sets * are structured by the distance to the target. */ static struct ConsensusSet consensi[DEFAULT_FISHEYE_DEPTH]; /** * Handle to the core service api. */ static struct GNUNET_CORE_Handle *core_api; /** * The identity of our peer. */ static struct GNUNET_PeerIdentity my_identity; /** * The configuration for this service. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * The client, the DV plugin connected to us (or an event monitor). * Hopefully this client will never change, although if the plugin * dies and returns for some reason it may happen. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Handle for the statistics service. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Handle to ATS service. */ static struct GNUNET_ATS_PerformanceHandle *ats; /** * Task scheduled to refresh routes based on direct neighbours. */ static GNUNET_SCHEDULER_TaskIdentifier rr_task; /** * #GNUNET_YES if we are shutting down. */ static int in_shutdown; /** * Start creating a new DV set union by initiating the connection. * * @param cls the 'struct DirectNeighbor' of the peer we're building * a routing consensus with * @param tc scheduler context */ static void initiate_set_union (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Start creating a new DV set union construction, our neighbour has * asked for it (callback for listening peer). * * @param cls the 'struct DirectNeighbor' of the peer we're building * a routing consensus with * @param other_peer the other peer * @param context_msg message with application specific information from * the other peer * @param request request from the other peer, use GNUNET_SET_accept * to accept it, otherwise the request will be refused * Note that we don't use a return value here, as it is also * necessary to specify the set we want to do the operation with, * whith sometimes can be derived from the context message. * Also necessary to specify the timeout. */ static void listen_set_union (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request); /** * Forward a message from another peer to the plugin. * * @param message the message to send to the plugin * @param origin the original sender of the message * @param distance distance to the original sender of the message */ static void send_data_to_plugin (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *origin, uint32_t distance) { struct GNUNET_DV_ReceivedMessage *received_msg; size_t size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering message from peer `%s' at distance %u\n", GNUNET_i2s (origin), (unsigned int) distance); size = sizeof (struct GNUNET_DV_ReceivedMessage) + ntohs (message->size); if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); /* too big */ return; } received_msg = GNUNET_malloc (size); received_msg->header.size = htons (size); received_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_RECV); received_msg->distance = htonl (distance); received_msg->sender = *origin; memcpy (&received_msg[1], message, ntohs (message->size)); GNUNET_SERVER_notification_context_broadcast (nc, &received_msg->header, GNUNET_YES); GNUNET_free (received_msg); } /** * Forward a control message to the plugin. * * @param message the message to send to the plugin */ static void send_control_to_plugin (const struct GNUNET_MessageHeader *message) { GNUNET_SERVER_notification_context_broadcast (nc, message, GNUNET_NO); } /** * Give an (N)ACK message to the plugin, we transmitted a message for it. * * @param target peer that received the message * @param uid plugin-chosen UID for the message * @param nack #GNUNET_NO to send ACK, #GNUNET_YES to send NACK */ static void send_ack_to_plugin (const struct GNUNET_PeerIdentity *target, uint32_t uid, int nack) { struct GNUNET_DV_AckMessage ack_msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering ACK for message to peer `%s'\n", GNUNET_i2s (target)); ack_msg.header.size = htons (sizeof (ack_msg)); ack_msg.header.type = htons ((GNUNET_YES == nack) ? GNUNET_MESSAGE_TYPE_DV_SEND_NACK : GNUNET_MESSAGE_TYPE_DV_SEND_ACK); ack_msg.uid = htonl (uid); ack_msg.target = *target; send_control_to_plugin (&ack_msg.header); } /** * Send a DISTANCE_CHANGED message to the plugin. * * @param peer peer with a changed distance * @param distance new distance to the peer * @param network network used by the neighbor */ static void send_distance_change_to_plugin (const struct GNUNET_PeerIdentity *peer, uint32_t distance, enum GNUNET_ATS_Network_Type network) { struct GNUNET_DV_DistanceUpdateMessage du_msg; GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != network); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering DISTANCE_CHANGED for message about peer `%s'\n", GNUNET_i2s (peer)); du_msg.header.size = htons (sizeof (du_msg)); du_msg.header.type = htons (GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED); du_msg.distance = htonl (distance); du_msg.peer = *peer; du_msg.network = htonl ((uint32_t) network); send_control_to_plugin (&du_msg.header); } /** * Give a CONNECT message to the plugin. * * @param target peer that connected * @param distance distance to the target * @param network the network the next hop is located in */ static void send_connect_to_plugin (const struct GNUNET_PeerIdentity *target, uint32_t distance, enum GNUNET_ATS_Network_Type network) { struct GNUNET_DV_ConnectMessage cm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering CONNECT about peer %s with distance %u\n", GNUNET_i2s (target), distance); cm.header.size = htons (sizeof (cm)); cm.header.type = htons (GNUNET_MESSAGE_TYPE_DV_CONNECT); cm.distance = htonl (distance); cm.network = htonl ((uint32_t) network); cm.peer = *target; send_control_to_plugin (&cm.header); } /** * Give a DISCONNECT message to the plugin. * * @param target peer that disconnected */ static void send_disconnect_to_plugin (const struct GNUNET_PeerIdentity *target) { struct GNUNET_DV_DisconnectMessage dm; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering DISCONNECT about peer `%s'\n", GNUNET_i2s (target)); dm.header.size = htons (sizeof (dm)); dm.header.type = htons (GNUNET_MESSAGE_TYPE_DV_DISCONNECT); dm.reserved = htonl (0); dm.peer = *target; send_control_to_plugin (&dm.header); } /** * Function called to transfer a message to another peer * via core. * * @param cls closure with the direct neighbor * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t core_transmit_notify (void *cls, size_t size, void *buf) { struct DirectNeighbor *dn = cls; char *cbuf = buf; struct PendingMessage *pending; size_t off; size_t msize; dn->cth = NULL; if (NULL == buf) { /* client disconnected */ return 0; } off = 0; while ( (NULL != (pending = dn->pm_head)) && (size >= off + (msize = ntohs (pending->msg->size)))) { dn->pm_queue_size--; GNUNET_CONTAINER_DLL_remove (dn->pm_head, dn->pm_tail, pending); memcpy (&cbuf[off], pending->msg, msize); if (0 != pending->uid) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Acking transmission of %u bytes to %s with plugin\n", msize, GNUNET_i2s (&pending->next_target)); send_ack_to_plugin (&pending->next_target, pending->uid, GNUNET_NO); } GNUNET_free (pending); off += msize; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting total of %u bytes to %s\n", off, GNUNET_i2s (&dn->peer)); GNUNET_assert (NULL != core_api); if (NULL != dn->pm_head) dn->cth = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_YES /* cork */, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_UNIT_FOREVER_REL, &dn->peer, msize, &core_transmit_notify, dn); return off; } /** * Forward the given payload to the given target. * * @param target where to send the message * @param distance distance to the @a sender * @param uid unique ID for the message * @param sender original sender of the message * @param actual_target ultimate recipient for the message * @param payload payload of the message */ static void forward_payload (struct DirectNeighbor *target, uint32_t distance, uint32_t uid, const struct GNUNET_PeerIdentity *sender, const struct GNUNET_PeerIdentity *actual_target, const struct GNUNET_MessageHeader *payload) { struct PendingMessage *pm; struct RouteMessage *rm; size_t msize; if ( (target->pm_queue_size >= MAX_QUEUE_SIZE) && (0 == uid) && (0 != memcmp (sender, &my_identity, sizeof (struct GNUNET_PeerIdentity))) ) { /* not _our_ client and queue is full, drop */ GNUNET_STATISTICS_update (stats, "# messages dropped", 1, GNUNET_NO); return; } msize = sizeof (struct RouteMessage) + ntohs (payload->size); if (msize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); return; } pm = GNUNET_malloc (sizeof (struct PendingMessage) + msize); pm->next_target = target->peer; pm->uid = uid; pm->msg = (const struct GNUNET_MessageHeader *) &pm[1]; rm = (struct RouteMessage *) &pm[1]; rm->header.size = htons ((uint16_t) msize); rm->header.type = htons (GNUNET_MESSAGE_TYPE_DV_ROUTE); rm->distance = htonl (distance); rm->target = *actual_target; rm->sender = *sender; memcpy (&rm[1], payload, ntohs (payload->size)); GNUNET_CONTAINER_DLL_insert_tail (target->pm_head, target->pm_tail, pm); target->pm_queue_size++; GNUNET_assert (NULL != core_api); if (NULL == target->cth) target->cth = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_YES /* cork */, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_UNIT_FOREVER_REL, &target->peer, msize, &core_transmit_notify, target); } /** * Find a free slot for storing a 'route' in the 'consensi' * set at the given distance. * * @param distance distance to use for the set slot */ static unsigned int get_consensus_slot (uint32_t distance) { struct ConsensusSet *cs; unsigned int i; GNUNET_assert (distance < DEFAULT_FISHEYE_DEPTH); cs = &consensi[distance]; i = 0; while ( (i < cs->array_length) && (NULL != cs->targets[i]) ) i++; if (i == cs->array_length) { GNUNET_array_grow (cs->targets, cs->array_length, cs->array_length * 2 + 2); } return i; } /** * Allocate a slot in the consensus set for a route. * * @param route route to initialize * @param distance which consensus set to use */ static void allocate_route (struct Route *route, uint32_t distance) { unsigned int i; if (distance >= DEFAULT_FISHEYE_DEPTH) { route->target.distance = htonl (distance); route->set_offset = UINT_MAX; /* invalid slot */ return; } i = get_consensus_slot (distance); route->set_offset = i; consensi[distance].targets[i] = route; route->target.distance = htonl (distance); } /** * Release a slot in the consensus set for a route. * * @param route route to release the slot from */ static void release_route (struct Route *route) { if (UINT_MAX == route->set_offset) return; GNUNET_assert (ntohl (route->target.distance) < DEFAULT_FISHEYE_DEPTH); consensi[ntohl (route->target.distance)].targets[route->set_offset] = NULL; route->set_offset = UINT_MAX; /* indicate invalid slot */ } /** * Move a route from one consensus set to another. * * @param route route to move * @param new_distance new distance for the route (destination set) */ static void move_route (struct Route *route, uint32_t new_distance) { release_route (route); allocate_route (route, new_distance); } /** * Initialize this neighbors 'my_set' and when done give * it to the pending set operation for execution. * * Add a single element to the set per call: * * If we reached the last element of a consensus element: increase distance * * * @param cls the neighbor for which we are building the set */ static void build_set (void *cls) { struct DirectNeighbor *neighbor = cls; struct GNUNET_SET_Element element; struct Target *target; struct Route *route; target = NULL; /* skip over NULL entries */ while ( (DEFAULT_FISHEYE_DEPTH > neighbor->consensus_insertion_distance) && (consensi[neighbor->consensus_insertion_distance].array_length > neighbor->consensus_insertion_offset) && (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) neighbor->consensus_insertion_offset++; while ( (DEFAULT_FISHEYE_DEPTH > neighbor->consensus_insertion_distance) && (consensi[neighbor->consensus_insertion_distance].array_length == neighbor->consensus_insertion_offset) ) { /* If we reached the last element of a consensus array element: increase distance and start with next array */ neighbor->consensus_insertion_offset = 0; neighbor->consensus_insertion_distance++; /* skip over NULL entries */ while ( (DEFAULT_FISHEYE_DEPTH > neighbor->consensus_insertion_distance) && (consensi[neighbor->consensus_insertion_distance].array_length > neighbor->consensus_insertion_offset) && (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) neighbor->consensus_insertion_offset++; } if (DEFAULT_FISHEYE_DEPTH == neighbor->consensus_insertion_distance) { /* we have added all elements to the set, run the operation */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished building my SET for peer `%s' with %u elements, committing\n", GNUNET_i2s (&neighbor->peer), neighbor->consensus_elements); GNUNET_SET_commit (neighbor->set_op, neighbor->my_set); GNUNET_SET_destroy (neighbor->my_set); neighbor->my_set = NULL; return; } route = consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]; GNUNET_assert (NULL != route); target = &route->target; GNUNET_assert (ntohl (target->distance) < DEFAULT_FISHEYE_DEPTH); element.size = sizeof (struct Target); element.type = htons (0); /* do we need this? */ element.data = target; /* Find next non-NULL entry */ neighbor->consensus_insertion_offset++; if ( (0 != memcmp (&target->peer, &my_identity, sizeof (my_identity))) && (0 != memcmp (&target->peer, &neighbor->peer, sizeof (neighbor->peer))) ) { /* Add target if it is not the neighbor or this peer */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding peer `%s' with distance %u to SET\n", GNUNET_i2s (&target->peer), ntohl (target->distance) + 1); GNUNET_SET_add_element (neighbor->my_set, &element, &build_set, neighbor); neighbor->consensus_elements++; } else build_set (neighbor); } /** * A peer is now connected to us at distance 1. Initiate DV exchange. * * @param neighbor entry for the neighbor at distance 1 */ static void handle_direct_connect (struct DirectNeighbor *neighbor) { struct Route *route; struct GNUNET_HashCode h1; struct GNUNET_HashCode h2; struct GNUNET_HashCode session_id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Direct connection to %s established, routing table exchange begins.\n", GNUNET_i2s (&neighbor->peer)); GNUNET_STATISTICS_update (stats, "# peers connected (1-hop)", 1, GNUNET_NO); route = GNUNET_CONTAINER_multipeermap_get (all_routes, &neighbor->peer); if (NULL != route) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (all_routes, &neighbor->peer, route)); send_disconnect_to_plugin (&neighbor->peer); release_route (route); GNUNET_free (route); } neighbor->direct_route = GNUNET_new (struct Route); neighbor->direct_route->next_hop = neighbor; neighbor->direct_route->target.peer = neighbor->peer; allocate_route (neighbor->direct_route, DIRECT_NEIGHBOR_COST); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Adding direct route to %s\n", GNUNET_i2s (&neighbor->direct_route->target.peer)); /* construct session ID seed as XOR of both peer's identities */ GNUNET_CRYPTO_hash (&my_identity, sizeof (my_identity), &h1); GNUNET_CRYPTO_hash (&neighbor->peer, sizeof (struct GNUNET_PeerIdentity), &h2); GNUNET_CRYPTO_hash_xor (&h1, &h2, &session_id); /* make sure session ID is unique across applications by salting it with 'DV' */ GNUNET_CRYPTO_hkdf (&neighbor->real_session_id, sizeof (struct GNUNET_HashCode), GCRY_MD_SHA512, GCRY_MD_SHA256, "DV-SALT", 2, &session_id, sizeof (session_id), NULL, 0); if (0 < memcmp (&neighbor->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity))) { if (NULL != neighbor->listen_handle) { GNUNET_break (0); } else neighbor->initiate_task = GNUNET_SCHEDULER_add_now (&initiate_set_union, neighbor); } else { if (NULL != neighbor->listen_handle) { GNUNET_break (0); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting SET listen operation with peer `%s'\n", GNUNET_i2s(&neighbor->peer)); neighbor->listen_handle = GNUNET_SET_listen (cfg, GNUNET_SET_OPERATION_UNION, &neighbor->real_session_id, &listen_set_union, neighbor); } } } /** * Method called whenever a peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct DirectNeighbor *neighbor; /* Check for connect to self message */ if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; /* check if entry exists */ neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, peer); if (NULL != neighbor) { GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != neighbor->network); GNUNET_break (GNUNET_YES != neighbor->connected); neighbor->connected = GNUNET_YES; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core connected to %s (distance %u)\n", GNUNET_i2s (peer), (unsigned int) neighbor->distance); if (DIRECT_NEIGHBOR_COST != neighbor->distance) return; handle_direct_connect (neighbor); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core connected to %s (distance unknown)\n", GNUNET_i2s (peer)); neighbor = GNUNET_new (struct DirectNeighbor); neighbor->peer = *peer; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (direct_neighbors, peer, neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); neighbor->connected = GNUNET_YES; neighbor->distance = 0; /* unknown */ neighbor->network = GNUNET_ATS_NET_UNSPECIFIED; } /** * Called for each 'target' in a neighbor table to free the associated memory. * * @param cls NULL * @param key key of the value * @param value value to free * @return #GNUNET_OK to continue to iterate */ static int free_targets (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { GNUNET_free (value); return GNUNET_OK; } /** * Add a new route to the given @a target via the given @a neighbor. * * @param target the target of the route * @param neighbor the next hop for communicating with the @a target */ static void add_new_route (struct Target *target, struct DirectNeighbor *neighbor) { struct Route *route; route = GNUNET_new (struct Route); route->next_hop = neighbor; route->target.peer = target->peer; allocate_route (route, ntohl (target->distance) + 1); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (all_routes, &route->target.peer, route, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); send_connect_to_plugin (&route->target.peer, ntohl (route->target.distance), neighbor->network); } /** * Multipeerhmap iterator for checking if a given route is * (now) useful to this peer. * * @param cls the direct neighbor for the given route * @param key key value stored under * @param value a 'struct Target' that may or may not be useful; not that * the distance in 'target' does not include the first hop yet * @return #GNUNET_YES to continue iteration, #GNUNET_NO to stop */ static int check_possible_route (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct DirectNeighbor *neighbor = cls; struct Target *target = value; struct Route *route; if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (direct_neighbors, key)) return GNUNET_YES; /* direct route, do not care about alternatives */ route = GNUNET_CONTAINER_multipeermap_get (all_routes, key); if (NULL != route) { /* we have an existing route, check how it compares with going via 'target' */ if (ntohl (route->target.distance) > ntohl (target->distance) + 1) { /* via 'target' is cheaper than the existing route; switch to alternative route! */ move_route (route, ntohl (target->distance) + 1); route->next_hop = neighbor; send_distance_change_to_plugin (&target->peer, ntohl (target->distance) + 1, neighbor->network); } return GNUNET_YES; /* got a route to this target already */ } if (ntohl (target->distance) >= DEFAULT_FISHEYE_DEPTH) return GNUNET_YES; /* distance is too large to be interesting */ add_new_route (target, neighbor); return GNUNET_YES; } /** * Multipeermap iterator for finding routes that were previously * "hidden" due to a better route (called after a disconnect event). * * @param cls NULL * @param key peer identity of the given direct neighbor * @param value a `struct DirectNeighbor` to check for additional routes * @return #GNUNET_YES to continue iteration */ static int refresh_routes (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct DirectNeighbor *neighbor = value; if ( (GNUNET_YES != neighbor->connected) || (DIRECT_NEIGHBOR_COST != neighbor->distance) ) return GNUNET_YES; if (NULL != neighbor->neighbor_table) GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, &check_possible_route, neighbor); return GNUNET_YES; } /** * Task to run #refresh_routes() on all direct neighbours. * * @param cls NULL * @param tc unused */ static void refresh_routes_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { rr_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_CONTAINER_multipeermap_iterate (direct_neighbors, &refresh_routes, NULL); } /** * Asynchronously run #refresh_routes() at the next opportunity * on all direct neighbours. */ static void schedule_refresh_routes () { if (GNUNET_SCHEDULER_NO_TASK == rr_task) rr_task = GNUNET_SCHEDULER_add_now (&refresh_routes_task, NULL); } /** * Get distance information from 'atsi'. * * @param atsi performance data * @param atsi_count number of entries in atsi * @return connected transport distance */ static uint32_t get_atsi_distance (const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { uint32_t i; for (i = 0; i < atsi_count; i++) if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DISTANCE) return (0 == ntohl (atsi[i].value)) ? DIRECT_NEIGHBOR_COST : ntohl (atsi[i].value); // FIXME: 0 check should not be required once ATS is fixed! /* If we do not have explicit distance data, assume direct neighbor. */ return DIRECT_NEIGHBOR_COST; } /** * Get network information from 'atsi'. * * @param atsi performance data * @param atsi_count number of entries in atsi * @return connected transport network */ static enum GNUNET_ATS_Network_Type get_atsi_network (const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { uint32_t i; for (i = 0; i < atsi_count; i++) if (ntohl (atsi[i].type) == GNUNET_ATS_NETWORK_TYPE) return (enum GNUNET_ATS_Network_Type) ntohl (atsi[i].value); return GNUNET_ATS_NET_UNSPECIFIED; } /** * Multipeermap iterator for freeing routes that go via a particular * neighbor that disconnected and is thus no longer available. * * @param cls the direct neighbor that is now unavailable * @param key key value stored under * @param value a `struct Route` that may or may not go via neighbor * * @return #GNUNET_YES to continue iteration, #GNUNET_NO to stop */ static int cull_routes (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct DirectNeighbor *neighbor = cls; struct Route *route = value; if (route->next_hop != neighbor) return GNUNET_YES; /* not affected */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (all_routes, key, value)); release_route (route); send_disconnect_to_plugin (&route->target.peer); GNUNET_free (route); return GNUNET_YES; } /** * Handle the case that a direct connection to a peer is * disrupted. Remove all routes via that peer and * stop the consensus with it. * * @param neighbor peer that was disconnected (or at least is no * longer at distance 1) */ static void handle_direct_disconnect (struct DirectNeighbor *neighbor) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Culling routes via %s due to direct disconnect\n", GNUNET_i2s (&neighbor->peer)); GNUNET_CONTAINER_multipeermap_iterate (all_routes, &cull_routes, neighbor); if (NULL != neighbor->cth) { GNUNET_CORE_notify_transmit_ready_cancel (neighbor->cth); neighbor->cth = NULL; } if (NULL != neighbor->direct_route) { release_route (neighbor->direct_route); GNUNET_free (neighbor->direct_route); neighbor->direct_route = NULL; } if (NULL != neighbor->neighbor_table_consensus) { GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, &free_targets, NULL); GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table_consensus); neighbor->neighbor_table_consensus = NULL; } if (NULL != neighbor->neighbor_table) { GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, &free_targets, NULL); GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table); neighbor->neighbor_table = NULL; } if (NULL != neighbor->set_op) { GNUNET_SET_operation_cancel (neighbor->set_op); neighbor->set_op = NULL; } if (NULL != neighbor->my_set) { GNUNET_SET_destroy (neighbor->my_set); neighbor->my_set = NULL; } if (NULL != neighbor->listen_handle) { GNUNET_SET_listen_cancel (neighbor->listen_handle); neighbor->listen_handle = NULL; } if (GNUNET_SCHEDULER_NO_TASK != neighbor->initiate_task) { GNUNET_SCHEDULER_cancel (neighbor->initiate_task); neighbor->initiate_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Function that is called with QoS information about an address; used * to update our current distance to another peer. * * @param cls closure * @param address the address * @param active is this address in active use * @param bandwidth_out assigned outbound bandwidth for the connection * @param bandwidth_in assigned inbound bandwidth for the connection * @param ats performance data for the address (as far as known) * @param ats_count number of performance records in @a ats */ static void handle_ats_update (void *cls, const struct GNUNET_HELLO_Address *address, int active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct DirectNeighbor *neighbor; uint32_t distance; enum GNUNET_ATS_Network_Type network = GNUNET_ATS_NET_UNSPECIFIED; if (GNUNET_NO == active) return; distance = get_atsi_distance (ats, ats_count); network = get_atsi_network (ats, ats_count); GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != network); /* check if entry exists */ neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, &address->peer); if (NULL != neighbor) { neighbor->network = network; if (neighbor->distance == distance) return; /* nothing new to see here, move along */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS says distance to %s is now %u\n", GNUNET_i2s (&address->peer), (unsigned int) distance); if ( (DIRECT_NEIGHBOR_COST == neighbor->distance) && (DIRECT_NEIGHBOR_COST == distance) ) return; /* no change */ if (DIRECT_NEIGHBOR_COST == neighbor->distance) { neighbor->distance = distance; GNUNET_STATISTICS_update (stats, "# peers connected (1-hop)", -1, GNUNET_NO); handle_direct_disconnect (neighbor); schedule_refresh_routes (); return; } neighbor->distance = distance; if (DIRECT_NEIGHBOR_COST != neighbor->distance) return; if (GNUNET_YES != neighbor->connected) return; handle_direct_connect (neighbor); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ATS says distance to %s is now %u\n", GNUNET_i2s (&address->peer), (unsigned int) distance); neighbor = GNUNET_new (struct DirectNeighbor); neighbor->peer = address->peer; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (direct_neighbors, &address->peer, neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); neighbor->connected = GNUNET_NO; /* not yet */ neighbor->distance = distance; neighbor->network = network; } /** * Check if a target was removed from the set of the other peer; if so, * if we also used it for our route, we need to remove it from our * 'all_routes' set (and later check if an alternative path now exists). * * @param cls the `struct DirectNeighbor` * @param key peer identity for the target * @param value a `struct Target` previously reachable via the given neighbor */ static int check_target_removed (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct DirectNeighbor *neighbor = cls; struct Target *new_target; struct Route *current_route; new_target = GNUNET_CONTAINER_multipeermap_get (neighbor->neighbor_table_consensus, key); current_route = GNUNET_CONTAINER_multipeermap_get (all_routes, key); if (NULL != new_target) { /* target was in old set, is in new set */ if ( (NULL != current_route) && (current_route->next_hop == neighbor) && (current_route->target.distance != new_target->distance) ) { /* need to recalculate routes due to distance change */ neighbor->target_removed = GNUNET_YES; } return GNUNET_OK; } /* target was revoked, check if it was used */ if ( (NULL == current_route) || (current_route->next_hop != neighbor) ) { /* didn't matter, wasn't used */ return GNUNET_OK; } /* remove existing route */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Lost route to %s\n", GNUNET_i2s (¤t_route->target.peer)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (all_routes, key, current_route)); send_disconnect_to_plugin (¤t_route->target.peer); release_route (current_route); GNUNET_free (current_route); neighbor->target_removed = GNUNET_YES; return GNUNET_OK; } /** * Check if a target was added to the set of the other peer; if it * was added or impoves the existing route, do the needed updates. * * @param cls the `struct DirectNeighbor` * @param key peer identity for the target * @param value a `struct Target` now reachable via the given neighbor */ static int check_target_added (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct DirectNeighbor *neighbor = cls; struct Target *target = value; struct Route *current_route; /* target was revoked, check if it was used */ current_route = GNUNET_CONTAINER_multipeermap_get (all_routes, key); if (NULL != current_route) { /* route exists */ if (current_route->next_hop == neighbor) { /* we had the same route before, no change in target */ if (ntohl (target->distance) + 1 != ntohl (current_route->target.distance)) { /* but distance changed! */ if (ntohl (target->distance) + 1 > DEFAULT_FISHEYE_DEPTH) { /* distance increased beyond what is allowed, kill route */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (all_routes, key, current_route)); send_disconnect_to_plugin (key); release_route (current_route); GNUNET_free (current_route); } else { /* distance decreased, update route */ move_route (current_route, ntohl (target->distance) + 1); send_distance_change_to_plugin (&target->peer, ntohl (target->distance) + 1, neighbor->network); } } return GNUNET_OK; } if (ntohl (current_route->target.distance) <= ntohl (target->distance) + 1) { /* alternative, shorter route exists, ignore */ return GNUNET_OK; } /* new route is better than the existing one, take over! */ /* NOTE: minor security issue: malicious peers may advertise very short routes to take over longer paths; as we don't check that the shorter routes actually work, a malicious direct neighbor can use this to DoS our long routes */ move_route (current_route, ntohl (target->distance) + 1); current_route->next_hop = neighbor; send_distance_change_to_plugin (&target->peer, ntohl (target->distance) + 1, neighbor->network); return GNUNET_OK; } /* new route */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Discovered new route to %s using %u hops\n", GNUNET_i2s (&target->peer), (unsigned int) (ntohl (target->distance) + 1)); current_route = GNUNET_new (struct Route); current_route->next_hop = neighbor; current_route->target.peer = target->peer; allocate_route (current_route, ntohl (target->distance) + 1); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (all_routes, ¤t_route->target.peer, current_route, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); send_connect_to_plugin (¤t_route->target.peer, ntohl (current_route->target.distance), neighbor->network); return GNUNET_OK; } /** * Callback for set operation results. Called for each element * in the result set. * We have learned a new route from the other peer. Add it to the * route set we're building. * * @param cls the `struct DirectNeighbor` we're building the consensus with * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK * @param status see `enum GNUNET_SET_Status` */ static void handle_set_union_result (void *cls, const struct GNUNET_SET_Element *element, enum GNUNET_SET_Status status) { struct DirectNeighbor *neighbor = cls; struct DirectNeighbor *dn; struct Target *target; char *status_str; switch (status) { case GNUNET_SET_STATUS_OK: status_str = "GNUNET_SET_STATUS_OK"; break; case GNUNET_SET_STATUS_TIMEOUT: status_str = "GNUNET_SET_STATUS_TIMEOUT"; break; case GNUNET_SET_STATUS_FAILURE: status_str = "GNUNET_SET_STATUS_FAILURE"; break; case GNUNET_SET_STATUS_HALF_DONE: status_str = "GNUNET_SET_STATUS_HALF_DONE"; break; case GNUNET_SET_STATUS_DONE: status_str = "GNUNET_SET_STATUS_DONE"; break; default: status_str = "UNDEFINED"; break; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got SET union result: %s\n", status_str); switch (status) { case GNUNET_SET_STATUS_OK: if (sizeof (struct Target) != element->size) { GNUNET_break_op (0); return; } if ( (NULL != (dn = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, &((struct Target *) element->data)->peer))) && (DIRECT_NEIGHBOR_COST == dn->distance) ) { /* this is a direct neighbor of ours, we do not care about routes to this peer */ return; } target = GNUNET_new (struct Target); memcpy (target, element->data, sizeof (struct Target)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received information about peer `%s' with distance %u from SET\n", GNUNET_i2s (&target->peer), ntohl (target->distance) + 1); if (NULL == neighbor->neighbor_table_consensus) neighbor->neighbor_table_consensus = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_put (neighbor->neighbor_table_consensus, &target->peer, target, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { GNUNET_break_op (0); GNUNET_free (target); } break; case GNUNET_SET_STATUS_TIMEOUT: case GNUNET_SET_STATUS_FAILURE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to establish DV union, will try again later\n"); neighbor->set_op = NULL; if (NULL != neighbor->neighbor_table_consensus) { GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, &free_targets, NULL); GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table_consensus); neighbor->neighbor_table_consensus = NULL; } if (0 < memcmp (&neighbor->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity))) neighbor->initiate_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, &initiate_set_union, neighbor); break; case GNUNET_SET_STATUS_HALF_DONE: break; case GNUNET_SET_STATUS_DONE: /* we got all of our updates; integrate routing table! */ neighbor->target_removed = GNUNET_NO; if (NULL == neighbor->neighbor_table_consensus) neighbor->neighbor_table_consensus = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); if (NULL != neighbor->neighbor_table) GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, &check_target_removed, neighbor); if (GNUNET_YES == neighbor->target_removed) { /* check if we got an alternative for the removed routes */ schedule_refresh_routes (); } /* add targets that appeared (and check for improved routes) */ GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, &check_target_added, neighbor); if (NULL != neighbor->neighbor_table) { GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, &free_targets, NULL); GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table); neighbor->neighbor_table = NULL; } neighbor->neighbor_table = neighbor->neighbor_table_consensus; neighbor->neighbor_table_consensus = NULL; /* operation done, schedule next run! */ neighbor->set_op = NULL; if (0 < memcmp (&neighbor->peer, &my_identity, sizeof (struct GNUNET_PeerIdentity))) neighbor->initiate_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, &initiate_set_union, neighbor); break; default: GNUNET_break (0); return; } } /** * Start creating a new DV set union construction, our neighbour has * asked for it (callback for listening peer). * * @param cls the 'struct DirectNeighbor' of the peer we're building * a routing consensus with * @param other_peer the other peer * @param context_msg message with application specific information from * the other peer * @param request request from the other peer, use GNUNET_SET_accept * to accept it, otherwise the request will be refused * Note that we don't use a return value here, as it is also * necessary to specify the set we want to do the operation with, * whith sometimes can be derived from the context message. * Also necessary to specify the timeout. */ static void listen_set_union (void *cls, const struct GNUNET_PeerIdentity *other_peer, const struct GNUNET_MessageHeader *context_msg, struct GNUNET_SET_Request *request) { struct DirectNeighbor *neighbor = cls; if (NULL == request) return; /* why??? */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to create consensus with %s\n", GNUNET_i2s (&neighbor->peer)); if (NULL != neighbor->set_op) { GNUNET_SET_operation_cancel (neighbor->set_op); neighbor->set_op = NULL; } if (NULL != neighbor->my_set) { GNUNET_SET_destroy (neighbor->my_set); neighbor->my_set = NULL; } neighbor->my_set = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); neighbor->set_op = GNUNET_SET_accept (request, GNUNET_SET_RESULT_ADDED, &handle_set_union_result, neighbor); neighbor->consensus_insertion_offset = 0; neighbor->consensus_insertion_distance = 0; neighbor->consensus_elements = 0; build_set (neighbor); } /** * Start creating a new DV set union by initiating the connection. * * @param cls the `struct DirectNeighbor *` of the peer we're building * a routing consensus with * @param tc scheduler context */ static void initiate_set_union (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { static uint16_t salt; struct DirectNeighbor *neighbor = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initiating SET union with peer `%s'\n", GNUNET_i2s (&neighbor->peer)); neighbor->initiate_task = GNUNET_SCHEDULER_NO_TASK; neighbor->my_set = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); neighbor->set_op = GNUNET_SET_prepare (&neighbor->peer, &neighbor->real_session_id, NULL, salt++, GNUNET_SET_RESULT_ADDED, &handle_set_union_result, neighbor); neighbor->consensus_insertion_offset = 0; neighbor->consensus_insertion_distance = 0; neighbor->consensus_elements = 0; build_set (neighbor); } /** * Core handler for DV data messages. Whatever this message * contains all we really have to do is rip it out of its * DV layering and give it to our pal the DV plugin to report * in with. * * @param cls closure * @param peer peer which sent the message (immediate sender) * @param message the message * @return #GNUNET_OK on success, #GNUNET_SYSERR if the other peer violated the protocol */ static int handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { const struct RouteMessage *rm; const struct GNUNET_MessageHeader *payload; struct Route *route; struct DirectNeighbor *neighbor; struct DirectNeighbor *dn; struct Target *target; uint32_t distance; char me[5]; char src[5]; char prev[5]; char dst[5]; if (ntohs (message->size) < sizeof (struct RouteMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return GNUNET_SYSERR; } rm = (const struct RouteMessage *) message; distance = ntohl (rm->distance); payload = (const struct GNUNET_MessageHeader *) &rm[1]; if (ntohs (message->size) != sizeof (struct RouteMessage) + ntohs (payload->size)) { GNUNET_break_op (0); return GNUNET_SYSERR; } strncpy (prev, GNUNET_i2s (peer), 4); strncpy (me, GNUNET_i2s (&my_identity), 4); strncpy (src, GNUNET_i2s (&rm->sender), 4); strncpy (dst, GNUNET_i2s (&rm->target), 4); prev[4] = me[4] = src[4] = dst[4] = '\0'; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handling DV message with %u bytes payload of type %u from %s to %s routed by %s to me (%s @ hop %u)\n", ntohs (message->size) - sizeof (struct RouteMessage), ntohs (payload->type), src, dst, prev, me, (unsigned int) distance + 1); if (0 == memcmp (&rm->target, &my_identity, sizeof (struct GNUNET_PeerIdentity))) { if ((NULL != (dn = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, &rm->sender))) && (DIRECT_NEIGHBOR_COST == dn->distance)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Discarding DV message, as %s is a direct neighbor\n", GNUNET_i2s (&rm->sender)); GNUNET_STATISTICS_update (stats, "# messages discarded (direct neighbor)", 1, GNUNET_NO); return GNUNET_OK; } /* message is for me, check reverse route! */ route = GNUNET_CONTAINER_multipeermap_get (all_routes, &rm->sender); if ( (NULL == route) && (distance < DEFAULT_FISHEYE_DEPTH) ) { /* don't have reverse route yet, learn it! */ neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, peer); if (NULL == neighbor) { GNUNET_break (0); return GNUNET_SYSERR; } target = GNUNET_new (struct Target); target->peer = rm->sender; target->distance = htonl (distance); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Learning sender %s at distance %u from delivery!\n", GNUNET_i2s (&rm->sender), (unsigned int) distance + 1); if (NULL == neighbor->neighbor_table) neighbor->neighbor_table = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_put (neighbor->neighbor_table, &target->peer, target, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { GNUNET_break_op (0); GNUNET_free (target); return GNUNET_SYSERR; } add_new_route (target, neighbor); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering %u bytes from %s to myself!\n", ntohs (payload->size), GNUNET_i2s (&rm->sender)); send_data_to_plugin (payload, &rm->sender, 1 + distance); return GNUNET_OK; } if ( (NULL == GNUNET_CONTAINER_multipeermap_get (direct_neighbors, &rm->sender)) && (NULL == GNUNET_CONTAINER_multipeermap_get (all_routes, &rm->sender)) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Learning sender %s at distance %u from forwarding!\n", GNUNET_i2s (&rm->sender), 1 + distance); neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, peer); if (NULL == neighbor) { GNUNET_break (0); return GNUNET_SYSERR; } target = GNUNET_new (struct Target); target->peer = rm->sender; target->distance = htonl (distance); if (NULL == neighbor->neighbor_table) neighbor->neighbor_table = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_put (neighbor->neighbor_table, &target->peer, target, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { GNUNET_break_op (0); GNUNET_free (target); } add_new_route (target, neighbor); } route = GNUNET_CONTAINER_multipeermap_get (all_routes, &rm->target); if (NULL == route) { neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, &rm->target); if (NULL == neighbor) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No route to %s, not routing %u bytes!\n", GNUNET_i2s (&rm->target), ntohs (payload->size)); GNUNET_STATISTICS_update (stats, "# messages discarded (no route)", 1, GNUNET_NO); return GNUNET_OK; } } else { neighbor = route->next_hop; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarding message to %s\n", GNUNET_i2s (&neighbor->peer)); forward_payload (neighbor, distance + 1, 0, &rm->sender, &rm->target, payload); return GNUNET_OK; } /** * Service server's handler for message send requests (which come * bubbling up to us through the DV plugin). * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_dv_send_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct Route *route; const struct GNUNET_DV_SendMessage *msg; const struct GNUNET_MessageHeader *payload; if (ntohs (message->size) < sizeof (struct GNUNET_DV_SendMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg = (const struct GNUNET_DV_SendMessage *) message; GNUNET_break (0 != ntohl (msg->uid)); payload = (const struct GNUNET_MessageHeader *) &msg[1]; if (ntohs (message->size) != sizeof (struct GNUNET_DV_SendMessage) + ntohs (payload->size)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } route = GNUNET_CONTAINER_multipeermap_get (all_routes, &msg->target); if (NULL == route) { /* got disconnected */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No route to %s, dropping local message of type %u\n", GNUNET_i2s (&msg->target), ntohs (payload->type)); GNUNET_STATISTICS_update (stats, "# local messages discarded (no route)", 1, GNUNET_NO); send_ack_to_plugin (&msg->target, ntohl (msg->uid), GNUNET_YES); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarding %u bytes of type %u to %s\n", ntohs (payload->size), ntohs (payload->type), GNUNET_i2s (&msg->target)); forward_payload (route->next_hop, 0 /* first hop, distance is zero */, htonl (msg->uid), &my_identity, &msg->target, payload); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Cleanup all of the data structures associated with a given neighbor. * * @param neighbor neighbor to clean up */ static void cleanup_neighbor (struct DirectNeighbor *neighbor) { struct PendingMessage *pending; while (NULL != (pending = neighbor->pm_head)) { neighbor->pm_queue_size--; GNUNET_CONTAINER_DLL_remove (neighbor->pm_head, neighbor->pm_tail, pending); GNUNET_free (pending); } handle_direct_disconnect (neighbor); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (direct_neighbors, &neighbor->peer, neighbor)); GNUNET_free (neighbor); } /** * Method called whenever a given peer disconnects. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct DirectNeighbor *neighbor; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received core peer disconnect message for peer `%s'!\n", GNUNET_i2s (peer)); /* Check for disconnect from self message */ if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity))) return; neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, peer); if (NULL == neighbor) { GNUNET_break (0); return; } GNUNET_break (GNUNET_YES == neighbor->connected); neighbor->connected = GNUNET_NO; if (DIRECT_NEIGHBOR_COST == neighbor->distance) { GNUNET_STATISTICS_update (stats, "# peers connected (1-hop)", -1, GNUNET_NO); } cleanup_neighbor (neighbor); if (GNUNET_YES == in_shutdown) return; schedule_refresh_routes (); } /** * Multipeermap iterator for freeing routes. Should never be called. * * @param cls NULL * @param key key value stored under * @param value the route to be freed * @return #GNUNET_YES to continue iteration, #GNUNET_NO to stop */ static int free_route (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct Route *route = value; GNUNET_break (0); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (all_routes, key, value)); release_route (route); send_disconnect_to_plugin (&route->target.peer); GNUNET_free (route); return GNUNET_YES; } /** * Multipeermap iterator for freeing direct neighbors. Should never be called. * * @param cls NULL * @param key key value stored under * @param value the direct neighbor to be freed * @return #GNUNET_YES to continue iteration, #GNUNET_NO to stop */ static int free_direct_neighbors (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct DirectNeighbor *neighbor = value; cleanup_neighbor (neighbor); return GNUNET_YES; } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int i; in_shutdown = GNUNET_YES; GNUNET_assert (NULL != core_api); GNUNET_CORE_disconnect (core_api); core_api = NULL; GNUNET_ATS_performance_done (ats); ats = NULL; GNUNET_CONTAINER_multipeermap_iterate (direct_neighbors, &free_direct_neighbors, NULL); GNUNET_CONTAINER_multipeermap_iterate (all_routes, &free_route, NULL); GNUNET_CONTAINER_multipeermap_destroy (direct_neighbors); GNUNET_CONTAINER_multipeermap_destroy (all_routes); GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; for (i=0;itarget.distance); cm.peer = route->target.peer; GNUNET_SERVER_notification_context_unicast (nc, client, &cm.header, GNUNET_NO); return GNUNET_OK; } /** * Handle START-message. This is the first message sent to us * by the client (can only be one!). * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message */ static void handle_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_CONTAINER_multipeermap_iterate (all_routes, ¬ify_client_about_route, client); } /** * Called on core init. * * @param cls unused * @param identity this peer's identity */ static void core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am peer: %s\n", GNUNET_i2s (identity)); my_identity = *identity; } /** * Process dv requests. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static struct GNUNET_CORE_MessageHandler core_handlers[] = { {&handle_dv_route_message, GNUNET_MESSAGE_TYPE_DV_ROUTE, 0}, {NULL, 0, 0} }; static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = { {&handle_start, NULL, GNUNET_MESSAGE_TYPE_DV_START, sizeof (struct GNUNET_MessageHeader) }, { &handle_dv_send_message, NULL, GNUNET_MESSAGE_TYPE_DV_SEND, 0}, {NULL, NULL, 0, 0} }; in_shutdown = GNUNET_NO; cfg = c; direct_neighbors = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); all_routes = GNUNET_CONTAINER_multipeermap_create (65536, GNUNET_NO); core_api = GNUNET_CORE_connect (cfg, NULL, &core_init, &handle_core_connect, &handle_core_disconnect, NULL, GNUNET_NO, NULL, GNUNET_NO, core_handlers); if (NULL == core_api) return; ats = GNUNET_ATS_performance_init (cfg, &handle_ats_update, NULL); if (NULL == ats) { GNUNET_CORE_disconnect (core_api); core_api = NULL; return; } nc = GNUNET_SERVER_notification_context_create (server, MAX_QUEUE_SIZE_PLUGIN); stats = GNUNET_STATISTICS_create ("dv", cfg); GNUNET_SERVER_add_handlers (server, plugin_handlers); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for the dv service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "dv", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-dv.c */ gnunet-0.10.1/src/dv/test_transport_blacklist_data.conf0000644000175000017500000000010212225230043020157 00000000000000@INLINE@ template_dv.conf [transport] PORT = 2565 PLUGINS = tcp gnunet-0.10.1/src/ats-tool/0000755000175000017500000000000012320755625012432 500000000000000gnunet-0.10.1/src/ats-tool/Makefile.in0000644000175000017500000005365312320752060014421 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-ats$(EXEEXT) subdir = src/ats-tool DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_gnunet_ats_OBJECTS = gnunet-ats.$(OBJEXT) gnunet_ats_OBJECTS = $(am_gnunet_ats_OBJECTS) am__DEPENDENCIES_1 = gnunet_ats_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(gnunet_ats_SOURCES) DIST_SOURCES = $(gnunet_ats_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage gnunet_ats_SOURCES = \ gnunet-ats.c gnunet_ats_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(GN_LIBINTL) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ats-tool/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/ats-tool/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-ats$(EXEEXT): $(gnunet_ats_OBJECTS) $(gnunet_ats_DEPENDENCIES) $(EXTRA_gnunet_ats_DEPENDENCIES) @rm -f gnunet-ats$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_ats_OBJECTS) $(gnunet_ats_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-ats.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/ats-tool/gnunet-ats.c0000644000175000017500000004160512320724370014602 00000000000000/* This file is part of GNUnet. (C) 2009--2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tool/gnunet-ats.c * @brief ATS command line tool * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_ats_service.h" #include "gnunet_transport_service.h" #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5) #define BIG_M_STRING "unlimited" /** * Final status code. */ static int ret; static int results; static int resolve_addresses_numeric; static int receive_done; /** * For which peer should we change preference values? */ static char *pid_str; static char *type_str; static unsigned int value; static int pending; /** * Print verbose ATS information */ static int verbose; /** * List only addresses currently used (active) */ static int op_list_used; /** * List all addresses */ static int op_list_all; /** * List all addresses */ static int op_set_pref; /** * Print quotas configured */ static int op_print_quotas; /** * Monitor addresses used */ static int op_monitor; static struct GNUNET_ATS_PerformanceHandle *ph; static struct GNUNET_ATS_AddressListHandle *alh; static struct GNUNET_CONFIGURATION_Handle *cfg; static GNUNET_SCHEDULER_TaskIdentifier end_task; static struct GNUNET_CONTAINER_MultiPeerMap *addresses; struct PendingResolutions { struct PendingResolutions *next; struct PendingResolutions *prev; struct GNUNET_HELLO_Address *address; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; struct GNUNET_ATS_Information *ats; uint32_t ats_count; struct GNUNET_TRANSPORT_AddressToStringContext * tats_ctx; }; struct ATSAddress { struct GNUNET_HELLO_Address *address; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out; struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in; }; static struct PendingResolutions *head; static struct PendingResolutions *tail; static int free_addr_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct ATSAddress *a = value; GNUNET_break (GNUNET_OK != GNUNET_CONTAINER_multipeermap_remove (addresses, key, a)); GNUNET_HELLO_address_free (a->address); GNUNET_free (a); return GNUNET_OK; } static void end(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PendingResolutions * pr; struct PendingResolutions * next; unsigned int pending; if (NULL != alh) { GNUNET_ATS_performance_list_addresses_cancel (alh); alh = NULL; } if (NULL != ph) { GNUNET_ATS_performance_done (ph); ph = NULL; } pending = 0; next = head; while (NULL != (pr = next)) { next = pr->next; GNUNET_CONTAINER_DLL_remove(head, tail, pr); GNUNET_TRANSPORT_address_to_string_cancel (pr->tats_ctx); GNUNET_free(pr->address); GNUNET_free(pr); pending++; } GNUNET_CONTAINER_multipeermap_iterate(addresses, &free_addr_it, NULL); GNUNET_CONTAINER_multipeermap_destroy(addresses); if (0 < pending) fprintf (stderr, _("%u address resolutions had a timeout\n"), pending); if (op_list_used || op_list_all) fprintf (stderr, _("ATS returned results for %u addresses\n"), results); ret = 0; } static void transport_addr_to_str_cb(void *cls, const char *address) { struct PendingResolutions * pr = cls; char *ats_str; char *ats_tmp; char *ats_prop_arr[GNUNET_ATS_PropertyCount] = GNUNET_ATS_PropertyStrings; char *ats_prop_value; unsigned int c; uint32_t ats_type; uint32_t ats_value; uint32_t network; if (NULL != address) { ats_str = GNUNET_strdup(""); network = GNUNET_ATS_NET_UNSPECIFIED; for (c = 0; c < pr->ats_count; c++) { ats_tmp = ats_str; ats_type = ntohl (pr->ats[c].type); ats_value = ntohl (pr->ats[c].value); if (ats_type > GNUNET_ATS_PropertyCount) { fprintf (stderr, "Invalid ATS property type %u %u for address %s\n", ats_type, pr->ats[c].type, address); continue; } switch (ats_type) { case GNUNET_ATS_NETWORK_TYPE: if (ats_value > GNUNET_ATS_NetworkTypeCount) { GNUNET_break(0); continue; } network = ats_value; GNUNET_asprintf (&ats_prop_value, "%s", GNUNET_ATS_print_network_type (ats_value)); break; default: GNUNET_asprintf (&ats_prop_value, "%u", ats_value); break; } if ((verbose) && (ats_type < GNUNET_ATS_PropertyCount)) { GNUNET_asprintf (&ats_str, "%s%s=%s, ", ats_tmp, ats_prop_arr[ats_type], ats_prop_value); GNUNET_free(ats_tmp); } GNUNET_free(ats_prop_value); } fprintf (stderr, _("Peer `%s' plugin `%s', address `%s', `%s' bw out: %u Bytes/s, bw in %u Bytes/s, %s\n"), GNUNET_i2s (&pr->address->peer), pr->address->transport_name, address, GNUNET_ATS_print_network_type (network), ntohl (pr->bandwidth_out.value__), ntohl (pr->bandwidth_in.value__), ats_str); GNUNET_free(ats_str); } else { /* We're done */ GNUNET_CONTAINER_DLL_remove(head, tail, pr); GNUNET_free(pr->address); GNUNET_free(pr); pending--; if ((GNUNET_YES == receive_done) && (0 == pending)) { /* All messages received and no resolutions pending*/ if (end_task != GNUNET_SCHEDULER_NO_TASK ) GNUNET_SCHEDULER_cancel (end_task); end_task = GNUNET_SCHEDULER_add_now (end, NULL ); } } } struct AddressFindCtx { const struct GNUNET_HELLO_Address *src; struct ATSAddress *res; }; static int find_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct AddressFindCtx *actx = cls; struct ATSAddress *exist = value; if (0 == GNUNET_HELLO_address_cmp (actx->src, exist->address)) { actx->res = exist; return GNUNET_NO; } return GNUNET_YES; } static void ats_perf_cb(void *cls, const struct GNUNET_HELLO_Address *address, int active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct PendingResolutions * pr; if ((GNUNET_YES == op_monitor) && (GNUNET_NO == verbose)) { struct AddressFindCtx actx; actx.src = address; actx.res = NULL; GNUNET_CONTAINER_multipeermap_iterate (addresses, find_address_it, &actx); if ((actx.res != NULL)) { if ((bandwidth_in.value__ == actx.res->bandwidth_in.value__) && (bandwidth_out.value__ == actx.res->bandwidth_out.value__) ) { return; /* Nothing to do here */ } else { actx.res->bandwidth_in = bandwidth_in; actx.res->bandwidth_out = bandwidth_out; } } struct ATSAddress *a = GNUNET_new (struct ATSAddress); a->address = GNUNET_HELLO_address_copy(address); a->bandwidth_in = bandwidth_in; a->bandwidth_out = bandwidth_out; GNUNET_CONTAINER_multipeermap_put (addresses, &address->peer, a, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } if (NULL != address) { pr = GNUNET_malloc (sizeof (struct PendingResolutions) + ats_count * sizeof (struct GNUNET_ATS_Information)); pr->ats_count = ats_count; pr->ats = (struct GNUNET_ATS_Information *) &pr[1]; if (ats_count > 0) memcpy (pr->ats, ats, ats_count * sizeof(struct GNUNET_ATS_Information)); pr->address = GNUNET_HELLO_address_copy (address); pr->bandwidth_in = bandwidth_in; pr->bandwidth_out = bandwidth_out; pr->tats_ctx = GNUNET_TRANSPORT_address_to_string (cfg, address, resolve_addresses_numeric, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), transport_addr_to_str_cb, pr); GNUNET_CONTAINER_DLL_insert(head, tail, pr); results++; pending++; } else { /* All messages received */ receive_done = GNUNET_YES; alh = NULL; if (0 == pending) { /* All messages received and no resolutions pending*/ if (end_task != GNUNET_SCHEDULER_NO_TASK ) GNUNET_SCHEDULER_cancel (end_task); end_task = GNUNET_SCHEDULER_add_now (end, NULL ); } } } static unsigned int print_quotas(const struct GNUNET_CONFIGURATION_Handle *cfg) { char *network_str[GNUNET_ATS_NetworkTypeCount] = GNUNET_ATS_NetworkTypeString; char * entry_in = NULL; char * entry_out = NULL; char * quota_out_str; char * quota_in_str; unsigned long long int quota_out; unsigned long long int quota_in; int c; for (c = 0; (c < GNUNET_ATS_NetworkTypeCount); c++) { GNUNET_asprintf (&entry_out, "%s_QUOTA_OUT", network_str[c]); GNUNET_asprintf (&entry_in, "%s_QUOTA_IN", network_str[c]); /* quota out */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ats", entry_out, "a_out_str)) { if (0 == strcmp (quota_out_str, BIG_M_STRING) || (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_out_str, "a_out))) quota_out = UINT32_MAX; GNUNET_free(quota_out_str); GNUNET_asprintf ("a_out_str, "%llu", quota_out); } else { fprintf (stderr, "Outbound quota for network `%11s' not configured!\n", network_str[c]); GNUNET_asprintf ("a_out_str, "-"); } GNUNET_free(entry_out); /* quota in */ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "ats", entry_in, "a_in_str)) { if (0 == strcmp (quota_in_str, BIG_M_STRING) || (GNUNET_SYSERR == GNUNET_STRINGS_fancy_size_to_bytes (quota_in_str, "a_in))) quota_in = UINT32_MAX; GNUNET_free(quota_in_str); GNUNET_asprintf ("a_in_str, "%llu", quota_in); } else { fprintf (stderr, "Inbound quota for network `%11s' not configured!\n", network_str[c]); GNUNET_asprintf ("a_in_str, "-"); } GNUNET_free(entry_in); fprintf (stderr, _("Quota for network `%11s' (in/out): %10s / %10s\n"), network_str[c], quota_in_str, quota_out_str); GNUNET_free(quota_out_str); GNUNET_free(quota_in_str); } return GNUNET_ATS_NetworkTypeCount; } static void testservice_ats(void *cls, int result) { struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_PeerIdentity pid; unsigned int c; unsigned int type; addresses = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_YES); if (GNUNET_YES != result) { FPRINTF (stderr, _("Service `%s' is not running\n"), "ats"); return; } results = 0; if (NULL != pid_str) { if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (pid_str, strlen (pid_str), &pid.public_key)) { FPRINTF (stderr, _("Failed to parse peer identity `%s'\n"), pid_str); return; } } c = op_list_all + op_list_used + op_monitor + op_set_pref; if ((1 < c)) { FPRINTF (stderr, _("Please select one operation : %s or %s or %s or %s or %s\n"), "--used", "--all", "--monitor", "--preference", "--quotas"); return; } if ((0 == c)) op_list_used = GNUNET_YES; /* set default */ if (op_print_quotas) { ret = print_quotas (cfg); return; } if (op_list_all) { ph = GNUNET_ATS_performance_init (cfg, NULL, NULL ); if (NULL == ph) { fprintf (stderr, _("Cannot connect to ATS service, exiting...\n") ); return; } alh = GNUNET_ATS_performance_list_addresses (ph, (NULL == pid_str) ? NULL : &pid, GNUNET_YES, ats_perf_cb, NULL ); if (NULL == alh) { fprintf (stderr, _("Cannot issue request to ATS service, exiting...\n") ); end_task = GNUNET_SCHEDULER_add_now (&end, NULL ); return; } end_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &end, NULL ); } else if (op_list_used) { ph = GNUNET_ATS_performance_init (cfg, NULL, NULL ); if (NULL == ph) fprintf (stderr, _("Cannot connect to ATS service, exiting...\n") ); alh = GNUNET_ATS_performance_list_addresses (ph, (NULL == pid_str) ? NULL : &pid, GNUNET_NO, ats_perf_cb, NULL ); if (NULL == alh) { fprintf (stderr, _("Cannot issue request to ATS service, exiting...\n") ); end_task = GNUNET_SCHEDULER_add_now (&end, NULL ); return; } end_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &end, NULL ); } else if (op_monitor) { ph = GNUNET_ATS_performance_init (cfg, &ats_perf_cb, NULL ); if (NULL == ph) fprintf (stderr, _("Cannot connect to ATS service, exiting...\n") ); end_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &end, NULL ); } else if (op_set_pref) { if (NULL == type_str) { fprintf (stderr, _("No preference type given!\n") ); return; } if (NULL == pid_str) { fprintf (stderr, _("No peer given!\n") ); return; } for (c = 0; c < strlen (type_str); c++) { if (isupper (type_str[c])) type_str[c] = tolower (type_str[c]); } if (0 == strcasecmp ("latency", type_str)) type = GNUNET_ATS_PREFERENCE_LATENCY; else if (0 == strcasecmp ("bandwidth", type_str)) type = GNUNET_ATS_PREFERENCE_BANDWIDTH; else { FPRINTF (stderr, "%s", _("Valid type required\n") ); return; } /* set */ ph = GNUNET_ATS_performance_init (cfg, NULL, NULL ); if (NULL == ph) fprintf (stderr, _("Cannot connect to ATS service, exiting...\n") ); GNUNET_ATS_performance_change_preference (ph, &pid, type, (double) value, GNUNET_ATS_PREFERENCE_END); end_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &end, NULL ); } ret = 1; } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param my_cfg configuration */ static void run(void *cls, char * const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *my_cfg) { cfg = (struct GNUNET_CONFIGURATION_Handle *) my_cfg; GNUNET_CLIENT_service_test ("ats", cfg, TIMEOUT, &testservice_ats, (void *) cfg); } /** * The main function. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main(int argc, char * const *argv) { int res; resolve_addresses_numeric = GNUNET_NO; op_monitor = GNUNET_NO; op_list_all = GNUNET_NO; op_list_used = GNUNET_NO; op_set_pref = GNUNET_NO; pending = 0; receive_done = GNUNET_NO; type_str = NULL; static const struct GNUNET_GETOPT_CommandLineOption options[] = { { 'u', "used", NULL, gettext_noop ("get list of active addresses currently used"), 0, &GNUNET_GETOPT_set_one, &op_list_used }, { 'a', "all", NULL, gettext_noop ("get list of all active addresses"), 0, &GNUNET_GETOPT_set_one, &op_list_all }, { 'n', "numeric", NULL, gettext_noop ("do not resolve IP addresses to hostnames"), 0, &GNUNET_GETOPT_set_one, &resolve_addresses_numeric }, { 'm', "monitor", NULL, gettext_noop ("monitor mode"), 0, &GNUNET_GETOPT_set_one, &op_monitor }, { 'p', "preference", NULL, gettext_noop ("set preference for the given peer"), 0, &GNUNET_GETOPT_set_one, &op_set_pref }, { 'q', "quotas", NULL, gettext_noop ("print all configured quotas"), 0, &GNUNET_GETOPT_set_one, &op_print_quotas }, { 'i', "id", "TYPE", gettext_noop ("peer id"), 1, &GNUNET_GETOPT_set_string, &pid_str }, { 't', "type", "TYPE", gettext_noop ("preference type to set: latency | bandwidth"), 1, &GNUNET_GETOPT_set_string, &type_str }, { 'k', "value", "VALUE", gettext_noop ("preference value"), 1, &GNUNET_GETOPT_set_uint, &value }, { 'V', "verbose", NULL, gettext_noop ("verbose output (include ATS address properties)"), 0, &GNUNET_GETOPT_set_one, &verbose }, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; res = GNUNET_PROGRAM_run (argc, argv, "gnunet-ats", gettext_noop ("Print information about ATS state"), options, &run, NULL ); GNUNET_free_non_null(pid_str); GNUNET_free_non_null(type_str); GNUNET_free((void * ) argv); if (GNUNET_OK == res) return ret; else return 1; } /* end of gnunet-ats.c */ gnunet-0.10.1/src/ats-tool/Makefile.am0000644000175000017500000000074612320751517014411 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif bin_PROGRAMS = \ gnunet-ats gnunet_ats_SOURCES = \ gnunet-ats.c gnunet_ats_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/hello/libgnunethello.la \ $(GN_LIBINTL) gnunet-0.10.1/src/scalarproduct/0000755000175000017500000000000012320755627013540 500000000000000gnunet-0.10.1/src/scalarproduct/test_scalarproduct.sh0000755000175000017500000000226412254263402017717 00000000000000#!/bin/bash # compute a simple scalar product # payload for this test: INPUTALICE="-k CCC -e 3,3,-1" INPUTBOB="-k CCC -e 1000,100,24" # necessary to make the testing prefix deterministic, so we can access the config files PREFIX=/tmp/test-scalarproduct`date +%H%M%S` # where can we find the peers config files? CFGALICE="-c $PREFIX/0/config" CFGBOB="-c $PREFIX/1/config" # launch two peers in line topology non-interactively # # interactive mode would terminate the test immediately # because the rest of the script is already in stdin, # thus redirecting stdin does not suffice) #GNUNET_LOG='scalarproduct;;;;DEBUG' GNUNET_TESTING_PREFIX=$PREFIX ../testbed/gnunet-testbed-profiler -n -c test_scalarproduct.conf -p 2 & PID=$! # sleep 1 is too short on most systems, 2 works on most, 5 seems to be safe sleep 5 # get bob's peer ID, necessary for alice PEERIDBOB=`gnunet-peerinfo -qs $CFGBOB` #GNUNET_LOG=';;;;DEBUG' gnunet-scalarproduct $CFGBOB $INPUTBOB & GNUNET_LOG=';;;;DEBUG' RESULT=`gnunet-scalarproduct $CFGALICE $INPUTALICE -p $PEERIDBOB` # terminate the testbed kill $PID EXPECTED="0CCC" if [ "$RESULT" == "$EXPECTED" ] then echo "OK" exit 0 else echo "Result $RESULT NOTOK" exit 1 fi gnunet-0.10.1/src/scalarproduct/test_scalarproduct_negativezero.sh0000755000175000017500000000230312254263402022473 00000000000000#!/bin/bash # compute a simple scalar product # payload for this test: INPUTALICE="-k CCC -e -1,1,1" INPUTBOB="-k CCC -e 1,1,0" # necessary to make the testing prefix deterministic, so we can access the config files PREFIX=/tmp/test-scalarproduct`date +%H%M%S` # where can we find the peers config files? CFGALICE="-c $PREFIX/0/config" CFGBOB="-c $PREFIX/1/config" # launch two peers in line topology non-interactively # # interactive mode would terminate the test immediately # because the rest of the script is already in stdin, # thus redirecting stdin does not suffice) # GNUNET_LOG='scalarproduct;;;;DEBUG' GNUNET_TESTING_PREFIX=$PREFIX ../testbed/gnunet-testbed-profiler -n -c test_scalarproduct.conf -p 2 & PID=$! # sleep 1 is too short on most systems, 2 works on most, 5 seems to be safe sleep 5 # get bob's peer ID, necessary for alice PEERIDBOB=`gnunet-peerinfo -qs $CFGBOB` #GNUNET_LOG=';;;;DEBUG' gnunet-scalarproduct $CFGBOB $INPUTBOB & #GNUNET_LOG=';;;;DEBUG' RESULT=`gnunet-scalarproduct $CFGALICE $INPUTALICE -p $PEERIDBOB` # terminate the testbed kill $PID EXPECTED="00" if [ "$RESULT" == "$EXPECTED" ] then echo "OK" exit 0 else echo "Result $RESULT NOTOK" exit 1 fi gnunet-0.10.1/src/scalarproduct/test_scalarproduct.conf0000644000175000017500000000215512227705277020241 00000000000000[arm] DEFAULTSERVICES = core mesh statistics scalarproduct PORT = 12366 [ats] WAN_QUOTA_OUT = 3932160 WAN_QUOTA_IN = 3932160 [block] plugins = dht test [consensus] AUTOSTART = NO [core] PORT = 12092 AUTOSTART = YES [dht] AUTOSTART = YES DISABLE_TRY_CONNECT = NO [dhtcache] QUOTA = 1 MB DATABASE = heap [dns] AUTOSTART = NO [fs] AUTOSTART = NO [gnunetd] HOSTKEY = $SERVICEHOME/.hostkey [mesh] #AUTOSTART = YES ACCEPT_FROM = 127.0.0.1; PORT = 10700 [nat] RETURN_LOCAL_ADDRESSES = YES [namestore] AUTOSTART = NO [nse] AUTOSTART = NO [PATHS] GNUNET_TEST_HOME = /tmp/test-scalarproduct/ [psycstore] AUTOSTART = NO [regex] AUTOSTART = NO [resolver] AUTOSTART = NO HOSTNAME = localhost [statistics] AUTOSTART = NO [scalarproduct] AUTOSTART = YES BINARY = gnunet-service-scalarproduct UNIXPATH = $SERVICEHOME/scalarproduct.sock #HOME = $SERVICEHOME HOSTNAME = localhost PORT = 13087 [transport] PLUGINS = tcp ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; NEIGHBOUR_LIMIT = 50 PORT = 12365 [transport-tcp] TIMEOUT = 300 s PORT = 12368 [testbed] OVERLAY_TOPOLOGY = LINE [TESTING] WEAKRANDOM = YES [vpn] AUTOSTART = NO gnunet-0.10.1/src/scalarproduct/test_scalarproduct_negative.sh0000755000175000017500000000232412254263402021576 00000000000000#!/bin/bash # compute a simple scalar product # payload for this test: INPUTALICE="-k CCC -e -3,-3,1" INPUTBOB="-k CCC -e 1000,100,24" # necessary to make the testing prefix deterministic, so we can access the config files PREFIX=/tmp/test-scalarproduct`date +%H%M%S` # where can we find the peers config files? CFGALICE="-c $PREFIX/0/config" CFGBOB="-c $PREFIX/1/config" # launch two peers in line topology non-interactively # # interactive mode would terminate the test immediately # because the rest of the script is already in stdin, # thus redirecting stdin does not suffice) #GNUNET_LOG='scalarproduct;;;;DEBUG' GNUNET_TESTING_PREFIX=$PREFIX ../testbed/gnunet-testbed-profiler -n -c test_scalarproduct.conf -p 2 & PID=$! # sleep 1 is too short on most systems, 2 works on most, 5 seems to be safe sleep 5 # get bob's peer ID, necessary for alice PEERIDBOB=`gnunet-peerinfo -qs $CFGBOB` #GNUNET_LOG=';;;;DEBUG' gnunet-scalarproduct $CFGBOB $INPUTBOB & #RESULT=`GNUNET_LOG=';;;;DEBUG' RESULT=`gnunet-scalarproduct $CFGALICE $INPUTALICE -p $PEERIDBOB` # terminate the testbed kill $PID EXPECTED="-0CCC" if [ "$RESULT" == "$EXPECTED" ] then echo "OK" exit 0 else echo "Result $RESULT NOTOK" exit 1 fi gnunet-0.10.1/src/scalarproduct/Makefile.in0000644000175000017500000007575112320752063015533 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-scalarproduct$(EXEEXT) libexec_PROGRAMS = gnunet-service-scalarproduct$(EXEEXT) subdir = src/scalarproduct DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/scalarproduct.conf.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = scalarproduct.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetscalarproduct_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetscalarproduct_la_OBJECTS = scalarproduct_api.lo libgnunetscalarproduct_la_OBJECTS = \ $(am_libgnunetscalarproduct_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetscalarproduct_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetscalarproduct_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_scalarproduct_OBJECTS = gnunet-scalarproduct.$(OBJEXT) gnunet_scalarproduct_OBJECTS = $(am_gnunet_scalarproduct_OBJECTS) am_gnunet_service_scalarproduct_OBJECTS = \ gnunet-service-scalarproduct.$(OBJEXT) gnunet_service_scalarproduct_OBJECTS = \ $(am_gnunet_service_scalarproduct_OBJECTS) gnunet_service_scalarproduct_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/set/libgnunetset.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetscalarproduct_la_SOURCES) \ $(gnunet_scalarproduct_SOURCES) \ $(gnunet_service_scalarproduct_SOURCES) DIST_SOURCES = $(libgnunetscalarproduct_la_SOURCES) \ $(gnunet_scalarproduct_SOURCES) \ $(gnunet_service_scalarproduct_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ scalarproduct.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage lib_LTLIBRARIES = \ libgnunetscalarproduct.la gnunet_scalarproduct_SOURCES = \ gnunet-scalarproduct.c gnunet_scalarproduct_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/scalarproduct/libgnunetscalarproduct.la \ $(LIBGCRYPT_LIBS) \ -lgcrypt \ $(GN_LIBINTL) gnunet_scalarproduct_DEPENDENCIES = \ libgnunetscalarproduct.la gnunet_service_scalarproduct_SOURCES = \ gnunet-service-scalarproduct.c gnunet_service_scalarproduct_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/set/libgnunetset.la \ $(LIBGCRYPT_LIBS) \ -lgcrypt \ $(GN_LIBINTL) libgnunetscalarproduct_la_SOURCES = \ scalarproduct_api.c \ scalarproduct.h libgnunetscalarproduct_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(LIBGCRYPT_LIBS) \ -lgcrypt \ $(LTLIBINTL) libgnunetscalarproduct_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) EXTRA_DIST = \ test_scalarproduct.conf \ $(check_SCRIPTS) check_SCRIPTS = \ test_scalarproduct.sh \ test_scalarproduct_negative.sh \ test_scalarproduct_negativezero.sh @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/scalarproduct/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/scalarproduct/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): scalarproduct.conf: $(top_builddir)/config.status $(srcdir)/scalarproduct.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetscalarproduct.la: $(libgnunetscalarproduct_la_OBJECTS) $(libgnunetscalarproduct_la_DEPENDENCIES) $(EXTRA_libgnunetscalarproduct_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetscalarproduct_la_LINK) -rpath $(libdir) $(libgnunetscalarproduct_la_OBJECTS) $(libgnunetscalarproduct_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-scalarproduct$(EXEEXT): $(gnunet_scalarproduct_OBJECTS) $(gnunet_scalarproduct_DEPENDENCIES) $(EXTRA_gnunet_scalarproduct_DEPENDENCIES) @rm -f gnunet-scalarproduct$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_scalarproduct_OBJECTS) $(gnunet_scalarproduct_LDADD) $(LIBS) gnunet-service-scalarproduct$(EXEEXT): $(gnunet_service_scalarproduct_OBJECTS) $(gnunet_service_scalarproduct_DEPENDENCIES) $(EXTRA_gnunet_service_scalarproduct_DEPENDENCIES) @rm -f gnunet-service-scalarproduct$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_scalarproduct_OBJECTS) $(gnunet_service_scalarproduct_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-scalarproduct.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-scalarproduct.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scalarproduct_api.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libexecPROGRAMS clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libexecPROGRAMS install-man install-pdf install-pdf-am \ install-pkgcfgDATA install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # TESTS = $(check_SCRIPTS) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/scalarproduct/Makefile.am0000644000175000017500000000331212320751517015505 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ scalarproduct.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif bin_PROGRAMS = \ gnunet-scalarproduct libexec_PROGRAMS = \ gnunet-service-scalarproduct lib_LTLIBRARIES = \ libgnunetscalarproduct.la gnunet_scalarproduct_SOURCES = \ gnunet-scalarproduct.c gnunet_scalarproduct_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/scalarproduct/libgnunetscalarproduct.la \ $(LIBGCRYPT_LIBS) \ -lgcrypt \ $(GN_LIBINTL) gnunet_scalarproduct_DEPENDENCIES = \ libgnunetscalarproduct.la gnunet_service_scalarproduct_SOURCES = \ gnunet-service-scalarproduct.c gnunet_service_scalarproduct_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/mesh/libgnunetmesh.la \ $(top_builddir)/src/set/libgnunetset.la \ $(LIBGCRYPT_LIBS) \ -lgcrypt \ $(GN_LIBINTL) libgnunetscalarproduct_la_SOURCES = \ scalarproduct_api.c \ scalarproduct.h libgnunetscalarproduct_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(LIBGCRYPT_LIBS) \ -lgcrypt \ $(LTLIBINTL) libgnunetscalarproduct_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) EXTRA_DIST = \ test_scalarproduct.conf \ $(check_SCRIPTS) check_SCRIPTS = \ test_scalarproduct.sh \ test_scalarproduct_negative.sh \ test_scalarproduct_negativezero.sh if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; # TESTS = $(check_SCRIPTS) endif gnunet-0.10.1/src/scalarproduct/gnunet-service-scalarproduct.c0000644000175000017500000022253012307312000021405 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file scalarproduct/gnunet-service-scalarproduct.c * @brief scalarproduct service implementation * @author Christian M. Fuchs */ #include "platform.h" #include #include #include "gnunet_util_lib.h" #include "gnunet_core_service.h" #include "gnunet_mesh_service.h" #include "gnunet_applications.h" #include "gnunet_protocols.h" #include "gnunet_scalarproduct_service.h" #include "scalarproduct.h" #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct", __VA_ARGS__) /////////////////////////////////////////////////////////////////////////////// // Service Structure Definitions /////////////////////////////////////////////////////////////////////////////// /** * state a session can be in */ enum SessionState { CLIENT_REQUEST_RECEIVED, WAITING_FOR_BOBS_CONNECT, CLIENT_RESPONSE_RECEIVED, WAITING_FOR_SERVICE_REQUEST, WAITING_FOR_MULTIPART_TRANSMISSION, WAITING_FOR_SERVICE_RESPONSE, SERVICE_REQUEST_RECEIVED, SERVICE_RESPONSE_RECEIVED, FINALIZED }; /** * role a peer in a session can assume */ enum PeerRole { ALICE, BOB }; /** * A scalarproduct session which tracks: * * a request form the client to our final response. * or * a request from a service to us(service). */ struct ServiceSession { /** * the role this peer has */ enum PeerRole role; /** * session information is kept in a DLL */ struct ServiceSession *next; /** * session information is kept in a DLL */ struct ServiceSession *prev; /** * (hopefully) unique transaction ID */ struct GNUNET_HashCode key; /** * state of the session */ enum SessionState state; /** * Alice or Bob's peerID */ struct GNUNET_PeerIdentity peer; /** * the client this request is related to */ struct GNUNET_SERVER_Client * client; /** * The message to send */ struct GNUNET_MessageHeader * msg; /** * how many elements we were supplied with from the client */ uint32_t total; /** * how many elements actually are used after applying the mask */ uint32_t used; /** * already transferred elements (sent/received) for multipart messages, less or equal than used_element_count for */ uint32_t transferred; /** * index of the last transferred element for multipart messages */ uint32_t last_processed; /** * how many bytes the mask is long. * just for convenience so we don't have to re-re-re calculate it each time */ uint32_t mask_length; /** * all the vector elements we received */ int32_t * vector; /** * mask of which elements to check */ unsigned char * mask; /** * Public key of the remote service, only used by bob */ struct GNUNET_CRYPTO_PaillierPublicKey * remote_pubkey; /** * ai(Alice) after applying the mask */ gcry_mpi_t * a; /** * E(ai)(Bob) after applying the mask */ struct GNUNET_CRYPTO_PaillierCiphertext * e_a; /** * Bob's permutation p of R */ struct GNUNET_CRYPTO_PaillierCiphertext * r; /** * Bob's permutation q of R */ struct GNUNET_CRYPTO_PaillierCiphertext * r_prime; /** * Bob's s */ struct GNUNET_CRYPTO_PaillierCiphertext * s; /** * Bob's s' */ struct GNUNET_CRYPTO_PaillierCiphertext * s_prime; /** * Bobs matching response session from the client */ struct ServiceSession * response; /** * The computed scalar */ gcry_mpi_t product; /** * My transmit handle for the current message to a alice/bob */ struct GNUNET_MESH_TransmitHandle * service_transmit_handle; /** * My transmit handle for the current message to the client */ struct GNUNET_SERVER_TransmitHandle * client_transmit_handle; /** * channel-handle associated with our mesh handle */ struct GNUNET_MESH_Channel * channel; /** * Handle to a task that sends a msg to the our client */ GNUNET_SCHEDULER_TaskIdentifier client_notification_task; /** * Handle to a task that sends a msg to the our peer */ GNUNET_SCHEDULER_TaskIdentifier service_request_task; }; /////////////////////////////////////////////////////////////////////////////// // Forward Delcarations /////////////////////////////////////////////////////////////////////////////// /** * Send a multi part chunk of a service request from alice to bob. * This element only contains a part of the elements-vector (session->a[]), * mask and public key set have to be contained within the first message * * This allows a ~32kbit key length while using 32000 elements or 62000 elements per request. * * @param cls the associated service session */ static void prepare_service_request_multipart (void *cls); /** * Send a multi part chunk of a service response from bob to alice. * This element only contains the two permutations of R, R'. * * @param cls the associated service session */ static void prepare_service_response_multipart (void *cls); /////////////////////////////////////////////////////////////////////////////// // Global Variables /////////////////////////////////////////////////////////////////////////////// /** * Handle to the core service (NULL until we've connected to it). */ static struct GNUNET_MESH_Handle *my_mesh; /** * The identity of this host. */ static struct GNUNET_PeerIdentity me; /** * Service's own public key */ static struct GNUNET_CRYPTO_PaillierPublicKey my_pubkey; /** * Service's own private key */ static struct GNUNET_CRYPTO_PaillierPrivateKey my_privkey; /** * Service's offset for values that could possibly be negative but are plaintext for encryption. */ static gcry_mpi_t my_offset; /** * Head of our double linked list for client-requests sent to us. * for all of these elements we calculate a scalar product with a remote peer * split between service->service and client->service for simplicity */ static struct ServiceSession * from_client_head; /** * Tail of our double linked list for client-requests sent to us. * for all of these elements we calculate a scalar product with a remote peer * split between service->service and client->service for simplicity */ static struct ServiceSession * from_client_tail; /** * Head of our double linked list for service-requests sent to us. * for all of these elements we help the requesting service in calculating a scalar product * split between service->service and client->service for simplicity */ static struct ServiceSession * from_service_head; /** * Tail of our double linked list for service-requests sent to us. * for all of these elements we help the requesting service in calculating a scalar product * split between service->service and client->service for simplicity */ static struct ServiceSession * from_service_tail; /** * Certain events (callbacks for server & mesh operations) must not be queued after shutdown. */ static int do_shutdown; /////////////////////////////////////////////////////////////////////////////// // Helper Functions /////////////////////////////////////////////////////////////////////////////// /** * computes the square sum over a vector of a given length. * * @param vector the vector to encrypt * @param length the length of the vector * @return an MPI value containing the calculated sum, never NULL */ static gcry_mpi_t compute_square_sum (gcry_mpi_t * vector, uint32_t length) { gcry_mpi_t elem; gcry_mpi_t sum; int32_t i; GNUNET_assert (sum = gcry_mpi_new (0)); GNUNET_assert (elem = gcry_mpi_new (0)); // calculare E(sum (ai ^ 2), publickey) for (i = 0; i < length; i++) { gcry_mpi_mul (elem, vector[i], vector[i]); gcry_mpi_add (sum, sum, elem); } gcry_mpi_release (elem); return sum; } /** * Primitive callback for copying over a message, as they * usually are too complex to be handled in the callback itself. * clears a session-callback, if a session was handed over and the transmit handle was stored * * @param cls the message object * @param size the size of the buffer we got * @param buf the buffer to copy the message to * @return 0 if we couldn't copy, else the size copied over */ static size_t do_send_message (void *cls, size_t size, void *buf) { struct ServiceSession * session = cls; uint16_t type; GNUNET_assert (buf); if (ntohs (session->msg->size) != size) { GNUNET_break (0); return 0; } type = ntohs (session->msg->type); memcpy (buf, session->msg, size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent a message of type %hu.\n", type); GNUNET_free (session->msg); session->msg = NULL; switch (type) { case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT: session->state = FINALIZED; session->client_transmit_handle = NULL; break; case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB: case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART: session->service_transmit_handle = NULL; if (session->state == WAITING_FOR_MULTIPART_TRANSMISSION) prepare_service_request_multipart (session); break; case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE: case GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE_MULTIPART: session->service_transmit_handle = NULL; if (session->state == WAITING_FOR_MULTIPART_TRANSMISSION) prepare_service_response_multipart (session); break; default: GNUNET_assert (0); } return size; } /** * initializes a new vector with fresh MPI values (=0) of a given length * * @param length of the vector to create * @return the initialized vector, never NULL */ static gcry_mpi_t * initialize_mpi_vector (uint32_t length) { uint32_t i; gcry_mpi_t * output = GNUNET_malloc (sizeof (gcry_mpi_t) * length); for (i = 0; i < length; i++) GNUNET_assert (NULL != (output[i] = gcry_mpi_new (0))); return output; } /** * Finds a not terminated client/service session in the * given DLL based on session key, element count and state. * * @param tail - the tail of the DLL * @param key - the key we want to search for * @param element_count - the total element count of the dataset (session->total) * @param state - a pointer to the state the session should be in, NULL to ignore * @param peerid - a pointer to the peer ID of the associated peer, NULL to ignore * @return a pointer to a matching session, or NULL */ static struct ServiceSession * find_matching_session (struct ServiceSession * tail, const struct GNUNET_HashCode * key, uint32_t element_count, enum SessionState * state, const struct GNUNET_PeerIdentity * peerid) { struct ServiceSession * curr; for (curr = tail; NULL != curr; curr = curr->prev) { // if the key matches, and the element_count is same if ((!memcmp (&curr->key, key, sizeof (struct GNUNET_HashCode))) && (curr->total == element_count)) { // if incoming state is NULL OR is same as state of the queued request if ((NULL == state) || (curr->state == *state)) { // if peerid is NULL OR same as the peer Id in the queued request if ((NULL == peerid) || (!memcmp (&curr->peer, peerid, sizeof (struct GNUNET_PeerIdentity)))) // matches and is not an already terminated session return curr; } } } return NULL; } /** * Safely frees ALL memory areas referenced by a session. * * @param session - the session to free elements from */ static void free_session_variables (struct ServiceSession * session) { unsigned int i; if (session->a) { for (i = 0; i < session->used; i++) if (session->a[i]) gcry_mpi_release (session->a[i]); GNUNET_free (session->a); session->a = NULL; } if (session->e_a) { GNUNET_free (session->e_a); session->e_a = NULL; } if (session->mask) { GNUNET_free (session->mask); session->mask = NULL; } if (session->r) { GNUNET_free (session->r); session->r = NULL; } if (session->r_prime) { GNUNET_free (session->r_prime); session->r_prime = NULL; } if (session->s) { GNUNET_free (session->s); session->s = NULL; } if (session->s_prime) { GNUNET_free (session->s_prime); session->s_prime = NULL; } if (session->product) { gcry_mpi_release (session->product); session->product = NULL; } if (session->remote_pubkey) { GNUNET_free (session->remote_pubkey); session->remote_pubkey = NULL; } if (session->vector) { GNUNET_free_non_null (session->vector); session->s = NULL; } } /////////////////////////////////////////////////////////////////////////////// // Event and Message Handlers /////////////////////////////////////////////////////////////////////////////// /** * A client disconnected. * * Remove the associated session(s), release data structures * and cancel pending outgoing transmissions to the client. * if the session has not yet completed, we also cancel Alice's request to Bob. * * @param cls closure, NULL * @param client identification of the client */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ServiceSession *session; if (NULL != client) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Client (%p) disconnected from us.\n"), client); else return; session = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession); if (NULL == session) return; GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session); if (!(session->role == BOB && session->state == FINALIZED)) { //we MUST terminate any client message underway if (session->service_transmit_handle && session->channel) GNUNET_MESH_notify_transmit_ready_cancel (session->service_transmit_handle); if (session->channel && session->state == WAITING_FOR_SERVICE_RESPONSE) GNUNET_MESH_channel_destroy (session->channel); } if (GNUNET_SCHEDULER_NO_TASK != session->client_notification_task) { GNUNET_SCHEDULER_cancel (session->client_notification_task); session->client_notification_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != session->service_request_task) { GNUNET_SCHEDULER_cancel (session->service_request_task); session->service_request_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != session->client_transmit_handle) { GNUNET_SERVER_notify_transmit_ready_cancel (session->client_transmit_handle); session->client_transmit_handle = NULL; } free_session_variables (session); GNUNET_free (session); } /** * Notify the client that the session has succeeded or failed completely. * This message gets sent to * * alice's client if bob disconnected or to * * bob's client if the operation completed or alice disconnected * * @param cls the associated client session * @param tc the task context handed to us by the scheduler, unused */ static void prepare_client_end_notification (void * cls, const struct GNUNET_SCHEDULER_TaskContext * tc) { struct ServiceSession * session = cls; struct GNUNET_SCALARPRODUCT_client_response * msg; session->client_notification_task = GNUNET_SCHEDULER_NO_TASK; msg = GNUNET_new (struct GNUNET_SCALARPRODUCT_client_response); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT); memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode)); memcpy (&msg->peer, &session->peer, sizeof ( struct GNUNET_PeerIdentity)); msg->header.size = htons (sizeof (struct GNUNET_SCALARPRODUCT_client_response)); // signal error if not signalized, positive result-range field but zero length. msg->product_length = htonl (0); msg->range = (session->state == FINALIZED) ? 0 : -1; session->msg = &msg->header; //transmit this message to our client session->client_transmit_handle = GNUNET_SERVER_notify_transmit_ready (session->client, sizeof (struct GNUNET_SCALARPRODUCT_client_response), GNUNET_TIME_UNIT_FOREVER_REL, &do_send_message, session); // if we could not even queue our request, something is wrong if (NULL == session->client_transmit_handle) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not send message to client (%p)!\n"), session->client); // usually gets freed by do_send_message session->msg = NULL; GNUNET_free (msg); } else GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Sending session-end notification to client (%p) for session %s\n"), &session->client, GNUNET_h2s (&session->key)); free_session_variables (session); } /** * prepare the response we will send to alice or bobs' clients. * in Bobs case the product will be NULL. * * @param cls the session associated with our client. * @param tc the task context handed to us by the scheduler, unused */ static void prepare_client_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceSession * session = cls; struct GNUNET_SCALARPRODUCT_client_response * msg; unsigned char * product_exported = NULL; size_t product_length = 0; uint32_t msg_length = 0; int8_t range = -1; gcry_error_t rc; int sign; session->client_notification_task = GNUNET_SCHEDULER_NO_TASK; if (session->product) { gcry_mpi_t value = gcry_mpi_new (0); sign = gcry_mpi_cmp_ui (session->product, 0); // libgcrypt can not handle a print of a negative number // if (a->sign) return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */ if (0 > sign) { gcry_mpi_sub (value, value, session->product); } else if (0 < sign) { range = 1; gcry_mpi_add (value, value, session->product); } else range = 0; gcry_mpi_release (session->product); session->product = NULL; // get representation as string if (range && (0 != (rc = gcry_mpi_aprint (GCRYMPI_FMT_STD, &product_exported, &product_length, value)))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); product_length = 0; range = -1; // signal error with product-length = 0 and range = -1 } gcry_mpi_release (value); } msg_length = sizeof (struct GNUNET_SCALARPRODUCT_client_response) +product_length; msg = GNUNET_malloc (msg_length); msg->key = session->key; msg->peer = session->peer; if (product_exported != NULL) { memcpy (&msg[1], product_exported, product_length); GNUNET_free (product_exported); } msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT); msg->header.size = htons (msg_length); msg->range = range; msg->product_length = htonl (product_length); session->msg = (struct GNUNET_MessageHeader *) msg; //transmit this message to our client session->client_transmit_handle = GNUNET_SERVER_notify_transmit_ready (session->client, msg_length, GNUNET_TIME_UNIT_FOREVER_REL, &do_send_message, session); if (NULL == session->client_transmit_handle) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Could not send message to client (%p)!\n"), session->client); session->client = NULL; // callback was not called! GNUNET_free (msg); session->msg = NULL; } else // gracefully sent message, just terminate session structure GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Sent result to client (%p), this session (%s) has ended!\n"), session->client, GNUNET_h2s (&session->key)); free_session_variables (session); } /** * Send a multipart chunk of a service response from bob to alice. * This element only contains the two permutations of R, R'. * * @param cls the associated service session */ static void prepare_service_response_multipart (void *cls) { struct ServiceSession * session = cls; struct GNUNET_CRYPTO_PaillierCiphertext * payload; struct GNUNET_SCALARPRODUCT_multipart_message * msg; unsigned int i; unsigned int j; uint32_t msg_length; uint32_t todo_count; msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message); todo_count = session->used - session->transferred; if (todo_count > MULTIPART_ELEMENT_CAPACITY / 2) // send the currently possible maximum chunk, we always transfer both permutations todo_count = MULTIPART_ELEMENT_CAPACITY / 2; msg_length += todo_count * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2; msg = GNUNET_malloc (msg_length); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART); msg->header.size = htons (msg_length); msg->multipart_element_count = htonl (todo_count); payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1]; for (i = session->transferred, j=0; i < session->transferred + todo_count; i++) { //r[i][p] and r[i][q] memcpy (&payload[j++], &session->r[i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); memcpy (&payload[j++], &session->r_prime[i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); } session->transferred += todo_count; session->msg = (struct GNUNET_MessageHeader *) msg; session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready (session->channel, GNUNET_YES, GNUNET_TIME_UNIT_FOREVER_REL, msg_length, &do_send_message, session); //disconnect our client if (NULL == session->service_transmit_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response message via mesh!)\n")); session->state = FINALIZED; session->response->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, session->response); return; } if (session->transferred != session->used) // more multiparts session->state = WAITING_FOR_MULTIPART_TRANSMISSION; else { // final part session->state = FINALIZED; GNUNET_free (session->r_prime); GNUNET_free (session->r); session->r_prime = NULL; session->r = NULL; } } /** * Bob executes: * generates the response message to be sent to alice after computing * the values (1), (2), S and S' * (1)[]: $E_A(a_{pi(i)}) times E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$ * (2)[]: $E_A(a_{pi'(i)}) times E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$ * S: $S := E_A(sum (r_i + b_i)^2)$ * S': $S' := E_A(sum r_i^2)$ * * @param session the associated requesting session with alice * @return #GNUNET_NO if we could not send our message * #GNUNET_OK if the operation succeeded */ static int prepare_service_response (struct ServiceSession * session) { struct GNUNET_SCALARPRODUCT_service_response * msg; uint32_t msg_length = 0; struct GNUNET_CRYPTO_PaillierCiphertext * payload; int i; msg_length = sizeof (struct GNUNET_SCALARPRODUCT_service_response) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); // s, stick if (GNUNET_SERVER_MAX_MESSAGE_SIZE > msg_length + 2 * session->used * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)) { //r, r' msg_length += 2 * session->used * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); session->transferred = session->used; } else session->transferred = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - msg_length) / (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * 2); msg = GNUNET_malloc (msg_length); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE); msg->header.size = htons (msg_length); msg->total_element_count = htonl (session->total); msg->used_element_count = htonl (session->used); msg->contained_element_count = htonl (session->transferred); memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode)); payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1]; memcpy (&payload[0], session->s, sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); memcpy (&payload[1], session->s_prime, sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); GNUNET_free (session->s_prime); session->s_prime = NULL; GNUNET_free (session->s); session->s = NULL; // convert k[][] for (i = 0; i < session->transferred; i++) { //k[i][p] and k[i][q] memcpy (&payload[2 + i*2], &session->r[i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); memcpy (&payload[3 + i*2], &session->r_prime[i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); } session->msg = (struct GNUNET_MessageHeader *) msg; session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready (session->channel, GNUNET_YES, GNUNET_TIME_UNIT_FOREVER_REL, msg_length, &do_send_message, session); //disconnect our client if (NULL == session->service_transmit_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-response message via mesh!)\n")); session->state = FINALIZED; session->response->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, session->response); return GNUNET_NO; } if (session->transferred != session->used) // multipart session->state = WAITING_FOR_MULTIPART_TRANSMISSION; else { //singlepart session->state = FINALIZED; GNUNET_free (session->r); session->r = NULL; GNUNET_free (session->r_prime); session->r_prime = NULL; } return GNUNET_OK; } /** * executed by bob: * compute the values * (1)[]: $E_A(a_{pi(i)}) otimes E_A(- r_{pi(i)} - b_{pi(i)}) &= E_A(a_{pi(i)} - r_{pi(i)} - b_{pi(i)})$ * (2)[]: $E_A(a_{pi'(i)}) otimes E_A(- r_{pi'(i)}) &= E_A(a_{pi'(i)} - r_{pi'(i)})$ * S: $S := E_A(sum (r_i + b_i)^2)$ * S': $S' := E_A(sum r_i^2)$ * * @param request the requesting session + bob's requesting peer * @param response the responding session + bob's client handle * @return GNUNET_SYSERR if the computation failed * GNUNET_OK if everything went well. */ static int compute_service_response (struct ServiceSession * request, struct ServiceSession * response) { int i; int j; int ret = GNUNET_SYSERR; unsigned int * p; unsigned int * q; uint32_t count; gcry_mpi_t * rand = NULL; gcry_mpi_t tmp; gcry_mpi_t * b; struct GNUNET_CRYPTO_PaillierCiphertext * a; struct GNUNET_CRYPTO_PaillierCiphertext * r; struct GNUNET_CRYPTO_PaillierCiphertext * r_prime; struct GNUNET_CRYPTO_PaillierCiphertext * s; struct GNUNET_CRYPTO_PaillierCiphertext * s_prime; uint32_t value; count = request->used; a = request->e_a; b = initialize_mpi_vector (count); q = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, count); p = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, count); rand = initialize_mpi_vector (count); r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count); r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * count); s = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); s_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); // convert responder session to from long to mpi for (i = 0, j = 0; i < response->total && j < count; i++) { if (request->mask[i / 8] & (1 << (i % 8))) { value = response->vector[i] >= 0 ? response->vector[i] : -response->vector[i]; // long to gcry_mpi_t if (0 > response->vector[i]) gcry_mpi_sub_ui (b[j], b[j], value); else b[j] = gcry_mpi_set_ui (b[j], value); j++; } } GNUNET_free (response->vector); response->vector = NULL; for (i = 0; i < count; i++) { int32_t svalue; svalue = (int32_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX); // long to gcry_mpi_t if (svalue < 0) gcry_mpi_sub_ui (rand[i], rand[i], -svalue); else rand[i] = gcry_mpi_set_ui (rand[i], svalue); } tmp = gcry_mpi_new (0); // encrypt the element // for the sake of readability I decided to have dedicated permutation // vectors, which get rid of all the lookups in p/q. // however, ap/aq are not absolutely necessary but are just abstraction // Calculate Kp = E(S + a_pi) (+) E(S - r_pi - b_pi) for (i = 0; i < count; i++) { // E(S - r_pi - b_pi) gcry_mpi_sub (tmp, my_offset, rand[p[i]]); gcry_mpi_sub (tmp, tmp, b[p[i]]); GNUNET_CRYPTO_paillier_encrypt (request->remote_pubkey, tmp, 2, &r[i]); // E(S - r_pi - b_pi) * E(S + a_pi) == E(2*S + a - r - b) GNUNET_CRYPTO_paillier_hom_add (request->remote_pubkey, &r[i], &a[p[i]], &r[i]); } // Calculate Kq = E(S + a_qi) (+) E(S - r_qi) for (i = 0; i < count; i++) { // E(S - r_qi) gcry_mpi_sub (tmp, my_offset, rand[q[i]]); GNUNET_assert (2 == GNUNET_CRYPTO_paillier_encrypt (request->remote_pubkey, tmp, 2, &r_prime[i])); // E(S - r_qi) * E(S + a_qi) == E(2*S + a_qi - r_qi) GNUNET_assert (1 == GNUNET_CRYPTO_paillier_hom_add (request->remote_pubkey, &r_prime[i], &a[q[i]], &r_prime[i])); } // Calculate S' = E(SUM( r_i^2 )) tmp = compute_square_sum (rand, count); GNUNET_CRYPTO_paillier_encrypt (request->remote_pubkey, tmp, 1, s_prime); // Calculate S = E(SUM( (r_i + b_i)^2 )) for (i = 0; i < count; i++) gcry_mpi_add (rand[i], rand[i], b[i]); tmp = compute_square_sum (rand, count); GNUNET_CRYPTO_paillier_encrypt (request->remote_pubkey, tmp, 1, s); request->r = r; request->r_prime = r_prime; request->s = s; request->s_prime = s_prime; request->response = response; // release rand, b and a for (i = 0; i < count; i++) { gcry_mpi_release (rand[i]); gcry_mpi_release (b[i]); gcry_mpi_release (request->a[i]); } gcry_mpi_release (tmp); GNUNET_free (request->a); request->a = NULL; GNUNET_free (p); GNUNET_free (q); GNUNET_free (b); GNUNET_free (rand); // copy the r[], r_prime[], S and Stick into a new message, prepare_service_response frees these if (GNUNET_YES != prepare_service_response (request)) GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Failed to communicate with `%s', scalar product calculation aborted.\n"), GNUNET_i2s (&request->peer)); else ret = GNUNET_OK; return ret; } /** * Send a multi part chunk of a service request from alice to bob. * This element only contains a part of the elements-vector (session->a[]), * mask and public key set have to be contained within the first message * * This allows a ~32kbit key length while using 32000 elements or 62000 elements per request. * * @param cls the associated service session */ static void prepare_service_request_multipart (void *cls) { struct ServiceSession * session = cls; struct GNUNET_SCALARPRODUCT_multipart_message * msg; struct GNUNET_CRYPTO_PaillierCiphertext * payload; unsigned int i; unsigned int j; uint32_t msg_length; uint32_t todo_count; gcry_mpi_t a; uint32_t value; msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message); todo_count = session->used - session->transferred; if (todo_count > MULTIPART_ELEMENT_CAPACITY) // send the currently possible maximum chunk todo_count = MULTIPART_ELEMENT_CAPACITY; msg_length += todo_count * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext); msg = GNUNET_malloc (msg_length); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART); msg->header.size = htons (msg_length); msg->multipart_element_count = htonl (todo_count); a = gcry_mpi_new (0); payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1]; // encrypt our vector and generate string representations for (i = session->last_processed, j = 0; i < session->total; i++) { // is this a used element? if (session->mask[i / 8] & 1 << (i % 8)) { if (todo_count <= j) break; //reached end of this message, can't include more value = session->vector[i] >= 0 ? session->vector[i] : -session->vector[i]; a = gcry_mpi_set_ui (a, 0); // long to gcry_mpi_t if (session->vector[i] < 0) gcry_mpi_sub_ui (a, a, value); else gcry_mpi_add_ui (a, a, value); session->a[session->transferred + j] = gcry_mpi_set (NULL, a); gcry_mpi_add (a, a, my_offset); GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[j++]); } } gcry_mpi_release (a); session->transferred += todo_count; session->msg = (struct GNUNET_MessageHeader *) msg; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n")); //transmit via mesh messaging session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready (session->channel, GNUNET_YES, GNUNET_TIME_UNIT_FOREVER_REL, msg_length, &do_send_message, session); if (!session->service_transmit_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send service-request multipart message to channel!\n")); GNUNET_free (msg); session->msg = NULL; session->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, session); return; } if (session->transferred != session->used) { session->last_processed = i; } else //final part session->state = WAITING_FOR_SERVICE_RESPONSE; } /** * Executed by Alice, fills in a service-request message and sends it to the given peer * * @param cls the session associated with this request * @param tc task context handed over by scheduler, unsued */ static void prepare_service_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceSession * session = cls; unsigned char * current; struct GNUNET_SCALARPRODUCT_service_request * msg; struct GNUNET_CRYPTO_PaillierCiphertext * payload; unsigned int i; unsigned int j; uint32_t msg_length; gcry_mpi_t a; uint32_t value; session->service_request_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Successfully created new channel to peer (%s)!\n"), GNUNET_i2s (&session->peer)); msg_length = sizeof (struct GNUNET_SCALARPRODUCT_service_request) + session->mask_length + sizeof(struct GNUNET_CRYPTO_PaillierPublicKey); if (GNUNET_SERVER_MAX_MESSAGE_SIZE > msg_length + session->used * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)) { msg_length += session->used * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext); session->transferred = session->used; } else { //create a multipart msg, first we calculate a new msg size for the head msg session->transferred = (GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - msg_length) / sizeof(struct GNUNET_CRYPTO_PaillierCiphertext); } msg = GNUNET_malloc (msg_length); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB); msg->total_element_count = htonl (session->used); msg->contained_element_count = htonl (session->transferred); memcpy (&msg->key, &session->key, sizeof (struct GNUNET_HashCode)); msg->mask_length = htonl (session->mask_length); msg->element_count = htonl (session->total); msg->header.size = htons (msg_length); // fill in the payload current = (unsigned char *) &msg[1]; // copy over the mask memcpy (current, session->mask, session->mask_length); // copy over our public key current += session->mask_length; memcpy (current, &my_pubkey, sizeof(struct GNUNET_CRYPTO_PaillierPublicKey)); current += sizeof(struct GNUNET_CRYPTO_PaillierPublicKey); payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) current; // now copy over the element vector session->a = GNUNET_malloc (sizeof (gcry_mpi_t) * session->used); a = gcry_mpi_new (0); // encrypt our vector and generate string representations for (i = 0, j = 0; i < session->total; i++) { // if this is a used element... if (session->mask[i / 8] & 1 << (i % 8)) { if (session->transferred <= j) break; //reached end of this message, can't include more value = session->vector[i] >= 0 ? session->vector[i] : -session->vector[i]; a = gcry_mpi_set_ui (a, 0); // long to gcry_mpi_t if (session->vector[i] < 0) gcry_mpi_sub_ui (a, a, value); else gcry_mpi_add_ui (a, a, value); session->a[j] = gcry_mpi_set (NULL, a); gcry_mpi_add (a, a, my_offset); GNUNET_CRYPTO_paillier_encrypt (&my_pubkey, a, 3, &payload[j++]); } } gcry_mpi_release (a); session->msg = (struct GNUNET_MessageHeader *) msg; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Transmitting service request.\n")); //transmit via mesh messaging session->service_transmit_handle = GNUNET_MESH_notify_transmit_ready (session->channel, GNUNET_YES, GNUNET_TIME_UNIT_FOREVER_REL, msg_length, &do_send_message, session); if (!session->service_transmit_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Could not send message to channel!\n")); GNUNET_free (msg); session->msg = NULL; session->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, session); return; } if (session->transferred != session->used) { session->state = WAITING_FOR_MULTIPART_TRANSMISSION; session->last_processed = i; } else //singlepart message session->state = WAITING_FOR_SERVICE_RESPONSE; } /** * Handler for a client request message. * Can either be type A or B * A: request-initiation to compute a scalar product with a peer * B: response role, keep the values + session and wait for a matching session or process a waiting request * * @param cls closure * @param client identification of the client * @param message the actual message */ static void handle_client_request (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_SCALARPRODUCT_client_request * msg = (const struct GNUNET_SCALARPRODUCT_client_request *) message; struct ServiceSession * session; uint32_t element_count; uint32_t mask_length; uint32_t msg_type; int32_t * vector; uint32_t i; // only one concurrent session per client connection allowed, simplifies logics a lot... session = GNUNET_SERVER_client_get_user_context (client, struct ServiceSession); if ((NULL != session) && (session->state != FINALIZED)) { GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } else if (NULL != session) { // old session is already completed, clean it up GNUNET_CONTAINER_DLL_remove (from_client_head, from_client_tail, session); free_session_variables (session); GNUNET_free (session); } //we need at least a peer and one message id to compare if (sizeof (struct GNUNET_SCALARPRODUCT_client_request) > ntohs (msg->header.size)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Too short message received from client!\n")); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msg_type = ntohs (msg->header.type); element_count = ntohl (msg->element_count); mask_length = ntohl (msg->mask_length); //sanity check: is the message as long as the message_count fields suggests? if ((ntohs (msg->header.size) != (sizeof (struct GNUNET_SCALARPRODUCT_client_request) +element_count * sizeof (int32_t) + mask_length)) || (0 == element_count)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Invalid message received from client, session information incorrect!\n")); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } // do we have a duplicate session here already? if (NULL != find_matching_session (from_client_tail, &msg->key, element_count, NULL, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Duplicate session information received, cannot create new session with key `%s'\n"), GNUNET_h2s (&msg->key)); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } session = GNUNET_new (struct ServiceSession); session->service_request_task = GNUNET_SCHEDULER_NO_TASK; session->client_notification_task = GNUNET_SCHEDULER_NO_TASK; session->client = client; session->total = element_count; session->mask_length = mask_length; // get our transaction key memcpy (&session->key, &msg->key, sizeof (struct GNUNET_HashCode)); //allocate memory for vector and encrypted vector session->vector = GNUNET_malloc (sizeof (int32_t) * element_count); vector = (int32_t *) & msg[1]; if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE == msg_type) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Got client-request-session with key %s, preparing channel to remote service.\n"), GNUNET_h2s (&session->key)); session->role = ALICE; // fill in the mask session->mask = GNUNET_malloc (mask_length); memcpy (session->mask, &vector[element_count], mask_length); // copy over the elements session->used = 0; for (i = 0; i < element_count; i++) { session->vector[i] = ntohl (vector[i]); if (session->vector[i] == 0) session->mask[i / 8] &= ~(1 << (i % 8)); if (session->mask[i / 8] & (1 << (i % 8))) session->used++; } if (0 == session->used) { GNUNET_break_op (0); GNUNET_free (session->vector); GNUNET_free (session); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } //session with ourself makes no sense! if (!memcmp (&msg->peer, &me, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); GNUNET_free (session->vector); GNUNET_free (session); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } // get our peer ID memcpy (&session->peer, &msg->peer, sizeof (struct GNUNET_PeerIdentity)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Creating new channel for session with key %s.\n"), GNUNET_h2s (&session->key)); session->channel = GNUNET_MESH_channel_create (my_mesh, session, &session->peer, GNUNET_APPLICATION_TYPE_SCALARPRODUCT, GNUNET_MESH_OPTION_RELIABLE); //prepare_service_request, channel_peer_disconnect_handler, if (!session->channel) { GNUNET_break (0); GNUNET_free (session->vector); GNUNET_free (session); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_client_set_user_context (client, session); GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session); session->state = CLIENT_REQUEST_RECEIVED; session->service_request_task = GNUNET_SCHEDULER_add_now (&prepare_service_request, session); } else { struct ServiceSession * requesting_session; enum SessionState needed_state = SERVICE_REQUEST_RECEIVED; session->role = BOB; session->mask = NULL; // copy over the elements session->used = element_count; for (i = 0; i < element_count; i++) session->vector[i] = ntohl (vector[i]); session->state = CLIENT_RESPONSE_RECEIVED; GNUNET_SERVER_client_set_user_context (client, session); GNUNET_CONTAINER_DLL_insert (from_client_head, from_client_tail, session); //check if service queue contains a matching request requesting_session = find_matching_session (from_service_tail, &session->key, session->total, &needed_state, NULL); if (NULL != requesting_session) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got client-responder-session with key %s and a matching service-request-session set, processing.\n"), GNUNET_h2s (&session->key)); if (GNUNET_OK != compute_service_response (requesting_session, session)) session->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, session); } else { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got client-responder-session with key %s but NO matching service-request-session set, queuing element for later use.\n"), GNUNET_h2s (&session->key)); // no matching session exists yet, store the response // for later processing by handle_service_request() } } GNUNET_SERVER_receive_done (client, GNUNET_YES); } /** * Function called for inbound channels. * * @param cls closure * @param channel new handle to the channel * @param initiator peer that started the channel * @param port unused * @param options unused * * @return session associated with the channel */ static void * channel_incoming_handler (void *cls, struct GNUNET_MESH_Channel *channel, const struct GNUNET_PeerIdentity *initiator, uint32_t port, enum GNUNET_MESH_ChannelOption options) { struct ServiceSession * c = GNUNET_new (struct ServiceSession); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("New incoming channel from peer %s.\n"), GNUNET_i2s (initiator)); c->peer = *initiator; c->channel = channel; c->role = BOB; c->state = WAITING_FOR_SERVICE_REQUEST; return c; } /** * Function called whenever a channel is destroyed. Should clean up * any associated state. * * It must NOT call GNUNET_MESH_channel_destroy on the channel. * * @param cls closure (set from GNUNET_MESH_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void channel_destruction_handler (void *cls, const struct GNUNET_MESH_Channel *channel, void *channel_ctx) { struct ServiceSession * session = channel_ctx; struct ServiceSession * client_session; struct ServiceSession * curr; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Peer disconnected, terminating session %s with peer (%s)\n"), GNUNET_h2s (&session->key), GNUNET_i2s (&session->peer)); if (ALICE == session->role) { // as we have only one peer connected in each session, just remove the session if ((SERVICE_RESPONSE_RECEIVED > session->state) && (!do_shutdown)) { session->channel = NULL; // if this happened before we received the answer, we must terminate the session session->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, session); } } else { //(BOB == session->role) service session // remove the session, unless it has already been dequeued, but somehow still active // this could bug without the IF in case the queue is empty and the service session was the only one know to the service // scenario: disconnect before alice can send her message to bob. for (curr = from_service_head; NULL != curr; curr = curr->next) if (curr == session) { GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, curr); break; } // there is a client waiting for this service session, terminate it, too! // i assume the tupel of key and element count is unique. if it was not the rest of the code would not work either. client_session = find_matching_session (from_client_tail, &session->key, session->total, NULL, NULL); free_session_variables (session); GNUNET_free (session); // the client has to check if it was waiting for a result // or if it was a responder, no point in adding more statefulness if (client_session && (!do_shutdown)) { client_session->state = FINALIZED; client_session->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, client_session); } } } /** * Compute our scalar product, done by Alice * * @param session - the session associated with this computation * @return product as MPI, never NULL */ static gcry_mpi_t compute_scalar_product (struct ServiceSession * session) { uint32_t count; gcry_mpi_t t; gcry_mpi_t u; gcry_mpi_t u_prime; gcry_mpi_t p; gcry_mpi_t p_prime; gcry_mpi_t tmp; gcry_mpi_t r[session->used]; gcry_mpi_t r_prime[session->used]; gcry_mpi_t s; gcry_mpi_t s_prime; unsigned int i; count = session->used; // due to the introduced static offset S, we now also have to remove this // from the E(a_pi)(+)E(-b_pi-r_pi) and E(a_qi)(+)E(-r_qi) twice each, // the result is E((S + a_pi) + (S -b_pi-r_pi)) and E(S + a_qi + S - r_qi) for (i = 0; i < count; i++) { GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey, &session->r[i], r[i]); gcry_mpi_sub (r[i], r[i], my_offset); gcry_mpi_sub (r[i], r[i], my_offset); GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey, &session->r_prime[i], r_prime[i]); gcry_mpi_sub (r_prime[i], r_prime[i], my_offset); gcry_mpi_sub (r_prime[i], r_prime[i], my_offset); } // calculate t = sum(ai) t = compute_square_sum (session->a, count); // calculate U u = gcry_mpi_new (0); tmp = compute_square_sum (r, count); gcry_mpi_sub (u, u, tmp); gcry_mpi_release (tmp); //calculate U' u_prime = gcry_mpi_new (0); tmp = compute_square_sum (r_prime, count); gcry_mpi_sub (u_prime, u_prime, tmp); GNUNET_assert (p = gcry_mpi_new (0)); GNUNET_assert (p_prime = gcry_mpi_new (0)); GNUNET_assert (s = gcry_mpi_new (0)); GNUNET_assert (s_prime = gcry_mpi_new (0)); // compute P GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey, session->s, s); GNUNET_CRYPTO_paillier_decrypt (&my_privkey, &my_pubkey, session->s_prime, s_prime); // compute P gcry_mpi_add (p, s, t); gcry_mpi_add (p, p, u); // compute P' gcry_mpi_add (p_prime, s_prime, t); gcry_mpi_add (p_prime, p_prime, u_prime); gcry_mpi_release (t); gcry_mpi_release (u); gcry_mpi_release (u_prime); gcry_mpi_release (s); gcry_mpi_release (s_prime); // compute product gcry_mpi_sub (p, p, p_prime); gcry_mpi_release (p_prime); tmp = gcry_mpi_set_ui (tmp, 2); gcry_mpi_div (p, NULL, p, tmp, 0); gcry_mpi_release (tmp); for (i = 0; i < count; i++){ gcry_mpi_release (session->a[i]); gcry_mpi_release (r[i]); gcry_mpi_release (r_prime[i]); } GNUNET_free (session->a); session->a = NULL; GNUNET_free (session->s); session->s = NULL; GNUNET_free (session->s_prime); session->s_prime = NULL; GNUNET_free (session->r); session->r = NULL; GNUNET_free (session->r_prime); session->r_prime = NULL; return p; } /** * Handle a multipart-chunk of a request from another service to calculate a scalarproduct with us. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handle_service_request_multipart (void *cls, struct GNUNET_MESH_Channel * channel, void **channel_ctx, const struct GNUNET_MessageHeader * message) { struct ServiceSession * session; const struct GNUNET_SCALARPRODUCT_multipart_message * msg = (const struct GNUNET_SCALARPRODUCT_multipart_message *) message; struct GNUNET_CRYPTO_PaillierCiphertext *payload; uint32_t used_elements; uint32_t contained_elements = 0; uint32_t msg_length; // are we in the correct state? session = (struct ServiceSession *) * channel_ctx; if ((BOB != session->role) || (WAITING_FOR_MULTIPART_TRANSMISSION != session->state)) { goto except; } // shorter than minimum? if (ntohs (msg->header.size) <= sizeof (struct GNUNET_SCALARPRODUCT_multipart_message)) { goto except; } used_elements = session->used; contained_elements = ntohl (msg->multipart_element_count); msg_length = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message) + contained_elements * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext); //sanity check if ((ntohs (msg->header.size) != msg_length) || (used_elements < contained_elements + session->transferred)) { goto except; } payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1]; if (contained_elements != 0) { // Convert each vector element to MPI_value memcpy(&session->e_a[session->transferred], payload, sizeof(struct GNUNET_CRYPTO_PaillierCiphertext) * contained_elements); session->transferred += contained_elements; if (session->transferred == used_elements) { // single part finished session->state = SERVICE_REQUEST_RECEIVED; if (session->response) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s and a matching element set, processing.\n"), GNUNET_h2s (&session->key)); if (GNUNET_OK != compute_service_response (session, session->response)) { //something went wrong, remove it again... goto except; } } else GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s without a matching element set, queueing.\n"), GNUNET_h2s (&session->key)); } else { // multipart message } } return GNUNET_OK; except: // and notify our client-session that we could not complete the session GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session); if (session->response) // we just found the responder session in this queue session->response->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, session->response); free_session_variables (session); GNUNET_free (session); return GNUNET_SYSERR; } /** * Handle a request from another service to calculate a scalarproduct with us. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handle_service_request (void *cls, struct GNUNET_MESH_Channel * channel, void **channel_ctx, const struct GNUNET_MessageHeader * message) { struct ServiceSession * session; const struct GNUNET_SCALARPRODUCT_service_request * msg = (const struct GNUNET_SCALARPRODUCT_service_request *) message; uint32_t mask_length; struct GNUNET_CRYPTO_PaillierCiphertext *payload; uint32_t used_elements; uint32_t contained_elements = 0; uint32_t element_count; uint32_t msg_length; unsigned char * current; enum SessionState needed_state; session = (struct ServiceSession *) * channel_ctx; if (WAITING_FOR_SERVICE_REQUEST != session->state) { goto invalid_msg; } // Check if message was sent by me, which would be bad! if (!memcmp (&session->peer, &me, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_free (session); GNUNET_break (0); return GNUNET_SYSERR; } // shorter than expected? if (ntohs (msg->header.size) < sizeof (struct GNUNET_SCALARPRODUCT_service_request)) { GNUNET_free (session); GNUNET_break_op (0); return GNUNET_SYSERR; } mask_length = ntohl (msg->mask_length); used_elements = ntohl (msg->total_element_count); contained_elements = ntohl (msg->contained_element_count); element_count = ntohl (msg->element_count); msg_length = sizeof (struct GNUNET_SCALARPRODUCT_service_request) + mask_length + sizeof(struct GNUNET_CRYPTO_PaillierPublicKey) + contained_elements * sizeof(struct GNUNET_CRYPTO_PaillierCiphertext); //sanity check: is the message as long as the message_count fields suggests? if ((ntohs (msg->header.size) != msg_length) || (element_count < used_elements) || (used_elements < contained_elements) || (0 == used_elements) || (mask_length != (element_count / 8 + ((element_count % 8) ? 1 : 0)))) { GNUNET_free (session); GNUNET_break_op (0); return GNUNET_SYSERR; } if (find_matching_session (from_service_tail, &msg->key, element_count, NULL, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Got message with duplicate session key (`%s'), ignoring service request.\n"), (const char *) &(msg->key)); GNUNET_free (session); return GNUNET_SYSERR; } session->total = element_count; session->used = used_elements; session->transferred = contained_elements; session->channel = channel; // session key memcpy (&session->key, &msg->key, sizeof (struct GNUNET_HashCode)); current = (unsigned char *) &msg[1]; //preserve the mask, we will need that later on session->mask = GNUNET_malloc (mask_length); memcpy (session->mask, current, mask_length); //the public key current += mask_length; //convert the publickey to sexp session->remote_pubkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_PaillierPublicKey)); memcpy(session->remote_pubkey, current, sizeof(struct GNUNET_CRYPTO_PaillierPublicKey)); current += sizeof(struct GNUNET_CRYPTO_PaillierPublicKey); payload = (struct GNUNET_CRYPTO_PaillierCiphertext*) current; //check if service queue contains a matching request needed_state = CLIENT_RESPONSE_RECEIVED; session->response = find_matching_session (from_client_tail, &session->key, session->total, &needed_state, NULL); session->state = WAITING_FOR_MULTIPART_TRANSMISSION; GNUNET_CONTAINER_DLL_insert (from_service_head, from_service_tail, session); session->e_a = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * used_elements); if (contained_elements != 0) { // Convert each vector element to MPI_value memcpy(session->e_a, payload, sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * used_elements); if (contained_elements == used_elements) { // single part finished session->state = SERVICE_REQUEST_RECEIVED; if (session->response) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s and a matching element set, processing.\n"), GNUNET_h2s (&session->key)); if (GNUNET_OK != compute_service_response (session, session->response)) { //something went wrong, remove it again... goto invalid_msg; } } else GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Got session with key %s without a matching element set, queueing.\n"), GNUNET_h2s (&session->key)); } else { // multipart message } } return GNUNET_OK; invalid_msg: GNUNET_break_op (0); if ((NULL != session->next) || (NULL != session->prev) || (from_service_head == session)) GNUNET_CONTAINER_DLL_remove (from_service_head, from_service_tail, session); // and notify our client-session that we could not complete the session if (session->response) // we just found the responder session in this queue session->response->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_end_notification, session->response); free_session_variables (session); return GNUNET_SYSERR; } /** * Handle a multipart chunk of a response we got from another service we wanted to calculate a scalarproduct with. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static int handle_service_response_multipart (void *cls, struct GNUNET_MESH_Channel * channel, void **channel_ctx, const struct GNUNET_MessageHeader * message) { struct ServiceSession * session; const struct GNUNET_SCALARPRODUCT_multipart_message * msg = (const struct GNUNET_SCALARPRODUCT_multipart_message *) message; struct GNUNET_CRYPTO_PaillierCiphertext * payload; size_t i; uint32_t contained = 0; size_t msg_size; size_t required_size; GNUNET_assert (NULL != message); // are we in the correct state? session = (struct ServiceSession *) * channel_ctx; if ((ALICE != session->role) || (WAITING_FOR_MULTIPART_TRANSMISSION != session->state)) { goto invalid_msg; } msg_size = ntohs (msg->header.size); required_size = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); // shorter than minimum? if (required_size > msg_size) { goto invalid_msg; } contained = ntohl (msg->multipart_element_count); required_size = sizeof (struct GNUNET_SCALARPRODUCT_multipart_message) + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); //sanity check: is the message as long as the message_count fields suggests? if ((required_size != msg_size) || (session->used < session->transferred + contained)) { goto invalid_msg; } payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1]; // Convert each k[][perm] to its MPI_value for (i = 0; i < contained; i++) { memcpy(&session->r[session->transferred+i], &payload[2*i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); memcpy(&session->r_prime[session->transferred+i], &payload[2*i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); } session->transferred += contained; if (session->transferred != session->used) return GNUNET_OK; session->state = SERVICE_RESPONSE_RECEIVED; session->product = compute_scalar_product (session); //never NULL invalid_msg: GNUNET_break_op (NULL != session->product); //NULL if we never tried to compute it... // send message with product to client if (ALICE == session->role) { session->state = FINALIZED; session->channel = NULL; session->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_response, session); } // the channel has done its job, terminate our connection and the channel // the peer will be notified that the channel was destroyed via channel_destruction_handler // just close the connection, as recommended by Christian return GNUNET_SYSERR; } /** * Handle a response we got from another service we wanted to calculate a scalarproduct with. * * @param cls closure (set from #GNUNET_MESH_connect) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (we are done) */ static int handle_service_response (void *cls, struct GNUNET_MESH_Channel * channel, void **channel_ctx, const struct GNUNET_MessageHeader * message) { struct ServiceSession * session; const struct GNUNET_SCALARPRODUCT_service_response * msg = (const struct GNUNET_SCALARPRODUCT_service_response *) message; struct GNUNET_CRYPTO_PaillierCiphertext * payload; size_t i; uint32_t contained = 0; size_t msg_size; size_t required_size; GNUNET_assert (NULL != message); session = (struct ServiceSession *) * channel_ctx; // are we in the correct state? if (WAITING_FOR_SERVICE_RESPONSE != session->state) { goto invalid_msg; } //we need at least a full message without elements attached msg_size = ntohs (msg->header.size); required_size = sizeof (struct GNUNET_SCALARPRODUCT_service_response) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); if (required_size > msg_size) { goto invalid_msg; } contained = ntohl (msg->contained_element_count); required_size = sizeof (struct GNUNET_SCALARPRODUCT_service_response) + 2 * contained * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) + 2 * sizeof (struct GNUNET_CRYPTO_PaillierCiphertext); //sanity check: is the message as long as the message_count fields suggests? if ((msg_size != required_size) || (session->used < contained)) { goto invalid_msg; } session->state = WAITING_FOR_MULTIPART_TRANSMISSION; session->transferred = contained; //convert s payload = (struct GNUNET_CRYPTO_PaillierCiphertext *) &msg[1]; session->s = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)); session->s_prime = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)); memcpy(session->s,&payload[0],sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)); memcpy(session->s_prime,&payload[1],sizeof(struct GNUNET_CRYPTO_PaillierCiphertext)); session->r = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * session->used); session->r_prime = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_PaillierCiphertext) * session->used); // Convert each k[][perm] to its MPI_value for (i = 0; i < contained; i++) { memcpy(&session->r[i], &payload[2 + 2*i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); memcpy(&session->r_prime[i], &payload[3 + 2*i], sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)); } if (session->transferred != session->used) return GNUNET_OK; //wait for the other multipart chunks session->state = SERVICE_RESPONSE_RECEIVED; session->product = compute_scalar_product (session); //never NULL invalid_msg: GNUNET_break_op (NULL != session->product); // send message with product to client if (ALICE == session->role) { session->state = FINALIZED; session->channel = NULL; session->client_notification_task = GNUNET_SCHEDULER_add_now (&prepare_client_response, session); } // the channel has done its job, terminate our connection and the channel // the peer will be notified that the channel was destroyed via channel_destruction_handler // just close the connection, as recommended by Christian return GNUNET_SYSERR; } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ServiceSession * session; GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Shutting down, initiating cleanup.\n")); do_shutdown = GNUNET_YES; // terminate all owned open channels. for (session = from_client_head; NULL != session; session = session->next) { if ((FINALIZED != session->state) && (NULL != session->channel)) { GNUNET_MESH_channel_destroy (session->channel); session->channel = NULL; } if (GNUNET_SCHEDULER_NO_TASK != session->client_notification_task) { GNUNET_SCHEDULER_cancel (session->client_notification_task); session->client_notification_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != session->service_request_task) { GNUNET_SCHEDULER_cancel (session->service_request_task); session->service_request_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != session->client) { GNUNET_SERVER_client_disconnect (session->client); session->client = NULL; } } for (session = from_service_head; NULL != session; session = session->next) if (NULL != session->channel) { GNUNET_MESH_channel_destroy (session->channel); session->channel = NULL; } if (my_mesh) { GNUNET_MESH_disconnect (my_mesh); my_mesh = NULL; } } /** * Initialization of the program and message handlers * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler server_handlers[] = { {&handle_client_request, NULL, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE, 0}, {&handle_client_request, NULL, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB, 0}, {NULL, NULL, 0, 0} }; static const struct GNUNET_MESH_MessageHandler mesh_handlers[] = { { &handle_service_request, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB, 0}, { &handle_service_request_multipart, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_ALICE_TO_BOB_MULTIPART, 0}, { &handle_service_response, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE, 0}, { &handle_service_response_multipart, GNUNET_MESSAGE_TYPE_SCALARPRODUCT_BOB_TO_ALICE_MULTIPART, 0}, {NULL, 0, 0} }; static const uint32_t ports[] = { GNUNET_APPLICATION_TYPE_SCALARPRODUCT, 0 }; //generate private/public key set GNUNET_CRYPTO_paillier_create (&my_pubkey, &my_privkey); // offset has to be sufficiently small to allow computation of: // m1+m2 mod n == (S + a) + (S + b) mod n, // if we have more complex operations, this factor needs to be lowered my_offset = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS / 3); gcry_mpi_set_bit (my_offset, GNUNET_CRYPTO_PAILLIER_BITS / 3); // register server callbacks and disconnect handler GNUNET_SERVER_add_handlers (server, server_handlers); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); GNUNET_break (GNUNET_OK == GNUNET_CRYPTO_get_peer_identity (c, &me)); my_mesh = GNUNET_MESH_connect (c, NULL, &channel_incoming_handler, &channel_destruction_handler, mesh_handlers, ports); if (!my_mesh) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Connect to MESH failed\n")); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Mesh initialized\n")); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for the scalarproduct service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "scalarproduct", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-scalarproduct.c */ gnunet-0.10.1/src/scalarproduct/scalarproduct_api.c0000644000175000017500000004225112261236532017320 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file scalarproduct/scalarproduct_api.c * @brief API for the scalarproduct * @author Christian Fuchs * @author Gaurav Kukreja * */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_scalarproduct_service.h" #include "gnunet_protocols.h" #include "scalarproduct.h" #define LOG(kind,...) GNUNET_log_from (kind, "scalarproduct-api",__VA_ARGS__) /************************************************************** *** Datatype Declarations ********** **************************************************************/ /** * the abstraction function for our internal callback */ typedef void (*GNUNET_SCALARPRODUCT_ResponseMessageHandler) (void *cls, const struct GNUNET_MessageHeader *msg, enum GNUNET_SCALARPRODUCT_ResponseStatus status); /** * Entry in the request queue per client */ struct GNUNET_SCALARPRODUCT_ComputationHandle { /** * This is a linked list. */ struct GNUNET_SCALARPRODUCT_ComputationHandle *next; /** * This is a linked list. */ struct GNUNET_SCALARPRODUCT_ComputationHandle *prev; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Current connection to the scalarproduct service. */ struct GNUNET_CLIENT_Connection *client; /** * Handle for statistics. */ struct GNUNET_STATISTICS_Handle *stats; /** * The shared session key identifying this computation */ struct GNUNET_HashCode key; /** * Current transmit handle. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Size of the message */ uint16_t message_size; /** * Message to be sent to the scalarproduct service */ struct GNUNET_SCALARPRODUCT_client_request * msg; /** * The msg handler callback */ union { /** * Function to call after transmission of the request. */ GNUNET_SCALARPRODUCT_ContinuationWithStatus cont_status; /** * Function to call after transmission of the request. */ GNUNET_SCALARPRODUCT_DatumProcessor cont_datum; }; /** * Closure for 'cont'. */ void *cont_cls; /** * Response Processor for response from the service. This function calls the * continuation function provided by the client. */ GNUNET_SCALARPRODUCT_ResponseMessageHandler response_proc; }; /************************************************************** *** Global Variables ********** **************************************************************/ /** * Head of the active sessions queue */ static struct GNUNET_SCALARPRODUCT_ComputationHandle *head; /** * Tail of the active sessions queue */ static struct GNUNET_SCALARPRODUCT_ComputationHandle *tail; /************************************************************** *** Function Declarations ********** **************************************************************/ void GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle * h); /************************************************************** *** Static Function Declarations ********** **************************************************************/ /** * Handles the STATUS received from the service for a response, does not contain a payload * * @param cls our Handle * @param msg Pointer to the response received * @param status the condition the request was terminated with (eg: disconnect) */ static void process_status_message (void *cls, const struct GNUNET_MessageHeader *msg, enum GNUNET_SCALARPRODUCT_ResponseStatus status) { struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls; qe->cont_status (qe->cont_cls, status); } /** * Handles the RESULT received from the service for a request, should contain a result MPI value * * @param cls our Handle * @param msg Pointer to the response received * @param status the condition the request was terminated with (eg: disconnect) */ static void process_result_message (void *cls, const struct GNUNET_MessageHeader *msg, enum GNUNET_SCALARPRODUCT_ResponseStatus status) { struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls; const struct GNUNET_SCALARPRODUCT_client_response *message = (const struct GNUNET_SCALARPRODUCT_client_response *) msg; gcry_mpi_t result = NULL; gcry_error_t rc; if (GNUNET_SCALARPRODUCT_Status_Success == status) { size_t product_len = ntohl (message->product_length); result = gcry_mpi_new (0); if (0 < product_len) { gcry_mpi_t num; size_t read = 0; if (0 != (rc = gcry_mpi_scan (&num, GCRYMPI_FMT_STD, &message[1], product_len, &read))) { LOG_GCRY(GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); gcry_mpi_release (result); result = NULL; status = GNUNET_SCALARPRODUCT_Status_InvalidResponse; } else { if (0 < message->range) gcry_mpi_add (result, result, num); else if (0 > message->range) gcry_mpi_sub (result, result, num); gcry_mpi_release (num); } } } qe->cont_datum (qe->cont_cls, status, result); } /** * Called when a response is received from the service. After basic check, the * handler in qe->response_proc is called. This functions handles the response * to the client which used the API. * * @param cls Pointer to the Master Context * @param msg Pointer to the data received in response */ static void receive_cb (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls; const struct GNUNET_SCALARPRODUCT_client_response *message = (const struct GNUNET_SCALARPRODUCT_client_response *) msg; enum GNUNET_SCALARPRODUCT_ResponseStatus status = GNUNET_SCALARPRODUCT_Status_InvalidResponse; if (NULL == msg) { LOG (GNUNET_ERROR_TYPE_WARNING, "Disconnected by Service.\n"); status = GNUNET_SCALARPRODUCT_Status_ServiceDisconnected; } else if (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_SERVICE_TO_CLIENT != ntohs (msg->type)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Invalid message type received\n"); } else if (0 < ntohl (message->product_length) || (0 == message->range)) { // response for the responder client, successful GNUNET_STATISTICS_update (qe->stats, gettext_noop ("# SUC responder result messages received"), 1, GNUNET_NO); status = GNUNET_SCALARPRODUCT_Status_Success; } if (qe->cont_datum != NULL) qe->response_proc (qe, msg, status); GNUNET_CONTAINER_DLL_remove (head, tail, qe); GNUNET_free (qe); } /** * Transmits the request to the VectorProduct Service * * @param cls Closure * @param size Size of the buffer * @param buf Pointer to the buffer * * @return Size of the message sent */ static size_t transmit_request (void *cls, size_t size, void *buf) { struct GNUNET_SCALARPRODUCT_ComputationHandle *qe = cls; if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to SCALARPRODUCT.\n"); GNUNET_STATISTICS_update (qe->stats, gettext_noop ("# transmission request failures"), 1, GNUNET_NO); // notify caller about the error, done here. if (qe->cont_datum != NULL) qe->response_proc (qe, NULL, GNUNET_SCALARPRODUCT_Status_Failure); GNUNET_SCALARPRODUCT_cancel (cls); return 0; } memcpy (buf, qe->msg, size); GNUNET_free (qe->msg); qe->msg = NULL; qe->th = NULL; GNUNET_CLIENT_receive (qe->client, &receive_cb, qe, GNUNET_TIME_UNIT_FOREVER_REL); #if INSANE_STATISTICS GNUNET_STATISTICS_update (qe->stats, gettext_noop ("# bytes sent to scalarproduct"), 1, GNUNET_NO); #endif return size; } /************************************************************** *** API ********** **************************************************************/ /** * Used by Bob's client to cooperate with Alice, * * @param cfg the gnunet configuration handle * @param key Session key unique to the requesting client * @param elements Array of elements of the vector * @param element_count Number of elements in the vector * @param cont Callback function * @param cont_cls Closure for the callback function * * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * GNUNET_SCALARPRODUCT_response (const struct GNUNET_CONFIGURATION_Handle * cfg, const struct GNUNET_HashCode * key, const int32_t * elements, uint32_t element_count, GNUNET_SCALARPRODUCT_ContinuationWithStatus cont, void * cont_cls) { struct GNUNET_SCALARPRODUCT_ComputationHandle *h; struct GNUNET_SCALARPRODUCT_client_request *msg; int32_t * vector; uint16_t size; uint64_t i; GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_SCALARPRODUCT_client_request) + element_count * sizeof (int32_t)); h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle); h->client = GNUNET_CLIENT_connect ("scalarproduct", cfg); if (!h->client) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to connect to the scalarproduct service\n")); GNUNET_free (h); return NULL; } h->stats = GNUNET_STATISTICS_create ("scalarproduct-api", cfg); if (!h->stats) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to send a message to the statistics service\n")); GNUNET_CLIENT_disconnect (h->client); GNUNET_free (h); return NULL; } size = sizeof (struct GNUNET_SCALARPRODUCT_client_request) + element_count * sizeof (int32_t); h->cont_status = cont; h->cont_cls = cont_cls; h->response_proc = &process_status_message; h->cfg = cfg; memcpy (&h->key, key, sizeof (struct GNUNET_HashCode)); msg = (struct GNUNET_SCALARPRODUCT_client_request*) GNUNET_malloc (size); h->msg = msg; msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_BOB); msg->element_count = htonl (element_count); vector = (int32_t*) & msg[1]; // copy each element over to the message for (i = 0; i < element_count; i++) vector[i] = htonl (elements[i]); memcpy (&msg->key, key, sizeof (struct GNUNET_HashCode)); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, // retry is OK in the initial stage &transmit_request, h); if (!h->th) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to send a message to the scalarproduct service\n")); GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES); GNUNET_CLIENT_disconnect (h->client); GNUNET_free (h->msg); GNUNET_free (h); return NULL; } GNUNET_CONTAINER_DLL_insert (head, tail, h); return h; } /** * Request by Alice's client for computing a scalar product * * @param cfg the gnunet configuration handle * @param key Session key should be unique to the requesting client * @param peer PeerID of the other peer * @param elements Array of elements of the vector * @param element_count Number of elements in the vector * @param mask Array of the mask * @param mask_bytes number of bytes in the mask * @param cont Callback function * @param cont_cls Closure for the callback function * * @return a new handle for this computation */ struct GNUNET_SCALARPRODUCT_ComputationHandle * GNUNET_SCALARPRODUCT_request (const struct GNUNET_CONFIGURATION_Handle * cfg, const struct GNUNET_HashCode * key, const struct GNUNET_PeerIdentity *peer, const int32_t * elements, uint32_t element_count, const unsigned char * mask, uint32_t mask_bytes, GNUNET_SCALARPRODUCT_DatumProcessor cont, void * cont_cls) { struct GNUNET_SCALARPRODUCT_ComputationHandle *h; struct GNUNET_SCALARPRODUCT_client_request *msg; int32_t * vector; uint16_t size; uint64_t i; GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_SCALARPRODUCT_client_request) +element_count * sizeof (int32_t) + mask_bytes); h = GNUNET_new (struct GNUNET_SCALARPRODUCT_ComputationHandle); h->client = GNUNET_CLIENT_connect ("scalarproduct", cfg); if (!h->client) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to connect to the scalarproduct service\n")); GNUNET_free (h); return NULL; } h->stats = GNUNET_STATISTICS_create ("scalarproduct-api", cfg); if (!h->stats) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to send a message to the statistics service\n")); GNUNET_CLIENT_disconnect (h->client); GNUNET_free (h); return NULL; } size = sizeof (struct GNUNET_SCALARPRODUCT_client_request) + element_count * sizeof (int32_t) + mask_bytes; h->cont_datum = cont; h->cont_cls = cont_cls; h->response_proc = &process_result_message; h->cfg = cfg; memcpy (&h->key, key, sizeof (struct GNUNET_HashCode)); msg = (struct GNUNET_SCALARPRODUCT_client_request*) GNUNET_malloc (size); h->msg = msg; msg->header.size = htons (size); msg->header.type = htons (GNUNET_MESSAGE_TYPE_SCALARPRODUCT_CLIENT_TO_ALICE); msg->element_count = htonl (element_count); msg->mask_length = htonl (mask_bytes); vector = (int32_t*) & msg[1]; // copy each element over to the message for (i = 0; i < element_count; i++) vector[i] = htonl (elements[i]); memcpy (&msg->peer, peer, sizeof (struct GNUNET_PeerIdentity)); memcpy (&msg->key, key, sizeof (struct GNUNET_HashCode)); memcpy (&vector[element_count], mask, mask_bytes); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, // retry is OK in the initial stage &transmit_request, h); if (!h->th) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Failed to send a message to the scalarproduct service\n")); GNUNET_STATISTICS_destroy (h->stats, GNUNET_YES); GNUNET_CLIENT_disconnect (h->client); GNUNET_free (h->msg); GNUNET_free (h); return NULL; } GNUNET_CONTAINER_DLL_insert (head, tail, h); return h; } /** * Cancel an ongoing computation or revoke our collaboration offer. * Closes the connection to the service * * @param h computation handle to terminate */ void GNUNET_SCALARPRODUCT_cancel (struct GNUNET_SCALARPRODUCT_ComputationHandle * h) { struct GNUNET_SCALARPRODUCT_ComputationHandle * qe; for (qe = head; head != NULL; qe = head) { if (qe == h) { GNUNET_CONTAINER_DLL_remove (head, tail, qe); if (NULL != qe->th) GNUNET_CLIENT_notify_transmit_ready_cancel (qe->th); GNUNET_CLIENT_disconnect (qe->client); GNUNET_STATISTICS_destroy (qe->stats, GNUNET_YES); GNUNET_free_non_null (qe->msg); GNUNET_free (qe); break; } } } /** * Cancel ALL ongoing computation or revoke our collaboration offer. * Closes ALL connections to the service */ void GNUNET_SCALARPRODUCT_disconnect () { struct GNUNET_SCALARPRODUCT_ComputationHandle * qe; LOG (GNUNET_ERROR_TYPE_INFO, "Disconnecting from VectorProduct\n"); for (qe = head; head != NULL; qe = head) { GNUNET_CONTAINER_DLL_remove (head, tail, qe); if (NULL != qe->th) GNUNET_CLIENT_notify_transmit_ready_cancel (qe->th); GNUNET_CLIENT_disconnect (qe->client); GNUNET_STATISTICS_destroy (qe->stats, GNUNET_YES); GNUNET_free_non_null (qe->msg); GNUNET_free (qe); } } /* end of scalarproduct_api.c */ gnunet-0.10.1/src/scalarproduct/scalarproduct.h0000644000175000017500000001304512307312000016455 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file scalarproduct.h * @brief Scalar Product Message Types * @author Christian M. Fuchs * * Created on September 2, 2013, 3:43 PM */ #ifndef SCALARPRODUCT_H #define SCALARPRODUCT_H #ifdef __cplusplus extern "C" { #endif /////////////////////////////////////////////////////////////////////////////// // Defines /////////////////////////////////////////////////////////////////////////////// /** * Maximum count of elements we can put into a multipart message */ #define MULTIPART_ELEMENT_CAPACITY ((GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - sizeof (struct GNUNET_SCALARPRODUCT_multipart_message)) / sizeof (struct GNUNET_CRYPTO_PaillierCiphertext)) /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by gcry_strerror(rc). */ #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0) /////////////////////////////////////////////////////////////////////////////// // Scalar Product Message Types /////////////////////////////////////////////////////////////////////////////// /** * Message type passed from client to service * to initiate a request or responder role */ struct GNUNET_SCALARPRODUCT_client_request { /** * GNUNET message header */ struct GNUNET_MessageHeader header; /** * how many elements the vector in payload contains */ uint32_t element_count GNUNET_PACKED; /** * how many bytes the mask has */ uint32_t mask_length GNUNET_PACKED; /** * the transaction/session key used to identify a session */ struct GNUNET_HashCode key; /** * the identity of a remote peer we want to communicate with */ struct GNUNET_PeerIdentity peer; /** * followed by long vector[element_count] | [unsigned char mask[mask_bytes]] */ }; /** * Message type passed from requesting service Alice to responding service Bob * to initiate a request and make bob participate in our protocol */ struct GNUNET_SCALARPRODUCT_service_request { /** * GNUNET message header */ struct GNUNET_MessageHeader header; /** * how many elements the total message including all multipart msgs contains */ uint32_t total_element_count GNUNET_PACKED; /** * how many elements are actually included after the mask was applied. */ uint32_t contained_element_count GNUNET_PACKED; /** * how many bytes the mask has */ uint32_t mask_length GNUNET_PACKED; /** * the transaction/session key used to identify a session */ struct GNUNET_HashCode key; /** * how many elements the vector in payload contains */ uint32_t element_count GNUNET_PACKED; /** * followed by mask | public_key | vector[used_element_count] */ }; /** * Multipart Message type passed between to supply additional elements for the peer */ struct GNUNET_SCALARPRODUCT_multipart_message { /** * GNUNET message header */ struct GNUNET_MessageHeader header; /** * how many elements we supply within this message */ uint32_t multipart_element_count GNUNET_PACKED; // followed by vector[multipart_element_count] or k[i][perm] }; /** * Message type passed from responding service Bob to responding service Alice * to complete a request and allow Alice to compute the result */ struct GNUNET_SCALARPRODUCT_service_response { /** * GNUNET message header */ struct GNUNET_MessageHeader header; /** * how many elements the session input had */ uint32_t total_element_count GNUNET_PACKED; /** * how many elements were included after the mask was applied including all multipart msgs. */ uint32_t used_element_count GNUNET_PACKED; /** * how many elements this individual message delivers */ uint32_t contained_element_count GNUNET_PACKED; /** * the transaction/session key used to identify a session */ struct GNUNET_HashCode key; /** * followed by s | s' | k[i][perm] */ }; /** * Message type passed from service client * to finalize a session as requester or responder */ struct GNUNET_SCALARPRODUCT_client_response { /** * GNUNET message header */ struct GNUNET_MessageHeader header; /** * 0 if no product attached */ uint32_t product_length GNUNET_PACKED; /** * the transaction/session key used to identify a session */ struct GNUNET_HashCode key; /** * the identity of a remote peer we want to communicate with */ struct GNUNET_PeerIdentity peer; /** * Workaround for libgcrypt: -1 if negative, 0 if zero, else 1 */ int8_t range; /** * followed by product of length product_length (or nothing) */ }; #ifdef __cplusplus } #endif #endif /* SCALARPRODUCT_H */ gnunet-0.10.1/src/scalarproduct/gnunet-scalarproduct.c0000644000175000017500000002736712267431203017776 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file scalarproduct/gnunet-scalarproduct.c * @brief scalarproduct client * @author Christian M. Fuchs */ #define GCRYPT_NO_DEPRECATED #include #include #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_scalarproduct_service.h" #include "gnunet_protocols.h" #include "scalarproduct.h" #define LOG(kind,...) GNUNET_log_from (kind, "gnunet-scalarproduct",__VA_ARGS__) #define INPUTSTRINGLENGTH 1024 /** * A primitive closure structure holding information about our session */ struct ScalarProductCallbackClosure { /** * the session key identifying this computation */ struct GNUNET_HashCode key; /** * PeerID we want to compute a scalar product with */ struct GNUNET_PeerIdentity peer; }; /** * Option -p: destination peer identity for checking message-ids with */ static char *input_peer_id; /** * Option -p: destination peer identity for checking message-ids with */ static char *input_key; /** * Option -e: vector to calculate a scalarproduct with */ static char *input_elements; /** * Option -m: message-ids to calculate a scalarproduct with */ static char *input_mask; /** * Global return value */ static int ret = -1; /** * Callback called if we are initiating a new computation session * * @param cls unused * @param status if our job was successfully processed */ static void responder_callback (void *cls, enum GNUNET_SCALARPRODUCT_ResponseStatus status) { struct ScalarProductCallbackClosure * closure = cls; switch (status) { case GNUNET_SCALARPRODUCT_Status_Success: ret = 0; LOG (GNUNET_ERROR_TYPE_INFO, "Session %s concluded.\n", GNUNET_h2s (&closure->key)); break; case GNUNET_SCALARPRODUCT_Status_InvalidResponse: LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: invalid response\n", GNUNET_h2s (&closure->key)); break; case GNUNET_SCALARPRODUCT_Status_Failure: LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: service failure\n", GNUNET_h2s (&closure->key)); break; case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected: LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: service disconnect!\n", GNUNET_h2s (&closure->key)); break; default: LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s failed: return code %d\n", GNUNET_h2s (&closure->key), status); } GNUNET_SCHEDULER_shutdown(); } /** * Callback called if we are initiating a new computation session * * @param cls unused * @param status if our job was successfully processed * @param result the result in gnu/gcry MPI format */ static void requester_callback (void *cls, enum GNUNET_SCALARPRODUCT_ResponseStatus status, gcry_mpi_t result) { struct ScalarProductCallbackClosure * closure = cls; unsigned char * buf; gcry_error_t rc; switch (status) { case GNUNET_SCALARPRODUCT_Status_Success: if (0 == (rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, result))) { ret = 0; printf ("%s", buf); } else LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_aprint", rc); break; case GNUNET_SCALARPRODUCT_Status_InvalidResponse: LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s with peer %s failed: invalid response received\n", GNUNET_h2s (&closure->key), GNUNET_i2s (&closure->peer)); break; case GNUNET_SCALARPRODUCT_Status_Failure: LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s with peer %s failed: API failure\n", GNUNET_h2s (&closure->key), GNUNET_i2s (&closure->peer)); break; case GNUNET_SCALARPRODUCT_Status_ServiceDisconnected: LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s with peer %s was disconnected from service.\n", GNUNET_h2s (&closure->key), GNUNET_i2s (&closure->peer)); break; default: LOG (GNUNET_ERROR_TYPE_ERROR, "Session %s with peer %s failed: return code %d\n", GNUNET_h2s (&closure->key), GNUNET_i2s (&closure->peer), status); } GNUNET_SCHEDULER_shutdown(); } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SCALARPRODUCT_disconnect (); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *begin = input_elements; char *end; int32_t element; int i; int32_t *elements; unsigned char *mask; uint32_t mask_bytes; uint32_t element_count = 0; struct ScalarProductCallbackClosure * closure; if (NULL == input_elements) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("You must specify at least one message ID to check!\n")); return; } if (NULL == input_key) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("This program needs a session identifier for comparing vectors.\n")); return; } if (1 > strnlen (input_key, sizeof (struct GNUNET_HashCode))) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Please give a session key for --input_key!\n")); return; } closure = GNUNET_new (struct ScalarProductCallbackClosure); GNUNET_CRYPTO_hash (input_key, strlen (input_key), &closure->key); if (input_peer_id && (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (input_peer_id, strlen (input_peer_id), (struct GNUNET_CRYPTO_EddsaPublicKey *) &closure->peer))) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Tried to set initiator mode, as peer ID was given. " "However, `%s' is not a valid peer identifier.\n"), input_peer_id); return; } /* Count input_elements_peer1, and put in elements_peer1 array */ do { // get the length of the current element for (end = begin; *end && *end != ','; end++); if (0 == *begin) { break; } else if (1 == sscanf (begin, "%" SCNd32 ",", &element)) { //element in the middle element_count++; begin = end; if (',' == *end) begin += 1; } else { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Could not convert `%s' to int32_t.\n"), begin); return; } } while (1); if (0 == element_count) { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Need elements to compute the vectorproduct, got none.\n")); return; } begin = input_elements; elements = GNUNET_malloc (sizeof (int32_t) * element_count); element_count = 0; /* Read input_elements_peer1, and put in elements_peer1 array */ do { // get the length of the current element for (end = begin; *end && *end != ','; end++); if (0 == *begin) { break; } else if (1 == sscanf (begin, "%" SCNd32 ",", &elements[element_count])) { //element in the middle element_count++; begin = end; if (',' == *end) begin += 1; } else { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Could not convert `%s' to int32_t.\n"), begin); return; } } while (1); mask_bytes = element_count / 8 + ( (element_count % 8) ? 1 : 0); mask = GNUNET_malloc ((element_count / 8) + 1); /* Read input_mask_peer1 and read in mask_peer1 array */ if ((NULL != input_peer_id) && (NULL != input_mask)) { begin = input_mask; unsigned short mask_count = 0; do { // get the length of the current element and replace , with null for (end = begin; *end && *end != ','; end++); if (1 == sscanf (begin, "%" SCNd32 ",", &element)) { //element in the middle begin = end + 1; } else if (*begin == 0) { break; } else { LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Could not convert `%s' to integer.\n"), begin); return; } if (element) mask[mask_count / 8] = mask[mask_count / 8] | 1 << (mask_count % 8); mask_count++; } while (mask_count < element_count); } else if (NULL != input_peer_id) for (i = 0; i <= mask_bytes; i++) mask[i] = UCHAR_MAX; // all 1's if (input_peer_id && (NULL == GNUNET_SCALARPRODUCT_request (cfg, &closure->key, &closure->peer, elements, element_count, mask, mask_bytes, &requester_callback, (void *) &closure))) { GNUNET_free (elements); GNUNET_free (mask); return; } if ((NULL == input_peer_id) && (NULL == GNUNET_SCALARPRODUCT_response (cfg, &closure->key, elements, element_count, &responder_callback, (void *) &closure))) { GNUNET_free (elements); GNUNET_free (mask); return; } GNUNET_free (elements); GNUNET_free (mask); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); ret = 0; } /** * The main function to the scalarproduct client. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'e', "elements", "\"val1,val2,...,valn\"", gettext_noop ("A comma separated list of elements to compare as vector with our remote peer."), 1, &GNUNET_GETOPT_set_string, &input_elements}, {'m', "mask", "\"0,1,...,maskn\"", gettext_noop ("A comma separated mask to select which elements should actually be compared."), 1, &GNUNET_GETOPT_set_string, &input_mask}, {'p', "peer", "PEERID", gettext_noop ("[Optional] peer to calculate our scalarproduct with. If this parameter is not given, the service will wait for a remote peer to compute the request."), 1, &GNUNET_GETOPT_set_string, &input_peer_id}, {'k', "key", "TRANSACTION_ID", gettext_noop ("Transaction ID shared with peer."), 1, &GNUNET_GETOPT_set_string, &input_key}, GNUNET_GETOPT_OPTION_END }; return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-scalarproduct", gettext_noop ("Calculate the Vectorproduct with a GNUnet peer."), options, &run, NULL)) ? ret : 1; } gnunet-0.10.1/src/scalarproduct/scalarproduct.conf.in0000644000175000017500000000023512227705277017604 00000000000000[scalarproduct] BINARY = gnunet-service-scalarproduct UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-scalarproduct.sock # PORT = 2106 @UNIXONLY@ PORT = 2087 gnunet-0.10.1/src/nse/0000755000175000017500000000000012320755625011455 500000000000000gnunet-0.10.1/src/nse/nse.conf.in0000644000175000017500000000247012320466615013437 00000000000000[nse] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2097 HOSTNAME = localhost BINARY = gnunet-service-nse ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-nse.unix UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES PROOFFILE = $GNUNET_DATA_HOME/nse/proof.dat # The directory where the NSE services logs timestamps everytime # a size estime flooding message is received # This option is only used for benchmarking, not in production. HISTOGRAM_DIR = $GNUNET_CACHE_HOME/nse/histogram # How 'slowly' should the proof-of-work be constructed (delay # between rounds); sane values between 0 and ~1000. # It should rarely make sense to change this value. # Only systems with slow CPUs where 5ms is a long time might # want it to be reduced. WORKDELAY = 5 ms # Note: changing any of the values below will make this peer # completely incompatible with other peers! # How often do peers exchange network size messages? # Note that all peers MUST use the same interval. # DO NOT CHANGE THIS VALUE, doing so will break the protocol! INTERVAL = 1 h # 2^22 hash operations take about 2-3h on a modern i7 (single-core) # for SCRYPT; with 2ms/op and 5ms workdelay, we can expect # the POW calculation to be done by a high-end peer in about 6h # DO NOT CHANGE THIS VALUE, doing so will break the protocol! WORKBITS = 22 gnunet-0.10.1/src/nse/test_nse_api.c0000644000175000017500000000576412225777502014234 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nse/test_nse_api.c * @brief testcase for nse_api.c */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_nse_service.h" #include "gnunet_testing_lib.h" static struct GNUNET_NSE_Handle *h; static GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Signature of the main function of a task. * * @param cls closure * @param tc context information (why was this task triggered now) */ static void end_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (h != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from NSE service.\n"); GNUNET_NSE_disconnect (h); } } /** * Callback to call when network size estimate is updated. * * @param cls unused * @param timestamp time when the estimate was received from the server (or created by the server) * @param estimate the value of the current network size estimate * @param std_dev standard deviation (rounded down to nearest integer) * of the size estimation values seen * */ static void check_nse_message (void *cls, struct GNUNET_TIME_Absolute timestamp, double estimate, double std_dev) { int *ok = cls; FPRINTF (stderr, "Received NSE message, estimate %f, standard deviation %f.\n", estimate, std_dev); /* Fantastic check below. Expect NaN, the only thing not equal to itself. */ (*ok) = 0; if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); die_task = GNUNET_SCHEDULER_add_now (&end_test, NULL); } static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 1), &end_test, NULL); h = GNUNET_NSE_connect (cfg, &check_nse_message, cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to NSE service.\n"); GNUNET_assert (h != NULL); } int main (int argc, char *argv[]) { int ok = 1; if (0 != GNUNET_TESTING_peer_run ("test_nse_api", "test_nse.conf", &run, &ok)) return 1; return ok; } /* end of test_nse_api.c */ gnunet-0.10.1/src/nse/gnunet-nse.c0000644000175000017500000001071712320530515013617 00000000000000/* This file is part of GNUnet (C) 2008--2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nse/gnunet-nse.c * @brief Program to display network size estimates from the NSE service * @author Sree Harsha Totakura */ #include "platform.h" #include "gnunet_nse_service.h" /** * Handle to our configuration */ static struct GNUNET_CONFIGURATION_Handle *cfg; /** * The handle to the NSE service */ static struct GNUNET_NSE_Handle *nse; /** * The handle to test if NSE service is running or not */ static struct GNUNET_CLIENT_TestHandle *test; /** * Shutdown task */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * The program status; 0 for success. */ static int status; /** * Task to shutdown and clean up all state * * @param cls NULL * @param tc the scheduler task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != test) GNUNET_CLIENT_service_test_cancel (test); if (NULL != nse) GNUNET_NSE_disconnect (nse); if (NULL != cfg) GNUNET_CONFIGURATION_destroy (cfg); } /** * Callback to call when network size estimate is updated. * * @param cls NULL * @param timestamp server timestamp * @param estimate the value of the current network size estimate * @param std_dev standard deviation (rounded down to nearest integer) * of the size estimation values seen */ static void handle_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, double estimate, double std_dev) { FPRINTF (stdout, "%llu %f %f %f\n", (unsigned long long) timestamp.abs_value_us, GNUNET_NSE_log_estimate_to_n (estimate), estimate, std_dev); } /** * Function called with the result on the service test for the NSE service * * @param cls NULL * @param result #GNUNET_YES if the service is running, * #GNUNET_NO if the service is not running * #GNUNET_SYSERR if the configuration is invalid */ static void nse_test_result (void *cls, int result) { test = NULL; switch (result) { case GNUNET_YES: nse = GNUNET_NSE_connect (cfg, &handle_estimate, NULL); status = 0; break; case GNUNET_NO: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("NSE service is not running\n")); GNUNET_SCHEDULER_shutdown (); return; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Error while checking if NSE service is running or not\n")); GNUNET_SCHEDULER_shutdown (); return; } } /** * Actual main function that runs the emulation. * * @param cls unused * @param args remaining args, unused * @param cfgfile name of the configuration * @param cfg configuration handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *_cfg) { cfg = GNUNET_CONFIGURATION_dup (_cfg); test = GNUNET_CLIENT_service_test ("nse", cfg, GNUNET_TIME_UNIT_SECONDS, nse_test_result, NULL); shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, NULL); } /** * Main function. * * @return 0 on success */ int main (int argc, char *const *argv) { static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; status = 1; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "gnunet-nse", gettext_noop ("Show network size estimates from NSE service."), options, &run, NULL)) return 2; return status; } gnunet-0.10.1/src/nse/nse_api.c0000644000175000017500000001642112225777502013165 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nse/nse_api.c * @brief api to get information from the network size estimation service * @author Nathan Evans */ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_arm_service.h" #include "gnunet_hello_lib.h" #include "gnunet_protocols.h" #include "gnunet_util_lib.h" #include "gnunet_nse_service.h" #include "nse.h" #define LOG(kind,...) GNUNET_log_from (kind, "nse-api",__VA_ARGS__) /** * Handle for talking with the NSE service. */ struct GNUNET_NSE_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Currently pending transmission request. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Task doing exponential back-off trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Time for next connect retry. */ struct GNUNET_TIME_Relative reconnect_delay; /** * Callback function to call when message is received. */ GNUNET_NSE_Callback recv_cb; /** * Closure to pass to @e recv_cb callback. */ void *recv_cb_cls; }; /** * Try again to connect to network size estimation service. * * @param cls the handle to the transport service * @param tc scheduler context */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void message_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_NSE_Handle *h = cls; const struct GNUNET_NSE_ClientMessage *client_msg; if (NULL == msg) { /* Error, timeout, death */ GNUNET_CLIENT_disconnect (h->client); h->client = NULL; h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); return; } if ((ntohs (msg->size) != sizeof (struct GNUNET_NSE_ClientMessage)) || (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_NSE_ESTIMATE)) { GNUNET_break (0); return; } client_msg = (const struct GNUNET_NSE_ClientMessage *) msg; h->recv_cb (h->recv_cb_cls, GNUNET_TIME_absolute_ntoh (client_msg->timestamp), GNUNET_ntoh_double (client_msg->size_estimate), GNUNET_ntoh_double (client_msg->std_deviation)); GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Reschedule a connect attempt to the service. * * @param h transport service to reconnect */ static void reschedule_connect (struct GNUNET_NSE_Handle *h) { GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task to reconnect to nse service in %s.\n", GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, GNUNET_YES)); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); } /** * Transmit START message to service. * * @param cls the `struct GNUNET_NSE_Handle *` * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to @a buf */ static size_t send_start (void *cls, size_t size, void *buf) { struct GNUNET_NSE_Handle *h = cls; struct GNUNET_MessageHeader *msg; h->th = NULL; if (NULL == buf) { /* Connect error... */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Error while trying to transmit `%s' request.\n", "START"); reschedule_connect (h); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "START"); GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); msg = (struct GNUNET_MessageHeader *) buf; msg->size = htons (sizeof (struct GNUNET_MessageHeader)); msg->type = htons (GNUNET_MESSAGE_TYPE_NSE_START); GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); return sizeof (struct GNUNET_MessageHeader); } /** * Try again to connect to network size estimation service. * * @param cls the `struct GNUNET_NSE_Handle *` * @param tc scheduler context */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_NSE_Handle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to network size estimation service.\n"); GNUNET_assert (NULL == h->client); h->client = GNUNET_CLIENT_connect ("nse", h->cfg); GNUNET_assert (NULL != h->client); GNUNET_assert (NULL == h->th); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_start, h); GNUNET_assert (NULL != h->th); } /** * Connect to the network size estimation service. * * @param cfg the configuration to use * @param func funtion to call with network size estimate * @param func_cls closure to pass to @a func * @return handle to use */ struct GNUNET_NSE_Handle * GNUNET_NSE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_NSE_Callback func, void *func_cls) { struct GNUNET_NSE_Handle *ret; GNUNET_assert (func != NULL); ret = GNUNET_new (struct GNUNET_NSE_Handle); ret->cfg = cfg; ret->recv_cb = func; ret->recv_cb_cls = func_cls; ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO; ret->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, ret); return ret; } /** * Disconnect from network size estimation service * * @param h handle to destroy */ void GNUNET_NSE_disconnect (struct GNUNET_NSE_Handle *h) { GNUNET_assert (NULL != h); if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } GNUNET_free (h); } /* end of nse_api.c */ gnunet-0.10.1/src/nse/test_nse.conf0000644000175000017500000000251312225230043014053 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-nse-multipeer/ [nse] PORT = 22353 UNIXPATH = $GNUNET_RUNTIME_DIR/test-nse-service-nse.unix BINARY = gnunet-service-nse #BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/nse/.libs/gnunet-service-nse #PREFIX = valgrind --leak-check=full --log-file=valgrind_nse.%p AUTOSTART = YES PROOFFILE = $GNUNET_TEST_HOME/proof.nse # Overriding network settings for faster testing (do NOT use # these values in production just because they are here) WORKDELAY = 1 ms INTERVAL = 60 s WORKBITS = 1 HISTOGRAM = $GNUNET_TEST_HOME/nse-histogram [arm] PORT = 22354 DEFAULTSERVICES = nse core UNIXPATH = $GNUNET_RUNTIME_DIR/test-nse-service-arm.unix [fs] AUTOSTART = NO [datastore] AUTOSTART = NO [dht] AUTOSTART = NO [transport] AUTOSTART = YES [core] AUTOSTART = YES [peerinfo] AUTOSTART = YES [nat] DISABLEV6 = YES BINDTO = 127.0.0.1 ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 [dns] AUTOSTART = NO [testing] WEAKRANDOM = YES [testing_old] NUM_PEERS = 10 TOPOLOGY = NONE CONNECT_TOPOLOGY = SMALL_WORLD_RING PERCENTAGE = 3 F2F = NO CONNECT_TIMEOUT = 60 s CONNECT_ATTEMPTS = 3 HOSTKEYSFILE = ${DATADIR}/testing_hostkeys.dat MAX_CONCURRENT_SSH = 20 USE_PROGRESSBARS = YES PEERGROUP_TIMEOUT = 1000 s DELETE_FILES = NO [consensus] AUTOSTART = NO gnunet-0.10.1/src/nse/perf_kdf.c0000644000175000017500000000435612225777502013333 00000000000000/* This file is part of GNUnet. (C) 2002, 2003, 2004, 2006, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file nse/perf_kdf.c * @brief measure performance of KDF hash function */ #include "platform.h" #include "gnunet_util_lib.h" #include #include /** * Calculate the 'proof-of-work' hash (an expensive hash). * * @param buf data to hash * @param buf_len number of bytes in 'buf' * @param result where to write the resulting hash */ static void pow_hash (const void *buf, size_t buf_len, struct GNUNET_HashCode *result) { GNUNET_break (0 == gcry_kdf_derive (buf, buf_len, GCRY_KDF_SCRYPT, 1 /* subalgo */, "gnunet-proof-of-work", strlen ("gnunet-proof-of-work"), 2 /* iterations; keep cost of individual op small */, sizeof (struct GNUNET_HashCode), result)); } static void perfHash () { struct GNUNET_HashCode hc; unsigned int i; char buf[64]; memset (buf, 1, sizeof (buf)); for (i = 0; i < 1024; i++) pow_hash (buf, sizeof (buf), &hc); } int main (int argc, char *argv[]) { struct GNUNET_TIME_Absolute start; start = GNUNET_TIME_absolute_get (); perfHash (); printf ("Hash perf took %s\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); GAUGER ("NSE", "Proof-of-work hashing", 1024 / (1 + GNUNET_TIME_absolute_get_duration (start).rel_value_us / 1000LL), "hashes/ms"); return 0; } /* end of perf_kdf.c */ gnunet-0.10.1/src/nse/nse_profiler_test.conf0000644000175000017500000000376412225230043015766 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/nse-profiler/ [testbed] AUTOSTART = NO PORT = 12113 ACCEPT_FROM = 127.0.0.1; 10.6.0.0/16; HOSTNAME = localhost MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 5 OVERLAY_TOPOLOGY = RANDOM OVERLAY_RANDOM_LINKS = 1000 OPERATION_TIMEOUT = 45 s [nse] PORT = 12114 UNIXPATH = $GNUNET_RUNTIME_DIR/test-nse-service-nse.unix BINARY = gnunet-service-nse #BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/nse/.libs/gnunet-service-nse #PREFIX = valgrind --leak-check=full --log-file=valgrind_nse.%p AUTOSTART = NO # Overriding network settings for faster testing (do NOT use # these values in production just because they are here) WORKDELAY = 60 s INTERVAL = 10 s WORKBITS = 0 PROOFFILE = $GNUNET_TEST_HOME/nse.proof [arm] DEFAULTSERVICES = core nse UNIXPATH = $GNUNET_RUNTIME_DIR/test-nse-service-arm.unix [statistics] AUTOSTART = YES PORT = 12115 [fs] AUTOSTART = NO [datastore] AUTOSTART = NO [dht] AUTOSTART = NO [nat] DISABLEV6 = YES BINDTO = 127.0.0.1 ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 [transport] plugins = udp [transport-udp] PORT = 12116 [core] AUTOSTART = YES [peerinfo] AUTOSTART = YES [dns] AUTOSTART = NO [topology] AUTOSTART = NO [dv] AUTOSTART = NO [resolver] AUTOSTART = YES [mesh] AUTOSTART = NO [chat] AUTOSTART = NO [gns] AUTOSTART = NO [vpn] AUTOSTART = NO [nse-profiler] OUTPUT_FILE = nse_output_2000_peers.dat TOPOLOGY_OUTPUT_FILE = nse_topo_2000_peers DATA_OUTPUT_FILE = nse_stats_2000_peers ROUND0 = 1000 #ROUND1 = 2000 ROUND2 = 2000 ROUND3 = 2000 ROUND4 = 2000 ROUND5 = 2000 ROUND6 = 2000 ROUND7 = 2000 ROUND8 = 2000 ROUND9 = 2000 ROUND10 = 2000 ROUND11 = 1000 ROUND12 = 1000 ROUND13 = 1000 ROUND14 = 1000 ROUND15 = 1000 ROUND16 = 1000 ROUND17 = 1000 ROUND18 = 1000 ROUND19 = 1000 ROUND20 = 1000 ROUND21 = 2000 ROUND22 = 2000 ROUND23 = 2000 ROUND24 = 2000 ROUND25 = 2000 ROUND26 = 2000 ROUND27 = 2000 ROUND28 = 2000 ROUND29 = 2000 ROUND30 = 2000 WAIT_TIME = 1920 s CONNECTION_LIMIT = 10 gnunet-0.10.1/src/nse/Makefile.in0000644000175000017500000013671112320752063013444 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-nse$(EXEEXT) libexec_PROGRAMS = gnunet-service-nse$(EXEEXT) @HAVE_TESTING_TRUE@noinst_PROGRAMS = gnunet-nse-profiler$(EXEEXT) @ENABLE_NSE_HISTOGRAM_TRUE@am__append_1 = \ @ENABLE_NSE_HISTOGRAM_TRUE@ $(top_builddir)/src/testbed/libgnunettestbedlogger.la @ENABLE_NSE_HISTOGRAM_TRUE@am__append_2 = \ @ENABLE_NSE_HISTOGRAM_TRUE@ $(top_builddir)/src/testbed/libgnunettestbedlogger.la @HAVE_TESTING_TRUE@check_PROGRAMS = test_nse_api$(EXEEXT) \ @HAVE_TESTING_TRUE@ perf_kdf$(EXEEXT) $(am__EXEEXT_1) subdir = src/nse DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/nse.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = nse.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetnse_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetnse_la_OBJECTS = nse_api.lo libgnunetnse_la_OBJECTS = $(am_libgnunetnse_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetnse_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetnse_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_BENCHMARKS_TRUE@am__EXEEXT_1 = test_nse_multipeer$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_nse_OBJECTS = gnunet-nse.$(OBJEXT) gnunet_nse_OBJECTS = $(am_gnunet_nse_OBJECTS) gnunet_nse_LDADD = $(LDADD) gnunet_nse_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(gnunet_nse_LDFLAGS) $(LDFLAGS) -o $@ am_gnunet_nse_profiler_OBJECTS = gnunet-nse-profiler.$(OBJEXT) gnunet_nse_profiler_OBJECTS = $(am_gnunet_nse_profiler_OBJECTS) am_gnunet_service_nse_OBJECTS = gnunet-service-nse.$(OBJEXT) gnunet_service_nse_OBJECTS = $(am_gnunet_service_nse_OBJECTS) am_perf_kdf_OBJECTS = perf_kdf.$(OBJEXT) perf_kdf_OBJECTS = $(am_perf_kdf_OBJECTS) perf_kdf_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_test_nse_api_OBJECTS = test_nse_api.$(OBJEXT) test_nse_api_OBJECTS = $(am_test_nse_api_OBJECTS) test_nse_api_DEPENDENCIES = $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_nse_multipeer_OBJECTS = test_nse_multipeer.$(OBJEXT) test_nse_multipeer_OBJECTS = $(am_test_nse_multipeer_OBJECTS) test_nse_multipeer_DEPENDENCIES = \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetnse_la_SOURCES) $(gnunet_nse_SOURCES) \ $(gnunet_nse_profiler_SOURCES) $(gnunet_service_nse_SOURCES) \ $(perf_kdf_SOURCES) $(test_nse_api_SOURCES) \ $(test_nse_multipeer_SOURCES) DIST_SOURCES = $(libgnunetnse_la_SOURCES) $(gnunet_nse_SOURCES) \ $(gnunet_nse_profiler_SOURCES) $(gnunet_service_nse_SOURCES) \ $(perf_kdf_SOURCES) $(test_nse_api_SOURCES) \ $(test_nse_multipeer_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ nse.conf gnunet_nse_SOURCES = gnunet-nse.c gnunet_nse_LDFLAGS = \ libgnunetnse.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(XLIB) $(GN_LIBINTL) gnunet_nse_DEPENDENCIES = \ libgnunetnse.la \ $(top_builddir)/src/util/libgnunetutil.la lib_LTLIBRARIES = libgnunetnse.la libgnunetnse_la_SOURCES = \ nse_api.c nse.h libgnunetnse_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetnse_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 gnunet_nse_profiler_SOURCES = \ gnunet-nse-profiler.c gnunet_nse_profiler_LDADD = -lm \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(GN_LIBINTL) gnunet_nse_profiler_DEPENDENCIES = \ libgnunetnse.la gnunet_service_nse_SOURCES = \ gnunet-service-nse.c gnunet_service_nse_LDADD = $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(LIBGCRYPT_LIBS) -lm -lgcrypt $(GN_LIBINTL) $(am__append_1) gnunet_service_nse_DEPENDENCIES = libgnunetnse.la $(am__append_2) @HAVE_BENCHMARKS_TRUE@MULTIPEER_TEST = test_nse_multipeer @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_nse_api_SOURCES = \ test_nse_api.c test_nse_api_LDADD = \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_nse_multipeer_SOURCES = \ test_nse_multipeer.c test_nse_multipeer_LDADD = \ $(top_builddir)/src/nse/libgnunetnse.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ -lm perf_kdf_SOURCES = \ perf_kdf.c perf_kdf_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(LIBGCRYPT_LIBS) \ -lgcrypt EXTRA_DIST = \ test_nse.conf \ nse_profiler_test.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/nse/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/nse/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): nse.conf: $(top_builddir)/config.status $(srcdir)/nse.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetnse.la: $(libgnunetnse_la_OBJECTS) $(libgnunetnse_la_DEPENDENCIES) $(EXTRA_libgnunetnse_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetnse_la_LINK) -rpath $(libdir) $(libgnunetnse_la_OBJECTS) $(libgnunetnse_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-nse$(EXEEXT): $(gnunet_nse_OBJECTS) $(gnunet_nse_DEPENDENCIES) $(EXTRA_gnunet_nse_DEPENDENCIES) @rm -f gnunet-nse$(EXEEXT) $(AM_V_CCLD)$(gnunet_nse_LINK) $(gnunet_nse_OBJECTS) $(gnunet_nse_LDADD) $(LIBS) gnunet-nse-profiler$(EXEEXT): $(gnunet_nse_profiler_OBJECTS) $(gnunet_nse_profiler_DEPENDENCIES) $(EXTRA_gnunet_nse_profiler_DEPENDENCIES) @rm -f gnunet-nse-profiler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_nse_profiler_OBJECTS) $(gnunet_nse_profiler_LDADD) $(LIBS) gnunet-service-nse$(EXEEXT): $(gnunet_service_nse_OBJECTS) $(gnunet_service_nse_DEPENDENCIES) $(EXTRA_gnunet_service_nse_DEPENDENCIES) @rm -f gnunet-service-nse$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_nse_OBJECTS) $(gnunet_service_nse_LDADD) $(LIBS) perf_kdf$(EXEEXT): $(perf_kdf_OBJECTS) $(perf_kdf_DEPENDENCIES) $(EXTRA_perf_kdf_DEPENDENCIES) @rm -f perf_kdf$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_kdf_OBJECTS) $(perf_kdf_LDADD) $(LIBS) test_nse_api$(EXEEXT): $(test_nse_api_OBJECTS) $(test_nse_api_DEPENDENCIES) $(EXTRA_test_nse_api_DEPENDENCIES) @rm -f test_nse_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_nse_api_OBJECTS) $(test_nse_api_LDADD) $(LIBS) test_nse_multipeer$(EXEEXT): $(test_nse_multipeer_OBJECTS) $(test_nse_multipeer_DEPENDENCIES) $(EXTRA_test_nse_multipeer_DEPENDENCIES) @rm -f test_nse_multipeer$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_nse_multipeer_OBJECTS) $(test_nse_multipeer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-nse-profiler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-nse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-nse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nse_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_kdf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_nse_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_nse_multipeer.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_nse_api.log: test_nse_api$(EXEEXT) @p='test_nse_api$(EXEEXT)'; \ b='test_nse_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_kdf.log: perf_kdf$(EXEEXT) @p='perf_kdf$(EXEEXT)'; \ b='perf_kdf'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_nse_multipeer.log: test_nse_multipeer$(EXEEXT) @p='test_nse_multipeer$(EXEEXT)'; \ b='test_nse_multipeer'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-libexecPROGRAMS \ install-man install-pdf install-pdf-am install-pkgcfgDATA \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/nse/gnunet-service-nse.c0000644000175000017500000013420112320466615015261 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nse/gnunet-service-nse.c * @brief network size estimation service * @author Nathan Evans * @author Christian Grothoff * * The purpose of this service is to estimate the size of the network. * Given a specified interval, each peer hashes the most recent * timestamp which is evenly divisible by that interval. This hash is * compared in distance to the peer identity to choose an offset. The * closer the peer identity to the hashed timestamp, the earlier the * peer sends out a "nearest peer" message. The closest peer's * message should thus be received before any others, which stops * those peer from sending their messages at a later duration. So * every peer should receive the same nearest peer message, and from * this can calculate the expected number of peers in the network. */ #include "platform.h" #include #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_signatures.h" #include "gnunet_statistics_service.h" #include "gnunet_core_service.h" #include "gnunet_nse_service.h" #if ENABLE_NSE_HISTOGRAM #include "gnunet_testbed_logger_service.h" #endif #include "nse.h" #include /** * Should messages be delayed randomly? This option should be set to * #GNUNET_NO only for experiments, not in production. */ #define USE_RANDOM_DELAYS GNUNET_YES /** * Generate extensive debug-level log messages? */ #define DEBUG_NSE GNUNET_NO /** * Over how many values do we calculate the weighted average? */ #define HISTORY_SIZE 64 /** * Message priority to use. */ #define NSE_PRIORITY GNUNET_CORE_PRIO_CRITICAL_CONTROL #if FREEBSD #define log2(a) (log(a)/log(2)) #endif /** * Amount of work required (W-bit collisions) for NSE proofs, in collision-bits. */ static unsigned long long nse_work_required; /** * Interval for sending network size estimation flood requests. */ static struct GNUNET_TIME_Relative gnunet_nse_interval; /** * Interval between proof find runs. */ static struct GNUNET_TIME_Relative proof_find_delay; #if ENABLE_NSE_HISTOGRAM /** * Handle to test if testbed logger service is running or not */ struct GNUNET_CLIENT_TestHandle *logger_test; /** * Handle for writing when we received messages to disk. */ static struct GNUNET_TESTBED_LOGGER_Handle *lh; /** * Handle for writing message received timestamp information to disk. */ static struct GNUNET_BIO_WriteHandle *histogram; #endif /** * Per-peer information. */ struct NSEPeerEntry { /** * Core handle for sending messages to this peer. */ struct GNUNET_CORE_TransmitHandle *th; /** * What is the identity of the peer? */ struct GNUNET_PeerIdentity id; /** * Task scheduled to send message to this peer. */ GNUNET_SCHEDULER_TaskIdentifier transmit_task; /** * Did we receive or send a message about the previous round * to this peer yet? GNUNET_YES if the previous round has * been taken care of. */ int previous_round; #if ENABLE_NSE_HISTOGRAM /** * Amount of messages received from this peer on this round. */ unsigned int received_messages; /** * Amount of messages transmitted to this peer on this round. */ unsigned int transmitted_messages; /** * Which size did we tell the peer the network is? */ unsigned int last_transmitted_size; #endif }; GNUNET_NETWORK_STRUCT_BEGIN /** * Network size estimate reply; sent when "this" * peer's timer has run out before receiving a * valid reply from another peer. */ struct GNUNET_NSE_FloodMessage { /** * Type: GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD */ struct GNUNET_MessageHeader header; /** * Number of hops this message has taken so far. */ uint32_t hop_count GNUNET_PACKED; /** * Purpose. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * The current timestamp value (which all * peers should agree on). */ struct GNUNET_TIME_AbsoluteNBO timestamp; /** * Number of matching bits between the hash * of timestamp and the initiator's public * key. */ uint32_t matching_bits GNUNET_PACKED; /** * Public key of the originator. */ struct GNUNET_PeerIdentity origin; /** * Proof of work, causing leading zeros when hashed with pkey. */ uint64_t proof_of_work GNUNET_PACKED; /** * Signature (over range specified in purpose). */ struct GNUNET_CRYPTO_EddsaSignature signature; }; GNUNET_NETWORK_STRUCT_END /** * Handle to our current configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the statistics service. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Handle to the core service. */ static struct GNUNET_CORE_Handle *core_api; /** * Map of all connected peers. */ static struct GNUNET_CONTAINER_MultiPeerMap *peers; /** * The current network size estimate. Number of bits matching on * average thus far. */ static double current_size_estimate; /** * The standard deviation of the last #HISTORY_SIZE network * size estimates. */ static double current_std_dev = NAN; /** * Current hop counter estimate (estimate for network diameter). */ static uint32_t hop_count_max; /** * Message for the next round, if we got any. */ static struct GNUNET_NSE_FloodMessage next_message; /** * Array of recent size estimate messages. */ static struct GNUNET_NSE_FloodMessage size_estimate_messages[HISTORY_SIZE]; /** * Index of most recent estimate. */ static unsigned int estimate_index; /** * Number of valid entries in the history. */ static unsigned int estimate_count; /** * Task scheduled to update our flood message for the next round. */ static GNUNET_SCHEDULER_TaskIdentifier flood_task; /** * Task scheduled to compute our proof. */ static GNUNET_SCHEDULER_TaskIdentifier proof_task; /** * Notification context, simplifies client broadcasts. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * The next major time. */ static struct GNUNET_TIME_Absolute next_timestamp; /** * The current major time. */ static struct GNUNET_TIME_Absolute current_timestamp; /** * The private key of this peer. */ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; /** * The peer identity of this peer. */ static struct GNUNET_PeerIdentity my_identity; /** * Proof of work for this peer. */ static uint64_t my_proof; /** * Handle to this serivce's server. */ static struct GNUNET_SERVER_Handle *srv; /** * Initialize a message to clients with the current network * size estimate. * * @param em message to fill in */ static void setup_estimate_message (struct GNUNET_NSE_ClientMessage *em) { unsigned int i; unsigned int j; double mean; double sum; double std_dev; double variance; double val; double nsize; #define WEST 1 /* Weighted incremental algorithm for stddev according to West (1979) */ #if WEST double sumweight; double weight; double q; double r; double temp; mean = 0.0; sum = 0.0; sumweight = 0.0; variance = 0.0; for (i = 0; i < estimate_count; i++) { j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE; val = htonl (size_estimate_messages[j].matching_bits); weight = estimate_count + 1 - i; temp = weight + sumweight; q = val - mean; r = q * weight / temp; mean += r; sum += sumweight * q * r; sumweight = temp; } if (estimate_count > 0) variance = (sum / sumweight) * estimate_count / (estimate_count - 1.0); #else /* trivial version for debugging */ double vsq; /* non-weighted trivial version */ sum = 0.0; vsq = 0.0; variance = 0.0; mean = 0.0; for (i = 0; i < estimate_count; i++) { j = (estimate_index - i + HISTORY_SIZE) % HISTORY_SIZE; val = htonl (size_estimate_messages[j].matching_bits); sum += val; vsq += val * val; } if (0 != estimate_count) { mean = sum / estimate_count; variance = (vsq - mean * sum) / (estimate_count - 1.0); // terrible for numerical stability... } #endif if (variance >= 0) std_dev = sqrt (variance); else std_dev = variance; /* must be infinity due to estimate_count == 0 */ current_std_dev = std_dev; current_size_estimate = mean; em->header.size = htons (sizeof (struct GNUNET_NSE_ClientMessage)); em->header.type = htons (GNUNET_MESSAGE_TYPE_NSE_ESTIMATE); em->reserved = htonl (0); em->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); double se = mean - 0.332747; nsize = log2 (GNUNET_CONTAINER_multipeermap_size (peers) + 1); em->size_estimate = GNUNET_hton_double (GNUNET_MAX (se, nsize)); em->std_deviation = GNUNET_hton_double (std_dev); GNUNET_STATISTICS_set (stats, "# nodes in the network (estimate)", (uint64_t) pow (2, mean - 1.0 / 3.0), GNUNET_NO); } /** * Handler for START message from client, triggers an * immediate current network estimate notification. * Also, we remember the client for updates upon future * estimate measurements. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_start_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_NSE_ClientMessage em; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received START message from client\n"); GNUNET_SERVER_notification_context_add (nc, client); setup_estimate_message (&em); GNUNET_SERVER_notification_context_unicast (nc, client, &em.header, GNUNET_YES); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * How long should we delay a message to go the given number of * matching bits? * * @param matching_bits number of matching bits to consider */ static double get_matching_bits_delay (uint32_t matching_bits) { /* Calculated as: S + f/2 - (f / pi) * (atan(x - p')) */ // S is next_timestamp (ignored in return value) // f is frequency (gnunet_nse_interval) // x is matching_bits // p' is current_size_estimate return ((double) gnunet_nse_interval.rel_value_us / (double) 2.0) - ((gnunet_nse_interval.rel_value_us / M_PI) * atan (matching_bits - current_size_estimate)); } /** * What delay randomization should we apply for a given number of matching bits? * * @param matching_bits number of matching bits * @return random delay to apply */ static struct GNUNET_TIME_Relative get_delay_randomization (uint32_t matching_bits) { #if USE_RANDOM_DELAYS struct GNUNET_TIME_Relative ret; uint32_t i; double d; d = get_matching_bits_delay (matching_bits); i = (uint32_t) (d / (double) (hop_count_max + 1)); ret.rel_value_us = i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Randomizing flood using latencies up to %s\n", GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); ret.rel_value_us = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, i + 1); return ret; #else return GNUNET_TIME_UNIT_ZERO; #endif } /** * Calculate the 'proof-of-work' hash (an expensive hash). * * @param buf data to hash * @param buf_len number of bytes in @a buf * @param result where to write the resulting hash */ static void pow_hash (const void *buf, size_t buf_len, struct GNUNET_HashCode *result) { GNUNET_break (0 == gcry_kdf_derive (buf, buf_len, GCRY_KDF_SCRYPT, 1 /* subalgo */, "gnunet-proof-of-work", strlen ("gnunet-proof-of-work"), 2 /* iterations; keep cost of individual op small */, sizeof (struct GNUNET_HashCode), result)); } /** * Get the number of matching bits that the given timestamp has to the given peer ID. * * @param timestamp time to generate key * @param id peer identity to compare with * @return number of matching bits */ static uint32_t get_matching_bits (struct GNUNET_TIME_Absolute timestamp, const struct GNUNET_PeerIdentity *id) { struct GNUNET_HashCode timestamp_hash; struct GNUNET_HashCode pid_hash; GNUNET_CRYPTO_hash (×tamp.abs_value_us, sizeof (timestamp.abs_value_us), ×tamp_hash); GNUNET_CRYPTO_hash (id, sizeof (struct GNUNET_PeerIdentity), &pid_hash); return GNUNET_CRYPTO_hash_matching_bits (×tamp_hash, &pid_hash); } /** * Get the transmission delay that should be applied for a * particular round. * * @param round_offset -1 for the previous round (random delay between 0 and 50ms) * 0 for the current round (based on our proximity to time key) * @return delay that should be applied */ static struct GNUNET_TIME_Relative get_transmit_delay (int round_offset) { struct GNUNET_TIME_Relative ret; struct GNUNET_TIME_Absolute tgt; double dist_delay; uint32_t matching_bits; switch (round_offset) { case -1: /* previous round is randomized between 0 and 50 ms */ #if USE_RANDOM_DELAYS ret.rel_value_us = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, 50); #else ret = GNUNET_TIME_UNIT_ZERO; #endif GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting previous round behind schedule in %s\n", GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); return ret; case 0: /* current round is based on best-known matching_bits */ matching_bits = ntohl (size_estimate_messages[estimate_index].matching_bits); dist_delay = get_matching_bits_delay (matching_bits); dist_delay += get_delay_randomization (matching_bits).rel_value_us; ret.rel_value_us = (uint64_t) dist_delay; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "For round %s, delay for %u matching bits is %s\n", GNUNET_STRINGS_absolute_time_to_string (current_timestamp), (unsigned int) matching_bits, GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); /* now consider round start time and add delay to it */ tgt = GNUNET_TIME_absolute_add (current_timestamp, ret); return GNUNET_TIME_absolute_get_remaining (tgt); } GNUNET_break (0); return GNUNET_TIME_UNIT_FOREVER_REL; } /** * Task that triggers a NSE P2P transmission. * * @param cls the `struct NSEPeerEntry *` * @param tc scheduler context */ static void transmit_task_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Called when core is ready to send a message we asked for * out to the destination. * * @param cls closure with the `struct NSEPeerEntry *` * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ static size_t transmit_ready (void *cls, size_t size, void *buf) { struct NSEPeerEntry *peer_entry = cls; unsigned int idx; peer_entry->th = NULL; if (NULL == buf) { /* client disconnected */ return 0; } GNUNET_assert (size >= sizeof (struct GNUNET_NSE_FloodMessage)); idx = estimate_index; if (GNUNET_NO == peer_entry->previous_round) { idx = (idx + HISTORY_SIZE - 1) % HISTORY_SIZE; peer_entry->previous_round = GNUNET_YES; peer_entry->transmit_task = GNUNET_SCHEDULER_add_delayed (get_transmit_delay (0), &transmit_task_cb, peer_entry); } if ((0 == ntohl (size_estimate_messages[idx].hop_count)) && (GNUNET_SCHEDULER_NO_TASK != proof_task)) { GNUNET_STATISTICS_update (stats, "# flood messages not generated (no proof yet)", 1, GNUNET_NO); return 0; } if (0 == ntohs (size_estimate_messages[idx].header.size)) { GNUNET_STATISTICS_update (stats, "# flood messages not generated (lack of history)", 1, GNUNET_NO); return 0; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In round s, sending to `%s' estimate with %u bits\n", GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (size_estimate_messages[idx].timestamp)), GNUNET_i2s (&peer_entry->id), (unsigned int) ntohl (size_estimate_messages[idx].matching_bits)); if (ntohl (size_estimate_messages[idx].hop_count) == 0) GNUNET_STATISTICS_update (stats, "# flood messages started", 1, GNUNET_NO); GNUNET_STATISTICS_update (stats, "# flood messages transmitted", 1, GNUNET_NO); #if ENABLE_NSE_HISTOGRAM peer_entry->transmitted_messages++; peer_entry->last_transmitted_size = ntohl(size_estimate_messages[idx].matching_bits); #endif memcpy (buf, &size_estimate_messages[idx], sizeof (struct GNUNET_NSE_FloodMessage)); return sizeof (struct GNUNET_NSE_FloodMessage); } /** * Task that triggers a NSE P2P transmission. * * @param cls the `struct NSEPeerEntry *` * @param tc scheduler context */ static void transmit_task_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct NSEPeerEntry *peer_entry = cls; peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (NULL == peer_entry->th); peer_entry->th = GNUNET_CORE_notify_transmit_ready (core_api, GNUNET_NO, NSE_PRIORITY, GNUNET_TIME_UNIT_FOREVER_REL, &peer_entry->id, sizeof (struct GNUNET_NSE_FloodMessage), &transmit_ready, peer_entry); } /** * We've sent on our flood message or one that we received which was * validated and closer than ours. Update the global list of recent * messages and the average. Also re-broadcast the message to any * clients. */ static void update_network_size_estimate () { struct GNUNET_NSE_ClientMessage em; setup_estimate_message (&em); GNUNET_SERVER_notification_context_broadcast (nc, &em.header, GNUNET_YES); } /** * Setup a flood message in our history array at the given * slot offset for the given timestamp. * * @param slot index to use * @param ts timestamp to use */ static void setup_flood_message (unsigned int slot, struct GNUNET_TIME_Absolute ts) { struct GNUNET_NSE_FloodMessage *fm; uint32_t matching_bits; matching_bits = get_matching_bits (ts, &my_identity); fm = &size_estimate_messages[slot]; fm->header.size = htons (sizeof (struct GNUNET_NSE_FloodMessage)); fm->header.type = htons (GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD); fm->hop_count = htonl (0); fm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_NSE_SEND); fm->purpose.size = htonl (sizeof (struct GNUNET_NSE_FloodMessage) - sizeof (struct GNUNET_MessageHeader) - sizeof (uint32_t) - sizeof (struct GNUNET_CRYPTO_EddsaSignature)); fm->matching_bits = htonl (matching_bits); fm->timestamp = GNUNET_TIME_absolute_hton (ts); fm->origin = my_identity; fm->proof_of_work = my_proof; if (nse_work_required > 0) GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_private_key, &fm->purpose, &fm->signature)); else memset (&fm->signature, 0, sizeof (fm->signature)); } /** * Schedule transmission for the given peer for the current round based * on what we know about the desired delay. * * @param cls unused * @param key hash of peer identity * @param value the `struct NSEPeerEntry` * @return #GNUNET_OK (continue to iterate) */ static int schedule_current_round (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct NSEPeerEntry *peer_entry = value; struct GNUNET_TIME_Relative delay; if (NULL != peer_entry->th) { peer_entry->previous_round = GNUNET_NO; return GNUNET_OK; } if (GNUNET_SCHEDULER_NO_TASK != peer_entry->transmit_task) { GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); peer_entry->previous_round = GNUNET_NO; } #if ENABLE_NSE_HISTOGRAM if (peer_entry->received_messages > 1) GNUNET_STATISTICS_update(stats, "# extra messages", peer_entry->received_messages - 1, GNUNET_NO); peer_entry->transmitted_messages = 0; peer_entry->last_transmitted_size = 0; peer_entry->received_messages = 0; #endif delay = get_transmit_delay ((peer_entry->previous_round == GNUNET_NO) ? -1 : 0); peer_entry->transmit_task = GNUNET_SCHEDULER_add_delayed (delay, &transmit_task_cb, peer_entry); return GNUNET_OK; } /** * Update our flood message to be sent (and our timestamps). * * @param cls unused * @param tc context for this message */ static void update_flood_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Relative offset; unsigned int i; flood_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; offset = GNUNET_TIME_absolute_get_remaining (next_timestamp); if (0 != offset.rel_value_us) { /* somehow run early, delay more */ flood_task = GNUNET_SCHEDULER_add_delayed (offset, &update_flood_message, NULL); return; } estimate_index = (estimate_index + 1) % HISTORY_SIZE; if (estimate_count < HISTORY_SIZE) estimate_count++; current_timestamp = next_timestamp; next_timestamp = GNUNET_TIME_absolute_add (current_timestamp, gnunet_nse_interval); if ((current_timestamp.abs_value_us == GNUNET_TIME_absolute_ntoh (next_message.timestamp).abs_value_us) && (get_matching_bits (current_timestamp, &my_identity) < ntohl(next_message.matching_bits))) { /* we received a message for this round way early, use it! */ size_estimate_messages[estimate_index] = next_message; size_estimate_messages[estimate_index].hop_count = htonl (1 + ntohl (next_message.hop_count)); } else setup_flood_message (estimate_index, current_timestamp); next_message.matching_bits = htonl (0); /* reset for 'next' round */ hop_count_max = 0; for (i = 0; i < HISTORY_SIZE; i++) hop_count_max = GNUNET_MAX (ntohl (size_estimate_messages[i].hop_count), hop_count_max); GNUNET_CONTAINER_multipeermap_iterate (peers, &schedule_current_round, NULL); flood_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (next_timestamp), &update_flood_message, NULL); } /** * Count the leading zeroes in hash. * * @param hash to count leading zeros in * @return the number of leading zero bits. */ static unsigned int count_leading_zeroes (const struct GNUNET_HashCode *hash) { unsigned int hash_count; hash_count = 0; while (0 == GNUNET_CRYPTO_hash_get_bit (hash, hash_count)) hash_count++; return hash_count; } /** * Check whether the given public key and integer are a valid proof of * work. * * @param pkey the public key * @param val the integer * @return #GNUNET_YES if valid, #GNUNET_NO if not */ static int check_proof_of_work (const struct GNUNET_CRYPTO_EddsaPublicKey *pkey, uint64_t val) { char buf[sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) + sizeof (val)] GNUNET_ALIGN; struct GNUNET_HashCode result; memcpy (buf, &val, sizeof (val)); memcpy (&buf[sizeof (val)], pkey, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); pow_hash (buf, sizeof (buf), &result); return (count_leading_zeroes (&result) >= nse_work_required) ? GNUNET_YES : GNUNET_NO; } /** * Write our current proof to disk. */ static void write_proof () { char *proof; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "PROOFFILE", &proof)) return; if (sizeof (my_proof) != GNUNET_DISK_fn_write (proof, &my_proof, sizeof (my_proof), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", proof); GNUNET_free (proof); } /** * Find our proof of work. * * @param cls closure (unused) * @param tc task context */ static void find_proof (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { #define ROUND_SIZE 10 uint64_t counter; char buf[sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) + sizeof (uint64_t)] GNUNET_ALIGN; struct GNUNET_HashCode result; unsigned int i; proof_task = GNUNET_SCHEDULER_NO_TASK; memcpy (&buf[sizeof (uint64_t)], &my_identity, sizeof (struct GNUNET_PeerIdentity)); i = 0; counter = my_proof; while ((counter != UINT64_MAX) && (i < ROUND_SIZE)) { memcpy (buf, &counter, sizeof (uint64_t)); pow_hash (buf, sizeof (buf), &result); if (nse_work_required <= count_leading_zeroes (&result)) { my_proof = counter; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Proof of work found: %llu!\n", (unsigned long long) GNUNET_ntohll (counter)); write_proof (); setup_flood_message (estimate_index, current_timestamp); return; } counter++; i++; } if (my_proof / (100 * ROUND_SIZE) < counter / (100 * ROUND_SIZE)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testing proofs currently at %llu\n", (unsigned long long) counter); /* remember progress every 100 rounds */ my_proof = counter; write_proof (); } else { my_proof = counter; } proof_task = GNUNET_SCHEDULER_add_delayed_with_priority (proof_find_delay, GNUNET_SCHEDULER_PRIORITY_IDLE, &find_proof, NULL); } /** * An incoming flood message has been received which claims * to have more bits matching than any we know in this time * period. Verify the signature and/or proof of work. * * @param incoming_flood the message to verify * @return #GNUNET_YES if the message is verified * #GNUNET_NO if the key/signature don't verify */ static int verify_message_crypto (const struct GNUNET_NSE_FloodMessage *incoming_flood) { if (GNUNET_YES != check_proof_of_work (&incoming_flood->origin.public_key, incoming_flood->proof_of_work)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Proof of work invalid: %llu!\n", (unsigned long long) GNUNET_ntohll (incoming_flood->proof_of_work)); GNUNET_break_op (0); return GNUNET_NO; } if ((nse_work_required > 0) && (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_NSE_SEND, &incoming_flood->purpose, &incoming_flood->signature, &incoming_flood->origin.public_key))) { GNUNET_break_op (0); return GNUNET_NO; } return GNUNET_YES; } /** * Update transmissions for the given peer for the current round based * on updated proximity information. * * @param cls peer entry to exclude from updates * @param key hash of peer identity * @param value the `struct NSEPeerEntry *` of a peer to transmit to * @return #GNUNET_OK (continue to iterate) */ static int update_flood_times (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct NSEPeerEntry *exclude = cls; struct NSEPeerEntry *peer_entry = value; struct GNUNET_TIME_Relative delay; if (NULL != peer_entry->th) return GNUNET_OK; /* already active */ if (peer_entry == exclude) return GNUNET_OK; /* trigger of the update */ if (peer_entry->previous_round == GNUNET_NO) { /* still stuck in previous round, no point to update, check that * we are active here though... */ if ( (GNUNET_SCHEDULER_NO_TASK == peer_entry->transmit_task) && (NULL == peer_entry->th) ) { GNUNET_break (0); } return GNUNET_OK; } if (GNUNET_SCHEDULER_NO_TASK != peer_entry->transmit_task) { GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK; } delay = get_transmit_delay (0); peer_entry->transmit_task = GNUNET_SCHEDULER_add_delayed (delay, &transmit_task_cb, peer_entry); return GNUNET_OK; } /** * Core handler for size estimate flooding messages. * * @param cls closure unused * @param message message * @param peer peer identity this message is from (ignored) */ static int handle_p2p_size_estimate (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { const struct GNUNET_NSE_FloodMessage *incoming_flood; struct GNUNET_TIME_Absolute ts; struct NSEPeerEntry *peer_entry; uint32_t matching_bits; unsigned int idx; #if ENABLE_NSE_HISTOGRAM { uint64_t t; t = GNUNET_TIME_absolute_get().abs_value_us; if (NULL != lh) GNUNET_TESTBED_LOGGER_write (lh, &t, sizeof (uint64_t)); if (NULL != histogram) GNUNET_BIO_write_int64 (histogram, t); } #endif incoming_flood = (const struct GNUNET_NSE_FloodMessage *) message; GNUNET_STATISTICS_update (stats, "# flood messages received", 1, GNUNET_NO); matching_bits = ntohl (incoming_flood->matching_bits); #if DEBUG_NSE { char origin[5]; char pred[5]; struct GNUNET_PeerIdentity os; GNUNET_snprintf (origin, sizeof (origin), "%4s", GNUNET_i2s (&incoming_flood->origin)); GNUNET_snprintf (pred, sizeof (pred), "%4s", GNUNET_i2s (peer)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Flood at %s from `%s' via `%s' at `%s' with bits %u\n", GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp)), origin, pred, GNUNET_i2s (&my_identity), (unsigned int) matching_bits); } #endif peer_entry = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == peer_entry) { GNUNET_break (0); return GNUNET_OK; } #if ENABLE_NSE_HISTOGRAM peer_entry->received_messages++; if (peer_entry->transmitted_messages > 0 && peer_entry->last_transmitted_size >= matching_bits) GNUNET_STATISTICS_update(stats, "# cross messages", 1, GNUNET_NO); #endif ts = GNUNET_TIME_absolute_ntoh (incoming_flood->timestamp); if (ts.abs_value_us == current_timestamp.abs_value_us) idx = estimate_index; else if (ts.abs_value_us == current_timestamp.abs_value_us - gnunet_nse_interval.rel_value_us) idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE; else if (ts.abs_value_us == next_timestamp.abs_value_us) { if (matching_bits <= ntohl (next_message.matching_bits)) return GNUNET_OK; /* ignore, simply too early/late */ if (GNUNET_YES != verify_message_crypto (incoming_flood)) { GNUNET_break_op (0); return GNUNET_OK; } next_message = *incoming_flood; return GNUNET_OK; } else { GNUNET_STATISTICS_update (stats, "# flood messages discarded (clock skew too large)", 1, GNUNET_NO); return GNUNET_OK; } if (0 == (memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))) { /* send to self, update our own estimate IF this also comes from us! */ if (0 == memcmp (&incoming_flood->origin, &my_identity, sizeof (my_identity))) update_network_size_estimate (); return GNUNET_OK; } if (matching_bits == ntohl (size_estimate_messages[idx].matching_bits)) { /* Cancel transmission in the other direction, as this peer clearly has up-to-date information already. Even if we didn't talk to this peer in the previous round, we should no longer send it stale information as it told us about the current round! */ peer_entry->previous_round = GNUNET_YES; if (idx != estimate_index) { /* do not transmit information for the previous round to this peer anymore (but allow current round) */ return GNUNET_OK; } /* got up-to-date information for current round, cancel transmission to * this peer altogether */ if (GNUNET_SCHEDULER_NO_TASK != peer_entry->transmit_task) { GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != peer_entry->th) { GNUNET_CORE_notify_transmit_ready_cancel (peer_entry->th); peer_entry->th = NULL; } return GNUNET_OK; } if (matching_bits < ntohl (size_estimate_messages[idx].matching_bits)) { if ((idx < estimate_index) && (peer_entry->previous_round == GNUNET_YES)) { peer_entry->previous_round = GNUNET_NO; } /* push back our result now, that peer is spreading bad information... */ if (NULL == peer_entry->th) { if (peer_entry->transmit_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); peer_entry->transmit_task = GNUNET_SCHEDULER_add_now (&transmit_task_cb, peer_entry); } /* Not closer than our most recent message, no need to do work here */ GNUNET_STATISTICS_update (stats, "# flood messages ignored (had closer already)", 1, GNUNET_NO); return GNUNET_OK; } if (GNUNET_YES != verify_message_crypto (incoming_flood)) { GNUNET_break_op (0); return GNUNET_OK; } GNUNET_assert (matching_bits > ntohl (size_estimate_messages[idx].matching_bits)); /* Cancel transmission in the other direction, as this peer clearly has * up-to-date information already. */ peer_entry->previous_round = GNUNET_YES; if (idx == estimate_index) { /* cancel any activity for current round */ if (peer_entry->transmit_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (peer_entry->transmit_task); peer_entry->transmit_task = GNUNET_SCHEDULER_NO_TASK; } if (peer_entry->th != NULL) { GNUNET_CORE_notify_transmit_ready_cancel (peer_entry->th); peer_entry->th = NULL; } } size_estimate_messages[idx] = *incoming_flood; size_estimate_messages[idx].hop_count = htonl (ntohl (incoming_flood->hop_count) + 1); hop_count_max = GNUNET_MAX (ntohl (incoming_flood->hop_count) + 1, hop_count_max); GNUNET_STATISTICS_set (stats, "# estimated network diameter", hop_count_max, GNUNET_NO); /* have a new, better size estimate, inform clients */ update_network_size_estimate (); /* flood to rest */ GNUNET_CONTAINER_multipeermap_iterate (peers, &update_flood_times, peer_entry); return GNUNET_OK; } /** * Method called whenever a peer connects. Sets up the PeerEntry and * schedules the initial size info transmission to this peer. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct NSEPeerEntry *peer_entry; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' connected to us\n", GNUNET_i2s (peer)); peer_entry = GNUNET_new (struct NSEPeerEntry); peer_entry->id = *peer; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (peers, peer, peer_entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); peer_entry->transmit_task = GNUNET_SCHEDULER_add_delayed (get_transmit_delay (-1), &transmit_task_cb, peer_entry); GNUNET_STATISTICS_update (stats, "# peers connected", 1, GNUNET_NO); } /** * Method called whenever a peer disconnects. Deletes the PeerEntry and cancels * any pending transmission requests to that peer. * * @param cls closure * @param peer peer identity this notification is about */ static void handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct NSEPeerEntry *pos; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%s' disconnected from us\n", GNUNET_i2s (peer)); pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); if (NULL == pos) { GNUNET_break (0); return; } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (peers, peer, pos)); if (pos->transmit_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (pos->transmit_task); pos->transmit_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != pos->th) { GNUNET_CORE_notify_transmit_ready_cancel (pos->th); pos->th = NULL; } GNUNET_free (pos); GNUNET_STATISTICS_update (stats, "# peers connected", -1, GNUNET_NO); } #if ENABLE_NSE_HISTOGRAM /** * Functions of this type are called to notify a successful transmission of the * message to the logger service * * @param cls NULL * @param size the amount of data sent (ignored) */ static void flush_comp_cb (void *cls, size_t size) { GNUNET_TESTBED_LOGGER_disconnect (lh); lh = NULL; } #endif /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_SCHEDULER_NO_TASK != flood_task) { GNUNET_SCHEDULER_cancel (flood_task); flood_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != proof_task) { GNUNET_SCHEDULER_cancel (proof_task); proof_task = GNUNET_SCHEDULER_NO_TASK; write_proof (); /* remember progress */ } if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } if (NULL != core_api) { GNUNET_CORE_disconnect (core_api); core_api = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } if (NULL != peers) { GNUNET_CONTAINER_multipeermap_destroy (peers); peers = NULL; } if (NULL != my_private_key) { GNUNET_free (my_private_key); my_private_key = NULL; } #if ENABLE_NSE_HISTOGRAM if (NULL != logger_test) { GNUNET_CLIENT_service_test_cancel (logger_test); logger_test = NULL; } if (NULL != lh) { struct GNUNET_TIME_Relative timeout; timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30); GNUNET_TESTBED_LOGGER_flush (lh, timeout, &flush_comp_cb, NULL); } if (NULL != histogram) { GNUNET_BIO_write_close (histogram); histogram = NULL; } #endif } /** * Called on core init/fail. * * @param cls service closure * @param identity the public identity of this peer */ static void core_init (void *cls, const struct GNUNET_PeerIdentity *identity) { struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute prev_time; if (NULL == identity) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connection to core FAILED!\n"); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_assert (0 == memcmp (&my_identity, identity, sizeof (struct GNUNET_PeerIdentity))); now = GNUNET_TIME_absolute_get (); current_timestamp.abs_value_us = (now.abs_value_us / gnunet_nse_interval.rel_value_us) * gnunet_nse_interval.rel_value_us; next_timestamp = GNUNET_TIME_absolute_add (current_timestamp, gnunet_nse_interval); estimate_index = HISTORY_SIZE - 1; estimate_count = 0; if (GNUNET_YES == check_proof_of_work (&my_identity.public_key, my_proof)) { int idx = (estimate_index + HISTORY_SIZE - 1) % HISTORY_SIZE; prev_time.abs_value_us = current_timestamp.abs_value_us - gnunet_nse_interval.rel_value_us; setup_flood_message (idx, prev_time); setup_flood_message (estimate_index, current_timestamp); estimate_count++; } flood_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (next_timestamp), &update_flood_message, NULL); } #if ENABLE_NSE_HISTOGRAM /** * Function called with the status of the testbed logger service * * @param cls NULL * @param status GNUNET_YES if the service is running, * GNUNET_NO if the service is not running * GNUNET_SYSERR if the configuration is invalid */ static void status_cb (void *cls, int status) { logger_test = NULL; if (GNUNET_YES != status) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed logger not running\n"); return; } if (NULL == (lh = GNUNET_TESTBED_LOGGER_connect (cfg))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Cannot connect to the testbed logger. Exiting.\n"); GNUNET_SCHEDULER_shutdown (); } } #endif /** * Handle network size estimate clients. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_start_message, NULL, GNUNET_MESSAGE_TYPE_NSE_START, sizeof (struct GNUNET_MessageHeader)}, {NULL, NULL, 0, 0} }; static const struct GNUNET_CORE_MessageHandler core_handlers[] = { {&handle_p2p_size_estimate, GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD, sizeof (struct GNUNET_NSE_FloodMessage)}, {NULL, 0, 0} }; char *proof; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; cfg = c; srv = server; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "NSE", "INTERVAL", &gnunet_nse_interval)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "INTERVAL"); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "NSE", "WORKDELAY", &proof_find_delay)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKDELAY"); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "NSE", "WORKBITS", &nse_work_required)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKBITS"); GNUNET_SCHEDULER_shutdown (); return; } if (nse_work_required >= sizeof (struct GNUNET_HashCode) * 8) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "NSE", "WORKBITS", _("Value is too large.\n")); GNUNET_SCHEDULER_shutdown (); return; } #if ENABLE_NSE_HISTOGRAM { char *histogram_dir; char *histogram_fn; if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "HISTOGRAM_DIR", &histogram_dir)) { GNUNET_assert (0 < GNUNET_asprintf (&histogram_fn, "%s/timestamps", histogram_dir)); GNUNET_free (histogram_dir); histogram = GNUNET_BIO_write_open (histogram_fn); GNUNET_free (histogram_fn); if (NULL == histogram) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to open histogram file\n"); } logger_test = GNUNET_CLIENT_service_test ("testbed-logger", cfg, GNUNET_TIME_UNIT_SECONDS, &status_cb, NULL); } #endif GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); pk = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg); GNUNET_assert (NULL != pk); my_private_key = pk; GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_identity.public_key); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "NSE", "PROOFFILE", &proof)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "NSE", "PROOFFILE"); GNUNET_free (my_private_key); my_private_key = NULL; GNUNET_SCHEDULER_shutdown (); return; } if ((GNUNET_YES != GNUNET_DISK_file_test (proof)) || (sizeof (my_proof) != GNUNET_DISK_fn_read (proof, &my_proof, sizeof (my_proof)))) my_proof = 0; GNUNET_free (proof); proof_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, &find_proof, NULL); peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); GNUNET_SERVER_add_handlers (srv, handlers); nc = GNUNET_SERVER_notification_context_create (srv, 1); /* Connect to core service and register core handlers */ core_api = GNUNET_CORE_connect (cfg, /* Main configuration */ NULL, /* Closure passed to functions */ &core_init, /* Call core_init once connected */ &handle_core_connect, /* Handle connects */ &handle_core_disconnect, /* Handle disconnects */ NULL, /* Don't want notified about all incoming messages */ GNUNET_NO, /* For header only inbound notification */ NULL, /* Don't want notified about all outbound messages */ GNUNET_NO, /* For header only outbound notification */ core_handlers); /* Register these handlers */ if (NULL == core_api) { GNUNET_SCHEDULER_shutdown (); return; } stats = GNUNET_STATISTICS_create ("nse", cfg); } /** * The main function for the network size estimation service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "nse", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } #ifdef LINUX #include /** * MINIMIZE heap size (way below 128k) since this process doesn't need much. */ void __attribute__ ((constructor)) GNUNET_ARM_memory_init () { mallopt (M_TRIM_THRESHOLD, 4 * 1024); mallopt (M_TOP_PAD, 1 * 1024); malloc_trim (0); } #endif /* end of gnunet-service-nse.c */ gnunet-0.10.1/src/nse/test_nse_multipeer.c0000644000175000017500000001363212225777502015462 00000000000000/* This file is part of GNUnet. (C) 2009, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file nse/test_nse_multipeer.c * @brief Testcase for the network size estimation service. Starts * a peergroup with a given number of peers, then waits to * receive size estimates from each peer. Expects to wait * for one message from each peer. */ #include "platform.h" #include "gnunet_testbed_service.h" #include "gnunet_nse_service.h" /** * How many peers do we start? */ #define NUM_PEERS 4 /** * How long do we run the test? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) /** * Information we track for each peer. */ struct NSEPeer { /** * Handle for NSE connect operation. */ struct GNUNET_TESTBED_Operation *op; /** * Handle to NSE service. */ struct GNUNET_NSE_Handle *nse_handle; }; /** * Information for all the peers. */ static struct NSEPeer nse_peers[NUM_PEERS]; /** * Return value from 'main'. */ static int ok; /** * Task run on timeout to shut everything down. */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int i; for (i=0;iop); if (NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to NSE service: %s\n", emsg); ok = 1; GNUNET_SCHEDULER_shutdown (); return; } peer->nse_handle = nse; } /** * Adapter function called to establish a connection to * the NSE service. * * @param cls closure * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * nse_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_NSE_connect (cfg, &handle_estimate, cls); } /** * Adapter function called to destroy connection to * NSE service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void nse_disconnect_adapter (void *cls, void *op_result) { GNUNET_NSE_disconnect (op_result); } /** * Actual "main" function for the testcase. * * @param cls closure * @param h the run handle * @param num_peers number of peers in 'peers' * @param peers handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { unsigned int i; GNUNET_assert (NUM_PEERS == num_peers); for (i=0;inse_op) GNUNET_TESTBED_operation_done (pos->nse_op); if (NULL != pos->stat_op) GNUNET_TESTBED_operation_done (pos->stat_op); GNUNET_CONTAINER_DLL_remove (peer_head, peer_tail, pos); GNUNET_free (pos); } while (NULL != (oplist_entry = oplist_head)) { GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, oplist_entry); GNUNET_TESTBED_operation_done (oplist_entry->op); GNUNET_free (oplist_entry); } } /** * Task run on shutdown; cleans up everything. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { shutdown_task_id = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_YES == shutting_down) return; shutting_down = GNUNET_YES; LOG_DEBUG ("Ending test.\n"); close_monitor_connections (); if (NULL != data_file) { GNUNET_DISK_file_close (data_file); data_file = NULL; } if (NULL != output_file) { GNUNET_DISK_file_close (output_file); output_file = NULL; } if (NULL != testing_cfg) GNUNET_CONFIGURATION_destroy (testing_cfg); testing_cfg = NULL; } /** * Schedules shutdown task to be run now */ static void shutdown_now () { if (GNUNET_SCHEDULER_NO_TASK != shutdown_task_id) GNUNET_SCHEDULER_cancel (shutdown_task_id); shutdown_task_id = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } /** * Callback to call when network size estimate is updated. * * @param cls closure with the 'struct NSEPeer' providing the update * @param timestamp server timestamp * @param estimate the value of the current network size estimate * @param std_dev standard deviation (rounded down to nearest integer) * of the size estimation values seen */ static void handle_estimate (void *cls, struct GNUNET_TIME_Absolute timestamp, double estimate, double std_dev) { struct NSEPeer *peer = cls; char output_buffer[512]; size_t size; if (NULL == output_file) { FPRINTF (stderr, "Received network size estimate from peer %p. Size: %f std.dev. %f\n", peer, estimate, std_dev); return; } size = GNUNET_snprintf (output_buffer, sizeof (output_buffer), "%p %llu %llu %f %f %f\n", peer, peers_running, (unsigned long long) timestamp.abs_value_us, GNUNET_NSE_log_estimate_to_n (estimate), estimate, std_dev); if (size != GNUNET_DISK_file_write (output_file, output_buffer, size)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); } /** * Adapter function called to establish a connection to * NSE service. * * @param cls closure (the 'struct NSEPeer') * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * nse_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct NSEPeer *current_peer = cls; return GNUNET_NSE_connect (cfg, &handle_estimate, current_peer); } /** * Adapter function called to destroy a connection to * NSE service. * * @param cls closure * @param op_result service handle returned from the connect adapter */ static void nse_disconnect_adapter (void *cls, void *op_result) { GNUNET_NSE_disconnect (op_result); } /** * Callback function to process statistic values. * * @param cls `struct NSEPeer` * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration */ static int stat_iterator (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { char *output_buffer; struct GNUNET_TIME_Absolute now; size_t size; unsigned int flag; GNUNET_assert (NULL != data_file); now = GNUNET_TIME_absolute_get (); flag = strcasecmp (subsystem, "core"); if (0 != flag) flag = 1; size = GNUNET_asprintf (&output_buffer, "%llu %llu %u\n", now.abs_value_us / 1000LL / 1000LL, value, flag); if (size != GNUNET_DISK_file_write (data_file, output_buffer, size)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to write to file!\n"); GNUNET_free (output_buffer); return GNUNET_SYSERR; } GNUNET_free (output_buffer); return GNUNET_OK; } /** * Called to open a connection to the peer's statistics * * @param cls peer context * @param cfg configuration of the peer to connect to; will be available until * GNUNET_TESTBED_operation_done() is called on the operation returned * from GNUNET_TESTBED_service_connect() * @return service handle to return in 'op_result', NULL on error */ static void * stat_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct NSEPeer *peer = cls; peer->sh = GNUNET_STATISTICS_create ("nse-profiler", cfg); return peer->sh; } /** * Called to disconnect from peer's statistics service * * @param cls peer context * @param op_result service handle returned from the connect adapter */ static void stat_disconnect_adapter (void *cls, void *op_result) { struct NSEPeer *peer = cls; GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "core", "# peers connected", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel (peer->sh, "nse", "# peers connected", stat_iterator, peer)); GNUNET_STATISTICS_destroy (op_result, GNUNET_NO); peer->sh = NULL; } /** * Called after successfully opening a connection to a peer's statistics * service; we register statistics monitoring for CORE and NSE here. * * @param cls the callback closure from functions generating an operation * @param op the operation that has been finished * @param ca_result the service handle returned from GNUNET_TESTBED_ConnectAdapter() * @param emsg error message in case the operation has failed; will be NULL if * operation has executed successfully. */ static void stat_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg ) { struct GNUNET_STATISTICS_Handle *sh = ca_result; struct NSEPeer *peer = cls; if (NULL != emsg) { GNUNET_break (0); return; } GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, "core", "# peers connected", stat_iterator, peer)); GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch (sh, "nse", "# peers connected", stat_iterator, peer)); } /** * Task run to connect to the NSE and statistics services to a subset of * all of the running peers. */ static void connect_nse_service () { struct NSEPeer *current_peer; unsigned int i; unsigned int connections; if (0 == connection_limit) return; LOG_DEBUG ("Connecting to nse service of peers\n"); connections = 0; for (i = 0; i < num_peers_in_round[current_round]; i++) { if ((num_peers_in_round[current_round] > connection_limit) && (0 != (i % (num_peers_in_round[current_round] / connection_limit)))) continue; LOG_DEBUG ("Connecting to nse service of peer %d\n", i); current_peer = GNUNET_new (struct NSEPeer); current_peer->daemon = daemons[i]; current_peer->nse_op = GNUNET_TESTBED_service_connect (NULL, current_peer->daemon, "nse", NULL, NULL, &nse_connect_adapter, &nse_disconnect_adapter, current_peer); if (NULL != data_file) current_peer->stat_op = GNUNET_TESTBED_service_connect (NULL, current_peer->daemon, "statistics", stat_comp_cb, current_peer, &stat_connect_adapter, &stat_disconnect_adapter, current_peer); GNUNET_CONTAINER_DLL_insert (peer_head, peer_tail, current_peer); if (++connections == connection_limit) break; } } /** * Task that starts/stops peers to move to the next round. * * @param cls NULL, unused * @param tc scheduler context (unused) */ static void next_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * We're at the end of a round. Stop monitoring, write total * number of connections to log and get full stats. Then trigger * the next round. * * @param cls unused, NULL * @param tc unused */ static void finish_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; LOG (GNUNET_ERROR_TYPE_INFO, "Have %u connections\n", total_connections); close_monitor_connections (); GNUNET_SCHEDULER_add_now (&next_round, NULL); } /** * We have reached the desired number of peers for the current round. * Run it (by connecting and monitoring a few peers and waiting the * specified delay before finishing the round). */ static void run_round () { LOG_DEBUG ("Running round %u\n", current_round); connect_nse_service (); GNUNET_SCHEDULER_add_delayed (wait_time, &finish_round, NULL); } /** * Creates an oplist entry and adds it to the oplist DLL */ static struct OpListEntry * make_oplist_entry () { struct OpListEntry *entry; entry = GNUNET_new (struct OpListEntry); GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry); return entry; } /** * Callback to be called when NSE service is started or stopped at peers * * @param cls NULL * @param op the operation handle * @param emsg NULL on success; otherwise an error description */ static void manage_service_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { struct OpListEntry *entry = cls; GNUNET_TESTBED_operation_done (entry->op); if (NULL != emsg) { LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop NSE at a peer\n"); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_assert (0 != entry->delta); peers_running += entry->delta; GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry); GNUNET_free (entry); if (num_peers_in_round[current_round] == peers_running) run_round (); } /** * Adjust the number of running peers to match the required number of running * peers for the round */ static void adjust_running_peers () { struct OpListEntry *entry; unsigned int i; /* start peers if we have too few */ for (i=peers_running;idelta = 1; entry->op = GNUNET_TESTBED_peer_manage_service (NULL, daemons[i], "nse", &manage_service_cb, entry, 1); } /* stop peers if we have too many */ for (i=num_peers_in_round[current_round];idelta = -1; entry->op = GNUNET_TESTBED_peer_manage_service (NULL, daemons[i], "nse", &manage_service_cb, entry, 0); } } /** * Task run at the end of a round. Disconnect from all monitored * peers; then get statistics from *all* peers. * * @param cls NULL, unused * @param tc unused */ static void next_round (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; LOG_DEBUG ("Disconnecting nse service of peers\n"); current_round++; if (current_round == num_rounds) { /* this was the last round, terminate */ ok = 0; GNUNET_SCHEDULER_shutdown (); return; } if (num_peers_in_round[current_round] == peers_running) { /* no need to churn, just run next round */ run_round (); return; } adjust_running_peers (); } /** * Function that will be called whenever something in the * testbed changes. * * @param cls closure, NULL * @param event information on what is happening */ static void master_controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { case GNUNET_TESTBED_ET_CONNECT: total_connections++; break; case GNUNET_TESTBED_ET_DISCONNECT: total_connections--; break; default: break; } } /** * Signature of a main function for a testcase. * * @param cls NULL * @param h the run handle * @param num_peers_ number of peers in 'peers' * @param peers handle to peers run in the testbed. NULL upon timeout (see * GNUNET_TESTBED_test_run()). * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void test_master (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers_, struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, unsigned int links_failed) { if (NULL == peers) { shutdown_now (); return; } daemons = peers; GNUNET_break (num_peers_ == num_peers); peers_running = num_peers; if (num_peers_in_round[current_round] == peers_running) { /* no need to churn, just run the starting round */ run_round (); return; } adjust_running_peers (); } /** * Actual main function that runs the emulation. * * @param cls unused * @param args remaining args, unused * @param cfgfile name of the configuration * @param cfg configuration handle */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { char *tok; uint64_t event_mask; unsigned int num; ok = 1; testing_cfg = GNUNET_CONFIGURATION_dup (cfg); LOG_DEBUG ("Starting daemons.\n"); if (NULL == num_peer_spec) { fprintf (stderr, "You need to specify the number of peers to run\n"); return; } for (tok = strtok (num_peer_spec, ","); NULL != tok; tok = strtok (NULL, ",")) { if (1 != sscanf (tok, "%u", &num)) { fprintf (stderr, "You need to specify numbers, not `%s'\n", tok); return; } if (0 == num) { fprintf (stderr, "Refusing to run a round with 0 peers\n"); return; } GNUNET_array_append (num_peers_in_round, num_rounds, num); num_peers = GNUNET_MAX (num_peers, num); } if (0 == num_peers) { fprintf (stderr, "Refusing to run a testbed with no rounds\n"); return; } if ( (NULL != data_filename) && (NULL == (data_file = GNUNET_DISK_file_open (data_filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", data_filename); if ( (NULL != output_filename) && (NULL == (output_file = GNUNET_DISK_file_open (output_filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", output_filename); event_mask = 0LL; event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START); event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP); event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1LL << GNUNET_TESTBED_ET_DISCONNECT); GNUNET_TESTBED_run (hosts_file, cfg, num_peers, event_mask, master_controller_cb, NULL, /* master_controller_cb cls */ &test_master, NULL); /* test_master cls */ shutdown_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * Main function. * * @return 0 on success */ int main (int argc, char *const *argv) { static struct GNUNET_GETOPT_CommandLineOption options[] = { {'C', "connections", "COUNT", gettext_noop ("limit to the number of connections to NSE services, 0 for none"), 1, &GNUNET_GETOPT_set_uint, &connection_limit}, {'d', "details", "FILENAME", gettext_noop ("name of the file for writing connection information and statistics"), 1, &GNUNET_GETOPT_set_string, &data_filename}, {'H', "hosts", "FILENAME", gettext_noop ("name of the file with the login information for the testbed"), 1, &GNUNET_GETOPT_set_string, &hosts_file}, {'o', "output", "FILENAME", gettext_noop ("name of the file for writing the main results"), 1, &GNUNET_GETOPT_set_string, &output_filename}, {'p', "peers", "NETWORKSIZESPEC", gettext_noop ("Number of peers to run in each round, separated by commas"), 1, &GNUNET_GETOPT_set_string, &num_peer_spec}, {'V', "verbose", NULL, gettext_noop ("be verbose (print progress information)"), 0, &GNUNET_GETOPT_increment_value, &verbose}, {'w', "wait", "DELAY", gettext_noop ("delay between rounds"), 1, &GNUNET_GETOPT_set_relative_time, &wait_time}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "nse-profiler", gettext_noop ("Measure quality and performance of the NSE service."), options, &run, NULL)) ok = 1; return ok; } /* end of nse-profiler.c */ gnunet-0.10.1/src/identity/0000755000175000017500000000000012320755626012522 500000000000000gnunet-0.10.1/src/identity/gnunet-service-identity.c0000644000175000017500000006233312241144577017401 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file identity/gnunet-service-identity.c * @brief identity management service * @author Christian Grothoff * * The purpose of this service is to manage private keys that * represent the various egos/pseudonyms/identities of a GNUnet user. * * Todo: * - auto-initialze default egos; maybe trigger default * initializations (such as gnunet-gns-import.sh?) */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet_identity_service.h" #include "identity.h" /** * Information we keep about each ego. */ struct Ego { /** * We keep egos in a DLL. */ struct Ego *next; /** * We keep egos in a DLL. */ struct Ego *prev; /** * Private key of the ego. */ struct GNUNET_CRYPTO_EcdsaPrivateKey *pk; /** * String identifier for the ego. */ char *identifier; }; /** * Handle to our current configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to subsystem configuration which for each subsystem contains * the name of the default ego. */ static struct GNUNET_CONFIGURATION_Handle *subsystem_cfg; /** * Handle to the statistics service. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Notification context, simplifies client broadcasts. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Directory where we store the identities. */ static char *ego_directory; /** * Configuration file name where subsystem information is kept. */ static char *subsystem_cfg_file; /** * Head of DLL of all egos. */ static struct Ego *ego_head; /** * Tail of DLL of all egos. */ static struct Ego *ego_tail; /** * Get the name of the file we use to store a given ego. * * @param ego ego for which we need the filename * @return full filename for the given ego */ static char * get_ego_filename (struct Ego *ego) { char *filename; GNUNET_asprintf (&filename, "%s%s%s", ego_directory, DIR_SEPARATOR_STR, ego->identifier); return filename; } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Ego *e; if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } GNUNET_CONFIGURATION_destroy (subsystem_cfg); subsystem_cfg = NULL; GNUNET_free (subsystem_cfg_file); subsystem_cfg_file = NULL; GNUNET_free (ego_directory); ego_directory = NULL; while (NULL != (e = ego_head)) { GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, e); GNUNET_free (e->pk); GNUNET_free (e->identifier); GNUNET_free (e); } } /** * Send a result code back to the client. * * @param client client that should receive the result code * @param result_code code to transmit * @param emsg error message to include (or NULL for none) */ static void send_result_code (struct GNUNET_SERVER_Client *client, uint32_t result_code, const char *emsg) { struct GNUNET_IDENTITY_ResultCodeMessage *rcm; size_t elen; if (NULL == emsg) elen = 0; else elen = strlen (emsg) + 1; rcm = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) + elen); rcm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE); rcm->header.size = htons (sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) + elen); rcm->result_code = htonl (result_code); if (0 < elen) memcpy (&rcm[1], emsg, elen); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending result %d (%s) to client\n", (int) result_code, emsg); GNUNET_SERVER_notification_context_unicast (nc, client, &rcm->header, GNUNET_NO); GNUNET_free (rcm); } /** * Create an update message with information about the current state of an ego. * * @param ego ego to create message for * @return corresponding update message */ static struct GNUNET_IDENTITY_UpdateMessage * create_update_message (struct Ego *ego) { struct GNUNET_IDENTITY_UpdateMessage *um; size_t name_len; name_len = (NULL == ego->identifier) ? 0 : (strlen (ego->identifier) + 1); um = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_UpdateMessage) + name_len); um->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE); um->header.size = htons (sizeof (struct GNUNET_IDENTITY_UpdateMessage) + name_len); um->name_len = htons (name_len); um->end_of_list = htons (GNUNET_NO); um->private_key = *ego->pk; memcpy (&um[1], ego->identifier, name_len); return um; } /** * Create a set default message with information about the current state of an ego. * * @param ego ego to create message for * @param servicename name of the service to provide in the message * @return corresponding set default message */ static struct GNUNET_IDENTITY_SetDefaultMessage * create_set_default_message (struct Ego *ego, const char *servicename) { struct GNUNET_IDENTITY_SetDefaultMessage *sdm; size_t name_len; name_len = (NULL == servicename) ? 0 : (strlen (servicename) + 1); sdm = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) + name_len); sdm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT); sdm->header.size = htons (sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) + name_len); sdm->name_len = htons (name_len); sdm->reserved = htons (0); sdm->private_key = *ego->pk; memcpy (&sdm[1], servicename, name_len); return sdm; } /** * Handler for START message from client, sends information * about all identities to the client immediately and * adds the client to the notification context for future * updates. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_start_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_IDENTITY_UpdateMessage *um; struct GNUNET_IDENTITY_UpdateMessage ume; struct Ego *ego; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received START message from client\n"); GNUNET_SERVER_notification_context_add (nc, client); for (ego = ego_head; NULL != ego; ego = ego->next) { um = create_update_message (ego); GNUNET_SERVER_notification_context_unicast (nc, client, &um->header, GNUNET_NO); GNUNET_free (um); } memset (&ume, 0, sizeof (ume)); ume.header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE); ume.header.size = htons (sizeof (struct GNUNET_IDENTITY_UpdateMessage)); ume.end_of_list = htons (GNUNET_YES); ume.name_len = htons (0); GNUNET_SERVER_notification_context_unicast (nc, client, &ume.header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handler for GET_DEFAULT message from client, returns * default identity for some service. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_get_default_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_IDENTITY_GetDefaultMessage *gdm; struct GNUNET_IDENTITY_SetDefaultMessage *sdm; uint16_t size; uint16_t name_len; struct Ego *ego; const char *name; char *identifier; size = ntohs (message->size); if (size <= sizeof (struct GNUNET_IDENTITY_GetDefaultMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } gdm = (const struct GNUNET_IDENTITY_GetDefaultMessage *) message; name = (const char *) &gdm[1]; name_len = ntohs (gdm->name_len); if ( (name_len + sizeof (struct GNUNET_IDENTITY_GetDefaultMessage) != size) || (0 != ntohs (gdm->reserved)) || ('\0' != name[name_len - 1]) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received GET_DEFAULT for service `%s' from client\n", name); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg, name, "DEFAULT_IDENTIFIER", &identifier)) { send_result_code (client, 1, gettext_noop ("no default known")); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == strcmp (ego->identifier, identifier)) { sdm = create_set_default_message (ego, name); GNUNET_SERVER_notification_context_unicast (nc, client, &sdm->header, GNUNET_NO); GNUNET_free (sdm); GNUNET_SERVER_receive_done (client, GNUNET_OK); GNUNET_free (identifier); return; } } GNUNET_free (identifier); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to find ego `%s'\n", name); send_result_code (client, 1, gettext_noop ("default configured, but ego unknown (internal error)")); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Compare the given two private keys for equality. * * @param pk1 one private key * @param pk2 another private key * @return 0 if the keys are equal */ static int key_cmp (const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk1, const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk2) { return memcmp (pk1, pk2, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); } /** * Handler for SET_DEFAULT message from client, updates * default identity for some service. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_set_default_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_IDENTITY_SetDefaultMessage *sdm; uint16_t size; uint16_t name_len; struct Ego *ego; const char *str; size = ntohs (message->size); if (size <= sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } sdm = (const struct GNUNET_IDENTITY_SetDefaultMessage *) message; name_len = ntohs (sdm->name_len); GNUNET_break (0 == ntohs (sdm->reserved)); if (name_len + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) != size) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } str = (const char *) &sdm[1]; if ('\0' != str[name_len - 1]) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received SET_DEFAULT for service `%s' from client\n", str); for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == key_cmp (ego->pk, &sdm->private_key)) { GNUNET_CONFIGURATION_set_value_string (subsystem_cfg, str, "DEFAULT_IDENTIFIER", ego->identifier); if (GNUNET_OK != GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to write subsystem default identifier map to `%s'.\n"), subsystem_cfg_file); send_result_code (client, 0, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } } send_result_code (client, 1, _("Unknown ego specified for service (internal error)")); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Send an updated message for the given ego to all listeners. * * @param ego ego to send the update for */ static void notify_listeners (struct Ego *ego) { struct GNUNET_IDENTITY_UpdateMessage *um; um = create_update_message (ego); GNUNET_SERVER_notification_context_broadcast (nc, &um->header, GNUNET_NO); GNUNET_free (um); } /** * Handler for CREATE message from client, creates * new identity. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_create_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_IDENTITY_CreateRequestMessage *crm; uint16_t size; uint16_t name_len; struct Ego *ego; const char *str; char *fn; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received CREATE message from client\n"); size = ntohs (message->size); if (size <= sizeof (struct GNUNET_IDENTITY_CreateRequestMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } crm = (const struct GNUNET_IDENTITY_CreateRequestMessage *) message; name_len = ntohs (crm->name_len); GNUNET_break (0 == ntohs (crm->reserved)); if (name_len + sizeof (struct GNUNET_IDENTITY_CreateRequestMessage) != size) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } str = (const char *) &crm[1]; if ('\0' != str[name_len - 1]) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == strcmp (ego->identifier, str)) { send_result_code (client, 1, gettext_noop ("identifier already in use for another ego")); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } } ego = GNUNET_new (struct Ego); ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); *ego->pk = crm->private_key; ego->identifier = GNUNET_strdup (str); GNUNET_CONTAINER_DLL_insert (ego_head, ego_tail, ego); send_result_code (client, 0, NULL); fn = get_ego_filename (ego); (void) GNUNET_DISK_directory_create_for_file (fn); if (sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) != GNUNET_DISK_fn_write (fn, &crm->private_key, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "write", fn); GNUNET_free (fn); notify_listeners (ego); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Closure for 'handle_ego_rename'. */ struct RenameContext { /** * Old name. */ const char *old_name; /** * New name. */ const char *new_name; }; /** * An ego was renamed; rename it in all subsystems where it is * currently set as the default. * * @param cls the 'struct RenameContext' * @param section a section in the configuration to process */ static void handle_ego_rename (void *cls, const char *section) { struct RenameContext *rc = cls; char *id; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg, section, "DEFAULT_IDENTIFIER", &id)) return; if (0 != strcmp (id, rc->old_name)) { GNUNET_free (id); return; } GNUNET_CONFIGURATION_set_value_string (subsystem_cfg, section, "DEFAULT_IDENTIFIER", rc->new_name); GNUNET_free (id); } /** * Handler for RENAME message from client, creates * new identity. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_rename_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_IDENTITY_RenameMessage *rm; uint16_t size; uint16_t old_name_len; uint16_t new_name_len; struct Ego *ego; const char *old_name; const char *new_name; struct RenameContext rename_ctx; char *fn_old; char *fn_new; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received RENAME message from client\n"); size = ntohs (message->size); if (size <= sizeof (struct GNUNET_IDENTITY_RenameMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } rm = (const struct GNUNET_IDENTITY_RenameMessage *) message; old_name_len = ntohs (rm->old_name_len); new_name_len = ntohs (rm->new_name_len); old_name = (const char *) &rm[1]; new_name = &old_name[old_name_len]; if ( (old_name_len + new_name_len + sizeof (struct GNUNET_IDENTITY_RenameMessage) != size) || ('\0' != old_name[old_name_len - 1]) || ('\0' != new_name[new_name_len - 1]) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } /* check if new name is already in use */ for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == strcmp (ego->identifier, new_name)) { send_result_code (client, 1, gettext_noop ("target name already exists")); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } } /* locate old name and, if found, perform rename */ for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == strcmp (ego->identifier, old_name)) { fn_old = get_ego_filename (ego); GNUNET_free (ego->identifier); rename_ctx.old_name = old_name; rename_ctx.new_name = new_name; GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg, &handle_ego_rename, &rename_ctx); if (GNUNET_OK != GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to write subsystem default identifier map to `%s'.\n"), subsystem_cfg_file); ego->identifier = GNUNET_strdup (new_name); fn_new = get_ego_filename (ego); if (0 != RENAME (fn_old, fn_new)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rename", fn_old); GNUNET_free (fn_old); GNUNET_free (fn_new); notify_listeners (ego); send_result_code (client, 0, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } } /* failed to locate old name */ send_result_code (client, 1, gettext_noop ("no matching ego found")); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * An ego was removed, remove it from all subsystems where it is * currently set as the default. * * @param cls name of the removed ego (const char *) * @param section a section in the configuration to process */ static void handle_ego_delete (void *cls, const char *section) { const char *identifier = cls; char *id; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (subsystem_cfg, section, "DEFAULT_IDENTIFIER", &id)) return; if (0 != strcmp (id, identifier)) { GNUNET_free (id); return; } GNUNET_CONFIGURATION_set_value_string (subsystem_cfg, section, "DEFAULT_IDENTIFIER", NULL); GNUNET_free (id); } /** * Handler for DELETE message from client, creates * new identity. * * @param cls unused * @param client who sent the message * @param message the message received */ static void handle_delete_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_IDENTITY_DeleteMessage *dm; uint16_t size; uint16_t name_len; struct Ego *ego; const char *name; char *fn; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received DELETE message from client\n"); size = ntohs (message->size); if (size <= sizeof (struct GNUNET_IDENTITY_DeleteMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } dm = (const struct GNUNET_IDENTITY_DeleteMessage *) message; name = (const char *) &dm[1]; name_len = ntohs (dm->name_len); if ( (name_len + sizeof (struct GNUNET_IDENTITY_DeleteMessage) != size) || (0 != ntohs (dm->reserved)) || ('\0' != name[name_len - 1]) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } for (ego = ego_head; NULL != ego; ego = ego->next) { if (0 == strcmp (ego->identifier, name)) { GNUNET_CONTAINER_DLL_remove (ego_head, ego_tail, ego); GNUNET_CONFIGURATION_iterate_sections (subsystem_cfg, &handle_ego_delete, ego->identifier); if (GNUNET_OK != GNUNET_CONFIGURATION_write (subsystem_cfg, subsystem_cfg_file)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to write subsystem default identifier map to `%s'.\n"), subsystem_cfg_file); fn = get_ego_filename (ego); if (0 != UNLINK (fn)) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); GNUNET_free (fn); GNUNET_free (ego->identifier); ego->identifier = NULL; notify_listeners (ego); GNUNET_free (ego->pk); GNUNET_free (ego); send_result_code (client, 0, NULL); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } } send_result_code (client, 1, gettext_noop ("no matching ego found")); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Process the given file from the "EGODIR". Parses the file * and creates the respective 'struct Ego' in memory. * * @param cls NULL * @param filename name of the file to parse * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, * #GNUNET_SYSERR to abort iteration with error! */ static int process_ego_file (void *cls, const char *filename) { struct Ego *ego; const char *fn; fn = strrchr (filename, (int) DIR_SEPARATOR); if (NULL == fn) { GNUNET_break (0); return GNUNET_OK; } ego = GNUNET_new (struct Ego); ego->pk = GNUNET_CRYPTO_ecdsa_key_create_from_file (filename); if (NULL == ego->pk) { GNUNET_free (ego); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to parse ego information in `%s'\n"), filename); return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loaded ego `%s'\n", fn + 1); ego->identifier = GNUNET_strdup (fn + 1); GNUNET_CONTAINER_DLL_insert (ego_head, ego_tail, ego); return GNUNET_OK; } /** * Handle network size estimate clients. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_start_message, NULL, GNUNET_MESSAGE_TYPE_IDENTITY_START, sizeof (struct GNUNET_MessageHeader)}, {&handle_get_default_message, NULL, GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT, 0}, {&handle_set_default_message, NULL, GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT, 0}, {&handle_create_message, NULL, GNUNET_MESSAGE_TYPE_IDENTITY_CREATE, 0}, {&handle_rename_message, NULL, GNUNET_MESSAGE_TYPE_IDENTITY_RENAME, 0}, {&handle_delete_message, NULL, GNUNET_MESSAGE_TYPE_IDENTITY_DELETE, 0}, {NULL, NULL, 0, 0} }; cfg = c; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "identity", "EGODIR", &ego_directory)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "EGODIR"); GNUNET_SCHEDULER_shutdown (); return; } if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "identity", "SUBSYSTEM_CFG", &subsystem_cfg_file)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "identity", "SUBSYSTEM_CFG"); GNUNET_SCHEDULER_shutdown (); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading subsystem configuration `%s'\n", subsystem_cfg_file); subsystem_cfg = GNUNET_CONFIGURATION_create (); if ( (GNUNET_YES == GNUNET_DISK_file_test (subsystem_cfg_file)) && (GNUNET_OK != GNUNET_CONFIGURATION_parse (subsystem_cfg, subsystem_cfg_file)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse subsystem identity configuration file `%s'\n"), subsystem_cfg_file); GNUNET_SCHEDULER_shutdown (); return; } stats = GNUNET_STATISTICS_create ("identity", cfg); GNUNET_SERVER_add_handlers (server, handlers); nc = GNUNET_SERVER_notification_context_create (server, 1); if (GNUNET_OK != GNUNET_DISK_directory_create (ego_directory)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to create directory `%s' for storing egos\n"), ego_directory); } GNUNET_DISK_directory_scan (ego_directory, &process_ego_file, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for the network size estimation service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "identity", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-identity.c */ gnunet-0.10.1/src/identity/gnunet-identity.c0000644000175000017500000002105012225777502015734 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file identity/gnunet-identity.c * @brief IDENTITY management command line tool * @author Christian Grothoff * * Todo: * - add options to get default egos */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_identity_service.h" /** * Handle to IDENTITY service. */ static struct GNUNET_IDENTITY_Handle *sh; /** * Was "list" specified? */ static int list; /** * Was "monitor" specified? */ static int monitor; /** * -C option */ static char *create_ego; /** * -D option */ static char *delete_ego; /** * -s option. */ static char *set_ego; /** * -S option. */ static char *set_subsystem; /** * Operation handle for set operation. */ static struct GNUNET_IDENTITY_Operation *set_op; /** * Handle for create operation. */ static struct GNUNET_IDENTITY_Operation *create_op; /** * Handle for delete operation. */ static struct GNUNET_IDENTITY_Operation *delete_op; /** * Task run on shutdown. * * @param cls NULL * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != set_op) { GNUNET_IDENTITY_cancel (set_op); set_op = NULL; } if (NULL != create_op) { GNUNET_IDENTITY_cancel (create_op); create_op = NULL; } if (NULL != delete_op) { GNUNET_IDENTITY_cancel (delete_op); delete_op = NULL; } GNUNET_IDENTITY_disconnect (sh); sh = NULL; } /** * Test if we are finished yet. */ static void test_finished () { if ( (NULL == create_op) && (NULL == delete_op) && (NULL == set_op) && (NULL == set_ego) && (! list) && (! monitor) ) GNUNET_SCHEDULER_shutdown (); } /** * Deletion operation finished. * * @param cls pointer to operation handle * @param emsg NULL on success, otherwise an error message */ static void delete_finished (void *cls, const char *emsg) { struct GNUNET_IDENTITY_Operation **op = cls; *op = NULL; if (NULL != emsg) fprintf (stderr, "%s\n", gettext (emsg)); test_finished (); } /** * Creation operation finished. * * @param cls pointer to operation handle * @param emsg error message, NULL on success */ static void create_finished (void *cls, const char *emsg) { struct GNUNET_IDENTITY_Operation **op = cls; *op = NULL; if (NULL != emsg) fprintf (stderr, _("Failed to create ego: %s\n"), emsg); test_finished (); } /** * Function called by #GNUNET_IDENTITY_set up on completion. * * @param cls NULL * @param emsg error message (NULL on success) */ static void set_done (void *cls, const char *emsg) { set_op = NULL; if (NULL != emsg) fprintf (stderr, _("Failed to set default ego: %s\n"), emsg); test_finished (); } /** * If listing is enabled, prints information about the egos. * * This function is initially called for all egos and then again * whenever a ego's identifier changes or if it is deleted. At the * end of the initial pass over all egos, the function is once called * with 'NULL' for 'ego'. That does NOT mean that the callback won't * be invoked in the future or that there was an error. * * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', * this function is only called ONCE, and 'NULL' being passed in * 'ego' does indicate an error (i.e. name is taken or no default * value is known). If 'ego' is non-NULL and if '*ctx' * is set in those callbacks, the value WILL be passed to a subsequent * call to the identity callback of 'GNUNET_IDENTITY_connect' (if * that one was not NULL). * * When an identity is renamed, this function is called with the * (known) ego but the NEW identifier. * * When an identity is deleted, this function is called with the * (known) ego and "NULL" for the 'identifier'. In this case, * the 'ego' is henceforth invalid (and the 'ctx' should also be * cleaned up). * * @param cls closure * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param identifier identifier assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void print_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier) { struct GNUNET_CRYPTO_EcdsaPublicKey pk; char *s; if ( (NULL != set_ego) && (NULL != ego) && (NULL != identifier) && (0 == strcmp (identifier, set_ego)) ) { set_op = GNUNET_IDENTITY_set (sh, set_subsystem, ego, &set_done, NULL); GNUNET_free (set_subsystem); set_subsystem = NULL; GNUNET_free (set_ego); set_ego = NULL; } if ( (NULL == ego) && (NULL != set_ego) ) { fprintf (stderr, "Could not set ego to `%s' for subsystem `%s', ego not known\n", set_ego, set_subsystem); GNUNET_free (set_subsystem); set_subsystem = NULL; GNUNET_free (set_ego); set_ego = NULL; } if ( (NULL == ego) && (! monitor) ) { GNUNET_SCHEDULER_shutdown (); return; } if (! (list | monitor)) return; if (NULL == ego) return; GNUNET_IDENTITY_ego_get_public_key (ego, &pk); s = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); if ( (monitor) || (NULL != identifier) ) fprintf (stdout, "%s - %s\n", identifier, s); GNUNET_free (s); } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { if ( (NULL == set_subsystem) ^ (NULL == set_ego) ) { fprintf (stderr, "Options -e and -s must always be specified together\n"); return; } sh = GNUNET_IDENTITY_connect (cfg, &print_ego, NULL); if (NULL != delete_ego) delete_op = GNUNET_IDENTITY_delete (sh, delete_ego, &delete_finished, &delete_op); if (NULL != create_ego) create_op = GNUNET_IDENTITY_create (sh, create_ego, &create_finished, &create_op); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); test_finished (); } /** * The main function. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int res; static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'C', "create", "NAME", gettext_noop ("create ego NAME"), 1, &GNUNET_GETOPT_set_string, &create_ego}, {'D', "delete", "NAME", gettext_noop ("delete ego NAME "), 1, &GNUNET_GETOPT_set_string, &delete_ego}, {'d', "display", NULL, gettext_noop ("display all egos"), 0, &GNUNET_GETOPT_set_one, &list}, {'e', "ego", "NAME", gettext_noop ("set default identity to EGO for a subsystem SUBSYSTEM (use together with -s)"), 1, &GNUNET_GETOPT_set_string, &set_ego}, {'m', "monitor", NULL, gettext_noop ("run in monitor mode egos"), 0, &GNUNET_GETOPT_set_one, &monitor}, {'s', "set", "SUBSYSYSTEM", gettext_noop ("set default identity to EGO for a subsystem SUBSYSTEM (use together with -e)"), 1, &GNUNET_GETOPT_set_string, &set_subsystem}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; res = GNUNET_PROGRAM_run (argc, argv, "gnunet-identity", gettext_noop ("Maintain egos"), options, &run, NULL); GNUNET_free ((void *) argv); if (GNUNET_OK != res) return 1; return 0; } /* end of gnunet-identity.c */ gnunet-0.10.1/src/identity/Makefile.in0000644000175000017500000013236612320752062014511 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = gnunet-identity$(EXEEXT) libexec_PROGRAMS = gnunet-service-identity$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = test_identity$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_identity_defaults$(EXEEXT) subdir = src/identity DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/identity.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = identity.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunetidentity_la_OBJECTS = identity_api.lo \ identity_api_lookup.lo libgnunetidentity_la_OBJECTS = $(am_libgnunetidentity_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetidentity_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetidentity_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_identity_OBJECTS = gnunet-identity.$(OBJEXT) gnunet_identity_OBJECTS = $(am_gnunet_identity_OBJECTS) am_gnunet_service_identity_OBJECTS = \ gnunet-service-identity.$(OBJEXT) gnunet_service_identity_OBJECTS = \ $(am_gnunet_service_identity_OBJECTS) am_test_identity_OBJECTS = test_identity.$(OBJEXT) test_identity_OBJECTS = $(am_test_identity_OBJECTS) am_test_identity_defaults_OBJECTS = test_identity_defaults.$(OBJEXT) test_identity_defaults_OBJECTS = $(am_test_identity_defaults_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetidentity_la_SOURCES) $(gnunet_identity_SOURCES) \ $(gnunet_service_identity_SOURCES) $(test_identity_SOURCES) \ $(test_identity_defaults_SOURCES) DIST_SOURCES = $(libgnunetidentity_la_SOURCES) \ $(gnunet_identity_SOURCES) $(gnunet_service_identity_SOURCES) \ $(test_identity_SOURCES) $(test_identity_defaults_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ identity.conf lib_LTLIBRARIES = libgnunetidentity.la libgnunetidentity_la_SOURCES = \ identity_api.c \ identity_api_lookup.c \ identity.h libgnunetidentity_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetidentity_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetidentity_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la gnunet_service_identity_SOURCES = \ gnunet-service-identity.c gnunet_service_identity_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_identity_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_identity_SOURCES = \ gnunet-identity.c gnunet_identity_LDADD = \ libgnunetidentity.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_identity_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_identity_SOURCES = \ test_identity.c test_identity_LDADD = \ libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_identity_DEPENDENCIES = \ libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_identity_defaults_SOURCES = \ test_identity_defaults.c test_identity_defaults_LDADD = \ libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_identity_defaults_DEPENDENCIES = \ libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_identity.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/identity/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/identity/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): identity.conf: $(top_builddir)/config.status $(srcdir)/identity.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetidentity.la: $(libgnunetidentity_la_OBJECTS) $(libgnunetidentity_la_DEPENDENCIES) $(EXTRA_libgnunetidentity_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetidentity_la_LINK) -rpath $(libdir) $(libgnunetidentity_la_OBJECTS) $(libgnunetidentity_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-identity$(EXEEXT): $(gnunet_identity_OBJECTS) $(gnunet_identity_DEPENDENCIES) $(EXTRA_gnunet_identity_DEPENDENCIES) @rm -f gnunet-identity$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_identity_OBJECTS) $(gnunet_identity_LDADD) $(LIBS) gnunet-service-identity$(EXEEXT): $(gnunet_service_identity_OBJECTS) $(gnunet_service_identity_DEPENDENCIES) $(EXTRA_gnunet_service_identity_DEPENDENCIES) @rm -f gnunet-service-identity$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_identity_OBJECTS) $(gnunet_service_identity_LDADD) $(LIBS) test_identity$(EXEEXT): $(test_identity_OBJECTS) $(test_identity_DEPENDENCIES) $(EXTRA_test_identity_DEPENDENCIES) @rm -f test_identity$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_identity_OBJECTS) $(test_identity_LDADD) $(LIBS) test_identity_defaults$(EXEEXT): $(test_identity_defaults_OBJECTS) $(test_identity_defaults_DEPENDENCIES) $(EXTRA_test_identity_defaults_DEPENDENCIES) @rm -f test_identity_defaults$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_identity_defaults_OBJECTS) $(test_identity_defaults_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-identity.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-identity.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/identity_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/identity_api_lookup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_identity.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_identity_defaults.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_identity.log: test_identity$(EXEEXT) @p='test_identity$(EXEEXT)'; \ b='test_identity'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_identity_defaults.log: test_identity_defaults$(EXEEXT) @p='test_identity_defaults$(EXEEXT)'; \ b='test_identity_defaults'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/identity/identity.conf.in0000644000175000017500000000077012252271745015552 00000000000000[identity] AUTOSTART = @AUTOSTART@ USER_SERVICE = YES @JAVAPORT@PORT = 2108 HOSTNAME = localhost BINARY = gnunet-service-identity ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-identity.unix UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES # Directory where we store information about our egos EGODIR = $GNUNET_DATA_HOME/identity/egos/ # File where we store default identities for subsystems SUBSYSTEM_CFG = $GNUNET_CONFIG_HOME/identity/subsystem_defaults.conf gnunet-0.10.1/src/identity/identity_api.c0000644000175000017500000006270312242135660015271 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public Liceidentity as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Liceidentity for more details. You should have received a copy of the GNU General Public Liceidentity along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file identity/identity_api.c * @brief api to interact with the identity service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_identity_service.h" #include "identity.h" #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) /** * Handle for an ego. */ struct GNUNET_IDENTITY_Ego { /** * Private key associated with this ego. */ struct GNUNET_CRYPTO_EcdsaPrivateKey *pk; /** * Current name associated with this ego. */ char *name; /** * Client context associated with this ego. */ void *ctx; /** * Hash of the public key of this ego. */ struct GNUNET_HashCode id; }; /** * Handle for an operation with the identity service. */ struct GNUNET_IDENTITY_Operation { /** * Main identity handle. */ struct GNUNET_IDENTITY_Handle *h; /** * We keep operations in a DLL. */ struct GNUNET_IDENTITY_Operation *next; /** * We keep operations in a DLL. */ struct GNUNET_IDENTITY_Operation *prev; /** * Message to send to the identity service. * Allocated at the end of this struct. */ const struct GNUNET_MessageHeader *msg; /** * Continuation to invoke with the result of the transmission; @e cb * will be NULL in this case. */ GNUNET_IDENTITY_Continuation cont; /** * Continuation to invoke with the result of the transmission for * 'get' operations (@e cont will be NULL in this case). */ GNUNET_IDENTITY_Callback cb; /** * Closure for @e cont or @e cb. */ void *cls; }; /** * Handle for the service. */ struct GNUNET_IDENTITY_Handle { /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Hash map from the hash of the public key to the * respective 'GNUNET_IDENTITY_Ego' handle. */ struct GNUNET_CONTAINER_MultiHashMap *egos; /** * Function to call when we receive updates. */ GNUNET_IDENTITY_Callback cb; /** * Closure for 'cb'. */ void *cb_cls; /** * Head of active operations. */ struct GNUNET_IDENTITY_Operation *op_head; /** * Tail of active operations. */ struct GNUNET_IDENTITY_Operation *op_tail; /** * Currently pending transmission request, or NULL for none. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Task doing exponential back-off trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Time for next connect retry. */ struct GNUNET_TIME_Relative reconnect_delay; /** * Are we polling for incoming messages right now? */ int in_receive; }; /** * Obtain the ego representing 'anonymous' users. * * @return handle for the anonymous user, must not be freed */ const struct GNUNET_IDENTITY_Ego * GNUNET_IDENTITY_ego_get_anonymous () { static struct GNUNET_IDENTITY_Ego anon; struct GNUNET_CRYPTO_EcdsaPublicKey pub; if (NULL != anon.pk) return &anon; anon.pk = (struct GNUNET_CRYPTO_EcdsaPrivateKey *) GNUNET_CRYPTO_ecdsa_key_get_anonymous (); GNUNET_CRYPTO_ecdsa_key_get_public (anon.pk, &pub); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &anon.id); return &anon; } /** * Try again to connect to the identity service. * * @param cls handle to the identity service. * @param tc scheduler context */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Reschedule a connect attempt to the service. * * @param h transport service to reconnect */ static void reschedule_connect (struct GNUNET_IDENTITY_Handle *h) { GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->in_receive = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task to reconnect to identity service in %s.\n", GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, GNUNET_YES)); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); } /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void message_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_IDENTITY_Handle *h = cls; struct GNUNET_IDENTITY_Operation *op; struct GNUNET_IDENTITY_Ego *ego; const struct GNUNET_IDENTITY_ResultCodeMessage *rcm; const struct GNUNET_IDENTITY_UpdateMessage *um; const struct GNUNET_IDENTITY_SetDefaultMessage *sdm; struct GNUNET_CRYPTO_EcdsaPublicKey pub; struct GNUNET_HashCode id; const char *str; uint16_t size; uint16_t name_len; if (NULL == msg) { reschedule_connect (h); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %d from identity service\n", ntohs (msg->type)); size = ntohs (msg->size); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE: if (size < sizeof (struct GNUNET_IDENTITY_ResultCodeMessage)) { GNUNET_break (0); reschedule_connect (h); return; } rcm = (const struct GNUNET_IDENTITY_ResultCodeMessage *) msg; str = (const char *) &rcm[1]; if ( (size > sizeof (struct GNUNET_IDENTITY_ResultCodeMessage)) && ('\0' != str[size - sizeof (struct GNUNET_IDENTITY_ResultCodeMessage) - 1]) ) { GNUNET_break (0); reschedule_connect (h); return; } if (size == sizeof (struct GNUNET_IDENTITY_ResultCodeMessage)) str = NULL; op = h->op_head; GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); if (NULL != op->cont) op->cont (op->cls, str); else if (NULL != op->cb) op->cb (op->cls, NULL, NULL, NULL); GNUNET_free (op); break; case GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE: if (size < sizeof (struct GNUNET_IDENTITY_UpdateMessage)) { GNUNET_break (0); reschedule_connect (h); return; } um = (const struct GNUNET_IDENTITY_UpdateMessage *) msg; name_len = ntohs (um->name_len); str = (const char *) &um[1]; if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_UpdateMessage)) || ( (0 != name_len) && ('\0' != str[name_len - 1])) ) { GNUNET_break (0); reschedule_connect (h); return; } if (GNUNET_YES == ntohs (um->end_of_list)) { /* end of initial list of data */ GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); if (NULL != h->cb) h->cb (h->cb_cls, NULL, NULL, NULL); break; } GNUNET_CRYPTO_ecdsa_key_get_public (&um->private_key, &pub); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id); if (0 == name_len) str = NULL; else str = (const char *) &um[1]; ego = GNUNET_CONTAINER_multihashmap_get (h->egos, &id); if (NULL == ego) { /* ego was created */ if (NULL == str) { /* deletion of unknown ego? not allowed */ GNUNET_break (0); reschedule_connect (h); return; } ego = GNUNET_new (struct GNUNET_IDENTITY_Ego); ego->pk = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey); *ego->pk = um->private_key; ego->name = GNUNET_strdup (str); ego->id = id; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_put (h->egos, &ego->id, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } if (NULL == str) { /* ego was deleted */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (h->egos, &ego->id, ego)); } else { /* ego changed name */ GNUNET_free (ego->name); ego->name = GNUNET_strdup (str); } GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); /* inform application about change */ if (NULL != h->cb) h->cb (h->cb_cls, ego, &ego->ctx, str); if (NULL == str) { GNUNET_free (ego->pk); GNUNET_free (ego->name); GNUNET_free (ego); } break; case GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT: if (size < sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) { GNUNET_break (0); reschedule_connect (h); return; } sdm = (const struct GNUNET_IDENTITY_SetDefaultMessage *) msg; GNUNET_break (0 == ntohs (sdm->reserved)); name_len = ntohs (sdm->name_len); str = (const char *) &sdm[1]; if ( (size != name_len + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) || ( (0 != name_len) && ('\0' != str[name_len - 1]) ) ) { GNUNET_break (0); reschedule_connect (h); return; } /* Note: we know which service this should be for, so we're not really using 'str' henceforth */ GNUNET_CRYPTO_ecdsa_key_get_public (&sdm->private_key, &pub); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &id); ego = GNUNET_CONTAINER_multihashmap_get (h->egos, &id); if (NULL == ego) { GNUNET_break (0); reschedule_connect (h); return; } op = h->op_head; if (NULL == op) { GNUNET_break (0); reschedule_connect (h); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received SET_DEFAULT message from identity service\n"); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); if (NULL != op->cb) op->cb (op->cls, ego, &ego->ctx, ego->name); GNUNET_free (op); break; default: GNUNET_break (0); reschedule_connect (h); return; } } /** * Schedule transmission of the next message from our queue. * * @param h identity handle */ static void transmit_next (struct GNUNET_IDENTITY_Handle *h); /** * Transmit next message to service. * * @param cls the `struct GNUNET_IDENTITY_Handle`. * @param size number of bytes available in @a buf * @param buf where to copy the message * @return number of bytes copied to buf */ static size_t send_next_message (void *cls, size_t size, void *buf) { struct GNUNET_IDENTITY_Handle *h = cls; struct GNUNET_IDENTITY_Operation *op = h->op_head; size_t ret; h->th = NULL; if (NULL == op) return 0; ret = ntohs (op->msg->size); if (ret > size) { reschedule_connect (h); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending message of type %d to identity service\n", ntohs (op->msg->type)); memcpy (buf, op->msg, ret); if ( (NULL == op->cont) && (NULL == op->cb) ) { GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); GNUNET_free (op); transmit_next (h); } if (GNUNET_NO == h->in_receive) { h->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &message_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); } return ret; } /** * Schedule transmission of the next message from our queue. * * @param h identity handle */ static void transmit_next (struct GNUNET_IDENTITY_Handle *h) { struct GNUNET_IDENTITY_Operation *op = h->op_head; GNUNET_assert (NULL == h->th); if (NULL == op) return; if (NULL == h->client) return; h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ntohs (op->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_next_message, h); } /** * Try again to connect to the identity service. * * @param cls handle to the identity service. * @param tc scheduler context */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_IDENTITY_Handle *h = cls; struct GNUNET_IDENTITY_Operation *op; struct GNUNET_MessageHeader msg; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to identity service.\n"); GNUNET_assert (NULL == h->client); h->client = GNUNET_CLIENT_connect ("identity", h->cfg); GNUNET_assert (NULL != h->client); if ( (NULL == h->op_head) || (GNUNET_MESSAGE_TYPE_IDENTITY_START != ntohs (h->op_head->msg->type)) ) { op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_MessageHeader)); op->h = h; op->msg = (const struct GNUNET_MessageHeader *) &op[1]; msg.size = htons (sizeof (msg)); msg.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_START); memcpy (&op[1], &msg, sizeof (msg)); GNUNET_CONTAINER_DLL_insert (h->op_head, h->op_tail, op); } transmit_next (h); GNUNET_assert (NULL != h->th); } /** * Connect to the identity service. * * @param cfg the configuration to use * @param cb function to call on all identity events, can be NULL * @param cb_cls closure for @a cb * @return handle to use */ struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls) { struct GNUNET_IDENTITY_Handle *h; h = GNUNET_new (struct GNUNET_IDENTITY_Handle); h->cfg = cfg; h->cb = cb; h->cb_cls = cb_cls; h->egos = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_YES); h->reconnect_delay = GNUNET_TIME_UNIT_ZERO; h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, h); return h; } /** * Obtain the ECC key associated with a ego. * * @param ego the ego * @return associated ECC key, valid as long as the ego is valid */ const struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego) { return ego->pk; } /** * Get the identifier (public key) of an ego. * * @param ego identity handle with the private key * @param pk set to ego's public key */ void GNUNET_IDENTITY_ego_get_public_key (const struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EcdsaPublicKey *pk) { GNUNET_CRYPTO_ecdsa_key_get_public (ego->pk, pk); } /** * Obtain the identity that is currently preferred/default * for a service. * * @param id identity service to query * @param service_name for which service is an identity wanted * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_get (struct GNUNET_IDENTITY_Handle *id, const char *service_name, GNUNET_IDENTITY_Callback cb, void *cb_cls) { struct GNUNET_IDENTITY_Operation *op; struct GNUNET_IDENTITY_GetDefaultMessage *gdm; size_t slen; slen = strlen (service_name) + 1; if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_GetDefaultMessage)) { GNUNET_break (0); return NULL; } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_GetDefaultMessage) + slen); op->h = id; op->cb = cb; op->cls = cb_cls; gdm = (struct GNUNET_IDENTITY_GetDefaultMessage *) &op[1]; gdm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT); gdm->header.size = htons (sizeof (struct GNUNET_IDENTITY_GetDefaultMessage) + slen); gdm->name_len = htons (slen); gdm->reserved = htons (0); memcpy (&gdm[1], service_name, slen); op->msg = &gdm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, op); if (NULL == id->th) transmit_next (id); return op; } /** * Set the preferred/default identity for a service. * * @param id identity service to inform * @param service_name for which service is an identity set * @param ego new default identity to be set for this service * @param cont function to call once the operation finished * @param cont_cls closure for @a cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_set (struct GNUNET_IDENTITY_Handle *id, const char *service_name, struct GNUNET_IDENTITY_Ego *ego, GNUNET_IDENTITY_Continuation cont, void *cont_cls) { struct GNUNET_IDENTITY_Operation *op; struct GNUNET_IDENTITY_SetDefaultMessage *sdm; size_t slen; slen = strlen (service_name) + 1; if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_SetDefaultMessage)) { GNUNET_break (0); return NULL; } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) + slen); op->h = id; op->cont = cont; op->cls = cont_cls; sdm = (struct GNUNET_IDENTITY_SetDefaultMessage *) &op[1]; sdm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT); sdm->header.size = htons (sizeof (struct GNUNET_IDENTITY_SetDefaultMessage) + slen); sdm->name_len = htons (slen); sdm->reserved = htons (0); sdm->private_key = *ego->pk; memcpy (&sdm[1], service_name, slen); op->msg = &sdm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, op); if (NULL == id->th) transmit_next (id); return op; } /** * Create a new identity with the given name. * * @param id identity service to use * @param name desired name * @param cont function to call with the result (will only be called once) * @param cont_cls closure for @a cont * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *id, const char *name, GNUNET_IDENTITY_Continuation cont, void *cont_cls) { struct GNUNET_IDENTITY_Operation *op; struct GNUNET_IDENTITY_CreateRequestMessage *crm; struct GNUNET_CRYPTO_EcdsaPrivateKey *pk; size_t slen; slen = strlen (name) + 1; pk = GNUNET_CRYPTO_ecdsa_key_create (); if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_CreateRequestMessage)) { GNUNET_break (0); GNUNET_free (pk); return NULL; } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_CreateRequestMessage) + slen); op->h = id; op->cont = cont; op->cls = cont_cls; crm = (struct GNUNET_IDENTITY_CreateRequestMessage *) &op[1]; crm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_CREATE); crm->header.size = htons (sizeof (struct GNUNET_IDENTITY_CreateRequestMessage) + slen); crm->name_len = htons (slen); crm->reserved = htons (0); crm->private_key = *pk; memcpy (&crm[1], name, slen); op->msg = &crm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, op); if (NULL == id->th) transmit_next (id); GNUNET_free (pk); return op; } /** * Renames an existing identity. * * @param id identity service to use * @param old_name old name * @param new_name desired new name * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_rename (struct GNUNET_IDENTITY_Handle *id, const char *old_name, const char *new_name, GNUNET_IDENTITY_Continuation cb, void *cb_cls) { struct GNUNET_IDENTITY_Operation *op; struct GNUNET_IDENTITY_RenameMessage *grm; size_t slen_old; size_t slen_new; char *dst; slen_old = strlen (old_name) + 1; slen_new = strlen (new_name) + 1; if ( (slen_old >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (slen_new >= GNUNET_SERVER_MAX_MESSAGE_SIZE) || (slen_old + slen_new >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_RenameMessage)) ) { GNUNET_break (0); return NULL; } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_RenameMessage) + slen_old + slen_new); op->h = id; op->cont = cb; op->cls = cb_cls; grm = (struct GNUNET_IDENTITY_RenameMessage *) &op[1]; grm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_RENAME); grm->header.size = htons (sizeof (struct GNUNET_IDENTITY_RenameMessage) + slen_old + slen_new); grm->old_name_len = htons (slen_old); grm->new_name_len = htons (slen_new); dst = (char *) &grm[1]; memcpy (dst, old_name, slen_old); memcpy (&dst[slen_old], new_name, slen_new); op->msg = &grm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, op); if (NULL == id->th) transmit_next (id); return op; } /** * Delete an existing identity. * * @param id identity service to use * @param name name of the identity to delete * @param cb function to call with the result (will only be called once) * @param cb_cls closure for @a cb * @return handle to abort the operation */ struct GNUNET_IDENTITY_Operation * GNUNET_IDENTITY_delete (struct GNUNET_IDENTITY_Handle *id, const char *name, GNUNET_IDENTITY_Continuation cb, void *cb_cls) { struct GNUNET_IDENTITY_Operation *op; struct GNUNET_IDENTITY_DeleteMessage *gdm; size_t slen; slen = strlen (name) + 1; if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_DeleteMessage)) { GNUNET_break (0); return NULL; } op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Operation) + sizeof (struct GNUNET_IDENTITY_DeleteMessage) + slen); op->h = id; op->cont = cb; op->cls = cb_cls; gdm = (struct GNUNET_IDENTITY_DeleteMessage *) &op[1]; gdm->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_DELETE); gdm->header.size = htons (sizeof (struct GNUNET_IDENTITY_DeleteMessage) + slen); gdm->name_len = htons (slen); gdm->reserved = htons (0); memcpy (&gdm[1], name, slen); op->msg = &gdm->header; GNUNET_CONTAINER_DLL_insert_tail (id->op_head, id->op_tail, op); if (NULL == id->th) transmit_next (id); return op; } /** * Cancel an identity operation. Note that the operation MAY still * be executed; this merely cancels the continuation; if the request * was already transmitted, the service may still choose to complete * the operation. * * @param op operation to cancel */ void GNUNET_IDENTITY_cancel (struct GNUNET_IDENTITY_Operation *op) { struct GNUNET_IDENTITY_Handle *h = op->h; if ( (h->op_head != op) || (NULL == h->client) ) { /* request not active, can simply remove */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client aborted non-head operation, simply removing it\n"); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); GNUNET_free (op); return; } if (NULL != h->th) { /* request active but not yet with service, can still abort */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client aborted head operation prior to transmission, aborting it\n"); GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); GNUNET_free (op); transmit_next (h); return; } /* request active with service, simply ensure continuations are not called */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client aborted active request, NULLing continuation\n"); op->cont = NULL; op->cb = NULL; } /** * Free ego from hash map. * * @param cls identity service handle * @param key unused * @param value ego to free * @return #GNUNET_OK (continue to iterate) */ static int free_ego (void *cls, const struct GNUNET_HashCode *key, void *value) { struct GNUNET_IDENTITY_Handle *h = cls; struct GNUNET_IDENTITY_Ego *ego = value; if (NULL != h->cb) h->cb (h->cb_cls, ego, &ego->ctx, NULL); GNUNET_free (ego->pk); GNUNET_free (ego->name); GNUNET_free (ego); return GNUNET_OK; } /** * Disconnect from identity service * * @param h handle to destroy */ void GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h) { struct GNUNET_IDENTITY_Operation *op; GNUNET_assert (NULL != h); if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (h->reconnect_task); h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != h->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); h->th = NULL; } if (NULL != h->egos) { GNUNET_CONTAINER_multihashmap_iterate (h->egos, &free_ego, h); GNUNET_CONTAINER_multihashmap_destroy (h->egos); h->egos = NULL; } while (NULL != (op = h->op_head)) { GNUNET_break (NULL == op->cont); GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, op); GNUNET_free (op); } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } GNUNET_free (h); } /* end of identity_api.c */ gnunet-0.10.1/src/identity/identity_api_lookup.c0000644000175000017500000000763212225777502016672 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public Liceidentity as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Liceidentity for more details. You should have received a copy of the GNU General Public Liceidentity along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file identity/identity_api_lookup.c * @brief api to lookup an ego * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_identity_service.h" #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) /** * Handle for ego lookup. */ struct GNUNET_IDENTITY_EgoLookup { /** * Handle to the identity service. */ struct GNUNET_IDENTITY_Handle *identity; /** * Name of the ego we are looking up. */ char *name; /** * Function to call with the result. */ GNUNET_IDENTITY_EgoCallback cb; /** * Closure for @e cb */ void *cb_cls; }; /** * Method called to inform about the egos of this peer. * * When used with #GNUNET_IDENTITY_connect, this function is * initially called for all egos and then again whenever a * ego's name changes or if it is deleted. At the end of * the initial pass over all egos, the function is once called * with 'NULL' for @a ego. That does NOT mean that the callback won't * be invoked in the future or that there was an error. * * If the @a name matches the name from @a cls, we found the zone * for our computation and will invoke the callback. * If we have iterated over all egos and not found the name, we * invoke the callback with NULL. * * @param cls closure with the `struct GNUNET_IDENTITY_EgoLookup` * @param ego ego handle * @param ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param name name assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *name) { struct GNUNET_IDENTITY_EgoLookup *el = cls; if ( (NULL != name) && (0 == strcmp (name, el->name)) ) { el->cb (el->cb_cls, ego); GNUNET_IDENTITY_ego_lookup_cancel (el); return; } if (NULL == ego) { /* not found */ el->cb (el->cb_cls, NULL); GNUNET_IDENTITY_ego_lookup_cancel (el); return; } } /** * Lookup an ego by name. * * @param cfg configuration to use * @param name name to look up * @param cb callback to invoke with the result * @param cb_cls closure for @a cb * @return NULL on error */ struct GNUNET_IDENTITY_EgoLookup * GNUNET_IDENTITY_ego_lookup (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name, GNUNET_IDENTITY_EgoCallback cb, void *cb_cls) { struct GNUNET_IDENTITY_EgoLookup *el; el = GNUNET_new (struct GNUNET_IDENTITY_EgoLookup); el->name = GNUNET_strdup (name); el->cb = cb; el->cb_cls = cb_cls; el->identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, el); return el; } /** * Abort ego lookup attempt. * * @param el handle for lookup to abort */ void GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el) { GNUNET_IDENTITY_disconnect (el->identity); GNUNET_free (el->name); GNUNET_free (el); } /* end of identity_api_lookup.c */ gnunet-0.10.1/src/identity/Makefile.am0000644000175000017500000000500012320751517014464 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ identity.conf lib_LTLIBRARIES = libgnunetidentity.la libgnunetidentity_la_SOURCES = \ identity_api.c \ identity_api_lookup.c \ identity.h libgnunetidentity_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetidentity_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetidentity_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la bin_PROGRAMS = \ gnunet-identity libexec_PROGRAMS = \ gnunet-service-identity gnunet_service_identity_SOURCES = \ gnunet-service-identity.c gnunet_service_identity_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_identity_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_identity_SOURCES = \ gnunet-identity.c gnunet_identity_LDADD = \ libgnunetidentity.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_identity_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ libgnunetidentity.la \ $(top_builddir)/src/util/libgnunetutil.la if HAVE_TESTING check_PROGRAMS = \ test_identity \ test_identity_defaults endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_identity_SOURCES = \ test_identity.c test_identity_LDADD = \ libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_identity_DEPENDENCIES = \ libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_identity_defaults_SOURCES = \ test_identity_defaults.c test_identity_defaults_LDADD = \ libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la test_identity_defaults_DEPENDENCIES = \ libgnunetidentity.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_identity.conf gnunet-0.10.1/src/identity/test_identity.c0000644000175000017500000001342012236654562015501 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file identity/test_identity.c * @brief testcase for identity service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_identity_service.h" #include "gnunet_testing_lib.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) /** * Return value from 'main'. */ static int res; /** * Handle to identity service. */ static struct GNUNET_IDENTITY_Handle *h; /** * Handle to identity operation. */ static struct GNUNET_IDENTITY_Operation *op; /** * Handle for task for timeout termination. */ static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; /** * Clean up all resources used. */ static void cleanup () { if (NULL != op) { GNUNET_IDENTITY_cancel (op); op = NULL; } if (NULL != h) { GNUNET_IDENTITY_disconnect (h); h = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Termiante the testcase (failure). * * @param cls NULL * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 1; } /** * Termiante the testcase (success). * * @param cls NULL * @param tc scheduler context */ static void end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } /** * Finish the testcase (successfully). */ static void end () { if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &end_normally, NULL); } /** * Called with events about egos. * * @param cls NULL * @param ego ego handle * @param ego_ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param identifier identifier assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void notification_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier) { static struct GNUNET_IDENTITY_Ego *my_ego; static int round; switch (round) { case 0: /* end of initial iteration */ GNUNET_assert (NULL == ego); GNUNET_assert (NULL == identifier); break; case 1: /* create */ GNUNET_assert (NULL != ego); GNUNET_assert (0 == strcmp (identifier, "test-id")); my_ego = ego; *ctx = &round; break; case 2: /* rename */ GNUNET_assert (my_ego == ego); GNUNET_assert (0 == strcmp (identifier, "test")); GNUNET_assert (*ctx == &round); break; case 3: /* delete */ GNUNET_assert (my_ego == ego); GNUNET_assert (NULL == identifier); GNUNET_assert (*ctx == &round); *ctx = NULL; break; default: GNUNET_break (0); } round++; } /** * Continuation called from successful delete operation. * * @param cls NULL * @param emsg (should also be NULL) */ static void delete_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); end (); } /** * Continuation called from expected-to-fail rename operation. * * @param cls NULL * @param emsg (should also be NULL) */ static void fail_rename_cont (void *cls, const char *emsg) { GNUNET_assert (NULL != emsg); op = GNUNET_IDENTITY_delete (h, "test", &delete_cont, NULL); end (); /* yepee */ } /** * Continuation called from successful rename operation. * * @param cls NULL * @param emsg (should also be NULL) */ static void success_rename_cont (void *cls, const char *emsg) { GNUNET_assert (NULL == emsg); op = GNUNET_IDENTITY_rename (h, "test-id", "test", &fail_rename_cont, NULL); } /** * Called with events about created ego. * * @param cls NULL * @param emsg error message */ static void create_cb (void *cls, const char *emsg) { GNUNET_assert (NULL == emsg); op = GNUNET_IDENTITY_rename (h, "test-id", "test", &success_rename_cont, NULL); } /** * Main function of the test, run from scheduler. * * @param cls NULL * @param cfg configuration we use (also to connect to identity service) * @param peer handle to access more of the peer (not used) */ static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); h = GNUNET_IDENTITY_connect (cfg, ¬ification_cb, NULL); GNUNET_assert (NULL != h); op = GNUNET_IDENTITY_create (h, "test-id", &create_cb, NULL); } int main (int argc, char *argv[]) { GNUNET_DISK_directory_remove ("/tmp/test-identity-service"); res = 1; if (0 != GNUNET_TESTING_service_run ("test-identity", "identity", "test_identity.conf", &run, NULL)) return 1; return res; } /* end of test_identity.c */ gnunet-0.10.1/src/identity/test_identity.conf0000644000175000017500000000042712225230043016165 00000000000000[arm] PORT = 12000 DEFAULTSERVICES = identity UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [identity] # need to overwrite paths to ensure they stay the same between runs... EGODIR = /tmp/test-identity-service/egos/ SUBSYSTEM_CFG = /tmp/test-identity-service/s.conf gnunet-0.10.1/src/identity/test_identity_defaults.c0000644000175000017500000001372312241134531017357 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file identity/test_identity.c * @brief testcase for identity service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_identity_service.h" #include "gnunet_testing_lib.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) /** * Return value from 'main'. */ static int res; /** * Handle to identity service. */ static struct GNUNET_IDENTITY_Handle *h; /** * Handle to identity operation. */ static struct GNUNET_IDENTITY_Operation *op; /** * Handle for task for timeout termination. */ static GNUNET_SCHEDULER_TaskIdentifier endbadly_task; /** * Clean up all resources used. */ static void cleanup () { if (NULL != op) { GNUNET_IDENTITY_cancel (op); op = NULL; } if (NULL != h) { GNUNET_IDENTITY_disconnect (h); h = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Termiante the testcase (failure). * * @param cls NULL * @param tc scheduler context */ static void endbadly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 1; } /** * Termiante the testcase (success). * * @param cls NULL * @param tc scheduler context */ static void end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { cleanup (); res = 0; } /** * Finish the testcase (successfully). */ static void end () { if (endbadly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (endbadly_task); endbadly_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &end_normally, NULL); } /** * Continuation called from successful delete operation. * * @param cls NULL * @param emsg (should also be NULL) */ static void delete_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); end (); } /** * Continuation called from expected-to-fail rename operation. * * @param cls NULL * @param emsg (should also be NULL) */ static void get_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier) { GNUNET_assert (NULL != ego); GNUNET_assert (NULL != identifier); GNUNET_assert (0 == strcmp (identifier, "test-id")); op = GNUNET_IDENTITY_delete (h, "test-id", &delete_cont, NULL); } /** * Main function of the test, run from scheduler. * * @param cls NULL * @param cfg configuration we use (also to connect to identity service) * @param peer handle to access more of the peer (not used) */ static void run_get (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); h = GNUNET_IDENTITY_connect (cfg, NULL, NULL); GNUNET_assert (NULL != h); op = GNUNET_IDENTITY_get (h, "test-service", &get_cb, NULL); } /** * Continuation called from successful rename operation. * * @param cls NULL * @param emsg (should also be NULL) */ static void success_set_cont (void *cls, const char *emsg) { op = NULL; GNUNET_assert (NULL == emsg); end (); } /** * Called with events about egos. * * @param cls NULL * @param ego ego handle * @param ego_ctx context for application to store data for this ego * (during the lifetime of this process, initially NULL) * @param identifier identifier assigned by the user for this ego, * NULL if the user just deleted the ego and it * must thus no longer be used */ static void notification_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier) { if (NULL == ego) return; /* skip first call */ if (NULL == identifier) return; /* deletion / shutdown */ op = GNUNET_IDENTITY_set (h, "test-service", ego, &success_set_cont, NULL); } /** * Called with events about created ego. * * @param cls NULL * @param emsg error message */ static void create_cb (void *cls, const char *emsg) { GNUNET_assert (NULL == emsg); op = NULL; } /** * Main function of the test, run from scheduler. * * @param cls NULL * @param cfg configuration we use (also to connect to identity service) * @param peer handle to access more of the peer (not used) */ static void run_set (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL); h = GNUNET_IDENTITY_connect (cfg, ¬ification_cb, NULL); GNUNET_assert (NULL != h); op = GNUNET_IDENTITY_create (h, "test-id", &create_cb, NULL); } int main (int argc, char *argv[]) { GNUNET_DISK_directory_remove ("/tmp/test-identity-service"); res = 1; if (0 != GNUNET_TESTING_service_run ("test-identity-defaults", "identity", "test_identity.conf", &run_set, NULL)) return 1; if (0 != GNUNET_TESTING_service_run ("test-identity-defaults", "identity", "test_identity.conf", &run_get, NULL)) return 1; GNUNET_DISK_directory_remove ("/tmp/test-identity-service"); return res; } /* end of test_identity.c */ gnunet-0.10.1/src/identity/identity.h0000644000175000017500000001154512242135660014443 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public Liceidentity as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Liceidentity for more details. You should have received a copy of the GNU General Public Liceidentity along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @author Christian Grothoff * @file identity/identity.h * * @brief Common type definitions for the identity * service and API. */ #ifndef IDENTITY_H #define IDENTITY_H #include "gnunet_common.h" GNUNET_NETWORK_STRUCT_BEGIN /** * Answer from service to client about last operation; * GET_DEFAULT maybe answered with this message on failure; * CREATE and RENAME will always be answered with this message. */ struct GNUNET_IDENTITY_ResultCodeMessage { /** * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE */ struct GNUNET_MessageHeader header; /** * Status code for the last operation, in NBO. * (currently not used). */ uint32_t result_code GNUNET_PACKED; /* followed by 0-terminated error message (on error) */ }; /** * Service informs client about status of a pseudonym. */ struct GNUNET_IDENTITY_UpdateMessage { /** * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE */ struct GNUNET_MessageHeader header; /** * Number of bytes in ego name string including 0-termination, in NBO; * 0 if the ego was deleted. */ uint16_t name_len GNUNET_PACKED; /** * Usually #GNUNET_NO, #GNUNET_YES to signal end of list. */ uint16_t end_of_list GNUNET_PACKED; /** * The private key */ struct GNUNET_CRYPTO_EcdsaPrivateKey private_key; /* followed by 0-terminated ego name */ }; /** * Client requests knowledge about default identity for * a subsystem from identity service. */ struct GNUNET_IDENTITY_GetDefaultMessage { /** * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_GET_DEFAULT */ struct GNUNET_MessageHeader header; /** * Number of bytes in service name string including 0-termination, in NBO. */ uint16_t name_len GNUNET_PACKED; /** * Always zero. */ uint16_t reserved GNUNET_PACKED; /* followed by 0-terminated service name */ }; /** * Used from service to client as a result to the GET_DEFAULT * message, used from client to service to SET_DEFAULT. */ struct GNUNET_IDENTITY_SetDefaultMessage { /** * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_SET_DEFAULT */ struct GNUNET_MessageHeader header; /** * Number of bytes in service name string including 0-termination, in NBO. */ uint16_t name_len GNUNET_PACKED; /** * Always zero. */ uint16_t reserved GNUNET_PACKED; /** * The private key */ struct GNUNET_CRYPTO_EcdsaPrivateKey private_key; /* followed by 0-terminated service name */ }; /** * Client requests creation of an identity. Service * will respond with a result code. */ struct GNUNET_IDENTITY_CreateRequestMessage { /** * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_CREATE */ struct GNUNET_MessageHeader header; /** * Number of bytes in identity name string including 0-termination, in NBO. */ uint16_t name_len GNUNET_PACKED; /** * Always zero. */ uint16_t reserved GNUNET_PACKED; /** * The private key */ struct GNUNET_CRYPTO_EcdsaPrivateKey private_key; /* followed by 0-terminated identity name */ }; /** * Client requests renaming of an identity. Service * will respond with a result code. */ struct GNUNET_IDENTITY_RenameMessage { /** * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_RENAME */ struct GNUNET_MessageHeader header; /** * Number of characters in the old name including 0-termination, in NBO. */ uint16_t old_name_len GNUNET_PACKED; /** * Number of characters in the new name including 0-termination, in NBO. */ uint16_t new_name_len GNUNET_PACKED; /* followed by 0-terminated old name */ /* followed by 0-terminated new name */ }; /** * Client requests deletion of an identity. Service * will respond with a result code. */ struct GNUNET_IDENTITY_DeleteMessage { /** * Type: #GNUNET_MESSAGE_TYPE_IDENTITY_DELETE */ struct GNUNET_MessageHeader header; /** * Number of characters in the name including 0-termination, in NBO. */ uint16_t name_len GNUNET_PACKED; /** * Always zero. */ uint16_t reserved GNUNET_PACKED; /* followed by 0-terminated name */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/core/0000755000175000017500000000000012320755625011620 500000000000000gnunet-0.10.1/src/core/test_core_quota_peer2.conf0000644000175000017500000000215712225230043016673 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core-quota-sym-peer-2/ [arm] PORT = 22476 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p2-service-arm.sock [statistics] PORT = 22477 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p2-service-statistics.sock [resolver] PORT = 22474 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p2-service-resolver.sock [peerinfo] PORT = 22479 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p2-service-peerinfo.sock [transport] PORT = 22475 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p2-service-transport.sock [core] PORT = 22480 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p2-service-core.sock [ats] PORT = 22482 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p2-service-ats.sock # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 10240 UNSPECIFIED_QUOTA_OUT = 10240 # LOOPBACK LOOPBACK_QUOTA_IN = 10240 LOOPBACK_QUOTA_OUT = 10240 # LAN LAN_QUOTA_IN = 10240 LAN_QUOTA_OUT = 10240 # WAN WAN_QUOTA_IN = 10240 WAN_QUOTA_OUT = 10240 # WLAN WLAN_QUOTA_IN = 10240 WLAN_QUOTA_OUT = 10240 [transport-tcp] PORT = 22467 [transport-udp] PORT = 22468 [transport-http] PORT = 22469 gnunet-0.10.1/src/core/gnunet-service-core_typemap.h0000644000175000017500000000572612225777503017351 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_typemap.h * @brief management of map that specifies which message types this peer supports * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_CORE_TYPEMAP_H #define GNUNET_SERVICE_CORE_TYPEMAP_H #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" /** * Map specifying which message types a peer supports. */ struct GSC_TypeMap; /** * Add a set of types to our type map. */ void GSC_TYPEMAP_add (const uint16_t * types, unsigned int tlen); /** * Remove a set of types from our type map. */ void GSC_TYPEMAP_remove (const uint16_t * types, unsigned int tlen); /** * Compute a type map message for this peer. * * @return this peers current type map message. */ struct GNUNET_MessageHeader * GSC_TYPEMAP_compute_type_map_message (void); /** * Extract a type map from a TYPE_MAP message. * * @param msg a type map message * @return NULL on error */ struct GSC_TypeMap * GSC_TYPEMAP_get_from_message (const struct GNUNET_MessageHeader *msg); /** * Test if any of the types from the types array is in the * given type map. * * @param tmap map to test * @param types array of types * @param tcnt number of entries in types * @return GNUNET_YES if a type is in the map, GNUNET_NO if not */ int GSC_TYPEMAP_test_match (const struct GSC_TypeMap *tmap, const uint16_t * types, unsigned int tcnt); /** * Add additional types to a given typemap. * * @param tmap map to extend (not changed) * @param types array of types to add * @param tcnt number of entries in types * @return updated type map (fresh copy) */ struct GSC_TypeMap * GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap, const uint16_t * types, unsigned int tcnt); /** * Create an empty type map. * * @return an empty type map */ struct GSC_TypeMap * GSC_TYPEMAP_create (void); /** * Free the given type map. * * @param tmap a type map */ void GSC_TYPEMAP_destroy (struct GSC_TypeMap *tmap); /** * Initialize typemap subsystem. */ void GSC_TYPEMAP_init (void); /** * Shutdown typemap subsystem. */ void GSC_TYPEMAP_done (void); #endif /* end of gnunet-service-core_typemap.h */ gnunet-0.10.1/src/core/gnunet-service-core.c0000644000175000017500000000761712225777502015605 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core.c * @brief high-level P2P messaging * @author Christian Grothoff */ #include "platform.h" #include #include "gnunet_util_lib.h" #include "gnunet-service-core.h" #include "gnunet-service-core_clients.h" #include "gnunet-service-core_kx.h" #include "gnunet-service-core_neighbours.h" #include "gnunet-service-core_sessions.h" #include "gnunet-service-core_typemap.h" /** * Our identity. */ struct GNUNET_PeerIdentity GSC_my_identity; /** * Our configuration. */ const struct GNUNET_CONFIGURATION_Handle *GSC_cfg; /** * For creating statistics. */ struct GNUNET_STATISTICS_Handle *GSC_stats; /** * Handle to the server of the core service. */ static struct GNUNET_SERVER_Handle *GSC_server; /** * Last task run during shutdown. Disconnects us from * the transport. * * @param cls NULL, unused * @param tc scheduler context, unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n"); GSC_CLIENTS_done (); GSC_NEIGHBOURS_done (); GSC_SESSIONS_done (); GSC_KX_done (); GSC_TYPEMAP_done (); if (NULL != GSC_stats) { GNUNET_STATISTICS_destroy (GSC_stats, GNUNET_NO); GSC_stats = NULL; } GSC_cfg = NULL; } /** * Initiate core service. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { struct GNUNET_CRYPTO_EddsaPrivateKey *pk; char *keyfile; GSC_cfg = c; GSC_server = server; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (GSC_cfg, "PEER", "PRIVATE_KEY", &keyfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Core service is lacking HOSTKEY configuration setting. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } GSC_stats = GNUNET_STATISTICS_create ("core", GSC_cfg); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); GNUNET_SERVER_suspend (server); GSC_TYPEMAP_init (); pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile); GNUNET_free (keyfile); GNUNET_assert (NULL != pk); if ((GNUNET_OK != GSC_KX_init (pk)) || (GNUNET_OK != GSC_NEIGHBOURS_init ())) { GNUNET_SCHEDULER_shutdown (); return; } GSC_SESSIONS_init (); GSC_CLIENTS_init (GSC_server); GNUNET_SERVER_resume (GSC_server); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Core service of `%4s' ready.\n"), GNUNET_i2s (&GSC_my_identity)); } /** * The main function for the transport service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "core", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-core.c */ gnunet-0.10.1/src/core/core.h0000644000175000017500000001463212272521114012635 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/core.h * @brief common internal definitions for core service * @author Christian Grothoff */ #ifndef CORE_H #define CORE_H #include "gnunet_bandwidth_lib.h" #include "gnunet_transport_service.h" #include "gnunet_crypto_lib.h" #include "gnunet_time_lib.h" /** * General core debugging. */ #define DEBUG_CORE GNUNET_EXTRA_LOGGING /** * Definition of bits in the InitMessage's options field that specify * which events this client cares about. Note that inbound messages * for handlers that were specifically registered are always * transmitted to the client. */ #define GNUNET_CORE_OPTION_NOTHING 0 #define GNUNET_CORE_OPTION_SEND_STATUS_CHANGE 4 #define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 8 #define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 16 #define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32 #define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 64 GNUNET_NETWORK_STRUCT_BEGIN /** * Message transmitted core clients to gnunet-service-core * to start the interaction. This header is followed by * uint16_t type values specifying which messages this * client is interested in. */ struct InitMessage { /** * Header with type GNUNET_MESSAGE_TYPE_CORE_INIT. */ struct GNUNET_MessageHeader header; /** * Options, see GNUNET_CORE_OPTION_ values. */ uint32_t options GNUNET_PACKED; }; /** * Message transmitted by the gnunet-service-core process * to its clients in response to an INIT message. */ struct InitReplyMessage { /** * Header with type GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Public key of the local peer. */ struct GNUNET_PeerIdentity my_identity; }; /** * Message sent by the service to clients to notify them * about a peer connecting. */ struct ConnectNotifyMessage { /** * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Identity of the connecting peer. */ struct GNUNET_PeerIdentity peer; }; /** * Message sent by the service to clients to notify them * about a peer disconnecting. */ struct DisconnectNotifyMessage { /** * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT. */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Identity of the connecting peer. */ struct GNUNET_PeerIdentity peer; }; /** * Message sent by the service to clients to notify them about * messages being received or transmitted. This overall message is * followed by the real message, or just the header of the real * message (depending on the client's preferences). The receiver can * tell if he got the full message or only a partial message by * looking at the size field in the header of NotifyTrafficMessage and * checking it with the size field in the message that follows. */ struct NotifyTrafficMessage { /** * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND * or GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND. */ struct GNUNET_MessageHeader header; /** * Identity of the receiver or sender. */ struct GNUNET_PeerIdentity peer; /* Followed by payload (message or just header), variable size */ }; /** * Client notifying core about the maximum-priority * message it has in the queue for a particular target. */ struct SendMessageRequest { /** * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST */ struct GNUNET_MessageHeader header; /** * How important is this message? */ uint32_t priority GNUNET_PACKED; /** * By what time would the sender really like to see this * message transmitted? */ struct GNUNET_TIME_AbsoluteNBO deadline; /** * Identity of the intended target. */ struct GNUNET_PeerIdentity peer; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * How large is the message? */ uint16_t size GNUNET_PACKED; /** * Counter for this peer to match SMRs to replies. */ uint16_t smr_id GNUNET_PACKED; }; /** * Core notifying client that it is allowed to now * transmit a message to the given target * (response to #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST). */ struct SendMessageReady { /** * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND_READY */ struct GNUNET_MessageHeader header; /** * How many bytes are allowed for transmission? * Guaranteed to be at least as big as the requested size, * or ZERO if the request is rejected (will timeout, * peer disconnected, queue full, etc.). */ uint16_t size GNUNET_PACKED; /** * smr_id from the request. */ uint16_t smr_id GNUNET_PACKED; /** * Identity of the intended target. */ struct GNUNET_PeerIdentity peer; }; /** * Client asking core to transmit a particular message to a particular * target (response to #GNUNET_MESSAGE_TYPE_CORE_SEND_READY). */ struct SendMessage { /** * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND */ struct GNUNET_MessageHeader header; /** * How important is this message? */ uint32_t priority GNUNET_PACKED; /** * By what time would the sender really like to see this * message transmitted? */ struct GNUNET_TIME_AbsoluteNBO deadline; /** * Identity of the intended receiver. */ struct GNUNET_PeerIdentity peer; /** * #GNUNET_YES if corking is allowed, #GNUNET_NO if not. */ uint32_t cork GNUNET_PACKED; /** * Always 0. */ uint32_t reserved GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END #endif /* end of core.h */ gnunet-0.10.1/src/core/gnunet-service-core_neighbours.h0000644000175000017500000000444412276375236020036 00000000000000/* This file is part of GNUnet. (C) 2009-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_neighbours.h * @brief code for managing low-level 'plaintext' connections with transport (key exchange may or may not be done yet) * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_CORE_NEIGHBOURS_H #define GNUNET_SERVICE_CORE_NEIGHBOURS_H #include "gnunet_util_lib.h" /** * Transmit the given message to the given target. Note that a * non-control messages should only be transmitted after a * 'GSC_SESSION_solicit' call was made (that call is always invoked * when the message queue is empty). Outbound quotas and memory * bounds will then be enfoced (as GSC_SESSION_solicit is only called * if sufficient banwdith is available). * * @param target peer that should receive the message (must be connected) * @param msg message to transmit * @param timeout by when should the transmission be done? */ void GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative timeout); /** * Check if the given neighbour has excess bandwidth available. * * @param target neighbour to check * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not */ int GSC_NEIGHBOURS_check_excess_bandwidth (const struct GNUNET_PeerIdentity *target); /** * Initialize neighbours subsystem. */ int GSC_NEIGHBOURS_init (void); /** * Shutdown neighbours subsystem. */ void GSC_NEIGHBOURS_done (void); #endif gnunet-0.10.1/src/core/test_core_defaults.conf0000644000175000017500000000175012255773026016272 00000000000000[PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core/ [arm] DEFAULTSERVICES = [nat] DISABLEV6 = YES ENABLE_UPNP = NO BEHIND_NAT = NO ALLOW_NAT = NO INTERNAL_ADDRESS = 127.0.0.1 EXTERNAL_ADDRESS = 127.0.0.1 USE_LOCALADDR = NO [ats] WAN_QUOTA_IN = 1 GB WAN_QUOTA_OUT = 1 GB [core] PORT = 12470 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-core.sock [transport-tcp] BINDTO = 127.0.0.1 [transport-udp] BROADCAST = NO [testing] WEAKRANDOM = YES [peerinfo] NO_IO = YES [fs] AUTOSTART = NO [datastore] AUTOSTART = NO [dht] AUTOSTART = NO [mesh] AUTOSTART = NO [dns] AUTOSTART = NO [nse] AUTOSTART = NO [dv] AUTOSTART = NO [chat] AUTOSTART = NO [gns] AUTOSTART = NO [vpn] AUTOSTART = NO [namestore] AUTOSTART = NO [lockmanager] AUTOSTART = NO [consensus] AUTOSTART = NO [regex] AUTOSTART = NO [identity] AUTOSTART = NO [psycstore] AUTOSTART = NO [multicast] AUTOSTART = NO [revocation] AUTOSTART = NO [conversation] AUTOSTART = NO [namecache] AUTOSTART = NO [set] AUTOSTART = NO gnunet-0.10.1/src/core/test_core_api_send_to_self.conf0000644000175000017500000000107712225230043017742 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = ~/.gnunet/ [arm] PORT = 2425 DEFAULTSERVICES = core test-sts [core] PORT = 24512 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-core.sock [ats] WAN_QUOTA_IN = 104857600 WAN_QUOTA_OUT = 104757600 PORT = 24571 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-ats.sock [test-sts] AUTOSTART = YES PORT = 9252 HOSTNAME = localhost BINARY = test_core_api_send_to_self ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; TOTAL_QUOTA_IN = 65536 TOTAL_QUOTA_OUT = 65536 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-sts.sock gnunet-0.10.1/src/core/test_core_api_peer2.conf0000644000175000017500000000144612225230043016313 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core-peer-2/ [arm] PORT = 22460 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock [statistics] PORT = 22461 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock [resolver] PORT = 22462 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock [peerinfo] PORT = 22463 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock [transport] PORT = 22464 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock [core] PORT = 22475 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-core.sock [ats] PORT = 22476 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-ats.sock [transport-tcp] PORT = 22467 [transport-udp] PORT = 22468 [transport-unix] PORT = 22469 [transport-http] PORT = 22470 gnunet-0.10.1/src/core/core.conf.in0000644000175000017500000000102412316526362013740 00000000000000[core] AUTOSTART = @AUTOSTART@ @JAVAPORT@PORT = 2092 HOSTNAME = localhost BINARY = gnunet-service-core ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-core.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES # DISABLE_SOCKET_FORWARDING = NO # USERNAME = # MAXBUF = # TIMEOUT = # DISABLEV6 = # BINDTO = # REJECT_FROM = # REJECT_FROM6 = # PREFIX = # Note: this MUST be set to YES in production, only set to NO for testing # for performance (testbed/cluster-scale use!). USE_EPHEMERAL_KEYS = YES gnunet-0.10.1/src/core/test_core_quota_asymmetric_recv_limited_peer2.conf0000644000175000017500000000224512225230043023654 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core-quota-asym-recv-lim-peer-2/ [arm] PORT = 22486 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-arm.sock [statistics] PORT = 22487 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-statistics.sock [resolver] PORT = 22484 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-resolver.sock [peerinfo] PORT = 22489 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-peerinfo.sock [transport] PORT = 22485 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-transport.sock [core] PORT = 22490 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-core.sock [ats] PORT = 22491 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-ats.sock # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 10240 UNSPECIFIED_QUOTA_OUT = 10240 # LOOPBACK LOOPBACK_QUOTA_IN = 10240 LOOPBACK_QUOTA_OUT = 10240 # LAN LAN_QUOTA_IN = 10240 LAN_QUOTA_OUT = 10240 # WAN WAN_QUOTA_IN = 10240 WAN_QUOTA_OUT = 10240 # WLAN WLAN_QUOTA_IN = 10240 WLAN_QUOTA_OUT = 10240 [transport-tcp] PORT = 22467 [transport-http] PORT = 22469 [transport-tcp] PORT = 22468 gnunet-0.10.1/src/core/core_api_iterate_peers.c0000644000175000017500000001301712225777502016404 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/core_api_iterate_peers.c * @brief implementation of the peer_iterate function * @author Christian Grothoff * @author Nathan Evans */ #include "platform.h" #include "gnunet_core_service.h" #include "core.h" struct GNUNET_CORE_RequestContext { /** * Our connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * Handle for transmitting a request. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Function called with the peer. */ GNUNET_CORE_ConnectEventHandler peer_cb; /** * Peer to check for. */ struct GNUNET_PeerIdentity *peer; /** * Closure for peer_cb. */ void *cb_cls; }; /** * Receive reply from core service with information about a peer. * * @param cls our 'struct GNUNET_CORE_RequestContext *' * @param msg NULL on error or last entry */ static void receive_info (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CORE_RequestContext *request_context = cls; const struct ConnectNotifyMessage *connect_message; uint16_t msize; /* Handle last message or error case, disconnect and clean up */ if ((msg == NULL) || ((ntohs (msg->type) == GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END) && (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader)))) { if (request_context->peer_cb != NULL) request_context->peer_cb (request_context->cb_cls, NULL); GNUNET_CLIENT_disconnect (request_context->client); GNUNET_free (request_context); return; } msize = ntohs (msg->size); /* Handle incorrect message type or size, disconnect and clean up */ if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) || (msize < sizeof (struct ConnectNotifyMessage))) { GNUNET_break (0); if (request_context->peer_cb != NULL) request_context->peer_cb (request_context->cb_cls, NULL); GNUNET_CLIENT_disconnect (request_context->client); GNUNET_free (request_context); return; } connect_message = (const struct ConnectNotifyMessage *) msg; if (msize != sizeof (struct ConnectNotifyMessage)) { GNUNET_break (0); if (request_context->peer_cb != NULL) request_context->peer_cb (request_context->cb_cls, NULL); GNUNET_CLIENT_disconnect (request_context->client); GNUNET_free (request_context); return; } /* Normal case */ if (request_context->peer_cb != NULL) request_context->peer_cb (request_context->cb_cls, &connect_message->peer); GNUNET_CLIENT_receive (request_context->client, &receive_info, request_context, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Function called to notify a client about the socket * begin ready to queue more data. "buf" will be * NULL and "size" zero if the socket was closed for * writing in the meantime. * * @param cls closure, always NULL * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t transmit_request (void *cls, size_t size, void *buf) { struct GNUNET_MessageHeader *msg; int msize; msize = sizeof (struct GNUNET_MessageHeader); if ((size < msize) || (buf == NULL)) return 0; msg = (struct GNUNET_MessageHeader *) buf; msg->size = htons (msize); msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS); return msize; } /** * Iterate over all currently connected peers. * Calls peer_cb with each connected peer, and then * once with NULL to indicate that all peers have * been handled. * * @param cfg configuration to use * @param peer_cb function to call with the peer information * @param cb_cls closure for @a peer_cb * @return #GNUNET_OK if iterating, #GNUNET_SYSERR on error */ int GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CORE_ConnectEventHandler peer_cb, void *cb_cls) { struct GNUNET_CORE_RequestContext *request_context; struct GNUNET_CLIENT_Connection *client; client = GNUNET_CLIENT_connect ("core", cfg); if (client == NULL) return GNUNET_SYSERR; request_context = GNUNET_new (struct GNUNET_CORE_RequestContext); request_context->client = client; request_context->peer_cb = peer_cb; request_context->cb_cls = cb_cls; request_context->th = GNUNET_CLIENT_notify_transmit_ready (client, sizeof (struct GNUNET_MessageHeader), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, &transmit_request, NULL); GNUNET_CLIENT_receive (client, &receive_info, request_context, GNUNET_TIME_UNIT_FOREVER_REL); return GNUNET_OK; } /* end of core_api_iterate_peers.c */ gnunet-0.10.1/src/core/test_core_api_reliability.c0000644000175000017500000003505612301361474017120 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/test_core_api_reliability.c * @brief testcase for core_api.c focusing on reliable transmission (with TCP) */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_core_service.h" #include "gnunet_getopt_lib.h" #include "gnunet_os_lib.h" #include "gnunet_program_lib.h" #include "gnunet_scheduler_lib.h" #include "gnunet_transport_service.h" #include /** * Note that this value must not significantly exceed * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise * messages may be dropped even for a reliable transport. */ #define TOTAL_MSGS (600 * 10) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 6000) /** * What delay do we request from the core service for transmission? */ #define FAST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) #define MTYPE 12345 static unsigned long long total_bytes; static struct GNUNET_TIME_Absolute start_time; static GNUNET_SCHEDULER_TaskIdentifier err_task; static GNUNET_SCHEDULER_TaskIdentifier connect_task; struct PeerContext { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CORE_Handle *ch; struct GNUNET_PeerIdentity id; struct GNUNET_TRANSPORT_Handle *th; struct GNUNET_MessageHeader *hello; struct GNUNET_TRANSPORT_GetHelloHandle *ghh; int connect_status; struct GNUNET_OS_Process *arm_proc; }; static struct PeerContext p1; static struct PeerContext p2; static int ok; static int32_t tr_n; #define OKPP do { ok++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) struct TestMessage { struct GNUNET_MessageHeader header; uint32_t num; }; static unsigned int get_size (unsigned int iter) { unsigned int ret; if (iter < 60000) return iter + sizeof (struct TestMessage); ret = (iter * iter * iter); return sizeof (struct TestMessage) + (ret % 60000); } static void process_hello (void *cls, const struct GNUNET_MessageHeader *message); static void terminate_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned long long delta; GNUNET_TRANSPORT_get_hello_cancel (p1.ghh); GNUNET_TRANSPORT_get_hello_cancel (p2.ghh); GNUNET_CORE_disconnect (p1.ch); p1.ch = NULL; GNUNET_free_non_null (p1.hello); GNUNET_CORE_disconnect (p2.ch); p2.ch = NULL; GNUNET_free_non_null (p2.hello); if (connect_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (connect_task); GNUNET_TRANSPORT_disconnect (p1.th); p1.th = NULL; GNUNET_TRANSPORT_disconnect (p2.th); p2.th = NULL; delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; FPRINTF (stderr, "\nThroughput was %llu kb/s\n", total_bytes * 1000000LL / 1024 / delta); GAUGER ("CORE", "Core throughput/s", total_bytes * 1000000LL / 1024 / delta, "kb/s"); ok = 0; } static void terminate_task_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_break (0); if (p1.ch != NULL) { GNUNET_CORE_disconnect (p1.ch); p1.ch = NULL; } if (p2.ch != NULL) { GNUNET_CORE_disconnect (p2.ch); p2.ch = NULL; } if (connect_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (connect_task); if (p1.th != NULL) { GNUNET_TRANSPORT_get_hello_cancel (p1.ghh); GNUNET_TRANSPORT_disconnect (p1.th); p1.th = NULL; } if (p2.th != NULL) { GNUNET_TRANSPORT_get_hello_cancel (p2.ghh); GNUNET_TRANSPORT_disconnect (p2.th); p2.th = NULL; } ok = 42; } static void try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { connect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &try_connect, NULL); GNUNET_TRANSPORT_try_connect (p1.th, &p2.id, NULL, NULL); /*FIXME TRY_CONNECT change */ } static size_t transmit_ready (void *cls, size_t size, void *buf) { char *cbuf = buf; struct TestMessage hdr; unsigned int s; unsigned int ret; GNUNET_assert (size <= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE); if (buf == NULL) { if (p1.ch != NULL) GNUNET_break (NULL != GNUNET_CORE_notify_transmit_ready (p1.ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, FAST_TIMEOUT, &p2.id, get_size (tr_n), &transmit_ready, &p1)); return 0; } GNUNET_assert (tr_n < TOTAL_MSGS); ret = 0; s = get_size (tr_n); GNUNET_assert (size >= s); GNUNET_assert (buf != NULL); cbuf = buf; do { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message %u of size %u at offset %u\n", tr_n, s, ret); hdr.header.size = htons (s); hdr.header.type = htons (MTYPE); hdr.num = htonl (tr_n); memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage)); ret += sizeof (struct TestMessage); memset (&cbuf[ret], tr_n, s - sizeof (struct TestMessage)); ret += s - sizeof (struct TestMessage); tr_n++; s = get_size (tr_n); if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16)) break; /* sometimes pack buffer full, sometimes not */ } while (size - ret >= s); GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &terminate_task_error, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Returning total message block of size %u\n", ret); total_bytes += ret; return ret; } static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *pc = cls; if (0 == memcmp (&pc->id, peer, sizeof (struct GNUNET_PeerIdentity))) return; GNUNET_assert (pc->connect_status == 0); pc->connect_status = 1; if (pc == &p1) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted connection established to peer `%4s'\n", GNUNET_i2s (peer)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking core (1) for transmission to peer `%4s'\n", GNUNET_i2s (&p2.id)); GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &terminate_task_error, NULL); start_time = GNUNET_TIME_absolute_get (); GNUNET_break (NULL != GNUNET_CORE_notify_transmit_ready (p1.ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, TIMEOUT, &p2.id, get_size (0), &transmit_ready, &p1)); } } static void disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *pc = cls; if (0 == memcmp (&pc->id, peer, sizeof (struct GNUNET_PeerIdentity))) return; pc->connect_status = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer)); } static int inbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core provides inbound data from `%4s'.\n", GNUNET_i2s (other)); return GNUNET_OK; } static int outbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core notifies about outbound data for `%4s'.\n", GNUNET_i2s (other)); return GNUNET_OK; } static size_t transmit_ready (void *cls, size_t size, void *buf); static int process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { static int n; unsigned int s; const struct TestMessage *hdr; hdr = (const struct TestMessage *) message; s = get_size (n); if (MTYPE != ntohs (message->type)) return GNUNET_SYSERR; if (ntohs (message->size) != s) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", n, s, ntohs (message->size), ntohl (hdr->num)); GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_now (&terminate_task_error, NULL); return GNUNET_SYSERR; } if (ntohl (hdr->num) != n) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", n, s, ntohs (message->size), ntohl (hdr->num)); GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_now (&terminate_task_error, NULL); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got message %u of size %u\n", ntohl (hdr->num), ntohs (message->size)); n++; if (0 == (n % (TOTAL_MSGS / 100))) FPRINTF (stderr, "%s", "."); if (n == TOTAL_MSGS) { GNUNET_SCHEDULER_cancel (err_task); GNUNET_SCHEDULER_add_now (&terminate_task, NULL); } else { if (n == tr_n) GNUNET_break (NULL != GNUNET_CORE_notify_transmit_ready (p1.ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, FAST_TIMEOUT, &p2.id, get_size (tr_n), &transmit_ready, &p1)); } return GNUNET_OK; } static struct GNUNET_CORE_MessageHandler handlers[] = { {&process_mtype, MTYPE, 0}, {NULL, 0, 0} }; static void init_notify (void *cls, const struct GNUNET_PeerIdentity *my_identity) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection to CORE service of `%4s' established\n", GNUNET_i2s (my_identity)); p->id = *my_identity; if (cls == &p1) { GNUNET_assert (ok == 2); OKPP; /* connect p2 */ GNUNET_assert (NULL != (p2.ch = GNUNET_CORE_connect (p2.cfg, &p2, &init_notify, &connect_notify, &disconnect_notify, &inbound_notify, GNUNET_YES, &outbound_notify, GNUNET_YES, handlers))); } else { GNUNET_assert (ok == 3); OKPP; GNUNET_assert (cls == &p2); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking transport (1) to connect to peer `%4s'\n", GNUNET_i2s (&p2.id)); connect_task = GNUNET_SCHEDULER_add_now (&try_connect, NULL); } } static void process_hello (void *cls, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received (my) `%s' from transport service\n", "HELLO"); GNUNET_assert (message != NULL); p->hello = GNUNET_copy_message (message); if ((p == &p1) && (p2.th != NULL)) GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL); if ((p == &p2) && (p1.th != NULL)) GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL); if ((p == &p1) && (p2.hello != NULL)) GNUNET_TRANSPORT_offer_hello (p1.th, p2.hello, NULL, NULL); if ((p == &p2) && (p1.hello != NULL)) GNUNET_TRANSPORT_offer_hello (p2.th, p1.hello, NULL, NULL); } static void setup_peer (struct PeerContext *p, const char *cfgname) { char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); p->cfg = GNUNET_CONFIGURATION_create (); p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-arm", "-c", cfgname, NULL); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, NULL, NULL, NULL); GNUNET_assert (p->th != NULL); p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &process_hello, p); GNUNET_free (binary); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_assert (ok == 1); OKPP; setup_peer (&p1, "test_core_api_peer1.conf"); setup_peer (&p2, "test_core_api_peer2.conf"); err_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &terminate_task_error, NULL); GNUNET_assert (NULL != (p1.ch = GNUNET_CORE_connect (p1.cfg, &p1, &init_notify, &connect_notify, &disconnect_notify, &inbound_notify, GNUNET_YES, &outbound_notify, GNUNET_YES, handlers))); } static void stop_arm (struct PeerContext *p) { if (0 != GNUNET_OS_process_kill (p->arm_proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; GNUNET_CONFIGURATION_destroy (p->cfg); } int main (int argc, char *argv1[]) { char *const argv[] = { "test-core-api-reliability", "-c", "test_core_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; ok = 1; GNUNET_log_setup ("test-core-api", "WARNING", NULL); GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-core-api-reliability", "nohelp", options, &run, &ok); stop_arm (&p1); stop_arm (&p2); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-2"); return ok; } /* end of test_core_api_reliability.c */ gnunet-0.10.1/src/core/Makefile.in0000644000175000017500000016112412320752060013600 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-core$(EXEEXT) bin_PROGRAMS = gnunet-core$(EXEEXT) check_PROGRAMS = test_core_api_start_only$(EXEEXT) \ test_core_api$(EXEEXT) test_core_api_reliability$(EXEEXT) \ test_core_quota_compliance_symmetric$(EXEEXT) \ test_core_quota_compliance_asymmetric_send_limited$(EXEEXT) \ test_core_quota_compliance_asymmetric_recv_limited$(EXEEXT) \ $(am__EXEEXT_1) subdir = src/core DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/core.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = core.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunetcore_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunetcore_la_OBJECTS = core_api.lo core_api_iterate_peers.lo libgnunetcore_la_OBJECTS = $(am_libgnunetcore_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetcore_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetcore_la_LDFLAGS) $(LDFLAGS) \ -o $@ @HAVE_TESTING_TRUE@am__EXEEXT_1 = test_core_api_send_to_self$(EXEEXT) \ @HAVE_TESTING_TRUE@ test_core_api_mq$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_core_OBJECTS = gnunet-core.$(OBJEXT) gnunet_core_OBJECTS = $(am_gnunet_core_OBJECTS) am_gnunet_service_core_OBJECTS = gnunet-service-core.$(OBJEXT) \ gnunet-service-core_clients.$(OBJEXT) \ gnunet-service-core_neighbours.$(OBJEXT) \ gnunet-service-core_kx.$(OBJEXT) \ gnunet-service-core_sessions.$(OBJEXT) \ gnunet-service-core_typemap.$(OBJEXT) gnunet_service_core_OBJECTS = $(am_gnunet_service_core_OBJECTS) gnunet_service_core_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_test_core_api_OBJECTS = test_core_api.$(OBJEXT) test_core_api_OBJECTS = $(am_test_core_api_OBJECTS) test_core_api_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_core_api_mq_OBJECTS = test_core_api_mq.$(OBJEXT) test_core_api_mq_OBJECTS = $(am_test_core_api_mq_OBJECTS) test_core_api_mq_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_core_api_reliability_OBJECTS = \ test_core_api_reliability.$(OBJEXT) test_core_api_reliability_OBJECTS = \ $(am_test_core_api_reliability_OBJECTS) test_core_api_reliability_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_core_api_send_to_self_OBJECTS = \ test_core_api_send_to_self.$(OBJEXT) test_core_api_send_to_self_OBJECTS = \ $(am_test_core_api_send_to_self_OBJECTS) test_core_api_send_to_self_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_core_api_start_only_OBJECTS = \ test_core_api_start_only.$(OBJEXT) test_core_api_start_only_OBJECTS = \ $(am_test_core_api_start_only_OBJECTS) test_core_api_start_only_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_core_quota_compliance_asymmetric_recv_limited_OBJECTS = \ test_core_quota_compliance.$(OBJEXT) test_core_quota_compliance_asymmetric_recv_limited_OBJECTS = $(am_test_core_quota_compliance_asymmetric_recv_limited_OBJECTS) test_core_quota_compliance_asymmetric_recv_limited_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_core_quota_compliance_asymmetric_send_limited_OBJECTS = \ test_core_quota_compliance.$(OBJEXT) test_core_quota_compliance_asymmetric_send_limited_OBJECTS = $(am_test_core_quota_compliance_asymmetric_send_limited_OBJECTS) test_core_quota_compliance_asymmetric_send_limited_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la am_test_core_quota_compliance_symmetric_OBJECTS = \ test_core_quota_compliance.$(OBJEXT) test_core_quota_compliance_symmetric_OBJECTS = \ $(am_test_core_quota_compliance_symmetric_OBJECTS) test_core_quota_compliance_symmetric_DEPENDENCIES = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetcore_la_SOURCES) $(gnunet_core_SOURCES) \ $(gnunet_service_core_SOURCES) $(test_core_api_SOURCES) \ $(test_core_api_mq_SOURCES) \ $(test_core_api_reliability_SOURCES) \ $(test_core_api_send_to_self_SOURCES) \ $(test_core_api_start_only_SOURCES) \ $(test_core_quota_compliance_asymmetric_recv_limited_SOURCES) \ $(test_core_quota_compliance_asymmetric_send_limited_SOURCES) \ $(test_core_quota_compliance_symmetric_SOURCES) DIST_SOURCES = $(libgnunetcore_la_SOURCES) $(gnunet_core_SOURCES) \ $(gnunet_service_core_SOURCES) $(test_core_api_SOURCES) \ $(test_core_api_mq_SOURCES) \ $(test_core_api_reliability_SOURCES) \ $(test_core_api_send_to_self_SOURCES) \ $(test_core_api_start_only_SOURCES) \ $(test_core_quota_compliance_asymmetric_recv_limited_SOURCES) \ $(test_core_quota_compliance_asymmetric_send_limited_SOURCES) \ $(test_core_quota_compliance_symmetric_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ core.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov lib_LTLIBRARIES = \ libgnunetcore.la libgnunetcore_la_SOURCES = \ core_api.c core.h \ core_api_iterate_peers.c libgnunetcore_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetcore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:1:0 gnunet_service_core_SOURCES = \ gnunet-service-core.c gnunet-service-core.h \ gnunet-service-core_clients.c gnunet-service-core_clients.h \ gnunet-service-core_neighbours.c gnunet-service-core_neighbours.h \ gnunet-service-core_kx.c gnunet-service-core_kx.h \ gnunet-service-core_sessions.c gnunet-service-core_sessions.h \ gnunet-service-core_typemap.c gnunet-service-core_typemap.h gnunet_service_core_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(Z_LIBS) gnunet_core_SOURCES = \ gnunet-core.c gnunet_core_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_core_DEPENDENCIES = \ libgnunetcore.la @HAVE_TESTING_TRUE@TESTING_TESTS = test_core_api_send_to_self test_core_api_mq @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_core_api_SOURCES = \ test_core_api.c test_core_api_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_api_reliability_SOURCES = \ test_core_api_reliability.c test_core_api_reliability_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_api_send_to_self_SOURCES = \ test_core_api_send_to_self.c test_core_api_send_to_self_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_api_mq_SOURCES = \ test_core_api_mq.c test_core_api_mq_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_api_start_only_SOURCES = \ test_core_api_start_only.c test_core_api_start_only_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_quota_compliance_symmetric_SOURCES = \ test_core_quota_compliance.c test_core_quota_compliance_symmetric_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_core_quota_compliance_asymmetric_send_limited_SOURCES = \ test_core_quota_compliance.c test_core_quota_compliance_asymmetric_send_limited_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_core_quota_compliance_asymmetric_recv_limited_SOURCES = \ test_core_quota_compliance.c test_core_quota_compliance_asymmetric_recv_limited_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la EXTRA_DIST = \ test_core_defaults.conf \ test_core_api_data.conf \ test_core_api_peer1.conf \ test_core_api_peer2.conf \ test_core_api_send_to_self.conf \ test_core_quota_asymmetric_recv_limited_peer1.conf \ test_core_quota_asymmetric_recv_limited_peer2.conf \ test_core_quota_asymmetric_send_limit_peer1.conf \ test_core_quota_asymmetric_send_limit_peer2.conf \ test_core_quota_peer1.conf \ test_core_quota_peer2.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/core/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/core/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): core.conf: $(top_builddir)/config.status $(srcdir)/core.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetcore.la: $(libgnunetcore_la_OBJECTS) $(libgnunetcore_la_DEPENDENCIES) $(EXTRA_libgnunetcore_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetcore_la_LINK) -rpath $(libdir) $(libgnunetcore_la_OBJECTS) $(libgnunetcore_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-core$(EXEEXT): $(gnunet_core_OBJECTS) $(gnunet_core_DEPENDENCIES) $(EXTRA_gnunet_core_DEPENDENCIES) @rm -f gnunet-core$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_core_OBJECTS) $(gnunet_core_LDADD) $(LIBS) gnunet-service-core$(EXEEXT): $(gnunet_service_core_OBJECTS) $(gnunet_service_core_DEPENDENCIES) $(EXTRA_gnunet_service_core_DEPENDENCIES) @rm -f gnunet-service-core$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_core_OBJECTS) $(gnunet_service_core_LDADD) $(LIBS) test_core_api$(EXEEXT): $(test_core_api_OBJECTS) $(test_core_api_DEPENDENCIES) $(EXTRA_test_core_api_DEPENDENCIES) @rm -f test_core_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_core_api_OBJECTS) $(test_core_api_LDADD) $(LIBS) test_core_api_mq$(EXEEXT): $(test_core_api_mq_OBJECTS) $(test_core_api_mq_DEPENDENCIES) $(EXTRA_test_core_api_mq_DEPENDENCIES) @rm -f test_core_api_mq$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_core_api_mq_OBJECTS) $(test_core_api_mq_LDADD) $(LIBS) test_core_api_reliability$(EXEEXT): $(test_core_api_reliability_OBJECTS) $(test_core_api_reliability_DEPENDENCIES) $(EXTRA_test_core_api_reliability_DEPENDENCIES) @rm -f test_core_api_reliability$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_core_api_reliability_OBJECTS) $(test_core_api_reliability_LDADD) $(LIBS) test_core_api_send_to_self$(EXEEXT): $(test_core_api_send_to_self_OBJECTS) $(test_core_api_send_to_self_DEPENDENCIES) $(EXTRA_test_core_api_send_to_self_DEPENDENCIES) @rm -f test_core_api_send_to_self$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_core_api_send_to_self_OBJECTS) $(test_core_api_send_to_self_LDADD) $(LIBS) test_core_api_start_only$(EXEEXT): $(test_core_api_start_only_OBJECTS) $(test_core_api_start_only_DEPENDENCIES) $(EXTRA_test_core_api_start_only_DEPENDENCIES) @rm -f test_core_api_start_only$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_core_api_start_only_OBJECTS) $(test_core_api_start_only_LDADD) $(LIBS) test_core_quota_compliance_asymmetric_recv_limited$(EXEEXT): $(test_core_quota_compliance_asymmetric_recv_limited_OBJECTS) $(test_core_quota_compliance_asymmetric_recv_limited_DEPENDENCIES) $(EXTRA_test_core_quota_compliance_asymmetric_recv_limited_DEPENDENCIES) @rm -f test_core_quota_compliance_asymmetric_recv_limited$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_core_quota_compliance_asymmetric_recv_limited_OBJECTS) $(test_core_quota_compliance_asymmetric_recv_limited_LDADD) $(LIBS) test_core_quota_compliance_asymmetric_send_limited$(EXEEXT): $(test_core_quota_compliance_asymmetric_send_limited_OBJECTS) $(test_core_quota_compliance_asymmetric_send_limited_DEPENDENCIES) $(EXTRA_test_core_quota_compliance_asymmetric_send_limited_DEPENDENCIES) @rm -f test_core_quota_compliance_asymmetric_send_limited$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_core_quota_compliance_asymmetric_send_limited_OBJECTS) $(test_core_quota_compliance_asymmetric_send_limited_LDADD) $(LIBS) test_core_quota_compliance_symmetric$(EXEEXT): $(test_core_quota_compliance_symmetric_OBJECTS) $(test_core_quota_compliance_symmetric_DEPENDENCIES) $(EXTRA_test_core_quota_compliance_symmetric_DEPENDENCIES) @rm -f test_core_quota_compliance_symmetric$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_core_quota_compliance_symmetric_OBJECTS) $(test_core_quota_compliance_symmetric_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_api_iterate_peers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-core.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-core.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-core_clients.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-core_kx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-core_neighbours.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-core_sessions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-core_typemap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_core_api.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_core_api_mq.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_core_api_reliability.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_core_api_send_to_self.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_core_api_start_only.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_core_quota_compliance.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_core_api_start_only.log: test_core_api_start_only$(EXEEXT) @p='test_core_api_start_only$(EXEEXT)'; \ b='test_core_api_start_only'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_core_api.log: test_core_api$(EXEEXT) @p='test_core_api$(EXEEXT)'; \ b='test_core_api'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_core_api_reliability.log: test_core_api_reliability$(EXEEXT) @p='test_core_api_reliability$(EXEEXT)'; \ b='test_core_api_reliability'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_core_quota_compliance_symmetric.log: test_core_quota_compliance_symmetric$(EXEEXT) @p='test_core_quota_compliance_symmetric$(EXEEXT)'; \ b='test_core_quota_compliance_symmetric'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_core_quota_compliance_asymmetric_send_limited.log: test_core_quota_compliance_asymmetric_send_limited$(EXEEXT) @p='test_core_quota_compliance_asymmetric_send_limited$(EXEEXT)'; \ b='test_core_quota_compliance_asymmetric_send_limited'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_core_quota_compliance_asymmetric_recv_limited.log: test_core_quota_compliance_asymmetric_recv_limited$(EXEEXT) @p='test_core_quota_compliance_asymmetric_recv_limited$(EXEEXT)'; \ b='test_core_quota_compliance_asymmetric_recv_limited'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_core_api_send_to_self.log: test_core_api_send_to_self$(EXEEXT) @p='test_core_api_send_to_self$(EXEEXT)'; \ b='test_core_api_send_to_self'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_core_api_mq.log: test_core_api_mq$(EXEEXT) @p='test_core_api_mq$(EXEEXT)'; \ b='test_core_api_mq'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/core/gnunet-service-core_clients.h0000644000175000017500000001104012225777503017315 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_clients.h * @brief code for managing interactions with clients of core service * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_CORE_CLIENTS_H #define GNUNET_SERVICE_CORE_CLIENTS_H #include "gnunet_util_lib.h" #include "gnunet-service-core.h" #include "gnunet-service-core_typemap.h" /** * Send a message to one of our clients. * * @param client target for the message * @param msg message to transmit * @param can_drop could this message be dropped if the * client's queue is getting too large? */ void GSC_CLIENTS_send_to_client (struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg, int can_drop); /** * Notify a particular client about a change to existing connection to * one of our neighbours (check if the client is interested). Called * from 'GSC_SESSIONS_notify_client_about_sessions'. * * @param client client to notify * @param neighbour identity of the neighbour that changed status * @param tmap_old previous type map for the neighbour, NULL for disconnect * @param tmap_new updated type map for the neighbour, NULL for disconnect */ void GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client, const struct GNUNET_PeerIdentity *neighbour, const struct GSC_TypeMap *tmap_old, const struct GSC_TypeMap *tmap_new); /** * Notify all clients about a change to existing session. * Called from SESSIONS whenever there is a change in sessions * or types processed by the respective peer. * * @param neighbour identity of the neighbour that changed status * @param tmap_old previous type map for the neighbour, NULL for disconnect * @param tmap_new updated type map for the neighbour, NULL for disconnect */ void GSC_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour, const struct GSC_TypeMap *tmap_old, const struct GSC_TypeMap *tmap_new); /** * Deliver P2P message to interested clients. Caller must have checked * that the sending peer actually lists the given message type as one * of its types. * * @param sender peer who sent us the message * @param msg the message * @param msize number of bytes to transmit * @param options options for checking which clients should * receive the message */ void GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, uint16_t msize, uint32_t options); /** * Tell a client that we are ready to receive the message. * * @param car request that is now ready; the responsibility * for the handle remains shared between CLIENTS * and SESSIONS after this call. */ void GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car); /** * Tell a client that we will never be ready to receive the * given message in time (disconnect or timeout). * * @param car request that now permanently failed; the * responsibility for the handle is now returned * to CLIENTS (SESSIONS is done with it). */ void GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car); /** * Initialize clients subsystem. * * @param server handle to server clients connect to */ void GSC_CLIENTS_init (struct GNUNET_SERVER_Handle *server); /** * Shutdown clients subsystem. */ void GSC_CLIENTS_done (void); #endif /* end of gnunet-service-core_clients.h */ gnunet-0.10.1/src/core/gnunet-service-core_neighbours.c0000644000175000017500000003575612320463574020034 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_neighbours.c * @brief code for managing low-level 'plaintext' connections with transport (key exchange may or may not be done yet) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet-service-core.h" #include "gnunet-service-core_neighbours.h" #include "gnunet-service-core_kx.h" #include "gnunet-service-core_sessions.h" #include "gnunet_constants.h" /** * Message ready for transmission via transport service. This struct * is followed by the actual content of the message. */ struct NeighbourMessageEntry { /** * We keep messages in a doubly linked list. */ struct NeighbourMessageEntry *next; /** * We keep messages in a doubly linked list. */ struct NeighbourMessageEntry *prev; /** * By when are we supposed to transmit this message? */ struct GNUNET_TIME_Absolute deadline; /** * How long is the message? (number of bytes following the "struct * MessageEntry", but not including the size of "struct * MessageEntry" itself!) */ size_t size; }; /** * Data kept per transport-connected peer. */ struct Neighbour { /** * Head of the batched message queue (already ordered, transmit * starting with the head). */ struct NeighbourMessageEntry *message_head; /** * Tail of the batched message queue (already ordered, append new * messages to tail). */ struct NeighbourMessageEntry *message_tail; /** * Handle for pending requests for transmission to this peer * with the transport service. NULL if no request is pending. */ struct GNUNET_TRANSPORT_TransmitHandle *th; /** * Information about the key exchange with the other peer. */ struct GSC_KeyExchangeInfo *kxinfo; /** * Identity of the other peer. */ struct GNUNET_PeerIdentity peer; /** * ID of task used for re-trying plaintext scheduling. */ GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task; /** * #GNUNET_YES if this peer currently has excess bandwidth. */ int has_excess_bandwidth; }; /** * Map of peer identities to 'struct Neighbour'. */ static struct GNUNET_CONTAINER_MultiPeerMap *neighbours; /** * Transport service. */ static struct GNUNET_TRANSPORT_Handle *transport; /** * Find the entry for the given neighbour. * * @param peer identity of the neighbour * @return NULL if we are not connected, otherwise the * neighbour's entry. */ static struct Neighbour * find_neighbour (const struct GNUNET_PeerIdentity *peer) { if (NULL == neighbours) return NULL; return GNUNET_CONTAINER_multipeermap_get (neighbours, peer); } /** * Free the given entry for the neighbour. * * @param n neighbour to free */ static void free_neighbour (struct Neighbour *n) { struct NeighbourMessageEntry *m; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying neighbour entry for peer `%4s'\n", GNUNET_i2s (&n->peer)); while (NULL != (m = n->message_head)) { GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m); GNUNET_free (m); } if (NULL != n->th) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th); n->th = NULL; } GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# sessions terminated by transport disconnect"), 1, GNUNET_NO); if (NULL != n->kxinfo) { GSC_KX_stop (n->kxinfo); n->kxinfo = NULL; } if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (n->retry_plaintext_task); n->retry_plaintext_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_remove (neighbours, &n->peer, n)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# neighbour entries allocated"), GNUNET_CONTAINER_multipeermap_size (neighbours), GNUNET_NO); GNUNET_free (n); } /** * Check if we have encrypted messages for the specified neighbour * pending, and if so, check with the transport about sending them * out. * * @param n neighbour to check. */ static void process_queue (struct Neighbour *n); /** * Function called when the transport service is ready to receive a * message for the respective peer * * @param cls neighbour to use message from * @param size number of bytes we can transmit * @param buf where to copy the message * @return number of bytes transmitted */ static size_t transmit_ready (void *cls, size_t size, void *buf) { struct Neighbour *n = cls; struct NeighbourMessageEntry *m; size_t ret; char *cbuf; n->th = NULL; m = n->message_head; if (NULL == m) { GNUNET_break (0); return 0; } GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m); if (NULL == buf) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission of message of type %u and size %u failed\n", (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type), (unsigned int) m->size); GNUNET_free (m); process_queue (n); return 0; } cbuf = buf; GNUNET_assert (size >= m->size); memcpy (cbuf, &m[1], m->size); ret = m->size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Copied message of type %u and size %u into transport buffer for `%4s'\n", (unsigned int) ntohs (((struct GNUNET_MessageHeader *) &m[1])->type), (unsigned int) ret, GNUNET_i2s (&n->peer)); GNUNET_free (m); n->has_excess_bandwidth = GNUNET_NO; process_queue (n); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# encrypted bytes given to transport"), ret, GNUNET_NO); return ret; } /** * Check if we have messages for the specified neighbour pending, and * if so, check with the transport about sending them out. * * @param n neighbour to check. */ static void process_queue (struct Neighbour *n) { struct NeighbourMessageEntry *m; if (n->th != NULL) return; /* request already pending */ m = n->message_head; if (m == NULL) { /* notify sessions that the queue is empty and more messages * could thus be queued now */ GSC_SESSIONS_solicit (&n->peer); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking transport for transmission of %u bytes to `%4s' in next %s\n", (unsigned int) m->size, GNUNET_i2s (&n->peer), GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (m->deadline), GNUNET_NO)); n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer, m->size, GNUNET_TIME_absolute_get_remaining (m->deadline), &transmit_ready, n); if (n->th != NULL) return; /* message request too large or duplicate request */ GNUNET_break (0); /* discard encrypted message */ GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m); GNUNET_free (m); process_queue (n); } /** * Function called by transport to notify us that * a peer connected to us (on the network level). * * @param cls closure * @param peer the peer that connected */ static void handle_transport_notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct Neighbour *n; if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); return; } n = find_neighbour (peer); if (n != NULL) { /* duplicate connect notification!? */ GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received connection from `%4s'.\n", GNUNET_i2s (peer)); n = GNUNET_new (struct Neighbour); n->peer = *peer; GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (neighbours, &n->peer, n, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# neighbour entries allocated"), GNUNET_CONTAINER_multipeermap_size (neighbours), GNUNET_NO); n->kxinfo = GSC_KX_start (peer); } /** * Function called by transport telling us that a peer * disconnected. * * @param cls closure * @param peer the peer that disconnected */ static void handle_transport_notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct Neighbour *n; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer `%4s' disconnected from us; received notification from transport.\n", GNUNET_i2s (peer)); n = find_neighbour (peer); if (n == NULL) { GNUNET_break (0); return; } free_neighbour (n); } /** * Function called by the transport for each received message. * * @param cls closure * @param peer (claimed) identity of the other peer * @param message the message */ static void handle_transport_receive (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { struct Neighbour *n; uint16_t type; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u from `%4s', demultiplexing.\n", (unsigned int) ntohs (message->type), GNUNET_i2s (peer)); if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break (0); return; } n = find_neighbour (peer); if (n == NULL) { /* received message from peer that is not connected!? */ GNUNET_break (0); return; } type = ntohs (message->type); switch (type) { case GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY: GSC_KX_handle_ephemeral_key (n->kxinfo, message); break; case GNUNET_MESSAGE_TYPE_CORE_PING: GSC_KX_handle_ping (n->kxinfo, message); break; case GNUNET_MESSAGE_TYPE_CORE_PONG: GSC_KX_handle_pong (n->kxinfo, message); break; case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE: GSC_KX_handle_encrypted_message (n->kxinfo, message); break; case GNUNET_MESSAGE_TYPE_DUMMY: /* Dummy messages for testing / benchmarking, just discard */ break; default: GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Unsupported message of type %u (%u bytes) received from peer `%s'\n"), (unsigned int) type, (unsigned int) ntohs (message->size), GNUNET_i2s (peer)); return; } } /** * Transmit the given message to the given target. * * @param target peer that should receive the message (must be connected) * @param msg message to transmit * @param timeout by when should the transmission be done? */ void GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target, const struct GNUNET_MessageHeader *msg, struct GNUNET_TIME_Relative timeout) { struct NeighbourMessageEntry *me; struct Neighbour *n; size_t msize; n = find_neighbour (target); if (NULL == n) { GNUNET_break (0); return; } msize = ntohs (msg->size); me = GNUNET_malloc (sizeof (struct NeighbourMessageEntry) + msize); me->deadline = GNUNET_TIME_relative_to_absolute (timeout); me->size = msize; memcpy (&me[1], msg, msize); GNUNET_CONTAINER_DLL_insert_tail (n->message_head, n->message_tail, me); process_queue (n); } /** * One of our neighbours has excess bandwidth, * remember this. * * @param cls NULL * @param pid identity of the peer with excess bandwidth */ static void handle_transport_notify_excess_bw (void *cls, const struct GNUNET_PeerIdentity *pid) { struct Neighbour *n; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %s has excess bandwidth available\n", GNUNET_i2s (pid)); n = find_neighbour (pid); if (NULL == n) { GNUNET_break (0); return; } n->has_excess_bandwidth = GNUNET_YES; GSC_SESSIONS_solicit (pid); } /** * Check if the given neighbour has excess bandwidth available. * * @param target neighbour to check * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not */ int GSC_NEIGHBOURS_check_excess_bandwidth (const struct GNUNET_PeerIdentity *target) { struct Neighbour *n; n = find_neighbour (target); if (NULL == n) { GNUNET_break (0); return GNUNET_SYSERR; } return n->has_excess_bandwidth; } /** * Initialize neighbours subsystem. */ int GSC_NEIGHBOURS_init () { neighbours = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); transport = GNUNET_TRANSPORT_connect2 (GSC_cfg, &GSC_my_identity, NULL, &handle_transport_receive, &handle_transport_notify_connect, &handle_transport_notify_disconnect, &handle_transport_notify_excess_bw); if (NULL == transport) { GNUNET_CONTAINER_multipeermap_destroy (neighbours); neighbours = NULL; return GNUNET_SYSERR; } return GNUNET_OK; } /** * Wrapper around 'free_neighbour'. * * @param cls unused * @param key peer identity * @param value the `struct Neighbour` to free * @return #GNUNET_OK (continue to iterate) */ static int free_neighbour_helper (void *cls, const struct GNUNET_PeerIdentity * key, void *value) { struct Neighbour *n = value; /* transport should have 'disconnected' all neighbours... */ GNUNET_break (0); free_neighbour (n); return GNUNET_OK; } /** * Shutdown neighbours subsystem. */ void GSC_NEIGHBOURS_done () { if (NULL != transport) { GNUNET_TRANSPORT_disconnect (transport); transport = NULL; } if (NULL != neighbours) { GNUNET_CONTAINER_multipeermap_iterate (neighbours, &free_neighbour_helper, NULL); GNUNET_CONTAINER_multipeermap_destroy (neighbours); neighbours = NULL; } } /* end of gnunet-service-core_neighbours.c */ gnunet-0.10.1/src/core/test_core_api_peer1.conf0000644000175000017500000000122512225230043016305 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core-peer-1/ [arm] PORT = 12460 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock [statistics] PORT = 12461 [resolver] PORT = 12462 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock [peerinfo] PORT = 12463 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock [transport] PORT = 12464 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock [ats] PORT = 12475 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-ats.sock [transport-tcp] PORT = 12467 [transport-udp] PORT = 12468 [transport-unix] PORT = 12469 [transport-http] PORT = 12470 gnunet-0.10.1/src/core/gnunet-service-core_kx.c0000644000175000017500000013755412320463212016275 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_kx.c * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other peers * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-core_kx.h" #include "gnunet-service-core.h" #include "gnunet-service-core_clients.h" #include "gnunet-service-core_neighbours.h" #include "gnunet-service-core_sessions.h" #include "gnunet_statistics_service.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_protocols.h" #include "core.h" /** * How long do we wait for SET_KEY confirmation initially? */ #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) /** * What is the minimum frequency for a PING message? */ #define MIN_PING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * How often do we rekey? */ #define REKEY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) /** * What time difference do we tolerate? */ #define REKEY_TOLERANCE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) /** * What is the maximum age of a message for us to consider processing * it? Note that this looks at the timestamp used by the other peer, * so clock skew between machines does come into play here. So this * should be picked high enough so that a little bit of clock skew * does not prevent peers from connecting to us. */ #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS GNUNET_NETWORK_STRUCT_BEGIN /** * Message transmitted with the signed ephemeral key of a peer. The * session key is then derived from the two ephemeral keys (ECDHE). */ struct EphemeralKeyMessage { /** * Message type is #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY. */ struct GNUNET_MessageHeader header; /** * Status of the sender (should be in "enum PeerStateMachine"), nbo. */ int32_t sender_status GNUNET_PACKED; /** * An ECC signature of the 'origin' asserting the validity of * the given ephemeral key. */ struct GNUNET_CRYPTO_EddsaSignature signature; /** * Information about what is being signed. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** * At what time was this key created (beginning of validity). */ struct GNUNET_TIME_AbsoluteNBO creation_time; /** * When does the given ephemeral key expire (end of validity). */ struct GNUNET_TIME_AbsoluteNBO expiration_time; /** * Ephemeral public ECC key. */ struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; /** * Public key of the signing peer (persistent version, not the ephemeral public key). */ struct GNUNET_PeerIdentity origin_identity; }; /** * We're sending an (encrypted) PING to the other peer to check if he * can decrypt. The other peer should respond with a PONG with the * same content, except this time encrypted with the receiver's key. */ struct PingMessage { /** * Message type is #GNUNET_MESSAGE_TYPE_CORE_PING. */ struct GNUNET_MessageHeader header; /** * Seed for the IV */ uint32_t iv_seed GNUNET_PACKED; /** * Intended target of the PING, used primarily to check * that decryption actually worked. */ struct GNUNET_PeerIdentity target; /** * Random number chosen to make reply harder. */ uint32_t challenge GNUNET_PACKED; }; /** * Response to a PING. Includes data from the original PING. */ struct PongMessage { /** * Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG. */ struct GNUNET_MessageHeader header; /** * Seed for the IV */ uint32_t iv_seed GNUNET_PACKED; /** * Random number to make faking the reply harder. Must be * first field after header (this is where we start to encrypt!). */ uint32_t challenge GNUNET_PACKED; /** * Reserved, always zero. */ uint32_t reserved; /** * Intended target of the PING, used primarily to check * that decryption actually worked. */ struct GNUNET_PeerIdentity target; }; /** * Encapsulation for encrypted messages exchanged between * peers. Followed by the actual encrypted data. */ struct EncryptedMessage { /** * Message type is either #GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE. */ struct GNUNET_MessageHeader header; /** * Random value used for IV generation. */ uint32_t iv_seed GNUNET_PACKED; /** * MAC of the encrypted message (starting at 'sequence_number'), * used to verify message integrity. Everything after this value * (excluding this value itself) will be encrypted and authenticated. * ENCRYPTED_HEADER_SIZE must be set to the offset of the *next* field. */ struct GNUNET_HashCode hmac; /** * Sequence number, in network byte order. This field * must be the first encrypted/decrypted field */ uint32_t sequence_number GNUNET_PACKED; /** * Reserved, always zero. */ uint32_t reserved; /** * Timestamp. Used to prevent reply of ancient messages * (recent messages are caught with the sequence number). */ struct GNUNET_TIME_AbsoluteNBO timestamp; }; GNUNET_NETWORK_STRUCT_END /** * Number of bytes (at the beginning) of "struct EncryptedMessage" * that are NOT encrypted. */ #define ENCRYPTED_HEADER_SIZE (offsetof(struct EncryptedMessage, sequence_number)) /** * State machine for our P2P encryption handshake. Everyone starts in * "DOWN", if we receive the other peer's key (other peer initiated) * we start in state RECEIVED (since we will immediately send our * own); otherwise we start in SENT. If we get back a PONG from * within either state, we move up to CONFIRMED (the PONG will always * be sent back encrypted with the key we sent to the other peer). */ enum KxStateMachine { /** * No handshake yet. */ KX_STATE_DOWN, /** * We've sent our session key. */ KX_STATE_KEY_SENT, /** * We've received the other peers session key. */ KX_STATE_KEY_RECEIVED, /** * The other peer has confirmed our session key + PING with a PONG * message encrypted with his session key (which we got). Key * exchange is done. */ KX_STATE_UP, /** * We're rekeying (or had a timeout), so we have sent the other peer * our new ephemeral key, but we did not get a matching PONG yet. * This is equivalent to being 'KX_STATE_KEY_RECEIVED', except that * the session is marked as 'up' with sessions (as we don't want to * drop and re-establish P2P connections simply due to rekeying). */ KX_STATE_REKEY_SENT }; /** * Information about the status of a key exchange with another peer. */ struct GSC_KeyExchangeInfo { /** * DLL. */ struct GSC_KeyExchangeInfo *next; /** * DLL. */ struct GSC_KeyExchangeInfo *prev; /** * Identity of the peer. */ struct GNUNET_PeerIdentity peer; /** * PING message we transmit to the other peer. */ struct PingMessage ping; /** * Ephemeral public ECC key of the other peer. */ struct GNUNET_CRYPTO_EcdhePublicKey other_ephemeral_key; /** * Key we use to encrypt our messages for the other peer * (initialized by us when we do the handshake). */ struct GNUNET_CRYPTO_SymmetricSessionKey encrypt_key; /** * Key we use to decrypt messages from the other peer * (given to us by the other peer during the handshake). */ struct GNUNET_CRYPTO_SymmetricSessionKey decrypt_key; /** * At what time did the other peer generate the decryption key? */ struct GNUNET_TIME_Absolute foreign_key_expires; /** * When should the session time out (if there are no PONGs)? */ struct GNUNET_TIME_Absolute timeout; /** * At what frequency are we currently re-trying SET_KEY messages? */ struct GNUNET_TIME_Relative set_key_retry_frequency; /** * ID of task used for re-trying SET_KEY and PING message. */ GNUNET_SCHEDULER_TaskIdentifier retry_set_key_task; /** * ID of task used for sending keep-alive pings. */ GNUNET_SCHEDULER_TaskIdentifier keep_alive_task; /** * Bit map indicating which of the 32 sequence numbers before the last * were received (good for accepting out-of-order packets and * estimating reliability of the connection) */ unsigned int last_packets_bitmap; /** * last sequence number received on this connection (highest) */ uint32_t last_sequence_number_received; /** * last sequence number transmitted */ uint32_t last_sequence_number_sent; /** * What was our PING challenge number (for this peer)? */ uint32_t ping_challenge; /** * What is our connection status? */ enum KxStateMachine status; }; /** * Our private key. */ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; /** * Our ephemeral private key. */ static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key; /** * Current message we send for a key exchange. */ static struct EphemeralKeyMessage current_ekm; /** * Our message stream tokenizer (for encrypted payload). */ static struct GNUNET_SERVER_MessageStreamTokenizer *mst; /** * DLL head. */ static struct GSC_KeyExchangeInfo *kx_head; /** * DLL tail. */ static struct GSC_KeyExchangeInfo *kx_tail; /** * Task scheduled for periodic re-generation (and thus rekeying) of our * ephemeral key. */ static GNUNET_SCHEDULER_TaskIdentifier rekey_task; /** * Derive an authentication key from "set key" information * * @param akey authentication key to derive * @param skey session key to use * @param seed seed to use */ static void derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed) { static const char ctx[] = "authentication key"; GNUNET_CRYPTO_hmac_derive_key (akey, skey, &seed, sizeof (seed), skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), ctx, sizeof (ctx), NULL); } /** * Derive an IV from packet information * * @param iv initialization vector to initialize * @param skey session key to use * @param seed seed to use * @param identity identity of the other peer to use */ static void derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed, const struct GNUNET_PeerIdentity *identity) { static const char ctx[] = "initialization vector"; GNUNET_CRYPTO_symmetric_derive_iv (iv, skey, &seed, sizeof (seed), identity, sizeof (struct GNUNET_PeerIdentity), ctx, sizeof (ctx), NULL); } /** * Derive an IV from pong packet information * * @param iv initialization vector to initialize * @param skey session key to use * @param seed seed to use * @param challenge nonce to use * @param identity identity of the other peer to use */ static void derive_pong_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *skey, uint32_t seed, uint32_t challenge, const struct GNUNET_PeerIdentity *identity) { static const char ctx[] = "pong initialization vector"; GNUNET_CRYPTO_symmetric_derive_iv (iv, skey, &seed, sizeof (seed), identity, sizeof (struct GNUNET_PeerIdentity), &challenge, sizeof (challenge), ctx, sizeof (ctx), NULL); } /** * Derive an AES key from key material * * @param sender peer identity of the sender * @param receiver peer identity of the sender * @param key_material high entropy key material to use * @param skey set to derived session key */ static void derive_aes_key (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_PeerIdentity *receiver, const struct GNUNET_HashCode *key_material, struct GNUNET_CRYPTO_SymmetricSessionKey *skey) { static const char ctx[] = "aes key generation vector"; GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), ctx, sizeof (ctx), key_material, sizeof (struct GNUNET_HashCode), sender, sizeof (struct GNUNET_PeerIdentity), receiver, sizeof (struct GNUNET_PeerIdentity), NULL); } /** * Encrypt size bytes from @a in and write the result to @a out. Use the * @a kx key for outbound traffic of the given neighbour. * * @param kx key information context * @param iv initialization vector to use * @param in ciphertext * @param out plaintext * @param size size of @a in/@a out * @return #GNUNET_OK on success */ static int do_encrypt (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const void *in, void *out, size_t size) { if (size != (uint16_t) size) { GNUNET_break (0); return GNUNET_NO; } GNUNET_assert (size == GNUNET_CRYPTO_symmetric_encrypt (in, (uint16_t) size, &kx->encrypt_key, iv, out)); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes encrypted"), size, GNUNET_NO); /* the following is too sensitive to write to log files by accident, so we require manual intervention to get this one... */ #if 0 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted %u bytes for `%4s' using key %u, IV %u\n", (unsigned int) size, GNUNET_i2s (&kx->peer), (unsigned int) kx->encrypt_key.crc32, GNUNET_CRYPTO_crc32_n (iv, sizeof (iv))); #endif return GNUNET_OK; } /** * Decrypt size bytes from @a in and write the result to @a out. Use the * @a kx key for inbound traffic of the given neighbour. This function does * NOT do any integrity-checks on the result. * * @param kx key information context * @param iv initialization vector to use * @param in ciphertext * @param out plaintext * @param size size of @a in / @a out * @return #GNUNET_OK on success */ static int do_decrypt (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, const void *in, void *out, size_t size) { if (size != (uint16_t) size) { GNUNET_break (0); return GNUNET_NO; } if ( (kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && (kx->status != KX_STATE_REKEY_SENT) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } if (size != GNUNET_CRYPTO_symmetric_decrypt (in, (uint16_t) size, &kx->decrypt_key, iv, out)) { GNUNET_break (0); return GNUNET_SYSERR; } GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes decrypted"), size, GNUNET_NO); /* the following is too sensitive to write to log files by accident, so we require manual intervention to get this one... */ #if 0 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decrypted %u bytes from `%4s' using key %u, IV %u\n", (unsigned int) size, GNUNET_i2s (&kx->peer), (unsigned int) kx->decrypt_key.crc32, GNUNET_CRYPTO_crc32_n (iv, sizeof (*iv))); #endif return GNUNET_OK; } /** * Send our key (and encrypted PING) to the other peer. * * @param kx key exchange context */ static void send_key (struct GSC_KeyExchangeInfo *kx); /** * Task that will retry #send_key() if our previous attempt failed. * * @param cls our `struct GSC_KeyExchangeInfo` * @param tc scheduler context */ static void set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSC_KeyExchangeInfo *kx = cls; kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; kx->set_key_retry_frequency = GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency); GNUNET_assert (KX_STATE_DOWN != kx->status); send_key (kx); } /** * Create a fresh PING message for transmission to the other peer. * * @param kx key exchange context to create PING for */ static void setup_fresh_ping (struct GSC_KeyExchangeInfo *kx) { struct PingMessage pp; struct PingMessage *pm; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; pm = &kx->ping; pm->header.size = htons (sizeof (struct PingMessage)); pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING); pm->iv_seed = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, &kx->peer); pp.challenge = kx->ping_challenge; pp.target = kx->peer; do_encrypt (kx, &iv, &pp.target, &pm->target, sizeof (struct PingMessage) - ((void *) &pm->target - (void *) pm)); } /** * Start the key exchange with the given peer. * * @param pid identity of the peer to do a key exchange with * @return key exchange information context */ struct GSC_KeyExchangeInfo * GSC_KX_start (const struct GNUNET_PeerIdentity *pid) { struct GSC_KeyExchangeInfo *kx; struct GNUNET_HashCode h1; struct GNUNET_HashCode h2; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initiating key exchange with `%s'\n", GNUNET_i2s (pid)); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# key exchanges initiated"), 1, GNUNET_NO); kx = GNUNET_new (struct GSC_KeyExchangeInfo); kx->peer = *pid; kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY; GNUNET_CONTAINER_DLL_insert (kx_head, kx_tail, kx); GNUNET_CRYPTO_hash (pid, sizeof (struct GNUNET_PeerIdentity), &h1); GNUNET_CRYPTO_hash (&GSC_my_identity, sizeof (struct GNUNET_PeerIdentity), &h2); kx->status = KX_STATE_KEY_SENT; if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2)) { /* peer with "lower" identity starts KX, otherwise we typically end up with both peers starting the exchange and transmit the 'set key' message twice */ send_key (kx); } else { /* peer with "higher" identity starts a delayed KX, if the "lower" peer * does not start a KX since he sees no reasons to do so */ kx->retry_set_key_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &set_key_retry_task, kx); } return kx; } /** * Stop key exchange with the given peer. Clean up key material. * * @param kx key exchange to stop */ void GSC_KX_stop (struct GSC_KeyExchangeInfo *kx) { GSC_SESSIONS_end (&kx->peer); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# key exchanges stopped"), 1, GNUNET_NO); if (kx->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; } if (kx->keep_alive_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (kx->keep_alive_task); kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx); GNUNET_free (kx); } /** * Send our PING to the other peer. * * @param kx key exchange context */ static void send_ping (struct GSC_KeyExchangeInfo *kx) { GSC_NEIGHBOURS_transmit (&kx->peer, &kx->ping.header, MIN_PING_FREQUENCY); } /** * Derive fresh session keys from the current ephemeral keys. * * @param kx session to derive keys for */ static void derive_session_keys (struct GSC_KeyExchangeInfo *kx) { struct GNUNET_HashCode key_material; if (GNUNET_OK != GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key, &kx->other_ephemeral_key, &key_material)) { GNUNET_break (0); return; } derive_aes_key (&GSC_my_identity, &kx->peer, &key_material, &kx->encrypt_key); derive_aes_key (&kx->peer, &GSC_my_identity, &key_material, &kx->decrypt_key); memset (&key_material, 0, sizeof (key_material)); /* fresh key, reset sequence numbers */ kx->last_sequence_number_received = 0; kx->last_packets_bitmap = 0; setup_fresh_ping (kx); } /** * We received a SET_KEY message. Validate and update * our key material and status. * * @param kx key exchange status for the corresponding peer * @param msg the set key message we received */ void GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg) { const struct EphemeralKeyMessage *m; struct GNUNET_TIME_Absolute start_t; struct GNUNET_TIME_Absolute end_t; struct GNUNET_TIME_Absolute now; enum KxStateMachine sender_status; uint16_t size; size = ntohs (msg->size); if (sizeof (struct EphemeralKeyMessage) != size) { GNUNET_break_op (0); return; } m = (const struct EphemeralKeyMessage *) msg; end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time); if ( ( (KX_STATE_KEY_RECEIVED == kx->status) || (KX_STATE_UP == kx->status) || (KX_STATE_REKEY_SENT == kx->status) ) && (end_t.abs_value_us <= kx->foreign_key_expires.abs_value_us) ) { GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# old ephemeral keys ignored"), 1, GNUNET_NO); return; } start_t = GNUNET_TIME_absolute_ntoh (m->creation_time); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# ephemeral keys received"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service receives `%s' request from `%4s'.\n", "EPHEMERAL_KEY", GNUNET_i2s (&kx->peer)); if (0 != memcmp (&m->origin_identity, &kx->peer.public_key, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); return; } if ((ntohl (m->purpose.size) != sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) || (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY, &m->purpose, &m->signature, &m->origin_identity.public_key))) { /* invalid signature */ GNUNET_break_op (0); return; } now = GNUNET_TIME_absolute_get (); if ( (end_t.abs_value_us < GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value_us) || (start_t.abs_value_us > GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value_us) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Ephemeral key message from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"), GNUNET_i2s (&kx->peer), now.abs_value_us, start_t.abs_value_us, end_t.abs_value_us); return; } kx->other_ephemeral_key = m->ephemeral_key; kx->foreign_key_expires = end_t; derive_session_keys (kx); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# EPHEMERAL_KEY messages received"), 1, GNUNET_NO); /* check if we still need to send the sender our key */ sender_status = (enum KxStateMachine) ntohl (m->sender_status); switch (sender_status) { case KX_STATE_DOWN: GNUNET_break_op (0); break; case KX_STATE_KEY_SENT: /* fine, need to send our key after updating our status, see below */ break; case KX_STATE_KEY_RECEIVED: case KX_STATE_UP: case KX_STATE_REKEY_SENT: /* other peer already got our key */ break; default: GNUNET_break (0); break; } /* check if we need to confirm everything is fine via PING + PONG */ switch (kx->status) { case KX_STATE_DOWN: GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); kx->status = KX_STATE_KEY_RECEIVED; if (KX_STATE_KEY_SENT == sender_status) send_key (kx); send_ping (kx); break; case KX_STATE_KEY_SENT: GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); kx->status = KX_STATE_KEY_RECEIVED; if (KX_STATE_KEY_SENT == sender_status) send_key (kx); send_ping (kx); break; case KX_STATE_KEY_RECEIVED: GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); if (KX_STATE_KEY_SENT == sender_status) send_key (kx); send_ping (kx); break; case KX_STATE_UP: kx->status = KX_STATE_REKEY_SENT; if (KX_STATE_KEY_SENT == sender_status) send_key (kx); /* we got a new key, need to reconfirm! */ send_ping (kx); break; case KX_STATE_REKEY_SENT: if (KX_STATE_KEY_SENT == sender_status) send_key (kx); /* we got a new key, need to reconfirm! */ send_ping (kx); break; default: GNUNET_break (0); break; } } /** * We received a PING message. Validate and transmit * a PONG message. * * @param kx key exchange status for the corresponding peer * @param msg the encrypted PING message itself */ void GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg) { const struct PingMessage *m; struct PingMessage t; struct PongMessage tx; struct PongMessage tp; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; uint16_t msize; msize = ntohs (msg->size); if (msize != sizeof (struct PingMessage)) { GNUNET_break_op (0); return; } GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PING messages received"), 1, GNUNET_NO); if ( (kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && (kx->status != KX_STATE_REKEY_SENT)) { /* ignore */ GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PING messages dropped (out of order)"), 1, GNUNET_NO); return; } m = (const struct PingMessage *) msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service receives `%s' request from `%4s'.\n", "PING", GNUNET_i2s (&kx->peer)); derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity); if (GNUNET_OK != do_decrypt (kx, &iv, &m->target, &t.target, sizeof (struct PingMessage) - ((void *) &m->target - (void *) m))) { GNUNET_break_op (0); return; } if (0 != memcmp (&t.target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) { char sender[9]; char peer[9]; GNUNET_snprintf (sender, sizeof (sender), "%8s", GNUNET_i2s (&kx->peer)); GNUNET_snprintf (peer, sizeof (peer), "%8s", GNUNET_i2s (&t.target)); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Received PING from `%s' for different identity: I am `%s', PONG identity: `%s'\n"), sender, GNUNET_i2s (&GSC_my_identity), peer); GNUNET_break_op (0); return; } /* construct PONG */ tx.reserved = 0; tx.challenge = t.challenge; tx.target = t.target; tp.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG); tp.header.size = htons (sizeof (struct PongMessage)); tp.iv_seed = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); derive_pong_iv (&iv, &kx->encrypt_key, tp.iv_seed, t.challenge, &kx->peer); do_encrypt (kx, &iv, &tx.challenge, &tp.challenge, sizeof (struct PongMessage) - ((void *) &tp.challenge - (void *) &tp)); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PONG messages created"), 1, GNUNET_NO); GSC_NEIGHBOURS_transmit (&kx->peer, &tp.header, GNUNET_TIME_UNIT_FOREVER_REL /* FIXME: timeout */ ); } /** * Task triggered when a neighbour entry is about to time out * (and we should prevent this by sending a PING). * * @param cls the 'struct GSC_KeyExchangeInfo' * @param tc scheduler context (not used) */ static void send_keep_alive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSC_KeyExchangeInfo *kx = cls; struct GNUNET_TIME_Relative retry; struct GNUNET_TIME_Relative left; kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; left = GNUNET_TIME_absolute_get_remaining (kx->timeout); if (0 == left.rel_value_us) { GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# sessions terminated by timeout"), 1, GNUNET_NO); GSC_SESSIONS_end (&kx->peer); kx->status = KX_STATE_KEY_SENT; send_key (kx); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending KEEPALIVE to `%s'\n", GNUNET_i2s (&kx->peer)); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# keepalive messages sent"), 1, GNUNET_NO); setup_fresh_ping (kx); GSC_NEIGHBOURS_transmit (&kx->peer, &kx->ping.header, kx->set_key_retry_frequency); retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2), MIN_PING_FREQUENCY); kx->keep_alive_task = GNUNET_SCHEDULER_add_delayed (retry, &send_keep_alive, kx); } /** * We've seen a valid message from the other peer. * Update the time when the session would time out * and delay sending our keep alive message further. * * @param kx key exchange where we saw activity */ static void update_timeout (struct GSC_KeyExchangeInfo *kx) { kx->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); if (kx->keep_alive_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (kx->keep_alive_task); kx->keep_alive_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2), &send_keep_alive, kx); } /** * We received a PONG message. Validate and update our status. * * @param kx key exchange context for the the PONG * @param msg the encrypted PONG message itself */ void GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg) { const struct PongMessage *m; struct PongMessage t; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; uint16_t msize; msize = ntohs (msg->size); if (sizeof (struct PongMessage) != msize) { GNUNET_break_op (0); return; } GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PONG messages received"), 1, GNUNET_NO); switch (kx->status) { case KX_STATE_DOWN: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PONG messages dropped (connection down)"), 1, GNUNET_NO); return; case KX_STATE_KEY_SENT: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PONG messages dropped (out of order)"), 1, GNUNET_NO); return; case KX_STATE_KEY_RECEIVED: break; case KX_STATE_UP: break; case KX_STATE_REKEY_SENT: break; default: GNUNET_break (0); return; } m = (const struct PongMessage *) msg; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service receives `%s' response from `%4s'.\n", "PONG", GNUNET_i2s (&kx->peer)); /* mark as garbage, just to be sure */ memset (&t, 255, sizeof (t)); derive_pong_iv (&iv, &kx->decrypt_key, m->iv_seed, kx->ping_challenge, &GSC_my_identity); if (GNUNET_OK != do_decrypt (kx, &iv, &m->challenge, &t.challenge, sizeof (struct PongMessage) - ((void *) &m->challenge - (void *) m))) { GNUNET_break_op (0); return; } GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PONG messages decrypted"), 1, GNUNET_NO); if ((0 != memcmp (&t.target, &kx->peer, sizeof (struct GNUNET_PeerIdentity))) || (kx->ping_challenge != t.challenge)) { /* PONG malformed */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received malformed `%s' wanted sender `%4s' with challenge %u\n", "PONG", GNUNET_i2s (&kx->peer), (unsigned int) kx->ping_challenge); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received malformed `%s' received from `%4s' with challenge %u\n", "PONG", GNUNET_i2s (&t.target), (unsigned int) t.challenge); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received PONG from `%s'\n", GNUNET_i2s (&kx->peer)); /* no need to resend key any longer */ if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) { GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; } switch (kx->status) { case KX_STATE_DOWN: GNUNET_assert (0); /* should be impossible */ return; case KX_STATE_KEY_SENT: GNUNET_assert (0); /* should be impossible */ return; case KX_STATE_KEY_RECEIVED: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# session keys confirmed via PONG"), 1, GNUNET_NO); kx->status = KX_STATE_UP; GSC_SESSIONS_create (&kx->peer, kx); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); update_timeout (kx); break; case KX_STATE_UP: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# timeouts prevented via PONG"), 1, GNUNET_NO); update_timeout (kx); break; case KX_STATE_REKEY_SENT: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# rekey operations confirmed via PONG"), 1, GNUNET_NO); kx->status = KX_STATE_UP; update_timeout (kx); break; default: GNUNET_break (0); break; } } /** * Send our key to the other peer. * * @param kx key exchange context */ static void send_key (struct GSC_KeyExchangeInfo *kx) { GNUNET_assert (KX_STATE_DOWN != kx->status); if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) { GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; } /* always update sender status in SET KEY message */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending key to `%s' (my status: %d)\n", GNUNET_i2s (&kx->peer), kx->status); current_ekm.sender_status = htonl ((int32_t) (kx->status)); GSC_NEIGHBOURS_transmit (&kx->peer, ¤t_ekm.header, kx->set_key_retry_frequency); kx->retry_set_key_task = GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, &set_key_retry_task, kx); } /** * Encrypt and transmit a message with the given payload. * * @param kx key exchange context * @param payload payload of the message * @param payload_size number of bytes in 'payload' */ void GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, const void *payload, size_t payload_size) { size_t used = payload_size + sizeof (struct EncryptedMessage); char pbuf[used]; /* plaintext */ char cbuf[used]; /* ciphertext */ struct EncryptedMessage *em; /* encrypted message */ struct EncryptedMessage *ph; /* plaintext header */ struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_AuthKey auth_key; ph = (struct EncryptedMessage *) pbuf; ph->iv_seed = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); ph->sequence_number = htonl (++kx->last_sequence_number_sent); ph->reserved = 0; ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); memcpy (&ph[1], payload, payload_size); em = (struct EncryptedMessage *) cbuf; em->header.size = htons (used); em->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE); em->iv_seed = ph->iv_seed; derive_iv (&iv, &kx->encrypt_key, ph->iv_seed, &kx->peer); GNUNET_assert (GNUNET_OK == do_encrypt (kx, &iv, &ph->sequence_number, &em->sequence_number, used - ENCRYPTED_HEADER_SIZE)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted %u bytes for %s\n", used - ENCRYPTED_HEADER_SIZE, GNUNET_i2s (&kx->peer)); derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed); GNUNET_CRYPTO_hmac (&auth_key, &em->sequence_number, used - ENCRYPTED_HEADER_SIZE, &em->hmac); GSC_NEIGHBOURS_transmit (&kx->peer, &em->header, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Closure for #deliver_message() */ struct DeliverMessageContext { /** * Key exchange context. */ struct GSC_KeyExchangeInfo *kx; /** * Sender of the message. */ const struct GNUNET_PeerIdentity *peer; }; /** * We received an encrypted message. Decrypt, validate and * pass on to the appropriate clients. * * @param kx key exchange context for encrypting the message * @param msg encrypted message */ void GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg) { const struct EncryptedMessage *m; struct EncryptedMessage *pt; /* plaintext */ struct GNUNET_HashCode ph; uint32_t snum; struct GNUNET_TIME_Absolute t; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_AuthKey auth_key; struct DeliverMessageContext dmc; uint16_t size = ntohs (msg->size); char buf[size] GNUNET_ALIGN; if (size < sizeof (struct EncryptedMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break_op (0); return; } m = (const struct EncryptedMessage *) msg; if (KX_STATE_UP != kx->status) { GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# DATA message dropped (out of order)"), 1, GNUNET_NO); return; } if (0 == GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Session to peer `%s' went down due to key expiration (should not happen)\n"), GNUNET_i2s (&kx->peer)); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# sessions terminated by key expiration"), 1, GNUNET_NO); GSC_SESSIONS_end (&kx->peer); if (GNUNET_SCHEDULER_NO_TASK != kx->keep_alive_task) { GNUNET_SCHEDULER_cancel (kx->keep_alive_task); kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; } kx->status = KX_STATE_KEY_SENT; send_key (kx); return; } /* validate hash */ derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed); GNUNET_CRYPTO_hmac (&auth_key, &m->sequence_number, size - ENCRYPTED_HEADER_SIZE, &ph); if (0 != memcmp (&ph, &m->hmac, sizeof (struct GNUNET_HashCode))) { /* checksum failed */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed checksum validation for a message from `%s'\n", GNUNET_i2s (&kx->peer)); return; } derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity); /* decrypt */ if (GNUNET_OK != do_decrypt (kx, &iv, &m->sequence_number, &buf[ENCRYPTED_HEADER_SIZE], size - ENCRYPTED_HEADER_SIZE)) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Decrypted %u bytes from %s\n", size - ENCRYPTED_HEADER_SIZE, GNUNET_i2s (&kx->peer)); pt = (struct EncryptedMessage *) buf; /* validate sequence number */ snum = ntohl (pt->sequence_number); if (kx->last_sequence_number_received == snum) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received duplicate message, ignoring.\n"); /* duplicate, ignore */ GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes dropped (duplicates)"), size, GNUNET_NO); return; } if ((kx->last_sequence_number_received > snum) && (kx->last_sequence_number_received - snum > 32)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ancient out of sequence message, ignoring.\n"); /* ancient out of sequence, ignore */ GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes dropped (out of sequence)"), size, GNUNET_NO); return; } if (kx->last_sequence_number_received > snum) { unsigned int rotbit = 1 << (kx->last_sequence_number_received - snum - 1); if ((kx->last_packets_bitmap & rotbit) != 0) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received duplicate message, ignoring.\n"); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes dropped (duplicates)"), size, GNUNET_NO); /* duplicate, ignore */ return; } kx->last_packets_bitmap |= rotbit; } if (kx->last_sequence_number_received < snum) { unsigned int shift = (snum - kx->last_sequence_number_received); if (shift >= 8 * sizeof (kx->last_packets_bitmap)) kx->last_packets_bitmap = 0; else kx->last_packets_bitmap <<= shift; kx->last_sequence_number_received = snum; } /* check timestamp */ t = GNUNET_TIME_absolute_ntoh (pt->timestamp); if (GNUNET_TIME_absolute_get_duration (t).rel_value_us > MAX_MESSAGE_AGE.rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message received far too old (%s). Content ignored.\n", GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (t), GNUNET_YES)); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes dropped (ancient message)"), size, GNUNET_NO); return; } /* process decrypted message(s) */ update_timeout (kx); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# bytes of payload decrypted"), size - sizeof (struct EncryptedMessage), GNUNET_NO); dmc.kx = kx; dmc.peer = &kx->peer; if (GNUNET_OK != GNUNET_SERVER_mst_receive (mst, &dmc, &buf[sizeof (struct EncryptedMessage)], size - sizeof (struct EncryptedMessage), GNUNET_YES, GNUNET_NO)) GNUNET_break_op (0); } /** * Deliver P2P message to interested clients. * Invokes send twice, once for clients that want the full message, and once * for clients that only want the header * * @param cls always NULL * @param client who sent us the message (struct GSC_KeyExchangeInfo) * @param m the message */ static int deliver_message (void *cls, void *client, const struct GNUNET_MessageHeader *m) { struct DeliverMessageContext *dmc = client; if (KX_STATE_UP != dmc->kx->status) { GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# PAYLOAD dropped (out of order)"), 1, GNUNET_NO); return GNUNET_OK; } switch (ntohs (m->type)) { case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP: case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP: GSC_SESSIONS_set_typemap (dmc->peer, m); return GNUNET_OK; default: GSC_CLIENTS_deliver_message (dmc->peer, m, ntohs (m->size), GNUNET_CORE_OPTION_SEND_FULL_INBOUND); GSC_CLIENTS_deliver_message (dmc->peer, m, sizeof (struct GNUNET_MessageHeader), GNUNET_CORE_OPTION_SEND_HDR_INBOUND); } return GNUNET_OK; } /** * Setup the message that links the ephemeral key to our persistent * public key and generate the appropriate signature. */ static void sign_ephemeral_key () { current_ekm.header.size = htons (sizeof (struct EphemeralKeyMessage)); current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY); current_ekm.sender_status = 0; /* to be set later */ current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY); current_ekm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + sizeof (struct GNUNET_PeerIdentity)); current_ekm.creation_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (GSC_cfg, "core", "USE_EPHEMERAL_KEYS")) { current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_add (REKEY_FREQUENCY, REKEY_TOLERANCE))); } else { current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS); } GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key, ¤t_ekm.ephemeral_key); current_ekm.origin_identity = GSC_my_identity; GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (my_private_key, ¤t_ekm.purpose, ¤t_ekm.signature)); } /** * Task run to trigger rekeying. * * @param cls closure, NULL * @param tc scheduler context */ static void do_rekey (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GSC_KeyExchangeInfo *pos; rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL); if (NULL != my_ephemeral_key) GNUNET_free (my_ephemeral_key); my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create (); GNUNET_assert (NULL != my_ephemeral_key); sign_ephemeral_key (); for (pos = kx_head; NULL != pos; pos = pos->next) { if (KX_STATE_UP == pos->status) { pos->status = KX_STATE_REKEY_SENT; derive_session_keys (pos); } if (KX_STATE_DOWN == pos->status) { pos->status = KX_STATE_KEY_SENT; } send_key (pos); } } /** * Initialize KX subsystem. * * @param pk private key to use for the peer * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk) { my_private_key = pk; GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &GSC_my_identity.public_key); my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create (); if (NULL == my_ephemeral_key) { GNUNET_break (0); GNUNET_free (my_private_key); my_private_key = NULL; return GNUNET_SYSERR; } sign_ephemeral_key (); rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL); mst = GNUNET_SERVER_mst_create (&deliver_message, NULL); return GNUNET_OK; } /** * Shutdown KX subsystem. */ void GSC_KX_done () { if (GNUNET_SCHEDULER_NO_TASK != rekey_task) { GNUNET_SCHEDULER_cancel (rekey_task); rekey_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != my_ephemeral_key) { GNUNET_free (my_ephemeral_key); my_ephemeral_key = NULL; } if (NULL != my_private_key) { GNUNET_free (my_private_key); my_private_key = NULL; } if (NULL != mst) { GNUNET_SERVER_mst_destroy (mst); mst = NULL; } } /* end of gnunet-service-core_kx.c */ gnunet-0.10.1/src/core/gnunet-core.c0000644000175000017500000001505512316473376014145 00000000000000/* This file is part of GNUnet. (C) 2011, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-core.c * @brief Print information about other known _connected_ peers. * @author Nathan Evans */ #include "platform.h" #include "gnunet_crypto_lib.h" #include "gnunet_configuration_lib.h" #include "gnunet_getopt_lib.h" #include "gnunet_peerinfo_service.h" #include "gnunet_transport_service.h" #include "gnunet_core_service.h" #include "gnunet_program_lib.h" /** * Option -m. */ static int monitor_connections; /** * Current number of connections in monitor mode */ static int monitor_connections_counter; static struct GNUNET_CORE_Handle *ch; static struct GNUNET_PeerIdentity my_id; /** * Task run in monitor mode when the user presses CTRL-C to abort. * Stops monitoring activity. * * @param cls the 'struct GNUNET_TRANSPORT_PeerIterateContext *' * @param tc scheduler context */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != ch) { GNUNET_CORE_disconnect (ch); ch = NULL; } } /** * Callback for retrieving a list of connected peers. * * @param cls closure (unused) * @param peer peer identity this notification is about */ static void connected_peer_callback (void *cls, const struct GNUNET_PeerIdentity *peer) { if (NULL == peer) return; printf (_("Peer `%s'\n"), GNUNET_i2s_full (peer)); } static void monitor_notify_startup (void *cls, const struct GNUNET_PeerIdentity *my_identity) { my_id = (*my_identity); } /** * Function called to notify core users that another * peer connected to us. * * @param cls closure * @param peer the peer that connected */ static void monitor_notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); const char *now_str; if (0 != memcmp (&my_id, peer, sizeof (my_id))) { monitor_connections_counter ++; now_str = GNUNET_STRINGS_absolute_time_to_string (now); FPRINTF (stdout, _("%24s: %-17s %4s (%u connections in total)\n"), now_str, _("Connected to"), GNUNET_i2s (peer), monitor_connections_counter); } } /** * Function called to notify core users that another * peer disconnected from us. * * @param cls closure * @param peer the peer that disconnected */ static void monitor_notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); const char *now_str; if (0 != memcmp (&my_id, peer, sizeof (my_id))) { now_str = GNUNET_STRINGS_absolute_time_to_string (now); GNUNET_assert (monitor_connections_counter > 0); monitor_connections_counter--; FPRINTF (stdout, _("%24s: %-17s %4s (%u connections in total)\n"), now_str, _("Disconnected from"), GNUNET_i2s (peer), monitor_connections_counter); } } /** * Function called with the result of the check if the 'transport' * service is running. * * @param cls closure with our configuration * @param result #GNUNET_YES if transport is running */ static void testservice_task (void *cls, int result) { const struct GNUNET_CONFIGURATION_Handle *cfg = cls; static const struct GNUNET_CORE_MessageHandler handlers[] = { {NULL, 0, 0} }; if (result != GNUNET_OK) { FPRINTF (stderr, _("Service `%s' is not running\n"), "core"); return; } if (GNUNET_NO == monitor_connections) { if (GNUNET_OK != GNUNET_CORE_iterate_peers (cfg, &connected_peer_callback, NULL)) { fprintf (stderr, ("Failed to connect to CORE service to iterate peers!\n")); return; } } else { memset(&my_id, '\0', sizeof (my_id)); ch = GNUNET_CORE_connect (cfg, NULL, monitor_notify_startup, monitor_notify_connect, monitor_notify_disconnect, NULL, GNUNET_NO, NULL, GNUNET_NO, handlers); if (NULL == ch) { GNUNET_SCHEDULER_add_now (shutdown_task, NULL); fprintf (stderr, ("Failed to connect to CORE service!\n")); return; } else GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, shutdown_task, NULL); } } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { if (args[0] != NULL) { FPRINTF (stderr, _("Invalid command line argument `%s'\n"), args[0]); return; } GNUNET_CLIENT_service_test ("core", cfg, GNUNET_TIME_UNIT_SECONDS, &testservice_task, (void *) cfg); } /** * The main function to obtain peer information. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { int res; static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'m', "monitor", NULL, gettext_noop ("provide information about all current connections (continuously)"), 0, &GNUNET_GETOPT_set_one, &monitor_connections}, GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; res = GNUNET_PROGRAM_run (argc, argv, "gnunet-core", gettext_noop ("Print information about connected peers."), options, &run, NULL); GNUNET_free ((void *) argv); if (GNUNET_OK == res) return 0; else return 1; } /* end of gnunet-core.c */ gnunet-0.10.1/src/core/test_core_quota_peer1.conf0000644000175000017500000000225012225230043016664 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core-quota-sym-peer-1/ [transport-tcp] PORT = 12468 [arm] PORT = 12476 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-arm.sock [statistics] PORT = 12477 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-statistics.sock [resolver] PORT = 12474 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-resolver.sock [peerinfo] PORT = 12479 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-peerinfo.sock [transport] PORT = 12475 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-transport.sock [ats] PORT = 12471 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-ats.sock # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 10240 UNSPECIFIED_QUOTA_OUT = 10240 # LOOPBACK LOOPBACK_QUOTA_IN = 10240 LOOPBACK_QUOTA_OUT = 10240 # LAN LAN_QUOTA_IN = 10240 LAN_QUOTA_OUT = 10240 # WAN WAN_QUOTA_IN = 10240 WAN_QUOTA_OUT = 10240 # WLAN WLAN_QUOTA_IN = 10240 WLAN_QUOTA_OUT = 10240 [core] PORT = 12480 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-core.sock [ats] PORT = 12481 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-ats.sock [transport-udp] PORT = 12482 gnunet-0.10.1/src/core/gnunet-service-core_typemap.c0000644000175000017500000001561512255010512017321 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_typemap.c * @brief management of map that specifies which message types this peer supports * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" #include "gnunet-service-core.h" #include "gnunet-service-core_sessions.h" #include "gnunet-service-core_typemap.h" #include /** * A type map describing which messages a given neighbour is able * to process. */ struct GSC_TypeMap { uint32_t bits[(UINT16_MAX + 1) / 32]; }; /** * Bitmap of message types this peer is able to handle. */ static struct GSC_TypeMap my_type_map; /** * Counters for message types this peer is able to handle. */ static uint8_t map_counters[UINT16_MAX + 1]; /** * Compute a type map message for this peer. * * @return this peers current type map message. */ struct GNUNET_MessageHeader * GSC_TYPEMAP_compute_type_map_message () { char *tmp; uLongf dlen; struct GNUNET_MessageHeader *hdr; #ifdef compressBound dlen = compressBound (sizeof (my_type_map)); #else dlen = sizeof (my_type_map) + (sizeof (my_type_map) / 100) + 20; /* documentation says 100.1% oldSize + 12 bytes, but we * should be able to overshoot by more to be safe */ #endif hdr = GNUNET_malloc (dlen + sizeof (struct GNUNET_MessageHeader)); tmp = (char *) &hdr[1]; if ((Z_OK != compress2 ((Bytef *) tmp, &dlen, (const Bytef *) &my_type_map, sizeof (my_type_map), 9)) || (dlen >= sizeof (my_type_map))) { dlen = sizeof (my_type_map); memcpy (tmp, &my_type_map, sizeof (my_type_map)); hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP); } else { hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP); } hdr->size = htons ((uint16_t) dlen + sizeof (struct GNUNET_MessageHeader)); return hdr; } /** * Extract a type map from a TYPE_MAP message. * * @param msg a type map message * @return NULL on error */ struct GSC_TypeMap * GSC_TYPEMAP_get_from_message (const struct GNUNET_MessageHeader *msg) { struct GSC_TypeMap *ret; uint16_t size; uLongf dlen; size = ntohs (msg->size); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# type maps received"), 1, GNUNET_NO); if (size != sizeof (struct GSC_TypeMap)) { GNUNET_break_op (0); return NULL; } ret = GNUNET_new (struct GSC_TypeMap); memcpy (ret, &msg[1], sizeof (struct GSC_TypeMap)); return ret; case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP: GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# type maps received"), 1, GNUNET_NO); ret = GNUNET_new (struct GSC_TypeMap); dlen = sizeof (struct GSC_TypeMap); if ((Z_OK != uncompress ((Bytef *) ret, &dlen, (const Bytef *) &msg[1], (uLong) size)) || (dlen != sizeof (struct GSC_TypeMap))) { GNUNET_break_op (0); GNUNET_free (ret); return NULL; } return ret; default: GNUNET_break (0); return NULL; } } /** * Send my type map to all connected peers (it got changed). */ static void broadcast_my_type_map () { struct GNUNET_MessageHeader *hdr; hdr = GSC_TYPEMAP_compute_type_map_message (); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# updates to my type map"), 1, GNUNET_NO); GSC_SESSIONS_broadcast (hdr); GNUNET_free (hdr); } /** * Add a set of types to our type map. */ void GSC_TYPEMAP_add (const uint16_t * types, unsigned int tlen) { unsigned int i; int changed; changed = GNUNET_NO; for (i = 0; i < tlen; i++) { if (0 == map_counters[types[i]]++) { my_type_map.bits[types[i] / 32] |= (1 << (types[i] % 32)); changed = GNUNET_YES; } } if (GNUNET_YES == changed) broadcast_my_type_map (); } /** * Remove a set of types from our type map. */ void GSC_TYPEMAP_remove (const uint16_t * types, unsigned int tlen) { unsigned int i; int changed; changed = GNUNET_NO; for (i = 0; i < tlen; i++) { if (0 == --map_counters[types[i]]) { my_type_map.bits[types[i] / 32] &= ~(1 << (types[i] % 32)); changed = GNUNET_YES; } } if (GNUNET_YES == changed) broadcast_my_type_map (); } /** * Test if any of the types from the types array is in the * given type map. * * @param tmap map to test * @param types array of types * @param tcnt number of entries in types * @return GNUNET_YES if a type is in the map, GNUNET_NO if not */ int GSC_TYPEMAP_test_match (const struct GSC_TypeMap *tmap, const uint16_t * types, unsigned int tcnt) { unsigned int i; if (NULL == tmap) return GNUNET_NO; if (0 == tcnt) return GNUNET_YES; /* matches all */ for (i = 0; i < tcnt; i++) if (0 != (tmap->bits[types[i] / 32] & (1 << (types[i] % 32)))) return GNUNET_YES; return GNUNET_NO; } /** * Add additional types to a given typemap. * * @param tmap map to extend (not changed) * @param types array of types to add * @param tcnt number of entries in types * @return updated type map (fresh copy) */ struct GSC_TypeMap * GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap, const uint16_t * types, unsigned int tcnt) { struct GSC_TypeMap *ret; unsigned int i; ret = GNUNET_new (struct GSC_TypeMap); if (NULL != tmap) memcpy (ret, tmap, sizeof (struct GSC_TypeMap)); for (i = 0; i < tcnt; i++) ret->bits[types[i] / 32] |= (1 << (types[i] % 32)); return ret; } /** * Create an empty type map. * * @return an empty type map */ struct GSC_TypeMap * GSC_TYPEMAP_create () { return GNUNET_new (struct GSC_TypeMap); } /** * Free the given type map. * * @param tmap a type map */ void GSC_TYPEMAP_destroy (struct GSC_TypeMap *tmap) { GNUNET_free (tmap); } /** * Initialize typemap subsystem. */ void GSC_TYPEMAP_init () { /* nothing to do */ } /** * Shutdown typemap subsystem. */ void GSC_TYPEMAP_done () { /* nothing to do */ } /* end of gnunet-service-core_typemap.c */ gnunet-0.10.1/src/core/test_core_api_start_only.c0000644000175000017500000001400612301361474016775 00000000000000/* This file is part of GNUnet. (C) 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file transport/test_core_api_start_only.c * @brief testcase for core_api.c that only starts two peers, * connects to the core service and shuts down again */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_core_service.h" #include "gnunet_getopt_lib.h" #include "gnunet_os_lib.h" #include "gnunet_program_lib.h" #include "gnunet_scheduler_lib.h" #define TIMEOUT 5 #define MTYPE 12345 struct PeerContext { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CORE_Handle *ch; struct GNUNET_PeerIdentity id; struct GNUNET_OS_Process *arm_proc; }; static struct PeerContext p1; static struct PeerContext p2; static GNUNET_SCHEDULER_TaskIdentifier timeout_task_id; static int ok; #if VERBOSE #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { } static void disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { } static int inbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { return GNUNET_OK; } static int outbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { return GNUNET_OK; } static struct GNUNET_CORE_MessageHandler handlers[] = { {NULL, 0, 0} }; static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_CORE_disconnect (p1.ch); p1.ch = NULL; GNUNET_CORE_disconnect (p2.ch); p2.ch = NULL; ok = 0; } static void init_notify (void *cls, const struct GNUNET_PeerIdentity *my_identity) { struct PeerContext *p = cls; if (p == &p1) { /* connect p2 */ p2.ch = GNUNET_CORE_connect (p2.cfg, &p2, &init_notify, &connect_notify, &disconnect_notify, &inbound_notify, GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); } else { GNUNET_assert (p == &p2); GNUNET_SCHEDULER_cancel (timeout_task_id); GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); } } static void setup_peer (struct PeerContext *p, const char *cfgname) { char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); p->cfg = GNUNET_CONFIGURATION_create (); p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-arm", "-c", cfgname, NULL); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); GNUNET_free (binary); } static void timeout_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { FPRINTF (stderr, "%s", "Timeout.\n"); if (p1.ch != NULL) { GNUNET_CORE_disconnect (p1.ch); p1.ch = NULL; } if (p2.ch != NULL) { GNUNET_CORE_disconnect (p2.ch); p2.ch = NULL; } ok = 42; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_assert (ok == 1); OKPP; setup_peer (&p1, "test_core_api_peer1.conf"); setup_peer (&p2, "test_core_api_peer2.conf"); timeout_task_id = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, TIMEOUT), &timeout_task, NULL); p1.ch = GNUNET_CORE_connect (p1.cfg, &p1, &init_notify, &connect_notify, &disconnect_notify, &inbound_notify, GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); } static void stop_arm (struct PeerContext *p) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peer\n"); if (0 != GNUNET_OS_process_kill (p->arm_proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; GNUNET_CONFIGURATION_destroy (p->cfg); } static int check () { char *const argv[] = { "test-core-api-start-only", "-c", "test_core_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-2"); ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-core-api-start-only", "nohelp", options, &run, &ok); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test finished\n"); stop_arm (&p1); stop_arm (&p2); return ok; } int main (int argc, char *argv[]) { int ret; GNUNET_log_setup ("test-core-api-start-only", "WARNING", NULL); ret = check (); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-2"); return ret; } /* end of test_core_api_start_only.c */ gnunet-0.10.1/src/core/gnunet-service-core_kx.h0000644000175000017500000000700212320463642016271 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_kx.h * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other peers * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_CORE_KX_H #define GNUNET_SERVICE_CORE_KX_H #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" /** * Information about the status of a key exchange with another peer. */ struct GSC_KeyExchangeInfo; /** * We received a EPHEMERAL_KEY message. Validate and update * our key material and status. * * @param kx key exchange status for the corresponding peer * @param msg the set key message we received */ void GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg); /** * We received a PING message. Validate and transmit * a PONG message. * * @param kx key exchange status for the corresponding peer * @param msg the encrypted PING message itself */ void GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg); /** * We received a PONG message. Validate and update our status. * * @param kx key exchange status for the corresponding peer * @param msg the encrypted PONG message itself */ void GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg); /** * Encrypt and transmit a message with the given payload. * * @param kx key exchange context * @param payload payload of the message * @param payload_size number of bytes in 'payload' */ void GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, const void *payload, size_t payload_size); /** * We received an encrypted message. Decrypt, validate and * pass on to the appropriate clients. * * @param kx key exchange information context * @param msg encrypted message */ void GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, const struct GNUNET_MessageHeader *msg); /** * Start the key exchange with the given peer. * * @param pid identity of the peer to do a key exchange with * @return key exchange information context */ struct GSC_KeyExchangeInfo * GSC_KX_start (const struct GNUNET_PeerIdentity *pid); /** * Stop key exchange with the given peer. Clean up key material. * * @param kx key exchange to stop */ void GSC_KX_stop (struct GSC_KeyExchangeInfo *kx); /** * Initialize KX subsystem. * * @param pk private key to use for the peer * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ int GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk); /** * Shutdown KX subsystem. */ void GSC_KX_done (void); #endif /* end of gnunet-service-core_kx.h */ gnunet-0.10.1/src/core/test_core_api_data.conf0000644000175000017500000000032512225230043016202 00000000000000@INLINE@ test_core_defaults.conf [PATHS] [arm] DEFAULTSERVICES = topology hostlist [ats] WAN_QUOTA_IN = 64 kiB WAN_QUOTA_OUT = 64 kiB [core] PORT = 2092 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-core.sock gnunet-0.10.1/src/core/test_core_quota_asymmetric_send_limit_peer1.conf0000644000175000017500000000220312225230043023326 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core-quota-asym-send-lim-peer-1/ [transport-tcp] PORT = 12488 [transport-udp] PORT = 12492 [arm] PORT = 12486 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-arm.sock [statistics] PORT = 12487 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-statistics.sock [resolver] PORT = 12484 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-1-service-resolver.sock [peerinfo] PORT = 12489 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-peerinfo.sock [transport] PORT = 12485 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-transport.sock [ats] PORT = 12491 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-ats.sock # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 10240 UNSPECIFIED_QUOTA_OUT = 10240 # LOOPBACK LOOPBACK_QUOTA_IN = 10240 LOOPBACK_QUOTA_OUT = 10240 # LAN LAN_QUOTA_IN = 10240 LAN_QUOTA_OUT = 10240 # WAN WAN_QUOTA_IN = 10240 WAN_QUOTA_OUT = 10240 # WLAN WLAN_QUOTA_IN = 10240 WLAN_QUOTA_OUT = 10240 [core] PORT = 12490 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-core.sock gnunet-0.10.1/src/core/test_core_quota_asymmetric_send_limit_peer2.conf0000644000175000017500000000244112225230043023333 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core-quota-asym-send-lim-peer-2/ [arm] PORT = 22486 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-arm.sock [statistics] PORT = 22487 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-statistics.sock [resolver] PORT = 22484 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-resolver.sock [peerinfo] PORT = 22489 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-peerinfo.sock [transport] PORT = 22485 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-transport.sock [core] PORT = 22490 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-core.sock [ats] PORT = 22491 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-ats.sock WAN_QUOTA_IN = 1 MB WAN_QUOTA_OUT = 1 MB [ats] PORT = 12471 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-ats.sock # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 1 MB UNSPECIFIED_QUOTA_OUT = 1 MB # LOOPBACK LOOPBACK_QUOTA_IN = 1 MB LOOPBACK_QUOTA_OUT = 1 MB # LAN LAN_QUOTA_IN = 1 MB LAN_QUOTA_OUT = 1 MB # WAN WAN_QUOTA_IN = 1 MB WAN_QUOTA_OUT = 1 MB # WLAN WLAN_QUOTA_IN = 1 MB WLAN_QUOTA_OUT = 1 MB [transport-tcp] PORT = 22467 [transport-udp] PORT = 22468 [transport-http] PORT = 22469 gnunet-0.10.1/src/core/Makefile.am0000644000175000017500000001121512320751517013570 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ core.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif lib_LTLIBRARIES = \ libgnunetcore.la libgnunetcore_la_SOURCES = \ core_api.c core.h \ core_api_iterate_peers.c libgnunetcore_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) libgnunetcore_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:1:0 libexec_PROGRAMS = \ gnunet-service-core bin_PROGRAMS = \ gnunet-core gnunet_service_core_SOURCES = \ gnunet-service-core.c gnunet-service-core.h \ gnunet-service-core_clients.c gnunet-service-core_clients.h \ gnunet-service-core_neighbours.c gnunet-service-core_neighbours.h \ gnunet-service-core_kx.c gnunet-service-core_kx.h \ gnunet-service-core_sessions.c gnunet-service-core_sessions.h \ gnunet-service-core_typemap.c gnunet-service-core_typemap.h gnunet_service_core_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(Z_LIBS) gnunet_core_SOURCES = \ gnunet-core.c gnunet_core_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_core_DEPENDENCIES = \ libgnunetcore.la if HAVE_TESTING TESTING_TESTS = test_core_api_send_to_self test_core_api_mq endif check_PROGRAMS = \ test_core_api_start_only \ test_core_api \ test_core_api_reliability \ test_core_quota_compliance_symmetric \ test_core_quota_compliance_asymmetric_send_limited \ test_core_quota_compliance_asymmetric_recv_limited \ $(TESTING_TESTS) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_core_api_SOURCES = \ test_core_api.c test_core_api_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_api_reliability_SOURCES = \ test_core_api_reliability.c test_core_api_reliability_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_api_send_to_self_SOURCES = \ test_core_api_send_to_self.c test_core_api_send_to_self_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_api_mq_SOURCES = \ test_core_api_mq.c test_core_api_mq_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_api_start_only_SOURCES = \ test_core_api_start_only.c test_core_api_start_only_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/util/libgnunetutil.la test_core_quota_compliance_symmetric_SOURCES = \ test_core_quota_compliance.c test_core_quota_compliance_symmetric_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_core_quota_compliance_asymmetric_send_limited_SOURCES = \ test_core_quota_compliance.c test_core_quota_compliance_asymmetric_send_limited_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la test_core_quota_compliance_asymmetric_recv_limited_SOURCES = \ test_core_quota_compliance.c test_core_quota_compliance_asymmetric_recv_limited_LDADD = \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la EXTRA_DIST = \ test_core_defaults.conf \ test_core_api_data.conf \ test_core_api_peer1.conf \ test_core_api_peer2.conf \ test_core_api_send_to_self.conf \ test_core_quota_asymmetric_recv_limited_peer1.conf \ test_core_quota_asymmetric_recv_limited_peer2.conf \ test_core_quota_asymmetric_send_limit_peer1.conf \ test_core_quota_asymmetric_send_limit_peer2.conf \ test_core_quota_peer1.conf \ test_core_quota_peer2.conf gnunet-0.10.1/src/core/test_core_api.c0000644000175000017500000002513112301361474014520 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/test_core_api.c * @brief testcase for core_api.c */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_core_service.h" #include "gnunet_getopt_lib.h" #include "gnunet_os_lib.h" #include "gnunet_program_lib.h" #include "gnunet_scheduler_lib.h" #include "gnunet_transport_service.h" #define MTYPE 12345 struct PeerContext { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CORE_Handle *ch; struct GNUNET_PeerIdentity id; struct GNUNET_TRANSPORT_Handle *th; struct GNUNET_TRANSPORT_GetHelloHandle *ghh; struct GNUNET_MessageHeader *hello; int connect_status; struct GNUNET_OS_Process *arm_proc; }; static struct PeerContext p1; static struct PeerContext p2; static GNUNET_SCHEDULER_TaskIdentifier err_task; static GNUNET_SCHEDULER_TaskIdentifier con_task; static int ok; #define OKPP do { ok++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) static void process_hello (void *cls, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received (my) `%s' from transport service\n", "HELLO"); GNUNET_assert (message != NULL); if ((p == &p1) && (p2.th != NULL)) GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL); if ((p == &p2) && (p1.th != NULL)) GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL); } static void terminate_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_assert (ok == 6); GNUNET_CORE_disconnect (p1.ch); p1.ch = NULL; GNUNET_CORE_disconnect (p2.ch); p2.ch = NULL; GNUNET_TRANSPORT_get_hello_cancel (p1.ghh); p1.ghh = NULL; GNUNET_TRANSPORT_get_hello_cancel (p2.ghh); p2.ghh = NULL; GNUNET_TRANSPORT_disconnect (p1.th); p1.th = NULL; GNUNET_TRANSPORT_disconnect (p2.th); p2.th = NULL; if (GNUNET_SCHEDULER_NO_TASK != con_task) { GNUNET_SCHEDULER_cancel (con_task); con_task = GNUNET_SCHEDULER_NO_TASK; } ok = 0; } static void terminate_task_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ENDING ANGRILY %u\n", ok); GNUNET_break (0); if (NULL != p1.ch) { GNUNET_CORE_disconnect (p1.ch); p1.ch = NULL; } if (NULL != p2.ch) { GNUNET_CORE_disconnect (p2.ch); p2.ch = NULL; } if (p1.th != NULL) { GNUNET_TRANSPORT_get_hello_cancel (p1.ghh); GNUNET_TRANSPORT_disconnect (p1.th); p1.th = NULL; } if (p2.th != NULL) { GNUNET_TRANSPORT_get_hello_cancel (p2.ghh); GNUNET_TRANSPORT_disconnect (p2.th); p2.th = NULL; } if (GNUNET_SCHEDULER_NO_TASK != con_task) { GNUNET_SCHEDULER_cancel (con_task); con_task = GNUNET_SCHEDULER_NO_TASK; } ok = 42; } static size_t transmit_ready (void *cls, size_t size, void *buf) { struct PeerContext *p = cls; struct GNUNET_MessageHeader *m; GNUNET_assert (ok == 4); OKPP; GNUNET_assert (p == &p1); GNUNET_assert (buf != NULL); m = (struct GNUNET_MessageHeader *) buf; m->type = htons (MTYPE); m->size = htons (sizeof (struct GNUNET_MessageHeader)); return sizeof (struct GNUNET_MessageHeader); } static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *pc = cls; if (0 == memcmp (&pc->id, peer, sizeof (struct GNUNET_PeerIdentity))) return; GNUNET_assert (pc->connect_status == 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted connection established to peer `%4s'\n", GNUNET_i2s (peer)); if (GNUNET_SCHEDULER_NO_TASK != con_task) { GNUNET_SCHEDULER_cancel (con_task); con_task = GNUNET_SCHEDULER_NO_TASK; } pc->connect_status = 1; if (pc == &p1) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking core (1) for transmission to peer `%4s'\n", GNUNET_i2s (&p2.id)); if (NULL == GNUNET_CORE_notify_transmit_ready (p1.ch, GNUNET_YES, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 145), &p2.id, sizeof (struct GNUNET_MessageHeader), &transmit_ready, &p1)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n", GNUNET_i2s (&p2.id)); } } } static void disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *pc = cls; if (0 == memcmp (&pc->id, peer, sizeof (struct GNUNET_PeerIdentity))) return; pc->connect_status = 0; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer)); } static int inbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core provides inbound data from `%4s'.\n", GNUNET_i2s (other)); return GNUNET_OK; } static int outbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core notifies about outbound data for `%4s'.\n", GNUNET_i2s (other)); return GNUNET_OK; } static int process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message from `%4s'.\n", GNUNET_i2s (peer)); GNUNET_assert (ok == 5); OKPP; GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_now (&terminate_task, NULL); return GNUNET_OK; } static struct GNUNET_CORE_MessageHandler handlers[] = { {&process_mtype, MTYPE, sizeof (struct GNUNET_MessageHeader)}, {NULL, 0, 0} }; static void connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { con_task = GNUNET_SCHEDULER_NO_TASK; return; } con_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &connect_task, NULL); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking transport (1) to connect to peer `%4s'\n", GNUNET_i2s (&p2.id)); GNUNET_TRANSPORT_try_connect (p1.th, &p2.id, NULL, NULL); /*FIXME TRY_CONNECT change */ } static void init_notify (void *cls, const struct GNUNET_PeerIdentity *my_identity) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core connection to `%4s' established\n", GNUNET_i2s (my_identity)); p->id = *my_identity; if (cls == &p1) { GNUNET_assert (ok == 2); OKPP; /* connect p2 */ p2.ch = GNUNET_CORE_connect (p2.cfg, &p2, &init_notify, &connect_notify, &disconnect_notify, &inbound_notify, GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); } else { GNUNET_assert (ok == 3); OKPP; GNUNET_assert (cls == &p2); con_task = GNUNET_SCHEDULER_add_now (&connect_task, NULL); } } static void setup_peer (struct PeerContext *p, const char *cfgname) { char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); p->cfg = GNUNET_CONFIGURATION_create (); p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-arm", "-c", cfgname, NULL); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, NULL, NULL, NULL); GNUNET_assert (p->th != NULL); p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &process_hello, p); GNUNET_free (binary); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_assert (ok == 1); OKPP; setup_peer (&p1, "test_core_api_peer1.conf"); setup_peer (&p2, "test_core_api_peer2.conf"); err_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300), &terminate_task_error, NULL); p1.ch = GNUNET_CORE_connect (p1.cfg, &p1, &init_notify, &connect_notify, &disconnect_notify, &inbound_notify, GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); } static void stop_arm (struct PeerContext *p) { if (0 != GNUNET_OS_process_kill (p->arm_proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; GNUNET_CONFIGURATION_destroy (p->cfg); } int main (int argc, char *argv1[]) { char *const argv[] = { "test-core-api", "-c", "test_core_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; ok = 1; GNUNET_log_setup ("test-core-api", "WARNING", NULL); GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-core-api", "nohelp", options, &run, &ok); stop_arm (&p1); stop_arm (&p2); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-1"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-2"); return ok; } /* end of test_core_api.c */ gnunet-0.10.1/src/core/test_core_quota_asymmetric_recv_limited_peer1.conf0000644000175000017500000000220312225230043023645 00000000000000@INLINE@ test_core_defaults.conf [PATHS] GNUNET_TEST_HOME = /tmp/test-gnunet-core-quota-asym-recv-lim-peer-1/ [transport-tcp] PORT = 12488 [arm] PORT = 12486 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-arm.sock [statistics] PORT = 12487 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-statistics.sock [resolver] PORT = 12484 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-1-service-resolver.sock [peerinfo] PORT = 12489 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-peerinfo.sock [transport] PORT = 12485 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-transport.sock [transport-udp] PORT = 12489 [ats] PORT = 12491 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-ats.sock # UNSPECIFIED UNSPECIFIED_QUOTA_IN = 1 MB UNSPECIFIED_QUOTA_OUT = 1 MB # LOOPBACK LOOPBACK_QUOTA_IN = 1 MB LOOPBACK_QUOTA_OUT = 1 MB # LAN LAN_QUOTA_IN = 1 MB LAN_QUOTA_OUT = 1 MB # WAN WAN_QUOTA_IN = 1 MB WAN_QUOTA_OUT = 1 MB # WLAN WLAN_QUOTA_IN = 1 MB WLAN_QUOTA_OUT = 1 MB [core] PORT = 12490 UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-core.sock gnunet-0.10.1/src/core/gnunet-service-core_sessions.h0000644000175000017500000001161012276375236017530 00000000000000/* This file is part of GNUnet. (C) 2009-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_neighbours.h * @brief code for managing of 'encrypted' sessions (key exchange done) * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_CORE_SESSIONS_H #define GNUNET_SERVICE_CORE_SESSIONS_H #include "gnunet-service-core.h" #include "gnunet-service-core_kx.h" /** * Create a session, a key exchange was just completed. * * @param peer peer that is now connected * @param kx key exchange that completed */ void GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer, struct GSC_KeyExchangeInfo *kx); /** * End the session with the given peer (we are no longer * connected). * * @param pid identity of peer to kill session with */ void GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid); /** * Traffic is being solicited for the given peer. This means that the * message queue on the transport-level (NEIGHBOURS subsystem) is now * empty and it is now OK to transmit another (non-control) message. * * @param pid identity of peer ready to receive data */ void GSC_SESSIONS_solicit (const struct GNUNET_PeerIdentity *pid); /** * Queue a request from a client for transmission to a particular peer. * * @param car request to queue; this handle is then shared between * the caller (CLIENTS subsystem) and SESSIONS and must not * be released by either until either 'GNUNET_SESSIONS_dequeue', * or 'GNUNET_CLIENTS_failed' * have been invoked on it */ void GSC_SESSIONS_queue_request (struct GSC_ClientActiveRequest *car); /** * Dequeue a request from a client from transmission to a particular peer. * * @param car request to dequeue; this handle will then be 'owned' by * the caller (CLIENTS sysbsystem) */ void GSC_SESSIONS_dequeue_request (struct GSC_ClientActiveRequest *car); /** * Transmit a message to a particular peer. * * @param car original request that was queued and then solicited, * ownership does not change (dequeue will be called soon). * @param msg message to transmit * @param cork is corking allowed? * @param priority how important is this message */ void GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car, const struct GNUNET_MessageHeader *msg, int cork, enum GNUNET_CORE_Priority priority); /** * Broadcast a message to all neighbours. * * @param msg message to transmit */ void GSC_SESSIONS_broadcast (const struct GNUNET_MessageHeader *msg); /** * We have a new client, notify it about all current sessions. * * @param client the new client */ void GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client); /** * We've received a typemap message from a peer, update ours. * Notifies clients about the session. * * @param peer peer this is about * @param msg typemap update message */ void GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg); /** * The given peer send a message of the specified type. Make sure the * respective bit is set in its type-map and that clients are notified * about the session. * * @param peer peer this is about * @param type type of the message */ void GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer, uint16_t type); /** * Handle CORE_ITERATE_PEERS request. For this request type, the client * does not have to have transmitted an INIT request. All current peers * are returned, regardless of which message types they accept. * * @param cls unused * @param client client sending the iteration request * @param message iteration request message */ void GSC_SESSIONS_handle_client_iterate_peers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message); /** * Initialize sessions subsystem. */ void GSC_SESSIONS_init (void); /** * Shutdown sessions subsystem. */ void GSC_SESSIONS_done (void); #endif gnunet-0.10.1/src/core/gnunet-service-core_sessions.c0000644000175000017500000006301512320464254017516 00000000000000/* This file is part of GNUnet. (C) 2009-2014 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_sessions.c * @brief code for managing of 'encrypted' sessions (key exchange done) * @author Christian Grothoff */ #include "platform.h" #include "gnunet-service-core.h" #include "gnunet-service-core_neighbours.h" #include "gnunet-service-core_kx.h" #include "gnunet-service-core_typemap.h" #include "gnunet-service-core_sessions.h" #include "gnunet-service-core_clients.h" #include "gnunet_constants.h" #include "core.h" /** * How often do we transmit our typemap? */ #define TYPEMAP_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) /** * How often do we transmit our typemap on first attempt? */ #define TYPEMAP_FREQUENCY_FIRST GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * Message ready for encryption. This struct is followed by the * actual content of the message. */ struct SessionMessageEntry { /** * We keep messages in a doubly linked list. */ struct SessionMessageEntry *next; /** * We keep messages in a doubly linked list. */ struct SessionMessageEntry *prev; /** * Deadline for transmission, 1s after we received it (if we * are not corking), otherwise "now". Note that this message * does NOT expire past its deadline. */ struct GNUNET_TIME_Absolute deadline; /** * How long is the message? (number of bytes following the "struct * MessageEntry", but not including the size of "struct * MessageEntry" itself!) */ size_t size; /** * How important is this message. */ enum GNUNET_CORE_Priority priority; }; /** * Data kept per session. */ struct Session { /** * Identity of the other peer. */ struct GNUNET_PeerIdentity peer; /** * Head of list of requests from clients for transmission to * this peer. */ struct GSC_ClientActiveRequest *active_client_request_head; /** * Tail of list of requests from clients for transmission to * this peer. */ struct GSC_ClientActiveRequest *active_client_request_tail; /** * Head of list of messages ready for encryption. */ struct SessionMessageEntry *sme_head; /** * Tail of list of messages ready for encryption. */ struct SessionMessageEntry *sme_tail; /** * Information about the key exchange with the other peer. */ struct GSC_KeyExchangeInfo *kxinfo; /** * Current type map for this peer. */ struct GSC_TypeMap *tmap; /** * Task to transmit corked messages with a delay. */ GNUNET_SCHEDULER_TaskIdentifier cork_task; /** * Task to transmit our type map. */ GNUNET_SCHEDULER_TaskIdentifier typemap_task; /** * Is the neighbour queue empty and thus ready for us * to transmit an encrypted message? */ int ready_to_transmit; /** * Is this the first time we're sending the typemap? If so, * we want to send it a bit faster the second time. 0 if * we are sending for the first time, 1 if not. */ int first_typemap; }; /** * Map of peer identities to `struct Session`. */ static struct GNUNET_CONTAINER_MultiPeerMap *sessions; /** * Find the session for the given peer. * * @param peer identity of the peer * @return NULL if we are not connected, otherwise the * session handle */ static struct Session * find_session (const struct GNUNET_PeerIdentity *peer) { return GNUNET_CONTAINER_multipeermap_get (sessions, peer); } /** * End the session with the given peer (we are no longer * connected). * * @param pid identity of peer to kill session with */ void GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid) { struct Session *session; struct GSC_ClientActiveRequest *car; struct SessionMessageEntry *sme; session = find_session (pid); if (NULL == session) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Destroying session for peer `%4s'\n", GNUNET_i2s (&session->peer)); if (GNUNET_SCHEDULER_NO_TASK != session->cork_task) { GNUNET_SCHEDULER_cancel (session->cork_task); session->cork_task = GNUNET_SCHEDULER_NO_TASK; } while (NULL != (car = session->active_client_request_head)) { GNUNET_CONTAINER_DLL_remove (session->active_client_request_head, session->active_client_request_tail, car); GSC_CLIENTS_reject_request (car); } while (NULL != (sme = session->sme_head)) { GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme); GNUNET_free (sme); } GNUNET_SCHEDULER_cancel (session->typemap_task); GSC_CLIENTS_notify_clients_about_neighbour (&session->peer, session->tmap, NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (sessions, &session->peer, session)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"), GNUNET_CONTAINER_multipeermap_size (sessions), GNUNET_NO); GSC_TYPEMAP_destroy (session->tmap); session->tmap = NULL; GNUNET_free (session); } /** * Transmit our current typemap message to the other peer. * (Done periodically in case an update got lost). * * @param cls the `struct Session *` * @param tc unused */ static void transmit_typemap_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *session = cls; struct GNUNET_MessageHeader *hdr; struct GNUNET_TIME_Relative delay; if (0 == session->first_typemap) { delay = TYPEMAP_FREQUENCY_FIRST; session->first_typemap = 1; } else { delay = TYPEMAP_FREQUENCY; } /* randomize a bit to avoid spont. sync */ delay.rel_value_us += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000 * 1000); session->typemap_task = GNUNET_SCHEDULER_add_delayed (delay, &transmit_typemap_task, session); GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# type map refreshes sent"), 1, GNUNET_NO); hdr = GSC_TYPEMAP_compute_type_map_message (); GSC_KX_encrypt_and_transmit (session->kxinfo, hdr, ntohs (hdr->size)); GNUNET_free (hdr); } /** * Create a session, a key exchange was just completed. * * @param peer peer that is now connected * @param kx key exchange that completed */ void GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer, struct GSC_KeyExchangeInfo *kx) { struct Session *session; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating session for peer `%4s'\n", GNUNET_i2s (peer)); session = GNUNET_new (struct Session); session->tmap = GSC_TYPEMAP_create (); session->peer = *peer; session->kxinfo = kx; session->typemap_task = GNUNET_SCHEDULER_add_now (&transmit_typemap_task, session); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (sessions, peer, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); GNUNET_STATISTICS_set (GSC_stats, gettext_noop ("# peers connected"), GNUNET_CONTAINER_multipeermap_size (sessions), GNUNET_NO); GSC_CLIENTS_notify_clients_about_neighbour (peer, NULL, session->tmap); } /** * Notify the given client about the session (client is new). * * @param cls the `struct GSC_Client` * @param key peer identity * @param value the `struct Session` * @return #GNUNET_OK (continue to iterate) */ static int notify_client_about_session (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GSC_Client *client = cls; struct Session *session = value; GSC_CLIENTS_notify_client_about_neighbour (client, &session->peer, NULL, /* old TMAP: none */ session->tmap); return GNUNET_OK; } /** * We have a new client, notify it about all current sessions. * * @param client the new client */ void GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client) { /* notify new client about existing sessions */ GNUNET_CONTAINER_multipeermap_iterate (sessions, ¬ify_client_about_session, client); } /** * Try to perform a transmission on the given session. Will solicit * additional messages if the 'sme' queue is not full enough. * * @param session session to transmit messages from */ static void try_transmission (struct Session *session); /** * Queue a request from a client for transmission to a particular peer. * * @param car request to queue; this handle is then shared between * the caller (CLIENTS subsystem) and SESSIONS and must not * be released by either until either #GSC_SESSIONS_dequeue(), * #GSC_SESSIONS_transmit() or #GSC_CLIENTS_failed() * have been invoked on it */ void GSC_SESSIONS_queue_request (struct GSC_ClientActiveRequest *car) { struct Session *session; session = find_session (&car->target); if (NULL == session) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Dropped client request for transmission (am disconnected)\n"); GNUNET_break (0); /* should have been rejected earlier */ GSC_CLIENTS_reject_request (car); return; } if (car->msize > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); GSC_CLIENTS_reject_request (car); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received client transmission request. queueing\n"); GNUNET_CONTAINER_DLL_insert (session->active_client_request_head, session->active_client_request_tail, car); try_transmission (session); } /** * Dequeue a request from a client from transmission to a particular peer. * * @param car request to dequeue; this handle will then be 'owned' by * the caller (CLIENTS sysbsystem) */ void GSC_SESSIONS_dequeue_request (struct GSC_ClientActiveRequest *car) { struct Session *s; if (0 == memcmp (&car->target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) return; s = find_session (&car->target); GNUNET_assert (NULL != s); GNUNET_CONTAINER_DLL_remove (s->active_client_request_head, s->active_client_request_tail, car); } /** * Discard all expired active transmission requests from clients. * * @param session session to clean up */ static void discard_expired_requests (struct Session *session) { struct GSC_ClientActiveRequest *pos; struct GSC_ClientActiveRequest *nxt; struct GNUNET_TIME_Absolute now; now = GNUNET_TIME_absolute_get (); pos = NULL; nxt = session->active_client_request_head; while (NULL != nxt) { pos = nxt; nxt = pos->next; if ((pos->deadline.abs_value_us < now.abs_value_us) && (GNUNET_YES != pos->was_solicited)) { GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# messages discarded (expired prior to transmission)"), 1, GNUNET_NO); GNUNET_CONTAINER_DLL_remove (session->active_client_request_head, session->active_client_request_tail, pos); GSC_CLIENTS_reject_request (pos); } } } /** * Solicit messages for transmission, starting with those of the highest * priority. * * @param session session to solict messages for * @param msize how many bytes do we have already */ static void solicit_messages (struct Session *session, size_t msize) { struct GSC_ClientActiveRequest *car; struct GSC_ClientActiveRequest *nxt; size_t so_size; enum GNUNET_CORE_Priority pmax; discard_expired_requests (session); so_size = msize; pmax = GNUNET_CORE_PRIO_BACKGROUND; for (car = session->active_client_request_head; NULL != car; car = car->next) { if (GNUNET_YES == car->was_solicited) continue; pmax = GNUNET_MAX (pmax, car->priority); } nxt = session->active_client_request_head; while (NULL != (car = nxt)) { nxt = car->next; if (car->priority < pmax) continue; if (so_size + car->msize > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) break; so_size += car->msize; if (GNUNET_YES == car->was_solicited) continue; car->was_solicited = GNUNET_YES; GSC_CLIENTS_solicit_request (car); } } /** * Some messages were delayed (corked), but the timeout has now expired. * Send them now. * * @param cls `struct Session` with the messages to transmit now * @param tc scheduler context (unused) */ static void pop_cork_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct Session *session = cls; session->cork_task = GNUNET_SCHEDULER_NO_TASK; try_transmission (session); } /** * Try to perform a transmission on the given session. Will solicit * additional messages if the 'sme' queue is not full enough or has * only low-priority messages. * * @param session session to transmit messages from */ static void try_transmission (struct Session *session) { struct SessionMessageEntry *pos; size_t msize; struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute min_deadline; enum GNUNET_CORE_Priority maxp; enum GNUNET_CORE_Priority maxpc; struct GSC_ClientActiveRequest *car; int excess; if (GNUNET_YES != session->ready_to_transmit) return; msize = 0; min_deadline = GNUNET_TIME_UNIT_FOREVER_ABS; /* if the peer has excess bandwidth, background traffic is allowed, otherwise not */ excess = GSC_NEIGHBOURS_check_excess_bandwidth (&session->peer); if (GNUNET_YES == excess) maxp = GNUNET_CORE_PRIO_BACKGROUND; else maxp = GNUNET_CORE_PRIO_BEST_EFFORT; /* determine highest priority of 'ready' messages we already solicited from clients */ pos = session->sme_head; while ((NULL != pos) && (msize + pos->size <= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)) { GNUNET_assert (pos->size < GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE); msize += pos->size; maxp = GNUNET_MAX (maxp, pos->priority); min_deadline = GNUNET_TIME_absolute_min (min_deadline, pos->deadline); pos = pos->next; } if (maxp < GNUNET_CORE_PRIO_CRITICAL_CONTROL) { /* if highest already solicited priority from clients is not critical, check if there are higher-priority messages to be solicited from clients */ if (GNUNET_YES == excess) maxpc = GNUNET_CORE_PRIO_BACKGROUND; else maxpc = GNUNET_CORE_PRIO_BEST_EFFORT; for (car = session->active_client_request_head; NULL != car; car = car->next) { if (GNUNET_YES == car->was_solicited) continue; maxpc = GNUNET_MAX (maxpc, car->priority); } if (maxpc > maxp) { /* we have messages waiting for solicitation that have a higher priority than those that we already accepted; solicit the high-priority messages first */ solicit_messages (session, 0); return; } } now = GNUNET_TIME_absolute_get (); if ( ( (GNUNET_YES == excess) || (maxpc >= GNUNET_CORE_PRIO_BEST_EFFORT) ) && ( (0 == msize) || ( (msize < GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / 2) && (min_deadline.abs_value_us > now.abs_value_us))) ) { /* not enough ready yet (tiny message & cork possible), or no messages at all, and either excess bandwidth or best-effort or higher message waiting at client; in this case, we try to solicit more */ solicit_messages (session, msize); if (msize > 0) { /* if there is data to send, just not yet, make sure we do transmit * it once the deadline is reached */ if (GNUNET_SCHEDULER_NO_TASK != session->cork_task) GNUNET_SCHEDULER_cancel (session->cork_task); session->cork_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (min_deadline), &pop_cork_task, session); } return; } /* create plaintext buffer of all messages (that fit), encrypt and transmit */ { static unsigned long long total_bytes; static unsigned int total_msgs; char pbuf[msize]; /* plaintext */ size_t used; used = 0; while ((NULL != (pos = session->sme_head)) && (used + pos->size <= msize)) { memcpy (&pbuf[used], &pos[1], pos->size); used += pos->size; GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, pos); GNUNET_free (pos); } /* compute average payload size */ total_bytes += used; total_msgs++; if (0 == total_msgs) { /* 2^32 messages, wrap around... */ total_msgs = 1; total_bytes = used; } GNUNET_STATISTICS_set (GSC_stats, "# avg payload per encrypted message", total_bytes / total_msgs, GNUNET_NO); /* now actually transmit... */ session->ready_to_transmit = GNUNET_NO; GSC_KX_encrypt_and_transmit (session->kxinfo, pbuf, used); } } /** * Send a message to the neighbour now. * * @param cls the message * @param key neighbour's identity * @param value `struct Neighbour` of the target * @return always #GNUNET_OK */ static int do_send_message (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { const struct GNUNET_MessageHeader *hdr = cls; struct Session *session = value; struct SessionMessageEntry *m; uint16_t size; size = ntohs (hdr->size); m = GNUNET_malloc (sizeof (struct SessionMessageEntry) + size); memcpy (&m[1], hdr, size); m->size = size; m->priority = GNUNET_CORE_PRIO_CRITICAL_CONTROL; GNUNET_CONTAINER_DLL_insert_tail (session->sme_head, session->sme_tail, m); try_transmission (session); return GNUNET_OK; } /** * Broadcast a message to all neighbours. * * @param msg message to transmit */ void GSC_SESSIONS_broadcast (const struct GNUNET_MessageHeader *msg) { if (NULL == sessions) return; GNUNET_CONTAINER_multipeermap_iterate (sessions, &do_send_message, (void *) msg); } /** * Traffic is being solicited for the given peer. This means that the * message queue on the transport-level (NEIGHBOURS subsystem) is now * empty and it is now OK to transmit another (non-control) message. * * @param pid identity of peer ready to receive data */ void GSC_SESSIONS_solicit (const struct GNUNET_PeerIdentity *pid) { struct Session *session; session = find_session (pid); if (NULL == session) return; session->ready_to_transmit = GNUNET_YES; try_transmission (session); } /** * Transmit a message to a particular peer. * * @param car original request that was queued and then solicited; * this handle will now be 'owned' by the SESSIONS subsystem * @param msg message to transmit * @param cork is corking allowed? * @param priority how important is this message */ void GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car, const struct GNUNET_MessageHeader *msg, int cork, enum GNUNET_CORE_Priority priority) { struct Session *session; struct SessionMessageEntry *sme; struct SessionMessageEntry *pos; size_t msize; session = find_session (&car->target); if (NULL == session) return; msize = ntohs (msg->size); sme = GNUNET_malloc (sizeof (struct SessionMessageEntry) + msize); memcpy (&sme[1], msg, msize); sme->size = msize; sme->priority = priority; if (GNUNET_YES == cork) sme->deadline = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY); pos = session->sme_head; while ( (NULL != pos) && (pos->priority > sme->priority) ) pos = pos->next; if (NULL == pos) GNUNET_CONTAINER_DLL_insert_tail (session->sme_head, session->sme_tail, sme); else GNUNET_CONTAINER_DLL_insert_after (session->sme_head, session->sme_tail, pos->prev, sme); try_transmission (session); } /** * Helper function for #GSC_SESSIONS_handle_client_iterate_peers(). * * @param cls the `struct GNUNET_SERVER_TransmitContext` to queue replies * @param key identity of the connected peer * @param value the `struct Neighbour` for the peer * @return #GNUNET_OK (continue to iterate) */ static int queue_connect_message (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_SERVER_TransmitContext *tc = cls; struct Session *session = value; struct ConnectNotifyMessage cnm; /* FIXME: code duplication with clients... */ cnm.header.size = htons (sizeof (struct ConnectNotifyMessage)); cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); cnm.reserved = htonl (0); cnm.peer = session->peer; GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header); return GNUNET_OK; } /** * Handle CORE_ITERATE_PEERS request. For this request type, the client * does not have to have transmitted an INIT request. All current peers * are returned, regardless of which message types they accept. * * @param cls unused * @param client client sending the iteration request * @param message iteration request message */ void GSC_SESSIONS_handle_client_iterate_peers (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_MessageHeader done_msg; struct GNUNET_SERVER_TransmitContext *tc; tc = GNUNET_SERVER_transmit_context_create (client); GNUNET_CONTAINER_multipeermap_iterate (sessions, &queue_connect_message, tc); done_msg.size = htons (sizeof (struct GNUNET_MessageHeader)); done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END); GNUNET_SERVER_transmit_context_append_message (tc, &done_msg); GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); } /** * We've received a typemap message from a peer, update ours. * Notifies clients about the session. * * @param peer peer this is about * @param msg typemap update message */ void GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *msg) { struct Session *session; struct GSC_TypeMap *nmap; nmap = GSC_TYPEMAP_get_from_message (msg); if (NULL == nmap) return; /* malformed */ session = find_session (peer); if (NULL == session) { GNUNET_break (0); return; } GSC_CLIENTS_notify_clients_about_neighbour (peer, session->tmap, nmap); GSC_TYPEMAP_destroy (session->tmap); session->tmap = nmap; } /** * The given peer send a message of the specified type. Make sure the * respective bit is set in its type-map and that clients are notified * about the session. * * @param peer peer this is about * @param type type of the message */ void GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer, uint16_t type) { struct Session *session; struct GSC_TypeMap *nmap; if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) return; session = find_session (peer); GNUNET_assert (NULL != session); if (GNUNET_YES == GSC_TYPEMAP_test_match (session->tmap, &type, 1)) return; /* already in it */ nmap = GSC_TYPEMAP_extend (session->tmap, &type, 1); GSC_CLIENTS_notify_clients_about_neighbour (peer, session->tmap, nmap); GSC_TYPEMAP_destroy (session->tmap); session->tmap = nmap; } /** * Initialize sessions subsystem. */ void GSC_SESSIONS_init () { sessions = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); } /** * Helper function for GSC_SESSIONS_handle_client_iterate_peers. * * @param cls NULL * @param key identity of the connected peer * @param value the `struct Session` for the peer * @return #GNUNET_OK (continue to iterate) */ static int free_session_helper (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct Session *session = value; GSC_SESSIONS_end (&session->peer); return GNUNET_OK; } /** * Shutdown sessions subsystem. */ void GSC_SESSIONS_done () { if (NULL != sessions) { GNUNET_CONTAINER_multipeermap_iterate (sessions, &free_session_helper, NULL); GNUNET_CONTAINER_multipeermap_destroy (sessions); sessions = NULL; } } /* end of gnunet-service-core_sessions.c */ gnunet-0.10.1/src/core/gnunet-service-core.h0000644000175000017500000000476312272514213015577 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core.h * @brief Globals for gnunet-service-core * @author Christian Grothoff */ #ifndef GNUNET_SERVICE_CORE_H #define GNUNET_SERVICE_CORE_H #include "gnunet_statistics_service.h" #include "gnunet_core_service.h" #include "core.h" /** * Opaque handle to a client. */ struct GSC_Client; /** * Record kept for each request for transmission issued by a * client that is still pending. (This struct is used by * both the 'CLIENTS' and 'SESSIONS' subsystems.) */ struct GSC_ClientActiveRequest { /** * Active requests are kept in a doubly-linked list of * the respective target peer. */ struct GSC_ClientActiveRequest *next; /** * Active requests are kept in a doubly-linked list of * the respective target peer. */ struct GSC_ClientActiveRequest *prev; /** * Which peer is the message going to be for? */ struct GNUNET_PeerIdentity target; /** * Handle to the client. */ struct GSC_Client *client_handle; /** * By what time would the client want to see this message out? */ struct GNUNET_TIME_Absolute deadline; /** * How important is this request. */ enum GNUNET_CORE_Priority priority; /** * Has this request been solicited yet? */ int was_solicited; /** * How many bytes does the client intend to send? */ uint16_t msize; /** * Unique request ID (in big endian). */ uint16_t smr_id; }; /** * Our configuration. */ extern const struct GNUNET_CONFIGURATION_Handle *GSC_cfg; /** * For creating statistics. */ extern struct GNUNET_STATISTICS_Handle *GSC_stats; /** * Our identity. */ extern struct GNUNET_PeerIdentity GSC_my_identity; #endif gnunet-0.10.1/src/core/test_core_quota_compliance.c0000644000175000017500000005763412301361474017307 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/test_core_quota_compliance.c * @brief testcase for core_api.c focusing quota compliance on core level */ #include "platform.h" #include "gnunet_arm_service.h" #include "gnunet_core_service.h" #include "gnunet_getopt_lib.h" #include "gnunet_os_lib.h" #include "gnunet_program_lib.h" #include "gnunet_scheduler_lib.h" #include "gnunet_transport_service.h" #include "gnunet_statistics_service.h" #define SYMMETRIC 0 #define ASYMMETRIC_SEND_LIMITED 1 #define ASYMMETRIC_RECV_LIMITED 2 /** * Note that this value must not significantly exceed * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise * messages may be dropped even for a reliable transport. */ #define TOTAL_MSGS (60000 * 10) /** * How long until we give up on transmitting the message? */ #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) /** * What delay do we request from the core service for transmission? */ #define FAST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 150) #define MTYPE 12345 #define MESSAGESIZE 1024 #define MEASUREMENT_LENGTH GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) static unsigned long long total_bytes_sent; static unsigned long long total_bytes_recv; static struct GNUNET_TIME_Absolute start_time; static GNUNET_SCHEDULER_TaskIdentifier err_task; static GNUNET_SCHEDULER_TaskIdentifier measure_task; static GNUNET_SCHEDULER_TaskIdentifier connect_task; struct PeerContext { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CORE_Handle *ch; struct GNUNET_CORE_TransmitHandle *nth; struct GNUNET_PeerIdentity id; struct GNUNET_TRANSPORT_Handle *th; struct GNUNET_MessageHeader *hello; struct GNUNET_STATISTICS_Handle *stats; struct GNUNET_TRANSPORT_GetHelloHandle *ghh; int connect_status; struct GNUNET_OS_Process *arm_proc; }; static struct PeerContext p1; static struct PeerContext p2; static unsigned long long current_quota_p1_in; static unsigned long long current_quota_p1_out; static unsigned long long current_quota_p2_in; static unsigned long long current_quota_p2_out; static int ok; static int test; static int32_t tr_n; static int running; #if VERBOSE #define OKPP do { ok++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0) #else #define OKPP do { ok++; } while (0) #endif struct TestMessage { struct GNUNET_MessageHeader header; uint32_t num; }; static void process_hello (void *cls, const struct GNUNET_MessageHeader *message); static void terminate_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CORE_Handle *ch; err_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_STATISTICS_destroy (p1.stats, GNUNET_NO); GNUNET_STATISTICS_destroy (p2.stats, GNUNET_NO); GNUNET_TRANSPORT_get_hello_cancel (p2.ghh); GNUNET_TRANSPORT_get_hello_cancel (p1.ghh); if (p1.nth != NULL) { GNUNET_CORE_notify_transmit_ready_cancel (p1.nth); p1.nth = NULL; } if (connect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (connect_task); connect_task = GNUNET_SCHEDULER_NO_TASK; } ch = p1.ch; p1.ch = NULL; GNUNET_CORE_disconnect (ch); ch = p2.ch; p2.ch = NULL; GNUNET_CORE_disconnect (ch); GNUNET_TRANSPORT_disconnect (p1.th); p1.th = NULL; GNUNET_TRANSPORT_disconnect (p2.th); p2.th = NULL; GNUNET_free_non_null (p1.hello); GNUNET_free_non_null (p2.hello); } static void terminate_task_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { err_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Testcase failed!\n"); //GNUNET_break (0); if (p1.nth != NULL) { GNUNET_CORE_notify_transmit_ready_cancel (p1.nth); p1.nth = NULL; } if (measure_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (measure_task); if (connect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (connect_task); connect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_TRANSPORT_get_hello_cancel (p1.ghh); GNUNET_TRANSPORT_get_hello_cancel (p2.ghh); if (NULL != p1.ch) GNUNET_CORE_disconnect (p1.ch); p1.ch = NULL; if (NULL != p2.ch) GNUNET_CORE_disconnect (p2.ch); p2.ch = NULL; if (NULL != p1.th) GNUNET_TRANSPORT_disconnect (p1.th); p1.th = NULL; if (NULL != p2.th) GNUNET_TRANSPORT_disconnect (p2.th); p2.th = NULL; ok = 42; } static void try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { connect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &try_connect, NULL); GNUNET_TRANSPORT_try_connect (p1.th, &p2.id, NULL, NULL); /*FIXME TRY_CONNECT change */ GNUNET_TRANSPORT_try_connect (p2.th, &p1.id, NULL, NULL); /*FIXME TRY_CONNECT change */ } /** * Callback function to process statistic values. * * @param cls closure * @param subsystem name of subsystem that created the statistic * @param name the name of the datum * @param value the current value * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration */ static int print_stat (void *cls, const char *subsystem, const char *name, uint64_t value, int is_persistent) { if (cls == &p1) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer1 %50s = %12llu\n", name, (unsigned long long) value); if (cls == &p2) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer2 %50s = %12llu\n", name, (unsigned long long) value); return GNUNET_OK; } static void measurement_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned long long delta; unsigned long long throughput_out; unsigned long long throughput_in; unsigned long long max_quota_in; unsigned long long max_quota_out; unsigned long long quota_delta; enum GNUNET_ErrorType kind = GNUNET_ERROR_TYPE_DEBUG; measure_task = GNUNET_SCHEDULER_NO_TASK; FPRINTF (stdout, "%s", "\n"); running = GNUNET_NO; delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us; throughput_out = total_bytes_sent * 1000000LL / delta; /* convert to bytes/s */ throughput_in = total_bytes_recv * 1000000LL / delta; /* convert to bytes/s */ max_quota_in = GNUNET_MIN (current_quota_p1_in, current_quota_p2_in); max_quota_out = GNUNET_MIN (current_quota_p1_out, current_quota_p2_out); if (max_quota_out < max_quota_in) quota_delta = max_quota_in / 3; else quota_delta = max_quota_out / 3; if ((throughput_out > (max_quota_out + quota_delta)) || (throughput_in > (max_quota_in + quota_delta))) ok = 1; /* fail */ else ok = 0; /* pass */ GNUNET_STATISTICS_get (p1.stats, "core", "# discarded CORE_SEND requests", GNUNET_TIME_UNIT_FOREVER_REL, NULL, &print_stat, &p1); GNUNET_STATISTICS_get (p1.stats, "core", "# discarded CORE_SEND request bytes", GNUNET_TIME_UNIT_FOREVER_REL, NULL, &print_stat, &p1); GNUNET_STATISTICS_get (p1.stats, "core", "# discarded lower priority CORE_SEND requests", GNUNET_TIME_UNIT_FOREVER_REL, NULL, &print_stat, NULL); GNUNET_STATISTICS_get (p1.stats, "core", "# discarded lower priority CORE_SEND request bytes", GNUNET_TIME_UNIT_FOREVER_REL, NULL, &print_stat, &p1); GNUNET_STATISTICS_get (p2.stats, "core", "# discarded CORE_SEND requests", GNUNET_TIME_UNIT_FOREVER_REL, NULL, &print_stat, &p2); GNUNET_STATISTICS_get (p2.stats, "core", "# discarded CORE_SEND request bytes", GNUNET_TIME_UNIT_FOREVER_REL, NULL, &print_stat, &p2); GNUNET_STATISTICS_get (p2.stats, "core", "# discarded lower priority CORE_SEND requests", GNUNET_TIME_UNIT_FOREVER_REL, NULL, &print_stat, &p2); GNUNET_STATISTICS_get (p2.stats, "core", "# discarded lower priority CORE_SEND request bytes", GNUNET_TIME_UNIT_FOREVER_REL, NULL, &print_stat, &p2); if (ok != 0) kind = GNUNET_ERROR_TYPE_ERROR; switch (test) { case SYMMETRIC: GNUNET_log (kind, "Core quota compliance test with symmetric quotas: %s\n", (0 == ok) ? "PASSED" : "FAILED"); break; case ASYMMETRIC_SEND_LIMITED: GNUNET_log (kind, "Core quota compliance test with limited sender quota: %s\n", (0 == ok) ? "PASSED" : "FAILED"); break; case ASYMMETRIC_RECV_LIMITED: GNUNET_log (kind, "Core quota compliance test with limited receiver quota: %s\n", (0 == ok) ? "PASSED" : "FAILED"); break; }; GNUNET_log (kind, "Peer 1 send rate: %llu b/s (%llu bytes in %llu ms)\n", throughput_out, total_bytes_sent, delta); GNUNET_log (kind, "Peer 1 send quota: %llu b/s\n", current_quota_p1_out); GNUNET_log (kind, "Peer 2 receive rate: %llu b/s (%llu bytes in %llu ms)\n", throughput_in, total_bytes_recv, delta); GNUNET_log (kind, "Peer 2 receive quota: %llu b/s\n", current_quota_p2_in); /* GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Max. inbound quota allowed: %llu b/s\n",max_quota_in ); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Max. outbound quota allowed: %llu b/s\n",max_quota_out); */ GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_now (&terminate_task, NULL); } static size_t transmit_ready (void *cls, size_t size, void *buf) { char *cbuf = buf; struct TestMessage hdr; unsigned int ret; p1.nth = NULL; GNUNET_assert (size <= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE); if (buf == NULL) { if ((p1.ch != NULL) && (p1.connect_status == 1)) GNUNET_break (NULL != (p1.nth = GNUNET_CORE_notify_transmit_ready (p1.ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, FAST_TIMEOUT, &p2.id, MESSAGESIZE, &transmit_ready, &p1))); return 0; } GNUNET_assert (tr_n < TOTAL_MSGS); ret = 0; GNUNET_assert (size >= MESSAGESIZE); GNUNET_assert (buf != NULL); cbuf = buf; do { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message %u of size %u at offset %u\n", tr_n, MESSAGESIZE, ret); hdr.header.size = htons (MESSAGESIZE); hdr.header.type = htons (MTYPE); hdr.num = htonl (tr_n); memcpy (&cbuf[ret], &hdr, sizeof (struct TestMessage)); ret += sizeof (struct TestMessage); memset (&cbuf[ret], tr_n, MESSAGESIZE - sizeof (struct TestMessage)); ret += MESSAGESIZE - sizeof (struct TestMessage); tr_n++; if (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 16)) break; /* sometimes pack buffer full, sometimes not */ } while (size - ret >= MESSAGESIZE); GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &terminate_task_error, NULL); total_bytes_sent += ret; return ret; } static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *pc = cls; if (0 == memcmp (&pc->id, peer, sizeof (struct GNUNET_PeerIdentity))) return; /* loopback */ GNUNET_assert (pc->connect_status == 0); pc->connect_status = 1; if (pc == &p1) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted connection established to peer `%4s'\n", GNUNET_i2s (peer)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking core (1) for transmission to peer `%4s'\n", GNUNET_i2s (&p2.id)); if (err_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &terminate_task_error, NULL); start_time = GNUNET_TIME_absolute_get (); running = GNUNET_YES; measure_task = GNUNET_SCHEDULER_add_delayed (MEASUREMENT_LENGTH, &measurement_stop, NULL); GNUNET_break (NULL != (p1.nth = GNUNET_CORE_notify_transmit_ready (p1.ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, TIMEOUT, &p2.id, MESSAGESIZE, &transmit_ready, &p1))); } } static void disconnect_notify (void *cls, const struct GNUNET_PeerIdentity *peer) { struct PeerContext *pc = cls; if (0 == memcmp (&pc->id, peer, sizeof (struct GNUNET_PeerIdentity))) return; /* loopback */ pc->connect_status = 0; if (GNUNET_SCHEDULER_NO_TASK != measure_task) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Measurement aborted due to disconnect!\n"); GNUNET_SCHEDULER_cancel (measure_task); measure_task = GNUNET_SCHEDULER_NO_TASK; } if (pc->nth != NULL) { GNUNET_CORE_notify_transmit_ready_cancel (pc->nth); pc->nth = NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted connection to `%4s' cut\n", GNUNET_i2s (peer)); } static int inbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core provides inbound data from `%4s' %llu.\n", GNUNET_i2s (other), ntohs (message->size)); total_bytes_recv += ntohs (message->size); return GNUNET_OK; } static int outbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core notifies about outbound data for `%4s'.\n", GNUNET_i2s (other)); return GNUNET_OK; } static size_t transmit_ready (void *cls, size_t size, void *buf); static int process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { static int n; const struct TestMessage *hdr; hdr = (const struct TestMessage *) message; if (MTYPE != ntohs (message->type)) return GNUNET_SYSERR; if (ntohs (message->size) != MESSAGESIZE) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", n, MESSAGESIZE, ntohs (message->size), ntohl (hdr->num)); GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_now (&terminate_task_error, NULL); return GNUNET_SYSERR; } if (ntohl (hdr->num) != n) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected message %u of size %u, got %u bytes of message %u\n", n, MESSAGESIZE, ntohs (message->size), ntohl (hdr->num)); GNUNET_SCHEDULER_cancel (err_task); err_task = GNUNET_SCHEDULER_add_now (&terminate_task_error, NULL); return GNUNET_SYSERR; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got message %u of size %u\n", ntohl (hdr->num), ntohs (message->size)); n++; if (0 == (n % 10)) FPRINTF (stderr, "%s", "."); if (running == GNUNET_YES) GNUNET_break (NULL != GNUNET_CORE_notify_transmit_ready (p1.ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, FAST_TIMEOUT, &p2.id, MESSAGESIZE, &transmit_ready, &p1)); return GNUNET_OK; } static struct GNUNET_CORE_MessageHandler handlers[] = { {&process_mtype, MTYPE, 0}, {NULL, 0, 0} }; static void init_notify (void *cls, const struct GNUNET_PeerIdentity *my_identity) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection to CORE service of `%4s' established\n", GNUNET_i2s (my_identity)); GNUNET_assert (NULL != my_identity); p->id = *my_identity; if (cls == &p1) { GNUNET_assert (ok == 2); OKPP; /* connect p2 */ p2.ch = GNUNET_CORE_connect (p2.cfg, &p2, &init_notify, &connect_notify, &disconnect_notify, &inbound_notify, GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); } else { GNUNET_assert (ok == 3); OKPP; GNUNET_assert (cls == &p2); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asking core (1) to connect to peer `%4s'\n", GNUNET_i2s (&p2.id)); connect_task = GNUNET_SCHEDULER_add_now (&try_connect, NULL); } } static void process_hello (void *cls, const struct GNUNET_MessageHeader *message) { struct PeerContext *p = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received (my) `%s' from transport service\n", "HELLO"); GNUNET_assert (message != NULL); p->hello = GNUNET_malloc (ntohs (message->size)); memcpy (p->hello, message, ntohs (message->size)); if ((p == &p1) && (p2.th != NULL)) GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL); if ((p == &p2) && (p1.th != NULL)) GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL); if ((p == &p1) && (p2.hello != NULL)) GNUNET_TRANSPORT_offer_hello (p1.th, p2.hello, NULL, NULL); if ((p == &p2) && (p1.hello != NULL)) GNUNET_TRANSPORT_offer_hello (p2.th, p1.hello, NULL, NULL); } static void setup_peer (struct PeerContext *p, const char *cfgname) { char *binary; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm"); p->cfg = GNUNET_CONFIGURATION_create (); p->arm_proc = GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, NULL, binary, "gnunet-service-arm", "-c", cfgname, NULL); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname)); p->stats = GNUNET_STATISTICS_create ("core", p->cfg); GNUNET_assert (p->stats != NULL); p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, NULL, NULL, NULL); GNUNET_assert (p->th != NULL); p->ghh = GNUNET_TRANSPORT_get_hello (p->th, &process_hello, p); GNUNET_free (binary); } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { GNUNET_assert (ok == 1); OKPP; err_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &terminate_task_error, NULL); if (test == SYMMETRIC) { setup_peer (&p1, "test_core_quota_peer1.conf"); setup_peer (&p2, "test_core_quota_peer2.conf"); } else if (test == ASYMMETRIC_SEND_LIMITED) { setup_peer (&p1, "test_core_quota_asymmetric_send_limit_peer1.conf"); setup_peer (&p2, "test_core_quota_asymmetric_send_limit_peer2.conf"); } else if (test == ASYMMETRIC_RECV_LIMITED) { setup_peer (&p1, "test_core_quota_asymmetric_recv_limited_peer1.conf"); setup_peer (&p2, "test_core_quota_asymmetric_recv_limited_peer2.conf"); } GNUNET_assert (test != -1); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_size (p1.cfg, "ATS", "WAN_QUOTA_IN", ¤t_quota_p1_in)); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_size (p2.cfg, "ATS", "WAN_QUOTA_IN", ¤t_quota_p2_in)); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_size (p1.cfg, "ATS", "WAN_QUOTA_OUT", ¤t_quota_p1_out)); GNUNET_assert (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_size (p2.cfg, "ATS", "WAN_QUOTA_OUT", ¤t_quota_p2_out)); p1.ch = GNUNET_CORE_connect (p1.cfg, &p1, &init_notify, &connect_notify, &disconnect_notify, &inbound_notify, GNUNET_YES, &outbound_notify, GNUNET_YES, handlers); } static void stop_arm (struct PeerContext *p) { if (0 != GNUNET_OS_process_kill (p->arm_proc, GNUNET_TERM_SIG)) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); if (GNUNET_OS_process_wait (p->arm_proc) != GNUNET_OK) GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ARM process %u stopped\n", GNUNET_OS_process_get_pid (p->arm_proc)); GNUNET_OS_process_destroy (p->arm_proc); p->arm_proc = NULL; GNUNET_CONFIGURATION_destroy (p->cfg); } static int check () { char *const argv[] = { "test-core-quota-compliance", "-c", "test_core_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; ok = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test-core-quota-compliance", "nohelp", options, &run, &ok); stop_arm (&p1); stop_arm (&p2); return ok; } int main (int argc, char *argv[]) { int ret; test = -1; if (strstr (argv[0], "_symmetric") != NULL) { test = SYMMETRIC; } else if (strstr (argv[0], "_asymmetric_send") != NULL) { test = ASYMMETRIC_SEND_LIMITED; } else if (strstr (argv[0], "_asymmetric_recv") != NULL) { test = ASYMMETRIC_RECV_LIMITED; } GNUNET_assert (test != -1); if (test == SYMMETRIC) { GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-sym-peer-1/"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-sym-peer-2/"); } else if (test == ASYMMETRIC_SEND_LIMITED) { GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-asym-send-lim-peer-1/"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-asym-send-lim-peer-2/"); } else if (test == ASYMMETRIC_RECV_LIMITED) { GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-asym-recv-lim-peer-1/"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-asym-recv-lim-peer-2/"); } GNUNET_log_setup ("test-core-quota-compliance", "WARNING", NULL); ret = check (); if (test == SYMMETRIC) { GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-sym-peer-1/"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-sym-peer-2/"); } else if (test == ASYMMETRIC_SEND_LIMITED) { GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-asym-send-lim-peer-1/"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-asym-send-lim-peer-2/"); } else if (test == ASYMMETRIC_RECV_LIMITED) { GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-asym-recv-lim-peer-1/"); GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-asym-recv-lim-peer-2/"); } return ret; } /* end of test_core_quota_compliance.c */ gnunet-0.10.1/src/core/test_core_api_send_to_self.c0000644000175000017500000001134312225777502017254 00000000000000/* This file is part of GNUnet. (C) 2010 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/test_core_api_send_to_self.c * @brief * @author Philipp Toelke */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_protocols.h" #include "gnunet_core_service.h" #include "gnunet_constants.h" /** * Final status code. */ static int ret; /** * Handle to the cleanup task. */ GNUNET_SCHEDULER_TaskIdentifier die_task; /** * Identity of this peer. */ static struct GNUNET_PeerIdentity myself; /** * The handle to core */ struct GNUNET_CORE_Handle *core; /** * Function scheduled as very last function, cleans up after us */ static void cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tskctx) { die_task = GNUNET_SCHEDULER_NO_TASK; if (core != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting core.\n"); GNUNET_CORE_disconnect (core); core = NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); } static int receive (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { if (die_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (die_task); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message from peer %s\n", GNUNET_i2s (other)); GNUNET_assert (GNUNET_MESSAGE_TYPE_DUMMY == ntohs (message->type)); GNUNET_assert (0 == memcmp (other, &myself, sizeof (myself))); GNUNET_SCHEDULER_add_now (&cleanup, NULL); ret = 0; return GNUNET_OK; } static size_t send_message (void *cls, size_t size, void *buf) { if (size == 0 || buf == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not send; got 0 buffer\n"); return 0; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending!\n"); struct GNUNET_MessageHeader *hdr = buf; hdr->size = htons (sizeof (struct GNUNET_MessageHeader)); hdr->type = htons (GNUNET_MESSAGE_TYPE_DUMMY); return ntohs (hdr->size); } static void init (void *cls, const struct GNUNET_PeerIdentity *my_identity) { if (NULL == my_identity) { GNUNET_break (0); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Correctly connected to CORE; we are the peer %s.\n", GNUNET_i2s (my_identity)); memcpy (&myself, my_identity, sizeof (struct GNUNET_PeerIdentity)); } static void connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to peer %s.\n", GNUNET_i2s (peer)); if (0 == memcmp (peer, &myself, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to myself; sending message!\n"); GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 0, GNUNET_TIME_UNIT_FOREVER_REL, peer, sizeof (struct GNUNET_MessageHeader), send_message, NULL); } } /** * Main function that will be run by the scheduler. * * @param cls closure * @param cfg configuration */ static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { const static struct GNUNET_CORE_MessageHandler handlers[] = { {&receive, GNUNET_MESSAGE_TYPE_DUMMY, 0}, {NULL, 0, 0} }; core = GNUNET_CORE_connect (cfg, NULL, &init, &connect_cb, NULL, NULL, 0, NULL, 0, handlers); die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300), &cleanup, NULL); } /** * The main function to test sending a message to the local peer via core * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-core-api-send-to-self", "test_core_api_peer1.conf", &run, NULL)) return 1; return ret; } /* end of test_core_api_send_to_self.c */ gnunet-0.10.1/src/core/test_core_api_mq.c0000644000175000017500000000701512261236531015216 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_core_service.h" #define NUM_MSG 5 /** * Has the test been successful? */ int result; unsigned int num_received; struct GNUNET_CORE_Handle *core; struct GNUNET_MQ_Handle *mq; struct GNUNET_PeerIdentity myself; static void init_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity) { if (NULL == my_identity) { GNUNET_break (0); return; } myself = *my_identity; mq = GNUNET_CORE_mq_create (core, my_identity); } static void connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to peer %s.\n", GNUNET_i2s (peer)); if (0 == memcmp (peer, &myself, sizeof (struct GNUNET_PeerIdentity))) { unsigned int i; struct GNUNET_MQ_Envelope *ev; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing messages.\n"); for (i = 0; i < NUM_MSG; i++) { ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_TEST); GNUNET_MQ_send (mq, ev); } } } static int handle_test (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got test message %d\n", num_received); num_received++; if (NUM_MSG == num_received) { result = GNUNET_OK; GNUNET_SCHEDULER_shutdown (); return GNUNET_SYSERR; } if (num_received > NUM_MSG) { GNUNET_abort (); return GNUNET_SYSERR; } return GNUNET_OK; } static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n"); GNUNET_MQ_destroy (mq); GNUNET_CORE_disconnect (core); } /** * Initialize framework and start test * * @param cls Closure (unused). * @param cfg Configuration handle. * @param peer Testing peer handle. */ static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer) { static const struct GNUNET_CORE_MessageHandler handlers[] = { {&handle_test, GNUNET_MESSAGE_TYPE_TEST, 0}, {NULL, 0, 0} }; core = GNUNET_CORE_connect (cfg, NULL, &init_cb, &connect_cb, NULL, NULL, GNUNET_NO, NULL, GNUNET_NO, handlers); if (NULL == core) { GNUNET_abort (); return; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } int main (int argc, char *argv1[]) { if (0 != GNUNET_TESTING_peer_run ("test-core-api-mq", "test_core_api_peer1.conf", &run, NULL)) return 2; return (result == GNUNET_OK) ? 0 : 1; } gnunet-0.10.1/src/core/core_api.c0000644000175000017500000013056212272516003013463 00000000000000/* This file is part of GNUnet. (C) 2009, 2010 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/core_api.c * @brief core service; this is the main API for encrypted P2P * communications * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_core_service.h" #include "core.h" #define LOG(kind,...) GNUNET_log_from (kind, "core-api",__VA_ARGS__) /** * Handle for a transmission request. */ struct GNUNET_CORE_TransmitHandle { /** * Corresponding peer record. */ struct PeerRecord *peer; /** * Corresponding SEND_REQUEST message. Only non-NULL * while SEND_REQUEST message is pending. */ struct ControlMessage *cm; /** * Function that will be called to get the actual request * (once we are ready to transmit this request to the core). * The function will be called with a NULL buffer to signal * timeout. */ GNUNET_CONNECTION_TransmitReadyNotify get_message; /** * Closure for get_message. */ void *get_message_cls; /** * Timeout for this handle. */ struct GNUNET_TIME_Absolute timeout; /** * How important is this message? */ enum GNUNET_CORE_Priority priority; /** * Size of this request. */ uint16_t msize; /** * Send message request ID for this request. */ uint16_t smr_id; /** * Is corking allowed? */ int cork; }; /** * Information we track for each peer. */ struct PeerRecord { /** * We generally do NOT keep peer records in a DLL; this * DLL is only used IF this peer's 'pending_head' message * is ready for transmission. */ struct PeerRecord *prev; /** * We generally do NOT keep peer records in a DLL; this * DLL is only used IF this peer's 'pending_head' message * is ready for transmission. */ struct PeerRecord *next; /** * Peer the record is about. */ struct GNUNET_PeerIdentity peer; /** * Corresponding core handle. */ struct GNUNET_CORE_Handle *ch; /** * Pending request, if any. 'th->peer' is set to NULL if the * request is not active. */ struct GNUNET_CORE_TransmitHandle th; /** * ID of timeout task for the 'pending_head' handle * which is the one with the smallest timeout. */ GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** * ID of task to run 'next_request_transmission'. */ GNUNET_SCHEDULER_TaskIdentifier ntr_task; /** * SendMessageRequest ID generator for this peer. */ uint16_t smr_id_gen; }; struct CoreMQState { struct GNUNET_PeerIdentity target; struct GNUNET_CORE_Handle *core; struct GNUNET_CORE_TransmitHandle *th; }; /** * Type of function called upon completion. * * @param cls closure * @param success GNUNET_OK on success (which for request_connect * ONLY means that we transmitted the connect request to CORE, * it does not mean that we are actually now connected!); * GNUNET_NO on timeout, * GNUNET_SYSERR if core was shut down */ typedef void (*GNUNET_CORE_ControlContinuation) (void *cls, int success); /** * Entry in a doubly-linked list of control messages to be transmitted * to the core service. Control messages include traffic allocation, * connection requests and of course our initial 'init' request. * * The actual message is allocated at the end of this struct. */ struct ControlMessage { /** * This is a doubly-linked list. */ struct ControlMessage *next; /** * This is a doubly-linked list. */ struct ControlMessage *prev; /** * Function to run after transmission failed/succeeded. */ GNUNET_CORE_ControlContinuation cont; /** * Closure for 'cont'. */ void *cont_cls; /** * Transmit handle (if one is associated with this ControlMessage), or NULL. */ struct GNUNET_CORE_TransmitHandle *th; }; /** * Context for the core service connection. */ struct GNUNET_CORE_Handle { /** * Configuration we're using. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Closure for the various callbacks. */ void *cls; /** * Function to call once we've handshaked with the core service. */ GNUNET_CORE_StartupCallback init; /** * Function to call whenever we're notified about a peer connecting. */ GNUNET_CORE_ConnectEventHandler connects; /** * Function to call whenever we're notified about a peer disconnecting. */ GNUNET_CORE_DisconnectEventHandler disconnects; /** * Function to call whenever we receive an inbound message. */ GNUNET_CORE_MessageCallback inbound_notify; /** * Function to call whenever we receive an outbound message. */ GNUNET_CORE_MessageCallback outbound_notify; /** * Function handlers for messages of particular type. */ const struct GNUNET_CORE_MessageHandler *handlers; /** * Our connection to the service. */ struct GNUNET_CLIENT_Connection *client; /** * Handle for our current transmission request. */ struct GNUNET_CLIENT_TransmitHandle *cth; /** * Head of doubly-linked list of pending requests. */ struct ControlMessage *control_pending_head; /** * Tail of doubly-linked list of pending requests. */ struct ControlMessage *control_pending_tail; /** * Head of doubly-linked list of peers that are core-approved * to send their next message. */ struct PeerRecord *ready_peer_head; /** * Tail of doubly-linked list of peers that are core-approved * to send their next message. */ struct PeerRecord *ready_peer_tail; /** * Hash map listing all of the peers that we are currently * connected to. */ struct GNUNET_CONTAINER_MultiPeerMap *peers; /** * Identity of this peer. */ struct GNUNET_PeerIdentity me; /** * ID of reconnect task (if any). */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Current delay we use for re-trying to connect to core. */ struct GNUNET_TIME_Relative retry_backoff; /** * Number of entries in the handlers array. */ unsigned int hcnt; /** * For inbound notifications without a specific handler, do * we expect to only receive headers? */ int inbound_hdr_only; /** * For outbound notifications without a specific handler, do * we expect to only receive headers? */ int outbound_hdr_only; /** * Are we currently disconnected and hence unable to forward * requests? */ int currently_down; }; /** * Our current client connection went down. Clean it up * and try to reconnect! * * @param h our handle to the core service */ static void reconnect (struct GNUNET_CORE_Handle *h); /** * Task schedule to try to re-connect to core. * * @param cls the `struct GNUNET_CORE_Handle` * @param tc task context */ static void reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CORE_Handle *h = cls; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CORE service after delay\n"); reconnect (h); } /** * Notify clients about disconnect and free * the entry for connected peer. * * @param cls the `struct GNUNET_CORE_Handle *` * @param key the peer identity (not used) * @param value the `struct PeerRecord` to free. * @return #GNUNET_YES (continue) */ static int disconnect_and_free_peer_entry (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GNUNET_CORE_Handle *h = cls; struct GNUNET_CORE_TransmitHandle *th; struct PeerRecord *pr = value; if (GNUNET_SCHEDULER_NO_TASK != pr->timeout_task) { GNUNET_SCHEDULER_cancel (pr->timeout_task); pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != pr->ntr_task) { GNUNET_SCHEDULER_cancel (pr->ntr_task); pr->ntr_task = GNUNET_SCHEDULER_NO_TASK; } if ((NULL != pr->prev) || (NULL != pr->next) || (h->ready_peer_head == pr)) GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); if (NULL != h->disconnects) h->disconnects (h->cls, &pr->peer); /* all requests should have been cancelled, clean up anyway, just in case */ th = &pr->th; if (NULL != th->peer) { GNUNET_break (0); th->peer = NULL; if (NULL != th->cm) th->cm->th = NULL; } /* done with 'voluntary' cleanups, now on to normal freeing */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (h->peers, key, pr)); GNUNET_assert (pr->ch == h); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pr->timeout_task); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pr->ntr_task); GNUNET_free (pr); return GNUNET_YES; } /** * Close down any existing connection to the CORE service and * try re-establishing it later. * * @param h our handle */ static void reconnect_later (struct GNUNET_CORE_Handle *h) { struct ControlMessage *cm; struct PeerRecord *pr; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task); if (NULL != h->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); h->cth = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } h->currently_down = GNUNET_YES; GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_task, h); while (NULL != (cm = h->control_pending_head)) { GNUNET_CONTAINER_DLL_remove (h->control_pending_head, h->control_pending_tail, cm); if (NULL != cm->th) cm->th->cm = NULL; if (NULL != cm->cont) cm->cont (cm->cont_cls, GNUNET_NO); GNUNET_free (cm); } GNUNET_CONTAINER_multipeermap_iterate (h->peers, &disconnect_and_free_peer_entry, h); while (NULL != (pr = h->ready_peer_head)) GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); GNUNET_assert (h->control_pending_head == NULL); h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff); } /** * Check the list of pending requests, send the next * one to the core. * * @param h core handle * @param ignore_currently_down transmit message even if not initialized? */ static void trigger_next_request (struct GNUNET_CORE_Handle *h, int ignore_currently_down); /** * The given request hit its timeout. Remove from the * doubly-linked list and call the respective continuation. * * @param cls the transmit handle of the request that timed out * @param tc context, can be NULL (!) */ static void transmission_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Send a control message to the peer asking for transmission * of the message in the given peer record. * * @param pr peer to request transmission to */ static void request_next_transmission (struct PeerRecord *pr) { struct GNUNET_CORE_Handle *h = pr->ch; struct ControlMessage *cm; struct SendMessageRequest *smr; struct GNUNET_CORE_TransmitHandle *th; if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (pr->timeout_task); pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; } th = &pr->th; if (NULL == th->peer) { trigger_next_request (h, GNUNET_NO); return; } if (th->cm != NULL) return; /* already done */ GNUNET_assert (pr->prev == NULL); GNUNET_assert (pr->next == NULL); pr->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (th->timeout), &transmission_timeout, pr); cm = GNUNET_malloc (sizeof (struct ControlMessage) + sizeof (struct SendMessageRequest)); th->cm = cm; cm->th = th; smr = (struct SendMessageRequest *) &cm[1]; smr->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST); smr->header.size = htons (sizeof (struct SendMessageRequest)); smr->priority = htonl ((uint32_t) th->priority); smr->deadline = GNUNET_TIME_absolute_hton (th->timeout); smr->peer = pr->peer; smr->reserved = htonl (0); smr->size = htons (th->msize); smr->smr_id = htons (th->smr_id = pr->smr_id_gen++); GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, h->control_pending_tail, cm); LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding SEND REQUEST for peer `%s' to message queue\n", GNUNET_i2s (&pr->peer)); trigger_next_request (h, GNUNET_NO); } /** * The given request hit its timeout. Remove from the * doubly-linked list and call the respective continuation. * * @param cls the transmit handle of the request that timed out * @param tc context, can be NULL (!) */ static void transmission_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerRecord *pr = cls; struct GNUNET_CORE_Handle *h = pr->ch; struct GNUNET_CORE_TransmitHandle *th; pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != pr->ntr_task) { GNUNET_SCHEDULER_cancel (pr->ntr_task); pr->ntr_task = GNUNET_SCHEDULER_NO_TASK; } th = &pr->th; th->peer = NULL; if ((NULL != pr->prev) || (NULL != pr->next) || (pr == h->ready_peer_head)) { /* the request that was 'approved' by core was * canceled before it could be transmitted; remove * us from the 'ready' list */ GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); } if (NULL != th->cm) { /* we're currently in the control queue, remove */ GNUNET_CONTAINER_DLL_remove (h->control_pending_head, h->control_pending_tail, th->cm); GNUNET_free (th->cm); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Signalling timeout of request for transmission to peer `%s' via CORE\n", GNUNET_i2s (&pr->peer)); trigger_next_request (h, GNUNET_NO); GNUNET_assert (0 == th->get_message (th->get_message_cls, 0, NULL)); } /** * Transmit the next message to the core service. * * @param cls closure with the `struct GNUNET_CORE_Handle` * @param size number of bytes available in @a buf * @param buf where the callee should write the message * @return number of bytes written to @a buf */ static size_t transmit_message (void *cls, size_t size, void *buf) { struct GNUNET_CORE_Handle *h = cls; struct ControlMessage *cm; struct GNUNET_CORE_TransmitHandle *th; struct PeerRecord *pr; struct SendMessage *sm; const struct GNUNET_MessageHeader *hdr; uint16_t msize; size_t ret; GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); h->cth = NULL; if (NULL == buf) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed, initiating reconnect\n"); reconnect_later (h); return 0; } /* first check for control messages */ if (NULL != (cm = h->control_pending_head)) { hdr = (const struct GNUNET_MessageHeader *) &cm[1]; msize = ntohs (hdr->size); if (size < msize) { trigger_next_request (h, GNUNET_NO); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting control message with %u bytes of type %u to core.\n", (unsigned int) msize, (unsigned int) ntohs (hdr->type)); memcpy (buf, hdr, msize); GNUNET_CONTAINER_DLL_remove (h->control_pending_head, h->control_pending_tail, cm); if (NULL != cm->th) cm->th->cm = NULL; if (NULL != cm->cont) cm->cont (cm->cont_cls, GNUNET_OK); GNUNET_free (cm); trigger_next_request (h, GNUNET_NO); return msize; } /* now check for 'ready' P2P messages */ if (NULL == (pr = h->ready_peer_head)) return 0; GNUNET_assert (NULL != pr->th.peer); th = &pr->th; if (size < th->msize + sizeof (struct SendMessage)) { trigger_next_request (h, GNUNET_NO); return 0; } GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); th->peer = NULL; if (GNUNET_SCHEDULER_NO_TASK != pr->timeout_task) { GNUNET_SCHEDULER_cancel (pr->timeout_task); pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting SEND request to `%s' with %u bytes.\n", GNUNET_i2s (&pr->peer), (unsigned int) th->msize); sm = (struct SendMessage *) buf; sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND); sm->priority = htonl ((uint32_t) th->priority); sm->deadline = GNUNET_TIME_absolute_hton (th->timeout); sm->peer = pr->peer; sm->cork = htonl ((uint32_t) th->cork); sm->reserved = htonl (0); ret = th->get_message (th->get_message_cls, size - sizeof (struct SendMessage), &sm[1]); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting SEND request to `%s' yielded %u bytes.\n", GNUNET_i2s (&pr->peer), ret); if (0 == ret) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Size of clients message to peer %s is 0!\n", GNUNET_i2s (&pr->peer)); /* client decided to send nothing! */ request_next_transmission (pr); return 0; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Produced SEND message to core with %u bytes payload\n", (unsigned int) ret); GNUNET_assert (ret >= sizeof (struct GNUNET_MessageHeader)); if (ret + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); request_next_transmission (pr); return 0; } ret += sizeof (struct SendMessage); sm->header.size = htons (ret); GNUNET_assert (ret <= size); request_next_transmission (pr); return ret; } /** * Check the list of pending requests, send the next * one to the core. * * @param h core handle * @param ignore_currently_down transmit message even if not initialized? */ static void trigger_next_request (struct GNUNET_CORE_Handle *h, int ignore_currently_down) { uint16_t msize; if ((GNUNET_YES == h->currently_down) && (ignore_currently_down == GNUNET_NO)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Core connection down, not processing queue\n"); return; } if (NULL != h->cth) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Request pending, not processing queue\n"); return; } if (NULL != h->control_pending_head) msize = ntohs (((struct GNUNET_MessageHeader *) &h-> control_pending_head[1])->size); else if (h->ready_peer_head != NULL) msize = h->ready_peer_head->th.msize + sizeof (struct SendMessage); else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Request queue empty, not processing queue\n"); return; /* no pending message */ } h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client, msize, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &transmit_message, h); } /** * Handler for notification messages received from the core. * * @param cls our `struct GNUNET_CORE_Handle` * @param msg the message received from the core service */ static void main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_CORE_Handle *h = cls; const struct InitReplyMessage *m; const struct ConnectNotifyMessage *cnm; const struct DisconnectNotifyMessage *dnm; const struct NotifyTrafficMessage *ntm; const struct GNUNET_MessageHeader *em; const struct SendMessageReady *smr; const struct GNUNET_CORE_MessageHandler *mh; GNUNET_CORE_StartupCallback init; struct PeerRecord *pr; struct GNUNET_CORE_TransmitHandle *th; unsigned int hpos; int trigger; uint16_t msize; uint16_t et; if (NULL == msg) { LOG (GNUNET_ERROR_TYPE_INFO, _("Client was disconnected from core service, trying to reconnect.\n")); reconnect_later (h); return; } msize = ntohs (msg->size); LOG (GNUNET_ERROR_TYPE_DEBUG, "Processing message of type %u and size %u from core service\n", ntohs (msg->type), msize); switch (ntohs (msg->type)) { case GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY: if (ntohs (msg->size) != sizeof (struct InitReplyMessage)) { GNUNET_break (0); reconnect_later (h); return; } m = (const struct InitReplyMessage *) msg; GNUNET_break (0 == ntohl (m->reserved)); /* start our message processing loop */ if (GNUNET_YES == h->currently_down) { h->currently_down = GNUNET_NO; trigger_next_request (h, GNUNET_NO); } h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS; h->me = m->my_identity; if (NULL != (init = h->init)) { /* mark so we don't call init on reconnect */ h->init = NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connected to core service of peer `%s'.\n", GNUNET_i2s (&h->me)); init (h->cls, &h->me); } else { LOG (GNUNET_ERROR_TYPE_DEBUG, "Successfully reconnected to core service.\n"); } /* fake 'connect to self' */ pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &h->me); GNUNET_assert (NULL == pr); pr = GNUNET_new (struct PeerRecord); pr->peer = h->me; pr->ch = h; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (h->peers, &h->me, pr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); if (NULL != h->connects) h->connects (h->cls, &h->me); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT: if (msize < sizeof (struct ConnectNotifyMessage)) { GNUNET_break (0); reconnect_later (h); return; } cnm = (const struct ConnectNotifyMessage *) msg; if (msize != sizeof (struct ConnectNotifyMessage)) { GNUNET_break (0); reconnect_later (h); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received notification about connection from `%s'.\n", GNUNET_i2s (&cnm->peer)); if (0 == memcmp (&h->me, &cnm->peer, sizeof (struct GNUNET_PeerIdentity))) { /* connect to self!? */ GNUNET_break (0); return; } pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &cnm->peer); if (NULL != pr) { GNUNET_break (0); reconnect_later (h); return; } pr = GNUNET_new (struct PeerRecord); pr->peer = cnm->peer; pr->ch = h; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (h->peers, &cnm->peer, pr, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); if (NULL != h->connects) h->connects (h->cls, &cnm->peer); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT: if (msize != sizeof (struct DisconnectNotifyMessage)) { GNUNET_break (0); reconnect_later (h); return; } dnm = (const struct DisconnectNotifyMessage *) msg; if (0 == memcmp (&h->me, &dnm->peer, sizeof (struct GNUNET_PeerIdentity))) { /* connection to self!? */ GNUNET_break (0); return; } GNUNET_break (0 == ntohl (dnm->reserved)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received notification about disconnect from `%s'.\n", GNUNET_i2s (&dnm->peer)); pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &dnm->peer); if (NULL == pr) { GNUNET_break (0); reconnect_later (h); return; } trigger = ((pr->prev != NULL) || (pr->next != NULL) || (h->ready_peer_head == pr)); disconnect_and_free_peer_entry (h, &dnm->peer, pr); if (trigger) trigger_next_request (h, GNUNET_NO); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND: if (msize < sizeof (struct NotifyTrafficMessage)) { GNUNET_break (0); reconnect_later (h); return; } ntm = (const struct NotifyTrafficMessage *) msg; if ((msize < sizeof (struct NotifyTrafficMessage) + sizeof (struct GNUNET_MessageHeader)) ) { GNUNET_break (0); reconnect_later (h); return; } em = (const struct GNUNET_MessageHeader *) &ntm[1]; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u and size %u from peer `%4s'\n", ntohs (em->type), ntohs (em->size), GNUNET_i2s (&ntm->peer)); if ((GNUNET_NO == h->inbound_hdr_only) && (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage))) { GNUNET_break (0); reconnect_later (h); return; } et = ntohs (em->type); for (hpos = 0; hpos < h->hcnt; hpos++) { mh = &h->handlers[hpos]; if (mh->type != et) continue; if ((mh->expected_size != ntohs (em->size)) && (mh->expected_size != 0)) { LOG (GNUNET_ERROR_TYPE_ERROR, "Unexpected message size %u for message of type %u from peer `%4s'\n", htons (em->size), mh->type, GNUNET_i2s (&ntm->peer)); GNUNET_break_op (0); continue; } pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &ntm->peer); if (NULL == pr) { GNUNET_break (0); reconnect_later (h); return; } if (GNUNET_OK != h->handlers[hpos].callback (h->cls, &ntm->peer, em)) { /* error in processing, do not process other messages! */ break; } } if (NULL != h->inbound_notify) h->inbound_notify (h->cls, &ntm->peer, em); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND: if (msize < sizeof (struct NotifyTrafficMessage)) { GNUNET_break (0); reconnect_later (h); return; } ntm = (const struct NotifyTrafficMessage *) msg; if ((msize < sizeof (struct NotifyTrafficMessage) + sizeof (struct GNUNET_MessageHeader)) ) { GNUNET_break (0); reconnect_later (h); return; } em = (const struct GNUNET_MessageHeader *) &ntm[1]; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received notification about transmission to `%s'.\n", GNUNET_i2s (&ntm->peer)); if ((GNUNET_NO == h->outbound_hdr_only) && (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage))) { GNUNET_break (0); reconnect_later (h); return; } if (NULL == h->outbound_notify) { GNUNET_break (0); break; } h->outbound_notify (h->cls, &ntm->peer, em); break; case GNUNET_MESSAGE_TYPE_CORE_SEND_READY: if (msize != sizeof (struct SendMessageReady)) { GNUNET_break (0); reconnect_later (h); return; } smr = (const struct SendMessageReady *) msg; pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &smr->peer); if (NULL == pr) { GNUNET_break (0); reconnect_later (h); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Received notification about transmission readiness to `%s'.\n", GNUNET_i2s (&smr->peer)); if (NULL == pr->th.peer) { /* request must have been cancelled between the original request * and the response from core, ignore core's readiness */ break; } th = &pr->th; if (ntohs (smr->smr_id) != th->smr_id) { /* READY message is for expired or cancelled message, * ignore! (we should have already sent another request) */ break; } if ((NULL != pr->prev) || (NULL != pr->next) || (h->ready_peer_head == pr)) { /* we should not already be on the ready list... */ GNUNET_break (0); reconnect_later (h); return; } GNUNET_CONTAINER_DLL_insert (h->ready_peer_head, h->ready_peer_tail, pr); trigger_next_request (h, GNUNET_NO); break; default: reconnect_later (h); return; } GNUNET_CLIENT_receive (h->client, &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Task executed once we are done transmitting the INIT message. * Starts our 'receive' loop. * * @param cls the 'struct GNUNET_CORE_Handle' * @param success were we successful */ static void init_done_task (void *cls, int success) { struct GNUNET_CORE_Handle *h = cls; if (GNUNET_SYSERR == success) return; /* shutdown */ if (GNUNET_NO == success) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to exchange INIT with core, retrying\n"); if (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK) reconnect_later (h); return; } GNUNET_CLIENT_receive (h->client, &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); } /** * Our current client connection went down. Clean it up * and try to reconnect! * * @param h our handle to the core service */ static void reconnect (struct GNUNET_CORE_Handle *h) { struct ControlMessage *cm; struct InitMessage *init; uint32_t opt; uint16_t msize; uint16_t *ts; unsigned int hpos; GNUNET_assert (NULL == h->client); GNUNET_assert (GNUNET_YES == h->currently_down); GNUNET_assert (NULL != h->cfg); h->client = GNUNET_CLIENT_connect ("core", h->cfg); if (NULL == h->client) { reconnect_later (h); return; } msize = h->hcnt * sizeof (uint16_t) + sizeof (struct InitMessage); cm = GNUNET_malloc (sizeof (struct ControlMessage) + msize); cm->cont = &init_done_task; cm->cont_cls = h; init = (struct InitMessage *) &cm[1]; init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT); init->header.size = htons (msize); opt = 0; if (h->inbound_notify != NULL) { if (h->inbound_hdr_only) opt |= GNUNET_CORE_OPTION_SEND_HDR_INBOUND; else opt |= GNUNET_CORE_OPTION_SEND_FULL_INBOUND; } if (h->outbound_notify != NULL) { if (h->outbound_hdr_only) opt |= GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND; else opt |= GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND; } LOG (GNUNET_ERROR_TYPE_INFO, "(Re)connecting to CORE service, monitoring messages of type %u\n", opt); init->options = htonl (opt); ts = (uint16_t *) & init[1]; for (hpos = 0; hpos < h->hcnt; hpos++) ts[hpos] = htons (h->handlers[hpos].type); GNUNET_CONTAINER_DLL_insert (h->control_pending_head, h->control_pending_tail, cm); trigger_next_request (h, GNUNET_YES); } /** * Connect to the core service. Note that the connection may * complete (or fail) asynchronously. * * @param cfg configuration to use * @param cls closure for the various callbacks that follow (including handlers in the handlers array) * @param init callback to call once we have successfully * connected to the core service * @param connects function to call on peer connect, can be NULL * @param disconnects function to call on peer disconnect / timeout, can be NULL * @param inbound_notify function to call for all inbound messages, can be NULL * @param inbound_hdr_only set to #GNUNET_YES if inbound_notify will only read the * GNUNET_MessageHeader and hence we do not need to give it the full message; * can be used to improve efficiency, ignored if @a inbound_notify is NULLL * @param outbound_notify function to call for all outbound messages, can be NULL * @param outbound_hdr_only set to #GNUNET_YES if outbound_notify will only read the * GNUNET_MessageHeader and hence we do not need to give it the full message * can be used to improve efficiency, ignored if @a outbound_notify is NULLL * @param handlers callbacks for messages we care about, NULL-terminated * @return handle to the core service (only useful for disconnect until 'init' is called); * NULL on error (in this case, init is never called) */ struct GNUNET_CORE_Handle * GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_CORE_StartupCallback init, GNUNET_CORE_ConnectEventHandler connects, GNUNET_CORE_DisconnectEventHandler disconnects, GNUNET_CORE_MessageCallback inbound_notify, int inbound_hdr_only, GNUNET_CORE_MessageCallback outbound_notify, int outbound_hdr_only, const struct GNUNET_CORE_MessageHandler *handlers) { struct GNUNET_CORE_Handle *h; GNUNET_assert (NULL != cfg); h = GNUNET_new (struct GNUNET_CORE_Handle); h->cfg = cfg; h->cls = cls; h->init = init; h->connects = connects; h->disconnects = disconnects; h->inbound_notify = inbound_notify; h->outbound_notify = outbound_notify; h->inbound_hdr_only = inbound_hdr_only; h->outbound_hdr_only = outbound_hdr_only; h->handlers = handlers; h->hcnt = 0; h->currently_down = GNUNET_YES; h->peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); if (NULL != handlers) while (handlers[h->hcnt].callback != NULL) h->hcnt++; GNUNET_assert (h->hcnt < (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct InitMessage)) / sizeof (uint16_t)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CORE service\n"); reconnect (h); return h; } /** * Disconnect from the core service. This function can only * be called *after* all pending #GNUNET_CORE_notify_transmit_ready() * requests have been explicitly canceled. * * @param handle connection to core to disconnect */ void GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle) { struct ControlMessage *cm; GNUNET_assert (NULL != handle); LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from CORE service\n"); if (NULL != handle->cth) { GNUNET_CLIENT_notify_transmit_ready_cancel (handle->cth); handle->cth = NULL; } while (NULL != (cm = handle->control_pending_head)) { GNUNET_CONTAINER_DLL_remove (handle->control_pending_head, handle->control_pending_tail, cm); if (NULL != cm->th) cm->th->cm = NULL; if (NULL != cm->cont) cm->cont (cm->cont_cls, GNUNET_SYSERR); GNUNET_free (cm); } if (NULL != handle->client) { GNUNET_CLIENT_disconnect (handle->client); handle->client = NULL; } GNUNET_CONTAINER_multipeermap_iterate (handle->peers, &disconnect_and_free_peer_entry, handle); if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (handle->reconnect_task); handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_CONTAINER_multipeermap_destroy (handle->peers); handle->peers = NULL; GNUNET_break (handle->ready_peer_head == NULL); GNUNET_free (handle); } /** * Task that calls 'request_next_transmission'. * * @param cls the 'struct PeerRecord *' * @param tc scheduler context */ static void run_request_next_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct PeerRecord *pr = cls; pr->ntr_task = GNUNET_SCHEDULER_NO_TASK; request_next_transmission (pr); } /** * Ask the core to call @a notify once it is ready to transmit the * given number of bytes to the specified @a target. Must only be * called after a connection to the respective peer has been * established (and the client has been informed about this). You may * have one request of this type pending for each connected peer at * any time. If a peer disconnects, the application MUST call * #GNUNET_CORE_notify_transmit_ready_cancel on the respective * transmission request, if one such request is pending. * * @param handle connection to core service * @param cork is corking allowed for this transmission? * @param priority how important is the message? * @param maxdelay how long can the message wait? Only effective if @a cork is #GNUNET_YES * @param target who should receive the message, never NULL (can be this peer's identity for loopback) * @param notify_size how many bytes of buffer space does @a notify want? * @param notify function to call when buffer space is available; * will be called with NULL on timeout; clients MUST cancel * all pending transmission requests DURING the disconnect * handler * @param notify_cls closure for notify * @return non-NULL if the notify callback was queued, * NULL if we can not even queue the request (request already pending); * if NULL is returned, @a notify will NOT be called. */ struct GNUNET_CORE_TransmitHandle * GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, int cork, enum GNUNET_CORE_Priority priority, struct GNUNET_TIME_Relative maxdelay, const struct GNUNET_PeerIdentity *target, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { struct PeerRecord *pr; struct GNUNET_CORE_TransmitHandle *th; if (notify_size > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE) { GNUNET_break (0); return NULL; } GNUNET_assert (NULL != notify); LOG (GNUNET_ERROR_TYPE_DEBUG, "Asking core for transmission of %u bytes to `%s'\n", (unsigned int) notify_size, GNUNET_i2s (target)); pr = GNUNET_CONTAINER_multipeermap_get (handle->peers, target); if (NULL == pr) { /* attempt to send to peer that is not connected */ GNUNET_break (0); return NULL; } if (NULL != pr->th.peer) { /* attempting to queue a second request for the same destination */ GNUNET_break (0); return NULL; } GNUNET_assert (notify_size + sizeof (struct SendMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); th = &pr->th; memset (th, 0, sizeof (struct GNUNET_CORE_TransmitHandle)); th->peer = pr; th->get_message = notify; th->get_message_cls = notify_cls; th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); th->priority = priority; th->msize = notify_size; th->cork = cork; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == pr->ntr_task); pr->ntr_task = GNUNET_SCHEDULER_add_now (&run_request_next_transmission, pr); LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission request added to queue\n"); return th; } /** * Cancel the specified transmission-ready notification. * * @param th handle that was returned by "notify_transmit_ready". */ void GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle *th) { struct PeerRecord *pr = th->peer; struct GNUNET_CORE_Handle *h; GNUNET_assert (NULL != th); GNUNET_assert (NULL != pr); LOG (GNUNET_ERROR_TYPE_DEBUG, "Aborting transmission request to core for %u bytes to `%s'\n", (unsigned int) th->msize, GNUNET_i2s (&pr->peer)); th->peer = NULL; h = pr->ch; if (NULL != th->cm) { /* we're currently in the control queue, remove */ GNUNET_CONTAINER_DLL_remove (h->control_pending_head, h->control_pending_tail, th->cm); GNUNET_free (th->cm); th->cm = NULL; } if ((NULL != pr->prev) || (NULL != pr->next) || (pr == h->ready_peer_head)) { /* the request that was 'approved' by core was * canceled before it could be transmitted; remove * us from the 'ready' list */ GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); } if (GNUNET_SCHEDULER_NO_TASK != pr->ntr_task) { GNUNET_SCHEDULER_cancel (pr->ntr_task); pr->ntr_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Check if the given peer is currently connected. This function is for special * cirumstances (GNUNET_TESTBED uses it), normal users of the CORE API are * expected to track which peers are connected based on the connect/disconnect * callbacks from GNUNET_CORE_connect. This function is NOT part of the * 'versioned', 'official' API. The difference between this function and the * function GNUNET_CORE_is_peer_connected() is that this one returns * synchronously after looking in the CORE API cache. The function * GNUNET_CORE_is_peer_connected() sends a message to the CORE service and hence * its response is given asynchronously. * * @param h the core handle * @param pid the identity of the peer to check if it has been connected to us * @return GNUNET_YES if the peer is connected to us; GNUNET_NO if not */ int GNUNET_CORE_is_peer_connected_sync (const struct GNUNET_CORE_Handle *h, const struct GNUNET_PeerIdentity *pid) { GNUNET_assert (NULL != h); GNUNET_assert (NULL != pid); return GNUNET_CONTAINER_multipeermap_contains (h->peers, pid); } /** * Function called to notify a client about the connection * begin ready to queue more data. "buf" will be * NULL and "size" zero if the connection was closed for * writing in the meantime. * * @param cls closure * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf */ static size_t core_mq_ntr (void *cls, size_t size, void *buf) { struct GNUNET_MQ_Handle *mq = cls; struct CoreMQState *mqs = GNUNET_MQ_impl_state (mq); const struct GNUNET_MessageHeader *mh = GNUNET_MQ_impl_current (mq); size_t msg_size = ntohs (mh->size); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "core-mq", "ntr called (size %u, type %u)\n", msg_size, ntohs (mh->type)); mqs->th = NULL; if (NULL == buf) { GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "core-mq", "send error\n"); GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE); return 0; } memcpy (buf, mh, msg_size); GNUNET_MQ_impl_send_continue (mq); return msg_size; } /** * Signature of functions implementing the * sending functionality of a message queue. * * @param mq the message queue * @param msg the message to send * @param impl_state state of the implementation */ static void core_mq_send (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state) { struct CoreMQState *mqs = impl_state; GNUNET_assert (NULL == mqs->th); GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "core-mq", "Sending queued message (size %u)\n", ntohs (msg->size)); mqs->th = GNUNET_CORE_notify_transmit_ready (mqs->core, GNUNET_YES, 0, GNUNET_TIME_UNIT_FOREVER_REL, &mqs->target, ntohs (msg->size), core_mq_ntr, mq); } /** * Signature of functions implementing the * destruction of a message queue. * Implementations must not free @a mq, but should * take care of @a impl_state. * * @param mq the message queue to destroy * @param impl_state state of the implementation */ static void core_mq_destroy (struct GNUNET_MQ_Handle *mq, void *impl_state) { struct CoreMQState *mqs = impl_state; if (NULL != mqs->th) { GNUNET_CORE_notify_transmit_ready_cancel (mqs->th); mqs->th = NULL; } GNUNET_free (mqs); } /** * Implementation function that cancels the currently sent message. * * @param mq message queue * @param impl_state state specific to the implementation */ static void core_mq_cancel (struct GNUNET_MQ_Handle *mq, void *impl_state) { struct CoreMQState *mqs = impl_state; GNUNET_assert (NULL != mqs->th); GNUNET_CORE_notify_transmit_ready_cancel (mqs->th); } /** * Create a message queue for sending messages to a peer with CORE. * Messages may only be queued with #GNUNET_MQ_send once the init callback has * been called for the given handle. * There must only be one queue per peer for each core handle. * The message queue can only be used to transmit messages, * not to receive them. * * @param h the core handle * @param target the target peer for this queue, may not be NULL * @return a message queue for sending messages over the core handle * to the target peer */ struct GNUNET_MQ_Handle * GNUNET_CORE_mq_create (struct GNUNET_CORE_Handle *h, const struct GNUNET_PeerIdentity *target) { struct CoreMQState *mqs = GNUNET_new (struct CoreMQState); mqs->core = h; mqs->target = *target; return GNUNET_MQ_queue_for_callbacks (core_mq_send, core_mq_destroy, core_mq_cancel, mqs, NULL, NULL, NULL); } /* end of core_api.c */ gnunet-0.10.1/src/core/gnunet-service-core_clients.c0000644000175000017500000006767612320464037017331 00000000000000/* This file is part of GNUnet. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file core/gnunet-service-core_clients.c * @brief code for managing interactions with clients of core service * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" #include "gnunet-service-core.h" #include "gnunet-service-core_clients.h" #include "gnunet-service-core_sessions.h" #include "gnunet-service-core_typemap.h" #include "core.h" /** * How many messages do we queue up at most for optional * notifications to a client? (this can cause notifications * about outgoing messages to be dropped). */ #define MAX_NOTIFY_QUEUE 1024 /** * Data structure for each client connected to the CORE service. */ struct GSC_Client { /** * Clients are kept in a linked list. */ struct GSC_Client *next; /** * Clients are kept in a linked list. */ struct GSC_Client *prev; /** * Handle for the client with the server API. */ struct GNUNET_SERVER_Client *client_handle; /** * Array of the types of messages this peer cares * about (with @e tcnt entries). Allocated as part * of this client struct, do not free! */ const uint16_t *types; /** * Map of peer identities to active transmission requests of this * client to the peer (of type `struct GSC_ClientActiveRequest`). */ struct GNUNET_CONTAINER_MultiPeerMap *requests; /** * Map containing all peers that this client knows we're connected to. */ struct GNUNET_CONTAINER_MultiPeerMap *connectmap; /** * Options for messages this client cares about, * see GNUNET_CORE_OPTION_ values. */ uint32_t options; /** * Number of types of incoming messages this client * specifically cares about. Size of the @e types array. */ unsigned int tcnt; }; /** * Big "or" of all client options. */ static uint32_t all_client_options; /** * Head of linked list of our clients. */ static struct GSC_Client *client_head; /** * Tail of linked list of our clients. */ static struct GSC_Client *client_tail; /** * Context for notifications we need to send to our clients. */ static struct GNUNET_SERVER_NotificationContext *notifier; /** * Tokenizer for messages received from clients. */ static struct GNUNET_SERVER_MessageStreamTokenizer *client_mst; /** * Lookup our client struct given the server's client handle. * * @param client server client handle to look up * @return our client handle for the client */ static struct GSC_Client * find_client (struct GNUNET_SERVER_Client *client) { struct GSC_Client *c; c = client_head; while ((c != NULL) && (c->client_handle != client)) c = c->next; return c; } /** * Send a message to one of our clients. * * @param client target for the message * @param msg message to transmit * @param can_drop could this message be dropped if the * client's queue is getting too large? */ static void send_to_client (struct GSC_Client *client, const struct GNUNET_MessageHeader *msg, int can_drop) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Preparing to send %u bytes of message of type %u to client.\n", (unsigned int) ntohs (msg->size), (unsigned int) ntohs (msg->type)); GNUNET_SERVER_notification_context_unicast (notifier, client->client_handle, msg, can_drop); } /** * Send a message to one of our clients. * * @param client target for the message * @param msg message to transmit * @param can_drop could this message be dropped if the * client's queue is getting too large? */ void GSC_CLIENTS_send_to_client (struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg, int can_drop) { struct GSC_Client *c; c = find_client (client); if (NULL == c) { GNUNET_break (0); return; } send_to_client (c, msg, can_drop); } /** * Test if the client is interested in messages of the given type. * * @param type message type * @param c client to test * @return #GNUNET_YES if @a c is interested, #GNUNET_NO if not. */ static int type_match (uint16_t type, struct GSC_Client *c) { unsigned int i; if (c->tcnt == 0) return GNUNET_YES; /* peer without handlers matches ALL */ for (i = 0; i < c->tcnt; i++) if (type == c->types[i]) return GNUNET_YES; return GNUNET_NO; } /** * Send a message to all of our current clients that have the right * options set. * * @param partner origin (or destination) of the message (used to check that this peer is * known to be connected to the respective client) * @param msg message to multicast * @param can_drop can this message be discarded if the queue is too long * @param options mask to use * @param type type of the embedded message, 0 for none */ static void send_to_all_clients (const struct GNUNET_PeerIdentity *partner, const struct GNUNET_MessageHeader *msg, int can_drop, uint32_t options, uint16_t type) { struct GSC_Client *c; int tm; for (c = client_head; NULL != c; c = c->next) { tm = type_match (type, c); if (! ( (0 != (c->options & options)) || ( (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) && (GNUNET_YES == tm) ) ) ) continue; /* neither options nor type match permit the message */ if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) && ( (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || (GNUNET_YES == tm) ) ) continue; if ( (0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) && (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)) ) continue; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %u message with %u bytes to client interested in messages of type %u.\n", options, ntohs (msg->size), (unsigned int) type); GNUNET_assert ( (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) || (GNUNET_YES != tm) || (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (c->connectmap, partner)) ); send_to_client (c, msg, can_drop); } } /** * Handle CORE_INIT request. * * @param cls unused * @param client new client that sent INIT * @param message the 'struct InitMessage' (presumably) */ static void handle_client_init (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct InitMessage *im; struct InitReplyMessage irm; struct GSC_Client *c; uint16_t msize; const uint16_t *types; uint16_t *wtypes; unsigned int i; /* check that we don't have an entry already */ c = find_client (client); if (NULL != c) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } msize = ntohs (message->size); if (msize < sizeof (struct InitMessage)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_SERVER_notification_context_add (notifier, client); im = (const struct InitMessage *) message; types = (const uint16_t *) &im[1]; msize -= sizeof (struct InitMessage); c = GNUNET_malloc (sizeof (struct GSC_Client) + msize); c->client_handle = client; c->tcnt = msize / sizeof (uint16_t); c->options = ntohl (im->options); all_client_options |= c->options; c->types = (const uint16_t *) &c[1]; c->connectmap = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (c->connectmap, &GSC_my_identity, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); wtypes = (uint16_t *) & c[1]; for (i = 0; i < c->tcnt; i++) wtypes[i] = ntohs (types[i]); GSC_TYPEMAP_add (wtypes, c->tcnt); GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connecting to core service is interested in %u message types\n", (unsigned int) c->tcnt); /* send init reply message */ irm.header.size = htons (sizeof (struct InitReplyMessage)); irm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY); irm.reserved = htonl (0); irm.my_identity = GSC_my_identity; send_to_client (c, &irm.header, GNUNET_NO); GSC_SESSIONS_notify_client_about_sessions (c); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle CORE_SEND_REQUEST message. * * @param cls unused * @param client new client that sent CORE_SEND_REQUEST * @param message the 'struct SendMessageRequest' (presumably) */ static void handle_client_send_request (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct SendMessageRequest *req; struct GSC_Client *c; struct GSC_ClientActiveRequest *car; int is_loopback; req = (const struct SendMessageRequest *) message; c = find_client (client); if (c == NULL) { /* client did not send INIT first! */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } if (c->requests == NULL) c->requests = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client asked for transmission to `%s'\n", GNUNET_i2s (&req->peer)); is_loopback = (0 == memcmp (&req->peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))); if ((!is_loopback) && (GNUNET_YES != GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &req->peer))) { /* neighbour must have disconnected since request was issued, * ignore (client will realize it once it processes the * disconnect notification) */ GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# send requests dropped (disconnected)"), 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } car = GNUNET_CONTAINER_multipeermap_get (c->requests, &req->peer); if (NULL == car) { /* create new entry */ car = GNUNET_new (struct GSC_ClientActiveRequest); GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (c->requests, &req->peer, car, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); car->client_handle = c; } else { GSC_SESSIONS_dequeue_request (car); } car->target = req->peer; car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline); car->priority = (enum GNUNET_CORE_Priority) ntohl (req->priority); car->msize = ntohs (req->size); car->smr_id = req->smr_id; car->was_solicited = GNUNET_NO; if (is_loopback) { /* loopback, satisfy immediately */ GSC_CLIENTS_solicit_request (car); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GSC_SESSIONS_queue_request (car); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Closure for the #client_tokenizer_callback(). */ struct TokenizerContext { /** * Active request handle for the message. */ struct GSC_ClientActiveRequest *car; /** * How important is this message. */ enum GNUNET_CORE_Priority priority; /** * Is corking allowed (set only once we have the real message). */ int cork; }; /** * Handle CORE_SEND request. * * @param cls unused * @param client the client issuing the request * @param message the `struct SendMessage` */ static void handle_client_send (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct SendMessage *sm; struct GSC_Client *c; struct TokenizerContext tc; uint16_t msize; msize = ntohs (message->size); if (msize < sizeof (struct SendMessage) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } sm = (const struct SendMessage *) message; msize -= sizeof (struct SendMessage); GNUNET_break (0 == ntohl (sm->reserved)); c = find_client (client); if (NULL == c) { /* client did not send INIT first! */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } tc.car = GNUNET_CONTAINER_multipeermap_get (c->requests, &sm->peer); if (NULL == tc.car) { /* Must have been that we first approved the request, then got disconnected * (which triggered removal of the 'car') and now the client gives us a message * just *before* the client learns about the disconnect. Theoretically, we * might also now be *again* connected. So this can happen (but should be * rare). If it does happen, the message is discarded. */ GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# messages discarded (session disconnected)"), 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (c->requests, &sm->peer, tc.car)); tc.cork = ntohl (sm->cork); tc.priority = (enum GNUNET_CORE_Priority) ntohl (sm->priority); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client asked for transmission of %u bytes to `%s' %s\n", msize, GNUNET_i2s (&sm->peer), tc.cork ? "now" : ""); GNUNET_SERVER_mst_receive (client_mst, &tc, (const char *) &sm[1], msize, GNUNET_YES, GNUNET_NO); if (0 != memcmp (&tc.car->target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) GSC_SESSIONS_dequeue_request (tc.car); GNUNET_free (tc.car); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Functions with this signature are called whenever a complete * message is received by the tokenizer. Used by the 'client_mst' for * dispatching messages from clients to either the SESSION subsystem * or other CLIENT (for loopback). * * @param cls closure * @param client reservation request (`struct GSC_ClientActiveRequest`) * @param message the actual message */ static int client_tokenizer_callback (void *cls, void *client, const struct GNUNET_MessageHeader *message) { struct TokenizerContext *tc = client; struct GSC_ClientActiveRequest *car = tc->car; char buf[92]; GNUNET_snprintf (buf, sizeof (buf), gettext_noop ("# bytes of messages of type %u received"), (unsigned int) ntohs (message->type)); GNUNET_STATISTICS_update (GSC_stats, buf, ntohs (message->size), GNUNET_NO); if (0 == memcmp (&car->target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering message of type %u to myself\n", ntohs (message->type)); GSC_CLIENTS_deliver_message (&GSC_my_identity, message, ntohs (message->size), GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND); GSC_CLIENTS_deliver_message (&GSC_my_identity, message, sizeof (struct GNUNET_MessageHeader), GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND); GSC_CLIENTS_deliver_message (&GSC_my_identity, message, ntohs (message->size), GNUNET_CORE_OPTION_SEND_FULL_INBOUND); GSC_CLIENTS_deliver_message (&GSC_my_identity, message, sizeof (struct GNUNET_MessageHeader), GNUNET_CORE_OPTION_SEND_HDR_INBOUND); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Delivering message of type %u to %s\n", ntohs (message->type), GNUNET_i2s (&car->target)); GSC_CLIENTS_deliver_message (&car->target, message, ntohs (message->size), GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND); GSC_CLIENTS_deliver_message (&car->target, message, sizeof (struct GNUNET_MessageHeader), GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND); GSC_SESSIONS_transmit (car, message, tc->cork, tc->priority); } return GNUNET_OK; } /** * Free client request records. * * @param cls NULL * @param key identity of peer for which this is an active request * @param value the `struct GSC_ClientActiveRequest` to free * @return #GNUNET_YES (continue iteration) */ static int destroy_active_client_request (void *cls, const struct GNUNET_PeerIdentity *key, void *value) { struct GSC_ClientActiveRequest *car = value; GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (car-> client_handle->requests, &car->target, car)); GSC_SESSIONS_dequeue_request (car); GNUNET_free (car); return GNUNET_YES; } /** * A client disconnected, clean up. * * @param cls closure * @param client identification of the client */ static void handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct GSC_Client *c; if (client == NULL) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p has disconnected from core service.\n", client); c = find_client (client); if (c == NULL) return; /* client never sent INIT */ GNUNET_CONTAINER_DLL_remove (client_head, client_tail, c); if (c->requests != NULL) { GNUNET_CONTAINER_multipeermap_iterate (c->requests, &destroy_active_client_request, NULL); GNUNET_CONTAINER_multipeermap_destroy (c->requests); } GNUNET_CONTAINER_multipeermap_destroy (c->connectmap); c->connectmap = NULL; GSC_TYPEMAP_remove (c->types, c->tcnt); GNUNET_free (c); /* recalculate 'all_client_options' */ all_client_options = 0; for (c = client_head; NULL != c ; c = c->next) all_client_options |= c->options; } /** * Tell a client that we are ready to receive the message. * * @param car request that is now ready; the responsibility * for the handle remains shared between CLIENTS * and SESSIONS after this call. */ void GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car) { struct GSC_Client *c; struct SendMessageReady smr; c = car->client_handle; if (GNUNET_YES != GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &car->target)) { /* connection has gone down since, drop request */ GNUNET_assert (0 != memcmp (&car->target, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity))); GSC_SESSIONS_dequeue_request (car); GSC_CLIENTS_reject_request (car); return; } smr.header.size = htons (sizeof (struct SendMessageReady)); smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY); smr.size = htons (car->msize); smr.smr_id = car->smr_id; smr.peer = car->target; send_to_client (c, &smr.header, GNUNET_NO); } /** * Tell a client that we will never be ready to receive the * given message in time (disconnect or timeout). * * @param car request that now permanently failed; the * responsibility for the handle is now returned * to CLIENTS (SESSIONS is done with it). */ void GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car) { GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (car-> client_handle->requests, &car->target, car)); GNUNET_free (car); } /** * Notify a particular client about a change to existing connection to * one of our neighbours (check if the client is interested). Called * from 'GSC_SESSIONS_notify_client_about_sessions'. * * @param client client to notify * @param neighbour identity of the neighbour that changed status * @param tmap_old previous type map for the neighbour, NULL for connect * @param tmap_new updated type map for the neighbour, NULL for disconnect */ void GSC_CLIENTS_notify_client_about_neighbour (struct GSC_Client *client, const struct GNUNET_PeerIdentity *neighbour, const struct GSC_TypeMap *tmap_old, const struct GSC_TypeMap *tmap_new) { struct ConnectNotifyMessage *cnm; size_t size; char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; struct DisconnectNotifyMessage dcm; int old_match; int new_match; old_match = GSC_TYPEMAP_test_match (tmap_old, client->types, client->tcnt); new_match = GSC_TYPEMAP_test_match (tmap_new, client->types, client->tcnt); if (old_match == new_match) { GNUNET_assert (old_match == GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour)); return; /* no change */ } if (old_match == GNUNET_NO) { /* send connect */ GNUNET_assert (GNUNET_NO == GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_put (client->connectmap, neighbour, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); size = sizeof (struct ConnectNotifyMessage); cnm = (struct ConnectNotifyMessage *) buf; cnm->header.size = htons (size); cnm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); cnm->reserved = htonl (0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to client.\n", "NOTIFY_CONNECT"); cnm->peer = *neighbour; send_to_client (client, &cnm->header, GNUNET_NO); } else { /* send disconnect */ GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour)); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (client->connectmap, neighbour, NULL)); dcm.header.size = htons (sizeof (struct DisconnectNotifyMessage)); dcm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT); dcm.reserved = htonl (0); dcm.peer = *neighbour; send_to_client (client, &dcm.header, GNUNET_NO); } } /** * Notify all clients about a change to existing session. * Called from SESSIONS whenever there is a change in sessions * or types processed by the respective peer. * * @param neighbour identity of the neighbour that changed status * @param tmap_old previous type map for the neighbour, NULL for connect * @param tmap_new updated type map for the neighbour, NULL for disconnect */ void GSC_CLIENTS_notify_clients_about_neighbour (const struct GNUNET_PeerIdentity *neighbour, const struct GSC_TypeMap *tmap_old, const struct GSC_TypeMap *tmap_new) { struct GSC_Client *c; for (c = client_head; c != NULL; c = c->next) GSC_CLIENTS_notify_client_about_neighbour (c, neighbour, tmap_old, tmap_new); } /** * Deliver P2P message to interested clients. Caller must have checked * that the sending peer actually lists the given message type as one * of its types. * * @param sender peer who sent us the message * @param msg the message * @param msize number of bytes to transmit * @param options options for checking which clients should * receive the message */ void GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, uint16_t msize, uint32_t options) { size_t size = msize + sizeof (struct NotifyTrafficMessage); char buf[size] GNUNET_ALIGN; struct NotifyTrafficMessage *ntm; if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); /* recovery strategy: throw performance data away... */ size = msize + sizeof (struct NotifyTrafficMessage); } if (! ( (0 != (all_client_options & options)) || (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) )) return; /* no client cares about this message notification */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service passes message from `%4s' of type %u to client.\n", GNUNET_i2s (sender), (unsigned int) ntohs (msg->type)); GSC_SESSIONS_add_to_typemap (sender, ntohs (msg->type)); ntm = (struct NotifyTrafficMessage *) buf; ntm->header.size = htons (size); if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND | GNUNET_CORE_OPTION_SEND_HDR_INBOUND))) ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND); else ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND); ntm->peer = *sender; memcpy (&ntm[1], msg, msize); send_to_all_clients (sender, &ntm->header, GNUNET_YES, options, ntohs (msg->type)); } /** * Initialize clients subsystem. * * @param server handle to server clients connect to */ void GSC_CLIENTS_init (struct GNUNET_SERVER_Handle *server) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_CORE_INIT, 0}, {&GSC_SESSIONS_handle_client_iterate_peers, NULL, GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS, sizeof (struct GNUNET_MessageHeader)}, {&handle_client_send_request, NULL, GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST, sizeof (struct SendMessageRequest)}, {&handle_client_send, NULL, GNUNET_MESSAGE_TYPE_CORE_SEND, 0}, {NULL, NULL, 0, 0} }; /* setup notification */ client_mst = GNUNET_SERVER_mst_create (&client_tokenizer_callback, NULL); notifier = GNUNET_SERVER_notification_context_create (server, MAX_NOTIFY_QUEUE); GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); GNUNET_SERVER_add_handlers (server, handlers); } /** * Shutdown clients subsystem. */ void GSC_CLIENTS_done () { struct GSC_Client *c; while (NULL != (c = client_head)) handle_client_disconnect (NULL, c->client_handle); if (NULL != notifier) { GNUNET_SERVER_notification_context_destroy (notifier); notifier = NULL; } if (NULL != client_mst) { GNUNET_SERVER_mst_destroy (client_mst); client_mst = NULL; } } /* end of gnunet-service-core_clients.c */ gnunet-0.10.1/src/tun/0000755000175000017500000000000012320755622011473 500000000000000gnunet-0.10.1/src/tun/Makefile.in0000644000175000017500000011206712320752065013465 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_tun$(EXEEXT) test_regex$(EXEEXT) subdir = src/tun DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunettun_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libgnunettun_la_OBJECTS = tun.lo regex.lo libgnunettun_la_OBJECTS = $(am_libgnunettun_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunettun_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunettun_la_LDFLAGS) $(LDFLAGS) \ -o $@ am_test_regex_OBJECTS = test_regex.$(OBJEXT) test_regex_OBJECTS = $(am_test_regex_OBJECTS) test_regex_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/tun/libgnunettun.la am_test_tun_OBJECTS = test_tun.$(OBJEXT) test_tun_OBJECTS = $(am_test_tun_OBJECTS) test_tun_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/tun/libgnunettun.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunettun_la_SOURCES) $(test_regex_SOURCES) \ $(test_tun_SOURCES) DIST_SOURCES = $(libgnunettun_la_SOURCES) $(test_regex_SOURCES) \ $(test_tun_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov lib_LTLIBRARIES = libgnunettun.la libgnunettun_la_SOURCES = \ tun.c \ regex.c libgnunettun_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ $(LTLIBINTL) libgnunettun_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 1:0:1 @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_tun_SOURCES = \ test_tun.c test_tun_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/tun/libgnunettun.la test_regex_SOURCES = \ test_regex.c test_regex_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/tun/libgnunettun.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/tun/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/tun/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunettun.la: $(libgnunettun_la_OBJECTS) $(libgnunettun_la_DEPENDENCIES) $(EXTRA_libgnunettun_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunettun_la_LINK) -rpath $(libdir) $(libgnunettun_la_OBJECTS) $(libgnunettun_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list test_regex$(EXEEXT): $(test_regex_OBJECTS) $(test_regex_DEPENDENCIES) $(EXTRA_test_regex_DEPENDENCIES) @rm -f test_regex$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_regex_OBJECTS) $(test_regex_LDADD) $(LIBS) test_tun$(EXEEXT): $(test_tun_OBJECTS) $(test_tun_DEPENDENCIES) $(EXTRA_test_tun_DEPENDENCIES) @rm -f test_tun$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_tun_OBJECTS) $(test_tun_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_regex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_tun.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tun.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_tun.log: test_tun$(EXEEXT) @p='test_tun$(EXEEXT)'; \ b='test_tun'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_regex.log: test_regex$(EXEEXT) @p='test_regex$(EXEEXT)'; \ b='test_regex'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/tun/test_tun.c0000644000175000017500000000365412225777502013441 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file tun/test_tun.c * @brief test for tun.c * @author Christian Grothoff */ #include "platform.h" #include "gnunet_tun_lib.h" static int ret; static void test_udp (size_t pll, int pl_fill, uint16_t crc) { struct GNUNET_TUN_IPv4Header ip; struct GNUNET_TUN_UdpHeader udp; char payload[pll]; struct in_addr src; struct in_addr dst; GNUNET_assert (1 == inet_pton (AF_INET, "1.2.3.4", &src)); GNUNET_assert (1 == inet_pton (AF_INET, "122.2.3.5", &dst)); memset (payload, pl_fill, sizeof (payload)); GNUNET_TUN_initialize_ipv4_header (&ip, IPPROTO_UDP, pll + sizeof (udp), &src, &dst); udp.source_port = htons (4242); udp.destination_port = htons (4242); udp.len = htons (pll); GNUNET_TUN_calculate_udp4_checksum (&ip, &udp, payload, pll); if (crc != ntohs (udp.crc)) { fprintf (stderr, "Got CRC: %u, wanted: %u\n", ntohs (udp.crc), crc); ret = 1; } } int main (int argc, char **argv) { test_udp (4, 3, 22439); test_udp (4, 1, 23467); test_udp (7, 17, 6516); test_udp (12451, 251, 42771); return ret; } gnunet-0.10.1/src/tun/tun.c0000644000175000017500000002143612225777502012400 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file tun/tun.c * @brief standard IP calculations for TUN interaction * @author Philipp Toelke * @author Christian Grothoff */ #include "platform.h" #include "gnunet_tun_lib.h" /** * IP TTL we use for packets that we assemble (8 bit unsigned integer) */ #define FRESH_TTL 64 /** * Initialize an IPv4 header. * * @param ip header to initialize * @param protocol protocol to use (i.e. IPPROTO_UDP) * @param payload_length number of bytes of payload that follow (excluding IPv4 header) * @param src source IP address to use * @param dst destination IP address to use */ void GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip, uint8_t protocol, uint16_t payload_length, const struct in_addr *src, const struct in_addr *dst) { GNUNET_assert (20 == sizeof (struct GNUNET_TUN_IPv4Header)); GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv4Header)); memset (ip, 0, sizeof (struct GNUNET_TUN_IPv4Header)); ip->header_length = sizeof (struct GNUNET_TUN_IPv4Header) / 4; ip->version = 4; ip->total_length = htons (sizeof (struct GNUNET_TUN_IPv4Header) + payload_length); ip->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 65536); ip->ttl = FRESH_TTL; ip->protocol = protocol; ip->source_address = *src; ip->destination_address = *dst; ip->checksum = GNUNET_CRYPTO_crc16_n (ip, sizeof (struct GNUNET_TUN_IPv4Header)); } /** * Initialize an IPv6 header. * * @param ip header to initialize * @param protocol protocol to use (i.e. IPPROTO_UDP), technically "next_header" for IPv6 * @param payload_length number of bytes of payload that follow (excluding IPv4 header) * @param src source IP address to use * @param dst destination IP address to use */ void GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip, uint8_t protocol, uint16_t payload_length, const struct in6_addr *src, const struct in6_addr *dst) { GNUNET_assert (40 == sizeof (struct GNUNET_TUN_IPv6Header)); GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv6Header)); memset (ip, 0, sizeof (struct GNUNET_TUN_IPv6Header)); ip->version = 6; ip->next_header = protocol; ip->payload_length = htons ((uint16_t) payload_length); ip->hop_limit = FRESH_TTL; ip->destination_address = *dst; ip->source_address = *src; } /** * Calculate IPv4 TCP checksum. * * @param ip ipv4 header fully initialized * @param tcp TCP header (initialized except for CRC) * @param payload the TCP payload * @param payload_length number of bytes of TCP payload */ void GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length) { uint32_t sum; uint16_t tmp; GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader)); GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_TcpHeader) == ntohs (ip->total_length)); GNUNET_assert (IPPROTO_TCP == ip->protocol); tcp->crc = 0; sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, sizeof (struct in_addr) * 2); tmp = htons (IPPROTO_TCP); sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); tmp = htons (payload_length + sizeof (struct GNUNET_TUN_TcpHeader)); sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); sum = GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader)); sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); tcp->crc = GNUNET_CRYPTO_crc16_finish (sum); } /** * Calculate IPv6 TCP checksum. * * @param ip ipv6 header fully initialized * @param tcp header (initialized except for CRC) * @param payload the TCP payload * @param payload_length number of bytes of TCP payload */ void GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_TcpHeader *tcp, const void *payload, uint16_t payload_length) { uint32_t sum; uint32_t tmp; GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader)); GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_TcpHeader) == ntohs (ip->payload_length)); GNUNET_assert (IPPROTO_TCP == ip->next_header); tcp->crc = 0; sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, 2 * sizeof (struct in6_addr)); tmp = htonl (sizeof (struct GNUNET_TUN_TcpHeader) + payload_length); sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); tmp = htonl (IPPROTO_TCP); sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); sum = GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader)); sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); tcp->crc = GNUNET_CRYPTO_crc16_finish (sum); } /** * Calculate IPv4 UDP checksum. * * @param ip ipv4 header fully initialized * @param udp UDP header (initialized except for CRC) * @param payload the UDP payload * @param payload_length number of bytes of UDP payload */ void GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length) { uint32_t sum; uint16_t tmp; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_UdpHeader) == ntohs (ip->total_length)); GNUNET_assert (IPPROTO_UDP == ip->protocol); udp->crc = 0; /* technically optional, but we calculate it anyway, just to be sure */ sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, sizeof (struct in_addr) * 2); tmp = htons (IPPROTO_UDP); sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t)); sum = GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader)); sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); udp->crc = GNUNET_CRYPTO_crc16_finish (sum); } /** * Calculate IPv6 UDP checksum. * * @param ip ipv6 header fully initialized * @param udp UDP header (initialized except for CRC) * @param payload the UDP payload * @param payload_length number of bytes of UDP payload */ void GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip, struct GNUNET_TUN_UdpHeader *udp, const void *payload, uint16_t payload_length) { uint32_t sum; uint32_t tmp; GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) == ntohs (ip->payload_length)); GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) == ntohs (udp->len)); GNUNET_assert (IPPROTO_UDP == ip->next_header); udp->crc = 0; sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, sizeof (struct in6_addr) * 2); tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); /* aka udp->len */ sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); tmp = htons (ip->next_header); sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t)); sum = GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader)); sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); udp->crc = GNUNET_CRYPTO_crc16_finish (sum); } /** * Calculate ICMP checksum. * * @param icmp IMCP header (initialized except for CRC) * @param payload the ICMP payload * @param payload_length number of bytes of ICMP payload */ void GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp, const void *payload, uint16_t payload_length) { uint32_t sum; GNUNET_assert (8 == sizeof (struct GNUNET_TUN_IcmpHeader)); icmp->crc = 0; sum = GNUNET_CRYPTO_crc16_step (0, icmp, sizeof (struct GNUNET_TUN_IcmpHeader)); sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length); icmp->crc = GNUNET_CRYPTO_crc16_finish (sum); } /* end of tun.c */ gnunet-0.10.1/src/tun/Makefile.am0000644000175000017500000000165112320751517013451 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif lib_LTLIBRARIES = libgnunettun.la libgnunettun_la_SOURCES = \ tun.c \ regex.c libgnunettun_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ $(LTLIBINTL) libgnunettun_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 1:0:1 check_PROGRAMS = \ test_tun \ test_regex if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_tun_SOURCES = \ test_tun.c test_tun_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/tun/libgnunettun.la test_regex_SOURCES = \ test_regex.c test_regex_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/tun/libgnunettun.la gnunet-0.10.1/src/tun/test_regex.c0000644000175000017500000001136212264756022013735 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file tun/test_regex.c * @brief simple test for regex.c iptoregex functions * @author Maximilian Szengel */ #include "platform.h" #include "gnunet_tun_lib.h" static int test_iptoregex (const char *ipv4, uint16_t port, const char *expectedv4, const char *ipv6, uint16_t port6, const char *expectedv6) { int error = 0; struct in_addr a; struct in6_addr b; char rxv4[GNUNET_TUN_IPV4_REGEXLEN]; char rxv6[GNUNET_TUN_IPV6_REGEXLEN]; GNUNET_assert (1 == inet_pton (AF_INET, ipv4, &a)); GNUNET_TUN_ipv4toregexsearch (&a, port, rxv4); if (0 != strcmp (rxv4, expectedv4)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected: %s but got: %s\n", expectedv4, rxv4); error++; } GNUNET_assert (1 == inet_pton (AF_INET6, ipv6, &b)); GNUNET_TUN_ipv6toregexsearch (&b, port6, rxv6); if (0 != strcmp (rxv6, expectedv6)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected: %s but got: %s\n", expectedv6, rxv6); error++; } return error; } static int test_policy4toregex (const char *policy, const char *regex) { char *r; int ret; ret = 0; r = GNUNET_TUN_ipv4policy2regex (policy); if (NULL == r) { GNUNET_break (0); return 1; } if (0 != strcmp (regex, r)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected: `%s' but got: `%s'\n", regex, r); ret = 2; } GNUNET_free (r); return ret; } static int test_policy6toregex (const char *policy, const char *regex) { char *r; int ret; ret = 0; r = GNUNET_TUN_ipv6policy2regex (policy); if (NULL == r) { GNUNET_break (0); return 1; } if (0 != strcmp (regex, r)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected: `%s' but got: `%s'\n", regex, r); ret = 2; } GNUNET_free (r); return ret; } int main (int argc, char *argv[]) { int error; char *r; GNUNET_log_setup ("test-regex", "WARNING", NULL); error = 0; /* this is just a performance test ... */ r = GNUNET_TUN_ipv4policy2regex ("1.2.3.4/16:!25;"); GNUNET_break (NULL != r); GNUNET_free (r); error += test_iptoregex ("192.1.2.3", 2086, "4-0826-C0010203", "FFFF::1", 8080, "6-1F90-FFFF0000000000000000000000000001"); error += test_iptoregex ("187.238.255.0", 80, "4-0050-BBEEFF00", "E1E1:73F9:51BE::0", 49, "6-0031-E1E173F951BE00000000000000000000"); error += test_policy4toregex ("192.1.2.0/24:80;", "4-0050-C00102.."); error += test_policy4toregex ("192.1.0.0/16;", "4-....-C001...."); error += test_policy4toregex ("192.1.0.0/16:80-81;", "4-(0050|0051)-C001...."); error += test_policy4toregex ("192.1.0.0/8:!3-65535;", "4-000(0|1|2)-C0......"); error += test_policy4toregex ("192.1.0.0/8:!25-56;", "4-(0(0(0.|1(0|1|2|3|4|5|6|7|8)|3(9|A|B|C|D|E|F)|(4|5|6|7|8|9|A|B|C|D|E|F).)|(1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)..)|(1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)...)-C0......"); error += test_policy6toregex ("E1E1::1;", "6-....-E1E10000000000000000000000000001"); error += test_policy6toregex ("E1E1:ABCD::1/120;", "6-....-E1E1ABCD0000000000000000000000.."); error += test_policy6toregex ("E1E1:ABCD::ABCD/126;", "6-....-E1E1ABCD00000000000000000000ABC(C|D|E|F)"); error += test_policy6toregex ("E1E1:ABCD::ABCD/127;", "6-....-E1E1ABCD00000000000000000000ABC(C|D)"); error += test_policy6toregex ("E1E1:ABCD::ABCD/128:80;", "6-0050-E1E1ABCD00000000000000000000ABCD"); return error; } gnunet-0.10.1/src/tun/regex.c0000644000175000017500000004613612264756022012705 00000000000000/* This file is part of GNUnet (C) 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/tun/regex.c * @brief functions to convert IP networks to regexes * @author Maximilian Szengel * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_tun_lib.h" /** * Create a regex in @a rxstr from the given @a ip and @a netmask. * * @param ip IPv4 representation. * @param port destination port * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN * bytes long. */ void GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip, uint16_t port, char *rxstr) { GNUNET_snprintf (rxstr, GNUNET_TUN_IPV4_REGEXLEN, "4-%04X-%08X", (unsigned int) port, ntohl (ip->s_addr)); } /** * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen. * * @param ipv6 IPv6 representation. * @param port destination port * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN * bytes long. */ void GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6, uint16_t port, char *rxstr) { const uint32_t *addr; addr = (const uint32_t *) ipv6; GNUNET_snprintf (rxstr, GNUNET_TUN_IPV6_REGEXLEN, "6-%04X-%08X%08X%08X%08X", (unsigned int) port, ntohl (addr[0]), ntohl (addr[1]), ntohl (addr[2]), ntohl (addr[3])); } /** * Convert the given 4-bit (!) number to a regex. * * @param value the value, only the lowest 4 bits will be looked at * @param mask which bits in value are wildcards (any value)? */ static char * nibble_to_regex (uint8_t value, uint8_t mask) { char *ret; value &= mask; switch (mask) { case 0: return GNUNET_strdup ("."); /* wildcard */ case 8: GNUNET_asprintf (&ret, "(%X|%X|%X|%X|%X|%X|%X|%X)", value, value + 1, value + 2, value + 3, value + 4, value + 5, value + 6, value + 7); return ret; case 12: GNUNET_asprintf (&ret, "(%X|%X|%X|%X)", value, value + 1, value + 2, value + 3); return ret; case 14: GNUNET_asprintf (&ret, "(%X|%X)", value, value + 1); return ret; case 15: GNUNET_asprintf (&ret, "%X", value); return ret; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Bad mask: %d\n"), mask); GNUNET_break (0); return NULL; } } /** * Convert the given 16-bit number to a regex. * * @param value the value * @param mask which bits in value are wildcards (any value)? */ static char * num_to_regex (uint16_t value, uint16_t mask) { const uint8_t *v = (const uint8_t *) &value; const uint8_t *m = (const uint8_t *) &mask; char *a; char *b; char *c; char *d; char *ret; a = nibble_to_regex (v[0] >> 4, m[0] >> 4); b = nibble_to_regex (v[0] & 15, m[0] & 15); c = nibble_to_regex (v[1] >> 4, m[1] >> 4); d = nibble_to_regex (v[1] & 15, m[1] & 15); ret = NULL; if ( (NULL != a) && (NULL != b) && (NULL != c) && (NULL != d) ) GNUNET_asprintf (&ret, "%s%s%s%s", a, b, c, d); GNUNET_free_non_null (a); GNUNET_free_non_null (b); GNUNET_free_non_null (c); GNUNET_free_non_null (d); return ret; } /** * Do we need to put parents around the given argument? * * @param arg part of a regular expression * @return #GNUNET_YES if we should parens, * #GNUNET_NO if not */ static int needs_parens (const char *arg) { size_t off; size_t len; unsigned int op; op = 0; len = strlen (arg); for (off=0;off 0); op--; break; case '|': if (0 == op) return GNUNET_YES; break; default: break; } } return GNUNET_NO; } /** * Compute port policy for the given range of * port numbers. * * @param start starting offset * @param end end offset * @param step increment level (power of 16) * @param pp port policy to convert * @return corresponding regex */ static char * compute_policy (unsigned int start, unsigned int end, unsigned int step, const struct GNUNET_STRINGS_PortPolicy *pp) { unsigned int i; char before[36]; /* 16 * 2 + 3 dots + 0-terminator */ char middlel[33]; /* 16 * 2 + 0-terminator */ char middleh[33]; /* 16 * 2 + 0-terminator */ char after[36]; /* 16 * 2 + 3 dots + 0-terminator */ char beforep[36+2]; /* 16 * 2 + 3 dots + 0-terminator + ()*/ char middlehp[33+2]; /* 16 * 2 + 0-terminator + () */ char middlelp[33+2]; /* 16 * 2 + 0-terminator + () */ char afterp[36+2]; /* 16 * 2 + 3 dots + 0-terminator + () */ char dots[4]; char buf[3]; char *middle; char *ret; unsigned int xstep; char *recl; char *rech; char *reclp; char *rechp; unsigned int start_port; unsigned int end_port; GNUNET_assert (GNUNET_YES == pp->negate_portrange); start_port = pp->start_port; if (1 == start_port) start_port = 0; end_port = pp->end_port; GNUNET_assert ((end - start) / step <= 0xF); before[0] = '\0'; middlel[0] = '\0'; middleh[0] = '\0'; after[0] = '\0'; for (i=start;i<=end;i+=step) { GNUNET_snprintf (buf, sizeof (buf), "%X|", (i - start) / step); if (i / step < start_port / step) strcat (before, buf); else if (i / step > end_port / step) strcat (after, buf); else if (i / step == start_port / step) strcat (middlel, buf); else if (i / step == end_port / step) strcat (middleh, buf); } if (strlen (before) > 0) before[strlen (before)-1] = '\0'; if (strlen (middlel) > 0) middlel[strlen (middlel)-1] = '\0'; if (strlen (middleh) > 0) middleh[strlen (middleh)-1] = '\0'; if (strlen (after) > 0) after[strlen (after)-1] = '\0'; if (needs_parens (before)) GNUNET_snprintf (beforep, sizeof (beforep), "(%s)", before); else strcpy (beforep, before); if (needs_parens (middlel)) GNUNET_snprintf (middlelp, sizeof (middlelp), "(%s)", middlel); else strcpy (middlelp, middlel); if (needs_parens (middleh)) GNUNET_snprintf (middlehp, sizeof (middlehp), "(%s)", middleh); else strcpy (middlehp, middleh); if (needs_parens (after)) GNUNET_snprintf (afterp, sizeof (afterp), "(%s)", after); else strcpy (afterp, after); dots[0] = '\0'; for (xstep=step/16;xstep>0;xstep/=16) strcat (dots, "."); if (step >= 16) { if (strlen (middlel) > 0) recl = compute_policy ((start_port / step) * step, (start_port / step) * step + step - 1, step / 16, pp); else recl = GNUNET_strdup (""); if (strlen (middleh) > 0) rech = compute_policy ((end_port / step) * step, (end_port / step) * step + step - 1, step / 16, pp); else rech = GNUNET_strdup (""); } else { recl = GNUNET_strdup (""); rech = GNUNET_strdup (""); middlel[0] = '\0'; middlelp[0] = '\0'; middleh[0] = '\0'; middlehp[0] = '\0'; } if (needs_parens (recl)) GNUNET_asprintf (&reclp, "(%s)", recl); else reclp = GNUNET_strdup (recl); if (needs_parens (rech)) GNUNET_asprintf (&rechp, "(%s)", rech); else rechp = GNUNET_strdup (rech); if ( (strlen (middleh) > 0) && (strlen (rech) > 0) && (strlen (middlel) > 0) && (strlen (recl) > 0) ) { GNUNET_asprintf (&middle, "%s%s|%s%s", middlel, reclp, middleh, rechp); } else if ( (strlen (middleh) > 0) && (strlen (rech) > 0) ) { GNUNET_asprintf (&middle, "%s%s", middleh, rechp); } else if ( (strlen (middlel) > 0) && (strlen (recl) > 0) ) { GNUNET_asprintf (&middle, "%s%s", middlel, reclp); } else { middle = GNUNET_strdup (""); } if ( (strlen(before) > 0) && (strlen(after) > 0) ) { if (strlen (dots) > 0) { if (strlen (middle) > 0) GNUNET_asprintf (&ret, "(%s%s|%s|%s%s)", beforep, dots, middle, afterp, dots); else GNUNET_asprintf (&ret, "(%s|%s)%s", beforep, afterp, dots); } else { if (strlen (middle) > 0) GNUNET_asprintf (&ret, "(%s|%s|%s)", before, middle, after); else if (1 == step) GNUNET_asprintf (&ret, "%s|%s", before, after); else GNUNET_asprintf (&ret, "(%s|%s)", before, after); } } else if (strlen (before) > 0) { if (strlen (dots) > 0) { if (strlen (middle) > 0) GNUNET_asprintf (&ret, "(%s%s|%s)", beforep, dots, middle); else GNUNET_asprintf (&ret, "%s%s", beforep, dots); } else { if (strlen (middle) > 0) GNUNET_asprintf (&ret, "(%s|%s)", before, middle); else GNUNET_asprintf (&ret, "%s", before); } } else if (strlen (after) > 0) { if (strlen (dots) > 0) { if (strlen (middle) > 0) GNUNET_asprintf (&ret, "(%s|%s%s)", middle, afterp, dots); else GNUNET_asprintf (&ret, "%s%s", afterp, dots); } else { if (strlen (middle) > 0) GNUNET_asprintf (&ret, "%s|%s", middle, after); else GNUNET_asprintf (&ret, "%s", after); } } else if (strlen (middle) > 0) { GNUNET_asprintf (&ret, "%s", middle); } else { ret = GNUNET_strdup (""); } GNUNET_free (middle); GNUNET_free (reclp); GNUNET_free (rechp); GNUNET_free (recl); GNUNET_free (rech); return ret; } /** * Convert a port policy to a regular expression. Note: this is a * very simplistic implementation, we might want to consider doing * something more sophisiticated (resulting in smaller regular * expressions) at a later time. * * @param pp port policy to convert * @return NULL on error */ static char * port_to_regex (const struct GNUNET_STRINGS_PortPolicy *pp) { char *reg; char *ret; char *pos; unsigned int i; unsigned int cnt; if ( (0 == pp->start_port) || ( (1 == pp->start_port) && (0xFFFF == pp->end_port) && (GNUNET_NO == pp->negate_portrange)) ) return GNUNET_strdup ("...."); if ( (pp->start_port == pp->end_port) && (GNUNET_NO == pp->negate_portrange)) { GNUNET_asprintf (&ret, "%04X", pp->start_port); return ret; } if (pp->end_port < pp->start_port) return NULL; if (GNUNET_YES == pp->negate_portrange) { ret = compute_policy (0, 0xFFFF, 0x1000, pp); } else { cnt = pp->end_port - pp->start_port + 1; reg = GNUNET_malloc (cnt * 5 + 1); pos = reg; for (i=1;i<=0xFFFF;i++) { if ( (i >= pp->start_port) && (i <= pp->end_port) ) { if (pos == reg) { GNUNET_snprintf (pos, 5, "%04X", i); } else { GNUNET_snprintf (pos, 6, "|%04X", i); } pos += strlen (pos); } } GNUNET_asprintf (&ret, "(%s)", reg); GNUNET_free (reg); } return ret; } /** * Convert an address (IPv4 or IPv6) to a regex. * * @param addr address * @param mask network mask * @param len number of bytes in @a addr and @a mask * @return NULL on error, otherwise regex for the address */ static char * address_to_regex (const void *addr, const void *mask, size_t len) { const uint16_t *a = addr; const uint16_t *m = mask; char *ret; char *tmp; char *reg; unsigned int i; ret = NULL; GNUNET_assert (1 != (len % 2)); for (i=0;inetwork, &v4->netmask, sizeof (struct in_addr)); if (NULL == reg) return NULL; pp = port_to_regex (&v4->pp); if (NULL == pp) { GNUNET_free (reg); return NULL; } GNUNET_asprintf (&ret, "4-%s-%s", pp, reg); GNUNET_free (pp); GNUNET_free (reg); return ret; } /** * Convert a single line of an IPv4 policy to a regular expression. * * @param v6 line to convert * @return NULL on error */ static char * ipv6_to_regex (const struct GNUNET_STRINGS_IPv6NetworkPolicy *v6) { char *reg; char *pp; char *ret; reg = address_to_regex (&v6->network, &v6->netmask, sizeof (struct in6_addr)); if (NULL == reg) return NULL; pp = port_to_regex (&v6->pp); if (NULL == pp) { GNUNET_free (reg); return NULL; } GNUNET_asprintf (&ret, "6-%s-%s", pp, reg); GNUNET_free (pp); GNUNET_free (reg); return ret; } /** * Convert an exit policy to a regular expression. The exit policy * specifies a set of subnets this peer is willing to serve as an * exit for; the resulting regular expression will match the * IPv4 address strings as returned by 'GNUNET_TUN_ipv4toregexsearch'. * * @param policy exit policy specification * @return regular expression, NULL on error */ char * GNUNET_TUN_ipv4policy2regex (const char *policy) { struct GNUNET_STRINGS_IPv4NetworkPolicy *np; char *reg; char *tmp; char *line; unsigned int i; np = GNUNET_STRINGS_parse_ipv4_policy (policy); if (NULL == np) return NULL; reg = NULL; for (i=0; (0 == i) || (0 != np[i].network.s_addr); i++) { line = ipv4_to_regex (&np[i]); if (NULL == line) { GNUNET_free_non_null (reg); GNUNET_free (np); return NULL; } if (NULL == reg) { reg = line; } else { GNUNET_asprintf (&tmp, "%s|(%s)", reg, line); GNUNET_free (reg); GNUNET_free (line); reg = tmp; } if (0 == np[i].network.s_addr) break; } GNUNET_free (np); return reg; } /** * Convert an exit policy to a regular expression. The exit policy * specifies a set of subnets this peer is willing to serve as an * exit for; the resulting regular expression will match the * IPv6 address strings as returned by #GNUNET_TUN_ipv6toregexsearch(). * * @param policy exit policy specification * @return regular expression, NULL on error */ char * GNUNET_TUN_ipv6policy2regex (const char *policy) { struct in6_addr zero; struct GNUNET_STRINGS_IPv6NetworkPolicy *np; char *reg; char *tmp; char *line; unsigned int i; np = GNUNET_STRINGS_parse_ipv6_policy (policy); if (NULL == np) return NULL; reg = NULL; memset (&zero, 0, sizeof (struct in6_addr)); for (i=0; (0 == i) || (0 != memcmp (&zero, &np[i].network, sizeof (struct in6_addr))); i++) { line = ipv6_to_regex (&np[i]); if (NULL == line) { GNUNET_free_non_null (reg); GNUNET_free (np); return NULL; } if (NULL == reg) { reg = line; } else { GNUNET_asprintf (&tmp, "%s|(%s)", reg, line); GNUNET_free (reg); GNUNET_free (line); reg = tmp; } if (0 == memcmp (&zero, &np[i].network, sizeof (struct in6_addr))) break; } GNUNET_free (np); return reg; } /** * Hash the service name of a hosted service to the * hash code that is used to identify the service on * the network. * * @param service_name a string * @param hc corresponding hash */ void GNUNET_TUN_service_name_to_hash (const char *service_name, struct GNUNET_HashCode *hc) { GNUNET_CRYPTO_hash (service_name, strlen (service_name), hc); } /* end of regex.c */ gnunet-0.10.1/src/gnsrecord/0000755000175000017500000000000012320755626012657 500000000000000gnunet-0.10.1/src/gnsrecord/gnsrecord.c0000644000175000017500000001347312307322113014723 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnsrecord/gnsrecord.c * @brief API to access GNS record data * @author Martin Schanzenbach * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gnsrecord_plugin.h" #include "gnunet_tun_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) /** * Handle for a plugin. */ struct Plugin { /** * Name of the shared library. */ char *library_name; /** * Plugin API. */ struct GNUNET_GNSRECORD_PluginFunctions *api; }; /** * Array of our plugins. */ static struct Plugin **gns_plugins; /** * Size of the 'plugins' array. */ static unsigned int num_plugins; /** * Global to mark if we've run the initialization. */ static int once; /** * Add a plugin to the list managed by the block library. * * @param cls NULL * @param library_name name of the plugin * @param lib_ret the plugin API */ static void add_plugin (void *cls, const char *library_name, void *lib_ret) { struct GNUNET_GNSRECORD_PluginFunctions *api = lib_ret; struct Plugin *plugin; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Loading block plugin `%s'\n", library_name); plugin = GNUNET_new (struct Plugin); plugin->api = api; plugin->library_name = GNUNET_strdup (library_name); GNUNET_array_append (gns_plugins, num_plugins, plugin); } /** * Loads all plugins (lazy initialization). */ static void init () { if (1 == once) return; once = 1; GNUNET_PLUGIN_load_all ("libgnunet_plugin_gnsrecord_", NULL, &add_plugin, NULL); } /** * Dual function to #init(). */ void __attribute__ ((destructor)) GNSRECORD_fini () { unsigned int i; struct Plugin *plugin; for (i = 0; i < num_plugins; i++) { plugin = gns_plugins[i]; GNUNET_break (NULL == GNUNET_PLUGIN_unload (plugin->library_name, plugin->api)); GNUNET_free (plugin->library_name); GNUNET_free (plugin); } GNUNET_free_non_null (gns_plugins); gns_plugins = NULL; once = 0; num_plugins = 0; } /** * Convert the 'value' of a record to a string. * * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in @a data * @return NULL on error, otherwise human-readable representation of the value */ char * GNUNET_GNSRECORD_value_to_string (uint32_t type, const void *data, size_t data_size) { unsigned int i; struct Plugin *plugin; char *ret; init (); for (i = 0; i < num_plugins; i++) { plugin = gns_plugins[i]; if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls, type, data, data_size))) return ret; } return NULL; } /** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ int GNUNET_GNSRECORD_string_to_value (uint32_t type, const char *s, void **data, size_t *data_size) { unsigned int i; struct Plugin *plugin; init (); for (i = 0; i < num_plugins; i++) { plugin = gns_plugins[i]; if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls, type, s, data, data_size)) return GNUNET_OK; } return GNUNET_SYSERR; } /** * Convert a type name (i.e. "AAAA") to the corresponding number. * * @param dns_typename name to convert * @return corresponding number, UINT32_MAX on error */ uint32_t GNUNET_GNSRECORD_typename_to_number (const char *dns_typename) { unsigned int i; struct Plugin *plugin; uint32_t ret; init (); for (i = 0; i < num_plugins; i++) { plugin = gns_plugins[i]; if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls, dns_typename))) return ret; } return UINT32_MAX; } /** * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") * * @param type number of a type to convert * @return corresponding typestring, NULL on error */ const char * GNUNET_GNSRECORD_number_to_typename (uint32_t type) { unsigned int i; struct Plugin *plugin; const char * ret; init (); for (i = 0; i < num_plugins; i++) { plugin = gns_plugins[i]; if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls, type))) return ret; } return NULL; } /* end of gnsrecord.c */ gnunet-0.10.1/src/gnsrecord/test_gnsrecord_crypto.c0000644000175000017500000001025212230221077017354 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnsrecord/test_gnsrecord_crypto.c * @brief testcase for block creation, verification and decryption */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_gnsrecord_lib.h" #define RECORDS 5 #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TEST_REMOVE_RECORD_TYPE 4321 #define TEST_REMOVE_RECORD_DATALEN 255 #define TEST_REMOVE_RECORD_DATA 'b' static struct GNUNET_CRYPTO_EcdsaPrivateKey * privkey; static struct GNUNET_GNSRECORD_Data *s_rd; static char *s_name; static int res; static struct GNUNET_GNSRECORD_Data * create_record (int count) { unsigned int c; struct GNUNET_GNSRECORD_Data *rd; rd = GNUNET_malloc (count * sizeof (struct GNUNET_GNSRECORD_Data)); for (c = 0; c < count; c++) { rd[c].expiration_time = GNUNET_TIME_absolute_get().abs_value_us + 1000000000; rd[c].record_type = TEST_RECORD_TYPE; rd[c].data_size = TEST_RECORD_DATALEN; rd[c].data = GNUNET_malloc(TEST_RECORD_DATALEN); memset ((char *) rd[c].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); } return rd; } static void rd_decrypt_cb (void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { char rd_cmp_data[TEST_RECORD_DATALEN]; int c; GNUNET_assert (RECORDS == rd_count); GNUNET_assert (NULL != rd); memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN); for (c = 0; c < rd_count; c++) { GNUNET_assert (TEST_RECORD_TYPE == rd[c].record_type); GNUNET_assert (TEST_RECORD_DATALEN == rd[c].data_size); GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[c].data, TEST_RECORD_DATALEN)); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Block was decrypted successfully \n"); res = 0; } static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_GNSRECORD_Block *block; struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; /* load privat key */ char *hostkey_file; GNUNET_asprintf(&hostkey_file, "zonefiles%s%s", DIR_SEPARATOR_STR, "N0UJMP015AFUNR2BTNM3FKPBLG38913BL8IDMCO2H0A1LIB81960.zkey"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zonekey file `%s'\n", hostkey_file); privkey = GNUNET_CRYPTO_ecdsa_key_create_from_file(hostkey_file); GNUNET_free (hostkey_file); GNUNET_assert (privkey != NULL); struct GNUNET_TIME_Absolute expire = GNUNET_TIME_absolute_get(); /* get public key */ GNUNET_CRYPTO_ecdsa_key_get_public(privkey, &pubkey); /* create record */ s_name = "DUMMY.dummy.gnunet"; s_rd = create_record (RECORDS); /* Create block */ GNUNET_assert (NULL != (block = GNUNET_GNSRECORD_block_create (privkey, expire,s_name, s_rd, RECORDS))); GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_verify (block)); GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt (block, &pubkey, s_name, &rd_decrypt_cb, s_name)); GNUNET_free (block); } int main (int argc, char *argv[]) { static char *const argvx[] = { "test-gnsrecord-crypto", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; res = 1; GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-namestore-api", "nohelp", options, &run, &res); return res; } /* end of test_gnsrecord_crypto.c */ gnunet-0.10.1/src/gnsrecord/gnsrecord_misc.c0000644000175000017500000001744412236140650015745 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnsrecord/gnsrecord_misc.c * @brief MISC functions related to GNS records * @author Martin Schanzenbach * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_arm_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_tun_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) /** * Convert a UTF-8 string to UTF-8 lowercase * @param src source string * @return converted result */ char * GNUNET_GNSRECORD_string_to_lowercase (const char *src) { char *res; res = GNUNET_strdup (src); GNUNET_STRINGS_utf8_tolower (src, res); return res; } /** * Convert a zone key to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param z the zone key * @return string form; will be overwritten by next call to #GNUNET_GNSRECORD_z2s */ const char * GNUNET_GNSRECORD_z2s (const struct GNUNET_CRYPTO_EcdsaPublicKey *z) { static char buf[sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) * 8]; char *end; end = GNUNET_STRINGS_data_to_string ((const unsigned char *) z, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), buf, sizeof (buf)); if (NULL == end) { GNUNET_break (0); return NULL; } *end = '\0'; return buf; } /** * Compares if two records are equal (ignoring flags such * as authority, private and pending, but not relative vs. * absolute expiration time). * * @param a record * @param b record * @return #GNUNET_YES if the records are equal or #GNUNET_NO if they are not */ int GNUNET_GNSRECORD_records_cmp (const struct GNUNET_GNSRECORD_Data *a, const struct GNUNET_GNSRECORD_Data *b) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Comparing records\n"); if (a->record_type != b->record_type) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Record type %lu != %lu\n", a->record_type, b->record_type); return GNUNET_NO; } if ((a->expiration_time != b->expiration_time) && ((a->expiration_time != 0) && (b->expiration_time != 0))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Expiration time %llu != %llu\n", a->expiration_time, b->expiration_time); return GNUNET_NO; } if ((a->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS) != (b->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Flags %lu (%lu) != %lu (%lu)\n", a->flags, a->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS, b->flags, b->flags & GNUNET_GNSRECORD_RF_RCMP_FLAGS); return GNUNET_NO; } if (a->data_size != b->data_size) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Data size %lu != %lu\n", a->data_size, b->data_size); return GNUNET_NO; } if (0 != memcmp (a->data, b->data, a->data_size)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Data contents do not match\n"); return GNUNET_NO; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Records are equal\n"); return GNUNET_YES; } /** * Returns the expiration time of the given block of records. The block * expiration time is the expiration time of the record with smallest * expiration time. * * @param rd_count number of records given in @a rd * @param rd array of records * @return absolute expiration time */ struct GNUNET_TIME_Absolute GNUNET_GNSRECORD_record_get_expiration_time (unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { unsigned int c; unsigned int c2; struct GNUNET_TIME_Absolute expire; struct GNUNET_TIME_Absolute at; struct GNUNET_TIME_Relative rt; struct GNUNET_TIME_Absolute at_shadow; struct GNUNET_TIME_Relative rt_shadow; if (NULL == rd) return GNUNET_TIME_UNIT_ZERO_ABS; expire = GNUNET_TIME_UNIT_FOREVER_ABS; for (c = 0; c < rd_count; c++) { if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) { rt.rel_value_us = rd[c].expiration_time; at = GNUNET_TIME_relative_to_absolute (rt); } else { at.abs_value_us = rd[c].expiration_time; } for (c2 = 0; c2 < rd_count; c2++) { /* Check for shadow record */ if ((c == c2) || (rd[c].record_type != rd[c2].record_type) || (0 == (rd[c2].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD))) continue; /* We have a shadow record */ if (0 != (rd[c2].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) { rt_shadow.rel_value_us = rd[2].expiration_time; at_shadow = GNUNET_TIME_relative_to_absolute (rt_shadow); } else { at_shadow.abs_value_us = rd[c2].expiration_time; } at = GNUNET_TIME_absolute_max (at, at_shadow); } expire = GNUNET_TIME_absolute_min (at, expire); } LOG (GNUNET_ERROR_TYPE_DEBUG, "Determined expiration time for block with %u records to be %s\n", rd_count, GNUNET_STRINGS_absolute_time_to_string (expire)); return expire; } /** * Test if a given record is expired. * * @return #GNUNET_YES if the record is expired, * #GNUNET_NO if not */ int GNUNET_GNSRECORD_is_expired (const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_TIME_Absolute at; if (0 != (rd->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) return GNUNET_NO; at.abs_value_us = rd->expiration_time; return (0 == GNUNET_TIME_absolute_get_remaining (at).rel_value_us) ? GNUNET_YES : GNUNET_NO; } /** * Convert public key to the respective absolute domain name in the * ".zkey" pTLD. * This is one of the very few calls in the entire API that is * NOT reentrant! * * @param pkey a public key with a point on the eliptic curve * @return string "X.zkey" where X is the public * key in an encoding suitable for DNS labels. */ const char * GNUNET_GNSRECORD_pkey_to_zkey (const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey) { static char ret[128]; char *pkeys; pkeys = GNUNET_CRYPTO_ecdsa_public_key_to_string (pkey); GNUNET_snprintf (ret, sizeof (ret), "%s.zkey", pkeys); GNUNET_free (pkeys); return ret; } /** * Convert an absolute domain name in the ".zkey" pTLD to the * respective public key. * * @param zkey string "X.zkey" where X is the coordinates of the public * key in an encoding suitable for DNS labels. * @param pkey set to a public key on the eliptic curve * @return #GNUNET_SYSERR if @a zkey has the wrong syntax */ int GNUNET_GNSRECORD_zkey_to_pkey (const char *zkey, struct GNUNET_CRYPTO_EcdsaPublicKey *pkey) { char *cpy; char *dot; const char *x; cpy = GNUNET_strdup (zkey); x = cpy; if (NULL == (dot = strchr (x, (int) '.'))) goto error; *dot = '\0'; if (0 != strcasecmp (dot + 1, "zkey")) goto error; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (x, strlen (x), pkey)) goto error; GNUNET_free (cpy); return GNUNET_OK; error: GNUNET_free (cpy); return GNUNET_SYSERR; } /* end of gnsrecord_misc.c */ gnunet-0.10.1/src/gnsrecord/test_gnsrecord_serialization.c0000644000175000017500000000707212227705277020736 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnsrecord/test_gnsrecord_serialization.c * @brief testcase for gnsrecord_serialization.c */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_gnsrecord_lib.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100) static int res; static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { size_t len; int c; int rd_count = 3; size_t data_len; struct GNUNET_GNSRECORD_Data src[rd_count]; memset(src, '\0', rd_count * sizeof (struct GNUNET_GNSRECORD_Data)); data_len = 0; for (c = 0; c < rd_count; c++) { src[c].record_type = c+1; src[c].data_size = data_len; src[c].data = GNUNET_malloc (data_len); /* Setting data to data_len * record_type */ memset ((char *) src[c].data, 'a', data_len); data_len += 10; } res = 0; len = GNUNET_GNSRECORD_records_get_size(rd_count, src); char rd_ser[len]; GNUNET_assert (len == GNUNET_GNSRECORD_records_serialize(rd_count, src, len, rd_ser)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Serialized data len: %u\n",len); GNUNET_assert (rd_ser != NULL); struct GNUNET_GNSRECORD_Data dst[rd_count]; GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_records_deserialize (len, rd_ser, rd_count, dst)); GNUNET_assert (dst != NULL); for (c = 0; c < rd_count; c++) { if (src[c].data_size != dst[c].data_size) { GNUNET_break (0); res = 1; } if (src[c].expiration_time != dst[c].expiration_time) { GNUNET_break (0); res = 1; } if (src[c].flags != dst[c].flags) { GNUNET_break (0); res = 1; } if (src[c].record_type != dst[c].record_type) { GNUNET_break (0); res = 1; } size_t data_size = src[c].data_size; char data[data_size]; memset (data, 'a', data_size); if (0 != memcmp (data, dst[c].data, data_size)) { GNUNET_break (0); res = 1; } if (0 != memcmp (data, src[c].data, data_size)) { GNUNET_break (0); res = 1; } if (0 != memcmp (src[c].data, dst[c].data, src[c].data_size)) { GNUNET_break (0); res = 1; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Element [%i]: EQUAL\n", c); } for (c = 0; c < rd_count; c++) { GNUNET_free ((void *)src[c].data); } } int main (int argcx, char *argvx[]) { static char *const argv[] = { "test_gnsrecord_serialization", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; res = 1; GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, "test_namestore_record_serialization", "nohelp", options, &run, &res); return res; } /* end of test_gnsrecord_serialization.c */ gnunet-0.10.1/src/gnsrecord/Makefile.in0000644000175000017500000012636312320752062014646 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_gnsrecord_crypto$(EXEEXT) \ test_gnsrecord_serialization$(EXEEXT) \ test_gnsrecord_block_expiration$(EXEEXT) @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) subdir = src/gnsrecord DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = libgnunet_plugin_gnsrecord_dns_la_DEPENDENCIES = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunet_plugin_gnsrecord_dns_la_OBJECTS = \ plugin_gnsrecord_dns.lo libgnunet_plugin_gnsrecord_dns_la_OBJECTS = \ $(am_libgnunet_plugin_gnsrecord_dns_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_gnsrecord_dns_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_gnsrecord_dns_la_LDFLAGS) $(LDFLAGS) -o $@ libgnunetgnsrecord_la_DEPENDENCIES = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(am__DEPENDENCIES_1) am_libgnunetgnsrecord_la_OBJECTS = gnsrecord.lo \ gnsrecord_serialization.lo gnsrecord_crypto.lo \ gnsrecord_misc.lo libgnunetgnsrecord_la_OBJECTS = $(am_libgnunetgnsrecord_la_OBJECTS) libgnunetgnsrecord_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetgnsrecord_la_LDFLAGS) \ $(LDFLAGS) -o $@ am_test_gnsrecord_block_expiration_OBJECTS = \ test_gnsrecord_block_expiration.$(OBJEXT) test_gnsrecord_block_expiration_OBJECTS = \ $(am_test_gnsrecord_block_expiration_OBJECTS) test_gnsrecord_block_expiration_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnsrecord_crypto_OBJECTS = test_gnsrecord_crypto.$(OBJEXT) test_gnsrecord_crypto_OBJECTS = $(am_test_gnsrecord_crypto_OBJECTS) test_gnsrecord_crypto_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la am_test_gnsrecord_serialization_OBJECTS = \ test_gnsrecord_serialization.$(OBJEXT) test_gnsrecord_serialization_OBJECTS = \ $(am_test_gnsrecord_serialization_OBJECTS) test_gnsrecord_serialization_DEPENDENCIES = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_gnsrecord_dns_la_SOURCES) \ $(libgnunetgnsrecord_la_SOURCES) \ $(test_gnsrecord_block_expiration_SOURCES) \ $(test_gnsrecord_crypto_SOURCES) \ $(test_gnsrecord_serialization_SOURCES) DIST_SOURCES = $(libgnunet_plugin_gnsrecord_dns_la_SOURCES) \ $(libgnunetgnsrecord_la_SOURCES) \ $(test_gnsrecord_block_expiration_SOURCES) \ $(test_gnsrecord_crypto_SOURCES) \ $(test_gnsrecord_serialization_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir = $(pkgdatadir)/config.d/ @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIBS = -lgcov @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; lib_LTLIBRARIES = \ libgnunetgnsrecord.la libgnunetgnsrecord_la_SOURCES = \ gnsrecord.c \ gnsrecord_serialization.c \ gnsrecord_crypto.c \ gnsrecord_misc.c libgnunetgnsrecord_la_LIBADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetgnsrecord_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 plugin_LTLIBRARIES = \ libgnunet_plugin_gnsrecord_dns.la libgnunet_plugin_gnsrecord_dns_la_SOURCES = \ plugin_gnsrecord_dns.c libgnunet_plugin_gnsrecord_dns_la_LIBADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_gnsrecord_dns_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) EXTRA_DIST = \ $(check_SCRIPTS) test_gnsrecord_serialization_SOURCES = \ test_gnsrecord_serialization.c test_gnsrecord_serialization_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnsrecord_block_expiration_SOURCES = \ test_gnsrecord_block_expiration.c test_gnsrecord_block_expiration_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnsrecord_crypto_SOURCES = \ test_gnsrecord_crypto.c test_gnsrecord_crypto_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gnsrecord/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/gnsrecord/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_gnsrecord_dns.la: $(libgnunet_plugin_gnsrecord_dns_la_OBJECTS) $(libgnunet_plugin_gnsrecord_dns_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_gnsrecord_dns_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_gnsrecord_dns_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_gnsrecord_dns_la_OBJECTS) $(libgnunet_plugin_gnsrecord_dns_la_LIBADD) $(LIBS) libgnunetgnsrecord.la: $(libgnunetgnsrecord_la_OBJECTS) $(libgnunetgnsrecord_la_DEPENDENCIES) $(EXTRA_libgnunetgnsrecord_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetgnsrecord_la_LINK) -rpath $(libdir) $(libgnunetgnsrecord_la_OBJECTS) $(libgnunetgnsrecord_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list test_gnsrecord_block_expiration$(EXEEXT): $(test_gnsrecord_block_expiration_OBJECTS) $(test_gnsrecord_block_expiration_DEPENDENCIES) $(EXTRA_test_gnsrecord_block_expiration_DEPENDENCIES) @rm -f test_gnsrecord_block_expiration$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnsrecord_block_expiration_OBJECTS) $(test_gnsrecord_block_expiration_LDADD) $(LIBS) test_gnsrecord_crypto$(EXEEXT): $(test_gnsrecord_crypto_OBJECTS) $(test_gnsrecord_crypto_DEPENDENCIES) $(EXTRA_test_gnsrecord_crypto_DEPENDENCIES) @rm -f test_gnsrecord_crypto$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnsrecord_crypto_OBJECTS) $(test_gnsrecord_crypto_LDADD) $(LIBS) test_gnsrecord_serialization$(EXEEXT): $(test_gnsrecord_serialization_OBJECTS) $(test_gnsrecord_serialization_DEPENDENCIES) $(EXTRA_test_gnsrecord_serialization_DEPENDENCIES) @rm -f test_gnsrecord_serialization$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gnsrecord_serialization_OBJECTS) $(test_gnsrecord_serialization_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnsrecord.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnsrecord_crypto.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnsrecord_misc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnsrecord_serialization.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_gnsrecord_dns.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnsrecord_block_expiration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnsrecord_crypto.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gnsrecord_serialization.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_gnsrecord_crypto.log: test_gnsrecord_crypto$(EXEEXT) @p='test_gnsrecord_crypto$(EXEEXT)'; \ b='test_gnsrecord_crypto'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnsrecord_serialization.log: test_gnsrecord_serialization$(EXEEXT) @p='test_gnsrecord_serialization$(EXEEXT)'; \ b='test_gnsrecord_serialization'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_gnsrecord_block_expiration.log: test_gnsrecord_block_expiration$(EXEEXT) @p='test_gnsrecord_block_expiration$(EXEEXT)'; \ b='test_gnsrecord_block_expiration'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-pluginLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-pluginLTLIBRARIES install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-libLTLIBRARIES \ uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/gnsrecord/plugin_gnsrecord_dns.c0000644000175000017500000004226712255010512017147 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnsrecord/plugin_gnsrecord_dns.c * @brief gnsrecord plugin to provide the API for basic DNS records * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_gnsrecord_plugin.h" /** * Convert the 'value' of a record to a string. * * @param cls closure, unused * @param type type of the record * @param data value in binary encoding * @param data_size number of bytes in @a data * @return NULL on error, otherwise human-readable representation of the value */ static char * dns_value_to_string (void *cls, uint32_t type, const void *data, size_t data_size) { const char *cdata; char* result; char tmp[INET6_ADDRSTRLEN]; switch (type) { case GNUNET_DNSPARSER_TYPE_A: if (data_size != sizeof (struct in_addr)) return NULL; if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp))) return NULL; return GNUNET_strdup (tmp); case GNUNET_DNSPARSER_TYPE_NS: { char *ns; size_t off; off = 0; ns = GNUNET_DNSPARSER_parse_name (data, data_size, &off); if ( (NULL == ns) || (off != data_size) ) { GNUNET_break_op (0); GNUNET_free_non_null (ns); return NULL; } return ns; } case GNUNET_DNSPARSER_TYPE_CNAME: { char *cname; size_t off; off = 0; cname = GNUNET_DNSPARSER_parse_name (data, data_size, &off); if ( (NULL == cname) || (off != data_size) ) { GNUNET_break_op (0); GNUNET_free_non_null (cname); return NULL; } return cname; } case GNUNET_DNSPARSER_TYPE_SOA: { struct GNUNET_DNSPARSER_SoaRecord *soa; size_t off; off = 0; soa = GNUNET_DNSPARSER_parse_soa (data, data_size, &off); if ( (NULL == soa) || (off != data_size) ) { GNUNET_break_op (0); if (NULL != soa) GNUNET_DNSPARSER_free_soa (soa); return NULL; } GNUNET_asprintf (&result, "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu", soa->rname, soa->mname, soa->serial, soa->refresh, soa->retry, soa->expire, soa->minimum_ttl); GNUNET_DNSPARSER_free_soa (soa); return result; } case GNUNET_DNSPARSER_TYPE_PTR: { char *ptr; size_t off; off = 0; ptr = GNUNET_DNSPARSER_parse_name (data, data_size, &off); if ( (NULL == ptr) || (off != data_size) ) { GNUNET_break_op (0); GNUNET_free_non_null (ptr); return NULL; } return ptr; } case GNUNET_DNSPARSER_TYPE_CERT: { struct GNUNET_DNSPARSER_CertRecord *cert; size_t off; char *base64; int len; off = 0; cert = GNUNET_DNSPARSER_parse_cert (data, data_size, &off); if ( (NULL == cert) || (off != data_size) ) { GNUNET_break_op (0); GNUNET_DNSPARSER_free_cert (cert); return NULL; } len = GNUNET_STRINGS_base64_encode (cert->certificate_data, cert->certificate_size, &base64); GNUNET_asprintf (&result, "%u %u %u %.*s", cert->cert_type, cert->cert_tag, cert->algorithm, len, base64); GNUNET_free (base64); GNUNET_DNSPARSER_free_cert (cert); return result; } case GNUNET_DNSPARSER_TYPE_MX: { struct GNUNET_DNSPARSER_MxRecord *mx; size_t off; off = 0; mx = GNUNET_DNSPARSER_parse_mx (data, data_size, &off); if ( (NULL == mx) || (off != data_size) ) { GNUNET_break_op (0); GNUNET_DNSPARSER_free_mx (mx); return NULL; } GNUNET_asprintf (&result, "%hu,%s", mx->preference, mx->mxhost); GNUNET_DNSPARSER_free_mx (mx); return result; } case GNUNET_DNSPARSER_TYPE_TXT: return GNUNET_strndup (data, data_size); case GNUNET_DNSPARSER_TYPE_AAAA: if (data_size != sizeof (struct in6_addr)) return NULL; if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp))) return NULL; return GNUNET_strdup (tmp); case GNUNET_DNSPARSER_TYPE_SRV: { struct GNUNET_DNSPARSER_SrvRecord *srv; size_t off; off = 0; srv = GNUNET_DNSPARSER_parse_srv ("+", /* FIXME: is this OK? */ data, data_size, &off); if ( (NULL == srv) || (off != data_size) ) { GNUNET_break_op (0); if (NULL != srv) GNUNET_DNSPARSER_free_srv (srv); return NULL; } GNUNET_asprintf (&result, "%d %d %d _%s._%s.%s", srv->priority, srv->weight, srv->port, srv->service, srv->proto, srv->domain_name); GNUNET_DNSPARSER_free_srv (srv); return result; } case GNUNET_DNSPARSER_TYPE_TLSA: { const struct GNUNET_TUN_DnsTlsaRecord *tlsa; char* tlsa_str; cdata = data; if ( (data_size <= sizeof (struct GNUNET_TUN_DnsTlsaRecord)) || ('\0' != cdata[data_size - 1]) ) return NULL; /* malformed */ tlsa = data; if (0 == GNUNET_asprintf (&tlsa_str, "%c %c %c %s", tlsa->usage, tlsa->selector, tlsa->matching_type, (const char *) &tlsa[1])) { GNUNET_free (tlsa_str); return NULL; } return tlsa_str; } default: return NULL; } } /** * Convert human-readable version of a 'value' of a record to the binary * representation. * * @param cls closure, unused * @param type type of the record * @param s human-readable string * @param data set to value in binary encoding (will be allocated) * @param data_size set to number of bytes in @a data * @return #GNUNET_OK on success */ static int dns_string_to_value (void *cls, uint32_t type, const char *s, void **data, size_t *data_size) { struct in_addr value_a; struct in6_addr value_aaaa; struct GNUNET_TUN_DnsTlsaRecord *tlsa; if (NULL == s) return GNUNET_SYSERR; switch (type) { case GNUNET_DNSPARSER_TYPE_A: if (1 != inet_pton (AF_INET, s, &value_a)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse IPv4 address `%s'\n"), s); return GNUNET_SYSERR; } *data = GNUNET_new (struct in_addr); memcpy (*data, &value_a, sizeof (value_a)); *data_size = sizeof (value_a); return GNUNET_OK; case GNUNET_DNSPARSER_TYPE_NS: { char nsbuf[256]; size_t off; off = 0; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof (nsbuf), &off, s)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize NS record with value `%s'\n"), s); return GNUNET_SYSERR; } *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, nsbuf, off); return GNUNET_OK; } case GNUNET_DNSPARSER_TYPE_CNAME: { char cnamebuf[256]; size_t off; off = 0; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (cnamebuf, sizeof (cnamebuf), &off, s)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize CNAME record with value `%s'\n"), s); return GNUNET_SYSERR; } *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, cnamebuf, off); return GNUNET_OK; } case GNUNET_DNSPARSER_TYPE_CERT: { char *sdup; const char *typep; const char *keyp; const char *algp; const char *certp; unsigned int type; unsigned int key; unsigned int alg; size_t cert_size; char *cert_data; struct GNUNET_DNSPARSER_CertRecord cert; sdup = GNUNET_strdup (s); typep = strtok (sdup, " "); /* TODO: add typep mnemonic conversion according to RFC 4398 */ if ( (NULL == typep) || (1 != sscanf (typep, "%u", &type)) || (type > UINT16_MAX) ) { GNUNET_free (sdup); return GNUNET_SYSERR; } keyp = strtok (NULL, " "); if ( (NULL == keyp) || (1 != sscanf (keyp, "%u", &key)) || (key > UINT16_MAX) ) { GNUNET_free (sdup); return GNUNET_SYSERR; } algp = strtok (NULL, " "); /* TODO: add algp mnemonic conversion according to RFC 4398/RFC 4034 */ if ( (NULL == algp) || (1 != sscanf (algp, "%u", &alg)) || (alg > UINT8_MAX) ) { GNUNET_free (sdup); return GNUNET_SYSERR; } certp = strtok (NULL, " "); if ( (NULL == certp) || (0 == strlen (certp) ) ) { GNUNET_free (sdup); return GNUNET_SYSERR; } cert_size = GNUNET_STRINGS_base64_decode (certp, strlen (certp), &cert_data); GNUNET_free (sdup); cert.cert_type = type; cert.cert_tag = key; cert.algorithm = alg; cert.certificate_size = cert_size; cert.certificate_data = cert_data; { char certbuf[cert_size + sizeof (struct GNUNET_TUN_DnsCertRecord)]; size_t off; off = 0; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_cert (certbuf, sizeof (certbuf), &off, &cert)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize CERT record with %u bytes\n"), (unsigned int) cert_size); GNUNET_free (cert_data); return GNUNET_SYSERR; } GNUNET_free (cert_data); *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, certbuf, off); } GNUNET_free (cert_data); return GNUNET_OK; } case GNUNET_DNSPARSER_TYPE_SOA: { struct GNUNET_DNSPARSER_SoaRecord soa; char soabuf[540]; char soa_rname[253 + 1]; char soa_mname[253 + 1]; unsigned int soa_serial; unsigned int soa_refresh; unsigned int soa_retry; unsigned int soa_expire; unsigned int soa_min; size_t off; if (7 != SSCANF (s, "rname=%253s mname=%253s %u,%u,%u,%u,%u", soa_rname, soa_mname, &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse SOA record `%s'\n"), s); return GNUNET_SYSERR; } soa.mname = soa_mname; soa.rname = soa_rname; soa.serial = (uint32_t) soa_serial; soa.refresh =(uint32_t) soa_refresh; soa.retry = (uint32_t) soa_retry; soa.expire = (uint32_t) soa_expire; soa.minimum_ttl = (uint32_t) soa_min; off = 0; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_soa (soabuf, sizeof (soabuf), &off, &soa)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize SOA record with mname `%s' and rname `%s'\n"), soa_mname, soa_rname); return GNUNET_SYSERR; } *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, soabuf, off); return GNUNET_OK; } case GNUNET_DNSPARSER_TYPE_PTR: { char ptrbuf[256]; size_t off; off = 0; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (ptrbuf, sizeof (ptrbuf), &off, s)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize PTR record with value `%s'\n"), s); return GNUNET_SYSERR; } *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, ptrbuf, off); return GNUNET_OK; } case GNUNET_DNSPARSER_TYPE_MX: { struct GNUNET_DNSPARSER_MxRecord mx; char mxbuf[258]; char mxhost[253 + 1]; uint16_t mx_pref; size_t off; if (2 != SSCANF(s, "%hu,%253s", &mx_pref, mxhost)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse MX record `%s'\n"), s); return GNUNET_SYSERR; } mx.preference = mx_pref; mx.mxhost = mxhost; off = 0; if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_mx (mxbuf, sizeof (mxbuf), &off, &mx)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to serialize MX record with hostname `%s'\n"), mxhost); return GNUNET_SYSERR; } *data_size = off; *data = GNUNET_malloc (off); memcpy (*data, mxbuf, off); return GNUNET_OK; } case GNUNET_DNSPARSER_TYPE_SRV: GNUNET_break (0); // FIXME: not implemented! return GNUNET_SYSERR; case GNUNET_DNSPARSER_TYPE_TXT: *data = GNUNET_strdup (s); *data_size = strlen (s); return GNUNET_OK; case GNUNET_DNSPARSER_TYPE_AAAA: if (1 != inet_pton (AF_INET6, s, &value_aaaa)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse IPv6 address `%s'\n"), s); return GNUNET_SYSERR; } *data = GNUNET_new (struct in6_addr); *data_size = sizeof (struct in6_addr); memcpy (*data, &value_aaaa, sizeof (value_aaaa)); return GNUNET_OK; case GNUNET_DNSPARSER_TYPE_TLSA: *data_size = sizeof (struct GNUNET_TUN_DnsTlsaRecord) + strlen (s) - 6; *data = tlsa = GNUNET_malloc (*data_size); if (4 != SSCANF (s, "%c %c %c %s", &tlsa->usage, &tlsa->selector, &tlsa->matching_type, (char*)&tlsa[1])) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to parse TLSA record string `%s'\n"), s); *data_size = 0; GNUNET_free (tlsa); return GNUNET_SYSERR; } return GNUNET_OK; default: return GNUNET_SYSERR; } } /** * Mapping of record type numbers to human-readable * record type names. */ static struct { const char *name; uint32_t number; } name_map[] = { { "A", GNUNET_DNSPARSER_TYPE_A }, { "NS", GNUNET_DNSPARSER_TYPE_NS }, { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME }, { "SOA", GNUNET_DNSPARSER_TYPE_SOA }, { "PTR", GNUNET_DNSPARSER_TYPE_PTR }, { "MX", GNUNET_DNSPARSER_TYPE_MX }, { "TXT", GNUNET_DNSPARSER_TYPE_TXT }, { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA }, { "TLSA", GNUNET_DNSPARSER_TYPE_TLSA }, { NULL, UINT32_MAX } }; /** * Convert a type name (i.e. "AAAA") to the corresponding number. * * @param cls closure, unused * @param dns_typename name to convert * @return corresponding number, UINT32_MAX on error */ static uint32_t dns_typename_to_number (void *cls, const char *dns_typename) { unsigned int i; i=0; while ( (name_map[i].name != NULL) && (0 != strcasecmp (dns_typename, name_map[i].name)) ) i++; return name_map[i].number; } /** * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") * * @param cls closure, unused * @param type number of a type to convert * @return corresponding typestring, NULL on error */ static const char * dns_number_to_typename (void *cls, uint32_t type) { unsigned int i; i=0; while ( (name_map[i].name != NULL) && (type != name_map[i].number) ) i++; return name_map[i].name; } /** * Entry point for the plugin. * * @param cls NULL * @return the exported block API */ void * libgnunet_plugin_gnsrecord_dns_init (void *cls) { struct GNUNET_GNSRECORD_PluginFunctions *api; api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions); api->value_to_string = &dns_value_to_string; api->string_to_value = &dns_string_to_value; api->typename_to_number = &dns_typename_to_number; api->number_to_typename = &dns_number_to_typename; return api; } /** * Exit point from the plugin. * * @param cls the return value from #libgnunet_plugin_block_test_init * @return NULL */ void * libgnunet_plugin_gnsrecord_dns_done (void *cls) { struct GNUNET_GNSRECORD_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_gnsrecord_dns.c */ gnunet-0.10.1/src/gnsrecord/gnsrecord_serialization.c0000644000175000017500000001211712245644744017674 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnsrecord/gnsrecord_serialization.c * @brief API to serialize and deserialize GNS records * @author Martin Schanzenbach * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_arm_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_tun_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) GNUNET_NETWORK_STRUCT_BEGIN /** * Internal format of a record in the serialized form. */ struct NetworkRecord { /** * Expiration time for the DNS record; relative or absolute depends * on 'flags', network byte order. */ uint64_t expiration_time GNUNET_PACKED; /** * Number of bytes in 'data', network byte order. */ uint32_t data_size GNUNET_PACKED; /** * Type of the GNS/DNS record, network byte order. */ uint32_t record_type GNUNET_PACKED; /** * Flags for the record, network byte order. */ uint32_t flags GNUNET_PACKED; }; GNUNET_NETWORK_STRUCT_END /** * Calculate how many bytes we will need to serialize the given * records. * * @param rd_count number of records in the rd array * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements * @return the required size to serialize */ size_t GNUNET_GNSRECORD_records_get_size (unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd) { unsigned int i; size_t ret; ret = sizeof (struct NetworkRecord) * rd_count; for (i=0;i= ret); ret += rd[i].data_size; } return ret; } /** * Serialize the given records to the given destination buffer. * * @param rd_count number of records in the rd array * @param rd array of #GNUNET_GNSRECORD_Data with @a rd_count elements * @param dest_size size of the destination array * @param dest where to write the result * @return the size of serialized records, -1 if records do not fit */ ssize_t GNUNET_GNSRECORD_records_serialize (unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest) { struct NetworkRecord rec; unsigned int i; size_t off; off = 0; for (i=0;i dest_size) return -1; memcpy (&dest[off], &rec, sizeof (rec)); off += sizeof (rec); if (off + rd[i].data_size > dest_size) return -1; memcpy (&dest[off], rd[i].data, rd[i].data_size); off += rd[i].data_size; } return off; } /** * Deserialize the given records to the given destination. * * @param len size of the serialized record data * @param src the serialized record data * @param rd_count number of records in the rd array * @param dest where to put the data * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int GNUNET_GNSRECORD_records_deserialize (size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest) { struct NetworkRecord rec; unsigned int i; size_t off; off = 0; for (i=0;i len) return GNUNET_SYSERR; memcpy (&rec, &src[off], sizeof (rec)); dest[i].expiration_time = GNUNET_ntohll (rec.expiration_time); dest[i].data_size = ntohl ((uint32_t) rec.data_size); dest[i].record_type = ntohl (rec.record_type); dest[i].flags = ntohl (rec.flags); off += sizeof (rec); if (off + dest[i].data_size > len) return GNUNET_SYSERR; dest[i].data = &src[off]; off += dest[i].data_size; #if 0 LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserialized record %u with flags %d and expiration time %llu\n", i, dest[i].flags, (unsigned long long) dest[i].expiration_time); #endif } return GNUNET_OK; } /* end of gnsrecord_serialization.c */ gnunet-0.10.1/src/gnsrecord/Makefile.am0000644000175000017500000000420112320751517014623 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include plugindir = $(libdir)/gnunet pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIBS = -lgcov endif check_PROGRAMS = \ test_gnsrecord_crypto \ test_gnsrecord_serialization \ test_gnsrecord_block_expiration if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = \ $(check_PROGRAMS) \ $(check_SCRIPTS) endif lib_LTLIBRARIES = \ libgnunetgnsrecord.la libgnunetgnsrecord_la_SOURCES = \ gnsrecord.c \ gnsrecord_serialization.c \ gnsrecord_crypto.c \ gnsrecord_misc.c libgnunetgnsrecord_la_LIBADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) libgnunetgnsrecord_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 plugin_LTLIBRARIES = \ libgnunet_plugin_gnsrecord_dns.la libgnunet_plugin_gnsrecord_dns_la_SOURCES = \ plugin_gnsrecord_dns.c libgnunet_plugin_gnsrecord_dns_la_LIBADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(LTLIBINTL) libgnunet_plugin_gnsrecord_dns_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) EXTRA_DIST = \ $(check_SCRIPTS) test_gnsrecord_serialization_SOURCES = \ test_gnsrecord_serialization.c test_gnsrecord_serialization_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnsrecord_block_expiration_SOURCES = \ test_gnsrecord_block_expiration.c test_gnsrecord_block_expiration_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la test_gnsrecord_crypto_SOURCES = \ test_gnsrecord_crypto.c test_gnsrecord_crypto_LDADD = \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet-0.10.1/src/gnsrecord/gnsrecord_crypto.c0000644000175000017500000002460512255055174016336 00000000000000/* This file is part of GNUnet. (C) 2009-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnsrecord/gnsrecord_crypto.c * @brief API for GNS record-related crypto * @author Martin Schanzenbach * @author Matthias Wachs * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_signatures.h" #include "gnunet_arm_service.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_tun_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) /** * Derive session key and iv from label and public key. * * @param iv initialization vector to initialize * @param skey session key to initialize * @param label label to use for KDF * @param pub public key to use for KDF */ static void derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, struct GNUNET_CRYPTO_SymmetricSessionKey *skey, const char *label, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) { static const char ctx_key[] = "gns-aes-ctx-key"; static const char ctx_iv[] = "gns-aes-ctx-iv"; GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), label, strlen (label), ctx_key, strlen (ctx_key), NULL, 0); GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), label, strlen (label), ctx_iv, strlen (ctx_iv), NULL, 0); } /** * Sign name and records * * @param key the private key * @param expire block expiration * @param label the name for the records * @param rd record data * @param rd_count number of records * @return NULL on error (block too large) */ struct GNUNET_GNSRECORD_Block * GNUNET_GNSRECORD_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count) { size_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); char payload[sizeof (uint32_t) + payload_len]; struct GNUNET_GNSRECORD_Block *block; struct GNUNET_CRYPTO_EcdsaPublicKey pkey; struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_SymmetricSessionKey skey; struct GNUNET_GNSRECORD_Data rdc[rd_count]; uint32_t rd_count_nbo; unsigned int i; struct GNUNET_TIME_Absolute now; if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE) return NULL; /* convert relative to absolute times */ now = GNUNET_TIME_absolute_get (); for (i=0;ipurpose.size = htonl (sizeof (uint32_t) + payload_len + sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO)); block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); block->expiration_time = GNUNET_TIME_absolute_hton (expire); /* encrypt and sign */ dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key, label, "gns"); GNUNET_CRYPTO_ecdsa_key_get_public (dkey, &block->derived_key); GNUNET_CRYPTO_ecdsa_key_get_public (key, &pkey); derive_block_aes_key (&iv, &skey, label, &pkey); GNUNET_break (payload_len + sizeof (uint32_t) == GNUNET_CRYPTO_symmetric_encrypt (payload, payload_len + sizeof (uint32_t), &skey, &iv, &block[1])); if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (dkey, &block->purpose, &block->signature)) { GNUNET_break (0); GNUNET_free (dkey); GNUNET_free (block); return NULL; } GNUNET_free (dkey); return block; } /** * Check if a signature is valid. This API is used by the GNS Block * to validate signatures received from the network. * * @param block block to verify * @return #GNUNET_OK if the signature is valid */ int GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block) { return GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, &block->purpose, &block->signature, &block->derived_key); } /** * Decrypt block. * * @param block block to decrypt * @param zone_key public key of the zone * @param label the name for the records * @param proc function to call with the result * @param proc_cls closure for proc * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was * not well-formed */ int GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls) { size_t payload_len = ntohl (block->purpose.size) - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) - sizeof (struct GNUNET_TIME_AbsoluteNBO); struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_SymmetricSessionKey skey; if (ntohl (block->purpose.size) < sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO)) { GNUNET_break_op (0); return GNUNET_SYSERR; } derive_block_aes_key (&iv, &skey, label, zone_key); { char payload[payload_len]; uint32_t rd_count; GNUNET_break (payload_len == GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len, &skey, &iv, payload)); memcpy (&rd_count, payload, sizeof (uint32_t)); rd_count = ntohl (rd_count); if (rd_count > 2048) { /* limit to sane value */ GNUNET_break_op (0); return GNUNET_SYSERR; } { struct GNUNET_GNSRECORD_Data rd[rd_count]; unsigned int i; unsigned int j; unsigned int k; struct GNUNET_TIME_Absolute now; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (payload_len - sizeof (uint32_t), &payload[sizeof (uint32_t)], rd_count, rd)) { GNUNET_break_op (0); return GNUNET_SYSERR; } /* hide expired records */ now = GNUNET_TIME_absolute_get (); j = 0; for (i=0;i= now.abs_value_us) && (0 == (rd[k].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD))) include_record = GNUNET_NO; /* We have a non-expired, non-shadow record of the same type */ } if (GNUNET_YES == include_record) { rd[i].flags ^= GNUNET_GNSRECORD_RF_SHADOW_RECORD; /* Remove Flag */ if (j != i) rd[j] = rd[i]; j++; } } else if (rd[i].expiration_time >= now.abs_value_us) { /* Include this record */ if (j != i) rd[j] = rd[i]; j++; } } rd_count = j; if (NULL != proc) proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL); } } return GNUNET_OK; } /** * Calculate the DHT query for a given @a label in a given @a zone. * * @param zone private key of the zone * @param label label of the record * @param query hash to use for the query */ void GNUNET_GNSRECORD_query_from_private_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, struct GNUNET_HashCode *query) { struct GNUNET_CRYPTO_EcdsaPublicKey pub; GNUNET_CRYPTO_ecdsa_key_get_public (zone, &pub); GNUNET_GNSRECORD_query_from_public_key (&pub, label, query); } /** * Calculate the DHT query for a given @a label in a given @a zone. * * @param pub public key of the zone * @param label label of the record * @param query hash to use for the query */ void GNUNET_GNSRECORD_query_from_public_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, struct GNUNET_HashCode *query) { struct GNUNET_CRYPTO_EcdsaPublicKey pd; GNUNET_CRYPTO_ecdsa_public_key_derive (pub, label, "gns", &pd); GNUNET_CRYPTO_hash (&pd, sizeof (pd), query); } /* end of gnsrecord_crypto.c */ gnunet-0.10.1/src/gnsrecord/test_gnsrecord_block_expiration.c0000644000175000017500000000650612236140650021402 00000000000000/* This file is part of GNUnet. (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file gnsrecord/test_gnsrecord_crypto.c * @brief testcase for block creation, verification and decryption */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_gnsrecord_lib.h" #define RECORDS 5 #define TEST_RECORD_TYPE 1234 #define TEST_RECORD_DATALEN 123 #define TEST_RECORD_DATA 'a' #define TEST_REMOVE_RECORD_TYPE 4321 #define TEST_REMOVE_RECORD_DATALEN 255 #define TEST_REMOVE_RECORD_DATA 'b' static int res; static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_GNSRECORD_Data rd[2]; struct GNUNET_TIME_Absolute expiration_abs; struct GNUNET_TIME_Absolute expiration_abs_shadow; expiration_abs.abs_value_us = GNUNET_TIME_absolute_get().abs_value_us + GNUNET_TIME_UNIT_SECONDS.rel_value_us; expiration_abs_shadow.abs_value_us = GNUNET_TIME_absolute_get().abs_value_us + GNUNET_TIME_UNIT_MINUTES.rel_value_us; /* create record */ rd[0].expiration_time = expiration_abs.abs_value_us; rd[0].record_type = TEST_RECORD_TYPE; rd[0].data_size = TEST_RECORD_DATALEN; rd[0].data = GNUNET_malloc(TEST_RECORD_DATALEN); rd[0].flags = GNUNET_GNSRECORD_RF_NONE; memset ((char *) rd[0].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); rd[1].expiration_time = expiration_abs.abs_value_us; rd[1].record_type = TEST_RECORD_TYPE; rd[1].data_size = TEST_RECORD_DATALEN; rd[1].data = GNUNET_malloc(TEST_RECORD_DATALEN); rd[1].flags = GNUNET_GNSRECORD_RF_NONE; memset ((char *) rd[1].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); GNUNET_assert (expiration_abs.abs_value_us == GNUNET_GNSRECORD_record_get_expiration_time(2, rd).abs_value_us); rd[1].expiration_time = expiration_abs_shadow.abs_value_us; rd[1].record_type = TEST_RECORD_TYPE; rd[1].data_size = TEST_RECORD_DATALEN; rd[1].data = GNUNET_malloc(TEST_RECORD_DATALEN); rd[1].flags = GNUNET_GNSRECORD_RF_SHADOW_RECORD; memset ((char *) rd[1].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN); GNUNET_assert (expiration_abs_shadow.abs_value_us == GNUNET_GNSRECORD_record_get_expiration_time(2, rd).abs_value_us); res = 0; } int main (int argc, char *argv[]) { static char *const argvx[] = { "test-gnsrecord-crypto", NULL }; static struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; res = 1; GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, argvx, "test-namestore-api", "nohelp", options, &run, &res); return res; } /* end of test_gnsrecord_crypto.c */ gnunet-0.10.1/src/ats-tests/0000755000175000017500000000000012320755625012617 500000000000000gnunet-0.10.1/src/ats-tests/perf_ats.c0000644000175000017500000003337012274162760014514 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats/perf_ats.c * @brief ats benchmark: start peers and modify preferences, monitor change over time * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "gnunet_core_service.h" #include "ats-testing.h" #define TEST_ATS_PREFRENCE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) #define TEST_ATS_PREFRENCE_START 1.0 #define TEST_ATS_PREFRENCE_DELTA 1.0 #define TEST_MESSAGE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) #define BENCHMARK_DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) #define LOGGING_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) #define TESTNAME_PREFIX "perf_ats_" #define DEFAULT_SLAVES_NUM 2 #define DEFAULT_MASTERS_NUM 1 /** * Shutdown task */ static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Progress task */ static GNUNET_SCHEDULER_TaskIdentifier progress_task; /** * Test result */ static int result; /** * Test result logging */ static int logging; /**Test core (GNUNET_YES) or transport (GNUNET_NO) */ static int test_core; /** * Solver string */ static char *solver; /** * Preference string */ static char *testname; /** * Preference string */ static char *pref_str; /** * ATS preference value */ static int pref_val; /** * Benchmark duration */ static struct GNUNET_TIME_Relative perf_duration; /** * Logging frequency */ static struct GNUNET_TIME_Relative log_frequency; /** * Number master peers */ static unsigned int num_masters; /** * Array of master peers */ static struct BenchmarkPeer *mps; /** * Number slave peers */ static unsigned int num_slaves; /** * Array of master peers */ static struct BenchmarkPeer *sps; static struct LoggingHandle *l; static void evaluate () { int c_m; int c_s; unsigned int duration; struct BenchmarkPeer *mp; struct BenchmarkPartner *p; unsigned int kb_sent_sec; double kb_sent_percent; unsigned int kb_recv_sec; double kb_recv_percent; unsigned int rtt; duration = (perf_duration.rel_value_us / (1000 * 1000)); for (c_m = 0; c_m < num_masters; c_m++) { mp = &mps[c_m]; fprintf (stderr, _("Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. = %u KiB/s\n"), mp->no, mp->total_bytes_sent / 1024, duration, (mp->total_bytes_sent / 1024) / duration, mp->total_bytes_received / 1024, duration, (mp->total_bytes_received / 1024) / duration); for (c_s = 0; c_s < num_slaves; c_s++) { p = &mp->partners[c_s]; kb_sent_sec = 0; kb_recv_sec = 0; kb_sent_percent = 0.0; kb_recv_percent = 0.0; rtt = 0; if (duration > 0) { kb_sent_sec = (p->bytes_sent / 1024) / duration; kb_recv_sec = (p->bytes_received / 1024) / duration; } if (mp->total_bytes_sent > 0) kb_sent_percent = ((double) p->bytes_sent * 100) / mp->total_bytes_sent; if (mp->total_bytes_received > 0) kb_recv_percent = ((double) p->bytes_received * 100) / mp->total_bytes_received; if (1000 * p->messages_sent > 0) rtt = p->total_app_rtt / (1000 * p->messages_sent); fprintf (stderr, "%c Master [%u] -> Slave [%u]: sent %u KiB/s (%.2f %%), received %u KiB/s (%.2f %%)\n", (mp->pref_partner == p->dest) ? '*' : ' ', mp->no, p->dest->no, kb_sent_sec, kb_sent_percent, kb_recv_sec, kb_recv_percent); fprintf (stderr, "%c Master [%u] -> Slave [%u]: Average application layer RTT: %u ms\n", (mp->pref_partner == p->dest) ? '*' : ' ', mp->no, p->dest->no, rtt); } } } /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (GNUNET_YES == logging) GNUNET_ATS_TEST_logging_clean_up(l); shutdown_task = GNUNET_SCHEDULER_NO_TASK; if (GNUNET_SCHEDULER_NO_TASK != progress_task) { fprintf (stderr, "0\n"); GNUNET_SCHEDULER_cancel (progress_task); } progress_task = GNUNET_SCHEDULER_NO_TASK; evaluate (); GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n")); GNUNET_ATS_TEST_shutdown_topology(); } static void print_progress () { static int calls; progress_task = GNUNET_SCHEDULER_NO_TASK; fprintf (stderr, "%llu..", (long long unsigned) perf_duration.rel_value_us / (1000 * 1000) - calls); calls++; progress_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &print_progress, NULL ); } static void ats_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct BenchmarkPeer *me = cls; me->ats_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, " Master [%u] set preference for slave [%u] to %f\n", me->no, me->pref_partner->no, me->pref_value); GNUNET_ATS_performance_change_preference (me->ats_perf_handle, &me->pref_partner->id, pref_val, me->pref_value, GNUNET_ATS_PREFERENCE_END); me->pref_value += TEST_ATS_PREFRENCE_DELTA; me->ats_task = GNUNET_SCHEDULER_add_delayed (TEST_ATS_PREFRENCE_FREQUENCY, &ats_pref_task, cls); } static void start_benchmark() { int c_m; int c_s; GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking start\n")); if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) GNUNET_SCHEDULER_cancel(shutdown_task); shutdown_task = GNUNET_SCHEDULER_add_delayed(perf_duration, &do_shutdown, NULL ); progress_task = GNUNET_SCHEDULER_add_now(&print_progress, NULL ); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Topology connected, start benchmarking...\n"); /* Start sending test messages */ for (c_m = 0; c_m < num_masters; c_m++) { for (c_s = 0; c_s < num_slaves; c_s++) { GNUNET_ATS_TEST_generate_traffic_start (&mps[c_m], &mps[c_m].partners[c_s], GNUNET_ATS_TEST_TG_LINEAR, UINT32_MAX, UINT32_MAX, GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_FOREVER_REL); } if (pref_val != GNUNET_ATS_PREFERENCE_END) mps[c_m].ats_task = GNUNET_SCHEDULER_add_now(&ats_pref_task, &mps[c_m]); } if (GNUNET_YES == logging) l = GNUNET_ATS_TEST_logging_start (log_frequency, testname, mps, num_masters, num_slaves, GNUNET_NO); } static void do_benchmark (void *cls, struct BenchmarkPeer *masters, struct BenchmarkPeer *slaves) { mps = masters; sps = slaves; GNUNET_SCHEDULER_add_now(&start_benchmark, NULL); } static struct BenchmarkPartner * find_partner (struct BenchmarkPeer *me, const struct GNUNET_PeerIdentity * peer) { int c_m; GNUNET_assert (NULL != me); GNUNET_assert (NULL != peer); for (c_m = 0; c_m < me->num_partners; c_m++) { /* Find a partner with other as destination */ if (0 == memcmp (peer, &me->partners[c_m].dest->id, sizeof(struct GNUNET_PeerIdentity))) { return &me->partners[c_m]; } } return NULL; } static void test_recv_cb (void *cls, const struct GNUNET_PeerIdentity * peer, const struct GNUNET_MessageHeader * message) { } static void log_request_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct BenchmarkPeer *me = cls; struct BenchmarkPartner *p; int c_a; char *peer_id; p = find_partner (me, &address->peer); if (NULL == p) { /* This is not one of my partners * Will happen since the peers will connect to each other due to gossiping */ return; } peer_id = GNUNET_strdup (GNUNET_i2s (&me->id)); if ((p->bandwidth_in != ntohl (bandwidth_in.value__)) || (p->bandwidth_out != ntohl (bandwidth_out.value__))) p->bandwidth_in = ntohl (bandwidth_in.value__); p->bandwidth_out = ntohl (bandwidth_out.value__); for (c_a = 0; c_a < ats_count; c_a++) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s [%u] received ATS information: %s %s %u\n", (GNUNET_YES == p->me->master) ? "Master" : "Slave", p->me->no, GNUNET_i2s (&p->dest->id), GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)), ntohl(ats[c_a].value)); } GNUNET_free(peer_id); if (NULL != l) GNUNET_ATS_TEST_logging_now (l); } /* * Start the performance test case */ int main (int argc, char *argv[]) { char *tmp; char *tmp_sep; char *test_name; char *conf_name; char *comm_name; char *dotexe; char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString; int c; result = 0; /* figure out testname */ tmp = strstr (argv[0], TESTNAME_PREFIX); if (NULL == tmp) { fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]); return GNUNET_SYSERR; } tmp += strlen (TESTNAME_PREFIX); solver = GNUNET_strdup (tmp); if (NULL != (dotexe = strstr (solver, ".exe")) && dotexe[4] == '\0') dotexe[0] = '\0'; tmp_sep = strchr (solver, '_'); if (NULL == tmp_sep) { fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]); GNUNET_free(solver); return GNUNET_SYSERR; } tmp_sep[0] = '\0'; comm_name = GNUNET_strdup (&tmp_sep[1]); tmp_sep = strchr (comm_name, '_'); if (NULL == tmp_sep) { fprintf (stderr, "Unable to parse test name `%s'\n", argv[0]); GNUNET_free(solver); return GNUNET_SYSERR; } tmp_sep[0] = '\0'; for (c = 0; c <= strlen (comm_name); c++) comm_name[c] = toupper (comm_name[c]); if (0 == strcmp (comm_name, "CORE")) test_core = GNUNET_YES; else if (0 == strcmp (comm_name, "TRANSPORT")) test_core = GNUNET_NO; else { GNUNET_free (comm_name); GNUNET_free (solver); return GNUNET_SYSERR; } pref_str = GNUNET_strdup(tmp_sep + 1); GNUNET_asprintf (&conf_name, "%s%s_%s.conf", TESTNAME_PREFIX, solver, pref_str); GNUNET_asprintf (&test_name, "%s%s_%s", TESTNAME_PREFIX, solver, pref_str); for (c = 0; c <= strlen (pref_str); c++) pref_str[c] = toupper (pref_str[c]); pref_val = -1; if (0 != strcmp (pref_str, "NONE")) { for (c = 1; c < GNUNET_ATS_PreferenceCount; c++) { if (0 == strcmp (pref_str, prefs[c])) { pref_val = c; break; } } } else { /* abuse terminator to indicate no pref */ pref_val = GNUNET_ATS_PREFERENCE_END; } if (-1 == pref_val) { fprintf (stderr, "Unknown preference: `%s'\n", pref_str); GNUNET_free(solver); GNUNET_free(pref_str); GNUNET_free (comm_name); return -1; } for (c = 0; c < (argc - 1); c++) { if (0 == strcmp (argv[c], "-d")) break; } if (c < argc - 1) { if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[c + 1], &perf_duration)) fprintf (stderr, "Failed to parse duration `%s'\n", argv[c + 1]); } else { perf_duration = BENCHMARK_DURATION; } fprintf (stderr, "Running benchmark for %llu secs\n", (unsigned long long) (perf_duration.rel_value_us) / (1000 * 1000)); for (c = 0; c < (argc - 1); c++) { if (0 == strcmp (argv[c], "-s")) break; } if (c < argc - 1) { if ((0L != (num_slaves = strtol (argv[c + 1], NULL, 10))) && (num_slaves >= 1)) fprintf (stderr, "Starting %u slave peers\n", num_slaves); else num_slaves = DEFAULT_SLAVES_NUM; } else num_slaves = DEFAULT_SLAVES_NUM; for (c = 0; c < (argc - 1); c++) { if (0 == strcmp (argv[c], "-m")) break; } if (c < argc - 1) { if ((0L != (num_masters = strtol (argv[c + 1], NULL, 10))) && (num_masters >= 2)) fprintf (stderr, "Starting %u master peers\n", num_masters); else num_masters = DEFAULT_MASTERS_NUM; } else num_masters = DEFAULT_MASTERS_NUM; logging = GNUNET_NO; for (c = 0; c < argc; c++) { if (0 == strcmp (argv[c], "-l")) logging = GNUNET_YES; } if (GNUNET_YES == logging) { for (c = 0; c < (argc - 1); c++) { if (0 == strcmp (argv[c], "-f")) break; } if (c < argc - 1) { if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[c + 1], &log_frequency)) fprintf (stderr, "Failed to parse duration `%s'\n", argv[c + 1]); } else { log_frequency = LOGGING_FREQUENCY; } fprintf (stderr, "Using log frequency %llu ms\n", (unsigned long long) (log_frequency.rel_value_us) / (1000)); } GNUNET_asprintf (&testname, "%s_%s_%s",solver, comm_name, pref_str); if (num_slaves < num_masters) { fprintf (stderr, "Number of master peers is lower than slaves! exit...\n"); GNUNET_free(test_name); GNUNET_free(solver); GNUNET_free(pref_str); GNUNET_free (comm_name); return GNUNET_SYSERR; } /** * Setup the topology */ GNUNET_ATS_TEST_create_topology ("perf-ats", conf_name, num_slaves, num_masters, test_core, &do_benchmark, NULL, &test_recv_cb, &log_request_cb); return result; } /* end of file perf_ats.c */ gnunet-0.10.1/src/ats-tests/ats-testing.c0000644000175000017500000006370412316473376015164 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing.c * @brief ats testing library: setup topology * solvers * @author Christian Grothoff * @author Matthias Wachs */ #include "ats-testing.h" /** * Connect peers with testbed */ struct TestbedConnectOperation { /** * The benchmarking master initiating this connection */ struct BenchmarkPeer *master; /** * The benchmarking slave to connect to */ struct BenchmarkPeer *slave; /** * Testbed operation to connect peers */ struct GNUNET_TESTBED_Operation *connect_op; }; struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_ATS_TEST_Topology *top; /** * Shutdown nicely * * @param cls NULL * @param tc the task context */ static void do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int c_m; int c_s; int c_op; struct BenchmarkPeer *p; top->shutdown_task = GNUNET_SCHEDULER_NO_TASK; top->state.benchmarking = GNUNET_NO; GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Benchmarking done\n")); GNUNET_ATS_TEST_generate_traffic_stop_all (); for (c_m = 0; c_m < top->num_masters; c_m++) { p = &top->mps[c_m]; if (NULL != top->mps[c_m].peer_id_op) { GNUNET_TESTBED_operation_done (p->peer_id_op); p->peer_id_op = NULL; } if (GNUNET_SCHEDULER_NO_TASK != p->ats_task) GNUNET_SCHEDULER_cancel (p->ats_task); p->ats_task = GNUNET_SCHEDULER_NO_TASK; for (c_op = 0; c_op < p->num_partners; c_op++) { if (NULL != p->partners[c_op].cth) { GNUNET_CORE_notify_transmit_ready_cancel (p->partners[c_op].cth); p->partners[c_op].cth = NULL; } if (NULL != p->partners[c_op].tth) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (p->partners[c_op].tth); p->partners[c_op].tth = NULL; } if ( (NULL != p->core_connect_ops) && (NULL != p->core_connect_ops[c_op].connect_op) ) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Failed to connect peer 0 and %u\n"), c_op); GNUNET_TESTBED_operation_done ( p->core_connect_ops[c_op].connect_op); p->core_connect_ops[c_op].connect_op = NULL; } } if (NULL != p->ats_perf_op) { GNUNET_TESTBED_operation_done (p->ats_perf_op); p->ats_perf_op = NULL; } if (NULL != p->comm_op) { GNUNET_TESTBED_operation_done (p->comm_op); p->comm_op = NULL; } GNUNET_free_non_null (p->core_connect_ops); GNUNET_free(p->partners); p->partners = NULL; } for (c_s = 0; c_s < top->num_slaves; c_s++) { p = &top->sps[c_s]; if (NULL != p->peer_id_op) { GNUNET_TESTBED_operation_done (p->peer_id_op); p->peer_id_op = NULL; } for (c_op = 0; c_op < p->num_partners; c_op++) { if (NULL != p->partners[c_op].cth) { GNUNET_CORE_notify_transmit_ready_cancel (p->partners[c_op].cth); p->partners[c_op].cth = NULL; } if (NULL != p->partners[c_op].tth) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (p->partners[c_op].tth); p->partners[c_op].tth = NULL; } } if (NULL != p->ats_perf_op) { GNUNET_TESTBED_operation_done (p->ats_perf_op); p->ats_perf_op = NULL; } if (NULL != p->comm_op) { GNUNET_TESTBED_operation_done (p->comm_op); p->comm_op = NULL; } GNUNET_free(p->partners); p->partners = NULL; } GNUNET_SCHEDULER_shutdown (); GNUNET_free (top); top = NULL; } static struct BenchmarkPartner * find_partner (struct BenchmarkPeer *me, const struct GNUNET_PeerIdentity * peer) { int c_m; GNUNET_assert (NULL != me); GNUNET_assert (NULL != peer); for (c_m = 0; c_m < me->num_partners; c_m++) { /* Find a partner with other as destination */ if (0 == memcmp (peer, &me->partners[c_m].dest->id, sizeof(struct GNUNET_PeerIdentity))) { return &me->partners[c_m]; } } return NULL; } static struct BenchmarkPeer * find_peer (const struct GNUNET_PeerIdentity * peer) { int c_p; for (c_p = 0; c_p < top->num_masters; c_p++) { if (0 == memcmp (&top->mps[c_p].id, peer, sizeof(struct GNUNET_PeerIdentity))) return &top->mps[c_p]; } for (c_p = 0; c_p < top->num_slaves; c_p++) { if (0 == memcmp (&top->sps[c_p].id, peer, sizeof(struct GNUNET_PeerIdentity))) return &top->sps[c_p]; } return NULL ; } /** * Method called whenever a given peer connects. * * @param cls closure * @param peer peer identity this notification is about */ static void comm_connect_cb (void *cls, const struct GNUNET_PeerIdentity * peer) { struct BenchmarkPeer *me = cls; struct BenchmarkPeer *remote; char *id; int c; int completed; remote = find_peer (peer); if (NULL == remote) { GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unknown peer connected: `%s'\n", GNUNET_i2s (peer)); GNUNET_break(0); return; } id = GNUNET_strdup (GNUNET_i2s (&me->id)); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s [%u] `%s' connected to %s [%u] %s\n", (me->master == GNUNET_YES) ? "Master": "Slave", me->no, id, (remote->master == GNUNET_YES) ? "Master": "Slave", remote->no, GNUNET_i2s (peer)); me->core_connections++; if ((GNUNET_YES == me->master) && (GNUNET_NO == remote->master) && (GNUNET_NO == top->state.connected_CORE)) { me->core_slave_connections++; if (me->core_slave_connections == top->num_slaves) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Master [%u] connected all slaves\n", me->no); } completed = GNUNET_YES; for (c = 0; c < top->num_masters; c++) { if (top->mps[c].core_slave_connections != top->num_slaves) completed = GNUNET_NO; } if (GNUNET_YES == completed) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "All master peers connected all slave peers\n", id, GNUNET_i2s (peer)); top->state.connected_CORE = GNUNET_YES; /* Notify about setup done */ if (NULL != top->done_cb) top->done_cb (top->done_cb_cls, top->mps, top->sps); } } GNUNET_free(id); } static void comm_disconnect_cb (void *cls, const struct GNUNET_PeerIdentity * peer) { struct BenchmarkPeer *me = cls; struct BenchmarkPartner *p; char *id; if (NULL == (p = find_partner (me, peer))) return; id = GNUNET_strdup (GNUNET_i2s (&me->id)); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s disconnected from %s \n", id, GNUNET_i2s (peer)); GNUNET_assert(me->core_connections > 0); me->core_connections--; if ((GNUNET_YES == top->state.benchmarking) && ((GNUNET_YES == me->master) || (GNUNET_YES == p->dest->master))) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s disconnected from %s while benchmarking \n", id, GNUNET_i2s (peer)); if (NULL != p->tth) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (p->tth); p->tth = NULL; } if (NULL != p->cth) { GNUNET_CORE_notify_transmit_ready_cancel (p->cth); p->cth = NULL; } } GNUNET_free(id); } static void * core_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct BenchmarkPeer *me = cls; me->ch = GNUNET_CORE_connect (cfg, me, NULL, comm_connect_cb, comm_disconnect_cb, NULL, GNUNET_NO, NULL, GNUNET_NO, top->handlers); if (NULL == me->ch) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create core connection \n"); return me->ch; } static void core_disconnect_adapter (void *cls, void *op_result) { struct BenchmarkPeer *me = cls; GNUNET_CORE_disconnect (me->ch); me->ch = NULL; } static int comm_handle_pong (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { struct BenchmarkPeer *me = cls; struct BenchmarkPartner *p = NULL; if (NULL == (p = find_partner (me, other))) { GNUNET_break(0); return GNUNET_SYSERR; } GNUNET_ATS_TEST_traffic_handle_pong (p); return GNUNET_OK; } static int comm_handle_ping (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message) { struct BenchmarkPeer *me = cls; struct BenchmarkPartner *p = NULL; if (NULL == (p = find_partner(me, other))) { GNUNET_break(0); return GNUNET_SYSERR; } GNUNET_ATS_TEST_traffic_handle_ping (p); return GNUNET_OK; } static void test_recv_cb (void *cls, const struct GNUNET_PeerIdentity * peer, const struct GNUNET_MessageHeader * message) { if (TEST_MESSAGE_SIZE != ntohs (message->size) || (TEST_MESSAGE_TYPE_PING != ntohs (message->type) && TEST_MESSAGE_TYPE_PONG != ntohs (message->type))) { return; } if (TEST_MESSAGE_TYPE_PING == ntohs (message->type)) comm_handle_ping (cls, peer, message); if (TEST_MESSAGE_TYPE_PONG == ntohs (message->type)) comm_handle_pong (cls, peer, message); } static void * transport_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct BenchmarkPeer *me = cls; me->th = GNUNET_TRANSPORT_connect (cfg, &me->id, me, &test_recv_cb, &comm_connect_cb, &comm_disconnect_cb); if (NULL == me->th) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create transport connection \n"); return me->th; } static void transport_disconnect_adapter (void *cls, void *op_result) { struct BenchmarkPeer *me = cls; GNUNET_TRANSPORT_disconnect (me->th); me->th = NULL; } static void connect_completion_callback (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) { struct TestbedConnectOperation *cop = cls; static int ops = 0; int c; if (NULL == emsg) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Connected master [%u] with slave [%u]\n"), cop->master->no, cop->slave->no); } else { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Failed to connect master peer [%u] with slave [%u]\n"), cop->master->no, cop->slave->no); GNUNET_break(0); if (GNUNET_SCHEDULER_NO_TASK != top->shutdown_task) GNUNET_SCHEDULER_cancel (top->shutdown_task); top->shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL ); } GNUNET_TESTBED_operation_done (op); ops++; for (c = 0; c < top->num_slaves; c++) { if (cop == &cop->master->core_connect_ops[c]) cop->master->core_connect_ops[c].connect_op = NULL; } if (ops == top->num_masters * top->num_slaves) { top->state.connected_PEERS = GNUNET_YES; } } static void do_connect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int c_m; int c_s; struct BenchmarkPeer *p; if ((top->state.connected_ATS_service == GNUNET_NO) || (top->state.connected_COMM_service == GNUNET_NO)) return; GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Connecting peers on CORE level\n")); for (c_m = 0; c_m < top->num_masters; c_m++) { p = &top->mps[c_m]; p->core_connect_ops = GNUNET_malloc (top->num_slaves * sizeof (struct TestbedConnectOperation)); for (c_s = 0; c_s < top->num_slaves; c_s++) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Connecting master [%u] with slave [%u]\n"), p->no, top->sps[c_s].no); p->core_connect_ops[c_s].master = p; p->core_connect_ops[c_s].slave = &top->sps[c_s]; p->core_connect_ops[c_s].connect_op = GNUNET_TESTBED_overlay_connect ( NULL, &connect_completion_callback, &p->core_connect_ops[c_s], top->sps[c_s].peer, p->peer); if (NULL == p->core_connect_ops[c_s].connect_op) { GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("Could not connect master [%u] and slave [%u]\n"), p->no, top->sps[c_s].no); GNUNET_break(0); if (GNUNET_SCHEDULER_NO_TASK != top->shutdown_task) GNUNET_SCHEDULER_cancel (top->shutdown_task); top->shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL ); return; } } } } static void comm_connect_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { static int comm_done = 0; if ((NULL != emsg) || (NULL == ca_result)) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initialization failed, shutdown\n")); GNUNET_break(0); if (GNUNET_SCHEDULER_NO_TASK != top->shutdown_task) GNUNET_SCHEDULER_cancel (top->shutdown_task); top->shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL ); return; } comm_done++; if (comm_done == top->num_slaves + top->num_masters) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to all %s services\n", (GNUNET_YES == top->test_core) ? "CORE" : "TRANSPORT"); top->state.connected_COMM_service = GNUNET_YES; GNUNET_SCHEDULER_add_now (&do_connect_peers, NULL ); } } static void do_comm_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int c_s; int c_m; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connecting to all %s services\n", (GNUNET_YES == top->test_core) ? "CORE" : "TRANSPORT"); for (c_m = 0; c_m < top->num_masters; c_m++) { if (GNUNET_YES == top->test_core) top->mps[c_m].comm_op = GNUNET_TESTBED_service_connect (NULL, top->mps[c_m].peer, "core", &comm_connect_completion_cb, NULL, &core_connect_adapter, &core_disconnect_adapter, &top->mps[c_m]); else { top->mps[c_m].comm_op = GNUNET_TESTBED_service_connect (NULL, top->mps[c_m].peer, "transport", &comm_connect_completion_cb, NULL, &transport_connect_adapter, &transport_disconnect_adapter, &top->mps[c_m]); } } for (c_s = 0; c_s < top->num_slaves; c_s++) { if (GNUNET_YES == top->test_core) top->sps[c_s].comm_op = GNUNET_TESTBED_service_connect (NULL, top->sps[c_s].peer, "core", &comm_connect_completion_cb, NULL, &core_connect_adapter, &core_disconnect_adapter, &top->sps[c_s]); else { top->sps[c_s].comm_op = GNUNET_TESTBED_service_connect (NULL, top->sps[c_s].peer, "transport", &comm_connect_completion_cb, NULL, &transport_connect_adapter, &transport_disconnect_adapter, &top->sps[c_s]); } } } static void ats_performance_info_cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { struct BenchmarkPeer *me = cls; struct BenchmarkPartner *p; int c_a; int log; char *peer_id; p = find_partner (me, &address->peer); if (NULL == p) { /* This is not one of my partners * Will happen since the peers will connect to each other due to gossiping */ return; } peer_id = GNUNET_strdup (GNUNET_i2s (&me->id)); log = GNUNET_NO; if ((p->bandwidth_in != ntohl (bandwidth_in.value__)) || (p->bandwidth_out != ntohl (bandwidth_out.value__))) log = GNUNET_YES; p->bandwidth_in = ntohl (bandwidth_in.value__); p->bandwidth_out = ntohl (bandwidth_out.value__); for (c_a = 0; c_a < ats_count; c_a++) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s [%u] received ATS information: %s %s %u\n", (GNUNET_YES == p->me->master) ? "Master" : "Slave", p->me->no, GNUNET_i2s (&p->dest->id), GNUNET_ATS_print_property_type(ntohl(ats[c_a].type)), ntohl(ats[c_a].value)); switch (ntohl (ats[c_a].type )) { case GNUNET_ATS_ARRAY_TERMINATOR: break; case GNUNET_ATS_UTILIZATION_OUT: if (p->ats_utilization_up != ntohl (ats[c_a].value)) log = GNUNET_YES; p->ats_utilization_up = ntohl (ats[c_a].value); break; case GNUNET_ATS_UTILIZATION_IN: if (p->ats_utilization_down != ntohl (ats[c_a].value)) log = GNUNET_YES; p->ats_utilization_down = ntohl (ats[c_a].value); break; case GNUNET_ATS_NETWORK_TYPE: if (p->ats_network_type != ntohl (ats[c_a].value)) log = GNUNET_YES; p->ats_network_type = ntohl (ats[c_a].value); break; case GNUNET_ATS_QUALITY_NET_DELAY: if (p->ats_delay != ntohl (ats[c_a].value)) log = GNUNET_YES; p->ats_delay = ntohl (ats[c_a].value); break; case GNUNET_ATS_QUALITY_NET_DISTANCE: if (p->ats_distance != ntohl (ats[c_a].value)) log = GNUNET_YES; p->ats_distance = ntohl (ats[c_a].value); GNUNET_break (0); break; case GNUNET_ATS_COST_WAN: if (p->ats_cost_wan != ntohl (ats[c_a].value)) log = GNUNET_YES; p->ats_cost_wan = ntohl (ats[c_a].value); break; case GNUNET_ATS_COST_LAN: if (p->ats_cost_lan != ntohl (ats[c_a].value)) log = GNUNET_YES; p->ats_cost_lan = ntohl (ats[c_a].value); break; case GNUNET_ATS_COST_WLAN: if (p->ats_cost_wlan != ntohl (ats[c_a].value)) log = GNUNET_YES; p->ats_cost_wlan = ntohl (ats[c_a].value); break; default: break; } } if (GNUNET_YES == log) top->ats_perf_cb (cls, address, address_active, bandwidth_out, bandwidth_in, ats, ats_count); GNUNET_free(peer_id); } static void * ats_perf_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct BenchmarkPeer *me = cls; me->ats_perf_handle = GNUNET_ATS_performance_init (cfg, ats_performance_info_cb, me); if (NULL == me->ats_perf_handle) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to create ATS performance handle \n"); return me->ats_perf_handle; } static void ats_perf_disconnect_adapter (void *cls, void *op_result) { struct BenchmarkPeer *me = cls; GNUNET_ATS_performance_done (me->ats_perf_handle); me->ats_perf_handle = NULL; } static void ats_connect_completion_cb (void *cls, struct GNUNET_TESTBED_Operation *op, void *ca_result, const char *emsg) { static int op_done = 0; if ((NULL != emsg) || (NULL == ca_result)) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Initialization failed, shutdown\n")); GNUNET_break(0); if (GNUNET_SCHEDULER_NO_TASK != top->shutdown_task) GNUNET_SCHEDULER_cancel (top->shutdown_task); top->shutdown_task = GNUNET_SCHEDULER_add_now (do_shutdown, NULL ); return; } op_done++; if (op_done == (top->num_masters + top->num_slaves)) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connected to all ATS services\n"); top->state.connected_ATS_service = GNUNET_YES; GNUNET_SCHEDULER_add_now (&do_comm_connect, NULL ); } } static void do_connect_ats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { int c_m; int c_s; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Connecting to all ATS services\n"); for (c_m = 0; c_m < top->num_masters; c_m++) { top->mps[c_m].ats_perf_op = GNUNET_TESTBED_service_connect (NULL, top->mps[c_m].peer, "ats", ats_connect_completion_cb, NULL, &ats_perf_connect_adapter, &ats_perf_disconnect_adapter, &top->mps[c_m]); } for (c_s = 0; c_s < top->num_slaves; c_s++) { top->sps[c_s].ats_perf_op = GNUNET_TESTBED_service_connect (NULL, top->sps[c_s].peer, "ats", ats_connect_completion_cb, NULL, &ats_perf_connect_adapter, &ats_perf_disconnect_adapter, &top->sps[c_s]); } } static void peerinformation_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation*pinfo, const char *emsg) { struct BenchmarkPeer *p = cb_cls; static int done = 0; GNUNET_assert(pinfo->pit == GNUNET_TESTBED_PIT_IDENTITY); p->id = *pinfo->result.id; GNUNET_log(GNUNET_ERROR_TYPE_INFO, "%s [%u] has peer id `%s'\n", (p->master == GNUNET_YES) ? "Master" : "Slave", p->no, GNUNET_i2s (&p->id)); GNUNET_TESTBED_operation_done (op); p->peer_id_op = NULL; done++; if (done == top->num_slaves + top->num_masters) { GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Retrieved all peer ID, connect to ATS\n"); GNUNET_SCHEDULER_add_now (&do_connect_ats, NULL ); } } /** * Signature of a main function for a testcase. * * @param cls closure * @param h testbed handle * @param num_peers number of peers in 'peers' * @param peers_ handle to peers run in the testbed * @param links_succeeded the number of overlay link connection attempts that * succeeded * @param links_failed the number of overlay link connection attempts that * failed */ static void main_run (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers_, unsigned int links_succeeded, unsigned int links_failed) { int c_m; int c_s; GNUNET_assert(NULL == cls); GNUNET_assert(top->num_masters + top->num_slaves == num_peers); GNUNET_assert(NULL != peers_); top->shutdown_task = GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_UNIT_FOREVER_REL, &do_shutdown, top); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up %u masters and %u slaves\n", top->num_masters, top->num_slaves); /* Setup master peers */ for (c_m = 0; c_m < top->num_masters; c_m++) { GNUNET_assert(NULL != peers_[c_m]); top->mps[c_m].peer = peers_[c_m]; top->mps[c_m].no = c_m; top->mps[c_m].master = GNUNET_YES; top->mps[c_m].pref_partner = &top->sps[c_m]; top->mps[c_m].pref_value = TEST_ATS_PREFERENCE_DEFAULT; top->mps[c_m].partners = GNUNET_malloc (top->num_slaves * sizeof (struct BenchmarkPartner)); top->mps[c_m].num_partners = top->num_slaves; /* Initialize partners */ for (c_s = 0; c_s < top->num_slaves; c_s++) { top->mps[c_m].partners[c_s].me = &top->mps[c_m]; top->mps[c_m].partners[c_s].dest = &top->sps[c_s]; } /* Get configuration */ top->mps[c_m].peer_id_op = GNUNET_TESTBED_peer_get_information (top->mps[c_m].peer, GNUNET_TESTBED_PIT_IDENTITY, &peerinformation_cb, &top->mps[c_m]); } /* Setup slave peers */ for (c_s = 0; c_s < top->num_slaves; c_s++) { GNUNET_assert(NULL != peers_[c_s + top->num_masters]); top->sps[c_s].peer = peers_[c_s + top->num_masters]; top->sps[c_s].no = c_s + top->num_masters; top->sps[c_s].master = GNUNET_NO; top->sps[c_s].partners = GNUNET_malloc (top->num_masters * sizeof (struct BenchmarkPartner)); top->sps[c_s].num_partners = top->num_masters; /* Initialize partners */ for (c_m = 0; c_m < top->num_masters; c_m++) { top->sps[c_s].partners[c_m].me = &top->sps[c_s]; top->sps[c_s].partners[c_m].dest = &top->mps[c_m]; } /* Get configuration */ top->sps[c_s].peer_id_op = GNUNET_TESTBED_peer_get_information (top->sps[c_s].peer, GNUNET_TESTBED_PIT_IDENTITY, &peerinformation_cb, &top->sps[c_s]); } } /** * Controller event callback * * @param cls NULL * @param event the controller event */ static void controller_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) { struct GNUNET_ATS_TEST_Topology *top = cls; switch (event->type) { case GNUNET_TESTBED_ET_CONNECT: break; case GNUNET_TESTBED_ET_OPERATION_FINISHED: break; default: GNUNET_break(0); GNUNET_SCHEDULER_cancel (top->shutdown_task); top->shutdown_task = GNUNET_SCHEDULER_add_now (&do_shutdown, NULL ); } } struct BenchmarkPeer * GNUNET_ATS_TEST_get_peer (int src) { if (src > top->num_masters) return NULL; return &top->mps[src]; } struct BenchmarkPartner * GNUNET_ATS_TEST_get_partner (int src, int dest) { if (src > top->num_masters) return NULL; if (dest > top->num_slaves) return NULL; return &top->mps[src].partners[dest]; } /** * Create a topology for ats testing * * @param name test name * @param cfg_file configuration file to use for the peers * @param num_slaves number of slaves * @param num_masters number of masters * @param test_core connect to CORE service (GNUNET_YES) or transport (GNUNET_NO) * @param done_cb function to call when topology is setup * @param done_cb_cls cls for callback * @param transport_recv_cb callback to call when data are received * @param log_request_cb callback to call when logging is required */ void GNUNET_ATS_TEST_create_topology (char *name, char *cfg_file, unsigned int num_slaves, unsigned int num_masters, int test_core, GNUNET_ATS_TEST_TopologySetupDoneCallback done_cb, void *done_cb_cls, GNUNET_TRANSPORT_ReceiveCallback transport_recv_cb, GNUNET_ATS_AddressInformationCallback log_request_cb) { static struct GNUNET_CORE_MessageHandler handlers[] = { {&comm_handle_ping, TEST_MESSAGE_TYPE_PING, 0 }, {&comm_handle_pong, TEST_MESSAGE_TYPE_PONG, 0 }, { NULL, 0, 0 } }; top = GNUNET_new (struct GNUNET_ATS_TEST_Topology); top->num_masters = num_masters; top->num_slaves = num_slaves; top->handlers = handlers; top->done_cb = done_cb; top->done_cb_cls = done_cb_cls; top->test_core = test_core; top->transport_recv_cb = transport_recv_cb; top->ats_perf_cb = log_request_cb; top->mps = GNUNET_malloc (num_masters * sizeof (struct BenchmarkPeer)); top->sps = GNUNET_malloc (num_slaves * sizeof (struct BenchmarkPeer)); /* Start topology */ uint64_t event_mask; event_mask = 0; event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT); event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); (void) GNUNET_TESTBED_test_run (name, cfg_file, num_slaves + num_masters, event_mask, &controller_event_cb, NULL, &main_run, NULL); } /** * Shutdown topology */ void GNUNET_ATS_TEST_shutdown_topology (void) { if (NULL == top) return; GNUNET_SCHEDULER_shutdown(); } /* end of file ats-testing.c */ gnunet-0.10.1/src/ats-tests/ats-testing-experiment.c0000644000175000017500000004747512316473376017351 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing-experiment.c * @brief ats benchmark: controlled experiment execution * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "ats-testing.h" const char * print_op (enum OperationType op) { switch (op) { case START_SEND: return "START_SEND"; case STOP_SEND: return "STOP_SEND"; case START_PREFERENCE: return "START_PREFERENCE"; case STOP_PREFERENCE: return "STOP_PREFERENCE"; default: break; } return ""; } static struct Experiment * create_experiment () { struct Experiment *e; e = GNUNET_new (struct Experiment); e->name = NULL; e->num_masters = 0; e->num_slaves = 0; e->start = NULL; e->total_duration = GNUNET_TIME_UNIT_ZERO; return e; } static void free_experiment (struct Experiment *e) { struct Episode *cur; struct Episode *next; struct GNUNET_ATS_TEST_Operation *cur_o; struct GNUNET_ATS_TEST_Operation *next_o; next = e->start; for (cur = next; NULL != cur; cur = next) { next = cur->next; next_o = cur->head; for (cur_o = next_o; NULL != cur_o; cur_o = next_o) { next_o = cur_o->next; GNUNET_free (cur_o); } GNUNET_free (cur); } GNUNET_free_non_null (e->name); GNUNET_free_non_null (e->cfg_file); GNUNET_free (e); } static int load_episode (struct Experiment *e, struct Episode *cur, struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_ATS_TEST_Operation *o; char *sec_name; char *op_name; char *op; char *type; char *pref; int op_counter = 0; fprintf (stderr, "Parsing episode %u\n",cur->id); GNUNET_asprintf(&sec_name, "episode-%u", cur->id); while (1) { /* Load operation */ GNUNET_asprintf(&op_name, "op-%u-operation", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, sec_name, op_name, &op)) { GNUNET_free (op_name); break; } o = GNUNET_new (struct GNUNET_ATS_TEST_Operation); /* operations = set_rate, start_send, stop_send, set_preference */ if (0 == strcmp (op, "start_send")) { o->type = START_SEND; } else if (0 == strcmp (op, "stop_send")) { o->type = STOP_SEND; } else if (0 == strcmp (op, "start_preference")) { o->type = START_PREFERENCE; } else if (0 == strcmp (op, "stop_preference")) { o->type = STOP_PREFERENCE; } else { fprintf (stderr, "Invalid operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get source */ GNUNET_asprintf(&op_name, "op-%u-src", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->src_id)) { fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); return GNUNET_SYSERR; } if (o->src_id > (e->num_masters - 1)) { fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n", o->src_id, op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get destination */ GNUNET_asprintf(&op_name, "op-%u-dest", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->dest_id)) { fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); return GNUNET_SYSERR; } if (o->dest_id > (e->num_slaves - 1)) { fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n", o->dest_id, op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); GNUNET_asprintf(&op_name, "op-%u-type", op_counter); if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg, sec_name, op_name, &type)) && ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type))) { /* Load arguments for set_rate, start_send, set_preference */ if (0 == strcmp (type, "constant")) { o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT; } else if (0 == strcmp (type, "linear")) { o->gen_type = GNUNET_ATS_TEST_TG_LINEAR; } else if (0 == strcmp (type, "sinus")) { o->gen_type = GNUNET_ATS_TEST_TG_SINUS; } else if (0 == strcmp (type, "random")) { o->gen_type = GNUNET_ATS_TEST_TG_RANDOM; } else { fprintf (stderr, "Invalid type %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get base rate */ GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->base_rate)) { fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op); GNUNET_free (op_name); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get max rate */ GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->max_rate)) { if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) || (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) || (GNUNET_ATS_TEST_TG_SINUS == o->gen_type)) { fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op_name); GNUNET_free (op); return GNUNET_SYSERR; } } GNUNET_free (op_name); /* Get period */ GNUNET_asprintf(&op_name, "op-%u-period", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, sec_name, op_name, &o->period)) { o->period = cur->duration; } GNUNET_free (op_name); if (START_PREFERENCE == o->type) { /* Get frequency */ GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, sec_name, op_name, &o->frequency)) { fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op_name); GNUNET_free (op); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get preference */ GNUNET_asprintf(&op_name, "op-%u-pref", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &pref)) { fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op_name); GNUNET_free (op); GNUNET_free_non_null (pref); return GNUNET_SYSERR; } if (0 == strcmp(pref, "bandwidth")) o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH; else if (0 == strcmp(pref, "latency")) o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY; else { fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op_name); GNUNET_free (op); GNUNET_free (pref); GNUNET_free_non_null (pref); return GNUNET_SYSERR; } GNUNET_free (pref); GNUNET_free (op_name); } } /* Safety checks */ if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) || (GNUNET_ATS_TEST_TG_SINUS == o->gen_type)) { if ((o->max_rate - o->base_rate) > o->base_rate) { /* This will cause an underflow */ GNUNET_break (0); } fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n"); } if ((START_SEND == o->type) || (START_PREFERENCE == o->type)) fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n", op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id, (NULL != type) ? type : "", o->base_rate, o->max_rate, GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES)); else fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n", op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id); GNUNET_free_non_null (type); GNUNET_free (op); GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o); op_counter++; } GNUNET_free (sec_name); return GNUNET_OK; } static int load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg) { int e_counter = 0; char *sec_name; struct GNUNET_TIME_Relative e_duration; struct Episode *cur; struct Episode *last; e_counter = 0; last = NULL; while (1) { GNUNET_asprintf(&sec_name, "episode-%u", e_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, sec_name, "duration", &e_duration)) { GNUNET_free (sec_name); break; } cur = GNUNET_new (struct Episode); cur->duration = e_duration; cur->id = e_counter; if (GNUNET_OK != load_episode (e, cur, cfg)) { GNUNET_free (sec_name); GNUNET_free (cur); return GNUNET_SYSERR; } fprintf (stderr, "Found episode %u with duration %s \n", e_counter, GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES)); /* Update experiment */ e->num_episodes ++; e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration); /* Put in linked list */ if (NULL == last) e->start = cur; else last->next = cur; GNUNET_free (sec_name); e_counter ++; last = cur; } return e_counter; } static void timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { struct Experiment *e = cls; e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; fprintf (stderr, "Experiment timeout!\n"); if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task) { GNUNET_SCHEDULER_cancel (e->episode_timeout_task); e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; } e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_SYSERR); } static void enforce_start_send (struct GNUNET_ATS_TEST_Operation *op) { struct BenchmarkPeer *peer; struct BenchmarkPartner *partner; peer = GNUNET_ATS_TEST_get_peer (op->src_id); if (NULL == peer) { GNUNET_break (0); return; } partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id); if (NULL == partner) { GNUNET_break (0); return; } fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id); if (NULL != partner->tg) { fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id); GNUNET_ATS_TEST_generate_traffic_stop(partner->tg); partner->tg = NULL; } partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner, op->gen_type, op->base_rate, op->max_rate, op->period, GNUNET_TIME_UNIT_FOREVER_REL); } static void enforce_stop_send (struct GNUNET_ATS_TEST_Operation *op) { struct BenchmarkPartner *p; p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id); if (NULL == p) { GNUNET_break (0); return; } fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id); if (NULL != p->tg) { fprintf (stderr, "Stopping traffic between master %llu slave %llu\n", op->src_id, op->dest_id); GNUNET_ATS_TEST_generate_traffic_stop(p->tg); p->tg = NULL; } } static void enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op) { struct BenchmarkPeer *peer; struct BenchmarkPartner *partner; peer = GNUNET_ATS_TEST_get_peer (op->src_id); if (NULL == peer) { GNUNET_break (0); return; } partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id); if (NULL == partner) { GNUNET_break (0); return; } fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id); if (NULL != partner->pg) { fprintf (stderr, "Stopping traffic between master %llu slave %llu\n", op->src_id, op->dest_id); GNUNET_ATS_TEST_generate_preferences_stop(partner->pg); partner->pg = NULL; } partner->pg = GNUNET_ATS_TEST_generate_preferences_start(peer, partner, op->gen_type, op->base_rate, op->max_rate, op->period, op->frequency, op->pref_type); } static void enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op) { struct BenchmarkPartner *p; p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id); if (NULL == p) { GNUNET_break (0); return; } fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id); if (NULL != p->pg) { fprintf (stderr, "Stopping preference between master %llu slave %llu\n", op->src_id, op->dest_id); GNUNET_ATS_TEST_generate_preferences_stop (p->pg); p->pg = NULL; } } static void enforce_episode (struct Episode *ep) { struct GNUNET_ATS_TEST_Operation *cur; for (cur = ep->head; NULL != cur; cur = cur->next) { fprintf (stderr, "Enforcing operation: %s [%llu]->[%llu] == %llu\n", print_op (cur->type), cur->src_id, cur->dest_id, cur->base_rate); switch (cur->type) { case START_SEND: enforce_start_send (cur); break; case STOP_SEND: enforce_stop_send (cur); break; case START_PREFERENCE: enforce_start_preference (cur); break; case STOP_PREFERENCE: enforce_stop_preference (cur); break; default: break; } } } static void timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { struct Experiment *e = cls; e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != e->ep_done_cb) e->ep_done_cb (e->cur); /* Scheduling next */ e->cur = e->cur->next; if (NULL == e->cur) { /* done */ fprintf (stderr, "Last episode done!\n"); if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task) { GNUNET_SCHEDULER_cancel (e->experiment_timeout_task); e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; } e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK); return; } fprintf (stderr, "Running episode %u with timeout %s\n", e->cur->id, GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES)); enforce_episode(e->cur); e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration, &timeout_episode, e); } void GNUNET_ATS_TEST_experimentation_run (struct Experiment *e, GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb, GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb) { fprintf (stderr, "Running experiment `%s' with timeout %s\n", e->name, GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES)); e->e_done_cb = e_done_cb; e->ep_done_cb = ep_done_cb; e->start_time = GNUNET_TIME_absolute_get(); /* Start total time out */ e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration, &timeout_experiment, e); /* Start */ e->cur = e->start; fprintf (stderr, "Running episode %u with timeout %s\n", e->cur->id, GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES)); enforce_episode(e->cur); e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration, &timeout_episode, e); } struct Experiment * GNUNET_ATS_TEST_experimentation_load (char *filename) { struct Experiment *e; struct GNUNET_CONFIGURATION_Handle *cfg; e = NULL; cfg = GNUNET_CONFIGURATION_create(); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename)) { fprintf (stderr, "Failed to load `%s'\n", filename); GNUNET_CONFIGURATION_destroy (cfg); return NULL; } e = create_experiment (); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment", "name", &e->name)) { fprintf (stderr, "Invalid %s", "name"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment name: `%s'\n", e->name); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment", "cfg_file", &e->cfg_file)) { fprintf (stderr, "Invalid %s", "cfg_file"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment", "masters", &e->num_masters)) { fprintf (stderr, "Invalid %s", "masters"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment masters: `%llu'\n", e->num_masters); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment", "slaves", &e->num_slaves)) { fprintf (stderr, "Invalid %s", "slaves"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment slaves: `%llu'\n", e->num_slaves); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment", "log_freq", &e->log_freq)) { fprintf (stderr, "Invalid %s", "log_freq"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment logging frequency: `%s'\n", GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES)); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment", "max_duration", &e->max_duration)) { fprintf (stderr, "Invalid %s", "max_duration"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment duration: `%s'\n", GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES)); load_episodes (e, cfg); fprintf (stderr, "Loaded %u episodes with total duration %s\n", e->num_episodes, GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES)); GNUNET_CONFIGURATION_destroy (cfg); return e; } void GNUNET_ATS_TEST_experimentation_stop (struct Experiment *e) { if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task) { GNUNET_SCHEDULER_cancel (e->experiment_timeout_task); e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task) { GNUNET_SCHEDULER_cancel (e->episode_timeout_task); e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; } free_experiment (e); } /* end of file ats-testing-experiment.c*/ gnunet-0.10.1/src/ats-tests/ats-testing.h0000644000175000017500000003660712316473376015173 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing.h * @brief ats testing library: setup topology and provide logging to test ats * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "gnunet_core_service.h" #define TEST_ATS_PREFERENCE_DEFAULT 1.0 /** * Message type sent for traffic generation */ #define TEST_MESSAGE_TYPE_PING 12345 /** * Message type sent as response during traffic generation */ #define TEST_MESSAGE_TYPE_PONG 12346 /** * Size of test messages */ #define TEST_MESSAGE_SIZE 100 struct BenchmarkPartner; struct BenchmarkPeer; struct GNUNET_ATS_TEST_Topology; struct TrafficGenerator; struct LoggingHandle; enum GeneratorType { GNUNET_ATS_TEST_TG_LINEAR, GNUNET_ATS_TEST_TG_CONSTANT, GNUNET_ATS_TEST_TG_RANDOM, GNUNET_ATS_TEST_TG_SINUS }; /** * Callback to call when topology setup is completed * * @param cls the closure * @param masters array of master peers * @param slaves array of master peers */ typedef void (*GNUNET_ATS_TEST_TopologySetupDoneCallback) (void *cls, struct BenchmarkPeer *masters, struct BenchmarkPeer *slaves); /** * Callback called when logging is required for the data contained * * @param cls the closure * @param address an address * @param address_active is address active * @param bandwidth_out bandwidth outbound * @param bandwidth_in bandwidth inbound * @param ats ats information * @param ats_count number of ats inforation */ typedef void (*GNUNET_ATS_TEST_LogRequest) (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count); /** * Information we track for a peer in the testbed. */ struct BenchmarkPeer { /** * Handle with testbed. */ struct GNUNET_TESTBED_Peer *peer; /** * Unique identifier */ int no; /** * Is this peer a measter: GNUNET_YES/GNUNET_NO */ int master; /** * Peer ID */ struct GNUNET_PeerIdentity id; /** * Testbed operation to get peer information */ struct GNUNET_TESTBED_Operation *peer_id_op; /** * Testbed operation to connect to ATS performance service */ struct GNUNET_TESTBED_Operation *ats_perf_op; /** * Testbed operation to connect to core */ struct GNUNET_TESTBED_Operation *comm_op; /** * ATS performance handle */ struct GNUNET_ATS_PerformanceHandle *ats_perf_handle; /** * Masters only: * Testbed connect operations to connect masters to slaves */ struct TestbedConnectOperation *core_connect_ops; /** * Core handle */ struct GNUNET_CORE_Handle *ch; /** * Core handle */ struct GNUNET_TRANSPORT_Handle *th; /** * Masters only: * Peer to set ATS preferences for */ struct BenchmarkPeer *pref_partner; /** * Masters only * Progress task */ GNUNET_SCHEDULER_TaskIdentifier ats_task; /** * Masters only * Progress task */ double pref_value; /** * Array of partners with num_slaves entries (if master) or * num_master entries (if slave) */ struct BenchmarkPartner *partners; /** * Number of partners */ int num_partners; /** * Number of core connections */ int core_connections; /** * Masters only: * Number of connections to slave peers */ int core_slave_connections; /** * Total number of messages this peer has sent */ unsigned int total_messages_sent; /** * Total number of bytes this peer has sent */ unsigned int total_bytes_sent; /** * Total number of messages this peer has received */ unsigned int total_messages_received; /** * Total number of bytes this peer has received */ unsigned int total_bytes_received; }; struct TrafficGenerator { struct TrafficGenerator *prev; struct TrafficGenerator *next; enum GeneratorType type; struct BenchmarkPeer *src; struct BenchmarkPartner *dest; long int base_rate; long int max_rate; struct GNUNET_TIME_Relative duration_period; GNUNET_SCHEDULER_TaskIdentifier send_task; struct GNUNET_TIME_Absolute next_ping_transmission; struct GNUNET_TIME_Absolute time_start; }; struct PreferenceGenerator { struct PreferenceGenerator *prev; struct PreferenceGenerator *next; enum GeneratorType type; struct BenchmarkPeer *src; struct BenchmarkPartner *dest; enum GNUNET_ATS_PreferenceKind kind; long int base_value; long int max_value; struct GNUNET_TIME_Relative duration_period; struct GNUNET_TIME_Relative frequency; GNUNET_SCHEDULER_TaskIdentifier set_task; struct GNUNET_TIME_Absolute next_ping_transmission; struct GNUNET_TIME_Absolute time_start; }; /** * Information about a benchmarking partner */ struct BenchmarkPartner { /** * The peer itself this partner belongs to */ struct BenchmarkPeer *me; /** * The partner peer */ struct BenchmarkPeer *dest; /** * Core transmit handles */ struct GNUNET_CORE_TransmitHandle *cth; /** * Transport transmit handles */ struct GNUNET_TRANSPORT_TransmitHandle *tth; struct TrafficGenerator *tg; struct PreferenceGenerator *pg; /** * Timestamp to calculate communication layer delay */ struct GNUNET_TIME_Absolute last_message_sent; /** * Accumulated RTT for all messages */ unsigned int total_app_rtt; /** * Number of messages sent to this partner */ unsigned int messages_sent; /** * Number of bytes sent to this partner */ unsigned int bytes_sent; /** * Number of messages received from this partner */ unsigned int messages_received; /** * Number of bytes received from this partner */ unsigned int bytes_received; /* Current ATS properties */ uint32_t ats_distance; uint32_t ats_delay; uint32_t bandwidth_in; uint32_t bandwidth_out; uint32_t ats_utilization_up; uint32_t ats_utilization_down; uint32_t ats_network_type; uint32_t ats_cost_wan; uint32_t ats_cost_lan; uint32_t ats_cost_wlan; double pref_bandwidth; double pref_delay; }; /** * Overall state of the performance benchmark */ struct BenchmarkState { /** * Are we connected to ATS service of all peers: GNUNET_YES/NO */ int connected_ATS_service; /** * Are we connected to CORE service of all peers: GNUNET_YES/NO */ int connected_COMM_service; /** * Are we connected to all peers: GNUNET_YES/NO */ int connected_PEERS; /** * Are we connected to all slave peers on CORE level: GNUNET_YES/NO */ int connected_CORE; /** * Are we connected to CORE service of all peers: GNUNET_YES/NO */ int benchmarking; }; struct GNUNET_ATS_TEST_Topology { /** * Shutdown task */ GNUNET_SCHEDULER_TaskIdentifier shutdown_task; /** * Progress task */ GNUNET_SCHEDULER_TaskIdentifier progress_task; /** * Test result */ int result; /**Test core (GNUNET_YES) or transport (GNUNET_NO) */ int test_core; /** * Solver string */ char *solver; /** * Preference string */ char *testname; /** * Preference string */ char *pref_str; /** * ATS preference value */ int pref_val; /** * Number master peers */ unsigned int num_masters; /** * Array of master peers */ struct BenchmarkPeer *mps; /** * Number slave peers */ unsigned int num_slaves; /** * Array of slave peers */ struct BenchmarkPeer *sps; /** * Benchmark duration */ struct GNUNET_TIME_Relative perf_duration; /** * Logging frequency */ struct GNUNET_TIME_Relative log_frequency; /** * Benchmark state */ struct BenchmarkState state; struct GNUNET_CORE_MessageHandler *handlers; GNUNET_TRANSPORT_ReceiveCallback transport_recv_cb; GNUNET_ATS_TEST_TopologySetupDoneCallback done_cb; GNUNET_ATS_AddressInformationCallback ats_perf_cb; void *done_cb_cls; }; enum OperationType { START_SEND, STOP_SEND, START_PREFERENCE, STOP_PREFERENCE }; struct Episode; struct Experiment; typedef void (*GNUNET_ATS_TESTING_EpisodeDoneCallback) ( struct Episode *e); typedef void (*GNUNET_ATS_TESTING_ExperimentDoneCallback) (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success); /** * An operation in an experiment */ struct GNUNET_ATS_TEST_Operation { struct GNUNET_ATS_TEST_Operation *next; struct GNUNET_ATS_TEST_Operation *prev; long long unsigned int src_id; long long unsigned int dest_id; long long unsigned int base_rate; long long unsigned int max_rate; struct GNUNET_TIME_Relative period; struct GNUNET_TIME_Relative frequency; enum OperationType type; enum GeneratorType gen_type; enum GNUNET_ATS_PreferenceKind pref_type; }; struct Episode { int id; struct Episode *next; struct GNUNET_TIME_Relative duration; struct GNUNET_ATS_TEST_Operation *head; struct GNUNET_ATS_TEST_Operation *tail; }; struct Experiment { char *name; char *cfg_file; unsigned long long int num_masters; unsigned long long int num_slaves; struct GNUNET_TIME_Relative log_freq; struct GNUNET_TIME_Relative max_duration; struct GNUNET_TIME_Relative total_duration; struct GNUNET_TIME_Absolute start_time; unsigned int num_episodes; struct Episode *start; GNUNET_SCHEDULER_TaskIdentifier experiment_timeout_task; GNUNET_SCHEDULER_TaskIdentifier episode_timeout_task; struct Episode *cur; GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb; GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb; }; /* * Experiment related functions */ extern struct GNUNET_CONFIGURATION_Handle *cfg; /** * Execute the specified experiment * * @param e the Experiment * @param ep_done_cb a episode is completed * @param e_done_cb the experiment is completed */ void GNUNET_ATS_TEST_experimentation_run (struct Experiment *e, GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb, GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb); /** * Load an experiment from a file * * @param filename the file * @return the Experiment or NULL on failure */ struct Experiment * GNUNET_ATS_TEST_experimentation_load (char *filename); /** * Stop an experiment * * @param e the experiment */ void GNUNET_ATS_TEST_experimentation_stop (struct Experiment *e); /* * Traffic related functions */ void GNUNET_ATS_TEST_traffic_handle_ping (struct BenchmarkPartner *p); void GNUNET_ATS_TEST_traffic_handle_pong (struct BenchmarkPartner *p); /** * Generate between the source master and the partner and send traffic with a * maximum rate. * * @param src traffic source * @param dest traffic partner * @param type type of traffic to generate * @param base_rate traffic base rate to send data with * @param max_rate traffic maximum rate to send data with * @param period duration of a period of traffic generation (~ 1/frequency) * @param duration how long to generate traffic * @return the traffic generator */ struct TrafficGenerator * GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src, struct BenchmarkPartner *dest, enum GeneratorType type, long int base_rate, long int max_rate, struct GNUNET_TIME_Relative period, struct GNUNET_TIME_Relative duration); void GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg); /** * Stop all traffic generators */ void GNUNET_ATS_TEST_generate_traffic_stop_all (); /** * Generate between the source master and the partner and set preferences with a * value depending on the generator. * * @param src source * @param dest partner * @param type type of preferences to generate * @param base_value traffic base rate to send data with * @param value_rate traffic maximum rate to send data with * @param period duration of a period of preferences generation (~ 1/frequency) * @param frequency how long to generate preferences * @param kind ATS preference to generate * @return the traffic generator */ struct PreferenceGenerator * GNUNET_ATS_TEST_generate_preferences_start (struct BenchmarkPeer *src, struct BenchmarkPartner *dest, enum GeneratorType type, long int base_value, long int value_rate, struct GNUNET_TIME_Relative period, struct GNUNET_TIME_Relative frequency, enum GNUNET_ATS_PreferenceKind kind); void GNUNET_ATS_TEST_generate_preferences_stop (struct PreferenceGenerator *pg); void GNUNET_ATS_TEST_generate_preferences_stop_all (); /* * Logging related functions */ /** * Start logging * * @param log_frequency the logging frequency * @param testname the testname * @param masters the master peers used for benchmarking * @param num_masters the number of master peers * @param num_slaves the number of slave peers * @param verbose verbose logging * @return the logging handle or NULL on error */ struct LoggingHandle * GNUNET_ATS_TEST_logging_start(struct GNUNET_TIME_Relative log_frequency, char *testname, struct BenchmarkPeer *masters, int num_masters, int num_slaves, int verbose); /** * Stop logging * * @param l the logging handle */ void GNUNET_ATS_TEST_logging_clean_up (struct LoggingHandle *l); /** * Stop logging * * @param l the logging handle */ void GNUNET_ATS_TEST_logging_stop (struct LoggingHandle *l); /** * Log all data now * * @param l logging handle to use */ void GNUNET_ATS_TEST_logging_now (struct LoggingHandle *l); /** * Write logging data to file * * @param l logging handle to use * @param test_name name of the current test * @param plots create gnuplots: GNUNET_YES or GNUNET_NO */ void GNUNET_ATS_TEST_logging_write_to_file (struct LoggingHandle *l, char *test_name, int plots); /* * Topology related functions */ struct BenchmarkPeer * GNUNET_ATS_TEST_get_peer (int src); struct BenchmarkPartner * GNUNET_ATS_TEST_get_partner (int src, int dest); /** * Create a topology for ats testing * * @param name test name * @param cfg_file configuration file to use for the peers * @param num_slaves number of slaves * @param num_masters number of masters * @param test_core connect to CORE service (GNUNET_YES) or transport (GNUNET_NO) * @param done_cb function to call when topology is setup * @param done_cb_cls cls for callback * @param transport_recv_cb callback to call when data are received * @param log_request_cb callback to call when logging is required */ void GNUNET_ATS_TEST_create_topology (char *name, char *cfg_file, unsigned int num_slaves, unsigned int num_masters, int test_core, GNUNET_ATS_TEST_TopologySetupDoneCallback done_cb, void *done_cb_cls, GNUNET_TRANSPORT_ReceiveCallback recv_cb, GNUNET_ATS_TEST_LogRequest ats_perf_cb); /** * Shutdown topology */ void GNUNET_ATS_TEST_shutdown_topology (void); /* end of file ats-testing.h */ gnunet-0.10.1/src/ats-tests/perf_ats_ril_none.conf0000644000175000017500000000006112225230043017055 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = RILgnunet-0.10.1/src/ats-tests/perf_ats_proportional_latency.conf0000644000175000017500000000007312225230043021522 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = PROPORTIONAL gnunet-0.10.1/src/ats-tests/ats-testing-traffic.c0000644000175000017500000003153512274162760016570 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing-traffic.c * @brief ats benchmark: traffic generator * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "ats-testing.h" static struct TrafficGenerator *tg_head; static struct TrafficGenerator *tg_tail; extern struct GNUNET_ATS_TEST_Topology *top; static struct GNUNET_TIME_Relative get_delay (struct TrafficGenerator *tg) { struct GNUNET_TIME_Relative delay; struct GNUNET_TIME_Relative time_delta; long long int cur_rate; long long int delta_rate; delay.rel_value_us = 0; /* Calculate the current transmission rate based on the type of traffic */ switch (tg->type) { case GNUNET_ATS_TEST_TG_CONSTANT: if (UINT32_MAX == tg->base_rate) return GNUNET_TIME_UNIT_ZERO; cur_rate = tg->base_rate; break; case GNUNET_ATS_TEST_TG_LINEAR: time_delta = GNUNET_TIME_absolute_get_duration(tg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % tg->duration_period.rel_value_us; delta_rate = ((double) time_delta.rel_value_us / tg->duration_period.rel_value_us) * (tg->max_rate - tg->base_rate); if ((tg->max_rate < tg->base_rate) && ((tg->max_rate - tg->base_rate) > tg->base_rate)) { /* This will cause an underflow */ GNUNET_break (0); } cur_rate = tg->base_rate + delta_rate; break; case GNUNET_ATS_TEST_TG_RANDOM: cur_rate = tg->base_rate + GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, tg->max_rate - tg->base_rate); break; case GNUNET_ATS_TEST_TG_SINUS: time_delta = GNUNET_TIME_absolute_get_duration(tg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % tg->duration_period.rel_value_us; if ((tg->max_rate - tg->base_rate) > tg->base_rate) { /* This will cause an underflow for second half of sinus period, * will be detected in general when experiments are loaded */ GNUNET_break (0); } delta_rate = (tg->max_rate - tg->base_rate) * sin ( (2 * M_PI) / ((double) tg->duration_period.rel_value_us) * time_delta.rel_value_us); cur_rate = tg->base_rate + delta_rate; break; default: return delay; break; } if (cur_rate < 0) { cur_rate = 1; } /* Calculate the delay for the next message based on the current delay */ delay.rel_value_us = GNUNET_TIME_UNIT_SECONDS.rel_value_us * TEST_MESSAGE_SIZE / cur_rate; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Current rate is %u, calculated delay is %u \n", cur_rate, delay.rel_value_us); return delay; } static size_t send_ping_ready_cb (void *cls, size_t size, void *buf) { struct BenchmarkPartner *p = cls; static char msgbuf[TEST_MESSAGE_SIZE]; struct GNUNET_MessageHeader *msg; struct GNUNET_TIME_Relative delay; if (NULL == buf) { GNUNET_break (0); return 0; } if (size < TEST_MESSAGE_SIZE) { GNUNET_break (0); return 0; } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: Sending PING to [%u]\n", p->me->no, p->dest->no); if (top->test_core) { if (NULL == p->cth) { GNUNET_break (0); } p->cth = NULL; } else { if (NULL == p->tth) { GNUNET_break (0); } p->tth = NULL; } msg = (struct GNUNET_MessageHeader *) &msgbuf; memset (&msgbuf, 'a', TEST_MESSAGE_SIZE); msg->type = htons (TEST_MESSAGE_TYPE_PING); msg->size = htons (TEST_MESSAGE_SIZE); memcpy (buf, msg, TEST_MESSAGE_SIZE); p->messages_sent++; p->bytes_sent += TEST_MESSAGE_SIZE; p->me->total_messages_sent++; p->me->total_bytes_sent += TEST_MESSAGE_SIZE; if (NULL == p->tg) { GNUNET_break (0); return TEST_MESSAGE_SIZE; } delay = get_delay (p->tg); GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Delay for next transmission %llu ms\n", (long long unsigned int) delay.rel_value_us / 1000); p->tg->next_ping_transmission = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay); return TEST_MESSAGE_SIZE; } static void comm_schedule_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct BenchmarkPartner *p = cls; p->tg->send_task = GNUNET_SCHEDULER_NO_TASK; p->last_message_sent = GNUNET_TIME_absolute_get(); if (GNUNET_YES == top->test_core) { p->cth = GNUNET_CORE_notify_transmit_ready (p->me->ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE, &send_ping_ready_cb, p); } else { p->tth = GNUNET_TRANSPORT_notify_transmit_ready (p->me->th, &p->dest->id, TEST_MESSAGE_SIZE, GNUNET_TIME_UNIT_MINUTES, &send_ping_ready_cb, p); } } static size_t comm_send_pong_ready (void *cls, size_t size, void *buf) { static char msgbuf[TEST_MESSAGE_SIZE]; struct BenchmarkPartner *p = cls; struct GNUNET_MessageHeader *msg; if (GNUNET_YES == top->test_core) p->cth = NULL; else p->tth = NULL; p->messages_sent++; p->bytes_sent += TEST_MESSAGE_SIZE; p->me->total_messages_sent++; p->me->total_bytes_sent += TEST_MESSAGE_SIZE; msg = (struct GNUNET_MessageHeader *) &msgbuf; memset (&msgbuf, 'a', TEST_MESSAGE_SIZE); msg->type = htons (TEST_MESSAGE_TYPE_PONG); msg->size = htons (TEST_MESSAGE_SIZE); memcpy (buf, msg, TEST_MESSAGE_SIZE); return TEST_MESSAGE_SIZE; } void GNUNET_ATS_TEST_traffic_handle_ping (struct BenchmarkPartner *p) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Slave [%u]: Received PING from [%u], sending PONG\n", p->me->no, p->dest->no); p->messages_received++; p->bytes_received += TEST_MESSAGE_SIZE; p->me->total_messages_received++; p->me->total_bytes_received += TEST_MESSAGE_SIZE; if (GNUNET_YES == top->test_core) { GNUNET_assert (NULL == p->cth); p->cth = GNUNET_CORE_notify_transmit_ready (p->me->ch, GNUNET_NO, GNUNET_CORE_PRIO_BEST_EFFORT, GNUNET_TIME_UNIT_MINUTES, &p->dest->id, TEST_MESSAGE_SIZE, &comm_send_pong_ready, p); } else { GNUNET_assert (NULL == p->tth); p->tth = GNUNET_TRANSPORT_notify_transmit_ready (p->me->th, &p->dest->id, TEST_MESSAGE_SIZE, GNUNET_TIME_UNIT_MINUTES, &comm_send_pong_ready, p); } } void GNUNET_ATS_TEST_traffic_handle_pong (struct BenchmarkPartner *p) { struct GNUNET_TIME_Relative left; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: Received PONG from [%u], next message\n", p->me->no, p->dest->no); p->messages_received++; p->bytes_received += TEST_MESSAGE_SIZE; p->me->total_messages_received++; p->me->total_bytes_received += TEST_MESSAGE_SIZE; p->total_app_rtt += GNUNET_TIME_absolute_get_difference(p->last_message_sent, GNUNET_TIME_absolute_get()).rel_value_us; /* Schedule next send event */ if (NULL == p->tg) return; left = GNUNET_TIME_absolute_get_remaining(p->tg->next_ping_transmission); if (UINT32_MAX == p->tg->base_rate) { p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p); } else if (0 == left.rel_value_us) { p->tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, p); } else { /* Enforce minimum transmission rate 1 msg / sec */ if (GNUNET_TIME_UNIT_SECONDS.rel_value_us == (left = GNUNET_TIME_relative_min (left, GNUNET_TIME_UNIT_SECONDS)).rel_value_us) GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Enforcing minimum send rate between master [%u] and slave [%u]\n", p->me->no, p->dest->no); p->tg->send_task = GNUNET_SCHEDULER_add_delayed (left, &comm_schedule_send, p); } } /** * Generate between the source master and the partner and send traffic with a * maximum rate. * * @param src traffic source * @param dest traffic partner * @param type type of traffic to generate * @param base_rate traffic base rate to send data with * @param max_rate traffic maximum rate to send data with * @param period duration of a period of traffic generation (~ 1/frequency) * @param duration how long to generate traffic * @return the traffic generator */ struct TrafficGenerator * GNUNET_ATS_TEST_generate_traffic_start (struct BenchmarkPeer *src, struct BenchmarkPartner *dest, enum GeneratorType type, long int base_rate, long int max_rate, struct GNUNET_TIME_Relative period, struct GNUNET_TIME_Relative duration) { struct TrafficGenerator *tg; if (NULL != dest->tg) { GNUNET_break (0); return NULL; } tg = GNUNET_new (struct TrafficGenerator); GNUNET_CONTAINER_DLL_insert (tg_head, tg_tail, tg); tg->type = type; tg->src = src; tg->dest = dest; tg->base_rate = base_rate; tg->max_rate = max_rate; tg->duration_period = period; tg->time_start = GNUNET_TIME_absolute_get(); tg->next_ping_transmission = GNUNET_TIME_UNIT_FOREVER_ABS; switch (type) { case GNUNET_ATS_TEST_TG_CONSTANT: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up constant traffic generator master[%u] `%s' and slave [%u] `%s' max %u Bips\n", dest->me->no, GNUNET_i2s (&dest->me->id), dest->dest->no, GNUNET_i2s (&dest->dest->id), base_rate); break; case GNUNET_ATS_TEST_TG_LINEAR: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up linear traffic generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bips\n", dest->me->no, GNUNET_i2s (&dest->me->id), dest->dest->no, GNUNET_i2s (&dest->dest->id), base_rate, max_rate); break; case GNUNET_ATS_TEST_TG_SINUS: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up sinus traffic generator master[%u] `%s' and slave [%u] `%s' baserate %u Bips, amplitude %u Bps\n", dest->me->no, GNUNET_i2s (&dest->me->id), dest->dest->no, GNUNET_i2s (&dest->dest->id), base_rate, max_rate); break; case GNUNET_ATS_TEST_TG_RANDOM: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up random traffic generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bps\n", dest->me->no, GNUNET_i2s (&dest->me->id), dest->dest->no, GNUNET_i2s (&dest->dest->id), base_rate, max_rate); break; default: break; } if ( ((GNUNET_YES == top->test_core) && (NULL != dest->cth)) || ((GNUNET_NO == top->test_core) && (NULL != dest->tth)) ) { GNUNET_break (0); GNUNET_CONTAINER_DLL_remove (tg_head, tg_tail, tg); GNUNET_free (tg); return NULL; } dest->tg = tg; tg->send_task = GNUNET_SCHEDULER_add_now (&comm_schedule_send, dest); return tg; } void GNUNET_ATS_TEST_generate_traffic_stop (struct TrafficGenerator *tg) { GNUNET_CONTAINER_DLL_remove (tg_head, tg_tail, tg); tg->dest->tg = NULL; if (GNUNET_SCHEDULER_NO_TASK != tg->send_task) { GNUNET_SCHEDULER_cancel (tg->send_task); tg->send_task = GNUNET_SCHEDULER_NO_TASK; } if (top->test_core) { if (NULL != tg->dest->cth) { GNUNET_CORE_notify_transmit_ready_cancel (tg->dest->cth); tg->dest->cth = NULL; } } else { if (NULL != tg->dest->tth) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (tg->dest->tth); tg->dest->tth = NULL; } } GNUNET_free (tg); } /** * Stop all traffic generators */ void GNUNET_ATS_TEST_generate_traffic_stop_all () { struct TrafficGenerator *cur; struct TrafficGenerator *next; next = tg_head; for (cur = next; NULL != cur; cur = next) { next = cur->next; GNUNET_ATS_TEST_generate_traffic_stop(cur); } } /* end of file ats-testing-traffic.c */ gnunet-0.10.1/src/ats-tests/perf_ats_mlp_none.conf0000644000175000017500000000006112225230043017057 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = MLPgnunet-0.10.1/src/ats-tests/Makefile.in0000644000175000017500000016544412320752372014616 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = $(am__EXEEXT_2) noinst_PROGRAMS = gnunet-ats-sim$(EXEEXT) gnunet-solver-eval$(EXEEXT) subdir = src/ats-tests DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunetatstesting_la_OBJECTS = ats-testing.lo ats-testing-log.lo \ ats-testing-traffic.lo ats-testing-experiment.lo \ ats-testing-preferences.lo libgnunetatstesting_la_OBJECTS = $(am_libgnunetatstesting_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetatstesting_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetatstesting_la_LDFLAGS) \ $(LDFLAGS) -o $@ @HAVE_LIBGLPK_TRUE@am__EXEEXT_1 = \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_transport_none$(EXEEXT) \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_core_none$(EXEEXT) \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_transport_bandwidth$(EXEEXT) \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_core_bandwidth$(EXEEXT) \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_transport_latency$(EXEEXT) \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_core_latency$(EXEEXT) @HAVE_TESTING_TRUE@am__EXEEXT_2 = perf_ats_proportional_transport_none$(EXEEXT) \ @HAVE_TESTING_TRUE@ perf_ats_proportional_core_none$(EXEEXT) \ @HAVE_TESTING_TRUE@ perf_ats_proportional_transport_bandwidth$(EXEEXT) \ @HAVE_TESTING_TRUE@ perf_ats_proportional_core_bandwidth$(EXEEXT) \ @HAVE_TESTING_TRUE@ perf_ats_proportional_transport_latency$(EXEEXT) \ @HAVE_TESTING_TRUE@ perf_ats_proportional_core_latency$(EXEEXT) \ @HAVE_TESTING_TRUE@ $(am__EXEEXT_1) PROGRAMS = $(noinst_PROGRAMS) am_gnunet_ats_sim_OBJECTS = gnunet-ats-sim.$(OBJEXT) gnunet_ats_sim_OBJECTS = $(am_gnunet_ats_sim_OBJECTS) am_gnunet_solver_eval_OBJECTS = gnunet-solver-eval.$(OBJEXT) gnunet_solver_eval_OBJECTS = $(am_gnunet_solver_eval_OBJECTS) am_perf_ats_mlp_core_bandwidth_OBJECTS = perf_ats.$(OBJEXT) perf_ats_mlp_core_bandwidth_OBJECTS = \ $(am_perf_ats_mlp_core_bandwidth_OBJECTS) am_perf_ats_mlp_core_latency_OBJECTS = perf_ats.$(OBJEXT) perf_ats_mlp_core_latency_OBJECTS = \ $(am_perf_ats_mlp_core_latency_OBJECTS) am_perf_ats_mlp_core_none_OBJECTS = perf_ats.$(OBJEXT) perf_ats_mlp_core_none_OBJECTS = $(am_perf_ats_mlp_core_none_OBJECTS) am_perf_ats_mlp_transport_bandwidth_OBJECTS = perf_ats.$(OBJEXT) perf_ats_mlp_transport_bandwidth_OBJECTS = \ $(am_perf_ats_mlp_transport_bandwidth_OBJECTS) am_perf_ats_mlp_transport_latency_OBJECTS = perf_ats.$(OBJEXT) perf_ats_mlp_transport_latency_OBJECTS = \ $(am_perf_ats_mlp_transport_latency_OBJECTS) perf_ats_mlp_transport_latency_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la am_perf_ats_mlp_transport_none_OBJECTS = perf_ats.$(OBJEXT) perf_ats_mlp_transport_none_OBJECTS = \ $(am_perf_ats_mlp_transport_none_OBJECTS) am_perf_ats_proportional_core_bandwidth_OBJECTS = perf_ats.$(OBJEXT) perf_ats_proportional_core_bandwidth_OBJECTS = \ $(am_perf_ats_proportional_core_bandwidth_OBJECTS) am_perf_ats_proportional_core_latency_OBJECTS = perf_ats.$(OBJEXT) perf_ats_proportional_core_latency_OBJECTS = \ $(am_perf_ats_proportional_core_latency_OBJECTS) am_perf_ats_proportional_core_none_OBJECTS = perf_ats.$(OBJEXT) perf_ats_proportional_core_none_OBJECTS = \ $(am_perf_ats_proportional_core_none_OBJECTS) am_perf_ats_proportional_transport_bandwidth_OBJECTS = \ perf_ats.$(OBJEXT) perf_ats_proportional_transport_bandwidth_OBJECTS = \ $(am_perf_ats_proportional_transport_bandwidth_OBJECTS) am_perf_ats_proportional_transport_latency_OBJECTS = \ perf_ats.$(OBJEXT) perf_ats_proportional_transport_latency_OBJECTS = \ $(am_perf_ats_proportional_transport_latency_OBJECTS) am_perf_ats_proportional_transport_none_OBJECTS = perf_ats.$(OBJEXT) perf_ats_proportional_transport_none_OBJECTS = \ $(am_perf_ats_proportional_transport_none_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetatstesting_la_SOURCES) $(gnunet_ats_sim_SOURCES) \ $(gnunet_solver_eval_SOURCES) \ $(perf_ats_mlp_core_bandwidth_SOURCES) \ $(perf_ats_mlp_core_latency_SOURCES) \ $(perf_ats_mlp_core_none_SOURCES) \ $(perf_ats_mlp_transport_bandwidth_SOURCES) \ $(perf_ats_mlp_transport_latency_SOURCES) \ $(perf_ats_mlp_transport_none_SOURCES) \ $(perf_ats_proportional_core_bandwidth_SOURCES) \ $(perf_ats_proportional_core_latency_SOURCES) \ $(perf_ats_proportional_core_none_SOURCES) \ $(perf_ats_proportional_transport_bandwidth_SOURCES) \ $(perf_ats_proportional_transport_latency_SOURCES) \ $(perf_ats_proportional_transport_none_SOURCES) DIST_SOURCES = $(libgnunetatstesting_la_SOURCES) \ $(gnunet_ats_sim_SOURCES) $(gnunet_solver_eval_SOURCES) \ $(perf_ats_mlp_core_bandwidth_SOURCES) \ $(perf_ats_mlp_core_latency_SOURCES) \ $(perf_ats_mlp_core_none_SOURCES) \ $(perf_ats_mlp_transport_bandwidth_SOURCES) \ $(perf_ats_mlp_transport_latency_SOURCES) \ $(perf_ats_mlp_transport_none_SOURCES) \ $(perf_ats_proportional_core_bandwidth_SOURCES) \ $(perf_ats_proportional_core_latency_SOURCES) \ $(perf_ats_proportional_core_none_SOURCES) \ $(perf_ats_proportional_transport_bandwidth_SOURCES) \ $(perf_ats_proportional_transport_latency_SOURCES) \ $(perf_ats_proportional_transport_none_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = -fprofile-arcs -ftest-coverage @HAVE_LIBGLPK_TRUE@PERF_MLP = perf_ats_mlp_transport_none \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_core_none \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_transport_bandwidth \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_core_bandwidth \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_transport_latency \ @HAVE_LIBGLPK_TRUE@ perf_ats_mlp_core_latency @HAVE_TESTING_TRUE@TESTING_TESTS = \ @HAVE_TESTING_TRUE@ perf_ats_proportional_transport_none \ @HAVE_TESTING_TRUE@ perf_ats_proportional_core_none \ @HAVE_TESTING_TRUE@ perf_ats_proportional_transport_bandwidth \ @HAVE_TESTING_TRUE@ perf_ats_proportional_core_bandwidth \ @HAVE_TESTING_TRUE@ perf_ats_proportional_transport_latency \ @HAVE_TESTING_TRUE@ perf_ats_proportional_core_latency \ @HAVE_TESTING_TRUE@ $(PERF_MLP) # perf_ats_ril_transport_none perf_ats_ril_core_none perf_ats_ril_transport_bandwidth perf_ats_ril_core_bandwidth perf_ats_ril_transport_latency perf_ats_ril_core_latency lib_LTLIBRARIES = \ libgnunetatstesting.la @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) libgnunetatstesting_la_SOURCES = \ ats-testing.c ats-testing.h \ ats-testing-log.c ats-testing-traffic.c \ ats-testing-experiment.c ats-testing-preferences.c libgnunetatstesting_la_LIBADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(GN_LIBINTL) libgnunetatstesting_la_DEPENDENCIES = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la libgnunetatstesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) gnunet_ats_sim_SOURCES = \ gnunet-ats-sim.c gnunet_ats_sim_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la gnunet_ats_sim_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_solver_eval_SOURCES = \ gnunet-solver-eval.c gnunet_solver_eval_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la gnunet_solver_eval_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_core_none_SOURCES = \ perf_ats.c perf_ats_proportional_core_none_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_core_none_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_transport_none_SOURCES = \ perf_ats.c perf_ats_proportional_transport_none_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_transport_none_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_core_bandwidth_SOURCES = \ perf_ats.c perf_ats_proportional_core_bandwidth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_core_bandwidth_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_transport_bandwidth_SOURCES = \ perf_ats.c perf_ats_proportional_transport_bandwidth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_transport_bandwidth_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_core_latency_SOURCES = \ perf_ats.c perf_ats_proportional_core_latency_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_core_latency_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_transport_latency_SOURCES = \ perf_ats.c perf_ats_proportional_transport_latency_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_transport_latency_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_core_none_SOURCES = \ perf_ats.c perf_ats_mlp_core_none_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_core_none_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_transport_none_SOURCES = \ perf_ats.c perf_ats_mlp_transport_none_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_transport_none_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_core_bandwidth_SOURCES = \ perf_ats.c perf_ats_mlp_core_bandwidth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_core_bandwidth_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_transport_bandwidth_SOURCES = \ perf_ats.c perf_ats_mlp_transport_bandwidth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_transport_bandwidth_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_core_latency_SOURCES = \ perf_ats.c perf_ats_mlp_core_latency_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_core_latency_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_transport_latency_SOURCES = \ perf_ats.c perf_ats_mlp_transport_latency_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_transport_latencyDEPENDENCIES = \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la #perf_ats_ril_core_none_SOURCES = \ # perf_ats.c #perf_ats_ril_core_none_LDADD = \ # $(top_builddir)/src/util/libgnunetutil.la \ # $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ # $(top_builddir)/src/testbed/libgnunettestbed.la \ # $(top_builddir)/src/ats/libgnunetats.la \ # $(top_builddir)/src/core/libgnunetcore.la \ # $(top_builddir)/src/transport/libgnunettransport.la #perf_ats_ril_core_none_DEPENDENCIES = \ # libgnunetatstesting.la \ # $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ gnunet_ats_sim_default.conf \ perf_ats_proportional_none.conf \ perf_ats_proportional_bandwidth.conf \ perf_ats_proportional_latency.conf \ perf_ats_mlp_none.conf \ perf_ats_mlp_bandwidth.conf \ perf_ats_mlp_latency.conf \ perf_ats_ril_none.conf \ perf_ats_ril_bandwidth.conf \ perf_ats_ril_latency.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/ats-tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/ats-tests/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetatstesting.la: $(libgnunetatstesting_la_OBJECTS) $(libgnunetatstesting_la_DEPENDENCIES) $(EXTRA_libgnunetatstesting_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetatstesting_la_LINK) -rpath $(libdir) $(libgnunetatstesting_la_OBJECTS) $(libgnunetatstesting_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-ats-sim$(EXEEXT): $(gnunet_ats_sim_OBJECTS) $(gnunet_ats_sim_DEPENDENCIES) $(EXTRA_gnunet_ats_sim_DEPENDENCIES) @rm -f gnunet-ats-sim$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_ats_sim_OBJECTS) $(gnunet_ats_sim_LDADD) $(LIBS) gnunet-solver-eval$(EXEEXT): $(gnunet_solver_eval_OBJECTS) $(gnunet_solver_eval_DEPENDENCIES) $(EXTRA_gnunet_solver_eval_DEPENDENCIES) @rm -f gnunet-solver-eval$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_solver_eval_OBJECTS) $(gnunet_solver_eval_LDADD) $(LIBS) perf_ats_mlp_core_bandwidth$(EXEEXT): $(perf_ats_mlp_core_bandwidth_OBJECTS) $(perf_ats_mlp_core_bandwidth_DEPENDENCIES) $(EXTRA_perf_ats_mlp_core_bandwidth_DEPENDENCIES) @rm -f perf_ats_mlp_core_bandwidth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_mlp_core_bandwidth_OBJECTS) $(perf_ats_mlp_core_bandwidth_LDADD) $(LIBS) perf_ats_mlp_core_latency$(EXEEXT): $(perf_ats_mlp_core_latency_OBJECTS) $(perf_ats_mlp_core_latency_DEPENDENCIES) $(EXTRA_perf_ats_mlp_core_latency_DEPENDENCIES) @rm -f perf_ats_mlp_core_latency$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_mlp_core_latency_OBJECTS) $(perf_ats_mlp_core_latency_LDADD) $(LIBS) perf_ats_mlp_core_none$(EXEEXT): $(perf_ats_mlp_core_none_OBJECTS) $(perf_ats_mlp_core_none_DEPENDENCIES) $(EXTRA_perf_ats_mlp_core_none_DEPENDENCIES) @rm -f perf_ats_mlp_core_none$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_mlp_core_none_OBJECTS) $(perf_ats_mlp_core_none_LDADD) $(LIBS) perf_ats_mlp_transport_bandwidth$(EXEEXT): $(perf_ats_mlp_transport_bandwidth_OBJECTS) $(perf_ats_mlp_transport_bandwidth_DEPENDENCIES) $(EXTRA_perf_ats_mlp_transport_bandwidth_DEPENDENCIES) @rm -f perf_ats_mlp_transport_bandwidth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_mlp_transport_bandwidth_OBJECTS) $(perf_ats_mlp_transport_bandwidth_LDADD) $(LIBS) perf_ats_mlp_transport_latency$(EXEEXT): $(perf_ats_mlp_transport_latency_OBJECTS) $(perf_ats_mlp_transport_latency_DEPENDENCIES) $(EXTRA_perf_ats_mlp_transport_latency_DEPENDENCIES) @rm -f perf_ats_mlp_transport_latency$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_mlp_transport_latency_OBJECTS) $(perf_ats_mlp_transport_latency_LDADD) $(LIBS) perf_ats_mlp_transport_none$(EXEEXT): $(perf_ats_mlp_transport_none_OBJECTS) $(perf_ats_mlp_transport_none_DEPENDENCIES) $(EXTRA_perf_ats_mlp_transport_none_DEPENDENCIES) @rm -f perf_ats_mlp_transport_none$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_mlp_transport_none_OBJECTS) $(perf_ats_mlp_transport_none_LDADD) $(LIBS) perf_ats_proportional_core_bandwidth$(EXEEXT): $(perf_ats_proportional_core_bandwidth_OBJECTS) $(perf_ats_proportional_core_bandwidth_DEPENDENCIES) $(EXTRA_perf_ats_proportional_core_bandwidth_DEPENDENCIES) @rm -f perf_ats_proportional_core_bandwidth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_proportional_core_bandwidth_OBJECTS) $(perf_ats_proportional_core_bandwidth_LDADD) $(LIBS) perf_ats_proportional_core_latency$(EXEEXT): $(perf_ats_proportional_core_latency_OBJECTS) $(perf_ats_proportional_core_latency_DEPENDENCIES) $(EXTRA_perf_ats_proportional_core_latency_DEPENDENCIES) @rm -f perf_ats_proportional_core_latency$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_proportional_core_latency_OBJECTS) $(perf_ats_proportional_core_latency_LDADD) $(LIBS) perf_ats_proportional_core_none$(EXEEXT): $(perf_ats_proportional_core_none_OBJECTS) $(perf_ats_proportional_core_none_DEPENDENCIES) $(EXTRA_perf_ats_proportional_core_none_DEPENDENCIES) @rm -f perf_ats_proportional_core_none$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_proportional_core_none_OBJECTS) $(perf_ats_proportional_core_none_LDADD) $(LIBS) perf_ats_proportional_transport_bandwidth$(EXEEXT): $(perf_ats_proportional_transport_bandwidth_OBJECTS) $(perf_ats_proportional_transport_bandwidth_DEPENDENCIES) $(EXTRA_perf_ats_proportional_transport_bandwidth_DEPENDENCIES) @rm -f perf_ats_proportional_transport_bandwidth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_proportional_transport_bandwidth_OBJECTS) $(perf_ats_proportional_transport_bandwidth_LDADD) $(LIBS) perf_ats_proportional_transport_latency$(EXEEXT): $(perf_ats_proportional_transport_latency_OBJECTS) $(perf_ats_proportional_transport_latency_DEPENDENCIES) $(EXTRA_perf_ats_proportional_transport_latency_DEPENDENCIES) @rm -f perf_ats_proportional_transport_latency$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_proportional_transport_latency_OBJECTS) $(perf_ats_proportional_transport_latency_LDADD) $(LIBS) perf_ats_proportional_transport_none$(EXEEXT): $(perf_ats_proportional_transport_none_OBJECTS) $(perf_ats_proportional_transport_none_DEPENDENCIES) $(EXTRA_perf_ats_proportional_transport_none_DEPENDENCIES) @rm -f perf_ats_proportional_transport_none$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_ats_proportional_transport_none_OBJECTS) $(perf_ats_proportional_transport_none_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ats-testing-experiment.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ats-testing-log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ats-testing-preferences.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ats-testing-traffic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ats-testing.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-ats-sim.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-solver-eval.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_ats.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? perf_ats_proportional_transport_none.log: perf_ats_proportional_transport_none$(EXEEXT) @p='perf_ats_proportional_transport_none$(EXEEXT)'; \ b='perf_ats_proportional_transport_none'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_proportional_core_none.log: perf_ats_proportional_core_none$(EXEEXT) @p='perf_ats_proportional_core_none$(EXEEXT)'; \ b='perf_ats_proportional_core_none'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_proportional_transport_bandwidth.log: perf_ats_proportional_transport_bandwidth$(EXEEXT) @p='perf_ats_proportional_transport_bandwidth$(EXEEXT)'; \ b='perf_ats_proportional_transport_bandwidth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_proportional_core_bandwidth.log: perf_ats_proportional_core_bandwidth$(EXEEXT) @p='perf_ats_proportional_core_bandwidth$(EXEEXT)'; \ b='perf_ats_proportional_core_bandwidth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_proportional_transport_latency.log: perf_ats_proportional_transport_latency$(EXEEXT) @p='perf_ats_proportional_transport_latency$(EXEEXT)'; \ b='perf_ats_proportional_transport_latency'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_proportional_core_latency.log: perf_ats_proportional_core_latency$(EXEEXT) @p='perf_ats_proportional_core_latency$(EXEEXT)'; \ b='perf_ats_proportional_core_latency'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_mlp_transport_none.log: perf_ats_mlp_transport_none$(EXEEXT) @p='perf_ats_mlp_transport_none$(EXEEXT)'; \ b='perf_ats_mlp_transport_none'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_mlp_core_none.log: perf_ats_mlp_core_none$(EXEEXT) @p='perf_ats_mlp_core_none$(EXEEXT)'; \ b='perf_ats_mlp_core_none'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_mlp_transport_bandwidth.log: perf_ats_mlp_transport_bandwidth$(EXEEXT) @p='perf_ats_mlp_transport_bandwidth$(EXEEXT)'; \ b='perf_ats_mlp_transport_bandwidth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_mlp_core_bandwidth.log: perf_ats_mlp_core_bandwidth$(EXEEXT) @p='perf_ats_mlp_core_bandwidth$(EXEEXT)'; \ b='perf_ats_mlp_core_bandwidth'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_mlp_transport_latency.log: perf_ats_mlp_transport_latency$(EXEEXT) @p='perf_ats_mlp_transport_latency$(EXEEXT)'; \ b='perf_ats_mlp_transport_latency'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) perf_ats_mlp_core_latency.log: perf_ats_mlp_core_latency$(EXEEXT) @p='perf_ats_mlp_core_latency$(EXEEXT)'; \ b='perf_ats_mlp_core_latency'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(libdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-noinstPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/ats-tests/perf_ats_mlp_latency.conf0000644000175000017500000000006212225230043017560 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = MLP gnunet-0.10.1/src/ats-tests/Makefile.am0000644000175000017500000002270312320752366014576 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = -fprofile-arcs -ftest-coverage endif if HAVE_LIBGLPK PERF_MLP = perf_ats_mlp_transport_none \ perf_ats_mlp_core_none \ perf_ats_mlp_transport_bandwidth \ perf_ats_mlp_core_bandwidth \ perf_ats_mlp_transport_latency \ perf_ats_mlp_core_latency endif if HAVE_TESTING TESTING_TESTS = \ perf_ats_proportional_transport_none \ perf_ats_proportional_core_none \ perf_ats_proportional_transport_bandwidth \ perf_ats_proportional_core_bandwidth \ perf_ats_proportional_transport_latency \ perf_ats_proportional_core_latency \ $(PERF_MLP) # perf_ats_ril_transport_none perf_ats_ril_core_none perf_ats_ril_transport_bandwidth perf_ats_ril_core_bandwidth perf_ats_ril_transport_latency perf_ats_ril_core_latency endif lib_LTLIBRARIES = \ libgnunetatstesting.la check_PROGRAMS = \ $(TESTING_TESTS) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif noinst_PROGRAMS = \ gnunet-ats-sim gnunet-solver-eval libgnunetatstesting_la_SOURCES = \ ats-testing.c ats-testing.h \ ats-testing-log.c ats-testing-traffic.c \ ats-testing-experiment.c ats-testing-preferences.c libgnunetatstesting_la_LIBADD = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(GN_LIBINTL) libgnunetatstesting_la_DEPENDENCIES = \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la libgnunetatstesting_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) gnunet_ats_sim_SOURCES = \ gnunet-ats-sim.c gnunet_ats_sim_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la gnunet_ats_sim_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la gnunet_solver_eval_SOURCES = \ gnunet-solver-eval.c gnunet_solver_eval_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la gnunet_solver_eval_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_core_none_SOURCES = \ perf_ats.c perf_ats_proportional_core_none_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_core_none_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_transport_none_SOURCES = \ perf_ats.c perf_ats_proportional_transport_none_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_transport_none_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_core_bandwidth_SOURCES = \ perf_ats.c perf_ats_proportional_core_bandwidth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_core_bandwidth_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_transport_bandwidth_SOURCES = \ perf_ats.c perf_ats_proportional_transport_bandwidth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_transport_bandwidth_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_core_latency_SOURCES = \ perf_ats.c perf_ats_proportional_core_latency_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_core_latency_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_proportional_transport_latency_SOURCES = \ perf_ats.c perf_ats_proportional_transport_latency_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_proportional_transport_latency_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_core_none_SOURCES = \ perf_ats.c perf_ats_mlp_core_none_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_core_none_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_transport_none_SOURCES = \ perf_ats.c perf_ats_mlp_transport_none_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_transport_none_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_core_bandwidth_SOURCES = \ perf_ats.c perf_ats_mlp_core_bandwidth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_core_bandwidth_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_transport_bandwidth_SOURCES = \ perf_ats.c perf_ats_mlp_transport_bandwidth_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_transport_bandwidth_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_core_latency_SOURCES = \ perf_ats.c perf_ats_mlp_core_latency_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_core_latency_DEPENDENCIES = \ libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la perf_ats_mlp_transport_latency_SOURCES = \ perf_ats.c perf_ats_mlp_transport_latency_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ $(top_builddir)/src/ats/libgnunetats.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/transport/libgnunettransport.la perf_ats_mlp_transport_latencyDEPENDENCIES = \ $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ $(top_builddir)/src/util/libgnunetutil.la #perf_ats_ril_core_none_SOURCES = \ # perf_ats.c #perf_ats_ril_core_none_LDADD = \ # $(top_builddir)/src/util/libgnunetutil.la \ # $(top_builddir)/src/ats-tests/libgnunetatstesting.la \ # $(top_builddir)/src/testbed/libgnunettestbed.la \ # $(top_builddir)/src/ats/libgnunetats.la \ # $(top_builddir)/src/core/libgnunetcore.la \ # $(top_builddir)/src/transport/libgnunettransport.la #perf_ats_ril_core_none_DEPENDENCIES = \ # libgnunetatstesting.la \ # $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ gnunet_ats_sim_default.conf \ perf_ats_proportional_none.conf \ perf_ats_proportional_bandwidth.conf \ perf_ats_proportional_latency.conf \ perf_ats_mlp_none.conf \ perf_ats_mlp_bandwidth.conf \ perf_ats_mlp_latency.conf \ perf_ats_ril_none.conf \ perf_ats_ril_bandwidth.conf \ perf_ats_ril_latency.conf gnunet-0.10.1/src/ats-tests/gnunet-ats-sim.c0000644000175000017500000002514112274162760015561 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/gnunet-ats-sim.c * @brief ats traffic simulator: this tool uses the ats-test library to setup a * topology and generate traffic between these peers. The traffic description * is loaded from a experiment description file * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_testbed_service.h" #include "gnunet_ats_service.h" #include "gnunet_core_service.h" #include "ats-testing.h" #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) static struct BenchmarkPeer *masters_p; static struct BenchmarkPeer *slaves_p; /** * cmd option -e: experiment file */ static char *opt_exp_file; /** * cmd option -l: enable logging */ static int opt_log; /** * cmd option -p: enable plots */ static int opt_plot; /** * cmd option -v: verbose logs */ static int opt_verbose; GNUNET_SCHEDULER_TaskIdentifier timeout_task; struct Experiment *e; struct LoggingHandle *l; static void evaluate (struct GNUNET_TIME_Relative duration_total) { int c_m; int c_s; unsigned int duration; struct BenchmarkPeer *mp; struct BenchmarkPartner *p; unsigned int b_sent_sec; double kb_sent_percent; unsigned int b_recv_sec; double kb_recv_percent; unsigned int rtt; duration = (duration_total.rel_value_us / (1000 * 1000)); for (c_m = 0; c_m < e->num_masters; c_m++) { mp = &masters_p[c_m]; fprintf (stderr, _("Master [%u]: sent: %u KiB in %u sec. = %u KiB/s, received: %u KiB in %u sec. = %u KiB/s\n"), mp->no, mp->total_bytes_sent / 1024, duration, (mp->total_bytes_sent / 1024) / duration, mp->total_bytes_received / 1024, duration, (mp->total_bytes_received / 1024) / duration); for (c_s = 0; c_s < e->num_slaves; c_s++) { p = &mp->partners[c_s]; b_sent_sec = 0; b_recv_sec = 0; kb_sent_percent = 0.0; kb_recv_percent = 0.0; rtt = 0; if (duration > 0) { b_sent_sec = p->bytes_sent / duration; b_recv_sec = p->bytes_received / duration; } if (mp->total_bytes_sent > 0) kb_sent_percent = ((double) p->bytes_sent * 100) / mp->total_bytes_sent; if (mp->total_bytes_received > 0) kb_recv_percent = ((double) p->bytes_received * 100) / mp->total_bytes_received; if (1000 * p->messages_sent > 0) rtt = p->total_app_rtt / (1000 * p->messages_sent); fprintf (stderr, "%c Master [%u] -> Slave [%u]: sent %u Bips (%.2f %%), received %u Bips (%.2f %%)\n", (mp->pref_partner == p->dest) ? '*' : ' ', mp->no, p->dest->no, b_sent_sec, kb_sent_percent, b_recv_sec, kb_recv_percent); fprintf (stderr, "%c Master [%u] -> Slave [%u]: Average application layer RTT: %u ms\n", (mp->pref_partner == p->dest) ? '*' : ' ', mp->no, p->dest->no, rtt); } } } static void do_shutdown () { fprintf (stderr, "Shutdown\n"); /* timeout */ if (NULL != l) { GNUNET_ATS_TEST_logging_stop (l); GNUNET_ATS_TEST_logging_clean_up (l); l = NULL; } /* Stop traffic generation */ GNUNET_ATS_TEST_generate_traffic_stop_all(); /* Stop all preference generations */ GNUNET_ATS_TEST_generate_preferences_stop_all (); if (NULL != e) { GNUNET_ATS_TEST_experimentation_stop (e); e = NULL; } GNUNET_ATS_TEST_shutdown_topology (); } static void transport_recv_cb (void *cls, const struct GNUNET_PeerIdentity * peer, const struct GNUNET_MessageHeader * message) { } static void log_request__cb (void *cls, const struct GNUNET_HELLO_Address *address, int address_active, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, const struct GNUNET_ATS_Information *ats, uint32_t ats_count) { if (NULL != l) { //GNUNET_break (0); //GNUNET_ATS_TEST_logging_now (l); } } static void experiment_done_cb (struct Experiment *e, struct GNUNET_TIME_Relative duration,int success) { if (GNUNET_OK == success) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment done successful in %s\n", GNUNET_STRINGS_relative_time_to_string (duration, GNUNET_YES)); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Experiment failed \n"); if (GNUNET_SCHEDULER_NO_TASK != timeout_task) { GNUNET_SCHEDULER_cancel (timeout_task); timeout_task = GNUNET_SCHEDULER_NO_TASK; } /* Stop logging */ GNUNET_ATS_TEST_logging_stop (l); /* Stop traffic generation */ GNUNET_ATS_TEST_generate_traffic_stop_all(); /* Stop all preference generations */ GNUNET_ATS_TEST_generate_preferences_stop_all (); evaluate (duration); if (opt_log) GNUNET_ATS_TEST_logging_write_to_file(l, opt_exp_file, opt_plot); if (NULL != l) { GNUNET_ATS_TEST_logging_stop (l); GNUNET_ATS_TEST_logging_clean_up (l); l = NULL; } /* Clean up experiment */ GNUNET_ATS_TEST_experimentation_stop (e); e = NULL; /* Shutdown topology */ GNUNET_ATS_TEST_shutdown_topology (); } static void episode_done_cb (struct Episode *ep) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Episode %u done\n", ep->id); } static void topology_setup_done (void *cls, struct BenchmarkPeer *masters, struct BenchmarkPeer *slaves) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Topology setup complete!\n"); masters_p = masters; slaves_p = slaves; l = GNUNET_ATS_TEST_logging_start (e->log_freq, e->name, masters_p, e->num_masters, e->num_slaves, opt_verbose); GNUNET_ATS_TEST_experimentation_run (e, &episode_done_cb, &experiment_done_cb); /* GNUNET_ATS_TEST_generate_preferences_start(&masters[0],&masters[0].partners[0], GNUNET_ATS_TEST_TG_CONSTANT, 1, 1, GNUNET_TIME_UNIT_SECONDS, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_ATS_PREFERENCE_BANDWIDTH); */ /* GNUNET_ATS_TEST_generate_preferences_start(&masters[0],&masters[0].partners[0], GNUNET_ATS_TEST_TG_LINEAR, 1, 50, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 2), GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_ATS_PREFERENCE_BANDWIDTH); */ /* GNUNET_ATS_TEST_generate_preferences_start(&masters[0],&masters[0].partners[0], GNUNET_ATS_TEST_TG_RANDOM, 1, 50, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 2), GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_ATS_PREFERENCE_BANDWIDTH); */ /* GNUNET_ATS_TEST_generate_preferences_start(&masters[0],&masters[0].partners[0], GNUNET_ATS_TEST_TG_SINUS, 10, 5, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250), GNUNET_ATS_PREFERENCE_BANDWIDTH); */ #if 0 int c_m; int c_s; for (c_m = 0; c_m < e->num_masters; c_m++) { for (c_s = 0; c_s < e->num_slaves; c_s++) { /* Generate maximum traffic to all peers */ /* Example: Generate traffic with constant 10,000 Bytes/s */ GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m], &masters[c_m].partners[c_s], GNUNET_ATS_TEST_TG_CONSTANT, 10000, GNUNET_TIME_UNIT_FOREVER_REL); /* Example: Generate traffic with an increasing rate from 1000 to 2000 * Bytes/s with in a minute */ GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m], &masters[c_m].partners[c_s], GNUNET_ATS_TEST_TG_LINEAR, 1000, 2000, GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_FOREVER_REL); /* Example: Generate traffic with a random rate between 1000 to 2000 * Bytes/s */ GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m], &masters[c_m].partners[c_s], GNUNET_ATS_TEST_TG_RANDOM, 1000, 2000, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_FOREVER_REL); /* Example: Generate traffic with a sinus form, a base rate of * 1000 Bytes/s, an amplitude of (max-base), and a period of 1 minute */ GNUNET_ATS_TEST_generate_traffic_start (&masters[c_m], &masters[c_m].partners[c_s], GNUNET_ATS_TEST_TG_SINUS, 1000, 2000, GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_FOREVER_REL); } } #endif timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_add (GNUNET_TIME_UNIT_MINUTES, e->max_duration), &do_shutdown, NULL); } static void parse_args (int argc, char *argv[]) { int c; opt_exp_file = NULL; opt_log = GNUNET_NO; opt_plot = GNUNET_NO; for (c = 0; c < argc; c++) { if ((c < (argc - 1)) && (0 == strcmp (argv[c], "-e"))) { opt_exp_file = GNUNET_strdup ( argv[c + 1]); } if (0 == strcmp (argv[c], "-l")) { opt_log = GNUNET_YES; } if (0 == strcmp (argv[c], "-p")) { opt_plot = GNUNET_YES; } if (0 == strcmp (argv[c], "-v")) { opt_verbose = GNUNET_YES; } } } int main (int argc, char *argv[]) { GNUNET_log_setup("gnunet-ats-sim", "INFO", NULL); parse_args (argc, argv); if (NULL == opt_exp_file ) { fprintf (stderr, "No experiment given...\n"); return 1; } fprintf (stderr, "Loading experiment `%s' \n", opt_exp_file ); e = GNUNET_ATS_TEST_experimentation_load (opt_exp_file); if (NULL == e) { fprintf (stderr, "Invalid experiment\n"); return 1; } if (0 == e->num_episodes) { fprintf (stderr, "No episodes included\n"); return 1; } /* Setup a topology with */ GNUNET_ATS_TEST_create_topology ("gnunet-ats-sim", e->cfg_file, e->num_slaves, e->num_masters, GNUNET_NO, &topology_setup_done, NULL, &transport_recv_cb, &log_request__cb); GNUNET_free (opt_exp_file); return 0; } /* end of file gnunet-ats-sim.c */ gnunet-0.10.1/src/ats-tests/perf_ats_mlp_bandwidth.conf0000644000175000017500000000006112225230043020064 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = MLPgnunet-0.10.1/src/ats-tests/perf_ats_ril_bandwidth.conf0000644000175000017500000000006112225230043020062 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = RILgnunet-0.10.1/src/ats-tests/gnunet_ats_sim_default.conf0000644000175000017500000000012612272425070020122 00000000000000@INLINE@ template_perf_ats.conf [transport] plugins = unix [ats] MODE = PROPORTIONAL gnunet-0.10.1/src/ats-tests/perf_ats_proportional_none.conf0000644000175000017500000000007312225230043021022 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = PROPORTIONAL gnunet-0.10.1/src/ats-tests/perf_ats_proportional_bandwidth.conf0000644000175000017500000000007312225230043022027 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = PROPORTIONAL gnunet-0.10.1/src/ats-tests/ats-testing-preferences.c0000644000175000017500000001713712316473376017462 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing-preferences.c * @brief ats benchmark: preference generator * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "ats-testing.h" static struct PreferenceGenerator *pg_head; static struct PreferenceGenerator *pg_tail; extern struct GNUNET_ATS_TEST_Topology *top; static double get_preference (struct PreferenceGenerator *pg) { struct GNUNET_TIME_Relative time_delta; double delta_value; double pref_value; /* Calculate the current preference value */ switch (pg->type) { case GNUNET_ATS_TEST_TG_CONSTANT: pref_value = pg->base_value; break; case GNUNET_ATS_TEST_TG_LINEAR: time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % pg->duration_period.rel_value_us; delta_value = ((double) time_delta.rel_value_us / pg->duration_period.rel_value_us) * (pg->max_value - pg->base_value); if ((pg->max_value < pg->base_value) && ((pg->max_value - pg->base_value) > pg->base_value)) { /* This will cause an underflow */ GNUNET_break (0); } pref_value = pg->base_value + delta_value; break; case GNUNET_ATS_TEST_TG_RANDOM: delta_value = (double) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 10000 * (pg->max_value - pg->base_value)) / 10000; pref_value = pg->base_value + delta_value; break; case GNUNET_ATS_TEST_TG_SINUS: time_delta = GNUNET_TIME_absolute_get_duration(pg->time_start); /* Calculate point of time in the current period */ time_delta.rel_value_us = time_delta.rel_value_us % pg->duration_period.rel_value_us; if ((pg->max_value - pg->base_value) > pg->base_value) { /* This will cause an underflow for second half of sinus period, * will be detected in general when experiments are loaded */ GNUNET_break (0); } delta_value = (pg->max_value - pg->base_value) * sin ( (2 * M_PI) / ((double) pg->duration_period.rel_value_us) * time_delta.rel_value_us); pref_value = pg->base_value + delta_value; break; default: pref_value = 0.0; break; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Current preference value is %f\n", pref_value); return pref_value; } static void set_pref_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct BenchmarkPartner *p = cls; double pref_value; p->pg->set_task = GNUNET_SCHEDULER_NO_TASK; pref_value = get_preference (p->pg); GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Setting preference for master [%u] and slave [%u] for %s to %f\n", p->me->no, p->dest->no, GNUNET_ATS_print_preference_type (p->pg->kind), pref_value); GNUNET_ATS_performance_change_preference(p->me->ats_perf_handle, &p->dest->id, p->pg->kind, pref_value, GNUNET_ATS_PREFERENCE_END); switch (p->pg->kind) { case GNUNET_ATS_PREFERENCE_BANDWIDTH: p->pref_bandwidth = pref_value; break; case GNUNET_ATS_PREFERENCE_LATENCY: p->pref_delay = pref_value; break; default: break; } p->pg->set_task = GNUNET_SCHEDULER_add_delayed (p->pg->frequency, set_pref_task, p); } /** * Generate between the source master and the partner and set preferences with a * value depending on the generator. * * @param src source * @param dest partner * @param type type of preferences to generate * @param base_value traffic base rate to send data with * @param value_rate traffic maximum rate to send data with * @param period duration of a period of preferences generation (~ 1/frequency) * @param frequency how long to generate preferences * @param kind ATS preference to generate * @return the preference generator */ struct PreferenceGenerator * GNUNET_ATS_TEST_generate_preferences_start (struct BenchmarkPeer *src, struct BenchmarkPartner *dest, enum GeneratorType type, long int base_value, long int value_rate, struct GNUNET_TIME_Relative period, struct GNUNET_TIME_Relative frequency, enum GNUNET_ATS_PreferenceKind kind) { struct PreferenceGenerator *pg; if (NULL != dest->pg) { GNUNET_break (0); return NULL; } pg = GNUNET_new (struct PreferenceGenerator); GNUNET_CONTAINER_DLL_insert (pg_head, pg_tail, pg); pg->type = type; pg->src = src; pg->dest = dest; pg->kind = kind; pg->base_value = base_value; pg->max_value = value_rate; pg->duration_period = period; pg->frequency = frequency; pg->time_start = GNUNET_TIME_absolute_get(); switch (type) { case GNUNET_ATS_TEST_TG_CONSTANT: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up constant preference generator master[%u] `%s' and slave [%u] `%s' max %u Bips\n", dest->me->no, GNUNET_i2s (&dest->me->id), dest->dest->no, GNUNET_i2s (&dest->dest->id), base_value); break; case GNUNET_ATS_TEST_TG_LINEAR: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up linear preference generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bips\n", dest->me->no, GNUNET_i2s (&dest->me->id), dest->dest->no, GNUNET_i2s (&dest->dest->id), base_value, value_rate); break; case GNUNET_ATS_TEST_TG_SINUS: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up sinus preference generator master[%u] `%s' and slave [%u] `%s' baserate %u Bips, amplitude %u Bps\n", dest->me->no, GNUNET_i2s (&dest->me->id), dest->dest->no, GNUNET_i2s (&dest->dest->id), base_value, value_rate); break; case GNUNET_ATS_TEST_TG_RANDOM: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting up random preference generator master[%u] `%s' and slave [%u] `%s' min %u Bips max %u Bps\n", dest->me->no, GNUNET_i2s (&dest->me->id), dest->dest->no, GNUNET_i2s (&dest->dest->id), base_value, value_rate); break; default: break; } dest->pg = pg; pg->set_task = GNUNET_SCHEDULER_add_now (&set_pref_task, dest); return pg; } void GNUNET_ATS_TEST_generate_preferences_stop (struct PreferenceGenerator *pg) { GNUNET_CONTAINER_DLL_remove (pg_head, pg_tail, pg); pg->dest->pg = NULL; if (GNUNET_SCHEDULER_NO_TASK != pg->set_task) { GNUNET_SCHEDULER_cancel (pg->set_task); pg->set_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_free (pg); } /** * Stop all preferences generators */ void GNUNET_ATS_TEST_generate_preferences_stop_all () { struct PreferenceGenerator *cur; struct PreferenceGenerator *next; next = pg_head; for (cur = next; NULL != cur; cur = next) { next = cur->next; GNUNET_ATS_TEST_generate_preferences_stop(cur); } } /* end of file ats-testing-preferences.c */ gnunet-0.10.1/src/ats-tests/gnunet-solver-eval.c0000644000175000017500000006001612320724370016434 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing-experiment.c * @brief ats benchmark: controlled experiment execution * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_ats_plugin.h" #include "gnunet_ats_service.h" #include "ats-testing.h" /** * Experiments */ const char * print_op (enum OperationType op) { switch (op) { case START_SEND: return "START_SEND"; case STOP_SEND: return "STOP_SEND"; case START_PREFERENCE: return "START_PREFERENCE"; case STOP_PREFERENCE: return "STOP_PREFERENCE"; default: break; } return ""; } static struct Experiment * create_experiment () { struct Experiment *e; e = GNUNET_new (struct Experiment); e->name = NULL; e->num_masters = 0; e->num_slaves = 0; e->start = NULL; e->total_duration = GNUNET_TIME_UNIT_ZERO; return e; } static void free_experiment (struct Experiment *e) { struct Episode *cur; struct Episode *next; struct GNUNET_ATS_TEST_Operation *cur_o; struct GNUNET_ATS_TEST_Operation *next_o; next = e->start; for (cur = next; NULL != cur; cur = next) { next = cur->next; next_o = cur->head; for (cur_o = next_o; NULL != cur_o; cur_o = next_o) { next_o = cur_o->next; GNUNET_free (cur_o); } GNUNET_free (cur); } GNUNET_free_non_null (e->name); GNUNET_free_non_null (e->cfg_file); GNUNET_free (e); } static int load_episode (struct Experiment *e, struct Episode *cur, struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_ATS_TEST_Operation *o; char *sec_name; char *op_name; char *op; char *type; char *pref; int op_counter = 0; fprintf (stderr, "Parsing episode %u\n",cur->id); GNUNET_asprintf(&sec_name, "episode-%u", cur->id); while (1) { /* Load operation */ GNUNET_asprintf(&op_name, "op-%u-operation", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, sec_name, op_name, &op)) { GNUNET_free (op_name); break; } o = GNUNET_new (struct GNUNET_ATS_TEST_Operation); /* operations = set_rate, start_send, stop_send, set_preference */ if (0 == strcmp (op, "start_send")) { o->type = START_SEND; } else if (0 == strcmp (op, "stop_send")) { o->type = STOP_SEND; } else if (0 == strcmp (op, "start_preference")) { o->type = START_PREFERENCE; } else if (0 == strcmp (op, "stop_preference")) { o->type = STOP_PREFERENCE; } else { fprintf (stderr, "Invalid operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get source */ GNUNET_asprintf(&op_name, "op-%u-src", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->src_id)) { fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } if (o->src_id > (e->num_masters - 1)) { fprintf (stderr, "Invalid src %llu in operation %u `%s' in episode %u\n", o->src_id, op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get destination */ GNUNET_asprintf(&op_name, "op-%u-dest", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->dest_id)) { fprintf (stderr, "Missing src in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } if (o->dest_id > (e->num_slaves - 1)) { fprintf (stderr, "Invalid destination %llu in operation %u `%s' in episode %u\n", o->dest_id, op_counter, op, cur->id); GNUNET_free (op); GNUNET_free (op_name); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } GNUNET_free (op_name); GNUNET_asprintf(&op_name, "op-%u-type", op_counter); if ( (GNUNET_SYSERR != GNUNET_CONFIGURATION_get_value_string(cfg, sec_name, op_name, &type)) && ((STOP_SEND != o->type) || (STOP_PREFERENCE != o->type))) { /* Load arguments for set_rate, start_send, set_preference */ if (0 == strcmp (type, "constant")) { o->gen_type = GNUNET_ATS_TEST_TG_CONSTANT; } else if (0 == strcmp (type, "linear")) { o->gen_type = GNUNET_ATS_TEST_TG_LINEAR; } else if (0 == strcmp (type, "sinus")) { o->gen_type = GNUNET_ATS_TEST_TG_SINUS; } else if (0 == strcmp (type, "random")) { o->gen_type = GNUNET_ATS_TEST_TG_RANDOM; } else { fprintf (stderr, "Invalid type %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op); GNUNET_free (op_name); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get base rate */ GNUNET_asprintf(&op_name, "op-%u-base-rate", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->base_rate)) { fprintf (stderr, "Missing base rate in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op); GNUNET_free (op_name); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get max rate */ GNUNET_asprintf(&op_name, "op-%u-max-rate", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, sec_name, op_name, &o->max_rate)) { if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) || (GNUNET_ATS_TEST_TG_RANDOM == o->gen_type) || (GNUNET_ATS_TEST_TG_SINUS == o->gen_type)) { fprintf (stderr, "Missing max rate in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op_name); GNUNET_free (op); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } } GNUNET_free (op_name); /* Get period */ GNUNET_asprintf(&op_name, "op-%u-period", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, sec_name, op_name, &o->period)) { o->period = cur->duration; } GNUNET_free (op_name); if (START_PREFERENCE == o->type) { /* Get frequency */ GNUNET_asprintf(&op_name, "op-%u-frequency", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (cfg, sec_name, op_name, &o->frequency)) { fprintf (stderr, "Missing frequency in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op_name); GNUNET_free (op); GNUNET_free (sec_name); GNUNET_free (o); return GNUNET_SYSERR; } GNUNET_free (op_name); /* Get preference */ GNUNET_asprintf(&op_name, "op-%u-pref", op_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, sec_name, op_name, &pref)) { fprintf (stderr, "Missing preference in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op_name); GNUNET_free (op); GNUNET_free (sec_name); GNUNET_free_non_null (pref); GNUNET_free (o); return GNUNET_SYSERR; } if (0 == strcmp(pref, "bandwidth")) o->pref_type = GNUNET_ATS_PREFERENCE_BANDWIDTH; else if (0 == strcmp(pref, "latency")) o->pref_type = GNUNET_ATS_PREFERENCE_LATENCY; else { fprintf (stderr, "Invalid preference in operation %u `%s' in episode %u\n", op_counter, op, cur->id); GNUNET_free (type); GNUNET_free (op_name); GNUNET_free (op); GNUNET_free (pref); GNUNET_free (sec_name); GNUNET_free_non_null (pref); GNUNET_free (o); return GNUNET_SYSERR; } GNUNET_free (pref); GNUNET_free (op_name); } } /* Safety checks */ if ((GNUNET_ATS_TEST_TG_LINEAR == o->gen_type) || (GNUNET_ATS_TEST_TG_SINUS == o->gen_type)) { if ((o->max_rate - o->base_rate) > o->base_rate) { /* This will cause an underflow */ GNUNET_break (0); } fprintf (stderr, "Selected max rate and base rate cannot be used for desired traffic form!\n"); } if ((START_SEND == o->type) || (START_PREFERENCE == o->type)) fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu] == %s, %llu -> %llu in %s\n", op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id, (NULL != type) ? type : "", o->base_rate, o->max_rate, GNUNET_STRINGS_relative_time_to_string (o->period, GNUNET_YES)); else fprintf (stderr, "Found operation %u in episode %u: %s [%llu]->[%llu]\n", op_counter, cur->id, print_op (o->type), o->src_id, o->dest_id); GNUNET_free_non_null (type); GNUNET_free (op); GNUNET_CONTAINER_DLL_insert (cur->head,cur->tail, o); op_counter++; } GNUNET_free (sec_name); return GNUNET_OK; } static int load_episodes (struct Experiment *e, struct GNUNET_CONFIGURATION_Handle *cfg) { int e_counter = 0; char *sec_name; struct GNUNET_TIME_Relative e_duration; struct Episode *cur; struct Episode *last; e_counter = 0; last = NULL; while (1) { GNUNET_asprintf(&sec_name, "episode-%u", e_counter); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, sec_name, "duration", &e_duration)) { GNUNET_free (sec_name); break; } cur = GNUNET_new (struct Episode); cur->duration = e_duration; cur->id = e_counter; if (GNUNET_OK != load_episode (e, cur, cfg)) { GNUNET_free (sec_name); GNUNET_free (cur); return GNUNET_SYSERR; } fprintf (stderr, "Found episode %u with duration %s \n", e_counter, GNUNET_STRINGS_relative_time_to_string(cur->duration, GNUNET_YES)); /* Update experiment */ e->num_episodes ++; e->total_duration = GNUNET_TIME_relative_add(e->total_duration, cur->duration); /* Put in linked list */ if (NULL == last) e->start = cur; else last->next = cur; GNUNET_free (sec_name); e_counter ++; last = cur; } return e_counter; } static void timeout_experiment (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { struct Experiment *e = cls; e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; fprintf (stderr, "Experiment timeout!\n"); if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task) { GNUNET_SCHEDULER_cancel (e->episode_timeout_task); e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; } e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_SYSERR); } static void enforce_start_send (struct GNUNET_ATS_TEST_Operation *op) { /* struct BenchmarkPeer *peer; struct BenchmarkPartner *partner; peer = GNUNET_ATS_TEST_get_peer (op->src_id); if (NULL == peer) { GNUNET_break (0); return; } partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id); if (NULL == partner) { GNUNET_break (0); return; } fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id); if (NULL != partner->tg) { fprintf (stderr, "Stopping traffic between master %llu slave %llu\n",op->src_id, op->dest_id); GNUNET_ATS_TEST_generate_traffic_stop(partner->tg); partner->tg = NULL; } partner->tg = GNUNET_ATS_TEST_generate_traffic_start(peer, partner, op->tg_type, op->base_rate, op->max_rate, op->period, GNUNET_TIME_UNIT_FOREVER_REL); */ } static void enforce_stop_send (struct GNUNET_ATS_TEST_Operation *op) { /* struct BenchmarkPartner *p; p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id); if (NULL == p) { GNUNET_break (0); return; } fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id); if (NULL != p->tg) { fprintf (stderr, "Stopping traffic between master %llu slave %llu\n", op->src_id, op->dest_id); GNUNET_ATS_TEST_generate_traffic_stop(p->tg); p->tg = NULL; } */ } static void enforce_start_preference (struct GNUNET_ATS_TEST_Operation *op) { /* struct BenchmarkPeer *peer; struct BenchmarkPartner *partner; peer = GNUNET_ATS_TEST_get_peer (op->src_id); if (NULL == peer) { GNUNET_break (0); return; } partner = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id); if (NULL == partner) { GNUNET_break (0); return; } fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id); if (NULL != partner->pg) { fprintf (stderr, "Stopping traffic between master %llu slave %llu\n", op->src_id, op->dest_id); GNUNET_ATS_TEST_generate_preferences_stop(partner->pg); partner->pg = NULL; } partner->pg = GNUNET_ATS_TEST_generate_preferences_start(peer, partner, op->tg_type, op->base_rate, op->max_rate, op->period, op->frequency, op->pref_type); */ } static void enforce_stop_preference (struct GNUNET_ATS_TEST_Operation *op) { /* struct BenchmarkPartner *p; p = GNUNET_ATS_TEST_get_partner (op->src_id, op->dest_id); if (NULL == p) { GNUNET_break (0); return; } fprintf (stderr, "Found master %llu slave %llu\n",op->src_id, op->dest_id); if (NULL != p->pg) { fprintf (stderr, "Stopping preference between master %llu slave %llu\n", op->src_id, op->dest_id); GNUNET_ATS_TEST_generate_preferences_stop (p->pg); p->pg = NULL; } */ } static void enforce_episode (struct Episode *ep) { struct GNUNET_ATS_TEST_Operation *cur; for (cur = ep->head; NULL != cur; cur = cur->next) { fprintf (stderr, "Enforcing operation: %s [%llu]->[%llu] == %llu\n", print_op (cur->type), cur->src_id, cur->dest_id, cur->base_rate); switch (cur->type) { case START_SEND: enforce_start_send (cur); break; case STOP_SEND: enforce_stop_send (cur); break; case START_PREFERENCE: enforce_start_preference (cur); break; case STOP_PREFERENCE: enforce_stop_preference (cur); break; default: break; } } } static void timeout_episode (void *cls, const struct GNUNET_SCHEDULER_TaskContext* tc) { struct Experiment *e = cls; e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; if (NULL != e->ep_done_cb) e->ep_done_cb (e->cur); /* Scheduling next */ e->cur = e->cur->next; if (NULL == e->cur) { /* done */ fprintf (stderr, "Last episode done!\n"); if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task) { GNUNET_SCHEDULER_cancel (e->experiment_timeout_task); e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; } e->e_done_cb (e, GNUNET_TIME_absolute_get_duration(e->start_time), GNUNET_OK); return; } fprintf (stderr, "Running episode %u with timeout %s\n", e->cur->id, GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES)); enforce_episode(e->cur); e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration, &timeout_episode, e); } void GNUNET_ATS_solvers_experimentation_run (struct Experiment *e, GNUNET_ATS_TESTING_EpisodeDoneCallback ep_done_cb, GNUNET_ATS_TESTING_ExperimentDoneCallback e_done_cb) { fprintf (stderr, "Running experiment `%s' with timeout %s\n", e->name, GNUNET_STRINGS_relative_time_to_string(e->max_duration, GNUNET_YES)); e->e_done_cb = e_done_cb; e->ep_done_cb = ep_done_cb; e->start_time = GNUNET_TIME_absolute_get(); /* Start total time out */ e->experiment_timeout_task = GNUNET_SCHEDULER_add_delayed (e->max_duration, &timeout_experiment, e); /* Start */ e->cur = e->start; fprintf (stderr, "Running episode %u with timeout %s\n", e->cur->id, GNUNET_STRINGS_relative_time_to_string(e->cur->duration, GNUNET_YES)); enforce_episode(e->cur); e->episode_timeout_task = GNUNET_SCHEDULER_add_delayed (e->cur->duration, &timeout_episode, e); } struct Experiment * GNUNET_ATS_solvers_experimentation_load (char *filename) { struct Experiment *e; struct GNUNET_CONFIGURATION_Handle *cfg; e = NULL; cfg = GNUNET_CONFIGURATION_create(); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_load (cfg, filename)) { fprintf (stderr, "Failed to load `%s'\n", filename); GNUNET_CONFIGURATION_destroy (cfg); return NULL; } e = create_experiment (); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg, "experiment", "name", &e->name)) { fprintf (stderr, "Invalid %s", "name"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment name: `%s'\n", e->name); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_filename (cfg, "experiment", "cfg_file", &e->cfg_file)) { fprintf (stderr, "Invalid %s", "cfg_file"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment name: `%s'\n", e->cfg_file); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment", "masters", &e->num_masters)) { fprintf (stderr, "Invalid %s", "masters"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment masters: `%llu'\n", e->num_masters); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number(cfg, "experiment", "slaves", &e->num_slaves)) { fprintf (stderr, "Invalid %s", "slaves"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment slaves: `%llu'\n", e->num_slaves); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment", "log_freq", &e->log_freq)) { fprintf (stderr, "Invalid %s", "log_freq"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment logging frequency: `%s'\n", GNUNET_STRINGS_relative_time_to_string (e->log_freq, GNUNET_YES)); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time(cfg, "experiment", "max_duration", &e->max_duration)) { fprintf (stderr, "Invalid %s", "max_duration"); free_experiment (e); return NULL; } else fprintf (stderr, "Experiment duration: `%s'\n", GNUNET_STRINGS_relative_time_to_string (e->max_duration, GNUNET_YES)); load_episodes (e, cfg); fprintf (stderr, "Loaded %u episodes with total duration %s\n", e->num_episodes, GNUNET_STRINGS_relative_time_to_string (e->total_duration, GNUNET_YES)); GNUNET_CONFIGURATION_destroy (cfg); return e; } void GNUNET_ATS_solvers_experimentation_stop (struct Experiment *e) { if (GNUNET_SCHEDULER_NO_TASK != e->experiment_timeout_task) { GNUNET_SCHEDULER_cancel (e->experiment_timeout_task); e->experiment_timeout_task = GNUNET_SCHEDULER_NO_TASK; } if (GNUNET_SCHEDULER_NO_TASK != e->episode_timeout_task) { GNUNET_SCHEDULER_cancel (e->episode_timeout_task); e->episode_timeout_task = GNUNET_SCHEDULER_NO_TASK; } free_experiment (e); } /** * Solver */ struct GNUNET_ATS_TESTING_SolverHandle { char * plugin; struct GNUNET_ATS_PluginEnvironment env; void *solver; }; enum GNUNET_ATS_Solvers { GNUNET_ATS_SOLVER_PROPORTIONAL, GNUNET_ATS_SOLVER_MLP, GNUNET_ATS_SOLVER_RIL, }; void GNUNET_ATS_solvers_solver_stop (struct GNUNET_ATS_TESTING_SolverHandle *sh) { GNUNET_PLUGIN_unload (sh->plugin, sh->solver); GNUNET_free (sh->plugin); GNUNET_free (sh); } struct GNUNET_ATS_TESTING_SolverHandle * GNUNET_ATS_solvers_solver_start (enum GNUNET_ATS_Solvers type) { struct GNUNET_ATS_TESTING_SolverHandle *sh; char * solver_str; switch (type) { case GNUNET_ATS_SOLVER_PROPORTIONAL: solver_str = "proportional"; break; case GNUNET_ATS_SOLVER_MLP: solver_str = "mlp"; break; case GNUNET_ATS_SOLVER_RIL: solver_str = "ril"; break; default: GNUNET_break (0); return NULL; break; } sh = GNUNET_new (struct GNUNET_ATS_TESTING_SolverHandle); GNUNET_asprintf (&sh->plugin, "libgnunet_plugin_ats_%s", solver_str); //sh->solver = GNUNET_PLUGIN_load (sh->plugin, &sh->env); if (NULL == sh->solver) { fprintf (stderr, "Failed to load solver `%s'\n", sh->plugin); exit (1); } return sh; } static struct Experiment *e; static struct GNUNET_ATS_TESTING_SolverHandle *sh; /** * cmd option -e: experiment file */ static char *opt_exp_file; static char *opt_solver; /** * cmd option -l: enable logging */ static int opt_log; /** * cmd option -p: enable plots */ static int opt_plot; /** * cmd option -v: verbose logs */ static int opt_verbose; static void run (void *cls, char * const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { enum GNUNET_ATS_Solvers solver; if (NULL == opt_exp_file) { fprintf (stderr, "No experiment given ...\n"); exit (1); } if (NULL == opt_solver) { fprintf (stderr, "No solver given ...\n"); exit (1); } if (0 == strcmp(opt_solver, "mlp")) { solver = GNUNET_ATS_SOLVER_MLP; } else if (0 == strcmp(opt_solver, "proportional")) { solver = GNUNET_ATS_SOLVER_PROPORTIONAL; } else if (0 == strcmp(opt_solver, "ril")) { solver = GNUNET_ATS_SOLVER_RIL; } else { fprintf (stderr, "No solver given ..."); return; } /* load experiment */ e = GNUNET_ATS_solvers_experimentation_load (opt_exp_file); if (NULL == e) { fprintf (stderr, "Failed to load experiment ...\n"); return; } /* load solver */ sh = GNUNET_ATS_solvers_solver_start (solver); if (NULL == sh) { fprintf (stderr, "Failed to start solver ...\n"); return; } /* start logging */ /* run experiment */ /* WAIT */ } /** * Main function of the benchmark * * @param argc argument count * @param argv argument values */ int main (int argc, char *argv[]) { opt_exp_file = NULL; opt_solver = NULL; opt_log = GNUNET_NO; opt_plot = GNUNET_NO; static struct GNUNET_GETOPT_CommandLineOption options[] = { { 's', "solver", NULL, gettext_noop ("solver to use"), 1, &GNUNET_GETOPT_set_string, &opt_solver}, { 'e', "experiment", NULL, gettext_noop ("experiment to use"), 1, &GNUNET_GETOPT_set_string, &opt_exp_file}, { 'e', "experiment", NULL, gettext_noop ("experiment to use"), 1, &GNUNET_GETOPT_set_one, &opt_verbose}, GNUNET_GETOPT_OPTION_END }; GNUNET_PROGRAM_run (argc, argv, argv[0], NULL, options, &run, argv[0]); return 0; } /* end of file ats-testing-experiment.c*/ gnunet-0.10.1/src/ats-tests/ats-testing-log.c0000644000175000017500000006564412320724370015734 00000000000000/* This file is part of GNUnet. (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file ats-tests/ats-testing-log.c * @brief ats benchmark: logging for performance tests * @author Christian Grothoff * @author Matthias Wachs */ #include "platform.h" #include "gnunet_util_lib.h" #include "ats-testing.h" #define THROUGHPUT_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Throughput between Master and Slaves\" \n" \ "set xlabel \"Time in ms\" \n" \ "set ylabel \"Bytes/s\" \n" \ "set grid \n" #define RTT_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Application level roundtrip time between Master and Slaves\" \n" \ "set xlabel \"Time in ms\" \n" \ "set ylabel \"ms\" \n" \ "set grid \n" #define BW_TEMPLATE "#!/usr/bin/gnuplot \n" \ "set datafile separator ';' \n" \ "set title \"Bandwidth inbound and outbound between Master and Slaves\" \n" \ "set xlabel \"Time in ms\" \n" \ "set ylabel \"Bytes / s \" \n" \ "set grid \n" #define LOG_ITEMS_TIME 2 #define LOG_ITEMS_PER_PEER 17 #define LOG_ITEM_BYTES_SENT 1 #define LOG_ITEM_MSGS_SENT 2 #define LOG_ITEM_THROUGHPUT_SENT 3 #define LOG_ITEM_BYTES_RECV 4 #define LOG_ITEM_MSGS_RECV 5 #define LOG_ITEM_THROUGHPUT_RECV 6 #define LOG_ITEM_APP_RTT 7 #define LOG_ITEM_ATS_BW_IN 8 #define LOG_ITEM_ATS_BW_OUT 9 #define LOG_ITEM_ATS_COSTS_LAN 10 #define LOG_ITEM_ATS_WAN 11 #define LOG_ITEM_ATS_WLAN 12 #define LOG_ITEM_ATS_DELAY 13 #define LOG_ITEM_ATS_DISTANCE 14 #define LOG_ITEM_ATS_NETWORKTYPE 15 #define LOG_ITEM_ATS_UTIL_UP 16 #define LOG_ITEM_ATS_UTIL_DOWN 17 /** * A single logging time step for a partner */ struct PartnerLoggingTimestep { /** * Peer */ struct BenchmarkPeer *slave; /** * Total number of messages this peer has sent */ unsigned int total_messages_sent; /** * Total number of bytes this peer has sent */ unsigned int total_bytes_sent; /** * Total number of messages this peer has received */ unsigned int total_messages_received; /** * Total number of bytes this peer has received */ unsigned int total_bytes_received; /** * Total outbound throughput for master in Bytes / s */ unsigned int throughput_sent; /** * Total inbound throughput for master in Bytes / s */ unsigned int throughput_recv; /** * Accumulated RTT for all messages */ unsigned int total_app_rtt; /** * Current application level delay */ unsigned int app_rtt; /* Current ATS properties */ uint32_t ats_distance; uint32_t ats_delay; uint32_t bandwidth_in; uint32_t bandwidth_out; uint32_t ats_utilization_up; uint32_t ats_utilization_down; uint32_t ats_network_type; uint32_t ats_cost_wan; uint32_t ats_cost_lan; uint32_t ats_cost_wlan; double pref_bandwidth; double pref_delay; }; /** * A single logging time step for a peer */ struct PeerLoggingTimestep { /** * Next in DLL */ struct PeerLoggingTimestep *next; /** * Prev in DLL */ struct PeerLoggingTimestep *prev; /** * Logging timestamp */ struct GNUNET_TIME_Absolute timestamp; /** * Total number of messages this peer has sent */ unsigned int total_messages_sent; /** * Total number of bytes this peer has sent */ unsigned int total_bytes_sent; /** * Total number of messages this peer has received */ unsigned int total_messages_received; /** * Total number of bytes this peer has received */ unsigned int total_bytes_received; /** * Total outbound throughput for master in Bytes / s */ unsigned int total_throughput_send; /** * Total inbound throughput for master in Bytes / s */ unsigned int total_throughput_recv; /** * Logs for slaves */ struct PartnerLoggingTimestep *slaves_log; }; /** * Entry for a benchmark peer */ struct LoggingPeer { /** * Peer */ struct BenchmarkPeer *peer; /** * Start time */ struct GNUNET_TIME_Absolute start; /** * DLL for logging entries: head */ struct PeerLoggingTimestep *head; /** * DLL for logging entries: tail */ struct PeerLoggingTimestep *tail; }; struct LoggingHandle { /** * Logging task */ GNUNET_SCHEDULER_TaskIdentifier log_task; /** * Reference to perf_ats' masters */ int num_masters; int num_slaves; int running; int verbose; char *name; struct GNUNET_TIME_Relative frequency; /** * Log structure of length num_peers */ struct LoggingPeer *lp; }; static void write_throughput_gnuplot_script (char * fn, struct LoggingPeer *lp, char **fs, int slaves) { struct GNUNET_DISK_FileHandle *f; char * gfn; char *data; int c_s; GNUNET_asprintf (&gfn, "gnuplot_throughput_%s",fn); fprintf (stderr, "Writing throughput plot for master %u and %u slaves to `%s'\n", lp->peer->no, slaves, gfn); f = GNUNET_DISK_file_open (gfn, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn); GNUNET_free (gfn); return; } /* Write header */ if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, THROUGHPUT_TEMPLATE, strlen(THROUGHPUT_TEMPLATE))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); /* Write master data */ GNUNET_asprintf (&data, "plot '%s' using 2:%u with lines title 'Master %u send total', \\\n" \ "'%s' using 2:%u with lines title 'Master %u receive total', \\\n", fn, LOG_ITEMS_TIME + LOG_ITEM_THROUGHPUT_SENT, lp->peer->no, fn, LOG_ITEMS_TIME + LOG_ITEM_THROUGHPUT_RECV, lp->peer->no); if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); GNUNET_free (data); for (c_s = 0; c_s < slaves; c_s++) { GNUNET_asprintf (&data, "'%s' using 2:%u with lines title 'Master %u - Slave %u send', \\\n" \ "'%s' using 2:%u with lines title 'Master %u - Slave %u receive'%s\n", fs[c_s], LOG_ITEMS_TIME + LOG_ITEM_THROUGHPUT_SENT, lp->peer->no, lp->peer->partners[c_s].dest->no, fs[c_s], LOG_ITEMS_TIME + LOG_ITEM_THROUGHPUT_RECV, lp->peer->no, lp->peer->partners[c_s].dest->no, (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1"); if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); GNUNET_free (data); } if (GNUNET_SYSERR == GNUNET_DISK_file_close(f)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn); GNUNET_free (gfn); } static void write_rtt_gnuplot_script (char * fn, struct LoggingPeer *lp, char **fs, int slaves) { struct GNUNET_DISK_FileHandle *f; char * gfn; char *data; int c_s; GNUNET_asprintf (&gfn, "gnuplot_rtt_%s",fn); fprintf (stderr, "Writing rtt plot for master %u to `%s'\n", lp->peer->no, gfn); f = GNUNET_DISK_file_open (gfn, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn); GNUNET_free (gfn); return; } /* Write header */ if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, RTT_TEMPLATE, strlen(RTT_TEMPLATE))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); for (c_s = 0; c_s < slaves; c_s++) { GNUNET_asprintf (&data, "%s'%s' using 2:%u with lines title 'Master %u - Slave %u '%s\n", (0 == c_s) ? "plot " :"", fs[c_s], LOG_ITEMS_TIME + LOG_ITEM_APP_RTT, lp->peer->no, lp->peer->partners[c_s].dest->no, (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1"); if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); GNUNET_free (data); } if (GNUNET_SYSERR == GNUNET_DISK_file_close(f)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn); GNUNET_free (gfn); } static void write_bw_gnuplot_script (char * fn, struct LoggingPeer *lp, char **fs, int slaves) { struct GNUNET_DISK_FileHandle *f; char * gfn; char *data; int c_s; GNUNET_asprintf (&gfn, "gnuplot_bw_%s",fn); fprintf (stderr, "Writing bandwidth plot for master %u to `%s'\n", lp->peer->no, gfn); f = GNUNET_DISK_file_open (gfn, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_EXEC | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open gnuplot file `%s'\n", gfn); GNUNET_free (gfn); return; } /* Write header */ if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, BW_TEMPLATE, strlen(BW_TEMPLATE))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); for (c_s = 0; c_s < slaves; c_s++) { GNUNET_asprintf (&data, "%s"\ "'%s' using 2:%u with lines title 'BW out master %u - Slave %u ', \\\n" \ "'%s' using 2:%u with lines title 'BW in master %u - Slave %u '"\ "%s\n", (0 == c_s) ? "plot " :"", fs[c_s], LOG_ITEMS_TIME + LOG_ITEM_ATS_BW_OUT, lp->peer->no, c_s, fs[c_s], LOG_ITEMS_TIME + LOG_ITEM_ATS_BW_IN, lp->peer->no, c_s, (c_s < lp->peer->num_partners -1) ? ", \\" : "\n pause -1"); if (GNUNET_SYSERR == GNUNET_DISK_file_write(f, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to plot file `%s'\n", gfn); GNUNET_free (data); } if (GNUNET_SYSERR == GNUNET_DISK_file_close(f)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close gnuplot file `%s'\n", gfn); else GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data successfully written to plot file `%s'\n", gfn); GNUNET_free (gfn); } void GNUNET_ATS_TEST_logging_write_to_file (struct LoggingHandle *l, char *experiment_name, int plots) { struct GNUNET_DISK_FileHandle *f[l->num_slaves]; struct GNUNET_DISK_FileHandle *f_m; char *tmp_exp_name; char *filename_master; char *filename_slaves[l->num_slaves]; char *data; struct PeerLoggingTimestep *cur_lt; struct PartnerLoggingTimestep *plt; struct GNUNET_TIME_Absolute timestamp; int c_m; int c_s; timestamp = GNUNET_TIME_absolute_get(); tmp_exp_name = experiment_name; for (c_m = 0; c_m < l->num_masters; c_m++) { GNUNET_asprintf (&filename_master, "%s_%llu_master%u_%s", experiment_name, timestamp.abs_value_us, c_m, l->name); fprintf (stderr, "Writing data for master %u to file `%s'\n", c_m,filename_master); f_m = GNUNET_DISK_file_open (filename_master, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f_m) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open log file `%s'\n", filename_master); GNUNET_free (filename_master); return; } GNUNET_asprintf (&data, "# master %u; experiment : %s\n" "timestamp; timestamp delta; #messages sent; #bytes sent; #throughput sent; #messages received; #bytes received; #throughput received; \n" , c_m, experiment_name); if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_m, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n",filename_master); GNUNET_free (data); for (c_s = 0; c_s < l->lp[c_m].peer->num_partners; c_s++) { GNUNET_asprintf (&filename_slaves[c_s], "%s_%llu_master%u_slave_%u_%s", tmp_exp_name, timestamp.abs_value_us, c_m, c_s, l->name); fprintf (stderr, "Writing data for master %u slave %u to file `%s'\n", c_m, c_s, filename_slaves[c_s]); f[c_s] = GNUNET_DISK_file_open (filename_slaves[c_s], GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (NULL == f[c_s]) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot open log file `%s'\n", filename_slaves[c_s]); GNUNET_free (filename_slaves[c_s]); return; } /* Header */ GNUNET_asprintf (&data, "# master %u; slave %u ; experiment : %s\n" "timestamp; timestamp delta; #messages sent; #bytes sent; #throughput sent; #messages received; #bytes received; #throughput received; " \ "rtt; bw in; bw out; ats_cost_lan; ats_cost_wlan; ats_delay; ats_distance; ats_network_type; ats_utilization_up ;ats_utilization_down;" \ "pref bandwidth; pref delay\n", c_m, c_s, experiment_name); if (GNUNET_SYSERR == GNUNET_DISK_file_write(f[c_s], data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n",filename_slaves[c_s]); GNUNET_free (data); } for (cur_lt = l->lp[c_m].head; NULL != cur_lt; cur_lt = cur_lt->next) { if (l->verbose) fprintf (stderr, "Master [%u]: timestamp %llu %llu ; %u %u %u ; %u %u %u\n", l->lp[c_m].peer->no, (long long unsigned int) cur_lt->timestamp.abs_value_us, (long long unsigned int) GNUNET_TIME_absolute_get_difference(l->lp[c_m].start, cur_lt->timestamp).rel_value_us / 1000, cur_lt->total_messages_sent, cur_lt->total_bytes_sent, cur_lt->total_throughput_send, cur_lt->total_messages_received, cur_lt->total_bytes_received, cur_lt->total_throughput_recv); /* Assembling master string */ GNUNET_asprintf (&data, "%llu;%llu;%u;%u;%u;%u;%u;%u;\n", (long long unsigned int) cur_lt->timestamp.abs_value_us, (long long unsigned int) GNUNET_TIME_absolute_get_difference(l->lp[c_m].start, cur_lt->timestamp).rel_value_us / 1000, cur_lt->total_messages_sent, cur_lt->total_bytes_sent, cur_lt->total_throughput_send, cur_lt->total_messages_received, cur_lt->total_bytes_received, cur_lt->total_throughput_recv); if (GNUNET_SYSERR == GNUNET_DISK_file_write(f_m, data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to master file %u\n", c_m); GNUNET_free (data); for (c_s = 0; c_s < l->lp[c_m].peer->num_partners; c_s++) { plt = &cur_lt->slaves_log[c_s]; /* Log partners */ /* Assembling slave string */ GNUNET_asprintf(&data, "%llu;%llu;%u;%u;%u;%u;%u;%u;%.3f;%u;%u;%u;%u;%u;%u;%u;%u;%u;%u;%.3f;%.3f\n", (long long unsigned int) cur_lt->timestamp.abs_value_us, (long long unsigned int) GNUNET_TIME_absolute_get_difference(l->lp[c_m].start, cur_lt->timestamp).rel_value_us / 1000, plt->total_messages_sent, plt->total_bytes_sent, plt->throughput_sent, plt->total_messages_received, plt->total_bytes_received, plt->throughput_recv, (double) plt->app_rtt / 1000, plt->bandwidth_in, plt->bandwidth_out, plt->ats_cost_lan, plt->ats_cost_wan, plt->ats_cost_wlan, plt->ats_delay, plt->ats_distance, plt->ats_network_type, plt->ats_utilization_up, plt->ats_utilization_down, plt->pref_bandwidth, plt->pref_delay); if (l->verbose) fprintf (stderr, "\t Slave [%u]: %u %u %u ; %u %u %u rtt %u delay %u bw_in %u bw_out %u \n", plt->slave->no, plt->total_messages_sent, plt->total_bytes_sent, plt->throughput_sent, plt->total_messages_received, plt->total_bytes_received, plt->throughput_recv, plt->app_rtt, plt->ats_delay, plt->bandwidth_in, plt->bandwidth_out); if (GNUNET_SYSERR == GNUNET_DISK_file_write(f[c_s], data, strlen(data))) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot write data to log file `%s'\n", filename_slaves[c_s]); GNUNET_free (data); } } for (c_s = 0; c_s < l->lp[c_m].peer->num_partners; c_s++) { if (GNUNET_SYSERR == GNUNET_DISK_file_close(f[c_s])) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file for master[%u] slave[%u]\n", c_m, c_s); continue; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data file successfully written to log file for `%s'\n", filename_slaves[c_s]); } if (GNUNET_SYSERR == GNUNET_DISK_file_close(f_m)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Cannot close log file `%s'\n", filename_master); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Data file successfully written to log file for master `%s'\n", filename_master); if (GNUNET_YES == plots) { write_throughput_gnuplot_script (filename_master, &l->lp[c_m], filename_slaves, l->num_slaves); write_rtt_gnuplot_script (filename_master, &l->lp[c_m], filename_slaves, l->num_slaves); write_bw_gnuplot_script (filename_master, &l->lp[c_m], filename_slaves, l->num_slaves); } } GNUNET_free (filename_master); } /** * Log all data now * * @param l logging handle to use */ void GNUNET_ATS_TEST_logging_now (struct LoggingHandle *l) { struct LoggingPeer *bp; struct PeerLoggingTimestep *mlt; struct PeerLoggingTimestep *prev_log_mlt; struct PartnerLoggingTimestep *slt; struct PartnerLoggingTimestep *prev_log_slt; struct BenchmarkPartner *p; struct GNUNET_TIME_Relative delta; int c_s; int c_m; unsigned int app_rtt; double mult; if (GNUNET_YES != l->running) return; for (c_m = 0; c_m < l->num_masters; c_m++) { bp = &l->lp[c_m]; mlt = GNUNET_new (struct PeerLoggingTimestep); GNUNET_CONTAINER_DLL_insert_tail(l->lp[c_m].head, l->lp[c_m].tail, mlt); prev_log_mlt = mlt->prev; /* Collect data */ /* Current master state */ mlt->timestamp = GNUNET_TIME_absolute_get(); mlt->total_bytes_sent = bp->peer->total_bytes_sent; mlt->total_messages_sent = bp->peer->total_messages_sent; mlt->total_bytes_received = bp->peer->total_bytes_received; mlt->total_messages_received = bp->peer->total_messages_received; /* Throughput */ if (NULL == prev_log_mlt) { /* Get difference to start */ delta = GNUNET_TIME_absolute_get_difference (l->lp[c_m].start, mlt->timestamp); } else { /* Get difference to last timestep */ delta = GNUNET_TIME_absolute_get_difference (mlt->prev->timestamp, mlt->timestamp); } /* Multiplication factor for throughput calculation */ mult = (double) GNUNET_TIME_UNIT_SECONDS.rel_value_us / (delta.rel_value_us); /* Total throughput */ if (NULL != prev_log_mlt) { if (mlt->total_bytes_sent - mlt->prev->total_bytes_sent > 0) { mlt->total_throughput_send = mult * (mlt->total_bytes_sent - mlt->prev->total_bytes_sent); } else { mlt->total_throughput_send = 0; // mlt->total_throughput_send = prev_log_mlt->total_throughput_send; /* no msgs send */ } if (mlt->total_bytes_received - mlt->prev->total_bytes_received > 0) { mlt->total_throughput_recv = mult * (mlt->total_bytes_received - mlt->prev->total_bytes_received); } else { mlt->total_throughput_send = 0; //mlt->total_throughput_recv = prev_log_mlt->total_throughput_recv; /* no msgs received */ } } else { mlt->total_throughput_send = mult * mlt->total_bytes_sent; mlt->total_throughput_send = mult * mlt->total_bytes_received; } if (GNUNET_YES == l->verbose) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Master[%u] delta: %llu us, bytes (sent/received): %u / %u; throughput send/recv: %u / %u\n", c_m, delta.rel_value_us, mlt->total_bytes_sent, mlt->total_bytes_received, mlt->total_throughput_send, mlt->total_throughput_recv); } mlt->slaves_log = GNUNET_malloc (bp->peer->num_partners * sizeof (struct PartnerLoggingTimestep)); for (c_s = 0; c_s < bp->peer->num_partners; c_s++) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Collect logging data master[%u] slave [%u]\n", c_m, c_s); p = &bp->peer->partners[c_s]; slt = &mlt->slaves_log[c_s]; slt->slave = p->dest; /* Bytes sent from master to this slave */ slt->total_bytes_sent = p->bytes_sent; /* Messages sent from master to this slave */ slt->total_messages_sent = p->messages_sent; /* Bytes master received from this slave */ slt->total_bytes_received = p->bytes_received; /* Messages master received from this slave */ slt->total_messages_received = p->messages_received; slt->total_app_rtt = p->total_app_rtt; /* ats performance information */ slt->ats_cost_lan = p->ats_cost_lan; slt->ats_cost_wan = p->ats_cost_wan; slt->ats_cost_wlan = p->ats_cost_wlan; slt->ats_delay = p->ats_delay; slt->ats_distance = p->ats_distance; slt->ats_network_type = p->ats_network_type; slt->ats_utilization_down = p->ats_utilization_down; slt->ats_utilization_up = p->ats_utilization_up; slt->bandwidth_in = p->bandwidth_in; slt->bandwidth_out = p->bandwidth_out; slt->pref_bandwidth = p->pref_bandwidth; slt->pref_delay = p->pref_delay; /* Total application level rtt */ if (NULL == prev_log_mlt) { if (0 != slt->total_messages_sent) app_rtt = slt->total_app_rtt / slt->total_messages_sent; else app_rtt = 0; } else { prev_log_slt = &prev_log_mlt->slaves_log[c_s]; if ((slt->total_messages_sent - prev_log_slt->total_messages_sent) > 0) app_rtt = (slt->total_app_rtt - prev_log_slt->total_app_rtt) / (slt->total_messages_sent - prev_log_slt->total_messages_sent); else { app_rtt = prev_log_slt->app_rtt; /* No messages were */ } } slt->app_rtt = app_rtt; /* Partner throughput */ if (NULL != prev_log_mlt) { prev_log_slt = &prev_log_mlt->slaves_log[c_s]; if (slt->total_bytes_sent > prev_log_slt->total_bytes_sent) slt->throughput_sent = mult * (slt->total_bytes_sent - prev_log_slt->total_bytes_sent); else slt->throughput_sent = 0; if (slt->total_bytes_received > prev_log_slt->total_bytes_received) slt->throughput_recv = mult * (slt->total_bytes_received - prev_log_slt->total_bytes_received); else slt->throughput_recv = 0; } else { slt->throughput_sent = mult * slt->total_bytes_sent; slt->throughput_recv = mult * slt->total_bytes_received; } if (GNUNET_YES == l->verbose) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Master [%u] -> Slave [%u]: delta: %llu us, bytes (sent/received): %u / %u; throughput send/recv: %u / %u\n", c_m, c_s, delta.rel_value_us, mlt->total_bytes_sent, mlt->total_bytes_received, slt->throughput_sent, slt->throughput_recv); } else GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Master [%u]: slave [%u]\n", bp->peer->no, p->dest->no); } } } static void collect_log_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct LoggingHandle *l = cls; l->log_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_ATS_TEST_logging_now (l); if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return; l->log_task = GNUNET_SCHEDULER_add_delayed (l->frequency, &collect_log_task, l); } /** * Stop logging * * @param l the logging handle */ void GNUNET_ATS_TEST_logging_stop (struct LoggingHandle *l) { if (GNUNET_YES!= l->running) return; if (GNUNET_SCHEDULER_NO_TASK != l->log_task) GNUNET_SCHEDULER_cancel (l->log_task); l->log_task = GNUNET_SCHEDULER_NO_TASK; l->running = GNUNET_NO; GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Stop logging\n")); } /** * Clean up logging data * * @param l the logging handle */ void GNUNET_ATS_TEST_logging_clean_up (struct LoggingHandle *l) { int c_m; struct PeerLoggingTimestep *cur; if (GNUNET_YES == l->running) GNUNET_ATS_TEST_logging_stop (l); for (c_m = 0; c_m < l->num_masters; c_m++) { while (NULL != (cur = l->lp[c_m].head)) { GNUNET_CONTAINER_DLL_remove (l->lp[c_m].head, l->lp[c_m].tail, cur); GNUNET_free (cur->slaves_log); GNUNET_free (cur); } } GNUNET_free (l->lp); GNUNET_free (l); } /** * Start logging * * @param log_frequency the logging frequency * @param testname the testname * @param masters the master peers used for benchmarking * @param num_masters the number of master peers * @param num_slaves the number of slave peers * @param verbose verbose logging * @return the logging handle or NULL on error */ struct LoggingHandle * GNUNET_ATS_TEST_logging_start(struct GNUNET_TIME_Relative log_frequency, char *testname, struct BenchmarkPeer *masters, int num_masters, int num_slaves, int verbose) { struct LoggingHandle *l; int c_m; GNUNET_log(GNUNET_ERROR_TYPE_INFO, _("Start logging `%s'\n"), testname); l = GNUNET_new (struct LoggingHandle); l->num_masters = num_masters; l->num_slaves = num_slaves; l->name = testname; l->frequency = log_frequency; l->verbose = verbose; l->lp = GNUNET_malloc (num_masters * sizeof (struct LoggingPeer)); for (c_m = 0; c_m < num_masters; c_m ++) { l->lp[c_m].peer = &masters[c_m]; l->lp[c_m].start = GNUNET_TIME_absolute_get(); } /* Schedule logging task */ l->log_task = GNUNET_SCHEDULER_add_now (&collect_log_task, l); l->running = GNUNET_YES; return l; } /* end of file ats-testing-log.c */ gnunet-0.10.1/src/ats-tests/perf_ats_ril_latency.conf0000644000175000017500000000006212225230043017556 00000000000000@INLINE@ template_perf_ats.conf [ats] MODE = RIL gnunet-0.10.1/src/psyc/0000755000175000017500000000000012320755627011650 500000000000000gnunet-0.10.1/src/psyc/psyc_api.c0000644000175000017500000014114712310570720013537 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psyc/psyc_api.c * @brief PSYC service; high-level access to the PSYC protocol * note that clients of this API are NOT expected to * understand the PSYC message format, only the semantics! * Parsing (and serializing) the PSYC stream format is done * within the implementation of the libgnunetpsyc library, * and this API deliberately exposes as little as possible * of the actual data stream format to the application! * @author Gabor X Toth */ #include #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_env_lib.h" #include "gnunet_multicast_service.h" #include "gnunet_psyc_service.h" #include "psyc.h" #define LOG(kind,...) GNUNET_log_from (kind, "psyc-api",__VA_ARGS__) struct OperationHandle { struct OperationHandle *prev; struct OperationHandle *next; struct GNUNET_MessageHeader *msg; }; /** * Handle for a pending PSYC transmission operation. */ struct GNUNET_PSYC_ChannelTransmitHandle { struct GNUNET_PSYC_Channel *ch; GNUNET_PSYC_TransmitNotifyModifier notify_mod; GNUNET_PSYC_TransmitNotifyData notify_data; void *notify_cls; enum MessageState state; }; /** * Handle to access PSYC channel operations for both the master and slaves. */ struct GNUNET_PSYC_Channel { /** * Transmission handle; */ struct GNUNET_PSYC_ChannelTransmitHandle tmit; /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Socket (if available). */ struct GNUNET_CLIENT_Connection *client; /** * Currently pending transmission request, or NULL for none. */ struct GNUNET_CLIENT_TransmitHandle *th; /** * Head of operations to transmit. */ struct OperationHandle *tmit_head; /** * Tail of operations to transmit. */ struct OperationHandle *tmit_tail; /** * Message being transmitted to the PSYC service. */ struct OperationHandle *tmit_msg; /** * Message to send on reconnect. */ struct GNUNET_MessageHeader *reconnect_msg; /** * Task doing exponential back-off trying to reconnect. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Time for next connect retry. */ struct GNUNET_TIME_Relative reconnect_delay; /** * Message part callback. */ GNUNET_PSYC_MessageCallback message_cb; /** * Message part callback for historic message. */ GNUNET_PSYC_MessageCallback hist_message_cb; /** * Join handler callback. */ GNUNET_PSYC_JoinCallback join_cb; /** * Closure for @a message_cb and @a join_cb. */ void *cb_cls; /** * ID of the message being received from the PSYC service. */ uint64_t recv_message_id; /** * Public key of the slave from which a message is being received. */ struct GNUNET_CRYPTO_EddsaPublicKey recv_slave_key; /** * State of the currently being received message from the PSYC service. */ enum MessageState recv_state; /** * Flags for the currently being received message from the PSYC service. */ enum GNUNET_PSYC_MessageFlags recv_flags; /** * Expected value size for the modifier being received from the PSYC service. */ uint32_t recv_mod_value_size_expected; /** * Actual value size for the modifier being received from the PSYC service. */ uint32_t recv_mod_value_size; /** * Is transmission paused? */ uint8_t tmit_paused; /** * Are we still waiting for a PSYC_TRANSMIT_ACK? */ uint8_t tmit_ack_pending; /** * Are we polling for incoming messages right now? */ uint8_t in_receive; /** * Are we currently transmitting a message? */ uint8_t in_transmit; /** * Is this a master or slave channel? */ uint8_t is_master; }; /** * Handle for the master of a PSYC channel. */ struct GNUNET_PSYC_Master { struct GNUNET_PSYC_Channel ch; GNUNET_PSYC_MasterStartCallback start_cb; uint64_t max_message_id; }; /** * Handle for a PSYC channel slave. */ struct GNUNET_PSYC_Slave { struct GNUNET_PSYC_Channel ch; GNUNET_PSYC_SlaveJoinCallback join_cb; uint64_t max_message_id; }; /** * Handle that identifies a join request. * * Used to match calls to #GNUNET_PSYC_JoinCallback to the * corresponding calls to GNUNET_PSYC_join_decision(). */ struct GNUNET_PSYC_JoinHandle { }; /** * Handle for a pending PSYC transmission operation. */ struct GNUNET_PSYC_SlaveTransmitHandle { }; /** * Handle to a story telling operation. */ struct GNUNET_PSYC_Story { }; /** * Handle for a state query operation. */ struct GNUNET_PSYC_StateQuery { }; static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); static void channel_transmit_data (struct GNUNET_PSYC_Channel *ch); /** * Reschedule a connect attempt to the service. * * @param c channel to reconnect */ static void reschedule_connect (struct GNUNET_PSYC_Channel *c) { GNUNET_assert (c->reconnect_task == GNUNET_SCHEDULER_NO_TASK); if (NULL != c->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (c->th); c->th = NULL; } if (NULL != c->client) { GNUNET_CLIENT_disconnect (c->client); c->client = NULL; } c->in_receive = GNUNET_NO; LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling task to reconnect to PSYC service in %s.\n", GNUNET_STRINGS_relative_time_to_string (c->reconnect_delay, GNUNET_YES)); c->reconnect_task = GNUNET_SCHEDULER_add_delayed (c->reconnect_delay, &reconnect, c); c->reconnect_delay = GNUNET_TIME_STD_BACKOFF (c->reconnect_delay); } /** * Schedule transmission of the next message from our queue. * * @param ch PSYC channel handle */ static void transmit_next (struct GNUNET_PSYC_Channel *ch); /** * Reset data stored related to the last received message. */ static void recv_reset (struct GNUNET_PSYC_Channel *ch) { ch->recv_state = MSG_STATE_START; ch->recv_flags = 0; ch->recv_message_id = 0; //FIXME: ch->recv_slave_key = { 0 }; ch->recv_mod_value_size = 0; ch->recv_mod_value_size_expected = 0; } static void recv_error (struct GNUNET_PSYC_Channel *ch) { GNUNET_PSYC_MessageCallback message_cb = ch->recv_flags & GNUNET_PSYC_MESSAGE_HISTORIC ? ch->hist_message_cb : ch->message_cb; if (NULL != message_cb) message_cb (ch->cb_cls, ch->recv_message_id, ch->recv_flags, NULL); recv_reset (ch); } /** * Queue a message part for transmission to the PSYC service. * * The message part is added to the current message buffer. * When this buffer is full, it is added to the transmission queue. * * @param ch Channel struct for the client. * @param msg Modifier message part, or NULL when there's no more modifiers. * @param end End of message. */ static void queue_message (struct GNUNET_PSYC_Channel *ch, const struct GNUNET_MessageHeader *msg, uint8_t end) { uint16_t size = msg ? ntohs (msg->size) : 0; LOG (GNUNET_ERROR_TYPE_DEBUG, "Queueing message of type %u and size %u (end: %u)).\n", ntohs (msg->type), size, end); struct OperationHandle *op = ch->tmit_msg; if (NULL != op) { if (NULL == msg || GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < op->msg->size + size) { /* End of message or buffer is full, add it to transmission queue * and start with empty buffer */ op->msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); op->msg->size = htons (op->msg->size); GNUNET_CONTAINER_DLL_insert_tail (ch->tmit_head, ch->tmit_tail, op); ch->tmit_msg = op = NULL; ch->tmit_ack_pending++; } else { /* Message fits in current buffer, append */ ch->tmit_msg = op = GNUNET_realloc (op, sizeof (*op) + op->msg->size + size); op->msg = (struct GNUNET_MessageHeader *) &op[1]; memcpy ((char *) op->msg + op->msg->size, msg, size); op->msg->size += size; } } if (NULL == op && NULL != msg) { /* Empty buffer, copy over message. */ ch->tmit_msg = op = GNUNET_malloc (sizeof (*op) + sizeof (*op->msg) + size); op->msg = (struct GNUNET_MessageHeader *) &op[1]; op->msg->size = sizeof (*op->msg) + size; memcpy (&op->msg[1], msg, size); } if (NULL != op && (GNUNET_YES == end || (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < op->msg->size + sizeof (struct GNUNET_MessageHeader)))) { /* End of message or buffer is full, add it to transmission queue. */ op->msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); op->msg->size = htons (op->msg->size); GNUNET_CONTAINER_DLL_insert_tail (ch->tmit_head, ch->tmit_tail, op); ch->tmit_msg = op = NULL; ch->tmit_ack_pending++; } if (GNUNET_YES == end) ch->in_transmit = GNUNET_NO; transmit_next (ch); } /** * Request a modifier from a client to transmit. * * @param mst Master handle. */ static void channel_transmit_mod (struct GNUNET_PSYC_Channel *ch) { uint16_t max_data_size, data_size; char data[GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD] = ""; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) data; int notify_ret; switch (ch->tmit.state) { case MSG_STATE_MODIFIER: { struct GNUNET_PSYC_MessageModifier *mod = (struct GNUNET_PSYC_MessageModifier *) msg; max_data_size = data_size = GNUNET_PSYC_MODIFIER_MAX_PAYLOAD; msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER); msg->size = sizeof (struct GNUNET_PSYC_MessageModifier); notify_ret = ch->tmit.notify_mod (ch->tmit.notify_cls, &data_size, &mod[1], &mod->oper, &mod->value_size); mod->name_size = strnlen ((char *) &mod[1], data_size); if (mod->name_size < data_size) { mod->value_size = htonl (mod->value_size); mod->name_size = htons (mod->name_size); } else if (0 < data_size) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got invalid modifier name.\n"); notify_ret = GNUNET_SYSERR; } break; } case MSG_STATE_MOD_CONT: { max_data_size = data_size = GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD; msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT); msg->size = sizeof (struct GNUNET_MessageHeader); notify_ret = ch->tmit.notify_mod (ch->tmit.notify_cls, &data_size, &msg[1], NULL, NULL); break; } default: GNUNET_assert (0); } switch (notify_ret) { case GNUNET_NO: if (0 == data_size) { /* Transmission paused, nothing to send. */ ch->tmit_paused = GNUNET_YES; return; } ch->tmit.state = MSG_STATE_MOD_CONT; break; case GNUNET_YES: if (0 == data_size) { /* End of modifiers. */ ch->tmit.state = MSG_STATE_DATA; if (0 == ch->tmit_ack_pending) channel_transmit_data (ch); return; } ch->tmit.state = MSG_STATE_MODIFIER; break; default: LOG (GNUNET_ERROR_TYPE_ERROR, "MasterTransmitNotifyModifier returned error " "when requesting a modifier.\n"); ch->tmit.state = MSG_STATE_CANCEL; msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); msg->size = htons (sizeof (*msg)); queue_message (ch, msg, GNUNET_YES); return; } if (0 < data_size) { GNUNET_assert (data_size <= max_data_size); msg->size = htons (msg->size + data_size); queue_message (ch, msg, GNUNET_NO); } channel_transmit_mod (ch); } /** * Request data from a client to transmit. * * @param mst Master handle. */ static void channel_transmit_data (struct GNUNET_PSYC_Channel *ch) { uint16_t data_size = GNUNET_PSYC_DATA_MAX_PAYLOAD; char data[GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD] = ""; struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) data; msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA); int notify_ret = ch->tmit.notify_data (ch->tmit.notify_cls, &data_size, &msg[1]); switch (notify_ret) { case GNUNET_NO: if (0 == data_size) { /* Transmission paused, nothing to send. */ ch->tmit_paused = GNUNET_YES; return; } break; case GNUNET_YES: ch->tmit.state = MSG_STATE_END; break; default: LOG (GNUNET_ERROR_TYPE_ERROR, "MasterTransmitNotify returned error when requesting data.\n"); ch->tmit.state = MSG_STATE_CANCEL; msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); msg->size = htons (sizeof (*msg)); queue_message (ch, msg, GNUNET_YES); return; } if (0 < data_size) { GNUNET_assert (data_size <= GNUNET_PSYC_DATA_MAX_PAYLOAD); msg->size = htons (sizeof (*msg) + data_size); queue_message (ch, msg, !notify_ret); } /* End of message. */ if (GNUNET_YES == notify_ret) { msg->type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END); msg->size = htons (sizeof (*msg)); queue_message (ch, msg, GNUNET_YES); } } /** * Send a message to a channel. * * @param ch Handle to the PSYC channel. * @param method_name Which method should be invoked. * @param notify_mod Function to call to obtain modifiers. * @param notify_data Function to call to obtain fragments of the data. * @param notify_cls Closure for @a notify_mod and @a notify_data. * @param flags Flags for the message being transmitted. * @return Transmission handle, NULL on error (i.e. more than one request queued). */ static struct GNUNET_PSYC_ChannelTransmitHandle * channel_transmit (struct GNUNET_PSYC_Channel *ch, const char *method_name, GNUNET_PSYC_TransmitNotifyModifier notify_mod, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_cls, uint32_t flags) { if (GNUNET_NO != ch->in_transmit) return NULL; ch->in_transmit = GNUNET_YES; size_t size = strlen (method_name) + 1; struct GNUNET_PSYC_MessageMethod *pmeth; struct OperationHandle *op; ch->tmit_msg = op = GNUNET_malloc (sizeof (*op) + sizeof (*op->msg) + sizeof (*pmeth) + size); op->msg = (struct GNUNET_MessageHeader *) &op[1]; op->msg->size = sizeof (*op->msg) + sizeof (*pmeth) + size; pmeth = (struct GNUNET_PSYC_MessageMethod *) &op->msg[1]; pmeth->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD); pmeth->header.size = htons (sizeof (*pmeth) + size); pmeth->flags = htonl (flags); memcpy (&pmeth[1], method_name, size); ch->tmit.ch = ch; ch->tmit.notify_mod = notify_mod; ch->tmit.notify_data = notify_data; ch->tmit.notify_cls = notify_cls; ch->tmit.state = MSG_STATE_MODIFIER; channel_transmit_mod (ch); return &ch->tmit; } /** * Resume transmission to the channel. * * @param th Handle of the request that is being resumed. */ static void channel_transmit_resume (struct GNUNET_PSYC_ChannelTransmitHandle *th) { struct GNUNET_PSYC_Channel *ch = th->ch; if (0 == ch->tmit_ack_pending) { ch->tmit_paused = GNUNET_NO; channel_transmit_data (ch); } } /** * Abort transmission request to channel. * * @param th Handle of the request that is being aborted. */ static void channel_transmit_cancel (struct GNUNET_PSYC_ChannelTransmitHandle *th) { struct GNUNET_PSYC_Channel *ch = th->ch; if (GNUNET_NO == ch->in_transmit) return; } /** * Handle incoming message from the PSYC service. * * @param ch The channel the message is sent to. * @param pmsg The message. */ static void handle_psyc_message (struct GNUNET_PSYC_Channel *ch, const struct GNUNET_PSYC_MessageHeader *msg) { uint16_t size = ntohs (msg->header.size); uint32_t flags = ntohl (msg->flags); GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, (struct GNUNET_MessageHeader *) msg); if (MSG_STATE_START == ch->recv_state) { ch->recv_message_id = GNUNET_ntohll (msg->message_id); ch->recv_flags = flags; ch->recv_slave_key = msg->slave_key; ch->recv_mod_value_size = 0; ch->recv_mod_value_size_expected = 0; } else if (GNUNET_ntohll (msg->message_id) != ch->recv_message_id) { // FIXME LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected message ID. Got: %" PRIu64 ", expected: %" PRIu64 "\n", GNUNET_ntohll (msg->message_id), ch->recv_message_id); GNUNET_break_op (0); recv_error (ch); return; } else if (flags != ch->recv_flags) { LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected message flags. Got: %lu, expected: %lu\n", flags, ch->recv_flags); GNUNET_break_op (0); recv_error (ch); return; } uint16_t pos = 0, psize = 0, ptype, size_eq, size_min; for (pos = 0; sizeof (*msg) + pos < size; pos += psize) { const struct GNUNET_MessageHeader *pmsg = (const struct GNUNET_MessageHeader *) ((char *) &msg[1] + pos); psize = ntohs (pmsg->size); ptype = ntohs (pmsg->type); size_eq = size_min = 0; if (psize < sizeof (*pmsg) || sizeof (*msg) + pos + psize > size) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Dropping message of type %u with invalid size %u.\n", ptype, psize); recv_error (ch); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message part from PSYC.\n"); GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg); switch (ptype) { case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: size_min = sizeof (struct GNUNET_PSYC_MessageMethod); break; case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: size_min = sizeof (struct GNUNET_PSYC_MessageModifier); break; case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: size_min = sizeof (struct GNUNET_MessageHeader); break; case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: size_eq = sizeof (struct GNUNET_MessageHeader); break; default: GNUNET_break_op (0); recv_error (ch); return; } if (! ((0 < size_eq && psize == size_eq) || (0 < size_min && size_min <= psize))) { GNUNET_break_op (0); recv_error (ch); return; } switch (ptype) { case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: { struct GNUNET_PSYC_MessageMethod *meth = (struct GNUNET_PSYC_MessageMethod *) pmsg; if (MSG_STATE_START != ch->recv_state) { LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping out of order message method (%u).\n", ch->recv_state); /* It is normal to receive an incomplete message right after connecting, * but should not happen later. * FIXME: add a check for this condition. */ GNUNET_break_op (0); recv_error (ch); return; } if ('\0' != *((char *) meth + psize - 1)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping message with malformed method. " "Message ID: %" PRIu64 "\n", ch->recv_message_id); GNUNET_break_op (0); recv_error (ch); return; } ch->recv_state = MSG_STATE_METHOD; break; } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: { if (!(MSG_STATE_METHOD == ch->recv_state || MSG_STATE_MODIFIER == ch->recv_state || MSG_STATE_MOD_CONT == ch->recv_state)) { LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping out of order message modifier (%u).\n", ch->recv_state); GNUNET_break_op (0); recv_error (ch); return; } struct GNUNET_PSYC_MessageModifier *mod = (struct GNUNET_PSYC_MessageModifier *) pmsg; uint16_t name_size = ntohs (mod->name_size); ch->recv_mod_value_size_expected = ntohl (mod->value_size); ch->recv_mod_value_size = psize - sizeof (*mod) - name_size - 1; if (psize < sizeof (*mod) + name_size + 1 || '\0' != *((char *) &mod[1] + name_size) || ch->recv_mod_value_size_expected < ch->recv_mod_value_size) { LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping malformed modifier.\n"); GNUNET_break_op (0); recv_error (ch); return; } ch->recv_state = MSG_STATE_MODIFIER; break; } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: { ch->recv_mod_value_size += psize - sizeof (*pmsg); if (!(MSG_STATE_MODIFIER == ch->recv_state || MSG_STATE_MOD_CONT == ch->recv_state) || ch->recv_mod_value_size_expected < ch->recv_mod_value_size) { LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping out of order message modifier continuation " "!(%u == %u || %u == %u) || %lu < %lu.\n", MSG_STATE_MODIFIER, ch->recv_state, MSG_STATE_MOD_CONT, ch->recv_state, ch->recv_mod_value_size_expected, ch->recv_mod_value_size); GNUNET_break_op (0); recv_error (ch); return; } break; } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: { if (ch->recv_state < MSG_STATE_METHOD || ch->recv_mod_value_size_expected != ch->recv_mod_value_size) { LOG (GNUNET_ERROR_TYPE_WARNING, "Dropping out of order message data fragment " "(%u < %u || %lu != %lu).\n", ch->recv_state, MSG_STATE_METHOD, ch->recv_mod_value_size_expected, ch->recv_mod_value_size); GNUNET_break_op (0); recv_error (ch); return; } ch->recv_state = MSG_STATE_DATA; break; } } GNUNET_PSYC_MessageCallback message_cb = ch->recv_flags & GNUNET_PSYC_MESSAGE_HISTORIC ? ch->hist_message_cb : ch->message_cb; if (NULL != message_cb) message_cb (ch->cb_cls, ch->recv_message_id, ch->recv_flags, pmsg); switch (ptype) { case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: recv_reset (ch); break; } } } /** * Handle incoming message acknowledgement from the PSYC service. * * @param ch The channel the acknowledgement is sent to. */ static void handle_psyc_message_ack (struct GNUNET_PSYC_Channel *ch) { if (0 == ch->tmit_ack_pending) { LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring extraneous message ACK\n"); GNUNET_break (0); return; } ch->tmit_ack_pending--; switch (ch->tmit.state) { case MSG_STATE_MODIFIER: case MSG_STATE_MOD_CONT: if (GNUNET_NO == ch->tmit_paused) channel_transmit_mod (ch); break; case MSG_STATE_DATA: if (GNUNET_NO == ch->tmit_paused) channel_transmit_data (ch); break; case MSG_STATE_END: case MSG_STATE_CANCEL: break; default: LOG (GNUNET_ERROR_TYPE_DEBUG, "Ignoring message ACK in state %u.\n", ch->tmit.state); } } /** * Type of a function to call when we receive a message * from the service. * * @param cls closure * @param msg message received, NULL on timeout or fatal error */ static void message_handler (void *cls, const struct GNUNET_MessageHeader *msg) { // YUCK! => please have disjoint message handlers... struct GNUNET_PSYC_Channel *ch = cls; struct GNUNET_PSYC_Master *mst = cls; struct GNUNET_PSYC_Slave *slv = cls; if (NULL == msg) { // timeout / disconnected from server, reconnect reschedule_connect (ch); return; } uint16_t size_eq = 0; uint16_t size_min = 0; uint16_t size = ntohs (msg->size); uint16_t type = ntohs (msg->type); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %d and size %u from PSYC service\n", type, size); switch (type) { case GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK: case GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK: size_eq = sizeof (struct CountersResult); break; case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE: size_min = sizeof (struct GNUNET_PSYC_MessageHeader); break; case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK: size_eq = sizeof (struct GNUNET_MessageHeader); break; default: GNUNET_break_op (0); return; } if (! ((0 < size_eq && size == size_eq) || (0 < size_min && size_min <= size))) { GNUNET_break_op (0); return; } switch (type) { case GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK: { struct CountersResult *cres = (struct CountersResult *) msg; mst->max_message_id = GNUNET_ntohll (cres->max_message_id); if (NULL != mst->start_cb) mst->start_cb (ch->cb_cls, mst->max_message_id); break; } case GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK: { struct CountersResult *cres = (struct CountersResult *) msg; slv->max_message_id = GNUNET_ntohll (cres->max_message_id); if (NULL != slv->join_cb) slv->join_cb (ch->cb_cls, slv->max_message_id); break; } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK: { handle_psyc_message_ack (ch); break; } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE: handle_psyc_message (ch, (const struct GNUNET_PSYC_MessageHeader *) msg); break; } if (NULL != ch->client) { GNUNET_CLIENT_receive (ch->client, &message_handler, ch, GNUNET_TIME_UNIT_FOREVER_REL); } } /** * Transmit next message to service. * * @param cls The 'struct GNUNET_PSYC_Channel'. * @param size Number of bytes available in buf. * @param buf Where to copy the message. * @return Number of bytes copied to buf. */ static size_t send_next_message (void *cls, size_t size, void *buf) { struct GNUNET_PSYC_Channel *ch = cls; struct OperationHandle *op = ch->tmit_head; size_t ret; LOG (GNUNET_ERROR_TYPE_DEBUG, "send_next_message()\n"); ch->th = NULL; if (NULL == op->msg) return 0; ret = ntohs (op->msg->size); if (ret > size) { reschedule_connect (ch); return 0; } memcpy (buf, op->msg, ret); GNUNET_CONTAINER_DLL_remove (ch->tmit_head, ch->tmit_tail, op); GNUNET_free (op); if (NULL != ch->tmit_head) transmit_next (ch); if (GNUNET_NO == ch->in_receive) { ch->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (ch->client, &message_handler, ch, GNUNET_TIME_UNIT_FOREVER_REL); } return ret; } /** * Schedule transmission of the next message from our queue. * * @param ch PSYC handle. */ static void transmit_next (struct GNUNET_PSYC_Channel *ch) { LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_next()\n"); if (NULL != ch->th || NULL == ch->client) return; struct OperationHandle *op = ch->tmit_head; if (NULL == op) return; ch->th = GNUNET_CLIENT_notify_transmit_ready (ch->client, ntohs (op->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_next_message, ch); } /** * Try again to connect to the PSYC service. * * @param cls Channel handle. * @param tc Scheduler context. */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PSYC_Channel *ch = cls; recv_reset (ch); ch->reconnect_task = GNUNET_SCHEDULER_NO_TASK; LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to PSYC service.\n"); GNUNET_assert (NULL == ch->client); ch->client = GNUNET_CLIENT_connect ("psyc", ch->cfg); GNUNET_assert (NULL != ch->client); if (NULL == ch->tmit_head || ch->tmit_head->msg->type != ch->reconnect_msg->type) { uint16_t reconn_size = ntohs (ch->reconnect_msg->size); struct OperationHandle *op = GNUNET_malloc (sizeof (*op) + reconn_size); memcpy (&op[1], ch->reconnect_msg, reconn_size); op->msg = (struct GNUNET_MessageHeader *) &op[1]; GNUNET_CONTAINER_DLL_insert (ch->tmit_head, ch->tmit_tail, op); } transmit_next (ch); } /** * Disconnect from the PSYC service. * * @param c Channel handle to disconnect */ static void disconnect (void *c) { struct GNUNET_PSYC_Channel *ch = c; GNUNET_assert (NULL != ch); if (ch->tmit_head != ch->tmit_tail) { LOG (GNUNET_ERROR_TYPE_ERROR, "Disconnecting while there are still outstanding messages!\n"); GNUNET_break (0); } if (ch->reconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ch->reconnect_task); ch->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } if (NULL != ch->th) { GNUNET_CLIENT_notify_transmit_ready_cancel (ch->th); ch->th = NULL; } if (NULL != ch->client) { GNUNET_CLIENT_disconnect (ch->client); ch->client = NULL; } if (NULL != ch->reconnect_msg) { GNUNET_free (ch->reconnect_msg); ch->reconnect_msg = NULL; } } /** * Start a PSYC master channel. * * Will start a multicast group identified by the given ECC key. Messages * received from group members will be given to the respective handler methods. * If a new member wants to join a group, the "join" method handler will be * invoked; the join handler must then generate a "join" message to approve the * joining of the new member. The channel can also change group membership * without explicit requests. Note that PSYC doesn't itself "understand" join * or part messages, the respective methods must call other PSYC functions to * inform PSYC about the meaning of the respective events. * * @param cfg Configuration to use (to connect to PSYC service). * @param channel_key ECC key that will be used to sign messages for this * PSYC session. The public key is used to identify the PSYC channel. * Note that end-users will usually not use the private key directly, but * rather look it up in GNS for places managed by other users, or select * a file with the private key(s) when setting up their own channels * FIXME: we'll likely want to use NOT the p521 curve here, but a cheaper * one in the future. * @param policy Channel policy specifying join and history restrictions. * Used to automate join decisions. * @param message_cb Function to invoke on message parts received from slaves. * @param join_cb Function to invoke when a peer wants to join. * @param master_started_cb Function to invoke after the channel master started. * @param cls Closure for @a master_started_cb and @a join_cb. * @return Handle for the channel master, NULL on error. */ struct GNUNET_PSYC_Master * GNUNET_PSYC_master_start (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key, enum GNUNET_PSYC_Policy policy, GNUNET_PSYC_MessageCallback message_cb, GNUNET_PSYC_JoinCallback join_cb, GNUNET_PSYC_MasterStartCallback master_started_cb, void *cls) { struct GNUNET_PSYC_Master *mst = GNUNET_malloc (sizeof (*mst)); struct GNUNET_PSYC_Channel *ch = &mst->ch; struct MasterStartRequest *req = GNUNET_malloc (sizeof (*req)); req->header.size = htons (sizeof (*req)); req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MASTER_START); req->channel_key = *channel_key; req->policy = policy; ch->cfg = cfg; ch->is_master = GNUNET_YES; ch->reconnect_msg = (struct GNUNET_MessageHeader *) req; ch->reconnect_delay = GNUNET_TIME_UNIT_ZERO; ch->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, mst); ch->message_cb = message_cb; ch->join_cb = join_cb; ch->cb_cls = cls; mst->start_cb = master_started_cb; return mst; } /** * Stop a PSYC master channel. * * @param master PSYC channel master to stop. */ void GNUNET_PSYC_master_stop (struct GNUNET_PSYC_Master *master) { disconnect (master); GNUNET_free (master); } /** * Function to call with the decision made for a join request. * * Must be called once and only once in response to an invocation of the * #GNUNET_PSYC_JoinCallback. * * @param jh Join request handle. * @param is_admitted #GNUNET_YES if joining is approved, * #GNUNET_NO if it is disapproved. * @param relay_count Number of relays given. * @param relays Array of suggested peers that might be useful relays to use * when joining the multicast group (essentially a list of peers that * are already part of the multicast group and might thus be willing * to help with routing). If empty, only this local peer (which must * be the multicast origin) is a good candidate for building the * multicast tree. Note that it is unnecessary to specify our own * peer identity in this array. * @param method_name Method name for the message transmitted with the response. * @param env Environment containing transient variables for the message, or NULL. * @param data Data of the message. * @param data_size Size of @a data. */ void GNUNET_PSYC_join_decision (struct GNUNET_PSYC_JoinHandle *jh, int is_admitted, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, const char *method_name, const struct GNUNET_ENV_Environment *env, const void *data, size_t data_size) { } /** * Send a message to call a method to all members in the PSYC channel. * * @param master Handle to the PSYC channel. * @param method_name Which method should be invoked. * @param notify_mod Function to call to obtain modifiers. * @param notify_data Function to call to obtain fragments of the data. * @param notify_cls Closure for @a notify_mod and @a notify_data. * @param flags Flags for the message being transmitted. * @return Transmission handle, NULL on error (i.e. more than one request queued). */ struct GNUNET_PSYC_MasterTransmitHandle * GNUNET_PSYC_master_transmit (struct GNUNET_PSYC_Master *master, const char *method_name, GNUNET_PSYC_TransmitNotifyModifier notify_mod, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_cls, enum GNUNET_PSYC_MasterTransmitFlags flags) { return (struct GNUNET_PSYC_MasterTransmitHandle *) channel_transmit (&master->ch, method_name, notify_mod, notify_data, notify_cls, flags); } /** * Resume transmission to the channel. * * @param th Handle of the request that is being resumed. */ void GNUNET_PSYC_master_transmit_resume (struct GNUNET_PSYC_MasterTransmitHandle *th) { channel_transmit_resume ((struct GNUNET_PSYC_ChannelTransmitHandle *) th); } /** * Abort transmission request to the channel. * * @param th Handle of the request that is being aborted. */ void GNUNET_PSYC_master_transmit_cancel (struct GNUNET_PSYC_MasterTransmitHandle *th) { channel_transmit_cancel ((struct GNUNET_PSYC_ChannelTransmitHandle *) th); } /** * Join a PSYC channel. * * The entity joining is always the local peer. The user must immediately use * the GNUNET_PSYC_slave_transmit() functions to transmit a @e join_msg to the * channel; if the join request succeeds, the channel state (and @e recent * method calls) will be replayed to the joining member. There is no explicit * notification on failure (as the channel may simply take days to approve, * and disapproval is simply being ignored). * * @param cfg Configuration to use. * @param channel_key ECC public key that identifies the channel we wish to join. * @param slave_key ECC private-public key pair that identifies the slave, and * used by multicast to sign the join request and subsequent unicast * requests sent to the master. * @param origin Peer identity of the origin. * @param relay_count Number of peers in the @a relays array. * @param relays Peer identities of members of the multicast group, which serve * as relays and used to join the group at. * @param message_cb Function to invoke on message parts received from the * channel, typically at least contains method handlers for @e join and * @e part. * @param join_cb function invoked once we have joined with the current * message ID of the channel * @param slave_joined_cb Function to invoke when a peer wants to join. * @param cls Closure for @a message_cb and @a slave_joined_cb. * @param method_name Method name for the join request. * @param env Environment containing transient variables for the request, or NULL. * @param data Payload for the join message. * @param data_size Number of bytes in @a data. * @return Handle for the slave, NULL on error. */ struct GNUNET_PSYC_Slave * GNUNET_PSYC_slave_join (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_CRYPTO_EddsaPublicKey *channel_key, const struct GNUNET_CRYPTO_EddsaPrivateKey *slave_key, const struct GNUNET_PeerIdentity *origin, uint32_t relay_count, const struct GNUNET_PeerIdentity *relays, GNUNET_PSYC_MessageCallback message_cb, GNUNET_PSYC_JoinCallback join_cb, GNUNET_PSYC_SlaveJoinCallback slave_joined_cb, void *cls, const char *method_name, const struct GNUNET_ENV_Environment *env, const void *data, uint16_t data_size) { struct GNUNET_PSYC_Slave *slv = GNUNET_malloc (sizeof (*slv)); struct GNUNET_PSYC_Channel *ch = &slv->ch; struct SlaveJoinRequest *req = GNUNET_malloc (sizeof (*req) + relay_count * sizeof (*relays)); req->header.size = htons (sizeof (*req) + relay_count * sizeof (*relays)); req->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN); req->channel_key = *channel_key; req->slave_key = *slave_key; req->origin = *origin; req->relay_count = htonl (relay_count); memcpy (&req[1], relays, relay_count * sizeof (*relays)); ch->message_cb = message_cb; ch->join_cb = join_cb; ch->cb_cls = cls; ch->cfg = cfg; ch->is_master = GNUNET_NO; ch->reconnect_msg = (struct GNUNET_MessageHeader *) req; ch->reconnect_delay = GNUNET_TIME_UNIT_ZERO; ch->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, slv); slv->join_cb = slave_joined_cb; return slv; } /** * Part a PSYC channel. * * Will terminate the connection to the PSYC service. Polite clients should * first explicitly send a part request (via GNUNET_PSYC_slave_transmit()). * * @param slave Slave handle. */ void GNUNET_PSYC_slave_part (struct GNUNET_PSYC_Slave *slave) { disconnect (slave); GNUNET_free (slave); } /** * Request a message to be sent to the channel master. * * @param slave Slave handle. * @param method_name Which (PSYC) method should be invoked (on host). * @param notify_mod Function to call to obtain modifiers. * @param notify_data Function to call to obtain fragments of the data. * @param notify_cls Closure for @a notify. * @param flags Flags for the message being transmitted. * @return Transmission handle, NULL on error (i.e. more than one request * queued). */ struct GNUNET_PSYC_SlaveTransmitHandle * GNUNET_PSYC_slave_transmit (struct GNUNET_PSYC_Slave *slave, const char *method_name, GNUNET_PSYC_TransmitNotifyModifier notify_mod, GNUNET_PSYC_TransmitNotifyData notify_data, void *notify_cls, enum GNUNET_PSYC_SlaveTransmitFlags flags) { return (struct GNUNET_PSYC_SlaveTransmitHandle *) channel_transmit (&slave->ch, method_name, notify_mod, notify_data, notify_cls, flags); } /** * Resume transmission to the master. * * @param th Handle of the request that is being resumed. */ void GNUNET_PSYC_slave_transmit_resume (struct GNUNET_PSYC_SlaveTransmitHandle *th) { channel_transmit_resume ((struct GNUNET_PSYC_ChannelTransmitHandle *) th); } /** * Abort transmission request to master. * * @param th Handle of the request that is being aborted. */ void GNUNET_PSYC_slave_transmit_cancel (struct GNUNET_PSYC_SlaveTransmitHandle *th) { channel_transmit_cancel ((struct GNUNET_PSYC_ChannelTransmitHandle *) th); } /** * Convert a channel @a master to a @e channel handle to access the @e channel * APIs. * * @param master Channel master handle. * @return Channel handle, valid for as long as @a master is valid. */ struct GNUNET_PSYC_Channel * GNUNET_PSYC_master_get_channel (struct GNUNET_PSYC_Master *master) { return &master->ch; } /** * Convert @a slave to a @e channel handle to access the @e channel APIs. * * @param slave Slave handle. * @return Channel handle, valid for as long as @a slave is valid. */ struct GNUNET_PSYC_Channel * GNUNET_PSYC_slave_get_channel (struct GNUNET_PSYC_Slave *slave) { return &slave->ch; } /** * Add a slave to the channel's membership list. * * Note that this will NOT generate any PSYC traffic, it will merely update the * local database to modify how we react to membership test queries. * The channel master still needs to explicitly transmit a @e join message to * notify other channel members and they then also must still call this function * in their respective methods handling the @e join message. This way, how @e * join and @e part operations are exactly implemented is still up to the * application; for example, there might be a @e part_all method to kick out * everyone. * * Note that channel slaves are explicitly trusted to execute such methods * correctly; not doing so correctly will result in either denying other slaves * access or offering access to channel data to non-members. * * @param channel Channel handle. * @param slave_key Identity of channel slave to add. * @param announced_at ID of the message that announced the membership change. * @param effective_since Addition of slave is in effect since this message ID. */ void GNUNET_PSYC_channel_slave_add (struct GNUNET_PSYC_Channel *channel, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t announced_at, uint64_t effective_since) { struct ChannelSlaveAdd *slvadd; struct OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*slvadd)); slvadd = (struct ChannelSlaveAdd *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) slvadd; slvadd->header.type = GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_ADD; slvadd->header.size = htons (sizeof (*slvadd)); slvadd->announced_at = GNUNET_htonll (announced_at); slvadd->effective_since = GNUNET_htonll (effective_since); GNUNET_CONTAINER_DLL_insert_tail (channel->tmit_head, channel->tmit_tail, op); transmit_next (channel); } /** * Remove a slave from the channel's membership list. * * Note that this will NOT generate any PSYC traffic, it will merely update the * local database to modify how we react to membership test queries. * The channel master still needs to explicitly transmit a @e part message to * notify other channel members and they then also must still call this function * in their respective methods handling the @e part message. This way, how * @e join and @e part operations are exactly implemented is still up to the * application; for example, there might be a @e part_all message to kick out * everyone. * * Note that channel members are explicitly trusted to perform these * operations correctly; not doing so correctly will result in either * denying members access or offering access to channel data to * non-members. * * @param channel Channel handle. * @param slave_key Identity of channel slave to remove. * @param announced_at ID of the message that announced the membership change. */ void GNUNET_PSYC_channel_slave_remove (struct GNUNET_PSYC_Channel *channel, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t announced_at) { struct ChannelSlaveRemove *slvrm; struct OperationHandle *op = GNUNET_malloc (sizeof (*op) + sizeof (*slvrm)); slvrm = (struct ChannelSlaveRemove *) &op[1]; op->msg = (struct GNUNET_MessageHeader *) slvrm; slvrm->header.type = GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_RM; slvrm->header.size = htons (sizeof (*slvrm)); slvrm->announced_at = GNUNET_htonll (announced_at); GNUNET_CONTAINER_DLL_insert_tail (channel->tmit_head, channel->tmit_tail, op); transmit_next (channel); } /** * Request to be told the message history of the channel. * * Historic messages (but NOT the state at the time) will be replayed (given to * the normal method handlers) if available and if access is permitted. * * To get the latest message, use 0 for both the start and end message ID. * * @param channel Which channel should be replayed? * @param start_message_id Earliest interesting point in history. * @param end_message_id Last (exclusive) interesting point in history. * @param message_cb Function to invoke on message parts received from the story. * @param finish_cb Function to call when the requested story has been fully * told (counting message IDs might not suffice, as some messages * might be secret and thus the listener would not know the story is * finished without being told explicitly) once this function * has been called, the client must not call * GNUNET_PSYC_channel_story_tell_cancel() anymore. * @param cls Closure for the callbacks. * @return Handle to cancel story telling operation. */ struct GNUNET_PSYC_Story * GNUNET_PSYC_channel_story_tell (struct GNUNET_PSYC_Channel *channel, uint64_t start_message_id, uint64_t end_message_id, GNUNET_PSYC_MessageCallback message_cb, GNUNET_PSYC_FinishCallback finish_cb, void *cls) { return NULL; } /** * Abort story telling. * * This function must not be called from within method handlers (as given to * GNUNET_PSYC_slave_join()) of the slave. * * @param story Story telling operation to stop. */ void GNUNET_PSYC_channel_story_tell_cancel (struct GNUNET_PSYC_Story *story) { } /** * Retrieve the best matching channel state variable. * * If the requested variable name is not present in the state, the nearest * less-specific name is matched; for example, requesting "_a_b" will match "_a" * if "_a_b" does not exist. * * @param channel Channel handle. * @param full_name Full name of the requested variable, the actual variable * returned might have a shorter name.. * @param cb Function called once when a matching state variable is found. * Not called if there's no matching state variable. * @param cb_cls Closure for the callbacks. * @return Handle that can be used to cancel the query operation. */ struct GNUNET_PSYC_StateQuery * GNUNET_PSYC_channel_state_get (struct GNUNET_PSYC_Channel *channel, const char *full_name, GNUNET_PSYC_StateCallback cb, void *cb_cls) { return NULL; } /** * Return all channel state variables whose name matches a given prefix. * * A name matches if it starts with the given @a name_prefix, thus requesting * the empty prefix ("") will match all values; requesting "_a_b" will also * return values stored under "_a_b_c". * * The @a state_cb is invoked on all matching state variables asynchronously, as * the state is stored in and retrieved from the PSYCstore, * * @param channel Channel handle. * @param name_prefix Prefix of the state variable name to match. * @param cb Function to call with the matching state variables. * @param cb_cls Closure for the callbacks. * @return Handle that can be used to cancel the query operation. */ struct GNUNET_PSYC_StateQuery * GNUNET_PSYC_channel_state_get_prefix (struct GNUNET_PSYC_Channel *channel, const char *name_prefix, GNUNET_PSYC_StateCallback cb, void *cb_cls) { return NULL; } /** * Cancel a state query operation. * * @param query Handle for the operation to cancel. */ void GNUNET_PSYC_channel_state_get_cancel (struct GNUNET_PSYC_StateQuery *query) { } /* end of psyc_api.c */ gnunet-0.10.1/src/psyc/psyc_common.c0000644000175000017500000000645712310570720014262 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psyc/psyc_common.c * @brief Common functions for PSYC * @author Gabor X Toth */ #include #include "psyc.h" /** * Check if @a data contains a series of valid message parts. * * @param data_size Size of @a data. * @param data Data. * * @return Message type number * or GNUNET_NO if the message contains invalid or no parts. */ uint16_t GNUNET_PSYC_message_last_part (uint16_t data_size, const char *data) { const struct GNUNET_MessageHeader *pmsg; uint16_t ptype = GNUNET_NO; uint16_t psize = 0; uint16_t pos = 0; for (pos = 0; pos < data_size; pos += psize) { pmsg = (const struct GNUNET_MessageHeader *) (data + pos); psize = ntohs (pmsg->size); ptype = ntohs (pmsg->type); if (psize < sizeof (*pmsg) || pos + psize > data_size || ptype < GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD || GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL < ptype) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid message part of type %u and size %u.\n", ptype, psize); return GNUNET_NO; } } return ptype; } void GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind, const struct GNUNET_MessageHeader *msg) { uint16_t size = ntohs (msg->size); uint16_t type = ntohs (msg->type); GNUNET_log (kind, "Message of type %d and size %u:\n", type, size); switch (type) { case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE: { struct GNUNET_PSYC_MessageHeader *pmsg = (struct GNUNET_PSYC_MessageHeader *) msg; GNUNET_log (kind, "\tID: %" PRIu64 "\tflags: %" PRIu32 "\n", GNUNET_ntohll (pmsg->message_id), ntohl (pmsg->flags)); break; } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: { struct GNUNET_PSYC_MessageMethod *meth = (struct GNUNET_PSYC_MessageMethod *) msg; GNUNET_log (kind, "\t%.*s\n", size - sizeof (*meth), &meth[1]); break; } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: { struct GNUNET_PSYC_MessageModifier *mod = (struct GNUNET_PSYC_MessageModifier *) msg; uint16_t name_size = ntohs (mod->name_size); char oper = ' ' < mod->oper ? mod->oper : ' '; GNUNET_log (kind, "\t%c%.*s\t%.*s\n", oper, name_size, &mod[1], size - sizeof (*mod) - name_size - 1, ((char *) &mod[1]) + name_size + 1); break; } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: GNUNET_log (kind, "\t%.*s\n", size - sizeof (*msg), &msg[1]); break; } } gnunet-0.10.1/src/psyc/Makefile.in0000644000175000017500000013764112320752063013640 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = libexec_PROGRAMS = gnunet-service-psyc$(EXEEXT) @HAVE_TESTING_TRUE@check_PROGRAMS = test_psyc$(EXEEXT) subdir = src/psyc DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/psyc.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = psyc.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = am_libgnunetpsyc_la_OBJECTS = psyc_api.lo psyc_common.lo libgnunetpsyc_la_OBJECTS = $(am_libgnunetpsyc_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunetpsyc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetpsyc_la_LDFLAGS) $(LDFLAGS) \ -o $@ PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) am_gnunet_service_psyc_OBJECTS = \ gnunet_service_psyc-gnunet-service-psyc.$(OBJEXT) \ gnunet_service_psyc-psyc_common.$(OBJEXT) gnunet_service_psyc_OBJECTS = $(am_gnunet_service_psyc_OBJECTS) gnunet_service_psyc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(gnunet_service_psyc_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_test_psyc_OBJECTS = test_psyc.$(OBJEXT) test_psyc_OBJECTS = $(am_test_psyc_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunetpsyc_la_SOURCES) $(gnunet_service_psyc_SOURCES) \ $(test_psyc_SOURCES) DIST_SOURCES = $(libgnunetpsyc_la_SOURCES) \ $(gnunet_service_psyc_SOURCES) $(test_psyc_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir = $(pkgdatadir)/config.d/ pkgcfg_DATA = \ psyc.conf @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov lib_LTLIBRARIES = libgnunetpsyc.la libgnunetpsyc_la_SOURCES = \ psyc_api.c psyc.h \ psyc_common.c libgnunetpsyc_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/env/libgnunetenv.la \ $(GN_LIBINTL) $(XLIB) libgnunetpsyc_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetpsyc_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/env/libgnunetenv.la gnunet_service_psyc_SOURCES = \ gnunet-service-psyc.c \ psyc_common.c gnunet_service_psyc_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/multicast/libgnunetmulticast.la \ $(top_builddir)/src/psycstore/libgnunetpsycstore.la \ $(GN_LIBINTL) gnunet_service_psyc_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/multicast/libgnunetmulticast.la \ $(top_builddir)/src/psycstore/libgnunetpsycstore.la gnunet_service_psyc_CFLAGS = $(AM_CFLAGS) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_psyc_SOURCES = \ test_psyc.c test_psyc_LDADD = \ libgnunetpsyc.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/env/libgnunetenv.la \ $(top_builddir)/src/util/libgnunetutil.la test_psyc_DEPENDENCIES = \ libgnunetpsyc.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/env/libgnunetenv.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_psyc.conf all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/psyc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/psyc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): psyc.conf: $(top_builddir)/config.status $(srcdir)/psyc.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunetpsyc.la: $(libgnunetpsyc_la_OBJECTS) $(libgnunetpsyc_la_DEPENDENCIES) $(EXTRA_libgnunetpsyc_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetpsyc_la_LINK) -rpath $(libdir) $(libgnunetpsyc_la_OBJECTS) $(libgnunetpsyc_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-service-psyc$(EXEEXT): $(gnunet_service_psyc_OBJECTS) $(gnunet_service_psyc_DEPENDENCIES) $(EXTRA_gnunet_service_psyc_DEPENDENCIES) @rm -f gnunet-service-psyc$(EXEEXT) $(AM_V_CCLD)$(gnunet_service_psyc_LINK) $(gnunet_service_psyc_OBJECTS) $(gnunet_service_psyc_LDADD) $(LIBS) test_psyc$(EXEEXT): $(test_psyc_OBJECTS) $(test_psyc_DEPENDENCIES) $(EXTRA_test_psyc_DEPENDENCIES) @rm -f test_psyc$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_psyc_OBJECTS) $(test_psyc_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_psyc-gnunet-service-psyc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet_service_psyc-psyc_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psyc_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/psyc_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_psyc.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< gnunet_service_psyc-gnunet-service-psyc.o: gnunet-service-psyc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_psyc_CFLAGS) $(CFLAGS) -MT gnunet_service_psyc-gnunet-service-psyc.o -MD -MP -MF $(DEPDIR)/gnunet_service_psyc-gnunet-service-psyc.Tpo -c -o gnunet_service_psyc-gnunet-service-psyc.o `test -f 'gnunet-service-psyc.c' || echo '$(srcdir)/'`gnunet-service-psyc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_psyc-gnunet-service-psyc.Tpo $(DEPDIR)/gnunet_service_psyc-gnunet-service-psyc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-psyc.c' object='gnunet_service_psyc-gnunet-service-psyc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_psyc_CFLAGS) $(CFLAGS) -c -o gnunet_service_psyc-gnunet-service-psyc.o `test -f 'gnunet-service-psyc.c' || echo '$(srcdir)/'`gnunet-service-psyc.c gnunet_service_psyc-gnunet-service-psyc.obj: gnunet-service-psyc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_psyc_CFLAGS) $(CFLAGS) -MT gnunet_service_psyc-gnunet-service-psyc.obj -MD -MP -MF $(DEPDIR)/gnunet_service_psyc-gnunet-service-psyc.Tpo -c -o gnunet_service_psyc-gnunet-service-psyc.obj `if test -f 'gnunet-service-psyc.c'; then $(CYGPATH_W) 'gnunet-service-psyc.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-psyc.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_psyc-gnunet-service-psyc.Tpo $(DEPDIR)/gnunet_service_psyc-gnunet-service-psyc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gnunet-service-psyc.c' object='gnunet_service_psyc-gnunet-service-psyc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_psyc_CFLAGS) $(CFLAGS) -c -o gnunet_service_psyc-gnunet-service-psyc.obj `if test -f 'gnunet-service-psyc.c'; then $(CYGPATH_W) 'gnunet-service-psyc.c'; else $(CYGPATH_W) '$(srcdir)/gnunet-service-psyc.c'; fi` gnunet_service_psyc-psyc_common.o: psyc_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_psyc_CFLAGS) $(CFLAGS) -MT gnunet_service_psyc-psyc_common.o -MD -MP -MF $(DEPDIR)/gnunet_service_psyc-psyc_common.Tpo -c -o gnunet_service_psyc-psyc_common.o `test -f 'psyc_common.c' || echo '$(srcdir)/'`psyc_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_psyc-psyc_common.Tpo $(DEPDIR)/gnunet_service_psyc-psyc_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='psyc_common.c' object='gnunet_service_psyc-psyc_common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_psyc_CFLAGS) $(CFLAGS) -c -o gnunet_service_psyc-psyc_common.o `test -f 'psyc_common.c' || echo '$(srcdir)/'`psyc_common.c gnunet_service_psyc-psyc_common.obj: psyc_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_psyc_CFLAGS) $(CFLAGS) -MT gnunet_service_psyc-psyc_common.obj -MD -MP -MF $(DEPDIR)/gnunet_service_psyc-psyc_common.Tpo -c -o gnunet_service_psyc-psyc_common.obj `if test -f 'psyc_common.c'; then $(CYGPATH_W) 'psyc_common.c'; else $(CYGPATH_W) '$(srcdir)/psyc_common.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/gnunet_service_psyc-psyc_common.Tpo $(DEPDIR)/gnunet_service_psyc-psyc_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='psyc_common.c' object='gnunet_service_psyc-psyc_common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(gnunet_service_psyc_CFLAGS) $(CFLAGS) -c -o gnunet_service_psyc-psyc_common.obj `if test -f 'psyc_common.c'; then $(CYGPATH_W) 'psyc_common.c'; else $(CYGPATH_W) '$(srcdir)/psyc_common.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_psyc.log: test_psyc$(EXEEXT) @p='test_psyc$(EXEEXT)'; \ b='test_psyc'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ install-libexecPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/psyc/psyc.h0000644000175000017500000001032712310570720012706 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psyc/psyc.h * @brief Common type definitions for the PSYC service and API. * @author Gabor X Toth */ #ifndef PSYC_H #define PSYC_H #include "platform.h" #include "gnunet_psyc_service.h" uint16_t GNUNET_PSYC_message_last_part (uint16_t data_size, const char *data); void GNUNET_PSYC_log_message (enum GNUNET_ErrorType kind, const struct GNUNET_MessageHeader *msg); enum MessageState { MSG_STATE_START = 0, MSG_STATE_HEADER = 1, MSG_STATE_METHOD = 2, MSG_STATE_MODIFIER = 3, MSG_STATE_MOD_CONT = 4, MSG_STATE_DATA = 5, MSG_STATE_END = 6, MSG_STATE_CANCEL = 7, }; GNUNET_NETWORK_STRUCT_BEGIN /**** library -> service ****/ struct MasterStartRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYC_MASTER_START */ struct GNUNET_MessageHeader header; struct GNUNET_CRYPTO_EddsaPrivateKey channel_key; uint32_t policy GNUNET_PACKED; }; struct SlaveJoinRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN */ struct GNUNET_MessageHeader header; uint32_t relay_count GNUNET_PACKED; struct GNUNET_CRYPTO_EddsaPublicKey channel_key; struct GNUNET_CRYPTO_EddsaPrivateKey slave_key; struct GNUNET_PeerIdentity origin; /* Followed by struct GNUNET_PeerIdentity relays[relay_count] */ }; struct ChannelSlaveAdd { /** * Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_ADD */ struct GNUNET_MessageHeader header; uint32_t reserved; struct GNUNET_CRYPTO_EddsaPublicKey *slave_key; uint64_t announced_at; uint64_t effective_since; }; struct ChannelSlaveRemove { /** * Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_RM */ struct GNUNET_MessageHeader header; uint32_t reserved; struct GNUNET_CRYPTO_EddsaPublicKey *slave_key; uint64_t announced_at; }; struct StoryRequest { /** * Type: GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STORY_REQUEST */ struct GNUNET_MessageHeader header; uint64_t op_id; uint64_t start_message_id; uint64_t end_message_id; }; struct StateRequest { /** * Types: * - GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STATE_GET * - GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STATE_GET_PREFIX */ struct GNUNET_MessageHeader header; /** * ID for this operation. */ uint64_t op_id; /* Followed by NUL-terminated name. */ }; /**** service -> library ****/ struct CountersResult { /** * Type: GNUNET_MESSAGE_TYPE_PSYC_RESULT_COUNTERS */ struct GNUNET_MessageHeader header; /** * Status code for the operation. */ int32_t result_code GNUNET_PACKED; /** * Last message ID sent to the channel. */ uint64_t max_message_id; }; /** * Answer from service to client about last operation. */ struct OperationResult { /** * Types: * - GNUNET_MESSAGE_TYPE_PSYC_RESULT_CODE * - GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STORY_RESULT * - GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_STATE_RESULT */ struct GNUNET_MessageHeader header; /** * Operation ID. */ uint32_t op_id GNUNET_PACKED; /** * Status code for the operation. */ int64_t result_code GNUNET_PACKED; /* Followed by: * - on error: NUL-terminated error message * - on success: one of the following message types * * For a STORY_RESULT: * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE * * For a STATE_RESULT, one of: * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT * - GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/psyc/Makefile.am0000644000175000017500000000405212320751517013617 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ pkgcfg_DATA = \ psyc.conf if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 XLIB = -lgcov endif lib_LTLIBRARIES = libgnunetpsyc.la libgnunetpsyc_la_SOURCES = \ psyc_api.c psyc.h \ psyc_common.c libgnunetpsyc_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/env/libgnunetenv.la \ $(GN_LIBINTL) $(XLIB) libgnunetpsyc_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ -version-info 0:0:0 libgnunetpsyc_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/env/libgnunetenv.la bin_PROGRAMS = libexec_PROGRAMS = \ gnunet-service-psyc gnunet_service_psyc_SOURCES = \ gnunet-service-psyc.c \ psyc_common.c gnunet_service_psyc_LDADD = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/multicast/libgnunetmulticast.la \ $(top_builddir)/src/psycstore/libgnunetpsycstore.la \ $(GN_LIBINTL) gnunet_service_psyc_DEPENDENCIES = \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/multicast/libgnunetmulticast.la \ $(top_builddir)/src/psycstore/libgnunetpsycstore.la gnunet_service_psyc_CFLAGS = $(AM_CFLAGS) if HAVE_TESTING check_PROGRAMS = \ test_psyc endif if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) endif test_psyc_SOURCES = \ test_psyc.c test_psyc_LDADD = \ libgnunetpsyc.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/env/libgnunetenv.la \ $(top_builddir)/src/util/libgnunetutil.la test_psyc_DEPENDENCIES = \ libgnunetpsyc.la \ $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/env/libgnunetenv.la \ $(top_builddir)/src/util/libgnunetutil.la EXTRA_DIST = \ test_psyc.conf gnunet-0.10.1/src/psyc/test_psyc.conf0000644000175000017500000000063612262754601014455 00000000000000[arm] UNIXPATH = $GNUNET_RUNTIME_DIR/test-gnunet-service-arm.sock DEFAULTSERVICES = psyc [psyc] AUTOSTART = YES BINARY = gnunet-service-psyc UNIXPATH = $GNUNET_RUNTIME_DIR/test-gnunet-service-psyc.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES [psycstore] AUTOSTART = YES BINARY = gnunet-service-psycstore UNIXPATH = $GNUNET_RUNTIME_DIR/test-gnunet-service-psycstore.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES gnunet-0.10.1/src/psyc/gnunet-service-psyc.c0000644000175000017500000010640312310570720015636 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psyc/gnunet-service-psyc.c * @brief PSYC service * @author Gabor X Toth */ #include #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_statistics_service.h" #include "gnunet_multicast_service.h" #include "gnunet_psycstore_service.h" #include "gnunet_psyc_service.h" #include "psyc.h" /** * Handle to our current configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle to the statistics service. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Notification context, simplifies client broadcasts. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Handle to the PSYCstore. */ static struct GNUNET_PSYCSTORE_Handle *store; /** * All connected masters and slaves. * Channel's pub_key_hash -> struct Channel */ static struct GNUNET_CONTAINER_MultiHashMap *clients; /** * Message in the transmission queue. */ struct TransmitMessage { struct TransmitMessage *prev; struct TransmitMessage *next; /** * Buffer with message to be transmitted. */ char *buf; /** * Size of @a buf */ uint16_t size ; /** * @see enum MessageState */ uint8_t state; }; /** * Cache for received message fragments. * Message fragments are only sent to clients after all modifiers arrived. * * chan_key -> MultiHashMap chan_msgs */ static struct GNUNET_CONTAINER_MultiHashMap *recv_cache; /** * Entry in the chan_msgs hashmap of @a recv_cache: * fragment_id -> FragmentEntry */ struct FragmentEntry { struct GNUNET_MULTICAST_MessageHeader *mmsg; uint16_t ref_count; }; /** * Entry in the @a recv_msgs hash map of a @a Channel. * message_id -> FragmentCache */ struct FragmentCache { /** * Total size of header fragments (METHOD & MODIFIERs) */ uint64_t header_size; /** * Fragment IDs stored in @a recv_cache. */ struct GNUNET_CONTAINER_Heap *fragments; }; /** * Common part of the client context for both a master and slave channel. */ struct Channel { struct GNUNET_SERVER_Client *client; struct TransmitMessage *tmit_head; struct TransmitMessage *tmit_tail; /** * Received fragments not yet sent to the client. * message_id -> FragmentCache */ struct GNUNET_CONTAINER_MultiHashMap *recv_msgs; /** * FIXME */ GNUNET_SCHEDULER_TaskIdentifier tmit_task; /** * Public key of the channel. */ struct GNUNET_CRYPTO_EddsaPublicKey pub_key; /** * Hash of @a pub_key. */ struct GNUNET_HashCode pub_key_hash; /** * Expected value size for the modifier being received from the PSYC service. */ uint32_t tmit_mod_value_size_expected; /** * Actual value size for the modifier being received from the PSYC service. */ uint32_t tmit_mod_value_size; /** * @see enum MessageState */ uint8_t tmit_state; /** * FIXME */ uint8_t in_transmit; /** * Is this a channel master (#GNUNET_YES), or slave (#GNUNET_NO)? */ uint8_t is_master; /** * Ready to receive messages from client? #GNUNET_YES or #GNUNET_NO */ uint8_t ready; /** * Is the client disconnected? #GNUNET_YES or #GNUNET_NO */ uint8_t disconnected; }; /** * Client context for a channel master. */ struct Master { /** * Channel struct common for Master and Slave */ struct Channel channel; /** * Private key of the channel. */ struct GNUNET_CRYPTO_EddsaPrivateKey priv_key; /** * Handle for the multicast origin. */ struct GNUNET_MULTICAST_Origin *origin; /** * Transmit handle for multicast. */ struct GNUNET_MULTICAST_OriginMessageHandle *tmit_handle; /** * Maximum message ID for this channel. * * Incremented before sending a message, thus the message_id in messages sent * starts from 1. */ uint64_t max_message_id; /** * ID of the last message that contains any state operations. * 0 if there is no such message. */ uint64_t max_state_message_id; /** * Maximum group generation for this channel. */ uint64_t max_group_generation; /** * @see enum GNUNET_PSYC_Policy */ uint32_t policy; }; /** * Client context for a channel slave. */ struct Slave { /** * Channel struct common for Master and Slave */ struct Channel channel; /** * Private key of the slave. */ struct GNUNET_CRYPTO_EddsaPrivateKey slave_key; /** * Handle for the multicast member. */ struct GNUNET_MULTICAST_Member *member; /** * Transmit handle for multicast. */ struct GNUNET_MULTICAST_MemberRequestHandle *tmit_handle; /** * Peer identity of the origin. */ struct GNUNET_PeerIdentity origin; /** * Number of items in @a relays. */ uint32_t relay_count; /** * Relays that multicast can use to connect. */ struct GNUNET_PeerIdentity *relays; /** * Join request to be transmitted to the master on join. */ struct GNUNET_MessageHeader *join_req; /** * Maximum message ID for this channel. */ uint64_t max_message_id; /** * Maximum request ID for this channel. */ uint64_t max_request_id; }; static inline void transmit_message (struct Channel *ch, uint8_t inc_msg_id); /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != nc) { GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; } if (NULL != stats) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } } static void client_cleanup (struct Channel *ch) { /* FIXME: fragment_cache_clear */ if (ch->is_master) { struct Master *mst = (struct Master *) ch; if (NULL != mst->origin) GNUNET_MULTICAST_origin_stop (mst->origin); GNUNET_CONTAINER_multihashmap_remove (clients, &ch->pub_key_hash, mst); } else { struct Slave *slv = (struct Slave *) ch; if (NULL != slv->join_req) GNUNET_free (slv->join_req); if (NULL != slv->relays) GNUNET_free (slv->relays); if (NULL != slv->member) GNUNET_MULTICAST_member_part (slv->member); } GNUNET_free (ch); } /** * Called whenever a client is disconnected. * Frees our resources associated with that client. * * @param cls Closure. * @param client Identification of the client. */ static void client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { if (NULL == client) return; struct Channel *ch = GNUNET_SERVER_client_get_user_context (client, struct Channel); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Client disconnected\n", ch); if (NULL == ch) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%p User context is NULL in client_disconnect()\n", ch); GNUNET_break (0); return; } ch->disconnected = GNUNET_YES; /* Send pending messages to multicast before cleanup. */ if (NULL != ch->tmit_head) { transmit_message (ch, GNUNET_NO); } else { client_cleanup (ch); } } /** * Master receives a join request from a slave. */ static void join_cb (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, const struct GNUNET_MessageHeader *join_req, struct GNUNET_MULTICAST_JoinHandle *jh) { } static void membership_test_cb (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t message_id, uint64_t group_generation, struct GNUNET_MULTICAST_MembershipTestHandle *mth) { } static void replay_fragment_cb (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t fragment_id, uint64_t flags, struct GNUNET_MULTICAST_ReplayHandle *rh) { } static void replay_message_cb (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, uint64_t message_id, uint64_t fragment_offset, uint64_t flags, struct GNUNET_MULTICAST_ReplayHandle *rh) { } static void fragment_store_result (void *cls, int64_t result, const char *err_msg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "fragment_store() returned %l (%s)\n", result, err_msg); } static void message_to_client (struct Channel *ch, const struct GNUNET_MULTICAST_MessageHeader *mmsg) { uint16_t size = ntohs (mmsg->header.size); struct GNUNET_PSYC_MessageHeader *pmsg; uint16_t psize = sizeof (*pmsg) + size - sizeof (*mmsg); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Sending message to client. " "fragment_id: %" PRIu64 ", message_id: %" PRIu64 "\n", ch, GNUNET_ntohll (mmsg->fragment_id), GNUNET_ntohll (mmsg->message_id)); pmsg = GNUNET_malloc (psize); pmsg->header.size = htons (psize); pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); pmsg->message_id = mmsg->message_id; memcpy (&pmsg[1], &mmsg[1], size - sizeof (*mmsg)); GNUNET_SERVER_notification_context_add (nc, ch->client); GNUNET_SERVER_notification_context_unicast (nc, ch->client, (const struct GNUNET_MessageHeader *) pmsg, GNUNET_NO); GNUNET_free (pmsg); } /** * Convert an uint64_t in network byte order to a HashCode * that can be used as key in a MultiHashMap */ static inline void hash_key_from_nll (struct GNUNET_HashCode *key, uint64_t n) { /* use little-endian order, as idx_of MultiHashMap casts key to unsigned int */ n = ((n << 8) & 0xFF00FF00FF00FF00ULL) | ((n >> 8) & 0x00FF00FF00FF00FFULL); n = ((n << 16) & 0xFFFF0000FFFF0000ULL) | ((n >> 16) & 0x0000FFFF0000FFFFULL); *key = (struct GNUNET_HashCode) {{ 0 }}; *((uint64_t *) key) = (n << 32) | (n >> 32); } /** * Convert an uint64_t in host byte order to a HashCode * that can be used as key in a MultiHashMap */ static inline void hash_key_from_hll (struct GNUNET_HashCode *key, uint64_t n) { #if __BYTE_ORDER == __BIG_ENDIAN hash_key_from_nll (key, n); #elif __BYTE_ORDER == __LITTLE_ENDIAN *key = (struct GNUNET_HashCode) {{ 0 }}; *((uint64_t *) key) = n; #else #error byteorder undefined #endif } static void fragment_cache_insert (struct Channel *ch, const struct GNUNET_HashCode *msg_id, struct FragmentCache *frag_cache, const struct GNUNET_MULTICAST_MessageHeader *mmsg, uint16_t last_part_type) { uint16_t size = ntohs (mmsg->header.size); struct GNUNET_CONTAINER_MultiHashMap *chan_msgs = GNUNET_CONTAINER_multihashmap_get (recv_cache, &ch->pub_key_hash); if (NULL == frag_cache) { frag_cache = GNUNET_new (struct FragmentCache); frag_cache->fragments = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); if (NULL == ch->recv_msgs) { ch->recv_msgs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); } GNUNET_CONTAINER_multihashmap_put (ch->recv_msgs, msg_id, frag_cache, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); if (NULL == chan_msgs) { chan_msgs = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO); GNUNET_CONTAINER_multihashmap_put (recv_cache, &ch->pub_key_hash, chan_msgs, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); } } struct GNUNET_HashCode *frag_id = GNUNET_new (struct GNUNET_HashCode); hash_key_from_nll (frag_id, mmsg->fragment_id); struct FragmentEntry *frag_entry = GNUNET_CONTAINER_multihashmap_get (chan_msgs, frag_id); if (NULL == frag_entry) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Adding message fragment to cache. " "fragment_id: %" PRIu64 ", " "header_size: %" PRIu64 " + %" PRIu64 ").\n", ch, GNUNET_ntohll (mmsg->fragment_id), frag_cache->header_size, size); frag_entry = GNUNET_new (struct FragmentEntry); frag_entry->ref_count = 1; frag_entry->mmsg = GNUNET_malloc (size); memcpy (frag_entry->mmsg, mmsg, size); GNUNET_CONTAINER_multihashmap_put (chan_msgs, frag_id, frag_entry, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); } else { frag_entry->ref_count++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Message fragment already in cache. " "fragment_id: %" PRIu64 ", ref_count: %u\n", ch, GNUNET_ntohll (mmsg->fragment_id), frag_entry->ref_count); } switch (last_part_type) { case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: frag_cache->header_size += size; } GNUNET_CONTAINER_heap_insert (frag_cache->fragments, frag_id, GNUNET_ntohll (mmsg->fragment_id)); } static void fragment_cache_clear (struct Channel *ch, const struct GNUNET_HashCode *msg_id, struct FragmentCache *frag_cache, uint8_t send_to_client) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Clearing message fragment cache.\n", ch); struct GNUNET_CONTAINER_MultiHashMap *chan_msgs = GNUNET_CONTAINER_multihashmap_get (recv_cache, &ch->pub_key_hash); GNUNET_assert (NULL != chan_msgs); struct GNUNET_HashCode *frag_id; while ((frag_id = GNUNET_CONTAINER_heap_remove_root (frag_cache->fragments))) { struct FragmentEntry *frag_entry = GNUNET_CONTAINER_multihashmap_get (chan_msgs, frag_id); if (frag_entry != NULL) { if (GNUNET_YES == send_to_client) { message_to_client (ch, frag_entry->mmsg); } if (1 == frag_entry->ref_count) { GNUNET_CONTAINER_multihashmap_remove (chan_msgs, frag_id, frag_entry); GNUNET_free (frag_entry->mmsg); GNUNET_free (frag_entry); } else { frag_entry->ref_count--; } } GNUNET_free (frag_id); } GNUNET_CONTAINER_multihashmap_remove (ch->recv_msgs, msg_id, frag_cache); GNUNET_CONTAINER_heap_destroy (frag_cache->fragments); GNUNET_free (frag_cache); } /** * Incoming message fragment from multicast. * * Store it using PSYCstore and send it to the client of the channel. */ static void message_cb (void *cls, const struct GNUNET_MessageHeader *msg) { struct Channel *ch = cls; uint16_t type = ntohs (msg->type); uint16_t size = ntohs (msg->size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Received message of type %u and size %u from multicast.\n", ch, type, size); switch (type) { case GNUNET_MESSAGE_TYPE_MULTICAST_MESSAGE: { GNUNET_PSYCSTORE_fragment_store (store, &ch->pub_key, (const struct GNUNET_MULTICAST_MessageHeader *) msg, 0, NULL, NULL); #if TODO /* FIXME: apply modifiers to state in PSYCstore */ GNUNET_PSYCSTORE_state_modify (store, &ch->pub_key, GNUNET_ntohll (mmsg->message_id), meth->mod_count, mods, rcb, rcb_cls); #endif const struct GNUNET_MULTICAST_MessageHeader *mmsg = (const struct GNUNET_MULTICAST_MessageHeader *) msg; uint16_t ptype = GNUNET_PSYC_message_last_part (size - sizeof (*mmsg), (const char *) &mmsg[1]); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last message part type %u\n", ptype); if (GNUNET_NO == ptype) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%p Received message with invalid parts from multicast. " "Dropping message.\n", ch); GNUNET_break_op (0); break; } struct GNUNET_HashCode msg_id; hash_key_from_nll (&msg_id, mmsg->message_id); struct FragmentCache *frag_cache = NULL; if (NULL != ch->recv_msgs) frag_cache = GNUNET_CONTAINER_multihashmap_get (ch->recv_msgs, &msg_id); switch (ptype) { case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END: /* FIXME: check state flag / max_state_message_id */ if (NULL == frag_cache) { message_to_client (ch, mmsg); break; } else { if (GNUNET_ntohll (mmsg->fragment_offset) == frag_cache->header_size) { /* first data fragment after the header, send cached fragments */ fragment_cache_clear (ch, &msg_id, frag_cache, GNUNET_YES); message_to_client (ch, mmsg); break; } else { /* still missing fragments from the header, cache data fragment */ /* fall thru */ } } case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER: case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT: /* not all modifiers arrived yet, cache fragment */ fragment_cache_insert (ch, &msg_id, frag_cache, mmsg, ptype); break; case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL: if (NULL != frag_cache) { /* fragments not yet sent to client, remove from cache */ fragment_cache_clear (ch, &msg_id, frag_cache, GNUNET_NO); } else { message_to_client (ch, mmsg); } break; } break; } default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%p Dropping unknown message of type %u and size %u.\n", ch, type, size); } } /** * Incoming request fragment from multicast for a master. * * @param cls Master. * @param slave_key Sending slave's public key. * @param msg The message. * @param flags Request flags. */ static void request_cb (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, const struct GNUNET_MessageHeader *msg, enum GNUNET_MULTICAST_MessageFlags flags) { struct Master *mst = cls; struct Channel *ch = &mst->channel; uint16_t type = ntohs (msg->type); uint16_t size = ntohs (msg->size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Received request of type %u and size %u from multicast.\n", ch, type, size); switch (type) { case GNUNET_MESSAGE_TYPE_MULTICAST_REQUEST: { const struct GNUNET_MULTICAST_RequestHeader *req = (const struct GNUNET_MULTICAST_RequestHeader *) msg; /* FIXME: see message_cb() */ if (GNUNET_NO == GNUNET_PSYC_message_last_part (size - sizeof (*req), (const char *) &req[1])) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%p Dropping message with invalid parts " "received from multicast.\n", ch); GNUNET_break_op (0); break; } struct GNUNET_PSYC_MessageHeader *pmsg; uint16_t psize = sizeof (*pmsg) + size - sizeof (*req); pmsg = GNUNET_malloc (psize); pmsg->header.size = htons (psize); pmsg->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE); pmsg->message_id = req->request_id; pmsg->flags = htonl (GNUNET_PSYC_MESSAGE_REQUEST); memcpy (&pmsg[1], &req[1], size - sizeof (*req)); GNUNET_SERVER_notification_context_add (nc, ch->client); GNUNET_SERVER_notification_context_unicast (nc, ch->client, (const struct GNUNET_MessageHeader *) pmsg, GNUNET_NO); GNUNET_free (pmsg); break; } default: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Dropping unknown request of type %u and size %u.\n", ch, type, size); GNUNET_break_op (0); } } /** * Response from PSYCstore with the current counter values for a channel master. */ static void master_counters_cb (void *cls, int result, uint64_t max_fragment_id, uint64_t max_message_id, uint64_t max_group_generation, uint64_t max_state_message_id) { struct Master *mst = cls; struct Channel *ch = &mst->channel; struct CountersResult *res = GNUNET_malloc (sizeof (*res)); res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MASTER_START_ACK); res->header.size = htons (sizeof (*res)); res->result_code = htonl (result); res->max_message_id = GNUNET_htonll (max_message_id); if (GNUNET_OK == result || GNUNET_NO == result) { mst->max_message_id = max_message_id; mst->max_state_message_id = max_state_message_id; mst->max_group_generation = max_group_generation; mst->origin = GNUNET_MULTICAST_origin_start (cfg, &mst->priv_key, max_fragment_id + 1, join_cb, membership_test_cb, replay_fragment_cb, replay_message_cb, request_cb, message_cb, ch); ch->ready = GNUNET_YES; } GNUNET_SERVER_notification_context_add (nc, ch->client); GNUNET_SERVER_notification_context_unicast (nc, ch->client, &res->header, GNUNET_NO); GNUNET_free (res); } /** * Response from PSYCstore with the current counter values for a channel slave. */ void slave_counters_cb (void *cls, int result, uint64_t max_fragment_id, uint64_t max_message_id, uint64_t max_group_generation, uint64_t max_state_message_id) { struct Slave *slv = cls; struct Channel *ch = &slv->channel; struct CountersResult *res = GNUNET_malloc (sizeof (*res)); res->header.type = htons (GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN_ACK); res->header.size = htons (sizeof (*res)); res->result_code = htonl (result); res->max_message_id = GNUNET_htonll (max_message_id); if (GNUNET_OK == result || GNUNET_NO == result) { slv->max_message_id = max_message_id; slv->member = GNUNET_MULTICAST_member_join (cfg, &ch->pub_key, &slv->slave_key, &slv->origin, slv->relay_count, slv->relays, slv->join_req, join_cb, membership_test_cb, replay_fragment_cb, replay_message_cb, message_cb, ch); ch->ready = GNUNET_YES; } GNUNET_SERVER_notification_context_add (nc, ch->client); GNUNET_SERVER_notification_context_unicast (nc, ch->client, &res->header, GNUNET_NO); GNUNET_free (res); } /** * Handle a connecting client starting a channel master. */ static void handle_master_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct MasterStartRequest *req = (const struct MasterStartRequest *) msg; struct Master *mst = GNUNET_new (struct Master); struct Channel *ch = &mst->channel; ch->client = client; ch->is_master = GNUNET_YES; mst->policy = ntohl (req->policy); mst->priv_key = req->channel_key; GNUNET_CRYPTO_eddsa_key_get_public (&mst->priv_key, &ch->pub_key); GNUNET_CRYPTO_hash (&ch->pub_key, sizeof (ch->pub_key), &ch->pub_key_hash); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Master connected to channel %s.\n", mst, GNUNET_h2s (&ch->pub_key_hash)); GNUNET_PSYCSTORE_counters_get (store, &ch->pub_key, master_counters_cb, mst); GNUNET_SERVER_client_set_user_context (client, &mst->channel); GNUNET_CONTAINER_multihashmap_put (clients, &ch->pub_key_hash, mst, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle a connecting client joining as a channel slave. */ static void handle_slave_join (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { const struct SlaveJoinRequest *req = (const struct SlaveJoinRequest *) msg; struct Slave *slv = GNUNET_new (struct Slave); struct Channel *ch = &slv->channel; slv->channel.client = client; slv->channel.is_master = GNUNET_NO; slv->slave_key = req->slave_key; ch->pub_key = req->channel_key; GNUNET_CRYPTO_hash (&ch->pub_key, sizeof (ch->pub_key), &ch->pub_key_hash); slv->origin = req->origin; slv->relay_count = ntohl (req->relay_count); if (0 < slv->relay_count) { const struct GNUNET_PeerIdentity *relays = (const struct GNUNET_PeerIdentity *) &req[1]; slv->relays = GNUNET_malloc (slv->relay_count * sizeof (struct GNUNET_PeerIdentity)); uint32_t i; for (i = 0; i < slv->relay_count; i++) memcpy (&slv->relays[i], &relays[i], sizeof (*relays)); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Slave connected to channel %s.\n", slv, GNUNET_h2s (&ch->pub_key_hash)); GNUNET_PSYCSTORE_counters_get (store, &ch->pub_key, slave_counters_cb, slv); GNUNET_SERVER_client_set_user_context (client, &slv->channel); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Send acknowledgement to a client. * * Sent after a message fragment has been passed on to multicast. * * @param ch The channel struct for the client. */ static void send_message_ack (struct Channel *ch) { struct GNUNET_MessageHeader res; res.size = htons (sizeof (res)); res.type = htons (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_ACK); GNUNET_SERVER_notification_context_add (nc, ch->client); GNUNET_SERVER_notification_context_unicast (nc, ch->client, &res, GNUNET_NO); } /** * Callback for the transmit functions of multicast. */ static int transmit_notify (void *cls, size_t *data_size, void *data) { struct Channel *ch = cls; struct TransmitMessage *tmit_msg = ch->tmit_head; if (NULL == tmit_msg || *data_size < tmit_msg->size) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p transmit_notify: nothing to send.\n", ch); *data_size = 0; return GNUNET_NO; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p transmit_notify: sending %u bytes.\n", ch, tmit_msg->size); *data_size = tmit_msg->size; memcpy (data, tmit_msg->buf, *data_size); GNUNET_CONTAINER_DLL_remove (ch->tmit_head, ch->tmit_tail, tmit_msg); GNUNET_free (tmit_msg); int ret = (MSG_STATE_END < ch->tmit_state) ? GNUNET_NO : GNUNET_YES; send_message_ack (ch); if (0 == ch->tmit_task) { if (NULL != ch->tmit_head) { transmit_message (ch, GNUNET_NO); } else if (ch->disconnected) { /* FIXME: handle partial message (when still in_transmit) */ client_cleanup (ch); } } return ret; } /** * Callback for the transmit functions of multicast. */ static int master_transmit_notify (void *cls, size_t *data_size, void *data) { int ret = transmit_notify (cls, data_size, data); if (GNUNET_YES == ret) { struct Master *mst = cls; mst->tmit_handle = NULL; } return ret; } /** * Callback for the transmit functions of multicast. */ static int slave_transmit_notify (void *cls, size_t *data_size, void *data) { int ret = transmit_notify (cls, data_size, data); if (GNUNET_YES == ret) { struct Slave *slv = cls; slv->tmit_handle = NULL; } return ret; } /** * Transmit a message from a channel master to the multicast group. */ static void master_transmit_message (struct Master *mst, uint8_t inc_msg_id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p master_transmit_message()\n", mst); mst->channel.tmit_task = 0; if (NULL == mst->tmit_handle) { if (GNUNET_YES == inc_msg_id) mst->max_message_id++; mst->tmit_handle = GNUNET_MULTICAST_origin_to_all (mst->origin, mst->max_message_id, mst->max_group_generation, master_transmit_notify, mst); } else { GNUNET_MULTICAST_origin_to_all_resume (mst->tmit_handle); } } /** * Transmit a message from a channel slave to the multicast group. */ static void slave_transmit_message (struct Slave *slv, uint8_t inc_msg_id) { slv->channel.tmit_task = 0; if (NULL == slv->tmit_handle) { if (GNUNET_YES == inc_msg_id) slv->max_message_id++; slv->tmit_handle = GNUNET_MULTICAST_member_to_origin (slv->member, slv->max_request_id, slave_transmit_notify, slv); } else { GNUNET_MULTICAST_member_to_origin_resume (slv->tmit_handle); } } static inline void transmit_message (struct Channel *ch, uint8_t inc_msg_id) { ch->is_master ? master_transmit_message ((struct Master *) ch, inc_msg_id) : slave_transmit_message ((struct Slave *) ch, inc_msg_id); } static void transmit_error (struct Channel *ch) { struct GNUNET_MessageHeader *msg; struct TransmitMessage *tmit_msg = GNUNET_malloc (sizeof (*tmit_msg) + sizeof (*msg)); msg = (struct GNUNET_MessageHeader *) &tmit_msg[1]; msg->size = ntohs (sizeof (*msg)); msg->type = ntohs (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL); tmit_msg->buf = (char *) &tmit_msg[1]; tmit_msg->size = sizeof (*msg); tmit_msg->state = ch->tmit_state; GNUNET_CONTAINER_DLL_insert_tail (ch->tmit_head, ch->tmit_tail, tmit_msg); transmit_message (ch, GNUNET_NO); /* FIXME: cleanup */ } /** * Incoming message from a client. */ static void handle_psyc_message (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { struct Channel *ch = GNUNET_SERVER_client_get_user_context (client, struct Channel); GNUNET_assert (NULL != ch); if (GNUNET_YES != ch->ready) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%p Dropping message from client, channel is not ready yet.\n", ch); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } uint8_t inc_msg_id = GNUNET_NO; uint16_t size = ntohs (msg->size); uint16_t psize = 0, ptype = 0, pos = 0; if (GNUNET_MULTICAST_FRAGMENT_MAX_PAYLOAD < size - sizeof (*msg)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%p Message payload too large\n", ch); GNUNET_break (0); transmit_error (ch); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Received message from client.\n", ch); GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, msg); for (pos = 0; sizeof (*msg) + pos < size; pos += psize) { const struct GNUNET_MessageHeader *pmsg = (const struct GNUNET_MessageHeader *) ((char *) &msg[1] + pos); psize = ntohs (pmsg->size); ptype = ntohs (pmsg->type); if (psize < sizeof (*pmsg) || sizeof (*msg) + pos + psize > size) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%p Received invalid message part of type %u and size %u " "from client.\n", ch, ptype, psize); GNUNET_break (0); transmit_error (ch); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%p Received message part from client.\n", ch); GNUNET_PSYC_log_message (GNUNET_ERROR_TYPE_DEBUG, pmsg); if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype) inc_msg_id = GNUNET_YES; } size -= sizeof (*msg); struct TransmitMessage *tmit_msg = GNUNET_malloc (sizeof (*tmit_msg) + size); tmit_msg->buf = (char *) &tmit_msg[1]; memcpy (tmit_msg->buf, &msg[1], size); tmit_msg->size = size; tmit_msg->state = ch->tmit_state; GNUNET_CONTAINER_DLL_insert_tail (ch->tmit_head, ch->tmit_tail, tmit_msg); transmit_message (ch, inc_msg_id); GNUNET_SERVER_receive_done (client, GNUNET_OK); }; /** * Client requests to add a slave to the membership database. */ static void handle_slave_add (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Client requests to remove a slave from the membership database. */ static void handle_slave_remove (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Client requests channel history from PSYCstore. */ static void handle_story_request (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Client requests best matching state variable from PSYCstore. */ static void handle_state_get (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Client requests state variables with a given prefix from PSYCstore. */ static void handle_state_get_prefix (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *msg) { } /** * Initialize the PSYC service. * * @param cls Closure. * @param server The initialized server. * @param c Configuration to use. */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { { &handle_master_start, NULL, GNUNET_MESSAGE_TYPE_PSYC_MASTER_START, 0 }, { &handle_slave_join, NULL, GNUNET_MESSAGE_TYPE_PSYC_SLAVE_JOIN, 0 }, { &handle_psyc_message, NULL, GNUNET_MESSAGE_TYPE_PSYC_MESSAGE, 0 }, { &handle_slave_add, NULL, GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_ADD, 0 }, { &handle_slave_remove, NULL, GNUNET_MESSAGE_TYPE_PSYC_CHANNEL_SLAVE_RM, 0 }, { &handle_story_request, NULL, GNUNET_MESSAGE_TYPE_PSYC_STORY_REQUEST, 0 }, { &handle_state_get, NULL, GNUNET_MESSAGE_TYPE_PSYC_STATE_GET, 0 }, { &handle_state_get_prefix, NULL, GNUNET_MESSAGE_TYPE_PSYC_STATE_GET_PREFIX, 0 } }; cfg = c; store = GNUNET_PSYCSTORE_connect (cfg); stats = GNUNET_STATISTICS_create ("psyc", cfg); clients = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); recv_cache = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_YES); nc = GNUNET_SERVER_notification_context_create (server, 1); GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); } /** * The main function for the service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "psyc", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1; } /* end of gnunet-service-psycstore.c */ gnunet-0.10.1/src/psyc/psyc.conf.in0000644000175000017500000000030712251306467014017 00000000000000[psyc] AUTOSTART = @AUTOSTART@ BINARY = gnunet-service-psyc UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-psyc.sock UNIX_MATCH_UID = NO UNIX_MATCH_GID = YES @UNIXONLY@PORT = 2115 HOSTNAME = localhostgnunet-0.10.1/src/psyc/test_psyc.c0000644000175000017500000003551212310570720013743 00000000000000/* * This file is part of GNUnet * (C) 2013 Christian Grothoff (and other contributing authors) * * GNUnet is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 3, or (at your * option) any later version. * * GNUnet is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNUnet; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /** * @file psyc/test_psyc.c * @brief Test for the PSYC service. * @author Gabor X Toth * @author Christian Grothoff */ #include #include "platform.h" #include "gnunet_crypto_lib.h" #include "gnunet_common.h" #include "gnunet_util_lib.h" #include "gnunet_testing_lib.h" #include "gnunet_env_lib.h" #include "gnunet_psyc_service.h" #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) #define DEBUG_SERVICE 1 /** * Return value from 'main'. */ static int res; static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Handle for task for timeout termination. */ static GNUNET_SCHEDULER_TaskIdentifier end_badly_task; static struct GNUNET_PSYC_Master *mst; static struct GNUNET_PSYC_Slave *slv; static struct GNUNET_PSYC_Channel *ch; static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key; static struct GNUNET_CRYPTO_EddsaPrivateKey *slave_key; static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key; static struct GNUNET_CRYPTO_EddsaPublicKey slave_pub_key; struct GNUNET_PSYC_MasterTransmitHandle *mth; struct TransmitClosure { struct GNUNET_PSYC_MasterTransmitHandle *mst_tmit; struct GNUNET_PSYC_SlaveTransmitHandle *slv_tmit; struct GNUNET_ENV_Environment *env; char *data[16]; const char *mod_value; size_t mod_value_size; uint8_t data_delay[16]; uint8_t data_count; uint8_t paused; uint8_t n; }; struct TransmitClosure *tmit; enum { TEST_NONE, TEST_SLAVE_TRANSMIT, TEST_MASTER_TRANSMIT, } test; static void master_transmit (); /** * Clean up all resources used. */ static void cleanup () { if (NULL != slv) { GNUNET_PSYC_slave_part (slv); slv = NULL; } if (NULL != mst) { GNUNET_PSYC_master_stop (mst); mst = NULL; } if (NULL != tmit) { GNUNET_ENV_environment_destroy (tmit->env); GNUNET_free (tmit); tmit = NULL; } GNUNET_SCHEDULER_shutdown (); } /** * Terminate the testcase (failure). * * @param cls NULL * @param tc scheduler context */ static void end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { res = 1; cleanup (); } /** * Terminate the testcase (success). * * @param cls NULL * @param tc scheduler context */ static void end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { res = 0; cleanup (); } /** * Finish the testcase (successfully). */ static void end () { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n"); if (end_badly_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (end_badly_task); end_badly_task = GNUNET_SCHEDULER_NO_TASK; } GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &end_normally, NULL); } static void master_message (void *cls, uint64_t message_id, uint32_t flags, const struct GNUNET_MessageHeader *msg) { if (NULL == msg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error while receiving message %llu\n", message_id); return; } uint16_t type = ntohs (msg->type); uint16_t size = ntohs (msg->size); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Master got message part of type %u and size %u " "belonging to message ID %llu with flags %u\n", type, size, message_id, flags); switch (test) { case TEST_SLAVE_TRANSMIT: if (GNUNET_PSYC_MESSAGE_REQUEST != flags) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unexpected request flags: %lu\n", flags); GNUNET_assert (0); return; } // FIXME: check rest of message if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END == type) master_transmit (); break; case TEST_MASTER_TRANSMIT: break; default: GNUNET_assert (0); } } static void slave_message (void *cls, uint64_t message_id, uint32_t flags, const struct GNUNET_MessageHeader *msg) { if (NULL == msg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error while receiving message %llu\n", message_id); return; } uint16_t type = ntohs (msg->type); uint16_t size = ntohs (msg->size); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Slave got message part of type %u and size %u " "belonging to message ID %llu with flags %u\n", type, size, message_id, flags); switch (test) { case TEST_MASTER_TRANSMIT: if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END == type) end (); break; default: GNUNET_assert (0); } } static void join_request (void *cls, const struct GNUNET_CRYPTO_EddsaPublicKey *slave_key, const char *method_name, size_t variable_count, const struct GNUNET_ENV_Modifier *variables, const void *data, size_t data_size, struct GNUNET_PSYC_JoinHandle *jh) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Got join request: %s (%zu vars)", method_name, variable_count); GNUNET_PSYC_join_decision (jh, GNUNET_YES, 0, NULL, "_notice_join", NULL, "you're in", 9); } static void transmit_resume (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n"); struct TransmitClosure *tmit = cls; if (NULL != tmit->mst_tmit) GNUNET_PSYC_master_transmit_resume (tmit->mst_tmit); else GNUNET_PSYC_slave_transmit_resume (tmit->slv_tmit); } static int tmit_notify_mod (void *cls, uint16_t *data_size, void *data, uint8_t *oper, uint32_t *full_value_size) { struct TransmitClosure *tmit = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmit notify modifier: %lu bytes available, " "%u modifiers left to process.\n", *data_size, GNUNET_ENV_environment_get_count (tmit->env)); enum GNUNET_ENV_Operator op = 0; const char *name = NULL; const char *value = NULL; uint16_t name_size = 0; size_t value_size = 0; if (NULL != oper) { /* New modifier */ if (GNUNET_NO == GNUNET_ENV_environment_shift (tmit->env, &op, &name, (void *) &value, &value_size)) { /* No more modifiers, continue with data */ *data_size = 0; return GNUNET_YES; } GNUNET_assert (value_size < UINT32_MAX); *full_value_size = value_size; *oper = op; name_size = strlen (name); if (name_size + 1 + value_size <= *data_size) { *data_size = name_size + 1 + value_size; } else { tmit->mod_value_size = value_size; value_size = *data_size - name_size - 1; tmit->mod_value_size -= value_size; tmit->mod_value = value + value_size; } memcpy (data, name, name_size); ((char *)data)[name_size] = '\0'; memcpy ((char *)data + name_size + 1, value, value_size); } else if (NULL != tmit->mod_value && 0 < tmit->mod_value_size) { /* Modifier continuation */ value = tmit->mod_value; if (tmit->mod_value_size <= *data_size) { value_size = tmit->mod_value_size; tmit->mod_value = NULL; } else { value_size = *data_size; tmit->mod_value += value_size; } tmit->mod_value_size -= value_size; if (*data_size < value_size) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "value larger than buffer: %u < %zu\n", *data_size, value_size); *data_size = 0; return GNUNET_NO; } *data_size = value_size; memcpy (data, value, value_size); } return 0 == tmit->mod_value_size ? GNUNET_YES : GNUNET_NO; } static int tmit_notify_data (void *cls, uint16_t *data_size, void *data) { struct TransmitClosure *tmit = cls; if (0 == tmit->data_count) { *data_size = 0; return GNUNET_YES; } uint16_t size = strlen (tmit->data[tmit->n]); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmit notify data: %u bytes available, " "processing fragment %u/%u (size %u).\n", *data_size, tmit->n + 1, tmit->data_count, size); if (*data_size < size) { *data_size = 0; GNUNET_assert (0); return GNUNET_SYSERR; } if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n]) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n"); tmit->paused = GNUNET_YES; GNUNET_SCHEDULER_add_delayed ( GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, tmit->data_delay[tmit->n]), &transmit_resume, tmit); *data_size = 0; return GNUNET_NO; } tmit->paused = GNUNET_NO; *data_size = size; memcpy (data, tmit->data[tmit->n], size); return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES; } static void slave_joined (void *cls, uint64_t max_message_id) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Slave joined: %lu\n", max_message_id); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Slave sending request to master.\n"); test = TEST_SLAVE_TRANSMIT; tmit = GNUNET_new (struct TransmitClosure); tmit->env = GNUNET_ENV_environment_create (); GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, "_abc", "abc def", 7); GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, "_abc_def", "abc def ghi", 11); tmit->n = 0; tmit->data[0] = "slave test"; tmit->data_count = 1; tmit->slv_tmit = GNUNET_PSYC_slave_transmit (slv, "_request_test", tmit_notify_mod, tmit_notify_data, tmit, GNUNET_PSYC_SLAVE_TRANSMIT_NONE); } static void slave_join () { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Joining slave.\n"); struct GNUNET_PeerIdentity origin; struct GNUNET_PeerIdentity relays[16]; struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create (); GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN, "_foo", "bar baz", 7); GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_ASSIGN, "_foo_bar", "foo bar baz", 11); slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key, &origin, 16, relays, &slave_message, &join_request, &slave_joined, NULL, "_request_join", env, "some data", 9); GNUNET_ENV_environment_destroy (env); } static void master_transmit () { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Master sending message to all.\n"); test = TEST_MASTER_TRANSMIT; uint32_t i, j; char *name_max = "_test_max"; uint8_t name_max_size = sizeof ("_test_max"); char *val_max = GNUNET_malloc (GNUNET_PSYC_MODIFIER_MAX_PAYLOAD); for (i = 0; i < GNUNET_PSYC_MODIFIER_MAX_PAYLOAD; i++) val_max[i] = (0 == i % 10000) ? '0' + i / 10000 : '.'; char *name_cont = "_test_cont"; uint8_t name_cont_size = sizeof ("_test_cont"); char *val_cont = GNUNET_malloc (GNUNET_PSYC_MODIFIER_MAX_PAYLOAD + GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD); for (i = 0; i < GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_cont_size; i++) val_cont[i] = (0 == i % 10000) ? '0' + i / 10000 : ':'; for (j = 0; j < GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD; j++, i++) val_cont[i] = (0 == j % 10000) ? '0' + j / 10000 : '!'; tmit = GNUNET_new (struct TransmitClosure); tmit->env = GNUNET_ENV_environment_create (); GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, "_foo", "bar baz", 7); GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, name_max, val_max, GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_max_size); GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, "_foo_bar", "foo bar baz", 11); GNUNET_ENV_environment_add (tmit->env, GNUNET_ENV_OP_ASSIGN, name_cont, val_cont, GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_cont_size + GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD); tmit->data[0] = "foo"; tmit->data[1] = GNUNET_malloc (GNUNET_PSYC_DATA_MAX_PAYLOAD + 1); for (i = 0; i < GNUNET_PSYC_DATA_MAX_PAYLOAD; i++) tmit->data[1][i] = (0 == i % 10000) ? '0' + i / 10000 : '_'; tmit->data[2] = "foo bar"; tmit->data[3] = "foo bar baz"; tmit->data_delay[1] = 3; tmit->data_count = 4; tmit->mst_tmit = GNUNET_PSYC_master_transmit (mst, "_notice_test", tmit_notify_mod, tmit_notify_data, tmit, GNUNET_PSYC_MASTER_TRANSMIT_INC_GROUP_GEN); } static void master_started (void *cls, uint64_t max_message_id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Master started: %" PRIu64 "\n", max_message_id); slave_join (); } /** * Main function of the test, run from scheduler. * * @param cls NULL * @param cfg configuration we use (also to connect to PSYC service) * @param peer handle to access more of the peer (not used) */ static void #if DEBUG_SERVICE run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) #else run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_TESTING_Peer *peer) #endif { cfg = c; end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL); channel_key = GNUNET_CRYPTO_eddsa_key_create (); slave_key = GNUNET_CRYPTO_eddsa_key_create (); GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key); GNUNET_CRYPTO_eddsa_key_get_public (slave_key, &slave_pub_key); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting master.\n"); mst = GNUNET_PSYC_master_start (cfg, channel_key, GNUNET_PSYC_CHANNEL_PRIVATE, &master_message, &join_request, &master_started, NULL); } int main (int argc, char *argv[]) { res = 1; #if DEBUG_SERVICE const struct GNUNET_GETOPT_CommandLineOption opts[] = { GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psyc", "test-psyc [options]", opts, &run, NULL)) return 1; #else if (0 != GNUNET_TESTING_peer_run ("test-psyc", "test_psyc.conf", &run, NULL)) return 1; #endif return res; } /* end of test_psyc.c */ gnunet-0.10.1/src/dns/0000755000175000017500000000000012320755626011455 500000000000000gnunet-0.10.1/src/dns/dns_api.c0000644000175000017500000003141312255010512013141 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dns/dns_api.c * @brief API to access the DNS service. * @author Christian Grothoff */ #include "platform.h" #include "gnunet_dns_service.h" #include "dns.h" /** * Reply to send to service. */ struct ReplyQueueEntry { /** * Kept in DLL. */ struct ReplyQueueEntry *next; /** * Kept in DLL. */ struct ReplyQueueEntry *prev; /** * Message to transmit, allocated at the end of this struct. */ const struct GNUNET_MessageHeader *msg; }; /** * Handle to identify an individual DNS request. */ struct GNUNET_DNS_RequestHandle { /** * Handle to DNS API. */ struct GNUNET_DNS_Handle *dh; /** * Stored in network byte order (as for us, it is just a random number). */ uint64_t request_id; /** * Re-connect counter, to make sure we did not reconnect in the meantime. */ uint32_t generation; }; /** * DNS handle */ struct GNUNET_DNS_Handle { /** * Connection to DNS service, or NULL. */ struct GNUNET_CLIENT_Connection *dns_connection; /** * Handle to active transmission request, or NULL. */ struct GNUNET_CLIENT_TransmitHandle *dns_transmit_handle; /** * Configuration to use. */ const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Function to call to get replies. */ GNUNET_DNS_RequestHandler rh; /** * Closure for 'rh'. */ void *rh_cls; /** * Head of replies to transmit. */ struct ReplyQueueEntry *rq_head; /** * Tail of replies to transmit. */ struct ReplyQueueEntry *rq_tail; /** * Task to reconnect to the service. */ GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** * Re-connect counter, to make sure we did not reconnect in the meantime. */ uint32_t generation; /** * Flags for events we care about. */ enum GNUNET_DNS_Flags flags; /** * Did we start the receive loop yet? */ int in_receive; /** * Number of GNUNET_DNS_RequestHandles we have outstanding. Must be 0 before * we can be disconnected. */ unsigned int pending_requests; }; /** * Add the given reply to our transmission queue and trigger sending if needed. * * @param dh handle with the connection * @param qe reply to queue */ static void queue_reply (struct GNUNET_DNS_Handle *dh, struct ReplyQueueEntry *qe); /** * Reconnect to the DNS service. * * @param cls handle with the connection to connect * @param tc scheduler context (unused) */ static void reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DNS_Handle *dh = cls; struct ReplyQueueEntry *qe; struct GNUNET_DNS_Register *msg; dh->reconnect_task = GNUNET_SCHEDULER_NO_TASK; dh->dns_connection = GNUNET_CLIENT_connect ("dns", dh->cfg); if (NULL == dh->dns_connection) return; dh->generation++; qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) + sizeof (struct GNUNET_DNS_Register)); msg = (struct GNUNET_DNS_Register*) &qe[1]; qe->msg = &msg->header; msg->header.size = htons (sizeof (struct GNUNET_DNS_Register)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT); msg->flags = htonl (dh->flags); queue_reply (dh, qe); } /** * Disconnect from the DNS service. * * @param dh handle with the connection to disconnect */ static void disconnect (struct GNUNET_DNS_Handle *dh) { struct ReplyQueueEntry *qe; if (NULL != dh->dns_transmit_handle) { GNUNET_CLIENT_notify_transmit_ready_cancel (dh->dns_transmit_handle); dh->dns_transmit_handle = NULL; } if (NULL != dh->dns_connection) { GNUNET_CLIENT_disconnect (dh->dns_connection); dh->dns_connection = NULL; } while (NULL != (qe = dh->rq_head)) { GNUNET_CONTAINER_DLL_remove (dh->rq_head, dh->rq_tail, qe); GNUNET_free (qe); } dh->in_receive = GNUNET_NO; } /** * This receives packets from the DNS service and calls the application to * handle it. * * @param cls the struct GNUNET_DNS_Handle * @param msg message from the service (request) */ static void request_handler (void *cls, const struct GNUNET_MessageHeader *msg) { struct GNUNET_DNS_Handle *dh = cls; const struct GNUNET_DNS_Request *req; struct GNUNET_DNS_RequestHandle *rh; size_t payload_length; /* the service disconnected, reconnect after short wait */ if (msg == NULL) { disconnect (dh); dh->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect, dh); return; } if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST) || (ntohs (msg->size) < sizeof (struct GNUNET_DNS_Request)) ) { /* the service did something strange, reconnect immediately */ GNUNET_break (0); disconnect (dh); dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh); return; } req = (const struct GNUNET_DNS_Request *) msg; GNUNET_break (ntohl (req->reserved) == 0); payload_length = ntohs (req->header.size) - sizeof (struct GNUNET_DNS_Request); GNUNET_CLIENT_receive (dh->dns_connection, &request_handler, dh, GNUNET_TIME_UNIT_FOREVER_REL); /* finally, pass request to callback for answers */ rh = GNUNET_new (struct GNUNET_DNS_RequestHandle); rh->dh =dh; rh->request_id = req->request_id; rh->generation = dh->generation; dh->pending_requests++; dh->rh (dh->rh_cls, rh, payload_length, (const char*) &req[1]); } /** * Callback called by notify_transmit_ready; sends DNS replies * to the DNS service. * * @param cls the struct GNUNET_DNS_Handle * @param size number of bytes available in buf * @param buf where to copy the message for transmission * @return number of bytes copied to buf */ static size_t send_response (void *cls, size_t size, void *buf) { struct GNUNET_DNS_Handle *dh = cls; struct ReplyQueueEntry *qe; size_t len; dh->dns_transmit_handle = NULL; if (NULL == buf) { disconnect (dh); dh->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect, dh); return 0; } qe = dh->rq_head; if (NULL == qe) return 0; len = ntohs (qe->msg->size); if (len > size) { dh->dns_transmit_handle = GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection, len, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_response, dh); return 0; } memcpy (buf, qe->msg, len); GNUNET_CONTAINER_DLL_remove (dh->rq_head, dh->rq_tail, qe); GNUNET_free (qe); if (GNUNET_NO == dh->in_receive) { dh->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (dh->dns_connection, &request_handler, dh, GNUNET_TIME_UNIT_FOREVER_REL); } if (NULL != (qe = dh->rq_head)) { dh->dns_transmit_handle = GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection, ntohs (qe->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_response, dh); } return len; } /** * Add the given reply to our transmission queue and trigger sending if needed. * * @param dh handle with the connection * @param qe reply to queue */ static void queue_reply (struct GNUNET_DNS_Handle *dh, struct ReplyQueueEntry *qe) { if (NULL == dh->dns_connection) { GNUNET_free (qe); return; } GNUNET_CONTAINER_DLL_insert_tail (dh->rq_head, dh->rq_tail, qe); if (NULL != dh->dns_transmit_handle) return; /* trigger sending */ dh->dns_transmit_handle = GNUNET_CLIENT_notify_transmit_ready (dh->dns_connection, ntohs (dh->rq_head->msg->size), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_NO, &send_response, dh); } /** * If a GNUNET_DNS_RequestHandler calls this function, the request is * given to other clients or the global DNS for resolution. Once a * global response has been obtained, the request handler is AGAIN * called to give it a chance to observe and modify the response after * the "normal" resolution. It is not legal for the request handler * to call this function if a response is already present. * * @param rh request that should now be forwarded */ void GNUNET_DNS_request_forward (struct GNUNET_DNS_RequestHandle *rh) { struct ReplyQueueEntry *qe; struct GNUNET_DNS_Response *resp; GNUNET_assert (0 < rh->dh->pending_requests--); if (rh->generation != rh->dh->generation) { GNUNET_free (rh); return; } qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) + sizeof (struct GNUNET_DNS_Response)); resp = (struct GNUNET_DNS_Response*) &qe[1]; qe->msg = &resp->header; resp->header.size = htons (sizeof (struct GNUNET_DNS_Response)); resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE); resp->drop_flag = htonl (1); resp->request_id = rh->request_id; queue_reply (rh->dh, qe); GNUNET_free (rh); } /** * If a GNUNET_DNS_RequestHandler calls this function, the request is * to be dropped and no response should be generated. * * @param rh request that should now be dropped */ void GNUNET_DNS_request_drop (struct GNUNET_DNS_RequestHandle *rh) { struct ReplyQueueEntry *qe; struct GNUNET_DNS_Response *resp; GNUNET_assert (0 < rh->dh->pending_requests--); if (rh->generation != rh->dh->generation) { GNUNET_free (rh); return; } qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) + sizeof (struct GNUNET_DNS_Response)); resp = (struct GNUNET_DNS_Response*) &qe[1]; qe->msg = &resp->header; resp->header.size = htons (sizeof (struct GNUNET_DNS_Response)); resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE); resp->request_id = rh->request_id; resp->drop_flag = htonl (0); queue_reply (rh->dh, qe); GNUNET_free (rh); } /** * If a GNUNET_DNS_RequestHandler calls this function, the request is * supposed to be answered with the data provided to this call (with * the modifications the function might have made). * * @param rh request that should now be answered * @param reply_length size of reply (uint16_t to force sane size) * @param reply reply data */ void GNUNET_DNS_request_answer (struct GNUNET_DNS_RequestHandle *rh, uint16_t reply_length, const char *reply) { struct ReplyQueueEntry *qe; struct GNUNET_DNS_Response *resp; GNUNET_assert (0 < rh->dh->pending_requests--); if (rh->generation != rh->dh->generation) { GNUNET_free (rh); return; } if (reply_length + sizeof (struct GNUNET_DNS_Response) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); GNUNET_free (rh); return; } qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) + sizeof (struct GNUNET_DNS_Response) + reply_length); resp = (struct GNUNET_DNS_Response*) &qe[1]; qe->msg = &resp->header; resp->header.size = htons (sizeof (struct GNUNET_DNS_Response) + reply_length); resp->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE); resp->drop_flag = htonl (2); resp->request_id = rh->request_id; memcpy (&resp[1], reply, reply_length); queue_reply (rh->dh, qe); GNUNET_free (rh); } /** * Connect to the service-dns * * @param cfg configuration to use * @param flags when to call rh * @param rh function to call with DNS requests * @param rh_cls closure to pass to rh * @return DNS handle */ struct GNUNET_DNS_Handle * GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, enum GNUNET_DNS_Flags flags, GNUNET_DNS_RequestHandler rh, void *rh_cls) { struct GNUNET_DNS_Handle *dh; dh = GNUNET_new (struct GNUNET_DNS_Handle); dh->cfg = cfg; dh->flags = flags; dh->rh = rh; dh->rh_cls = rh_cls; dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh); return dh; } /** * Disconnect from the DNS service. * * @param dh DNS handle */ void GNUNET_DNS_disconnect (struct GNUNET_DNS_Handle *dh) { if (GNUNET_SCHEDULER_NO_TASK != dh->reconnect_task) { GNUNET_SCHEDULER_cancel (dh->reconnect_task); dh->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } disconnect (dh); /* make sure client has no pending requests left over! */ GNUNET_assert (0 == dh->pending_requests); GNUNET_free (dh); } /* end of dns_api_new.c */ gnunet-0.10.1/src/dns/dnsparser.c0000644000175000017500000010541012250434324013532 00000000000000/* This file is part of GNUnet (C) 2010-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dns/dnsparser.c * @brief helper library to parse DNS packets. * @author Philipp Toelke * @author Christian Grothoff */ #include "platform.h" #include #if WINDOWS #include #endif #include "gnunet_util_lib.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_tun_lib.h" /** * Check if a label in UTF-8 format can be coded into valid IDNA. * This can fail if the ASCII-conversion becomes longer than 63 characters. * * @param label label to check (UTF-8 string) * @return #GNUNET_OK if the label can be converted to IDNA, * #GNUNET_SYSERR if the label is not valid for DNS names */ int GNUNET_DNSPARSER_check_label (const char *label) { char *output; size_t slen; if (NULL != strchr (label, '.')) return GNUNET_SYSERR; /* not a label! Did you mean GNUNET_DNSPARSER_check_name? */ if (IDNA_SUCCESS != idna_to_ascii_8z (label, &output, IDNA_ALLOW_UNASSIGNED)) return GNUNET_SYSERR; slen = strlen (output); #if WINDOWS idn_free (output); #else free (output); #endif return (slen > 63) ? GNUNET_SYSERR : GNUNET_OK; } /** * Check if a label in UTF-8 format can be coded into valid IDNA. * This can fail if the ASCII-conversion becomes longer than 253 characters. * * @param name name to check (UTF-8 string) * @return #GNUNET_OK if the label can be converted to IDNA, * #GNUNET_SYSERR if the label is not valid for DNS names */ int GNUNET_DNSPARSER_check_name (const char *name) { char *ldup; char *output; size_t slen; char *tok; ldup = GNUNET_strdup (name); for (tok = strtok (ldup, "."); NULL != tok; tok = strtok (NULL, ".")) if (GNUNET_OK != GNUNET_DNSPARSER_check_label (tok)) { GNUNET_free (ldup); return GNUNET_SYSERR; } GNUNET_free (ldup); if (IDNA_SUCCESS != idna_to_ascii_8z (name, &output, IDNA_ALLOW_UNASSIGNED)) return GNUNET_SYSERR; slen = strlen (output); #if WINDOWS idn_free (output); #else free (output); #endif return (slen > 253) ? GNUNET_SYSERR : GNUNET_OK; } /** * Free SOA information record. * * @param soa record to free */ void GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa) { if (NULL == soa) return; GNUNET_free_non_null (soa->mname); GNUNET_free_non_null (soa->rname); GNUNET_free (soa); } /** * Free CERT information record. * * @param cert record to free */ void GNUNET_DNSPARSER_free_cert (struct GNUNET_DNSPARSER_CertRecord *cert) { if (NULL == cert) return; GNUNET_free_non_null (cert->certificate_data); GNUNET_free (cert); } /** * Free SRV information record. * * @param srv record to free */ void GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv) { if (NULL == srv) return; GNUNET_free_non_null (srv->target); GNUNET_free_non_null (srv->domain_name); GNUNET_free_non_null (srv->proto); GNUNET_free_non_null (srv->service); GNUNET_free (srv); } /** * Free MX information record. * * @param mx record to free */ void GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx) { if (NULL == mx) return; GNUNET_free_non_null (mx->mxhost); GNUNET_free (mx); } /** * Free the given DNS record. * * @param r record to free */ void GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r) { GNUNET_free_non_null (r->name); switch (r->type) { case GNUNET_DNSPARSER_TYPE_MX: GNUNET_DNSPARSER_free_mx (r->data.mx); break; case GNUNET_DNSPARSER_TYPE_SOA: GNUNET_DNSPARSER_free_soa (r->data.soa); break; case GNUNET_DNSPARSER_TYPE_SRV: GNUNET_DNSPARSER_free_srv (r->data.srv); break; case GNUNET_DNSPARSER_TYPE_CERT: GNUNET_DNSPARSER_free_cert (r->data.cert); break; case GNUNET_DNSPARSER_TYPE_NS: case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: GNUNET_free_non_null (r->data.hostname); break; default: GNUNET_free_non_null (r->data.raw.data); break; } } /** * Parse name inside of a DNS query or record. * * @param udp_payload entire UDP payload * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the name to parse in the udp_payload (to be * incremented by the size of the name) * @param depth current depth of our recursion (to prevent stack overflow) * @return name as 0-terminated C string on success, NULL if the payload is malformed */ static char * parse_name (const char *udp_payload, size_t udp_payload_length, size_t *off, unsigned int depth) { const uint8_t *input = (const uint8_t *) udp_payload; char *ret; char *tmp; char *xstr; uint8_t len; size_t xoff; char *utf8; Idna_rc rc; ret = GNUNET_strdup (""); while (1) { if (*off >= udp_payload_length) { GNUNET_break_op (0); goto error; } len = input[*off]; if (0 == len) { (*off)++; break; } if (len < 64) { if (*off + 1 + len > udp_payload_length) { GNUNET_break_op (0); goto error; } GNUNET_asprintf (&tmp, "%.*s", (int) len, &udp_payload[*off + 1]); if (IDNA_SUCCESS != (rc = idna_to_unicode_8z8z (tmp, &utf8, IDNA_ALLOW_UNASSIGNED))) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Failed to convert DNS IDNA name `%s' to UTF-8: %s\n"), tmp, idna_strerror (rc)); GNUNET_free (tmp); GNUNET_asprintf (&tmp, "%s%.*s.", ret, (int) len, &udp_payload[*off + 1]); } else { GNUNET_free (tmp); GNUNET_asprintf (&tmp, "%s%s.", ret, utf8); #if WINDOWS idn_free (utf8); #else free (utf8); #endif } GNUNET_free (ret); ret = tmp; *off += 1 + len; } else if ((64 | 128) == (len & (64 | 128)) ) { if (depth > 32) { GNUNET_break_op (0); goto error; /* hard bound on stack to prevent "infinite" recursion, disallow! */ } /* pointer to string */ if (*off + 1 > udp_payload_length) { GNUNET_break_op (0); goto error; } xoff = ((len - (64 | 128)) << 8) + input[*off+1]; xstr = parse_name (udp_payload, udp_payload_length, &xoff, depth + 1); if (NULL == xstr) { GNUNET_break_op (0); goto error; } GNUNET_asprintf (&tmp, "%s%s.", ret, xstr); GNUNET_free (ret); GNUNET_free (xstr); ret = tmp; if (strlen (ret) > udp_payload_length) { GNUNET_break_op (0); goto error; /* we are looping (building an infinite string) */ } *off += 2; /* pointers always terminate names */ break; } else { /* neither pointer nor inline string, not supported... */ GNUNET_break_op (0); goto error; } } if (0 < strlen(ret)) ret[strlen(ret)-1] = '\0'; /* eat tailing '.' */ return ret; error: GNUNET_break_op (0); GNUNET_free (ret); return NULL; } /** * Parse name inside of a DNS query or record. * * @param udp_payload entire UDP payload * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the name to parse in the udp_payload (to be * incremented by the size of the name) * @return name as 0-terminated C string on success, NULL if the payload is malformed */ char * GNUNET_DNSPARSER_parse_name (const char *udp_payload, size_t udp_payload_length, size_t *off) { return parse_name (udp_payload, udp_payload_length, off, 0); } /** * Parse a DNS query entry. * * @param udp_payload entire UDP payload * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the udp_payload (to be * incremented by the size of the query) * @param q where to write the query information * @return #GNUNET_OK on success, #GNUNET_SYSERR if the query is malformed */ int GNUNET_DNSPARSER_parse_query (const char *udp_payload, size_t udp_payload_length, size_t *off, struct GNUNET_DNSPARSER_Query *q) { char *name; struct GNUNET_TUN_DnsQueryLine ql; name = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); if (NULL == name) { GNUNET_break_op (0); return GNUNET_SYSERR; } q->name = name; if (*off + sizeof (struct GNUNET_TUN_DnsQueryLine) > udp_payload_length) { GNUNET_break_op (0); return GNUNET_SYSERR; } memcpy (&ql, &udp_payload[*off], sizeof (ql)); *off += sizeof (ql); q->type = ntohs (ql.type); q->dns_traffic_class = ntohs (ql.dns_traffic_class); return GNUNET_OK; } /** * Parse a DNS SOA record. * * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the SOA record (to be * incremented by the size of the record), unchanged on error * @return the parsed SOA record, NULL on error */ struct GNUNET_DNSPARSER_SoaRecord * GNUNET_DNSPARSER_parse_soa (const char *udp_payload, size_t udp_payload_length, size_t *off) { struct GNUNET_DNSPARSER_SoaRecord *soa; struct GNUNET_TUN_DnsSoaRecord soa_bin; size_t old_off; old_off = *off; soa = GNUNET_new (struct GNUNET_DNSPARSER_SoaRecord); soa->mname = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); soa->rname = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); if ( (NULL == soa->mname) || (NULL == soa->rname) || (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > udp_payload_length) ) { GNUNET_break_op (0); GNUNET_DNSPARSER_free_soa (soa); *off = old_off; return NULL; } memcpy (&soa_bin, &udp_payload[*off], sizeof (struct GNUNET_TUN_DnsSoaRecord)); soa->serial = ntohl (soa_bin.serial); soa->refresh = ntohl (soa_bin.refresh); soa->retry = ntohl (soa_bin.retry); soa->expire = ntohl (soa_bin.expire); soa->minimum_ttl = ntohl (soa_bin.minimum); (*off) += sizeof (struct GNUNET_TUN_DnsSoaRecord); return soa; } /** * Parse a DNS MX record. * * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the MX record (to be * incremented by the size of the record), unchanged on error * @return the parsed MX record, NULL on error */ struct GNUNET_DNSPARSER_MxRecord * GNUNET_DNSPARSER_parse_mx (const char *udp_payload, size_t udp_payload_length, size_t *off) { struct GNUNET_DNSPARSER_MxRecord *mx; uint16_t mxpref; size_t old_off; old_off = *off; if (*off + sizeof (uint16_t) > udp_payload_length) { GNUNET_break_op (0); return NULL; } memcpy (&mxpref, &udp_payload[*off], sizeof (uint16_t)); (*off) += sizeof (uint16_t); mx = GNUNET_new (struct GNUNET_DNSPARSER_MxRecord); mx->preference = ntohs (mxpref); mx->mxhost = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); if (NULL == mx->mxhost) { GNUNET_break_op (0); GNUNET_DNSPARSER_free_mx (mx); *off = old_off; return NULL; } return mx; } /** * Parse a DNS SRV record. * * @param r_name name of the SRV record * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the SRV record (to be * incremented by the size of the record), unchanged on error * @return the parsed SRV record, NULL on error */ struct GNUNET_DNSPARSER_SrvRecord * GNUNET_DNSPARSER_parse_srv (const char *r_name, const char *udp_payload, size_t udp_payload_length, size_t *off) { struct GNUNET_DNSPARSER_SrvRecord *srv; struct GNUNET_TUN_DnsSrvRecord srv_bin; size_t old_off; char *ndup; char *tok; if ('_' != *r_name) return NULL; /* all valid srv names must start with "_" */ if (NULL == strstr (r_name, "._")) return NULL; /* necessary string from "._$PROTO" not present */ old_off = *off; if (*off + sizeof (struct GNUNET_TUN_DnsSrvRecord) > udp_payload_length) return NULL; memcpy (&srv_bin, &udp_payload[*off], sizeof (struct GNUNET_TUN_DnsSrvRecord)); (*off) += sizeof (struct GNUNET_TUN_DnsSrvRecord); srv = GNUNET_new (struct GNUNET_DNSPARSER_SrvRecord); srv->priority = ntohs (srv_bin.prio); srv->weight = ntohs (srv_bin.weight); srv->port = ntohs (srv_bin.port); /* parse 'data.hostname' into components, which are "_$SERVICE._$PROTO.$DOMAIN_NAME" */ ndup = GNUNET_strdup (r_name); tok = strtok (ndup, "."); GNUNET_assert (NULL != tok); GNUNET_assert ('_' == *tok); srv->service = GNUNET_strdup (&tok[1]); tok = strtok (NULL, "."); if ( (NULL == tok) || ('_' != *tok) ) { GNUNET_DNSPARSER_free_srv (srv); GNUNET_free (ndup); *off = old_off; return NULL; } srv->proto = GNUNET_strdup (&tok[1]); tok = strtok (NULL, "."); if (NULL == tok) { GNUNET_DNSPARSER_free_srv (srv); GNUNET_free (ndup); *off = old_off; return NULL; } srv->domain_name = GNUNET_strdup (tok); GNUNET_free (ndup); srv->target = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); if (NULL == srv->target) { GNUNET_DNSPARSER_free_srv (srv); *off = old_off; return NULL; } return srv; } /** * Parse a DNS CERT record. * * @param udp_payload reference to UDP packet * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the query to parse in the CERT record (to be * incremented by the size of the record), unchanged on error * @return the parsed CERT record, NULL on error */ struct GNUNET_DNSPARSER_CertRecord * GNUNET_DNSPARSER_parse_cert (const char *udp_payload, size_t udp_payload_length, size_t *off) { struct GNUNET_DNSPARSER_CertRecord *cert; struct GNUNET_TUN_DnsCertRecord dcert; if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) >= udp_payload_length) { GNUNET_break_op (0); return NULL; } memcpy (&dcert, &udp_payload[*off], sizeof (struct GNUNET_TUN_DnsCertRecord)); (*off) += sizeof (sizeof (struct GNUNET_TUN_DnsCertRecord)); cert = GNUNET_new (struct GNUNET_DNSPARSER_CertRecord); cert->cert_type = ntohs (dcert.cert_type); cert->cert_tag = ntohs (dcert.cert_tag); cert->algorithm = dcert.algorithm; cert->certificate_size = udp_payload_length - (*off); cert->certificate_data = GNUNET_malloc (cert->certificate_size); memcpy (cert->certificate_data, &udp_payload[*off], cert->certificate_size); (*off) += cert->certificate_size; return cert; } /** * Parse a DNS record entry. * * @param udp_payload entire UDP payload * @param udp_payload_length length of @a udp_payload * @param off pointer to the offset of the record to parse in the udp_payload (to be * incremented by the size of the record) * @param r where to write the record information * @return #GNUNET_OK on success, #GNUNET_SYSERR if the record is malformed */ int GNUNET_DNSPARSER_parse_record (const char *udp_payload, size_t udp_payload_length, size_t *off, struct GNUNET_DNSPARSER_Record *r) { char *name; struct GNUNET_TUN_DnsRecordLine rl; size_t old_off; uint16_t data_len; name = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); if (NULL == name) { GNUNET_break_op (0); return GNUNET_SYSERR; } r->name = name; if (*off + sizeof (struct GNUNET_TUN_DnsRecordLine) > udp_payload_length) { GNUNET_break_op (0); return GNUNET_SYSERR; } memcpy (&rl, &udp_payload[*off], sizeof (rl)); (*off) += sizeof (rl); r->type = ntohs (rl.type); r->dns_traffic_class = ntohs (rl.dns_traffic_class); r->expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, ntohl (rl.ttl))); data_len = ntohs (rl.data_len); if (*off + data_len > udp_payload_length) { GNUNET_break_op (0); return GNUNET_SYSERR; } old_off = *off; switch (r->type) { case GNUNET_DNSPARSER_TYPE_NS: case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: r->data.hostname = GNUNET_DNSPARSER_parse_name (udp_payload, udp_payload_length, off); if ( (NULL == r->data.hostname) || (old_off + data_len != *off) ) return GNUNET_SYSERR; return GNUNET_OK; case GNUNET_DNSPARSER_TYPE_SOA: r->data.soa = GNUNET_DNSPARSER_parse_soa (udp_payload, udp_payload_length, off); if ( (NULL == r->data.soa) || (old_off + data_len != *off) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } return GNUNET_OK; case GNUNET_DNSPARSER_TYPE_MX: r->data.mx = GNUNET_DNSPARSER_parse_mx (udp_payload, udp_payload_length, off); if ( (NULL == r->data.mx) || (old_off + data_len != *off) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } return GNUNET_OK; case GNUNET_DNSPARSER_TYPE_SRV: r->data.srv = GNUNET_DNSPARSER_parse_srv (r->name, udp_payload, udp_payload_length, off); if ( (NULL == r->data.srv) || (old_off + data_len != *off) ) { GNUNET_break_op (0); return GNUNET_SYSERR; } return GNUNET_OK; default: r->data.raw.data = GNUNET_malloc (data_len); r->data.raw.data_len = data_len; memcpy (r->data.raw.data, &udp_payload[*off], data_len); break; } (*off) += data_len; return GNUNET_OK; } /** * Parse a UDP payload of a DNS packet in to a nice struct for further * processing and manipulation. * * @param udp_payload wire-format of the DNS packet * @param udp_payload_length number of bytes in @a udp_payload * @return NULL on error, otherwise the parsed packet */ struct GNUNET_DNSPARSER_Packet * GNUNET_DNSPARSER_parse (const char *udp_payload, size_t udp_payload_length) { struct GNUNET_DNSPARSER_Packet *p; const struct GNUNET_TUN_DnsHeader *dns; size_t off; unsigned int n; unsigned int i; if (udp_payload_length < sizeof (struct GNUNET_TUN_DnsHeader)) return NULL; dns = (const struct GNUNET_TUN_DnsHeader *) udp_payload; off = sizeof (struct GNUNET_TUN_DnsHeader); p = GNUNET_new (struct GNUNET_DNSPARSER_Packet); p->flags = dns->flags; p->id = dns->id; n = ntohs (dns->query_count); if (n > 0) { p->queries = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Query)); p->num_queries = n; for (i=0;iqueries[i])) goto error; } n = ntohs (dns->answer_rcount); if (n > 0) { p->answers = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record)); p->num_answers = n; for (i=0;ianswers[i])) goto error; } n = ntohs (dns->authority_rcount); if (n > 0) { p->authority_records = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record)); p->num_authority_records = n; for (i=0;iauthority_records[i])) goto error; } n = ntohs (dns->additional_rcount); if (n > 0) { p->additional_records = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record)); p->num_additional_records = n; for (i=0;iadditional_records[i])) goto error; } return p; error: GNUNET_break_op (0); GNUNET_DNSPARSER_free_packet (p); return NULL; } /** * Free memory taken by a packet. * * @param p packet to free */ void GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p) { unsigned int i; for (i=0;inum_queries;i++) GNUNET_free_non_null (p->queries[i].name); GNUNET_free_non_null (p->queries); for (i=0;inum_answers;i++) GNUNET_DNSPARSER_free_record (&p->answers[i]); GNUNET_free_non_null (p->answers); for (i=0;inum_authority_records;i++) GNUNET_DNSPARSER_free_record (&p->authority_records[i]); GNUNET_free_non_null (p->authority_records); for (i=0;inum_additional_records;i++) GNUNET_DNSPARSER_free_record (&p->additional_records[i]); GNUNET_free_non_null (p->additional_records); GNUNET_free (p); } /* ********************** DNS packet assembly code **************** */ /** * Add a DNS name to the UDP packet at the given location, converting * the name to IDNA notation as necessary. * * @param dst where to write the name (UDP packet) * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the name (increment by bytes used) * must not be changed if there is an error * @param name name to write * @return #GNUNET_SYSERR if @a name is invalid * #GNUNET_NO if @a name did not fit * #GNUNET_OK if @a name was added to @a dst */ int GNUNET_DNSPARSER_builder_add_name (char *dst, size_t dst_len, size_t *off, const char *name) { const char *dot; const char *idna_name; char *idna_start; size_t start; size_t pos; size_t len; Idna_rc rc; if (NULL == name) return GNUNET_SYSERR; if (IDNA_SUCCESS != (rc = idna_to_ascii_8z (name, &idna_start, IDNA_ALLOW_UNASSIGNED))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n"), name, idna_strerror (rc)); return GNUNET_NO; } idna_name = idna_start; start = *off; if (start + strlen (idna_name) + 2 > dst_len) goto fail; pos = start; do { dot = strchr (idna_name, '.'); if (NULL == dot) len = strlen (idna_name); else len = dot - idna_name; if ( (len >= 64) || (0 == len) ) { GNUNET_break (0); goto fail; /* segment too long or empty */ } dst[pos++] = (char) (uint8_t) len; memcpy (&dst[pos], idna_name, len); pos += len; idna_name += len + 1; /* also skip dot */ } while (NULL != dot); dst[pos++] = '\0'; /* terminator */ *off = pos; #if WINDOWS idn_free (idna_start); #else free (idna_start); #endif return GNUNET_OK; fail: #if WINDOWS idn_free (idna_start); #else free (idna_start); #endif return GNUNET_NO; } /** * Add a DNS query to the UDP packet at the given location. * * @param dst where to write the query * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the query (increment by bytes used) * must not be changed if there is an error * @param query query to write * @return #GNUNET_SYSERR if @a query is invalid * #GNUNET_NO if @a query did not fit * #GNUNET_OK if @a query was added to @a dst */ int GNUNET_DNSPARSER_builder_add_query (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_Query *query) { int ret; struct GNUNET_TUN_DnsQueryLine ql; ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len - sizeof (struct GNUNET_TUN_DnsQueryLine), off, query->name); if (ret != GNUNET_OK) return ret; ql.type = htons (query->type); ql.dns_traffic_class = htons (query->dns_traffic_class); memcpy (&dst[*off], &ql, sizeof (ql)); (*off) += sizeof (ql); return GNUNET_OK; } /** * Add an MX record to the UDP packet at the given location. * * @param dst where to write the mx record * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the mx information (increment by bytes used); * can also change if there was an error * @param mx mx information to write * @return #GNUNET_SYSERR if @a mx is invalid * #GNUNET_NO if @a mx did not fit * #GNUNET_OK if @a mx was added to @a dst */ int GNUNET_DNSPARSER_builder_add_mx (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_MxRecord *mx) { uint16_t mxpref; if (*off + sizeof (uint16_t) > dst_len) return GNUNET_NO; mxpref = htons (mx->preference); memcpy (&dst[*off], &mxpref, sizeof (mxpref)); (*off) += sizeof (mxpref); return GNUNET_DNSPARSER_builder_add_name (dst, dst_len, off, mx->mxhost); } /** * Add a CERT record to the UDP packet at the given location. * * @param dst where to write the CERT record * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the CERT information (increment by bytes used); * can also change if there was an error * @param cert CERT information to write * @return #GNUNET_SYSERR if @a cert is invalid * #GNUNET_NO if @a cert did not fit * #GNUNET_OK if @a cert was added to @a dst */ int GNUNET_DNSPARSER_builder_add_cert (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_CertRecord *cert) { struct GNUNET_TUN_DnsCertRecord dcert; if ( (cert->cert_type > UINT16_MAX) || (cert->cert_tag > UINT16_MAX) || (cert->algorithm > UINT8_MAX) ) { GNUNET_break (0); return GNUNET_SYSERR; } if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) + cert->certificate_size > dst_len) return GNUNET_NO; dcert.cert_type = htons ((uint16_t) cert->cert_type); dcert.cert_tag = htons ((uint16_t) cert->cert_tag); dcert.algorithm = (uint8_t) cert->algorithm; memcpy (&dst[*off], &dcert, sizeof (dcert)); (*off) += sizeof (dcert); memcpy (&dst[*off], cert->certificate_data, cert->certificate_size); (*off) += cert->certificate_size; return GNUNET_OK; } /** * Add an SOA record to the UDP packet at the given location. * * @param dst where to write the SOA record * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the SOA information (increment by bytes used) * can also change if there was an error * @param soa SOA information to write * @return #GNUNET_SYSERR if @a soa is invalid * #GNUNET_NO if @a soa did not fit * #GNUNET_OK if @a soa was added to @a dst */ int GNUNET_DNSPARSER_builder_add_soa (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SoaRecord *soa) { struct GNUNET_TUN_DnsSoaRecord sd; int ret; if ( (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len, off, soa->mname))) || (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len, off, soa->rname)) ) ) return ret; if (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > dst_len) return GNUNET_NO; sd.serial = htonl (soa->serial); sd.refresh = htonl (soa->refresh); sd.retry = htonl (soa->retry); sd.expire = htonl (soa->expire); sd.minimum = htonl (soa->minimum_ttl); memcpy (&dst[*off], &sd, sizeof (sd)); (*off) += sizeof (sd); return GNUNET_OK; } /** * Add an SRV record to the UDP packet at the given location. * * @param dst where to write the SRV record * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the SRV information (increment by bytes used) * can also change if there was an error * @param srv SRV information to write * @return #GNUNET_SYSERR if @a srv is invalid * #GNUNET_NO if @a srv did not fit * #GNUNET_OK if @a srv was added to @a dst */ int GNUNET_DNSPARSER_builder_add_srv (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_SrvRecord *srv) { struct GNUNET_TUN_DnsSrvRecord sd; int ret; if (*off + sizeof (struct GNUNET_TUN_DnsSrvRecord) > dst_len) return GNUNET_NO; sd.prio = htons (srv->priority); sd.weight = htons (srv->weight); sd.port = htons (srv->port); memcpy (&dst[*off], &sd, sizeof (sd)); (*off) += sizeof (sd); if (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len, off, srv->target))) return ret; return GNUNET_OK; } /** * Add a DNS record to the UDP packet at the given location. * * @param dst where to write the query * @param dst_len number of bytes in @a dst * @param off pointer to offset where to write the query (increment by bytes used) * must not be changed if there is an error * @param record record to write * @return #GNUNET_SYSERR if @a record is invalid * #GNUNET_NO if @a record did not fit * #GNUNET_OK if @a record was added to @a dst */ static int add_record (char *dst, size_t dst_len, size_t *off, const struct GNUNET_DNSPARSER_Record *record) { int ret; size_t start; size_t pos; struct GNUNET_TUN_DnsRecordLine rl; char *name; start = *off; /* for SRV records, we can create the name from the details of the record if needed */ name = record->name; if ( (GNUNET_DNSPARSER_TYPE_SRV == record->type) && (NULL == name) ) GNUNET_asprintf (&name, "_%s._%s.%s", record->data.srv->service, record->data.srv->proto, record->data.srv->domain_name); ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len - sizeof (struct GNUNET_TUN_DnsRecordLine), off, name); if (name != record->name) GNUNET_free (name); if (GNUNET_OK != ret) return ret; /* '*off' is now the position where we will need to write the record line */ pos = *off + sizeof (struct GNUNET_TUN_DnsRecordLine); switch (record->type) { case GNUNET_DNSPARSER_TYPE_MX: ret = GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &pos, record->data.mx); break; case GNUNET_DNSPARSER_TYPE_CERT: ret = GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &pos, record->data.cert); break; case GNUNET_DNSPARSER_TYPE_SOA: ret = GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &pos, record->data.soa); break; case GNUNET_DNSPARSER_TYPE_NS: case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &pos, record->data.hostname); break; case GNUNET_DNSPARSER_TYPE_SRV: ret = GNUNET_DNSPARSER_builder_add_srv (dst, dst_len, &pos, record->data.srv); break; default: if (pos + record->data.raw.data_len > dst_len) { ret = GNUNET_NO; break; } memcpy (&dst[pos], record->data.raw.data, record->data.raw.data_len); pos += record->data.raw.data_len; ret = GNUNET_OK; break; } if (GNUNET_OK != ret) { *off = start; return GNUNET_NO; } if (pos - (*off + sizeof (struct GNUNET_TUN_DnsRecordLine)) > UINT16_MAX) { /* record data too long */ *off = start; return GNUNET_NO; } rl.type = htons (record->type); rl.dns_traffic_class = htons (record->dns_traffic_class); rl.ttl = htonl (GNUNET_TIME_absolute_get_remaining (record->expiration_time).rel_value_us / 1000LL / 1000LL); /* in seconds */ rl.data_len = htons ((uint16_t) (pos - (*off + sizeof (struct GNUNET_TUN_DnsRecordLine)))); memcpy (&dst[*off], &rl, sizeof (struct GNUNET_TUN_DnsRecordLine)); *off = pos; return GNUNET_OK; } /** * Given a DNS packet @a p, generate the corresponding UDP payload. * Note that we do not attempt to pack the strings with pointers * as this would complicate the code and this is about being * simple and secure, not fast, fancy and broken like bind. * * @param p packet to pack * @param max maximum allowed size for the resulting UDP payload * @param buf set to a buffer with the packed message * @param buf_length set to the length of @a buf * @return #GNUNET_SYSERR if @a p is invalid * #GNUNET_NO if @a p was truncated (but there is still a result in @a buf) * #GNUNET_OK if @a p was packed completely into @a buf */ int GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p, uint16_t max, char **buf, size_t *buf_length) { struct GNUNET_TUN_DnsHeader dns; size_t off; char tmp[max]; unsigned int i; int ret; int trc; if ( (p->num_queries > UINT16_MAX) || (p->num_answers > UINT16_MAX) || (p->num_authority_records > UINT16_MAX) || (p->num_additional_records > UINT16_MAX) ) return GNUNET_SYSERR; dns.id = p->id; dns.flags = p->flags; dns.query_count = htons (p->num_queries); dns.answer_rcount = htons (p->num_answers); dns.authority_rcount = htons (p->num_authority_records); dns.additional_rcount = htons (p->num_additional_records); off = sizeof (struct GNUNET_TUN_DnsHeader); trc = GNUNET_NO; for (i=0;inum_queries;i++) { ret = GNUNET_DNSPARSER_builder_add_query (tmp, sizeof (tmp), &off, &p->queries[i]); if (GNUNET_SYSERR == ret) return GNUNET_SYSERR; if (GNUNET_NO == ret) { dns.query_count = htons ((uint16_t) (i-1)); trc = GNUNET_YES; break; } } for (i=0;inum_answers;i++) { ret = add_record (tmp, sizeof (tmp), &off, &p->answers[i]); if (GNUNET_SYSERR == ret) return GNUNET_SYSERR; if (GNUNET_NO == ret) { dns.answer_rcount = htons ((uint16_t) (i-1)); trc = GNUNET_YES; break; } } for (i=0;inum_authority_records;i++) { ret = add_record (tmp, sizeof (tmp), &off, &p->authority_records[i]); if (GNUNET_SYSERR == ret) return GNUNET_SYSERR; if (GNUNET_NO == ret) { dns.authority_rcount = htons ((uint16_t) (i-1)); trc = GNUNET_YES; break; } } for (i=0;inum_additional_records;i++) { ret = add_record (tmp, sizeof (tmp), &off, &p->additional_records[i]); if (GNUNET_SYSERR == ret) return GNUNET_SYSERR; if (GNUNET_NO == ret) { dns.additional_rcount = htons (i-1); trc = GNUNET_YES; break; } } if (GNUNET_YES == trc) dns.flags.message_truncated = 1; memcpy (tmp, &dns, sizeof (struct GNUNET_TUN_DnsHeader)); *buf = GNUNET_malloc (off); *buf_length = off; memcpy (*buf, tmp, off); if (GNUNET_YES == trc) return GNUNET_NO; return GNUNET_OK; } /* end of dnsparser.c */ gnunet-0.10.1/src/dns/gnunet-dns-redirector.c0000644000175000017500000001510112225777502015762 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/dns/gnunet-dns-redirector.c * @brief Tool to change DNS replies (for testing) * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dns_service.h" #include "gnunet_dnsparser_lib.h" /** * Handle to DNS service. */ static struct GNUNET_DNS_Handle *handle; /** * New target for A records. */ static char *n4; /** * New target for AAAA records. */ static char *n6; /** * Global return value (0 success). */ static int ret; /** * Selected level of verbosity. */ static int verbosity; /** * Modify the given DNS record. * * @param record record to modify */ static void modify_record (const struct GNUNET_DNSPARSER_Record *record) { char buf[INET6_ADDRSTRLEN]; switch (record->type) { case GNUNET_DNSPARSER_TYPE_A: if (record->data.raw.data_len != sizeof (struct in_addr)) return; if (NULL != n4) { if (verbosity > 1) fprintf (stderr, "Changing A record from `%s' to `%s'\n", inet_ntop (AF_INET, record->data.raw.data, buf, sizeof (buf)), n4); GNUNET_assert (1 == inet_pton (AF_INET, n4, record->data.raw.data)); } break; case GNUNET_DNSPARSER_TYPE_AAAA: if (record->data.raw.data_len != sizeof (struct in6_addr)) return; if (NULL != n6) { if (verbosity > 1) fprintf (stderr, "Changing AAAA record from `%s' to `%s'\n", inet_ntop (AF_INET6, record->data.raw.data, buf, sizeof (buf)), n6); GNUNET_assert (1 == inet_pton (AF_INET6, n6, record->data.raw.data)); } break; case GNUNET_DNSPARSER_TYPE_NS: case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: case GNUNET_DNSPARSER_TYPE_SOA: case GNUNET_DNSPARSER_TYPE_MX: case GNUNET_DNSPARSER_TYPE_TXT: break; default: break; } } /** * Signature of a function that is called whenever the DNS service * encounters a DNS request and needs to do something with it. The * function has then the chance to generate or modify the response by * calling one of the three "GNUNET_DNS_request_*" continuations. * * When a request is intercepted, this function is called first to * give the client a chance to do the complete address resolution; * "rdata" will be NULL for this first call for a DNS request, unless * some other client has already filled in a response. * * If multiple clients exist, all of them are called before the global * DNS. The global DNS is only called if all of the clients' * functions call GNUNET_DNS_request_forward. Functions that call * GNUNET_DNS_request_forward will be called again before a final * response is returned to the application. If any of the clients' * functions call GNUNET_DNS_request_drop, the response is dropped. * * @param cls closure * @param rh request handle to user for reply * @param request_length number of bytes in request * @param request udp payload of the DNS request */ static void modify_request (void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request) { struct GNUNET_DNSPARSER_Packet *p; unsigned int i; char *buf; size_t len; int ret; p = GNUNET_DNSPARSER_parse (request, request_length); if (NULL == p) { fprintf (stderr, "Received malformed DNS packet, leaving it untouched\n"); GNUNET_DNS_request_forward (rh); return; } for (i=0;inum_answers;i++) modify_record (&p->answers[i]); buf = NULL; ret = GNUNET_DNSPARSER_pack (p, 1024, &buf, &len); GNUNET_DNSPARSER_free_packet (p); if (GNUNET_OK != ret) { if (GNUNET_NO == ret) fprintf (stderr, "Modified DNS response did not fit, keeping old response\n"); else GNUNET_break (0); /* our modifications should have been sane! */ GNUNET_DNS_request_forward (rh); } else { if (verbosity > 0) fprintf (stdout, "Injecting modified DNS response\n"); GNUNET_DNS_request_answer (rh, len, buf); } GNUNET_free_non_null (buf); } /** * Shutdown. */ static void do_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != handle) { GNUNET_DNS_disconnect (handle); handle = NULL; } } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct in_addr i4; struct in6_addr i6; if ( (n4 != NULL) && (1 != inet_pton (AF_INET, n4, &i4)) ) { fprintf (stderr, "`%s' is nto a valid IPv4 address!\n", n4); return; } if ( (n6 != NULL) && (1 != inet_pton (AF_INET6, n6, &i6)) ) { fprintf (stderr, "`%s' is nto a valid IPv6 address!\n", n6); return; } handle = GNUNET_DNS_connect (cfg, GNUNET_DNS_FLAG_POST_RESOLUTION, &modify_request, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_disconnect, NULL); } int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'4', "ipv4", "IPV4", gettext_noop ("set A records"), 1, &GNUNET_GETOPT_set_string, &n4}, {'6', "ipv4", "IPV6", gettext_noop ("set AAAA records"), 1, &GNUNET_GETOPT_set_string, &n6}, GNUNET_GETOPT_OPTION_VERBOSE (&verbosity), GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-dns-redirector", gettext_noop ("Change DNS replies to point elsewhere."), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-dns-redirector.c */ gnunet-0.10.1/src/dns/Makefile.in0000644000175000017500000013641012320752061013435 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ libexec_PROGRAMS = gnunet-service-dns$(EXEEXT) $(am__EXEEXT_1) noinst_PROGRAMS = gnunet-dns-monitor$(EXEEXT) \ gnunet-dns-redirector$(EXEEXT) @ENABLE_TEST_RUN_TRUE@TESTS = $(check_SCRIPTS) subdir = src/dns DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/dns.conf.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = dns.conf CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(plugin_LTLIBRARIES) libgnunet_plugin_block_dns_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunet_plugin_block_dns_la_OBJECTS = plugin_block_dns.lo libgnunet_plugin_block_dns_la_OBJECTS = \ $(am_libgnunet_plugin_block_dns_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgnunet_plugin_block_dns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) \ $(libgnunet_plugin_block_dns_la_LDFLAGS) $(LDFLAGS) -o $@ libgnunetdns_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetdns_la_OBJECTS = dns_api.lo libgnunetdns_la_OBJECTS = $(am_libgnunetdns_la_OBJECTS) libgnunetdns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetdns_la_LDFLAGS) $(LDFLAGS) \ -o $@ libgnunetdnsparser_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetdnsparser_la_OBJECTS = dnsparser.lo libgnunetdnsparser_la_OBJECTS = $(am_libgnunetdnsparser_la_OBJECTS) libgnunetdnsparser_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetdnsparser_la_LDFLAGS) \ $(LDFLAGS) -o $@ libgnunetdnsstub_la_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_libgnunetdnsstub_la_OBJECTS = dnsstub.lo libgnunetdnsstub_la_OBJECTS = $(am_libgnunetdnsstub_la_OBJECTS) libgnunetdnsstub_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetdnsstub_la_LDFLAGS) \ $(LDFLAGS) -o $@ @LINUX_TRUE@am__EXEEXT_1 = gnunet-helper-dns$(EXEEXT) PROGRAMS = $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_gnunet_dns_monitor_OBJECTS = gnunet-dns-monitor.$(OBJEXT) gnunet_dns_monitor_OBJECTS = $(am_gnunet_dns_monitor_OBJECTS) am__DEPENDENCIES_1 = am_gnunet_dns_redirector_OBJECTS = gnunet-dns-redirector.$(OBJEXT) gnunet_dns_redirector_OBJECTS = $(am_gnunet_dns_redirector_OBJECTS) am_gnunet_helper_dns_OBJECTS = gnunet-helper-dns.$(OBJEXT) gnunet_helper_dns_OBJECTS = $(am_gnunet_helper_dns_OBJECTS) gnunet_helper_dns_LDADD = $(LDADD) am_gnunet_service_dns_OBJECTS = gnunet-service-dns.$(OBJEXT) gnunet_service_dns_OBJECTS = $(am_gnunet_service_dns_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgnunet_plugin_block_dns_la_SOURCES) \ $(libgnunetdns_la_SOURCES) $(libgnunetdnsparser_la_SOURCES) \ $(libgnunetdnsstub_la_SOURCES) $(gnunet_dns_monitor_SOURCES) \ $(gnunet_dns_redirector_SOURCES) $(gnunet_helper_dns_SOURCES) \ $(gnunet_service_dns_SOURCES) DIST_SOURCES = $(libgnunet_plugin_block_dns_la_SOURCES) \ $(libgnunetdns_la_SOURCES) $(libgnunetdnsparser_la_SOURCES) \ $(libgnunetdnsstub_la_SOURCES) $(gnunet_dns_monitor_SOURCES) \ $(gnunet_dns_redirector_SOURCES) $(gnunet_helper_dns_SOURCES) \ $(gnunet_service_dns_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgcfg_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include @MINGW_TRUE@WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 pkgcfgdir = $(pkgdatadir)/config.d/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ dns.conf @LINUX_TRUE@HIJACKBIN = gnunet-helper-dns lib_LTLIBRARIES = \ libgnunetdnsparser.la \ libgnunetdnsstub.la \ libgnunetdns.la plugin_LTLIBRARIES = \ libgnunet_plugin_block_dns.la @LINUX_TRUE@check_SCRIPTS = \ @LINUX_TRUE@ test_gnunet_dns.sh gnunet_helper_dns_SOURCES = \ gnunet-helper-dns.c gnunet_dns_monitor_SOURCES = \ gnunet-dns-monitor.c gnunet_dns_monitor_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_dns_monitor_DEPENDENCIES = \ libgnunetdnsparser.la \ libgnunetdns.la gnunet_dns_redirector_SOURCES = \ gnunet-dns-redirector.c gnunet_dns_redirector_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_dns_redirector_DEPENDENCIES = \ libgnunetdnsparser.la \ libgnunetdns.la gnunet_service_dns_SOURCES = \ gnunet-service-dns.c gnunet_service_dns_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_dns_DEPENDENCIES = \ libgnunetdnsstub.la libgnunetdnsparser_la_SOURCES = \ dnsparser.c libgnunetdnsparser_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ -lidn libgnunetdnsparser_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 1:0:1 libgnunetdnsstub_la_SOURCES = \ dnsstub.c libgnunetdnsstub_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) libgnunetdnsstub_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 libgnunetdns_la_SOURCES = \ dns_api.c dns.h libgnunetdns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) libgnunetdns_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 libgnunet_plugin_block_dns_la_SOURCES = \ plugin_block_dns.c libgnunet_plugin_block_dns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_block_dns_la_LDFLAGS = \ $(top_builddir)/src/block/$(GN_PLUGIN_LDFLAGS) @ENABLE_TEST_RUN_TRUE@AM_TESTS_ENVIRONMENT = export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; EXTRA_DIST = \ $(check_SCRIPTS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/dns/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/dns/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): dns.conf: $(top_builddir)/config.status $(srcdir)/dns.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgnunet_plugin_block_dns.la: $(libgnunet_plugin_block_dns_la_OBJECTS) $(libgnunet_plugin_block_dns_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_block_dns_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_block_dns_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_block_dns_la_OBJECTS) $(libgnunet_plugin_block_dns_la_LIBADD) $(LIBS) libgnunetdns.la: $(libgnunetdns_la_OBJECTS) $(libgnunetdns_la_DEPENDENCIES) $(EXTRA_libgnunetdns_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetdns_la_LINK) -rpath $(libdir) $(libgnunetdns_la_OBJECTS) $(libgnunetdns_la_LIBADD) $(LIBS) libgnunetdnsparser.la: $(libgnunetdnsparser_la_OBJECTS) $(libgnunetdnsparser_la_DEPENDENCIES) $(EXTRA_libgnunetdnsparser_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetdnsparser_la_LINK) -rpath $(libdir) $(libgnunetdnsparser_la_OBJECTS) $(libgnunetdnsparser_la_LIBADD) $(LIBS) libgnunetdnsstub.la: $(libgnunetdnsstub_la_OBJECTS) $(libgnunetdnsstub_la_DEPENDENCIES) $(EXTRA_libgnunetdnsstub_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetdnsstub_la_LINK) -rpath $(libdir) $(libgnunetdnsstub_la_OBJECTS) $(libgnunetdnsstub_la_LIBADD) $(LIBS) install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list gnunet-dns-monitor$(EXEEXT): $(gnunet_dns_monitor_OBJECTS) $(gnunet_dns_monitor_DEPENDENCIES) $(EXTRA_gnunet_dns_monitor_DEPENDENCIES) @rm -f gnunet-dns-monitor$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_dns_monitor_OBJECTS) $(gnunet_dns_monitor_LDADD) $(LIBS) gnunet-dns-redirector$(EXEEXT): $(gnunet_dns_redirector_OBJECTS) $(gnunet_dns_redirector_DEPENDENCIES) $(EXTRA_gnunet_dns_redirector_DEPENDENCIES) @rm -f gnunet-dns-redirector$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_dns_redirector_OBJECTS) $(gnunet_dns_redirector_LDADD) $(LIBS) gnunet-helper-dns$(EXEEXT): $(gnunet_helper_dns_OBJECTS) $(gnunet_helper_dns_DEPENDENCIES) $(EXTRA_gnunet_helper_dns_DEPENDENCIES) @rm -f gnunet-helper-dns$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_helper_dns_OBJECTS) $(gnunet_helper_dns_LDADD) $(LIBS) gnunet-service-dns$(EXEEXT): $(gnunet_service_dns_OBJECTS) $(gnunet_service_dns_DEPENDENCIES) $(EXTRA_gnunet_service_dns_DEPENDENCIES) @rm -f gnunet-service-dns$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_dns_OBJECTS) $(gnunet_service_dns_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsparser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dnsstub.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-dns-monitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-dns-redirector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-helper-dns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-dns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_block_dns.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgcfgdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgcfgdir)" || exit $$?; \ done uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_gnunet_dns.sh.log: test_gnunet_dns.sh @p='test_gnunet_dns.sh'; \ b='test_gnunet_dns.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libexecPROGRAMS \ clean-libtool clean-noinstPROGRAMS clean-pluginLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgcfgDATA install-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-libexecPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-exec-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-generic clean-libLTLIBRARIES clean-libexecPROGRAMS \ clean-libtool clean-noinstPROGRAMS clean-pluginLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-exec-hook install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pkgcfgDATA \ install-pluginLTLIBRARIES install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am recheck tags tags-am uninstall \ uninstall-am uninstall-libLTLIBRARIES \ uninstall-libexecPROGRAMS uninstall-pkgcfgDATA \ uninstall-pluginLTLIBRARIES @LINUX_TRUE@install-exec-hook: @LINUX_TRUE@ $(top_srcdir)/src/dns/install-dns-helper.sh $(libexecdir) $(GNUNETDNS_GROUP) $(SUDO_BINARY) || true @LINUX_FALSE@install-exec-hook: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/src/dns/plugin_block_dns.c0000644000175000017500000001165012225777502015061 00000000000000/* This file is part of GNUnet (C) 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dns/plugin_block_dns.c * @brief block plugin for advertising a DNS exit service * @author Christian Grothoff * * Note that this plugin might more belong with EXIT and PT * as those two are using this type of block. Still, this * might be a natural enough place for people to find the code... */ #include "platform.h" #include "gnunet_block_plugin.h" #include "block_dns.h" #include "gnunet_signatures.h" /** * Function called to validate a reply or a request. For * request evaluation, simply pass "NULL" for the reply_block. * * @param cls closure * @param type block type * @param query original query (hash) * @param bf pointer to bloom filter associated with query; possibly updated (!) * @param bf_mutator mutation value for bf * @param xquery extended query data (can be NULL, depending on type) * @param xquery_size number of bytes in @a xquery * @param reply_block response to validate * @param reply_block_size number of bytes in @a reply_block * @return characterization of result */ static enum GNUNET_BLOCK_EvaluationResult block_plugin_dns_evaluate (void *cls, enum GNUNET_BLOCK_Type type, const struct GNUNET_HashCode * query, struct GNUNET_CONTAINER_BloomFilter **bf, int32_t bf_mutator, const void *xquery, size_t xquery_size, const void *reply_block, size_t reply_block_size) { const struct GNUNET_DNS_Advertisement *ad; switch (type) { case GNUNET_BLOCK_TYPE_DNS: if (0 != xquery_size) return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID; if (0 == reply_block_size) return GNUNET_BLOCK_EVALUATION_REQUEST_VALID; if (sizeof (struct GNUNET_DNS_Advertisement) != reply_block_size) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } ad = reply_block; if (ntohl (ad->purpose.size) != sizeof (struct GNUNET_DNS_Advertisement) - sizeof (struct GNUNET_CRYPTO_EddsaSignature)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (ad->expiration_time)).rel_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "DNS advertisement has expired\n"); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_DNS_RECORD, &ad->purpose, &ad->signature, &ad->peer.public_key)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } return GNUNET_BLOCK_EVALUATION_OK_MORE; default: return GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED; } } /** * Function called to obtain the key for a block. * * @param cls closure * @param type block type * @param block block to get the key for * @param block_size number of bytes in @a block * @param key set to the key (query) for the given block * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported * (or if extracting a key from a block of this type does not work) */ static int block_plugin_dns_get_key (void *cls, enum GNUNET_BLOCK_Type type, const void *block, size_t block_size, struct GNUNET_HashCode *key) { /* we cannot extract a key from a block of this type */ return GNUNET_SYSERR; } /** * Entry point for the plugin. */ void * libgnunet_plugin_block_dns_init (void *cls) { static enum GNUNET_BLOCK_Type types[] = { GNUNET_BLOCK_TYPE_DNS, GNUNET_BLOCK_TYPE_ANY /* end of list */ }; struct GNUNET_BLOCK_PluginFunctions *api; api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); api->evaluate = &block_plugin_dns_evaluate; api->get_key = &block_plugin_dns_get_key; api->types = types; return api; } /** * Exit point from the plugin. */ void * libgnunet_plugin_block_dns_done (void *cls) { struct GNUNET_BLOCK_PluginFunctions *api = cls; GNUNET_free (api); return NULL; } /* end of plugin_block_dns.c */ gnunet-0.10.1/src/dns/dns.conf.in0000644000175000017500000000235712250373167013442 00000000000000[dns] AUTOSTART = @AUTOSTART@ HOSTNAME = localhost BINARY = gnunet-service-dns UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-dns.sock # Access to this service can compromise all DNS queries in this # system. Thus access should be restricted to the same UID. # (see https://gnunet.org/gnunet-access-control-model) UNIX_MATCH_UID = YES UNIX_MATCH_GID = YES # As there is no sufficiently restrictive access control for TCP, # we never use it, even if @UNIXONLY@ is not set (just to be safe) @UNIXONLY@ PORT = 0 # Name of the virtual interface we use to intercept DNS traffic. IFNAME = gnunet-dns # Use RFC 3849-style documentation IPv6 address (RFC 4773 might provide an alternative in the future) # FIXME: or just default to a site-local address scope as we do for VPN!? IPV6ADDR = 2001:DB8::1 IPV6PREFIX = 126 # Use RFC 3927-style link-local address IPV4ADDR = 169.254.1.1 IPV4MASK = 255.255.0.0 # Enable GNUnet-wide DNS-EXIT service by setting this value to the IP address (IPv4 or IPv6) # of a DNS resolver to use. Only works if "PROVIDE_EXIT" is also set to YES. Must absolutely # NOT be an address of any of GNUnet's virtual tunnel interfaces. Use a well-known # public DNS resolver or your ISP's resolver from /etc/resolv.conf. DNS_EXIT = 8.8.8.8 gnunet-0.10.1/src/dns/Makefile.am0000644000175000017500000000561012320751517013426 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include if MINGW WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols endif if USE_COVERAGE AM_CFLAGS = --coverage -O0 endif pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ plugindir = $(libdir)/gnunet pkgcfg_DATA = \ dns.conf if LINUX HIJACKBIN = gnunet-helper-dns install-exec-hook: $(top_srcdir)/src/dns/install-dns-helper.sh $(libexecdir) $(GNUNETDNS_GROUP) $(SUDO_BINARY) || true else install-exec-hook: endif lib_LTLIBRARIES = \ libgnunetdnsparser.la \ libgnunetdnsstub.la \ libgnunetdns.la libexec_PROGRAMS = \ gnunet-service-dns $(HIJACKBIN) noinst_PROGRAMS = \ gnunet-dns-monitor gnunet-dns-redirector plugin_LTLIBRARIES = \ libgnunet_plugin_block_dns.la if LINUX check_SCRIPTS = \ test_gnunet_dns.sh endif gnunet_helper_dns_SOURCES = \ gnunet-helper-dns.c gnunet_dns_monitor_SOURCES = \ gnunet-dns-monitor.c gnunet_dns_monitor_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_dns_monitor_DEPENDENCIES = \ libgnunetdnsparser.la \ libgnunetdns.la gnunet_dns_redirector_SOURCES = \ gnunet-dns-redirector.c gnunet_dns_redirector_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsparser.la \ $(top_builddir)/src/dns/libgnunetdns.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_dns_redirector_DEPENDENCIES = \ libgnunetdnsparser.la \ libgnunetdns.la gnunet_service_dns_SOURCES = \ gnunet-service-dns.c gnunet_service_dns_LDADD = \ $(top_builddir)/src/dns/libgnunetdnsstub.la \ $(top_builddir)/src/tun/libgnunettun.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) gnunet_service_dns_DEPENDENCIES = \ libgnunetdnsstub.la libgnunetdnsparser_la_SOURCES = \ dnsparser.c libgnunetdnsparser_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ -lidn libgnunetdnsparser_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 1:0:1 libgnunetdnsstub_la_SOURCES = \ dnsstub.c libgnunetdnsstub_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) libgnunetdnsstub_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 libgnunetdns_la_SOURCES = \ dns_api.c dns.h libgnunetdns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la $(XLIB) libgnunetdns_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ -version-info 0:0:0 libgnunet_plugin_block_dns_la_SOURCES = \ plugin_block_dns.c libgnunet_plugin_block_dns_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la libgnunet_plugin_block_dns_la_LDFLAGS = \ $(top_builddir)/src/block/$(GN_PLUGIN_LDFLAGS) if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; TESTS = $(check_PROGRAMS) $(check_SCRIPTS) endif EXTRA_DIST = \ $(check_SCRIPTS) gnunet-0.10.1/src/dns/dns.h0000644000175000017500000000431512225777503012337 00000000000000/* This file is part of GNUnet (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dns/dns.h * @brief IPC messages between DNS API and DNS service * @author Christian Grothoff */ #ifndef DNS_H #define DNS_H GNUNET_NETWORK_STRUCT_BEGIN /** * Message from client to DNS service to register itself. */ struct GNUNET_DNS_Register { /** * Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT */ struct GNUNET_MessageHeader header; /** * NBO encoding of 'enum GNUNET_DNS_Flags' for the client. */ uint32_t flags; }; /** * Message from DNS service to client: please handle a request. */ struct GNUNET_DNS_Request { /** * Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST */ struct GNUNET_MessageHeader header; /** * Always zero. */ uint32_t reserved GNUNET_PACKED; /** * Unique request ID. */ uint64_t request_id GNUNET_PACKED; /* followed by original DNS request (without UDP header) */ }; /** * Message from client to DNS service: here is my reply. */ struct GNUNET_DNS_Response { /** * Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE */ struct GNUNET_MessageHeader header; /** * Zero to drop, 1 for no change (no payload), 2 for update (message has payload). */ uint32_t drop_flag GNUNET_PACKED; /** * Unique request ID. */ uint64_t request_id GNUNET_PACKED; /* followed by original DNS request (without UDP header) */ }; GNUNET_NETWORK_STRUCT_END #endif gnunet-0.10.1/src/dns/gnunet-dns-monitor.c0000644000175000017500000002456612225777502015326 00000000000000/* This file is part of GNUnet. (C) 2011 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file src/dns/gnunet-dns-monitor.c * @brief Tool to monitor DNS queries * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dns_service.h" #include "gnunet_dnsparser_lib.h" /** * Handle to transport service. */ static struct GNUNET_DNS_Handle *handle; /** * Option -i. */ static int inbound_only; /** * Option -o. */ static int outbound_only; /** * Global return value (0 success). */ static int ret; /** * Selected level of verbosity. */ static int verbosity; /** * Convert numeric DNS record type to a string. * * @param type type to convert * @return type as string, only valid until the next call to this function */ static const char * get_type (uint16_t type) { static char buf[6]; switch (type) { case GNUNET_DNSPARSER_TYPE_A: return "A"; case GNUNET_DNSPARSER_TYPE_NS: return "NS"; case GNUNET_DNSPARSER_TYPE_CNAME: return "CNAME"; case GNUNET_DNSPARSER_TYPE_SOA: return "SOA"; case GNUNET_DNSPARSER_TYPE_PTR: return "PTR"; case GNUNET_DNSPARSER_TYPE_MX: return "MX"; case GNUNET_DNSPARSER_TYPE_TXT: return "TXT"; case GNUNET_DNSPARSER_TYPE_AAAA: return "AAAA"; case GNUNET_DNSPARSER_TYPE_SRV: return "SRV"; } GNUNET_snprintf (buf, sizeof (buf), "%u", (unsigned int) type); return buf; } /** * Convert numeric DNS record class to a string. * * @param class class to convert * @return class as string, only valid until the next call to this function */ static const char * get_class (uint16_t class) { static char buf[6]; switch (class) { case GNUNET_TUN_DNS_CLASS_INTERNET: return "IN"; case GNUNET_TUN_DNS_CLASS_CHAOS: return "CHAOS"; case GNUNET_TUN_DNS_CLASS_HESIOD: return "HESIOD"; } GNUNET_snprintf (buf, sizeof (buf), "%u", (unsigned int) class); return buf; } /** * Output the given DNS query to stdout. * * @param query query to display. */ static void display_query (const struct GNUNET_DNSPARSER_Query *query) { fprintf (stdout, "\t\t%s %s: %s\n", get_class (query->dns_traffic_class), get_type (query->type), query->name); } /** * Output the given DNS record to stdout. * * @param record record to display. */ static void display_record (const struct GNUNET_DNSPARSER_Record *record) { const char *format; char buf[INET6_ADDRSTRLEN]; char *tmp; tmp = NULL; switch (record->type) { case GNUNET_DNSPARSER_TYPE_A: if (record->data.raw.data_len != sizeof (struct in_addr)) format = ""; else format = inet_ntop (AF_INET, record->data.raw.data, buf, sizeof (buf)); break; case GNUNET_DNSPARSER_TYPE_AAAA: if (record->data.raw.data_len != sizeof (struct in6_addr)) format = ""; else format = inet_ntop (AF_INET6, record->data.raw.data, buf, sizeof (buf)); break; case GNUNET_DNSPARSER_TYPE_NS: case GNUNET_DNSPARSER_TYPE_CNAME: case GNUNET_DNSPARSER_TYPE_PTR: format = record->data.hostname; break; case GNUNET_DNSPARSER_TYPE_SOA: if (NULL == record->data.soa) format = ""; else { GNUNET_asprintf (&tmp, "origin: %s, mail: %s, serial = %u, refresh = %u s, retry = %u s, expire = %u s, minimum = %u s", record->data.soa->mname, record->data.soa->rname, (unsigned int) record->data.soa->serial, (unsigned int) record->data.soa->refresh, (unsigned int) record->data.soa->retry, (unsigned int) record->data.soa->expire, (unsigned int) record->data.soa->minimum_ttl); format = tmp; } break; case GNUNET_DNSPARSER_TYPE_MX: if (record->data.mx == NULL) format = ""; else { GNUNET_asprintf (&tmp, "%u: %s", record->data.mx->preference, record->data.mx->mxhost); format = tmp; } break; case GNUNET_DNSPARSER_TYPE_SRV: if (NULL == record->data.srv) format = ""; else { GNUNET_asprintf (&tmp, "service: %s, protocol: %s, domain_name = %s, priority %u, weight = %s, port = %u, target = %s", record->data.srv->service, record->data.srv->proto, record->data.srv->domain_name, (unsigned int) record->data.srv->priority, (unsigned int) record->data.srv->weight, (unsigned int) record->data.srv->port, record->data.srv->target); format = tmp; } break; case GNUNET_DNSPARSER_TYPE_TXT: GNUNET_asprintf (&tmp, "%.*s", (unsigned int) record->data.raw.data_len, record->data.raw.data); format = tmp; break; default: format = ""; break; } fprintf (stdout, "\t\t%s %s: %s = %s (%u s)\n", get_class (record->dns_traffic_class), get_type (record->type), record->name, format, (unsigned int) (GNUNET_TIME_absolute_get_remaining (record->expiration_time).rel_value_us / 1000LL / 1000LL)); GNUNET_free_non_null (tmp); } /** * Signature of a function that is called whenever the DNS service * encounters a DNS request and needs to do something with it. The * function has then the chance to generate or modify the response by * calling one of the three "GNUNET_DNS_request_*" continuations. * * When a request is intercepted, this function is called first to * give the client a chance to do the complete address resolution; * "rdata" will be NULL for this first call for a DNS request, unless * some other client has already filled in a response. * * If multiple clients exist, all of them are called before the global * DNS. The global DNS is only called if all of the clients' * functions call GNUNET_DNS_request_forward. Functions that call * GNUNET_DNS_request_forward will be called again before a final * response is returned to the application. If any of the clients' * functions call GNUNET_DNS_request_drop, the response is dropped. * * @param cls closure * @param rh request handle to user for reply * @param request_length number of bytes in request * @param request udp payload of the DNS request */ static void display_request (void *cls, struct GNUNET_DNS_RequestHandle *rh, size_t request_length, const char *request) { static const char *return_codes[] = { "No error", "Format error", "Server failure", "Name error", "Not implemented", "Refused", "YXDomain", "YXRRset", "NXRRset", "NOT AUTH", "NOT ZONE", "", "", "", "", "" }; static const char *op_codes[] = { "Query", "Inverse query", "Status", "", "", "", "", "", "", "", "", "", "", "", "", "" }; struct GNUNET_DNSPARSER_Packet *p; unsigned int i; p = GNUNET_DNSPARSER_parse (request, request_length); if (NULL == p) { fprintf (stderr, "Received malformed DNS packet!\n"); // FIXME: drop instead? GNUNET_DNS_request_forward (rh); return; } fprintf (stdout, "%s with ID: %5u Flags: %s%s%s%s%s%s, Return Code: %s, Opcode: %s\n", p->flags.query_or_response ? "Response" : "Query", p->id, p->flags.recursion_desired ? "RD " : "", p->flags.message_truncated ? "MT " : "", p->flags.authoritative_answer ? "AA " : "", p->flags.checking_disabled ? "CD " : "", p->flags.authenticated_data ? "AD " : "", p->flags.recursion_available ? "RA " : "", return_codes[p->flags.return_code & 15], op_codes[p->flags.opcode & 15]); if (p->num_queries > 0) fprintf (stdout, "\tQueries:\n"); for (i=0;inum_queries;i++) display_query (&p->queries[i]); if (p->num_answers > 0) fprintf (stdout, "\tAnswers:\n"); for (i=0;inum_answers;i++) display_record (&p->answers[i]); fprintf (stdout, "\n"); GNUNET_DNSPARSER_free_packet (p); GNUNET_DNS_request_forward (rh); } /** * Shutdown. */ static void do_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { if (NULL != handle) { GNUNET_DNS_disconnect (handle); handle = NULL; } } /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) * @param cfg configuration */ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { enum GNUNET_DNS_Flags flags; flags = GNUNET_DNS_FLAG_REQUEST_MONITOR | GNUNET_DNS_FLAG_RESPONSE_MONITOR; if (inbound_only | outbound_only) flags = 0; if (inbound_only) flags |= GNUNET_DNS_FLAG_REQUEST_MONITOR; if (outbound_only) flags |= GNUNET_DNS_FLAG_RESPONSE_MONITOR; handle = GNUNET_DNS_connect (cfg, flags, &display_request, NULL); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_disconnect, NULL); } int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'i', "inbound-only", NULL, gettext_noop ("only monitor DNS queries"), 0, &GNUNET_GETOPT_set_one, &inbound_only}, {'o', "outbound-only", NULL, gettext_noop ("only monitor DNS replies"), 0, &GNUNET_GETOPT_set_one, &outbound_only}, GNUNET_GETOPT_OPTION_VERBOSE (&verbosity), GNUNET_GETOPT_OPTION_END }; if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 2; ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-dns-monitor", gettext_noop ("Monitor DNS queries."), options, &run, NULL)) ? ret : 1; GNUNET_free ((void*) argv); return ret; } /* end of gnunet-dns-monitor.c */ gnunet-0.10.1/src/dns/gnunet-helper-dns.c0000644000175000017500000006626012226712730015104 00000000000000/* This file is part of GNUnet. (C) 2010, 2011, 2012 Christian Grothoff GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dns/gnunet-helper-dns.c * @brief helper to install firewall rules to hijack all DNS traffic * and send it to our virtual interface (except for DNS traffic * that originates on the specified port). We then * allow interacting with our virtual interface via stdin/stdout. * @author Philipp Tölke * @author Christian Grothoff * * This program alters the Linux firewall rules so that DNS traffic * that ordinarily exits the system can be intercepted and managed by * a virtual interface. In order to achieve this, DNS traffic is * marked with the DNS_MARK given in below and re-routed to a custom * table with the DNS_TABLE ID given below. Systems and * administrators must take care to not cause conflicts with these * values (it was deemed safest to hardcode them as passing these * values as arguments might permit messing with arbitrary firewall * rules, which would be dangerous). Traffic coming from the same * group ID as the effective group ID that this process is running * as is not intercepted. * * The code first sets up the virtual interface, then begins to * redirect the DNS traffic to it, and then on errors or SIGTERM shuts * down the virtual interface and removes the rules for the traffic * redirection. * * * Note that having this binary SUID is only partially safe: it will * allow redirecting (and intercepting / mangling) of all DNS traffic * originating from this system by any user who is able to run it. * Furthermore, this code will make it trivial to DoS all DNS traffic * originating from the current system, simply by sending it to * nowhere (redirect stdout to /dev/null). * * Naturally, neither of these problems can be helped as this is the * fundamental purpose of the binary. Certifying that this code is * "safe" thus only means that it doesn't allow anything else (such * as local priv. escalation, etc.). * * The following list of people have reviewed this code and considered * it safe (within specifications) since the last modification (if you * reviewed it, please have your name added to the list): * * - Christian Grothoff */ #include "platform.h" #include /** * Need 'struct GNUNET_MessageHeader'. */ #include "gnunet_crypto_lib.h" #include "gnunet_common.h" /** * Need DNS message types. */ #include "gnunet_protocols.h" /** * Maximum size of a GNUnet message (GNUNET_SERVER_MAX_MESSAGE_SIZE) */ #define MAX_SIZE 65536 #ifndef _LINUX_IN6_H /** * This is in linux/include/net/ipv6.h, but not always exported... */ struct in6_ifreq { struct in6_addr ifr6_addr; uint32_t ifr6_prefixlen; unsigned int ifr6_ifindex; }; #endif /** * Name and full path of IPTABLES binary. */ static const char *sbin_iptables; /** * Name and full path of sysctl binary */ static const char *sbin_sysctl; /** * Name and full path of IPTABLES binary. */ static const char *sbin_ip; /** * Port for DNS traffic. */ #define DNS_PORT "53" /** * Marker we set for our hijacked DNS traffic. We use GNUnet's * port (2086) plus the DNS port (53) in HEX to make a 32-bit mark * (which is hopefully long enough to not collide); so * 0x08260035 = 136708149 (hopefully unique enough...). */ #define DNS_MARK "136708149" /** * Table we use for our DNS rules. 0-255 is the range and * 0, 253, 254 and 255 are already reserved. As this is about * DNS and as "53" is likely (fingers crossed!) high enough to * not usually conflict with a normal user's setup, we use 53 * to give a hint that this has something to do with DNS. */ #define DNS_TABLE "53" /** * Control pipe for shutdown via signal. [0] is the read end, * [1] is the write end. */ static int cpipe[2]; /** * Signal handler called to initiate "nice" shutdown. Signals select * loop via non-bocking pipe 'cpipe'. * * @param signal signal number of the signal (not used) */ static void signal_handler (int signal) { /* ignore return value, as the signal handler could theoretically be called many times before the shutdown can actually happen */ (void) write (cpipe[1], "K", 1); } /** * Open '/dev/null' and make the result the given * file descriptor. * * @param target_fd desired FD to point to /dev/null * @param flags open flags (O_RDONLY, O_WRONLY) */ static void open_dev_null (int target_fd, int flags) { int fd; fd = open ("/dev/null", flags); if (-1 == fd) abort (); if (fd == target_fd) return; if (-1 == dup2 (fd, target_fd)) { (void) close (fd); abort (); } (void) close (fd); } /** * Run the given command and wait for it to complete. * * @param file name of the binary to run * @param cmd command line arguments (as given to 'execv') * @return 0 on success, 1 on any error */ static int fork_and_exec (const char *file, char *const cmd[]) { int status; pid_t pid; pid_t ret; pid = fork (); if (-1 == pid) { fprintf (stderr, "fork failed: %s\n", strerror (errno)); return 1; } if (0 == pid) { /* we are the child process */ /* close stdin/stdout to not cause interference with the helper's main protocol! */ (void) close (0); open_dev_null (0, O_RDONLY); (void) close (1); open_dev_null (1, O_WRONLY); (void) execv (file, cmd); /* can only get here on error */ fprintf (stderr, "exec `%s' failed: %s\n", file, strerror (errno)); _exit (1); } /* keep running waitpid as long as the only error we get is 'EINTR' */ while ( (-1 == (ret = waitpid (pid, &status, 0))) && (errno == EINTR) ); if (-1 == ret) { fprintf (stderr, "waitpid failed: %s\n", strerror (errno)); return 1; } if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status)))) return 1; /* child process completed and returned success, we're happy */ return 0; } /** * Creates a tun-interface called dev; * * @param dev is asumed to point to a char[IFNAMSIZ] * if *dev == '\\0', uses the name supplied by the kernel; * @return the fd to the tun or -1 on error */ static int init_tun (char *dev) { struct ifreq ifr; int fd; if (NULL == dev) { errno = EINVAL; return -1; } if (-1 == (fd = open ("/dev/net/tun", O_RDWR))) { fprintf (stderr, "Error opening `%s': %s\n", "/dev/net/tun", strerror (errno)); return -1; } if (fd >= FD_SETSIZE) { fprintf (stderr, "File descriptor to large: %d", fd); (void) close (fd); return -1; } memset (&ifr, 0, sizeof (ifr)); ifr.ifr_flags = IFF_TUN; if ('\0' != *dev) strncpy (ifr.ifr_name, dev, IFNAMSIZ); if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr)) { fprintf (stderr, "Error with ioctl on `%s': %s\n", "/dev/net/tun", strerror (errno)); (void) close (fd); return -1; } strcpy (dev, ifr.ifr_name); return fd; } /** * @brief Sets the IPv6-Address given in address on the interface dev * * @param dev the interface to configure * @param address the IPv6-Address * @param prefix_len the length of the network-prefix */ static void set_address6 (const char *dev, const char *address, unsigned long prefix_len) { struct ifreq ifr; struct in6_ifreq ifr6; struct sockaddr_in6 sa6; int fd; /* * parse the new address */ memset (&sa6, 0, sizeof (struct sockaddr_in6)); sa6.sin6_family = AF_INET6; if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr)) { fprintf (stderr, "Failed to parse IPv6 address `%s': %s\n", address, strerror (errno)); exit (1); } if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0))) { fprintf (stderr, "Error creating IPv6 socket: %s (ignored)\n", strerror (errno)); /* ignore error, maybe only IPv4 works on this system! */ return; } memset (&ifr, 0, sizeof (struct ifreq)); /* * Get the index of the if */ strncpy (ifr.ifr_name, dev, IFNAMSIZ); if (-1 == ioctl (fd, SIOGIFINDEX, &ifr)) { fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } memset (&ifr6, 0, sizeof (struct in6_ifreq)); ifr6.ifr6_addr = sa6.sin6_addr; ifr6.ifr6_ifindex = ifr.ifr_ifindex; ifr6.ifr6_prefixlen = prefix_len; /* * Set the address */ if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Get the flags */ if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Add the UP and RUNNING flags */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } if (0 != close (fd)) { fprintf (stderr, "close failed: %s\n", strerror (errno)); exit (1); } } /** * @brief Sets the IPv4-Address given in address on the interface dev * * @param dev the interface to configure * @param address the IPv4-Address * @param mask the netmask */ static void set_address4 (const char *dev, const char *address, const char *mask) { int fd; struct sockaddr_in *addr; struct ifreq ifr; memset (&ifr, 0, sizeof (struct ifreq)); addr = (struct sockaddr_in *) &(ifr.ifr_addr); addr->sin_family = AF_INET; /* * Parse the address */ if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr)) { fprintf (stderr, "Failed to parse IPv4 address `%s': %s\n", address, strerror (errno)); exit (1); } if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0))) { fprintf (stderr, "Error creating IPv4 socket: %s\n", strerror (errno)); exit (1); } strncpy (ifr.ifr_name, dev, IFNAMSIZ); /* * Set the address */ if (-1 == ioctl (fd, SIOCSIFADDR, &ifr)) { fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Parse the netmask */ addr = (struct sockaddr_in *) &(ifr.ifr_netmask); if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr)) { fprintf (stderr, "Failed to parse address `%s': %s\n", mask, strerror (errno)); (void) close (fd); exit (1); } /* * Set the netmask */ if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Get the flags */ if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } /* * Add the UP and RUNNING flags */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) { fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); (void) close (fd); exit (1); } if (0 != close (fd)) { fprintf (stderr, "close failed: %s\n", strerror (errno)); (void) close (fd); exit (1); } } /** * Start forwarding to and from the tunnel. This function runs with * "reduced" priviledges (saved UID is still 0, but effective UID is * the real user ID). * * @param fd_tun tunnel FD */ static void run (int fd_tun) { /* * The buffer filled by reading from fd_tun */ unsigned char buftun[MAX_SIZE]; ssize_t buftun_size = 0; unsigned char *buftun_read = NULL; /* * The buffer filled by reading from stdin */ unsigned char bufin[MAX_SIZE]; ssize_t bufin_size = 0; size_t bufin_rpos = 0; unsigned char *bufin_read = NULL; fd_set fds_w; fd_set fds_r; int max; while (1) { FD_ZERO (&fds_w); FD_ZERO (&fds_r); /* * We are supposed to read and the buffer is empty * -> select on read from tun */ if (0 == buftun_size) FD_SET (fd_tun, &fds_r); /* * We are supposed to read and the buffer is not empty * -> select on write to stdout */ if (0 < buftun_size) FD_SET (1, &fds_w); /* * We are supposed to write and the buffer is empty * -> select on read from stdin */ if (NULL == bufin_read) FD_SET (0, &fds_r); /* * We are supposed to write and the buffer is not empty * -> select on write to tun */ if (NULL != bufin_read) FD_SET (fd_tun, &fds_w); FD_SET (cpipe[0], &fds_r); max = (fd_tun > cpipe[0]) ? fd_tun : cpipe[0]; int r = select (max + 1, &fds_r, &fds_w, NULL, NULL); if (-1 == r) { if (EINTR == errno) continue; fprintf (stderr, "select failed: %s\n", strerror (errno)); return; } if (r > 0) { if (FD_ISSET (cpipe[0], &fds_r)) return; /* aborted by signal */ if (FD_ISSET (fd_tun, &fds_r)) { buftun_size = read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader), MAX_SIZE - sizeof (struct GNUNET_MessageHeader)); if (-1 == buftun_size) { if ( (errno == EINTR) || (errno == EAGAIN) ) { buftun_size = 0; continue; } fprintf (stderr, "read-error: %s\n", strerror (errno)); return; } if (0 == buftun_size) { fprintf (stderr, "EOF on tun\n"); return; } buftun_read = buftun; { struct GNUNET_MessageHeader *hdr = (struct GNUNET_MessageHeader *) buftun; buftun_size += sizeof (struct GNUNET_MessageHeader); hdr->type = htons (GNUNET_MESSAGE_TYPE_DNS_HELPER); hdr->size = htons (buftun_size); } } else if (FD_ISSET (1, &fds_w)) { ssize_t written = write (1, buftun_read, buftun_size); if (-1 == written) { if ( (errno == EINTR) || (errno == EAGAIN) ) continue; fprintf (stderr, "write-error to stdout: %s\n", strerror (errno)); return; } if (0 == written) { fprintf (stderr, "write returned 0\n"); return; } buftun_size -= written; buftun_read += written; } if (FD_ISSET (0, &fds_r)) { bufin_size = read (0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos); if (-1 == bufin_size) { bufin_read = NULL; if ( (errno == EINTR) || (errno == EAGAIN) ) continue; fprintf (stderr, "read-error: %s\n", strerror (errno)); return; } if (0 == bufin_size) { bufin_read = NULL; fprintf (stderr, "EOF on stdin\n"); return; } { struct GNUNET_MessageHeader *hdr; PROCESS_BUFFER: bufin_rpos += bufin_size; if (bufin_rpos < sizeof (struct GNUNET_MessageHeader)) continue; hdr = (struct GNUNET_MessageHeader *) bufin; if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_DNS_HELPER) { fprintf (stderr, "protocol violation!\n"); return; } if (ntohs (hdr->size) > bufin_rpos) continue; bufin_read = bufin + sizeof (struct GNUNET_MessageHeader); bufin_size = ntohs (hdr->size) - sizeof (struct GNUNET_MessageHeader); bufin_rpos -= bufin_size + sizeof (struct GNUNET_MessageHeader); } } else if (FD_ISSET (fd_tun, &fds_w)) { ssize_t written = write (fd_tun, bufin_read, bufin_size); if (-1 == written) { if ( (errno == EINTR) || (errno == EAGAIN) ) continue; fprintf (stderr, "write-error to tun: %s\n", strerror (errno)); return; } if (0 == written) { fprintf (stderr, "write returned 0\n"); return; } { bufin_size -= written; bufin_read += written; if (0 == bufin_size) { memmove (bufin, bufin_read, bufin_rpos); bufin_read = NULL; /* start reading again */ bufin_size = 0; goto PROCESS_BUFFER; } } } } } } /** * Main function of "gnunet-helper-dns", which opens a VPN tunnel interface, * redirects all outgoing DNS traffic (except from the specified port) to that * interface and then passes traffic from and to the interface via stdin/stdout. * * Once stdin/stdout close or have other errors, the tunnel is closed and the * DNS traffic redirection is stopped. * * @param argc number of arguments * @param argv 0: binary name (should be "gnunet-helper-vpn") * 1: tunnel interface name (typically "gnunet-dns") * 2: IPv6 address for the tunnel ("FE80::1") * 3: IPv6 netmask length in bits ("64") * 4: IPv4 address for the tunnel ("1.2.3.4") * 5: IPv4 netmask ("255.255.0.0") * @return 0 on success, otherwise code indicating type of error: * 1 wrong number of arguments * 2 invalid arguments (i.e. port number / prefix length wrong) * 3 iptables not executable * 4 ip not executable * 5 failed to initialize tunnel interface * 6 failed to initialize control pipe * 8 failed to change routing table, cleanup successful * 9-23 failed to change routing table and failed to undo some changes to routing table * 24 failed to drop privs * 25-39 failed to drop privs and then failed to undo some changes to routing table * 40 failed to regain privs * 41-55 failed to regain prisv and then failed to undo some changes to routing table * 254 insufficient priviledges * 255 failed to handle kill signal properly */ int main (int argc, char *const*argv) { int r; char dev[IFNAMSIZ]; char mygid[32]; int fd_tun; uid_t uid; if (6 != argc) { fprintf (stderr, "Fatal: must supply 6 arguments!\n"); return 1; } /* assert privs so we can modify the firewall rules! */ uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, 0, 0)) { fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno)); return 254; } #else if (0 != seteuid (0)) { fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); return 254; } #endif /* verify that the binaries were care about are executable */ if (0 == access ("/sbin/iptables", X_OK)) sbin_iptables = "/sbin/iptables"; else if (0 == access ("/usr/sbin/iptables", X_OK)) sbin_iptables = "/usr/sbin/iptables"; else { fprintf (stderr, "Fatal: executable iptables not found in approved directories: %s\n", strerror (errno)); return 3; } if (0 == access ("/sbin/ip", X_OK)) sbin_ip = "/sbin/ip"; else if (0 == access ("/usr/sbin/ip", X_OK)) sbin_ip = "/usr/sbin/ip"; else { fprintf (stderr, "Fatal: executable ip not found in approved directories: %s\n", strerror (errno)); return 4; } if (0 == access ("/sbin/sysctl", X_OK)) sbin_sysctl = "/sbin/sysctl"; else if (0 == access ("/usr/sbin/sysctl", X_OK)) sbin_sysctl = "/usr/sbin/sysctl"; else { fprintf (stderr, "Fatal: executable sysctl not found in approved directories: %s\n", strerror (errno)); return 5; } /* setup 'mygid' string */ snprintf (mygid, sizeof (mygid), "%d", (int) getegid()); /* do not die on SIGPIPE */ if (SIG_ERR == signal (SIGPIPE, SIG_IGN)) { fprintf (stderr, "Failed to protect against SIGPIPE: %s\n", strerror (errno)); return 7; } /* setup pipe to shutdown nicely on SIGINT */ if (0 != pipe (cpipe)) { fprintf (stderr, "Fatal: could not setup control pipe: %s\n", strerror (errno)); return 6; } if (cpipe[0] >= FD_SETSIZE) { fprintf (stderr, "Pipe file descriptor to large: %d", cpipe[0]); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } { /* make pipe non-blocking, as we theoretically could otherwise block in the signal handler */ int flags = fcntl (cpipe[1], F_GETFL); if (-1 == flags) { fprintf (stderr, "Failed to read flags for pipe: %s", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } flags |= O_NONBLOCK; if (0 != fcntl (cpipe[1], F_SETFL, flags)) { fprintf (stderr, "Failed to make pipe non-blocking: %s", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 6; } } if ( (SIG_ERR == signal (SIGTERM, &signal_handler)) || #if (SIGTERM != GNUNET_TERM_SIG) (SIG_ERR == signal (GNUNET_TERM_SIG, &signal_handler)) || #endif (SIG_ERR == signal (SIGINT, &signal_handler)) || (SIG_ERR == signal (SIGHUP, &signal_handler)) ) { fprintf (stderr, "Fatal: could not initialize signal handler: %s\n", strerror (errno)); (void) close (cpipe[0]); (void) close (cpipe[1]); return 7; } /* get interface name */ strncpy (dev, argv[1], IFNAMSIZ); dev[IFNAMSIZ - 1] = '\0'; /* Disable rp filtering */ { char *const sysctl_args[] = {"sysctl", "-w", "net.ipv4.conf.all.rp_filter=0", NULL}; char *const sysctl_args2[] = {"sysctl", "-w", "net.ipv4.conf.default.rp_filter=0", NULL}; if ((0 != fork_and_exec (sbin_sysctl, sysctl_args)) || (0 != fork_and_exec (sbin_sysctl, sysctl_args2))) { fprintf (stderr, "Failed to disable rp filtering.\n"); return 5; } } /* now open virtual interface (first part that requires root) */ if (-1 == (fd_tun = init_tun (dev))) { fprintf (stderr, "Fatal: could not initialize tun-interface\n"); (void) signal (SIGTERM, SIG_IGN); #if (SIGTERM != GNUNET_TERM_SIG) (void) signal (GNUNET_TERM_SIG, SIG_IGN); #endif (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return 5; } /* now set interface addresses */ { const char *address = argv[2]; long prefix_len = atol (argv[3]); if ((prefix_len < 1) || (prefix_len > 127)) { fprintf (stderr, "Fatal: prefix_len out of range\n"); (void) signal (SIGTERM, SIG_IGN); #if (SIGTERM != GNUNET_TERM_SIG) (void) signal (GNUNET_TERM_SIG, SIG_IGN); #endif (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return 2; } set_address6 (dev, address, prefix_len); } { const char *address = argv[4]; const char *mask = argv[5]; set_address4 (dev, address, mask); } /* update routing tables -- next part why we need SUID! */ /* Forward everything from our EGID (which should only be held by the 'gnunet-service-dns') and with destination to port 53 on UDP, without hijacking */ r = 8; /* failed to fully setup routing table */ { char *const mangle_args[] = { "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p", "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", NULL }; if (0 != fork_and_exec (sbin_iptables, mangle_args)) goto cleanup_rest; } /* Mark all of the other DNS traffic using our mark DNS_MARK */ { char *const mark_args[] = { "iptables", "-t", "mangle", "-I", "OUTPUT", "2", "-p", "udp", "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL }; if (0 != fork_and_exec (sbin_iptables, mark_args)) goto cleanup_mangle_1; } /* Forward all marked DNS traffic to our DNS_TABLE */ { char *const forward_args[] = { "ip", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, forward_args)) goto cleanup_mark_2; } /* Finally, add rule in our forwarding table to pass to our virtual interface */ { char *const route_args[] = { "ip", "route", "add", "default", "dev", dev, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, route_args)) goto cleanup_forward_3; } /* drop privs *except* for the saved UID; this is not perfect, but better than doing nothing */ #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, 0)) { fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); r = 24; goto cleanup_route_4; } #else /* Note: no 'setuid' here as we must keep our saved UID as root */ if (0 != seteuid (uid)) { fprintf (stderr, "Failed to seteuid: %s\n", strerror (errno)); r = 24; goto cleanup_route_4; } #endif r = 0; /* did fully setup routing table (if nothing else happens, we were successful!) */ /* now forward until we hit a problem */ run (fd_tun); /* now need to regain privs so we can remove the firewall rules we added! */ #ifdef HAVE_SETRESUID if (0 != setresuid (uid, 0, 0)) { fprintf (stderr, "Failed to setresuid back to root: %s\n", strerror (errno)); r = 40; goto cleanup_route_4; } #else if (0 != seteuid (0)) { fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); r = 40; goto cleanup_route_4; } #endif /* update routing tables again -- this is why we could not fully drop privs */ /* now undo updating of routing tables; normal exit or clean-up-on-error case */ cleanup_route_4: { char *const route_clean_args[] = { "ip", "route", "del", "default", "dev", dev, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, route_clean_args)) r += 1; } cleanup_forward_3: { char *const forward_clean_args[] = { "ip", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL }; if (0 != fork_and_exec (sbin_ip, forward_clean_args)) r += 2; } cleanup_mark_2: { char *const mark_clean_args[] = { "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL }; if (0 != fork_and_exec (sbin_iptables, mark_clean_args)) r += 4; } cleanup_mangle_1: { char *const mangle_clean_args[] = { "iptables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", NULL }; if (0 != fork_and_exec (sbin_iptables, mangle_clean_args)) r += 8; } cleanup_rest: /* close virtual interface */ (void) close (fd_tun); /* remove signal handler so we can close the pipes */ (void) signal (SIGTERM, SIG_IGN); #if (SIGTERM != GNUNET_TERM_SIG) (void) signal (GNUNET_TERM_SIG, SIG_IGN); #endif (void) signal (SIGINT, SIG_IGN); (void) signal (SIGHUP, SIG_IGN); (void) close (cpipe[0]); (void) close (cpipe[1]); return r; } /* end of gnunet-helper-dns.c */ gnunet-0.10.1/src/dns/dnsstub.c0000644000175000017500000003246212255010512013213 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dns/dnsstub.c * @brief DNS stub resolver which sends DNS requests to an actual resolver * @author Christian Grothoff */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_dnsstub_lib.h" /** * Timeout for an external (Internet-DNS) DNS resolution */ #define REQUEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * How many DNS sockets do we open at most at the same time? * (technical socket maximum is this number x2 for IPv4+IPv6) */ #define DNS_SOCKET_MAX 128 /** * UDP socket we are using for sending DNS requests to the Internet. */ struct GNUNET_DNSSTUB_RequestSocket { /** * UDP socket we use for this request for IPv4 */ struct GNUNET_NETWORK_Handle *dnsout4; /** * UDP socket we use for this request for IPv6 */ struct GNUNET_NETWORK_Handle *dnsout6; /** * Function to call with result. */ GNUNET_DNSSTUB_ResultCallback rc; /** * Closure for 'rc'. */ void *rc_cls; /** * Task for reading from dnsout4 and dnsout6. */ GNUNET_SCHEDULER_TaskIdentifier read_task; /** * When should this request time out? */ struct GNUNET_TIME_Absolute timeout; /** * Address we sent the DNS request to. */ struct sockaddr_storage addr; /** * Number of bytes in 'addr'. */ socklen_t addrlen; }; /** * Handle to the stub resolver. */ struct GNUNET_DNSSTUB_Context { /** * Array of all open sockets for DNS requests. */ struct GNUNET_DNSSTUB_RequestSocket sockets[DNS_SOCKET_MAX]; /** * IP address to use for the DNS server if we are a DNS exit service * (for VPN via mesh); otherwise NULL. */ char *dns_exit; }; /** * We're done with a GNUNET_DNSSTUB_RequestSocket, close it for now. * * @param rs request socket to clean up */ static void cleanup_rs (struct GNUNET_DNSSTUB_RequestSocket *rs) { if (NULL != rs->dnsout4) { GNUNET_NETWORK_socket_close (rs->dnsout4); rs->dnsout4 = NULL; } if (NULL != rs->dnsout6) { GNUNET_NETWORK_socket_close (rs->dnsout6); rs->dnsout6 = NULL; } if (GNUNET_SCHEDULER_NO_TASK != rs->read_task) { GNUNET_SCHEDULER_cancel (rs->read_task); rs->read_task = GNUNET_SCHEDULER_NO_TASK; } } /** * Open source port for sending DNS requests * * @param af AF_INET or AF_INET6 * @return GNUNET_OK on success */ static struct GNUNET_NETWORK_Handle * open_socket (int af) { struct sockaddr_in a4; struct sockaddr_in6 a6; struct sockaddr *sa; socklen_t alen; struct GNUNET_NETWORK_Handle *ret; ret = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, 0); if (NULL == ret) return NULL; switch (af) { case AF_INET: memset (&a4, 0, alen = sizeof (struct sockaddr_in)); sa = (struct sockaddr *) &a4; break; case AF_INET6: memset (&a6, 0, alen = sizeof (struct sockaddr_in6)); sa = (struct sockaddr *) &a6; break; default: GNUNET_break (0); GNUNET_NETWORK_socket_close (ret); return NULL; } sa->sa_family = af; if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret, sa, alen)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not bind to any port: %s\n"), STRERROR (errno)); GNUNET_NETWORK_socket_close (ret); return NULL; } return ret; } /** * Read a DNS response from the (unhindered) UDP-Socket * * @param cls socket to read from * @param tc scheduler context (must be shutdown or read ready) */ static void read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); /** * Get a socket of the specified address family to send out a * UDP DNS request to the Internet. * * @param ctx the DNSSTUB context * @param af desired address family * @return NULL on error (given AF not "supported") */ static struct GNUNET_DNSSTUB_RequestSocket * get_request_socket (struct GNUNET_DNSSTUB_Context *ctx, int af) { struct GNUNET_DNSSTUB_RequestSocket *rs; struct GNUNET_NETWORK_FDSet *rset; rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, DNS_SOCKET_MAX)]; rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT); switch (af) { case AF_INET: if (NULL == rs->dnsout4) rs->dnsout4 = open_socket (AF_INET); break; case AF_INET6: if (NULL == rs->dnsout6) rs->dnsout6 = open_socket (AF_INET6); break; default: return NULL; } if (GNUNET_SCHEDULER_NO_TASK != rs->read_task) { GNUNET_SCHEDULER_cancel (rs->read_task); rs->read_task = GNUNET_SCHEDULER_NO_TASK; } if ( (NULL == rs->dnsout4) && (NULL == rs->dnsout6) ) return NULL; rset = GNUNET_NETWORK_fdset_create (); if (NULL != rs->dnsout4) GNUNET_NETWORK_fdset_set (rset, rs->dnsout4); if (NULL != rs->dnsout6) GNUNET_NETWORK_fdset_set (rset, rs->dnsout6); rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, REQUEST_TIMEOUT, rset, NULL, &read_response, rs); GNUNET_NETWORK_fdset_destroy (rset); return rs; } /** * Perform DNS resolution. * * @param ctx stub resolver to use * @param sa the socket address * @param sa_len the socket length * @param request DNS request to transmit * @param request_len number of bytes in msg * @param rc function to call with result * @param rc_cls closure for 'rc' * @return socket used for the request, NULL on error */ struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx, const struct sockaddr *sa, socklen_t sa_len, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls) { struct GNUNET_DNSSTUB_RequestSocket *rs; struct GNUNET_NETWORK_Handle *ret; int af; af = sa->sa_family; if (NULL == (rs = get_request_socket (ctx, af))) return NULL; if (NULL != rs->dnsout4) ret = rs->dnsout4; else ret = rs->dnsout6; GNUNET_assert (NULL != ret); memcpy (&rs->addr, sa, sa_len); rs->addrlen = sa_len; rs->rc = rc; rs->rc_cls = rc_cls; if (GNUNET_SYSERR == GNUNET_NETWORK_socket_sendto (ret, request, request_len, sa, sa_len)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to send DNS request to %s\n"), GNUNET_a2s (sa, sa_len)); else GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Sent DNS request to %s\n"), GNUNET_a2s (sa, sa_len)); return rs; } /** * Perform DNS resolution using our default IP from init. * * @param ctx stub resolver to use * @param request DNS request to transmit * @param request_len number of bytes in msg * @param rc function to call with result * @param rc_cls closure for 'rc' * @return socket used for the request, NULL on error */ struct GNUNET_DNSSTUB_RequestSocket * GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx, const void *request, size_t request_len, GNUNET_DNSSTUB_ResultCallback rc, void *rc_cls) { int af; struct sockaddr_in v4; struct sockaddr_in6 v6; struct sockaddr *sa; socklen_t salen; struct GNUNET_NETWORK_Handle *dnsout; struct GNUNET_DNSSTUB_RequestSocket *rs; memset (&v4, 0, sizeof (v4)); memset (&v6, 0, sizeof (v6)); if (1 == inet_pton (AF_INET, ctx->dns_exit, &v4.sin_addr)) { salen = sizeof (v4); v4.sin_family = AF_INET; v4.sin_port = htons (53); #if HAVE_SOCKADDR_IN_SIN_LEN v4.sin_len = (u_char) salen; #endif sa = (struct sockaddr *) &v4; af = AF_INET; } else if (1 == inet_pton (AF_INET6, ctx->dns_exit, &v6.sin6_addr)) { salen = sizeof (v6); v6.sin6_family = AF_INET6; v6.sin6_port = htons (53); #if HAVE_SOCKADDR_IN_SIN_LEN v6.sin6_len = (u_char) salen; #endif sa = (struct sockaddr *) &v6; af = AF_INET6; } else { GNUNET_break (0); return NULL; } if (NULL == (rs = get_request_socket (ctx, af))) return NULL; if (NULL != rs->dnsout4) dnsout = rs->dnsout4; else dnsout = rs->dnsout6; if (NULL == dnsout) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Configured DNS exit `%s' is not working / valid.\n"), ctx->dns_exit); return NULL; } memcpy (&rs->addr, sa, salen); rs->addrlen = salen; rs->rc = rc; rs->rc_cls = rc_cls; if (GNUNET_SYSERR == GNUNET_NETWORK_socket_sendto (dnsout, request, request_len, sa, salen)) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to send DNS request to %s\n"), GNUNET_a2s (sa, salen)); rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT); return rs; } /** * Actually do the reading of a DNS packet from our UDP socket and see * if we have a valid, matching, pending request. * * @param rs request socket with callback details * @param dnsout socket to read from * @return GNUNET_OK on success, GNUNET_NO on drop, GNUNET_SYSERR on IO-errors (closed socket) */ static int do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs, struct GNUNET_NETWORK_Handle *dnsout) { struct sockaddr_storage addr; socklen_t addrlen; struct GNUNET_TUN_DnsHeader *dns; ssize_t r; int len; #ifndef MINGW if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len)) { /* conservative choice: */ len = UINT16_MAX; } #else /* port the code above? */ len = UINT16_MAX; #endif GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving %d byte DNS reply\n", len); { unsigned char buf[len] GNUNET_ALIGN; addrlen = sizeof (addr); memset (&addr, 0, sizeof (addr)); r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf), (struct sockaddr*) &addr, &addrlen); if (-1 == r) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom"); GNUNET_NETWORK_socket_close (dnsout); return GNUNET_SYSERR; } if (sizeof (struct GNUNET_TUN_DnsHeader) > r) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Received DNS response that is too small (%u bytes)"), r); return GNUNET_NO; } dns = (struct GNUNET_TUN_DnsHeader *) buf; if ( (addrlen != rs->addrlen) || (0 != memcmp (&rs->addr, &addr, addrlen)) || (0 == GNUNET_TIME_absolute_get_remaining (rs->timeout).rel_value_us) ) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request timeout or invalid sender address; ignoring reply\n"); return GNUNET_NO; } if (NULL != rs->rc) rs->rc (rs->rc_cls, rs, dns, r); } return GNUNET_OK; } /** * Read a DNS response from the (unhindered) UDP-Socket * * @param cls socket to read from * @param tc scheduler context (must be shutdown or read ready) */ static void read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DNSSTUB_RequestSocket *rs = cls; struct GNUNET_NETWORK_FDSet *rset; rs->read_task = GNUNET_SCHEDULER_NO_TASK; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) { /* timeout or shutdown */ cleanup_rs (rs); return; } /* read and process ready sockets */ if ((NULL != rs->dnsout4) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout4)) && (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout4))) rs->dnsout4 = NULL; if ((NULL != rs->dnsout6) && (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout6)) && (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout6))) rs->dnsout6 = NULL; /* re-schedule read task */ rset = GNUNET_NETWORK_fdset_create (); if (NULL != rs->dnsout4) GNUNET_NETWORK_fdset_set (rset, rs->dnsout4); if (NULL != rs->dnsout6) GNUNET_NETWORK_fdset_set (rset, rs->dnsout6); rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, GNUNET_TIME_absolute_get_remaining (rs->timeout), rset, NULL, &read_response, rs); GNUNET_NETWORK_fdset_destroy (rset); } /** * Cancel DNS resolution. * * @param rs resolution to cancel */ void GNUNET_DNSSTUB_resolve_cancel (struct GNUNET_DNSSTUB_RequestSocket *rs) { rs->rc = NULL; } /** * Start a DNS stub resolver. * * @param dns_ip target IP address to use * @return NULL on error */ struct GNUNET_DNSSTUB_Context * GNUNET_DNSSTUB_start (const char *dns_ip) { struct GNUNET_DNSSTUB_Context *ctx; ctx = GNUNET_new (struct GNUNET_DNSSTUB_Context); if (NULL != dns_ip) ctx->dns_exit = GNUNET_strdup (dns_ip); return ctx; } /** * Cleanup DNSSTUB resolver. * * @param ctx stub resolver to clean up */ void GNUNET_DNSSTUB_stop (struct GNUNET_DNSSTUB_Context *ctx) { unsigned int i; for (i=0;isockets[i]); if (NULL != ctx->dns_exit) { GNUNET_free (ctx->dns_exit); ctx->dns_exit = NULL; } GNUNET_free (ctx); } /* end of dnsstub.c */ gnunet-0.10.1/src/dns/gnunet-service-dns.c0000644000175000017500000007551612255010512015260 00000000000000/* This file is part of GNUnet. (C) 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** * @file dns/gnunet-service-dns.c * @brief service to intercept and modify DNS queries (and replies) of this system * @author Christian Grothoff * * For "secure" interaction with the legacy DNS system, we permit * replies only to arrive within a 5s window (and they must match * ports, IPs and request IDs). Furthermore, we let the OS pick a * source port, opening up to 128 sockets per address family (IPv4 or * IPv6). Those sockets are closed if they are not in use for 5s * (which means they will be freshly randomized afterwards). For new * requests, we pick a random slot in the array with 128 socket slots * (and re-use an existing socket if the slot is still in use). Thus * each request will be given one of 128 random source ports, and the * 128 random source ports will also change "often" (less often if the * system is very busy, each time if we are mostly idle). At the same * time, the system will never use more than 256 UDP sockets. */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_applications.h" #include "gnunet_constants.h" #include "gnunet_protocols.h" #include "gnunet_signatures.h" #include "dns.h" #include "gnunet_dns_service.h" #include "gnunet_dnsparser_lib.h" #include "gnunet_dnsstub_lib.h" #include "gnunet_statistics_service.h" #include "gnunet_tun_lib.h" /** * Port number for DNS */ #define DNS_PORT 53 /** * Generic logging shorthand */ #define LOG(kind, ...) \ GNUNET_log_from (kind, "dns", __VA_ARGS__); /** * Phases each request goes through. */ enum RequestPhase { /** * Request has just been received. */ RP_INIT, /** * Showing the request to all monitor clients. If * client list is empty, will enter QUERY phase. */ RP_REQUEST_MONITOR, /** * Showing the request to PRE-RESOLUTION clients to find an answer. * If client list is empty, will trigger global DNS request. */ RP_QUERY, /** * Global Internet query is now pending. */ RP_INTERNET_DNS, /** * Client (or global DNS request) has resulted in a response. * Forward to all POST-RESOLUTION clients. If client list is empty, * will enter RESPONSE_MONITOR phase. */ RP_MODIFY, /** * Showing the request to all monitor clients. If * client list is empty, give the result to the hijacker (and be done). */ RP_RESPONSE_MONITOR, /** * Some client has told us to drop the request. */ RP_DROP }; /** * Entry we keep for each client. */ struct ClientRecord { /** * Kept in doubly-linked list. */ struct ClientRecord *next; /** * Kept in doubly-linked list. */ struct ClientRecord *prev; /** * Handle to the client. */ struct GNUNET_SERVER_Client *client; /** * Flags for the client. */ enum GNUNET_DNS_Flags flags; }; /** * Entry we keep for each active request. */ struct RequestRecord { /** * List of clients that still need to see this request (each entry * is set to NULL when the client is done). */ struct ClientRecord **client_wait_list; /** * Payload of the UDP packet (the UDP payload), can be either query * or already the response. */ char *payload; /** * Socket we are using to transmit this request (must match if we receive * a response). */ struct GNUNET_DNSSTUB_RequestSocket *rs; /** * Source address of the original request (for sending response). */ struct sockaddr_storage src_addr; /** * Destination address of the original request (for potential use as exit). */ struct sockaddr_storage dst_addr; /** * ID of this request, also basis for hashing. Lowest 16 bit will * be our message ID when doing a global DNS request and our index * into the 'requests' array. */ uint64_t request_id; /** * Number of bytes in payload. */ size_t payload_length; /** * Length of the client wait list. */ unsigned int client_wait_list_length; /** * In which phase this this request? */ enum RequestPhase phase; }; /** * Global return value from 'main'. */ static int global_ret; /** * The configuration to use */ static const struct GNUNET_CONFIGURATION_Handle *cfg; /** * Statistics. */ static struct GNUNET_STATISTICS_Handle *stats; /** * Handle to DNS hijacker helper process ("gnunet-helper-dns"). */ static struct GNUNET_HELPER_Handle *hijacker; /** * Command-line arguments we are giving to the hijacker process. */ static char *helper_argv[7]; /** * Head of DLL of clients we consult. */ static struct ClientRecord *clients_head; /** * Tail of DLL of clients we consult. */ static struct ClientRecord *clients_tail; /** * Our notification context. */ static struct GNUNET_SERVER_NotificationContext *nc; /** * Array of all open requests. */ static struct RequestRecord requests[UINT16_MAX + 1]; /** * Generator for unique request IDs. */ static uint64_t request_id_gen; /** * Handle to the DNS Stub resolver. */ static struct GNUNET_DNSSTUB_Context *dnsstub; /** * We're done processing a DNS request, free associated memory. * * @param rr request to clean up */ static void cleanup_rr (struct RequestRecord *rr) { GNUNET_free_non_null (rr->payload); rr->payload = NULL; rr->payload_length = 0; GNUNET_array_grow (rr->client_wait_list, rr->client_wait_list_length, 0); } /** * Task run during shutdown. * * @param cls unused * @param tc unused */ static void cleanup_task (void *cls GNUNET_UNUSED, const struct GNUNET_SCHEDULER_TaskContext *tc) { unsigned int i; GNUNET_HELPER_stop (hijacker, GNUNET_NO); hijacker = NULL; for (i=0;i<7;i++) GNUNET_free_non_null (helper_argv[i]); for (i=0;i<=UINT16_MAX;i++) cleanup_rr (&requests[i]); GNUNET_SERVER_notification_context_destroy (nc); nc = NULL; if (stats != NULL) { GNUNET_STATISTICS_destroy (stats, GNUNET_NO); stats = NULL; } if (NULL != dnsstub) { GNUNET_DNSSTUB_stop (dnsstub); dnsstub = NULL; } } /** * We're done with some request, finish processing. * * @param rr request send to the network or just clean up. */ static void request_done (struct RequestRecord *rr) { struct GNUNET_MessageHeader *hdr; size_t reply_len; uint16_t source_port; uint16_t destination_port; GNUNET_array_grow (rr->client_wait_list, rr->client_wait_list_length, 0); if (RP_RESPONSE_MONITOR != rr->phase) { /* no response, drop */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Got no response for request %llu, dropping\n", (unsigned long long) rr->request_id); cleanup_rr (rr); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting response for request %llu\n", (unsigned long long) rr->request_id); /* send response via hijacker */ reply_len = sizeof (struct GNUNET_MessageHeader); reply_len += sizeof (struct GNUNET_TUN_Layer2PacketHeader); switch (rr->src_addr.ss_family) { case AF_INET: reply_len += sizeof (struct GNUNET_TUN_IPv4Header); break; case AF_INET6: reply_len += sizeof (struct GNUNET_TUN_IPv6Header); break; default: GNUNET_break (0); cleanup_rr (rr); return; } reply_len += sizeof (struct GNUNET_TUN_UdpHeader); reply_len += rr->payload_length; if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { /* response too big, drop */ GNUNET_break (0); /* how can this be? */ cleanup_rr(rr); return; } { char buf[reply_len] GNUNET_ALIGN; size_t off; struct GNUNET_TUN_IPv4Header ip4; struct GNUNET_TUN_IPv6Header ip6; /* first, GNUnet message header */ hdr = (struct GNUNET_MessageHeader*) buf; hdr->type = htons (GNUNET_MESSAGE_TYPE_DNS_HELPER); hdr->size = htons ((uint16_t) reply_len); off = sizeof (struct GNUNET_MessageHeader); /* first, TUN header */ { struct GNUNET_TUN_Layer2PacketHeader tun; tun.flags = htons (0); if (rr->src_addr.ss_family == AF_INET) tun.proto = htons (ETH_P_IPV4); else tun.proto = htons (ETH_P_IPV6); memcpy (&buf[off], &tun, sizeof (struct GNUNET_TUN_Layer2PacketHeader)); off += sizeof (struct GNUNET_TUN_Layer2PacketHeader); } /* now IP header */ switch (rr->src_addr.ss_family) { case AF_INET: { struct sockaddr_in *src = (struct sockaddr_in *) &rr->src_addr; struct sockaddr_in *dst = (struct sockaddr_in *) &rr->dst_addr; source_port = dst->sin_port; destination_port = src->sin_port; GNUNET_TUN_initialize_ipv4_header (&ip4, IPPROTO_UDP, reply_len - off - sizeof (struct GNUNET_TUN_IPv4Header), &dst->sin_addr, &src->sin_addr); memcpy (&buf[off], &ip4, sizeof (ip4)); off += sizeof (ip4); } break; case AF_INET6: { struct sockaddr_in6 *src = (struct sockaddr_in6 *) &rr->src_addr; struct sockaddr_in6 *dst = (struct sockaddr_in6 *) &rr->dst_addr; source_port = dst->sin6_port; destination_port = src->sin6_port; GNUNET_TUN_initialize_ipv6_header (&ip6, IPPROTO_UDP, reply_len - sizeof (struct GNUNET_TUN_IPv6Header), &dst->sin6_addr, &src->sin6_addr); memcpy (&buf[off], &ip6, sizeof (ip6)); off += sizeof (ip6); } break; default: GNUNET_assert (0); } /* now UDP header */ { struct GNUNET_TUN_UdpHeader udp; udp.source_port = source_port; udp.destination_port = destination_port; udp.len = htons (reply_len - off); if (AF_INET == rr->src_addr.ss_family) GNUNET_TUN_calculate_udp4_checksum (&ip4, &udp, rr->payload, rr->payload_length); else GNUNET_TUN_calculate_udp6_checksum (&ip6, &udp, rr->payload, rr->payload_length); memcpy (&buf[off], &udp, sizeof (udp)); off += sizeof (udp); } /* now DNS payload */ { memcpy (&buf[off], rr->payload, rr->payload_length); off += rr->payload_length; } /* final checks & sending */ GNUNET_assert (off == reply_len); (void) GNUNET_HELPER_send (hijacker, hdr, GNUNET_YES, NULL, NULL); GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests answered via TUN interface"), 1, GNUNET_NO); } /* clean up, we're done */ cleanup_rr (rr); } /** * Show the payload of the given request record to the client * (and wait for a response). * * @param rr request to send to client * @param client client to send the response to */ static void send_request_to_client (struct RequestRecord *rr, struct GNUNET_SERVER_Client *client) { char buf[sizeof (struct GNUNET_DNS_Request) + rr->payload_length] GNUNET_ALIGN; struct GNUNET_DNS_Request *req; if (sizeof (buf) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_break (0); cleanup_rr (rr); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending information about request %llu to local client\n", (unsigned long long) rr->request_id); req = (struct GNUNET_DNS_Request*) buf; req->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST); req->header.size = htons (sizeof (buf)); req->reserved = htonl (0); req->request_id = rr->request_id; memcpy (&req[1], rr->payload, rr->payload_length); GNUNET_SERVER_notification_context_unicast (nc, client, &req->header, GNUNET_NO); } /** * Callback called from DNSSTUB resolver when a resolution * succeeded. * * @param cls NULL * @param rs the socket that received the response * @param dns the response itself * @param r number of bytes in dns */ static void process_dns_result (void *cls, struct GNUNET_DNSSTUB_RequestSocket *rs, const struct GNUNET_TUN_DnsHeader *dns, size_t r); /** * A client has completed its processing for this * request. Move on. * * @param rr request to process further */ static void next_phase (struct RequestRecord *rr) { struct ClientRecord *cr; int nz; unsigned int j; socklen_t salen; if (rr->phase == RP_DROP) { cleanup_rr (rr); return; } nz = -1; for (j=0;jclient_wait_list_length;j++) { if (NULL != rr->client_wait_list[j]) { nz = (int) j; break; } } if (-1 != nz) { send_request_to_client (rr, rr->client_wait_list[nz]->client); return; } /* done with current phase, advance! */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Request %llu now in phase %d\n", rr->request_id, rr->phase); switch (rr->phase) { case RP_INIT: rr->phase = RP_REQUEST_MONITOR; for (cr = clients_head; NULL != cr; cr = cr->next) { if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR)) GNUNET_array_append (rr->client_wait_list, rr->client_wait_list_length, cr); } next_phase (rr); return; case RP_REQUEST_MONITOR: rr->phase = RP_QUERY; for (cr = clients_head; NULL != cr; cr = cr->next) { if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION)) GNUNET_array_append (rr->client_wait_list, rr->client_wait_list_length, cr); } next_phase (rr); return; case RP_QUERY: switch (rr->dst_addr.ss_family) { case AF_INET: salen = sizeof (struct sockaddr_in); break; case AF_INET6: salen = sizeof (struct sockaddr_in6); break; default: GNUNET_assert (0); } rr->phase = RP_INTERNET_DNS; rr->rs = GNUNET_DNSSTUB_resolve (dnsstub, (struct sockaddr*) &rr->dst_addr, salen, rr->payload, rr->payload_length, &process_dns_result, NULL); if (NULL == rr->rs) { GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS exit failed (failed to open socket)"), 1, GNUNET_NO); cleanup_rr (rr); return; } return; case RP_INTERNET_DNS: rr->phase = RP_MODIFY; for (cr = clients_head; NULL != cr; cr = cr->next) { if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION)) GNUNET_array_append (rr->client_wait_list, rr->client_wait_list_length, cr); } next_phase (rr); return; case RP_MODIFY: rr->phase = RP_RESPONSE_MONITOR; for (cr = clients_head; NULL != cr; cr = cr->next) { if (0 != (cr->flags & GNUNET_DNS_FLAG_RESPONSE_MONITOR)) GNUNET_array_append (rr->client_wait_list, rr->client_wait_list_length, cr); } next_phase (rr); return; case RP_RESPONSE_MONITOR: request_done (rr); break; case RP_DROP: cleanup_rr (rr); break; default: GNUNET_break (0); cleanup_rr (rr); break; } } /** * A client disconnected, clean up after it. * * @param cls unused * @param client handle of client that disconnected */ static void client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct ClientRecord *cr; struct RequestRecord *rr; unsigned int i; unsigned int j; for (cr = clients_head; NULL != cr; cr = cr->next) { if (cr->client == client) { GNUNET_SERVER_client_drop (client); GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, cr); for (i=0;iclient_wait_list_length) continue; /* not in use */ for (j=0;jclient_wait_list_length;j++) { if (rr->client_wait_list[j] == cr) { rr->client_wait_list[j] = NULL; next_phase (rr); } } } GNUNET_free (cr); return; } } } /** * Callback called from DNSSTUB resolver when a resolution * succeeded. * * @param cls NULL * @param rs the socket that received the response * @param dns the response itself * @param r number of bytes in dns */ static void process_dns_result (void *cls, struct GNUNET_DNSSTUB_RequestSocket *rs, const struct GNUNET_TUN_DnsHeader *dns, size_t r) { struct RequestRecord *rr; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing DNS result from stub resolver\n"); GNUNET_assert (NULL == cls); rr = &requests[dns->id]; if ( (rr->phase != RP_INTERNET_DNS) || (rr->rs != rs) ) { /* unexpected / bogus reply */ GNUNET_STATISTICS_update (stats, gettext_noop ("# External DNS response discarded (no matching request)"), 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received DNS reply that does not match any pending request. Dropping.\n"); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a response from the stub resolver for DNS request %llu intercepted locally!\n", (unsigned long long) rr->request_id); GNUNET_free_non_null (rr->payload); rr->payload = GNUNET_malloc (r); memcpy (rr->payload, dns, r); rr->payload_length = r; next_phase (rr); } /** * We got a new client. Make sure all new DNS requests pass by its desk. * * @param cls unused * @param client the new client * @param message the init message (unused) */ static void handle_client_init (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct ClientRecord *cr; const struct GNUNET_DNS_Register *reg = (const struct GNUNET_DNS_Register*) message; cr = GNUNET_new (struct ClientRecord); cr->client = client; cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags); GNUNET_SERVER_client_keep (client); GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, cr); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * We got a response from a client. * * @param cls unused * @param client the client * @param message the response */ static void handle_client_response (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct GNUNET_DNS_Response *resp; struct RequestRecord *rr; unsigned int i; uint16_t msize; uint16_t off; msize = ntohs (message->size); if (msize < sizeof (struct GNUNET_DNS_Response)) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } resp = (const struct GNUNET_DNS_Response*) message; off = (uint16_t) resp->request_id; rr = &requests[off]; LOG (GNUNET_ERROR_TYPE_DEBUG, "Received DNS response with ID %llu from local client!\n", (unsigned long long) resp->request_id); if (rr->request_id != resp->request_id) { GNUNET_STATISTICS_update (stats, gettext_noop ("# Client response discarded (no matching request)"), 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } for (i=0;iclient_wait_list_length;i++) { if (NULL == rr->client_wait_list[i]) continue; if (rr->client_wait_list[i]->client != client) continue; rr->client_wait_list[i] = NULL; switch (ntohl (resp->drop_flag)) { case 0: /* drop */ rr->phase = RP_DROP; break; case 1: /* no change */ break; case 2: /* update */ msize -= sizeof (struct GNUNET_DNS_Response); if ( (sizeof (struct GNUNET_TUN_DnsHeader) > msize) || (RP_REQUEST_MONITOR == rr->phase) || (RP_RESPONSE_MONITOR == rr->phase) ) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); next_phase (rr); return; } GNUNET_free_non_null (rr->payload); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Changing DNS reply according to client specifications\n"); rr->payload = GNUNET_malloc (msize); rr->payload_length = msize; memcpy (rr->payload, &resp[1], msize); if (rr->phase == RP_QUERY) { /* clear wait list, we're moving to MODIFY phase next */ GNUNET_array_grow (rr->client_wait_list, rr->client_wait_list_length, 0); } /* if query changed to answer, move past DNS resolution phase... */ if ( (RP_QUERY == rr->phase) && (rr->payload_length > sizeof (struct GNUNET_TUN_DnsHeader)) && ((struct GNUNET_TUN_DnsFlags*)&(((struct GNUNET_TUN_DnsHeader*) rr->payload)->flags))->query_or_response == 1) { rr->phase = RP_INTERNET_DNS; GNUNET_array_grow (rr->client_wait_list, rr->client_wait_list_length, 0); } break; } next_phase (rr); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } /* odd, client was not on our list for the request, that ought to be an error */ GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); } /** * Functions with this signature are called whenever a complete * message is received by the tokenizer from the DNS hijack process. * * @param cls closure * @param client identification of the client * @param message the actual message, a DNS request we should handle */ static int process_helper_messages (void *cls GNUNET_UNUSED, void *client, const struct GNUNET_MessageHeader *message) { uint16_t msize; const struct GNUNET_TUN_Layer2PacketHeader *tun; const struct GNUNET_TUN_IPv4Header *ip4; const struct GNUNET_TUN_IPv6Header *ip6; const struct GNUNET_TUN_UdpHeader *udp; const struct GNUNET_TUN_DnsHeader *dns; struct RequestRecord *rr; struct sockaddr_in *srca4; struct sockaddr_in6 *srca6; struct sockaddr_in *dsta4; struct sockaddr_in6 *dsta6; LOG (GNUNET_ERROR_TYPE_DEBUG, "Intercepted message via DNS hijacker\n"); msize = ntohs (message->size); if (msize < sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader) + sizeof (struct GNUNET_TUN_IPv4Header)) { /* non-IP packet received on TUN!? */ GNUNET_break (0); return GNUNET_OK; } msize -= sizeof (struct GNUNET_MessageHeader); tun = (const struct GNUNET_TUN_Layer2PacketHeader *) &message[1]; msize -= sizeof (struct GNUNET_TUN_Layer2PacketHeader); switch (ntohs (tun->proto)) { case ETH_P_IPV4: ip4 = (const struct GNUNET_TUN_IPv4Header *) &tun[1]; ip6 = NULL; /* make compiler happy */ if ( (msize < sizeof (struct GNUNET_TUN_IPv4Header)) || (ip4->version != 4) || (ip4->header_length != sizeof (struct GNUNET_TUN_IPv4Header) / 4) || (ntohs(ip4->total_length) != msize) || (ip4->protocol != IPPROTO_UDP) ) { /* non-IP/UDP packet received on TUN (or with options) */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received malformed IPv4-UDP packet on TUN interface.\n")); return GNUNET_OK; } udp = (const struct GNUNET_TUN_UdpHeader*) &ip4[1]; msize -= sizeof (struct GNUNET_TUN_IPv4Header); break; case ETH_P_IPV6: ip4 = NULL; /* make compiler happy */ ip6 = (const struct GNUNET_TUN_IPv6Header *) &tun[1]; if ( (msize < sizeof (struct GNUNET_TUN_IPv6Header)) || (ip6->version != 6) || (ntohs (ip6->payload_length) != msize) || (ip6->next_header != IPPROTO_UDP) ) { /* non-IP/UDP packet received on TUN (or with extensions) */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received malformed IPv6-UDP packet on TUN interface.\n")); return GNUNET_OK; } udp = (const struct GNUNET_TUN_UdpHeader*) &ip6[1]; msize -= sizeof (struct GNUNET_TUN_IPv6Header); break; default: /* non-IP packet received on TUN!? */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Got non-IP packet with %u bytes and protocol %u from TUN\n"), (unsigned int) msize, ntohs (tun->proto)); return GNUNET_OK; } if ( (msize <= sizeof (struct GNUNET_TUN_UdpHeader) + sizeof (struct GNUNET_TUN_DnsHeader)) || (DNS_PORT != ntohs (udp->destination_port)) ) { /* non-DNS packet received on TUN, ignore */ GNUNET_STATISTICS_update (stats, gettext_noop ("# Non-DNS UDP packet received via TUN interface"), 1, GNUNET_NO); return GNUNET_OK; } msize -= sizeof (struct GNUNET_TUN_UdpHeader); dns = (const struct GNUNET_TUN_DnsHeader*) &udp[1]; rr = &requests[dns->id]; /* clean up from previous request */ GNUNET_free_non_null (rr->payload); rr->payload = NULL; GNUNET_array_grow (rr->client_wait_list, rr->client_wait_list_length, 0); /* setup new request */ rr->phase = RP_INIT; switch (ntohs (tun->proto)) { case ETH_P_IPV4: { srca4 = (struct sockaddr_in*) &rr->src_addr; dsta4 = (struct sockaddr_in*) &rr->dst_addr; memset (srca4, 0, sizeof (struct sockaddr_in)); memset (dsta4, 0, sizeof (struct sockaddr_in)); srca4->sin_family = AF_INET; dsta4->sin_family = AF_INET; srca4->sin_addr = ip4->source_address; dsta4->sin_addr = ip4->destination_address; srca4->sin_port = udp->source_port; dsta4->sin_port = udp->destination_port; #if HAVE_SOCKADDR_IN_SIN_LEN srca4->sin_len = sizeof (struct sockaddr_in); dsta4->sin_len = sizeof (struct sockaddr_in); #endif } break; case ETH_P_IPV6: { srca6 = (struct sockaddr_in6*) &rr->src_addr; dsta6 = (struct sockaddr_in6*) &rr->dst_addr; memset (srca6, 0, sizeof (struct sockaddr_in6)); memset (dsta6, 0, sizeof (struct sockaddr_in6)); srca6->sin6_family = AF_INET6; dsta6->sin6_family = AF_INET6; srca6->sin6_addr = ip6->source_address; dsta6->sin6_addr = ip6->destination_address; srca6->sin6_port = udp->source_port; dsta6->sin6_port = udp->destination_port; #if HAVE_SOCKADDR_IN_SIN_LEN srca6->sin6_len = sizeof (struct sockaddr_in6); dsta6->sin6_len = sizeof (struct sockaddr_in6); #endif } break; default: GNUNET_assert (0); } rr->payload = GNUNET_malloc (msize); rr->payload_length = msize; memcpy (rr->payload, dns, msize); rr->request_id = dns->id | (request_id_gen << 16); request_id_gen++; LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new DNS request %llu\n", (unsigned long long) rr->request_id); GNUNET_STATISTICS_update (stats, gettext_noop ("# DNS requests received via TUN interface"), 1, GNUNET_NO); /* start request processing state machine */ next_phase (rr); return GNUNET_OK; } /** * @param cls closure * @param server the initialized server * @param cfg_ configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *cfg_) { static const struct GNUNET_SERVER_MessageHandler handlers[] = { /* callback, cls, type, size */ {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, sizeof (struct GNUNET_DNS_Register)}, {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 0}, {NULL, NULL, 0, 0} }; char *ifc_name; char *ipv4addr; char *ipv4mask; char *ipv6addr; char *ipv6prefix; struct in_addr dns_exit4; struct in6_addr dns_exit6; char *dns_exit; char *binary; cfg = cfg_; binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-dns"); if (GNUNET_YES != GNUNET_OS_check_helper_binary (binary, GNUNET_YES, NULL)) // TODO: once we have a windows-testcase, add test parameters here { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("`%s' must be installed SUID, refusing to run\n"), binary); global_ret = 1; GNUNET_free (binary); return; } GNUNET_free (binary); stats = GNUNET_STATISTICS_create ("dns", cfg); nc = GNUNET_SERVER_notification_context_create (server, 1); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, cls); dns_exit = NULL; if ( ( (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "DNS_EXIT", &dns_exit)) || ( (1 != inet_pton (AF_INET, dns_exit, &dns_exit4)) && (1 != inet_pton (AF_INET6, dns_exit, &dns_exit6)) ) ) ) { GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "dns", "DNS_EXIT", _("need a valid IPv4 or IPv6 address\n")); GNUNET_free_non_null (dns_exit); dns_exit = NULL; } dnsstub = GNUNET_DNSSTUB_start (dns_exit); GNUNET_free_non_null (dns_exit); helper_argv[0] = GNUNET_strdup ("gnunet-dns"); if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IFNAME", &ifc_name)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No entry 'IFNAME' in configuration!\n"); GNUNET_SCHEDULER_shutdown (); return; } helper_argv[1] = ifc_name; if ( (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV6ADDR", &ipv6addr)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV6ADDR' in configuration!\n"); GNUNET_SCHEDULER_shutdown (); return; } helper_argv[2] = ipv6addr; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV6PREFIX", &ipv6prefix)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV6PREFIX' in configuration!\n"); GNUNET_SCHEDULER_shutdown (); return; } helper_argv[3] = ipv6prefix; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4ADDR", &ipv4addr)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV4ADDR' in configuration!\n"); GNUNET_SCHEDULER_shutdown (); return; } helper_argv[4] = ipv4addr; if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (cfg, "dns", "IPV4MASK", &ipv4mask)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No entry 'IPV4MASK' in configuration!\n"); GNUNET_SCHEDULER_shutdown (); return; } helper_argv[5] = ipv4mask; helper_argv[6] = NULL; hijacker = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-dns", helper_argv, &process_helper_messages, NULL, NULL); GNUNET_SERVER_add_handlers (server, handlers); GNUNET_SERVER_disconnect_notify (server, &client_disconnect, NULL); } /** * The main function for the dns service. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int main (int argc, char *const *argv) { /* make use of SGID capabilities on POSIX */ /* FIXME: this might need a port on systems without 'getresgid' */ #if HAVE_GETRESGID gid_t rgid; gid_t egid; gid_t sgid; if (-1 == getresgid (&rgid, &egid, &sgid)) { fprintf (stderr, "getresgid failed: %s\n", strerror (errno)); } else if (sgid != rgid) { if (-1 == setregid (sgid, sgid)) fprintf (stderr, "setregid failed: %s\n", strerror (errno)); } #endif return (GNUNET_OK == GNUNET_SERVICE_run (argc, argv, "dns", GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? global_ret : 1; } /* end of gnunet-service-dns.c */ gnunet-0.10.1/src/dns/test_gnunet_dns.sh0000755000175000017500000000211312147071275015132 00000000000000#!/bin/bash ME=`whoami` if [ "$ME" != "root" ] then echo "This test only works if run as root. Skipping." exit 0 fi if ! which sudo > /dev/null then echo "This test requires sudo. Skipping." exit 0 fi if [ ! -x `which sudo` ] then echo "This test requires sudo. Skipping." exit 0 fi if ! which nslookup > /dev/null then echo "This test requires nslookup. Skipping." exit 0 fi if [ ! -x `which nslookup` ] then echo "This test requires nslookup. Skipping." exit 0 fi if ! iptables -t mangle --list &> /dev/null then echo "This test requires iptables with 'mangle' support. Skipping." exit 0 fi export PATH=".:$PATH" gnunet-service-dns -c dns.conf & gnunet-dns-redirector -c dns.conf -4 127.0.0.1 & sleep 1 # need to run 'nslookup' as 'nobody', as gnunet-service-dns runs as root # and thus 'root' is excepted from DNS interception! LO=`sudo -u nobody nslookup gnunet.org | grep Address | tail -n1` if [ "$LO" != "Address: 127.0.0.1" ] then echo "Fail: got address $LO, wanted 127.0.0.1" ret=1 else echo "Test run, with success." ret=0 fi kill `jobs -p` exit $ret gnunet-0.10.1/install-sh0000755000175000017500000003325512320752057012031 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gnunet-0.10.1/depcomp0000755000175000017500000005601612320752065011401 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gnunet-0.10.1/gnunet_config.h0000644000175000017500000004550112320752103013010 00000000000000/* gnunet_config.h. Generated from gnunet_config.h.in by configure. */ /* gnunet_config.h.in. Generated from configure.ac by autoheader. */ #define _GNU_SOURCE 1 /* Define to 1 if the `closedir' function returns void instead of `int'. */ /* #undef CLOSEDIR_VOID */ /* This is a Cygwin system */ /* #undef CYGWIN */ /* This is an Apple Darwin system */ /* #undef DARWIN */ /* enable expensive heap statistics */ #define ENABLE_HEAP_STATISTICS 0 /* Define to 1 if translation of program messages to the user's native language is requested. */ #define ENABLE_NLS 1 /* have NSE send timestamp information to testbed logger */ #define ENABLE_NSE_HISTOGRAM 0 /* 1 if freed memory should be poisoned, 0 otherwise */ #define ENABLE_POISONING 0 /* Build with support for SuperMUC */ #define ENABLE_SUPERMUC 0 /* enable workarounds used on Windows (only useful for test cases) */ #define ENABLE_WINDOWS_WORKAROUNDS 0 /* Build a Mac OS X Framework */ /* #undef FRAMEWORK_BUILD */ /* This is a FreeBSD system */ /* #undef FREEBSD */ /* This is a GNU system */ /* #undef GNU */ /* Define to cull all logging calls */ /* #undef GNUNET_CULL_LOGGING */ /* This should be the default choice for the name of the first network interface */ #define GNUNET_DEFAULT_INTERFACE "eth0" /* 1 if extra logging is enabled, 2 for very verbose extra logging, 0 otherwise */ #define GNUNET_EXTRA_LOGGING GNUNET_NO /* Define to 1 if you have the header file. */ #define HAVE_ARGZ_H 1 /* Define to 1 if you have the header file. */ #define HAVE_ARPA_INET_H 1 /* Define to 1 if you have the `atoll' function. */ #define HAVE_ATOLL 1 /* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework. */ /* #undef HAVE_CFLOCALECOPYCURRENT */ /* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework. */ /* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ /* Define to 1 if your system has a working `chown' function. */ #define HAVE_CHOWN 1 /* Define to 1 if you have the header file. */ #define HAVE_CTYPE_H 1 /* Define if the GNU dcgettext() function is already present or preinstalled. */ #define HAVE_DCGETTEXT 1 /* Define to 1 if you have the declaration of `gcry_mpi_set_opaque_copy', and to 0 if you don't. */ #define HAVE_DECL_GCRY_MPI_SET_OPAQUE_COPY 0 /* Define to 1 if you have the declaration of `_stati64', and to 0 if you don't. */ #define HAVE_DECL__STATI64 0 /* Define to 1 if you have the header file, and it defines `DIR'. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ /* #undef HAVE_DOPRNT */ /* Define to 1 if you have the header file. */ #define HAVE_ENDIAN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_EXECINFO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_EXTRACTOR_H 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if you have the `freeifaddrs' function. */ #define HAVE_FREEIFADDRS 1 /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #define HAVE_FSEEKO 1 /* Define this if getaddrinfo() is available */ #define HAVE_GETADDRINFO 1 /* Define this if gethostbyaddr() is available */ #define HAVE_GETHOSTBYADDR 1 /* Define this if gethostbyname() is available */ #define HAVE_GETHOSTBYNAME 1 /* Define to 1 if you have the `gethostbyname2' function. */ #define HAVE_GETHOSTBYNAME2 1 /* Define this if gethostname() is available */ #define HAVE_GETHOSTNAME 1 /* Define to 1 if you have the `getifaddrs' function. */ #define HAVE_GETIFADDRS 1 /* getloadavg supported */ #define HAVE_GETLOADAVG 1 /* Define this if getnameinfo() is available */ #define HAVE_GETNAMEINFO 1 /* Define to 1 if you have the `getpeereid' function. */ /* #undef HAVE_GETPEEREID */ /* Define to 1 if you have the `getpeerucred' function. */ /* #undef HAVE_GETPEERUCRED */ /* Define to 1 if you have the `getresgid' function. */ #define HAVE_GETRESGID 1 /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define to 1 if you have the `getrusage' function. */ #define HAVE_GETRUSAGE 1 /* Define if the GNU gettext() function is already present or preinstalled. */ #define HAVE_GETTEXT 1 /* Define to 1 if you have the header file. */ #define HAVE_GLPK_H 1 /* Define to 1 if `presolve' is a member of `glp_iocp'. */ #define HAVE_GLP_IOCP_PRESOLVE 1 /* We have GnuTLS */ #define HAVE_GNUTLS true /* Define to 1 if you have the header file. */ #define HAVE_GNUTLS_ABSTRACT_H 1 /* We have GnuTLS with DANE support */ #define HAVE_GNUTLS_DANE 1 /* Define to 1 if you have the header file. */ #define HAVE_GNUTLS_DANE_H 1 /* Define if you have the iconv() function. */ #define HAVE_ICONV 1 /* Define to 1 if you have the header file. */ #define HAVE_IFADDRS_H 1 /* Define this if inet_ntoa() is available */ /* #undef HAVE_INET_NTOA */ /* Define to 1 if you have the `initgroups' function. */ #define HAVE_INITGROUPS 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_KSTAT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_KVM_H */ /* Define to 1 if you have the header file. */ #define HAVE_LANGINFO_H 1 /* Have bluetooth library */ /* #undef HAVE_LIBBLUETOOTH */ /* Have GLPK */ #define HAVE_LIBGLPK 1 /* Have libgnurl */ #define HAVE_LIBGNURL 1 /* Define to 1 if you have the `intl' library (-lintl). */ /* #undef HAVE_LIBINTL */ /* Define to 1 if you have the header file. */ #define HAVE_LIBINTL_H 1 /* Define to 1 if you have the `kstat' library (-lkstat). */ /* #undef HAVE_LIBKSTAT */ /* Define to 1 if you have the `kvm' library (-lkvm). */ /* #undef HAVE_LIBKVM */ /* Define to 1 if you have the `m' library (-lm). */ #define HAVE_LIBM 1 /* Define to 1 if you have the `resolv' library (-lresolv). */ /* #undef HAVE_LIBRESOLV */ /* Define to 1 if you have the `rt' library (-lrt). */ /* #undef HAVE_LIBRT */ /* Define to 1 if you have the `socket' library (-lsocket). */ /* #undef HAVE_LIBSOCKET */ /* Define if you have the unistring library. */ #define HAVE_LIBUNISTRING 1 /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_LTDL_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MACH_MACH_H */ /* Define to 1 if you have the `mallinfo' function. */ #define HAVE_MALLINFO 1 /* Define to 1 if you have the header file. */ #define HAVE_MALLOC_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MALLOC_MALLOC_H */ /* Define to 1 if you have the `malloc_size' function. */ /* #undef HAVE_MALLOC_SIZE */ /* Define to 1 if you have the `malloc_usable_size' function. */ #define HAVE_MALLOC_USABLE_SIZE 1 /* Define to 1 if you have the header file. */ #define HAVE_MATH_H 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* We have libmicrohttpd */ #define HAVE_MHD 1 /* Define to 1 if you have the header file. */ #define HAVE_MICROHTTPD_H 1 /* Define to 1 if you have the `mremap' function. */ #define HAVE_MREMAP 1 /* Define to 1 if you have the header file. */ #define HAVE_MYSQL_MYSQL_H 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NETDB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_SYSTM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IP_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NSS_H 1 /* Define to 1 if the system has the type `off_t'. */ #define HAVE_OFF_T 1 /* lacking ogg */ #define HAVE_OGG 1 /* Define to 1 if you have the header file. */ #define HAVE_OGG_OGG_H 1 /* Have libopus library */ #define HAVE_OPUS 1 /* Define to 1 if you have the header file. */ #define HAVE_POSTGRESQL_LIBPQ_FE_H 1 /* Have libpulse(audio) library */ #define HAVE_PULSE 1 /* Define to 1 if you have the `random' function. */ #define HAVE_RANDOM 1 /* Define this if select() is available */ /* #undef HAVE_SELECT */ /* Define to 1 if you have the `setresuid' function. */ #define HAVE_SETRESUID 1 /* Define to 1 if you have the `setrlimit' function. */ #define HAVE_SETRLIMIT 1 /* Define to 1 if you have the header file. */ #define HAVE_SIGNAL_H 1 /* Define to 1 if the system has the type `sigset_t'. */ #define HAVE_SIGSET_T 1 /* Define to 1 if the system has the type `size_t'. */ #define HAVE_SIZE_T 1 /* Do we have sockaddr_in.sin_len? */ /* #undef HAVE_SOCKADDR_IN_SIN_LEN */ /* Define this if socket() is available */ /* #undef HAVE_SOCKET */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SOCKLIB_H */ /* Define to 1 if you have the header file. */ #define HAVE_SQLITE3_H 1 /* Define to 1 if you have the `srandom' function. */ #define HAVE_SRANDOM 1 /* Define to 1 if you have the `stat' function. */ #define HAVE_STAT 1 /* Define to 1 if you have the `stat64' function. */ #define HAVE_STAT64 1 /* Define to 1 if you have the `statfs' function. */ #define HAVE_STATFS 1 /* Define to 1 if you have the `statvfs' function. */ #define HAVE_STATVFS 1 /* Define to 1 if `stat' has the bug that it succeeds when given the zero-length file name argument. */ /* #undef HAVE_STAT_EMPTY_STRING_BUG */ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 /* Define to 1 if stdbool.h conforms to C99. */ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDIO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strftime' function. */ #define HAVE_STRFTIME 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strndup' function. */ #define HAVE_STRNDUP 1 /* Define to 1 if you have the `strnlen' function. */ #define HAVE_STRNLEN 1 /* Define to 1 if you have the `sysconf' function. */ #define HAVE_SYSCONF 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_DIR_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_ENDIAN_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_FILE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_IOCTL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_MMAN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_MOUNT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_MSG_H 1 /* Define to 1 if you have the header file, and it defines `DIR'. */ /* #undef HAVE_SYS_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STATVFS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SYSINFO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMEB_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_UCRED_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_VFS_H 1 /* Define to 1 if you have that is POSIX.1 compatible. */ #define HAVE_SYS_WAIT_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_TERMINOS_H */ /* Define if struct tm has the tm_gmtoff member. */ #define HAVE_TM_GMTOFF 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_UCRED_H */ /* We can access-64 bit values that are only 32-bit aligned */ #define HAVE_UNALIGNED_64_ACCESS 0 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_VFORK_H */ /* Define to 1 if you have the `vprintf' function. */ #define HAVE_VPRINTF 1 /* Define to 1 if `fork' works. */ #define HAVE_WORKING_FORK 1 /* Define to 1 if `vfork' works. */ #define HAVE_WORKING_VFORK 1 /* Have compression library */ #define HAVE_ZLIB /**/ /* Define to 1 if the system has the type `_Bool'. */ #define HAVE__BOOL 1 /* Define as const if the declaration of iconv() needs const. */ #define ICONV_CONST /* Defined if libgnurl supports AsynchDNS */ /* #undef LIBGNURL_FEATURE_ASYNCHDNS */ /* Defined if libgnurl supports IDN */ #define LIBGNURL_FEATURE_IDN 1 /* Defined if libgnurl supports IPv6 */ #define LIBGNURL_FEATURE_IPV6 1 /* Defined if libgnurl supports KRB4 */ /* #undef LIBGNURL_FEATURE_KRB4 */ /* Defined if libgnurl supports libz */ #define LIBGNURL_FEATURE_LIBZ 1 /* Defined if libgnurl supports NTLM */ #define LIBGNURL_FEATURE_NTLM 1 /* Defined if libgnurl supports SSL */ #define LIBGNURL_FEATURE_SSL 1 /* Defined if libgnurl supports SSPI */ /* #undef LIBGNURL_FEATURE_SSPI */ /* Defined if libgnurl supports DICT */ /* #undef LIBGNURL_PROTOCOL_DICT */ /* Defined if libgnurl supports FILE */ /* #undef LIBGNURL_PROTOCOL_FILE */ /* Defined if libgnurl supports FTP */ /* #undef LIBGNURL_PROTOCOL_FTP */ /* Defined if libgnurl supports FTPS */ /* #undef LIBGNURL_PROTOCOL_FTPS */ /* Defined if libgnurl supports HTTP */ #define LIBGNURL_PROTOCOL_HTTP 1 /* Defined if libgnurl supports HTTPS */ #define LIBGNURL_PROTOCOL_HTTPS 1 /* Defined if libgnurl supports IMAP */ /* #undef LIBGNURL_PROTOCOL_IMAP */ /* Defined if libgnurl supports LDAP */ /* #undef LIBGNURL_PROTOCOL_LDAP */ /* Defined if libgnurl supports POP3 */ /* #undef LIBGNURL_PROTOCOL_POP3 */ /* Defined if libgnurl supports RTSP */ /* #undef LIBGNURL_PROTOCOL_RTSP */ /* Defined if libgnurl supports SMTP */ /* #undef LIBGNURL_PROTOCOL_SMTP */ /* Defined if libgnurl supports TELNET */ /* #undef LIBGNURL_PROTOCOL_TELNET */ /* Defined if libgnurl supports TFTP */ /* #undef LIBGNURL_PROTOCOL_TFTP */ /* This is a Linux kernel */ #define LINUX 1 /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" /* This is a MinGW system */ /* #undef MINGW */ /* required libgcrypt version */ #define NEED_LIBGCRYPT_VERSION "1.6.0" /* This is a NetBSD system */ /* #undef NETBSD */ /* This is an OpenBSD system */ /* #undef OPENBSD */ /* Some strange OS */ /* #undef OTHEROS */ /* Name of package */ #define PACKAGE "gnunet" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "bug-gnunet@gnu.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "gnunet" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "gnunet 0.10.1" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "gnunet" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "0.10.1" /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* Define to the type of arg 1 for `select'. */ #define SELECT_TYPE_ARG1 int /* Define to the type of args 2, 3 and 4 for `select'. */ #define SELECT_TYPE_ARG234 (fd_set *) /* Define to the type of arg 5 for `select'. */ #define SELECT_TYPE_ARG5 (struct timeval *) /* This is a Solaris system */ /* #undef SOLARIS */ /* This is a BSD system */ /* #undef SOMEBSD */ /* Define to 1 if the `S_IS*' macros in do not work properly. */ /* #undef STAT_MACROS_BROKEN */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 if your declares `struct tm'. */ /* #undef TM_IN_SYS_TIME */ /* VCS revision/hash or tarball version */ #define VCS_VERSION "svn-r32965:32971M" /* Version number of package */ #define VERSION "0.10.1" /* This is a Windows system */ /* #undef WINDOWS */ /* Define to 1 if the X Window System is missing or not being used. */ /* #undef X_DISPLAY_MISSING */ /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ /* #undef _LARGEFILE_SOURCE */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* Need with solaris or errno doesnt work */ /* #undef _REENTRANT */ /* This is a Windows system */ /* #undef _WIN32 */ /* Define curl_free() as free() if our version of gnurl lacks curl_free. */ /* #undef curl_free */ /* Define to `int' if doesn't define. */ /* #undef gid_t */ /* Define to `int' if does not define. */ /* #undef mode_t */ /* Define to `long int' if does not define. */ /* #undef off_t */ /* Define to `int' if does not define. */ /* #undef pid_t */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ /* Define to `int' if doesn't define. */ /* #undef uid_t */ /* Define as `fork' if `vfork' does not work. */ /* #undef vfork */ gnunet-0.10.1/aclocal.m40000644000175000017500000014670112320752054011663 00000000000000# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.14' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.14.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.14.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for 'mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl FIXME we are no longer going to remove this! adjust warning dnl FIXME message accordingly. AC_DIAGNOSE([obsolete], [$0: this macro is deprecated, and will soon be removed. You should use the Autoconf-provided 'AC][_PROG_MKDIR_P' macro instead, and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.]) dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Getting [:3] seems to be dnl the best way to do this; it's what "site.py" does in the standard dnl library. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/absolute-header.m4]) m4_include([m4/align.m4]) m4_include([m4/gettext.m4]) m4_include([m4/iconv.m4]) m4_include([m4/lib-ld.m4]) m4_include([m4/lib-link.m4]) m4_include([m4/lib-prefix.m4]) m4_include([m4/libgcrypt.m4]) m4_include([m4/libgnurl.m4]) m4_include([m4/libtool.m4]) m4_include([m4/libunistring.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/nls.m4]) m4_include([m4/pkg.m4]) m4_include([m4/po.m4]) m4_include([m4/progtest.m4]) m4_include([acinclude.m4]) gnunet-0.10.1/NEWS0000644000175000017500000000101712104437006010505 00000000000000====================================================================== THIS SVN VERSION OF GNUNET IS INCOMPATIBLE TO ALL PREVIOUS RELEASES. WE ARE WORKING ON CHANGING FUNDAMENTAL PARTS OF THE CRYPTOGRAPHIC PARTS OF THE SYSTEM. THE CURRENT IMPLEMENTATION DOES NOT GIVE YOU ANY SECURITY (AS SOME CRYPTO IS DISABLED/INCOMPLETE) AND WILL LIKELY NOT BE COMPATIBLE WITH YESTERDAYS OR TOMORROWS VERSION. AS SUCH, DO NOT USE IT, OTHER THAN FOR DEVELOPMENT! ======================================================================= gnunet-0.10.1/Makefile.in0000644000175000017500000007604012320752057012071 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = . DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ $(srcdir)/gnunet_config.h.in ABOUT-NLS \ $(gnunetinclude_HEADERS) COPYING compile config.guess \ config.rpath config.sub depcomp install-sh missing ltmain.sh ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(docdir)" \ "$(DESTDIR)$(gnunetincludedir)" DATA = $(doc_DATA) HEADERS = $(gnunetinclude_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)gnunet_config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = $(datadir)/doc/gnunet/ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src/include SUBDIRS = contrib doc m4 src po pkgconfig EXTRA_DIST = \ ABOUT-NLS \ config.rpath \ install-sh \ acinclude.m4 gnunetincludedir = $(includedir)/gnunet gnunetinclude_HEADERS = gnunet_config.h doc_DATA = COPYING README ACLOCAL_AMFLAGS = -I m4 all: gnunet_config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): gnunet_config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/gnunet_config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status gnunet_config.h $(srcdir)/gnunet_config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f gnunet_config.h stamp-h1 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) install-gnunetincludeHEADERS: $(gnunetinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(gnunetinclude_HEADERS)'; test -n "$(gnunetincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gnunetincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gnunetincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(gnunetincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(gnunetincludedir)" || exit $$?; \ done uninstall-gnunetincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(gnunetinclude_HEADERS)'; test -n "$(gnunetincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(gnunetincludedir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) $(HEADERS) gnunet_config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(docdir)" "$(DESTDIR)$(gnunetincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-docDATA install-gnunetincludeHEADERS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-docDATA uninstall-gnunetincludeHEADERS .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-generic \ distclean-hdr distclean-libtool distclean-tags distcleancheck \ distdir distuninstallcheck dvi dvi-am html html-am info \ info-am install install-am install-data install-data-am \ install-docDATA install-dvi install-dvi-am install-exec \ install-exec-am install-gnunetincludeHEADERS install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am uninstall-docDATA \ uninstall-gnunetincludeHEADERS ChangeLog: if test -f $(top_srcdir)/.svn/entries; then \ svn log -v --xml -r HEAD:18409 | \ xsltproc --stringparam ignore-message-starting "-" \ --stringparam strip-prefix "gnunet" \ --stringparam include-rev "yes" $(top_srcdir)/contrib/svn2cl.xsl - > $@; \ fi dist: ChangeLog .PHONY: ChangeLog # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/missing0000755000175000017500000001533012320752057011416 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gnunet-0.10.1/configure.ac0000644000175000017500000013556612320725530012317 00000000000000# This file is part of GNUnet. # (C) 2001--2014 Christian Grothoff (and other contributing authors) # # GNUnet is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 3, or (at your # option) any later version. # # GNUnet is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNUnet; see the file COPYING. If not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # # Process this file with autoconf to produce a configure script. # # AC_PREREQ(2.61) # Checks for programs. AC_INIT([gnunet], [0.10.1], [bug-gnunet@gnu.org]) AC_CANONICAL_TARGET AC_CANONICAL_HOST AC_CANONICAL_SYSTEM AM_INIT_AUTOMAKE m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_CONFIG_HEADERS([gnunet_config.h]) AH_TOP([#define _GNU_SOURCE 1]) AC_CONFIG_MACRO_DIR([m4]) AC_PROG_AWK AC_PROG_CC AC_PROG_CPP AC_PROG_CXX AC_PROG_OBJC AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AM_PROG_CC_C_O LT_INIT([disable-static dlopen win32-dll]) AC_SUBST(MKDIR_P) # large file support AC_SYS_LARGEFILE AC_FUNC_FSEEKO if test "$enable_shared" = "no" then AC_MSG_ERROR([GNUnet only works with shared libraries. Sorry.]) fi CFLAGS="-Wall $CFLAGS" # use '-fno-strict-aliasing', but only if the compiler can take it if gcc -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then CFLAGS="-fno-strict-aliasing $CFLAGS" fi # Use Linux interface name unless the OS has a different preference DEFAULT_INTERFACE="\"eth0\"" funcstocheck="getnameinfo gethostname gethostbyname gethostbyaddr getaddrinfo" # Srcdir in a form that native compiler understands (i.e. DOS path on W32) native_srcdir=$srcdir # Check system type case "$host_os" in *darwin* | *rhapsody* | *macosx*) AC_DEFINE_UNQUOTED(DARWIN,1,[This is an Apple Darwin system]) CPPFLAGS="-D_APPLE_C_SOURCE $CPPFLAGS" CFLAGS="-fno-common $CFLAGS" AC_MSG_WARN([The VPN application cannot be compiled on your OS]) build_target="darwin" DEFAULT_INTERFACE="\"en0\"" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; linux*) AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux kernel]) build_target="linux" LIBPREFIX= DLLDIR=lib UNIXONLY="#" AC_PATH_XTRA ;; *freebsd*) AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system]) AC_DEFINE_UNQUOTED(FREEBSD,1,[This is a FreeBSD system]) CFLAGS="-D_THREAD_SAFE $CFLAGS" build_target="freebsd" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *openbsd*) AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system]) AC_DEFINE_UNQUOTED(OPENBSD,1,[This is an OpenBSD system]) LIBS=`echo $LIBS | sed -e "s/-ldl//"` build_target="openbsd" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *netbsd*) AC_DEFINE_UNQUOTED(SOMEBSD,1,[This is a BSD system]) AC_DEFINE_UNQUOTED(NETBSD,1,[This is a NetBSD system]) LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *solaris*) AC_DEFINE_UNQUOTED(SOLARIS,1,[This is a Solaris system]) AC_DEFINE_UNQUOTED(_REENTRANT,1,[Need with solaris or errno doesnt work]) AC_CHECK_LIB(resolv, res_init) AC_CHECK_LIB(rt, nanosleep) build_target="solaris" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *arm-linux*) AC_DEFINE_UNQUOTED(LINUX,1,[This is a Linux kernel]) CFLAGS="-D_REENTRANT -fPIC -pipe $CFLAGS" build_target="linux" LIBPREFIX= DLLDIR=lib UNIXONLY="#" ;; *cygwin*) AC_DEFINE_UNQUOTED(CYGWIN,1,[This is a Cygwin system]) AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system]) AC_CHECK_LIB(intl, gettext) CFLAGS="-mms-bitfields $CFLAGS" build_target="cygwin" LIBPREFIX=lib DLLDIR=bin AC_PROG_CXX UNIXONLY="" ;; *mingw*) AC_DEFINE_UNQUOTED(MINGW,1,[This is a MinGW system]) AC_DEFINE_UNQUOTED(WINDOWS,1,[This is a Windows system]) AC_DEFINE_UNQUOTED(_WIN32,1,[This is a Windows system]) AC_CHECK_LIB(intl, gettext) LDFLAGS="$LDFLAGS -Wl,--export-all-symbols" LIBS="$LIBS -lws2_32 -lplibc -lgnurx -lole32" CFLAGS="-mms-bitfields $CFLAGS" CPPFLAGS="-D_WIN32_WINNT=0x0501 -DHAVE_STAT64=1 -D__USE_MINGW_ANSI_STDIO=1 $CPPFLAGS" build_target="mingw" AC_PROG_CXX LIBPREFIX=lib DLLDIR=bin UNIXONLY="" funcstocheck="" native_srcdir=$(cd $srcdir; pwd -W) ;; gnu*) AC_DEFINE_UNQUOTED(GNU,1,[This is a GNU system]) build_target="gnu" UNIXONLY="#" ;; *) AC_MSG_RESULT(Unrecognised OS $host_os) AC_DEFINE_UNQUOTED(OTHEROS,1,[Some strange OS]) UNIXONLY="" ;; esac AC_DEFINE_UNQUOTED([GNUNET_DEFAULT_INTERFACE], $DEFAULT_INTERFACE, [This should be the default choice for the name of the first network interface]) AC_SUBST(DEFAULT_INTERFACE) # Disable TCP-based IPC on systems that support UNIX domain # sockets in default configuratin: AC_SUBST(UNIXONLY) AC_MSG_CHECKING([for build target]) AM_CONDITIONAL(DARWIN, test "$build_target" = "darwin") AM_CONDITIONAL(CYGWIN, test "$build_target" = "cygwin") AM_CONDITIONAL(MINGW, test "$build_target" = "mingw") AM_CONDITIONAL(SOLARIS, test "$build_target" = "solaris") AM_CONDITIONAL(XFREEBSD, test "$build_target" = "freebsd") AM_CONDITIONAL(OPENBSD, test "$build_target" = "openbsd") AM_CONDITIONAL(LINUX, test "$build_target" = "linux") AM_CONDITIONAL(GNU, test "$build_target" = "gnu") AC_MSG_RESULT([$build_target]) AC_SUBST(build_target) AM_CONDITIONAL([am__fastdepOBJC], false) AC_UNALIGNED_64_ACCESS # some other checks for standard libs AC_SEARCH_LIBS([gethostbyname], [nsl ws2_32]) AC_CHECK_LIB(socket, socket) AC_CHECK_LIB(m, log) AC_CHECK_LIB(c, getloadavg, AC_DEFINE(HAVE_GETLOADAVG,1,[getloadavg supported])) AC_CHECK_MEMBER(struct tm.tm_gmtoff, [AC_DEFINE(HAVE_TM_GMTOFF, 1, [Define if struct tm has the tm_gmtoff member.])], , [#include ]) AC_CHECK_DECLS([_stati64]) # 'save' libs; only those libs found so far will be # linked against _everywhere_. For the others, we # will be more selective! SAVE_LIBS=$LIBS # libgnurx (regex library for W32) gnurx=0 AC_CHECK_LIB(gnurx, regexec, gnurx=1) if test "x$gnurx" = "x0" -a "x$build_target" = "xmingw" then AC_MSG_ERROR([on W32 GNUnet needs libgnurx]) fi # libgcrypt gcrypt=0 NEED_LIBGCRYPT_API=1 NEED_LIBGCRYPT_VERSION=1.6.0 AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION", gcrypt=1) AC_CHECK_DECLS([gcry_mpi_set_opaque_copy], [], [], [[#include ]]) if test $gcrypt = 0 then AC_MSG_ERROR([[ *** *** You need libgcrypt to build this program. ** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/libgcrypt/ *** (at least version $NEED_LIBGCRYPT_VERSION (API $NEED_LIBGCRYPT_API) *** is required.) ***]]) fi AC_DEFINE_UNQUOTED([NEED_LIBGCRYPT_VERSION], "$NEED_LIBGCRYPT_VERSION", [required libgcrypt version]) # Adam shostack suggests the following for Windows: # -D_FORTIFY_SOURCE=2 -fstack-protector-all AC_ARG_ENABLE(gcc-hardening, AS_HELP_STRING(--enable-gcc-hardening, enable compiler security checks), [if test x$enableval = xyes; then CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2 -fstack-protector-all" CFLAGS="$CFLAGS -fwrapv -fPIE -Wstack-protector" CFLAGS="$CFLAGS --param ssp-buffer-size=1" LDFLAGS="$LDFLAGS -pie" fi]) # Linker hardening options # Currently these options are ELF specific - you can't use this with MacOSX AC_ARG_ENABLE(linker-hardening, AS_HELP_STRING(--enable-linker-hardening, enable linker security fixups), [if test x$enableval = xyes; then LDFLAGS="$LDFLAGS -z relro -z now" fi]) extra_logging=GNUNET_NO AC_ARG_ENABLE([logging], AS_HELP_STRING([--enable-logging@<:@=value@:>@],[Enable logging calls. Possible values: yes,no,verbose,veryverbose ('yes' is the default)]), [AS_IF([test "x$enableval" = "xyes"], [], [test "x$enableval" = "xno"], [AC_DEFINE([GNUNET_CULL_LOGGING],[],[Define to cull all logging calls])], [test "x$enableval" = "xverbose"], [extra_logging=GNUNET_YES] [test "x$enableval" = "xveryverbose"], [extra_logging=\(GNUNET_YES+1\)]) ], []) AC_DEFINE_UNQUOTED([GNUNET_EXTRA_LOGGING],[$extra_logging],[1 if extra logging is enabled, 2 for very verbose extra logging, 0 otherwise]) # should memory poisoning be enabled? AC_MSG_CHECKING(whether to poison freed memory) AC_ARG_ENABLE([poisoning], [AS_HELP_STRING([--enable-poisoning], [enable poisoning of freed memory (good for debugging)])], [enable_poisoning=${enableval}], [ if test "x$extra_logging" != "xGNUNET_NO"; then enable_poisoning="defaults to yes (extra logging is enabled)" else enable_poisoning=no fi ]) AC_MSG_RESULT($enable_poisoning) if test ! "x$enable_poisoning" = "xno"; then enable_poisoning=1 else enable_poisoning=0 fi AC_DEFINE_UNQUOTED([ENABLE_POISONING],[$enable_poisoning],[1 if freed memory should be poisoned, 0 otherwise]) if test $build = $target then AC_MSG_CHECKING([for working HMAC]) AC_LANG_PUSH(C) LIBS="$LIBS $LIBGCRYPT_LIBS" CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS" AC_RUN_IFELSE( [AC_LANG_PROGRAM([#include #include ], [[ gcry_md_hd_t mac; unsigned char data[] = { 0xbf, 0x16, 0x6e, 0x46, 0x3a, 0x6c, 0xf3, 0x93, 0xa7, 0x72, 0x11, 0xa1, 0xdc, 0x0b, 0x07, 0xdb, 0x1a, 0x5e, 0xd9, 0xb9, 0x81, 0xbe, 0xea, 0xe4, 0x31, 0x5f, 0x24, 0xff, 0xfe, 0x50, 0x8a, 0xde }; unsigned char key[] = { 0xfc, 0x62, 0x76, 0x35 }; unsigned char result[] = {0xa2, 0xb, 0x1, 0xd9, 0xc0, 0x8b, 0x5a, 0x12, 0x80, 0xd5, 0x50, 0x12, 0x8e, 0xd0, 0x5b, 0xb6, 0x5c, 0x87, 0x24, 0xe2, 0xd0, 0xd2, 0xaf, 0x63, 0xae, 0xd1, 0xd6, 0x64, 0x14, 0xe3, 0x6e, 0x61, 0x5b, 0xd, 0xba, 0x17, 0x7d, 0xd3, 0x10, 0xb1, 0x37, 0x41, 0x91, 0x7d, 0xeb, 0x1, 0x4d, 0x71, 0xe8, 0x59, 0x71, 0x42, 0x8e, 0xd6, 0xf3, 0x29, 0x3b, 0x90, 0xf2, 0xd1, 0xaf, 0x65, 0x1e, 0xb3}; if (!gcry_check_version (GCRYPT_VERSION)) { fprintf (stderr, "Version mismatch %s <-> %s \n", gcry_check_version (NULL), GCRYPT_VERSION); return 1; } gcry_control (GCRYCTL_DISABLE_SECMEM, 0); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); if (gcry_md_open(&mac, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR) { fprintf (stderr, "gcry_md_open error\n"); return 2; } gcry_md_setkey (mac, key, sizeof (key)); gcry_md_write (mac, data, sizeof (data)); if (memcmp(gcry_md_read (mac, 0), result, gcry_md_get_algo_dlen (gcry_md_get_algo (mac))) != 0) { fprintf (stderr, "memcmp error\n"); return 3; } gcry_md_close (mac); return 0; ]])], [AC_MSG_RESULT([yes])], [ RESULT=$? if test $RESULT = 3 then AC_MSG_FAILURE([HMAC test vector does not match. This is a known problem with libgcrypt 1.2.2 on Windows and fixed in 1.4.6.]) fi if test $RESULT = 2 then AC_MSG_FAILURE([HMAC test failed]) fi if test $RESULT = 1 then AC_MSG_FAILURE([libgcrypt header version does not match library version]) fi ]) AC_LANG_POP(C) fi # $build = $target # check for bluetooth library bluetooth=0 AC_CHECK_LIB(bluetooth, ba2str,[AC_CHECK_HEADER([bluetooth/bluetooth.h],bluetooth=1)]) if test "$bluetooth" = 1 then AM_CONDITIONAL(HAVE_LIBBLUETOOTH, true) AC_DEFINE([HAVE_LIBBLUETOOTH],[1],[Have bluetooth library]) else AM_CONDITIONAL(HAVE_LIBBLUETOOTH, false) fi if test "$build_target" = "mingw" then bluetooth=1 fi # check for libpulse(audio) library pulse=0 AC_CHECK_LIB(pulse,pa_stream_peek, [AC_CHECK_HEADER([pulse/simple.h],pulse=1)]) if test "$pulse" = 1 then AC_DEFINE([HAVE_PULSE],[1],[Have libpulse(audio) library]) fi if test "$build_target" = "mingw" then pulse=0 fi # check for libopus(audio) library opus=0 AC_CHECK_LIB(opus,opus_decode_float, [AC_CHECK_HEADER([opus/opus.h], [AC_CHECK_DECL([OPUS_SET_GAIN],[opus=1],[],[[#include ]] )] )] ) if test "$opus" = 1 then AC_DEFINE([HAVE_OPUS],[1],[Have libopus library]) fi # libogg AC_CHECK_LIB(ogg, ogg_stream_flush_fill, [AC_CHECK_HEADERS([ogg/ogg.h], AM_CONDITIONAL(HAVE_OGG, true) ogg=1 AC_DEFINE(HAVE_OGG,1,[Have ogg]), AM_CONDITIONAL(HAVE_OGG, false) ogg=0 AC_DEFINE(HAVE_OGG,0,[lacking ogg]))], AM_CONDITIONAL(HAVE_OGG, false) ogg=0) gst=0 PKG_CHECK_MODULES( [GST], [glib-2.0 gobject-2.0 gstreamer-1.0 gstreamer-app-1.0 gstreamer-audio-1.0], [ gst=1 AC_MSG_RESULT(ok) ], [ gst=0 AC_MSG_RESULT(not found) ]) # Pulse Audio if test "x$pulse" != "x1" -o "x$opus" != "x1" -o "x$ogg" != "x1" then if test "x$gst" != "x1" then conversation_backend=none AM_CONDITIONAL(BUILD_PULSE_HELPERS, false) AM_CONDITIONAL(BUILD_GST_HELPERS, false) else conversation_backend=gst AM_CONDITIONAL(BUILD_PULSE_HELPERS, false) AM_CONDITIONAL(BUILD_GST_HELPERS, true) fi else conversation_backend=pulse AM_CONDITIONAL(BUILD_PULSE_HELPERS, true) AM_CONDITIONAL(BUILD_GST_HELPERS, false) fi # libgnurl LIBGNURL_CHECK_CONFIG(,7.34.0,gnurl=1,gnurl=0) if test "$gnurl" = 1 then AM_CONDITIONAL(HAVE_LIBGNURL, true) AC_DEFINE([HAVE_LIBGNURL],[1],[Have libgnurl]) else AM_CONDITIONAL(HAVE_LIBGNURL, false) fi # libidn AC_MSG_CHECKING([if Libidn can be used]) AC_ARG_WITH(libidn, AC_HELP_STRING([--with-libidn=[DIR]], [Support IDN (needs GNU Libidn)]), libidn=$withval, libidn=yes) if test "$libidn" != "no"; then if test "$libidn" != "yes"; then LDFLAGS="${LDFLAGS} -L$libidn/lib" CPPFLAGS="${CPPFLAGS} -I$libidn/include" fi fi libidn=no AC_CHECK_HEADER(idna.h, AC_CHECK_LIB(idn, stringprep_check_version, [libidn=yes LIBS="${LIBS} -lidn"], []), []) if test "$libidn" != "yes"; then AC_MSG_FAILURE([GNUnet requires libidn. libidn-1.13 should be sufficient, newer versions work too.]) fi AC_MSG_RESULT($libidn) # restore LIBS LIBS=$SAVE_LIBS AC_CHECK_HEADERS([glpk.h],[glpk=true],[gplk=false]) # GLPK must support glpk_init_env, version >= 4.43 AC_CHECK_LIB([glpk],[glp_init_env],,[gplk=false]) # GLPK must support atm MLP presolving, version >= 4.32 AC_CHECK_MEMBERS(glp_iocp.presolve,,[gplk=false],[[#include ]]) if test x$gplk = xfalse then AM_CONDITIONAL(HAVE_LIBGLPK, false) AC_MSG_WARN([GNUnet requires GLPK >= 4.32]) else AM_CONDITIONAL(HAVE_LIBGLPK, true) AC_DEFINE([HAVE_LIBGLPK],[1],[Have GLPK]) fi AC_CHECK_HEADERS([nss.h],[nss=true],[nss=false]) if test x$nss = xfalse then AM_CONDITIONAL(HAVE_GLIBCNSS, false) AC_MSG_WARN([No GNU libc nss header, will not build NSS plugin]) else AM_CONDITIONAL(HAVE_GLIBCNSS, true) fi # test for kvm and kstat (for CPU stats under BSD/Solaris) AC_CHECK_LIB([kvm],[kvm_open]) AC_CHECK_LIB([kstat],[kstat_open]) # test for libextractor extractor=0 AC_MSG_CHECKING(for libextractor) AC_ARG_WITH(extractor, [ --with-extractor=PFX base of libextractor installation], [AC_MSG_RESULT([$with_extractor]) case $with_extractor in no) ;; yes) AC_CHECK_HEADERS(extractor.h, AC_CHECK_LIB([extractor], [EXTRACTOR_plugin_add_defaults], extractor=1)) ;; *) LDFLAGS="-L$with_extractor/lib $LDFLAGS" CPPFLAGS="-I$with_extractor/include $CPPFLAGS" AC_CHECK_HEADERS(extractor.h, AC_CHECK_LIB([extractor], [EXTRACTOR_plugin_add_defaults], EXT_LIB_PATH="-L$with_extractor/lib $EXT_LIB_PATH" extractor=1)) ;; esac ], [AC_MSG_RESULT([--with-extractor not specified]) AC_CHECK_HEADERS(extractor.h, AC_CHECK_LIB([extractor], [EXTRACTOR_plugin_add_defaults], extractor=1))]) if test "$extractor" != 1 then AC_MSG_ERROR([GNUnet requires libextractor]) fi # restore LIBS LIBS=$SAVE_LIBS # Check for libltdl header (#2999) ltdl=0 AC_MSG_CHECKING(for libltdl) AC_ARG_WITH(ltdl, [ --with-ltdl=PFX base of libltdl installation], [AC_MSG_RESULT([$with_ltdl]) case $with_ltdl in no) ;; yes) AC_CHECK_HEADERS(ltdl.h, AC_CHECK_LIB([ltdl], [lt_dlopenext], ltdl=1)) ;; *) LDFLAGS="-L$with_ltdl/lib $LDFLAGS" CPPFLAGS="-I$with_ltdl/include $CPPFLAGS" AC_CHECK_HEADERS(ltdl.h, AC_CHECK_LIB([ltdl], [lt_dlopenext], EXT_LIB_PATH="-L$with_ltdl/lib $EXT_LIB_PATH" ltdl=1)) ;; esac ], [AC_MSG_RESULT([--with-ltdl not specified]) AC_CHECK_HEADERS(ltdl.h, AC_CHECK_LIB([ltdl], [lt_dlopenext], ltdl=1))]) if test x$ltdl = x1 then AC_MSG_RESULT([libltdl found]) else AC_MSG_ERROR([GNUnet requires libltdl (from GNU libtool), try installing libltdl-dev]) fi # restore LIBS LIBS=$SAVE_LIBS # test for libunistring gl_LIBUNISTRING if test $HAVE_LIBUNISTRING != yes; then AC_MSG_ERROR([GNUnet requires libunistring]) fi if test $gl_libunistring_hexversion -le 2305; then AC_MSG_ERROR([GNUnet requires libunistring >= 0.9.1.1]) fi # restore LIBS LIBS=$SAVE_LIBS # Checks for standard header files. AC_HEADER_DIRENT AC_HEADER_STDC # Check for headers that are ALWAYS required AC_CHECK_HEADERS([fcntl.h math.h errno.h ctype.h limits.h stdio.h stdlib.h string.h unistd.h stdarg.h signal.h locale.h sys/stat.h sys/types.h],,AC_MSG_ERROR([Compiling GNUnet requires standard UNIX headers files])) # Checks for headers that are only required on some systems or opional (and where we do NOT abort if they are not there) AC_CHECK_HEADERS([malloc.h malloc/malloc.h langinfo.h sys/param.h sys/mount.h sys/statvfs.h sys/select.h sockLib.h sys/mman.h sys/msg.h sys/vfs.h arpa/inet.h fcntl.h libintl.h netdb.h netinet/in.h netinet/in_systm.h netinet/ip.h sys/ioctl.h sys/socket.h sys/time.h unistd.h kstat.h sys/sysinfo.h kvm.h sys/file.h sys/resource.h ifaddrs.h mach/mach.h stddef.h sys/timeb.h terminos.h argz.h ucred.h sys/ucred.h endian.h sys/endian.h execinfo.h]) SAVE_LDFLAGS=$LDFLAGS SAVE_CPPFLAGS=$CPPFLAGS # test for sqlite sqlite=false AC_MSG_CHECKING(for SQLite) AC_ARG_WITH(sqlite, [ --with-sqlite=PFX base of SQLite installation], [AC_MSG_RESULT("$with_sqlite") case $with_sqlite in no) ;; yes) AC_CHECK_HEADERS(sqlite3.h, sqlite=true) ;; *) LDFLAGS="-L$with_sqlite/lib $LDFLAGS" CPPFLAGS="-I$with_sqlite/include $CPPFLAGS" AC_CHECK_HEADERS(sqlite3.h, EXT_LIB_PATH="-L$with_sqlite/lib $EXT_LIB_PATH" SQLITE_LDFLAGS="-L$with_sqlite/lib" SQLITE_CPPFLAGS="-I$with_sqlite/include" sqlite=true) LDFLAGS=$SAVE_LDFLAGS CPPFLAGS=$SAVE_CPPFLAGS ;; esac ], [AC_MSG_RESULT([--with-sqlite not specified]) AC_CHECK_HEADERS(sqlite3.h, sqlite=true)]) AM_CONDITIONAL(HAVE_SQLITE, test x$sqlite = xtrue) AC_SUBST(SQLITE_CPPFLAGS) AC_SUBST(SQLITE_LDFLAGS) # test for postgres postgres=false AC_MSG_CHECKING(for postgres) AC_ARG_WITH(postgres, [ --with-postgres=PFX base of postgres installation], [AC_MSG_RESULT("$with_postgres") case $with_postgres in no) ;; yes) AC_CHECK_HEADERS(postgresql/libpq-fe.h, postgres=true) ;; *) LDFLAGS="-L$with_postgres/lib $LDFLAGS" CPPFLAGS="-I$with_postgres/include $CPPFLAGS" AC_CHECK_HEADERS(postgresql/libpq-fe.h, EXT_LIB_PATH="-L$with_postgres/lib $EXT_LIB_PATH" POSTGRES_LDFLAGS="-L$with_postgres/lib" POSTGRES_CPPFLAGS="-I$with_postgres/include" postgres=true) LDFLAGS=$SAVE_LDFLAGS CPPFLAGS=$SAVE_CPPFLAGS ;; esac ], [AC_MSG_RESULT([--with-postgres not specified]) AC_CHECK_HEADERS(postgresql/libpq-fe.h, postgres=true)]) AM_CONDITIONAL(HAVE_POSTGRES, test x$postgres = xtrue) AC_SUBST(POSTGRES_CPPFLAGS) AC_SUBST(POSTGRES_LDFLAGS) # test for zlib SAVE_LDFLAGS=$LDFLAGS SAVE_CPPFLAGS=$CPPFLAGS AC_ARG_WITH(zlib, [ --with-zlib[[=DIR]] use libz in DIR], [AS_IF([test "$withval" = "no"], [AC_MSG_ERROR([GNUnet requires zlib])], [test "$withval" != "yes"], [ Z_DIR=$withval CPPFLAGS="${CPPFLAGS} -I$withval/include" LDFLAGS="${LDFLAGS} -L$withval/lib" ]) ]) AC_CHECK_HEADER(zlib.h, [], [AC_MSG_ERROR([GNUnet requires zlib])]) AC_CHECK_LIB(z, compress2, [ AC_DEFINE([HAVE_ZLIB], [], [Have compression library]) if test "x${Z_DIR}" != "x"; then Z_CFLAGS="-I${Z_DIR}/include" Z_LIBS="-L${Z_DIR}/lib -lz" else Z_LIBS="-lz" fi], [AC_MSG_ERROR([GNUnet requires zlib])]) AC_SUBST(Z_CFLAGS) AC_SUBST(Z_LIBS) LDFLAGS=$SAVE_LDFLAGS CPPFLAGS=$SAVE_CPPFLAGS # mysql & windows AC_CHECK_TYPES([sigset_t, off_t], [], [], [#include ]) AC_CHECK_TYPES([size_t], [], [], [#include ]) if test "$build_target" = "mingw" then CYGWIN_MYSQL_MAGIC="#include " fi # test for mysql mysql=false mysqlfail=false SAVE_LDFLAGS=$LDFLAGS SAVE_CPPFLAGS=$CPPFLAGS AC_MSG_CHECKING(for mysql) AC_ARG_WITH(mysql, [ --with-mysql=PFX base of MySQL installation], [AC_MSG_RESULT("$with_mysql") if test "$with_mysql" != "no" then if test "$with_mysql" != "yes" then LDFLAGS="-L$with_mysql/lib -L$with_mysql/lib/mysql $LDFLAGS $ZLIBS" CPPFLAGS="-I$with_mysql/include $CPPFLAGS" fi AC_CHECK_HEADERS(mysql/mysql.h, AC_CHECK_LIB(mysqlclient, mysql_init, MYSQL_LDFLAGS="-L$with_mysql/lib -L$with_mysql/lib/mysql" MYSQL_CPPFLAGS="-I$with_mysql/include" mysql=true), [], [$CYGWIN_MYSQL_MAGIC]) fi ], [AC_MSG_RESULT([--with-mysql not specified]) if test -d "/usr/lib64/mysql"; then MYSQL_LIBDIR="/usr/lib64/mysql" elif test -d "/usr/lib/mysql"; then MYSQL_LIBDIR="/usr/lib/mysql" else MYSQL_LIBDIR="/usr/lib" fi LDFLAGS="-L$MYSQL_LIBDIR $LDFLAGS $ZLIBS" AC_CHECK_LIB(mysqlclient, mysql_init, [AC_CHECK_HEADERS(mysql/mysql.h, MYSQL_LDFLAGS="-L$MYSQL_LIBDIR" mysql=true , [], [$CYGWIN_MYSQL_MAGIC])]) ]) AC_SUBST(MYSQL_LDFLAGS) AC_SUBST(MYSQL_CPPFLAGS) # additional version check for mysql AC_ARG_ENABLE(mysql-version-check, [ --disable-mysql-version-check do not check MySQL version],, enable_mysql_version_check=yes) if test "$mysql" = "true" -a "x$enable_mysql_version_check" = "xyes" then AC_MSG_CHECKING(mysql version) AC_RUN_IFELSE([AC_LANG_PROGRAM( [[$CYGWIN_MYSQL_MAGIC #include ]], [[if (MYSQL_VERSION_ID < 40100) return(-1); else return(0); ]]) ],mysql=true,mysql=false) if test "$mysql" = "false" then mysqlfail=true AC_MSG_RESULT([fail, >= 4.1 required]) else AC_MSG_RESULT(ok) fi fi AM_CONDITIONAL(HAVE_MYSQL, test x$mysql = xtrue) AM_CONDITIONAL(HAVE_MYSQLE, test "0" = "1") # restore LIBS LIBS=$SAVE_LIBS LDFLAGS=$SAVE_LDFLAGS CPPFLAGS=$SAVE_CPPFLAGS if test "$sqlite" = 0 -a "$mysql" = 0 then AC_MSG_ERROR([GNUnet requires SQLite or MySQL]) fi # libmicrohttpd lmhd=0 AC_MSG_CHECKING([for libmicrohttpd]) AC_ARG_WITH(microhttpd, [ --with-microhttpd=PFX base of libmicrohttpd installation], [AC_MSG_RESULT([$with_microhttpd]) case $with_microhttpd in no) ;; yes) AC_CHECK_HEADERS([microhttpd.h], AC_CHECK_DECL(MHD_OPTION_PER_IP_CONNECTION_LIMIT, AC_CHECK_LIB([microhttpd], [MHD_start_daemon], [AC_MSG_CHECKING([for libmicrohttpd >= 0.9.31]) AC_RUN_IFELSE([AC_LANG_SOURCE([ #include "$native_srcdir/src/include/platform.h" #include int main () { return MHD_VERSION >= 0x0093002 ? 0 : 1; } ])], [ AC_MSG_RESULT(ok) lmhd=1],[AC_MSG_RESULT(failed)],lmhd=1)]), [],[#include "$native_srcdir/src/include/platform.h" #include ]),, [#include "$native_srcdir/src/include/platform.h"]) ;; *) LDFLAGS="-L$with_microhttpd/lib $LDFLAGS" CPPFLAGS="-I$with_microhttpd/include $CPPFLAGS" AC_CHECK_HEADERS(microhttpd.h, AC_CHECK_DECL(MHD_OPTION_PER_IP_CONNECTION_LIMIT, AC_CHECK_LIB([microhttpd], [MHD_start_daemon], EXT_LIB_PATH="-L$with_microhttpd/lib $EXT_LIB_PATH" [AC_MSG_CHECKING([for libmicrohttpd >= 0.9.31]) AC_RUN_IFELSE([AC_LANG_SOURCE([ #include "$native_srcdir/src/include/platform.h" #include int main () { return MHD_VERSION >= 0x0093002 ? 0 : 1; } ])], [ AC_MSG_RESULT(ok) lmhd=1],[AC_MSG_RESULT(failed)],lmhd=1)]), [],[#include "$native_srcdir/src/include/platform.h" #include ]),, [#include "$native_srcdir/src/include/platform.h"]) ;; esac ], [AC_MSG_RESULT([--with-microhttpd not specified]) AC_CHECK_HEADERS([microhttpd.h], AC_CHECK_DECL(MHD_OPTION_PER_IP_CONNECTION_LIMIT, AC_CHECK_LIB([microhttpd], [MHD_start_daemon], [AC_MSG_CHECKING([for libmicrohttpd >= 0.9.31]) AC_RUN_IFELSE([AC_LANG_SOURCE([ #include "$native_srcdir/src/include/platform.h" #include int main () { return MHD_VERSION >= 0x0093002 ? 0 : 1; } ])], [ AC_MSG_RESULT(ok) lmhd=1],[AC_MSG_RESULT(failed)],lmhd=1)]), [],[#include "$native_srcdir/src/include/platform.h" #include ]),, [#include "$native_srcdir/src/include/platform.h"])]) AM_CONDITIONAL(HAVE_MHD, test x$lmhd = x1) AC_DEFINE_UNQUOTED([HAVE_MHD], $lmhd, [We have libmicrohttpd]) # restore LIBS LIBS=$SAVE_LIBS # check for python & pexpect (used for some testcases only) AM_PATH_PYTHON([2.6],, [:]) AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :]) # check for gettext AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT_VERSION([0.16.1]) # check for iconv AM_ICONV # Checks for standard typedefs, structures, and compiler characteristics. AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_MODE_T AC_HEADER_TIME AC_HEADER_STAT AC_HEADER_STDBOOL AC_STRUCT_TM AC_CHECK_MEMBER([struct sockaddr_in.sin_len], [ AC_DEFINE(HAVE_SOCKADDR_IN_SIN_LEN, 1, [Do we have sockaddr_in.sin_len?]) ], [], [ #include #include #include ]) # Checks for library functions. AC_FUNC_CLOSEDIR_VOID AC_FUNC_FORK AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP AC_FUNC_SELECT_ARGTYPES AC_FUNC_CHOWN AC_TYPE_SIGNAL AC_FUNC_STAT AC_FUNC_STRFTIME AC_FUNC_VPRINTF AC_HEADER_SYS_WAIT AC_TYPE_OFF_T AC_TYPE_UID_T AC_CHECK_FUNCS([atoll stat64 strnlen mremap getrlimit setrlimit sysconf initgroups strndup gethostbyname2 getpeerucred getpeereid setresuid $funcstocheck getifaddrs freeifaddrs getresgid mallinfo malloc_size malloc_usable_size getrusage random srandom stat statfs statvfs]) # restore LIBS LIBS=$SAVE_LIBS GN_INTLINCL="" GN_LIBINTL="$LTLIBINTL" AC_ARG_ENABLE(framework, [ --enable-framework enable Mac OS X framework build helpers],enable_framework_build=$enableval) AM_CONDITIONAL(WANT_FRAMEWORK, test x$enable_framework_build = xyes) if test x$enable_framework_build = xyes then AC_DEFINE([FRAMEWORK_BUILD], 1, [Build a Mac OS X Framework]) GN_INTLINCL='-I$(top_srcdir)/src/intlemu' GN_LIBINTL='$(top_builddir)/src/intlemu/libintlemu.la -framework CoreFoundation' AC_LIB_APPENDTOVAR([CPPFLAGS], [$GN_INTLINCL]) fi GN_LIB_LDFLAGS="-export-dynamic -no-undefined" GN_PLUGIN_LDFLAGS="-export-dynamic -avoid-version -module -no-undefined" AC_SUBST(GN_LIB_LDFLAGS) AC_SUBST(GN_PLUGIN_LDFLAGS) AC_SUBST(GN_INTLINCL) AC_SUBST(GN_LIBINTL) AC_SUBST(CPPFLAGS) AC_SUBST(LIBS) AC_SUBST(LDFLAGS) AC_SUBST(EXT_LIB_PATH) AC_SUBST(EXT_LIBS) AC_SUBST(LIBPREFIX) AC_SUBST(DLLDIR) AC_SUBST(EXT_LIB_PATH) # test for sudo AC_MSG_CHECKING(for sudo) AC_ARG_WITH(sudo, [ --with-sudo=PATH path to sudo binary (or just yes)], [AC_MSG_RESULT("$with_sudo") case $with_sudo in no) SUDO_BINARY= ;; yes) SUDO_BINARY=sudo ;; *) SUDO_BINARY=$with_sudo ;; esac ], [AC_MSG_RESULT([no])]) AC_SUBST(SUDO_BINARY) AM_CONDITIONAL([HAVE_SUDO], [test "x$SUDO_BINARY" != "x" -o -w /]) # test for nssdir AC_MSG_CHECKING(with nssdir) AC_ARG_WITH(nssdir, [ --with-nssdir=PATH where to install NSS plugins], [AC_MSG_RESULT("$with_nssdir") case $with_nssdir in no) NSS_DIR= install_nss=0 ;; yes) NSS_DIR="/lib" install_nss=1 ;; *) NSS_DIR=$with_nssdir install_nss=1 ;; esac ], [ if test "x$SUDO_BINARY" != "x" -o -w / then NSS_DIR="/lib" install_nss=1 AC_MSG_RESULT([yes, to /lib]) else NSS_DIR= install_nss=0 AC_MSG_RESULT([no]) fi ]) AC_SUBST(NSS_DIR) AM_CONDITIONAL([INSTALL_NSS], [test "x$install_nss" != "x0"]) # test for gnunetdns group name GNUNETDNS_GROUP=gnunetdns AC_MSG_CHECKING(for gnunetdns group name) AC_ARG_WITH(gnunetdns, [ --with-gnunetdns=GRPNAME name for gnunetdns group], [AC_MSG_RESULT("$with_gnunetdns") case $with_gnunetdns in no) GNUNETDNS_GROUP=gnunet ;; yes) GNUNETDNS_GROUP=gnunetdns ;; *) GNUNETDNS_GROUP=$with_gnunetdns ;; esac ], [AC_MSG_RESULT([gnunetdns])]) AC_SUBST(GNUNETDNS_GROUP) # gnutls gnutls=0 gnutls_dane=0 AC_MSG_CHECKING(for gnutls) AC_ARG_WITH(gnutls, [ --with-gnutls=PFX base of gnutls installation], [AC_MSG_RESULT([$with_gnutls]) case $with_gnutls in no) ;; yes) AC_CHECK_HEADERS([gnutls/abstract.h], AC_CHECK_LIB([gnutls], [gnutls_priority_set], gnutls=true)) AC_CHECK_HEADERS([gnutls/dane.h], AC_CHECK_LIB([gnutls-dane], [dane_verify_crt_raw], gnutls_dane=1)) ;; *) LDFLAGS="-L$with_gnutls/lib $LDFLAGS" CPPFLAGS="-I$with_gnutls/include $CPPFLAGS" AC_CHECK_HEADERS([gnutls/abstract.h], AC_CHECK_LIB([gnutls], [gnutls_priority_set], EXT_LIB_PATH="-L$with_gnutls/lib $EXT_LIB_PATH" gnutls=true)) AC_CHECK_HEADERS([gnutls/dane.h], AC_CHECK_LIB([gnutls-dane], [dane_verify_crt_raw], gnutls_dane=1)) ;; esac ], [AC_MSG_RESULT([--with-gnutls not specified]) AC_CHECK_HEADERS([gnutls/abstract.h], AC_CHECK_LIB([gnutls], [gnutls_priority_set], gnutls=true)) AC_CHECK_HEADERS([gnutls/dane.h], AC_CHECK_LIB([gnutls-dane], [dane_verify_crt_raw], gnutls_dane=1)) ]) AM_CONDITIONAL(HAVE_GNUTLS, test x$gnutls = xtrue) AC_DEFINE_UNQUOTED([HAVE_GNUTLS], $gnutls, [We have GnuTLS]) AM_CONDITIONAL(HAVE_GNUTLS_DANE, test x$gnutls_dane = x1) AC_DEFINE_UNQUOTED([HAVE_GNUTLS_DANE], $gnutls_dane, [We have GnuTLS with DANE support]) # Test if we are building for superMUC AC_MSG_CHECKING(if GNUnet is being configured to run on the SuperMUC) AC_ARG_ENABLE([supermuc], [AS_HELP_STRING([--enable-supermuc], [build GNUnet with support to run on the SuperMUC (default is NO)])], [if test "x$enable_supermuc" = "xno" then supermuc=0 else supermuc=1 fi], [supermuc=0 enable_supermuc=no]) AC_MSG_RESULT($enable_SUPERMUC) AM_CONDITIONAL([ENABLE_SUPERMUC], [test "x$supermuc" = "x1"]) AC_DEFINE_UNQUOTED([ENABLE_SUPERMUC], [$supermuc], [Build with support for SuperMUC]) # Check if NSE has to send timestamp information to testbed logger for # generating histogram of messages received AC_MSG_CHECKING(if NSE has to send timestamp information to testbed logger) AC_ARG_ENABLE([nse-histogram], [AS_HELP_STRING([--enable-nse-histogram], [have NSE send timestamp information to testbed logger for generating histogram of received messages. NOT useful for production (default is NO)])], [if test "x$enableval" = "xno" then nse_histogram=0 else nse_histogram=1 fi], [nse_histogram=0 enable_nse_histogram=no]) AC_MSG_RESULT($enable_nse_histogram) AM_CONDITIONAL([ENABLE_NSE_HISTOGRAM], [test "x$nse_histogram" = "x1"]) AC_DEFINE_UNQUOTED([ENABLE_NSE_HISTOGRAM], [$nse_histogram], [have NSE send timestamp information to testbed logger]) # should 'make check' run tests? AC_MSG_CHECKING(whether to run tests) AC_ARG_ENABLE([testruns], [AS_HELP_STRING([--disable-testruns], [disable running tests on make check (default is YES)])], [enable_tests_run=${enableval}], [enable_tests_run=yes]) AC_MSG_RESULT($enable_test_run) AM_CONDITIONAL([ENABLE_TEST_RUN], [test "x$enable_tests_run" = "xyes"]) # should monkey be used when running (certain) services? AC_MSG_CHECKING(whether to run with monkey) AC_ARG_ENABLE([monkey], [AS_HELP_STRING([--enable-monkey], [enable running with monkey])], [enable_monkey=${enableval}], [enable_monkey=no]) AC_MSG_RESULT($enable_monkey) AM_CONDITIONAL([ENABLE_MONKEY], [test "x$enable_monkey" = "xyes"]) if test "x$enable_monkey" = "xyes" then MONKEYPREFIX="pathologist -d $(eval echo ${datarootdir}/gnunet/gnunet.sqlite) -p 30 --" else MONKEYPREFIX="" fi AC_SUBST(MONKEYPREFIX) # should expensive tests be run? AC_MSG_CHECKING(whether to run expensive tests) AC_ARG_ENABLE([expensivetests], [AS_HELP_STRING([--enable-expensivetests], [enable running expensive testcases])], [enable_expensive=${enableval}], [enable_expensive=no]) AC_MSG_RESULT($enable_expensive) AM_CONDITIONAL([HAVE_EXPENSIVE_TESTS], [test "x$enable_expensive" = "xyes"]) # should ports be open for Java services? AC_MSG_CHECKING(whether to enable ports for gnunet-java) AC_ARG_ENABLE([javaports], [AS_HELP_STRING([--enable-javaports], [use non-zero ports for services with Java bindings (default is NO)])], [enable_java_ports=${enableval}], [enable_java_ports=no]) AC_MSG_RESULT($enable_java_ports) if test "x$enable_java_ports" = "xyes" then JAVAPORT="" else JAVAPORT="$UNIXONLY" fi AC_SUBST(JAVAPORT) # should benchmarks be run? AC_MSG_CHECKING(whether to run benchmarks during make check) AC_ARG_ENABLE([benchmarks], [AS_HELP_STRING([--enable-benchmarks], [enable running benchmarks during make check])], [enable_benchmarks=${enableval}], [enable_benchmarks=no]) AC_MSG_RESULT($enable_benchmarks) AM_CONDITIONAL([HAVE_BENCHMARKS], [test "x$enable_benchmarks" = "xyes"]) # should gnunet-testing be compiled AC_MSG_CHECKING(wether to compile gnunet-testing) AC_ARG_ENABLE([testing], [AS_HELP_STRING([--disable-testing], [do not build gnunet-testing])], [enable_testing=${enableval}], [enable_testing=yes]) AC_MSG_RESULT($enable_testing) AM_CONDITIONAL([HAVE_TESTING], [test "x$enable_testing" = "xyes"]) # should experimental code be compiled (code that may not yet compile)? AC_MSG_CHECKING(whether to compile experimental code) AC_ARG_ENABLE([experimental], [AS_HELP_STRING([--enable-experimental], [enable compiling experimental code])], [enable_experimental=${enableval}], [enable_experimental=no]) AC_MSG_RESULT($enable_experimental) AM_CONDITIONAL([HAVE_EXPERIMENTAL], [test "x$enable_experimental" = "xyes"]) # should services be started by default when a peer starts? Some services may # choose to never start by default and it is upto the service/module developer to # decide it by having "AUTOSTART = NO" instead of "AUTOSTART = @AUTOSTART" in # the service/module's conf.in file. AUTOSTART="YES" AC_MSG_CHECKING(whether to auto-start peer's services by default) AC_ARG_ENABLE([autostart], [AS_HELP_STRING([--disable-autostart], [do not start peer's services by default])], [enable_autostart=${enableval} if test "x$enable_autostart" == "xno" then AUTOSTART="NO" fi ], [enable_autostart=yes]) AC_MSG_RESULT($enable_autostart) #AM_CONDITIONAL([HAVE_AUTOSTART], [test "x$enable_autostart" = "xyes"]) AC_SUBST(AUTOSTART) # should memory statistics be kept (very expensive CPU-wise!) AC_MSG_CHECKING(whether to create expensive statistics on memory use) AC_ARG_ENABLE([heapstats], [AS_HELP_STRING([--enable-heapstats], [enable expensive heap statistics])], [enable_heapstats=1], [enable_heapstats=0]) AC_MSG_RESULT($enable_heapstats) AC_DEFINE_UNQUOTED([ENABLE_HEAP_STATISTICS],$enable_heapstats,[enable expensive heap statistics]) # should code be enabled that works around missing OS functionality on Windows? # used for test cases if test $build_target = "mingw" then workarounds=1 AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ],[ int s = socket (0, 0, 0);]) ],[ AC_DEFINE_UNQUOTED([HAVE_SOCKET],1,[Define this if socket() is available]) ],[ AC_DEFINE_UNQUOTED([HAVE_SOCKET],0,[Define this if socket() is available]) ]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ],[ int s = select (0, NULL, NULL, NULL, NULL);]) ],[ AC_DEFINE_UNQUOTED([HAVE_SELECT],1,[Define this if select() is available]) ],[ AC_DEFINE_UNQUOTED([HAVE_SELECT],0,[Define this if select() is available]) ]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ],[ struct in_addr i; char *s = inet_ntoa (i);]) ],[ AC_DEFINE_UNQUOTED([HAVE_INET_NTOA],1,[Define this if inet_ntoa() is available]) ],[ AC_DEFINE_UNQUOTED([HAVE_INET_NTOA],0,[Define this if inet_ntoa() is available]) ]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ],[ int s = getnameinfo (NULL, 0, NULL, 0, NULL, 0, 0);]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETNAMEINFO],1,[Define this if getnameinfo() is available]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETNAMEINFO],0,[Define this if getnameinfo() is available]) ]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ],[ int s = gethostname (NULL, 0);]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETHOSTNAME],1,[Define this if gethostname() is available]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETHOSTNAME],0,[Define this if gethostname() is available]) ]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ],[ void *s = gethostbyname (NULL);]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETHOSTBYNAME],1,[Define this if gethostbyname() is available]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETHOSTBYNAME],0,[Define this if gethostbyname() is available]) ]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ],[ void *s = gethostbyaddr (NULL, 0, 0);]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETHOSTBYADDR],1,[Define this if gethostbyaddr() is available]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETHOSTBYADDR],0,[Define this if gethostbyaddr() is available]) ]) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [#include ],[ int s = getaddrinfo (NULL, NULL, NULL, NULL);]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETADDRINFO],1,[Define this if getaddrinfo() is available]) ],[ AC_DEFINE_UNQUOTED([HAVE_GETADDRINFO],1,[Define this if getaddrinfo() is available]) ]) else AC_MSG_CHECKING(whether to enable windows workarounds) AC_ARG_ENABLE([windows_workarounds], [AS_HELP_STRING([--enable-windows_workarounds], [enable workarounds used on Windows (only useful for test cases)])], [enable_workarounds=${enableval}], [enable_workarounds=no]) AC_MSG_RESULT($enable_workarounds) if test x$enable_windows_workarounds = "xyes" then workarounds=1 else workarounds=0 fi fi AC_DEFINE_UNQUOTED([ENABLE_WINDOWS_WORKAROUNDS], $workarounds, [enable workarounds used on Windows (only useful for test cases)]) # gcov compilation AC_MSG_CHECKING(whether to compile with support for code coverage analysis) AC_ARG_ENABLE([coverage], AS_HELP_STRING([--enable-coverage], [compile the library with code coverage support]), [use_gcov=${enableval}], [use_gcov=no]) AC_MSG_RESULT($use_gcov) AM_CONDITIONAL([USE_COVERAGE], [test "x$use_gcov" = "xyes"]) # version info AC_PATH_PROG(svnversioncommand, svnversion) AC_PATH_PROG(gitcommand, git) AC_MSG_CHECKING(for source being under a VCS) svn_version= gitsvn_version= AS_IF([test ! "X$svnversioncommand" = "X"], [ svn_version=$(cd $srcdir ; $svnversioncommand -n 2>/dev/null) ]) AS_IF([test ! "X$gitcommand" = "X"], [ gitsvn_version=$(cd $srcdir ; git log -1 2>/dev/null | grep "git-svn-id" | sed -e 's/.*@\([[0-9]]\+\) .*/\1/') ]) AS_IF([test "X$svn_version" = "X" -o "X$svn_version" = "Xexported" -o "X$svn_version" = "XUnversioned directory"], [ AS_IF([test "X$gitsvn_version" = "X"], [ vcs_name="no" vcs_version="\"release\"" ], [ vcs_name="yes, git-svn" vcs_version="\"svn-r$gitsvn_version\"" ]) ], [ vcs_name="yes, svn" vcs_version="\"svn-r$svn_version\"" ]) AC_MSG_RESULT($vcs_name) AC_MSG_CHECKING(VCS version) AC_MSG_RESULT($vcs_version) AC_DEFINE_UNQUOTED(VCS_VERSION, [$vcs_version], [VCS revision/hash or tarball version]) AC_CONFIG_FILES([ Makefile contrib/Makefile doc/Makefile doc/man/Makefile doc/doxygen/Makefile m4/Makefile po/Makefile.in src/Makefile src/arm/Makefile src/arm/arm.conf src/ats/Makefile src/ats/ats.conf src/ats-tool/Makefile src/ats-tests/Makefile src/block/Makefile src/core/Makefile src/core/core.conf src/consensus/Makefile src/consensus/consensus.conf src/conversation/Makefile src/conversation/conversation.conf src/datacache/Makefile src/datastore/Makefile src/datastore/datastore.conf src/dht/Makefile src/dht/dht.conf src/dns/Makefile src/dns/dns.conf src/dv/Makefile src/dv/dv.conf src/env/Makefile src/exit/Makefile src/experimentation/Makefile src/experimentation/experimentation.conf src/fragmentation/Makefile src/fs/Makefile src/fs/fs.conf src/gns/Makefile src/gns/gns.conf src/gns/nss/Makefile src/gnsrecord/Makefile src/hello/Makefile src/identity/Makefile src/identity/identity.conf src/include/Makefile src/integration-tests/Makefile src/hostlist/Makefile src/mesh/Makefile src/mesh/mesh.conf src/multicast/Makefile src/multicast/multicast.conf src/mysql/Makefile src/namecache/Makefile src/namecache/namecache.conf src/namestore/Makefile src/namestore/namestore.conf src/nat/Makefile src/nse/Makefile src/nse/nse.conf src/peerinfo/Makefile src/peerinfo/peerinfo.conf src/peerinfo-tool/Makefile src/postgres/Makefile src/psyc/Makefile src/psyc/psyc.conf src/psycstore/Makefile src/psycstore/psycstore.conf src/pt/Makefile src/regex/Makefile src/regex/regex.conf src/revocation/Makefile src/revocation/revocation.conf src/secretsharing/Makefile src/secretsharing/secretsharing.conf src/scalarproduct/Makefile src/scalarproduct/scalarproduct.conf src/set/Makefile src/set/set.conf src/statistics/Makefile src/statistics/statistics.conf src/template/Makefile src/testbed/Makefile src/testbed/testbed.conf src/testing/Makefile src/topology/Makefile src/transport/Makefile src/transport/transport.conf src/tun/Makefile src/util/Makefile src/util/resolver.conf src/vpn/Makefile src/vpn/vpn.conf pkgconfig/Makefile pkgconfig/gnunetarm.pc pkgconfig/gnunetats.pc pkgconfig/gnunetblock.pc pkgconfig/gnunetconsensus.pc pkgconfig/gnunetconversation.pc pkgconfig/gnunetcore.pc pkgconfig/gnunetdatacache.pc pkgconfig/gnunetdatastore.pc pkgconfig/gnunetdht.pc pkgconfig/gnunetdns.pc pkgconfig/gnunetdnsparser.pc pkgconfig/gnunetdnsstub.pc pkgconfig/gnunetdv.pc pkgconfig/gnunetenv.pc pkgconfig/gnunetfragmentation.pc pkgconfig/gnunetfs.pc pkgconfig/gnunetgns.pc pkgconfig/gnunethello.pc pkgconfig/gnunetidentity.pc pkgconfig/gnunetmesh.pc pkgconfig/gnunetmicrophone.pc pkgconfig/gnunetmulticast.pc pkgconfig/gnunetmysql.pc pkgconfig/gnunetnamestore.pc pkgconfig/gnunetnat.pc pkgconfig/gnunetnse.pc pkgconfig/gnunetpeerinfo.pc pkgconfig/gnunetpostgres.pc pkgconfig/gnunetpsyc.pc pkgconfig/gnunetpsycstore.pc pkgconfig/gnunetregex.pc pkgconfig/gnunetrevocation.pc pkgconfig/gnunetscalarproduct.pc pkgconfig/gnunetset.pc pkgconfig/gnunetspeaker.pc pkgconfig/gnunetstatistics.pc pkgconfig/gnunettestbed.pc pkgconfig/gnunettesting.pc pkgconfig/gnunettransport.pc pkgconfig/gnunettun.pc pkgconfig/gnunetutil.pc pkgconfig/gnunetvpn.pc ]) AC_OUTPUT # Finally: summary! # warn user if mysql found but not used due to version if test "$mysqlfail" = "true" then AC_MSG_NOTICE([NOTICE: MySQL found, but too old. MySQL support will not be compiled.]) fi # sqlite if test "x$sqlite" = "x0" then AC_MSG_ERROR([ERROR: sqlite3 not found, but sqlite3 is required.]) fi # libgnurl if test "x$gnurl" = "x0" then AC_MSG_NOTICE([NOTICE: libgnurl not found. http client support will not be compiled.]) AC_MSG_WARN([libgnurl not found. hostlist daemon will not be compiled, and you probably WANT hostlist daemon]) fi # bluetooth if test "x$bluetooth" = "x0" then AC_MSG_NOTICE([NOTICE: bluetooth library not found. bluetooth support will not be compiled.]) fi #gnutls if test x$gnutls != xtrue then AC_MSG_NOTICE([NOTICE: GnuTLS not found, gnunet-gns-proxy will not be built]) else if test "x$gnutls_dane" != "x1" then AC_MSG_NOTICE([NOTICE: GnuTLS has no DANE support, DANE validation will not be possible]) fi fi # java ports if test "x$enable_java_ports" = "xyes" then AC_MSG_NOTICE([NOTICE: opening ports for gnunet-java bindings by default.]) fi # MHD if test "x$lmhd" != "x1" then AC_MSG_NOTICE([NOTICE: libmicrohttpd not found, http transport will not be installed.]) fi # conversation if test "x$conversation_backend" == "xnone" then if test "x$pulse" != "x1" then AC_MSG_NOTICE([NOTICE: libpulse(audio) not found, conversation will not be built.]) fi if test "x$opus" != "x1" then AC_MSG_NOTICE([NOTICE: libopus not found, conversation will not be built.]) fi if test "x$gst" != "x1" then AC_MSG_NOTICE([NOTICE: GStreamer not found, conversation will not be built.]) fi fi AC_MSG_NOTICE([NOTICE: Database support is set to MySQL: $mysql, SQLite: $sqlite, Postgres: $postgres]) if test "$enable_framework_build" = "yes" then AC_MSG_NOTICE([NOTICE: Mac OS X framework build enabled.]) fi if test "x$SUDO_BINARY" = "x" -a ! -w / then AC_MSG_NOTICE([NOTICE: --with-sudo not specified and not running as 'root', will not install GNS NSS library]) fi AC_MSG_NOTICE([******************************************** Please make sure NOW that you have created a user and group 'gnunet' and additionally a group 'gnunetdns': addgroup gnunetdns adduser gnunet Make sure that '/var/lib/gnunet' is owned (and writable) by user 'gnunet'. Then, you can compile GNUnet with make After that, run (if necessary as 'root') make install to install everything. Each GNUnet user should be added to the 'gnunet' group (may require fresh login to come into effect): adduser USERNAME gnunet (run the above command as root once for each of your users, replacing "USERNAME" with the respective login names). If you have a global IP address, no further configuration is required. Optionally, download and compile gnunet-gtk to get a GUI for file-sharing and configuration. This is particularly recommended if your network setup is non-trivial, as gnunet-setup can be used to test in the GUI if your network configuration is working. gnunet-setup should be run as the "gnunet" user under X. As it does very little with the network, running it as "root" is likely also harmless. You can also run it as a normal user, but then you have to copy ~/.gnunet/gnunet.conf" over to the "gnunet" user's home directory in the end. Once you have configured your peer, run (as the 'gnunet' user) gnunet-arm -s to start the peer. You can then run the various GNUnet-tools as your "normal" user (who should only be in the group 'gnunet'). ********************************************]) gnunet-0.10.1/AUTHORS0000644000175000017500000000773612274162761011107 00000000000000Program: GNUnet Homepage: https://gnunet.org/ Maintainer: Christian Grothoff Bug reports: https://gnunet.org/bugs/ Security related bug reports: security@gnunet.org License: some GPLv2+, mostly GPLv3+ Primary developers (0.9.x series): Alejandra Morales Andreas Fuchs Bart Polot Bruno Cabral Christian Fuchs Christian Grothoff Claudiu Olteanu David Barksdale Fabian Oehlmann Florian Dold Gabor X Toth LRN Martin Schanzenbach Matthias Wachs Maximilian Szengel Nils Durner Simon Dieterle Sree Harsha Totakura --- http://sreeharsha.totakura.in/ Stephan A. Posselt Werner Koch Contributions also came from: Adam Warrington [ UPnP ] Alex Harper [ OS X CPU load ] Andrew McDonald [ SHA-512] Andy Green Antti Salonen Blake Matheny Bertrand Marc Clytie Siddall David Brodski David Kuehling Enrico Scholz Eric Haumant Eric Noack Felix von Leitner [ diet libc snprintf for win32 ] Gerd Knorr Glenn McGrath Hendrik Pagenhardt Heikki Lindholm Igor Wronsky Ioana Patrascu Jacob Appelbaum Jake Dust James Blackwell Jean-Luc Cooke [ SHA-512] Jussi Eloranta Jürgen Appel Kevin Vandersloot [original code of gnome-system-monitor] Krista Bennett Grothoff Kyle McMartin [ SHA-512] Larry Waldo Ludovic Courtès Marko Räihä Michael John Wensley Milan Bouchet-Valat Nathan Evans Paul Ruth Philipp Tölke , Renaldo Ferreira Risto Saarelma Roman Zippel Romain Lievin Safey Allah Mohammed sheda Simo Viitanen Thomas d'Otreppe Tiberius Stef Tomi Tukiainen Tuomas Toivonen Tzvetan Horozov Uli Luckas Vasil Dimov Vitaly Minko Werner Koch [original code of libgcrypt] Translations (webpage, documentation, as far as known): Chinese : Di Ma Danish : Jens Palsberg Deutsch : Christian Grothoff , Nils Durner French : Mathieu , Eric Haumant Milan Japanese : Hiroshi Yamauchi Polish : Adam Welc Romaneste : Bogdan Carbunar Kinyarwanda: Steven Michael Murphy Vietnamese : Phan Vinh Thinh and Clytie Siddall Swedish : Daniel Nylander Spanish : Miguel Angel Arruga Vivas Turkish : Nilgün Belma Bugüner Logos: GNU in Net : Christian Muellner GNU with Net : Christian Muellner AFS Face : Alex Jones new GNU in Net: Nicklas Larsson Maintainers: FreeBSD : Kirill Ponomarew Debian GNU/Linux: Daniel Baumann OS X : Jussi Eloranta If you have contributed and are not listed here, please notify one of the maintainers in order to be added. gnunet-0.10.1/ltmain.sh0000644000175000017500000105202612320752051011635 00000000000000 # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.7 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.2 Debian-2.4.2-1.7" TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 gnunet-0.10.1/test-driver0000755000175000017500000001027712320752065012221 00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2013 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then estatus=1 fi case $estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gnunet-0.10.1/doc/0000755000175000017500000000000012320755622010643 500000000000000gnunet-0.10.1/doc/Makefile.in0000644000175000017500000005056112320752057012636 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = doc DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = $(datadir)/doc/gnunet/ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = man doxygen all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/doc/Makefile.am0000644000175000017500000000006712272460772012627 00000000000000SUBDIRS = man doxygen docdir = $(datadir)/doc/gnunet/ gnunet-0.10.1/doc/man/0000755000175000017500000000000012320755622011416 500000000000000gnunet-0.10.1/doc/man/gnunet-ecc.10000644000175000017500000000262712225232703013451 00000000000000.TH GNUNET\-ECC 1 "Mar 15, 2012" "GNUnet" .SH NAME gnunet\-ecc \- manipulate GNUnet ECC key files .SH SYNOPSIS .B gnunet\-ecc .RI [ options ] FILENAME .br .SH DESCRIPTION \fBgnunet\-ecc\fP can be used to create an ECC private key and to print the corresponding public key. You must specify a filename containing an ECC private key in GNUnet format as an argument. If the file does not exist, gnunet\-ecc will create a key. This may then take a while. If the option \-p is given, the corresponding public key will be printed to the console. .SH OPTIONS .B .IP "\-g COUNT, \-\-generate-keys=COUNT" Create COUNT public-private key pairs and write them to FILENAME. Used for creating a file for testing. .B .IP "\-p, \-\-print-public-key" Print the corresponding public key to stdout. This is the value used for PKEY records in GNS. .B .IP "\-P, \-\-print-peer-identity" Print the corresponding peer identity (hash of the public key) to stdout. This hash is used for the name of peers. .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to gnunet-0.10.1/doc/man/gnunet-namestore.10000644000175000017500000000430312225232703014705 00000000000000.TH GNUNET\-NAMESTORE 1 "Mar 5, 2012" "GNUnet" .SH NAME gnunet\-namestore \- manipulate GNUnet zones .SH SYNOPSIS .B gnunet\-namestore .RI [ options ] -z ZONEFILE .br .SH DESCRIPTION \fBgnunet\-namestore\fP can be used to create and manipulate a GNS zone. .SH OPTIONS .B .IP "\-a, \-\-add" Desired operation is adding a record .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-d, \-\-delete" Desired operation is deleting all of the records under the given name .B .IP "\-D, \-\-display" Desired operation is listing of matching records .B .IP "\-e TIME, \-\-expiration=TIME" Specifies expiration time of record to add; format is relative time, i.e "1 h" or "7 d 30 m". Supported units are "ms", "s", "min" or "minutes", "h" (hours), "d" (days) and "a" (years). .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-m, \-\-monitor" Monitor changes to the zone on an ongoing basis (in contrast to \-D, which merely displays the current records) .B .IP "\-n NAME, \-\-name=NAME" Name of the record to add/delete/display .B .IP "\-r PKEY, \-\-reverse=PKEY" Determine our GNS name for the given public key (reverse lookup of the PKEY) in the given zone. .B .IP "\-t TYPE, \-\-type=TYPE" Type of the record to add/delete/display (i.e. "A", "AAAA", "NS", "PKEY", "MX" etc.) .B .IP "\-u URI, \-\-uri=URI" Add PKEY record from gnunet://gns/-URI to our zone; the record type is always PKEY, if no expiration is given FOREVER is used .B .IP "\-v, \-\-version" Print GNUnet version number. .B .IP "\-V VALUE, \-\-value=VALUE" Value to store or remove from the GNS zone. Specific format depends on the record type. A records expect a dotted decimal IPv4 address, AAAA records an IPv6 address, PKEY a public key in GNUnet's printable format, and CNAME and NS records should be a domain name. .B .IP "\-z EGO, \-\-zone=EGO" Specifies the name of the ego controlling the private key for the zone (mandatory option) .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-gns\fP(1) gnunet-0.10.1/doc/man/gnunet-gns-proxy.10000644000175000017500000000304012225232703014653 00000000000000.TH GNUNET\-GNS\-PROXY 1 "Oct 25, 2012" "GNUnet" .SH NAME gnunet\-gns\-proxy \- run a client side GNS SOCKS proxy .SH SYNOPSIS .B gnunet\-gns\-proxy .RI [ options ] .br .SH DESCRIPTION Most users will want to run this SOCKS proxy. It can be used in combination with browsers that support the SOCKS 4a protocol. The proxy will perform SSL authentication of GNS names and rewrite GNS enabled HTML content. To assert the validity of GNS names a local root CA certificate has to be generated that is used by the proxy. Thus "gnunet-gns-proxy-setup-ca" should be executed before the first launch of this proxy or the \-\-authority switch is used to specify an appropriate CA certificate that is already trusted by the browser. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-a AUTHORITY, \-\-authority=AUTHORITY" Path to a PEM CA file that contains the certificate and private key of the CA to use to assert the validity of GNS names. The default port is specified in the configuration file for the gns service under "[gns-proxy]" PROXY_CACERT. .B .IP "\-p PORT, \-\-port=PORT" The port this proxy should listen on. Default is 7777. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-gns(1) gnunet-0.10.1/doc/man/gnunet-search.10000644000175000017500000001257012225232703014162 00000000000000.TH GNUNET-SEARCH "1" "25 Feb 2012" "0.9.6" "GNUnet" .SH NAME gnunet\-search \- a command line interface to search for content on GNUnet .SH SYNOPSIS .B gnunet\-search [\fIOPTIONS\fR] [+]\fIKEYWORD\fR [[+]\fIKEYWORD\fR]* .B gnunet\-search [\fIOPTIONS\fR] [+]\fIURI\fR .SH DESCRIPTION .PP Search for content on GNUnet. The keywords are case\-sensitive. gnunet\-search can be used both for a search in the global namespace as well as for searching a private subspace. .TP \fB\-a \fILEVEL\fR, \fB\-\-anonymity=\fILEVEL\fR The \fB\-a\fR option can be used to specify additional anonymity constraints. If set to 0, GNUnet will try to download the file as fast as possible, including using non-anonymous methods. If you set it to 1 (default), you use the standard anonymous routing algorithm (which does not explicitly leak your identity). However, a powerful adversary may still be able to perform traffic analysis (statistics) to over time infer data about your identity. You can gain better privacy by specifying a higher level of anonymity, which increases the amount of cover traffic your own traffic will get, at the expense of performance. Note that your download performance is not only determined by your own anonymity level, but also by the anonymity level of the peers publishing the file. So even if you download with anonymity level 0, the peers publishing the data might be sharing with a higher anonymity level, which in this case will determine performance. Also, peers that cache content in the network always use anonymity level 1. This option can be used to limit requests further than that. In particular, you can require GNUnet to receive certain amounts of traffic from other peers before sending your queries. This way, you can gain very high levels of anonymity \- at the expense of much more traffic and much higher latency. So set it only if you really believe you need it. The definition of ANONYMITY\-RECEIVE is the following. 0 means no anonymity is required. Otherwise a value of 'v' means that 1 out of v bytes of "anonymous" traffic can be from the local user, leaving 'v-1' bytes of cover traffic per byte on the wire. Thus, if GNUnet routes n bytes of messages from foreign peers (using anonymous routing), it may originate n/(v-1) bytes of queries in the same time\-period. The time\-period is twice the average delay that GNUnet defers forwarded queries. The default is 1 and this should be fine for most users. Also notice that if you choose very large values, you may end up having no throughput at all, especially if many of your fellow GNUnet\-peers all do the same. .TP \fB\-c \fIFILENAME\fR, \fB\-\-config=\fIFILENAME\fR use config file (defaults: ~/.config/gnunet.conf) .TP \fB\-h\fR, \fB\-\-help\fR print help page .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=\fILOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-o \fIFILENAME\fR, \fB\-\-output=\fIFILENAME\fR Writes a GNUnet directory containing all of the search results to FILENAME. .TP \fB\-n\fR, \fB\-\-no-network\fR Only search locally, do not forward requests to other peers. .TP \fB\-N \fIVALUE\fR, \fB\-\-results=\fIVALUE\fR automatically terminate the search after receiving VALUE results. .TP \fB\-t \fIDELAY\fR, \fB\-\-timeout=\fIDELAY\fR Automatically timeout search after DELAY. The value given must be a number followed by a space and a time unit, for example "500 ms". Note that the quotes are required on the shell. Otherwise the search runs until gnunet\-search is aborted with CTRL\-C. .TP \fB\-v\fR, \fB\-\-version\fR print the version number .TP \fB\-V\fR, \fB\-\-verbose\fR print meta data from search results as well .SH NOTES You can run gnunet\-search with an URI instead of a keyword. The URI can have the format for a namespace search or for a keyword search. For a namespace search, the format is gnunet://fs/sks/NAMESPACE/IDENTIFIER. For a keyword search, use gnunet://fs/ksk/KEYWORD[+KEYWORD]*. If the format does not correspond to a GNUnet URI, GNUnet will automatically assume that keywords are supplied directly. If multiple keywords are passed, gnunet-search will look for content matching any of the keywords. The prefix "+" makes a keyword mandatory. # gnunet\-search "Das Kapital" searches for content matching the keyword "Das Kapital". Whereas # gnunet\-search +Das +Kapital Searches for content matching both mandatory keywords "Das" and "Kapital". Search results are printed by gnunet\-search like this: .P .ad l gnunet\-download \-o "COPYING" gnunet://fs/chk/HASH1.HASH2.SIZE Description: The GNU General Public License Mime-type: text/plain .ad b The first line contains the command to run to download the file. The suggested filename in the example is COPYING. The GNUnet URI consists of the key and query hash of the file and finally the size of the file. After the command to download the file GNUnet will print meta\-data about the file as advertised in the search result, here "The GNU General Public License" and the mime\-type (see the options for gnunet\-publish on how to supply meta-data by hand). .SH FILES .TP ~/.config/gnunet.conf GNUnet configuration file; specifies the default value for the timeout .SH "REPORTING BUGS" Report bugs to or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-fs\-gtk\fP(1), \fBgnunet\-publish\fP(1), \fBgnunet\-download\fP(1), \fBgnunet.conf\fP(5), gnunet-0.10.1/doc/man/gnunet-directory.10000644000175000017500000000576312225232703014727 00000000000000.TH gnunet-directory "1" "25 Feb 2012" "GNUnet" .SH NAME gnunet\-directory \- display directories .SH SYNOPSIS .B gnunet\-directory [\fIOPTIONS\fR] (FILENAME)* .SH DESCRIPTION .PP gnunet\-directory lists the contents of one or more GNUnet directories. A GNUnet directory is a binary file that contains a list of GNUnet file\-sharing URIs and meta data. The names of the directory files must be passed as command\-line arguments to gnunet\-directory. .TP \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR configuration file to use (useless option since gnunet\-directory does not really depend on any configuration options) .TP \fB\-h\fR, \fB\-\-help\fR print help page .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=LOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-v\fR, \fB\-\-version\fR print the version number .SH NOTES A GNUnet directory is a file containing a list of GNUnet URIs and meta data. The keys can point to files, other directories or files in namespaces. In other words, a GNUnet directory is similar to UNIX directories. The difference to tar and zip is that GNUnet directory does not contain the actual files (except if they are really small, in which case they may be inlined), just symbolic (links), similar to directories with symbolic links in UNIX filesystems. The benefit is that the individual files can be retrieved separately (if desired) and if some of the files are inserted to another node in GNUnet, this just increases their availability but does not produce useless duplicates (for example, it is a better idea to publish a collection of pictures or compressed sound files using a GNUnet directory instead of processing them with archivers such as tar or zip first). Directories can contain arbitrary meta data for each file. If a directory has missing blocks (for example, some blocks failed to download), GNUnet is typically able to retrieve information about other files in the directory. Files in a GNUnet directory have no particular order; the GNUnet code that generates a directory can reorder the entries in order to better fit the information about files into blocks of 32k. Respecting 32k boundaries where possible makes it easier for gnunet\-directory (and other tools) to recover information from partially downloaded directory files. At the moment, directories can be created by \fBgnunet\-fs\-gtk\fP and \fBgnunet\-publish\fP. Just like ordinary files, a directory can be published in a namespace. GNUnet directories use the (unregistered) mimetype \fBapplication/gnunet\-directory\fP. They can show up among normal search results. The directory file can be downloaded to disk by \fBgnunet\-download\fP(1) for later processing or be handled more directly by \fBgnunet\-fs\-gtk\fP(1). .SH "REPORTING BUGS" Report bugs by using mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-fs\-gtk\fP(1), \fBgnunet\-publish\fP(1), \fBgnunet\-search\fP(1), \fBgnunet\-download\fP(1) gnunet-0.10.1/doc/man/gnunet-auto-share.10000644000175000017500000001145512225232702014765 00000000000000.TH GNUNET\-AUTO\-SHARE "1" "18 Jun 2012" "GNUnet" .SH NAME gnunet\-auto\-share \- a command line tool to automatically share an entire directory with other users .SH SYNOPSIS .B gnunet\-auto\-share [\fIOPTIONS\fR] DIRNAME .SH DESCRIPTION .PP In order to share files with other GNUnet users, the files must first be made available to GNUnet. This tool can be used to automatically share all files from a certain directory. The program will periodically scan the directory for changes and publish files that are new or that changed on GNUnet. Which files have already been shared is remembered in a ".auto-share" file in the shared directory. You can run the tool by hand or automatically by adding the respective options to your configuration. gnunet\-auto\-share has many options in common with gnunet\-publish, but can only be used to index files. .PP You can use automatic meta\-data extraction (based on libextractor). .PP \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR Use alternate config file (if this option is not specified, the default is ~/.config/gnunet.conf). .TP \fB\-D\fR, \fB\-\-disable\-extractor\fR Disable use of GNU libextractor for finding additional keywords and metadata. .TP \fB\-h\fR, \fB\-\-help\fR Print a brief help page with all the options. .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=\fILOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-p \fIPRIORITY\fR, \fB\-\-prio=\fIPRIORITY\fR Executive summary: You probably don't need it. Set the priority of the published content (default: 365). If the local database is full, GNUnet will discard the content with the lowest ranking. Note that ranks change over time depending on popularity. The default should be high enough to preserve the locally published content in favor of content that migrates from other peers. .TP \fB\-r \fILEVEL\fR, \fB\-\-replication=\fILEVEL\fR Set the desired replication level. If CONTENT_PUSHING is set to YES, GNUnet will push each block (for the file) LEVEL times to other peers before doing normal "random" replication of all content. This option can be used to push some content out into the network harder. Note that pushing content LEVEL times into the network does not guarantee that there will actually be LEVEL replicas. .TP \fB\-v\fR, \fB\-\-version\fR Print the version number. .TP \fB\-V\fR, \fB\-\-verbose\fR Be verbose. Using this option causes gnunet\-publish to print progress information and at the end the file identification that can be used to download the file from GNUnet. .SH SETTING ANONYMITY LEVEL The \fB\-a\fR option can be used to specify additional anonymity constraints. If set to 0, GNUnet will publish the file non-anonymously and in fact sign the advertisement for the file using your peer's private key. This will allow other users to download the file as fast as possible, including using non-anonymous methods (DHT, direct transfer). If you set it to 1 (default), you use the standard anonymous routing algorithm (which does not explicitly leak your identity). However, a powerful adversary may still be able to perform traffic analysis (statistics) to over time infer data about your identity. You can gain better privacy by specifying a higher level of anonymity, which increases the amount of cover traffic your own traffic will get, at the expense of performance. Note that regardless of the anonymity level you choose, peers that cache content in the network always use anonymity level 1. The definition of the ANONYMITY LEVEL is the following. 0 means no anonymity is required. Otherwise a value of 'v' means that 1 out of v bytes of "anonymous" traffic can be from the local user, leaving 'v-1' bytes of cover traffic per byte on the wire. Thus, if GNUnet routes n bytes of messages from foreign peers (using anonymous routing), it may originate n/(v-1) bytes of data in the same time\-period. The time\-period is twice the average delay that GNUnet defers forwarded queries. The default is 1 and this should be fine for most users. Also notice that if you choose very large values, you may end up having no throughput at all, especially if many of your fellow GNUnet\-peers all do the same. .SH EXAMPLES .PP \fBBasic example\fR Share a directory "$HOME/gnunet\-share/": # gnunet\-auto\-share $HOME/gnunet\-share/ & \fBBasic configuration\fR Share a directory "$HOME/gnunet\-share/": [ARM] DEFAULTSERVICES = gnunet-auto-share # other default services here [gnunet-auto-share] OPTIONS = $HOME/gnunet\-share .SH FILES .TP ~/.config/gnunet.conf GNUnet configuration file .SH "REPORTING BUGS" Report bugs to or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-fs\-gtk\fP(1), \fBgnunet\-publish\fP(1), \fBgnunet\-search\fP(1), \fBgnunet\-download\fP(1), \fBgnunet.conf\fP(5), \fBextract\fP(1) gnunet-0.10.1/doc/man/gnunet-unindex.10000644000175000017500000000233012225232703014360 00000000000000.TH GNUNET-UNINDEX "1" "6 Sep 2009" "GNUnet" .SH NAME gnunet\-unindex \- a command line interface for deleting indexed files from GNUnet .SH SYNOPSIS .B gnunet\-unindex [\fIOPTIONS\fR] FILENAME .SH DESCRIPTION .PP gnunet\-unindex is used for deleting indexed files from GNUnet. .TP \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR use config file (defaults: ~/.config/gnunet.conf) .TP \fB\-h\fR, \fB\-\-help\fR print help page .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=LOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are NOTHING, ERROR, WARNING, INFO and DEBUG. .TP \fB\-v\fR, \fB\-\-version\fR print the version number .TP \fB\-V\fR, \fB\-\-verbose\fR be verbose .SH NOTES You can only unindex files that you indexed and that you still have available locally in full. You should use gnunet\-unindex on files that you indexed (not inserted) and that you are going to delete or move locally. .TP .SH FILES .TP ~/.config/gnunet.conf GNUnet configuration file .SH "REPORTING BUGS" Report bugs to or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-fs\-gtk\fP(1), \fBgnunet\-publish\fP(1), \fBgnunet\-search\fP(1), \fBgnunet\-download\fP(1), \fBgnunet.conf\fP(5) gnunet-0.10.1/doc/man/gnunet-gns.10000644000175000017500000000352012300637201013473 00000000000000.TH GNUNET\-GNS 1 "Aug 23, 2013" "GNUnet" .SH NAME gnunet\-gns \- Access to GNUnet Name Service .SH SYNOPSIS .B gnunet\-gns .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-gns\fP can be used to lookup and process GNUnet Name Service names. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-r, \-\-raw" No unneeded output. This is a quiet mode where only important information is displayed. For example a lookup for an IP address will only yield the IP address, no descriptive text. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-u NAME, \-\-lookup=NAME" Name to lookup. Resolve the specified name using the GNUnet Name System. .B .IP "\-p PKEY, \-\-public-key=PKEY" Public key of the zone to perform the lookup in. This option should be used if the lookup is to be performed against a zone not controlled by this peer (alternatively, you could pass a ".zkey" for the name). .B .IP "\-T DELAY, \-\-timeout=DELAY" Set the timeout to DELAY. By default, gnunet\-gns will continue to try to resolve the name until there is a definitive answer or until the user aborts with CTRL\-C. .B .IP "\-t TYPE, \-\-type=TYPE" Resource Record Type (TYPE) to look for. Supported TYPE's are: A, AAAA, CNAME, NS, PKEY, PSEU, TLSA, SRV, SOA, MX, LEHO, VPN, REV, PTR, TXT Defaults to "A". .B .IP "\-z NAME, \-\-zone=NAME" Name of the ego of the zone to lookup the record in. The public key associated with the ego will be used for the zone. .B .IP "\-v, \-\-version" Print GNUnet version number. .B .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-namestore\fP(1), \fBgnunet\-identity\fP(1) gnunet-0.10.1/doc/man/gnunet-conversation-test.10000644000175000017500000000226012234016443016400 00000000000000.TH GNUNET\-CONVERSATION\-TEST 1 "Oct 30, 2013" "GNUnet" .SH NAME gnunet\-conversation\-test \- check your speaker and microphone settings .SH SYNOPSIS .B gnunet\-conversation\-test [OPTIONS] .RI URI .br .SH DESCRIPTION \fBgnunet\-conversation\-test\fP can be used to check your speaker and microphone settings. It will record you for five seconds and then play the recording back to you. If this fails, you might want to use the \fBpavucontrol\fP tool to check which microphone or speaker were assigned to GNUnet by PulseAudio (you may have more than one set of microphones or speakers known to your computer). You can use gnunet\-conversation\-test without having a peer running on your computer. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-conversation\fP(1) gnunet-0.10.1/doc/man/gnunet-datastore.10000644000175000017500000000270212225232703014677 00000000000000.TH gnunet\-datastore "1" "30 May 2013" "GNUnet" .SH NAME gnunet\-datastore \- merge or convert GNUnet datastore databases .SH SYNOPSIS .B gnunet\-datastore [\fIOPTIONS\fR] .SH DESCRIPTION .PP gnunet\-datastore can be used to convert or merge GNUnet datastores. This is useful if a datastore is to be migrated between SQL databases, i.e. from sqlite to postgres or vice versa. gnunet\-datastore basically takes two configuration files (which must specify different databases) and reads in all of the data from the datasource (\-s option) and copies it to the destination (\-c option). Note that replication level information is lost in the process at this time. .TP \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR configuration file to use for the destination database .TP \fB\-h\fR, \fB\-\-help\fR print help page .TP \fB\-i\fR, \fB\-\-list-indexed\fR print information about files that are currently indexed by file-sharing .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=LOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-s \fIFILENAME\fR, \fB\-\-sourcecfg=FILENAME\fR configuration file to use for the source database .TP \fB\-v\fR, \fB\-\-version\fR print the version number .TP \fB\-V\fR, \fB\-\-verbose\fR be verbose .SH NOTES .SH "REPORTING BUGS" Report bugs by using mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-publish\fP(1) gnunet-0.10.1/doc/man/gnunet-fs.10000644000175000017500000000214312225232703013320 00000000000000.TH gnunet\-fs "1" "2 Nov 2011" "GNUnet" .SH NAME gnunet\-fs \- measure and control the fs subsystem .SH SYNOPSIS .B gnunet\-fs [\fIOPTIONS\fR] .SH DESCRIPTION .PP gnunet\-fs is a tool to access various functions of GNUnet's fs subsystem from the command\-line. Most of these are not expected to be useful for end-users. gnunet\-fs can currently only be used to obtain a list of indexed files. Other functions should be added in the near future. .TP \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR configuration file to use .TP \fB\-h\fR, \fB\-\-help\fR print help page .TP \fB\-i\fR, \fB\-\-list-indexed\fR print information about files that are currently indexed by file-sharing .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=LOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-v\fR, \fB\-\-version\fR print the version number .TP \fB\-V\fR, \fB\-\-verbose\fR be verbose .SH NOTES .SH "REPORTING BUGS" Report bugs by using mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-publish\fP(1) gnunet-0.10.1/doc/man/gnunet-download.10000644000175000017500000001502012225232703014515 00000000000000.TH GNUNET-DOWNLOAD "1" "25 Feb 2012" "GNUnet" .SH NAME gnunet\-download \- a command line interface for downloading files from GNUnet .SH SYNOPSIS .B gnunet\-download [\fIOPTIONS\fR] \-\- GNUNET_URI .SH DESCRIPTION .PP Download files from GNUnet. .TP \fB\-a \fILEVEL\fR, \fB\-\-anonymity=LEVEL\fR set desired level of receiver anonymity. Default is 1. .TP \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR use config file (defaults: ~/.config/gnunet.conf) .TP \fB\-D, \fB\-\-delete\-incomplete\fR causes gnunet\-download to delete incomplete downloads when aborted with CTRL\-C. Note that complete files that are part of an incomplete recursive download will not be deleted even with this option. Without this option, terminating gnunet\-download with a signal will cause incomplete downloads to stay on disk. If gnunet\-download runs to (normal) completion finishing the download, this option has no effect. .TP \fB\-h\fR, \fB\-\-help\fR print help page .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=LOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-n\fR, \fB\-\-no-network\fR Only search locally, do not forward requests to other peers. .TP \fB\-o \fIFILENAME\fR, \fB\-\-output=FILENAME\fR write the file to FILENAME. Hint: when recursively downloading a directory, append a '/' to the end of the FILENAME to create a directory of that name. If no FILENAME is specified, gnunet\-download constructs a temporary ID from the URI of the file. The final filename is constructed based on meta\-data extracted using libextractor (if available). .TP \fB\-p \fIDOWNLOADS\fR, \fB\-\-parallelism=DOWNLOADS\fR set the maximum number of parallel downloads that is allowed. More parallel downloads can, to some extent, improve the overall time to download content. However, parallel downloads also take more memory (see also option \-r which can be used to limit memory utilization) and more sockets. This option is used to limit the number of files that are downloaded in parallel (\-r can be used to limit the number of blocks that are concurrently requested). As a result, the value only matters for recursive downloads. The default value is 32. .TP \fB\-r \fIREQUESTS\fR, \fB\-\-request-parallelism=REQUESTS\fR set the maximum number of parallel requests that is allowed. If multiple files are downloaded, gnunet\-download will not run them in parallel if this would cause the number of pending requests to possibly exceed the given value. This is useful since, for example, downloading dozens of multi\-gigabyte files in parallel could exhaust memory resources and would hardly improve performance. Note that the limit only applies to this specific process and that other download activities by other processes are not included in this limit. Consider raising this limit for large recursive downloads with many large files if memory and network bandwidth are not fully utilized and if the parallelism limit (\-p option) is not reached. This option also only matters for recursive downloads. The default value is 4092. .TP \fB\-R\fR, \fB\-\-recursive\fR download directories recursively (and in parallel); note that the URI must belong to a GNUnet directory and that the filename given must end with a '/' \-\- otherwise, only the file corresponding to the URI will be downloaded. Note that in addition to using '\-R', you must also specify a filename ending in '.gnd' so that the code realizes that the top-level file is a directory (since we have no meta data). .TP \fB\-v\fR, \fB\-\-version\fR print the version number .TP \fB\-V\fR, \fB\-\-verbose\fR print progress information .SH NOTES The GNUNET_URI is typically obtained from gnunet\-search. gnunet\-fs\-gtk can also be used instead of gnunet\-download. If you ever have to abort a download, you can at any time continue it by re\-issuing gnunet\-download with the same filename. In that case GNUnet will not download blocks again that are already present. GNUnet's file\-encoding will ensure file integrity, even if the existing file was not downloaded from GNUnet in the first place. Temporary information will be appended to the target file until the download is completed. .SH SETTING ANONYMITY LEVEL The \fB\-a\fR option can be used to specify additional anonymity constraints. If set to 0, GNUnet will try to download the file as fast as possible, including using non-anonymous methods. If you set it to 1 (default), you use the standard anonymous routing algorithm (which does not explicitly leak your identity). However, a powerful adversary may still be able to perform traffic analysis (statistics) to over time infer data about your identity. You can gain better privacy by specifying a higher level of anonymity, which increases the amount of cover traffic your own traffic will get, at the expense of performance. Note that your download performance is not only determined by your own anonymity level, but also by the anonymity level of the peers publishing the file. So even if you download with anonymity level 0, the peers publishing the data might be sharing with a higher anonymity level, which in this case will determine performance. Also, peers that cache content in the network always use anonymity level 1. This option can be used to limit requests further than that. In particular, you can require GNUnet to receive certain amounts of traffic from other peers before sending your queries. This way, you can gain very high levels of anonymity \- at the expense of much more traffic and much higher latency. So set it only if you really believe you need it. The definition of ANONYMITY\-RECEIVE is the following. 0 means no anonymity is required. Otherwise a value of 'v' means that 1 out of v bytes of "anonymous" traffic can be from the local user, leaving 'v-1' bytes of cover traffic per byte on the wire. Thus, if GNUnet routes n bytes of messages from foreign peers (using anonymous routing), it may originate n/(v-1) bytes of queries in the same time\-period. The time\-period is twice the average delay that GNUnet defers forwarded queries. The default is 1 and this should be fine for most users. Also notice that if you choose very large values, you may end up having no throughput at all, especially if many of your fellow GNUnet\-peers all do the same. .SH FILES .TP ~/.config/gnunet.conf GNUnet configuration file .SH "REPORTING BUGS" Report bugs to or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-fs\-gtk\fP(1), \fBgnunet\-publish\fP(1), \fBgnunet\-search\fP(1), \fBgnunet.conf\fP(5), \fBgnunet\-service\-fs\fP(1) gnunet-0.10.1/doc/man/gnunet-conversation.10000644000175000017500000000270212225232703015423 00000000000000.TH GNUNET\-CONVERSATION 1 "Oct 5, 2013" "GNUnet" .SH NAME gnunet\-conversation \- have a conversation with your peers .SH SYNOPSIS .B gnunet\-conversation \-e NAME [OPTIONS] .RI URI .br .SH DESCRIPTION \fBgnunet\-conversation\fP can be used to have a conversation with other GNUnet users. You can make calls and receive incoming calls. You need to setup an ego using gnunet\-identity first. For others to be able to call you, you must add a PHONE record to your zone in the GNU Name System (using gnunet\-namestore). gnunet\-conversation has an interactive help system via the /help command. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-e NAME, \-\-ego=NAME" Specifies the NAME of the ego to use (for caller ID) and the GNS master zone for our own lookups. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-p LINE, \-\-phone=LINE" Optional argument that can be used to specify the phone LINE to be used with the conversation service. The default LINE is zero, which should be fine for most users. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-identity\fP(1), \fBgnunet\-namestore\fP(1), \fBgnunet\-gns\fP(1) gnunet-0.10.1/doc/man/gnunet-resolver.10000644000175000017500000000150412274162761014563 00000000000000.TH GNUNET\-RESOLVER 1 "Jan 4, 2012" "GNUnet" .SH NAME gnunet\-resolver \- build-in GNUnet stub resolver .SH SYNOPSIS .B gnunet\-resolver .RI [ options ] [ hostname ] .br .SH DESCRIPTION \fBgnunet\-resolver\fP uses build-in GNUnet stub resolver. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-l LOGFILE, \-\-logfile=LOGFILE" Configure logging to write logs to LOGFILE. .B .IP "\-r, \-\-reverse" Perform a reverse lookup. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to gnunet-0.10.1/doc/man/gnunet-peerinfo.10000644000175000017500000000241112225232703014515 00000000000000.TH GNUNET\-PEERINFO 1 "Mar 4, 2013" "GNUnet" .SH NAME gnunet\-peerinfo \- Display information about other peers. .SH SYNOPSIS .B gnunet\-peerinfo .RI [ options ] .br .SH DESCRIPTION .PP \fBgnunet\-peerinfo\fP display the known addresses and trust of known peers. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Load config file (default: ~/.config/gnunet.conf) .B .IP "\-g, \-\-get\-hello Output HELLO uri(s) .B .IP "\-h, \-\-help" Print help page .B .IP "\-i, \-\-info" List all known peers (and their addresses) .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Set the loglevel .B .IP "\-l LOGFILE, \-\-logfile=LOGFILE" Log messages to LOGFILE .B .IP "\-n, \-\-numeric" Disable resolution of IPs to hostnames .B .IP "\-p, \-\-put\-hello=HELLO Add given HELLO uri to the database .B .IP "\-q, \-\-quiet" Do not print anything but the peer identities .B .IP "\-s, \-\-self" Print only our own identity (together with "\-q", this is the exact line that other peers would have to put in to their friends file in order to consider this peer one of their friends in F2F mode). .B .IP "\-v, \-\-version" Print the version number .SH BUGS Report bugs by using mantis or by sending electronic mail to .SH SEE ALSO gnunet.conf(5) gnunet-0.10.1/doc/man/gnunet-config.10000644000175000017500000000250012225232702014151 00000000000000.TH GNUNET\-CONFIG 1 "Jul 15, 2012" "GNUnet" .SH NAME gnunet\-config \- manipulate GNUnet configuration files .SH SYNOPSIS .B gnunet\-config .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-config\fP can be used to read or modify GNUnet configuration files. .SH OPTIONS .B .IP "\-f, \-\-filename" When accessing a specific option using \-s and \-o, perform expansions as if the value represents a filename. .B .IP "\-s SECTION, \-\-section=SECTION" Which configuration section should be accessed or edited. Required option. .B .IP "\-o OPTION, \-\-option=OPTION" Which configuration option should be accessed or edited. Required to set a value. If not given, all values of a given section will be printed in the format "OPTION = VALUE". .B .IP "\-V VALUE, \-\-value VALUE" Configuration value to store in the given section under the given option. Must only be given together with \-s and \-o options. .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to gnunet-0.10.1/doc/man/gnunet-scalarproduct.10000644000175000017500000000541512225232703015563 00000000000000.TH GNUNET\-VECTORPRODUCT 1 "8 Aug 2013" "GNUnet" .SH NAME gnunet\-vectorproduct \- compute a vectorproduct .SH SYNOPSIS .B gnunet\-vectorproduct .RI [ options ] .br .SH DESCRIPTION \fBgnunet-vectorproduct\fP enables you to compute a vectorproduct across two peers \fBAlice\fP and \fBBob\fP. A client can issue one of two messages to its service: .TS tab (@); l lx. 1@T{ A request to compute a vectorproduct with another peer (\fBAlice\fP) T} 2@T{ Elements to support a peer in computing a vectorproduct (\fBBob\fP) T} .TE Both requests must share the same SID, which can be an arbitrary string identifying the session. SIDs should be unique, however it is sufficient to guarantee the uniqueness of the tupel element count and session ID. \fBAlice\fP\'s client must supply the ASCII encoded peer ID of bob\'s service, it will internally be checked by the client for validity. Invalid values here result in the client or the service failing the session. Elements are handed over as signed decimal integers, the element count supplied by \fBAlice\fP and \fBBob\fP must match. \fBAlice\fP can also supply a mask for these values to her service, which allows partial vector products to be computed across the vector. Elements can be masked by setting their the corresponding mask element to zero, any other value means the element will not be masked. \fBAlice\fP\'s client will also mask all 0-values to avoid information leakage to \fBBob\fP. The protocol by definition relies on \fBAlice\fP and \fBBob\fP being benign, thus \fBBob\fP can arbitrarily falsify his information. Both peers collaborate to achieve a correct result. .SH OPTIONS .B .IP "\-e ELEMENTS, \-\-elements=ELEMENTS" The element-vector the vectorproduct should be computed over in signed decimal form, eg: \"42,1,-3,3,7\". Zero value elements will be automatically masked. .B .IP "\-m MASK, \-\-mask=MASK" Elements in the vector can be masked. There must be at least two elements left in the vector to compute a vectorproduct. Non-Zero values indicate an element is not maskes. .B .IP "\-k KEY, \-\-key=KEY" The session key, a shared string of arbitrary length from which the SID will be generated .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-p PEERID, \-\-peer=PEERID" The remote peer\'s ASCII-armored gnunet-peer ID as output by gnunet-peerinfo. If this option is not given, the peer will take the \fBBob\fP\'s role. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-peerinfo(1) gnunet-0.10.1/doc/man/Makefile.in0000644000175000017500000004730612320752057013414 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = doc/man DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" man5dir = $(mandir)/man5 NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ man_MANS = \ gnunet.conf.5 \ gnunet-arm.1 \ gnunet-ats.1 \ gnunet-auto-share.1 \ gnunet-config.1 \ gnunet-core.1 \ gnunet-conversation.1 \ gnunet-conversation-test.1 \ gnunet-directory.1 \ gnunet-dns2gns.1 \ gnunet-datastore.1 \ gnunet-download.1 \ gnunet-download-manager.1 \ gnunet-ecc.1 \ gnunet-fs.1 \ gnunet-gns.1 \ gnunet-gns-import.1 \ gnunet-gns-proxy.1 \ gnunet-identity.1 \ gnunet-mesh.1 \ gnunet-namecache.1 \ gnunet-namestore.1 \ gnunet-namestore-fcfsd.1 \ gnunet-nat-server.1 \ gnunet-peerinfo.1 \ gnunet-publish.1 \ gnunet-resolver.1 \ gnunet-revocation.1 \ gnunet-scalarproduct.1 \ gnunet-search.1 \ gnunet-statistics.1 \ gnunet-testing-run-service.1 \ gnunet-transport.1 \ gnunet-transport-certificate-creation.1 \ gnunet-unindex.1 \ gnunet-uri.1 \ gnunet-vpn.1 EXTRA_DIST = ${man_MANS} all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/man/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/man/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-man5: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) installdirs: for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-man5 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man1 uninstall-man5 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man1 install-man5 install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-man uninstall-man1 uninstall-man5 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/doc/man/gnunet-namecache.10000644000175000017500000000165012227705277014633 00000000000000.TH GNUNET\-NAMECACHE 1 "Oct 16, 2013" "GNUnet" .SH NAME gnunet\-namecache \- inspect namecache .SH SYNOPSIS .B gnunet\-namecache .RI [ options ] -z PKEY -n LABEL .br .SH DESCRIPTION \fBgnunet\-namecache\fP can be used to inspect values in the namecache. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-n NAME, \-\-name=NAME" Name (label) of the record to display (mandatory option) .B .IP "\-v, \-\-version" Print GNUnet version number. .B .IP "\-z PKEY, \-\-zone=PKEY" Specifies the public key of the zone to inspect (mandatory option) .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-gns\fP(1) gnunet-0.10.1/doc/man/gnunet-transport-certificate-creation.10000644000175000017500000000110112274162761021031 00000000000000.TH GNUNET\-TRANSPORT\-CERTIFICATE\-CREATION 1 "Jan 31, 2014" "GNUnet" .SH NAME gnunet\-transport\-certificate\-creation \- create certificate for HTTPS transport .SH SYNOPSIS .B gnunet\-transport\-certificate\-creation .I privatekey certificate .br .SH DESCRIPTION \fBgnunet\-transport\-certificate\-creation\fP uses openssl to generate a RSA private key and then a self-signed certificate for HTTPS transport. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-transport(1) gnunet-0.10.1/doc/man/gnunet-gns-import.10000644000175000017500000000073312274162761015024 00000000000000.TH GNUNET\-GNS\-IMPORT 1 "Jan 31, 2014" "GNUnet" .SH NAME gnunet\-gns\-import \- import some GNS authorities into your GNS namestore .SH SYNOPSIS .B gnunet\-gns\-import .br .SH DESCRIPTION \fBgnunet\-gns\-import\fP calls gnunet-namestore to fetch some GNS authorities into your GNS namestore. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-gns(1), gnunet\-namestore(1) gnunet-0.10.1/doc/man/gnunet-uri.10000644000175000017500000000166212225232703013514 00000000000000.TH GNUNET\-URI 1 "Jun 26, 2012" "GNUnet" .SH NAME gnunet\-uri \- invoke default handler for GNUnet URIs .SH SYNOPSIS .B gnunet\-uri .RI URI .br .SH DESCRIPTION \fBgnunet\-uri\fP can be used to invoke the correct tool to handle a GNUnet URI. GNUnet URIs have the format "gnunet://SUBSYSTEM/DETAILS" and thus the specific tool to handle the URI depends on the subsystem. gnunet\-uri will determine the correct tool (by looking for SUBSYSTEM in the configuration section "uri") and invoke it. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to gnunet-0.10.1/doc/man/gnunet-statistics.10000644000175000017500000000275712225232703015115 00000000000000.TH GNUNET\-STATISTICS 1 "Jan 4, 2012" "GNUnet" .SH NAME gnunet\-statistics \- Display statistics about your GNUnet system .SH SYNOPSIS .B gnunet\-statistics .RI [ options ] .RI [ VALUE ] .br .SH DESCRIPTION \fBgnunet\-statistics\fP is used to display detailed information about various aspect of GNUnet's operation. This tool only works if the "statistics" service is available. gnunet\-statistics can be used to set a value by giving the options \-n, \-s and also a VALUE. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-n NAME, \-\-name=NAME" Each statistic has a name that is unique with in its subsystem. With this option, the output can be restricted to statistics that have a particular name. .B .IP "\-p, \-\-persistent" When setting a value, make the value persistent. If the value used to be persistent and this flag is not given, it will be marked as non\-persistent. .B .IP "\-s SUBSYSTEM, \-\-subsystem=SUBSYSTEM" Statistics are kept for various subsystems. With this option, the output can be restricted to a particular subsystem only. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-service\-statistics(1) gnunet-0.10.1/doc/man/gnunet-testing-run-service.10000644000175000017500000000214212274162761016636 00000000000000.TH GNUNET\-TESTING\-RUN\-SERVICE 1 "Aug 25, 2013" "GNUnet" .SH NAME gnunet\-testing\-run\-service \- Command line tool to start a service for testing. .SH SYNOPSIS .B gnunet\-testing\-run\-service .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-testing\-run\-service\fP is a command line tool to start a service for testing. It starts a peer, running only the service specified on the command line, outputs the path to the temporary configuration file to stdout. The peer will run until this program is killed, or stdin is closed. When reading the character 'r' from stdin, the running service is restarted with the same configuration. This executable is intended to be used by gnunet-java, in order to reliably start and stop services for test cases. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Name of the template configuration file to use (optional). .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-s SERVICE, \-\-service=SERVICE" Name of the service to run. .SH BUGS Report bugs by using Mantis or by sending electronic mail to gnunet-0.10.1/doc/man/Makefile.am0000644000175000017500000000155612274162761013405 00000000000000man_MANS = \ gnunet.conf.5 \ gnunet-arm.1 \ gnunet-ats.1 \ gnunet-auto-share.1 \ gnunet-config.1 \ gnunet-core.1 \ gnunet-conversation.1 \ gnunet-conversation-test.1 \ gnunet-directory.1 \ gnunet-dns2gns.1 \ gnunet-datastore.1 \ gnunet-download.1 \ gnunet-download-manager.1 \ gnunet-ecc.1 \ gnunet-fs.1 \ gnunet-gns.1 \ gnunet-gns-import.1 \ gnunet-gns-proxy.1 \ gnunet-identity.1 \ gnunet-mesh.1 \ gnunet-namecache.1 \ gnunet-namestore.1 \ gnunet-namestore-fcfsd.1 \ gnunet-nat-server.1 \ gnunet-peerinfo.1 \ gnunet-publish.1 \ gnunet-resolver.1 \ gnunet-revocation.1 \ gnunet-scalarproduct.1 \ gnunet-search.1 \ gnunet-statistics.1 \ gnunet-testing-run-service.1 \ gnunet-transport.1 \ gnunet-transport-certificate-creation.1 \ gnunet-unindex.1 \ gnunet-uri.1 \ gnunet-vpn.1 EXTRA_DIST = ${man_MANS} gnunet-0.10.1/doc/man/gnunet-download-manager.10000644000175000017500000000171112225232703016127 00000000000000.TH GNUNET-DOWNLOAD-MANAGER 1 "15 Jan, 2011" "GNUnet" .SH NAME gnunet-download-manager \- manage downloads across sessions .SH SYNOPSIS .B gnunet\-download\-manager .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-download\-manager\fP is a script that can be used to track download sessions. It makes the process of resuming downloads after a system reboot easier. A typical use is to define an alias (depending on your shell) of the form $ alias gnunet\-download='gnunet\-download\-manager.scm download' Other commands for the download manager include resume (resumes all downloads), status (show status of pending downloads), killall (abort all downloads), settings (for configuration) and help (print help text). gnunet\-download\-manager is a scheme script and will only work if guile is available. .SH BUGS Report bugs by using mantis or by sending electronic mail to .SH SEE ALSO gnunet\-download(1) gnunet-0.10.1/doc/man/gnunet.conf.50000644000175000017500000001256212226016773013660 00000000000000.TH GNUNET.CONF "5" "12 Aug 2013" "GNUnet" .SH NAME gnunet.conf \- GNUnet configuration file .SH SYNOPSIS ~/.config/gnunet.conf .SH DESCRIPTION .PP A GNUnet setup typically consists of a a set of service processes run by a user "gnunet" and a set of user-interface processes run by a standard account. The default location for the configuration file for the services is "~gnunet/.config/gnunet.conf"; however, as normal users also may need read-access to this configuration, you might want to instead put the service process configuration in "/etc/gnunet.conf". gnunet\-setup (part of the GTK package) can be used to edit this configuration. The parts of GNUnet that is ran as a normal user may have config options too and they read from "$HOME/.config/gnunet.conf". The latter config file can skip any options for the services. .TP The basic structure of the configuration file is the following. The file is split into sections. Every section begins with "[SECTIONNAME]" and contains a number of options of the form "OPTION=VALUE". Empty lines and lines beginning with a "#" are treated as comments. Almost all options are optional and the tools resort to reasonable defaults if they are not present. .PP Default values for all of the options can be found in the files in the "$GNUNET_PREFIX/share/gnunet/config.d/" directory. A typical setup will work out of the box with those. See the examples section below for some common setups on top of that. .SH General OPTIONS .PP Many options will be common between sections. They can be repeated under each section with different values. The "[PATHS]" section is special. Here, it is possible to specify values for variables like "GNUNET_HOME". Then, in all filenames that begin with "$GNUNET_HOME" the "$GNUNET_HOME" will be replaced with the respective value at runtime. The main use of this is to redefine "$GNUNET_HOME", which by default points to "$HOME/.config/". By setting this variable, you can change the location where GNUnet stores its internal data. .PP The following options are generic and shared by all services: .IP HOSTNAME The hostname specifies the machine on which the service is running. This is usually "localhost". .IP BINARY The filename that implements the service. For example "gnunet-service-ats". .IP AUTOSTART This defines the section it is defined in, which should be a service, will be started by the ARM service if the value is set to YES. .IP ACCEPT_FROM A semi-column separated list of IPv4 addresses that are allowed to use the service; usually 127.0.0.1. .IP ACCEPT_FROM6 A semi-column separated list of IPv6 addresses that are allowed to use the service; usually ::1. .IP UNIXPATH Path to use for the UNIX domain socket for inter process communication with the service on POSIX systems. .IP UNIX_MATCH_UID If UNIX domain sockets are used, set this to YES if only users with the same UID are allowed to access the service. .IP UNIX_MATCH_GID If UNIX domain sockets are used, set this to YES if only users with the same GID are allowed to access the service. .IP USER_SERVICE Set to YES if this service should be run per-user, NO if this is a system service. End-users should never have to change the defaults GNUnet provides for this option. .SH ARM Options This section is configuration for the automatic restart manager which is responsible for launching services. .IP DEFAULTSERVICES list of services that ARM should always start by default. AUTOSTART services are only started when the service is needed by some other service. The services listed here will always be started, not just on-demand. "topology" and "hostlist" should virtually always be listed here, and most users will want to specify high-level applications like "fs", "gns" or "pt" here as well. .B .SH ATS Options .IP UNSPECIFIED_QUOTA_IN quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP UNSPECIFIED_QUOTA_OUT quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP LOOPBACK_QUOTA_IN quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP LOOPBACK_QUOTA_OUT quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP LAN_QUOTA_IN quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP LAN_QUOTA_OUT quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP WAN_QUOTA_IN quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP WAN_QUOTA_OUT quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP WLAN_QUOTA_IN quotes in KiB or MiB per seconds. Or use the word "unlimited" .IP WLAN_QUOTA_OUT quotes in KiB or MiB per seconds. Or use the word "unlimited" .SH EXAMPLES This example is a simple way to get started, using a server that has a known list of peers to get you started. Most users will be behind a firewal on IPv4, as such NAT is enabled. Please rememeber to change your IP address to the actual external address for your usage. .PP [hostlist] OPTIONS = -b SERVERS = http://v9.gnunet.org:58080/ [arm] DEFAULTSERVICES = topology hostlist fs [nat] BEHIND_NAT = YES ENABLE_UPNP = YES DISABLEV6 = YES EXTERNAL_ADDRESS = 157.166.249.10 .SH FILES .TP ~/.config/gnunet.conf GNUnet configuration file .SH "REPORTING BUGS" Report bugs by using Mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-setup\fP(1), \fBgnunet\-arm\fP(1) gnunet-0.10.1/doc/man/gnunet-revocation.10000644000175000017500000000526012225232703015064 00000000000000.TH GNUNET\-REVOCATION 1 "Mar 15, 2012" "GNUnet" .SH NAME gnunet\-revocation \- revoke private keys (of egos) in GNUnet .SH SYNOPSIS .B gnunet\-revocation .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-revocation\fP can be used to verify if a key has been revoked, to create a revocation certificate for later revocation, to instantly revoke a key and to use a pre-generated revocation certificate to revoke a key. Upon successful revocation, all peers will be informed about the invalidity of the key. As this is an expensive operation, GNUnet requires the issuer of the revocation to perform an expensive proof-of-work computation before he will be allowed to perform the revocation. gnunet\-revocation will perform this computation. The computation can be performed ahead of time, with the resulting revocation certificate being stored in a file for later "instant" use. gnunet\-revocation also makes is possible to resume the pre-calculation of a revocation --- simply abort a running proof-of-work calculation with CTRL-C, and the existing revocation certificate file will contain the status of the computation. Note that performing a revocation proof-of-work is deliberately VERY expensive. Depending on your CPU, the calculation can take days or weeks. .SH OPTIONS .B .IP "\-t KEY, \-\-test=KEY" Check if the given KEY (ASCII\-encoded public key required) has been revoked. .B .IP "\-R NAME, \-\-revoke=NAME" Calculate or perform revocation for the ego with the given NAME. .B .IP "\-p, \-\-perform" Actually perform the revocation as soon as possible (do not just generate a revocation certificate, use it). Must be supplied to actually perform the revocation. .B .IP "\-f NAME, \-\-filename=NAME" Use NAME as the name of the file that is to contain the revocation certificate. Intermediate computation results will be stored here, as well as the final revocation certificate. When used together with \-p, this file will be inspected to see if it contains a valid certificate for instant revocation, in which case the revocation can be performed instantly. If the given file contains anything (a valid certificate, with or without the completed proof-of-work) there is no need to supply the "\-R" option or to still have the private key of the ego to perform the revocation. .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to gnunet-0.10.1/doc/man/gnunet-namestore-fcfsd.10000644000175000017500000000373412225232703015777 00000000000000.TH GNUNET\-NAMESTORE-FCFSD 1 "5 Sep 2013" "GNUnet" .SH NAME gnunet\-namestore-fcfsd \- HTTP server for GNU Name System First-Come-First-Served name registration .SH SYNOPSIS .B gnunet\-namestore-fcfsd .RI [ options ] .br .SH DESCRIPTION Most users will not want to run an FCFS\-zone and thus will not need this program. \fBgnunet\-gns-fcfsd\fP runs a web server where users can register names to be mapped to their GNS zone. Names are made available on a First Come First Served basis (hence fcfs). Registered names do not expire. The HTTP server is run on the port that is specified in the configuration file in section "[fcfsd]" under the name "HTTPPORT". The key of the zone in which the names are registered must be specified under the name "ZONEKEY" in the same section. It is possible to manage gnunet\-gns\-fcfsd using gnunet\-(service\-arm) by starting the daemon using "gnunet\-arm \-i fcfsd" or by adding "fcfds" to the "DEFAULTSERVICES" option. An FCFS\-zone is run at http://gnunet.org/fcfs/. The respective zone key can be imported into an individual user's zone using "gnunet-gns-import.sh". GNS users are encouraged to register their zone with the gnunet.org FCFS authority. If you want to run your own FCFS registrar, you need to first create a pseudonym (using "gnunet\-identity \-C NAME"), and then assign it to be used for the "fcfsd" service using "gnunet\-identity \-e NAME \-s fcfsd". After that, you can start the FCFSD service (possibly using gnunet\-arm). .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-identity(1), gnunet\-gns(1), gnunet\-gns\-proxy(1) gnunet-0.10.1/doc/man/gnunet-identity.10000644000175000017500000000374112225232703014546 00000000000000.TH GNUNET-IDENTITY "1" "5 Sep 2013" "GNUnet" .SH NAME gnunet\-identity \- create, delete or list egos .SH SYNOPSIS .B gnunet\-identity [options] .SH DESCRIPTION .PP gnunet\-identity is a tool for managing egos. An ego is the persona that controls a namespace. It is identical to a public\-private ECC key pair. gnunet\-identity can be used to list all of the egos that were created locally, to create new egos, and to delete existing egos (the namespace will continue to exist, but it will be impossible to add additional data to it). Creating a new ego requires using the \-C option together with an identifier (name) that is to be used for the new ego. This identifier is only used locally for this peer and not shared with other peers. .TP \fB\-C NAME\fR, \fB\-\-create=NAME\fR Creates a new ego with the given NAME. .TP \fB\-D NAME\fR, \fB\-\-delete=NAME\fR Delete the ego with the given NAME. .TP \fB\-e NAME\fR, \fB\-\-ego=NAME\fR Perform "set" operation with the respective ego. Needs to be used together with option \-s. .TP \fB\-h\fR, \fB\-\-help\fR Print help page. .TP \fB\-d\fR, \fB\-\-display\fR display all ouf our egos .TP \fB\-m\fR, \fB\-\-monitor\fR run in monitor mode, listing all ouf our egos until CTRL-C is pressed. Each ego is listed together with a unique pointer value; if egos are renamed, that pointer value remains the same; if egos are deleted, they are listed one more time with a name of "". .TP \fB\-s SUBSYSTEM\fR, \fB\-\-set=SUBSYSTEM\fR Perform "set" operation for the specified SUBSYSTEM with the respective ego. Needs to be used together with option \-e. After this, the given SUBSYSTEM will use the ego with the specified NAME. This will fail if NAME does not yet exist. .SH FILES .TP ~/.gnunet/egos/ Directory where the egos are stored (by default) .SH "REPORTING BUGS" Report bugs by using Mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-gns\fP(1), \fBgnunet\-namestore\fP(1) gnunet-0.10.1/doc/man/gnunet-core.10000644000175000017500000000171512225232703013644 00000000000000.TH gnunet\-core "1" "1 Apr 2012" "GNUnet" .SH NAME gnunet\-core \- measure and control the core subsystem .SH SYNOPSIS .B gnunet\-core [\fIOPTIONS\fR] .SH DESCRIPTION .PP gnunet\-core is a tool to access various functions of GNUnet's core subsystem from the command\-line. The only function right now is to list the peers that are directly connected to this peer (with successful cryptographic handshake). .TP \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR configuration file to use .TP \fB\-h\fR, \fB\-\-help\fR print help page .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=LOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-v\fR, \fB\-\-version\fR print the version number .TP \fB\-V\fR, \fB\-\-verbose\fR be verbose .SH NOTES .SH "REPORTING BUGS" Report bugs by using mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-transport\fP(1) gnunet-0.10.1/doc/man/gnunet-mesh.10000644000175000017500000000174412274162761013664 00000000000000.TH GNUNET\-MESH 1 "Jan 31, 2014" "GNUnet" .SH NAME gnunet\-mesh \- Print information about mesh tunnels and peers .SH SYNOPSIS .B gnunet\-mesh .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-mesh\fP prints information about mesh tunnels and peers. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-l LOGFILE, \-\-logfile=LOGFILE" Configure logging to write logs to LOGFILE. .B .IP "\-m, \-\-monitor" Provide information about all tunnels (continuously) NOT IMPLEMENTED. .B .IP "\-t OWNER\_ID:TUNNEL\_ID, \-\-tunnel=OWNER\_ID:TUNNEL\_ID" Provide information about a particular tunnel. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to gnunet-0.10.1/doc/man/gnunet-ats.10000644000175000017500000000306012274162761013510 00000000000000.TH GNUNET\-ATS 1 "Oct 31, 2012" "GNUnet" .SH NAME gnunet\-ats \- display information about transport resource allocation .SH SYNOPSIS .B gnunet\-ats .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-ats\fP can be used to display information about the GNUnet's transport selection mechanism. It shows information about the addresses and the assigned input and output bandwidth. .SH OPTIONS .B .IP "\-a, \-\-aa" List all addresses currently known to ats. .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-i, \-\-id=PEERID" Print information for a specific peer identity only .B .IP "\-k, \-\-value=VALUE" Value to set for when changing preference values .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-m, \-\-monitor" Monitor changes to the bandwidth assignments continuously .B .IP "\-n, \-\-numeric" Do not resolve IP addresses to hostnames .B .IP "\-k, \-\-preference=E" Set preference values, \-i, \-k and \-t required .B .IP "\-q, \-\-quotas" Print quotas for all network types .B .IP "\-t, \-\-type=VALUE" Preference type to change: latency | bandwidth .B .IP "\-u, \-\-used" Print addresses actively used only .B .IP "\-V, \-\-verbose" Print verbose output (include ATS address properties) .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-transport(1) gnunet-0.10.1/doc/man/gnunet-dns2gns.10000644000175000017500000000452512225232703014274 00000000000000.TH GNUNET\-DNS2GNS 1 "Oct 25, 2012" "GNUnet" .SH NAME gnunet\-dns2gns \- run a DNS-to-GNS proxy .SH SYNOPSIS .B gnunet\-dns2gns .RI [ options ] .br .SH DESCRIPTION Most users will not want to run an DNS to GADS proxy/gateway and thus will not need this program. \fBgnunet\-dns2gns\fP runs a DNS resolver which delegates requests to the ".gads" and ".zkey" zones to GADS. All other requests are forwarded to DNS. This DNS proxy is useful for enabling non-personalized GADS\-resolution to an entire network or to offer GADS\-resolution to DNS users. A DNS\-to\-GNS proxy using gnunet\-dns2gns is available at ".zkey.eu" If you do not want to specify a public key and are the owner of the zone that gnunet\-dns2gns will use for GNS lookups, you need to first create a pseudonym (using "gnunet\-identity \-C NAME"), and then assign it to be used for the "dns2gns" service using "gnunet\-identity \-e NAME \-s dns2gns". After that, you can start the dns2gns service (possibly using gnunet\-arm) without specifying a public key using "\-z". .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-d IP, \-\-dns=IP" IP address of a recursive DNS resolver that should be used for non-GADS hostnames. .B .IP "\-f NAME, \-\-fcfs=NAME" Authoritative FCFS suffix to use. This is the name under which the local zone's names will be made available. Default is "fcfs.zkey.eu". .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-s SUFFIX, \-\-suffix=SUFFIX" Authoritative DNS suffix to use. This is the name under which the GADS ".zkey" zone is mapped into the DNS namespace. Default is "zkey.eu". .B .IP "\-v, \-\-version" Print GNUnet version number. .B .IP "\-z PUBLICKEY, \-\-zone=PUBLICKEY" Use PUBLICKEY for the zone to resolve GNS names in. The PUBLICKEY must be encoded in the text format which can be obtained using gnunet\-ecc, seen in PKEY records and output by gnunet\-identity. If this option is not specified, the default ego associated by gnunet\-identity for the "dns2gns" subsystem will be used. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-gns\-fcfs(1), gnunet\-gns(1), gnunet\-identity(1) gnunet-0.10.1/doc/man/gnunet-nat-server.10000644000175000017500000000437512225232703015007 00000000000000.TH GNUNET\-NAT\-SERVER 1 "25 Feb 2012" "GNUnet" .SH NAME gnunet\-nat\-server \- help GNUnet setup test network setup with NAT .SH SYNOPSIS .B gnunet\-nat\-server .RI [ options ] .RI PORT .br .SH DESCRIPTION Normal GNUnet end-users should not concern themselves with gnunet\-nat\-server. In fact, distributions are encouraged to consider not shipping it at all. Running gnunet\-nat\-server's is similar to running hostlist servers: it is a special service to the community with special requirements and no benefit to those running the service. This program will listen on the specified PORT for incoming requests to test a peer's network connectivity. Incoming requests can ask it to connect to a given IPv4 address (and port) using TCP or UDP and to send a 2-byte test message using the specified address. The program can also be asked to send a "fake" ICMP response message to a given IPv4 address (for autonomous NAT traversal \-\-\- see the description in the respective research paper). The idea is that gnunet\-nat\-server will be run on some trusted hosts with unrestricted connectivity to allow GNUnet users to test their network configuration. As written, the code allows any user on the Internet to cause the gnunet\-nat\-server to send 2-bytes of arbitrary data to any TCP or UDP port at any address. We believe that this is generally harmless. When running gnunet\-nat\-server, make sure to use a configuration that disables most NAT options but enables 'enable_nat_client' and sets 'internal_address' to the global IP address of your local host. Also, the gnunet\-helper\-nat\-client should be installed locally and run with root privileges (SUID), otherwise the gnunet\-nat\-server will not work properly. Note that gnunet\-nat\-server could be run via gnunet\-arm but typically is not. Also, the name of the host and port that gnunet\-nat\-server is run on should be specified in the NATSERVER option in the [setup] section of the configuration file of hosts that are supposed to autoconfigure with this server. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-transport(1) gnunet-0.10.1/doc/man/gnunet-arm.10000644000175000017500000000411012225232702013462 00000000000000.TH GNUNET\-ARM 1 "Jan 4, 2012" "GNUnet" .SH NAME gnunet\-arm \- control GNUnet services .SH SYNOPSIS .B gnunet\-arm .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-arm\fP can be used to start or stop GNUnet services, including the ARM service itself. The ARM service is a supervisor for GNUnet's service processes. ARM starts services on-demand or as configured and re-starts them if they crash. .SH OPTIONS .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-e, \-\-end" Shutdown all GNUnet services (including ARM itself). Running "gnunet-arm \-e" is the usual way to shutdown a GNUnet peer. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-i SERVICE, \-\-init=SERVICE" Starts the specified SERVICE if it is not already running. More specifically, this makes the service behave as if it were in the default services list. .B .IP "\-k SERVICE, \-\-kill=SERVICE" Stop the specified SERVICE if it is running. While this will kill the service right now, the service may be restarted immediately if other services depend on it (service is then started 'on-demand'). If the service used to be a 'default' service, its default-service status will be revoked. If the service was not a default service, it will just be (temporarily) stopped, but could be re-started on-demand at any time. .B .IP "\-m, \-\-monitor" Monitor service activity of ARM. In this mode, the command will not terminate until the user presses CTRL-C. .B .IP "\-s, \-\-start" Start all GNUnet default services on this system (and also ARM). Naturally, if a service is demanded by a default service, it will then also be started. Running "gnunet-arm \-s" is the usual way to start a GNUnet peer. .B .IP "\-I, \-\-info" List all running services. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-service\-arm(1) gnunet-0.10.1/doc/man/gnunet-publish.10000644000175000017500000003252712225232703014367 00000000000000.TH GNUNET-PUBLISH "1" "25 Feb 2012" "GNUnet" .SH NAME gnunet\-publish \- a command line interface for publishing new content into GNUnet .SH SYNOPSIS .B gnunet\-publish [\fIOPTIONS\fR] FILENAME .SH DESCRIPTION .PP In order to share files with other GNUnet users, the files must first be made available to GNUnet. GNUnet does not automatically share all files from a certain directory (however, you can do this with the gnunet\-auto\-share tool). In fact, even files that are downloaded are not automatically shared. .PP In order to start sharing files, the files must be added either using gnunet\-publish or a graphical interface such as gnunet\-fs\-gtk. The command line tool gnunet\-publish is more useful if many files are supposed to be added. gnunet\-publish can automatically publish batches of files, recursively publish directories, create directories that can be browsed within GNUnet and publish file lists in a namespace. When run on a directory, gnunet\-publish will always recursively publish all of the files in the directory. .PP gnunet\-publish can automatically extract keywords from the files that are shared. Users that want to download files from GNUnet use keywords to search for the appropriate content. You can disable keyword extraction with the \-D option. You can manually add keywords using the \-k option. The keywords are case\-sensitive. .PP In addition to searching for files by keyword, GNUnet allows organizing files into directories. With directories, the user only needs to find the directory in order to be able to download any of the files listed in the directory. Directories can contain pointers to other directories. .PP With gnunet\-publish, it is easy to create new directories simultaneously when adding the files. Simply pass the name of a directory instead of a file. .PP Since keywords can be spammed (any user can add any content under any keyword), GNUnet supports namespaces. A namespace is a subset of the searchspace into which only the holder of a certain pseudonym can add content. Any GNUnet user can create any number of pseudonyms using \fBgnunet\-pseudonym\fR. Pseudonyms are stored in the user's GNUnet directory. While pseudonyms are locally identified with an arbitrary string that the user selects when the pseudonym is created, the namespace is globally known only under the hash of the public key of the pseudonym. Since only the owner of the pseudonym can add content to the namespace, it is impossible for other users to pollute the namespace. gnunet\-publish automatically publishes the top\-directory (or the only file if only one file is specified) into the namespace if a pseudonym is specified. .PP It is possible to update content in GNUnet if that content was placed and obtained from a particular namespace. Updates are only possible for content in namespaces since this is the only way to assure that a malicious party can not supply counterfeited updates. Note that an update with GNUnet does not make the old content unavailable, GNUnet merely allows the publisher to point users to more recent versions. You can use the \-N option to specify the future identifier of an update. When using this option, a GNUnet client that finds the current (\-t) identifier will automatically begin a search for the update (\-N) identifier. If you later publish an update under the (\-N) identifier, both results will be given to the user. .PP You can use automatic meta\-data extraction (based on libextractor) or the command\-line option \-m to specify meta-data. For the \-m option you need to use the form keyword\-type:value. For example, use "\-m os:Linux" to specify that the operating system is Linux. Common meta\-data types are "author", "title" , "mimetype", "filename", "language", "subject" and "keywords". A full list can be obtained from the extract tool using the option \-\-list. The meta\-data is used to help users in searching for files on the network. The keywords are case\-sensitive. .PP GNUnet supports two styles of publishing files on the network. Publishing a file means that a copy of the file is made in the local (!) database of the node. Indexing a file means that an index is added to the local (!) database with symbolic links to the file itself. The links will use the SHA-512 hash of the entire file as the filename. Indexing is generally significantly more efficient and the default choice. However, indexing only works if the indexed file can be read (using the same absolute path) by gnunet-service-fs. If this is not the case, indexing will fail (and gnunet\-publish will automatically revert to publishing instead). Regardless of which method is used to publish the file, the file will be slowly (depending on how often it is requested and on how much bandwidth is available) dispersed into the network. If you publish or index a file and then leave the network, it will almost always NOT be available anymore. \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR Use alternate config file (if this option is not specified, the default is ~/.config/gnunet.conf). .TP \fB\-D\fR, \fB\-\-disable\-extractor\fR Disable use of GNU libextractor for finding additional keywords and metadata. .TP \fB\-e\fR, \fB\-\-extract\fR Print the list of keywords that will be used for each file given the current options. Do not perform any indexing or publishing. .TP \fB\-h\fR, \fB\-\-help\fR Print a brief help page with all the options. .TP \fB\-k \fIKEYWORD\fR, \fB\-\-key=KEYWORD\fR additional key to index the content with (to add multiple keys, specify multiple times). Each additional key is case\-sensitive. Can be specified multiple times. The keyword is only applied to the top\-level file or directory. .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=\fILOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-m \fITYPE:VALUE\fR, \fB\-\-meta=\fITYPE:VALUE\fR For the main file (or directory), set the metadata of the given TYPE to the given VALUE. Note that this will not add the respective VALUE to the set of keywords under which the file can be found. .TP \fB\-n\fR, \fB\-\-noindex\fR Executive summary: You probably don't need it. Do not index, full publishing. Note that directories, RBlocks, SBlocks and IBlocks are always published (even without this option). With this option, every block of the actual files is stored in encrypted form in the block database of the local peer. While this adds security if the local node is compromised (the adversary snags your machine), it is significantly less efficient compared to on\-demand encryption and is definitely not recommended for large files. .TP \fB\-N \fIID\fR, \fB\-\-next=\fIID\fR Specifies the next ID of a future version of the SBlock. This option is only valid together with the \-P option. This option can be used to specify what the identifier of an updated version will look like. Note that specifying \-i and \-N without \-t is not allowed. .TP \fB\-p \fIPRIORITY\fR, \fB\-\-prio=\fIPRIORITY\fR Executive summary: You probably don't need it. Set the priority of the published content (default: 365). If the local database is full, GNUnet will discard the content with the lowest ranking. Note that ranks change over time depending on popularity. The default should be high enough to preserve the locally published content in favor of content that migrates from other peers. .TP \fB\-P \fINAME\fR, \fB\-\-pseudonym=\fINAME\fR For the top\-level directory or file, create an SBlock that places the file into the namespace specified by the pseudonym NAME. .TP \fB\-r \fILEVEL\fR, \fB\-\-replication=\fILEVEL\fR Set the desired replication level. If CONTENT_PUSHING is set to YES, GNUnet will push each block (for the file) LEVEL times to other peers before doing normal "random" replication of all content. This option can be used to push some content out into the network harder. Note that pushing content LEVEL times into the network does not guarantee that there will actually be LEVEL replicas. .TP \fB\-s\fR, \fB\-\-simulate-only\fR When this option is used, gnunet\-publish will not actually publish the file but just simulate what would be done. This can be used to compute the GNUnet URI for a file without actually sharing it. .TP \fB\-t \fIID\fR, \fB\-\-this=\fIID\fR Specifies the ID of the SBlock. This option is only valid together with the\ \-s option. .TP \fB\-u \fIURI\fR, \fB\-\-uri=\fIURI\fR This option can be used to specify the URI of a file instead of a filename (this is the only case where the otherwise mandatory filename argument must be omitted). Instead of publishing a file or directory and using the corresponding URI, gnunet\-publish will use this URI and perform the selected namespace or keyword operations. This can be used to add additional keywords to a file that has already been shared or to add files to a namespace for which the URI is known but the content is not locally available. .TP \fB\-v\fR, \fB\-\-version\fR Print the version number. .TP \fB\-V\fR, \fB\-\-verbose\fR Be verbose. Using this option causes gnunet\-publish to print progress information and at the end the file identification that can be used to download the file from GNUnet. .SH SETTING ANONYMITY LEVEL The \fB\-a\fR option can be used to specify additional anonymity constraints. If set to 0, GNUnet will publish the file non-anonymously and in fact sign the advertisement for the file using your peer's private key. This will allow other users to download the file as fast as possible, including using non-anonymous methods (DHT, direct transfer). If you set it to 1 (default), you use the standard anonymous routing algorithm (which does not explicitly leak your identity). However, a powerful adversary may still be able to perform traffic analysis (statistics) to over time infer data about your identity. You can gain better privacy by specifying a higher level of anonymity, which increases the amount of cover traffic your own traffic will get, at the expense of performance. Note that regardless of the anonymity level you choose, peers that cache content in the network always use anonymity level 1. The definition of the ANONYMITY LEVEL is the following. 0 means no anonymity is required. Otherwise a value of 'v' means that 1 out of v bytes of "anonymous" traffic can be from the local user, leaving 'v-1' bytes of cover traffic per byte on the wire. Thus, if GNUnet routes n bytes of messages from foreign peers (using anonymous routing), it may originate n/(v-1) bytes of data in the same time\-period. The time\-period is twice the average delay that GNUnet defers forwarded queries. The default is 1 and this should be fine for most users. Also notice that if you choose very large values, you may end up having no throughput at all, especially if many of your fellow GNUnet\-peers all do the same. .SH EXAMPLES .PP \fBBasic examples\fR Index a file COPYING: # gnunet\-publish COPYING Publish a file COPYING: # gnunet\-publish \-n COPYING Index a file COPYING with the keywords \fBgpl\fR and \fBtest\fR: # gnunet\-publish \-k gpl \-k test COPYING Index a file COPYING with description "GNU License", mime-type "text/plain" and keywords \fBgpl\fR and \fBtest\fR: # gnunet\-publish \-m "description:GNU License" \-k gpl \-k test \-m "mimetype:text/plain" COPYING \fBUsing directories\fR Index the files COPYING and AUTHORS with keyword \fBtest\fR and build a directory containing the two files. Make the directory itself available under keyword \fBgnu\fR and disable keyword extraction using libextractor: # mkdir gnu # mv COPYING AUTHORS gnu/ # gnunet\-publish \-K test \-k gnu \-D gnu/ Neatly publish an image gallery in \fBkittendir/\fR and its subdirs with keyword \fBkittens\fR for the directory but no keywords for the individual files or subdirs (\-n). Force description for all files: # gnunet\-publish \-n \-m "description:Kitten collection" \-k kittens kittendir/ \fBSecure publishing with namespaces\fR Publish file COPYING with pseudonym RIAA-2 (\-P) and with identifier \fBgpl\fR (\-t) and no updates: # gnunet\-publish \-P RIAA-2 \-t gpl COPYING Recursively index /home/ogg and build a matching directory structure. Publish the top\-level directory into the namespace under the pseudonym RIAA-2 (\-P) under identifier 'MUSIC' (\-t) and promise to provide an update with identifier 'VIDEOS' (\-N): # gnunet\-publish \-P RIAA-2 \-t MUSIC \-N VIDEOS /home/ogg Recursively publish (\-n) /var/lib/mysql and build a matching directory structure, but disable the use of libextractor to extract keywords (\-n). Print the file identifiers (\-V) that can be used to retrieve the files. This will store a copy of the MySQL database in GNUnet but without adding any keywords to search for it. Thus only people that have been told the secret file identifiers printed with the \-V option can retrieve the (secret?) files: # gnunet\-publish \-nV /var/lib/mysql Create a namespace entry 'root' in namespace MPAA-1 and announce that the next update will be called 'next': # gnunet\-publish \-P MPAA-1 \-t root \-N next noise.mp3 Update the previous entry, do not allow any future updates: # gnunet\-publish \-P MPAA-1 \-t next noise_updated.mp3 .SH FILES .TP ~/.config/gnunet.conf GNUnet configuration file .SH "REPORTING BUGS" Report bugs to or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-auto\-share\fP(1), \fBgnunet\-fs\-gtk\fP(1), \fBgnunet\-search\fP(1), \fBgnunet\-download\fP(1), \fBgnunet.conf\fP(5), \fBextract\fP(1) gnunet-0.10.1/doc/man/gnunet-transport.10000644000175000017500000000500412225232703014743 00000000000000.TH gnunet\-transport "1" "26 Oct 2011" "GNUnet" .SH NAME gnunet\-transport \- measure and control the transport subsystem .SH SYNOPSIS .B gnunet\-transport [\fIOPTIONS\fR] .SH DESCRIPTION .PP gnunet\-transport is a tool to access various functions of GNUnet's transport subsystem from the command\-line. Most of these are not expected to be useful for end-users. gnunet\-transport can be used to evaluate the performance of the transports, force a peer to connect to another peer (if possible). Other functions should be added in the near future. .TP \fB\-b\fR, \fB\-\-benchmark\fR measure how fast we are receiving data (from all connections). On exit, the data rate will be reported. Runs until aborted with CTRL-C. .TP \fB\-C \fIPEER\fR, \fB\-\-connect=PEER\fR peer to connect to (used in conjunction with \-p) .TP \fB\-c \fIFILENAME\fR, \fB\-\-config=FILENAME\fR configuration file to use .TP \fB\-e \fB\-\-events\fR provide information about all connect and disconnect events (continuously) .TP \fB\-h\fR, \fB\-\-help\fR print help page .TP \fB\-i\fR, \fB\-\-information\fR print information about our current connections (once) .TP \fB\-L \fILOGLEVEL\fR, \fB\-\-loglevel=LOGLEVEL\fR Change the loglevel. Possible values for LOGLEVEL are ERROR, WARNING, INFO and DEBUG. .TP \fB\-l \fILOGFILE\fR, \fB\-\-logfile=LOGFILE\fR configure logging to write logs to LOGFILE .TP \fB\-m\fR, \fB\-\-monitor\fR print information about our current connections (continuously) .TP \fB\-p \fIPEER\fR, \fB\-\-peer=PEER\fR the peer identity .TP \fB\-s\fR, \fB\-\-send\fR transmit (dummy) traffic as quickly as possible to the peer specified with the \-p option. The rate will still be limited by the quota(s) determined by the peers (ATS subsystem). Will run until CTRL\-C is pressed or until the connection to the other peer is disrupted. .TP \fB\-t\fR, \fB\-\-test\fR test transport configuration. With this flag, the tool will check if each of the configured transport plugins has a working address. Plugins that do not have a listen port configured will be ignored. The test is performed with the help of an external server (by default running on gnunet.org) which tries to contact the local machine. The test can only work if the local GNUnet peer is not yet running. .TP \fB\-v\fR, \fB\-\-version\fR print the version number .TP \fB\-V\fR, \fB\-\-verbose\fR be verbose .SH NOTES .SH "REPORTING BUGS" Report bugs by using mantis or by sending electronic mail to .SH "SEE ALSO" \fBgnunet\-arm\fP(1) gnunet-0.10.1/doc/man/gnunet-vpn.10000644000175000017500000000526212225232703013520 00000000000000.TH GNUNET\-VPN 1 "25 Feb 2012" "GNUnet" .SH NAME gnunet\-vpn \- manually setup a GNUnet VPN tunnel .SH SYNOPSIS .B gnunet\-vpn .RI [ options ] .br .SH DESCRIPTION \fBgnunet\-vpn\fP can be used to manually setup a VPN tunnel via the GNUnet network. There are two main types of tunnels. Tunnels to an exit node which routes the traffic to the global Internet, and tunnels to a node that runs a service only within GNUnet. Depending on the type of tunnel, gnunet\-vpn takes different options. The "\-i" option is required for tunnels to an exit node, whereas the "\-p" and "\-s" options in conjunction with either "\-u" or "\-t" are required for tunnels to services. For exit tunnels, both UDP and TCP traffic will be redirected. For service tunnels, either UDP ("\-u") or TCP ("\-t") traffic will be redirected. The tool will display the IP address for this end of the tunnel. The address can be displayed as soon as it has been allocated, or only after ("\-a") the tunnel has been created. .SH OPTIONS .B .IP "\-4, \-\-ipv4" Desired IP address on this end of the tunnel should be an IPv4 address. .B .IP "\-6, \-\-ipv6" Desired IP address on this end of the tunnel should be an IPv6 address. .B .IP "\-c FILENAME, \-\-config=FILENAME" Use the configuration file FILENAME. .B .IP "\-d TIME, \-\-duration TIME" The mapping should be established for TIME. The value given must be a number followed by a space and a time unit, for example "500 ms". Note that the quotes are required on the shell. Default is 5 minutes. .B .IP "\-h, \-\-help" Print short help on options. .B .IP "\-i IP, \-\-ip IP" Tunnel should be to an exit node and connect to the given IPv4 or IPv6 IP address. Note that you can specify an IPv6 address as the target here, even in combination with "\-4" (4to6) and similarly you can specify an IPv4 address in combination with "\-6" (6to4). .B .IP "\-L LOGLEVEL, \-\-loglevel=LOGLEVEL" Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING and ERROR. .B .IP "\-p PEERID, \-\-peer=PEERID" Name of the peer offering the service to connect to. Cannot be used in conjunction with "\-i", requires "\-s". .B .IP "\-s NAME, \-\-service=NAME" Name of the service running on the target peer. Cannot be used in conjunction with "\-i", requires "\-p". .B .IP "\-t, \-\-tcp" Service runs TCP. Either "\-t" or "\-u" must be specified when using "\-s". .B .IP "\-u, \-\-udp" Service runs UDP. Either "\-t" or "\-u" must be specified when using "\-s". .B .IP "\-V, \-\-verbose" Be verbose. .B .IP "\-v, \-\-version" Print GNUnet version number. .SH BUGS Report bugs by using Mantis or by sending electronic mail to .SH SEE ALSO gnunet\-setup(1) gnunet-0.10.1/doc/doxygen/0000755000175000017500000000000012320755622012320 500000000000000gnunet-0.10.1/doc/doxygen/Makefile.in0000644000175000017500000003460712320752057014316 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = doc/doxygen DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/doxygen/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/doxygen/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am all: @echo -e \ "Generate documentation:\n" \ "\tmake full - full documentation with dependency graphs (slow)\n" \ "\tmake fast - fast mode without dependency graphs" full: gnunet.doxy doxygen $< fast: gnunet.doxy sed 's/\(HAVE_DOT.*=\).*/\1 NO/' $< | doxygen - clean: rm -rf html # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/doc/doxygen/Makefile.am0000644000175000017500000000044012272460772014277 00000000000000all: @echo -e \ "Generate documentation:\n" \ "\tmake full - full documentation with dependency graphs (slow)\n" \ "\tmake fast - fast mode without dependency graphs" full: gnunet.doxy doxygen $< fast: gnunet.doxy sed 's/\(HAVE_DOT.*=\).*/\1 NO/' $< | doxygen - clean: rm -rf html gnunet-0.10.1/Makefile.am0000644000175000017500000000117712272460772012065 00000000000000AM_CPPFLAGS = -I$(top_srcdir)/src/include SUBDIRS = contrib doc m4 src po pkgconfig EXTRA_DIST = \ ABOUT-NLS \ config.rpath \ install-sh \ acinclude.m4 gnunetincludedir = $(includedir)/gnunet gnunetinclude_HEADERS = gnunet_config.h docdir = $(datadir)/doc/gnunet/ doc_DATA = COPYING README ACLOCAL_AMFLAGS = -I m4 ChangeLog: if test -f $(top_srcdir)/.svn/entries; then \ svn log -v --xml -r HEAD:18409 | \ xsltproc --stringparam ignore-message-starting "-" \ --stringparam strip-prefix "gnunet" \ --stringparam include-rev "yes" $(top_srcdir)/contrib/svn2cl.xsl - > $@; \ fi dist: ChangeLog .PHONY: ChangeLog gnunet-0.10.1/compile0000755000175000017500000001624512320752057011403 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: gnunet-0.10.1/INSTALL0000644000175000017500000003661012320752057011054 00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command `./configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. gnunet-0.10.1/config.rpath0000755000175000017500000003744411374167231012343 00000000000000#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2006 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; darwin*) case $cc_basename in xlc*) wl='-Wl,' ;; esac ;; mingw* | pw32* | os2*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux*) case $cc_basename in icc* | ecc*) wl='-Wl,' ;; pgcc | pgf77 | pgf90) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; sco3.2v5*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) wl='-Wl,' ;; sysv4*MP*) ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we cannot use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; interix3*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; linux*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi[45]*) ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if test "$GCC" = yes ; then : else case $cc_basename in xlc*) ;; *) ld_shlibs=no ;; esac fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd1*) ld_shlibs=no ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | kfreebsd*-gnu | dragonfly*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. libname_spec='lib$name' case "$host_os" in aix3*) ;; aix4* | aix5*) ;; amigaos*) ;; beos*) ;; bsdi[45]*) ;; cygwin* | mingw* | pw32*) shrext=.dll ;; darwin* | rhapsody*) shrext=.dylib ;; dgux*) ;; freebsd1*) ;; kfreebsd*-gnu) ;; freebsd* | dragonfly*) ;; gnu*) ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac ;; interix3*) ;; irix5* | irix6* | nonstopux*) case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux*) ;; knetbsd*-gnu) ;; netbsd*) ;; newsos6) ;; nto-qnx*) ;; openbsd*) ;; os2*) libname_spec='$name' shrext=.dll ;; osf3* | osf4* | osf5*) ;; solaris*) ;; sunos4*) ;; sysv4 | sysv4.3*) ;; sysv4*MP*) ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) ;; uts4*) ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' < Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . gnunet-0.10.1/m4/0000755000175000017500000000000012320755622010416 500000000000000gnunet-0.10.1/m4/inttypes_h.m40000644000175000017500000000164411374167230012773 00000000000000# inttypes_h.m4 serial 7 dnl Copyright (C) 1997-2004, 2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_INTTYPES_H_WITH_UINTMAX if exists, # doesn't clash with , and declares uintmax_t. AC_DEFUN([gl_AC_HEADER_INTTYPES_H], [ AC_CACHE_CHECK([for inttypes.h], gl_cv_header_inttypes_h, [AC_TRY_COMPILE( [#include #include ], [uintmax_t i = (uintmax_t) -1; return !i;], gl_cv_header_inttypes_h=yes, gl_cv_header_inttypes_h=no)]) if test $gl_cv_header_inttypes_h = yes; then AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1, [Define if exists, doesn't clash with , and declares uintmax_t. ]) fi ]) gnunet-0.10.1/m4/isc-posix.m40000644000175000017500000000213311374167230012515 00000000000000# isc-posix.m4 serial 2 (gettext-0.11.2) dnl Copyright (C) 1995-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. # This file is not needed with autoconf-2.53 and newer. Remove it in 2005. # This test replaces the one in autoconf. # Currently this macro should have the same name as the autoconf macro # because gettext's gettext.m4 (distributed in the automake package) # still uses it. Otherwise, the use in gettext.m4 makes autoheader # give these diagnostics: # configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX # configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX undefine([AC_ISC_POSIX]) AC_DEFUN([AC_ISC_POSIX], [ dnl This test replaces the obsolescent AC_ISC_POSIX kludge. AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"]) ] ) gnunet-0.10.1/m4/signed.m40000644000175000017500000000140111374167230012045 00000000000000# signed.m4 serial 1 (gettext-0.10.40) dnl Copyright (C) 2001-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl From Bruno Haible. AC_DEFUN([bh_C_SIGNED], [ AC_CACHE_CHECK([for signed], bh_cv_c_signed, [AC_TRY_COMPILE(, [signed char x;], bh_cv_c_signed=yes, bh_cv_c_signed=no)]) if test $bh_cv_c_signed = no; then AC_DEFINE(signed, , [Define to empty if the C compiler doesn't support this keyword.]) fi ]) gnunet-0.10.1/m4/wint_t.m40000644000175000017500000000130411374167230012102 00000000000000# wint_t.m4 serial 1 (gettext-0.12) dnl Copyright (C) 2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether has the 'wint_t' type. dnl Prerequisite: AC_PROG_CC AC_DEFUN([gt_TYPE_WINT_T], [ AC_CACHE_CHECK([for wint_t], gt_cv_c_wint_t, [AC_TRY_COMPILE([#include wint_t foo = (wchar_t)'\0';], , gt_cv_c_wint_t=yes, gt_cv_c_wint_t=no)]) if test $gt_cv_c_wint_t = yes; then AC_DEFINE(HAVE_WINT_T, 1, [Define if you have the 'wint_t' type.]) fi ]) gnunet-0.10.1/m4/gtk-2.0.m40000644000175000017500000001655411374167230011675 00000000000000# Configure paths for GTK+ # Owen Taylor 1997-2001 dnl AM_PATH_GTK_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) dnl Test for GTK+, and define GTK_CFLAGS and GTK_LIBS, if gthread is specified in MODULES, dnl pass to pkg-config dnl AC_DEFUN([AM_PATH_GTK_2_0], [dnl dnl Get the cflags and libraries from pkg-config dnl AC_ARG_ENABLE(gtktest, [ --disable-gtktest do not try to compile and run a test GTK+ program], , enable_gtktest=yes) pkg_config_args=gtk+-2.0 for module in . $4 do case "$module" in gthread) pkg_config_args="$pkg_config_args gthread-2.0" ;; esac done no_gtk="" AC_PATH_PROG(PKG_CONFIG, pkg-config, no) if test x$PKG_CONFIG != xno ; then if pkg-config --atleast-pkgconfig-version 0.7 ; then : else echo "*** pkg-config too old; version 0.7 or better required." no_gtk=yes PKG_CONFIG=no fi else no_gtk=yes fi min_gtk_version=ifelse([$1], ,2.0.0,$1) AC_MSG_CHECKING(for GTK+ - version >= $min_gtk_version) if test x$PKG_CONFIG != xno ; then ## don't try to run the test against uninstalled libtool libs if $PKG_CONFIG --uninstalled $pkg_config_args; then echo "Will use uninstalled version of GTK+ found in PKG_CONFIG_PATH" enable_gtktest=no fi if $PKG_CONFIG --atleast-version $min_gtk_version $pkg_config_args; then : else no_gtk=yes fi fi if test x"$no_gtk" = x ; then GTK_CFLAGS=`$PKG_CONFIG $pkg_config_args --cflags` GTK_LIBS=`$PKG_CONFIG $pkg_config_args --libs` gtk_config_major_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` gtk_config_minor_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` gtk_config_micro_version=`$PKG_CONFIG --modversion gtk+-2.0 | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "x$enable_gtktest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $GTK_CFLAGS" LIBS="$GTK_LIBS $LIBS" dnl dnl Now check if the installed GTK+ is sufficiently new. (Also sanity dnl checks the results of pkg-config to some extent) dnl rm -f conf.gtktest AC_TRY_RUN([ #include #include #include int main () { int major, minor, micro; char *tmp_version; system ("touch conf.gtktest"); /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = g_strdup("$min_gtk_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string\n", "$min_gtk_version"); exit(1); } if ((gtk_major_version != $gtk_config_major_version) || (gtk_minor_version != $gtk_config_minor_version) || (gtk_micro_version != $gtk_config_micro_version)) { printf("\n*** 'pkg-config --modversion gtk+-2.0' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version, gtk_major_version, gtk_minor_version, gtk_micro_version); printf ("*** was found! If pkg-config was correct, then it is best\n"); printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n"); printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); printf("*** required on your system.\n"); printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); printf("*** to point to the correct configuration files\n"); } else if ((gtk_major_version != GTK_MAJOR_VERSION) || (gtk_minor_version != GTK_MINOR_VERSION) || (gtk_micro_version != GTK_MICRO_VERSION)) { printf("*** GTK+ header files (version %d.%d.%d) do not match\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); printf("*** library (version %d.%d.%d)\n", gtk_major_version, gtk_minor_version, gtk_micro_version); } else { if ((gtk_major_version > major) || ((gtk_major_version == major) && (gtk_minor_version > minor)) || ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro))) { return 0; } else { printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n", gtk_major_version, gtk_minor_version, gtk_micro_version); printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n", major, minor, micro); printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n"); printf("***\n"); printf("*** If you have already installed a sufficiently new version, this error\n"); printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); printf("*** being found. The easiest way to fix this is to remove the old version\n"); printf("*** of GTK+, but you can also set the PKG_CONFIG environment to point to the\n"); printf("*** correct copy of pkg-config. (In this case, you will have to\n"); printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); printf("*** so that the correct libraries are found at run-time))\n"); } } return 1; } ],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_gtk" = x ; then AC_MSG_RESULT(yes (version $gtk_config_major_version.$gtk_config_minor_version.$gtk_config_micro_version)) ifelse([$2], , :, [$2]) else AC_MSG_RESULT(no) if test "$PKG_CONFIG" = "no" ; then echo "*** A new enough version of pkg-config was not found." echo "*** See http://pkgconfig.sourceforge.net" else if test -f conf.gtktest ; then : else echo "*** Could not run GTK+ test program, checking why..." ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $GTK_CFLAGS" LIBS="$LIBS $GTK_LIBS" AC_TRY_LINK([ #include #include ], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding GTK+ or finding the wrong" echo "*** version of GTK+. If it is not finding GTK+, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means GTK+ is incorrectly installed."]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi GTK_CFLAGS="" GTK_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_LIBS) rm -f conf.gtktest ]) gnunet-0.10.1/m4/libgnurl.m40000644000175000017500000002416412235670732012430 00000000000000# LIBGNURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION], # [ACTION-IF-YES], [ACTION-IF-NO]) # ---------------------------------------------------------- # David Shaw May-09-2006 # # Checks for libgnurl. DEFAULT-ACTION is the string yes or no to # specify whether to default to --with-libgnurl or --without-libgnurl. # If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the # minimum version of libgnurl to accept. Pass the version as a regular # version number like 7.10.1. If not supplied, any version is # accepted. ACTION-IF-YES is a list of shell commands to run if # libgnurl was successfully found and passed the various tests. # ACTION-IF-NO is a list of shell commands that are run otherwise. # Note that using --without-libgnurl does run ACTION-IF-NO. # # This macro #defines HAVE_LIBGNURL if a working libgnurl setup is # found, and sets @LIBGNURL@ and @LIBGNURL_CPPFLAGS@ to the necessary # values. Other useful defines are LIBGNURL_FEATURE_xxx where xxx are # the various features supported by libgnurl, and LIBGNURL_PROTOCOL_yyy # where yyy are the various protocols supported by libgnurl. Both xxx # and yyy are capitalized. See the list of AH_TEMPLATEs at the top of # the macro for the complete list of possible defines. Shell # variables $libgnurl_feature_xxx and $libgnurl_protocol_yyy are also # defined to 'yes' for those features and protocols that were found. # Note that xxx and yyy keep the same capitalization as in the # gnurl-config list (e.g. it's "HTTP" and not "http"). # # Users may override the detected values by doing something like: # LIBGNURL="-lgnurl" LIBGNURL_CPPFLAGS="-I/usr/myinclude" ./configure # # For the sake of sanity, this macro assumes that any libgnurl that is # found is after version 7.7.2, the first version that included the # gnurl-config script. Note that it is very important for people # packaging binary versions of libgnurl to include this script! # Without gnurl-config, we can only guess what protocols are available, # or use gnurl_version_info to figure it out at runtime. AC_DEFUN([LIBGNURL_CHECK_CONFIG], [ AH_TEMPLATE([LIBGNURL_FEATURE_SSL],[Defined if libgnurl supports SSL]) AH_TEMPLATE([LIBGNURL_FEATURE_KRB4],[Defined if libgnurl supports KRB4]) AH_TEMPLATE([LIBGNURL_FEATURE_IPV6],[Defined if libgnurl supports IPv6]) AH_TEMPLATE([LIBGNURL_FEATURE_LIBZ],[Defined if libgnurl supports libz]) AH_TEMPLATE([LIBGNURL_FEATURE_ASYNCHDNS],[Defined if libgnurl supports AsynchDNS]) AH_TEMPLATE([LIBGNURL_FEATURE_IDN],[Defined if libgnurl supports IDN]) AH_TEMPLATE([LIBGNURL_FEATURE_SSPI],[Defined if libgnurl supports SSPI]) AH_TEMPLATE([LIBGNURL_FEATURE_NTLM],[Defined if libgnurl supports NTLM]) AH_TEMPLATE([LIBGNURL_PROTOCOL_HTTP],[Defined if libgnurl supports HTTP]) AH_TEMPLATE([LIBGNURL_PROTOCOL_HTTPS],[Defined if libgnurl supports HTTPS]) AH_TEMPLATE([LIBGNURL_PROTOCOL_FTP],[Defined if libgnurl supports FTP]) AH_TEMPLATE([LIBGNURL_PROTOCOL_FTPS],[Defined if libgnurl supports FTPS]) AH_TEMPLATE([LIBGNURL_PROTOCOL_FILE],[Defined if libgnurl supports FILE]) AH_TEMPLATE([LIBGNURL_PROTOCOL_TELNET],[Defined if libgnurl supports TELNET]) AH_TEMPLATE([LIBGNURL_PROTOCOL_LDAP],[Defined if libgnurl supports LDAP]) AH_TEMPLATE([LIBGNURL_PROTOCOL_DICT],[Defined if libgnurl supports DICT]) AH_TEMPLATE([LIBGNURL_PROTOCOL_TFTP],[Defined if libgnurl supports TFTP]) AH_TEMPLATE([LIBGNURL_PROTOCOL_RTSP],[Defined if libgnurl supports RTSP]) AH_TEMPLATE([LIBGNURL_PROTOCOL_POP3],[Defined if libgnurl supports POP3]) AH_TEMPLATE([LIBGNURL_PROTOCOL_IMAP],[Defined if libgnurl supports IMAP]) AH_TEMPLATE([LIBGNURL_PROTOCOL_SMTP],[Defined if libgnurl supports SMTP]) AC_ARG_WITH(libgnurl, AC_HELP_STRING([--with-libgnurl=PREFIX],[look for the gnurl library in PREFIX/lib and headers in PREFIX/include]), [_libgnurl_with=$withval],[_libgnurl_with=ifelse([$1],,[yes],[$1])]) if test "$_libgnurl_with" != "no" ; then AC_PROG_AWK _libgnurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'" _libgnurl_try_link=yes if test -d "$_libgnurl_with" ; then LIBGNURL_CPPFLAGS="-I$withval/include" _libgnurl_ldflags="-L$withval/lib" AC_PATH_PROG([_libgnurl_config],[gnurl-config],[], ["$withval/bin"]) else AC_PATH_PROG([_libgnurl_config],[gnurl-config],[],[$PATH]) fi if test x$_libgnurl_config != "x" ; then AC_CACHE_CHECK([for the version of libgnurl], [libgnurl_cv_lib_gnurl_version], [libgnurl_cv_lib_gnurl_version=`$_libgnurl_config --version | $AWK '{print $[]2}'`]) _libgnurl_version=`echo $libgnurl_cv_lib_gnurl_version | $_libgnurl_version_parse` _libgnurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libgnurl_version_parse` if test $_libgnurl_wanted -gt 0 ; then AC_CACHE_CHECK([for libgnurl >= version $2], [libgnurl_cv_lib_version_ok], [ if test $_libgnurl_version -ge $_libgnurl_wanted ; then libgnurl_cv_lib_version_ok=yes else libgnurl_cv_lib_version_ok=no fi ]) fi if test $_libgnurl_wanted -eq 0 || test x$libgnurl_cv_lib_version_ok = xyes ; then if test x"$LIBGNURL_CPPFLAGS" = "x" ; then LIBGNURL_CPPFLAGS=`$_libgnurl_config --cflags` fi if test x"$LIBGNURL" = "x" ; then LIBGNURL=`$_libgnurl_config --libs` # This is so silly, but Apple actually has a bug in their # gnurl-config script. Fixed in Tiger, but there are still # lots of Panther installs around. case "${host}" in powerpc-apple-darwin7*) LIBGNURL=`echo $LIBGNURL | sed -e 's|-arch i386||g'` ;; esac fi # All gnurl-config scripts support --feature _libgnurl_features=`$_libgnurl_config --feature` # Is it modern enough to have --protocols? (7.12.4) if test $_libgnurl_version -ge 461828 ; then _libgnurl_protocols=`$_libgnurl_config --protocols` fi else _libgnurl_try_link=no fi unset _libgnurl_wanted fi if test $_libgnurl_try_link = yes ; then # we didn't find gnurl-config, so let's see if the user-supplied # link line (or failing that, "-lgnurl") is enough. LIBGNURL=${LIBGNURL-"$_libgnurl_ldflags -lgnurl"} AC_CACHE_CHECK([whether libgnurl is usable], [libgnurl_cv_lib_gnurl_usable], [ _libgnurl_save_cppflags=$CPPFLAGS CPPFLAGS="$LIBGNURL_CPPFLAGS $CPPFLAGS" _libgnurl_save_libs=$LIBS LIBS="$LIBGNURL $LIBS" AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],[ /* Try and use a few common options to force a failure if we are missing symbols or can't link. */ int x; curl_easy_setopt(NULL,CURLOPT_URL,NULL); x=CURL_ERROR_SIZE; x=CURLOPT_WRITEFUNCTION; x=CURLOPT_FILE; x=CURLOPT_ERRORBUFFER; x=CURLOPT_STDERR; x=CURLOPT_VERBOSE; ])],libgnurl_cv_lib_gnurl_usable=yes,libgnurl_cv_lib_gnurl_usable=no) CPPFLAGS=$_libgnurl_save_cppflags LIBS=$_libgnurl_save_libs unset _libgnurl_save_cppflags unset _libgnurl_save_libs ]) if test $libgnurl_cv_lib_gnurl_usable = yes ; then # Does gnurl_free() exist in this version of libgnurl? # If not, fake it with free() _libgnurl_save_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LIBGNURL_CPPFLAGS" _libgnurl_save_libs=$LIBS LIBS="$LIBS $LIBGNURL" AC_CHECK_FUNC(curl_free,, AC_DEFINE(curl_free,free, [Define curl_free() as free() if our version of gnurl lacks curl_free.])) CPPFLAGS=$_libgnurl_save_cppflags LIBS=$_libgnurl_save_libs unset _libgnurl_save_cppflags unset _libgnurl_save_libs AC_DEFINE(HAVE_LIBGNURL,1, [Define to 1 if you have a functional gnurl library.]) AC_SUBST(LIBGNURL_CPPFLAGS) AC_SUBST(LIBGNURL) for _libgnurl_feature in $_libgnurl_features ; do AC_DEFINE_UNQUOTED(AS_TR_CPP(libgnurl_feature_$_libgnurl_feature),[1]) eval AS_TR_SH(libgnurl_feature_$_libgnurl_feature)=yes done if test "x$_libgnurl_protocols" = "x" ; then # We don't have --protocols, so just assume that all # protocols are available _libgnurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" if test x$libgnurl_feature_SSL = xyes ; then _libgnurl_protocols="$_libgnurl_protocols HTTPS" # FTPS wasn't standards-compliant until version # 7.11.0 (0x070b00 == 461568) if test $_libgnurl_version -ge 461568; then _libgnurl_protocols="$_libgnurl_protocols FTPS" fi fi # RTSP, IMAP, POP3 and SMTP were added in # 7.20.0 (0x071400 == 463872) if test $_libgnurl_version -ge 463872; then _libgnurl_protocols="$_libgnurl_protocols RTSP IMAP POP3 SMTP" fi fi for _libgnurl_protocol in $_libgnurl_protocols ; do AC_DEFINE_UNQUOTED(AS_TR_CPP(libgnurl_protocol_$_libgnurl_protocol),[1]) eval AS_TR_SH(libgnurl_protocol_$_libgnurl_protocol)=yes done else unset LIBGNURL unset LIBGNURL_CPPFLAGS fi fi unset _libgnurl_try_link unset _libgnurl_version_parse unset _libgnurl_config unset _libgnurl_feature unset _libgnurl_features unset _libgnurl_protocol unset _libgnurl_protocols unset _libgnurl_version unset _libgnurl_ldflags fi if test x$_libgnurl_with = xno || test x$libgnurl_cv_lib_gnurl_usable != xyes ; then # This is the IF-NO path ifelse([$4],,:,[$4]) else # This is the IF-YES path ifelse([$3],,:,[$3]) fi unset _libgnurl_with ])dnl gnunet-0.10.1/m4/glibc2.m40000644000175000017500000000135411374167230011745 00000000000000# glibc2.m4 serial 1 dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # Test for the GNU C Library, version 2.0 or newer. # From Bruno Haible. AC_DEFUN([gt_GLIBC2], [ AC_CACHE_CHECK(whether we are using the GNU C Library 2 or newer, ac_cv_gnu_library_2, [AC_EGREP_CPP([Lucky GNU user], [ #include #ifdef __GNU_LIBRARY__ #if (__GLIBC__ >= 2) Lucky GNU user #endif #endif ], ac_cv_gnu_library_2=yes, ac_cv_gnu_library_2=no) ] ) AC_SUBST(GLIBC2) GLIBC2="$ac_cv_gnu_library_2" ] ) gnunet-0.10.1/m4/codeset.m40000644000175000017500000000136611374167230012234 00000000000000# codeset.m4 serial 2 (gettext-0.16) dnl Copyright (C) 2000-2002, 2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_LANGINFO_CODESET], [ AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset, [AC_TRY_LINK([#include ], [char* cs = nl_langinfo(CODESET); return !cs;], am_cv_langinfo_codeset=yes, am_cv_langinfo_codeset=no) ]) if test $am_cv_langinfo_codeset = yes; then AC_DEFINE(HAVE_LANGINFO_CODESET, 1, [Define if you have and nl_langinfo(CODESET).]) fi ]) gnunet-0.10.1/m4/intdiv0.m40000644000175000017500000000334011374167230012155 00000000000000# intdiv0.m4 serial 1 (gettext-0.11.3) dnl Copyright (C) 2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([gt_INTDIV0], [ AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], gt_cv_int_divbyzero_sigfpe, [ AC_TRY_RUN([ #include #include static void #ifdef __cplusplus sigfpe_handler (int sig) #else sigfpe_handler (sig) int sig; #endif { /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ exit (sig != SIGFPE); } int x = 1; int y = 0; int z; int nan; int main () { signal (SIGFPE, sigfpe_handler); /* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ #if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) signal (SIGTRAP, sigfpe_handler); #endif /* Linux/SPARC yields signal SIGILL. */ #if defined (__sparc__) && defined (__linux__) signal (SIGILL, sigfpe_handler); #endif z = x / y; nan = y / y; exit (1); } ], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no, [ # Guess based on the CPU. case "$host_cpu" in alpha* | i[34567]86 | m68k | s390*) gt_cv_int_divbyzero_sigfpe="guessing yes";; *) gt_cv_int_divbyzero_sigfpe="guessing no";; esac ]) ]) case "$gt_cv_int_divbyzero_sigfpe" in *yes) value=1;; *) value=0;; esac AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value, [Define if integer division by zero raises signal SIGFPE.]) ]) gnunet-0.10.1/m4/intmax.m40000644000175000017500000000201111374167230012072 00000000000000# intmax.m4 serial 3 (gettext-0.16) dnl Copyright (C) 2002-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether the system has the 'intmax_t' type, but don't attempt to dnl find a replacement if it is lacking. AC_DEFUN([gt_TYPE_INTMAX_T], [ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) AC_CACHE_CHECK(for intmax_t, gt_cv_c_intmax_t, [AC_TRY_COMPILE([ #include #include #if HAVE_STDINT_H_WITH_UINTMAX #include #endif #if HAVE_INTTYPES_H_WITH_UINTMAX #include #endif ], [intmax_t x = -1; return !x;], gt_cv_c_intmax_t=yes, gt_cv_c_intmax_t=no)]) if test $gt_cv_c_intmax_t = yes; then AC_DEFINE(HAVE_INTMAX_T, 1, [Define if you have the 'intmax_t' type in or .]) fi ]) gnunet-0.10.1/m4/longlong.m40000644000175000017500000000327411374167230012425 00000000000000# longlong.m4 serial 8 dnl Copyright (C) 1999-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_LONG_LONG_INT if 'long long int' works. # This fixes a bug in Autoconf 2.60, but can be removed once we # assume 2.61 everywhere. # Note: If the type 'long long int' exists but is only 32 bits large # (as on some very old compilers), AC_TYPE_LONG_LONG_INT will not be # defined. In this case you can treat 'long long int' like 'long int'. AC_DEFUN([AC_TYPE_LONG_LONG_INT], [ AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], [AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[long long int ll = 9223372036854775807ll; long long int nll = -9223372036854775807LL; typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) ? 1 : -1)]; int i = 63;]], [[long long int llmax = 9223372036854775807ll; return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) | (llmax / ll) | (llmax % ll));]])], [ac_cv_type_long_long_int=yes], [ac_cv_type_long_long_int=no])]) if test $ac_cv_type_long_long_int = yes; then AC_DEFINE([HAVE_LONG_LONG_INT], 1, [Define to 1 if the system has the type `long long int'.]) fi ]) # This macro is obsolescent and should go away soon. AC_DEFUN([gl_AC_TYPE_LONG_LONG], [ AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) ac_cv_type_long_long=$ac_cv_type_long_long_int if test $ac_cv_type_long_long = yes; then AC_DEFINE(HAVE_LONG_LONG, 1, [Define if you have the 'long long' type.]) fi ]) gnunet-0.10.1/m4/libgcrypt.m40000644000175000017500000001011611374167230012576 00000000000000dnl Autoconf macros for libgcrypt dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc. dnl dnl This file is free software; as a special exception the author gives dnl unlimited permission to copy and/or distribute it, with or without dnl modifications, as long as this notice is preserved. dnl dnl This file is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed dnl with the API version to also check the API compatibility. Example: dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using dnl this features allows to prevent build against newer versions of libgcrypt dnl with a changed API. dnl AC_DEFUN([AM_PATH_LIBGCRYPT], [ AC_ARG_WITH(libgcrypt-prefix, AC_HELP_STRING([--with-libgcrypt-prefix=PFX], [prefix where LIBGCRYPT is installed (optional)]), libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") if test x$libgcrypt_config_prefix != x ; then if test x${LIBGCRYPT_CONFIG+set} != xset ; then LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config fi fi AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) tmp=ifelse([$1], ,1:1.2.0,$1) if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` else req_libgcrypt_api=0 min_libgcrypt_version="$tmp" fi AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) ok=no if test "$LIBGCRYPT_CONFIG" != "no" ; then req_major=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` req_minor=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` req_micro=`echo $min_libgcrypt_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` major=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` minor=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` micro=`echo $libgcrypt_config_version | \ sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` if test "$major" -gt "$req_major"; then ok=yes else if test "$major" -eq "$req_major"; then if test "$minor" -gt "$req_minor"; then ok=yes else if test "$minor" -eq "$req_minor"; then if test "$micro" -ge "$req_micro"; then ok=yes fi fi fi fi fi fi if test $ok = yes; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi if test $ok = yes; then # If we have a recent libgcrypt, we should also check that the # API is compatible if test "$req_libgcrypt_api" -gt 0 ; then tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` if test "$tmp" -gt 0 ; then AC_MSG_CHECKING([LIBGCRYPT API version]) if test "$req_libgcrypt_api" -eq "$tmp" ; then AC_MSG_RESULT(okay) else ok=no AC_MSG_RESULT([does not match (want=$req_libgcrypt_api got=$tmp)]) fi fi fi fi if test $ok = yes; then LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` ifelse([$2], , :, [$2]) else LIBGCRYPT_CFLAGS="" LIBGCRYPT_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(LIBGCRYPT_CFLAGS) AC_SUBST(LIBGCRYPT_LIBS) ]) gnunet-0.10.1/m4/xsize.m40000644000175000017500000000064511374167230011747 00000000000000# xsize.m4 serial 3 dnl Copyright (C) 2003-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_XSIZE], [ dnl Prerequisites of lib/xsize.h. AC_REQUIRE([gl_SIZE_MAX]) AC_REQUIRE([AC_C_INLINE]) AC_CHECK_HEADERS(stdint.h) ]) gnunet-0.10.1/m4/glib-gettext.m40000644000175000017500000002724711374167230013213 00000000000000# Copyright (C) 1995-2002 Free Software Foundation, Inc. # Copyright (C) 2001-2003 Red Hat, Inc. # # This file is free software, distributed under the terms of the GNU # General Public License. As a special exception to the GNU General # Public License, this file may be distributed as part of a program # that contains a configuration script generated by Autoconf, under # the same distribution terms as the rest of that program. # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU Public License # but which still want to provide support for the GNU gettext functionality. # # Macro to add for using GNU gettext. # Ulrich Drepper , 1995, 1996 # # Modified to never use included libintl. # Owen Taylor , 12/15/1998 # # Major rework to remove unused code # Owen Taylor , 12/11/2002 # # Added better handling of ALL_LINGUAS from GNU gettext version # written by Bruno Haible, Owen Taylor 5/30/3002 # # We need this here as well, since someone might use autoconf-2.5x # to configure GLib then an older version to configure a package # using AM_GLIB_GNU_GETTEXT AC_PREREQ(2.53) dnl dnl We go to great lengths to make sure that aclocal won't dnl try to pull in the installed version of these macros dnl when running aclocal in the glib directory. dnl m4_copy([AC_DEFUN],[glib_DEFUN]) m4_copy([AC_REQUIRE],[glib_REQUIRE]) dnl dnl At the end, if we're not within glib, we'll define the public dnl definitions in terms of our private definitions. dnl # GLIB_LC_MESSAGES #-------------------- glib_DEFUN([GLIB_LC_MESSAGES], [AC_CHECK_HEADERS([locale.h]) if test $ac_cv_header_locale_h = yes; then AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, [AC_TRY_LINK([#include ], [return LC_MESSAGES], am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) if test $am_cv_val_LC_MESSAGES = yes; then AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your file defines LC_MESSAGES.]) fi fi]) # GLIB_PATH_PROG_WITH_TEST #---------------------------- dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) glib_DEFUN([GLIB_PATH_PROG_WITH_TEST], [# Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL(ac_cv_path_$1, [case "[$]$1" in /*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in ifelse([$5], , $PATH, [$5]); do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$]$1) else AC_MSG_RESULT(no) fi AC_SUBST($1)dnl ]) # GLIB_WITH_NLS #----------------- glib_DEFUN([GLIB_WITH_NLS], dnl NLS is obligatory [USE_NLS=yes AC_SUBST(USE_NLS) gt_cv_have_gettext=no CATOBJEXT=NONE XGETTEXT=: INTLLIBS= AC_CHECK_HEADER(libintl.h, [gt_cv_func_dgettext_libintl="no" libintl_extra_libs="" # # First check in libc # AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, [AC_TRY_LINK([ #include ], [return (int) dgettext ("","")], gt_cv_func_dgettext_libc=yes, gt_cv_func_dgettext_libc=no) ]) if test "$gt_cv_func_dgettext_libc" = "yes" ; then AC_CHECK_FUNCS(bind_textdomain_codeset) fi # # If we don't have everything we want, check in libintl # if test "$gt_cv_func_dgettext_libc" != "yes" \ || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then AC_CHECK_LIB(intl, bindtextdomain, [AC_CHECK_LIB(intl, dgettext, gt_cv_func_dgettext_libintl=yes)]) if test "$gt_cv_func_dgettext_libintl" != "yes" ; then AC_MSG_CHECKING([if -liconv is needed to use gettext]) AC_MSG_RESULT([]) AC_CHECK_LIB(intl, dcgettext, [gt_cv_func_dgettext_libintl=yes libintl_extra_libs=-liconv], :,-liconv) fi # # If we found libintl, then check in it for bind_textdomain_codeset(); # we'll prefer libc if neither have bind_textdomain_codeset(), # and both have dgettext # if test "$gt_cv_func_dgettext_libintl" = "yes" ; then glib_save_LIBS="$LIBS" LIBS="$LIBS -lintl $libintl_extra_libs" unset ac_cv_func_bind_textdomain_codeset AC_CHECK_FUNCS(bind_textdomain_codeset) LIBS="$glib_save_LIBS" if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then gt_cv_func_dgettext_libc=no else if test "$gt_cv_func_dgettext_libc" = "yes"; then gt_cv_func_dgettext_libintl=no fi fi fi fi if test "$gt_cv_func_dgettext_libc" = "yes" \ || test "$gt_cv_func_dgettext_libintl" = "yes"; then gt_cv_have_gettext=yes fi if test "$gt_cv_func_dgettext_libintl" = "yes"; then INTLLIBS="-lintl $libintl_extra_libs" fi if test "$gt_cv_have_gettext" = "yes"; then AC_DEFINE(HAVE_GETTEXT,1, [Define if the GNU gettext() function is already present or preinstalled.]) GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl if test "$MSGFMT" != "no"; then glib_save_LIBS="$LIBS" LIBS="$LIBS $INTLLIBS" AC_CHECK_FUNCS(dcgettext) AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; return _nl_msg_cat_cntr], [CATOBJEXT=.gmo DATADIRNAME=share], [case $host in *-*-solaris*) dnl On Solaris, if bind_textdomain_codeset is in libc, dnl GNU format message catalog is always supported, dnl since both are added to the libc all together. dnl Hence, we'd like to go with DATADIRNAME=share and dnl and CATOBJEXT=.gmo in this case. AC_CHECK_FUNC(bind_textdomain_codeset, [CATOBJEXT=.gmo DATADIRNAME=share], [CATOBJEXT=.mo DATADIRNAME=lib]) ;; *) CATOBJEXT=.mo DATADIRNAME=lib ;; esac]) LIBS="$glib_save_LIBS" INSTOBJEXT=.mo else gt_cv_have_gettext=no fi fi ]) if test "$gt_cv_have_gettext" = "yes" ; then AC_DEFINE(ENABLE_NLS, 1, [always defined to indicate that i18n is enabled]) fi dnl Test whether we really found GNU xgettext. if test "$XGETTEXT" != ":"; then dnl If it is not GNU xgettext we define it as : so that the dnl Makefiles still can work. if $XGETTEXT --omit-header /dev/null 2> /dev/null; then : ; else AC_MSG_RESULT( [found xgettext program is not GNU xgettext; ignore it]) XGETTEXT=":" fi fi # We need to process the po/ directory. POSUB=po AC_OUTPUT_COMMANDS( [case "$CONFIG_FILES" in *po/Makefile.in*) sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile esac]) dnl These rules are solely for the distribution goal. While doing this dnl we only have to keep exactly one list of the available catalogs dnl in configure.in. for lang in $ALL_LINGUAS; do GMOFILES="$GMOFILES $lang.gmo" POFILES="$POFILES $lang.po" done dnl Make all variables we use known to autoconf. AC_SUBST(CATALOGS) AC_SUBST(CATOBJEXT) AC_SUBST(DATADIRNAME) AC_SUBST(GMOFILES) AC_SUBST(INSTOBJEXT) AC_SUBST(INTLLIBS) AC_SUBST(PO_IN_DATADIR_TRUE) AC_SUBST(PO_IN_DATADIR_FALSE) AC_SUBST(POFILES) AC_SUBST(POSUB) ]) # AM_GLIB_GNU_GETTEXT # ------------------- # Do checks necessary for use of gettext. If a suitable implementation # of gettext is found in either in libintl or in the C library, # it will set INTLLIBS to the libraries needed for use of gettext # and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable # gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST() # on various variables needed by the Makefile.in.in installed by # glib-gettextize. dnl glib_DEFUN([GLIB_GNU_GETTEXT], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_HEADER_STDC])dnl GLIB_LC_MESSAGES GLIB_WITH_NLS if test "$gt_cv_have_gettext" = "yes"; then if test "x$ALL_LINGUAS" = "x"; then LINGUAS= else AC_MSG_CHECKING(for catalogs to be installed) NEW_LINGUAS= for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then NEW_LINGUAS="$NEW_LINGUAS $presentlang" fi done LINGUAS=$NEW_LINGUAS AC_MSG_RESULT($LINGUAS) fi dnl Construct list of names of catalog files to be constructed. if test -n "$LINGUAS"; then for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done fi fi dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly dnl find the mkinstalldirs script in another subdir but ($top_srcdir). dnl Try to locate is. MKINSTALLDIRS= if test -n "$ac_aux_dir"; then MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" fi if test -z "$MKINSTALLDIRS"; then MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" fi AC_SUBST(MKINSTALLDIRS) dnl Generate list of files to be processed by xgettext which will dnl be included in po/Makefile. test -d po || mkdir po if test "x$srcdir" != "x."; then if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then posrcprefix="$srcdir/" else posrcprefix="../$srcdir/" fi else posrcprefix="../" fi rm -f po/POTFILES sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ < $srcdir/po/POTFILES.in > po/POTFILES ]) # AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) # ------------------------------- # Define VARIABLE to the location where catalog files will # be installed by po/Makefile. glib_DEFUN([GLIB_DEFINE_LOCALEDIR], [glib_REQUIRE([GLIB_GNU_GETTEXT])dnl glib_save_prefix="$prefix" glib_save_exec_prefix="$exec_prefix" test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix=$prefix if test "x$CATOBJEXT" = "x.mo" ; then localedir=`eval echo "${libdir}/locale"` else localedir=`eval echo "${datadir}/locale"` fi prefix="$glib_save_prefix" exec_prefix="$glib_save_exec_prefix" AC_DEFINE_UNQUOTED($1, "$localedir", [Define the location where the catalogs will be installed]) ]) dnl dnl Now the definitions that aclocal will find dnl ifdef(glib_configure_in,[],[ AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)]) AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)]) ])dnl gnunet-0.10.1/m4/inttypes-pri.m40000644000175000017500000000215211374167230013247 00000000000000# inttypes-pri.m4 serial 4 (gettext-0.16) dnl Copyright (C) 1997-2002, 2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_PREREQ(2.52) # Define PRI_MACROS_BROKEN if exists and defines the PRI* # macros to non-string values. This is the case on AIX 4.3.3. AC_DEFUN([gt_INTTYPES_PRI], [ AC_CHECK_HEADERS([inttypes.h]) if test $ac_cv_header_inttypes_h = yes; then AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], gt_cv_inttypes_pri_broken, [ AC_TRY_COMPILE([#include #ifdef PRId32 char *p = PRId32; #endif ], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes) ]) fi if test "$gt_cv_inttypes_pri_broken" = yes; then AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1, [Define if exists and defines unusable PRI* macros.]) PRI_MACROS_BROKEN=1 else PRI_MACROS_BROKEN=0 fi AC_SUBST([PRI_MACROS_BROKEN]) ]) gnunet-0.10.1/m4/ulonglong.m40000644000175000017500000000353211374167230012607 00000000000000# ulonglong.m4 serial 6 dnl Copyright (C) 1999-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. # This fixes a bug in Autoconf 2.60, but can be removed once we # assume 2.61 everywhere. # Note: If the type 'unsigned long long int' exists but is only 32 bits # large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT # will not be defined. In this case you can treat 'unsigned long long int' # like 'unsigned long int'. AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], [ AC_CACHE_CHECK([for unsigned long long int], [ac_cv_type_unsigned_long_long_int], [AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[unsigned long long int ull = 18446744073709551615ULL; typedef int a[(18446744073709551615ULL <= (unsigned long long int) -1 ? 1 : -1)]; int i = 63;]], [[unsigned long long int ullmax = 18446744073709551615ull; return (ull << 63 | ull >> 63 | ull << i | ull >> i | ullmax / ull | ullmax % ull);]])], [ac_cv_type_unsigned_long_long_int=yes], [ac_cv_type_unsigned_long_long_int=no])]) if test $ac_cv_type_unsigned_long_long_int = yes; then AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1, [Define to 1 if the system has the type `unsigned long long int'.]) fi ]) # This macro is obsolescent and should go away soon. AC_DEFUN([gl_AC_TYPE_UNSIGNED_LONG_LONG], [ AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) ac_cv_type_unsigned_long_long=$ac_cv_type_unsigned_long_long_int if test $ac_cv_type_unsigned_long_long = yes; then AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, [Define if you have the 'unsigned long long' type.]) fi ]) gnunet-0.10.1/m4/wchar_t.m40000644000175000017500000000146211531140570012223 00000000000000# wchar_t.m4 serial 4 (gettext-0.18.2) dnl Copyright (C) 2002-2003, 2008-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether has the 'wchar_t' type. dnl Prerequisite: AC_PROG_CC AC_DEFUN([gt_TYPE_WCHAR_T], [ AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t], [AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include wchar_t foo = (wchar_t)'\0';]], [[]])], [gt_cv_c_wchar_t=yes], [gt_cv_c_wchar_t=no])]) if test $gt_cv_c_wchar_t = yes; then AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.]) fi ]) gnunet-0.10.1/m4/ltsugar.m40000644000175000017500000001042412320752051012253 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) gnunet-0.10.1/m4/Makefile.in0000644000175000017500000003523412320752057012411 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = m4 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ChangeLog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = glibc2.m4 intl.m4 intldir.m4 lock.m4 visibility.m4 \ absolute-header.m4 \ libunistring.m4 \ codeset.m4 \ freetype2.m4\ gettext.m4\ glib-2.0.m4\ glibc21.m4\ glib-gettext.m4\ gnulib-cache.m4\ gtk-2.0.m4\ iconv.m4\ intdiv0.m4\ intmax.m4\ inttypes_h.m4\ inttypes.m4\ inttypes-pri.m4\ isc-posix.m4\ lcmessage.m4\ libgcrypt.m4\ lib-ld.m4\ lib-link.m4\ lib-prefix.m4\ libxml2.m4\ longdouble.m4\ longlong.m4\ nls.m4\ pkg.m4\ po.m4\ printf-posix.m4\ progtest.m4\ signed.m4\ size_max.m4\ stdint_h.m4\ uintmax_t.m4\ ulonglong.m4\ wchar_t.m4\ wint_t.m4\ xsize.m4 all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu m4/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/m4/longdouble.m40000644000175000017500000000227711374167230012742 00000000000000# longdouble.m4 serial 2 (gettext-0.15) dnl Copyright (C) 2002-2003, 2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether the compiler supports the 'long double' type. dnl Prerequisite: AC_PROG_CC dnl This file is only needed in autoconf <= 2.59. Newer versions of autoconf dnl have a macro AC_TYPE_LONG_DOUBLE with identical semantics. AC_DEFUN([gt_TYPE_LONGDOUBLE], [ AC_CACHE_CHECK([for long double], gt_cv_c_long_double, [if test "$GCC" = yes; then gt_cv_c_long_double=yes else AC_TRY_COMPILE([ /* The Stardent Vistra knows sizeof(long double), but does not support it. */ long double foo = 0.0; /* On Ultrix 4.3 cc, long double is 4 and double is 8. */ int array [2*(sizeof(long double) >= sizeof(double)) - 1]; ], , gt_cv_c_long_double=yes, gt_cv_c_long_double=no) fi]) if test $gt_cv_c_long_double = yes; then AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the 'long double' type.]) fi ]) gnunet-0.10.1/m4/uintmax_t.m40000644000175000017500000000207611374167230012615 00000000000000# uintmax_t.m4 serial 9 dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. AC_PREREQ(2.13) # Define uintmax_t to 'unsigned long' or 'unsigned long long' # if it is not already defined in or . AC_DEFUN([gl_AC_TYPE_UINTMAX_T], [ AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then AC_REQUIRE([gl_AC_TYPE_UNSIGNED_LONG_LONG]) test $ac_cv_type_unsigned_long_long = yes \ && ac_type='unsigned long long' \ || ac_type='unsigned long' AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, [Define to unsigned long or unsigned long long if and don't define.]) else AC_DEFINE(HAVE_UINTMAX_T, 1, [Define if you have the 'uintmax_t' type in or .]) fi ]) gnunet-0.10.1/m4/lib-link.m40000644000175000017500000006424411374167230012313 00000000000000# lib-link.m4 serial 9 (gettext-0.16) dnl Copyright (C) 2001-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_PREREQ(2.50) dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and dnl augments the CPPFLAGS variable. AC_DEFUN([AC_LIB_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ AC_LIB_LINKFLAGS_BODY([$1], [$2]) ac_cv_lib[]Name[]_libs="$LIB[]NAME" ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" ac_cv_lib[]Name[]_cppflags="$INC[]NAME" ]) LIB[]NAME="$ac_cv_lib[]Name[]_libs" LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" INC[]NAME="$ac_cv_lib[]Name[]_cppflags" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the dnl results of this search when this library appears as a dependency. HAVE_LIB[]NAME=yes undefine([Name]) undefine([NAME]) ]) dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode) dnl searches for libname and the libraries corresponding to explicit and dnl implicit dependencies, together with the specified include files and dnl the ability to compile and link the specified testcode. If found, it dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], [ AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) define([Name],[translit([$1],[./-], [___])]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME dnl accordingly. AC_LIB_LINKFLAGS_BODY([$1], [$2]) dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, dnl because if the user has installed lib[]Name and not disabled its use dnl via --without-lib[]Name-prefix, he wants to use it. ac_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ ac_save_LIBS="$LIBS" LIBS="$LIBS $LIB[]NAME" AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no]) LIBS="$ac_save_LIBS" ]) if test "$ac_cv_lib[]Name" = yes; then HAVE_LIB[]NAME=yes AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.]) AC_MSG_CHECKING([how to link with lib[]$1]) AC_MSG_RESULT([$LIB[]NAME]) else HAVE_LIB[]NAME=no dnl If $LIB[]NAME didn't lead to a usable library, we don't need dnl $INC[]NAME either. CPPFLAGS="$ac_save_CPPFLAGS" LIB[]NAME= LTLIB[]NAME= fi AC_SUBST([HAVE_LIB]NAME) AC_SUBST([LIB]NAME) AC_SUBST([LTLIB]NAME) undefine([Name]) undefine([NAME]) ]) dnl Determine the platform dependent parameters needed to use rpath: dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator, dnl hardcode_direct, hardcode_minus_L. AC_DEFUN([AC_LIB_RPATH], [ dnl Tell automake >= 1.10 to complain if config.rpath is missing. m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh . ./conftest.sh rm -f ./conftest.sh acl_cv_rpath=done ]) wl="$acl_cv_wl" libext="$acl_cv_libext" shlibext="$acl_cv_shlibext" hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" hardcode_direct="$acl_cv_hardcode_direct" hardcode_minus_L="$acl_cv_hardcode_minus_L" dnl Determine whether the user wants rpath handling at all. AC_ARG_ENABLE(rpath, [ --disable-rpath do not hardcode runtime library paths], :, enable_rpath=yes) ]) dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and dnl the libraries corresponding to explicit and implicit dependencies. dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. AC_DEFUN([AC_LIB_LINKFLAGS_BODY], [ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib$1-prefix], [ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib --without-lib$1-prefix don't search for lib$1 in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi ]) dnl Search the library and its dependencies in $additional_libdir and dnl $LDFLAGS. Using breadth-first-seach. LIB[]NAME= LTLIB[]NAME= INC[]NAME= rpathdirs= ltrpathdirs= names_already_handled= names_next_round='$1 $2' while test -n "$names_next_round"; do names_this_round="$names_next_round" names_next_round= for name in $names_this_round; do already_handled= for n in $names_already_handled; do if test "$n" = "$name"; then already_handled=yes break fi done if test -z "$already_handled"; then names_already_handled="$names_already_handled $name" dnl See if it was already located by an earlier AC_LIB_LINKFLAGS dnl or AC_LIB_HAVE_LINKFLAGS call. uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` eval value=\"\$HAVE_LIB$uppername\" if test -n "$value"; then if test "$value" = yes; then eval value=\"\$LIB$uppername\" test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" eval value=\"\$LTLIB$uppername\" test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" else dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined dnl that this library doesn't exist. So just drop it. : fi else dnl Search the library lib$name in $additional_libdir and $LDFLAGS dnl and the already constructed $LIBNAME/$LTLIBNAME. found_dir= found_la= found_so= found_a= if test $use_additional = yes; then if test -n "$shlibext" \ && { test -f "$additional_libdir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$additional_libdir/lib$name.dll.a"; }; }; then found_dir="$additional_libdir" if test -f "$additional_libdir/lib$name.$shlibext"; then found_so="$additional_libdir/lib$name.$shlibext" else found_so="$additional_libdir/lib$name.dll.a" fi if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi else if test -f "$additional_libdir/lib$name.$libext"; then found_dir="$additional_libdir" found_a="$additional_libdir/lib$name.$libext" if test -f "$additional_libdir/lib$name.la"; then found_la="$additional_libdir/lib$name.la" fi fi fi fi if test "X$found_dir" = "X"; then for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) case "$x" in -L*) dir=`echo "X$x" | sed -e 's/^X-L//'` if test -n "$shlibext" \ && { test -f "$dir/lib$name.$shlibext" \ || { test "$shlibext" = dll \ && test -f "$dir/lib$name.dll.a"; }; }; then found_dir="$dir" if test -f "$dir/lib$name.$shlibext"; then found_so="$dir/lib$name.$shlibext" else found_so="$dir/lib$name.dll.a" fi if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi else if test -f "$dir/lib$name.$libext"; then found_dir="$dir" found_a="$dir/lib$name.$libext" if test -f "$dir/lib$name.la"; then found_la="$dir/lib$name.la" fi fi fi ;; esac if test "X$found_dir" != "X"; then break fi done fi if test "X$found_dir" != "X"; then dnl Found the library. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" if test "X$found_so" != "X"; then dnl Linking with a shared library. We attempt to hardcode its dnl directory into the executable's runpath, unless it's the dnl standard /usr/lib. if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then dnl No hardcoding is needed. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $found_dir" fi dnl The hardcoding into $LIBNAME is system dependent. if test "$hardcode_direct" = yes; then dnl Using DIR/libNAME.so during linking hardcodes DIR into the dnl resulting binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then dnl Use an explicit option to hardcode DIR into the resulting dnl binary. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $found_dir" fi else dnl Rely on "-L$found_dir". dnl But don't add it if it's already contained in the LDFLAGS dnl or the already constructed $LIBNAME haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$found_dir"; then haveit=yes break fi done if test -z "$haveit"; then LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" fi if test "$hardcode_minus_L" != no; then dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" else dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH dnl here, because this doesn't fit in flags passed to the dnl compiler. So give up. No hardcoding. This affects only dnl very old systems. dnl FIXME: Not sure whether we should use dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" dnl here. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" fi fi fi fi else if test "X$found_a" != "X"; then dnl Linking with a static library. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" else dnl We shouldn't come here, but anyway it's good to have a dnl fallback. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" fi fi dnl Assume the include files are nearby. additional_includedir= case "$found_dir" in */$acl_libdirstem | */$acl_libdirstem/) basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` additional_includedir="$basedir/include" ;; esac if test "X$additional_includedir" != "X"; then dnl Potentially add $additional_includedir to $INCNAME. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's /usr/local/include and we are using GCC on Linux, dnl 3. if it's already present in $CPPFLAGS or the already dnl constructed $INCNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then for x in $CPPFLAGS $INC[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $INCNAME. INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" fi fi fi fi fi dnl Look for dependencies. if test -n "$found_la"; then dnl Read the .la file. It defines the variables dnl dlname, library_names, old_library, dependency_libs, current, dnl age, revision, installed, dlopen, dlpreopen, libdir. save_libdir="$libdir" case "$found_la" in */* | *\\*) . "$found_la" ;; *) . "./$found_la" ;; esac libdir="$save_libdir" dnl We use only dependency_libs. for dep in $dependency_libs; do case "$dep" in -L*) additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's /usr/local/lib and we are using GCC on Linux, dnl 3. if it's already present in $LDFLAGS or the already dnl constructed $LIBNAME, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then haveit= for x in $LDFLAGS $LIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LIBNAME. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" fi fi haveit= for x in $LDFLAGS $LTLIB[]NAME; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LTLIBNAME. LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" fi fi fi fi ;; -R*) dir=`echo "X$dep" | sed -e 's/^X-R//'` if test "$enable_rpath" != no; then dnl Potentially add DIR to rpathdirs. dnl The rpathdirs will be appended to $LIBNAME at the end. haveit= for x in $rpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then rpathdirs="$rpathdirs $dir" fi dnl Potentially add DIR to ltrpathdirs. dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. haveit= for x in $ltrpathdirs; do if test "X$x" = "X$dir"; then haveit=yes break fi done if test -z "$haveit"; then ltrpathdirs="$ltrpathdirs $dir" fi fi ;; -l*) dnl Handle this in the next round. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` ;; *.la) dnl Handle this in the next round. Throw away the .la's dnl directory; it is already contained in a preceding -L dnl option. names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` ;; *) dnl Most likely an immediate library name. LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" ;; esac done fi else dnl Didn't find the library; assume it is in the system directories dnl known to the linker and runtime loader. (All the system dnl directories known to the linker should also be known to the dnl runtime loader, otherwise the system is severely misconfigured.) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" fi fi fi done done if test "X$rpathdirs" != "X"; then if test -n "$hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user must dnl pass all path elements in one option. We can arrange that for a dnl single library, but not when more than one $LIBNAMEs are used. alldirs= for found_dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" done dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl. acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" else dnl The -rpath options are cumulative. for found_dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$found_dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" done fi fi if test "X$ltrpathdirs" != "X"; then dnl When using libtool, the option that works for both libraries and dnl executables is -R. The -R options are cumulative. for found_dir in $ltrpathdirs; do LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" done fi ]) dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, dnl unless already present in VAR. dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes dnl contains two or three consecutive elements that belong together. AC_DEFUN([AC_LIB_APPENDTOVAR], [ for element in [$2]; do haveit= for x in $[$1]; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X$element"; then haveit=yes break fi done if test -z "$haveit"; then [$1]="${[$1]}${[$1]:+ }$element" fi done ]) dnl For those cases where a variable contains several -L and -l options dnl referring to unknown libraries and directories, this macro determines the dnl necessary additional linker options for the runtime path. dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) dnl sets LDADDVAR to linker options needed together with LIBSVALUE. dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, dnl otherwise linking without libtool is assumed. AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], [ AC_REQUIRE([AC_LIB_RPATH]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) $1= if test "$enable_rpath" != no; then if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then dnl Use an explicit option to hardcode directories into the resulting dnl binary. rpathdirs= next= for opt in $2; do if test -n "$next"; then dir="$next" dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem"; then rpathdirs="$rpathdirs $dir" fi next= else case $opt in -L) next=yes ;; -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` dnl No need to hardcode the standard /usr/lib. if test "X$dir" != "X/usr/$acl_libdirstem"; then rpathdirs="$rpathdirs $dir" fi next= ;; *) next= ;; esac fi done if test "X$rpathdirs" != "X"; then if test -n ""$3""; then dnl libtool is used for linking. Use -R options. for dir in $rpathdirs; do $1="${$1}${$1:+ }-R$dir" done else dnl The linker is used for linking directly. if test -n "$hardcode_libdir_separator"; then dnl Weird platform: only the last -rpath option counts, the user dnl must pass all path elements in one option. alldirs= for dir in $rpathdirs; do alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$dir" done acl_save_libdir="$libdir" libdir="$alldirs" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="$flag" else dnl The -rpath options are cumulative. for dir in $rpathdirs; do acl_save_libdir="$libdir" libdir="$dir" eval flag=\"$hardcode_libdir_flag_spec\" libdir="$acl_save_libdir" $1="${$1}${$1:+ }$flag" done fi fi fi fi fi AC_SUBST([$1]) ]) gnunet-0.10.1/m4/size_max.m40000644000175000017500000000461011374167230012420 00000000000000# size_max.m4 serial 5 dnl Copyright (C) 2003, 2005-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([gl_SIZE_MAX], [ AC_CHECK_HEADERS(stdint.h) dnl First test whether the system already has SIZE_MAX. AC_MSG_CHECKING([for SIZE_MAX]) AC_CACHE_VAL([gl_cv_size_max], [ gl_cv_size_max= AC_EGREP_CPP([Found it], [ #include #if HAVE_STDINT_H #include #endif #ifdef SIZE_MAX Found it #endif ], gl_cv_size_max=yes) if test -z "$gl_cv_size_max"; then dnl Define it ourselves. Here we assume that the type 'size_t' is not wider dnl than the type 'unsigned long'. Try hard to find a definition that can dnl be used in a preprocessor #if, i.e. doesn't contain a cast. _AC_COMPUTE_INT([sizeof (size_t) * CHAR_BIT - 1], size_t_bits_minus_1, [#include #include ], size_t_bits_minus_1=) _AC_COMPUTE_INT([sizeof (size_t) <= sizeof (unsigned int)], fits_in_uint, [#include ], fits_in_uint=) if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then if test $fits_in_uint = 1; then dnl Even though SIZE_MAX fits in an unsigned int, it must be of type dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. AC_TRY_COMPILE([#include extern size_t foo; extern unsigned long foo; ], [], fits_in_uint=0) fi dnl We cannot use 'expr' to simplify this expression, because 'expr' dnl works only with 'long' integers in the host environment, while we dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. if test $fits_in_uint = 1; then gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" else gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" fi else dnl Shouldn't happen, but who knows... gl_cv_size_max='((size_t)~(size_t)0)' fi fi ]) AC_MSG_RESULT([$gl_cv_size_max]) if test "$gl_cv_size_max" != yes; then AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max], [Define as the maximum value of type 'size_t', if the system doesn't define it.]) fi ]) gnunet-0.10.1/m4/pkg.m40000644000175000017500000000375311374167230011371 00000000000000 dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page dnl also defines GSTUFF_PKG_ERRORS on error AC_DEFUN([PKG_CHECK_MODULES], [ succeeded=no if test -z "$PKG_CONFIG"; then AC_PATH_PROG(PKG_CONFIG, pkg-config, no) fi if test "$PKG_CONFIG" = "no" ; then echo "*** The pkg-config script could not be found. Make sure it is" echo "*** in your path, or set the PKG_CONFIG environment variable" echo "*** to the full path to pkg-config." echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." else PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then AC_MSG_CHECKING(for $2) if $PKG_CONFIG --exists "$2" ; then AC_MSG_RESULT(yes) succeeded=yes AC_MSG_CHECKING($1_CFLAGS) $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` AC_MSG_RESULT($$1_CFLAGS) AC_MSG_CHECKING($1_LIBS) $1_LIBS=`$PKG_CONFIG --libs "$2"` AC_MSG_RESULT($$1_LIBS) else $1_CFLAGS="" $1_LIBS="" ## If we have a custom action on failure, don't print errors, but ## do set a variable so people can do so. $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` ifelse([$4], ,echo $$1_PKG_ERRORS,) fi AC_SUBST($1_CFLAGS) AC_SUBST($1_LIBS) else echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." echo "*** See http://www.freedesktop.org/software/pkgconfig" fi fi if test $succeeded = yes; then ifelse([$3], , :, [$3]) else ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) fi ]) gnunet-0.10.1/m4/iconv.m40000644000175000017500000000642611374167230011726 00000000000000# iconv.m4 serial AM4 (gettext-0.11.3) dnl Copyright (C) 2000-2002 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], [ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_LIB_LINKFLAGS_BODY([iconv]) ]) AC_DEFUN([AM_ICONV_LINK], [ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and dnl those with the standalone portable GNU libiconv installed). dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV dnl accordingly. AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) dnl Add $INCICONV to CPPFLAGS before performing the following checks, dnl because if the user has installed libiconv and not disabled its use dnl via --without-libiconv-prefix, he wants to use it. The first dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed. am_save_CPPFLAGS="$CPPFLAGS" AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [ am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_func_iconv=yes) if test "$am_cv_func_iconv" != yes; then am_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include #include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], am_cv_lib_iconv=yes am_cv_func_iconv=yes) LIBS="$am_save_LIBS" fi ]) if test "$am_cv_func_iconv" = yes; then AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) fi if test "$am_cv_lib_iconv" = yes; then AC_MSG_CHECKING([how to link with libiconv]) AC_MSG_RESULT([$LIBICONV]) else dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV dnl either. CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi AC_SUBST(LIBICONV) AC_SUBST(LTLIBICONV) ]) AC_DEFUN([AM_ICONV], [ AM_ICONV_LINK if test "$am_cv_func_iconv" = yes; then AC_MSG_CHECKING([for iconv declaration]) AC_CACHE_VAL(am_cv_proto_iconv, [ AC_TRY_COMPILE([ #include #include extern #ifdef __cplusplus "C" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif ], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const") am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` AC_MSG_RESULT([$]{ac_t:- }[$]am_cv_proto_iconv) AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1, [Define as const if the declaration of iconv() needs const.]) fi ]) gnunet-0.10.1/m4/lib-prefix.m40000644000175000017500000001503611374167230012646 00000000000000# lib-prefix.m4 serial 5 (gettext-0.15) dnl Copyright (C) 2001-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't dnl require excessive bracketing. ifdef([AC_HELP_STRING], [AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], [AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed dnl to access previously installed libraries. The basic assumption is that dnl a user will want packages to use other packages he previously installed dnl with the same --prefix option. dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate dnl libraries, but is otherwise very convenient. AC_DEFUN([AC_LIB_PREFIX], [ AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) dnl By default, look in $includedir and $libdir. use_additional=yes AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) AC_LIB_ARG_WITH([lib-prefix], [ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib --without-lib-prefix don't search for libraries in includedir and libdir], [ if test "X$withval" = "Xno"; then use_additional=no else if test "X$withval" = "X"; then AC_LIB_WITH_FINAL_PREFIX([ eval additional_includedir=\"$includedir\" eval additional_libdir=\"$libdir\" ]) else additional_includedir="$withval/include" additional_libdir="$withval/$acl_libdirstem" fi fi ]) if test $use_additional = yes; then dnl Potentially add $additional_includedir to $CPPFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/include, dnl 2. if it's already present in $CPPFLAGS, dnl 3. if it's /usr/local/include and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_includedir" != "X/usr/include"; then haveit= for x in $CPPFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-I$additional_includedir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_includedir" = "X/usr/local/include"; then if test -n "$GCC"; then case $host_os in linux* | gnu* | k*bsd*-gnu) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_includedir"; then dnl Really add $additional_includedir to $CPPFLAGS. CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" fi fi fi fi dnl Potentially add $additional_libdir to $LDFLAGS. dnl But don't add it dnl 1. if it's the standard /usr/lib, dnl 2. if it's already present in $LDFLAGS, dnl 3. if it's /usr/local/lib and we are using GCC on Linux, dnl 4. if it doesn't exist as a directory. if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then haveit= for x in $LDFLAGS; do AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) if test "X$x" = "X-L$additional_libdir"; then haveit=yes break fi done if test -z "$haveit"; then if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then if test -n "$GCC"; then case $host_os in linux*) haveit=yes;; esac fi fi if test -z "$haveit"; then if test -d "$additional_libdir"; then dnl Really add $additional_libdir to $LDFLAGS. LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" fi fi fi fi fi ]) dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, dnl acl_final_exec_prefix, containing the values to which $prefix and dnl $exec_prefix will expand at the end of the configure script. AC_DEFUN([AC_LIB_PREPARE_PREFIX], [ dnl Unfortunately, prefix and exec_prefix get only finally determined dnl at the end of configure. if test "X$prefix" = "XNONE"; then acl_final_prefix="$ac_default_prefix" else acl_final_prefix="$prefix" fi if test "X$exec_prefix" = "XNONE"; then acl_final_exec_prefix='${prefix}' else acl_final_exec_prefix="$exec_prefix" fi acl_save_prefix="$prefix" prefix="$acl_final_prefix" eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" prefix="$acl_save_prefix" ]) dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the dnl variables prefix and exec_prefix bound to the values they will have dnl at the end of the configure script. AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], [ acl_save_prefix="$prefix" prefix="$acl_final_prefix" acl_save_exec_prefix="$exec_prefix" exec_prefix="$acl_final_exec_prefix" $1 exec_prefix="$acl_save_exec_prefix" prefix="$acl_save_prefix" ]) dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing dnl the basename of the libdir, either "lib" or "lib64". AC_DEFUN([AC_LIB_PREPARE_MULTILIB], [ dnl There is no formal standard regarding lib and lib64. The current dnl practice is that on a system supporting 32-bit and 64-bit instruction dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit dnl libraries go under $prefix/lib. We determine the compiler's default dnl mode by looking at the compiler's library search path. If at least dnl of its elements ends in /lib64 or points to a directory whose absolute dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the dnl default, namely "lib". acl_libdirstem=lib searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` if test -n "$searchpath"; then acl_save_IFS="${IFS= }"; IFS=":" for searchdir in $searchpath; do if test -d "$searchdir"; then case "$searchdir" in */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; *) searchdir=`cd "$searchdir" && pwd` case "$searchdir" in */lib64 ) acl_libdirstem=lib64 ;; esac ;; esac fi done IFS="$acl_save_IFS" fi ]) gnunet-0.10.1/m4/progtest.m40000644000175000017500000000555011374167230012454 00000000000000# progtest.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 1996-2003, 2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1996. AC_PREREQ(2.50) # Search path for a program which passes the given test. dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) AC_DEFUN([AM_PATH_PROG_WITH_TEST], [ # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Find out how to test for executable files. Don't use a zero-byte file, # as systems may use methods other than mode bits to determine executability. cat >conf$$.file <<_ASEOF #! /bin/sh exit 0 _ASEOF chmod +x conf$$.file if test -x conf$$.file >/dev/null 2>&1; then ac_executable_p="test -x" else ac_executable_p="test -f" fi rm -f conf$$.file # Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL(ac_cv_path_$1, [case "[$]$1" in [[\\/]]* | ?:[[\\/]]*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in ifelse([$5], , $PATH, [$5]); do IFS="$ac_save_IFS" test -z "$ac_dir" && ac_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" break 2 fi fi done done IFS="$ac_save_IFS" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$]$1) else AC_MSG_RESULT(no) fi AC_SUBST($1)dnl ]) gnunet-0.10.1/m4/intldir.m40000644000175000017500000000161611374167230012251 00000000000000# intldir.m4 serial 1 (gettext-0.16) dnl Copyright (C) 2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. AC_PREREQ(2.52) dnl Tells the AM_GNU_GETTEXT macro to consider an intl/ directory. AC_DEFUN([AM_GNU_GETTEXT_INTL_SUBDIR], []) gnunet-0.10.1/m4/absolute-header.m40000644000175000017500000000641111700261537013644 00000000000000# absolute-header.m4 serial 12 dnl Copyright (C) 2006-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Derek Price. # gl_ABSOLUTE_HEADER(HEADER1 HEADER2 ...) # --------------------------------------- # Find the absolute name of a header file, testing first if the header exists. # If the header were sys/inttypes.h, this macro would define # ABSOLUTE_SYS_INTTYPES_H to the `""' quoted absolute name of sys/inttypes.h # in config.h # (e.g. `#define ABSOLUTE_SYS_INTTYPES_H "///usr/include/sys/inttypes.h"'). # The three "///" are to pacify Sun C 5.8, which otherwise would say # "warning: #include of /usr/include/... may be non-portable". # Use `""', not `<>', so that the /// cannot be confused with a C99 comment. # Note: This macro assumes that the header file is not empty after # preprocessing, i.e. it does not only define preprocessor macros but also # provides some type/enum definitions or function/variable declarations. AC_DEFUN([gl_ABSOLUTE_HEADER], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_PREPROC_REQUIRE()dnl m4_foreach_w([gl_HEADER_NAME], [$1], [AS_VAR_PUSHDEF([gl_absolute_header], [gl_cv_absolute_]m4_defn([gl_HEADER_NAME]))dnl AC_CACHE_CHECK([absolute name of <]m4_defn([gl_HEADER_NAME])[>], m4_defn([gl_absolute_header]), [AS_VAR_PUSHDEF([ac_header_exists], [ac_cv_header_]m4_defn([gl_HEADER_NAME]))dnl AC_CHECK_HEADERS_ONCE(m4_defn([gl_HEADER_NAME]))dnl if test AS_VAR_GET(ac_header_exists) = yes; then gl_ABSOLUTE_HEADER_ONE(m4_defn([gl_HEADER_NAME])) fi AS_VAR_POPDEF([ac_header_exists])dnl ])dnl AC_DEFINE_UNQUOTED(AS_TR_CPP([ABSOLUTE_]m4_defn([gl_HEADER_NAME])), ["AS_VAR_GET(gl_absolute_header)"], [Define this to an absolute name of <]m4_defn([gl_HEADER_NAME])[>.]) AS_VAR_POPDEF([gl_absolute_header])dnl ])dnl ])# gl_ABSOLUTE_HEADER # gl_ABSOLUTE_HEADER_ONE(HEADER) # ------------------------------ # Like gl_ABSOLUTE_HEADER, except that: # - it assumes that the header exists, # - it uses the current CPPFLAGS, # - it does not cache the result, # - it is silent. AC_DEFUN([gl_ABSOLUTE_HEADER_ONE], [ AC_LANG_CONFTEST([AC_LANG_SOURCE([[#include <]]m4_dquote([$1])[[>]])]) dnl AIX "xlc -E" and "cc -E" omit #line directives for header files dnl that contain only a #include of other header files and no dnl non-comment tokens of their own. This leads to a failure to dnl detect the absolute name of , , dnl and others. The workaround is to force preservation of comments dnl through option -C. This ensures all necessary #line directives dnl are present. GCC supports option -C as well. case "$host_os" in aix*) gl_absname_cpp="$ac_cpp -C" ;; *) gl_absname_cpp="$ac_cpp" ;; esac dnl eval is necessary to expand gl_absname_cpp. dnl Ultrix and Pyramid sh refuse to redirect output of eval, dnl so use subshell. AS_VAR_SET([gl_cv_absolute_]AS_TR_SH([[$1]]), [`(eval "$gl_absname_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | sed -n '\#/$1#{ s#.*"\(.*/$1\)".*#\1# s#^/[^/]#//&# p q }'`]) ]) gnunet-0.10.1/m4/printf-posix.m40000644000175000017500000000266111374167230013247 00000000000000# printf-posix.m4 serial 2 (gettext-0.13.1) dnl Copyright (C) 2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Test whether the printf() function supports POSIX/XSI format strings with dnl positions. AC_DEFUN([gt_PRINTF_POSIX], [ AC_REQUIRE([AC_PROG_CC]) AC_CACHE_CHECK([whether printf() supports POSIX/XSI format strings], gt_cv_func_printf_posix, [ AC_TRY_RUN([ #include #include /* The string "%2$d %1$d", with dollar characters protected from the shell's dollar expansion (possibly an autoconf bug). */ static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; static char buf[100]; int main () { sprintf (buf, format, 33, 55); return (strcmp (buf, "55 33") != 0); }], gt_cv_func_printf_posix=yes, gt_cv_func_printf_posix=no, [ AC_EGREP_CPP(notposix, [ #if defined __NetBSD__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ notposix #endif ], gt_cv_func_printf_posix="guessing no", gt_cv_func_printf_posix="guessing yes") ]) ]) case $gt_cv_func_printf_posix in *yes) AC_DEFINE(HAVE_POSIX_PRINTF, 1, [Define if your printf() function supports format strings with positions.]) ;; esac ]) gnunet-0.10.1/m4/libunistring.m40000644000175000017500000001431411700261537013312 00000000000000# libunistring.m4 serial 11 dnl Copyright (C) 2009-2012 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl gl_LIBUNISTRING dnl Searches for an installed libunistring. dnl If found, it sets and AC_SUBSTs HAVE_LIBUNISTRING=yes and the LIBUNISTRING dnl and LTLIBUNISTRING variables, sets the LIBUNISTRING_VERSION variable, and dnl augments the CPPFLAGS variable, and #defines HAVE_LIBUNISTRING to 1. dnl Otherwise, it sets and AC_SUBSTs HAVE_LIBUNISTRING=no and LIBUNISTRING and dnl LTLIBUNISTRING to empty. dnl Define gl_LIBUNISTRING using AC_DEFUN_ONCE for Autoconf >= 2.64, in order dnl to avoid warnings like dnl "warning: AC_REQUIRE: `gl_LIBUNISTRING' was expanded before it was required". dnl This is tricky because of the way 'aclocal' is implemented: dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. dnl Otherwise aclocal's initial scan pass would miss the macro definition. dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. dnl Otherwise aclocal would emit many "Use of uninitialized value $1" dnl warnings. m4_define([gl_libunistring_AC_DEFUN], m4_version_prereq([2.64], [[AC_DEFUN_ONCE( [$1], [$2])]], [m4_ifdef([gl_00GNULIB], [[AC_DEFUN_ONCE( [$1], [$2])]], [[AC_DEFUN( [$1], [$2])]])])) gl_libunistring_AC_DEFUN([gl_LIBUNISTRING], [ AC_BEFORE([$0], [gl_LIBUNISTRING_MODULE]) AC_BEFORE([$0], [gl_LIBUNISTRING_LIBHEADER]) AC_BEFORE([$0], [gl_LIBUNISTRING_LIB_PREPARE]) m4_ifdef([gl_LIBUNISTRING_OPTIONAL], [ AC_MSG_CHECKING([whether included libunistring is requested]) AC_ARG_WITH([included-libunistring], [ --with-included-libunistring use the libunistring parts included here], [gl_libunistring_force_included=$withval], [gl_libunistring_force_included=no]) AC_MSG_RESULT([$gl_libunistring_force_included]) gl_libunistring_use_included="$gl_libunistring_force_included" if test "$gl_libunistring_use_included" = yes; then dnl Assume that libunistring is not installed until some other macro dnl explicitly invokes gl_LIBUNISTRING_CORE. if test -z "$HAVE_LIBUNISTRING"; then HAVE_LIBUNISTRING=no fi LIBUNISTRING= LTLIBUNISTRING= else gl_LIBUNISTRING_CORE if test $HAVE_LIBUNISTRING = no; then gl_libunistring_use_included=yes LIBUNISTRING= LTLIBUNISTRING= fi fi ], [gl_LIBUNISTRING_CORE]) ]) AC_DEFUN([gl_LIBUNISTRING_CORE], [ AC_REQUIRE([AM_ICONV]) if test -n "$LIBICONV"; then dnl First, try to link without -liconv. libunistring often depends on dnl libiconv, but we don't know (and often don't need to know) where dnl libiconv is installed. AC_LIB_HAVE_LINKFLAGS([unistring], [], [#include ], [u8_strconv_from_locale((char*)0);], [no, trying again together with libiconv]) if test "$ac_cv_libunistring" != yes; then dnl Second try, with -liconv. dnl We have to erase the cached result of the first AC_LIB_HAVE_LINKFLAGS dnl invocation, otherwise the second one will not be run. unset ac_cv_libunistring glus_save_LIBS="$LIBS" LIBS="$LIBS $LIBICONV" AC_LIB_HAVE_LINKFLAGS([unistring], [], [#include ], [u8_strconv_from_locale((char*)0);], [no, consider installing GNU libunistring]) if test -n "$LIBUNISTRING"; then LIBUNISTRING="$LIBUNISTRING $LIBICONV" LTLIBUNISTRING="$LTLIBUNISTRING $LTLIBICONV" fi LIBS="$glus_save_LIBS" fi else AC_LIB_HAVE_LINKFLAGS([unistring], [], [#include ], [u8_strconv_from_locale((char*)0);], [no, consider installing GNU libunistring]) fi if test $HAVE_LIBUNISTRING = yes; then dnl Determine the installed version. AC_CACHE_CHECK([for libunistring version], [gl_cv_libunistring_version], [AC_COMPUTE_INT([gl_libunistring_hexversion], [_LIBUNISTRING_VERSION], [#include ]) dnl Versions <= 0.9.3 had a hexversion of 0x0009. dnl Use other tests to distinguish them. if test $gl_libunistring_hexversion = 9; then dnl Version 0.9.2 introduced the header . AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[]])], [gl_cv_libunistring_version092=true], [gl_cv_libunistring_version092=false]) if $gl_cv_libunistring_version092; then dnl Version 0.9.3 changed a comment in . gl_ABSOLUTE_HEADER_ONE([unistr.h]) if test -n "$gl_cv_absolute_unistr_h" \ && grep 'Copy no more than N units of SRC to DEST. Return a pointer' $gl_cv_absolute_unistr_h > /dev/null; then dnl Detected version 0.9.3. gl_libunistring_hexversion=2307 else dnl Detected version 0.9.2. gl_libunistring_hexversion=2306 fi else dnl Version 0.9.1 introduced the type casing_suffix_context_t. AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [[#include casing_suffix_context_t ct;]], [[]])], [gl_cv_libunistring_version091=true], [gl_cv_libunistring_version091=false]) if $gl_cv_libunistring_version091; then dnl Detected version 0.9.1. gl_libunistring_hexversion=2305 else dnl Detected version 0.9. gl_libunistring_hexversion=2304 fi fi fi dnl Transform into the usual major.minor.subminor notation. gl_libunistring_major=`expr $gl_libunistring_hexversion / 65536` gl_libunistring_minor=`expr $gl_libunistring_hexversion / 256 % 256` gl_libunistring_subminor=`expr $gl_libunistring_hexversion % 256` gl_cv_libunistring_version="$gl_libunistring_major.$gl_libunistring_minor.$gl_libunistring_subminor" ]) LIBUNISTRING_VERSION="$gl_cv_libunistring_version" fi ]) gnunet-0.10.1/m4/ltversion.m40000644000175000017500000000126212320752051012617 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) gnunet-0.10.1/m4/stdint_h.m40000644000175000017500000000161411374167230012416 00000000000000# stdint_h.m4 serial 6 dnl Copyright (C) 1997-2004, 2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert. # Define HAVE_STDINT_H_WITH_UINTMAX if exists, # doesn't clash with , and declares uintmax_t. AC_DEFUN([gl_AC_HEADER_STDINT_H], [ AC_CACHE_CHECK([for stdint.h], gl_cv_header_stdint_h, [AC_TRY_COMPILE( [#include #include ], [uintmax_t i = (uintmax_t) -1; return !i;], gl_cv_header_stdint_h=yes, gl_cv_header_stdint_h=no)]) if test $gl_cv_header_stdint_h = yes; then AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1, [Define if exists, doesn't clash with , and declares uintmax_t. ]) fi ]) gnunet-0.10.1/m4/glibc21.m40000644000175000017500000000144511374167230012027 00000000000000# glibc21.m4 serial 3 dnl Copyright (C) 2000-2002, 2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # Test for the GNU C Library, version 2.1 or newer. # From Bruno Haible. AC_DEFUN([gl_GLIBC21], [ AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer, ac_cv_gnu_library_2_1, [AC_EGREP_CPP([Lucky GNU user], [ #include #ifdef __GNU_LIBRARY__ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) Lucky GNU user #endif #endif ], ac_cv_gnu_library_2_1=yes, ac_cv_gnu_library_2_1=no) ] ) AC_SUBST(GLIBC21) GLIBC21="$ac_cv_gnu_library_2_1" ] ) gnunet-0.10.1/m4/Makefile.am0000644000175000017500000000106412272460772012400 00000000000000EXTRA_DIST = glibc2.m4 intl.m4 intldir.m4 lock.m4 visibility.m4 \ absolute-header.m4 \ libunistring.m4 \ codeset.m4 \ freetype2.m4\ gettext.m4\ glib-2.0.m4\ glibc21.m4\ glib-gettext.m4\ gnulib-cache.m4\ gtk-2.0.m4\ iconv.m4\ intdiv0.m4\ intmax.m4\ inttypes_h.m4\ inttypes.m4\ inttypes-pri.m4\ isc-posix.m4\ lcmessage.m4\ libgcrypt.m4\ lib-ld.m4\ lib-link.m4\ lib-prefix.m4\ libxml2.m4\ longdouble.m4\ longlong.m4\ nls.m4\ pkg.m4\ po.m4\ printf-posix.m4\ progtest.m4\ signed.m4\ size_max.m4\ stdint_h.m4\ uintmax_t.m4\ ulonglong.m4\ wchar_t.m4\ wint_t.m4\ xsize.m4 gnunet-0.10.1/m4/gettext.m40000644000175000017500000003773211374167230012300 00000000000000# gettext.m4 serial 59 (gettext-0.16.1) dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2006. dnl Macro to add for using GNU gettext. dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The dnl default (if it is not specified or empty) is 'no-libtool'. dnl INTLSYMBOL should be 'external' for packages with no intl directory, dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. dnl If INTLSYMBOL is 'use-libtool', then a libtool library dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, dnl depending on --{enable,disable}-{shared,static} and on the presence of dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library dnl $(top_builddir)/intl/libintl.a will be created. dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext dnl implementations (in libc or libintl) without the ngettext() function dnl will be ignored. If NEEDSYMBOL is specified and is dnl 'need-formatstring-macros', then GNU gettext implementations that don't dnl support the ISO C 99 formatstring macros will be ignored. dnl INTLDIR is used to find the intl libraries. If empty, dnl the value `$(top_builddir)/intl/' is used. dnl dnl The result of the configuration is one of three cases: dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled dnl and used. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 2) GNU gettext has been found in the system's C library. dnl Catalog format: GNU --> install in $(datadir) dnl Catalog extension: .mo after installation, .gmo in source tree dnl 3) No internationalization, always use English msgid. dnl Catalog format: none dnl Catalog extension: none dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. dnl The use of .gmo is historical (it was needed to avoid overwriting the dnl GNU format catalogs when building on a platform with an X/Open gettext), dnl but we keep it in order not to force irrelevant filename changes on the dnl maintainers. dnl AC_DEFUN([AM_GNU_GETTEXT], [ dnl Argument checking. ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT ])])])])]) ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT ])])])]) define([gt_included_intl], ifelse([$1], [external], ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), [yes])) define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) gt_NEEDS_INIT AM_GNU_GETTEXT_NEED([$2]) AC_REQUIRE([AM_PO_SUBDIRS])dnl ifelse(gt_included_intl, yes, [ AC_REQUIRE([AM_INTL_SUBDIR])dnl ]) dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) AC_REQUIRE([AC_LIB_RPATH]) dnl Sometimes libintl requires libiconv, so first search for libiconv. dnl Ideally we would do this search only after the dnl if test "$USE_NLS" = "yes"; then dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT dnl the configure script would need to contain the same shell code dnl again, outside any 'if'. There are two solutions: dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not dnl documented, we avoid it. ifelse(gt_included_intl, yes, , [ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) ]) dnl Sometimes, on MacOS X, libintl requires linking with CoreFoundation. gt_INTL_MACOSX dnl Set USE_NLS. AC_REQUIRE([AM_NLS]) ifelse(gt_included_intl, yes, [ BUILD_INCLUDED_LIBINTL=no USE_INCLUDED_LIBINTL=no ]) LIBINTL= LTLIBINTL= POSUB= dnl Add a version number to the cache macros. case " $gt_needs " in *" need-formatstring-macros "*) gt_api_version=3 ;; *" need-ngettext "*) gt_api_version=2 ;; *) gt_api_version=1 ;; esac gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" dnl If we use NLS figure out what method if test "$USE_NLS" = "yes"; then gt_use_preinstalled_gnugettext=no ifelse(gt_included_intl, yes, [ AC_MSG_CHECKING([whether included gettext is requested]) AC_ARG_WITH(included-gettext, [ --with-included-gettext use the GNU gettext library included here], nls_cv_force_use_gnu_gettext=$withval, nls_cv_force_use_gnu_gettext=no) AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" if test "$nls_cv_force_use_gnu_gettext" != "yes"; then ]) dnl User does not insist on using GNU NLS library. Figure out what dnl to use. If GNU gettext is available we use this. Else we have dnl to fall back to GNU NLS library. if test $gt_api_version -ge 3; then gt_revision_test_code=' #ifndef __GNU_GETTEXT_SUPPORTED_REVISION #define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) #endif changequote(,)dnl typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; changequote([,])dnl ' else gt_revision_test_code= fi if test $gt_api_version -ge 2; then gt_expression_test_code=' + * ngettext ("", "", 0)' else gt_expression_test_code= fi AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], [AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern int *_nl_domain_bindings;], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings], [eval "$gt_func_gnugettext_libc=yes"], [eval "$gt_func_gnugettext_libc=no"])]) if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then dnl Sometimes libintl requires libiconv, so first search for libiconv. ifelse(gt_included_intl, yes, , [ AM_ICONV_LINK ]) dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) dnl because that would add "-liconv" to LIBINTL and LTLIBINTL dnl even if libiconv doesn't exist. AC_LIB_LINKFLAGS_BODY([intl]) AC_CACHE_CHECK([for GNU gettext in libintl], [$gt_func_gnugettext_libintl], [gt_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $INCINTL" gt_save_LIBS="$LIBS" LIBS="$LIBS $LIBINTL" dnl Now see whether libintl exists and does not depend on libiconv. AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [eval "$gt_func_gnugettext_libintl=yes"], [eval "$gt_func_gnugettext_libintl=no"]) dnl Now see whether libintl exists and depends on libiconv. if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then LIBS="$LIBS $LIBICONV" AC_TRY_LINK([#include $gt_revision_test_code extern int _nl_msg_cat_cntr; extern #ifdef __cplusplus "C" #endif const char *_nl_expand_alias (const char *);], [bindtextdomain ("", ""); return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("")], [LIBINTL="$LIBINTL $LIBICONV" LTLIBINTL="$LTLIBINTL $LTLIBICONV" eval "$gt_func_gnugettext_libintl=yes" ]) fi CPPFLAGS="$gt_save_CPPFLAGS" LIBS="$gt_save_LIBS"]) fi dnl If an already present or preinstalled GNU gettext() is found, dnl use it. But if this macro is used in GNU gettext, and GNU dnl gettext is already preinstalled in libintl, we update this dnl libintl. (Cf. the install rule in intl/Makefile.in.) if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ && test "$PACKAGE" != gettext-runtime \ && test "$PACKAGE" != gettext-tools; }; then gt_use_preinstalled_gnugettext=yes else dnl Reset the values set by searching for libintl. LIBINTL= LTLIBINTL= INCINTL= fi ifelse(gt_included_intl, yes, [ if test "$gt_use_preinstalled_gnugettext" != "yes"; then dnl GNU gettext is not found in the C library. dnl Fall back on included GNU gettext library. nls_cv_use_gnu_gettext=yes fi fi if test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions used to generate GNU NLS library. BUILD_INCLUDED_LIBINTL=yes USE_INCLUDED_LIBINTL=yes LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` fi CATOBJEXT= if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Mark actions to use GNU gettext tools. CATOBJEXT=.gmo fi ]) if test -n "$INTL_MACOSX_LIBS"; then if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then dnl Some extra flags are needed during linking. LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" fi fi if test "$gt_use_preinstalled_gnugettext" = "yes" \ || test "$nls_cv_use_gnu_gettext" = "yes"; then AC_DEFINE(ENABLE_NLS, 1, [Define to 1 if translation of program messages to the user's native language is requested.]) else USE_NLS=no fi fi AC_MSG_CHECKING([whether to use NLS]) AC_MSG_RESULT([$USE_NLS]) if test "$USE_NLS" = "yes"; then AC_MSG_CHECKING([where the gettext function comes from]) if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then gt_source="external libintl" else gt_source="libc" fi else gt_source="included intl directory" fi AC_MSG_RESULT([$gt_source]) fi if test "$USE_NLS" = "yes"; then if test "$gt_use_preinstalled_gnugettext" = "yes"; then if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then AC_MSG_CHECKING([how to link with libintl]) AC_MSG_RESULT([$LIBINTL]) AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) fi dnl For backward compatibility. Some packages may be using this. AC_DEFINE(HAVE_GETTEXT, 1, [Define if the GNU gettext() function is already present or preinstalled.]) AC_DEFINE(HAVE_DCGETTEXT, 1, [Define if the GNU dcgettext() function is already present or preinstalled.]) fi dnl We need to process the po/ directory. POSUB=po fi ifelse(gt_included_intl, yes, [ dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL dnl to 'yes' because some of the testsuite requires it. if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then BUILD_INCLUDED_LIBINTL=yes fi dnl Make all variables we use known to autoconf. AC_SUBST(BUILD_INCLUDED_LIBINTL) AC_SUBST(USE_INCLUDED_LIBINTL) AC_SUBST(CATOBJEXT) dnl For backward compatibility. Some configure.ins may be using this. nls_cv_header_intl= nls_cv_header_libgt= dnl For backward compatibility. Some Makefiles may be using this. DATADIRNAME=share AC_SUBST(DATADIRNAME) dnl For backward compatibility. Some Makefiles may be using this. INSTOBJEXT=.mo AC_SUBST(INSTOBJEXT) dnl For backward compatibility. Some Makefiles may be using this. GENCAT=gencat AC_SUBST(GENCAT) dnl For backward compatibility. Some Makefiles may be using this. INTLOBJS= if test "$USE_INCLUDED_LIBINTL" = yes; then INTLOBJS="\$(GETTOBJS)" fi AC_SUBST(INTLOBJS) dnl Enable libtool support if the surrounding package wishes it. INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX) ]) dnl For backward compatibility. Some Makefiles may be using this. INTLLIBS="$LIBINTL" AC_SUBST(INTLLIBS) dnl Make all documented variables known to autoconf. AC_SUBST(LIBINTL) AC_SUBST(LTLIBINTL) AC_SUBST(POSUB) ]) dnl Checks for special options needed on MacOS X. dnl Defines INTL_MACOSX_LIBS. AC_DEFUN([gt_INTL_MACOSX], [ dnl Check for API introduced in MacOS X 10.2. AC_CACHE_CHECK([for CFPreferencesCopyAppValue], gt_cv_func_CFPreferencesCopyAppValue, [gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" AC_TRY_LINK([#include ], [CFPreferencesCopyAppValue(NULL, NULL)], [gt_cv_func_CFPreferencesCopyAppValue=yes], [gt_cv_func_CFPreferencesCopyAppValue=no]) LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], 1, [Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) fi dnl Check for API introduced in MacOS X 10.3. AC_CACHE_CHECK([for CFLocaleCopyCurrent], gt_cv_func_CFLocaleCopyCurrent, [gt_save_LIBS="$LIBS" LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" AC_TRY_LINK([#include ], [CFLocaleCopyCurrent();], [gt_cv_func_CFLocaleCopyCurrent=yes], [gt_cv_func_CFLocaleCopyCurrent=no]) LIBS="$gt_save_LIBS"]) if test $gt_cv_func_CFLocaleCopyCurrent = yes; then AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], 1, [Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) fi INTL_MACOSX_LIBS= if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" fi AC_SUBST([INTL_MACOSX_LIBS]) ]) dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. m4_define([gt_NEEDS_INIT], [ m4_divert_text([DEFAULTS], [gt_needs=]) m4_define([gt_NEEDS_INIT], []) ]) dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) AC_DEFUN([AM_GNU_GETTEXT_NEED], [ m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) ]) dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) gnunet-0.10.1/m4/libtool.m40000644000175000017500000106011112320752051012235 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS gnunet-0.10.1/m4/lib-ld.m40000644000175000017500000000653111374167230011750 00000000000000# lib-ld.m4 serial 3 (gettext-0.13) dnl Copyright (C) 1996-2003 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl Subroutines of libtool.m4, dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision dnl with libtool.m4. dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no. AC_DEFUN([AC_LIB_PROG_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by GCC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]* | [A-Za-z]:[\\/]*)] [re_direlt='/[^/][^/]*/\.\./'] # Canonicalize the path of ld ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(acl_cv_path_LD, [if test -z "$LD"; then IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then acl_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$ac_save_ifs" else acl_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$acl_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) AC_LIB_PROG_LD_GNU ]) gnunet-0.10.1/m4/gnulib-cache.m40000644000175000017500000000240411531140570013112 00000000000000# Copyright (C) 2002-2011 Free Software Foundation, Inc. # # This file is free software, distributed under the terms of the GNU # General Public License. As a special exception to the GNU General # Public License, this file may be distributed as part of a program # that contains a configuration script generated by Autoconf, under # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. # # This file represents the specification of how gnulib-tool is used. # It acts as a cache: It is written and read by gnulib-tool. # In projects that use version control, this file is meant to be put under # version control, like the configure.ac and various Makefile.am files. # Specification in the form of a command-line invocation: # gnulib-tool --import --dir=/home/nils/workspace/gnunet --lib=libgnu --source-base=src/util/libgnu --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --libtool --macro-prefix=gl strtok_r # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) gl_MODULES([ strtok_r ]) gl_AVOID([]) gl_SOURCE_BASE([src/util/libgnu]) gl_M4_BASE([m4]) gl_PO_BASE([]) gl_DOC_BASE([doc]) gl_TESTS_BASE([tests]) gl_LIB([libgnu]) gl_MAKEFILE_NAME([]) gl_LIBTOOL gl_MACRO_PREFIX([gl]) gl_PO_DOMAIN([]) gnunet-0.10.1/m4/ltoptions.m40000644000175000017500000003007312320752051012627 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) gnunet-0.10.1/m4/lock.m40000644000175000017500000002770511374167230011543 00000000000000# lock.m4 serial 6 (gettext-0.16) dnl Copyright (C) 2005-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Tests for a multithreading library to be used. dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS, dnl USE_PTH_THREADS, USE_WIN32_THREADS dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with dnl libtool). dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for dnl programs that really need multithread functionality. The difference dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread". dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for dnl multithread-safe programs. AC_DEFUN([gl_LOCK_EARLY], [ AC_REQUIRE([gl_LOCK_EARLY_BODY]) ]) dnl The guts of gl_LOCK_EARLY. Needs to be expanded only once. AC_DEFUN([gl_LOCK_EARLY_BODY], [ dnl Ordering constraints: This macro modifies CPPFLAGS in a way that dnl influences the result of the autoconf tests that test for *_unlocked dnl declarations, on AIX 5 at least. Therefore it must come early. AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl AC_BEFORE([$0], [gl_ARGP])dnl AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_GNU_SOURCE]) dnl needed for pthread_rwlock_t on glibc systems dnl Check for multithreading. AC_ARG_ENABLE(threads, AC_HELP_STRING([--enable-threads={posix|solaris|pth|win32}], [specify multithreading API]) AC_HELP_STRING([--disable-threads], [build without multithread safety]), [gl_use_threads=$enableval], [case "$host_os" in dnl Disable multithreading by default on OSF/1, because it interferes dnl with fork()/exec(): When msgexec is linked with -lpthread, its child dnl process gets an endless segmentation fault inside execvp(). osf*) gl_use_threads=no ;; *) gl_use_threads=yes ;; esac ]) if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then # For using : case "$host_os" in osf*) # On OSF/1, the compiler needs the flag -D_REENTRANT so that it # groks . cc also understands the flag -pthread, but # we don't use it because 1. gcc-2.95 doesn't understand -pthread, # 2. putting a flag into CPPFLAGS that has an effect on the linker # causes the AC_TRY_LINK test below to succeed unexpectedly, # leading to wrong values of LIBTHREAD and LTLIBTHREAD. CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; esac # Some systems optimize for single-threaded programs by default, and # need special flags to disable these optimizations. For example, the # definition of 'errno' in . case "$host_os" in aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; esac fi ]) dnl The guts of gl_LOCK. Needs to be expanded only once. AC_DEFUN([gl_LOCK_BODY], [ AC_REQUIRE([gl_LOCK_EARLY_BODY]) gl_threads_api=none LIBTHREAD= LTLIBTHREAD= LIBMULTITHREAD= LTLIBMULTITHREAD= if test "$gl_use_threads" != no; then dnl Check whether the compiler and linker support weak declarations. AC_MSG_CHECKING([whether imported symbols can be declared weak]) gl_have_weak=no AC_TRY_LINK([extern void xyzzy (); #pragma weak xyzzy], [xyzzy();], [gl_have_weak=yes]) AC_MSG_RESULT([$gl_have_weak]) if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that # it groks . It's added above, in gl_LOCK_EARLY_BODY. AC_CHECK_HEADER(pthread.h, gl_have_pthread_h=yes, gl_have_pthread_h=no) if test "$gl_have_pthread_h" = yes; then # Other possible tests: # -lpthreads (FSU threads, PCthreads) # -lgthreads gl_have_pthread= # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist # in libc. IRIX 6.5 has the first one in both libc and libpthread, but # the second one only in libpthread, and lock.c needs it. AC_TRY_LINK([#include ], [pthread_mutex_lock((pthread_mutex_t*)0); pthread_mutexattr_init((pthread_mutexattr_t*)0);], [gl_have_pthread=yes]) # Test for libpthread by looking for pthread_kill. (Not pthread_self, # since it is defined as a macro on OSF/1.) if test -n "$gl_have_pthread"; then # The program links fine without libpthread. But it may actually # need to link with libpthread in order to create multiple threads. AC_CHECK_LIB(pthread, pthread_kill, [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread # On Solaris and HP-UX, most pthread functions exist also in libc. # Therefore pthread_in_use() needs to actually try to create a # thread: pthread_create from libc will fail, whereas # pthread_create will actually create a thread. case "$host_os" in solaris* | hpux*) AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], 1, [Define if the pthread_in_use() detection is hard.]) esac ]) else # Some library is needed. Try libpthread and libc_r. AC_CHECK_LIB(pthread, pthread_kill, [gl_have_pthread=yes LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread]) if test -z "$gl_have_pthread"; then # For FreeBSD 4. AC_CHECK_LIB(c_r, pthread_kill, [gl_have_pthread=yes LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r]) fi fi if test -n "$gl_have_pthread"; then gl_threads_api=posix AC_DEFINE([USE_POSIX_THREADS], 1, [Define if the POSIX multithreading library can be used.]) if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then if test $gl_have_weak = yes; then AC_DEFINE([USE_POSIX_THREADS_WEAK], 1, [Define if references to the POSIX multithreading library should be made weak.]) LIBTHREAD= LTLIBTHREAD= fi fi # OSF/1 4.0 and MacOS X 10.1 lack the pthread_rwlock_t type and the # pthread_rwlock_* functions. AC_CHECK_TYPE([pthread_rwlock_t], [AC_DEFINE([HAVE_PTHREAD_RWLOCK], 1, [Define if the POSIX multithreading library has read/write locks.])], [], [#include ]) # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. AC_TRY_COMPILE([#include ], [#if __FreeBSD__ == 4 error "No, in FreeBSD 4.0 recursive mutexes actually don't work." #else int x = (int)PTHREAD_MUTEX_RECURSIVE; return !x; #endif], [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1, [Define if the defines PTHREAD_MUTEX_RECURSIVE.])]) fi fi fi if test -z "$gl_have_pthread"; then if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then gl_have_solaristhread= gl_save_LIBS="$LIBS" LIBS="$LIBS -lthread" AC_TRY_LINK([#include #include ], [thr_self();], [gl_have_solaristhread=yes]) LIBS="$gl_save_LIBS" if test -n "$gl_have_solaristhread"; then gl_threads_api=solaris LIBTHREAD=-lthread LTLIBTHREAD=-lthread LIBMULTITHREAD="$LIBTHREAD" LTLIBMULTITHREAD="$LTLIBTHREAD" AC_DEFINE([USE_SOLARIS_THREADS], 1, [Define if the old Solaris multithreading library can be used.]) if test $gl_have_weak = yes; then AC_DEFINE([USE_SOLARIS_THREADS_WEAK], 1, [Define if references to the old Solaris multithreading library should be made weak.]) LIBTHREAD= LTLIBTHREAD= fi fi fi fi if test "$gl_use_threads" = pth; then gl_save_CPPFLAGS="$CPPFLAGS" AC_LIB_LINKFLAGS(pth) gl_have_pth= gl_save_LIBS="$LIBS" LIBS="$LIBS -lpth" AC_TRY_LINK([#include ], [pth_self();], gl_have_pth=yes) LIBS="$gl_save_LIBS" if test -n "$gl_have_pth"; then gl_threads_api=pth LIBTHREAD="$LIBPTH" LTLIBTHREAD="$LTLIBPTH" LIBMULTITHREAD="$LIBTHREAD" LTLIBMULTITHREAD="$LTLIBTHREAD" AC_DEFINE([USE_PTH_THREADS], 1, [Define if the GNU Pth multithreading library can be used.]) if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then if test $gl_have_weak = yes; then AC_DEFINE([USE_PTH_THREADS_WEAK], 1, [Define if references to the GNU Pth multithreading library should be made weak.]) LIBTHREAD= LTLIBTHREAD= fi fi else CPPFLAGS="$gl_save_CPPFLAGS" fi fi if test -z "$gl_have_pthread"; then if test "$gl_use_threads" = yes || test "$gl_use_threads" = win32; then if { case "$host_os" in mingw*) true;; *) false;; esac }; then gl_threads_api=win32 AC_DEFINE([USE_WIN32_THREADS], 1, [Define if the Win32 multithreading API can be used.]) fi fi fi fi AC_MSG_CHECKING([for multithread API to use]) AC_MSG_RESULT([$gl_threads_api]) AC_SUBST(LIBTHREAD) AC_SUBST(LTLIBTHREAD) AC_SUBST(LIBMULTITHREAD) AC_SUBST(LTLIBMULTITHREAD) ]) AC_DEFUN([gl_LOCK], [ AC_REQUIRE([gl_LOCK_EARLY]) AC_REQUIRE([gl_LOCK_BODY]) gl_PREREQ_LOCK ]) # Prerequisites of lib/lock.c. AC_DEFUN([gl_PREREQ_LOCK], [ AC_REQUIRE([AC_C_INLINE]) ]) dnl Survey of platforms: dnl dnl Platform Available Compiler Supports test-lock dnl flavours option weak result dnl --------------- --------- --------- -------- --------- dnl Linux 2.4/glibc posix -lpthread Y OK dnl dnl GNU Hurd/glibc posix dnl dnl FreeBSD 5.3 posix -lc_r Y dnl posix -lkse ? Y dnl posix -lpthread ? Y dnl posix -lthr Y dnl dnl FreeBSD 5.2 posix -lc_r Y dnl posix -lkse Y dnl posix -lthr Y dnl dnl FreeBSD 4.0,4.10 posix -lc_r Y OK dnl dnl NetBSD 1.6 -- dnl dnl OpenBSD 3.4 posix -lpthread Y OK dnl dnl MacOS X 10.[123] posix -lpthread Y OK dnl dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK dnl dnl HP-UX 11 posix -lpthread N (cc) OK dnl Y (gcc) dnl dnl IRIX 6.5 posix -lpthread Y 0.5 dnl dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK dnl dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK dnl -lpthread (gcc) Y dnl dnl Cygwin posix -lpthread Y OK dnl dnl Any of the above pth -lpth 0.0 dnl dnl Mingw win32 N OK dnl dnl BeOS 5 -- dnl dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is dnl turned off: dnl OK if all three tests terminate OK, dnl 0.5 if the first test terminates OK but the second one loops endlessly, dnl 0.0 if the first test already loops endlessly. gnunet-0.10.1/m4/align.m40000644000175000017500000000247112215576245011703 00000000000000# align.m4 dnl Copyright (C) 2008 Christian Grothoff dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. # Define HAVE_UNALIGNED_64_ACCESS if reading a 64-bit value at a 32-bit aligned offset works # Note that the program intentionally causes a SIGBUS (so you may # see some message along those lines on the console). AC_DEFUN([AC_UNALIGNED_64_ACCESS], [AC_CACHE_CHECK([whether unaligned 64-bit access works], ac_cv_unaligned_64_access, [ AC_RUN_IFELSE([AC_LANG_PROGRAM([[struct S { int a,b,c;};]], [[struct S s = {0,0,0}; long long * p = (long long *) &s.b; void *bp = malloc (50); long long x = *p; long long *be = (long long*) &bp[1]; long long y = *be; return (int) x*y;]]), ac_cv_unaligned_64_access=yes, ac_cv_unaligned_64_access=no, ac_cv_unaligned_64_access=no]) ]) case "$ac_cv_unaligned_64_access" in *yes) value=1;; *) value=0;; esac AC_DEFINE_UNQUOTED([HAVE_UNALIGNED_64_ACCESS], $value, [We can access-64 bit values that are only 32-bit aligned]) ]) gnunet-0.10.1/m4/nls.m40000644000175000017500000000226611374167230011402 00000000000000# nls.m4 serial 3 (gettext-0.15) dnl Copyright (C) 1995-2003, 2005-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ(2.50) AC_DEFUN([AM_NLS], [ AC_MSG_CHECKING([whether NLS is requested]) dnl Default is enabled NLS AC_ARG_ENABLE(nls, [ --disable-nls do not use Native Language Support], USE_NLS=$enableval, USE_NLS=yes) AC_MSG_RESULT($USE_NLS) AC_SUBST(USE_NLS) ]) gnunet-0.10.1/m4/libxml2.m40000644000175000017500000001731011374167230012153 00000000000000# Configure paths for LIBXML2 # Mike Hommey 2004-06-19 # use CPPFLAGS instead of CFLAGS # Toshio Kuratomi 2001-04-21 # Adapted from: # Configure paths for GLIB # Owen Taylor 97-11-3 dnl AM_PATH_XML2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for XML, and define XML_CPPFLAGS and XML_LIBS dnl AC_DEFUN([AM_PATH_XML2],[ AC_ARG_WITH(xml-prefix, [ --with-xml-prefix=PFX Prefix where libxml is installed (optional)], xml_config_prefix="$withval", xml_config_prefix="") AC_ARG_WITH(xml-exec-prefix, [ --with-xml-exec-prefix=PFX Exec prefix where libxml is installed (optional)], xml_config_exec_prefix="$withval", xml_config_exec_prefix="") AC_ARG_ENABLE(xmltest, [ --disable-xmltest Do not try to compile and run a test LIBXML program],, enable_xmltest=yes) if test x$xml_config_exec_prefix != x ; then xml_config_args="$xml_config_args" if test x${XML2_CONFIG+set} != xset ; then XML2_CONFIG=$xml_config_exec_prefix/bin/xml2-config fi fi if test x$xml_config_prefix != x ; then xml_config_args="$xml_config_args --prefix=$xml_config_prefix" if test x${XML2_CONFIG+set} != xset ; then XML2_CONFIG=$xml_config_prefix/bin/xml2-config fi fi AC_PATH_PROG(XML2_CONFIG, xml2-config, no) min_xml_version=ifelse([$1], ,2.0.0,[$1]) AC_MSG_CHECKING(for libxml - version >= $min_xml_version) no_xml="" if test "$XML2_CONFIG" = "no" ; then no_xml=yes else XML_CPPFLAGS=`$XML2_CONFIG $xml_config_args --cflags` XML_LIBS=`$XML2_CONFIG $xml_config_args --libs` xml_config_major_version=`$XML2_CONFIG $xml_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` xml_config_minor_version=`$XML2_CONFIG $xml_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` xml_config_micro_version=`$XML2_CONFIG $xml_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "x$enable_xmltest" = "xyes" ; then ac_save_CPPFLAGS="$CPPFLAGS" ac_save_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" LIBS="$XML_LIBS $LIBS" dnl dnl Now check if the installed libxml is sufficiently new. dnl (Also sanity checks the results of xml2-config to some extent) dnl rm -f conf.xmltest AC_TRY_RUN([ #include #include #include #include int main() { int xml_major_version, xml_minor_version, xml_micro_version; int major, minor, micro; char *tmp_version; system("touch conf.xmltest"); /* Capture xml2-config output via autoconf/configure variables */ /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = (char *)strdup("$min_xml_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string from xml2-config\n", "$min_xml_version"); exit(1); } free(tmp_version); /* Capture the version information from the header files */ tmp_version = (char *)strdup(LIBXML_DOTTED_VERSION); if (sscanf(tmp_version, "%d.%d.%d", &xml_major_version, &xml_minor_version, &xml_micro_version) != 3) { printf("%s, bad version string from libxml includes\n", "LIBXML_DOTTED_VERSION"); exit(1); } free(tmp_version); /* Compare xml2-config output to the libxml headers */ if ((xml_major_version != $xml_config_major_version) || (xml_minor_version != $xml_config_minor_version) || (xml_micro_version != $xml_config_micro_version)) { printf("*** libxml header files (version %d.%d.%d) do not match\n", xml_major_version, xml_minor_version, xml_micro_version); printf("*** xml2-config (version %d.%d.%d)\n", $xml_config_major_version, $xml_config_minor_version, $xml_config_micro_version); return 1; } /* Compare the headers to the library to make sure we match */ /* Less than ideal -- doesn't provide us with return value feedback, * only exits if there's a serious mismatch between header and library. */ LIBXML_TEST_VERSION; /* Test that the library is greater than our minimum version */ if ((xml_major_version > major) || ((xml_major_version == major) && (xml_minor_version > minor)) || ((xml_major_version == major) && (xml_minor_version == minor) && (xml_micro_version >= micro))) { return 0; } else { printf("\n*** An old version of libxml (%d.%d.%d) was found.\n", xml_major_version, xml_minor_version, xml_micro_version); printf("*** You need a version of libxml newer than %d.%d.%d. The latest version of\n", major, minor, micro); printf("*** libxml is always available from ftp://ftp.xmlsoft.org.\n"); printf("***\n"); printf("*** If you have already installed a sufficiently new version, this error\n"); printf("*** probably means that the wrong copy of the xml2-config shell script is\n"); printf("*** being found. The easiest way to fix this is to remove the old version\n"); printf("*** of LIBXML, but you can also set the XML2_CONFIG environment to point to the\n"); printf("*** correct copy of xml2-config. (In this case, you will have to\n"); printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); printf("*** so that the correct libraries are found at run-time))\n"); } return 1; } ],, no_xml=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CPPFLAGS="$ac_save_CPPFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_xml" = x ; then AC_MSG_RESULT(yes (version $xml_config_major_version.$xml_config_minor_version.$xml_config_micro_version)) ifelse([$2], , :, [$2]) else AC_MSG_RESULT(no) if test "$XML2_CONFIG" = "no" ; then echo "*** The xml2-config script installed by LIBXML could not be found" echo "*** If libxml was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the XML2_CONFIG environment variable to the" echo "*** full path to xml2-config." else if test -f conf.xmltest ; then : else echo "*** Could not run libxml test program, checking why..." CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" LIBS="$LIBS $XML_LIBS" AC_TRY_LINK([ #include #include ], [ LIBXML_TEST_VERSION; return 0;], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding LIBXML or finding the wrong" echo "*** version of LIBXML. If it is not finding LIBXML, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means LIBXML was incorrectly installed" echo "*** or that you have moved LIBXML since it was installed. In the latter case, you" echo "*** may want to edit the xml2-config script: $XML2_CONFIG" ]) CPPFLAGS="$ac_save_CPPFLAGS" LIBS="$ac_save_LIBS" fi fi XML_CPPFLAGS="" XML_LIBS="" ifelse([$3], , :, [$3]) fi AC_SUBST(XML_CPPFLAGS) AC_SUBST(XML_LIBS) rm -f conf.xmltest ]) gnunet-0.10.1/m4/lt~obsolete.m40000644000175000017500000001375612320752051013157 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) gnunet-0.10.1/m4/po.m40000644000175000017500000004461612220037066011223 00000000000000# po.m4 serial 17 (gettext-0.18) dnl Copyright (C) 1995-2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2003. AC_PREREQ([2.50]) dnl Checks for all prerequisites of the po subdirectory. AC_DEFUN([AM_PO_SUBDIRS], [ AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake AC_REQUIRE([AM_NLS])dnl dnl Release version of the gettext macros. This is used to ensure that dnl the gettext macros and po/Makefile.in.in are in sync. AC_SUBST([GETTEXT_MACRO_VERSION], [0.18]) dnl Perform the following tests also if --disable-nls has been given, dnl because they are needed for "make dist" to work. dnl Search for GNU msgfmt in the PATH. dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. dnl The second test excludes FreeBSD msgfmt. AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) dnl Test whether it is GNU msgfmt >= 0.15. changequote(,)dnl case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; *) MSGFMT_015=$MSGFMT ;; esac changequote([,])dnl AC_SUBST([MSGFMT_015]) changequote(,)dnl case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; *) GMSGFMT_015=$GMSGFMT ;; esac changequote([,])dnl AC_SUBST([GMSGFMT_015]) dnl Search for GNU xgettext 0.12 or newer in the PATH. dnl The first test excludes Solaris xgettext and early GNU xgettext versions. dnl The second test excludes FreeBSD xgettext. AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], :) dnl Remove leftover from FreeBSD xgettext call. rm -f messages.po dnl Test whether it is GNU xgettext >= 0.15. changequote(,)dnl case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; *) XGETTEXT_015=$XGETTEXT ;; esac changequote([,])dnl AC_SUBST([XGETTEXT_015]) dnl Search for GNU msgmerge 0.11 or newer in the PATH. AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) dnl Installation directories. dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we dnl have to define it here, so that it can be used in po/Makefile. test -n "$localedir" || localedir='${datadir}/locale' AC_SUBST([localedir]) dnl Support for AM_XGETTEXT_OPTION. test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) AC_CONFIG_COMMANDS([po-directories], [[ for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; esac # PO directories have a Makefile.in generated from Makefile.in.in. case "$ac_file" in */Makefile.in) # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Treat a directory as a PO directory if and only if it has a # POTFILES.in file. This allows packages to have multiple PO # directories under different names or in different locations. if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then rm -f "$ac_dir/POTFILES" test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" POMAKEFILEDEPS="POTFILES.in" # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend # on $ac_dir but don't depend on user-specified configuration # parameters. if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then # The LINGUAS file contains the set of available languages. if test -n "$OBSOLETE_ALL_LINGUAS"; then test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" fi ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$ALL_LINGUAS_' POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" else # The set of available languages was given in configure.in. # Hide the ALL_LINGUAS assigment from automake < 1.5. eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' fi # Compute POFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) # Compute UPDATEPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) # Compute DUMMYPOFILES # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) # Compute GMOFILES # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) case "$ac_given_srcdir" in .) srcdirpre= ;; *) srcdirpre='$(srcdir)/' ;; esac POFILES= UPDATEPOFILES= DUMMYPOFILES= GMOFILES= for lang in $ALL_LINGUAS; do POFILES="$POFILES $srcdirpre$lang.po" UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $lang.nop" GMOFILES="$GMOFILES $srcdirpre$lang.gmo" done # CATALOGS depends on both $ac_dir and the user's LINGUAS # environment variable. INST_LINGUAS= if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do if test -f "$f"; then case "$f" in *.orig | *.bak | *~) ;; *) cat "$f" >> "$ac_dir/Makefile" ;; esac fi done fi ;; esac done]], [# Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it # from automake < 1.5. eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' # Capture the value of LINGUAS because we need it to compute CATALOGS. LINGUAS="${LINGUAS-%UNSET%}" ]) ]) dnl Postprocesses a Makefile in a directory containing PO files. AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], [ # When this code is run, in config.status, two variables have already been # set: # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, # - LINGUAS is the value of the environment variable LINGUAS at configure # time. changequote(,)dnl # Adjust a relative srcdir. ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`" ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` # In autoconf-2.13 it is called $ac_given_srcdir. # In autoconf-2.50 it is called $srcdir. test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" case "$ac_given_srcdir" in .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; /*) top_srcdir="$ac_given_srcdir" ;; *) top_srcdir="$ac_dots$ac_given_srcdir" ;; esac # Find a way to echo strings without interpreting backslash. if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then gt_echo='echo' else if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then gt_echo='printf %s\n' else echo_func () { cat < "$ac_file.tmp" if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` cat >> "$ac_file.tmp" < /dev/null; then # Add dependencies that cannot be formulated as a simple suffix rule. for lang in $ALL_LINGUAS; do frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` cat >> "$ac_file.tmp" <> "$ac_file.tmp" < * gettext.m4: Upgrade to gettext-0.16.1. * iconv.m4: Upgrade to gettext-0.16.1. * lib-ld.m4: Upgrade to gettext-0.16.1. * lib-link.m4: Upgrade to gettext-0.16.1. * lib-prefix.m4: Upgrade to gettext-0.16.1. * nls.m4: Upgrade to gettext-0.16.1. * po.m4: Upgrade to gettext-0.16.1. * progtest.m4: Upgrade to gettext-0.16.1. * codeset.m4: Upgrade to gettext-0.16.1. * glibc2.m4: New file, from gettext-0.16.1. * glibc21.m4: Upgrade to gettext-0.16.1. * intdiv0.m4: Upgrade to gettext-0.16.1. * intl.m4: New file, from gettext-0.16.1. * intldir.m4: New file, from gettext-0.16.1. * intmax.m4: Upgrade to gettext-0.16.1. * inttypes_h.m4: Upgrade to gettext-0.16.1. * inttypes-pri.m4: Upgrade to gettext-0.16.1. * lcmessage.m4: Upgrade to gettext-0.16.1. * lock.m4: New file, from gettext-0.16.1. * longdouble.m4: Upgrade to gettext-0.16.1. * longlong.m4: Upgrade to gettext-0.16.1. * printf-posix.m4: Upgrade to gettext-0.16.1. * size_max.m4: Upgrade to gettext-0.16.1. * stdint_h.m4: Upgrade to gettext-0.16.1. * uintmax_t.m4: Upgrade to gettext-0.16.1. * ulonglong.m4: Upgrade to gettext-0.16.1. * visibility.m4: New file, from gettext-0.16.1. * wchar_t.m4: Upgrade to gettext-0.16.1. * wint_t.m4: Upgrade to gettext-0.16.1. * xsize.m4: Upgrade to gettext-0.16.1. * Makefile.am (EXTRA_DIST): Add the new files. 2004-08-21 gettextize * codeset.m4: New file, from gettext-0.14. * gettext.m4: New file, from gettext-0.14. * glibc21.m4: New file, from gettext-0.14. * iconv.m4: New file, from gettext-0.14. * intdiv0.m4: New file, from gettext-0.14. * intmax.m4: New file, from gettext-0.14. * inttypes.m4: New file, from gettext-0.14. * inttypes_h.m4: New file, from gettext-0.14. * inttypes-pri.m4: New file, from gettext-0.14. * isc-posix.m4: New file, from gettext-0.14. * lcmessage.m4: New file, from gettext-0.14. * lib-ld.m4: New file, from gettext-0.14. * lib-link.m4: New file, from gettext-0.14. * lib-prefix.m4: New file, from gettext-0.14. * longdouble.m4: New file, from gettext-0.14. * longlong.m4: New file, from gettext-0.14. * nls.m4: New file, from gettext-0.14. * po.m4: New file, from gettext-0.14. * printf-posix.m4: New file, from gettext-0.14. * progtest.m4: New file, from gettext-0.14. * signed.m4: New file, from gettext-0.14. * size_max.m4: New file, from gettext-0.14. * stdint_h.m4: New file, from gettext-0.14. * uintmax_t.m4: New file, from gettext-0.14. * ulonglong.m4: New file, from gettext-0.14. * wchar_t.m4: New file, from gettext-0.14. * wint_t.m4: New file, from gettext-0.14. * xsize.m4: New file, from gettext-0.14. * Makefile.am: New file. gnunet-0.10.1/m4/lcmessage.m40000644000175000017500000000240411374167230012543 00000000000000# lcmessage.m4 serial 4 (gettext-0.14.2) dnl Copyright (C) 1995-2002, 2004-2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995. # Check whether LC_MESSAGES is available in . AC_DEFUN([gt_LC_MESSAGES], [ AC_CACHE_CHECK([for LC_MESSAGES], gt_cv_val_LC_MESSAGES, [AC_TRY_LINK([#include ], [return LC_MESSAGES], gt_cv_val_LC_MESSAGES=yes, gt_cv_val_LC_MESSAGES=no)]) if test $gt_cv_val_LC_MESSAGES = yes; then AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your file defines LC_MESSAGES.]) fi ]) gnunet-0.10.1/m4/freetype2.m40000644000175000017500000001304511374167230012510 00000000000000# Configure paths for FreeType2 # Marcelo Magallon 2001-10-26, based on gtk.m4 by Owen Taylor # # serial 2 # AC_CHECK_FT2([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) # Test for FreeType 2, and define FT2_CFLAGS and FT2_LIBS. # MINIMUM-VERSION is what libtool reports; the default is `7.0.1' (this is # FreeType 2.0.4). # AC_DEFUN([AC_CHECK_FT2], [# Get the cflags and libraries from the freetype-config script # AC_ARG_WITH([ft-prefix], dnl don't quote AS_HELP_STRING! AS_HELP_STRING([--with-ft-prefix=PREFIX], [Prefix where FreeType is installed (optional)]), [ft_config_prefix="$withval"], [ft_config_prefix=""]) AC_ARG_WITH([ft-exec-prefix], dnl don't quote AS_HELP_STRING! AS_HELP_STRING([--with-ft-exec-prefix=PREFIX], [Exec prefix where FreeType is installed (optional)]), [ft_config_exec_prefix="$withval"], [ft_config_exec_prefix=""]) AC_ARG_ENABLE([freetypetest], dnl don't quote AS_HELP_STRING! AS_HELP_STRING([--disable-freetypetest], [Do not try to compile and run a test FreeType program]), [], [enable_fttest=yes]) if test x$ft_config_exec_prefix != x ; then ft_config_args="$ft_config_args --exec-prefix=$ft_config_exec_prefix" if test x${FT2_CONFIG+set} != xset ; then FT2_CONFIG=$ft_config_exec_prefix/bin/freetype-config fi fi if test x$ft_config_prefix != x ; then ft_config_args="$ft_config_args --prefix=$ft_config_prefix" if test x${FT2_CONFIG+set} != xset ; then FT2_CONFIG=$ft_config_prefix/bin/freetype-config fi fi AC_PATH_PROG([FT2_CONFIG], [freetype-config], [no]) min_ft_version=m4_if([$1], [], [7.0.1], [$1]) AC_MSG_CHECKING([for FreeType -- version >= $min_ft_version]) no_ft="" if test "$FT2_CONFIG" = "no" ; then no_ft=yes else FT2_CFLAGS=`$FT2_CONFIG $ft_config_args --cflags` FT2_LIBS=`$FT2_CONFIG $ft_config_args --libs` ft_config_major_version=`$FT2_CONFIG $ft_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` ft_config_minor_version=`$FT2_CONFIG $ft_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` ft_config_micro_version=`$FT2_CONFIG $ft_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` ft_min_major_version=`echo $min_ft_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` ft_min_minor_version=`echo $min_ft_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` ft_min_micro_version=`echo $min_ft_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test x$enable_fttest = xyes ; then ft_config_is_lt="" if test $ft_config_major_version -lt $ft_min_major_version ; then ft_config_is_lt=yes else if test $ft_config_major_version -eq $ft_min_major_version ; then if test $ft_config_minor_version -lt $ft_min_minor_version ; then ft_config_is_lt=yes else if test $ft_config_minor_version -eq $ft_min_minor_version ; then if test $ft_config_micro_version -lt $ft_min_micro_version ; then ft_config_is_lt=yes fi fi fi fi fi if test x$ft_config_is_lt = xyes ; then no_ft=yes else ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $FT2_CFLAGS" LIBS="$FT2_LIBS $LIBS" # # Sanity checks for the results of freetype-config to some extent. # AC_RUN_IFELSE([ AC_LANG_SOURCE([[ #include #include FT_FREETYPE_H #include #include int main() { FT_Library library; FT_Error error; error = FT_Init_FreeType(&library); if (error) return 1; else { FT_Done_FreeType(library); return 0; } } ]]) ], [], [no_ft=yes], [echo $ECHO_N "cross compiling; assuming OK... $ECHO_C"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi # test $ft_config_version -lt $ft_min_version fi # test x$enable_fttest = xyes fi # test "$FT2_CONFIG" = "no" if test x$no_ft = x ; then AC_MSG_RESULT([yes]) m4_if([$2], [], [:], [$2]) else AC_MSG_RESULT([no]) if test "$FT2_CONFIG" = "no" ; then AC_MSG_WARN([ The freetype-config script installed by FreeType 2 could not be found. If FreeType 2 was installed in PREFIX, make sure PREFIX/bin is in your path, or set the FT2_CONFIG environment variable to the full path to freetype-config. ]) else if test x$ft_config_is_lt = xyes ; then AC_MSG_WARN([ Your installed version of the FreeType 2 library is too old. If you have different versions of FreeType 2, make sure that correct values for --with-ft-prefix or --with-ft-exec-prefix are used, or set the FT2_CONFIG environment variable to the full path to freetype-config. ]) else AC_MSG_WARN([ The FreeType test program failed to run. If your system uses shared libraries and they are installed outside the normal system library path, make sure the variable LD_LIBRARY_PATH (or whatever is appropiate for your system) is correctly set. ]) fi fi FT2_CFLAGS="" FT2_LIBS="" m4_if([$3], [], [:], [$3]) fi AC_SUBST([FT2_CFLAGS]) AC_SUBST([FT2_LIBS])]) # end of freetype2.m4 gnunet-0.10.1/m4/inttypes.m40000644000175000017500000000171711374167230012465 00000000000000# inttypes.m4 serial 1 (gettext-0.11.4) dnl Copyright (C) 1997-2002 Free Software Foundation, Inc. dnl This file is free software, distributed under the terms of the GNU dnl General Public License. As a special exception to the GNU General dnl Public License, this file may be distributed as part of a program dnl that contains a configuration script generated by Autoconf, under dnl the same distribution terms as the rest of that program. dnl From Paul Eggert. # Define HAVE_INTTYPES_H if exists and doesn't clash with # . AC_DEFUN([gt_HEADER_INTTYPES_H], [ AC_CACHE_CHECK([for inttypes.h], gt_cv_header_inttypes_h, [ AC_TRY_COMPILE( [#include #include ], [], gt_cv_header_inttypes_h=yes, gt_cv_header_inttypes_h=no) ]) if test $gt_cv_header_inttypes_h = yes; then AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1, [Define if exists and doesn't clash with .]) fi ]) gnunet-0.10.1/m4/glib-2.0.m40000644000175000017500000001776211374167230012027 00000000000000# Configure paths for GLIB # Owen Taylor 1997-2001 dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject or dnl gthread is specified in MODULES, pass to pkg-config dnl AC_DEFUN([AM_PATH_GLIB_2_0], [dnl dnl Get the cflags and libraries from pkg-config dnl AC_ARG_ENABLE(glibtest, [ --disable-glibtest do not try to compile and run a test GLIB program], , enable_glibtest=yes) pkg_config_args=glib-2.0 for module in . $4 do case "$module" in gmodule) pkg_config_args="$pkg_config_args gmodule-2.0" ;; gobject) pkg_config_args="$pkg_config_args gobject-2.0" ;; gthread) pkg_config_args="$pkg_config_args gthread-2.0" ;; esac done AC_PATH_PROG(PKG_CONFIG, pkg-config, no) no_glib="" if test x$PKG_CONFIG != xno ; then if $PKG_CONFIG --atleast-pkgconfig-version 0.7 ; then : else echo *** pkg-config too old; version 0.7 or better required. no_glib=yes PKG_CONFIG=no fi else no_glib=yes fi min_glib_version=ifelse([$1], ,2.0.0,$1) AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) if test x$PKG_CONFIG != xno ; then ## don't try to run the test against uninstalled libtool libs if $PKG_CONFIG --uninstalled $pkg_config_args; then echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH" enable_glibtest=no fi if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then : else no_glib=yes fi fi if test x"$no_glib" = x ; then GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0` GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0` GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args` glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "x$enable_glibtest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $GLIB_CFLAGS" LIBS="$GLIB_LIBS $LIBS" dnl dnl Now check if the installed GLIB is sufficiently new. (Also sanity dnl checks the results of pkg-config to some extent) dnl rm -f conf.glibtest AC_TRY_RUN([ #include #include #include int main () { int major, minor, micro; char *tmp_version; system ("touch conf.glibtest"); /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = g_strdup("$min_glib_version"); if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { printf("%s, bad version string\n", "$min_glib_version"); exit(1); } if ((glib_major_version != $glib_config_major_version) || (glib_minor_version != $glib_config_minor_version) || (glib_micro_version != $glib_config_micro_version)) { printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, glib_major_version, glib_minor_version, glib_micro_version); printf ("*** was found! If pkg-config was correct, then it is best\n"); printf ("*** to remove the old version of GLib. You may also be able to fix the error\n"); printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); printf("*** required on your system.\n"); printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n"); printf("*** to point to the correct configuration files\n"); } else if ((glib_major_version != GLIB_MAJOR_VERSION) || (glib_minor_version != GLIB_MINOR_VERSION) || (glib_micro_version != GLIB_MICRO_VERSION)) { printf("*** GLIB header files (version %d.%d.%d) do not match\n", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); printf("*** library (version %d.%d.%d)\n", glib_major_version, glib_minor_version, glib_micro_version); } else { if ((glib_major_version > major) || ((glib_major_version == major) && (glib_minor_version > minor)) || ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) { return 0; } else { printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n", glib_major_version, glib_minor_version, glib_micro_version); printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n", major, minor, micro); printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); printf("***\n"); printf("*** If you have already installed a sufficiently new version, this error\n"); printf("*** probably means that the wrong copy of the pkg-config shell script is\n"); printf("*** being found. The easiest way to fix this is to remove the old version\n"); printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n"); printf("*** correct copy of pkg-config. (In this case, you will have to\n"); printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); printf("*** so that the correct libraries are found at run-time))\n"); } } return 1; } ],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_glib" = x ; then AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)) ifelse([$2], , :, [$2]) else AC_MSG_RESULT(no) if test "$PKG_CONFIG" = "no" ; then echo "*** A new enough version of pkg-config was not found." echo "*** See http://www.freedesktop.org/software/pkgconfig/" else if test -f conf.glibtest ; then : else echo "*** Could not run GLIB test program, checking why..." ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $GLIB_CFLAGS" LIBS="$LIBS $GLIB_LIBS" AC_TRY_LINK([ #include #include ], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], [ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding GLIB or finding the wrong" echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" echo "*** to the installed location Also, make sure you have run ldconfig if that" echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ], [ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means GLIB is incorrectly installed."]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi GLIB_CFLAGS="" GLIB_LIBS="" GLIB_GENMARSHAL="" GOBJECT_QUERY="" GLIB_MKENUMS="" ifelse([$3], , :, [$3]) fi AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) AC_SUBST(GLIB_GENMARSHAL) AC_SUBST(GOBJECT_QUERY) AC_SUBST(GLIB_MKENUMS) rm -f conf.glibtest ]) gnunet-0.10.1/m4/intl.m40000644000175000017500000002333011374167230011547 00000000000000# intl.m4 serial 3 (gettext-0.16) dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl dnl This file can can be used in projects which are not available under dnl the GNU General Public License or the GNU Library General Public dnl License but which still want to provide support for the GNU gettext dnl functionality. dnl Please note that the actual code of the GNU gettext library is covered dnl by the GNU Library General Public License, and the rest of the GNU dnl gettext package package is covered by the GNU General Public License. dnl They are *not* in the public domain. dnl Authors: dnl Ulrich Drepper , 1995-2000. dnl Bruno Haible , 2000-2006. AC_PREREQ(2.52) dnl Checks for all prerequisites of the intl subdirectory, dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. AC_DEFUN([AM_INTL_SUBDIR], [ AC_REQUIRE([AC_PROG_INSTALL])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([gt_GLIBC2])dnl AC_REQUIRE([AC_PROG_RANLIB])dnl AC_REQUIRE([gl_VISIBILITY])dnl AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl AC_REQUIRE([gt_TYPE_LONGDOUBLE])dnl AC_REQUIRE([gt_TYPE_WCHAR_T])dnl AC_REQUIRE([gt_TYPE_WINT_T])dnl AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gt_TYPE_INTMAX_T]) AC_REQUIRE([gt_PRINTF_POSIX]) AC_REQUIRE([gl_GLIBC21])dnl AC_REQUIRE([gl_XSIZE])dnl AC_REQUIRE([gt_INTL_MACOSX])dnl AC_CHECK_TYPE([ptrdiff_t], , [AC_DEFINE([ptrdiff_t], [long], [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) ]) AC_CHECK_HEADERS([stddef.h stdlib.h string.h]) AC_CHECK_FUNCS([asprintf fwprintf putenv setenv setlocale snprintf wcslen]) dnl Use the _snprintf function only if it is declared (because on NetBSD it dnl is defined as a weak alias of snprintf; we prefer to use the latter). gt_CHECK_DECL(_snprintf, [#include ]) gt_CHECK_DECL(_snwprintf, [#include ]) dnl Use the *_unlocked functions only if they are declared. dnl (because some of them were defined without being declared in Solaris dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built dnl on Solaris 2.5.1 to run on Solaris 2.6). dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. gt_CHECK_DECL(getc_unlocked, [#include ]) case $gt_cv_func_printf_posix in *yes) HAVE_POSIX_PRINTF=1 ;; *) HAVE_POSIX_PRINTF=0 ;; esac AC_SUBST([HAVE_POSIX_PRINTF]) if test "$ac_cv_func_asprintf" = yes; then HAVE_ASPRINTF=1 else HAVE_ASPRINTF=0 fi AC_SUBST([HAVE_ASPRINTF]) if test "$ac_cv_func_snprintf" = yes; then HAVE_SNPRINTF=1 else HAVE_SNPRINTF=0 fi AC_SUBST([HAVE_SNPRINTF]) if test "$ac_cv_func_wprintf" = yes; then HAVE_WPRINTF=1 else HAVE_WPRINTF=0 fi AC_SUBST([HAVE_WPRINTF]) AM_LANGINFO_CODESET gt_LC_MESSAGES dnl Compilation on mingw and Cygwin needs special Makefile rules, because dnl 1. when we install a shared library, we must arrange to export dnl auxiliary pointer variables for every exported variable, dnl 2. when we install a shared library and a static library simultaneously, dnl the include file specifies __declspec(dllimport) and therefore we dnl must arrange to define the auxiliary pointer variables for the dnl exported variables _also_ in the static library. if test "$enable_shared" = yes; then case "$host_os" in cygwin*) is_woe32dll=yes ;; *) is_woe32dll=no ;; esac else is_woe32dll=no fi WOE32DLL=$is_woe32dll AC_SUBST([WOE32DLL]) dnl Rename some macros and functions used for locking. AH_BOTTOM([ #define __libc_lock_t gl_lock_t #define __libc_lock_define gl_lock_define #define __libc_lock_define_initialized gl_lock_define_initialized #define __libc_lock_init gl_lock_init #define __libc_lock_lock gl_lock_lock #define __libc_lock_unlock gl_lock_unlock #define __libc_lock_recursive_t gl_recursive_lock_t #define __libc_lock_define_recursive gl_recursive_lock_define #define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized #define __libc_lock_init_recursive gl_recursive_lock_init #define __libc_lock_lock_recursive gl_recursive_lock_lock #define __libc_lock_unlock_recursive gl_recursive_lock_unlock #define glthread_in_use libintl_thread_in_use #define glthread_lock_init libintl_lock_init #define glthread_lock_lock libintl_lock_lock #define glthread_lock_unlock libintl_lock_unlock #define glthread_lock_destroy libintl_lock_destroy #define glthread_rwlock_init libintl_rwlock_init #define glthread_rwlock_rdlock libintl_rwlock_rdlock #define glthread_rwlock_wrlock libintl_rwlock_wrlock #define glthread_rwlock_unlock libintl_rwlock_unlock #define glthread_rwlock_destroy libintl_rwlock_destroy #define glthread_recursive_lock_init libintl_recursive_lock_init #define glthread_recursive_lock_lock libintl_recursive_lock_lock #define glthread_recursive_lock_unlock libintl_recursive_lock_unlock #define glthread_recursive_lock_destroy libintl_recursive_lock_destroy #define glthread_once libintl_once #define glthread_once_call libintl_once_call #define glthread_once_singlethreaded libintl_once_singlethreaded ]) ]) dnl Checks for the core files of the intl subdirectory: dnl dcigettext.c dnl eval-plural.h dnl explodename.c dnl finddomain.c dnl gettextP.h dnl gmo.h dnl hash-string.h hash-string.c dnl l10nflist.c dnl libgnuintl.h.in (except the *printf stuff) dnl loadinfo.h dnl loadmsgcat.c dnl localealias.c dnl log.c dnl plural-exp.h plural-exp.c dnl plural.y dnl Used by libglocale. AC_DEFUN([gt_INTL_SUBDIR_CORE], [ AC_REQUIRE([AC_C_INLINE])dnl AC_REQUIRE([AC_TYPE_SIZE_T])dnl AC_REQUIRE([gl_AC_HEADER_STDINT_H]) AC_REQUIRE([AC_FUNC_ALLOCA])dnl AC_REQUIRE([AC_FUNC_MMAP])dnl AC_REQUIRE([gt_INTDIV0])dnl AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl AC_REQUIRE([gt_INTTYPES_PRI])dnl AC_REQUIRE([gl_LOCK])dnl AC_TRY_LINK( [int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }], [], [AC_DEFINE([HAVE_BUILTIN_EXPECT], 1, [Define to 1 if the compiler understands __builtin_expect.])]) AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h]) AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ stpcpy strcasecmp strdup strtoul tsearch argz_count argz_stringify \ argz_next __fsetlocking]) dnl Use the *_unlocked functions only if they are declared. dnl (because some of them were defined without being declared in Solaris dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built dnl on Solaris 2.5.1 to run on Solaris 2.6). dnl Don't use AC_CHECK_DECLS because it isn't supported in autoconf-2.13. gt_CHECK_DECL(feof_unlocked, [#include ]) gt_CHECK_DECL(fgets_unlocked, [#include ]) AM_ICONV dnl glibc >= 2.4 has a NL_LOCALE_NAME macro when _GNU_SOURCE is defined, dnl and a _NL_LOCALE_NAME macro always. AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name, [AC_TRY_LINK([#include #include ], [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES));], gt_cv_nl_locale_name=yes, gt_cv_nl_locale_name=no) ]) if test $gt_cv_nl_locale_name = yes; then AC_DEFINE(HAVE_NL_LOCALE_NAME, 1, [Define if you have and it defines the NL_LOCALE_NAME macro if _GNU_SOURCE is defined.]) fi dnl intl/plural.c is generated from intl/plural.y. It requires bison, dnl because plural.y uses bison specific features. It requires at least dnl bison-1.26 because earlier versions generate a plural.c that doesn't dnl compile. dnl bison is only needed for the maintainer (who touches plural.y). But in dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put dnl the rule in general Makefile. Now, some people carelessly touch the dnl files or have a broken "make" program, hence the plural.c rule will dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not dnl present or too old. AC_CHECK_PROGS([INTLBISON], [bison]) if test -z "$INTLBISON"; then ac_verc_fail=yes else dnl Found it, now check the version. AC_MSG_CHECKING([version of bison]) changequote(<<,>>)dnl ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` case $ac_prog_version in '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) changequote([,])dnl ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; esac AC_MSG_RESULT([$ac_prog_version]) fi if test $ac_verc_fail = yes; then INTLBISON=: fi ]) dnl gt_CHECK_DECL(FUNC, INCLUDES) dnl Check whether a function is declared. AC_DEFUN([gt_CHECK_DECL], [ AC_CACHE_CHECK([whether $1 is declared], ac_cv_have_decl_$1, [AC_TRY_COMPILE([$2], [ #ifndef $1 char *p = (char *) $1; #endif ], ac_cv_have_decl_$1=yes, ac_cv_have_decl_$1=no)]) if test $ac_cv_have_decl_$1 = yes; then gt_value=1 else gt_value=0 fi AC_DEFINE_UNQUOTED([HAVE_DECL_]translit($1, [a-z], [A-Z]), [$gt_value], [Define to 1 if you have the declaration of `$1', and to 0 if you don't.]) ]) gnunet-0.10.1/m4/visibility.m40000644000175000017500000000413011374167230012765 00000000000000# visibility.m4 serial 1 (gettext-0.15) dnl Copyright (C) 2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Bruno Haible. dnl Tests whether the compiler supports the command-line option dnl -fvisibility=hidden and the function and variable attributes dnl __attribute__((__visibility__("hidden"))) and dnl __attribute__((__visibility__("default"))). dnl Does *not* test for __visibility__("protected") - which has tricky dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on dnl MacOS X. dnl Does *not* test for __visibility__("internal") - which has processor dnl dependent semantics. dnl Does *not* test for #pragma GCC visibility push(hidden) - which is dnl "really only recommended for legacy code". dnl Set the variable CFLAG_VISIBILITY. dnl Defines and sets the variable HAVE_VISIBILITY. AC_DEFUN([gl_VISIBILITY], [ AC_REQUIRE([AC_PROG_CC]) CFLAG_VISIBILITY= HAVE_VISIBILITY=0 if test -n "$GCC"; then AC_MSG_CHECKING([for simple visibility declarations]) AC_CACHE_VAL(gl_cv_cc_visibility, [ gl_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fvisibility=hidden" AC_TRY_COMPILE( [extern __attribute__((__visibility__("hidden"))) int hiddenvar; extern __attribute__((__visibility__("default"))) int exportedvar; extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); extern __attribute__((__visibility__("default"))) int exportedfunc (void);], [], gl_cv_cc_visibility=yes, gl_cv_cc_visibility=no) CFLAGS="$gl_save_CFLAGS"]) AC_MSG_RESULT([$gl_cv_cc_visibility]) if test $gl_cv_cc_visibility = yes; then CFLAG_VISIBILITY="-fvisibility=hidden" HAVE_VISIBILITY=1 fi fi AC_SUBST([CFLAG_VISIBILITY]) AC_SUBST([HAVE_VISIBILITY]) AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.]) ]) gnunet-0.10.1/config.guess0000755000175000017500000013036112320752057012341 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-06-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: gnunet-0.10.1/ChangeLog0000644000175000017500000160234112207603742011576 000000000000002013-08-27 16:35 dold * [r28875] src/testing/gnunet-testing.c: removed unnecessary printf again 2013-08-27 15:03 dold * [r28874] src/testing/gnunet-testing.c: consistent output with gnunet-testing-run-service 2013-08-27 14:52 dold * [r28873] src/set/gnunet-service-set_union.c: doxygen typo 2013-08-27 14:42 dold * [r28872] src/testing/gnunet-testing.c: superflous printf 2013-08-27 14:37 dold * [r28871] src/testing/Makefile.am, src/testing/gnunet-testing-run-service.c, src/testing/gnunet-testing.c: merged 'gnunet-testing-run-service' into 'gnunet-testing' 2013-08-27 07:29 tg * [r28869] configure.ac, src/Makefile.am, src/include/gnunet_protocols.h, src/include/gnunet_psycstore_service.h, src/psycstore, src/psycstore/Makefile.am, src/psycstore/gnunet-service-psycstore.c, src/psycstore/psycstore.conf, src/psycstore/psycstore.h, src/psycstore/psycstore_api.c, src/psycstore/test_psycstore.c, src/psycstore/test_psycstore.conf: psycstore service skeleton 2013-08-27 07:29 tg * [r28868] src/identity/identity_api.c: identity: doc fixes 2013-08-27 07:29 tg * [r28867] src/include/gnunet_env_lib.h, src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h: multicast/psyc/psycstore api: fix typos / type names 2013-08-26 12:11 wachs * [r28865] src/integration-tests/confs/c_nat_client.conf, src/integration-tests/confs/c_no_nat_client_2.conf, src/integration-tests/test_integration_connect_on_restart.py.in: more changes to configs 2013-08-26 12:05 wachs * [r28864] src/integration-tests/confs/c_no_nat_client_2.conf, src/integration-tests/hostkeys/c_no_nat_client_2, src/integration-tests/test_integration_clique.py.in: fix second peer for clique test 2013-08-26 12:03 wachs * [r28863] src/integration-tests/test_integration_bootstrap_and_connect.py.in, src/integration-tests/test_integration_bootstrap_and_connect_and_disconnect.py.in, src/integration-tests/test_integration_bootstrap_and_connect_and_disconnect_nat.py.in, src/integration-tests/test_integration_restart.py.in: cleanup service home directories since left overs can break the test 2013-08-26 11:47 wachs * [r28862] src/integration-tests/confs/c_nat_client.conf, src/integration-tests/hostkeys/c_nat_client: fix 2013-08-26 11:41 wachs * [r28861] src/integration-tests/confs/c_bootstrap_server.conf, src/integration-tests/confs/c_no_nat_client.conf, src/integration-tests/hostkeys/c_bootstrap_server, src/integration-tests/hostkeys/c_no_nat_client, src/integration-tests/test_integration_bootstrap_and_connect.py.in: fixing integration tests 2013-08-26 07:59 wachs * [r28860] src/ats/perf_ats_proportional_delay.conf: missing cfg file 2013-08-26 07:45 wachs * [r28859] src/ats/perf_ats_proportional_bandwidth.conf: missing config file 2013-08-24 06:25 tg * [r28833] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: multicast: added replay_end(), returning replay handle from join_decision(); removed admitted/effective since where not needed; social: keep_active flag instead of away 2013-08-23 13:56 cfuchs * [r28822] src/vectorproduct/gnunet_vectorproduct.h, src/vectorproduct/test_vectorproduct_api_regression.c, src/vectorproduct/vectorproduct_testing.h: fixed a couple of doxygen keywords added a missing license-header 2013-08-23 12:33 cfuchs * [r28813] src/vectorproduct/gnunet-service-vectorproduct.c: removed texml-command-backslashes from comments which prodced warnings in doxygen 2013-08-23 12:25 wachs * [r28812] src/ats/perf_ats.c, src/ats/perf_ats_simplistic_bandwidth.conf: quotas + partner evaluation 2013-08-23 12:20 cfuchs * [r28810] configure.ac: added vectorproduct's config- and makefile to configure-automake-template 2013-08-23 12:19 cfuchs * [r28809] src/vectorproduct/Makefile.am: adjusted makefile-template for gnunet-mainline toolchain 2013-08-23 10:01 wachs * [r28808] src/ats/perf_ats.c: partner task 2013-08-23 09:26 wachs * [r28807] src/ats/perf_ats.c: load balancing for partner selection 2013-08-23 07:51 wachs * [r28806] src/core/test_core_api_reliability.c: how did this test ever work without assigning core handles? 2013-08-23 07:36 wachs * [r28805] src/core/test_core_api_peer1.conf, src/core/test_core_api_peer2.conf, src/core/test_core_defaults.conf: fixed core configs 2013-08-23 07:25 wachs * [r28804] src/core/core_api.c: safety checks for arguments 2013-08-22 15:24 wachs * [r28797] src/ats/perf_ats.c: communication done 2013-08-22 14:14 wachs * [r28795] src/ats/perf_ats.c: basic communications 2013-08-22 13:41 cfuchs * [r28794] doc/man/Makefile.am, doc/man/gnunet-vectorproduct.1, po/POTFILES.in, src/Makefile.am, src/include/gnunet_applications.h, src/include/gnunet_protocols.h, src/include/gnunet_vectorproduct_service.h, src/vectorproduct, src/vectorproduct/Makefile.am, src/vectorproduct/gnunet-service-vectorproduct.c, src/vectorproduct/gnunet-vectorproduct.c, src/vectorproduct/gnunet_vectorproduct.h, src/vectorproduct/test_vectorproduct_api.c, src/vectorproduct/test_vectorproduct_api_4peers.c, src/vectorproduct/test_vectorproduct_api_data.conf, src/vectorproduct/test_vectorproduct_api_regression.c, src/vectorproduct/test_vectorproduct_api_regression2.c, src/vectorproduct/vectorproduct.conf.in, src/vectorproduct/vectorproduct_api.c, src/vectorproduct/vectorproduct_testing.h: added vectorproduct protocol definitions added to be localized files to POTFILES added (inactive) changes to the src/Makefile.am added manpage for vectorproduct added apptype for vectorproduct added vectorproduct service, client, API and related sources to SVN 2013-08-22 13:12 wachs * [r28793] src/ats/perf_ats.c: planned end of test 2013-08-22 11:01 LRN * [r28792] contrib/timeout_watchdog_w32.c: Fix the use of s/S field types with ANSI-compliant wprintfs 2013-08-22 09:42 wachs * [r28789] src/gns/gnunet-service-gns_resolver.c: cannot link memrchr on OS X 2013-08-22 08:51 wachs * [r28788] src/namestore/Makefile.am, src/namestore/test_namestore_api_remove.c: test if records are removed correctly 2013-08-22 08:27 wachs * [r28787] src/namestore/plugin_namestore_postgres.c: ported postgres plugin to new API to get it to compile functionality was not adapted 2013-08-22 07:52 wachs * [r28786] src/ats/gnunet-service-ats-solver_proportional.c: remove debugging break 2013-08-22 07:51 wachs * [r28785] src/ats/gnunet-service-ats-solver_proportional.c: simplify to make reader and clang happy 2013-08-21 16:12 wachs * [r28765] src/ats/perf_ats.c: fix for all masters 2013-08-21 16:03 grothoff * [r28764] src/core/core_api.c, src/core/gnunet-core.c, src/core/test_core_api.c, src/core/test_core_api_reliability.c, src/core/test_core_api_send_to_self.c, src/core/test_core_api_start_only.c, src/core/test_core_quota_compliance.c, src/dht/gnunet-service-dht_neighbours.c, src/dv/gnunet-service-dv.c, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/fs/gnunet-service-fs.c, src/hostlist/gnunet-daemon-hostlist.c, src/include/gnunet_core_service.h, src/integration-tests/connection_watchdog.c, src/mesh/gnunet-service-mesh-enc.c, src/mesh/gnunet-service-mesh.c, src/nse/gnunet-service-nse.c, src/testbed/gnunet-service-testbed_cache.c, src/topology/gnunet-daemon-topology.c: removing deprecated argument in 'init' callback of GNUNET_CORE_connect 2013-08-21 15:51 wachs * [r28763] src/ats/Makefile.am: fix typo 2013-08-21 15:46 wachs * [r28760] src/ats/perf_ats.c: latest changes to support multi master 2013-08-21 15:34 grothoff * [r28758] src/core/gnunet-service-core_kx.c, src/fs/fs_publish_ublock.c, src/fs/fs_uri.c, src/fs/test_fs_namespace.c, src/fs/test_fs_namespace_list_updateable.c, src/fs/test_pseudonym.c, src/gns/gnunet-gns-helper-service-w32.c, src/gns/gnunet-gns-proxy.c, src/gns/gnunet-gns.c, src/gns/test_gns_cname_lookup.c, src/gns/test_gns_dht_three_peers.c, src/gns/test_gns_max_queries.c, src/gns/test_gns_ns_lookup.c, src/gns/test_gns_proxy.c, src/gns/test_gns_pseu_shorten.c, src/gns/test_gns_revocation.c, src/gns/test_gns_simple_delegated_lookup.c, src/gns/test_gns_simple_lookup.c, src/gns/test_gns_simple_mx_lookup.c, src/gns/test_gns_simple_shorten.c, src/gns/test_gns_simple_srv_lookup.c, src/gns/test_gns_simple_zkey_lookup.c, src/identity/gnunet-service-identity.c, src/identity/identity_api.c, src/include/gnunet_crypto_lib.h, src/namestore/gnunet-namestore-fcfsd.c, src/namestore/test_namestore_api.c, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_lookup.c, src/namestore/test_namestore_api_lookup_specific_type.c, src/namestore/test_namestore_api_monitoring.c, src/namestore/test_namestore_api_put.c, src/namestore/test_namestore_api_remove.c, src/namestore/test_namestore_api_remove_not_existing_record.c, src/namestore/test_namestore_api_zone_iteration.c, src/namestore/test_namestore_api_zone_iteration_specific_zone.c, src/namestore/test_namestore_api_zone_iteration_stop.c, src/namestore/test_namestore_api_zone_to_name.c, src/nse/gnunet-service-nse.c, src/peerinfo-tool/gnunet-peerinfo.c, src/pt/test_gns_vpn.c, src/regex/gnunet-daemon-regexprofiler.c, src/regex/gnunet-service-regex.c, src/testing/gnunet-testing.c, src/testing/testing.c, src/transport/gnunet-service-transport.c, src/util/crypto_ecc.c, src/util/gnunet-ecc.c, src/util/test_crypto_ecc.c: removing GNUNET_CRYPTO_ecc_key_free, use GNUNET_free directly instead 2013-08-21 15:19 grothoff * [r28754] src/gns/gnunet-dns2gns.c, src/gns/gnunet-service-gns_interceptor.c: document places where SHADOW records likely need to be handled 2013-08-21 15:18 grothoff * [r28753] src/gns/gnunet-service-gns.c: implement conversion to absolute TTL 2013-08-21 15:17 grothoff * [r28751] src/util/container_bloomfilter.c: simplified OR2 API 2013-08-21 15:17 grothoff * [r28750] src/core/Makefile.am, src/core/core_api_is_connected.c, src/core/core_api_iterate_peers.c, src/core/gnunet-service-core_clients.c, src/core/gnunet-service-core_sessions.c, src/core/gnunet-service-core_sessions.h: removing deprecated, dead test-connected API 2013-08-21 14:04 wachs * [r28744] src/ats/perf_ats.c: serialized startup 2013-08-21 12:31 wachs * [r28743] src/ats/perf_ats.c: supporting multi master/slave approach 2013-08-21 11:29 wachs * [r28741] src/ats/Makefile.am: applying new speak: proportional 2013-08-21 09:53 wachs * [r28739] src/namestore/Makefile.am, src/namestore/test_namestore_api_blocks.c, src/namestore/test_namestore_api_sign_verify.c: reorder tests: namestore_common -> plugins -> api block test 2013-08-21 09:46 wachs * [r28738] src/namestore/namestore_api_common.c: fixing memory leak caused by key derivation 2013-08-21 09:38 wachs * [r28737] src/namestore/namestore_api_common.c: missing check 2013-08-21 09:22 wachs * [r28736] src/namestore/test_namestore_api.c: log level 2013-08-21 09:21 wachs * [r28735] src/namestore/test_namestore_api.c: switched test to new api 2013-08-21 09:13 wachs * [r28734] src/namestore/namestore_api.c: fixed crash: wrong cls in api 2013-08-21 08:22 wachs * [r28733] src/namestore/test_plugin_namestore.c: remove docu 2013-08-21 08:15 wachs * [r28732] src/namestore/test_plugin_namestore.c: test compiles again, but fail to get the stored record: in sqlite:get_record_and_call_iterator: if (SQLITE_ROW == (sret = sqlite3_step (stmt))) is false 2013-08-20 14:31 wachs * [r28729] src/transport/plugin_transport_udp.c: check in wrong line 2013-08-20 11:44 wachs * [r28724] src/transport/plugin_transport_udp.c: more clang fixes 2013-08-20 11:33 wachs * [r28723] src/transport/plugin_transport_wlan.c: fix clang report 2013-08-20 11:32 wachs * [r28722] src/transport/gnunet-service-transport_manipulation.c, src/transport/plugin_transport_wlan.c: fixing clang reports 2013-08-20 11:15 wachs * [r28721] src/transport/plugin_transport_udp.c: fixing bugs found by clang 2013-08-20 03:24 LRN * [r28720] src/gns/Makefile.am: Link gns to vpn - always 2013-08-20 03:24 LRN * [r28719] src/gns/gnunet-gns-helper-service-w32.c: Remove short hashes from W32 GNS helper 2013-08-19 19:56 szengel * [r28718] src/regex/regex_internal.c, src/regex/test_regex_iterate_api.c: Fix 'way too many REGEX PUTs' issue. 2013-08-19 16:26 wachs * [r28709] src/transport/test_transport_blacklisting_cfg_blp_peer1_full.conf, src/transport/test_transport_blacklisting_cfg_blp_peer1_multiple_plugins.conf, src/transport/test_transport_blacklisting_cfg_blp_peer1_plugin.conf, src/transport/test_transport_blacklisting_cfg_blp_peer2_full.conf, src/transport/test_transport_blacklisting_cfg_blp_peer2_multiple_plugins.conf, src/transport/test_transport_blacklisting_cfg_blp_peer2_plugin.conf: fixing blacklist: peer ids for blacklisting have changed due to crypto change, so blacklisting did not work 2013-08-19 16:06 wachs * [r28708] src/transport/test_transport_blacklisting_cfg_blp_peer1_full.conf, src/transport/test_transport_blacklisting_cfg_blp_peer2_full.conf: fix peer ids 2013-08-19 15:57 wachs * [r28707] src/transport/test_plugin_transport.c: make test resistant againt duplicate notifications 2013-08-19 15:47 wachs * [r28706] src/nat/nat.conf: fixing mantis 3002 timeouts were off by factor 10 - fixed timeouts - changed default configuration values to fancy strings - intervalls are not corresponding to the default values used internaly in nat.c 2013-08-19 14:13 harsha * [r28705] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_operations.c, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h, src/testbed/testbed_api_statistics.c: fix 2893: Move adaptive parallelisation mechanism to operation queues 2013-08-19 14:03 wachs * [r28704] src/nat/nat.conf: changing to fancy string and from 3 seconds to 30 seconds 2013-08-19 08:27 wachs * [r28702] src/ats/perf_ats.c: fix test result 2013-08-19 08:10 wachs * [r28701] src/transport/gnunet-transport.c: fix logical error to assure buf is never NULL 2013-08-19 08:06 wachs * [r28700] src/nat/gnunet-helper-nat-client.c: printing size to eliminate dead assignment 2013-08-19 07:52 wachs * [r28699] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_blacklist.c, src/transport/gnunet-service-transport_manipulation.c: remove dead assignments 2013-08-19 07:48 wachs * [r28698] src/ats/gnunet-service-ats_addresses.c: dead assignment 2013-08-19 07:47 wachs * [r28697] src/transport/gnunet-helper-transport-wlan-dummy.c, src/transport/gnunet-helper-transport-wlan.c, src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_udp_broadcasting.c, src/transport/plugin_transport_unix.c: remove dead assignments 2013-08-19 07:33 wachs * [r28696] src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats_normalization.c: remove dead assignments 2013-08-19 06:44 tg * [r28695] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: multicast/psyc: added admitted_since arg for join_decision(); social: added nym arg for the method cb 2013-08-18 10:04 tg * [r28691] src/include/gnunet_multicast_service.h: multicast: replay functions, args, callbacks, return codes 2013-08-18 10:04 tg * [r28690] src/include/gnunet_social_service.h: social: place_look args 2013-08-16 04:08 LRN * [r28680] src/ats/perf_ats.c: Fix perf_ats to work on W32 2013-08-16 04:08 LRN * [r28679] src/mesh/Makefile.am: Link mesh tests to mesh lib, duh 2013-08-16 04:08 LRN * [r28678] src/arm/test_exponential_backoff.c: Make exponential backoff test compile again 2013-08-16 04:08 LRN * [r28677] src/gns/gnunet-gns-helper-service-w32.c: Make w32 gns helper compile again 2013-08-16 04:08 LRN * [r28676] src/gns/gnunet-service-gns_resolver.c: Fix the lack of memrchr on W32 2013-08-16 04:08 LRN * [r28675] src/util/w32cat.c: Try to fix a warning 2013-08-16 04:08 LRN * [r28674] configure.ac, src/include/plibc.h: Modernize plibc, use MinGW ANSI STDIO 2013-08-16 04:08 LRN * [r28673] src/arm/test_gnunet_arm.py.in, src/dht/test_dht_tools.py.in, src/fs/test_gnunet_fs_idx.py.in, src/fs/test_gnunet_fs_ns.py.in, src/fs/test_gnunet_fs_psd.py.in, src/fs/test_gnunet_fs_rec.py.in, src/peerinfo-tool/test_gnunet_peerinfo.py.in, src/statistics/test_gnunet_statistics.py.in: Fix invocation of just-built tools 2013-08-15 19:57 tg * [r28671] src/include/gnunet_social_service.h: social: place_enter2 arg fix 2013-08-15 19:20 tg * [r28670] src/include/gnunet_social_service.h: social: place_enter args 2013-08-15 16:43 tg * [r28668] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: multicast/psyc: transmit callbacks; social: password for home_advertise() 2013-08-15 12:17 tg * [r28654] src/include/gnunet_social_service.h: social: home_advertise() - added arg to specify peers for the entry 2013-08-15 11:53 tg * [r28651] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: moved policies from multicast to psyc layer 2013-08-15 10:09 tg * [r28644] src/include/gnunet_social_service.h: social api: use ego from identity service 2013-08-15 10:09 tg * [r28643] src/include/gnunet_env_lib.h, src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: psycstore: added state_hash_update() and counters_get(); psyc: async state_get*(); multicast: membership test & replay params 2013-08-12 21:04 tg * [r28548] src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: psyc/social: slave transmit & guest talk flags 2013-08-12 17:45 tg * [r28544] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: psyc/social: transmit/announcement flags; multicast: re-added sig. purpose 2013-08-12 16:57 tg * [r28543] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: psyc/store: added effective_since msg ID for specifying when a membership change went into effect; psyc/social: added state_reset/clear_objects flag for message sending functions 2013-08-11 23:46 tg * [r28513] src/include/gnunet_env_lib.h, src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: social: use full pubkey as place/nym id; multicast/psyc/store: identify members by their pubkey here too 2013-08-11 21:21 grothoff * [r28501] src/arm/gnunet-arm.c, src/arm/gnunet-service-arm.c, src/arm/test_exponential_backoff.c, src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats_performance.c, src/ats/gnunet-service-ats_reservations.c, src/ats/perf_ats_mlp.c, src/ats/test_ats_api_scheduling_block_and_reset.c, src/ats/test_ats_api_scheduling_init.c, src/core/gnunet-service-core_kx.c, src/core/gnunet-service-core_sessions.c, src/core/test_core_api_reliability.c, src/core/test_core_quota_compliance.c, src/datacache/perf_datacache.c, src/datacache/plugin_datacache_heap.c, src/datacache/plugin_datacache_postgres.c, src/datacache/plugin_datacache_sqlite.c, src/datacache/test_datacache.c, src/datacache/test_datacache_quota.c, src/datastore/datastore_api.c, src/datastore/gnunet-service-datastore.c, src/datastore/perf_datastore_api.c, src/datastore/perf_plugin_datastore.c, src/datastore/plugin_datastore_heap.c, src/datastore/plugin_datastore_mysql.c, src/datastore/plugin_datastore_postgres.c, src/datastore/plugin_datastore_sqlite.c, src/datastore/test_datastore_api.c, src/datastore/test_datastore_api_management.c, src/datastore/test_plugin_datastore.c, src/dht/gnunet-service-dht_clients.c, src/dht/gnunet-service-dht_hello.c, src/dht/gnunet-service-dht_neighbours.c, src/dht/gnunet-service-dht_routing.c, src/dns/dnsparser.c, src/dns/dnsstub.c, src/dns/gnunet-dns-monitor.c, src/dns/plugin_block_dns.c, src/exit/gnunet-daemon-exit.c, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c, src/fragmentation/defragmentation.c, src/fragmentation/fragmentation.c, src/fs/fs_api.c, src/fs/fs_download.c, src/fs/fs_misc.c, src/fs/fs_search.c, src/fs/fs_uri.c, src/fs/gnunet-daemon-fsprofiler.c, src/fs/gnunet-download.c, src/fs/gnunet-fs-profiler.c, src/fs/gnunet-search.c, src/fs/gnunet-service-fs.c, src/fs/gnunet-service-fs_cp.c, src/fs/gnunet-service-fs_pe.c, src/fs/gnunet-service-fs_pr.c, src/fs/gnunet-service-fs_push.c, src/fs/perf_gnunet_service_fs_p2p.c, src/fs/perf_gnunet_service_fs_p2p_respect.c, src/fs/test_fs_download.c, src/fs/test_fs_download_persistence.c, src/fs/test_fs_list_indexed.c, src/fs/test_fs_publish.c, src/fs/test_fs_publish_persistence.c, src/fs/test_fs_unindex.c, src/fs/test_fs_unindex_persistence.c, src/fs/test_gnunet_service_fs_migration.c, src/fs/test_gnunet_service_fs_p2p.c, src/gns/gnunet-dns2gns.c, src/gns/gnunet-gns-fcfsd.c, src/gns/gnunet-gns-proxy.c, src/gns/gnunet-service-gns.c, src/gns/gnunet-service-gns_interceptor.c, src/gns/gnunet-service-gns_resolver.c, src/gns/plugin_block_gns.c, src/gns/test_gns_dht_three_peers.c, src/gns/test_gns_proxy.c, src/gns/test_gns_pseu_shorten.c, src/gns/test_gns_simple_delegated_lookup.c, src/gns/test_gns_simple_mx_lookup.c, src/gns/test_gns_simple_srv_lookup.c, src/hello/hello.c, src/hostlist/hostlist-client.c, src/hostlist/hostlist-server.c, src/identity/identity_api.c, src/include/gnunet_ats_service.h, src/include/gnunet_client_lib.h, src/include/gnunet_resolver_service.h, src/include/gnunet_scheduler_lib.h, src/include/gnunet_server_lib.h, src/include/gnunet_time_lib.h, src/mesh/gnunet-service-mesh-enc.c, src/mesh/gnunet-service-mesh.c, src/mesh/mesh_api.c, src/mesh/mesh_api_enc.c, src/mesh/test_mesh_small.c, src/namestore/gnunet-namestore.c, src/namestore/gnunet-service-namestore.c, src/namestore/namestore_api_common.c, src/namestore/plugin_namestore_postgres.c, src/namestore/plugin_namestore_sqlite.c, src/namestore/test_namestore_api.c, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_lookup.c, src/namestore/test_namestore_api_lookup_specific_type.c, src/namestore/test_namestore_api_monitoring.c, src/namestore/test_namestore_api_put.c, src/namestore/test_namestore_api_remove.c, src/namestore/test_namestore_api_remove_not_existing_record.c, src/namestore/test_namestore_api_sign_verify.c, src/namestore/test_namestore_api_zone_iteration.c, src/namestore/test_namestore_api_zone_iteration_specific_zone.c, src/namestore/test_namestore_api_zone_iteration_stop.c, src/namestore/test_namestore_api_zone_to_name.c, src/namestore/test_plugin_namestore.c, src/nse/gnunet-nse-profiler.c, src/nse/gnunet-service-nse.c, src/nse/nse_api.c, src/nse/perf_kdf.c, src/peerinfo/gnunet-service-peerinfo.c, src/pt/test_gns_vpn.c, src/regex/gnunet-daemon-regexprofiler.c, src/regex/plugin_block_regex.c, src/sysmon/gnunet-service-sysmon.c, src/testbed/gnunet-service-testbed_cpustatus.c, src/testbed/testbed_api_hosts.c, src/topology/gnunet-daemon-topology.c, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_validation.c, src/transport/gnunet-transport.c, src/transport/plugin_transport_bluetooth.c, src/transport/plugin_transport_http.c, src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c, src/transport/test_quota_compliance.c, src/transport/test_transport_api_manipulation_cfg.c, src/transport/test_transport_api_manipulation_recv_tcp.c, src/transport/test_transport_api_manipulation_send_tcp.c, src/transport/test_transport_api_reliability.c, src/transport/test_transport_api_timeout.c, src/transport/test_transport_api_unreliability.c, src/transport/test_transport_api_unreliability_constant.c, src/transport/transport_api.c, src/util/bandwidth.c, src/util/client.c, src/util/common_logging.c, src/util/connection.c, src/util/gnunet-service-resolver.c, src/util/load.c, src/util/network.c, src/util/perf_crypto_hash.c, src/util/perf_malloc.c, src/util/resolver_api.c, src/util/scheduler.c, src/util/server.c, src/util/speedup.c, src/util/strings.c, src/util/test_common_logging_dummy.c, src/util/test_crypto_ecc.c, src/util/test_scheduler_delay.c, src/util/test_speedup.c, src/util/test_strings.c, src/util/test_time.c, src/util/time.c, src/vpn/gnunet-service-vpn.c: changing time measurement from milliseconds to microseconds 2013-08-08 15:34 wachs * [r28475] src/ats/perf_ats.c: number for peers 2013-08-08 13:36 wachs * [r28469] src/transport/plugin_transport_tcp.c: remove output 2013-08-08 13:24 wachs * [r28468] src/util/resolver_api.c: fix for resolver timeout issues 2013-08-08 12:16 wachs * [r28466] src/transport/plugin_transport_tcp.c: debugging messages due to mantis bug 2980 2013-08-08 09:53 wachs * [r28462] src/core/gnunet-service-core_kx.c: improved messages 2013-08-08 09:53 wachs * [r28461] src/transport/gnunet-service-transport_neighbours.c: improved messages 2013-08-08 09:13 wachs * [r28459] contrib/hellos/CDTU8QQ8UPLGHR3B91V0CLTDOHONLB8QGHGUEM2JM1GANTEV0O6T20SD2N2HDN2QSHDG6IDTBR48KRDCS601FI6VHG59E7DQA98JD2O, contrib/hellos/HIJN5O404QNUR37OSJUTNJ6H2KJS198DHI2J3I8SE3DMKVRG1RNQPODN1IJBF14KEMPPPRM0B9F9ILFKHOFCA655CH6M5OCNCMR0FE0: valid hellos for gnunet9 and fulcrum 2013-08-08 08:54 wachs * [r28458] src/transport/gnunet-service-transport_clients.c: added warning for self connect 2013-08-08 08:50 wachs * [r28457] src/transport/gnunet-service-transport.c: more info 2013-08-08 08:44 wachs * [r28456] contrib/hellos/M2D1DU1TBUNFTTJ19D7D2MVIILK6E9BIBUNPFS0TIVCP6TD27MJDVDU40CKKJLCJEFKFD5KTD5VO4BUC40U2S7N99KT0CUCBOBU3UMG: invalid for gnunet9 2013-08-08 08:43 wachs * [r28455] contrib/hellos/SLOSLEH4PLO4GN2BVVJIFPIGVL38L9QKTEIJ6D4UE2FAVNAD3QMVCC1330N4OGLK516T3I8TU5EE4L4AARIN405UMD8PSEI3JULB7N0: this hello causes self-connects 2013-08-08 07:58 wachs * [r28454] src/transport/plugin_transport_tcp.c: added error message 2013-08-07 10:08 wachs * [r28436] contrib/hellos/M2D1DU1TBUNFTTJ19D7D2MVIILK6E9BIBUNPFS0TIVCP6TD27MJDVDU40CKKJLCJEFKFD5KTD5VO4BUC40U2S7N99KT0CUCBOBU3UMG, contrib/hellos/SLOSLEH4PLO4GN2BVVJIFPIGVL38L9QKTEIJ6D4UE2FAVNAD3QMVCC1330N4OGLK516T3I8TU5EE4L4AARIN405UMD8PSEI3JULB7N0: new hellos for fulcrum and gnunet9 2013-08-07 10:04 wachs * [r28435] src/transport/gnunet-service-transport_validation.c: error message instead of assertion 2013-08-07 09:45 wachs * [r28434] src/hello/gnunet-hello.c: some output 2013-08-07 08:09 wachs * [r28429] src/ats/Makefile.am: core missing for one test 2013-08-06 14:56 wachs * [r28421] src/ats/perf_ats.c: ready to start with benchmarkign implementation 2013-08-06 14:38 wachs * [r28420] src/ats/Makefile.am, src/ats/perf_ats.c: core connections 2013-08-06 14:18 grothoff * [r28414] contrib/Makefile.am, src/Makefile.am, src/core/gnunet-service-core_kx.c, src/dht/gnunet-service-dht_neighbours.c, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/fs/fs_api.h, src/fs/fs_pseudonym.c, src/fs/fs_publish_ksk.c, src/fs/fs_uri.c, src/fs/test_fs_defaults.conf, src/gns/gns.h, src/gns/gns_api.c, src/gns/gnunet-gns-fcfsd.c, src/gns/gnunet-gns-helper-service-w32.c, src/gns/gnunet-gns-proxy.c, src/gns/gnunet-gns.c, src/gns/gnunet-service-gns.c, src/gns/gnunet-service-gns_resolver.c, src/gns/plugin_block_gns.c, src/gns/test_gns_cname_lookup.c, src/gns/test_gns_dht_delegated_lookup.c, src/gns/test_gns_dht_three_peers.c, src/gns/test_gns_max_queries.c, src/gns/test_gns_ns_lookup.c, src/gns/test_gns_pseu_shorten.c, src/gns/test_gns_revocation.c, src/gns/test_gns_simple_delegated_lookup.c, src/gns/test_gns_simple_get_authority.c, src/gns/test_gns_simple_lookup.c, src/gns/test_gns_simple_mx_lookup.c, src/gns/test_gns_simple_shorten.c, src/gns/test_gns_simple_srv_lookup.c, src/gns/test_gns_simple_zkey_lookup.c, src/hello/gnunet-hello.c, src/hello/hello.c, src/hello/test_friend_hello.c, src/hello/test_hello.c, src/identity/gnunet-service-identity.c, src/identity/identity.h, src/identity/identity_api.c, src/include/block_dns.h, src/include/block_gns.h, src/include/block_regex.h, src/include/gnunet_chat_service.h, src/include/gnunet_crypto_lib.h, src/include/gnunet_fs_service.h, src/include/gnunet_hello_lib.h, src/include/gnunet_identity_service.h, src/include/gnunet_namestore_plugin.h, src/include/gnunet_namestore_service.h, src/include/gnunet_testing_lib.h, src/mesh/gnunet-service-mesh-enc.c, src/mesh/gnunet-service-mesh.c, src/namestore/gnunet-namestore.c, src/namestore/gnunet-service-namestore.c, src/namestore/namestore.h, src/namestore/namestore_api.c, src/namestore/plugin_namestore_postgres.c, src/namestore/plugin_namestore_sqlite.c, src/namestore/test_namestore_api.c, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_lookup.c, src/namestore/test_namestore_api_lookup_specific_type.c, src/namestore/test_namestore_api_monitoring.c, src/namestore/test_namestore_api_put.c, src/namestore/test_namestore_api_remove.c, src/namestore/test_namestore_api_remove_not_existing_record.c, src/namestore/test_namestore_api_sign_verify.c, src/namestore/test_namestore_api_zone_iteration.c, src/namestore/test_namestore_api_zone_iteration_specific_zone.c, src/namestore/test_namestore_api_zone_iteration_stop.c, src/namestore/test_namestore_api_zone_to_name.c, src/namestore/test_plugin_namestore.c, src/nse/gnunet-service-nse.c, src/peerinfo-tool/gnunet-peerinfo.c, src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/perf_peerinfo_api.c, src/peerinfo/test_peerinfo_api.c, src/peerinfo/test_peerinfo_api_friend_only.c, src/peerinfo/test_peerinfo_api_notify_friend_only.c, src/regex/regex_internal_dht.c, src/testing/gnunet-testing.c, src/testing/testing.c, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport.h, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_validation.c, src/transport/gnunet-service-transport_validation.h, src/transport/test_plugin_transport.c, src/util/crypto_ecc.c, src/util/gnunet-ecc.c, src/util/test_crypto_ecc.c: moving to new, fixed-size encoding of public and private ECC keys everywhere, also improving ECC API to better support ECRS/GADS operations 2013-08-06 13:47 wachs * [r28413] src/ats/perf_ats.c: peers are connecting 2013-08-06 10:31 wachs * [r28412] src/ats/perf_ats.c: connects only with valgrind?! 2013-08-06 10:15 wachs * [r28411] src/ats/perf_ats.c: connecting 2013-08-06 10:12 wachs * [r28410] src/ats/perf_ats.c: changes to perf_ats 2013-08-06 09:00 wachs * [r28409] src/ats/perf_ats.c: initialization with ats 2013-08-06 07:57 wachs * [r28408] src/ats/perf_ats.c: variable number of peer 2013-08-05 15:02 wachs * [r28405] src/ats/Makefile.am, src/ats/perf_ats.c: intermediate commit 2013-08-05 14:26 wachs * [r28404] src/ats/Makefile.am, src/ats/perf_ats.c, src/ats/perf_ats_simplistic_bandwidth.conf, src/ats/perf_ats_simplistic_delay.conf: add testbed disable all connections in conf 2013-08-05 13:32 wachs * [r28398] src/ats/Makefile.am, src/ats/perf_ats.c, src/ats/perf_ats_simplistic_bandwidth.conf, src/ats/perf_ats_simplistic_delay.conf: confs and makefile 2013-08-05 12:49 wachs * [r28397] src/ats/Makefile.am, src/ats/perf_ats.c: basics for generic ats benchmark 2013-08-05 12:38 wachs * [r28396] src/ats/perf_ats_mlp.c: duplicate header 2013-08-04 18:43 claudiu * [r28390] src/transport/plugin_transport_bluetooth.c: Fixing the comments 2013-08-04 18:37 claudiu * [r28389] src/transport/gnunet-helper-transport-bluetooth.c: Fixing the comments 2013-08-04 18:19 claudiu * [r28388] src/transport/Makefile.am, src/transport/gnunet-helper-transport-bluetooth.c, src/transport/plugin_transport_bluetooth.c, src/transport/test_quota_compliance_bluetooth_asymmetric_peer1.conf, src/transport/test_quota_compliance_bluetooth_asymmetric_peer2.conf, src/transport/test_quota_compliance_bluetooth_peer1.conf, src/transport/test_quota_compliance_bluetooth_peer2.conf, src/transport/test_transport_api_bluetooth_peer1.conf, src/transport/test_transport_api_bluetooth_peer2.conf, src/transport/test_transport_api_reliability_bluetooth_peer1.conf, src/transport/test_transport_api_reliability_bluetooth_peer2.conf, src/transport/test_transport_api_unreliability_bluetooth_peer1.conf, src/transport/test_transport_api_unreliability_bluetooth_peer2.conf: Extending the testcases to use bluetooth 2013-08-02 13:56 wachs * [r28381] src/transport/plugin_transport_http_server.c: fix for crash on buildbots 2013-08-02 12:40 wachs * [r28380] src/include/gnunet_transport_plugin.h: fixed doxygen documentation 2013-08-02 11:59 wachs * [r28378] src/experimentation/test_experimentation_clique.conf: no valgrind 2013-08-01 15:26 wachs * [r28356] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_capabilities.c, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c, src/experimentation/test_experimentation_clique_run.c: fixed stat counters reduced logging 2013-08-01 14:49 wachs * [r28355] src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c, src/experimentation/test_experimentation_clique_run.c: fixes for list queues 2013-08-01 14:39 wachs * [r28354] src/experimentation/gnunet-daemon-experimentation_nodes.c: fixes 2013-08-01 14:36 wachs * [r28353] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c, src/experimentation/test_experimentation_clique.conf: new unified communication mechanism 2013-08-01 12:25 wachs * [r28350] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c: changes to scheduler 2013-08-01 09:55 wachs * [r28348] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_nodes.c: message parsing on receive 2013-08-01 08:51 wachs * [r28346] src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_capabilities.c, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c: renaming stats and cfg 2013-08-01 08:50 wachs * [r28345] src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_capabilities.c, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c, src/experimentation/gnunet-daemon-experimentation_storage.c: refactoring since names are too long 2013-08-01 08:14 wachs * [r28344] src/experimentation/gnunet-daemon-experimentation_scheduler.c: docu and additional queue 2013-08-01 07:52 wachs * [r28342] src/experimentation/Makefile.am, src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c, src/experimentation/test_experimentation_clique_run.c, src/include/gnunet_protocols.h: changes for experimentation 2013-07-30 12:22 wachs * [r28337] src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c: updated code 2013-07-29 03:50 tg * [r28334] src/include/gnunet_multicast_service.h: multicast: no state_delta 2013-07-28 19:57 tg * [r28333] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h: multicast/psyc: join cb for members/slaves too 2013-07-28 19:30 tg * [r28332] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: multicast: additional args for member_start, origin_start, origin_to_all; social: use private key struct instead of file 2013-07-28 11:11 claudiu * [r28329] src/transport/gnunet-helper-transport-bluetooth.c, src/transport/plugin_transport_bluetooth.c: Implementing broadcast functionality; Resolving the 'security block' errors; Handling select and send errors 2013-07-26 12:56 tg * [r28327] src/include/gnunet_social_service.h: social: home_leave() 2013-07-26 12:56 tg * [r28326] src/include/gnunet_psycstore_service.h: psycstore: state_modify() 2013-07-26 12:56 tg * [r28325] src/include/gnunet_psyc_service.h: psyc: use relays for join decision in this api too 2013-07-25 14:13 durner * [r28323] src/transport/gnunet-service-transport_manipulation.c: fix 2013-07-25 13:45 tg * [r28320] src/include/gnunet_env_lib.h, src/include/gnunet_multicast_service.h: multicast: message_cb and last_fragment_id for origin_start(); env lib: indicating state reset 2013-07-24 14:50 wachs * [r28311] src/gns/gns_common.c, src/gns/gnunet-service-gns.c, src/namestore/gnunet-service-namestore.c: RFC new gns publishing 2013-07-24 14:03 dold * [r28307] src/dv/gnunet-service-dv.c: strange typo in dv 2013-07-23 20:15 claudiu * [r28282] src/transport/gnunet-helper-transport-bluetooth.c: skiping the broadcast messages 2013-07-23 14:32 bartpolot * [r28271] src/include/gnunet_mesh_service_enc.h, src/include/gnunet_protocols.h, src/mesh/mesh_api_enc.c: Change MESH API to use Tunnel to use Channel 2013-07-23 05:38 tg * [r28262] src/include/gnunet_multicast_service.h: multicast: group_member_remove() 2013-07-23 05:38 tg * [r28261] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h: multicast/psyc: no part cb needed 2013-07-23 05:38 tg * [r28260] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h: multicast/psyc: use start/stop naming for master/origin 2013-07-23 05:38 tg * [r28259] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: untabify 2013-07-22 07:18 grothoff * [r28232] src/include/gnunet_tun_lib.h, src/tun/regex.c, src/tun/test_regex.c, src/vpn/gnunet-service-vpn.c: rename GNUNET_TUN_ipvXtoregex to GNUNET_TUN_ipvXtoregexsearch to clarify that this is for generating the search strings 2013-07-21 12:51 claudiu * [r28223] src/transport/plugin_transport_bluetooth.c: Fixing the function called to convert a string address to a binary address 2013-07-19 16:48 claudiu * [r28205] src/transport/gnunet-helper-transport-bluetooth.c: Fixed some bugs 2013-07-19 13:55 claudiu * [r28200] src/transport/Makefile.am: Fixing dependencies for bluetooth plugin 2013-07-18 14:37 wachs * [r28171] src/transport/gnunet-service-transport_validation.c: uninitialized variable 2013-07-18 13:51 wachs * [r28169] src/transport/gnunet-service-transport_plugins.c: const was discarded 2013-07-18 07:03 wachs * [r28132] src/transport/plugin_transport_unix.c: memory leak 2013-07-18 07:01 wachs * [r28131] src/transport/gnunet-service-transport_plugins.c: bug fix 2013-07-17 13:43 tg * [r28121] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: PSYC/multicast: message parameters for join/part requests 2013-07-17 07:12 wachs * [r28102] src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c: removing breaks, adding stats 2013-07-17 07:03 wachs * [r28101] src/gns/gnunet-gns-proxy.c: broken build 2013-07-16 19:08 tg * [r28098] src/include/gnunet_social_service.h: social: finish callback for history lesson 2013-07-16 12:49 bartpolot * [r28091] src/mesh/mesh_api.c: debug tunnel destroy 2013-07-16 11:21 bartpolot * [r28086] configure.ac, src/Makefile.am, src/consensus/Makefile.am, src/fs/test_fs_defaults.conf, src/include/Makefile.am, src/set/Makefile.am, src/stream: Remove stream 2013-07-16 08:42 tg * [r28081] configure.ac, doc/doxygen, doc/doxygen/Makefile.am, doc/doxygen/gnunet.doxy: local doxygen 2013-07-16 08:42 tg * [r28080] src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: psyc/social docs 2013-07-16 08:40 grothoff * [r28079] doc/man/Makefile.am, doc/man/gnunet-identity.1, src/identity/gnunet-identity.c, src/identity/gnunet-service-identity.c, src/include/gnunet_disk_lib.h: initial version of gnunet-identity command-line tool 2013-07-15 23:00 bartpolot * [r28070] src/mesh/gnunet-service-mesh.c: - debug 2013-07-15 19:05 bartpolot * [r28057] src/mesh/gnunet-service-mesh.c: Refactored code to eliminate duplicates depending on FWD/BCK traffic 2013-07-15 12:22 bartpolot * [r28046] src/include/gnunet_mesh_service.h, src/mesh/mesh.h, src/mesh/mesh_api.c: Change get_info API 2013-07-15 09:57 wachs * [r28040] src/transport/plugin_transport_udp.c: udp returned addresses with 0-port 2013-07-15 09:22 wachs * [r28039] src/transport/gnunet-service-transport_plugins.c: improved printing 2013-07-15 09:22 wachs * [r28038] src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c: while running transport: valgrind showed memory leak due to not removed resolution processes storing pretty printer requests and removing them after timeout 2013-07-15 09:13 tg * [r28037] src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: PSYC: historic message flag 2013-07-15 08:43 wachs * [r28036] src/ats-tool/gnunet-ats.c: do not use forever 2013-07-15 08:27 tg * [r28035] src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: social: use the TransmitReadyNotify callback from the connection lib for transmissions 2013-07-15 07:54 tg * [r28034] src/include/gnunet_psyc_service.h: PSYC: move history & state functions to the common channel API 2013-07-15 07:54 tg * [r28033] src/include/gnunet_env_lib.h, src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: env: doc; spaces 2013-07-15 07:25 tg * [r28032] src/include/gnunet_env_lib.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: PSYC API: use master/slave/channel terminology 2013-07-15 07:25 tg * [r28031] src/include/gnunet_env_lib.h, src/include/gnunet_psyc_lib.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: PSYC/social: use an Environment for setting variables / state operations 2013-07-15 07:25 tg * [r28030] src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h: psyc(store): group generation only needed when storing the message 2013-07-15 07:25 tg * [r28029] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: multicast: message fragmentation 2013-07-15 07:25 tg * [r28028] src/include/gnunet_psyc_service.h: psyc api: no state events, those are handled in social 2013-07-15 07:25 tg * [r28027] src/include/gnunet_gns_service.h, src/include/gnunet_namestore_service.h: PLACE record type for gns & namestore 2013-07-14 11:25 claudiu * [r28008] src/transport/transport.conf.in: Integrating bluetooth in the configuration file 2013-07-14 11:05 claudiu * [r28007] configure.ac, src/transport/Makefile.am: Integrating bluetooth plugin 2013-07-13 15:00 bartpolot * [r27995] src/mesh/gnunet-service-mesh.c: dont skip when mid > traget 2013-07-13 14:58 claudiu * [r27994] src/transport/gnunet-helper-transport-bluetooth.c, src/transport/install-bluetooth-helper.sh, src/transport/plugin_transport_bluetooth.c: Adding a copy of wlan plugin used for bluetooth plugin 2013-07-13 14:54 bartpolot * [r27993] src/mesh/gnunet-service-mesh.c: fixes 2013-07-13 12:09 bartpolot * [r27992] src/mesh/gnunet-service-mesh.c: fixes. lunch break 2013-07-13 01:20 bartpolot * [r27972] src/mesh/gnunet-service-mesh.c: Add context to a client immediately after connection. Otherwise calling SERVER_get_client_context on a client that never sent an initial message (and didn't have a chance to receive something via SERVER_set_client_context) causes an assertion failure in server.c:355. This happens when the client can connect to the service on multiple protocols, one of the connections will be immediately closed (see bug for ghost client disconnects) 2013-07-12 15:27 wachs * [r27965] contrib/hellos/A6HJ4F4TT4OLRDBPMGJ7527JQJS1C1TPQTIHI7PCE6MD37K0GSB2U3UTP9I4JJ6C1SD2RIADU04DLM9K6QDG8IH3TU98DJ11GA8L0F8, contrib/hellos/TFRM29O2RQNKLVBQIGODJ6GD58LSQ2NM9TNFBC6N48BRJHQO38Q73N2OM3V4CLKDM6CILQV4CU8PMJDRG0FNB0PDI057DBRANMLPLRG: new hellos 2013-07-12 15:04 wachs * [r27964] src/transport/plugin_transport_template.c: template update 2013-07-12 14:56 wachs * [r27963] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_plugins.c, src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c: using inbound string 2013-07-12 14:55 wachs * [r27962] src/include/gnunet_transport_plugin.h: String to print inbound connections 2013-07-12 14:45 wachs * [r27961] src/transport/plugin_transport_udp.c: fixing crash 2013-07-12 14:42 wachs * [r27960] src/transport/gnunet-service-transport_validation.c: unused variable 2013-07-12 14:15 wachs * [r27959] src/transport/plugin_transport_udp.c: important check 2013-07-12 13:46 wachs * [r27957] src/peerinfo-tool/gnunet-peerinfo.c: fix 2013-07-12 13:43 wachs * [r27956] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_http_server.c: fix if plugin is loaded only in stub mode 2013-07-12 13:28 wachs * [r27955] src/hello/hello.c: automatically replace all server addresses with client addresses 2013-07-12 13:04 wachs * [r27954] src/peerinfo-tool/gnunet-peerinfo_plugins.c: substring search is the root of all evil: peerinfo did load wrong plugin if substring matches: used https for http address 2013-07-12 09:43 tg * [r27951] src/include/gnunet_psyc_lib.h, src/include/gnunet_psyc_service.h, src/include/gnunet_social_service.h: PSYC/social: header for method callbacks 2013-07-12 09:15 wachs * [r27950] src/peerinfo-tool/gnunet-peerinfo.c: fix state machine 2013-07-12 08:58 wachs * [r27949] src/transport/gnunet-service-transport_validation.c: disabling error level message, adding stats instead 2013-07-12 08:51 wachs * [r27947] src/transport/gnunet-service-transport_validation.c: fixed address validation for plugins with client server architecture 2013-07-12 08:50 wachs * [r27946] src/transport/plugin_transport_http_server.c: verified and improved address checking for external hostname and verify option 2013-07-12 08:47 tg * [r27945] AUTHORS, src/include/gnunet_crypto_lib.h, src/include/gnunet_multicast_service.h, src/include/gnunet_protocols.h, src/include/gnunet_psyc_lib.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: PSYC APIs: added missing args and functions, more consistent naming - multicast: origin arg for join; s/leave/part/g - psyc: origin arg for join; join/part callbacks - social: enter2, home_advertise, away - psycstore/social: get latest historic message using ID 0 - added PSYC lib 2013-07-11 19:01 dold * [r27939] src/util/test_mq_client.c: fixed test case 2013-07-11 16:03 wachs * [r27936] src/transport/gnunet-service-transport_validation.c, src/transport/plugin_transport_http_server.c: enabling address check in validation 2013-07-11 15:24 wachs * [r27933] src/ats/gnunet-service-ats_addresses.c: improved network switching 2013-07-11 15:04 wachs * [r27929] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport.h: notify ATS about a session (used for for validation) if we receive payload from a remote peer on this session 2013-07-11 14:44 wachs * [r27927] src/ats/ats_api_scheduling.c, src/include/gnunet_ats_service.h: new function to check if session is known to ats required for two reasons: we cannot update metrics for validation sessions since these are not known to ats a remote peer can decide to use an inbound validation session to transmit data, so we have to add the session to ats if we receive payload on a session 2013-07-11 14:30 bartpolot * [r27925] src/mesh/gnunet-service-mesh.c: Finishing mesh reliable: - per-tunnel retransmission, always retransmit oldest not-ACK'd message - adaptive retransmission delay -- start with 1s -- use per-message timing to update expected delay on each ACK as d = avg (d, new) -- update pending retransmissions with new values 2013-07-11 14:03 wachs * [r27924] src/transport/test_transport_api_bidirectional_connect.c: log level 2013-07-11 13:50 wachs * [r27923] src/transport/plugin_transport_unix.c: removing unwanted break 2013-07-11 13:49 wachs * [r27922] src/transport/gnunet-service-transport.c: removing general address adding 2013-07-11 13:48 wachs * [r27921] src/transport/plugin_transport_http_common.c: printing inbound addresses 2013-07-11 13:48 wachs * [r27920] src/transport/plugin_transport_http_client.c: adding debug message 2013-07-11 13:48 wachs * [r27919] src/transport/plugin_transport_http_server.c: fixed: inbound address size reporting inbound sessions 2013-07-11 12:56 wachs * [r27917] src/transport/plugin_transport_wlan.c: notification for inbound sessions 2013-07-11 12:34 wachs * [r27914] src/transport/plugin_transport_wlan.c: fix: wrong address length 2013-07-11 12:06 wachs * [r27912] src/transport/plugin_transport_udp.c: fixed: printing of inbound session size of inbound sessions 2013-07-11 11:35 wachs * [r27906] src/ats/ats.conf.in: added bt quota 2013-07-11 11:29 wachs * [r27905] src/transport/plugin_transport_unix.c: fixed: - printing inbound connections - lookup for existing sessions - notifying transport with session_start only for inbound sessions 2013-07-11 09:37 wachs * [r27902] src/transport/plugin_transport_tcp.c: fix: return address length 0 for inbound session - return session only if inbound flag is set: issue because plugin sends TCP_WELCOME messages for incoming connections not only outbount 2013-07-11 09:15 wachs * [r27901] src/transport/gnunet-service-transport_plugins.c: fix for printing 2013-07-11 07:47 wachs * [r27900] src/include/gnunet_ats_service.h: remove , 2013-07-11 07:24 wachs * [r27899] src/ats/perf_ats_mlp.c: fixing uninitialized values 2013-07-11 07:03 wachs * [r27898] src/include/gnunet_ats_service.h: fix for header 2013-07-10 12:45 wachs * [r27880] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c: session report in http server 2013-07-10 12:34 wachs * [r27877] src/transport/plugin_transport_udp.c: report session 2013-07-10 12:20 wachs * [r27875] src/transport/gnunet-service-transport.c: unkown session reporting 2013-07-10 12:20 wachs * [r27874] src/ats/ats_api_scheduling.c: move error reporting to client, since now it's the plugins fault if sessions are unknown 2013-07-10 12:01 wachs * [r27872] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_validation.c: modified validation to use new api call to set networktype 2013-07-10 10:33 wachs * [r27868] src/peerinfo-tool/gnunet-peerinfo.c: fix: infinite loop if option was given 2013-07-10 10:24 wachs * [r27867] src/peerinfo-tool/gnunet-peerinfo.c: add default operation when no argument is given 2013-07-10 10:19 wachs * [r27866] src/peerinfo-tool/gnunet-peerinfo.c: including expiration time in output 2013-07-10 08:55 wachs * [r27865] src/transport/gnunet-service-transport.h: renaming function 2013-07-10 08:53 wachs * [r27864] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport.h, src/transport/gnunet-service-transport_neighbours.c: move add function directly to transport 2013-07-10 08:24 wachs * [r27863] src/transport/gnunet-service-transport_neighbours.c: code deduplication: move to function 2013-07-10 07:59 wachs * [r27862] src/transport/gnunet-service-transport_plugins.c: check implementation of api while loading plugn 2013-07-10 07:48 wachs * [r27861] src/include/gnunet_transport_plugin.h, src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_template.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c: changed return type to enum added get_network to template 2013-07-09 20:12 grothoff * [r27841] src/include/gnunet_multicast_service.h: rename 'leave' to 'part' as 'part' is the better opposite of 'join' 2013-07-09 15:40 wachs * [r27840] src/transport/gnunet-service-transport_neighbours.c: adding addresses with network 2013-07-09 15:39 wachs * [r27839] src/transport/gnunet-service-transport.c: this add should not be required anymore 2013-07-09 15:39 wachs * [r27838] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c: get function implementation in all plugins 2013-07-09 15:28 wachs * [r27837] src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c: added function 2013-07-09 15:23 wachs * [r27836] src/include/gnunet_transport_plugin.h, src/transport/gnunet-service-transport_neighbours.c, src/transport/plugin_transport_tcp.c: new api function to get network for session 2013-07-09 14:44 wachs * [r27834] src/ats/gnunet-service-ats_addresses.c: do not add or update if sessions are equal 2013-07-09 14:33 wachs * [r27831] src/ats/gnunet-service-ats_addresses.c: fixed adding addresses with updated networks 2013-07-09 14:19 wachs * [r27830] src/include/gnunet_transport_plugin.h: missing file 2013-07-09 13:26 grothoff * [r27828] src/namestore/gnunet-service-namestore.c: finish implementation of monitoring, send change notifications to all clients 2013-07-09 13:19 wachs * [r27827] src/peerinfo/gnunet-service-peerinfo.c: if io is enabled and shipped hellos not, hellos from peers we created should still be read 2013-07-09 12:40 wachs * [r27826] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_plugins.c, src/transport/gnunet-service-transport_plugins.h: new function for plugins to signal inbound session, have to extend plugins 2013-07-09 11:23 wachs * [r27824] src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/peerinfo.conf.in: functionality to disable shipped hellos 2013-07-09 11:23 wachs * [r27823] src/transport/plugin_transport_tcp.c: better just a warning 2013-07-09 11:22 wachs * [r27822] src/transport/template_cfg_peer1.conf, src/transport/template_cfg_peer2.conf: do not use hellos included in gnunet with testcases 2013-07-09 09:27 wachs * [r27820] src/ats-tool/gnunet-ats.c: fixing output + additional peer id check 2013-07-09 09:23 wachs * [r27819] src/ats-tool/gnunet-ats.c: fixing ats-tool output 2013-07-09 09:21 wachs * [r27818] src/ats-tool/gnunet-ats.c: fix segfault on missing type 2013-07-09 07:18 grothoff * [r27810] doc/man/gnunet-namestore.1, src/include/gnunet_namestore_service.h, src/include/gnunet_protocols.h, src/namestore/gnunet-namestore.c, src/namestore/namestore_api_monitor.c: add '-m' option to gnunet-namestore, extend namestore monitor API with notification about being in sync 2013-07-08 16:57 claudiu * [r27801] src/transport/gnunet-helper-transport-bluetooth.c: Implementing SDP protocol 2013-07-08 11:04 bartpolot * [r27784] src/fs/gnunet-service-fs_mesh.c, src/include/gnunet_mesh_service.h, src/include/gnunet_protocols.h, src/mesh/gnunet-service-mesh.c, src/mesh/mesh.h, src/mesh/mesh_api.c, src/mesh/mesh_protocol.h, src/pt/gnunet-daemon-pt.c, src/set/gnunet-service-set.c, src/stream/stream_api.c, src/util/peer.c, src/vpn/gnunet-service-vpn.c: Added mesh reliable tunnels 2013-07-08 07:16 wachs * [r27782] src/transport/test_transport_api_bidirectional_connect.c: removing debugging breaks 2013-07-07 13:43 claudiu * [r27778] src/transport/gnunet-helper-transport-bluetooth.c: Adding a helper file for bluetooth plugin : gnunet-helper-transport-bluetooth.c 2013-07-07 00:20 dold * [r27776] src/mesh/Makefile.am, src/mesh/test_mesh_single.c: test case for single mesh handle 2013-07-05 14:01 wachs * [r27763] src/ats/gnunet-service-ats-solver_proportional.c: more doxygen documentation 2013-07-05 14:00 wachs * [r27762] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/perf_ats_mlp.c: doxygen documentation 2013-07-05 14:00 wachs * [r27761] src/namestore/namestore_api_common.c: doxygen fix 2013-07-05 13:38 wachs * [r27760] src/ats/gnunet-service-ats-solver_mlp.c: improved value updating for unkown values 2013-07-05 12:52 wachs * [r27759] src/ats/gnunet-service-ats-solver_mlp.c: improved network switching for ats 2013-07-05 12:17 wachs * [r27758] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats_addresses.c: documentation + remove unused code 2013-07-05 12:12 wachs * [r27757] src/ats/gnunet-service-ats_addresses.h: documentation for new solver api in header 2013-07-05 11:00 wachs * [r27756] src/ats/gnunet-service-ats-solver_proportional.c: updating now works with bulk lock 2013-07-05 11:00 wachs * [r27755] src/ats/gnunet-service-ats_addresses.c: removing debugging break 2013-07-05 09:56 wachs * [r27753] src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp.c, src/ats/test_ats_simplistic_switch_networks.c: updating tests to match api 2013-07-05 09:55 wachs * [r27752] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_mlp_update.c: split up update function and using normalized values 2013-07-04 15:27 wachs * [r27748] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h, src/ats/test_ats_api.conf: major change to solver api: split _update function since it combined 3 different functionalities proportional almost done, mlp to do 2013-07-04 12:31 wachs * [r27744] src/ats/gnunet-service-ats-solver_mlp.c: multiple fixes: - read cfg option to dump problem and solution - do not resolve if no requests or addresses - fixed address deletion - implemented function to update single value - fixed preference changes - preference changes now use normalized values 2013-07-04 12:29 wachs * [r27743] src/ats/gnunet-service-ats_addresses.c: correct order of address deletion: remove, notify, free 2013-07-04 12:29 wachs * [r27742] src/ats/gnunet-service-ats-solver_mlp.h: name now reflects function 2013-07-04 07:58 wachs * [r27741] src/ats/gnunet-service-ats-solver_mlp.c: new function to update a value in the matrix 2013-07-03 15:20 wachs * [r27736] src/ats/gnunet-service-ats-solver_proportional.c: removing breaks and output 2013-07-03 15:09 wachs * [r27735] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats_normalization.c: proportional solver uses normalized properties 2013-07-03 13:40 wachs * [r27734] src/ats/test_ats_api.conf: no valgrind 2013-07-03 13:40 wachs * [r27733] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_normalization.c, src/ats/perf_ats_mlp.c, src/ats/test_ats_api.conf, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp_update.c: changing solver api: remove address hashmap from functions and pass instead with init 2013-07-03 11:55 wachs * [r27732] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: function to get normalized properties in solver 2013-07-03 11:55 wachs * [r27731] src/ats/gnunet-service-ats_addresses.h: remove unused fields 2013-07-03 06:42 wachs * [r27730] src/ats/gnunet-service-ats-solver_proportional.c: fixing log level 2013-07-02 15:08 wachs * [r27727] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats-solver_proportional.c: finished buld support 2013-07-02 14:54 wachs * [r27726] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats_addresses.c: added support for bulk operations 2013-07-02 13:30 wachs * [r27722] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h: adding functions for bulkmode 2013-07-02 11:52 wachs * [r27721] src/include/gnunet_ats_service.h: adding bluetooth network type 2013-07-02 11:46 wachs * [r27720] src/transport/plugin_transport_http_server.c: fix network type for external hostnames in http_server 2013-07-02 11:44 wachs * [r27719] src/ats/gnunet-service-ats-solver_proportional.c: fix: do not assert if plugin sends you invalid network type 2013-07-02 11:39 wachs * [r27718] src/transport/plugin_transport_http_client.c: fixed: invalid network scope for external hostname 2013-07-02 11:19 wachs * [r27717] src/transport/plugin_transport_http_server.c: fix: - empty string if no url given - print port as short 2013-07-02 07:54 wachs * [r27716] src/transport/plugin_transport_wlan.c: fix failing tests: returned wrong address size 2013-07-02 07:40 wachs * [r27715] src/transport/plugin_transport_tcp.c: fix: memory leak 2013-07-02 07:39 wachs * [r27714] src/transport/plugin_transport_udp.c: fix: memory leak 2013-07-02 07:32 wachs * [r27713] src/transport/plugin_transport_wlan.c: fixing stack corruption due to buffer overflow 2013-07-01 13:15 wachs * [r27704] src/transport/plugin_transport_unix.c: fixing size check in get_session 2013-07-01 13:09 wachs * [r27703] src/transport/plugin_transport_unix.c: fixing size check in address to string 2013-07-01 09:52 wachs * [r27701] src/integration-tests/Makefile.am: fixing extradist in makefile 2013-07-01 08:12 wachs * [r27700] src/transport/plugin_transport_wlan.c: fix address printing 2013-07-01 08:10 wachs * [r27699] src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_unix.c: doxygen fixes 2013-07-01 08:09 wachs * [r27698] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: doxygen fixes 2013-06-28 15:22 wachs * [r27682] src/transport/test_transport_api_bidirectional_connect.c: fixes in tests: scheduling, removing connect request: 2013-06-28 14:34 bartpolot * [r27681] ., src/exit/gnunet-daemon-exit.c, src/fs/gnunet-service-fs_mesh.c, src/include/block_mesh.h, src/include/gnunet_mesh2_service.h, src/include/gnunet_mesh_service.h, src/include/gnunet_stream_lib.h, src/mesh/Makefile.am, src/mesh/gnunet-mesh.c, src/mesh/gnunet-service-mesh-new.c, src/mesh/gnunet-service-mesh.c, src/mesh/mesh.h, src/mesh/mesh2.h, src/mesh/mesh2_api.c, src/mesh/mesh2_protocol.h, src/mesh/mesh2_test_lib.c, src/mesh/mesh2_test_lib.h, src/mesh/mesh_api.c, src/mesh/mesh_path.c, src/mesh/mesh_path.h, src/mesh/mesh_protocol.h, src/mesh/mesh_test_lib.c, src/mesh/mesh_test_lib.h, src/mesh/plugin_block_mesh.c, src/mesh/test_mesh.conf, src/mesh/test_mesh2.conf, src/mesh/test_mesh2_local.c, src/mesh/test_mesh2_small.c, src/mesh/test_mesh_2dtorus.c, src/mesh/test_mesh_2dtorus.conf, src/mesh/test_mesh_api.c, src/mesh/test_mesh_local.c, src/mesh/test_mesh_local_1.c, src/mesh/test_mesh_local_2.c, src/mesh/test_mesh_local_traffic.c, src/mesh/test_mesh_small.c, src/mesh/test_mesh_small.conf, src/mesh/test_mesh_tree_api.c, src/pt/gnunet-daemon-pt.c, src/set/Makefile.am, src/set/gnunet-service-set.h, src/stream/stream_api.c, src/vpn/gnunet-service-vpn.c: Replace mesh with new version 2013-06-28 14:16 wachs * [r27679] src/transport/plugin_transport_template.c: updating template with address options 2013-06-28 14:02 wachs * [r27678] src/transport/plugin_transport_wlan.c: added option field for WLAN addresses 2013-06-28 14:01 wachs * [r27676] src/ats/gnunet-service-ats-solver_proportional.c: fixing memory leak: unused hashmap fixing segfault by adding NULL check 2013-06-28 12:32 wachs * [r27673] src/transport/plugin_transport_unix.c: options support for unix 2013-06-28 08:26 wachs * [r27670] src/transport/plugin_transport_http_server.c, src/transport/test_transport_api_https_peer2.conf: added: port can be automatically included in external hostname required for testing when ports are modified automatically 2013-06-28 08:24 wachs * [r27669] src/transport/transport.conf.in: new cfg option to include port in external hostname 2013-06-27 15:29 wachs * [r27662] src/transport/plugin_transport_http_client.c: printing fix 2013-06-27 15:16 wachs * [r27661] src/transport/plugin_transport_http_common.c: fix printing 2013-06-27 15:16 wachs * [r27660] src/transport/plugin_transport_http_client.c: (CURLOPT_SSL_VERIFYHOST, 1L) is not suported anymore, have to use 2L 2013-06-27 15:02 wachs * [r27659] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_http_server.c: Implementing bug 0002910 - extended plugin to contain option field in addresses Implementing bug 0002677 - adding ssl verification for external hostname having - the server send the HTTP_OPTIONS_VERIFY_CERTIFICATE option - client use this option to enable ssl verification 2013-06-27 14:57 wachs * [r27658] src/transport/test_plugin_transport.c: remove log message 2013-06-27 14:57 wachs * [r27657] src/transport/test_transport_api_https_peer2.conf, src/transport/transport.conf.in: enabling certification verification in test adding cfg options for certificate verification 2013-06-27 13:37 wachs * [r27652] src/transport/plugin_transport_tcp.c: fix crash 2013-06-27 10:37 tg * [r27648] src/include/gnunet_multicast_service.h: multicast: ping/pong docs 2013-06-27 10:05 tg * [r27647] src/include/gnunet_multicast_service.h, src/include/gnunet_protocols.h: multicast: messages types; function & callback for ping/pong messages; separate join/leave callbacks 2013-06-27 10:01 wachs * [r27646] src/transport/plugin_transport_udp.h: added options in header 2013-06-27 10:01 wachs * [r27645] src/transport/plugin_transport_udp.c: added options field to addresses fixed stack allocation problem when converting string to address 2013-06-27 09:20 wachs * [r27643] src/transport/plugin_transport_tcp.c: added option field in tcp plugin + fixed bug in port map callback: stack allocated variables not zeroed out -> addresses not comparable! 2013-06-27 09:14 wachs * [r27642] src/transport/test_plugin_transport.c: updated test 2013-06-27 06:11 amatus * [r27641] configure.ac, src/Makefile.am, src/ats/Makefile.am, src/core/Makefile.am, src/datacache/Makefile.am, src/datastore/Makefile.am, src/dht/Makefile.am, src/dv/Makefile.am, src/fs/Makefile.am, src/gns/Makefile.am, src/lockmanager/Makefile.am, src/mesh/Makefile.am, src/namestore/Makefile.am, src/nse/Makefile.am, src/peerinfo/Makefile.am, src/pt/Makefile.am, src/regex/Makefile.am, src/set/Makefile.am, src/stream/Makefile.am, src/topology/Makefile.am, src/transport/Makefile.am, src/util/Makefile.am, src/util/test_mq.c: Make building gnunet-testing lib optional. This is all because emscripten doesn't have getaddrinfo. 2013-06-26 17:13 tg * [r27634] src/include/gnunet_multicast_service.h, src/include/gnunet_protocols.h: multicast message types and api docs 2013-06-26 17:12 tg * [r27633] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: psyc apis: use more doxygen syntax, added some missing docs 2013-06-26 10:58 dold * [r27619] src/set/gnunet-service-set.c: fixed duplicate tunnel creation 2013-06-26 10:47 dold * [r27618] src/set/gnunet-service-set.h, src/set/gnunet-service-set_union.c: comment 2013-06-26 10:16 dold * [r27617] src/set/gnunet-service-set.h, src/set/gnunet-service-set_union.c: doxygen 2013-06-26 10:12 dold * [r27615] src/util/network.c: doxygen 2013-06-25 23:37 dold * [r27598] doc/testbed_test.c, src/consensus/consensus_api.c, src/consensus/gnunet-service-consensus.c, src/include/gnunet_mq_lib.h, src/include/gnunet_set_service.h, src/include/gnunet_stream_lib.h, src/set/gnunet-service-set.c, src/set/gnunet-service-set.h, src/set/gnunet-service-set_intersection.c, src/set/gnunet-service-set_union.c, src/set/gnunet-set-profiler.c, src/set/set_api.c, src/stream/stream_api.c, src/util/mq.c: doxygen 2013-06-25 20:51 dold * [r27597] src/include/gnunet_container_lib.h: documented corner case of dll remove 2013-06-25 16:52 dold * [r27596] src/mesh/Makefile.am: testing lib missing in mesh Makefile.am 2013-06-25 15:13 dold * [r27593] src/set/gnunet-service-set.c, src/set/gnunet-service-set.h, src/set/gnunet-set-profiler.c: mesh bug for bart 2013-06-25 13:42 dold * [r27591] src/set/gnunet-service-set.c, src/set/gnunet-service-set.h, src/set/gnunet-service-set_union.c: commented out calls to functions not yet implemented 2013-06-25 13:02 cfuchs * [r27585] src/set/gnunet-service-set.c, src/set/gnunet-service-set_intersection.c: a few more changes to the lib and the service for intersection 2013-06-25 12:20 cfuchs * [r27577] src/set/gnunet-service-set.c, src/set/gnunet-service-set_intersection.c: initial modifications to the set service to support intersection added set intersection sources based upon union 2013-06-25 12:15 wachs * [r27576] src/experimentation/Makefile.am: disable unavailable test 2013-06-25 12:03 wachs * [r27575] src/include/gnunet_ats_service.h: renaming properties and adding function to print properties 2013-06-25 11:25 wachs * [r27572] src/ats/gnunet-service-ats_normalization.c: fixing coverity 10474 Unused pointer value 2013-06-25 11:23 wachs * [r27571] src/ats/test_ats_api_performance_address_info.c: reenable address suggestion in test 2013-06-25 11:20 wachs * [r27570] src/ats/ats_api_scheduling.c: fix for 10472 Structurally dead code 2013-06-25 11:17 wachs * [r27569] src/transport/test_transport_api_timeout.c: fixing coverity 10467 Resource leak 2013-06-25 11:16 wachs * [r27568] src/transport/test_transport_api_disconnect.c: fixing coverity 10466: Resource leak 2013-06-25 11:14 wachs * [r27566] src/transport/test_transport_api_disconnect.c: fixing coverity 10465: Resource leak 2013-06-25 11:12 wachs * [r27565] src/transport/test_plugin_transport.c: fixing coverity 10464: Resource leak 2013-06-25 11:07 wachs * [r27562] src/transport/gnunet-service-transport_manipulation.c: workaround for coverty 10451: Unchecked return value 2013-06-25 11:02 wachs * [r27561] src/ats-tool/gnunet-ats.c: fixing coverity 10470: Uninitialized scalar variable 2013-06-25 10:59 wachs * [r27560] src/ats/gnunet-service-ats_normalization.c: fixing coverity 10444 2013-06-25 10:06 grothoff * [r27558] README, configure.ac, src/Makefile.am: fix #2901: fail hard if libidn or header are not found 2013-06-25 09:58 wachs * [r27556] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: completed normalizing with min max handlin 2013-06-25 09:57 wachs * [r27555] src/ats/test_ats_normalization_update_quality.c: fixed test 2013-06-25 02:05 amatus * [r27551] Makefile.am: Another fix for --with-included-ltdl. 2013-06-24 20:07 wachs * [r27550] src/ats/test_ats_normalization_update_quality.c: fix testname fix array out of bounds for test addresses 2013-06-24 15:06 wachs * [r27549] src/ats/Makefile.am, src/ats/ats_api_scheduling.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h, src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp_update.c, src/ats/test_ats_normalization_update_quality.c: implemented ats property normalization with callback to address to do: recalculate min/max to prevent outdated max values have an impact on normalization 2013-06-24 12:12 wachs * [r27547] src/transport/plugin_transport_template.c: update for plugin template 2013-06-24 10:56 wachs * [r27546] src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: quality normalization without checking if min and max are given 2013-06-24 09:27 wachs * [r27544] doc/gnunet-c-tutorial.pdf, doc/gnunet-c-tutorial.tex: Updating the tutorial section in the source and including an updated version of the pdf about command line parsing. This update describes how a developer can check if a command line argument was set at all by initializing the variables storing the commandline arguments with a specific value and checking this value after the run function applied the commandline parsing. 2013-06-23 18:17 amatus * [r27543] src/include/gnunet_os_lib.h, src/util/Makefile.am, src/util/os_priority.c, src/util/test_os_priority.c: Removed GNUNET_OS_set_process_priority since it's not used. 2013-06-23 16:23 amatus * [r27542] configure.ac, contrib/Makefile.am, src/util/Makefile.am: Make --with-included-ltdl work. 2013-06-21 17:32 grothoff * [r27519] src/testbed/testbed_api.c: cleaner to not use ptr after freeing it, even for printing 2013-06-21 17:30 grothoff * [r27518] src/transport/plugin_transport_http_server.c: cleaner to not use ptr after freeing it, even for printing 2013-06-21 16:15 grothoff * [r27512] src/tun/test_regex.c: fix compile error left from renaming fest 2013-06-21 15:08 wachs * [r27511] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: basics for quality normalization 2013-06-21 13:40 wachs * [r27510] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: doxygen fixes 2013-06-21 13:16 wachs * [r27509] src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: normalization docu 2013-06-21 13:06 wachs * [r27508] src/ats/gnunet-service-ats_normalization.c: fix for crashing perf_ats_mlp 2013-06-21 03:16 amatus * [r27506] src/util/network.c: Fix non-windows non-IPv6 build. 2013-06-20 21:37 grothoff * [r27505] src/regex/Makefile.am: fix linker issues on W32 -- regex needs DHT 2013-06-20 15:32 amatus * [r27504] src/arm/gnunet-service-arm.c, src/dns/dnsstub.c, src/gns/gnunet-dns2gns.c, src/gns/gnunet-gns-proxy.c, src/gns/gnunet-service-gns_resolver.c, src/include/gnunet_network_lib.h, src/nat/nat_test.c, src/testing/testing.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c, src/util/client.c, src/util/network.c, src/util/server.c, src/util/test_connection.c, src/util/test_connection_addressing.c, src/util/test_connection_receive_cancel.c, src/util/test_connection_timeout.c: Fixed GNUNET_CLIENT_service_test on FreeBSD. This should also fix any other platform with AF_UNIX that is not Linux or Mingw. 2013-06-20 09:03 grothoff * [r27502] src/exit/Makefile.am, src/mesh/Makefile.am, src/regex/Makefile.am, src/vpn/Makefile.am: renaming libgnunetregexnew to libgnunetregex 2013-06-20 09:02 grothoff * [r27501] src/regex/Makefile.am, src/regex/gnunet-daemon-regexprofiler.c, src/regex/gnunet-regex-profiler.c, src/regex/gnunet-regex-simulation-profiler.c, src/regex/gnunet-service-regex.c, src/regex/perf-regex.c, src/regex/plugin_block_regex.c, src/regex/regex_block_lib.c, src/regex/regex_block_lib.h, src/regex/regex_internal.c, src/regex/regex_internal.h, src/regex/regex_internal_dht.c, src/regex/regex_internal_lib.h, src/regex/regex_test_graph.c, src/regex/regex_test_lib.c, src/regex/regex_test_lib.h, src/regex/regex_test_random.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_graph_api.c, src/regex/test_regex_iterate_api.c, src/regex/test_regex_proofs.c: renaming symbols from libgnunetregextest to have the prefix REGEX_TEST 2013-06-20 08:56 grothoff * [r27500] src/tun/regex.c: adding file that was moved here from regex.c and forgotten in earlier commit 2013-06-20 08:55 grothoff * [r27499] src/regex/Makefile.am, src/regex/regex.c, src/regex/regex_dht.c, src/regex/regex_graph.c, src/regex/regex_internal.c, src/regex/regex_internal.h, src/regex/regex_internal_dht.c, src/regex/regex_internal_lib.h, src/regex/regex_random.c, src/regex/regex_test_graph.c, src/regex/regex_test_lib.h, src/regex/regex_test_random.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_graph_api.c, src/regex/test_regex_proofs.c: moving functions for testing and evaluation and experiments to the test library, minimizing the internal library, renaming files according to which library they belong to 2013-06-20 08:32 grothoff * [r27498] src/Makefile.am, src/include/Makefile.am, src/include/gnunet_regex_lib.h, src/include/gnunet_tun_lib.h, src/mesh/Makefile.am, src/mesh/gnunet-service-mesh.c, src/regex/Makefile.am, src/regex/gnunet-daemon-regexprofiler.c, src/regex/gnunet-regex-profiler.c, src/regex/gnunet-regex-simulation-profiler.c, src/regex/gnunet-service-regex.c, src/regex/perf-regex.c, src/regex/plugin_block_regex.c, src/regex/regex.c, src/regex/regex_block_lib.c, src/regex/regex_block_lib.h, src/regex/regex_dht.c, src/regex/regex_graph.c, src/regex/regex_internal.h, src/regex/regex_internal_lib.h, src/regex/regex_random.c, src/regex/regex_test_lib.c, src/regex/regex_test_lib.h, src/regex/test_regex_eval_api.c, src/regex/test_regex_graph_api.c, src/regex/test_regex_iptoregex.c, src/regex/test_regex_iterate_api.c, src/regex/test_regex_proofs.c, src/tun/Makefile.am, src/tun/test_regex.c, src/vpn/gnunet-service-vpn.c: continuing refactoring of regex library structure, disambiguating symbol names between old regex library which is now internal and the public API; moving IP-to-regex conversion functions to tun library, as only vpn is using those to begin with 2013-06-19 16:09 amatus * [r27495] src/util/disk.c: Fix windows build, statfs is broken there. 2013-06-19 11:50 bartpolot * [r27489] src/fs/gnunet-service-fs_mesh.c, src/include/gnunet_mesh2_service.h, src/mesh/mesh2_api.c: Change in mesh API: data callback no longer provides sender, user must remember tunnel<->sender if needed (fix bug #2894) 2013-06-19 05:51 wachs * [r27480] src/ats/test_ats_mlp_update.c: fix 2013-06-19 05:32 wachs * [r27479] src/ats/Makefile.am, src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp_update.c: fixes 2013-06-19 05:27 wachs * [r27478] src/ats/perf_ats_mlp.c, src/ats/test_ats_change_preference.c: missing file 2013-06-19 05:16 wachs * [r27477] src/ats/Makefile.am, src/ats/test_ats_mlp.c: changes to test 2013-06-19 05:11 wachs * [r27476] src/ats/gnunet-service-ats-solver_mlp.c, src/ats/gnunet-service-ats-solver_mlp.h: renamed 2013-06-19 05:11 wachs * [r27475] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: renaming mlp solver for consistency 2013-06-19 04:59 wachs * [r27474] src/ats/Makefile.am, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: remove normalization from solvers, use in address only 2013-06-19 04:21 wachs * [r27473] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: doxygen fixes 2013-06-19 02:15 amatus * [r27472] configure.ac, src/util/disk.c: This should be a more portable GNUNET_DISK_file_get_identifiers. 2013-06-18 23:46 amatus * [r27470] src/include/gnunet_disk_lib.h, src/util/disk.c, src/util/test_disk.c: Removed GNUNET_DISK_get_blocks_available since it's not used and it would be hard to port to emscripten. 2013-06-18 11:40 LRN * [r27468] src/ats/test_ats_api_scheduling_destroy_address.c, src/ats/test_ats_api_scheduling_destroy_inbound_connection.c, src/ats/test_ats_api_scheduling_destroy_session.c: Rename WAIT_TIMEOUT (clashes with windows.h) 2013-06-18 08:02 wachs * [r27467] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_normalization.c, src/ats/test_ats_mlp.c: changes 2013-06-18 07:28 wachs * [r27466] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: changes 2013-06-18 06:47 wachs * [r27465] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: changes 2013-06-18 06:29 wachs * [r27464] src/ats/Makefile.am, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: 2013-06-18 02:51 amatus * [r27463] configure.ac, src/include/platform.h: Compile on platforms without netinet/ip.h. Furthur fixes to come. 2013-06-18 02:49 amatus * [r27462] configure.ac, src/util/crypto_random.c: Generalize condition for missing random/srandom. 2013-06-17 14:38 wachs * [r27460] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: proportional solver uses normalizationy 2013-06-17 11:47 wachs * [r27459] src/ats/gnunet-service-ats_normalization.c: changes 2013-06-17 11:13 tg * [r27458] src/include/gnunet_social_service.h: social api docs 2013-06-15 21:32 LRN * [r27455] src/datastore/Makefile.am: Make gnunet-datastore dependent on libgnunetdatastore 2013-06-14 14:46 wachs * [r27448] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_normalization.c, src/ats/gnunet-service-ats_normalization.h: adding generic normalization support for all solvers 2013-06-14 09:45 wachs * [r27446] src/ats/gnunet-service-ats-solver_proportional.c: rename 2013-06-14 07:47 wachs * [r27445] src/ats/gnunet-service-ats-solver_proportional.c: rename function 2013-06-14 06:34 wachs * [r27444] src/ats/gnunet-service-ats-solver_proportional.c: changes 2013-06-13 11:57 tg * [r27439] src/include/gnunet_psycstore_service.h: psycstore api docs 2013-06-13 06:49 wachs * [r27437] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: doxygen 2013-06-13 06:46 wachs * [r27436] src/experimentation/gnunet-daemon-experimentation_experiments.c: doxygen 2013-06-12 20:41 grothoff * [r27434] src/include/gnunet_psycstore_service.h: first design for psycstore API 2013-06-12 20:01 grothoff * [r27432] src/include/gnunet_social_service.h: improving social API a bit more 2013-06-12 19:48 grothoff * [r27431] src/include/gnunet_social_service.h: better name for entering a home 2013-06-12 19:47 grothoff * [r27430] src/include/gnunet_gns_service.h, src/include/gnunet_social_service.h: first design for social service API 2013-06-12 17:35 tg * [r27428] src/include/gnunet_multicast_service.h, src/include/gnunet_psyc_service.h, src/include/gnunet_psycstore_service.h, src/include/gnunet_social_service.h: psyc apis 2013-06-12 10:46 bartpolot * [r27424] src/include/gnunet_mesh2_service.h: changes to MESH API: add receive_done, document end handlers 2013-06-12 03:25 amatus * [r27419] configure.ac, src/Makefile.am: Make libidn optional. 2013-06-12 01:56 amatus * [r27418] po/POTFILES.in: Removing missing source files. 2013-06-11 11:44 wachs * [r27411] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h: changes 2013-06-11 08:20 wachs * [r27406] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h: docu 2013-06-09 04:46 amatus * [r27400] configure.ac, src/core/Makefile.am, src/datastore/Makefile.am, src/dht/Makefile.am, src/testbed/Makefile.am, src/util/Makefile.am: Add --with-zlib=[DIR] configure option. 2013-06-07 14:51 wachs * [r27399] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h: changes 2013-06-07 13:59 wachs * [r27398] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c: rename 2013-06-07 13:18 wachs * [r27397] src/ats/gnunet-service-ats-solver_proportional.c: changes 2013-06-07 13:13 wachs * [r27396] src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c: restructure 2013-06-07 11:59 wachs * [r27395] src/ats/Makefile.am, src/ats/gnunet-service-ats-solver_proportional.c, src/ats/gnunet-service-ats-solver_proportional.h, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: rename and cleanup due to writing docu 2013-06-07 11:07 wachs * [r27393] src/ats/gnunet-service-ats_addresses_simplistic.c: reflow and docu 2013-06-05 18:07 bartpolot * [r27369] src/mesh/gnunet-service-mesh-new.c: refactor, improve debug output 2013-05-30 19:10 grothoff * [r27342] doc/man/Makefile.am, doc/man/gnunet-datastore.1, src/datastore/Makefile.am, src/datastore/gnunet-datastore.c, src/include/gnunet_datastore_service.h, src/util/gnunet-resolver.c: adding tool to convert/merge datastores (#2875) 2013-05-29 13:56 wachs * [r27329] src/experimentation/Makefile.am, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c: changes 2013-05-29 13:20 wachs * [r27328] src/experimentation/Makefile.am, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c, src/experimentation/test_experimentation_clique.c, src/experimentation/test_experimentation_clique_connect.c: changes 2013-05-28 10:03 wachs * [r27322] src/experimentation/test_experimentation_clique.conf: no valgrind 2013-05-28 10:02 wachs * [r27321] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/test_experimentation_clique.c, src/experimentation/test_experimentation_clique.conf: changes 2013-05-28 09:52 wachs * [r27320] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_nodes.c: changes 2013-05-28 09:35 wachs * [r27319] src/experimentation/gnunet-daemon-experimentation_experiments.c: changes 2013-05-28 09:34 wachs * [r27318] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c: changes`` 2013-05-27 23:35 bartpolot * [r27315] src/regex/regex_test_lib.c: Fix regexes with accepting common prefix, optimize regex prefix lengths 2013-05-27 15:39 wachs * [r27312] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_scheduler.c: scheduling 2013-05-27 15:09 wachs * [r27311] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_experiments.c: experimentation timing 2013-05-27 08:53 wachs * [r27307] src/experimentation/Makefile.am, src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_scheduler.c, src/experimentation/gnunet-daemon-experimentation_storage.c: new components 2013-05-27 08:22 wachs * [r27306] src/experimentation/gnunet-daemon-experimentation_experiments.c: docu 2013-05-27 08:19 wachs * [r27305] src/experimentation/gnunet-daemon-experimentation_capabilities.c: docu 2013-05-27 08:18 wachs * [r27304] src/experimentation/gnunet-daemon-experimentation_nodes.c: docu 2013-05-27 08:09 wachs * [r27303] src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_capabilities.c: documentation 2013-05-27 07:40 wachs * [r27302] src/transport/plugin_transport_tcp.c: additional check 2013-05-24 15:09 wachs * [r27299] src/experimentation/gnunet-daemon-experimentation_experiments.c: pubkey 2013-05-24 14:44 wachs * [r27298] src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/test_experimentation_clique.c, src/experimentation/test_experimentation_clique.conf: extended test 2013-05-24 14:24 wachs * [r27296] src/experimentation/Makefile.am, src/experimentation/test_experiments.exp: test experiments 2013-05-24 14:21 wachs * [r27295] src/experimentation/gnunet-daemon-experimentation_experiments.c: experiments 2013-05-24 13:35 wachs * [r27294] src/experimentation/gnunet-daemon-experimentation_experiments.c: parsing 2013-05-24 12:27 wachs * [r27291] src/experimentation/Makefile.am, src/experimentation/experimentation.conf.in, src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_capabilites.c, src/experimentation/gnunet-daemon-experimentation_capabilities.c, src/experimentation/gnunet-daemon-experimentation_experiments.c, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/test_experimentation_clique.c, src/experimentation/test_experimentation_clique.conf: issuer 2013-05-24 11:25 wachs * [r27286] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_capabilites.c, src/experimentation/gnunet-daemon-experimentation_nodes.c: changes 2013-05-24 09:44 wachs * [r27283] src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_capabilites.c: capability bit shifting 2013-05-24 07:57 wachs * [r27280] src/experimentation/Makefile.am: check experimental 2013-05-24 07:50 wachs * [r27279] src/experimentation/gnunet-daemon-experimentation_capabilites.c: no comma 2013-05-23 15:25 wachs * [r27275] src/experimentation/gnunet-daemon-experimentation_capabilites.c: changes 2013-05-23 14:57 wachs * [r27274] src/transport/gnunet-service-transport_manipulation.c: one '&' to break it all... 2013-05-23 14:11 wachs * [r27272] src/transport/gnunet-service-transport_manipulation.c: fix 2013-05-23 14:01 wachs * [r27271] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h: fix for 0002890 2013-05-23 12:37 wachs * [r27268] src/transport/gnunet-service-transport_validation.c: remove warn message and add documentation 2013-05-23 12:22 wachs * [r27267] src/experimentation/Makefile.am, src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_capabilites.c, src/experimentation/gnunet-daemon-experimentation_nodes.c: adding capabilities 2013-05-23 11:38 wachs * [r27266] src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c: use GSE_stat as extern 2013-05-23 11:28 wachs * [r27265] src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c: documentation 2013-05-23 11:19 wachs * [r27264] src/experimentation/Makefile.am, src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/gnunet-daemon-experimentation.h, src/experimentation/gnunet-daemon-experimentation_nodes.c, src/experimentation/test_experimentation_clique.c: split up code to multiple files 2013-05-22 22:52 LRN * [r27262] src/mesh/Makefile.am: Try to fix mesh dependencies 2013-05-22 19:11 wachs * [r27261] src/include/gnunet_protocols.h: message types 2013-05-22 14:12 wachs * [r27259] src/experimentation/Makefile.am, src/experimentation/test_experimentation_clique.conf: changes 2013-05-22 14:11 wachs * [r27258] src/experimentation/gnunet-daemon-experimentation.c: modifications 2013-05-22 14:11 wachs * [r27257] src/experimentation/test_experimentation_clique.c: added statistics support 2013-05-22 13:01 wachs * [r27256] src/experimentation/gnunet-daemon-experimentation.c: manage requests 2013-05-22 12:19 wachs * [r27254] src/experimentation/gnunet-daemon-experimentation.c: changes 2013-05-22 06:06 LRN * [r27239] src/arm/test_arm_api.c: Adjust test_arm_api after API changes in r27231 2013-05-21 15:12 wachs * [r27232] src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/test_experimentation_clique.conf: request management 2013-05-21 15:00 grothoff * [r27231] doc/man/gnunet-arm.1, src/arm/arm_api.c, src/arm/gnunet-arm.c: fixing ARM restarting, adding monitor mode to command line 2013-05-21 14:19 wachs * [r27230] doc/gnunet-c-tutorial.pdf, doc/gnunet-c-tutorial.tex: execute ldconfig 2013-05-21 13:38 wachs * [r27227] src/experimentation/Makefile, src/experimentation/Makefile.am, src/experimentation/gnunet-daemon-experimentation.c, src/experimentation/test_experimentation_clique.c, src/experimentation/test_experimentation_clique.conf: testcase to connect daemons in a clique 2013-05-21 12:58 grothoff * [r27221] src/dns/gnunet-helper-dns.c: keep DNS helper running if IPv6 sockets fail, then we do IPv4-only 2013-05-21 12:35 wachs * [r27216] configure.ac, src/Makefile.am, src/experimentation, src/experimentation/Makefile, src/experimentation/Makefile.am, src/experimentation/experimentation.conf.in, src/experimentation/gnunet-daemon-experimentation.c: adding experimentation daemon 2013-05-17 13:11 wachs * [r27199] src/transport/test_transport_api_manipulation_cfg.c: fix return value 2013-05-17 12:59 wachs * [r27198] src/transport/gnunet-service-transport_manipulation.c, src/transport/test_transport_api_manipulation_cfg.c, src/transport/test_transport_api_manipulation_cfg_peer2.conf: improved test 2013-05-17 11:37 wachs * [r27197] src/transport/gnunet-service-transport_manipulation.c: more dbg msg 2013-05-17 11:32 wachs * [r27196] src/transport/gnunet-service-transport_manipulation.c: already defined on OSX 2013-05-17 11:29 wachs * [r27195] src/transport/gnunet-service-transport_manipulation.c: debug msg 2013-05-16 13:26 wachs * [r27176] src/transport/plugin_transport_udp_broadcasting.c: fix 2013-05-16 13:02 wachs * [r27174] src/transport/plugin_transport_udp.c: returning here is not a good idea since: - IPv6 socket can be opened but will be not closed if IPv4 error is handled as hard error - Plugin will return correctly with IPv6 socket open but never scheduled 2013-05-16 12:45 wachs * [r27173] src/transport/plugin_transport_udp.c, src/transport/plugin_transport_udp.h, src/transport/plugin_transport_udp_broadcasting.c: fixing memory leaks in udp 2013-05-16 11:58 wachs * [r27171] src/transport/plugin_transport_udp.c: remove memory debug code 2013-05-16 07:21 wachs * [r27159] src/transport/test_transport_api_manipulation_cfg.c: test failing on pi 2013-05-15 20:47 grothoff * [r27155] doc/gnunet-c-tutorial.pdf, doc/testbed_test.c: improving example documentation 2013-05-15 12:28 wachs * [r27147] src/transport/transport.conf.in: docu 2013-05-15 12:27 wachs * [r27146] src/transport/test_transport_api_udp_peer1.conf: test using autodetection 2013-05-15 12:05 wachs * [r27145] src/transport/plugin_transport_udp.c: changes to binding port 2013-05-15 11:35 dold * [r27143] src/set/gnunet-service-set.c, src/set/gnunet-service-set_union.c: removed unnecessary malloc 2013-05-15 10:48 dold * [r27142] src/include/gnunet_protocols.h, src/set/Makefile.am, src/set/gnunet-service-set.c, src/set/gnunet-service-set.h, src/set/gnunet-service-set_union.c, src/set/gnunet-set-bug.c, src/set/gnunet-set.c, src/set/ibf.c, src/set/mq.c, src/set/mq.h, src/set/set.h, src/set/set_api.c, src/set/strata_estimator.c, src/set/test_mq.c, src/set/test_mq_client.c, src/set/test_set.conf, src/set/test_set_api.c: test cases for mq, set works 2013-05-15 09:00 grothoff * [r27139] src/nat/nat.c: do not enumerate all IP addresses from our interfaces if the plugin is bound to a specific IP address only 2013-05-14 16:25 wachs * [r27135] src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c: improved messages 2013-05-14 15:50 wachs * [r27133] src/transport/plugin_transport_udp.c, src/transport/test_transport_api_udp_peer1.conf, src/transport/test_transport_api_udp_peer2.conf: fixing udp bindto 2013-05-14 14:31 wachs * [r27128] src/transport/gnunet-service-transport_manipulation.c: fix for manipulation, machine horribly died while testing 2013-05-14 08:33 wachs * [r27112] src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/plugin_transport_udp.c, src/transport/transport_api.c: compile error in udp additional debug messages for transport connections 2013-05-14 08:10 wachs * [r27111] contrib/ssh-keys: new ssh key 2013-05-13 12:55 wachs * [r27103] src/transport/plugin_transport_udp.c: bound (IPv6) socket to wrong (IPv4) address 2013-05-12 11:08 dold * [r27100] src/mesh/mesh.conf.in: missing config value 2013-05-08 07:23 wachs * [r27061] src/transport/test_transport_api_manipulation_cfg.c: missing test 2013-05-07 15:57 wachs * [r27057] src/transport/gnunet-service-transport_manipulation.c: documentation 2013-05-07 15:53 wachs * [r27056] src/transport/transport.conf.in: added warning 2013-05-07 15:51 wachs * [r27055] src/transport/Makefile.am, src/transport/gnunet-service-transport_manipulation.c, src/transport/test_transport_api_manipulation_cfg_peer1.conf, src/transport/test_transport_api_manipulation_cfg_peer2.conf: fix for 0002881 + test 2013-05-07 14:35 harsha * [r27054] src/testbed, src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed.h, src/testbed/gnunet-service-testbed_peers.c, src/testbed/test_testbed_api_peer_reconfiguration.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: fix #2665: peer reconfiguration now implemented 2013-05-07 11:36 bartpolot * [r27046] src/mesh/Makefile.am, src/mesh/mesh2_api.c: Initial mesh2 api import 2013-05-06 12:33 wachs * [r27036] src/transport/transport.conf.in: traffic manipulation cfg settings 2013-05-02 08:07 harsha * [r27013] src/stream/stream.h, src/stream/stream_api.c: fix #2877: stream doesn't distinguish between the application ports 2013-04-30 11:53 dold * [r27008] src/set/gnunet-service-set.c, src/set/gnunet-service-set.h, src/set/gnunet-service-set_union.c: fix/docs 2013-04-30 11:05 dold * [r27007] src/set/gnunet-service-set_union.c, src/set/set.h, src/set/strata_estimator.c, src/set/strata_estimator.h: fix / documentation 2013-04-30 04:38 LRN * [r27005] src/util/test_os_start_process.c: Fix test_os_startprocess Previous code wrongly assumed that the message will be read from the pipe completely in one go. It does not happen like that _every_ time. 2013-04-30 00:04 dold * [r27004] src/include/gnunet_set_service.h, src/set/gnunet-service-set.c, src/set/gnunet-service-set.h, src/set/gnunet-service-set_union.c, src/set/gnunet-set-bug.c, src/set/mq.c, src/set/mq.h, src/set/set_api.c: implemented most parts of the set service 2013-04-29 09:09 dold * [r27003] src/set/gnunet-service-set.c, src/set/gnunet-service-set_union.c, src/set/set.h: fix 2013-04-27 14:24 dold * [r27002] src/set/Makefile.am, src/set/gnunet-set-bug.c: forgot to add c file 2013-04-27 14:16 dold * [r27001] po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/include/gnunet_set_service.h, src/set/Makefile.am, src/set/gnunet-service-set.c, src/set/gnunet-service-set.h, src/set/gnunet-service-set_union.c, src/set/gnunet-set.c, src/set/mq.c, src/set/mq.h, src/set/set_api.c, src/util/crypto_ecc.c: work on gnunet-set, isolated bug in stream 2013-04-27 11:04 dold * [r27000] src/include/gnunet_crypto_lib.h, src/util/crypto_ecc.c: implemented GNUNET_CRYPTO_get_host_identity 2013-04-26 15:43 dold * [r26999] src/testing/Makefile.am: reverted changes to makefile, was just a problem with autotools on my system 2013-04-26 14:29 dold * [r26998] src/testing/Makefile.am: fixed compilation errors: undefined reference to `GNUNET_ARM_[...]' 2013-04-24 12:05 dold * [r26983] src/set/gnunet-service-set.h, src/set/gnunet-service-set_union.c, src/set/set_protocol.h: forgot to commit new files 2013-04-24 11:48 dold * [r26981] src/include/gnunet_applications.h, src/include/gnunet_protocols.h, src/include/gnunet_set_service.h, src/set/Makefile.am, src/set/gnunet-service-set.c, src/set/gnunet-set.c, src/set/mq.c, src/set/mq.h, src/set/set.conf.in, src/set/set.h, src/set/set_api.c, src/set/strata_estimator.c, src/set/strata_estimator.h, src/set/test_set_api.c: started implementing union operation for set 2013-04-22 14:42 bartpolot * [r26970] src/util/disk.c: Allow callback to stop a DISK_scan with no error, similar to other er APIs 2013-04-22 08:10 LRN * [r26967] src/arm/gnunet-service-arm.c: Don't start accept task twice 2013-04-22 08:10 LRN * [r26966] src/arm/arm_monitor_api.c: Correctly forget task ID once task runs 2013-04-21 20:01 harsha * [r26964] src/include/gnunet_protocols.h, src/include/gnunet_testbed_service.h, src/testbed/gnunet-service-testbed.c, src/testbed/testbed.conf.in, src/testbed/testbed.h, src/testbed/testbed_api.c: fix #2666: Implement service sharing among peers 2013-04-21 17:54 LRN * [r26962] src/chat/Makefile.am, src/chat/chat.c: Fix chat to compile and link successfully 2013-04-21 17:53 LRN * [r26961] src/gns/w32nsp-resolve.c: Better fix for w32nsp warnings 2013-04-21 17:53 LRN * [r26960] src/gns/w32nsp-resolve.c: Fix a warning - include ws2 before windows.h 2013-04-21 17:53 LRN * [r26959] src/exit/gnunet-helper-exit-windows.c: Mingw-w64 compatibility for W32 exit helper 2013-04-21 17:53 LRN * [r26958] src/vpn/gnunet-helper-vpn-windows.c: Mingw-w64 compatibility for VPN helper 2013-04-21 17:53 LRN * [r26957] src/fs/Makefile.am: Try to fix fs block plugin deps 2013-04-21 13:37 LRN * [r26956] src/gns/w32nsp-resolve.c, src/gns/w32nsp.c, src/gns/w32nsp.def: Fix mingw-w64 warnings in w32nsp 2013-04-21 13:37 LRN * [r26955] src/util/win.c: Better mingw-w64 compatibility for win.c 2013-04-21 13:36 LRN * [r26954] contrib/timeout_watchdog_w32.c: Use safer functions in w32 watchdog 2013-04-21 13:36 LRN * [r26953] src/include/plibc.h: Update plibc header 2013-04-19 14:58 cfuchs * [r26944] src/dns/gnunet-service-dns.c, src/gns/test_gns_proxy.c, src/nat/nat.c, src/nat/nat_auto.c, src/pt/test_gns_vpn.c: added privilege testing parameters for nat-server and added parameters to currently windows-only tests (less work in the future, even if this is ATM unused) 2013-04-19 14:50 cfuchs * [r26943] src/exit/gnunet-daemon-exit.c, src/nat/nat.c, src/nat/nat_auto.c, src/pt/test_gnunet_vpn.c, src/vpn/gnunet-service-vpn.c: added privilege testing parameters for helper-vpn, exit and nat-client. todo: nat-server 2013-04-18 14:48 bartpolot * [r26935] src/include/gnunet_getopt_lib.h, src/util/getopt_helpers.c: Add filename getopt operator 2013-04-17 15:32 bartpolot * [r26925] src/arm/do_start_process.c, src/arm/gnunet-service-arm.c: Dont restart services/daemons that have exited with exit code 0. 2013-04-17 12:20 grothoff * [r26921] src/util/disk.c: set close-on-exec file for opened disk file descriptors 2013-04-17 11:34 dold * [r26920] src/set/mq.h: api fix 2013-04-17 11:07 dold * [r26919] src/set/gnunet-service-set.c, src/set/set_api.c: fix 2013-04-17 10:53 dold * [r26916] src/set/mq.h, src/set/set_api.c: fix 2013-04-17 10:47 dold * [r26914] src/set/mq.h: partial docs 2013-04-17 10:41 dold * [r26913] src/set/mq.h, src/set/set.h, src/set/set_api.c: fix 2013-04-17 00:44 dold * [r26911] src/include/gnunet_protocols.h, src/include/gnunet_set_service.h, src/include/gnunet_testing_lib.h, src/set/Makefile.am, src/set/mq.c, src/set/mq.h, src/set/set.h, src/set/set_api.c, src/set/test_set_api.c: started implementing set api, draft for mq 2013-04-16 18:32 dold * [r26909] configure.ac, po/POTFILES.in, po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/Makefile.am, src/consensus/gnunet-service-consensus.c, src/set, src/set/Makefile.am, src/set/gnunet-service-set.c, src/set/gnunet-set.c, src/set/ibf.c, src/set/ibf.h, src/set/set.conf.in, src/set/set_api.c, src/set/strata_estimator.c, src/set/strata_estimator.h, src/set/test_set.conf, src/set/test_set_api.c: added skeleton for gnunet set 2013-04-16 18:01 dold * [r26908] src/chat/Makefile.am, src/chat/gnunet-chat.c: fixed compilation error in chat 2013-04-16 14:53 LRN * [r26906] contrib/timeout_watchdog_w32.c: Use a W32 constant in a pure W32 program 2013-04-15 12:36 cfuchs * [r26890] src/dns/gnunet-service-dns.c, src/exit/gnunet-daemon-exit.c, src/exit/gnunet-helper-exit-windows.c, src/gns/test_gns_proxy.c, src/include/gnunet_os_lib.h, src/nat/Makefile.am, src/nat/gnunet-helper-nat-client-windows.c, src/nat/gnunet-helper-nat-server-windows.c, src/nat/nat.c, src/nat/nat_auto.c, src/nat/nat_mini.c, src/nat/test_nat_test.c, src/pt/Makefile.am, src/pt/test_gns_vpn.c, src/pt/test_gnunet_vpn.c, src/transport/plugin_transport_wlan.c, src/util/os_installation.c, src/util/os_priority.c, src/vpn/gnunet-helper-vpn-windows.c, src/vpn/gnunet-service-vpn.c: extended the GNUNET_OS_check_helper_binary parameters to do previlege checking in windows. To do so, tested binaries must still be supplied with valid commandline arguments, but on windows gnunet will utilize the -d flag to run the programs initialization phase or privileged operations only. In these modes, a program will not enter its mainloop or communicate with the outside. updated relevant function calls gnunet-wide to meet the extended function parameters. 2013-04-15 09:39 grothoff * [r26887] doc/gnunet-c-tutorial.pdf, doc/gnunet-c-tutorial.tex: gitlibgcrypt 2013-04-14 20:21 grothoff * [r26874] src/Makefile.am, src/chat/chat.c, src/chat/gnunet-chat.c, src/fs/fs_api.h, src/fs/fs_namespace.c, src/fs/fs_pseudonym.c, src/fs/fs_publish_ksk.c, src/fs/fs_search.c, src/fs/fs_unindex.c, src/fs/fs_uri.c, src/fs/gnunet-pseudonym.c, src/fs/plugin_block_fs.c, src/fs/test_fs_namespace.c, src/fs/test_fs_uri.c, src/fs/test_pseudonym.c, src/include/block_fs.h, src/include/gnunet_fs_service.h: renaming GNUNET_PSEUDONYM_-API to GNUNET_FS_pseudonym-API 2013-04-12 13:44 wachs * [r26864] doc/figs, doc/figs/Service.pdf, doc/figs/System.pdf, doc/gnunet-c-tutorial.pdf, doc/gnunet-c-tutorial.tex: changes thx to SAP 2013-04-12 12:31 wachs * [r26861] src/transport/gnunet-service-transport_manipulation.c: uninitialized 2013-04-11 14:07 wachs * [r26854] src/transport/template_cfg_peer1.conf, src/transport/template_cfg_peer2.conf: prevent hostlist connects 2013-04-11 13:30 wachs * [r26848] src/transport/gnunet-service-transport.c: surpress core message " Unsupported message of type 16" 2013-04-11 12:26 wachs * [r26847] contrib/hellos/PIEU: new hello 2013-04-11 10:08 dold * [r26846] src/consensus/Makefile.am, src/consensus/consensus-simulation.py, src/consensus/consensus_api.c, src/consensus/consensus_flout.h, src/consensus/gnunet-consensus-ibf.c, src/consensus/gnunet-consensus.c, src/consensus/gnunet-service-consensus.c, src/consensus/ibf.c, src/consensus/ibf.h, src/consensus/strata_estimator.c, src/consensus/strata_estimator.h, src/dv/gnunet-service-dv.c, src/include/gnunet_consensus_service.h, src/include/gnunet_protocols.h: added consensus log-round simulation, work on consensus service, still problems with dv test case 2013-04-11 08:51 wachs * [r26845] contrib/hellos/02UK, contrib/hellos/1G1M, contrib/hellos/7RAV, contrib/hellos/8B4T, contrib/hellos/94CH, contrib/hellos/ATF4, contrib/hellos/F1GT, contrib/hellos/KD9V, contrib/hellos/KUPL, contrib/hellos/LJR8, contrib/hellos/R69Q, contrib/hellos/R6OV, contrib/hellos/RL7P: remove invalid HELLOs 2013-04-11 08:07 wachs * [r26844] contrib/hellos/TFRM: Added a valid HELLO for my machine - peerinfo test should pass now 2013-04-11 07:13 wachs * [r26843] src/peerinfo-tool/gnunet-peerinfo.c: fix? 2013-04-10 13:29 wachs * [r26838] src/peerinfo/gnunet-service-peerinfo.c: doxygen 2013-04-10 13:03 wachs * [r26836] src/hello/hello.c: changes 2013-04-10 12:55 wachs * [r26835] src/peerinfo-tool/gnunet-peerinfo.c: dump hello to file 2013-04-10 12:16 wachs * [r26834] src/peerinfo/gnunet-service-peerinfo.c: simplified hostfile reading 2013-04-10 11:27 wachs * [r26833] src/peerinfo-tool/gnunet-peerinfo.c: fixed friend flag 2013-04-10 11:27 wachs * [r26832] src/peerinfo/gnunet-service-peerinfo.c: fixed periodic cleanup 2013-04-10 09:57 wachs * [r26829] src/peerinfo/gnunet-service-peerinfo.c: fix 2013-04-10 09:48 wachs * [r26828] src/peerinfo/gnunet-service-peerinfo.c: fix 2013-04-10 09:42 wachs * [r26827] src/peerinfo/gnunet-service-peerinfo.c: fix mem leak and counting valid addresses 2013-04-10 09:20 wachs * [r26825] src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/test_peerinfo_api_notify_friend_only.c: fix 2013-04-10 09:02 wachs * [r26824] src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/test_peerinfo_api.c, src/peerinfo/test_peerinfo_api_friend_only.c, src/peerinfo/test_peerinfo_shipped_hellos.c: multiple major fixes: - shipped hellos were never parsed - when hello files was parsed from certain file, hello from this was ignored major changes in this commit which can break functionality atm 2013-04-10 07:25 wachs * [r26823] src/peerinfo/Makefile.am, src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/test_peerinfo_shipped_hellos.c: testing hellos shipped 2013-04-09 15:24 wachs * [r26821] src/peerinfo/gnunet-service-peerinfo.c: fixes 2013-04-09 14:24 wachs * [r26820] src/peerinfo/gnunet-service-peerinfo.c: work in progress 2013-04-09 12:08 wachs * [r26818] src/peerinfo/gnunet-service-peerinfo.c: store 2 hellos 2013-04-09 08:22 wachs * [r26814] src/peerinfo/gnunet-service-peerinfo.c: initial changes to support 2 hellos 2013-04-08 15:14 wachs * [r26812] src/peerinfo/gnunet-service-peerinfo.c: additional struct 2013-04-08 13:06 wachs * [r26811] src/integration-tests/Makefile.am, src/integration-tests/test_integration_bootstrap_and_connect.py.in, src/integration-tests/test_integration_bootstrap_and_connect_and_disconnect.py.in, src/integration-tests/test_integration_bootstrap_and_connect_and_disconnect_nat.py.in, src/integration-tests/test_integration_clique_nat.py.in: disable verbose 2013-04-08 13:06 wachs * [r26810] configure.ac, src/Makefile.am: remove sysmon and disable libgtop check since it is not working on planetlab anyway 2013-04-08 11:21 wachs * [r26807] src/integration-tests/test_integration_connect_on_restart.py.in: fix 2013-04-08 11:19 wachs * [r26806] src/integration-tests/test_integration_clique_nat.py.in: fix 2013-04-08 11:17 wachs * [r26805] src/integration-tests/test_integration_clique.py.in: change 2013-04-08 11:08 wachs * [r26804] src/integration-tests/confs/c_no_nat_client_2.conf, src/integration-tests/hostkeys/0003-hostkey, src/integration-tests/hostkeys/c_no_nat_client_2: changes 2013-04-08 10:00 wachs * [r26803] src/integration-tests/test_integration_restart.py.in: fix 2013-04-08 09:56 wachs * [r26802] src/integration-tests/test_integration_restart.py.in: cleanup 2013-04-08 09:54 wachs * [r26801] src/integration-tests/Makefile.am, src/integration-tests/confs/c_bootstrap_server.conf, src/integration-tests/confs/c_nat_client.conf, src/integration-tests/confs/c_no_nat_client.conf, src/integration-tests/hostkeys/0000-hostkey, src/integration-tests/hostkeys/0001-hostkey, src/integration-tests/hostkeys/0002-hostkey, src/integration-tests/hostkeys/c_bootstrap_server, src/integration-tests/hostkeys/c_nat_client, src/integration-tests/hostkeys/c_no_nat_client, src/integration-tests/test_integration_bootstrap_and_connect_and_disconnect_nat.py.in: changes 2013-04-08 09:47 wachs * [r26800] src/integration-tests/test_integration_bootstrap_and_connect_and_disconnect.py.in: fix 2013-04-08 09:45 wachs * [r26799] src/integration-tests/test_integration_bootstrap_and_connect.py.in: fixed cleanup 2013-04-08 09:16 wachs * [r26797] src/fs/gnunet-service-fs_cp.c: fs crashing in integraton tests added check 2013-04-08 08:57 wachs * [r26796] src/integration-tests/confs/c_bootstrap_server.conf, src/integration-tests/confs/c_no_nat_client.conf: test fix for integration tests 2013-04-08 08:20 wachs * [r26795] src/integration-tests/hostkeys/0000-hostkey: additional hostkey 2013-04-08 08:07 wachs * [r26794] src/integration-tests/hostkeys/0001-hostkey, src/integration-tests/hostkeys/0002-hostkey, src/integration-tests/hostkeys/0003-hostkey, src/integration-tests/hostkeys/0004-hostkey, src/integration-tests/hostkeys/0005-hostkey, src/integration-tests/hostkeys/0006-hostkey, src/integration-tests/hostkeys/0007-hostkey, src/integration-tests/hostkeys/0008-hostkey, src/integration-tests/hostkeys/0009-hostkey: fixing invalid hostkeys 2013-04-08 07:27 wachs * [r26793] src/peerinfo/gnunet-service-peerinfo.c: not required 2013-04-08 07:19 wachs * [r26792] src/ats/gnunet-service-ats_addresses_mlp.h: doxygen 2013-04-05 15:03 wachs * [r26785] src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/perf_peerinfo_api.c: perf test 2013-04-05 14:43 wachs * [r26784] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/peerinfo/gnunet-service-peerinfo.c: doxygen 2013-04-05 14:11 cfuchs * [r26783] src/exit/gnunet-helper-exit-windows.c: dryrun functionality added, removed irrelevant return code reset 2013-04-05 14:10 cfuchs * [r26782] src/vpn/gnunet-helper-vpn-windows.c: added dryrun functionality to helper-vpn-windows 2013-04-05 14:10 cfuchs * [r26781] src/util/os_installation.c: removed raw-pipe checking code for windows. this will always fail new windows. functionality will be replaced with windows-dryrun checking 2013-04-05 14:08 cfuchs * [r26780] src/pt/test_gnunet_vpn.c: started making test_gnunet_vpn a bit less linux-only. does not work on windows yet, though due to permissions checking, see other commits! 2013-04-05 13:35 wachs * [r26779] src/transport/gnunet-service-transport_hello.c: refresh hello fix 2013-04-05 13:16 wachs * [r26778] src/peerinfo-tool/gnunet-peerinfo.c: fix 2013-04-05 13:07 wachs * [r26777] src/peerinfo/peerinfo.conf.in: add uri info 2013-04-05 13:07 LRN * [r26776] src/util/w32cat.c: Don't wcscmp a NULL pointer 2013-04-05 13:02 wachs * [r26775] src/hello/hello.c: print hello friend type 2013-04-05 12:22 wachs * [r26773] src/ats/gnunet-service-ats_addresses.c: fix 2013-04-05 11:38 grothoff * [r26771] src/nse/gnunet-service-nse.c, src/nse/nse.conf.in, src/nse/perf_kdf.c: use SCRYPT - fixing # 2685, needs LATEST libgcrypt (Git from today) 2013-04-05 09:26 wachs * [r26770] src/peerinfo/Makefile.am, src/peerinfo/test_peerinfo_api_notify_friend_only.c: test 2013-04-05 08:52 wachs * [r26769] src/peerinfo/gnunet-service-peerinfo.c: wrong log type 2013-04-05 08:51 wachs * [r26768] src/peerinfo/gnunet-service-peerinfo.c: fixed client notifications 2013-04-05 08:51 wachs * [r26767] src/peerinfo/peerinfo_api_notify.c: wrong struct 2013-04-05 07:51 wachs * [r26764] doc/gnunet-c-tutorial.pdf, doc/gnunet-c-tutorial.tex: c tutorial 2013-04-04 13:56 wachs * [r26760] src/peerinfo/Makefile.am, src/peerinfo/test_peerinfo_api_friend_only.c: test 2013-04-04 13:41 wachs * [r26759] src/peerinfo/gnunet-service-peerinfo.c: peerinfo get implementation 2013-04-04 13:08 wachs * [r26756] src/hostlist/hostlist-server.c, src/peerinfo/gnunet-service-peerinfo.c: implement peerinfo notification api 2013-04-04 12:02 wachs * [r26754] src/dht/gnunet-service-dht_hello.c, src/hostlist/hostlist-server.c, src/include/gnunet_peerinfo_service.h, src/peerinfo-tool/gnunet-peerinfo.c, src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/peerinfo.h, src/peerinfo/peerinfo_api.c, src/peerinfo/peerinfo_api_notify.c, src/peerinfo/test_peerinfo_api.c, src/topology/gnunet-daemon-topology.c, src/transport/gnunet-service-transport_validation.c: peerinfo API change + changes in code using api 2013-04-04 09:43 wachs * [r26751] src/hello/gnunet-hello.c, src/hello/hello.c, src/include/gnunet_hello_lib.h, src/include/gnunet_protocols.h, src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/peerinfo.conf.in, src/testbed/gnunet-service-testbed_oc.c, src/topology/gnunet-daemon-topology.c, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_validation.c, src/transport/plugin_transport_udp_broadcasting.c, src/transport/plugin_transport_wlan.c, src/transport/transport_api.c: changes for mantis 0002676 2013-04-04 08:21 wachs * [r26749] src/ats/gnunet-service-ats_addresses.c: use after free 2013-04-04 08:07 wachs * [r26748] src/ats/gnunet-service-ats_addresses.c: uninitialized value causing segfault 2013-04-03 16:04 wachs * [r26744] src/transport/plugin_transport_http_server.c, src/transport/transport.conf.in: initial server side change for MITM ssl validation 2013-04-03 15:49 wachs * [r26742] src/transport/gnunet-service-transport_manipulation.c: generic ats support 2013-04-03 15:18 wachs * [r26741] src/transport/gnunet-service-transport_manipulation.c: changes 2013-04-03 14:59 wachs * [r26740] src/transport/gnunet-service-transport_manipulation.c: generic ats manipulation 2013-04-03 14:22 wachs * [r26739] src/include/gnunet_ats_service.h: docu fix 2013-04-03 14:18 wachs * [r26738] src/transport/gnunet-service-transport_manipulation.c: docu 2013-04-03 14:11 wachs * [r26737] src/transport/gnunet-service-transport_manipulation.c: docu 2013-04-03 12:22 wachs * [r26735] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_mlp_update.c, src/include/gnunet_ats_service.h: ats change, done 2013-04-03 11:12 wachs * [r26733] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c: fixed network switching 2013-04-03 10:56 wachs * [r26732] src/ats/gnunet-service-ats_addresses.c: delta support for disassemble 2013-04-03 09:30 wachs * [r26731] src/ats/test_ats_api_common.c: fix 2013-04-03 09:24 wachs * [r26730] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/ats/perf_ats_mlp.c, src/ats/test_ats_api_scheduling_update_address.c, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp_update.c: api change, fix and improvements 2013-04-03 07:59 wachs * [r26729] src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_api_scheduling_check_min_bw_alt.c: test 2013-04-03 07:37 wachs * [r26728] src/ats/gnunet-service-ats_addresses_mlp.c: fixed mlp 2013-04-03 07:25 wachs * [r26727] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c: changes 2013-04-02 15:39 wachs * [r26724] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_simplistic.c: breaks tests 2013-04-02 14:48 wachs * [r26722] src/ats/gnunet-service-ats_addresses.h: docue 2013-04-02 14:39 wachs * [r26721] src/ats/gnunet-service-ats_addresses.c: docu 2013-04-02 14:25 wachs * [r26720] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h: documentation 2013-04-02 09:02 wachs * [r26716] src/ats/gnunet-service-ats_addresses.h: some documentation 2013-03-31 20:48 harsha * [r26704] src/include/gnunet_testing_lib.h, src/testing/test_testing_peerstartup2.c, src/testing/testing.c: support for asynchronous peer start/stop and service start/stop using ARM API 2013-03-31 01:24 LRN * [r26689] src/integration-tests/Makefile.am, src/integration-tests/test_buildslave_hangup.py: Remove temporary W32 buildslave test 2013-03-31 01:23 LRN * [r26688] contrib/buildslave-0.8.5-gnunet-w32.patch, contrib/buildslave-0.8.6p1-gnunet-w32.patch: Update w32 buildslave patch to 0.8.6p1, and FINALLY FIX THE DAMN THING 2013-03-30 16:31 LRN * [r26684] src/integration-tests/Makefile.am: ARGH. Automake and its special variables... 2013-03-30 16:18 LRN * [r26678] src/integration-tests/Makefile.am, src/integration-tests/test_buildslave_hangup.py: A temporary test for buildslave process killing 2013-03-30 15:29 harsha * [r26674] contrib/infiniband_cluster.hosts: current working infiniband hosts 2013-03-28 16:47 harsha * [r26650] src/ats/gnunet-service-ats_addresses.c, src/consensus/gnunet-consensus-start-peers.c, src/consensus/gnunet-consensus.c, src/dht/dht_test_lib.c, src/dv/test_transport_blacklist.c, src/dv/test_transport_dv.c, src/fs/gnunet-fs-profiler.c, src/fs/perf_gnunet_service_fs_p2p.c, src/fs/perf_gnunet_service_fs_p2p_respect.c, src/fs/test_fs_test_lib.c, src/fs/test_gnunet_service_fs_migration.c, src/fs/test_gnunet_service_fs_p2p.c, src/gns/test_gns_dht_three_peers.c, src/include/gnunet_testbed_service.h, src/mesh/mesh_test_lib.c, src/nse/gnunet-nse-profiler.c, src/nse/test_nse_multipeer.c, src/stream/perf_stream_api.c, src/stream/test_stream_2peers.c, src/stream/test_stream_2peers_halfclose.c, src/testbed/gnunet-testbed-profiler.c, src/testbed/test_testbed_api_statistics.c, src/testbed/test_testbed_api_test.c, src/testbed/test_testbed_api_test_timeout.c, src/testbed/test_testbed_api_testbed_run.c, src/testbed/test_testbed_api_topology.c, src/testbed/test_testbed_api_topology_clique.c, src/testbed/testbed_api_testbed.c, src/topology/test_gnunet_daemon_topology.c: provide how many links succeeded and how many failed in test master callback from GNUNET_TESTBED_run() and GNUNET_TESTBED_test_run() functions 2013-03-28 15:59 wachs * [r26648] src/peerinfo/gnunet-service-peerinfo.c, src/testbed/gnunet-service-testbed_oc.c, src/topology/gnunet-daemon-topology.c: support for FRIEND_HELLO 2013-03-28 15:43 wachs * [r26647] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_hello.c, src/transport/gnunet-service-transport_hello.h, src/transport/gnunet-service-transport_validation.c, src/transport/plugin_transport_wlan.c, src/transport/transport_api.c: support for FRIEND_HELLO messages 2013-03-28 15:24 wachs * [r26646] src/hello/hello.c, src/include/gnunet_hello_lib.h: change type 2013-03-28 15:14 wachs * [r26645] src/hello/Makefile.am, src/hello/gnunet-hello.c, src/hello/hello.c, src/hello/test_friend_hello.c, src/hello/test_hello.c, src/include/gnunet_hello_lib.h, src/include/gnunet_protocols.h, src/peerinfo/perf_peerinfo_api.c, src/peerinfo/test_peerinfo_api.c, src/transport/gnunet-service-transport_hello.c, src/transport/gnunet-service-transport_validation.c, src/transport/test_plugin_transport.c: new friend only HELLO type GNUNET_MESSAGE_TYPE_FRIEND_HELLO 2013-03-28 14:28 cfuchs * [r26644] src/pt/test_gnunet_vpn.c: some fixes to the pt/vpn testcase. 2013-03-28 13:54 wachs * [r26641] src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h: more docu 2013-03-28 13:49 wachs * [r26640] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h: docu 2013-03-28 13:26 wachs * [r26639] src/transport/gnunet-service-transport_blacklist.c, src/transport/test_transport_blacklisting.c: docu 2013-03-28 12:37 wachs * [r26638] src/transport/test_transport_blacklisting_cfg_blp_peer2_multiple_plugins.conf: fix 2013-03-28 12:29 wachs * [r26637] src/transport/Makefile.am, src/transport/test_transport_blacklisting.c, src/transport/test_transport_blacklisting_cfg_blp_peer1_multiple_plugins.conf, src/transport/test_transport_blacklisting_cfg_blp_peer2_multiple_plugins.conf: additional test 2013-03-28 12:15 wachs * [r26633] src/transport/Makefile.am, src/transport/gnunet-service-transport_blacklist.c, src/transport/test_transport_blacklisting_cfg.c, src/transport/test_transport_blacklisting_cfg_blp_peer1.conf: fixes to blacklisting 2013-03-28 12:14 wachs * [r26632] src/transport/test_transport_blacklisting.c, src/transport/test_transport_blacklisting_cfg_blp_peer2.conf: modified test 2013-03-28 12:13 wachs * [r26631] src/transport/test_transport_blacklisting_cfg_blp_peer1_full.conf, src/transport/test_transport_blacklisting_cfg_blp_peer1_plugin.conf, src/transport/test_transport_blacklisting_cfg_blp_peer2_full.conf, src/transport/test_transport_blacklisting_cfg_blp_peer2_plugin.conf: confs 2013-03-28 09:50 wachs * [r26628] src/transport/test_transport_blacklisting_cfg.c: missing test 2013-03-28 09:18 harsha * [r26624] src/nse/nse_infiniband.conf: infiniband nse evaluation config 2013-03-27 16:31 wachs * [r26619] src/transport/Makefile.am, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_blacklist.c, src/transport/gnunet-service-transport_blacklist.h, src/transport/test_transport_blacklisting_cfg_blp_peer1.conf, src/transport/test_transport_blacklisting_cfg_blp_peer2.conf, src/transport/test_transport_blacklisting_cfg_peer1.conf, src/transport/test_transport_blacklisting_cfg_peer2.conf: transport cfg based blacklisting 2013-03-27 08:30 wachs * [r26615] src/ats/gnunet-service-ats_addresses.c, src/dv/gnunet-service-dv.c, src/fs/gnunet-service-fs.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h: fix 2013-03-26 15:02 wachs * [r26612] src/ats-tool/gnunet-ats.c, src/ats/Makefile.am, src/ats/ats_api_performance.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_performance.c, src/ats/test_ats_api_performance_address_info.c, src/ats/test_ats_api_performance_list_addresses.c, src/ats/test_ats_api_performance_monitor.c, src/ats/test_ats_simplistic_change_preference.c, src/ats/test_ats_simplistic_pref_aging.c, src/dht/gnunet-service-dht_neighbours.c, src/dv/gnunet-service-dv.c, src/fs/gnunet-service-fs.c, src/include/gnunet_ats_service.h: api change 2013-03-26 13:03 wachs * [r26610] src/dv/gnunet-service-dv.c: fix 2013-03-26 12:52 wachs * [r26609] src/ats/test_ats_api_performance_address_info.c: test 2013-03-26 12:37 wachs * [r26608] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_api_performance_monitor.c: test 2013-03-26 10:50 wachs * [r26606] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_performance.c, src/ats/gnunet-service-ats_performance.h, src/ats/test_ats_api_performance_monitor.c: changes 2013-03-26 10:07 wachs * [r26604] src/ats/test_ats_api_performance_monitor.c: preliminary change 2013-03-26 08:30 wachs * [r26602] src/ats/ats_api_scheduling.c: fix if cb == NULL 2013-03-26 08:11 wachs * [r26601] src/ats/Makefile.am, src/ats/test_ats_api_performance.c, src/ats/test_ats_api_performance_list_addresses.c: rename test 2013-03-26 08:07 wachs * [r26600] src/ats/ats.h, src/ats/gnunet-service-ats_performance.c: unused 2013-03-25 16:10 wachs * [r26599] src/transport/test_plugin_transport.c: fix 2013-03-25 16:06 wachs * [r26598] src/ats-tool/gnunet-ats.c, src/ats/ats_api_performance.c, src/ats/gnunet-service-ats.c, src/ats/gnunet-service-ats_performance.c, src/ats/test_ats_api_performance.c, src/ats/test_ats_api_performance_monitor.c, src/ats/test_ats_simplistic_change_preference.c, src/ats/test_ats_simplistic_pref_aging.c, src/dht/gnunet-service-dht_neighbours.c, src/fs/gnunet-service-fs.c, src/include/gnunet_ats_service.h, src/include/gnunet_protocols.h: ats api change 2013-03-25 14:23 wachs * [r26597] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h: ATS manipulation 2013-03-25 09:41 wachs * [r26592] src/fs/gnunet-service-fs_cp.c: doxygen 2013-03-25 09:41 wachs * [r26591] src/ats/ats_api_performance.c, src/core/gnunet-service-core_neighbours.c, src/include/gnunet_ats_service.h, src/include/gnunet_transport_plugin.h, src/testbed/gnunet-service-testbed_cache.c, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport.h, src/transport/gnunet-service-transport_manipulation.c: doxygen 2013-03-25 09:40 wachs * [r26590] src/hostlist/gnunet-daemon-hostlist.c, src/transport/gnunet-service-transport_blacklist.c, src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_manipulation.h: doxygen 2013-03-25 09:39 wachs * [r26589] src/core/test_core_api.c, src/core/test_core_api_reliability.c: ftb 2013-03-22 17:29 harsha * [r26578] src/testbed/gnunet-helper-testbed.c: fix: 2839 2013-03-22 17:02 cfuchs * [r26577] src/Makefile.am, src/exit/Makefile.am, src/exit/gnunet-helper-exit-windows.c, src/vpn/gnunet-helper-vpn-windows.c: * added vpn and exit to the default build options for mingw/windows builds. This code is considered experimental and has not yet undergone intensive testing. Use it at your own peril, but we would still be really glad for feedback and bug reports! (thanks!) * fixed a typo in the exit-makefile (buildflags) * adjusted output of gnunet-helper-exit-windows to properly identify itself * updated driver-paths for looking for tap32/tap64 2013-03-22 15:51 cfuchs * [r26574] contrib/Makefile.am, contrib/openvpn-tap32/tapw32, contrib/openvpn-tap32/tapw32/OemWin2k.inf, contrib/openvpn-tap32/tapw32/tap0901.cat, contrib/openvpn-tap32/tapw32/tap0901.sys, contrib/openvpn-tap32/tapw64, contrib/openvpn-tap32/tapw64/OemWin2k.inf, contrib/openvpn-tap32/tapw64/tap0901.cat, contrib/openvpn-tap32/tapw64/tap0901.sys: added 32 and 64bit tapw32 drivers for exit and vpn helpers in windows 2013-03-22 15:50 wachs * [r26573] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport.h, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/test_plugin_transport.c: fixing ATS data 2013-03-22 14:53 wachs * [r26572] src/topology/gnunet-daemon-topology.c: fix 2013-03-22 11:08 wachs * [r26570] src/util/test_strings_to_data.c: more check 2013-03-22 11:01 wachs * [r26569] src/util/Makefile.am, src/util/test_strings_to_data.c: failing test 2013-03-22 09:09 wachs * [r26566] src/dv/gnunet-service-dv.c: fix 2013-03-22 08:25 wachs * [r26564] src/nse/gnunet-service-nse.c: fix 2013-03-22 06:07 LRN * [r26563] contrib/buildslave-0.8.5-gnunet-w32.patch: Fix the buildslave patch 2013-03-21 17:27 cfuchs * [r26562] src/exit/gnunet-helper-exit-windows.c, src/vpn/gnunet-helper-vpn-windows.c: * fixed incorrect doxygen commant fields in exit and vpn-helper-windows 2013-03-21 17:16 cfuchs * [r26561] src/exit/gnunet-helper-exit-windows.c: * adde ipv6 forwarding functionality for helper-exit-windows 2013-03-21 16:44 cfuchs * [r26559] src/exit/gnunet-daemon-exit.c, src/exit/gnunet-helper-exit-windows.c, src/exit/gnunet-helper-exit.c: * replaced no-nat delimiter which was % (reserved char on windows) with - for exit-helper-windows and exit-helper. * added ipv4 NAPT and removal functionality to exit-helper-windows * moved a few variables * next todo: ipv6 forwarding rules for netsh 2013-03-21 15:26 wachs * [r26557] src/fs/gnunet-service-fs.c, src/fs/gnunet-service-fs_cp.c: fs using ats data 2013-03-21 15:18 wachs * [r26556] src/peerinfo/test_peerinfo_api.c: fix 2013-03-21 15:02 wachs * [r26555] src/nse/gnunet-service-nse.c, src/testbed/gnunet-service-testbed_cache.c, src/topology/gnunet-daemon-topology.c: fixes 2013-03-21 14:57 wachs * [r26554] src/mesh/gnunet-service-mesh-new.c, src/mesh/gnunet-service-mesh.c: fix core api 2013-03-21 14:51 wachs * [r26552] src/integration-tests/connection_watchdog.c: api change 2013-03-21 14:49 wachs * [r26551] src/hostlist/gnunet-daemon-hostlist.c, src/hostlist/hostlist-client.c, src/hostlist/hostlist-server.c, src/hostlist/test_gnunet_daemon_hostlist.c, src/hostlist/test_gnunet_daemon_hostlist_learning.c, src/hostlist/test_gnunet_daemon_hostlist_reconnect.c: fix core api changes 2013-03-21 14:43 wachs * [r26548] src/chat/gnunet-service-chat.c, src/core/core_api.c, src/core/core_api_is_connected.c, src/core/core_api_iterate_peers.c, src/core/gnunet-core.c, src/core/test_core_api.c, src/core/test_core_api_reliability.c, src/core/test_core_api_send_to_self.c, src/core/test_core_api_start_only.c, src/core/test_core_quota_compliance.c, src/dht/gnunet-service-dht_neighbours.c, src/fs/gnunet-service-fs.c, src/fs/gnunet-service-fs_cp.c, src/fs/gnunet-service-fs_cp.h, src/include/gnunet_core_service.h: change to core pai 2013-03-21 14:08 wachs * [r26545] src/include/gnunet_transport_service.h, src/transport/gnunet-transport.c, src/transport/test_quota_compliance.c, src/transport/test_transport_api.c, src/transport/test_transport_api_bidirectional_connect.c, src/transport/test_transport_api_blacklisting.c, src/transport/test_transport_api_disconnect.c, src/transport/test_transport_api_limited_sockets.c, src/transport/test_transport_api_manipulation_recv_tcp.c, src/transport/test_transport_api_manipulation_send_tcp.c, src/transport/test_transport_api_reliability.c, src/transport/test_transport_api_restart_1peer.c, src/transport/test_transport_api_restart_2peers.c, src/transport/test_transport_api_timeout.c, src/transport/test_transport_api_unreliability.c, src/transport/test_transport_api_unreliability_constant.c, src/transport/test_transport_startonly.c, src/transport/test_transport_testing.c, src/transport/transport-testing.c, src/transport/transport_api.c: api fix 2013-03-21 14:08 wachs * [r26544] src/testbed/gnunet-service-testbed_cache.c: fix 2013-03-21 14:06 wachs * [r26543] src/core/gnunet-service-core_neighbours.c: fix 2013-03-21 13:45 wachs * [r26541] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_blacklist.c, src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_neighbours.h, src/transport/test_transport_startonly.c, src/transport/transport.h, src/transport/transport_api.c: changes to connect_cb 2013-03-21 13:33 wachs * [r26540] src/transport/test_transport_testing.c: fix test 2013-03-21 13:31 wachs * [r26539] src/include/gnunet_transport_service.h: changes 2013-03-21 13:31 wachs * [r26538] src/core/core.h, src/core/core_api.c, src/core/core_api_is_connected.c, src/core/core_api_iterate_peers.c, src/core/gnunet-service-core_clients.c, src/core/gnunet-service-core_clients.h, src/core/gnunet-service-core_kx.c, src/core/gnunet-service-core_kx.h, src/core/gnunet-service-core_neighbours.c, src/core/gnunet-service-core_sessions.c: ats related changes in core 2013-03-21 13:30 wachs * [r26537] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_neighbours.h, src/transport/gnunet-transport.c, src/transport/transport-testing.c, src/transport/transport.h, src/transport/transport_api.c: ats related changes in transport 2013-03-21 12:33 wachs * [r26535] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_neighbours.h: removing ats 2013-03-21 12:09 wachs * [r26534] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h: ats manipulation 2013-03-21 11:01 wachs * [r26533] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h: ats manipulation 2013-03-21 01:53 dold * [r26529] src/consensus/gnunet-service-consensus.c: fix 2013-03-21 01:39 dold * [r26528] src/consensus/gnunet-service-consensus.c: fix 2013-03-21 01:27 dold * [r26527] src/consensus/gnunet-service-consensus.c: fix 2013-03-21 01:06 dold * [r26526] src/consensus/consensus_flout.h, src/consensus/consensus_protocol.h, src/consensus/gnunet-consensus-ibf.c, src/consensus/gnunet-consensus.c, src/consensus/gnunet-service-consensus.c, src/consensus/ibf.c, src/consensus/ibf.h, src/consensus/test_consensus.conf, src/include/gnunet_container_lib.h: fixed consensus multi-peer communication, memory leaks, various bugs 2013-03-20 19:15 LRN * [r26525] src/util/network.c: Fix warnings and fix/improve logging in network.c 2013-03-20 18:50 LRN * [r26524] src/arm/arm_api.c, src/arm/arm_monitor_api.c, src/arm/gnunet-arm.c, src/arm/test_arm_api.c, src/arm/test_exponential_backoff.c, src/arm/test_gnunet_service_arm.c, src/include/gnunet_arm_service.h, src/regex/gnunet-regex-profiler.c: Simplify ARM alloc/connect 2013-03-20 18:50 LRN * [r26523] src/arm/arm_api.c, src/arm/gnunet-arm.c, src/arm/test_arm_api.c, src/arm/test_exponential_backoff.c, src/arm/test_gnunet_service_arm.c, src/include/gnunet_arm_service.h, src/regex/gnunet-regex-profiler.c: disconnect -> disconnect_and_free rename 2013-03-20 16:15 wachs * [r26522] src/ats/test_ats_api_performance_monitor.c: return 2013-03-20 12:37 wachs * [r26513] src/ats/ats_api_performance.c, src/ats/gnunet-service-ats_performance.c, src/ats/test_ats_api_performance_monitor.c: test 2013-03-20 09:33 wachs * [r26507] src/ats/ats_api_performance.c, src/ats/gnunet-service-ats_performance.c, src/ats/test_ats_api_performance_monitor.c: initial cb 2013-03-20 09:13 wachs * [r26506] src/ats/gnunet-service-ats_performance.c, src/ats/test_ats_api_performance_monitor.c: changes 2013-03-20 08:17 wachs * [r26504] src/ats/ats_api_performance.c: mod 2013-03-20 08:14 wachs * [r26503] src/transport/gnunet-service-transport_manipulation.c: fixed delay manipulation 2013-03-19 16:48 wachs * [r26502] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_performance.c: changes 2013-03-19 16:34 dold * [r26501] src/consensus/gnunet-service-consensus.c, src/consensus/test_consensus.conf: fix for for multi-peer consensus, non-power-of-two consensus now works 2013-03-19 14:53 wachs * [r26499] src/ats/gnunet-service-ats_performance.c, src/ats/test_ats_api_performance_monitor.c: changes 2013-03-19 14:06 LRN * [r26495] contrib/buildslave-0.8.5-gnunet-w32.patch: A buildslave patch for our W32 slaves * Safe process termination * Use BUILDSLAVE_SHELL, if defined, to run commands (Define it to something like %SLAVEDIR%/dir-where-msys-is/bin/sh.exe --login -c to be able to configure buildmaster with POSIX shell commands for all platforms) * Use temporary script files to change current directory when running MSYS 2013-03-19 12:58 wachs * [r26492] src/ats/gnunet-service-ats_performance.c, src/ats/gnunet-service-ats_performance.h: changes 2013-03-19 12:21 wachs * [r26491] src/ats/gnunet-service-ats_performance.c: changes 2013-03-19 11:56 wachs * [r26489] src/ats/ats_api_scheduling.c: remove break until fixeremove break until fixedd 2013-03-19 11:01 wachs * [r26488] src/include/gnunet_protocols.h: commit 2013-03-19 11:01 wachs * [r26487] src/ats/ats.h, src/ats/ats_api_performance.c, src/ats/gnunet-service-ats.c, src/ats/gnunet-service-ats_performance.c, src/ats/gnunet-service-ats_performance.h, src/ats/test_ats_api_performance_monitor.c: pre lunch commit 2013-03-19 10:05 wachs * [r26486] src/ats/Makefile.am, src/ats/test_ats_api_performance_monitor.c: test 2013-03-19 10:04 wachs * [r26485] src/ats/ats_api_performance.c, src/include/gnunet_ats_service.h: performance monitor API + rename 2013-03-19 09:33 wachs * [r26483] src/dv/plugin_transport_dv.c: dv plugin 2013-03-19 02:09 dold * [r26482] src/consensus/consensus.h, src/consensus/consensus_api.c, src/consensus/consensus_protocol.h, src/consensus/gnunet-consensus.c, src/consensus/gnunet-service-consensus.c, src/consensus/ibf.c, src/dv/gnunet-service-dv.c, src/include/gnunet_consensus_service.h, src/include/gnunet_protocols.h: fixed consensus for two peers, added log-rounds, started implementing freeze, multiple peers still buggy 2013-03-18 17:03 harsha * [r26480] src/nse/gnunet-nse-profiler.c: use testbed helper functions and lose old code 2013-03-18 16:10 wachs * [r26479] src/include/gnunet_transport_plugin.h, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport.h, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h, src/transport/gnunet-service-transport_plugins.c, src/transport/gnunet-service-transport_plugins.h, src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_udp_broadcasting.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c, src/transport/test_plugin_transport.c: transport plugin api change: split of address receive and ats updates 2013-03-18 13:11 harsha * [r26474] src/include/gnunet_testbed_service.h, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_2peers_1controller.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/test_testbed_api_testbed_run.c, src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_services.c, src/testbed/testbed_api_testbed.c: expose Operation and associated closure in every event 2013-03-15 16:09 wachs * [r26464] src/transport/plugin_transport_tcp.c: unused 2013-03-15 14:27 wachs * [r26462] src/include/gnunet_transport_service.h: clean up 2013-03-15 14:27 wachs * [r26461] src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h, src/transport/test_transport_api_manipulation_recv_tcp.c, src/transport/test_transport_api_manipulation_send_tcp.c, src/transport/transport_api.c: clean up 2013-03-15 14:00 wachs * [r26460] src/transport/gnunet-service-transport_manipulation.c: unused 2013-03-15 13:42 wachs * [r26459] src/transport/gnunet-service-transport_manipulation.c: changes 2013-03-15 12:34 wachs * [r26456] src/transport/gnunet-service-transport_manipulation.c, src/transport/plugin_transport_tcp.c: manipulation recv side 2013-03-15 09:53 wachs * [r26443] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h: changes to manipulation 2013-03-15 09:37 harsha * [r26441] src/include/gnunet_testbed_service.h, src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_test_timeout.c, src/testbed/test_testbed_api_test_timeout.conf, src/testbed/testbed.conf.in, src/testbed/testbed_api_testbed.c: Call TestMaster callback upon timeout set through configuration fixes #2833 2013-03-15 09:07 wachs * [r26439] src/include/gnunet_transport_service.h, src/transport/gnunet-transport.c, src/transport/transport_api.c: doxygen 2013-03-15 09:01 wachs * [r26438] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_simplistic.c: doxygen 2013-03-15 07:05 LRN * [r26434] src/arm/gnunet-arm.c, src/arm/gnunet-service-arm.c, src/include/gnunet_disk_lib.h, src/util/pseudonym.c: Docfixes 2013-03-14 12:06 cfuchs * [r26418] contrib/ssh-keys: added my ssh public-key 2013-03-14 06:52 LRN * [r26414] src/arm/gnunet-arm.c: Correct %s in some cases 2013-03-14 06:49 LRN * [r26413] src/arm/gnunet-service-arm.c: Use correct size for messages. Again. D'oh. 2013-03-14 06:49 LRN * [r26412] src/util/server.c: Do log messages with wrong size 2013-03-13 21:17 LRN * [r26408] src/arm/gnunet-arm.c: Continue processing after listing services 2013-03-13 21:01 LRN * [r26407] src/arm/test_gnunet_service_arm.c: Modify one of the tests to check service list 2013-03-13 21:01 LRN * [r26406] src/arm/gnunet-service-arm.c: Fix arm service message handler declaration 2013-03-13 21:01 LRN * [r26405] src/arm/gnunet-service-arm.c: Use correct argument for receive_done 2013-03-13 19:50 LRN * [r26404] src/arm/gnunet-service-arm.c: Receive_done in monitor hanlding 2013-03-13 18:03 LRN * [r26403] src/arm/arm_monitor_api.c: Forgot to add the file... 2013-03-13 17:49 LRN * [r26402] src/arm/Makefile.am, src/arm/arm.h, src/arm/arm_api.c, src/arm/gnunet-arm.c, src/arm/gnunet-service-arm.c, src/arm/mockup-service.c, src/arm/test_arm_api.c, src/arm/test_exponential_backoff.c, src/arm/test_gnunet_service_arm.c, src/include/gnunet_arm_service.h, src/include/gnunet_protocols.h, src/include/gnunet_server_lib.h, src/regex/gnunet-regex-profiler.c, src/regex/regex_test_lib.c, src/util/client.c, src/util/connection.c, src/util/server.c: All-encompassing ARM update 2013-03-13 17:49 LRN * [r26401] src/arm/arm_api.c: Correctly destroy OS_Process (cosmetic fix) 2013-03-13 10:51 harsha * [r26395] src/include/gnunet_testbed_service.h, src/testbed/Makefile.am, src/testbed/test_testbed_api_statistics.conf, src/testbed/testbed_api.c, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h, src/testbed/testbed_api_statistics.c, src/testbed/testbed_api_testbed.c: Implement GNUNET_TESTBED_get_statistics() - resolves #2662 Test case for testing GNUNET_TESTBED_get_statistics() Fix waiting for SHUTDOWN_PEERS reply when controller crashes 2013-03-12 13:49 wachs * [r26391] src/ats/gnunet-service-ats_addresses_mlp.c: disable output 2013-03-11 16:02 wachs * [r26385] src/ats/perf_ats_mlp.c: perf test done /w update 2013-03-11 15:37 bartpolot * [r26384] src/dht/gnunet-service-dht_neighbours.c: BLOCK_EVALUATE regex PUT messages - reorder debug info for easier following 2013-03-11 14:46 wachs * [r26380] src/ats/perf_ats_mlp.c: implemented ats info updates + initial address update (fixing issue of execution time peaks) 2013-03-11 13:23 wachs * [r26377] src/ats/perf_ats_mlp.c: updating addresses 2013-03-08 16:37 wachs * [r26370] src/core/gnunet-service-core_neighbours.c: fix cast 2013-03-08 15:10 wachs * [r26363] src/ats/gnunet-service-ats_addresses_mlp.c: address specific names 2013-03-08 15:01 wachs * [r26362] src/ats/perf_ats_mlp.c: changes 2013-03-08 14:51 wachs * [r26361] src/ats/test_ats_mlp.c: test should not dump 2013-03-08 14:26 wachs * [r26360] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/test_ats_mlp.c: writing solutions and MPS dumps 2013-03-08 10:22 harsha * [r26356] src/include/gnunet_protocols.h, src/include/gnunet_testbed_service.h, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h: testbed API function to shutdown (stop + destroy) all peers. Client side functionality only. 2013-03-07 14:12 dold * [r26350] src/consensus/consensus_api.c, src/consensus/consensus_protocol.h, src/consensus/gnunet-consensus-ibf.c, src/consensus/gnunet-consensus.c, src/consensus/gnunet-service-consensus.c, src/consensus/ibf.c, src/consensus/ibf.h, src/include/gnunet_consensus_service.h, src/include/gnunet_protocols.h: consensus now implemented with primitive conclusion group selection 2013-03-06 17:24 bartpolot * [r26343] src/dht/gnunet-service-dht_neighbours.c: fix 2013-03-06 15:17 harsha * [r26340] src/testbed/gnunet-helper-testbed.c, src/testbed/test_gnunet_helper_testbed.c: Don't call gnunet scheduler from signal handler. Instead, write to a pipe (ARM-style) to run a scheduler task when signal is received. 2013-03-06 12:47 harsha * [r26337] src/testbed/gnunet_testbed_mpi_spawn.c: clean the lock file 2013-03-06 11:02 harsha * [r26334] contrib/testbed_infiniband.conf, contrib/testbed_supermuc.conf: SuperMUC testbed config 2013-03-06 10:52 harsha * [r26333] src/testbed/gnunet_testbed_mpi_spawn.c: Remove MPI code Starts the child process only in one instance (checks for lowest host ip; and that host ensures all instances co-ordinate via explicit lock file creation) Implemented basic ARM-like functionality for dealing with child processes 2013-03-06 08:40 wachs * [r26331] src/transport/gnunet-service-transport_validation.c: print warning only on failure 2013-03-06 08:22 LRN * [r26328] src/include/gnunet_pseudonym_lib.h, src/util/pseudonym.c: Pseudonym-removal function 2013-03-06 03:37 LRN * [r26327] src/testbed/Makefile.am: Correct testbed dependencies 2013-03-05 16:10 grothoff * [r26326] src/fs/Makefile.am, src/fs/fs.h, src/fs/fs_api.h, src/fs/fs_namespace.c, src/fs/fs_namespace_advertise.c, src/fs/fs_publish_ksk.c, src/fs/fs_search.c, src/fs/fs_unindex.c, src/fs/fs_uri.c, src/fs/gnunet-pseudonym.c, src/fs/gnunet-service-fs.c, src/fs/gnunet-service-fs.h, src/fs/gnunet-service-fs_cp.c, src/fs/gnunet-service-fs_lc.c, src/fs/gnunet-service-fs_pr.c, src/fs/gnunet-service-fs_pr.h, src/fs/gnunet-service-fs_put.c, src/fs/plugin_block_fs.c, src/fs/test_fs_namespace.c, src/fs/test_fs_uri.c, src/include/block_fs.h, src/include/gnunet_block_lib.h, src/include/gnunet_fs_service.h, src/include/gnunet_pseudonym_lib.h, src/include/gnunet_signatures.h, src/util/pseudonym.c, src/util/strings.c, src/util/test_pseudonym.c: starting major change towards implementing #2564, this breaks some FS tests and FS APIs 2013-03-05 13:40 wachs * [r26322] src/transport/gnunet-service-transport_validation.c: changes 2013-03-05 12:38 harsha * [r26319] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed_oc.c: be verbose while sending error message instead of emitting a warning 2013-03-04 20:33 LRN * [r26312] src/include/gnunet_crypto_lib.h: Increase GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH 2013-03-04 15:25 wachs * [r26310] src/transport/gnunet-service-transport_validation.c: disable message 2013-03-04 14:50 wachs * [r26308] src/transport/gnunet-service-transport_validation.c: error msg 2013-03-04 14:50 wachs * [r26307] src/transport/gnunet-service-transport_validation.c: validation fast start and throttling 2013-03-04 14:24 harsha * [r26300] src/include/gnunet_testing_lib.h, src/testing/testing.c: cache peer identities 2013-03-04 14:09 grothoff * [r26299] src/gns/gns.conf.in, src/include/gnunet_crypto_lib.h, src/testing/testing.c, src/util/crypto_ecc.c: add argument to GNUNET_CRYPTO_ecc_decode_key to allow testing to disable key validation 2013-03-04 13:19 wachs * [r26295] src/transport/gnunet-service-transport_validation.c: implementing pong singature caching 2013-03-04 08:28 LRN * [r26290] src/util/strings.c, src/util/test_strings.c: Accept time strings where number and unit are not separated by a space Fixes #2806 2013-03-04 02:42 grothoff * [r26282] doc/man/gnunet-peerinfo.1: fix #2811 - missing options in gnunet-peerinfo man page 2013-03-04 01:20 LRN * [r26281] src/fs/fs_namespace_advertise.c, src/include/gnunet_fs_service.h: Implement GNUNET_FS_namespace_insert_advertisement_into_metadata 2013-03-04 01:20 LRN * [r26280] src/fs/fs_uri.c: Add error messages to GNUNET_FS_uri_sks_create 2013-03-03 11:33 LRN * [r26271] src/fs/fs_namespace.c, src/include/gnunet_fs_service.h: Make 2nd and 3rd arguments of GNUNET_FS_namespace_rename constant pointers 2013-03-03 08:14 grothoff * [r26268] src/core/gnunet-service-core_kx.c, src/core/gnunet-service-core_sessions.c, src/core/gnunet-service-core_typemap.c: reduce messages in initial KX 2013-03-03 01:57 LRN * [r26265] src/fs/fs_namespace.c, src/include/gnunet_fs_service.h: GNUNET_FS_namespace_rename 2013-03-03 01:57 LRN * [r26264] src/fs/fs_namespace.c, src/include/gnunet_fs_service.h: Be able to open existing namespaces 2013-03-03 01:57 LRN * [r26263] src/include/gnunet_crypto_lib.h, src/util/crypto_rsa.c: Be able to only-read-not-create RSA keys 2013-03-03 01:57 LRN * [r26262] src/fs/fs_namespace.c, src/fs/fs_uri.c, src/include/gnunet_fs_service.h: Implement and use GNUNET_FS_namespace_get_public_key_hash 2013-03-03 01:57 LRN * [r26261] src/fs/fs_namespace.c, src/fs/fs_search.c, src/fs/fs_unindex.c, src/include/gnunet_crypto_lib.h, src/util/crypto_rsa.c: Implement and use GNUNET_CRYPTO_rsa_get_public_key_hash 2013-03-02 22:40 grothoff * [r26260] src/core/gnunet-service-core_kx.c: do not verify an ephemeral key again if it is the same as the previous key 2013-03-02 22:19 grothoff * [r26259] src/core/core.conf.in, src/core/gnunet-service-core_kx.c: adding option to disable use of ephemeral keys for HPC testing 2013-03-01 14:32 harsha * [r26250] src/testbed/gnunet_testbed_mpi_spawn.c: finish off with MPI before spawning 2013-03-01 12:47 bartpolot * [r26246] src/dht/gnunet-service-dht_neighbours.c: Remove CORE corking from DHT traffic 2013-03-01 06:55 LRN * [r26242] src/util/os_priority.c: Silence a warning 2013-02-28 13:28 harsha * [r26231] contrib/testbed_setup_pre_ecc_tree.sh: update configure.ac to HEAD 2013-02-28 11:55 harsha * [r26230] src/testbed/gnunet_testbed_mpi_spawn.c: not using GNUNET_PROGRAM_run() as it is eating away the trailing command arguments 2013-02-28 10:09 wachs * [r26229] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: changes 2013-02-27 23:13 LRN * [r26228] src/fs/test_fs_namespace.c: NS test: Use different URIs for different phases 2013-02-27 21:24 harsha * [r26227] configure.ac: define WITH_LL only if libllapi is found 2013-02-27 17:23 harsha * [r26223] src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed_api_testbed.c: get hosts from loadleveler instead of reading them from hostlist 2013-02-27 17:05 harsha * [r26222] src/testbed/testbed_api_hosts.c: GNUNET_TESTBED_hosts_load_from_loadleveler() function available only when --with-ll is specified 2013-02-27 16:58 harsha * [r26221] contrib/testbed_setup_pre_ecc_tree.sh: script to prepare tree for pre-ecc testbed compilation 2013-02-27 16:46 harsha * [r26220] src/include/gnunet_protocols.h: reverting back to the previous working version 2013-02-27 16:43 harsha * [r26219] src/include/gnunet_protocols.h: version to make updated testbed compile with pre-ecc age code. 2013-02-27 16:39 wachs * [r26218] src/ats/gnunet-service-ats_addresses_mlp.c: switching networks 2013-02-27 16:10 wachs * [r26217] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_mlp_update.c: quality update 2013-02-27 15:04 wachs * [r26216] src/ats/gnunet-service-ats_addresses_mlp.c: quality update 2013-02-27 14:22 harsha * [r26215] src/include/gnunet_testbed_service.h, src/testbed/gnunet_testbed_mpi_spawn.c, src/testbed/testbed_api_hosts.c: Parsing LoadLeveler allocated hosts and creating testbed hosts from them 2013-02-27 14:12 wachs * [r26214] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_mlp_update.c: changes 2013-02-27 13:43 harsha * [r26213] src/testbed/Makefile.am, src/testbed/gnunet_testbed_mpi_spawn.c: checkpoint save 2013-02-27 13:43 wachs * [r26212] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_mlp_update.c: new test 2013-02-27 09:59 wachs * [r26211] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: changes 2013-02-26 15:26 wachs * [r26209] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/perf_ats_mlp.c: changes 2013-02-26 15:07 wachs * [r26208] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/perf_ats_mlp.c: performance analysis 2013-02-26 13:31 wachs * [r26207] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp.conf: perf 2013-02-26 09:04 wachs * [r26206] src/ats/test_ats_mlp.c: fix for test 2013-02-25 16:27 wachs * [r26205] src/ats/Makefile.am, src/ats/perf_ats_mlp.c: changes to perf 2013-02-25 15:51 wachs * [r26204] src/ats/test_ats_mlp.c: memory leak 2013-02-25 15:38 wachs * [r26203] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_mlp.c: changes 2013-02-25 14:58 wachs * [r26202] src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/test_ats_mlp.c: old code 2013-02-25 14:53 wachs * [r26201] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: code cleanup + api extension 2013-02-25 13:08 wachs * [r26200] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_mlp.c: fixes 2013-02-25 10:43 wachs * [r26199] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_mlp.c: fixes 2013-02-25 10:02 wachs * [r26198] src/ats/gnunet-service-ats_addresses_mlp.c: changes 2013-02-22 16:24 wachs * [r26196] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: modifications 2013-02-22 15:45 wachs * [r26195] src/ats/gnunet-service-ats_addresses_mlp.c: create constrain function 2013-02-22 15:36 wachs * [r26194] src/ats/gnunet-service-ats_addresses_mlp.c: simplify 2013-02-22 15:21 wachs * [r26193] src/ats/gnunet-service-ats_addresses_mlp.c: simplyfiying code 2013-02-22 14:53 harsha * [r26192] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed.h, src/testbed/gnunet-service-testbed_oc.c, src/testbed/testbed_api.c: Use a sub operation while forwarding controller link operations. This helps to propagate the change in a host's configuration along the controller tree's branch back to root. 2013-02-22 14:37 wachs * [r26191] src/ats/gnunet-service-ats_addresses_mlp.c: changes 2013-02-22 14:28 wachs * [r26190] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: create set_value function 2013-02-22 14:17 wachs * [r26189] src/ats/gnunet-service-ats_addresses_mlp.c: changes 2013-02-22 13:32 wachs * [r26188] src/ats/gnunet-service-ats_addresses_mlp.c: implementing restructured problem creation 2013-02-22 08:47 wachs * [r26186] src/ats/test_ats_api_common.c, src/ats/test_ats_api_common.h, src/ats/test_ats_simplistic_pref_aging.c: fix test 2013-02-21 17:06 harsha * [r26182] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed.h, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h: send configurations of newly started slave controllers as part of controller link operations 2013-02-21 15:50 wachs * [r26180] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: auto_solve 2013-02-21 15:12 wachs * [r26179] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: result propagation 2013-02-21 14:38 wachs * [r26178] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: changes 2013-02-21 14:20 harsha * [r26177] src/testbed/testbed_api_hosts.c: host locking; warn upon API violation 2013-02-21 13:18 wachs * [r26176] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: refactoring 2013-02-21 12:14 wachs * [r26174] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: changes 2013-02-21 11:32 harsha * [r26173] src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h: M testbed/testbed.h naming consistency include uncompressed config size M testbed/testbed_api_hosts.c pulled host registration functions from testbed_api.c M testbed/testbed_api_hosts.h export handler to handle ADD_HOST confirmation messages M testbed/gnunet-service-testbed.c parse the modified ADD_HOST message M testbed/testbed_api.c lose host registration code extract configuration from ADD_HOST messages M testbed/testbed_api.h include hacks 2013-02-21 10:51 wachs * [r26172] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp_averaging.c: clean up of MLP_Handle 2013-02-20 17:53 wachs * [r26169] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: changes 2013-02-20 16:24 wachs * [r26168] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/test_ats_mlp.c: changes 2013-02-20 15:15 harsha * [r26167] contrib/testbed_infiniband.conf, src/include/gnunet_testbed_service.h, src/nse/gnunet-nse-profiler.c, src/regex/gnunet-regex-profiler.c, src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_2peers_1controller.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h, src/testbed/testbed_api_testbed.c: Assosiate a configuration template while creating hosts. This paves a way to manage the configurations of controllers running on a host automatically. modified ADD_HOST message structure to have host configuration. This feature is yet to be implemented. The idea is that GNUNET_TESTBED_link_controllers() should take no configuration when hosts automatically update configuration when a new configuration is generated from a template. 2013-02-20 13:20 wachs * [r26166] src/ats/gnunet-service-ats_addresses_mlp.c: changes 2013-02-19 16:46 wachs * [r26162] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_mlp.c: changes 2013-02-19 15:37 wachs * [r26161] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_mlp.c: changes 2013-02-19 13:39 wachs * [r26160] src/ats/gnunet-service-ats_addresses_mlp.c: documentation 2013-02-19 13:37 wachs * [r26159] src/ats/ats.conf.in, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp.conf: changes 2013-02-19 12:52 wachs * [r26158] src/ats/Makefile.am, src/ats/ats.conf.in, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/test_ats_api_common.h, src/ats/test_ats_mlp.c: refactoring and renaming 2013-02-19 09:31 wachs * [r26157] src/ats/test_ats_mlp.c: test 2013-02-19 04:04 LRN * [r26156] src/fs/fs_namespace.c, src/fs/test_fs_namespace.c, src/include/gnunet_fs_service.h: Asynchronous namespace creation. With a test. 2013-02-19 04:04 LRN * [r26155] src/fs/fs_namespace.c: Don't generate namespace key files in the root dir... 2013-02-19 04:04 LRN * [r26154] configure.ac: Fix git version detection in configure (D'oh...) 2013-02-18 16:11 wachs * [r26152] src/ats/gnunet-service-ats_addresses_simplistic.c: docu 2013-02-18 15:39 wachs * [r26151] src/ats/gnunet-service-ats_addresses.c: docu 2013-02-18 15:07 wachs * [r26150] src/ats/gnunet-service-ats_addresses_simplistic.c: docu 2013-02-18 10:01 LRN * [r26148] src/util/os_priority.c: It's on stack... 2013-02-18 09:35 wachs * [r26147] src/peerinfo-tool/gnunet-peerinfo.c: does not terminate on invalid uri 2013-02-18 09:22 wachs * [r26146] src/peerinfo-tool/gnunet-peerinfo.c: memory corruption 2013-02-18 08:35 wachs * [r26145] src/util/crypto_ecc.c: break 2013-02-16 16:16 LRN * [r26144] src/util/os_priority.c: Make pipe sanity check work on W32 too 2013-02-15 16:06 wachs * [r26142] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/include/gnunet_ats_service.h, src/util/crypto_ecc.c: changes 2013-02-15 15:04 wachs * [r26141] src/ats/gnunet-service-ats_addresses.c: auto generation note 2013-02-15 14:30 harsha * [r26140] contrib/testbed_perfhacks.patch: Hacks to reduce per-peer load on CPU by increasing transport retransmission timeouts. This helps to keep the load on testbed node low. Thanks Bart! 2013-02-15 14:01 wachs * [r26139] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c: more docu 2013-02-15 13:05 wachs * [r26136] src/ats/gnunet-service-ats_addresses.c: docu 2013-02-15 12:12 wachs * [r26135] src/ats/gnunet-service-ats_addresses.c: docu 2013-02-15 11:21 LRN * [r26134] src/util/os_priority.c: Detect bad control pipes earlier 2013-02-15 10:51 wachs * [r26133] src/ats/gnunet-service-ats_addresses.c: docu 2013-02-15 10:49 wachs * [r26132] src/ats/gnunet-service-ats_addresses.c: docu 2013-02-15 10:32 wachs * [r26130] src/ats/gnunet-service-ats_addresses.c: more docu 2013-02-15 10:03 LRN * [r26129] src/util/os_priority.c: Try to fix process spawning 2013-02-15 09:52 wachs * [r26128] src/ats/gnunet-service-ats_addresses.c: docu 2013-02-15 09:47 LRN * [r26127] src/util/test_os_start_process.c: Another highly temporary fix to make os_start_process pass 2013-02-15 09:32 wachs * [r26126] src/ats/gnunet-service-ats_addresses.c: more docu 2013-02-15 09:23 wachs * [r26125] src/ats/gnunet-service-ats_addresses.c: docu 2013-02-15 09:18 wachs * [r26124] src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_simplistic_switch_networks.c: remove static function 2013-02-14 18:33 LRN * [r26122] src/util/test_os_start_process.c: Temporary fix to make test_os_start_process pass again 2013-02-14 17:20 LRN * [r26120] src/util/os_priority.c: Oops 2013-02-14 16:46 harsha * [r26119] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed.h, src/testbed/gnunet-service-testbed_oc.c, src/testbed/testbed.conf.in: fix 2793: Testbed does not allow to set TIMEOUT for operations 2013-02-14 16:15 LRN * [r26118] src/util/w32cat.c: Make w32cat pipe-controllable 2013-02-14 16:15 LRN * [r26117] src/util/disk.c, src/util/os_priority.c: Use passed-by-fd pipe to control chilren Removes npipe_*() functions. Uses normal GNUnet pipe for child control (the pipe is anonymous on *nix, named-with-unique-name on W32). Also tighten W32 code (close pipes correctly on errors). Remove some FIXME NILS comments. Convert #if MINGW -> #if defined (WINDOWS) in some places. Better start_process() debug logging on W32 2013-02-14 16:15 LRN * [r26116] src/util/disk.c: Minimal W32 version to XP, use uniqueness flag 2013-02-14 16:15 LRN * [r26115] src/include/gnunet_disk_lib.h, src/util/disk.c: More flexible native->GNUnet_handle file opening Can now open not just FILEs, but also integer fds and native Windows handles. The last two will be used later by the new pipe control code. 2013-02-14 16:15 LRN * [r26114] src/util/disk.c: Fix file close to work on pipe ends correctly 2013-02-14 16:15 LRN * [r26113] src/include/gnunet_disk_lib.h, src/util/disk.c: Make pipe ends detachable, fix W32 corner-cases Now pipe ends are fully-functional FileHandles. You can detach them from the pipe, and closing pipe will not affect them afterwards. Tightened W32 implementation (make it close events!) 2013-02-14 16:15 LRN * [r26112] src/util/os_priority.c: W32: Don't leak stdin/stdout when spawning If stdin/stdout pipe is provided by us, AND we tell start_process() to pass along our own current stdin/stdout, our current stdin/stdout will be leaked to the child (child will have a copy, but won't know about it). 2013-02-14 15:01 wachs * [r26110] src/hostlist/hostlist-client.c: change to WARNING 2013-02-14 14:39 wachs * [r26107] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.h: docu 2013-02-14 13:36 wachs * [r26106] src/ats/test_ats_mlp.c: mod test 2013-02-14 13:28 wachs * [r26105] src/ats/test_ats_api_common.c, src/ats/test_ats_api_common.h, src/ats/test_ats_mlp.c: mod 2013-02-14 12:42 wachs * [r26102] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_api_common.c, src/ats/test_ats_api_common.h, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp.conf: modifications 2013-02-14 12:33 harsha * [r26101] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h, src/testbed/testbed_api_peers.c: move parallel overlay connect operation queue from controller handle to host handle 2013-02-14 12:10 wachs * [r26100] src/ats/Makefile.am, src/ats/test_ats_mlp.c: active test 2013-02-14 12:06 wachs * [r26099] src/ats/test_ats_mlp.c: change in test 2013-02-14 12:05 wachs * [r26098] src/ats/Makefile.am, src/ats/test_ats_mlp.conf: new config file 2013-02-14 10:41 harsha * [r26097] src/testbed, src/testbed/Makefile.am, src/testbed/standard_deviation.c, src/testbed/test_testbed_api_sd.c, src/testbed/testbed_api.c, src/testbed/testbed_api.c.new, src/testbed/testbed_api_sd.c, src/testbed/testbed_api_sd.h: separate SD calculations 2013-02-14 10:34 wachs * [r26096] src/util/os_installation.c: fix for 0002797 2013-02-12 17:14 harsha * [r26081] src/testbed/testbed_api.c: fix 2780: Testbed doesn't clean up properly on error 2013-02-12 16:48 harsha * [r26079] src/include/gnunet_helper_lib.h, src/util/helper.c: stop helpers by closing stdin 2013-02-11 08:49 wachs * [r26062] src/transport/plugin_transport_http_client.c: hotfix for curl vulnerability: libcurl SASL buffer overflow vulnerability CVE-2013-0249 2013-02-05 20:49 grothoff * [r26035] NEWS, README, README.1st, src/core/Makefile.am, src/core/gnunet-service-core.c, src/core/gnunet-service-core_kx.c, src/core/gnunet-service-core_kx.h, src/core/gnunet-service-core_neighbours.c, src/hello/gnunet-hello.c, src/hello/hello.c, src/hello/test_hello.c, src/include/gnunet_crypto_lib.h, src/include/gnunet_hello_lib.h, src/include/gnunet_protocols.h, src/include/gnunet_signatures.h, src/include/gnunet_testing_lib.h, src/peerinfo-tool/gnunet-peerinfo.c, src/testing/gnunet-testing.c, src/testing/testing.c, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport.h, src/transport/gnunet-service-transport_hello.c, src/transport/gnunet-service-transport_hello.h, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_validation.c, src/transport/gnunet-service-transport_validation.h, src/transport/test_plugin_transport.c, src/util/crypto_aes.c, src/util/crypto_hash.c, src/util/gnunet-ecc.c, src/util/gnunet-rsa.c, src/util/test_crypto_aes.c, src/util/test_crypto_aes_weak.c: switching to ECDHE cryptography f, implementation is incomplete and INSECURE, do not use for anything but testing 2013-02-05 20:48 grothoff * [r26034] configure.ac, po/POTFILES.in, po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/arm/Makefile.am, src/mesh/Makefile.am, src/regex/Makefile.am, src/transport/Makefile.am: 095a 2013-02-05 16:06 wachs * [r26026] src/transport/gnunet-service-transport_manipulation.c, src/transport/test_transport_api_manipulation_recv_tcp.c, src/transport/test_transport_api_manipulation_send_tcp.c: documentation 2013-02-05 16:03 wachs * [r26025] src/transport/Makefile.am: extradist -This line, and those below, will be ignored-- M src/transport/Makefile.am 2013-02-05 16:02 wachs * [r26024] src/include/gnunet_transport_service.h, src/transport/transport_api.c: docu 2013-02-05 15:53 wachs * [r26023] src/transport/test_transport_api_manipulation_recv_tcp.c: new test 2013-02-05 15:50 wachs * [r26022] src/transport/gnunet-service-transport_manipulation.c, src/transport/test_transport_api_manipulation_send_tcp.c: fixes 2013-02-05 15:35 wachs * [r26021] src/transport/Makefile.am, src/transport/gnunet-service-transport_manipulation.c, src/transport/gnunet-service-transport_manipulation.h, src/transport/test_transport_api_manipulation.c, src/transport/test_transport_api_manipulation_recv_tcp_peer1.conf, src/transport/test_transport_api_manipulation_recv_tcp_peer2.conf, src/transport/test_transport_api_manipulation_send_tcp.c, src/transport/test_transport_api_manipulation_send_tcp_peer1.conf, src/transport/test_transport_api_manipulation_send_tcp_peer2.conf, src/transport/test_transport_api_manipulation_tcp_peer1.conf, src/transport/test_transport_api_manipulation_tcp_peer2.conf: traffic manipulation: receive delay 2013-02-05 14:39 wachs * [r26020] src/transport/test_transport_api_manipulation.c: delay sending implemented 2013-02-05 14:24 harsha * [r26019] src/gns/test_gns_dht_three_peers.c, src/include/gnunet_testbed_service.h, src/regex/gnunet-regex-profiler.c, src/testbed/test_testbed_api_topology.c, src/testbed/test_testbed_api_topology_clique.c, src/testbed/testbed_api_testbed.c, src/testbed/testbed_api_topology.c: add completion callback for overlay topology configure functions 2013-02-05 12:47 wachs * [r26016] src/include/gnunet_transport_service.h, src/transport/Makefile.am, src/transport/transport_api.c: last commit for metric 2013-02-05 12:46 wachs * [r26015] src/include/gnunet_protocols.h, src/transport/test_transport_api_manipulation_tcp_peer1.conf, src/transport/test_transport_api_manipulation_tcp_peer2.conf: more 2013-02-05 12:45 wachs * [r26014] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport.h, src/transport/transport.h: more metric 2013-02-05 12:44 wachs * [r26013] src/transport/gnunet-service-transport_clients.c, src/transport/test_transport_api_manipulation.c: transport metric manipulation 2013-02-04 16:54 wachs * [r26007] src/transport/plugin_transport_tcp.c: limit connection for tcp 2013-02-04 15:40 wachs * [r26003] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_neighbours.h, src/transport/gnunet-service-transport_validation.c, src/transport/gnunet-service-transport_validation.h, src/transport/transport.h: throttling validations 2013-02-04 15:34 wachs * [r26002] configure.ac: check for getrlimit 2013-02-04 10:52 wachs * [r26001] src/transport/gnunet-transport.c: implemented 0002773 2013-02-04 09:53 wachs * [r25997] src/ats/gnunet-service-ats_addresses.c: fix for 0002723 2013-02-04 09:34 wachs * [r25996] src/transport/gnunet-service-transport.c, src/transport/plugin_transport_tcp.c: check code for 0002774 2013-02-02 17:26 LRN * [r25988] src/util/container_meta_data.c: Discard large metadata items first 2013-02-02 17:26 LRN * [r25987] src/util/container_meta_data.c: Fix a memory leak in MD serializer 2013-02-02 17:25 LRN * [r25986] src/util/container_meta_data.c: Fix a buffer overflow 2013-02-02 17:25 LRN * [r25985] src/fs/gnunet-helper-fs-publish.c: Don't send more than 64k from fs helper 2013-02-01 12:49 harsha * [r25974] src/transport/transport_api.c: GNUNET_TRANSPORT_get_hello() to call its callback asynchronously 2013-01-31 14:15 cfuchs * [r25967] src/exit/gnunet-helper-exit-windows.c: re-enumated argv to conform with helper-exit syntax added stub for ipv4 nat. Note that there is a problem ahead! 2013-01-31 13:12 cfuchs * [r25966] src/exit/gnunet-helper-exit-windows.c, src/vpn/gnunet-helper-vpn-windows.c: added support for partial write to stdin/stdout. there seems to be no point in adding support for partial read from the TAP, as there is no delimiter and we get data on a per-frame level. 2013-01-31 12:32 cfuchs * [r25964] src/exit/gnunet-helper-exit-windows.c, src/vpn/gnunet-helper-vpn-windows.c: added support for partial reads from stdin 2013-01-31 10:41 cfuchs * [r25959] src/exit/gnunet-helper-exit-windows.c, src/vpn/gnunet-helper-vpn-windows.c: helper-vpn and helper-exit now are 64bit capabled. added check if we are running on a win32/wow64/win64 host system. 2013-01-31 09:45 grothoff * [r25956] src/vpn/vpn.conf.in: porting to W32 requires a port, yepee 2013-01-31 09:11 cfuchs * [r25954] src/exit/gnunet-helper-exit-windows.c, src/vpn/gnunet-helper-vpn-windows.c: some final code-beautification (coding style 4tw!) removed a few obsolete variables 2013-01-31 08:52 cfuchs * [r25953] src/exit/Makefile.am, src/exit/gnunet-helper-exit-windows.c: added gnunet-helper-exit-windows, which currently is just a copy of gnunet-helper-vpn-windows 2013-01-30 17:45 cfuchs * [r25952] src/vpn/gnunet-helper-vpn-windows.c: added nice debug output for gnunet-herlper-vpn-windows. 2013-01-30 15:54 grothoff * [r25947] src/fs/perf_gnunet_service_fs_p2p.c, src/fs/perf_gnunet_service_fs_p2p.conf, src/include/gnunet_network_lib.h, src/testbed/gnunet-service-testbed_hc.c: API extension, make blocking socket API visible 2013-01-30 15:06 harsha * [r25945] src/testbed/gnunet-service-testbed_hc.c: towards caching CORE handles 2013-01-30 13:38 harsha * [r25944] src/core/core_api.c, src/include/gnunet_core_service.h: function to synchronously check if a peer is connected at CORE level 2013-01-30 10:06 harsha * [r25938] src/testbed/gnunet-service-testbed.h, src/testbed/gnunet-service-testbed_hc.c, src/testbed/gnunet-service-testbed_oc.c: cache transport handles with peer connect notifications 2013-01-30 09:22 wachs * [r25937] src/include/gnunet_transport_service.h, src/transport/transport_api.c: forgot 2013-01-29 15:10 harsha * [r25933] src/testbed/gnunet-service-testbed_hc.c, src/testbed/gnunet-service-testbed_oc.c: caching transport handles 2013-01-26 14:27 harsha * [r25921] src/testbed/gnunet-service-testbed_oc.c: bound remote overlay connect operation execution to limited number of open file descriptors 2013-01-26 09:50 grothoff * [r25919] src/arm/gnunet-arm.c, src/arm/test_arm_api.c, src/arm/test_exponential_backoff.c, src/arm/test_gnunet_service_arm.c: LRN: Here's a patch. See if it doesn't break anything for you. Arm service is started with -c only when the process that runs arm service has "[arm]/CONFIG" defined in the configuration used to run arm service (usually - process' own configuration). Since default [arm] config has no CONFIG defined anymore (thanks to your r25908), we need to add this code to put the config file that was passed to gnunet-arm tool via -c as "[arm]/CONFIG" for arm service to receive it. Otherwise arm service is run without config and reads default config (~/.gnunet/gnunet.conf) instead, which is clearly not what we need. 2013-01-25 22:27 harsha * [r25918] po/POTFILES.in: fix 2746 2013-01-25 20:38 harsha * [r25917] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed.h, src/testbed/testbed.conf.in: read MAX_OPEN_FDS from configuration 2013-01-25 16:42 harsha * [r25913] src/testbed/gnunet-service-testbed_oc.c: bound overlay connect operation execution to limited number of open file descriptors 2013-01-25 16:02 grothoff * [r25907] src/arm/arm_api.c: start gnunet-service-arm nicely if configuration file does not exist 2013-01-25 15:22 grothoff * [r25904] src/exit/Makefile.am, src/exit/exit.conf, src/exit/gnunet-daemon-exit.c: add DNS exit for mesh to gnunet-daemon-exit 2013-01-25 15:22 grothoff * [r25903] src/dns/Makefile.am, src/dns/dns.conf.in, src/dns/gnunet-service-dns.c: remove DNS exit for mesh from gnunet-service-dns 2013-01-25 10:55 harsha * [r25892] src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed.h, src/testbed/gnunet-service-testbed_hc.c: separate hello cache as module 2013-01-24 17:01 harsha * [r25889] src/testbed/test_testbed_api_operations.c: test harder 2013-01-24 15:46 bartpolot * [r25886] src/mesh/Makefile.am, src/mesh/gnunet-daemon-regexprofiler.c, src/mesh/gnunet-regex-profiler.c, src/mesh/gnunet-service-mesh.c, src/regex, src/regex/Makefile.am, src/regex/gnunet-daemon-regexprofiler.c, src/regex/gnunet-regex-profiler.c: Moved regex profiler and profiler daemon from mesh to regex, adaped to regex dht lib 2013-01-24 13:54 cfuchs * [r25885] src/vpn/gnunet-helper-vpn-windows.c: re-fixed incorrect from last commit... :-D forgot to save. 2013-01-24 13:51 cfuchs * [r25884] src/vpn/gnunet-helper-vpn-windows.c: added debug logics to print to and read from STDIN, instead of from named pipes moved declaration of hdr outside of the ifs fixed an incorrect comparison introduced in last commit 2013-01-24 13:07 cfuchs * [r25883] src/vpn/gnunet-helper-vpn-windows.c: helper now always uses BOOL(winbool) instead of boolean to stay consistent attept_write now properly resets the read facility to IOSTATE_RESUME, in case read was stalled because write was busy 2013-01-24 12:49 cfuchs * [r25882] src/vpn/gnunet-helper-vpn-windows.c: added IOSTATE_RESUME and related code to state machines 2013-01-24 12:24 harsha * [r25881] src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h: operations now can explicitly register how many resources they require 2013-01-24 11:46 dold * [r25879] src/consensus/gnunet-consensus.c: fix 2013-01-24 08:51 cfuchs * [r25871] src/vpn/gnunet-helper-vpn-windows.c: added gnunet-header stripping and adding functionality woops logics bug discovered: when read goes into waiting, the output facility will not transfer the input buffer and forget about it silently... 2013-01-24 08:23 cfuchs * [r25870] src/vpn/gnunet-helper-vpn-windows.c: added ip-address remove functions newly set IP addresses now should expire upon reboot (buggy on some windows, but at least it solves the IP-persistence issues in win7 and above) cloned read functions to properly apply or strip the gnunet message header removed the status BOOL from the overlapped struct and made it local some fixes here and there added a lot of comments style adjustments TODO: * actually strip the gnunet message header or apply it again * test with the main vpn binary 2013-01-24 02:55 dold * [r25866] src/consensus/consensus_api.c, src/consensus/consensus_protocol.h, src/consensus/gnunet-consensus.c, src/consensus/gnunet-service-consensus.c, src/consensus/ibf.c, src/consensus/test_consensus.conf: implemented value exchange, various fixes 2013-01-23 13:15 harsha * [r25862] contrib/testbed_infiniband.conf: profiler now depends on config file to give topology option 2013-01-23 13:14 harsha * [r25861] src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed_api_testbed.c: fix 2688: profiler now uses GNUNET_TESTBED_run () 2013-01-23 10:46 harsha * [r25860] src/testbed/testbed_api_testbed.c: use all IP addresses of master controller as trusted ip 2013-01-23 10:10 wachs * [r25859] src/ats/test_ats_simplistic_pref_aging.c: test 2013-01-22 16:44 wachs * [r25857] src/ats/test_ats_simplistic_pref_aging.c: changes 2013-01-22 16:01 wachs * [r25856] src/ats/gnunet-service-ats_addresses_simplistic.c: wrong type causing invalid reads 2013-01-22 11:04 wachs * [r25854] contrib/pydmesg: print dmesg messages with human readable timestamps useful to check when segfaults etc happened 2013-01-21 16:58 wachs * [r25853] src/ats/gnunet-service-ats_addresses_simplistic.c: changes to aging 2013-01-21 16:29 wachs * [r25850] src/ats/gnunet-service-ats_addresses_simplistic.c: fixes 2013-01-21 16:26 LRN * [r25848] po/POTFILES.in: mesh_block_lib.c is gone 2013-01-21 16:15 wachs * [r25847] src/ats/test_ats_simplistic_pref_aging.c: improving test 2013-01-21 13:24 grothoff * [r25837] contrib/gnunet-chk.py: 3 2013-01-18 16:52 wachs * [r25835] src/ats/gnunet-service-ats_addresses_simplistic.c: preference aging + improved quota recalculation due to pref change 2013-01-18 15:48 wachs * [r25833] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_simplistic_pref_aging.c: changes 2013-01-18 14:07 wachs * [r25831] src/ats-tool/gnunet-ats.c: print network type 2013-01-18 13:49 wachs * [r25830] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_common.c: changes 2013-01-18 12:23 wachs * [r25829] src/transport/plugin_transport_http_common.c, src/transport/test_http_common.c: changes 2013-01-18 12:01 wachs * [r25828] src/transport/plugin_transport_http_common.c: mem leak 2013-01-18 11:16 wachs * [r25827] src/transport/test_http_common.c: change 2013-01-18 11:07 wachs * [r25826] src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_common.h, src/transport/test_http_common.c: address parsing 2013-01-18 04:51 LRN * [r25823] src/regex/Makefile.am: Fix regex dependencies 2013-01-18 04:43 LRN * [r25822] src/transport/gnunet-transport.c: Fix FPRINTF invocation 2013-01-18 04:43 LRN * [r25821] src/core/gnunet-service-core_kx.c: Replace EPV with a warning 2013-01-18 04:43 LRN * [r25820] src/transport/gnunet-service-transport_validation.c: Re-enable signature check warning 2013-01-17 17:09 bartpolot * [r25819] src/include/block_mesh.h, src/include/block_regex.h, src/include/gnunet_block_lib.h, src/include/gnunet_regex_lib.h, src/mesh/Makefile.am, src/mesh/gnunet-service-mesh-new.c, src/mesh/gnunet-service-mesh.c, src/mesh/mesh_block_lib.c, src/mesh/mesh_block_lib.h, src/mesh/plugin_block_mesh.c, src/regex/Makefile.am, src/regex/plugin_block_regex.c, src/regex/regex.c, src/regex/regex_block_lib.c, src/regex/regex_block_lib.h, src/regex/regex_dht.c: Move regex DHT integration from mesh to regex 2013-01-17 16:31 wachs * [r25818] src/transport/test_http_common.c: test 2013-01-17 16:21 wachs * [r25817] src/transport/Makefile.am, src/transport/gnunet-service-transport_clients.c, src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_common.h: address parsing 2013-01-17 14:23 cfuchs * [r25816] src/vpn/gnunet-helper-vpn-windows.c: * a little bit of bugfixing * added functionality to remove ip addresses from our interfaces * some formatting work * added rety-loop for the interface-name resolver (retry up to 30 seconds) * set new ipv4/v6 addresses to be forgotten on bootup (store=active) * adjusted some debug output (added a few \n here and there) 2013-01-17 13:33 wachs * [r25814] src/transport/gnunet-transport.c: end when no addresses returned 2013-01-17 13:03 wachs * [r25813] src/transport/gnunet-transport.c: improved timeout handling for address listing 2013-01-17 12:25 wachs * [r25812] src/transport/gnunet-transport.c: timeout for address listing 2013-01-17 10:28 grothoff * [r25809] src/vpn/gnunet-helper-vpn-windows.c: minor style stuff 2013-01-16 17:21 cfuchs * [r25805] src/vpn/gnunet-helper-vpn-windows.c: more debugging work. Registry is extremely slow at refreshing. inserted a makeshift sleep(5) to avoid retrieving outdated interface-information. added proper return-codes to set_address4/6 fixed incorrect string-length handling for the HWID tags updatedriverforplugandplaydevicesa now updates only the driver for our current device, no longer the other siblings too (for >10 devices, this could easily have taken > 60 seconds! ). removed inet_pton, as we require API version XPSP2 anyway. 2013-01-15 20:22 cfuchs * [r25802] src/vpn/Makefile.am, src/vpn/gnunet-helper-vpn-windows.c: added calls for updating the driver in a for device. seems like this is mandatory when adding a new device node. unfortunately this is pretty slow... added new required include+library to link against: newdev.h/dll 2013-01-15 19:15 cfuchs * [r25801] src/vpn/gnunet-helper-vpn-windows.c: more bug fixing 2013-01-15 18:50 cfuchs * [r25800] src/vpn/gnunet-helper-vpn-windows.c: a bit of bugfixing 2013-01-15 14:45 cfuchs * [r25799] src/vpn/gnunet-helper-vpn-windows.c: final logics for run implemented added teardown functionality. now: testing... 2013-01-15 14:42 wachs * [r25798] src/ats/gnunet-service-ats_addresses_simplistic.c: fix for failing fs tests 2013-01-15 14:11 wachs * [r25797] src/sysmon/gnunet-service-sysmon.c, src/sysmon/sysmon.conf.in: changes 2013-01-15 13:32 wachs * [r25794] src/sysmon/gnunet-service-sysmon.c, src/sysmon/sysmon.conf.in: time stamp 2013-01-15 13:23 wachs * [r25793] src/sysmon/gnunet-service-sysmon.c: IPv6 support 2013-01-15 12:55 wachs * [r25792] src/sysmon/gnunet-service-sysmon.c, src/sysmon/sysmon.conf.in, src/sysmon/test_glibtop_network.c: changes 2013-01-15 11:14 wachs * [r25791] src/sysmon/Makefile.am, src/sysmon/gnunet-service-sysmon.c, src/sysmon/sysmon-properties.conf, src/sysmon/sysmon.conf.in: changes 2013-01-15 10:17 wachs * [r25790] src/sysmon/gnunet-service-sysmon.c: fix 2013-01-15 10:14 wachs * [r25789] src/sysmon/gnunet-service-sysmon.c: fix 2013-01-15 10:13 wachs * [r25788] src/sysmon/Makefile.am: install withouth libgtop 2013-01-15 09:34 wachs * [r25787] src/ats/gnunet-service-ats_addresses_simplistic.c: fixing 0002735: precision error when calculating quotas 2013-01-15 09:09 wachs * [r25786] src/ats/gnunet-service-ats_addresses_simplistic.c: get more information 2013-01-14 16:44 wachs * [r25785] src/sysmon/gnunet-service-sysmon.c, src/sysmon/sysmon.conf.in: gtop integration 2013-01-14 16:22 wachs * [r25784] src/sysmon/gnunet-service-sysmon.c: changes 2013-01-14 15:53 wachs * [r25782] src/sysmon/gnunet-service-sysmon.c, src/sysmon/sysmon.conf.in: changes 2013-01-14 15:39 harsha * [r25781] contrib/testbed_infiniband.conf: - kill irrelavant stuff 2013-01-14 15:09 wachs * [r25779] src/sysmon/gnunet-service-sysmon.c: changes 2013-01-14 12:02 wachs * [r25771] src/include/gnunet_ats_service.h: handle 2013-01-14 11:14 wachs * [r25770] src/transport/gnunet-service-transport_neighbours.c: fixing mantis 0002732 2013-01-14 11:11 wachs * [r25769] src/ats/ats_api_scheduling.c: adding suggest handle to allow transport to check if we have pending address request 2013-01-14 11:00 wachs * [r25768] src/ats/test_ats_simplistic_change_preference.c: no pending request 2013-01-14 10:49 wachs * [r25767] src/ats/test_ats_simplistic.c: no suggest to cancel 2013-01-14 10:01 wachs * [r25766] src/ats/gnunet-service-ats_addresses_simplistic.c: fix for quota check 2013-01-11 16:32 wachs * [r25762] src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_simplistic_change_preference.c: changes 2013-01-11 15:32 wachs * [r25761] src/ats/gnunet-service-ats_addresses_simplistic.c: fix for broken tests 2013-01-11 15:31 wachs * [r25760] src/ats/test_ats_api_scheduling_check_min_bw_alt.c: fix test 2013-01-11 14:32 wachs * [r25759] src/ats/gnunet-service-ats_addresses_simplistic.c: changes 2013-01-11 13:38 wachs * [r25758] src/ats/gnunet-service-ats_addresses_simplistic.c: changes 2013-01-11 13:37 wachs * [r25757] src/ats/test_ats_simplistic_change_preference.c: change to test to let updates settle 2013-01-11 12:39 wachs * [r25754] src/ats/gnunet-service-ats_addresses_simplistic.c: global calculation 2013-01-11 10:37 wachs * [r25753] src/ats/gnunet-service-ats_addresses_simplistic.c: docu 2013-01-11 09:51 wachs * [r25752] src/ats/gnunet-service-ats_addresses.c: commit for mantis: 0002729 quota load: support "unlimited", fancy strings and integer values (set by gnunet setup) 2013-01-10 12:36 cfuchs * [r25743] src/vpn/gnunet-helper-vpn-windows.c: consolidated read and write functions, as we can read from a named pipe the same way as we can read from our TAP. added high-level description of attempt_read 2013-01-10 11:54 cfuchs * [r25741] src/vpn/gnunet-helper-vpn-windows.c: as discussed, vpn-helper-windows will only function if stdin/stdout are handed down as pipes. helper will reopen stdin and stdout in overlapped mode. ReOpenFile requires WinXPSP2 or Win2003SP1. 2013-01-10 09:39 cfuchs * [r25737] src/vpn/gnunet-helper-vpn-windows.c: In Windows, pipes, files and the console have to be accessed differently(in contrast to *nix). overlapping does not exist for console handles, and different functions are required to read/write/poll stdin/out. - THus, we can now detect the type of handle we got as stdin/stdout from our calling process. - Did a bit of refactoring. next: add logics to use the proper access mode depending on our handletype. 2013-01-09 23:53 harsha * [r25736] src/testbed/testbed_api.c: allow customizing remote shell command and the program started by it 2013-01-09 09:34 wachs * [r25727] src/ats/gnunet-service-ats_addresses_simplistic.c: enable preference calculation to finish it and debug 2013-01-09 08:48 wachs * [r25726] src/transport/gnunet-service-transport_validation.c: debug code for mantis 0002726 2013-01-08 14:08 cfuchs * [r25713] src/vpn/gnunet-helper-vpn-windows.c: fixed a wrong conditional more research on the conin/stdin+overlapping issue. 2013-01-07 16:09 wachs * [r25708] src/gns/test_gns_dht_three_peers.c: 10 sec was too optimistic for mamasparc 2013-01-07 15:52 wachs * [r25707] src/gns/test_gns_dht_three_peers.c: fixing test by debugging (but still fails) 2013-01-06 00:13 harsha * [r25702] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.conf, src/testbed/test_testbed_api_testbed_run_topology2dtorus.conf, src/testbed/test_testbed_api_testbed_run_topologyclique.conf, src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf, src/testbed/test_testbed_api_testbed_run_topologyline.conf, src/testbed/test_testbed_api_testbed_run_topologyrandom.conf, src/testbed/test_testbed_api_testbed_run_topologyring.conf, src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf, src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf, src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf, src/testbed/testbed.conf.in: cache HELLO's of peers 2013-01-05 16:48 harsha * [r25700] src/testbed/gnunet-service-testbed.c: aggressively persuade transport to connect 2013-01-04 12:18 grothoff * [r25691] src/peerinfo/gnunet-service-peerinfo.c: fix 2013-01-03 22:40 grothoff * [r25686] src/peerinfo/gnunet-service-peerinfo.c, src/peerinfo/peerinfo.conf.in: adding NO_IO option to peerinfo to disable disc accesses for experiments 2013-01-03 16:11 cfuchs * [r25683] src/vpn/gnunet-helper-vpn-windows.c: There are now four states for the OI facilities: * ready (to do work), * queued (waiting for async-io to return), * waiting (a read-facilities wait for its output partner to get process) * failed (if a socket error occured) added attempt_tap_read machine. reworked run() for overlapped IO 2013-01-03 14:58 harsha * [r25682] src/testbed/testbed_api_testbed.c: fix #2720 2013-01-03 10:40 cfuchs * [r25677] src/vpn/gnunet-helper-vpn-windows.c: added initial stuff for overlapped IO and event handling 2013-01-03 00:43 dold * [r25675] src/consensus/Makefile.am, src/consensus/consensus.h, src/consensus/consensus_api.c, src/consensus/gnunet-consensus-start-peers.c, src/consensus/gnunet-consensus.c, src/consensus/gnunet-service-consensus.c, src/consensus/test_consensus_api.c, src/include/gnunet_applications.h, src/include/gnunet_consensus_service.h, src/include/gnunet_protocols.h: implemented the modified consensus api, started implementing p2p protocol for consensus 2013-01-02 16:03 harsha * [r25674] src/testbed/testbed_api.c, src/testbed/testbed_api.h: weigh all readings equally 2013-01-02 15:36 harsha * [r25673] src/testbed/testbed_api.c: linear increase and decrease when SD is within 1 and 2 SD respectively 2013-01-01 22:44 harsha * [r25670] src/testbed/standard_deviation.c, src/testbed/test_testbed_api.conf, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: adaptive parallelism for overlay connect operations based on SD calculations 2013-01-01 11:49 cfuchs * [r25668] src/vpn/gnunet-helper-vpn-windows.c: * re-added mainloop for run * started work on our select-equivalent for windows. 2012-12-31 15:52 cfuchs * [r25667] src/include/tap-windows.h, src/vpn/gnunet-helper-vpn-windows.c: * added tap version checking logics. Many tap32 versions are broken, Only version 9.8 and later support IPv6, 9.8 is broken with IPv4. Thus, we are using the same minium version as openvpn 2.3: tap32-9.9 * created our TAP/TUN handle-object (equivalent to the *nix init_tun() function), this still requires some more logics to be complete. * added logics to set the tun up (+a fixed sleep, to wait for it to come up) * we now also store the device's GUID, as we need it for creating the handle. * added the exports of tap32: src/include/tap_windows.h , for the sake of upgradability. This file contains version-specific defines for the driver. * happy new year! 2012-12-29 20:20 cfuchs * [r25665] src/vpn/gnunet-helper-vpn-windows.c: reworked vpn-helper to now use regular(!) char, instead of wchar, according to recommendations found in the C/C++-specs(wchar != unicode support, but may break compiler compatibility). 2012-12-24 12:08 LRN * [r25643] src/consensus/Makefile.am: Dependencies in consensus makefiles 2012-12-24 09:48 LRN * [r25642] src/sysmon/sysmon.conf.in: Resolve port conflict between ats and sysmon 2012-12-22 08:50 LRN * [r25640] src/hostlist/hostlist.conf: Fix default hostlists 2012-12-21 16:48 grothoff * [r25635] po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po: releasing GNUnet 0.9.5 2012-12-21 16:29 harsha * [r25634] src/lockmanager/gnunet-service-lockmanager.c: remove disconnecting client from waitling lists of other locks 2012-12-21 10:06 dold * [r25613] src/consensus/gnunet-consensus-ibf.c, src/consensus/ibf.c, src/consensus/ibf.h: collision detection for IBF, timing for test tool 2012-12-20 14:50 wachs * [r25583] src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_simplistic_change_preference.c: preference value calculation 2012-12-20 14:01 bartpolot * [r25581] configure.ac, po/POTFILES.in, src/Makefile.am, src/testing_old: Remove testing_old 2012-12-20 13:57 LRN * [r25580] src/fs/fs_uri.c: Fix percentization of non-ASCII strings 2012-12-20 00:39 dold * [r25571] src/consensus/Makefile.am, src/consensus/gnunet-consensus-ibf.c, src/consensus/ibf.c, src/consensus/ibf.h: implemented the invertible bloom filter 2012-12-19 09:36 wachs * [r25538] src/ats/test_ats_simplistic_change_preference.c: fixing test 2012-12-17 16:03 wachs * [r25520] src/ats/ats_api_peer_change_preference.c: unused code 2012-12-17 15:08 wachs * [r25517] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c: changes 2012-12-17 14:30 wachs * [r25516] src/ats/test_ats_api.conf: no valgrind 2012-12-17 14:30 wachs * [r25515] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/ats/gnunet-service-ats_performance.c, src/ats/test_ats_api.conf: adding client reference 2012-12-17 12:48 wachs * [r25511] configure.ac: libgtop check 2012-12-17 12:45 wachs * [r25509] src/sysmon/Makefile.am: new check 2012-12-17 12:15 wachs * [r25506] src/sysmon/Makefile.am: glib check 2012-12-17 12:14 wachs * [r25505] configure.ac: check for glib 2012-12-15 14:24 grothoff * [r25493] src/fs/gnunet-service-fs_pe.c: LRN: fixing #2701 2012-12-14 10:56 wachs * [r25480] src/dns/dnsparser.c: doxygen 2012-12-14 10:54 wachs * [r25479] src/hello/hello.c: doxyen 2012-12-14 10:54 wachs * [r25478] src/sysmon/gnunet-service-sysmon.c: doxygen 2012-12-14 10:51 wachs * [r25477] src/fs/Makefile.am: fixes for make dist 2012-12-14 10:43 wachs * [r25476] doc/man/gnunet-ats.1: updated man page 2012-12-14 10:02 wachs * [r25475] src/include/gnunet_ats_service.h: docu 2012-12-14 10:01 wachs * [r25474] src/ats/ats.conf.in, src/ats/gnunet-service-ats_addresses.c, src/include/gnunet_ats_service.h: improved quota loading 2012-12-14 09:28 wachs * [r25473] src/ats-tool/gnunet-ats.c: new switch -q to print configured quotas 2012-12-13 19:31 grothoff * [r25465] src/regex/regex.c, src/regex/regex_internal.h: reduce reallocing to improve performance 2012-12-13 16:13 wachs * [r25459] src/ats/gnunet-service-ats_addresses_simplistic.c: statistics for solver 2012-12-13 13:46 wachs * [r25449] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_api_scheduling_switch_network.c, src/ats/test_ats_simplistic_switch_networks.c: simplistic solver supports moving addresses between networks, test renamed 2012-12-13 13:01 wachs * [r25445] src/ats/test_ats_api_scheduling_switch_network.c: test: check network type 2012-12-13 12:41 wachs * [r25444] src/ats/test_ats_api_scheduling_switch_network.c: changes 2012-12-12 21:45 grothoff * [r25434] src/nat/Makefile.am, src/nat/nat_auto.c: nat auto code from gnunet-gtk now compiles as part of libgnunetnat 2012-12-12 21:44 grothoff * [r25433] src/include/gnunet_configuration_lib.h, src/util/configuration.c: adding function to compute configuration differences in memory 2012-12-12 21:22 cfuchs * [r25432] src/vpn/gnunet-helper-vpn-windows.c: Added basic functionality for setting IPv4/V6 addresses in win32 using netsh. Added wrapper for launching programs in a windows shell. Added define for _tpopen 2012-12-12 16:51 bartpolot * [r25429] src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed_api.c: Run testbed-helper in a sh interactive session to make sure the env is set up properly 2012-12-12 16:15 wachs * [r25427] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_api_scheduling_switch_network.c: changes and test 2012-12-12 15:32 wachs * [r25424] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: updating addresses support changing networks 2012-12-12 13:48 wachs * [r25423] src/transport/plugin_transport_tcp.c: fix: tcp did not return network type 2012-12-12 13:28 wachs * [r25422] src/ats/gnunet-service-ats.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/ats/gnunet-service-ats_performance.c, src/ats/gnunet-service-ats_performance.h, src/ats/gnunet-service-ats_scheduling.c, src/sysmon/Makefile.am, src/sysmon/gnunet-daemon-sysmon.c, src/sysmon/gnunet-service-sysmon.c, src/sysmon/sysmon.conf.in: changes 2012-12-12 11:25 bartpolot * [r25420] src/mesh/gnunet-service-mesh.c: mesh now accepts REGEXes longer than 64KiB 2012-12-12 11:11 wachs * [r25419] src/ats/test_ats_api.conf, src/ats/test_ats_api_scheduling_block_and_reset.c: add additional stage due to issues on powerbot: initial address suggestion can take quite long during service startup 2012-12-12 10:48 cfuchs * [r25417] contrib/openvpn-tap32, contrib/openvpn-tap32/INSTALL, contrib/openvpn-tap32/tap32-signed-i386-2.1.zip, contrib/openvpn-tap32/tap32-source-2.1.zip: added a copy of the current sources(openvpn-2.1) and a signed copy of the compiled drivers of tap32, which is used by vpn-helper-windows to emulate tun/tap on win32. 2012-12-12 10:34 wachs * [r25416] src/transport/plugin_transport_unix.c: msg 2012-12-12 10:32 wachs * [r25415] src/ats-tool/gnunet-ats.c: fix coverity 10389 2012-12-12 10:13 wachs * [r25414] src/core/test_core_quota_asymmetric_recv_limited_peer1.conf, src/core/test_core_quota_asymmetric_recv_limited_peer2.conf, src/core/test_core_quota_asymmetric_send_limit_peer1.conf, src/core/test_core_quota_asymmetric_send_limit_peer2.conf, src/core/test_core_quota_peer1.conf, src/core/test_core_quota_peer2.conf: fixing confs: core tests should pass 2012-12-12 09:54 wachs * [r25413] src/ats/gnunet-service-ats_addresses_simplistic.c: fix coverity 10390 2012-12-12 09:37 wachs * [r25407] src/ats/test_ats_api_performance.c: fix break 2012-12-12 09:27 wachs * [r25406] src/ats/ats_api_scheduling.c, src/include/gnunet_ats_service.h: adding function 2012-12-12 09:20 wachs * [r25405] src/ats/ats_api_scheduling.c: msgs 2012-12-12 08:57 wachs * [r25404] src/transport/test_quota_compliance.c: FIX: add quotas for all networks, transport tests should pass 2012-12-11 22:35 cfuchs * [r25401] src/vpn/gnunet-helper-vpn-windows.c: grml, friendlyName is not friendly, because it does not help us for finding anything. Switched over to backup plan: * lookup the devices's name directly in registry via the PNPInterfaceID. Registry fun, yey! * added a few fixes here and there 2012-12-11 15:46 wachs * [r25398] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/ats/test_ats_api_common.c, src/ats/test_ats_api_common.h, src/ats/test_ats_api_scheduling_add_address.c, src/ats/test_ats_api_scheduling_add_session.c, src/ats/test_ats_api_scheduling_block_and_reset.c, src/ats/test_ats_api_scheduling_destroy_address.c, src/ats/test_ats_api_scheduling_destroy_inbound_connection.c, src/ats/test_ats_api_scheduling_destroy_session.c, src/ats/test_ats_api_scheduling_update_address.c, src/ats/test_ats_simplistic.c: changes 2012-12-11 14:32 wachs * [r25396] src/ats/gnunet-service-ats.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_scheduling.c, src/ats/gnunet-service-ats_scheduling.h: changes 2012-12-11 13:56 wachs * [r25394] src/ats/gnunet-service-ats_addresses_simplistic.c: changes 2012-12-11 13:48 harsha * [r25393] src/fs/gnunet-fs-profiler.c, src/include/gnunet_testbed_service.h, src/testbed/test_testbed_api_testbed_run.c, src/testbed/testbed_api_test.c, src/testbed/testbed_api_testbed.c: fix 2689 2012-12-11 13:46 wachs * [r25392] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_api_scheduling_destroy_address.c: 2012-12-11 12:27 harsha * [r25390] src/consensus/gnunet-consensus-start-peers.c, src/dht/dht_test_lib.c, src/fs/perf_gnunet_service_fs_p2p.c, src/fs/perf_gnunet_service_fs_p2p_respect.c, src/fs/test_fs_test_lib.c, src/fs/test_gnunet_service_fs_migration.c, src/fs/test_gnunet_service_fs_p2p.c, src/gns/test_gns_dht_three_peers.c, src/include/gnunet_testbed_service.h, src/nse/test_nse_multipeer.c, src/stream/perf_stream_api.c, src/stream/test_stream_2peers.c, src/stream/test_stream_2peers_halfclose.c, src/testbed/test_testbed_api_test.c, src/testbed/test_testbed_api_topology.c, src/testbed/test_testbed_api_topology_clique.c, src/testbed/testbed_api_test.c, src/topology/test_gnunet_daemon_topology.c: GNUNET_TESTBED_test_run to return status 2012-12-11 10:51 harsha * [r25386] src/include/gnunet_stream_lib.h, src/stream/stream_api.c: allow calling GNUNET_STREAM_read() from DataProcessor callback 2012-12-11 10:50 wachs * [r25385] src/ats/test_ats_api_scheduling_add_session.c: new test 2012-12-11 10:50 wachs * [r25384] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_api_scheduling_add_address.c: changes 2012-12-11 10:08 wachs * [r25382] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_api_scheduling_add_address.c: changes 2012-12-11 09:30 wachs * [r25381] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp_averaging.c: rename 2012-12-11 09:28 wachs * [r25380] src/ats/gnunet-service-ats_addresses_simplistic.c: changes 2012-12-10 20:42 cfuchs * [r25378] src/vpn/gnunet-helper-vpn-windows.c: added functionality to fetch the virtual interface's FriendlyName from the registry. This information is needed for netsh later on. 2012-12-10 16:22 wachs * [r25374] src/ats/test_ats_api_common.h, src/ats/test_ats_api_scheduling_add_address.c, src/ats/test_ats_api_scheduling_block_and_reset.c, src/ats/test_ats_api_scheduling_destroy_address.c, src/ats/test_ats_api_scheduling_destroy_session.c, src/ats/test_ats_api_scheduling_update_address.c, src/ats/test_ats_simplistic.c: changes 2012-12-10 15:38 wachs * [r25372] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/test_ats_simplistic.c: test and change 2012-12-10 14:48 wachs * [r25367] src/ats/gnunet-service-ats_performance.c: remove hattrick check 2012-12-10 14:42 wachs * [r25365] src/ats-tool/gnunet-ats.c: coverity 2012-12-10 14:38 wachs * [r25364] src/ats/test_ats_api_performance.c: coverity 2012-12-10 14:38 wachs * [r25363] src/ats/gnunet-service-ats_addresses_simplistic.c: clean up 2012-12-10 14:34 grothoff * [r25361] src/fs/gnunet-service-fs_stream.c: do not queue more than one write at a time to stream, -- hopefully fixing #2672 2012-12-10 14:25 wachs * [r25360] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: more changes 2012-12-10 14:11 harsha * [r25357] src/fs/gnunet-service-fs_stream.c, src/include/gnunet_stream_lib.h, src/stream/stream_api.c: fix 2672 2012-12-10 13:53 wachs * [r25356] src/ats/gnunet-service-ats_addresses_simplistic.c: mgmt 2012-12-10 13:01 wachs * [r25353] src/ats/test_ats_api.conf: fix 2012-12-10 13:01 wachs * [r25352] src/ats/gnunet-service-ats_performance.c, src/ats/test_ats_api.conf: fix 2012-12-10 12:35 wachs * [r25347] src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_api.conf: fix 2012-12-10 12:27 LRN * [r25346] src/util/configuration.c: Unnecessary argument 2012-12-10 12:22 wachs * [r25345] src/util/plugin.c: one more time 2012-12-10 12:20 wachs * [r25344] src/util/configuration.c, src/util/plugin.c: mem leak in line 193configuration.c 2012-12-10 12:13 wachs * [r25343] src/util/plugin.c: mistake 2012-12-10 12:12 wachs * [r25342] src/util/configuration.c, src/util/plugin.c: mem leak 2012-12-10 12:04 LRN * [r25340] src/util/configuration.c: Fix configuration parsing * Don't leak strndup'ed lines. * Trim leading whitespace, not just trailing * Do whitespace trimming _before_ discarding commented lines (now # or % does not need to be the first character in the line). . 2012-12-09 23:22 cfuchs * [r25336] src/vpn/gnunet-helper-vpn-windows.c: added unique additional hwid entry to allow us to find our individual virtual interface again. Needed, because netsh requires us to resolve the devices name as string, which can not be derived off the deviceinfoset directly. we are now using the handed over devicename + our PID the result looks something like this: gnunet-vpn13381 2012-12-09 15:38 grothoff * [r25333] src/include/gnunet_disk_lib.h, src/util/crypto_rsa.c, src/util/disk.c: adding GNUNET_DISK_file_backup function; fixing #2646 2012-12-08 21:38 grothoff * [r25329] src/util/os_installation.c: look in /opt/jdk1.6.0_22/bin:/usr/lib/jvm/java-6-sun//bin:.:/home/grothoff/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games for gnunet-arm before trying /proc/exe 2012-12-08 20:19 grothoff * [r25328] src/util/configuration.c: fixing #2680 -- config file lines can now have any length 2012-12-07 16:05 wachs * [r25315] src/ats/gnunet-service-ats_addresses_simplistic.c: changes 2012-12-07 15:39 wachs * [r25312] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: mod 2012-12-07 15:32 wachs * [r25311] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: mod 2012-12-07 15:13 wachs * [r25310] src/ats/gnunet-service-ats_addresses.c: change 2012-12-07 14:15 cfuchs * [r25309] src/vpn/gnunet-helper-vpn-windows.c: solved fixme's, linked device handling functions to main program flow, added some fixes here and there. added more comments to the code. 2012-12-07 11:12 wachs * [r25306] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c: increase blocking on suggest in addresses, checking in solver 2012-12-06 15:21 wachs * [r25300] src/ats/Makefile.am, src/ats/test_ats_api_scheduling.c: remove old code 2012-12-06 15:18 wachs * [r25299] src/ats/Makefile.am: changes 2012-12-06 15:16 wachs * [r25298] src/ats/Makefile.am, src/ats/test_ats_api_reset_backoff.c, src/ats/test_ats_api_scheduling_block_and_reset.c: tests 2012-12-06 14:00 wachs * [r25297] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_api_scheduling_update_address.c: changes 2012-12-06 13:16 wachs * [r25293] src/ats/test_ats_api_scheduling_add_address.c, src/ats/test_ats_api_scheduling_update_address.c: ats info 2012-12-06 12:32 wachs * [r25291] src/ats/test_ats_api_scheduling_add_address.c, src/ats/test_ats_api_scheduling_destroy_address.c, src/ats/test_ats_api_scheduling_destroy_session.c, src/ats/test_ats_api_scheduling_update_address.c: improvements 2012-12-06 12:20 wachs * [r25290] src/ats/Makefile.am, src/ats/test_ats_api_scheduling_destroy_address.c, src/ats/test_ats_api_scheduling_destroy_session.c, src/ats/test_ats_api_scheduling_update_address.c, src/ats/test_ats_api_update_address.c: changes 2012-12-06 12:17 wachs * [r25289] src/ats/test_ats_api_scheduling_add_address.c: changes 2012-12-06 10:37 dold * [r25287] src/include/gnunet_protocols.h: added consensus message types 2012-12-06 10:02 wachs * [r25285] src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_api_common.h, src/ats/test_ats_api_scheduling_destroy_session.c: changes 2012-12-06 09:42 wachs * [r25284] src/ats/test_ats_api_scheduling_add_address.c, src/ats/test_ats_api_scheduling_destroy_address.c: changes 2012-12-06 09:22 wachs * [r25283] src/ats/test_ats_api_scheduling_destroy_address.c: fix 2012-12-06 09:09 wachs * [r25281] src/ats/ats_api_scheduling.c, src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_api_scheduling_add_address.c: fix 2012-12-06 08:41 wachs * [r25280] src/ats/test_ats_api_scheduling_init.c: minor 2012-12-06 01:34 LRN * [r25279] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c: Don't crash when address suggestor fails 2012-12-05 22:34 LRN * [r25278] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_mlp.h: Should be compilable without libglpk again 2012-12-05 21:41 dold * [r25275] src/consensus/Makefile.am, src/consensus/consensus.h, src/consensus/consensus_api.c, src/consensus/gnunet-consensus-start-peers.c, src/consensus/gnunet-consensus.c, src/consensus/gnunet-service-consensus.c, src/consensus/ibf.c, src/consensus/ibf.h, src/consensus/test_consensus.conf: consensus api, consensus service (local), peer driver and ibf sketch 2012-12-05 16:39 wachs * [r25266] src/ats/test_ats_api_scheduling_add_address.c, src/ats/test_ats_api_scheduling_destroy_address.c: changes 2012-12-05 16:33 wachs * [r25265] src/ats/test_ats_api_scheduling_destroy_session.c: changes 2012-12-05 16:23 wachs * [r25264] src/ats/Makefile.am, src/ats/test_ats_api_scheduling_destroy_session.c: changes 2012-12-05 16:18 wachs * [r25263] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_api_scheduling_destroy_address.c: fix and new test 2012-12-05 16:04 wachs * [r25262] src/ats/test_ats_api_common.h: test rewrite 2012-12-05 15:57 wachs * [r25261] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses.c, src/ats/test_ats_api_scheduling_add_address.c, src/ats/test_ats_api_scheduling_init.c: test rewrite 2012-12-05 15:38 wachs * [r25260] src/ats/ats_api_performance.c: callback check 2012-12-05 14:56 wachs * [r25259] src/ats/gnunet-service-ats_addresses.c: changes 2012-12-05 14:42 wachs * [r25258] src/ats/gnunet-service-ats_addresses.c: remove unusued code 2012-12-05 14:41 wachs * [r25257] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: remove unusued code 2012-12-05 14:31 wachs * [r25256] src/ats/gnunet-service-ats_addresses.h: some docu 2012-12-05 14:18 wachs * [r25255] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp_averaging.c: fix tests 2012-12-05 14:06 wachs * [r25254] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp_averaging.c: commit required ... things can be broken 2012-12-05 10:44 wachs * [r25250] src/ats/gnunet-service-ats_addresses.c: fix for tests 2012-12-05 10:14 cfuchs * [r25249] src/vpn/gnunet-helper-vpn-windows.c: added teardown functionality for deconstructing the interface created by the win32 vpn-helper. 2012-12-04 16:04 wachs * [r25243] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_scheduling.c: changes 2012-12-04 15:26 wachs * [r25237] src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h: doxygen 2012-12-04 15:14 wachs * [r25235] src/ats/gnunet-service-ats_addresses.c: changes 2012-12-04 15:09 wachs * [r25233] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: docu 2012-12-04 14:57 wachs * [r25232] src/ats/gnunet-service-ats_addresses.c: changes 2012-12-04 14:38 wachs * [r25229] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: changes 2012-12-04 14:02 wachs * [r25228] src/ats/gnunet-service-ats_addresses.c: mem leak 2012-12-04 13:45 wachs * [r25226] src/ats/gnunet-service-ats.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h: restructure 2012-12-04 13:16 wachs * [r25223] src/ats/ats.conf.in, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/ats/perf_ats_mlp.c, src/ats/test_ats_mlp.c, src/ats/test_ats_mlp_averaging.c: changes 2012-12-03 22:58 cfuchs * [r25209] src/vpn/gnunet-helper-vpn-windows.c: Added logics to install virtual networks interfaces for gnunet-vpn in win32 based on the info that can be found in the MSDN. Current revision: http://msdn.microsoft.com/en-us/library/windows/hardware/ff549791%28v=vs.85%29.aspx 2012-12-03 16:46 harsha * [r25199] src/include/gnunet_testbed_service.h, src/testbed/gnunet-testbed-profiler.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_testbed.c: host compatibility check in GNUNET_TESTBED_run() and fixes 2012-12-03 15:09 wachs * [r25191] src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: doxygen 2012-12-03 15:05 wachs * [r25190] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: changes 2012-12-03 14:57 wachs * [r25189] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h: changes 2012-12-03 14:50 harsha * [r25188] src/testbed/gnunet-testbed-profiler.c: display and update number of hosts checked 2012-12-03 14:50 wachs * [r25187] src/ats/Makefile.am, src/ats/ats.conf.in, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_simplistic.c, src/ats/gnunet-service-ats_addresses_simplistic.h, src/ats/test_ats_api.conf: changes 2012-12-03 13:58 harsha * [r25185] src/consensus, src/include/gnunet_testbed_service.h, src/sysmon, src/testbed/gnunet-testbed-profiler.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_testbed.c: making GNUNET_TESTBED_is_host_compatible() asynchronous 2012-12-02 12:02 harsha * [r25176] src/testbed/testbed_api_testbed.c: hosts file support in GNUNET_TESTBED_run() - fixes 2667 2012-11-30 16:56 harsha * [r25173] configure.ac: configure option for using IBM LoadLeveler for scheduling testbed slaves on SuperMUC 2012-11-29 09:36 wachs * [r25160] src/sysmon/Makefile.am, src/sysmon/test_glibtop.c: installation test 2012-11-29 09:07 wachs * [r25158] src/sysmon/gnunet-daemon-sysmon.c: type issues 2012-11-28 16:45 dold * [r25157] src/consensus/gnunet-service-consensus.c: fixed copying of wrong memory address 2012-11-28 16:36 wachs * [r25156] configure.ac: possbility a) I did not commit or b) some removed my commit?! Please complain about it 2012-11-28 16:33 dold * [r25155] src/include/gnunet_protocols.h: deleted duplicate message id definition 2012-11-28 16:32 dold * [r25154] po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/consensus/Makefile.am, src/consensus/consensus_api.c, src/consensus/gnunet-service-consensus.c, src/consensus/gnunet-service-consensus.cc, src/consensus/test_consensus.conf, src/consensus/test_consensus_api.c, src/include/gnunet_consensus_service.h, src/include/gnunet_protocols.h: dummy consensus service 2012-11-28 16:14 wachs * [r25153] src/sysmon/Makefile.am, src/sysmon/test_glibtop.c, src/sysmon/test_glibtop_network.c, src/sysmon/test_glibtop_process.c: network test 2012-11-28 15:10 wachs * [r25152] src/include/gnunet_protocols.h: compile error 2012-11-28 14:33 wachs * [r25150] src/sysmon/test_glibtop.c: changes 2012-11-28 14:21 wachs * [r25149] src/sysmon/test_glibtop.c: test 2012-11-28 13:50 wachs * [r25148] src/sysmon/Makefile.am, src/sysmon/gnunet-daemon-sysmon.c: add a test for glibtop 2012-11-26 17:12 dold * [r25143] src/consensus/consensus_api.c, src/include/gnunet_consensus_service.h: fixed doxygen 2012-11-26 13:33 harsha * [r25139] src/stream/stream_api.c: exponential delay for data retransmissions 2012-11-26 13:00 harsha * [r25137] src/stream/stream_api.c: seperate timeouts for MESH retries 2012-11-26 10:48 wachs * [r25135] src/sysmon/gnunet-daemon-sysmon.c: changes 2012-11-26 10:26 wachs * [r25134] src/sysmon/gnunet-daemon-sysmon.c: changes 2012-11-26 10:11 cfuchs * [r25133] src/vpn/Makefile.am: added libraries for setupapi & dependencies 2012-11-24 23:54 grothoff * [r25125] src/stream/stream_api.c: removing invalid assertions that shutdown must preceed closing 2012-11-24 23:45 grothoff * [r25123] src/fs/gnunet-service-fs.c, src/fs/gnunet-service-fs_pr.c, src/fs/gnunet-service-fs_pr.h, src/fs/gnunet-service-fs_put.c: actually using stream for dblock/iblock transfer if possible 2012-11-24 22:49 grothoff * [r25119] src/fs/test_fs_download_indexed.conf, src/fs/test_fs_download_stream.conf: combining test_fs_download.c and test_fs_download_index.c into one file, adding additional test test_fs_download_stream 2012-11-24 22:49 grothoff * [r25118] src/fs/Makefile.am, src/fs/test_fs_download.c, src/fs/test_fs_download_data.conf, src/fs/test_fs_download_indexed.c: combining test_fs_download.c and test_fs_download_index.c into one file, adding additional test test_fs_download_stream 2012-11-24 22:43 grothoff * [r25117] src/include/gauger.h: adding missing parens around macro arguments in gauger macros 2012-11-24 08:08 LRN * [r25115] src/transport/plugin_transport_udp.c: Be more specific about UDP read failures 2012-11-23 17:07 wachs * [r25114] src/sysmon, src/sysmon/Makefile.am, src/sysmon/gnunet-daemon-sysmon.c, src/sysmon/sysmon.conf.in: changes 2012-11-23 12:23 harsha * [r25113] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_testbed_run_topologyscalefree.conf: test case for scale free routing 2012-11-22 19:57 grothoff * [r25111] src/fs/gnunet-service-fs_pr.c, src/fs/gnunet-service-fs_stream.c, src/fs/gnunet-service-fs_stream.h: towards using stream for non-anonymous file-sharing 2012-11-22 18:27 grothoff * [r25110] src/fs/gnunet-service-fs.c, src/fs/gnunet-service-fs.h, src/fs/gnunet-service-fs_pr.c, src/fs/gnunet-service-fs_stream.c, src/include/gnunet_protocols.h: mostly finishing server-side for FS-over-stream 2012-11-22 17:03 harsha * [r25107] src/testbed, src/testbed/Makefile.am, src/testbed/overlay_topology.txt, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_testbed_run_topologyfromfile.conf, src/testbed/testbed_api_testbed.c, src/testbed/testbed_api_topology.c: topology loading from file 2012-11-22 15:49 grothoff * [r25106] src/Makefile.am, src/fs/Makefile.am, src/fs/gnunet-service-fs.c, src/fs/gnunet-service-fs_stream.c, src/fs/gnunet-service-fs_stream.h, src/include/gnunet_applications.h, src/include/gnunet_stream_lib.h, src/stream/stream_api.c: starting to use stream in fs 2012-11-22 15:29 wachs * [r25104] src/ats/gnunet-service-ats_performance.c: fix uninitialized mem 2012-11-22 15:15 wachs * [r25102] src/ats/gnunet-service-ats_performance.c: bug fixing: cannot drop messages 2012-11-22 14:05 wachs * [r25099] src/ats/test_ats_api_performance.c: test done 2012-11-22 13:49 wachs * [r25098] src/ats/Makefile.am, src/ats/test_ats_api_performance.c: stage 3 2012-11-21 20:56 dold * [r25091] po/POTFILES.in, po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/consensus/Makefile.am, src/consensus/consensus.h, src/consensus/consensus_api.c, src/consensus/gnunet-service-consensus.cc, src/consensus/test_consensus.conf, src/consensus/test_consensus_api.c, src/include/gnunet_consensus_service.h, src/include/gnunet_protocols.h: started implementing consensus api and service 2012-11-21 10:51 wachs * [r25083] src/ats/ats_api_performance.c, src/ats/gnunet-service-ats_performance.c, src/ats/gnunet-service-ats_performance.h, src/include/gnunet_ats_service.h: dogygen 2012-11-20 15:00 wachs * [r25070] src/ats-tool/gnunet-ats.c, src/ats/ats_api_performance.c: changes, almost done 2012-11-20 12:29 harsha * [r25067] src/include/gnunet_testbed_service.h, src/mesh/gnunet-regex-profiler.c, src/testbed/gnunet-testbed-profiler.c, src/testbed/test_testbed_api_topology.c, src/testbed/test_testbed_api_topology_clique.c, src/testbed/testbed_api_testbed.c, src/testbed/testbed_api_topology.c: extended overlay configure topology to return max connections 2012-11-20 11:24 harsha * [r25063] src/testbed/testbed_api_topology.c: scale free topology 2012-11-19 18:14 LRN * [r25059] configure.ac, src/util/program.c, src/util/service.c, src/util/test_getopt.c: Hardcode svn revision in compiled binaries 2012-11-19 16:30 wachs * [r25058] src/ats-tool/gnunet-ats.c, src/ats/ats.h, src/ats/ats_api_performance.c, src/ats/gnunet-service-ats.c, src/ats/gnunet-service-ats_performance.c, src/ats/gnunet-service-ats_performance.h, src/include/gnunet_protocols.h: changes ... more TBD 2012-11-19 13:59 harsha * [r25050] src/include/gnunet_stream_lib.h, src/stream/stream_api.c: cleanup write handle upon shutdown 2012-11-19 09:56 wachs * [r25045] contrib/ssh-keys: omar ssh key 2012-11-18 20:56 tg * [r25044] src/include/gnunet_hello_lib.h: hello lib header fix 2012-11-18 19:54 harsha * [r25042] src/stream/Makefile.am, src/stream/stream_api.c, src/stream/test_stream_local.conf: use statistics 2012-11-18 18:09 tg * [r25040] src/hello/hello.c, src/include/gnunet_crypto_lib.h, src/include/gnunet_hello_lib.h, src/peerinfo-tool/gnunet-peerinfo.c, src/util/crypto_rsa.c: moved hello uri functions to hello lib 2012-11-18 18:09 tg * [r25039] src/dht/gnunet-service-dht.c, src/dht/gnunet-service-dht_neighbours.c, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_hello.c: configurable hello expiration 2012-11-18 18:09 tg * [r25038] src/util/server.c: util/server: removed unused var 2012-11-17 22:21 bartpolot * [r25034] src/include/gnunet_mesh_service.h, src/include/gnunet_protocols.h, src/mesh/Makefile.am, src/mesh/gnunet-service-mesh.c, src/mesh/mesh.h, src/mesh/mesh_api.c: Added mesh CLI with basic tunnel listing 2012-11-17 12:24 harsha * [r25032] src/testing/testing.c: fix memleak 2012-11-17 08:57 LRN * [r25031] src/statistics/gnunet-statistics.c: Use full, 3-argument fprintf invocation 2012-11-16 17:53 harsha * [r25029] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_testbed_run_topologysmallworld.conf, src/testbed/testbed_api_testbed.c, src/testbed/testbed_api_topology.c: small world topology 2012-11-16 16:43 harsha * [r25017] src/include/gnunet_testbed_service.h, src/testbed/testbed_api_topology.c: 2D Torus topology 2012-11-16 16:36 wachs * [r25014] src/transport/gnunet-service-transport_neighbours.c: logging 2012-11-16 16:35 wachs * [r25011] src/ats/gnunet-service-ats_addresses.c, src/transport/gnunet-service-transport_neighbours.c: transmit all ats properties 2012-11-16 14:36 harsha * [r25002] src/testbed/test_testbed_api.conf, src/testbed/testbed.conf.in, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c: adaptive parallel overlay connects 2012-11-16 14:11 wachs * [r25001] src/ats-tool/gnunet-ats.c, src/include/gnunet_ats_service.h: print ats properties 2012-11-16 13:14 szengel * [r24998] contrib/regex_profiler_infiniband.conf: Saner default values for the infiniband regex profiler conf 2012-11-16 13:08 szengel * [r24997] src/regex/gnunet-regex-simulation-profiler.c, src/regex/regex.c, src/regex/regex_internal.h, src/regex/regex_random.c, src/regex/regex_simulation_profiler_test.conf, src/regex/test_regex_eval_api.c, src/regex/test_regex_graph_api.c, src/regex/test_regex_iterate_api.c: Cleaup, indentation, comments etc. 2012-11-16 13:06 wachs * [r24995] src/ats-tool/gnunet-ats.c: print ats information 2012-11-16 11:20 harsha * [r24993] src/testbed/test_testbed_api_operations.c, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h: dynamically adjustable operation queues 2012-11-15 14:50 wachs * [r24985] src/namestore/gnunet-service-namestore.c, src/namestore/namestore.h, src/namestore/namestore_common.c, src/namestore/test_namestore_api.conf, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_lookup.c, src/namestore/test_namestore_api_lookup_specific_type.c, src/namestore/test_namestore_api_put.c, src/namestore/test_namestore_api_remove.c, src/namestore/test_namestore_api_remove_not_existing_record.c, src/namestore/test_namestore_api_sign_verify.c: implementing mantis 0002193 2012-11-15 13:59 wachs * [r24984] src/testing/testing.c: prefix support for testing 2012-11-15 13:38 grothoff * [r24982] src/include/gnunet_consensus_service.h: polishing consensus API 2012-11-15 10:44 dold * [r24978] src/consensus/Makefile.am, src/consensus/gnunet-consensus.c, src/consensus/gnunet-service-consensus.cc, src/include/gnunet_consensus_service.h: added declarations for the consensus api 2012-11-15 10:24 dold * [r24977] src/mesh/mesh.conf.in: changed @UNIXONLY@ to @JAVAPORT@ 2012-11-15 09:58 wachs * [r24974] src/transport/plugin_transport_udp.c: fix 2012-11-14 17:06 harsha * [r24970] src/include/gnunet_testing_lib-new.h, src/testbed/gnunet-service-testbed.c, src/testing/testing.c: kill all peers first and wait for them later 2012-11-14 15:55 wachs * [r24966] src/transport/plugin_transport_unix.c: fix mantis 0002653 2012-11-14 15:53 grothoff * [r24965] src/dht/dht_api.c, src/dht/gnunet-service-dht_clients.c, src/dht/gnunet-service-dht_neighbours.c: fixing crash of mesh service -- reproduced by regex profiler w 100 peers -- on shutdown due to failure to initialize dht_handle field 2012-11-14 15:15 wachs * [r24962] src/transport/plugin_transport_unix.c: use api correctly 2012-11-14 14:21 wachs * [r24957] src/transport/test_transport_api_unreliability.c: hunting bugs 2012-11-14 14:09 wachs * [r24955] src/transport/plugin_transport_unix.c, src/transport/test_transport_api_unreliability.c: improve unix timeout behaviour 2012-11-14 13:41 szengel * [r24953] src/mesh/gnunet-regex-profiler.c: Removed waiting time before linking 2012-11-14 13:03 grothoff * [r24950] src/dht/gnunet-service-dht_clients.c: use exp backoff macro, start with retry frequency of 1s, instead of the insane 1ms 2012-11-14 10:50 bartpolot * [r24945] src/dht/gnunet-service-dht_clients.c, src/dht/gnunet-service-dht_datacache.c, src/dht/gnunet-service-dht_routing.c, src/include/gnunet_block_lib.h, src/mesh/plugin_block_mesh.c: Added GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT 2012-11-14 09:19 szengel * [r24943] src/mesh/gnunet-daemon-regexprofiler.c: doxygen 2012-11-14 09:16 szengel * [r24942] src/mesh/gnunet-daemon-regexprofiler.c: union of regexes in profiler 2012-11-13 20:05 grothoff * [r24938] src/datacache/Makefile.am, src/datacache/datacache.c, src/datacache/perf_datacache.c, src/datacache/perf_datacache_data_heap.conf, src/datacache/perf_datacache_data_mysql.conf, src/datacache/plugin_datacache_heap.c, src/datacache/plugin_datacache_mysql.c, src/datacache/plugin_datacache_postgres.c, src/datacache/plugin_datacache_sqlite.c, src/datacache/plugin_datacache_template.c, src/datacache/test_datacache.c, src/datacache/test_datacache_data_heap.conf, src/datacache/test_datacache_data_mysql.conf, src/datacache/test_datacache_quota.c, src/dht/gnunet-service-dht_datacache.c, src/include/gnunet_datacache_lib.h, src/include/gnunet_datacache_plugin.h: changing datacache API to separate put-paths from data (so that plugins can test for duplicates), removing support for MySQL 2012-11-13 17:02 szengel * [r24933] src/regex/regex.c, src/regex/regex_internal.h: optimizations 2012-11-13 13:55 grothoff * [r24931] src/datacache/datacache.c: fixing #2641, datastore size way off 2012-11-13 13:25 grothoff * [r24928] src/datastore/plugin_datastore_sqlite.c: fixing bloomfilter reconstruction after quota change, iterator for sqlite failed to return keys due to off-by-one error 2012-11-12 18:14 harsha * [r24920] src/include/gnunet_testbed_service.h: Options for 2D Torus 2012-11-12 18:13 harsha * [r24919] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_testbed_run_topologyrandom.conf, src/testbed/test_testbed_api_testbed_run_topologysmallworldring.conf, src/testbed/testbed_api_testbed.c, src/testbed/testbed_api_topology.c: implementing small world ring topology 2012-11-12 16:55 harsha * [r24918] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_testbed_run_topologyring.conf, src/testbed/testbed_api_testbed.c: test case for ring topology 2012-11-12 16:21 harsha * [r24917] src/testbed/testbed_api_topology.c: implemented line topology 2012-11-12 14:42 grothoff * [r24913] src/datacache/datacache.c: add option to disable Bloom filter entirely (only for benchmarking) 2012-11-12 11:00 grothoff * [r24908] src/datacache/datacache.c, src/datacache/plugin_datacache_sqlite.c: support running purely in-memory 2012-11-12 08:45 wachs * [r24906] src/include/gnunet_transport_service.h, src/transport/transport_api.c: doxygen 2012-11-11 15:04 szengel * [r24901] src/mesh/gnunet-daemon-regexprofiler.c, src/mesh/gnunet-service-mesh.c: doxygen 2012-11-11 14:23 szengel * [r24900] contrib/regex_profiler_infiniband.conf, src/mesh/gnunet-daemon-regexprofiler.c, src/mesh/gnunet-regex-profiler.c, src/mesh/gnunet-service-mesh.c: Better mesh/regex profiler performance. 2012-11-10 22:16 grothoff * [r24893] doc/man/gnunet-peerinfo.1: "man gnunet-peerinfo" doesn't have the -g or -p options which are listed in "gnunet-peerinfo --help". One spelling mistake is also fixed in the attached "diff" (see: additional information). This was against r24891. - #2649. 2012-11-10 21:36 grothoff * [r24892] src/fs/gnunet-service-fs_pr.c: use new DHT API to block known results when searching in the DHT 2012-11-10 20:21 LRN * [r24890] src/gns/w32nsp.c: Update w32nsp to use 'gads' instead of 'gnunet' 2012-11-10 13:41 grothoff * [r24883] src/util/os_installation.c: trying to fix #2645 -- support lib64/gnunet/libexec/ installations 2012-11-10 10:29 LRN * [r24882] src/include/gauger.h: Fix W32 gauger C bindings - quote arguments 2012-11-10 05:51 LRN * [r24881] src/include/gauger.h: Update gauger C binding for W32 2012-11-09 15:56 wachs * [r24873] src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-transport.c: implement mantis 0002419 2012-11-09 15:04 harsha * [r24870] src/testbed/test_testbed_api_2peers_1controller.c: save tests from crashing 2012-11-09 15:01 wachs * [r24868] src/include/gnunet_transport_service.h: docu 2012-11-09 13:52 wachs * [r24863] src/transport/gnunet-transport.c: API change 2012-11-09 13:33 wachs * [r24862] src/core/test_core_api.c, src/core/test_core_api_reliability.c, src/core/test_core_quota_compliance.c, src/dht/gnunet-service-dht_neighbours.c, src/include/gnunet_transport_service.h, src/testbed/gnunet-service-testbed.c, src/testing_old/testing.c, src/topology/gnunet-daemon-topology.c, src/transport/gnunet-transport.c, src/transport/test_transport_api_restart_1peer.c, src/transport/test_transport_api_restart_2peers.c, src/transport/transport-testing.c, src/transport/transport_api.c: changes to transport api 2012-11-09 12:34 harsha * [r24861] src/testbed/gnunet-service-testbed.c: adopting to new transport API 2012-11-08 19:25 bartpolot * [r24849] src/mesh/gnunet-service-mesh.c, src/mesh/mesh_block_lib.c, src/mesh/mesh_block_lib.h, src/mesh/mesh_common.c, src/mesh/plugin_block_mesh.c: MESH uses DHT xquery to limit the results returned during a regex string search 2012-11-08 16:50 LRN * [r24848] src/transport/gnunet-transport.c: Use full, 3-argument invocation of FRPINTF (again) 2012-11-08 15:12 grothoff * [r24847] src/statistics/statistics_api.c: add option to disable use of stats entirely 2012-11-08 15:04 wachs * [r24846] src/transport/gnunet-transport.c: fixed -b semantics: receive from all peers 2012-11-08 14:09 wachs * [r24841] src/transport/gnunet-transport.c: changes 2012-11-08 11:01 wachs * [r24834] src/transport/gnunet-transport.c: not working yet 2012-11-07 18:26 harsha * [r24826] src/include/gnunet_disk_lib.h, src/util/disk.c: making readable check optional 2012-11-07 17:26 szengel * [r24825] src/mesh/Makefile.am, src/mesh/gnunet-daemon-regexprofiler.c, src/mesh/gnunet-service-regexprofiler.c: regexprofiler service to daemon 2012-11-07 16:56 harsha * [r24823] src/chat/chat.c, src/fs/fs_api.c, src/fs/gnunet-auto-share.c, src/include/gnunet_disk_lib.h, src/mesh/gnunet-regex-profiler.c, src/regex/gnunet-regex-simulation-profiler.c, src/util/disk.c, src/util/test_disk.c: Parameterized directory listing permission check 2012-11-07 11:24 LRN * [r24818] src/ats-tool/gnunet-ats.c: Use full, 3-argument FPRINTF invocation 2012-11-07 09:54 wachs * [r24817] src/transport/gnunet-service-transport_clients.c: fix mem leak mantis 0002635 2012-11-06 23:46 harsha * [r24816] src/stream/perf_stream_api.c: reduce number of packets 2012-11-06 23:25 harsha * [r24815] src/arm/gnunet-arm.c: print help for timeout argument 2012-11-06 22:32 harsha * [r24813] src/util/disk.c: check for existing directories in reverse order 2012-11-06 18:16 szengel * [r24811] contrib/regex_profiler_infiniband.conf, src/mesh/gnunet-regex-profiler.c, src/mesh/gnunet-service-regexprofiler.c: Added regex prefix to config for regex profiler. 2012-11-05 21:37 harsha * [r24801] src/gns/nss/Makefile.am: nss uninstall script to extra dist 2012-11-05 21:35 harsha * [r24800] src/testbed/Makefile.am: including sample_hosts.txt to EXTRA_DIST 2012-11-05 21:21 grothoff * [r24799] po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/transport/Makefile.am: ready for 0.9.4 release 2012-11-05 21:01 szengel * [r24792] src/mesh/gnunet-regex-profiler.c, src/mesh/gnunet-service-regexprofiler.c: regex profiler fixes 2012-11-05 20:46 harsha * [r24788] src/stream/perf_stream_api.c: dead code 2012-11-05 20:41 harsha * [r24787] src/stream/perf_stream_api.c: changing to fixed number of packets instead of fixed size test data 2012-11-05 20:05 wachs * [r24782] src/transport/plugin_transport_http_common.c: last cb NULL 2012-11-05 19:21 harsha * [r24779] src/testing/testing.c: coverity fixes 2012-11-05 19:11 harsha * [r24777] src/testbed/testbed_api_testbed.c: coverity fix 2012-11-05 19:05 harsha * [r24776] src/stream/stream_api.c: coverity fixes 2012-11-05 18:53 wachs * [r24774] src/transport/plugin_transport_http_server.c: fix 2012-11-05 17:03 bartpolot * [r24764] src/mesh/gnunet-service-mesh.c: dont cancel mesh pending traffic on tunnel destroy 2012-11-05 17:03 harsha * [r24763] src/testbed/test_testbed_api.conf, src/testbed/test_testbed_api_testbed_run_topologyclique.conf, src/testbed/test_testbed_api_testbed_run_topologyline.conf, src/testbed/test_testbed_api_testbed_run_topologyrandom.conf: reverted test configurations to include ATS 2012-11-05 16:54 harsha * [r24762] src/testbed/test_testbed_api_testbed_run_topologyclique.conf, src/testbed/test_testbed_api_testbed_run_topologyline.conf, src/testbed/test_testbed_api_testbed_run_topologyrandom.conf: merging configs 2012-11-05 16:49 harsha * [r24761] src/testbed/test_testbed_api.conf, src/testbed/test_testbed_api_testbed_run_topologyclique.conf, src/testbed/test_testbed_api_testbed_run_topologyline.conf, src/testbed/test_testbed_api_testbed_run_topologyrandom.conf: merging configs 2012-11-05 16:31 wachs * [r24760] src/ats/gnunet-service-ats_addresses.c: not a hard error, print a warning 2012-11-05 16:08 harsha * [r24759] src/testbed/test_testbed_api.conf: do not start gns-helper-service even on windows 2012-11-05 16:02 harsha * [r24758] src/testbed/Makefile.am: added testing configuration files 2012-11-05 16:01 szengel * [r24757] src/include/gnunet_regex_lib.h, src/mesh/gnunet-regex-profiler.c, src/mesh/gnunet-service-regexprofiler.c, src/mesh/regexprofiler.conf: regex profiler fixes 2012-11-05 15:59 harsha * [r24756] src/testbed/testbed_api.c: maintain argv for helpers 2012-11-05 15:58 wachs * [r24755] src/transport/plugin_transport_http_client.c: docu 2012-11-05 15:54 harsha * [r24754] src/util/helper.c: fix 2012-11-05 15:50 wachs * [r24753] src/transport/plugin_transport_http_client.c, src/transport/test_transport_api_unreliability.c: doxygen error 2012-11-05 15:22 wachs * [r24752] src/dht/Makefile.am: make dist not working 2012-11-05 14:52 wachs * [r24749] src/ats/ats_api_performance.c: infocb can be NULL 2012-11-05 14:33 szengel * [r24744] contrib/regex_profiler_infiniband.conf, src/mesh/Makefile.am, src/mesh/regex_profiler_test.conf: Moving regex profiler config to contrib 2012-11-05 14:30 szengel * [r24743] src/mesh/regex_profiler_test.conf: Commiting changes to regex_profiler_test.conf before moving it to contrib 2012-11-05 13:56 wachs * [r24738] src/transport/test_transport_api_unreliability.c: hunting 2012-11-05 13:52 wachs * [r24736] src/transport/test_transport_api_unreliability.c: bug hunting 2012-11-05 13:29 szengel * [r24731] src/mesh/Makefile.am, src/mesh/gnunet-service-regexprofiler.c, src/mesh/regexprofiler.conf: Adding new regexprofiler service that is used in conjunction with the gnunet-regex-profiler to announce regexes from a policy file 2012-11-05 12:56 harsha * [r24723] src/stream/perf_stream_api.c: fix to keep testing running 2012-11-05 12:17 wachs * [r24718] src/gns/gnunet-service-gns_resolver.c: fix memory leak 2012-11-05 09:39 wachs * [r24705] src/transport/plugin_transport_http_server.c: coverity bugs 10360 && 10361 2012-11-05 09:06 wachs * [r24699] contrib/Makefile.am: make check fails in root dir 2012-11-04 23:57 LRN * [r24697] src/hello/test_hello.c: Typo 2012-11-04 21:49 szengel * [r24695] src/mesh/gnunet-regex-profiler.c: fix 2012-11-04 18:35 szengel * [r24692] src/mesh/gnunet-regex-profiler.c: regex profiler fixes 2012-11-04 17:48 szengel * [r24691] src/mesh/gnunet-regex-profiler.c: regex profiler cleanup 2012-11-03 22:47 LRN * [r24687] src/dht/Makefile.am: link testbed after dhttest (depends on testbed) 2012-11-03 19:10 LRN * [r24685] src/dht/Makefile.am: twopeer test depends on dhttest library 2012-11-02 19:35 szengel * [r24684] src/mesh/gnunet-regex-profiler.c: regex profiler fixes 2012-11-02 18:22 LRN * [r24683] src/dht/Makefile.am: twopeer test depends on testbed 2012-11-02 16:41 szengel * [r24682] src/exit/Makefile.am, src/exit/gnunet-daemon-exit.c, src/include/gnunet_applications.h, src/vpn/Makefile.am, src/vpn/gnunet-service-vpn.c: Using regex for exit/vpn 2012-11-02 16:01 harsha * [r24681] src: ignore gtags files 2012-11-02 15:54 harsha * [r24680] src/testing/testing.c: reverting back to fix failing testbed tests due to late startup of peers 2012-11-02 15:52 harsha * [r24679] src/testbed/gnunet-service-testbed.c: fix memleak 2012-11-02 15:14 harsha * [r24678] src/testbed/test_testbed_api_3peers_3controllers.c: fix crashing test 2012-11-02 09:28 harsha * [r24672] src/testbed/test_testbed_api_testbed_run.c: fix test on W32 2012-11-01 23:03 LRN * [r24671] src/testbed/test_testbed_api_testbed_run.c, src/testing_old/test_testing_large_topology.c: Use strrchr() instead of legacy rindex() 2012-11-01 22:03 harsha * [r24669] src/testing/test_testing_peerstartup.c, src/testing/test_testing_portreservation.c: fix 2012-11-01 22:02 harsha * [r24668] src/testing/test_testing_peerstartup.c, src/testing/test_testing_portreservation.c: fix crashing checks 2012-11-01 21:30 harsha * [r24667] src/testbed/testbed_api_testbed.c: fix 2012-11-01 21:12 harsha * [r24666] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api.conf, src/testbed/test_testbed_api_testbed_run.c, src/testbed/test_testbed_api_testbed_run_topologyclique.conf, src/testbed/test_testbed_api_testbed_run_topologyline.conf, src/testbed/test_testbed_api_testbed_run_topologyrandom.conf, src/testbed/testbed_api_testbed.c: topology option support for GNUNET_TESTBED_run() via configuration 2012-11-01 16:45 LRN * [r24663] src/util/network.c: W32: Remove unnecessary 0 and -1 checks 2012-11-01 16:43 LRN * [r24662] src/util/network.c: W32: optimize GNUNET_NETWORK_fdset_add 2012-11-01 16:43 LRN * [r24661] src/util/configuration.c: More configuration debugging 2012-11-01 16:42 LRN * [r24660] src/util/configuration.c: Debug for dollar-expansion 2012-11-01 16:01 harsha * [r24656] src/testing/testing.c: fix 2012-11-01 11:55 harsha * [r24655] src/testing/testing.c: fixing testing failures on pi 2012-11-01 11:44 harsha * [r24654] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.conf: fix for port-conflicts while starting multiple controllers on same host 2012-10-31 21:13 harsha * [r24641] src/testing/testing.c: check all available addresses 2012-10-31 20:36 harsha * [r24640] src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c: fixes failing tests 2012-10-31 15:36 harsha * [r24639] src/include/gnunet_protocols.h, src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h, src/testbed/testbed_api.c: dead code 2012-10-31 15:10 wachs * [r24637] src/transport/plugin_transport_http_server.c: fix 2012-10-31 14:24 wachs * [r24636] src/transport/plugin_transport_http_server.c: error 2012-10-31 13:52 wachs * [r24635] src/ats-test: unused code 2012-10-31 12:21 harsha * [r24632] src/testbed/gnunet-helper-testbed.c: fix crashes when aborting testing drivers 2012-10-31 10:22 wachs * [r24630] src/ats-tool/gnunet-ats.c: docu 2012-10-31 10:13 harsha * [r24629] src/include/gnunet_stream_lib.h, src/stream/stream_api.c: fixes 2012-10-31 10:12 wachs * [r24628] doc/man/Makefile.am, doc/man/gnunet-ats.1: man 2012-10-31 09:15 harsha * [r24627] src/include/gnunet_testbed_service.h, src/mesh/gnunet-regex-profiler.c, src/testbed/gnunet-testbed-profiler.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed.conf.in, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_hosts.c: locate helpers in libexec 2012-10-30 23:03 harsha * [r24626] src/util/helper.c: for starting up non gnunet helpers (SSH for example) 2012-10-30 22:26 szengel * [r24625] src/mesh/gnunet-regex-profiler.c, src/mesh/gnunet-service-mesh.c, src/mesh/regex_profiler_test.conf: mesh regex profiler 2012-10-30 22:12 LRN * [r24624] src/datacache/plugin_datacache_sqlite.c, src/datastore/plugin_datastore_sqlite.c, src/fs/fs_getopt.c, src/namestore/plugin_namestore_sqlite.c: Fix ENABLE_NLS usage ENABLE_NLS is for gettext only, it's not an indicator of nl_langinfo availability. Use unistring instead of nl_langinfo, since unistring is always there. GNUnet supports UTF-8 now (or should support), so most conversions are unnecessary anyway. 2012-10-30 22:11 LRN * [r24623] src/util/strings.c, src/util/test_strings.c: Restore warnings, fix test compilation 2012-10-30 21:23 LRN * [r24622] src/util/strings.c: Just use unistring 2012-10-30 21:22 LRN * [r24621] src/util/strings.c: Missing include 2012-10-30 21:08 LRN * [r24619] src/util/os_installation.c: W32: Fix get_path_from_module_filename() 2012-10-30 21:08 LRN * [r24618] src/util/strings.c: Allow using libunistring for string conversion 2012-10-29 16:41 szengel * [r24597] src/mesh/gnunet-regex-profiler.c: sequential mesh service connects and regex announcing in regex profiler 2012-10-29 16:14 grothoff * [r24593] src/arm/Makefile.am, src/arm/do_start_process.c, src/ats-tool, src/ats/Makefile.am, src/chat/Makefile.am, src/chat/test_chat.c, src/chat/test_chat_private.c, src/core/Makefile.am, src/core/test_core_api.c, src/core/test_core_api_reliability.c, src/core/test_core_api_start_only.c, src/core/test_core_quota_compliance.c, src/datastore/Makefile.am, src/dht/Makefile.am, src/dns/Makefile.am, src/dv/Makefile.am, src/exit/Makefile.am, src/fs/Makefile.am, src/gns/Makefile.am, src/hostlist/Makefile.am, src/hostlist/test_gnunet_daemon_hostlist.c, src/hostlist/test_gnunet_daemon_hostlist_learning.c, src/hostlist/test_gnunet_daemon_hostlist_reconnect.c, src/include/gnunet_os_lib.h, src/lockmanager/Makefile.am, src/mesh/Makefile.am, src/namestore/Makefile.am, src/nat/Makefile.am, src/nse/Makefile.am, src/peerinfo/Makefile.am, src/pt/Makefile.am, src/regex, src/statistics/Makefile.am, src/statistics/test_statistics_api.c, src/statistics/test_statistics_api_loop.c, src/statistics/test_statistics_api_watch.c, src/statistics/test_statistics_api_watch_zero_value.c, src/template/Makefile.am, src/testbed/Makefile.am, src/testing/testing.c, src/topology/Makefile.am, src/transport/Makefile.am, src/util, src/util/Makefile.am, src/util/helper.c, src/util/os_installation.c, src/util/test_resolver_api.c, src/vpn/Makefile.am: installing all service, daemon and helper binaries to lib/gnunet/libexec/; updating code to run binaries from new location, which is no longer in PATH 2012-10-29 15:43 harsha * [r24592] src/testing/testing.c: starting testing processes with a low priority to not overwhelm testing hosts 2012-10-28 22:35 szengel * [r24583] src/mesh/gnunet-regex-profiler.c: batch regex announcing in profiler 2012-10-26 18:23 szengel * [r24571] src/mesh/mesh_api.c: passing mesage header instead of message 2012-10-26 16:10 szengel * [r24570] src/regex/gnunet-regex-simulation-profiler.c: using prepared statements for regex simulation profiler 2012-10-26 15:59 szengel * [r24569] src/mesh/gnunet-regex-profiler.c: added max path compression parameter to regex profiler 2012-10-26 15:10 wachs * [r24566] src/statistics/gnunet-statistics.c: gnunet-statistics can retrieve stats from remote hosts without config 2012-10-26 15:08 wachs * [r24565] src/util/strings.c: memory leak: is const 2012-10-26 12:58 harsha * [r24562] src/fs/fs_test_lib.c, src/gns/test_gns_dht_three_peers.c, src/include/gnunet_testbed_service.h, src/mesh/gnunet-regex-profiler.c, src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed_api_testbed.c, src/testbed/testbed_api_topology.c: removed GNUNET_TESTBED_operation_cancel 2012-10-26 12:22 wachs * [r24561] src/transport/plugin_transport_unix.c: simplify retry mechanism 2012-10-26 11:38 wachs * [r24560] src/transport/plugin_transport_unix.c: change 2012-10-26 08:28 wachs * [r24559] src/transport/gnunet-service-transport_neighbours.c, src/transport/plugin_transport_udp.c: more changes 2012-10-26 08:17 wachs * [r24558] src/transport/gnunet-service-transport_neighbours.c: bug hunting 2012-10-26 08:07 wachs * [r24557] src/ats/gnunet-service-ats_performance.c: fix unused variable 2012-10-26 07:02 wachs * [r24556] src/transport/plugin_transport_wlan.c: use calculated delays /w wlan 2012-10-25 19:37 LRN * [r24554] src/ats/gnunet-service-ats_addresses.c: Fix naming, HEAD fails to compile here 2012-10-25 19:37 LRN * [r24553] src/util/network.c: bratao: W32: Optimize ..._select() implementation Begin with a quick sequential check of sockets and pipes, and bail out if something is selected already, or if timeout is zero, avoiding overhead of setting up all the stuff necessary to sleep until either a socket or a pipe wakes us up. 2012-10-25 15:13 wachs * [r24552] src/transport/plugin_transport_wlan.c: workaround 2012-10-25 15:04 wachs * [r24551] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_performance.c: doxygen 2012-10-25 14:59 wachs * [r24549] src/ats-tool/gnunet-ats.c: doxygen 2012-10-25 14:46 wachs * [r24545] src/ats-tool/gnunet-ats.c: monitor mode 2012-10-25 14:21 wachs * [r24544] src/ats/gnunet-service-ats_addresses.h: some docu 2012-10-25 14:21 wachs * [r24543] src/ats/gnunet-ats.c: move to ats-tool 2012-10-25 14:15 wachs * [r24541] configure.ac, src/Makefile.am: add ats-tool to buildsystem 2012-10-25 14:14 wachs * [r24540] src/ats-tool, src/ats-tool/Makefile.am, src/ats-tool/gnunet-ats.c: move ats-tool due to transport dependency 2012-10-25 13:56 wachs * [r24539] src/ats/Makefile.am, src/ats/gnunet-ats.c: gnunet-ats /w address printing support 2012-10-25 12:52 wachs * [r24537] src/ats/gnunet-service-ats_addresses.c: report only active addresses used 2012-10-25 12:33 wachs * [r24536] src/ats/gnunet-ats.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_performance.c, src/ats/gnunet-service-ats_performance.h: gnunet-ats working and bug 0002593 2012-10-25 11:57 szengel * [r24535] src/mesh/gnunet-regex-profiler.c, src/mesh/regex_profiler_test.conf: regex profiler fixes 2012-10-25 11:25 wachs * [r24533] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/ats/gnunet-service-ats_performance.c: changes 2012-10-24 21:32 szengel * [r24523] configure.ac, src/mysql/Makefile.am: libmysqlclient linking for /usr/lib64 (fedora 17) 2012-10-24 20:34 harsha * [r24522] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_operations.c, src/testbed/testbed_api.c, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_services.c, src/testbed/testbed_api_topology.c, src/testbed/x64_misc.supp: multiple operation queues for an operation 2012-10-24 16:08 harsha * [r24521] src/testbed/gnunet-service-testbed.c: removed exponential backoff while offering HELLO 2012-10-24 16:01 harsha * [r24518] src/testbed/testbed_api.c, src/testbed/testbed_api_topology.c: fixes 2012-10-24 13:24 wachs * [r24512] src/transport/plugin_transport_udp.c: fix 2012-10-24 13:22 wachs * [r24511] src/ats/gnunet-ats.c: basics 2012-10-24 12:56 wachs * [r24509] src/transport/plugin_transport_udp.c: fix 2012-10-24 12:29 wachs * [r24502] src/transport/plugin_transport_udp.c: coverity 2012-10-24 08:56 LRN * [r24499] src/transport/test_plugin_transport.c: Create directory for hostkey 2012-10-23 17:41 szengel * [r24492] src/mesh/Makefile.am: fix 2012-10-23 17:07 szengel * [r24489] src/mesh/Makefile.am, src/mesh/gnunet-regex-profiler.c: added libgnunetstatistics to regex profiler dependencies 2012-10-23 15:39 szengel * [r24488] src/mesh/gnunet-regex-profiler.c, src/mesh/regex_profiler_test.conf: regex profiler saving statistics 2012-10-23 15:11 wachs * [r24487] src/transport/plugin_transport_udp.c: timeout stats 2012-10-23 15:02 wachs * [r24486] src/transport/template_cfg_peer1.conf, src/transport/template_cfg_peer2.conf: conf 2012-10-23 14:46 szengel * [r24483] src/mesh/gnunet-regex-profiler.c: formatting 2012-10-23 14:42 szengel * [r24482] src/mesh/gnunet-regex-profiler.c: Added statistics service connection to regex profiler 2012-10-23 12:37 harsha * [r24472] src/testbed/gnunet-testbed-profiler.c: exit during errors too 2012-10-23 12:31 harsha * [r24471] src/testbed/gnunet-service-testbed.c: fix for crashing service while shutting down when peer create fails 2012-10-23 10:42 harsha * [r24470] src/testbed/gnunet-testbed-profiler.c: trying to fix win32 build 2012-10-23 09:13 szengel * [r24469] src/mesh/gnunet-regex-profiler.c, src/mesh/regex_profiler_test.conf: regex profiler fixes 2012-10-22 23:07 harsha * [r24468] src/testbed/gnunet-testbed-profiler.c: fix 2012-10-22 22:55 harsha * [r24467] src/include/gnunet_testbed_service.h: doc 2012-10-22 22:54 harsha * [r24466] src/testing/testing.c: fix 2012-10-22 22:29 harsha * [r24465] src/testbed/testbed_api_peers.c: fix 2012-10-22 21:30 harsha * [r24464] src/testbed/gnunet-testbed-profiler.c: fixes 2012-10-22 21:26 harsha * [r24463] src/testbed/gnunet-testbed-profiler.c: profiler topology option 2012-10-22 20:52 harsha * [r24462] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_topology_clique.c, src/testbed/testbed_api_topology.c: clique topology 2012-10-22 15:09 harsha * [r24459] src/testbed/gnunet-testbed-profiler.c: allow single host deployments 2012-10-22 14:25 harsha * [r24458] src/testbed/gnunet-testbed-profiler.c: fix 2012-10-22 13:58 harsha * [r24456] src/testbed/testbed_api.c: fix 2012-10-22 13:52 szengel * [r24455] src/mesh/gnunet-regex-profiler.c, src/mesh/regex_profiler_test.conf: regex profiler: measuring the time it takes to match all strings 2012-10-22 13:46 wachs * [r24454] src/fragmentation/fragmentation.c: fix 2012-10-22 12:34 harsha * [r24450] src/testbed/gnunet-testbed-profiler.c: less verbose 2012-10-22 11:57 harsha * [r24449] contrib/testbed_cleanup.sh, contrib/testbed_infiniband.conf: remove username part 2012-10-22 11:56 wachs * [r24448] src/transport/plugin_transport_http_client.c: doxygen errors 2012-10-22 11:51 harsha * [r24447] src/testbed/gnunet-testbed-profiler.c: disable auto retry 2012-10-22 11:44 harsha * [r24446] src/include/gnunet_testbed_service.h, src/testbed/gnunet-testbed-profiler.c, src/testbed/test_testbed_api_topology.c, src/testbed/testbed_api_topology.c: option for disabling auto retry 2012-10-21 17:36 harsha * [r24442] src/testbed/gnunet-service-testbed.c: simplify 2012-10-21 17:25 harsha * [r24441] src/testbed/gnunet-service-testbed.c: tracking forwarded operations 2012-10-21 15:24 szengel * [r24440] src/mesh/gnunet-regex-profiler.c: regex profiler: loading a set of search strings from a file 2012-10-21 08:55 harsha * [r24439] src/testbed/gnunet-service-testbed.c: tracking forwarded operations as part of link controllers operation 2012-10-20 10:39 szengel * [r24437] src/mesh/gnunet-regex-profiler.c, src/mesh/regex_profiler_test.conf: Updated regex profiler config with mesh and dht default arm services 2012-10-20 09:31 harsha * [r24436] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_topology.c: removed duplicate definition 2012-10-19 17:50 szengel * [r24434] src/mesh/gnunet-regex-profiler.c: Aborting profiler after a timeout 2012-10-19 16:38 szengel * [r24433] src/mesh/gnunet-regex-profiler.c: regex profiler fix 2012-10-19 14:32 harsha * [r24429] src/testbed/gnunet-testbed-profiler.c: doxygen 2012-10-19 14:24 szengel * [r24428] src/regex/regex.c: coverity 2012-10-19 14:19 harsha * [r24427] src/testbed/gnunet-service-testbed.c: fix 2012-10-19 13:56 harsha * [r24425] src/testbed/test_testbed_api_topology.c: reverted to version 24399 2012-10-19 13:47 harsha * [r24424] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_topology.c, src/testbed/testbed_api_topology.c: counting references in overlay connect context 2012-10-19 12:37 harsha * [r24422] src/testbed/gnunet-service-testbed.c: cleanup rocc 2012-10-19 12:15 harsha * [r24421] src/testbed/gnunet-service-testbed.c: removed redundancy 2012-10-19 12:01 harsha * [r24420] src/testbed/gnunet-service-testbed.c: remove remote peers upon destroy 2012-10-19 11:42 wachs * [r24419] src/transport/plugin_transport_udp.c: coverity 2012-10-19 10:17 szengel * [r24416] src/mesh/gnunet-regex-profiler.c: mesh connections in regex profiler 2012-10-19 10:15 szengel * [r24415] src/mesh/gnunet-regex-profiler.c, src/mesh/regex_profiler_test.conf: mesh connections in regex profiler 2012-10-19 08:39 harsha * [r24413] contrib/testbed_infiniband_results, contrib/testbed_infiniband_results/30000_connections_90000_peers_30_poc.txt, contrib/testbed_infiniband_results/6000_connections_10000_peers_100_poc.txt, contrib/testbed_infiniband_results/6000_connections_10000_peers_20_poc.txt, contrib/testbed_infiniband_results/6000_connections_10000_peers_30_poc.txt, contrib/testbed_infiniband_results/6000_connections_20000_peers.txt, contrib/testbed_infiniband_results/6000_connections_40000_peers.txt, contrib/testbed_infiniband_results/6000_connections_60000_peers.txt, contrib/testbed_infiniband_results/6000_connections_60000_peers_5_poc.txt, contrib/testbed_infiniband_results/6000_connections_80000_peers_20_poc.txt, contrib/testbed_infiniband_results/6000_connections_80000_peers_5_poc.txt: testbed results 2012-10-18 23:02 harsha * [r24409] src/testbed/gnunet-testbed-profiler.c: parameterized how many failures to tolerate 2012-10-18 18:01 szengel * [r24407] src/mesh/test_mesh_regex.c: doxygen 2012-10-18 18:00 szengel * [r24406] src/mesh/gnunet-regex-profiler.c, src/mesh/regex_profiler_test.conf: regex profiler 2012-10-18 16:38 szengel * [r24405] src/include/gnunet_testbed_service.h, src/testbed/testbed_api_hosts.c: Exposing GNUNET_TESTBED_host_get_hostname 2012-10-18 15:53 harsha * [r24404] src/testbed/gnunet-testbed-profiler.c: print statistics 2012-10-18 15:12 wachs * [r24401] src/transport/gnunet-service-transport_validation.c, src/transport/plugin_transport_udp.c: preliminary workaround for 0002549 2012-10-18 14:52 harsha * [r24400] src/testbed/testbed_api.c: use controller's host when slave host is NULL 2012-10-18 12:51 wachs * [r24398] src/transport/plugin_transport_udp.c: new statistics 2012-10-17 20:17 szengel * [r24383] src/regex/regex.c, src/regex/test_regex_iterate_api.c: fix 2012-10-17 18:16 harsha * [r24377] src/testbed/gnunet-testbed-profiler.c: peer destroy state 2012-10-17 18:11 harsha * [r24376] contrib/infiniband_cluster.hosts, contrib/testbed_infiniband.conf: more cluster nodes 2012-10-17 18:08 harsha * [r24375] src/testbed/gnunet-service-testbed.c: stop peer before destroying it 2012-10-17 17:39 szengel * [r24373] src/mesh/Makefile.am, src/mesh/gnunet-regex-profiler.c, src/mesh/regex_profiler_test.conf, src/regex/Makefile.am, src/regex/gnunet-regex-profiler.c, src/regex/regex_profiler_test.conf: Moved regex profiler to mesh, because of dependencies. 2012-10-17 16:39 wachs * [r24371] src/transport/plugin_transport_udp.c: stat 2012-10-17 16:33 szengel * [r24370] src/regex/gnunet-regex-profiler.c: doxygen, indentation 2012-10-17 16:22 harsha * [r24368] src/testbed/testbed.conf.in, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c: new operation queue for limiting overlay connects 2012-10-17 15:52 wachs * [r24366] src/transport/plugin_transport_udp.c: new statistic values and fixes 2012-10-17 15:26 harsha * [r24364] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-profiler.c: fixs for crash while adding slaves with id greater than 9 2012-10-17 15:16 wachs * [r24362] src/transport/plugin_transport_udp.c: minors 2012-10-17 14:40 szengel * [r24359] src/regex/Makefile.am, src/regex/gnunet-regex-profiler.c: doxygen 2012-10-17 14:20 wachs * [r24357] src/transport/plugin_transport_udp.c: clean up and fixes 2012-10-17 13:53 harsha * [r24356] src/testbed/gnunet-service-testbed.c: fixed memory leak 2012-10-17 13:29 harsha * [r24354] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed.c.new, src/testbed/test_testbed_api_3peers_3controllers.c: a decent way to auto link controllers during overlay connects 2012-10-17 13:10 wachs * [r24353] src/transport/plugin_transport_udp.c: improve code while debugging 2012-10-17 09:33 wachs * [r24350] src/transport/Makefile.am, src/transport/test_plugin_hostkey, src/transport/test_plugin_transport.c: use precomputed hostkey for slow computers 2012-10-17 09:22 wachs * [r24349] src/transport/test_plugin_transport.c: fix 2012-10-17 09:05 wachs * [r24348] src/transport/test_plugin_transport.c: crash in test due to pending callbacks 2012-10-17 07:39 wachs * [r24346] src/dv/dv_api.c: overhead for dv 2012-10-16 15:44 harsha * [r24345] src/testbed/gnunet-service-testbed.c.new, src/testbed/testbed_api_hosts.c: checkpoint save 2012-10-16 14:59 wachs * [r24344] src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c: doxygen 2012-10-16 14:43 wachs * [r24343] src/transport/plugin_transport_udp.c, src/transport/transport_api.c: changes 2012-10-16 14:30 wachs * [r24342] src/transport/plugin_transport_udp.c, src/transport/transport_api.c: stats + delay 2012-10-16 13:25 wachs * [r24341] src/transport/gnunet-service-transport_clients.c, src/transport/plugin_transport_udp.c, src/transport/transport.h, src/transport/transport_api.c: changes 2012-10-16 12:19 wachs * [r24340] src/transport/gnunet-service-transport_neighbours.c: debugging 2012-10-16 12:11 wachs * [r24339] src/include/gnunet_transport_plugin.h: header 2012-10-16 11:43 wachs * [r24338] src/transport/gnunet-service-transport_neighbours.c: rm error msg 2012-10-16 11:42 wachs * [r24337] src/transport/gnunet-service-transport_neighbours.c, src/transport/plugin_transport_unix.c: fix for overhead measurement in unix,also fixes assertion in neighbours 1152 2012-10-16 11:20 wachs * [r24336] src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_neighbours.h, src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c: overhead reporting 2012-10-16 08:20 wachs * [r24335] src/transport/plugin_transport_udp.c, src/transport/plugin_transport_udp.h: changes 2012-10-16 08:08 wachs * [r24334] src/transport/plugin_transport_udp.c: documentation and preparation 2012-10-15 21:30 harsha * [r24331] src/testbed/gnunet-service-testbed.c: host registration queues in slave handles 2012-10-15 20:24 harsha * [r24329] src/testbed/gnunet-service-testbed.c: peer to use slave handle 2012-10-15 19:48 harsha * [r24328] src/testbed/test_testbed_api_topology.c: reducing peers to avoid timeouts 2012-10-15 17:22 szengel * [r24325] src/regex/gnunet-regex-profiler.c, src/regex/test_regex_big.c, src/regex/test_regex_big.conf: replacing test_regex_big with gnunet-regex-profiler 2012-10-15 17:06 szengel * [r24324] src/include/gnunet_regex_lib.h: fix 2012-10-15 17:06 szengel * [r24323] src/regex/Makefile.am, src/regex/gnunet-regex-profiler.c, src/regex/regex.c, src/regex/regex_internal.h, src/regex/regex_profiler_test.conf, src/regex/test_regex_graph_api.c, src/regex/test_regex_iptoregex.c, src/regex/test_regex_iterate_api.c: renamed test_regex_big / fixes 2012-10-15 16:17 harsha * [r24322] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api_topology.c: logging and fixes 2012-10-15 10:51 harsha * [r24321] src/testbed/gnunet-service-testbed.c: timeouts during forwarded overlay connects 2012-10-14 16:48 harsha * [r24314] src/testbed/gnunet-testbed-profiler.c: output status for connects 2012-10-14 13:56 harsha * [r24312] src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_topology.c: peer linking 2012-10-14 13:23 harsha * [r24310] src/testbed/test_testbed_api_topology.c, src/testbed/testbed_api_topology.c: Random graph topology 2012-10-14 12:50 harsha * [r24308] src/testbed/gnunet-testbed-profiler.c: corrected profiling time measurement for peer create 2012-10-14 12:36 harsha * [r24307] src/testbed/gnunet-testbed-profiler.c: peer start 2012-10-14 12:21 harsha * [r24306] src/include/gnunet_testbed_service.h, src/nse/gnunet-nse-profiler.c, src/regex/test_regex_big.c, src/testbed/gnunet-testbed-profiler.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_2peers_1controller.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_testbed.c: operation closure in peer start 2012-10-14 10:57 harsha * [r24305] src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h: doxygen 2012-10-14 10:49 harsha * [r24304] src/testbed/gnunet-testbed-profiler.c: towards peer create 2012-10-14 09:30 harsha * [r24303] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-profiler.c: fixes 2012-10-14 09:19 harsha * [r24302] src/testbed/gnunet-testbed-profiler.c: removed peer destroy. May leak memory, but anyway we need that till the end 2012-10-14 09:18 harsha * [r24301] src/testbed/gnunet-testbed-profiler.c: fix 2012-10-14 08:45 harsha * [r24300] src/testbed/gnunet-testbed-profiler.c: peer create 2012-10-12 16:14 harsha * [r24297] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-profiler.c: fixes 2012-10-12 15:44 harsha * [r24296] src/testbed/gnunet-testbed-profiler.c: slave startup 2012-10-12 14:58 harsha * [r24293] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed_api.c: fixes 2012-10-12 14:01 harsha * [r24292] contrib/infiniband_cluster.hosts: correct ips 2012-10-12 13:40 harsha * [r24291] src/testbed/gnunet-testbed-profiler.c, src/testbed/testbed_api.c: host registrations in profiler 2012-10-12 13:39 harsha * [r24290] contrib/infiniband_cluster.hosts: added infiniband hosts 2012-10-12 12:13 harsha * [r24289] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_3peers_3controllers.c: send self config during overlay connect 2012-10-12 10:31 harsha * [r24288] src/testbed/testbed_api_hosts.c: no auto allocation during scanf 2012-10-12 10:17 harsha * [r24287] src/testbed/gnunet-testbed-profiler.c: fix w32 build 2012-10-12 10:11 harsha * [r24286] src/testbed/testbed_api_testbed.c: tolerate stopped peers while shutting down testbed_run 2012-10-12 09:21 harsha * [r24285] src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api_hosts.c: fixing scanf failures 2012-10-12 09:02 harsha * [r24284] src/include/gnunet_testbed_service.h, src/testbed/gnunet-testbed-profiler.c, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api_hosts.c: host file support for testbed profiler 2012-10-12 07:47 harsha * [r24283] src/testbed/testbed_api_hosts.c: fixes 2012-10-11 21:23 harsha * [r24280] src/include/gnunet_testbed_service.h, src/testbed/sample_hosts.txt, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api_hosts.c: fixes for invalid reads 2012-10-11 20:45 harsha * [r24279] src/testbed/sample_hosts.txt, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api_hosts.c: host loading from file 2012-10-11 18:54 harsha * [r24278] src/testing/testing.c: using header-defined hostkeyfilesize 2012-10-11 15:43 harsha * [r24270] src/testbed, src/testbed/Makefile.am, src/testbed/gnunet-testbed-profiler.c: testbed profiler 2012-10-11 14:45 harsha * [r24269] src/testbed/testbed_api.c: disabling hostkey checking for localhost 2012-10-11 13:34 harsha * [r24264] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h: working overlay connect with implicit suboperations 2012-10-11 11:03 harsha * [r24262] src/testbed/gnunet-service-testbed.c: overlay connect suboperations 2012-10-10 19:33 harsha * [r24258] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h: controller linking with host ids 2012-10-10 15:37 harsha * [r24253] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h: checkpoint save 2012-10-10 10:59 harsha * [r24252] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_services.c: operation id generation from controller host id and internal counter 2012-10-10 09:38 harsha * [r24250] src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: towards handling suboperations during overlay connect 2012-10-09 17:44 harsha * [r24236] src/include/gnunet_protocols.h: fixing compile 2012-10-09 14:03 harsha * [r24234] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-service-testbed.c.new, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.c.new: towards on-demand configuration retrival for remote controllers during overlay connect operations 2012-10-08 22:41 LRN * [r24231] src/util/network.c: Implement non-inheritable sockets for W32 2012-10-08 17:18 szengel * [r24227] src/regex/test_regex_big.c: mesh service connect skeleton 2012-10-08 14:50 harsha * [r24226] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c: added get peer config forwarding 2012-10-08 13:28 harsha * [r24224] src/testbed/gnunet-service-testbed.c: forwarding overlay request connect 2012-10-07 13:41 szengel * [r24214] src/regex/regex_graph.c: fix 2012-10-06 14:14 harsha * [r24206] src/testbed/test_testbed_api_topology.c: fail nicely 2012-10-06 14:02 harsha * [r24204] src/testbed/gnunet-service-testbed.c: exponential delay in offering HELLOs 2012-10-05 16:41 szengel * [r24198] src/regex/test_regex_big.c, src/regex/test_regex_big.conf: simple overlay connection working 2012-10-05 14:45 harsha * [r24197] src/regex/test_regex_big.c, src/regex/test_regex_big.conf: working test on inifiniband cluster 2012-10-05 14:12 harsha * [r24196] src/include/gnunet_testing_lib-new.h, src/testbed/gnunet-helper-testbed.c, src/testbed/gnunet-service-testbed.c, src/testbed/test_gnunet_helper_testbed.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_helper.h, src/testing/gnunet-testing.c, src/testing/test_testing_peerstartup.c, src/testing/test_testing_portreservation.c, src/testing/testing.c, src/transport/transport-testing.c: testing now includes valid hostname rewriting 2012-10-05 11:54 harsha * [r24192] src/util/gnunet-rsa.c: generate keys to use 2048 bit rsa 2012-10-05 10:08 szengel * [r24189] src/regex/test_regex_big.c, src/regex/test_regex_big.conf: regex testbed testcase 2012-10-04 14:02 harsha * [r24184] src/include/gnunet_testbed_service.h, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api.c: added operation closure to GNUNET_TESTBED_controller_link() 2012-10-04 13:54 harsha * [r24183] src/stream/stream_api.c: removed fixme 2012-10-04 12:55 wachs * [r24181] src/transport/gnunet-service-transport_neighbours.c: undo 2012-10-04 12:52 wachs * [r24180] src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_clients.h: not required 2012-10-04 12:47 wachs * [r24179] src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_clients.h, src/transport/gnunet-service-transport_neighbours.c, src/transport/plugin_transport_http_server.c: fix type issue 2012-10-04 12:28 harsha * [r24178] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_3peers_3controllers.c, src/testbed/test_testbed_api_3peers_3controllers.c.new, src/testbed/testbed_api.c: test case for overlay connect via lateral links 2012-10-04 09:11 harsha * [r24171] src/include/gnunet_stream_lib.h, src/stream/stream_api.c: doc 2012-10-04 08:53 harsha * [r24170] src/stream/stream_api.c: removed session id 2012-10-04 08:49 harsha * [r24169] src/stream/stream_api.c: moved read_io task and its corresponding timeout task to read handle 2012-10-02 14:54 harsha * [r24162] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api.c: test case for lateral connections between controllers 2012-10-02 12:16 harsha * [r24161] src/stream/perf_stream_api.c, src/stream/stream_api.c: fixing #2574 2012-10-02 09:33 harsha * [r24160] src/testbed/gnunet-service-testbed.c: allow lateral connections from other controllers 2012-10-02 08:54 harsha * [r24159] src/testbed/gnunet-service-testbed.c: slave get config service implementation 2012-10-02 08:05 harsha * [r24158] src/include/gnunet_testbed_service.h, src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.c: clean handling of slave 2012-10-01 15:04 harsha * [r24157] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_services.c: rename to extract_config_() 2012-10-01 14:59 harsha * [r24156] src/include/gnunet_protocols.h, src/include/gnunet_testbed_service.h, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_services.c: slave get config client part 2012-10-01 11:50 harsha * [r24155] src/testbed/test_testbed_api_2peers_1controller.c: remove duplicate specifier 2012-10-01 10:15 harsha * [r24154] src/gns/gnunet-gns-proxy.c: fixes #2573 2012-09-30 21:32 harsha * [r24153] src/testbed/test_testbed_api_3peers_3controllers.c.new: checkpoint save 2012-09-30 21:32 harsha * [r24152] src/include/gnunet_testbed_service.h, src/testbed/testbed_api.c: get slave config 2012-09-30 21:29 harsha * [r24150] src/include/gnunet_stream_lib.h: doc 2012-09-30 21:12 harsha * [r24149] src/stream/stream_api.c: fixing #2571 2012-09-30 16:25 LRN * [r24147] src/lockmanager/gnunet-service-lockmanager.c: Fix 0-terminator test in lockmanager 2012-09-30 15:20 harsha * [r24146] src/testbed, src/testbed/test_testbed_api.conf: disabling VPN to remove verbose warnings for VPN 2012-09-30 15:11 harsha * [r24145] src/stream/perf_stream_api.c, src/stream/test_stream_2peers.c, src/stream/test_stream_2peers_halfclose.c, src/stream/test_stream_big.c, src/stream/test_stream_local.c, src/stream/test_stream_sequence_wraparound.c: more fixes for #2570 2012-09-30 14:26 harsha * [r24144] src/lockmanager/test_lockmanager_api.c, src/lockmanager/test_lockmanager_api_acquireretry.c, src/lockmanager/test_lockmanager_api_lockrelease.c, src/lockmanager/test_lockmanager_api_servercrash.c: removed duplicate specifiers 2012-09-30 14:23 harsha * [r24143] src/testbed/test_gnunet_helper_testbed.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_2peers_1controller.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/test_testbed_api_test.c, src/testbed/test_testbed_api_testbed_run.c, src/testbed/test_testbed_api_topology.c: removing duplicate specifiers 2012-09-30 14:02 harsha * [r24142] src/stream/test_stream_2peers_halfclose.c, src/stream/test_stream_big.c, src/stream/test_stream_local.c, src/stream/test_stream_sequence_wraparound.c: fixes for #2570 2012-09-30 12:34 harsha * [r24141] src/stream/test_stream_2peers.c: clean exit while aborting 2012-09-30 12:04 LRN * [r24140] src/testbed/test_testbed_api_3peers_3controllers.c: Try to fix W32 builds 2012-09-30 08:25 harsha * [r24138] src/testbed/Makefile.am, src/testbed/test_testbed_api_2peers_2controllers.c, src/testbed/test_testbed_api_3peers_3controllers.c: rename 2012-09-30 02:05 LRN * [r24137] src/testing_old/testing.c: Short timeout for starting local services 2012-09-29 20:49 harsha * [r24132] src/testbed/test_testbed_api_2peers_2controllers.c: removed getaddrinfo 2012-09-29 19:36 LRN * [r24131] src/gns/gnunet-service-gns.c: Missing declarations 2012-09-29 18:34 harsha * [r24129] src/testbed/test_testbed_api_2peers_2controllers.c: towards starting 3 controllers on a single machine 2012-09-29 06:44 harsha * [r24125] src/testbed/gnunet-service-testbed.c: fixes #2568 2012-09-29 01:29 LRN * [r24124] src/transport/transport-testing.c: Fix a typo 2012-09-28 12:36 bartpolot * [r24098] src/include/gnunet_getopt_lib.h, src/util/getopt.c, src/util/getopt_helpers.c, src/util/service.c, src/util/test_getopt.c: Passing -v or -h options to a command no longer returns error code 2012-09-28 10:10 harsha * [r24089] src/testbed: svn ignore 2012-09-28 10:06 harsha * [r24086] src/testbed/Makefile.am, src/testbed/test_testbed_api_topology.c, src/testbed/testbed_api.c, src/testbed/testbed_api_topology.c: topology test case 2012-09-28 09:48 wachs * [r24080] src/transport/plugin_transport_http_client_old.c, src/transport/plugin_transport_http_server_old.c: rm old code 2012-09-28 09:36 harsha * [r24076] src/testbed/testbed_api_topology.c: implemented generic topology overlay connections 2012-09-27 22:55 LRN * [r24065] src/util/Makefile.am, src/util/win.c, src/util/win.cc: W32-specific platform stuff is now pure C 2012-09-27 19:40 grothoff * [r24063] contrib/pogen.sh, po/POTFILES.in, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/util/helper.c: improving PO set 2012-09-27 19:01 grothoff * [r24060] contrib/pogen.sh, src/arm/arm_api.c, src/arm/gnunet-arm.c, src/arm/gnunet-service-arm.c, src/chat/chat.c, src/datastore/plugin_datastore_sqlite.c, src/dv/test_transport_api_dv.c, src/fs/fs_namespace.c, src/fs/gnunet-service-fs_indexing.c, src/fs/gnunet-service-fs_pr.c, src/fs/gnunet-service-fs_push.c, src/gns/gnunet-gns-fcfsd.c, src/include/gnunet_common.h, src/namestore/gnunet-namestore.c, src/namestore/plugin_namestore_sqlite.c, src/topology/gnunet-daemon-topology.c, src/transport/gnunet-service-transport_blacklist.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_wlan.c, src/util/common_logging.c, src/util/gnunet-config.c: reducing error messages about missing configuration options by introducing new helper functions to print them uniformly 2012-09-27 14:19 szengel * [r24059] src/regex/test_regex_eval_api.c: fix 2012-09-27 14:11 szengel * [r24058] src/regex/test_regex_eval_api.c, src/regex/test_regex_graph_api.c, src/regex/test_regex_iptoregex.c, src/regex/test_regex_iterate_api.c, src/regex/test_regex_proofs.c: tests 2012-09-27 13:18 szengel * [r24054] src/include/gnunet_regex_lib.h, src/regex/Makefile.am, src/regex/regex.c, src/regex/test_regex_iptoregex.c: iptoregex test 2012-09-27 09:19 wachs * [r24034] src/transport/plugin_transport_udp.c: new statistics value to measure payload 2012-09-26 21:22 szengel * [r24025] src/regex/regex.c: ip/prefix to regex 2012-09-26 20:16 grothoff * [r24024] configure.ac, src/util/crypto_random.c: releaxing libgcrypt version check, fixing Debian #684997 2012-09-26 14:46 szengel * [r24019] src/regex/regex.c, src/regex/test_regex_iterate_api.c: fixes 2012-09-26 13:55 wachs * [r24018] src/transport/plugin_transport_unix.c: UNIX stats 2012-09-26 13:51 wachs * [r24017] src/transport/plugin_transport_wlan.c: WLAN stats 2012-09-26 13:39 harsha * [r24016] src/testbed/testbed.conf.in, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_topology.c: towards generic topology creation 2012-09-26 13:29 harsha * [r24014] src/include/gnunet_testbed_service.h: doc 2012-09-26 08:55 wachs * [r24006] src/transport/plugin_transport_http_client.c: changing type 2012-09-25 18:10 grothoff * [r24003] doc/man/gnunet-rsa.1, src/util/gnunet-rsa.c: turn gnunet-rsa into key generation tool 2012-09-25 15:32 harsha * [r24002] src/testbed/gnunet-service-testbed.c: fixes 2012-09-25 13:12 harsha * [r23991] src/testbed/gnunet-service-testbed.c: overlay connect using lateral connections 2012-09-25 12:09 harsha * [r23990] src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h, src/testbed/testbed_api_peers.c: added peer2_host field in overlay connect message 2012-09-25 11:44 harsha * [r23989] src/testbed/gnunet-service-testbed.c: overlay connect forwarding when peer1 is not local 2012-09-24 19:11 szengel * [r23982] src/regex/regex.c, src/regex/test_regex_iterate_api.c: regex: iteration improvements/fixes 2012-09-24 12:49 wachs * [r23979] src/gns/gns_api.c, src/gns/gnunet-gns.c, src/transport/transport-testing.c: coverity bugs 2012-09-24 12:39 wachs * [r23978] src/gns/gnunet-service-gns_resolver.c, src/util/os_priority.c, src/util/test_os_start_process.c: coverity bugs 2012-09-24 12:25 wachs * [r23977] src/gns/gns_api.c, src/gns/gnunet-service-gns_resolver.h: dozygen 2012-09-24 10:07 wachs * [r23974] src/transport/plugin_transport_http_client.c: hunting bugs 2012-09-24 10:05 wachs * [r23973] src/transport/plugin_transport_http_client.c: hunting bugs 2012-09-24 09:53 wachs * [r23972] src/transport/plugin_transport_http_client.c: changes 2012-09-24 08:31 LRN * [r23968] src/gns/Makefile.am: Add ldflags to gnunetgns_common 2012-09-24 07:34 LRN * [r23967] configure.ac: Use native srcdir for #includes 2012-09-24 05:18 LRN * [r23966] po/POTFILES.in: Remove non-existing files from POTFILES 2012-09-23 16:56 szengel * [r23960] src/regex/regex_internal.h, src/regex/test_regex_iterate_api.c: refactoring 2012-09-23 16:24 szengel * [r23959] src/regex/regex.c, src/regex/regex_internal.h: DFA path compression 2012-09-23 13:08 szengel * [r23958] src/regex/test_regex_eval_api.c: fixed leak 2012-09-23 07:39 harsha * [r23957] src/include/gnunet_testbed_service.h: doc 2012-09-23 07:38 harsha * [r23956] src/stream/perf_stream_api.c: measuring uplink and downlink 2012-09-22 22:10 harsha * [r23955] src/stream/stream_api.c: fixing stream data retransmissions 2012-09-22 09:01 LRN * [r23941] src/gns/Makefile.am: Fix gns dependencies 2012-09-21 12:15 wachs * [r23932] src/transport/gnunet-service-transport_clients.c, src/transport/gnunet-service-transport_plugins.c, src/transport/gnunet-service-transport_plugins.h: prefix based plugin lookup for transport 2012-09-21 12:15 wachs * [r23931] src/peerinfo-tool/gnunet-peerinfo_plugins.c: prefix based plugin lookup for peerinfo tool 2012-09-21 12:10 szengel * [r23930] src/pt/test_gnunet_vpn.c: Added warning to check the firewall when tests fail (which happend to me). The long diff is due to running pre-commit script prior to check-in. 2012-09-20 21:46 szengel * [r23927] src/regex/regex.c: optimizations 2012-09-20 13:48 grothoff * [r23923] src/exit/gnunet-helper-exit.c: give sysctl /dev/null instead of no stdin/stdout 2012-09-20 13:26 wachs * [r23919] src/transport/template_cfg_peer1.conf, src/transport/template_cfg_peer2.conf: no valgrind 2012-09-20 10:57 grothoff * [r23909] src/gns/gnocksy: tot tot 2012-09-19 12:51 wachs * [r23901] src/transport/plugin_transport_http_server.c, src/transport/transport.conf.in: move https cert location to servicehome 2012-09-19 09:27 wachs * [r23897] src/transport/plugin_transport_http_server.c: strip external hostname prefix && improve url parsing output 2012-09-18 15:46 harsha * [r23893] src/stream/perf_stream_api.c: 1 hop performance testing 2012-09-18 15:34 harsha * [r23891] src/testbed/testbed_api.c: fixing valgrind unconditional jump error 2012-09-18 14:09 harsha * [r23890] src/stream/perf_stream_api.c: case to show lowered throughtput if payload size if 64000 2012-09-18 14:08 harsha * [r23889] src/stream/stream_api.c: sequence difference calculation fixes while processing DATA_ACKs 2012-09-18 12:38 harsha * [r23881] src/testing/testing.c: appropriate logging string 2012-09-18 12:38 harsha * [r23880] src/testbed/test_testbed_api_2peers_2controllers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/test_testbed_api_testbed_run.c: fixes 2012-09-17 14:32 szengel * [r23863] src/regex/regex.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_graph_api.c: coverity 2012-09-17 13:20 grothoff * [r23854] src/datastore/datastore.conf.in: fixing Debian #684317 2012-09-17 13:18 grothoff * [r23853] src/transport/plugin_transport_udp.c, src/transport/plugin_transport_udp.h: fixing udp busyloop reported by LRN on #gnunet on 8-27 2012-09-17 10:45 grothoff * [r23845] src/core/gnunet-service-core.c, src/core/gnunet-service-core_kx.c, src/core/gnunet-service-core_kx.h, src/fs/fs_uri.c, src/include/gnunet_crypto_lib.h, src/include/gnunet_server_lib.h, src/mesh/gnunet-service-mesh.c, src/nse/gnunet-service-nse.c, src/peerinfo-tool/gnunet-peerinfo.c, src/transport/gnunet-service-transport.c, src/transport/test_plugin_transport.c, src/util/crypto_random.c, src/util/crypto_rsa.c, src/util/gnunet-rsa.c, src/util/server.c: fixing #1551/#2503 2012-09-17 10:09 harsha * [r23844] src/testbed/Makefile.am: test_testbed_api_2peers_2controllers to default tests 2012-09-17 10:09 harsha * [r23843] src/testbed/test_testbed_api_2peers_2controllers.c: checks for working local SSH 2012-09-17 10:06 harsha * [r23842] src/testbed/gnunet-service-testbed.c: doxygen fixes 2012-09-17 10:02 harsha * [r23840] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_2peers_2controllers.c: fixes and working testcase for 2peers_2controllers 2012-09-17 09:06 wachs * [r23838] src/util/helper.c: fix for "bad address " issue with wlan helper 2012-09-16 13:50 harsha * [r23836] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_2peers_2controllers.c, src/testbed/testbed_api_peers.c: new test case (not working) 2012-09-16 12:33 harsha * [r23835] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_2peers.c, src/testbed/test_testbed_api_2peers_1controller.c: rename 2012-09-16 11:51 harsha * [r23834] src/testbed/gnunet-service-testbed.c: extended rocc 2012-09-16 03:42 LRN * [r23832] src/dht/gnunet-dht-monitor.c: Remove duplicate cleanups 2012-09-15 18:53 grothoff * [r23830] src/nse/Makefile.am, src/nse/test_nse_multipeer.c: making nse multipeer test use testbed 2012-09-15 18:28 grothoff * [r23829] src/dht/gnunet-dht-monitor.c, src/dht/gnunet-dht-put.c: fixing #2544 2012-09-14 20:42 harsha * [r23828] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_services.c: coverity fixes 2012-09-14 20:07 harsha * [r23827] src/testbed/gnunet-service-testbed.c: handler for overlay request connect 2012-09-14 17:06 schanzen * [r23826] src/gns/gnunet-gns.c: leak 2012-09-14 14:53 harsha * [r23812] src/testbed/gnunet-service-testbed.c: 1/2 part - inter-host overlay connect 2012-09-14 14:05 harsha * [r23807] src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h: unstable checkpoint save 2012-09-14 13:18 wachs * [r23804] src/transport/plugin_transport_http_client.c: client side PUT disconnect 2012-09-14 12:48 harsha * [r23803] src/include/gnunet_protocols.h: messages for inter-controller overlay connect 2012-09-14 12:46 harsha * [r23802] src/testbed/gnunet-service-testbed.c: stop peers before destroying 2012-09-14 12:23 grothoff * [r23799] src/dht/gnunet-dht-monitor.c: fix 2012-09-14 12:14 harsha * [r23798] src/testbed/gnunet-service-testbed.c, src/testbed/misc.supp: add to routing if delegated host is subordinate 2012-09-14 11:51 harsha * [r23797] src/testbed/gnunet-service-testbed.c: more checks on while working on overlay connect request 2012-09-14 11:31 harsha * [r23790] src/testbed/gnunet-service-testbed.c: removed OCC state 2012-09-14 10:43 harsha * [r23788] src/testbed/testbed.h: added new message for inter-host overlay connects 2012-09-14 10:33 harsha * [r23787] src/testbed/gnunet-service-testbed.c: disambiguating local overlay connect 2012-09-14 09:02 wachs * [r23781] src/dht/gnunet-dht-get.c, src/dht/gnunet-dht-put.c: demux everywhere option for CLI 2012-09-14 07:57 grothoff * [r23773] src/dht/gnunet-dht-get.c: code cleanup 2012-09-13 09:25 szengel * [r23762] src/regex/regex.c, src/regex/regex_internal.h: comments 2012-09-12 20:25 harsha * [r23761] contrib/ssh-keys, src/stream/perf_stream_api.c: added work ssh key 2012-09-12 16:46 harsha * [r23760] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_2peers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/test_testbed_api_hosts.c, src/testbed/test_testbed_api_operations.c, src/testbed/testbed.h, src/testbed/testbed_helper.h: file end comment 2012-09-12 16:16 harsha * [r23759] src/testbed/test_testbed_api_2peers.c: tests to show overlay_connect on already connected peers doesn't fail 2012-09-12 13:43 harsha * [r23758] src/testbed/gnunet-service-testbed.c: removed dead code 2012-09-12 10:51 grothoff * [r23757] src/include/gnunet_testbed_service.h, src/nse/gnunet-nse-profiler.c: triple star fun done 2012-09-12 10:44 grothoff * [r23756] src/include/gnunet_testbed_service.h, src/nse/gnunet-nse-profiler.c, src/stream/stream_protocol.h, src/testbed/testbed_api_hosts.c: triple star fun 2012-09-12 10:37 harsha * [r23755] src/stream/perf_stream_api.c, src/stream/stream_api.c: fixes 2012-09-12 10:18 harsha * [r23754] src/stream/perf_stream_api.c: fix 2012-09-12 10:09 harsha * [r23753] src/stream/perf_stream_api.c: reasonable buffer for performance measurements 2012-09-12 10:04 harsha * [r23752] src/stream/perf_stream_api.c, src/stream/test_stream_big.c: stream performance - implemented 1 hop throughput calculation 2012-09-11 20:44 harsha * [r23751] src/stream/perf_stream_api.c: more scaffolding 2012-09-11 20:01 harsha * [r23750] src/stream/perf_stream_api.c: scaffolding 2012-09-11 14:12 harsha * [r23749] src/stream, src/stream/Makefile.am, src/stream/perf_stream_api.c: stub for stream performance tests 2012-09-11 12:55 harsha * [r23748] src/stream/stream_api.c: stream speedup fixes 2012-09-11 10:36 harsha * [r23747] src/stream/test_stream_big.c, src/stream/test_stream_sequence_wraparound.c: reduced payload size 2012-09-11 10:24 harsha * [r23746] src/include/gnunet_stream_lib.h, src/stream/mesh.supp, src/stream/stream_api.c: rename MAX_PACKET_SIZE option to MAX_PAYLOAD_SIZE 2012-09-11 09:37 harsha * [r23745] src/include/gnunet_stream_lib.h, src/stream/stream_api.c, src/stream/test_stream_big.c, src/stream/test_stream_sequence_wraparound.c: stream option to set packet size 2012-09-10 22:17 grothoff * [r23744] src/fs/fs_api.c, src/fs/fs_api.h, src/fs/fs_namespace.c, src/fs/fs_publish.c, src/fs/fs_search.c, src/fs/fs_uri.c, src/include/gnunet_fs_service.h: eliminating use of 'namespace' as a fieldname / variable name to be C++ compatible 2012-09-10 20:33 harsha * [r23743] src/include/gnunet_testbed_service.h, src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c: cleanup when operations fail 2012-09-10 19:19 grothoff * [r23742] src/namestore/namestore.conf.in: fixing Debian #686238 2012-09-10 19:01 grothoff * [r23741] src/nse/Makefile.am, src/nse/gnunet-nse-profiler.c: nse profiler _compiles_ against new testbed API 2012-09-10 18:58 grothoff * [r23740] src/include/gnunet_testbed_service.h, src/testbed/Makefile.am, src/testbed/testbed_api_statistics.c: adding another testbed API function: convenience function to get all stats from all peers 2012-09-10 14:08 szengel * [r23738] src/regex/regex.c, src/regex/test_regex_graph_api.c: removing temp file in graph test 2012-09-09 18:37 grothoff * [r23731] src/dv/Makefile.am: commenting out dead test 2012-09-09 18:36 grothoff * [r23730] doc/man/gnunet-search.1, src/fs/gnunet-search.c, src/include/gnunet_getopt_lib.h, src/util/getopt_helpers.c: new getopt helper function to parse relative time command line argument 2012-09-09 14:20 harsha * [r23725] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_services.c: error reporting in service_connect 2012-09-09 13:52 harsha * [r23724] src/include/gnunet_protocols.h, src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api_services.c: renamed GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONEVENT to GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT 2012-09-09 13:46 harsha * [r23723] src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: implemented continuations to testbed peer start/stop API 2012-09-09 13:41 grothoff * [r23722] src/testbed/testbed_api_peers.h: doxygen fix 2012-09-09 13:39 grothoff * [r23721] src/topology/Makefile.am, src/topology/test_gnunet_daemon_topology.c: migrating topology test to new testbed API 2012-09-09 13:28 grothoff * [r23720] src/fs/Makefile.am, src/fs/fs_test_lib.c, src/fs/fs_test_lib.h, src/fs/perf_gnunet_service_fs_p2p.c, src/fs/perf_gnunet_service_fs_p2p_respect.c, src/fs/test_fs_test_lib.c, src/fs/test_gnunet_service_fs_migration.c, src/fs/test_gnunet_service_fs_p2p.c: make fs tests build against new testbed library -- they do not pass yet 2012-09-08 19:19 grothoff * [r23716] configure.ac: clarify - kernel 2012-09-08 13:50 harsha * [r23711] src/stream/Makefile.am, src/stream/test_stream_2peers_halfclose.c: test_stream_2peers_halfclose to testbed 2012-09-07 16:53 harsha * [r23700] src/stream, src/stream/Makefile.am, src/stream/test_stream_2peers.c, src/stream/test_stream_2peers_new.c: migrate stream 2peers test to testbed 2012-09-07 16:38 szengel * [r23699] src/regex/Makefile.am, src/regex/regex.c, src/regex/regex_graph.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_graph_api.c, src/regex/test_regex_iterate_api.c: coverage 2012-09-07 12:04 wachs * [r23697] src/integration-tests/confs/c_bootstrap_server_w_massif.conf, src/integration-tests/gnunet_testing.py.in, src/integration-tests/test_mem_consumption.py: changes 2012-09-07 11:17 bartpolot * [r23695] src/mesh/gnunet-service-mesh.c, src/mesh/mesh_protocol.h: Added explicit keepalive to mesh 2012-09-07 10:03 wachs * [r23692] src/transport/plugin_transport_http_server.c: 2012-09-07 09:07 wachs * [r23687] src/transport/test_transport_api_multi_peer1.conf, src/transport/test_transport_api_multi_peer2.conf: error message on windows 2012-09-06 16:24 schanzen * [r23681] src/dns/dnsstub.c, src/include/gns_protocol.h: doxy 2012-09-06 15:51 grothoff * [r23676] src/dns/dnsstub.c, src/dns/gnunet-service-dns.c: fix use uninit 2012-09-05 13:36 harsha * [r23660] src/stream/mesh.supp: suppressions for mesh 2012-09-05 13:32 harsha * [r23659] src/stream/test_stream_2peers_new.c: fix 2012-09-05 13:20 wachs * [r23658] src/gns/Makefile.am, src/gns/test_gns_dht_three_peers.c: fix 2012-09-05 11:47 wachs * [r23657] src/gns/Makefile.am: does not compile due to api changes ... 2012-09-05 11:44 harsha * [r23656] src/include/gnunet_testbed_service.h, src/testbed/test_testbed_api.c, src/testbed/testbed_api_services.c: service connect callback instead of operation completion callback 2012-09-05 10:50 harsha * [r23655] src/include/gnunet_testbed_service-new.h, src/include/gnunet_testbed_service.h, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_2peers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/test_testbed_api_test.c, src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h, src/testbed/testbed_api_services.c: changed testbed API to include convenience callbacks 2012-09-05 09:00 wachs * [r23651] src/gns/test_gns_dht_three_peers.c: test working, but fails 2012-09-05 08:33 wachs * [r23650] src/gns/test_gns_dht_three_peers.c: more 2012-09-05 08:28 wachs * [r23649] src/gns/test_gns_dht_default.conf, src/gns/test_gns_dht_three_peers.c: do not autostart: I have to copy zonefile 2012-09-05 07:46 wachs * [r23646] src/gns/Makefile.am, src/gns/test_gns_dht_three_peers.c: use precomputed zonekeys 2012-09-05 07:16 wachs * [r23645] src/Makefile.am: install testbed 2012-09-05 06:51 wachs * [r23644] src/gns/Makefile.am: fix 2012-09-04 18:00 harsha * [r23640] src/include/gnunet_testbed_service-new.h, src/include/gnunet_testbed_service.h.new: new testbed interface 2012-09-04 14:46 harsha * [r23631] src/include/gnunet_testbed_service.h.new: save 2012-09-04 14:09 harsha * [r23628] src/stream/Makefile.am: new stream/testbed testcase into defaults 2012-09-04 14:09 harsha * [r23627] src/testbed/test_testbed_api.conf: enable offline checks 2012-09-04 13:59 grothoff * [r23626] contrib/gnunet.doxy: updating doxygen options 2012-09-04 13:50 harsha * [r23625] src/testbed/test_testbed_api_2peers.c: sane timeout 2012-09-04 12:45 grothoff * [r23617] src/gns/gnunet-service-gns_resolver.c: check return value from sendto 2012-09-04 12:43 grothoff * [r23616] src/util/disk.c: mark fcntl return value as intentionally unchecked 2012-09-04 12:24 harsha * [r23613] src/stream, src/stream/Makefile.am, src/stream/stream_api.c, src/stream/stream_protocol.h, src/stream/test_stream_2peers_new.c: new stream testcase using testbed 2012-09-04 11:14 wachs * [r23607] src/gns/test_gns_proxy.c: shutdown 2012-09-04 10:28 harsha * [r23604] src/testbed/gnunet-service-testbed.c: sane logging and code 2012-09-04 10:01 wachs * [r23603] src/transport/plugin_transport_http_client.c: fix unload 2012-09-04 08:48 wachs * [r23601] src/gns/test_gns_simple_lookup.conf: no valgrind 2012-09-04 08:47 wachs * [r23600] src/gns/gnunet-service-gns_resolver.c, src/gns/test_gns_simple_lookup.conf: unaligned memory access 2012-09-04 06:52 wachs * [r23598] src/gns/test_gns_max_queries.c, src/gns/test_gns_ns_lookup.c, src/gns/test_gns_simple_shorten.c, src/gns/test_gns_simple_srv_lookup.c: minor fixes 2012-09-03 15:25 wachs * [r23596] src/gns/Makefile.am, src/gns/test_gns_revocation.c: next 2012-09-03 15:04 wachs * [r23593] src/gns/Makefile.am, src/gns/test_gns_max_queries.c: next one 2012-09-03 13:25 grothoff * [r23573] src/gns/gnunet-dns2gns.c, src/gns/gnunet-service-gns_resolver.c: better log message, fixing stale task 2012-09-03 13:07 harsha * [r23571] src/include/gnunet_testbed_service.h: fix 2012-09-03 13:00 grothoff * [r23570] src/util/service.c: always allow root 2012-09-03 12:42 wachs * [r23568] src/integration-tests/Makefile.am: fix 2012-09-03 12:03 wachs * [r23566] src/gns/Makefile.am, src/gns/test_gns_simple_get_authority.c, src/gns/test_gns_simple_shorten.c: test 2012-09-03 11:44 wachs * [r23564] src/gns/test_gns_simple_shorten.c: fix 2012-09-03 11:26 wachs * [r23563] src/gns/Makefile.am, src/gns/test_gns_simple_shorten.c: test porting 2012-09-03 10:45 harsha * [r23562] src/testbed/test_testbed_api_test.c, src/testbed/testbed_api_test.c, src/testbed/testbed_api_testbed.c: controller callback added in GNUNET_TESTBED_test_run 2012-09-03 10:12 harsha * [r23561] src/testbed/testbed.h: doc 2012-09-02 16:33 grothoff * [r23557] src/dht/dht.conf.in: typo 2012-09-02 14:06 grothoff * [r23556] src/fs/fs_search.c: commenting code 2012-09-02 12:51 grothoff * [r23555] src/dht/dht.conf.in, src/dht/gnunet-service-dht_neighbours.c: adding DHT option to disable calls to try connect 2012-09-02 11:17 harsha * [r23554] src/include/gnunet_testbed_service.h, src/testbed/testbed_api_test.c, src/testbed/testbed_api_testbed.c: input checks 2012-09-02 10:25 harsha * [r23553] contrib/ssh-keys: removed testbed testing key 2012-09-01 16:08 harsha * [r23550] src/testbed/test_testbed_api_testbed_run.c, src/testbed/testbed_api_testbed.c: repect event mask before calling event callback 2012-09-01 15:44 harsha * [r23549] src/testbed/Makefile.am: added new testcase to default checks 2012-09-01 15:42 harsha * [r23548] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api_test.c, src/testbed/test_testbed_api_testbed_run.c, src/testbed/testbed_api_test.c, src/testbed/testbed_api_testbed.c: tests for testbed_test_run and some fixes 2012-08-31 16:24 harsha * [r23546] src/testbed/testbed_api_test.c: implemented GNUNET_TESTBED_test_run 2012-08-31 16:23 harsha * [r23545] src/testbed/testbed_api_testbed.c: restructuring and checks 2012-08-31 13:32 wachs * [r23544] src/transport/test_transport_api_http_reverse_peer2.conf: a config file 2012-08-31 13:25 wachs * [r23543] src/transport/Makefile.am: changes 2012-08-31 13:24 wachs * [r23542] src/transport/transport.conf.in: external host 2012-08-31 12:24 wachs * [r23541] src/transport/transport.conf.in: config for new http/s plugins 2012-08-31 12:05 harsha * [r23540] src/testbed/test_testbed_api_testbed_run.c, src/testbed/testbed_api_testbed.c: check if peer has already been stopped before attempting to stop it again 2012-08-31 11:45 wachs * [r23537] src/transport/plugin_transport_http_server.c: doxygen fix 2012-08-31 11:41 wachs * [r23536] src/transport/plugin_transport_http_server.c: cleanup 2012-08-31 11:07 harsha * [r23535] src/lockmanager/gnunet-service-lockmanager.c, src/lockmanager/lockmanager_api.c, src/lockmanager/test_lockmanager_api.c, src/lockmanager/test_lockmanager_api_acquireretry.c, src/lockmanager/test_lockmanager_api_lockrelease.c, src/lockmanager/test_lockmanager_api_servercrash.c: indentation standard 2012-08-31 11:03 wachs * [r23534] src/transport/Makefile.am: makefile 2012-08-31 10:57 harsha * [r23533] src/testbed, src/testbed/Makefile.am, src/testbed/gnunet-helper-testbed.c, src/testbed/gnunet-testbed-helper.c, src/testbed/test_gnunet_helper_testbed.c, src/testbed/test_gnunet_testbed_helper.c, src/testbed/testbed_api.c, src/testbed/testbed_helper.h: renamed gnunet-testbed-helper to gnunet-helper-testbed 2012-08-31 10:56 wachs * [r23532] src/transport/plugin_transport_http_client.c: cleanup for http_client 2012-08-31 10:36 harsha * [r23531] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-helper.c, src/testbed/test_gnunet_testbed_helper.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_2peers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/test_testbed_api_hosts.c, src/testbed/test_testbed_api_operations.c, src/testbed/test_testbed_api_testbed_run.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h, src/testbed/testbed_api_services.c, src/testbed/testbed_api_test.c, src/testbed/testbed_api_testbed.c, src/testbed/testbed_api_topology.c, src/testbed/testbed_helper.h: adhering to indentation standard 2012-08-31 10:06 harsha * [r23530] src/testbed/Makefile.am: added testbed_run test to default checks 2012-08-31 10:05 harsha * [r23529] src/testbed/test_testbed_api_testbed_run.c, src/testbed/testbed_api_testbed.c: stop peers before destroying them 2012-08-31 07:52 harsha * [r23528] src/include/gnunet_testbed_service.h, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_testbed_run.c, src/testbed/testbed_api_testbed.c, src/testbed/x64_misc.supp: Removed RunHandle return from GNUNET_TESTBED_run 2012-08-30 19:54 harsha * [r23527] src/testbed/testbed_api.c: api handler for operation fail event 2012-08-30 19:53 harsha * [r23526] src/testbed/testbed_api_peers.c: peer_create starts with 0 2012-08-30 19:52 harsha * [r23525] src/testbed/gnunet-service-testbed.c: peer_list handling fixes 2012-08-30 18:41 grothoff * [r23522] src/fs/fs_uri.c: fixing #2530 2012-08-29 22:46 harsha * [r23512] src/testbed/gnunet-service-testbed.c: fixes 2012-08-29 22:23 harsha * [r23511] src/testbed, src/testbed/test_testbed_api_testbed_run.c: added the forgotten test case 2012-08-29 22:10 harsha * [r23510] src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api_testbed.c: GNUNET_TESTBED_run and test cases 2012-08-29 16:39 harsha * [r23508] src/include/gnunet_testbed_service.h: GNUNET_TESTBED_run to return a handle which can be used for clean shutdown 2012-08-29 14:56 harsha * [r23501] src/testbed/testbed_api.c, src/testbed/testbed_api_testbed.c: checkpoint save for testbed_run 2012-08-29 13:18 wachs * [r23498] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/test_plugin_transport.c: changes 2012-08-29 13:09 grothoff * [r23497] configure.ac, src/dns/gnunet-service-dns.c, src/exit/gnunet-daemon-exit.c, src/fs/fs_dirmetascan.c, src/include/gnunet_helper_lib.h, src/testbed/test_gnunet_testbed_helper.c, src/testbed/testbed_api.c, src/transport/plugin_transport_wlan.c, src/transport/test_plugin_transport.c, src/util/common_allocation.c, src/util/helper.c, src/vpn/gnunet-service-vpn.c: only use control pipe with helpers IF the helper actually supports it 2012-08-29 12:35 grothoff * [r23494] src/include/gnunet_testing_lib-new.h, src/testing/testing.c: extend API to enalbe exclusive port ranges to be specified for testing-system objects 2012-08-29 09:14 wachs * [r23490] src/transport/plugin_transport_http_client.c, src/transport/test_plugin_transport.c: changes 2012-08-29 08:14 wachs * [r23488] src/transport/plugin_transport_http_client.c, src/transport/test_plugin_transport.c: changes 2012-08-29 07:41 wachs * [r23487] src/transport/test_plugin_transport_udp.c: not used 2012-08-29 07:20 wachs * [r23486] src/transport/plugin_transport_http_client.c: coverity 10259 2012-08-29 07:18 wachs * [r23485] src/transport/plugin_transport_http_common.c: coverity 10260 2012-08-29 07:16 wachs * [r23484] src/transport/test_plugin_transport.c: coverity 10270 2012-08-29 00:39 LRN * [r23482] src/transport/test_transport_api_http_peer1.conf, src/transport/test_transport_api_http_peer2.conf, src/transport/test_transport_api_http_reverse_peer1.conf: No valgrind in HEAD, please 2012-08-28 15:11 wachs * [r23480] src/ats/ats_api_scheduling.c, src/include/gnunet_transport_plugin.h: changes 2012-08-28 15:11 wachs * [r23479] src/transport/Makefile.am, src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_http_server.c, src/transport/test_transport_api_http_nat_peer1.conf, src/transport/test_transport_api_http_nat_peer2.conf, src/transport/test_transport_api_http_peer1.conf, src/transport/test_transport_api_http_reverse_peer1.conf, src/transport/test_transport_api_http_reverse_proxy.conf, src/transport/test_transport_api_https_nat_peer1.conf, src/transport/test_transport_api_https_nat_peer2.conf, src/transport/test_transport_api_reliability_http_nat_peer1.conf, src/transport/test_transport_api_reliability_http_nat_peer2.conf, src/transport/test_transport_api_reliability_https_nat_peer1.conf, src/transport/test_transport_api_reliability_https_nat_peer2.conf: confs + coverity 2012-08-28 14:51 wachs * [r23478] src/transport/plugin_transport_http_server.c: changes 2012-08-28 14:51 wachs * [r23477] src/transport/plugin_transport_http_common.c: changes 2012-08-28 14:51 wachs * [r23476] src/transport/plugin_transport_http_common.h: changes 2012-08-28 14:51 wachs * [r23475] src/transport/plugin_transport_http_client.c: changes 2012-08-28 13:41 LRN * [r23473] src/transport/Makefile.am: Fix https client ldflags 2012-08-28 11:43 wachs * [r23472] src/transport/Makefile.am, src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/test_quota_compliance_https_asymmetric_peer1.conf, src/transport/test_quota_compliance_https_asymmetric_peer2.conf, src/transport/test_quota_compliance_https_peer1.conf, src/transport/test_quota_compliance_https_peer2.conf, src/transport/test_transport_api_https_peer1.conf, src/transport/test_transport_api_https_peer2.conf, src/transport/test_transport_api_reliability_https_peer1.conf, src/transport/test_transport_api_reliability_https_peer2.conf, src/transport/test_transport_api_timeout_https_peer1.conf, src/transport/test_transport_api_timeout_https_peer2.conf: tests 2012-08-28 10:54 wachs * [r23471] src/transport/test_quota_compliance_http_asymmetric_peer1.conf, src/transport/test_quota_compliance_http_asymmetric_peer2.conf: asymmetric 2012-08-28 10:51 wachs * [r23470] src/transport/Makefile.am, src/transport/test_quota_compliance_http_peer1.conf, src/transport/test_quota_compliance_http_peer2.conf: qutoa 2012-08-28 10:19 LRN * [r23469] configure.ac: Make poisoning configurable. Enable it on debug builds by default 2012-08-28 09:55 wachs * [r23467] src/transport/Makefile.am, src/transport/plugin_transport_http_common.h, src/transport/test_transport_api_http_peer2.conf, src/transport/test_transport_api_reliability_http_peer1.conf, src/transport/test_transport_api_reliability_http_peer2.conf, src/transport/test_transport_api_timeout_http_peer1.conf, src/transport/test_transport_api_timeout_http_peer2.conf: test conf updates 2012-08-28 08:45 LRN * [r23465] src/transport/Makefile.am: fix http client ldflags 2012-08-27 21:31 harsha * [r23459] src/include/gnunet_testbed_service.h: more doc 2012-08-27 18:52 grothoff * [r23453] Makefile.am, contrib/Makefile.am, contrib/hostlist.cgi, contrib/hostlist.php, contrib/report.sh, contrib/submit, doc/Makefile.am: updating report.sh, removing obsolete hostlist scripts 2012-08-27 17:36 harsha * [r23448] src/testbed/Makefile.am, src/testbed/test_testbed_api.c, src/testbed/testbed_api_services.c: peer service connect and its test case 2012-08-27 15:47 LRN * [r23446] src/fs/perf_gnunet_service_fs_p2p.conf: Fix fs test config 2012-08-27 15:42 wachs * [r23445] src/transport/plugin_transport_http_client.c: timeout 2012-08-27 15:33 wachs * [r23444] src/transport/plugin_transport_http_client.c: fix 2012-08-27 15:02 wachs * [r23442] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_http_server.c: changes 2012-08-27 14:23 wachs * [r23439] src/transport/plugin_transport_http_client.c: more code 2012-08-27 13:40 wachs * [r23437] src/transport/plugin_transport_http_server.c: change 2012-08-27 13:03 wachs * [r23436] src/transport/plugin_transport_http_client.c: more 2012-08-27 13:03 wachs * [r23435] src/transport/plugin_transport_http_server.c: 2012-08-27 12:08 wachs * [r23434] src/transport/plugin_transport_http_client.c: code 2012-08-27 11:51 wachs * [r23433] src/transport/plugin_transport_http_client.c, src/transport/test_transport_api_http_peer1.conf, src/transport/test_transport_api_http_peer2.conf, src/transport/test_transport_api_http_reverse_proxy.conf: changes 2012-08-27 11:44 wachs * [r23432] src/transport/transport-testing.c: docu 2012-08-27 11:40 wachs * [r23431] src/transport/test_plugin_transport.c: fix 2012-08-27 11:33 wachs * [r23430] src/transport/Makefile.am: test 2012-08-27 11:32 wachs * [r23429] src/transport/plugin_transport_http_client.c: changes 2012-08-27 09:58 szengel * [r23428] src/regex/regex.c, src/regex/regex_internal.h: Fixes 2012-08-27 09:24 wachs * [r23427] src/transport/test_plugin_transport.c: fix for wlan 2012-08-27 09:10 harsha * [r23425] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_services.c: service connect checkpoint save 2012-08-26 10:45 harsha * [r23423] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api_peers.c: doxygen fixes 2012-08-25 14:19 LRN * [r23421] src/include/gnunet_transport_plugin.h, src/transport/plugin_transport_http.c: changes to address notification strike back 2012-08-25 11:50 harsha * [r23420] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h, src/testbed/testbed_api_services.c: towards implementing service_connect 2012-08-25 10:29 harsha * [r23419] src/testbed/testbed.conf.in, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c: operation queue renaming 2012-08-24 17:52 harsha * [r23415] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api.c: peer start/stop forwarding with tests 2012-08-24 15:46 harsha * [r23412] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_controllerlink.c: peer destroy forwarding with tests 2012-08-24 15:18 wachs * [r23410] src/transport/gnunet-service-transport.c, src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c: changes to address notification 2012-08-24 15:11 wachs * [r23409] src/transport/plugin_transport_template.c: update 2012-08-24 14:51 wachs * [r23408] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_http_server.c, src/transport/test_transport_api_http_reverse_proxy.conf: changes 2012-08-24 13:51 harsha * [r23407] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_controllerlink.c: peer create fowarding with tests 2012-08-24 13:24 wachs * [r23405] src/transport/plugin_transport_http_server.c: more 2012-08-24 13:02 wachs * [r23402] src/transport/plugin_transport_http_server.c: code 2012-08-24 12:20 LRN * [r23401] src/mesh/gnunet-service-mesh.c: More dont-access-t-when-it-is-NULL fixes 2012-08-24 10:39 LRN * [r23400] src/mesh/gnunet-service-mesh.c: Don't access t when t is NULL 2012-08-24 08:12 wachs * [r23399] src/transport/plugin_transport_http_server.c: mod 2012-08-23 18:02 LRN * [r23390] src/dns/Makefile.am: Roll back r23388, fix it differently 2012-08-23 17:52 LRN * [r23389] src/transport/Makefile.am: Don't run unix test on W32 2012-08-23 17:49 LRN * [r23388] src/dns/Makefile.am: Fix dns service dependencies 2012-08-23 14:54 wachs * [r23385] src/transport/plugin_transport_http_server.c: more code 2012-08-23 12:28 wachs * [r23380] src/transport/Makefile.am, src/transport/test_plugin_transport_data.conf: more test 2012-08-23 12:24 wachs * [r23379] src/transport/plugin_transport_http_common.c: improved security checks 2012-08-23 12:23 wachs * [r23378] src/transport/test_plugin_transport.c: mem leak 2012-08-23 12:12 wachs * [r23377] src/transport/plugin_transport_http_server.c: fix 2012-08-23 11:59 wachs * [r23376] src/transport/test_plugin_transport.c: fix 2012-08-23 11:48 wachs * [r23375] src/transport/Makefile.am, src/transport/plugin_transport_udp_broadcasting.c, src/transport/test_plugin_transport.c: plugin test 2012-08-23 10:01 wachs * [r23373] src/transport/test_plugin_transport.c: 2012-08-23 07:29 wachs * [r23372] src/transport/test_plugin_transport.c: changes to plugin test 2012-08-23 07:04 wachs * [r23371] src/transport/plugin_transport_template.c: update template with latest api changes 2012-08-22 15:26 wachs * [r23364] src/transport/plugin_transport_http_client.c: changes 2012-08-22 15:23 wachs * [r23363] src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_http_server.c, src/transport/test_transport_api_http_reverse_proxy.conf: latest changes 2012-08-22 14:49 wachs * [r23362] src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_http_server.c, src/transport/test_transport_api_http_reverse_proxy.conf: changes 2012-08-22 13:41 wachs * [r23360] src/transport/Makefile.am, src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_common.c, src/transport/plugin_transport_http_common.h, src/transport/plugin_transport_http_server.c, src/transport/test_transport_api_http_reverse_proxy.conf: changes 2012-08-22 12:49 harsha * [r23359] contrib/ssh-keys: added testbed testing ssh key 2012-08-22 12:19 wachs * [r23358] src/transport/Makefile.am: changes 2012-08-22 12:14 wachs * [r23357] src/transport/plugin_transport_http_server.c: fix for https 2012-08-22 12:03 harsha * [r23356] src/testbed/testbed_api.c: added ssh batch mode param 2012-08-22 10:56 wachs * [r23355] src/transport/plugin_transport_http_server.c, src/transport/test_transport_api_http_reverse_proxy.conf: more 2012-08-22 10:06 wachs * [r23354] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c, src/transport/test_transport_api_http_reverse_proxy.conf: changes 2012-08-22 08:13 wachs * [r23353] configure.ac, src/transport/Makefile.am: libcurl check 2012-08-22 06:34 wachs * [r23352] contrib/ssh-keys: key 2012-08-21 13:46 harsha * [r23345] src/testbed/Makefile.am, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api.c: added checks for passwordless ssh login during tests 2012-08-21 12:12 harsha * [r23340] src/testbed/Makefile.am, src/testbed/test_testbed_api_controllerlink.c: removed controller link testcase from default tests 2012-08-21 11:59 harsha * [r23339] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.c: modified link controller forwarding to use forwarded operations 2012-08-21 11:15 wachs * [r23338] src/transport/plugin_transport_http.c, src/transport/plugin_transport_http.h, src/transport/test_transport_api_http_reverse_proxy.conf: mod 2012-08-21 11:05 wachs * [r23337] src/transport/plugin_transport_http_server.c: improved url parsing 2012-08-21 08:50 wachs * [r23336] src/transport/Makefile.am: change 2012-08-21 08:49 wachs * [r23335] src/transport/test_transport_api_http_reverse_proxy.conf: new conf 2012-08-21 08:16 harsha * [r23334] src/testbed/Makefile.am: added controller link testcase to default tests 2012-08-21 06:01 grothoff * [r23331] po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/dns/Makefile.am, src/dns/dnsstub.c, src/dns/gnunet-service-dns.c, src/include/Makefile.am, src/include/gnunet_dnsstub_lib.h: refactoring dns service to take stub code into separate library for use in gns2dns proxy 2012-08-17 17:33 szengel * [r23290] src/regex/regex.c, src/regex/test_regex_eval_api.c: Fixed eval test case and stack smashing protection 2012-08-17 14:54 harsha * [r23288] src/include/gnunet_testbed_service.h, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c: controller link as operation 2012-08-17 12:32 harsha * [r23286] src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-helper.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c: fixes 2012-08-17 10:03 szengel * [r23280] src/regex/regex.c, src/regex/regex_graph.c, src/regex/regex_internal.h: Added multi-striding capabilities to regex. 2012-08-14 14:25 harsha * [r23229] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_controllerlink.c: fixes 2012-08-14 13:38 harsha * [r23225] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api_hosts.c: fixes and removed slave2 from controller link test 2012-08-14 13:24 harsha * [r23224] src/testbed, src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_2peers.c, src/testbed/test_testbed_api_controllerlink.c, src/testbed/testbed_api.c: fixes 2012-08-13 16:17 szengel * [r23212] src/regex/regex.c, src/regex/regex_graph.c, src/regex/regex_internal.h: using strings as labels 2012-08-11 15:13 harsha * [r23203] src/testbed/gnunet-service-testbed.c: implemented peer create operation forwarding 2012-08-11 13:04 harsha * [r23201] src/testbed/testbed_api.c, src/testbed/testbed_api.h: forward operation msg cancel 2012-08-11 12:46 harsha * [r23200] src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h: api forward operation message 2012-08-11 10:38 harsha * [r23199] src/testbed/gnunet-service-testbed.c: Local and remote peers 2012-08-10 20:03 harsha * [r23198] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.h: towards peer create forwarding 2012-08-10 15:33 harsha * [r23195] src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h, src/testbed/testbed_api.c: controller hostname in init 2012-08-10 09:56 harsha * [r23193] src/testbed/gnunet-service-testbed.c: overlay connect operation failure reporting 2012-08-10 07:34 harsha * [r23192] src/testbed/gnunet-service-testbed.c: cleaner peer destory 2012-08-09 09:31 wachs * [r23171] src/namestore/namestore_common.c: bug 2012-08-08 13:12 wachs * [r23164] src/integration-tests/connection_watchdog.c: coverity 2012-08-08 10:31 wachs * [r23162] src/transport/transport_api.c: callback for offer_hello 2012-08-08 10:05 wachs * [r23161] src/transport/gnunet-service-transport_validation.c: remove msg 2012-08-07 20:33 harsha * [r23158] src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.c: fixed memory leak with HELLO 2012-08-07 15:02 harsha * [r23149] src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.conf, src/testbed/test_testbed_api_2peers.c, src/testbed/testbed_api.c: working version of peer connect 2012-08-07 12:23 harsha * [r23146] src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_2peers.c, src/testbed/testbed_api_operations.c: hacking overlay connect 2012-08-04 07:45 LRN * [r23093] src/gns/gnunet-gns-proxy.c: Fix a typo 2012-08-03 22:34 harsha * [r23076] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api_2peers.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: refined overlay connect and extended test case 2012-08-03 18:32 grothoff * [r23073] src/gns/gnunet-gns-proxy.c: better style 2012-08-01 15:03 harsha * [r23032] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api_peers.c: improved overlay connect handling 2012-08-01 11:48 harsha * [r23029] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c: state information for OperationContext 2012-08-01 11:12 harsha * [r23027] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c: peer info with new operations handling 2012-07-31 18:48 harsha * [r23022] src/testbed/testbed_api.c, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_peers.c: peer start/stop with new operations handling 2012-07-31 15:29 harsha * [r23020] src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: peer destroy with new operations handling 2012-07-31 14:53 harsha * [r23019] src/include/gnunet_testbed_service.h: doc 2012-07-31 14:52 harsha * [r23018] src/testbed/testbed.conf.in, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: peer create with new operations handling 2012-07-31 07:38 wachs * [r23009] src/gns/nss/Makefile.am: fix 2012-07-30 10:59 LRN * [r22969] src/dns/Makefile.am, src/dns/install-dns-helper.sh, src/exit/Makefile.am, src/exit/install-exit-helper.sh, src/gns/nss/Makefile.am, src/gns/nss/install-nss-plugin.sh, src/nat/Makefile.am, src/nat/install-nat-helper.sh, src/transport/Makefile.am, src/transport/install-wlan-helper.sh, src/vpn/Makefile.am, src/vpn/install-vpn-helper.sh: Do not run install commands from makefiles directly 2012-07-30 07:26 grothoff * [r22960] src/include/gnunet_common.h: fix for gcc alginment issue on sparc reported to Debian as #670578 2012-07-29 21:32 harsha * [r22958] src/testbed/test_testbed_api_operations.c, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h: removed redundant cls(data) 2012-07-29 20:40 harsha * [r22955] src/stream/stream_api.c: fixes 2012-07-29 11:24 harsha * [r22953] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_operations.c, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h: testbed operations 2012-07-28 23:05 harsha * [r22952] src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h: testbed operations 2012-07-27 15:06 harsha * [r22950] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api_hosts.c: fixes 2012-07-27 14:37 harsha * [r22947] src/testbed/gnunet-service-testbed.c: extensive message checking 2012-07-27 13:54 harsha * [r22945] src/testbed/gnunet-service-testbed.c: fixed LCF forwarding 2012-07-27 12:41 harsha * [r22942] src/testbed/testbed_api_hosts.c: fixed incorrect realloc size 2012-07-27 12:02 harsha * [r22941] src/testbed/gnunet-service-testbed.c: removed slave context 2012-07-27 10:25 LRN * [r22938] src/util/helper.c: Use pipe control for helper processes This fixes testbed service leak in testbed tests. Either this, or NOT using helper API for testbed helper. 2012-07-27 10:25 LRN * [r22937] src/gns/gnunet-gns-helper-service-w32.c, src/gns/w32nsp-install.c, src/gns/w32nsp-resolve.c, src/gns/w32nsp-uninstall.c, src/gns/w32nsp.c: Fix w32nsp headers 2012-07-27 10:09 harsha * [r22936] src/testbed/gnunet-testbed-helper.c: helper shutdown on stdin close 2012-07-26 06:50 wachs * [r22919] src/ats/ats_api_scheduling.c: transport fix 2012-07-25 15:31 bartpolot * [r22916] src/dns/gnunet-service-dns.c, src/exit/gnunet-daemon-exit.c, src/include/gnunet_mesh_service.h, src/mesh/mesh_api.c, src/pt/gnunet-daemon-pt.c, src/stream/stream_api.c, src/vpn/gnunet-service-vpn.c: Eliminate mesh priority option 2012-07-25 14:22 bartpolot * [r22910] src/dns/gnunet-service-dns.c, src/exit/gnunet-daemon-exit.c, src/include/gnunet_mesh_service.h, src/include/gnunet_protocols.h, src/mesh/mesh.h, src/mesh/mesh_api.c, src/pt/gnunet-daemon-pt.c, src/stream/stream_api.c, src/vpn/gnunet-service-vpn.c: Eliminated mesh API buffering 2012-07-25 12:27 wachs * [r22907] src/transport/gnunet-service-transport_validation.c: comment 2012-07-24 13:46 harsha * [r22870] src/testbed/test_testbed_api.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_operations.c, src/testbed/testbed_api_operations.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: fixed mem leaks with operations 2012-07-24 12:39 harsha * [r22868] src/testbed/test_testbed_api.c, src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: testcases for peer get information 2012-07-24 11:40 harsha * [r22867] src/testbed/gnunet-service-testbed.c: hack for unix domain sockets 2012-07-24 11:31 harsha * [r22866] src/testbed/testbed_api.c: message checks at client receive side 2012-07-23 14:35 szengel * [r22847] src/regex/regex.c: Fixed coverty issues 2012-07-23 11:40 wachs * [r22836] src/ats/gnunet-service-ats_addresses_mlp.c: coverity 10104/3/2 2012-07-22 18:33 harsha * [r22823] src/include/gnunet_testbed_service.h: removed redundant info request 2012-07-22 13:47 LRN * [r22820] src/dht/Makefile.am, src/dht/test_dht_tools.py.in, src/fs/test_gnunet_fs_rec.py.in: pythonize test_dht_tools 2012-07-22 13:47 LRN * [r22819] contrib/Makefile.am, contrib/pydiffer.py.in, src/fs/test_gnunet_fs_rec.py.in: Use Python batteries in fs_rec test 2012-07-22 13:47 LRN * [r22818] src/ats-test/test_transport_ats_1addr.conf, src/ats-test/test_transport_ats_2addr.conf, src/ats-test/test_transport_ats_4addr.conf, src/dht/test_dht_2dtorus.conf, src/dht/test_dht_api_data.conf, src/dht/test_dht_line.conf, src/dht/test_dht_multipeer_data.conf, src/dht/test_dht_twopeer_data.conf, src/dv/test_transport_dv_data.conf, src/fs/test_fs_defaults.conf, src/gns/test_gns_defaults.conf, src/gns/test_gns_proxy.conf, src/integration-tests/test_connection_stability.conf, src/mesh/test_mesh_2dtorus.conf, src/mesh/test_mesh_small.conf, src/nse/test_nse.conf, src/stream/test_stream_local.conf, src/testing/test_testing_defaults.conf, src/testing_old/test_testing_2dtorus.conf, src/testing_old/test_testing_defaults.conf, src/testing_old/testing_group.c, src/topology/test_gnunet_daemon_topology_data.conf: Fix hostkey loading for old testing framework 2012-07-22 13:47 LRN * [r22817] src/transport/transport-testing.c: DOS-pathsep-compatible filename extraction 2012-07-22 13:46 LRN * [r22816] src/gns/Makefile.am: Fix dns2gns dependencies 2012-07-22 13:46 LRN * [r22815] src/fs/test_gnunet_fs_idx.py.in, src/fs/test_gnunet_fs_psd.py.in: Use test tgz instead of COPYING for FS tests 2012-07-20 20:17 grothoff * [r22810] src/gns/Makefile.am, src/gns/gnunet-dns2gns.c: ns2gns 2012-07-20 15:03 harsha * [r22800] src/testbed/gnunet-service-testbed.c: fix NULL memory access 2012-07-20 14:57 harsha * [r22799] src/testbed/gnunet-service-testbed.c: fix mem leak 2012-07-20 14:49 harsha * [r22798] src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.c, src/testbed/testbed_api.c, src/testbed/testbed_api_peers.c: peer start and stop 2012-07-20 14:48 harsha * [r22797] src/testing/testing.c: decide btw ipv4 or ipv6 2012-07-20 12:02 harsha * [r22788] src/include/gnunet_testbed_service.h, src/testbed, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_2peers.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: peer create callback 2012-07-19 12:50 wachs * [r22774] src/ats/gnunet-service-ats_addresses.c: memory leak 2012-07-18 21:55 harsha * [r22769] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c: peer_stop and service handle for peerstop message: TODO: handler for peer stop success 2012-07-18 19:38 LRN * [r22767] src/util/os_priority.c: Fix arm-lsocks protocol violation on W32 2012-07-18 17:46 LRN * [r22766] src/mesh/Makefile.am: Really try to fix compilation on Windows 2012-07-18 15:42 harsha * [r22761] src/testbed/gnunet-service-testbed.c: peer create handling at service 2012-07-18 15:25 harsha * [r22755] src/testbed/test_testbed_api_2peers.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c: testbed api peer start 2012-07-18 13:25 harsha * [r22749] src/testbed/Makefile.am, src/testbed/gnunet-testbed-helper.c, src/testbed/test_testbed_api_2peers.c, src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h, src/testbed/testbed_api_peers.c: API internal function call changes 2012-07-18 13:03 harsha * [r22748] src/include/gnunet_testbed_service.h, src/testbed/Makefile.am, src/testbed/test_testbed_api.c, src/testbed/testbed_api.c, src/testbed/valgrind-zlib.supp: fix; modified testcase for test_testbed_api; valigrind suppression for zlib 2012-07-18 11:58 harsha * [r22743] src/testbed/testbed_api.c: fix 2012-07-18 11:56 harsha * [r22742] src/testbed/test_gnunet_testbed_helper.c, src/testbed/testbed_api.c: implemented controller_start success callback 2012-07-18 11:33 harsha * [r22741] src/testbed/Makefile.am: libz linking 2012-07-18 08:45 harsha * [r22739] src/mesh/Makefile.am: mesh compile 2012-07-18 08:35 harsha * [r22738] src/testbed/Makefile.am, src/testbed/gnunet-testbed-helper.c, src/testbed/test_gnunet_testbed_helper.c: fixed test_gnunet_testbed_helper 2012-07-18 07:43 harsha * [r22737] src/testbed/Makefile.am: fix compile 2012-07-17 22:25 harsha * [r22736] src/include/gnunet_protocols.h, src/include/gnunet_testbed_service.h, src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/gnunet-testbed-helper.c, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h, src/testbed/testbed_helper.h: helper reply with modified config 2012-07-17 19:09 harsha * [r22726] src/include/gnunet_helper_lib.h, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c, src/util/helper.c: helper exception callback lesser parameters 2012-07-17 14:59 harsha * [r22720] src/include/gnunet_testbed_service.h, src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h: helper integration to GNUNET_TESTBED_host_run_() todo: add controller start callback with the configuration with which the controller is started 2012-07-17 12:54 bartpolot * [r22715] src/mesh/Makefile.am, src/mesh/gnunet-service-mesh.c, src/mesh/gnunet-service-mesh_new.c: Added REGEX announce and discovery to MESH 2012-07-17 12:12 harsha * [r22713] src/testbed/test_gnunet_testbed_helper.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h: separated helper init message 2012-07-16 18:58 harsha * [r22707] src/dns/gnunet-service-dns.c, src/exit/gnunet-daemon-exit.c, src/fs/fs_dirmetascan.c, src/include/gnunet_helper_lib.h, src/testbed/test_gnunet_testbed_helper.c, src/transport/plugin_transport_wlan.c, src/util/helper.c, src/vpn/gnunet-service-vpn.c: extended HELPER api to notify when child crashes 2012-07-15 15:07 harsha * [r22686] src/include/gnunet_testing_lib-new.h, src/testing/testing.c: doc 2012-07-15 14:30 harsha * [r22684] src/testbed/gnunet-testbed-helper.c, src/testbed/test_gnunet_testbed_helper.c: config localization and service startup 2012-07-15 14:29 harsha * [r22683] src/util: svn ignore 2012-07-14 23:26 harsha * [r22672] src/testbed/gnunet-testbed-helper.c, src/testbed/testbed_helper.h: init message handling 2012-07-14 22:54 harsha * [r22668] src/include/gnunet_disk_lib.h: doc 2012-07-14 18:39 harsha * [r22660] src/testbed/gnunet-testbed-helper.c, src/testbed/test_gnunet_testbed_helper.c: relaxed time for shutdown 2012-07-14 09:44 harsha * [r22649] src/include/gnunet_protocols.h: testbed helper init message 2012-07-14 01:15 harsha * [r22648] src/testbed, src/testbed/Makefile.am, src/testbed/test_gnunet_testbed_helper.c: testbed helper testcase 2012-07-13 16:37 harsha * [r22640] src/testbed, src/testbed/Makefile.am, src/testbed/gnunet-testbed-helper.c, src/testbed/testbed_helper.h: testbed helper 2012-07-13 16:24 LRN * [r22639] src/transport/Makefile.am: Fix transport makefile 2012-07-13 16:24 LRN * [r22638] src/util/os_priority.c: W32: correct handling of crazy W32 process quirks 2012-07-13 16:24 LRN * [r22637] src/util/network.c: Handle peek errors more appropriately in w32 select 2012-07-13 16:24 LRN * [r22636] src/util/network.c: Safer handling of corner-cases in w32 select 2012-07-13 00:39 LRN * [r22625] src/util/disk.c: Demote WARNING to INFO, preserve errno 2012-07-12 21:08 LRN * [r22624] contrib/terminate.py.in: Missing file 2012-07-12 21:06 LRN * [r22623] contrib/Makefile.am, contrib/gnunet_janitor.py.in, src/include/winproc.h, src/util/os_priority.c, src/util/win.cc: W32: safer process termination 2012-07-12 11:50 harsha * [r22616] src/testbed/gnunet-service-testbed.c, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h: implemented controller error callback 2012-07-11 20:19 LRN * [r22611] src/util/w32cat.c: A small fix for W32cat 2012-07-11 15:36 szengel * [r22610] src/regex/regex.c: bugfix 2012-07-11 15:06 harsha * [r22607] src/include/gnunet_testbed_service.h, src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api.c: fixes for controller_start() API changes 2012-07-11 08:05 LRN * [r22598] src/gns/gns.conf.in: Make gns port non-unix-only 2012-07-10 14:33 wachs * [r22594] src/transport/plugin_transport_http_server.c: improved server disconnect 2012-07-09 18:48 harsha * [r22577] src/testbed/gnunet-service-testbed.c: more fixes 2012-07-09 15:18 szengel * [r22575] src/regex/regex.c: regex: fixed iterating over the initial states. 2012-07-09 15:18 szengel * [r22574] src/regex/test_regex_iterate_api.c: regex: fixed iterating over the initial states 2012-07-08 20:28 harsha * [r22546] src/testbed/testbed_api.c, src/testbed/testbed_api.h, src/testbed/testbed_api_peers.c, src/testbed/testbed_api_peers.h: operation and peer_destroy 2012-07-07 16:12 harsha * [r22540] src/include/gnunet_testing_lib-new.h, src/testing/testing.c: testing doc 2012-07-06 22:49 harsha * [r22535] src/testbed/testbed_api_peers.c: testbed peer_create () 2012-07-06 22:36 harsha * [r22534] src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api.h: function exports from testbed_api 2012-07-06 15:29 wachs * [r22532] src/transport/transport_api.c: undo 2012-07-06 15:24 wachs * [r22530] src/transport/Makefile.am, src/transport/gnunet-service-transport_neighbours.c, src/transport/test_quota_compliance.c, src/transport/test_quota_compliance_wlan_asymmetric_peer1.conf, src/transport/test_quota_compliance_wlan_asymmetric_peer2.conf, src/transport/test_quota_compliance_wlan_peer1.conf, src/transport/test_quota_compliance_wlan_peer2.conf, src/transport/transport_api.c: quota tests for wlan 2012-07-06 15:13 harsha * [r22529] src/testbed, src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/test_testbed_api.c, src/testbed/test_testbed_api.conf, src/testbed/testbed_api.c: testbed api test case and fixes 2012-07-06 14:30 szengel * [r22527] src/regex/regex.c, src/regex/regex_graph.c: regex: iterating over the initial states 2012-07-06 08:49 wachs * [r22516] src/transport/gnunet-transport.c: fixing assertion: cancel transmit ready on disconnect 2012-07-05 22:29 harsha * [r22509] src/testbed/testbed_api_hosts.c: fixes 2012-07-05 21:14 harsha * [r22508] src/testbed/gnunet-service-testbed.c: routing controller link messages 2012-07-05 19:59 harsha * [r22507] src/testbed/gnunet-service-testbed.c: direct links to slave controllers 2012-07-05 14:29 szengel * [r22500] src/include/gnunet_regex_lib.h, src/regex/regex_graph.c: regex: added verbose flag to graph api. 2012-07-05 09:46 szengel * [r22492] src/regex/regex.c, src/regex/regex_graph.c: regex: fixed static analyzer warnings 2012-07-05 07:57 grothoff * [r22488] src/namestore/namestore_common.c: LRN: More logging for namespace comparison: Changes GNUNET_NAMESTORE_records_cmp from a simple if statement to a chain of if statements, each of which will log the reason comparison failed before returning FALSE, making it obvious why comparison failed. 2012-07-04 15:46 szengel * [r22482] src/include/gnunet_regex_lib.h, src/regex/regex.c, src/regex/test_regex_iterate_api.c: regex: actually checking the proof, fixes 2012-07-04 13:54 szengel * [r22478] src/regex/Makefile.am, src/regex/regex.c, src/regex/regex_graph.c, src/regex/regex_internal.h, src/regex/test_regex_eval_api.c, src/regex/test_regex_proofs.c: Summary: regex cleanup and bugfixes Author: szengel 2012-07-02 21:42 harsha * [r22447] src/transport/transport.conf.in: ignoring ACCEPT_FROM for transport plugins while testing 2012-07-02 21:39 harsha * [r22446] src/testing/test_testing_defaults.conf, src/testing/test_testing_portreservation.c, src/testing/testing.c: added TESTING_IGNORE_KEYS 2012-07-02 14:56 wachs * [r22441] src/transport/Makefile.am, src/transport/test_transport_testing.c, src/transport/test_transport_testing_restart.c, src/transport/test_transport_testing_startstop.c, src/transport/transport-testing.c, src/transport/transport-testing.h: porting transport testing to new testing lib (mantis 2453) 2012-07-02 14:34 wachs * [r22440] src/testing/testing.c: workaround for mantis 2476 2012-07-02 13:23 szengel * [r22435] src/regex/regex.c: fixed leaks 2012-07-02 12:25 szengel * [r22430] src/regex/regex.c: removed unnecessary debug statements 2012-07-02 12:22 szengel * [r22429] src/regex/regex.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_iterate_api.c, src/regex/test_regex_proofs.c: regex bugfixes 2012-07-02 07:52 wachs * [r22422] src/transport/gnunet-service-transport_neighbours.c: fix for mantis 2445 & 2471 2012-07-01 22:08 harsha * [r22420] src/testbed/gnunet-service-testbed.c: routing 2012-07-01 15:37 harsha * [r22413] src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h, src/testbed/testbed_api.c: link controller handler 2012-06-29 16:43 wachs * [r22394] src/transport/gnunet-service-transport_neighbours.c: fix for mantis 2445 2012-06-29 15:12 harsha * [r22390] src/testbed/testbed.h, src/testbed/testbed_api.c: testbed api: controller link message 2012-06-29 13:30 wachs * [r22381] src/transport/plugin_transport_udp.c, src/transport/transport.conf.in: improved error messages when no network connectivity and fancy interval time 2012-06-29 12:25 wachs * [r22378] src/transport/plugin_transport_udp_broadcasting.c, src/transport/transport.conf.in: do not print error msg when we have no network connectivity 2012-06-28 12:41 szengel * [r22363] src/regex/regex.c: cleanup, fixes 2012-06-27 16:13 szengel * [r22353] src/include/gnunet_regex_lib.h, src/regex/Makefile.am, src/regex/regex.c, src/regex/regex_internal.h, src/regex/regex_random.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_proofs.c: new and improved tests 2012-06-27 15:34 dold * [r22352] src/peerinfo/peerinfo.conf.in, src/testing/gnunet-testing-run-service.c: added JAVAPORT to peerinfo config, fix in gnunet-testing-run-service.c 2012-06-27 12:24 harsha * [r22345] src/include/gnunet_configuration_lib.h, src/util/configuration.c: configuration serialization 2012-06-26 19:07 harsha * [r22313] src/include/gnunet_protocols.h, src/include/gnunet_testbed_service.h, src/testbed/gnunet-service-testbed.c, src/testbed/testbed.h, src/testbed/testbed_api.c, src/testbed/testbed_api_hosts.c, src/testbed/testbed_api_hosts.h: testbed host registration 2012-06-26 14:45 wachs * [r22301] src/transport/gnunet-service-transport_neighbours.c: fix for 0002463 2012-06-26 13:52 szengel * [r22298] src/include/gnunet_regex_lib.h, src/regex/regex.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_proofs.c: doxygen fixes 2012-06-26 13:01 wachs * [r22293] src/transport/gnunet-service-transport_neighbours.c: fix for mantis 0002462 2012-06-25 22:36 grothoff * [r22283] src/include/gnunet_namestore_service.h, src/namestore/gnunet-namestore.c, src/namestore/gnunet-service-namestore.c, src/namestore/namestore.conf.in, src/namestore/namestore_api.c, src/namestore/plugin_namestore_postgres.c, src/namestore/test_namestore_api.c, src/namestore/test_namestore_api.conf, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_lookup.c, src/namestore/test_namestore_api_lookup_specific_type.c, src/namestore/test_namestore_api_put.c, src/namestore/test_namestore_api_remove.c, src/namestore/test_namestore_api_remove_not_existing_record.c, src/namestore/test_namestore_api_zone_iteration.c, src/namestore/test_namestore_api_zone_iteration_specific_zone.c, src/namestore/test_namestore_api_zone_iteration_stop.c, src/namestore/test_namestore_api_zone_to_name.c, src/namestore/test_plugin_namestore.c, src/namestore/test_plugin_namestore_postgres.conf: trying to fix #2458, largely works 2012-06-25 16:16 szengel * [r22275] src/regex/regex.c, src/regex/test_regex_iterate_api.c: regex bugfixes and optimizations 2012-06-25 11:15 szengel * [r22269] src/regex/Makefile.am, src/regex/regex.c, src/regex/test_regex_proofs.c: new test for regex 2012-06-25 10:36 szengel * [r22268] src/regex/regex.c: regex optimizations 2012-06-25 08:33 szengel * [r22266] src/regex/regex.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_iterate_api.c: regex simplification wip 2012-06-22 00:37 schanzen * [r22197] src/gns/Makefile.am, src/gns/gnunet-service-gns_resolver.c, src/gns/test_gns_simple_srv_lookup.c, src/include/gnunet_dnsparser_lib.h, src/include/gnunet_gns_service.h: Added proper SRV handling and test 2012-06-21 19:03 szengel * [r22193] src/regex/test_regex_eval_api.c: Updated testcase to use fewer random regexes. 2012-06-20 19:24 harsha * [r22173] src/lockmanager/Makefile.am, src/lockmanager/gnunet-service-lockmanager.c, src/lockmanager/lockmanager_api.c, src/lockmanager/test_lockmanager_api.c, src/lockmanager/test_lockmanager_api_acquireretry.c, src/lockmanager/test_lockmanager_api_lockrelease.c, src/lockmanager/test_lockmanager_api_servercrash.c: lockmanager testcase new testing library 2012-06-20 10:53 wachs * [r22139] src/namestore/namestore_api.c: clean up and documentation for namestor API 2012-06-19 21:44 grothoff * [r22121] src/include/gnunet_strings_lib.h, src/util/strings.c: adding API for parsing absolute time 2012-06-19 12:40 harsha * [r22108] src/testbed, src/testbed/Makefile.am, src/testbed/test_testbed_api.conf, src/testbed/test_testbed_api_hosts.c, src/testbed/testbed_api_hosts.c: testbed_api_hosts test cases 2012-06-19 09:39 wachs * [r22104] src/ats/gnunet-service-ats_addresses.c: fix a major bug: delete session for unknown address (addr==NULL, length==0) 2012-06-19 08:04 wachs * [r22099] src/ats/Makefile.am, src/ats/test_ats_api_scheduling_destroy_session.c: new test deleting a session using the plugin_env_session_end way (addr=NULL,addr_length=0) + session this fails atm and is a bug 2012-06-18 15:00 grothoff * [r22081] doc/man/Makefile.am, doc/man/gnunet-auto-share.1, doc/man/gnunet-publish.1, src/fs/fs.conf.in, src/include/gnunet_scheduler_lib.h: adding man page for gnunet-auto-share, updating man page for gnunet-publish 2012-06-16 21:47 schanzen * [r22053] src/gns/gnunet-service-gns_resolver.c: properly handle CNAME as specified in rfc1034#section-3.6.2 2012-06-16 16:53 grothoff * [r22043] src/include/gnunet_hello_lib.h, src/include/gnunet_peer_lib.h: fix compilation with c++ 2012-06-16 09:44 schanzen * [r22036] src/gns/Makefile.am, src/gns/gnunet-service-gns_resolver.c, src/gns/gnunet-service-gns_resolver.h, src/include/gnunet_gns_service.h: Add VPN resolution 2012-06-15 15:28 harsha * [r22027] src/stream/Makefile.am: added test_stream_big to make check tests 2012-06-15 15:25 harsha * [r22025] src/stream/stream_api.c, src/stream/test_stream_big.c: remvod verbose debugging in stream api; fixed warning in stream_big test case 2012-06-15 15:19 harsha * [r22024] src/stream/stream_api.c, src/stream/test_stream_big.c: stream misc fixing 2012-06-14 09:52 wachs * [r21994] src/ats/ats_api_scheduling.c: fixing deletion of unknown addresses 2012-06-14 08:51 wachs * [r21987] src/util/test_common_logging_runtime_loglevels.c: fix for segfault 2012-06-14 08:09 harsha * [r21985] src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c: handling add host 2012-06-13 12:41 dold * [r21964] src/testing/gnunet-testing-run-service.c: changed how gnunet-testing-run-service communicates over stdin/stdout 2012-06-13 11:42 szengel * [r21952] src/regex/regex.c, src/regex/test_regex_iterate_api.c: more regex simplifications. fixes. 2012-06-12 23:01 dold * [r21937] src/testing/gnunet-testing-run-service.c: fix 2012-06-12 22:37 dold * [r21936] src/testing/gnunet-testing-run-service.c: fixed indentation 2012-06-12 22:30 dold * [r21935] src/testing/gnunet-testing-run-service.c: fix 2012-06-12 22:26 dold * [r21934] src/include/gnunet_testing_lib-new.h, src/testing/Makefile.am, src/testing/gnunet-testing-run-service.c, src/testing/testing.c: added a command line tool for running and controlling services for testing 2012-06-12 21:12 harsha * [r21932] src/testbed, src/testbed/testbed_api_hosts.c: fixed static to non static 2012-06-12 20:23 harsha * [r21930] configure.ac, src/testbed, src/testbed/Makefile.am, src/testbed/gnunet-service-testbed.c, src/testbed/testbed.conf, src/testbed/testbed.conf.in, src/testbed/testbed.h: testbed service build system 2012-06-12 12:58 bartpolot * [r21914] src/mesh/gnunet-service-mesh.c: Removed core queue requirements from mesh (backporting mesh_new) 2012-06-12 12:43 wachs * [r21912] src/core/gnunet-core.c: exclude notification about myself 2012-06-12 11:24 wachs * [r21910] src/transport/gnunet-transport.c: clean up 2012-06-12 11:24 wachs * [r21909] src/core/gnunet-core.c: core monitor mode 2012-06-12 11:17 schanzen * [r21908] src/gns/Makefile.am, src/gns/gnunet-gns-proxy-setup-ca: autoimport CA 2012-06-12 10:21 grothoff * [r21903] src/namestore/plugin_namestore_postgres.c: completed postgres plugin for namestore service 2012-06-12 10:04 schanzen * [r21902] src/gns/createProxyCa.sh, src/gns/gns.conf.in, src/gns/gnunet-gns-proxy.c: Script for CA generation. Making it easy with config option 2012-06-12 09:02 wachs * [r21900] src/transport/gnunet-transport.c: monitor mode implemented correctly 2012-06-11 15:10 szengel * [r21892] src/regex/regex.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_iterate_api.c: simplified regex/proof generation 2012-06-11 14:59 schanzen * [r21890] src/gns/gns.conf.in, src/gns/gns.h, src/gns/gns_api.c, src/gns/gnunet-gns-proxy.c, src/gns/gnunet-gns.c, src/gns/gnunet-service-gns.c, src/gns/test_gns_pseu_shorten.c, src/include/gnunet_gns_service.h: new API for shorten key 2012-06-11 09:54 grothoff * [r21873] README, configure.ac, src/gns/Makefile.am: adding check for gnutls 2012-06-10 22:47 grothoff * [r21867] src/arm/gnunet-arm.c, src/ats/perf_ats_mlp.c, src/chat/gnunet-chat.c, src/core/gnunet-core.c, src/dht/gnunet-dht-get.c, src/dht/gnunet-dht-monitor.c, src/dht/gnunet-dht-put.c, src/dns/gnunet-dns-monitor.c, src/dns/gnunet-dns-redirector.c, src/exit/gnunet-daemon-exit.c, src/fs/gnunet-directory.c, src/fs/gnunet-download.c, src/fs/gnunet-fs.c, src/fs/gnunet-helper-fs-publish.c, src/fs/gnunet-pseudonym.c, src/fs/gnunet-publish.c, src/fs/gnunet-search.c, src/fs/gnunet-unindex.c, src/gns/gnunet-gns-fcfsd.c, src/gns/gnunet-gns-lookup.c, src/gns/gnunet-gns-proxy.c, src/gns/gnunet-gns.c, src/hostlist/gnunet-daemon-hostlist.c, src/include/gnunet_strings_lib.h, src/integration-tests/connection_watchdog.c, src/namestore/gnunet-namestore.c, src/nat/gnunet-nat-server.c, src/nse/gnunet-nse-profiler.c, src/peerinfo-tool/gnunet-peerinfo.c, src/pt/gnunet-daemon-pt.c, src/statistics/gnunet-statistics.c, src/template/gnunet-template.c, src/testing_old/gnunet-testing.c, src/topology/gnunet-daemon-topology.c, src/transport/gnunet-transport.c, src/util/gnunet-resolver.c, src/util/gnunet-rsa.c, src/util/program.c, src/util/strings.c, src/vpn/gnunet-vpn.c: LRN: new utf8 argv converter for W32, converting strings on command-line to UTF-8 for all command-line tools. 2012-06-10 22:44 grothoff * [r21866] src/testing_old/testing_group.c: LRN: Fix-test_group-interval.patch: Just a wild guess - you wanted to find ids either inside the interval or outside of it. Although maybe you should have used <= and >= in one of the conditions then? CG: only mrwiggles knows the truth. Anyway, old testing will be gone soon enough.... 2012-06-10 22:42 grothoff * [r21865] src/util/crypto_random.c: LRN: fix RAND_MAX on W32: MinGW stdlib.h defines it to 0x7FFF, but our implementation is better. 2012-06-07 07:05 grothoff * [r21794] src/util/network.c: LRN: new select wrapper for W32 which avoids busy-waiting 2012-06-06 21:12 grothoff * [r21790] README: bumping required curl version to 7.21.3 2012-06-06 15:00 szengel * [r21788] src/regex/regex.c: removed unnecessary brackets 2012-06-06 14:35 szengel * [r21787] src/include/gnunet_regex_lib.h, src/regex/regex.c, src/regex/test_regex_eval_api.c: Test for computed regex. 2012-06-06 13:05 szengel * [r21782] src/regex/regex.c: even better proofs 2012-06-06 12:10 grothoff * [r21780] src/testing/testing_new.c: fix arm termination on W32 by enabling signalling pipe to be used 2012-06-06 10:54 szengel * [r21774] src/regex/regex.c, src/regex/test_regex_iterate_api.c: Better proofs 2012-06-04 13:59 szengel * [r21760] src/regex/regex.c: assigning proofs 2012-06-04 13:30 szengel * [r21759] src/regex/regex.c, src/regex/test_regex_iterate_api.c: Towards new proof algorithm 2012-06-04 09:31 grothoff * [r21752] src/include/platform.h: #2404, patch 03: include net/if on GNU 2012-06-04 09:31 grothoff * [r21751] src/util/disk.c: #2404, patch 02: include sys/vfs on GNU 2012-06-04 09:30 grothoff * [r21750] configure.ac: #2404, patch 01: configure support for GNU Hurd 2012-06-02 14:39 grothoff * [r21729] configure.ac, src/include/plibc.h, src/util/server.c, src/util/winproc.c: LRN: Update plibc and utf8ization 2012-06-01 18:51 wachs * [r21714] src/transport/plugin_transport_http_client.c, src/transport/plugin_transport_http_server.c: fix for 2395 2012-06-01 15:36 wachs * [r21704] src/ats/gnunet-service-ats_addresses.c: fix for 0002392 2012-06-01 08:58 schanzen * [r21684] src/gns/nss/Makefile.am, src/gns/nss/nss_gns.c, src/gns/nss/nss_gns_query.c, src/gns/nss/nss_gns_query.h, src/gns/nss/query.c, src/gns/nss/query.h, src/gns/nss/util.c, src/gns/nss/util.h: cleanup 2012-06-01 08:53 wachs * [r21683] src/transport/plugin_transport_unix.c: additional error message 2012-06-01 08:53 wachs * [r21682] src/transport/plugin_transport_http_server.c: remove unused variable 2012-05-30 21:21 harsha * [r21647] src/testing/Makefile.am, src/testing/testing_new.c: test case for peer startup in new testing library 2012-05-30 14:47 wachs * [r21646] src/util/Makefile.am, src/util/program.c, src/util/service.c, src/util/speedup.c, src/util/test_speedup.c, src/util/test_speedup_data.conf, src/util/util.conf: speedup mechanism to manipulate gnunet time 2012-05-30 14:34 harsha * [r21645] src/testing/testing_new.c: comments and fixed NULL check for tm 2012-05-30 14:26 harsha * [r21644] src/testing/testing_new.c: refined GNUNET_TESTING_service_run 2012-05-29 14:06 harsha * [r21634] src/testing/testing_new.c: removed double rsa key free 2012-05-27 21:46 grothoff * [r21608] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/test_ats_api_update_address.c, src/core/core_api_is_connected.c, src/core/core_api_iterate_peers.c, src/dns/plugin_block_dns.c, src/dv/gnunet-service-dv.c, src/gns/gnunet-service-gns_resolver.c, src/gns/plugin_block_gns.c, src/gns/test_gns_dht_delegated_lookup.c, src/gns/test_gns_max_queries.c, src/gns/test_gns_pseu_shorten.c, src/gns/test_gns_simple_delegated_lookup.c, src/gns/test_gns_simple_get_authority.c, src/gns/test_gns_simple_lookup.c, src/gns/test_gns_simple_mx_lookup.c, src/gns/test_gns_simple_shorten.c, src/gns/test_gns_simple_zkey_lookup.c, src/hostlist/hostlist-client.c, src/include/gnunet_time_lib.h, src/integration-tests/connection_watchdog.c, src/mesh/gnunet-service-mesh.c, src/mesh/test_mesh_2dtorus.c, src/mesh/test_mesh_small.c, src/namestore/gnunet-namestore.c, src/namestore/gnunet-service-namestore.c, src/namestore/namestore_api.c, src/namestore/test_namestore_api.c, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_lookup.c, src/namestore/test_namestore_api_lookup_specific_type.c, src/namestore/test_namestore_api_put.c, src/namestore/test_namestore_api_remove.c, src/namestore/test_namestore_api_remove_not_existing_record.c, src/namestore/test_namestore_api_zone_iteration.c, src/namestore/test_namestore_api_zone_iteration_specific_zone.c, src/namestore/test_namestore_api_zone_iteration_stop.c, src/namestore/test_namestore_record_serialization.c, src/nse/gnunet-nse-profiler.c, src/nse/nse_profiler_test.conf, src/testing/test_testing_2dtorus.c, src/testing/testing_group.c, src/transport/plugin_transport_http.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_udp.c, src/util/test_time.c, src/util/time.c: renaming GNUNET_TIME_relative_get_forever and GNUNET_TIME_absolute_get_forever methods, adding underscore, to make it clear that the respective #defines should be used instead; replacing use of direct function calls with respective macros where applicable; adding additional GNUNET_TIME_relative_get_xxx-functions to avoid calls to GNUNET_TIME_relative_multiply, which turn out to have gotten performance-relevant 2012-05-27 21:11 grothoff * [r21607] src/util/server.c: use GNUNET_SCHEDULER_add_read_net_with_priority instead of constructing fd sets in server with only one active listen socket 2012-05-27 21:10 grothoff * [r21606] src/gns/gnunet-service-gns.c, src/include/gnunet_scheduler_lib.h, src/util/scheduler.c: adding GNUNET_SCHEDULER_add_read_net_with_priority 2012-05-26 15:14 harsha * [r21586] src/testing/test_testing_new_portreservation.c, src/testing/testing_new.c: port reservation - release 2012-05-26 14:04 harsha * [r21585] src/testing, src/testing/Makefile.am, src/testing/test_testing_new_portreservation.c, src/testing/testing_new.c: port reservation and test cases 2012-05-25 14:40 harsha * [r21578] src/testing/testing_new.c: testing port reservation 2012-05-25 09:34 wachs * [r21573] src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c: session timeout for udp and tcp 2012-05-25 08:25 wachs * [r21572] src/transport/gnunet-service-transport_neighbours.c: 2012-05-23 07:10 wachs * [r21562] contrib/gnunet_janitor.py.in: LRN's patch 2012-05-22 15:43 harsha * [r21561] src/stream, src/testing/testing_new.c: testing port checking (incomplete) 2012-05-22 15:03 harsha * [r21560] src/stream/test_stream_2peers.c, src/stream/test_stream_2peers_halfclose.c, src/stream/test_stream_local.c: fixed segmentation fault due to missing GNUNET_STREAM_OPTION_END 2012-05-20 15:06 harsha * [r21552] src/testing/testing_new.c: testing system 2012-05-15 14:07 harsha * [r21499] src/lockmanager, src/lockmanager/lockmanager_api.c, src/lockmanager/test_lockmanager_api.c, src/lockmanager/test_lockmanager_api_servercrash.c: handling replies continuously from server 2012-05-15 13:09 harsha * [r21497] src/lockmanager/Makefile.am, src/lockmanager/lockmanager_api.c, src/lockmanager/test_lockmanager_api_servercrash.c: server crash test case 2012-05-15 10:00 wachs * [r21492] src/transport/gnunet-service-transport_neighbours.c: fix for mantis 2356 2012-05-15 09:11 wachs * [r21491] src/transport/plugin_transport_wlan.c: fix memleak 2012-05-15 08:09 wachs * [r21490] src/transport/gnunet-service-transport_neighbours.c: fix for mantis 2355 2012-05-14 13:32 harsha * [r21476] src/lockmanager/lockmanager_api.c: removed local function 2012-05-14 13:04 harsha * [r21475] src/stream/stream_api.c, src/stream/test_stream_2peers_halfclose.c: warnings 2012-05-14 09:06 wachs * [r21469] src/transport/plugin_transport_udp.c: fix for mantis 2346 2012-05-13 18:07 harsha * [r21463] src/include/gnunet_lockmanager_service.h, src/lockmanager/lockmanager_api.c: change in API documentation and function for finding lockingRequest in hashmap 2012-05-13 17:21 harsha * [r21462] src/lockmanager, src/lockmanager/Makefile.am, src/lockmanager/gnunet-service-lockmanager.c, src/lockmanager/lockmanager_api.c, src/lockmanager/test_lockmanager_api.conf, src/lockmanager/test_lockmanager_api_lockrelease.c: clean shutdown in lockmanager, test case for lock release and message format checks for incoming msg in lockmanager API 2012-05-12 08:40 harsha * [r21447] src/stream/stream_api.c: peer ids in logging and indentation 2012-05-11 21:50 harsha * [r21442] src/lockmanager/gnunet-service-lockmanager.c: inlining of helper functions 2012-05-11 13:55 grothoff * [r21440] src/lockmanager/gnunet-service-lockmanager.c, src/transport/plugin_transport_wlan.c: doxygen 2012-05-11 08:18 harsha * [r21435] src/stream/stream_api.c: logging and indentation 2012-05-10 16:26 wachs * [r21421] src/transport/plugin_transport_wlan.c: fixing WLAN 2012-05-10 15:44 harsha * [r21420] src/lockmanager/gnunet-service-lockmanager.c: NULL check on disconnect handler 2012-05-10 15:26 harsha * [r21419] src/lockmanager/gnunet-service-lockmanager.c: lockmanager with new datastructure 2012-05-09 14:29 szengel * [r21387] src/regex/regex.c: fixes 2012-05-09 13:32 wachs * [r21383] src/util/server_nc.c: fix for mantis 2330#c5818 GNUNET_SERVER_notification_context_destroy does not cancel transmit_ready 2012-05-09 13:25 szengel * [r21382] src/regex/regex.c: Fixed warning 2012-05-09 09:59 harsha * [r21369] src/lockmanager/gnunet-service-lockmanager.c: processing upon lock release 2012-05-09 08:29 harsha * [r21367] src/lockmanager/gnunet-service-lockmanager.c: lock acquire and release 2012-05-09 07:09 harsha * [r21366] src/lockmanager/gnunet-service-lockmanager.c: added list processing 2012-05-08 17:10 bartpolot * [r21352] src/arm/gnunet-service-arm.c, src/ats/test_ats_api_bandwidth_consumption.c, src/ats/test_ats_api_scheduling.c, src/chat/test_chat.c, src/chat/test_chat_private.c, src/core/test_core_api.c, src/core/test_core_api_reliability.c, src/core/test_core_api_send_to_self.c, src/core/test_core_api_start_only.c, src/core/test_core_quota_compliance.c, src/datastore/perf_datastore_api.c, src/datastore/test_datastore_api.c, src/datastore/test_datastore_api_management.c, src/dht/test_dht_api.c, src/fs/test_fs.c, src/fs/test_fs_download.c, src/fs/test_fs_download_indexed.c, src/fs/test_fs_download_persistence.c, src/fs/test_fs_download_recursive.c, src/fs/test_fs_list_indexed.c, src/fs/test_fs_namespace.c, src/fs/test_fs_namespace_list_updateable.c, src/fs/test_fs_publish.c, src/fs/test_fs_publish_persistence.c, src/fs/test_fs_search.c, src/fs/test_fs_search_persistence.c, src/fs/test_fs_search_probes.c, src/fs/test_fs_search_ranking.c, src/fs/test_fs_start_stop.c, src/fs/test_fs_unindex.c, src/fs/test_fs_unindex_persistence.c, src/hostlist/test_gnunet_daemon_hostlist.c, src/hostlist/test_gnunet_daemon_hostlist_learning.c, src/hostlist/test_gnunet_daemon_hostlist_reconnect.c, src/include/gnunet_os_lib.h, src/lockmanager/test_lockmanager_api.c, src/mesh/test_mesh_api.c, src/mesh/test_mesh_local_1.c, src/mesh/test_mesh_local_2.c, src/namestore/test_namestore_api.c, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_lookup.c, src/namestore/test_namestore_api_lookup_specific_type.c, src/namestore/test_namestore_api_put.c, src/namestore/test_namestore_api_remove.c, src/namestore/test_namestore_api_remove_not_existing_record.c, src/namestore/test_namestore_api_zone_iteration.c, src/namestore/test_namestore_api_zone_iteration_specific_zone.c, src/namestore/test_namestore_api_zone_iteration_stop.c, src/namestore/test_namestore_api_zone_to_name.c, src/nat/nat.c, src/nat/nat_mini.c, src/nat/test_nat_test.c, src/nse/test_nse_api.c, src/peerinfo/perf_peerinfo_api.c, src/peerinfo/test_peerinfo_api.c, src/statistics/test_statistics_api.c, src/statistics/test_statistics_api_loop.c, src/statistics/test_statistics_api_watch.c, src/statistics/test_statistics_api_watch_zero_value.c, src/stream/test_stream_api.c, src/stream/test_stream_local.c, src/testing/test_testing_large_topology.c, src/testing/test_testing_topology.c, src/testing/testing.c, src/testing/testing_group.c, src/transport/gnunet-transport-certificate-creation.c, src/transport/gnunet-transport.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_wlan.c, src/transport/transport-testing.c, src/util/crypto_random.c, src/util/helper.c, src/util/os_priority.c, src/util/test_common_logging_runtime_loglevels.c, src/util/test_os_start_process.c, src/util/test_resolver_api.c, src/vpn/test_gnunet_vpn.c: Renamed GNUNET_OS_process_close to GNUNET_OS_process_destroy 2012-05-07 17:31 szengel * [r21330] src/regex/regex.c, src/regex/test_regex_iterate_api.c: Fixed compilation warnings 2012-05-07 13:35 grothoff * [r21324] contrib/Makefile.am, contrib/timeout_watchdog_w32.c: LRN: creating watchdog helper binary for W32 2012-05-07 08:25 wachs * [r21315] src/transport/gnunet-service-transport_neighbours.c: fix for mantis 2320 2012-05-04 12:57 bartpolot * [r21271] src/dht/dht.h, src/dht/dht_api.c, src/dht/gnunet-service-dht_clients.c: Added stop operation for dht monitoring 2012-05-03 13:49 grothoff * [r21248] src/peerinfo/peerinfo_api.c: doxygen 2012-05-03 11:36 grothoff * [r21244] src/peerinfo/perf_peerinfo_api.c, src/peerinfo/test_peerinfo_api.c: f-xi 2012-05-02 13:24 wachs * [r21223] src/peerinfo-tool/gnunet-peerinfo.c: fix 2297 2012-04-27 13:44 wachs * [r21203] src/transport/plugin_transport_unix.c: working string toaddress 2012-04-22 19:52 grothoff * [r21075] src/arm/gnunet-service-arm.c, src/ats/gnunet-service-ats.c, src/include/gnunet_server_lib.h, src/include/gnunet_service_lib.h, src/namestore/gnunet-service-namestore.c, src/peerinfo/gnunet-service-peerinfo.c, src/statistics/gnunet-service-statistics.c, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_blacklist.c, src/transport/gnunet-service-transport_clients.c, src/transport/plugin_transport_tcp.c, src/util/server.c, src/util/service.c: introducing soft shutdown concept for services; during soft shutdown, services that are still managing non-monitor clients continue to run until those clients disconnect; however, the services do stop to accept new connections (will stop listening); soft shutdown is now used by ats, transport, peerinfo, namestore and most importantly statistics; this should fix #2197 2012-04-21 18:16 grothoff * [r21060] src/include/gnunet_container_lib.h, src/util/container_bloomfilter.c: changing bloomfilter to allow GNUNET_CONTAINER_bloomfilter_init with sizes that are not powers of 2 -- GNUNET_CONTAINER_bloomfilter_load will continue to round up to power of two 2012-04-20 12:35 szengel * [r21054] src/regex/regex.c, src/regex/test_regex_iterate_api.c: recursion for dfa construction 2012-04-19 11:39 szengel * [r21025] src/regex/regex.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_iterate_api.c: dfa minimization fix 2012-04-18 14:02 szengel * [r21011] src/include/gnunet_regex_lib.h, src/regex/Makefile.am, src/regex/regex.c, src/regex/test_regex.c, src/regex/test_regex_eval_api.c, src/regex/test_regex_iterate_api.c: test update 2012-04-18 13:49 wachs * [r21009] src/statistics/statistics_api.c: fix 2273 2012-04-18 09:55 wachs * [r21005] src/statistics/Makefile.am, src/statistics/gnunet-service-statistics.c, src/statistics/test_statistics_api_watch_zero_value.c: fixing bug 2272: added functionality for watch to notifz about fresh created entries with value 0 2012-04-18 09:30 szengel * [r21004] src/include/gnunet_regex_lib.h, src/regex/regex.c: added accepting state info to api 2012-04-17 20:43 szengel * [r21001] src/include/gnunet_regex_lib.h, src/regex/regex.c: api changes 2012-04-12 13:28 szengel * [r20965] src/regex/regex.c: bugfix 2012-04-12 11:48 szengel * [r20959] src/regex/regex.c, src/regex/test_regex.c: Added '?' operator 2012-04-11 15:30 szengel * [r20947] src/regex/regex.c: comments 2012-04-11 14:13 szengel * [r20943] src/regex/regex.c: doxygen fix 2012-04-10 14:37 szengel * [r20925] src/regex/regex.c, src/regex/test_regex.c: fix 2012-04-10 14:30 szengel * [r20924] src/regex/regex.c, src/regex/test_regex.c: dfa minimization wip 2012-04-09 14:56 szengel * [r20911] src/regex/regex.c, src/regex/test_regex.c: fixes 2012-04-05 14:28 szengel * [r20905] src/regex/regex.c, src/regex/test_regex.c: removing unreachable states 2012-04-05 12:38 szengel * [r20904] src/regex/test_regex.c: better testing 2012-04-05 11:46 szengel * [r20902] src/regex/regex.c, src/regex/test_regex.c: Automatic regex generation for testing 2012-04-04 08:21 grothoff * [r20893] configure.ac, src/fs/fs.conf.in: adding configure option to run GNUnet with monkey 2012-04-03 13:46 szengel * [r20883] src/include/gnunet_regex_lib.h, src/regex/Makefile.am, src/regex/regex.c, src/regex/regex.h, src/regex/test_regex.c: fix 2012-04-02 11:20 wachs * [r20848] src/transport/plugin_transport_http.c, src/transport/transport.conf.in: fixing 0002249: report only new addresses 2012-04-02 10:19 szengel * [r20847] src/regex/regex.c, src/regex/test_regex.c: NFA evaluation 2012-04-02 09:39 szengel * [r20845] src/include/gnunet_regex_lib.h, src/regex/regex.c, src/regex/test_regex.c: DFA evaluation 2012-04-01 09:13 grothoff * [r20826] src/core/gnunet-service-core_kx.c: implementing rekeying, some code cleanup 2012-04-01 07:56 grothoff * [r20825] doc/man/Makefile.am, doc/man/gnunet-core.1, src/core/Makefile.am, src/core/gnunet-core-list-connections.c, src/core/gnunet-core.c, src/include/gnunet_fs_service.h: renaming gnunet-core-list-connections to gnunet-core, adding man page 2012-03-30 15:43 wachs * [r20819] src/transport/gnunet-service-transport_neighbours.c: 2012-03-28 19:27 szengel * [r20801] src/include/gnunet_regex_lib.h, src/regex/regex.c: doxygen fix 2012-03-28 15:49 szengel * [r20800] src/include/gnunet_regex_lib.h, src/regex/regex.c, src/regex/test_regex.c: api changes 2012-03-27 16:37 szengel * [r20790] src/regex/regex.c, src/regex/test_regex.c: formatting 2012-03-24 19:13 grothoff * [r20751] src/fs/fs_api.c, src/fs/fs_publish.c, src/fs/fs_tree.c: fixing issue with gnunet-publish not closing files early enough when publishing directories with more than FD_MAX files (#2239) 2012-03-24 09:05 harsha * [r20740] src/include/gnunet_stream_lib.h, src/stream/stream_api.c: fixed compile error from r20729 2012-03-23 17:40 szengel * [r20738] src/include/gnunet_regex_lib.h, src/regex/regex.c, src/regex/test_regex.c: towards dfa 2012-03-23 11:15 harsha * [r20714] src/stream/stream_api.c: bugfix 2012-03-23 10:58 harsha * [r20711] src/stream/stream_api.c, src/stream/stream_protocol.h: fixed read packets removal after read processor, byte ordering bugs, ack_bitmap handling in handle_ack ack_task cancelling in socket close 2012-03-23 08:04 szengel * [r20699] src/regex/regex.c: fix 2012-03-22 21:25 szengel * [r20698] src/regex/regex.c: cleanup 2012-03-22 19:41 szengel * [r20697] configure.ac, pkgconfig/gnunetregex.pc, src/include/gnunet_regex_lib.h, src/regex/Makefile.am, src/regex/regex.c, src/regex/regex.h, src/regex/test_regex.c: Added initial version of regex lib 2012-03-22 18:47 grothoff * [r20693] configure.ac, src/Makefile.am, src/datacache/Makefile.am, src/datacache/plugin_datacache_postgres.c, src/datastore/plugin_datastore_postgres.c, src/include/Makefile.am, src/include/gnunet_mysql_lib.h, src/include/gnunet_postgres_lib.h, src/postgres, src/postgres/Makefile.am, src/postgres/postgres.c: adding libgnunetpostgres for shared postgres functionality between postgres datastore/datacache backends 2012-03-22 11:05 wachs * [r20670] src/include/gnunet_namestore_service.h, src/namestore/gnunet-service-namestore.c, src/namestore/namestore.h, src/namestore/namestore_common.c: 2012-03-21 12:32 harsha * [r20644] src/stream/stream_api.c, src/stream/test_stream_local.c: fixed read timeout problem and added ack sending incase of ignored data messages 2012-03-21 09:43 grothoff * [r20643] src/Makefile.am, src/include/Makefile.am, src/mysql, src/mysql/Makefile.am, src/mysql/mysql.c: creating mysql helper library for the various mysql backends 2012-03-21 07:06 harsha * [r20639] src/stream/stream_api.c, src/stream/test_stream_local.c: fixed listen callback to happen after reaching ESTABLISHED state 2012-03-19 14:53 grothoff * [r20606] configure.ac, src/core/core.conf.in, src/dht/dht.conf.in, src/nse/nse.conf.in, src/statistics/statistics.conf.in: add configure option --enable-javaports to open ports of services with Java bindings by default (#2228) 2012-03-19 10:17 grothoff * [r20598] doc/man/gnunet-rsa.1, src/datastore/datastore.h, src/exit/exit.h, src/fs/gnunet-service-fs.h, src/include/block_dns.h, src/include/gnunet_common.h, src/include/gnunet_crypto_lib.h, src/include/gnunet_strings_lib.h, src/util/crypto_hash.c, src/util/gnunet-rsa.c, src/util/strings.c, src/vpn/vpn.h: adding API for short (256-bit) hash codes 2012-03-16 14:47 grothoff * [r20570] src/gns/gnunet-gns-fcfsd.c: fix 2012-03-15 21:24 wachs * [r20551] src/namestore/gnunet-namestore.c: 2012-03-15 18:22 wachs * [r20548] src/namestore/gnunet-service-namestore.c: fix segfault 2012-03-15 10:59 grothoff * [r20515] doc/man/gnunet-rsa.1, src/util/gnunet-rsa.c: add -P option for printing peer identities with gnunet-rsa 2012-03-11 22:51 grothoff * [r20445] src/hostlist/hostlist-server.c, src/hostlist/hostlist.conf: vminko: implementing BINDTO option for hostlist service (#2140) 2012-03-10 23:17 grothoff * [r20431] src/include/gnunet_transport_plugin.h, src/transport/plugin_transport_http.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c: add support for stub-mode for transport plugins 2012-03-10 15:09 harsha * [r20424] src/stream/stream_api.c: using GNUNET_STREAM_ACK_BITMAP_BIT_LENGTH 2012-03-10 09:13 harsha * [r20423] src/stream/stream_api.c, src/stream/test_stream_local.c: fixed retransmission task 2012-03-09 15:16 grothoff * [r20415] src/fs/fs_api.c, src/fs/fs_api.h, src/fs/fs_unindex.c: implementing removal of KBlocks during unindex operation (#1926) 2012-03-09 12:53 harsha * [r20407] src/stream/stream_api.c, src/stream/stream_protocol.h, src/stream/test_stream_local.c: fixed byte conversion bugs 2012-03-09 11:39 grothoff * [r20398] src/arm/gnunet-service-arm.c: adding code to measure and report shutdown time for services to gnunet-service-arm at INFO level logging 2012-03-09 08:50 harsha * [r20390] src/stream/stream_api.c: corrected HELLO_ACK message size 2012-03-08 17:26 wachs * [r20375] src/namestore/gnunet-service-namestore.c, src/namestore/hostkey, src/namestore/hostkey2, src/namestore/namestore.conf.in, src/namestore/test_namestore_api.c, src/namestore/test_namestore_api.conf, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_lookup.c, src/namestore/test_namestore_api_lookup_specific_type.c, src/namestore/test_namestore_api_put.c, src/namestore/test_namestore_api_remove.c, src/namestore/test_namestore_api_remove_not_existing_record.c, src/namestore/test_namestore_api_sign_verify.c, src/namestore/test_namestore_api_zone_iteration.c, src/namestore/test_namestore_api_zone_iteration_specific_zone.c, src/namestore/test_namestore_api_zone_iteration_stop.c, src/namestore/test_namestore_api_zone_to_name.c, src/namestore/zonefiles, src/namestore/zonefiles/4UCICULTINKC87UO4326KEEDQ9MTEP2AJT88MJFVGTGNK12QNGMQI2S41VI07UUU6EO19BTB06PDL0HE6VP1OM50HOJEI75RHP4JP80.zone, src/namestore/zonefiles/KJI3AL00K91EDPFJF58DAJM7H61D189TLP70N56JL8SVDCJE1SJ3SNNBOQPPONTL37FMHPS39SMK2NMVC0GQMGA6QCMHITT78O8GF80.zone: namestore manages zonekey files with private keys 2012-03-08 16:30 harsha * [r20373] src/stream/stream_api.c: peer interning 2012-03-08 13:23 harsha * [r20365] src/stream/stream_api.c, src/stream/test_stream_local.c: more assertions 2012-03-08 07:45 harsha * [r20362] src/stream/stream_api.c, src/stream/test_stream_local.c: Data message retransmissions 2012-03-07 12:45 wachs * [r20336] src/gns/gnunet-gns-fcfsd.c, src/gns/namestore_stub_api.c, src/gns/test_gns_dht_delegated_lookup.c, src/gns/test_gns_simple_delegated_lookup.c, src/gns/test_gns_simple_lookup.c, src/gns/test_gns_twopeer.c, src/include/gnunet_namestore_service.h, src/namestore/gnunet-namestore.c, src/namestore/gnunet-service-namestore.c, src/namestore/namestore_api.c, src/namestore/test_namestore_api.conf, src/namestore/test_namestore_api_create.c, src/namestore/test_namestore_api_create_update.c, src/namestore/test_namestore_api_zone_iteration.c, src/namestore/test_namestore_api_zone_iteration_specific_zone.c, src/namestore/test_namestore_api_zone_iteration_stop.c: namestore api change: include block expiration time in record create 2012-03-07 10:11 grothoff * [r20329] src/namestore/namestore_common.c: implementing more of GNUNET_NAMESTORE_value_to_string 2012-03-06 09:50 grothoff * [r20302] src/namestore/namestore.h: breaking stuff 2012-03-05 21:04 grothoff * [r20294] src/statistics/gnunet-service-statistics.c: fix 2012-03-05 15:38 grothoff * [r20282] src/include/gnunet_gns_service.h: fix 2012-03-04 22:55 grothoff * [r20258] src/fs/fs.conf.in, src/fs/fs_api.c: adding fs/ to all default directory names relating to file sharing 2012-03-04 22:10 grothoff * [r20252] src/fs/fs_api.c: fixing #1927 by further limiting the time a download probe can be active at a time in the download queue; this is equivalent to it having a low priority 2012-03-04 20:59 grothoff * [r20246] src/statistics/gnunet-service-statistics.c, src/statistics/statistics.h, src/statistics/statistics_api.c: make gnunet-service-statistics not exit on external shutdown signal as long as there are connected clients to be managed 2012-03-04 15:02 grothoff * [r20241] doc/man/Makefile.am, doc/man/gnunet-gns.1, src/gns/Makefile.am, src/gns/gnunet-gns.c: adding gnunet-gns, a new tool for zone manipulations 2012-03-04 14:37 grothoff * [r20237] doc/man/Makefile.am, doc/man/gnunet-rsa.1, src/util/Makefile.am, src/util/gnunet-rsa.c: adding gnunet-rsa, a new tool to create RSA keys and to print the public key 2012-03-04 13:51 grothoff * [r20232] src/include/gnunet_crypto_lib.h, src/util/crypto_hash.c: LRN: adding generic functions for conversion of binary data to ascii and back: GNUNET_CRYPTO_string_to_data and GNUNET_CRYPTO_data_to_string 2012-03-02 17:29 wachs * [r20206] src/namestore/Makefile.am, src/namestore/gnunet-service-namestore.c, src/namestore/namestore.h, src/namestore/namestore_api.c, src/namestore/test_namestore_api_put.c: 2012-03-02 15:39 wachs * [r20205] src/transport/plugin_transport_tcp.c: fix for mantis 2189 2012-03-01 11:58 szengel * [r20164] src/arm/gnunet-service-arm.c: Using GNUNET_snprintf. 2012-03-01 08:24 grothoff * [r20154] src/chat/gnunet-chat.c, src/fs/fs_uri.c, src/fs/gnunet-pseudonym.c, src/include/gnunet_pseudonym_lib.h, src/util/pseudonym.c, src/util/test_pseudonym.c: LRN: updates to pseudonym API from #1952, change pseudonym management 2012-02-29 19:21 wachs * [r20150] src/include/gnunet_crypto_lib.h, src/util/crypto_rsa.c: serialize privat key 2012-02-29 12:50 grothoff * [r20143] src/include/gnunet_common.h, src/include/gnunet_dnsparser_lib.h, src/include/gnunet_tun_lib.h: LRN: Enforce GCC bitfield layout for some structs on W32 2012-02-29 11:11 wachs * [r20142] src/include/gnunet_namestore_plugin.h, src/include/gnunet_namestore_service.h, src/namestore/gnunet-service-namestore.c, src/namestore/namestore_api.c, src/namestore/plugin_namestore_sqlite.c, src/namestore/test_namestore_api_lookup.c: nametore api change 2012-02-29 08:59 szengel * [r20135] src/arm/arm.h, src/arm/arm_api.c, src/arm/gnunet-arm.c, src/arm/gnunet-service-arm.c, src/include/gnunet_arm_service.h, src/include/gnunet_protocols.h: Adding arm list/info feature. 2012-02-28 19:08 grothoff * [r20127] src/include/gnunet_crypto_lib.h, src/util/crypto_rsa.c, src/vpn/test_gnunet_vpn.c: adding GNUNET_CRYPTO_setup_hostkey to setup a hostkey ahead of time, using this function in the VPN testcases to avoid timeouts in cases where creating a hostkey just takes too long --- such as on our UltraSprac 2012-02-28 17:29 grothoff * [r20121] src/util/os_priority.c: LRN: Apparently cleanup is not for W32 2012-02-28 17:28 grothoff * [r20120] po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po, src/util/os_priority.c: LRN: W32 pipe name generation needs random 2012-02-28 10:54 grothoff * [r20112] po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po: releasing GNUnet 0.9.2 2012-02-28 09:32 grothoff * [r20097] configure.ac, src/Makefile.am: add gns 2012-02-28 09:08 schanzen * [r20093] src/gns/plugin_block_gns.c: -fix 2012-02-27 20:00 wachs * [r20087] configure.ac: enabling libglpk detection 2012-02-27 11:00 grothoff * [r20060] src/arm/arm_api.c, src/arm/do_start_process.c, src/arm/gnunet-service-arm.c, src/ats/test_ats_api_bandwidth_consumption.c, src/ats/test_ats_api_scheduling.c, src/chat/test_chat.c, src/chat/test_chat_private.c, src/core/test_core_api.c, src/core/test_core_api_reliability.c, src/core/test_core_api_send_to_self.c, src/core/test_core_api_start_only.c, src/core/test_core_defaults.conf, src/core/test_core_quota_compliance.c, src/datastore/perf_datastore_api.c, src/datastore/test_datastore_api.c, src/datastore/test_datastore_api_management.c, src/datastore/test_defaults.conf, src/dht/test_dht_api.c, src/fs/test_fs_defaults.conf, src/fs/test_fs_download.c, src/fs/test_fs_download_indexed.c, src/fs/test_fs_download_persistence.c, src/fs/test_fs_list_indexed.c, src/fs/test_fs_namespace.c, src/fs/test_fs_namespace_list_updateable.c, src/fs/test_fs_publish.c, src/fs/test_fs_publish_persistence.c, src/fs/test_fs_search.c, src/fs/test_fs_search_persistence.c, src/fs/test_fs_start_stop.c, src/fs/test_fs_unindex.c, src/fs/test_fs_unindex_persistence.c, src/hostlist/test_gnunet_daemon_hostlist.c, src/hostlist/test_gnunet_daemon_hostlist_learning.c, src/hostlist/test_gnunet_daemon_hostlist_reconnect.c, src/hostlist/test_hostlist_defaults.conf, src/include/gnunet_disk_lib.h, src/include/gnunet_os_lib.h, src/include/platform.h, src/mesh/test_mesh_api.c, src/mesh/test_mesh_local_1.c, src/mesh/test_mesh_local_2.c, src/namestore/test_namestore_api.c, src/nat/nat.c, src/nat/nat_mini.c, src/nat/test_nat_test.c, src/nse/test_nse_api.c, src/peerinfo/test_peerinfo_api.c, src/statistics/test_statistics_api.c, src/statistics/test_statistics_api_loop.c, src/statistics/test_statistics_api_watch.c, src/stream/test_stream_local.c, src/stream/test_stream_local_halfclose.c, src/testing/test_testing_defaults.conf, src/testing/testing.c, src/testing/testing_group.c, src/transport/gnunet-transport-certificate-creation.c, src/transport/gnunet-transport-connect-running-peers.c, src/transport/gnunet-transport.c, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_wlan.c, src/transport/transport-testing.c, src/util/crypto_random.c, src/util/disk.c, src/util/helper.c, src/util/os_priority.c, src/util/scheduler.c, src/util/test_common_logging_runtime_loglevels.c, src/util/test_os_start_process.c, src/util/test_resolver_api.c, src/util/test_strings.c, src/vpn/test_gnunet_vpn.c: enabling use of pipes for signal communication also on UNIX to enable future integration with Java services 2012-02-27 10:54 wachs * [r20059] src/transport/test_transport_api.c: adding error messages 2012-02-25 19:08 grothoff * [r20026] doc/man/gnunet-directory.1, doc/man/gnunet-download.1, doc/man/gnunet-nat-server.1, doc/man/gnunet-pseudonym.1, doc/man/gnunet-publish.1, doc/man/gnunet-search.1, doc/man/gnunet-vpn.1: Igor/CG: various minor updates to man pages 2012-02-24 06:54 grothoff * [r19998] src/include/winproc.h, src/util/os_network.c: bratao/LRN: Use-bigger-buffer-for-EnumNICs3_results 2012-02-23 18:09 wachs * [r19993] src/transport/gnunet-service-transport_validation.c: not an error: plugin can return NULL (e.g. for IPv6 address when does not support IPv6) 2012-02-23 18:08 wachs * [r19992] src/transport/plugin_transport_unix.c: improved rescheduling improved recv error handling 2012-02-23 17:35 wachs * [r19983] src/transport/plugin_transport_udp.c, src/transport/plugin_transport_udp.h: splitted ipv4 and ipv6 socket select scheduling removed looping for write select improved ipv4/v6 en/disabling session management 2012-02-23 16:41 grothoff * [r19979] AUTHORS, src/include/gnunet_common.h, src/include/gnunet_crypto_lib.h, src/include/gnunet_server_lib.h, src/util/common_logging.c, src/util/crypto_hash.c, src/util/server.c: TG: attached are the following patches for GNUnet: - 1: added GNUNET_i2s_full - full variant of GNUNET_i2s - 2: GNUNET_CRYPTO_hash_from_string2 with additional length parameter, useful to prevent an additional strlen call when the caller already knows the length - 3: custom mst callbacks for the server, enables using the server with a custom parser - 4: added GNUNET_SERVER_client_set_finish_pending_write - enables changing the server behavior to finish pending writes when closing the connection Best regards, Gabor Adam Toth 2012-02-23 16:01 wachs * [r19975] src/transport/plugin_transport_unix.c: fix to the 100% CPU load problem 2012-02-23 15:34 wachs * [r19974] src/transport/gnunet-service-transport_neighbours.c: fix: ats suggested address for unknown plugin 2012-02-23 14:40 wachs * [r19968] src/ats/Makefile.am, src/ats/gnunet-service-ats_addresses_mlp.c, src/ats/gnunet-service-ats_addresses_mlp.h, src/ats/test_ats_api.conf, src/ats/test_ats_mlp.c: averaging fast changing quality values 2012-02-23 10:28 wachs * [r19962] src/transport/plugin_transport_udp.c: fix for mantis bug 0002154: change order of calls: - discard unsend messages - call transmit send continuation - call session_end 2012-02-23 10:18 wachs * [r19961] src/transport/plugin_transport_udp.c: fix to use correct queue 2012-02-22 18:34 grothoff * [r19949] src/fs/fs_api.c, src/fs/fs_dirmetascan.c, src/fs/fs_file_information.c, src/fs/fs_publish.c, src/fs/fs_sharetree.c, src/fs/gnunet-helper-fs-publish.c, src/fs/gnunet-publish.c: LRN: two directory patches change the way "is_directory" is evaluated. Now it must be GNUNET_YES for the execution flow to switch to a branch where something is considered to be a directory. The reason for that is that some functions might return GNUNET_SYSERR when asked whether something is a directory or not. Checking this value as "!= GNUNET_NO" will produce positive result, even though it's not a directory. 2012-02-22 12:43 wachs * [r19932] src/transport/gnunet-service-transport_validation.c: fix coverity 10138 2012-02-22 10:10 harsha * [r19915] src/stream/stream_api.c: added ack sending 2012-02-21 19:08 grothoff * [r19906] src/util/os_priority.c: LRN: Escape-trailing-slash-when-spawning-W32-process: 2012-02-21 10:12 schanzen * [r19881] src/gns/gnunet-service-gns.c, src/gns/namestore_stub_api.c: Better logging modified ns stub 2012-02-20 14:28 schanzen * [r19868] src/gns/Makefile.am, src/gns/gns_api.c, src/gns/gnunet-service-gns.c, src/gns/namestore_stub_api.c, src/include/gnunet_gns_service.h, src/include/gnunet_namestore_service.h: namestore stub api added fixes to namestore api 2012-02-20 12:08 grothoff * [r19864] src/fs/gnunet-helper-fs-publish.c: LRN: Do-partial-serialization-in-fs-publish-helper: 2012-02-20 09:09 grothoff * [r19859] src/fs/fs_sharetree.c: LRN: Iterate-over-a-copy-of-ksk-when-removing-items 2012-02-20 09:09 grothoff * [r19858] src/fs/gnunet-service-fs_put.c: LRN: check for tc being NULL 2012-02-18 19:03 grothoff * [r19844] src/fs/Makefile.am, src/fs/fs_api.h, src/fs/fs_list_indexed.c, src/fs/fs_namespace.c, src/fs/fs_namespace_advertise.c, src/fs/fs_publish.c, src/fs/fs_publish_ksk.c, src/fs/fs_tree.c, src/fs/gnunet-fs.c, src/fs/gnunet-publish.c, src/include/gnunet_fs_service.h: make all (?) asynchronously operating FS operations actually cancel-able 2012-02-18 15:16 grothoff * [r19837] src/fs/fs_namespace.c, src/include/gnunet_fs_service.h: add GNUNET_FS_namespace_dup API call 2012-02-18 13:50 grothoff * [r19836] src/util/disk.c: LRN: don't free memory on the stack 2012-02-16 14:29 wachs * [r19820] src/transport/gnunet-service-transport_neighbours.c: fix for fast reconnect: send ack after fast reconnect even when we are already connected since other peer waits for it 2012-02-16 14:28 wachs * [r19819] src/transport/test_transport_api_restart_1peer.c: fix test for peer restart 2012-02-16 12:58 grothoff * [r19817] src/fs/gnunet-helper-fs-publish.c: LRN: Use binary mode on W32 (lol -CG) 2012-02-15 13:39 schanzen * [r19812] src/gns/gns_api.c, src/gns/gnunet-gns-add.c, src/gns/gnunet-gns-lookup.c, src/gns/gnunet-service-gns.c, src/include/gnunet_gns_service.h: Added preliminary API and stubs for GNS 2012-02-15 09:49 wachs * [r19811] src/transport/gnunet-service-transport_neighbours.c: fix for Assertion failed at gnunet-service-ats_addresses.c:587 2012-02-13 16:36 wachs * [r19795] src/include/gnunet_transport_plugin.h: changes in includes 2012-02-13 16:02 wachs * [r19791] src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_validation.c, src/transport/plugin_transport_http.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_template.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c: removing legacy send functions from plugins and renaming new send function 2012-02-13 15:38 wachs * [r19790] src/transport/gnunet-service-transport_validation.c, src/transport/plugin_transport_http.h: new sending in validation 2012-02-13 13:27 wachs * [r19777] src/transport/plugin_transport_tcp.c: fix access before null check 2012-02-13 12:22 wachs * [r19775] src/transport/gnunet-service-transport_neighbours.c: removing old send code from neighbours 2012-02-13 11:57 wachs * [r19771] src/transport/Makefile.am, src/transport/gnunet-service-transport_neighbours.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_udp.h, src/transport/plugin_transport_udp_broadcasting.c, src/transport/plugin_transport_udp_new.h, src/transport/plugin_transport_udp_new_broadcasting.c: adding rewritten udp plugin 2012-02-13 10:58 wachs * [r19770] src/ats/gnunet-service-ats_math.c, src/ats/gnunet-service-ats_math.h: removing backup ATS code 2012-02-08 15:23 bartpolot * [r19733] src/mesh/gnunet-service-mesh.c, src/mesh/mesh_api.c, src/mesh/test_mesh_small.c: Attemp to fix ctrl-c crashes - disconnect from services before calling daemons_stop, since the cfg is free'd in the latter. 2012-02-06 09:34 grothoff * [r19707] doc/man/gnunet-transport.1, src/transport/gnunet-transport.c: adding -m option to gnunet-transport to enable monitor mode (see #1972) 2012-02-01 17:37 bartpolot * [r19608] src/include/gnunet_common.h: Let the compiler not include debug strings in binary when make is not configured with verbose 2012-02-01 17:08 wachs * [r19603] src/transport/Makefile.am, src/transport/gnunet-service-transport_blacklist.c, src/transport/test_transport_api_blacklisting.c, src/transport/transport_api_blacklist.c: fixing and testing blacklisting api and service 2012-02-01 15:00 wachs * [r19598] src/transport/test_transport_api_blacklisting.c: improved blacklisting test 2012-02-01 14:59 wachs * [r19597] src/transport/transport_api_blacklist.c: fix 2 crashes in blacklisting api - client transmit handle was not sent to NULL after sending - BlacklistMessage was not checked for NULL 2012-02-01 13:26 wachs * [r19596] src/transport/transport_api_blacklist.c: fix segfault: api never saved callback and callback_cls 2012-02-01 09:04 wachs * [r19591] src/transport/gnunet-service-transport_blacklist.c: added assertion (which is successfully failing ;-) ) 2012-01-31 13:46 wachs * [r19571] src/transport/plugin_transport_wlan.c: session based sending for wlan 2012-01-31 13:12 wachs * [r19568] src/util/os_network.c: ifconfig parsing Shum's patch bugs fixed in patch: - IPv4 loopback address was not included: added line 179 - stack allocated strings were not zeroed out, so last value was used if value was not included in current line - IPv4 netmask was passed as broadcast address (patch line 81) - IPv4 netmask was passed as IPv6 netmask, caused invalid address conversion (patch line 113) 2012-01-31 13:04 wachs * [r19567] src/util/test_os_network.c: adding verbose message 2012-01-31 08:25 wachs * [r19563] src/ats/ats_api_scheduling.c, src/hello/address.c, src/include/gnunet_ats_service.h: fixing const api and add check to address 2012-01-31 08:19 wachs * [r19562] src/transport/test_transport_api.c: fix assertion 2012-01-30 16:38 wachs * [r19543] src/transport/test_transport_api.c: variable message size 2012-01-27 15:51 wachs * [r19486] src/transport/plugin_transport_unix.c: implemented sessions 2012-01-27 14:30 wachs * [r19485] src/transport/plugin_transport_unix.c: removing retry code removing unused structs removing UDP Address structs fixed PrettyPrinter (printed UDP addresses???) 2012-01-27 13:48 wachs * [r19484] src/transport/plugin_transport_unix.c: complete select write implementation 2012-01-27 13:21 wachs * [r19483] src/transport/test_transport_api.c: fix memory leaks 2012-01-26 14:53 wachs * [r19440] src/transport/gnunet-service-transport_neighbours.c: fixing mantis 2101 2012-01-26 14:09 wachs * [r19437] src/transport/gnunet-service-transport_neighbours.c, src/transport/plugin_transport_http.c, src/transport/plugin_transport_http_server.c: implemented session based sending in transport service (coexisting with old code) 2012-01-26 14:01 bartpolot * [r19436] src/mesh/gnunet-service-mesh.c: Workaround for #2104, initialize local tid when local type destination connects after tunnel connect request by origin 2012-01-26 13:23 wachs * [r19435] src/ats/ats_api.c, src/ats/gnunet-service-ats_addresses_mlp.c: cppcheck 2012-01-25 14:22 wachs * [r19389] src/ats/gnunet-service-ats_scheduling.c: clang: mem access if plugin_name_length == 0 2012-01-25 13:56 wachs * [r19387] src/transport/plugin_transport_tcp.c: coverity 10054 2012-01-25 13:55 wachs * [r19386] src/transport/plugin_transport_http_client.c: coverity 10048 2012-01-24 20:28 grothoff * [r19359] src/vpn: ign 2012-01-24 01:32 bartpolot * [r19334] src/mesh/gnunet-service-mesh.c: Changed incoming tunnel notification to delay until relvant traffic is received from remote peer. Allowed several remote clients for each tunnel. 2012-01-23 15:45 wachs * [r19331] src/ats/gnunet-service-ats_addresses.c: fixing mantis 2098: ats did not lookup addresses correctly ats overwrote existing session when updating addresses 2012-01-23 15:43 wachs * [r19330] src/transport/gnunet-service-transport_neighbours.c: fixing: mantis 0002098: transport did not propagate session to ats 2012-01-23 14:54 grothoff * [r19329] src/include/gnunet_common.h: use noreturn macro for GNUNET_abort to help gcc and others 2012-01-23 09:14 grothoff * [r19322] src/util/win.cc: It-might-be-NULL 2012-01-20 15:41 bartpolot * [r19283] src/include/gnunet_mesh_service.h: Reflected changes in r19282. 2012-01-20 15:40 bartpolot * [r19282] src/mesh/mesh_api.c: Don't call cleaner on tunnels explicity destroyed. Updated and improved documentation. 2012-01-20 12:49 bartpolot * [r19280] src/mesh/gnunet-service-mesh.c: Fixed bug with remote tunnel traffic reception 2012-01-20 12:48 bartpolot * [r19279] src/mesh/mesh_api.c: Added more debug info 2012-01-19 23:17 bartpolot * [r19274] src/mesh/gnunet-service-mesh.c: Added TTL and MID initialization to tunnel refresh packets. 2012-01-19 23:00 bartpolot * [r19273] src/mesh/gnunet-service-mesh.c: Fixed #2088, don't call receive_done on traffic not generated by client. Improved debug output. 2012-01-19 22:39 bartpolot * [r19272] src/mesh/gnunet-service-mesh.c: Fixed #2087, wrong local tunnel number sent when multiple clients are subscribed to one type message on same peer and one clientis owner of the tunnel and the other is target 2012-01-19 22:13 bartpolot * [r19271] src/mesh/mesh_api.c: Fixed a memory leak on disconnect, double peer_rc decrease on tunnel destroy, adjusted backoff, completed doxygen 2012-01-19 15:20 bartpolot * [r19260] src/mesh/gnunet-service-mesh.c: Fixed client disconnect bug, delimited debug messages. 2012-01-19 14:33 bartpolot * [r19258] src/mesh/mesh_api.c: Fixed a peer_rc bug. 2012-01-19 11:06 bartpolot * [r19253] src/mesh/gnunet-service-mesh.c: Fixed an assert error when a client disconnects with open tunnels and without doing MESH_disconnect 2012-01-19 10:58 bartpolot * [r19252] src/mesh/mesh_api.c: Improved debug message 2012-01-18 19:28 grothoff * [r19248] src/include/gnunet_testing_lib.h, src/testing/Makefile.am, src/testing/helper.c: implementing GNUNET_TESTING_get_peer_identity (addressing #2083) 2012-01-18 15:10 bartpolot * [r19244] src/mesh/gnunet-service-mesh.c: Fixed client shutdown case, various minor fixes 2012-01-18 12:47 bartpolot * [r19233] src/mesh/gnunet-service-mesh.c: Implemented workaround for #2071 2012-01-18 11:27 bartpolot * [r19228] src/mesh/gnunet-service-mesh.c: Allowed client to send again 2012-01-18 11:17 bartpolot * [r19227] src/mesh/gnunet-service-mesh.c: Fixed a bug when a multicast packet is delivered exclusively to local clients 2012-01-17 19:45 bartpolot * [r19217] src/mesh/mesh_api.c: Added debug info for #2071 2012-01-17 17:29 bartpolot * [r19208] src/mesh/gnunet-service-mesh.c: Fixed #2070 and simplified data transmission unicast/multicast handling 2012-01-17 16:17 bartpolot * [r19206] src/mesh/gnunet-service-mesh.c: Temporal workaround for #2070 2012-01-17 16:13 bartpolot * [r19204] src/mesh/gnunet-service-mesh.c: Temporl workaround for #2070 2012-01-17 15:36 bartpolot * [r19196] src/mesh/mesh_api.c: Fixed queue bug 2012-01-16 21:11 grothoff * [r19181] src/pt/gnunet-daemon-pt.c: implemented new protocol translation daemon (#2063) 2012-01-16 17:17 harsha * [r19176] src/stream/test_stream_local.c, src/stream/test_stream_local_halfclose.c: refined test cases 2012-01-15 23:40 grothoff * [r19169] doc/man/Makefile.am, doc/man/gnunet-download-manager.1, src/fs/Makefile.am, src/fs/gnunet-download-manager.scm: adding Ludo's gnunet-download-manager.scm back to SVN HEAD 2012-01-14 23:18 grothoff * [r19146] src/arm/gnunet-service-arm.c, src/fs/fs_dirmetascan.c, src/include/gnunet_disk_lib.h, src/nat/nat.c, src/nat/nat_mini.c, src/testing/testing.c, src/transport/plugin_transport_wlan.c, src/util/disk.c, src/util/helper.c, src/util/os_priority.c, src/util/scheduler.c, src/util/test_common_logging_runtime_loglevels.c, src/util/test_os_start_process.c, src/util/test_scheduler.c: LRN: enable more fine-grained control over blocking/non-blocking pipe operation 2012-01-14 20:58 grothoff * [r19141] src/exit/exit.conf, src/exit/gnunet-daemon-exit.c, src/exit/gnunet-helper-exit.c: changing exit helper code to automatically do the network configuration for an exit node (by running sysctl/iptables commands as necessary) 2012-01-14 15:24 grothoff * [r19135] src/fs/Makefile.am, src/include/gnunet_fs_service.h: LRN: new threaded directory metadata scanner 2012-01-14 15:20 grothoff * [r19134] src/fs/fs_uri.c: LRN: skip short keywords when generating keywords automatically from metadata 2012-01-14 15:20 grothoff * [r19133] src/include/gnunet_disk_lib.h, src/util/disk.c: LRN: new pipe creation function GNUNET_DISK_pipe_from_fd to wrap existing file descriptor pair 2012-01-14 15:17 grothoff * [r19131] src/include/gnunet_strings_lib.h, src/util/strings.c: LRN: add function GNUNET_STRINGS_get_short_name to get basename 2012-01-13 22:14 harsha * [r19130] src/stream/test_stream_local.c: added half-closed shutdown test 2012-01-13 22:10 grothoff * [r19129] configure.ac, src/dht/dht.conf.in, src/dns/Makefile.am, src/dns/dns.conf.in, src/dv/dv.conf.in, src/transport/transport.conf.in, src/util/service.c, src/vpn/vpn.conf.in: improving code and build system to be in line with gnunet access control model for services as described at https://gnunet.org/gnunet-access-control-model 2012-01-13 21:33 harsha * [r19128] src/stream/test_stream_local.c: added shutdown call in testcase 2012-01-13 21:33 harsha * [r19127] src/include/gnunet_stream_lib.h: removed ambigious description 2012-01-13 18:10 harsha * [r19126] src/stream/stream_protocol.h, src/stream/test_stream_local.c, src/stream/test_stream_local.conf: test case for stream API 2012-01-13 17:41 harsha * [r19125] src/include/gnunet_stream_lib.h: generic type for read data 2012-01-13 17:04 grothoff * [r19123] configure.ac, src/arm/Makefile.am, src/arm/arm.conf, src/arm/arm.conf.in, src/ats/Makefile.am, src/ats/ats.conf, src/ats/ats.conf.in, src/chat/Makefile.am, src/chat/chat.conf, src/chat/chat.conf.in, src/core/Makefile.am, src/core/core.conf, src/core/core.conf.in, src/datastore/Makefile.am, src/datastore/datastore.conf, src/datastore/datastore.conf.in, src/dht/Makefile.am, src/dht/dht.conf, src/dht/dht.conf.in, src/dns/Makefile.am, src/dns/dns.conf, src/dns/dns.conf.in, src/dv/Makefile.am, src/dv/dv.conf, src/dv/dv.conf.in, src/exit/exit.conf, src/fs/Makefile.am, src/fs/fs.conf, src/fs/fs.conf.in, src/mesh/Makefile.am, src/mesh/mesh.conf, src/mesh/mesh.conf.in, src/nse/Makefile.am, src/nse/nse.conf, src/nse/nse.conf.in, src/peerinfo/Makefile.am, src/peerinfo/peerinfo.conf, src/peerinfo/peerinfo.conf.in, src/statistics/Makefile.am, src/statistics/statistics.conf, src/statistics/statistics.conf.in, src/transport/Makefile.am, src/transport/transport.conf, src/transport/transport.conf.in, src/util/Makefile.am, src/util/client.c, src/util/resolver.conf, src/util/resolver.conf.in, src/vpn/Makefile.am, src/vpn/vpn.conf, src/vpn/vpn.conf.in: change default configurations on systems with UNIX domain sockets to NOT specify any port for TCP-based IPC (and interpret that as no TCP-based IPC desired), as we can and want to use UNIX domain sockets in this case by default 2012-01-12 09:26 wachs * [r19101] src/vpn/gnunet-service-vpn.c: fix compile errors 2012-01-11 21:11 grothoff * [r19093] src/fs/fs_api.c, src/fs/fs_api.h, src/fs/fs_publish.c: fixing bug to ensure that we properly descend into deep directories for the various publish start/stop/suspend/resume event callbacks 2012-01-11 13:18 wachs * [r19085] src/ats/ats.conf, src/ats/gnunet-service-ats_addresses.c: mlp configuration 2012-01-11 12:41 wachs * [r19084] src/ats/Makefile.am: adding glpk to the makefile 2012-01-10 23:18 harsha * [r19082] src/stream/stream_protocol.h: stream P2P protocol message specification 2012-01-10 16:06 wachs * [r19078] src/vpn/vpn.conf: fix: wrong binary and duplicate unix path 2012-01-10 15:54 wachs * [r19077] src/integration-tests/confs/c_bootstrap_server.conf, src/integration-tests/confs/c_nat_client.conf, src/integration-tests/confs/c_no_nat_client.conf: added section to solve vpn conflicts 2012-01-09 16:38 grothoff * [r19069] src/include/gnunet_disk_lib.h, src/util/disk.c: LRN: make disk iterator start return GNUNET_SYSERR if run on empty directory 2012-01-05 21:04 grothoff * [r19023] src/exit/Makefile.am: fix 2012-01-05 20:58 bartpolot * [r19021] src/dht, src/dht/Makefile.am, src/dht/dht_api.c, src/dht/test_dht_monitor.c: Added testcase for DHT monitoring. 2012-01-05 20:18 grothoff * [r19017] src/include/gnunet_crypto_lib.h, src/util/crypto_crc.c: fix crc16 prototypes 2012-01-04 20:00 bartpolot * [r18989] src/dht/dht.h, src/dht/dht_api.c, src/dht/gnunet-service-dht_clients.c, src/dht/gnunet-service-dht_clients.h, src/dht/gnunet-service-dht_neighbours.c, src/include/gnunet_dht_service.h, src/include/gnunet_protocols.h: New DHT-monitor functionality 2012-01-04 15:48 grothoff * [r18988] doc/man/Makefile.am, doc/man/gnunet-monkey.1: move monkey man page to monkey 2012-01-04 14:20 grothoff * [r18982] src/dns/dnsparser.c, src/dns/gnunet-dns-monitor.c, src/dns/gnunet-service-dns_new.c: adding missing file 2012-01-02 12:23 grothoff * [r18937] src/dns/Makefile.am, src/dns/gnunet-helper-dns.c: DNS helper for DNS redesign 2012-01-02 10:22 grothoff * [r18929] src/include/gnunet_crypto_lib.h, src/util/crypto_crc.c: adding crc16 to gnunet_crypto_lib.h 2012-01-02 09:26 grothoff * [r18924] src/include/Makefile.am, src/include/gnunet_helper_lib.h, src/util/Makefile.am, src/util/helper.c: adding new GNUNET_HELPER_ API for communication with (SUID) helper binaries via stdin/stdout using standard GNUNET messages 2012-01-02 08:24 grothoff * [r18923] src/include/gnunet_os_lib.h, src/util/os_priority.c: adding GNUNET_OS_start_process_vap function 2012-01-02 03:51 grothoff * [r18912] src/dns/gnunet-helper-hijack-dns.c: dns hijacker code review 2012-01-01 23:39 grothoff * [r18908] src/dns/Makefile.am, src/dns/dns_api.c, src/include/gnunet_dns_service.h, src/vpn/Makefile.am, src/vpn/gnunet-daemon-vpn-dns.c, src/vpn/gnunet-daemon-vpn-dns.h, src/vpn/gnunet-daemon-vpn-helper.c, src/vpn/gnunet-daemon-vpn.c, src/vpn/gnunet-daemon-vpn.h: first quick hack to extract an initial DNS service API 2012-01-01 21:12 grothoff * [r18889] src/arm/gnunet-service-arm.c, src/chat/gnunet-chat.c, src/datastore/gnunet-service-datastore.c, src/fs/fs_api.c, src/fs/gnunet-service-fs_cp.c, src/include/gnunet_scheduler_lib.h, src/nse/gnunet-service-nse.c, src/peerinfo/gnunet-service-peerinfo.c, src/util/crypto_hash.c, src/util/scheduler.c: changing scheduler priorities to revert to DEFAULT instead of inheriting parent-task priority unless something else is explicitly specified 2011-12-30 22:25 grothoff * [r18853] src/fs/Makefile.am, src/fs/fs_uri.c: LRN: normalize keywords (decapitalize, split) using libunistring - #2052 2011-12-26 19:31 grothoff * [r18828] src/fs/fs_misc.c, src/include/gnunet_fs_service.h, src/util/os_network.c: adding GNUNET_FS_time_to_year function to FS API 2011-12-25 20:45 grothoff * [r18815] src/fs/gnunet-service-fs_cp.h, src/fs/gnunet-service-fs_pr.c: fixing migration stop delay calculation, largely by first calculating datastore load correctly and then by better distinguishing between datastore full, datastore timeout and success and finally by adding per-peer tracking of the current block interval to adjust to repeated undesireable behavior. See #2029. 2011-12-23 20:13 wachs * [r18794] src/ats/Makefile.am: missing file 2011-12-22 14:15 wachs * [r18756] src/transport/gnunet-transport.c: include plugin in gnunet-transport output 2011-12-21 18:03 bartpolot * [r18754] src/nse/gnunet-nse-profiler.c, src/nse/gnunet-service-nse.c: Added statistic reading to NSE, fixed some minor bugs 2011-12-21 16:39 wachs * [r18751] src/vpn/gnunet-helper-vpn.c: fix compile error 2011-12-21 14:33 wachs * [r18742] src/transport/plugin_transport_http.c: fixed assertion in gnunet-service resolver improved address printing for IPv6 addresses, especially if reverse lookup is not successful 2011-12-21 12:39 wachs * [r18735] src/transport/plugin_transport_udp.c: fixed assertion: wrong return value 2011-12-21 09:56 grothoff * [r18732] contrib/report.sh: add version reporting for MHD to report.sh 2011-12-21 09:40 grothoff * [r18730] src/arm/arm.h, src/ats-test/test_transport_ats_multiple_peers.c, src/ats/ats.h, src/chat/chat.h, src/core/core.h, src/core/gnunet-service-core_kx.c, src/datastore/datastore.h, src/dht/dht.h, src/dht/gnunet-service-dht_neighbours.c, src/dv/dv.h, src/dv/test_transport_api_dv.c, src/fragmentation/fragmentation.h, src/fs/fs.h, src/fs/gnunet-service-fs.h, src/hello/hello.c, src/hostlist/gnunet-daemon-hostlist.c, src/include/block_dns.h, src/include/block_fs.h, src/include/gnunet_ats_service.h, src/include/gnunet_bandwidth_lib.h, src/include/gnunet_common.h, src/include/gnunet_crypto_lib.h, src/include/gnunet_time_lib.h, src/mesh/mesh.h, src/mesh/mesh_protocol.h, src/nat/nat.h, src/nse/gnunet-service-nse.c, src/nse/nse.h, src/peerinfo/peerinfo.h, src/statistics/statistics.h, src/testing/test_testing_large_topology.c, src/testing/test_testing_topology.c, src/testing/test_testing_topology_blacklist.c, src/testing/test_testing_topology_churn.c, src/transport/gnunet-helper-transport-wlan.c, src/transport/gnunet-service-transport_neighbours.c, src/transport/gnunet-service-transport_validation.c, src/transport/gnunet-transport-wlan-sender.c, src/transport/plugin_transport_http.h, src/transport/plugin_transport_smtp.c, src/transport/plugin_transport_tcp.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_udp_new.c, src/transport/plugin_transport_unix.c, src/transport/plugin_transport_wlan.c, src/transport/plugin_transport_wlan.h, src/transport/test_quota_compliance.c, src/transport/test_transport_api_reliability.c, src/transport/test_transport_api_unreliability.c, src/transport/test_transport_api_unreliability_constant.c, src/transport/transport.h, src/util/crypto_ksk.c, src/util/crypto_rsa.c, src/util/resolver.h, src/vpn/gnunet-service-dns-p.h, src/vpn/gnunet-service-dns.c, src/vpn/gnunet-vpn-packet.h: fixing 2012: network structure alignment now forced to be correct even on W32 using #pragma pack from gcc 4.x 2011-12-20 16:41 wachs * [r18726] src/transport/gnunet-service-transport_neighbours.c: fix for mantis 1959 compare addresses and only mark address when addresses match 2011-12-20 16:01 wachs * [r18723] src/transport/gnunet-service-transport_clients.c: fix for mantis #2008 2011-12-20 15:48 wachs * [r18722] src/transport/transport_api.c: Improvement in reconnect: first disconnect, then destroy neighbours 2011-12-20 12:58 wachs * [r18719] src/include/gnunet_transport_plugin.h, src/transport/plugin_transport_tcp.c: first changes for new plugin api 2011-12-20 09:20 grothoff * [r18714] AUTHORS, configure.ac, src/dht/test_dht_2dtorus.conf: Adding optional compiler and linker hardening options as per suggestion from Jacob 2011-12-19 23:24 grothoff * [r18710] src/dht/test_dht_2dtorus.conf: do not run with full on NSE during testing 2011-12-19 21:26 grothoff * [r18704] src/include/gnunet_statistics_service.h, src/statistics/statistics_api.c: implement watch_cancel function 2011-12-19 17:15 grothoff * [r18698] src/fs/fs_api.c, src/fs/fs_api.h, src/fs/fs_search.c: improving results seen communication to consider which exact keywords a particular result has been seen for so far 2011-12-19 17:10 wachs * [r18697] src/integration-tests/Makefile.am, src/integration-tests/gnunet_testing.py.in, src/integration-tests/test_integration_disconnect.py.in: a new nat disconnect test 2011-12-19 16:31 grothoff * [r18696] src/transport/gnunet-service-transport_neighbours.c: fixing #2014 2011-12-19 15:59 grothoff * [r18693] src/fs/gnunet-service-fs_pr.c: limit lifetime of migrated content to at most 1 year 2011-12-19 15:52 grothoff * [r18692] src/fs/gnunet-service-fs_cp.c, src/fs/gnunet-service-fs_cp.h, src/fs/gnunet-service-fs_pr.c: block data migration based on lowest discarded expiration of content in the datastore to avoid wasting bandwidth on migrating content that is just instantly discarded again anyway 2011-12-19 15:02 wachs * [r18691] src/integration-tests/test_integration_clique.py.in, src/integration-tests/test_integration_disconnect.py.in, src/integration-tests/test_integration_restart.py.in: fixing some timeouts 2011-12-19 14:26 wachs * [r18690] src/ats/ats_api_scheduling.c: 2011-12-19 14:25 wachs * [r18689] src/ats/ats_api_scheduling.c, src/transport/gnunet-service-transport_neighbours.c: fixes for mantis #1988 and cleanup 2011-12-19 14:10 grothoff * [r18688] src/fs/gnunet-service-fs_cp.c, src/fs/gnunet-service-fs_pr.c, src/fs/gnunet-service-fs_pr.h: actually limit FS memory consumption by limiting how many requests we track from other peers (respective GSF-option had not been set; new code also inverts the meaning of the bit, so it does not have to be set for peers but rather is now set for clients to excempt them from the limitation) 2011-12-19 13:54 grothoff * [r18686] src/datastore/datastore.h, src/datastore/datastore_api.c, src/datastore/perf_datastore_api.c, src/datastore/test_datastore_api.c, src/datastore/test_datastore_api_management.c, src/fs/fs_namespace.c, src/fs/fs_publish.c, src/fs/fs_unindex.c, src/fs/gnunet-service-fs_indexing.c, src/fs/gnunet-service-fs_pr.c, src/include/gnunet_datastore_service.h: adding min_expiration argument to GNUNET_DATASTORE_ContinuationWithStatus callback to communicate which content has a chance of being stored in the medium term 2011-12-19 13:08 wachs * [r18684] src/hostlist/test_gnunet_daemon_hostlist.c: added LRN's patch from mantis bug 1998 2011-12-19 12:12 wachs * [r18682] src/include/gnunet_ats_service.h, src/transport/plugin_transport_wlan.c: additional network type for WLAN 2011-12-19 12:08 wachs * [r18681] src/ats/ats_api_scheduling.c: checked mantis #0002016 and added additional assertion 2011-12-19 10:59 grothoff * [r18680] src/nat/gnunet-helper-nat-server.c: Jacob Appelbaum reviewed gnunet-helper-nat-server and affirms that the code 'seems fine' 2011-12-19 09:32 grothoff * [r18678] src/datastore/gnunet-service-datastore.c: fixing calculation of Bloom filter size that was too large by 1024x because it was not adjusted when the unit for the quota was changed from kb to bytes 2011-12-17 18:32 grothoff * [r18662] contrib/apparmor, contrib/apparmor/usr.bin.gnunet-helper-nat-server: adding apparmor profile for gnunet-helper-nat-server from Jacob 2011-12-16 22:42 grothoff * [r18653] src/datastore/plugin_datastore_sqlite.c: implementing get_keys API for sqlite datastore plugin (#2013) 2011-12-16 22:19 grothoff * [r18652] src/statistics/statistics_api.c, src/statistics/test_statistics_api_watch.c: code cleanup, also trying to fix #2011 2011-12-16 22:13 grothoff * [r18650] src/nat/gnunet-helper-nat-client.c: really minimizing gnunet-helper-nat-client code running with root rights 2011-12-16 22:04 grothoff * [r18649] src/nat/gnunet-helper-nat-server-windows.c, src/nat/gnunet-helper-nat-server.c: really minimizing code running with root rights 2011-12-16 21:19 grothoff * [r18647] src/util/container_bloomfilter.c: cleaning up bloomfilter code and disk file size tests 2011-12-16 17:15 wachs * [r18635] src/integration-tests/confs/c_nat_client.conf, src/integration-tests/gnunet_testing.py.in, src/integration-tests/test_integration_clique_nat.py.in: 2011-12-16 16:27 wachs * [r18634] src/integration-tests/gnunet_testing.py.in, src/integration-tests/test_integration_clique_nat.py.in: improvements and fixes 2011-12-16 16:12 wachs * [r18633] src/integration-tests/confs/c_nat_client.conf, src/integration-tests/gnunet_testing.py.in, src/integration-tests/test_integration_clique_nat.py.in: fix 2011-12-16 14:49 wachs * [r18632] src/integration-tests/Makefile.am, src/integration-tests/confs/c_nat_client.conf, src/integration-tests/test_integration_clique_nat.py.in: adding nat clique test 2011-12-16 14:03 wachs * [r18631] src/integration-tests/gnunet_testing.py.in: improved statisc output 2011-12-16 13:43 wachs * [r18630] src/integration-tests/test_integration_restart.py.in: new test: connect after peer restart? 2011-12-16 13:43 wachs * [r18629] src/integration-tests/Makefile.am, src/integration-tests/test_integration_bootstrap_and_connect.py.in, src/integration-tests/test_integration_clique.py.in, src/integration-tests/test_integration_disconnect.py.in: 2011-12-16 12:25 wachs * [r18627] src/integration-tests/gnunet_testing.py.in, src/integration-tests/test_integration_bootstrap_and_connect.py.in, src/integration-tests/test_integration_clique.py.in, src/integration-tests/test_integration_disconnect.py.in: added support for interupting a test 2011-12-16 11:19 grothoff * [r18625] src/nat/gnunet-helper-nat-client.c, src/nat/gnunet-helper-nat-server.c: additional stylistic changes to gnunet-helper-nat-client anticipating next round of suggestions from Jacob Applebaum 2011-12-16 11:16 grothoff * [r18624] configure.ac, src/nat/gnunet-helper-nat-server.c: some very minor stylistic changes to gnunet-helper-nat-server based on suggestions from Jacob Applebaum 2011-12-15 17:03 wachs * [r18620] src/integration-tests/gnunet_testing.py.in, src/integration-tests/test_integration_bootstrap_and_connect.py.in, src/integration-tests/test_integration_clique.py.in, src/integration-tests/test_integration_disconnect.py.in: improved tests 2011-12-15 15:56 wachs * [r18617] src/integration-tests/Makefile.am, src/integration-tests/gnunet_testing.py.in, src/integration-tests/test_integration_bootstrap_and_connect.py.in, src/integration-tests/test_integration_clique.py.in: improved test framework 2011-12-15 15:20 wachs * [r18615] src/integration-tests/gnunet_testing.py.in: added improved check management 2011-12-15 14:56 grothoff * [r18614] src/fs/gnunet-service-fs_cp.c, src/fs/gnunet-service-fs_pr.c: use better heuristic to deal with datastore put failures; log migration stop message transmissions 2011-12-15 14:55 grothoff * [r18613] src/datastore/gnunet-service-datastore.c, src/include/gnunet_datastore_plugin.h: adding support for detection quota changes / missing bloomfilter files and reconstruction/recovery code 2011-12-15 14:21 wachs * [r18603] src/integration-tests/gnunet_testing.py.in: peer get automatically stopped 2011-12-15 14:09 wachs * [r18602] src/integration-tests/gnunet_testing.py.in: improved peer management 2011-12-15 12:44 grothoff * [r18601] src/util/container_bloomfilter.c: only try to read bf from disk if we didn't just create the file 2011-12-15 12:41 grothoff * [r18600] src/datastore/datastore.conf: store Bloomfilter with rest of datastore data 2011-12-15 12:40 grothoff * [r18599] src/include/gnunet_disk_lib.h, src/util/container_bloomfilter.c, src/util/disk.c: extra error checking in Bloom filter to check that the size of the file on disk corresponds to the expected size for the given filter 2011-12-15 09:51 wachs * [r18597] README: added python remark to hacking This line, and those below, will be ignored -- M README 2011-12-15 09:46 wachs * [r18596] configure.ac: Python version required to run tests is >= 2.6 2011-12-14 13:32 wachs * [r18590] src/include/gnunet_ats_service.h, src/transport/gnunet-service-transport.c, src/transport/plugin_transport_http.c, src/transport/plugin_transport_udp.c, src/transport/plugin_transport_unix.c: wan/lan detection in plugins 2011-12-14 13:31 wachs * [r18589] src/ats/ats_api_scheduling.c: adding detection for AF_UNIX 2011-12-14 10:25 wachs * [r18588] src/transport/plugin_transport_http.c, src/transport/plugin_transport_http.h, src/transport/plugin_transport_http_server.c, src/transport/plugin_transport_tcp.c: WAN/LAN for HTTP/S 2011-12-14 08:53 wachs * [r18587] src/include/gnunet_transport_plugin.h, src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_plugins.c, src/transport/gnunet-service-transport_plugins.h, src/transport/plugin_transport_tcp.c: removing ats functions from plugins, instead provide callback function 2011-12-14 08:52 wachs * [r18586] src/ats/ats_api_scheduling.c: 2011-12-13 16:26 wachs * [r18578] src/include/gnunet_transport_plugin.h: missing 2011-12-13 16:20 wachs * [r18577] src/transport/gnunet-service-transport.c, src/transport/gnunet-service-transport_plugins.c, src/transport/plugin_transport_tcp.c: changes: changed order of startup since ats is now required for plugins transport provides ATS handles for plugins network detection for tcp 2011-12-13 15:19 wachs * [r18576] src/transport/plugin_transport_wlan.c: address type in WLAN 2011-12-13 15:15 wachs * [r18575] src/transport/plugin_transport_unix.c: added ATS addresstype information to unix 2011-12-13 15:13 wachs * [r18574] src/ats/ats_api_scheduling.c, src/ats/gnunet-service-ats_addresses.c: fixing crash 0002007 adding network information to addresses 2011-12-13 15:02 wachs * [r18573] src/util/os_network.c: LRN's patch argument order 2011-12-13 14:36 grothoff * [r18572] src/fs/gnunet-service-fs.c, src/fs/gnunet-service-fs_lc.c, src/fs/gnunet-service-fs_pr.h: trying to fix #2000 2011-12-13 12:31 wachs * [r18566] src/ats/Makefile.am, src/ats/ats_api_scheduling.c, src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h, src/include/gnunet_ats_service.h: move code from service to api fix bug add test 2011-12-12 17:11 wachs * [r18562] src/ats/gnunet-service-ats_addresses.c, src/include/gnunet_ats_service.h: WAN/LAN detection Mantis 1991 2011-12-12 13:58 wachs * [r18560] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h: IPv4 check implemented TODO: IPv6 2011-12-12 12:52 wachs * [r18559] src/ats/gnunet-service-ats_addresses.c, src/ats/gnunet-service-ats_addresses.h: WAN/LAN detection 2011-12-12 12:05 wachs * [r18558] src/Makefile.am, src/integration-tests/test_integration_clique.py.in: including integration tests in checks 2011-12-11 15:39 grothoff * [r18556] src/transport, src/transport/Makefile.am, src/transport/gnunet-helper-transport-wlan-dummy.c, src/transport/gnunet-helper-transport-wlan.c, src/transport/gnunet-transport-wlan-helper-dummy.c, src/transport/gnunet-transport-wlan-helper.c, src/transport/gnunet-transport-wlan-sender.c, src/transport/plugin_transport_wlan.c: renaming WLAN helper process to gnunet-helper-transport-wlan in order to satisfy naming conventions 2011-12-10 13:49 harsha * [r18543] src/include/gnunet_stream_lib.h: syntax 2011-12-09 17:31 wachs * [r18541] src/integration-tests/Makefile.am, src/integration-tests/confs/c_no_nat_client_2.conf, src/integration-tests/hostkeys/0002-hostkey, src/integration-tests/hostkeys/0003-hostkey, src/integration-tests/hostkeys/0004-hostkey, src/integration-tests/hostkeys/0005-hostkey, src/integration-tests/hostkeys/0006-hostkey, src/integration-tests/hostkeys/0007-hostkey, src/integration-tests/hostkeys/0008-hostkey, src/integration-tests/hostkeys/0009-hostkey, src/integration-tests/test_integration_clique.py.in, src/integration-tests/test_integration_disconnect.py.in: clique 2011-12-09 16:18 wachs * [r18534] src/integration-tests/Makefile.am, src/integration-tests/test_integration_bootstrap_and_connect.py.in, src/integration-tests/test_integration_disconnect.py.in: disconnect test 2011-12-09 16:09 grothoff * [r18533] src/statistics/statistics_api.c: fix crash 2011-12-09 15:57 harsha * [r18532] src/include/gnunet_stream_lib.h: fixed missing doc comment 2011-12-09 15:55 harsha * [r18531] src/include/gnunet_stream_lib.h, src/stream, src/stream/README: added API definitions for stream library 2011-12-09 15:19 wachs * [r18530] src/integration-tests/test_integration_bootstrap_and_connect.py.in: added core sessions 2011-12-09 14:48 wachs * [r18528] src/integration-tests/confs/c_bootstrap_server.conf, src/integration-tests/confs/c_no_nat_client.conf, src/integration-tests/test_integration_bootstrap_and_connect.py.in: first test ready 2011-12-09 12:41 wachs * [r18526] src/integration-tests/test_integration_bootstrap_and_connect.py.in: test now checks if boths transports are connecting 2011-12-09 10:40 wachs * [r18525] src/statistics/gnunet-statistics.c: added quiet mode just printing the value 2011-12-08 16:16 wachs * [r18517] src/integration-tests/Makefile.am, src/integration-tests/confs, src/integration-tests/confs/c_bootstrap_server.conf, src/integration-tests/confs/c_nat_client.conf, src/integration-tests/confs/c_no_nat_client.conf, src/integration-tests/test_integration_bootstrap_and_connect.py.in, src/integration-tests/test_integration_clique.py.in: step by step 2011-12-08 15:45 grothoff * [r18515] doc/man/gnunet-arm.1, po/POTFILES.in, src/arm/Makefile.am, src/arm/arm.h, src/arm/arm_api.c, src/arm/do_start_process.c, src/arm/gnunet-arm.c, src/arm/gnunet-service-arm.c, src/arm/mockup-service.c, src/arm/test_arm_api.c, src/arm/test_exponential_backoff.c, src/arm/test_gnunet_arm.sh, src/arm/test_gnunet_service_manager.c, src/include/gnunet_arm_service.h, src/include/gnunet_protocols.h: major rewrite of ARM service and a bit of the ARM IPC to take advantage of the simplifications possible now that we no longer intercept traffic; the new code in particular is better at communicating what exactly ARM was doing in response to requests. A major change is that gnunet-arm -i/-k now only impacts if a service is running by-default, on-demand starting is no longer impacted, option -t from gnunet-arm was removed 2011-12-08 15:32 wachs * [r18512] src/testing/gnunet-testing.c: modified to create cfg with default without template 2011-12-08 13:43 wachs * [r18511] src/testing/gnunet-testing.c: added option to specify hostkey file 2011-12-08 13:16 wachs * [r18510] configure.ac, src/integration-tests, src/integration-tests/Makefile.am, src/integration-tests/test_integration_clique.py.in: basics for integration tests 2011-12-08 13:04 wachs * [r18509] src/testing/Makefile.am: space after backslash 2011-12-08 12:42 grothoff * [r18506] src/nse/gnunet-service-nse.c: add statistic to track estimated network diameter 2011-12-08 12:38 grothoff * [r18505] src/nse/gnunet-service-nse.c: fixing issue with sending back size estimate messages to peers that already have good estimate information 2011-12-07 17:02 wachs * [r18497] src/testing/gnunet-testing.c: added hostkey generation functionality 2011-12-07 15:34 wachs * [r18496] src/include/gnunet_testing_lib.h, src/testing/gnunet-testing.c, src/testing/testing_group.c: 2011-12-07 15:33 bartpolot * [r18495] src/nse/nse_api.c: Made sure that NSE never returns invalid standard deviation values 2011-12-07 13:23 wachs * [r18492] src/testing/gnunet-testing.c: 2011-12-07 12:42 wachs * [r18491] src/include/gnunet_getopt_lib.h, src/util/getopt_helpers.c: fixed docu 2011-12-07 12:28 wachs * [r18490] src/testing/Makefile.am, src/testing/gnunet-testing.c: testing cmd line tool 2011-12-06 20:20 grothoff * [r18484] src/arm/gnunet-service-arm_interceptor.c: removing ARM interceptor connection forwarding post-accept code, now using lsocks everywhere 2011-12-06 20:07 grothoff * [r18479] src/include/gnunet_common.h, src/include/gnunet_network_lib.h, src/include/gnunet_server_lib.h, src/transport/Makefile.am, src/transport/gnunet-transport-wlan-helper.c, src/util/pseudonym.c: eliminating last dependency on util code from wlan helper by inlining 2011-12-06 19:06 grothoff * [r18476] src/util/common_logging.c: LRN: correct behaviour when logfile does not exist 2011-12-06 18:06 grothoff * [r18475] src/arm/gnunet-service-arm_interceptor.c: fix compile 2011-12-06 18:06 grothoff * [r18474] src/util/common_logging.c: LRN: Ensure that GTK can then do the internal call write(2, message, strlen (message)); successfully by default. 2011-12-06 17:58 grothoff * [r18473] src/arm/do_start_process.c, src/arm/gnunet-service-arm.c, src/arm/gnunet-service-arm.h, src/arm/gnunet-service-arm_interceptor.c, src/include/gnunet_network_lib.h, src/include/gnunet_os_lib.h, src/include/platform.h, src/util/network.c, src/util/os_priority.c, src/util/service.c: Implement passing sockets in IPC on W32 (#1975) 2011-12-06 14:55 wachs * [r18463] src/include/gnunet_common.h, src/transport/gnunet-transport-wlan-helper.c, src/transport/gnunet_wlan_sender.c, src/transport/plugin_transport_wlan.c: adding GNUnet endian operations 2011-12-06 14:19 wachs * [r18461] src/transport/gnunet_wlan_sender.c: timestamp not supported on fedora core 8 2011-12-06 14:13 grothoff * [r18460] src/datastore/gnunet-service-datastore.c, src/util/common_allocation.c, src/util/container_bloomfilter.c: Fixing #1976 by allowing allocations between INT_MAX and SIZE_MAX and at the same time limiting BF size for datastore to 2 GB. Also fixing infinite loop when creating BFs of sizes between 2-4 GB 2011-12-06 13:54 grothoff * [r18456] src/arm/gnunet-service-arm_interceptor.c, src/include/gnunet_common.h, src/util/common_endian.c: use uint64_t instead of long long for GNUNET_ntohll/GNUNET_htonll 2011-12-06 13:35 bartpolot * [r18451] src/include/platform.h: Removed legacy code 2011-12-06 12:49 grothoff * [r18445] src/include/platform.h, src/include/winproc.h, src/nat/gnunet-helper-nat-client-windows.c, src/nat/gnunet-helper-nat-server-windows.c: LRN: Fixing Mantis #1974: On W32 winsock2.h defines FD_SETSIZE (if it was not defined before inclusion of the header) to 64, which means that it's not possible to select on more than 64 sockets at once. This might work during the tests, but in the wild people might want to have more than 60 connections, at least in the transport service. The patch attached should increase the limit to 1024. 2011-12-06 09:44 grothoff * [r18432] README: fix 2011-12-06 01:56 grothoff * [r18431] contrib/Makefile.am: distfix 2011-12-01 09:17 grothoff * [r18412] src/datastore/perf_plugin_datastore.c, src/util/winproc.c: LRN: Adding vectored exception handling for W32 (#1965) Whenever an exception occurs, and the process is not being debugged, it will run a debugger specified by GNUNET_DEBUGGER environment variable, and wait for it to attach. The net effect is the same as using JIT debugging (AeDebug), but without the stack being broken by SEH (because VEH has a priority over SEH), which allows for fuller backtraces for any exception, not just for GNUNET_abort() calls. 2011-11-30 15:21 grothoff * [r18410] Makefile.am, configure.ac, po/de.po, po/es.po, po/sv.po, po/vi.po, po/zh_CN.po: releasing GNUnet 0.9.0 gnunet-0.10.1/gnunet_config.h.in0000644000175000017500000004332312320752056013424 00000000000000/* gnunet_config.h.in. Generated from configure.ac by autoheader. */ #define _GNU_SOURCE 1 /* Define to 1 if the `closedir' function returns void instead of `int'. */ #undef CLOSEDIR_VOID /* This is a Cygwin system */ #undef CYGWIN /* This is an Apple Darwin system */ #undef DARWIN /* enable expensive heap statistics */ #undef ENABLE_HEAP_STATISTICS /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS /* have NSE send timestamp information to testbed logger */ #undef ENABLE_NSE_HISTOGRAM /* 1 if freed memory should be poisoned, 0 otherwise */ #undef ENABLE_POISONING /* Build with support for SuperMUC */ #undef ENABLE_SUPERMUC /* enable workarounds used on Windows (only useful for test cases) */ #undef ENABLE_WINDOWS_WORKAROUNDS /* Build a Mac OS X Framework */ #undef FRAMEWORK_BUILD /* This is a FreeBSD system */ #undef FREEBSD /* This is a GNU system */ #undef GNU /* Define to cull all logging calls */ #undef GNUNET_CULL_LOGGING /* This should be the default choice for the name of the first network interface */ #undef GNUNET_DEFAULT_INTERFACE /* 1 if extra logging is enabled, 2 for very verbose extra logging, 0 otherwise */ #undef GNUNET_EXTRA_LOGGING /* Define to 1 if you have the header file. */ #undef HAVE_ARGZ_H /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the `atoll' function. */ #undef HAVE_ATOLL /* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework. */ #undef HAVE_CFLOCALECOPYCURRENT /* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework. */ #undef HAVE_CFPREFERENCESCOPYAPPVALUE /* Define to 1 if your system has a working `chown' function. */ #undef HAVE_CHOWN /* Define to 1 if you have the header file. */ #undef HAVE_CTYPE_H /* Define if the GNU dcgettext() function is already present or preinstalled. */ #undef HAVE_DCGETTEXT /* Define to 1 if you have the declaration of `gcry_mpi_set_opaque_copy', and to 0 if you don't. */ #undef HAVE_DECL_GCRY_MPI_SET_OPAQUE_COPY /* Define to 1 if you have the declaration of `_stati64', and to 0 if you don't. */ #undef HAVE_DECL__STATI64 /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_EXTRACTOR_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the `freeifaddrs' function. */ #undef HAVE_FREEIFADDRS /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #undef HAVE_FSEEKO /* Define this if getaddrinfo() is available */ #undef HAVE_GETADDRINFO /* Define this if gethostbyaddr() is available */ #undef HAVE_GETHOSTBYADDR /* Define this if gethostbyname() is available */ #undef HAVE_GETHOSTBYNAME /* Define to 1 if you have the `gethostbyname2' function. */ #undef HAVE_GETHOSTBYNAME2 /* Define this if gethostname() is available */ #undef HAVE_GETHOSTNAME /* Define to 1 if you have the `getifaddrs' function. */ #undef HAVE_GETIFADDRS /* getloadavg supported */ #undef HAVE_GETLOADAVG /* Define this if getnameinfo() is available */ #undef HAVE_GETNAMEINFO /* Define to 1 if you have the `getpeereid' function. */ #undef HAVE_GETPEEREID /* Define to 1 if you have the `getpeerucred' function. */ #undef HAVE_GETPEERUCRED /* Define to 1 if you have the `getresgid' function. */ #undef HAVE_GETRESGID /* Define to 1 if you have the `getrlimit' function. */ #undef HAVE_GETRLIMIT /* Define to 1 if you have the `getrusage' function. */ #undef HAVE_GETRUSAGE /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define to 1 if you have the header file. */ #undef HAVE_GLPK_H /* Define to 1 if `presolve' is a member of `glp_iocp'. */ #undef HAVE_GLP_IOCP_PRESOLVE /* We have GnuTLS */ #undef HAVE_GNUTLS /* Define to 1 if you have the header file. */ #undef HAVE_GNUTLS_ABSTRACT_H /* We have GnuTLS with DANE support */ #undef HAVE_GNUTLS_DANE /* Define to 1 if you have the header file. */ #undef HAVE_GNUTLS_DANE_H /* Define if you have the iconv() function. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_IFADDRS_H /* Define this if inet_ntoa() is available */ #undef HAVE_INET_NTOA /* Define to 1 if you have the `initgroups' function. */ #undef HAVE_INITGROUPS /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_KSTAT_H /* Define to 1 if you have the header file. */ #undef HAVE_KVM_H /* Define to 1 if you have the header file. */ #undef HAVE_LANGINFO_H /* Have bluetooth library */ #undef HAVE_LIBBLUETOOTH /* Have GLPK */ #undef HAVE_LIBGLPK /* Have libgnurl */ #undef HAVE_LIBGNURL /* Define to 1 if you have the `intl' library (-lintl). */ #undef HAVE_LIBINTL /* Define to 1 if you have the header file. */ #undef HAVE_LIBINTL_H /* Define to 1 if you have the `kstat' library (-lkstat). */ #undef HAVE_LIBKSTAT /* Define to 1 if you have the `kvm' library (-lkvm). */ #undef HAVE_LIBKVM /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the `resolv' library (-lresolv). */ #undef HAVE_LIBRESOLV /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET /* Define if you have the unistring library. */ #undef HAVE_LIBUNISTRING /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the header file. */ #undef HAVE_LTDL_H /* Define to 1 if you have the header file. */ #undef HAVE_MACH_MACH_H /* Define to 1 if you have the `mallinfo' function. */ #undef HAVE_MALLINFO /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_MALLOC_H /* Define to 1 if you have the `malloc_size' function. */ #undef HAVE_MALLOC_SIZE /* Define to 1 if you have the `malloc_usable_size' function. */ #undef HAVE_MALLOC_USABLE_SIZE /* Define to 1 if you have the header file. */ #undef HAVE_MATH_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* We have libmicrohttpd */ #undef HAVE_MHD /* Define to 1 if you have the header file. */ #undef HAVE_MICROHTTPD_H /* Define to 1 if you have the `mremap' function. */ #undef HAVE_MREMAP /* Define to 1 if you have the header file. */ #undef HAVE_MYSQL_MYSQL_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_SYSTM_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IP_H /* Define to 1 if you have the header file. */ #undef HAVE_NSS_H /* Define to 1 if the system has the type `off_t'. */ #undef HAVE_OFF_T /* lacking ogg */ #undef HAVE_OGG /* Define to 1 if you have the header file. */ #undef HAVE_OGG_OGG_H /* Have libopus library */ #undef HAVE_OPUS /* Define to 1 if you have the header file. */ #undef HAVE_POSTGRESQL_LIBPQ_FE_H /* Have libpulse(audio) library */ #undef HAVE_PULSE /* Define to 1 if you have the `random' function. */ #undef HAVE_RANDOM /* Define this if select() is available */ #undef HAVE_SELECT /* Define to 1 if you have the `setresuid' function. */ #undef HAVE_SETRESUID /* Define to 1 if you have the `setrlimit' function. */ #undef HAVE_SETRLIMIT /* Define to 1 if you have the header file. */ #undef HAVE_SIGNAL_H /* Define to 1 if the system has the type `sigset_t'. */ #undef HAVE_SIGSET_T /* Define to 1 if the system has the type `size_t'. */ #undef HAVE_SIZE_T /* Do we have sockaddr_in.sin_len? */ #undef HAVE_SOCKADDR_IN_SIN_LEN /* Define this if socket() is available */ #undef HAVE_SOCKET /* Define to 1 if you have the header file. */ #undef HAVE_SOCKLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_SQLITE3_H /* Define to 1 if you have the `srandom' function. */ #undef HAVE_SRANDOM /* Define to 1 if you have the `stat' function. */ #undef HAVE_STAT /* Define to 1 if you have the `stat64' function. */ #undef HAVE_STAT64 /* Define to 1 if you have the `statfs' function. */ #undef HAVE_STATFS /* Define to 1 if you have the `statvfs' function. */ #undef HAVE_STATVFS /* Define to 1 if `stat' has the bug that it succeeds when given the zero-length file name argument. */ #undef HAVE_STAT_EMPTY_STRING_BUG /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H /* Define to 1 if stdbool.h conforms to C99. */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_ENDIAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MMAN_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MSG_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_RESOURCE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIMEB_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UCRED_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VFS_H /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_TERMINOS_H /* Define if struct tm has the tm_gmtoff member. */ #undef HAVE_TM_GMTOFF /* Define to 1 if you have the header file. */ #undef HAVE_UCRED_H /* We can access-64 bit values that are only 32-bit aligned */ #undef HAVE_UNALIGNED_64_ACCESS /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* Have compression library */ #undef HAVE_ZLIB /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL /* Define as const if the declaration of iconv() needs const. */ #undef ICONV_CONST /* Defined if libgnurl supports AsynchDNS */ #undef LIBGNURL_FEATURE_ASYNCHDNS /* Defined if libgnurl supports IDN */ #undef LIBGNURL_FEATURE_IDN /* Defined if libgnurl supports IPv6 */ #undef LIBGNURL_FEATURE_IPV6 /* Defined if libgnurl supports KRB4 */ #undef LIBGNURL_FEATURE_KRB4 /* Defined if libgnurl supports libz */ #undef LIBGNURL_FEATURE_LIBZ /* Defined if libgnurl supports NTLM */ #undef LIBGNURL_FEATURE_NTLM /* Defined if libgnurl supports SSL */ #undef LIBGNURL_FEATURE_SSL /* Defined if libgnurl supports SSPI */ #undef LIBGNURL_FEATURE_SSPI /* Defined if libgnurl supports DICT */ #undef LIBGNURL_PROTOCOL_DICT /* Defined if libgnurl supports FILE */ #undef LIBGNURL_PROTOCOL_FILE /* Defined if libgnurl supports FTP */ #undef LIBGNURL_PROTOCOL_FTP /* Defined if libgnurl supports FTPS */ #undef LIBGNURL_PROTOCOL_FTPS /* Defined if libgnurl supports HTTP */ #undef LIBGNURL_PROTOCOL_HTTP /* Defined if libgnurl supports HTTPS */ #undef LIBGNURL_PROTOCOL_HTTPS /* Defined if libgnurl supports IMAP */ #undef LIBGNURL_PROTOCOL_IMAP /* Defined if libgnurl supports LDAP */ #undef LIBGNURL_PROTOCOL_LDAP /* Defined if libgnurl supports POP3 */ #undef LIBGNURL_PROTOCOL_POP3 /* Defined if libgnurl supports RTSP */ #undef LIBGNURL_PROTOCOL_RTSP /* Defined if libgnurl supports SMTP */ #undef LIBGNURL_PROTOCOL_SMTP /* Defined if libgnurl supports TELNET */ #undef LIBGNURL_PROTOCOL_TELNET /* Defined if libgnurl supports TFTP */ #undef LIBGNURL_PROTOCOL_TFTP /* This is a Linux kernel */ #undef LINUX /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ #undef LSTAT_FOLLOWS_SLASHED_SYMLINK /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* This is a MinGW system */ #undef MINGW /* required libgcrypt version */ #undef NEED_LIBGCRYPT_VERSION /* This is a NetBSD system */ #undef NETBSD /* This is an OpenBSD system */ #undef OPENBSD /* Some strange OS */ #undef OTHEROS /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* Define to the type of arg 1 for `select'. */ #undef SELECT_TYPE_ARG1 /* Define to the type of args 2, 3 and 4 for `select'. */ #undef SELECT_TYPE_ARG234 /* Define to the type of arg 5 for `select'. */ #undef SELECT_TYPE_ARG5 /* This is a Solaris system */ #undef SOLARIS /* This is a BSD system */ #undef SOMEBSD /* Define to 1 if the `S_IS*' macros in do not work properly. */ #undef STAT_MACROS_BROKEN /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* VCS revision/hash or tarball version */ #undef VCS_VERSION /* Version number of package */ #undef VERSION /* This is a Windows system */ #undef WINDOWS /* Define to 1 if the X Window System is missing or not being used. */ #undef X_DISPLAY_MISSING /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ #undef _LARGEFILE_SOURCE /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Need with solaris or errno doesnt work */ #undef _REENTRANT /* This is a Windows system */ #undef _WIN32 /* Define curl_free() as free() if our version of gnurl lacks curl_free. */ #undef curl_free /* Define to `int' if doesn't define. */ #undef gid_t /* Define to `int' if does not define. */ #undef mode_t /* Define to `long int' if does not define. */ #undef off_t /* Define to `int' if does not define. */ #undef pid_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to `int' if doesn't define. */ #undef uid_t /* Define as `fork' if `vfork' does not work. */ #undef vfork gnunet-0.10.1/config.sub0000755000175000017500000010535412320752057012010 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-08-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or1k-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: gnunet-0.10.1/pkgconfig/0000755000175000017500000000000012320755631012045 500000000000000gnunet-0.10.1/pkgconfig/gnunetfs.pc.in0000644000175000017500000000040612221077151014541 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet fs Description: Provides API for GNUnet File-Sharing service URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetfs Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetpsycstore.pc.in0000644000175000017500000000043312225177415016174 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet PSYCSTORE Description: library to for persistent storage of PSYC messages URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetpsycstore Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetmysql.pc.in0000644000175000017500000000043012221077151015273 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet MySQL Description: Provides API for common interactions with libmysqlclient URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetmysql Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetarm.pc.in0000644000175000017500000000043412221077151014711 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet ARM Description: Provides API for accessing the Automated Restart Manager service URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetarm Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetblock.pc.in0000644000175000017500000000040312221077151015220 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet block Description: Library for data block manipulation URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetblock Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetfragmentation.pc.in0000644000175000017500000000051512221077151016770 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet fragmentation Description: Provides API for sending and receiving messages that are larger than the MTU of the transport URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetfragmentation Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetconsensus.pc.in0000644000175000017500000000046512225177415016166 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet CONSENSUS Description: library to calculate a set union for a group of peers (multiparty consensus) URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetconsensus Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetcore.pc.in0000644000175000017500000000041412221077151015060 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet core Description: Provides API for (encrypted) P2P communication URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetcore Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetenv.pc.in0000644000175000017500000000040412225177415014727 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet ENV Description: library to manipulate PSYC environments URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetenv Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetmesh.pc.in0000644000175000017500000000043212221077151015064 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet Mesh Description: API for multicast and multi-hop routing between GNUnet peers URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetmesh Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetdatastore.pc.in0000644000175000017500000000044712221077151016124 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet datastore Description: Management API for the datastore for persistant storage to disk URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetdatastore Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetpostgres.pc.in0000644000175000017500000000043212221077151015776 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet Postgres Description: API with common functions for interacting with libpq URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetpostgres Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetconversation.pc.in0000644000175000017500000000043112225177415016651 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet CONVERSATION Description: library to transmit voice data over GNUnet URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetconversation Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetregex.pc.in0000644000175000017500000000044112221077151015242 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet regex Description: Provides API for parsing regular expressions into finite automata URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetregex Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/Makefile.in0000644000175000017500000006506112320752057014041 00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = pkgconfig DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/gnunetarm.pc.in $(srcdir)/gnunetats.pc.in \ $(srcdir)/gnunetblock.pc.in $(srcdir)/gnunetconsensus.pc.in \ $(srcdir)/gnunetconversation.pc.in $(srcdir)/gnunetcore.pc.in \ $(srcdir)/gnunetdatacache.pc.in \ $(srcdir)/gnunetdatastore.pc.in $(srcdir)/gnunetdht.pc.in \ $(srcdir)/gnunetdns.pc.in $(srcdir)/gnunetdnsparser.pc.in \ $(srcdir)/gnunetdnsstub.pc.in $(srcdir)/gnunetdv.pc.in \ $(srcdir)/gnunetenv.pc.in $(srcdir)/gnunetfragmentation.pc.in \ $(srcdir)/gnunetfs.pc.in $(srcdir)/gnunetgns.pc.in \ $(srcdir)/gnunethello.pc.in $(srcdir)/gnunetidentity.pc.in \ $(srcdir)/gnunetmesh.pc.in $(srcdir)/gnunetmicrophone.pc.in \ $(srcdir)/gnunetmulticast.pc.in $(srcdir)/gnunetmysql.pc.in \ $(srcdir)/gnunetnamestore.pc.in $(srcdir)/gnunetnat.pc.in \ $(srcdir)/gnunetnse.pc.in $(srcdir)/gnunetpeerinfo.pc.in \ $(srcdir)/gnunetpostgres.pc.in $(srcdir)/gnunetpsyc.pc.in \ $(srcdir)/gnunetpsycstore.pc.in $(srcdir)/gnunetregex.pc.in \ $(srcdir)/gnunetrevocation.pc.in \ $(srcdir)/gnunetscalarproduct.pc.in $(srcdir)/gnunetset.pc.in \ $(srcdir)/gnunetspeaker.pc.in $(srcdir)/gnunetstatistics.pc.in \ $(srcdir)/gnunettestbed.pc.in $(srcdir)/gnunettesting.pc.in \ $(srcdir)/gnunettransport.pc.in $(srcdir)/gnunettun.pc.in \ $(srcdir)/gnunetutil.pc.in $(srcdir)/gnunetvpn.pc.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/gettext.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libgnurl.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/pkg.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/gnunet_config.h CONFIG_CLEAN_FILES = gnunetarm.pc gnunetats.pc gnunetblock.pc \ gnunetconsensus.pc gnunetconversation.pc gnunetcore.pc \ gnunetdatacache.pc gnunetdatastore.pc gnunetdht.pc \ gnunetdns.pc gnunetdnsparser.pc gnunetdnsstub.pc gnunetdv.pc \ gnunetenv.pc gnunetfragmentation.pc gnunetfs.pc gnunetgns.pc \ gnunethello.pc gnunetidentity.pc gnunetmesh.pc \ gnunetmicrophone.pc gnunetmulticast.pc gnunetmysql.pc \ gnunetnamestore.pc gnunetnat.pc gnunetnse.pc gnunetpeerinfo.pc \ gnunetpostgres.pc gnunetpsyc.pc gnunetpsycstore.pc \ gnunetregex.pc gnunetrevocation.pc gnunetscalarproduct.pc \ gnunetset.pc gnunetspeaker.pc gnunetstatistics.pc \ gnunettestbed.pc gnunettesting.pc gnunettransport.pc \ gnunettun.pc gnunetutil.pc gnunetvpn.pc CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkgconfigdir)" DATA = $(pkgconfig_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AUTOSTART = @AUTOSTART@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_INTERFACE = @DEFAULT_INTERFACE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLDIR = @DLLDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ GN_INTLINCL = @GN_INTLINCL@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GREP = @GREP@ GST_CFLAGS = @GST_CFLAGS@ GST_LIBS = @GST_LIBS@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INTLLIBS = @INTLLIBS@ INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ JAVAPORT = @JAVAPORT@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBGNURL = @LIBGNURL@ LIBGNURL_CPPFLAGS = @LIBGNURL_CPPFLAGS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBOBJS = @LIBOBJS@ LIBPREFIX = @LIBPREFIX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBUNISTRING = @LIBUNISTRING@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBICONV = @LTLIBICONV@ LTLIBINTL = @LTLIBINTL@ LTLIBOBJS = @LTLIBOBJS@ LTLIBUNISTRING = @LTLIBUNISTRING@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ MSGFMT_015 = @MSGFMT_015@ MSGMERGE = @MSGMERGE@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE_CPPFLAGS = @SQLITE_CPPFLAGS@ SQLITE_LDFLAGS = @SQLITE_LDFLAGS@ STRIP = @STRIP@ SUDO_BINARY = @SUDO_BINARY@ UNIXONLY = @UNIXONLY@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Z_CFLAGS = @Z_CFLAGS@ Z_LIBS = @Z_LIBS@ _libgnurl_config = @_libgnurl_config@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_target = @build_target@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ svnversioncommand = @svnversioncommand@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pcfiles = \ gnunetarm.pc \ gnunetats.pc \ gnunetblock.pc \ gnunetconsensus.pc \ gnunetconversation.pc \ gnunetcore.pc \ gnunetdatacache.pc \ gnunetdatastore.pc \ gnunetdht.pc \ gnunetdns.pc \ gnunetdnsparser.pc \ gnunetdnsstub.pc \ gnunetdv.pc \ gnunetenv.pc \ gnunetfragmentation.pc \ gnunetfs.pc \ gnunetgns.pc \ gnunethello.pc \ gnunetidentity.pc \ gnunetmesh.pc \ gnunetmicrophone.pc \ gnunetmulticast.pc \ gnunetmysql.pc \ gnunetnamestore.pc \ gnunetnat.pc \ gnunetnse.pc \ gnunetpeerinfo.pc \ gnunetpostgres.pc \ gnunetpsyc.pc \ gnunetpsycstore.pc \ gnunetregex.pc \ gnunetrevocation.pc \ gnunetscalarproduct.pc \ gnunetset.pc \ gnunetspeaker.pc \ gnunetstatistics.pc \ gnunettestbed.pc \ gnunettesting.pc \ gnunettransport.pc \ gnunettun.pc \ gnunetutil.pc \ gnunetvpn.pc cp_verbose = $(cp_verbose_$(V)) cp_verbose_ = $(cp_verbose_$(AM_DEFAULT_VERBOSITY)) cp_verbose_0 = @echo " CP $@"; pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = $(pcfiles) EXTRA_DIST = \ gnunetarm.pc.in \ gnunetats.pc.in \ gnunetblock.pc.in \ gnunetconsensus.pc.in \ gnunetconversation.pc.in \ gnunetcore.pc.in \ gnunetdatacache.pc.in \ gnunetdatastore.pc.in \ gnunetdht.pc.in \ gnunetdns.pc.in \ gnunetdnsparser.pc.in \ gnunetdnsstub.pc.in \ gnunetdv.pc.in \ gnunetenv.pc.in \ gnunetfragmentation.pc.in \ gnunetfs.pc.in \ gnunetgns.pc.in \ gnunethello.pc.in \ gnunetidentity.pc.in \ gnunetmesh.pc.in \ gnunetmicrophone.pc.in \ gnunetmulticast.pc.in \ gnunetmysql.pc.in \ gnunetnamestore.pc.in \ gnunetnat.pc.in \ gnunetnse.pc.in \ gnunetpeerinfo.pc.in \ gnunetpostgres.pc.in \ gnunetpsyc.pc.in \ gnunetpsycstore.pc.in \ gnunetregex.pc.in \ gnunetrevocation.pc.in \ gnunetscalarproduct.pc.in \ gnunetset.pc.in \ gnunetspeaker.pc.in \ gnunetstatistics.pc.in \ gnunettestbed.pc.in \ gnunettesting.pc.in \ gnunettransport.pc.in \ gnunettun.pc.in \ gnunetutil.pc.in \ gnunetvpn.pc.in CLEANFILES = $(pcfiles) AM_CPPFLAGS = -I$(top_srcdir)/src/include all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu pkgconfig/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu pkgconfig/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): gnunetarm.pc: $(top_builddir)/config.status $(srcdir)/gnunetarm.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetats.pc: $(top_builddir)/config.status $(srcdir)/gnunetats.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetblock.pc: $(top_builddir)/config.status $(srcdir)/gnunetblock.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetconsensus.pc: $(top_builddir)/config.status $(srcdir)/gnunetconsensus.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetconversation.pc: $(top_builddir)/config.status $(srcdir)/gnunetconversation.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetcore.pc: $(top_builddir)/config.status $(srcdir)/gnunetcore.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetdatacache.pc: $(top_builddir)/config.status $(srcdir)/gnunetdatacache.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetdatastore.pc: $(top_builddir)/config.status $(srcdir)/gnunetdatastore.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetdht.pc: $(top_builddir)/config.status $(srcdir)/gnunetdht.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetdns.pc: $(top_builddir)/config.status $(srcdir)/gnunetdns.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetdnsparser.pc: $(top_builddir)/config.status $(srcdir)/gnunetdnsparser.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetdnsstub.pc: $(top_builddir)/config.status $(srcdir)/gnunetdnsstub.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetdv.pc: $(top_builddir)/config.status $(srcdir)/gnunetdv.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetenv.pc: $(top_builddir)/config.status $(srcdir)/gnunetenv.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetfragmentation.pc: $(top_builddir)/config.status $(srcdir)/gnunetfragmentation.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetfs.pc: $(top_builddir)/config.status $(srcdir)/gnunetfs.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetgns.pc: $(top_builddir)/config.status $(srcdir)/gnunetgns.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunethello.pc: $(top_builddir)/config.status $(srcdir)/gnunethello.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetidentity.pc: $(top_builddir)/config.status $(srcdir)/gnunetidentity.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetmesh.pc: $(top_builddir)/config.status $(srcdir)/gnunetmesh.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetmicrophone.pc: $(top_builddir)/config.status $(srcdir)/gnunetmicrophone.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetmulticast.pc: $(top_builddir)/config.status $(srcdir)/gnunetmulticast.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetmysql.pc: $(top_builddir)/config.status $(srcdir)/gnunetmysql.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetnamestore.pc: $(top_builddir)/config.status $(srcdir)/gnunetnamestore.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetnat.pc: $(top_builddir)/config.status $(srcdir)/gnunetnat.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetnse.pc: $(top_builddir)/config.status $(srcdir)/gnunetnse.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetpeerinfo.pc: $(top_builddir)/config.status $(srcdir)/gnunetpeerinfo.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetpostgres.pc: $(top_builddir)/config.status $(srcdir)/gnunetpostgres.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetpsyc.pc: $(top_builddir)/config.status $(srcdir)/gnunetpsyc.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetpsycstore.pc: $(top_builddir)/config.status $(srcdir)/gnunetpsycstore.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetregex.pc: $(top_builddir)/config.status $(srcdir)/gnunetregex.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetrevocation.pc: $(top_builddir)/config.status $(srcdir)/gnunetrevocation.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetscalarproduct.pc: $(top_builddir)/config.status $(srcdir)/gnunetscalarproduct.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetset.pc: $(top_builddir)/config.status $(srcdir)/gnunetset.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetspeaker.pc: $(top_builddir)/config.status $(srcdir)/gnunetspeaker.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetstatistics.pc: $(top_builddir)/config.status $(srcdir)/gnunetstatistics.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunettestbed.pc: $(top_builddir)/config.status $(srcdir)/gnunettestbed.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunettesting.pc: $(top_builddir)/config.status $(srcdir)/gnunettesting.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunettransport.pc: $(top_builddir)/config.status $(srcdir)/gnunettransport.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunettun.pc: $(top_builddir)/config.status $(srcdir)/gnunettun.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetutil.pc: $(top_builddir)/config.status $(srcdir)/gnunetutil.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ gnunetvpn.pc: $(top_builddir)/config.status $(srcdir)/gnunetvpn.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) all-local installdirs: for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-pkgconfigDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkgconfigDATA .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-pkgconfigDATA install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-pkgconfigDATA all-local: $(pcfiles) %.pc: %.pc $(cp_verbose_0)cp $< $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: gnunet-0.10.1/pkgconfig/gnunettransport.pc.in0000644000175000017500000000043512221077151016167 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet transport Description: Library to access the low-level GNUnet P2P IO service URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunettransport Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetnat.pc.in0000644000175000017500000000036612221077151014720 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet NAT Description: library for NAT traversal URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetnat Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetmulticast.pc.in0000644000175000017500000000043212225177415016145 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet MULTICAST Description: library to multicast messages to a group of peers URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetmulticast Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunettun.pc.in0000644000175000017500000000044312221077151014740 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet TUN Description: Provides API for parsing IP packets for Linux TUN interface interaction URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunettun Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetdnsstub.pc.in0000644000175000017500000000044512225177415015626 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet DNS stub Description: Provides API for asynchronous DNS resolution (DNS stub resolver) URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetdnsstub Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetdnsparser.pc.in0000644000175000017500000000043512221077151016134 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet DNS parser Description: Provides API for parsing and serializing DNS packets URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetdnsparser Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunettestbed.pc.in0000644000175000017500000000042412221077151015563 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet Testbed Description: Provides API for deploying and managing testbeds URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunettestbed Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetpsyc.pc.in0000644000175000017500000000041412225177415015116 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet PSYC Description: library for PSYC multicast channel management URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetpsyc Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetpeerinfo.pc.in0000644000175000017500000000042412221077151015740 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet peerinfo Description: Provides API to access GNUnet peerinfo service URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetpeerinfo Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetmicrophone.pc.in0000644000175000017500000000046512225177415016311 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet MICROPHONE Description: library to access the system's microphone (recording of OPUS-encoded data) URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetmicrophone Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/Makefile.am0000644000175000017500000000504012272460772014025 00000000000000pcfiles = \ gnunetarm.pc \ gnunetats.pc \ gnunetblock.pc \ gnunetconsensus.pc \ gnunetconversation.pc \ gnunetcore.pc \ gnunetdatacache.pc \ gnunetdatastore.pc \ gnunetdht.pc \ gnunetdns.pc \ gnunetdnsparser.pc \ gnunetdnsstub.pc \ gnunetdv.pc \ gnunetenv.pc \ gnunetfragmentation.pc \ gnunetfs.pc \ gnunetgns.pc \ gnunethello.pc \ gnunetidentity.pc \ gnunetmesh.pc \ gnunetmicrophone.pc \ gnunetmulticast.pc \ gnunetmysql.pc \ gnunetnamestore.pc \ gnunetnat.pc \ gnunetnse.pc \ gnunetpeerinfo.pc \ gnunetpostgres.pc \ gnunetpsyc.pc \ gnunetpsycstore.pc \ gnunetregex.pc \ gnunetrevocation.pc \ gnunetscalarproduct.pc \ gnunetset.pc \ gnunetspeaker.pc \ gnunetstatistics.pc \ gnunettestbed.pc \ gnunettesting.pc \ gnunettransport.pc \ gnunettun.pc \ gnunetutil.pc \ gnunetvpn.pc all-local: $(pcfiles) cp_verbose = $(cp_verbose_$(V)) cp_verbose_ = $(cp_verbose_$(AM_DEFAULT_VERBOSITY)) cp_verbose_0 = @echo " CP $@"; %.pc: %.pc $(cp_verbose_0)cp $< $@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = $(pcfiles) EXTRA_DIST = \ gnunetarm.pc.in \ gnunetats.pc.in \ gnunetblock.pc.in \ gnunetconsensus.pc.in \ gnunetconversation.pc.in \ gnunetcore.pc.in \ gnunetdatacache.pc.in \ gnunetdatastore.pc.in \ gnunetdht.pc.in \ gnunetdns.pc.in \ gnunetdnsparser.pc.in \ gnunetdnsstub.pc.in \ gnunetdv.pc.in \ gnunetenv.pc.in \ gnunetfragmentation.pc.in \ gnunetfs.pc.in \ gnunetgns.pc.in \ gnunethello.pc.in \ gnunetidentity.pc.in \ gnunetmesh.pc.in \ gnunetmicrophone.pc.in \ gnunetmulticast.pc.in \ gnunetmysql.pc.in \ gnunetnamestore.pc.in \ gnunetnat.pc.in \ gnunetnse.pc.in \ gnunetpeerinfo.pc.in \ gnunetpostgres.pc.in \ gnunetpsyc.pc.in \ gnunetpsycstore.pc.in \ gnunetregex.pc.in \ gnunetrevocation.pc.in \ gnunetscalarproduct.pc.in \ gnunetset.pc.in \ gnunetspeaker.pc.in \ gnunetstatistics.pc.in \ gnunettestbed.pc.in \ gnunettesting.pc.in \ gnunettransport.pc.in \ gnunettun.pc.in \ gnunetutil.pc.in \ gnunetvpn.pc.in CLEANFILES = $(pcfiles) AM_CPPFLAGS = -I$(top_srcdir)/src/include gnunet-0.10.1/pkgconfig/gnunetidentity.pc.in0000644000175000017500000000044512225177415015775 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet IDENTITY Description: library to access and organize private keys of the user's egos URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetidentity Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetnse.pc.in0000644000175000017500000000042712221077151014721 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet NSE Description: library to access GNUnet network size estimate information URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetnse Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetgns.pc.in0000644000175000017500000000041312221077151014716 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet GNS Description: Provides API to access the GNUnet Naming System URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetgns Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetdatacache.pc.in0000644000175000017500000000043412221077151016027 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet datacache Description: Provides datacache API for temporary storage to disk URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetdatacache Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunettesting.pc.in0000644000175000017500000000043512221077151015610 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet testing Description: Provides convenience API for writing testcases for GNUnet URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunettesting Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetstatistics.pc.in0000644000175000017500000000042312221077151016322 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet statistics Description: Provides API of GNUnet statistics service URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetstatistics Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetscalarproduct.pc.in0000644000175000017500000000046712225177415017016 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet SCALARPRODUCT Description: library to perform privacy-preserving scalar product between two peers URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetscalarproduct Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetdv.pc.in0000644000175000017500000000037512221077151014547 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet dv Description: Library to access GNUnet DV service URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetdv Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetutil.pc.in0000644000175000017500000000043112221077151015104 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet util Description: Provides miscellaneous utility functions and API for GNUnet URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetutil Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetats.pc.in0000644000175000017500000000052012221077151014715 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet ATS Description: Provides API for allocating bandwidth, expressing preferences for certain peers and accessing allocation information URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetats Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetset.pc.in0000644000175000017500000000045012225177415014733 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet SET Description: library to perform set computations (union, intersection) between two peers URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetset Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunethello.pc.in0000644000175000017500000000042112221077151015231 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet hello Description: Helper library for handling GNUnet HELLO messages URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunethello Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetvpn.pc.in0000644000175000017500000000040512221077151014733 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet VPN Description: Provides API for accessing the GNUnet VPN URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetvpn Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetrevocation.pc.in0000644000175000017500000000042612225177415016314 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet REVOCATION Description: library to perform key revocation in GNUnet URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetrevocation Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetspeaker.pc.in0000644000175000017500000000045312225177415015575 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet SPEAKER Description: library to access the system's speaker (playback of OPUS-encoded data) URL: https://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetspeaker Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetdht.pc.in0000644000175000017500000000040012221077151014702 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet DHT Description: Library to access GNUnet DHT service URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetdht Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetdns.pc.in0000644000175000017500000000046112221077151014716 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet DNS Description: Provides API to access GNUnet's DNS service (to intercept and manipulate DNS queries) URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetdns Cflags: -I${includedir} gnunet-0.10.1/pkgconfig/gnunetnamestore.pc.in0000644000175000017500000000043212221077151016125 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: GNUnet Namestore Description: Provides API for storing GNS records to a database URL: http://gnunet.org Version: @VERSION@ Requires: Libs: -L${libdir} -lgnunetnamestore Cflags: -I${includedir}